summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CREDITS4
-rw-r--r--Documentation/ABI/testing/debugfs-pfo-nx-crypto45
-rw-r--r--Documentation/ABI/testing/dev-kmsg90
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio (renamed from drivers/staging/iio/Documentation/sysfs-bus-iio)52
-rw-r--r--Documentation/ABI/testing/sysfs-bus-usb19
-rw-r--r--Documentation/ABI/testing/sysfs-class-extcon97
-rw-r--r--Documentation/ABI/testing/sysfs-devices-power35
-rw-r--r--Documentation/ABI/testing/sysfs-devices-system-cpu25
-rw-r--r--Documentation/ABI/testing/sysfs-driver-wacom8
-rw-r--r--Documentation/ABI/testing/sysfs-power59
-rw-r--r--Documentation/DocBook/kernel-hacking.tmpl2
-rw-r--r--Documentation/DocBook/libata.tmpl2
-rw-r--r--Documentation/DocBook/media/v4l/controls.xml6
-rw-r--r--Documentation/HOWTO32
-rw-r--r--Documentation/Makefile2
-rw-r--r--Documentation/RCU/torture.txt15
-rw-r--r--Documentation/arm/00-INDEX2
-rw-r--r--Documentation/arm/IXP200069
-rw-r--r--Documentation/arm/SPEAr/overview.txt13
-rw-r--r--Documentation/blackfin/bfin-gpio-notes.txt2
-rw-r--r--Documentation/cgroups/resource_counter.txt4
-rw-r--r--Documentation/devices.txt3
-rw-r--r--Documentation/devicetree/bindings/arm/arch_timer.txt27
-rw-r--r--Documentation/devicetree/bindings/arm/atmel-adc.txt65
-rw-r--r--Documentation/devicetree/bindings/arm/lpc32xx-mic.txt38
-rw-r--r--Documentation/devicetree/bindings/arm/lpc32xx.txt8
-rw-r--r--Documentation/devicetree/bindings/arm/mrvl/intc.txt40
-rw-r--r--Documentation/devicetree/bindings/arm/mrvl/mrvl.txt (renamed from Documentation/devicetree/bindings/arm/mrvl.txt)8
-rw-r--r--Documentation/devicetree/bindings/arm/mrvl/timer.txt13
-rw-r--r--Documentation/devicetree/bindings/arm/spear.txt18
-rw-r--r--Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt16
-rw-r--r--Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt18
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-nmk.txt31
-rw-r--r--Documentation/devicetree/bindings/gpio/mrvl-gpio.txt18
-rw-r--r--Documentation/devicetree/bindings/i2c/mrvl-i2c.txt15
-rw-r--r--Documentation/devicetree/bindings/i2c/pnx.txt36
-rw-r--r--Documentation/devicetree/bindings/misc/bmp085.txt20
-rw-r--r--Documentation/devicetree/bindings/mtd/orion-nand.txt50
-rw-r--r--Documentation/devicetree/bindings/net/can/fsl-flexcan.txt2
-rw-r--r--Documentation/devicetree/bindings/net/lpc-eth.txt24
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt95
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx51-pinctrl.txt787
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx53-pinctrl.txt1202
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt1628
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt918
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt132
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt132
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt128
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl_spear.txt108
-rw-r--r--Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt5
-rw-r--r--Documentation/devicetree/bindings/regulator/fixed-regulator.txt5
-rw-r--r--Documentation/devicetree/bindings/regulator/tps62360-regulator.txt44
-rw-r--r--Documentation/devicetree/bindings/regulator/tps6586x.txt97
-rw-r--r--Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt49
-rw-r--r--Documentation/devicetree/bindings/sound/mxs-audio-sgtl5000.txt17
-rw-r--r--Documentation/devicetree/bindings/sound/mxs-saif.txt36
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra30-ahub.txt32
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra30-i2s.txt15
-rw-r--r--Documentation/devicetree/bindings/sound/tegra-audio-trimslice.txt14
-rw-r--r--Documentation/devicetree/bindings/sound/tegra-audio-wm8753.txt54
-rw-r--r--Documentation/devicetree/bindings/staging/iio/adc/lpc32xx-adc.txt16
-rw-r--r--Documentation/devicetree/bindings/staging/iio/adc/spear-adc.txt26
-rw-r--r--Documentation/devicetree/bindings/usb/isp1301.txt25
-rw-r--r--Documentation/devicetree/bindings/usb/lpc32xx-udc.txt28
-rw-r--r--Documentation/devicetree/bindings/usb/ohci-nxp.txt24
-rw-r--r--Documentation/devicetree/bindings/usb/spear-usb.txt39
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--Documentation/devicetree/bindings/watchdog/pnx4008-wdt.txt13
-rw-r--r--Documentation/driver-model/devres.txt8
-rw-r--r--Documentation/dvb/opera-firmware.txt4
-rw-r--r--Documentation/dynamic-debug-howto.txt184
-rw-r--r--Documentation/edac.txt2
-rw-r--r--Documentation/extcon/porting-android-switch-class124
-rw-r--r--Documentation/feature-removal-schedule.txt20
-rw-r--r--Documentation/filesystems/gfs2-glocks.txt119
-rw-r--r--Documentation/filesystems/gfs2.txt9
-rw-r--r--Documentation/filesystems/nfs/pnfs.txt2
-rw-r--r--Documentation/filesystems/qnx6.txt28
-rw-r--r--Documentation/hwmon/ina2xx29
-rw-r--r--Documentation/hwmon/it8730
-rw-r--r--Documentation/hwmon/wm831x2
-rw-r--r--Documentation/ioctl/ioctl-number.txt1
-rw-r--r--Documentation/kernel-parameters.txt117
-rw-r--r--Documentation/memory-devices/ti-emif.txt57
-rw-r--r--Documentation/memory-hotplug.txt2
-rw-r--r--Documentation/misc-devices/mei/.gitignore1
-rw-r--r--Documentation/misc-devices/mei/Makefile8
-rw-r--r--Documentation/misc-devices/mei/TODO2
-rw-r--r--Documentation/misc-devices/mei/mei-amt-version.c (renamed from drivers/staging/mei/mei-amt-version.c)2
-rw-r--r--Documentation/misc-devices/mei/mei.txt (renamed from drivers/staging/mei/mei.txt)0
-rw-r--r--Documentation/networking/can.txt2
-rw-r--r--Documentation/parisc/debugging2
-rw-r--r--Documentation/pinctrl.txt94
-rw-r--r--Documentation/power/regulator/regulator.txt3
-rw-r--r--Documentation/power/suspend-and-cpuhotplug.txt2
-rw-r--r--Documentation/prctl/seccomp_filter.txt163
-rw-r--r--Documentation/ramoops.txt16
-rw-r--r--Documentation/scheduler/sched-design-CFS.txt6
-rw-r--r--Documentation/scheduler/sched-domains.txt4
-rw-r--r--Documentation/scsi/ChangeLog.megaraid_sas8
-rw-r--r--Documentation/security/Smack.txt204
-rw-r--r--Documentation/security/Yama.txt10
-rw-r--r--Documentation/security/keys.txt17
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt2
-rw-r--r--Documentation/sound/alsa/compress_offload.txt2
-rw-r--r--Documentation/sound/oss/ALS4
-rw-r--r--Documentation/sparc/README-2.546
-rw-r--r--Documentation/static-keys.txt2
-rw-r--r--Documentation/usb/dwc3.txt2
-rw-r--r--Documentation/usb/functionfs.txt67
-rw-r--r--Documentation/usb/wusb-cbaf2
-rw-r--r--Documentation/video4linux/README.cpia22
-rw-r--r--Documentation/virtual/virtio-spec.txt1164
-rw-r--r--Documentation/vme_api.txt (renamed from drivers/staging/vme/vme_api.txt)0
-rw-r--r--Documentation/watchdog/src/watchdog-test.c20
-rw-r--r--Documentation/watchdog/watchdog-kernel-api.txt2
-rw-r--r--Documentation/zh_CN/magic-number.txt2
-rw-r--r--MAINTAINERS177
-rw-r--r--Makefile50
-rw-r--r--README222
-rw-r--r--arch/Kconfig38
-rw-r--r--arch/alpha/Kconfig1
-rw-r--r--arch/alpha/include/asm/processor.h3
-rw-r--r--arch/alpha/kernel/Makefile2
-rw-r--r--arch/alpha/kernel/pci_iommu.c20
-rw-r--r--arch/alpha/kernel/perf_event.c3
-rw-r--r--arch/alpha/kernel/smp.c20
-rw-r--r--arch/arm/Kconfig78
-rw-r--r--arch/arm/Makefile6
-rw-r--r--arch/arm/boot/compressed/head-xscale.S7
-rw-r--r--arch/arm/boot/compressed/head.S71
-rw-r--r--arch/arm/boot/dts/at91sam9260.dtsi273
-rw-r--r--arch/arm/boot/dts/at91sam9263.dtsi220
-rw-r--r--arch/arm/boot/dts/at91sam9263ek.dts156
-rw-r--r--arch/arm/boot/dts/at91sam9g20.dtsi222
-rw-r--r--arch/arm/boot/dts/at91sam9g20ek.dts29
-rw-r--r--arch/arm/boot/dts/at91sam9g20ek_2mmc.dts29
-rw-r--r--arch/arm/boot/dts/at91sam9g20ek_common.dtsi142
-rw-r--r--arch/arm/boot/dts/at91sam9g45.dtsi37
-rw-r--r--arch/arm/boot/dts/at91sam9n12.dtsi221
-rw-r--r--arch/arm/boot/dts/at91sam9n12ek.dts84
-rw-r--r--arch/arm/boot/dts/at91sam9x5.dtsi38
-rw-r--r--arch/arm/boot/dts/db8500.dtsi63
-rw-r--r--arch/arm/boot/dts/emev2-kzm9d.dts26
-rw-r--r--arch/arm/boot/dts/emev2.dtsi63
-rw-r--r--arch/arm/boot/dts/ethernut5.dts84
-rw-r--r--arch/arm/boot/dts/kirkwood-dns320.dts64
-rw-r--r--arch/arm/boot/dts/kirkwood-dns325.dts59
-rw-r--r--arch/arm/boot/dts/kirkwood-ib62x0.dts44
-rw-r--r--arch/arm/boot/dts/kirkwood-iconnect.dts26
-rw-r--r--arch/arm/boot/dts/kirkwood.dtsi15
-rw-r--r--arch/arm/boot/dts/kizbox.dts138
-rw-r--r--arch/arm/boot/dts/lpc32xx.dtsi292
-rw-r--r--arch/arm/boot/dts/mmp2-brownstone.dts38
-rw-r--r--arch/arm/boot/dts/mmp2.dtsi220
-rw-r--r--arch/arm/boot/dts/omap3-beagle.dts49
-rw-r--r--arch/arm/boot/dts/omap3.dtsi102
-rw-r--r--arch/arm/boot/dts/omap4-panda.dts71
-rw-r--r--arch/arm/boot/dts/omap4-sdp.dts140
-rw-r--r--arch/arm/boot/dts/omap4.dtsi117
-rw-r--r--arch/arm/boot/dts/phy3250.dts145
-rw-r--r--arch/arm/boot/dts/pxa168.dtsi67
-rw-r--r--arch/arm/boot/dts/pxa910-dkb.dts38
-rw-r--r--arch/arm/boot/dts/pxa910.dtsi140
-rw-r--r--arch/arm/boot/dts/r8a7740-armadillo800eva.dts22
-rw-r--r--arch/arm/boot/dts/sh7372.dtsi21
-rw-r--r--arch/arm/boot/dts/sh73a0-kzm9g.dts22
-rw-r--r--arch/arm/boot/dts/snowball.dts40
-rw-r--r--arch/arm/boot/dts/spear300-evb.dts221
-rw-r--r--arch/arm/boot/dts/spear300.dtsi77
-rw-r--r--arch/arm/boot/dts/spear310-evb.dts172
-rw-r--r--arch/arm/boot/dts/spear310.dtsi80
-rw-r--r--arch/arm/boot/dts/spear320-evb.dts173
-rw-r--r--arch/arm/boot/dts/spear320.dtsi95
-rw-r--r--arch/arm/boot/dts/spear3xx.dtsi144
-rw-r--r--arch/arm/boot/dts/spear600-evb.dts4
-rw-r--r--arch/arm/boot/dts/spear600.dtsi8
-rw-r--r--arch/arm/boot/dts/tegra-cardhu.dts44
-rw-r--r--arch/arm/boot/dts/tegra-harmony.dts224
-rw-r--r--arch/arm/boot/dts/tegra-paz00.dts220
-rw-r--r--arch/arm/boot/dts/tegra-seaboard.dts243
-rw-r--r--arch/arm/boot/dts/tegra-trimslice.dts230
-rw-r--r--arch/arm/boot/dts/tegra-ventana.dts230
-rw-r--r--arch/arm/boot/dts/tny_a9260.dts15
-rw-r--r--arch/arm/boot/dts/tny_a9260_common.dtsi83
-rw-r--r--arch/arm/boot/dts/tny_a9263.dts97
-rw-r--r--arch/arm/boot/dts/tny_a9g20.dts15
-rw-r--r--arch/arm/boot/dts/twl4030.dtsi47
-rw-r--r--arch/arm/boot/dts/twl6030.dtsi86
-rw-r--r--arch/arm/boot/dts/usb_a9260.dts23
-rw-r--r--arch/arm/boot/dts/usb_a9260_common.dtsi117
-rw-r--r--arch/arm/boot/dts/usb_a9263.dts131
-rw-r--r--arch/arm/boot/dts/usb_a9g20.dts102
-rw-r--r--arch/arm/common/Makefile2
-rw-r--r--arch/arm/common/it8152.c7
-rw-r--r--arch/arm/common/uengine.c507
-rw-r--r--arch/arm/common/via82c505.c11
-rw-r--r--arch/arm/common/vic.c56
-rw-r--r--arch/arm/configs/armadillo800eva_defconfig142
-rw-r--r--arch/arm/configs/at91_dt_defconfig196
-rw-r--r--arch/arm/configs/at91rm9200_defconfig1
-rw-r--r--arch/arm/configs/bcmring_defconfig2
-rw-r--r--arch/arm/configs/imx_v4_v5_defconfig4
-rw-r--r--arch/arm/configs/ixp2000_defconfig99
-rw-r--r--arch/arm/configs/ixp23xx_defconfig105
-rw-r--r--arch/arm/configs/kzm9g_defconfig139
-rw-r--r--arch/arm/configs/lpc32xx_defconfig44
-rw-r--r--arch/arm/configs/nhk8815_defconfig1
-rw-r--r--arch/arm/configs/omap2plus_defconfig2
-rw-r--r--arch/arm/configs/rpc_defconfig2
-rw-r--r--arch/arm/configs/spear3xx_defconfig52
-rw-r--r--arch/arm/configs/spear6xx_defconfig41
-rw-r--r--arch/arm/include/asm/arch_timer.h19
-rw-r--r--arch/arm/include/asm/cacheflush.h6
-rw-r--r--arch/arm/include/asm/cmpxchg.h73
-rw-r--r--arch/arm/include/asm/cpu.h1
-rw-r--r--arch/arm/include/asm/glue-df.h8
-rw-r--r--arch/arm/include/asm/glue-proc.h18
-rw-r--r--arch/arm/include/asm/hardware/cs89712.h49
-rw-r--r--arch/arm/include/asm/hardware/ep7212.h83
-rw-r--r--arch/arm/include/asm/hardware/it8152.h2
-rw-r--r--arch/arm/include/asm/hardware/uengine.h62
-rw-r--r--arch/arm/include/asm/mach/pci.h17
-rw-r--r--arch/arm/include/asm/mach/time.h5
-rw-r--r--arch/arm/include/asm/mmu.h7
-rw-r--r--arch/arm/include/asm/mmu_context.h104
-rw-r--r--arch/arm/include/asm/page.h9
-rw-r--r--arch/arm/include/asm/pgtable-3level.h2
-rw-r--r--arch/arm/include/asm/processor.h5
-rw-r--r--arch/arm/include/asm/ptrace.h5
-rw-r--r--arch/arm/include/asm/syscall.h93
-rw-r--r--arch/arm/include/asm/thread_info.h1
-rw-r--r--arch/arm/include/asm/tlbflush.h21
-rw-r--r--arch/arm/kernel/Makefile3
-rw-r--r--arch/arm/kernel/arch_timer.c350
-rw-r--r--arch/arm/kernel/bios32.c37
-rw-r--r--arch/arm/kernel/entry-armv.S4
-rw-r--r--arch/arm/kernel/entry-common.S28
-rw-r--r--arch/arm/kernel/head.S9
-rw-r--r--arch/arm/kernel/init_task.c37
-rw-r--r--arch/arm/kernel/perf_event_v6.c4
-rw-r--r--arch/arm/kernel/perf_event_v7.c4
-rw-r--r--arch/arm/kernel/perf_event_xscale.c8
-rw-r--r--arch/arm/kernel/process.c20
-rw-r--r--arch/arm/kernel/ptrace.c21
-rw-r--r--arch/arm/kernel/signal.c2
-rw-r--r--arch/arm/kernel/smp.c29
-rw-r--r--arch/arm/kernel/smp_scu.c3
-rw-r--r--arch/arm/kernel/thumbee.c4
-rw-r--r--arch/arm/kernel/time.c36
-rw-r--r--arch/arm/kernel/traps.c11
-rw-r--r--arch/arm/lib/Makefile23
-rw-r--r--arch/arm/lib/io-readsw-armv3.S106
-rw-r--r--arch/arm/lib/io-writesw-armv3.S126
-rw-r--r--arch/arm/lib/uaccess.S564
-rw-r--r--arch/arm/mach-at91/Kconfig194
-rw-r--r--arch/arm/mach-at91/Makefile27
-rw-r--r--arch/arm/mach-at91/Makefile.boot14
-rw-r--r--arch/arm/mach-at91/at91rm9200.c12
-rw-r--r--arch/arm/mach-at91/at91rm9200_devices.c12
-rw-r--r--arch/arm/mach-at91/at91sam9260.c20
-rw-r--r--arch/arm/mach-at91/at91sam9260_devices.c122
-rw-r--r--arch/arm/mach-at91/at91sam9261.c12
-rw-r--r--arch/arm/mach-at91/at91sam9261_devices.c12
-rw-r--r--arch/arm/mach-at91/at91sam9263.c22
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c32
-rw-r--r--arch/arm/mach-at91/at91sam9g45.c21
-rw-r--r--arch/arm/mach-at91/at91sam9g45_devices.c143
-rw-r--r--arch/arm/mach-at91/at91sam9n12.c233
-rw-r--r--arch/arm/mach-at91/at91sam9rl.c12
-rw-r--r--arch/arm/mach-at91/at91sam9rl_devices.c12
-rw-r--r--arch/arm/mach-at91/at91sam9x5.c6
-rw-r--r--arch/arm/mach-at91/board-1arm.c24
-rw-r--r--arch/arm/mach-at91/board-afeb-9260v1.c28
-rw-r--r--arch/arm/mach-at91/board-cam60.c8
-rw-r--r--arch/arm/mach-at91/board-carmeva.c18
-rw-r--r--arch/arm/mach-at91/board-cpu9krea.c52
-rw-r--r--arch/arm/mach-at91/board-cpuat91.c40
-rw-r--r--arch/arm/mach-at91/board-csb337.c13
-rw-r--r--arch/arm/mach-at91/board-csb637.c8
-rw-r--r--arch/arm/mach-at91/board-dt.c8
-rw-r--r--arch/arm/mach-at91/board-eb9200.c24
-rw-r--r--arch/arm/mach-at91/board-ecbat91.c20
-rw-r--r--arch/arm/mach-at91/board-eco920.c13
-rw-r--r--arch/arm/mach-at91/board-flexibity.c8
-rw-r--r--arch/arm/mach-at91/board-foxg20.c71
-rw-r--r--arch/arm/mach-at91/board-gsia18s.c63
-rw-r--r--arch/arm/mach-at91/board-kafa.c20
-rw-r--r--arch/arm/mach-at91/board-kb9202.c32
-rw-r--r--arch/arm/mach-at91/board-neocore926.c14
-rw-r--r--arch/arm/mach-at91/board-pcontrol-g20.c21
-rw-r--r--arch/arm/mach-at91/board-picotux200.c18
-rw-r--r--arch/arm/mach-at91/board-qil-a9260.c31
-rw-r--r--arch/arm/mach-at91/board-rm9200dk.c24
-rw-r--r--arch/arm/mach-at91/board-rm9200ek.c24
-rw-r--r--arch/arm/mach-at91/board-rsi-ews.c36
-rw-r--r--arch/arm/mach-at91/board-sam9-l9260.c30
-rw-r--r--arch/arm/mach-at91/board-sam9260ek.c24
-rw-r--r--arch/arm/mach-at91/board-sam9261ek.c14
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c14
-rw-r--r--arch/arm/mach-at91/board-sam9g20ek.c38
-rw-r--r--arch/arm/mach-at91/board-sam9m10g45ek.c28
-rw-r--r--arch/arm/mach-at91/board-sam9rlek.c14
-rw-r--r--arch/arm/mach-at91/board-snapper9260.c18
-rw-r--r--arch/arm/mach-at91/board-stamp9g20.c64
-rw-r--r--arch/arm/mach-at91/board-usb-a926x.c12
-rw-r--r--arch/arm/mach-at91/board-yl-9200.c36
-rw-r--r--arch/arm/mach-at91/clock.c15
-rw-r--r--arch/arm/mach-at91/cpuidle.c8
-rw-r--r--arch/arm/mach-at91/generic.h11
-rw-r--r--arch/arm/mach-at91/include/mach/at91rm9200.h5
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9260.h7
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9261.h4
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9263.h4
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9g45.h5
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9n12.h60
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h53
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9rl.h5
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9x5.h8
-rw-r--r--arch/arm/mach-at91/include/mach/board.h1
-rw-r--r--arch/arm/mach-at91/include/mach/cpu.h38
-rw-r--r--arch/arm/mach-at91/include/mach/hardware.h17
-rw-r--r--arch/arm/mach-at91/include/mach/uncompress.h178
-rw-r--r--arch/arm/mach-at91/pm.c12
-rw-r--r--arch/arm/mach-at91/pm.h15
-rw-r--r--arch/arm/mach-at91/pm_slowclock.S2
-rw-r--r--arch/arm/mach-at91/setup.c6
-rw-r--r--arch/arm/mach-at91/soc.h19
-rw-r--r--arch/arm/mach-clps711x/Kconfig21
-rw-r--r--arch/arm/mach-clps711x/common.c17
-rw-r--r--arch/arm/mach-clps711x/include/mach/clps711x.h (renamed from arch/arm/include/asm/hardware/clps7111.h)130
-rw-r--r--arch/arm/mach-clps711x/include/mach/debug-macro.S5
-rw-r--r--arch/arm/mach-clps711x/include/mach/entry-macro.S3
-rw-r--r--arch/arm/mach-clps711x/include/mach/hardware.h59
-rw-r--r--arch/arm/mach-clps711x/include/mach/irqs.h5
-rw-r--r--arch/arm/mach-clps711x/include/mach/time.h49
-rw-r--r--arch/arm/mach-clps711x/include/mach/uncompress.h21
-rw-r--r--arch/arm/mach-clps711x/p720t-leds.c3
-rw-r--r--arch/arm/mach-cns3xxx/pcie.c12
-rw-r--r--arch/arm/mach-davinci/board-da850-evm.c2
-rw-r--r--arch/arm/mach-davinci/davinci.h4
-rw-r--r--arch/arm/mach-davinci/devices-da8xx.c2
-rw-r--r--arch/arm/mach-davinci/dm355.c2
-rw-r--r--arch/arm/mach-davinci/dm365.c2
-rw-r--r--arch/arm/mach-davinci/dma.c6
-rw-r--r--arch/arm/mach-davinci/include/mach/da8xx.h3
-rw-r--r--arch/arm/mach-davinci/include/mach/psc.h2
-rw-r--r--arch/arm/mach-dove/common.c2
-rw-r--r--arch/arm/mach-dove/mpp.c8
-rw-r--r--arch/arm/mach-dove/pcie.c24
-rw-r--r--arch/arm/mach-ep93xx/Kconfig5
-rw-r--r--arch/arm/mach-ep93xx/core.c110
-rw-r--r--arch/arm/mach-exynos/Kconfig12
-rw-r--r--arch/arm/mach-exynos/cpuidle.c53
-rw-r--r--arch/arm/mach-exynos/dev-ahci.c12
-rw-r--r--arch/arm/mach-exynos/dev-audio.c156
-rw-r--r--arch/arm/mach-exynos/include/mach/irqs.h1
-rw-r--r--arch/arm/mach-exynos/include/mach/map.h4
-rw-r--r--arch/arm/mach-exynos/include/mach/regs-pmu.h3
-rw-r--r--arch/arm/mach-exynos/mach-armlex4210.c16
-rw-r--r--arch/arm/mach-exynos/mach-nuri.c46
-rw-r--r--arch/arm/mach-exynos/mach-origen.c37
-rw-r--r--arch/arm/mach-exynos/mach-smdk4x12.c18
-rw-r--r--arch/arm/mach-exynos/mach-smdkv310.c47
-rw-r--r--arch/arm/mach-exynos/mach-universal_c210.c46
-rw-r--r--arch/arm/mach-exynos/setup-usb-phy.c100
-rw-r--r--arch/arm/mach-footbridge/cats-pci.c9
-rw-r--r--arch/arm/mach-footbridge/dc21285.c7
-rw-r--r--arch/arm/mach-footbridge/ebsa285-pci.c3
-rw-r--r--arch/arm/mach-footbridge/netwinder-pci.c3
-rw-r--r--arch/arm/mach-footbridge/personal-pci.c2
-rw-r--r--arch/arm/mach-imx/Kconfig41
-rw-r--r--arch/arm/mach-imx/Makefile4
-rw-r--r--arch/arm/mach-imx/eukrea_mbimx27-baseboard.c2
-rw-r--r--arch/arm/mach-imx/eukrea_mbimx51-baseboard.c206
-rw-r--r--arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c51
-rw-r--r--arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c42
-rw-r--r--arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c (renamed from arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c)120
-rw-r--r--arch/arm/mach-imx/imx51-dt.c3
-rw-r--r--arch/arm/mach-imx/imx53-dt.c3
-rw-r--r--arch/arm/mach-imx/mach-cpuimx35.c2
-rw-r--r--arch/arm/mach-imx/mach-cpuimx51.c301
-rw-r--r--arch/arm/mach-imx/mach-cpuimx51sd.c50
-rw-r--r--arch/arm/mach-imx/mach-eukrea_cpuimx25.c2
-rw-r--r--arch/arm/mach-imx/mach-imx27_visstrim_m10.c55
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c7
-rw-r--r--arch/arm/mach-imx/mach-mx1ads.c2
-rw-r--r--arch/arm/mach-imx/mach-mx21ads.c3
-rw-r--r--arch/arm/mach-imx/mach-mx31_3ds.c22
-rw-r--r--arch/arm/mach-imx/mach-mx31lite.c2
-rw-r--r--arch/arm/mach-imx/mach-mx31moboard.c22
-rw-r--r--arch/arm/mach-imx/mach-mx35_3ds.c195
-rw-r--r--arch/arm/mach-imx/mach-mx51_efikamx.c3
-rw-r--r--arch/arm/mach-imx/mach-mx51_efikasb.c2
-rw-r--r--arch/arm/mach-imx/mach-pcm037.c2
-rw-r--r--arch/arm/mach-imx/mach-pcm043.c2
-rw-r--r--arch/arm/mach-imx/mach-vpr200.c2
-rw-r--r--arch/arm/mach-imx/mm-imx1.c2
-rw-r--r--arch/arm/mach-imx/mm-imx21.c2
-rw-r--r--arch/arm/mach-imx/mm-imx25.c2
-rw-r--r--arch/arm/mach-imx/mm-imx27.c2
-rw-r--r--arch/arm/mach-imx/mm-imx3.c2
-rw-r--r--arch/arm/mach-imx/mm-imx5.c2
-rw-r--r--arch/arm/mach-integrator/impd1.c22
-rw-r--r--arch/arm/mach-integrator/include/mach/entry-macro.S39
-rw-r--r--arch/arm/mach-integrator/include/mach/irqs.h63
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c10
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c33
-rw-r--r--arch/arm/mach-integrator/pci.c19
-rw-r--r--arch/arm/mach-integrator/pci_v3.c8
-rw-r--r--arch/arm/mach-iop13xx/iq81340mc.c1
-rw-r--r--arch/arm/mach-iop13xx/iq81340sc.c1
-rw-r--r--arch/arm/mach-iop32x/em7210.c3
-rw-r--r--arch/arm/mach-iop32x/glantank.c3
-rw-r--r--arch/arm/mach-iop32x/iq31244.c6
-rw-r--r--arch/arm/mach-iop32x/iq80321.c3
-rw-r--r--arch/arm/mach-iop32x/n2100.c3
-rw-r--r--arch/arm/mach-iop33x/iq80331.c3
-rw-r--r--arch/arm/mach-iop33x/iq80332.c3
-rw-r--r--arch/arm/mach-ixp2000/Kconfig72
-rw-r--r--arch/arm/mach-ixp2000/Makefile14
-rw-r--r--arch/arm/mach-ixp2000/Makefile.boot3
-rw-r--r--arch/arm/mach-ixp2000/core.c520
-rw-r--r--arch/arm/mach-ixp2000/enp2611.c265
-rw-r--r--arch/arm/mach-ixp2000/include/mach/debug-macro.S25
-rw-r--r--arch/arm/mach-ixp2000/include/mach/enp2611.h46
-rw-r--r--arch/arm/mach-ixp2000/include/mach/entry-macro.S54
-rw-r--r--arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h48
-rw-r--r--arch/arm/mach-ixp2000/include/mach/hardware.h36
-rw-r--r--arch/arm/mach-ixp2000/include/mach/io.h133
-rw-r--r--arch/arm/mach-ixp2000/include/mach/irqs.h207
-rw-r--r--arch/arm/mach-ixp2000/include/mach/ixdp2x00.h92
-rw-r--r--arch/arm/mach-ixp2000/include/mach/ixdp2x01.h57
-rw-r--r--arch/arm/mach-ixp2000/include/mach/ixp2000-regs.h451
-rw-r--r--arch/arm/mach-ixp2000/include/mach/memory.h31
-rw-r--r--arch/arm/mach-ixp2000/include/mach/platform.h153
-rw-r--r--arch/arm/mach-ixp2000/include/mach/timex.h13
-rw-r--r--arch/arm/mach-ixp2000/include/mach/uncompress.h47
-rw-r--r--arch/arm/mach-ixp2000/ixdp2400.c180
-rw-r--r--arch/arm/mach-ixp2000/ixdp2800.c295
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x00.c306
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x01.c483
-rw-r--r--arch/arm/mach-ixp2000/pci.c252
-rw-r--r--arch/arm/mach-ixp23xx/Kconfig25
-rw-r--r--arch/arm/mach-ixp23xx/Makefile11
-rw-r--r--arch/arm/mach-ixp23xx/Makefile.boot2
-rw-r--r--arch/arm/mach-ixp23xx/core.c455
-rw-r--r--arch/arm/mach-ixp23xx/espresso.c93
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/debug-macro.S25
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/entry-macro.S31
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/hardware.h32
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/io.h22
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/irqs.h223
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/ixdp2351.h89
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/ixp23xx.h298
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/memory.h34
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/platform.h58
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/time.h3
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/timex.h7
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/uncompress.h40
-rw-r--r--arch/arm/mach-ixp23xx/ixdp2351.c347
-rw-r--r--arch/arm/mach-ixp23xx/pci.c294
-rw-r--r--arch/arm/mach-ixp23xx/roadrunner.c180
-rw-r--r--arch/arm/mach-ixp4xx/avila-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/common-pci.c6
-rw-r--r--arch/arm/mach-ixp4xx/coyote-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/fsg-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/gateway7001-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/goramo_mlr.c3
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/platform.h2
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/ixdpg425-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/miccpt-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/vulcan-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/wg302v2-pci.c3
-rw-r--r--arch/arm/mach-kirkwood/Kconfig22
-rw-r--r--arch/arm/mach-kirkwood/Makefile3
-rw-r--r--arch/arm/mach-kirkwood/Makefile.boot4
-rw-r--r--arch/arm/mach-kirkwood/board-dnskw.c275
-rw-r--r--arch/arm/mach-kirkwood/board-dt.c13
-rw-r--r--arch/arm/mach-kirkwood/board-ib62x0.c143
-rw-r--r--arch/arm/mach-kirkwood/board-iconnect.c165
-rw-r--r--arch/arm/mach-kirkwood/common.c12
-rw-r--r--arch/arm/mach-kirkwood/common.h18
-rw-r--r--arch/arm/mach-kirkwood/pcie.c16
-rw-r--r--arch/arm/mach-ks8695/pci.c9
-rw-r--r--arch/arm/mach-lpc32xx/Kconfig26
-rw-r--r--arch/arm/mach-lpc32xx/clock.c77
-rw-r--r--arch/arm/mach-lpc32xx/common.c188
-rw-r--r--arch/arm/mach-lpc32xx/common.h14
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/i2c.h63
-rw-r--r--arch/arm/mach-lpc32xx/irq.c78
-rw-r--r--arch/arm/mach-lpc32xx/phy3250.c149
-rw-r--r--arch/arm/mach-mmp/Kconfig36
-rw-r--r--arch/arm/mach-mmp/Makefile14
-rw-r--r--arch/arm/mach-mmp/aspenite.c20
-rw-r--r--arch/arm/mach-mmp/devices.c282
-rw-r--r--arch/arm/mach-mmp/include/mach/addr-map.h12
-rw-r--r--arch/arm/mach-mmp/include/mach/devices.h3
-rw-r--r--arch/arm/mach-mmp/include/mach/entry-macro.S4
-rw-r--r--arch/arm/mach-mmp/include/mach/irqs.h27
-rw-r--r--arch/arm/mach-mmp/include/mach/pm-mmp2.h61
-rw-r--r--arch/arm/mach-mmp/include/mach/pm-pxa910.h77
-rw-r--r--arch/arm/mach-mmp/include/mach/pxa168.h8
-rw-r--r--arch/arm/mach-mmp/include/mach/pxa910.h3
-rw-r--r--arch/arm/mach-mmp/include/mach/regs-apbc.h3
-rw-r--r--arch/arm/mach-mmp/include/mach/regs-apmu.h3
-rw-r--r--arch/arm/mach-mmp/include/mach/regs-usb.h253
-rw-r--r--arch/arm/mach-mmp/irq-mmp2.c158
-rw-r--r--arch/arm/mach-mmp/irq-pxa168.c54
-rw-r--r--arch/arm/mach-mmp/irq.c458
-rw-r--r--arch/arm/mach-mmp/mmp-dt.c66
-rw-r--r--arch/arm/mach-mmp/mmp2-dt.c60
-rw-r--r--arch/arm/mach-mmp/pm-mmp2.c264
-rw-r--r--arch/arm/mach-mmp/pm-pxa910.c285
-rw-r--r--arch/arm/mach-mmp/pxa168.c20
-rw-r--r--arch/arm/mach-mmp/pxa910.c2
-rw-r--r--arch/arm/mach-mmp/time.c81
-rw-r--r--arch/arm/mach-mmp/ttc_dkb.c48
-rw-r--r--arch/arm/mach-msm/board-msm7x30.c1
-rw-r--r--arch/arm/mach-msm/board-qsd8x50.c1
-rw-r--r--arch/arm/mach-msm/include/mach/debug-macro.S3
-rw-r--r--arch/arm/mach-msm/scm.c3
-rw-r--r--arch/arm/mach-mv78xx0/pcie.c24
-rw-r--r--arch/arm/mach-mxs/Kconfig2
-rw-r--r--arch/arm/mach-mxs/devices-mx23.h12
-rw-r--r--arch/arm/mach-mxs/devices-mx28.h12
-rw-r--r--arch/arm/mach-mxs/devices.c16
-rw-r--r--arch/arm/mach-mxs/devices/Makefile1
-rw-r--r--arch/arm/mach-mxs/devices/amba-duart.c40
-rw-r--r--arch/arm/mach-mxs/include/mach/common.h2
-rw-r--r--arch/arm/mach-mxs/include/mach/devices-common.h5
-rw-r--r--arch/arm/mach-mxs/mach-apx4devkit.c2
-rw-r--r--arch/arm/mach-mxs/mach-m28evk.c2
-rw-r--r--arch/arm/mach-mxs/mach-mx23evk.c2
-rw-r--r--arch/arm/mach-mxs/mach-mx28evk.c2
-rw-r--r--arch/arm/mach-mxs/mach-stmp378x_devb.c2
-rw-r--r--arch/arm/mach-mxs/mach-tx28.c2
-rw-r--r--arch/arm/mach-mxs/mm.c11
-rw-r--r--arch/arm/mach-nomadik/Kconfig1
-rw-r--r--arch/arm/mach-omap1/Kconfig1
-rw-r--r--arch/arm/mach-omap1/Makefile13
-rw-r--r--arch/arm/mach-omap1/ams-delta-fiq.c2
-rw-r--r--arch/arm/mach-omap1/board-fsample.c16
-rw-r--r--arch/arm/mach-omap1/board-h2.c17
-rw-r--r--arch/arm/mach-omap1/board-h3.c16
-rw-r--r--arch/arm/mach-omap1/board-nand.c37
-rw-r--r--arch/arm/mach-omap1/board-palmz71.c4
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c16
-rw-r--r--arch/arm/mach-omap1/clock.c3
-rw-r--r--arch/arm/mach-omap1/common.h15
-rw-r--r--arch/arm/mach-omap1/fpga.c2
-rw-r--r--arch/arm/mach-omap1/id.c2
-rw-r--r--arch/arm/mach-omap1/io.c3
-rw-r--r--arch/arm/mach-omap1/irq.c2
-rw-r--r--arch/arm/mach-omap1/lcd_dma.c7
-rw-r--r--arch/arm/mach-omap1/ocpi.c (renamed from arch/arm/plat-omap/ocpi.c)7
-rw-r--r--arch/arm/mach-omap1/pm.c9
-rw-r--r--arch/arm/mach-omap1/reset.c2
-rw-r--r--arch/arm/mach-omap1/timer.c3
-rw-r--r--arch/arm/mach-omap1/usb.c3
-rw-r--r--arch/arm/mach-omap2/Kconfig1
-rw-r--r--arch/arm/mach-omap2/Makefile13
-rw-r--r--arch/arm/mach-omap2/am35xx-emac.c37
-rw-r--r--arch/arm/mach-omap2/board-3430sdp.c38
-rw-r--r--arch/arm/mach-omap2/board-4430sdp.c91
-rw-r--r--arch/arm/mach-omap2/board-am3517crane.c2
-rw-r--r--arch/arm/mach-omap2/board-am3517evm.c25
-rw-r--r--arch/arm/mach-omap2/board-cm-t35.c35
-rw-r--r--arch/arm/mach-omap2/board-devkit8000.c30
-rw-r--r--arch/arm/mach-omap2/board-flash.c4
-rw-r--r--arch/arm/mach-omap2/board-flash.h11
-rw-r--r--arch/arm/mach-omap2/board-generic.c37
-rw-r--r--arch/arm/mach-omap2/board-igep0020.c116
-rw-r--r--arch/arm/mach-omap2/board-omap3beagle.c44
-rw-r--r--arch/arm/mach-omap2/board-omap3evm.c37
-rw-r--r--arch/arm/mach-omap2/board-omap3logic.c26
-rw-r--r--arch/arm/mach-omap2/board-omap3stalker.c29
-rw-r--r--arch/arm/mach-omap2/board-omap4panda.c119
-rw-r--r--arch/arm/mach-omap2/board-overo.c25
-rw-r--r--arch/arm/mach-omap2/board-rx51-peripherals.c92
-rw-r--r--arch/arm/mach-omap2/board-rx51.c38
-rw-r--r--arch/arm/mach-omap2/board-zoom-display.c1
-rw-r--r--arch/arm/mach-omap2/clock.c2
-rw-r--r--arch/arm/mach-omap2/clock3xxx_data.c25
-rw-r--r--arch/arm/mach-omap2/clock44xx_data.c11
-rw-r--r--arch/arm/mach-omap2/clockdomain.c7
-rw-r--r--arch/arm/mach-omap2/clockdomain44xx.c6
-rw-r--r--arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c10
-rw-r--r--arch/arm/mach-omap2/clockdomains3xxx_data.c6
-rw-r--r--arch/arm/mach-omap2/clockdomains44xx_data.c2
-rw-r--r--arch/arm/mach-omap2/clockdomains_common_data.c24
-rw-r--r--arch/arm/mach-omap2/cm-regbits-34xx.h4
-rw-r--r--arch/arm/mach-omap2/cminst44xx.c28
-rw-r--r--arch/arm/mach-omap2/common.c1
-rw-r--r--arch/arm/mach-omap2/common.h6
-rw-r--r--arch/arm/mach-omap2/cpuidle34xx.c298
-rw-r--r--arch/arm/mach-omap2/cpuidle44xx.c126
-rw-r--r--arch/arm/mach-omap2/devices.c47
-rw-r--r--arch/arm/mach-omap2/dpll3xxx.c23
-rw-r--r--arch/arm/mach-omap2/dsp.c5
-rw-r--r--arch/arm/mach-omap2/gpio.c10
-rw-r--r--arch/arm/mach-omap2/gpmc-onenand.c3
-rw-r--r--arch/arm/mach-omap2/gpmc.c3
-rw-r--r--arch/arm/mach-omap2/hdq1w.c72
-rw-r--r--arch/arm/mach-omap2/hwspinlock.c2
-rw-r--r--arch/arm/mach-omap2/id.c5
-rw-r--r--arch/arm/mach-omap2/io.c19
-rw-r--r--arch/arm/mach-omap2/irq.c6
-rw-r--r--arch/arm/mach-omap2/mailbox.c6
-rw-r--r--arch/arm/mach-omap2/msdi.c88
-rw-r--r--arch/arm/mach-omap2/mux.c2
-rw-r--r--arch/arm/mach-omap2/omap-secure.c1
-rw-r--r--arch/arm/mach-omap2/omap-wakeupgen.c2
-rw-r--r--arch/arm/mach-omap2/omap4-common.c58
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c1143
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2420_data.c1580
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2430_data.c1968
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c9
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c22
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c266
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c585
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c3087
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c6323
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_common_data.h76
-rw-r--r--arch/arm/mach-omap2/pm.h21
-rw-r--r--arch/arm/mach-omap2/pm24xx.c3
-rw-r--r--arch/arm/mach-omap2/pm34xx.c10
-rw-r--r--arch/arm/mach-omap2/powerdomain.c10
-rw-r--r--arch/arm/mach-omap2/powerdomain.h1
-rw-r--r--arch/arm/mach-omap2/prcm-common.h17
-rw-r--r--arch/arm/mach-omap2/prcm.c8
-rw-r--r--arch/arm/mach-omap2/prm_common.c4
-rw-r--r--arch/arm/mach-omap2/prminst44xx.c27
-rw-r--r--arch/arm/mach-omap2/serial.c10
-rw-r--r--arch/arm/mach-omap2/timer.c22
-rw-r--r--arch/arm/mach-omap2/twl-common.c190
-rw-r--r--arch/arm/mach-omap2/twl-common.h2
-rw-r--r--arch/arm/mach-omap2/usb-tusb6010.c2
-rw-r--r--arch/arm/mach-omap2/vc3xxx_data.c1
-rw-r--r--arch/arm/mach-omap2/voltage.c21
-rw-r--r--arch/arm/mach-omap2/wd_timer.c45
-rw-r--r--arch/arm/mach-omap2/wd_timer.h1
-rw-r--r--arch/arm/mach-orion5x/Kconfig1
-rw-r--r--arch/arm/mach-orion5x/addr-map.c2
-rw-r--r--arch/arm/mach-orion5x/common.c2
-rw-r--r--arch/arm/mach-orion5x/common.h1
-rw-r--r--arch/arm/mach-orion5x/db88f5281-setup.c1
-rw-r--r--arch/arm/mach-orion5x/dns323-setup.c26
-rw-r--r--arch/arm/mach-orion5x/kurobox_pro-setup.c1
-rw-r--r--arch/arm/mach-orion5x/mss2-setup.c1
-rw-r--r--arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c1
-rw-r--r--arch/arm/mach-orion5x/rd88f5181l-ge-setup.c1
-rw-r--r--arch/arm/mach-orion5x/rd88f5182-setup.c1
-rw-r--r--arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c1
-rw-r--r--arch/arm/mach-orion5x/terastation_pro2-setup.c1
-rw-r--r--arch/arm/mach-orion5x/ts209-setup.c1
-rw-r--r--arch/arm/mach-orion5x/ts409-setup.c1
-rw-r--r--arch/arm/mach-orion5x/ts78xx-fpga.h6
-rw-r--r--arch/arm/mach-orion5x/ts78xx-setup.c52
-rw-r--r--arch/arm/mach-orion5x/wnr854t-setup.c1
-rw-r--r--arch/arm/mach-orion5x/wrt350n-v2-setup.c1
-rw-r--r--arch/arm/mach-pnx4008/i2c.c64
-rw-r--r--arch/arm/mach-pnx4008/include/mach/i2c.h64
-rw-r--r--arch/arm/mach-prima2/irq.c6
-rw-r--r--arch/arm/mach-pxa/balloon3.c4
-rw-r--r--arch/arm/mach-pxa/cm-x2xx-pci.c3
-rw-r--r--arch/arm/mach-pxa/cm-x300.c4
-rw-r--r--arch/arm/mach-pxa/em-x270.c5
-rw-r--r--arch/arm/mach-pxa/hx4700.c47
-rw-r--r--arch/arm/mach-pxa/include/mach/mfp-pxa27x.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/mioa701.h3
-rw-r--r--arch/arm/mach-pxa/include/mach/pcm990_baseboard.h68
-rw-r--r--arch/arm/mach-pxa/magician.c8
-rw-r--r--arch/arm/mach-pxa/mioa701.c6
-rw-r--r--arch/arm/mach-pxa/palm27x.c4
-rw-r--r--arch/arm/mach-pxa/pcm990-baseboard.c83
-rw-r--r--arch/arm/mach-pxa/spitz.c4
-rw-r--r--arch/arm/mach-pxa/stargate2.c5
-rw-r--r--arch/arm/mach-pxa/vpac270.c4
-rw-r--r--arch/arm/mach-pxa/z2.c4
-rw-r--r--arch/arm/mach-s3c24xx/bast-ide.c36
-rw-r--r--arch/arm/mach-s3c24xx/mach-amlm5900.c9
-rw-r--r--arch/arm/mach-s3c24xx/mach-anubis.c62
-rw-r--r--arch/arm/mach-s3c24xx/mach-at2440evb.c19
-rw-r--r--arch/arm/mach-s3c24xx/mach-bast.c45
-rw-r--r--arch/arm/mach-s3c24xx/mach-gta02.c7
-rw-r--r--arch/arm/mach-s3c24xx/mach-h1940.c9
-rw-r--r--arch/arm/mach-s3c24xx/mach-mini2440.c19
-rw-r--r--arch/arm/mach-s3c24xx/mach-nexcoder.c6
-rw-r--r--arch/arm/mach-s3c24xx/mach-osiris.c12
-rw-r--r--arch/arm/mach-s3c24xx/mach-otom.c6
-rw-r--r--arch/arm/mach-s3c24xx/mach-qt2410.c12
-rw-r--r--arch/arm/mach-s3c24xx/mach-rx1950.c9
-rw-r--r--arch/arm/mach-s3c24xx/mach-tct_hammer.c7
-rw-r--r--arch/arm/mach-s3c24xx/mach-vr1000.c39
-rw-r--r--arch/arm/mach-s3c24xx/simtec-nor.c6
-rw-r--r--arch/arm/mach-s3c64xx/Kconfig4
-rw-r--r--arch/arm/mach-s3c64xx/dev-audio.c120
-rw-r--r--arch/arm/mach-s3c64xx/dev-uart.c48
-rw-r--r--arch/arm/mach-s3c64xx/mach-anw6410.c19
-rw-r--r--arch/arm/mach-s3c64xx/mach-crag6410.c46
-rw-r--r--arch/arm/mach-s3c64xx/mach-mini6410.c19
-rw-r--r--arch/arm/mach-s3c64xx/mach-real6410.c19
-rw-r--r--arch/arm/mach-s3c64xx/mach-smartq.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-smdk6410.c15
-rw-r--r--arch/arm/mach-s5p64x0/dev-audio.c72
-rw-r--r--arch/arm/mach-s5pc100/dev-audio.c138
-rw-r--r--arch/arm/mach-s5pv210/Kconfig1
-rw-r--r--arch/arm/mach-s5pv210/dev-audio.c156
-rw-r--r--arch/arm/mach-s5pv210/mach-goni.c6
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkv210.c19
-rw-r--r--arch/arm/mach-sa1100/pci-nanoengine.c8
-rw-r--r--arch/arm/mach-shark/pci.c3
-rw-r--r--arch/arm/mach-shmobile/Kconfig31
-rw-r--r--arch/arm/mach-shmobile/Makefile5
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c37
-rw-r--r--arch/arm/mach-shmobile/board-armadillo800eva.c784
-rw-r--r--arch/arm/mach-shmobile/board-bonito.c2
-rw-r--r--arch/arm/mach-shmobile/board-kzm9d.c85
-rw-r--r--arch/arm/mach-shmobile/board-kzm9g.c460
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c45
-rw-r--r--arch/arm/mach-shmobile/clock-emev2.c249
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7740.c128
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h2
-rw-r--r--arch/arm/mach-shmobile/include/mach/emev2.h19
-rw-r--r--arch/arm/mach-shmobile/include/mach/intc.h44
-rw-r--r--arch/arm/mach-shmobile/include/mach/irqs.h2
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh7372.h2
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh73a0.h37
-rw-r--r--arch/arm/mach-shmobile/intc-sh7372.c34
-rw-r--r--arch/arm/mach-shmobile/pfc-r8a7740.c39
-rw-r--r--arch/arm/mach-shmobile/pfc-sh73a0.c4
-rw-r--r--arch/arm/mach-shmobile/platsmp.c21
-rw-r--r--arch/arm/mach-shmobile/setup-emev2.c452
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7740.c19
-rw-r--r--arch/arm/mach-shmobile/setup-sh7372.c58
-rw-r--r--arch/arm/mach-shmobile/smp-emev2.c97
-rw-r--r--arch/arm/mach-shmobile/timer.c18
-rw-r--r--arch/arm/mach-spear3xx/Kconfig37
-rw-r--r--arch/arm/mach-spear3xx/Makefile13
-rw-r--r--arch/arm/mach-spear3xx/Makefile.boot4
-rw-r--r--arch/arm/mach-spear3xx/clock.c280
-rw-r--r--arch/arm/mach-spear3xx/include/mach/generic.h164
-rw-r--r--arch/arm/mach-spear3xx/include/mach/hardware.h24
-rw-r--r--arch/arm/mach-spear3xx/include/mach/irqs.h130
-rw-r--r--arch/arm/mach-spear3xx/include/mach/misc_regs.h144
-rw-r--r--arch/arm/mach-spear3xx/include/mach/spear.h47
-rw-r--r--arch/arm/mach-spear3xx/include/mach/spear300.h54
-rw-r--r--arch/arm/mach-spear3xx/include/mach/spear310.h58
-rw-r--r--arch/arm/mach-spear3xx/include/mach/spear320.h67
-rw-r--r--arch/arm/mach-spear3xx/spear300.c654
-rw-r--r--arch/arm/mach-spear3xx/spear300_evb.c75
-rw-r--r--arch/arm/mach-spear3xx/spear310.c476
-rw-r--r--arch/arm/mach-spear3xx/spear310_evb.c81
-rw-r--r--arch/arm/mach-spear3xx/spear320.c725
-rw-r--r--arch/arm/mach-spear3xx/spear320_evb.c79
-rw-r--r--arch/arm/mach-spear3xx/spear3xx.c547
-rw-r--r--arch/arm/mach-spear6xx/Kconfig18
-rw-r--r--arch/arm/mach-spear6xx/Makefile.boot2
-rw-r--r--arch/arm/mach-spear6xx/clock.c186
-rw-r--r--arch/arm/mach-spear6xx/include/mach/generic.h29
-rw-r--r--arch/arm/mach-spear6xx/include/mach/hardware.h24
-rw-r--r--arch/arm/mach-spear6xx/include/mach/irqs.h75
-rw-r--r--arch/arm/mach-spear6xx/include/mach/misc_regs.h154
-rw-r--r--arch/arm/mach-spear6xx/include/mach/spear.h55
-rw-r--r--arch/arm/mach-spear6xx/include/mach/spear600.h21
-rw-r--r--arch/arm/mach-spear6xx/spear6xx.c417
-rw-r--r--arch/arm/mach-tegra/Makefile3
-rw-r--r--arch/arm/mach-tegra/board-dt-tegra20.c38
-rw-r--r--arch/arm/mach-tegra/board-harmony-pinmux.c266
-rw-r--r--arch/arm/mach-tegra/board-harmony.c3
-rw-r--r--arch/arm/mach-tegra/board-paz00-pinmux.c263
-rw-r--r--arch/arm/mach-tegra/board-paz00.c3
-rw-r--r--arch/arm/mach-tegra/board-pinmux.c105
-rw-r--r--arch/arm/mach-tegra/board-pinmux.h40
-rw-r--r--arch/arm/mach-tegra/board-seaboard-pinmux.c346
-rw-r--r--arch/arm/mach-tegra/board-seaboard.c24
-rw-r--r--arch/arm/mach-tegra/board-trimslice-pinmux.c264
-rw-r--r--arch/arm/mach-tegra/board-trimslice.c18
-rw-r--r--arch/arm/mach-tegra/devices.c16
-rw-r--r--arch/arm/mach-tegra/devices.h1
-rw-r--r--arch/arm/mach-tegra/flowctrl.c4
-rw-r--r--arch/arm/mach-tegra/include/mach/dma.h4
-rw-r--r--arch/arm/mach-tegra/include/mach/gpio-tegra.h9
-rw-r--r--arch/arm/mach-tegra/include/mach/pinmux-tegra20.h184
-rw-r--r--arch/arm/mach-tegra/include/mach/pinmux-tegra30.h320
-rw-r--r--arch/arm/mach-tegra/include/mach/pinmux.h302
-rw-r--r--arch/arm/mach-tegra/pcie.c1
-rw-r--r--arch/arm/mach-tegra/pinmux-tegra20-tables.c244
-rw-r--r--arch/arm/mach-tegra/pinmux-tegra30-tables.c376
-rw-r--r--arch/arm/mach-tegra/pinmux.c987
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c10
-rw-r--r--arch/arm/mach-tegra/timer.c5
-rw-r--r--arch/arm/mach-tegra/usb_phy.c1
-rw-r--r--arch/arm/mach-ux500/Kconfig28
-rw-r--r--arch/arm/mach-ux500/Makefile9
-rw-r--r--arch/arm/mach-ux500/board-mop500-msp.c267
-rw-r--r--arch/arm/mach-ux500/board-mop500-msp.h14
-rw-r--r--arch/arm/mach-ux500/board-mop500-pins.c733
-rw-r--r--arch/arm/mach-ux500/board-mop500-uib.c2
-rw-r--r--arch/arm/mach-ux500/board-mop500.c178
-rw-r--r--arch/arm/mach-ux500/board-mop500.h10
-rw-r--r--arch/arm/mach-ux500/board-u5500-sdi.c74
-rw-r--r--arch/arm/mach-ux500/board-u5500.c162
-rw-r--r--arch/arm/mach-ux500/cache-l2x0.c18
-rw-r--r--arch/arm/mach-ux500/clock.c38
-rw-r--r--arch/arm/mach-ux500/cpu-db5500.c247
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c43
-rw-r--r--arch/arm/mach-ux500/cpu.c22
-rw-r--r--arch/arm/mach-ux500/cpuidle.c171
-rw-r--r--arch/arm/mach-ux500/devices-common.c33
-rw-r--r--arch/arm/mach-ux500/devices-common.h85
-rw-r--r--arch/arm/mach-ux500/devices-db5500.h99
-rw-r--r--arch/arm/mach-ux500/devices-db8500.c3
-rw-r--r--arch/arm/mach-ux500/devices-db8500.h16
-rw-r--r--arch/arm/mach-ux500/dma-db5500.c137
-rw-r--r--arch/arm/mach-ux500/id.c9
-rw-r--r--arch/arm/mach-ux500/include/mach/crypto-ux500.h22
-rw-r--r--arch/arm/mach-ux500/include/mach/db5500-regs.h143
-rw-r--r--arch/arm/mach-ux500/include/mach/db8500-regs.h6
-rw-r--r--arch/arm/mach-ux500/include/mach/debug-macro.S4
-rw-r--r--arch/arm/mach-ux500/include/mach/devices.h4
-rw-r--r--arch/arm/mach-ux500/include/mach/hardware.h7
-rw-r--r--arch/arm/mach-ux500/include/mach/id.h17
-rw-r--r--arch/arm/mach-ux500/include/mach/irqs-board-u5500.h21
-rw-r--r--arch/arm/mach-ux500/include/mach/irqs-db5500.h113
-rw-r--r--arch/arm/mach-ux500/include/mach/irqs.h7
-rw-r--r--arch/arm/mach-ux500/include/mach/mbox-db5500.h88
-rw-r--r--arch/arm/mach-ux500/include/mach/msp.h29
-rw-r--r--arch/arm/mach-ux500/include/mach/setup.h6
-rw-r--r--arch/arm/mach-ux500/include/mach/uncompress.h7
-rw-r--r--arch/arm/mach-ux500/mbox-db5500.c565
-rw-r--r--arch/arm/mach-ux500/modem-irq-db5500.c143
-rw-r--r--arch/arm/mach-ux500/pins-db5500.h620
-rw-r--r--arch/arm/mach-ux500/pins-db8500.h72
-rw-r--r--arch/arm/mach-ux500/platsmp.c8
-rw-r--r--arch/arm/mach-ux500/ste-dma40-db5500.h135
-rw-r--r--arch/arm/mach-ux500/timer.c37
-rw-r--r--arch/arm/mach-versatile/core.c18
-rw-r--r--arch/arm/mach-versatile/pci.c13
-rw-r--r--arch/arm/mach-vexpress/v2m.c8
-rw-r--r--arch/arm/mm/Kconfig46
-rw-r--r--arch/arm/mm/Makefile4
-rw-r--r--arch/arm/mm/cache-tauros2.c24
-rw-r--r--arch/arm/mm/cache-v3.S1
-rw-r--r--arch/arm/mm/cache-v4.S1
-rw-r--r--arch/arm/mm/cache-v4wb.S6
-rw-r--r--arch/arm/mm/cache-v4wt.S1
-rw-r--r--arch/arm/mm/cache-v6.S10
-rw-r--r--arch/arm/mm/cache-v7.S10
-rw-r--r--arch/arm/mm/context.c57
-rw-r--r--arch/arm/mm/copypage-v3.c81
-rw-r--r--arch/arm/mm/fault.c7
-rw-r--r--arch/arm/mm/mmu.c3
-rw-r--r--arch/arm/mm/proc-arm1020.S1
-rw-r--r--arch/arm/mm/proc-arm1020e.S1
-rw-r--r--arch/arm/mm/proc-arm1022.S1
-rw-r--r--arch/arm/mm/proc-arm1026.S1
-rw-r--r--arch/arm/mm/proc-arm6_7.S327
-rw-r--r--arch/arm/mm/proc-arm920.S1
-rw-r--r--arch/arm/mm/proc-arm922.S1
-rw-r--r--arch/arm/mm/proc-arm925.S1
-rw-r--r--arch/arm/mm/proc-arm926.S1
-rw-r--r--arch/arm/mm/proc-arm940.S6
-rw-r--r--arch/arm/mm/proc-arm946.S1
-rw-r--r--arch/arm/mm/proc-feroceon.S1
-rw-r--r--arch/arm/mm/proc-mohawk.S36
-rw-r--r--arch/arm/mm/proc-v7-2level.S9
-rw-r--r--arch/arm/mm/tlb-v3.S48
-rw-r--r--arch/arm/nwfpe/fpmodule.c2
-rw-r--r--arch/arm/plat-iop/pci.c8
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mx51.h48
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mx53.h4
-rw-r--r--arch/arm/plat-nomadik/include/plat/gpio-nomadik.h8
-rw-r--r--arch/arm/plat-nomadik/include/plat/pincfg.h32
-rw-r--r--arch/arm/plat-omap/Makefile3
-rw-r--r--arch/arm/plat-omap/common.c1
-rw-r--r--arch/arm/plat-omap/counter_32k.c6
-rw-r--r--arch/arm/plat-omap/devices.c4
-rw-r--r--arch/arm/plat-omap/dma.c13
-rw-r--r--arch/arm/plat-omap/dmtimer.c3
-rw-r--r--arch/arm/plat-omap/include/plat/board.h2
-rw-r--r--arch/arm/plat-omap/include/plat/clkdev_omap.h4
-rw-r--r--arch/arm/plat-omap/include/plat/common.h2
-rw-r--r--arch/arm/plat-omap/include/plat/cpu.h1
-rw-r--r--arch/arm/plat-omap/include/plat/dma.h1
-rw-r--r--arch/arm/plat-omap/include/plat/dmtimer.h6
-rw-r--r--arch/arm/plat-omap/include/plat/hdq1w.h36
-rw-r--r--arch/arm/plat-omap/include/plat/mmc.h4
-rw-r--r--arch/arm/plat-omap/include/plat/omap-serial.h1
-rw-r--r--arch/arm/plat-omap/include/plat/omap_hwmod.h41
-rw-r--r--arch/arm/plat-omap/omap_device.c2
-rw-r--r--arch/arm/plat-omap/sram.c4
-rw-r--r--arch/arm/plat-omap/usb.c8
-rw-r--r--arch/arm/plat-orion/gpio.c27
-rw-r--r--arch/arm/plat-orion/include/plat/gpio.h2
-rw-r--r--arch/arm/plat-samsung/devs.c18
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h379
-rw-r--r--arch/arm/plat-samsung/include/plat/sdhci.h7
-rw-r--r--arch/arm/plat-samsung/platformdata.c2
-rw-r--r--arch/arm/plat-spear/Kconfig4
-rw-r--r--arch/arm/plat-spear/Makefile4
-rw-r--r--arch/arm/plat-spear/include/plat/debug-macro.S2
-rw-r--r--arch/arm/plat-spear/include/plat/hardware.h17
-rw-r--r--arch/arm/plat-spear/include/plat/padmux.h92
-rw-r--r--arch/arm/plat-spear/include/plat/pl080.h21
-rw-r--r--arch/arm/plat-spear/include/plat/uncompress.h2
-rw-r--r--arch/arm/plat-spear/padmux.c164
-rw-r--r--arch/arm/plat-spear/pl080.c80
-rw-r--r--arch/arm/plat-spear/restart.c2
-rw-r--r--arch/arm/plat-spear/time.c17
-rw-r--r--arch/arm/plat-versatile/Kconfig6
-rw-r--r--arch/arm/plat-versatile/fpga-irq.c116
-rw-r--r--arch/arm/plat-versatile/include/plat/fpga-irq.h11
-rw-r--r--arch/arm/tools/mach-types505
-rw-r--r--arch/arm/vfp/vfpmodule.c40
-rw-r--r--arch/avr32/include/asm/processor.h3
-rw-r--r--arch/avr32/kernel/Makefile2
-rw-r--r--arch/avr32/kernel/init_task.c31
-rw-r--r--arch/blackfin/ADI_BSD.txt41
-rw-r--r--arch/blackfin/Clear_BSD.txt33
-rw-r--r--arch/blackfin/Kconfig187
-rw-r--r--arch/blackfin/Kconfig.debug7
-rw-r--r--arch/blackfin/Makefile4
-rw-r--r--arch/blackfin/configs/BF561-EZKIT-SMP_defconfig4
-rw-r--r--arch/blackfin/configs/BF609-EZKIT_defconfig155
-rw-r--r--arch/blackfin/include/asm/bfin-global.h5
-rw-r--r--arch/blackfin/include/asm/bfin6xx_spi.h258
-rw-r--r--arch/blackfin/include/asm/bfin_crc.h139
-rw-r--r--arch/blackfin/include/asm/bfin_dma.h84
-rw-r--r--arch/blackfin/include/asm/bfin_pfmon.h2
-rw-r--r--arch/blackfin/include/asm/bfin_ppi.h128
-rw-r--r--arch/blackfin/include/asm/bfin_rotary.h1
-rw-r--r--arch/blackfin/include/asm/bfin_serial.h182
-rw-r--r--arch/blackfin/include/asm/bfin_sport.h1
-rw-r--r--arch/blackfin/include/asm/bfin_sport3.h107
-rw-r--r--arch/blackfin/include/asm/bfin_twi.h142
-rw-r--r--arch/blackfin/include/asm/blackfin.h8
-rw-r--r--arch/blackfin/include/asm/clkdev.h14
-rw-r--r--arch/blackfin/include/asm/clocks.h23
-rw-r--r--arch/blackfin/include/asm/cplb.h4
-rw-r--r--arch/blackfin/include/asm/def_LPBlackfin.h6
-rw-r--r--arch/blackfin/include/asm/dma.h137
-rw-r--r--arch/blackfin/include/asm/dpmc.h656
-rw-r--r--arch/blackfin/include/asm/fixed_code.h30
-rw-r--r--arch/blackfin/include/asm/gpio.h44
-rw-r--r--arch/blackfin/include/asm/gptimers.h104
-rw-r--r--arch/blackfin/include/asm/irqflags.h6
-rw-r--r--arch/blackfin/include/asm/page.h5
-rw-r--r--arch/blackfin/include/asm/pda.h2
-rw-r--r--arch/blackfin/include/asm/pm.h31
-rw-r--r--arch/blackfin/include/asm/processor.h2
-rw-r--r--arch/blackfin/include/asm/unistd.h2
-rw-r--r--arch/blackfin/kernel/Makefile2
-rw-r--r--arch/blackfin/kernel/bfin_dma.c146
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c28
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cplbinit.c4
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cplbmgr.c6
-rw-r--r--arch/blackfin/kernel/debug-mmrs.c9
-rw-r--r--arch/blackfin/kernel/entry.S10
-rw-r--r--arch/blackfin/kernel/gptimers.c85
-rw-r--r--arch/blackfin/kernel/init_task.c32
-rw-r--r--arch/blackfin/kernel/process.c8
-rw-r--r--arch/blackfin/kernel/reboot.c6
-rw-r--r--arch/blackfin/kernel/setup.c132
-rw-r--r--arch/blackfin/kernel/shadow_console.c6
-rw-r--r--arch/blackfin/kernel/time-ts.c27
-rw-r--r--arch/blackfin/lib/divsi3.S2
-rw-r--r--arch/blackfin/lib/memchr.S2
-rw-r--r--arch/blackfin/lib/memcmp.S2
-rw-r--r--arch/blackfin/lib/memcpy.S2
-rw-r--r--arch/blackfin/lib/memmove.S2
-rw-r--r--arch/blackfin/lib/memset.S2
-rw-r--r--arch/blackfin/lib/modsi3.S2
-rw-r--r--arch/blackfin/lib/muldi3.S2
-rw-r--r--arch/blackfin/lib/smulsi3_highpart.S2
-rw-r--r--arch/blackfin/lib/strcmp.S2
-rw-r--r--arch/blackfin/lib/strcpy.S2
-rw-r--r--arch/blackfin/lib/strncmp.S2
-rw-r--r--arch/blackfin/lib/strncpy.S2
-rw-r--r--arch/blackfin/lib/udivsi3.S2
-rw-r--r--arch/blackfin/lib/umodsi3.S2
-rw-r--r--arch/blackfin/lib/umulsi3_highpart.S2
-rw-r--r--arch/blackfin/mach-bf518/boards/ezbrd.c5
-rw-r--r--arch/blackfin/mach-bf518/boards/tcm-bf518.c5
-rw-r--r--arch/blackfin/mach-bf518/include/mach/anomaly.h3
-rw-r--r--arch/blackfin/mach-bf518/include/mach/cdefBF512.h2
-rw-r--r--arch/blackfin/mach-bf518/include/mach/cdefBF514.h2
-rw-r--r--arch/blackfin/mach-bf518/include/mach/cdefBF516.h2
-rw-r--r--arch/blackfin/mach-bf518/include/mach/cdefBF518.h2
-rw-r--r--arch/blackfin/mach-bf518/include/mach/defBF512.h73
-rw-r--r--arch/blackfin/mach-bf518/include/mach/defBF514.h2
-rw-r--r--arch/blackfin/mach-bf518/include/mach/defBF516.h2
-rw-r--r--arch/blackfin/mach-bf518/include/mach/defBF518.h2
-rw-r--r--arch/blackfin/mach-bf527/boards/ad7160eval.c6
-rw-r--r--arch/blackfin/mach-bf527/boards/cm_bf527.c5
-rw-r--r--arch/blackfin/mach-bf527/boards/ezbrd.c5
-rw-r--r--arch/blackfin/mach-bf527/boards/ezkit.c6
-rw-r--r--arch/blackfin/mach-bf527/boards/tll6527m.c5
-rw-r--r--arch/blackfin/mach-bf527/include/mach/anomaly.h3
-rw-r--r--arch/blackfin/mach-bf527/include/mach/defBF522.h73
-rw-r--r--arch/blackfin/mach-bf527/include/mach/defBF525.h2
-rw-r--r--arch/blackfin/mach-bf527/include/mach/defBF527.h2
-rw-r--r--arch/blackfin/mach-bf533/include/mach/anomaly.h3
-rw-r--r--arch/blackfin/mach-bf533/include/mach/defBF532.h2
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537e.c5
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537u.c5
-rw-r--r--arch/blackfin/mach-bf537/boards/dnp5370.c5
-rw-r--r--arch/blackfin/mach-bf537/boards/minotaur.c5
-rw-r--r--arch/blackfin/mach-bf537/boards/stamp.c66
-rw-r--r--arch/blackfin/mach-bf537/boards/tcm_bf537.c5
-rw-r--r--arch/blackfin/mach-bf537/include/mach/anomaly.h3
-rw-r--r--arch/blackfin/mach-bf537/include/mach/defBF534.h71
-rw-r--r--arch/blackfin/mach-bf537/include/mach/defBF537.h2
-rw-r--r--arch/blackfin/mach-bf538/boards/ezkit.c8
-rw-r--r--arch/blackfin/mach-bf538/include/mach/anomaly.h3
-rw-r--r--arch/blackfin/mach-bf538/include/mach/defBF538.h78
-rw-r--r--arch/blackfin/mach-bf538/include/mach/defBF539.h2
-rw-r--r--arch/blackfin/mach-bf548/boards/cm_bf548.c10
-rw-r--r--arch/blackfin/mach-bf548/boards/ezkit.c11
-rw-r--r--arch/blackfin/mach-bf548/include/mach/anomaly.h3
-rw-r--r--arch/blackfin/mach-bf548/include/mach/defBF542.h2
-rw-r--r--arch/blackfin/mach-bf548/include/mach/defBF544.h2
-rw-r--r--arch/blackfin/mach-bf548/include/mach/defBF547.h2
-rw-r--r--arch/blackfin/mach-bf548/include/mach/defBF548.h2
-rw-r--r--arch/blackfin/mach-bf548/include/mach/defBF549.h2
-rw-r--r--arch/blackfin/mach-bf548/include/mach/defBF54x_base.h111
-rw-r--r--arch/blackfin/mach-bf561/include/mach/anomaly.h3
-rw-r--r--arch/blackfin/mach-bf561/include/mach/defBF561.h2
-rw-r--r--arch/blackfin/mach-bf609/Kconfig56
-rw-r--r--arch/blackfin/mach-bf609/Makefile6
-rw-r--r--arch/blackfin/mach-bf609/boards/Kconfig12
-rw-r--r--arch/blackfin/mach-bf609/boards/Makefile5
-rw-r--r--arch/blackfin/mach-bf609/boards/ezkit.c1340
-rw-r--r--arch/blackfin/mach-bf609/clock.c390
-rw-r--r--arch/blackfin/mach-bf609/dma.c202
-rw-r--r--arch/blackfin/mach-bf609/hibernate.S65
-rw-r--r--arch/blackfin/mach-bf609/include/mach/anomaly.h130
-rw-r--r--arch/blackfin/mach-bf609/include/mach/bf609.h93
-rw-r--r--arch/blackfin/mach-bf609/include/mach/bfin_serial.h17
-rw-r--r--arch/blackfin/mach-bf609/include/mach/blackfin.h25
-rw-r--r--arch/blackfin/mach-bf609/include/mach/cdefBF609.h15
-rw-r--r--arch/blackfin/mach-bf609/include/mach/cdefBF60x_base.h3252
-rw-r--r--arch/blackfin/mach-bf609/include/mach/defBF609.h15
-rw-r--r--arch/blackfin/mach-bf609/include/mach/defBF60x_base.h3587
-rw-r--r--arch/blackfin/mach-bf609/include/mach/dma.h116
-rw-r--r--arch/blackfin/mach-bf609/include/mach/gpio.h171
-rw-r--r--arch/blackfin/mach-bf609/include/mach/irq.h318
-rw-r--r--arch/blackfin/mach-bf609/include/mach/mem_map.h86
-rw-r--r--arch/blackfin/mach-bf609/include/mach/pll.h1
-rw-r--r--arch/blackfin/mach-bf609/include/mach/pm.h21
-rw-r--r--arch/blackfin/mach-bf609/include/mach/portmux.h347
-rw-r--r--arch/blackfin/mach-bf609/pm.c362
-rw-r--r--arch/blackfin/mach-common/Makefile5
-rw-r--r--arch/blackfin/mach-common/clock.h27
-rw-r--r--arch/blackfin/mach-common/clocks-init.c153
-rw-r--r--arch/blackfin/mach-common/cpufreq.c46
-rw-r--r--arch/blackfin/mach-common/dpmc_modes.S606
-rw-r--r--arch/blackfin/mach-common/entry.S5
-rw-r--r--arch/blackfin/mach-common/head.S2
-rw-r--r--arch/blackfin/mach-common/ints-priority.c423
-rw-r--r--arch/blackfin/mach-common/pm.c62
-rw-r--r--arch/blackfin/mach-common/smp.c19
-rw-r--r--arch/blackfin/mm/init.c14
-rw-r--r--arch/blackfin/mm/sram-alloc.c36
-rw-r--r--arch/c6x/Kconfig14
-rw-r--r--arch/c6x/include/asm/elf.h14
-rw-r--r--arch/c6x/include/asm/mmu.h4
-rw-r--r--arch/c6x/include/asm/processor.h3
-rw-r--r--arch/c6x/include/asm/ptrace.h5
-rw-r--r--arch/c6x/include/asm/thread_info.h17
-rw-r--r--arch/c6x/kernel/process.c16
-rw-r--r--arch/cris/Kconfig1
-rw-r--r--arch/cris/arch-v32/kernel/smp.c14
-rw-r--r--arch/cris/include/asm/processor.h9
-rw-r--r--arch/cris/include/asm/thread_info.h6
-rw-r--r--arch/cris/kernel/process.c28
-rw-r--r--arch/frv/Makefile2
-rw-r--r--arch/frv/include/asm/processor.h6
-rw-r--r--arch/frv/include/asm/thread_info.h15
-rw-r--r--arch/frv/kernel/Makefile2
-rw-r--r--arch/frv/kernel/init_task.c32
-rw-r--r--arch/frv/kernel/process.c26
-rw-r--r--arch/h8300/include/asm/processor.h2
-rw-r--r--arch/h8300/kernel/Makefile2
-rw-r--r--arch/h8300/kernel/init_task.c36
-rw-r--r--arch/hexagon/Kconfig24
-rw-r--r--arch/hexagon/Makefile8
-rw-r--r--arch/hexagon/include/asm/processor.h7
-rw-r--r--arch/hexagon/include/asm/spinlock_types.h2
-rw-r--r--arch/hexagon/include/asm/thread_info.h8
-rw-r--r--arch/hexagon/kernel/Makefile2
-rw-r--r--arch/hexagon/kernel/dma.c2
-rw-r--r--arch/hexagon/kernel/init_task.c54
-rw-r--r--arch/hexagon/kernel/process.c37
-rw-r--r--arch/hexagon/kernel/smp.c11
-rw-r--r--arch/hexagon/kernel/time.c6
-rw-r--r--arch/hexagon/mm/vm_fault.c22
-rw-r--r--arch/ia64/Kconfig4
-rw-r--r--arch/ia64/include/asm/Kbuild1
-rw-r--r--arch/ia64/include/asm/irq_remapping.h4
-rw-r--r--arch/ia64/include/asm/processor.h9
-rw-r--r--arch/ia64/include/asm/thread_info.h3
-rw-r--r--arch/ia64/include/asm/topology.h25
-rw-r--r--arch/ia64/kernel/fsys.S191
-rw-r--r--arch/ia64/kernel/process.c20
-rw-r--r--arch/ia64/kernel/smpboot.c63
-rw-r--r--arch/m32r/Makefile2
-rw-r--r--arch/m32r/include/asm/processor.h2
-rw-r--r--arch/m32r/include/asm/thread_info.h17
-rw-r--r--arch/m32r/kernel/Makefile2
-rw-r--r--arch/m32r/kernel/init_task.c34
-rw-r--r--arch/m32r/kernel/smpboot.c6
-rw-r--r--arch/m68k/Kconfig.cpu2
-rw-r--r--arch/m68k/Makefile25
-rw-r--r--arch/m68k/amiga/platform.c126
-rw-r--r--arch/m68k/atari/ataints.c4
-rw-r--r--arch/m68k/configs/m5475evb_defconfig62
-rw-r--r--arch/m68k/include/asm/atariints.h4
-rw-r--r--arch/m68k/include/asm/cacheflush_no.h32
-rw-r--r--arch/m68k/include/asm/entry.h6
-rw-r--r--arch/m68k/include/asm/flat.h7
-rw-r--r--arch/m68k/include/asm/io_mm.h7
-rw-r--r--arch/m68k/include/asm/m528xsim.h179
-rw-r--r--arch/m68k/include/asm/mcfgpio.h57
-rw-r--r--arch/m68k/include/asm/processor.h3
-rw-r--r--arch/m68k/include/asm/unaligned.h2
-rw-r--r--arch/m68k/include/asm/vga.h27
-rw-r--r--arch/m68k/kernel/Makefile2
-rw-r--r--arch/m68k/kernel/dma.c165
-rw-r--r--arch/m68k/kernel/dma_mm.c131
-rw-r--r--arch/m68k/kernel/dma_no.c75
-rw-r--r--arch/m68k/kernel/init_task.c35
-rw-r--r--arch/m68k/kernel/signal.c1201
-rw-r--r--arch/m68k/kernel/signal_mm.c1115
-rw-r--r--arch/m68k/kernel/signal_no.c765
-rw-r--r--arch/m68k/mm/fault.c42
-rw-r--r--arch/m68k/platform/5206/Makefile18
-rw-r--r--arch/m68k/platform/5206/gpio.c49
-rw-r--r--arch/m68k/platform/520x/Makefile17
-rw-r--r--arch/m68k/platform/520x/gpio.c175
-rw-r--r--arch/m68k/platform/523x/Makefile17
-rw-r--r--arch/m68k/platform/523x/gpio.c284
-rw-r--r--arch/m68k/platform/5249/Makefile18
-rw-r--r--arch/m68k/platform/5249/gpio.c65
-rw-r--r--arch/m68k/platform/5272/Makefile18
-rw-r--r--arch/m68k/platform/5272/gpio.c81
-rw-r--r--arch/m68k/platform/527x/Makefile18
-rw-r--r--arch/m68k/platform/527x/gpio.c609
-rw-r--r--arch/m68k/platform/528x/Makefile18
-rw-r--r--arch/m68k/platform/528x/gpio.c438
-rw-r--r--arch/m68k/platform/5307/Makefile20
-rw-r--r--arch/m68k/platform/5307/gpio.c49
-rw-r--r--arch/m68k/platform/532x/Makefile18
-rw-r--r--arch/m68k/platform/532x/gpio.c337
-rw-r--r--arch/m68k/platform/5407/Makefile18
-rw-r--r--arch/m68k/platform/5407/gpio.c49
-rw-r--r--arch/m68k/platform/54xx/Makefile19
-rw-r--r--arch/m68k/platform/coldfire/Makefile28
-rw-r--r--arch/m68k/platform/coldfire/firebee.c (renamed from arch/m68k/platform/54xx/firebee.c)0
-rw-r--r--arch/m68k/platform/coldfire/gpio.c4
-rw-r--r--arch/m68k/platform/coldfire/intc-5249.c (renamed from arch/m68k/platform/5249/intc2.c)0
-rw-r--r--arch/m68k/platform/coldfire/intc-5272.c (renamed from arch/m68k/platform/5272/intc.c)0
-rw-r--r--arch/m68k/platform/coldfire/m5206.c (renamed from arch/m68k/platform/5206/config.c)9
-rw-r--r--arch/m68k/platform/coldfire/m520x.c (renamed from arch/m68k/platform/520x/config.c)16
-rw-r--r--arch/m68k/platform/coldfire/m523x.c (renamed from arch/m68k/platform/523x/config.c)22
-rw-r--r--arch/m68k/platform/coldfire/m5249.c (renamed from arch/m68k/platform/5249/config.c)10
-rw-r--r--arch/m68k/platform/coldfire/m5272.c (renamed from arch/m68k/platform/5272/config.c)11
-rw-r--r--arch/m68k/platform/coldfire/m527x.c (renamed from arch/m68k/platform/527x/config.c)43
-rw-r--r--arch/m68k/platform/coldfire/m528x.c (renamed from arch/m68k/platform/528x/config.c)31
-rw-r--r--arch/m68k/platform/coldfire/m5307.c (renamed from arch/m68k/platform/5307/config.c)9
-rw-r--r--arch/m68k/platform/coldfire/m532x.c (renamed from arch/m68k/platform/532x/config.c)27
-rw-r--r--arch/m68k/platform/coldfire/m5407.c (renamed from arch/m68k/platform/5407/config.c)9
-rw-r--r--arch/m68k/platform/coldfire/m54xx.c (renamed from arch/m68k/platform/54xx/config.c)7
-rw-r--r--arch/m68k/platform/coldfire/nettel.c (renamed from arch/m68k/platform/5307/nettel.c)0
-rw-r--r--arch/microblaze/include/asm/processor.h1
-rw-r--r--arch/microblaze/kernel/Makefile2
-rw-r--r--arch/microblaze/kernel/init_task.c26
-rw-r--r--arch/microblaze/kernel/ptrace.c2
-rw-r--r--arch/microblaze/pci/pci-common.c1
-rw-r--r--arch/mips/Kconfig6
-rw-r--r--arch/mips/Kconfig.debug2
-rw-r--r--arch/mips/Makefile2
-rw-r--r--arch/mips/include/asm/mach-ip27/topology.h17
-rw-r--r--arch/mips/include/asm/processor.h3
-rw-r--r--arch/mips/include/asm/thread_info.h12
-rw-r--r--arch/mips/kernel/Makefile2
-rw-r--r--arch/mips/kernel/init_task.c35
-rw-r--r--arch/mips/kernel/mips-mt.c2
-rw-r--r--arch/mips/kernel/perf_event_mipsxx.c2
-rw-r--r--arch/mips/kernel/ptrace.c2
-rw-r--r--arch/mips/kernel/smp.c56
-rw-r--r--arch/mips/lantiq/xway/gpio.c2
-rw-r--r--arch/mips/lantiq/xway/gpio_ebu.c2
-rw-r--r--arch/mips/lantiq/xway/gpio_stp.c2
-rw-r--r--arch/mips/sni/pcimt.c2
-rw-r--r--arch/mn10300/Makefile2
-rw-r--r--arch/mn10300/include/asm/processor.h3
-rw-r--r--arch/mn10300/include/asm/thread_info.h17
-rw-r--r--arch/mn10300/kernel/Makefile2
-rw-r--r--arch/mn10300/kernel/init_task.c39
-rw-r--r--arch/mn10300/kernel/kgdb.c3
-rw-r--r--arch/mn10300/kernel/process.c10
-rw-r--r--arch/mn10300/kernel/smp.c2
-rw-r--r--arch/openrisc/Kconfig3
-rw-r--r--arch/openrisc/Makefile2
-rw-r--r--arch/openrisc/include/asm/Kbuild3
-rw-r--r--arch/openrisc/include/asm/dma-mapping.h147
-rw-r--r--arch/openrisc/include/asm/elf.h12
-rw-r--r--arch/openrisc/include/asm/processor.h4
-rw-r--r--arch/openrisc/include/asm/ptrace.h6
-rw-r--r--arch/openrisc/kernel/Makefile2
-rw-r--r--arch/openrisc/kernel/dma.c109
-rw-r--r--arch/openrisc/kernel/entry.S8
-rw-r--r--arch/openrisc/kernel/init_task.c42
-rw-r--r--arch/openrisc/kernel/irq.c83
-rw-r--r--arch/openrisc/mm/fault.c32
-rw-r--r--arch/parisc/Kconfig1
-rw-r--r--arch/parisc/Makefile2
-rw-r--r--arch/parisc/include/asm/kbdleds.h19
-rw-r--r--arch/parisc/include/asm/prefetch.h7
-rw-r--r--arch/parisc/include/asm/processor.h3
-rw-r--r--arch/parisc/kernel/Makefile2
-rw-r--r--arch/parisc/kernel/entry.S4
-rw-r--r--arch/parisc/kernel/init_task.c70
-rw-r--r--arch/parisc/kernel/pacache.S38
-rw-r--r--arch/parisc/kernel/smp.c25
-rw-r--r--arch/parisc/mm/init.c12
-rw-r--r--arch/powerpc/Kconfig11
-rw-r--r--arch/powerpc/Makefile49
-rw-r--r--arch/powerpc/boot/dts/bluestone.dts25
-rw-r--r--arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig1
-rw-r--r--arch/powerpc/configs/chroma_defconfig2
-rw-r--r--arch/powerpc/configs/g5_defconfig1
-rw-r--r--arch/powerpc/configs/gamecube_defconfig2
-rw-r--r--arch/powerpc/configs/maple_defconfig1
-rw-r--r--arch/powerpc/configs/mpc85xx_defconfig1
-rw-r--r--arch/powerpc/configs/mpc85xx_smp_defconfig1
-rw-r--r--arch/powerpc/configs/pasemi_defconfig1
-rw-r--r--arch/powerpc/configs/ps3_defconfig6
-rw-r--r--arch/powerpc/configs/wii_defconfig2
-rw-r--r--arch/powerpc/include/asm/asm-compat.h11
-rw-r--r--arch/powerpc/include/asm/cputhreads.h2
-rw-r--r--arch/powerpc/include/asm/hvcall.h25
-rw-r--r--arch/powerpc/include/asm/lppaca.h196
-rw-r--r--arch/powerpc/include/asm/lv1call.h4
-rw-r--r--arch/powerpc/include/asm/pSeries_reconfig.h12
-rw-r--r--arch/powerpc/include/asm/ppc_asm.h10
-rw-r--r--arch/powerpc/include/asm/processor.h4
-rw-r--r--arch/powerpc/include/asm/ptrace.h6
-rw-r--r--arch/powerpc/include/asm/switch_to.h6
-rw-r--r--arch/powerpc/include/asm/thread_info.h14
-rw-r--r--arch/powerpc/include/asm/topology.h36
-rw-r--r--arch/powerpc/include/asm/vio.h46
-rw-r--r--arch/powerpc/kernel/Makefile2
-rw-r--r--arch/powerpc/kernel/asm-offsets.c4
-rw-r--r--arch/powerpc/kernel/entry_64.S30
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S4
-rw-r--r--arch/powerpc/kernel/head_44x.S8
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S8
-rw-r--r--arch/powerpc/kernel/idle.c23
-rw-r--r--arch/powerpc/kernel/init_task.c29
-rw-r--r--arch/powerpc/kernel/irq.c2
-rw-r--r--arch/powerpc/kernel/misc_32.S203
-rw-r--r--arch/powerpc/kernel/paca.c3
-rw-r--r--arch/powerpc/kernel/process.c52
-rw-r--r--arch/powerpc/kernel/prom_init.c17
-rw-r--r--arch/powerpc/kernel/ptrace.c44
-rw-r--r--arch/powerpc/kernel/ptrace32.c32
-rw-r--r--arch/powerpc/kernel/smp.c76
-rw-r--r--arch/powerpc/kernel/vector.S10
-rw-r--r--arch/powerpc/kernel/vio.c273
-rw-r--r--arch/powerpc/lib/copyuser_64.S6
-rw-r--r--arch/powerpc/lib/mem_64.S6
-rw-r--r--arch/powerpc/lib/memcpy_64.S6
-rw-r--r--arch/powerpc/mm/hugetlbpage.c3
-rw-r--r--arch/powerpc/perf/core-book3s.c3
-rw-r--r--arch/powerpc/perf/core-fsl-emb.c3
-rw-r--r--arch/powerpc/platforms/44x/Kconfig2
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype43
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c1
-rw-r--r--arch/powerpc/platforms/ps3/Kconfig22
-rw-r--r--arch/powerpc/platforms/ps3/mm.c77
-rw-r--r--arch/powerpc/platforms/ps3/platform.h16
-rw-r--r--arch/powerpc/platforms/ps3/repository.c198
-rw-r--r--arch/powerpc/platforms/pseries/Kconfig2
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c2
-rw-r--r--arch/powerpc/platforms/pseries/plpar_wrappers.h4
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c7
-rw-r--r--arch/powerpc/sysdev/ppc4xx_msi.c42
-rw-r--r--arch/s390/Kconfig56
-rw-r--r--arch/s390/Makefile1
-rw-r--r--arch/s390/boot/.gitignore2
-rw-r--r--arch/s390/boot/compressed/.gitignore3
-rw-r--r--arch/s390/defconfig1
-rw-r--r--arch/s390/include/asm/barrier.h37
-rw-r--r--arch/s390/include/asm/ccwgroup.h14
-rw-r--r--arch/s390/include/asm/io.h7
-rw-r--r--arch/s390/include/asm/processor.h3
-rw-r--r--arch/s390/include/asm/qdio.h19
-rw-r--r--arch/s390/include/asm/setup.h3
-rw-r--r--arch/s390/include/asm/smp.h2
-rw-r--r--arch/s390/include/asm/thread_info.h2
-rw-r--r--arch/s390/include/asm/timex.h17
-rw-r--r--arch/s390/kernel/.gitignore1
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/compat_signal.c7
-rw-r--r--arch/s390/kernel/early.c2
-rw-r--r--arch/s390/kernel/entry.S21
-rw-r--r--arch/s390/kernel/entry64.S51
-rw-r--r--arch/s390/kernel/head.S123
-rw-r--r--arch/s390/kernel/init_task.c38
-rw-r--r--arch/s390/kernel/ptrace.c2
-rw-r--r--arch/s390/kernel/signal.c16
-rw-r--r--arch/s390/kernel/smp.c39
-rw-r--r--arch/s390/kernel/vdso32/.gitignore1
-rw-r--r--arch/s390/kernel/vdso64/.gitignore1
-rw-r--r--arch/s390/mm/fault.c45
-rw-r--r--arch/s390/mm/hugetlbpage.c2
-rw-r--r--arch/s390/mm/maccess.c67
-rw-r--r--arch/s390/mm/pgtable.c2
-rw-r--r--arch/score/include/asm/processor.h1
-rw-r--r--arch/score/include/asm/thread_info.h10
-rw-r--r--arch/score/kernel/Makefile2
-rw-r--r--arch/score/kernel/init_task.c46
-rw-r--r--arch/sh/Kconfig49
-rw-r--r--arch/sh/Kconfig.cpu2
-rw-r--r--arch/sh/Makefile6
-rw-r--r--arch/sh/boards/Kconfig9
-rw-r--r--arch/sh/boards/board-edosk7705.c4
-rw-r--r--arch/sh/boards/board-edosk7760.c16
-rw-r--r--arch/sh/boards/board-espt.c3
-rw-r--r--arch/sh/boards/board-magicpanelr2.c27
-rw-r--r--arch/sh/boards/board-polaris.c1
-rw-r--r--arch/sh/boards/board-secureedge5410.c1
-rw-r--r--arch/sh/boards/board-sh7757lcr.c27
-rw-r--r--arch/sh/boards/board-sh7785lcr.c15
-rw-r--r--arch/sh/boards/board-urquell.c3
-rw-r--r--arch/sh/boards/mach-ap325rxa/setup.c15
-rw-r--r--arch/sh/boards/mach-cayman/setup.c1
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c70
-rw-r--r--arch/sh/boards/mach-hp6xx/setup.c5
-rw-r--r--arch/sh/boards/mach-kfr2r09/setup.c15
-rw-r--r--arch/sh/boards/mach-lboxre2/setup.c1
-rw-r--r--arch/sh/boards/mach-microdev/setup.c1
-rw-r--r--arch/sh/boards/mach-migor/setup.c13
-rw-r--r--arch/sh/boards/mach-rsk/Kconfig10
-rw-r--r--arch/sh/boards/mach-rsk/Makefile2
-rw-r--r--arch/sh/boards/mach-rsk/devices-rsk7264.c58
-rw-r--r--arch/sh/boards/mach-rsk/devices-rsk7269.c60
-rw-r--r--arch/sh/boards/mach-sdk7780/setup.c1
-rw-r--r--arch/sh/boards/mach-se/7206/setup.c1
-rw-r--r--arch/sh/boards/mach-se/770x/setup.c11
-rw-r--r--arch/sh/boards/mach-se/7721/setup.c1
-rw-r--r--arch/sh/boards/mach-se/7722/setup.c3
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c47
-rw-r--r--arch/sh/boards/mach-se/7751/setup.c1
-rw-r--r--arch/sh/boards/mach-se/7780/setup.c1
-rw-r--r--arch/sh/boards/mach-se/board-se7619.c1
-rw-r--r--arch/sh/boards/mach-sh03/setup.c1
-rw-r--r--arch/sh/boards/mach-sh7763rdp/setup.c6
-rw-r--r--arch/sh/configs/rsk7264_defconfig80
-rw-r--r--arch/sh/configs/rsk7269_defconfig65
-rw-r--r--arch/sh/configs/sh7785lcr_32bit_defconfig2
-rw-r--r--arch/sh/drivers/dma/Kconfig17
-rw-r--r--arch/sh/drivers/dma/dma-sh.c290
-rw-r--r--arch/sh/drivers/dma/dma-sysfs.c2
-rw-r--r--arch/sh/drivers/pci/fixups-landisk.c3
-rw-r--r--arch/sh/drivers/pci/fixups-r7780rp.c7
-rw-r--r--arch/sh/drivers/pci/fixups-sdk7780.c18
-rw-r--r--arch/sh/drivers/pci/fixups-se7751.c5
-rw-r--r--arch/sh/drivers/pci/fixups-sh03.c19
-rw-r--r--arch/sh/drivers/pci/fixups-snapgear.c11
-rw-r--r--arch/sh/drivers/pci/pcie-sh7786.c3
-rw-r--r--arch/sh/include/asm/dma-sh.h87
-rw-r--r--arch/sh/include/asm/dma.h9
-rw-r--r--arch/sh/include/asm/fixmap.h2
-rw-r--r--arch/sh/include/asm/i2c-sh7760.h2
-rw-r--r--arch/sh/include/asm/io.h5
-rw-r--r--arch/sh/include/asm/io_noioport.h41
-rw-r--r--arch/sh/include/asm/irq.h13
-rw-r--r--arch/sh/include/asm/kdebug.h2
-rw-r--r--arch/sh/include/asm/kgdb.h30
-rw-r--r--arch/sh/include/asm/machvec.h1
-rw-r--r--arch/sh/include/asm/pgtable_64.h3
-rw-r--r--arch/sh/include/asm/processor.h10
-rw-r--r--arch/sh/include/asm/processor_32.h3
-rw-r--r--arch/sh/include/asm/processor_64.h4
-rw-r--r--arch/sh/include/asm/stackprotector.h27
-rw-r--r--arch/sh/include/asm/thread_info.h57
-rw-r--r--arch/sh/include/asm/topology.h25
-rw-r--r--arch/sh/include/asm/traps_64.h14
-rw-r--r--arch/sh/include/cpu-sh2/cpu/dma.h23
-rw-r--r--arch/sh/include/cpu-sh2a/cpu/dma.h1
-rw-r--r--arch/sh/include/cpu-sh2a/cpu/sh7264.h176
-rw-r--r--arch/sh/include/cpu-sh2a/cpu/sh7269.h201
-rw-r--r--arch/sh/include/cpu-sh3/cpu/dma.h13
-rw-r--r--arch/sh/include/cpu-sh4/cpu/dma-sh4a.h83
-rw-r--r--arch/sh/include/cpu-sh4/cpu/dma.h25
-rw-r--r--arch/sh/include/cpu-sh4/cpu/freq.h5
-rw-r--r--arch/sh/include/cpu-sh4/cpu/sh7734.h306
-rw-r--r--arch/sh/include/cpu-sh4a/cpu/dma.h72
-rw-r--r--arch/sh/include/cpu-sh5/cpu/dma.h6
-rw-r--r--arch/sh/include/mach-common/mach/hp6xx.h7
-rw-r--r--arch/sh/include/mach-common/mach/lboxre2.h13
-rw-r--r--arch/sh/include/mach-common/mach/sdk7780.h5
-rw-r--r--arch/sh/include/mach-common/mach/titan.h12
-rw-r--r--arch/sh/include/mach-dreamcast/mach/dma.h2
-rw-r--r--arch/sh/include/mach-landisk/mach/iodata_landisk.h19
-rw-r--r--arch/sh/include/mach-se/mach/se.h19
-rw-r--r--arch/sh/include/mach-se/mach/se7343.h9
-rw-r--r--arch/sh/include/mach-se/mach/se7721.h6
-rw-r--r--arch/sh/include/mach-se/mach/se7722.h9
-rw-r--r--arch/sh/include/mach-se/mach/se7724.h7
-rw-r--r--arch/sh/include/mach-se/mach/se7751.h3
-rw-r--r--arch/sh/include/mach-se/mach/se7780.h7
-rw-r--r--arch/sh/kernel/Makefile2
-rw-r--r--arch/sh/kernel/cpu/proc.c4
-rw-r--r--arch/sh/kernel/cpu/sh2/setup-sh7619.c6
-rw-r--r--arch/sh/kernel/cpu/sh2a/Makefile4
-rw-r--r--arch/sh/kernel/cpu/sh2a/clock-sh7264.c153
-rw-r--r--arch/sh/kernel/cpu/sh2a/clock-sh7269.c184
-rw-r--r--arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c2136
-rw-r--r--arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c2800
-rw-r--r--arch/sh/kernel/cpu/sh2a/probe.c6
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-mxg.c2
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7201.c16
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7203.c8
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7206.c8
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7264.c606
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7269.c615
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S11
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7705.c13
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh770x.c15
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7710.c13
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7720.c32
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c3
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh4-202.c12
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7750.c17
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7760.c26
-rw-r--r--arch/sh/kernel/cpu/sh4a/Makefile3
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7734.c266
-rw-r--r--arch/sh/kernel/cpu/sh4a/pinmux-sh7734.c2497
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7343.c31
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7366.c23
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c47
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7723.c47
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7724.c77
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7734.c800
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7757.c90
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7763.c30
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7770.c39
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7780.c37
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7785.c43
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7786.c47
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-shx3.c31
-rw-r--r--arch/sh/kernel/cpu/sh5/entry.S22
-rw-r--r--arch/sh/kernel/cpu/sh5/fpu.c3
-rw-r--r--arch/sh/kernel/idle.c20
-rw-r--r--arch/sh/kernel/init_task.c30
-rw-r--r--arch/sh/kernel/irq.c6
-rw-r--r--arch/sh/kernel/kgdb.c105
-rw-r--r--arch/sh/kernel/machvec.c3
-rw-r--r--arch/sh/kernel/process.c60
-rw-r--r--arch/sh/kernel/process_32.c14
-rw-r--r--arch/sh/kernel/ptrace_32.c2
-rw-r--r--arch/sh/kernel/ptrace_64.c2
-rw-r--r--arch/sh/kernel/smp.c14
-rw-r--r--arch/sh/kernel/traps_64.c2
-rw-r--r--arch/sh/mm/Makefile8
-rw-r--r--arch/sh/mm/fault.c514
-rw-r--r--arch/sh/mm/fault_32.c374
-rw-r--r--arch/sh/mm/fault_64.c265
-rw-r--r--arch/sh/mm/tlb-sh5.c40
-rw-r--r--arch/sh/mm/tlbex_32.c78
-rw-r--r--arch/sh/mm/tlbex_64.c166
-rw-r--r--arch/sh/mm/tlbflush_64.c294
-rw-r--r--arch/sh/tools/mach-types2
-rw-r--r--arch/sparc/Kbuild8
-rw-r--r--arch/sparc/Kconfig15
-rw-r--r--arch/sparc/Makefile49
-rw-r--r--arch/sparc/boot/Makefile61
-rw-r--r--arch/sparc/boot/btfixupprep.c386
-rw-r--r--arch/sparc/configs/sparc64_defconfig2
-rw-r--r--arch/sparc/include/asm/asi.h14
-rw-r--r--arch/sparc/include/asm/asmmacro.h17
-rw-r--r--arch/sparc/include/asm/btfixup.h208
-rw-r--r--arch/sparc/include/asm/cache.h114
-rw-r--r--arch/sparc/include/asm/cacheflush.h4
-rw-r--r--arch/sparc/include/asm/cacheflush_32.h73
-rw-r--r--arch/sparc/include/asm/cacheflush_64.h3
-rw-r--r--arch/sparc/include/asm/cachetlb_32.h29
-rw-r--r--arch/sparc/include/asm/cmpxchg_32.h27
-rw-r--r--arch/sparc/include/asm/contregs.h22
-rw-r--r--arch/sparc/include/asm/cpu_type.h20
-rw-r--r--arch/sparc/include/asm/cpudata_32.h1
-rw-r--r--arch/sparc/include/asm/cypress.h79
-rw-r--r--arch/sparc/include/asm/dma.h52
-rw-r--r--arch/sparc/include/asm/elf_32.h13
-rw-r--r--arch/sparc/include/asm/floppy_32.h45
-rw-r--r--arch/sparc/include/asm/floppy_64.h6
-rw-r--r--arch/sparc/include/asm/head_32.h21
-rw-r--r--arch/sparc/include/asm/leon.h66
-rw-r--r--arch/sparc/include/asm/machines.h23
-rw-r--r--arch/sparc/include/asm/mbus.h4
-rw-r--r--arch/sparc/include/asm/memreg.h51
-rw-r--r--arch/sparc/include/asm/mmu_context_32.h11
-rw-r--r--arch/sparc/include/asm/obio.h13
-rw-r--r--arch/sparc/include/asm/oplib_32.h8
-rw-r--r--arch/sparc/include/asm/page_32.h13
-rw-r--r--arch/sparc/include/asm/pgalloc_32.h76
-rw-r--r--arch/sparc/include/asm/pgtable_32.h387
-rw-r--r--arch/sparc/include/asm/pgtable_64.h4
-rw-r--r--arch/sparc/include/asm/pgtsrmmu.h50
-rw-r--r--arch/sparc/include/asm/pgtsun4c.h172
-rw-r--r--arch/sparc/include/asm/processor_32.h4
-rw-r--r--arch/sparc/include/asm/processor_64.h3
-rw-r--r--arch/sparc/include/asm/setup.h3
-rw-r--r--arch/sparc/include/asm/shmparam_32.h4
-rw-r--r--arch/sparc/include/asm/smp_32.h114
-rw-r--r--arch/sparc/include/asm/smpprim.h54
-rw-r--r--arch/sparc/include/asm/string_32.h63
-rw-r--r--arch/sparc/include/asm/sysen.h15
-rw-r--r--arch/sparc/include/asm/thread_info_32.h10
-rw-r--r--arch/sparc/include/asm/thread_info_64.h25
-rw-r--r--arch/sparc/include/asm/timer_32.h33
-rw-r--r--arch/sparc/include/asm/timex_32.h1
-rw-r--r--arch/sparc/include/asm/tlbflush_32.h56
-rw-r--r--arch/sparc/include/asm/topology_64.h19
-rw-r--r--arch/sparc/include/asm/uaccess_32.h1
-rw-r--r--arch/sparc/include/asm/vac-ops.h127
-rw-r--r--arch/sparc/include/asm/vaddrs.h16
-rw-r--r--arch/sparc/include/asm/winmacro.h49
-rw-r--r--arch/sparc/kernel/Makefile4
-rw-r--r--arch/sparc/kernel/auxio_32.c13
-rw-r--r--arch/sparc/kernel/devices.c4
-rw-r--r--arch/sparc/kernel/ds.c2
-rw-r--r--arch/sparc/kernel/entry.S432
-rw-r--r--arch/sparc/kernel/etrap_32.S50
-rw-r--r--arch/sparc/kernel/head_32.S639
-rw-r--r--arch/sparc/kernel/head_64.S2
-rw-r--r--arch/sparc/kernel/idprom.c19
-rw-r--r--arch/sparc/kernel/init_task.c22
-rw-r--r--arch/sparc/kernel/ioport.c23
-rw-r--r--arch/sparc/kernel/irq.h60
-rw-r--r--arch/sparc/kernel/irq_32.c19
-rw-r--r--arch/sparc/kernel/irq_64.c2
-rw-r--r--arch/sparc/kernel/kernel.h10
-rw-r--r--arch/sparc/kernel/leon_kernel.c98
-rw-r--r--arch/sparc/kernel/leon_smp.c122
-rw-r--r--arch/sparc/kernel/module.c21
-rw-r--r--arch/sparc/kernel/muldiv.c238
-rw-r--r--arch/sparc/kernel/of_device_32.c4
-rw-r--r--arch/sparc/kernel/pcic.c55
-rw-r--r--arch/sparc/kernel/perf_event.c4
-rw-r--r--arch/sparc/kernel/process_32.c116
-rw-r--r--arch/sparc/kernel/ptrace_64.c2
-rw-r--r--arch/sparc/kernel/rtrap_32.S76
-rw-r--r--arch/sparc/kernel/rtrap_64.S12
-rw-r--r--arch/sparc/kernel/setup_32.c70
-rw-r--r--arch/sparc/kernel/signal_32.c7
-rw-r--r--arch/sparc/kernel/smp_32.c187
-rw-r--r--arch/sparc/kernel/smp_64.c12
-rw-r--r--arch/sparc/kernel/sparc_ksyms_32.c14
-rw-r--r--arch/sparc/kernel/sun4c_irq.c264
-rw-r--r--arch/sparc/kernel/sun4d_irq.c48
-rw-r--r--arch/sparc/kernel/sun4d_smp.c127
-rw-r--r--arch/sparc/kernel/sun4m_irq.c58
-rw-r--r--arch/sparc/kernel/sun4m_smp.c124
-rw-r--r--arch/sparc/kernel/sys_sparc_32.c11
-rw-r--r--arch/sparc/kernel/systbls_64.S2
-rw-r--r--arch/sparc/kernel/time_32.c220
-rw-r--r--arch/sparc/kernel/trampoline_32.S22
-rw-r--r--arch/sparc/kernel/traps_32.c2
-rw-r--r--arch/sparc/kernel/ttable_32.S417
-rw-r--r--arch/sparc/kernel/ttable_64.S (renamed from arch/sparc/kernel/ttable.S)0
-rw-r--r--arch/sparc/kernel/unaligned_64.c1
-rw-r--r--arch/sparc/kernel/wof.S72
-rw-r--r--arch/sparc/kernel/wuf.S60
-rw-r--r--arch/sparc/lib/Makefile6
-rw-r--r--arch/sparc/lib/ashldi3.S7
-rw-r--r--arch/sparc/lib/ashrdi3.S7
-rw-r--r--arch/sparc/lib/atomic_32.S44
-rw-r--r--arch/sparc/lib/atomic_64.S49
-rw-r--r--arch/sparc/lib/bitops.S37
-rw-r--r--arch/sparc/lib/blockops.S10
-rw-r--r--arch/sparc/lib/bzero.S20
-rw-r--r--arch/sparc/lib/divdi3.S4
-rw-r--r--arch/sparc/lib/ipcsum.S9
-rw-r--r--arch/sparc/lib/ksyms.c22
-rw-r--r--arch/sparc/lib/lshrdi3.S5
-rw-r--r--arch/sparc/lib/memmove.S9
-rw-r--r--arch/sparc/lib/mul.S137
-rw-r--r--arch/sparc/lib/muldi3.S4
-rw-r--r--arch/sparc/lib/rem.S384
-rw-r--r--arch/sparc/lib/sdiv.S381
-rw-r--r--arch/sparc/lib/strlen_user_64.S8
-rw-r--r--arch/sparc/lib/strncmp_32.S8
-rw-r--r--arch/sparc/lib/strncmp_64.S8
-rw-r--r--arch/sparc/lib/strncpy_from_user_32.S6
-rw-r--r--arch/sparc/lib/strncpy_from_user_64.S8
-rw-r--r--arch/sparc/lib/ucmpdi2.c19
-rw-r--r--arch/sparc/lib/udiv.S357
-rw-r--r--arch/sparc/lib/udivdi3.S3
-rw-r--r--arch/sparc/lib/umul.S171
-rw-r--r--arch/sparc/lib/urem.S357
-rw-r--r--arch/sparc/lib/xor.S50
-rw-r--r--arch/sparc/mm/Makefile9
-rw-r--r--arch/sparc/mm/btfixup.c328
-rw-r--r--arch/sparc/mm/fault_32.c207
-rw-r--r--arch/sparc/mm/init_32.c51
-rw-r--r--arch/sparc/mm/init_64.c121
-rw-r--r--arch/sparc/mm/io-unit.c35
-rw-r--r--arch/sparc/mm/iommu.c71
-rw-r--r--arch/sparc/mm/leon_mm.c95
-rw-r--r--arch/sparc/mm/loadmmu.c43
-rw-r--r--arch/sparc/mm/nosun4c.c77
-rw-r--r--arch/sparc/mm/srmmu.c1232
-rw-r--r--arch/sparc/mm/srmmu.h4
-rw-r--r--arch/sparc/mm/sun4c.c2166
-rw-r--r--arch/sparc/mm/viking.S1
-rw-r--r--arch/sparc/prom/Makefile1
-rw-r--r--arch/sparc/prom/segment.c28
-rw-r--r--arch/tile/Kconfig1
-rw-r--r--arch/tile/include/asm/processor.h3
-rw-r--r--arch/tile/include/asm/thread_info.h6
-rw-r--r--arch/tile/include/asm/topology.h26
-rw-r--r--arch/tile/kernel/Makefile2
-rw-r--r--arch/tile/kernel/init_task.c59
-rw-r--r--arch/tile/kernel/process.c23
-rw-r--r--arch/tile/kernel/setup.c16
-rw-r--r--arch/tile/kernel/smpboot.c2
-rw-r--r--arch/um/Kconfig.common5
-rw-r--r--arch/um/defconfig1
-rw-r--r--arch/um/drivers/chan_kern.c9
-rw-r--r--arch/um/drivers/line.c2
-rw-r--r--arch/um/drivers/mconsole_kern.c1
-rw-r--r--arch/um/drivers/net_kern.c4
-rw-r--r--arch/um/drivers/port_kern.c2
-rw-r--r--arch/um/drivers/xterm_kern.c2
-rw-r--r--arch/um/include/asm/pgtable.h10
-rw-r--r--arch/um/include/asm/processor-generic.h7
-rw-r--r--arch/um/include/asm/thread_info.h2
-rw-r--r--arch/um/include/shared/irq_kern.h2
-rw-r--r--arch/um/kernel/Makefile2
-rw-r--r--arch/um/kernel/init_task.c38
-rw-r--r--arch/um/kernel/irq.c9
-rw-r--r--arch/um/kernel/process.c10
-rw-r--r--arch/um/kernel/signal.c14
-rw-r--r--arch/um/kernel/skas/syscall.c2
-rw-r--r--arch/um/kernel/smp.c2
-rw-r--r--arch/um/kernel/tlb.c1
-rw-r--r--arch/um/kernel/um_arch.c5
-rw-r--r--arch/um/os-Linux/skas/mem.c10
-rw-r--r--arch/unicore32/Makefile1
-rw-r--r--arch/unicore32/include/asm/processor.h3
-rw-r--r--arch/unicore32/kernel/Makefile2
-rw-r--r--arch/unicore32/kernel/init_task.c44
-rw-r--r--arch/x86/Kconfig48
-rw-r--r--arch/x86/Makefile10
-rw-r--r--arch/x86/boot/compressed/Makefile9
-rw-r--r--arch/x86/boot/compressed/eboot.c14
-rw-r--r--arch/x86/boot/header.S26
-rw-r--r--arch/x86/boot/main.c18
-rw-r--r--arch/x86/boot/tools/build.c24
-rw-r--r--arch/x86/crypto/aesni-intel_glue.c793
-rw-r--r--arch/x86/ia32/ia32_signal.c4
-rw-r--r--arch/x86/ia32/ia32entry.S9
-rw-r--r--arch/x86/ia32/sys_ia32.c23
-rw-r--r--arch/x86/include/asm/apic.h23
-rw-r--r--arch/x86/include/asm/apicdef.h2
-rw-r--r--arch/x86/include/asm/asm.h38
-rw-r--r--arch/x86/include/asm/atomic64_32.h10
-rw-r--r--arch/x86/include/asm/boot.h2
-rw-r--r--arch/x86/include/asm/bootparam.h3
-rw-r--r--arch/x86/include/asm/compat.h2
-rw-r--r--arch/x86/include/asm/current.h2
-rw-r--r--arch/x86/include/asm/desc.h1
-rw-r--r--arch/x86/include/asm/device.h4
-rw-r--r--arch/x86/include/asm/dma-mapping.h9
-rw-r--r--arch/x86/include/asm/fpu-internal.h6
-rw-r--r--arch/x86/include/asm/ftrace.h3
-rw-r--r--arch/x86/include/asm/hardirq.h9
-rw-r--r--arch/x86/include/asm/ia32.h6
-rw-r--r--arch/x86/include/asm/io_apic.h35
-rw-r--r--arch/x86/include/asm/irq_regs.h4
-rw-r--r--arch/x86/include/asm/irq_remapping.h118
-rw-r--r--arch/x86/include/asm/kbdleds.h17
-rw-r--r--arch/x86/include/asm/kdebug.h1
-rw-r--r--arch/x86/include/asm/kvm_host.h5
-rw-r--r--arch/x86/include/asm/kvm_para.h3
-rw-r--r--arch/x86/include/asm/mmu_context.h12
-rw-r--r--arch/x86/include/asm/mmzone_32.h6
-rw-r--r--arch/x86/include/asm/msr-index.h5
-rw-r--r--arch/x86/include/asm/msr.h9
-rw-r--r--arch/x86/include/asm/nmi.h22
-rw-r--r--arch/x86/include/asm/nops.h4
-rw-r--r--arch/x86/include/asm/page_32_types.h4
-rw-r--r--arch/x86/include/asm/page_64_types.h4
-rw-r--r--arch/x86/include/asm/paravirt.h6
-rw-r--r--arch/x86/include/asm/percpu.h24
-rw-r--r--arch/x86/include/asm/perf_event.h12
-rw-r--r--arch/x86/include/asm/processor.h5
-rw-r--r--arch/x86/include/asm/segment.h4
-rw-r--r--arch/x86/include/asm/smp.h15
-rw-r--r--arch/x86/include/asm/spinlock.h2
-rw-r--r--arch/x86/include/asm/stackprotector.h4
-rw-r--r--arch/x86/include/asm/stat.h21
-rw-r--r--arch/x86/include/asm/syscall.h27
-rw-r--r--arch/x86/include/asm/thread_info.h23
-rw-r--r--arch/x86/include/asm/tlbflush.h10
-rw-r--r--arch/x86/include/asm/topology.h38
-rw-r--r--arch/x86/include/asm/uaccess.h25
-rw-r--r--arch/x86/include/asm/x86_init.h9
-rw-r--r--arch/x86/include/asm/xor_32.h6
-rw-r--r--arch/x86/include/asm/xor_64.h8
-rw-r--r--arch/x86/include/asm/xor_avx.h214
-rw-r--r--arch/x86/include/asm/xsave.h10
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/acpi/boot.c2
-rw-r--r--arch/x86/kernel/apic/apic.c42
-rw-r--r--arch/x86/kernel/apic/apic_flat_64.c2
-rw-r--r--arch/x86/kernel/apic/apic_noop.c1
-rw-r--r--arch/x86/kernel/apic/apic_numachip.c1
-rw-r--r--arch/x86/kernel/apic/bigsmp_32.c1
-rw-r--r--arch/x86/kernel/apic/es7000_32.c2
-rw-r--r--arch/x86/kernel/apic/io_apic.c383
-rw-r--r--arch/x86/kernel/apic/numaq_32.c1
-rw-r--r--arch/x86/kernel/apic/probe_32.c1
-rw-r--r--arch/x86/kernel/apic/summit_32.c1
-rw-r--r--arch/x86/kernel/apic/x2apic_cluster.c1
-rw-r--r--arch/x86/kernel/apic/x2apic_phys.c1
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c1
-rw-r--r--arch/x86/kernel/apm_32.c2
-rw-r--r--arch/x86/kernel/check.c20
-rw-r--r--arch/x86/kernel/cpu/common.c2
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c4
-rw-r--r--arch/x86/kernel/cpu/match.c2
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c55
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c65
-rw-r--r--arch/x86/kernel/cpu/perf_event.c7
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd.c22
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd_ibs.c570
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c4
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c6
-rw-r--r--arch/x86/kernel/cpu/perf_event_p4.c6
-rw-r--r--arch/x86/kernel/dumpstack.c23
-rw-r--r--arch/x86/kernel/dumpstack_32.c2
-rw-r--r--arch/x86/kernel/dumpstack_64.c2
-rw-r--r--arch/x86/kernel/entry_32.S47
-rw-r--r--arch/x86/kernel/entry_64.S16
-rw-r--r--arch/x86/kernel/ftrace.c500
-rw-r--r--arch/x86/kernel/head_32.S223
-rw-r--r--arch/x86/kernel/head_64.S80
-rw-r--r--arch/x86/kernel/i387.c2
-rw-r--r--arch/x86/kernel/init_task.c42
-rw-r--r--arch/x86/kernel/irq_32.c8
-rw-r--r--arch/x86/kernel/kprobes.c4
-rw-r--r--arch/x86/kernel/microcode_core.c9
-rw-r--r--arch/x86/kernel/microcode_intel.c14
-rw-r--r--arch/x86/kernel/nmi.c95
-rw-r--r--arch/x86/kernel/nmi_selftest.c13
-rw-r--r--arch/x86/kernel/paravirt.c12
-rw-r--r--arch/x86/kernel/pci-calgary_64.c8
-rw-r--r--arch/x86/kernel/process.c73
-rw-r--r--arch/x86/kernel/process_32.c11
-rw-r--r--arch/x86/kernel/process_64.c19
-rw-r--r--arch/x86/kernel/ptrace.c7
-rw-r--r--arch/x86/kernel/reboot.c277
-rw-r--r--arch/x86/kernel/setup.c10
-rw-r--r--arch/x86/kernel/smp.c100
-rw-r--r--arch/x86/kernel/smpboot.c191
-rw-r--r--arch/x86/kernel/test_rodata.c10
-rw-r--r--arch/x86/kernel/traps.c8
-rw-r--r--arch/x86/kernel/vsmp_64.c40
-rw-r--r--arch/x86/kernel/x86_init.c8
-rw-r--r--arch/x86/kernel/xsave.c2
-rw-r--r--arch/x86/lib/checksum_32.S9
-rw-r--r--arch/x86/lib/copy_user_64.S63
-rw-r--r--arch/x86/lib/copy_user_nocache_64.S50
-rw-r--r--arch/x86/lib/csum-copy_64.S16
-rw-r--r--arch/x86/lib/getuser.S9
-rw-r--r--arch/x86/lib/putuser.S12
-rw-r--r--arch/x86/lib/usercopy.c20
-rw-r--r--arch/x86/lib/usercopy_32.c232
-rw-r--r--arch/x86/mm/extable.c142
-rw-r--r--arch/x86/mm/init.c21
-rw-r--r--arch/x86/mm/init_64.c23
-rw-r--r--arch/x86/mm/numa_emulation.c8
-rw-r--r--arch/x86/mm/tlb.c16
-rw-r--r--arch/x86/pci/Makefile2
-rw-r--r--arch/x86/pci/acpi.c128
-rw-r--r--arch/x86/pci/amd_bus.c91
-rw-r--r--arch/x86/pci/broadcom_bus.c12
-rw-r--r--arch/x86/pci/bus_numa.c69
-rw-r--r--arch/x86/pci/bus_numa.h18
-rw-r--r--arch/x86/pci/common.c43
-rw-r--r--arch/x86/pci/fixup.c17
-rw-r--r--arch/x86/pci/i386.c2
-rw-r--r--arch/x86/pci/sta2x11-fixup.c366
-rw-r--r--arch/x86/platform/olpc/olpc-xo1-sci.c43
-rw-r--r--arch/x86/platform/visws/visws_quirks.c2
-rw-r--r--arch/x86/tools/.gitignore1
-rw-r--r--arch/x86/tools/Makefile4
-rw-r--r--arch/x86/tools/relocs.c (renamed from arch/x86/boot/compressed/relocs.c)242
-rw-r--r--arch/x86/um/asm/elf.h42
-rw-r--r--arch/x86/um/asm/ptrace.h34
-rw-r--r--arch/x86/um/asm/ptrace_32.h23
-rw-r--r--arch/x86/um/asm/ptrace_64.h26
-rw-r--r--arch/x86/um/checksum_32.S9
-rw-r--r--arch/x86/um/shared/sysdep/ptrace.h67
-rw-r--r--arch/x86/um/shared/sysdep/ptrace_32.h92
-rw-r--r--arch/x86/um/shared/sysdep/ptrace_64.h101
-rw-r--r--arch/x86/um/signal.c29
-rw-r--r--arch/x86/um/sys_call_table_64.c1
-rw-r--r--arch/x86/um/syscalls_32.c12
-rw-r--r--arch/x86/um/sysrq_32.c8
-rw-r--r--arch/x86/um/sysrq_64.c8
-rw-r--r--arch/x86/um/tls_32.c2
-rw-r--r--arch/x86/xen/Makefile2
-rw-r--r--arch/x86/xen/apic.c33
-rw-r--r--arch/x86/xen/enlighten.c2
-rw-r--r--arch/x86/xen/mmu.c4
-rw-r--r--arch/x86/xen/smp.c19
-rw-r--r--arch/x86/xen/xen-asm_32.S6
-rw-r--r--arch/x86/xen/xen-ops.h4
-rw-r--r--arch/xtensa/include/asm/processor.h3
-rw-r--r--arch/xtensa/kernel/Makefile2
-rw-r--r--arch/xtensa/kernel/init_task.c31
-rw-r--r--arch/xtensa/kernel/process.c9
-rw-r--r--arch/xtensa/variants/s6000/dmac.c2
-rw-r--r--arch/xtensa/variants/s6000/gpio.c4
-rw-r--r--arch/xtensa/variants/s6000/include/variant/dmac.h2
-rw-r--r--arch/xtensa/variants/s6000/irq.c4
-rw-r--r--block/blk-cgroup.c45
-rw-r--r--block/genhd.c10
-rw-r--r--block/partitions/ibm.c2
-rw-r--r--crypto/xor.c18
-rw-r--r--drivers/Kconfig8
-rw-r--r--drivers/Makefile4
-rw-r--r--drivers/acpi/bus.c4
-rw-r--r--drivers/acpi/glue.c2
-rw-r--r--drivers/acpi/pci_link.c12
-rw-r--r--drivers/acpi/power.c9
-rw-r--r--drivers/acpi/scan.c4
-rw-r--r--drivers/acpi/sleep.c8
-rw-r--r--drivers/acpi/utils.c30
-rw-r--r--drivers/amba/bus.c53
-rw-r--r--drivers/ata/Kconfig9
-rw-r--r--drivers/ata/Makefile1
-rw-r--r--drivers/ata/ata_generic.c2
-rw-r--r--drivers/ata/ata_piix.c36
-rw-r--r--drivers/ata/libata-core.c7
-rw-r--r--drivers/ata/libata-eh.c24
-rw-r--r--drivers/ata/pata_ep93xx.c1044
-rw-r--r--drivers/base/bus.c3
-rw-r--r--drivers/base/core.c58
-rw-r--r--drivers/base/cpu.c4
-rw-r--r--drivers/base/devres.c35
-rw-r--r--drivers/base/devtmpfs.c6
-rw-r--r--drivers/base/dma-buf.c12
-rw-r--r--drivers/base/driver.c2
-rw-r--r--drivers/base/power/domain.c176
-rw-r--r--drivers/base/power/domain_governor.c166
-rw-r--r--drivers/base/power/main.c10
-rw-r--r--drivers/base/power/qos.c19
-rw-r--r--drivers/base/power/runtime.c103
-rw-r--r--drivers/base/power/sysfs.c54
-rw-r--r--drivers/base/power/wakeup.c174
-rw-r--r--drivers/base/regmap/Kconfig4
-rw-r--r--drivers/base/regmap/Makefile1
-rw-r--r--drivers/base/regmap/internal.h26
-rw-r--r--drivers/base/regmap/regcache-lzo.c11
-rw-r--r--drivers/base/regmap/regcache-rbtree.c44
-rw-r--r--drivers/base/regmap/regcache.c34
-rw-r--r--drivers/base/regmap/regmap-debugfs.c18
-rw-r--r--drivers/base/regmap/regmap-i2c.c13
-rw-r--r--drivers/base/regmap/regmap-irq.c184
-rw-r--r--drivers/base/regmap/regmap-mmio.c224
-rw-r--r--drivers/base/regmap/regmap-spi.c13
-rw-r--r--drivers/base/regmap/regmap.c276
-rw-r--r--drivers/bcma/scan.c19
-rw-r--r--drivers/block/DAC960.c23
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c4
-rw-r--r--drivers/block/virtio_blk.c21
-rw-r--r--drivers/bluetooth/ath3k.c1
-rw-r--r--drivers/bluetooth/bcm203x.c1
-rw-r--r--drivers/bluetooth/bfusb.c1
-rw-r--r--drivers/bluetooth/bpa10x.c1
-rw-r--r--drivers/bluetooth/btusb.c1
-rw-r--r--drivers/char/Kconfig8
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/hw_random/Kconfig17
-rw-r--r--drivers/char/hw_random/Makefile1
-rw-r--r--drivers/char/hw_random/omap-rng.c22
-rw-r--r--drivers/char/hw_random/pseries-rng.c96
-rw-r--r--drivers/char/mem.c42
-rw-r--r--drivers/char/ramoops.c250
-rw-r--r--drivers/char/virtio_console.c7
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c30
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.h2
-rw-r--r--drivers/clk/clkdev.c142
-rw-r--r--drivers/clocksource/Kconfig2
-rw-r--r--drivers/cpufreq/db8500-cpufreq.c2
-rw-r--r--drivers/cpuidle/cpuidle.c13
-rw-r--r--drivers/crypto/Kconfig30
-rw-r--r--drivers/crypto/Makefile1
-rw-r--r--drivers/crypto/amcc/crypto4xx_core.c2
-rw-r--r--drivers/crypto/caam/caamalg.c14
-rw-r--r--drivers/crypto/caam/ctrl.c16
-rw-r--r--drivers/crypto/nx/Makefile11
-rw-r--r--drivers/crypto/nx/nx-aes-cbc.c141
-rw-r--r--drivers/crypto/nx/nx-aes-ccm.c468
-rw-r--r--drivers/crypto/nx/nx-aes-ctr.c178
-rw-r--r--drivers/crypto/nx/nx-aes-ecb.c139
-rw-r--r--drivers/crypto/nx/nx-aes-gcm.c353
-rw-r--r--drivers/crypto/nx/nx-aes-xcbc.c236
-rw-r--r--drivers/crypto/nx/nx-sha256.c246
-rw-r--r--drivers/crypto/nx/nx-sha512.c265
-rw-r--r--drivers/crypto/nx/nx.c716
-rw-r--r--drivers/crypto/nx/nx.h193
-rw-r--r--drivers/crypto/nx/nx_csbcpb.h205
-rw-r--r--drivers/crypto/nx/nx_debugfs.c103
-rw-r--r--drivers/crypto/ux500/Kconfig30
-rw-r--r--drivers/crypto/ux500/Makefile8
-rw-r--r--drivers/crypto/ux500/cryp/Makefile13
-rw-r--r--drivers/crypto/ux500/cryp/cryp.c389
-rw-r--r--drivers/crypto/ux500/cryp/cryp.h308
-rw-r--r--drivers/crypto/ux500/cryp/cryp_core.c1784
-rw-r--r--drivers/crypto/ux500/cryp/cryp_irq.c45
-rw-r--r--drivers/crypto/ux500/cryp/cryp_irq.h31
-rw-r--r--drivers/crypto/ux500/cryp/cryp_irqp.h125
-rw-r--r--drivers/crypto/ux500/cryp/cryp_p.h123
-rw-r--r--drivers/crypto/ux500/hash/Makefile11
-rw-r--r--drivers/crypto/ux500/hash/hash_alg.h395
-rw-r--r--drivers/crypto/ux500/hash/hash_core.c2009
-rw-r--r--drivers/devfreq/Kconfig2
-rw-r--r--drivers/devfreq/governor_performance.c7
-rw-r--r--drivers/devfreq/governor_powersave.c7
-rw-r--r--drivers/dma/at_hdmac.c4
-rw-r--r--drivers/dma/ep93xx_dma.c4
-rw-r--r--drivers/dma/pl330.c3
-rw-r--r--drivers/edac/edac_core.h4
-rw-r--r--drivers/edac/edac_device.c8
-rw-r--r--drivers/edac/i7core_edac.c10
-rw-r--r--drivers/edac/sb_edac.c6
-rw-r--r--drivers/extcon/Kconfig32
-rw-r--r--drivers/extcon/Makefile7
-rw-r--r--drivers/extcon/extcon-max8997.c (renamed from drivers/misc/max8997-muic.c)206
-rw-r--r--drivers/extcon/extcon_class.c832
-rw-r--r--drivers/extcon/extcon_gpio.c169
-rw-r--r--drivers/firewire/core-card.c1
-rw-r--r--drivers/firewire/core-transaction.c9
-rw-r--r--drivers/firewire/core.h15
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/devres.c3
-rw-r--r--drivers/gpio/gpio-em.c418
-rw-r--r--drivers/gpio/gpio-pxa.c116
-rw-r--r--drivers/gpio/gpio-tegra.c39
-rw-r--r--drivers/gpu/drm/radeon/radeon_cp.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_gart.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_gem.c2
-rw-r--r--drivers/hid/Kconfig36
-rw-r--r--drivers/hid/Makefile3
-rw-r--r--drivers/hid/hid-apple.c5
-rw-r--r--drivers/hid/hid-aureal.c54
-rw-r--r--drivers/hid/hid-core.c316
-rw-r--r--drivers/hid/hid-generic.c53
-rw-r--r--drivers/hid/hid-hyperv.c15
-rw-r--r--drivers/hid/hid-ids.h8
-rw-r--r--drivers/hid/hid-input.c36
-rw-r--r--drivers/hid/hid-lg.c55
-rw-r--r--drivers/hid/hid-lg.h5
-rw-r--r--drivers/hid/hid-lg4ff.c258
-rw-r--r--drivers/hid/hid-logitech-dj.c76
-rw-r--r--drivers/hid/hid-multitouch.c233
-rw-r--r--drivers/hid/hid-uclogic.c141
-rw-r--r--drivers/hid/hid-wacom.c302
-rw-r--r--drivers/hid/hid-waltop.c230
-rw-r--r--drivers/hid/hid-wiimote-core.c16
-rw-r--r--drivers/hid/hidraw.c19
-rw-r--r--drivers/hid/usbhid/hid-core.c146
-rw-r--r--drivers/hid/usbhid/hid-quirks.c1
-rw-r--r--drivers/hid/usbhid/hiddev.c9
-rw-r--r--drivers/hid/usbhid/usbhid.h1
-rw-r--r--drivers/hid/usbhid/usbmouse.c7
-rw-r--r--drivers/hv/channel_mgmt.c73
-rw-r--r--drivers/hv/hv.c2
-rw-r--r--drivers/hv/hv_kvp.c3
-rw-r--r--drivers/hv/hv_util.c9
-rw-r--r--drivers/hv/hyperv_vmbus.h2
-rw-r--r--drivers/hwmon/Kconfig15
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/acpi_power_meter.c166
-rw-r--r--drivers/hwmon/ad7314.c11
-rw-r--r--drivers/hwmon/fam15h_power.c13
-rw-r--r--drivers/hwmon/ina2xx.c368
-rw-r--r--drivers/hwmon/it87.c384
-rw-r--r--drivers/hwmon/k10temp.c13
-rw-r--r--drivers/hwmon/k8temp.c13
-rw-r--r--drivers/hwmon/ntc_thermistor.c191
-rw-r--r--drivers/i2c/busses/Kconfig2
-rw-r--r--drivers/i2c/busses/i2c-imx.c8
-rw-r--r--drivers/i2c/busses/i2c-mxs.c6
-rw-r--r--drivers/i2c/busses/i2c-pnx.c157
-rw-r--r--drivers/i2c/busses/i2c-powermac.c98
-rw-r--r--drivers/i2c/busses/i2c-s6000.c2
-rw-r--r--drivers/i2c/busses/i2c-s6000.h2
-rw-r--r--drivers/iio/Kconfig54
-rw-r--r--drivers/iio/Makefile13
-rw-r--r--drivers/iio/adc/Kconfig16
-rw-r--r--drivers/iio/adc/Makefile5
-rw-r--r--drivers/iio/adc/at91_adc.c802
-rw-r--r--drivers/iio/amplifiers/Kconfig17
-rw-r--r--drivers/iio/amplifiers/Makefile5
-rw-r--r--drivers/iio/amplifiers/ad8366.c222
-rw-r--r--drivers/iio/iio_core.h (renamed from drivers/staging/iio/iio_core.h)6
-rw-r--r--drivers/iio/iio_core_trigger.h (renamed from drivers/staging/iio/iio_core_trigger.h)0
-rw-r--r--drivers/iio/industrialio-buffer.c (renamed from drivers/staging/iio/industrialio-buffer.c)91
-rw-r--r--drivers/iio/industrialio-core.c (renamed from drivers/staging/iio/industrialio-core.c)94
-rw-r--r--drivers/iio/industrialio-event.c (renamed from drivers/staging/iio/industrialio-event.c)14
-rw-r--r--drivers/iio/industrialio-trigger.c (renamed from drivers/staging/iio/industrialio-trigger.c)24
-rw-r--r--drivers/iio/inkern.c (renamed from drivers/staging/iio/inkern.c)8
-rw-r--r--drivers/iio/kfifo_buf.c (renamed from drivers/staging/iio/kfifo_buf.c)3
-rw-r--r--drivers/infiniband/Kconfig1
-rw-r--r--drivers/infiniband/Makefile1
-rw-r--r--drivers/infiniband/core/cma.c42
-rw-r--r--drivers/infiniband/core/umem.c2
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c108
-rw-r--r--drivers/infiniband/core/verbs.c15
-rw-r--r--drivers/infiniband/hw/cxgb4/Makefile2
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c36
-rw-r--r--drivers/infiniband/hw/cxgb4/device.c340
-rw-r--r--drivers/infiniband/hw/cxgb4/ev.c8
-rw-r--r--drivers/infiniband/hw/cxgb4/id_table.c112
-rw-r--r--drivers/infiniband/hw/cxgb4/iw_cxgb4.h134
-rw-r--r--drivers/infiniband/hw/cxgb4/mem.c21
-rw-r--r--drivers/infiniband/hw/cxgb4/provider.c19
-rw-r--r--drivers/infiniband/hw/cxgb4/qp.c105
-rw-r--r--drivers/infiniband/hw/cxgb4/resource.c180
-rw-r--r--drivers/infiniband/hw/cxgb4/t4.h24
-rw-r--r--drivers/infiniband/hw/cxgb4/user.h2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_iba6110.c3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c3
-rw-r--r--drivers/infiniband/hw/mlx4/cq.c13
-rw-r--r--drivers/infiniband/hw/mlx4/main.c104
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h2
-rw-r--r--drivers/infiniband/hw/mlx4/mr.c2
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c54
-rw-r--r--drivers/infiniband/hw/mlx4/srq.c2
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c7
-rw-r--r--drivers/infiniband/hw/ocrdma/Kconfig8
-rw-r--r--drivers/infiniband/hw/ocrdma/Makefile5
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma.h393
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_abi.h134
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_ah.c172
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_ah.h42
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_hw.c2640
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_hw.h132
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_main.c577
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_sli.h1672
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_verbs.c2537
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_verbs.h94
-rw-r--r--drivers/infiniband/hw/qib/qib.h35
-rw-r--r--drivers/infiniband/hw/qib/qib_driver.c5
-rw-r--r--drivers/infiniband/hw/qib/qib_iba6120.c1
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7220.c1
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7322.c3
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c3
-rw-r--r--drivers/infiniband/hw/qib/qib_mad.c63
-rw-r--r--drivers/infiniband/hw/qib/qib_qp.c7
-rw-r--r--drivers/infiniband/hw/qib/qib_rc.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_ruc.c12
-rw-r--r--drivers/infiniband/hw/qib/qib_sysfs.c7
-rw-r--r--drivers/infiniband/hw/qib/qib_tx.c25
-rw-r--r--drivers/infiniband/hw/qib/qib_uc.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_ud.c16
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs.h145
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c5
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c3
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.c10
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c3
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c16
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c18
-rw-r--r--drivers/input/joystick/iforce/iforce.h1
-rw-r--r--drivers/input/joystick/xpad.c35
-rw-r--r--drivers/input/misc/cm109.c33
-rw-r--r--drivers/input/misc/keyspan_remote.c23
-rw-r--r--drivers/input/misc/powermate.c13
-rw-r--r--drivers/input/misc/yealink.c31
-rw-r--r--drivers/input/mouse/appletouch.c59
-rw-r--r--drivers/input/mouse/bcm5974.c24
-rw-r--r--drivers/input/tablet/acecad.c15
-rw-r--r--drivers/input/tablet/aiptek.c28
-rw-r--r--drivers/input/tablet/gtco.c110
-rw-r--r--drivers/input/tablet/kbtab.c15
-rw-r--r--drivers/input/tablet/wacom_sys.c11
-rw-r--r--drivers/input/tablet/wacom_wac.c16
-rw-r--r--drivers/input/touchscreen/Kconfig4
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c77
-rw-r--r--drivers/iommu/Kconfig4
-rw-r--r--drivers/iommu/Makefile2
-rw-r--r--drivers/iommu/dmar.c11
-rw-r--r--drivers/iommu/intel-iommu.c3
-rw-r--r--drivers/iommu/intel_irq_remapping.c (renamed from drivers/iommu/intr_remapping.c)359
-rw-r--r--drivers/iommu/intr_remapping.h17
-rw-r--r--drivers/iommu/irq_remapping.c166
-rw-r--r--drivers/iommu/irq_remapping.h90
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c1
-rw-r--r--drivers/isdn/gigaset/usb-gigaset.c1
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c1
-rw-r--r--drivers/isdn/hisax/hfc_usb.c1
-rw-r--r--drivers/isdn/hisax/st5481_init.c1
-rw-r--r--drivers/isdn/i4l/isdn_common.c5
-rw-r--r--drivers/isdn/i4l/isdn_tty.c466
-rw-r--r--drivers/macintosh/Kconfig23
-rw-r--r--drivers/macintosh/Makefile14
-rw-r--r--drivers/macintosh/ams/ams-i2c.c2
-rw-r--r--drivers/macintosh/therm_adt746x.c480
-rw-r--r--drivers/macintosh/windfarm.h51
-rw-r--r--drivers/macintosh/windfarm_ad7417_sensor.c347
-rw-r--r--drivers/macintosh/windfarm_core.c23
-rw-r--r--drivers/macintosh/windfarm_cpufreq_clamp.c6
-rw-r--r--drivers/macintosh/windfarm_fcu_controls.c613
-rw-r--r--drivers/macintosh/windfarm_lm75_sensor.c135
-rw-r--r--drivers/macintosh/windfarm_lm87_sensor.c201
-rw-r--r--drivers/macintosh/windfarm_max6690_sensor.c109
-rw-r--r--drivers/macintosh/windfarm_mpu.h105
-rw-r--r--drivers/macintosh/windfarm_pm72.c847
-rw-r--r--drivers/macintosh/windfarm_pm81.c25
-rw-r--r--drivers/macintosh/windfarm_pm91.c33
-rw-r--r--drivers/macintosh/windfarm_rm31.c740
-rw-r--r--drivers/macintosh/windfarm_smu_controls.c1
-rw-r--r--drivers/macintosh/windfarm_smu_sat.c132
-rw-r--r--drivers/md/bitmap.c1100
-rw-r--r--drivers/md/bitmap.h60
-rw-r--r--drivers/md/dm-raid.c22
-rw-r--r--drivers/md/dm-thin.c32
-rw-r--r--drivers/md/md.c372
-rw-r--r--drivers/md/md.h12
-rw-r--r--drivers/md/raid1.c22
-rw-r--r--drivers/md/raid10.c1317
-rw-r--r--drivers/md/raid10.h34
-rw-r--r--drivers/md/raid5.c252
-rw-r--r--drivers/md/raid5.h7
-rw-r--r--drivers/media/video/gspca/ov534_9.c2
-rw-r--r--drivers/media/video/hdpvr/hdpvr-core.c4
-rw-r--r--drivers/memory/Kconfig43
-rw-r--r--drivers/memory/Makefile7
-rw-r--r--drivers/memory/emif.c1670
-rw-r--r--drivers/memory/emif.h589
-rw-r--r--drivers/memory/tegra20-mc.c257
-rw-r--r--drivers/memory/tegra30-mc.c382
-rw-r--r--drivers/mfd/Kconfig44
-rw-r--r--drivers/mfd/Makefile5
-rw-r--r--drivers/mfd/ab5500-core.c1439
-rw-r--r--drivers/mfd/ab5500-debugfs.c807
-rw-r--r--drivers/mfd/ab5500-debugfs.h22
-rw-r--r--drivers/mfd/da9052-core.c8
-rw-r--r--drivers/mfd/db5500-prcmu.c451
-rw-r--r--drivers/mfd/mc13xxx-core.c3
-rw-r--r--drivers/mfd/palmas.c509
-rw-r--r--drivers/mfd/tps65090.c11
-rw-r--r--drivers/mfd/tps6586x.c86
-rw-r--r--drivers/mfd/tps65911-comparator.c2
-rw-r--r--drivers/mfd/twl-core.c7
-rw-r--r--drivers/mfd/wm8994-irq.c6
-rw-r--r--drivers/misc/Kconfig35
-rw-r--r--drivers/misc/Makefile4
-rw-r--r--drivers/misc/ad525x_dpot.c2
-rw-r--r--drivers/misc/bh1780gli.c2
-rw-r--r--drivers/misc/bmp085-i2c.c91
-rw-r--r--drivers/misc/bmp085-spi.c91
-rw-r--r--drivers/misc/bmp085.c356
-rw-r--r--drivers/misc/bmp085.h (renamed from arch/arm/include/asm/hardware/ep7211.h)33
-rw-r--r--drivers/misc/c2port/Kconfig6
-rw-r--r--drivers/misc/eeprom/at25.c19
-rw-r--r--drivers/misc/mei/Kconfig (renamed from drivers/staging/mei/Kconfig)0
-rw-r--r--drivers/misc/mei/Makefile (renamed from drivers/staging/mei/Makefile)0
-rw-r--r--drivers/misc/mei/hw.h (renamed from drivers/staging/mei/hw.h)0
-rw-r--r--drivers/misc/mei/init.c (renamed from drivers/staging/mei/init.c)4
-rw-r--r--drivers/misc/mei/interface.c (renamed from drivers/staging/mei/interface.c)2
-rw-r--r--drivers/misc/mei/interface.h (renamed from drivers/staging/mei/interface.h)5
-rw-r--r--drivers/misc/mei/interrupt.c (renamed from drivers/staging/mei/interrupt.c)2
-rw-r--r--drivers/misc/mei/iorw.c (renamed from drivers/staging/mei/iorw.c)2
-rw-r--r--drivers/misc/mei/main.c (renamed from drivers/staging/mei/main.c)41
-rw-r--r--drivers/misc/mei/mei_dev.h (renamed from drivers/staging/mei/mei_dev.h)2
-rw-r--r--drivers/misc/mei/wd.c (renamed from drivers/staging/mei/wd.c)76
-rw-r--r--drivers/misc/pch_phub.c4
-rw-r--r--drivers/misc/pti.c2
-rw-r--r--drivers/mmc/host/mmci.c18
-rw-r--r--drivers/mmc/host/mxs-mmc.c8
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c9
-rw-r--r--drivers/mmc/host/sdhci-tegra.c24
-rw-r--r--drivers/mtd/devices/docg3.c16
-rw-r--r--drivers/mtd/nand/autcpu12.c10
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.c9
-rw-r--r--drivers/mtd/nand/h1910.c2
-rw-r--r--drivers/mtd/nand/orion_nand.c47
-rw-r--r--drivers/mtd/ubi/Kconfig8
-rw-r--r--drivers/mtd/ubi/Makefile5
-rw-r--r--drivers/mtd/ubi/attach.c (renamed from drivers/mtd/ubi/scan.c)970
-rw-r--r--drivers/mtd/ubi/build.c85
-rw-r--r--drivers/mtd/ubi/cdev.c36
-rw-r--r--drivers/mtd/ubi/debug.c137
-rw-r--r--drivers/mtd/ubi/debug.h98
-rw-r--r--drivers/mtd/ubi/eba.c68
-rw-r--r--drivers/mtd/ubi/gluebi.c2
-rw-r--r--drivers/mtd/ubi/io.c211
-rw-r--r--drivers/mtd/ubi/kapi.c61
-rw-r--r--drivers/mtd/ubi/scan.h174
-rw-r--r--drivers/mtd/ubi/ubi-media.h8
-rw-r--r--drivers/mtd/ubi/ubi.h179
-rw-r--r--drivers/mtd/ubi/upd.c16
-rw-r--r--drivers/mtd/ubi/vmt.c62
-rw-r--r--drivers/mtd/ubi/vtbl.c228
-rw-r--r--drivers/mtd/ubi/wl.c260
-rw-r--r--drivers/net/can/flexcan.c6
-rw-r--r--drivers/net/can/sja1000/Kconfig2
-rw-r--r--drivers/net/ethernet/3com/typhoon.c3
-rw-r--r--drivers/net/ethernet/amd/ariadne.c8
-rw-r--r--drivers/net/ethernet/amd/atarilance.c11
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c41
-rw-r--r--drivers/net/ethernet/broadcom/tg3.h2
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.c4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h23
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c235
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h11
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c22
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c62
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_regs.h53
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h15
-rw-r--r--drivers/net/ethernet/cirrus/cs89x0.c2221
-rw-r--r--drivers/net/ethernet/emulex/benet/Makefile2
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h40
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c95
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.h58
-rw-r--r--drivers/net/ethernet/emulex/benet/be_ethtool.c77
-rw-r--r--drivers/net/ethernet/emulex/benet/be_hw.h4
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c125
-rw-r--r--drivers/net/ethernet/emulex/benet/be_roce.c182
-rw-r--r--drivers/net/ethernet/emulex/benet/be_roce.h75
-rw-r--r--drivers/net/ethernet/freescale/fec.c9
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/alloc.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c29
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c2
-rw-r--r--drivers/net/ethernet/nxp/lpc_eth.c71
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c3
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c3
-rw-r--r--drivers/net/ethernet/realtek/r8169.c2
-rw-r--r--drivers/net/ethernet/s6gmac.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c4
-rw-r--r--drivers/net/ethernet/tehuti/tehuti.c4
-rw-r--r--drivers/net/irda/Kconfig6
-rw-r--r--drivers/net/irda/irda-usb.c2
-rw-r--r--drivers/net/irda/kingsun-sir.c42
-rw-r--r--drivers/net/irda/ks959-sir.c31
-rw-r--r--drivers/net/irda/ksdazzle-sir.c46
-rw-r--r--drivers/net/irda/stir4200.c6
-rw-r--r--drivers/net/ppp/ppp_async.c2
-rw-r--r--drivers/net/ppp/ppp_generic.c14
-rw-r--r--drivers/net/ppp/ppp_synctty.c4
-rw-r--r--drivers/net/ppp/pppoe.c6
-rw-r--r--drivers/net/ppp/pptp.c2
-rw-r--r--drivers/net/usb/asix.c1
-rw-r--r--drivers/net/usb/catc.c26
-rw-r--r--drivers/net/usb/cdc-phonet.c1
-rw-r--r--drivers/net/usb/cdc_eem.c1
-rw-r--r--drivers/net/usb/cdc_ether.c57
-rw-r--r--drivers/net/usb/cdc_ncm.c1
-rw-r--r--drivers/net/usb/cdc_subset.c1
-rw-r--r--drivers/net/usb/cx82310_eth.c1
-rw-r--r--drivers/net/usb/dm9601.c1
-rw-r--r--drivers/net/usb/gl620a.c1
-rw-r--r--drivers/net/usb/hso.c106
-rw-r--r--drivers/net/usb/int51x1.c1
-rw-r--r--drivers/net/usb/ipheth.c35
-rw-r--r--drivers/net/usb/kalmia.c3
-rw-r--r--drivers/net/usb/kaweth.c64
-rw-r--r--drivers/net/usb/lg-vl600.c1
-rw-r--r--drivers/net/usb/mcs7830.c1
-rw-r--r--drivers/net/usb/net1080.c1
-rw-r--r--drivers/net/usb/pegasus.c1
-rw-r--r--drivers/net/usb/plusb.c1
-rw-r--r--drivers/net/usb/qmi_wwan.c40
-rw-r--r--drivers/net/usb/rndis_host.c1
-rw-r--r--drivers/net/usb/rtl8150.c18
-rw-r--r--drivers/net/usb/sierra_net.c1
-rw-r--r--drivers/net/usb/smsc75xx.c1
-rw-r--r--drivers/net/usb/smsc95xx.c1
-rw-r--r--drivers/net/usb/zaurus.c1
-rw-r--r--drivers/net/virtio_net.c2
-rw-r--r--drivers/net/wan/Kconfig31
-rw-r--r--drivers/net/wan/Makefile5
-rw-r--r--drivers/net/wireless/at76c50x-usb.c3
-rw-r--r--drivers/net/wireless/ath/ath6kl/usb.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c1
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rx.c7
-rw-r--r--drivers/net/wireless/libertas/if_usb.c1
-rw-r--r--drivers/net/wireless/libertas_tf/if_usb.c1
-rw-r--r--drivers/net/wireless/orinoco/orinoco_usb.c1
-rw-r--r--drivers/net/wireless/p54/p54usb.c1
-rw-r--r--drivers/net/wireless/rndis_wlan.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c1
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/dev.c1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/sw.c1
-rw-r--r--drivers/net/wireless/zd1201.c1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c1
-rw-r--r--drivers/of/address.c1
-rw-r--r--drivers/of/base.c41
-rw-r--r--drivers/parisc/superio.c2
-rw-r--r--drivers/parport/parport_amiga.c36
-rw-r--r--drivers/parport/parport_atari.c9
-rw-r--r--drivers/parport/parport_mfc3.c35
-rw-r--r--drivers/parport/parport_pc.c292
-rw-r--r--drivers/parport/parport_sunbpp.c21
-rw-r--r--drivers/pci/Makefile2
-rw-r--r--drivers/pci/host-bridge.c96
-rw-r--r--drivers/pci/pci-acpi.c2
-rw-r--r--drivers/pci/pci-driver.c6
-rw-r--r--drivers/pci/pci.c30
-rw-r--r--drivers/pci/pcie/portdrv_core.c2
-rw-r--r--drivers/pci/probe.c154
-rw-r--r--drivers/pci/quirks.c58
-rw-r--r--drivers/pcmcia/Kconfig2
-rw-r--r--drivers/pcmcia/Makefile1
-rw-r--r--drivers/pcmcia/pxa2xx_hx4700.c121
-rw-r--r--drivers/pinctrl/Kconfig57
-rw-r--r--drivers/pinctrl/Makefile14
-rw-r--r--drivers/pinctrl/core.c244
-rw-r--r--drivers/pinctrl/core.h12
-rw-r--r--drivers/pinctrl/devicetree.c249
-rw-r--r--drivers/pinctrl/devicetree.h35
-rw-r--r--drivers/pinctrl/pinconf.c56
-rw-r--r--drivers/pinctrl/pinconf.h17
-rw-r--r--drivers/pinctrl/pinctrl-coh901.c4
-rw-r--r--drivers/pinctrl/pinctrl-imx.c620
-rw-r--r--drivers/pinctrl/pinctrl-imx.h106
-rw-r--r--drivers/pinctrl/pinctrl-imx23.c305
-rw-r--r--drivers/pinctrl/pinctrl-imx28.c421
-rw-r--r--drivers/pinctrl/pinctrl-imx51.c1322
-rw-r--r--drivers/pinctrl/pinctrl-imx53.c1649
-rw-r--r--drivers/pinctrl/pinctrl-imx6q.c2331
-rw-r--r--drivers/pinctrl/pinctrl-mxs.c528
-rw-r--r--drivers/pinctrl/pinctrl-mxs.h91
-rw-r--r--drivers/pinctrl/pinctrl-nomadik-db8500.c857
-rw-r--r--drivers/pinctrl/pinctrl-nomadik.c (renamed from drivers/gpio/gpio-nomadik.c)857
-rw-r--r--drivers/pinctrl/pinctrl-nomadik.h77
-rw-r--r--drivers/pinctrl/pinctrl-pxa3xx.c30
-rw-r--r--drivers/pinctrl/pinctrl-sirf.c20
-rw-r--r--drivers/pinctrl/pinctrl-tegra.c439
-rw-r--r--drivers/pinctrl/pinctrl-tegra.h23
-rw-r--r--drivers/pinctrl/pinctrl-tegra20.c40
-rw-r--r--drivers/pinctrl/pinctrl-tegra30.c40
-rw-r--r--drivers/pinctrl/pinctrl-u300.c20
-rw-r--r--drivers/pinctrl/pinmux.c97
-rw-r--r--drivers/pinctrl/pinmux.h18
-rw-r--r--drivers/pinctrl/spear/Kconfig34
-rw-r--r--drivers/pinctrl/spear/Makefile7
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear.c354
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear.h142
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear300.c708
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear310.c431
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear320.c3468
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear3xx.c588
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear3xx.h92
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c2
-rw-r--r--drivers/power/bq27x00_battery.c2
-rw-r--r--drivers/ps3/ps3av.c24
-rw-r--r--drivers/ptp/Kconfig2
-rw-r--r--drivers/regulator/88pm8607.c179
-rw-r--r--drivers/regulator/Kconfig33
-rw-r--r--drivers/regulator/Makefile5
-rw-r--r--drivers/regulator/aat2870-regulator.c10
-rw-r--r--drivers/regulator/ab3100.c65
-rw-r--r--drivers/regulator/ab8500.c235
-rw-r--r--drivers/regulator/ad5398.c19
-rw-r--r--drivers/regulator/anatop-regulator.c9
-rw-r--r--drivers/regulator/core.c456
-rw-r--r--drivers/regulator/da903x.c209
-rw-r--r--drivers/regulator/da9052-regulator.c441
-rw-r--r--drivers/regulator/db8500-prcmu.c133
-rw-r--r--drivers/regulator/dummy.c7
-rw-r--r--drivers/regulator/fixed.c69
-rw-r--r--drivers/regulator/gpio-regulator.c22
-rw-r--r--drivers/regulator/isl6271a-regulator.c73
-rw-r--r--drivers/regulator/lp3971.c87
-rw-r--r--drivers/regulator/lp3972.c74
-rw-r--r--drivers/regulator/max1586.c28
-rw-r--r--drivers/regulator/max8649.c110
-rw-r--r--drivers/regulator/max8660.c165
-rw-r--r--drivers/regulator/max8925-regulator.c83
-rw-r--r--drivers/regulator/max8952.c70
-rw-r--r--drivers/regulator/max8997.c342
-rw-r--r--drivers/regulator/max8998.c122
-rw-r--r--drivers/regulator/mc13783-regulator.c12
-rw-r--r--drivers/regulator/mc13892-regulator.c25
-rw-r--r--drivers/regulator/mc13xxx-regulator-core.c54
-rw-r--r--drivers/regulator/mc13xxx.h2
-rw-r--r--drivers/regulator/of_regulator.c47
-rw-r--r--drivers/regulator/palmas-regulator.c822
-rw-r--r--drivers/regulator/pcap-regulator.c54
-rw-r--r--drivers/regulator/pcf50633-regulator.c199
-rw-r--r--drivers/regulator/rc5t583-regulator.c255
-rw-r--r--drivers/regulator/s5m8767.c327
-rw-r--r--drivers/regulator/tps6105x-regulator.c11
-rw-r--r--drivers/regulator/tps62360-regulator.c380
-rw-r--r--drivers/regulator/tps65023-regulator.c244
-rw-r--r--drivers/regulator/tps6507x-regulator.c22
-rw-r--r--drivers/regulator/tps65090-regulator.c150
-rw-r--r--drivers/regulator/tps65217-regulator.c78
-rw-r--r--drivers/regulator/tps6524x-regulator.c47
-rw-r--r--drivers/regulator/tps6586x-regulator.c108
-rw-r--r--drivers/regulator/tps65910-regulator.c343
-rw-r--r--drivers/regulator/tps65912-regulator.c60
-rw-r--r--drivers/regulator/twl-regulator.c127
-rw-r--r--drivers/regulator/userspace-consumer.c20
-rw-r--r--drivers/regulator/virtual.c26
-rw-r--r--drivers/regulator/wm831x-dcdc.c174
-rw-r--r--drivers/regulator/wm831x-isink.c8
-rw-r--r--drivers/regulator/wm831x-ldo.c201
-rw-r--r--drivers/regulator/wm8350-regulator.c11
-rw-r--r--drivers/regulator/wm8400-regulator.c176
-rw-r--r--drivers/regulator/wm8994-regulator.c111
-rw-r--r--drivers/remoteproc/remoteproc_core.c3
-rw-r--r--drivers/rtc/Kconfig2
-rw-r--r--drivers/rtc/rtc-pl031.c18
-rw-r--r--drivers/s390/char/con3215.c142
-rw-r--r--drivers/s390/char/keyboard.c30
-rw-r--r--drivers/s390/char/keyboard.h14
-rw-r--r--drivers/s390/char/sclp_cmd.c12
-rw-r--r--drivers/s390/char/sclp_tty.c33
-rw-r--r--drivers/s390/char/sclp_vt220.c33
-rw-r--r--drivers/s390/char/tape.h43
-rw-r--r--drivers/s390/char/tape_34xx.c136
-rw-r--r--drivers/s390/char/tape_3590.c105
-rw-r--r--drivers/s390/char/tape_char.c13
-rw-r--r--drivers/s390/char/tape_core.c16
-rw-r--r--drivers/s390/char/tty3270.c121
-rw-r--r--drivers/s390/cio/ccwgroup.c112
-rw-r--r--drivers/s390/cio/cio.c73
-rw-r--r--drivers/s390/cio/device.c13
-rw-r--r--drivers/s390/cio/device.h1
-rw-r--r--drivers/s390/cio/qdio_main.c47
-rw-r--r--drivers/s390/crypto/ap_bus.c24
-rw-r--r--drivers/s390/crypto/ap_bus.h7
-rw-r--r--drivers/s390/crypto/zcrypt_cex2a.c3
-rw-r--r--drivers/s390/crypto/zcrypt_pcica.c3
-rw-r--r--drivers/s390/crypto/zcrypt_pcicc.c3
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.c5
-rw-r--r--drivers/s390/net/claw.c165
-rw-r--r--drivers/s390/net/ctcm_main.c52
-rw-r--r--drivers/s390/net/ctcm_main.h8
-rw-r--r--drivers/s390/net/ctcm_sysfs.c37
-rw-r--r--drivers/s390/net/lcs.c52
-rw-r--r--drivers/s390/net/qeth_core.h24
-rw-r--r--drivers/s390/net/qeth_core_main.c178
-rw-r--r--drivers/s390/net/qeth_core_sys.c49
-rw-r--r--drivers/s390/net/qeth_l2_main.c16
-rw-r--r--drivers/s390/net/qeth_l3_main.c16
-rw-r--r--drivers/scsi/Kconfig1
-rw-r--r--drivers/scsi/aacraid/src.c2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_seq.c3
-rw-r--r--drivers/scsi/atari_scsi.c26
-rw-r--r--drivers/scsi/atari_scsi.h5
-rw-r--r--drivers/scsi/be2iscsi/be.h4
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.c2
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.h154
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.c493
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.h15
-rw-r--r--drivers/scsi/be2iscsi/be_main.c447
-rw-r--r--drivers/scsi/be2iscsi/be_main.h17
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c522
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.h50
-rw-r--r--drivers/scsi/bfa/bfa_fcs.h3
-rw-r--r--drivers/scsi/bfa/bfa_fcs_lport.c32
-rw-r--r--drivers/scsi/bfa/bfad.c17
-rw-r--r--drivers/scsi/bfa/bfad_attr.c20
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_constants.h2
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_hsi.h2
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h2
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c2
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c6
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c3
-rw-r--r--drivers/scsi/bnx2i/bnx2i_sysfs.c2
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c70
-rw-r--r--drivers/scsi/esp_scsi.c2
-rw-r--r--drivers/scsi/fcoe/fcoe.c41
-rw-r--r--drivers/scsi/fcoe/fcoe.h4
-rw-r--r--drivers/scsi/fcoe/fcoe_ctlr.c8
-rw-r--r--drivers/scsi/hpsa.c683
-rw-r--r--drivers/scsi/hpsa.h85
-rw-r--r--drivers/scsi/hpsa_cmd.h37
-rw-r--r--drivers/scsi/isci/host.c703
-rw-r--r--drivers/scsi/isci/host.h124
-rw-r--r--drivers/scsi/isci/init.c212
-rw-r--r--drivers/scsi/isci/phy.c76
-rw-r--r--drivers/scsi/isci/phy.h9
-rw-r--r--drivers/scsi/isci/port.c68
-rw-r--r--drivers/scsi/isci/port.h11
-rw-r--r--drivers/scsi/isci/port_config.c18
-rw-r--r--drivers/scsi/isci/probe_roms.c12
-rw-r--r--drivers/scsi/isci/probe_roms.h2
-rw-r--r--drivers/scsi/isci/registers.h8
-rw-r--r--drivers/scsi/isci/remote_device.c576
-rw-r--r--drivers/scsi/isci/remote_device.h63
-rw-r--r--drivers/scsi/isci/remote_node_context.c393
-rw-r--r--drivers/scsi/isci/remote_node_context.h43
-rw-r--r--drivers/scsi/isci/request.c715
-rw-r--r--drivers/scsi/isci/request.h125
-rw-r--r--drivers/scsi/isci/scu_completion_codes.h2
-rw-r--r--drivers/scsi/isci/task.c800
-rw-r--r--drivers/scsi/isci/task.h132
-rw-r--r--drivers/scsi/isci/unsolicited_frame_control.c30
-rw-r--r--drivers/scsi/isci/unsolicited_frame_control.h6
-rw-r--r--drivers/scsi/libfc/fc_lport.c2
-rw-r--r--drivers/scsi/lpfc/lpfc.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h8
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c46
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.h418
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c141
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c18
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h18
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c377
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c9
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c414
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c785
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h17
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h6
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c21
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c4
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2.h7
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h68
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c38
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h10
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c312
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c597
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c243
-rw-r--r--drivers/scsi/pm8001/pm8001_defs.h3
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c23
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.h2
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c10
-rw-r--r--drivers/scsi/qla1280.c7
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c3
-rw-r--r--drivers/scsi/scsi.c6
-rw-r--r--drivers/scsi/scsi_error.c6
-rw-r--r--drivers/scsi/scsi_lib.c10
-rw-r--r--drivers/scsi/scsi_pm.c2
-rw-r--r--drivers/scsi/scsi_priv.h2
-rw-r--r--drivers/scsi/scsi_transport_fc.c24
-rw-r--r--drivers/scsi/scsi_transport_spi.c4
-rw-r--r--drivers/scsi/sd.c5
-rw-r--r--drivers/scsi/sg.c183
-rw-r--r--drivers/scsi/st.h2
-rw-r--r--drivers/scsi/storvsc_drv.c20
-rw-r--r--drivers/scsi/ufs/ufshcd.c8
-rw-r--r--drivers/sh/clk/cpg.c77
-rw-r--r--drivers/sh/intc/dynamic.c8
-rw-r--r--drivers/spi/spi-imx.c8
-rw-r--r--drivers/staging/Kconfig16
-rw-r--r--drivers/staging/Makefile7
-rw-r--r--drivers/staging/android/Kconfig33
-rw-r--r--drivers/staging/android/Makefile3
-rw-r--r--drivers/staging/android/alarm-dev.c137
-rw-r--r--drivers/staging/android/alarm.c601
-rw-r--r--drivers/staging/android/android_alarm.h59
-rw-r--r--drivers/staging/android/binder.h10
-rw-r--r--drivers/staging/android/logger.c113
-rw-r--r--drivers/staging/android/ram_console.c2
-rw-r--r--drivers/staging/android/switch/Kconfig11
-rw-r--r--drivers/staging/android/switch/Makefile4
-rw-r--r--drivers/staging/android/switch/switch.h53
-rw-r--r--drivers/staging/android/switch/switch_class.c174
-rw-r--r--drivers/staging/android/switch/switch_gpio.c172
-rw-r--r--drivers/staging/android/timed_output.c1
-rw-r--r--drivers/staging/asus_oled/asus_oled.c6
-rw-r--r--drivers/staging/bcm/Adapter.h883
-rw-r--r--drivers/staging/bcm/DDRInit.c26
-rw-r--r--drivers/staging/bcm/IPv6Protocol.c409
-rw-r--r--drivers/staging/bcm/Misc.c2
-rw-r--r--drivers/staging/ccg/Kconfig20
-rw-r--r--drivers/staging/ccg/Makefile4
-rw-r--r--drivers/staging/ccg/TODO6
-rw-r--r--drivers/staging/ccg/ccg.c1299
-rw-r--r--drivers/staging/ccg/sysfs-class-ccg_usb158
-rw-r--r--drivers/staging/comedi/Kconfig253
-rw-r--r--drivers/staging/comedi/comedi.h2
-rw-r--r--drivers/staging/comedi/comedi_fops.c729
-rw-r--r--drivers/staging/comedi/comedidev.h72
-rw-r--r--drivers/staging/comedi/drivers.c326
-rw-r--r--drivers/staging/comedi/drivers/8255.c73
-rw-r--r--drivers/staging/comedi/drivers/acl7225b.c55
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c3556
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.h145
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c18
-rw-r--r--drivers/staging/comedi/drivers/adl_pci6208.c263
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7230.c133
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7296.c77
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7432.c149
-rw-r--r--drivers/staging/comedi/drivers/adl_pci8164.c301
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9111.c106
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9118.c182
-rw-r--r--drivers/staging/comedi/drivers/adq12b.c250
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1710.c223
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1723.c103
-rw-r--r--drivers/staging/comedi/drivers/adv_pci_dio.c130
-rw-r--r--drivers/staging/comedi/drivers/aio_aio12_8.c33
-rw-r--r--drivers/staging/comedi/drivers/aio_iiro_16.c113
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200.c99
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc236.c85
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc263.c87
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci224.c256
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci230.c120
-rw-r--r--drivers/staging/comedi/drivers/c6xdigio.c44
-rw-r--r--drivers/staging/comedi/drivers/cb_das16_cs.c9
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas.c109
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas64.c142
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidda.c175
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidio.c131
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdas.c123
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdda.c132
-rw-r--r--drivers/staging/comedi/drivers/comedi_bond.c216
-rw-r--r--drivers/staging/comedi/drivers/comedi_parport.c38
-rw-r--r--drivers/staging/comedi/drivers/comedi_test.c373
-rw-r--r--drivers/staging/comedi/drivers/contec_pci_dio.c163
-rw-r--r--drivers/staging/comedi/drivers/daqboard2000.c87
-rw-r--r--drivers/staging/comedi/drivers/das08.c132
-rw-r--r--drivers/staging/comedi/drivers/das08.h2
-rw-r--r--drivers/staging/comedi/drivers/das16.c891
-rw-r--r--drivers/staging/comedi/drivers/das16m1.c219
-rw-r--r--drivers/staging/comedi/drivers/das1800.c61
-rw-r--r--drivers/staging/comedi/drivers/das6402.c68
-rw-r--r--drivers/staging/comedi/drivers/das800.c8
-rw-r--r--drivers/staging/comedi/drivers/dmm32at.c15
-rw-r--r--drivers/staging/comedi/drivers/dt2801.c283
-rw-r--r--drivers/staging/comedi/drivers/dt2811.c309
-rw-r--r--drivers/staging/comedi/drivers/dt2814.c116
-rw-r--r--drivers/staging/comedi/drivers/dt2815.c42
-rw-r--r--drivers/staging/comedi/drivers/dt2817.c37
-rw-r--r--drivers/staging/comedi/drivers/dt282x.c397
-rw-r--r--drivers/staging/comedi/drivers/dt3000.c234
-rw-r--r--drivers/staging/comedi/drivers/dt9812.c43
-rw-r--r--drivers/staging/comedi/drivers/dyna_pci10xx.c79
-rw-r--r--drivers/staging/comedi/drivers/fl512.c47
-rw-r--r--drivers/staging/comedi/drivers/gsc_hpdi.c98
-rw-r--r--drivers/staging/comedi/drivers/icp_multi.c289
-rw-r--r--drivers/staging/comedi/drivers/ii_pci20kc.c36
-rw-r--r--drivers/staging/comedi/drivers/jr3_pci.c84
-rw-r--r--drivers/staging/comedi/drivers/ke_counter.c98
-rw-r--r--drivers/staging/comedi/drivers/me4000.c432
-rw-r--r--drivers/staging/comedi/drivers/me_daq.c101
-rw-r--r--drivers/staging/comedi/drivers/mite.h4
-rw-r--r--drivers/staging/comedi/drivers/mpc624.c236
-rw-r--r--drivers/staging/comedi/drivers/mpc8260cpm.c114
-rw-r--r--drivers/staging/comedi/drivers/multiq3.c37
-rw-r--r--drivers/staging/comedi/drivers/ni_6527.c10
-rw-r--r--drivers/staging/comedi/drivers/ni_65xx.c9
-rw-r--r--drivers/staging/comedi/drivers/ni_660x.c15
-rw-r--r--drivers/staging/comedi/drivers/ni_670x.c12
-rw-r--r--drivers/staging/comedi/drivers/ni_at_a2150.c360
-rw-r--r--drivers/staging/comedi/drivers/ni_at_ao.c238
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio.c94
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio16d.c82
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_700.c17
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_dio24.c17
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.c9
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.h2
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_cs.c10
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_cs.c13
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c142
-rw-r--r--drivers/staging/comedi/drivers/ni_pcimio.c198
-rw-r--r--drivers/staging/comedi/drivers/ni_tio_internal.h36
-rw-r--r--drivers/staging/comedi/drivers/pcl711.c75
-rw-r--r--drivers/staging/comedi/drivers/pcl724.c65
-rw-r--r--drivers/staging/comedi/drivers/pcl725.c37
-rw-r--r--drivers/staging/comedi/drivers/pcl726.c46
-rw-r--r--drivers/staging/comedi/drivers/pcl730.c57
-rw-r--r--drivers/staging/comedi/drivers/pcl812.c166
-rw-r--r--drivers/staging/comedi/drivers/pcl816.c153
-rw-r--r--drivers/staging/comedi/drivers/pcl818.c166
-rw-r--r--drivers/staging/comedi/drivers/pcm3724.c51
-rw-r--r--drivers/staging/comedi/drivers/pcm3730.c37
-rw-r--r--drivers/staging/comedi/drivers/pcmad.c63
-rw-r--r--drivers/staging/comedi/drivers/pcmda12.c224
-rw-r--r--drivers/staging/comedi/drivers/pcmmio.c661
-rw-r--r--drivers/staging/comedi/drivers/pcmuio.c542
-rw-r--r--drivers/staging/comedi/drivers/poc.c205
-rw-r--r--drivers/staging/comedi/drivers/quatech_daqp_cs.c16
-rw-r--r--drivers/staging/comedi/drivers/rtd520.c188
-rw-r--r--drivers/staging/comedi/drivers/rti800.c54
-rw-r--r--drivers/staging/comedi/drivers/rti802.c37
-rw-r--r--drivers/staging/comedi/drivers/s526.c495
-rw-r--r--drivers/staging/comedi/drivers/s626.c137
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c69
-rw-r--r--drivers/staging/comedi/drivers/skel.c9
-rw-r--r--drivers/staging/comedi/drivers/ssv_dnp.c223
-rw-r--r--drivers/staging/comedi/drivers/unioxx5.c453
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c149
-rw-r--r--drivers/staging/comedi/drivers/usbduxfast.c93
-rw-r--r--drivers/staging/comedi/drivers/usbduxsigma.c48
-rw-r--r--drivers/staging/comedi/drivers/vmk80xx.c113
-rw-r--r--drivers/staging/comedi/internal.h6
-rw-r--r--drivers/staging/et131x/et131x.c10
-rw-r--r--drivers/staging/frontier/alphatrack.c15
-rw-r--r--drivers/staging/frontier/tranzport.c16
-rw-r--r--drivers/staging/gdm72xx/Kconfig46
-rw-r--r--drivers/staging/gdm72xx/Makefile6
-rw-r--r--drivers/staging/gdm72xx/TODO5
-rw-r--r--drivers/staging/gdm72xx/gdm_qos.c460
-rw-r--r--drivers/staging/gdm72xx/gdm_qos.h93
-rw-r--r--drivers/staging/gdm72xx/gdm_sdio.c754
-rw-r--r--drivers/staging/gdm72xx/gdm_sdio.h72
-rw-r--r--drivers/staging/gdm72xx/gdm_usb.c798
-rw-r--r--drivers/staging/gdm72xx/gdm_usb.h85
-rw-r--r--drivers/staging/gdm72xx/gdm_wimax.c1026
-rw-r--r--drivers/staging/gdm72xx/gdm_wimax.h92
-rw-r--r--drivers/staging/gdm72xx/hci.h218
-rw-r--r--drivers/staging/gdm72xx/netlink_k.c150
-rw-r--r--drivers/staging/gdm72xx/netlink_k.h24
-rw-r--r--drivers/staging/gdm72xx/sdio_boot.c159
-rw-r--r--drivers/staging/gdm72xx/sdio_boot.h21
-rw-r--r--drivers/staging/gdm72xx/usb_boot.c404
-rw-r--r--drivers/staging/gdm72xx/usb_boot.h22
-rw-r--r--drivers/staging/gdm72xx/usb_ids.h82
-rw-r--r--drivers/staging/gdm72xx/wm_ioctl.h97
-rw-r--r--drivers/staging/iio/Documentation/device.txt4
-rw-r--r--drivers/staging/iio/Documentation/generic_buffer.c4
-rw-r--r--drivers/staging/iio/Documentation/iio_event_monitor.c2
-rwxr-xr-xdrivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl25836
-rwxr-xr-xdrivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2x7x13
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio-ad719220
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio-dds81
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio-light15
-rw-r--r--drivers/staging/iio/Documentation/trigger.txt2
-rw-r--r--drivers/staging/iio/Kconfig46
-rw-r--r--drivers/staging/iio/Makefile8
-rw-r--r--drivers/staging/iio/TODO2
-rw-r--r--drivers/staging/iio/accel/adis16201_core.c123
-rw-r--r--drivers/staging/iio/accel/adis16201_ring.c9
-rw-r--r--drivers/staging/iio/accel/adis16201_trigger.c10
-rw-r--r--drivers/staging/iio/accel/adis16203_core.c108
-rw-r--r--drivers/staging/iio/accel/adis16203_ring.c16
-rw-r--r--drivers/staging/iio/accel/adis16203_trigger.c10
-rw-r--r--drivers/staging/iio/accel/adis16204_core.c115
-rw-r--r--drivers/staging/iio/accel/adis16204_ring.c16
-rw-r--r--drivers/staging/iio/accel/adis16204_trigger.c10
-rw-r--r--drivers/staging/iio/accel/adis16209_core.c159
-rw-r--r--drivers/staging/iio/accel/adis16209_ring.c17
-rw-r--r--drivers/staging/iio/accel/adis16209_trigger.c10
-rw-r--r--drivers/staging/iio/accel/adis16220_core.c39
-rw-r--r--drivers/staging/iio/accel/adis16240_core.c129
-rw-r--r--drivers/staging/iio/accel/adis16240_ring.c16
-rw-r--r--drivers/staging/iio/accel/adis16240_trigger.c10
-rw-r--r--drivers/staging/iio/accel/kxsd9.c16
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_core.c50
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_ring.c25
-rw-r--r--drivers/staging/iio/accel/sca3000_core.c66
-rw-r--r--drivers/staging/iio/accel/sca3000_ring.c12
-rw-r--r--drivers/staging/iio/adc/Kconfig27
-rw-r--r--drivers/staging/iio/adc/Makefile1
-rw-r--r--drivers/staging/iio/adc/ad7192.c81
-rw-r--r--drivers/staging/iio/adc/ad7280a.c31
-rw-r--r--drivers/staging/iio/adc/ad7291.c26
-rw-r--r--drivers/staging/iio/adc/ad7298.h1
-rw-r--r--drivers/staging/iio/adc/ad7298_core.c79
-rw-r--r--drivers/staging/iio/adc/ad7298_ring.c46
-rw-r--r--drivers/staging/iio/adc/ad7476.h1
-rw-r--r--drivers/staging/iio/adc/ad7476_core.c60
-rw-r--r--drivers/staging/iio/adc/ad7476_ring.c58
-rw-r--r--drivers/staging/iio/adc/ad7606_core.c39
-rw-r--r--drivers/staging/iio/adc/ad7606_par.c2
-rw-r--r--drivers/staging/iio/adc/ad7606_ring.c30
-rw-r--r--drivers/staging/iio/adc/ad7606_spi.c2
-rw-r--r--drivers/staging/iio/adc/ad7780.c44
-rw-r--r--drivers/staging/iio/adc/ad7793.c103
-rw-r--r--drivers/staging/iio/adc/ad7816.c26
-rw-r--r--drivers/staging/iio/adc/ad7887.h1
-rw-r--r--drivers/staging/iio/adc/ad7887_core.c20
-rw-r--r--drivers/staging/iio/adc/ad7887_ring.c46
-rw-r--r--drivers/staging/iio/adc/ad799x.h1
-rw-r--r--drivers/staging/iio/adc/ad799x_core.c62
-rw-r--r--drivers/staging/iio/adc/ad799x_ring.c44
-rw-r--r--drivers/staging/iio/adc/adt7310.c40
-rw-r--r--drivers/staging/iio/adc/adt7410.c40
-rw-r--r--drivers/staging/iio/adc/lpc32xx_adc.c35
-rw-r--r--drivers/staging/iio/adc/max1363_core.c33
-rw-r--r--drivers/staging/iio/adc/max1363_ring.c10
-rw-r--r--drivers/staging/iio/adc/spear_adc.c448
-rw-r--r--drivers/staging/iio/addac/adt7316.c152
-rw-r--r--drivers/staging/iio/cdc/ad7150.c24
-rw-r--r--drivers/staging/iio/cdc/ad7152.c30
-rw-r--r--drivers/staging/iio/cdc/ad7746.c49
-rw-r--r--drivers/staging/iio/dac/Kconfig6
-rw-r--r--drivers/staging/iio/dac/ad5064.c29
-rw-r--r--drivers/staging/iio/dac/ad5360.c21
-rw-r--r--drivers/staging/iio/dac/ad5380.c25
-rw-r--r--drivers/staging/iio/dac/ad5421.c19
-rw-r--r--drivers/staging/iio/dac/ad5446.c293
-rw-r--r--drivers/staging/iio/dac/ad5446.h20
-rw-r--r--drivers/staging/iio/dac/ad5504.c27
-rw-r--r--drivers/staging/iio/dac/ad5624r_spi.c23
-rw-r--r--drivers/staging/iio/dac/ad5686.c25
-rw-r--r--drivers/staging/iio/dac/ad5764.c17
-rw-r--r--drivers/staging/iio/dac/ad5791.c25
-rw-r--r--drivers/staging/iio/dac/max517.c15
-rw-r--r--drivers/staging/iio/dds/dds.h110
-rw-r--r--drivers/staging/iio/frequency/Kconfig (renamed from drivers/staging/iio/dds/Kconfig)0
-rw-r--r--drivers/staging/iio/frequency/Makefile (renamed from drivers/staging/iio/dds/Makefile)0
-rw-r--r--drivers/staging/iio/frequency/ad5930.c (renamed from drivers/staging/iio/dds/ad5930.c)12
-rw-r--r--drivers/staging/iio/frequency/ad9832.c (renamed from drivers/staging/iio/dds/ad9832.c)36
-rw-r--r--drivers/staging/iio/frequency/ad9832.h (renamed from drivers/staging/iio/dds/ad9832.h)0
-rw-r--r--drivers/staging/iio/frequency/ad9834.c (renamed from drivers/staging/iio/dds/ad9834.c)74
-rw-r--r--drivers/staging/iio/frequency/ad9834.h (renamed from drivers/staging/iio/dds/ad9834.h)0
-rw-r--r--drivers/staging/iio/frequency/ad9850.c (renamed from drivers/staging/iio/dds/ad9850.c)12
-rw-r--r--drivers/staging/iio/frequency/ad9852.c (renamed from drivers/staging/iio/dds/ad9852.c)12
-rw-r--r--drivers/staging/iio/frequency/ad9910.c (renamed from drivers/staging/iio/dds/ad9910.c)12
-rw-r--r--drivers/staging/iio/frequency/ad9951.c (renamed from drivers/staging/iio/dds/ad9951.c)12
-rw-r--r--drivers/staging/iio/frequency/dds.h110
-rw-r--r--drivers/staging/iio/gyro/adis16060_core.c18
-rw-r--r--drivers/staging/iio/gyro/adis16080_core.c16
-rw-r--r--drivers/staging/iio/gyro/adis16130_core.c12
-rw-r--r--drivers/staging/iio/gyro/adis16260_core.c116
-rw-r--r--drivers/staging/iio/gyro/adis16260_ring.c16
-rw-r--r--drivers/staging/iio/gyro/adis16260_trigger.c10
-rw-r--r--drivers/staging/iio/gyro/adxrs450.h2
-rw-r--r--drivers/staging/iio/gyro/adxrs450_core.c24
-rw-r--r--drivers/staging/iio/iio_dummy_evgen.c4
-rw-r--r--drivers/staging/iio/iio_hwmon.c4
-rw-r--r--drivers/staging/iio/iio_simple_dummy.c35
-rw-r--r--drivers/staging/iio/iio_simple_dummy_buffer.c21
-rw-r--r--drivers/staging/iio/iio_simple_dummy_events.c8
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c83
-rw-r--r--drivers/staging/iio/imu/adis16400_core.c141
-rw-r--r--drivers/staging/iio/imu/adis16400_ring.c20
-rw-r--r--drivers/staging/iio/imu/adis16400_trigger.c10
-rw-r--r--drivers/staging/iio/light/Kconfig37
-rw-r--r--drivers/staging/iio/light/Makefile2
-rw-r--r--drivers/staging/iio/light/isl29018.c211
-rw-r--r--drivers/staging/iio/light/isl29028.c566
-rw-r--r--drivers/staging/iio/light/tsl2563.c24
-rw-r--r--drivers/staging/iio/light/tsl2583.c34
-rwxr-xr-xdrivers/staging/iio/light/tsl2x7x.h100
-rwxr-xr-xdrivers/staging/iio/light/tsl2x7x_core.c2082
-rw-r--r--drivers/staging/iio/magnetometer/Kconfig8
-rw-r--r--drivers/staging/iio/magnetometer/ak8975.c19
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843.c522
-rw-r--r--drivers/staging/iio/meter/ade7753.c22
-rw-r--r--drivers/staging/iio/meter/ade7754.c22
-rw-r--r--drivers/staging/iio/meter/ade7758_core.c299
-rw-r--r--drivers/staging/iio/meter/ade7758_ring.c33
-rw-r--r--drivers/staging/iio/meter/ade7758_trigger.c10
-rw-r--r--drivers/staging/iio/meter/ade7759.c22
-rw-r--r--drivers/staging/iio/meter/ade7854-i2c.c22
-rw-r--r--drivers/staging/iio/meter/ade7854-spi.c22
-rw-r--r--drivers/staging/iio/meter/ade7854.c28
-rw-r--r--drivers/staging/iio/meter/meter.h2
-rw-r--r--drivers/staging/iio/resolver/ad2s1200.c12
-rw-r--r--drivers/staging/iio/resolver/ad2s1210.c38
-rw-r--r--drivers/staging/iio/resolver/ad2s90.c11
-rw-r--r--drivers/staging/iio/ring_sw.c2
-rw-r--r--drivers/staging/iio/ring_sw.h2
-rw-r--r--drivers/staging/iio/trigger/iio-trig-bfin-timer.c10
-rw-r--r--drivers/staging/iio/trigger/iio-trig-gpio.c10
-rw-r--r--drivers/staging/iio/trigger/iio-trig-periodic-rtc.c8
-rw-r--r--drivers/staging/iio/trigger/iio-trig-sysfs.c10
-rw-r--r--drivers/staging/ipack/Kconfig20
-rw-r--r--drivers/staging/ipack/Makefile6
-rw-r--r--drivers/staging/ipack/TODO46
-rw-r--r--drivers/staging/ipack/bridges/Kconfig8
-rw-r--r--drivers/staging/ipack/bridges/Makefile1
-rw-r--r--drivers/staging/ipack/bridges/tpci200.c1141
-rw-r--r--drivers/staging/ipack/bridges/tpci200.h162
-rw-r--r--drivers/staging/ipack/devices/Kconfig7
-rw-r--r--drivers/staging/ipack/devices/Makefile1
-rw-r--r--drivers/staging/ipack/devices/ipoctal.c901
-rw-r--r--drivers/staging/ipack/devices/ipoctal.h80
-rw-r--r--drivers/staging/ipack/devices/scc2698.h228
-rw-r--r--drivers/staging/ipack/ipack.c205
-rw-r--r--drivers/staging/ipack/ipack.h183
-rw-r--r--drivers/staging/line6/config.h48
-rw-r--r--drivers/staging/line6/driver.c88
-rw-r--r--drivers/staging/line6/midi.c2
-rw-r--r--drivers/staging/line6/midibuf.c2
-rw-r--r--drivers/staging/line6/pcm.c2
-rw-r--r--drivers/staging/line6/toneport.c2
-rw-r--r--drivers/staging/media/as102/as102_drv.c34
-rw-r--r--drivers/staging/media/as102/as102_fe.c2
-rw-r--r--drivers/staging/media/as102/as102_fw.c5
-rw-r--r--drivers/staging/media/as102/as102_usb_drv.c12
-rw-r--r--drivers/staging/media/as102/as102_usb_drv.h2
-rw-r--r--drivers/staging/media/easycap/easycap_ioctl.c1
-rw-r--r--drivers/staging/media/easycap/easycap_main.c6
-rw-r--r--drivers/staging/media/go7007/README2
-rw-r--r--drivers/staging/media/go7007/go7007.txt1
-rw-r--r--drivers/staging/media/go7007/s2250-loader.c26
-rw-r--r--drivers/staging/media/lirc/lirc_imon.c80
-rw-r--r--drivers/staging/media/lirc/lirc_sasem.c100
-rw-r--r--drivers/staging/media/lirc/lirc_ttusbir.c13
-rw-r--r--drivers/staging/mei/TODO10
-rw-r--r--drivers/staging/net/Kconfig38
-rw-r--r--drivers/staging/net/Makefile5
-rw-r--r--drivers/staging/net/TODO5
-rw-r--r--drivers/staging/net/pc300-falc-lh.h (renamed from drivers/net/wan/pc300-falc-lh.h)0
-rw-r--r--drivers/staging/net/pc300.h (renamed from drivers/net/wan/pc300.h)0
-rw-r--r--drivers/staging/net/pc300_drv.c (renamed from drivers/net/wan/pc300_drv.c)0
-rw-r--r--drivers/staging/net/pc300_tty.c (renamed from drivers/net/wan/pc300_tty.c)0
-rw-r--r--drivers/staging/nvec/nvec.h2
-rw-r--r--drivers/staging/octeon/ethernet-rx.c2
-rw-r--r--drivers/staging/octeon/ethernet-tx.c10
-rw-r--r--drivers/staging/octeon/ethernet-util.h2
-rw-r--r--drivers/staging/octeon/ethernet.c2
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.c29
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon_xo_1.c2
-rw-r--r--drivers/staging/omapdrm/Makefile1
-rw-r--r--drivers/staging/omapdrm/omap_dmm_tiler.c4
-rw-r--r--drivers/staging/omapdrm/omap_drv.c6
-rw-r--r--drivers/staging/omapdrm/omap_drv.h14
-rw-r--r--drivers/staging/omapdrm/omap_fb.c7
-rw-r--r--drivers/staging/omapdrm/omap_gem.c130
-rw-r--r--drivers/staging/omapdrm/omap_gem_dmabuf.c220
-rw-r--r--drivers/staging/omapdrm/tcm-sita.c2
-rw-r--r--drivers/staging/ozwpan/README2
-rw-r--r--drivers/staging/ozwpan/ozappif.h12
-rw-r--r--drivers/staging/ozwpan/ozcdev.c17
-rw-r--r--drivers/staging/ozwpan/ozevent.c195
-rw-r--r--drivers/staging/ozwpan/ozevent.h11
-rw-r--r--drivers/staging/ozwpan/ozeventdef.h19
-rw-r--r--drivers/staging/ozwpan/ozhcd.c6
-rw-r--r--drivers/staging/ozwpan/ozmain.c8
-rw-r--r--drivers/staging/ozwpan/ozusbsvc.c2
-rw-r--r--drivers/staging/panel/panel.c2
-rw-r--r--drivers/staging/quatech_usb2/Kconfig15
-rw-r--r--drivers/staging/quatech_usb2/Makefile1
-rw-r--r--drivers/staging/quatech_usb2/TODO8
-rw-r--r--drivers/staging/quatech_usb2/quatech_usb2.c1976
-rw-r--r--drivers/staging/ramster/Kconfig2
-rw-r--r--drivers/staging/ramster/cluster/tcp.c4
-rw-r--r--drivers/staging/ramster/xvmalloc.c2
-rw-r--r--drivers/staging/ramster/zcache-main.c6
-rw-r--r--drivers/staging/rtl8187se/Makefile2
-rw-r--r--drivers/staging/rtl8187se/ieee80211/dot11d.c2
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211.h14
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c26
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c2
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c7
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c2
-rw-r--r--drivers/staging/rtl8187se/r8180.h10
-rw-r--r--drivers/staging/rtl8187se/r8180_core.c33
-rw-r--r--drivers/staging/rtl8187se/r8180_dm.c16
-rw-r--r--drivers/staging/rtl8187se/r8180_rtl8225z2.c4
-rw-r--r--drivers/staging/rtl8187se/r8180_wx.c6
-rw-r--r--drivers/staging/rtl8187se/r8180_wx.h2
-rw-r--r--drivers/staging/rtl8187se/r8185b_init.c1329
-rw-r--r--drivers/staging/rtl8192e/Kconfig4
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c3
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r819xE_phyreg.h4
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c13
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.h3
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.c22
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_wx.c4
-rw-r--r--drivers/staging/rtl8192e/rtl819x_TSProc.c2
-rw-r--r--drivers/staging/rtl8192e/rtllib.h18
-rw-r--r--drivers/staging/rtl8192e/rtllib_rx.c10
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac.c35
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac_wx.c4
-rw-r--r--drivers/staging/rtl8192e/rtllib_tx.c14
-rw-r--r--drivers/staging/rtl8192e/rtllib_wx.c4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_module.c2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c7
-rw-r--r--drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c2
-rw-r--r--drivers/staging/rtl8192u/r8180_93cx6.c2
-rw-r--r--drivers/staging/rtl8192u/r8180_93cx6.h2
-rw-r--r--drivers/staging/rtl8192u/r8192U.h9
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c60
-rw-r--r--drivers/staging/rtl8192u/r8192U_dm.c74
-rw-r--r--drivers/staging/rtl8192u/r8192U_hw.h2
-rw-r--r--drivers/staging/rtl8192u/r8192U_wx.c12
-rw-r--r--drivers/staging/rtl8192u/r8192U_wx.h2
-rw-r--r--drivers/staging/rtl8192u/r819xU_HTType.h2
-rw-r--r--drivers/staging/rtl8192u/r819xU_cmdpkt.c12
-rw-r--r--drivers/staging/rtl8192u/r819xU_firmware.c4
-rw-r--r--drivers/staging/rtl8192u/r819xU_phy.c16
-rw-r--r--drivers/staging/rtl8192u/r819xU_phyreg.h2
-rw-r--r--drivers/staging/rtl8712/big_endian.h94
-rw-r--r--drivers/staging/rtl8712/drv_types.h2
-rw-r--r--drivers/staging/rtl8712/generic.h178
-rw-r--r--drivers/staging/rtl8712/hal_init.c1
-rw-r--r--drivers/staging/rtl8712/ieee80211.h2
-rw-r--r--drivers/staging/rtl8712/if_ether.h141
-rw-r--r--drivers/staging/rtl8712/ip.h137
-rw-r--r--drivers/staging/rtl8712/little_endian.h94
-rw-r--r--drivers/staging/rtl8712/os_intfs.c4
-rw-r--r--drivers/staging/rtl8712/osdep_service.h3
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.c7
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.h2
-rw-r--r--drivers/staging/rtl8712/rtl8712_efuse.c2
-rw-r--r--drivers/staging/rtl8712/rtl8712_gp_bitdef.h2
-rw-r--r--drivers/staging/rtl8712/rtl8712_hal.h4
-rw-r--r--drivers/staging/rtl8712/rtl8712_led.c6
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.c9
-rw-r--r--drivers/staging/rtl8712/rtl8712_xmit.c1
-rw-r--r--drivers/staging/rtl8712/rtl871x_byteorder.h32
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.c1
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.h2
-rw-r--r--drivers/staging/rtl8712/rtl871x_io.h2
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_linux.c19
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.c2
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.c8
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.h6
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h4
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.c4
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.c3
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.h2
-rw-r--r--drivers/staging/rtl8712/swab.h131
-rw-r--r--drivers/staging/rtl8712/usb_halinit.c4
-rw-r--r--drivers/staging/rtl8712/usb_intf.c36
-rw-r--r--drivers/staging/rtl8712/usb_ops.c1
-rw-r--r--drivers/staging/rtl8712/wifi.h1
-rw-r--r--drivers/staging/rtl8712/xmit_linux.c6
-rw-r--r--drivers/staging/rts5139/ms.c11
-rw-r--r--drivers/staging/rts5139/ms.h2
-rw-r--r--drivers/staging/rts5139/ms_mg.c4
-rw-r--r--drivers/staging/rts5139/rts51x.c83
-rw-r--r--drivers/staging/rts5139/rts51x.h10
-rw-r--r--drivers/staging/rts5139/rts51x_card.c52
-rw-r--r--drivers/staging/rts5139/rts51x_card.h11
-rw-r--r--drivers/staging/rts5139/rts51x_chip.c178
-rw-r--r--drivers/staging/rts5139/rts51x_chip.h95
-rw-r--r--drivers/staging/rts5139/rts51x_fop.c5
-rw-r--r--drivers/staging/rts5139/rts51x_fop.h5
-rw-r--r--drivers/staging/rts5139/rts51x_scsi.c93
-rw-r--r--drivers/staging/rts5139/rts51x_scsi.h5
-rw-r--r--drivers/staging/rts5139/rts51x_sys.h54
-rw-r--r--drivers/staging/rts5139/rts51x_transport.c282
-rw-r--r--drivers/staging/rts5139/rts51x_transport.h12
-rw-r--r--drivers/staging/rts5139/sd.c142
-rw-r--r--drivers/staging/rts5139/sd.h29
-rw-r--r--drivers/staging/rts5139/sd_cprm.c166
-rw-r--r--drivers/staging/rts5139/xd.c122
-rw-r--r--drivers/staging/rts5139/xd.h2
-rw-r--r--drivers/staging/rts_pstor/ms.c2
-rw-r--r--drivers/staging/rts_pstor/rtsx_transport.c4
-rw-r--r--drivers/staging/sep/sep_driver_config.h6
-rw-r--r--drivers/staging/sep/sep_main.c12
-rw-r--r--drivers/staging/serial/68360serial.c2979
-rw-r--r--drivers/staging/serial/Kconfig16
-rw-r--r--drivers/staging/serial/Makefile1
-rw-r--r--drivers/staging/serial/TODO6
-rw-r--r--drivers/staging/serqt_usb2/serqt_usb2.c79
-rw-r--r--drivers/staging/sm7xx/smtcfb.c232
-rw-r--r--drivers/staging/sm7xx/smtcfb.h8
-rw-r--r--drivers/staging/telephony/ixj.c228
-rw-r--r--drivers/staging/tidspbridge/core/io_sm.c2
-rw-r--r--drivers/staging/tidspbridge/core/ue_deh.c2
-rw-r--r--drivers/staging/usbip/stub_dev.c12
-rw-r--r--drivers/staging/usbip/usbip_common.h17
-rw-r--r--drivers/staging/usbip/usbip_protocol.txt2
-rw-r--r--drivers/staging/usbip/userspace/libsrc/vhci_driver.c20
-rw-r--r--drivers/staging/usbip/vhci_hcd.c8
-rw-r--r--drivers/staging/usbip/vhci_rx.c2
-rw-r--r--drivers/staging/usbip/vhci_sysfs.c4
-rw-r--r--drivers/staging/vme/Makefile7
-rw-r--r--drivers/staging/vme/TODO5
-rw-r--r--drivers/staging/vme/devices/Kconfig3
-rw-r--r--drivers/staging/vme/devices/vme_pio2_cntr.c2
-rw-r--r--drivers/staging/vme/devices/vme_pio2_core.c3
-rw-r--r--drivers/staging/vme/devices/vme_pio2_gpio.c5
-rw-r--r--drivers/staging/vme/devices/vme_user.c45
-rw-r--r--drivers/staging/vt6655/wpa.c4
-rw-r--r--drivers/staging/vt6656/dpc.c2
-rw-r--r--drivers/staging/vt6656/ioctl.c24
-rw-r--r--drivers/staging/vt6656/main_usb.c4
-rw-r--r--drivers/staging/vt6656/wpa.c4
-rw-r--r--drivers/staging/wlags49_h2/README.ubuntu2
-rw-r--r--drivers/staging/wlags49_h2/hcf.c10
-rw-r--r--drivers/staging/wlags49_h2/hcf.h12
-rw-r--r--drivers/staging/wlags49_h2/mmd.c12
-rw-r--r--drivers/staging/wlags49_h2/wl_cs.c3
-rw-r--r--drivers/staging/wlags49_h2/wl_netdev.c9
-rw-r--r--drivers/staging/wlags49_h2/wl_pci.c4
-rw-r--r--drivers/staging/wlags49_h2/wl_profile.c8
-rw-r--r--drivers/staging/wlags49_h2/wl_util.c11
-rw-r--r--drivers/staging/wlan-ng/cfg80211.c10
-rw-r--r--drivers/staging/wlan-ng/prism2mgmt.c4
-rw-r--r--drivers/staging/xgifb/XGI_main.h221
-rw-r--r--drivers/staging/xgifb/XGI_main_26.c101
-rw-r--r--drivers/staging/xgifb/XGIfb.h6
-rw-r--r--drivers/staging/xgifb/vb_init.c78
-rw-r--r--drivers/staging/xgifb/vb_setmode.c1457
-rw-r--r--drivers/staging/xgifb/vb_struct.h27
-rw-r--r--drivers/staging/xgifb/vb_table.h725
-rw-r--r--drivers/staging/xgifb/vgatypes.h2
-rw-r--r--drivers/staging/zsmalloc/zsmalloc-main.c40
-rw-r--r--drivers/staging/zsmalloc/zsmalloc_int.h2
-rw-r--r--drivers/target/Kconfig1
-rw-r--r--drivers/target/Makefile1
-rw-r--r--drivers/target/iscsi/iscsi_target.c821
-rw-r--r--drivers/target/iscsi/iscsi_target.h3
-rw-r--r--drivers/target/iscsi/iscsi_target_configfs.c2
-rw-r--r--drivers/target/iscsi/iscsi_target_core.h12
-rw-r--r--drivers/target/iscsi/iscsi_target_datain_values.c35
-rw-r--r--drivers/target/iscsi/iscsi_target_erl0.c31
-rw-r--r--drivers/target/iscsi/iscsi_target_erl1.c23
-rw-r--r--drivers/target/iscsi/iscsi_target_erl2.c28
-rw-r--r--drivers/target/iscsi/iscsi_target_parameters.c17
-rw-r--r--drivers/target/iscsi/iscsi_target_seq_pdu_list.c145
-rw-r--r--drivers/target/iscsi/iscsi_target_seq_pdu_list.h2
-rw-r--r--drivers/target/iscsi/iscsi_target_tmr.c15
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c192
-rw-r--r--drivers/target/iscsi/iscsi_target_util.h3
-rw-r--r--drivers/target/loopback/tcm_loop.c4
-rw-r--r--drivers/target/sbp/Kconfig11
-rw-r--r--drivers/target/sbp/Makefile1
-rw-r--r--drivers/target/sbp/sbp_target.c2621
-rw-r--r--drivers/target/sbp/sbp_target.h251
-rw-r--r--drivers/target/target_core_alua.c100
-rw-r--r--drivers/target/target_core_alua.h14
-rw-r--r--drivers/target/target_core_cdb.c118
-rw-r--r--drivers/target/target_core_configfs.c25
-rw-r--r--drivers/target/target_core_device.c84
-rw-r--r--drivers/target/target_core_file.c153
-rw-r--r--drivers/target/target_core_file.h4
-rw-r--r--drivers/target/target_core_iblock.c152
-rw-r--r--drivers/target/target_core_iblock.h1
-rw-r--r--drivers/target/target_core_internal.h25
-rw-r--r--drivers/target/target_core_pr.c70
-rw-r--r--drivers/target/target_core_pr.h8
-rw-r--r--drivers/target/target_core_pscsi.c179
-rw-r--r--drivers/target/target_core_pscsi.h1
-rw-r--r--drivers/target/target_core_rd.c168
-rw-r--r--drivers/target/target_core_rd.h20
-rw-r--r--drivers/target/target_core_tmr.c71
-rw-r--r--drivers/target/target_core_tpg.c5
-rw-r--r--drivers/target/target_core_transport.c994
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c18
-rw-r--r--drivers/target/tcm_fc/tfc_conf.c3
-rw-r--r--drivers/target/tcm_fc/tfc_io.c2
-rw-r--r--drivers/tty/amiserial.c14
-rw-r--r--drivers/tty/bfin_jtag_comm.c44
-rw-r--r--drivers/tty/cyclades.c2
-rw-r--r--drivers/tty/hvc/hvc_console.c96
-rw-r--r--drivers/tty/hvc/hvc_console.h4
-rw-r--r--drivers/tty/hvc/hvc_xen.c4
-rw-r--r--drivers/tty/hvc/hvcs.c74
-rw-r--r--drivers/tty/hvc/hvsi.c128
-rw-r--r--drivers/tty/hvc/hvsi_lib.c2
-rw-r--r--drivers/tty/ipwireless/tty.c81
-rw-r--r--drivers/tty/mxser.c2
-rw-r--r--drivers/tty/n_r3964.c11
-rw-r--r--drivers/tty/n_tty.c9
-rw-r--r--drivers/tty/pty.c40
-rw-r--r--drivers/tty/serial/68328serial.c383
-rw-r--r--drivers/tty/serial/68328serial.h186
-rw-r--r--drivers/tty/serial/8250/8250.c312
-rw-r--r--drivers/tty/serial/8250/8250.h16
-rw-r--r--drivers/tty/serial/8250/8250_em.c186
-rw-r--r--drivers/tty/serial/8250/8250_pci.c63
-rw-r--r--drivers/tty/serial/8250/Kconfig8
-rw-r--r--drivers/tty/serial/8250/Makefile1
-rw-r--r--drivers/tty/serial/amba-pl011.c117
-rw-r--r--drivers/tty/serial/bfin_uart.c74
-rw-r--r--drivers/tty/serial/clps711x.c1
-rw-r--r--drivers/tty/serial/crisv10.c36
-rw-r--r--drivers/tty/serial/imx.c8
-rw-r--r--drivers/tty/serial/mxs-auart.c10
-rw-r--r--drivers/tty/serial/of_serial.c26
-rw-r--r--drivers/tty/serial/omap-serial.c74
-rw-r--r--drivers/tty/serial/pch_uart.c53
-rw-r--r--drivers/tty/serial/serial_core.c1
-rw-r--r--drivers/tty/serial/sh-sci.c49
-rw-r--r--drivers/tty/synclink.c4
-rw-r--r--drivers/tty/synclink_gt.c4
-rw-r--r--drivers/tty/synclinkmp.c4
-rw-r--r--drivers/tty/tty_buffer.c85
-rw-r--r--drivers/tty/tty_io.c76
-rw-r--r--drivers/tty/tty_ldisc.c37
-rw-r--r--drivers/tty/tty_mutex.c60
-rw-r--r--drivers/tty/tty_port.c6
-rw-r--r--drivers/tty/vt/consolemap.c123
-rw-r--r--drivers/tty/vt/keyboard.c20
-rw-r--r--drivers/tty/vt/vt.c68
-rw-r--r--drivers/tty/vt/vt_ioctl.c25
-rw-r--r--drivers/uio/uio_pdrv_genirq.c8
-rw-r--r--drivers/usb/Kconfig4
-rw-r--r--drivers/usb/Makefile2
-rw-r--r--drivers/usb/atm/cxacru.c34
-rw-r--r--drivers/usb/atm/speedtch.c2
-rw-r--r--drivers/usb/atm/ueagle-atm.c15
-rw-r--r--drivers/usb/atm/usbatm.c30
-rw-r--r--drivers/usb/atm/xusbatm.c4
-rw-r--r--drivers/usb/chipidea/Kconfig32
-rw-r--r--drivers/usb/chipidea/Makefile14
-rw-r--r--drivers/usb/chipidea/bits.h90
-rw-r--r--drivers/usb/chipidea/ci.h313
-rw-r--r--drivers/usb/chipidea/ci13xxx_msm.c (renamed from drivers/usb/gadget/ci13xxx_msm.c)60
-rw-r--r--drivers/usb/chipidea/ci13xxx_pci.c (renamed from drivers/usb/gadget/ci13xxx_pci.c)154
-rw-r--r--drivers/usb/chipidea/core.c474
-rw-r--r--drivers/usb/chipidea/debug.c804
-rw-r--r--drivers/usb/chipidea/debug.h56
-rw-r--r--drivers/usb/chipidea/host.c160
-rw-r--r--drivers/usb/chipidea/host.h17
-rw-r--r--drivers/usb/chipidea/udc.c1809
-rw-r--r--drivers/usb/chipidea/udc.h93
-rw-r--r--drivers/usb/class/cdc-acm.c1
-rw-r--r--drivers/usb/class/cdc-wdm.c38
-rw-r--r--drivers/usb/class/usblp.c82
-rw-r--r--drivers/usb/core/Kconfig53
-rw-r--r--drivers/usb/core/Makefile2
-rw-r--r--drivers/usb/core/devio.c93
-rw-r--r--drivers/usb/core/driver.c103
-rw-r--r--drivers/usb/core/file.c4
-rw-r--r--drivers/usb/core/hcd.c15
-rw-r--r--drivers/usb/core/hub.c676
-rw-r--r--drivers/usb/core/inode.c748
-rw-r--r--drivers/usb/core/message.c38
-rw-r--r--drivers/usb/core/quirks.c3
-rw-r--r--drivers/usb/core/sysfs.c6
-rw-r--r--drivers/usb/core/urb.c21
-rw-r--r--drivers/usb/core/usb-acpi.c117
-rw-r--r--drivers/usb/core/usb.c9
-rw-r--r--drivers/usb/core/usb.h7
-rw-r--r--drivers/usb/dwc3/Kconfig2
-rw-r--r--drivers/usb/dwc3/core.c31
-rw-r--r--drivers/usb/dwc3/core.h40
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c32
-rw-r--r--drivers/usb/dwc3/ep0.c157
-rw-r--r--drivers/usb/dwc3/gadget.c151
-rw-r--r--drivers/usb/dwc3/gadget.h1
-rw-r--r--drivers/usb/dwc3/host.c19
-rw-r--r--drivers/usb/dwc3/io.h16
-rw-r--r--drivers/usb/gadget/Kconfig78
-rw-r--r--drivers/usb/gadget/Makefile6
-rw-r--r--drivers/usb/gadget/amd5536udc.c27
-rw-r--r--drivers/usb/gadget/amd5536udc.h1
-rw-r--r--drivers/usb/gadget/at91_udc.c77
-rw-r--r--drivers/usb/gadget/at91_udc.h3
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c76
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.h1
-rw-r--r--drivers/usb/gadget/ci13xxx_udc.c2996
-rw-r--r--drivers/usb/gadget/ci13xxx_udc.h227
-rw-r--r--drivers/usb/gadget/composite.c107
-rw-r--r--drivers/usb/gadget/dummy_hcd.c8
-rw-r--r--drivers/usb/gadget/f_fs.c52
-rw-r--r--drivers/usb/gadget/f_hid.c2
-rw-r--r--drivers/usb/gadget/f_loopback.c4
-rw-r--r--drivers/usb/gadget/f_mass_storage.c7
-rw-r--r--drivers/usb/gadget/f_rndis.c30
-rw-r--r--drivers/usb/gadget/f_sourcesink.c424
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.c371
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.h1
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c55
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.h12
-rw-r--r--drivers/usb/gadget/fusb300_udc.c4
-rw-r--r--drivers/usb/gadget/fusb300_udc.h1
-rw-r--r--drivers/usb/gadget/g_ffs.c200
-rw-r--r--drivers/usb/gadget/g_zero.h5
-rw-r--r--drivers/usb/gadget/gadget_chips.h3
-rw-r--r--drivers/usb/gadget/goku_udc.c32
-rw-r--r--drivers/usb/gadget/goku_udc.h1
-rw-r--r--drivers/usb/gadget/imx_udc.c53
-rw-r--r--drivers/usb/gadget/langwell_udc.c3434
-rw-r--r--drivers/usb/gadget/langwell_udc.h224
-rw-r--r--drivers/usb/gadget/lpc32xx_udc.c3538
-rw-r--r--drivers/usb/gadget/m66592-udc.c10
-rw-r--r--drivers/usb/gadget/m66592-udc.h2
-rw-r--r--drivers/usb/gadget/mv_udc.h1
-rw-r--r--drivers/usb/gadget/mv_udc_core.c19
-rw-r--r--drivers/usb/gadget/omap_udc.c19
-rw-r--r--drivers/usb/gadget/omap_udc.h1
-rw-r--r--drivers/usb/gadget/pch_udc.c29
-rw-r--r--drivers/usb/gadget/printer.c470
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c26
-rw-r--r--drivers/usb/gadget/pxa25x_udc.h1
-rw-r--r--drivers/usb/gadget/r8a66597-udc.c29
-rw-r--r--drivers/usb/gadget/r8a66597-udc.h3
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c1633
-rw-r--r--drivers/usb/gadget/s3c-hsotg.h377
-rw-r--r--drivers/usb/gadget/s3c-hsudc.c9
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c14
-rw-r--r--drivers/usb/gadget/s3c2410_udc.h1
-rw-r--r--drivers/usb/gadget/tcm_usb_gadget.c2480
-rw-r--r--drivers/usb/gadget/tcm_usb_gadget.h146
-rw-r--r--drivers/usb/gadget/u_ether.c8
-rw-r--r--drivers/usb/gadget/u_ether.h46
-rw-r--r--drivers/usb/gadget/u_serial.c57
-rw-r--r--drivers/usb/gadget/zero.c19
-rw-r--r--drivers/usb/host/Kconfig43
-rw-r--r--drivers/usb/host/Makefile2
-rw-r--r--drivers/usb/host/bcma-hcd.c335
-rw-r--r--drivers/usb/host/ehci-dbg.c6
-rw-r--r--drivers/usb/host/ehci-fsl.c41
-rw-r--r--drivers/usb/host/ehci-fsl.h13
-rw-r--r--drivers/usb/host/ehci-hcd.c36
-rw-r--r--drivers/usb/host/ehci-hub.c22
-rw-r--r--drivers/usb/host/ehci-omap.c22
-rw-r--r--drivers/usb/host/ehci-pci.c4
-rw-r--r--drivers/usb/host/ehci-platform.c6
-rw-r--r--drivers/usb/host/ehci-q.c19
-rw-r--r--drivers/usb/host/ehci-s5p.c4
-rw-r--r--drivers/usb/host/ehci-sched.c55
-rw-r--r--drivers/usb/host/ehci-sead3.c266
-rw-r--r--drivers/usb/host/ehci-sh.c8
-rw-r--r--drivers/usb/host/ehci-spear.c36
-rw-r--r--drivers/usb/host/ehci-tegra.c82
-rw-r--r--drivers/usb/host/fhci-tds.c2
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c41
-rw-r--r--drivers/usb/host/isp1760-hcd.c9
-rw-r--r--drivers/usb/host/isp1760-if.c8
-rw-r--r--drivers/usb/host/ohci-at91.c16
-rw-r--r--drivers/usb/host/ohci-au1xxx.c3
-rw-r--r--drivers/usb/host/ohci-cns3xxx.c3
-rw-r--r--drivers/usb/host/ohci-da8xx.c2
-rw-r--r--drivers/usb/host/ohci-dbg.c4
-rw-r--r--drivers/usb/host/ohci-ep93xx.c9
-rw-r--r--drivers/usb/host/ohci-exynos.c3
-rw-r--r--drivers/usb/host/ohci-hcd.c21
-rw-r--r--drivers/usb/host/ohci-nxp.c173
-rw-r--r--drivers/usb/host/ohci-omap.c10
-rw-r--r--drivers/usb/host/ohci-platform.c4
-rw-r--r--drivers/usb/host/ohci-pnx8550.c3
-rw-r--r--drivers/usb/host/ohci-ppc-of.c5
-rw-r--r--drivers/usb/host/ohci-ppc-soc.c3
-rw-r--r--drivers/usb/host/ohci-ps3.c3
-rw-r--r--drivers/usb/host/ohci-pxa27x.c3
-rw-r--r--drivers/usb/host/ohci-s3c2410.c3
-rw-r--r--drivers/usb/host/ohci-sa1111.c4
-rw-r--r--drivers/usb/host/ohci-sh.c8
-rw-r--r--drivers/usb/host/ohci-spear.c36
-rw-r--r--drivers/usb/host/ohci-ssb.c260
-rw-r--r--drivers/usb/host/ohci-tmio.c3
-rw-r--r--drivers/usb/host/ohci-xls.c3
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c13
-rw-r--r--drivers/usb/host/pci-quirks.c32
-rw-r--r--drivers/usb/host/r8a66597-hcd.c20
-rw-r--r--drivers/usb/host/ssb-hcd.c280
-rw-r--r--drivers/usb/host/xhci-hub.c41
-rw-r--r--drivers/usb/host/xhci-mem.c39
-rw-r--r--drivers/usb/host/xhci-pci.c14
-rw-r--r--drivers/usb/host/xhci-ring.c28
-rw-r--r--drivers/usb/host/xhci.c483
-rw-r--r--drivers/usb/host/xhci.h17
-rw-r--r--drivers/usb/image/mdc800.c19
-rw-r--r--drivers/usb/misc/appledisplay.c12
-rw-r--r--drivers/usb/misc/emi26.c59
-rw-r--r--drivers/usb/misc/emi62.c62
-rw-r--r--drivers/usb/misc/idmouse.c9
-rw-r--r--drivers/usb/misc/iowarrior.c4
-rw-r--r--drivers/usb/misc/ldusb.c15
-rw-r--r--drivers/usb/misc/legousbtower.c45
-rw-r--r--drivers/usb/misc/rio500.c65
-rw-r--r--drivers/usb/misc/usblcd.c24
-rw-r--r--drivers/usb/misc/usbtest.c17
-rw-r--r--drivers/usb/misc/uss720.c49
-rw-r--r--drivers/usb/misc/yurex.c54
-rw-r--r--drivers/usb/musb/Kconfig8
-rw-r--r--drivers/usb/musb/Makefile1
-rw-r--r--drivers/usb/musb/cppi_dma.c1
-rw-r--r--drivers/usb/musb/musb_core.c4
-rw-r--r--drivers/usb/musb/musb_dsps.c711
-rw-r--r--drivers/usb/musb/musb_io.h2
-rw-r--r--drivers/usb/otg/gpio_vbus.c81
-rw-r--r--drivers/usb/otg/twl6030-usb.c4
-rw-r--r--drivers/usb/phy/Kconfig17
-rw-r--r--drivers/usb/phy/Makefile7
-rw-r--r--drivers/usb/phy/isp1301.c77
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c19
-rw-r--r--drivers/usb/serial/Kconfig9
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/aircable.c16
-rw-r--r--drivers/usb/serial/ark3116.c36
-rw-r--r--drivers/usb/serial/belkin_sa.c47
-rw-r--r--drivers/usb/serial/bus.c9
-rw-r--r--drivers/usb/serial/ch341.c48
-rw-r--r--drivers/usb/serial/console.c9
-rw-r--r--drivers/usb/serial/cp210x.c32
-rw-r--r--drivers/usb/serial/cyberjack.c27
-rw-r--r--drivers/usb/serial/cypress_m8.c45
-rw-r--r--drivers/usb/serial/digi_acceleport.c35
-rw-r--r--drivers/usb/serial/empeg.c13
-rw-r--r--drivers/usb/serial/ezusb.c2
-rw-r--r--drivers/usb/serial/f81232.c37
-rw-r--r--drivers/usb/serial/ftdi_sio.c47
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h8
-rw-r--r--drivers/usb/serial/funsoft.c9
-rw-r--r--drivers/usb/serial/garmin_gps.c29
-rw-r--r--drivers/usb/serial/generic.c68
-rw-r--r--drivers/usb/serial/hp4x.c9
-rw-r--r--drivers/usb/serial/io_edgeport.c2
-rw-r--r--drivers/usb/serial/io_tables.h7
-rw-r--r--drivers/usb/serial/io_ti.c27
-rw-r--r--drivers/usb/serial/ipaq.c52
-rw-r--r--drivers/usb/serial/ipw.c18
-rw-r--r--drivers/usb/serial/ir-usb.c72
-rw-r--r--drivers/usb/serial/iuu_phoenix.c47
-rw-r--r--drivers/usb/serial/keyspan.c53
-rw-r--r--drivers/usb/serial/keyspan.h7
-rw-r--r--drivers/usb/serial/keyspan_pda.c17
-rw-r--r--drivers/usb/serial/kl5kusb105.c18
-rw-r--r--drivers/usb/serial/kobil_sct.c19
-rw-r--r--drivers/usb/serial/mct_u232.c33
-rw-r--r--drivers/usb/serial/metro-usb.c92
-rw-r--r--drivers/usb/serial/mos7720.c49
-rw-r--r--drivers/usb/serial/mos7840.c298
-rw-r--r--drivers/usb/serial/moto_modem.c9
-rw-r--r--drivers/usb/serial/navman.c26
-rw-r--r--drivers/usb/serial/omninet.c24
-rw-r--r--drivers/usb/serial/opticon.c53
-rw-r--r--drivers/usb/serial/option.c18
-rw-r--r--drivers/usb/serial/oti6858.c44
-rw-r--r--drivers/usb/serial/pl2303.c114
-rw-r--r--drivers/usb/serial/qcaux.c9
-rw-r--r--drivers/usb/serial/qcserial.c41
-rw-r--r--drivers/usb/serial/quatech2.c1155
-rw-r--r--drivers/usb/serial/safe_serial.c11
-rw-r--r--drivers/usb/serial/siemens_mpi.c9
-rw-r--r--drivers/usb/serial/sierra.c56
-rw-r--r--drivers/usb/serial/spcp8x5.c24
-rw-r--r--drivers/usb/serial/ssu100.c33
-rw-r--r--drivers/usb/serial/symbolserial.c30
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c65
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h1
-rw-r--r--drivers/usb/serial/usb-serial.c109
-rw-r--r--drivers/usb/serial/usb_debug.c9
-rw-r--r--drivers/usb/serial/usb_wwan.c50
-rw-r--r--drivers/usb/serial/visor.c98
-rw-r--r--drivers/usb/serial/vivopay-serial.c9
-rw-r--r--drivers/usb/serial/whiteheat.c569
-rw-r--r--drivers/usb/serial/zio.c9
-rw-r--r--drivers/usb/storage/ene_ub6250.c6
-rw-r--r--drivers/usb/storage/unusual_devs.h9
-rw-r--r--drivers/usb/storage/usb.c22
-rw-r--r--drivers/usb/usb-skeleton.c36
-rw-r--r--drivers/video/au1100fb.c2
-rw-r--r--drivers/video/clps711xfb.c1
-rw-r--r--drivers/video/mxsfb.c9
-rw-r--r--drivers/video/omap2/displays/Kconfig8
-rw-r--r--drivers/video/omap2/displays/Makefile2
-rw-r--r--drivers/video/omap2/displays/panel-taal.c22
-rw-r--r--drivers/video/omap2/displays/panel-tfp410.c (renamed from drivers/video/omap2/displays/panel-dvi.c)134
-rw-r--r--drivers/video/omap2/dss/dsi.c133
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c5
-rw-r--r--drivers/video/sh_mobile_lcdcfb.h1
-rw-r--r--drivers/video/udlfb.c2
-rw-r--r--drivers/virtio/Kconfig11
-rw-r--r--drivers/virtio/virtio.c11
-rw-r--r--drivers/virtio/virtio_balloon.c34
-rw-r--r--drivers/virtio/virtio_mmio.c163
-rw-r--r--drivers/vme/Kconfig (renamed from drivers/staging/vme/Kconfig)6
-rw-r--r--drivers/vme/Makefile7
-rw-r--r--drivers/vme/boards/Kconfig (renamed from drivers/staging/vme/boards/Kconfig)0
-rw-r--r--drivers/vme/boards/Makefile (renamed from drivers/staging/vme/boards/Makefile)0
-rw-r--r--drivers/vme/boards/vme_vmivme7805.c (renamed from drivers/staging/vme/boards/vme_vmivme7805.c)0
-rw-r--r--drivers/vme/boards/vme_vmivme7805.h (renamed from drivers/staging/vme/boards/vme_vmivme7805.h)0
-rw-r--r--drivers/vme/bridges/Kconfig (renamed from drivers/staging/vme/bridges/Kconfig)0
-rw-r--r--drivers/vme/bridges/Makefile (renamed from drivers/staging/vme/bridges/Makefile)0
-rw-r--r--drivers/vme/bridges/vme_ca91cx42.c (renamed from drivers/staging/vme/bridges/vme_ca91cx42.c)8
-rw-r--r--drivers/vme/bridges/vme_ca91cx42.h (renamed from drivers/staging/vme/bridges/vme_ca91cx42.h)0
-rw-r--r--drivers/vme/bridges/vme_tsi148.c (renamed from drivers/staging/vme/bridges/vme_tsi148.c)189
-rw-r--r--drivers/vme/bridges/vme_tsi148.h (renamed from drivers/staging/vme/bridges/vme_tsi148.h)21
-rw-r--r--drivers/vme/vme.c (renamed from drivers/staging/vme/vme.c)41
-rw-r--r--drivers/vme/vme_bridge.h (renamed from drivers/staging/vme/vme_bridge.h)0
-rw-r--r--drivers/w1/Kconfig2
-rw-r--r--drivers/w1/slaves/w1_ds2408.c2
-rw-r--r--drivers/w1/w1.c2
-rw-r--r--drivers/w1/w1_io.c22
-rw-r--r--drivers/watchdog/Kconfig38
-rw-r--r--drivers/watchdog/Makefile2
-rw-r--r--drivers/watchdog/ar7_wdt.c33
-rw-r--r--drivers/watchdog/hpwdt.c59
-rw-r--r--drivers/watchdog/i6300esb.c14
-rw-r--r--drivers/watchdog/ie6xx_wdt.c348
-rw-r--r--drivers/watchdog/it87_wdt.c7
-rw-r--r--drivers/watchdog/ixp2000_wdt.c215
-rw-r--r--drivers/watchdog/pcwd_pci.c18
-rw-r--r--drivers/watchdog/pnx4008_wdt.c10
-rw-r--r--drivers/watchdog/s3c2410_wdt.c7
-rw-r--r--drivers/watchdog/sch311x_wdt.c39
-rw-r--r--drivers/watchdog/shwdt.c306
-rw-r--r--drivers/watchdog/sp5100_tco.c2
-rw-r--r--drivers/watchdog/via_wdt.c18
-rw-r--r--drivers/watchdog/wdt_pci.c34
-rw-r--r--drivers/watchdog/wm831x_wdt.c13
-rw-r--r--drivers/xen/Kconfig2
-rw-r--r--fs/Kconfig.binfmt2
-rw-r--r--fs/aio.c30
-rw-r--r--fs/bio.c7
-rw-r--r--fs/block_dev.c6
-rw-r--r--fs/btrfs/disk-io.c2
-rw-r--r--fs/buffer.c4
-rw-r--r--fs/dcache.c186
-rw-r--r--fs/dlm/ast.c3
-rw-r--r--fs/dlm/dlm_internal.h16
-rw-r--r--fs/dlm/lock.c541
-rw-r--r--fs/dlm/lock.h7
-rw-r--r--fs/dlm/lockspace.c20
-rw-r--r--fs/dlm/lowcomms.c28
-rw-r--r--fs/dlm/memory.c8
-rw-r--r--fs/dlm/rcom.c61
-rw-r--r--fs/dlm/recover.c73
-rw-r--r--fs/dlm/recoverd.c15
-rw-r--r--fs/dlm/requestqueue.c43
-rw-r--r--fs/eventpoll.c90
-rw-r--r--fs/exec.c25
-rw-r--r--fs/ext2/namei.c2
-rw-r--r--fs/ext3/namei.c2
-rw-r--r--fs/ext4/namei.c5
-rw-r--r--fs/gfs2/acl.c12
-rw-r--r--fs/gfs2/aops.c18
-rw-r--r--fs/gfs2/bmap.c10
-rw-r--r--fs/gfs2/dir.c2
-rw-r--r--fs/gfs2/file.c12
-rw-r--r--fs/gfs2/glops.c6
-rw-r--r--fs/gfs2/incore.h27
-rw-r--r--fs/gfs2/inode.h3
-rw-r--r--fs/gfs2/lock_dlm.c2
-rw-r--r--fs/gfs2/log.c103
-rw-r--r--fs/gfs2/log.h2
-rw-r--r--fs/gfs2/lops.c520
-rw-r--r--fs/gfs2/lops.h14
-rw-r--r--fs/gfs2/main.c26
-rw-r--r--fs/gfs2/meta_io.c28
-rw-r--r--fs/gfs2/meta_io.h4
-rw-r--r--fs/gfs2/ops_fstype.c8
-rw-r--r--fs/gfs2/quota.c6
-rw-r--r--fs/gfs2/rgrp.c102
-rw-r--r--fs/gfs2/sys.c10
-rw-r--r--fs/gfs2/trace_gfs2.h16
-rw-r--r--fs/gfs2/trans.c44
-rw-r--r--fs/gfs2/util.c3
-rw-r--r--fs/gfs2/util.h3
-rw-r--r--fs/libfs.c4
-rw-r--r--fs/namei.c77
-rw-r--r--fs/nfs/dir.c5
-rw-r--r--fs/nfs/nfs3proc.c3
-rw-r--r--fs/nfs/nfs4proc.c3
-rw-r--r--fs/nfs/proc.c3
-rw-r--r--fs/nilfs2/namei.c2
-rw-r--r--fs/open.c2
-rw-r--r--fs/proc/base.c63
-rw-r--r--fs/pstore/Kconfig17
-rw-r--r--fs/pstore/Makefile3
-rw-r--r--fs/pstore/ram.c383
-rw-r--r--fs/pstore/ram_core.c (renamed from drivers/staging/android/persistent_ram.c)161
-rw-r--r--fs/stat.c49
-rw-r--r--fs/sysfs/dir.c37
-rw-r--r--fs/ubifs/Kconfig23
-rw-r--r--fs/ubifs/Makefile5
-rw-r--r--fs/ubifs/commit.c14
-rw-r--r--fs/ubifs/debug.c158
-rw-r--r--fs/ubifs/debug.h217
-rw-r--r--fs/ubifs/dir.c10
-rw-r--r--fs/ubifs/file.c4
-rw-r--r--fs/ubifs/gc.c2
-rw-r--r--fs/ubifs/io.c74
-rw-r--r--fs/ubifs/journal.c10
-rw-r--r--fs/ubifs/log.c18
-rw-r--r--fs/ubifs/lprops.c18
-rw-r--r--fs/ubifs/lpt.c78
-rw-r--r--fs/ubifs/lpt_commit.c86
-rw-r--r--fs/ubifs/master.c8
-rw-r--r--fs/ubifs/orphan.c25
-rw-r--r--fs/ubifs/recovery.c43
-rw-r--r--fs/ubifs/replay.c27
-rw-r--r--fs/ubifs/sb.c26
-rw-r--r--fs/ubifs/scan.c14
-rw-r--r--fs/ubifs/super.c31
-rw-r--r--fs/ubifs/tnc.c28
-rw-r--r--fs/ubifs/tnc_commit.c28
-rw-r--r--fs/ubifs/tnc_misc.c36
-rw-r--r--fs/ubifs/ubifs.h26
-rw-r--r--fs/ubifs/xattr.c10
-rw-r--r--fs/udf/namei.c2
-rw-r--r--fs/ufs/super.c5
-rw-r--r--include/acpi/acpi_bus.h36
-rw-r--r--include/asm-generic/pci-bridge.h6
-rw-r--r--include/asm-generic/siginfo.h22
-rw-r--r--include/asm-generic/syscall.h14
-rw-r--r--include/asm-generic/vmlinux.lds.h2
-rw-r--r--include/keys/keyring-type.h2
-rw-r--r--include/linux/Kbuild4
-rw-r--r--include/linux/alarmtimer.h3
-rw-r--r--include/linux/amba/bus.h8
-rw-r--r--include/linux/audit.h8
-rw-r--r--include/linux/bcma/bcma.h1
-rw-r--r--include/linux/blkdev.h3
-rw-r--r--include/linux/capability.h5
-rw-r--r--include/linux/cgroup.h81
-rw-r--r--include/linux/clk.h32
-rw-r--r--include/linux/clkdev.h3
-rw-r--r--include/linux/cpu.h2
-rw-r--r--include/linux/cs5535.h1
-rw-r--r--include/linux/dcache.h21
-rw-r--r--include/linux/device.h34
-rw-r--r--include/linux/dlm.h1
-rw-r--r--include/linux/dmar.h85
-rw-r--r--include/linux/dynamic_debug.h22
-rw-r--r--include/linux/eventpoll.h12
-rw-r--r--include/linux/extcon.h324
-rw-r--r--include/linux/extcon/extcon_gpio.h52
-rw-r--r--include/linux/filter.h12
-rw-r--r--include/linux/firewire.h15
-rw-r--r--include/linux/fs.h1
-rw-r--r--include/linux/fsl_devices.h9
-rw-r--r--include/linux/ftrace.h19
-rw-r--r--include/linux/ftrace_event.h2
-rw-r--r--include/linux/generic_serial.h64
-rw-r--r--include/linux/genhd.h6
-rw-r--r--include/linux/hid.h36
-rw-r--r--include/linux/hidraw.h4
-rw-r--r--include/linux/hyperv.h4
-rw-r--r--include/linux/i2c-pnx.h10
-rw-r--r--include/linux/i2c/twl.h13
-rw-r--r--include/linux/if_ec.h68
-rw-r--r--include/linux/iio/buffer.h (renamed from drivers/staging/iio/buffer.h)4
-rw-r--r--include/linux/iio/consumer.h (renamed from drivers/staging/iio/consumer.h)2
-rw-r--r--include/linux/iio/driver.h (renamed from drivers/staging/iio/driver.h)0
-rw-r--r--include/linux/iio/events.h (renamed from drivers/staging/iio/events.h)2
-rw-r--r--include/linux/iio/iio.h (renamed from drivers/staging/iio/iio.h)101
-rw-r--r--include/linux/iio/kfifo_buf.h (renamed from drivers/staging/iio/kfifo_buf.h)4
-rw-r--r--include/linux/iio/machine.h (renamed from drivers/staging/iio/machine.h)0
-rw-r--r--include/linux/iio/sysfs.h (renamed from drivers/staging/iio/sysfs.h)0
-rw-r--r--include/linux/iio/trigger.h (renamed from drivers/staging/iio/trigger.h)8
-rw-r--r--include/linux/iio/trigger_consumer.h (renamed from drivers/staging/iio/trigger_consumer.h)0
-rw-r--r--include/linux/iio/types.h (renamed from drivers/staging/iio/types.h)2
-rw-r--r--include/linux/interrupt.h8
-rw-r--r--include/linux/ioport.h7
-rw-r--r--include/linux/irq.h5
-rw-r--r--include/linux/isdn.h26
-rw-r--r--include/linux/kernel.h13
-rw-r--r--include/linux/key.h11
-rw-r--r--include/linux/keyctl.h1
-rw-r--r--include/linux/libata.h1
-rw-r--r--include/linux/lockdep.h18
-rw-r--r--include/linux/lsm_audit.h6
-rw-r--r--include/linux/mei.h (renamed from drivers/staging/mei/mei.h)0
-rw-r--r--include/linux/mfd/abx500.h5
-rw-r--r--include/linux/mfd/abx500/ab5500.h140
-rw-r--r--include/linux/mfd/asic3.h1
-rw-r--r--include/linux/mfd/da9052/da9052.h1
-rw-r--r--include/linux/mfd/db5500-prcmu.h105
-rw-r--r--include/linux/mfd/dbx500-prcmu.h242
-rw-r--r--include/linux/mfd/max8997.h23
-rw-r--r--include/linux/mfd/mc13xxx.h11
-rw-r--r--include/linux/mfd/palmas.h2620
-rw-r--r--include/linux/mfd/rc5t583.h29
-rw-r--r--include/linux/mfd/s5m87xx/s5m-core.h1
-rw-r--r--include/linux/mfd/s5m87xx/s5m-pmic.h29
-rw-r--r--include/linux/mfd/tps65090.h13
-rw-r--r--include/linux/mfd/tps6586x.h1
-rw-r--r--include/linux/mfd/wm831x/pdata.h2
-rw-r--r--include/linux/mfd/wm8994/core.h12
-rw-r--r--include/linux/mlx4/device.h8
-rw-r--r--include/linux/mlx4/qp.h3
-rw-r--r--include/linux/mm.h6
-rw-r--r--include/linux/mmzone.h2
-rw-r--r--include/linux/mod_devicetable.h4
-rw-r--r--include/linux/moduleparam.h3
-rw-r--r--include/linux/mtd/ubi.h31
-rw-r--r--include/linux/netdevice.h2
-rw-r--r--include/linux/of.h51
-rw-r--r--include/linux/of_serial.h17
-rw-r--r--include/linux/pci.h9
-rw-r--r--include/linux/percpu.h54
-rw-r--r--include/linux/perf_event.h5
-rw-r--r--include/linux/pinctrl/consumer.h44
-rw-r--r--include/linux/pinctrl/machine.h7
-rw-r--r--include/linux/pinctrl/pinconf.h6
-rw-r--r--include/linux/pinctrl/pinctrl-state.h13
-rw-r--r--include/linux/pinctrl/pinctrl.h22
-rw-r--r--include/linux/pinctrl/pinmux.h9
-rw-r--r--include/linux/platform_data/at91_adc.h61
-rw-r--r--include/linux/platform_data/ehci-sh.h28
-rw-r--r--include/linux/platform_data/emif_plat.h128
-rw-r--r--include/linux/platform_data/gpio-em.h10
-rw-r--r--include/linux/platform_data/ina2xx.h19
-rw-r--r--include/linux/platform_data/s3c-hsotg.h (renamed from arch/arm/plat-samsung/include/plat/udc-hs.h)5
-rw-r--r--include/linux/platform_data/tegra_usb.h1
-rw-r--r--include/linux/pm.h2
-rw-r--r--include/linux/pm_domain.h13
-rw-r--r--include/linux/pm_runtime.h3
-rw-r--r--include/linux/pm_wakeup.h15
-rw-r--r--include/linux/prctl.h15
-rw-r--r--include/linux/printk.h13
-rw-r--r--include/linux/pstore_ram.h (renamed from drivers/staging/android/persistent_ram.h)30
-rw-r--r--include/linux/ptrace.h5
-rw-r--r--include/linux/raid/md_p.h15
-rw-r--r--include/linux/raid/pq.h18
-rw-r--r--include/linux/ramoops.h17
-rw-r--r--include/linux/rational.h2
-rw-r--r--include/linux/rculist.h40
-rw-r--r--include/linux/rcupdate.h20
-rw-r--r--include/linux/rcutiny.h11
-rw-r--r--include/linux/rcutree.h19
-rw-r--r--include/linux/regmap.h44
-rw-r--r--include/linux/regulator/driver.h73
-rw-r--r--include/linux/regulator/fixed.h7
-rw-r--r--include/linux/regulator/of_regulator.h18
-rw-r--r--include/linux/regulator/tps62360.h6
-rw-r--r--include/linux/regulator/tps65090-regulator.h50
-rw-r--r--include/linux/res_counter.h2
-rw-r--r--include/linux/ring_buffer.h6
-rw-r--r--include/linux/sched.h63
-rw-r--r--include/linux/seccomp.h107
-rw-r--r--include/linux/security.h14
-rw-r--r--include/linux/serial_8250.h2
-rw-r--r--include/linux/serial_core.h5
-rw-r--r--include/linux/serial_sci.h2
-rw-r--r--include/linux/sh_clk.h34
-rw-r--r--include/linux/sh_intc.h1
-rw-r--r--include/linux/skbuff.h47
-rw-r--r--include/linux/smp.h6
-rw-r--r--include/linux/spi/eeprom.h10
-rw-r--r--include/linux/srcu.h48
-rw-r--r--include/linux/suspend.h14
-rw-r--r--include/linux/sysfs.h12
-rw-r--r--include/linux/tcp.h2
-rw-r--r--include/linux/thread_info.h6
-rw-r--r--include/linux/ti_wilink_st.h2
-rw-r--r--include/linux/topology.h46
-rw-r--r--include/linux/tty.h23
-rw-r--r--include/linux/tty_ldisc.h2
-rw-r--r--include/linux/usb.h79
-rw-r--r--include/linux/usb/ch11.h2
-rw-r--r--include/linux/usb/ch9.h58
-rw-r--r--include/linux/usb/chipidea.h28
-rw-r--r--include/linux/usb/composite.h6
-rw-r--r--include/linux/usb/functionfs.h4
-rw-r--r--include/linux/usb/gpio_vbus.h2
-rw-r--r--include/linux/usb/hcd.h32
-rw-r--r--include/linux/usb/isp1301.h80
-rw-r--r--include/linux/usb/langwell_udc.h310
-rw-r--r--include/linux/usb/serial.h34
-rw-r--r--include/linux/uuid.h4
-rw-r--r--include/linux/virtio_config.h11
-rw-r--r--include/linux/vme.h (renamed from drivers/staging/vme/vme.h)0
-rw-r--r--include/linux/vt_kern.h1
-rw-r--r--include/memory/jedec_ddr.h175
-rw-r--r--include/mtd/ubi-user.h34
-rw-r--r--include/net/addrconf.h18
-rw-r--r--include/net/inet_frag.h3
-rw-r--r--include/net/ip6_route.h2
-rw-r--r--include/net/ipv6.h34
-rw-r--r--include/net/lapb.h6
-rw-r--r--include/net/rawv6.h2
-rw-r--r--include/net/sock.h12
-rw-r--r--include/net/tcp_memcontrol.h4
-rw-r--r--include/rdma/ib_mad.h2
-rw-r--r--include/rdma/ib_verbs.h4
-rw-r--r--include/scsi/iscsi_proto.h2
-rw-r--r--include/scsi/sas.h1
-rw-r--r--include/sound/asound.h14
-rw-r--r--include/sound/asoundef.h41
-rw-r--r--include/sound/cs42l52.h36
-rw-r--r--include/sound/max98095.h12
-rw-r--r--include/sound/sh_fsi.h18
-rw-r--r--include/sound/simple_card.h38
-rw-r--r--include/sound/soc-dai.h4
-rw-r--r--include/sound/soc-dapm.h28
-rw-r--r--include/sound/soc-dpcm.h138
-rw-r--r--include/sound/soc.h118
-rw-r--r--include/target/target_core_backend.h16
-rw-r--r--include/target/target_core_base.h59
-rw-r--r--include/target/target_core_fabric.h11
-rw-r--r--include/trace/events/asoc.h80
-rw-r--r--include/trace/events/power.h34
-rw-r--r--include/trace/events/rcu.h2
-rw-r--r--include/trace/events/workqueue.h2
-rw-r--r--include/video/omap-panel-nokia-dsi.h3
-rw-r--r--include/video/omap-panel-tfp410.h (renamed from include/video/omap-panel-dvi.h)18
-rw-r--r--include/video/omapdss.h28
-rw-r--r--include/video/vga.h22
-rw-r--r--init/Kconfig67
-rw-r--r--init/Makefile4
-rw-r--r--init/init_task.c (renamed from arch/alpha/kernel/init_task.c)17
-rw-r--r--init/main.c40
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/auditsc.c8
-rw-r--r--kernel/cgroup.c564
-rw-r--r--kernel/cgroup_freezer.c11
-rw-r--r--kernel/cpu.c13
-rw-r--r--kernel/cpuset.c31
-rw-r--r--kernel/events/core.c11
-rw-r--r--kernel/extable.c8
-rw-r--r--kernel/fork.c74
-rw-r--r--kernel/hung_task.c4
-rw-r--r--kernel/irq/chip.c4
-rw-r--r--kernel/irq/manage.c52
-rw-r--r--kernel/irq/pm.c7
-rw-r--r--kernel/irq/resend.c7
-rw-r--r--kernel/module.c2
-rw-r--r--kernel/params.c62
-rw-r--r--kernel/power/Kconfig27
-rw-r--r--kernel/power/Makefile2
-rw-r--r--kernel/power/autosleep.c127
-rw-r--r--kernel/power/hibernate.c13
-rw-r--r--kernel/power/main.c160
-rw-r--r--kernel/power/power.h27
-rw-r--r--kernel/power/swap.c62
-rw-r--r--kernel/power/wakelock.c259
-rw-r--r--kernel/printk.c1390
-rw-r--r--kernel/rcupdate.c28
-rw-r--r--kernel/rcutiny_plugin.h16
-rw-r--r--kernel/rcutorture.c257
-rw-r--r--kernel/rcutree.c332
-rw-r--r--kernel/rcutree.h23
-rw-r--r--kernel/rcutree_plugin.h154
-rw-r--r--kernel/rcutree_trace.c4
-rw-r--r--kernel/res_counter.c71
-rw-r--r--kernel/sched/Makefile2
-rw-r--r--kernel/sched/core.c441
-rw-r--r--kernel/sched/debug.c12
-rw-r--r--kernel/sched/fair.c462
-rw-r--r--kernel/sched/idle_task.c2
-rw-r--r--kernel/sched/rt.c56
-rw-r--r--kernel/sched/sched.h8
-rw-r--r--kernel/seccomp.c458
-rw-r--r--kernel/semaphore.c2
-rw-r--r--kernel/signal.c9
-rw-r--r--kernel/smp.c27
-rw-r--r--kernel/smpboot.c62
-rw-r--r--kernel/smpboot.h18
-rw-r--r--kernel/srcu.c548
-rw-r--r--kernel/sys.c12
-rw-r--r--kernel/time/alarmtimer.c4
-rw-r--r--kernel/timer.c12
-rw-r--r--kernel/trace/Kconfig3
-rw-r--r--kernel/trace/Makefile1
-rw-r--r--kernel/trace/ftrace.c242
-rw-r--r--kernel/trace/ring_buffer.c585
-rw-r--r--kernel/trace/trace.c503
-rw-r--r--kernel/trace/trace.h4
-rw-r--r--kernel/trace/trace_events.c5
-rw-r--r--kernel/trace/trace_export.c1
-rw-r--r--kernel/trace/trace_printk.c4
-rw-r--r--kernel/trace/trace_workqueue.c300
-rw-r--r--kernel/workqueue.c21
-rw-r--r--lib/Kconfig8
-rw-r--r--lib/Kconfig.debug42
-rw-r--r--lib/Makefile2
-rw-r--r--lib/debugobjects.c11
-rw-r--r--lib/dynamic_debug.c190
-rw-r--r--lib/jedec_ddr_data.c135
-rw-r--r--lib/kobject.c14
-rw-r--r--lib/list_debug.c22
-rw-r--r--lib/raid6/Makefile2
-rw-r--r--lib/raid6/algos.c127
-rw-r--r--lib/raid6/mktables.c25
-rw-r--r--lib/raid6/recov.c15
-rw-r--r--lib/raid6/recov_ssse3.c335
-rw-r--r--lib/raid6/test/Makefile2
-rw-r--r--lib/raid6/test/test.c32
-rw-r--r--lib/raid6/x86.h15
-rw-r--r--lib/rational.c2
-rw-r--r--mm/memcontrol.c117
-rw-r--r--mm/memory.c28
-rw-r--r--mm/mmap.c18
-rw-r--r--mm/page_alloc.c6
-rw-r--r--mm/slub.c2
-rw-r--r--net/9p/trans_virtio.c3
-rw-r--r--net/Kconfig8
-rw-r--r--net/Makefile1
-rw-r--r--net/atm/lec.h4
-rw-r--r--net/bluetooth/hidp/core.c27
-rw-r--r--net/bluetooth/rfcomm/tty.c137
-rw-r--r--net/caif/Kconfig2
-rw-r--r--net/compat.c8
-rw-r--r--net/core/dev.c3
-rw-r--r--net/core/filter.c6
-rw-r--r--net/core/netprio_cgroup.c30
-rw-r--r--net/core/pktgen.c4
-rw-r--r--net/core/skbuff.c168
-rw-r--r--net/core/sock.c10
-rw-r--r--net/dns_resolver/dns_key.c5
-rw-r--r--net/econet/Kconfig36
-rw-r--r--net/econet/Makefile7
-rw-r--r--net/econet/af_econet.c1172
-rw-r--r--net/ipv4/ip_fragment.c36
-rw-r--r--net/ipv4/ipconfig.c5
-rw-r--r--net/ipv4/route.c8
-rw-r--r--net/ipv4/tcp.c11
-rw-r--r--net/ipv4/tcp_input.c67
-rw-r--r--net/ipv4/tcp_memcontrol.c77
-rw-r--r--net/ipv4/udp.c8
-rw-r--r--net/ipv6/addrlabel.c24
-rw-r--r--net/ipv6/af_inet6.c10
-rw-r--r--net/ipv6/ah6.c6
-rw-r--r--net/ipv6/anycast.c12
-rw-r--r--net/ipv6/datagram.c4
-rw-r--r--net/ipv6/exthdrs.c69
-rw-r--r--net/ipv6/exthdrs_core.c2
-rw-r--r--net/ipv6/icmp.c14
-rw-r--r--net/ipv6/ip6_flowlabel.c24
-rw-r--r--net/ipv6/ip6_input.c9
-rw-r--r--net/ipv6/ip6_output.c13
-rw-r--r--net/ipv6/ip6_tunnel.c2
-rw-r--r--net/ipv6/mcast.c66
-rw-r--r--net/ipv6/ndisc.c4
-rw-r--r--net/ipv6/raw.c10
-rw-r--r--net/ipv6/reassembly.c35
-rw-r--r--net/ipv6/route.c8
-rw-r--r--net/ipv6/udp.c6
-rw-r--r--net/ipx/af_ipx.c4
-rw-r--r--net/lapb/lapb_iface.c22
-rw-r--r--net/lapb/lapb_in.c320
-rw-r--r--net/lapb/lapb_out.c38
-rw-r--r--net/lapb/lapb_subr.c28
-rw-r--r--net/lapb/lapb_timer.c32
-rw-r--r--net/netfilter/xt_TEE.c12
-rw-r--r--net/sched/cls_cgroup.c31
-rw-r--r--net/socket.c4
-rw-r--r--net/sunrpc/clnt.c4
-rw-r--r--net/sunrpc/rpc_pipe.c7
-rw-r--r--net/xfrm/xfrm_policy.c1
-rw-r--r--samples/Makefile2
-rw-r--r--samples/seccomp/Makefile32
-rw-r--r--samples/seccomp/bpf-direct.c190
-rw-r--r--samples/seccomp/bpf-fancy.c102
-rw-r--r--samples/seccomp/bpf-helper.c89
-rw-r--r--samples/seccomp/bpf-helper.h238
-rw-r--r--samples/seccomp/dropper.c68
-rw-r--r--scripts/.gitignore1
-rw-r--r--scripts/Makefile5
-rw-r--r--scripts/mod/file2alias.c5
-rw-r--r--scripts/sortextable.c322
-rw-r--r--scripts/sortextable.h191
-rw-r--r--security/Kconfig68
-rw-r--r--security/apparmor/audit.c11
-rw-r--r--security/apparmor/capability.c4
-rw-r--r--security/apparmor/domain.c35
-rw-r--r--security/apparmor/file.c2
-rw-r--r--security/apparmor/include/audit.h1
-rw-r--r--security/apparmor/ipc.c2
-rw-r--r--security/apparmor/lib.c2
-rw-r--r--security/apparmor/lsm.c6
-rw-r--r--security/apparmor/path.c2
-rw-r--r--security/apparmor/policy.c6
-rw-r--r--security/apparmor/policy_unpack.c2
-rw-r--r--security/apparmor/resource.c2
-rw-r--r--security/capability.c4
-rw-r--r--security/commoncap.c7
-rw-r--r--security/device_cgroup.c10
-rw-r--r--security/integrity/ima/ima_main.c4
-rw-r--r--security/keys/Kconfig71
-rw-r--r--security/keys/Makefile12
-rw-r--r--security/keys/compat.c3
-rw-r--r--security/keys/gc.c94
-rw-r--r--security/keys/internal.h15
-rw-r--r--security/keys/key.c25
-rw-r--r--security/keys/keyctl.c34
-rw-r--r--security/keys/keyring.c167
-rw-r--r--security/keys/permission.c43
-rw-r--r--security/keys/proc.c3
-rw-r--r--security/keys/process_keys.c2
-rw-r--r--security/lsm_audit.c15
-rw-r--r--security/security.c4
-rw-r--r--security/selinux/avc.c130
-rw-r--r--security/selinux/hooks.c268
-rw-r--r--security/selinux/include/avc.h100
-rw-r--r--security/selinux/include/security.h4
-rw-r--r--security/selinux/netif.c6
-rw-r--r--security/selinux/netnode.c6
-rw-r--r--security/selinux/netport.c6
-rw-r--r--security/selinux/selinuxfs.c11
-rw-r--r--security/selinux/ss/context.h20
-rw-r--r--security/selinux/ss/mls.c24
-rw-r--r--security/selinux/ss/policydb.c44
-rw-r--r--security/selinux/ss/policydb.h14
-rw-r--r--security/selinux/ss/services.c56
-rw-r--r--security/smack/smack.h59
-rw-r--r--security/smack/smack_access.c233
-rw-r--r--security/smack/smack_lsm.c243
-rw-r--r--security/smack/smackfs.c993
-rw-r--r--security/tomoyo/common.c26
-rw-r--r--security/tomoyo/common.h1
-rw-r--r--security/tomoyo/tomoyo.c6
-rw-r--r--security/yama/yama_lsm.c63
-rw-r--r--sound/atmel/ac97c.c2
-rw-r--r--sound/core/jack.c5
-rw-r--r--sound/core/pcm_lib.c18
-rw-r--r--sound/core/pcm_native.c12
-rw-r--r--sound/core/sound_oss.c6
-rw-r--r--sound/drivers/aloop.c62
-rw-r--r--sound/firewire/amdtp.c49
-rw-r--r--sound/firewire/amdtp.h29
-rw-r--r--sound/isa/als100.c2
-rw-r--r--sound/pci/Kconfig2
-rw-r--r--sound/pci/ad1889.c15
-rw-r--r--sound/pci/ali5451/ali5451.c15
-rw-r--r--sound/pci/als300.c15
-rw-r--r--sound/pci/als4000.c15
-rw-r--r--sound/pci/atiixp.c16
-rw-r--r--sound/pci/atiixp_modem.c16
-rw-r--r--sound/pci/au88x0/au88x0.c17
-rw-r--r--sound/pci/aw2/aw2-alsa.c23
-rw-r--r--sound/pci/azt3328.c23
-rw-r--r--sound/pci/bt87x.c19
-rw-r--r--sound/pci/ca0106/ca0106_main.c17
-rw-r--r--sound/pci/cmipci.c15
-rw-r--r--sound/pci/cs4281.c15
-rw-r--r--sound/pci/cs46xx/cs46xx.c15
-rw-r--r--sound/pci/cs5530.c16
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c15
-rw-r--r--sound/pci/ctxfi/xfi.c13
-rw-r--r--sound/pci/echoaudio/echoaudio.c22
-rw-r--r--sound/pci/emu10k1/emu10k1.c15
-rw-r--r--sound/pci/emu10k1/emu10k1x.c17
-rw-r--r--sound/pci/ens1370.c15
-rw-r--r--sound/pci/es1938.c15
-rw-r--r--sound/pci/es1968.c15
-rw-r--r--sound/pci/fm801.c15
-rw-r--r--sound/pci/hda/Makefile2
-rw-r--r--sound/pci/hda/hda_auto_parser.c760
-rw-r--r--sound/pci/hda/hda_auto_parser.h160
-rw-r--r--sound/pci/hda/hda_codec.c1027
-rw-r--r--sound/pci/hda/hda_codec.h15
-rw-r--r--sound/pci/hda/hda_intel.c57
-rw-r--r--sound/pci/hda/hda_jack.c1
-rw-r--r--sound/pci/hda/hda_jack.h2
-rw-r--r--sound/pci/hda/hda_local.h122
-rw-r--r--sound/pci/hda/patch_analog.c14
-rw-r--r--sound/pci/hda/patch_ca0110.c8
-rw-r--r--sound/pci/hda/patch_ca0132.c9
-rw-r--r--sound/pci/hda/patch_cirrus.c30
-rw-r--r--sound/pci/hda/patch_cmedia.c1
-rw-r--r--sound/pci/hda/patch_conexant.c186
-rw-r--r--sound/pci/hda/patch_hdmi.c4
-rw-r--r--sound/pci/hda/patch_realtek.c467
-rw-r--r--sound/pci/hda/patch_sigmatel.c120
-rw-r--r--sound/pci/hda/patch_via.c33
-rw-r--r--sound/pci/ice1712/ice1712.c15
-rw-r--r--sound/pci/ice1712/ice1724.c15
-rw-r--r--sound/pci/intel8x0.c16
-rw-r--r--sound/pci/intel8x0m.c16
-rw-r--r--sound/pci/korg1212/korg1212.c15
-rw-r--r--sound/pci/lola/lola.c15
-rw-r--r--sound/pci/lx6464es/lx6464es.c17
-rw-r--r--sound/pci/maestro3.c15
-rw-r--r--sound/pci/mixart/mixart.c15
-rw-r--r--sound/pci/nm256/nm256.c16
-rw-r--r--sound/pci/oxygen/oxygen.c21
-rw-r--r--sound/pci/oxygen/virtuoso.c13
-rw-r--r--sound/pci/oxygen/xonar_dg.c7
-rw-r--r--sound/pci/pcxhr/pcxhr.c15
-rw-r--r--sound/pci/riptide/riptide.c3
-rw-r--r--sound/pci/rme32.c15
-rw-r--r--sound/pci/rme96.c15
-rw-r--r--sound/pci/rme9652/hdsp.c15
-rw-r--r--sound/pci/rme9652/hdspm.c16
-rw-r--r--sound/pci/rme9652/rme9652.c15
-rw-r--r--sound/pci/sis7019.c13
-rw-r--r--sound/pci/sonicvibes.c15
-rw-r--r--sound/pci/trident/trident.c15
-rw-r--r--sound/pci/via82xx.c15
-rw-r--r--sound/pci/via82xx_modem.c15
-rw-r--r--sound/pci/vx222/vx222.c15
-rw-r--r--sound/pci/ymfpci/ymfpci.c15
-rw-r--r--sound/sh/sh_dac_audio.c4
-rw-r--r--sound/soc/Kconfig5
-rw-r--r--sound/soc/Makefile3
-rw-r--r--sound/soc/blackfin/bf5xx-ssm2602.c37
-rw-r--r--sound/soc/codecs/Kconfig20
-rw-r--r--sound/soc/codecs/Makefile12
-rw-r--r--sound/soc/codecs/ac97.c6
-rw-r--r--sound/soc/codecs/ad1836.c4
-rw-r--r--sound/soc/codecs/ad193x.c4
-rw-r--r--sound/soc/codecs/adau1701.c3
-rw-r--r--sound/soc/codecs/ak4104.c3
-rw-r--r--sound/soc/codecs/ak4535.c3
-rw-r--r--sound/soc/codecs/ak4641.c113
-rw-r--r--sound/soc/codecs/alc5623.c23
-rw-r--r--sound/soc/codecs/alc5632.c31
-rw-r--r--sound/soc/codecs/cs4270.c11
-rw-r--r--sound/soc/codecs/cs4271.c3
-rw-r--r--sound/soc/codecs/cs42l51.c9
-rw-r--r--sound/soc/codecs/cs42l52.c1295
-rw-r--r--sound/soc/codecs/cs42l52.h274
-rw-r--r--sound/soc/codecs/cs42l73.c93
-rw-r--r--sound/soc/codecs/da7210.c379
-rw-r--r--sound/soc/codecs/jz4740.c3
-rw-r--r--sound/soc/codecs/lm49453.c1550
-rw-r--r--sound/soc/codecs/lm49453.h380
-rw-r--r--sound/soc/codecs/max98095.c158
-rw-r--r--sound/soc/codecs/max98095.h22
-rw-r--r--sound/soc/codecs/mc13783.c786
-rw-r--r--sound/soc/codecs/mc13783.h28
-rw-r--r--sound/soc/codecs/ml26124.c681
-rw-r--r--sound/soc/codecs/ml26124.h184
-rw-r--r--sound/soc/codecs/omap-hdmi.c69
-rw-r--r--sound/soc/codecs/rt5631.c110
-rw-r--r--sound/soc/codecs/sgtl5000.c33
-rw-r--r--sound/soc/codecs/ssm2602.c138
-rw-r--r--sound/soc/codecs/sta32x.c3
-rw-r--r--sound/soc/codecs/tlv320aic23.c13
-rw-r--r--sound/soc/codecs/tlv320aic26.c3
-rw-r--r--sound/soc/codecs/tlv320aic3x.c21
-rw-r--r--sound/soc/codecs/tlv320dac33.c35
-rw-r--r--sound/soc/codecs/twl4030.c18
-rw-r--r--sound/soc/codecs/twl6040.c450
-rw-r--r--sound/soc/codecs/uda134x.c6
-rw-r--r--sound/soc/codecs/uda1380.c6
-rw-r--r--sound/soc/codecs/wl1273.c6
-rw-r--r--sound/soc/codecs/wm1250-ev1.c65
-rw-r--r--sound/soc/codecs/wm5100-tables.c125
-rw-r--r--sound/soc/codecs/wm5100.c47
-rw-r--r--sound/soc/codecs/wm5100.h159
-rw-r--r--sound/soc/codecs/wm8350.c187
-rw-r--r--sound/soc/codecs/wm8400.c135
-rw-r--r--sound/soc/codecs/wm8510.c3
-rw-r--r--sound/soc/codecs/wm8523.c3
-rw-r--r--sound/soc/codecs/wm8728.c3
-rw-r--r--sound/soc/codecs/wm8731.c37
-rw-r--r--sound/soc/codecs/wm8737.c3
-rw-r--r--sound/soc/codecs/wm8741.c3
-rw-r--r--sound/soc/codecs/wm8750.c3
-rw-r--r--sound/soc/codecs/wm8753.c6
-rw-r--r--sound/soc/codecs/wm8900.c3
-rw-r--r--sound/soc/codecs/wm8903.c3
-rw-r--r--sound/soc/codecs/wm8940.c3
-rw-r--r--sound/soc/codecs/wm8960.c3
-rw-r--r--sound/soc/codecs/wm8962.c18
-rw-r--r--sound/soc/codecs/wm8971.c3
-rw-r--r--sound/soc/codecs/wm8978.c3
-rw-r--r--sound/soc/codecs/wm8988.c3
-rw-r--r--sound/soc/codecs/wm8990.c3
-rw-r--r--sound/soc/codecs/wm8993.c86
-rw-r--r--sound/soc/codecs/wm8994.c290
-rw-r--r--sound/soc/codecs/wm8994.h3
-rw-r--r--sound/soc/codecs/wm8996.c12
-rw-r--r--sound/soc/codecs/wm9081.c5
-rw-r--r--sound/soc/codecs/wm9705.c6
-rw-r--r--sound/soc/codecs/wm9712.c10
-rw-r--r--sound/soc/codecs/wm_hubs.c220
-rw-r--r--sound/soc/codecs/wm_hubs.h12
-rw-r--r--sound/soc/ep93xx/ep93xx-ac97.c74
-rw-r--r--sound/soc/ep93xx/ep93xx-i2s.c49
-rw-r--r--sound/soc/fsl/Kconfig129
-rw-r--r--sound/soc/fsl/Makefile31
-rw-r--r--sound/soc/fsl/eukrea-tlv320.c (renamed from sound/soc/imx/eukrea-tlv320.c)2
-rw-r--r--sound/soc/fsl/fsl_ssi.c167
-rw-r--r--sound/soc/fsl/fsl_utils.c91
-rw-r--r--sound/soc/fsl/fsl_utils.h26
-rw-r--r--sound/soc/fsl/imx-audmux.c (renamed from sound/soc/imx/imx-audmux.c)0
-rw-r--r--sound/soc/fsl/imx-audmux.h (renamed from sound/soc/imx/imx-audmux.h)0
-rw-r--r--sound/soc/fsl/imx-mc13783.c156
-rw-r--r--sound/soc/fsl/imx-pcm-dma.c (renamed from sound/soc/imx/imx-pcm-dma-mx2.c)3
-rw-r--r--sound/soc/fsl/imx-pcm-fiq.c (renamed from sound/soc/imx/imx-pcm-fiq.c)0
-rw-r--r--sound/soc/fsl/imx-pcm.c (renamed from sound/soc/imx/imx-pcm.c)0
-rw-r--r--sound/soc/fsl/imx-pcm.h (renamed from sound/soc/imx/imx-pcm.h)1
-rw-r--r--sound/soc/fsl/imx-sgtl5000.c221
-rw-r--r--sound/soc/fsl/imx-ssi.c (renamed from sound/soc/imx/imx-ssi.c)2
-rw-r--r--sound/soc/fsl/imx-ssi.h (renamed from sound/soc/imx/imx-ssi.h)0
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c166
-rw-r--r--sound/soc/fsl/mx27vis-aic32x4.c (renamed from sound/soc/imx/mx27vis-aic32x4.c)0
-rw-r--r--sound/soc/fsl/p1022_ds.c158
-rw-r--r--sound/soc/fsl/phycore-ac97.c (renamed from sound/soc/imx/phycore-ac97.c)0
-rw-r--r--sound/soc/fsl/wm1133-ev1.c (renamed from sound/soc/imx/wm1133-ev1.c)0
-rw-r--r--sound/soc/generic/Kconfig4
-rw-r--r--sound/soc/generic/Makefile3
-rw-r--r--sound/soc/generic/simple-card.c114
-rw-r--r--sound/soc/imx/Kconfig79
-rw-r--r--sound/soc/imx/Makefile22
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c4
-rw-r--r--sound/soc/mxs/mxs-pcm.c24
-rw-r--r--sound/soc/mxs/mxs-pcm.h3
-rw-r--r--sound/soc/mxs/mxs-saif.c100
-rw-r--r--sound/soc/mxs/mxs-saif.h1
-rw-r--r--sound/soc/mxs/mxs-sgtl5000.c50
-rw-r--r--sound/soc/omap/Kconfig1
-rw-r--r--sound/soc/pxa/pxa-ssp.c28
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c4
-rw-r--r--sound/soc/samsung/littlemill.c102
-rw-r--r--sound/soc/samsung/lowland.c75
-rw-r--r--sound/soc/samsung/speyside.c33
-rw-r--r--sound/soc/sh/Kconfig24
-rw-r--r--sound/soc/sh/Makefile6
-rw-r--r--sound/soc/sh/fsi-ak4642.c108
-rw-r--r--sound/soc/sh/fsi-da7210.c81
-rw-r--r--sound/soc/sh/fsi-hdmi.c118
-rw-r--r--sound/soc/sh/fsi.c224
-rw-r--r--sound/soc/soc-core.c690
-rw-r--r--sound/soc/soc-dapm.c562
-rw-r--r--sound/soc/soc-jack.c5
-rw-r--r--sound/soc/soc-pcm.c1718
-rw-r--r--sound/soc/tegra/Kconfig68
-rw-r--r--sound/soc/tegra/Makefile20
-rw-r--r--sound/soc/tegra/tegra20_das.c233
-rw-r--r--sound/soc/tegra/tegra20_das.h134
-rw-r--r--sound/soc/tegra/tegra20_i2s.c494
-rw-r--r--sound/soc/tegra/tegra20_i2s.h164
-rw-r--r--sound/soc/tegra/tegra20_spdif.c404
-rw-r--r--sound/soc/tegra/tegra20_spdif.h471
-rw-r--r--sound/soc/tegra/tegra30_ahub.c631
-rw-r--r--sound/soc/tegra/tegra30_ahub.h483
-rw-r--r--sound/soc/tegra/tegra30_i2s.c536
-rw-r--r--sound/soc/tegra/tegra30_i2s.h242
-rw-r--r--sound/soc/tegra/tegra_alc5632.c48
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.c37
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.h9
-rw-r--r--sound/soc/tegra/tegra_das.c261
-rw-r--r--sound/soc/tegra/tegra_das.h135
-rw-r--r--sound/soc/tegra/tegra_i2s.c459
-rw-r--r--sound/soc/tegra/tegra_i2s.h166
-rw-r--r--sound/soc/tegra/tegra_pcm.c28
-rw-r--r--sound/soc/tegra/tegra_pcm.h5
-rw-r--r--sound/soc/tegra/tegra_spdif.c364
-rw-r--r--sound/soc/tegra/tegra_spdif.h473
-rw-r--r--sound/soc/tegra/tegra_wm8753.c224
-rw-r--r--sound/soc/tegra/tegra_wm8903.c29
-rw-r--r--sound/soc/tegra/trimslice.c41
-rw-r--r--sound/soc/ux500/Kconfig14
-rw-r--r--sound/soc/ux500/Makefile4
-rw-r--r--sound/soc/ux500/ux500_msp_dai.c843
-rw-r--r--sound/soc/ux500/ux500_msp_dai.h79
-rw-r--r--sound/soc/ux500/ux500_msp_i2s.c742
-rw-r--r--sound/soc/ux500/ux500_msp_i2s.h553
-rw-r--r--sound/sound_core.c2
-rw-r--r--sound/usb/card.c10
-rw-r--r--sound/usb/card.h86
-rw-r--r--sound/usb/endpoint.c1609
-rw-r--r--sound/usb/endpoint.h32
-rw-r--r--sound/usb/mixer.c50
-rw-r--r--sound/usb/mixer.h3
-rw-r--r--sound/usb/mixer_maps.c13
-rw-r--r--sound/usb/mixer_quirks.c472
-rw-r--r--sound/usb/pcm.c453
-rw-r--r--sound/usb/proc.c38
-rw-r--r--sound/usb/stream.c31
-rw-r--r--sound/usb/usbaudio.h2
-rw-r--r--tools/Makefile77
-rw-r--r--tools/lib/traceevent/Makefile303
-rw-r--r--tools/lib/traceevent/event-parse.c5065
-rw-r--r--tools/lib/traceevent/event-parse.h804
-rw-r--r--tools/lib/traceevent/event-utils.h80
-rw-r--r--tools/lib/traceevent/parse-filter.c2262
-rw-r--r--tools/lib/traceevent/parse-utils.c110
-rw-r--r--tools/lib/traceevent/trace-seq.c200
-rw-r--r--tools/perf/Documentation/perf-evlist.txt8
-rw-r--r--tools/perf/Documentation/perf-record.txt2
-rw-r--r--tools/perf/Documentation/perfconfig.example1
-rw-r--r--tools/perf/Makefile136
-rw-r--r--tools/perf/builtin-buildid-list.c6
-rw-r--r--tools/perf/builtin-evlist.c103
-rw-r--r--tools/perf/builtin-inject.c5
-rw-r--r--tools/perf/builtin-kmem.c6
-rw-r--r--tools/perf/builtin-lock.c26
-rw-r--r--tools/perf/builtin-record.c69
-rw-r--r--tools/perf/builtin-report.c21
-rw-r--r--tools/perf/builtin-sched.c42
-rw-r--r--tools/perf/builtin-script.c2
-rw-r--r--tools/perf/builtin-stat.c124
-rw-r--r--tools/perf/builtin-test.c565
-rw-r--r--tools/perf/builtin-top.c59
-rw-r--r--tools/perf/perf.h8
-rw-r--r--tools/perf/ui/browser.c (renamed from tools/perf/util/ui/browser.c)116
-rw-r--r--tools/perf/ui/browser.h (renamed from tools/perf/util/ui/browser.h)9
-rw-r--r--tools/perf/ui/browsers/annotate.c867
-rw-r--r--tools/perf/ui/browsers/hists.c (renamed from tools/perf/util/ui/browsers/hists.c)26
-rw-r--r--tools/perf/ui/browsers/map.c (renamed from tools/perf/util/ui/browsers/map.c)6
-rw-r--r--tools/perf/ui/browsers/map.h (renamed from tools/perf/util/ui/browsers/map.h)0
-rw-r--r--tools/perf/ui/gtk/browser.c (renamed from tools/perf/util/gtk/browser.c)31
-rw-r--r--tools/perf/ui/gtk/gtk.h (renamed from tools/perf/util/gtk/gtk.h)0
-rw-r--r--tools/perf/ui/gtk/setup.c12
-rw-r--r--tools/perf/ui/helpline.c (renamed from tools/perf/util/ui/helpline.c)0
-rw-r--r--tools/perf/ui/helpline.h (renamed from tools/perf/util/ui/helpline.h)0
-rw-r--r--tools/perf/ui/keysyms.h (renamed from tools/perf/util/ui/keysyms.h)0
-rw-r--r--tools/perf/ui/libslang.h (renamed from tools/perf/util/ui/libslang.h)0
-rw-r--r--tools/perf/ui/progress.c (renamed from tools/perf/util/ui/progress.c)0
-rw-r--r--tools/perf/ui/progress.h (renamed from tools/perf/util/ui/progress.h)0
-rw-r--r--tools/perf/ui/setup.c45
-rw-r--r--tools/perf/ui/tui/setup.c (renamed from tools/perf/util/ui/setup.c)77
-rw-r--r--tools/perf/ui/ui.h (renamed from tools/perf/util/ui/ui.h)0
-rw-r--r--tools/perf/ui/util.c (renamed from tools/perf/util/ui/util.c)0
-rw-r--r--tools/perf/ui/util.h (renamed from tools/perf/util/ui/util.h)0
-rw-r--r--tools/perf/util/annotate.c599
-rw-r--r--tools/perf/util/annotate.h67
-rw-r--r--tools/perf/util/build-id.c2
-rw-r--r--tools/perf/util/cache.h24
-rw-r--r--tools/perf/util/debug.c1
-rw-r--r--tools/perf/util/debug.h2
-rw-r--r--tools/perf/util/evlist.c16
-rw-r--r--tools/perf/util/evlist.h4
-rw-r--r--tools/perf/util/evsel.c21
-rw-r--r--tools/perf/util/header.c29
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/hist.c2
-rw-r--r--tools/perf/util/hist.h2
-rw-r--r--tools/perf/util/parse-events-test.c625
-rw-r--r--tools/perf/util/parse-events.c114
-rw-r--r--tools/perf/util/parse-events.h43
-rw-r--r--tools/perf/util/parse-events.l26
-rw-r--r--tools/perf/util/parse-events.y93
-rw-r--r--tools/perf/util/pmu.c74
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c16
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c16
-rw-r--r--tools/perf/util/session.c96
-rw-r--r--tools/perf/util/symbol.h5
-rw-r--r--tools/perf/util/target.c142
-rw-r--r--tools/perf/util/target.h65
-rw-r--r--tools/perf/util/thread_map.h2
-rw-r--r--tools/perf/util/top.c19
-rw-r--r--tools/perf/util/top.h6
-rw-r--r--tools/perf/util/trace-event-info.c4
-rw-r--r--tools/perf/util/trace-event-parse.c3142
-rw-r--r--tools/perf/util/trace-event-read.c44
-rw-r--r--tools/perf/util/trace-event.h269
-rw-r--r--tools/perf/util/types.h5
-rw-r--r--tools/perf/util/ui/browsers/annotate.c433
-rw-r--r--tools/perf/util/usage.c38
-rw-r--r--tools/perf/util/util.c10
-rw-r--r--tools/perf/util/util.h5
-rw-r--r--tools/power/cpupower/man/cpupower-set.19
-rw-r--r--tools/power/cpupower/utils/helpers/sysfs.c35
-rw-r--r--tools/scripts/Makefile.include58
-rw-r--r--tools/testing/ktest/examples/README32
-rw-r--r--tools/testing/ktest/examples/crosstests.conf260
-rw-r--r--tools/testing/ktest/examples/include/bisect.conf90
-rw-r--r--tools/testing/ktest/examples/include/defaults.conf157
-rw-r--r--tools/testing/ktest/examples/include/min-config.conf60
-rw-r--r--tools/testing/ktest/examples/include/patchcheck.conf74
-rw-r--r--tools/testing/ktest/examples/include/tests.conf74
-rw-r--r--tools/testing/ktest/examples/kvm.conf88
-rw-r--r--tools/testing/ktest/examples/snowball.conf53
-rw-r--r--tools/testing/ktest/examples/test.conf62
-rwxr-xr-xtools/testing/ktest/ktest.pl36
-rw-r--r--tools/testing/ktest/sample.conf18
-rw-r--r--tools/usb/ffs-test.c2
-rw-r--r--tools/usb/testusb.c5
4349 files changed, 250073 insertions, 145013 deletions
diff --git a/CREDITS b/CREDITS
index 370b4c7da39b..d8fe12a9421f 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3814,8 +3814,8 @@ D: INFO-SHEET, former maintainer
D: Author of the longest-living linux bug
N: Jonathan Woithe
-E: jwoithe@physics.adelaide.edu.au
-W: http://www.physics.adelaide.edu.au/~jwoithe
+E: jwoithe@just42.net
+W: http:/www.just42.net/jwoithe
D: ALS-007 sound card extensions to Sound Blaster driver
S: 20 Jordan St
S: Valley View, SA 5093
diff --git a/Documentation/ABI/testing/debugfs-pfo-nx-crypto b/Documentation/ABI/testing/debugfs-pfo-nx-crypto
new file mode 100644
index 000000000000..685d5a448423
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-pfo-nx-crypto
@@ -0,0 +1,45 @@
+What: /sys/kernel/debug/nx-crypto/*
+Date: March 2012
+KernelVersion: 3.4
+Contact: Kent Yoder <key@linux.vnet.ibm.com>
+Description:
+
+ These debugfs interfaces are built by the nx-crypto driver, built in
+arch/powerpc/crypto/nx.
+
+Error Detection
+===============
+
+errors:
+- A u32 providing a total count of errors since the driver was loaded. The
+only errors counted here are those returned from the hcall, H_COP_OP.
+
+last_error:
+- The most recent non-zero return code from the H_COP_OP hcall. -EBUSY is not
+recorded here (the hcall will retry until -EBUSY goes away).
+
+last_error_pid:
+- The process ID of the process who received the most recent error from the
+hcall.
+
+Device Use
+==========
+
+aes_bytes:
+- The total number of bytes encrypted using AES in any of the driver's
+supported modes.
+
+aes_ops:
+- The total number of AES operations submitted to the hardware.
+
+sha256_bytes:
+- The total number of bytes hashed by the hardware using SHA-256.
+
+sha256_ops:
+- The total number of SHA-256 operations submitted to the hardware.
+
+sha512_bytes:
+- The total number of bytes hashed by the hardware using SHA-512.
+
+sha512_ops:
+- The total number of SHA-512 operations submitted to the hardware.
diff --git a/Documentation/ABI/testing/dev-kmsg b/Documentation/ABI/testing/dev-kmsg
new file mode 100644
index 000000000000..281ecc5f9709
--- /dev/null
+++ b/Documentation/ABI/testing/dev-kmsg
@@ -0,0 +1,90 @@
+What: /dev/kmsg
+Date: Mai 2012
+KernelVersion: 3.5
+Contact: Kay Sievers <kay@vrfy.org>
+Description: The /dev/kmsg character device node provides userspace access
+ to the kernel's printk buffer.
+
+ Injecting messages:
+ Every write() to the opened device node places a log entry in
+ the kernel's printk buffer.
+
+ The logged line can be prefixed with a <N> syslog prefix, which
+ carries the syslog priority and facility. The single decimal
+ prefix number is composed of the 3 lowest bits being the syslog
+ priority and the higher bits the syslog facility number.
+
+ If no prefix is given, the priority number is the default kernel
+ log priority and the facility number is set to LOG_USER (1). It
+ is not possible to inject messages from userspace with the
+ facility number LOG_KERN (0), to make sure that the origin of
+ the messages can always be reliably determined.
+
+ Accessing the buffer:
+ Every read() from the opened device node receives one record
+ of the kernel's printk buffer.
+
+ The first read() directly following an open() always returns
+ first message in the buffer; there is no kernel-internal
+ persistent state; many readers can concurrently open the device
+ and read from it, without affecting other readers.
+
+ Every read() will receive the next available record. If no more
+ records are available read() will block, or if O_NONBLOCK is
+ used -EAGAIN returned.
+
+ Messages in the record ring buffer get overwritten as whole,
+ there are never partial messages received by read().
+
+ In case messages get overwritten in the circular buffer while
+ the device is kept open, the next read() will return -EPIPE,
+ and the seek position be updated to the next available record.
+ Subsequent reads() will return available records again.
+
+ Unlike the classic syslog() interface, the 64 bit record
+ sequence numbers allow to calculate the amount of lost
+ messages, in case the buffer gets overwritten. And they allow
+ to reconnect to the buffer and reconstruct the read position
+ if needed, without limiting the interface to a single reader.
+
+ The device supports seek with the following parameters:
+ SEEK_SET, 0
+ seek to the first entry in the buffer
+ SEEK_END, 0
+ seek after the last entry in the buffer
+ SEEK_DATA, 0
+ seek after the last record available at the time
+ the last SYSLOG_ACTION_CLEAR was issued.
+
+ The output format consists of a prefix carrying the syslog
+ prefix including priority and facility, the 64 bit message
+ sequence number and the monotonic timestamp in microseconds.
+ The values are separated by a ','. Future extensions might
+ add more comma separated values before the terminating ';'.
+ Unknown values should be gracefully ignored.
+
+ The human readable text string starts directly after the ';'
+ and is terminated by a '\n'. Untrusted values derived from
+ hardware or other facilities are printed, therefore
+ all non-printable characters in the log message are escaped
+ by "\x00" C-style hex encoding.
+
+ A line starting with ' ', is a continuation line, adding
+ key/value pairs to the log message, which provide the machine
+ readable context of the message, for reliable processing in
+ userspace.
+
+ Example:
+ 7,160,424069;pci_root PNP0A03:00: host bridge window [io 0x0000-0x0cf7] (ignored)
+ SUBSYSTEM=acpi
+ DEVICE=+acpi:PNP0A03:00
+ 6,339,5140900;NET: Registered protocol family 10
+ 30,340,5690716;udevd[80]: starting version 181
+
+ The DEVICE= key uniquely identifies devices the following way:
+ b12:8 - block dev_t
+ c127:3 - char dev_t
+ n8 - netdev ifindex
+ +sound:card0 - subsystem:devname
+
+Users: dmesg(1), userspace kernel log consumers
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 46a995d6d261..5bc8a476c15e 100644
--- a/drivers/staging/iio/Documentation/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -108,7 +108,7 @@ Description:
physically equivalent inputs when non differential readings are
separately available. In differential only parts, then all that
is required is a consistent labeling. Units after application
- of scale and offset are nanofarads..
+ of scale and offset are nanofarads.
What: /sys/bus/iio/devices/iio:deviceX/in_temp_raw
What: /sys/bus/iio/devices/iio:deviceX/in_tempX_raw
@@ -119,7 +119,7 @@ KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
Raw (unscaled no bias removal etc) temperature measurement.
- It an axis is specified it generally means that the temperature
+ If an axis is specified it generally means that the temperature
sensor is associated with one part of a compound device (e.g.
a gyroscope axis). Units after application of scale and offset
are milli degrees Celsuis.
@@ -232,7 +232,7 @@ Description:
If known for a device, scale to be applied to <type>Y[_name]_raw
post addition of <type>[Y][_name]_offset in order to obtain the
measured value in <type> units as specified in
- <type>[Y][_name]_raw documentation.. If shared across all in
+ <type>[Y][_name]_raw documentation. If shared across all in
channels then Y and <x|y|z> are not present and the value is
called <type>[Y][_name]_scale. The peak modifier means this
value is applied to <type>Y[_name]_peak_raw values.
@@ -243,6 +243,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias
+What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibbias
+What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
@@ -258,6 +260,8 @@ What /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibscale
+what /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale
+what /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
@@ -276,6 +280,13 @@ Description:
If a discrete set of scale values are available, they
are listed in this attribute.
+What /sys/bus/iio/devices/iio:deviceX/out_voltageY_hardwaregain
+KernelVersion: 2.6.35
+Contact: linux-iio@vger.kernel.org
+Description:
+ Hardware applied gain factor. If shared across all channels,
+ <type>_hardwaregain is used.
+
What: /sys/.../in_accel_filter_low_pass_3db_frequency
What: /sys/.../in_magn_filter_low_pass_3db_frequency
What: /sys/.../in_anglvel_filter_low_pass_3db_frequency
@@ -453,10 +464,14 @@ What: /sys/.../events/in_magn_z_raw_thresh_rising_value
What: /sys/.../events/in_magn_z_raw_thresh_falling_value
What: /sys/.../events/in_voltageY_supply_raw_thresh_rising_value
What: /sys/.../events/in_voltageY_supply_raw_thresh_falling_value
+What: /sys/.../events/in_voltageY_raw_thresh_rising_value
What: /sys/.../events/in_voltageY_raw_thresh_falling_value
-What: /sys/.../events/in_voltageY_raw_thresh_falling_value
-What: /sys/.../events/in_tempY_raw_thresh_falling_value
+What: /sys/.../events/in_tempY_raw_thresh_rising_value
What: /sys/.../events/in_tempY_raw_thresh_falling_value
+What: /sys/.../events/in_illuminance0_thresh_falling_value
+what: /sys/.../events/in_illuminance0_thresh_rising_value
+what: /sys/.../events/in_proximity0_thresh_falling_value
+what: /sys/.../events/in_proximity0_thresh_rising_value
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
@@ -490,9 +505,9 @@ What: /sys/.../events/in_magn_z_raw_roc_rising_value
What: /sys/.../events/in_magn_z_raw_roc_falling_value
What: /sys/.../events/in_voltageY_supply_raw_roc_rising_value
What: /sys/.../events/in_voltageY_supply_raw_roc_falling_value
+What: /sys/.../events/in_voltageY_raw_roc_rising_value
What: /sys/.../events/in_voltageY_raw_roc_falling_value
-What: /sys/.../events/in_voltageY_raw_roc_falling_value
-What: /sys/.../events/in_tempY_raw_roc_falling_value
+What: /sys/.../events/in_tempY_raw_roc_rising_value
What: /sys/.../events/in_tempY_raw_roc_falling_value
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
@@ -556,6 +571,8 @@ What: /sys/.../events/in_tempY_thresh_falling_period
What: /sys/.../events/in_tempY_roc_rising_period
What: /sys/.../events/in_tempY_roc_falling_period
What: /sys/.../events/in_accel_x&y&z_mag_falling_period
+What: /sys/.../events/in_intensity0_thresh_period
+What: /sys/.../events/in_proximity0_thresh_period
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
@@ -718,24 +735,3 @@ Contact: linux-iio@vger.kernel.org
Description:
This attribute is used to read the amount of quadrature error
present in the device at a given time.
-
-What: /sys/.../iio:deviceX/ac_excitation_en
-KernelVersion: 3.1.0
-Contact: linux-iio@vger.kernel.org
-Description:
- This attribute, if available, is used to enable the AC
- excitation mode found on some converters. In ac excitation mode,
- the polarity of the excitation voltage is reversed on
- alternate cycles, to eliminate DC errors.
-
-What: /sys/.../iio:deviceX/bridge_switch_en
-KernelVersion: 3.1.0
-Contact: linux-iio@vger.kernel.org
-Description:
- This attribute, if available, is used to close or open the
- bridge power down switch found on some converters.
- In bridge applications, such as strain gauges and load cells,
- the bridge itself consumes the majority of the current in the
- system. To minimize the current consumption of the system,
- the bridge can be disconnected (when it is not being used
- using the bridge_switch_en attribute.
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index 7c22a532fdfb..6df4e6f57560 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -135,6 +135,17 @@ Description:
for the device and attempt to bind to it. For example:
# echo "8086 10f5" > /sys/bus/usb/drivers/foo/new_id
+ Reading from this file will list all dynamically added
+ device IDs in the same format, with one entry per
+ line. For example:
+ # cat /sys/bus/usb/drivers/foo/new_id
+ 8086 10f5
+ dead beef 06
+ f00d cafe
+
+ The list will be truncated at PAGE_SIZE bytes due to
+ sysfs restrictions.
+
What: /sys/bus/usb-serial/drivers/.../new_id
Date: October 2011
Contact: linux-usb@vger.kernel.org
@@ -157,6 +168,10 @@ Description:
match the driver to the device. For example:
# echo "046d c315" > /sys/bus/usb/drivers/foo/remove_id
+ Reading from this file will list the dynamically added
+ device IDs, exactly like reading from the entry
+ "/sys/bus/usb/drivers/.../new_id"
+
What: /sys/bus/usb/device/.../avoid_reset_quirk
Date: December 2009
Contact: Oliver Neukum <oliver@neukum.org>
@@ -189,7 +204,7 @@ Contact: Matthew Garrett <mjg@redhat.com>
Description:
Some information about whether a given USB device is
physically fixed to the platform can be inferred from a
- combination of hub decriptor bits and platform-specific data
+ combination of hub descriptor bits and platform-specific data
such as ACPI. This file will read either "removable" or
"fixed" if the information is available, and "unknown"
- otherwise. \ No newline at end of file
+ otherwise.
diff --git a/Documentation/ABI/testing/sysfs-class-extcon b/Documentation/ABI/testing/sysfs-class-extcon
new file mode 100644
index 000000000000..20ab361bd8c6
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-extcon
@@ -0,0 +1,97 @@
+What: /sys/class/extcon/.../
+Date: February 2012
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+ Provide a place in sysfs for the extcon objects.
+ This allows accessing extcon specific variables.
+ The name of extcon object denoted as ... is the name given
+ with extcon_dev_register.
+
+ One extcon device denotes a single external connector
+ port. An external connector may have multiple cables
+ attached simultaneously. Many of docks, cradles, and
+ accessory cables have such capability. For example,
+ the 30-pin port of Nuri board (/arch/arm/mach-exynos)
+ may have both HDMI and Charger attached, or analog audio,
+ video, and USB cables attached simulteneously.
+
+ If there are cables mutually exclusive with each other,
+ such binary relations may be expressed with extcon_dev's
+ mutually_exclusive array.
+
+What: /sys/class/extcon/.../name
+Date: February 2012
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+ The /sys/class/extcon/.../name shows the name of the extcon
+ object. If the extcon object has an optional callback
+ "show_name" defined, the callback will provide the name with
+ this sysfs node.
+
+What: /sys/class/extcon/.../state
+Date: February 2012
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+ The /sys/class/extcon/.../state shows and stores the cable
+ attach/detach information of the corresponding extcon object.
+ If the extcon object has an optional callback "show_state"
+ defined, the showing function is overriden with the optional
+ callback.
+
+ If the default callback for showing function is used, the
+ format is like this:
+ # cat state
+ USB_OTG=1
+ HDMI=0
+ TA=1
+ EAR_JACK=0
+ #
+ In this example, the extcon device have USB_OTG and TA
+ cables attached and HDMI and EAR_JACK cables detached.
+
+ In order to update the state of an extcon device, enter a hex
+ state number starting with 0x.
+ echo 0xHEX > state
+
+ This updates the whole state of the extcon dev.
+ Inputs of all the methods are required to meet the
+ mutually_exclusive contidions if they exist.
+
+ It is recommended to use this "global" state interface if
+ you need to enter the value atomically. The later state
+ interface associated with each cable cannot update
+ multiple cable states of an extcon device simultaneously.
+
+What: /sys/class/extcon/.../cable.x/name
+Date: February 2012
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+ The /sys/class/extcon/.../cable.x/name shows the name of cable
+ "x" (integer between 0 and 31) of an extcon device.
+
+What: /sys/class/extcon/.../cable.x/state
+Date: February 2012
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+ The /sys/class/extcon/.../cable.x/name shows and stores the
+ state of cable "x" (integer between 0 and 31) of an extcon
+ device. The state value is either 0 (detached) or 1
+ (attached).
+
+What: /sys/class/extcon/.../mutually_exclusive/...
+Date: December 2011
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+ Shows the relations of mutually exclusiveness. For example,
+ if the mutually_exclusive array of extcon_dev is
+ {0x3, 0x5, 0xC, 0x0}, the, the output is:
+ # ls mutually_exclusive/
+ 0x3
+ 0x5
+ 0xc
+ #
+
+ Note that mutually_exclusive is a sub-directory of the extcon
+ device and the file names under the mutually_exclusive
+ directory show the mutually-exclusive sets, not the contents
+ of the files.
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index 840f7d64d483..45000f0db4d4 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -96,16 +96,26 @@ Description:
is read-only. If the device is not enabled to wake up the
system from sleep states, this attribute is not present.
-What: /sys/devices/.../power/wakeup_hit_count
-Date: September 2010
+What: /sys/devices/.../power/wakeup_abort_count
+Date: February 2012
Contact: Rafael J. Wysocki <rjw@sisk.pl>
Description:
- The /sys/devices/.../wakeup_hit_count attribute contains the
+ The /sys/devices/.../wakeup_abort_count attribute contains the
number of times the processing of a wakeup event associated with
- the device might prevent the system from entering a sleep state.
- This attribute is read-only. If the device is not enabled to
- wake up the system from sleep states, this attribute is not
- present.
+ the device might have aborted system transition into a sleep
+ state in progress. This attribute is read-only. If the device
+ is not enabled to wake up the system from sleep states, this
+ attribute is not present.
+
+What: /sys/devices/.../power/wakeup_expire_count
+Date: February 2012
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/devices/.../wakeup_expire_count attribute contains the
+ number of times a wakeup event associated with the device has
+ been reported with a timeout that expired. This attribute is
+ read-only. If the device is not enabled to wake up the system
+ from sleep states, this attribute is not present.
What: /sys/devices/.../power/wakeup_active
Date: September 2010
@@ -148,6 +158,17 @@ Description:
not enabled to wake up the system from sleep states, this
attribute is not present.
+What: /sys/devices/.../power/wakeup_prevent_sleep_time_ms
+Date: February 2012
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/devices/.../wakeup_prevent_sleep_time_ms attribute
+ contains the total time the device has been preventing
+ opportunistic transitions to sleep states from occuring.
+ This attribute is read-only. If the device is not enabled to
+ wake up the system from sleep states, this attribute is not
+ present.
+
What: /sys/devices/.../power/autosuspend_delay_ms
Date: September 2010
Contact: Alan Stern <stern@rowland.harvard.edu>
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index e7be75b96e4b..5dab36448b44 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -9,31 +9,6 @@ Description:
/sys/devices/system/cpu/cpu#/
-What: /sys/devices/system/cpu/sched_mc_power_savings
- /sys/devices/system/cpu/sched_smt_power_savings
-Date: June 2006
-Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
-Description: Discover and adjust the kernel's multi-core scheduler support.
-
- Possible values are:
-
- 0 - No power saving load balance (default value)
- 1 - Fill one thread/core/package first for long running threads
- 2 - Also bias task wakeups to semi-idle cpu package for power
- savings
-
- sched_mc_power_savings is dependent upon SCHED_MC, which is
- itself architecture dependent.
-
- sched_smt_power_savings is dependent upon SCHED_SMT, which
- is itself architecture dependent.
-
- The two files are independent of each other. It is possible
- that one file may be present without the other.
-
- Introduced by git commit 5c45bf27.
-
-
What: /sys/devices/system/cpu/kernel_max
/sys/devices/system/cpu/offline
/sys/devices/system/cpu/online
diff --git a/Documentation/ABI/testing/sysfs-driver-wacom b/Documentation/ABI/testing/sysfs-driver-wacom
index 0130d6683c14..56c54558c8a4 100644
--- a/Documentation/ABI/testing/sysfs-driver-wacom
+++ b/Documentation/ABI/testing/sysfs-driver-wacom
@@ -9,6 +9,14 @@ Description:
or 0 otherwise. Writing to this file one of these values
switches reporting speed.
+What: /sys/class/leds/0005\:056A\:00BD.0001\:selector\:*/
+Date: May 2012
+Kernel Version: 3.5
+Contact: linux-bluetooth@vger.kernel.org
+Description:
+ LED selector for Intuos4 WL. There are 4 leds, but only one LED
+ can be lit at a time. Max brightness is 127.
+
What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/led
Date: August 2011
Contact: linux-input@vger.kernel.org
diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index b464d12761ba..31725ffeeb3a 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -172,3 +172,62 @@ Description:
Reading from this file will display the current value, which is
set to 1 MB by default.
+
+What: /sys/power/autosleep
+Date: April 2012
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/power/autosleep file can be written one of the strings
+ returned by reads from /sys/power/state. If that happens, a
+ work item attempting to trigger a transition of the system to
+ the sleep state represented by that string is queued up. This
+ attempt will only succeed if there are no active wakeup sources
+ in the system at that time. After every execution, regardless
+ of whether or not the attempt to put the system to sleep has
+ succeeded, the work item requeues itself until user space
+ writes "off" to /sys/power/autosleep.
+
+ Reading from this file causes the last string successfully
+ written to it to be returned.
+
+What: /sys/power/wake_lock
+Date: February 2012
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/power/wake_lock file allows user space to create
+ wakeup source objects and activate them on demand (if one of
+ those wakeup sources is active, reads from the
+ /sys/power/wakeup_count file block or return false). When a
+ string without white space is written to /sys/power/wake_lock,
+ it will be assumed to represent a wakeup source name. If there
+ is a wakeup source object with that name, it will be activated
+ (unless active already). Otherwise, a new wakeup source object
+ will be registered, assigned the given name and activated.
+ If a string written to /sys/power/wake_lock contains white
+ space, the part of the string preceding the white space will be
+ regarded as a wakeup source name and handled as descrived above.
+ The other part of the string will be regarded as a timeout (in
+ nanoseconds) such that the wakeup source will be automatically
+ deactivated after it has expired. The timeout, if present, is
+ set regardless of the current state of the wakeup source object
+ in question.
+
+ Reads from this file return a string consisting of the names of
+ wakeup sources created with the help of it that are active at
+ the moment, separated with spaces.
+
+
+What: /sys/power/wake_unlock
+Date: February 2012
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/power/wake_unlock file allows user space to deactivate
+ wakeup sources created with the help of /sys/power/wake_lock.
+ When a string is written to /sys/power/wake_unlock, it will be
+ assumed to represent the name of a wakeup source to deactivate.
+ If a wakeup source object of that name exists and is active at
+ the moment, it will be deactivated.
+
+ Reads from this file return a string consisting of the names of
+ wakeup sources created with the help of /sys/power/wake_lock
+ that are inactive at the moment, separated with spaces.
diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl
index 07a9c48de5a2..eee71426ecb8 100644
--- a/Documentation/DocBook/kernel-hacking.tmpl
+++ b/Documentation/DocBook/kernel-hacking.tmpl
@@ -1289,7 +1289,7 @@ static struct block_device_operations opt_fops = {
* Sparc assembly will do this to ya.
*/
C_LABEL(cputypvar):
- .asciz "compatability"
+ .asciz "compatibility"
/* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */
.align 4
diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
index 31df1aa00710..deb71baed328 100644
--- a/Documentation/DocBook/libata.tmpl
+++ b/Documentation/DocBook/libata.tmpl
@@ -918,7 +918,7 @@ and other resources, etc.
<title>HSM violation</title>
<para>
This error is indicated when STATUS value doesn't match HSM
- requirement during issuing or excution any ATA/ATAPI command.
+ requirement during issuing or execution any ATA/ATAPI command.
</para>
<itemizedlist>
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index b84f25e9cc87..dd03cf4a6539 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -2023,7 +2023,7 @@ Possible values are:</entry>
<entry>integer</entry>
</row>
<row><entry spanname="descr">Cyclic intra macroblock refresh. This is the number of continuous macroblocks
-refreshed every frame. Each frame a succesive set of macroblocks is refreshed until the cycle completes and starts from the
+refreshed every frame. Each frame a successive set of macroblocks is refreshed until the cycle completes and starts from the
top of the frame. Applicable to H264, H263 and MPEG4 encoder.</entry>
</row>
@@ -2183,7 +2183,7 @@ Applicable to the MPEG4 and H264 encoders.</entry>
<entry>integer</entry>
</row>
<row><entry spanname="descr">The Video Buffer Verifier size in kilobytes, it is used as a limitation of frame skip.
-The VBV is defined in the standard as a mean to verify that the produced stream will be succesfully decoded.
+The VBV is defined in the standard as a mean to verify that the produced stream will be successfully decoded.
The standard describes it as "Part of a hypothetical decoder that is conceptually connected to the
output of the encoder. Its purpose is to provide a constraint on the variability of the data rate that an
encoder or editing process may produce.".
@@ -2196,7 +2196,7 @@ Applicable to the MPEG1, MPEG2, MPEG4 encoders.</entry>
<entry>integer</entry>
</row>
<row><entry spanname="descr">The Coded Picture Buffer size in kilobytes, it is used as a limitation of frame skip.
-The CPB is defined in the H264 standard as a mean to verify that the produced stream will be succesfully decoded.
+The CPB is defined in the H264 standard as a mean to verify that the produced stream will be successfully decoded.
Applicable to the H264 encoder.</entry>
</row>
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index f7ade3b3b40d..59c080f084ef 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -218,16 +218,16 @@ The development process
Linux kernel development process currently consists of a few different
main kernel "branches" and lots of different subsystem-specific kernel
branches. These different branches are:
- - main 2.6.x kernel tree
- - 2.6.x.y -stable kernel tree
- - 2.6.x -git kernel patches
+ - main 3.x kernel tree
+ - 3.x.y -stable kernel tree
+ - 3.x -git kernel patches
- subsystem specific kernel trees and patches
- - the 2.6.x -next kernel tree for integration tests
+ - the 3.x -next kernel tree for integration tests
-2.6.x kernel tree
+3.x kernel tree
-----------------
-2.6.x kernels are maintained by Linus Torvalds, and can be found on
-kernel.org in the pub/linux/kernel/v2.6/ directory. Its development
+3.x kernels are maintained by Linus Torvalds, and can be found on
+kernel.org in the pub/linux/kernel/v3.x/ directory. Its development
process is as follows:
- As soon as a new kernel is released a two weeks window is open,
during this period of time maintainers can submit big diffs to
@@ -262,20 +262,20 @@ mailing list about kernel releases:
released according to perceived bug status, not according to a
preconceived timeline."
-2.6.x.y -stable kernel tree
+3.x.y -stable kernel tree
---------------------------
-Kernels with 4-part versions are -stable kernels. They contain
+Kernels with 3-part versions are -stable kernels. They contain
relatively small and critical fixes for security problems or significant
-regressions discovered in a given 2.6.x kernel.
+regressions discovered in a given 3.x kernel.
This is the recommended branch for users who want the most recent stable
kernel and are not interested in helping test development/experimental
versions.
-If no 2.6.x.y kernel is available, then the highest numbered 2.6.x
+If no 3.x.y kernel is available, then the highest numbered 3.x
kernel is the current stable kernel.
-2.6.x.y are maintained by the "stable" team <stable@vger.kernel.org>, and
+3.x.y are maintained by the "stable" team <stable@vger.kernel.org>, and
are released as needs dictate. The normal release period is approximately
two weeks, but it can be longer if there are no pressing problems. A
security-related problem, instead, can cause a release to happen almost
@@ -285,7 +285,7 @@ The file Documentation/stable_kernel_rules.txt in the kernel tree
documents what kinds of changes are acceptable for the -stable tree, and
how the release process works.
-2.6.x -git patches
+3.x -git patches
------------------
These are daily snapshots of Linus' kernel tree which are managed in a
git repository (hence the name.) These patches are usually released
@@ -317,13 +317,13 @@ revisions to it, and maintainers can mark patches as under review,
accepted, or rejected. Most of these patchwork sites are listed at
http://patchwork.kernel.org/.
-2.6.x -next kernel tree for integration tests
+3.x -next kernel tree for integration tests
---------------------------------------------
-Before updates from subsystem trees are merged into the mainline 2.6.x
+Before updates from subsystem trees are merged into the mainline 3.x
tree, they need to be integration-tested. For this purpose, a special
testing repository exists into which virtually all subsystem trees are
pulled on an almost daily basis:
- http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git
+ http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
http://linux.f-seidel.de/linux-next/pmwiki/
This way, the -next kernel gives a summary outlook onto what will be
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 30b656ece7aa..31d302bc5863 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -1,3 +1,3 @@
obj-m := DocBook/ accounting/ auxdisplay/ connector/ \
filesystems/ filesystems/configfs/ ia64/ laptops/ networking/ \
- pcmcia/ spi/ timers/ watchdog/src/
+ pcmcia/ spi/ timers/ watchdog/src/ misc-devices/mei/
diff --git a/Documentation/RCU/torture.txt b/Documentation/RCU/torture.txt
index 375d3fb71437..4ddf3913fd8c 100644
--- a/Documentation/RCU/torture.txt
+++ b/Documentation/RCU/torture.txt
@@ -47,6 +47,16 @@ irqreader Says to invoke RCU readers from irq level. This is currently
permit this. (Or, more accurately, variants of RCU that do
-not- permit this know to ignore this variable.)
+n_barrier_cbs If this is nonzero, RCU barrier testing will be conducted,
+ in which case n_barrier_cbs specifies the number of
+ RCU callbacks (and corresponding kthreads) to use for
+ this testing. The value cannot be negative. If you
+ specify this to be non-zero when torture_type indicates a
+ synchronous RCU implementation (one for which a member of
+ the synchronize_rcu() rather than the call_rcu() family is
+ used -- see the documentation for torture_type below), an
+ error will be reported and no testing will be carried out.
+
nfakewriters This is the number of RCU fake writer threads to run. Fake
writer threads repeatedly use the synchronous "wait for
current readers" function of the interface selected by
@@ -188,7 +198,7 @@ OUTPUT
The statistics output is as follows:
rcu-torture:--- Start of test: nreaders=16 nfakewriters=4 stat_interval=30 verbose=0 test_no_idle_hz=1 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4
- rcu-torture: rtc: (null) ver: 155441 tfle: 0 rta: 155441 rtaf: 8884 rtf: 155440 rtmbe: 0 rtbke: 0 rtbre: 0 rtbf: 0 rtb: 0 nt: 3055767
+ rcu-torture: rtc: (null) ver: 155441 tfle: 0 rta: 155441 rtaf: 8884 rtf: 155440 rtmbe: 0 rtbe: 0 rtbke: 0 rtbre: 0 rtbf: 0 rtb: 0 nt: 3055767
rcu-torture: Reader Pipe: 727860534 34213 0 0 0 0 0 0 0 0 0
rcu-torture: Reader Batch: 727877838 17003 0 0 0 0 0 0 0 0 0
rcu-torture: Free-Block Circulation: 155440 155440 155440 155440 155440 155440 155440 155440 155440 155440 0
@@ -230,6 +240,9 @@ o "rtmbe": A non-zero value indicates that rcutorture believes that
rcu_assign_pointer() and rcu_dereference() are not working
correctly. This value should be zero.
+o "rtbe": A non-zero value indicates that one of the rcu_barrier()
+ family of functions is not working correctly.
+
o "rtbke": rcutorture was unable to create the real-time kthreads
used to force RCU priority inversion. This value should be zero.
diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX
index 91c24a1e8a9e..36420e116c90 100644
--- a/Documentation/arm/00-INDEX
+++ b/Documentation/arm/00-INDEX
@@ -4,8 +4,6 @@ Booting
- requirements for booting
Interrupts
- ARM Interrupt subsystem documentation
-IXP2000
- - Release Notes for Linux on Intel's IXP2000 Network Processor
msm
- MSM specific documentation
Netwinder
diff --git a/Documentation/arm/IXP2000 b/Documentation/arm/IXP2000
deleted file mode 100644
index 68d21d92a30b..000000000000
--- a/Documentation/arm/IXP2000
+++ /dev/null
@@ -1,69 +0,0 @@
-
--------------------------------------------------------------------------
-Release Notes for Linux on Intel's IXP2000 Network Processor
-
-Maintained by Deepak Saxena <dsaxena@plexity.net>
--------------------------------------------------------------------------
-
-1. Overview
-
-Intel's IXP2000 family of NPUs (IXP2400, IXP2800, IXP2850) is designed
-for high-performance network applications such high-availability
-telecom systems. In addition to an XScale core, it contains up to 8
-"MicroEngines" that run special code, several high-end networking
-interfaces (UTOPIA, SPI, etc), a PCI host bridge, one serial port,
-flash interface, and some other odds and ends. For more information, see:
-
-http://developer.intel.com
-
-2. Linux Support
-
-Linux currently supports the following features on the IXP2000 NPUs:
-
-- On-chip serial
-- PCI
-- Flash (MTD/JFFS2)
-- I2C through GPIO
-- Timers (watchdog, OS)
-
-That is about all we can support under Linux ATM b/c the core networking
-components of the chip are accessed via Intel's closed source SDK.
-Please contact Intel directly on issues with using those. There is
-also a mailing list run by some folks at Princeton University that might
-be of help: https://lists.cs.princeton.edu/mailman/listinfo/ixp2xxx
-
-WHATEVER YOU DO, DO NOT POST EMAIL TO THE LINUX-ARM OR LINUX-ARM-KERNEL
-MAILING LISTS REGARDING THE INTEL SDK.
-
-3. Supported Platforms
-
-- Intel IXDP2400 Reference Platform
-- Intel IXDP2800 Reference Platform
-- Intel IXDP2401 Reference Platform
-- Intel IXDP2801 Reference Platform
-- RadiSys ENP-2611
-
-4. Usage Notes
-
-- The IXP2000 platforms usually have rather complex PCI bus topologies
- with large memory space requirements. In addition, b/c of the way the
- Intel SDK is designed, devices are enumerated in a very specific
- way. B/c of this this, we use "pci=firmware" option in the kernel
- command line so that we do not re-enumerate the bus.
-
-- IXDP2x01 systems have variable clock tick rates that we cannot determine
- via HW registers. The "ixdp2x01_clk=XXX" cmd line options allow you
- to pass the clock rate to the board port.
-
-5. Thanks
-
-The IXP2000 work has been funded by Intel Corp. and MontaVista Software, Inc.
-
-The following people have contributed patches/comments/etc:
-
-Naeem F. Afzal
-Lennert Buytenhek
-Jeffrey Daly
-
--------------------------------------------------------------------------
-Last Update: 8/09/2004
diff --git a/Documentation/arm/SPEAr/overview.txt b/Documentation/arm/SPEAr/overview.txt
index 253a35c6f782..28a9af953b9d 100644
--- a/Documentation/arm/SPEAr/overview.txt
+++ b/Documentation/arm/SPEAr/overview.txt
@@ -17,14 +17,14 @@ Introduction
SPEAr (Platform)
- SPEAr3XX (3XX SOC series, based on ARM9)
- SPEAr300 (SOC)
- - SPEAr300_EVB (Evaluation Board)
+ - SPEAr300 Evaluation Board
- SPEAr310 (SOC)
- - SPEAr310_EVB (Evaluation Board)
+ - SPEAr310 Evaluation Board
- SPEAr320 (SOC)
- - SPEAr320_EVB (Evaluation Board)
+ - SPEAr320 Evaluation Board
- SPEAr6XX (6XX SOC series, based on ARM9)
- SPEAr600 (SOC)
- - SPEAr600_EVB (Evaluation Board)
+ - SPEAr600 Evaluation Board
- SPEAr13XX (13XX SOC series, based on ARM CORTEXA9)
- SPEAr1300 (SOC)
@@ -51,10 +51,11 @@ Introduction
Common file for machines of spear3xx family is mach-spear3xx/spear3xx.c and for
spear6xx is mach-spear6xx/spear6xx.c. mach-spear* also contain soc/machine
specific files, like spear300.c, spear310.c, spear320.c and spear600.c.
- mach-spear* also contains board specific files for each machine type.
+ mach-spear* doesn't contains board specific files as they fully support
+ Flattened Device Tree.
Document Author
---------------
- Viresh Kumar, (c) 2010 ST Microelectronics
+ Viresh Kumar <viresh.kumar@st.com>, (c) 2010-2012 ST Microelectronics
diff --git a/Documentation/blackfin/bfin-gpio-notes.txt b/Documentation/blackfin/bfin-gpio-notes.txt
index d36b01f778b9..d245f39c3d01 100644
--- a/Documentation/blackfin/bfin-gpio-notes.txt
+++ b/Documentation/blackfin/bfin-gpio-notes.txt
@@ -53,7 +53,7 @@
3. But there are some exceptions
- Kernel permit the identical GPIO be requested both as GPIO and GPIO
- interrut.
+ interrupt.
Some drivers, like gpio-keys, need this behavior. Kernel only print out
warning messages like,
bfin-gpio: GPIO 24 is already reserved by gpio-keys: BTN0, and you are
diff --git a/Documentation/cgroups/resource_counter.txt b/Documentation/cgroups/resource_counter.txt
index 95b24d766eab..f3c4ec3626a2 100644
--- a/Documentation/cgroups/resource_counter.txt
+++ b/Documentation/cgroups/resource_counter.txt
@@ -77,11 +77,11 @@ to work with it.
where the charging failed.
d. int res_counter_charge_locked
- (struct res_counter *rc, unsigned long val)
+ (struct res_counter *rc, unsigned long val, bool force)
The same as res_counter_charge(), but it must not acquire/release the
res_counter->lock internally (it must be called with res_counter->lock
- held).
+ held). The force parameter indicates whether we can bypass the limit.
e. void res_counter_uncharge[_locked]
(struct res_counter *rc, unsigned long val)
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index c162be1c3234..47a154f30290 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -98,7 +98,8 @@ Your cooperation is appreciated.
8 = /dev/random Nondeterministic random number gen.
9 = /dev/urandom Faster, less secure random number gen.
10 = /dev/aio Asynchronous I/O notification interface
- 11 = /dev/kmsg Writes to this come out as printk's
+ 11 = /dev/kmsg Writes to this come out as printk's, reads
+ export the buffered printk records.
12 = /dev/oldmem Used by crashdump kernels to access
the memory of the kernel that crashed.
diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
new file mode 100644
index 000000000000..52478c83d0cc
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
@@ -0,0 +1,27 @@
+* ARM architected timer
+
+ARM Cortex-A7 and Cortex-A15 have a per-core architected timer, which
+provides per-cpu timers.
+
+The timer is attached to a GIC to deliver its per-processor interrupts.
+
+** Timer node properties:
+
+- compatible : Should at least contain "arm,armv7-timer".
+
+- interrupts : Interrupt list for secure, non-secure, virtual and
+ hypervisor timers, in that order.
+
+- clock-frequency : The frequency of the main counter, in Hz. Optional.
+
+Example:
+
+ timer {
+ compatible = "arm,cortex-a15-timer",
+ "arm,armv7-timer";
+ interrupts = <1 13 0xf08>,
+ <1 14 0xf08>,
+ <1 11 0xf08>,
+ <1 10 0xf08>;
+ clock-frequency = <100000000>;
+ };
diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt
new file mode 100644
index 000000000000..c63097d6afeb
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt
@@ -0,0 +1,65 @@
+* AT91's Analog to Digital Converter (ADC)
+
+Required properties:
+ - compatible: Should be "atmel,at91sam9260-adc"
+ - reg: Should contain ADC registers location and length
+ - interrupts: Should contain the IRQ line for the ADC
+ - atmel,adc-channel-base: Offset of the first channel data register
+ - atmel,adc-channels-used: Bitmask of the channels muxed and enable for this
+ device
+ - atmel,adc-drdy-mask: Mask of the DRDY interruption in the ADC
+ - atmel,adc-num-channels: Number of channels available in the ADC
+ - atmel,adc-startup-time: Startup Time of the ADC in microseconds as
+ defined in the datasheet
+ - atmel,adc-status-register: Offset of the Interrupt Status Register
+ - atmel,adc-trigger-register: Offset of the Trigger Register
+ - atmel,adc-vref: Reference voltage in millivolts for the conversions
+
+Optional properties:
+ - atmel,adc-use-external: Boolean to enable of external triggers
+
+Optional trigger Nodes:
+ - Required properties:
+ * trigger-name: Name of the trigger exposed to the user
+ * trigger-value: Value to put in the Trigger register
+ to activate this trigger
+ - Optional properties:
+ * trigger-external: Is the trigger an external trigger?
+
+Examples:
+adc0: adc@fffb0000 {
+ compatible = "atmel,at91sam9260-adc";
+ reg = <0xfffb0000 0x100>;
+ interrupts = <20 4>;
+ atmel,adc-channel-base = <0x30>;
+ atmel,adc-channels-used = <0xff>;
+ atmel,adc-drdy-mask = <0x10000>;
+ atmel,adc-num-channels = <8>;
+ atmel,adc-startup-time = <40>;
+ atmel,adc-status-register = <0x1c>;
+ atmel,adc-trigger-register = <0x08>;
+ atmel,adc-use-external;
+ atmel,adc-vref = <3300>;
+
+ trigger@0 {
+ trigger-name = "external-rising";
+ trigger-value = <0x1>;
+ trigger-external;
+ };
+ trigger@1 {
+ trigger-name = "external-falling";
+ trigger-value = <0x2>;
+ trigger-external;
+ };
+
+ trigger@2 {
+ trigger-name = "external-any";
+ trigger-value = <0x3>;
+ trigger-external;
+ };
+
+ trigger@3 {
+ trigger-name = "continuous";
+ trigger-value = <0x6>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/arm/lpc32xx-mic.txt b/Documentation/devicetree/bindings/arm/lpc32xx-mic.txt
new file mode 100644
index 000000000000..539adca19e8f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/lpc32xx-mic.txt
@@ -0,0 +1,38 @@
+* NXP LPC32xx Main Interrupt Controller
+ (MIC, including SIC1 and SIC2 secondary controllers)
+
+Required properties:
+- compatible: Should be "nxp,lpc3220-mic"
+- interrupt-controller: Identifies the node as an interrupt controller.
+- interrupt-parent: Empty for the interrupt controller itself
+- #interrupt-cells: The number of cells to define the interrupts. Should be 2.
+ The first cell is the IRQ number
+ The second cell is used to specify mode:
+ 1 = low-to-high edge triggered
+ 2 = high-to-low edge triggered
+ 4 = active high level-sensitive
+ 8 = active low level-sensitive
+ Default for internal sources should be set to 4 (active high).
+- reg: Should contain MIC registers location and length
+
+Examples:
+ /*
+ * MIC
+ */
+ mic: interrupt-controller@40008000 {
+ compatible = "nxp,lpc3220-mic";
+ interrupt-controller;
+ interrupt-parent;
+ #interrupt-cells = <2>;
+ reg = <0x40008000 0xC000>;
+ };
+
+ /*
+ * ADC
+ */
+ adc@40048000 {
+ compatible = "nxp,lpc3220-adc";
+ reg = <0x40048000 0x1000>;
+ interrupt-parent = <&mic>;
+ interrupts = <39 4>;
+ };
diff --git a/Documentation/devicetree/bindings/arm/lpc32xx.txt b/Documentation/devicetree/bindings/arm/lpc32xx.txt
new file mode 100644
index 000000000000..56ec8ddc4a3b
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/lpc32xx.txt
@@ -0,0 +1,8 @@
+NXP LPC32xx Platforms Device Tree Bindings
+------------------------------------------
+
+Boards with the NXP LPC32xx SoC shall have the following properties:
+
+Required root node property:
+
+compatible: must be "nxp,lpc3220", "nxp,lpc3230", "nxp,lpc3240" or "nxp,lpc3250"
diff --git a/Documentation/devicetree/bindings/arm/mrvl/intc.txt b/Documentation/devicetree/bindings/arm/mrvl/intc.txt
new file mode 100644
index 000000000000..80b9a94d9a23
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mrvl/intc.txt
@@ -0,0 +1,40 @@
+* Marvell MMP Interrupt controller
+
+Required properties:
+- compatible : Should be "mrvl,mmp-intc", "mrvl,mmp2-intc" or
+ "mrvl,mmp2-mux-intc"
+- reg : Address and length of the register set of the interrupt controller.
+ If the interrupt controller is intc, address and length means the range
+ of the whold interrupt controller. If the interrupt controller is mux-intc,
+ address and length means one register. Since address of mux-intc is in the
+ range of intc. mux-intc is secondary interrupt controller.
+- reg-names : Name of the register set of the interrupt controller. It's
+ only required in mux-intc interrupt controller.
+- interrupts : Should be the port interrupt shared by mux interrupts. It's
+ only required in mux-intc interrupt controller.
+- interrupt-controller : Identifies the node as an interrupt controller.
+- #interrupt-cells : Specifies the number of cells needed to encode an
+ interrupt source.
+- mrvl,intc-nr-irqs : Specifies the number of interrupts in the interrupt
+ controller.
+- mrvl,clr-mfp-irq : Specifies the interrupt that needs to clear MFP edge
+ detection first.
+
+Example:
+ intc: interrupt-controller@d4282000 {
+ compatible = "mrvl,mmp2-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0xd4282000 0x1000>;
+ mrvl,intc-nr-irqs = <64>;
+ };
+
+ intcmux4@d4282150 {
+ compatible = "mrvl,mmp2-mux-intc";
+ interrupts = <4>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x150 0x4>, <0x168 0x4>;
+ reg-names = "mux status", "mux mask";
+ mrvl,intc-nr-irqs = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/arm/mrvl.txt b/Documentation/devicetree/bindings/arm/mrvl/mrvl.txt
index d8de933e9d81..117d741a2e4f 100644
--- a/Documentation/devicetree/bindings/arm/mrvl.txt
+++ b/Documentation/devicetree/bindings/arm/mrvl/mrvl.txt
@@ -4,3 +4,11 @@ Marvell Platforms Device Tree Bindings
PXA168 Aspenite Board
Required root node properties:
- compatible = "mrvl,pxa168-aspenite", "mrvl,pxa168";
+
+PXA910 DKB Board
+Required root node properties:
+ - compatible = "mrvl,pxa910-dkb";
+
+MMP2 Brownstone Board
+Required root node properties:
+ - compatible = "mrvl,mmp2-brownstone";
diff --git a/Documentation/devicetree/bindings/arm/mrvl/timer.txt b/Documentation/devicetree/bindings/arm/mrvl/timer.txt
new file mode 100644
index 000000000000..9a6e251462e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mrvl/timer.txt
@@ -0,0 +1,13 @@
+* Marvell MMP Timer controller
+
+Required properties:
+- compatible : Should be "mrvl,mmp-timer".
+- reg : Address and length of the register set of timer controller.
+- interrupts : Should be the interrupt number.
+
+Example:
+ timer0: timer@d4014000 {
+ compatible = "mrvl,mmp-timer";
+ reg = <0xd4014000 0x100>;
+ interrupts = <13>;
+ };
diff --git a/Documentation/devicetree/bindings/arm/spear.txt b/Documentation/devicetree/bindings/arm/spear.txt
index f8e54f092328..aa5f355cc947 100644
--- a/Documentation/devicetree/bindings/arm/spear.txt
+++ b/Documentation/devicetree/bindings/arm/spear.txt
@@ -6,3 +6,21 @@ Boards with the ST SPEAr600 SoC shall have the following properties:
Required root node property:
compatible = "st,spear600";
+
+Boards with the ST SPEAr300 SoC shall have the following properties:
+
+Required root node property:
+
+compatible = "st,spear300";
+
+Boards with the ST SPEAr310 SoC shall have the following properties:
+
+Required root node property:
+
+compatible = "st,spear310";
+
+Boards with the ST SPEAr320 SoC shall have the following properties:
+
+Required root node property:
+
+compatible = "st,spear320";
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt
new file mode 100644
index 000000000000..c25a0a55151d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt
@@ -0,0 +1,16 @@
+NVIDIA Tegra20 MC(Memory Controller)
+
+Required properties:
+- compatible : "nvidia,tegra20-mc"
+- reg : Should contain 2 register ranges(address and length); see the
+ example below. Note that the MC registers are interleaved with the
+ GART registers, and hence must be represented as multiple ranges.
+- interrupts : Should contain MC General interrupt.
+
+Example:
+ mc {
+ compatible = "nvidia,tegra20-mc";
+ reg = <0x7000f000 0x024
+ 0x7000f03c 0x3c4>;
+ interrupts = <0 77 0x04>;
+ };
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt
new file mode 100644
index 000000000000..e47e73f612f4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt
@@ -0,0 +1,18 @@
+NVIDIA Tegra30 MC(Memory Controller)
+
+Required properties:
+- compatible : "nvidia,tegra30-mc"
+- reg : Should contain 4 register ranges(address and length); see the
+ example below. Note that the MC registers are interleaved with the
+ SMMU registers, and hence must be represented as multiple ranges.
+- interrupts : Should contain MC General interrupt.
+
+Example:
+ mc {
+ compatible = "nvidia,tegra30-mc";
+ reg = <0x7000f000 0x010
+ 0x7000f03c 0x1b4
+ 0x7000f200 0x028
+ 0x7000f284 0x17c>;
+ interrupts = <0 77 0x04>;
+ };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-nmk.txt b/Documentation/devicetree/bindings/gpio/gpio-nmk.txt
new file mode 100644
index 000000000000..ee87467ad8d6
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-nmk.txt
@@ -0,0 +1,31 @@
+Nomadik GPIO controller
+
+Required properties:
+- compatible : Should be "st,nomadik-gpio".
+- reg : Physical base address and length of the controller's registers.
+- interrupts : The interrupt outputs from the controller.
+- #gpio-cells : Should be two:
+ The first cell is the pin number.
+ The second cell is used to specify optional parameters:
+ - bits[3:0] trigger type and level flags:
+ 1 = low-to-high edge triggered.
+ 2 = high-to-low edge triggered.
+ 4 = active high level-sensitive.
+ 8 = active low level-sensitive.
+- gpio-controller : Marks the device node as a GPIO controller.
+- interrupt-controller : Marks the device node as an interrupt controller.
+- gpio-bank : Specifies which bank a controller owns.
+- st,supports-sleepmode : Specifies whether controller can sleep or not
+
+Example:
+
+ gpio1: gpio@8012e080 {
+ compatible = "st,nomadik-gpio";
+ reg = <0x8012e080 0x80>;
+ interrupts = <0 120 0x4>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ supports-sleepmode;
+ gpio-bank = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/gpio/mrvl-gpio.txt b/Documentation/devicetree/bindings/gpio/mrvl-gpio.txt
index 1e34cfe5ebea..05428f39d9ac 100644
--- a/Documentation/devicetree/bindings/gpio/mrvl-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/mrvl-gpio.txt
@@ -3,19 +3,25 @@
Required properties:
- compatible : Should be "mrvl,pxa-gpio" or "mrvl,mmp-gpio"
- reg : Address and length of the register set for the device
-- interrupts : Should be the port interrupt shared by all gpio pins, if
-- interrupt-name : Should be the name of irq resource.
- one number.
+- interrupts : Should be the port interrupt shared by all gpio pins.
+ There're three gpio interrupts in arch-pxa, and they're gpio0,
+ gpio1 and gpio_mux. There're only one gpio interrupt in arch-mmp,
+ gpio_mux.
+- interrupt-name : Should be the name of irq resource. Each interrupt
+ binds its interrupt-name.
+- interrupt-controller : Identifies the node as an interrupt controller.
+- #interrupt-cells: Specifies the number of cells needed to encode an
+ interrupt source.
- gpio-controller : Marks the device node as a gpio controller.
- #gpio-cells : Should be one. It is the pin number.
Example:
gpio: gpio@d4019000 {
- compatible = "mrvl,mmp-gpio", "mrvl,pxa-gpio";
+ compatible = "mrvl,mmp-gpio";
reg = <0xd4019000 0x1000>;
- interrupts = <49>, <17>, <18>;
- interrupt-name = "gpio_mux", "gpio0", "gpio1";
+ interrupts = <49>;
+ interrupt-name = "gpio_mux";
gpio-controller;
#gpio-cells = <1>;
interrupt-controller;
diff --git a/Documentation/devicetree/bindings/i2c/mrvl-i2c.txt b/Documentation/devicetree/bindings/i2c/mrvl-i2c.txt
index 071eb3caae91..b891ee218354 100644
--- a/Documentation/devicetree/bindings/i2c/mrvl-i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/mrvl-i2c.txt
@@ -3,34 +3,31 @@
Required properties :
- reg : Offset and length of the register set for the device
- - compatible : should be "mrvl,mmp-twsi" where CHIP is the name of a
+ - compatible : should be "mrvl,mmp-twsi" where mmp is the name of a
compatible processor, e.g. pxa168, pxa910, mmp2, mmp3.
For the pxa2xx/pxa3xx, an additional node "mrvl,pxa-i2c" is required
as shown in the example below.
Recommended properties :
- - interrupts : <a b> where a is the interrupt number and b is a
- field that represents an encoding of the sense and level
- information for the interrupt. This should be encoded based on
- the information in section 2) depending on the type of interrupt
- controller you have.
+ - interrupts : the interrupt number
- interrupt-parent : the phandle for the interrupt controller that
- services interrupts for this device.
+ services interrupts for this device. If the parent is the default
+ interrupt controller in device tree, it could be ignored.
- mrvl,i2c-polling : Disable interrupt of i2c controller. Polling
status register of i2c controller instead.
- mrvl,i2c-fast-mode : Enable fast mode of i2c controller.
Examples:
twsi1: i2c@d4011000 {
- compatible = "mrvl,mmp-twsi", "mrvl,pxa-i2c";
+ compatible = "mrvl,mmp-twsi";
reg = <0xd4011000 0x1000>;
interrupts = <7>;
mrvl,i2c-fast-mode;
};
twsi2: i2c@d4025000 {
- compatible = "mrvl,mmp-twsi", "mrvl,pxa-i2c";
+ compatible = "mrvl,mmp-twsi";
reg = <0xd4025000 0x1000>;
interrupts = <58>;
};
diff --git a/Documentation/devicetree/bindings/i2c/pnx.txt b/Documentation/devicetree/bindings/i2c/pnx.txt
new file mode 100644
index 000000000000..fe98ada33ee4
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/pnx.txt
@@ -0,0 +1,36 @@
+* NXP PNX I2C Controller
+
+Required properties:
+
+ - reg: Offset and length of the register set for the device
+ - compatible: should be "nxp,pnx-i2c"
+ - interrupts: configure one interrupt line
+ - #address-cells: always 1 (for i2c addresses)
+ - #size-cells: always 0
+ - interrupt-parent: the phandle for the interrupt controller that
+ services interrupts for this device.
+
+Optional properties:
+
+ - clock-frequency: desired I2C bus clock frequency in Hz, Default: 100000 Hz
+
+Examples:
+
+ i2c1: i2c@400a0000 {
+ compatible = "nxp,pnx-i2c";
+ reg = <0x400a0000 0x100>;
+ interrupt-parent = <&mic>;
+ interrupts = <51 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c2: i2c@400a8000 {
+ compatible = "nxp,pnx-i2c";
+ reg = <0x400a8000 0x100>;
+ interrupt-parent = <&mic>;
+ interrupts = <50 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ };
diff --git a/Documentation/devicetree/bindings/misc/bmp085.txt b/Documentation/devicetree/bindings/misc/bmp085.txt
new file mode 100644
index 000000000000..91dfda2e4e11
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/bmp085.txt
@@ -0,0 +1,20 @@
+BMP085/BMP18x digital pressure sensors
+
+Required properties:
+- compatible: bosch,bmp085
+
+Optional properties:
+- chip-id: configurable chip id for non-default chip revisions
+- temp-measurement-period: temperature measurement period (milliseconds)
+- default-oversampling: default oversampling value to be used at startup,
+ value range is 0-3 with rising sensitivity.
+
+Example:
+
+pressure@77 {
+ compatible = "bosch,bmp085";
+ reg = <0x77>;
+ chip-id = <10>;
+ temp-measurement-period = <100>;
+ default-oversampling = <2>;
+};
diff --git a/Documentation/devicetree/bindings/mtd/orion-nand.txt b/Documentation/devicetree/bindings/mtd/orion-nand.txt
new file mode 100644
index 000000000000..b2356b7d2fa4
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/orion-nand.txt
@@ -0,0 +1,50 @@
+NAND support for Marvell Orion SoC platforms
+
+Required properties:
+- compatible : "mrvl,orion-nand".
+- reg : Base physical address of the NAND and length of memory mapped
+ region
+
+Optional properties:
+- cle : Address line number connected to CLE. Default is 0
+- ale : Address line number connected to ALE. Default is 1
+- bank-width : Width in bytes of the device. Default is 1
+- chip-delay : Chip dependent delay for transferring data from array to read
+ registers in usecs
+
+The device tree may optionally contain sub-nodes describing partitions of the
+address space. See partition.txt for more detail.
+
+Example:
+
+nand@f4000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ cle = <0>;
+ ale = <1>;
+ bank-width = <1>;
+ chip-delay = <25>;
+ compatible = "mrvl,orion-nand";
+ reg = <0xf4000000 0x400>;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0000000 0x100000>;
+ read-only;
+ };
+
+ partition@100000 {
+ label = "uImage";
+ reg = <0x0100000 0x200000>;
+ };
+
+ partition@300000 {
+ label = "dtb";
+ reg = <0x0300000 0x100000>;
+ };
+
+ partition@400000 {
+ label = "root";
+ reg = <0x0400000 0x7d00000>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
index 1ad80d5865a9..f31b686d4556 100644
--- a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
+++ b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
@@ -1,4 +1,4 @@
-Flexcan CAN contoller on Freescale's ARM and PowerPC system-on-a-chip (SOC).
+Flexcan CAN controller on Freescale's ARM and PowerPC system-on-a-chip (SOC).
Required properties:
diff --git a/Documentation/devicetree/bindings/net/lpc-eth.txt b/Documentation/devicetree/bindings/net/lpc-eth.txt
new file mode 100644
index 000000000000..585021acd178
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/lpc-eth.txt
@@ -0,0 +1,24 @@
+* NXP LPC32xx SoC Ethernet Controller
+
+Required properties:
+- compatible: Should be "nxp,lpc-eth"
+- reg: Address and length of the register set for the device
+- interrupts: Should contain ethernet controller interrupt
+
+Optional properties:
+- phy-mode: String, operation mode of the PHY interface.
+ Supported values are: "mii", "rmii" (default)
+- use-iram: Use LPC32xx internal SRAM (IRAM) for DMA buffering
+- local-mac-address : 6 bytes, mac address
+
+Example:
+
+ mac: ethernet@31060000 {
+ compatible = "nxp,lpc-eth";
+ reg = <0x31060000 0x1000>;
+ interrupt-parent = <&mic>;
+ interrupts = <29 0>;
+
+ phy-mode = "rmii";
+ use-iram;
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt
new file mode 100644
index 000000000000..ab19e6bc7d3b
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt
@@ -0,0 +1,95 @@
+* Freescale IOMUX Controller (IOMUXC) for i.MX
+
+The IOMUX Controller (IOMUXC), together with the IOMUX, enables the IC
+to share one PAD to several functional blocks. The sharing is done by
+multiplexing the PAD input/output signals. For each PAD there are up to
+8 muxing options (called ALT modes). Since different modules require
+different PAD settings (like pull up, keeper, etc) the IOMUXC controls
+also the PAD settings parameters.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+Freescale IMX pin configuration node is a node of a group of pins which can be
+used for a specific device or function. This node represents both mux and config
+of the pins in that group. The 'mux' selects the function mode(also named mux
+mode) this pin can work on and the 'config' configures various pad settings
+such as pull-up, open drain, drive strength, etc.
+
+Required properties for iomux controller:
+- compatible: "fsl,<soc>-iomuxc"
+ Please refer to each fsl,<soc>-pinctrl.txt binding doc for supported SoCs.
+
+Required properties for pin configuration node:
+- fsl,pins: two integers array, represents a group of pins mux and config
+ setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
+ pin working on a specific function, CONFIG is the pad setting value like
+ pull-up on this pin. Please refer to fsl,<soc>-pinctrl.txt for the valid
+ pins and functions of each SoC.
+
+Bits used for CONFIG:
+NO_PAD_CTL(1 << 31): indicate this pin does not need config.
+
+SION(1 << 30): Software Input On Field.
+Force the selected mux mode input path no matter of MUX_MODE functionality.
+By default the input path is determined by functionality of the selected
+mux mode (regular).
+
+Other bits are used for PAD setting.
+Please refer to each fsl,<soc>-pinctrl,txt binding doc for SoC specific part
+of bits definitions.
+
+NOTE:
+Some requirements for using fsl,imx-pinctrl binding:
+1. We have pin function node defined under iomux controller node to represent
+ what pinmux functions this SoC supports.
+2. The pin configuration node intends to work on a specific function should
+ to be defined under that specific function node.
+ The function node's name should represent well about what function
+ this group of pins in this pin configuration node are working on.
+3. The driver can use the function node's name and pin configuration node's
+ name describe the pin function and group hierarchy.
+ For example, Linux IMX pinctrl driver takes the function node's name
+ as the function name and pin configuration node's name as group name to
+ create the map table.
+4. Each pin configuration node should have a phandle, devices can set pins
+ configurations by referring to the phandle of that pin configuration node.
+
+Examples:
+usdhc@0219c000 { /* uSDHC4 */
+ fsl,card-wired;
+ vmmc-supply = <&reg_3p3v>;
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc4_1>;
+};
+
+iomuxc@020e0000 {
+ compatible = "fsl,imx6q-iomuxc";
+ reg = <0x020e0000 0x4000>;
+
+ /* shared pinctrl settings */
+ usdhc4 {
+ pinctrl_usdhc4_1: usdhc4grp-1 {
+ fsl,pins = <1386 0x17059 /* MX6Q_PAD_SD4_CMD__USDHC4_CMD */
+ 1392 0x10059 /* MX6Q_PAD_SD4_CLK__USDHC4_CLK */
+ 1462 0x17059 /* MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 */
+ 1470 0x17059 /* MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 */
+ 1478 0x17059 /* MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 */
+ 1486 0x17059 /* MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 */
+ 1493 0x17059 /* MX6Q_PAD_SD4_DAT4__USDHC4_DAT4 */
+ 1501 0x17059 /* MX6Q_PAD_SD4_DAT5__USDHC4_DAT5 */
+ 1509 0x17059 /* MX6Q_PAD_SD4_DAT6__USDHC4_DAT6 */
+ 1517 0x17059>; /* MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 */
+ };
+ };
+ ....
+};
+Refer to the IOMUXC controller chapter in imx6q datasheet,
+0x17059 means enable hysteresis, 47KOhm Pull Up, 50Mhz speed,
+80Ohm driver strength and Fast Slew Rate.
+User should refer to each SoC spec to set the correct value.
+
+TODO: when dtc macro support is available, we can change above raw data
+to dt macro which can get better readability in dts file.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx51-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx51-pinctrl.txt
new file mode 100644
index 000000000000..b96fa4c31745
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx51-pinctrl.txt
@@ -0,0 +1,787 @@
+* Freescale IMX51 IOMUX Controller
+
+Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
+and usage.
+
+Required properties:
+- compatible: "fsl,imx51-iomuxc"
+- fsl,pins: two integers array, represents a group of pins mux and config
+ setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
+ pin working on a specific function, CONFIG is the pad setting value like
+ pull-up for this pin. Please refer to imx51 datasheet for the valid pad
+ config settings.
+
+CONFIG bits definition:
+PAD_CTL_HVE (1 << 13)
+PAD_CTL_HYS (1 << 8)
+PAD_CTL_PKE (1 << 7)
+PAD_CTL_PUE (1 << 6)
+PAD_CTL_PUS_100K_DOWN (0 << 4)
+PAD_CTL_PUS_47K_UP (1 << 4)
+PAD_CTL_PUS_100K_UP (2 << 4)
+PAD_CTL_PUS_22K_UP (3 << 4)
+PAD_CTL_ODE (1 << 3)
+PAD_CTL_DSE_LOW (0 << 1)
+PAD_CTL_DSE_MED (1 << 1)
+PAD_CTL_DSE_HIGH (2 << 1)
+PAD_CTL_DSE_MAX (3 << 1)
+PAD_CTL_SRE_FAST (1 << 0)
+PAD_CTL_SRE_SLOW (0 << 0)
+
+See below for available PIN_FUNC_ID for imx51:
+MX51_PAD_EIM_D16__AUD4_RXFS 0
+MX51_PAD_EIM_D16__AUD5_TXD 1
+MX51_PAD_EIM_D16__EIM_D16 2
+MX51_PAD_EIM_D16__GPIO2_0 3
+MX51_PAD_EIM_D16__I2C1_SDA 4
+MX51_PAD_EIM_D16__UART2_CTS 5
+MX51_PAD_EIM_D16__USBH2_DATA0 6
+MX51_PAD_EIM_D17__AUD5_RXD 7
+MX51_PAD_EIM_D17__EIM_D17 8
+MX51_PAD_EIM_D17__GPIO2_1 9
+MX51_PAD_EIM_D17__UART2_RXD 10
+MX51_PAD_EIM_D17__UART3_CTS 11
+MX51_PAD_EIM_D17__USBH2_DATA1 12
+MX51_PAD_EIM_D18__AUD5_TXC 13
+MX51_PAD_EIM_D18__EIM_D18 14
+MX51_PAD_EIM_D18__GPIO2_2 15
+MX51_PAD_EIM_D18__UART2_TXD 16
+MX51_PAD_EIM_D18__UART3_RTS 17
+MX51_PAD_EIM_D18__USBH2_DATA2 18
+MX51_PAD_EIM_D19__AUD4_RXC 19
+MX51_PAD_EIM_D19__AUD5_TXFS 20
+MX51_PAD_EIM_D19__EIM_D19 21
+MX51_PAD_EIM_D19__GPIO2_3 22
+MX51_PAD_EIM_D19__I2C1_SCL 23
+MX51_PAD_EIM_D19__UART2_RTS 24
+MX51_PAD_EIM_D19__USBH2_DATA3 25
+MX51_PAD_EIM_D20__AUD4_TXD 26
+MX51_PAD_EIM_D20__EIM_D20 27
+MX51_PAD_EIM_D20__GPIO2_4 28
+MX51_PAD_EIM_D20__SRTC_ALARM_DEB 29
+MX51_PAD_EIM_D20__USBH2_DATA4 30
+MX51_PAD_EIM_D21__AUD4_RXD 31
+MX51_PAD_EIM_D21__EIM_D21 32
+MX51_PAD_EIM_D21__GPIO2_5 33
+MX51_PAD_EIM_D21__SRTC_ALARM_DEB 34
+MX51_PAD_EIM_D21__USBH2_DATA5 35
+MX51_PAD_EIM_D22__AUD4_TXC 36
+MX51_PAD_EIM_D22__EIM_D22 37
+MX51_PAD_EIM_D22__GPIO2_6 38
+MX51_PAD_EIM_D22__USBH2_DATA6 39
+MX51_PAD_EIM_D23__AUD4_TXFS 40
+MX51_PAD_EIM_D23__EIM_D23 41
+MX51_PAD_EIM_D23__GPIO2_7 42
+MX51_PAD_EIM_D23__SPDIF_OUT1 43
+MX51_PAD_EIM_D23__USBH2_DATA7 44
+MX51_PAD_EIM_D24__AUD6_RXFS 45
+MX51_PAD_EIM_D24__EIM_D24 46
+MX51_PAD_EIM_D24__GPIO2_8 47
+MX51_PAD_EIM_D24__I2C2_SDA 48
+MX51_PAD_EIM_D24__UART3_CTS 49
+MX51_PAD_EIM_D24__USBOTG_DATA0 50
+MX51_PAD_EIM_D25__EIM_D25 51
+MX51_PAD_EIM_D25__KEY_COL6 52
+MX51_PAD_EIM_D25__UART2_CTS 53
+MX51_PAD_EIM_D25__UART3_RXD 54
+MX51_PAD_EIM_D25__USBOTG_DATA1 55
+MX51_PAD_EIM_D26__EIM_D26 56
+MX51_PAD_EIM_D26__KEY_COL7 57
+MX51_PAD_EIM_D26__UART2_RTS 58
+MX51_PAD_EIM_D26__UART3_TXD 59
+MX51_PAD_EIM_D26__USBOTG_DATA2 60
+MX51_PAD_EIM_D27__AUD6_RXC 61
+MX51_PAD_EIM_D27__EIM_D27 62
+MX51_PAD_EIM_D27__GPIO2_9 63
+MX51_PAD_EIM_D27__I2C2_SCL 64
+MX51_PAD_EIM_D27__UART3_RTS 65
+MX51_PAD_EIM_D27__USBOTG_DATA3 66
+MX51_PAD_EIM_D28__AUD6_TXD 67
+MX51_PAD_EIM_D28__EIM_D28 68
+MX51_PAD_EIM_D28__KEY_ROW4 69
+MX51_PAD_EIM_D28__USBOTG_DATA4 70
+MX51_PAD_EIM_D29__AUD6_RXD 71
+MX51_PAD_EIM_D29__EIM_D29 72
+MX51_PAD_EIM_D29__KEY_ROW5 73
+MX51_PAD_EIM_D29__USBOTG_DATA5 74
+MX51_PAD_EIM_D30__AUD6_TXC 75
+MX51_PAD_EIM_D30__EIM_D30 76
+MX51_PAD_EIM_D30__KEY_ROW6 77
+MX51_PAD_EIM_D30__USBOTG_DATA6 78
+MX51_PAD_EIM_D31__AUD6_TXFS 79
+MX51_PAD_EIM_D31__EIM_D31 80
+MX51_PAD_EIM_D31__KEY_ROW7 81
+MX51_PAD_EIM_D31__USBOTG_DATA7 82
+MX51_PAD_EIM_A16__EIM_A16 83
+MX51_PAD_EIM_A16__GPIO2_10 84
+MX51_PAD_EIM_A16__OSC_FREQ_SEL0 85
+MX51_PAD_EIM_A17__EIM_A17 86
+MX51_PAD_EIM_A17__GPIO2_11 87
+MX51_PAD_EIM_A17__OSC_FREQ_SEL1 88
+MX51_PAD_EIM_A18__BOOT_LPB0 89
+MX51_PAD_EIM_A18__EIM_A18 90
+MX51_PAD_EIM_A18__GPIO2_12 91
+MX51_PAD_EIM_A19__BOOT_LPB1 92
+MX51_PAD_EIM_A19__EIM_A19 93
+MX51_PAD_EIM_A19__GPIO2_13 94
+MX51_PAD_EIM_A20__BOOT_UART_SRC0 95
+MX51_PAD_EIM_A20__EIM_A20 96
+MX51_PAD_EIM_A20__GPIO2_14 97
+MX51_PAD_EIM_A21__BOOT_UART_SRC1 98
+MX51_PAD_EIM_A21__EIM_A21 99
+MX51_PAD_EIM_A21__GPIO2_15 100
+MX51_PAD_EIM_A22__EIM_A22 101
+MX51_PAD_EIM_A22__GPIO2_16 102
+MX51_PAD_EIM_A23__BOOT_HPN_EN 103
+MX51_PAD_EIM_A23__EIM_A23 104
+MX51_PAD_EIM_A23__GPIO2_17 105
+MX51_PAD_EIM_A24__EIM_A24 106
+MX51_PAD_EIM_A24__GPIO2_18 107
+MX51_PAD_EIM_A24__USBH2_CLK 108
+MX51_PAD_EIM_A25__DISP1_PIN4 109
+MX51_PAD_EIM_A25__EIM_A25 110
+MX51_PAD_EIM_A25__GPIO2_19 111
+MX51_PAD_EIM_A25__USBH2_DIR 112
+MX51_PAD_EIM_A26__CSI1_DATA_EN 113
+MX51_PAD_EIM_A26__DISP2_EXT_CLK 114
+MX51_PAD_EIM_A26__EIM_A26 115
+MX51_PAD_EIM_A26__GPIO2_20 116
+MX51_PAD_EIM_A26__USBH2_STP 117
+MX51_PAD_EIM_A27__CSI2_DATA_EN 118
+MX51_PAD_EIM_A27__DISP1_PIN1 119
+MX51_PAD_EIM_A27__EIM_A27 120
+MX51_PAD_EIM_A27__GPIO2_21 121
+MX51_PAD_EIM_A27__USBH2_NXT 122
+MX51_PAD_EIM_EB0__EIM_EB0 123
+MX51_PAD_EIM_EB1__EIM_EB1 124
+MX51_PAD_EIM_EB2__AUD5_RXFS 125
+MX51_PAD_EIM_EB2__CSI1_D2 126
+MX51_PAD_EIM_EB2__EIM_EB2 127
+MX51_PAD_EIM_EB2__FEC_MDIO 128
+MX51_PAD_EIM_EB2__GPIO2_22 129
+MX51_PAD_EIM_EB2__GPT_CMPOUT1 130
+MX51_PAD_EIM_EB3__AUD5_RXC 131
+MX51_PAD_EIM_EB3__CSI1_D3 132
+MX51_PAD_EIM_EB3__EIM_EB3 133
+MX51_PAD_EIM_EB3__FEC_RDATA1 134
+MX51_PAD_EIM_EB3__GPIO2_23 135
+MX51_PAD_EIM_EB3__GPT_CMPOUT2 136
+MX51_PAD_EIM_OE__EIM_OE 137
+MX51_PAD_EIM_OE__GPIO2_24 138
+MX51_PAD_EIM_CS0__EIM_CS0 139
+MX51_PAD_EIM_CS0__GPIO2_25 140
+MX51_PAD_EIM_CS1__EIM_CS1 141
+MX51_PAD_EIM_CS1__GPIO2_26 142
+MX51_PAD_EIM_CS2__AUD5_TXD 143
+MX51_PAD_EIM_CS2__CSI1_D4 144
+MX51_PAD_EIM_CS2__EIM_CS2 145
+MX51_PAD_EIM_CS2__FEC_RDATA2 146
+MX51_PAD_EIM_CS2__GPIO2_27 147
+MX51_PAD_EIM_CS2__USBOTG_STP 148
+MX51_PAD_EIM_CS3__AUD5_RXD 149
+MX51_PAD_EIM_CS3__CSI1_D5 150
+MX51_PAD_EIM_CS3__EIM_CS3 151
+MX51_PAD_EIM_CS3__FEC_RDATA3 152
+MX51_PAD_EIM_CS3__GPIO2_28 153
+MX51_PAD_EIM_CS3__USBOTG_NXT 154
+MX51_PAD_EIM_CS4__AUD5_TXC 155
+MX51_PAD_EIM_CS4__CSI1_D6 156
+MX51_PAD_EIM_CS4__EIM_CS4 157
+MX51_PAD_EIM_CS4__FEC_RX_ER 158
+MX51_PAD_EIM_CS4__GPIO2_29 159
+MX51_PAD_EIM_CS4__USBOTG_CLK 160
+MX51_PAD_EIM_CS5__AUD5_TXFS 161
+MX51_PAD_EIM_CS5__CSI1_D7 162
+MX51_PAD_EIM_CS5__DISP1_EXT_CLK 163
+MX51_PAD_EIM_CS5__EIM_CS5 164
+MX51_PAD_EIM_CS5__FEC_CRS 165
+MX51_PAD_EIM_CS5__GPIO2_30 166
+MX51_PAD_EIM_CS5__USBOTG_DIR 167
+MX51_PAD_EIM_DTACK__EIM_DTACK 168
+MX51_PAD_EIM_DTACK__GPIO2_31 169
+MX51_PAD_EIM_LBA__EIM_LBA 170
+MX51_PAD_EIM_LBA__GPIO3_1 171
+MX51_PAD_EIM_CRE__EIM_CRE 172
+MX51_PAD_EIM_CRE__GPIO3_2 173
+MX51_PAD_DRAM_CS1__DRAM_CS1 174
+MX51_PAD_NANDF_WE_B__GPIO3_3 175
+MX51_PAD_NANDF_WE_B__NANDF_WE_B 176
+MX51_PAD_NANDF_WE_B__PATA_DIOW 177
+MX51_PAD_NANDF_WE_B__SD3_DATA0 178
+MX51_PAD_NANDF_RE_B__GPIO3_4 179
+MX51_PAD_NANDF_RE_B__NANDF_RE_B 180
+MX51_PAD_NANDF_RE_B__PATA_DIOR 181
+MX51_PAD_NANDF_RE_B__SD3_DATA1 182
+MX51_PAD_NANDF_ALE__GPIO3_5 183
+MX51_PAD_NANDF_ALE__NANDF_ALE 184
+MX51_PAD_NANDF_ALE__PATA_BUFFER_EN 185
+MX51_PAD_NANDF_CLE__GPIO3_6 186
+MX51_PAD_NANDF_CLE__NANDF_CLE 187
+MX51_PAD_NANDF_CLE__PATA_RESET_B 188
+MX51_PAD_NANDF_WP_B__GPIO3_7 189
+MX51_PAD_NANDF_WP_B__NANDF_WP_B 190
+MX51_PAD_NANDF_WP_B__PATA_DMACK 191
+MX51_PAD_NANDF_WP_B__SD3_DATA2 192
+MX51_PAD_NANDF_RB0__ECSPI2_SS1 193
+MX51_PAD_NANDF_RB0__GPIO3_8 194
+MX51_PAD_NANDF_RB0__NANDF_RB0 195
+MX51_PAD_NANDF_RB0__PATA_DMARQ 196
+MX51_PAD_NANDF_RB0__SD3_DATA3 197
+MX51_PAD_NANDF_RB1__CSPI_MOSI 198
+MX51_PAD_NANDF_RB1__ECSPI2_RDY 199
+MX51_PAD_NANDF_RB1__GPIO3_9 200
+MX51_PAD_NANDF_RB1__NANDF_RB1 201
+MX51_PAD_NANDF_RB1__PATA_IORDY 202
+MX51_PAD_NANDF_RB1__SD4_CMD 203
+MX51_PAD_NANDF_RB2__DISP2_WAIT 204
+MX51_PAD_NANDF_RB2__ECSPI2_SCLK 205
+MX51_PAD_NANDF_RB2__FEC_COL 206
+MX51_PAD_NANDF_RB2__GPIO3_10 207
+MX51_PAD_NANDF_RB2__NANDF_RB2 208
+MX51_PAD_NANDF_RB2__USBH3_H3_DP 209
+MX51_PAD_NANDF_RB2__USBH3_NXT 210
+MX51_PAD_NANDF_RB3__DISP1_WAIT 211
+MX51_PAD_NANDF_RB3__ECSPI2_MISO 212
+MX51_PAD_NANDF_RB3__FEC_RX_CLK 213
+MX51_PAD_NANDF_RB3__GPIO3_11 214
+MX51_PAD_NANDF_RB3__NANDF_RB3 215
+MX51_PAD_NANDF_RB3__USBH3_CLK 216
+MX51_PAD_NANDF_RB3__USBH3_H3_DM 217
+MX51_PAD_GPIO_NAND__GPIO_NAND 218
+MX51_PAD_GPIO_NAND__PATA_INTRQ 219
+MX51_PAD_NANDF_CS0__GPIO3_16 220
+MX51_PAD_NANDF_CS0__NANDF_CS0 221
+MX51_PAD_NANDF_CS1__GPIO3_17 222
+MX51_PAD_NANDF_CS1__NANDF_CS1 223
+MX51_PAD_NANDF_CS2__CSPI_SCLK 224
+MX51_PAD_NANDF_CS2__FEC_TX_ER 225
+MX51_PAD_NANDF_CS2__GPIO3_18 226
+MX51_PAD_NANDF_CS2__NANDF_CS2 227
+MX51_PAD_NANDF_CS2__PATA_CS_0 228
+MX51_PAD_NANDF_CS2__SD4_CLK 229
+MX51_PAD_NANDF_CS2__USBH3_H1_DP 230
+MX51_PAD_NANDF_CS3__FEC_MDC 231
+MX51_PAD_NANDF_CS3__GPIO3_19 232
+MX51_PAD_NANDF_CS3__NANDF_CS3 233
+MX51_PAD_NANDF_CS3__PATA_CS_1 234
+MX51_PAD_NANDF_CS3__SD4_DAT0 235
+MX51_PAD_NANDF_CS3__USBH3_H1_DM 236
+MX51_PAD_NANDF_CS4__FEC_TDATA1 237
+MX51_PAD_NANDF_CS4__GPIO3_20 238
+MX51_PAD_NANDF_CS4__NANDF_CS4 239
+MX51_PAD_NANDF_CS4__PATA_DA_0 240
+MX51_PAD_NANDF_CS4__SD4_DAT1 241
+MX51_PAD_NANDF_CS4__USBH3_STP 242
+MX51_PAD_NANDF_CS5__FEC_TDATA2 243
+MX51_PAD_NANDF_CS5__GPIO3_21 244
+MX51_PAD_NANDF_CS5__NANDF_CS5 245
+MX51_PAD_NANDF_CS5__PATA_DA_1 246
+MX51_PAD_NANDF_CS5__SD4_DAT2 247
+MX51_PAD_NANDF_CS5__USBH3_DIR 248
+MX51_PAD_NANDF_CS6__CSPI_SS3 249
+MX51_PAD_NANDF_CS6__FEC_TDATA3 250
+MX51_PAD_NANDF_CS6__GPIO3_22 251
+MX51_PAD_NANDF_CS6__NANDF_CS6 252
+MX51_PAD_NANDF_CS6__PATA_DA_2 253
+MX51_PAD_NANDF_CS6__SD4_DAT3 254
+MX51_PAD_NANDF_CS7__FEC_TX_EN 255
+MX51_PAD_NANDF_CS7__GPIO3_23 256
+MX51_PAD_NANDF_CS7__NANDF_CS7 257
+MX51_PAD_NANDF_CS7__SD3_CLK 258
+MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0 259
+MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK 260
+MX51_PAD_NANDF_RDY_INT__GPIO3_24 261
+MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT 262
+MX51_PAD_NANDF_RDY_INT__SD3_CMD 263
+MX51_PAD_NANDF_D15__ECSPI2_MOSI 264
+MX51_PAD_NANDF_D15__GPIO3_25 265
+MX51_PAD_NANDF_D15__NANDF_D15 266
+MX51_PAD_NANDF_D15__PATA_DATA15 267
+MX51_PAD_NANDF_D15__SD3_DAT7 268
+MX51_PAD_NANDF_D14__ECSPI2_SS3 269
+MX51_PAD_NANDF_D14__GPIO3_26 270
+MX51_PAD_NANDF_D14__NANDF_D14 271
+MX51_PAD_NANDF_D14__PATA_DATA14 272
+MX51_PAD_NANDF_D14__SD3_DAT6 273
+MX51_PAD_NANDF_D13__ECSPI2_SS2 274
+MX51_PAD_NANDF_D13__GPIO3_27 275
+MX51_PAD_NANDF_D13__NANDF_D13 276
+MX51_PAD_NANDF_D13__PATA_DATA13 277
+MX51_PAD_NANDF_D13__SD3_DAT5 278
+MX51_PAD_NANDF_D12__ECSPI2_SS1 279
+MX51_PAD_NANDF_D12__GPIO3_28 280
+MX51_PAD_NANDF_D12__NANDF_D12 281
+MX51_PAD_NANDF_D12__PATA_DATA12 282
+MX51_PAD_NANDF_D12__SD3_DAT4 283
+MX51_PAD_NANDF_D11__FEC_RX_DV 284
+MX51_PAD_NANDF_D11__GPIO3_29 285
+MX51_PAD_NANDF_D11__NANDF_D11 286
+MX51_PAD_NANDF_D11__PATA_DATA11 287
+MX51_PAD_NANDF_D11__SD3_DATA3 288
+MX51_PAD_NANDF_D10__GPIO3_30 289
+MX51_PAD_NANDF_D10__NANDF_D10 290
+MX51_PAD_NANDF_D10__PATA_DATA10 291
+MX51_PAD_NANDF_D10__SD3_DATA2 292
+MX51_PAD_NANDF_D9__FEC_RDATA0 293
+MX51_PAD_NANDF_D9__GPIO3_31 294
+MX51_PAD_NANDF_D9__NANDF_D9 295
+MX51_PAD_NANDF_D9__PATA_DATA9 296
+MX51_PAD_NANDF_D9__SD3_DATA1 297
+MX51_PAD_NANDF_D8__FEC_TDATA0 298
+MX51_PAD_NANDF_D8__GPIO4_0 299
+MX51_PAD_NANDF_D8__NANDF_D8 300
+MX51_PAD_NANDF_D8__PATA_DATA8 301
+MX51_PAD_NANDF_D8__SD3_DATA0 302
+MX51_PAD_NANDF_D7__GPIO4_1 303
+MX51_PAD_NANDF_D7__NANDF_D7 304
+MX51_PAD_NANDF_D7__PATA_DATA7 305
+MX51_PAD_NANDF_D7__USBH3_DATA0 306
+MX51_PAD_NANDF_D6__GPIO4_2 307
+MX51_PAD_NANDF_D6__NANDF_D6 308
+MX51_PAD_NANDF_D6__PATA_DATA6 309
+MX51_PAD_NANDF_D6__SD4_LCTL 310
+MX51_PAD_NANDF_D6__USBH3_DATA1 311
+MX51_PAD_NANDF_D5__GPIO4_3 312
+MX51_PAD_NANDF_D5__NANDF_D5 313
+MX51_PAD_NANDF_D5__PATA_DATA5 314
+MX51_PAD_NANDF_D5__SD4_WP 315
+MX51_PAD_NANDF_D5__USBH3_DATA2 316
+MX51_PAD_NANDF_D4__GPIO4_4 317
+MX51_PAD_NANDF_D4__NANDF_D4 318
+MX51_PAD_NANDF_D4__PATA_DATA4 319
+MX51_PAD_NANDF_D4__SD4_CD 320
+MX51_PAD_NANDF_D4__USBH3_DATA3 321
+MX51_PAD_NANDF_D3__GPIO4_5 322
+MX51_PAD_NANDF_D3__NANDF_D3 323
+MX51_PAD_NANDF_D3__PATA_DATA3 324
+MX51_PAD_NANDF_D3__SD4_DAT4 325
+MX51_PAD_NANDF_D3__USBH3_DATA4 326
+MX51_PAD_NANDF_D2__GPIO4_6 327
+MX51_PAD_NANDF_D2__NANDF_D2 328
+MX51_PAD_NANDF_D2__PATA_DATA2 329
+MX51_PAD_NANDF_D2__SD4_DAT5 330
+MX51_PAD_NANDF_D2__USBH3_DATA5 331
+MX51_PAD_NANDF_D1__GPIO4_7 332
+MX51_PAD_NANDF_D1__NANDF_D1 333
+MX51_PAD_NANDF_D1__PATA_DATA1 334
+MX51_PAD_NANDF_D1__SD4_DAT6 335
+MX51_PAD_NANDF_D1__USBH3_DATA6 336
+MX51_PAD_NANDF_D0__GPIO4_8 337
+MX51_PAD_NANDF_D0__NANDF_D0 338
+MX51_PAD_NANDF_D0__PATA_DATA0 339
+MX51_PAD_NANDF_D0__SD4_DAT7 340
+MX51_PAD_NANDF_D0__USBH3_DATA7 341
+MX51_PAD_CSI1_D8__CSI1_D8 342
+MX51_PAD_CSI1_D8__GPIO3_12 343
+MX51_PAD_CSI1_D9__CSI1_D9 344
+MX51_PAD_CSI1_D9__GPIO3_13 345
+MX51_PAD_CSI1_D10__CSI1_D10 346
+MX51_PAD_CSI1_D11__CSI1_D11 347
+MX51_PAD_CSI1_D12__CSI1_D12 348
+MX51_PAD_CSI1_D13__CSI1_D13 349
+MX51_PAD_CSI1_D14__CSI1_D14 350
+MX51_PAD_CSI1_D15__CSI1_D15 351
+MX51_PAD_CSI1_D16__CSI1_D16 352
+MX51_PAD_CSI1_D17__CSI1_D17 353
+MX51_PAD_CSI1_D18__CSI1_D18 354
+MX51_PAD_CSI1_D19__CSI1_D19 355
+MX51_PAD_CSI1_VSYNC__CSI1_VSYNC 356
+MX51_PAD_CSI1_VSYNC__GPIO3_14 357
+MX51_PAD_CSI1_HSYNC__CSI1_HSYNC 358
+MX51_PAD_CSI1_HSYNC__GPIO3_15 359
+MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK 360
+MX51_PAD_CSI1_MCLK__CSI1_MCLK 361
+MX51_PAD_CSI2_D12__CSI2_D12 362
+MX51_PAD_CSI2_D12__GPIO4_9 363
+MX51_PAD_CSI2_D13__CSI2_D13 364
+MX51_PAD_CSI2_D13__GPIO4_10 365
+MX51_PAD_CSI2_D14__CSI2_D14 366
+MX51_PAD_CSI2_D15__CSI2_D15 367
+MX51_PAD_CSI2_D16__CSI2_D16 368
+MX51_PAD_CSI2_D17__CSI2_D17 369
+MX51_PAD_CSI2_D18__CSI2_D18 370
+MX51_PAD_CSI2_D18__GPIO4_11 371
+MX51_PAD_CSI2_D19__CSI2_D19 372
+MX51_PAD_CSI2_D19__GPIO4_12 373
+MX51_PAD_CSI2_VSYNC__CSI2_VSYNC 374
+MX51_PAD_CSI2_VSYNC__GPIO4_13 375
+MX51_PAD_CSI2_HSYNC__CSI2_HSYNC 376
+MX51_PAD_CSI2_HSYNC__GPIO4_14 377
+MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK 378
+MX51_PAD_CSI2_PIXCLK__GPIO4_15 379
+MX51_PAD_I2C1_CLK__GPIO4_16 380
+MX51_PAD_I2C1_CLK__I2C1_CLK 381
+MX51_PAD_I2C1_DAT__GPIO4_17 382
+MX51_PAD_I2C1_DAT__I2C1_DAT 383
+MX51_PAD_AUD3_BB_TXD__AUD3_TXD 384
+MX51_PAD_AUD3_BB_TXD__GPIO4_18 385
+MX51_PAD_AUD3_BB_RXD__AUD3_RXD 386
+MX51_PAD_AUD3_BB_RXD__GPIO4_19 387
+MX51_PAD_AUD3_BB_RXD__UART3_RXD 388
+MX51_PAD_AUD3_BB_CK__AUD3_TXC 389
+MX51_PAD_AUD3_BB_CK__GPIO4_20 390
+MX51_PAD_AUD3_BB_FS__AUD3_TXFS 391
+MX51_PAD_AUD3_BB_FS__GPIO4_21 392
+MX51_PAD_AUD3_BB_FS__UART3_TXD 393
+MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 394
+MX51_PAD_CSPI1_MOSI__GPIO4_22 395
+MX51_PAD_CSPI1_MOSI__I2C1_SDA 396
+MX51_PAD_CSPI1_MISO__AUD4_RXD 397
+MX51_PAD_CSPI1_MISO__ECSPI1_MISO 398
+MX51_PAD_CSPI1_MISO__GPIO4_23 399
+MX51_PAD_CSPI1_SS0__AUD4_TXC 400
+MX51_PAD_CSPI1_SS0__ECSPI1_SS0 401
+MX51_PAD_CSPI1_SS0__GPIO4_24 402
+MX51_PAD_CSPI1_SS1__AUD4_TXD 403
+MX51_PAD_CSPI1_SS1__ECSPI1_SS1 404
+MX51_PAD_CSPI1_SS1__GPIO4_25 405
+MX51_PAD_CSPI1_RDY__AUD4_TXFS 406
+MX51_PAD_CSPI1_RDY__ECSPI1_RDY 407
+MX51_PAD_CSPI1_RDY__GPIO4_26 408
+MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 409
+MX51_PAD_CSPI1_SCLK__GPIO4_27 410
+MX51_PAD_CSPI1_SCLK__I2C1_SCL 411
+MX51_PAD_UART1_RXD__GPIO4_28 412
+MX51_PAD_UART1_RXD__UART1_RXD 413
+MX51_PAD_UART1_TXD__GPIO4_29 414
+MX51_PAD_UART1_TXD__PWM2_PWMO 415
+MX51_PAD_UART1_TXD__UART1_TXD 416
+MX51_PAD_UART1_RTS__GPIO4_30 417
+MX51_PAD_UART1_RTS__UART1_RTS 418
+MX51_PAD_UART1_CTS__GPIO4_31 419
+MX51_PAD_UART1_CTS__UART1_CTS 420
+MX51_PAD_UART2_RXD__FIRI_TXD 421
+MX51_PAD_UART2_RXD__GPIO1_20 422
+MX51_PAD_UART2_RXD__UART2_RXD 423
+MX51_PAD_UART2_TXD__FIRI_RXD 424
+MX51_PAD_UART2_TXD__GPIO1_21 425
+MX51_PAD_UART2_TXD__UART2_TXD 426
+MX51_PAD_UART3_RXD__CSI1_D0 427
+MX51_PAD_UART3_RXD__GPIO1_22 428
+MX51_PAD_UART3_RXD__UART1_DTR 429
+MX51_PAD_UART3_RXD__UART3_RXD 430
+MX51_PAD_UART3_TXD__CSI1_D1 431
+MX51_PAD_UART3_TXD__GPIO1_23 432
+MX51_PAD_UART3_TXD__UART1_DSR 433
+MX51_PAD_UART3_TXD__UART3_TXD 434
+MX51_PAD_OWIRE_LINE__GPIO1_24 435
+MX51_PAD_OWIRE_LINE__OWIRE_LINE 436
+MX51_PAD_OWIRE_LINE__SPDIF_OUT 437
+MX51_PAD_KEY_ROW0__KEY_ROW0 438
+MX51_PAD_KEY_ROW1__KEY_ROW1 439
+MX51_PAD_KEY_ROW2__KEY_ROW2 440
+MX51_PAD_KEY_ROW3__KEY_ROW3 441
+MX51_PAD_KEY_COL0__KEY_COL0 442
+MX51_PAD_KEY_COL0__PLL1_BYP 443
+MX51_PAD_KEY_COL1__KEY_COL1 444
+MX51_PAD_KEY_COL1__PLL2_BYP 445
+MX51_PAD_KEY_COL2__KEY_COL2 446
+MX51_PAD_KEY_COL2__PLL3_BYP 447
+MX51_PAD_KEY_COL3__KEY_COL3 448
+MX51_PAD_KEY_COL4__I2C2_SCL 449
+MX51_PAD_KEY_COL4__KEY_COL4 450
+MX51_PAD_KEY_COL4__SPDIF_OUT1 451
+MX51_PAD_KEY_COL4__UART1_RI 452
+MX51_PAD_KEY_COL4__UART3_RTS 453
+MX51_PAD_KEY_COL5__I2C2_SDA 454
+MX51_PAD_KEY_COL5__KEY_COL5 455
+MX51_PAD_KEY_COL5__UART1_DCD 456
+MX51_PAD_KEY_COL5__UART3_CTS 457
+MX51_PAD_USBH1_CLK__CSPI_SCLK 458
+MX51_PAD_USBH1_CLK__GPIO1_25 459
+MX51_PAD_USBH1_CLK__I2C2_SCL 460
+MX51_PAD_USBH1_CLK__USBH1_CLK 461
+MX51_PAD_USBH1_DIR__CSPI_MOSI 462
+MX51_PAD_USBH1_DIR__GPIO1_26 463
+MX51_PAD_USBH1_DIR__I2C2_SDA 464
+MX51_PAD_USBH1_DIR__USBH1_DIR 465
+MX51_PAD_USBH1_STP__CSPI_RDY 466
+MX51_PAD_USBH1_STP__GPIO1_27 467
+MX51_PAD_USBH1_STP__UART3_RXD 468
+MX51_PAD_USBH1_STP__USBH1_STP 469
+MX51_PAD_USBH1_NXT__CSPI_MISO 470
+MX51_PAD_USBH1_NXT__GPIO1_28 471
+MX51_PAD_USBH1_NXT__UART3_TXD 472
+MX51_PAD_USBH1_NXT__USBH1_NXT 473
+MX51_PAD_USBH1_DATA0__GPIO1_11 474
+MX51_PAD_USBH1_DATA0__UART2_CTS 475
+MX51_PAD_USBH1_DATA0__USBH1_DATA0 476
+MX51_PAD_USBH1_DATA1__GPIO1_12 477
+MX51_PAD_USBH1_DATA1__UART2_RXD 478
+MX51_PAD_USBH1_DATA1__USBH1_DATA1 479
+MX51_PAD_USBH1_DATA2__GPIO1_13 480
+MX51_PAD_USBH1_DATA2__UART2_TXD 481
+MX51_PAD_USBH1_DATA2__USBH1_DATA2 482
+MX51_PAD_USBH1_DATA3__GPIO1_14 483
+MX51_PAD_USBH1_DATA3__UART2_RTS 484
+MX51_PAD_USBH1_DATA3__USBH1_DATA3 485
+MX51_PAD_USBH1_DATA4__CSPI_SS0 486
+MX51_PAD_USBH1_DATA4__GPIO1_15 487
+MX51_PAD_USBH1_DATA4__USBH1_DATA4 488
+MX51_PAD_USBH1_DATA5__CSPI_SS1 489
+MX51_PAD_USBH1_DATA5__GPIO1_16 490
+MX51_PAD_USBH1_DATA5__USBH1_DATA5 491
+MX51_PAD_USBH1_DATA6__CSPI_SS3 492
+MX51_PAD_USBH1_DATA6__GPIO1_17 493
+MX51_PAD_USBH1_DATA6__USBH1_DATA6 494
+MX51_PAD_USBH1_DATA7__ECSPI1_SS3 495
+MX51_PAD_USBH1_DATA7__ECSPI2_SS3 496
+MX51_PAD_USBH1_DATA7__GPIO1_18 497
+MX51_PAD_USBH1_DATA7__USBH1_DATA7 498
+MX51_PAD_DI1_PIN11__DI1_PIN11 499
+MX51_PAD_DI1_PIN11__ECSPI1_SS2 500
+MX51_PAD_DI1_PIN11__GPIO3_0 501
+MX51_PAD_DI1_PIN12__DI1_PIN12 502
+MX51_PAD_DI1_PIN12__GPIO3_1 503
+MX51_PAD_DI1_PIN13__DI1_PIN13 504
+MX51_PAD_DI1_PIN13__GPIO3_2 505
+MX51_PAD_DI1_D0_CS__DI1_D0_CS 506
+MX51_PAD_DI1_D0_CS__GPIO3_3 507
+MX51_PAD_DI1_D1_CS__DI1_D1_CS 508
+MX51_PAD_DI1_D1_CS__DISP1_PIN14 509
+MX51_PAD_DI1_D1_CS__DISP1_PIN5 510
+MX51_PAD_DI1_D1_CS__GPIO3_4 511
+MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1 512
+MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN 513
+MX51_PAD_DISPB2_SER_DIN__GPIO3_5 514
+MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6 515
+MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO 516
+MX51_PAD_DISPB2_SER_DIO__GPIO3_6 517
+MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17 518
+MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7 519
+MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK 520
+MX51_PAD_DISPB2_SER_CLK__GPIO3_7 521
+MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK 522
+MX51_PAD_DISPB2_SER_RS__DISP1_PIN16 523
+MX51_PAD_DISPB2_SER_RS__DISP1_PIN8 524
+MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS 525
+MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS 526
+MX51_PAD_DISPB2_SER_RS__GPIO3_8 527
+MX51_PAD_DISP1_DAT0__DISP1_DAT0 528
+MX51_PAD_DISP1_DAT1__DISP1_DAT1 529
+MX51_PAD_DISP1_DAT2__DISP1_DAT2 530
+MX51_PAD_DISP1_DAT3__DISP1_DAT3 531
+MX51_PAD_DISP1_DAT4__DISP1_DAT4 532
+MX51_PAD_DISP1_DAT5__DISP1_DAT5 533
+MX51_PAD_DISP1_DAT6__BOOT_USB_SRC 534
+MX51_PAD_DISP1_DAT6__DISP1_DAT6 535
+MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG 536
+MX51_PAD_DISP1_DAT7__DISP1_DAT7 537
+MX51_PAD_DISP1_DAT8__BOOT_SRC0 538
+MX51_PAD_DISP1_DAT8__DISP1_DAT8 539
+MX51_PAD_DISP1_DAT9__BOOT_SRC1 540
+MX51_PAD_DISP1_DAT9__DISP1_DAT9 541
+MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE 542
+MX51_PAD_DISP1_DAT10__DISP1_DAT10 543
+MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2 544
+MX51_PAD_DISP1_DAT11__DISP1_DAT11 545
+MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL 546
+MX51_PAD_DISP1_DAT12__DISP1_DAT12 547
+MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0 548
+MX51_PAD_DISP1_DAT13__DISP1_DAT13 549
+MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1 550
+MX51_PAD_DISP1_DAT14__DISP1_DAT14 551
+MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH 552
+MX51_PAD_DISP1_DAT15__DISP1_DAT15 553
+MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0 554
+MX51_PAD_DISP1_DAT16__DISP1_DAT16 555
+MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1 556
+MX51_PAD_DISP1_DAT17__DISP1_DAT17 557
+MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0 558
+MX51_PAD_DISP1_DAT18__DISP1_DAT18 559
+MX51_PAD_DISP1_DAT18__DISP2_PIN11 560
+MX51_PAD_DISP1_DAT18__DISP2_PIN5 561
+MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1 562
+MX51_PAD_DISP1_DAT19__DISP1_DAT19 563
+MX51_PAD_DISP1_DAT19__DISP2_PIN12 564
+MX51_PAD_DISP1_DAT19__DISP2_PIN6 565
+MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0 566
+MX51_PAD_DISP1_DAT20__DISP1_DAT20 567
+MX51_PAD_DISP1_DAT20__DISP2_PIN13 568
+MX51_PAD_DISP1_DAT20__DISP2_PIN7 569
+MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1 570
+MX51_PAD_DISP1_DAT21__DISP1_DAT21 571
+MX51_PAD_DISP1_DAT21__DISP2_PIN14 572
+MX51_PAD_DISP1_DAT21__DISP2_PIN8 573
+MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0 574
+MX51_PAD_DISP1_DAT22__DISP1_DAT22 575
+MX51_PAD_DISP1_DAT22__DISP2_D0_CS 576
+MX51_PAD_DISP1_DAT22__DISP2_DAT16 577
+MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1 578
+MX51_PAD_DISP1_DAT23__DISP1_DAT23 579
+MX51_PAD_DISP1_DAT23__DISP2_D1_CS 580
+MX51_PAD_DISP1_DAT23__DISP2_DAT17 581
+MX51_PAD_DISP1_DAT23__DISP2_SER_CS 582
+MX51_PAD_DI1_PIN3__DI1_PIN3 583
+MX51_PAD_DI1_PIN2__DI1_PIN2 584
+MX51_PAD_DI_GP2__DISP1_SER_CLK 585
+MX51_PAD_DI_GP2__DISP2_WAIT 586
+MX51_PAD_DI_GP3__CSI1_DATA_EN 587
+MX51_PAD_DI_GP3__DISP1_SER_DIO 588
+MX51_PAD_DI_GP3__FEC_TX_ER 589
+MX51_PAD_DI2_PIN4__CSI2_DATA_EN 590
+MX51_PAD_DI2_PIN4__DI2_PIN4 591
+MX51_PAD_DI2_PIN4__FEC_CRS 592
+MX51_PAD_DI2_PIN2__DI2_PIN2 593
+MX51_PAD_DI2_PIN2__FEC_MDC 594
+MX51_PAD_DI2_PIN3__DI2_PIN3 595
+MX51_PAD_DI2_PIN3__FEC_MDIO 596
+MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK 597
+MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 598
+MX51_PAD_DI_GP4__DI2_PIN15 599
+MX51_PAD_DI_GP4__DISP1_SER_DIN 600
+MX51_PAD_DI_GP4__DISP2_PIN1 601
+MX51_PAD_DI_GP4__FEC_RDATA2 602
+MX51_PAD_DISP2_DAT0__DISP2_DAT0 603
+MX51_PAD_DISP2_DAT0__FEC_RDATA3 604
+MX51_PAD_DISP2_DAT0__KEY_COL6 605
+MX51_PAD_DISP2_DAT0__UART3_RXD 606
+MX51_PAD_DISP2_DAT0__USBH3_CLK 607
+MX51_PAD_DISP2_DAT1__DISP2_DAT1 608
+MX51_PAD_DISP2_DAT1__FEC_RX_ER 609
+MX51_PAD_DISP2_DAT1__KEY_COL7 610
+MX51_PAD_DISP2_DAT1__UART3_TXD 611
+MX51_PAD_DISP2_DAT1__USBH3_DIR 612
+MX51_PAD_DISP2_DAT2__DISP2_DAT2 613
+MX51_PAD_DISP2_DAT3__DISP2_DAT3 614
+MX51_PAD_DISP2_DAT4__DISP2_DAT4 615
+MX51_PAD_DISP2_DAT5__DISP2_DAT5 616
+MX51_PAD_DISP2_DAT6__DISP2_DAT6 617
+MX51_PAD_DISP2_DAT6__FEC_TDATA1 618
+MX51_PAD_DISP2_DAT6__GPIO1_19 619
+MX51_PAD_DISP2_DAT6__KEY_ROW4 620
+MX51_PAD_DISP2_DAT6__USBH3_STP 621
+MX51_PAD_DISP2_DAT7__DISP2_DAT7 622
+MX51_PAD_DISP2_DAT7__FEC_TDATA2 623
+MX51_PAD_DISP2_DAT7__GPIO1_29 624
+MX51_PAD_DISP2_DAT7__KEY_ROW5 625
+MX51_PAD_DISP2_DAT7__USBH3_NXT 626
+MX51_PAD_DISP2_DAT8__DISP2_DAT8 627
+MX51_PAD_DISP2_DAT8__FEC_TDATA3 628
+MX51_PAD_DISP2_DAT8__GPIO1_30 629
+MX51_PAD_DISP2_DAT8__KEY_ROW6 630
+MX51_PAD_DISP2_DAT8__USBH3_DATA0 631
+MX51_PAD_DISP2_DAT9__AUD6_RXC 632
+MX51_PAD_DISP2_DAT9__DISP2_DAT9 633
+MX51_PAD_DISP2_DAT9__FEC_TX_EN 634
+MX51_PAD_DISP2_DAT9__GPIO1_31 635
+MX51_PAD_DISP2_DAT9__USBH3_DATA1 636
+MX51_PAD_DISP2_DAT10__DISP2_DAT10 637
+MX51_PAD_DISP2_DAT10__DISP2_SER_CS 638
+MX51_PAD_DISP2_DAT10__FEC_COL 639
+MX51_PAD_DISP2_DAT10__KEY_ROW7 640
+MX51_PAD_DISP2_DAT10__USBH3_DATA2 641
+MX51_PAD_DISP2_DAT11__AUD6_TXD 642
+MX51_PAD_DISP2_DAT11__DISP2_DAT11 643
+MX51_PAD_DISP2_DAT11__FEC_RX_CLK 644
+MX51_PAD_DISP2_DAT11__GPIO1_10 645
+MX51_PAD_DISP2_DAT11__USBH3_DATA3 646
+MX51_PAD_DISP2_DAT12__AUD6_RXD 647
+MX51_PAD_DISP2_DAT12__DISP2_DAT12 648
+MX51_PAD_DISP2_DAT12__FEC_RX_DV 649
+MX51_PAD_DISP2_DAT12__USBH3_DATA4 650
+MX51_PAD_DISP2_DAT13__AUD6_TXC 651
+MX51_PAD_DISP2_DAT13__DISP2_DAT13 652
+MX51_PAD_DISP2_DAT13__FEC_TX_CLK 653
+MX51_PAD_DISP2_DAT13__USBH3_DATA5 654
+MX51_PAD_DISP2_DAT14__AUD6_TXFS 655
+MX51_PAD_DISP2_DAT14__DISP2_DAT14 656
+MX51_PAD_DISP2_DAT14__FEC_RDATA0 657
+MX51_PAD_DISP2_DAT14__USBH3_DATA6 658
+MX51_PAD_DISP2_DAT15__AUD6_RXFS 659
+MX51_PAD_DISP2_DAT15__DISP1_SER_CS 660
+MX51_PAD_DISP2_DAT15__DISP2_DAT15 661
+MX51_PAD_DISP2_DAT15__FEC_TDATA0 662
+MX51_PAD_DISP2_DAT15__USBH3_DATA7 663
+MX51_PAD_SD1_CMD__AUD5_RXFS 664
+MX51_PAD_SD1_CMD__CSPI_MOSI 665
+MX51_PAD_SD1_CMD__SD1_CMD 666
+MX51_PAD_SD1_CLK__AUD5_RXC 667
+MX51_PAD_SD1_CLK__CSPI_SCLK 668
+MX51_PAD_SD1_CLK__SD1_CLK 669
+MX51_PAD_SD1_DATA0__AUD5_TXD 670
+MX51_PAD_SD1_DATA0__CSPI_MISO 671
+MX51_PAD_SD1_DATA0__SD1_DATA0 672
+MX51_PAD_EIM_DA0__EIM_DA0 673
+MX51_PAD_EIM_DA1__EIM_DA1 674
+MX51_PAD_EIM_DA2__EIM_DA2 675
+MX51_PAD_EIM_DA3__EIM_DA3 676
+MX51_PAD_SD1_DATA1__AUD5_RXD 677
+MX51_PAD_SD1_DATA1__SD1_DATA1 678
+MX51_PAD_EIM_DA4__EIM_DA4 679
+MX51_PAD_EIM_DA5__EIM_DA5 680
+MX51_PAD_EIM_DA6__EIM_DA6 681
+MX51_PAD_EIM_DA7__EIM_DA7 682
+MX51_PAD_SD1_DATA2__AUD5_TXC 683
+MX51_PAD_SD1_DATA2__SD1_DATA2 684
+MX51_PAD_EIM_DA10__EIM_DA10 685
+MX51_PAD_EIM_DA11__EIM_DA11 686
+MX51_PAD_EIM_DA8__EIM_DA8 687
+MX51_PAD_EIM_DA9__EIM_DA9 688
+MX51_PAD_SD1_DATA3__AUD5_TXFS 689
+MX51_PAD_SD1_DATA3__CSPI_SS1 690
+MX51_PAD_SD1_DATA3__SD1_DATA3 691
+MX51_PAD_GPIO1_0__CSPI_SS2 692
+MX51_PAD_GPIO1_0__GPIO1_0 693
+MX51_PAD_GPIO1_0__SD1_CD 694
+MX51_PAD_GPIO1_1__CSPI_MISO 695
+MX51_PAD_GPIO1_1__GPIO1_1 696
+MX51_PAD_GPIO1_1__SD1_WP 697
+MX51_PAD_EIM_DA12__EIM_DA12 698
+MX51_PAD_EIM_DA13__EIM_DA13 699
+MX51_PAD_EIM_DA14__EIM_DA14 700
+MX51_PAD_EIM_DA15__EIM_DA15 701
+MX51_PAD_SD2_CMD__CSPI_MOSI 702
+MX51_PAD_SD2_CMD__I2C1_SCL 703
+MX51_PAD_SD2_CMD__SD2_CMD 704
+MX51_PAD_SD2_CLK__CSPI_SCLK 705
+MX51_PAD_SD2_CLK__I2C1_SDA 706
+MX51_PAD_SD2_CLK__SD2_CLK 707
+MX51_PAD_SD2_DATA0__CSPI_MISO 708
+MX51_PAD_SD2_DATA0__SD1_DAT4 709
+MX51_PAD_SD2_DATA0__SD2_DATA0 710
+MX51_PAD_SD2_DATA1__SD1_DAT5 711
+MX51_PAD_SD2_DATA1__SD2_DATA1 712
+MX51_PAD_SD2_DATA1__USBH3_H2_DP 713
+MX51_PAD_SD2_DATA2__SD1_DAT6 714
+MX51_PAD_SD2_DATA2__SD2_DATA2 715
+MX51_PAD_SD2_DATA2__USBH3_H2_DM 716
+MX51_PAD_SD2_DATA3__CSPI_SS2 717
+MX51_PAD_SD2_DATA3__SD1_DAT7 718
+MX51_PAD_SD2_DATA3__SD2_DATA3 719
+MX51_PAD_GPIO1_2__CCM_OUT_2 720
+MX51_PAD_GPIO1_2__GPIO1_2 721
+MX51_PAD_GPIO1_2__I2C2_SCL 722
+MX51_PAD_GPIO1_2__PLL1_BYP 723
+MX51_PAD_GPIO1_2__PWM1_PWMO 724
+MX51_PAD_GPIO1_3__GPIO1_3 725
+MX51_PAD_GPIO1_3__I2C2_SDA 726
+MX51_PAD_GPIO1_3__PLL2_BYP 727
+MX51_PAD_GPIO1_3__PWM2_PWMO 728
+MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ 729
+MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B 730
+MX51_PAD_GPIO1_4__DISP2_EXT_CLK 731
+MX51_PAD_GPIO1_4__EIM_RDY 732
+MX51_PAD_GPIO1_4__GPIO1_4 733
+MX51_PAD_GPIO1_4__WDOG1_WDOG_B 734
+MX51_PAD_GPIO1_5__CSI2_MCLK 735
+MX51_PAD_GPIO1_5__DISP2_PIN16 736
+MX51_PAD_GPIO1_5__GPIO1_5 737
+MX51_PAD_GPIO1_5__WDOG2_WDOG_B 738
+MX51_PAD_GPIO1_6__DISP2_PIN17 739
+MX51_PAD_GPIO1_6__GPIO1_6 740
+MX51_PAD_GPIO1_6__REF_EN_B 741
+MX51_PAD_GPIO1_7__CCM_OUT_0 742
+MX51_PAD_GPIO1_7__GPIO1_7 743
+MX51_PAD_GPIO1_7__SD2_WP 744
+MX51_PAD_GPIO1_7__SPDIF_OUT1 745
+MX51_PAD_GPIO1_8__CSI2_DATA_EN 746
+MX51_PAD_GPIO1_8__GPIO1_8 747
+MX51_PAD_GPIO1_8__SD2_CD 748
+MX51_PAD_GPIO1_8__USBH3_PWR 749
+MX51_PAD_GPIO1_9__CCM_OUT_1 750
+MX51_PAD_GPIO1_9__DISP2_D1_CS 751
+MX51_PAD_GPIO1_9__DISP2_SER_CS 752
+MX51_PAD_GPIO1_9__GPIO1_9 753
+MX51_PAD_GPIO1_9__SD2_LCTL 754
+MX51_PAD_GPIO1_9__USBH3_OC 755
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx53-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx53-pinctrl.txt
new file mode 100644
index 000000000000..ca85ca432ef0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx53-pinctrl.txt
@@ -0,0 +1,1202 @@
+* Freescale IMX53 IOMUX Controller
+
+Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
+and usage.
+
+Required properties:
+- compatible: "fsl,imx53-iomuxc"
+- fsl,pins: two integers array, represents a group of pins mux and config
+ setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
+ pin working on a specific function, CONFIG is the pad setting value like
+ pull-up for this pin. Please refer to imx53 datasheet for the valid pad
+ config settings.
+
+CONFIG bits definition:
+PAD_CTL_HVE (1 << 13)
+PAD_CTL_HYS (1 << 8)
+PAD_CTL_PKE (1 << 7)
+PAD_CTL_PUE (1 << 6)
+PAD_CTL_PUS_100K_DOWN (0 << 4)
+PAD_CTL_PUS_47K_UP (1 << 4)
+PAD_CTL_PUS_100K_UP (2 << 4)
+PAD_CTL_PUS_22K_UP (3 << 4)
+PAD_CTL_ODE (1 << 3)
+PAD_CTL_DSE_LOW (0 << 1)
+PAD_CTL_DSE_MED (1 << 1)
+PAD_CTL_DSE_HIGH (2 << 1)
+PAD_CTL_DSE_MAX (3 << 1)
+PAD_CTL_SRE_FAST (1 << 0)
+PAD_CTL_SRE_SLOW (0 << 0)
+
+See below for available PIN_FUNC_ID for imx53:
+MX53_PAD_GPIO_19__KPP_COL_5 0
+MX53_PAD_GPIO_19__GPIO4_5 1
+MX53_PAD_GPIO_19__CCM_CLKO 2
+MX53_PAD_GPIO_19__SPDIF_OUT1 3
+MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2 4
+MX53_PAD_GPIO_19__ECSPI1_RDY 5
+MX53_PAD_GPIO_19__FEC_TDATA_3 6
+MX53_PAD_GPIO_19__SRC_INT_BOOT 7
+MX53_PAD_KEY_COL0__KPP_COL_0 8
+MX53_PAD_KEY_COL0__GPIO4_6 9
+MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC 10
+MX53_PAD_KEY_COL0__UART4_TXD_MUX 11
+MX53_PAD_KEY_COL0__ECSPI1_SCLK 12
+MX53_PAD_KEY_COL0__FEC_RDATA_3 13
+MX53_PAD_KEY_COL0__SRC_ANY_PU_RST 14
+MX53_PAD_KEY_ROW0__KPP_ROW_0 15
+MX53_PAD_KEY_ROW0__GPIO4_7 16
+MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 17
+MX53_PAD_KEY_ROW0__UART4_RXD_MUX 18
+MX53_PAD_KEY_ROW0__ECSPI1_MOSI 19
+MX53_PAD_KEY_ROW0__FEC_TX_ER 20
+MX53_PAD_KEY_COL1__KPP_COL_1 21
+MX53_PAD_KEY_COL1__GPIO4_8 22
+MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 23
+MX53_PAD_KEY_COL1__UART5_TXD_MUX 24
+MX53_PAD_KEY_COL1__ECSPI1_MISO 25
+MX53_PAD_KEY_COL1__FEC_RX_CLK 26
+MX53_PAD_KEY_COL1__USBPHY1_TXREADY 27
+MX53_PAD_KEY_ROW1__KPP_ROW_1 28
+MX53_PAD_KEY_ROW1__GPIO4_9 29
+MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD 30
+MX53_PAD_KEY_ROW1__UART5_RXD_MUX 31
+MX53_PAD_KEY_ROW1__ECSPI1_SS0 32
+MX53_PAD_KEY_ROW1__FEC_COL 33
+MX53_PAD_KEY_ROW1__USBPHY1_RXVALID 34
+MX53_PAD_KEY_COL2__KPP_COL_2 35
+MX53_PAD_KEY_COL2__GPIO4_10 36
+MX53_PAD_KEY_COL2__CAN1_TXCAN 37
+MX53_PAD_KEY_COL2__FEC_MDIO 38
+MX53_PAD_KEY_COL2__ECSPI1_SS1 39
+MX53_PAD_KEY_COL2__FEC_RDATA_2 40
+MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE 41
+MX53_PAD_KEY_ROW2__KPP_ROW_2 42
+MX53_PAD_KEY_ROW2__GPIO4_11 43
+MX53_PAD_KEY_ROW2__CAN1_RXCAN 44
+MX53_PAD_KEY_ROW2__FEC_MDC 45
+MX53_PAD_KEY_ROW2__ECSPI1_SS2 46
+MX53_PAD_KEY_ROW2__FEC_TDATA_2 47
+MX53_PAD_KEY_ROW2__USBPHY1_RXERROR 48
+MX53_PAD_KEY_COL3__KPP_COL_3 49
+MX53_PAD_KEY_COL3__GPIO4_12 50
+MX53_PAD_KEY_COL3__USBOH3_H2_DP 51
+MX53_PAD_KEY_COL3__SPDIF_IN1 52
+MX53_PAD_KEY_COL3__I2C2_SCL 53
+MX53_PAD_KEY_COL3__ECSPI1_SS3 54
+MX53_PAD_KEY_COL3__FEC_CRS 55
+MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK 56
+MX53_PAD_KEY_ROW3__KPP_ROW_3 57
+MX53_PAD_KEY_ROW3__GPIO4_13 58
+MX53_PAD_KEY_ROW3__USBOH3_H2_DM 59
+MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK 60
+MX53_PAD_KEY_ROW3__I2C2_SDA 61
+MX53_PAD_KEY_ROW3__OSC32K_32K_OUT 62
+MX53_PAD_KEY_ROW3__CCM_PLL4_BYP 63
+MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0 64
+MX53_PAD_KEY_COL4__KPP_COL_4 65
+MX53_PAD_KEY_COL4__GPIO4_14 66
+MX53_PAD_KEY_COL4__CAN2_TXCAN 67
+MX53_PAD_KEY_COL4__IPU_SISG_4 68
+MX53_PAD_KEY_COL4__UART5_RTS 69
+MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC 70
+MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1 71
+MX53_PAD_KEY_ROW4__KPP_ROW_4 72
+MX53_PAD_KEY_ROW4__GPIO4_15 73
+MX53_PAD_KEY_ROW4__CAN2_RXCAN 74
+MX53_PAD_KEY_ROW4__IPU_SISG_5 75
+MX53_PAD_KEY_ROW4__UART5_CTS 76
+MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR 77
+MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID 78
+MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK 79
+MX53_PAD_DI0_DISP_CLK__GPIO4_16 80
+MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR 81
+MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0 82
+MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0 83
+MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID 84
+MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 85
+MX53_PAD_DI0_PIN15__GPIO4_17 86
+MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC 87
+MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1 88
+MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1 89
+MX53_PAD_DI0_PIN15__USBPHY1_BVALID 90
+MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 91
+MX53_PAD_DI0_PIN2__GPIO4_18 92
+MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD 93
+MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2 94
+MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2 95
+MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION 96
+MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 97
+MX53_PAD_DI0_PIN3__GPIO4_19 98
+MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS 99
+MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3 100
+MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3 101
+MX53_PAD_DI0_PIN3__USBPHY1_IDDIG 102
+MX53_PAD_DI0_PIN4__IPU_DI0_PIN4 103
+MX53_PAD_DI0_PIN4__GPIO4_20 104
+MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD 105
+MX53_PAD_DI0_PIN4__ESDHC1_WP 106
+MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD 107
+MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4 108
+MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT 109
+MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 110
+MX53_PAD_DISP0_DAT0__GPIO4_21 111
+MX53_PAD_DISP0_DAT0__CSPI_SCLK 112
+MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0 113
+MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN 114
+MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5 115
+MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY 116
+MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 117
+MX53_PAD_DISP0_DAT1__GPIO4_22 118
+MX53_PAD_DISP0_DAT1__CSPI_MOSI 119
+MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1 120
+MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL 121
+MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6 122
+MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID 123
+MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 124
+MX53_PAD_DISP0_DAT2__GPIO4_23 125
+MX53_PAD_DISP0_DAT2__CSPI_MISO 126
+MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2 127
+MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE 128
+MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7 129
+MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE 130
+MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 131
+MX53_PAD_DISP0_DAT3__GPIO4_24 132
+MX53_PAD_DISP0_DAT3__CSPI_SS0 133
+MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3 134
+MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR 135
+MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8 136
+MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR 137
+MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 138
+MX53_PAD_DISP0_DAT4__GPIO4_25 139
+MX53_PAD_DISP0_DAT4__CSPI_SS1 140
+MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4 141
+MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB 142
+MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9 143
+MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK 144
+MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 145
+MX53_PAD_DISP0_DAT5__GPIO4_26 146
+MX53_PAD_DISP0_DAT5__CSPI_SS2 147
+MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5 148
+MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS 149
+MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10 150
+MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0 151
+MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 152
+MX53_PAD_DISP0_DAT6__GPIO4_27 153
+MX53_PAD_DISP0_DAT6__CSPI_SS3 154
+MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6 155
+MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE 156
+MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11 157
+MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1 158
+MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 159
+MX53_PAD_DISP0_DAT7__GPIO4_28 160
+MX53_PAD_DISP0_DAT7__CSPI_RDY 161
+MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7 162
+MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0 163
+MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12 164
+MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID 165
+MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 166
+MX53_PAD_DISP0_DAT8__GPIO4_29 167
+MX53_PAD_DISP0_DAT8__PWM1_PWMO 168
+MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B 169
+MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1 170
+MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13 171
+MX53_PAD_DISP0_DAT8__USBPHY2_AVALID 172
+MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 173
+MX53_PAD_DISP0_DAT9__GPIO4_30 174
+MX53_PAD_DISP0_DAT9__PWM2_PWMO 175
+MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B 176
+MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2 177
+MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14 178
+MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0 179
+MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 180
+MX53_PAD_DISP0_DAT10__GPIO4_31 181
+MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP 182
+MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3 183
+MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15 184
+MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1 185
+MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 186
+MX53_PAD_DISP0_DAT11__GPIO5_5 187
+MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT 188
+MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4 189
+MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16 190
+MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2 191
+MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 192
+MX53_PAD_DISP0_DAT12__GPIO5_6 193
+MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK 194
+MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5 195
+MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17 196
+MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3 197
+MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 198
+MX53_PAD_DISP0_DAT13__GPIO5_7 199
+MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS 200
+MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0 201
+MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18 202
+MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4 203
+MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 204
+MX53_PAD_DISP0_DAT14__GPIO5_8 205
+MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC 206
+MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1 207
+MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19 208
+MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5 209
+MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 210
+MX53_PAD_DISP0_DAT15__GPIO5_9 211
+MX53_PAD_DISP0_DAT15__ECSPI1_SS1 212
+MX53_PAD_DISP0_DAT15__ECSPI2_SS1 213
+MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2 214
+MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20 215
+MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6 216
+MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 217
+MX53_PAD_DISP0_DAT16__GPIO5_10 218
+MX53_PAD_DISP0_DAT16__ECSPI2_MOSI 219
+MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC 220
+MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 221
+MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3 222
+MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21 223
+MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7 224
+MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 225
+MX53_PAD_DISP0_DAT17__GPIO5_11 226
+MX53_PAD_DISP0_DAT17__ECSPI2_MISO 227
+MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD 228
+MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 229
+MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4 230
+MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22 231
+MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 232
+MX53_PAD_DISP0_DAT18__GPIO5_12 233
+MX53_PAD_DISP0_DAT18__ECSPI2_SS0 234
+MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS 235
+MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS 236
+MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5 237
+MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23 238
+MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2 239
+MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 240
+MX53_PAD_DISP0_DAT19__GPIO5_13 241
+MX53_PAD_DISP0_DAT19__ECSPI2_SCLK 242
+MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD 243
+MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC 244
+MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6 245
+MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24 246
+MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3 247
+MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 248
+MX53_PAD_DISP0_DAT20__GPIO5_14 249
+MX53_PAD_DISP0_DAT20__ECSPI1_SCLK 250
+MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC 251
+MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7 252
+MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25 253
+MX53_PAD_DISP0_DAT20__SATA_PHY_TDI 254
+MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 255
+MX53_PAD_DISP0_DAT21__GPIO5_15 256
+MX53_PAD_DISP0_DAT21__ECSPI1_MOSI 257
+MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD 258
+MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0 259
+MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26 260
+MX53_PAD_DISP0_DAT21__SATA_PHY_TDO 261
+MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 262
+MX53_PAD_DISP0_DAT22__GPIO5_16 263
+MX53_PAD_DISP0_DAT22__ECSPI1_MISO 264
+MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS 265
+MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1 266
+MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27 267
+MX53_PAD_DISP0_DAT22__SATA_PHY_TCK 268
+MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 269
+MX53_PAD_DISP0_DAT23__GPIO5_17 270
+MX53_PAD_DISP0_DAT23__ECSPI1_SS0 271
+MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD 272
+MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2 273
+MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28 274
+MX53_PAD_DISP0_DAT23__SATA_PHY_TMS 275
+MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK 276
+MX53_PAD_CSI0_PIXCLK__GPIO5_18 277
+MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 278
+MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29 279
+MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC 280
+MX53_PAD_CSI0_MCLK__GPIO5_19 281
+MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK 282
+MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 283
+MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30 284
+MX53_PAD_CSI0_MCLK__TPIU_TRCTL 285
+MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN 286
+MX53_PAD_CSI0_DATA_EN__GPIO5_20 287
+MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 288
+MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31 289
+MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK 290
+MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC 291
+MX53_PAD_CSI0_VSYNC__GPIO5_21 292
+MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 293
+MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32 294
+MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0 295
+MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4 296
+MX53_PAD_CSI0_DAT4__GPIO5_22 297
+MX53_PAD_CSI0_DAT4__KPP_COL_5 298
+MX53_PAD_CSI0_DAT4__ECSPI1_SCLK 299
+MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP 300
+MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC 301
+MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33 302
+MX53_PAD_CSI0_DAT4__TPIU_TRACE_1 303
+MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5 304
+MX53_PAD_CSI0_DAT5__GPIO5_23 305
+MX53_PAD_CSI0_DAT5__KPP_ROW_5 306
+MX53_PAD_CSI0_DAT5__ECSPI1_MOSI 307
+MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT 308
+MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD 309
+MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34 310
+MX53_PAD_CSI0_DAT5__TPIU_TRACE_2 311
+MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6 312
+MX53_PAD_CSI0_DAT6__GPIO5_24 313
+MX53_PAD_CSI0_DAT6__KPP_COL_6 314
+MX53_PAD_CSI0_DAT6__ECSPI1_MISO 315
+MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK 316
+MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS 317
+MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35 318
+MX53_PAD_CSI0_DAT6__TPIU_TRACE_3 319
+MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7 320
+MX53_PAD_CSI0_DAT7__GPIO5_25 321
+MX53_PAD_CSI0_DAT7__KPP_ROW_6 322
+MX53_PAD_CSI0_DAT7__ECSPI1_SS0 323
+MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR 324
+MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD 325
+MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36 326
+MX53_PAD_CSI0_DAT7__TPIU_TRACE_4 327
+MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8 328
+MX53_PAD_CSI0_DAT8__GPIO5_26 329
+MX53_PAD_CSI0_DAT8__KPP_COL_7 330
+MX53_PAD_CSI0_DAT8__ECSPI2_SCLK 331
+MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC 332
+MX53_PAD_CSI0_DAT8__I2C1_SDA 333
+MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37 334
+MX53_PAD_CSI0_DAT8__TPIU_TRACE_5 335
+MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9 336
+MX53_PAD_CSI0_DAT9__GPIO5_27 337
+MX53_PAD_CSI0_DAT9__KPP_ROW_7 338
+MX53_PAD_CSI0_DAT9__ECSPI2_MOSI 339
+MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR 340
+MX53_PAD_CSI0_DAT9__I2C1_SCL 341
+MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38 342
+MX53_PAD_CSI0_DAT9__TPIU_TRACE_6 343
+MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10 344
+MX53_PAD_CSI0_DAT10__GPIO5_28 345
+MX53_PAD_CSI0_DAT10__UART1_TXD_MUX 346
+MX53_PAD_CSI0_DAT10__ECSPI2_MISO 347
+MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC 348
+MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 349
+MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39 350
+MX53_PAD_CSI0_DAT10__TPIU_TRACE_7 351
+MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11 352
+MX53_PAD_CSI0_DAT11__GPIO5_29 353
+MX53_PAD_CSI0_DAT11__UART1_RXD_MUX 354
+MX53_PAD_CSI0_DAT11__ECSPI2_SS0 355
+MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS 356
+MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 357
+MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40 358
+MX53_PAD_CSI0_DAT11__TPIU_TRACE_8 359
+MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 360
+MX53_PAD_CSI0_DAT12__GPIO5_30 361
+MX53_PAD_CSI0_DAT12__UART4_TXD_MUX 362
+MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0 363
+MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 364
+MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41 365
+MX53_PAD_CSI0_DAT12__TPIU_TRACE_9 366
+MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 367
+MX53_PAD_CSI0_DAT13__GPIO5_31 368
+MX53_PAD_CSI0_DAT13__UART4_RXD_MUX 369
+MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1 370
+MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 371
+MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42 372
+MX53_PAD_CSI0_DAT13__TPIU_TRACE_10 373
+MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 374
+MX53_PAD_CSI0_DAT14__GPIO6_0 375
+MX53_PAD_CSI0_DAT14__UART5_TXD_MUX 376
+MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2 377
+MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 378
+MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43 379
+MX53_PAD_CSI0_DAT14__TPIU_TRACE_11 380
+MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 381
+MX53_PAD_CSI0_DAT15__GPIO6_1 382
+MX53_PAD_CSI0_DAT15__UART5_RXD_MUX 383
+MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3 384
+MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 385
+MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44 386
+MX53_PAD_CSI0_DAT15__TPIU_TRACE_12 387
+MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 388
+MX53_PAD_CSI0_DAT16__GPIO6_2 389
+MX53_PAD_CSI0_DAT16__UART4_RTS 390
+MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4 391
+MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 392
+MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45 393
+MX53_PAD_CSI0_DAT16__TPIU_TRACE_13 394
+MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 395
+MX53_PAD_CSI0_DAT17__GPIO6_3 396
+MX53_PAD_CSI0_DAT17__UART4_CTS 397
+MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5 398
+MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 399
+MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46 400
+MX53_PAD_CSI0_DAT17__TPIU_TRACE_14 401
+MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 402
+MX53_PAD_CSI0_DAT18__GPIO6_4 403
+MX53_PAD_CSI0_DAT18__UART5_RTS 404
+MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6 405
+MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 406
+MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47 407
+MX53_PAD_CSI0_DAT18__TPIU_TRACE_15 408
+MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 409
+MX53_PAD_CSI0_DAT19__GPIO6_5 410
+MX53_PAD_CSI0_DAT19__UART5_CTS 411
+MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7 412
+MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 413
+MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48 414
+MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK 415
+MX53_PAD_EIM_A25__EMI_WEIM_A_25 416
+MX53_PAD_EIM_A25__GPIO5_2 417
+MX53_PAD_EIM_A25__ECSPI2_RDY 418
+MX53_PAD_EIM_A25__IPU_DI1_PIN12 419
+MX53_PAD_EIM_A25__CSPI_SS1 420
+MX53_PAD_EIM_A25__IPU_DI0_D1_CS 421
+MX53_PAD_EIM_A25__USBPHY1_BISTOK 422
+MX53_PAD_EIM_EB2__EMI_WEIM_EB_2 423
+MX53_PAD_EIM_EB2__GPIO2_30 424
+MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK 425
+MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS 426
+MX53_PAD_EIM_EB2__ECSPI1_SS0 427
+MX53_PAD_EIM_EB2__I2C2_SCL 428
+MX53_PAD_EIM_D16__EMI_WEIM_D_16 429
+MX53_PAD_EIM_D16__GPIO3_16 430
+MX53_PAD_EIM_D16__IPU_DI0_PIN5 431
+MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK 432
+MX53_PAD_EIM_D16__ECSPI1_SCLK 433
+MX53_PAD_EIM_D16__I2C2_SDA 434
+MX53_PAD_EIM_D17__EMI_WEIM_D_17 435
+MX53_PAD_EIM_D17__GPIO3_17 436
+MX53_PAD_EIM_D17__IPU_DI0_PIN6 437
+MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN 438
+MX53_PAD_EIM_D17__ECSPI1_MISO 439
+MX53_PAD_EIM_D17__I2C3_SCL 440
+MX53_PAD_EIM_D18__EMI_WEIM_D_18 441
+MX53_PAD_EIM_D18__GPIO3_18 442
+MX53_PAD_EIM_D18__IPU_DI0_PIN7 443
+MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO 444
+MX53_PAD_EIM_D18__ECSPI1_MOSI 445
+MX53_PAD_EIM_D18__I2C3_SDA 446
+MX53_PAD_EIM_D18__IPU_DI1_D0_CS 447
+MX53_PAD_EIM_D19__EMI_WEIM_D_19 448
+MX53_PAD_EIM_D19__GPIO3_19 449
+MX53_PAD_EIM_D19__IPU_DI0_PIN8 450
+MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS 451
+MX53_PAD_EIM_D19__ECSPI1_SS1 452
+MX53_PAD_EIM_D19__EPIT1_EPITO 453
+MX53_PAD_EIM_D19__UART1_CTS 454
+MX53_PAD_EIM_D19__USBOH3_USBH2_OC 455
+MX53_PAD_EIM_D20__EMI_WEIM_D_20 456
+MX53_PAD_EIM_D20__GPIO3_20 457
+MX53_PAD_EIM_D20__IPU_DI0_PIN16 458
+MX53_PAD_EIM_D20__IPU_SER_DISP0_CS 459
+MX53_PAD_EIM_D20__CSPI_SS0 460
+MX53_PAD_EIM_D20__EPIT2_EPITO 461
+MX53_PAD_EIM_D20__UART1_RTS 462
+MX53_PAD_EIM_D20__USBOH3_USBH2_PWR 463
+MX53_PAD_EIM_D21__EMI_WEIM_D_21 464
+MX53_PAD_EIM_D21__GPIO3_21 465
+MX53_PAD_EIM_D21__IPU_DI0_PIN17 466
+MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK 467
+MX53_PAD_EIM_D21__CSPI_SCLK 468
+MX53_PAD_EIM_D21__I2C1_SCL 469
+MX53_PAD_EIM_D21__USBOH3_USBOTG_OC 470
+MX53_PAD_EIM_D22__EMI_WEIM_D_22 471
+MX53_PAD_EIM_D22__GPIO3_22 472
+MX53_PAD_EIM_D22__IPU_DI0_PIN1 473
+MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN 474
+MX53_PAD_EIM_D22__CSPI_MISO 475
+MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR 476
+MX53_PAD_EIM_D23__EMI_WEIM_D_23 477
+MX53_PAD_EIM_D23__GPIO3_23 478
+MX53_PAD_EIM_D23__UART3_CTS 479
+MX53_PAD_EIM_D23__UART1_DCD 480
+MX53_PAD_EIM_D23__IPU_DI0_D0_CS 481
+MX53_PAD_EIM_D23__IPU_DI1_PIN2 482
+MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN 483
+MX53_PAD_EIM_D23__IPU_DI1_PIN14 484
+MX53_PAD_EIM_EB3__EMI_WEIM_EB_3 485
+MX53_PAD_EIM_EB3__GPIO2_31 486
+MX53_PAD_EIM_EB3__UART3_RTS 487
+MX53_PAD_EIM_EB3__UART1_RI 488
+MX53_PAD_EIM_EB3__IPU_DI1_PIN3 489
+MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC 490
+MX53_PAD_EIM_EB3__IPU_DI1_PIN16 491
+MX53_PAD_EIM_D24__EMI_WEIM_D_24 492
+MX53_PAD_EIM_D24__GPIO3_24 493
+MX53_PAD_EIM_D24__UART3_TXD_MUX 494
+MX53_PAD_EIM_D24__ECSPI1_SS2 495
+MX53_PAD_EIM_D24__CSPI_SS2 496
+MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS 497
+MX53_PAD_EIM_D24__ECSPI2_SS2 498
+MX53_PAD_EIM_D24__UART1_DTR 499
+MX53_PAD_EIM_D25__EMI_WEIM_D_25 500
+MX53_PAD_EIM_D25__GPIO3_25 501
+MX53_PAD_EIM_D25__UART3_RXD_MUX 502
+MX53_PAD_EIM_D25__ECSPI1_SS3 503
+MX53_PAD_EIM_D25__CSPI_SS3 504
+MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC 505
+MX53_PAD_EIM_D25__ECSPI2_SS3 506
+MX53_PAD_EIM_D25__UART1_DSR 507
+MX53_PAD_EIM_D26__EMI_WEIM_D_26 508
+MX53_PAD_EIM_D26__GPIO3_26 509
+MX53_PAD_EIM_D26__UART2_TXD_MUX 510
+MX53_PAD_EIM_D26__FIRI_RXD 511
+MX53_PAD_EIM_D26__IPU_CSI0_D_1 512
+MX53_PAD_EIM_D26__IPU_DI1_PIN11 513
+MX53_PAD_EIM_D26__IPU_SISG_2 514
+MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 515
+MX53_PAD_EIM_D27__EMI_WEIM_D_27 516
+MX53_PAD_EIM_D27__GPIO3_27 517
+MX53_PAD_EIM_D27__UART2_RXD_MUX 518
+MX53_PAD_EIM_D27__FIRI_TXD 519
+MX53_PAD_EIM_D27__IPU_CSI0_D_0 520
+MX53_PAD_EIM_D27__IPU_DI1_PIN13 521
+MX53_PAD_EIM_D27__IPU_SISG_3 522
+MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 523
+MX53_PAD_EIM_D28__EMI_WEIM_D_28 524
+MX53_PAD_EIM_D28__GPIO3_28 525
+MX53_PAD_EIM_D28__UART2_CTS 526
+MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO 527
+MX53_PAD_EIM_D28__CSPI_MOSI 528
+MX53_PAD_EIM_D28__I2C1_SDA 529
+MX53_PAD_EIM_D28__IPU_EXT_TRIG 530
+MX53_PAD_EIM_D28__IPU_DI0_PIN13 531
+MX53_PAD_EIM_D29__EMI_WEIM_D_29 532
+MX53_PAD_EIM_D29__GPIO3_29 533
+MX53_PAD_EIM_D29__UART2_RTS 534
+MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS 535
+MX53_PAD_EIM_D29__CSPI_SS0 536
+MX53_PAD_EIM_D29__IPU_DI1_PIN15 537
+MX53_PAD_EIM_D29__IPU_CSI1_VSYNC 538
+MX53_PAD_EIM_D29__IPU_DI0_PIN14 539
+MX53_PAD_EIM_D30__EMI_WEIM_D_30 540
+MX53_PAD_EIM_D30__GPIO3_30 541
+MX53_PAD_EIM_D30__UART3_CTS 542
+MX53_PAD_EIM_D30__IPU_CSI0_D_3 543
+MX53_PAD_EIM_D30__IPU_DI0_PIN11 544
+MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 545
+MX53_PAD_EIM_D30__USBOH3_USBH1_OC 546
+MX53_PAD_EIM_D30__USBOH3_USBH2_OC 547
+MX53_PAD_EIM_D31__EMI_WEIM_D_31 548
+MX53_PAD_EIM_D31__GPIO3_31 549
+MX53_PAD_EIM_D31__UART3_RTS 550
+MX53_PAD_EIM_D31__IPU_CSI0_D_2 551
+MX53_PAD_EIM_D31__IPU_DI0_PIN12 552
+MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 553
+MX53_PAD_EIM_D31__USBOH3_USBH1_PWR 554
+MX53_PAD_EIM_D31__USBOH3_USBH2_PWR 555
+MX53_PAD_EIM_A24__EMI_WEIM_A_24 556
+MX53_PAD_EIM_A24__GPIO5_4 557
+MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 558
+MX53_PAD_EIM_A24__IPU_CSI1_D_19 559
+MX53_PAD_EIM_A24__IPU_SISG_2 560
+MX53_PAD_EIM_A24__USBPHY2_BVALID 561
+MX53_PAD_EIM_A23__EMI_WEIM_A_23 562
+MX53_PAD_EIM_A23__GPIO6_6 563
+MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 564
+MX53_PAD_EIM_A23__IPU_CSI1_D_18 565
+MX53_PAD_EIM_A23__IPU_SISG_3 566
+MX53_PAD_EIM_A23__USBPHY2_ENDSESSION 567
+MX53_PAD_EIM_A22__EMI_WEIM_A_22 568
+MX53_PAD_EIM_A22__GPIO2_16 569
+MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 570
+MX53_PAD_EIM_A22__IPU_CSI1_D_17 571
+MX53_PAD_EIM_A22__SRC_BT_CFG1_7 572
+MX53_PAD_EIM_A21__EMI_WEIM_A_21 573
+MX53_PAD_EIM_A21__GPIO2_17 574
+MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 575
+MX53_PAD_EIM_A21__IPU_CSI1_D_16 576
+MX53_PAD_EIM_A21__SRC_BT_CFG1_6 577
+MX53_PAD_EIM_A20__EMI_WEIM_A_20 578
+MX53_PAD_EIM_A20__GPIO2_18 579
+MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 580
+MX53_PAD_EIM_A20__IPU_CSI1_D_15 581
+MX53_PAD_EIM_A20__SRC_BT_CFG1_5 582
+MX53_PAD_EIM_A19__EMI_WEIM_A_19 583
+MX53_PAD_EIM_A19__GPIO2_19 584
+MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 585
+MX53_PAD_EIM_A19__IPU_CSI1_D_14 586
+MX53_PAD_EIM_A19__SRC_BT_CFG1_4 587
+MX53_PAD_EIM_A18__EMI_WEIM_A_18 588
+MX53_PAD_EIM_A18__GPIO2_20 589
+MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 590
+MX53_PAD_EIM_A18__IPU_CSI1_D_13 591
+MX53_PAD_EIM_A18__SRC_BT_CFG1_3 592
+MX53_PAD_EIM_A17__EMI_WEIM_A_17 593
+MX53_PAD_EIM_A17__GPIO2_21 594
+MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 595
+MX53_PAD_EIM_A17__IPU_CSI1_D_12 596
+MX53_PAD_EIM_A17__SRC_BT_CFG1_2 597
+MX53_PAD_EIM_A16__EMI_WEIM_A_16 598
+MX53_PAD_EIM_A16__GPIO2_22 599
+MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK 600
+MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK 601
+MX53_PAD_EIM_A16__SRC_BT_CFG1_1 602
+MX53_PAD_EIM_CS0__EMI_WEIM_CS_0 603
+MX53_PAD_EIM_CS0__GPIO2_23 604
+MX53_PAD_EIM_CS0__ECSPI2_SCLK 605
+MX53_PAD_EIM_CS0__IPU_DI1_PIN5 606
+MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 607
+MX53_PAD_EIM_CS1__GPIO2_24 608
+MX53_PAD_EIM_CS1__ECSPI2_MOSI 609
+MX53_PAD_EIM_CS1__IPU_DI1_PIN6 610
+MX53_PAD_EIM_OE__EMI_WEIM_OE 611
+MX53_PAD_EIM_OE__GPIO2_25 612
+MX53_PAD_EIM_OE__ECSPI2_MISO 613
+MX53_PAD_EIM_OE__IPU_DI1_PIN7 614
+MX53_PAD_EIM_OE__USBPHY2_IDDIG 615
+MX53_PAD_EIM_RW__EMI_WEIM_RW 616
+MX53_PAD_EIM_RW__GPIO2_26 617
+MX53_PAD_EIM_RW__ECSPI2_SS0 618
+MX53_PAD_EIM_RW__IPU_DI1_PIN8 619
+MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT 620
+MX53_PAD_EIM_LBA__EMI_WEIM_LBA 621
+MX53_PAD_EIM_LBA__GPIO2_27 622
+MX53_PAD_EIM_LBA__ECSPI2_SS1 623
+MX53_PAD_EIM_LBA__IPU_DI1_PIN17 624
+MX53_PAD_EIM_LBA__SRC_BT_CFG1_0 625
+MX53_PAD_EIM_EB0__EMI_WEIM_EB_0 626
+MX53_PAD_EIM_EB0__GPIO2_28 627
+MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 628
+MX53_PAD_EIM_EB0__IPU_CSI1_D_11 629
+MX53_PAD_EIM_EB0__GPC_PMIC_RDY 630
+MX53_PAD_EIM_EB0__SRC_BT_CFG2_7 631
+MX53_PAD_EIM_EB1__EMI_WEIM_EB_1 632
+MX53_PAD_EIM_EB1__GPIO2_29 633
+MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 634
+MX53_PAD_EIM_EB1__IPU_CSI1_D_10 635
+MX53_PAD_EIM_EB1__SRC_BT_CFG2_6 636
+MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 637
+MX53_PAD_EIM_DA0__GPIO3_0 638
+MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 639
+MX53_PAD_EIM_DA0__IPU_CSI1_D_9 640
+MX53_PAD_EIM_DA0__SRC_BT_CFG2_5 641
+MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 642
+MX53_PAD_EIM_DA1__GPIO3_1 643
+MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 644
+MX53_PAD_EIM_DA1__IPU_CSI1_D_8 645
+MX53_PAD_EIM_DA1__SRC_BT_CFG2_4 646
+MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 647
+MX53_PAD_EIM_DA2__GPIO3_2 648
+MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 649
+MX53_PAD_EIM_DA2__IPU_CSI1_D_7 650
+MX53_PAD_EIM_DA2__SRC_BT_CFG2_3 651
+MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 652
+MX53_PAD_EIM_DA3__GPIO3_3 653
+MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 654
+MX53_PAD_EIM_DA3__IPU_CSI1_D_6 655
+MX53_PAD_EIM_DA3__SRC_BT_CFG2_2 656
+MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 657
+MX53_PAD_EIM_DA4__GPIO3_4 658
+MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 659
+MX53_PAD_EIM_DA4__IPU_CSI1_D_5 660
+MX53_PAD_EIM_DA4__SRC_BT_CFG3_7 661
+MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 662
+MX53_PAD_EIM_DA5__GPIO3_5 663
+MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 664
+MX53_PAD_EIM_DA5__IPU_CSI1_D_4 665
+MX53_PAD_EIM_DA5__SRC_BT_CFG3_6 666
+MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 667
+MX53_PAD_EIM_DA6__GPIO3_6 668
+MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 669
+MX53_PAD_EIM_DA6__IPU_CSI1_D_3 670
+MX53_PAD_EIM_DA6__SRC_BT_CFG3_5 671
+MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7 672
+MX53_PAD_EIM_DA7__GPIO3_7 673
+MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 674
+MX53_PAD_EIM_DA7__IPU_CSI1_D_2 675
+MX53_PAD_EIM_DA7__SRC_BT_CFG3_4 676
+MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8 677
+MX53_PAD_EIM_DA8__GPIO3_8 678
+MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 679
+MX53_PAD_EIM_DA8__IPU_CSI1_D_1 680
+MX53_PAD_EIM_DA8__SRC_BT_CFG3_3 681
+MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9 682
+MX53_PAD_EIM_DA9__GPIO3_9 683
+MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 684
+MX53_PAD_EIM_DA9__IPU_CSI1_D_0 685
+MX53_PAD_EIM_DA9__SRC_BT_CFG3_2 686
+MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10 687
+MX53_PAD_EIM_DA10__GPIO3_10 688
+MX53_PAD_EIM_DA10__IPU_DI1_PIN15 689
+MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN 690
+MX53_PAD_EIM_DA10__SRC_BT_CFG3_1 691
+MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11 692
+MX53_PAD_EIM_DA11__GPIO3_11 693
+MX53_PAD_EIM_DA11__IPU_DI1_PIN2 694
+MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC 695
+MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12 696
+MX53_PAD_EIM_DA12__GPIO3_12 697
+MX53_PAD_EIM_DA12__IPU_DI1_PIN3 698
+MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC 699
+MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13 700
+MX53_PAD_EIM_DA13__GPIO3_13 701
+MX53_PAD_EIM_DA13__IPU_DI1_D0_CS 702
+MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK 703
+MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14 704
+MX53_PAD_EIM_DA14__GPIO3_14 705
+MX53_PAD_EIM_DA14__IPU_DI1_D1_CS 706
+MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK 707
+MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15 708
+MX53_PAD_EIM_DA15__GPIO3_15 709
+MX53_PAD_EIM_DA15__IPU_DI1_PIN1 710
+MX53_PAD_EIM_DA15__IPU_DI1_PIN4 711
+MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B 712
+MX53_PAD_NANDF_WE_B__GPIO6_12 713
+MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B 714
+MX53_PAD_NANDF_RE_B__GPIO6_13 715
+MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT 716
+MX53_PAD_EIM_WAIT__GPIO5_0 717
+MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B 718
+MX53_PAD_LVDS1_TX3_P__GPIO6_22 719
+MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 720
+MX53_PAD_LVDS1_TX2_P__GPIO6_24 721
+MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 722
+MX53_PAD_LVDS1_CLK_P__GPIO6_26 723
+MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK 724
+MX53_PAD_LVDS1_TX1_P__GPIO6_28 725
+MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 726
+MX53_PAD_LVDS1_TX0_P__GPIO6_30 727
+MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 728
+MX53_PAD_LVDS0_TX3_P__GPIO7_22 729
+MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 730
+MX53_PAD_LVDS0_CLK_P__GPIO7_24 731
+MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK 732
+MX53_PAD_LVDS0_TX2_P__GPIO7_26 733
+MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 734
+MX53_PAD_LVDS0_TX1_P__GPIO7_28 735
+MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 736
+MX53_PAD_LVDS0_TX0_P__GPIO7_30 737
+MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 738
+MX53_PAD_GPIO_10__GPIO4_0 739
+MX53_PAD_GPIO_10__OSC32k_32K_OUT 740
+MX53_PAD_GPIO_11__GPIO4_1 741
+MX53_PAD_GPIO_12__GPIO4_2 742
+MX53_PAD_GPIO_13__GPIO4_3 743
+MX53_PAD_GPIO_14__GPIO4_4 744
+MX53_PAD_NANDF_CLE__EMI_NANDF_CLE 745
+MX53_PAD_NANDF_CLE__GPIO6_7 746
+MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0 747
+MX53_PAD_NANDF_ALE__EMI_NANDF_ALE 748
+MX53_PAD_NANDF_ALE__GPIO6_8 749
+MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1 750
+MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B 751
+MX53_PAD_NANDF_WP_B__GPIO6_9 752
+MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2 753
+MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 754
+MX53_PAD_NANDF_RB0__GPIO6_10 755
+MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3 756
+MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 757
+MX53_PAD_NANDF_CS0__GPIO6_11 758
+MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4 759
+MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1 760
+MX53_PAD_NANDF_CS1__GPIO6_14 761
+MX53_PAD_NANDF_CS1__MLB_MLBCLK 762
+MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5 763
+MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2 764
+MX53_PAD_NANDF_CS2__GPIO6_15 765
+MX53_PAD_NANDF_CS2__IPU_SISG_0 766
+MX53_PAD_NANDF_CS2__ESAI1_TX0 767
+MX53_PAD_NANDF_CS2__EMI_WEIM_CRE 768
+MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK 769
+MX53_PAD_NANDF_CS2__MLB_MLBSIG 770
+MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6 771
+MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3 772
+MX53_PAD_NANDF_CS3__GPIO6_16 773
+MX53_PAD_NANDF_CS3__IPU_SISG_1 774
+MX53_PAD_NANDF_CS3__ESAI1_TX1 775
+MX53_PAD_NANDF_CS3__EMI_WEIM_A_26 776
+MX53_PAD_NANDF_CS3__MLB_MLBDAT 777
+MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7 778
+MX53_PAD_FEC_MDIO__FEC_MDIO 779
+MX53_PAD_FEC_MDIO__GPIO1_22 780
+MX53_PAD_FEC_MDIO__ESAI1_SCKR 781
+MX53_PAD_FEC_MDIO__FEC_COL 782
+MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2 783
+MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3 784
+MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49 785
+MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 786
+MX53_PAD_FEC_REF_CLK__GPIO1_23 787
+MX53_PAD_FEC_REF_CLK__ESAI1_FSR 788
+MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 789
+MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50 790
+MX53_PAD_FEC_RX_ER__FEC_RX_ER 791
+MX53_PAD_FEC_RX_ER__GPIO1_24 792
+MX53_PAD_FEC_RX_ER__ESAI1_HCKR 793
+MX53_PAD_FEC_RX_ER__FEC_RX_CLK 794
+MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3 795
+MX53_PAD_FEC_CRS_DV__FEC_RX_DV 796
+MX53_PAD_FEC_CRS_DV__GPIO1_25 797
+MX53_PAD_FEC_CRS_DV__ESAI1_SCKT 798
+MX53_PAD_FEC_RXD1__FEC_RDATA_1 799
+MX53_PAD_FEC_RXD1__GPIO1_26 800
+MX53_PAD_FEC_RXD1__ESAI1_FST 801
+MX53_PAD_FEC_RXD1__MLB_MLBSIG 802
+MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1 803
+MX53_PAD_FEC_RXD0__FEC_RDATA_0 804
+MX53_PAD_FEC_RXD0__GPIO1_27 805
+MX53_PAD_FEC_RXD0__ESAI1_HCKT 806
+MX53_PAD_FEC_RXD0__OSC32k_32K_OUT 807
+MX53_PAD_FEC_TX_EN__FEC_TX_EN 808
+MX53_PAD_FEC_TX_EN__GPIO1_28 809
+MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2 810
+MX53_PAD_FEC_TXD1__FEC_TDATA_1 811
+MX53_PAD_FEC_TXD1__GPIO1_29 812
+MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3 813
+MX53_PAD_FEC_TXD1__MLB_MLBCLK 814
+MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK 815
+MX53_PAD_FEC_TXD0__FEC_TDATA_0 816
+MX53_PAD_FEC_TXD0__GPIO1_30 817
+MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1 818
+MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0 819
+MX53_PAD_FEC_MDC__FEC_MDC 820
+MX53_PAD_FEC_MDC__GPIO1_31 821
+MX53_PAD_FEC_MDC__ESAI1_TX5_RX0 822
+MX53_PAD_FEC_MDC__MLB_MLBDAT 823
+MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG 824
+MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1 825
+MX53_PAD_PATA_DIOW__PATA_DIOW 826
+MX53_PAD_PATA_DIOW__GPIO6_17 827
+MX53_PAD_PATA_DIOW__UART1_TXD_MUX 828
+MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2 829
+MX53_PAD_PATA_DMACK__PATA_DMACK 830
+MX53_PAD_PATA_DMACK__GPIO6_18 831
+MX53_PAD_PATA_DMACK__UART1_RXD_MUX 832
+MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3 833
+MX53_PAD_PATA_DMARQ__PATA_DMARQ 834
+MX53_PAD_PATA_DMARQ__GPIO7_0 835
+MX53_PAD_PATA_DMARQ__UART2_TXD_MUX 836
+MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0 837
+MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4 838
+MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN 839
+MX53_PAD_PATA_BUFFER_EN__GPIO7_1 840
+MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 841
+MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1 842
+MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5 843
+MX53_PAD_PATA_INTRQ__PATA_INTRQ 844
+MX53_PAD_PATA_INTRQ__GPIO7_2 845
+MX53_PAD_PATA_INTRQ__UART2_CTS 846
+MX53_PAD_PATA_INTRQ__CAN1_TXCAN 847
+MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2 848
+MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6 849
+MX53_PAD_PATA_DIOR__PATA_DIOR 850
+MX53_PAD_PATA_DIOR__GPIO7_3 851
+MX53_PAD_PATA_DIOR__UART2_RTS 852
+MX53_PAD_PATA_DIOR__CAN1_RXCAN 853
+MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7 854
+MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B 855
+MX53_PAD_PATA_RESET_B__GPIO7_4 856
+MX53_PAD_PATA_RESET_B__ESDHC3_CMD 857
+MX53_PAD_PATA_RESET_B__UART1_CTS 858
+MX53_PAD_PATA_RESET_B__CAN2_TXCAN 859
+MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0 860
+MX53_PAD_PATA_IORDY__PATA_IORDY 861
+MX53_PAD_PATA_IORDY__GPIO7_5 862
+MX53_PAD_PATA_IORDY__ESDHC3_CLK 863
+MX53_PAD_PATA_IORDY__UART1_RTS 864
+MX53_PAD_PATA_IORDY__CAN2_RXCAN 865
+MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1 866
+MX53_PAD_PATA_DA_0__PATA_DA_0 867
+MX53_PAD_PATA_DA_0__GPIO7_6 868
+MX53_PAD_PATA_DA_0__ESDHC3_RST 869
+MX53_PAD_PATA_DA_0__OWIRE_LINE 870
+MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2 871
+MX53_PAD_PATA_DA_1__PATA_DA_1 872
+MX53_PAD_PATA_DA_1__GPIO7_7 873
+MX53_PAD_PATA_DA_1__ESDHC4_CMD 874
+MX53_PAD_PATA_DA_1__UART3_CTS 875
+MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3 876
+MX53_PAD_PATA_DA_2__PATA_DA_2 877
+MX53_PAD_PATA_DA_2__GPIO7_8 878
+MX53_PAD_PATA_DA_2__ESDHC4_CLK 879
+MX53_PAD_PATA_DA_2__UART3_RTS 880
+MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4 881
+MX53_PAD_PATA_CS_0__PATA_CS_0 882
+MX53_PAD_PATA_CS_0__GPIO7_9 883
+MX53_PAD_PATA_CS_0__UART3_TXD_MUX 884
+MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5 885
+MX53_PAD_PATA_CS_1__PATA_CS_1 886
+MX53_PAD_PATA_CS_1__GPIO7_10 887
+MX53_PAD_PATA_CS_1__UART3_RXD_MUX 888
+MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6 889
+MX53_PAD_PATA_DATA0__PATA_DATA_0 890
+MX53_PAD_PATA_DATA0__GPIO2_0 891
+MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 892
+MX53_PAD_PATA_DATA0__ESDHC3_DAT4 893
+MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0 894
+MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0 895
+MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7 896
+MX53_PAD_PATA_DATA1__PATA_DATA_1 897
+MX53_PAD_PATA_DATA1__GPIO2_1 898
+MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 899
+MX53_PAD_PATA_DATA1__ESDHC3_DAT5 900
+MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1 901
+MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1 902
+MX53_PAD_PATA_DATA2__PATA_DATA_2 903
+MX53_PAD_PATA_DATA2__GPIO2_2 904
+MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 905
+MX53_PAD_PATA_DATA2__ESDHC3_DAT6 906
+MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2 907
+MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2 908
+MX53_PAD_PATA_DATA3__PATA_DATA_3 909
+MX53_PAD_PATA_DATA3__GPIO2_3 910
+MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 911
+MX53_PAD_PATA_DATA3__ESDHC3_DAT7 912
+MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3 913
+MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3 914
+MX53_PAD_PATA_DATA4__PATA_DATA_4 915
+MX53_PAD_PATA_DATA4__GPIO2_4 916
+MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 917
+MX53_PAD_PATA_DATA4__ESDHC4_DAT4 918
+MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4 919
+MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4 920
+MX53_PAD_PATA_DATA5__PATA_DATA_5 921
+MX53_PAD_PATA_DATA5__GPIO2_5 922
+MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 923
+MX53_PAD_PATA_DATA5__ESDHC4_DAT5 924
+MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5 925
+MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5 926
+MX53_PAD_PATA_DATA6__PATA_DATA_6 927
+MX53_PAD_PATA_DATA6__GPIO2_6 928
+MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 929
+MX53_PAD_PATA_DATA6__ESDHC4_DAT6 930
+MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6 931
+MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6 932
+MX53_PAD_PATA_DATA7__PATA_DATA_7 933
+MX53_PAD_PATA_DATA7__GPIO2_7 934
+MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 935
+MX53_PAD_PATA_DATA7__ESDHC4_DAT7 936
+MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7 937
+MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7 938
+MX53_PAD_PATA_DATA8__PATA_DATA_8 939
+MX53_PAD_PATA_DATA8__GPIO2_8 940
+MX53_PAD_PATA_DATA8__ESDHC1_DAT4 941
+MX53_PAD_PATA_DATA8__EMI_NANDF_D_8 942
+MX53_PAD_PATA_DATA8__ESDHC3_DAT0 943
+MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8 944
+MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8 945
+MX53_PAD_PATA_DATA9__PATA_DATA_9 946
+MX53_PAD_PATA_DATA9__GPIO2_9 947
+MX53_PAD_PATA_DATA9__ESDHC1_DAT5 948
+MX53_PAD_PATA_DATA9__EMI_NANDF_D_9 949
+MX53_PAD_PATA_DATA9__ESDHC3_DAT1 950
+MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9 951
+MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9 952
+MX53_PAD_PATA_DATA10__PATA_DATA_10 953
+MX53_PAD_PATA_DATA10__GPIO2_10 954
+MX53_PAD_PATA_DATA10__ESDHC1_DAT6 955
+MX53_PAD_PATA_DATA10__EMI_NANDF_D_10 956
+MX53_PAD_PATA_DATA10__ESDHC3_DAT2 957
+MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10 958
+MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10 959
+MX53_PAD_PATA_DATA11__PATA_DATA_11 960
+MX53_PAD_PATA_DATA11__GPIO2_11 961
+MX53_PAD_PATA_DATA11__ESDHC1_DAT7 962
+MX53_PAD_PATA_DATA11__EMI_NANDF_D_11 963
+MX53_PAD_PATA_DATA11__ESDHC3_DAT3 964
+MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11 965
+MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11 966
+MX53_PAD_PATA_DATA12__PATA_DATA_12 967
+MX53_PAD_PATA_DATA12__GPIO2_12 968
+MX53_PAD_PATA_DATA12__ESDHC2_DAT4 969
+MX53_PAD_PATA_DATA12__EMI_NANDF_D_12 970
+MX53_PAD_PATA_DATA12__ESDHC4_DAT0 971
+MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12 972
+MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12 973
+MX53_PAD_PATA_DATA13__PATA_DATA_13 974
+MX53_PAD_PATA_DATA13__GPIO2_13 975
+MX53_PAD_PATA_DATA13__ESDHC2_DAT5 976
+MX53_PAD_PATA_DATA13__EMI_NANDF_D_13 977
+MX53_PAD_PATA_DATA13__ESDHC4_DAT1 978
+MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13 979
+MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13 980
+MX53_PAD_PATA_DATA14__PATA_DATA_14 981
+MX53_PAD_PATA_DATA14__GPIO2_14 982
+MX53_PAD_PATA_DATA14__ESDHC2_DAT6 983
+MX53_PAD_PATA_DATA14__EMI_NANDF_D_14 984
+MX53_PAD_PATA_DATA14__ESDHC4_DAT2 985
+MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14 986
+MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14 987
+MX53_PAD_PATA_DATA15__PATA_DATA_15 988
+MX53_PAD_PATA_DATA15__GPIO2_15 989
+MX53_PAD_PATA_DATA15__ESDHC2_DAT7 990
+MX53_PAD_PATA_DATA15__EMI_NANDF_D_15 991
+MX53_PAD_PATA_DATA15__ESDHC4_DAT3 992
+MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15 993
+MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15 994
+MX53_PAD_SD1_DATA0__ESDHC1_DAT0 995
+MX53_PAD_SD1_DATA0__GPIO1_16 996
+MX53_PAD_SD1_DATA0__GPT_CAPIN1 997
+MX53_PAD_SD1_DATA0__CSPI_MISO 998
+MX53_PAD_SD1_DATA0__CCM_PLL3_BYP 999
+MX53_PAD_SD1_DATA1__ESDHC1_DAT1 1000
+MX53_PAD_SD1_DATA1__GPIO1_17 1001
+MX53_PAD_SD1_DATA1__GPT_CAPIN2 1002
+MX53_PAD_SD1_DATA1__CSPI_SS0 1003
+MX53_PAD_SD1_DATA1__CCM_PLL4_BYP 1004
+MX53_PAD_SD1_CMD__ESDHC1_CMD 1005
+MX53_PAD_SD1_CMD__GPIO1_18 1006
+MX53_PAD_SD1_CMD__GPT_CMPOUT1 1007
+MX53_PAD_SD1_CMD__CSPI_MOSI 1008
+MX53_PAD_SD1_CMD__CCM_PLL1_BYP 1009
+MX53_PAD_SD1_DATA2__ESDHC1_DAT2 1010
+MX53_PAD_SD1_DATA2__GPIO1_19 1011
+MX53_PAD_SD1_DATA2__GPT_CMPOUT2 1012
+MX53_PAD_SD1_DATA2__PWM2_PWMO 1013
+MX53_PAD_SD1_DATA2__WDOG1_WDOG_B 1014
+MX53_PAD_SD1_DATA2__CSPI_SS1 1015
+MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB 1016
+MX53_PAD_SD1_DATA2__CCM_PLL2_BYP 1017
+MX53_PAD_SD1_CLK__ESDHC1_CLK 1018
+MX53_PAD_SD1_CLK__GPIO1_20 1019
+MX53_PAD_SD1_CLK__OSC32k_32K_OUT 1020
+MX53_PAD_SD1_CLK__GPT_CLKIN 1021
+MX53_PAD_SD1_CLK__CSPI_SCLK 1022
+MX53_PAD_SD1_CLK__SATA_PHY_DTB_0 1023
+MX53_PAD_SD1_DATA3__ESDHC1_DAT3 1024
+MX53_PAD_SD1_DATA3__GPIO1_21 1025
+MX53_PAD_SD1_DATA3__GPT_CMPOUT3 1026
+MX53_PAD_SD1_DATA3__PWM1_PWMO 1027
+MX53_PAD_SD1_DATA3__WDOG2_WDOG_B 1028
+MX53_PAD_SD1_DATA3__CSPI_SS2 1029
+MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB 1030
+MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1 1031
+MX53_PAD_SD2_CLK__ESDHC2_CLK 1032
+MX53_PAD_SD2_CLK__GPIO1_10 1033
+MX53_PAD_SD2_CLK__KPP_COL_5 1034
+MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS 1035
+MX53_PAD_SD2_CLK__CSPI_SCLK 1036
+MX53_PAD_SD2_CLK__SCC_RANDOM_V 1037
+MX53_PAD_SD2_CMD__ESDHC2_CMD 1038
+MX53_PAD_SD2_CMD__GPIO1_11 1039
+MX53_PAD_SD2_CMD__KPP_ROW_5 1040
+MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC 1041
+MX53_PAD_SD2_CMD__CSPI_MOSI 1042
+MX53_PAD_SD2_CMD__SCC_RANDOM 1043
+MX53_PAD_SD2_DATA3__ESDHC2_DAT3 1044
+MX53_PAD_SD2_DATA3__GPIO1_12 1045
+MX53_PAD_SD2_DATA3__KPP_COL_6 1046
+MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC 1047
+MX53_PAD_SD2_DATA3__CSPI_SS2 1048
+MX53_PAD_SD2_DATA3__SJC_DONE 1049
+MX53_PAD_SD2_DATA2__ESDHC2_DAT2 1050
+MX53_PAD_SD2_DATA2__GPIO1_13 1051
+MX53_PAD_SD2_DATA2__KPP_ROW_6 1052
+MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD 1053
+MX53_PAD_SD2_DATA2__CSPI_SS1 1054
+MX53_PAD_SD2_DATA2__SJC_FAIL 1055
+MX53_PAD_SD2_DATA1__ESDHC2_DAT1 1056
+MX53_PAD_SD2_DATA1__GPIO1_14 1057
+MX53_PAD_SD2_DATA1__KPP_COL_7 1058
+MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS 1059
+MX53_PAD_SD2_DATA1__CSPI_SS0 1060
+MX53_PAD_SD2_DATA1__RTIC_SEC_VIO 1061
+MX53_PAD_SD2_DATA0__ESDHC2_DAT0 1062
+MX53_PAD_SD2_DATA0__GPIO1_15 1063
+MX53_PAD_SD2_DATA0__KPP_ROW_7 1064
+MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD 1065
+MX53_PAD_SD2_DATA0__CSPI_MISO 1066
+MX53_PAD_SD2_DATA0__RTIC_DONE_INT 1067
+MX53_PAD_GPIO_0__CCM_CLKO 1068
+MX53_PAD_GPIO_0__GPIO1_0 1069
+MX53_PAD_GPIO_0__KPP_COL_5 1070
+MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 1071
+MX53_PAD_GPIO_0__EPIT1_EPITO 1072
+MX53_PAD_GPIO_0__SRTC_ALARM_DEB 1073
+MX53_PAD_GPIO_0__USBOH3_USBH1_PWR 1074
+MX53_PAD_GPIO_0__CSU_TD 1075
+MX53_PAD_GPIO_1__ESAI1_SCKR 1076
+MX53_PAD_GPIO_1__GPIO1_1 1077
+MX53_PAD_GPIO_1__KPP_ROW_5 1078
+MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK 1079
+MX53_PAD_GPIO_1__PWM2_PWMO 1080
+MX53_PAD_GPIO_1__WDOG2_WDOG_B 1081
+MX53_PAD_GPIO_1__ESDHC1_CD 1082
+MX53_PAD_GPIO_1__SRC_TESTER_ACK 1083
+MX53_PAD_GPIO_9__ESAI1_FSR 1084
+MX53_PAD_GPIO_9__GPIO1_9 1085
+MX53_PAD_GPIO_9__KPP_COL_6 1086
+MX53_PAD_GPIO_9__CCM_REF_EN_B 1087
+MX53_PAD_GPIO_9__PWM1_PWMO 1088
+MX53_PAD_GPIO_9__WDOG1_WDOG_B 1089
+MX53_PAD_GPIO_9__ESDHC1_WP 1090
+MX53_PAD_GPIO_9__SCC_FAIL_STATE 1091
+MX53_PAD_GPIO_3__ESAI1_HCKR 1092
+MX53_PAD_GPIO_3__GPIO1_3 1093
+MX53_PAD_GPIO_3__I2C3_SCL 1094
+MX53_PAD_GPIO_3__DPLLIP1_TOG_EN 1095
+MX53_PAD_GPIO_3__CCM_CLKO2 1096
+MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0 1097
+MX53_PAD_GPIO_3__USBOH3_USBH1_OC 1098
+MX53_PAD_GPIO_3__MLB_MLBCLK 1099
+MX53_PAD_GPIO_6__ESAI1_SCKT 1100
+MX53_PAD_GPIO_6__GPIO1_6 1101
+MX53_PAD_GPIO_6__I2C3_SDA 1102
+MX53_PAD_GPIO_6__CCM_CCM_OUT_0 1103
+MX53_PAD_GPIO_6__CSU_CSU_INT_DEB 1104
+MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 1105
+MX53_PAD_GPIO_6__ESDHC2_LCTL 1106
+MX53_PAD_GPIO_6__MLB_MLBSIG 1107
+MX53_PAD_GPIO_2__ESAI1_FST 1108
+MX53_PAD_GPIO_2__GPIO1_2 1109
+MX53_PAD_GPIO_2__KPP_ROW_6 1110
+MX53_PAD_GPIO_2__CCM_CCM_OUT_1 1111
+MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 1112
+MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2 1113
+MX53_PAD_GPIO_2__ESDHC2_WP 1114
+MX53_PAD_GPIO_2__MLB_MLBDAT 1115
+MX53_PAD_GPIO_4__ESAI1_HCKT 1116
+MX53_PAD_GPIO_4__GPIO1_4 1117
+MX53_PAD_GPIO_4__KPP_COL_7 1118
+MX53_PAD_GPIO_4__CCM_CCM_OUT_2 1119
+MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 1120
+MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3 1121
+MX53_PAD_GPIO_4__ESDHC2_CD 1122
+MX53_PAD_GPIO_4__SCC_SEC_STATE 1123
+MX53_PAD_GPIO_5__ESAI1_TX2_RX3 1124
+MX53_PAD_GPIO_5__GPIO1_5 1125
+MX53_PAD_GPIO_5__KPP_ROW_7 1126
+MX53_PAD_GPIO_5__CCM_CLKO 1127
+MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 1128
+MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4 1129
+MX53_PAD_GPIO_5__I2C3_SCL 1130
+MX53_PAD_GPIO_5__CCM_PLL1_BYP 1131
+MX53_PAD_GPIO_7__ESAI1_TX4_RX1 1132
+MX53_PAD_GPIO_7__GPIO1_7 1133
+MX53_PAD_GPIO_7__EPIT1_EPITO 1134
+MX53_PAD_GPIO_7__CAN1_TXCAN 1135
+MX53_PAD_GPIO_7__UART2_TXD_MUX 1136
+MX53_PAD_GPIO_7__FIRI_RXD 1137
+MX53_PAD_GPIO_7__SPDIF_PLOCK 1138
+MX53_PAD_GPIO_7__CCM_PLL2_BYP 1139
+MX53_PAD_GPIO_8__ESAI1_TX5_RX0 1140
+MX53_PAD_GPIO_8__GPIO1_8 1141
+MX53_PAD_GPIO_8__EPIT2_EPITO 1142
+MX53_PAD_GPIO_8__CAN1_RXCAN 1143
+MX53_PAD_GPIO_8__UART2_RXD_MUX 1144
+MX53_PAD_GPIO_8__FIRI_TXD 1145
+MX53_PAD_GPIO_8__SPDIF_SRCLK 1146
+MX53_PAD_GPIO_8__CCM_PLL3_BYP 1147
+MX53_PAD_GPIO_16__ESAI1_TX3_RX2 1148
+MX53_PAD_GPIO_16__GPIO7_11 1149
+MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT 1150
+MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1 1151
+MX53_PAD_GPIO_16__SPDIF_IN1 1152
+MX53_PAD_GPIO_16__I2C3_SDA 1153
+MX53_PAD_GPIO_16__SJC_DE_B 1154
+MX53_PAD_GPIO_17__ESAI1_TX0 1155
+MX53_PAD_GPIO_17__GPIO7_12 1156
+MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0 1157
+MX53_PAD_GPIO_17__GPC_PMIC_RDY 1158
+MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG 1159
+MX53_PAD_GPIO_17__SPDIF_OUT1 1160
+MX53_PAD_GPIO_17__IPU_SNOOP2 1161
+MX53_PAD_GPIO_17__SJC_JTAG_ACT 1162
+MX53_PAD_GPIO_18__ESAI1_TX1 1163
+MX53_PAD_GPIO_18__GPIO7_13 1164
+MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1 1165
+MX53_PAD_GPIO_18__OWIRE_LINE 1166
+MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG 1167
+MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK 1168
+MX53_PAD_GPIO_18__ESDHC1_LCTL 1169
+MX53_PAD_GPIO_18__SRC_SYSTEM_RST 1170
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt
new file mode 100644
index 000000000000..82b43f915857
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt
@@ -0,0 +1,1628 @@
+* Freescale IMX6Q IOMUX Controller
+
+Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
+and usage.
+
+Required properties:
+- compatible: "fsl,imx6q-iomuxc"
+- fsl,pins: two integers array, represents a group of pins mux and config
+ setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
+ pin working on a specific function, CONFIG is the pad setting value like
+ pull-up for this pin. Please refer to imx6q datasheet for the valid pad
+ config settings.
+
+CONFIG bits definition:
+PAD_CTL_HYS (1 << 16)
+PAD_CTL_PUS_100K_DOWN (0 << 14)
+PAD_CTL_PUS_47K_UP (1 << 14)
+PAD_CTL_PUS_100K_UP (2 << 14)
+PAD_CTL_PUS_22K_UP (3 << 14)
+PAD_CTL_PUE (1 << 13)
+PAD_CTL_PKE (1 << 12)
+PAD_CTL_ODE (1 << 11)
+PAD_CTL_SPEED_LOW (1 << 6)
+PAD_CTL_SPEED_MED (2 << 6)
+PAD_CTL_SPEED_HIGH (3 << 6)
+PAD_CTL_DSE_DISABLE (0 << 3)
+PAD_CTL_DSE_240ohm (1 << 3)
+PAD_CTL_DSE_120ohm (2 << 3)
+PAD_CTL_DSE_80ohm (3 << 3)
+PAD_CTL_DSE_60ohm (4 << 3)
+PAD_CTL_DSE_48ohm (5 << 3)
+PAD_CTL_DSE_40ohm (6 << 3)
+PAD_CTL_DSE_34ohm (7 << 3)
+PAD_CTL_SRE_FAST (1 << 0)
+PAD_CTL_SRE_SLOW (0 << 0)
+
+See below for available PIN_FUNC_ID for imx6q:
+MX6Q_PAD_SD2_DAT1__USDHC2_DAT1 0
+MX6Q_PAD_SD2_DAT1__ECSPI5_SS0 1
+MX6Q_PAD_SD2_DAT1__WEIM_WEIM_CS_2 2
+MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS 3
+MX6Q_PAD_SD2_DAT1__KPP_COL_7 4
+MX6Q_PAD_SD2_DAT1__GPIO_1_14 5
+MX6Q_PAD_SD2_DAT1__CCM_WAIT 6
+MX6Q_PAD_SD2_DAT1__ANATOP_TESTO_0 7
+MX6Q_PAD_SD2_DAT2__USDHC2_DAT2 8
+MX6Q_PAD_SD2_DAT2__ECSPI5_SS1 9
+MX6Q_PAD_SD2_DAT2__WEIM_WEIM_CS_3 10
+MX6Q_PAD_SD2_DAT2__AUDMUX_AUD4_TXD 11
+MX6Q_PAD_SD2_DAT2__KPP_ROW_6 12
+MX6Q_PAD_SD2_DAT2__GPIO_1_13 13
+MX6Q_PAD_SD2_DAT2__CCM_STOP 14
+MX6Q_PAD_SD2_DAT2__ANATOP_TESTO_1 15
+MX6Q_PAD_SD2_DAT0__USDHC2_DAT0 16
+MX6Q_PAD_SD2_DAT0__ECSPI5_MISO 17
+MX6Q_PAD_SD2_DAT0__AUDMUX_AUD4_RXD 18
+MX6Q_PAD_SD2_DAT0__KPP_ROW_7 19
+MX6Q_PAD_SD2_DAT0__GPIO_1_15 20
+MX6Q_PAD_SD2_DAT0__DCIC2_DCIC_OUT 21
+MX6Q_PAD_SD2_DAT0__TESTO_2 22
+MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA 23
+MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC 24
+MX6Q_PAD_RGMII_TXC__SPDIF_SPDIF_EXTCLK 25
+MX6Q_PAD_RGMII_TXC__GPIO_6_19 26
+MX6Q_PAD_RGMII_TXC__MIPI_CORE_DPHY_IN_0 27
+MX6Q_PAD_RGMII_TXC__ANATOP_24M_OUT 28
+MX6Q_PAD_RGMII_TD0__MIPI_HSI_CRL_TX_RDY 29
+MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0 30
+MX6Q_PAD_RGMII_TD0__GPIO_6_20 31
+MX6Q_PAD_RGMII_TD0__MIPI_CORE_DPHY_IN_1 32
+MX6Q_PAD_RGMII_TD1__MIPI_HSI_CRL_RX_FLG 33
+MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1 34
+MX6Q_PAD_RGMII_TD1__GPIO_6_21 35
+MX6Q_PAD_RGMII_TD1__MIPI_CORE_DPHY_IN_2 36
+MX6Q_PAD_RGMII_TD1__CCM_PLL3_BYP 37
+MX6Q_PAD_RGMII_TD2__MIPI_HSI_CRL_RX_DTA 38
+MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2 39
+MX6Q_PAD_RGMII_TD2__GPIO_6_22 40
+MX6Q_PAD_RGMII_TD2__MIPI_CORE_DPHY_IN_3 41
+MX6Q_PAD_RGMII_TD2__CCM_PLL2_BYP 42
+MX6Q_PAD_RGMII_TD3__MIPI_HSI_CRL_RX_WAK 43
+MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3 44
+MX6Q_PAD_RGMII_TD3__GPIO_6_23 45
+MX6Q_PAD_RGMII_TD3__MIPI_CORE_DPHY_IN_4 46
+MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA 47
+MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL 48
+MX6Q_PAD_RGMII_RX_CTL__GPIO_6_24 49
+MX6Q_PAD_RGMII_RX_CTL__MIPI_DPHY_IN_5 50
+MX6Q_PAD_RGMII_RD0__MIPI_HSI_CRL_RX_RDY 51
+MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0 52
+MX6Q_PAD_RGMII_RD0__GPIO_6_25 53
+MX6Q_PAD_RGMII_RD0__MIPI_CORE_DPHY_IN_6 54
+MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE 55
+MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL 56
+MX6Q_PAD_RGMII_TX_CTL__GPIO_6_26 57
+MX6Q_PAD_RGMII_TX_CTL__CORE_DPHY_IN_7 58
+MX6Q_PAD_RGMII_TX_CTL__ANATOP_REF_OUT 59
+MX6Q_PAD_RGMII_RD1__MIPI_HSI_CTRL_TX_FL 60
+MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1 61
+MX6Q_PAD_RGMII_RD1__GPIO_6_27 62
+MX6Q_PAD_RGMII_RD1__CORE_DPHY_TEST_IN_8 63
+MX6Q_PAD_RGMII_RD1__SJC_FAIL 64
+MX6Q_PAD_RGMII_RD2__MIPI_HSI_CRL_TX_DTA 65
+MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 66
+MX6Q_PAD_RGMII_RD2__GPIO_6_28 67
+MX6Q_PAD_RGMII_RD2__MIPI_CORE_DPHY_IN_9 68
+MX6Q_PAD_RGMII_RD3__MIPI_HSI_CRL_TX_WAK 69
+MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 70
+MX6Q_PAD_RGMII_RD3__GPIO_6_29 71
+MX6Q_PAD_RGMII_RD3__MIPI_CORE_DPHY_IN10 72
+MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE 73
+MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC 74
+MX6Q_PAD_RGMII_RXC__GPIO_6_30 75
+MX6Q_PAD_RGMII_RXC__MIPI_CORE_DPHY_IN11 76
+MX6Q_PAD_EIM_A25__WEIM_WEIM_A_25 77
+MX6Q_PAD_EIM_A25__ECSPI4_SS1 78
+MX6Q_PAD_EIM_A25__ECSPI2_RDY 79
+MX6Q_PAD_EIM_A25__IPU1_DI1_PIN12 80
+MX6Q_PAD_EIM_A25__IPU1_DI0_D1_CS 81
+MX6Q_PAD_EIM_A25__GPIO_5_2 82
+MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE 83
+MX6Q_PAD_EIM_A25__PL301_PER1_HBURST_0 84
+MX6Q_PAD_EIM_EB2__WEIM_WEIM_EB_2 85
+MX6Q_PAD_EIM_EB2__ECSPI1_SS0 86
+MX6Q_PAD_EIM_EB2__CCM_DI1_EXT_CLK 87
+MX6Q_PAD_EIM_EB2__IPU2_CSI1_D_19 88
+MX6Q_PAD_EIM_EB2__HDMI_TX_DDC_SCL 89
+MX6Q_PAD_EIM_EB2__GPIO_2_30 90
+MX6Q_PAD_EIM_EB2__I2C2_SCL 91
+MX6Q_PAD_EIM_EB2__SRC_BT_CFG_30 92
+MX6Q_PAD_EIM_D16__WEIM_WEIM_D_16 93
+MX6Q_PAD_EIM_D16__ECSPI1_SCLK 94
+MX6Q_PAD_EIM_D16__IPU1_DI0_PIN5 95
+MX6Q_PAD_EIM_D16__IPU2_CSI1_D_18 96
+MX6Q_PAD_EIM_D16__HDMI_TX_DDC_SDA 97
+MX6Q_PAD_EIM_D16__GPIO_3_16 98
+MX6Q_PAD_EIM_D16__I2C2_SDA 99
+MX6Q_PAD_EIM_D17__WEIM_WEIM_D_17 100
+MX6Q_PAD_EIM_D17__ECSPI1_MISO 101
+MX6Q_PAD_EIM_D17__IPU1_DI0_PIN6 102
+MX6Q_PAD_EIM_D17__IPU2_CSI1_PIXCLK 103
+MX6Q_PAD_EIM_D17__DCIC1_DCIC_OUT 104
+MX6Q_PAD_EIM_D17__GPIO_3_17 105
+MX6Q_PAD_EIM_D17__I2C3_SCL 106
+MX6Q_PAD_EIM_D17__PL301_PER1_HBURST_1 107
+MX6Q_PAD_EIM_D18__WEIM_WEIM_D_18 108
+MX6Q_PAD_EIM_D18__ECSPI1_MOSI 109
+MX6Q_PAD_EIM_D18__IPU1_DI0_PIN7 110
+MX6Q_PAD_EIM_D18__IPU2_CSI1_D_17 111
+MX6Q_PAD_EIM_D18__IPU1_DI1_D0_CS 112
+MX6Q_PAD_EIM_D18__GPIO_3_18 113
+MX6Q_PAD_EIM_D18__I2C3_SDA 114
+MX6Q_PAD_EIM_D18__PL301_PER1_HBURST_2 115
+MX6Q_PAD_EIM_D19__WEIM_WEIM_D_19 116
+MX6Q_PAD_EIM_D19__ECSPI1_SS1 117
+MX6Q_PAD_EIM_D19__IPU1_DI0_PIN8 118
+MX6Q_PAD_EIM_D19__IPU2_CSI1_D_16 119
+MX6Q_PAD_EIM_D19__UART1_CTS 120
+MX6Q_PAD_EIM_D19__GPIO_3_19 121
+MX6Q_PAD_EIM_D19__EPIT1_EPITO 122
+MX6Q_PAD_EIM_D19__PL301_PER1_HRESP 123
+MX6Q_PAD_EIM_D20__WEIM_WEIM_D_20 124
+MX6Q_PAD_EIM_D20__ECSPI4_SS0 125
+MX6Q_PAD_EIM_D20__IPU1_DI0_PIN16 126
+MX6Q_PAD_EIM_D20__IPU2_CSI1_D_15 127
+MX6Q_PAD_EIM_D20__UART1_RTS 128
+MX6Q_PAD_EIM_D20__GPIO_3_20 129
+MX6Q_PAD_EIM_D20__EPIT2_EPITO 130
+MX6Q_PAD_EIM_D21__WEIM_WEIM_D_21 131
+MX6Q_PAD_EIM_D21__ECSPI4_SCLK 132
+MX6Q_PAD_EIM_D21__IPU1_DI0_PIN17 133
+MX6Q_PAD_EIM_D21__IPU2_CSI1_D_11 134
+MX6Q_PAD_EIM_D21__USBOH3_USBOTG_OC 135
+MX6Q_PAD_EIM_D21__GPIO_3_21 136
+MX6Q_PAD_EIM_D21__I2C1_SCL 137
+MX6Q_PAD_EIM_D21__SPDIF_IN1 138
+MX6Q_PAD_EIM_D22__WEIM_WEIM_D_22 139
+MX6Q_PAD_EIM_D22__ECSPI4_MISO 140
+MX6Q_PAD_EIM_D22__IPU1_DI0_PIN1 141
+MX6Q_PAD_EIM_D22__IPU2_CSI1_D_10 142
+MX6Q_PAD_EIM_D22__USBOH3_USBOTG_PWR 143
+MX6Q_PAD_EIM_D22__GPIO_3_22 144
+MX6Q_PAD_EIM_D22__SPDIF_OUT1 145
+MX6Q_PAD_EIM_D22__PL301_PER1_HWRITE 146
+MX6Q_PAD_EIM_D23__WEIM_WEIM_D_23 147
+MX6Q_PAD_EIM_D23__IPU1_DI0_D0_CS 148
+MX6Q_PAD_EIM_D23__UART3_CTS 149
+MX6Q_PAD_EIM_D23__UART1_DCD 150
+MX6Q_PAD_EIM_D23__IPU2_CSI1_DATA_EN 151
+MX6Q_PAD_EIM_D23__GPIO_3_23 152
+MX6Q_PAD_EIM_D23__IPU1_DI1_PIN2 153
+MX6Q_PAD_EIM_D23__IPU1_DI1_PIN14 154
+MX6Q_PAD_EIM_EB3__WEIM_WEIM_EB_3 155
+MX6Q_PAD_EIM_EB3__ECSPI4_RDY 156
+MX6Q_PAD_EIM_EB3__UART3_RTS 157
+MX6Q_PAD_EIM_EB3__UART1_RI 158
+MX6Q_PAD_EIM_EB3__IPU2_CSI1_HSYNC 159
+MX6Q_PAD_EIM_EB3__GPIO_2_31 160
+MX6Q_PAD_EIM_EB3__IPU1_DI1_PIN3 161
+MX6Q_PAD_EIM_EB3__SRC_BT_CFG_31 162
+MX6Q_PAD_EIM_D24__WEIM_WEIM_D_24 163
+MX6Q_PAD_EIM_D24__ECSPI4_SS2 164
+MX6Q_PAD_EIM_D24__UART3_TXD 165
+MX6Q_PAD_EIM_D24__ECSPI1_SS2 166
+MX6Q_PAD_EIM_D24__ECSPI2_SS2 167
+MX6Q_PAD_EIM_D24__GPIO_3_24 168
+MX6Q_PAD_EIM_D24__AUDMUX_AUD5_RXFS 169
+MX6Q_PAD_EIM_D24__UART1_DTR 170
+MX6Q_PAD_EIM_D25__WEIM_WEIM_D_25 171
+MX6Q_PAD_EIM_D25__ECSPI4_SS3 172
+MX6Q_PAD_EIM_D25__UART3_RXD 173
+MX6Q_PAD_EIM_D25__ECSPI1_SS3 174
+MX6Q_PAD_EIM_D25__ECSPI2_SS3 175
+MX6Q_PAD_EIM_D25__GPIO_3_25 176
+MX6Q_PAD_EIM_D25__AUDMUX_AUD5_RXC 177
+MX6Q_PAD_EIM_D25__UART1_DSR 178
+MX6Q_PAD_EIM_D26__WEIM_WEIM_D_26 179
+MX6Q_PAD_EIM_D26__IPU1_DI1_PIN11 180
+MX6Q_PAD_EIM_D26__IPU1_CSI0_D_1 181
+MX6Q_PAD_EIM_D26__IPU2_CSI1_D_14 182
+MX6Q_PAD_EIM_D26__UART2_TXD 183
+MX6Q_PAD_EIM_D26__GPIO_3_26 184
+MX6Q_PAD_EIM_D26__IPU1_SISG_2 185
+MX6Q_PAD_EIM_D26__IPU1_DISP1_DAT_22 186
+MX6Q_PAD_EIM_D27__WEIM_WEIM_D_27 187
+MX6Q_PAD_EIM_D27__IPU1_DI1_PIN13 188
+MX6Q_PAD_EIM_D27__IPU1_CSI0_D_0 189
+MX6Q_PAD_EIM_D27__IPU2_CSI1_D_13 190
+MX6Q_PAD_EIM_D27__UART2_RXD 191
+MX6Q_PAD_EIM_D27__GPIO_3_27 192
+MX6Q_PAD_EIM_D27__IPU1_SISG_3 193
+MX6Q_PAD_EIM_D27__IPU1_DISP1_DAT_23 194
+MX6Q_PAD_EIM_D28__WEIM_WEIM_D_28 195
+MX6Q_PAD_EIM_D28__I2C1_SDA 196
+MX6Q_PAD_EIM_D28__ECSPI4_MOSI 197
+MX6Q_PAD_EIM_D28__IPU2_CSI1_D_12 198
+MX6Q_PAD_EIM_D28__UART2_CTS 199
+MX6Q_PAD_EIM_D28__GPIO_3_28 200
+MX6Q_PAD_EIM_D28__IPU1_EXT_TRIG 201
+MX6Q_PAD_EIM_D28__IPU1_DI0_PIN13 202
+MX6Q_PAD_EIM_D29__WEIM_WEIM_D_29 203
+MX6Q_PAD_EIM_D29__IPU1_DI1_PIN15 204
+MX6Q_PAD_EIM_D29__ECSPI4_SS0 205
+MX6Q_PAD_EIM_D29__UART2_RTS 206
+MX6Q_PAD_EIM_D29__GPIO_3_29 207
+MX6Q_PAD_EIM_D29__IPU2_CSI1_VSYNC 208
+MX6Q_PAD_EIM_D29__IPU1_DI0_PIN14 209
+MX6Q_PAD_EIM_D30__WEIM_WEIM_D_30 210
+MX6Q_PAD_EIM_D30__IPU1_DISP1_DAT_21 211
+MX6Q_PAD_EIM_D30__IPU1_DI0_PIN11 212
+MX6Q_PAD_EIM_D30__IPU1_CSI0_D_3 213
+MX6Q_PAD_EIM_D30__UART3_CTS 214
+MX6Q_PAD_EIM_D30__GPIO_3_30 215
+MX6Q_PAD_EIM_D30__USBOH3_USBH1_OC 216
+MX6Q_PAD_EIM_D30__PL301_PER1_HPROT_0 217
+MX6Q_PAD_EIM_D31__WEIM_WEIM_D_31 218
+MX6Q_PAD_EIM_D31__IPU1_DISP1_DAT_20 219
+MX6Q_PAD_EIM_D31__IPU1_DI0_PIN12 220
+MX6Q_PAD_EIM_D31__IPU1_CSI0_D_2 221
+MX6Q_PAD_EIM_D31__UART3_RTS 222
+MX6Q_PAD_EIM_D31__GPIO_3_31 223
+MX6Q_PAD_EIM_D31__USBOH3_USBH1_PWR 224
+MX6Q_PAD_EIM_D31__PL301_PER1_HPROT_1 225
+MX6Q_PAD_EIM_A24__WEIM_WEIM_A_24 226
+MX6Q_PAD_EIM_A24__IPU1_DISP1_DAT_19 227
+MX6Q_PAD_EIM_A24__IPU2_CSI1_D_19 228
+MX6Q_PAD_EIM_A24__IPU2_SISG_2 229
+MX6Q_PAD_EIM_A24__IPU1_SISG_2 230
+MX6Q_PAD_EIM_A24__GPIO_5_4 231
+MX6Q_PAD_EIM_A24__PL301_PER1_HPROT_2 232
+MX6Q_PAD_EIM_A24__SRC_BT_CFG_24 233
+MX6Q_PAD_EIM_A23__WEIM_WEIM_A_23 234
+MX6Q_PAD_EIM_A23__IPU1_DISP1_DAT_18 235
+MX6Q_PAD_EIM_A23__IPU2_CSI1_D_18 236
+MX6Q_PAD_EIM_A23__IPU2_SISG_3 237
+MX6Q_PAD_EIM_A23__IPU1_SISG_3 238
+MX6Q_PAD_EIM_A23__GPIO_6_6 239
+MX6Q_PAD_EIM_A23__PL301_PER1_HPROT_3 240
+MX6Q_PAD_EIM_A23__SRC_BT_CFG_23 241
+MX6Q_PAD_EIM_A22__WEIM_WEIM_A_22 242
+MX6Q_PAD_EIM_A22__IPU1_DISP1_DAT_17 243
+MX6Q_PAD_EIM_A22__IPU2_CSI1_D_17 244
+MX6Q_PAD_EIM_A22__GPIO_2_16 245
+MX6Q_PAD_EIM_A22__TPSMP_HDATA_0 246
+MX6Q_PAD_EIM_A22__SRC_BT_CFG_22 247
+MX6Q_PAD_EIM_A21__WEIM_WEIM_A_21 248
+MX6Q_PAD_EIM_A21__IPU1_DISP1_DAT_16 249
+MX6Q_PAD_EIM_A21__IPU2_CSI1_D_16 250
+MX6Q_PAD_EIM_A21__RESERVED_RESERVED 251
+MX6Q_PAD_EIM_A21__MIPI_CORE_DPHY_OUT_18 252
+MX6Q_PAD_EIM_A21__GPIO_2_17 253
+MX6Q_PAD_EIM_A21__TPSMP_HDATA_1 254
+MX6Q_PAD_EIM_A21__SRC_BT_CFG_21 255
+MX6Q_PAD_EIM_A20__WEIM_WEIM_A_20 256
+MX6Q_PAD_EIM_A20__IPU1_DISP1_DAT_15 257
+MX6Q_PAD_EIM_A20__IPU2_CSI1_D_15 258
+MX6Q_PAD_EIM_A20__RESERVED_RESERVED 259
+MX6Q_PAD_EIM_A20__MIPI_CORE_DPHY_OUT_19 260
+MX6Q_PAD_EIM_A20__GPIO_2_18 261
+MX6Q_PAD_EIM_A20__TPSMP_HDATA_2 262
+MX6Q_PAD_EIM_A20__SRC_BT_CFG_20 263
+MX6Q_PAD_EIM_A19__WEIM_WEIM_A_19 264
+MX6Q_PAD_EIM_A19__IPU1_DISP1_DAT_14 265
+MX6Q_PAD_EIM_A19__IPU2_CSI1_D_14 266
+MX6Q_PAD_EIM_A19__RESERVED_RESERVED 267
+MX6Q_PAD_EIM_A19__MIPI_CORE_DPHY_OUT_20 268
+MX6Q_PAD_EIM_A19__GPIO_2_19 269
+MX6Q_PAD_EIM_A19__TPSMP_HDATA_3 270
+MX6Q_PAD_EIM_A19__SRC_BT_CFG_19 271
+MX6Q_PAD_EIM_A18__WEIM_WEIM_A_18 272
+MX6Q_PAD_EIM_A18__IPU1_DISP1_DAT_13 273
+MX6Q_PAD_EIM_A18__IPU2_CSI1_D_13 274
+MX6Q_PAD_EIM_A18__RESERVED_RESERVED 275
+MX6Q_PAD_EIM_A18__MIPI_CORE_DPHY_OUT_21 276
+MX6Q_PAD_EIM_A18__GPIO_2_20 277
+MX6Q_PAD_EIM_A18__TPSMP_HDATA_4 278
+MX6Q_PAD_EIM_A18__SRC_BT_CFG_18 279
+MX6Q_PAD_EIM_A17__WEIM_WEIM_A_17 280
+MX6Q_PAD_EIM_A17__IPU1_DISP1_DAT_12 281
+MX6Q_PAD_EIM_A17__IPU2_CSI1_D_12 282
+MX6Q_PAD_EIM_A17__RESERVED_RESERVED 283
+MX6Q_PAD_EIM_A17__MIPI_CORE_DPHY_OUT_22 284
+MX6Q_PAD_EIM_A17__GPIO_2_21 285
+MX6Q_PAD_EIM_A17__TPSMP_HDATA_5 286
+MX6Q_PAD_EIM_A17__SRC_BT_CFG_17 287
+MX6Q_PAD_EIM_A16__WEIM_WEIM_A_16 288
+MX6Q_PAD_EIM_A16__IPU1_DI1_DISP_CLK 289
+MX6Q_PAD_EIM_A16__IPU2_CSI1_PIXCLK 290
+MX6Q_PAD_EIM_A16__MIPI_CORE_DPHY_OUT_23 291
+MX6Q_PAD_EIM_A16__GPIO_2_22 292
+MX6Q_PAD_EIM_A16__TPSMP_HDATA_6 293
+MX6Q_PAD_EIM_A16__SRC_BT_CFG_16 294
+MX6Q_PAD_EIM_CS0__WEIM_WEIM_CS_0 295
+MX6Q_PAD_EIM_CS0__IPU1_DI1_PIN5 296
+MX6Q_PAD_EIM_CS0__ECSPI2_SCLK 297
+MX6Q_PAD_EIM_CS0__MIPI_CORE_DPHY_OUT_24 298
+MX6Q_PAD_EIM_CS0__GPIO_2_23 299
+MX6Q_PAD_EIM_CS0__TPSMP_HDATA_7 300
+MX6Q_PAD_EIM_CS1__WEIM_WEIM_CS_1 301
+MX6Q_PAD_EIM_CS1__IPU1_DI1_PIN6 302
+MX6Q_PAD_EIM_CS1__ECSPI2_MOSI 303
+MX6Q_PAD_EIM_CS1__MIPI_CORE_DPHY_OUT_25 304
+MX6Q_PAD_EIM_CS1__GPIO_2_24 305
+MX6Q_PAD_EIM_CS1__TPSMP_HDATA_8 306
+MX6Q_PAD_EIM_OE__WEIM_WEIM_OE 307
+MX6Q_PAD_EIM_OE__IPU1_DI1_PIN7 308
+MX6Q_PAD_EIM_OE__ECSPI2_MISO 309
+MX6Q_PAD_EIM_OE__MIPI_CORE_DPHY_OUT_26 310
+MX6Q_PAD_EIM_OE__GPIO_2_25 311
+MX6Q_PAD_EIM_OE__TPSMP_HDATA_9 312
+MX6Q_PAD_EIM_RW__WEIM_WEIM_RW 313
+MX6Q_PAD_EIM_RW__IPU1_DI1_PIN8 314
+MX6Q_PAD_EIM_RW__ECSPI2_SS0 315
+MX6Q_PAD_EIM_RW__MIPI_CORE_DPHY_OUT_27 316
+MX6Q_PAD_EIM_RW__GPIO_2_26 317
+MX6Q_PAD_EIM_RW__TPSMP_HDATA_10 318
+MX6Q_PAD_EIM_RW__SRC_BT_CFG_29 319
+MX6Q_PAD_EIM_LBA__WEIM_WEIM_LBA 320
+MX6Q_PAD_EIM_LBA__IPU1_DI1_PIN17 321
+MX6Q_PAD_EIM_LBA__ECSPI2_SS1 322
+MX6Q_PAD_EIM_LBA__GPIO_2_27 323
+MX6Q_PAD_EIM_LBA__TPSMP_HDATA_11 324
+MX6Q_PAD_EIM_LBA__SRC_BT_CFG_26 325
+MX6Q_PAD_EIM_EB0__WEIM_WEIM_EB_0 326
+MX6Q_PAD_EIM_EB0__IPU1_DISP1_DAT_11 327
+MX6Q_PAD_EIM_EB0__IPU2_CSI1_D_11 328
+MX6Q_PAD_EIM_EB0__MIPI_CORE_DPHY_OUT_0 329
+MX6Q_PAD_EIM_EB0__CCM_PMIC_RDY 330
+MX6Q_PAD_EIM_EB0__GPIO_2_28 331
+MX6Q_PAD_EIM_EB0__TPSMP_HDATA_12 332
+MX6Q_PAD_EIM_EB0__SRC_BT_CFG_27 333
+MX6Q_PAD_EIM_EB1__WEIM_WEIM_EB_1 334
+MX6Q_PAD_EIM_EB1__IPU1_DISP1_DAT_10 335
+MX6Q_PAD_EIM_EB1__IPU2_CSI1_D_10 336
+MX6Q_PAD_EIM_EB1__MIPI_CORE_DPHY__OUT_1 337
+MX6Q_PAD_EIM_EB1__GPIO_2_29 338
+MX6Q_PAD_EIM_EB1__TPSMP_HDATA_13 339
+MX6Q_PAD_EIM_EB1__SRC_BT_CFG_28 340
+MX6Q_PAD_EIM_DA0__WEIM_WEIM_DA_A_0 341
+MX6Q_PAD_EIM_DA0__IPU1_DISP1_DAT_9 342
+MX6Q_PAD_EIM_DA0__IPU2_CSI1_D_9 343
+MX6Q_PAD_EIM_DA0__MIPI_CORE_DPHY__OUT_2 344
+MX6Q_PAD_EIM_DA0__GPIO_3_0 345
+MX6Q_PAD_EIM_DA0__TPSMP_HDATA_14 346
+MX6Q_PAD_EIM_DA0__SRC_BT_CFG_0 347
+MX6Q_PAD_EIM_DA1__WEIM_WEIM_DA_A_1 348
+MX6Q_PAD_EIM_DA1__IPU1_DISP1_DAT_8 349
+MX6Q_PAD_EIM_DA1__IPU2_CSI1_D_8 350
+MX6Q_PAD_EIM_DA1__MIPI_CORE_DPHY_OUT_3 351
+MX6Q_PAD_EIM_DA1__USBPHY1_TX_LS_MODE 352
+MX6Q_PAD_EIM_DA1__GPIO_3_1 353
+MX6Q_PAD_EIM_DA1__TPSMP_HDATA_15 354
+MX6Q_PAD_EIM_DA1__SRC_BT_CFG_1 355
+MX6Q_PAD_EIM_DA2__WEIM_WEIM_DA_A_2 356
+MX6Q_PAD_EIM_DA2__IPU1_DISP1_DAT_7 357
+MX6Q_PAD_EIM_DA2__IPU2_CSI1_D_7 358
+MX6Q_PAD_EIM_DA2__MIPI_CORE_DPHY_OUT_4 359
+MX6Q_PAD_EIM_DA2__USBPHY1_TX_HS_MODE 360
+MX6Q_PAD_EIM_DA2__GPIO_3_2 361
+MX6Q_PAD_EIM_DA2__TPSMP_HDATA_16 362
+MX6Q_PAD_EIM_DA2__SRC_BT_CFG_2 363
+MX6Q_PAD_EIM_DA3__WEIM_WEIM_DA_A_3 364
+MX6Q_PAD_EIM_DA3__IPU1_DISP1_DAT_6 365
+MX6Q_PAD_EIM_DA3__IPU2_CSI1_D_6 366
+MX6Q_PAD_EIM_DA3__MIPI_CORE_DPHY_OUT_5 367
+MX6Q_PAD_EIM_DA3__USBPHY1_TX_HIZ 368
+MX6Q_PAD_EIM_DA3__GPIO_3_3 369
+MX6Q_PAD_EIM_DA3__TPSMP_HDATA_17 370
+MX6Q_PAD_EIM_DA3__SRC_BT_CFG_3 371
+MX6Q_PAD_EIM_DA4__WEIM_WEIM_DA_A_4 372
+MX6Q_PAD_EIM_DA4__IPU1_DISP1_DAT_5 373
+MX6Q_PAD_EIM_DA4__IPU2_CSI1_D_5 374
+MX6Q_PAD_EIM_DA4__MIPI_CORE_DPHY_OUT_6 375
+MX6Q_PAD_EIM_DA4__ANATOP_USBPHY1_TX_EN 376
+MX6Q_PAD_EIM_DA4__GPIO_3_4 377
+MX6Q_PAD_EIM_DA4__TPSMP_HDATA_18 378
+MX6Q_PAD_EIM_DA4__SRC_BT_CFG_4 379
+MX6Q_PAD_EIM_DA5__WEIM_WEIM_DA_A_5 380
+MX6Q_PAD_EIM_DA5__IPU1_DISP1_DAT_4 381
+MX6Q_PAD_EIM_DA5__IPU2_CSI1_D_4 382
+MX6Q_PAD_EIM_DA5__MIPI_CORE_DPHY_OUT_7 383
+MX6Q_PAD_EIM_DA5__ANATOP_USBPHY1_TX_DP 384
+MX6Q_PAD_EIM_DA5__GPIO_3_5 385
+MX6Q_PAD_EIM_DA5__TPSMP_HDATA_19 386
+MX6Q_PAD_EIM_DA5__SRC_BT_CFG_5 387
+MX6Q_PAD_EIM_DA6__WEIM_WEIM_DA_A_6 388
+MX6Q_PAD_EIM_DA6__IPU1_DISP1_DAT_3 389
+MX6Q_PAD_EIM_DA6__IPU2_CSI1_D_3 390
+MX6Q_PAD_EIM_DA6__MIPI_CORE_DPHY_OUT_8 391
+MX6Q_PAD_EIM_DA6__ANATOP_USBPHY1_TX_DN 392
+MX6Q_PAD_EIM_DA6__GPIO_3_6 393
+MX6Q_PAD_EIM_DA6__TPSMP_HDATA_20 394
+MX6Q_PAD_EIM_DA6__SRC_BT_CFG_6 395
+MX6Q_PAD_EIM_DA7__WEIM_WEIM_DA_A_7 396
+MX6Q_PAD_EIM_DA7__IPU1_DISP1_DAT_2 397
+MX6Q_PAD_EIM_DA7__IPU2_CSI1_D_2 398
+MX6Q_PAD_EIM_DA7__MIPI_CORE_DPHY_OUT_9 399
+MX6Q_PAD_EIM_DA7__GPIO_3_7 400
+MX6Q_PAD_EIM_DA7__TPSMP_HDATA_21 401
+MX6Q_PAD_EIM_DA7__SRC_BT_CFG_7 402
+MX6Q_PAD_EIM_DA8__WEIM_WEIM_DA_A_8 403
+MX6Q_PAD_EIM_DA8__IPU1_DISP1_DAT_1 404
+MX6Q_PAD_EIM_DA8__IPU2_CSI1_D_1 405
+MX6Q_PAD_EIM_DA8__MIPI_CORE_DPHY_OUT_10 406
+MX6Q_PAD_EIM_DA8__GPIO_3_8 407
+MX6Q_PAD_EIM_DA8__TPSMP_HDATA_22 408
+MX6Q_PAD_EIM_DA8__SRC_BT_CFG_8 409
+MX6Q_PAD_EIM_DA9__WEIM_WEIM_DA_A_9 410
+MX6Q_PAD_EIM_DA9__IPU1_DISP1_DAT_0 411
+MX6Q_PAD_EIM_DA9__IPU2_CSI1_D_0 412
+MX6Q_PAD_EIM_DA9__MIPI_CORE_DPHY_OUT_11 413
+MX6Q_PAD_EIM_DA9__GPIO_3_9 414
+MX6Q_PAD_EIM_DA9__TPSMP_HDATA_23 415
+MX6Q_PAD_EIM_DA9__SRC_BT_CFG_9 416
+MX6Q_PAD_EIM_DA10__WEIM_WEIM_DA_A_10 417
+MX6Q_PAD_EIM_DA10__IPU1_DI1_PIN15 418
+MX6Q_PAD_EIM_DA10__IPU2_CSI1_DATA_EN 419
+MX6Q_PAD_EIM_DA10__MIPI_CORE_DPHY_OUT12 420
+MX6Q_PAD_EIM_DA10__GPIO_3_10 421
+MX6Q_PAD_EIM_DA10__TPSMP_HDATA_24 422
+MX6Q_PAD_EIM_DA10__SRC_BT_CFG_10 423
+MX6Q_PAD_EIM_DA11__WEIM_WEIM_DA_A_11 424
+MX6Q_PAD_EIM_DA11__IPU1_DI1_PIN2 425
+MX6Q_PAD_EIM_DA11__IPU2_CSI1_HSYNC 426
+MX6Q_PAD_EIM_DA11__MIPI_CORE_DPHY_OUT13 427
+MX6Q_PAD_EIM_DA11__SDMA_DBG_EVT_CHN_6 428
+MX6Q_PAD_EIM_DA11__GPIO_3_11 429
+MX6Q_PAD_EIM_DA11__TPSMP_HDATA_25 430
+MX6Q_PAD_EIM_DA11__SRC_BT_CFG_11 431
+MX6Q_PAD_EIM_DA12__WEIM_WEIM_DA_A_12 432
+MX6Q_PAD_EIM_DA12__IPU1_DI1_PIN3 433
+MX6Q_PAD_EIM_DA12__IPU2_CSI1_VSYNC 434
+MX6Q_PAD_EIM_DA12__MIPI_CORE_DPHY_OUT14 435
+MX6Q_PAD_EIM_DA12__SDMA_DEBUG_EVT_CHN_3 436
+MX6Q_PAD_EIM_DA12__GPIO_3_12 437
+MX6Q_PAD_EIM_DA12__TPSMP_HDATA_26 438
+MX6Q_PAD_EIM_DA12__SRC_BT_CFG_12 439
+MX6Q_PAD_EIM_DA13__WEIM_WEIM_DA_A_13 440
+MX6Q_PAD_EIM_DA13__IPU1_DI1_D0_CS 441
+MX6Q_PAD_EIM_DA13__CCM_DI1_EXT_CLK 442
+MX6Q_PAD_EIM_DA13__MIPI_CORE_DPHY_OUT15 443
+MX6Q_PAD_EIM_DA13__SDMA_DEBUG_EVT_CHN_4 444
+MX6Q_PAD_EIM_DA13__GPIO_3_13 445
+MX6Q_PAD_EIM_DA13__TPSMP_HDATA_27 446
+MX6Q_PAD_EIM_DA13__SRC_BT_CFG_13 447
+MX6Q_PAD_EIM_DA14__WEIM_WEIM_DA_A_14 448
+MX6Q_PAD_EIM_DA14__IPU1_DI1_D1_CS 449
+MX6Q_PAD_EIM_DA14__CCM_DI0_EXT_CLK 450
+MX6Q_PAD_EIM_DA14__MIPI_CORE_DPHY_OUT16 451
+MX6Q_PAD_EIM_DA14__SDMA_DEBUG_EVT_CHN_5 452
+MX6Q_PAD_EIM_DA14__GPIO_3_14 453
+MX6Q_PAD_EIM_DA14__TPSMP_HDATA_28 454
+MX6Q_PAD_EIM_DA14__SRC_BT_CFG_14 455
+MX6Q_PAD_EIM_DA15__WEIM_WEIM_DA_A_15 456
+MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN1 457
+MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN4 458
+MX6Q_PAD_EIM_DA15__MIPI_CORE_DPHY_OUT17 459
+MX6Q_PAD_EIM_DA15__GPIO_3_15 460
+MX6Q_PAD_EIM_DA15__TPSMP_HDATA_29 461
+MX6Q_PAD_EIM_DA15__SRC_BT_CFG_15 462
+MX6Q_PAD_EIM_WAIT__WEIM_WEIM_WAIT 463
+MX6Q_PAD_EIM_WAIT__WEIM_WEIM_DTACK_B 464
+MX6Q_PAD_EIM_WAIT__GPIO_5_0 465
+MX6Q_PAD_EIM_WAIT__TPSMP_HDATA_30 466
+MX6Q_PAD_EIM_WAIT__SRC_BT_CFG_25 467
+MX6Q_PAD_EIM_BCLK__WEIM_WEIM_BCLK 468
+MX6Q_PAD_EIM_BCLK__IPU1_DI1_PIN16 469
+MX6Q_PAD_EIM_BCLK__GPIO_6_31 470
+MX6Q_PAD_EIM_BCLK__TPSMP_HDATA_31 471
+MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DSP_CLK 472
+MX6Q_PAD_DI0_DISP_CLK__IPU2_DI0_DSP_CLK 473
+MX6Q_PAD_DI0_DISP_CLK__MIPI_CR_DPY_OT28 474
+MX6Q_PAD_DI0_DISP_CLK__SDMA_DBG_CR_STA0 475
+MX6Q_PAD_DI0_DISP_CLK__GPIO_4_16 476
+MX6Q_PAD_DI0_DISP_CLK__MMDC_DEBUG_0 477
+MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15 478
+MX6Q_PAD_DI0_PIN15__IPU2_DI0_PIN15 479
+MX6Q_PAD_DI0_PIN15__AUDMUX_AUD6_TXC 480
+MX6Q_PAD_DI0_PIN15__MIPI_CR_DPHY_OUT_29 481
+MX6Q_PAD_DI0_PIN15__SDMA_DBG_CORE_STA_1 482
+MX6Q_PAD_DI0_PIN15__GPIO_4_17 483
+MX6Q_PAD_DI0_PIN15__MMDC_MMDC_DEBUG_1 484
+MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN2 485
+MX6Q_PAD_DI0_PIN2__IPU2_DI0_PIN2 486
+MX6Q_PAD_DI0_PIN2__AUDMUX_AUD6_TXD 487
+MX6Q_PAD_DI0_PIN2__MIPI_CR_DPHY_OUT_30 488
+MX6Q_PAD_DI0_PIN2__SDMA_DBG_CORE_STA_2 489
+MX6Q_PAD_DI0_PIN2__GPIO_4_18 490
+MX6Q_PAD_DI0_PIN2__MMDC_DEBUG_2 491
+MX6Q_PAD_DI0_PIN2__PL301_PER1_HADDR_9 492
+MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN3 493
+MX6Q_PAD_DI0_PIN3__IPU2_DI0_PIN3 494
+MX6Q_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS 495
+MX6Q_PAD_DI0_PIN3__MIPI_CORE_DPHY_OUT31 496
+MX6Q_PAD_DI0_PIN3__SDMA_DBG_CORE_STA_3 497
+MX6Q_PAD_DI0_PIN3__GPIO_4_19 498
+MX6Q_PAD_DI0_PIN3__MMDC_MMDC_DEBUG_3 499
+MX6Q_PAD_DI0_PIN3__PL301_PER1_HADDR_10 500
+MX6Q_PAD_DI0_PIN4__IPU1_DI0_PIN4 501
+MX6Q_PAD_DI0_PIN4__IPU2_DI0_PIN4 502
+MX6Q_PAD_DI0_PIN4__AUDMUX_AUD6_RXD 503
+MX6Q_PAD_DI0_PIN4__USDHC1_WP 504
+MX6Q_PAD_DI0_PIN4__SDMA_DEBUG_YIELD 505
+MX6Q_PAD_DI0_PIN4__GPIO_4_20 506
+MX6Q_PAD_DI0_PIN4__MMDC_MMDC_DEBUG_4 507
+MX6Q_PAD_DI0_PIN4__PL301_PER1_HADDR_11 508
+MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0 509
+MX6Q_PAD_DISP0_DAT0__IPU2_DISP0_DAT_0 510
+MX6Q_PAD_DISP0_DAT0__ECSPI3_SCLK 511
+MX6Q_PAD_DISP0_DAT0__USDHC1_USDHC_DBG_0 512
+MX6Q_PAD_DISP0_DAT0__SDMA_DBG_CORE_RUN 513
+MX6Q_PAD_DISP0_DAT0__GPIO_4_21 514
+MX6Q_PAD_DISP0_DAT0__MMDC_MMDC_DEBUG_5 515
+MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1 516
+MX6Q_PAD_DISP0_DAT1__IPU2_DISP0_DAT_1 517
+MX6Q_PAD_DISP0_DAT1__ECSPI3_MOSI 518
+MX6Q_PAD_DISP0_DAT1__USDHC1_USDHC_DBG_1 519
+MX6Q_PAD_DISP0_DAT1__SDMA_DBG_EVT_CHNSL 520
+MX6Q_PAD_DISP0_DAT1__GPIO_4_22 521
+MX6Q_PAD_DISP0_DAT1__MMDC_DEBUG_6 522
+MX6Q_PAD_DISP0_DAT1__PL301_PER1_HADR_12 523
+MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2 524
+MX6Q_PAD_DISP0_DAT2__IPU2_DISP0_DAT_2 525
+MX6Q_PAD_DISP0_DAT2__ECSPI3_MISO 526
+MX6Q_PAD_DISP0_DAT2__USDHC1_USDHC_DBG_2 527
+MX6Q_PAD_DISP0_DAT2__SDMA_DEBUG_MODE 528
+MX6Q_PAD_DISP0_DAT2__GPIO_4_23 529
+MX6Q_PAD_DISP0_DAT2__MMDC_DEBUG_7 530
+MX6Q_PAD_DISP0_DAT2__PL301_PER1_HADR_13 531
+MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3 532
+MX6Q_PAD_DISP0_DAT3__IPU2_DISP0_DAT_3 533
+MX6Q_PAD_DISP0_DAT3__ECSPI3_SS0 534
+MX6Q_PAD_DISP0_DAT3__USDHC1_USDHC_DBG_3 535
+MX6Q_PAD_DISP0_DAT3__SDMA_DBG_BUS_ERROR 536
+MX6Q_PAD_DISP0_DAT3__GPIO_4_24 537
+MX6Q_PAD_DISP0_DAT3__MMDC_MMDC_DBG_8 538
+MX6Q_PAD_DISP0_DAT3__PL301_PER1_HADR_14 539
+MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4 540
+MX6Q_PAD_DISP0_DAT4__IPU2_DISP0_DAT_4 541
+MX6Q_PAD_DISP0_DAT4__ECSPI3_SS1 542
+MX6Q_PAD_DISP0_DAT4__USDHC1_USDHC_DBG_4 543
+MX6Q_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB 544
+MX6Q_PAD_DISP0_DAT4__GPIO_4_25 545
+MX6Q_PAD_DISP0_DAT4__MMDC_MMDC_DEBUG_9 546
+MX6Q_PAD_DISP0_DAT4__PL301_PER1_HADR_15 547
+MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5 548
+MX6Q_PAD_DISP0_DAT5__IPU2_DISP0_DAT_5 549
+MX6Q_PAD_DISP0_DAT5__ECSPI3_SS2 550
+MX6Q_PAD_DISP0_DAT5__AUDMUX_AUD6_RXFS 551
+MX6Q_PAD_DISP0_DAT5__SDMA_DBG_MCH_DMBUS 552
+MX6Q_PAD_DISP0_DAT5__GPIO_4_26 553
+MX6Q_PAD_DISP0_DAT5__MMDC_DEBUG_10 554
+MX6Q_PAD_DISP0_DAT5__PL301_PER1_HADR_16 555
+MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6 556
+MX6Q_PAD_DISP0_DAT6__IPU2_DISP0_DAT_6 557
+MX6Q_PAD_DISP0_DAT6__ECSPI3_SS3 558
+MX6Q_PAD_DISP0_DAT6__AUDMUX_AUD6_RXC 559
+MX6Q_PAD_DISP0_DAT6__SDMA_DBG_RTBUF_WRT 560
+MX6Q_PAD_DISP0_DAT6__GPIO_4_27 561
+MX6Q_PAD_DISP0_DAT6__MMDC_DEBUG_11 562
+MX6Q_PAD_DISP0_DAT6__PL301_PER1_HADR_17 563
+MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7 564
+MX6Q_PAD_DISP0_DAT7__IPU2_DISP0_DAT_7 565
+MX6Q_PAD_DISP0_DAT7__ECSPI3_RDY 566
+MX6Q_PAD_DISP0_DAT7__USDHC1_USDHC_DBG_5 567
+MX6Q_PAD_DISP0_DAT7__SDMA_DBG_EVT_CHN_0 568
+MX6Q_PAD_DISP0_DAT7__GPIO_4_28 569
+MX6Q_PAD_DISP0_DAT7__MMDC_DEBUG_12 570
+MX6Q_PAD_DISP0_DAT7__PL301_PER1_HADR_18 571
+MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8 572
+MX6Q_PAD_DISP0_DAT8__IPU2_DISP0_DAT_8 573
+MX6Q_PAD_DISP0_DAT8__PWM1_PWMO 574
+MX6Q_PAD_DISP0_DAT8__WDOG1_WDOG_B 575
+MX6Q_PAD_DISP0_DAT8__SDMA_DBG_EVT_CHN_1 576
+MX6Q_PAD_DISP0_DAT8__GPIO_4_29 577
+MX6Q_PAD_DISP0_DAT8__MMDC_DEBUG_13 578
+MX6Q_PAD_DISP0_DAT8__PL301_PER1_HADR_19 579
+MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9 580
+MX6Q_PAD_DISP0_DAT9__IPU2_DISP0_DAT_9 581
+MX6Q_PAD_DISP0_DAT9__PWM2_PWMO 582
+MX6Q_PAD_DISP0_DAT9__WDOG2_WDOG_B 583
+MX6Q_PAD_DISP0_DAT9__SDMA_DBG_EVT_CHN_2 584
+MX6Q_PAD_DISP0_DAT9__GPIO_4_30 585
+MX6Q_PAD_DISP0_DAT9__MMDC_DEBUG_14 586
+MX6Q_PAD_DISP0_DAT9__PL301_PER1_HADR_20 587
+MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10 588
+MX6Q_PAD_DISP0_DAT10__IPU2_DISP0_DAT_10 589
+MX6Q_PAD_DISP0_DAT10__USDHC1_DBG_6 590
+MX6Q_PAD_DISP0_DAT10__SDMA_DBG_EVT_CHN3 591
+MX6Q_PAD_DISP0_DAT10__GPIO_4_31 592
+MX6Q_PAD_DISP0_DAT10__MMDC_DEBUG_15 593
+MX6Q_PAD_DISP0_DAT10__PL301_PER1_HADR21 594
+MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11 595
+MX6Q_PAD_DISP0_DAT11__IPU2_DISP0_DAT_11 596
+MX6Q_PAD_DISP0_DAT11__USDHC1_USDHC_DBG7 597
+MX6Q_PAD_DISP0_DAT11__SDMA_DBG_EVT_CHN4 598
+MX6Q_PAD_DISP0_DAT11__GPIO_5_5 599
+MX6Q_PAD_DISP0_DAT11__MMDC_DEBUG_16 600
+MX6Q_PAD_DISP0_DAT11__PL301_PER1_HADR22 601
+MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12 602
+MX6Q_PAD_DISP0_DAT12__IPU2_DISP0_DAT_12 603
+MX6Q_PAD_DISP0_DAT12__RESERVED_RESERVED 604
+MX6Q_PAD_DISP0_DAT12__SDMA_DBG_EVT_CHN5 605
+MX6Q_PAD_DISP0_DAT12__GPIO_5_6 606
+MX6Q_PAD_DISP0_DAT12__MMDC_DEBUG_17 607
+MX6Q_PAD_DISP0_DAT12__PL301_PER1_HADR23 608
+MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13 609
+MX6Q_PAD_DISP0_DAT13__IPU2_DISP0_DAT_13 610
+MX6Q_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS 611
+MX6Q_PAD_DISP0_DAT13__SDMA_DBG_EVT_CHN0 612
+MX6Q_PAD_DISP0_DAT13__GPIO_5_7 613
+MX6Q_PAD_DISP0_DAT13__MMDC_DEBUG_18 614
+MX6Q_PAD_DISP0_DAT13__PL301_PER1_HADR24 615
+MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14 616
+MX6Q_PAD_DISP0_DAT14__IPU2_DISP0_DAT_14 617
+MX6Q_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC 618
+MX6Q_PAD_DISP0_DAT14__SDMA_DBG_EVT_CHN1 619
+MX6Q_PAD_DISP0_DAT14__GPIO_5_8 620
+MX6Q_PAD_DISP0_DAT14__MMDC_DEBUG_19 621
+MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15 622
+MX6Q_PAD_DISP0_DAT15__IPU2_DISP0_DAT_15 623
+MX6Q_PAD_DISP0_DAT15__ECSPI1_SS1 624
+MX6Q_PAD_DISP0_DAT15__ECSPI2_SS1 625
+MX6Q_PAD_DISP0_DAT15__SDMA_DBG_EVT_CHN2 626
+MX6Q_PAD_DISP0_DAT15__GPIO_5_9 627
+MX6Q_PAD_DISP0_DAT15__MMDC_DEBUG_20 628
+MX6Q_PAD_DISP0_DAT15__PL301_PER1_HADR25 629
+MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16 630
+MX6Q_PAD_DISP0_DAT16__IPU2_DISP0_DAT_16 631
+MX6Q_PAD_DISP0_DAT16__ECSPI2_MOSI 632
+MX6Q_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC 633
+MX6Q_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 634
+MX6Q_PAD_DISP0_DAT16__GPIO_5_10 635
+MX6Q_PAD_DISP0_DAT16__MMDC_DEBUG_21 636
+MX6Q_PAD_DISP0_DAT16__PL301_PER1_HADR26 637
+MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17 638
+MX6Q_PAD_DISP0_DAT17__IPU2_DISP0_DAT_17 639
+MX6Q_PAD_DISP0_DAT17__ECSPI2_MISO 640
+MX6Q_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD 641
+MX6Q_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 642
+MX6Q_PAD_DISP0_DAT17__GPIO_5_11 643
+MX6Q_PAD_DISP0_DAT17__MMDC_DEBUG_22 644
+MX6Q_PAD_DISP0_DAT17__PL301_PER1_HADR27 645
+MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18 646
+MX6Q_PAD_DISP0_DAT18__IPU2_DISP0_DAT_18 647
+MX6Q_PAD_DISP0_DAT18__ECSPI2_SS0 648
+MX6Q_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS 649
+MX6Q_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS 650
+MX6Q_PAD_DISP0_DAT18__GPIO_5_12 651
+MX6Q_PAD_DISP0_DAT18__MMDC_DEBUG_23 652
+MX6Q_PAD_DISP0_DAT18__WEIM_WEIM_CS_2 653
+MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19 654
+MX6Q_PAD_DISP0_DAT19__IPU2_DISP0_DAT_19 655
+MX6Q_PAD_DISP0_DAT19__ECSPI2_SCLK 656
+MX6Q_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD 657
+MX6Q_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC 658
+MX6Q_PAD_DISP0_DAT19__GPIO_5_13 659
+MX6Q_PAD_DISP0_DAT19__MMDC_DEBUG_24 660
+MX6Q_PAD_DISP0_DAT19__WEIM_WEIM_CS_3 661
+MX6Q_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20 662
+MX6Q_PAD_DISP0_DAT20__IPU2_DISP0_DAT_20 663
+MX6Q_PAD_DISP0_DAT20__ECSPI1_SCLK 664
+MX6Q_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC 665
+MX6Q_PAD_DISP0_DAT20__SDMA_DBG_EVT_CHN7 666
+MX6Q_PAD_DISP0_DAT20__GPIO_5_14 667
+MX6Q_PAD_DISP0_DAT20__MMDC_DEBUG_25 668
+MX6Q_PAD_DISP0_DAT20__PL301_PER1_HADR28 669
+MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21 670
+MX6Q_PAD_DISP0_DAT21__IPU2_DISP0_DAT_21 671
+MX6Q_PAD_DISP0_DAT21__ECSPI1_MOSI 672
+MX6Q_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD 673
+MX6Q_PAD_DISP0_DAT21__SDMA_DBG_BUS_DEV0 674
+MX6Q_PAD_DISP0_DAT21__GPIO_5_15 675
+MX6Q_PAD_DISP0_DAT21__MMDC_DEBUG_26 676
+MX6Q_PAD_DISP0_DAT21__PL301_PER1_HADR29 677
+MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22 678
+MX6Q_PAD_DISP0_DAT22__IPU2_DISP0_DAT_22 679
+MX6Q_PAD_DISP0_DAT22__ECSPI1_MISO 680
+MX6Q_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS 681
+MX6Q_PAD_DISP0_DAT22__SDMA_DBG_BUS_DEV1 682
+MX6Q_PAD_DISP0_DAT22__GPIO_5_16 683
+MX6Q_PAD_DISP0_DAT22__MMDC_DEBUG_27 684
+MX6Q_PAD_DISP0_DAT22__PL301_PER1_HADR30 685
+MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23 686
+MX6Q_PAD_DISP0_DAT23__IPU2_DISP0_DAT_23 687
+MX6Q_PAD_DISP0_DAT23__ECSPI1_SS0 688
+MX6Q_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD 689
+MX6Q_PAD_DISP0_DAT23__SDMA_DBG_BUS_DEV2 690
+MX6Q_PAD_DISP0_DAT23__GPIO_5_17 691
+MX6Q_PAD_DISP0_DAT23__MMDC_DEBUG_28 692
+MX6Q_PAD_DISP0_DAT23__PL301_PER1_HADR31 693
+MX6Q_PAD_ENET_MDIO__RESERVED_RESERVED 694
+MX6Q_PAD_ENET_MDIO__ENET_MDIO 695
+MX6Q_PAD_ENET_MDIO__ESAI1_SCKR 696
+MX6Q_PAD_ENET_MDIO__SDMA_DEBUG_BUS_DEV3 697
+MX6Q_PAD_ENET_MDIO__ENET_1588_EVT1_OUT 698
+MX6Q_PAD_ENET_MDIO__GPIO_1_22 699
+MX6Q_PAD_ENET_MDIO__SPDIF_PLOCK 700
+MX6Q_PAD_ENET_REF_CLK__RESERVED_RSRVED 701
+MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK 702
+MX6Q_PAD_ENET_REF_CLK__ESAI1_FSR 703
+MX6Q_PAD_ENET_REF_CLK__SDMA_DBGBUS_DEV4 704
+MX6Q_PAD_ENET_REF_CLK__GPIO_1_23 705
+MX6Q_PAD_ENET_REF_CLK__SPDIF_SRCLK 706
+MX6Q_PAD_ENET_REF_CLK__USBPHY1_RX_SQH 707
+MX6Q_PAD_ENET_RX_ER__ENET_RX_ER 708
+MX6Q_PAD_ENET_RX_ER__ESAI1_HCKR 709
+MX6Q_PAD_ENET_RX_ER__SPDIF_IN1 710
+MX6Q_PAD_ENET_RX_ER__ENET_1588_EVT2_OUT 711
+MX6Q_PAD_ENET_RX_ER__GPIO_1_24 712
+MX6Q_PAD_ENET_RX_ER__PHY_TDI 713
+MX6Q_PAD_ENET_RX_ER__USBPHY1_RX_HS_RXD 714
+MX6Q_PAD_ENET_CRS_DV__RESERVED_RSRVED 715
+MX6Q_PAD_ENET_CRS_DV__ENET_RX_EN 716
+MX6Q_PAD_ENET_CRS_DV__ESAI1_SCKT 717
+MX6Q_PAD_ENET_CRS_DV__SPDIF_EXTCLK 718
+MX6Q_PAD_ENET_CRS_DV__GPIO_1_25 719
+MX6Q_PAD_ENET_CRS_DV__PHY_TDO 720
+MX6Q_PAD_ENET_CRS_DV__USBPHY1_RX_FS_RXD 721
+MX6Q_PAD_ENET_RXD1__MLB_MLBSIG 722
+MX6Q_PAD_ENET_RXD1__ENET_RDATA_1 723
+MX6Q_PAD_ENET_RXD1__ESAI1_FST 724
+MX6Q_PAD_ENET_RXD1__ENET_1588_EVT3_OUT 725
+MX6Q_PAD_ENET_RXD1__GPIO_1_26 726
+MX6Q_PAD_ENET_RXD1__PHY_TCK 727
+MX6Q_PAD_ENET_RXD1__USBPHY1_RX_DISCON 728
+MX6Q_PAD_ENET_RXD0__OSC32K_32K_OUT 729
+MX6Q_PAD_ENET_RXD0__ENET_RDATA_0 730
+MX6Q_PAD_ENET_RXD0__ESAI1_HCKT 731
+MX6Q_PAD_ENET_RXD0__SPDIF_OUT1 732
+MX6Q_PAD_ENET_RXD0__GPIO_1_27 733
+MX6Q_PAD_ENET_RXD0__PHY_TMS 734
+MX6Q_PAD_ENET_RXD0__USBPHY1_PLL_CK20DIV 735
+MX6Q_PAD_ENET_TX_EN__RESERVED_RSRVED 736
+MX6Q_PAD_ENET_TX_EN__ENET_TX_EN 737
+MX6Q_PAD_ENET_TX_EN__ESAI1_TX3_RX2 738
+MX6Q_PAD_ENET_TX_EN__GPIO_1_28 739
+MX6Q_PAD_ENET_TX_EN__SATA_PHY_TDI 740
+MX6Q_PAD_ENET_TX_EN__USBPHY2_RX_SQH 741
+MX6Q_PAD_ENET_TXD1__MLB_MLBCLK 742
+MX6Q_PAD_ENET_TXD1__ENET_TDATA_1 743
+MX6Q_PAD_ENET_TXD1__ESAI1_TX2_RX3 744
+MX6Q_PAD_ENET_TXD1__ENET_1588_EVENT0_IN 745
+MX6Q_PAD_ENET_TXD1__GPIO_1_29 746
+MX6Q_PAD_ENET_TXD1__SATA_PHY_TDO 747
+MX6Q_PAD_ENET_TXD1__USBPHY2_RX_HS_RXD 748
+MX6Q_PAD_ENET_TXD0__RESERVED_RSRVED 749
+MX6Q_PAD_ENET_TXD0__ENET_TDATA_0 750
+MX6Q_PAD_ENET_TXD0__ESAI1_TX4_RX1 751
+MX6Q_PAD_ENET_TXD0__GPIO_1_30 752
+MX6Q_PAD_ENET_TXD0__SATA_PHY_TCK 753
+MX6Q_PAD_ENET_TXD0__USBPHY2_RX_FS_RXD 754
+MX6Q_PAD_ENET_MDC__MLB_MLBDAT 755
+MX6Q_PAD_ENET_MDC__ENET_MDC 756
+MX6Q_PAD_ENET_MDC__ESAI1_TX5_RX0 757
+MX6Q_PAD_ENET_MDC__ENET_1588_EVENT1_IN 758
+MX6Q_PAD_ENET_MDC__GPIO_1_31 759
+MX6Q_PAD_ENET_MDC__SATA_PHY_TMS 760
+MX6Q_PAD_ENET_MDC__USBPHY2_RX_DISCON 761
+MX6Q_PAD_DRAM_D40__MMDC_DRAM_D_40 762
+MX6Q_PAD_DRAM_D41__MMDC_DRAM_D_41 763
+MX6Q_PAD_DRAM_D42__MMDC_DRAM_D_42 764
+MX6Q_PAD_DRAM_D43__MMDC_DRAM_D_43 765
+MX6Q_PAD_DRAM_D44__MMDC_DRAM_D_44 766
+MX6Q_PAD_DRAM_D45__MMDC_DRAM_D_45 767
+MX6Q_PAD_DRAM_D46__MMDC_DRAM_D_46 768
+MX6Q_PAD_DRAM_D47__MMDC_DRAM_D_47 769
+MX6Q_PAD_DRAM_SDQS5__MMDC_DRAM_SDQS_5 770
+MX6Q_PAD_DRAM_DQM5__MMDC_DRAM_DQM_5 771
+MX6Q_PAD_DRAM_D32__MMDC_DRAM_D_32 772
+MX6Q_PAD_DRAM_D33__MMDC_DRAM_D_33 773
+MX6Q_PAD_DRAM_D34__MMDC_DRAM_D_34 774
+MX6Q_PAD_DRAM_D35__MMDC_DRAM_D_35 775
+MX6Q_PAD_DRAM_D36__MMDC_DRAM_D_36 776
+MX6Q_PAD_DRAM_D37__MMDC_DRAM_D_37 777
+MX6Q_PAD_DRAM_D38__MMDC_DRAM_D_38 778
+MX6Q_PAD_DRAM_D39__MMDC_DRAM_D_39 779
+MX6Q_PAD_DRAM_DQM4__MMDC_DRAM_DQM_4 780
+MX6Q_PAD_DRAM_SDQS4__MMDC_DRAM_SDQS_4 781
+MX6Q_PAD_DRAM_D24__MMDC_DRAM_D_24 782
+MX6Q_PAD_DRAM_D25__MMDC_DRAM_D_25 783
+MX6Q_PAD_DRAM_D26__MMDC_DRAM_D_26 784
+MX6Q_PAD_DRAM_D27__MMDC_DRAM_D_27 785
+MX6Q_PAD_DRAM_D28__MMDC_DRAM_D_28 786
+MX6Q_PAD_DRAM_D29__MMDC_DRAM_D_29 787
+MX6Q_PAD_DRAM_SDQS3__MMDC_DRAM_SDQS_3 788
+MX6Q_PAD_DRAM_D30__MMDC_DRAM_D_30 789
+MX6Q_PAD_DRAM_D31__MMDC_DRAM_D_31 790
+MX6Q_PAD_DRAM_DQM3__MMDC_DRAM_DQM_3 791
+MX6Q_PAD_DRAM_D16__MMDC_DRAM_D_16 792
+MX6Q_PAD_DRAM_D17__MMDC_DRAM_D_17 793
+MX6Q_PAD_DRAM_D18__MMDC_DRAM_D_18 794
+MX6Q_PAD_DRAM_D19__MMDC_DRAM_D_19 795
+MX6Q_PAD_DRAM_D20__MMDC_DRAM_D_20 796
+MX6Q_PAD_DRAM_D21__MMDC_DRAM_D_21 797
+MX6Q_PAD_DRAM_D22__MMDC_DRAM_D_22 798
+MX6Q_PAD_DRAM_SDQS2__MMDC_DRAM_SDQS_2 799
+MX6Q_PAD_DRAM_D23__MMDC_DRAM_D_23 800
+MX6Q_PAD_DRAM_DQM2__MMDC_DRAM_DQM_2 801
+MX6Q_PAD_DRAM_A0__MMDC_DRAM_A_0 802
+MX6Q_PAD_DRAM_A1__MMDC_DRAM_A_1 803
+MX6Q_PAD_DRAM_A2__MMDC_DRAM_A_2 804
+MX6Q_PAD_DRAM_A3__MMDC_DRAM_A_3 805
+MX6Q_PAD_DRAM_A4__MMDC_DRAM_A_4 806
+MX6Q_PAD_DRAM_A5__MMDC_DRAM_A_5 807
+MX6Q_PAD_DRAM_A6__MMDC_DRAM_A_6 808
+MX6Q_PAD_DRAM_A7__MMDC_DRAM_A_7 809
+MX6Q_PAD_DRAM_A8__MMDC_DRAM_A_8 810
+MX6Q_PAD_DRAM_A9__MMDC_DRAM_A_9 811
+MX6Q_PAD_DRAM_A10__MMDC_DRAM_A_10 812
+MX6Q_PAD_DRAM_A11__MMDC_DRAM_A_11 813
+MX6Q_PAD_DRAM_A12__MMDC_DRAM_A_12 814
+MX6Q_PAD_DRAM_A13__MMDC_DRAM_A_13 815
+MX6Q_PAD_DRAM_A14__MMDC_DRAM_A_14 816
+MX6Q_PAD_DRAM_A15__MMDC_DRAM_A_15 817
+MX6Q_PAD_DRAM_CAS__MMDC_DRAM_CAS 818
+MX6Q_PAD_DRAM_CS0__MMDC_DRAM_CS_0 819
+MX6Q_PAD_DRAM_CS1__MMDC_DRAM_CS_1 820
+MX6Q_PAD_DRAM_RAS__MMDC_DRAM_RAS 821
+MX6Q_PAD_DRAM_RESET__MMDC_DRAM_RESET 822
+MX6Q_PAD_DRAM_SDBA0__MMDC_DRAM_SDBA_0 823
+MX6Q_PAD_DRAM_SDBA1__MMDC_DRAM_SDBA_1 824
+MX6Q_PAD_DRAM_SDCLK_0__MMDC_DRAM_SDCLK0 825
+MX6Q_PAD_DRAM_SDBA2__MMDC_DRAM_SDBA_2 826
+MX6Q_PAD_DRAM_SDCKE0__MMDC_DRAM_SDCKE_0 827
+MX6Q_PAD_DRAM_SDCLK_1__MMDC_DRAM_SDCLK1 828
+MX6Q_PAD_DRAM_SDCKE1__MMDC_DRAM_SDCKE_1 829
+MX6Q_PAD_DRAM_SDODT0__MMDC_DRAM_ODT_0 830
+MX6Q_PAD_DRAM_SDODT1__MMDC_DRAM_ODT_1 831
+MX6Q_PAD_DRAM_SDWE__MMDC_DRAM_SDWE 832
+MX6Q_PAD_DRAM_D0__MMDC_DRAM_D_0 833
+MX6Q_PAD_DRAM_D1__MMDC_DRAM_D_1 834
+MX6Q_PAD_DRAM_D2__MMDC_DRAM_D_2 835
+MX6Q_PAD_DRAM_D3__MMDC_DRAM_D_3 836
+MX6Q_PAD_DRAM_D4__MMDC_DRAM_D_4 837
+MX6Q_PAD_DRAM_D5__MMDC_DRAM_D_5 838
+MX6Q_PAD_DRAM_SDQS0__MMDC_DRAM_SDQS_0 839
+MX6Q_PAD_DRAM_D6__MMDC_DRAM_D_6 840
+MX6Q_PAD_DRAM_D7__MMDC_DRAM_D_7 841
+MX6Q_PAD_DRAM_DQM0__MMDC_DRAM_DQM_0 842
+MX6Q_PAD_DRAM_D8__MMDC_DRAM_D_8 843
+MX6Q_PAD_DRAM_D9__MMDC_DRAM_D_9 844
+MX6Q_PAD_DRAM_D10__MMDC_DRAM_D_10 845
+MX6Q_PAD_DRAM_D11__MMDC_DRAM_D_11 846
+MX6Q_PAD_DRAM_D12__MMDC_DRAM_D_12 847
+MX6Q_PAD_DRAM_D13__MMDC_DRAM_D_13 848
+MX6Q_PAD_DRAM_D14__MMDC_DRAM_D_14 849
+MX6Q_PAD_DRAM_SDQS1__MMDC_DRAM_SDQS_1 850
+MX6Q_PAD_DRAM_D15__MMDC_DRAM_D_15 851
+MX6Q_PAD_DRAM_DQM1__MMDC_DRAM_DQM_1 852
+MX6Q_PAD_DRAM_D48__MMDC_DRAM_D_48 853
+MX6Q_PAD_DRAM_D49__MMDC_DRAM_D_49 854
+MX6Q_PAD_DRAM_D50__MMDC_DRAM_D_50 855
+MX6Q_PAD_DRAM_D51__MMDC_DRAM_D_51 856
+MX6Q_PAD_DRAM_D52__MMDC_DRAM_D_52 857
+MX6Q_PAD_DRAM_D53__MMDC_DRAM_D_53 858
+MX6Q_PAD_DRAM_D54__MMDC_DRAM_D_54 859
+MX6Q_PAD_DRAM_D55__MMDC_DRAM_D_55 860
+MX6Q_PAD_DRAM_SDQS6__MMDC_DRAM_SDQS_6 861
+MX6Q_PAD_DRAM_DQM6__MMDC_DRAM_DQM_6 862
+MX6Q_PAD_DRAM_D56__MMDC_DRAM_D_56 863
+MX6Q_PAD_DRAM_SDQS7__MMDC_DRAM_SDQS_7 864
+MX6Q_PAD_DRAM_D57__MMDC_DRAM_D_57 865
+MX6Q_PAD_DRAM_D58__MMDC_DRAM_D_58 866
+MX6Q_PAD_DRAM_D59__MMDC_DRAM_D_59 867
+MX6Q_PAD_DRAM_D60__MMDC_DRAM_D_60 868
+MX6Q_PAD_DRAM_DQM7__MMDC_DRAM_DQM_7 869
+MX6Q_PAD_DRAM_D61__MMDC_DRAM_D_61 870
+MX6Q_PAD_DRAM_D62__MMDC_DRAM_D_62 871
+MX6Q_PAD_DRAM_D63__MMDC_DRAM_D_63 872
+MX6Q_PAD_KEY_COL0__ECSPI1_SCLK 873
+MX6Q_PAD_KEY_COL0__ENET_RDATA_3 874
+MX6Q_PAD_KEY_COL0__AUDMUX_AUD5_TXC 875
+MX6Q_PAD_KEY_COL0__KPP_COL_0 876
+MX6Q_PAD_KEY_COL0__UART4_TXD 877
+MX6Q_PAD_KEY_COL0__GPIO_4_6 878
+MX6Q_PAD_KEY_COL0__DCIC1_DCIC_OUT 879
+MX6Q_PAD_KEY_COL0__SRC_ANY_PU_RST 880
+MX6Q_PAD_KEY_ROW0__ECSPI1_MOSI 881
+MX6Q_PAD_KEY_ROW0__ENET_TDATA_3 882
+MX6Q_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 883
+MX6Q_PAD_KEY_ROW0__KPP_ROW_0 884
+MX6Q_PAD_KEY_ROW0__UART4_RXD 885
+MX6Q_PAD_KEY_ROW0__GPIO_4_7 886
+MX6Q_PAD_KEY_ROW0__DCIC2_DCIC_OUT 887
+MX6Q_PAD_KEY_ROW0__PL301_PER1_HADR_0 888
+MX6Q_PAD_KEY_COL1__ECSPI1_MISO 889
+MX6Q_PAD_KEY_COL1__ENET_MDIO 890
+MX6Q_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 891
+MX6Q_PAD_KEY_COL1__KPP_COL_1 892
+MX6Q_PAD_KEY_COL1__UART5_TXD 893
+MX6Q_PAD_KEY_COL1__GPIO_4_8 894
+MX6Q_PAD_KEY_COL1__USDHC1_VSELECT 895
+MX6Q_PAD_KEY_COL1__PL301MX_PER1_HADR_1 896
+MX6Q_PAD_KEY_ROW1__ECSPI1_SS0 897
+MX6Q_PAD_KEY_ROW1__ENET_COL 898
+MX6Q_PAD_KEY_ROW1__AUDMUX_AUD5_RXD 899
+MX6Q_PAD_KEY_ROW1__KPP_ROW_1 900
+MX6Q_PAD_KEY_ROW1__UART5_RXD 901
+MX6Q_PAD_KEY_ROW1__GPIO_4_9 902
+MX6Q_PAD_KEY_ROW1__USDHC2_VSELECT 903
+MX6Q_PAD_KEY_ROW1__PL301_PER1_HADDR_2 904
+MX6Q_PAD_KEY_COL2__ECSPI1_SS1 905
+MX6Q_PAD_KEY_COL2__ENET_RDATA_2 906
+MX6Q_PAD_KEY_COL2__CAN1_TXCAN 907
+MX6Q_PAD_KEY_COL2__KPP_COL_2 908
+MX6Q_PAD_KEY_COL2__ENET_MDC 909
+MX6Q_PAD_KEY_COL2__GPIO_4_10 910
+MX6Q_PAD_KEY_COL2__USBOH3_H1_PWRCTL_WKP 911
+MX6Q_PAD_KEY_COL2__PL301_PER1_HADDR_3 912
+MX6Q_PAD_KEY_ROW2__ECSPI1_SS2 913
+MX6Q_PAD_KEY_ROW2__ENET_TDATA_2 914
+MX6Q_PAD_KEY_ROW2__CAN1_RXCAN 915
+MX6Q_PAD_KEY_ROW2__KPP_ROW_2 916
+MX6Q_PAD_KEY_ROW2__USDHC2_VSELECT 917
+MX6Q_PAD_KEY_ROW2__GPIO_4_11 918
+MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 919
+MX6Q_PAD_KEY_ROW2__PL301_PER1_HADR_4 920
+MX6Q_PAD_KEY_COL3__ECSPI1_SS3 921
+MX6Q_PAD_KEY_COL3__ENET_CRS 922
+MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL 923
+MX6Q_PAD_KEY_COL3__KPP_COL_3 924
+MX6Q_PAD_KEY_COL3__I2C2_SCL 925
+MX6Q_PAD_KEY_COL3__GPIO_4_12 926
+MX6Q_PAD_KEY_COL3__SPDIF_IN1 927
+MX6Q_PAD_KEY_COL3__PL301_PER1_HADR_5 928
+MX6Q_PAD_KEY_ROW3__OSC32K_32K_OUT 929
+MX6Q_PAD_KEY_ROW3__ASRC_ASRC_EXT_CLK 930
+MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 931
+MX6Q_PAD_KEY_ROW3__KPP_ROW_3 932
+MX6Q_PAD_KEY_ROW3__I2C2_SDA 933
+MX6Q_PAD_KEY_ROW3__GPIO_4_13 934
+MX6Q_PAD_KEY_ROW3__USDHC1_VSELECT 935
+MX6Q_PAD_KEY_ROW3__PL301_PER1_HADR_6 936
+MX6Q_PAD_KEY_COL4__CAN2_TXCAN 937
+MX6Q_PAD_KEY_COL4__IPU1_SISG_4 938
+MX6Q_PAD_KEY_COL4__USBOH3_USBOTG_OC 939
+MX6Q_PAD_KEY_COL4__KPP_COL_4 940
+MX6Q_PAD_KEY_COL4__UART5_RTS 941
+MX6Q_PAD_KEY_COL4__GPIO_4_14 942
+MX6Q_PAD_KEY_COL4__MMDC_DEBUG_49 943
+MX6Q_PAD_KEY_COL4__PL301_PER1_HADDR_7 944
+MX6Q_PAD_KEY_ROW4__CAN2_RXCAN 945
+MX6Q_PAD_KEY_ROW4__IPU1_SISG_5 946
+MX6Q_PAD_KEY_ROW4__USBOH3_USBOTG_PWR 947
+MX6Q_PAD_KEY_ROW4__KPP_ROW_4 948
+MX6Q_PAD_KEY_ROW4__UART5_CTS 949
+MX6Q_PAD_KEY_ROW4__GPIO_4_15 950
+MX6Q_PAD_KEY_ROW4__MMDC_DEBUG_50 951
+MX6Q_PAD_KEY_ROW4__PL301_PER1_HADR_8 952
+MX6Q_PAD_GPIO_0__CCM_CLKO 953
+MX6Q_PAD_GPIO_0__KPP_COL_5 954
+MX6Q_PAD_GPIO_0__ASRC_ASRC_EXT_CLK 955
+MX6Q_PAD_GPIO_0__EPIT1_EPITO 956
+MX6Q_PAD_GPIO_0__GPIO_1_0 957
+MX6Q_PAD_GPIO_0__USBOH3_USBH1_PWR 958
+MX6Q_PAD_GPIO_0__SNVS_HP_WRAP_SNVS_VIO5 959
+MX6Q_PAD_GPIO_1__ESAI1_SCKR 960
+MX6Q_PAD_GPIO_1__WDOG2_WDOG_B 961
+MX6Q_PAD_GPIO_1__KPP_ROW_5 962
+MX6Q_PAD_GPIO_1__PWM2_PWMO 963
+MX6Q_PAD_GPIO_1__GPIO_1_1 964
+MX6Q_PAD_GPIO_1__USDHC1_CD 965
+MX6Q_PAD_GPIO_1__SRC_TESTER_ACK 966
+MX6Q_PAD_GPIO_9__ESAI1_FSR 967
+MX6Q_PAD_GPIO_9__WDOG1_WDOG_B 968
+MX6Q_PAD_GPIO_9__KPP_COL_6 969
+MX6Q_PAD_GPIO_9__CCM_REF_EN_B 970
+MX6Q_PAD_GPIO_9__PWM1_PWMO 971
+MX6Q_PAD_GPIO_9__GPIO_1_9 972
+MX6Q_PAD_GPIO_9__USDHC1_WP 973
+MX6Q_PAD_GPIO_9__SRC_EARLY_RST 974
+MX6Q_PAD_GPIO_3__ESAI1_HCKR 975
+MX6Q_PAD_GPIO_3__OBSERVE_MUX_INT_OUT0 976
+MX6Q_PAD_GPIO_3__I2C3_SCL 977
+MX6Q_PAD_GPIO_3__ANATOP_24M_OUT 978
+MX6Q_PAD_GPIO_3__CCM_CLKO2 979
+MX6Q_PAD_GPIO_3__GPIO_1_3 980
+MX6Q_PAD_GPIO_3__USBOH3_USBH1_OC 981
+MX6Q_PAD_GPIO_3__MLB_MLBCLK 982
+MX6Q_PAD_GPIO_6__ESAI1_SCKT 983
+MX6Q_PAD_GPIO_6__OBSERVE_MUX_INT_OUT1 984
+MX6Q_PAD_GPIO_6__I2C3_SDA 985
+MX6Q_PAD_GPIO_6__CCM_CCM_OUT_0 986
+MX6Q_PAD_GPIO_6__CSU_CSU_INT_DEB 987
+MX6Q_PAD_GPIO_6__GPIO_1_6 988
+MX6Q_PAD_GPIO_6__USDHC2_LCTL 989
+MX6Q_PAD_GPIO_6__MLB_MLBSIG 990
+MX6Q_PAD_GPIO_2__ESAI1_FST 991
+MX6Q_PAD_GPIO_2__OBSERVE_MUX_INT_OUT2 992
+MX6Q_PAD_GPIO_2__KPP_ROW_6 993
+MX6Q_PAD_GPIO_2__CCM_CCM_OUT_1 994
+MX6Q_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 995
+MX6Q_PAD_GPIO_2__GPIO_1_2 996
+MX6Q_PAD_GPIO_2__USDHC2_WP 997
+MX6Q_PAD_GPIO_2__MLB_MLBDAT 998
+MX6Q_PAD_GPIO_4__ESAI1_HCKT 999
+MX6Q_PAD_GPIO_4__OBSERVE_MUX_INT_OUT3 1000
+MX6Q_PAD_GPIO_4__KPP_COL_7 1001
+MX6Q_PAD_GPIO_4__CCM_CCM_OUT_2 1002
+MX6Q_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 1003
+MX6Q_PAD_GPIO_4__GPIO_1_4 1004
+MX6Q_PAD_GPIO_4__USDHC2_CD 1005
+MX6Q_PAD_GPIO_4__OCOTP_CRL_WRAR_FUSE_LA 1006
+MX6Q_PAD_GPIO_5__ESAI1_TX2_RX3 1007
+MX6Q_PAD_GPIO_5__OBSERVE_MUX_INT_OUT4 1008
+MX6Q_PAD_GPIO_5__KPP_ROW_7 1009
+MX6Q_PAD_GPIO_5__CCM_CLKO 1010
+MX6Q_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 1011
+MX6Q_PAD_GPIO_5__GPIO_1_5 1012
+MX6Q_PAD_GPIO_5__I2C3_SCL 1013
+MX6Q_PAD_GPIO_5__CHEETAH_EVENTI 1014
+MX6Q_PAD_GPIO_7__ESAI1_TX4_RX1 1015
+MX6Q_PAD_GPIO_7__ECSPI5_RDY 1016
+MX6Q_PAD_GPIO_7__EPIT1_EPITO 1017
+MX6Q_PAD_GPIO_7__CAN1_TXCAN 1018
+MX6Q_PAD_GPIO_7__UART2_TXD 1019
+MX6Q_PAD_GPIO_7__GPIO_1_7 1020
+MX6Q_PAD_GPIO_7__SPDIF_PLOCK 1021
+MX6Q_PAD_GPIO_7__USBOH3_OTGUSB_HST_MODE 1022
+MX6Q_PAD_GPIO_8__ESAI1_TX5_RX0 1023
+MX6Q_PAD_GPIO_8__ANATOP_ANATOP_32K_OUT 1024
+MX6Q_PAD_GPIO_8__EPIT2_EPITO 1025
+MX6Q_PAD_GPIO_8__CAN1_RXCAN 1026
+MX6Q_PAD_GPIO_8__UART2_RXD 1027
+MX6Q_PAD_GPIO_8__GPIO_1_8 1028
+MX6Q_PAD_GPIO_8__SPDIF_SRCLK 1029
+MX6Q_PAD_GPIO_8__USBOH3_OTG_PWRCTL_WAK 1030
+MX6Q_PAD_GPIO_16__ESAI1_TX3_RX2 1031
+MX6Q_PAD_GPIO_16__ENET_1588_EVENT2_IN 1032
+MX6Q_PAD_GPIO_16__ENET_ETHERNET_REF_OUT 1033
+MX6Q_PAD_GPIO_16__USDHC1_LCTL 1034
+MX6Q_PAD_GPIO_16__SPDIF_IN1 1035
+MX6Q_PAD_GPIO_16__GPIO_7_11 1036
+MX6Q_PAD_GPIO_16__I2C3_SDA 1037
+MX6Q_PAD_GPIO_16__SJC_DE_B 1038
+MX6Q_PAD_GPIO_17__ESAI1_TX0 1039
+MX6Q_PAD_GPIO_17__ENET_1588_EVENT3_IN 1040
+MX6Q_PAD_GPIO_17__CCM_PMIC_RDY 1041
+MX6Q_PAD_GPIO_17__SDMA_SDMA_EXT_EVENT_0 1042
+MX6Q_PAD_GPIO_17__SPDIF_OUT1 1043
+MX6Q_PAD_GPIO_17__GPIO_7_12 1044
+MX6Q_PAD_GPIO_17__SJC_JTAG_ACT 1045
+MX6Q_PAD_GPIO_18__ESAI1_TX1 1046
+MX6Q_PAD_GPIO_18__ENET_RX_CLK 1047
+MX6Q_PAD_GPIO_18__USDHC3_VSELECT 1048
+MX6Q_PAD_GPIO_18__SDMA_SDMA_EXT_EVENT_1 1049
+MX6Q_PAD_GPIO_18__ASRC_ASRC_EXT_CLK 1050
+MX6Q_PAD_GPIO_18__GPIO_7_13 1051
+MX6Q_PAD_GPIO_18__SNVS_HP_WRA_SNVS_VIO5 1052
+MX6Q_PAD_GPIO_18__SRC_SYSTEM_RST 1053
+MX6Q_PAD_GPIO_19__KPP_COL_5 1054
+MX6Q_PAD_GPIO_19__ENET_1588_EVENT0_OUT 1055
+MX6Q_PAD_GPIO_19__SPDIF_OUT1 1056
+MX6Q_PAD_GPIO_19__CCM_CLKO 1057
+MX6Q_PAD_GPIO_19__ECSPI1_RDY 1058
+MX6Q_PAD_GPIO_19__GPIO_4_5 1059
+MX6Q_PAD_GPIO_19__ENET_TX_ER 1060
+MX6Q_PAD_GPIO_19__SRC_INT_BOOT 1061
+MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 1062
+MX6Q_PAD_CSI0_PIXCLK__PCIE_CTRL_MUX_12 1063
+MX6Q_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 1064
+MX6Q_PAD_CSI0_PIXCLK__GPIO_5_18 1065
+MX6Q_PAD_CSI0_PIXCLK___MMDC_DEBUG_29 1066
+MX6Q_PAD_CSI0_PIXCLK__CHEETAH_EVENTO 1067
+MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 1068
+MX6Q_PAD_CSI0_MCLK__PCIE_CTRL_MUX_13 1069
+MX6Q_PAD_CSI0_MCLK__CCM_CLKO 1070
+MX6Q_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 1071
+MX6Q_PAD_CSI0_MCLK__GPIO_5_19 1072
+MX6Q_PAD_CSI0_MCLK__MMDC_MMDC_DEBUG_30 1073
+MX6Q_PAD_CSI0_MCLK__CHEETAH_TRCTL 1074
+MX6Q_PAD_CSI0_DATA_EN__IPU1_CSI0_DA_EN 1075
+MX6Q_PAD_CSI0_DATA_EN__WEIM_WEIM_D_0 1076
+MX6Q_PAD_CSI0_DATA_EN__PCIE_CTRL_MUX_14 1077
+MX6Q_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 1078
+MX6Q_PAD_CSI0_DATA_EN__GPIO_5_20 1079
+MX6Q_PAD_CSI0_DATA_EN__MMDC_DEBUG_31 1080
+MX6Q_PAD_CSI0_DATA_EN__CHEETAH_TRCLK 1081
+MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 1082
+MX6Q_PAD_CSI0_VSYNC__WEIM_WEIM_D_1 1083
+MX6Q_PAD_CSI0_VSYNC__PCIE_CTRL_MUX_15 1084
+MX6Q_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 1085
+MX6Q_PAD_CSI0_VSYNC__GPIO_5_21 1086
+MX6Q_PAD_CSI0_VSYNC__MMDC_DEBUG_32 1087
+MX6Q_PAD_CSI0_VSYNC__CHEETAH_TRACE_0 1088
+MX6Q_PAD_CSI0_DAT4__IPU1_CSI0_D_4 1089
+MX6Q_PAD_CSI0_DAT4__WEIM_WEIM_D_2 1090
+MX6Q_PAD_CSI0_DAT4__ECSPI1_SCLK 1091
+MX6Q_PAD_CSI0_DAT4__KPP_COL_5 1092
+MX6Q_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC 1093
+MX6Q_PAD_CSI0_DAT4__GPIO_5_22 1094
+MX6Q_PAD_CSI0_DAT4__MMDC_DEBUG_43 1095
+MX6Q_PAD_CSI0_DAT4__CHEETAH_TRACE_1 1096
+MX6Q_PAD_CSI0_DAT5__IPU1_CSI0_D_5 1097
+MX6Q_PAD_CSI0_DAT5__WEIM_WEIM_D_3 1098
+MX6Q_PAD_CSI0_DAT5__ECSPI1_MOSI 1099
+MX6Q_PAD_CSI0_DAT5__KPP_ROW_5 1100
+MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD 1101
+MX6Q_PAD_CSI0_DAT5__GPIO_5_23 1102
+MX6Q_PAD_CSI0_DAT5__MMDC_MMDC_DEBUG_44 1103
+MX6Q_PAD_CSI0_DAT5__CHEETAH_TRACE_2 1104
+MX6Q_PAD_CSI0_DAT6__IPU1_CSI0_D_6 1105
+MX6Q_PAD_CSI0_DAT6__WEIM_WEIM_D_4 1106
+MX6Q_PAD_CSI0_DAT6__ECSPI1_MISO 1107
+MX6Q_PAD_CSI0_DAT6__KPP_COL_6 1108
+MX6Q_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS 1109
+MX6Q_PAD_CSI0_DAT6__GPIO_5_24 1110
+MX6Q_PAD_CSI0_DAT6__MMDC_MMDC_DEBUG_45 1111
+MX6Q_PAD_CSI0_DAT6__CHEETAH_TRACE_3 1112
+MX6Q_PAD_CSI0_DAT7__IPU1_CSI0_D_7 1113
+MX6Q_PAD_CSI0_DAT7__WEIM_WEIM_D_5 1114
+MX6Q_PAD_CSI0_DAT7__ECSPI1_SS0 1115
+MX6Q_PAD_CSI0_DAT7__KPP_ROW_6 1116
+MX6Q_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD 1117
+MX6Q_PAD_CSI0_DAT7__GPIO_5_25 1118
+MX6Q_PAD_CSI0_DAT7__MMDC_MMDC_DEBUG_46 1119
+MX6Q_PAD_CSI0_DAT7__CHEETAH_TRACE_4 1120
+MX6Q_PAD_CSI0_DAT8__IPU1_CSI0_D_8 1121
+MX6Q_PAD_CSI0_DAT8__WEIM_WEIM_D_6 1122
+MX6Q_PAD_CSI0_DAT8__ECSPI2_SCLK 1123
+MX6Q_PAD_CSI0_DAT8__KPP_COL_7 1124
+MX6Q_PAD_CSI0_DAT8__I2C1_SDA 1125
+MX6Q_PAD_CSI0_DAT8__GPIO_5_26 1126
+MX6Q_PAD_CSI0_DAT8__MMDC_MMDC_DEBUG_47 1127
+MX6Q_PAD_CSI0_DAT8__CHEETAH_TRACE_5 1128
+MX6Q_PAD_CSI0_DAT9__IPU1_CSI0_D_9 1129
+MX6Q_PAD_CSI0_DAT9__WEIM_WEIM_D_7 1130
+MX6Q_PAD_CSI0_DAT9__ECSPI2_MOSI 1131
+MX6Q_PAD_CSI0_DAT9__KPP_ROW_7 1132
+MX6Q_PAD_CSI0_DAT9__I2C1_SCL 1133
+MX6Q_PAD_CSI0_DAT9__GPIO_5_27 1134
+MX6Q_PAD_CSI0_DAT9__MMDC_MMDC_DEBUG_48 1135
+MX6Q_PAD_CSI0_DAT9__CHEETAH_TRACE_6 1136
+MX6Q_PAD_CSI0_DAT10__IPU1_CSI0_D_10 1137
+MX6Q_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC 1138
+MX6Q_PAD_CSI0_DAT10__ECSPI2_MISO 1139
+MX6Q_PAD_CSI0_DAT10__UART1_TXD 1140
+MX6Q_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 1141
+MX6Q_PAD_CSI0_DAT10__GPIO_5_28 1142
+MX6Q_PAD_CSI0_DAT10__MMDC_MMDC_DEBUG_33 1143
+MX6Q_PAD_CSI0_DAT10__CHEETAH_TRACE_7 1144
+MX6Q_PAD_CSI0_DAT11__IPU1_CSI0_D_11 1145
+MX6Q_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS 1146
+MX6Q_PAD_CSI0_DAT11__ECSPI2_SS0 1147
+MX6Q_PAD_CSI0_DAT11__UART1_RXD 1148
+MX6Q_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 1149
+MX6Q_PAD_CSI0_DAT11__GPIO_5_29 1150
+MX6Q_PAD_CSI0_DAT11__MMDC_MMDC_DEBUG_34 1151
+MX6Q_PAD_CSI0_DAT11__CHEETAH_TRACE_8 1152
+MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12 1153
+MX6Q_PAD_CSI0_DAT12__WEIM_WEIM_D_8 1154
+MX6Q_PAD_CSI0_DAT12__PCIE_CTRL_MUX_16 1155
+MX6Q_PAD_CSI0_DAT12__UART4_TXD 1156
+MX6Q_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 1157
+MX6Q_PAD_CSI0_DAT12__GPIO_5_30 1158
+MX6Q_PAD_CSI0_DAT12__MMDC_MMDC_DEBUG_35 1159
+MX6Q_PAD_CSI0_DAT12__CHEETAH_TRACE_9 1160
+MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13 1161
+MX6Q_PAD_CSI0_DAT13__WEIM_WEIM_D_9 1162
+MX6Q_PAD_CSI0_DAT13__PCIE_CTRL_MUX_17 1163
+MX6Q_PAD_CSI0_DAT13__UART4_RXD 1164
+MX6Q_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 1165
+MX6Q_PAD_CSI0_DAT13__GPIO_5_31 1166
+MX6Q_PAD_CSI0_DAT13__MMDC_MMDC_DEBUG_36 1167
+MX6Q_PAD_CSI0_DAT13__CHEETAH_TRACE_10 1168
+MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14 1169
+MX6Q_PAD_CSI0_DAT14__WEIM_WEIM_D_10 1170
+MX6Q_PAD_CSI0_DAT14__PCIE_CTRL_MUX_18 1171
+MX6Q_PAD_CSI0_DAT14__UART5_TXD 1172
+MX6Q_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 1173
+MX6Q_PAD_CSI0_DAT14__GPIO_6_0 1174
+MX6Q_PAD_CSI0_DAT14__MMDC_MMDC_DEBUG_37 1175
+MX6Q_PAD_CSI0_DAT14__CHEETAH_TRACE_11 1176
+MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15 1177
+MX6Q_PAD_CSI0_DAT15__WEIM_WEIM_D_11 1178
+MX6Q_PAD_CSI0_DAT15__PCIE_CTRL_MUX_19 1179
+MX6Q_PAD_CSI0_DAT15__UART5_RXD 1180
+MX6Q_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 1181
+MX6Q_PAD_CSI0_DAT15__GPIO_6_1 1182
+MX6Q_PAD_CSI0_DAT15__MMDC_MMDC_DEBUG_38 1183
+MX6Q_PAD_CSI0_DAT15__CHEETAH_TRACE_12 1184
+MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16 1185
+MX6Q_PAD_CSI0_DAT16__WEIM_WEIM_D_12 1186
+MX6Q_PAD_CSI0_DAT16__PCIE_CTRL_MUX_20 1187
+MX6Q_PAD_CSI0_DAT16__UART4_RTS 1188
+MX6Q_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 1189
+MX6Q_PAD_CSI0_DAT16__GPIO_6_2 1190
+MX6Q_PAD_CSI0_DAT16__MMDC_MMDC_DEBUG_39 1191
+MX6Q_PAD_CSI0_DAT16__CHEETAH_TRACE_13 1192
+MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17 1193
+MX6Q_PAD_CSI0_DAT17__WEIM_WEIM_D_13 1194
+MX6Q_PAD_CSI0_DAT17__PCIE_CTRL_MUX_21 1195
+MX6Q_PAD_CSI0_DAT17__UART4_CTS 1196
+MX6Q_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 1197
+MX6Q_PAD_CSI0_DAT17__GPIO_6_3 1198
+MX6Q_PAD_CSI0_DAT17__MMDC_MMDC_DEBUG_40 1199
+MX6Q_PAD_CSI0_DAT17__CHEETAH_TRACE_14 1200
+MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18 1201
+MX6Q_PAD_CSI0_DAT18__WEIM_WEIM_D_14 1202
+MX6Q_PAD_CSI0_DAT18__PCIE_CTRL_MUX_22 1203
+MX6Q_PAD_CSI0_DAT18__UART5_RTS 1204
+MX6Q_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 1205
+MX6Q_PAD_CSI0_DAT18__GPIO_6_4 1206
+MX6Q_PAD_CSI0_DAT18__MMDC_MMDC_DEBUG_41 1207
+MX6Q_PAD_CSI0_DAT18__CHEETAH_TRACE_15 1208
+MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19 1209
+MX6Q_PAD_CSI0_DAT19__WEIM_WEIM_D_15 1210
+MX6Q_PAD_CSI0_DAT19__PCIE_CTRL_MUX_23 1211
+MX6Q_PAD_CSI0_DAT19__UART5_CTS 1212
+MX6Q_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 1213
+MX6Q_PAD_CSI0_DAT19__GPIO_6_5 1214
+MX6Q_PAD_CSI0_DAT19__MMDC_MMDC_DEBUG_42 1215
+MX6Q_PAD_CSI0_DAT19__ANATOP_TESTO_9 1216
+MX6Q_PAD_JTAG_TMS__SJC_TMS 1217
+MX6Q_PAD_JTAG_MOD__SJC_MOD 1218
+MX6Q_PAD_JTAG_TRSTB__SJC_TRSTB 1219
+MX6Q_PAD_JTAG_TDI__SJC_TDI 1220
+MX6Q_PAD_JTAG_TCK__SJC_TCK 1221
+MX6Q_PAD_JTAG_TDO__SJC_TDO 1222
+MX6Q_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 1223
+MX6Q_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 1224
+MX6Q_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK 1225
+MX6Q_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 1226
+MX6Q_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 1227
+MX6Q_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 1228
+MX6Q_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK 1229
+MX6Q_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 1230
+MX6Q_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 1231
+MX6Q_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 1232
+MX6Q_PAD_TAMPER__SNVS_LP_WRAP_SNVS_TD1 1233
+MX6Q_PAD_PMIC_ON_REQ__SNVS_LPWRAP_WKALM 1234
+MX6Q_PAD_PMIC_STBY_REQ__CCM_PMIC_STBYRQ 1235
+MX6Q_PAD_POR_B__SRC_POR_B 1236
+MX6Q_PAD_BOOT_MODE1__SRC_BOOT_MODE_1 1237
+MX6Q_PAD_RESET_IN_B__SRC_RESET_B 1238
+MX6Q_PAD_BOOT_MODE0__SRC_BOOT_MODE_0 1239
+MX6Q_PAD_TEST_MODE__TCU_TEST_MODE 1240
+MX6Q_PAD_SD3_DAT7__USDHC3_DAT7 1241
+MX6Q_PAD_SD3_DAT7__UART1_TXD 1242
+MX6Q_PAD_SD3_DAT7__PCIE_CTRL_MUX_24 1243
+MX6Q_PAD_SD3_DAT7__USBOH3_UH3_DFD_OUT_0 1244
+MX6Q_PAD_SD3_DAT7__USBOH3_UH2_DFD_OUT_0 1245
+MX6Q_PAD_SD3_DAT7__GPIO_6_17 1246
+MX6Q_PAD_SD3_DAT7__MIPI_CORE_DPHY_IN_12 1247
+MX6Q_PAD_SD3_DAT7__USBPHY2_CLK20DIV 1248
+MX6Q_PAD_SD3_DAT6__USDHC3_DAT6 1249
+MX6Q_PAD_SD3_DAT6__UART1_RXD 1250
+MX6Q_PAD_SD3_DAT6__PCIE_CTRL_MUX_25 1251
+MX6Q_PAD_SD3_DAT6__USBOH3_UH3_DFD_OUT_1 1252
+MX6Q_PAD_SD3_DAT6__USBOH3_UH2_DFD_OUT_1 1253
+MX6Q_PAD_SD3_DAT6__GPIO_6_18 1254
+MX6Q_PAD_SD3_DAT6__MIPI_CORE_DPHY_IN_13 1255
+MX6Q_PAD_SD3_DAT6__ANATOP_TESTO_10 1256
+MX6Q_PAD_SD3_DAT5__USDHC3_DAT5 1257
+MX6Q_PAD_SD3_DAT5__UART2_TXD 1258
+MX6Q_PAD_SD3_DAT5__PCIE_CTRL_MUX_26 1259
+MX6Q_PAD_SD3_DAT5__USBOH3_UH3_DFD_OUT_2 1260
+MX6Q_PAD_SD3_DAT5__USBOH3_UH2_DFD_OUT_2 1261
+MX6Q_PAD_SD3_DAT5__GPIO_7_0 1262
+MX6Q_PAD_SD3_DAT5__MIPI_CORE_DPHY_IN_14 1263
+MX6Q_PAD_SD3_DAT5__ANATOP_TESTO_11 1264
+MX6Q_PAD_SD3_DAT4__USDHC3_DAT4 1265
+MX6Q_PAD_SD3_DAT4__UART2_RXD 1266
+MX6Q_PAD_SD3_DAT4__PCIE_CTRL_MUX_27 1267
+MX6Q_PAD_SD3_DAT4__USBOH3_UH3_DFD_OUT_3 1268
+MX6Q_PAD_SD3_DAT4__USBOH3_UH2_DFD_OUT_3 1269
+MX6Q_PAD_SD3_DAT4__GPIO_7_1 1270
+MX6Q_PAD_SD3_DAT4__MIPI_CORE_DPHY_IN_15 1271
+MX6Q_PAD_SD3_DAT4__ANATOP_TESTO_12 1272
+MX6Q_PAD_SD3_CMD__USDHC3_CMD 1273
+MX6Q_PAD_SD3_CMD__UART2_CTS 1274
+MX6Q_PAD_SD3_CMD__CAN1_TXCAN 1275
+MX6Q_PAD_SD3_CMD__USBOH3_UH3_DFD_OUT_4 1276
+MX6Q_PAD_SD3_CMD__USBOH3_UH2_DFD_OUT_4 1277
+MX6Q_PAD_SD3_CMD__GPIO_7_2 1278
+MX6Q_PAD_SD3_CMD__MIPI_CORE_DPHY_IN_16 1279
+MX6Q_PAD_SD3_CMD__ANATOP_TESTO_13 1280
+MX6Q_PAD_SD3_CLK__USDHC3_CLK 1281
+MX6Q_PAD_SD3_CLK__UART2_RTS 1282
+MX6Q_PAD_SD3_CLK__CAN1_RXCAN 1283
+MX6Q_PAD_SD3_CLK__USBOH3_UH3_DFD_OUT_5 1284
+MX6Q_PAD_SD3_CLK__USBOH3_UH2_DFD_OUT_5 1285
+MX6Q_PAD_SD3_CLK__GPIO_7_3 1286
+MX6Q_PAD_SD3_CLK__MIPI_CORE_DPHY_IN_17 1287
+MX6Q_PAD_SD3_CLK__ANATOP_TESTO_14 1288
+MX6Q_PAD_SD3_DAT0__USDHC3_DAT0 1289
+MX6Q_PAD_SD3_DAT0__UART1_CTS 1290
+MX6Q_PAD_SD3_DAT0__CAN2_TXCAN 1291
+MX6Q_PAD_SD3_DAT0__USBOH3_UH3_DFD_OUT_6 1292
+MX6Q_PAD_SD3_DAT0__USBOH3_UH2_DFD_OUT_6 1293
+MX6Q_PAD_SD3_DAT0__GPIO_7_4 1294
+MX6Q_PAD_SD3_DAT0__MIPI_CORE_DPHY_IN_18 1295
+MX6Q_PAD_SD3_DAT0__ANATOP_TESTO_15 1296
+MX6Q_PAD_SD3_DAT1__USDHC3_DAT1 1297
+MX6Q_PAD_SD3_DAT1__UART1_RTS 1298
+MX6Q_PAD_SD3_DAT1__CAN2_RXCAN 1299
+MX6Q_PAD_SD3_DAT1__USBOH3_UH3_DFD_OUT_7 1300
+MX6Q_PAD_SD3_DAT1__USBOH3_UH2_DFD_OUT_7 1301
+MX6Q_PAD_SD3_DAT1__GPIO_7_5 1302
+MX6Q_PAD_SD3_DAT1__MIPI_CORE_DPHY_IN_19 1303
+MX6Q_PAD_SD3_DAT1__ANATOP_TESTI_0 1304
+MX6Q_PAD_SD3_DAT2__USDHC3_DAT2 1305
+MX6Q_PAD_SD3_DAT2__PCIE_CTRL_MUX_28 1306
+MX6Q_PAD_SD3_DAT2__USBOH3_UH3_DFD_OUT_8 1307
+MX6Q_PAD_SD3_DAT2__USBOH3_UH2_DFD_OUT_8 1308
+MX6Q_PAD_SD3_DAT2__GPIO_7_6 1309
+MX6Q_PAD_SD3_DAT2__MIPI_CORE_DPHY_IN_20 1310
+MX6Q_PAD_SD3_DAT2__ANATOP_TESTI_1 1311
+MX6Q_PAD_SD3_DAT3__USDHC3_DAT3 1312
+MX6Q_PAD_SD3_DAT3__UART3_CTS 1313
+MX6Q_PAD_SD3_DAT3__PCIE_CTRL_MUX_29 1314
+MX6Q_PAD_SD3_DAT3__USBOH3_UH3_DFD_OUT_9 1315
+MX6Q_PAD_SD3_DAT3__USBOH3_UH2_DFD_OUT_9 1316
+MX6Q_PAD_SD3_DAT3__GPIO_7_7 1317
+MX6Q_PAD_SD3_DAT3__MIPI_CORE_DPHY_IN_21 1318
+MX6Q_PAD_SD3_DAT3__ANATOP_TESTI_2 1319
+MX6Q_PAD_SD3_RST__USDHC3_RST 1320
+MX6Q_PAD_SD3_RST__UART3_RTS 1321
+MX6Q_PAD_SD3_RST__PCIE_CTRL_MUX_30 1322
+MX6Q_PAD_SD3_RST__USBOH3_UH3_DFD_OUT_10 1323
+MX6Q_PAD_SD3_RST__USBOH3_UH2_DFD_OUT_10 1324
+MX6Q_PAD_SD3_RST__GPIO_7_8 1325
+MX6Q_PAD_SD3_RST__MIPI_CORE_DPHY_IN_22 1326
+MX6Q_PAD_SD3_RST__ANATOP_ANATOP_TESTI_3 1327
+MX6Q_PAD_NANDF_CLE__RAWNAND_CLE 1328
+MX6Q_PAD_NANDF_CLE__IPU2_SISG_4 1329
+MX6Q_PAD_NANDF_CLE__PCIE_CTRL_MUX_31 1330
+MX6Q_PAD_NANDF_CLE__USBOH3_UH3_DFD_OT11 1331
+MX6Q_PAD_NANDF_CLE__USBOH3_UH2_DFD_OT11 1332
+MX6Q_PAD_NANDF_CLE__GPIO_6_7 1333
+MX6Q_PAD_NANDF_CLE__MIPI_CORE_DPHY_IN23 1334
+MX6Q_PAD_NANDF_CLE__TPSMP_HTRANS_0 1335
+MX6Q_PAD_NANDF_ALE__RAWNAND_ALE 1336
+MX6Q_PAD_NANDF_ALE__USDHC4_RST 1337
+MX6Q_PAD_NANDF_ALE__PCIE_CTRL_MUX_0 1338
+MX6Q_PAD_NANDF_ALE__USBOH3_UH3_DFD_OT12 1339
+MX6Q_PAD_NANDF_ALE__USBOH3_UH2_DFD_OT12 1340
+MX6Q_PAD_NANDF_ALE__GPIO_6_8 1341
+MX6Q_PAD_NANDF_ALE__MIPI_CR_DPHY_IN_24 1342
+MX6Q_PAD_NANDF_ALE__TPSMP_HTRANS_1 1343
+MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN 1344
+MX6Q_PAD_NANDF_WP_B__IPU2_SISG_5 1345
+MX6Q_PAD_NANDF_WP_B__PCIE_CTRL__MUX_1 1346
+MX6Q_PAD_NANDF_WP_B__USBOH3_UH3_DFDOT13 1347
+MX6Q_PAD_NANDF_WP_B__USBOH3_UH2_DFDOT13 1348
+MX6Q_PAD_NANDF_WP_B__GPIO_6_9 1349
+MX6Q_PAD_NANDF_WP_B__MIPI_CR_DPHY_OUT32 1350
+MX6Q_PAD_NANDF_WP_B__PL301_PER1_HSIZE_0 1351
+MX6Q_PAD_NANDF_RB0__RAWNAND_READY0 1352
+MX6Q_PAD_NANDF_RB0__IPU2_DI0_PIN1 1353
+MX6Q_PAD_NANDF_RB0__PCIE_CTRL_MUX_2 1354
+MX6Q_PAD_NANDF_RB0__USBOH3_UH3_DFD_OT14 1355
+MX6Q_PAD_NANDF_RB0__USBOH3_UH2_DFD_OT14 1356
+MX6Q_PAD_NANDF_RB0__GPIO_6_10 1357
+MX6Q_PAD_NANDF_RB0__MIPI_CR_DPHY_OUT_33 1358
+MX6Q_PAD_NANDF_RB0__PL301_PER1_HSIZE_1 1359
+MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N 1360
+MX6Q_PAD_NANDF_CS0__USBOH3_UH3_DFD_OT15 1361
+MX6Q_PAD_NANDF_CS0__USBOH3_UH2_DFD_OT15 1362
+MX6Q_PAD_NANDF_CS0__GPIO_6_11 1363
+MX6Q_PAD_NANDF_CS0__PL301_PER1_HSIZE_2 1364
+MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N 1365
+MX6Q_PAD_NANDF_CS1__USDHC4_VSELECT 1366
+MX6Q_PAD_NANDF_CS1__USDHC3_VSELECT 1367
+MX6Q_PAD_NANDF_CS1__PCIE_CTRL_MUX_3 1368
+MX6Q_PAD_NANDF_CS1__GPIO_6_14 1369
+MX6Q_PAD_NANDF_CS1__PL301_PER1_HRDYOUT 1370
+MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N 1371
+MX6Q_PAD_NANDF_CS2__IPU1_SISG_0 1372
+MX6Q_PAD_NANDF_CS2__ESAI1_TX0 1373
+MX6Q_PAD_NANDF_CS2__WEIM_WEIM_CRE 1374
+MX6Q_PAD_NANDF_CS2__CCM_CLKO2 1375
+MX6Q_PAD_NANDF_CS2__GPIO_6_15 1376
+MX6Q_PAD_NANDF_CS2__IPU2_SISG_0 1377
+MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N 1378
+MX6Q_PAD_NANDF_CS3__IPU1_SISG_1 1379
+MX6Q_PAD_NANDF_CS3__ESAI1_TX1 1380
+MX6Q_PAD_NANDF_CS3__WEIM_WEIM_A_26 1381
+MX6Q_PAD_NANDF_CS3__PCIE_CTRL_MUX_4 1382
+MX6Q_PAD_NANDF_CS3__GPIO_6_16 1383
+MX6Q_PAD_NANDF_CS3__IPU2_SISG_1 1384
+MX6Q_PAD_NANDF_CS3__TPSMP_CLK 1385
+MX6Q_PAD_SD4_CMD__USDHC4_CMD 1386
+MX6Q_PAD_SD4_CMD__RAWNAND_RDN 1387
+MX6Q_PAD_SD4_CMD__UART3_TXD 1388
+MX6Q_PAD_SD4_CMD__PCIE_CTRL_MUX_5 1389
+MX6Q_PAD_SD4_CMD__GPIO_7_9 1390
+MX6Q_PAD_SD4_CMD__TPSMP_HDATA_DIR 1391
+MX6Q_PAD_SD4_CLK__USDHC4_CLK 1392
+MX6Q_PAD_SD4_CLK__RAWNAND_WRN 1393
+MX6Q_PAD_SD4_CLK__UART3_RXD 1394
+MX6Q_PAD_SD4_CLK__PCIE_CTRL_MUX_6 1395
+MX6Q_PAD_SD4_CLK__GPIO_7_10 1396
+MX6Q_PAD_NANDF_D0__RAWNAND_D0 1397
+MX6Q_PAD_NANDF_D0__USDHC1_DAT4 1398
+MX6Q_PAD_NANDF_D0__GPU3D_GPU_DBG_OUT_0 1399
+MX6Q_PAD_NANDF_D0__USBOH3_UH2_DFD_OUT16 1400
+MX6Q_PAD_NANDF_D0__USBOH3_UH3_DFD_OUT16 1401
+MX6Q_PAD_NANDF_D0__GPIO_2_0 1402
+MX6Q_PAD_NANDF_D0__IPU1_IPU_DIAG_BUS_0 1403
+MX6Q_PAD_NANDF_D0__IPU2_IPU_DIAG_BUS_0 1404
+MX6Q_PAD_NANDF_D1__RAWNAND_D1 1405
+MX6Q_PAD_NANDF_D1__USDHC1_DAT5 1406
+MX6Q_PAD_NANDF_D1__GPU3D_GPU_DEBUG_OUT1 1407
+MX6Q_PAD_NANDF_D1__USBOH3_UH2_DFD_OUT17 1408
+MX6Q_PAD_NANDF_D1__USBOH3_UH3_DFD_OUT17 1409
+MX6Q_PAD_NANDF_D1__GPIO_2_1 1410
+MX6Q_PAD_NANDF_D1__IPU1_IPU_DIAG_BUS_1 1411
+MX6Q_PAD_NANDF_D1__IPU2_IPU_DIAG_BUS_1 1412
+MX6Q_PAD_NANDF_D2__RAWNAND_D2 1413
+MX6Q_PAD_NANDF_D2__USDHC1_DAT6 1414
+MX6Q_PAD_NANDF_D2__GPU3D_GPU_DBG_OUT_2 1415
+MX6Q_PAD_NANDF_D2__USBOH3_UH2_DFD_OUT18 1416
+MX6Q_PAD_NANDF_D2__USBOH3_UH3_DFD_OUT18 1417
+MX6Q_PAD_NANDF_D2__GPIO_2_2 1418
+MX6Q_PAD_NANDF_D2__IPU1_IPU_DIAG_BUS_2 1419
+MX6Q_PAD_NANDF_D2__IPU2_IPU_DIAG_BUS_2 1420
+MX6Q_PAD_NANDF_D3__RAWNAND_D3 1421
+MX6Q_PAD_NANDF_D3__USDHC1_DAT7 1422
+MX6Q_PAD_NANDF_D3__GPU3D_GPU_DBG_OUT_3 1423
+MX6Q_PAD_NANDF_D3__USBOH3_UH2_DFD_OUT19 1424
+MX6Q_PAD_NANDF_D3__USBOH3_UH3_DFD_OUT19 1425
+MX6Q_PAD_NANDF_D3__GPIO_2_3 1426
+MX6Q_PAD_NANDF_D3__IPU1_IPU_DIAG_BUS_3 1427
+MX6Q_PAD_NANDF_D3__IPU2_IPU_DIAG_BUS_3 1428
+MX6Q_PAD_NANDF_D4__RAWNAND_D4 1429
+MX6Q_PAD_NANDF_D4__USDHC2_DAT4 1430
+MX6Q_PAD_NANDF_D4__GPU3D_GPU_DBG_OUT_4 1431
+MX6Q_PAD_NANDF_D4__USBOH3_UH2_DFD_OUT20 1432
+MX6Q_PAD_NANDF_D4__USBOH3_UH3_DFD_OUT20 1433
+MX6Q_PAD_NANDF_D4__GPIO_2_4 1434
+MX6Q_PAD_NANDF_D4__IPU1_IPU_DIAG_BUS_4 1435
+MX6Q_PAD_NANDF_D4__IPU2_IPU_DIAG_BUS_4 1436
+MX6Q_PAD_NANDF_D5__RAWNAND_D5 1437
+MX6Q_PAD_NANDF_D5__USDHC2_DAT5 1438
+MX6Q_PAD_NANDF_D5__GPU3D_GPU_DBG_OUT_5 1439
+MX6Q_PAD_NANDF_D5__USBOH3_UH2_DFD_OUT21 1440
+MX6Q_PAD_NANDF_D5__USBOH3_UH3_DFD_OUT21 1441
+MX6Q_PAD_NANDF_D5__GPIO_2_5 1442
+MX6Q_PAD_NANDF_D5__IPU1_IPU_DIAG_BUS_5 1443
+MX6Q_PAD_NANDF_D5__IPU2_IPU_DIAG_BUS_5 1444
+MX6Q_PAD_NANDF_D6__RAWNAND_D6 1445
+MX6Q_PAD_NANDF_D6__USDHC2_DAT6 1446
+MX6Q_PAD_NANDF_D6__GPU3D_GPU_DBG_OUT_6 1447
+MX6Q_PAD_NANDF_D6__USBOH3_UH2_DFD_OUT22 1448
+MX6Q_PAD_NANDF_D6__USBOH3_UH3_DFD_OUT22 1449
+MX6Q_PAD_NANDF_D6__GPIO_2_6 1450
+MX6Q_PAD_NANDF_D6__IPU1_IPU_DIAG_BUS_6 1451
+MX6Q_PAD_NANDF_D6__IPU2_IPU_DIAG_BUS_6 1452
+MX6Q_PAD_NANDF_D7__RAWNAND_D7 1453
+MX6Q_PAD_NANDF_D7__USDHC2_DAT7 1454
+MX6Q_PAD_NANDF_D7__GPU3D_GPU_DBG_OUT_7 1455
+MX6Q_PAD_NANDF_D7__USBOH3_UH2_DFD_OUT23 1456
+MX6Q_PAD_NANDF_D7__USBOH3_UH3_DFD_OUT23 1457
+MX6Q_PAD_NANDF_D7__GPIO_2_7 1458
+MX6Q_PAD_NANDF_D7__IPU1_IPU_DIAG_BUS_7 1459
+MX6Q_PAD_NANDF_D7__IPU2_IPU_DIAG_BUS_7 1460
+MX6Q_PAD_SD4_DAT0__RAWNAND_D8 1461
+MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 1462
+MX6Q_PAD_SD4_DAT0__RAWNAND_DQS 1463
+MX6Q_PAD_SD4_DAT0__USBOH3_UH2_DFD_OUT24 1464
+MX6Q_PAD_SD4_DAT0__USBOH3_UH3_DFD_OUT24 1465
+MX6Q_PAD_SD4_DAT0__GPIO_2_8 1466
+MX6Q_PAD_SD4_DAT0__IPU1_IPU_DIAG_BUS_8 1467
+MX6Q_PAD_SD4_DAT0__IPU2_IPU_DIAG_BUS_8 1468
+MX6Q_PAD_SD4_DAT1__RAWNAND_D9 1469
+MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 1470
+MX6Q_PAD_SD4_DAT1__PWM3_PWMO 1471
+MX6Q_PAD_SD4_DAT1__USBOH3_UH2_DFD_OUT25 1472
+MX6Q_PAD_SD4_DAT1__USBOH3_UH3_DFD_OUT25 1473
+MX6Q_PAD_SD4_DAT1__GPIO_2_9 1474
+MX6Q_PAD_SD4_DAT1__IPU1_IPU_DIAG_BUS_9 1475
+MX6Q_PAD_SD4_DAT1__IPU2_IPU_DIAG_BUS_9 1476
+MX6Q_PAD_SD4_DAT2__RAWNAND_D10 1477
+MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 1478
+MX6Q_PAD_SD4_DAT2__PWM4_PWMO 1479
+MX6Q_PAD_SD4_DAT2__USBOH3_UH2_DFD_OUT26 1480
+MX6Q_PAD_SD4_DAT2__USBOH3_UH3_DFD_OUT26 1481
+MX6Q_PAD_SD4_DAT2__GPIO_2_10 1482
+MX6Q_PAD_SD4_DAT2__IPU1_IPU_DIAG_BUS_10 1483
+MX6Q_PAD_SD4_DAT2__IPU2_IPU_DIAG_BUS_10 1484
+MX6Q_PAD_SD4_DAT3__RAWNAND_D11 1485
+MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 1486
+MX6Q_PAD_SD4_DAT3__USBOH3_UH2_DFD_OUT27 1487
+MX6Q_PAD_SD4_DAT3__USBOH3_UH3_DFD_OUT27 1488
+MX6Q_PAD_SD4_DAT3__GPIO_2_11 1489
+MX6Q_PAD_SD4_DAT3__IPU1_IPU_DIAG_BUS_11 1490
+MX6Q_PAD_SD4_DAT3__IPU2_IPU_DIAG_BUS_11 1491
+MX6Q_PAD_SD4_DAT4__RAWNAND_D12 1492
+MX6Q_PAD_SD4_DAT4__USDHC4_DAT4 1493
+MX6Q_PAD_SD4_DAT4__UART2_RXD 1494
+MX6Q_PAD_SD4_DAT4__USBOH3_UH2_DFD_OUT28 1495
+MX6Q_PAD_SD4_DAT4__USBOH3_UH3_DFD_OUT28 1496
+MX6Q_PAD_SD4_DAT4__GPIO_2_12 1497
+MX6Q_PAD_SD4_DAT4__IPU1_IPU_DIAG_BUS_12 1498
+MX6Q_PAD_SD4_DAT4__IPU2_IPU_DIAG_BUS_12 1499
+MX6Q_PAD_SD4_DAT5__RAWNAND_D13 1500
+MX6Q_PAD_SD4_DAT5__USDHC4_DAT5 1501
+MX6Q_PAD_SD4_DAT5__UART2_RTS 1502
+MX6Q_PAD_SD4_DAT5__USBOH3_UH2_DFD_OUT29 1503
+MX6Q_PAD_SD4_DAT5__USBOH3_UH3_DFD_OUT29 1504
+MX6Q_PAD_SD4_DAT5__GPIO_2_13 1505
+MX6Q_PAD_SD4_DAT5__IPU1_IPU_DIAG_BUS_13 1506
+MX6Q_PAD_SD4_DAT5__IPU2_IPU_DIAG_BUS_13 1507
+MX6Q_PAD_SD4_DAT6__RAWNAND_D14 1508
+MX6Q_PAD_SD4_DAT6__USDHC4_DAT6 1509
+MX6Q_PAD_SD4_DAT6__UART2_CTS 1510
+MX6Q_PAD_SD4_DAT6__USBOH3_UH2_DFD_OUT30 1511
+MX6Q_PAD_SD4_DAT6__USBOH3_UH3_DFD_OUT30 1512
+MX6Q_PAD_SD4_DAT6__GPIO_2_14 1513
+MX6Q_PAD_SD4_DAT6__IPU1_IPU_DIAG_BUS_14 1514
+MX6Q_PAD_SD4_DAT6__IPU2_IPU_DIAG_BUS_14 1515
+MX6Q_PAD_SD4_DAT7__RAWNAND_D15 1516
+MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 1517
+MX6Q_PAD_SD4_DAT7__UART2_TXD 1518
+MX6Q_PAD_SD4_DAT7__USBOH3_UH2_DFD_OUT31 1519
+MX6Q_PAD_SD4_DAT7__USBOH3_UH3_DFD_OUT31 1520
+MX6Q_PAD_SD4_DAT7__GPIO_2_15 1521
+MX6Q_PAD_SD4_DAT7__IPU1_IPU_DIAG_BUS_15 1522
+MX6Q_PAD_SD4_DAT7__IPU2_IPU_DIAG_BUS_15 1523
+MX6Q_PAD_SD1_DAT1__USDHC1_DAT1 1524
+MX6Q_PAD_SD1_DAT1__ECSPI5_SS0 1525
+MX6Q_PAD_SD1_DAT1__PWM3_PWMO 1526
+MX6Q_PAD_SD1_DAT1__GPT_CAPIN2 1527
+MX6Q_PAD_SD1_DAT1__PCIE_CTRL_MUX_7 1528
+MX6Q_PAD_SD1_DAT1__GPIO_1_17 1529
+MX6Q_PAD_SD1_DAT1__HDMI_TX_OPHYDTB_0 1530
+MX6Q_PAD_SD1_DAT1__ANATOP_TESTO_8 1531
+MX6Q_PAD_SD1_DAT0__USDHC1_DAT0 1532
+MX6Q_PAD_SD1_DAT0__ECSPI5_MISO 1533
+MX6Q_PAD_SD1_DAT0__CAAM_WRAP_RNG_OSCOBS 1534
+MX6Q_PAD_SD1_DAT0__GPT_CAPIN1 1535
+MX6Q_PAD_SD1_DAT0__PCIE_CTRL_MUX_8 1536
+MX6Q_PAD_SD1_DAT0__GPIO_1_16 1537
+MX6Q_PAD_SD1_DAT0__HDMI_TX_OPHYDTB_1 1538
+MX6Q_PAD_SD1_DAT0__ANATOP_TESTO_7 1539
+MX6Q_PAD_SD1_DAT3__USDHC1_DAT3 1540
+MX6Q_PAD_SD1_DAT3__ECSPI5_SS2 1541
+MX6Q_PAD_SD1_DAT3__GPT_CMPOUT3 1542
+MX6Q_PAD_SD1_DAT3__PWM1_PWMO 1543
+MX6Q_PAD_SD1_DAT3__WDOG2_WDOG_B 1544
+MX6Q_PAD_SD1_DAT3__GPIO_1_21 1545
+MX6Q_PAD_SD1_DAT3__WDOG2_WDOG_RST_B_DEB 1546
+MX6Q_PAD_SD1_DAT3__ANATOP_TESTO_6 1547
+MX6Q_PAD_SD1_CMD__USDHC1_CMD 1548
+MX6Q_PAD_SD1_CMD__ECSPI5_MOSI 1549
+MX6Q_PAD_SD1_CMD__PWM4_PWMO 1550
+MX6Q_PAD_SD1_CMD__GPT_CMPOUT1 1551
+MX6Q_PAD_SD1_CMD__GPIO_1_18 1552
+MX6Q_PAD_SD1_CMD__ANATOP_TESTO_5 1553
+MX6Q_PAD_SD1_DAT2__USDHC1_DAT2 1554
+MX6Q_PAD_SD1_DAT2__ECSPI5_SS1 1555
+MX6Q_PAD_SD1_DAT2__GPT_CMPOUT2 1556
+MX6Q_PAD_SD1_DAT2__PWM2_PWMO 1557
+MX6Q_PAD_SD1_DAT2__WDOG1_WDOG_B 1558
+MX6Q_PAD_SD1_DAT2__GPIO_1_19 1559
+MX6Q_PAD_SD1_DAT2__WDOG1_WDOG_RST_B_DEB 1560
+MX6Q_PAD_SD1_DAT2__ANATOP_TESTO_4 1561
+MX6Q_PAD_SD1_CLK__USDHC1_CLK 1562
+MX6Q_PAD_SD1_CLK__ECSPI5_SCLK 1563
+MX6Q_PAD_SD1_CLK__OSC32K_32K_OUT 1564
+MX6Q_PAD_SD1_CLK__GPT_CLKIN 1565
+MX6Q_PAD_SD1_CLK__GPIO_1_20 1566
+MX6Q_PAD_SD1_CLK__PHY_DTB_0 1567
+MX6Q_PAD_SD1_CLK__SATA_PHY_DTB_0 1568
+MX6Q_PAD_SD2_CLK__USDHC2_CLK 1569
+MX6Q_PAD_SD2_CLK__ECSPI5_SCLK 1570
+MX6Q_PAD_SD2_CLK__KPP_COL_5 1571
+MX6Q_PAD_SD2_CLK__AUDMUX_AUD4_RXFS 1572
+MX6Q_PAD_SD2_CLK__PCIE_CTRL_MUX_9 1573
+MX6Q_PAD_SD2_CLK__GPIO_1_10 1574
+MX6Q_PAD_SD2_CLK__PHY_DTB_1 1575
+MX6Q_PAD_SD2_CLK__SATA_PHY_DTB_1 1576
+MX6Q_PAD_SD2_CMD__USDHC2_CMD 1577
+MX6Q_PAD_SD2_CMD__ECSPI5_MOSI 1578
+MX6Q_PAD_SD2_CMD__KPP_ROW_5 1579
+MX6Q_PAD_SD2_CMD__AUDMUX_AUD4_RXC 1580
+MX6Q_PAD_SD2_CMD__PCIE_CTRL_MUX_10 1581
+MX6Q_PAD_SD2_CMD__GPIO_1_11 1582
+MX6Q_PAD_SD2_DAT3__USDHC2_DAT3 1583
+MX6Q_PAD_SD2_DAT3__ECSPI5_SS3 1584
+MX6Q_PAD_SD2_DAT3__KPP_COL_6 1585
+MX6Q_PAD_SD2_DAT3__AUDMUX_AUD4_TXC 1586
+MX6Q_PAD_SD2_DAT3__PCIE_CTRL_MUX_11 1587
+MX6Q_PAD_SD2_DAT3__GPIO_1_12 1588
+MX6Q_PAD_SD2_DAT3__SJC_DONE 1589
+MX6Q_PAD_SD2_DAT3__ANATOP_TESTO_3 1590
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
new file mode 100644
index 000000000000..f7e8e8f4d9a3
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
@@ -0,0 +1,918 @@
+* Freescale MXS Pin Controller
+
+The pins controlled by mxs pin controller are organized in banks, each bank
+has 32 pins. Each pin has 4 multiplexing functions, and generally, the 4th
+function is GPIO. The configuration on the pins includes drive strength,
+voltage and pull-up.
+
+Required properties:
+- compatible: "fsl,imx23-pinctrl" or "fsl,imx28-pinctrl"
+- reg: Should contain the register physical address and length for the
+ pin controller.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices.
+
+The node of mxs pin controller acts as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for
+a group of pins, and only affects those parameters that are explicitly listed.
+In other words, a subnode that describes a drive strength parameter implies no
+information about pull-up. For this reason, even seemingly boolean values are
+actually tristates in this binding: unspecified, off, or on. Unspecified is
+represented as an absent property, and off/on are represented as integer
+values 0 and 1.
+
+Those subnodes under mxs pin controller node will fall into two categories.
+One is to set up a group of pins for a function, both mux selection and pin
+configurations, and it's called group node in the binding document. The other
+one is to adjust the pin configuration for some particular pins that need a
+different configuration than what is defined in group node. The binding
+document calls this type of node config node.
+
+On mxs, there is no hardware pin group. The pin group in this binding only
+means a group of pins put together for particular peripheral to work in
+particular function, like SSP0 functioning as mmc0-8bit. That said, the
+group node should include all the pins needed for one function rather than
+having these pins defined in several group nodes. It also means each of
+"pinctrl-*" phandle in client device node should only have one group node
+pointed in there, while the phandle can have multiple config node referenced
+there to adjust configurations for some pins in the group.
+
+Required subnode-properties:
+- fsl,pinmux-ids: An integer array. Each integer in the array specify a pin
+ with given mux function, with bank, pin and mux packed as below.
+
+ [15..12] : bank number
+ [11..4] : pin number
+ [3..0] : mux selection
+
+ This integer with mux selection packed is used as an entity by both group
+ and config nodes to identify a pin. The mux selection in the integer takes
+ effects only on group node, and will get ignored by driver with config node,
+ since config node is only meant to set up pin configurations.
+
+ Valid values for these integers are listed below.
+
+- reg: Should be the index of the group nodes for same function. This property
+ is required only for group nodes, and should not be present in any config
+ nodes.
+
+Optional subnode-properties:
+- fsl,drive-strength: Integer.
+ 0: 4 mA
+ 1: 8 mA
+ 2: 12 mA
+ 3: 16 mA
+- fsl,voltage: Integer.
+ 0: 1.8 V
+ 1: 3.3 V
+- fsl,pull-up: Integer.
+ 0: Disable the internal pull-up
+ 1: Enable the internal pull-up
+
+Examples:
+
+pinctrl@80018000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx28-pinctrl";
+ reg = <0x80018000 2000>;
+
+ mmc0_8bit_pins_a: mmc0-8bit@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ 0x2000 0x2010 0x2020 0x2030
+ 0x2040 0x2050 0x2060 0x2070
+ 0x2080 0x2090 0x20a0>;
+ fsl,drive-strength = <1>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <1>;
+ };
+
+ mmc_cd_cfg: mmc-cd-cfg {
+ fsl,pinmux-ids = <0x2090>;
+ fsl,pull-up = <0>;
+ };
+
+ mmc_sck_cfg: mmc-sck-cfg {
+ fsl,pinmux-ids = <0x20a0>;
+ fsl,drive-strength = <2>;
+ fsl,pull-up = <0>;
+ };
+};
+
+In this example, group node mmc0-8bit defines a group of pins for mxs SSP0
+to function as a 8-bit mmc device, with 8mA, 3.3V and pull-up configurations
+applied on all these pins. And config nodes mmc-cd-cfg and mmc-sck-cfg are
+adjusting the configuration for pins card-detection and clock from what group
+node mmc0-8bit defines. Only the configuration properties to be adjusted need
+to be listed in the config nodes.
+
+Valid values for i.MX28 pinmux-id:
+
+pinmux id
+------ --
+MX28_PAD_GPMI_D00__GPMI_D0 0x0000
+MX28_PAD_GPMI_D01__GPMI_D1 0x0010
+MX28_PAD_GPMI_D02__GPMI_D2 0x0020
+MX28_PAD_GPMI_D03__GPMI_D3 0x0030
+MX28_PAD_GPMI_D04__GPMI_D4 0x0040
+MX28_PAD_GPMI_D05__GPMI_D5 0x0050
+MX28_PAD_GPMI_D06__GPMI_D6 0x0060
+MX28_PAD_GPMI_D07__GPMI_D7 0x0070
+MX28_PAD_GPMI_CE0N__GPMI_CE0N 0x0100
+MX28_PAD_GPMI_CE1N__GPMI_CE1N 0x0110
+MX28_PAD_GPMI_CE2N__GPMI_CE2N 0x0120
+MX28_PAD_GPMI_CE3N__GPMI_CE3N 0x0130
+MX28_PAD_GPMI_RDY0__GPMI_READY0 0x0140
+MX28_PAD_GPMI_RDY1__GPMI_READY1 0x0150
+MX28_PAD_GPMI_RDY2__GPMI_READY2 0x0160
+MX28_PAD_GPMI_RDY3__GPMI_READY3 0x0170
+MX28_PAD_GPMI_RDN__GPMI_RDN 0x0180
+MX28_PAD_GPMI_WRN__GPMI_WRN 0x0190
+MX28_PAD_GPMI_ALE__GPMI_ALE 0x01a0
+MX28_PAD_GPMI_CLE__GPMI_CLE 0x01b0
+MX28_PAD_GPMI_RESETN__GPMI_RESETN 0x01c0
+MX28_PAD_LCD_D00__LCD_D0 0x1000
+MX28_PAD_LCD_D01__LCD_D1 0x1010
+MX28_PAD_LCD_D02__LCD_D2 0x1020
+MX28_PAD_LCD_D03__LCD_D3 0x1030
+MX28_PAD_LCD_D04__LCD_D4 0x1040
+MX28_PAD_LCD_D05__LCD_D5 0x1050
+MX28_PAD_LCD_D06__LCD_D6 0x1060
+MX28_PAD_LCD_D07__LCD_D7 0x1070
+MX28_PAD_LCD_D08__LCD_D8 0x1080
+MX28_PAD_LCD_D09__LCD_D9 0x1090
+MX28_PAD_LCD_D10__LCD_D10 0x10a0
+MX28_PAD_LCD_D11__LCD_D11 0x10b0
+MX28_PAD_LCD_D12__LCD_D12 0x10c0
+MX28_PAD_LCD_D13__LCD_D13 0x10d0
+MX28_PAD_LCD_D14__LCD_D14 0x10e0
+MX28_PAD_LCD_D15__LCD_D15 0x10f0
+MX28_PAD_LCD_D16__LCD_D16 0x1100
+MX28_PAD_LCD_D17__LCD_D17 0x1110
+MX28_PAD_LCD_D18__LCD_D18 0x1120
+MX28_PAD_LCD_D19__LCD_D19 0x1130
+MX28_PAD_LCD_D20__LCD_D20 0x1140
+MX28_PAD_LCD_D21__LCD_D21 0x1150
+MX28_PAD_LCD_D22__LCD_D22 0x1160
+MX28_PAD_LCD_D23__LCD_D23 0x1170
+MX28_PAD_LCD_RD_E__LCD_RD_E 0x1180
+MX28_PAD_LCD_WR_RWN__LCD_WR_RWN 0x1190
+MX28_PAD_LCD_RS__LCD_RS 0x11a0
+MX28_PAD_LCD_CS__LCD_CS 0x11b0
+MX28_PAD_LCD_VSYNC__LCD_VSYNC 0x11c0
+MX28_PAD_LCD_HSYNC__LCD_HSYNC 0x11d0
+MX28_PAD_LCD_DOTCLK__LCD_DOTCLK 0x11e0
+MX28_PAD_LCD_ENABLE__LCD_ENABLE 0x11f0
+MX28_PAD_SSP0_DATA0__SSP0_D0 0x2000
+MX28_PAD_SSP0_DATA1__SSP0_D1 0x2010
+MX28_PAD_SSP0_DATA2__SSP0_D2 0x2020
+MX28_PAD_SSP0_DATA3__SSP0_D3 0x2030
+MX28_PAD_SSP0_DATA4__SSP0_D4 0x2040
+MX28_PAD_SSP0_DATA5__SSP0_D5 0x2050
+MX28_PAD_SSP0_DATA6__SSP0_D6 0x2060
+MX28_PAD_SSP0_DATA7__SSP0_D7 0x2070
+MX28_PAD_SSP0_CMD__SSP0_CMD 0x2080
+MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT 0x2090
+MX28_PAD_SSP0_SCK__SSP0_SCK 0x20a0
+MX28_PAD_SSP1_SCK__SSP1_SCK 0x20c0
+MX28_PAD_SSP1_CMD__SSP1_CMD 0x20d0
+MX28_PAD_SSP1_DATA0__SSP1_D0 0x20e0
+MX28_PAD_SSP1_DATA3__SSP1_D3 0x20f0
+MX28_PAD_SSP2_SCK__SSP2_SCK 0x2100
+MX28_PAD_SSP2_MOSI__SSP2_CMD 0x2110
+MX28_PAD_SSP2_MISO__SSP2_D0 0x2120
+MX28_PAD_SSP2_SS0__SSP2_D3 0x2130
+MX28_PAD_SSP2_SS1__SSP2_D4 0x2140
+MX28_PAD_SSP2_SS2__SSP2_D5 0x2150
+MX28_PAD_SSP3_SCK__SSP3_SCK 0x2180
+MX28_PAD_SSP3_MOSI__SSP3_CMD 0x2190
+MX28_PAD_SSP3_MISO__SSP3_D0 0x21a0
+MX28_PAD_SSP3_SS0__SSP3_D3 0x21b0
+MX28_PAD_AUART0_RX__AUART0_RX 0x3000
+MX28_PAD_AUART0_TX__AUART0_TX 0x3010
+MX28_PAD_AUART0_CTS__AUART0_CTS 0x3020
+MX28_PAD_AUART0_RTS__AUART0_RTS 0x3030
+MX28_PAD_AUART1_RX__AUART1_RX 0x3040
+MX28_PAD_AUART1_TX__AUART1_TX 0x3050
+MX28_PAD_AUART1_CTS__AUART1_CTS 0x3060
+MX28_PAD_AUART1_RTS__AUART1_RTS 0x3070
+MX28_PAD_AUART2_RX__AUART2_RX 0x3080
+MX28_PAD_AUART2_TX__AUART2_TX 0x3090
+MX28_PAD_AUART2_CTS__AUART2_CTS 0x30a0
+MX28_PAD_AUART2_RTS__AUART2_RTS 0x30b0
+MX28_PAD_AUART3_RX__AUART3_RX 0x30c0
+MX28_PAD_AUART3_TX__AUART3_TX 0x30d0
+MX28_PAD_AUART3_CTS__AUART3_CTS 0x30e0
+MX28_PAD_AUART3_RTS__AUART3_RTS 0x30f0
+MX28_PAD_PWM0__PWM_0 0x3100
+MX28_PAD_PWM1__PWM_1 0x3110
+MX28_PAD_PWM2__PWM_2 0x3120
+MX28_PAD_SAIF0_MCLK__SAIF0_MCLK 0x3140
+MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK 0x3150
+MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK 0x3160
+MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 0x3170
+MX28_PAD_I2C0_SCL__I2C0_SCL 0x3180
+MX28_PAD_I2C0_SDA__I2C0_SDA 0x3190
+MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 0x31a0
+MX28_PAD_SPDIF__SPDIF_TX 0x31b0
+MX28_PAD_PWM3__PWM_3 0x31c0
+MX28_PAD_PWM4__PWM_4 0x31d0
+MX28_PAD_LCD_RESET__LCD_RESET 0x31e0
+MX28_PAD_ENET0_MDC__ENET0_MDC 0x4000
+MX28_PAD_ENET0_MDIO__ENET0_MDIO 0x4010
+MX28_PAD_ENET0_RX_EN__ENET0_RX_EN 0x4020
+MX28_PAD_ENET0_RXD0__ENET0_RXD0 0x4030
+MX28_PAD_ENET0_RXD1__ENET0_RXD1 0x4040
+MX28_PAD_ENET0_TX_CLK__ENET0_TX_CLK 0x4050
+MX28_PAD_ENET0_TX_EN__ENET0_TX_EN 0x4060
+MX28_PAD_ENET0_TXD0__ENET0_TXD0 0x4070
+MX28_PAD_ENET0_TXD1__ENET0_TXD1 0x4080
+MX28_PAD_ENET0_RXD2__ENET0_RXD2 0x4090
+MX28_PAD_ENET0_RXD3__ENET0_RXD3 0x40a0
+MX28_PAD_ENET0_TXD2__ENET0_TXD2 0x40b0
+MX28_PAD_ENET0_TXD3__ENET0_TXD3 0x40c0
+MX28_PAD_ENET0_RX_CLK__ENET0_RX_CLK 0x40d0
+MX28_PAD_ENET0_COL__ENET0_COL 0x40e0
+MX28_PAD_ENET0_CRS__ENET0_CRS 0x40f0
+MX28_PAD_ENET_CLK__CLKCTRL_ENET 0x4100
+MX28_PAD_JTAG_RTCK__JTAG_RTCK 0x4140
+MX28_PAD_EMI_D00__EMI_DATA0 0x5000
+MX28_PAD_EMI_D01__EMI_DATA1 0x5010
+MX28_PAD_EMI_D02__EMI_DATA2 0x5020
+MX28_PAD_EMI_D03__EMI_DATA3 0x5030
+MX28_PAD_EMI_D04__EMI_DATA4 0x5040
+MX28_PAD_EMI_D05__EMI_DATA5 0x5050
+MX28_PAD_EMI_D06__EMI_DATA6 0x5060
+MX28_PAD_EMI_D07__EMI_DATA7 0x5070
+MX28_PAD_EMI_D08__EMI_DATA8 0x5080
+MX28_PAD_EMI_D09__EMI_DATA9 0x5090
+MX28_PAD_EMI_D10__EMI_DATA10 0x50a0
+MX28_PAD_EMI_D11__EMI_DATA11 0x50b0
+MX28_PAD_EMI_D12__EMI_DATA12 0x50c0
+MX28_PAD_EMI_D13__EMI_DATA13 0x50d0
+MX28_PAD_EMI_D14__EMI_DATA14 0x50e0
+MX28_PAD_EMI_D15__EMI_DATA15 0x50f0
+MX28_PAD_EMI_ODT0__EMI_ODT0 0x5100
+MX28_PAD_EMI_DQM0__EMI_DQM0 0x5110
+MX28_PAD_EMI_ODT1__EMI_ODT1 0x5120
+MX28_PAD_EMI_DQM1__EMI_DQM1 0x5130
+MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK 0x5140
+MX28_PAD_EMI_CLK__EMI_CLK 0x5150
+MX28_PAD_EMI_DQS0__EMI_DQS0 0x5160
+MX28_PAD_EMI_DQS1__EMI_DQS1 0x5170
+MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN 0x51a0
+MX28_PAD_EMI_A00__EMI_ADDR0 0x6000
+MX28_PAD_EMI_A01__EMI_ADDR1 0x6010
+MX28_PAD_EMI_A02__EMI_ADDR2 0x6020
+MX28_PAD_EMI_A03__EMI_ADDR3 0x6030
+MX28_PAD_EMI_A04__EMI_ADDR4 0x6040
+MX28_PAD_EMI_A05__EMI_ADDR5 0x6050
+MX28_PAD_EMI_A06__EMI_ADDR6 0x6060
+MX28_PAD_EMI_A07__EMI_ADDR7 0x6070
+MX28_PAD_EMI_A08__EMI_ADDR8 0x6080
+MX28_PAD_EMI_A09__EMI_ADDR9 0x6090
+MX28_PAD_EMI_A10__EMI_ADDR10 0x60a0
+MX28_PAD_EMI_A11__EMI_ADDR11 0x60b0
+MX28_PAD_EMI_A12__EMI_ADDR12 0x60c0
+MX28_PAD_EMI_A13__EMI_ADDR13 0x60d0
+MX28_PAD_EMI_A14__EMI_ADDR14 0x60e0
+MX28_PAD_EMI_BA0__EMI_BA0 0x6100
+MX28_PAD_EMI_BA1__EMI_BA1 0x6110
+MX28_PAD_EMI_BA2__EMI_BA2 0x6120
+MX28_PAD_EMI_CASN__EMI_CASN 0x6130
+MX28_PAD_EMI_RASN__EMI_RASN 0x6140
+MX28_PAD_EMI_WEN__EMI_WEN 0x6150
+MX28_PAD_EMI_CE0N__EMI_CE0N 0x6160
+MX28_PAD_EMI_CE1N__EMI_CE1N 0x6170
+MX28_PAD_EMI_CKE__EMI_CKE 0x6180
+MX28_PAD_GPMI_D00__SSP1_D0 0x0001
+MX28_PAD_GPMI_D01__SSP1_D1 0x0011
+MX28_PAD_GPMI_D02__SSP1_D2 0x0021
+MX28_PAD_GPMI_D03__SSP1_D3 0x0031
+MX28_PAD_GPMI_D04__SSP1_D4 0x0041
+MX28_PAD_GPMI_D05__SSP1_D5 0x0051
+MX28_PAD_GPMI_D06__SSP1_D6 0x0061
+MX28_PAD_GPMI_D07__SSP1_D7 0x0071
+MX28_PAD_GPMI_CE0N__SSP3_D0 0x0101
+MX28_PAD_GPMI_CE1N__SSP3_D3 0x0111
+MX28_PAD_GPMI_CE2N__CAN1_TX 0x0121
+MX28_PAD_GPMI_CE3N__CAN1_RX 0x0131
+MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT 0x0141
+MX28_PAD_GPMI_RDY1__SSP1_CMD 0x0151
+MX28_PAD_GPMI_RDY2__CAN0_TX 0x0161
+MX28_PAD_GPMI_RDY3__CAN0_RX 0x0171
+MX28_PAD_GPMI_RDN__SSP3_SCK 0x0181
+MX28_PAD_GPMI_WRN__SSP1_SCK 0x0191
+MX28_PAD_GPMI_ALE__SSP3_D1 0x01a1
+MX28_PAD_GPMI_CLE__SSP3_D2 0x01b1
+MX28_PAD_GPMI_RESETN__SSP3_CMD 0x01c1
+MX28_PAD_LCD_D03__ETM_DA8 0x1031
+MX28_PAD_LCD_D04__ETM_DA9 0x1041
+MX28_PAD_LCD_D08__ETM_DA3 0x1081
+MX28_PAD_LCD_D09__ETM_DA4 0x1091
+MX28_PAD_LCD_D20__ENET1_1588_EVENT2_OUT 0x1141
+MX28_PAD_LCD_D21__ENET1_1588_EVENT2_IN 0x1151
+MX28_PAD_LCD_D22__ENET1_1588_EVENT3_OUT 0x1161
+MX28_PAD_LCD_D23__ENET1_1588_EVENT3_IN 0x1171
+MX28_PAD_LCD_RD_E__LCD_VSYNC 0x1181
+MX28_PAD_LCD_WR_RWN__LCD_HSYNC 0x1191
+MX28_PAD_LCD_RS__LCD_DOTCLK 0x11a1
+MX28_PAD_LCD_CS__LCD_ENABLE 0x11b1
+MX28_PAD_LCD_VSYNC__SAIF1_SDATA0 0x11c1
+MX28_PAD_LCD_HSYNC__SAIF1_SDATA1 0x11d1
+MX28_PAD_LCD_DOTCLK__SAIF1_MCLK 0x11e1
+MX28_PAD_SSP0_DATA4__SSP2_D0 0x2041
+MX28_PAD_SSP0_DATA5__SSP2_D3 0x2051
+MX28_PAD_SSP0_DATA6__SSP2_CMD 0x2061
+MX28_PAD_SSP0_DATA7__SSP2_SCK 0x2071
+MX28_PAD_SSP1_SCK__SSP2_D1 0x20c1
+MX28_PAD_SSP1_CMD__SSP2_D2 0x20d1
+MX28_PAD_SSP1_DATA0__SSP2_D6 0x20e1
+MX28_PAD_SSP1_DATA3__SSP2_D7 0x20f1
+MX28_PAD_SSP2_SCK__AUART2_RX 0x2101
+MX28_PAD_SSP2_MOSI__AUART2_TX 0x2111
+MX28_PAD_SSP2_MISO__AUART3_RX 0x2121
+MX28_PAD_SSP2_SS0__AUART3_TX 0x2131
+MX28_PAD_SSP2_SS1__SSP2_D1 0x2141
+MX28_PAD_SSP2_SS2__SSP2_D2 0x2151
+MX28_PAD_SSP3_SCK__AUART4_TX 0x2181
+MX28_PAD_SSP3_MOSI__AUART4_RX 0x2191
+MX28_PAD_SSP3_MISO__AUART4_RTS 0x21a1
+MX28_PAD_SSP3_SS0__AUART4_CTS 0x21b1
+MX28_PAD_AUART0_RX__I2C0_SCL 0x3001
+MX28_PAD_AUART0_TX__I2C0_SDA 0x3011
+MX28_PAD_AUART0_CTS__AUART4_RX 0x3021
+MX28_PAD_AUART0_RTS__AUART4_TX 0x3031
+MX28_PAD_AUART1_RX__SSP2_CARD_DETECT 0x3041
+MX28_PAD_AUART1_TX__SSP3_CARD_DETECT 0x3051
+MX28_PAD_AUART1_CTS__USB0_OVERCURRENT 0x3061
+MX28_PAD_AUART1_RTS__USB0_ID 0x3071
+MX28_PAD_AUART2_RX__SSP3_D1 0x3081
+MX28_PAD_AUART2_TX__SSP3_D2 0x3091
+MX28_PAD_AUART2_CTS__I2C1_SCL 0x30a1
+MX28_PAD_AUART2_RTS__I2C1_SDA 0x30b1
+MX28_PAD_AUART3_RX__CAN0_TX 0x30c1
+MX28_PAD_AUART3_TX__CAN0_RX 0x30d1
+MX28_PAD_AUART3_CTS__CAN1_TX 0x30e1
+MX28_PAD_AUART3_RTS__CAN1_RX 0x30f1
+MX28_PAD_PWM0__I2C1_SCL 0x3101
+MX28_PAD_PWM1__I2C1_SDA 0x3111
+MX28_PAD_PWM2__USB0_ID 0x3121
+MX28_PAD_SAIF0_MCLK__PWM_3 0x3141
+MX28_PAD_SAIF0_LRCLK__PWM_4 0x3151
+MX28_PAD_SAIF0_BITCLK__PWM_5 0x3161
+MX28_PAD_SAIF0_SDATA0__PWM_6 0x3171
+MX28_PAD_I2C0_SCL__TIMROT_ROTARYA 0x3181
+MX28_PAD_I2C0_SDA__TIMROT_ROTARYB 0x3191
+MX28_PAD_SAIF1_SDATA0__PWM_7 0x31a1
+MX28_PAD_LCD_RESET__LCD_VSYNC 0x31e1
+MX28_PAD_ENET0_MDC__GPMI_CE4N 0x4001
+MX28_PAD_ENET0_MDIO__GPMI_CE5N 0x4011
+MX28_PAD_ENET0_RX_EN__GPMI_CE6N 0x4021
+MX28_PAD_ENET0_RXD0__GPMI_CE7N 0x4031
+MX28_PAD_ENET0_RXD1__GPMI_READY4 0x4041
+MX28_PAD_ENET0_TX_CLK__HSADC_TRIGGER 0x4051
+MX28_PAD_ENET0_TX_EN__GPMI_READY5 0x4061
+MX28_PAD_ENET0_TXD0__GPMI_READY6 0x4071
+MX28_PAD_ENET0_TXD1__GPMI_READY7 0x4081
+MX28_PAD_ENET0_RXD2__ENET1_RXD0 0x4091
+MX28_PAD_ENET0_RXD3__ENET1_RXD1 0x40a1
+MX28_PAD_ENET0_TXD2__ENET1_TXD0 0x40b1
+MX28_PAD_ENET0_TXD3__ENET1_TXD1 0x40c1
+MX28_PAD_ENET0_RX_CLK__ENET0_RX_ER 0x40d1
+MX28_PAD_ENET0_COL__ENET1_TX_EN 0x40e1
+MX28_PAD_ENET0_CRS__ENET1_RX_EN 0x40f1
+MX28_PAD_GPMI_CE2N__ENET0_RX_ER 0x0122
+MX28_PAD_GPMI_CE3N__SAIF1_MCLK 0x0132
+MX28_PAD_GPMI_RDY0__USB0_ID 0x0142
+MX28_PAD_GPMI_RDY2__ENET0_TX_ER 0x0162
+MX28_PAD_GPMI_RDY3__HSADC_TRIGGER 0x0172
+MX28_PAD_GPMI_ALE__SSP3_D4 0x01a2
+MX28_PAD_GPMI_CLE__SSP3_D5 0x01b2
+MX28_PAD_LCD_D00__ETM_DA0 0x1002
+MX28_PAD_LCD_D01__ETM_DA1 0x1012
+MX28_PAD_LCD_D02__ETM_DA2 0x1022
+MX28_PAD_LCD_D03__ETM_DA3 0x1032
+MX28_PAD_LCD_D04__ETM_DA4 0x1042
+MX28_PAD_LCD_D05__ETM_DA5 0x1052
+MX28_PAD_LCD_D06__ETM_DA6 0x1062
+MX28_PAD_LCD_D07__ETM_DA7 0x1072
+MX28_PAD_LCD_D08__ETM_DA8 0x1082
+MX28_PAD_LCD_D09__ETM_DA9 0x1092
+MX28_PAD_LCD_D10__ETM_DA10 0x10a2
+MX28_PAD_LCD_D11__ETM_DA11 0x10b2
+MX28_PAD_LCD_D12__ETM_DA12 0x10c2
+MX28_PAD_LCD_D13__ETM_DA13 0x10d2
+MX28_PAD_LCD_D14__ETM_DA14 0x10e2
+MX28_PAD_LCD_D15__ETM_DA15 0x10f2
+MX28_PAD_LCD_D16__ETM_DA7 0x1102
+MX28_PAD_LCD_D17__ETM_DA6 0x1112
+MX28_PAD_LCD_D18__ETM_DA5 0x1122
+MX28_PAD_LCD_D19__ETM_DA4 0x1132
+MX28_PAD_LCD_D20__ETM_DA3 0x1142
+MX28_PAD_LCD_D21__ETM_DA2 0x1152
+MX28_PAD_LCD_D22__ETM_DA1 0x1162
+MX28_PAD_LCD_D23__ETM_DA0 0x1172
+MX28_PAD_LCD_RD_E__ETM_TCTL 0x1182
+MX28_PAD_LCD_WR_RWN__ETM_TCLK 0x1192
+MX28_PAD_LCD_HSYNC__ETM_TCTL 0x11d2
+MX28_PAD_LCD_DOTCLK__ETM_TCLK 0x11e2
+MX28_PAD_SSP1_SCK__ENET0_1588_EVENT2_OUT 0x20c2
+MX28_PAD_SSP1_CMD__ENET0_1588_EVENT2_IN 0x20d2
+MX28_PAD_SSP1_DATA0__ENET0_1588_EVENT3_OUT 0x20e2
+MX28_PAD_SSP1_DATA3__ENET0_1588_EVENT3_IN 0x20f2
+MX28_PAD_SSP2_SCK__SAIF0_SDATA1 0x2102
+MX28_PAD_SSP2_MOSI__SAIF0_SDATA2 0x2112
+MX28_PAD_SSP2_MISO__SAIF1_SDATA1 0x2122
+MX28_PAD_SSP2_SS0__SAIF1_SDATA2 0x2132
+MX28_PAD_SSP2_SS1__USB1_OVERCURRENT 0x2142
+MX28_PAD_SSP2_SS2__USB0_OVERCURRENT 0x2152
+MX28_PAD_SSP3_SCK__ENET1_1588_EVENT0_OUT 0x2182
+MX28_PAD_SSP3_MOSI__ENET1_1588_EVENT0_IN 0x2192
+MX28_PAD_SSP3_MISO__ENET1_1588_EVENT1_OUT 0x21a2
+MX28_PAD_SSP3_SS0__ENET1_1588_EVENT1_IN 0x21b2
+MX28_PAD_AUART0_RX__DUART_CTS 0x3002
+MX28_PAD_AUART0_TX__DUART_RTS 0x3012
+MX28_PAD_AUART0_CTS__DUART_RX 0x3022
+MX28_PAD_AUART0_RTS__DUART_TX 0x3032
+MX28_PAD_AUART1_RX__PWM_0 0x3042
+MX28_PAD_AUART1_TX__PWM_1 0x3052
+MX28_PAD_AUART1_CTS__TIMROT_ROTARYA 0x3062
+MX28_PAD_AUART1_RTS__TIMROT_ROTARYB 0x3072
+MX28_PAD_AUART2_RX__SSP3_D4 0x3082
+MX28_PAD_AUART2_TX__SSP3_D5 0x3092
+MX28_PAD_AUART2_CTS__SAIF1_BITCLK 0x30a2
+MX28_PAD_AUART2_RTS__SAIF1_LRCLK 0x30b2
+MX28_PAD_AUART3_RX__ENET0_1588_EVENT0_OUT 0x30c2
+MX28_PAD_AUART3_TX__ENET0_1588_EVENT0_IN 0x30d2
+MX28_PAD_AUART3_CTS__ENET0_1588_EVENT1_OUT 0x30e2
+MX28_PAD_AUART3_RTS__ENET0_1588_EVENT1_IN 0x30f2
+MX28_PAD_PWM0__DUART_RX 0x3102
+MX28_PAD_PWM1__DUART_TX 0x3112
+MX28_PAD_PWM2__USB1_OVERCURRENT 0x3122
+MX28_PAD_SAIF0_MCLK__AUART4_CTS 0x3142
+MX28_PAD_SAIF0_LRCLK__AUART4_RTS 0x3152
+MX28_PAD_SAIF0_BITCLK__AUART4_RX 0x3162
+MX28_PAD_SAIF0_SDATA0__AUART4_TX 0x3172
+MX28_PAD_I2C0_SCL__DUART_RX 0x3182
+MX28_PAD_I2C0_SDA__DUART_TX 0x3192
+MX28_PAD_SAIF1_SDATA0__SAIF0_SDATA1 0x31a2
+MX28_PAD_SPDIF__ENET1_RX_ER 0x31b2
+MX28_PAD_ENET0_MDC__SAIF0_SDATA1 0x4002
+MX28_PAD_ENET0_MDIO__SAIF0_SDATA2 0x4012
+MX28_PAD_ENET0_RX_EN__SAIF1_SDATA1 0x4022
+MX28_PAD_ENET0_RXD0__SAIF1_SDATA2 0x4032
+MX28_PAD_ENET0_TX_CLK__ENET0_1588_EVENT2_OUT 0x4052
+MX28_PAD_ENET0_RXD2__ENET0_1588_EVENT0_OUT 0x4092
+MX28_PAD_ENET0_RXD3__ENET0_1588_EVENT0_IN 0x40a2
+MX28_PAD_ENET0_TXD2__ENET0_1588_EVENT1_OUT 0x40b2
+MX28_PAD_ENET0_TXD3__ENET0_1588_EVENT1_IN 0x40c2
+MX28_PAD_ENET0_RX_CLK__ENET0_1588_EVENT2_IN 0x40d2
+MX28_PAD_ENET0_COL__ENET0_1588_EVENT3_OUT 0x40e2
+MX28_PAD_ENET0_CRS__ENET0_1588_EVENT3_IN 0x40f2
+MX28_PAD_GPMI_D00__GPIO_0_0 0x0003
+MX28_PAD_GPMI_D01__GPIO_0_1 0x0013
+MX28_PAD_GPMI_D02__GPIO_0_2 0x0023
+MX28_PAD_GPMI_D03__GPIO_0_3 0x0033
+MX28_PAD_GPMI_D04__GPIO_0_4 0x0043
+MX28_PAD_GPMI_D05__GPIO_0_5 0x0053
+MX28_PAD_GPMI_D06__GPIO_0_6 0x0063
+MX28_PAD_GPMI_D07__GPIO_0_7 0x0073
+MX28_PAD_GPMI_CE0N__GPIO_0_16 0x0103
+MX28_PAD_GPMI_CE1N__GPIO_0_17 0x0113
+MX28_PAD_GPMI_CE2N__GPIO_0_18 0x0123
+MX28_PAD_GPMI_CE3N__GPIO_0_19 0x0133
+MX28_PAD_GPMI_RDY0__GPIO_0_20 0x0143
+MX28_PAD_GPMI_RDY1__GPIO_0_21 0x0153
+MX28_PAD_GPMI_RDY2__GPIO_0_22 0x0163
+MX28_PAD_GPMI_RDY3__GPIO_0_23 0x0173
+MX28_PAD_GPMI_RDN__GPIO_0_24 0x0183
+MX28_PAD_GPMI_WRN__GPIO_0_25 0x0193
+MX28_PAD_GPMI_ALE__GPIO_0_26 0x01a3
+MX28_PAD_GPMI_CLE__GPIO_0_27 0x01b3
+MX28_PAD_GPMI_RESETN__GPIO_0_28 0x01c3
+MX28_PAD_LCD_D00__GPIO_1_0 0x1003
+MX28_PAD_LCD_D01__GPIO_1_1 0x1013
+MX28_PAD_LCD_D02__GPIO_1_2 0x1023
+MX28_PAD_LCD_D03__GPIO_1_3 0x1033
+MX28_PAD_LCD_D04__GPIO_1_4 0x1043
+MX28_PAD_LCD_D05__GPIO_1_5 0x1053
+MX28_PAD_LCD_D06__GPIO_1_6 0x1063
+MX28_PAD_LCD_D07__GPIO_1_7 0x1073
+MX28_PAD_LCD_D08__GPIO_1_8 0x1083
+MX28_PAD_LCD_D09__GPIO_1_9 0x1093
+MX28_PAD_LCD_D10__GPIO_1_10 0x10a3
+MX28_PAD_LCD_D11__GPIO_1_11 0x10b3
+MX28_PAD_LCD_D12__GPIO_1_12 0x10c3
+MX28_PAD_LCD_D13__GPIO_1_13 0x10d3
+MX28_PAD_LCD_D14__GPIO_1_14 0x10e3
+MX28_PAD_LCD_D15__GPIO_1_15 0x10f3
+MX28_PAD_LCD_D16__GPIO_1_16 0x1103
+MX28_PAD_LCD_D17__GPIO_1_17 0x1113
+MX28_PAD_LCD_D18__GPIO_1_18 0x1123
+MX28_PAD_LCD_D19__GPIO_1_19 0x1133
+MX28_PAD_LCD_D20__GPIO_1_20 0x1143
+MX28_PAD_LCD_D21__GPIO_1_21 0x1153
+MX28_PAD_LCD_D22__GPIO_1_22 0x1163
+MX28_PAD_LCD_D23__GPIO_1_23 0x1173
+MX28_PAD_LCD_RD_E__GPIO_1_24 0x1183
+MX28_PAD_LCD_WR_RWN__GPIO_1_25 0x1193
+MX28_PAD_LCD_RS__GPIO_1_26 0x11a3
+MX28_PAD_LCD_CS__GPIO_1_27 0x11b3
+MX28_PAD_LCD_VSYNC__GPIO_1_28 0x11c3
+MX28_PAD_LCD_HSYNC__GPIO_1_29 0x11d3
+MX28_PAD_LCD_DOTCLK__GPIO_1_30 0x11e3
+MX28_PAD_LCD_ENABLE__GPIO_1_31 0x11f3
+MX28_PAD_SSP0_DATA0__GPIO_2_0 0x2003
+MX28_PAD_SSP0_DATA1__GPIO_2_1 0x2013
+MX28_PAD_SSP0_DATA2__GPIO_2_2 0x2023
+MX28_PAD_SSP0_DATA3__GPIO_2_3 0x2033
+MX28_PAD_SSP0_DATA4__GPIO_2_4 0x2043
+MX28_PAD_SSP0_DATA5__GPIO_2_5 0x2053
+MX28_PAD_SSP0_DATA6__GPIO_2_6 0x2063
+MX28_PAD_SSP0_DATA7__GPIO_2_7 0x2073
+MX28_PAD_SSP0_CMD__GPIO_2_8 0x2083
+MX28_PAD_SSP0_DETECT__GPIO_2_9 0x2093
+MX28_PAD_SSP0_SCK__GPIO_2_10 0x20a3
+MX28_PAD_SSP1_SCK__GPIO_2_12 0x20c3
+MX28_PAD_SSP1_CMD__GPIO_2_13 0x20d3
+MX28_PAD_SSP1_DATA0__GPIO_2_14 0x20e3
+MX28_PAD_SSP1_DATA3__GPIO_2_15 0x20f3
+MX28_PAD_SSP2_SCK__GPIO_2_16 0x2103
+MX28_PAD_SSP2_MOSI__GPIO_2_17 0x2113
+MX28_PAD_SSP2_MISO__GPIO_2_18 0x2123
+MX28_PAD_SSP2_SS0__GPIO_2_19 0x2133
+MX28_PAD_SSP2_SS1__GPIO_2_20 0x2143
+MX28_PAD_SSP2_SS2__GPIO_2_21 0x2153
+MX28_PAD_SSP3_SCK__GPIO_2_24 0x2183
+MX28_PAD_SSP3_MOSI__GPIO_2_25 0x2193
+MX28_PAD_SSP3_MISO__GPIO_2_26 0x21a3
+MX28_PAD_SSP3_SS0__GPIO_2_27 0x21b3
+MX28_PAD_AUART0_RX__GPIO_3_0 0x3003
+MX28_PAD_AUART0_TX__GPIO_3_1 0x3013
+MX28_PAD_AUART0_CTS__GPIO_3_2 0x3023
+MX28_PAD_AUART0_RTS__GPIO_3_3 0x3033
+MX28_PAD_AUART1_RX__GPIO_3_4 0x3043
+MX28_PAD_AUART1_TX__GPIO_3_5 0x3053
+MX28_PAD_AUART1_CTS__GPIO_3_6 0x3063
+MX28_PAD_AUART1_RTS__GPIO_3_7 0x3073
+MX28_PAD_AUART2_RX__GPIO_3_8 0x3083
+MX28_PAD_AUART2_TX__GPIO_3_9 0x3093
+MX28_PAD_AUART2_CTS__GPIO_3_10 0x30a3
+MX28_PAD_AUART2_RTS__GPIO_3_11 0x30b3
+MX28_PAD_AUART3_RX__GPIO_3_12 0x30c3
+MX28_PAD_AUART3_TX__GPIO_3_13 0x30d3
+MX28_PAD_AUART3_CTS__GPIO_3_14 0x30e3
+MX28_PAD_AUART3_RTS__GPIO_3_15 0x30f3
+MX28_PAD_PWM0__GPIO_3_16 0x3103
+MX28_PAD_PWM1__GPIO_3_17 0x3113
+MX28_PAD_PWM2__GPIO_3_18 0x3123
+MX28_PAD_SAIF0_MCLK__GPIO_3_20 0x3143
+MX28_PAD_SAIF0_LRCLK__GPIO_3_21 0x3153
+MX28_PAD_SAIF0_BITCLK__GPIO_3_22 0x3163
+MX28_PAD_SAIF0_SDATA0__GPIO_3_23 0x3173
+MX28_PAD_I2C0_SCL__GPIO_3_24 0x3183
+MX28_PAD_I2C0_SDA__GPIO_3_25 0x3193
+MX28_PAD_SAIF1_SDATA0__GPIO_3_26 0x31a3
+MX28_PAD_SPDIF__GPIO_3_27 0x31b3
+MX28_PAD_PWM3__GPIO_3_28 0x31c3
+MX28_PAD_PWM4__GPIO_3_29 0x31d3
+MX28_PAD_LCD_RESET__GPIO_3_30 0x31e3
+MX28_PAD_ENET0_MDC__GPIO_4_0 0x4003
+MX28_PAD_ENET0_MDIO__GPIO_4_1 0x4013
+MX28_PAD_ENET0_RX_EN__GPIO_4_2 0x4023
+MX28_PAD_ENET0_RXD0__GPIO_4_3 0x4033
+MX28_PAD_ENET0_RXD1__GPIO_4_4 0x4043
+MX28_PAD_ENET0_TX_CLK__GPIO_4_5 0x4053
+MX28_PAD_ENET0_TX_EN__GPIO_4_6 0x4063
+MX28_PAD_ENET0_TXD0__GPIO_4_7 0x4073
+MX28_PAD_ENET0_TXD1__GPIO_4_8 0x4083
+MX28_PAD_ENET0_RXD2__GPIO_4_9 0x4093
+MX28_PAD_ENET0_RXD3__GPIO_4_10 0x40a3
+MX28_PAD_ENET0_TXD2__GPIO_4_11 0x40b3
+MX28_PAD_ENET0_TXD3__GPIO_4_12 0x40c3
+MX28_PAD_ENET0_RX_CLK__GPIO_4_13 0x40d3
+MX28_PAD_ENET0_COL__GPIO_4_14 0x40e3
+MX28_PAD_ENET0_CRS__GPIO_4_15 0x40f3
+MX28_PAD_ENET_CLK__GPIO_4_16 0x4103
+MX28_PAD_JTAG_RTCK__GPIO_4_20 0x4143
+
+Valid values for i.MX23 pinmux-id:
+
+pinmux id
+------ --
+MX23_PAD_GPMI_D00__GPMI_D00 0x0000
+MX23_PAD_GPMI_D01__GPMI_D01 0x0010
+MX23_PAD_GPMI_D02__GPMI_D02 0x0020
+MX23_PAD_GPMI_D03__GPMI_D03 0x0030
+MX23_PAD_GPMI_D04__GPMI_D04 0x0040
+MX23_PAD_GPMI_D05__GPMI_D05 0x0050
+MX23_PAD_GPMI_D06__GPMI_D06 0x0060
+MX23_PAD_GPMI_D07__GPMI_D07 0x0070
+MX23_PAD_GPMI_D08__GPMI_D08 0x0080
+MX23_PAD_GPMI_D09__GPMI_D09 0x0090
+MX23_PAD_GPMI_D10__GPMI_D10 0x00a0
+MX23_PAD_GPMI_D11__GPMI_D11 0x00b0
+MX23_PAD_GPMI_D12__GPMI_D12 0x00c0
+MX23_PAD_GPMI_D13__GPMI_D13 0x00d0
+MX23_PAD_GPMI_D14__GPMI_D14 0x00e0
+MX23_PAD_GPMI_D15__GPMI_D15 0x00f0
+MX23_PAD_GPMI_CLE__GPMI_CLE 0x0100
+MX23_PAD_GPMI_ALE__GPMI_ALE 0x0110
+MX23_PAD_GPMI_CE2N__GPMI_CE2N 0x0120
+MX23_PAD_GPMI_RDY0__GPMI_RDY0 0x0130
+MX23_PAD_GPMI_RDY1__GPMI_RDY1 0x0140
+MX23_PAD_GPMI_RDY2__GPMI_RDY2 0x0150
+MX23_PAD_GPMI_RDY3__GPMI_RDY3 0x0160
+MX23_PAD_GPMI_WPN__GPMI_WPN 0x0170
+MX23_PAD_GPMI_WRN__GPMI_WRN 0x0180
+MX23_PAD_GPMI_RDN__GPMI_RDN 0x0190
+MX23_PAD_AUART1_CTS__AUART1_CTS 0x01a0
+MX23_PAD_AUART1_RTS__AUART1_RTS 0x01b0
+MX23_PAD_AUART1_RX__AUART1_RX 0x01c0
+MX23_PAD_AUART1_TX__AUART1_TX 0x01d0
+MX23_PAD_I2C_SCL__I2C_SCL 0x01e0
+MX23_PAD_I2C_SDA__I2C_SDA 0x01f0
+MX23_PAD_LCD_D00__LCD_D00 0x1000
+MX23_PAD_LCD_D01__LCD_D01 0x1010
+MX23_PAD_LCD_D02__LCD_D02 0x1020
+MX23_PAD_LCD_D03__LCD_D03 0x1030
+MX23_PAD_LCD_D04__LCD_D04 0x1040
+MX23_PAD_LCD_D05__LCD_D05 0x1050
+MX23_PAD_LCD_D06__LCD_D06 0x1060
+MX23_PAD_LCD_D07__LCD_D07 0x1070
+MX23_PAD_LCD_D08__LCD_D08 0x1080
+MX23_PAD_LCD_D09__LCD_D09 0x1090
+MX23_PAD_LCD_D10__LCD_D10 0x10a0
+MX23_PAD_LCD_D11__LCD_D11 0x10b0
+MX23_PAD_LCD_D12__LCD_D12 0x10c0
+MX23_PAD_LCD_D13__LCD_D13 0x10d0
+MX23_PAD_LCD_D14__LCD_D14 0x10e0
+MX23_PAD_LCD_D15__LCD_D15 0x10f0
+MX23_PAD_LCD_D16__LCD_D16 0x1100
+MX23_PAD_LCD_D17__LCD_D17 0x1110
+MX23_PAD_LCD_RESET__LCD_RESET 0x1120
+MX23_PAD_LCD_RS__LCD_RS 0x1130
+MX23_PAD_LCD_WR__LCD_WR 0x1140
+MX23_PAD_LCD_CS__LCD_CS 0x1150
+MX23_PAD_LCD_DOTCK__LCD_DOTCK 0x1160
+MX23_PAD_LCD_ENABLE__LCD_ENABLE 0x1170
+MX23_PAD_LCD_HSYNC__LCD_HSYNC 0x1180
+MX23_PAD_LCD_VSYNC__LCD_VSYNC 0x1190
+MX23_PAD_PWM0__PWM0 0x11a0
+MX23_PAD_PWM1__PWM1 0x11b0
+MX23_PAD_PWM2__PWM2 0x11c0
+MX23_PAD_PWM3__PWM3 0x11d0
+MX23_PAD_PWM4__PWM4 0x11e0
+MX23_PAD_SSP1_CMD__SSP1_CMD 0x2000
+MX23_PAD_SSP1_DETECT__SSP1_DETECT 0x2010
+MX23_PAD_SSP1_DATA0__SSP1_DATA0 0x2020
+MX23_PAD_SSP1_DATA1__SSP1_DATA1 0x2030
+MX23_PAD_SSP1_DATA2__SSP1_DATA2 0x2040
+MX23_PAD_SSP1_DATA3__SSP1_DATA3 0x2050
+MX23_PAD_SSP1_SCK__SSP1_SCK 0x2060
+MX23_PAD_ROTARYA__ROTARYA 0x2070
+MX23_PAD_ROTARYB__ROTARYB 0x2080
+MX23_PAD_EMI_A00__EMI_A00 0x2090
+MX23_PAD_EMI_A01__EMI_A01 0x20a0
+MX23_PAD_EMI_A02__EMI_A02 0x20b0
+MX23_PAD_EMI_A03__EMI_A03 0x20c0
+MX23_PAD_EMI_A04__EMI_A04 0x20d0
+MX23_PAD_EMI_A05__EMI_A05 0x20e0
+MX23_PAD_EMI_A06__EMI_A06 0x20f0
+MX23_PAD_EMI_A07__EMI_A07 0x2100
+MX23_PAD_EMI_A08__EMI_A08 0x2110
+MX23_PAD_EMI_A09__EMI_A09 0x2120
+MX23_PAD_EMI_A10__EMI_A10 0x2130
+MX23_PAD_EMI_A11__EMI_A11 0x2140
+MX23_PAD_EMI_A12__EMI_A12 0x2150
+MX23_PAD_EMI_BA0__EMI_BA0 0x2160
+MX23_PAD_EMI_BA1__EMI_BA1 0x2170
+MX23_PAD_EMI_CASN__EMI_CASN 0x2180
+MX23_PAD_EMI_CE0N__EMI_CE0N 0x2190
+MX23_PAD_EMI_CE1N__EMI_CE1N 0x21a0
+MX23_PAD_GPMI_CE1N__GPMI_CE1N 0x21b0
+MX23_PAD_GPMI_CE0N__GPMI_CE0N 0x21c0
+MX23_PAD_EMI_CKE__EMI_CKE 0x21d0
+MX23_PAD_EMI_RASN__EMI_RASN 0x21e0
+MX23_PAD_EMI_WEN__EMI_WEN 0x21f0
+MX23_PAD_EMI_D00__EMI_D00 0x3000
+MX23_PAD_EMI_D01__EMI_D01 0x3010
+MX23_PAD_EMI_D02__EMI_D02 0x3020
+MX23_PAD_EMI_D03__EMI_D03 0x3030
+MX23_PAD_EMI_D04__EMI_D04 0x3040
+MX23_PAD_EMI_D05__EMI_D05 0x3050
+MX23_PAD_EMI_D06__EMI_D06 0x3060
+MX23_PAD_EMI_D07__EMI_D07 0x3070
+MX23_PAD_EMI_D08__EMI_D08 0x3080
+MX23_PAD_EMI_D09__EMI_D09 0x3090
+MX23_PAD_EMI_D10__EMI_D10 0x30a0
+MX23_PAD_EMI_D11__EMI_D11 0x30b0
+MX23_PAD_EMI_D12__EMI_D12 0x30c0
+MX23_PAD_EMI_D13__EMI_D13 0x30d0
+MX23_PAD_EMI_D14__EMI_D14 0x30e0
+MX23_PAD_EMI_D15__EMI_D15 0x30f0
+MX23_PAD_EMI_DQM0__EMI_DQM0 0x3100
+MX23_PAD_EMI_DQM1__EMI_DQM1 0x3110
+MX23_PAD_EMI_DQS0__EMI_DQS0 0x3120
+MX23_PAD_EMI_DQS1__EMI_DQS1 0x3130
+MX23_PAD_EMI_CLK__EMI_CLK 0x3140
+MX23_PAD_EMI_CLKN__EMI_CLKN 0x3150
+MX23_PAD_GPMI_D00__LCD_D8 0x0001
+MX23_PAD_GPMI_D01__LCD_D9 0x0011
+MX23_PAD_GPMI_D02__LCD_D10 0x0021
+MX23_PAD_GPMI_D03__LCD_D11 0x0031
+MX23_PAD_GPMI_D04__LCD_D12 0x0041
+MX23_PAD_GPMI_D05__LCD_D13 0x0051
+MX23_PAD_GPMI_D06__LCD_D14 0x0061
+MX23_PAD_GPMI_D07__LCD_D15 0x0071
+MX23_PAD_GPMI_D08__LCD_D18 0x0081
+MX23_PAD_GPMI_D09__LCD_D19 0x0091
+MX23_PAD_GPMI_D10__LCD_D20 0x00a1
+MX23_PAD_GPMI_D11__LCD_D21 0x00b1
+MX23_PAD_GPMI_D12__LCD_D22 0x00c1
+MX23_PAD_GPMI_D13__LCD_D23 0x00d1
+MX23_PAD_GPMI_D14__AUART2_RX 0x00e1
+MX23_PAD_GPMI_D15__AUART2_TX 0x00f1
+MX23_PAD_GPMI_CLE__LCD_D16 0x0101
+MX23_PAD_GPMI_ALE__LCD_D17 0x0111
+MX23_PAD_GPMI_CE2N__ATA_A2 0x0121
+MX23_PAD_AUART1_RTS__IR_CLK 0x01b1
+MX23_PAD_AUART1_RX__IR_RX 0x01c1
+MX23_PAD_AUART1_TX__IR_TX 0x01d1
+MX23_PAD_I2C_SCL__GPMI_RDY2 0x01e1
+MX23_PAD_I2C_SDA__GPMI_CE2N 0x01f1
+MX23_PAD_LCD_D00__ETM_DA8 0x1001
+MX23_PAD_LCD_D01__ETM_DA9 0x1011
+MX23_PAD_LCD_D02__ETM_DA10 0x1021
+MX23_PAD_LCD_D03__ETM_DA11 0x1031
+MX23_PAD_LCD_D04__ETM_DA12 0x1041
+MX23_PAD_LCD_D05__ETM_DA13 0x1051
+MX23_PAD_LCD_D06__ETM_DA14 0x1061
+MX23_PAD_LCD_D07__ETM_DA15 0x1071
+MX23_PAD_LCD_D08__ETM_DA0 0x1081
+MX23_PAD_LCD_D09__ETM_DA1 0x1091
+MX23_PAD_LCD_D10__ETM_DA2 0x10a1
+MX23_PAD_LCD_D11__ETM_DA3 0x10b1
+MX23_PAD_LCD_D12__ETM_DA4 0x10c1
+MX23_PAD_LCD_D13__ETM_DA5 0x10d1
+MX23_PAD_LCD_D14__ETM_DA6 0x10e1
+MX23_PAD_LCD_D15__ETM_DA7 0x10f1
+MX23_PAD_LCD_RESET__ETM_TCTL 0x1121
+MX23_PAD_LCD_RS__ETM_TCLK 0x1131
+MX23_PAD_LCD_DOTCK__GPMI_RDY3 0x1161
+MX23_PAD_LCD_ENABLE__I2C_SCL 0x1171
+MX23_PAD_LCD_HSYNC__I2C_SDA 0x1181
+MX23_PAD_LCD_VSYNC__LCD_BUSY 0x1191
+MX23_PAD_PWM0__ROTARYA 0x11a1
+MX23_PAD_PWM1__ROTARYB 0x11b1
+MX23_PAD_PWM2__GPMI_RDY3 0x11c1
+MX23_PAD_PWM3__ETM_TCTL 0x11d1
+MX23_PAD_PWM4__ETM_TCLK 0x11e1
+MX23_PAD_SSP1_DETECT__GPMI_CE3N 0x2011
+MX23_PAD_SSP1_DATA1__I2C_SCL 0x2031
+MX23_PAD_SSP1_DATA2__I2C_SDA 0x2041
+MX23_PAD_ROTARYA__AUART2_RTS 0x2071
+MX23_PAD_ROTARYB__AUART2_CTS 0x2081
+MX23_PAD_GPMI_D00__SSP2_DATA0 0x0002
+MX23_PAD_GPMI_D01__SSP2_DATA1 0x0012
+MX23_PAD_GPMI_D02__SSP2_DATA2 0x0022
+MX23_PAD_GPMI_D03__SSP2_DATA3 0x0032
+MX23_PAD_GPMI_D04__SSP2_DATA4 0x0042
+MX23_PAD_GPMI_D05__SSP2_DATA5 0x0052
+MX23_PAD_GPMI_D06__SSP2_DATA6 0x0062
+MX23_PAD_GPMI_D07__SSP2_DATA7 0x0072
+MX23_PAD_GPMI_D08__SSP1_DATA4 0x0082
+MX23_PAD_GPMI_D09__SSP1_DATA5 0x0092
+MX23_PAD_GPMI_D10__SSP1_DATA6 0x00a2
+MX23_PAD_GPMI_D11__SSP1_DATA7 0x00b2
+MX23_PAD_GPMI_D15__GPMI_CE3N 0x00f2
+MX23_PAD_GPMI_RDY0__SSP2_DETECT 0x0132
+MX23_PAD_GPMI_RDY1__SSP2_CMD 0x0142
+MX23_PAD_GPMI_WRN__SSP2_SCK 0x0182
+MX23_PAD_AUART1_CTS__SSP1_DATA4 0x01a2
+MX23_PAD_AUART1_RTS__SSP1_DATA5 0x01b2
+MX23_PAD_AUART1_RX__SSP1_DATA6 0x01c2
+MX23_PAD_AUART1_TX__SSP1_DATA7 0x01d2
+MX23_PAD_I2C_SCL__AUART1_TX 0x01e2
+MX23_PAD_I2C_SDA__AUART1_RX 0x01f2
+MX23_PAD_LCD_D08__SAIF2_SDATA0 0x1082
+MX23_PAD_LCD_D09__SAIF1_SDATA0 0x1092
+MX23_PAD_LCD_D10__SAIF_MCLK_BITCLK 0x10a2
+MX23_PAD_LCD_D11__SAIF_LRCLK 0x10b2
+MX23_PAD_LCD_D12__SAIF2_SDATA1 0x10c2
+MX23_PAD_LCD_D13__SAIF2_SDATA2 0x10d2
+MX23_PAD_LCD_D14__SAIF1_SDATA2 0x10e2
+MX23_PAD_LCD_D15__SAIF1_SDATA1 0x10f2
+MX23_PAD_LCD_D16__SAIF_ALT_BITCLK 0x1102
+MX23_PAD_LCD_RESET__GPMI_CE3N 0x1122
+MX23_PAD_PWM0__DUART_RX 0x11a2
+MX23_PAD_PWM1__DUART_TX 0x11b2
+MX23_PAD_PWM3__AUART1_CTS 0x11d2
+MX23_PAD_PWM4__AUART1_RTS 0x11e2
+MX23_PAD_SSP1_CMD__JTAG_TDO 0x2002
+MX23_PAD_SSP1_DETECT__USB_OTG_ID 0x2012
+MX23_PAD_SSP1_DATA0__JTAG_TDI 0x2022
+MX23_PAD_SSP1_DATA1__JTAG_TCLK 0x2032
+MX23_PAD_SSP1_DATA2__JTAG_RTCK 0x2042
+MX23_PAD_SSP1_DATA3__JTAG_TMS 0x2052
+MX23_PAD_SSP1_SCK__JTAG_TRST 0x2062
+MX23_PAD_ROTARYA__SPDIF 0x2072
+MX23_PAD_ROTARYB__GPMI_CE3N 0x2082
+MX23_PAD_GPMI_D00__GPIO_0_0 0x0003
+MX23_PAD_GPMI_D01__GPIO_0_1 0x0013
+MX23_PAD_GPMI_D02__GPIO_0_2 0x0023
+MX23_PAD_GPMI_D03__GPIO_0_3 0x0033
+MX23_PAD_GPMI_D04__GPIO_0_4 0x0043
+MX23_PAD_GPMI_D05__GPIO_0_5 0x0053
+MX23_PAD_GPMI_D06__GPIO_0_6 0x0063
+MX23_PAD_GPMI_D07__GPIO_0_7 0x0073
+MX23_PAD_GPMI_D08__GPIO_0_8 0x0083
+MX23_PAD_GPMI_D09__GPIO_0_9 0x0093
+MX23_PAD_GPMI_D10__GPIO_0_10 0x00a3
+MX23_PAD_GPMI_D11__GPIO_0_11 0x00b3
+MX23_PAD_GPMI_D12__GPIO_0_12 0x00c3
+MX23_PAD_GPMI_D13__GPIO_0_13 0x00d3
+MX23_PAD_GPMI_D14__GPIO_0_14 0x00e3
+MX23_PAD_GPMI_D15__GPIO_0_15 0x00f3
+MX23_PAD_GPMI_CLE__GPIO_0_16 0x0103
+MX23_PAD_GPMI_ALE__GPIO_0_17 0x0113
+MX23_PAD_GPMI_CE2N__GPIO_0_18 0x0123
+MX23_PAD_GPMI_RDY0__GPIO_0_19 0x0133
+MX23_PAD_GPMI_RDY1__GPIO_0_20 0x0143
+MX23_PAD_GPMI_RDY2__GPIO_0_21 0x0153
+MX23_PAD_GPMI_RDY3__GPIO_0_22 0x0163
+MX23_PAD_GPMI_WPN__GPIO_0_23 0x0173
+MX23_PAD_GPMI_WRN__GPIO_0_24 0x0183
+MX23_PAD_GPMI_RDN__GPIO_0_25 0x0193
+MX23_PAD_AUART1_CTS__GPIO_0_26 0x01a3
+MX23_PAD_AUART1_RTS__GPIO_0_27 0x01b3
+MX23_PAD_AUART1_RX__GPIO_0_28 0x01c3
+MX23_PAD_AUART1_TX__GPIO_0_29 0x01d3
+MX23_PAD_I2C_SCL__GPIO_0_30 0x01e3
+MX23_PAD_I2C_SDA__GPIO_0_31 0x01f3
+MX23_PAD_LCD_D00__GPIO_1_0 0x1003
+MX23_PAD_LCD_D01__GPIO_1_1 0x1013
+MX23_PAD_LCD_D02__GPIO_1_2 0x1023
+MX23_PAD_LCD_D03__GPIO_1_3 0x1033
+MX23_PAD_LCD_D04__GPIO_1_4 0x1043
+MX23_PAD_LCD_D05__GPIO_1_5 0x1053
+MX23_PAD_LCD_D06__GPIO_1_6 0x1063
+MX23_PAD_LCD_D07__GPIO_1_7 0x1073
+MX23_PAD_LCD_D08__GPIO_1_8 0x1083
+MX23_PAD_LCD_D09__GPIO_1_9 0x1093
+MX23_PAD_LCD_D10__GPIO_1_10 0x10a3
+MX23_PAD_LCD_D11__GPIO_1_11 0x10b3
+MX23_PAD_LCD_D12__GPIO_1_12 0x10c3
+MX23_PAD_LCD_D13__GPIO_1_13 0x10d3
+MX23_PAD_LCD_D14__GPIO_1_14 0x10e3
+MX23_PAD_LCD_D15__GPIO_1_15 0x10f3
+MX23_PAD_LCD_D16__GPIO_1_16 0x1103
+MX23_PAD_LCD_D17__GPIO_1_17 0x1113
+MX23_PAD_LCD_RESET__GPIO_1_18 0x1123
+MX23_PAD_LCD_RS__GPIO_1_19 0x1133
+MX23_PAD_LCD_WR__GPIO_1_20 0x1143
+MX23_PAD_LCD_CS__GPIO_1_21 0x1153
+MX23_PAD_LCD_DOTCK__GPIO_1_22 0x1163
+MX23_PAD_LCD_ENABLE__GPIO_1_23 0x1173
+MX23_PAD_LCD_HSYNC__GPIO_1_24 0x1183
+MX23_PAD_LCD_VSYNC__GPIO_1_25 0x1193
+MX23_PAD_PWM0__GPIO_1_26 0x11a3
+MX23_PAD_PWM1__GPIO_1_27 0x11b3
+MX23_PAD_PWM2__GPIO_1_28 0x11c3
+MX23_PAD_PWM3__GPIO_1_29 0x11d3
+MX23_PAD_PWM4__GPIO_1_30 0x11e3
+MX23_PAD_SSP1_CMD__GPIO_2_0 0x2003
+MX23_PAD_SSP1_DETECT__GPIO_2_1 0x2013
+MX23_PAD_SSP1_DATA0__GPIO_2_2 0x2023
+MX23_PAD_SSP1_DATA1__GPIO_2_3 0x2033
+MX23_PAD_SSP1_DATA2__GPIO_2_4 0x2043
+MX23_PAD_SSP1_DATA3__GPIO_2_5 0x2053
+MX23_PAD_SSP1_SCK__GPIO_2_6 0x2063
+MX23_PAD_ROTARYA__GPIO_2_7 0x2073
+MX23_PAD_ROTARYB__GPIO_2_8 0x2083
+MX23_PAD_EMI_A00__GPIO_2_9 0x2093
+MX23_PAD_EMI_A01__GPIO_2_10 0x20a3
+MX23_PAD_EMI_A02__GPIO_2_11 0x20b3
+MX23_PAD_EMI_A03__GPIO_2_12 0x20c3
+MX23_PAD_EMI_A04__GPIO_2_13 0x20d3
+MX23_PAD_EMI_A05__GPIO_2_14 0x20e3
+MX23_PAD_EMI_A06__GPIO_2_15 0x20f3
+MX23_PAD_EMI_A07__GPIO_2_16 0x2103
+MX23_PAD_EMI_A08__GPIO_2_17 0x2113
+MX23_PAD_EMI_A09__GPIO_2_18 0x2123
+MX23_PAD_EMI_A10__GPIO_2_19 0x2133
+MX23_PAD_EMI_A11__GPIO_2_20 0x2143
+MX23_PAD_EMI_A12__GPIO_2_21 0x2153
+MX23_PAD_EMI_BA0__GPIO_2_22 0x2163
+MX23_PAD_EMI_BA1__GPIO_2_23 0x2173
+MX23_PAD_EMI_CASN__GPIO_2_24 0x2183
+MX23_PAD_EMI_CE0N__GPIO_2_25 0x2193
+MX23_PAD_EMI_CE1N__GPIO_2_26 0x21a3
+MX23_PAD_GPMI_CE1N__GPIO_2_27 0x21b3
+MX23_PAD_GPMI_CE0N__GPIO_2_28 0x21c3
+MX23_PAD_EMI_CKE__GPIO_2_29 0x21d3
+MX23_PAD_EMI_RASN__GPIO_2_30 0x21e3
+MX23_PAD_EMI_WEN__GPIO_2_31 0x21f3
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt
new file mode 100644
index 000000000000..c8e578263ce2
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt
@@ -0,0 +1,132 @@
+NVIDIA Tegra20 pinmux controller
+
+Required properties:
+- compatible: "nvidia,tegra20-pinmux"
+- reg: Should contain the register physical address and length for each of
+ the tri-state, mux, pull-up/down, and pad control register sets.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+Tegra's pin configuration nodes act as a container for an abitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, tristate, drive strength, etc.
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function or tristate parameter. For this
+reason, even seemingly boolean values are actually tristates in this binding:
+unspecified, off, or on. Unspecified is represented as an absent property,
+and off/on are represented as integer values 0 and 1.
+
+Required subnode-properties:
+- nvidia,pins : An array of strings. Each string contains the name of a pin or
+ group. Valid values for these names are listed below.
+
+Optional subnode-properties:
+- nvidia,function: A string containing the name of the function to mux to the
+ pin or group. Valid values for function names are listed below. See the Tegra
+ TRM to determine which are valid for each pin or group.
+- nvidia,pull: Integer, representing the pull-down/up to apply to the pin.
+ 0: none, 1: down, 2: up.
+- nvidia,tristate: Integer.
+ 0: drive, 1: tristate.
+- nvidia,high-speed-mode: Integer. Enable high speed mode the pins.
+ 0: no, 1: yes.
+- nvidia,schmitt: Integer. Enables Schmitt Trigger on the input.
+ 0: no, 1: yes.
+- nvidia,low-power-mode: Integer. Valid values 0-3. 0 is least power, 3 is
+ most power. Controls the drive power or current. See "Low Power Mode"
+ or "LPMD1" and "LPMD0" in the Tegra TRM.
+- nvidia,pull-down-strength: Integer. Controls drive strength. 0 is weakest.
+ The range of valid values depends on the pingroup. See "CAL_DRVDN" in the
+ Tegra TRM.
+- nvidia,pull-up-strength: Integer. Controls drive strength. 0 is weakest.
+ The range of valid values depends on the pingroup. See "CAL_DRVUP" in the
+ Tegra TRM.
+- nvidia,slew-rate-rising: Integer. Controls rising signal slew rate. 0 is
+ fastest. The range of valid values depends on the pingroup. See
+ "DRVDN_SLWR" in the Tegra TRM.
+- nvidia,slew-rate-falling: Integer. Controls falling signal slew rate. 0 is
+ fastest. The range of valid values depends on the pingroup. See
+ "DRVUP_SLWF" in the Tegra TRM.
+
+Note that many of these properties are only valid for certain specific pins
+or groups. See the Tegra TRM and various pinmux spreadsheets for complete
+details regarding which groups support which functionality. The Linux pinctrl
+driver may also be a useful reference, since it consolidates, disambiguates,
+and corrects data from all those sources.
+
+Valid values for pin and group names are:
+
+ mux groups:
+
+ These all support nvidia,function, nvidia,tristate, and many support
+ nvidia,pull.
+
+ ata, atb, atc, atd, ate, cdev1, cdev2, crtp, csus, dap1, dap2, dap3, dap4,
+ ddc, dta, dtb, dtc, dtd, dte, dtf, gma, gmb, gmc, gmd, gme, gpu, gpu7,
+ gpv, hdint, i2cp, irrx, irtx, kbca, kbcb, kbcc, kbcd, kbce, kbcf, lcsn,
+ ld0, ld1, ld2, ld3, ld4, ld5, ld6, ld7, ld8, ld9, ld10, ld11, ld12, ld13,
+ ld14, ld15, ld16, ld17, ldc, ldi, lhp0, lhp1, lhp2, lhs, lm0, lm1, lpp,
+ lpw0, lpw1, lpw2, lsc0, lsc1, lsck, lsda, lsdi, lspi, lvp0, lvp1, lvs,
+ owc, pmc, pta, rm, sdb, sdc, sdd, sdio1, slxa, slxc, slxd, slxk, spdi,
+ spdo, spia, spib, spic, spid, spie, spif, spig, spih, uaa, uab, uac, uad,
+ uca, ucb, uda.
+
+ tristate groups:
+
+ These only support nvidia,pull.
+
+ ck32, ddrc, pmca, pmcb, pmcc, pmcd, pmce, xm2c, xm2d, ls, lc, ld17_0,
+ ld19_18, ld21_20, ld23_22.
+
+ drive groups:
+
+ With some exceptions, these support nvidia,high-speed-mode,
+ nvidia,schmitt, nvidia,low-power-mode, nvidia,pull-down-strength,
+ nvidia,pull-up-strength, nvidia,slew_rate-rising, nvidia,slew_rate-falling.
+
+ drive_ao1, drive_ao2, drive_at1, drive_at2, drive_cdev1, drive_cdev2,
+ drive_csus, drive_dap1, drive_dap2, drive_dap3, drive_dap4, drive_dbg,
+ drive_lcd1, drive_lcd2, drive_sdmmc2, drive_sdmmc3, drive_spi, drive_uaa,
+ drive_uab, drive_uart2, drive_uart3, drive_vi1, drive_vi2, drive_xm2a,
+ drive_xm2c, drive_xm2d, drive_xm2clk, drive_sdio1, drive_crt, drive_ddc,
+ drive_gma, drive_gmb, drive_gmc, drive_gmd, drive_gme, drive_owr,
+ drive_uda.
+
+Example:
+
+ pinctrl@70000000 {
+ compatible = "nvidia,tegra20-pinmux";
+ reg = < 0x70000014 0x10 /* Tri-state registers */
+ 0x70000080 0x20 /* Mux registers */
+ 0x700000a0 0x14 /* Pull-up/down registers */
+ 0x70000868 0xa8 >; /* Pad control registers */
+ };
+
+Example board file extract:
+
+ pinctrl@70000000 {
+ sdio4_default: sdio4_default {
+ atb {
+ nvidia,pins = "atb", "gma", "gme";
+ nvidia,function = "sdio4";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
+ };
+ };
+
+ sdhci@c8000600 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio4_default>;
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt
new file mode 100644
index 000000000000..c275b70349c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt
@@ -0,0 +1,132 @@
+NVIDIA Tegra30 pinmux controller
+
+The Tegra30 pinctrl binding is very similar to the Tegra20 pinctrl binding,
+as described in nvidia,tegra20-pinmux.txt. In fact, this document assumes
+that binding as a baseline, and only documents the differences between the
+two bindings.
+
+Required properties:
+- compatible: "nvidia,tegra30-pinmux"
+- reg: Should contain the register physical address and length for each of
+ the pad control and mux registers.
+
+Tegra30 adds the following optional properties for pin configuration subnodes:
+- nvidia,enable-input: Integer. Enable the pin's input path. 0: no, 1: yes.
+- nvidia,open-drain: Integer. Enable open drain mode. 0: no, 1: yes.
+- nvidia,lock: Integer. Lock the pin configuration against further changes
+ until reset. 0: no, 1: yes.
+- nvidia,io-reset: Integer. Reset the IO path. 0: no, 1: yes.
+
+As with Tegra20, see the Tegra TRM for complete details regarding which groups
+support which functionality.
+
+Valid values for pin and group names are:
+
+ per-pin mux groups:
+
+ These all support nvidia,function, nvidia,tristate, nvidia,pull,
+ nvidia,enable-input, nvidia,lock. Some support nvidia,open-drain,
+ nvidia,io-reset.
+
+ clk_32k_out_pa0, uart3_cts_n_pa1, dap2_fs_pa2, dap2_sclk_pa3,
+ dap2_din_pa4, dap2_dout_pa5, sdmmc3_clk_pa6, sdmmc3_cmd_pa7, gmi_a17_pb0,
+ gmi_a18_pb1, lcd_pwr0_pb2, lcd_pclk_pb3, sdmmc3_dat3_pb4, sdmmc3_dat2_pb5,
+ sdmmc3_dat1_pb6, sdmmc3_dat0_pb7, uart3_rts_n_pc0, lcd_pwr1_pc1,
+ uart2_txd_pc2, uart2_rxd_pc3, gen1_i2c_scl_pc4, gen1_i2c_sda_pc5,
+ lcd_pwr2_pc6, gmi_wp_n_pc7, sdmmc3_dat5_pd0, sdmmc3_dat4_pd1, lcd_dc1_pd2,
+ sdmmc3_dat6_pd3, sdmmc3_dat7_pd4, vi_d1_pd5, vi_vsync_pd6, vi_hsync_pd7,
+ lcd_d0_pe0, lcd_d1_pe1, lcd_d2_pe2, lcd_d3_pe3, lcd_d4_pe4, lcd_d5_pe5,
+ lcd_d6_pe6, lcd_d7_pe7, lcd_d8_pf0, lcd_d9_pf1, lcd_d10_pf2, lcd_d11_pf3,
+ lcd_d12_pf4, lcd_d13_pf5, lcd_d14_pf6, lcd_d15_pf7, gmi_ad0_pg0,
+ gmi_ad1_pg1, gmi_ad2_pg2, gmi_ad3_pg3, gmi_ad4_pg4, gmi_ad5_pg5,
+ gmi_ad6_pg6, gmi_ad7_pg7, gmi_ad8_ph0, gmi_ad9_ph1, gmi_ad10_ph2,
+ gmi_ad11_ph3, gmi_ad12_ph4, gmi_ad13_ph5, gmi_ad14_ph6, gmi_ad15_ph7,
+ gmi_wr_n_pi0, gmi_oe_n_pi1, gmi_dqs_pi2, gmi_cs6_n_pi3, gmi_rst_n_pi4,
+ gmi_iordy_pi5, gmi_cs7_n_pi6, gmi_wait_pi7, gmi_cs0_n_pj0, lcd_de_pj1,
+ gmi_cs1_n_pj2, lcd_hsync_pj3, lcd_vsync_pj4, uart2_cts_n_pj5,
+ uart2_rts_n_pj6, gmi_a16_pj7, gmi_adv_n_pk0, gmi_clk_pk1, gmi_cs4_n_pk2,
+ gmi_cs2_n_pk3, gmi_cs3_n_pk4, spdif_out_pk5, spdif_in_pk6, gmi_a19_pk7,
+ vi_d2_pl0, vi_d3_pl1, vi_d4_pl2, vi_d5_pl3, vi_d6_pl4, vi_d7_pl5,
+ vi_d8_pl6, vi_d9_pl7, lcd_d16_pm0, lcd_d17_pm1, lcd_d18_pm2, lcd_d19_pm3,
+ lcd_d20_pm4, lcd_d21_pm5, lcd_d22_pm6, lcd_d23_pm7, dap1_fs_pn0,
+ dap1_din_pn1, dap1_dout_pn2, dap1_sclk_pn3, lcd_cs0_n_pn4, lcd_sdout_pn5,
+ lcd_dc0_pn6, hdmi_int_pn7, ulpi_data7_po0, ulpi_data0_po1, ulpi_data1_po2,
+ ulpi_data2_po3, ulpi_data3_po4, ulpi_data4_po5, ulpi_data5_po6,
+ ulpi_data6_po7, dap3_fs_pp0, dap3_din_pp1, dap3_dout_pp2, dap3_sclk_pp3,
+ dap4_fs_pp4, dap4_din_pp5, dap4_dout_pp6, dap4_sclk_pp7, kb_col0_pq0,
+ kb_col1_pq1, kb_col2_pq2, kb_col3_pq3, kb_col4_pq4, kb_col5_pq5,
+ kb_col6_pq6, kb_col7_pq7, kb_row0_pr0, kb_row1_pr1, kb_row2_pr2,
+ kb_row3_pr3, kb_row4_pr4, kb_row5_pr5, kb_row6_pr6, kb_row7_pr7,
+ kb_row8_ps0, kb_row9_ps1, kb_row10_ps2, kb_row11_ps3, kb_row12_ps4,
+ kb_row13_ps5, kb_row14_ps6, kb_row15_ps7, vi_pclk_pt0, vi_mclk_pt1,
+ vi_d10_pt2, vi_d11_pt3, vi_d0_pt4, gen2_i2c_scl_pt5, gen2_i2c_sda_pt6,
+ sdmmc4_cmd_pt7, pu0, pu1, pu2, pu3, pu4, pu5, pu6, jtag_rtck_pu7, pv0,
+ pv1, pv2, pv3, ddc_scl_pv4, ddc_sda_pv5, crt_hsync_pv6, crt_vsync_pv7,
+ lcd_cs1_n_pw0, lcd_m1_pw1, spi2_cs1_n_pw2, spi2_cs2_n_pw3, clk1_out_pw4,
+ clk2_out_pw5, uart3_txd_pw6, uart3_rxd_pw7, spi2_mosi_px0, spi2_miso_px1,
+ spi2_sck_px2, spi2_cs0_n_px3, spi1_mosi_px4, spi1_sck_px5, spi1_cs0_n_px6,
+ spi1_miso_px7, ulpi_clk_py0, ulpi_dir_py1, ulpi_nxt_py2, ulpi_stp_py3,
+ sdmmc1_dat3_py4, sdmmc1_dat2_py5, sdmmc1_dat1_py6, sdmmc1_dat0_py7,
+ sdmmc1_clk_pz0, sdmmc1_cmd_pz1, lcd_sdin_pz2, lcd_wr_n_pz3, lcd_sck_pz4,
+ sys_clk_req_pz5, pwr_i2c_scl_pz6, pwr_i2c_sda_pz7, sdmmc4_dat0_paa0,
+ sdmmc4_dat1_paa1, sdmmc4_dat2_paa2, sdmmc4_dat3_paa3, sdmmc4_dat4_paa4,
+ sdmmc4_dat5_paa5, sdmmc4_dat6_paa6, sdmmc4_dat7_paa7, pbb0,
+ cam_i2c_scl_pbb1, cam_i2c_sda_pbb2, pbb3, pbb4, pbb5, pbb6, pbb7,
+ cam_mclk_pcc0, pcc1, pcc2, sdmmc4_rst_n_pcc3, sdmmc4_clk_pcc4,
+ clk2_req_pcc5, pex_l2_rst_n_pcc6, pex_l2_clkreq_n_pcc7,
+ pex_l0_prsnt_n_pdd0, pex_l0_rst_n_pdd1, pex_l0_clkreq_n_pdd2,
+ pex_wake_n_pdd3, pex_l1_prsnt_n_pdd4, pex_l1_rst_n_pdd5,
+ pex_l1_clkreq_n_pdd6, pex_l2_prsnt_n_pdd7, clk3_out_pee0, clk3_req_pee1,
+ clk1_req_pee2, hdmi_cec_pee3, clk_32k_in, core_pwr_req, cpu_pwr_req, owr,
+ pwr_int_n.
+
+ drive groups:
+
+ These all support nvidia,pull-down-strength, nvidia,pull-up-strength,
+ nvidia,slew_rate-rising, nvidia,slew_rate-falling. Most but not all
+ support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode.
+
+ ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, cec, crt, csus, dap1,
+ dap2, dap3, dap4, dbg, ddc, dev3, gma, gmb, gmc, gmd, gme, gmf, gmg,
+ gmh, gpv, lcd1, lcd2, owr, sdio1, sdio2, sdio3, spi, uaa, uab, uart2,
+ uart3, uda, vi1.
+
+Example:
+
+ pinctrl@70000000 {
+ compatible = "nvidia,tegra30-pinmux";
+ reg = < 0x70000868 0xd0 /* Pad control registers */
+ 0x70003000 0x3e0 >; /* Mux registers */
+ };
+
+Example board file extract:
+
+ pinctrl@70000000 {
+ sdmmc4_default: pinmux {
+ sdmmc4_clk_pcc4 {
+ nvidia,pins = "sdmmc4_clk_pcc4",
+ "sdmmc4_rst_n_pcc3";
+ nvidia,function = "sdmmc4";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
+ sdmmc4_dat0_paa0 {
+ nvidia,pins = "sdmmc4_dat0_paa0",
+ "sdmmc4_dat1_paa1",
+ "sdmmc4_dat2_paa2",
+ "sdmmc4_dat3_paa3",
+ "sdmmc4_dat4_paa4",
+ "sdmmc4_dat5_paa5",
+ "sdmmc4_dat6_paa6",
+ "sdmmc4_dat7_paa7";
+ nvidia,function = "sdmmc4";
+ nvidia,pull = <2>;
+ nvidia,tristate = <0>;
+ };
+ };
+ };
+
+ sdhci@78000400 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc4_default>;
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
new file mode 100644
index 000000000000..c95ea8278f87
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
@@ -0,0 +1,128 @@
+== Introduction ==
+
+Hardware modules that control pin multiplexing or configuration parameters
+such as pull-up/down, tri-state, drive-strength etc are designated as pin
+controllers. Each pin controller must be represented as a node in device tree,
+just like any other hardware module.
+
+Hardware modules whose signals are affected by pin configuration are
+designated client devices. Again, each client device must be represented as a
+node in device tree, just like any other hardware module.
+
+For a client device to operate correctly, certain pin controllers must
+set up certain specific pin configurations. Some client devices need a
+single static pin configuration, e.g. set up during initialization. Others
+need to reconfigure pins at run-time, for example to tri-state pins when the
+device is inactive. Hence, each client device can define a set of named
+states. The number and names of those states is defined by the client device's
+own binding.
+
+The common pinctrl bindings defined in this file provide an infrastructure
+for client device device tree nodes to map those state names to the pin
+configuration used by those states.
+
+Note that pin controllers themselves may also be client devices of themselves.
+For example, a pin controller may set up its own "active" state when the
+driver loads. This would allow representing a board's static pin configuration
+in a single place, rather than splitting it across multiple client device
+nodes. The decision to do this or not somewhat rests with the author of
+individual board device tree files, and any requirements imposed by the
+bindings for the individual client devices in use by that board, i.e. whether
+they require certain specific named states for dynamic pin configuration.
+
+== Pinctrl client devices ==
+
+For each client device individually, every pin state is assigned an integer
+ID. These numbers start at 0, and are contiguous. For each state ID, a unique
+property exists to define the pin configuration. Each state may also be
+assigned a name. When names are used, another property exists to map from
+those names to the integer IDs.
+
+Each client device's own binding determines the set of states the must be
+defined in its device tree node, and whether to define the set of state
+IDs that must be provided, or whether to define the set of state names that
+must be provided.
+
+Required properties:
+pinctrl-0: List of phandles, each pointing at a pin configuration
+ node. These referenced pin configuration nodes must be child
+ nodes of the pin controller that they configure. Multiple
+ entries may exist in this list so that multiple pin
+ controllers may be configured, or so that a state may be built
+ from multiple nodes for a single pin controller, each
+ contributing part of the overall configuration. See the next
+ section of this document for details of the format of these
+ pin configuration nodes.
+
+ In some cases, it may be useful to define a state, but for it
+ to be empty. This may be required when a common IP block is
+ used in an SoC either without a pin controller, or where the
+ pin controller does not affect the HW module in question. If
+ the binding for that IP block requires certain pin states to
+ exist, they must still be defined, but may be left empty.
+
+Optional properties:
+pinctrl-1: List of phandles, each pointing at a pin configuration
+ node within a pin controller.
+...
+pinctrl-n: List of phandles, each pointing at a pin configuration
+ node within a pin controller.
+pinctrl-names: The list of names to assign states. List entry 0 defines the
+ name for integer state ID 0, list entry 1 for state ID 1, and
+ so on.
+
+For example:
+
+ /* For a client device requiring named states */
+ device {
+ pinctrl-names = "active", "idle";
+ pinctrl-0 = <&state_0_node_a>;
+ pinctrl-1 = <&state_1_node_a &state_1_node_b>;
+ };
+
+ /* For the same device if using state IDs */
+ device {
+ pinctrl-0 = <&state_0_node_a>;
+ pinctrl-1 = <&state_1_node_a &state_1_node_b>;
+ };
+
+ /*
+ * For an IP block whose binding supports pin configuration,
+ * but in use on an SoC that doesn't have any pin control hardware
+ */
+ device {
+ pinctrl-names = "active", "idle";
+ pinctrl-0 = <>;
+ pinctrl-1 = <>;
+ };
+
+== Pin controller devices ==
+
+Pin controller devices should contain the pin configuration nodes that client
+devices reference.
+
+For example:
+
+ pincontroller {
+ ... /* Standard DT properties for the device itself elided */
+
+ state_0_node_a {
+ ...
+ };
+ state_1_node_a {
+ ...
+ };
+ state_1_node_b {
+ ...
+ };
+ }
+
+The contents of each of those pin configuration child nodes is defined
+entirely by the binding for the individual pin controller device. There
+exists no common standard for this content.
+
+The pin configuration nodes need not be direct children of the pin controller
+device; they may be grandchildren, for example. Whether this is legal, and
+whether there is any interaction between the child and intermediate parent
+nodes, is again defined entirely by the binding for the individual pin
+controller device.
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl_spear.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl_spear.txt
new file mode 100644
index 000000000000..3664d37e6799
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl_spear.txt
@@ -0,0 +1,108 @@
+ST Microelectronics, SPEAr pinmux controller
+
+Required properties:
+- compatible : "st,spear300-pinmux"
+ : "st,spear310-pinmux"
+ : "st,spear320-pinmux"
+- reg : Address range of the pinctrl registers
+- st,pinmux-mode: Mandatory for SPEAr300 and SPEAr320 and invalid for others.
+ - Its values for SPEAr300:
+ - NAND_MODE : <0>
+ - NOR_MODE : <1>
+ - PHOTO_FRAME_MODE : <2>
+ - LEND_IP_PHONE_MODE : <3>
+ - HEND_IP_PHONE_MODE : <4>
+ - LEND_WIFI_PHONE_MODE : <5>
+ - HEND_WIFI_PHONE_MODE : <6>
+ - ATA_PABX_WI2S_MODE : <7>
+ - ATA_PABX_I2S_MODE : <8>
+ - CAML_LCDW_MODE : <9>
+ - CAMU_LCD_MODE : <10>
+ - CAMU_WLCD_MODE : <11>
+ - CAML_LCD_MODE : <12>
+ - Its values for SPEAr320:
+ - AUTO_NET_SMII_MODE : <0>
+ - AUTO_NET_MII_MODE : <1>
+ - AUTO_EXP_MODE : <2>
+ - SMALL_PRINTERS_MODE : <3>
+ - EXTENDED_MODE : <4>
+
+Please refer to pinctrl-bindings.txt in this directory for details of the common
+pinctrl bindings used by client devices.
+
+SPEAr's pinmux nodes act as a container for an abitrary number of subnodes. Each
+of these subnodes represents muxing for a pin, a group, or a list of pins or
+groups.
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Required subnode-properties:
+- st,pins : An array of strings. Each string contains the name of a pin or
+ group.
+- st,function: A string containing the name of the function to mux to the pin or
+ group. See the SPEAr's TRM to determine which are valid for each pin or group.
+
+ Valid values for group and function names can be found from looking at the
+ group and function arrays in driver files:
+ drivers/pinctrl/spear/pinctrl-spear3*0.c
+
+Valid values for group names are:
+For All SPEAr3xx machines:
+ "firda_grp", "i2c0_grp", "ssp_cs_grp", "ssp0_grp", "mii0_grp",
+ "gpio0_pin0_grp", "gpio0_pin1_grp", "gpio0_pin2_grp", "gpio0_pin3_grp",
+ "gpio0_pin4_grp", "gpio0_pin5_grp", "uart0_ext_grp", "uart0_grp",
+ "timer_0_1_grp", timer_0_1_pins, "timer_2_3_grp"
+
+For SPEAr300 machines:
+ "fsmc_2chips_grp", "fsmc_4chips_grp", "clcd_lcdmode_grp",
+ "clcd_pfmode_grp", "tdm_grp", "i2c_clk_grp_grp", "caml_grp", "camu_grp",
+ "dac_grp", "i2s_grp", "sdhci_4bit_grp", "sdhci_8bit_grp",
+ "gpio1_0_to_3_grp", "gpio1_4_to_7_grp"
+
+For SPEAr310 machines:
+ "emi_cs_0_to_5_grp", "uart1_grp", "uart2_grp", "uart3_grp", "uart4_grp",
+ "uart5_grp", "fsmc_grp", "rs485_0_grp", "rs485_1_grp", "tdm_grp"
+
+For SPEAr320 machines:
+ "clcd_grp", "emi_grp", "fsmc_8bit_grp", "fsmc_16bit_grp", "spp_grp",
+ "sdhci_led_grp", "sdhci_cd_12_grp", "sdhci_cd_51_grp", "i2s_grp",
+ "uart1_grp", "uart1_modem_2_to_7_grp", "uart1_modem_31_to_36_grp",
+ "uart1_modem_34_to_45_grp", "uart1_modem_80_to_85_grp", "uart2_grp",
+ "uart3_8_9_grp", "uart3_15_16_grp", "uart3_41_42_grp",
+ "uart3_52_53_grp", "uart3_73_74_grp", "uart3_94_95_grp",
+ "uart3_98_99_grp", "uart4_6_7_grp", "uart4_13_14_grp",
+ "uart4_39_40_grp", "uart4_71_72_grp", "uart4_92_93_grp",
+ "uart4_100_101_grp", "uart5_4_5_grp", "uart5_37_38_grp",
+ "uart5_69_70_grp", "uart5_90_91_grp", "uart6_2_3_grp",
+ "uart6_88_89_grp", "rs485_grp", "touchscreen_grp", "can0_grp",
+ "can1_grp", "pwm0_1_pin_8_9_grp", "pwm0_1_pin_14_15_grp",
+ "pwm0_1_pin_30_31_grp", "pwm0_1_pin_37_38_grp", "pwm0_1_pin_42_43_grp",
+ "pwm0_1_pin_59_60_grp", "pwm0_1_pin_88_89_grp", "pwm2_pin_7_grp",
+ "pwm2_pin_13_grp", "pwm2_pin_29_grp", "pwm2_pin_34_grp",
+ "pwm2_pin_41_grp", "pwm2_pin_58_grp", "pwm2_pin_87_grp",
+ "pwm3_pin_6_grp", "pwm3_pin_12_grp", "pwm3_pin_28_grp",
+ "pwm3_pin_40_grp", "pwm3_pin_57_grp", "pwm3_pin_86_grp",
+ "ssp1_17_20_grp", "ssp1_36_39_grp", "ssp1_48_51_grp", "ssp1_65_68_grp",
+ "ssp1_94_97_grp", "ssp2_13_16_grp", "ssp2_32_35_grp", "ssp2_44_47_grp",
+ "ssp2_61_64_grp", "ssp2_90_93_grp", "mii2_grp", "smii0_1_grp",
+ "rmii0_1_grp", "i2c1_8_9_grp", "i2c1_98_99_grp", "i2c2_0_1_grp",
+ "i2c2_2_3_grp", "i2c2_19_20_grp", "i2c2_75_76_grp", "i2c2_96_97_grp"
+
+Valid values for function names are:
+For All SPEAr3xx machines:
+ "firda", "i2c0", "ssp_cs", "ssp0", "mii0", "gpio0", "uart0_ext",
+ "uart0", "timer_0_1", "timer_2_3"
+
+For SPEAr300 machines:
+ "fsmc", "clcd", "tdm", "i2c1", "cam", "dac", "i2s", "sdhci", "gpio1"
+
+For SPEAr310 machines:
+ "emi", "uart1", "uart2", "uart3", "uart4", "uart5", "fsmc", "rs485_0",
+ "rs485_1", "tdm"
+
+For SPEAr320 machines:
+ "clcd", "emi", "fsmc", "spp", "sdhci", "i2s", "uart1", "uart1_modem",
+ "uart2", "uart3", "uart4", "uart5", "uart6", "rs485", "touchscreen",
+ "can0", "can1", "pwm0_1", "pwm2", "pwm3", "ssp1", "ssp2", "mii2",
+ "mii0_1", "i2c1", "i2c2"
diff --git a/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt b/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
deleted file mode 100644
index 36f82dbdd14d..000000000000
--- a/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-NVIDIA Tegra 2 pinmux controller
-
-Required properties:
-- compatible : "nvidia,tegra20-pinmux"
-
diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt
index 9cf57fd042d2..2f5b6b1ba15f 100644
--- a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt
@@ -8,6 +8,8 @@ Optional properties:
- startup-delay-us: startup time in microseconds
- enable-active-high: Polarity of GPIO is Active high
If this property is missing, the default assumed is Active low.
+- gpio-open-drain: GPIO is open drain type.
+ If this property is missing then default assumption is false.
Any property defined as part of the core regulator
binding, defined in regulator.txt, can also be used.
@@ -25,5 +27,6 @@ Example:
gpio = <&gpio1 16 0>;
startup-delay-us = <70000>;
enable-active-high;
- regulator-boot-on
+ regulator-boot-on;
+ gpio-open-drain;
};
diff --git a/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt b/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt
new file mode 100644
index 000000000000..c8ca6b8f6582
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt
@@ -0,0 +1,44 @@
+TPS62360 Voltage regulators
+
+Required properties:
+- compatible: Must be one of the following.
+ "ti,tps62360"
+ "ti,tps62361",
+ "ti,tps62362",
+ "ti,tps62363",
+- reg: I2C slave address
+
+Optional properties:
+- ti,enable-vout-discharge: Enable output discharge. This is boolean value.
+- ti,enable-pull-down: Enable pull down. This is boolean value.
+- ti,vsel0-gpio: GPIO for controlling VSEL0 line.
+ If this property is missing, then assume that there is no GPIO
+ for vsel0 control.
+- ti,vsel1-gpio: Gpio for controlling VSEL1 line.
+ If this property is missing, then assume that there is no GPIO
+ for vsel1 control.
+- ti,vsel0-state-high: Inital state of vsel0 input is high.
+ If this property is missing, then assume the state as low (0).
+- ti,vsel1-state-high: Inital state of vsel1 input is high.
+ If this property is missing, then assume the state as low (0).
+
+Any property defined as part of the core regulator binding, defined in
+regulator.txt, can also be used.
+
+Example:
+
+ abc: tps62360 {
+ compatible = "ti,tps62361";
+ reg = <0x60>;
+ regulator-name = "tps62361-vout";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-boot-on
+ ti,vsel0-gpio = <&gpio1 16 0>;
+ ti,vsel1-gpio = <&gpio1 17 0>;
+ ti,vsel0-state-high;
+ ti,vsel1-state-high;
+ ti,enable-pull-down;
+ ti,enable-force-pwm;
+ ti,enable-vout-discharge;
+ };
diff --git a/Documentation/devicetree/bindings/regulator/tps6586x.txt b/Documentation/devicetree/bindings/regulator/tps6586x.txt
new file mode 100644
index 000000000000..0fcabaa3baa3
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/tps6586x.txt
@@ -0,0 +1,97 @@
+TPS6586x family of regulators
+
+Required properties:
+- compatible: "ti,tps6586x"
+- reg: I2C slave address
+- interrupts: the interrupt outputs of the controller
+- #gpio-cells: number of cells to describe a GPIO
+- gpio-controller: mark the device as a GPIO controller
+- regulators: list of regulators provided by this controller, must be named
+ after their hardware counterparts: sm[0-2], ldo[0-9] and ldo_rtc
+
+Each regulator is defined using the standard binding for regulators.
+
+Example:
+
+ pmu: tps6586x@34 {
+ compatible = "ti,tps6586x";
+ reg = <0x34>;
+ interrupts = <0 88 0x4>;
+
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ regulators {
+ sm0_reg: sm0 {
+ regulator-min-microvolt = < 725000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sm1_reg: sm1 {
+ regulator-min-microvolt = < 725000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sm2_reg: sm2 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <4550000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo0_reg: ldo0 {
+ regulator-name = "PCIE CLK";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo1_reg: ldo1 {
+ regulator-min-microvolt = < 725000>;
+ regulator-max-microvolt = <1500000>;
+ };
+
+ ldo2_reg: ldo2 {
+ regulator-min-microvolt = < 725000>;
+ regulator-max-microvolt = <1500000>;
+ };
+
+ ldo3_reg: ldo3 {
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo4_reg: ldo4 {
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <2475000>;
+ };
+
+ ldo5_reg: ldo5 {
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo6_reg: ldo6 {
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo7_reg: ldo7 {
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo8_reg: ldo8 {
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo9_reg: ldo9 {
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt b/Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt
new file mode 100644
index 000000000000..e4acdd891e49
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt
@@ -0,0 +1,49 @@
+Freescale i.MX audio complex with SGTL5000 codec
+
+Required properties:
+- compatible : "fsl,imx-audio-sgtl5000"
+- model : The user-visible name of this sound complex
+- ssi-controller : The phandle of the i.MX SSI controller
+- audio-codec : The phandle of the SGTL5000 audio codec
+- audio-routing : A list of the connections between audio components.
+ Each entry is a pair of strings, the first being the connection's sink,
+ the second being the connection's source. Valid names could be power
+ supplies, SGTL5000 pins, and the jacks on the board:
+
+ Power supplies:
+ * Mic Bias
+
+ SGTL5000 pins:
+ * MIC_IN
+ * LINE_IN
+ * HP_OUT
+ * LINE_OUT
+
+ Board connectors:
+ * Mic Jack
+ * Line In Jack
+ * Headphone Jack
+ * Line Out Jack
+ * Ext Spk
+
+- mux-int-port : The internal port of the i.MX audio muxer (AUDMUX)
+- mux-ext-port : The external port of the i.MX audio muxer
+
+Note: The AUDMUX port numbering should start at 1, which is consistent with
+hardware manual.
+
+Example:
+
+sound {
+ compatible = "fsl,imx51-babbage-sgtl5000",
+ "fsl,imx-audio-sgtl5000";
+ model = "imx51-babbage-sgtl5000";
+ ssi-controller = <&ssi1>;
+ audio-codec = <&sgtl5000>;
+ audio-routing =
+ "MIC_IN", "Mic Jack",
+ "Mic Jack", "Mic Bias",
+ "Headphone Jack", "HP_OUT";
+ mux-int-port = <1>;
+ mux-ext-port = <3>;
+};
diff --git a/Documentation/devicetree/bindings/sound/mxs-audio-sgtl5000.txt b/Documentation/devicetree/bindings/sound/mxs-audio-sgtl5000.txt
new file mode 100644
index 000000000000..601c518eddaa
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mxs-audio-sgtl5000.txt
@@ -0,0 +1,17 @@
+* Freescale MXS audio complex with SGTL5000 codec
+
+Required properties:
+- compatible: "fsl,mxs-audio-sgtl5000"
+- model: The user-visible name of this sound complex
+- saif-controllers: The phandle list of the MXS SAIF controller
+- audio-codec: The phandle of the SGTL5000 audio codec
+
+Example:
+
+sound {
+ compatible = "fsl,imx28-evk-sgtl5000",
+ "fsl,mxs-audio-sgtl5000";
+ model = "imx28-evk-sgtl5000";
+ saif-controllers = <&saif0 &saif1>;
+ audio-codec = <&sgtl5000>;
+};
diff --git a/Documentation/devicetree/bindings/sound/mxs-saif.txt b/Documentation/devicetree/bindings/sound/mxs-saif.txt
new file mode 100644
index 000000000000..c37ba6143d9b
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mxs-saif.txt
@@ -0,0 +1,36 @@
+* Freescale MXS Serial Audio Interface (SAIF)
+
+Required properties:
+- compatible: Should be "fsl,<chip>-saif"
+- reg: Should contain registers location and length
+- interrupts: Should contain ERROR and DMA interrupts
+- fsl,saif-dma-channel: APBX DMA channel for the SAIF
+
+Optional properties:
+- fsl,saif-master: phandle to the master SAIF. It's only required for
+ the slave SAIF.
+
+Note: Each SAIF controller should have an alias correctly numbered
+in "aliases" node.
+
+Example:
+
+aliases {
+ saif0 = &saif0;
+ saif1 = &saif1;
+};
+
+saif0: saif@80042000 {
+ compatible = "fsl,imx28-saif";
+ reg = <0x80042000 2000>;
+ interrupts = <59 80>;
+ fsl,saif-dma-channel = <4>;
+};
+
+saif1: saif@80046000 {
+ compatible = "fsl,imx28-saif";
+ reg = <0x80046000 2000>;
+ interrupts = <58 81>;
+ fsl,saif-dma-channel = <5>;
+ fsl,saif-master = <&saif0>;
+};
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra30-ahub.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra30-ahub.txt
new file mode 100644
index 000000000000..1ac7b1642186
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra30-ahub.txt
@@ -0,0 +1,32 @@
+NVIDIA Tegra30 AHUB (Audio Hub)
+
+Required properties:
+- compatible : "nvidia,tegra30-ahub"
+- reg : Should contain the register physical address and length for each of
+ the AHUB's APBIF registers and the AHUB's own registers.
+- interrupts : Should contain AHUB interrupt
+- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
+ request selector for the first APBIF channel.
+- ranges : The bus address mapping for the configlink register bus.
+ Can be empty since the mapping is 1:1.
+- #address-cells : For the configlink bus. Should be <1>;
+- #size-cells : For the configlink bus. Should be <1>.
+
+AHUB client modules need to specify the IDs of their CIFs (Client InterFaces).
+For RX CIFs, the numbers indicate the register number within AHUB routing
+register space (APBIF 0..3 RX, I2S 0..5 RX, DAM 0..2 RX 0..1, SPDIF RX 0..1).
+For TX CIFs, the numbers indicate the bit position within the AHUB routing
+registers (APBIF 0..3 TX, I2S 0..5 TX, DAM 0..2 TX, SPDIF TX 0..1).
+
+Example:
+
+ahub@70080000 {
+ compatible = "nvidia,tegra30-ahub";
+ reg = <0x70080000 0x200 0x70080200 0x100>;
+ interrupts = < 0 103 0x04 >;
+ nvidia,dma-request-selector = <&apbdma 1>;
+
+ ranges;
+ #address-cells = <1>;
+ #size-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra30-i2s.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra30-i2s.txt
new file mode 100644
index 000000000000..dfa6c037124a
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra30-i2s.txt
@@ -0,0 +1,15 @@
+NVIDIA Tegra30 I2S controller
+
+Required properties:
+- compatible : "nvidia,tegra30-i2s"
+- reg : Should contain I2S registers location and length
+- nvidia,ahub-cif-ids : The list of AHUB CIF IDs for this port, rx (playback)
+ first, tx (capture) second. See nvidia,tegra30-ahub.txt for values.
+
+Example:
+
+i2s@70002800 {
+ compatible = "nvidia,tegra30-i2s";
+ reg = <0x70080300 0x100>;
+ nvidia,ahub-cif-ids = <4 4>;
+};
diff --git a/Documentation/devicetree/bindings/sound/tegra-audio-trimslice.txt b/Documentation/devicetree/bindings/sound/tegra-audio-trimslice.txt
new file mode 100644
index 000000000000..04b14cfb1f16
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tegra-audio-trimslice.txt
@@ -0,0 +1,14 @@
+NVIDIA Tegra audio complex for TrimSlice
+
+Required properties:
+- compatible : "nvidia,tegra-audio-trimslice"
+- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
+- nvidia,audio-codec : The phandle of the WM8903 audio codec
+
+Example:
+
+sound {
+ compatible = "nvidia,tegra-audio-trimslice";
+ nvidia,i2s-controller = <&tegra_i2s1>;
+ nvidia,audio-codec = <&codec>;
+};
diff --git a/Documentation/devicetree/bindings/sound/tegra-audio-wm8753.txt b/Documentation/devicetree/bindings/sound/tegra-audio-wm8753.txt
new file mode 100644
index 000000000000..c4dd39ce6165
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tegra-audio-wm8753.txt
@@ -0,0 +1,54 @@
+NVIDIA Tegra audio complex
+
+Required properties:
+- compatible : "nvidia,tegra-audio-wm8753"
+- nvidia,model : The user-visible name of this sound complex.
+- nvidia,audio-routing : A list of the connections between audio components.
+ Each entry is a pair of strings, the first being the connection's sink,
+ the second being the connection's source. Valid names for sources and
+ sinks are the WM8753's pins, and the jacks on the board:
+
+ WM8753 pins:
+
+ * LOUT1
+ * LOUT2
+ * ROUT1
+ * ROUT2
+ * MONO1
+ * MONO2
+ * OUT3
+ * OUT4
+ * LINE1
+ * LINE2
+ * RXP
+ * RXN
+ * ACIN
+ * ACOP
+ * MIC1N
+ * MIC1
+ * MIC2N
+ * MIC2
+ * Mic Bias
+
+ Board connectors:
+
+ * Headphone Jack
+ * Mic Jack
+
+- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
+- nvidia,audio-codec : The phandle of the WM8753 audio codec
+Example:
+
+sound {
+ compatible = "nvidia,tegra-audio-wm8753-whistler",
+ "nvidia,tegra-audio-wm8753"
+ nvidia,model = "tegra-wm8753-harmony";
+
+ nvidia,audio-routing =
+ "Headphone Jack", "LOUT1",
+ "Headphone Jack", "ROUT1";
+
+ nvidia,i2s-controller = <&i2s1>;
+ nvidia,audio-codec = <&wm8753>;
+};
+
diff --git a/Documentation/devicetree/bindings/staging/iio/adc/lpc32xx-adc.txt b/Documentation/devicetree/bindings/staging/iio/adc/lpc32xx-adc.txt
new file mode 100644
index 000000000000..b3629d3a9adf
--- /dev/null
+++ b/Documentation/devicetree/bindings/staging/iio/adc/lpc32xx-adc.txt
@@ -0,0 +1,16 @@
+* NXP LPC32xx SoC ADC controller
+
+Required properties:
+- compatible: must be "nxp,lpc3220-adc"
+- reg: physical base address of the controller and length of memory mapped
+ region.
+- interrupts: The ADC interrupt
+
+Example:
+
+ adc@40048000 {
+ compatible = "nxp,lpc3220-adc";
+ reg = <0x40048000 0x1000>;
+ interrupt-parent = <&mic>;
+ interrupts = <39 0>;
+ };
diff --git a/Documentation/devicetree/bindings/staging/iio/adc/spear-adc.txt b/Documentation/devicetree/bindings/staging/iio/adc/spear-adc.txt
new file mode 100644
index 000000000000..02ea23a63f20
--- /dev/null
+++ b/Documentation/devicetree/bindings/staging/iio/adc/spear-adc.txt
@@ -0,0 +1,26 @@
+* ST SPEAr ADC device driver
+
+Required properties:
+- compatible: Should be "st,spear600-adc"
+- reg: Address and length of the register set for the device
+- interrupt-parent: Should be the phandle for the interrupt controller
+ that services interrupts for this device
+- interrupts: Should contain the ADC interrupt
+- sampling-frequency: Default sampling frequency
+
+Optional properties:
+- vref-external: External voltage reference in milli-volts. If omitted
+ the internal voltage reference will be used.
+- average-samples: Number of samples to generate an average value. If
+ omitted, single data conversion will be used.
+
+Examples:
+
+ adc: adc@d8200000 {
+ compatible = "st,spear600-adc";
+ reg = <0xd8200000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <6>;
+ sampling-frequency = <5000000>;
+ vref-external = <2500>; /* 2.5V VRef */
+ };
diff --git a/Documentation/devicetree/bindings/usb/isp1301.txt b/Documentation/devicetree/bindings/usb/isp1301.txt
new file mode 100644
index 000000000000..5405d99d9aaa
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/isp1301.txt
@@ -0,0 +1,25 @@
+* NXP ISP1301 USB transceiver
+
+Required properties:
+- compatible: must be "nxp,isp1301"
+- reg: I2C address of the ISP1301 device
+
+Optional properties of devices using ISP1301:
+- transceiver: phandle of isp1301 - this helps the ISP1301 driver to find the
+ ISP1301 instance associated with the respective USB driver
+
+Example:
+
+ isp1301: usb-transceiver@2c {
+ compatible = "nxp,isp1301";
+ reg = <0x2c>;
+ };
+
+ usbd@31020000 {
+ compatible = "nxp,lpc3220-udc";
+ reg = <0x31020000 0x300>;
+ interrupt-parent = <&mic>;
+ interrupts = <0x3d 0>, <0x3e 0>, <0x3c 0>, <0x3a 0>;
+ transceiver = <&isp1301>;
+ status = "okay";
+ };
diff --git a/Documentation/devicetree/bindings/usb/lpc32xx-udc.txt b/Documentation/devicetree/bindings/usb/lpc32xx-udc.txt
new file mode 100644
index 000000000000..29f12a533f66
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/lpc32xx-udc.txt
@@ -0,0 +1,28 @@
+* NXP LPC32xx SoC USB Device Controller (UDC)
+
+Required properties:
+- compatible: Must be "nxp,lpc3220-udc"
+- reg: Physical base address of the controller and length of memory mapped
+ region.
+- interrupts: The USB interrupts:
+ * USB Device Low Priority Interrupt
+ * USB Device High Priority Interrupt
+ * USB Device DMA Interrupt
+ * External USB Transceiver Interrupt (OTG ATX)
+- transceiver: phandle of the associated ISP1301 device - this is necessary for
+ the UDC controller for connecting to the USB physical layer
+
+Example:
+
+ isp1301: usb-transceiver@2c {
+ compatible = "nxp,isp1301";
+ reg = <0x2c>;
+ };
+
+ usbd@31020000 {
+ compatible = "nxp,lpc3220-udc";
+ reg = <0x31020000 0x300>;
+ interrupt-parent = <&mic>;
+ interrupts = <0x3d 0>, <0x3e 0>, <0x3c 0>, <0x3a 0>;
+ transceiver = <&isp1301>;
+ };
diff --git a/Documentation/devicetree/bindings/usb/ohci-nxp.txt b/Documentation/devicetree/bindings/usb/ohci-nxp.txt
new file mode 100644
index 000000000000..71e28c1017ed
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ohci-nxp.txt
@@ -0,0 +1,24 @@
+* OHCI controller, NXP ohci-nxp variant
+
+Required properties:
+- compatible: must be "nxp,ohci-nxp"
+- reg: physical base address of the controller and length of memory mapped
+ region.
+- interrupts: The OHCI interrupt
+- transceiver: phandle of the associated ISP1301 device - this is necessary for
+ the UDC controller for connecting to the USB physical layer
+
+Example (LPC32xx):
+
+ isp1301: usb-transceiver@2c {
+ compatible = "nxp,isp1301";
+ reg = <0x2c>;
+ };
+
+ ohci@31020000 {
+ compatible = "nxp,ohci-nxp";
+ reg = <0x31020000 0x300>;
+ interrupt-parent = <&mic>;
+ interrupts = <0x3b 0>;
+ transceiver = <&isp1301>;
+ };
diff --git a/Documentation/devicetree/bindings/usb/spear-usb.txt b/Documentation/devicetree/bindings/usb/spear-usb.txt
new file mode 100644
index 000000000000..f8a464a25653
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/spear-usb.txt
@@ -0,0 +1,39 @@
+ST SPEAr SoC USB controllers:
+-----------------------------
+
+EHCI:
+-----
+
+Required properties:
+- compatible: "st,spear600-ehci"
+- interrupt-parent: Should be the phandle for the interrupt controller
+ that services interrupts for this device
+- interrupts: Should contain the EHCI interrupt
+
+Example:
+
+ ehci@e1800000 {
+ compatible = "st,spear600-ehci", "usb-ehci";
+ reg = <0xe1800000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <27>;
+ };
+
+
+OHCI:
+-----
+
+Required properties:
+- compatible: "st,spear600-ohci"
+- interrupt-parent: Should be the phandle for the interrupt controller
+ that services interrupts for this device
+- interrupts: Should contain the OHCI interrupt
+
+Example:
+
+ ohci@e1900000 {
+ compatible = "st,spear600-ohci", "usb-ohci";
+ reg = <0xe1800000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <26>;
+ };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 82ac057a24a9..107d8addf0e4 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -8,6 +8,7 @@ amcc Applied Micro Circuits Corporation (APM, formally AMCC)
apm Applied Micro Circuits Corporation (APM)
arm ARM Ltd.
atmel Atmel Corporation
+bosch Bosch Sensortec GmbH
cavium Cavium, Inc.
chrp Common Hardware Reference Platform
cortina Cortina Systems, Inc.
diff --git a/Documentation/devicetree/bindings/watchdog/pnx4008-wdt.txt b/Documentation/devicetree/bindings/watchdog/pnx4008-wdt.txt
new file mode 100644
index 000000000000..7c7f6887c796
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/pnx4008-wdt.txt
@@ -0,0 +1,13 @@
+* NXP PNX watchdog timer
+
+Required properties:
+- compatible: must be "nxp,pnx4008-wdt"
+- reg: physical base address of the controller and length of memory mapped
+ region.
+
+Example:
+
+ watchdog@4003C000 {
+ compatible = "nxp,pnx4008-wdt";
+ reg = <0x4003C000 0x1000>;
+ };
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 2a596a4fc23e..950856bd2e39 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -276,3 +276,11 @@ REGULATOR
devm_regulator_get()
devm_regulator_put()
devm_regulator_bulk_get()
+
+CLOCK
+ devm_clk_get()
+ devm_clk_put()
+
+PINCTRL
+ devm_pinctrl_get()
+ devm_pinctrl_put()
diff --git a/Documentation/dvb/opera-firmware.txt b/Documentation/dvb/opera-firmware.txt
index 93e784c2607b..fb6683188ef7 100644
--- a/Documentation/dvb/opera-firmware.txt
+++ b/Documentation/dvb/opera-firmware.txt
@@ -8,7 +8,7 @@ from the windriver disk into this directory.
Then run
-./get_dvb_firware opera1
+./get_dvb_firmware opera1
and after that you have 2 files:
@@ -24,4 +24,4 @@ After that the driver can load the firmware
in kernel config and have hotplug running).
-Marco Gittler <g.marco@freenet.de> \ No newline at end of file
+Marco Gittler <g.marco@freenet.de>
diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt
index 74e6c7782678..6e1684981da2 100644
--- a/Documentation/dynamic-debug-howto.txt
+++ b/Documentation/dynamic-debug-howto.txt
@@ -2,17 +2,17 @@
Introduction
============
-This document describes how to use the dynamic debug (ddebug) feature.
+This document describes how to use the dynamic debug (dyndbg) feature.
-Dynamic debug is designed to allow you to dynamically enable/disable kernel
-code to obtain additional kernel information. Currently, if
-CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_dbg() calls can be
-dynamically enabled per-callsite.
+Dynamic debug is designed to allow you to dynamically enable/disable
+kernel code to obtain additional kernel information. Currently, if
+CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_dbg() calls can
+be dynamically enabled per-callsite.
Dynamic debug has even more useful features:
- * Simple query language allows turning on and off debugging statements by
- matching any combination of 0 or 1 of:
+ * Simple query language allows turning on and off debugging
+ statements by matching any combination of 0 or 1 of:
- source filename
- function name
@@ -20,17 +20,19 @@ Dynamic debug has even more useful features:
- module name
- format string
- * Provides a debugfs control file: <debugfs>/dynamic_debug/control which can be
- read to display the complete list of known debug statements, to help guide you
+ * Provides a debugfs control file: <debugfs>/dynamic_debug/control
+ which can be read to display the complete list of known debug
+ statements, to help guide you
Controlling dynamic debug Behaviour
===================================
The behaviour of pr_debug()/dev_dbg()s are controlled via writing to a
-control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs
-filesystem, in order to make use of this feature. Subsequently, we refer to the
-control file as: <debugfs>/dynamic_debug/control. For example, if you want to
-enable printing from source file 'svcsock.c', line 1603 you simply do:
+control file in the 'debugfs' filesystem. Thus, you must first mount
+the debugfs filesystem, in order to make use of this feature.
+Subsequently, we refer to the control file as:
+<debugfs>/dynamic_debug/control. For example, if you want to enable
+printing from source file 'svcsock.c', line 1603 you simply do:
nullarbor:~ # echo 'file svcsock.c line 1603 +p' >
<debugfs>/dynamic_debug/control
@@ -44,15 +46,15 @@ nullarbor:~ # echo 'file svcsock.c wtf 1 +p' >
Viewing Dynamic Debug Behaviour
===========================
-You can view the currently configured behaviour of all the debug statements
-via:
+You can view the currently configured behaviour of all the debug
+statements via:
nullarbor:~ # cat <debugfs>/dynamic_debug/control
# filename:lineno [module]function flags format
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup - "SVCRDMA Module Removed, deregister RPC RDMA transport\012"
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init - "\011max_inline : %d\012"
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init - "\011sq_depth : %d\012"
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init - "\011max_requests : %d\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup =_ "SVCRDMA Module Removed, deregister RPC RDMA transport\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init =_ "\011max_inline : %d\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init =_ "\011sq_depth : %d\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init =_ "\011max_requests : %d\012"
...
@@ -65,12 +67,12 @@ nullarbor:~ # grep -i rdma <debugfs>/dynamic_debug/control | wc -l
nullarbor:~ # grep -i tcp <debugfs>/dynamic_debug/control | wc -l
42
-Note in particular that the third column shows the enabled behaviour
-flags for each debug statement callsite (see below for definitions of the
-flags). The default value, no extra behaviour enabled, is "-". So
-you can view all the debug statement callsites with any non-default flags:
+The third column shows the currently enabled flags for each debug
+statement callsite (see below for definitions of the flags). The
+default value, with no flags enabled, is "=_". So you can view all
+the debug statement callsites with any non-default flags:
-nullarbor:~ # awk '$3 != "-"' <debugfs>/dynamic_debug/control
+nullarbor:~ # awk '$3 != "=_"' <debugfs>/dynamic_debug/control
# filename:lineno [module]function flags format
/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process: st_sendto returned %d\012"
@@ -103,15 +105,14 @@ specifications, followed by a flags change specification.
command ::= match-spec* flags-spec
-The match-spec's are used to choose a subset of the known dprintk()
+The match-spec's are used to choose a subset of the known pr_debug()
callsites to which to apply the flags-spec. Think of them as a query
with implicit ANDs between each pair. Note that an empty list of
-match-specs is possible, but is not very useful because it will not
-match any debug statement callsites.
+match-specs will select all debug statement callsites.
-A match specification comprises a keyword, which controls the attribute
-of the callsite to be compared, and a value to compare against. Possible
-keywords are:
+A match specification comprises a keyword, which controls the
+attribute of the callsite to be compared, and a value to compare
+against. Possible keywords are:
match-spec ::= 'func' string |
'file' string |
@@ -164,15 +165,15 @@ format
characters (") or single quote characters (').
Examples:
- format svcrdma: // many of the NFS/RDMA server dprintks
- format readahead // some dprintks in the readahead cache
+ format svcrdma: // many of the NFS/RDMA server pr_debugs
+ format readahead // some pr_debugs in the readahead cache
format nfsd:\040SETATTR // one way to match a format with whitespace
format "nfsd: SETATTR" // a neater way to match a format with whitespace
format 'nfsd: SETATTR' // yet another way to match a format with whitespace
line
The given line number or range of line numbers is compared
- against the line number of each dprintk() callsite. A single
+ against the line number of each pr_debug() callsite. A single
line number matches the callsite line number exactly. A
range of line numbers matches any callsite between the first
and last line number inclusive. An empty first number means
@@ -188,51 +189,93 @@ The flags specification comprises a change operation followed
by one or more flag characters. The change operation is one
of the characters:
--
- remove the given flags
-
-+
- add the given flags
-
-=
- set the flags to the given flags
+ - remove the given flags
+ + add the given flags
+ = set the flags to the given flags
The flags are:
-f
- Include the function name in the printed message
-l
- Include line number in the printed message
-m
- Include module name in the printed message
-p
- Causes a printk() message to be emitted to dmesg
-t
- Include thread ID in messages not generated from interrupt context
+ p enables the pr_debug() callsite.
+ f Include the function name in the printed message
+ l Include line number in the printed message
+ m Include module name in the printed message
+ t Include thread ID in messages not generated from interrupt context
+ _ No flags are set. (Or'd with others on input)
+
+For display, the flags are preceded by '='
+(mnemonic: what the flags are currently equal to).
-Note the regexp ^[-+=][flmpt]+$ matches a flags specification.
-Note also that there is no convenient syntax to remove all
-the flags at once, you need to use "-flmpt".
+Note the regexp ^[-+=][flmpt_]+$ matches a flags specification.
+To clear all flags at once, use "=_" or "-flmpt".
-Debug messages during boot process
+Debug messages during Boot Process
==================================
-To be able to activate debug messages during the boot process,
-even before userspace and debugfs exists, use the boot parameter:
-ddebug_query="QUERY"
+To activate debug messages for core code and built-in modules during
+the boot process, even before userspace and debugfs exists, use
+dyndbg="QUERY", module.dyndbg="QUERY", or ddebug_query="QUERY"
+(ddebug_query is obsoleted by dyndbg, and deprecated). QUERY follows
+the syntax described above, but must not exceed 1023 characters. Your
+bootloader may impose lower limits.
+
+These dyndbg params are processed just after the ddebug tables are
+processed, as part of the arch_initcall. Thus you can enable debug
+messages in all code run after this arch_initcall via this boot
+parameter.
-QUERY follows the syntax described above, but must not exceed 1023
-characters. The enablement of debug messages is done as an arch_initcall.
-Thus you can enable debug messages in all code processed after this
-arch_initcall via this boot parameter.
On an x86 system for example ACPI enablement is a subsys_initcall and
-ddebug_query="file ec.c +p"
+ dyndbg="file ec.c +p"
will show early Embedded Controller transactions during ACPI setup if
your machine (typically a laptop) has an Embedded Controller.
PCI (or other devices) initialization also is a hot candidate for using
this boot parameter for debugging purposes.
+If foo module is not built-in, foo.dyndbg will still be processed at
+boot time, without effect, but will be reprocessed when module is
+loaded later. dyndbg_query= and bare dyndbg= are only processed at
+boot.
+
+
+Debug Messages at Module Initialization Time
+============================================
+
+When "modprobe foo" is called, modprobe scans /proc/cmdline for
+foo.params, strips "foo.", and passes them to the kernel along with
+params given in modprobe args or /etc/modprob.d/*.conf files,
+in the following order:
+
+1. # parameters given via /etc/modprobe.d/*.conf
+ options foo dyndbg=+pt
+ options foo dyndbg # defaults to +p
+
+2. # foo.dyndbg as given in boot args, "foo." is stripped and passed
+ foo.dyndbg=" func bar +p; func buz +mp"
+
+3. # args to modprobe
+ modprobe foo dyndbg==pmf # override previous settings
+
+These dyndbg queries are applied in order, with last having final say.
+This allows boot args to override or modify those from /etc/modprobe.d
+(sensible, since 1 is system wide, 2 is kernel or boot specific), and
+modprobe args to override both.
+
+In the foo.dyndbg="QUERY" form, the query must exclude "module foo".
+"foo" is extracted from the param-name, and applied to each query in
+"QUERY", and only 1 match-spec of each type is allowed.
+
+The dyndbg option is a "fake" module parameter, which means:
+
+- modules do not need to define it explicitly
+- every module gets it tacitly, whether they use pr_debug or not
+- it doesnt appear in /sys/module/$module/parameters/
+ To see it, grep the control file, or inspect /proc/cmdline.
+
+For CONFIG_DYNAMIC_DEBUG kernels, any settings given at boot-time (or
+enabled by -DDEBUG flag during compilation) can be disabled later via
+the sysfs interface if the debug messages are no longer needed:
+
+ echo "module module_name -p" > <debugfs>/dynamic_debug/control
Examples
========
@@ -260,3 +303,18 @@ nullarbor:~ # echo -n 'func svc_process -p' >
// enable messages for NFS calls READ, READLINK, READDIR and READDIR+.
nullarbor:~ # echo -n 'format "nfsd: READ" +p' >
<debugfs>/dynamic_debug/control
+
+// enable all messages
+nullarbor:~ # echo -n '+p' > <debugfs>/dynamic_debug/control
+
+// add module, function to all enabled messages
+nullarbor:~ # echo -n '+mf' > <debugfs>/dynamic_debug/control
+
+// boot-args example, with newlines and comments for readability
+Kernel command line: ...
+ // see whats going on in dyndbg=value processing
+ dynamic_debug.verbose=1
+ // enable pr_debugs in 2 builtins, #cmt is stripped
+ dyndbg="module params +p #cmt ; module sys +p"
+ // enable pr_debugs in 2 functions in a module loaded later
+ pc87360.dyndbg="func pc87360_init_device +p; func pc87360_find +p"
diff --git a/Documentation/edac.txt b/Documentation/edac.txt
index fdcc49fad8e1..03df2b020332 100644
--- a/Documentation/edac.txt
+++ b/Documentation/edac.txt
@@ -734,7 +734,7 @@ were done at i7core_edac driver. This chapter will cover those differences
associated with a physical CPU socket.
Each MC have 3 physical read channels, 3 physical write channels and
- 3 logic channels. The driver currenty sees it as just 3 channels.
+ 3 logic channels. The driver currently sees it as just 3 channels.
Each channel can have up to 3 DIMMs.
The minimum known unity is DIMMs. There are no information about csrows.
diff --git a/Documentation/extcon/porting-android-switch-class b/Documentation/extcon/porting-android-switch-class
new file mode 100644
index 000000000000..eb0fa5f4fe88
--- /dev/null
+++ b/Documentation/extcon/porting-android-switch-class
@@ -0,0 +1,124 @@
+
+ Staging/Android Switch Class Porting Guide
+ (linux/drivers/staging/android/switch)
+ (c) Copyright 2012 Samsung Electronics
+
+AUTHORS
+MyungJoo Ham <myungjoo.ham@samsung.com>
+
+/*****************************************************************
+ * CHAPTER 1. *
+ * PORTING SWITCH CLASS DEVICE DRIVERS *
+ *****************************************************************/
+
+****** STEP 1. Basic Functionality
+ No extcon extended feature, but switch features only.
+
+- struct switch_dev (fed to switch_dev_register/unregister)
+ @name: no change
+ @dev: no change
+ @index: drop (not used in switch device driver side anyway)
+ @state: no change
+ If you have used @state with magic numbers, keep it
+ at this step.
+ @print_name: no change but type change (switch_dev->extcon_dev)
+ @print_state: no change but type change (switch_dev->extcon_dev)
+
+- switch_dev_register(sdev, dev)
+ => extcon_dev_register(edev, dev)
+ : no change but type change (sdev->edev)
+- switch_dev_unregister(sdev)
+ => extcon_dev_unregister(edev)
+ : no change but type change (sdev->edev)
+- switch_get_state(sdev)
+ => extcon_get_state(edev)
+ : no change but type change (sdev->edev) and (return: int->u32)
+- switch_set_state(sdev, state)
+ => extcon_set_state(edev, state)
+ : no change but type change (sdev->edev) and (state: int->u32)
+
+With this changes, the ex-switch extcon class device works as it once
+worked as switch class device. However, it will now have additional
+interfaces (both ABI and in-kernel API) and different ABI locations.
+However, if CONFIG_ANDROID is enabled without CONFIG_ANDROID_SWITCH,
+/sys/class/switch/* will be symbolically linked to /sys/class/extcon/
+so that they are still compatible with legacy userspace processes.
+
+****** STEP 2. Multistate (no more magic numbers in state value)
+ Extcon's extended features for switch device drivers with
+ complex features usually required magic numbers in state
+ value of switch_dev. With extcon, such magic numbers that
+ support multiple cables (
+
+ 1. Define cable names at edev->supported_cable.
+ 2. (Recommended) remove print_state callback.
+ 3. Use extcon_get_cable_state_(edev, index) or
+ extcon_get_cable_state(edev, cable_name) instead of
+ extcon_get_state(edev) if you intend to get a state of a specific
+ cable. Same for set_state. This way, you can remove the usage of
+ magic numbers in state value.
+ 4. Use extcon_update_state() if you are updating specific bits of
+ the state value.
+
+Example: a switch device driver w/ magic numbers for two cables.
+ "0x00": no cables connected.
+ "0x01": cable 1 connected
+ "0x02": cable 2 connected
+ "0x03": cable 1 and 2 connected
+ 1. edev->supported_cable = {"1", "2", NULL};
+ 2. edev->print_state = NULL;
+ 3. extcon_get_cable_state_(edev, 0) shows cable 1's state.
+ extcon_get_cable_state(edev, "1") shows cable 1's state.
+ extcon_set_cable_state_(edev, 1) sets cable 2's state.
+ extcon_set_cable_state(edev, "2") sets cable 2's state
+ 4. extcon_update_state(edev, 0x01, 0) sets the least bit's 0.
+
+****** STEP 3. Notify other device drivers
+
+ You can notify others of the cable attach/detach events with
+notifier chains.
+
+ At the side of other device drivers (the extcon device itself
+does not need to get notified of its own events), there are two
+methods to register notifier_block for cable events:
+(a) for a specific cable or (b) for every cable.
+
+ (a) extcon_register_interest(obj, extcon_name, cable_name, nb)
+ Example: want to get news of "MAX8997_MUIC"'s "USB" cable
+
+ obj = kzalloc(sizeof(struct extcon_specific_cable_nb),
+ GFP_KERNEL);
+ nb->notifier_call = the_callback_to_handle_usb;
+
+ extcon_register_intereset(obj, "MAX8997_MUIC", "USB", nb);
+
+ (b) extcon_register_notifier(edev, nb)
+ Call nb for any changes in edev.
+
+ Please note that in order to properly behave with method (a),
+the extcon device driver should support multistate feature (STEP 2).
+
+****** STEP 4. Inter-cable relation (mutually exclusive)
+
+ You can provide inter-cable mutually exclusiveness information
+for an extcon device. When cables A and B are declared to be mutually
+exclusive, the two cables cannot be in ATTACHED state simulteneously.
+
+
+/*****************************************************************
+ * CHAPTER 2. *
+ * PORTING USERSPACE w/ SWITCH CLASS DEVICE SUPPORT *
+ *****************************************************************/
+
+****** ABI Location
+
+ If "CONFIG_ANDROID" is enabled and "CONFIG_ANDROID_SWITCH" is
+disabled, /sys/class/switch/* are created as symbolic links to
+/sys/class/extcon/*. Because CONFIG_ANDROID_SWITCH creates
+/sys/class/switch directory, we disable symboling linking if
+CONFIG_ANDROID_SWITCH is enabled.
+
+ The two files of switch class, name and state, are provided with
+extcon, too. When the multistate support (STEP 2 of CHAPTER 1.) is
+not enabled or print_state callback is supplied, the output of
+state ABI is same with switch class.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index e4b57756b9f5..1e69a81e99d4 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -2,7 +2,14 @@ The following is a list of files and features that are going to be
removed in the kernel source tree. Every entry should contain what
exactly is going away, why it is happening, and who is going to be doing
the work. When the feature is removed from the kernel, it should also
-be removed from this file.
+be removed from this file. The suggested deprecation period is 3 releases.
+
+---------------------------
+
+What: ddebug_query="query" boot cmdline param
+When: v3.8
+Why: obsoleted by dyndbg="query" and module.dyndbg="query"
+Who: Jim Cromie <jim.cromie@gmail.com>, Jason Baron <jbaron@redhat.com>
---------------------------
@@ -549,3 +556,14 @@ Why: The V4L2_CID_VCENTER, V4L2_CID_HCENTER controls have been deprecated
There are newer controls (V4L2_CID_PAN*, V4L2_CID_TILT*) that provide
similar functionality.
Who: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
+
+----------------------------
+
+What: cgroup option updates via remount
+When: March 2013
+Why: Remount currently allows changing bound subsystems and
+ release_agent. Rebinding is hardly useful as it only works
+ when the hierarchy is empty and release_agent itself should be
+ replaced with conventional fsnotify.
+
+----------------------------
diff --git a/Documentation/filesystems/gfs2-glocks.txt b/Documentation/filesystems/gfs2-glocks.txt
index 0494f78d87e4..fcc79957be63 100644
--- a/Documentation/filesystems/gfs2-glocks.txt
+++ b/Documentation/filesystems/gfs2-glocks.txt
@@ -61,7 +61,9 @@ go_unlock | Called on the final local unlock of a lock
go_dump | Called to print content of object for debugfs file, or on
| error to dump glock to the log.
go_type | The type of the glock, LM_TYPE_.....
-go_min_hold_time | The minimum hold time
+go_callback | Called if the DLM sends a callback to drop this lock
+go_flags | GLOF_ASPACE is set, if the glock has an address space
+ | associated with it
The minimum hold time for each lock is the time after a remote lock
grant for which we ignore remote demote requests. This is in order to
@@ -89,6 +91,7 @@ go_demote_ok | Sometimes | Yes
go_lock | Yes | No
go_unlock | Yes | No
go_dump | Sometimes | Yes
+go_callback | Sometimes (N/A) | Yes
N.B. Operations must not drop either the bit lock or the spinlock
if its held on entry. go_dump and do_demote_ok must never block.
@@ -111,4 +114,118 @@ itself (locking order as above), and the other, known as the iopen
glock is used in conjunction with the i_nlink field in the inode to
determine the lifetime of the inode in question. Locking of inodes
is on a per-inode basis. Locking of rgrps is on a per rgrp basis.
+In general we prefer to lock local locks prior to cluster locks.
+
+ Glock Statistics
+ ------------------
+
+The stats are divided into two sets: those relating to the
+super block and those relating to an individual glock. The
+super block stats are done on a per cpu basis in order to
+try and reduce the overhead of gathering them. They are also
+further divided by glock type. All timings are in nanoseconds.
+
+In the case of both the super block and glock statistics,
+the same information is gathered in each case. The super
+block timing statistics are used to provide default values for
+the glock timing statistics, so that newly created glocks
+should have, as far as possible, a sensible starting point.
+The per-glock counters are initialised to zero when the
+glock is created. The per-glock statistics are lost when
+the glock is ejected from memory.
+
+The statistics are divided into three pairs of mean and
+variance, plus two counters. The mean/variance pairs are
+smoothed exponential estimates and the algorithm used is
+one which will be very familiar to those used to calculation
+of round trip times in network code. See "TCP/IP Illustrated,
+Volume 1", W. Richard Stevens, sect 21.3, "Round-Trip Time Measurement",
+p. 299 and onwards. Also, Volume 2, Sect. 25.10, p. 838 and onwards.
+Unlike the TCP/IP Illustrated case, the mean and variance are
+not scaled, but are in units of integer nanoseconds.
+
+The three pairs of mean/variance measure the following
+things:
+
+ 1. DLM lock time (non-blocking requests)
+ 2. DLM lock time (blocking requests)
+ 3. Inter-request time (again to the DLM)
+
+A non-blocking request is one which will complete right
+away, whatever the state of the DLM lock in question. That
+currently means any requests when (a) the current state of
+the lock is exclusive, i.e. a lock demotion (b) the requested
+state is either null or unlocked (again, a demotion) or (c) the
+"try lock" flag is set. A blocking request covers all the other
+lock requests.
+
+There are two counters. The first is there primarily to show
+how many lock requests have been made, and thus how much data
+has gone into the mean/variance calculations. The other counter
+is counting queuing of holders at the top layer of the glock
+code. Hopefully that number will be a lot larger than the number
+of dlm lock requests issued.
+
+So why gather these statistics? There are several reasons
+we'd like to get a better idea of these timings:
+
+1. To be able to better set the glock "min hold time"
+2. To spot performance issues more easily
+3. To improve the algorithm for selecting resource groups for
+allocation (to base it on lock wait time, rather than blindly
+using a "try lock")
+
+Due to the smoothing action of the updates, a step change in
+some input quantity being sampled will only fully be taken
+into account after 8 samples (or 4 for the variance) and this
+needs to be carefully considered when interpreting the
+results.
+
+Knowing both the time it takes a lock request to complete and
+the average time between lock requests for a glock means we
+can compute the total percentage of the time for which the
+node is able to use a glock vs. time that the rest of the
+cluster has its share. That will be very useful when setting
+the lock min hold time.
+
+Great care has been taken to ensure that we
+measure exactly the quantities that we want, as accurately
+as possible. There are always inaccuracies in any
+measuring system, but I hope this is as accurate as we
+can reasonably make it.
+
+Per sb stats can be found here:
+/sys/kernel/debug/gfs2/<fsname>/sbstats
+Per glock stats can be found here:
+/sys/kernel/debug/gfs2/<fsname>/glstats
+
+Assuming that debugfs is mounted on /sys/kernel/debug and also
+that <fsname> is replaced with the name of the gfs2 filesystem
+in question.
+
+The abbreviations used in the output as are follows:
+
+srtt - Smoothed round trip time for non-blocking dlm requests
+srttvar - Variance estimate for srtt
+srttb - Smoothed round trip time for (potentially) blocking dlm requests
+srttvarb - Variance estimate for srttb
+sirt - Smoothed inter-request time (for dlm requests)
+sirtvar - Variance estimate for sirt
+dlm - Number of dlm requests made (dcnt in glstats file)
+queue - Number of glock requests queued (qcnt in glstats file)
+
+The sbstats file contains a set of these stats for each glock type (so 8 lines
+for each type) and for each cpu (one column per cpu). The glstats file contains
+a set of these stats for each glock in a similar format to the glocks file, but
+using the format mean/variance for each of the timing stats.
+
+The gfs2_glock_lock_time tracepoint prints out the current values of the stats
+for the glock in question, along with some addition information on each dlm
+reply that is received:
+
+status - The status of the dlm request
+flags - The dlm request flags
+tdiff - The time taken by this specific request
+(remaining fields as per above list)
+
diff --git a/Documentation/filesystems/gfs2.txt b/Documentation/filesystems/gfs2.txt
index 4cda926628aa..cc4f2306609e 100644
--- a/Documentation/filesystems/gfs2.txt
+++ b/Documentation/filesystems/gfs2.txt
@@ -1,7 +1,7 @@
Global File System
------------------
-http://sources.redhat.com/cluster/wiki/
+https://fedorahosted.org/cluster/wiki/HomePage
GFS is a cluster file system. It allows a cluster of computers to
simultaneously use a block device that is shared between them (with FC,
@@ -30,7 +30,8 @@ needed, simply:
If you are using Fedora, you need to install the gfs2-utils package
and, for lock_dlm, you will also need to install the cman package
-and write a cluster.conf as per the documentation.
+and write a cluster.conf as per the documentation. For F17 and above
+cman has been replaced by the dlm package.
GFS2 is not on-disk compatible with previous versions of GFS, but it
is pretty close.
@@ -39,8 +40,6 @@ The following man pages can be found at the URL above:
fsck.gfs2 to repair a filesystem
gfs2_grow to expand a filesystem online
gfs2_jadd to add journals to a filesystem online
- gfs2_tool to manipulate, examine and tune a filesystem
- gfs2_quota to examine and change quota values in a filesystem
+ tunegfs2 to manipulate, examine and tune a filesystem
gfs2_convert to convert a gfs filesystem to gfs2 in-place
- mount.gfs2 to help mount(8) mount a filesystem
mkfs.gfs2 to make a filesystem
diff --git a/Documentation/filesystems/nfs/pnfs.txt b/Documentation/filesystems/nfs/pnfs.txt
index c7919c6e3bea..52ae07f5f578 100644
--- a/Documentation/filesystems/nfs/pnfs.txt
+++ b/Documentation/filesystems/nfs/pnfs.txt
@@ -93,7 +93,7 @@ The API to the login script is as follows:
(allways exists)
(More protocols can be defined in the future.
The client does not interpret this string it is
- passed unchanged as recieved from the Server)
+ passed unchanged as received from the Server)
-o osdname of the requested target OSD
(Might be empty)
(A string which denotes the OSD name, there is a
diff --git a/Documentation/filesystems/qnx6.txt b/Documentation/filesystems/qnx6.txt
index 050223ea03c7..e59f2f09f56e 100644
--- a/Documentation/filesystems/qnx6.txt
+++ b/Documentation/filesystems/qnx6.txt
@@ -17,7 +17,7 @@ concepts of blocks, inodes and directories.
On QNX it is possible to create little endian and big endian qnx6 filesystems.
This feature makes it possible to create and use a different endianness fs
for the target (QNX is used on quite a range of embedded systems) plattform
-running on a different endianess.
+running on a different endianness.
The Linux driver handles endianness transparently. (LE and BE)
Blocks
@@ -26,7 +26,7 @@ Blocks
The space in the device or file is split up into blocks. These are a fixed
size of 512, 1024, 2048 or 4096, which is decided when the filesystem is
created.
-Blockpointers are 32bit, so the maximum space that can be adressed is
+Blockpointers are 32bit, so the maximum space that can be addressed is
2^32 * 4096 bytes or 16TB
The superblocks
@@ -47,16 +47,16 @@ inactive superblock.
Each superblock holds a set of root inodes for the different filesystem
parts. (Inode, Bitmap and Longfilenames)
Each of these root nodes holds information like total size of the stored
-data and the adressing levels in that specific tree.
-If the level value is 0, up to 16 direct blocks can be adressed by each
+data and the addressing levels in that specific tree.
+If the level value is 0, up to 16 direct blocks can be addressed by each
node.
-Level 1 adds an additional indirect adressing level where each indirect
-adressing block holds up to blocksize / 4 bytes pointers to data blocks.
-Level 2 adds an additional indirect adressig block level (so, already up
-to 16 * 256 * 256 = 1048576 blocks that can be adressed by such a tree)a
+Level 1 adds an additional indirect addressing level where each indirect
+addressing block holds up to blocksize / 4 bytes pointers to data blocks.
+Level 2 adds an additional indirect addressing block level (so, already up
+to 16 * 256 * 256 = 1048576 blocks that can be addressed by such a tree).
Unused block pointers are always set to ~0 - regardless of root node,
-indirect adressing blocks or inodes.
+indirect addressing blocks or inodes.
Data leaves are always on the lowest level. So no data is stored on upper
tree levels.
@@ -64,7 +64,7 @@ The first Superblock is located at 0x2000. (0x2000 is the bootblock size)
The Audi MMI 3G first superblock directly starts at byte 0.
Second superblock position can either be calculated from the superblock
information (total number of filesystem blocks) or by taking the highest
-device address, zeroing the last 3 bytes and then substracting 0x1000 from
+device address, zeroing the last 3 bytes and then subtracting 0x1000 from
that address.
0x1000 is the size reserved for each superblock - regardless of the
@@ -83,8 +83,8 @@ size, number of blocks used, access time, change time and modification time.
Object mode field is POSIX format. (which makes things easier)
There are also pointers to the first 16 blocks, if the object data can be
-adressed with 16 direct blocks.
-For more than 16 blocks an indirect adressing in form of another tree is
+addressed with 16 direct blocks.
+For more than 16 blocks an indirect addressing in form of another tree is
used. (scheme is the same as the one used for the superblock root nodes)
The filesize is stored 64bit. Inode counting starts with 1. (whilst long
@@ -118,13 +118,13 @@ no block pointers and the directory file record pointing to the target file
inode.
Character and block special devices do not exist in QNX as those files
-are handled by the QNX kernel/drivers and created in /dev independant of the
+are handled by the QNX kernel/drivers and created in /dev independent of the
underlaying filesystem.
Long filenames
--------------
-Long filenames are stored in a seperate adressing tree. The staring point
+Long filenames are stored in a separate addressing tree. The staring point
is the longfilename root node in the active superblock.
Each data block (tree leaves) holds one long filename. That filename is
limited to 510 bytes. The first two starting bytes are used as length field
diff --git a/Documentation/hwmon/ina2xx b/Documentation/hwmon/ina2xx
new file mode 100644
index 000000000000..f50a6cc27616
--- /dev/null
+++ b/Documentation/hwmon/ina2xx
@@ -0,0 +1,29 @@
+Kernel driver ina2xx
+====================
+
+Supported chips:
+ * Texas Instruments INA219
+ Prefix: 'ina219'
+ Addresses: I2C 0x40 - 0x4f
+ Datasheet: Publicly available at the Texas Instruments website
+ http://www.ti.com/
+
+ * Texas Instruments INA226
+ Prefix: 'ina226'
+ Addresses: I2C 0x40 - 0x4f
+ Datasheet: Publicly available at the Texas Instruments website
+ http://www.ti.com/
+
+Author: Lothar Felten <l-felten@ti.com>
+
+Description
+-----------
+
+The INA219 is a high-side current shunt and power monitor with an I2C
+interface. The INA219 monitors both shunt drop and supply voltage, with
+programmable conversion times and filtering.
+
+The INA226 is a current shunt and power monitor with an I2C interface.
+The INA226 monitors both a shunt voltage drop and bus supply voltage.
+
+The shunt value in micro-ohms can be set via platform data.
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index 23b7def21ba8..87850d86c559 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -30,6 +30,14 @@ Supported chips:
Prefix: 'it8728'
Addresses scanned: from Super I/O config space (8 I/O ports)
Datasheet: Not publicly available
+ * IT8782F
+ Prefix: 'it8782'
+ Addresses scanned: from Super I/O config space (8 I/O ports)
+ Datasheet: Not publicly available
+ * IT8783E/F
+ Prefix: 'it8783'
+ Addresses scanned: from Super I/O config space (8 I/O ports)
+ Datasheet: Not publicly available
* SiS950 [clone of IT8705F]
Prefix: 'it87'
Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -63,7 +71,7 @@ Module Parameters
Hardware Interfaces
-------------------
-All the chips suported by this driver are LPC Super-I/O chips, accessed
+All the chips supported by this driver are LPC Super-I/O chips, accessed
through the LPC bus (ISA-like I/O ports). The IT8712F additionally has an
SMBus interface to the hardware monitoring functions. This driver no
longer supports this interface though, as it is slower and less reliable
@@ -75,7 +83,8 @@ Description
-----------
This driver implements support for the IT8705F, IT8712F, IT8716F,
-IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E and SiS950 chips.
+IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E, IT8781F, IT8782F,
+IT8783E/F, and SiS950 chips.
These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
joysticks and other miscellaneous stuff. For hardware monitoring, they
@@ -99,11 +108,11 @@ The IT8716F, IT8718F, IT8720F, IT8721F/IT8758E and later IT8712F revisions
have support for 2 additional fans. The additional fans are supported by the
driver.
-The IT8716F, IT8718F, IT8720F and IT8721F/IT8758E, and late IT8712F and
-IT8705F also have optional 16-bit tachometer counters for fans 1 to 3. This
-is better (no more fan clock divider mess) but not compatible with the older
-chips and revisions. The 16-bit tachometer mode is enabled by the driver when
-one of the above chips is detected.
+The IT8716F, IT8718F, IT8720F, IT8721F/IT8758E, IT8782F, IT8783E/F, and late
+IT8712F and IT8705F also have optional 16-bit tachometer counters for fans 1 to
+3. This is better (no more fan clock divider mess) but not compatible with the
+older chips and revisions. The 16-bit tachometer mode is enabled by the driver
+when one of the above chips is detected.
The IT8726F is just bit enhanced IT8716F with additional hardware
for AMD power sequencing. Therefore the chip will appear as IT8716F
@@ -131,9 +140,10 @@ inputs can measure voltages between 0 and 4.08 volts, with a resolution of
0.016 volt (except IT8721F/IT8758E and IT8728F: 0.012 volt.) The battery
voltage in8 does not have limit registers.
-On the IT8721F/IT8758E, some voltage inputs are internal and scaled inside
-the chip (in7, in8 and optionally in3). The driver handles this transparently
-so user-space doesn't have to care.
+On the IT8721F/IT8758E, IT8782F, and IT8783E/F, some voltage inputs are
+internal and scaled inside the chip (in7 (optional for IT8782F and IT8783E/F),
+in8 and optionally in3). The driver handles this transparently so user-space
+doesn't have to care.
The VID lines (IT8712F/IT8716F/IT8718F/IT8720F) encode the core voltage value:
the voltage level your processor should work with. This is hardcoded by
diff --git a/Documentation/hwmon/wm831x b/Documentation/hwmon/wm831x
index 24f47d8f6a42..11446757c8c8 100644
--- a/Documentation/hwmon/wm831x
+++ b/Documentation/hwmon/wm831x
@@ -22,7 +22,7 @@ reporting of all the input values but does not provide any alarms.
Voltage Monitoring
------------------
-Voltages are sampled by a 12 bit ADC. Voltages in milivolts are 1.465
+Voltages are sampled by a 12 bit ADC. Voltages in millivolts are 1.465
times the ADC value.
Temperature Monitoring
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index e34b531dc316..915f28c470e9 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -120,6 +120,7 @@ Code Seq#(hex) Include File Comments
'G' 00-0F linux/gigaset_dev.h conflict!
'H' 00-7F linux/hiddev.h conflict!
'H' 00-0F linux/hidraw.h conflict!
+'H' 01 linux/mei.h conflict!
'H' 00-0F sound/asound.h conflict!
'H' 20-40 sound/asound_fm.h conflict!
'H' 80-8F sound/sfnt_info.h conflict!
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 38cad53620cc..5b6e58492229 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -109,6 +109,7 @@ parameter is applicable:
USB USB support is enabled.
USBHID USB Human Interface Device support is enabled.
V4L Video For Linux support is enabled.
+ VMMIO Driver for memory mapped virtio devices is enabled.
VGA The VGA console has been enabled.
VT Virtual terminal support is enabled.
WDT Watchdog support is enabled.
@@ -609,7 +610,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
ddebug_query= [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot
time. See Documentation/dynamic-debug-howto.txt for
- details.
+ details. Deprecated, see dyndbg.
debug [KNL] Enable kernel debugging (events log level).
@@ -729,6 +730,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
dscc4.setup= [NET]
+ dyndbg[="val"] [KNL,DYNAMIC_DEBUG]
+ module.dyndbg[="val"]
+ Enable debug messages at boot time. See
+ Documentation/dynamic-debug-howto.txt for details.
+
earlycon= [KNL] Output early console device and options.
uart[8250],io,<addr>[,options]
uart[8250],mmio,<addr>[,options]
@@ -2160,6 +2166,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
on: Turn realloc on
realloc same as realloc=on
noari do not use PCIe ARI.
+ pcie_scan_all Scan all possible PCIe devices. Otherwise we
+ only look for one device below a PCIe downstream
+ port.
pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power
Management.
@@ -2329,18 +2338,100 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
ramdisk_size= [RAM] Sizes of RAM disks in kilobytes
See Documentation/blockdev/ramdisk.txt.
- rcupdate.blimit= [KNL,BOOT]
+ rcutree.blimit= [KNL,BOOT]
Set maximum number of finished RCU callbacks to process
in one batch.
- rcupdate.qhimark= [KNL,BOOT]
+ rcutree.qhimark= [KNL,BOOT]
Set threshold of queued
RCU callbacks over which batch limiting is disabled.
- rcupdate.qlowmark= [KNL,BOOT]
+ rcutree.qlowmark= [KNL,BOOT]
Set threshold of queued RCU callbacks below which
batch limiting is re-enabled.
+ rcutree.rcu_cpu_stall_suppress= [KNL,BOOT]
+ Suppress RCU CPU stall warning messages.
+
+ rcutree.rcu_cpu_stall_timeout= [KNL,BOOT]
+ Set timeout for RCU CPU stall warning messages.
+
+ rcutorture.fqs_duration= [KNL,BOOT]
+ Set duration of force_quiescent_state bursts.
+
+ rcutorture.fqs_holdoff= [KNL,BOOT]
+ Set holdoff time within force_quiescent_state bursts.
+
+ rcutorture.fqs_stutter= [KNL,BOOT]
+ Set wait time between force_quiescent_state bursts.
+
+ rcutorture.irqreader= [KNL,BOOT]
+ Test RCU readers from irq handlers.
+
+ rcutorture.n_barrier_cbs= [KNL,BOOT]
+ Set callbacks/threads for rcu_barrier() testing.
+
+ rcutorture.nfakewriters= [KNL,BOOT]
+ Set number of concurrent RCU writers. These just
+ stress RCU, they don't participate in the actual
+ test, hence the "fake".
+
+ rcutorture.nreaders= [KNL,BOOT]
+ Set number of RCU readers.
+
+ rcutorture.onoff_holdoff= [KNL,BOOT]
+ Set time (s) after boot for CPU-hotplug testing.
+
+ rcutorture.onoff_interval= [KNL,BOOT]
+ Set time (s) between CPU-hotplug operations, or
+ zero to disable CPU-hotplug testing.
+
+ rcutorture.shuffle_interval= [KNL,BOOT]
+ Set task-shuffle interval (s). Shuffling tasks
+ allows some CPUs to go into dyntick-idle mode
+ during the rcutorture test.
+
+ rcutorture.shutdown_secs= [KNL,BOOT]
+ Set time (s) after boot system shutdown. This
+ is useful for hands-off automated testing.
+
+ rcutorture.stall_cpu= [KNL,BOOT]
+ Duration of CPU stall (s) to test RCU CPU stall
+ warnings, zero to disable.
+
+ rcutorture.stall_cpu_holdoff= [KNL,BOOT]
+ Time to wait (s) after boot before inducing stall.
+
+ rcutorture.stat_interval= [KNL,BOOT]
+ Time (s) between statistics printk()s.
+
+ rcutorture.stutter= [KNL,BOOT]
+ Time (s) to stutter testing, for example, specifying
+ five seconds causes the test to run for five seconds,
+ wait for five seconds, and so on. This tests RCU's
+ ability to transition abruptly to and from idle.
+
+ rcutorture.test_boost= [KNL,BOOT]
+ Test RCU priority boosting? 0=no, 1=maybe, 2=yes.
+ "Maybe" means test if the RCU implementation
+ under test support RCU priority boosting.
+
+ rcutorture.test_boost_duration= [KNL,BOOT]
+ Duration (s) of each individual boost test.
+
+ rcutorture.test_boost_interval= [KNL,BOOT]
+ Interval (s) between each boost test.
+
+ rcutorture.test_no_idle_hz= [KNL,BOOT]
+ Test RCU's dyntick-idle handling. See also the
+ rcutorture.shuffle_interval parameter.
+
+ rcutorture.torture_type= [KNL,BOOT]
+ Specify the RCU implementation to test.
+
+ rcutorture.verbose= [KNL,BOOT]
+ Enable additional printk() statements.
+
rdinit= [KNL]
Format: <full_path>
Run specified binary instead of /init from the ramdisk,
@@ -2371,6 +2462,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
resume= [SWSUSP]
Specify the partition device for software suspend
+ Format:
+ {/dev/<dev> | PARTUUID=<uuid> | <int>:<int> | <hex>}
resume_offset= [SWSUSP]
Specify the offset from the beginning of the partition
@@ -2846,6 +2939,22 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
video= [FB] Frame buffer configuration
See Documentation/fb/modedb.txt.
+ virtio_mmio.device=
+ [VMMIO] Memory mapped virtio (platform) device.
+
+ <size>@<baseaddr>:<irq>[:<id>]
+ where:
+ <size> := size (can use standard suffixes
+ like K, M and G)
+ <baseaddr> := physical base address
+ <irq> := interrupt number (as passed to
+ request_irq())
+ <id> := (optional) platform device id
+ example:
+ virtio_mmio.device=1K@0x100b0000:48:7
+
+ Can be used multiple times for multiple devices.
+
vga= [BOOT,X86-32] Select a particular video mode
See Documentation/x86/boot.txt and
Documentation/svga.txt.
diff --git a/Documentation/memory-devices/ti-emif.txt b/Documentation/memory-devices/ti-emif.txt
new file mode 100644
index 000000000000..f4ad9a7d0f4b
--- /dev/null
+++ b/Documentation/memory-devices/ti-emif.txt
@@ -0,0 +1,57 @@
+TI EMIF SDRAM Controller Driver:
+
+Author
+========
+Aneesh V <aneesh@ti.com>
+
+Location
+============
+driver/memory/emif.c
+
+Supported SoCs:
+===================
+TI OMAP44xx
+TI OMAP54xx
+
+Menuconfig option:
+==========================
+Device Drivers
+ Memory devices
+ Texas Instruments EMIF driver
+
+Description
+===========
+This driver is for the EMIF module available in Texas Instruments
+SoCs. EMIF is an SDRAM controller that, based on its revision,
+supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols.
+This driver takes care of only LPDDR2 memories presently. The
+functions of the driver includes re-configuring AC timing
+parameters and other settings during frequency, voltage and
+temperature changes
+
+Platform Data (see include/linux/platform_data/emif_plat.h):
+=====================================================================
+DDR device details and other board dependent and SoC dependent
+information can be passed through platform data (struct emif_platform_data)
+- DDR device details: 'struct ddr_device_info'
+- Device AC timings: 'struct lpddr2_timings' and 'struct lpddr2_min_tck'
+- Custom configurations: customizable policy options through
+ 'struct emif_custom_configs'
+- IP revision
+- PHY type
+
+Interface to the external world:
+================================
+EMIF driver registers notifiers for voltage and frequency changes
+affecting EMIF and takes appropriate actions when these are invoked.
+- freq_pre_notify_handling()
+- freq_post_notify_handling()
+- volt_notify_handling()
+
+Debugfs
+========
+The driver creates two debugfs entries per device.
+- regcache_dump : dump of register values calculated and saved for all
+ frequencies used so far.
+- mr4 : last polled value of MR4 register in the LPDDR2 device. MR4
+ indicates the current temperature level of the device.
diff --git a/Documentation/memory-hotplug.txt b/Documentation/memory-hotplug.txt
index 8f485d72cf25..6d0c2519cf47 100644
--- a/Documentation/memory-hotplug.txt
+++ b/Documentation/memory-hotplug.txt
@@ -341,7 +341,7 @@ Need more implementation yet....
--------------------------------
8. Memory hotplug event notifier
--------------------------------
-Memory hotplug has event notifer. There are 6 types of notification.
+Memory hotplug has event notifier. There are 6 types of notification.
MEMORY_GOING_ONLINE
Generated before new memory becomes available in order to be able to
diff --git a/Documentation/misc-devices/mei/.gitignore b/Documentation/misc-devices/mei/.gitignore
new file mode 100644
index 000000000000..f356b81ca1ec
--- /dev/null
+++ b/Documentation/misc-devices/mei/.gitignore
@@ -0,0 +1 @@
+mei-amt-version
diff --git a/Documentation/misc-devices/mei/Makefile b/Documentation/misc-devices/mei/Makefile
new file mode 100644
index 000000000000..00e8c3e836ff
--- /dev/null
+++ b/Documentation/misc-devices/mei/Makefile
@@ -0,0 +1,8 @@
+# kbuild trick to avoid linker error. Can be omitted if a module is built.
+obj- := dummy.o
+
+# List of programs to build
+hostprogs-y := mei-amt-version
+HOSTCFLAGS_mei-amt-version.o += -I$(objtree)/usr/include
+# Tell kbuild to always build the programs
+always := $(hostprogs-y)
diff --git a/Documentation/misc-devices/mei/TODO b/Documentation/misc-devices/mei/TODO
new file mode 100644
index 000000000000..6b3625d3058c
--- /dev/null
+++ b/Documentation/misc-devices/mei/TODO
@@ -0,0 +1,2 @@
+TODO:
+ - Cleanup and split the timer function
diff --git a/drivers/staging/mei/mei-amt-version.c b/Documentation/misc-devices/mei/mei-amt-version.c
index ac2a507be253..01804f216312 100644
--- a/drivers/staging/mei/mei-amt-version.c
+++ b/Documentation/misc-devices/mei/mei-amt-version.c
@@ -74,7 +74,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <bits/wordsize.h>
-#include "mei.h"
+#include <linux/mei.h>
/*****************************************************************************
* Intel Management Engine Interface
diff --git a/drivers/staging/mei/mei.txt b/Documentation/misc-devices/mei/mei.txt
index 2785697da59d..2785697da59d 100644
--- a/drivers/staging/mei/mei.txt
+++ b/Documentation/misc-devices/mei/mei.txt
diff --git a/Documentation/networking/can.txt b/Documentation/networking/can.txt
index 56ca3b75376e..ac295399f0d4 100644
--- a/Documentation/networking/can.txt
+++ b/Documentation/networking/can.txt
@@ -649,7 +649,7 @@ solution for a couple of reasons:
The CAN device must be configured via netlink interface. The supported
netlink message types are defined and briefly described in
"include/linux/can/netlink.h". CAN link support for the program "ip"
- of the IPROUTE2 utility suite is avaiable and it can be used as shown
+ of the IPROUTE2 utility suite is available and it can be used as shown
below:
- Setting CAN device properties:
diff --git a/Documentation/parisc/debugging b/Documentation/parisc/debugging
index d728594058e5..7d75223fa18d 100644
--- a/Documentation/parisc/debugging
+++ b/Documentation/parisc/debugging
@@ -34,6 +34,6 @@ registers interruption handlers read to find out where the machine
was interrupted - so if you get an interruption between the instruction
that clears the Q bit and the RFI that sets it again you don't know
where exactly it happened. If you're lucky the IAOQ will point to the
-instrucion that cleared the Q bit, if you're not it points anywhere
+instruction that cleared the Q bit, if you're not it points anywhere
at all. Usually Q bit problems will show themselves in unexplainable
system hangs or running off the end of physical memory.
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index d97bccf46147..e40f4b4e1977 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -152,11 +152,9 @@ static const struct foo_group foo_groups[] = {
};
-static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
+static int foo_get_groups_count(struct pinctrl_dev *pctldev)
{
- if (selector >= ARRAY_SIZE(foo_groups))
- return -EINVAL;
- return 0;
+ return ARRAY_SIZE(foo_groups);
}
static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
@@ -175,7 +173,7 @@ static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
}
static struct pinctrl_ops foo_pctrl_ops = {
- .list_groups = foo_list_groups,
+ .get_groups_count = foo_get_groups_count,
.get_group_name = foo_get_group_name,
.get_group_pins = foo_get_group_pins,
};
@@ -186,13 +184,12 @@ static struct pinctrl_desc foo_desc = {
.pctlops = &foo_pctrl_ops,
};
-The pin control subsystem will call the .list_groups() function repeatedly
-beginning on 0 until it returns non-zero to determine legal selectors, then
-it will call the other functions to retrieve the name and pins of the group.
-Maintaining the data structure of the groups is up to the driver, this is
-just a simple example - in practice you may need more entries in your group
-structure, for example specific register ranges associated with each group
-and so on.
+The pin control subsystem will call the .get_groups_count() function to
+determine total number of legal selectors, then it will call the other functions
+to retrieve the name and pins of the group. Maintaining the data structure of
+the groups is up to the driver, this is just a simple example - in practice you
+may need more entries in your group structure, for example specific register
+ranges associated with each group and so on.
Pin configuration
@@ -606,11 +603,9 @@ static const struct foo_group foo_groups[] = {
};
-static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
+static int foo_get_groups_count(struct pinctrl_dev *pctldev)
{
- if (selector >= ARRAY_SIZE(foo_groups))
- return -EINVAL;
- return 0;
+ return ARRAY_SIZE(foo_groups);
}
static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
@@ -629,7 +624,7 @@ static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
}
static struct pinctrl_ops foo_pctrl_ops = {
- .list_groups = foo_list_groups,
+ .get_groups_count = foo_get_groups_count,
.get_group_name = foo_get_group_name,
.get_group_pins = foo_get_group_pins,
};
@@ -640,7 +635,7 @@ struct foo_pmx_func {
const unsigned num_groups;
};
-static const char * const spi0_groups[] = { "spi0_1_grp" };
+static const char * const spi0_groups[] = { "spi0_0_grp", "spi0_1_grp" };
static const char * const i2c0_groups[] = { "i2c0_grp" };
static const char * const mmc0_groups[] = { "mmc0_1_grp", "mmc0_2_grp",
"mmc0_3_grp" };
@@ -663,11 +658,9 @@ static const struct foo_pmx_func foo_functions[] = {
},
};
-int foo_list_funcs(struct pinctrl_dev *pctldev, unsigned selector)
+int foo_get_functions_count(struct pinctrl_dev *pctldev)
{
- if (selector >= ARRAY_SIZE(foo_functions))
- return -EINVAL;
- return 0;
+ return ARRAY_SIZE(foo_functions);
}
const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector)
@@ -703,7 +696,7 @@ void foo_disable(struct pinctrl_dev *pctldev, unsigned selector,
}
struct pinmux_ops foo_pmxops = {
- .list_functions = foo_list_funcs,
+ .get_functions_count = foo_get_functions_count,
.get_function_name = foo_get_fname,
.get_function_groups = foo_get_groups,
.enable = foo_enable,
@@ -786,7 +779,7 @@ and spi on the second function mapping:
#include <linux/pinctrl/machine.h>
-static const struct pinctrl_map __initdata mapping[] = {
+static const struct pinctrl_map mapping[] __initconst = {
{
.dev_name = "foo-spi.0",
.name = PINCTRL_STATE_DEFAULT,
@@ -952,13 +945,13 @@ case), we define a mapping like this:
The result of grabbing this mapping from the device with something like
this (see next paragraph):
- p = pinctrl_get(dev);
+ p = devm_pinctrl_get(dev);
s = pinctrl_lookup_state(p, "8bit");
ret = pinctrl_select_state(p, s);
or more simply:
- p = pinctrl_get_select(dev, "8bit");
+ p = devm_pinctrl_get_select(dev, "8bit");
Will be that you activate all the three bottom records in the mapping at
once. Since they share the same name, pin controller device, function and
@@ -992,7 +985,7 @@ foo_probe()
/* Allocate a state holder named "foo" etc */
struct foo_state *foo = ...;
- foo->p = pinctrl_get(&device);
+ foo->p = devm_pinctrl_get(&device);
if (IS_ERR(foo->p)) {
/* FIXME: clean up "foo" here */
return PTR_ERR(foo->p);
@@ -1000,24 +993,17 @@ foo_probe()
foo->s = pinctrl_lookup_state(foo->p, PINCTRL_STATE_DEFAULT);
if (IS_ERR(foo->s)) {
- pinctrl_put(foo->p);
/* FIXME: clean up "foo" here */
return PTR_ERR(s);
}
ret = pinctrl_select_state(foo->s);
if (ret < 0) {
- pinctrl_put(foo->p);
/* FIXME: clean up "foo" here */
return ret;
}
}
-foo_remove()
-{
- pinctrl_put(state->p);
-}
-
This get/lookup/select/put sequence can just as well be handled by bus drivers
if you don't want each and every driver to handle it and you know the
arrangement on your bus.
@@ -1029,6 +1015,11 @@ The semantics of the pinctrl APIs are:
kernel memory to hold the pinmux state. All mapping table parsing or similar
slow operations take place within this API.
+- devm_pinctrl_get() is a variant of pinctrl_get() that causes pinctrl_put()
+ to be called automatically on the retrieved pointer when the associated
+ device is removed. It is recommended to use this function over plain
+ pinctrl_get().
+
- pinctrl_lookup_state() is called in process context to obtain a handle to a
specific state for a the client device. This operation may be slow too.
@@ -1041,14 +1032,30 @@ The semantics of the pinctrl APIs are:
- pinctrl_put() frees all information associated with a pinctrl handle.
+- devm_pinctrl_put() is a variant of pinctrl_put() that may be used to
+ explicitly destroy a pinctrl object returned by devm_pinctrl_get().
+ However, use of this function will be rare, due to the automatic cleanup
+ that will occur even without calling it.
+
+ pinctrl_get() must be paired with a plain pinctrl_put().
+ pinctrl_get() may not be paired with devm_pinctrl_put().
+ devm_pinctrl_get() can optionally be paired with devm_pinctrl_put().
+ devm_pinctrl_get() may not be paired with plain pinctrl_put().
+
Usually the pin control core handled the get/put pair and call out to the
device drivers bookkeeping operations, like checking available functions and
the associated pins, whereas the enable/disable pass on to the pin controller
driver which takes care of activating and/or deactivating the mux setting by
quickly poking some registers.
-The pins are allocated for your device when you issue the pinctrl_get() call,
-after this you should be able to see this in the debugfs listing of all pins.
+The pins are allocated for your device when you issue the devm_pinctrl_get()
+call, after this you should be able to see this in the debugfs listing of all
+pins.
+
+NOTE: the pinctrl system will return -EPROBE_DEFER if it cannot find the
+requested pinctrl handles, for example if the pinctrl driver has not yet
+registered. Thus make sure that the error path in your driver gracefully
+cleans up and is ready to retry the probing later in the startup process.
System pin control hogging
@@ -1094,13 +1101,13 @@ it, disables and releases it, and muxes it in on the pins defined by group B:
#include <linux/pinctrl/consumer.h>
-foo_switch()
-{
- struct pinctrl *p;
- struct pinctrl_state *s1, *s2;
+struct pinctrl *p;
+struct pinctrl_state *s1, *s2;
+foo_probe()
+{
/* Setup */
- p = pinctrl_get(&device);
+ p = devm_pinctrl_get(&device);
if (IS_ERR(p))
...
@@ -1111,7 +1118,10 @@ foo_switch()
s2 = pinctrl_lookup_state(foo->p, "pos-B");
if (IS_ERR(s2))
...
+}
+foo_switch()
+{
/* Enable on position A */
ret = pinctrl_select_state(s1);
if (ret < 0)
@@ -1125,8 +1135,6 @@ foo_switch()
...
...
-
- pinctrl_put(p);
}
The above has to be done from process context.
diff --git a/Documentation/power/regulator/regulator.txt b/Documentation/power/regulator/regulator.txt
index e272d9909e39..13902778ae44 100644
--- a/Documentation/power/regulator/regulator.txt
+++ b/Documentation/power/regulator/regulator.txt
@@ -11,8 +11,7 @@ Registration
Drivers can register a regulator by calling :-
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
- struct device *dev, struct regulator_init_data *init_data,
- void *driver_data, struct device_node *of_node);
+ const struct regulator_config *config);
This will register the regulators capabilities and operations to the regulator
core.
diff --git a/Documentation/power/suspend-and-cpuhotplug.txt b/Documentation/power/suspend-and-cpuhotplug.txt
index f28f9a6f0347..e13dafc8e8f1 100644
--- a/Documentation/power/suspend-and-cpuhotplug.txt
+++ b/Documentation/power/suspend-and-cpuhotplug.txt
@@ -29,7 +29,7 @@ More details follow:
Write 'mem' to
/sys/power/state
- syfs file
+ sysfs file
|
v
Acquire pm_mutex lock
diff --git a/Documentation/prctl/seccomp_filter.txt b/Documentation/prctl/seccomp_filter.txt
new file mode 100644
index 000000000000..597c3c581375
--- /dev/null
+++ b/Documentation/prctl/seccomp_filter.txt
@@ -0,0 +1,163 @@
+ SECure COMPuting with filters
+ =============================
+
+Introduction
+------------
+
+A large number of system calls are exposed to every userland process
+with many of them going unused for the entire lifetime of the process.
+As system calls change and mature, bugs are found and eradicated. A
+certain subset of userland applications benefit by having a reduced set
+of available system calls. The resulting set reduces the total kernel
+surface exposed to the application. System call filtering is meant for
+use with those applications.
+
+Seccomp filtering provides a means for a process to specify a filter for
+incoming system calls. The filter is expressed as a Berkeley Packet
+Filter (BPF) program, as with socket filters, except that the data
+operated on is related to the system call being made: system call
+number and the system call arguments. This allows for expressive
+filtering of system calls using a filter program language with a long
+history of being exposed to userland and a straightforward data set.
+
+Additionally, BPF makes it impossible for users of seccomp to fall prey
+to time-of-check-time-of-use (TOCTOU) attacks that are common in system
+call interposition frameworks. BPF programs may not dereference
+pointers which constrains all filters to solely evaluating the system
+call arguments directly.
+
+What it isn't
+-------------
+
+System call filtering isn't a sandbox. It provides a clearly defined
+mechanism for minimizing the exposed kernel surface. It is meant to be
+a tool for sandbox developers to use. Beyond that, policy for logical
+behavior and information flow should be managed with a combination of
+other system hardening techniques and, potentially, an LSM of your
+choosing. Expressive, dynamic filters provide further options down this
+path (avoiding pathological sizes or selecting which of the multiplexed
+system calls in socketcall() is allowed, for instance) which could be
+construed, incorrectly, as a more complete sandboxing solution.
+
+Usage
+-----
+
+An additional seccomp mode is added and is enabled using the same
+prctl(2) call as the strict seccomp. If the architecture has
+CONFIG_HAVE_ARCH_SECCOMP_FILTER, then filters may be added as below:
+
+PR_SET_SECCOMP:
+ Now takes an additional argument which specifies a new filter
+ using a BPF program.
+ The BPF program will be executed over struct seccomp_data
+ reflecting the system call number, arguments, and other
+ metadata. The BPF program must then return one of the
+ acceptable values to inform the kernel which action should be
+ taken.
+
+ Usage:
+ prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog);
+
+ The 'prog' argument is a pointer to a struct sock_fprog which
+ will contain the filter program. If the program is invalid, the
+ call will return -1 and set errno to EINVAL.
+
+ If fork/clone and execve are allowed by @prog, any child
+ processes will be constrained to the same filters and system
+ call ABI as the parent.
+
+ Prior to use, the task must call prctl(PR_SET_NO_NEW_PRIVS, 1) or
+ run with CAP_SYS_ADMIN privileges in its namespace. If these are not
+ true, -EACCES will be returned. This requirement ensures that filter
+ programs cannot be applied to child processes with greater privileges
+ than the task that installed them.
+
+ Additionally, if prctl(2) is allowed by the attached filter,
+ additional filters may be layered on which will increase evaluation
+ time, but allow for further decreasing the attack surface during
+ execution of a process.
+
+The above call returns 0 on success and non-zero on error.
+
+Return values
+-------------
+A seccomp filter may return any of the following values. If multiple
+filters exist, the return value for the evaluation of a given system
+call will always use the highest precedent value. (For example,
+SECCOMP_RET_KILL will always take precedence.)
+
+In precedence order, they are:
+
+SECCOMP_RET_KILL:
+ Results in the task exiting immediately without executing the
+ system call. The exit status of the task (status & 0x7f) will
+ be SIGSYS, not SIGKILL.
+
+SECCOMP_RET_TRAP:
+ Results in the kernel sending a SIGSYS signal to the triggering
+ task without executing the system call. The kernel will
+ rollback the register state to just before the system call
+ entry such that a signal handler in the task will be able to
+ inspect the ucontext_t->uc_mcontext registers and emulate
+ system call success or failure upon return from the signal
+ handler.
+
+ The SECCOMP_RET_DATA portion of the return value will be passed
+ as si_errno.
+
+ SIGSYS triggered by seccomp will have a si_code of SYS_SECCOMP.
+
+SECCOMP_RET_ERRNO:
+ Results in the lower 16-bits of the return value being passed
+ to userland as the errno without executing the system call.
+
+SECCOMP_RET_TRACE:
+ When returned, this value will cause the kernel to attempt to
+ notify a ptrace()-based tracer prior to executing the system
+ call. If there is no tracer present, -ENOSYS is returned to
+ userland and the system call is not executed.
+
+ A tracer will be notified if it requests PTRACE_O_TRACESECCOMP
+ using ptrace(PTRACE_SETOPTIONS). The tracer will be notified
+ of a PTRACE_EVENT_SECCOMP and the SECCOMP_RET_DATA portion of
+ the BPF program return value will be available to the tracer
+ via PTRACE_GETEVENTMSG.
+
+SECCOMP_RET_ALLOW:
+ Results in the system call being executed.
+
+If multiple filters exist, the return value for the evaluation of a
+given system call will always use the highest precedent value.
+
+Precedence is only determined using the SECCOMP_RET_ACTION mask. When
+multiple filters return values of the same precedence, only the
+SECCOMP_RET_DATA from the most recently installed filter will be
+returned.
+
+Pitfalls
+--------
+
+The biggest pitfall to avoid during use is filtering on system call
+number without checking the architecture value. Why? On any
+architecture that supports multiple system call invocation conventions,
+the system call numbers may vary based on the specific invocation. If
+the numbers in the different calling conventions overlap, then checks in
+the filters may be abused. Always check the arch value!
+
+Example
+-------
+
+The samples/seccomp/ directory contains both an x86-specific example
+and a more generic example of a higher level macro interface for BPF
+program generation.
+
+
+
+Adding architecture support
+-----------------------
+
+See arch/Kconfig for the authoritative requirements. In general, if an
+architecture supports both ptrace_event and seccomp, it will be able to
+support seccomp filter with minor fixup: SIGSYS support and seccomp return
+value checking. Then it must just add CONFIG_HAVE_ARCH_SECCOMP_FILTER
+to its arch-specific Kconfig.
diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
index 8fb1ba7fe7bf..4ba7db231cb2 100644
--- a/Documentation/ramoops.txt
+++ b/Documentation/ramoops.txt
@@ -3,7 +3,7 @@ Ramoops oops/panic logger
Sergiu Iordache <sergiu@chromium.org>
-Updated: 8 August 2011
+Updated: 17 November 2011
0. Introduction
@@ -30,6 +30,11 @@ variable while setting 0 in that variable dumps only the panics.
The module uses a counter to record multiple dumps but the counter gets reset
on restart (i.e. new dumps after the restart will overwrite old ones).
+Ramoops also supports software ECC protection of persistent memory regions.
+This might be useful when a hardware reset was used to bring the machine back
+to life (i.e. a watchdog triggered). In such cases, RAM may be somewhat
+corrupt, but usually it is restorable.
+
2. Setting the parameters
Setting the ramoops parameters can be done in 2 different manners:
@@ -38,7 +43,7 @@ Setting the ramoops parameters can be done in 2 different manners:
2. Use a platform device and set the platform data. The parameters can then
be set through that platform data. An example of doing that is:
-#include <linux/ramoops.h>
+#include <linux/pstore_ram.h>
[...]
static struct ramoops_platform_data ramoops_data = {
@@ -46,6 +51,7 @@ static struct ramoops_platform_data ramoops_data = {
.mem_address = <...>,
.record_size = <...>,
.dump_oops = <...>,
+ .ecc = <...>,
};
static struct platform_device ramoops_dev = {
@@ -71,6 +77,6 @@ timestamp and a new line. The dump then continues with the actual data.
4. Reading the data
-The dump data can be read from memory (through /dev/mem or other means).
-Getting the module parameters, which are needed in order to parse the data, can
-be done through /sys/module/ramoops/parameters/* .
+The dump data can be read from the pstore filesystem. The format for these
+files is "dmesg-ramoops-N", where N is the record number in memory. To delete
+a stored record from RAM, simply unlink the respective pstore file.
diff --git a/Documentation/scheduler/sched-design-CFS.txt b/Documentation/scheduler/sched-design-CFS.txt
index 91ecff07cede..d529e02d928d 100644
--- a/Documentation/scheduler/sched-design-CFS.txt
+++ b/Documentation/scheduler/sched-design-CFS.txt
@@ -130,7 +130,7 @@ CFS implements three scheduling policies:
idle timer scheduler in order to avoid to get into priority
inversion problems which would deadlock the machine.
-SCHED_FIFO/_RR are implemented in sched_rt.c and are as specified by
+SCHED_FIFO/_RR are implemented in sched/rt.c and are as specified by
POSIX.
The command chrt from util-linux-ng 2.13.1.1 can set all of these except
@@ -145,9 +145,9 @@ Classes," an extensible hierarchy of scheduler modules. These modules
encapsulate scheduling policy details and are handled by the scheduler core
without the core code assuming too much about them.
-sched_fair.c implements the CFS scheduler described above.
+sched/fair.c implements the CFS scheduler described above.
-sched_rt.c implements SCHED_FIFO and SCHED_RR semantics, in a simpler way than
+sched/rt.c implements SCHED_FIFO and SCHED_RR semantics, in a simpler way than
the previous vanilla scheduler did. It uses 100 runqueues (for all 100 RT
priority levels, instead of 140 in the previous scheduler) and it needs no
expired array.
diff --git a/Documentation/scheduler/sched-domains.txt b/Documentation/scheduler/sched-domains.txt
index b7ee379b651b..443f0c76bab4 100644
--- a/Documentation/scheduler/sched-domains.txt
+++ b/Documentation/scheduler/sched-domains.txt
@@ -61,10 +61,6 @@ The implementor should read comments in include/linux/sched.h:
struct sched_domain fields, SD_FLAG_*, SD_*_INIT to get an idea of
the specifics and what to tune.
-For SMT, the architecture must define CONFIG_SCHED_SMT and provide a
-cpumask_t cpu_sibling_map[NR_CPUS], where cpu_sibling_map[i] is the mask of
-all "i"'s siblings as well as "i" itself.
-
Architectures may retain the regular override the default SD_*_INIT flags
while using the generic domain builder in kernel/sched.c if they wish to
retain the traditional SMT->SMP->NUMA topology (or some subset of that). This
diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
index 83f8ea8b79eb..80441ab608e4 100644
--- a/Documentation/scsi/ChangeLog.megaraid_sas
+++ b/Documentation/scsi/ChangeLog.megaraid_sas
@@ -1,3 +1,11 @@
+Release Date : Mon. Mar 19, 2012 17:00:00 PST 2012 -
+ (emaild-id:megaraidlinux@lsi.com)
+ Adam Radford
+Current Version : 00.00.06.15-rc1
+Old Version : 00.00.06.14-rc1
+ 1. Optimize HostMSIxVectors setting.
+ 2. Add fpRead/WriteCapable, fpRead/WriteAcrossStripe checks.
+-------------------------------------------------------------------------------
Release Date : Fri. Jan 6, 2012 17:00:00 PST 2010 -
(emaild-id:megaraidlinux@lsi.com)
Adam Radford
diff --git a/Documentation/security/Smack.txt b/Documentation/security/Smack.txt
index d2f72ae66432..a416479b8a1c 100644
--- a/Documentation/security/Smack.txt
+++ b/Documentation/security/Smack.txt
@@ -15,7 +15,7 @@ at hand.
Smack consists of three major components:
- The kernel
- - A start-up script and a few modified applications
+ - Basic utilities, which are helpful but not required
- Configuration data
The kernel component of Smack is implemented as a Linux
@@ -23,37 +23,28 @@ Security Modules (LSM) module. It requires netlabel and
works best with file systems that support extended attributes,
although xattr support is not strictly required.
It is safe to run a Smack kernel under a "vanilla" distribution.
+
Smack kernels use the CIPSO IP option. Some network
configurations are intolerant of IP options and can impede
access to systems that use them as Smack does.
-The startup script etc-init.d-smack should be installed
-in /etc/init.d/smack and should be invoked early in the
-start-up process. On Fedora rc5.d/S02smack is recommended.
-This script ensures that certain devices have the correct
-Smack attributes and loads the Smack configuration if
-any is defined. This script invokes two programs that
-ensure configuration data is properly formatted. These
-programs are /usr/sbin/smackload and /usr/sin/smackcipso.
-The system will run just fine without these programs,
-but it will be difficult to set access rules properly.
-
-A version of "ls" that provides a "-M" option to display
-Smack labels on long listing is available.
+The current git repositories for Smack user space are:
-A hacked version of sshd that allows network logins by users
-with specific Smack labels is available. This version does
-not work for scp. You must set the /etc/ssh/sshd_config
-line:
- UsePrivilegeSeparation no
+ git@gitorious.org:meego-platform-security/smackutil.git
+ git@gitorious.org:meego-platform-security/libsmack.git
-The format of /etc/smack/usr is:
+These should make and install on most modern distributions.
+There are three commands included in smackutil:
- username smack
+smackload - properly formats data for writing to /smack/load
+smackcipso - properly formats data for writing to /smack/cipso
+chsmack - display or set Smack extended attribute values
In keeping with the intent of Smack, configuration data is
minimal and not strictly required. The most important
configuration step is mounting the smackfs pseudo filesystem.
+If smackutil is installed the startup script will take care
+of this, but it can be manually as well.
Add this line to /etc/fstab:
@@ -61,19 +52,148 @@ Add this line to /etc/fstab:
and create the /smack directory for mounting.
-Smack uses extended attributes (xattrs) to store file labels.
-The command to set a Smack label on a file is:
+Smack uses extended attributes (xattrs) to store labels on filesystem
+objects. The attributes are stored in the extended attribute security
+name space. A process must have CAP_MAC_ADMIN to change any of these
+attributes.
+
+The extended attributes that Smack uses are:
+
+SMACK64
+ Used to make access control decisions. In almost all cases
+ the label given to a new filesystem object will be the label
+ of the process that created it.
+SMACK64EXEC
+ The Smack label of a process that execs a program file with
+ this attribute set will run with this attribute's value.
+SMACK64MMAP
+ Don't allow the file to be mmapped by a process whose Smack
+ label does not allow all of the access permitted to a process
+ with the label contained in this attribute. This is a very
+ specific use case for shared libraries.
+SMACK64TRANSMUTE
+ Can only have the value "TRUE". If this attribute is present
+ on a directory when an object is created in the directory and
+ the Smack rule (more below) that permitted the write access
+ to the directory includes the transmute ("t") mode the object
+ gets the label of the directory instead of the label of the
+ creating process. If the object being created is a directory
+ the SMACK64TRANSMUTE attribute is set as well.
+SMACK64IPIN
+ This attribute is only available on file descriptors for sockets.
+ Use the Smack label in this attribute for access control
+ decisions on packets being delivered to this socket.
+SMACK64IPOUT
+ This attribute is only available on file descriptors for sockets.
+ Use the Smack label in this attribute for access control
+ decisions on packets coming from this socket.
+
+There are multiple ways to set a Smack label on a file:
# attr -S -s SMACK64 -V "value" path
+ # chsmack -a value path
-NOTE: Smack labels are limited to 23 characters. The attr command
- does not enforce this restriction and can be used to set
- invalid Smack labels on files.
-
-If you don't do anything special all users will get the floor ("_")
-label when they log in. If you do want to log in via the hacked ssh
-at other labels use the attr command to set the smack value on the
-home directory and its contents.
+A process can see the smack label it is running with by
+reading /proc/self/attr/current. A process with CAP_MAC_ADMIN
+can set the process smack by writing there.
+
+Most Smack configuration is accomplished by writing to files
+in the smackfs filesystem. This pseudo-filesystem is usually
+mounted on /smack.
+
+access
+ This interface reports whether a subject with the specified
+ Smack label has a particular access to an object with a
+ specified Smack label. Write a fixed format access rule to
+ this file. The next read will indicate whether the access
+ would be permitted. The text will be either "1" indicating
+ access, or "0" indicating denial.
+access2
+ This interface reports whether a subject with the specified
+ Smack label has a particular access to an object with a
+ specified Smack label. Write a long format access rule to
+ this file. The next read will indicate whether the access
+ would be permitted. The text will be either "1" indicating
+ access, or "0" indicating denial.
+ambient
+ This contains the Smack label applied to unlabeled network
+ packets.
+cipso
+ This interface allows a specific CIPSO header to be assigned
+ to a Smack label. The format accepted on write is:
+ "%24s%4d%4d"["%4d"]...
+ The first string is a fixed Smack label. The first number is
+ the level to use. The second number is the number of categories.
+ The following numbers are the categories.
+ "level-3-cats-5-19 3 2 5 19"
+cipso2
+ This interface allows a specific CIPSO header to be assigned
+ to a Smack label. The format accepted on write is:
+ "%s%4d%4d"["%4d"]...
+ The first string is a long Smack label. The first number is
+ the level to use. The second number is the number of categories.
+ The following numbers are the categories.
+ "level-3-cats-5-19 3 2 5 19"
+direct
+ This contains the CIPSO level used for Smack direct label
+ representation in network packets.
+doi
+ This contains the CIPSO domain of interpretation used in
+ network packets.
+load
+ This interface allows access control rules in addition to
+ the system defined rules to be specified. The format accepted
+ on write is:
+ "%24s%24s%5s"
+ where the first string is the subject label, the second the
+ object label, and the third the requested access. The access
+ string may contain only the characters "rwxat-", and specifies
+ which sort of access is allowed. The "-" is a placeholder for
+ permissions that are not allowed. The string "r-x--" would
+ specify read and execute access. Labels are limited to 23
+ characters in length.
+load2
+ This interface allows access control rules in addition to
+ the system defined rules to be specified. The format accepted
+ on write is:
+ "%s %s %s"
+ where the first string is the subject label, the second the
+ object label, and the third the requested access. The access
+ string may contain only the characters "rwxat-", and specifies
+ which sort of access is allowed. The "-" is a placeholder for
+ permissions that are not allowed. The string "r-x--" would
+ specify read and execute access.
+load-self
+ This interface allows process specific access rules to be
+ defined. These rules are only consulted if access would
+ otherwise be permitted, and are intended to provide additional
+ restrictions on the process. The format is the same as for
+ the load interface.
+load-self2
+ This interface allows process specific access rules to be
+ defined. These rules are only consulted if access would
+ otherwise be permitted, and are intended to provide additional
+ restrictions on the process. The format is the same as for
+ the load2 interface.
+logging
+ This contains the Smack logging state.
+mapped
+ This contains the CIPSO level used for Smack mapped label
+ representation in network packets.
+netlabel
+ This interface allows specific internet addresses to be
+ treated as single label hosts. Packets are sent to single
+ label hosts without CIPSO headers, but only from processes
+ that have Smack write access to the host label. All packets
+ received from single label hosts are given the specified
+ label. The format accepted on write is:
+ "%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label".
+onlycap
+ This contains the label processes must have for CAP_MAC_ADMIN
+ and CAP_MAC_OVERRIDE to be effective. If this file is empty
+ these capabilities are effective at for processes with any
+ label. The value is set by writing the desired label to the
+ file or cleared by writing "-" to the file.
You can add access rules in /etc/smack/accesses. They take the form:
@@ -83,10 +203,6 @@ access is a combination of the letters rwxa which specify the
kind of access permitted a subject with subjectlabel on an
object with objectlabel. If there is no rule no access is allowed.
-A process can see the smack label it is running with by
-reading /proc/self/attr/current. A privileged process can
-set the process smack by writing there.
-
Look for additional programs on http://schaufler-ca.com
From the Smack Whitepaper:
@@ -186,7 +302,7 @@ team. Smack labels are unstructured, case sensitive, and the only operation
ever performed on them is comparison for equality. Smack labels cannot
contain unprintable characters, the "/" (slash), the "\" (backslash), the "'"
(quote) and '"' (double-quote) characters.
-Smack labels cannot begin with a '-', which is reserved for special options.
+Smack labels cannot begin with a '-'. This is reserved for special options.
There are some predefined labels:
@@ -194,7 +310,7 @@ There are some predefined labels:
^ Pronounced "hat", a single circumflex character.
* Pronounced "star", a single asterisk character.
? Pronounced "huh", a single question mark character.
- @ Pronounced "Internet", a single at sign character.
+ @ Pronounced "web", a single at sign character.
Every task on a Smack system is assigned a label. System tasks, such as
init(8) and systems daemons, are run with the floor ("_") label. User tasks
@@ -246,13 +362,14 @@ The format of an access rule is:
Where subject-label is the Smack label of the task, object-label is the Smack
label of the thing being accessed, and access is a string specifying the sort
-of access allowed. The Smack labels are limited to 23 characters. The access
-specification is searched for letters that describe access modes:
+of access allowed. The access specification is searched for letters that
+describe access modes:
a: indicates that append access should be granted.
r: indicates that read access should be granted.
w: indicates that write access should be granted.
x: indicates that execute access should be granted.
+ t: indicates that the rule requests transmutation.
Uppercase values for the specification letters are allowed as well.
Access mode specifications can be in any order. Examples of acceptable rules
@@ -273,7 +390,7 @@ Examples of unacceptable rules are:
Spaces are not allowed in labels. Since a subject always has access to files
with the same label specifying a rule for that case is pointless. Only
-valid letters (rwxaRWXA) and the dash ('-') character are allowed in
+valid letters (rwxatRWXAT) and the dash ('-') character are allowed in
access specifications. The dash is a placeholder, so "a-r" is the same
as "ar". A lone dash is used to specify that no access should be allowed.
@@ -297,6 +414,13 @@ but not any of its attributes by the circumstance of having read access to the
containing directory but not to the differently labeled file. This is an
artifact of the file name being data in the directory, not a part of the file.
+If a directory is marked as transmuting (SMACK64TRANSMUTE=TRUE) and the
+access rule that allows a process to create an object in that directory
+includes 't' access the label assigned to the new object will be that
+of the directory, not the creating process. This makes it much easier
+for two processes with different labels to share data without granting
+access to all of their files.
+
IPC objects, message queues, semaphore sets, and memory segments exist in flat
namespaces and access requests are only required to match the object in
question.
diff --git a/Documentation/security/Yama.txt b/Documentation/security/Yama.txt
index a9511f179069..e369de2d48cd 100644
--- a/Documentation/security/Yama.txt
+++ b/Documentation/security/Yama.txt
@@ -34,7 +34,7 @@ parent to a child process (i.e. direct "gdb EXE" and "strace EXE" still
work), or with CAP_SYS_PTRACE (i.e. "gdb --pid=PID", and "strace -p PID"
still work as root).
-For software that has defined application-specific relationships
+In mode 1, software that has defined application-specific relationships
between a debugging process and its inferior (crash handlers, etc),
prctl(PR_SET_PTRACER, pid, ...) can be used. An inferior can declare which
other process (and its descendents) are allowed to call PTRACE_ATTACH
@@ -46,6 +46,8 @@ restrictions, it can call prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, ...)
so that any otherwise allowed process (even those in external pid namespaces)
may attach.
+These restrictions do not change how ptrace via PTRACE_TRACEME operates.
+
The sysctl settings are:
0 - classic ptrace permissions: a process can PTRACE_ATTACH to any other
@@ -60,6 +62,12 @@ The sysctl settings are:
inferior can call prctl(PR_SET_PTRACER, debugger, ...) to declare
an allowed debugger PID to call PTRACE_ATTACH on the inferior.
+2 - admin-only attach: only processes with CAP_SYS_PTRACE may use ptrace
+ with PTRACE_ATTACH.
+
+3 - no attach: no processes may use ptrace with PTRACE_ATTACH. Once set,
+ this sysctl cannot be changed to a lower value.
+
The original children-only logic was based on the restrictions in grsecurity.
==============================================================
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index d389acd31e19..aa0dbd74b71b 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -805,6 +805,23 @@ The keyctl syscall functions are:
kernel and resumes executing userspace.
+ (*) Invalidate a key.
+
+ long keyctl(KEYCTL_INVALIDATE, key_serial_t key);
+
+ This function marks a key as being invalidated and then wakes up the
+ garbage collector. The garbage collector immediately removes invalidated
+ keys from all keyrings and deletes the key when its reference count
+ reaches zero.
+
+ Keys that are marked invalidated become invisible to normal key operations
+ immediately, though they are still visible in /proc/keys until deleted
+ (they're marked with an 'i' flag).
+
+ A process must have search permission on the key for this function to be
+ successful.
+
+
===============
KERNEL SERVICES
===============
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 8c16d50f6cb6..221b81016dba 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -1545,7 +1545,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module for sound cards based on the C-Media CMI8786/8787/8788 chip:
* Asound A-8788
- * Asus Xonar DG
+ * Asus Xonar DG/DGX
* AuzenTech X-Meridian
* AuzenTech X-Meridian 2G
* Bgears b-Enspirer
diff --git a/Documentation/sound/alsa/compress_offload.txt b/Documentation/sound/alsa/compress_offload.txt
index c83a835350f0..90e9b3a11abc 100644
--- a/Documentation/sound/alsa/compress_offload.txt
+++ b/Documentation/sound/alsa/compress_offload.txt
@@ -18,7 +18,7 @@ processing. Support for such hardware has not been very good in Linux,
mostly because of a lack of a generic API available in the mainline
kernel.
-Rather than requiring a compability break with an API change of the
+Rather than requiring a compatibility break with an API change of the
ALSA PCM interface, a new 'Compressed Data' API is introduced to
provide a control and data-streaming interface for audio DSPs.
diff --git a/Documentation/sound/oss/ALS b/Documentation/sound/oss/ALS
index d01ffbfd5808..bf10bed4574b 100644
--- a/Documentation/sound/oss/ALS
+++ b/Documentation/sound/oss/ALS
@@ -57,10 +57,10 @@ The resulting sound driver will provide the following capabilities:
DSP/PCM/audio out (L&R), FM (L&R) and Mic in (mono).
Jonathan Woithe
-jwoithe@physics.adelaide.edu.au
+jwoithe@just42.net
30 March 1998
Modified 2000-02-26 by Dave Forrest, drf5n@virginia.edu to add ALS100/ALS200
Modified 2000-04-10 by Paul Laufer, pelaufer@csupomona.edu to add ISAPnP info.
-Modified 2000-11-19 by Jonathan Woithe, jwoithe@physics.adelaide.edu.au
+Modified 2000-11-19 by Jonathan Woithe, jwoithe@just42.net
- updated information for kernel 2.4.x.
diff --git a/Documentation/sparc/README-2.5 b/Documentation/sparc/README-2.5
deleted file mode 100644
index 806fe490a56d..000000000000
--- a/Documentation/sparc/README-2.5
+++ /dev/null
@@ -1,46 +0,0 @@
-BTFIXUP
--------
-
-To build new kernels you have to issue "make image". The ready kernel
-in ELF format is placed in arch/sparc/boot/image. Explanation is below.
-
-BTFIXUP is a unique feature of Linux/sparc among other architectures,
-developed by Jakub Jelinek (I think... Obviously David S. Miller took
-part, too). It allows to boot the same kernel at different
-sub-architectures, such as sun4c, sun4m, sun4d, where SunOS uses
-different kernels. This feature is convinient for people who you move
-disks between boxes and for distrution builders.
-
-To function, BTFIXUP must link the kernel "in the draft" first,
-analyze the result, write a special stub code based on that, and
-build the final kernel with the stub (btfix.o).
-
-Kai Germaschewski improved the build system of the kernel in the 2.5 series
-significantly. Unfortunately, the traditional way of running the draft
-linking from architecture specific Makefile before the actual linking
-by generic Makefile is nearly impossible to support properly in the
-new build system. Therefore, the way we integrate BTFIXUP with the
-build system was changed in 2.5.40. Now, generic Makefile performs
-the draft linking and stores the result in file vmlinux. Architecture
-specific post-processing invokes BTFIXUP machinery and final linking
-in the same way as other architectures do bootstraps.
-
-Implications of that change are as follows.
-
-1. Hackers must type "make image" now, instead of just "make", in the same
- way as s390 people do now. It is analogous to "make bzImage" on i386.
- This does NOT affect sparc64, you continue to use "make" to build sparc64
- kernels.
-
-2. vmlinux is not the final kernel, so RPM builders have to adjust
- their spec files (if they delivered vmlinux for debugging).
- System.map generated for vmlinux is still valid.
-
-3. Scripts that produce a.out images have to be changed. First, if they
- invoke make, they have to use "make image". Second, they have to pick up
- the new kernel in arch/sparc/boot/image instead of vmlinux.
-
-4. Since we are compliant with Kai's build system now, make -j is permitted.
-
--- Pete Zaitcev
-zaitcev@yahoo.com
diff --git a/Documentation/static-keys.txt b/Documentation/static-keys.txt
index d93f3c00f245..9f5263d3152c 100644
--- a/Documentation/static-keys.txt
+++ b/Documentation/static-keys.txt
@@ -235,7 +235,7 @@ label case adds:
6 (mov) + 2 (test) + 2 (jne) = 10 - 5 (5 byte jump 0) = 5 addition bytes.
If we then include the padding bytes, the jump label code saves, 16 total bytes
-of instruction memory for this small fucntion. In this case the non-jump label
+of instruction memory for this small function. In this case the non-jump label
function is 80 bytes long. Thus, we have have saved 20% of the instruction
footprint. We can in fact improve this even further, since the 5-byte no-op
really can be a 2-byte no-op since we can reach the branch with a 2-byte jmp.
diff --git a/Documentation/usb/dwc3.txt b/Documentation/usb/dwc3.txt
index 7b590edae145..1d02c01d1c7c 100644
--- a/Documentation/usb/dwc3.txt
+++ b/Documentation/usb/dwc3.txt
@@ -28,7 +28,7 @@ Please pick something while reading :)
none
- primary handler of the EP-interrupt
- reads the event and tries to process it. Everything that requries
+ reads the event and tries to process it. Everything that requires
sleeping is handed over to the Thread. The event is saved in an
per-endpoint data-structure.
We probably have to pay attention not to process events once we
diff --git a/Documentation/usb/functionfs.txt b/Documentation/usb/functionfs.txt
new file mode 100644
index 000000000000..eaaaea019fc7
--- /dev/null
+++ b/Documentation/usb/functionfs.txt
@@ -0,0 +1,67 @@
+*How FunctionFS works*
+
+From kernel point of view it is just a composite function with some
+unique behaviour. It may be added to an USB configuration only after
+the user space driver has registered by writing descriptors and
+strings (the user space program has to provide the same information
+that kernel level composite functions provide when they are added to
+the configuration).
+
+This in particular means that the composite initialisation functions
+may not be in init section (ie. may not use the __init tag).
+
+From user space point of view it is a file system which when
+mounted provides an "ep0" file. User space driver need to
+write descriptors and strings to that file. It does not need
+to worry about endpoints, interfaces or strings numbers but
+simply provide descriptors such as if the function was the
+only one (endpoints and strings numbers starting from one and
+interface numbers starting from zero). The FunctionFS changes
+them as needed also handling situation when numbers differ in
+different configurations.
+
+When descriptors and strings are written "ep#" files appear
+(one for each declared endpoint) which handle communication on
+a single endpoint. Again, FunctionFS takes care of the real
+numbers and changing of the configuration (which means that
+"ep1" file may be really mapped to (say) endpoint 3 (and when
+configuration changes to (say) endpoint 2)). "ep0" is used
+for receiving events and handling setup requests.
+
+When all files are closed the function disables itself.
+
+What I also want to mention is that the FunctionFS is designed in such
+a way that it is possible to mount it several times so in the end
+a gadget could use several FunctionFS functions. The idea is that
+each FunctionFS instance is identified by the device name used
+when mounting.
+
+One can imagine a gadget that has an Ethernet, MTP and HID interfaces
+where the last two are implemented via FunctionFS. On user space
+level it would look like this:
+
+$ insmod g_ffs.ko idVendor=<ID> iSerialNumber=<string> functions=mtp,hid
+$ mkdir /dev/ffs-mtp && mount -t functionfs mtp /dev/ffs-mtp
+$ ( cd /dev/ffs-mtp && mtp-daemon ) &
+$ mkdir /dev/ffs-hid && mount -t functionfs hid /dev/ffs-hid
+$ ( cd /dev/ffs-hid && hid-daemon ) &
+
+On kernel level the gadget checks ffs_data->dev_name to identify
+whether it's FunctionFS designed for MTP ("mtp") or HID ("hid").
+
+If no "functions" module parameters is supplied, the driver accepts
+just one function with any name.
+
+When "functions" module parameter is supplied, only functions
+with listed names are accepted. In particular, if the "functions"
+parameter's value is just a one-element list, then the behaviour
+is similar to when there is no "functions" at all; however,
+only a function with the specified name is accepted.
+
+The gadget is registered only after all the declared function
+filesystems have been mounted and USB descriptors of all functions
+have been written to their ep0's.
+
+Conversely, the gadget is unregistered after the first USB function
+closes its endpoints.
+
diff --git a/Documentation/usb/wusb-cbaf b/Documentation/usb/wusb-cbaf
index 426ddaaef96f..8b3d43efce90 100644
--- a/Documentation/usb/wusb-cbaf
+++ b/Documentation/usb/wusb-cbaf
@@ -36,7 +36,7 @@ COMMAND/ARGS are
get-cdid DEVICE
- Get the device ID associated to the HOST-CHDI we sent with
+ Get the device ID associated to the HOST-CHID we sent with
'set-chid'. We might not know about it.
set-cc DEVICE
diff --git a/Documentation/video4linux/README.cpia2 b/Documentation/video4linux/README.cpia2
index ce8213d28b67..38e742fd0df7 100644
--- a/Documentation/video4linux/README.cpia2
+++ b/Documentation/video4linux/README.cpia2
@@ -12,7 +12,7 @@ gqcam application to view this stream.
The driver is implemented as two kernel modules. The cpia2 module
contains the camera functions and the V4L interface. The cpia2_usb module
contains usb specific functions. The main reason for this was the size of the
-module was getting out of hand, so I separted them. It is not likely that
+module was getting out of hand, so I separated them. It is not likely that
there will be a parallel port version.
FEATURES:
diff --git a/Documentation/virtual/virtio-spec.txt b/Documentation/virtual/virtio-spec.txt
index da094737e2f8..0d6ec85481cb 100644
--- a/Documentation/virtual/virtio-spec.txt
+++ b/Documentation/virtual/virtio-spec.txt
@@ -1,11 +1,11 @@
[Generated file: see http://ozlabs.org/~rusty/virtio-spec/]
Virtio PCI Card Specification
-v0.9.1 DRAFT
+v0.9.5 DRAFT
-
-Rusty Russell <rusty@rustcorp.com.au>IBM Corporation (Editor)
+Rusty Russell <rusty@rustcorp.com.au> IBM Corporation (Editor)
-2011 August 1.
+2012 May 7.
Purpose and Description
@@ -68,11 +68,11 @@ and consists of three parts:
+-------------------+-----------------------------------+-----------+
-When the driver wants to send buffers to the device, it puts them
-in one or more slots in the descriptor table, and writes the
-descriptor indices into the available ring. It then notifies the
-device. When the device has finished with the buffers, it writes
-the descriptors into the used ring, and sends an interrupt.
+When the driver wants to send a buffer to the device, it fills in
+a slot in the descriptor table (or chains several together), and
+writes the descriptor index into the available ring. It then
+notifies the device. When the device has finished a buffer, it
+writes the descriptor into the used ring, and sends an interrupt.
Specification
@@ -106,8 +106,14 @@ for informational purposes by the guest).
+----------------------+--------------------+---------------+
| 6 | ioMemory | - |
+----------------------+--------------------+---------------+
+| 7 | rpmsg | Appendix H |
++----------------------+--------------------+---------------+
+| 8 | SCSI host | Appendix I |
++----------------------+--------------------+---------------+
| 9 | 9P transport | - |
+----------------------+--------------------+---------------+
+| 10 | mac80211 wlan | - |
++----------------------+--------------------+---------------+
Device Configuration
@@ -127,7 +133,7 @@ Note that this is possible because while the virtio header is PCI
the native endian of the guest (where such distinction is
applicable).
- Device Initialization Sequence
+ Device Initialization Sequence<sub:Device-Initialization-Sequence>
We start with an overview of device initialization, then expand
on the details of the device and how each step is preformed.
@@ -177,7 +183,10 @@ The virtio header looks as follows:
If MSI-X is enabled for the device, two additional fields
-immediately follow this header:
+immediately follow this header:[footnote:
+ie. once you enable MSI-X on the device, the other fields move.
+If you turn it off again, they move back!
+]
+------------++----------------+--------+
@@ -191,20 +200,6 @@ immediately follow this header:
+------------++----------------+--------+
-Finally, if feature bits (VIRTIO_F_FEATURES_HI) this is
-immediately followed by two additional fields:
-
-
-+------------++----------------------+----------------------
-| Bits || 32 | 32
-+------------++----------------------+----------------------
-| Read/Write || R | R+W
-+------------++----------------------+----------------------
-| Purpose || Device | Guest
-| || Features bits 32:63 | Features bits 32:63
-+------------++----------------------+----------------------
-
-
Immediately following these general headers, there may be
device-specific headers:
@@ -238,31 +233,25 @@ at least one bit should be set:
may be a significant (or infinite) delay before setting this
bit.
- DRIVER_OK (3) Indicates that the driver is set up and ready to
+ DRIVER_OK (4) Indicates that the driver is set up and ready to
drive the device.
- FAILED (8) Indicates that something went wrong in the guest,
+ FAILED (128) Indicates that something went wrong in the guest,
and it has given up on the device. This could be an internal
error, or the driver didn't like the device for some reason, or
even a fatal error during device operation. The device must be
reset before attempting to re-initialize.
- Feature Bits
+ Feature Bits<sub:Feature-Bits>
-The least significant 31 bits of the first configuration field
-indicates the features that the device supports (the high bit is
-reserved, and will be used to indicate the presence of future
-feature bits elsewhere). If more than 31 feature bits are
-supported, the device indicates so by setting feature bit 31 (see
-[cha:Reserved-Feature-Bits]). The bits are allocated as follows:
+Thefirst configuration field indicates the features that the
+device supports. The bits are allocated as follows:
0 to 23 Feature bits for the specific device type
- 24 to 40 Feature bits reserved for extensions to the queue and
+ 24 to 32 Feature bits reserved for extensions to the queue and
feature negotiation mechanisms
- 41 to 63 Feature bits reserved for future extensions
-
For example, feature bit 0 for a network device (i.e. Subsystem
Device ID 1) indicates that the device supports checksumming of
packets.
@@ -286,10 +275,6 @@ will not see that feature bit in the Device Features field and
can go into backwards compatibility mode (or, for poor
implementations, set the FAILED Device Status bit).
-Access to feature bits 32 to 63 is enabled by Guest by setting
-feature bit 31. If this bit is unset, Device must assume that all
-feature bits > 31 are unset.
-
Configuration/Queue Vectors
When MSI-X capability is present and enabled in the device
@@ -324,7 +309,7 @@ success, the previously written value is returned, and on
failure, NO_VECTOR is returned. If a mapping failure is detected,
the driver can retry mapping with fewervectors, or disable MSI-X.
- Virtqueue Configuration
+ Virtqueue Configuration<sec:Virtqueue-Configuration>
As a device can have zero or more virtqueues for bulk data
transport (for example, the network driver has two), the driver
@@ -587,7 +572,7 @@ and Red Hat under the (3-clause) BSD license so that it can be
freely used by all other projects, and is reproduced (with slight
variation to remove Linux assumptions) in Appendix A.
- Device Operation
+ Device Operation<sec:Device-Operation>
There are two parts to device operation: supplying new buffers to
the device, and processing used buffers from the device. As an
@@ -813,7 +798,7 @@ vring.used->ring[vq->last_seen_used%vsz];
}
- Dealing With Configuration Changes
+ Dealing With Configuration Changes<sub:Dealing-With-Configuration>
Some virtio PCI devices can change the device configuration
state, as reflected in the virtio header in the PCI configuration
@@ -1260,18 +1245,6 @@ Currently there are five device-independent feature bits defined:
driver should ignore the used_event field; the device should
ignore the avail_event field; the flags field is used
- VIRTIO_F_BAD_FEATURE(30) This feature should never be
- negotiated by the guest; doing so is an indication that the
- guest is faulty[footnote:
-An experimental virtio PCI driver contained in Linux version
-2.6.25 had this problem, and this feature bit can be used to
-detect it.
-]
-
- VIRTIO_F_FEATURES_HIGH(31) This feature indicates that the
- device supports feature bits 32:63. If unset, feature bits
- 32:63 are unset.
-
Appendix C: Network Device
The virtio network device is a virtual ethernet card, and is the
@@ -1335,11 +1308,17 @@ were required.
VIRTIO_NET_F_CTRL_VLAN (19) Control channel VLAN filtering.
+ VIRTIO_NET_F_GUEST_ANNOUNCE(21) Guest can send gratuitous
+ packets.
+
Device configuration layout Two configuration fields are
currently defined. The mac address field always exists (though
is only valid if VIRTIO_NET_F_MAC is set), and the status field
- only exists if VIRTIO_NET_F_STATUS is set. Only one bit is
- currently defined for the status field: VIRTIO_NET_S_LINK_UP. #define VIRTIO_NET_S_LINK_UP 1
+ only exists if VIRTIO_NET_F_STATUS is set. Two read-only bits
+ are currently defined for the status field:
+ VIRTIO_NET_S_LINK_UP and VIRTIO_NET_S_ANNOUNCE. #define VIRTIO_NET_S_LINK_UP 1
+
+#define VIRTIO_NET_S_ANNOUNCE 2
@@ -1377,12 +1356,19 @@ struct virtio_net_config {
packets by negotating the VIRTIO_NET_F_CSUM feature. This “
checksum offload” is a common feature on modern network cards.
- If that feature is negotiated, a driver can use TCP or UDP
- segmentation offload by negotiating the VIRTIO_NET_F_HOST_TSO4
- (IPv4 TCP), VIRTIO_NET_F_HOST_TSO6 (IPv6 TCP) and
- VIRTIO_NET_F_HOST_UFO (UDP fragmentation) features. It should
- not send TCP packets requiring segmentation offload which have
- the Explicit Congestion Notification bit set, unless the
+ If that feature is negotiated[footnote:
+ie. VIRTIO_NET_F_HOST_TSO* and VIRTIO_NET_F_HOST_UFO are
+dependent on VIRTIO_NET_F_CSUM; a dvice which offers the offload
+features must offer the checksum feature, and a driver which
+accepts the offload features must accept the checksum feature.
+Similar logic applies to the VIRTIO_NET_F_GUEST_TSO4 features
+depending on VIRTIO_NET_F_GUEST_CSUM.
+], a driver can use TCP or UDP segmentation offload by
+ negotiating the VIRTIO_NET_F_HOST_TSO4 (IPv4 TCP),
+ VIRTIO_NET_F_HOST_TSO6 (IPv6 TCP) and VIRTIO_NET_F_HOST_UFO
+ (UDP fragmentation) features. It should not send TCP packets
+ requiring segmentation offload which have the Explicit
+ Congestion Notification bit set, unless the
VIRTIO_NET_F_HOST_ECN feature is negotiated.[footnote:
This is a common restriction in real, older network cards.
]
@@ -1403,7 +1389,7 @@ segmentation, if both guests are amenable.
Packets are transmitted by placing them in the transmitq, and
buffers for incoming packets are placed in the receiveq. In each
-case, the packet itself is preceded by a header:
+case, the packet itself is preceeded by a header:
struct virtio_net_hdr {
@@ -1462,9 +1448,10 @@ It will have a 14 byte ethernet header and 20 byte IP header
followed by the TCP header (with the TCP checksum field 16 bytes
into that header). csum_start will be 14+20 = 34 (the TCP
checksum includes the header), and csum_offset will be 16. The
-value in the TCP checksum field will be the sum of the TCP pseudo
-header, so that replacing it by the ones' complement checksum of
-the TCP header and body will give the correct result.
+value in the TCP checksum field should be initialized to the sum
+of the TCP pseudo header, so that replacing it by the ones'
+complement checksum of the TCP header and body will give the
+correct result.
]
<enu:If-the-driver>If the driver negotiated
@@ -1483,8 +1470,8 @@ Due to various bugs in implementations, this field is not useful
as a guarantee of the transport header size.
]
- gso_size is the size of the packet beyond that header (ie.
- MSS).
+ gso_size is the maximum size of each packet beyond that header
+ (ie. MSS).
If the driver negotiated the VIRTIO_NET_F_HOST_ECN feature, the
VIRTIO_NET_HDR_GSO_ECN bit may be set in “gso_type” as well,
@@ -1567,7 +1554,9 @@ Processing packet involves:
If the VIRTIO_NET_F_GUEST_TSO4, TSO6 or UFO options were
negotiated, then the “gso_type” may be something other than
VIRTIO_NET_HDR_GSO_NONE, and the “gso_size” field indicates the
- desired MSS (see [enu:If-the-driver]).Control Virtqueue
+ desired MSS (see [enu:If-the-driver]).
+
+ Control Virtqueue
The driver uses the control virtqueue (if VIRTIO_NET_F_VTRL_VQ is
negotiated) to send commands to manipulate various features of
@@ -1642,7 +1631,7 @@ struct virtio_net_ctrl_mac {
The device can filter incoming packets by any number of
destination MAC addresses.[footnote:
-Since there are no guarantees, it can use a hash filter
+Since there are no guarentees, it can use a hash filter
orsilently switch to allmulti or promiscuous mode if it is given
too many addresses.
] This table is set using the class VIRTIO_NET_CTRL_MAC and the
@@ -1665,6 +1654,38 @@ can control a VLAN filter table in the device.
Both the VIRTIO_NET_CTRL_VLAN_ADD and VIRTIO_NET_CTRL_VLAN_DEL
command take a 16-bit VLAN id as the command-specific-data.
+ Gratuitous Packet Sending
+
+If the driver negotiates the VIRTIO_NET_F_GUEST_ANNOUNCE (depends
+on VIRTIO_NET_F_CTRL_VQ), it can ask the guest to send gratuitous
+packets; this is usually done after the guest has been physically
+migrated, and needs to announce its presence on the new network
+links. (As hypervisor does not have the knowledge of guest
+network configuration (eg. tagged vlan) it is simplest to prod
+the guest in this way).
+
+#define VIRTIO_NET_CTRL_ANNOUNCE 3
+
+ #define VIRTIO_NET_CTRL_ANNOUNCE_ACK 0
+
+The Guest needs to check VIRTIO_NET_S_ANNOUNCE bit in status
+field when it notices the changes of device configuration. The
+command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that
+driver has recevied the notification and device would clear the
+VIRTIO_NET_S_ANNOUNCE bit in the status filed after it received
+this command.
+
+Processing this notification involves:
+
+ Sending the gratuitous packets or marking there are pending
+ gratuitous packets to be sent and letting deferred routine to
+ send them.
+
+ Sending VIRTIO_NET_CTRL_ANNOUNCE_ACK command through control
+ vq.
+
+ .
+
Appendix D: Block Device
The virtio block device is a simple virtual block device (ie.
@@ -1699,8 +1720,6 @@ device except where noted.
VIRTIO_BLK_F_FLUSH (9) Cache flush command support.
-
-
Device configuration layout The capacity of the device
(expressed in 512-byte sectors) is always present. The
availability of the others all depend on various feature bits
@@ -1743,8 +1762,6 @@ device except where noted.
If the VIRTIO_BLK_F_RO feature is set by the device, any write
requests will fail.
-
-
Device Operation
The driver queues requests to the virtqueue, and they are used by
@@ -1805,7 +1822,7 @@ the FLUSH and FLUSH_OUT types are equivalent, the device does not
distinguish between them
]). If the device has VIRTIO_BLK_F_BARRIER feature the high bit
(VIRTIO_BLK_T_BARRIER) indicates that this request acts as a
-barrier and that all preceding requests must be complete before
+barrier and that all preceeding requests must be complete before
this one, and all following requests must not be started until
this is complete. Note that a barrier does not flush caches in
the underlying backend device in host, and thus does not serve as
@@ -2118,7 +2135,7 @@ This is historical, and independent of the guest page size
Otherwise, the guest may begin to re-use pages previously given
to the balloon before the device has acknowledged their
- withdrawal. [footnote:
+ withdrawl. [footnote:
In this case, deflation advice is merely a courtesy
]
@@ -2198,3 +2215,996 @@ as follows:
VIRTIO_BALLOON_S_MEMTOT The total amount of memory available
(in bytes).
+Appendix H: Rpmsg: Remote Processor Messaging
+
+Virtio rpmsg devices represent remote processors on the system
+which run in asymmetric multi-processing (AMP) configuration, and
+which are usually used to offload cpu-intensive tasks from the
+main application processor (a typical SoC methodology).
+
+Virtio is being used to communicate with those remote processors;
+empty buffers are placed in one virtqueue for receiving messages,
+and non-empty buffers, containing outbound messages, are enqueued
+in a second virtqueue for transmission.
+
+Numerous communication channels can be multiplexed over those two
+virtqueues, so different entities, running on the application and
+remote processor, can directly communicate in a point-to-point
+fashion.
+
+ Configuration
+
+ Subsystem Device ID 7
+
+ Virtqueues 0:receiveq. 1:transmitq.
+
+ Feature bits
+
+ VIRTIO_RPMSG_F_NS (0) Device sends (and capable of receiving)
+ name service messages announcing the creation (or
+ destruction) of a channel:/**
+
+ * struct rpmsg_ns_msg - dynamic name service announcement
+message
+
+ * @name: name of remote service that is published
+
+ * @addr: address of remote service that is published
+
+ * @flags: indicates whether service is created or destroyed
+
+ *
+
+ * This message is sent across to publish a new service (or
+announce
+
+ * about its removal). When we receives these messages, an
+appropriate
+
+ * rpmsg channel (i.e device) is created/destroyed.
+
+ */
+
+struct rpmsg_ns_msgoon_config {
+
+ char name[RPMSG_NAME_SIZE];
+
+ u32 addr;
+
+ u32 flags;
+
+} __packed;
+
+
+
+/**
+
+ * enum rpmsg_ns_flags - dynamic name service announcement flags
+
+ *
+
+ * @RPMSG_NS_CREATE: a new remote service was just created
+
+ * @RPMSG_NS_DESTROY: a remote service was just destroyed
+
+ */
+
+enum rpmsg_ns_flags {
+
+ RPMSG_NS_CREATE = 0,
+
+ RPMSG_NS_DESTROY = 1,
+
+};
+
+ Device configuration layout
+
+At his point none currently defined.
+
+ Device Initialization
+
+ The initialization routine should identify the receive and
+ transmission virtqueues.
+
+ The receive virtqueue should be filled with receive buffers.
+
+ Device Operation
+
+Messages are transmitted by placing them in the transmitq, and
+buffers for inbound messages are placed in the receiveq. In any
+case, messages are always preceded by the following header: /**
+
+ * struct rpmsg_hdr - common header for all rpmsg messages
+
+ * @src: source address
+
+ * @dst: destination address
+
+ * @reserved: reserved for future use
+
+ * @len: length of payload (in bytes)
+
+ * @flags: message flags
+
+ * @data: @len bytes of message payload data
+
+ *
+
+ * Every message sent(/received) on the rpmsg bus begins with
+this header.
+
+ */
+
+struct rpmsg_hdr {
+
+ u32 src;
+
+ u32 dst;
+
+ u32 reserved;
+
+ u16 len;
+
+ u16 flags;
+
+ u8 data[0];
+
+} __packed;
+
+Appendix I: SCSI Host Device
+
+The virtio SCSI host device groups together one or more virtual
+logical units (such as disks), and allows communicating to them
+using the SCSI protocol. An instance of the device represents a
+SCSI host to which many targets and LUNs are attached.
+
+The virtio SCSI device services two kinds of requests:
+
+ command requests for a logical unit;
+
+ task management functions related to a logical unit, target or
+ command.
+
+The device is also able to send out notifications about added and
+removed logical units. Together, these capabilities provide a
+SCSI transport protocol that uses virtqueues as the transfer
+medium. In the transport protocol, the virtio driver acts as the
+initiator, while the virtio SCSI host provides one or more
+targets that receive and process the requests.
+
+ Configuration
+
+ Subsystem Device ID 8
+
+ Virtqueues 0:controlq; 1:eventq; 2..n:request queues.
+
+ Feature bits
+
+ VIRTIO_SCSI_F_INOUT (0) A single request can include both
+ read-only and write-only data buffers.
+
+ VIRTIO_SCSI_F_HOTPLUG (1) The host should enable
+ hot-plug/hot-unplug of new LUNs and targets on the SCSI bus.
+
+ Device configuration layout All fields of this configuration
+ are always available. sense_size and cdb_size are writable by
+ the guest.struct virtio_scsi_config {
+
+ u32 num_queues;
+
+ u32 seg_max;
+
+ u32 max_sectors;
+
+ u32 cmd_per_lun;
+
+ u32 event_info_size;
+
+ u32 sense_size;
+
+ u32 cdb_size;
+
+ u16 max_channel;
+
+ u16 max_target;
+
+ u32 max_lun;
+
+};
+
+ num_queues is the total number of request virtqueues exposed by
+ the device. The driver is free to use only one request queue,
+ or it can use more to achieve better performance.
+
+ seg_max is the maximum number of segments that can be in a
+ command. A bidirectional command can include seg_max input
+ segments and seg_max output segments.
+
+ max_sectors is a hint to the guest about the maximum transfer
+ size it should use.
+
+ cmd_per_lun is a hint to the guest about the maximum number of
+ linked commands it should send to one LUN. The actual value
+ to be used is the minimum of cmd_per_lun and the virtqueue
+ size.
+
+ event_info_size is the maximum size that the device will fill
+ for buffers that the driver places in the eventq. The driver
+ should always put buffers at least of this size. It is
+ written by the device depending on the set of negotated
+ features.
+
+ sense_size is the maximum size of the sense data that the
+ device will write. The default value is written by the device
+ and will always be 96, but the driver can modify it. It is
+ restored to the default when the device is reset.
+
+ cdb_size is the maximum size of the CDB that the driver will
+ write. The default value is written by the device and will
+ always be 32, but the driver can likewise modify it. It is
+ restored to the default when the device is reset.
+
+ max_channel, max_target and max_lun can be used by the driver
+ as hints to constrain scanning the logical units on the
+ host.h
+
+ Device Initialization
+
+The initialization routine should first of all discover the
+device's virtqueues.
+
+If the driver uses the eventq, it should then place at least a
+buffer in the eventq.
+
+The driver can immediately issue requests (for example, INQUIRY
+or REPORT LUNS) or task management functions (for example, I_T
+RESET).
+
+ Device Operation: request queues
+
+The driver queues requests to an arbitrary request queue, and
+they are used by the device on that same queue. It is the
+responsibility of the driver to ensure strict request ordering
+for commands placed on different queues, because they will be
+consumed with no order constraints.
+
+Requests have the following format:
+
+struct virtio_scsi_req_cmd {
+
+ // Read-only
+
+ u8 lun[8];
+
+ u64 id;
+
+ u8 task_attr;
+
+ u8 prio;
+
+ u8 crn;
+
+ char cdb[cdb_size];
+
+ char dataout[];
+
+ // Write-only part
+
+ u32 sense_len;
+
+ u32 residual;
+
+ u16 status_qualifier;
+
+ u8 status;
+
+ u8 response;
+
+ u8 sense[sense_size];
+
+ char datain[];
+
+};
+
+
+
+/* command-specific response values */
+
+#define VIRTIO_SCSI_S_OK 0
+
+#define VIRTIO_SCSI_S_OVERRUN 1
+
+#define VIRTIO_SCSI_S_ABORTED 2
+
+#define VIRTIO_SCSI_S_BAD_TARGET 3
+
+#define VIRTIO_SCSI_S_RESET 4
+
+#define VIRTIO_SCSI_S_BUSY 5
+
+#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6
+
+#define VIRTIO_SCSI_S_TARGET_FAILURE 7
+
+#define VIRTIO_SCSI_S_NEXUS_FAILURE 8
+
+#define VIRTIO_SCSI_S_FAILURE 9
+
+
+
+/* task_attr */
+
+#define VIRTIO_SCSI_S_SIMPLE 0
+
+#define VIRTIO_SCSI_S_ORDERED 1
+
+#define VIRTIO_SCSI_S_HEAD 2
+
+#define VIRTIO_SCSI_S_ACA 3
+
+The lun field addresses a target and logical unit in the
+virtio-scsi device's SCSI domain. The only supported format for
+the LUN field is: first byte set to 1, second byte set to target,
+third and fourth byte representing a single level LUN structure,
+followed by four zero bytes. With this representation, a
+virtio-scsi device can serve up to 256 targets and 16384 LUNs per
+target.
+
+The id field is the command identifier (“tag”).
+
+task_attr, prio and crn should be left to zero. task_attr defines
+the task attribute as in the table above, but all task attributes
+may be mapped to SIMPLE by the device; crn may also be provided
+by clients, but is generally expected to be 0. The maximum CRN
+value defined by the protocol is 255, since CRN is stored in an
+8-bit integer.
+
+All of these fields are defined in SAM. They are always
+read-only, as are the cdb and dataout field. The cdb_size is
+taken from the configuration space.
+
+sense and subsequent fields are always write-only. The sense_len
+field indicates the number of bytes actually written to the sense
+buffer. The residual field indicates the residual size,
+calculated as “data_length - number_of_transferred_bytes”, for
+read or write operations. For bidirectional commands, the
+number_of_transferred_bytes includes both read and written bytes.
+A residual field that is less than the size of datain means that
+the dataout field was processed entirely. A residual field that
+exceeds the size of datain means that the dataout field was
+processed partially and the datain field was not processed at
+all.
+
+The status byte is written by the device to be the status code as
+defined in SAM.
+
+The response byte is written by the device to be one of the
+following:
+
+ VIRTIO_SCSI_S_OK when the request was completed and the status
+ byte is filled with a SCSI status code (not necessarily
+ "GOOD").
+
+ VIRTIO_SCSI_S_OVERRUN if the content of the CDB requires
+ transferring more data than is available in the data buffers.
+
+ VIRTIO_SCSI_S_ABORTED if the request was cancelled due to an
+ ABORT TASK or ABORT TASK SET task management function.
+
+ VIRTIO_SCSI_S_BAD_TARGET if the request was never processed
+ because the target indicated by the lun field does not exist.
+
+ VIRTIO_SCSI_S_RESET if the request was cancelled due to a bus
+ or device reset (including a task management function).
+
+ VIRTIO_SCSI_S_TRANSPORT_FAILURE if the request failed due to a
+ problem in the connection between the host and the target
+ (severed link).
+
+ VIRTIO_SCSI_S_TARGET_FAILURE if the target is suffering a
+ failure and the guest should not retry on other paths.
+
+ VIRTIO_SCSI_S_NEXUS_FAILURE if the nexus is suffering a failure
+ but retrying on other paths might yield a different result.
+
+ VIRTIO_SCSI_S_BUSY if the request failed but retrying on the
+ same path should work.
+
+ VIRTIO_SCSI_S_FAILURE for other host or guest error. In
+ particular, if neither dataout nor datain is empty, and the
+ VIRTIO_SCSI_F_INOUT feature has not been negotiated, the
+ request will be immediately returned with a response equal to
+ VIRTIO_SCSI_S_FAILURE.
+
+ Device Operation: controlq
+
+The controlq is used for other SCSI transport operations.
+Requests have the following format:
+
+struct virtio_scsi_ctrl {
+
+ u32 type;
+
+ ...
+
+ u8 response;
+
+};
+
+
+
+/* response values valid for all commands */
+
+#define VIRTIO_SCSI_S_OK 0
+
+#define VIRTIO_SCSI_S_BAD_TARGET 3
+
+#define VIRTIO_SCSI_S_BUSY 5
+
+#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6
+
+#define VIRTIO_SCSI_S_TARGET_FAILURE 7
+
+#define VIRTIO_SCSI_S_NEXUS_FAILURE 8
+
+#define VIRTIO_SCSI_S_FAILURE 9
+
+#define VIRTIO_SCSI_S_INCORRECT_LUN 12
+
+The type identifies the remaining fields.
+
+The following commands are defined:
+
+ Task management function
+#define VIRTIO_SCSI_T_TMF 0
+
+
+
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK 0
+
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1
+
+#define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2
+
+#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3
+
+#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4
+
+#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5
+
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK 6
+
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7
+
+
+
+struct virtio_scsi_ctrl_tmf
+
+{
+
+ // Read-only part
+
+ u32 type;
+
+ u32 subtype;
+
+ u8 lun[8];
+
+ u64 id;
+
+ // Write-only part
+
+ u8 response;
+
+}
+
+
+
+/* command-specific response values */
+
+#define VIRTIO_SCSI_S_FUNCTION_COMPLETE 0
+
+#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10
+
+#define VIRTIO_SCSI_S_FUNCTION_REJECTED 11
+
+ The type is VIRTIO_SCSI_T_TMF; the subtype field defines. All
+ fields except response are filled by the driver. The subtype
+ field must always be specified and identifies the requested
+ task management function.
+
+ Other fields may be irrelevant for the requested TMF; if so,
+ they are ignored but they should still be present. The lun
+ field is in the same format specified for request queues; the
+ single level LUN is ignored when the task management function
+ addresses a whole I_T nexus. When relevant, the value of the id
+ field is matched against the id values passed on the requestq.
+
+ The outcome of the task management function is written by the
+ device in the response field. The command-specific response
+ values map 1-to-1 with those defined in SAM.
+
+ Asynchronous notification query
+#define VIRTIO_SCSI_T_AN_QUERY 1
+
+
+
+struct virtio_scsi_ctrl_an {
+
+ // Read-only part
+
+ u32 type;
+
+ u8 lun[8];
+
+ u32 event_requested;
+
+ // Write-only part
+
+ u32 event_actual;
+
+ u8 response;
+
+}
+
+
+
+#define VIRTIO_SCSI_EVT_ASYNC_OPERATIONAL_CHANGE 2
+
+#define VIRTIO_SCSI_EVT_ASYNC_POWER_MGMT 4
+
+#define VIRTIO_SCSI_EVT_ASYNC_EXTERNAL_REQUEST 8
+
+#define VIRTIO_SCSI_EVT_ASYNC_MEDIA_CHANGE 16
+
+#define VIRTIO_SCSI_EVT_ASYNC_MULTI_HOST 32
+
+#define VIRTIO_SCSI_EVT_ASYNC_DEVICE_BUSY 64
+
+ By sending this command, the driver asks the device which
+ events the given LUN can report, as described in paragraphs 6.6
+ and A.6 of the SCSI MMC specification. The driver writes the
+ events it is interested in into the event_requested; the device
+ responds by writing the events that it supports into
+ event_actual.
+
+ The type is VIRTIO_SCSI_T_AN_QUERY. The lun and event_requested
+ fields are written by the driver. The event_actual and response
+ fields are written by the device.
+
+ No command-specific values are defined for the response byte.
+
+ Asynchronous notification subscription
+#define VIRTIO_SCSI_T_AN_SUBSCRIBE 2
+
+
+
+struct virtio_scsi_ctrl_an {
+
+ // Read-only part
+
+ u32 type;
+
+ u8 lun[8];
+
+ u32 event_requested;
+
+ // Write-only part
+
+ u32 event_actual;
+
+ u8 response;
+
+}
+
+ By sending this command, the driver asks the specified LUN to
+ report events for its physical interface, again as described in
+ the SCSI MMC specification. The driver writes the events it is
+ interested in into the event_requested; the device responds by
+ writing the events that it supports into event_actual.
+
+ Event types are the same as for the asynchronous notification
+ query message.
+
+ The type is VIRTIO_SCSI_T_AN_SUBSCRIBE. The lun and
+ event_requested fields are written by the driver. The
+ event_actual and response fields are written by the device.
+
+ No command-specific values are defined for the response byte.
+
+ Device Operation: eventq
+
+The eventq is used by the device to report information on logical
+units that are attached to it. The driver should always leave a
+few buffers ready in the eventq. In general, the device will not
+queue events to cope with an empty eventq, and will end up
+dropping events if it finds no buffer ready. However, when
+reporting events for many LUNs (e.g. when a whole target
+disappears), the device can throttle events to avoid dropping
+them. For this reason, placing 10-15 buffers on the event queue
+should be enough.
+
+Buffers are placed in the eventq and filled by the device when
+interesting events occur. The buffers should be strictly
+write-only (device-filled) and the size of the buffers should be
+at least the value given in the device's configuration
+information.
+
+Buffers returned by the device on the eventq will be referred to
+as "events" in the rest of this section. Events have the
+following format:
+
+#define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000
+
+
+
+struct virtio_scsi_event {
+
+ // Write-only part
+
+ u32 event;
+
+ ...
+
+}
+
+If bit 31 is set in the event field, the device failed to report
+an event due to missing buffers. In this case, the driver should
+poll the logical units for unit attention conditions, and/or do
+whatever form of bus scan is appropriate for the guest operating
+system.
+
+Other data that the device writes to the buffer depends on the
+contents of the event field. The following events are defined:
+
+ No event
+#define VIRTIO_SCSI_T_NO_EVENT 0
+
+ This event is fired in the following cases:
+
+ When the device detects in the eventq a buffer that is shorter
+ than what is indicated in the configuration field, it might
+ use it immediately and put this dummy value in the event
+ field. A well-written driver will never observe this
+ situation.
+
+ When events are dropped, the device may signal this event as
+ soon as the drivers makes a buffer available, in order to
+ request action from the driver. In this case, of course, this
+ event will be reported with the VIRTIO_SCSI_T_EVENTS_MISSED
+ flag.
+
+ Transport reset
+#define VIRTIO_SCSI_T_TRANSPORT_RESET 1
+
+
+
+struct virtio_scsi_event_reset {
+
+ // Write-only part
+
+ u32 event;
+
+ u8 lun[8];
+
+ u32 reason;
+
+}
+
+
+
+#define VIRTIO_SCSI_EVT_RESET_HARD 0
+
+#define VIRTIO_SCSI_EVT_RESET_RESCAN 1
+
+#define VIRTIO_SCSI_EVT_RESET_REMOVED 2
+
+ By sending this event, the device signals that a logical unit
+ on a target has been reset, including the case of a new device
+ appearing or disappearing on the bus.The device fills in all
+ fields. The event field is set to
+ VIRTIO_SCSI_T_TRANSPORT_RESET. The lun field addresses a
+ logical unit in the SCSI host.
+
+ The reason value is one of the three #define values appearing
+ above:
+
+ VIRTIO_SCSI_EVT_RESET_REMOVED (“LUN/target removed”) is used if
+ the target or logical unit is no longer able to receive
+ commands.
+
+ VIRTIO_SCSI_EVT_RESET_HARD (“LUN hard reset”) is used if the
+ logical unit has been reset, but is still present.
+
+ VIRTIO_SCSI_EVT_RESET_RESCAN (“rescan LUN/target”) is used if a
+ target or logical unit has just appeared on the device.
+
+ The “removed” and “rescan” events, when sent for LUN 0, may
+ apply to the entire target. After receiving them the driver
+ should ask the initiator to rescan the target, in order to
+ detect the case when an entire target has appeared or
+ disappeared. These two events will never be reported unless the
+ VIRTIO_SCSI_F_HOTPLUG feature was negotiated between the host
+ and the guest.
+
+ Events will also be reported via sense codes (this obviously
+ does not apply to newly appeared buses or targets, since the
+ application has never discovered them):
+
+ “LUN/target removed” maps to sense key ILLEGAL REQUEST, asc
+ 0x25, ascq 0x00 (LOGICAL UNIT NOT SUPPORTED)
+
+ “LUN hard reset” maps to sense key UNIT ATTENTION, asc 0x29
+ (POWER ON, RESET OR BUS DEVICE RESET OCCURRED)
+
+ “rescan LUN/target” maps to sense key UNIT ATTENTION, asc 0x3f,
+ ascq 0x0e (REPORTED LUNS DATA HAS CHANGED)
+
+ The preferred way to detect transport reset is always to use
+ events, because sense codes are only seen by the driver when it
+ sends a SCSI command to the logical unit or target. However, in
+ case events are dropped, the initiator will still be able to
+ synchronize with the actual state of the controller if the
+ driver asks the initiator to rescan of the SCSI bus. During the
+ rescan, the initiator will be able to observe the above sense
+ codes, and it will process them as if it the driver had
+ received the equivalent event.
+
+ Asynchronous notification
+#define VIRTIO_SCSI_T_ASYNC_NOTIFY 2
+
+
+
+struct virtio_scsi_event_an {
+
+ // Write-only part
+
+ u32 event;
+
+ u8 lun[8];
+
+ u32 reason;
+
+}
+
+ By sending this event, the device signals that an asynchronous
+ event was fired from a physical interface.
+
+ All fields are written by the device. The event field is set to
+ VIRTIO_SCSI_T_ASYNC_NOTIFY. The lun field addresses a logical
+ unit in the SCSI host. The reason field is a subset of the
+ events that the driver has subscribed to via the "Asynchronous
+ notification subscription" command.
+
+ When dropped events are reported, the driver should poll for
+ asynchronous events manually using SCSI commands.
+
+Appendix X: virtio-mmio
+
+Virtual environments without PCI support (a common situation in
+embedded devices models) might use simple memory mapped device (“
+virtio-mmio”) instead of the PCI device.
+
+The memory mapped virtio device behaviour is based on the PCI
+device specification. Therefore most of operations like device
+initialization, queues configuration and buffer transfers are
+nearly identical. Existing differences are described in the
+following sections.
+
+ Device Initialization
+
+Instead of using the PCI IO space for virtio header, the “
+virtio-mmio” device provides a set of memory mapped control
+registers, all 32 bits wide, followed by device-specific
+configuration space. The following list presents their layout:
+
+ Offset from the device base address | Direction | Name
+ Description
+
+ 0x000 | R | MagicValue
+ “virt” string.
+
+ 0x004 | R | Version
+ Device version number. Currently must be 1.
+
+ 0x008 | R | DeviceID
+ Virtio Subsystem Device ID (ie. 1 for network card).
+
+ 0x00c | R | VendorID
+ Virtio Subsystem Vendor ID.
+
+ 0x010 | R | HostFeatures
+ Flags representing features the device supports.
+ Reading from this register returns 32 consecutive flag bits,
+ first bit depending on the last value written to
+ HostFeaturesSel register. Access to this register returns bits HostFeaturesSel*32
+
+ to (HostFeaturesSel*32)+31
+, eg. feature bits 0 to 31 if
+ HostFeaturesSel is set to 0 and features bits 32 to 63 if
+ HostFeaturesSel is set to 1. Also see [sub:Feature-Bits]
+
+ 0x014 | W | HostFeaturesSel
+ Device (Host) features word selection.
+ Writing to this register selects a set of 32 device feature bits
+ accessible by reading from HostFeatures register. Device driver
+ must write a value to the HostFeaturesSel register before
+ reading from the HostFeatures register.
+
+ 0x020 | W | GuestFeatures
+ Flags representing device features understood and activated by
+ the driver.
+ Writing to this register sets 32 consecutive flag bits, first
+ bit depending on the last value written to GuestFeaturesSel
+ register. Access to this register sets bits GuestFeaturesSel*32
+
+ to (GuestFeaturesSel*32)+31
+, eg. feature bits 0 to 31 if
+ GuestFeaturesSel is set to 0 and features bits 32 to 63 if
+ GuestFeaturesSel is set to 1. Also see [sub:Feature-Bits]
+
+ 0x024 | W | GuestFeaturesSel
+ Activated (Guest) features word selection.
+ Writing to this register selects a set of 32 activated feature
+ bits accessible by writing to the GuestFeatures register.
+ Device driver must write a value to the GuestFeaturesSel
+ register before writing to the GuestFeatures register.
+
+ 0x028 | W | GuestPageSize
+ Guest page size.
+ Device driver must write the guest page size in bytes to the
+ register during initialization, before any queues are used.
+ This value must be a power of 2 and is used by the Host to
+ calculate Guest address of the first queue page (see QueuePFN).
+
+ 0x030 | W | QueueSel
+ Virtual queue index (first queue is 0).
+ Writing to this register selects the virtual queue that the
+ following operations on QueueNum, QueueAlign and QueuePFN apply
+ to.
+
+ 0x034 | R | QueueNumMax
+ Maximum virtual queue size.
+ Reading from the register returns the maximum size of the queue
+ the Host is ready to process or zero (0x0) if the queue is not
+ available. This applies to the queue selected by writing to
+ QueueSel and is allowed only when QueuePFN is set to zero
+ (0x0), so when the queue is not actively used.
+
+ 0x038 | W | QueueNum
+ Virtual queue size.
+ Queue size is a number of elements in the queue, therefore size
+ of the descriptor table and both available and used rings.
+ Writing to this register notifies the Host what size of the
+ queue the Guest will use. This applies to the queue selected by
+ writing to QueueSel.
+
+ 0x03c | W | QueueAlign
+ Used Ring alignment in the virtual queue.
+ Writing to this register notifies the Host about alignment
+ boundary of the Used Ring in bytes. This value must be a power
+ of 2 and applies to the queue selected by writing to QueueSel.
+
+ 0x040 | RW | QueuePFN
+ Guest physical page number of the virtual queue.
+ Writing to this register notifies the host about location of the
+ virtual queue in the Guest's physical address space. This value
+ is the index number of a page starting with the queue
+ Descriptor Table. Value zero (0x0) means physical address zero
+ (0x00000000) and is illegal. When the Guest stops using the
+ queue it must write zero (0x0) to this register.
+ Reading from this register returns the currently used page
+ number of the queue, therefore a value other than zero (0x0)
+ means that the queue is in use.
+ Both read and write accesses apply to the queue selected by
+ writing to QueueSel.
+
+ 0x050 | W | QueueNotify
+ Queue notifier.
+ Writing a queue index to this register notifies the Host that
+ there are new buffers to process in the queue.
+
+ 0x60 | R | InterruptStatus
+Interrupt status.
+Reading from this register returns a bit mask of interrupts
+ asserted by the device. An interrupt is asserted if the
+ corresponding bit is set, ie. equals one (1).
+
+ Bit 0 | Used Ring Update
+This interrupt is asserted when the Host has updated the Used
+ Ring in at least one of the active virtual queues.
+
+ Bit 1 | Configuration change
+This interrupt is asserted when configuration of the device has
+ changed.
+
+ 0x064 | W | InterruptACK
+ Interrupt acknowledge.
+ Writing to this register notifies the Host that the Guest
+ finished handling interrupts. Set bits in the value clear the
+ corresponding bits of the InterruptStatus register.
+
+ 0x070 | RW | Status
+ Device status.
+ Reading from this register returns the current device status
+ flags.
+ Writing non-zero values to this register sets the status flags,
+ indicating the Guest progress. Writing zero (0x0) to this
+ register triggers a device reset.
+ Also see [sub:Device-Initialization-Sequence]
+
+ 0x100+ | RW | Config
+ Device-specific configuration space starts at an offset 0x100
+ and is accessed with byte alignment. Its meaning and size
+ depends on the device and the driver.
+
+Virtual queue size is a number of elements in the queue,
+therefore size of the descriptor table and both available and
+used rings.
+
+The endianness of the registers follows the native endianness of
+the Guest. Writing to registers described as “R” and reading from
+registers described as “W” is not permitted and can cause
+undefined behavior.
+
+The device initialization is performed as described in [sub:Device-Initialization-Sequence]
+ with one exception: the Guest must notify the Host about its
+page size, writing the size in bytes to GuestPageSize register
+before the initialization is finished.
+
+The memory mapped virtio devices generate single interrupt only,
+therefore no special configuration is required.
+
+ Virtqueue Configuration
+
+The virtual queue configuration is performed in a similar way to
+the one described in [sec:Virtqueue-Configuration] with a few
+additional operations:
+
+ Select the queue writing its index (first queue is 0) to the
+ QueueSel register.
+
+ Check if the queue is not already in use: read QueuePFN
+ register, returned value should be zero (0x0).
+
+ Read maximum queue size (number of elements) from the
+ QueueNumMax register. If the returned value is zero (0x0) the
+ queue is not available.
+
+ Allocate and zero the queue pages in contiguous virtual memory,
+ aligning the Used Ring to an optimal boundary (usually page
+ size). Size of the allocated queue may be smaller than or equal
+ to the maximum size returned by the Host.
+
+ Notify the Host about the queue size by writing the size to
+ QueueNum register.
+
+ Notify the Host about the used alignment by writing its value
+ in bytes to QueueAlign register.
+
+ Write the physical number of the first page of the queue to the
+ QueuePFN register.
+
+The queue and the device are ready to begin normal operations
+now.
+
+ Device Operation
+
+The memory mapped virtio device behaves in the same way as
+described in [sec:Device-Operation], with the following
+exceptions:
+
+ The device is notified about new buffers available in a queue
+ by writing the queue index to register QueueNum instead of the
+ virtio header in PCI I/O space ([sub:Notifying-The-Device]).
+
+ The memory mapped virtio device is using single, dedicated
+ interrupt signal, which is raised when at least one of the
+ interrupts described in the InterruptStatus register
+ description is asserted. After receiving an interrupt, the
+ driver must read the InterruptStatus register to check what
+ caused the interrupt (see the register description). After the
+ interrupt is handled, the driver must acknowledge it by writing
+ a bit mask corresponding to the serviced interrupt to the
+ InterruptACK register.
+
diff --git a/drivers/staging/vme/vme_api.txt b/Documentation/vme_api.txt
index 856efa35f6e3..856efa35f6e3 100644
--- a/drivers/staging/vme/vme_api.txt
+++ b/Documentation/vme_api.txt
diff --git a/Documentation/watchdog/src/watchdog-test.c b/Documentation/watchdog/src/watchdog-test.c
index 63fdc34ceb98..73ff5cc93e05 100644
--- a/Documentation/watchdog/src/watchdog-test.c
+++ b/Documentation/watchdog/src/watchdog-test.c
@@ -7,6 +7,7 @@
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
+#include <signal.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/watchdog.h>
@@ -29,6 +30,14 @@ static void keep_alive(void)
* The main program. Run the program with "-d" to disable the card,
* or "-e" to enable the card.
*/
+
+void term(int sig)
+{
+ close(fd);
+ fprintf(stderr, "Stopping watchdog ticks...\n");
+ exit(0);
+}
+
int main(int argc, char *argv[])
{
int flags;
@@ -47,26 +56,31 @@ int main(int argc, char *argv[])
ioctl(fd, WDIOC_SETOPTIONS, &flags);
fprintf(stderr, "Watchdog card disabled.\n");
fflush(stderr);
- exit(0);
+ goto end;
} else if (!strncasecmp(argv[1], "-e", 2)) {
flags = WDIOS_ENABLECARD;
ioctl(fd, WDIOC_SETOPTIONS, &flags);
fprintf(stderr, "Watchdog card enabled.\n");
fflush(stderr);
- exit(0);
+ goto end;
} else {
fprintf(stderr, "-d to disable, -e to enable.\n");
fprintf(stderr, "run by itself to tick the card.\n");
fflush(stderr);
- exit(0);
+ goto end;
}
} else {
fprintf(stderr, "Watchdog Ticking Away!\n");
fflush(stderr);
}
+ signal(SIGINT, term);
+
while(1) {
keep_alive();
sleep(1);
}
+end:
+ close(fd);
+ return 0;
}
diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index 227f6cd0e5fa..25fe4304f2fc 100644
--- a/Documentation/watchdog/watchdog-kernel-api.txt
+++ b/Documentation/watchdog/watchdog-kernel-api.txt
@@ -59,7 +59,7 @@ It contains following fields:
* bootstatus: status of the device after booting (reported with watchdog
WDIOF_* status bits).
* driver_data: a pointer to the drivers private data of a watchdog device.
- This data should only be accessed via the watchdog_set_drvadata and
+ This data should only be accessed via the watchdog_set_drvdata and
watchdog_get_drvdata routines.
* status: this field contains a number of status bits that give extra
information about the status of the device (Like: is the watchdog timer
diff --git a/Documentation/zh_CN/magic-number.txt b/Documentation/zh_CN/magic-number.txt
index f606ba8598cf..4263022f5002 100644
--- a/Documentation/zh_CN/magic-number.txt
+++ b/Documentation/zh_CN/magic-number.txt
@@ -160,7 +160,7 @@ QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry drivers/scsi/arm/queue.c
HTB_CMAGIC 0xFEFAFEF1 htb_class net/sched/sch_htb.c
NMI_MAGIC 0x48414d4d455201 nmi_s arch/mips/include/asm/sn/nmi.h
-请注意,在声音记忆管理中仍然有每一些被定义的驱动魔术值。查看include/sound/sndmagic.h来获取他们完整的列表信息。很多OSS声音驱动拥有自己从声卡PCI ID构建的魔术值-他们也没有被列在这里。
+请注意,在声音记忆管理中仍然有一些特殊的为每个驱动定义的魔术值。查看include/sound/sndmagic.h来获取他们完整的列表信息。很多OSS声音驱动拥有自己从声卡PCI ID构建的魔术值-他们也没有被列在这里。
IrDA子系统也使用了大量的自己的魔术值,查看include/net/irda/irda.h来获取他们完整的信息。
diff --git a/MAINTAINERS b/MAINTAINERS
index 9fa728b53d4e..27a1d3c6eec8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -640,13 +640,6 @@ S: Maintained
F: drivers/amba/
F: include/linux/amba/bus.h
-ARM/ADI ROADRUNNER MACHINE SUPPORT
-M: Lennert Buytenhek <kernel@wantstofly.org>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S: Maintained
-F: arch/arm/mach-ixp23xx/
-F: arch/arm/mach-ixp23xx/include/mach/
-
ARM/ADS SPHERE MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -746,7 +739,10 @@ M: Barry Song <baohua.song@csr.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-prima2/
-F: drivers/dma/sirf-dma*
+F: drivers/dma/sirf-dma.c
+F: drivers/i2c/busses/i2c-sirf.c
+F: drivers/pinctrl/pinctrl-sirf.c
+F: drivers/spi/spi-sirf.c
ARM/EBSA110 MACHINE SUPPORT
M: Russell King <linux@arm.linux.org.uk>
@@ -859,21 +855,11 @@ M: Dan Williams <dan.j.williams@intel.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-ARM/INTEL IXP2000 ARM ARCHITECTURE
-M: Lennert Buytenhek <kernel@wantstofly.org>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S: Maintained
-
ARM/INTEL IXDP2850 MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-ARM/INTEL IXP23XX ARM ARCHITECTURE
-M: Lennert Buytenhek <kernel@wantstofly.org>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S: Maintained
-
ARM/INTEL IXP4XX ARM ARCHITECTURE
M: Imre Kaloz <kaloz@openwrt.org>
M: Krzysztof Halasa <khc@pm.waw.pl>
@@ -908,11 +894,12 @@ ARM/MAGICIAN MACHINE SUPPORT
M: Philipp Zabel <philipp.zabel@gmail.com>
S: Maintained
-ARM/Marvell Loki/Kirkwood/MV78xx0/Orion SOC support
-M: Lennert Buytenhek <kernel@wantstofly.org>
-M: Nicolas Pitre <nico@fluxnic.net>
+ARM/Marvell Dove/Kirkwood/MV78xx0/Orion SOC support
+M: Jason Cooper <jason@lakedaemon.net>
+M: Andrew Lunn <andrew@lunn.ch>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S: Odd Fixes
+S: Maintained
+F: arch/arm/mach-dove/
F: arch/arm/mach-kirkwood/
F: arch/arm/mach-mv78xx0/
F: arch/arm/mach-orion5x/
@@ -1331,6 +1318,21 @@ M: Nicolas Ferre <nicolas.ferre@atmel.com>
S: Supported
F: drivers/tty/serial/atmel_serial.c
+ATMEL DMA DRIVER
+M: Nicolas Ferre <nicolas.ferre@atmel.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Supported
+F: drivers/dma/at_hdmac.c
+F: drivers/dma/at_hdmac_regs.h
+F: arch/arm/mach-at91/include/mach/at_hdmac.h
+
+ATMEL ISI DRIVER
+M: Josh Wu <josh.wu@atmel.com>
+L: linux-media@vger.kernel.org
+S: Supported
+F: drivers/media/video/atmel-isi.c
+F: include/media/atmel-isi.h
+
ATMEL LCDFB DRIVER
M: Nicolas Ferre <nicolas.ferre@atmel.com>
L: linux-fbdev@vger.kernel.org
@@ -1348,10 +1350,22 @@ M: Nicolas Ferre <nicolas.ferre@atmel.com>
S: Supported
F: drivers/spi/spi-atmel.*
+ATMEL Timer Counter (TC) AND CLOCKSOURCE DRIVERS
+M: Nicolas Ferre <nicolas.ferre@atmel.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Supported
+F: drivers/misc/atmel_tclib.c
+F: drivers/clocksource/tcb_clksrc.c
+
+ATMEL TSADCC DRIVER
+M: Josh Wu <josh.wu@atmel.com>
+L: linux-input@vger.kernel.org
+S: Supported
+F: drivers/input/touchscreen/atmel_tsadcc.c
+
ATMEL USBA UDC DRIVER
M: Nicolas Ferre <nicolas.ferre@atmel.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W: http://avr32linux.org/twiki/bin/view/Main/AtmelUsbDeviceDriver
S: Supported
F: drivers/usb/gadget/atmel_usba_udc.*
@@ -1599,6 +1613,7 @@ F: include/linux/bcma/
BROCADE BFA FC SCSI DRIVER
M: Jing Huang <huangj@brocade.com>
+M: Krishna C Gudipati <kgudipat@brocade.com>
L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/bfa/
@@ -1732,6 +1747,7 @@ S: Supported
F: include/linux/capability.h
F: security/capability.c
F: security/commoncap.c
+F: kernel/capability.c
CELL BROADBAND ENGINE ARCHITECTURE
M: Arnd Bergmann <arnd@arndb.de>
@@ -1810,6 +1826,12 @@ L: linux-kernel@zh-kernel.org (moderated for non-subscribers)
S: Maintained
F: Documentation/zh_CN/
+CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
+M: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+L: linux-usb@vger.kernel.org
+S: Maintained
+F: drivers/usb/chipidea/
+
CISCO VIC ETHERNET NIC DRIVER
M: Christian Benvenuti <benve@cisco.com>
M: Roopa Prabhu <roprabhu@cisco.com>
@@ -2754,6 +2776,15 @@ T: git git://git.alsa-project.org/alsa-kernel.git
S: Maintained
F: sound/firewire/
+FIREWIRE SBP-2 TARGET
+M: Chris Boot <bootc@bootc.net>
+L: linux-scsi@vger.kernel.org
+L: target-devel@vger.kernel.org
+L: linux1394-devel@lists.sourceforge.net
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/nab/lio-core-2.6.git master
+S: Maintained
+F: drivers/target/sbp/
+
FIREWIRE SUBSYSTEM
M: Stefan Richter <stefanr@s5r6.in-berlin.de>
L: linux1394-devel@lists.sourceforge.net
@@ -2890,7 +2921,7 @@ S: Maintained
F: arch/frv/
FUJITSU LAPTOP EXTRAS
-M: Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
+M: Jonathan Woithe <jwoithe@just42.net>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/fujitsu-laptop.c
@@ -3378,6 +3409,7 @@ IIO SUBSYSTEM AND DRIVERS
M: Jonathan Cameron <jic23@cam.ac.uk>
L: linux-iio@vger.kernel.org
S: Maintained
+F: drivers/iio/
F: drivers/staging/iio/
IKANOS/ADI EAGLE ADSL USB DRIVER
@@ -3597,6 +3629,14 @@ S: Supported
W: http://wireless.kernel.org/en/users/Drivers/iwmc3200wifi
F: drivers/net/wireless/iwmc3200wifi/
+INTEL MANAGEMENT ENGINE (mei)
+M: Tomas Winkler <tomas.winkler@intel.com>
+L: linux-kernel@vger.kernel.org
+S: Supported
+F: include/linux/mei.h
+F: drivers/misc/mei/*
+F: Documentation/mei/*
+
IOC3 ETHERNET DRIVER
M: Ralf Baechle <ralf@linux-mips.org>
L: linux-mips@linux-mips.org
@@ -3622,7 +3662,7 @@ S: Maintained
F: drivers/net/ethernet/icplus/ipg.*
IPATH DRIVER
-M: Mike Marciniszyn <infinipath@qlogic.com>
+M: Mike Marciniszyn <infinipath@intel.com>
L: linux-rdma@vger.kernel.org
S: Maintained
F: drivers/infiniband/hw/ipath/
@@ -5115,19 +5155,13 @@ F: Documentation/powerpc/eeh-pci-error-recovery.txt
PCI SUBSYSTEM
M: Bjorn Helgaas <bhelgaas@google.com>
L: linux-pci@vger.kernel.org
-Q: http://patchwork.kernel.org/project/linux-pci/list/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci.git
+Q: http://patchwork.ozlabs.org/project/linux-pci/list/
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/linux.git
S: Supported
F: Documentation/PCI/
F: drivers/pci/
F: include/linux/pci*
-PCI HOTPLUG
-M: Bjorn Helgaas <bhelgaas@google.com>
-L: linux-pci@vger.kernel.org
-S: Supported
-F: drivers/pci/hotplug
-
PCMCIA SUBSYSTEM
P: Linux PCMCIA Team
L: linux-pcmcia@lists.infradead.org
@@ -5217,6 +5251,14 @@ M: Linus Walleij <linus.walleij@linaro.org>
S: Maintained
F: drivers/pinctrl/
+PIN CONTROLLER - ST SPEAR
+M: Viresh Kumar <viresh.kumar@st.com>
+L: spear-devel@list.st.com
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+W: http://www.st.com/spear
+S: Maintained
+F: driver/pinctrl/spear/
+
PKTCDVD DRIVER
M: Peter Osterlund <petero2@telia.com>
S: Maintained
@@ -5440,7 +5482,7 @@ L: rtc-linux@googlegroups.com
S: Maintained
QIB DRIVER
-M: Mike Marciniszyn <infinipath@qlogic.com>
+M: Mike Marciniszyn <infinipath@intel.com>
L: linux-rdma@vger.kernel.org
S: Supported
F: drivers/infiniband/hw/qib/
@@ -5590,14 +5632,13 @@ F: net/rds/
READ-COPY UPDATE (RCU)
M: Dipankar Sarma <dipankar@in.ibm.com>
M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
-W: http://www.rdrop.com/users/paulmck/rclock/
+W: http://www.rdrop.com/users/paulmck/RCU/
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
F: Documentation/RCU/
+X: Documentation/RCU/torture.txt
F: include/linux/rcu*
-F: include/linux/srcu*
F: kernel/rcu*
-F: kernel/srcu*
X: kernel/rcutorture.c
REAL TIME CLOCK (RTC) SUBSYSTEM
@@ -5943,7 +5984,7 @@ SECURITY SUBSYSTEM
M: James Morris <james.l.morris@oracle.com>
L: linux-security-module@vger.kernel.org (suggested Cc:)
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git
-W: http://security.wiki.kernel.org/
+W: http://kernsec.org/
S: Supported
F: security/
@@ -6114,6 +6155,15 @@ S: Maintained
F: include/linux/sl?b*.h
F: mm/sl?b.c
+SLEEPABLE READ-COPY UPDATE (SRCU)
+M: Lai Jiangshan <laijs@cn.fujitsu.com>
+M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
+W: http://www.rdrop.com/users/paulmck/RCU/
+S: Supported
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
+F: include/linux/srcu*
+F: kernel/srcu*
+
SMC91x ETHERNET DRIVER
M: Nicolas Pitre <nico@fluxnic.net>
S: Odd Fixes
@@ -6313,21 +6363,6 @@ F: arch/arm/mach-spear*/clock.c
F: arch/arm/plat-spear/clock.c
F: arch/arm/plat-spear/include/plat/clock.h
-SPEAR PAD MULTIPLEXING SUPPORT
-M: Viresh Kumar <viresh.kumar@st.com>
-L: spear-devel@list.st.com
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W: http://www.st.com/spear
-S: Maintained
-F: arch/arm/plat-spear/include/plat/padmux.h
-F: arch/arm/plat-spear/padmux.c
-F: arch/arm/mach-spear*/spear*xx.c
-F: arch/arm/mach-spear*/include/mach/generic.h
-F: arch/arm/mach-spear3xx/spear3*0.c
-F: arch/arm/mach-spear3xx/spear3*0_evb.c
-F: arch/arm/mach-spear6xx/spear600.c
-F: arch/arm/mach-spear6xx/spear600_evb.c
-
SPI SUBSYSTEM
M: Grant Likely <grant.likely@secretlab.ca>
L: spi-devel-general@lists.sourceforge.net
@@ -6534,7 +6569,7 @@ M: Paul Mundt <lethal@linux-sh.org>
L: linux-sh@vger.kernel.org
W: http://www.linux-sh.org
Q: http://patchwork.kernel.org/project/linux-sh/list/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git sh-latest
+T: git git://github.com/pmundt/linux-sh.git sh-latest
S: Supported
F: Documentation/sh/
F: arch/sh/
@@ -6652,6 +6687,12 @@ F: drivers/misc/tifm*
F: drivers/mmc/host/tifm_sd.c
F: include/linux/tifm.h
+TI LM49xxx FAMILY ASoC CODEC DRIVERS
+M: M R Swami Reddy <mr.swami.reddy@ti.com>
+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
+S: Maintained
+F: sound/soc/codecs/lm49453*
+
TI TWL4030 SERIES SOC CODEC DRIVER
M: Peter Ujfalusi <peter.ujfalusi@ti.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
@@ -6875,6 +6916,14 @@ F: Documentation/cdrom/
F: drivers/cdrom/cdrom.c
F: include/linux/cdrom.h
+UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER
+M: Vinayak Holikatti <vinholikatti@gmail.com>
+M: Santosh Y <santoshsy@gmail.com>
+L: linux-scsi@vger.kernel.org
+S: Supported
+F: Documentation/scsi/ufs.txt
+F: drivers/scsi/ufs/
+
UNSORTED BLOCK IMAGES (UBI)
M: Artem Bityutskiy <dedekind1@gmail.com>
W: http://www.linux-mtd.infradead.org/
@@ -7021,6 +7070,14 @@ W: http://pegasus2.sourceforge.net/
S: Maintained
F: drivers/net/usb/pegasus.*
+USB PHY LAYER
+M: Felipe Balbi <balbi@ti.com>
+L: linux-usb@vger.kernel.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
+S: Maintained
+F: drivers/usb/phy/
+F: drivers/usb/otg/
+
USB PRINTER DRIVER (usblp)
M: Pete Zaitcev <zaitcev@redhat.com>
L: linux-usb@vger.kernel.org
@@ -7304,6 +7361,18 @@ S: Maintained
F: drivers/vlynq/vlynq.c
F: include/linux/vlynq.h
+VME SUBSYSTEM
+M: Martyn Welch <martyn.welch@ge.com>
+M: Manohar Vanga <manohar.vanga@cern.ch>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+L: devel@driverdev.osuosl.org
+S: Maintained
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
+F: Documentation/vme_api.txt
+F: drivers/staging/vme/
+F: drivers/vme/
+F: include/linux/vme*
+
VMWARE VMXNET3 ETHERNET DRIVER
M: Shreyas Bhatewara <sbhatewara@vmware.com>
M: "VMware, Inc." <pv-drivers@vmware.com>
diff --git a/Makefile b/Makefile
index 48bd1f50dcc3..b62c1e09444a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 3
PATCHLEVEL = 4
SUBLEVEL = 0
-EXTRAVERSION = -rc7
+EXTRAVERSION =
NAME = Saber-toothed Squirrel
# *DOCUMENTATION*
@@ -400,8 +400,10 @@ export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_ve
# Files to ignore in find ... statements
-RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg -o -name .git \) -prune -o
-export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg --exclude .git
+RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS \
+ -o -name .pc -o -name .hg -o -name .git \) -prune -o
+export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn \
+ --exclude CVS --exclude .pc --exclude .hg --exclude .git
# ===========================================================================
# Rules shared between *config targets and build targets
@@ -442,7 +444,7 @@ asm-generic:
no-dot-config-targets := clean mrproper distclean \
cscope gtags TAGS tags help %docs check% coccicheck \
- include/linux/version.h headers_% archheaders \
+ include/linux/version.h headers_% archheaders archscripts \
kernelversion %src-pkg
config-targets := 0
@@ -564,6 +566,16 @@ else
KBUILD_CFLAGS += -O2
endif
+ifdef CONFIG_READABLE_ASM
+# Disable optimizations that make assembler listings hard to read.
+# reorder blocks reorders the control in the function
+# ipa clone creates specialized cloned functions
+# partial inlining inlines only parts of functions
+KBUILD_CFLAGS += $(call cc-option,-fno-reorder-blocks,) \
+ $(call cc-option,-fno-ipa-cp-clone,) \
+ $(call cc-option,-fno-partial-inlining)
+endif
+
include $(srctree)/arch/$(SRCARCH)/Makefile
ifneq ($(CONFIG_FRAME_WARN),0)
@@ -784,6 +796,10 @@ quiet_cmd_vmlinux_version = GEN .version
quiet_cmd_sysmap = SYSMAP
cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
+# Sort exception table at build time
+quiet_cmd_sortextable = SORTEX
+ cmd_sortextable = $(objtree)/scripts/sortextable
+
# Link of vmlinux
# If CONFIG_KALLSYMS is set .version is already updated
# Generate System.map and verify that the content is consistent
@@ -796,6 +812,12 @@ define rule_vmlinux__
$(call cmd,vmlinux__)
$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
+ $(if $(CONFIG_BUILDTIME_EXTABLE_SORT), \
+ $(Q)$(if $($(quiet)cmd_sortextable), \
+ echo ' $($(quiet)cmd_sortextable) vmlinux' &&) \
+ $(cmd_sortextable) vmlinux)
+
+
$(Q)$(if $($(quiet)cmd_sysmap), \
echo ' $($(quiet)cmd_sysmap) System.map' &&) \
$(cmd_sysmap) $@ System.map; \
@@ -966,7 +988,7 @@ prepare3: include/config/kernel.release
ifneq ($(KBUILD_SRC),)
@$(kecho) ' Using $(srctree) as source for kernel'
$(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
- echo " $(srctree) is not clean, please run 'make mrproper'";\
+ echo " $(srctree) is not clean, please run 'make mrproper'"; \
echo " in the '$(srctree)' directory.";\
/bin/false; \
fi;
@@ -979,7 +1001,7 @@ prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \
include/config/auto.conf
$(cmd_crmodverdir)
-archprepare: archheaders prepare1 scripts_basic
+archprepare: archheaders archscripts prepare1 scripts_basic
prepare0: archprepare FORCE
$(Q)$(MAKE) $(build)=.
@@ -1003,8 +1025,8 @@ define filechk_utsrelease.h
endef
define filechk_version.h
- (echo \#define LINUX_VERSION_CODE $(shell \
- expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \
+ (echo \#define LINUX_VERSION_CODE $(shell \
+ expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \
echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
endef
@@ -1049,8 +1071,11 @@ hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
PHONY += archheaders
archheaders:
+PHONY += archscripts
+archscripts:
+
PHONY += __headers
-__headers: include/linux/version.h scripts_basic asm-generic archheaders FORCE
+__headers: include/linux/version.h scripts_basic asm-generic archheaders archscripts FORCE
$(Q)$(MAKE) $(build)=scripts build_unifdef
PHONY += headers_install_all
@@ -1468,6 +1493,13 @@ kernelrelease:
kernelversion:
@echo $(KERNELVERSION)
+# Clear a bunch of variables before executing the submake
+tools/: FORCE
+ $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/
+
+tools/%: FORCE
+ $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/ $*
+
# Single targets
# ---------------------------------------------------------------------------
# Single targets are compatible with:
diff --git a/README b/README
index 0d5a7ddbe3ee..9beaed0ed620 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
- Linux kernel release 3.x <http://kernel.org/>
+ Linux kernel release 3.x <http://kernel.org/>
These are the release notes for Linux version 3. Read them carefully,
as they tell you what this is all about, explain how to install the
@@ -62,13 +62,13 @@ INSTALLING the kernel source:
directory where you have permissions (eg. your home directory) and
unpack it:
- gzip -cd linux-3.X.tar.gz | tar xvf -
+ gzip -cd linux-3.X.tar.gz | tar xvf -
or
- bzip2 -dc linux-3.X.tar.bz2 | tar xvf -
+ bzip2 -dc linux-3.X.tar.bz2 | tar xvf -
- Replace "XX" with the version number of the latest kernel.
+ Replace "X" with the version number of the latest kernel.
Do NOT use the /usr/src/linux area! This area has a (usually
incomplete) set of kernel headers that are used by the library header
@@ -78,49 +78,43 @@ INSTALLING the kernel source:
- You can also upgrade between 3.x releases by patching. Patches are
distributed in the traditional gzip and the newer bzip2 format. To
install by patching, get all the newer patch files, enter the
- top level directory of the kernel source (linux-3.x) and execute:
+ top level directory of the kernel source (linux-3.X) and execute:
- gzip -cd ../patch-3.x.gz | patch -p1
+ gzip -cd ../patch-3.x.gz | patch -p1
or
- bzip2 -dc ../patch-3.x.bz2 | patch -p1
- (repeat xx for all versions bigger than the version of your current
- source tree, _in_order_) and you should be ok. You may want to remove
- the backup files (xxx~ or xxx.orig), and make sure that there are no
- failed patches (xxx# or xxx.rej). If there are, either you or me has
- made a mistake.
+ bzip2 -dc ../patch-3.x.bz2 | patch -p1
+
+ Replace "x" for all versions bigger than the version "X" of your current
+ source tree, _in_order_, and you should be ok. You may want to remove
+ the backup files (some-file-name~ or some-file-name.orig), and make sure
+ that there are no failed patches (some-file-name# or some-file-name.rej).
+ If there are, either you or I have made a mistake.
Unlike patches for the 3.x kernels, patches for the 3.x.y kernels
(also known as the -stable kernels) are not incremental but instead apply
- directly to the base 3.x kernel. Please read
- Documentation/applying-patches.txt for more information.
+ directly to the base 3.x kernel. For example, if your base kernel is 3.0
+ and you want to apply the 3.0.3 patch, you must not first apply the 3.0.1
+ and 3.0.2 patches. Similarly, if you are running kernel version 3.0.2 and
+ want to jump to 3.0.3, you must first reverse the 3.0.2 patch (that is,
+ patch -R) _before_ applying the 3.0.3 patch. You can read more on this in
+ Documentation/applying-patches.txt
Alternatively, the script patch-kernel can be used to automate this
process. It determines the current kernel version and applies any
patches found.
- linux/scripts/patch-kernel linux
+ linux/scripts/patch-kernel linux
The first argument in the command above is the location of the
kernel source. Patches are applied from the current directory, but
an alternative directory can be specified as the second argument.
- - If you are upgrading between releases using the stable series patches
- (for example, patch-3.x.y), note that these "dot-releases" are
- not incremental and must be applied to the 3.x base tree. For
- example, if your base kernel is 3.0 and you want to apply the
- 3.0.3 patch, you do not and indeed must not first apply the
- 3.0.1 and 3.0.2 patches. Similarly, if you are running kernel
- version 3.0.2 and want to jump to 3.0.3, you must first
- reverse the 3.0.2 patch (that is, patch -R) _before_ applying
- the 3.0.3 patch.
- You can read more on this in Documentation/applying-patches.txt
-
- Make sure you have no stale .o files and dependencies lying around:
- cd linux
- make mrproper
+ cd linux
+ make mrproper
You should now have the sources correctly installed.
@@ -137,21 +131,23 @@ SOFTWARE REQUIREMENTS
BUILD directory for the kernel:
- When compiling the kernel all output files will per default be
+ When compiling the kernel, all output files will per default be
stored together with the kernel source code.
Using the option "make O=output/dir" allow you to specify an alternate
place for the output files (including .config).
Example:
- kernel source code: /usr/src/linux-3.N
- build directory: /home/name/build/kernel
- To configure and build the kernel use:
- cd /usr/src/linux-3.N
- make O=/home/name/build/kernel menuconfig
- make O=/home/name/build/kernel
- sudo make O=/home/name/build/kernel modules_install install
+ kernel source code: /usr/src/linux-3.X
+ build directory: /home/name/build/kernel
+
+ To configure and build the kernel, use:
- Please note: If the 'O=output/dir' option is used then it must be
+ cd /usr/src/linux-3.X
+ make O=/home/name/build/kernel menuconfig
+ make O=/home/name/build/kernel
+ sudo make O=/home/name/build/kernel modules_install install
+
+ Please note: If the 'O=output/dir' option is used, then it must be
used for all invocations of make.
CONFIGURING the kernel:
@@ -163,61 +159,78 @@ CONFIGURING the kernel:
new version with minimal work, use "make oldconfig", which will
only ask you for the answers to new questions.
- - Alternate configuration commands are:
- "make config" Plain text interface.
- "make menuconfig" Text based color menus, radiolists & dialogs.
- "make nconfig" Enhanced text based color menus.
- "make xconfig" X windows (Qt) based configuration tool.
- "make gconfig" X windows (Gtk) based configuration tool.
- "make oldconfig" Default all questions based on the contents of
- your existing ./.config file and asking about
- new config symbols.
- "make silentoldconfig"
- Like above, but avoids cluttering the screen
- with questions already answered.
- Additionally updates the dependencies.
- "make defconfig" Create a ./.config file by using the default
- symbol values from either arch/$ARCH/defconfig
- or arch/$ARCH/configs/${PLATFORM}_defconfig,
- depending on the architecture.
- "make ${PLATFORM}_defconfig"
- Create a ./.config file by using the default
- symbol values from
- arch/$ARCH/configs/${PLATFORM}_defconfig.
- Use "make help" to get a list of all available
- platforms of your architecture.
- "make allyesconfig"
- Create a ./.config file by setting symbol
- values to 'y' as much as possible.
- "make allmodconfig"
- Create a ./.config file by setting symbol
- values to 'm' as much as possible.
- "make allnoconfig" Create a ./.config file by setting symbol
- values to 'n' as much as possible.
- "make randconfig" Create a ./.config file by setting symbol
- values to random values.
+ - Alternative configuration commands are:
+
+ "make config" Plain text interface.
+
+ "make menuconfig" Text based color menus, radiolists & dialogs.
+
+ "make nconfig" Enhanced text based color menus.
+
+ "make xconfig" X windows (Qt) based configuration tool.
+
+ "make gconfig" X windows (Gtk) based configuration tool.
+
+ "make oldconfig" Default all questions based on the contents of
+ your existing ./.config file and asking about
+ new config symbols.
+
+ "make silentoldconfig"
+ Like above, but avoids cluttering the screen
+ with questions already answered.
+ Additionally updates the dependencies.
+
+ "make defconfig" Create a ./.config file by using the default
+ symbol values from either arch/$ARCH/defconfig
+ or arch/$ARCH/configs/${PLATFORM}_defconfig,
+ depending on the architecture.
+
+ "make ${PLATFORM}_defconfig"
+ Create a ./.config file by using the default
+ symbol values from
+ arch/$ARCH/configs/${PLATFORM}_defconfig.
+ Use "make help" to get a list of all available
+ platforms of your architecture.
+
+ "make allyesconfig"
+ Create a ./.config file by setting symbol
+ values to 'y' as much as possible.
+
+ "make allmodconfig"
+ Create a ./.config file by setting symbol
+ values to 'm' as much as possible.
+
+ "make allnoconfig" Create a ./.config file by setting symbol
+ values to 'n' as much as possible.
+
+ "make randconfig" Create a ./.config file by setting symbol
+ values to random values.
You can find more information on using the Linux kernel config tools
in Documentation/kbuild/kconfig.txt.
- NOTES on "make config":
- - having unnecessary drivers will make the kernel bigger, and can
- under some circumstances lead to problems: probing for a
- nonexistent controller card may confuse your other controllers
- - compiling the kernel with "Processor type" set higher than 386
- will result in a kernel that does NOT work on a 386. The
- kernel will detect this on bootup, and give up.
- - A kernel with math-emulation compiled in will still use the
- coprocessor if one is present: the math emulation will just
- never get used in that case. The kernel will be slightly larger,
- but will work on different machines regardless of whether they
- have a math coprocessor or not.
- - the "kernel hacking" configuration details usually result in a
- bigger or slower kernel (or both), and can even make the kernel
- less stable by configuring some routines to actively try to
- break bad code to find kernel problems (kmalloc()). Thus you
- should probably answer 'n' to the questions for
- "development", "experimental", or "debugging" features.
+ - NOTES on "make config":
+
+ - Having unnecessary drivers will make the kernel bigger, and can
+ under some circumstances lead to problems: probing for a
+ nonexistent controller card may confuse your other controllers
+
+ - Compiling the kernel with "Processor type" set higher than 386
+ will result in a kernel that does NOT work on a 386. The
+ kernel will detect this on bootup, and give up.
+
+ - A kernel with math-emulation compiled in will still use the
+ coprocessor if one is present: the math emulation will just
+ never get used in that case. The kernel will be slightly larger,
+ but will work on different machines regardless of whether they
+ have a math coprocessor or not.
+
+ - The "kernel hacking" configuration details usually result in a
+ bigger or slower kernel (or both), and can even make the kernel
+ less stable by configuring some routines to actively try to
+ break bad code to find kernel problems (kmalloc()). Thus you
+ should probably answer 'n' to the questions for "development",
+ "experimental", or "debugging" features.
COMPILING the kernel:
@@ -230,7 +243,7 @@ COMPILING the kernel:
possible to do "make install" if you have lilo installed to suit the
kernel makefiles, but you may want to check your particular lilo setup first.
- To do the actual install you have to be root, but none of the normal
+ To do the actual install, you have to be root, but none of the normal
build should require that. Don't take the name of root in vain.
- If you configured any of the parts of the kernel as `modules', you
@@ -238,13 +251,13 @@ COMPILING the kernel:
- Verbose kernel compile/build output:
- Normally the kernel build system runs in a fairly quiet mode (but not
+ Normally, the kernel build system runs in a fairly quiet mode (but not
totally silent). However, sometimes you or other kernel developers need
to see compile, link, or other commands exactly as they are executed.
For this, use "verbose" build mode. This is done by inserting
"V=1" in the "make" command. E.g.:
- make V=1 all
+ make V=1 all
To have the build system also tell the reason for the rebuild of each
target, use "V=2". The default is "V=0".
@@ -256,6 +269,7 @@ COMPILING the kernel:
are installing a new kernel with the same version number as your
working kernel, make a backup of your modules directory before you
do a "make modules_install".
+
Alternatively, before compiling, use the kernel config option
"LOCALVERSION" to append a unique suffix to the regular kernel version.
LOCALVERSION can be set in the "General Setup" menu.
@@ -267,7 +281,7 @@ COMPILING the kernel:
- Booting a kernel directly from a floppy without the assistance of a
bootloader such as LILO, is no longer supported.
- If you boot Linux from the hard drive, chances are you use LILO which
+ If you boot Linux from the hard drive, chances are you use LILO, which
uses the kernel image as specified in the file /etc/lilo.conf. The
kernel image file is usually /vmlinuz, /boot/vmlinuz, /bzImage or
/boot/bzImage. To use the new kernel, save a copy of the old image
@@ -306,21 +320,21 @@ IF SOMETHING GOES WRONG:
- If the bug results in a message like
- unable to handle kernel paging request at address C0000010
- Oops: 0002
- EIP: 0010:XXXXXXXX
- eax: xxxxxxxx ebx: xxxxxxxx ecx: xxxxxxxx edx: xxxxxxxx
- esi: xxxxxxxx edi: xxxxxxxx ebp: xxxxxxxx
- ds: xxxx es: xxxx fs: xxxx gs: xxxx
- Pid: xx, process nr: xx
- xx xx xx xx xx xx xx xx xx xx
+ unable to handle kernel paging request at address C0000010
+ Oops: 0002
+ EIP: 0010:XXXXXXXX
+ eax: xxxxxxxx ebx: xxxxxxxx ecx: xxxxxxxx edx: xxxxxxxx
+ esi: xxxxxxxx edi: xxxxxxxx ebp: xxxxxxxx
+ ds: xxxx es: xxxx fs: xxxx gs: xxxx
+ Pid: xx, process nr: xx
+ xx xx xx xx xx xx xx xx xx xx
or similar kernel debugging information on your screen or in your
system log, please duplicate it *exactly*. The dump may look
incomprehensible to you, but it does contain information that may
help debugging the problem. The text above the dump is also
important: it tells something about why the kernel dumped code (in
- the above example it's due to a bad kernel pointer). More information
+ the above example, it's due to a bad kernel pointer). More information
on making sense of the dump is in Documentation/oops-tracing.txt
- If you compiled the kernel with CONFIG_KALLSYMS you can send the dump
@@ -328,7 +342,7 @@ IF SOMETHING GOES WRONG:
sense of the dump (but compiling with CONFIG_KALLSYMS is usually preferred).
This utility can be downloaded from
ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops/ .
- Alternately you can do the dump lookup by hand:
+ Alternatively, you can do the dump lookup by hand:
- In debugging dumps like the above, it helps enormously if you can
look up what the EIP value means. The hex value as such doesn't help
@@ -342,7 +356,7 @@ IF SOMETHING GOES WRONG:
the file 'linux/vmlinux'. To extract the namelist and match it against
the EIP from the kernel crash, do:
- nm vmlinux | sort | less
+ nm vmlinux | sort | less
This will give you a list of kernel addresses sorted in ascending
order, from which it is simple to find the function that contains the
@@ -361,7 +375,7 @@ IF SOMETHING GOES WRONG:
kernel image or similar), telling me as much about your setup as
possible will help. Please read the REPORTING-BUGS document for details.
- - Alternately, you can use gdb on a running kernel. (read-only; i.e. you
+ - Alternatively, you can use gdb on a running kernel. (read-only; i.e. you
cannot change values or set break points.) To do this, first compile the
kernel with -g; edit arch/i386/Makefile appropriately, then do a "make
clean". You'll also need to enable CONFIG_PROC_FS (via "make config").
diff --git a/arch/Kconfig b/arch/Kconfig
index 684eb5af439d..1f9461b9cc89 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -145,6 +145,21 @@ config HAVE_DMA_ATTRS
config USE_GENERIC_SMP_HELPERS
bool
+config GENERIC_SMP_IDLE_THREAD
+ bool
+
+# Select if arch init_task initializer is different to init/init_task.c
+config ARCH_INIT_TASK
+ bool
+
+# Select if arch has its private alloc_task_struct() function
+config ARCH_TASK_STRUCT_ALLOCATOR
+ bool
+
+# Select if arch has its private alloc_thread_info() function
+config ARCH_THREAD_INFO_ALLOCATOR
+ bool
+
config HAVE_REGS_AND_STACK_ACCESS_API
bool
help
@@ -216,4 +231,27 @@ config HAVE_CMPXCHG_DOUBLE
config ARCH_WANT_OLD_COMPAT_IPC
bool
+config HAVE_ARCH_SECCOMP_FILTER
+ bool
+ help
+ An arch should select this symbol if it provides all of these things:
+ - syscall_get_arch()
+ - syscall_get_arguments()
+ - syscall_rollback()
+ - syscall_set_return_value()
+ - SIGSYS siginfo_t support
+ - secure_computing is called from a ptrace_event()-safe context
+ - secure_computing return value is checked and a return value of -1
+ results in the system call being skipped immediately.
+
+config SECCOMP_FILTER
+ def_bool y
+ depends on HAVE_ARCH_SECCOMP_FILTER && SECCOMP && NET
+ help
+ Enable tasks to build secure computing environments defined
+ in terms of Berkeley Packet Filter programs which implement
+ task-defined system call filtering polices.
+
+ See Documentation/prctl/seccomp_filter.txt for details.
+
source "kernel/gcov/Kconfig"
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 22e58a99f38b..0893f023efb8 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -15,6 +15,7 @@ config ALPHA
select GENERIC_IRQ_SHOW
select ARCH_WANT_OPTIONAL_GPIOLIB
select ARCH_HAVE_NMI_SAFE_CMPXCHG
+ select GENERIC_SMP_IDLE_THREAD
help
The Alpha is a 64-bit general-purpose processor designed and
marketed by the Digital Equipment Corporation of blessed memory,
diff --git a/arch/alpha/include/asm/processor.h b/arch/alpha/include/asm/processor.h
index 94afe5859301..e37b887b3d9f 100644
--- a/arch/alpha/include/asm/processor.h
+++ b/arch/alpha/include/asm/processor.h
@@ -49,9 +49,6 @@ extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
/* Create a kernel thread without removing it from tasklists. */
extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index 7a6d908bb865..84ec46b38f7d 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -6,7 +6,7 @@ extra-y := head.o vmlinux.lds
asflags-y := $(KBUILD_CFLAGS)
ccflags-y := -Wno-sign-compare
-obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
+obj-y := entry.o traps.o process.o osf_sys.o irq.o \
irq_alpha.o signal.o setup.o ptrace.o time.o \
alpha_ksyms.o systbls.o err_common.o io.o
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index cd634795aa9c..3f844d26d2c7 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -236,7 +236,7 @@ static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
ok = 0;
/* If both conditions above are met, we are fine. */
- DBGA("pci_dac_dma_supported %s from %p\n",
+ DBGA("pci_dac_dma_supported %s from %pf\n",
ok ? "yes" : "no", __builtin_return_address(0));
return ok;
@@ -268,7 +268,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
&& paddr + size <= __direct_map_size) {
ret = paddr + __direct_map_base;
- DBGA2("pci_map_single: [%p,%zx] -> direct %llx from %p\n",
+ DBGA2("pci_map_single: [%p,%zx] -> direct %llx from %pf\n",
cpu_addr, size, ret, __builtin_return_address(0));
return ret;
@@ -279,7 +279,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
if (dac_allowed) {
ret = paddr + alpha_mv.pci_dac_offset;
- DBGA2("pci_map_single: [%p,%zx] -> DAC %llx from %p\n",
+ DBGA2("pci_map_single: [%p,%zx] -> DAC %llx from %pf\n",
cpu_addr, size, ret, __builtin_return_address(0));
return ret;
@@ -316,7 +316,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
ret = arena->dma_base + dma_ofs * PAGE_SIZE;
ret += (unsigned long)cpu_addr & ~PAGE_MASK;
- DBGA2("pci_map_single: [%p,%zx] np %ld -> sg %llx from %p\n",
+ DBGA2("pci_map_single: [%p,%zx] np %ld -> sg %llx from %pf\n",
cpu_addr, size, npages, ret, __builtin_return_address(0));
return ret;
@@ -385,14 +385,14 @@ static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
&& dma_addr < __direct_map_base + __direct_map_size) {
/* Nothing to do. */
- DBGA2("pci_unmap_single: direct [%llx,%zx] from %p\n",
+ DBGA2("pci_unmap_single: direct [%llx,%zx] from %pf\n",
dma_addr, size, __builtin_return_address(0));
return;
}
if (dma_addr > 0xffffffff) {
- DBGA2("pci64_unmap_single: DAC [%llx,%zx] from %p\n",
+ DBGA2("pci64_unmap_single: DAC [%llx,%zx] from %pf\n",
dma_addr, size, __builtin_return_address(0));
return;
}
@@ -424,7 +424,7 @@ static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
spin_unlock_irqrestore(&arena->lock, flags);
- DBGA2("pci_unmap_single: sg [%llx,%zx] np %ld from %p\n",
+ DBGA2("pci_unmap_single: sg [%llx,%zx] np %ld from %pf\n",
dma_addr, size, npages, __builtin_return_address(0));
}
@@ -447,7 +447,7 @@ try_again:
cpu_addr = (void *)__get_free_pages(gfp, order);
if (! cpu_addr) {
printk(KERN_INFO "pci_alloc_consistent: "
- "get_free_pages failed from %p\n",
+ "get_free_pages failed from %pf\n",
__builtin_return_address(0));
/* ??? Really atomic allocation? Otherwise we could play
with vmalloc and sg if we can't find contiguous memory. */
@@ -466,7 +466,7 @@ try_again:
goto try_again;
}
- DBGA2("pci_alloc_consistent: %zx -> [%p,%llx] from %p\n",
+ DBGA2("pci_alloc_consistent: %zx -> [%p,%llx] from %pf\n",
size, cpu_addr, *dma_addrp, __builtin_return_address(0));
return cpu_addr;
@@ -486,7 +486,7 @@ static void alpha_pci_free_coherent(struct device *dev, size_t size,
pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
free_pages((unsigned long)cpu_addr, get_order(size));
- DBGA2("pci_free_consistent: [%llx,%zx] from %p\n",
+ DBGA2("pci_free_consistent: [%llx,%zx] from %pf\n",
dma_addr, size, __builtin_return_address(0));
}
diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c
index 0dae252f7a33..d821b17047e0 100644
--- a/arch/alpha/kernel/perf_event.c
+++ b/arch/alpha/kernel/perf_event.c
@@ -824,7 +824,6 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr,
idx = la_ptr;
- perf_sample_data_init(&data, 0);
for (j = 0; j < cpuc->n_events; j++) {
if (cpuc->current_idx[j] == idx)
break;
@@ -848,7 +847,7 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr,
hwc = &event->hw;
alpha_perf_event_update(event, hwc, idx, alpha_pmu->pmc_max_period[idx]+1);
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, 0, hwc->last_period);
if (alpha_perf_event_set_period(event, hwc, idx)) {
if (perf_event_overflow(event, &data, regs)) {
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 50d438db1f6b..35ddc02bfa4a 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -357,24 +357,10 @@ secondary_cpu_start(int cpuid, struct task_struct *idle)
* Bring one cpu online.
*/
static int __cpuinit
-smp_boot_one_cpu(int cpuid)
+smp_boot_one_cpu(int cpuid, struct task_struct *idle)
{
- struct task_struct *idle;
unsigned long timeout;
- /* Cook up an idler for this guy. Note that the address we
- give to kernel_thread is irrelevant -- it's going to start
- where HWRPB.CPU_restart says to start. But this gets all
- the other task-y sort of data structures set up like we
- wish. We can't use kernel_thread since we must avoid
- rescheduling the child. */
- idle = fork_idle(cpuid);
- if (IS_ERR(idle))
- panic("failed fork for CPU %d", cpuid);
-
- DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n",
- cpuid, idle->state, idle->flags));
-
/* Signal the secondary to wait a moment. */
smp_secondary_alive = -1;
@@ -487,9 +473,9 @@ smp_prepare_boot_cpu(void)
}
int __cpuinit
-__cpu_up(unsigned int cpu)
+__cpu_up(unsigned int cpu, struct task_struct *tidle)
{
- smp_boot_one_cpu(cpu);
+ smp_boot_one_cpu(cpu, tidle);
return cpu_online(cpu) ? 0 : -ENOSYS;
}
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 695cc39f3138..4f4c8115d79b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -11,6 +11,7 @@ config ARM
select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
select HAVE_ARCH_KGDB
+ select HAVE_ARCH_TRACEHOOK
select HAVE_KPROBES if !XIP_KERNEL
select HAVE_KRETPROBES if (HAVE_KPROBES)
select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
@@ -30,10 +31,15 @@ config ARM
select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
select HAVE_C_RECORDMCOUNT
select HAVE_GENERIC_HARDIRQS
+ select HARDIRQS_SW_RESEND
+ select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
+ select GENERIC_IRQ_PROBE
+ select HARDIRQS_SW_RESEND
select CPU_PM if (SUSPEND || CPU_IDLE)
select GENERIC_PCI_IOMAP
- select HAVE_BPF_JIT if NET
+ select HAVE_BPF_JIT
+ select GENERIC_SMP_IDLE_THREAD
help
The ARM series is a line of low-power-consumption RISC chip designs
licensed by ARM Ltd and targeted at embedded applications and
@@ -118,14 +124,6 @@ config TRACE_IRQFLAGS_SUPPORT
bool
default y
-config HARDIRQS_SW_RESEND
- bool
- default y
-
-config GENERIC_IRQ_PROBE
- bool
- default y
-
config GENERIC_LOCKBREAK
bool
default y
@@ -151,9 +149,6 @@ config ARCH_HAS_CPUFREQ
and that the relevant menu configurations are displayed for
it.
-config ARCH_HAS_CPU_IDLE_WAIT
- def_bool y
-
config GENERIC_HWEIGHT
bool
default y
@@ -272,6 +267,7 @@ config ARCH_INTEGRATOR
select NEED_MACH_IO_H
select NEED_MACH_MEMORY_H
select SPARSE_IRQ
+ select MULTI_IRQ_HANDLER
help
Support for ARM's Integrator platform.
@@ -332,8 +328,8 @@ config ARCH_AT91
select IRQ_DOMAIN
select NEED_MACH_IO_H if PCCARD
help
- This enables support for systems based on the Atmel AT91RM9200,
- AT91SAM9 processors.
+ This enables support for systems based on Atmel
+ AT91RM9200 and AT91SAM9* processors.
config ARCH_BCMRING
bool "Broadcom BCMRING"
@@ -365,12 +361,12 @@ config ARCH_HIGHBANK
Support for the Calxeda Highbank SoC based boards.
config ARCH_CLPS711X
- bool "Cirrus Logic CLPS711x/EP721x-based"
+ bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
select CPU_ARM720T
select ARCH_USES_GETTIMEOFFSET
select NEED_MACH_MEMORY_H
help
- Support for Cirrus Logic 711x/721x based boards.
+ Support for Cirrus Logic 711x/721x/731x based boards.
config ARCH_CNS3XXX
bool "Cavium Networks CNS3XXX family"
@@ -399,6 +395,8 @@ config ARCH_PRIMA2
select CLKDEV_LOOKUP
select GENERIC_IRQ_CHIP
select MIGHT_HAVE_CACHE_L2X0
+ select PINCTRL
+ select PINCTRL_SIRF
select USE_OF
select ZONE_DMA
help
@@ -461,6 +459,7 @@ config ARCH_MXS
select CLKDEV_LOOKUP
select CLKSRC_MMIO
select HAVE_CLK_PREPARE
+ select PINCTRL
help
Support for Freescale MXS-based family of processors
@@ -520,28 +519,6 @@ config ARCH_IOP33X
help
Support for Intel's IOP33X (XScale) family of processors.
-config ARCH_IXP23XX
- bool "IXP23XX-based"
- depends on MMU
- select CPU_XSC3
- select PCI
- select ARCH_USES_GETTIMEOFFSET
- select NEED_MACH_IO_H
- select NEED_MACH_MEMORY_H
- help
- Support for Intel's IXP23xx (XScale) family of processors.
-
-config ARCH_IXP2000
- bool "IXP2400/2800-based"
- depends on MMU
- select CPU_XSCALE
- select PCI
- select ARCH_USES_GETTIMEOFFSET
- select NEED_MACH_IO_H
- select NEED_MACH_MEMORY_H
- help
- Support for Intel's IXP2400/2800 (XScale) family of processors.
-
config ARCH_IXP4XX
bool "IXP4xx-based"
depends on MMU
@@ -589,6 +566,7 @@ config ARCH_LPC32XX
select USB_ARCH_HAS_OHCI
select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS
+ select USE_OF
help
Support for the NXP LPC32XX family of processors
@@ -624,7 +602,7 @@ config ARCH_MMP
select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS
select GPIO_PXA
- select TICK_ONESHOT
+ select IRQ_DOMAIN
select PLAT_PXA
select SPARSE_IRQ
select GENERIC_ALLOCATOR
@@ -708,7 +686,6 @@ config ARCH_PXA
select ARCH_REQUIRE_GPIOLIB
select GENERIC_CLOCKEVENTS
select GPIO_PXA
- select TICK_ONESHOT
select PLAT_PXA
select SPARSE_IRQ
select AUTO_ZRELADDR
@@ -775,7 +752,6 @@ config ARCH_SA1100
select CPU_FREQ
select GENERIC_CLOCKEVENTS
select CLKDEV_LOOKUP
- select TICK_ONESHOT
select ARCH_REQUIRE_GPIOLIB
select HAVE_IDE
select NEED_MACH_MEMORY_H
@@ -938,6 +914,7 @@ config ARCH_NOMADIK
select CPU_ARM926T
select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS
+ select PINCTRL
select MIGHT_HAVE_CACHE_L2X0
select ARCH_REQUIRE_GPIOLIB
help
@@ -1038,10 +1015,6 @@ source "arch/arm/mach-iop13xx/Kconfig"
source "arch/arm/mach-ixp4xx/Kconfig"
-source "arch/arm/mach-ixp2000/Kconfig"
-
-source "arch/arm/mach-ixp23xx/Kconfig"
-
source "arch/arm/mach-kirkwood/Kconfig"
source "arch/arm/mach-ks8695/Kconfig"
@@ -1544,10 +1517,15 @@ config HAVE_ARM_SCU
help
This option enables support for the ARM system coherency unit
+config ARM_ARCH_TIMER
+ bool "Architected timer support"
+ depends on CPU_V7
+ help
+ This option enables support for the ARM architected timer
+
config HAVE_ARM_TWD
bool
depends on SMP
- select TICK_ONESHOT
help
This options enables support for the ARM timer and watchdog unit
@@ -1928,10 +1906,10 @@ choice
default ZBOOT_ROM_NONE
help
Include experimental SD/MMC loading code in the ROM-able zImage.
- With this enabled it is possible to write the the ROM-able zImage
+ With this enabled it is possible to write the ROM-able zImage
kernel image to an MMC or SD card and boot the kernel straight
from the reset vector. At reset the processor Mask ROM will load
- the first part of the the ROM-able zImage which in turn loads the
+ the first part of the ROM-able zImage which in turn loads the
rest the kernel image to RAM.
config ZBOOT_ROM_NONE
@@ -2273,9 +2251,9 @@ menu "Power management options"
source "kernel/power/Kconfig"
config ARCH_SUSPEND_POSSIBLE
- depends on !ARCH_S5PC100
+ depends on !ARCH_S5PC100 && !ARCH_TEGRA
depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \
- CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE
+ CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE || CPU_MOHAWK
def_bool y
config ARM_CPU_SUSPEND
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 047a20780fc1..157900da8782 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -70,8 +70,6 @@ arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3
# This selects how we optimise for the processor.
-tune-$(CONFIG_CPU_ARM610) :=-mtune=arm610
-tune-$(CONFIG_CPU_ARM710) :=-mtune=arm710
tune-$(CONFIG_CPU_ARM7TDMI) :=-mtune=arm7tdmi
tune-$(CONFIG_CPU_ARM720T) :=-mtune=arm7tdmi
tune-$(CONFIG_CPU_ARM740T) :=-mtune=arm7tdmi
@@ -119,7 +117,7 @@ KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_THUMB2) $(arch-y) $(tune-y) -include asm/
CHECKFLAGS += -D__arm__
#Default value
-head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
+head-y := arch/arm/kernel/head$(MMUEXT).o
textofs-y := 0x00008000
textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000
# We don't want the htc bootloader to corrupt kernel during resume
@@ -149,8 +147,6 @@ machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
machine-$(CONFIG_ARCH_IOP13XX) := iop13xx
machine-$(CONFIG_ARCH_IOP32X) := iop32x
machine-$(CONFIG_ARCH_IOP33X) := iop33x
-machine-$(CONFIG_ARCH_IXP2000) := ixp2000
-machine-$(CONFIG_ARCH_IXP23XX) := ixp23xx
machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx
machine-$(CONFIG_ARCH_KIRKWOOD) := kirkwood
machine-$(CONFIG_ARCH_KS8695) := ks8695
diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S
index aa5ee49c5c5a..6ab0599c02dd 100644
--- a/arch/arm/boot/compressed/head-xscale.S
+++ b/arch/arm/boot/compressed/head-xscale.S
@@ -32,10 +32,3 @@ __XScale_start:
bic r0, r0, #0x1000 @ clear Icache
mcr p15, 0, r0, c1, c0, 0
-#ifdef CONFIG_ARCH_IXP2000
- mov r1, #-1
- mov r0, #0xd6000000
- str r1, [r0, #0x14]
- str r1, [r0, #0x18]
-#endif
-
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index dc7e8ce8e6be..b8c64b80bafc 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -567,6 +567,12 @@ __armv3_mpu_cache_on:
mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
mov pc, lr
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+#define CB_BITS 0x08
+#else
+#define CB_BITS 0x0c
+#endif
+
__setup_mmu: sub r3, r4, #16384 @ Page directory size
bic r3, r3, #0xff @ Align the pointer
bic r3, r3, #0x3f00
@@ -578,17 +584,14 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size
mov r9, r0, lsr #18
mov r9, r9, lsl #18 @ start of RAM
add r10, r9, #0x10000000 @ a reasonable RAM size
- mov r1, #0x12
- orr r1, r1, #3 << 10
+ mov r1, #0x12 @ XN|U + section mapping
+ orr r1, r1, #3 << 10 @ AP=11
add r2, r3, #16384
1: cmp r1, r9 @ if virt > start of RAM
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
- orrhs r1, r1, #0x08 @ set cacheable
-#else
- orrhs r1, r1, #0x0c @ set cacheable, bufferable
-#endif
- cmp r1, r10 @ if virt > end of RAM
- bichs r1, r1, #0x0c @ clear cacheable, bufferable
+ cmphs r10, r1 @ && end of RAM > virt
+ bic r1, r1, #0x1c @ clear XN|U + C + B
+ orrlo r1, r1, #0x10 @ Set XN|U for non-RAM
+ orrhs r1, r1, r6 @ set RAM section settings
str r1, [r0], #4 @ 1:1 mapping
add r1, r1, #1048576
teq r0, r2
@@ -599,7 +602,7 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size
* so there is no map overlap problem for up to 1 MB compressed kernel.
* If the execution is in RAM then we would only be duplicating the above.
*/
- mov r1, #0x1e
+ orr r1, r6, #0x04 @ ensure B is set for this
orr r1, r1, #3 << 10
mov r2, pc
mov r2, r2, lsr #20
@@ -620,6 +623,7 @@ __arm926ejs_mmu_cache_on:
__armv4_mmu_cache_on:
mov r12, lr
#ifdef CONFIG_MMU
+ mov r6, #CB_BITS | 0x12 @ U
bl __setup_mmu
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
@@ -641,6 +645,7 @@ __armv7_mmu_cache_on:
#ifdef CONFIG_MMU
mrc p15, 0, r11, c0, c1, 4 @ read ID_MMFR0
tst r11, #0xf @ VMSA
+ movne r6, #CB_BITS | 0x02 @ !XN
blne __setup_mmu
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
@@ -655,7 +660,7 @@ __armv7_mmu_cache_on:
orr r0, r0, #1 << 25 @ big-endian page tables
#endif
orrne r0, r0, #1 @ MMU enabled
- movne r1, #-1
+ movne r1, #0xfffffffd @ domain 0 = client
mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer
mcrne p15, 0, r1, c3, c0, 0 @ load domain access control
#endif
@@ -668,6 +673,7 @@ __armv7_mmu_cache_on:
__fa526_cache_on:
mov r12, lr
+ mov r6, #CB_BITS | 0x12 @ U
bl __setup_mmu
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 @ Invalidate whole cache
@@ -680,18 +686,6 @@ __fa526_cache_on:
mcr p15, 0, r0, c8, c7, 0 @ flush UTLB
mov pc, r12
-__arm6_mmu_cache_on:
- mov r12, lr
- bl __setup_mmu
- mov r0, #0
- mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
- mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
- mov r0, #0x30
- bl __common_mmu_cache_on
- mov r0, #0
- mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
- mov pc, r12
-
__common_mmu_cache_on:
#ifndef CONFIG_THUMB2_KERNEL
#ifndef DEBUG
@@ -756,16 +750,6 @@ call_cache_fn: adr r12, proc_types
.align 2
.type proc_types,#object
proc_types:
- .word 0x41560600 @ ARM6/610
- .word 0xffffffe0
- W(b) __arm6_mmu_cache_off @ works, but slow
- W(b) __arm6_mmu_cache_off
- mov pc, lr
- THUMB( nop )
-@ b __arm6_mmu_cache_on @ untested
-@ b __arm6_mmu_cache_off
-@ b __armv3_mmu_cache_flush
-
.word 0x00000000 @ old ARM ID
.word 0x0000f000
mov pc, lr
@@ -777,8 +761,10 @@ proc_types:
.word 0x41007000 @ ARM7/710
.word 0xfff8fe00
- W(b) __arm7_mmu_cache_off
- W(b) __arm7_mmu_cache_off
+ mov pc, lr
+ THUMB( nop )
+ mov pc, lr
+ THUMB( nop )
mov pc, lr
THUMB( nop )
@@ -977,21 +963,6 @@ __armv7_mmu_cache_off:
mcr p15, 0, r0, c7, c5, 4 @ ISB
mov pc, r12
-__arm6_mmu_cache_off:
- mov r0, #0x00000030 @ ARM6 control reg.
- b __armv3_mmu_cache_off
-
-__arm7_mmu_cache_off:
- mov r0, #0x00000070 @ ARM7 control reg.
- b __armv3_mmu_cache_off
-
-__armv3_mmu_cache_off:
- mcr p15, 0, r0, c1, c0, 0 @ turn MMU and cache off
- mov r0, #0
- mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
- mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
- mov pc, lr
-
/*
* Clean and flush the cache to maintain consistency.
*
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
new file mode 100644
index 000000000000..f449efc9825f
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -0,0 +1,273 @@
+/*
+ * at91sam9260.dtsi - Device Tree Include file for AT91SAM9260 family SoC
+ *
+ * Copyright (C) 2011 Atmel,
+ * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>,
+ * 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9260 family SoC";
+ compatible = "atmel,at91sam9260";
+ interrupt-parent = <&aic>;
+
+ aliases {
+ serial0 = &dbgu;
+ serial1 = &usart0;
+ serial2 = &usart1;
+ serial3 = &usart2;
+ serial4 = &usart3;
+ serial5 = &usart4;
+ serial6 = &usart5;
+ gpio0 = &pioA;
+ gpio1 = &pioB;
+ gpio2 = &pioC;
+ tcb0 = &tcb0;
+ tcb1 = &tcb1;
+ };
+ cpus {
+ cpu@0 {
+ compatible = "arm,arm926ejs";
+ };
+ };
+
+ memory {
+ reg = <0x20000000 0x04000000>;
+ };
+
+ ahb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ aic: interrupt-controller@fffff000 {
+ #interrupt-cells = <2>;
+ compatible = "atmel,at91rm9200-aic";
+ interrupt-controller;
+ reg = <0xfffff000 0x200>;
+ };
+
+ ramc0: ramc@ffffea00 {
+ compatible = "atmel,at91sam9260-sdramc";
+ reg = <0xffffea00 0x200>;
+ };
+
+ pmc: pmc@fffffc00 {
+ compatible = "atmel,at91rm9200-pmc";
+ reg = <0xfffffc00 0x100>;
+ };
+
+ rstc@fffffd00 {
+ compatible = "atmel,at91sam9260-rstc";
+ reg = <0xfffffd00 0x10>;
+ };
+
+ shdwc@fffffd10 {
+ compatible = "atmel,at91sam9260-shdwc";
+ reg = <0xfffffd10 0x10>;
+ };
+
+ pit: timer@fffffd30 {
+ compatible = "atmel,at91sam9260-pit";
+ reg = <0xfffffd30 0xf>;
+ interrupts = <1 4>;
+ };
+
+ tcb0: timer@fffa0000 {
+ compatible = "atmel,at91rm9200-tcb";
+ reg = <0xfffa0000 0x100>;
+ interrupts = <17 4 18 4 19 4>;
+ };
+
+ tcb1: timer@fffdc000 {
+ compatible = "atmel,at91rm9200-tcb";
+ reg = <0xfffdc000 0x100>;
+ interrupts = <26 4 27 4 28 4>;
+ };
+
+ pioA: gpio@fffff400 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff400 0x100>;
+ interrupts = <2 4>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ pioB: gpio@fffff600 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff600 0x100>;
+ interrupts = <3 4>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ pioC: gpio@fffff800 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff800 0x100>;
+ interrupts = <4 4>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ dbgu: serial@fffff200 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffff200 0x200>;
+ interrupts = <1 4>;
+ status = "disabled";
+ };
+
+ usart0: serial@fffb0000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffb0000 0x200>;
+ interrupts = <6 4>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart1: serial@fffb4000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffb4000 0x200>;
+ interrupts = <7 4>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart2: serial@fffb8000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffb8000 0x200>;
+ interrupts = <8 4>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart3: serial@fffd0000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffd0000 0x200>;
+ interrupts = <23 4>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart4: serial@fffd4000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffd4000 0x200>;
+ interrupts = <24 4>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart5: serial@fffd8000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffd8000 0x200>;
+ interrupts = <25 4>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ macb0: ethernet@fffc4000 {
+ compatible = "cdns,at32ap7000-macb", "cdns,macb";
+ reg = <0xfffc4000 0x100>;
+ interrupts = <21 4>;
+ status = "disabled";
+ };
+
+ usb1: gadget@fffa4000 {
+ compatible = "atmel,at91rm9200-udc";
+ reg = <0xfffa4000 0x4000>;
+ interrupts = <10 4>;
+ status = "disabled";
+ };
+
+ adc0: adc@fffe0000 {
+ compatible = "atmel,at91sam9260-adc";
+ reg = <0xfffe0000 0x100>;
+ interrupts = <5 4>;
+ atmel,adc-use-external-triggers;
+ atmel,adc-channels-used = <0xf>;
+ atmel,adc-vref = <3300>;
+ atmel,adc-num-channels = <4>;
+ atmel,adc-startup-time = <15>;
+ atmel,adc-channel-base = <0x30>;
+ atmel,adc-drdy-mask = <0x10000>;
+ atmel,adc-status-register = <0x1c>;
+ atmel,adc-trigger-register = <0x04>;
+
+ trigger@0 {
+ trigger-name = "timer-counter-0";
+ trigger-value = <0x1>;
+ };
+ trigger@1 {
+ trigger-name = "timer-counter-1";
+ trigger-value = <0x3>;
+ };
+
+ trigger@2 {
+ trigger-name = "timer-counter-2";
+ trigger-value = <0x5>;
+ };
+
+ trigger@3 {
+ trigger-name = "external";
+ trigger-value = <0x13>;
+ trigger-external;
+ };
+ };
+ };
+
+ nand0: nand@40000000 {
+ compatible = "atmel,at91rm9200-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x40000000 0x10000000
+ 0xffffe800 0x200
+ >;
+ atmel,nand-addr-offset = <21>;
+ atmel,nand-cmd-offset = <22>;
+ gpios = <&pioC 13 0
+ &pioC 14 0
+ 0
+ >;
+ status = "disabled";
+ };
+
+ usb0: ohci@00500000 {
+ compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+ reg = <0x00500000 0x100000>;
+ interrupts = <20 4>;
+ status = "disabled";
+ };
+ };
+
+ i2c@0 {
+ compatible = "i2c-gpio";
+ gpios = <&pioA 23 0 /* sda */
+ &pioA 24 0 /* scl */
+ >;
+ i2c-gpio,sda-open-drain;
+ i2c-gpio,scl-open-drain;
+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
new file mode 100644
index 000000000000..0209913a65a2
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9263.dtsi
@@ -0,0 +1,220 @@
+/*
+ * at91sam9263.dtsi - Device Tree Include file for AT91SAM9263 family SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 only.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9263 family SoC";
+ compatible = "atmel,at91sam9263";
+ interrupt-parent = <&aic>;
+
+ aliases {
+ serial0 = &dbgu;
+ serial1 = &usart0;
+ serial2 = &usart1;
+ serial3 = &usart2;
+ gpio0 = &pioA;
+ gpio1 = &pioB;
+ gpio2 = &pioC;
+ gpio3 = &pioD;
+ gpio4 = &pioE;
+ tcb0 = &tcb0;
+ };
+ cpus {
+ cpu@0 {
+ compatible = "arm,arm926ejs";
+ };
+ };
+
+ memory {
+ reg = <0x20000000 0x08000000>;
+ };
+
+ ahb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ aic: interrupt-controller@fffff000 {
+ #interrupt-cells = <2>;
+ compatible = "atmel,at91rm9200-aic";
+ interrupt-controller;
+ reg = <0xfffff000 0x200>;
+ };
+
+ pmc: pmc@fffffc00 {
+ compatible = "atmel,at91rm9200-pmc";
+ reg = <0xfffffc00 0x100>;
+ };
+
+ ramc: ramc@ffffe200 {
+ compatible = "atmel,at91sam9260-sdramc";
+ reg = <0xffffe200 0x200
+ 0xffffe800 0x200>;
+ };
+
+ pit: timer@fffffd30 {
+ compatible = "atmel,at91sam9260-pit";
+ reg = <0xfffffd30 0xf>;
+ interrupts = <1 4>;
+ };
+
+ tcb0: timer@fff7c000 {
+ compatible = "atmel,at91rm9200-tcb";
+ reg = <0xfff7c000 0x100>;
+ interrupts = <19 4>;
+ };
+
+ rstc@fffffd00 {
+ compatible = "atmel,at91sam9260-rstc";
+ reg = <0xfffffd00 0x10>;
+ };
+
+ shdwc@fffffd10 {
+ compatible = "atmel,at91sam9260-shdwc";
+ reg = <0xfffffd10 0x10>;
+ };
+
+ pioA: gpio@fffff200 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff200 0x100>;
+ interrupts = <2 4>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ pioB: gpio@fffff400 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff400 0x100>;
+ interrupts = <3 4>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ pioC: gpio@fffff600 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff600 0x100>;
+ interrupts = <4 4>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ pioD: gpio@fffff800 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff800 0x100>;
+ interrupts = <4 4>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ pioE: gpio@fffffa00 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffffa00 0x100>;
+ interrupts = <4 4>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ dbgu: serial@ffffee00 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xffffee00 0x200>;
+ interrupts = <1 4>;
+ status = "disabled";
+ };
+
+ usart0: serial@fff8c000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfff8c000 0x200>;
+ interrupts = <7 4>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart1: serial@fff90000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfff90000 0x200>;
+ interrupts = <8 4>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart2: serial@fff94000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfff94000 0x200>;
+ interrupts = <9 4>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ macb0: ethernet@fffbc000 {
+ compatible = "cdns,at32ap7000-macb", "cdns,macb";
+ reg = <0xfffbc000 0x100>;
+ interrupts = <21 4>;
+ status = "disabled";
+ };
+
+ usb1: gadget@fff78000 {
+ compatible = "atmel,at91rm9200-udc";
+ reg = <0xfff78000 0x4000>;
+ interrupts = <24 4>;
+ status = "disabled";
+ };
+ };
+
+ nand0: nand@40000000 {
+ compatible = "atmel,at91rm9200-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x40000000 0x10000000
+ 0xffffe000 0x200
+ >;
+ atmel,nand-addr-offset = <21>;
+ atmel,nand-cmd-offset = <22>;
+ gpios = <&pioA 22 0
+ &pioD 15 0
+ 0
+ >;
+ status = "disabled";
+ };
+
+ usb0: ohci@00a00000 {
+ compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+ reg = <0x00a00000 0x100000>;
+ interrupts = <29 4>;
+ status = "disabled";
+ };
+ };
+
+ i2c@0 {
+ compatible = "i2c-gpio";
+ gpios = <&pioB 4 0 /* sda */
+ &pioB 5 0 /* scl */
+ >;
+ i2c-gpio,sda-open-drain;
+ i2c-gpio,scl-open-drain;
+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9263ek.dts b/arch/arm/boot/dts/at91sam9263ek.dts
new file mode 100644
index 000000000000..f86ac4b609fc
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9263ek.dts
@@ -0,0 +1,156 @@
+/*
+ * at91sam9263ek.dts - Device Tree file for Atmel at91sam9263 reference board
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 only
+ */
+/dts-v1/;
+/include/ "at91sam9263.dtsi"
+
+/ {
+ model = "Atmel at91sam9263ek";
+ compatible = "atmel,at91sam9263ek", "atmel,at91sam9263", "atmel,at91sam9";
+
+ chosen {
+ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
+ };
+
+ memory {
+ reg = <0x20000000 0x4000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ main_clock: clock@0 {
+ compatible = "atmel,osc", "fixed-clock";
+ clock-frequency = <16367660>;
+ };
+ };
+
+ ahb {
+ apb {
+ dbgu: serial@ffffee00 {
+ status = "okay";
+ };
+
+ usart0: serial@fff8c000 {
+ status = "okay";
+ };
+
+ macb0: ethernet@fffbc000 {
+ phy-mode = "rmii";
+ status = "okay";
+ };
+
+ usb1: gadget@fff78000 {
+ atmel,vbus-gpio = <&pioA 25 0>;
+ status = "okay";
+ };
+ };
+
+ nand0: nand@40000000 {
+ nand-bus-width = <8>;
+ nand-ecc-mode = "soft";
+ nand-on-flash-bbt = <1>;
+ status = "okay";
+
+ at91bootstrap@0 {
+ label = "at91bootstrap";
+ reg = <0x0 0x20000>;
+ };
+
+ barebox@20000 {
+ label = "barebox";
+ reg = <0x20000 0x40000>;
+ };
+
+ bareboxenv@60000 {
+ label = "bareboxenv";
+ reg = <0x60000 0x20000>;
+ };
+
+ bareboxenv2@80000 {
+ label = "bareboxenv2";
+ reg = <0x80000 0x20000>;
+ };
+
+ oftree@80000 {
+ label = "oftree";
+ reg = <0xa0000 0x20000>;
+ };
+
+ kernel@a0000 {
+ label = "kernel";
+ reg = <0xc0000 0x400000>;
+ };
+
+ rootfs@4a0000 {
+ label = "rootfs";
+ reg = <0x4c0000 0x7800000>;
+ };
+
+ data@7ca0000 {
+ label = "data";
+ reg = <0x7cc0000 0x8340000>;
+ };
+ };
+
+ usb0: ohci@00a00000 {
+ num-ports = <2>;
+ status = "okay";
+ atmel,vbus-gpio = <&pioA 24 0
+ &pioA 21 0
+ >;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ d3 {
+ label = "d3";
+ gpios = <&pioB 7 0>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ d2 {
+ label = "d2";
+ gpios = <&pioC 29 1>;
+ linux,default-trigger = "nand-disk";
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ left_click {
+ label = "left_click";
+ gpios = <&pioC 5 1>;
+ linux,code = <272>;
+ gpio-key,wakeup;
+ };
+
+ right_click {
+ label = "right_click";
+ gpios = <&pioC 4 1>;
+ linux,code = <273>;
+ gpio-key,wakeup;
+ };
+ };
+
+ i2c@0 {
+ status = "okay";
+
+ 24c512@50 {
+ compatible = "24c512";
+ reg = <0x50>;
+ pagesize = <128>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi
index 773ef484037a..2a1d1ca8bd86 100644
--- a/arch/arm/boot/dts/at91sam9g20.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20.dtsi
@@ -1,238 +1,26 @@
/*
* at91sam9g20.dtsi - Device Tree Include file for AT91SAM9G20 family SoC
*
- * Copyright (C) 2011 Atmel,
- * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>,
- * 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
*
- * Licensed under GPLv2 or later.
+ * Licensed under GPLv2.
*/
-/include/ "skeleton.dtsi"
+/include/ "at91sam9260.dtsi"
/ {
model = "Atmel AT91SAM9G20 family SoC";
compatible = "atmel,at91sam9g20";
- interrupt-parent = <&aic>;
-
- aliases {
- serial0 = &dbgu;
- serial1 = &usart0;
- serial2 = &usart1;
- serial3 = &usart2;
- serial4 = &usart3;
- serial5 = &usart4;
- serial6 = &usart5;
- gpio0 = &pioA;
- gpio1 = &pioB;
- gpio2 = &pioC;
- tcb0 = &tcb0;
- tcb1 = &tcb1;
- };
- cpus {
- cpu@0 {
- compatible = "arm,arm926ejs";
- };
- };
memory {
reg = <0x20000000 0x08000000>;
};
ahb {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
apb {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
- aic: interrupt-controller@fffff000 {
- #interrupt-cells = <2>;
- compatible = "atmel,at91rm9200-aic";
- interrupt-controller;
- reg = <0xfffff000 0x200>;
- };
-
- ramc0: ramc@ffffea00 {
- compatible = "atmel,at91sam9260-sdramc";
- reg = <0xffffea00 0x200>;
- };
-
- pmc: pmc@fffffc00 {
- compatible = "atmel,at91rm9200-pmc";
- reg = <0xfffffc00 0x100>;
- };
-
- rstc@fffffd00 {
- compatible = "atmel,at91sam9260-rstc";
- reg = <0xfffffd00 0x10>;
- };
-
- shdwc@fffffd10 {
- compatible = "atmel,at91sam9260-shdwc";
- reg = <0xfffffd10 0x10>;
- };
-
- pit: timer@fffffd30 {
- compatible = "atmel,at91sam9260-pit";
- reg = <0xfffffd30 0xf>;
- interrupts = <1 4>;
- };
-
- tcb0: timer@fffa0000 {
- compatible = "atmel,at91rm9200-tcb";
- reg = <0xfffa0000 0x100>;
- interrupts = <17 4 18 4 19 4>;
- };
-
- tcb1: timer@fffdc000 {
- compatible = "atmel,at91rm9200-tcb";
- reg = <0xfffdc000 0x100>;
- interrupts = <26 4 27 4 28 4>;
- };
-
- pioA: gpio@fffff400 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x100>;
- interrupts = <2 4>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- };
-
- pioB: gpio@fffff600 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff600 0x100>;
- interrupts = <3 4>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- };
-
- pioC: gpio@fffff800 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff800 0x100>;
- interrupts = <4 4>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- };
-
- dbgu: serial@fffff200 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffff200 0x200>;
- interrupts = <1 4>;
- status = "disabled";
- };
-
- usart0: serial@fffb0000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffb0000 0x200>;
- interrupts = <6 4>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
- };
-
- usart1: serial@fffb4000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffb4000 0x200>;
- interrupts = <7 4>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
- };
-
- usart2: serial@fffb8000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffb8000 0x200>;
- interrupts = <8 4>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
- };
-
- usart3: serial@fffd0000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffd0000 0x200>;
- interrupts = <23 4>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
- };
-
- usart4: serial@fffd4000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffd4000 0x200>;
- interrupts = <24 4>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
- };
-
- usart5: serial@fffd8000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffd8000 0x200>;
- interrupts = <25 4>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
- };
-
- macb0: ethernet@fffc4000 {
- compatible = "cdns,at32ap7000-macb", "cdns,macb";
- reg = <0xfffc4000 0x100>;
- interrupts = <21 4>;
- status = "disabled";
- };
-
- usb1: gadget@fffa4000 {
- compatible = "atmel,at91rm9200-udc";
- reg = <0xfffa4000 0x4000>;
- interrupts = <10 4>;
- status = "disabled";
+ adc0: adc@fffe0000 {
+ atmel,adc-startup-time = <40>;
};
};
-
- nand0: nand@40000000 {
- compatible = "atmel,at91rm9200-nand";
- #address-cells = <1>;
- #size-cells = <1>;
- reg = <0x40000000 0x10000000
- 0xffffe800 0x200
- >;
- atmel,nand-addr-offset = <21>;
- atmel,nand-cmd-offset = <22>;
- gpios = <&pioC 13 0
- &pioC 14 0
- 0
- >;
- status = "disabled";
- };
-
- usb0: ohci@00500000 {
- compatible = "atmel,at91rm9200-ohci", "usb-ohci";
- reg = <0x00500000 0x100000>;
- interrupts = <20 4>;
- status = "disabled";
- };
- };
-
- i2c@0 {
- compatible = "i2c-gpio";
- gpios = <&pioA 23 0 /* sda */
- &pioA 24 0 /* scl */
- >;
- i2c-gpio,sda-open-drain;
- i2c-gpio,scl-open-drain;
- i2c-gpio,delay-us = <2>; /* ~100 kHz */
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/at91sam9g20ek.dts b/arch/arm/boot/dts/at91sam9g20ek.dts
new file mode 100644
index 000000000000..e5324bf9d529
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g20ek.dts
@@ -0,0 +1,29 @@
+/*
+ * at91sam9g20ek.dts - Device Tree file for Atmel at91sam9g20ek board
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+/dts-v1/;
+/include/ "at91sam9g20ek_common.dtsi"
+
+/ {
+ model = "Atmel at91sam9g20ek";
+ compatible = "atmel,at91sam9g20ek", "atmel,at91sam9g20", "atmel,at91sam9";
+
+ leds {
+ compatible = "gpio-leds";
+
+ ds1 {
+ label = "ds1";
+ gpios = <&pioA 9 0>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ ds5 {
+ label = "ds5";
+ gpios = <&pioA 6 1>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts b/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
new file mode 100644
index 000000000000..f1b2e148ac8c
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
@@ -0,0 +1,29 @@
+/*
+ * at91sam9g20ek_2mmc.dts - Device Tree file for Atmel at91sam9g20ek 2 MMC board
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+/dts-v1/;
+/include/ "at91sam9g20ek_common.dtsi"
+
+/ {
+ model = "Atmel at91sam9g20ek 2 mmc";
+ compatible = "atmel,at91sam9g20ek_2mmc", "atmel,at91sam9g20", "atmel,at91sam9";
+
+ leds {
+ compatible = "gpio-leds";
+
+ ds1 {
+ label = "ds1";
+ gpios = <&pioB 9 0>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ ds5 {
+ label = "ds5";
+ gpios = <&pioB 8 1>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
new file mode 100644
index 000000000000..b06c0db273b1
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
@@ -0,0 +1,142 @@
+/*
+ * at91sam9g20ek_common.dtsi - Device Tree file for Atmel at91sam9g20ek board
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+/include/ "at91sam9g20.dtsi"
+
+/ {
+
+ chosen {
+ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
+ };
+
+ memory {
+ reg = <0x20000000 0x4000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ main_clock: clock@0 {
+ compatible = "atmel,osc", "fixed-clock";
+ clock-frequency = <18432000>;
+ };
+ };
+
+ ahb {
+ apb {
+ dbgu: serial@fffff200 {
+ status = "okay";
+ };
+
+ usart0: serial@fffb0000 {
+ status = "okay";
+ };
+
+ usart1: serial@fffb4000 {
+ status = "okay";
+ };
+
+ macb0: ethernet@fffc4000 {
+ phy-mode = "rmii";
+ status = "okay";
+ };
+
+ usb1: gadget@fffa4000 {
+ atmel,vbus-gpio = <&pioC 5 0>;
+ status = "okay";
+ };
+ };
+
+ nand0: nand@40000000 {
+ nand-bus-width = <8>;
+ nand-ecc-mode = "soft";
+ nand-on-flash-bbt;
+ status = "okay";
+
+ at91bootstrap@0 {
+ label = "at91bootstrap";
+ reg = <0x0 0x20000>;
+ };
+
+ barebox@20000 {
+ label = "barebox";
+ reg = <0x20000 0x40000>;
+ };
+
+ bareboxenv@60000 {
+ label = "bareboxenv";
+ reg = <0x60000 0x20000>;
+ };
+
+ bareboxenv2@80000 {
+ label = "bareboxenv2";
+ reg = <0x80000 0x20000>;
+ };
+
+ oftree@80000 {
+ label = "oftree";
+ reg = <0xa0000 0x20000>;
+ };
+
+ kernel@a0000 {
+ label = "kernel";
+ reg = <0xc0000 0x400000>;
+ };
+
+ rootfs@4a0000 {
+ label = "rootfs";
+ reg = <0x4c0000 0x7800000>;
+ };
+
+ data@7ca0000 {
+ label = "data";
+ reg = <0x7cc0000 0x8340000>;
+ };
+ };
+
+ usb0: ohci@00500000 {
+ num-ports = <2>;
+ status = "okay";
+ };
+ };
+
+ i2c@0 {
+ status = "okay";
+
+ 24c512@50 {
+ compatible = "24c512";
+ reg = <0x50>;
+ };
+
+ wm8731@1b {
+ compatible = "wm8731";
+ reg = <0x1b>;
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ btn3 {
+ label = "Buttin 3";
+ gpios = <&pioA 30 1>;
+ linux,code = <0x103>;
+ gpio-key,wakeup;
+ };
+
+ btn4 {
+ label = "Buttin 4";
+ gpios = <&pioA 31 1>;
+ linux,code = <0x104>;
+ gpio-key,wakeup;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index c8042147eaa2..7dbccaf199f7 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -199,6 +199,43 @@
interrupts = <25 4>;
status = "disabled";
};
+
+ adc0: adc@fffb0000 {
+ compatible = "atmel,at91sam9260-adc";
+ reg = <0xfffb0000 0x100>;
+ interrupts = <20 4>;
+ atmel,adc-use-external-triggers;
+ atmel,adc-channels-used = <0xff>;
+ atmel,adc-vref = <3300>;
+ atmel,adc-num-channels = <8>;
+ atmel,adc-startup-time = <40>;
+ atmel,adc-channel-base = <0x30>;
+ atmel,adc-drdy-mask = <0x10000>;
+ atmel,adc-status-register = <0x1c>;
+ atmel,adc-trigger-register = <0x08>;
+
+ trigger@0 {
+ trigger-name = "external-rising";
+ trigger-value = <0x1>;
+ trigger-external;
+ };
+ trigger@1 {
+ trigger-name = "external-falling";
+ trigger-value = <0x2>;
+ trigger-external;
+ };
+
+ trigger@2 {
+ trigger-name = "external-any";
+ trigger-value = <0x3>;
+ trigger-external;
+ };
+
+ trigger@3 {
+ trigger-name = "continuous";
+ trigger-value = <0x6>;
+ };
+ };
};
nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
new file mode 100644
index 000000000000..cb84de791b5a
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
@@ -0,0 +1,221 @@
+/*
+ * at91sam9n12.dtsi - Device Tree include file for AT91SAM9N12 SoC
+ *
+ * Copyright (C) 2012 Atmel,
+ * 2012 Hong Xu <hong.xu@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9N12 SoC";
+ compatible = "atmel,at91sam9n12";
+ interrupt-parent = <&aic>;
+
+ aliases {
+ serial0 = &dbgu;
+ serial1 = &usart0;
+ serial2 = &usart1;
+ serial3 = &usart2;
+ serial4 = &usart3;
+ gpio0 = &pioA;
+ gpio1 = &pioB;
+ gpio2 = &pioC;
+ gpio3 = &pioD;
+ tcb0 = &tcb0;
+ tcb1 = &tcb1;
+ };
+ cpus {
+ cpu@0 {
+ compatible = "arm,arm926ejs";
+ };
+ };
+
+ memory {
+ reg = <0x20000000 0x10000000>;
+ };
+
+ ahb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ aic: interrupt-controller@fffff000 {
+ #interrupt-cells = <2>;
+ compatible = "atmel,at91rm9200-aic";
+ interrupt-controller;
+ reg = <0xfffff000 0x200>;
+ };
+
+ ramc0: ramc@ffffe800 {
+ compatible = "atmel,at91sam9g45-ddramc";
+ reg = <0xffffe800 0x200>;
+ };
+
+ pmc: pmc@fffffc00 {
+ compatible = "atmel,at91rm9200-pmc";
+ reg = <0xfffffc00 0x100>;
+ };
+
+ rstc@fffffe00 {
+ compatible = "atmel,at91sam9g45-rstc";
+ reg = <0xfffffe00 0x10>;
+ };
+
+ pit: timer@fffffe30 {
+ compatible = "atmel,at91sam9260-pit";
+ reg = <0xfffffe30 0xf>;
+ interrupts = <1 4>;
+ };
+
+ shdwc@fffffe10 {
+ compatible = "atmel,at91sam9x5-shdwc";
+ reg = <0xfffffe10 0x10>;
+ };
+
+ tcb0: timer@f8008000 {
+ compatible = "atmel,at91sam9x5-tcb";
+ reg = <0xf8008000 0x100>;
+ interrupts = <17 4>;
+ };
+
+ tcb1: timer@f800c000 {
+ compatible = "atmel,at91sam9x5-tcb";
+ reg = <0xf800c000 0x100>;
+ interrupts = <17 4>;
+ };
+
+ dma: dma-controller@ffffec00 {
+ compatible = "atmel,at91sam9g45-dma";
+ reg = <0xffffec00 0x200>;
+ interrupts = <20 4>;
+ };
+
+ pioA: gpio@fffff400 {
+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffff400 0x100>;
+ interrupts = <2 4>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ pioB: gpio@fffff600 {
+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffff600 0x100>;
+ interrupts = <2 4>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ pioC: gpio@fffff800 {
+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffff800 0x100>;
+ interrupts = <3 4>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ pioD: gpio@fffffa00 {
+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffffa00 0x100>;
+ interrupts = <3 4>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ };
+
+ dbgu: serial@fffff200 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffff200 0x200>;
+ interrupts = <1 4>;
+ status = "disabled";
+ };
+
+ usart0: serial@f801c000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xf801c000 0x4000>;
+ interrupts = <5 4>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart1: serial@f8020000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xf8020000 0x4000>;
+ interrupts = <6 4>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart2: serial@f8024000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xf8024000 0x4000>;
+ interrupts = <7 4>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart3: serial@f8028000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xf8028000 0x4000>;
+ interrupts = <8 4>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+ };
+
+ nand0: nand@40000000 {
+ compatible = "atmel,at91rm9200-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = < 0x40000000 0x10000000
+ 0xffffe000 0x00000600
+ 0xffffe600 0x00000200
+ 0x00100000 0x00100000
+ >;
+ atmel,nand-addr-offset = <21>;
+ atmel,nand-cmd-offset = <22>;
+ gpios = <&pioD 5 0
+ &pioD 4 0
+ 0
+ >;
+ status = "disabled";
+ };
+
+ usb0: ohci@00500000 {
+ compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+ reg = <0x00500000 0x00100000>;
+ interrupts = <22 4>;
+ status = "disabled";
+ };
+ };
+
+ i2c@0 {
+ compatible = "i2c-gpio";
+ gpios = <&pioA 30 0 /* sda */
+ &pioA 31 0 /* scl */
+ >;
+ i2c-gpio,sda-open-drain;
+ i2c-gpio,scl-open-drain;
+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts
new file mode 100644
index 000000000000..f4e43e38f3a1
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9n12ek.dts
@@ -0,0 +1,84 @@
+/*
+ * at91sam9n12ek.dts - Device Tree file for AT91SAM9N12-EK board
+ *
+ * Copyright (C) 2012 Atmel,
+ * 2012 Hong Xu <hong.xu@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9n12.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9N12-EK";
+ compatible = "atmel,at91sam9n12ek", "atmel,at91sam9n12", "atmel,at91sam9";
+
+ chosen {
+ bootargs = "mem=128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
+ };
+
+ memory {
+ reg = <0x20000000 0x10000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ main_clock: clock@0 {
+ compatible = "atmel,osc", "fixed-clock";
+ clock-frequency = <16000000>;
+ };
+ };
+
+ ahb {
+ apb {
+ dbgu: serial@fffff200 {
+ status = "okay";
+ };
+ };
+
+ nand0: nand@40000000 {
+ nand-bus-width = <8>;
+ nand-ecc-mode = "soft";
+ nand-on-flash-bbt;
+ status = "okay";
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ d8 {
+ label = "d8";
+ gpios = <&pioB 4 1>;
+ linux,default-trigger = "mmc0";
+ };
+
+ d9 {
+ label = "d6";
+ gpios = <&pioB 5 1>;
+ linux,default-trigger = "nand-disk";
+ };
+
+ d10 {
+ label = "d7";
+ gpios = <&pioB 6 0>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ enter {
+ label = "Enter";
+ gpios = <&pioB 4 1>;
+ linux,code = <28>;
+ gpio-key,wakeup;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index dd4ed748469a..6b3ef4339ae7 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -190,6 +190,44 @@
interrupts = <27 4>;
status = "disabled";
};
+
+ adc0: adc@f804c000 {
+ compatible = "atmel,at91sam9260-adc";
+ reg = <0xf804c000 0x100>;
+ interrupts = <19 4>;
+ atmel,adc-use-external;
+ atmel,adc-channels-used = <0xffff>;
+ atmel,adc-vref = <3300>;
+ atmel,adc-num-channels = <12>;
+ atmel,adc-startup-time = <40>;
+ atmel,adc-channel-base = <0x50>;
+ atmel,adc-drdy-mask = <0x1000000>;
+ atmel,adc-status-register = <0x30>;
+ atmel,adc-trigger-register = <0xc0>;
+
+ trigger@0 {
+ trigger-name = "external-rising";
+ trigger-value = <0x1>;
+ trigger-external;
+ };
+
+ trigger@1 {
+ trigger-name = "external-falling";
+ trigger-value = <0x2>;
+ trigger-external;
+ };
+
+ trigger@2 {
+ trigger-name = "external-any";
+ trigger-value = <0x3>;
+ trigger-external;
+ };
+
+ trigger@3 {
+ trigger-name = "continuous";
+ trigger-value = <0x6>;
+ };
+ };
};
nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi
index 14bc30705099..881bc3987844 100644
--- a/arch/arm/boot/dts/db8500.dtsi
+++ b/arch/arm/boot/dts/db8500.dtsi
@@ -55,83 +55,101 @@
gpio0: gpio@8012e000 {
compatible = "stericsson,db8500-gpio",
- "stmicroelectronics,nomadik-gpio";
+ "st,nomadik-gpio";
reg = <0x8012e000 0x80>;
interrupts = <0 119 0x4>;
supports-sleepmode;
gpio-controller;
+ #gpio-cells = <2>;
+ gpio-bank = <0>;
};
gpio1: gpio@8012e080 {
compatible = "stericsson,db8500-gpio",
- "stmicroelectronics,nomadik-gpio";
+ "st,nomadik-gpio";
reg = <0x8012e080 0x80>;
interrupts = <0 120 0x4>;
supports-sleepmode;
gpio-controller;
+ #gpio-cells = <2>;
+ gpio-bank = <1>;
};
gpio2: gpio@8000e000 {
compatible = "stericsson,db8500-gpio",
- "stmicroelectronics,nomadik-gpio";
+ "st,nomadik-gpio";
reg = <0x8000e000 0x80>;
interrupts = <0 121 0x4>;
supports-sleepmode;
gpio-controller;
+ #gpio-cells = <2>;
+ gpio-bank = <2>;
};
gpio3: gpio@8000e080 {
compatible = "stericsson,db8500-gpio",
- "stmicroelectronics,nomadik-gpio";
+ "st,nomadik-gpio";
reg = <0x8000e080 0x80>;
interrupts = <0 122 0x4>;
supports-sleepmode;
gpio-controller;
+ #gpio-cells = <2>;
+ gpio-bank = <3>;
};
gpio4: gpio@8000e100 {
compatible = "stericsson,db8500-gpio",
- "stmicroelectronics,nomadik-gpio";
+ "st,nomadik-gpio";
reg = <0x8000e100 0x80>;
interrupts = <0 123 0x4>;
supports-sleepmode;
gpio-controller;
+ #gpio-cells = <2>;
+ gpio-bank = <4>;
};
gpio5: gpio@8000e180 {
compatible = "stericsson,db8500-gpio",
- "stmicroelectronics,nomadik-gpio";
+ "st,nomadik-gpio";
reg = <0x8000e180 0x80>;
interrupts = <0 124 0x4>;
supports-sleepmode;
gpio-controller;
+ #gpio-cells = <2>;
+ gpio-bank = <5>;
};
gpio6: gpio@8011e000 {
compatible = "stericsson,db8500-gpio",
- "stmicroelectronics,nomadik-gpio";
+ "st,nomadik-gpio";
reg = <0x8011e000 0x80>;
interrupts = <0 125 0x4>;
supports-sleepmode;
gpio-controller;
+ #gpio-cells = <2>;
+ gpio-bank = <6>;
};
gpio7: gpio@8011e080 {
compatible = "stericsson,db8500-gpio",
- "stmicroelectronics,nomadik-gpio";
+ "st,nomadik-gpio";
reg = <0x8011e080 0x80>;
interrupts = <0 126 0x4>;
supports-sleepmode;
gpio-controller;
+ #gpio-cells = <2>;
+ gpio-bank = <7>;
};
gpio8: gpio@a03fe000 {
compatible = "stericsson,db8500-gpio",
- "stmicroelectronics,nomadik-gpio";
+ "st,nomadik-gpio";
reg = <0xa03fe000 0x80>;
interrupts = <0 127 0x4>;
supports-sleepmode;
gpio-controller;
+ #gpio-cells = <2>;
+ gpio-bank = <8>;
};
usb@a03e0000 {
@@ -153,7 +171,13 @@
reg = <0x80157000 0x1000>;
interrupts = <46 47>;
#address-cells = <1>;
- #size-cells = <0>;
+ #size-cells = <1>;
+ ranges;
+
+ prcmu-timer-4@80157450 {
+ compatible = "stericsson,db8500-prcmu-timer-4";
+ reg = <0x80157450 0xC>;
+ };
ab8500@5 {
compatible = "stericsson,ab8500";
@@ -163,7 +187,7 @@
};
i2c@80004000 {
- compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c";
+ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c";
reg = <0x80004000 0x1000>;
interrupts = <0 21 0x4>;
#address-cells = <1>;
@@ -171,7 +195,7 @@
};
i2c@80122000 {
- compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c";
+ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c";
reg = <0x80122000 0x1000>;
interrupts = <0 22 0x4>;
#address-cells = <1>;
@@ -179,7 +203,7 @@
};
i2c@80128000 {
- compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c";
+ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c";
reg = <0x80128000 0x1000>;
interrupts = <0 55 0x4>;
#address-cells = <1>;
@@ -187,7 +211,7 @@
};
i2c@80110000 {
- compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c";
+ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c";
reg = <0x80110000 0x1000>;
interrupts = <0 12 0x4>;
#address-cells = <1>;
@@ -195,7 +219,7 @@
};
i2c@8012a000 {
- compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c";
+ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c";
reg = <0x8012a000 0x1000>;
interrupts = <0 51 0x4>;
#address-cells = <1>;
@@ -270,5 +294,14 @@
interrupts = <0 100 0x4>;
status = "disabled";
};
+
+ external-bus@50000000 {
+ compatible = "simple-bus";
+ reg = <0x50000000 0x4000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x50000000 0x4000000>;
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/emev2-kzm9d.dts b/arch/arm/boot/dts/emev2-kzm9d.dts
new file mode 100644
index 000000000000..297e3baba71c
--- /dev/null
+++ b/arch/arm/boot/dts/emev2-kzm9d.dts
@@ -0,0 +1,26 @@
+/*
+ * Device Tree Source for the KZM9D board
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+/dts-v1/;
+
+/include/ "emev2.dtsi"
+
+/ {
+ model = "EMEV2 KZM9D Board";
+ compatible = "renesas,kzm9d", "renesas,emev2";
+
+ memory {
+ device_type = "memory";
+ reg = <0x40000000 0x8000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS1,115200n81";
+ };
+};
diff --git a/arch/arm/boot/dts/emev2.dtsi b/arch/arm/boot/dts/emev2.dtsi
new file mode 100644
index 000000000000..eb504a6c0f4a
--- /dev/null
+++ b/arch/arm/boot/dts/emev2.dtsi
@@ -0,0 +1,63 @@
+/*
+ * Device Tree Source for the EMEV2 SoC
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "renesas,emev2";
+ interrupt-parent = <&gic>;
+
+ cpus {
+ cpu@0 {
+ compatible = "arm,cortex-a9";
+ };
+ cpu@1 {
+ compatible = "arm,cortex-a9";
+ };
+ };
+
+ gic: interrupt-controller@e0020000 {
+ compatible = "arm,cortex-a9-gic";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ reg = <0xe0028000 0x1000>,
+ <0xe0020000 0x0100>;
+ };
+
+ sti@e0180000 {
+ compatible = "renesas,em-sti";
+ reg = <0xe0180000 0x54>;
+ interrupts = <0 125 0>;
+ };
+
+ uart@e1020000 {
+ compatible = "renesas,em-uart";
+ reg = <0xe1020000 0x38>;
+ interrupts = <0 8 0>;
+ };
+
+ uart@e1030000 {
+ compatible = "renesas,em-uart";
+ reg = <0xe1030000 0x38>;
+ interrupts = <0 9 0>;
+ };
+
+ uart@e1040000 {
+ compatible = "renesas,em-uart";
+ reg = <0xe1040000 0x38>;
+ interrupts = <0 10 0>;
+ };
+
+ uart@e1050000 {
+ compatible = "renesas,em-uart";
+ reg = <0xe1050000 0x38>;
+ interrupts = <0 11 0>;
+ };
+};
diff --git a/arch/arm/boot/dts/ethernut5.dts b/arch/arm/boot/dts/ethernut5.dts
new file mode 100644
index 000000000000..1ea9d34460a4
--- /dev/null
+++ b/arch/arm/boot/dts/ethernut5.dts
@@ -0,0 +1,84 @@
+/*
+ * ethernut5.dts - Device Tree file for Ethernut 5 board
+ *
+ * Copyright (C) 2012 egnite GmbH <info@egnite.de>
+ *
+ * Licensed under GPLv2.
+ */
+/dts-v1/;
+/include/ "at91sam9260.dtsi"
+
+/ {
+ model = "Ethernut 5";
+ compatible = "egnite,ethernut5", "atmel,at91sam9260", "atmel,at91sam9";
+
+ chosen {
+ bootargs = "console=ttyS0,115200 root=/dev/mtdblock0 rw rootfstype=jffs2";
+ };
+
+ memory {
+ reg = <0x20000000 0x08000000>;
+ };
+
+ ahb {
+ apb {
+ dbgu: serial@fffff200 {
+ status = "okay";
+ };
+
+ usart0: serial@fffb0000 {
+ status = "okay";
+ };
+
+ usart1: serial@fffb4000 {
+ status = "okay";
+ };
+
+ macb0: ethernet@fffc4000 {
+ phy-mode = "rmii";
+ status = "okay";
+ };
+
+ usb1: gadget@fffa4000 {
+ atmel,vbus-gpio = <&pioC 5 0>;
+ status = "okay";
+ };
+ };
+
+ nand0: nand@40000000 {
+ nand-bus-width = <8>;
+ nand-ecc-mode = "soft";
+ nand-on-flash-bbt;
+ status = "okay";
+
+ gpios = <0
+ &pioC 14 0
+ 0
+ >;
+
+ root@0 {
+ label = "root";
+ reg = <0x0 0x08000000>;
+ };
+
+ data@20000 {
+ label = "data";
+ reg = <0x08000000 0x38000000>;
+ };
+ };
+
+ usb0: ohci@00500000 {
+ num-ports = <2>;
+ status = "okay";
+ };
+ };
+
+ i2c@0 {
+ status = "okay";
+
+ pcf8563@50 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/kirkwood-dns320.dts b/arch/arm/boot/dts/kirkwood-dns320.dts
new file mode 100644
index 000000000000..dc09a735b04a
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-dns320.dts
@@ -0,0 +1,64 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+
+/ {
+ model = "D-Link DNS-320 NAS (Rev A1)";
+ compatible = "dlink,dns-320-a1", "dlink,dns-320", "dlink,dns-kirkwood", "mrvl,kirkwood-88f6281", "mrvl,kirkwood";
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x8000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8 earlyprintk";
+ };
+
+ ocp@f1000000 {
+ serial@12000 {
+ clock-frequency = <166666667>;
+ status = "okay";
+ };
+
+ serial@12100 {
+ clock-frequency = <166666667>;
+ status = "okay";
+ };
+
+ nand@3000000 {
+ status = "okay";
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0000000 0x100000>;
+ read-only;
+ };
+
+ partition@100000 {
+ label = "uImage";
+ reg = <0x0100000 0x500000>;
+ };
+
+ partition@600000 {
+ label = "ramdisk";
+ reg = <0x0600000 0x500000>;
+ };
+
+ partition@b00000 {
+ label = "image";
+ reg = <0x0b00000 0x6600000>;
+ };
+
+ partition@7100000 {
+ label = "mini firmware";
+ reg = <0x7100000 0xa00000>;
+ };
+
+ partition@7b00000 {
+ label = "config";
+ reg = <0x7b00000 0x500000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/kirkwood-dns325.dts b/arch/arm/boot/dts/kirkwood-dns325.dts
new file mode 100644
index 000000000000..c2a5562525d2
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-dns325.dts
@@ -0,0 +1,59 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+
+/ {
+ model = "D-Link DNS-325 NAS (Rev A1)";
+ compatible = "dlink,dns-325-a1", "dlink,dns-325", "dlink,dns-kirkwood", "mrvl,kirkwood-88f6281", "mrvl,kirkwood";
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x10000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8 earlyprintk";
+ };
+
+ ocp@f1000000 {
+ serial@12000 {
+ clock-frequency = <200000000>;
+ status = "okay";
+ };
+
+ nand@3000000 {
+ status = "okay";
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0000000 0x100000>;
+ read-only;
+ };
+
+ partition@100000 {
+ label = "uImage";
+ reg = <0x0100000 0x500000>;
+ };
+
+ partition@600000 {
+ label = "ramdisk";
+ reg = <0x0600000 0x500000>;
+ };
+
+ partition@b00000 {
+ label = "image";
+ reg = <0x0b00000 0x6600000>;
+ };
+
+ partition@7100000 {
+ label = "mini firmware";
+ reg = <0x7100000 0xa00000>;
+ };
+
+ partition@7b00000 {
+ label = "config";
+ reg = <0x7b00000 0x500000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/kirkwood-ib62x0.dts b/arch/arm/boot/dts/kirkwood-ib62x0.dts
new file mode 100644
index 000000000000..ada0f0c23085
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ib62x0.dts
@@ -0,0 +1,44 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+
+/ {
+ model = "RaidSonic ICY BOX IB-NAS62x0 (Rev B)";
+ compatible = "raidsonic,ib-nas6210-b", "raidsonic,ib-nas6220-b", "raidsonic,ib-nas6210", "raidsonic,ib-nas6220", "raidsonic,ib-nas62x0", "mrvl,kirkwood-88f6281", "mrvl,kirkwood";
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x10000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8 earlyprintk";
+ };
+
+ ocp@f1000000 {
+ serial@12000 {
+ clock-frequency = <200000000>;
+ status = "okay";
+ };
+
+ nand@3000000 {
+ status = "okay";
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0000000 0x100000>;
+ };
+
+ partition@100000 {
+ label = "uImage";
+ reg = <0x0100000 0x600000>;
+ };
+
+ partition@700000 {
+ label = "root";
+ reg = <0x0700000 0xf900000>;
+ };
+
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/kirkwood-iconnect.dts b/arch/arm/boot/dts/kirkwood-iconnect.dts
new file mode 100644
index 000000000000..1ba75d4adecc
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-iconnect.dts
@@ -0,0 +1,26 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+
+/ {
+ model = "Iomega Iconnect";
+ compatible = "iom,iconnect-1.1", "iom,iconnect", "mrvl,kirkwood-88f6281", "mrvl,kirkwood";
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x10000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8 earlyprintk mtdparts=orion_nand:0xc0000@0x0(uboot),0x20000@0xa0000(env),0x300000@0x100000(zImage),0x300000@0x540000(initrd),0x1f400000@0x980000(boot)";
+ linux,initrd-start = <0x4500040>;
+ linux,initrd-end = <0x4800000>;
+ };
+
+ ocp@f1000000 {
+ serial@12000 {
+ clock-frequency = <200000000>;
+ status = "ok";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index 3474ef890945..926528b81baa 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -5,7 +5,7 @@
ocp@f1000000 {
compatible = "simple-bus";
- ranges = <0 0xf1000000 0x1000000>;
+ ranges = <0 0xf1000000 0x4000000>;
#address-cells = <1>;
#size-cells = <1>;
@@ -32,5 +32,18 @@
reg = <0x10300 0x20>;
interrupts = <53>;
};
+
+ nand@3000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ cle = <0>;
+ ale = <1>;
+ bank-width = <1>;
+ compatible = "mrvl,orion-nand";
+ reg = <0x3000000 0x400>;
+ chip-delay = <25>;
+ /* set partition map and/or chip-delay in board dts */
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/kizbox.dts b/arch/arm/boot/dts/kizbox.dts
new file mode 100644
index 000000000000..e8814fe0e277
--- /dev/null
+++ b/arch/arm/boot/dts/kizbox.dts
@@ -0,0 +1,138 @@
+/*
+ * kizbox.dts - Device Tree file for Overkiz Kizbox board
+ *
+ * Copyright (C) 2012 Boris BREZILLON <linux-arm@overkiz.com>
+ *
+ * Licensed under GPLv2.
+ */
+/dts-v1/;
+/include/ "at91sam9g20.dtsi"
+
+/ {
+
+ model = "Overkiz kizbox";
+ compatible = "overkiz,kizbox", "atmel,at91sam9g20", "atmel,at91sam9";
+
+ chosen {
+ bootargs = "panic=5 ubi.mtd=1 rootfstype=ubifs root=ubi0:root";
+ };
+
+ memory {
+ reg = <0x20000000 0x2000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ main_clock: clock@0 {
+ compatible = "atmel,osc", "fixed-clock";
+ clock-frequency = <18432000>;
+ };
+ };
+
+ ahb {
+ apb {
+ dbgu: serial@fffff200 {
+ status = "okay";
+ };
+
+ usart0: serial@fffb0000 {
+ status = "okay";
+ };
+
+ usart1: serial@fffb4000 {
+ status = "okay";
+ };
+
+ macb0: ethernet@fffc4000 {
+ phy-mode = "mii";
+ status = "okay";
+ };
+
+ };
+
+ nand0: nand@40000000 {
+ nand-bus-width = <8>;
+ nand-ecc-mode = "soft";
+ status = "okay";
+
+ bootloaderkernel@0 {
+ label = "bootloader-kernel";
+ reg = <0x0 0xc0000>;
+ };
+
+ ubi@c0000 {
+ label = "ubi";
+ reg = <0xc0000 0x7f40000>;
+ };
+
+ };
+
+ usb0: ohci@00500000 {
+ num-ports = <1>;
+ status = "okay";
+ };
+ };
+
+ i2c@0 {
+ status = "okay";
+
+ pcf8563@51 {
+ /* nxp pcf8563 rtc */
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led1g {
+ label = "led1:green";
+ gpios = <&pioB 0 1>;
+ linux,default-trigger = "none";
+ };
+
+ led1r {
+ label = "led1:red";
+ gpios = <&pioB 1 1>;
+ linux,default-trigger = "none";
+ };
+
+ led2g {
+ label = "led2:green";
+ gpios = <&pioB 2 1>;
+ linux,default-trigger = "none";
+ default-state = "on";
+ };
+
+ led2r {
+ label = "led2:red";
+ gpios = <&pioB 3 1>;
+ linux,default-trigger = "none";
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reset {
+ label = "reset";
+ gpios = <&pioB 30 1>;
+ linux,code = <0x100>;
+ gpio-key,wakeup;
+ };
+
+ mode {
+ label = "mode";
+ gpios = <&pioB 31 1>;
+ linux,code = <0x101>;
+ gpio-key,wakeup;
+ };
+ };
+}; \ No newline at end of file
diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi
new file mode 100644
index 000000000000..2d696866f71c
--- /dev/null
+++ b/arch/arm/boot/dts/lpc32xx.dtsi
@@ -0,0 +1,292 @@
+/*
+ * NXP LPC32xx SoC
+ *
+ * Copyright 2012 Roland Stigge <stigge@antcom.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "nxp,lpc3220";
+ interrupt-parent = <&mic>;
+
+ cpus {
+ cpu@0 {
+ compatible = "arm,arm926ejs";
+ };
+ };
+
+ ahb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x20000000 0x20000000 0x30000000>;
+
+ /*
+ * Enable either SLC or MLC
+ */
+ slc: flash@20020000 {
+ compatible = "nxp,lpc3220-slc";
+ reg = <0x20020000 0x1000>;
+ status = "disable";
+ };
+
+ mlc: flash@200B0000 {
+ compatible = "nxp,lpc3220-mlc";
+ reg = <0x200B0000 0x1000>;
+ status = "disable";
+ };
+
+ dma@31000000 {
+ compatible = "arm,pl080", "arm,primecell";
+ reg = <0x31000000 0x1000>;
+ interrupts = <0x1c 0>;
+ };
+
+ /*
+ * Enable either ohci or usbd (gadget)!
+ */
+ ohci@31020000 {
+ compatible = "nxp,ohci-nxp", "usb-ohci";
+ reg = <0x31020000 0x300>;
+ interrupts = <0x3b 0>;
+ status = "disable";
+ };
+
+ usbd@31020000 {
+ compatible = "nxp,lpc3220-udc";
+ reg = <0x31020000 0x300>;
+ interrupts = <0x3d 0>, <0x3e 0>, <0x3c 0>, <0x3a 0>;
+ status = "disable";
+ };
+
+ clcd@31040000 {
+ compatible = "arm,pl110", "arm,primecell";
+ reg = <0x31040000 0x1000>;
+ interrupts = <0x0e 0>;
+ status = "disable";
+ };
+
+ mac: ethernet@31060000 {
+ compatible = "nxp,lpc-eth";
+ reg = <0x31060000 0x1000>;
+ interrupts = <0x1d 0>;
+ };
+
+ apb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x20000000 0x20000000 0x30000000>;
+
+ ssp0: ssp@20084000 {
+ compatible = "arm,pl022", "arm,primecell";
+ reg = <0x20084000 0x1000>;
+ interrupts = <0x14 0>;
+ };
+
+ spi1: spi@20088000 {
+ compatible = "nxp,lpc3220-spi";
+ reg = <0x20088000 0x1000>;
+ };
+
+ ssp1: ssp@2008c000 {
+ compatible = "arm,pl022", "arm,primecell";
+ reg = <0x2008c000 0x1000>;
+ interrupts = <0x15 0>;
+ };
+
+ spi2: spi@20090000 {
+ compatible = "nxp,lpc3220-spi";
+ reg = <0x20090000 0x1000>;
+ };
+
+ i2s0: i2s@20094000 {
+ compatible = "nxp,lpc3220-i2s";
+ reg = <0x20094000 0x1000>;
+ };
+
+ sd@20098000 {
+ compatible = "arm,pl180", "arm,primecell";
+ reg = <0x20098000 0x1000>;
+ interrupts = <0x0f 0>, <0x0d 0>;
+ };
+
+ i2s1: i2s@2009C000 {
+ compatible = "nxp,lpc3220-i2s";
+ reg = <0x2009C000 0x1000>;
+ };
+
+ uart3: serial@40080000 {
+ compatible = "nxp,serial";
+ reg = <0x40080000 0x1000>;
+ };
+
+ uart4: serial@40088000 {
+ compatible = "nxp,serial";
+ reg = <0x40088000 0x1000>;
+ };
+
+ uart5: serial@40090000 {
+ compatible = "nxp,serial";
+ reg = <0x40090000 0x1000>;
+ };
+
+ uart6: serial@40098000 {
+ compatible = "nxp,serial";
+ reg = <0x40098000 0x1000>;
+ };
+
+ i2c1: i2c@400A0000 {
+ compatible = "nxp,pnx-i2c";
+ reg = <0x400A0000 0x100>;
+ interrupts = <0x33 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pnx,timeout = <0x64>;
+ };
+
+ i2c2: i2c@400A8000 {
+ compatible = "nxp,pnx-i2c";
+ reg = <0x400A8000 0x100>;
+ interrupts = <0x32 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pnx,timeout = <0x64>;
+ };
+
+ i2cusb: i2c@31020300 {
+ compatible = "nxp,pnx-i2c";
+ reg = <0x31020300 0x100>;
+ interrupts = <0x3f 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pnx,timeout = <0x64>;
+ };
+ };
+
+ fab {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x20000000 0x20000000 0x30000000>;
+
+ /*
+ * MIC Interrupt controller includes:
+ * MIC @40008000
+ * SIC1 @4000C000
+ * SIC2 @40010000
+ */
+ mic: interrupt-controller@40008000 {
+ compatible = "nxp,lpc3220-mic";
+ interrupt-controller;
+ reg = <0x40008000 0xC000>;
+ #interrupt-cells = <2>;
+ };
+
+ uart1: serial@40014000 {
+ compatible = "nxp,serial";
+ reg = <0x40014000 0x1000>;
+ };
+
+ uart2: serial@40018000 {
+ compatible = "nxp,serial";
+ reg = <0x40018000 0x1000>;
+ };
+
+ uart7: serial@4001C000 {
+ compatible = "nxp,serial";
+ reg = <0x4001C000 0x1000>;
+ };
+
+ rtc@40024000 {
+ compatible = "nxp,lpc3220-rtc";
+ reg = <0x40024000 0x1000>;
+ interrupts = <0x34 0>;
+ };
+
+ gpio: gpio@40028000 {
+ compatible = "nxp,lpc3220-gpio";
+ reg = <0x40028000 0x1000>;
+ /* create a private address space for enumeration */
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio_p0: gpio-bank@0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0>;
+ };
+
+ gpio_p1: gpio-bank@1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <1>;
+ };
+
+ gpio_p2: gpio-bank@2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <2>;
+ };
+
+ gpio_p3: gpio-bank@3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <3>;
+ };
+
+ gpi_p3: gpio-bank@4 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <4>;
+ };
+
+ gpo_p3: gpio-bank@5 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <5>;
+ };
+ };
+
+ watchdog@4003C000 {
+ compatible = "nxp,pnx4008-wdt";
+ reg = <0x4003C000 0x1000>;
+ };
+
+ /*
+ * TSC vs. ADC: Since those two share the same
+ * hardware, you need to choose from one of the
+ * following two and do 'status = "okay";' for one of
+ * them
+ */
+
+ adc@40048000 {
+ compatible = "nxp,lpc3220-adc";
+ reg = <0x40048000 0x1000>;
+ interrupts = <0x27 0>;
+ status = "disable";
+ };
+
+ tsc@40048000 {
+ compatible = "nxp,lpc3220-tsc";
+ reg = <0x40048000 0x1000>;
+ interrupts = <0x27 0>;
+ status = "disable";
+ };
+
+ key@40050000 {
+ compatible = "nxp,lpc3220-key";
+ reg = <0x40050000 0x1000>;
+ };
+
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/mmp2-brownstone.dts b/arch/arm/boot/dts/mmp2-brownstone.dts
new file mode 100644
index 000000000000..153a4b2d12b5
--- /dev/null
+++ b/arch/arm/boot/dts/mmp2-brownstone.dts
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 Marvell Technology Group Ltd.
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+/dts-v1/;
+/include/ "mmp2.dtsi"
+
+/ {
+ model = "Marvell MMP2 Aspenite Development Board";
+ compatible = "mrvl,mmp2-brownstone", "mrvl,mmp2";
+
+ chosen {
+ bootargs = "console=ttyS2,38400 root=/dev/nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on";
+ };
+
+ memory {
+ reg = <0x00000000 0x04000000>;
+ };
+
+ soc {
+ apb@d4000000 {
+ uart3: uart@d4018000 {
+ status = "okay";
+ };
+ twsi1: i2c@d4011000 {
+ status = "okay";
+ };
+ rtc: rtc@d4010000 {
+ status = "okay";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/mmp2.dtsi b/arch/arm/boot/dts/mmp2.dtsi
new file mode 100644
index 000000000000..80f74e256408
--- /dev/null
+++ b/arch/arm/boot/dts/mmp2.dtsi
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2012 Marvell Technology Group Ltd.
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ aliases {
+ serial0 = &uart1;
+ serial1 = &uart2;
+ serial2 = &uart3;
+ serial3 = &uart4;
+ i2c0 = &twsi1;
+ i2c1 = &twsi2;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&intc>;
+ ranges;
+
+ axi@d4200000 { /* AXI */
+ compatible = "mrvl,axi-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xd4200000 0x00200000>;
+ ranges;
+
+ intc: interrupt-controller@d4282000 {
+ compatible = "mrvl,mmp2-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0xd4282000 0x1000>;
+ mrvl,intc-nr-irqs = <64>;
+ };
+
+ intcmux4@d4282150 {
+ compatible = "mrvl,mmp2-mux-intc";
+ interrupts = <4>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x150 0x4>, <0x168 0x4>;
+ reg-names = "mux status", "mux mask";
+ mrvl,intc-nr-irqs = <2>;
+ };
+
+ intcmux5: interrupt-controller@d4282154 {
+ compatible = "mrvl,mmp2-mux-intc";
+ interrupts = <5>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x154 0x4>, <0x16c 0x4>;
+ reg-names = "mux status", "mux mask";
+ mrvl,intc-nr-irqs = <2>;
+ mrvl,clr-mfp-irq = <1>;
+ };
+
+ intcmux9: interrupt-controller@d4282180 {
+ compatible = "mrvl,mmp2-mux-intc";
+ interrupts = <9>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x180 0x4>, <0x17c 0x4>;
+ reg-names = "mux status", "mux mask";
+ mrvl,intc-nr-irqs = <3>;
+ };
+
+ intcmux17: interrupt-controller@d4282158 {
+ compatible = "mrvl,mmp2-mux-intc";
+ interrupts = <17>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x158 0x4>, <0x170 0x4>;
+ reg-names = "mux status", "mux mask";
+ mrvl,intc-nr-irqs = <5>;
+ };
+
+ intcmux35: interrupt-controller@d428215c {
+ compatible = "mrvl,mmp2-mux-intc";
+ interrupts = <35>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x15c 0x4>, <0x174 0x4>;
+ reg-names = "mux status", "mux mask";
+ mrvl,intc-nr-irqs = <15>;
+ };
+
+ intcmux51: interrupt-controller@d4282160 {
+ compatible = "mrvl,mmp2-mux-intc";
+ interrupts = <51>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x160 0x4>, <0x178 0x4>;
+ reg-names = "mux status", "mux mask";
+ mrvl,intc-nr-irqs = <2>;
+ };
+
+ intcmux55: interrupt-controller@d4282188 {
+ compatible = "mrvl,mmp2-mux-intc";
+ interrupts = <55>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x188 0x4>, <0x184 0x4>;
+ reg-names = "mux status", "mux mask";
+ mrvl,intc-nr-irqs = <2>;
+ };
+ };
+
+ apb@d4000000 { /* APB */
+ compatible = "mrvl,apb-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xd4000000 0x00200000>;
+ ranges;
+
+ timer0: timer@d4014000 {
+ compatible = "mrvl,mmp-timer";
+ reg = <0xd4014000 0x100>;
+ interrupts = <13>;
+ };
+
+ uart1: uart@d4030000 {
+ compatible = "mrvl,mmp-uart";
+ reg = <0xd4030000 0x1000>;
+ interrupts = <27>;
+ status = "disabled";
+ };
+
+ uart2: uart@d4017000 {
+ compatible = "mrvl,mmp-uart";
+ reg = <0xd4017000 0x1000>;
+ interrupts = <28>;
+ status = "disabled";
+ };
+
+ uart3: uart@d4018000 {
+ compatible = "mrvl,mmp-uart";
+ reg = <0xd4018000 0x1000>;
+ interrupts = <24>;
+ status = "disabled";
+ };
+
+ uart4: uart@d4016000 {
+ compatible = "mrvl,mmp-uart";
+ reg = <0xd4016000 0x1000>;
+ interrupts = <46>;
+ status = "disabled";
+ };
+
+ gpio@d4019000 {
+ compatible = "mrvl,mmp-gpio";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xd4019000 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <49>;
+ interrupt-names = "gpio_mux";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ ranges;
+
+ gcb0: gpio@d4019000 {
+ reg = <0xd4019000 0x4>;
+ };
+
+ gcb1: gpio@d4019004 {
+ reg = <0xd4019004 0x4>;
+ };
+
+ gcb2: gpio@d4019008 {
+ reg = <0xd4019008 0x4>;
+ };
+
+ gcb3: gpio@d4019100 {
+ reg = <0xd4019100 0x4>;
+ };
+
+ gcb4: gpio@d4019104 {
+ reg = <0xd4019104 0x4>;
+ };
+
+ gcb5: gpio@d4019108 {
+ reg = <0xd4019108 0x4>;
+ };
+ };
+
+ twsi1: i2c@d4011000 {
+ compatible = "mrvl,mmp-twsi";
+ reg = <0xd4011000 0x1000>;
+ interrupts = <7>;
+ mrvl,i2c-fast-mode;
+ status = "disabled";
+ };
+
+ twsi2: i2c@d4025000 {
+ compatible = "mrvl,mmp-twsi";
+ reg = <0xd4025000 0x1000>;
+ interrupts = <58>;
+ status = "disabled";
+ };
+
+ rtc: rtc@d4010000 {
+ compatible = "mrvl,mmp-rtc";
+ reg = <0xd4010000 0x1000>;
+ interrupts = <1 0>;
+ interrupt-names = "rtc 1Hz", "rtc alarm";
+ interrupt-parent = <&intcmux5>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts
index 9f72cd4cf308..8c756be4d7ad 100644
--- a/arch/arm/boot/dts/omap3-beagle.dts
+++ b/arch/arm/boot/dts/omap3-beagle.dts
@@ -18,3 +18,52 @@
reg = <0x80000000 0x20000000>; /* 512 MB */
};
};
+
+&i2c1 {
+ clock-frequency = <2600000>;
+
+ twl: twl@48 {
+ reg = <0x48>;
+ interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+ interrupt-parent = <&intc>;
+
+ vsim: regulator@10 {
+ compatible = "ti,twl4030-vsim";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ };
+ };
+};
+
+/include/ "twl4030.dtsi"
+
+&i2c2 {
+ clock-frequency = <400000>;
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+
+ /*
+ * Display monitor features are burnt in the EEPROM
+ * as EDID data.
+ */
+ eeprom@50 {
+ compatible = "ti,eeprom";
+ reg = <0x50>;
+ };
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmc1>;
+ vmmc_aux-supply = <&vsim>;
+ ti,bus-width = <8>;
+};
+
+&mmc2 {
+ status = "disable";
+};
+
+&mmc3 {
+ status = "disable";
+};
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index c6121357c1eb..99474fa5fac4 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -69,6 +69,60 @@
reg = <0x48200000 0x1000>;
};
+ gpio1: gpio@48310000 {
+ compatible = "ti,omap3-gpio";
+ ti,hwmods = "gpio1";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio2: gpio@49050000 {
+ compatible = "ti,omap3-gpio";
+ ti,hwmods = "gpio2";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio3: gpio@49052000 {
+ compatible = "ti,omap3-gpio";
+ ti,hwmods = "gpio3";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio4: gpio@49054000 {
+ compatible = "ti,omap3-gpio";
+ ti,hwmods = "gpio4";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio5: gpio@49056000 {
+ compatible = "ti,omap3-gpio";
+ ti,hwmods = "gpio5";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio6: gpio@49058000 {
+ compatible = "ti,omap3-gpio";
+ ti,hwmods = "gpio6";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
uart1: serial@4806a000 {
compatible = "ti,omap3-uart";
ti,hwmods = "uart1";
@@ -113,5 +167,53 @@
#size-cells = <0>;
ti,hwmods = "i2c3";
};
+
+ mcspi1: spi@48098000 {
+ compatible = "ti,omap2-mcspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ ti,hwmods = "mcspi1";
+ ti,spi-num-cs = <4>;
+ };
+
+ mcspi2: spi@4809a000 {
+ compatible = "ti,omap2-mcspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ ti,hwmods = "mcspi2";
+ ti,spi-num-cs = <2>;
+ };
+
+ mcspi3: spi@480b8000 {
+ compatible = "ti,omap2-mcspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ ti,hwmods = "mcspi3";
+ ti,spi-num-cs = <2>;
+ };
+
+ mcspi4: spi@480ba000 {
+ compatible = "ti,omap2-mcspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ ti,hwmods = "mcspi4";
+ ti,spi-num-cs = <1>;
+ };
+
+ mmc1: mmc@4809c000 {
+ compatible = "ti,omap3-hsmmc";
+ ti,hwmods = "mmc1";
+ ti,dual-volt;
+ };
+
+ mmc2: mmc@480b4000 {
+ compatible = "ti,omap3-hsmmc";
+ ti,hwmods = "mmc2";
+ };
+
+ mmc3: mmc@480ad000 {
+ compatible = "ti,omap3-hsmmc";
+ ti,hwmods = "mmc3";
+ };
};
};
diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts
index 9755ad5917f8..e671361bc791 100644
--- a/arch/arm/boot/dts/omap4-panda.dts
+++ b/arch/arm/boot/dts/omap4-panda.dts
@@ -17,4 +17,75 @@
device_type = "memory";
reg = <0x80000000 0x40000000>; /* 1 GB */
};
+
+ leds {
+ compatible = "gpio-leds";
+ heartbeat {
+ label = "pandaboard::status1";
+ gpios = <&gpio1 7 0>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ mmc {
+ label = "pandaboard::status2";
+ gpios = <&gpio1 8 0>;
+ linux,default-trigger = "mmc0";
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <400000>;
+
+ twl: twl@48 {
+ reg = <0x48>;
+ /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */
+ interrupts = <0 7 4>; /* IRQ_SYS_1N cascaded to gic */
+ interrupt-parent = <&gic>;
+ };
+};
+
+/include/ "twl6030.dtsi"
+
+&i2c2 {
+ clock-frequency = <400000>;
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+
+ /*
+ * Display monitor features are burnt in their EEPROM as EDID data.
+ * The EEPROM is connected as I2C slave device.
+ */
+ eeprom@50 {
+ compatible = "ti,eeprom";
+ reg = <0x50>;
+ };
+};
+
+&i2c4 {
+ clock-frequency = <400000>;
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmc>;
+ ti,bus-width = <8>;
+};
+
+&mmc2 {
+ status = "disable";
+};
+
+&mmc3 {
+ status = "disable";
+};
+
+&mmc4 {
+ status = "disable";
+};
+
+&mmc5 {
+ ti,non-removable;
+ ti,bus-width = <4>;
};
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
index 63c6b2b2bf42..e5eeb6f9c6e6 100644
--- a/arch/arm/boot/dts/omap4-sdp.dts
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -17,4 +17,144 @@
device_type = "memory";
reg = <0x80000000 0x40000000>; /* 1 GB */
};
+
+ vdd_eth: fixedregulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDD_ETH";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 16 0>; /* gpio line 48 */
+ enable-active-high;
+ regulator-boot-on;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ debug0 {
+ label = "omap4:green:debug0";
+ gpios = <&gpio2 29 0>; /* 61 */
+ };
+
+ debug1 {
+ label = "omap4:green:debug1";
+ gpios = <&gpio1 30 0>; /* 30 */
+ };
+
+ debug2 {
+ label = "omap4:green:debug2";
+ gpios = <&gpio1 7 0>; /* 7 */
+ };
+
+ debug3 {
+ label = "omap4:green:debug3";
+ gpios = <&gpio1 8 0>; /* 8 */
+ };
+
+ debug4 {
+ label = "omap4:green:debug4";
+ gpios = <&gpio2 18 0>; /* 50 */
+ };
+
+ user1 {
+ label = "omap4:blue:user";
+ gpios = <&gpio6 9 0>; /* 169 */
+ };
+
+ user2 {
+ label = "omap4:red:user";
+ gpios = <&gpio6 10 0>; /* 170 */
+ };
+
+ user3 {
+ label = "omap4:green:user";
+ gpios = <&gpio5 11 0>; /* 139 */
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <400000>;
+
+ twl: twl@48 {
+ reg = <0x48>;
+ /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */
+ interrupts = <0 7 4>; /* IRQ_SYS_1N cascaded to gic */
+ interrupt-parent = <&gic>;
+ };
+};
+
+/include/ "twl6030.dtsi"
+
+&i2c2 {
+ clock-frequency = <400000>;
+};
+
+&i2c3 {
+ clock-frequency = <400000>;
+
+ /*
+ * Temperature Sensor
+ * http://www.ti.com/lit/ds/symlink/tmp105.pdf
+ */
+ tmp105@48 {
+ compatible = "ti,tmp105";
+ reg = <0x48>;
+ };
+
+ /*
+ * Ambient Light Sensor
+ * http://www.rohm.com/products/databook/sensor/pdf/bh1780gli-e.pdf
+ */
+ bh1780@29 {
+ compatible = "rohm,bh1780";
+ reg = <0x29>;
+ };
+};
+
+&i2c4 {
+ clock-frequency = <400000>;
+
+ /*
+ * 3-Axis Digital Compass
+ * http://www.sparkfun.com/datasheets/Sensors/Magneto/HMC5843.pdf
+ */
+ hmc5843@1e {
+ compatible = "honeywell,hmc5843";
+ reg = <0x1e>;
+ };
+};
+
+&mcspi1 {
+ eth@0 {
+ compatible = "ks8851";
+ spi-max-frequency = <24000000>;
+ reg = <0>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <2>; /* gpio line 34 */
+ vdd-supply = <&vdd_eth>;
+ };
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmc>;
+ ti,bus-width = <8>;
+};
+
+&mmc2 {
+ vmmc-supply = <&vaux1>;
+ ti,bus-width = <8>;
+ ti,non-removable;
+};
+
+&mmc3 {
+ status = "disable";
+};
+
+&mmc4 {
+ status = "disable";
+};
+
+&mmc5 {
+ ti,bus-width = <4>;
+ ti,non-removable;
};
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 3d35559e77bc..359c4979c8aa 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -104,6 +104,60 @@
<0x48240100 0x0100>;
};
+ gpio1: gpio@4a310000 {
+ compatible = "ti,omap4-gpio";
+ ti,hwmods = "gpio1";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio2: gpio@48055000 {
+ compatible = "ti,omap4-gpio";
+ ti,hwmods = "gpio2";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio3: gpio@48057000 {
+ compatible = "ti,omap4-gpio";
+ ti,hwmods = "gpio3";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio4: gpio@48059000 {
+ compatible = "ti,omap4-gpio";
+ ti,hwmods = "gpio4";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio5: gpio@4805b000 {
+ compatible = "ti,omap4-gpio";
+ ti,hwmods = "gpio5";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio6: gpio@4805d000 {
+ compatible = "ti,omap4-gpio";
+ ti,hwmods = "gpio6";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
uart1: serial@4806a000 {
compatible = "ti,omap4-uart";
ti,hwmods = "uart1";
@@ -155,5 +209,68 @@
#size-cells = <0>;
ti,hwmods = "i2c4";
};
+
+ mcspi1: spi@48098000 {
+ compatible = "ti,omap4-mcspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ ti,hwmods = "mcspi1";
+ ti,spi-num-cs = <4>;
+ };
+
+ mcspi2: spi@4809a000 {
+ compatible = "ti,omap4-mcspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ ti,hwmods = "mcspi2";
+ ti,spi-num-cs = <2>;
+ };
+
+ mcspi3: spi@480b8000 {
+ compatible = "ti,omap4-mcspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ ti,hwmods = "mcspi3";
+ ti,spi-num-cs = <2>;
+ };
+
+ mcspi4: spi@480ba000 {
+ compatible = "ti,omap4-mcspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ ti,hwmods = "mcspi4";
+ ti,spi-num-cs = <1>;
+ };
+
+ mmc1: mmc@4809c000 {
+ compatible = "ti,omap4-hsmmc";
+ ti,hwmods = "mmc1";
+ ti,dual-volt;
+ ti,needs-special-reset;
+ };
+
+ mmc2: mmc@480b4000 {
+ compatible = "ti,omap4-hsmmc";
+ ti,hwmods = "mmc2";
+ ti,needs-special-reset;
+ };
+
+ mmc3: mmc@480ad000 {
+ compatible = "ti,omap4-hsmmc";
+ ti,hwmods = "mmc3";
+ ti,needs-special-reset;
+ };
+
+ mmc4: mmc@480d1000 {
+ compatible = "ti,omap4-hsmmc";
+ ti,hwmods = "mmc4";
+ ti,needs-special-reset;
+ };
+
+ mmc5: mmc@480d5000 {
+ compatible = "ti,omap4-hsmmc";
+ ti,hwmods = "mmc5";
+ ti,needs-special-reset;
+ };
};
};
diff --git a/arch/arm/boot/dts/phy3250.dts b/arch/arm/boot/dts/phy3250.dts
new file mode 100644
index 000000000000..0167e86314c0
--- /dev/null
+++ b/arch/arm/boot/dts/phy3250.dts
@@ -0,0 +1,145 @@
+/*
+ * PHYTEC phyCORE-LPC3250 board
+ *
+ * Copyright 2012 Roland Stigge <stigge@antcom.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "lpc32xx.dtsi"
+
+/ {
+ model = "PHYTEC phyCORE-LPC3250 board based on NXP LPC3250";
+ compatible = "phytec,phy3250", "nxp,lpc3250";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory {
+ device_type = "memory";
+ reg = <0 0x4000000>;
+ };
+
+ ahb {
+ mac: ethernet@31060000 {
+ phy-mode = "rmii";
+ use-iram;
+ };
+
+ /* Here, choose exactly one from: ohci, usbd */
+ ohci@31020000 {
+ transceiver = <&isp1301>;
+ status = "okay";
+ };
+
+/*
+ usbd@31020000 {
+ transceiver = <&isp1301>;
+ status = "okay";
+ };
+*/
+
+ clcd@31040000 {
+ status = "okay";
+ };
+
+ /* 64MB Flash via SLC NAND controller */
+ slc: flash@20020000 {
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ mtd0@00000000 {
+ label = "phy3250-boot";
+ reg = <0x00000000 0x00064000>;
+ read-only;
+ };
+
+ mtd1@00064000 {
+ label = "phy3250-uboot";
+ reg = <0x00064000 0x00190000>;
+ read-only;
+ };
+
+ mtd2@001f4000 {
+ label = "phy3250-ubt-prms";
+ reg = <0x001f4000 0x00010000>;
+ };
+
+ mtd3@00204000 {
+ label = "phy3250-kernel";
+ reg = <0x00204000 0x00400000>;
+ };
+
+ mtd4@00604000 {
+ label = "phy3250-rootfs";
+ reg = <0x00604000 0x039fc000>;
+ };
+ };
+
+ apb {
+ i2c1: i2c@400A0000 {
+ clock-frequency = <100000>;
+
+ pcf8563: rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+
+ uda1380: uda1380@18 {
+ compatible = "nxp,uda1380";
+ reg = <0x18>;
+ power-gpio = <&gpio 0x59 0>;
+ reset-gpio = <&gpio 0x51 0>;
+ dac-clk = "wspll";
+ };
+ };
+
+ i2c2: i2c@400A8000 {
+ clock-frequency = <100000>;
+ };
+
+ i2cusb: i2c@31020300 {
+ clock-frequency = <100000>;
+
+ isp1301: usb-transceiver@2c {
+ compatible = "nxp,isp1301";
+ reg = <0x2c>;
+ };
+ };
+
+ ssp0: ssp@20084000 {
+ eeprom: at25@0 {
+ compatible = "atmel,at25";
+ };
+ };
+ };
+
+ fab {
+ tsc@40048000 {
+ status = "okay";
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led0 {
+ gpios = <&gpo_p3 1 1>; /* GPO_P3 1, GPIO 80, active low */
+ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+
+ led1 {
+ gpios = <&gpo_p3 14 1>; /* GPO_P3 14, GPIO 93, active low */
+ linux,default-trigger = "timer";
+ default-state = "off";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/pxa168.dtsi b/arch/arm/boot/dts/pxa168.dtsi
index d32d5128f225..31a718696080 100644
--- a/arch/arm/boot/dts/pxa168.dtsi
+++ b/arch/arm/boot/dts/pxa168.dtsi
@@ -18,13 +18,6 @@
i2c1 = &twsi2;
};
- intc: intc-interrupt-controller@d4282000 {
- compatible = "mrvl,mmp-intc", "mrvl,intc";
- interrupt-controller;
- #interrupt-cells = <1>;
- reg = <0xd4282000 0x1000>;
- };
-
soc {
#address-cells = <1>;
#size-cells = <1>;
@@ -32,6 +25,23 @@
interrupt-parent = <&intc>;
ranges;
+ axi@d4200000 { /* AXI */
+ compatible = "mrvl,axi-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xd4200000 0x00200000>;
+ ranges;
+
+ intc: interrupt-controller@d4282000 {
+ compatible = "mrvl,mmp-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0xd4282000 0x1000>;
+ mrvl,intc-nr-irqs = <64>;
+ };
+
+ };
+
apb@d4000000 { /* APB */
compatible = "mrvl,apb-bus", "simple-bus";
#address-cells = <1>;
@@ -39,40 +49,65 @@
reg = <0xd4000000 0x00200000>;
ranges;
+ timer0: timer@d4014000 {
+ compatible = "mrvl,mmp-timer";
+ reg = <0xd4014000 0x100>;
+ interrupts = <13>;
+ };
+
uart1: uart@d4017000 {
- compatible = "mrvl,mmp-uart", "mrvl,pxa-uart";
+ compatible = "mrvl,mmp-uart";
reg = <0xd4017000 0x1000>;
interrupts = <27>;
status = "disabled";
};
uart2: uart@d4018000 {
- compatible = "mrvl,mmp-uart", "mrvl,pxa-uart";
+ compatible = "mrvl,mmp-uart";
reg = <0xd4018000 0x1000>;
interrupts = <28>;
status = "disabled";
};
uart3: uart@d4026000 {
- compatible = "mrvl,mmp-uart", "mrvl,pxa-uart";
+ compatible = "mrvl,mmp-uart";
reg = <0xd4026000 0x1000>;
interrupts = <29>;
status = "disabled";
};
- gpio: gpio@d4019000 {
- compatible = "mrvl,mmp-gpio", "mrvl,pxa-gpio";
+ gpio@d4019000 {
+ compatible = "mrvl,mmp-gpio";
+ #address-cells = <1>;
+ #size-cells = <1>;
reg = <0xd4019000 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
interrupts = <49>;
interrupt-names = "gpio_mux";
- gpio-controller;
- #gpio-cells = <1>;
interrupt-controller;
#interrupt-cells = <1>;
+ ranges;
+
+ gcb0: gpio@d4019000 {
+ reg = <0xd4019000 0x4>;
+ };
+
+ gcb1: gpio@d4019004 {
+ reg = <0xd4019004 0x4>;
+ };
+
+ gcb2: gpio@d4019008 {
+ reg = <0xd4019008 0x4>;
+ };
+
+ gcb3: gpio@d4019100 {
+ reg = <0xd4019100 0x4>;
+ };
};
twsi1: i2c@d4011000 {
- compatible = "mrvl,mmp-twsi", "mrvl,pxa-i2c";
+ compatible = "mrvl,mmp-twsi";
reg = <0xd4011000 0x1000>;
interrupts = <7>;
mrvl,i2c-fast-mode;
@@ -80,7 +115,7 @@
};
twsi2: i2c@d4025000 {
- compatible = "mrvl,mmp-twsi", "mrvl,pxa-i2c";
+ compatible = "mrvl,mmp-twsi";
reg = <0xd4025000 0x1000>;
interrupts = <58>;
status = "disabled";
diff --git a/arch/arm/boot/dts/pxa910-dkb.dts b/arch/arm/boot/dts/pxa910-dkb.dts
new file mode 100644
index 000000000000..e92be5a474e7
--- /dev/null
+++ b/arch/arm/boot/dts/pxa910-dkb.dts
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 Marvell Technology Group Ltd.
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+/dts-v1/;
+/include/ "pxa910.dtsi"
+
+/ {
+ model = "Marvell PXA910 DKB Development Board";
+ compatible = "mrvl,pxa910-dkb", "mrvl,pxa910";
+
+ chosen {
+ bootargs = "console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on";
+ };
+
+ memory {
+ reg = <0x00000000 0x10000000>;
+ };
+
+ soc {
+ apb@d4000000 {
+ uart1: uart@d4017000 {
+ status = "okay";
+ };
+ twsi1: i2c@d4011000 {
+ status = "okay";
+ };
+ rtc: rtc@d4010000 {
+ status = "okay";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/pxa910.dtsi b/arch/arm/boot/dts/pxa910.dtsi
new file mode 100644
index 000000000000..aebf32de73b4
--- /dev/null
+++ b/arch/arm/boot/dts/pxa910.dtsi
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2012 Marvell Technology Group Ltd.
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ aliases {
+ serial0 = &uart1;
+ serial1 = &uart2;
+ serial2 = &uart3;
+ i2c0 = &twsi1;
+ i2c1 = &twsi2;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&intc>;
+ ranges;
+
+ axi@d4200000 { /* AXI */
+ compatible = "mrvl,axi-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xd4200000 0x00200000>;
+ ranges;
+
+ intc: interrupt-controller@d4282000 {
+ compatible = "mrvl,mmp-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0xd4282000 0x1000>;
+ mrvl,intc-nr-irqs = <64>;
+ };
+
+ };
+
+ apb@d4000000 { /* APB */
+ compatible = "mrvl,apb-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xd4000000 0x00200000>;
+ ranges;
+
+ timer0: timer@d4014000 {
+ compatible = "mrvl,mmp-timer";
+ reg = <0xd4014000 0x100>;
+ interrupts = <13>;
+ };
+
+ timer1: timer@d4016000 {
+ compatible = "mrvl,mmp-timer";
+ reg = <0xd4016000 0x100>;
+ interrupts = <29>;
+ status = "disabled";
+ };
+
+ uart1: uart@d4017000 {
+ compatible = "mrvl,mmp-uart";
+ reg = <0xd4017000 0x1000>;
+ interrupts = <27>;
+ status = "disabled";
+ };
+
+ uart2: uart@d4018000 {
+ compatible = "mrvl,mmp-uart";
+ reg = <0xd4018000 0x1000>;
+ interrupts = <28>;
+ status = "disabled";
+ };
+
+ uart3: uart@d4036000 {
+ compatible = "mrvl,mmp-uart";
+ reg = <0xd4036000 0x1000>;
+ interrupts = <59>;
+ status = "disabled";
+ };
+
+ gpio@d4019000 {
+ compatible = "mrvl,mmp-gpio";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xd4019000 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <49>;
+ interrupt-names = "gpio_mux";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ ranges;
+
+ gcb0: gpio@d4019000 {
+ reg = <0xd4019000 0x4>;
+ };
+
+ gcb1: gpio@d4019004 {
+ reg = <0xd4019004 0x4>;
+ };
+
+ gcb2: gpio@d4019008 {
+ reg = <0xd4019008 0x4>;
+ };
+
+ gcb3: gpio@d4019100 {
+ reg = <0xd4019100 0x4>;
+ };
+ };
+
+ twsi1: i2c@d4011000 {
+ compatible = "mrvl,mmp-twsi";
+ reg = <0xd4011000 0x1000>;
+ interrupts = <7>;
+ mrvl,i2c-fast-mode;
+ status = "disabled";
+ };
+
+ twsi2: i2c@d4037000 {
+ compatible = "mrvl,mmp-twsi";
+ reg = <0xd4037000 0x1000>;
+ interrupts = <54>;
+ status = "disabled";
+ };
+
+ rtc: rtc@d4010000 {
+ compatible = "mrvl,mmp-rtc";
+ reg = <0xd4010000 0x1000>;
+ interrupts = <5 6>;
+ interrupt-names = "rtc 1Hz", "rtc alarm";
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
new file mode 100644
index 000000000000..a7505a95a3b7
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
@@ -0,0 +1,22 @@
+/*
+ * Device Tree Source for the armadillo 800 eva board
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "armadillo 800 eva";
+ compatible = "renesas,armadillo800eva";
+
+ memory {
+ device_type = "memory";
+ reg = <0x40000000 0x20000000>;
+ };
+};
diff --git a/arch/arm/boot/dts/sh7372.dtsi b/arch/arm/boot/dts/sh7372.dtsi
new file mode 100644
index 000000000000..677fc603f8b3
--- /dev/null
+++ b/arch/arm/boot/dts/sh7372.dtsi
@@ -0,0 +1,21 @@
+/*
+ * Device Tree Source for the sh7372 SoC
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "renesas,sh7372";
+
+ cpus {
+ cpu@0 {
+ compatible = "arm,cortex-a8";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/sh73a0-kzm9g.dts b/arch/arm/boot/dts/sh73a0-kzm9g.dts
new file mode 100644
index 000000000000..bcb911951978
--- /dev/null
+++ b/arch/arm/boot/dts/sh73a0-kzm9g.dts
@@ -0,0 +1,22 @@
+/*
+ * Device Tree Source for the KZM-A9-GT board
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "KZM-A9-GT";
+ compatible = "renesas,kzm9g", "renesas,sh73a0";
+
+ memory {
+ device_type = "memory";
+ reg = <0x41000000 0x1e800000>;
+ };
+};
diff --git a/arch/arm/boot/dts/snowball.dts b/arch/arm/boot/dts/snowball.dts
index 359c6d679156..d99dc04f0d91 100644
--- a/arch/arm/boot/dts/snowball.dts
+++ b/arch/arm/boot/dts/snowball.dts
@@ -30,35 +30,35 @@
wakeup = <1>;
linux,code = <2>;
label = "userpb";
- gpios = <&gpio1 0>;
+ gpios = <&gpio1 0 0>;
};
button@2 {
debounce_interval = <50>;
wakeup = <1>;
linux,code = <3>;
- label = "userpb";
- gpios = <&gpio4 23>;
+ label = "extkb1";
+ gpios = <&gpio4 23 0>;
};
button@3 {
debounce_interval = <50>;
wakeup = <1>;
linux,code = <4>;
- label = "userpb";
- gpios = <&gpio4 23>;
+ label = "extkb2";
+ gpios = <&gpio4 24 0>;
};
button@4 {
debounce_interval = <50>;
wakeup = <1>;
linux,code = <5>;
- label = "userpb";
- gpios = <&gpio5 1>;
+ label = "extkb3";
+ gpios = <&gpio5 1 0>;
};
button@5 {
debounce_interval = <50>;
wakeup = <1>;
linux,code = <6>;
- label = "userpb";
- gpios = <&gpio5 2>;
+ label = "extkb4";
+ gpios = <&gpio5 2 0>;
};
};
@@ -73,17 +73,19 @@
soc-u9500 {
external-bus@50000000 {
- compatible = "simple-bus";
- reg = <0x50000000 0x10000000>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
- ethernet@50000000 {
- compatible = "smsc,9111";
- reg = <0x50000000 0x10000>;
- interrupts = <12>;
+ status = "okay";
+
+ ethernet@0 {
+ compatible = "smsc,lan9115";
+ reg = <0 0x10000>;
+ interrupts = <12 0x1>;
interrupt-parent = <&gpio4>;
+
+ reg-shift = <1>;
+ reg-io-width = <2>;
+ smsc,force-internal-phy;
+ smsc,irq-active-high;
+ smsc,irq-push-pull;
};
};
diff --git a/arch/arm/boot/dts/spear300-evb.dts b/arch/arm/boot/dts/spear300-evb.dts
new file mode 100644
index 000000000000..910e264b87c0
--- /dev/null
+++ b/arch/arm/boot/dts/spear300-evb.dts
@@ -0,0 +1,221 @@
+/*
+ * DTS file for SPEAr300 Evaluation Baord
+ *
+ * Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "spear300.dtsi"
+
+/ {
+ model = "ST SPEAr300 Evaluation Board";
+ compatible = "st,spear300-evb", "st,spear300";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory {
+ reg = <0 0x40000000>;
+ };
+
+ ahb {
+ pinmux@99000000 {
+ st,pinmux-mode = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+
+ state_default: pinmux {
+ i2c0 {
+ st,pins = "i2c0_grp";
+ st,function = "i2c0";
+ };
+ ssp0 {
+ st,pins = "ssp0_grp";
+ st,function = "ssp0";
+ };
+ mii0 {
+ st,pins = "mii0_grp";
+ st,function = "mii0";
+ };
+ uart0 {
+ st,pins = "uart0_grp";
+ st,function = "uart0";
+ };
+ clcd {
+ st,pins = "clcd_pfmode_grp";
+ st,function = "clcd";
+ };
+ sdhci {
+ st,pins = "sdhci_4bit_grp";
+ st,function = "sdhci";
+ };
+ gpio1 {
+ st,pins = "gpio1_4_to_7_grp",
+ "gpio1_0_to_3_grp";
+ st,function = "gpio1";
+ };
+ };
+ };
+
+ clcd@60000000 {
+ status = "okay";
+ };
+
+ dma@fc400000 {
+ status = "okay";
+ };
+
+ fsmc: flash@94000000 {
+ status = "okay";
+ };
+
+ gmac: eth@e0800000 {
+ status = "okay";
+ };
+
+ sdhci@70000000 {
+ int-gpio = <&gpio1 0 0>;
+ power-gpio = <&gpio1 2 1>;
+ status = "okay";
+ };
+
+ smi: flash@fc000000 {
+ status = "okay";
+ };
+
+ spi0: spi@d0100000 {
+ status = "okay";
+ };
+
+ ehci@e1800000 {
+ status = "okay";
+ };
+
+ ohci@e1900000 {
+ status = "okay";
+ };
+
+ ohci@e2100000 {
+ status = "okay";
+ };
+
+ apb {
+ gpio0: gpio@fc980000 {
+ status = "okay";
+ };
+
+ gpio1: gpio@a9000000 {
+ status = "okay";
+ };
+
+ i2c0: i2c@d0180000 {
+ status = "okay";
+ };
+
+ kbd@a0000000 {
+ linux,keymap = < 0x00000001
+ 0x00010002
+ 0x00020003
+ 0x00030004
+ 0x00040005
+ 0x00050006
+ 0x00060007
+ 0x00070008
+ 0x00080009
+ 0x0100000a
+ 0x0101000c
+ 0x0102000d
+ 0x0103000e
+ 0x0104000f
+ 0x01050010
+ 0x01060011
+ 0x01070012
+ 0x01080013
+ 0x02000014
+ 0x02010015
+ 0x02020016
+ 0x02030017
+ 0x02040018
+ 0x02050019
+ 0x0206001a
+ 0x0207001b
+ 0x0208001c
+ 0x0300001d
+ 0x0301001e
+ 0x0302001f
+ 0x03030020
+ 0x03040021
+ 0x03050022
+ 0x03060023
+ 0x03070024
+ 0x03080025
+ 0x04000026
+ 0x04010027
+ 0x04020028
+ 0x04030029
+ 0x0404002a
+ 0x0405002b
+ 0x0406002c
+ 0x0407002d
+ 0x0408002e
+ 0x0500002f
+ 0x05010030
+ 0x05020031
+ 0x05030032
+ 0x05040033
+ 0x05050034
+ 0x05060035
+ 0x05070036
+ 0x05080037
+ 0x06000038
+ 0x06010039
+ 0x0602003a
+ 0x0603003b
+ 0x0604003c
+ 0x0605003d
+ 0x0606003e
+ 0x0607003f
+ 0x06080040
+ 0x07000041
+ 0x07010042
+ 0x07020043
+ 0x07030044
+ 0x07040045
+ 0x07050046
+ 0x07060047
+ 0x07070048
+ 0x07080049
+ 0x0800004a
+ 0x0801004b
+ 0x0802004c
+ 0x0803004d
+ 0x0804004e
+ 0x0805004f
+ 0x08060050
+ 0x08070051
+ 0x08080052 >;
+ autorepeat;
+ st,mode = <0>;
+ status = "okay";
+ };
+
+ rtc@fc900000 {
+ status = "okay";
+ };
+
+ serial@d0000000 {
+ status = "okay";
+ };
+
+ wdt@fc880000 {
+ status = "okay";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/spear300.dtsi b/arch/arm/boot/dts/spear300.dtsi
new file mode 100644
index 000000000000..01c5e358fdb2
--- /dev/null
+++ b/arch/arm/boot/dts/spear300.dtsi
@@ -0,0 +1,77 @@
+/*
+ * DTS file for SPEAr300 SoC
+ *
+ * Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "spear3xx.dtsi"
+
+/ {
+ ahb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x60000000 0x60000000 0x50000000
+ 0xd0000000 0xd0000000 0x30000000>;
+
+ pinmux@99000000 {
+ compatible = "st,spear300-pinmux";
+ reg = <0x99000000 0x1000>;
+ };
+
+ clcd@60000000 {
+ compatible = "arm,clcd-pl110", "arm,primecell";
+ reg = <0x60000000 0x1000>;
+ interrupts = <30>;
+ status = "disabled";
+ };
+
+ fsmc: flash@94000000 {
+ compatible = "st,spear600-fsmc-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x94000000 0x1000 /* FSMC Register */
+ 0x80000000 0x0010>; /* NAND Base */
+ reg-names = "fsmc_regs", "nand_data";
+ st,ale-off = <0x20000>;
+ st,cle-off = <0x10000>;
+ status = "disabled";
+ };
+
+ sdhci@70000000 {
+ compatible = "st,sdhci-spear";
+ reg = <0x70000000 0x100>;
+ interrupts = <1>;
+ status = "disabled";
+ };
+
+ apb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0xa0000000 0xa0000000 0x10000000
+ 0xd0000000 0xd0000000 0x30000000>;
+
+ gpio1: gpio@a9000000 {
+ #gpio-cells = <2>;
+ compatible = "arm,pl061", "arm,primecell";
+ gpio-controller;
+ reg = <0xa9000000 0x1000>;
+ status = "disabled";
+ };
+
+ kbd@a0000000 {
+ compatible = "st,spear300-kbd";
+ reg = <0xa0000000 0x1000>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/spear310-evb.dts b/arch/arm/boot/dts/spear310-evb.dts
new file mode 100644
index 000000000000..6d95317100ad
--- /dev/null
+++ b/arch/arm/boot/dts/spear310-evb.dts
@@ -0,0 +1,172 @@
+/*
+ * DTS file for SPEAr310 Evaluation Baord
+ *
+ * Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "spear310.dtsi"
+
+/ {
+ model = "ST SPEAr310 Evaluation Board";
+ compatible = "st,spear310-evb", "st,spear310";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory {
+ reg = <0 0x40000000>;
+ };
+
+ ahb {
+ pinmux@b4000000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+
+ state_default: pinmux {
+ gpio0 {
+ st,pins = "gpio0_pin0_grp",
+ "gpio0_pin1_grp",
+ "gpio0_pin2_grp",
+ "gpio0_pin3_grp",
+ "gpio0_pin4_grp",
+ "gpio0_pin5_grp";
+ st,function = "gpio0";
+ };
+ i2c0 {
+ st,pins = "i2c0_grp";
+ st,function = "i2c0";
+ };
+ mii0 {
+ st,pins = "mii0_grp";
+ st,function = "mii0";
+ };
+ ssp0 {
+ st,pins = "ssp0_grp";
+ st,function = "ssp0";
+ };
+ uart0 {
+ st,pins = "uart0_grp";
+ st,function = "uart0";
+ };
+ emi {
+ st,pins = "emi_cs_0_to_5_grp";
+ st,function = "emi";
+ };
+ fsmc {
+ st,pins = "fsmc_grp";
+ st,function = "fsmc";
+ };
+ uart1 {
+ st,pins = "uart1_grp";
+ st,function = "uart1";
+ };
+ uart2 {
+ st,pins = "uart2_grp";
+ st,function = "uart2";
+ };
+ uart3 {
+ st,pins = "uart3_grp";
+ st,function = "uart3";
+ };
+ uart4 {
+ st,pins = "uart4_grp";
+ st,function = "uart4";
+ };
+ uart5 {
+ st,pins = "uart5_grp";
+ st,function = "uart5";
+ };
+ };
+ };
+
+ dma@fc400000 {
+ status = "okay";
+ };
+
+ fsmc: flash@44000000 {
+ status = "okay";
+ };
+
+ gmac: eth@e0800000 {
+ status = "okay";
+ };
+
+ smi: flash@fc000000 {
+ status = "okay";
+ clock-rate=<50000000>;
+
+ flash@f8000000 {
+ label = "m25p64";
+ reg = <0xf8000000 0x800000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ st,smi-fast-mode;
+ };
+ };
+
+ spi0: spi@d0100000 {
+ status = "okay";
+ };
+
+ ehci@e1800000 {
+ status = "okay";
+ };
+
+ ohci@e1900000 {
+ status = "okay";
+ };
+
+ ohci@e2100000 {
+ status = "okay";
+ };
+
+ apb {
+ gpio0: gpio@fc980000 {
+ status = "okay";
+ };
+
+ i2c0: i2c@d0180000 {
+ status = "okay";
+ };
+
+ rtc@fc900000 {
+ status = "okay";
+ };
+
+ serial@d0000000 {
+ status = "okay";
+ };
+
+ serial@b2000000 {
+ status = "okay";
+ };
+
+ serial@b2080000 {
+ status = "okay";
+ };
+
+ serial@b2100000 {
+ status = "okay";
+ };
+
+ serial@b2180000 {
+ status = "okay";
+ };
+
+ serial@b2200000 {
+ status = "okay";
+ };
+
+ wdt@fc880000 {
+ status = "okay";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/spear310.dtsi
new file mode 100644
index 000000000000..e47081c494d9
--- /dev/null
+++ b/arch/arm/boot/dts/spear310.dtsi
@@ -0,0 +1,80 @@
+/*
+ * DTS file for SPEAr310 SoC
+ *
+ * Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "spear3xx.dtsi"
+
+/ {
+ ahb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x40000000 0x40000000 0x10000000
+ 0xb0000000 0xb0000000 0x10000000
+ 0xd0000000 0xd0000000 0x30000000>;
+
+ pinmux@b4000000 {
+ compatible = "st,spear310-pinmux";
+ reg = <0xb4000000 0x1000>;
+ };
+
+ fsmc: flash@44000000 {
+ compatible = "st,spear600-fsmc-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x44000000 0x1000 /* FSMC Register */
+ 0x40000000 0x0010>; /* NAND Base */
+ reg-names = "fsmc_regs", "nand_data";
+ st,ale-off = <0x10000>;
+ st,cle-off = <0x20000>;
+ status = "disabled";
+ };
+
+ apb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0xb0000000 0xb0000000 0x10000000
+ 0xd0000000 0xd0000000 0x30000000>;
+
+ serial@b2000000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xb2000000 0x1000>;
+ status = "disabled";
+ };
+
+ serial@b2080000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xb2080000 0x1000>;
+ status = "disabled";
+ };
+
+ serial@b2100000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xb2100000 0x1000>;
+ status = "disabled";
+ };
+
+ serial@b2180000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xb2180000 0x1000>;
+ status = "disabled";
+ };
+
+ serial@b2200000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xb2200000 0x1000>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/spear320-evb.dts b/arch/arm/boot/dts/spear320-evb.dts
new file mode 100644
index 000000000000..0c6463b71a37
--- /dev/null
+++ b/arch/arm/boot/dts/spear320-evb.dts
@@ -0,0 +1,173 @@
+/*
+ * DTS file for SPEAr320 Evaluation Baord
+ *
+ * Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "spear320.dtsi"
+
+/ {
+ model = "ST SPEAr300 Evaluation Board";
+ compatible = "st,spear300-evb", "st,spear300";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory {
+ reg = <0 0x40000000>;
+ };
+
+ ahb {
+ pinmux@b3000000 {
+ st,pinmux-mode = <3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+
+ state_default: pinmux {
+ i2c0 {
+ st,pins = "i2c0_grp";
+ st,function = "i2c0";
+ };
+ mii0 {
+ st,pins = "mii0_grp";
+ st,function = "mii0";
+ };
+ ssp0 {
+ st,pins = "ssp0_grp";
+ st,function = "ssp0";
+ };
+ uart0 {
+ st,pins = "uart0_grp";
+ st,function = "uart0";
+ };
+ sdhci {
+ st,pins = "sdhci_cd_51_grp";
+ st,function = "sdhci";
+ };
+ i2s {
+ st,pins = "i2s_grp";
+ st,function = "i2s";
+ };
+ uart1 {
+ st,pins = "uart1_grp";
+ st,function = "uart1";
+ };
+ uart2 {
+ st,pins = "uart2_grp";
+ st,function = "uart2";
+ };
+ can0 {
+ st,pins = "can0_grp";
+ st,function = "can0";
+ };
+ can1 {
+ st,pins = "can1_grp";
+ st,function = "can1";
+ };
+ mii2 {
+ st,pins = "mii2_grp";
+ st,function = "mii2";
+ };
+ pwm0_1 {
+ st,pins = "pwm0_1_pin_14_15_grp";
+ st,function = "pwm0_1";
+ };
+ pwm2 {
+ st,pins = "pwm2_pin_13_grp";
+ st,function = "pwm2";
+ };
+ };
+ };
+
+ clcd@90000000 {
+ status = "okay";
+ };
+
+ dma@fc400000 {
+ status = "okay";
+ };
+
+ fsmc: flash@4c000000 {
+ status = "okay";
+ };
+
+ gmac: eth@e0800000 {
+ status = "okay";
+ };
+
+ sdhci@70000000 {
+ power-gpio = <&gpio0 2 1>;
+ power_always_enb;
+ status = "okay";
+ };
+
+ smi: flash@fc000000 {
+ status = "okay";
+ };
+
+ spi0: spi@d0100000 {
+ status = "okay";
+ };
+
+ spi1: spi@a5000000 {
+ status = "okay";
+ };
+
+ spi2: spi@a6000000 {
+ status = "okay";
+ };
+
+ ehci@e1800000 {
+ status = "okay";
+ };
+
+ ohci@e1900000 {
+ status = "okay";
+ };
+
+ ohci@e2100000 {
+ status = "okay";
+ };
+
+ apb {
+ gpio0: gpio@fc980000 {
+ status = "okay";
+ };
+
+ i2c0: i2c@d0180000 {
+ status = "okay";
+ };
+
+ i2c1: i2c@a7000000 {
+ status = "okay";
+ };
+
+ rtc@fc900000 {
+ status = "okay";
+ };
+
+ serial@d0000000 {
+ status = "okay";
+ };
+
+ serial@a3000000 {
+ status = "okay";
+ };
+
+ serial@a4000000 {
+ status = "okay";
+ };
+
+ wdt@fc880000 {
+ status = "okay";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/spear320.dtsi
new file mode 100644
index 000000000000..5372ca399b1f
--- /dev/null
+++ b/arch/arm/boot/dts/spear320.dtsi
@@ -0,0 +1,95 @@
+/*
+ * DTS file for SPEAr320 SoC
+ *
+ * Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "spear3xx.dtsi"
+
+/ {
+ ahb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x40000000 0x40000000 0x80000000
+ 0xd0000000 0xd0000000 0x30000000>;
+
+ pinmux@b3000000 {
+ compatible = "st,spear320-pinmux";
+ reg = <0xb3000000 0x1000>;
+ };
+
+ clcd@90000000 {
+ compatible = "arm,clcd-pl110", "arm,primecell";
+ reg = <0x90000000 0x1000>;
+ interrupts = <33>;
+ status = "disabled";
+ };
+
+ fsmc: flash@4c000000 {
+ compatible = "st,spear600-fsmc-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x4c000000 0x1000 /* FSMC Register */
+ 0x50000000 0x0010>; /* NAND Base */
+ reg-names = "fsmc_regs", "nand_data";
+ st,ale-off = <0x20000>;
+ st,cle-off = <0x10000>;
+ status = "disabled";
+ };
+
+ sdhci@70000000 {
+ compatible = "st,sdhci-spear";
+ reg = <0x70000000 0x100>;
+ interrupts = <29>;
+ status = "disabled";
+ };
+
+ spi1: spi@a5000000 {
+ compatible = "arm,pl022", "arm,primecell";
+ reg = <0xa5000000 0x1000>;
+ status = "disabled";
+ };
+
+ spi2: spi@a6000000 {
+ compatible = "arm,pl022", "arm,primecell";
+ reg = <0xa6000000 0x1000>;
+ status = "disabled";
+ };
+
+ apb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0xa0000000 0xa0000000 0x10000000
+ 0xd0000000 0xd0000000 0x30000000>;
+
+ i2c1: i2c@a7000000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,designware-i2c";
+ reg = <0xa7000000 0x1000>;
+ status = "disabled";
+ };
+
+ serial@a3000000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xa3000000 0x1000>;
+ status = "disabled";
+ };
+
+ serial@a4000000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xa4000000 0x1000>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/spear3xx.dtsi b/arch/arm/boot/dts/spear3xx.dtsi
new file mode 100644
index 000000000000..0ae7c8e86311
--- /dev/null
+++ b/arch/arm/boot/dts/spear3xx.dtsi
@@ -0,0 +1,144 @@
+/*
+ * DTS file for all SPEAr3xx SoCs
+ *
+ * Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ interrupt-parent = <&vic>;
+
+ cpus {
+ cpu@0 {
+ compatible = "arm,arm926ejs";
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0 0x40000000>;
+ };
+
+ ahb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0xd0000000 0xd0000000 0x30000000>;
+
+ vic: interrupt-controller@f1100000 {
+ compatible = "arm,pl190-vic";
+ interrupt-controller;
+ reg = <0xf1100000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ dma@fc400000 {
+ compatible = "arm,pl080", "arm,primecell";
+ reg = <0xfc400000 0x1000>;
+ interrupt-parent = <&vic>;
+ interrupts = <8>;
+ status = "disabled";
+ };
+
+ gmac: eth@e0800000 {
+ compatible = "st,spear600-gmac";
+ reg = <0xe0800000 0x8000>;
+ interrupts = <23 22>;
+ interrupt-names = "macirq", "eth_wake_irq";
+ status = "disabled";
+ };
+
+ smi: flash@fc000000 {
+ compatible = "st,spear600-smi";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xfc000000 0x1000>;
+ interrupts = <9>;
+ status = "disabled";
+ };
+
+ spi0: spi@d0100000 {
+ compatible = "arm,pl022", "arm,primecell";
+ reg = <0xd0100000 0x1000>;
+ interrupts = <20>;
+ status = "disabled";
+ };
+
+ ehci@e1800000 {
+ compatible = "st,spear600-ehci", "usb-ehci";
+ reg = <0xe1800000 0x1000>;
+ interrupts = <26>;
+ status = "disabled";
+ };
+
+ ohci@e1900000 {
+ compatible = "st,spear600-ohci", "usb-ohci";
+ reg = <0xe1900000 0x1000>;
+ interrupts = <25>;
+ status = "disabled";
+ };
+
+ ohci@e2100000 {
+ compatible = "st,spear600-ohci", "usb-ohci";
+ reg = <0xe2100000 0x1000>;
+ interrupts = <27>;
+ status = "disabled";
+ };
+
+ apb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0xd0000000 0xd0000000 0x30000000>;
+
+ gpio0: gpio@fc980000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc980000 0x1000>;
+ interrupts = <11>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ status = "disabled";
+ };
+
+ i2c0: i2c@d0180000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,designware-i2c";
+ reg = <0xd0180000 0x1000>;
+ interrupts = <21>;
+ status = "disabled";
+ };
+
+ rtc@fc900000 {
+ compatible = "st,spear-rtc";
+ reg = <0xfc900000 0x1000>;
+ interrupts = <10>;
+ status = "disabled";
+ };
+
+ serial@d0000000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xd0000000 0x1000>;
+ interrupts = <19>;
+ status = "disabled";
+ };
+
+ wdt@fc880000 {
+ compatible = "arm,sp805", "arm,primecell";
+ reg = <0xfc880000 0x1000>;
+ interrupts = <12>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/spear600-evb.dts b/arch/arm/boot/dts/spear600-evb.dts
index 636292e18c90..790a7a8a5ccd 100644
--- a/arch/arm/boot/dts/spear600-evb.dts
+++ b/arch/arm/boot/dts/spear600-evb.dts
@@ -24,6 +24,10 @@
};
ahb {
+ dma@fc400000 {
+ status = "okay";
+ };
+
gmac: ethernet@e0800000 {
phy-mode = "gmii";
status = "okay";
diff --git a/arch/arm/boot/dts/spear600.dtsi b/arch/arm/boot/dts/spear600.dtsi
index ebe0885a2b98..d777e3a6f178 100644
--- a/arch/arm/boot/dts/spear600.dtsi
+++ b/arch/arm/boot/dts/spear600.dtsi
@@ -45,6 +45,14 @@
#interrupt-cells = <1>;
};
+ dma@fc400000 {
+ compatible = "arm,pl080", "arm,primecell";
+ reg = <0xfc400000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <10>;
+ status = "disabled";
+ };
+
gmac: ethernet@e0800000 {
compatible = "st,spear600-gmac";
reg = <0xe0800000 0x8000>;
diff --git a/arch/arm/boot/dts/tegra-cardhu.dts b/arch/arm/boot/dts/tegra-cardhu.dts
index ac3fb7558459..0a9f34a2c3aa 100644
--- a/arch/arm/boot/dts/tegra-cardhu.dts
+++ b/arch/arm/boot/dts/tegra-cardhu.dts
@@ -10,6 +10,50 @@
reg = < 0x80000000 0x40000000 >;
};
+ pinmux@70000000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+
+ state_default: pinmux {
+ sdmmc1_clk_pz0 {
+ nvidia,pins = "sdmmc1_clk_pz0";
+ nvidia,function = "sdmmc1";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
+ sdmmc1_cmd_pz1 {
+ nvidia,pins = "sdmmc1_cmd_pz1",
+ "sdmmc1_dat0_py7",
+ "sdmmc1_dat1_py6",
+ "sdmmc1_dat2_py5",
+ "sdmmc1_dat3_py4";
+ nvidia,function = "sdmmc1";
+ nvidia,pull = <2>;
+ nvidia,tristate = <0>;
+ };
+ sdmmc4_clk_pcc4 {
+ nvidia,pins = "sdmmc4_clk_pcc4",
+ "sdmmc4_rst_n_pcc3";
+ nvidia,function = "sdmmc4";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
+ sdmmc4_dat0_paa0 {
+ nvidia,pins = "sdmmc4_dat0_paa0",
+ "sdmmc4_dat1_paa1",
+ "sdmmc4_dat2_paa2",
+ "sdmmc4_dat3_paa3",
+ "sdmmc4_dat4_paa4",
+ "sdmmc4_dat5_paa5",
+ "sdmmc4_dat6_paa6",
+ "sdmmc4_dat7_paa7";
+ nvidia,function = "sdmmc4";
+ nvidia,pull = <2>;
+ nvidia,tristate = <0>;
+ };
+ };
+ };
+
serial@70006000 {
clock-frequency = < 408000000 >;
};
diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts
index 6e8447dc0202..1a0b1f182944 100644
--- a/arch/arm/boot/dts/tegra-harmony.dts
+++ b/arch/arm/boot/dts/tegra-harmony.dts
@@ -10,6 +10,230 @@
reg = < 0x00000000 0x40000000 >;
};
+ pinmux@70000000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+
+ state_default: pinmux {
+ ata {
+ nvidia,pins = "ata";
+ nvidia,function = "ide";
+ };
+ atb {
+ nvidia,pins = "atb", "gma", "gme";
+ nvidia,function = "sdio4";
+ };
+ atc {
+ nvidia,pins = "atc";
+ nvidia,function = "nand";
+ };
+ atd {
+ nvidia,pins = "atd", "ate", "gmb", "gmd", "gpu",
+ "spia", "spib", "spic";
+ nvidia,function = "gmi";
+ };
+ cdev1 {
+ nvidia,pins = "cdev1";
+ nvidia,function = "plla_out";
+ };
+ cdev2 {
+ nvidia,pins = "cdev2";
+ nvidia,function = "pllp_out4";
+ };
+ crtp {
+ nvidia,pins = "crtp";
+ nvidia,function = "crt";
+ };
+ csus {
+ nvidia,pins = "csus";
+ nvidia,function = "vi_sensor_clk";
+ };
+ dap1 {
+ nvidia,pins = "dap1";
+ nvidia,function = "dap1";
+ };
+ dap2 {
+ nvidia,pins = "dap2";
+ nvidia,function = "dap2";
+ };
+ dap3 {
+ nvidia,pins = "dap3";
+ nvidia,function = "dap3";
+ };
+ dap4 {
+ nvidia,pins = "dap4";
+ nvidia,function = "dap4";
+ };
+ ddc {
+ nvidia,pins = "ddc";
+ nvidia,function = "i2c2";
+ };
+ dta {
+ nvidia,pins = "dta", "dtd";
+ nvidia,function = "sdio2";
+ };
+ dtb {
+ nvidia,pins = "dtb", "dtc", "dte";
+ nvidia,function = "rsvd1";
+ };
+ dtf {
+ nvidia,pins = "dtf";
+ nvidia,function = "i2c3";
+ };
+ gmc {
+ nvidia,pins = "gmc";
+ nvidia,function = "uartd";
+ };
+ gpu7 {
+ nvidia,pins = "gpu7";
+ nvidia,function = "rtck";
+ };
+ gpv {
+ nvidia,pins = "gpv", "slxa", "slxk";
+ nvidia,function = "pcie";
+ };
+ hdint {
+ nvidia,pins = "hdint", "pta";
+ nvidia,function = "hdmi";
+ };
+ i2cp {
+ nvidia,pins = "i2cp";
+ nvidia,function = "i2cp";
+ };
+ irrx {
+ nvidia,pins = "irrx", "irtx";
+ nvidia,function = "uarta";
+ };
+ kbca {
+ nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
+ "kbce", "kbcf";
+ nvidia,function = "kbc";
+ };
+ lcsn {
+ nvidia,pins = "lcsn", "ld0", "ld1", "ld2",
+ "ld3", "ld4", "ld5", "ld6", "ld7",
+ "ld8", "ld9", "ld10", "ld11", "ld12",
+ "ld13", "ld14", "ld15", "ld16", "ld17",
+ "ldc", "ldi", "lhp0", "lhp1", "lhp2",
+ "lhs", "lm0", "lm1", "lpp", "lpw0",
+ "lpw1", "lpw2", "lsc0", "lsc1", "lsck",
+ "lsda", "lsdi", "lspi", "lvp0", "lvp1",
+ "lvs";
+ nvidia,function = "displaya";
+ };
+ owc {
+ nvidia,pins = "owc", "spdi", "spdo", "uac";
+ nvidia,function = "rsvd2";
+ };
+ pmc {
+ nvidia,pins = "pmc";
+ nvidia,function = "pwr_on";
+ };
+ rm {
+ nvidia,pins = "rm";
+ nvidia,function = "i2c1";
+ };
+ sdb {
+ nvidia,pins = "sdb", "sdc", "sdd";
+ nvidia,function = "pwm";
+ };
+ sdio1 {
+ nvidia,pins = "sdio1";
+ nvidia,function = "sdio1";
+ };
+ slxc {
+ nvidia,pins = "slxc", "slxd";
+ nvidia,function = "spdif";
+ };
+ spid {
+ nvidia,pins = "spid", "spie", "spif";
+ nvidia,function = "spi1";
+ };
+ spig {
+ nvidia,pins = "spig", "spih";
+ nvidia,function = "spi2_alt";
+ };
+ uaa {
+ nvidia,pins = "uaa", "uab", "uda";
+ nvidia,function = "ulpi";
+ };
+ uad {
+ nvidia,pins = "uad";
+ nvidia,function = "irda";
+ };
+ uca {
+ nvidia,pins = "uca", "ucb";
+ nvidia,function = "uartc";
+ };
+ conf_ata {
+ nvidia,pins = "ata", "atb", "atc", "atd", "ate",
+ "cdev1", "dap1", "dtb", "gma", "gmb",
+ "gmc", "gmd", "gme", "gpu7", "gpv",
+ "i2cp", "pta", "rm", "slxa", "slxk",
+ "spia", "spib";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
+ conf_cdev2 {
+ nvidia,pins = "cdev2", "csus", "spid", "spif";
+ nvidia,pull = <1>;
+ nvidia,tristate = <1>;
+ };
+ conf_ck32 {
+ nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
+ "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
+ nvidia,pull = <0>;
+ };
+ conf_crtp {
+ nvidia,pins = "crtp", "dap2", "dap3", "dap4",
+ "dtc", "dte", "dtf", "gpu", "sdio1",
+ "slxc", "slxd", "spdi", "spdo", "spig",
+ "uac", "uda";
+ nvidia,pull = <0>;
+ nvidia,tristate = <1>;
+ };
+ conf_ddc {
+ nvidia,pins = "ddc", "dta", "dtd", "kbca",
+ "kbcb", "kbcc", "kbcd", "kbce", "kbcf",
+ "sdc";
+ nvidia,pull = <2>;
+ nvidia,tristate = <0>;
+ };
+ conf_hdint {
+ nvidia,pins = "hdint", "lcsn", "ldc", "lm1",
+ "lpw1", "lsc1", "lsck", "lsda", "lsdi",
+ "lvp0", "owc", "sdb";
+ nvidia,tristate = <1>;
+ };
+ conf_irrx {
+ nvidia,pins = "irrx", "irtx", "sdd", "spic",
+ "spie", "spih", "uaa", "uab", "uad",
+ "uca", "ucb";
+ nvidia,pull = <2>;
+ nvidia,tristate = <1>;
+ };
+ conf_lc {
+ nvidia,pins = "lc", "ls";
+ nvidia,pull = <2>;
+ };
+ conf_ld0 {
+ nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+ "ld5", "ld6", "ld7", "ld8", "ld9",
+ "ld10", "ld11", "ld12", "ld13", "ld14",
+ "ld15", "ld16", "ld17", "ldi", "lhp0",
+ "lhp1", "lhp2", "lhs", "lm0", "lpp",
+ "lpw0", "lpw2", "lsc0", "lspi", "lvp1",
+ "lvs", "pmc";
+ nvidia,tristate = <0>;
+ };
+ conf_ld17_0 {
+ nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+ "ld23_22";
+ nvidia,pull = <1>;
+ };
+ };
+ };
+
pmc@7000f400 {
nvidia,invert-interrupt;
};
diff --git a/arch/arm/boot/dts/tegra-paz00.dts b/arch/arm/boot/dts/tegra-paz00.dts
index 6c02abb469d4..10943fb2561c 100644
--- a/arch/arm/boot/dts/tegra-paz00.dts
+++ b/arch/arm/boot/dts/tegra-paz00.dts
@@ -10,6 +10,226 @@
reg = <0x00000000 0x20000000>;
};
+ pinmux@70000000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+
+ state_default: pinmux {
+ ata {
+ nvidia,pins = "ata", "atc", "atd", "ate",
+ "dap2", "gmb", "gmc", "gmd", "spia",
+ "spib", "spic", "spid", "spie";
+ nvidia,function = "gmi";
+ };
+ atb {
+ nvidia,pins = "atb", "gma", "gme";
+ nvidia,function = "sdio4";
+ };
+ cdev1 {
+ nvidia,pins = "cdev1";
+ nvidia,function = "plla_out";
+ };
+ cdev2 {
+ nvidia,pins = "cdev2";
+ nvidia,function = "pllp_out4";
+ };
+ crtp {
+ nvidia,pins = "crtp";
+ nvidia,function = "crt";
+ };
+ csus {
+ nvidia,pins = "csus";
+ nvidia,function = "pllc_out1";
+ };
+ dap1 {
+ nvidia,pins = "dap1";
+ nvidia,function = "dap1";
+ };
+ dap3 {
+ nvidia,pins = "dap3";
+ nvidia,function = "dap3";
+ };
+ dap4 {
+ nvidia,pins = "dap4";
+ nvidia,function = "dap4";
+ };
+ ddc {
+ nvidia,pins = "ddc";
+ nvidia,function = "i2c2";
+ };
+ dta {
+ nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
+ nvidia,function = "rsvd1";
+ };
+ dtf {
+ nvidia,pins = "dtf";
+ nvidia,function = "i2c3";
+ };
+ gpu {
+ nvidia,pins = "gpu", "sdb", "sdd";
+ nvidia,function = "pwm";
+ };
+ gpu7 {
+ nvidia,pins = "gpu7";
+ nvidia,function = "rtck";
+ };
+ gpv {
+ nvidia,pins = "gpv", "slxa", "slxk";
+ nvidia,function = "pcie";
+ };
+ hdint {
+ nvidia,pins = "hdint", "pta";
+ nvidia,function = "hdmi";
+ };
+ i2cp {
+ nvidia,pins = "i2cp";
+ nvidia,function = "i2cp";
+ };
+ irrx {
+ nvidia,pins = "irrx", "irtx";
+ nvidia,function = "uarta";
+ };
+ kbca {
+ nvidia,pins = "kbca", "kbcc", "kbce", "kbcf";
+ nvidia,function = "kbc";
+ };
+ kbcb {
+ nvidia,pins = "kbcb", "kbcd";
+ nvidia,function = "sdio2";
+ };
+ lcsn {
+ nvidia,pins = "lcsn", "ld0", "ld1", "ld2",
+ "ld3", "ld4", "ld5", "ld6", "ld7",
+ "ld8", "ld9", "ld10", "ld11", "ld12",
+ "ld13", "ld14", "ld15", "ld16", "ld17",
+ "ldc", "ldi", "lhp0", "lhp1", "lhp2",
+ "lhs", "lm0", "lm1", "lpp", "lpw0",
+ "lpw1", "lpw2", "lsc0", "lsc1", "lsck",
+ "lsda", "lsdi", "lspi", "lvp0", "lvp1",
+ "lvs";
+ nvidia,function = "displaya";
+ };
+ owc {
+ nvidia,pins = "owc";
+ nvidia,function = "owr";
+ };
+ pmc {
+ nvidia,pins = "pmc";
+ nvidia,function = "pwr_on";
+ };
+ rm {
+ nvidia,pins = "rm";
+ nvidia,function = "i2c1";
+ };
+ sdc {
+ nvidia,pins = "sdc";
+ nvidia,function = "twc";
+ };
+ sdio1 {
+ nvidia,pins = "sdio1";
+ nvidia,function = "sdio1";
+ };
+ slxc {
+ nvidia,pins = "slxc", "slxd";
+ nvidia,function = "spi4";
+ };
+ spdi {
+ nvidia,pins = "spdi", "spdo";
+ nvidia,function = "rsvd2";
+ };
+ spif {
+ nvidia,pins = "spif", "uac";
+ nvidia,function = "rsvd4";
+ };
+ spig {
+ nvidia,pins = "spig", "spih";
+ nvidia,function = "spi2_alt";
+ };
+ uaa {
+ nvidia,pins = "uaa", "uab", "uda";
+ nvidia,function = "ulpi";
+ };
+ uad {
+ nvidia,pins = "uad";
+ nvidia,function = "spdif";
+ };
+ uca {
+ nvidia,pins = "uca", "ucb";
+ nvidia,function = "uartc";
+ };
+ conf_ata {
+ nvidia,pins = "ata", "atb", "atc", "atd", "ate",
+ "cdev1", "dap1", "dap2", "dtf", "gma",
+ "gmb", "gmc", "gmd", "gme", "gpu",
+ "gpu7", "gpv", "i2cp", "pta", "rm",
+ "sdio1", "slxk", "spdo", "uac", "uda";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
+ conf_cdev2 {
+ nvidia,pins = "cdev2";
+ nvidia,pull = <1>;
+ nvidia,tristate = <0>;
+ };
+ conf_ck32 {
+ nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
+ "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
+ nvidia,pull = <0>;
+ };
+ conf_crtp {
+ nvidia,pins = "crtp", "dap3", "dap4", "dtb",
+ "dtc", "dte", "slxa", "slxc", "slxd",
+ "spdi";
+ nvidia,pull = <0>;
+ nvidia,tristate = <1>;
+ };
+ conf_csus {
+ nvidia,pins = "csus", "spia", "spib", "spid",
+ "spif";
+ nvidia,pull = <1>;
+ nvidia,tristate = <1>;
+ };
+ conf_ddc {
+ nvidia,pins = "ddc", "irrx", "irtx", "kbca",
+ "kbcb", "kbcc", "kbcd", "kbce", "kbcf",
+ "spic", "spig", "uaa", "uab";
+ nvidia,pull = <2>;
+ nvidia,tristate = <0>;
+ };
+ conf_dta {
+ nvidia,pins = "dta", "dtd", "owc", "sdc", "sdd",
+ "spie", "spih", "uad", "uca", "ucb";
+ nvidia,pull = <2>;
+ nvidia,tristate = <1>;
+ };
+ conf_hdint {
+ nvidia,pins = "hdint", "ld0", "ld1", "ld2",
+ "ld3", "ld4", "ld5", "ld6", "ld7",
+ "ld8", "ld9", "ld10", "ld11", "ld12",
+ "ld13", "ld14", "ld15", "ld16", "ld17",
+ "ldc", "ldi", "lhs", "lsc0", "lspi",
+ "lvs", "pmc";
+ nvidia,tristate = <0>;
+ };
+ conf_lc {
+ nvidia,pins = "lc", "ls";
+ nvidia,pull = <2>;
+ };
+ conf_lcsn {
+ nvidia,pins = "lcsn", "lhp0", "lhp1", "lhp2",
+ "lm0", "lm1", "lpp", "lpw0", "lpw1",
+ "lpw2", "lsc1", "lsck", "lsda", "lsdi",
+ "lvp0", "lvp1", "sdb";
+ nvidia,tristate = <1>;
+ };
+ conf_ld17_0 {
+ nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+ "ld23_22";
+ nvidia,pull = <1>;
+ };
+ };
+ };
+
i2c@7000c000 {
clock-frequency = <400000>;
diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts
index dbf1c5a171c2..ec33116f5df9 100644
--- a/arch/arm/boot/dts/tegra-seaboard.dts
+++ b/arch/arm/boot/dts/tegra-seaboard.dts
@@ -11,6 +11,249 @@
reg = < 0x00000000 0x40000000 >;
};
+ pinmux@70000000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+
+ state_default: pinmux {
+ ata {
+ nvidia,pins = "ata";
+ nvidia,function = "ide";
+ };
+ atb {
+ nvidia,pins = "atb", "gma", "gme";
+ nvidia,function = "sdio4";
+ };
+ atc {
+ nvidia,pins = "atc";
+ nvidia,function = "nand";
+ };
+ atd {
+ nvidia,pins = "atd", "ate", "gmb", "spia",
+ "spib", "spic";
+ nvidia,function = "gmi";
+ };
+ cdev1 {
+ nvidia,pins = "cdev1";
+ nvidia,function = "plla_out";
+ };
+ cdev2 {
+ nvidia,pins = "cdev2";
+ nvidia,function = "pllp_out4";
+ };
+ crtp {
+ nvidia,pins = "crtp", "lm1";
+ nvidia,function = "crt";
+ };
+ csus {
+ nvidia,pins = "csus";
+ nvidia,function = "vi_sensor_clk";
+ };
+ dap1 {
+ nvidia,pins = "dap1";
+ nvidia,function = "dap1";
+ };
+ dap2 {
+ nvidia,pins = "dap2";
+ nvidia,function = "dap2";
+ };
+ dap3 {
+ nvidia,pins = "dap3";
+ nvidia,function = "dap3";
+ };
+ dap4 {
+ nvidia,pins = "dap4";
+ nvidia,function = "dap4";
+ };
+ ddc {
+ nvidia,pins = "ddc", "owc", "spdi", "spdo",
+ "uac";
+ nvidia,function = "rsvd2";
+ };
+ dta {
+ nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
+ nvidia,function = "vi";
+ };
+ dtf {
+ nvidia,pins = "dtf";
+ nvidia,function = "i2c3";
+ };
+ gmc {
+ nvidia,pins = "gmc";
+ nvidia,function = "uartd";
+ };
+ gmd {
+ nvidia,pins = "gmd";
+ nvidia,function = "sflash";
+ };
+ gpu {
+ nvidia,pins = "gpu";
+ nvidia,function = "pwm";
+ };
+ gpu7 {
+ nvidia,pins = "gpu7";
+ nvidia,function = "rtck";
+ };
+ gpv {
+ nvidia,pins = "gpv", "slxa", "slxk";
+ nvidia,function = "pcie";
+ };
+ hdint {
+ nvidia,pins = "hdint", "lpw0", "lpw2", "lsc1",
+ "lsck", "lsda", "pta";
+ nvidia,function = "hdmi";
+ };
+ i2cp {
+ nvidia,pins = "i2cp";
+ nvidia,function = "i2cp";
+ };
+ irrx {
+ nvidia,pins = "irrx", "irtx";
+ nvidia,function = "uartb";
+ };
+ kbca {
+ nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
+ "kbce", "kbcf";
+ nvidia,function = "kbc";
+ };
+ lcsn {
+ nvidia,pins = "lcsn", "ldc", "lm0", "lpw1",
+ "lsdi", "lvp0";
+ nvidia,function = "rsvd4";
+ };
+ ld0 {
+ nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+ "ld5", "ld6", "ld7", "ld8", "ld9",
+ "ld10", "ld11", "ld12", "ld13", "ld14",
+ "ld15", "ld16", "ld17", "ldi", "lhp0",
+ "lhp1", "lhp2", "lhs", "lpp", "lsc0",
+ "lspi", "lvp1", "lvs";
+ nvidia,function = "displaya";
+ };
+ pmc {
+ nvidia,pins = "pmc";
+ nvidia,function = "pwr_on";
+ };
+ rm {
+ nvidia,pins = "rm";
+ nvidia,function = "i2c1";
+ };
+ sdb {
+ nvidia,pins = "sdb", "sdc", "sdd";
+ nvidia,function = "sdio3";
+ };
+ sdio1 {
+ nvidia,pins = "sdio1";
+ nvidia,function = "sdio1";
+ };
+ slxc {
+ nvidia,pins = "slxc", "slxd";
+ nvidia,function = "spdif";
+ };
+ spid {
+ nvidia,pins = "spid", "spie", "spif";
+ nvidia,function = "spi1";
+ };
+ spig {
+ nvidia,pins = "spig", "spih";
+ nvidia,function = "spi2_alt";
+ };
+ uaa {
+ nvidia,pins = "uaa", "uab", "uda";
+ nvidia,function = "ulpi";
+ };
+ uad {
+ nvidia,pins = "uad";
+ nvidia,function = "irda";
+ };
+ uca {
+ nvidia,pins = "uca", "ucb";
+ nvidia,function = "uartc";
+ };
+ conf_ata {
+ nvidia,pins = "ata", "atb", "atc", "atd",
+ "cdev1", "cdev2", "dap1", "dap2",
+ "dap4", "dtf", "gma", "gmc", "gmd",
+ "gme", "gpu", "gpu7", "i2cp", "irrx",
+ "irtx", "pta", "rm", "sdc", "sdd",
+ "slxd", "slxk", "spdi", "spdo", "uac",
+ "uad", "uca", "ucb", "uda";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
+ conf_ate {
+ nvidia,pins = "ate", "csus", "dap3", "ddc",
+ "gpv", "owc", "slxc", "spib", "spid",
+ "spie";
+ nvidia,pull = <0>;
+ nvidia,tristate = <1>;
+ };
+ conf_ck32 {
+ nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
+ "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
+ nvidia,pull = <0>;
+ };
+ conf_crtp {
+ nvidia,pins = "crtp", "gmb", "slxa", "spia",
+ "spig", "spih";
+ nvidia,pull = <2>;
+ nvidia,tristate = <1>;
+ };
+ conf_dta {
+ nvidia,pins = "dta", "dtb", "dtc", "dtd";
+ nvidia,pull = <1>;
+ nvidia,tristate = <0>;
+ };
+ conf_dte {
+ nvidia,pins = "dte", "spif";
+ nvidia,pull = <1>;
+ nvidia,tristate = <1>;
+ };
+ conf_hdint {
+ nvidia,pins = "hdint", "lcsn", "ldc", "lm1",
+ "lpw1", "lsc1", "lsck", "lsda", "lsdi",
+ "lvp0";
+ nvidia,tristate = <1>;
+ };
+ conf_kbca {
+ nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
+ "kbce", "kbcf", "sdio1", "spic", "uaa",
+ "uab";
+ nvidia,pull = <2>;
+ nvidia,tristate = <0>;
+ };
+ conf_lc {
+ nvidia,pins = "lc", "ls";
+ nvidia,pull = <2>;
+ };
+ conf_ld0 {
+ nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+ "ld5", "ld6", "ld7", "ld8", "ld9",
+ "ld10", "ld11", "ld12", "ld13", "ld14",
+ "ld15", "ld16", "ld17", "ldi", "lhp0",
+ "lhp1", "lhp2", "lhs", "lm0", "lpp",
+ "lpw0", "lpw2", "lsc0", "lspi", "lvp1",
+ "lvs", "pmc", "sdb";
+ nvidia,tristate = <0>;
+ };
+ conf_ld17_0 {
+ nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+ "ld23_22";
+ nvidia,pull = <1>;
+ };
+ drive_sdio1 {
+ nvidia,pins = "drive_sdio1";
+ nvidia,high-speed-mode = <0>;
+ nvidia,schmitt = <0>;
+ nvidia,low-power-mode = <3>;
+ nvidia,pull-down-strength = <31>;
+ nvidia,pull-up-strength = <31>;
+ nvidia,slew-rate-rising = <3>;
+ nvidia,slew-rate-falling = <3>;
+ };
+ };
+ };
+
i2c@7000c000 {
clock-frequency = <400000>;
diff --git a/arch/arm/boot/dts/tegra-trimslice.dts b/arch/arm/boot/dts/tegra-trimslice.dts
index 252476867b54..98efd5b0d7f9 100644
--- a/arch/arm/boot/dts/tegra-trimslice.dts
+++ b/arch/arm/boot/dts/tegra-trimslice.dts
@@ -10,6 +10,236 @@
reg = < 0x00000000 0x40000000 >;
};
+ pinmux@70000000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+
+ state_default: pinmux {
+ ata {
+ nvidia,pins = "ata";
+ nvidia,function = "ide";
+ };
+ atb {
+ nvidia,pins = "atb", "gma";
+ nvidia,function = "sdio4";
+ };
+ atc {
+ nvidia,pins = "atc", "gmb";
+ nvidia,function = "nand";
+ };
+ atd {
+ nvidia,pins = "atd", "ate", "gme", "pta";
+ nvidia,function = "gmi";
+ };
+ cdev1 {
+ nvidia,pins = "cdev1";
+ nvidia,function = "plla_out";
+ };
+ cdev2 {
+ nvidia,pins = "cdev2";
+ nvidia,function = "pllp_out4";
+ };
+ crtp {
+ nvidia,pins = "crtp";
+ nvidia,function = "crt";
+ };
+ csus {
+ nvidia,pins = "csus";
+ nvidia,function = "vi_sensor_clk";
+ };
+ dap1 {
+ nvidia,pins = "dap1";
+ nvidia,function = "dap1";
+ };
+ dap2 {
+ nvidia,pins = "dap2";
+ nvidia,function = "dap2";
+ };
+ dap3 {
+ nvidia,pins = "dap3";
+ nvidia,function = "dap3";
+ };
+ dap4 {
+ nvidia,pins = "dap4";
+ nvidia,function = "dap4";
+ };
+ ddc {
+ nvidia,pins = "ddc";
+ nvidia,function = "i2c2";
+ };
+ dta {
+ nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
+ nvidia,function = "vi";
+ };
+ dtf {
+ nvidia,pins = "dtf";
+ nvidia,function = "i2c3";
+ };
+ gmc {
+ nvidia,pins = "gmc", "gmd";
+ nvidia,function = "sflash";
+ };
+ gpu {
+ nvidia,pins = "gpu";
+ nvidia,function = "uarta";
+ };
+ gpu7 {
+ nvidia,pins = "gpu7";
+ nvidia,function = "rtck";
+ };
+ gpv {
+ nvidia,pins = "gpv", "slxa", "slxk";
+ nvidia,function = "pcie";
+ };
+ hdint {
+ nvidia,pins = "hdint";
+ nvidia,function = "hdmi";
+ };
+ i2cp {
+ nvidia,pins = "i2cp";
+ nvidia,function = "i2cp";
+ };
+ irrx {
+ nvidia,pins = "irrx", "irtx";
+ nvidia,function = "uartb";
+ };
+ kbca {
+ nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
+ "kbce", "kbcf";
+ nvidia,function = "kbc";
+ };
+ lcsn {
+ nvidia,pins = "lcsn", "ld0", "ld1", "ld2",
+ "ld3", "ld4", "ld5", "ld6", "ld7",
+ "ld8", "ld9", "ld10", "ld11", "ld12",
+ "ld13", "ld14", "ld15", "ld16", "ld17",
+ "ldc", "ldi", "lhp0", "lhp1", "lhp2",
+ "lhs", "lm0", "lm1", "lpp", "lpw0",
+ "lpw1", "lpw2", "lsc0", "lsc1", "lsck",
+ "lsda", "lsdi", "lspi", "lvp0", "lvp1",
+ "lvs";
+ nvidia,function = "displaya";
+ };
+ owc {
+ nvidia,pins = "owc", "uac";
+ nvidia,function = "rsvd2";
+ };
+ pmc {
+ nvidia,pins = "pmc";
+ nvidia,function = "pwr_on";
+ };
+ rm {
+ nvidia,pins = "rm";
+ nvidia,function = "i2c1";
+ };
+ sdb {
+ nvidia,pins = "sdb", "sdc", "sdd";
+ nvidia,function = "pwm";
+ };
+ sdio1 {
+ nvidia,pins = "sdio1";
+ nvidia,function = "sdio1";
+ };
+ slxc {
+ nvidia,pins = "slxc", "slxd";
+ nvidia,function = "sdio3";
+ };
+ spdi {
+ nvidia,pins = "spdi", "spdo";
+ nvidia,function = "spdif";
+ };
+ spia {
+ nvidia,pins = "spia", "spib", "spic";
+ nvidia,function = "spi2";
+ };
+ spid {
+ nvidia,pins = "spid", "spie", "spif";
+ nvidia,function = "spi1";
+ };
+ spig {
+ nvidia,pins = "spig", "spih";
+ nvidia,function = "spi2_alt";
+ };
+ uaa {
+ nvidia,pins = "uaa", "uab", "uda";
+ nvidia,function = "ulpi";
+ };
+ uad {
+ nvidia,pins = "uad";
+ nvidia,function = "irda";
+ };
+ uca {
+ nvidia,pins = "uca", "ucb";
+ nvidia,function = "uartc";
+ };
+ conf_ata {
+ nvidia,pins = "ata", "atc", "atd", "ate",
+ "crtp", "dap2", "dap3", "dap4", "dta",
+ "dtb", "dtc", "dtd", "dte", "gmb",
+ "gme", "i2cp", "pta", "slxc", "slxd",
+ "spdi", "spdo", "uda";
+ nvidia,pull = <0>;
+ nvidia,tristate = <1>;
+ };
+ conf_atb {
+ nvidia,pins = "atb", "cdev1", "dap1", "gma",
+ "gmc", "gmd", "gpu", "gpu7", "gpv",
+ "sdio1", "slxa", "slxk", "uac";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
+ conf_cdev2 {
+ nvidia,pins = "cdev2", "csus", "spia", "spib",
+ "spid", "spif";
+ nvidia,pull = <1>;
+ nvidia,tristate = <1>;
+ };
+ conf_ck32 {
+ nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
+ "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
+ nvidia,pull = <0>;
+ };
+ conf_ddc {
+ nvidia,pins = "ddc", "dtf", "rm", "sdc", "sdd";
+ nvidia,pull = <2>;
+ nvidia,tristate = <0>;
+ };
+ conf_hdint {
+ nvidia,pins = "hdint", "lcsn", "ldc", "lm1",
+ "lpw1", "lsc1", "lsck", "lsda", "lsdi",
+ "lvp0", "pmc";
+ nvidia,tristate = <1>;
+ };
+ conf_irrx {
+ nvidia,pins = "irrx", "irtx", "kbca", "kbcb",
+ "kbcc", "kbcd", "kbce", "kbcf", "owc",
+ "spic", "spie", "spig", "spih", "uaa",
+ "uab", "uad", "uca", "ucb";
+ nvidia,pull = <2>;
+ nvidia,tristate = <1>;
+ };
+ conf_lc {
+ nvidia,pins = "lc", "ls";
+ nvidia,pull = <2>;
+ };
+ conf_ld0 {
+ nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+ "ld5", "ld6", "ld7", "ld8", "ld9",
+ "ld10", "ld11", "ld12", "ld13", "ld14",
+ "ld15", "ld16", "ld17", "ldi", "lhp0",
+ "lhp1", "lhp2", "lhs", "lm0", "lpp",
+ "lpw0", "lpw2", "lsc0", "lspi", "lvp1",
+ "lvs", "sdb";
+ nvidia,tristate = <0>;
+ };
+ conf_ld17_0 {
+ nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+ "ld23_22";
+ nvidia,pull = <1>;
+ };
+ };
+ };
+
i2c@7000c000 {
clock-frequency = <400000>;
};
diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts
index 2dcff8728e90..71eb2e50a668 100644
--- a/arch/arm/boot/dts/tegra-ventana.dts
+++ b/arch/arm/boot/dts/tegra-ventana.dts
@@ -10,6 +10,236 @@
reg = < 0x00000000 0x40000000 >;
};
+ pinmux@70000000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+
+ state_default: pinmux {
+ ata {
+ nvidia,pins = "ata";
+ nvidia,function = "ide";
+ };
+ atb {
+ nvidia,pins = "atb", "gma", "gme";
+ nvidia,function = "sdio4";
+ };
+ atc {
+ nvidia,pins = "atc";
+ nvidia,function = "nand";
+ };
+ atd {
+ nvidia,pins = "atd", "ate", "gmb", "spia",
+ "spib", "spic";
+ nvidia,function = "gmi";
+ };
+ cdev1 {
+ nvidia,pins = "cdev1";
+ nvidia,function = "plla_out";
+ };
+ cdev2 {
+ nvidia,pins = "cdev2";
+ nvidia,function = "pllp_out4";
+ };
+ crtp {
+ nvidia,pins = "crtp", "lm1";
+ nvidia,function = "crt";
+ };
+ csus {
+ nvidia,pins = "csus";
+ nvidia,function = "vi_sensor_clk";
+ };
+ dap1 {
+ nvidia,pins = "dap1";
+ nvidia,function = "dap1";
+ };
+ dap2 {
+ nvidia,pins = "dap2";
+ nvidia,function = "dap2";
+ };
+ dap3 {
+ nvidia,pins = "dap3";
+ nvidia,function = "dap3";
+ };
+ dap4 {
+ nvidia,pins = "dap4";
+ nvidia,function = "dap4";
+ };
+ ddc {
+ nvidia,pins = "ddc", "owc", "spdi", "spdo",
+ "uac";
+ nvidia,function = "rsvd2";
+ };
+ dta {
+ nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
+ nvidia,function = "vi";
+ };
+ dtf {
+ nvidia,pins = "dtf";
+ nvidia,function = "i2c3";
+ };
+ gmc {
+ nvidia,pins = "gmc";
+ nvidia,function = "uartd";
+ };
+ gmd {
+ nvidia,pins = "gmd";
+ nvidia,function = "sflash";
+ };
+ gpu {
+ nvidia,pins = "gpu";
+ nvidia,function = "pwm";
+ };
+ gpu7 {
+ nvidia,pins = "gpu7";
+ nvidia,function = "rtck";
+ };
+ gpv {
+ nvidia,pins = "gpv", "slxa", "slxk";
+ nvidia,function = "pcie";
+ };
+ hdint {
+ nvidia,pins = "hdint", "pta";
+ nvidia,function = "hdmi";
+ };
+ i2cp {
+ nvidia,pins = "i2cp";
+ nvidia,function = "i2cp";
+ };
+ irrx {
+ nvidia,pins = "irrx", "irtx";
+ nvidia,function = "uartb";
+ };
+ kbca {
+ nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
+ "kbce", "kbcf";
+ nvidia,function = "kbc";
+ };
+ lcsn {
+ nvidia,pins = "lcsn", "ldc", "lm0", "lpw1",
+ "lsdi", "lvp0";
+ nvidia,function = "rsvd4";
+ };
+ ld0 {
+ nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+ "ld5", "ld6", "ld7", "ld8", "ld9",
+ "ld10", "ld11", "ld12", "ld13", "ld14",
+ "ld15", "ld16", "ld17", "ldi", "lhp0",
+ "lhp1", "lhp2", "lhs", "lpp", "lpw0",
+ "lpw2", "lsc0", "lsc1", "lsck", "lsda",
+ "lspi", "lvp1", "lvs";
+ nvidia,function = "displaya";
+ };
+ pmc {
+ nvidia,pins = "pmc";
+ nvidia,function = "pwr_on";
+ };
+ rm {
+ nvidia,pins = "rm";
+ nvidia,function = "i2c1";
+ };
+ sdb {
+ nvidia,pins = "sdb", "sdc", "sdd", "slxc";
+ nvidia,function = "sdio3";
+ };
+ sdio1 {
+ nvidia,pins = "sdio1";
+ nvidia,function = "sdio1";
+ };
+ slxd {
+ nvidia,pins = "slxd";
+ nvidia,function = "spdif";
+ };
+ spid {
+ nvidia,pins = "spid", "spie", "spif";
+ nvidia,function = "spi1";
+ };
+ spig {
+ nvidia,pins = "spig", "spih";
+ nvidia,function = "spi2_alt";
+ };
+ uaa {
+ nvidia,pins = "uaa", "uab", "uda";
+ nvidia,function = "ulpi";
+ };
+ uad {
+ nvidia,pins = "uad";
+ nvidia,function = "irda";
+ };
+ uca {
+ nvidia,pins = "uca", "ucb";
+ nvidia,function = "uartc";
+ };
+ conf_ata {
+ nvidia,pins = "ata", "atb", "atc", "atd",
+ "cdev1", "cdev2", "dap1", "dap2",
+ "dap4", "ddc", "dtf", "gma", "gmc",
+ "gme", "gpu", "gpu7", "i2cp", "irrx",
+ "irtx", "pta", "rm", "sdc", "sdd",
+ "slxc", "slxd", "slxk", "spdi", "spdo",
+ "uac", "uad", "uca", "ucb", "uda";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
+ conf_ate {
+ nvidia,pins = "ate", "csus", "dap3", "gmd",
+ "gpv", "owc", "spia", "spib", "spic",
+ "spid", "spie", "spig";
+ nvidia,pull = <0>;
+ nvidia,tristate = <1>;
+ };
+ conf_ck32 {
+ nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
+ "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
+ nvidia,pull = <0>;
+ };
+ conf_crtp {
+ nvidia,pins = "crtp", "gmb", "slxa", "spih";
+ nvidia,pull = <2>;
+ nvidia,tristate = <1>;
+ };
+ conf_dta {
+ nvidia,pins = "dta", "dtb", "dtc", "dtd";
+ nvidia,pull = <1>;
+ nvidia,tristate = <0>;
+ };
+ conf_dte {
+ nvidia,pins = "dte", "spif";
+ nvidia,pull = <1>;
+ nvidia,tristate = <1>;
+ };
+ conf_hdint {
+ nvidia,pins = "hdint", "lcsn", "ldc", "lm1",
+ "lpw1", "lsck", "lsda", "lsdi", "lvp0";
+ nvidia,tristate = <1>;
+ };
+ conf_kbca {
+ nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
+ "kbce", "kbcf", "sdio1", "uaa", "uab";
+ nvidia,pull = <2>;
+ nvidia,tristate = <0>;
+ };
+ conf_lc {
+ nvidia,pins = "lc", "ls";
+ nvidia,pull = <2>;
+ };
+ conf_ld0 {
+ nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+ "ld5", "ld6", "ld7", "ld8", "ld9",
+ "ld10", "ld11", "ld12", "ld13", "ld14",
+ "ld15", "ld16", "ld17", "ldi", "lhp0",
+ "lhp1", "lhp2", "lhs", "lm0", "lpp",
+ "lpw0", "lpw2", "lsc0", "lsc1", "lspi",
+ "lvp1", "lvs", "pmc", "sdb";
+ nvidia,tristate = <0>;
+ };
+ conf_ld17_0 {
+ nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+ "ld23_22";
+ nvidia,pull = <1>;
+ };
+ };
+ };
+
i2c@7000c000 {
clock-frequency = <400000>;
diff --git a/arch/arm/boot/dts/tny_a9260.dts b/arch/arm/boot/dts/tny_a9260.dts
new file mode 100644
index 000000000000..367a16dcd5ef
--- /dev/null
+++ b/arch/arm/boot/dts/tny_a9260.dts
@@ -0,0 +1,15 @@
+/*
+ * tny_a9260.dts - Device Tree file for Caloa TNY A9260 board
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+/dts-v1/;
+/include/ "at91sam9260.dtsi"
+/include/ "tny_a9260_common.dtsi"
+
+/ {
+ model = "Calao TNY A9260";
+ compatible = "calao,tny-a9260", "atmel,at91sam9260", "atmel,at91sam9";
+};
diff --git a/arch/arm/boot/dts/tny_a9260_common.dtsi b/arch/arm/boot/dts/tny_a9260_common.dtsi
new file mode 100644
index 000000000000..0e6d3de2e09e
--- /dev/null
+++ b/arch/arm/boot/dts/tny_a9260_common.dtsi
@@ -0,0 +1,83 @@
+/*
+ * tny_a9260_common.dtsi - Device Tree file for Caloa TNY A926x board
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/ {
+ chosen {
+ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock6 rw rootfstype=ubifs";
+ };
+
+ memory {
+ reg = <0x20000000 0x4000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ main_clock: clock@0 {
+ compatible = "atmel,osc", "fixed-clock";
+ clock-frequency = <12000000>;
+ };
+ };
+
+ ahb {
+ apb {
+ dbgu: serial@fffff200 {
+ status = "okay";
+ };
+ };
+
+ nand0: nand@40000000 {
+ nand-bus-width = <8>;
+ nand-ecc-mode = "soft";
+ nand-on-flash-bbt;
+ status = "okay";
+
+ at91bootstrap@0 {
+ label = "at91bootstrap";
+ reg = <0x0 0x20000>;
+ };
+
+ barebox@20000 {
+ label = "barebox";
+ reg = <0x20000 0x40000>;
+ };
+
+ bareboxenv@60000 {
+ label = "bareboxenv";
+ reg = <0x60000 0x20000>;
+ };
+
+ bareboxenv2@80000 {
+ label = "bareboxenv2";
+ reg = <0x80000 0x20000>;
+ };
+
+ oftree@80000 {
+ label = "oftree";
+ reg = <0xa0000 0x20000>;
+ };
+
+ kernel@a0000 {
+ label = "kernel";
+ reg = <0xc0000 0x400000>;
+ };
+
+ rootfs@4a0000 {
+ label = "rootfs";
+ reg = <0x4c0000 0x7800000>;
+ };
+
+ data@7ca0000 {
+ label = "data";
+ reg = <0x7cc0000 0x8340000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/tny_a9263.dts b/arch/arm/boot/dts/tny_a9263.dts
new file mode 100644
index 000000000000..dee9c571306b
--- /dev/null
+++ b/arch/arm/boot/dts/tny_a9263.dts
@@ -0,0 +1,97 @@
+/*
+ * usb_a9263.dts - Device Tree file for Caloa USB A9293 board
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 only
+ */
+/dts-v1/;
+/include/ "at91sam9263.dtsi"
+
+/ {
+ model = "Calao TNY A9263";
+ compatible = "atmel,tny-a9263", "atmel,at91sam9263", "atmel,at91sam9";
+
+ chosen {
+ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
+ };
+
+ memory {
+ reg = <0x20000000 0x4000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ main_clock: clock@0 {
+ compatible = "atmel,osc", "fixed-clock";
+ clock-frequency = <12000000>;
+ };
+ };
+
+ ahb {
+ apb {
+ dbgu: serial@ffffee00 {
+ status = "okay";
+ };
+
+ usb1: gadget@fff78000 {
+ atmel,vbus-gpio = <&pioB 11 0>;
+ status = "okay";
+ };
+ };
+
+ nand0: nand@40000000 {
+ nand-bus-width = <8>;
+ nand-ecc-mode = "soft";
+ nand-on-flash-bbt;
+ status = "okay";
+
+ at91bootstrap@0 {
+ label = "at91bootstrap";
+ reg = <0x0 0x20000>;
+ };
+
+ barebox@20000 {
+ label = "barebox";
+ reg = <0x20000 0x40000>;
+ };
+
+ bareboxenv@60000 {
+ label = "bareboxenv";
+ reg = <0x60000 0x20000>;
+ };
+
+ bareboxenv2@80000 {
+ label = "bareboxenv2";
+ reg = <0x80000 0x20000>;
+ };
+
+ oftree@80000 {
+ label = "oftree";
+ reg = <0xa0000 0x20000>;
+ };
+
+ kernel@a0000 {
+ label = "kernel";
+ reg = <0xc0000 0x400000>;
+ };
+
+ rootfs@4a0000 {
+ label = "rootfs";
+ reg = <0x4c0000 0x7800000>;
+ };
+
+ data@7ca0000 {
+ label = "data";
+ reg = <0x7cc0000 0x8340000>;
+ };
+ };
+ };
+
+ i2c@0 {
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/tny_a9g20.dts b/arch/arm/boot/dts/tny_a9g20.dts
new file mode 100644
index 000000000000..e1ab64c72dba
--- /dev/null
+++ b/arch/arm/boot/dts/tny_a9g20.dts
@@ -0,0 +1,15 @@
+/*
+ * tny_a9g20.dts - Device Tree file for Caloa TNY A9G20 board
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+/dts-v1/;
+/include/ "at91sam9g20.dtsi"
+/include/ "tny_a9260_common.dtsi"
+
+/ {
+ model = "Calao TNY A9G20";
+ compatible = "calao,tny-a9g20", "atmel,at91sam9g20", "atmel,at91sam9";
+};
diff --git a/arch/arm/boot/dts/twl4030.dtsi b/arch/arm/boot/dts/twl4030.dtsi
new file mode 100644
index 000000000000..22f4d1394ed3
--- /dev/null
+++ b/arch/arm/boot/dts/twl4030.dtsi
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Integrated Power Management Chip
+ */
+&twl {
+ compatible = "ti,twl4030";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ rtc {
+ compatible = "ti,twl4030-rtc";
+ interrupts = <11>;
+ };
+
+ vdac: regulator@0 {
+ compatible = "ti,twl4030-vdac";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vpll2: regulator@1 {
+ compatible = "ti,twl4030-vpll2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vmmc1: regulator@2 {
+ compatible = "ti,twl4030-vmmc1";
+ regulator-min-microvolt = <1850000>;
+ regulator-max-microvolt = <3150000>;
+ };
+
+ twl_gpio: gpio {
+ compatible = "ti,twl4030-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+};
diff --git a/arch/arm/boot/dts/twl6030.dtsi b/arch/arm/boot/dts/twl6030.dtsi
new file mode 100644
index 000000000000..3b2f3510d7eb
--- /dev/null
+++ b/arch/arm/boot/dts/twl6030.dtsi
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Integrated Power Management Chip
+ * http://www.ti.com/lit/ds/symlink/twl6030.pdf
+ */
+&twl {
+ compatible = "ti,twl6030";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ rtc {
+ compatible = "ti,twl4030-rtc";
+ interrupts = <11>;
+ };
+
+ vaux1: regulator@0 {
+ compatible = "ti,twl6030-vaux1";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ vaux2: regulator@1 {
+ compatible = "ti,twl6030-vaux2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ vaux3: regulator@2 {
+ compatible = "ti,twl6030-vaux3";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ vmmc: regulator@3 {
+ compatible = "ti,twl6030-vmmc";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ vpp: regulator@4 {
+ compatible = "ti,twl6030-vpp";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2500000>;
+ };
+
+ vusim: regulator@5 {
+ compatible = "ti,twl6030-vusim";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <2900000>;
+ };
+
+ vdac: regulator@6 {
+ compatible = "ti,twl6030-vdac";
+ };
+
+ vana: regulator@7 {
+ compatible = "ti,twl6030-vana";
+ };
+
+ vcxio: regulator@8 {
+ compatible = "ti,twl6030-vcxio";
+ };
+
+ vusb: regulator@9 {
+ compatible = "ti,twl6030-vusb";
+ };
+
+ v1v8: regulator@10 {
+ compatible = "ti,twl6030-v1v8";
+ };
+
+ v2v1: regulator@11 {
+ compatible = "ti,twl6030-v2v1";
+ };
+
+ clk32kg: regulator@12 {
+ compatible = "ti,twl6030-clk32kg";
+ };
+};
diff --git a/arch/arm/boot/dts/usb_a9260.dts b/arch/arm/boot/dts/usb_a9260.dts
new file mode 100644
index 000000000000..296216058c11
--- /dev/null
+++ b/arch/arm/boot/dts/usb_a9260.dts
@@ -0,0 +1,23 @@
+/*
+ * usb_a9260.dts - Device Tree file for Caloa USB A9260 board
+ *
+ * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9260.dtsi"
+/include/ "usb_a9260_common.dtsi"
+
+/ {
+ model = "Calao USB A9260";
+ compatible = "calao,usb-a9260", "atmel,at91sam9260", "atmel,at91sam9";
+
+ chosen {
+ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
+ };
+
+ memory {
+ reg = <0x20000000 0x4000000>;
+ };
+};
diff --git a/arch/arm/boot/dts/usb_a9260_common.dtsi b/arch/arm/boot/dts/usb_a9260_common.dtsi
new file mode 100644
index 000000000000..e70d229baef5
--- /dev/null
+++ b/arch/arm/boot/dts/usb_a9260_common.dtsi
@@ -0,0 +1,117 @@
+/*
+ * usb_a926x.dts - Device Tree file for Caloa USB A926x board
+ *
+ * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/ {
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ main_clock: clock@0 {
+ compatible = "atmel,osc", "fixed-clock";
+ clock-frequency = <12000000>;
+ };
+ };
+
+ ahb {
+ apb {
+ dbgu: serial@fffff200 {
+ status = "okay";
+ };
+
+ macb0: ethernet@fffc4000 {
+ phy-mode = "rmii";
+ status = "okay";
+ };
+
+ usb1: gadget@fffa4000 {
+ atmel,vbus-gpio = <&pioC 5 0>;
+ status = "okay";
+ };
+ };
+
+ nand0: nand@40000000 {
+ nand-bus-width = <8>;
+ nand-ecc-mode = "soft";
+ nand-on-flash-bbt;
+ status = "okay";
+
+ at91bootstrap@0 {
+ label = "at91bootstrap";
+ reg = <0x0 0x20000>;
+ };
+
+ barebox@20000 {
+ label = "barebox";
+ reg = <0x20000 0x40000>;
+ };
+
+ bareboxenv@60000 {
+ label = "bareboxenv";
+ reg = <0x60000 0x20000>;
+ };
+
+ bareboxenv2@80000 {
+ label = "bareboxenv2";
+ reg = <0x80000 0x20000>;
+ };
+
+ oftree@80000 {
+ label = "oftree";
+ reg = <0xa0000 0x20000>;
+ };
+
+ kernel@a0000 {
+ label = "kernel";
+ reg = <0xc0000 0x400000>;
+ };
+
+ rootfs@4a0000 {
+ label = "rootfs";
+ reg = <0x4c0000 0x7800000>;
+ };
+
+ data@7ca0000 {
+ label = "data";
+ reg = <0x7cc0000 0x8340000>;
+ };
+ };
+
+ usb0: ohci@00500000 {
+ num-ports = <2>;
+ status = "okay";
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ user_led {
+ label = "user_led";
+ gpios = <&pioB 21 1>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ user_pb {
+ label = "user_pb";
+ gpios = <&pioB 10 1>;
+ linux,code = <28>;
+ gpio-key,wakeup;
+ };
+ };
+
+ i2c@0 {
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/usb_a9263.dts b/arch/arm/boot/dts/usb_a9263.dts
new file mode 100644
index 000000000000..6fe05ccb6203
--- /dev/null
+++ b/arch/arm/boot/dts/usb_a9263.dts
@@ -0,0 +1,131 @@
+/*
+ * usb_a9263.dts - Device Tree file for Caloa USB A9293 board
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 only
+ */
+/dts-v1/;
+/include/ "at91sam9263.dtsi"
+
+/ {
+ model = "Calao USB A9263";
+ compatible = "atmel,usb-a9263", "atmel,at91sam9263", "atmel,at91sam9";
+
+ chosen {
+ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
+ };
+
+ memory {
+ reg = <0x20000000 0x4000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ main_clock: clock@0 {
+ compatible = "atmel,osc", "fixed-clock";
+ clock-frequency = <12000000>;
+ };
+ };
+
+ ahb {
+ apb {
+ dbgu: serial@ffffee00 {
+ status = "okay";
+ };
+
+ macb0: ethernet@fffbc000 {
+ phy-mode = "rmii";
+ status = "okay";
+ };
+
+ usb1: gadget@fff78000 {
+ atmel,vbus-gpio = <&pioB 11 0>;
+ status = "okay";
+ };
+
+ };
+
+ nand0: nand@40000000 {
+ nand-bus-width = <8>;
+ nand-ecc-mode = "soft";
+ nand-on-flash-bbt;
+ status = "okay";
+
+ at91bootstrap@0 {
+ label = "at91bootstrap";
+ reg = <0x0 0x20000>;
+ };
+
+ barebox@20000 {
+ label = "barebox";
+ reg = <0x20000 0x40000>;
+ };
+
+ bareboxenv@60000 {
+ label = "bareboxenv";
+ reg = <0x60000 0x20000>;
+ };
+
+ bareboxenv2@80000 {
+ label = "bareboxenv2";
+ reg = <0x80000 0x20000>;
+ };
+
+ oftree@80000 {
+ label = "oftree";
+ reg = <0xa0000 0x20000>;
+ };
+
+ kernel@a0000 {
+ label = "kernel";
+ reg = <0xc0000 0x400000>;
+ };
+
+ rootfs@4a0000 {
+ label = "rootfs";
+ reg = <0x4c0000 0x7800000>;
+ };
+
+ data@7ca0000 {
+ label = "data";
+ reg = <0x7cc0000 0x8340000>;
+ };
+ };
+
+ usb0: ohci@00a00000 {
+ num-ports = <2>;
+ status = "okay";
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ user_led {
+ label = "user_led";
+ gpios = <&pioB 21 0>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ user_pb {
+ label = "user_pb";
+ gpios = <&pioB 10 1>;
+ linux,code = <28>;
+ gpio-key,wakeup;
+ };
+ };
+
+ i2c@0 {
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts
index 7c2399c532e5..2dacb16ce4ae 100644
--- a/arch/arm/boot/dts/usb_a9g20.dts
+++ b/arch/arm/boot/dts/usb_a9g20.dts
@@ -7,6 +7,7 @@
*/
/dts-v1/;
/include/ "at91sam9g20.dtsi"
+/include/ "usb_a9260_common.dtsi"
/ {
model = "Calao USB A9G20";
@@ -20,108 +21,7 @@
reg = <0x20000000 0x4000000>;
};
- clocks {
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
- main_clock: clock@0 {
- compatible = "atmel,osc", "fixed-clock";
- clock-frequency = <12000000>;
- };
- };
-
- ahb {
- apb {
- dbgu: serial@fffff200 {
- status = "okay";
- };
-
- macb0: ethernet@fffc4000 {
- phy-mode = "rmii";
- status = "okay";
- };
-
- usb1: gadget@fffa4000 {
- atmel,vbus-gpio = <&pioC 5 0>;
- status = "okay";
- };
- };
-
- nand0: nand@40000000 {
- nand-bus-width = <8>;
- nand-ecc-mode = "soft";
- nand-on-flash-bbt;
- status = "okay";
-
- at91bootstrap@0 {
- label = "at91bootstrap";
- reg = <0x0 0x20000>;
- };
-
- barebox@20000 {
- label = "barebox";
- reg = <0x20000 0x40000>;
- };
-
- bareboxenv@60000 {
- label = "bareboxenv";
- reg = <0x60000 0x20000>;
- };
-
- bareboxenv2@80000 {
- label = "bareboxenv2";
- reg = <0x80000 0x20000>;
- };
-
- kernel@a0000 {
- label = "kernel";
- reg = <0xa0000 0x400000>;
- };
-
- rootfs@4a0000 {
- label = "rootfs";
- reg = <0x4a0000 0x7800000>;
- };
-
- data@7ca0000 {
- label = "data";
- reg = <0x7ca0000 0x8360000>;
- };
- };
-
- usb0: ohci@00500000 {
- num-ports = <2>;
- status = "okay";
- };
- };
-
- leds {
- compatible = "gpio-leds";
-
- user_led {
- label = "user_led";
- gpios = <&pioB 21 1>;
- linux,default-trigger = "heartbeat";
- };
- };
-
- gpio_keys {
- compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
-
- user_pb {
- label = "user_pb";
- gpios = <&pioB 10 1>;
- linux,code = <28>;
- gpio-key,wakeup;
- };
- };
-
i2c@0 {
- status = "okay";
-
rv3029c2@56 {
compatible = "rv3029c2";
reg = <0x56>;
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 215816f1775f..e8a4e58f1b82 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -11,7 +11,5 @@ obj-$(CONFIG_DMABOUNCE) += dmabounce.o
obj-$(CONFIG_SHARP_LOCOMO) += locomo.o
obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o
obj-$(CONFIG_SHARP_SCOOP) += scoop.o
-obj-$(CONFIG_ARCH_IXP2000) += uengine.o
-obj-$(CONFIG_ARCH_IXP23XX) += uengine.o
obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o
obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c
index dcb13494ca0d..c4110d1b1f2d 100644
--- a/arch/arm/common/it8152.c
+++ b/arch/arm/common/it8152.c
@@ -222,7 +222,7 @@ static int it8152_pci_write_config(struct pci_bus *bus,
return PCIBIOS_SUCCESSFUL;
}
-static struct pci_ops it8152_ops = {
+struct pci_ops it8152_ops = {
.read = it8152_pci_read_config,
.write = it8152_pci_write_config,
};
@@ -346,9 +346,4 @@ void pcibios_set_master(struct pci_dev *dev)
}
-struct pci_bus * __init it8152_pci_scan_bus(int nr, struct pci_sys_data *sys)
-{
- return pci_scan_root_bus(NULL, nr, &it8152_ops, sys, &sys->resources);
-}
-
EXPORT_SYMBOL(dma_set_coherent_mask);
diff --git a/arch/arm/common/uengine.c b/arch/arm/common/uengine.c
deleted file mode 100644
index bef408f3d76c..000000000000
--- a/arch/arm/common/uengine.c
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- * Generic library functions for the microengines found on the Intel
- * IXP2000 series of network processors.
- *
- * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <asm/hardware/uengine.h>
-
-#if defined(CONFIG_ARCH_IXP2000)
-#define IXP_UENGINE_CSR_VIRT_BASE IXP2000_UENGINE_CSR_VIRT_BASE
-#define IXP_PRODUCT_ID IXP2000_PRODUCT_ID
-#define IXP_MISC_CONTROL IXP2000_MISC_CONTROL
-#define IXP_RESET1 IXP2000_RESET1
-#else
-#if defined(CONFIG_ARCH_IXP23XX)
-#define IXP_UENGINE_CSR_VIRT_BASE IXP23XX_UENGINE_CSR_VIRT_BASE
-#define IXP_PRODUCT_ID IXP23XX_PRODUCT_ID
-#define IXP_MISC_CONTROL IXP23XX_MISC_CONTROL
-#define IXP_RESET1 IXP23XX_RESET1
-#else
-#error unknown platform
-#endif
-#endif
-
-#define USTORE_ADDRESS 0x000
-#define USTORE_DATA_LOWER 0x004
-#define USTORE_DATA_UPPER 0x008
-#define CTX_ENABLES 0x018
-#define CC_ENABLE 0x01c
-#define CSR_CTX_POINTER 0x020
-#define INDIRECT_CTX_STS 0x040
-#define ACTIVE_CTX_STS 0x044
-#define INDIRECT_CTX_SIG_EVENTS 0x048
-#define INDIRECT_CTX_WAKEUP_EVENTS 0x050
-#define NN_PUT 0x080
-#define NN_GET 0x084
-#define TIMESTAMP_LOW 0x0c0
-#define TIMESTAMP_HIGH 0x0c4
-#define T_INDEX_BYTE_INDEX 0x0f4
-#define LOCAL_CSR_STATUS 0x180
-
-u32 ixp2000_uengine_mask;
-
-static void *ixp2000_uengine_csr_area(int uengine)
-{
- return ((void *)IXP_UENGINE_CSR_VIRT_BASE) + (uengine << 10);
-}
-
-/*
- * LOCAL_CSR_STATUS=1 after a read or write to a microengine's CSR
- * space means that the microengine we tried to access was also trying
- * to access its own CSR space on the same clock cycle as we did. When
- * this happens, we lose the arbitration process by default, and the
- * read or write we tried to do was not actually performed, so we try
- * again until it succeeds.
- */
-u32 ixp2000_uengine_csr_read(int uengine, int offset)
-{
- void *uebase;
- u32 *local_csr_status;
- u32 *reg;
- u32 value;
-
- uebase = ixp2000_uengine_csr_area(uengine);
-
- local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS);
- reg = (u32 *)(uebase + offset);
- do {
- value = ixp2000_reg_read(reg);
- } while (ixp2000_reg_read(local_csr_status) & 1);
-
- return value;
-}
-EXPORT_SYMBOL(ixp2000_uengine_csr_read);
-
-void ixp2000_uengine_csr_write(int uengine, int offset, u32 value)
-{
- void *uebase;
- u32 *local_csr_status;
- u32 *reg;
-
- uebase = ixp2000_uengine_csr_area(uengine);
-
- local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS);
- reg = (u32 *)(uebase + offset);
- do {
- ixp2000_reg_write(reg, value);
- } while (ixp2000_reg_read(local_csr_status) & 1);
-}
-EXPORT_SYMBOL(ixp2000_uengine_csr_write);
-
-void ixp2000_uengine_reset(u32 uengine_mask)
-{
- u32 value;
-
- value = ixp2000_reg_read(IXP_RESET1) & ~ixp2000_uengine_mask;
-
- uengine_mask &= ixp2000_uengine_mask;
- ixp2000_reg_wrb(IXP_RESET1, value | uengine_mask);
- ixp2000_reg_wrb(IXP_RESET1, value);
-}
-EXPORT_SYMBOL(ixp2000_uengine_reset);
-
-void ixp2000_uengine_set_mode(int uengine, u32 mode)
-{
- /*
- * CTL_STR_PAR_EN: unconditionally enable parity checking on
- * control store.
- */
- mode |= 0x10000000;
- ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mode);
-
- /*
- * Enable updating of condition codes.
- */
- ixp2000_uengine_csr_write(uengine, CC_ENABLE, 0x00002000);
-
- /*
- * Initialise other per-microengine registers.
- */
- ixp2000_uengine_csr_write(uengine, NN_PUT, 0x00);
- ixp2000_uengine_csr_write(uengine, NN_GET, 0x00);
- ixp2000_uengine_csr_write(uengine, T_INDEX_BYTE_INDEX, 0);
-}
-EXPORT_SYMBOL(ixp2000_uengine_set_mode);
-
-static int make_even_parity(u32 x)
-{
- return hweight32(x) & 1;
-}
-
-static void ustore_write(int uengine, u64 insn)
-{
- /*
- * Generate even parity for top and bottom 20 bits.
- */
- insn |= (u64)make_even_parity((insn >> 20) & 0x000fffff) << 41;
- insn |= (u64)make_even_parity(insn & 0x000fffff) << 40;
-
- /*
- * Write to microstore. The second write auto-increments
- * the USTORE_ADDRESS index register.
- */
- ixp2000_uengine_csr_write(uengine, USTORE_DATA_LOWER, (u32)insn);
- ixp2000_uengine_csr_write(uengine, USTORE_DATA_UPPER, (u32)(insn >> 32));
-}
-
-void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns)
-{
- int i;
-
- /*
- * Start writing to microstore at address 0.
- */
- ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x80000000);
- for (i = 0; i < insns; i++) {
- u64 insn;
-
- insn = (((u64)ucode[0]) << 32) |
- (((u64)ucode[1]) << 24) |
- (((u64)ucode[2]) << 16) |
- (((u64)ucode[3]) << 8) |
- ((u64)ucode[4]);
- ucode += 5;
-
- ustore_write(uengine, insn);
- }
-
- /*
- * Pad with a few NOPs at the end (to avoid the microengine
- * aborting as it prefetches beyond the last instruction), unless
- * we run off the end of the instruction store first, at which
- * point the address register will wrap back to zero.
- */
- for (i = 0; i < 4; i++) {
- u32 addr;
-
- addr = ixp2000_uengine_csr_read(uengine, USTORE_ADDRESS);
- if (addr == 0x80000000)
- break;
- ustore_write(uengine, 0xf0000c0300ULL);
- }
-
- /*
- * End programming.
- */
- ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x00000000);
-}
-EXPORT_SYMBOL(ixp2000_uengine_load_microcode);
-
-void ixp2000_uengine_init_context(int uengine, int context, int pc)
-{
- /*
- * Select the right context for indirect access.
- */
- ixp2000_uengine_csr_write(uengine, CSR_CTX_POINTER, context);
-
- /*
- * Initialise signal masks to immediately go to Ready state.
- */
- ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_SIG_EVENTS, 1);
- ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_WAKEUP_EVENTS, 1);
-
- /*
- * Set program counter.
- */
- ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_STS, pc);
-}
-EXPORT_SYMBOL(ixp2000_uengine_init_context);
-
-void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask)
-{
- u32 mask;
-
- /*
- * Enable the specified context to go to Executing state.
- */
- mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES);
- mask |= ctx_mask << 8;
- ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask);
-}
-EXPORT_SYMBOL(ixp2000_uengine_start_contexts);
-
-void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask)
-{
- u32 mask;
-
- /*
- * Disable the Ready->Executing transition. Note that this
- * does not stop the context until it voluntarily yields.
- */
- mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES);
- mask &= ~(ctx_mask << 8);
- ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask);
-}
-EXPORT_SYMBOL(ixp2000_uengine_stop_contexts);
-
-static int check_ixp_type(struct ixp2000_uengine_code *c)
-{
- u32 product_id;
- u32 rev;
-
- product_id = ixp2000_reg_read(IXP_PRODUCT_ID);
- if (((product_id >> 16) & 0x1f) != 0)
- return 0;
-
- switch ((product_id >> 8) & 0xff) {
-#ifdef CONFIG_ARCH_IXP2000
- case 0: /* IXP2800 */
- if (!(c->cpu_model_bitmask & 4))
- return 0;
- break;
-
- case 1: /* IXP2850 */
- if (!(c->cpu_model_bitmask & 8))
- return 0;
- break;
-
- case 2: /* IXP2400 */
- if (!(c->cpu_model_bitmask & 2))
- return 0;
- break;
-#endif
-
-#ifdef CONFIG_ARCH_IXP23XX
- case 4: /* IXP23xx */
- if (!(c->cpu_model_bitmask & 0x3f0))
- return 0;
- break;
-#endif
-
- default:
- return 0;
- }
-
- rev = product_id & 0xff;
- if (rev < c->cpu_min_revision || rev > c->cpu_max_revision)
- return 0;
-
- return 1;
-}
-
-static void generate_ucode(u8 *ucode, u32 *gpr_a, u32 *gpr_b)
-{
- int offset;
- int i;
-
- offset = 0;
-
- for (i = 0; i < 128; i++) {
- u8 b3;
- u8 b2;
- u8 b1;
- u8 b0;
-
- b3 = (gpr_a[i] >> 24) & 0xff;
- b2 = (gpr_a[i] >> 16) & 0xff;
- b1 = (gpr_a[i] >> 8) & 0xff;
- b0 = gpr_a[i] & 0xff;
-
- /* immed[@ai, (b1 << 8) | b0] */
- /* 11110000 0000VVVV VVVV11VV VVVVVV00 1IIIIIII */
- ucode[offset++] = 0xf0;
- ucode[offset++] = (b1 >> 4);
- ucode[offset++] = (b1 << 4) | 0x0c | (b0 >> 6);
- ucode[offset++] = (b0 << 2);
- ucode[offset++] = 0x80 | i;
-
- /* immed_w1[@ai, (b3 << 8) | b2] */
- /* 11110100 0100VVVV VVVV11VV VVVVVV00 1IIIIIII */
- ucode[offset++] = 0xf4;
- ucode[offset++] = 0x40 | (b3 >> 4);
- ucode[offset++] = (b3 << 4) | 0x0c | (b2 >> 6);
- ucode[offset++] = (b2 << 2);
- ucode[offset++] = 0x80 | i;
- }
-
- for (i = 0; i < 128; i++) {
- u8 b3;
- u8 b2;
- u8 b1;
- u8 b0;
-
- b3 = (gpr_b[i] >> 24) & 0xff;
- b2 = (gpr_b[i] >> 16) & 0xff;
- b1 = (gpr_b[i] >> 8) & 0xff;
- b0 = gpr_b[i] & 0xff;
-
- /* immed[@bi, (b1 << 8) | b0] */
- /* 11110000 0000VVVV VVVV001I IIIIII11 VVVVVVVV */
- ucode[offset++] = 0xf0;
- ucode[offset++] = (b1 >> 4);
- ucode[offset++] = (b1 << 4) | 0x02 | (i >> 6);
- ucode[offset++] = (i << 2) | 0x03;
- ucode[offset++] = b0;
-
- /* immed_w1[@bi, (b3 << 8) | b2] */
- /* 11110100 0100VVVV VVVV001I IIIIII11 VVVVVVVV */
- ucode[offset++] = 0xf4;
- ucode[offset++] = 0x40 | (b3 >> 4);
- ucode[offset++] = (b3 << 4) | 0x02 | (i >> 6);
- ucode[offset++] = (i << 2) | 0x03;
- ucode[offset++] = b2;
- }
-
- /* ctx_arb[kill] */
- ucode[offset++] = 0xe0;
- ucode[offset++] = 0x00;
- ucode[offset++] = 0x01;
- ucode[offset++] = 0x00;
- ucode[offset++] = 0x00;
-}
-
-static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c)
-{
- int per_ctx_regs;
- u32 *gpr_a;
- u32 *gpr_b;
- u8 *ucode;
- int i;
-
- gpr_a = kzalloc(128 * sizeof(u32), GFP_KERNEL);
- gpr_b = kzalloc(128 * sizeof(u32), GFP_KERNEL);
- ucode = kmalloc(513 * 5, GFP_KERNEL);
- if (gpr_a == NULL || gpr_b == NULL || ucode == NULL) {
- kfree(ucode);
- kfree(gpr_b);
- kfree(gpr_a);
- return 1;
- }
-
- per_ctx_regs = 16;
- if (c->uengine_parameters & IXP2000_UENGINE_4_CONTEXTS)
- per_ctx_regs = 32;
-
- for (i = 0; i < 256; i++) {
- struct ixp2000_reg_value *r = c->initial_reg_values + i;
- u32 *bank;
- int inc;
- int j;
-
- if (r->reg == -1)
- break;
-
- bank = (r->reg & 0x400) ? gpr_b : gpr_a;
- inc = (r->reg & 0x80) ? 128 : per_ctx_regs;
-
- j = r->reg & 0x7f;
- while (j < 128) {
- bank[j] = r->value;
- j += inc;
- }
- }
-
- generate_ucode(ucode, gpr_a, gpr_b);
- ixp2000_uengine_load_microcode(uengine, ucode, 513);
- ixp2000_uengine_init_context(uengine, 0, 0);
- ixp2000_uengine_start_contexts(uengine, 0x01);
- for (i = 0; i < 100; i++) {
- u32 status;
-
- status = ixp2000_uengine_csr_read(uengine, ACTIVE_CTX_STS);
- if (!(status & 0x80000000))
- break;
- }
- ixp2000_uengine_stop_contexts(uengine, 0x01);
-
- kfree(ucode);
- kfree(gpr_b);
- kfree(gpr_a);
-
- return !!(i == 100);
-}
-
-int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c)
-{
- int ctx;
-
- if (!check_ixp_type(c))
- return 1;
-
- if (!(ixp2000_uengine_mask & (1 << uengine)))
- return 1;
-
- ixp2000_uengine_reset(1 << uengine);
- ixp2000_uengine_set_mode(uengine, c->uengine_parameters);
- if (set_initial_registers(uengine, c))
- return 1;
- ixp2000_uengine_load_microcode(uengine, c->insns, c->num_insns);
-
- for (ctx = 0; ctx < 8; ctx++)
- ixp2000_uengine_init_context(uengine, ctx, 0);
-
- return 0;
-}
-EXPORT_SYMBOL(ixp2000_uengine_load);
-
-
-static int __init ixp2000_uengine_init(void)
-{
- int uengine;
- u32 value;
-
- /*
- * Determine number of microengines present.
- */
- switch ((ixp2000_reg_read(IXP_PRODUCT_ID) >> 8) & 0x1fff) {
-#ifdef CONFIG_ARCH_IXP2000
- case 0: /* IXP2800 */
- case 1: /* IXP2850 */
- ixp2000_uengine_mask = 0x00ff00ff;
- break;
-
- case 2: /* IXP2400 */
- ixp2000_uengine_mask = 0x000f000f;
- break;
-#endif
-
-#ifdef CONFIG_ARCH_IXP23XX
- case 4: /* IXP23xx */
- ixp2000_uengine_mask = (*IXP23XX_EXP_CFG_FUSE >> 8) & 0xf;
- break;
-#endif
-
- default:
- printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n",
- (unsigned int)ixp2000_reg_read(IXP_PRODUCT_ID));
- ixp2000_uengine_mask = 0x00000000;
- break;
- }
-
- /*
- * Reset microengines.
- */
- ixp2000_uengine_reset(ixp2000_uengine_mask);
-
- /*
- * Synchronise timestamp counters across all microengines.
- */
- value = ixp2000_reg_read(IXP_MISC_CONTROL);
- ixp2000_reg_wrb(IXP_MISC_CONTROL, value & ~0x80);
- for (uengine = 0; uengine < 32; uengine++) {
- if (ixp2000_uengine_mask & (1 << uengine)) {
- ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0);
- ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0);
- }
- }
- ixp2000_reg_wrb(IXP_MISC_CONTROL, value | 0x80);
-
- return 0;
-}
-
-subsys_initcall(ixp2000_uengine_init);
diff --git a/arch/arm/common/via82c505.c b/arch/arm/common/via82c505.c
index 1171a5010aea..6cb362e56d29 100644
--- a/arch/arm/common/via82c505.c
+++ b/arch/arm/common/via82c505.c
@@ -51,7 +51,7 @@ via82c505_write_config(struct pci_bus *bus, unsigned int devfn, int where,
return PCIBIOS_SUCCESSFUL;
}
-static struct pci_ops via82c505_ops = {
+struct pci_ops via82c505_ops = {
.read = via82c505_read_config,
.write = via82c505_write_config,
};
@@ -81,12 +81,3 @@ int __init via82c505_setup(int nr, struct pci_sys_data *sys)
{
return (nr == 0);
}
-
-struct pci_bus * __init via82c505_scan_bus(int nr, struct pci_sys_data *sysdata)
-{
- if (nr == 0)
- return pci_scan_root_bus(NULL, 0, &via82c505_ops, sysdata,
- &sysdata->resources);
-
- return NULL;
-}
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index 7e288f96cedf..e0d538803cc3 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -39,6 +39,7 @@
* struct vic_device - VIC PM device
* @irq: The IRQ number for the base of the VIC.
* @base: The register base for the VIC.
+ * @valid_sources: A bitmask of valid interrupts
* @resume_sources: A bitmask of interrupts for resume.
* @resume_irqs: The IRQs enabled for resume.
* @int_select: Save for VIC_INT_SELECT.
@@ -50,6 +51,7 @@
struct vic_device {
void __iomem *base;
int irq;
+ u32 valid_sources;
u32 resume_sources;
u32 resume_irqs;
u32 int_select;
@@ -164,10 +166,32 @@ static int __init vic_pm_init(void)
late_initcall(vic_pm_init);
#endif /* CONFIG_PM */
+static struct irq_chip vic_chip;
+
+static int vic_irqdomain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct vic_device *v = d->host_data;
+
+ /* Skip invalid IRQs, only register handlers for the real ones */
+ if (!(v->valid_sources & (1 << hwirq)))
+ return -ENOTSUPP;
+ irq_set_chip_and_handler(irq, &vic_chip, handle_level_irq);
+ irq_set_chip_data(irq, v->base);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ return 0;
+}
+
+static struct irq_domain_ops vic_irqdomain_ops = {
+ .map = vic_irqdomain_map,
+ .xlate = irq_domain_xlate_onetwocell,
+};
+
/**
* vic_register() - Register a VIC.
* @base: The base address of the VIC.
* @irq: The base IRQ for the VIC.
+ * @valid_sources: bitmask of valid interrupts
* @resume_sources: bitmask of interrupts allowed for resume sources.
* @node: The device tree node associated with the VIC.
*
@@ -178,7 +202,8 @@ late_initcall(vic_pm_init);
* This also configures the IRQ domain for the VIC.
*/
static void __init vic_register(void __iomem *base, unsigned int irq,
- u32 resume_sources, struct device_node *node)
+ u32 valid_sources, u32 resume_sources,
+ struct device_node *node)
{
struct vic_device *v;
@@ -189,11 +214,12 @@ static void __init vic_register(void __iomem *base, unsigned int irq,
v = &vic_devices[vic_id];
v->base = base;
+ v->valid_sources = valid_sources;
v->resume_sources = resume_sources;
v->irq = irq;
vic_id++;
- v->domain = irq_domain_add_legacy(node, 32, irq, 0,
- &irq_domain_simple_ops, v);
+ v->domain = irq_domain_add_legacy(node, fls(valid_sources), irq, 0,
+ &vic_irqdomain_ops, v);
}
static void vic_ack_irq(struct irq_data *d)
@@ -287,23 +313,6 @@ static void __init vic_clear_interrupts(void __iomem *base)
}
}
-static void __init vic_set_irq_sources(void __iomem *base,
- unsigned int irq_start, u32 vic_sources)
-{
- unsigned int i;
-
- for (i = 0; i < 32; i++) {
- if (vic_sources & (1 << i)) {
- unsigned int irq = irq_start + i;
-
- irq_set_chip_and_handler(irq, &vic_chip,
- handle_level_irq);
- irq_set_chip_data(irq, base);
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
- }
- }
-}
-
/*
* The PL190 cell from ARM has been modified by ST to handle 64 interrupts.
* The original cell has 32 interrupts, while the modified one has 64,
@@ -338,8 +347,7 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
writel(32, base + VIC_PL190_DEF_VECT_ADDR);
}
- vic_set_irq_sources(base, irq_start, vic_sources);
- vic_register(base, irq_start, 0, node);
+ vic_register(base, irq_start, vic_sources, 0, node);
}
void __init __vic_init(void __iomem *base, unsigned int irq_start,
@@ -379,9 +387,7 @@ void __init __vic_init(void __iomem *base, unsigned int irq_start,
vic_init2(base);
- vic_set_irq_sources(base, irq_start, vic_sources);
-
- vic_register(base, irq_start, resume_sources, node);
+ vic_register(base, irq_start, vic_sources, resume_sources, node);
}
/**
diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
new file mode 100644
index 000000000000..ddc9fe6a78ac
--- /dev/null
+++ b/arch/arm/configs/armadillo800eva_defconfig
@@ -0,0 +1,142 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_R8A7740=y
+CONFIG_MACH_ARMADILLO800EVA=y
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BPREDICT_DISABLE=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_ERRATA_430973=y
+CONFIG_ARM_ERRATA_458693=y
+CONFIG_ARM_ERRATA_460075=y
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_ARM_ERRATA_743622=y
+CONFIG_ARM_ERRATA_751472=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_FORCE_MAX_ZONEORDER=13
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096"
+CONFIG_CMDLINE_FORCE=y
+CONFIG_KEXEC=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_SH_ETH=y
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ST1232=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=8
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_SH_MOBILE=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_SH_MOBILE_LCDC=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_SH4_FSI=y
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_RENESAS_USBHS=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_RENESAS_USBHS_UDC=y
+CONFIG_USB_ETH=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHI=y
+CONFIG_MMC_SH_MMCIF=y
+CONFIG_UIO=y
+CONFIG_UIO_PDRV_GENIRQ=y
+# CONFIG_DNOTIFY is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_XZ_DEC=y
diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig
new file mode 100644
index 000000000000..67bc571ed0c3
--- /dev/null
+++ b/arch/arm/configs/at91_dt_defconfig
@@ -0,0 +1,196 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_SOC_AT91SAM9260=y
+CONFIG_SOC_AT91SAM9263=y
+CONFIG_SOC_AT91SAM9G45=y
+CONFIG_SOC_AT91SAM9X5=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_AT91_TIMER_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw"
+CONFIG_KEXEC=y
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+CONFIG_IPV6_SIT_6RD=y
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_GLUEBI=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_ATMEL_PWM=y
+CONFIG_ATMEL_TCLIB=y
+CONFIG_EEPROM_93CX6=m
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_DAVICOM_PHY=y
+CONFIG_MICREL_PHY=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_POLLDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=480
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=272
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_SERIO is not set
+CONFIG_LEGACY_PTY_COUNT=4
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+CONFIG_SSB=m
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_ATMEL=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_ATMEL_LCDC=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_ACORN_8x8=y
+CONFIG_FONT_MINI_4x6=y
+CONFIG_LOGO=y
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_FTDI_SIO=y
+CONFIG_USB_SERIAL_PL2303=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_AT91=m
+CONFIG_USB_ATMEL_USBA=m
+CONFIG_USB_ETH=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_ACM_MS=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_MMC=y
+CONFIG_MMC_ATMELMCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91RM9200=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_DMADEVICES=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_FANOTIFY=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC7=m
+CONFIG_AVERAGE=y
diff --git a/arch/arm/configs/at91rm9200_defconfig b/arch/arm/configs/at91rm9200_defconfig
index bbe4e1a1f5d8..d54e2acd3ab1 100644
--- a/arch/arm/configs/at91rm9200_defconfig
+++ b/arch/arm/configs/at91rm9200_defconfig
@@ -14,6 +14,7 @@ CONFIG_MODULE_SRCVERSION_ALL=y
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91RM9200=y
CONFIG_MACH_ONEARM=y
CONFIG_ARCH_AT91RM9200DK=y
CONFIG_MACH_AT91RM9200EK=y
diff --git a/arch/arm/configs/bcmring_defconfig b/arch/arm/configs/bcmring_defconfig
index 795374d48f81..9e6a8fe13164 100644
--- a/arch/arm/configs/bcmring_defconfig
+++ b/arch/arm/configs/bcmring_defconfig
@@ -11,7 +11,7 @@ CONFIG_KALLSYMS_EXTRA_PASS=y
# CONFIG_TIMERFD is not set
# CONFIG_EVENTFD is not set
# CONFIG_AIO is not set
-CONFIG_PERF_COUNTERS=y
+CONFIG_PERF_EVENTS=y
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_SLUB_DEBUG is not set
# CONFIG_COMPAT_BRK is not set
diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig
index 6b31cb60daab..09a02963cf58 100644
--- a/arch/arm/configs/imx_v4_v5_defconfig
+++ b/arch/arm/configs/imx_v4_v5_defconfig
@@ -92,6 +92,7 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_MC13783=m
# CONFIG_SERIO is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_8250=m
@@ -107,7 +108,8 @@ CONFIG_SPI_SPIDEV=y
CONFIG_W1=y
CONFIG_W1_MASTER_MXC=y
CONFIG_W1_SLAVE_THERM=y
-# CONFIG_HWMON is not set
+CONFIG_HWMON=m
+CONFIG_SENSORS_MC13783_ADC=m
CONFIG_WATCHDOG=y
CONFIG_IMX2_WDT=y
CONFIG_MFD_MC13XXX=y
diff --git a/arch/arm/configs/ixp2000_defconfig b/arch/arm/configs/ixp2000_defconfig
deleted file mode 100644
index 8405aded97a3..000000000000
--- a/arch/arm/configs/ixp2000_defconfig
+++ /dev/null
@@ -1,99 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-# CONFIG_HOTPLUG is not set
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_ARCH_IXP2000=y
-CONFIG_ARCH_ENP2611=y
-CONFIG_ARCH_IXDP2400=y
-CONFIG_ARCH_IXDP2800=y
-CONFIG_ARCH_IXDP2401=y
-CONFIG_ARCH_IXDP2801=y
-# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
-# CONFIG_ARM_THUMB is not set
-CONFIG_CPU_BIG_ENDIAN=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0"
-CONFIG_FPE_NWFPE=y
-CONFIG_FPE_NWFPE_XP=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_SYN_COOKIES=y
-CONFIG_IPV6=y
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
-# CONFIG_IPV6_SIT is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_COMPLEX_MAPPINGS=y
-CONFIG_MTD_IXP2000=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_EEPROM_LEGACY=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_NET_PCI=y
-CONFIG_CS89x0=y
-CONFIG_E100=y
-CONFIG_ENP2611_MSF_NET=y
-CONFIG_WAN=y
-CONFIG_HDLC=y
-CONFIG_HDLC_RAW=y
-CONFIG_HDLC_CISCO=y
-CONFIG_HDLC_FR=y
-CONFIG_HDLC_PPP=y
-CONFIG_DLCI=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=3
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IXP2000=y
-CONFIG_WATCHDOG=y
-CONFIG_IXP2000_WATCHDOG=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/ixp23xx_defconfig b/arch/arm/configs/ixp23xx_defconfig
deleted file mode 100644
index 688717612e91..000000000000
--- a/arch/arm/configs/ixp23xx_defconfig
+++ /dev/null
@@ -1,105 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_ARCH_IXP23XX=y
-CONFIG_MACH_ESPRESSO=y
-CONFIG_MACH_IXDP2351=y
-CONFIG_MACH_ROADRUNNER=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_CPU_BIG_ENDIAN=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp"
-CONFIG_FPE_NWFPE=y
-CONFIG_FPE_NWFPE_XP=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_SYN_COOKIES=y
-CONFIG_IPV6=y
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
-# CONFIG_IPV6_SIT is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_FW_LOADER is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_COMPLEX_MAPPINGS=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_EEPROM_LEGACY=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_SIIMAGE=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_NET_PCI=y
-CONFIG_E100=y
-CONFIG_E1000=y
-CONFIG_WAN=y
-CONFIG_HDLC=y
-CONFIG_HDLC_RAW=y
-CONFIG_HDLC_CISCO=y
-CONFIG_HDLC_FR=y
-CONFIG_HDLC_PPP=y
-CONFIG_DLCI=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_WATCHDOG=y
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_MON=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_UHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig
new file mode 100644
index 000000000000..e3ebc20ed0a7
--- /dev/null
+++ b/arch/arm/configs/kzm9g_defconfig
@@ -0,0 +1,139 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_SHMOBILE=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+CONFIG_ARCH_SH73A0=y
+CONFIG_MACH_KZM9G=y
+CONFIG_MEMORY_START=0x41000000
+CONFIG_MEMORY_SIZE=0x1f000000
+CONFIG_ARM_ERRATA_743622=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_HIGHMEM=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=sh-sci.4,115200"
+CONFIG_KEXEC=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_IRDA=y
+CONFIG_SH_IRDA=y
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+CONFIG_SMSC911X=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_SPARSEKMAP=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ST1232=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=9
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_SH_MOBILE=y
+CONFIG_GPIO_PCF857X=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FB_SH_MOBILE_LCDC=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_FB_SH_MOBILE_MERAM=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_SH4_FSI=y
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_R8A66597_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_SDHI=y
+CONFIG_MMC_SH_MMCIF=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_RTC_CLASS=y
+CONFIG_DMADEVICES=y
+CONFIG_SH_DMAE=y
+CONFIG_ASYNC_TX_DMA=y
+CONFIG_STAGING=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRC16=y
diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig
index fb2088171ca9..4fa60547494a 100644
--- a/arch/arm/configs/lpc32xx_defconfig
+++ b/arch/arm/configs/lpc32xx_defconfig
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_LOG_BUF_SHIFT=16
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_BLK_DEV_INITRD=y
@@ -10,6 +10,7 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_EMBEDDED=y
CONFIG_SLAB=y
+CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
@@ -21,6 +22,8 @@ CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
CONFIG_CMDLINE="console=ttyS0,115200n81 root=/dev/ram0"
CONFIG_CPU_IDLE=y
CONFIG_FPE_NWFPE=y
@@ -40,7 +43,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
# CONFIG_WIRELESS is not set
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_FW_LOADER is not set
@@ -55,13 +59,24 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=1
CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_MISC_DEVICES=y
CONFIG_EEPROM_AT25=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_NETDEVICES=y
CONFIG_MII=y
-CONFIG_PHYLIB=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_LPC_ENET=y
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
CONFIG_SMSC_PHY=y
# CONFIG_WLAN is not set
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
@@ -97,16 +112,22 @@ CONFIG_SND_SEQUENCER=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_SEQUENCER_OSS=y
-CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
# CONFIG_SND_VERBOSE_PROCFS is not set
+CONFIG_SND_DEBUG=y
+CONFIG_SND_DEBUG_VERBOSE=y
# CONFIG_SND_DRIVERS is not set
# CONFIG_SND_ARM is not set
# CONFIG_SND_SPI is not set
CONFIG_SND_SOC=y
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=y
+CONFIG_USB_OHCI_HCD=y
CONFIG_USB_STORAGE=y
-CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_LPC32XX=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_ARMMMCI=y
@@ -114,10 +135,21 @@ CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_DS1374=y
+CONFIG_RTC_DRV_PCF8563=y
CONFIG_RTC_DRV_LPC32XX=y
+CONFIG_DMADEVICES=y
+CONFIG_AMBA_PL08X=y
+CONFIG_STAGING=y
+CONFIG_IIO=y
+CONFIG_LPC32XX_ADC=y
CONFIG_EXT2_FS=y
CONFIG_AUTOFS4_FS=y
CONFIG_MSDOS_FS=y
diff --git a/arch/arm/configs/nhk8815_defconfig b/arch/arm/configs/nhk8815_defconfig
index 37207d1bf44b..bf123c5384d4 100644
--- a/arch/arm/configs/nhk8815_defconfig
+++ b/arch/arm/configs/nhk8815_defconfig
@@ -97,6 +97,7 @@ CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_GPIO=y
CONFIG_DEBUG_GPIO=y
+CONFIG_PINCTRL_NOMADIK=y
# CONFIG_HWMON is not set
# CONFIG_VGA_CONSOLE is not set
CONFIG_RTC_CLASS=y
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index d5f00d7eb075..9854ff4279e0 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -98,6 +98,7 @@ CONFIG_LIBERTAS_USB=m
CONFIG_LIBERTAS_SDIO=m
CONFIG_LIBERTAS_DEBUG=y
CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC95XX=y
CONFIG_USB_ALI_M5632=y
CONFIG_USB_AN2720=y
CONFIG_USB_EPSON2888=y
@@ -175,6 +176,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_DEVICEFS=y
CONFIG_USB_SUSPEND=y
CONFIG_USB_MON=y
+CONFIG_USB_EHCI_HCD=y
CONFIG_USB_WDM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_LIBUSUAL=y
diff --git a/arch/arm/configs/rpc_defconfig b/arch/arm/configs/rpc_defconfig
index af278f7a2246..00515ef9782d 100644
--- a/arch/arm/configs/rpc_defconfig
+++ b/arch/arm/configs/rpc_defconfig
@@ -8,8 +8,6 @@ CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_ARCH_RPC=y
-CONFIG_CPU_ARM610=y
-CONFIG_CPU_ARM710=y
CONFIG_CPU_SA110=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
diff --git a/arch/arm/configs/spear3xx_defconfig b/arch/arm/configs/spear3xx_defconfig
index fea7e1f026a3..7ed42912d69a 100644
--- a/arch/arm/configs/spear3xx_defconfig
+++ b/arch/arm/configs/spear3xx_defconfig
@@ -2,33 +2,67 @@ CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
+CONFIG_PARTITION_ADVANCED=y
CONFIG_PLAT_SPEAR=y
-CONFIG_BOARD_SPEAR300_EVB=y
-CONFIG_BOARD_SPEAR310_EVB=y
-CONFIG_BOARD_SPEAR320_EVB=y
+CONFIG_MACH_SPEAR300=y
+CONFIG_MACH_SPEAR310=y
+CONFIG_MACH_SPEAR320=y
CONFIG_BINFMT_MISC=y
+CONFIG_NET=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSMC=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+CONFIG_STMMAC_ETH=y
+# CONFIG_WLAN is not set
CONFIG_INPUT_FF_MEMLESS=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_SPEAR=y
# CONFIG_INPUT_MOUSE is not set
+# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
# CONFIG_HW_RANDOM is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=8192
+CONFIG_I2C=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_SPI=y
+CONFIG_SPI_PL022=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_PL061=y
# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_ARM_SP805_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_ARMCLCD=y
# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SPEAR=y
+CONFIG_RTC_CLASS=y
+CONFIG_DMADEVICES=y
+CONFIG_AMBA_PL08X=y
+CONFIG_DMATEST=m
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_SECURITY=y
@@ -39,8 +73,6 @@ CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
CONFIG_TMPFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=m
@@ -48,6 +80,4 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_INFO=y
-# CONFIG_CRC32 is not set
diff --git a/arch/arm/configs/spear6xx_defconfig b/arch/arm/configs/spear6xx_defconfig
index cef2e836afd2..cf94bc73a0e0 100644
--- a/arch/arm/configs/spear6xx_defconfig
+++ b/arch/arm/configs/spear6xx_defconfig
@@ -2,29 +2,58 @@ CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
+CONFIG_PARTITION_ADVANCED=y
CONFIG_PLAT_SPEAR=y
CONFIG_ARCH_SPEAR6XX=y
-CONFIG_BOARD_SPEAR600_EVB=y
+CONFIG_BOARD_SPEAR600_DT=y
CONFIG_BINFMT_MISC=y
+CONFIG_NET=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSMC=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+CONFIG_STMMAC_ETH=y
+# CONFIG_WLAN is not set
CONFIG_INPUT_FF_MEMLESS=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=8192
+CONFIG_I2C=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_SPI=y
+CONFIG_SPI_PL022=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_PL061=y
# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_ARM_SP805_WATCHDOG=y
# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_RTC_CLASS=y
+CONFIG_DMADEVICES=y
+CONFIG_AMBA_PL08X=y
+CONFIG_DMATEST=m
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_SECURITY=y
@@ -35,8 +64,6 @@ CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
CONFIG_TMPFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=m
@@ -44,6 +71,4 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_INFO=y
-# CONFIG_CRC32 is not set
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
new file mode 100644
index 000000000000..ed2e95d46e29
--- /dev/null
+++ b/arch/arm/include/asm/arch_timer.h
@@ -0,0 +1,19 @@
+#ifndef __ASMARM_ARCH_TIMER_H
+#define __ASMARM_ARCH_TIMER_H
+
+#ifdef CONFIG_ARM_ARCH_TIMER
+int arch_timer_of_register(void);
+int arch_timer_sched_clock_init(void);
+#else
+static inline int arch_timer_of_register(void)
+{
+ return -ENXIO;
+}
+
+static inline int arch_timer_sched_clock_init(void)
+{
+ return -ENXIO;
+}
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index d5d8d5c72682..004c1bc95d2b 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -101,7 +101,7 @@ struct cpu_cache_fns {
void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
void (*coherent_kern_range)(unsigned long, unsigned long);
- void (*coherent_user_range)(unsigned long, unsigned long);
+ int (*coherent_user_range)(unsigned long, unsigned long);
void (*flush_kern_dcache_area)(void *, size_t);
void (*dma_map_area)(const void *, size_t, int);
@@ -142,7 +142,7 @@ extern void __cpuc_flush_kern_all(void);
extern void __cpuc_flush_user_all(void);
extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
-extern void __cpuc_coherent_user_range(unsigned long, unsigned long);
+extern int __cpuc_coherent_user_range(unsigned long, unsigned long);
extern void __cpuc_flush_dcache_area(void *, size_t);
/*
@@ -249,7 +249,7 @@ extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr
* Harvard caches are synchronised for the user space address range.
* This is used for the ARM private sys_cacheflush system call.
*/
-#define flush_cache_user_range(vma,start,end) \
+#define flush_cache_user_range(start,end) \
__cpuc_coherent_user_range((start) & PAGE_MASK, PAGE_ALIGN(end))
/*
diff --git a/arch/arm/include/asm/cmpxchg.h b/arch/arm/include/asm/cmpxchg.h
index d41d7cbf0ada..7eb18c1d8d6c 100644
--- a/arch/arm/include/asm/cmpxchg.h
+++ b/arch/arm/include/asm/cmpxchg.h
@@ -229,66 +229,19 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
(unsigned long)(n), \
sizeof(*(ptr))))
-#ifndef CONFIG_CPU_V6 /* min ARCH >= ARMv6K */
-
-/*
- * Note : ARMv7-M (currently unsupported by Linux) does not support
- * ldrexd/strexd. If ARMv7-M is ever supported by the Linux kernel, it should
- * not be allowed to use __cmpxchg64.
- */
-static inline unsigned long long __cmpxchg64(volatile void *ptr,
- unsigned long long old,
- unsigned long long new)
-{
- register unsigned long long oldval asm("r0");
- register unsigned long long __old asm("r2") = old;
- register unsigned long long __new asm("r4") = new;
- unsigned long res;
-
- do {
- asm volatile(
- " @ __cmpxchg8\n"
- " ldrexd %1, %H1, [%2]\n"
- " mov %0, #0\n"
- " teq %1, %3\n"
- " teqeq %H1, %H3\n"
- " strexdeq %0, %4, %H4, [%2]\n"
- : "=&r" (res), "=&r" (oldval)
- : "r" (ptr), "Ir" (__old), "r" (__new)
- : "memory", "cc");
- } while (res);
-
- return oldval;
-}
-
-static inline unsigned long long __cmpxchg64_mb(volatile void *ptr,
- unsigned long long old,
- unsigned long long new)
-{
- unsigned long long ret;
-
- smp_mb();
- ret = __cmpxchg64(ptr, old, new);
- smp_mb();
-
- return ret;
-}
-
-#define cmpxchg64(ptr,o,n) \
- ((__typeof__(*(ptr)))__cmpxchg64_mb((ptr), \
- (unsigned long long)(o), \
- (unsigned long long)(n)))
-
-#define cmpxchg64_local(ptr,o,n) \
- ((__typeof__(*(ptr)))__cmpxchg64((ptr), \
- (unsigned long long)(o), \
- (unsigned long long)(n)))
-
-#else /* min ARCH = ARMv6 */
-
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#endif
+#define cmpxchg64(ptr, o, n) \
+ ((__typeof__(*(ptr)))atomic64_cmpxchg(container_of((ptr), \
+ atomic64_t, \
+ counter), \
+ (unsigned long)(o), \
+ (unsigned long)(n)))
+
+#define cmpxchg64_local(ptr, o, n) \
+ ((__typeof__(*(ptr)))local64_cmpxchg(container_of((ptr), \
+ local64_t, \
+ a), \
+ (unsigned long)(o), \
+ (unsigned long)(n)))
#endif /* __LINUX_ARM_ARCH__ >= 6 */
diff --git a/arch/arm/include/asm/cpu.h b/arch/arm/include/asm/cpu.h
index 793968173bef..d797223b39d5 100644
--- a/arch/arm/include/asm/cpu.h
+++ b/arch/arm/include/asm/cpu.h
@@ -16,7 +16,6 @@
struct cpuinfo_arm {
struct cpu cpu;
#ifdef CONFIG_SMP
- struct task_struct *idle;
unsigned int loops_per_jiffy;
#endif
};
diff --git a/arch/arm/include/asm/glue-df.h b/arch/arm/include/asm/glue-df.h
index 354d571e8bcc..8cacbcda76da 100644
--- a/arch/arm/include/asm/glue-df.h
+++ b/arch/arm/include/asm/glue-df.h
@@ -31,14 +31,6 @@
#undef CPU_DABORT_HANDLER
#undef MULTI_DABORT
-#if defined(CONFIG_CPU_ARM610)
-# ifdef CPU_DABORT_HANDLER
-# define MULTI_DABORT 1
-# else
-# define CPU_DABORT_HANDLER cpu_arm6_data_abort
-# endif
-#endif
-
#if defined(CONFIG_CPU_ARM710)
# ifdef CPU_DABORT_HANDLER
# define MULTI_DABORT 1
diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
index e2be7f142668..ac1dd54724b6 100644
--- a/arch/arm/include/asm/glue-proc.h
+++ b/arch/arm/include/asm/glue-proc.h
@@ -23,15 +23,6 @@
* CPU_NAME - the prefix for CPU related functions
*/
-#ifdef CONFIG_CPU_ARM610
-# ifdef CPU_NAME
-# undef MULTI_CPU
-# define MULTI_CPU
-# else
-# define CPU_NAME cpu_arm6
-# endif
-#endif
-
#ifdef CONFIG_CPU_ARM7TDMI
# ifdef CPU_NAME
# undef MULTI_CPU
@@ -41,15 +32,6 @@
# endif
#endif
-#ifdef CONFIG_CPU_ARM710
-# ifdef CPU_NAME
-# undef MULTI_CPU
-# define MULTI_CPU
-# else
-# define CPU_NAME cpu_arm7
-# endif
-#endif
-
#ifdef CONFIG_CPU_ARM720T
# ifdef CPU_NAME
# undef MULTI_CPU
diff --git a/arch/arm/include/asm/hardware/cs89712.h b/arch/arm/include/asm/hardware/cs89712.h
deleted file mode 100644
index f75626933e94..000000000000
--- a/arch/arm/include/asm/hardware/cs89712.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * arch/arm/include/asm/hardware/cs89712.h
- *
- * This file contains the hardware definitions of the CS89712
- * additional internal registers.
- *
- * Copyright (C) 2001 Thomas Gleixner autronix automation <gleixner@autronix.de>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#ifndef __ASM_HARDWARE_CS89712_H
-#define __ASM_HARDWARE_CS89712_H
-
-/*
-* CS89712 additional registers
-*/
-
-#define PCDR 0x0002 /* Port C Data register ---------------------------- */
-#define PCDDR 0x0042 /* Port C Data Direction register ------------------ */
-#define SDCONF 0x2300 /* SDRAM Configuration register ---------------------*/
-#define SDRFPR 0x2340 /* SDRAM Refresh period register --------------------*/
-
-#define SDCONF_ACTIVE (1 << 10)
-#define SDCONF_CLKCTL (1 << 9)
-#define SDCONF_WIDTH_4 (0 << 7)
-#define SDCONF_WIDTH_8 (1 << 7)
-#define SDCONF_WIDTH_16 (2 << 7)
-#define SDCONF_WIDTH_32 (3 << 7)
-#define SDCONF_SIZE_16 (0 << 5)
-#define SDCONF_SIZE_64 (1 << 5)
-#define SDCONF_SIZE_128 (2 << 5)
-#define SDCONF_SIZE_256 (3 << 5)
-#define SDCONF_CASLAT_2 (2)
-#define SDCONF_CASLAT_3 (3)
-
-#endif /* __ASM_HARDWARE_CS89712_H */
diff --git a/arch/arm/include/asm/hardware/ep7212.h b/arch/arm/include/asm/hardware/ep7212.h
deleted file mode 100644
index 3b43bbeaf1db..000000000000
--- a/arch/arm/include/asm/hardware/ep7212.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * arch/arm/include/asm/hardware/ep7212.h
- *
- * This file contains the hardware definitions of the EP7212 internal
- * registers.
- *
- * Copyright (C) 2000 Deep Blue Solutions Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#ifndef __ASM_HARDWARE_EP7212_H
-#define __ASM_HARDWARE_EP7212_H
-
-/*
- * define EP7212_BASE to be the base address of the region
- * you want to access.
- */
-
-#define EP7212_PHYS_BASE (0x80000000)
-
-#ifndef __ASSEMBLY__
-#define ep_readl(off) __raw_readl(EP7212_BASE + (off))
-#define ep_writel(val,off) __raw_writel(val, EP7212_BASE + (off))
-#endif
-
-/*
- * These registers are specific to the EP7212 only
- */
-#define DAIR 0x2000
-#define DAIR0 0x2040
-#define DAIDR1 0x2080
-#define DAIDR2 0x20c0
-#define DAISR 0x2100
-#define SYSCON3 0x2200
-#define INTSR3 0x2240
-#define INTMR3 0x2280
-#define LEDFLSH 0x22c0
-
-#define DAIR_DAIEN (1 << 16)
-#define DAIR_ECS (1 << 17)
-#define DAIR_LCTM (1 << 19)
-#define DAIR_LCRM (1 << 20)
-#define DAIR_RCTM (1 << 21)
-#define DAIR_RCRM (1 << 22)
-#define DAIR_LBM (1 << 23)
-
-#define DAIDR2_FIFOEN (1 << 15)
-#define DAIDR2_FIFOLEFT (0x0d << 16)
-#define DAIDR2_FIFORIGHT (0x11 << 16)
-
-#define DAISR_RCTS (1 << 0)
-#define DAISR_RCRS (1 << 1)
-#define DAISR_LCTS (1 << 2)
-#define DAISR_LCRS (1 << 3)
-#define DAISR_RCTU (1 << 4)
-#define DAISR_RCRO (1 << 5)
-#define DAISR_LCTU (1 << 6)
-#define DAISR_LCRO (1 << 7)
-#define DAISR_RCNF (1 << 8)
-#define DAISR_RCNE (1 << 9)
-#define DAISR_LCNF (1 << 10)
-#define DAISR_LCNE (1 << 11)
-#define DAISR_FIFO (1 << 12)
-
-#define SYSCON3_ADCCON (1 << 0)
-#define SYSCON3_DAISEL (1 << 3)
-#define SYSCON3_ADCCKNSEN (1 << 4)
-#define SYSCON3_FASTWAKE (1 << 8)
-#define SYSCON3_DAIEN (1 << 9)
-
-#endif /* __ASM_HARDWARE_EP7212_H */
diff --git a/arch/arm/include/asm/hardware/it8152.h b/arch/arm/include/asm/hardware/it8152.h
index 73f84fa4f366..d36a73d7c0e8 100644
--- a/arch/arm/include/asm/hardware/it8152.h
+++ b/arch/arm/include/asm/hardware/it8152.h
@@ -110,6 +110,6 @@ extern void it8152_irq_demux(unsigned int irq, struct irq_desc *desc);
extern void it8152_init_irq(void);
extern int it8152_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
extern int it8152_pci_setup(int nr, struct pci_sys_data *sys);
-extern struct pci_bus *it8152_pci_scan_bus(int nr, struct pci_sys_data *sys);
+extern struct pci_ops it8152_ops;
#endif /* __ASM_HARDWARE_IT8152_H */
diff --git a/arch/arm/include/asm/hardware/uengine.h b/arch/arm/include/asm/hardware/uengine.h
deleted file mode 100644
index b442d65c6593..000000000000
--- a/arch/arm/include/asm/hardware/uengine.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Generic library functions for the microengines found on the Intel
- * IXP2000 series of network processors.
- *
- * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- */
-
-#ifndef __IXP2000_UENGINE_H
-#define __IXP2000_UENGINE_H
-
-extern u32 ixp2000_uengine_mask;
-
-struct ixp2000_uengine_code
-{
- u32 cpu_model_bitmask;
- u8 cpu_min_revision;
- u8 cpu_max_revision;
-
- u32 uengine_parameters;
-
- struct ixp2000_reg_value {
- int reg;
- u32 value;
- } *initial_reg_values;
-
- int num_insns;
- u8 *insns;
-};
-
-u32 ixp2000_uengine_csr_read(int uengine, int offset);
-void ixp2000_uengine_csr_write(int uengine, int offset, u32 value);
-void ixp2000_uengine_reset(u32 uengine_mask);
-void ixp2000_uengine_set_mode(int uengine, u32 mode);
-void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns);
-void ixp2000_uengine_init_context(int uengine, int context, int pc);
-void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask);
-void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask);
-int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c);
-
-#define IXP2000_UENGINE_8_CONTEXTS 0x00000000
-#define IXP2000_UENGINE_4_CONTEXTS 0x80000000
-#define IXP2000_UENGINE_PRN_UPDATE_EVERY 0x40000000
-#define IXP2000_UENGINE_PRN_UPDATE_ON_ACCESS 0x00000000
-#define IXP2000_UENGINE_NN_FROM_SELF 0x00100000
-#define IXP2000_UENGINE_NN_FROM_PREVIOUS 0x00000000
-#define IXP2000_UENGINE_ASSERT_EMPTY_AT_3 0x000c0000
-#define IXP2000_UENGINE_ASSERT_EMPTY_AT_2 0x00080000
-#define IXP2000_UENGINE_ASSERT_EMPTY_AT_1 0x00040000
-#define IXP2000_UENGINE_ASSERT_EMPTY_AT_0 0x00000000
-#define IXP2000_UENGINE_LM_ADDR1_GLOBAL 0x00020000
-#define IXP2000_UENGINE_LM_ADDR1_PER_CONTEXT 0x00000000
-#define IXP2000_UENGINE_LM_ADDR0_GLOBAL 0x00010000
-#define IXP2000_UENGINE_LM_ADDR0_PER_CONTEXT 0x00000000
-
-
-#endif
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index d943b7d20f11..26c511fddf8f 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -12,13 +12,14 @@
#define __ASM_MACH_PCI_H
struct pci_sys_data;
+struct pci_ops;
struct pci_bus;
struct hw_pci {
#ifdef CONFIG_PCI_DOMAINS
int domain;
#endif
- struct list_head buses;
+ struct pci_ops *ops;
int nr_controllers;
int (*setup)(int nr, struct pci_sys_data *);
struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
@@ -45,16 +46,10 @@ struct pci_sys_data {
u8 (*swizzle)(struct pci_dev *, u8 *);
/* IRQ mapping */
int (*map_irq)(const struct pci_dev *, u8, u8);
- struct hw_pci *hw;
void *private_data; /* platform controller private data */
};
/*
- * This is the standard PCI-PCI bridge swizzling algorithm.
- */
-#define pci_std_swizzle pci_common_swizzle
-
-/*
* Call this with your hw_pci struct to initialise the PCI system.
*/
void pci_common_init(struct hw_pci *);
@@ -62,22 +57,22 @@ void pci_common_init(struct hw_pci *);
/*
* PCI controllers
*/
+extern struct pci_ops iop3xx_ops;
extern int iop3xx_pci_setup(int nr, struct pci_sys_data *);
-extern struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *);
extern void iop3xx_pci_preinit(void);
extern void iop3xx_pci_preinit_cond(void);
+extern struct pci_ops dc21285_ops;
extern int dc21285_setup(int nr, struct pci_sys_data *);
-extern struct pci_bus *dc21285_scan_bus(int nr, struct pci_sys_data *);
extern void dc21285_preinit(void);
extern void dc21285_postinit(void);
+extern struct pci_ops via82c505_ops;
extern int via82c505_setup(int nr, struct pci_sys_data *);
-extern struct pci_bus *via82c505_scan_bus(int nr, struct pci_sys_data *);
extern void via82c505_init(void *sysdata);
+extern struct pci_ops pci_v3_ops;
extern int pci_v3_setup(int nr, struct pci_sys_data *);
-extern struct pci_bus *pci_v3_scan_bus(int nr, struct pci_sys_data *);
extern void pci_v3_preinit(void);
extern void pci_v3_postinit(void);
diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h
index f73c908b7fa0..6ca945f534ab 100644
--- a/arch/arm/include/asm/mach/time.h
+++ b/arch/arm/include/asm/mach/time.h
@@ -42,4 +42,9 @@ struct sys_timer {
extern void timer_tick(void);
+struct timespec;
+typedef void (*clock_access_fn)(struct timespec *);
+extern int register_persistent_clock(clock_access_fn read_boot,
+ clock_access_fn read_persistent);
+
#endif
diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
index b8e580a297e4..14965658a923 100644
--- a/arch/arm/include/asm/mmu.h
+++ b/arch/arm/include/asm/mmu.h
@@ -34,11 +34,4 @@ typedef struct {
#endif
-/*
- * switch_mm() may do a full cache flush over the context switch,
- * so enable interrupts over the context switch to avoid high
- * latency.
- */
-#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
-
#endif
diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h
index a0b3cac0547c..0306bc642c0d 100644
--- a/arch/arm/include/asm/mmu_context.h
+++ b/arch/arm/include/asm/mmu_context.h
@@ -43,45 +43,104 @@ void __check_kvm_seq(struct mm_struct *mm);
#define ASID_FIRST_VERSION (1 << ASID_BITS)
extern unsigned int cpu_last_asid;
-#ifdef CONFIG_SMP
-DECLARE_PER_CPU(struct mm_struct *, current_mm);
-#endif
void __init_new_context(struct task_struct *tsk, struct mm_struct *mm);
void __new_context(struct mm_struct *mm);
+void cpu_set_reserved_ttbr0(void);
-static inline void check_context(struct mm_struct *mm)
+static inline void switch_new_context(struct mm_struct *mm)
{
- /*
- * This code is executed with interrupts enabled. Therefore,
- * mm->context.id cannot be updated to the latest ASID version
- * on a different CPU (and condition below not triggered)
- * without first getting an IPI to reset the context. The
- * alternative is to take a read_lock on mm->context.id_lock
- * (after changing its type to rwlock_t).
- */
- if (unlikely((mm->context.id ^ cpu_last_asid) >> ASID_BITS))
- __new_context(mm);
+ unsigned long flags;
+
+ __new_context(mm);
+
+ local_irq_save(flags);
+ cpu_switch_mm(mm->pgd, mm);
+ local_irq_restore(flags);
+}
+static inline void check_and_switch_context(struct mm_struct *mm,
+ struct task_struct *tsk)
+{
if (unlikely(mm->context.kvm_seq != init_mm.context.kvm_seq))
__check_kvm_seq(mm);
+
+ /*
+ * Required during context switch to avoid speculative page table
+ * walking with the wrong TTBR.
+ */
+ cpu_set_reserved_ttbr0();
+
+ if (!((mm->context.id ^ cpu_last_asid) >> ASID_BITS))
+ /*
+ * The ASID is from the current generation, just switch to the
+ * new pgd. This condition is only true for calls from
+ * context_switch() and interrupts are already disabled.
+ */
+ cpu_switch_mm(mm->pgd, mm);
+ else if (irqs_disabled())
+ /*
+ * Defer the new ASID allocation until after the context
+ * switch critical region since __new_context() cannot be
+ * called with interrupts disabled (it sends IPIs).
+ */
+ set_ti_thread_flag(task_thread_info(tsk), TIF_SWITCH_MM);
+ else
+ /*
+ * That is a direct call to switch_mm() or activate_mm() with
+ * interrupts enabled and a new context.
+ */
+ switch_new_context(mm);
}
#define init_new_context(tsk,mm) (__init_new_context(tsk,mm),0)
-#else
-
-static inline void check_context(struct mm_struct *mm)
+#define finish_arch_post_lock_switch \
+ finish_arch_post_lock_switch
+static inline void finish_arch_post_lock_switch(void)
{
+ if (test_and_clear_thread_flag(TIF_SWITCH_MM))
+ switch_new_context(current->mm);
+}
+
+#else /* !CONFIG_CPU_HAS_ASID */
+
#ifdef CONFIG_MMU
+
+static inline void check_and_switch_context(struct mm_struct *mm,
+ struct task_struct *tsk)
+{
if (unlikely(mm->context.kvm_seq != init_mm.context.kvm_seq))
__check_kvm_seq(mm);
-#endif
+
+ if (irqs_disabled())
+ /*
+ * cpu_switch_mm() needs to flush the VIVT caches. To avoid
+ * high interrupt latencies, defer the call and continue
+ * running with the old mm. Since we only support UP systems
+ * on non-ASID CPUs, the old mm will remain valid until the
+ * finish_arch_post_lock_switch() call.
+ */
+ set_ti_thread_flag(task_thread_info(tsk), TIF_SWITCH_MM);
+ else
+ cpu_switch_mm(mm->pgd, mm);
}
+#define finish_arch_post_lock_switch \
+ finish_arch_post_lock_switch
+static inline void finish_arch_post_lock_switch(void)
+{
+ if (test_and_clear_thread_flag(TIF_SWITCH_MM)) {
+ struct mm_struct *mm = current->mm;
+ cpu_switch_mm(mm->pgd, mm);
+ }
+}
+
+#endif /* CONFIG_MMU */
+
#define init_new_context(tsk,mm) 0
-#endif
+#endif /* CONFIG_CPU_HAS_ASID */
#define destroy_context(mm) do { } while(0)
@@ -119,12 +178,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
__flush_icache_all();
#endif
if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) {
-#ifdef CONFIG_SMP
- struct mm_struct **crt_mm = &per_cpu(current_mm, cpu);
- *crt_mm = next;
-#endif
- check_context(next);
- cpu_switch_mm(next->pgd, next);
+ check_and_switch_context(next, tsk);
if (cache_is_vivt())
cpumask_clear_cpu(cpu, mm_cpumask(prev));
}
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h
index 5838361c48b3..ecf901902e44 100644
--- a/arch/arm/include/asm/page.h
+++ b/arch/arm/include/asm/page.h
@@ -34,7 +34,6 @@
* processor(s) we're building for.
*
* We have the following to choose from:
- * v3 - ARMv3
* v4wt - ARMv4 with writethrough cache, without minicache
* v4wb - ARMv4 with writeback cache, without minicache
* v4_mc - ARMv4 with minicache
@@ -44,14 +43,6 @@
#undef _USER
#undef MULTI_USER
-#ifdef CONFIG_CPU_COPY_V3
-# ifdef _USER
-# define MULTI_USER 1
-# else
-# define _USER v3
-# endif
-#endif
-
#ifdef CONFIG_CPU_COPY_V4WT
# ifdef _USER
# define MULTI_USER 1
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index 759af70f9a0a..b24903549d1c 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -69,8 +69,6 @@
*/
#define L_PTE_PRESENT (_AT(pteval_t, 3) << 0) /* Valid */
#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */
-#define L_PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) /* AttrIndx[0] */
-#define L_PTE_CACHEABLE (_AT(pteval_t, 1) << 3) /* AttrIndx[1] */
#define L_PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */
#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */
#define L_PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 5ac8d3d3e025..99afa7498260 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -77,9 +77,6 @@ struct task_struct;
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
unsigned long get_wchan(struct task_struct *p);
#if __LINUX_ARM_ARCH__ == 6 || defined(CONFIG_ARM_ERRATA_754327)
@@ -88,8 +85,6 @@ unsigned long get_wchan(struct task_struct *p);
#define cpu_relax() barrier()
#endif
-void cpu_idle_wait(void);
-
/*
* Create a new kernel thread
*/
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 451808ba1211..355ece523f41 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -249,6 +249,11 @@ static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
return regs->ARM_sp;
}
+static inline unsigned long user_stack_pointer(struct pt_regs *regs)
+{
+ return regs->ARM_sp;
+}
+
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h
new file mode 100644
index 000000000000..c334a23ddf75
--- /dev/null
+++ b/arch/arm/include/asm/syscall.h
@@ -0,0 +1,93 @@
+/*
+ * Access to user system call parameters and results
+ *
+ * See asm-generic/syscall.h for descriptions of what we must do here.
+ */
+
+#ifndef _ASM_ARM_SYSCALL_H
+#define _ASM_ARM_SYSCALL_H
+
+#include <linux/err.h>
+
+extern const unsigned long sys_call_table[];
+
+static inline int syscall_get_nr(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ return task_thread_info(task)->syscall;
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ regs->ARM_r0 = regs->ARM_ORIG_r0;
+}
+
+static inline long syscall_get_error(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ unsigned long error = regs->ARM_r0;
+ return IS_ERR_VALUE(error) ? error : 0;
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ return regs->ARM_r0;
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+ struct pt_regs *regs,
+ int error, long val)
+{
+ regs->ARM_r0 = (long) error ? error : val;
+}
+
+#define SYSCALL_MAX_ARGS 7
+
+static inline void syscall_get_arguments(struct task_struct *task,
+ struct pt_regs *regs,
+ unsigned int i, unsigned int n,
+ unsigned long *args)
+{
+ if (i + n > SYSCALL_MAX_ARGS) {
+ unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i;
+ unsigned int n_bad = n + i - SYSCALL_MAX_ARGS;
+ pr_warning("%s called with max args %d, handling only %d\n",
+ __func__, i + n, SYSCALL_MAX_ARGS);
+ memset(args_bad, 0, n_bad * sizeof(args[0]));
+ n = SYSCALL_MAX_ARGS - i;
+ }
+
+ if (i == 0) {
+ args[0] = regs->ARM_ORIG_r0;
+ args++;
+ i++;
+ n--;
+ }
+
+ memcpy(args, &regs->ARM_r0 + i, n * sizeof(args[0]));
+}
+
+static inline void syscall_set_arguments(struct task_struct *task,
+ struct pt_regs *regs,
+ unsigned int i, unsigned int n,
+ const unsigned long *args)
+{
+ if (i + n > SYSCALL_MAX_ARGS) {
+ pr_warning("%s called with max args %d, handling only %d\n",
+ __func__, i + n, SYSCALL_MAX_ARGS);
+ n = SYSCALL_MAX_ARGS - i;
+ }
+
+ if (i == 0) {
+ regs->ARM_ORIG_r0 = args[0];
+ args++;
+ i++;
+ n--;
+ }
+
+ memcpy(&regs->ARM_r0 + i, args, n * sizeof(args[0]));
+}
+
+#endif /* _ASM_ARM_SYSCALL_H */
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 0f04d84582e1..68388eb4946b 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -153,6 +153,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
#define TIF_RESTORE_SIGMASK 20
#define TIF_SECCOMP 21
+#define TIF_SWITCH_MM 22 /* deferred switch_mm */
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index 85fe61e73202..6e924d3a77eb 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -65,21 +65,6 @@
#define MULTI_TLB 1
#endif
-#define v3_tlb_flags (TLB_V3_FULL | TLB_V3_PAGE)
-
-#ifdef CONFIG_CPU_TLB_V3
-# define v3_possible_flags v3_tlb_flags
-# define v3_always_flags v3_tlb_flags
-# ifdef _TLB
-# define MULTI_TLB 1
-# else
-# define _TLB v3
-# endif
-#else
-# define v3_possible_flags 0
-# define v3_always_flags (-1UL)
-#endif
-
#define v4_tlb_flags (TLB_V4_U_FULL | TLB_V4_U_PAGE)
#ifdef CONFIG_CPU_TLB_V4WT
@@ -298,8 +283,7 @@ extern struct cpu_tlb_fns cpu_tlb;
* implemented the "%?" method, but this has been discontinued due to too
* many people getting it wrong.
*/
-#define possible_tlb_flags (v3_possible_flags | \
- v4_possible_flags | \
+#define possible_tlb_flags (v4_possible_flags | \
v4wbi_possible_flags | \
fr_possible_flags | \
v4wb_possible_flags | \
@@ -307,8 +291,7 @@ extern struct cpu_tlb_fns cpu_tlb;
v6wbi_possible_flags | \
v7wbi_possible_flags)
-#define always_tlb_flags (v3_always_flags & \
- v4_always_flags & \
+#define always_tlb_flags (v4_always_flags & \
v4wbi_always_flags & \
fr_always_flags & \
v4wb_always_flags & \
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 7b787d642af4..7ad2d5cf7008 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o
obj-$(CONFIG_SMP) += smp.o smp_tlb.o
obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
+obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o
@@ -81,4 +82,4 @@ head-y := head$(MMUEXT).o
obj-$(CONFIG_DEBUG_LL) += debug.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-extra-y := $(head-y) init_task.o vmlinux.lds
+extra-y := $(head-y) vmlinux.lds
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
new file mode 100644
index 000000000000..dd58035621f7
--- /dev/null
+++ b/arch/arm/kernel/arch_timer.c
@@ -0,0 +1,350 @@
+/*
+ * linux/arch/arm/kernel/arch_timer.c
+ *
+ * Copyright (C) 2011 ARM Ltd.
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/smp.h>
+#include <linux/cpu.h>
+#include <linux/jiffies.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+
+#include <asm/cputype.h>
+#include <asm/localtimer.h>
+#include <asm/arch_timer.h>
+#include <asm/system_info.h>
+#include <asm/sched_clock.h>
+
+static unsigned long arch_timer_rate;
+static int arch_timer_ppi;
+static int arch_timer_ppi2;
+
+static struct clock_event_device __percpu **arch_timer_evt;
+
+/*
+ * Architected system timer support.
+ */
+
+#define ARCH_TIMER_CTRL_ENABLE (1 << 0)
+#define ARCH_TIMER_CTRL_IT_MASK (1 << 1)
+#define ARCH_TIMER_CTRL_IT_STAT (1 << 2)
+
+#define ARCH_TIMER_REG_CTRL 0
+#define ARCH_TIMER_REG_FREQ 1
+#define ARCH_TIMER_REG_TVAL 2
+
+static void arch_timer_reg_write(int reg, u32 val)
+{
+ switch (reg) {
+ case ARCH_TIMER_REG_CTRL:
+ asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
+ break;
+ case ARCH_TIMER_REG_TVAL:
+ asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
+ break;
+ }
+
+ isb();
+}
+
+static u32 arch_timer_reg_read(int reg)
+{
+ u32 val;
+
+ switch (reg) {
+ case ARCH_TIMER_REG_CTRL:
+ asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
+ break;
+ case ARCH_TIMER_REG_FREQ:
+ asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
+ break;
+ case ARCH_TIMER_REG_TVAL:
+ asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
+ break;
+ default:
+ BUG();
+ }
+
+ return val;
+}
+
+static irqreturn_t arch_timer_handler(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+ unsigned long ctrl;
+
+ ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+ if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {
+ ctrl |= ARCH_TIMER_CTRL_IT_MASK;
+ arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static void arch_timer_disable(void)
+{
+ unsigned long ctrl;
+
+ ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+ ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
+ arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+}
+
+static void arch_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *clk)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ arch_timer_disable();
+ break;
+ default:
+ break;
+ }
+}
+
+static int arch_timer_set_next_event(unsigned long evt,
+ struct clock_event_device *unused)
+{
+ unsigned long ctrl;
+
+ ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+ ctrl |= ARCH_TIMER_CTRL_ENABLE;
+ ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
+
+ arch_timer_reg_write(ARCH_TIMER_REG_TVAL, evt);
+ arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+
+ return 0;
+}
+
+static int __cpuinit arch_timer_setup(struct clock_event_device *clk)
+{
+ /* Be safe... */
+ arch_timer_disable();
+
+ clk->features = CLOCK_EVT_FEAT_ONESHOT;
+ clk->name = "arch_sys_timer";
+ clk->rating = 450;
+ clk->set_mode = arch_timer_set_mode;
+ clk->set_next_event = arch_timer_set_next_event;
+ clk->irq = arch_timer_ppi;
+
+ clockevents_config_and_register(clk, arch_timer_rate,
+ 0xf, 0x7fffffff);
+
+ *__this_cpu_ptr(arch_timer_evt) = clk;
+
+ enable_percpu_irq(clk->irq, 0);
+ if (arch_timer_ppi2)
+ enable_percpu_irq(arch_timer_ppi2, 0);
+
+ return 0;
+}
+
+/* Is the optional system timer available? */
+static int local_timer_is_architected(void)
+{
+ return (cpu_architecture() >= CPU_ARCH_ARMv7) &&
+ ((read_cpuid_ext(CPUID_EXT_PFR1) >> 16) & 0xf) == 1;
+}
+
+static int arch_timer_available(void)
+{
+ unsigned long freq;
+
+ if (!local_timer_is_architected())
+ return -ENXIO;
+
+ if (arch_timer_rate == 0) {
+ arch_timer_reg_write(ARCH_TIMER_REG_CTRL, 0);
+ freq = arch_timer_reg_read(ARCH_TIMER_REG_FREQ);
+
+ /* Check the timer frequency. */
+ if (freq == 0) {
+ pr_warn("Architected timer frequency not available\n");
+ return -EINVAL;
+ }
+
+ arch_timer_rate = freq;
+ }
+
+ pr_info_once("Architected local timer running at %lu.%02luMHz.\n",
+ arch_timer_rate / 1000000, (arch_timer_rate / 10000) % 100);
+ return 0;
+}
+
+static inline cycle_t arch_counter_get_cntpct(void)
+{
+ u32 cvall, cvalh;
+
+ asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
+
+ return ((cycle_t) cvalh << 32) | cvall;
+}
+
+static inline cycle_t arch_counter_get_cntvct(void)
+{
+ u32 cvall, cvalh;
+
+ asm volatile("mrrc p15, 1, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
+
+ return ((cycle_t) cvalh << 32) | cvall;
+}
+
+static u32 notrace arch_counter_get_cntvct32(void)
+{
+ cycle_t cntvct = arch_counter_get_cntvct();
+
+ /*
+ * The sched_clock infrastructure only knows about counters
+ * with at most 32bits. Forget about the upper 24 bits for the
+ * time being...
+ */
+ return (u32)(cntvct & (u32)~0);
+}
+
+static cycle_t arch_counter_read(struct clocksource *cs)
+{
+ return arch_counter_get_cntpct();
+}
+
+static struct clocksource clocksource_counter = {
+ .name = "arch_sys_counter",
+ .rating = 400,
+ .read = arch_counter_read,
+ .mask = CLOCKSOURCE_MASK(56),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __cpuinit arch_timer_stop(struct clock_event_device *clk)
+{
+ pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n",
+ clk->irq, smp_processor_id());
+ disable_percpu_irq(clk->irq);
+ if (arch_timer_ppi2)
+ disable_percpu_irq(arch_timer_ppi2);
+ arch_timer_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
+}
+
+static struct local_timer_ops arch_timer_ops __cpuinitdata = {
+ .setup = arch_timer_setup,
+ .stop = arch_timer_stop,
+};
+
+static struct clock_event_device arch_timer_global_evt;
+
+static int __init arch_timer_register(void)
+{
+ int err;
+
+ err = arch_timer_available();
+ if (err)
+ return err;
+
+ arch_timer_evt = alloc_percpu(struct clock_event_device *);
+ if (!arch_timer_evt)
+ return -ENOMEM;
+
+ clocksource_register_hz(&clocksource_counter, arch_timer_rate);
+
+ err = request_percpu_irq(arch_timer_ppi, arch_timer_handler,
+ "arch_timer", arch_timer_evt);
+ if (err) {
+ pr_err("arch_timer: can't register interrupt %d (%d)\n",
+ arch_timer_ppi, err);
+ goto out_free;
+ }
+
+ if (arch_timer_ppi2) {
+ err = request_percpu_irq(arch_timer_ppi2, arch_timer_handler,
+ "arch_timer", arch_timer_evt);
+ if (err) {
+ pr_err("arch_timer: can't register interrupt %d (%d)\n",
+ arch_timer_ppi2, err);
+ arch_timer_ppi2 = 0;
+ goto out_free_irq;
+ }
+ }
+
+ err = local_timer_register(&arch_timer_ops);
+ if (err) {
+ /*
+ * We couldn't register as a local timer (could be
+ * because we're on a UP platform, or because some
+ * other local timer is already present...). Try as a
+ * global timer instead.
+ */
+ arch_timer_global_evt.cpumask = cpumask_of(0);
+ err = arch_timer_setup(&arch_timer_global_evt);
+ }
+
+ if (err)
+ goto out_free_irq;
+
+ return 0;
+
+out_free_irq:
+ free_percpu_irq(arch_timer_ppi, arch_timer_evt);
+ if (arch_timer_ppi2)
+ free_percpu_irq(arch_timer_ppi2, arch_timer_evt);
+
+out_free:
+ free_percpu(arch_timer_evt);
+
+ return err;
+}
+
+static const struct of_device_id arch_timer_of_match[] __initconst = {
+ { .compatible = "arm,armv7-timer", },
+ {},
+};
+
+int __init arch_timer_of_register(void)
+{
+ struct device_node *np;
+ u32 freq;
+
+ np = of_find_matching_node(NULL, arch_timer_of_match);
+ if (!np) {
+ pr_err("arch_timer: can't find DT node\n");
+ return -ENODEV;
+ }
+
+ /* Try to determine the frequency from the device tree or CNTFRQ */
+ if (!of_property_read_u32(np, "clock-frequency", &freq))
+ arch_timer_rate = freq;
+
+ arch_timer_ppi = irq_of_parse_and_map(np, 0);
+ arch_timer_ppi2 = irq_of_parse_and_map(np, 1);
+ pr_info("arch_timer: found %s irqs %d %d\n",
+ np->name, arch_timer_ppi, arch_timer_ppi2);
+
+ return arch_timer_register();
+}
+
+int __init arch_timer_sched_clock_init(void)
+{
+ int err;
+
+ err = arch_timer_available();
+ if (err)
+ return err;
+
+ setup_sched_clock(arch_counter_get_cntvct32, 32, arch_timer_rate);
+ return 0;
+}
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index ede5f7741c42..25552508c3fd 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -374,16 +374,29 @@ EXPORT_SYMBOL(pcibios_fixup_bus);
#endif
/*
- * Swizzle the device pin each time we cross a bridge.
- * This might update pin and returns the slot number.
+ * Swizzle the device pin each time we cross a bridge. If a platform does
+ * not provide a swizzle function, we perform the standard PCI swizzling.
+ *
+ * The default swizzling walks up the bus tree one level at a time, applying
+ * the standard swizzle function at each step, stopping when it finds the PCI
+ * root bus. This will return the slot number of the bridge device on the
+ * root bus and the interrupt pin on that device which should correspond
+ * with the downstream device interrupt.
+ *
+ * Platforms may override this, in which case the slot and pin returned
+ * depend entirely on the platform code. However, please note that the
+ * PCI standard swizzle is implemented on plug-in cards and Cardbus based
+ * PCI extenders, so it can not be ignored.
*/
static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 *pin)
{
struct pci_sys_data *sys = dev->sysdata;
- int slot = 0, oldpin = *pin;
+ int slot, oldpin = *pin;
if (sys->swizzle)
slot = sys->swizzle(dev, pin);
+ else
+ slot = pci_common_swizzle(dev, pin);
if (debug_pci)
printk("PCI: %s swizzling pin %d => pin %d slot %d\n",
@@ -410,7 +423,7 @@ static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
return irq;
}
-static void __init pcibios_init_hw(struct hw_pci *hw)
+static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
{
struct pci_sys_data *sys = NULL;
int ret;
@@ -424,7 +437,6 @@ static void __init pcibios_init_hw(struct hw_pci *hw)
#ifdef CONFIG_PCI_DOMAINS
sys->domain = hw->domain;
#endif
- sys->hw = hw;
sys->busnr = busnr;
sys->swizzle = hw->swizzle;
sys->map_irq = hw->map_irq;
@@ -440,14 +452,18 @@ static void __init pcibios_init_hw(struct hw_pci *hw)
&iomem_resource, sys->mem_offset);
}
- sys->bus = hw->scan(nr, sys);
+ if (hw->scan)
+ sys->bus = hw->scan(nr, sys);
+ else
+ sys->bus = pci_scan_root_bus(NULL, sys->busnr,
+ hw->ops, sys, &sys->resources);
if (!sys->bus)
panic("PCI: unable to scan bus!");
busnr = sys->bus->subordinate + 1;
- list_add(&sys->node, &hw->buses);
+ list_add(&sys->node, head);
} else {
kfree(sys);
if (ret < 0)
@@ -459,19 +475,18 @@ static void __init pcibios_init_hw(struct hw_pci *hw)
void __init pci_common_init(struct hw_pci *hw)
{
struct pci_sys_data *sys;
-
- INIT_LIST_HEAD(&hw->buses);
+ LIST_HEAD(head);
pci_add_flags(PCI_REASSIGN_ALL_RSRC);
if (hw->preinit)
hw->preinit();
- pcibios_init_hw(hw);
+ pcibios_init_hw(hw, &head);
if (hw->postinit)
hw->postinit();
pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
- list_for_each_entry(sys, &hw->buses, node) {
+ list_for_each_entry(sys, &head, node) {
struct pci_bus *bus = sys->bus;
if (!pci_has_flag(PCI_PROBE_ONLY)) {
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 7fd3ad048da9..437f0c426517 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -556,10 +556,6 @@ call_fpe:
#endif
tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27
tstne r0, #0x04000000 @ bit 26 set on both ARM and Thumb-2
-#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
- and r8, r0, #0x0f000000 @ mask out op-code bits
- teqne r8, #0x0f000000 @ SWI (ARM6/7 bug)?
-#endif
moveq pc, lr
get_thread_info r10 @ get current thread
and r8, r0, #0x00000f00 @ mask out CP number
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 54ee265dd819..7bd2d3cb8957 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -335,20 +335,6 @@ ENDPROC(ftrace_stub)
*-----------------------------------------------------------------------------
*/
- /* If we're optimising for StrongARM the resulting code won't
- run on an ARM7 and we can save a couple of instructions.
- --pb */
-#ifdef CONFIG_CPU_ARM710
-#define A710(code...) code
-.Larm710bug:
- ldmia sp, {r0 - lr}^ @ Get calling r0 - lr
- mov r0, r0
- add sp, sp, #S_FRAME_SIZE
- subs pc, lr, #4
-#else
-#define A710(code...)
-#endif
-
.align 5
ENTRY(vector_swi)
sub sp, sp, #S_FRAME_SIZE
@@ -379,9 +365,6 @@ ENTRY(vector_swi)
ldreq r10, [lr, #-4] @ get SWI instruction
#else
ldr r10, [lr, #-4] @ get SWI instruction
- A710( and ip, r10, #0x0f000000 @ check for SWI )
- A710( teq ip, #0x0f000000 )
- A710( bne .Larm710bug )
#endif
#ifdef CONFIG_CPU_ENDIAN_BE8
rev r10, r10 @ little endian instruction
@@ -392,26 +375,15 @@ ENTRY(vector_swi)
/*
* Pure EABI user space always put syscall number into scno (r7).
*/
- A710( ldr ip, [lr, #-4] @ get SWI instruction )
- A710( and ip, ip, #0x0f000000 @ check for SWI )
- A710( teq ip, #0x0f000000 )
- A710( bne .Larm710bug )
-
#elif defined(CONFIG_ARM_THUMB)
-
/* Legacy ABI only, possibly thumb mode. */
tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs
addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in
ldreq scno, [lr, #-4]
#else
-
/* Legacy ABI only. */
ldr scno, [lr, #-4] @ get SWI instruction
- A710( and ip, scno, #0x0f000000 @ check for SWI )
- A710( teq ip, #0x0f000000 )
- A710( bne .Larm710bug )
-
#endif
#ifdef CONFIG_ALIGNMENT_TRAP
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 3bf0c7f8b043..835898e7d704 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -277,10 +277,6 @@ __create_page_tables:
mov r3, r3, lsl #PMD_ORDER
add r0, r4, r3
- rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long)
- cmp r3, #0x0800 @ limit to 512MB
- movhi r3, #0x0800
- add r6, r0, r3
mov r3, r7, lsr #SECTION_SHIFT
ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
orr r3, r7, r3, lsl #SECTION_SHIFT
@@ -289,13 +285,10 @@ __create_page_tables:
#else
orr r3, r3, #PMD_SECT_XN
#endif
-1: str r3, [r0], #4
+ str r3, [r0], #4
#ifdef CONFIG_ARM_LPAE
str r7, [r0], #4
#endif
- add r3, r3, #1 << SECTION_SHIFT
- cmp r0, r6
- blo 1b
#else /* CONFIG_DEBUG_ICEDCC || CONFIG_DEBUG_SEMIHOSTING */
/* we don't need any serial debugging mappings */
diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c
deleted file mode 100644
index e7cbb50dc356..000000000000
--- a/arch/arm/kernel/init_task.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * linux/arch/arm/kernel/init_task.c
- */
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/mqueue.h>
-#include <linux/uaccess.h>
-
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is 8192-byte aligned due to the
- * way process stacks are handled. This is done by making sure
- * the linker maps this in the .text segment right after head.S,
- * and making head.S ensure the proper alignment.
- *
- * The things we do for performance..
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index b78af0cc6ef3..ab627a740fa3 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -489,8 +489,6 @@ armv6pmu_handle_irq(int irq_num,
*/
armv6_pmcr_write(pmcr);
- perf_sample_data_init(&data, 0);
-
cpuc = &__get_cpu_var(cpu_hw_events);
for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
struct perf_event *event = cpuc->events[idx];
@@ -509,7 +507,7 @@ armv6pmu_handle_irq(int irq_num,
hwc = &event->hw;
armpmu_event_update(event, hwc, idx);
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, 0, hwc->last_period);
if (!armpmu_event_set_period(event, hwc, idx))
continue;
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 00755d82e2f2..d3c536068162 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -1077,8 +1077,6 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
*/
regs = get_irq_regs();
- perf_sample_data_init(&data, 0);
-
cpuc = &__get_cpu_var(cpu_hw_events);
for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
struct perf_event *event = cpuc->events[idx];
@@ -1097,7 +1095,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
hwc = &event->hw;
armpmu_event_update(event, hwc, idx);
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, 0, hwc->last_period);
if (!armpmu_event_set_period(event, hwc, idx))
continue;
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
index 71a21e6712f5..e34e7254e652 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -248,8 +248,6 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
regs = get_irq_regs();
- perf_sample_data_init(&data, 0);
-
cpuc = &__get_cpu_var(cpu_hw_events);
for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
struct perf_event *event = cpuc->events[idx];
@@ -263,7 +261,7 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
hwc = &event->hw;
armpmu_event_update(event, hwc, idx);
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, 0, hwc->last_period);
if (!armpmu_event_set_period(event, hwc, idx))
continue;
@@ -588,8 +586,6 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
regs = get_irq_regs();
- perf_sample_data_init(&data, 0);
-
cpuc = &__get_cpu_var(cpu_hw_events);
for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
struct perf_event *event = cpuc->events[idx];
@@ -603,7 +599,7 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
hwc = &event->hw;
armpmu_event_update(event, hwc, idx);
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, 0, hwc->last_period);
if (!armpmu_event_set_period(event, hwc, idx))
continue;
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 2b7b017a20cd..19c95ea65b2f 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -157,26 +157,6 @@ EXPORT_SYMBOL(pm_power_off);
void (*arm_pm_restart)(char str, const char *cmd) = null_restart;
EXPORT_SYMBOL_GPL(arm_pm_restart);
-static void do_nothing(void *unused)
-{
-}
-
-/*
- * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
- * pm_idle and update to new pm_idle value. Required while changing pm_idle
- * handler on SMP systems.
- *
- * Caller must have changed pm_idle to the new value before the call. Old
- * pm_idle value will not be used by any CPU after the return of this function.
- */
-void cpu_idle_wait(void)
-{
- smp_mb();
- /* kick all the CPUs so that they exit out of pm_idle */
- smp_call_function(do_nothing, NULL, 1);
-}
-EXPORT_SYMBOL_GPL(cpu_idle_wait);
-
/*
* This is our default idle handler.
*/
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 9650c143afc1..14e38261cd31 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -24,6 +24,7 @@
#include <linux/hw_breakpoint.h>
#include <linux/regset.h>
#include <linux/audit.h>
+#include <linux/tracehook.h>
#include <asm/pgtable.h>
#include <asm/traps.h>
@@ -918,8 +919,6 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
if (!test_thread_flag(TIF_SYSCALL_TRACE))
return scno;
- if (!(current->ptrace & PT_PTRACED))
- return scno;
current_thread_info()->syscall = scno;
@@ -930,19 +929,11 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
ip = regs->ARM_ip;
regs->ARM_ip = why;
- /* the 0x80 provides a way for the tracing parent to distinguish
- between a syscall stop and SIGTRAP delivery */
- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- ? 0x80 : 0));
- /*
- * this isn't the same as continuing with a signal, but it will do
- * for normal use. strace only continues with a signal if the
- * stopping signal is not SIGTRAP. -brl
- */
- if (current->exit_code) {
- send_sig(current->exit_code, current, 1);
- current->exit_code = 0;
- }
+ if (why)
+ tracehook_report_syscall_exit(regs, 0);
+ else if (tracehook_report_syscall_entry(regs))
+ current_thread_info()->syscall = -1;
+
regs->ARM_ip = ip;
return current_thread_info()->syscall;
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index d68d1b694680..73d9a420850d 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -589,6 +589,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
*/
block_sigmask(ka, sig);
+ tracehook_signal_handler(sig, info, ka, regs, 0);
+
return 0;
}
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 8f4644659777..b735521a4a54 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -60,32 +60,11 @@ enum ipi_msg_type {
static DECLARE_COMPLETION(cpu_running);
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
{
- struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
- struct task_struct *idle = ci->idle;
int ret;
/*
- * Spawn a new process manually, if not already done.
- * Grab a pointer to its task struct so we can mess with it
- */
- if (!idle) {
- idle = fork_idle(cpu);
- if (IS_ERR(idle)) {
- printk(KERN_ERR "CPU%u: fork() failed\n", cpu);
- return PTR_ERR(idle);
- }
- ci->idle = idle;
- } else {
- /*
- * Since this idle thread is being re-used, call
- * init_idle() to reinitialize the thread structure.
- */
- init_idle(idle, cpu);
- }
-
- /*
* We need to tell the secondary core where to find
* its stack and the page tables.
*/
@@ -318,9 +297,6 @@ void __init smp_cpus_done(unsigned int max_cpus)
void __init smp_prepare_boot_cpu(void)
{
- unsigned int cpu = smp_processor_id();
-
- per_cpu(cpu_data, cpu).idle = current;
}
void __init smp_prepare_cpus(unsigned int max_cpus)
@@ -454,6 +430,9 @@ static struct local_timer_ops *lt_ops;
#ifdef CONFIG_LOCAL_TIMERS
int local_timer_register(struct local_timer_ops *ops)
{
+ if (!is_smp() || !setup_max_cpus)
+ return -ENXIO;
+
if (lt_ops)
return -EBUSY;
diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c
index 8f5dd7963356..b9f015e843d8 100644
--- a/arch/arm/kernel/smp_scu.c
+++ b/arch/arm/kernel/smp_scu.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <linux/io.h>
+#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <asm/cacheflush.h>
#include <asm/cputype.h>
@@ -74,7 +75,7 @@ void scu_enable(void __iomem *scu_base)
int scu_power_mode(void __iomem *scu_base, unsigned int mode)
{
unsigned int val;
- int cpu = smp_processor_id();
+ int cpu = cpu_logical_map(smp_processor_id());
if (mode > 3 || mode == 1 || cpu > 3)
return -EINVAL;
diff --git a/arch/arm/kernel/thumbee.c b/arch/arm/kernel/thumbee.c
index aab899764053..7b8403b76666 100644
--- a/arch/arm/kernel/thumbee.c
+++ b/arch/arm/kernel/thumbee.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <asm/cputype.h>
#include <asm/system_info.h>
#include <asm/thread_notify.h>
@@ -67,8 +68,7 @@ static int __init thumbee_init(void)
if (cpu_arch < CPU_ARCH_ARMv7)
return 0;
- /* processor feature register 0 */
- asm("mrc p15, 0, %0, c0, c1, 0\n" : "=r" (pfr0));
+ pfr0 = read_cpuid_ext(CPUID_EXT_PFR0);
if ((pfr0 & 0x0000f000) != 0x00001000)
return 0;
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index fe31b22f18fd..af2afb019672 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -110,6 +110,42 @@ void timer_tick(void)
}
#endif
+static void dummy_clock_access(struct timespec *ts)
+{
+ ts->tv_sec = 0;
+ ts->tv_nsec = 0;
+}
+
+static clock_access_fn __read_persistent_clock = dummy_clock_access;
+static clock_access_fn __read_boot_clock = dummy_clock_access;;
+
+void read_persistent_clock(struct timespec *ts)
+{
+ __read_persistent_clock(ts);
+}
+
+void read_boot_clock(struct timespec *ts)
+{
+ __read_boot_clock(ts);
+}
+
+int __init register_persistent_clock(clock_access_fn read_boot,
+ clock_access_fn read_persistent)
+{
+ /* Only allow the clockaccess functions to be registered once */
+ if (__read_persistent_clock == dummy_clock_access &&
+ __read_boot_clock == dummy_clock_access) {
+ if (read_boot)
+ __read_boot_clock = read_boot;
+ if (read_persistent)
+ __read_persistent_clock = read_persistent;
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS)
static int timer_suspend(void)
{
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 778454750a6c..3647170e9a16 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -479,14 +479,14 @@ static int bad_syscall(int n, struct pt_regs *regs)
return regs->ARM_r0;
}
-static inline void
+static inline int
do_cache_op(unsigned long start, unsigned long end, int flags)
{
struct mm_struct *mm = current->active_mm;
struct vm_area_struct *vma;
if (end < start || flags)
- return;
+ return -EINVAL;
down_read(&mm->mmap_sem);
vma = find_vma(mm, start);
@@ -496,9 +496,11 @@ do_cache_op(unsigned long start, unsigned long end, int flags)
if (end > vma->vm_end)
end = vma->vm_end;
- flush_cache_user_range(vma, start, end);
+ up_read(&mm->mmap_sem);
+ return flush_cache_user_range(start, end);
}
up_read(&mm->mmap_sem);
+ return -EINVAL;
}
/*
@@ -544,8 +546,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
* the specified region).
*/
case NR(cacheflush):
- do_cache_op(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2);
- return 0;
+ return do_cache_op(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2);
case NR(usr26):
if (!(elf_hwcap & HWCAP_26BIT))
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 0ade0acc1ed9..992769ae2599 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -17,30 +17,13 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
call_with_stack.o
mmu-y := clear_user.o copy_page.o getuser.o putuser.o
-
-# the code in uaccess.S is not preemption safe and
-# probably faster on ARMv3 only
-ifeq ($(CONFIG_PREEMPT),y)
- mmu-y += copy_from_user.o copy_to_user.o
-else
-ifneq ($(CONFIG_CPU_32v3),y)
- mmu-y += copy_from_user.o copy_to_user.o
-else
- mmu-y += uaccess.o
-endif
-endif
+mmu-y += copy_from_user.o copy_to_user.o
# using lib_ here won't override already available weak symbols
obj-$(CONFIG_UACCESS_WITH_MEMCPY) += uaccess_with_memcpy.o
-lib-$(CONFIG_MMU) += $(mmu-y)
-
-ifeq ($(CONFIG_CPU_32v3),y)
- lib-y += io-readsw-armv3.o io-writesw-armv3.o
-else
- lib-y += io-readsw-armv4.o io-writesw-armv4.o
-endif
-
+lib-$(CONFIG_MMU) += $(mmu-y)
+lib-y += io-readsw-armv4.o io-writesw-armv4.o
lib-$(CONFIG_ARCH_RPC) += ecard.o io-acorn.o floppydma.o
lib-$(CONFIG_ARCH_SHARK) += io-shark.o
diff --git a/arch/arm/lib/io-readsw-armv3.S b/arch/arm/lib/io-readsw-armv3.S
deleted file mode 100644
index 88487c8c4f23..000000000000
--- a/arch/arm/lib/io-readsw-armv3.S
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * linux/arch/arm/lib/io-readsw-armv3.S
- *
- * Copyright (C) 1995-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-
-.Linsw_bad_alignment:
- adr r0, .Linsw_bad_align_msg
- mov r2, lr
- b panic
-.Linsw_bad_align_msg:
- .asciz "insw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
- .align
-
-.Linsw_align: tst r1, #1
- bne .Linsw_bad_alignment
-
- ldr r3, [r0]
- strb r3, [r1], #1
- mov r3, r3, lsr #8
- strb r3, [r1], #1
-
- subs r2, r2, #1
- moveq pc, lr
-
-ENTRY(__raw_readsw)
- teq r2, #0 @ do we have to check for the zero len?
- moveq pc, lr
- tst r1, #3
- bne .Linsw_align
-
-.Linsw_aligned: mov ip, #0xff
- orr ip, ip, ip, lsl #8
- stmfd sp!, {r4, r5, r6, lr}
-
- subs r2, r2, #8
- bmi .Lno_insw_8
-
-.Linsw_8_lp: ldr r3, [r0]
- and r3, r3, ip
- ldr r4, [r0]
- orr r3, r3, r4, lsl #16
-
- ldr r4, [r0]
- and r4, r4, ip
- ldr r5, [r0]
- orr r4, r4, r5, lsl #16
-
- ldr r5, [r0]
- and r5, r5, ip
- ldr r6, [r0]
- orr r5, r5, r6, lsl #16
-
- ldr r6, [r0]
- and r6, r6, ip
- ldr lr, [r0]
- orr r6, r6, lr, lsl #16
-
- stmia r1!, {r3 - r6}
-
- subs r2, r2, #8
- bpl .Linsw_8_lp
-
- tst r2, #7
- ldmeqfd sp!, {r4, r5, r6, pc}
-
-.Lno_insw_8: tst r2, #4
- beq .Lno_insw_4
-
- ldr r3, [r0]
- and r3, r3, ip
- ldr r4, [r0]
- orr r3, r3, r4, lsl #16
-
- ldr r4, [r0]
- and r4, r4, ip
- ldr r5, [r0]
- orr r4, r4, r5, lsl #16
-
- stmia r1!, {r3, r4}
-
-.Lno_insw_4: tst r2, #2
- beq .Lno_insw_2
-
- ldr r3, [r0]
- and r3, r3, ip
- ldr r4, [r0]
- orr r3, r3, r4, lsl #16
-
- str r3, [r1], #4
-
-.Lno_insw_2: tst r2, #1
- ldrne r3, [r0]
- strneb r3, [r1], #1
- movne r3, r3, lsr #8
- strneb r3, [r1]
-
- ldmfd sp!, {r4, r5, r6, pc}
-
-
diff --git a/arch/arm/lib/io-writesw-armv3.S b/arch/arm/lib/io-writesw-armv3.S
deleted file mode 100644
index 49b800419e32..000000000000
--- a/arch/arm/lib/io-writesw-armv3.S
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * linux/arch/arm/lib/io-writesw-armv3.S
- *
- * Copyright (C) 1995-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-
-.Loutsw_bad_alignment:
- adr r0, .Loutsw_bad_align_msg
- mov r2, lr
- b panic
-.Loutsw_bad_align_msg:
- .asciz "outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
- .align
-
-.Loutsw_align: tst r1, #1
- bne .Loutsw_bad_alignment
-
- add r1, r1, #2
-
- ldr r3, [r1, #-4]
- mov r3, r3, lsr #16
- orr r3, r3, r3, lsl #16
- str r3, [r0]
- subs r2, r2, #1
- moveq pc, lr
-
-ENTRY(__raw_writesw)
- teq r2, #0 @ do we have to check for the zero len?
- moveq pc, lr
- tst r1, #3
- bne .Loutsw_align
-
- stmfd sp!, {r4, r5, r6, lr}
-
- subs r2, r2, #8
- bmi .Lno_outsw_8
-
-.Loutsw_8_lp: ldmia r1!, {r3, r4, r5, r6}
-
- mov ip, r3, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r3, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- mov ip, r4, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r4, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- mov ip, r5, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r5, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- mov ip, r6, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r6, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- subs r2, r2, #8
- bpl .Loutsw_8_lp
-
- tst r2, #7
- ldmeqfd sp!, {r4, r5, r6, pc}
-
-.Lno_outsw_8: tst r2, #4
- beq .Lno_outsw_4
-
- ldmia r1!, {r3, r4}
-
- mov ip, r3, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r3, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- mov ip, r4, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r4, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
-.Lno_outsw_4: tst r2, #2
- beq .Lno_outsw_2
-
- ldr r3, [r1], #4
-
- mov ip, r3, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r3, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
-.Lno_outsw_2: tst r2, #1
-
- ldrne r3, [r1]
-
- movne ip, r3, lsl #16
- orrne ip, ip, ip, lsr #16
- strne ip, [r0]
-
- ldmfd sp!, {r4, r5, r6, pc}
diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S
deleted file mode 100644
index 5c908b1cb8ed..000000000000
--- a/arch/arm/lib/uaccess.S
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * linux/arch/arm/lib/uaccess.S
- *
- * Copyright (C) 1995, 1996,1997,1998 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Routines to block copy data to/from user memory
- * These are highly optimised both for the 4k page size
- * and for various alignments.
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <asm/errno.h>
-#include <asm/domain.h>
-
- .text
-
-#define PAGE_SHIFT 12
-
-/* Prototype: int __copy_to_user(void *to, const char *from, size_t n)
- * Purpose : copy a block to user memory from kernel memory
- * Params : to - user memory
- * : from - kernel memory
- * : n - number of bytes to copy
- * Returns : Number of bytes NOT copied.
- */
-
-.Lc2u_dest_not_aligned:
- rsb ip, ip, #4
- cmp ip, #2
- ldrb r3, [r1], #1
-USER( TUSER( strb) r3, [r0], #1) @ May fault
- ldrgeb r3, [r1], #1
-USER( TUSER( strgeb) r3, [r0], #1) @ May fault
- ldrgtb r3, [r1], #1
-USER( TUSER( strgtb) r3, [r0], #1) @ May fault
- sub r2, r2, ip
- b .Lc2u_dest_aligned
-
-ENTRY(__copy_to_user)
- stmfd sp!, {r2, r4 - r7, lr}
- cmp r2, #4
- blt .Lc2u_not_enough
- ands ip, r0, #3
- bne .Lc2u_dest_not_aligned
-.Lc2u_dest_aligned:
-
- ands ip, r1, #3
- bne .Lc2u_src_not_aligned
-/*
- * Seeing as there has to be at least 8 bytes to copy, we can
- * copy one word, and force a user-mode page fault...
- */
-
-.Lc2u_0fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .Lc2u_0nowords
- ldr r3, [r1], #4
-USER( TUSER( str) r3, [r0], #4) @ May fault
- mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
- rsb ip, ip, #0
- movs ip, ip, lsr #32 - PAGE_SHIFT
- beq .Lc2u_0fupi
-/*
- * ip = max no. of bytes to copy before needing another "strt" insn
- */
- cmp r2, ip
- movlt ip, r2
- sub r2, r2, ip
- subs ip, ip, #32
- blt .Lc2u_0rem8lp
-
-.Lc2u_0cpy8lp: ldmia r1!, {r3 - r6}
- stmia r0!, {r3 - r6} @ Shouldnt fault
- ldmia r1!, {r3 - r6}
- subs ip, ip, #32
- stmia r0!, {r3 - r6} @ Shouldnt fault
- bpl .Lc2u_0cpy8lp
-
-.Lc2u_0rem8lp: cmn ip, #16
- ldmgeia r1!, {r3 - r6}
- stmgeia r0!, {r3 - r6} @ Shouldnt fault
- tst ip, #8
- ldmneia r1!, {r3 - r4}
- stmneia r0!, {r3 - r4} @ Shouldnt fault
- tst ip, #4
- ldrne r3, [r1], #4
- TUSER( strne) r3, [r0], #4 @ Shouldnt fault
- ands ip, ip, #3
- beq .Lc2u_0fupi
-.Lc2u_0nowords: teq ip, #0
- beq .Lc2u_finished
-.Lc2u_nowords: cmp ip, #2
- ldrb r3, [r1], #1
-USER( TUSER( strb) r3, [r0], #1) @ May fault
- ldrgeb r3, [r1], #1
-USER( TUSER( strgeb) r3, [r0], #1) @ May fault
- ldrgtb r3, [r1], #1
-USER( TUSER( strgtb) r3, [r0], #1) @ May fault
- b .Lc2u_finished
-
-.Lc2u_not_enough:
- movs ip, r2
- bne .Lc2u_nowords
-.Lc2u_finished: mov r0, #0
- ldmfd sp!, {r2, r4 - r7, pc}
-
-.Lc2u_src_not_aligned:
- bic r1, r1, #3
- ldr r7, [r1], #4
- cmp ip, #2
- bgt .Lc2u_3fupi
- beq .Lc2u_2fupi
-.Lc2u_1fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .Lc2u_1nowords
- mov r3, r7, pull #8
- ldr r7, [r1], #4
- orr r3, r3, r7, push #24
-USER( TUSER( str) r3, [r0], #4) @ May fault
- mov ip, r0, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
- movs ip, ip, lsr #32 - PAGE_SHIFT
- beq .Lc2u_1fupi
- cmp r2, ip
- movlt ip, r2
- sub r2, r2, ip
- subs ip, ip, #16
- blt .Lc2u_1rem8lp
-
-.Lc2u_1cpy8lp: mov r3, r7, pull #8
- ldmia r1!, {r4 - r7}
- subs ip, ip, #16
- orr r3, r3, r4, push #24
- mov r4, r4, pull #8
- orr r4, r4, r5, push #24
- mov r5, r5, pull #8
- orr r5, r5, r6, push #24
- mov r6, r6, pull #8
- orr r6, r6, r7, push #24
- stmia r0!, {r3 - r6} @ Shouldnt fault
- bpl .Lc2u_1cpy8lp
-
-.Lc2u_1rem8lp: tst ip, #8
- movne r3, r7, pull #8
- ldmneia r1!, {r4, r7}
- orrne r3, r3, r4, push #24
- movne r4, r4, pull #8
- orrne r4, r4, r7, push #24
- stmneia r0!, {r3 - r4} @ Shouldnt fault
- tst ip, #4
- movne r3, r7, pull #8
- ldrne r7, [r1], #4
- orrne r3, r3, r7, push #24
- TUSER( strne) r3, [r0], #4 @ Shouldnt fault
- ands ip, ip, #3
- beq .Lc2u_1fupi
-.Lc2u_1nowords: mov r3, r7, get_byte_1
- teq ip, #0
- beq .Lc2u_finished
- cmp ip, #2
-USER( TUSER( strb) r3, [r0], #1) @ May fault
- movge r3, r7, get_byte_2
-USER( TUSER( strgeb) r3, [r0], #1) @ May fault
- movgt r3, r7, get_byte_3
-USER( TUSER( strgtb) r3, [r0], #1) @ May fault
- b .Lc2u_finished
-
-.Lc2u_2fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .Lc2u_2nowords
- mov r3, r7, pull #16
- ldr r7, [r1], #4
- orr r3, r3, r7, push #16
-USER( TUSER( str) r3, [r0], #4) @ May fault
- mov ip, r0, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
- movs ip, ip, lsr #32 - PAGE_SHIFT
- beq .Lc2u_2fupi
- cmp r2, ip
- movlt ip, r2
- sub r2, r2, ip
- subs ip, ip, #16
- blt .Lc2u_2rem8lp
-
-.Lc2u_2cpy8lp: mov r3, r7, pull #16
- ldmia r1!, {r4 - r7}
- subs ip, ip, #16
- orr r3, r3, r4, push #16
- mov r4, r4, pull #16
- orr r4, r4, r5, push #16
- mov r5, r5, pull #16
- orr r5, r5, r6, push #16
- mov r6, r6, pull #16
- orr r6, r6, r7, push #16
- stmia r0!, {r3 - r6} @ Shouldnt fault
- bpl .Lc2u_2cpy8lp
-
-.Lc2u_2rem8lp: tst ip, #8
- movne r3, r7, pull #16
- ldmneia r1!, {r4, r7}
- orrne r3, r3, r4, push #16
- movne r4, r4, pull #16
- orrne r4, r4, r7, push #16
- stmneia r0!, {r3 - r4} @ Shouldnt fault
- tst ip, #4
- movne r3, r7, pull #16
- ldrne r7, [r1], #4
- orrne r3, r3, r7, push #16
- TUSER( strne) r3, [r0], #4 @ Shouldnt fault
- ands ip, ip, #3
- beq .Lc2u_2fupi
-.Lc2u_2nowords: mov r3, r7, get_byte_2
- teq ip, #0
- beq .Lc2u_finished
- cmp ip, #2
-USER( TUSER( strb) r3, [r0], #1) @ May fault
- movge r3, r7, get_byte_3
-USER( TUSER( strgeb) r3, [r0], #1) @ May fault
- ldrgtb r3, [r1], #0
-USER( TUSER( strgtb) r3, [r0], #1) @ May fault
- b .Lc2u_finished
-
-.Lc2u_3fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .Lc2u_3nowords
- mov r3, r7, pull #24
- ldr r7, [r1], #4
- orr r3, r3, r7, push #8
-USER( TUSER( str) r3, [r0], #4) @ May fault
- mov ip, r0, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
- movs ip, ip, lsr #32 - PAGE_SHIFT
- beq .Lc2u_3fupi
- cmp r2, ip
- movlt ip, r2
- sub r2, r2, ip
- subs ip, ip, #16
- blt .Lc2u_3rem8lp
-
-.Lc2u_3cpy8lp: mov r3, r7, pull #24
- ldmia r1!, {r4 - r7}
- subs ip, ip, #16
- orr r3, r3, r4, push #8
- mov r4, r4, pull #24
- orr r4, r4, r5, push #8
- mov r5, r5, pull #24
- orr r5, r5, r6, push #8
- mov r6, r6, pull #24
- orr r6, r6, r7, push #8
- stmia r0!, {r3 - r6} @ Shouldnt fault
- bpl .Lc2u_3cpy8lp
-
-.Lc2u_3rem8lp: tst ip, #8
- movne r3, r7, pull #24
- ldmneia r1!, {r4, r7}
- orrne r3, r3, r4, push #8
- movne r4, r4, pull #24
- orrne r4, r4, r7, push #8
- stmneia r0!, {r3 - r4} @ Shouldnt fault
- tst ip, #4
- movne r3, r7, pull #24
- ldrne r7, [r1], #4
- orrne r3, r3, r7, push #8
- TUSER( strne) r3, [r0], #4 @ Shouldnt fault
- ands ip, ip, #3
- beq .Lc2u_3fupi
-.Lc2u_3nowords: mov r3, r7, get_byte_3
- teq ip, #0
- beq .Lc2u_finished
- cmp ip, #2
-USER( TUSER( strb) r3, [r0], #1) @ May fault
- ldrgeb r3, [r1], #1
-USER( TUSER( strgeb) r3, [r0], #1) @ May fault
- ldrgtb r3, [r1], #0
-USER( TUSER( strgtb) r3, [r0], #1) @ May fault
- b .Lc2u_finished
-ENDPROC(__copy_to_user)
-
- .pushsection .fixup,"ax"
- .align 0
-9001: ldmfd sp!, {r0, r4 - r7, pc}
- .popsection
-
-/* Prototype: unsigned long __copy_from_user(void *to,const void *from,unsigned long n);
- * Purpose : copy a block from user memory to kernel memory
- * Params : to - kernel memory
- * : from - user memory
- * : n - number of bytes to copy
- * Returns : Number of bytes NOT copied.
- */
-.Lcfu_dest_not_aligned:
- rsb ip, ip, #4
- cmp ip, #2
-USER( TUSER( ldrb) r3, [r1], #1) @ May fault
- strb r3, [r0], #1
-USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault
- strgeb r3, [r0], #1
-USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault
- strgtb r3, [r0], #1
- sub r2, r2, ip
- b .Lcfu_dest_aligned
-
-ENTRY(__copy_from_user)
- stmfd sp!, {r0, r2, r4 - r7, lr}
- cmp r2, #4
- blt .Lcfu_not_enough
- ands ip, r0, #3
- bne .Lcfu_dest_not_aligned
-.Lcfu_dest_aligned:
- ands ip, r1, #3
- bne .Lcfu_src_not_aligned
-
-/*
- * Seeing as there has to be at least 8 bytes to copy, we can
- * copy one word, and force a user-mode page fault...
- */
-
-.Lcfu_0fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .Lcfu_0nowords
-USER( TUSER( ldr) r3, [r1], #4)
- str r3, [r0], #4
- mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
- rsb ip, ip, #0
- movs ip, ip, lsr #32 - PAGE_SHIFT
- beq .Lcfu_0fupi
-/*
- * ip = max no. of bytes to copy before needing another "strt" insn
- */
- cmp r2, ip
- movlt ip, r2
- sub r2, r2, ip
- subs ip, ip, #32
- blt .Lcfu_0rem8lp
-
-.Lcfu_0cpy8lp: ldmia r1!, {r3 - r6} @ Shouldnt fault
- stmia r0!, {r3 - r6}
- ldmia r1!, {r3 - r6} @ Shouldnt fault
- subs ip, ip, #32
- stmia r0!, {r3 - r6}
- bpl .Lcfu_0cpy8lp
-
-.Lcfu_0rem8lp: cmn ip, #16
- ldmgeia r1!, {r3 - r6} @ Shouldnt fault
- stmgeia r0!, {r3 - r6}
- tst ip, #8
- ldmneia r1!, {r3 - r4} @ Shouldnt fault
- stmneia r0!, {r3 - r4}
- tst ip, #4
- TUSER( ldrne) r3, [r1], #4 @ Shouldnt fault
- strne r3, [r0], #4
- ands ip, ip, #3
- beq .Lcfu_0fupi
-.Lcfu_0nowords: teq ip, #0
- beq .Lcfu_finished
-.Lcfu_nowords: cmp ip, #2
-USER( TUSER( ldrb) r3, [r1], #1) @ May fault
- strb r3, [r0], #1
-USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault
- strgeb r3, [r0], #1
-USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault
- strgtb r3, [r0], #1
- b .Lcfu_finished
-
-.Lcfu_not_enough:
- movs ip, r2
- bne .Lcfu_nowords
-.Lcfu_finished: mov r0, #0
- add sp, sp, #8
- ldmfd sp!, {r4 - r7, pc}
-
-.Lcfu_src_not_aligned:
- bic r1, r1, #3
-USER( TUSER( ldr) r7, [r1], #4) @ May fault
- cmp ip, #2
- bgt .Lcfu_3fupi
- beq .Lcfu_2fupi
-.Lcfu_1fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .Lcfu_1nowords
- mov r3, r7, pull #8
-USER( TUSER( ldr) r7, [r1], #4) @ May fault
- orr r3, r3, r7, push #24
- str r3, [r0], #4
- mov ip, r1, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
- movs ip, ip, lsr #32 - PAGE_SHIFT
- beq .Lcfu_1fupi
- cmp r2, ip
- movlt ip, r2
- sub r2, r2, ip
- subs ip, ip, #16
- blt .Lcfu_1rem8lp
-
-.Lcfu_1cpy8lp: mov r3, r7, pull #8
- ldmia r1!, {r4 - r7} @ Shouldnt fault
- subs ip, ip, #16
- orr r3, r3, r4, push #24
- mov r4, r4, pull #8
- orr r4, r4, r5, push #24
- mov r5, r5, pull #8
- orr r5, r5, r6, push #24
- mov r6, r6, pull #8
- orr r6, r6, r7, push #24
- stmia r0!, {r3 - r6}
- bpl .Lcfu_1cpy8lp
-
-.Lcfu_1rem8lp: tst ip, #8
- movne r3, r7, pull #8
- ldmneia r1!, {r4, r7} @ Shouldnt fault
- orrne r3, r3, r4, push #24
- movne r4, r4, pull #8
- orrne r4, r4, r7, push #24
- stmneia r0!, {r3 - r4}
- tst ip, #4
- movne r3, r7, pull #8
-USER( TUSER( ldrne) r7, [r1], #4) @ May fault
- orrne r3, r3, r7, push #24
- strne r3, [r0], #4
- ands ip, ip, #3
- beq .Lcfu_1fupi
-.Lcfu_1nowords: mov r3, r7, get_byte_1
- teq ip, #0
- beq .Lcfu_finished
- cmp ip, #2
- strb r3, [r0], #1
- movge r3, r7, get_byte_2
- strgeb r3, [r0], #1
- movgt r3, r7, get_byte_3
- strgtb r3, [r0], #1
- b .Lcfu_finished
-
-.Lcfu_2fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .Lcfu_2nowords
- mov r3, r7, pull #16
-USER( TUSER( ldr) r7, [r1], #4) @ May fault
- orr r3, r3, r7, push #16
- str r3, [r0], #4
- mov ip, r1, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
- movs ip, ip, lsr #32 - PAGE_SHIFT
- beq .Lcfu_2fupi
- cmp r2, ip
- movlt ip, r2
- sub r2, r2, ip
- subs ip, ip, #16
- blt .Lcfu_2rem8lp
-
-
-.Lcfu_2cpy8lp: mov r3, r7, pull #16
- ldmia r1!, {r4 - r7} @ Shouldnt fault
- subs ip, ip, #16
- orr r3, r3, r4, push #16
- mov r4, r4, pull #16
- orr r4, r4, r5, push #16
- mov r5, r5, pull #16
- orr r5, r5, r6, push #16
- mov r6, r6, pull #16
- orr r6, r6, r7, push #16
- stmia r0!, {r3 - r6}
- bpl .Lcfu_2cpy8lp
-
-.Lcfu_2rem8lp: tst ip, #8
- movne r3, r7, pull #16
- ldmneia r1!, {r4, r7} @ Shouldnt fault
- orrne r3, r3, r4, push #16
- movne r4, r4, pull #16
- orrne r4, r4, r7, push #16
- stmneia r0!, {r3 - r4}
- tst ip, #4
- movne r3, r7, pull #16
-USER( TUSER( ldrne) r7, [r1], #4) @ May fault
- orrne r3, r3, r7, push #16
- strne r3, [r0], #4
- ands ip, ip, #3
- beq .Lcfu_2fupi
-.Lcfu_2nowords: mov r3, r7, get_byte_2
- teq ip, #0
- beq .Lcfu_finished
- cmp ip, #2
- strb r3, [r0], #1
- movge r3, r7, get_byte_3
- strgeb r3, [r0], #1
-USER( TUSER( ldrgtb) r3, [r1], #0) @ May fault
- strgtb r3, [r0], #1
- b .Lcfu_finished
-
-.Lcfu_3fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .Lcfu_3nowords
- mov r3, r7, pull #24
-USER( TUSER( ldr) r7, [r1], #4) @ May fault
- orr r3, r3, r7, push #8
- str r3, [r0], #4
- mov ip, r1, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
- movs ip, ip, lsr #32 - PAGE_SHIFT
- beq .Lcfu_3fupi
- cmp r2, ip
- movlt ip, r2
- sub r2, r2, ip
- subs ip, ip, #16
- blt .Lcfu_3rem8lp
-
-.Lcfu_3cpy8lp: mov r3, r7, pull #24
- ldmia r1!, {r4 - r7} @ Shouldnt fault
- orr r3, r3, r4, push #8
- mov r4, r4, pull #24
- orr r4, r4, r5, push #8
- mov r5, r5, pull #24
- orr r5, r5, r6, push #8
- mov r6, r6, pull #24
- orr r6, r6, r7, push #8
- stmia r0!, {r3 - r6}
- subs ip, ip, #16
- bpl .Lcfu_3cpy8lp
-
-.Lcfu_3rem8lp: tst ip, #8
- movne r3, r7, pull #24
- ldmneia r1!, {r4, r7} @ Shouldnt fault
- orrne r3, r3, r4, push #8
- movne r4, r4, pull #24
- orrne r4, r4, r7, push #8
- stmneia r0!, {r3 - r4}
- tst ip, #4
- movne r3, r7, pull #24
-USER( TUSER( ldrne) r7, [r1], #4) @ May fault
- orrne r3, r3, r7, push #8
- strne r3, [r0], #4
- ands ip, ip, #3
- beq .Lcfu_3fupi
-.Lcfu_3nowords: mov r3, r7, get_byte_3
- teq ip, #0
- beq .Lcfu_finished
- cmp ip, #2
- strb r3, [r0], #1
-USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault
- strgeb r3, [r0], #1
-USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault
- strgtb r3, [r0], #1
- b .Lcfu_finished
-ENDPROC(__copy_from_user)
-
- .pushsection .fixup,"ax"
- .align 0
- /*
- * We took an exception. r0 contains a pointer to
- * the byte not copied.
- */
-9001: ldr r2, [sp], #4 @ void *to
- sub r2, r0, r2 @ bytes copied
- ldr r1, [sp], #4 @ unsigned long count
- subs r4, r1, r2 @ bytes left to copy
- movne r1, r4
- blne __memzero
- mov r0, r4
- ldmfd sp!, {r4 - r7, pc}
- .popsection
-
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 45db05d8d94c..19505c0a3f01 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -9,15 +9,6 @@ config HAVE_AT91_DBGU0
config HAVE_AT91_DBGU1
bool
-config HAVE_AT91_USART3
- bool
-
-config HAVE_AT91_USART4
- bool
-
-config HAVE_AT91_USART5
- bool
-
config AT91_SAM9_ALT_RESET
bool
default !ARCH_AT91X40
@@ -26,87 +17,129 @@ config AT91_SAM9G45_RESET
bool
default !ARCH_AT91X40
+config SOC_AT91SAM9
+ bool
+ select GENERIC_CLOCKEVENTS
+ select CPU_ARM926T
+
menu "Atmel AT91 System-on-Chip"
-choice
- prompt "Atmel AT91 Processor"
+comment "Atmel AT91 Processor"
-config ARCH_AT91RM9200
+config SOC_AT91SAM9
+ bool
+ select CPU_ARM926T
+ select AT91_SAM9_TIME
+ select AT91_SAM9_SMC
+
+config SOC_AT91RM9200
bool "AT91RM9200"
select CPU_ARM920T
select GENERIC_CLOCKEVENTS
select HAVE_AT91_DBGU0
- select HAVE_AT91_USART3
-config ARCH_AT91SAM9260
- bool "AT91SAM9260 or AT91SAM9XE"
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
+config SOC_AT91SAM9260
+ bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20"
+ select SOC_AT91SAM9
select HAVE_AT91_DBGU0
- select HAVE_AT91_USART3
- select HAVE_AT91_USART4
- select HAVE_AT91_USART5
select HAVE_NET_MACB
+ help
+ Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE
+ or AT91SAM9G20 SoC.
-config ARCH_AT91SAM9261
- bool "AT91SAM9261"
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
- select HAVE_FB_ATMEL
- select HAVE_AT91_DBGU0
-
-config ARCH_AT91SAM9G10
- bool "AT91SAM9G10"
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
+config SOC_AT91SAM9261
+ bool "AT91SAM9261 or AT91SAM9G10"
+ select SOC_AT91SAM9
select HAVE_AT91_DBGU0
select HAVE_FB_ATMEL
+ help
+ Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC.
-config ARCH_AT91SAM9263
+config SOC_AT91SAM9263
bool "AT91SAM9263"
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
+ select SOC_AT91SAM9
+ select HAVE_AT91_DBGU1
select HAVE_FB_ATMEL
select HAVE_NET_MACB
- select HAVE_AT91_DBGU1
-config ARCH_AT91SAM9RL
+config SOC_AT91SAM9RL
bool "AT91SAM9RL"
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
- select HAVE_AT91_USART3
- select HAVE_FB_ATMEL
- select HAVE_AT91_DBGU0
-
-config ARCH_AT91SAM9G20
- bool "AT91SAM9G20"
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
+ select SOC_AT91SAM9
select HAVE_AT91_DBGU0
- select HAVE_AT91_USART3
- select HAVE_AT91_USART4
- select HAVE_AT91_USART5
- select HAVE_NET_MACB
+ select HAVE_FB_ATMEL
-config ARCH_AT91SAM9G45
- bool "AT91SAM9G45"
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
- select HAVE_AT91_USART3
+config SOC_AT91SAM9G45
+ bool "AT91SAM9G45 or AT91SAM9M10 families"
+ select SOC_AT91SAM9
+ select HAVE_AT91_DBGU1
select HAVE_FB_ATMEL
select HAVE_NET_MACB
- select HAVE_AT91_DBGU1
+ help
+ Select this if you are using one of Atmel's AT91SAM9G45 family SoC.
+ This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11.
-config ARCH_AT91SAM9X5
+config SOC_AT91SAM9X5
bool "AT91SAM9x5 family"
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
+ select SOC_AT91SAM9
+ select HAVE_AT91_DBGU0
select HAVE_FB_ATMEL
select HAVE_NET_MACB
+ help
+ Select this if you are using one of Atmel's AT91SAM9x5 family SoC.
+ This means that your SAM9 name finishes with a '5' (except if it is
+ AT91SAM9G45!).
+ This support covers AT91SAM9G15, AT91SAM9G25, AT91SAM9X25, AT91SAM9G35
+ and AT91SAM9X35.
+
+config SOC_AT91SAM9N12
+ bool "AT91SAM9N12 family"
+ select SOC_AT91SAM9
select HAVE_AT91_DBGU0
+ select HAVE_FB_ATMEL
+ help
+ Select this if you are using Atmel's AT91SAM9N12 SoC.
+
+choice
+ prompt "Atmel AT91 Processor Devices for non DT boards"
+
+config ARCH_AT91_NONE
+ bool "None"
+
+config ARCH_AT91RM9200
+ bool "AT91RM9200"
+ select SOC_AT91RM9200
+
+config ARCH_AT91SAM9260
+ bool "AT91SAM9260 or AT91SAM9XE"
+ select SOC_AT91SAM9260
+
+config ARCH_AT91SAM9261
+ bool "AT91SAM9261"
+ select SOC_AT91SAM9261
+
+config ARCH_AT91SAM9G10
+ bool "AT91SAM9G10"
+ select SOC_AT91SAM9261
+
+config ARCH_AT91SAM9263
+ bool "AT91SAM9263"
+ select SOC_AT91SAM9263
+
+config ARCH_AT91SAM9RL
+ bool "AT91SAM9RL"
+ select SOC_AT91SAM9RL
+
+config ARCH_AT91SAM9G20
+ bool "AT91SAM9G20"
+ select SOC_AT91SAM9260
+
+config ARCH_AT91SAM9G45
+ bool "AT91SAM9G45"
+ select SOC_AT91SAM9G45
config ARCH_AT91X40
bool "AT91x40"
+ depends on !MMU
select ARCH_USES_GETTIMEOFFSET
endchoice
@@ -364,6 +397,7 @@ config MACH_AT91SAM9G20EK_2MMC
Select this if you are using an Atmel AT91SAM9G20-EK Evaluation Kit
with 2 SD/MMC Slots. This is the case for AT91SAM9G20-EK rev. C and
onwards.
+ <http://www.atmel.com/tools/SAM9G20-EK.aspx>
config MACH_CPU9G20
bool "Eukrea CPU9G20 board"
@@ -433,9 +467,10 @@ comment "AT91SAM9G45 Board Type"
config MACH_AT91SAM9M10G45EK
bool "Atmel AT91SAM9M10G45-EK Evaluation Kits"
help
- Select this if you are using Atmel's AT91SAM9G45-EKES Evaluation Kit.
- "ES" at the end of the name means that this board is an
- Engineering Sample.
+ Select this if you are using Atmel's AT91SAM9M10G45-EK Evaluation Kit.
+ Those boards can be populated with any SoC of AT91SAM9G45 or AT91SAM9M10
+ families: AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11.
+ <http://www.atmel.com/tools/SAM9M10-G45-EK.aspx>
endif
@@ -515,41 +550,6 @@ config AT91_TIMER_HZ
system clock (of at least several MHz), rounding is less of a
problem so it can be safer to use a decimal values like 100.
-choice
- prompt "Select a UART for early kernel messages"
-
-config AT91_EARLY_DBGU0
- bool "DBGU on rm9200, 9260/9g20, 9261/9g10 and 9rl"
- depends on HAVE_AT91_DBGU0
-
-config AT91_EARLY_DBGU1
- bool "DBGU on 9263 and 9g45"
- depends on HAVE_AT91_DBGU1
-
-config AT91_EARLY_USART0
- bool "USART0"
-
-config AT91_EARLY_USART1
- bool "USART1"
-
-config AT91_EARLY_USART2
- bool "USART2"
- depends on ! ARCH_AT91X40
-
-config AT91_EARLY_USART3
- bool "USART3"
- depends on HAVE_AT91_USART3
-
-config AT91_EARLY_USART4
- bool "USART4"
- depends on HAVE_AT91_USART4
-
-config AT91_EARLY_USART5
- bool "USART5"
- depends on HAVE_AT91_USART5
-
-endchoice
-
endmenu
endif
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 8512e53bed93..3bb7a51efc9d 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -10,17 +10,26 @@ obj- :=
obj-$(CONFIG_AT91_PMC_UNIT) += clock.o
obj-$(CONFIG_AT91_SAM9_ALT_RESET) += at91sam9_alt_reset.o
obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o
+obj-$(CONFIG_SOC_AT91SAM9) += at91sam926x_time.o sam9_smc.o
# CPU-specific support
-obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
-obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9X5) += at91sam9x5.o at91sam926x_time.o sam9_smc.o
+obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o at91rm9200_time.o
+obj-$(CONFIG_SOC_AT91SAM9260) += at91sam9260.o
+obj-$(CONFIG_SOC_AT91SAM9261) += at91sam9261.o
+obj-$(CONFIG_SOC_AT91SAM9263) += at91sam9263.o
+obj-$(CONFIG_SOC_AT91SAM9G45) += at91sam9g45.o
+obj-$(CONFIG_SOC_AT91SAM9N12) += at91sam9n12.o
+obj-$(CONFIG_SOC_AT91SAM9X5) += at91sam9x5.o
+obj-$(CONFIG_SOC_AT91SAM9RL) += at91sam9rl.o
+
+obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45_devices.o
obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o
# AT91RM9200 board-specific support
diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
index 0da66ca4a4f8..9e84fe4f2aaa 100644
--- a/arch/arm/mach-at91/Makefile.boot
+++ b/arch/arm/mach-at91/Makefile.boot
@@ -14,9 +14,23 @@ initrd_phys-y := 0x20410000
endif
# Keep dtb files sorted alphabetically for each SoC
+# sam9260
+dtb-$(CONFIG_MACH_AT91SAM_DT) += ethernut5.dtb
+dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9260.dtb
+dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9260.dtb
+# sam9263
+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9263ek.dtb
+dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9263.dtb
+dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9263.dtb
# sam9g20
+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek.dtb
+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek_2mmc.dtb
+dtb-$(CONFIG_MACH_AT91SAM_DT) += kizbox.dtb
+dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9g20.dtb
dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9g20.dtb
# sam9g45
dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb
+# sam9n12
+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9n12ek.dtb
# sam9x5
dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g25ek.dtb
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index 89106792d067..26917687fc30 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -249,18 +249,6 @@ static void __init at91rm9200_register_clocks(void)
clk_register(&pck3);
}
-static struct clk_lookup console_clock_lookup;
-
-void __init at91rm9200_set_console_clock(int id)
-{
- if (id >= ARRAY_SIZE(usart_clocks_lookups))
- return;
-
- console_clock_lookup.con_id = "usart";
- console_clock_lookup.clk = usart_clocks_lookups[id].clk;
- clkdev_add(&console_clock_lookup);
-}
-
/* --------------------------------------------------------------------
* GPIO
* -------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 60c472861e5e..e6b7d0533dd7 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -1152,14 +1152,6 @@ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
at91_uarts[portnr] = pdev;
}
-void __init at91_set_serial_console(unsigned portnr)
-{
- if (portnr < ATMEL_MAX_UART) {
- atmel_default_console_device = at91_uarts[portnr];
- at91rm9200_set_console_clock(at91_uarts[portnr]->id);
- }
-}
-
void __init at91_add_device_serial(void)
{
int i;
@@ -1168,13 +1160,9 @@ void __init at91_add_device_serial(void)
if (at91_uarts[i])
platform_device_register(at91_uarts[i]);
}
-
- if (!atmel_default_console_device)
- printk(KERN_INFO "AT91: No default serial console defined.\n");
}
#else
void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
void __init at91_add_device_serial(void) {}
#endif
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 46f774233298..2b1e438ed878 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -55,6 +55,13 @@ static struct clk adc_clk = {
.pmc_mask = 1 << AT91SAM9260_ID_ADC,
.type = CLK_TYPE_PERIPHERAL,
};
+
+static struct clk adc_op_clk = {
+ .name = "adc_op_clk",
+ .type = CLK_TYPE_PERIPHERAL,
+ .rate_hz = 5000000,
+};
+
static struct clk usart0_clk = {
.name = "usart0_clk",
.pmc_mask = 1 << AT91SAM9260_ID_US0,
@@ -166,6 +173,7 @@ static struct clk *periph_clocks[] __initdata = {
&pioB_clk,
&pioC_clk,
&adc_clk,
+ &adc_op_clk,
&usart0_clk,
&usart1_clk,
&usart2_clk,
@@ -268,18 +276,6 @@ static void __init at91sam9260_register_clocks(void)
clk_register(&pck1);
}
-static struct clk_lookup console_clock_lookup;
-
-void __init at91sam9260_set_console_clock(int id)
-{
- if (id >= ARRAY_SIZE(usart_clocks_lookups))
- return;
-
- console_clock_lookup.con_id = "usart";
- console_clock_lookup.clk = usart_clocks_lookups[id].clk;
- clkdev_add(&console_clock_lookup);
-}
-
/* --------------------------------------------------------------------
* GPIO
* -------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 5652dde4bbe2..0ded951f785a 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -17,12 +17,15 @@
#include <linux/platform_device.h>
#include <linux/i2c-gpio.h>
+#include <linux/platform_data/at91_adc.h>
+
#include <mach/board.h>
#include <mach/cpu.h>
#include <mach/at91sam9260.h>
#include <mach/at91sam9260_matrix.h>
#include <mach/at91_matrix.h>
#include <mach/at91sam9_smc.h>
+#include <mach/at91_adc.h>
#include "generic.h"
@@ -702,25 +705,8 @@ static struct platform_device at91sam9260_tcb1_device = {
.num_resources = ARRAY_SIZE(tcb1_resources),
};
-#if defined(CONFIG_OF)
-static struct of_device_id tcb_ids[] = {
- { .compatible = "atmel,at91rm9200-tcb" },
- { /*sentinel*/ }
-};
-#endif
-
static void __init at91_add_device_tc(void)
{
-#if defined(CONFIG_OF)
- struct device_node *np;
-
- np = of_find_matching_node(NULL, tcb_ids);
- if (np) {
- of_node_put(np);
- return;
- }
-#endif
-
platform_device_register(&at91sam9260_tcb0_device);
platform_device_register(&at91sam9260_tcb1_device);
}
@@ -1229,14 +1215,6 @@ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
at91_uarts[portnr] = pdev;
}
-void __init at91_set_serial_console(unsigned portnr)
-{
- if (portnr < ATMEL_MAX_UART) {
- atmel_default_console_device = at91_uarts[portnr];
- at91sam9260_set_console_clock(at91_uarts[portnr]->id);
- }
-}
-
void __init at91_add_device_serial(void)
{
int i;
@@ -1245,13 +1223,9 @@ void __init at91_add_device_serial(void)
if (at91_uarts[i])
platform_device_register(at91_uarts[i]);
}
-
- if (!atmel_default_console_device)
- printk(KERN_INFO "AT91: No default serial console defined.\n");
}
#else
void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
void __init at91_add_device_serial(void) {}
#endif
@@ -1369,6 +1343,93 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
void __init at91_add_device_cf(struct at91_cf_data * data) {}
#endif
+/* --------------------------------------------------------------------
+ * ADCs
+ * -------------------------------------------------------------------- */
+
+#if IS_ENABLED(CONFIG_AT91_ADC)
+static struct at91_adc_data adc_data;
+
+static struct resource adc_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_ADC,
+ .end = AT91SAM9260_BASE_ADC + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_ADC,
+ .end = AT91SAM9260_ID_ADC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91_adc_device = {
+ .name = "at91_adc",
+ .id = -1,
+ .dev = {
+ .platform_data = &adc_data,
+ },
+ .resource = adc_resources,
+ .num_resources = ARRAY_SIZE(adc_resources),
+};
+
+static struct at91_adc_trigger at91_adc_triggers[] = {
+ [0] = {
+ .name = "timer-counter-0",
+ .value = AT91_ADC_TRGSEL_TC0 | AT91_ADC_TRGEN,
+ },
+ [1] = {
+ .name = "timer-counter-1",
+ .value = AT91_ADC_TRGSEL_TC1 | AT91_ADC_TRGEN,
+ },
+ [2] = {
+ .name = "timer-counter-2",
+ .value = AT91_ADC_TRGSEL_TC2 | AT91_ADC_TRGEN,
+ },
+ [3] = {
+ .name = "external",
+ .value = AT91_ADC_TRGSEL_EXTERNAL | AT91_ADC_TRGEN,
+ .is_external = true,
+ },
+};
+
+static struct at91_adc_reg_desc at91_adc_register_g20 = {
+ .channel_base = AT91_ADC_CHR(0),
+ .drdy_mask = AT91_ADC_DRDY,
+ .status_register = AT91_ADC_SR,
+ .trigger_register = AT91_ADC_MR,
+};
+
+void __init at91_add_device_adc(struct at91_adc_data *data)
+{
+ if (!data)
+ return;
+
+ if (test_bit(0, &data->channels_used))
+ at91_set_A_periph(AT91_PIN_PC0, 0);
+ if (test_bit(1, &data->channels_used))
+ at91_set_A_periph(AT91_PIN_PC1, 0);
+ if (test_bit(2, &data->channels_used))
+ at91_set_A_periph(AT91_PIN_PC2, 0);
+ if (test_bit(3, &data->channels_used))
+ at91_set_A_periph(AT91_PIN_PC3, 0);
+
+ if (data->use_external_triggers)
+ at91_set_A_periph(AT91_PIN_PA22, 0);
+
+ data->num_channels = 4;
+ data->startup_time = 10;
+ data->registers = &at91_adc_register_g20;
+ data->trigger_number = 4;
+ data->trigger_list = at91_adc_triggers;
+
+ adc_data = *data;
+ platform_device_register(&at91_adc_device);
+}
+#else
+void __init at91_add_device_adc(struct at91_adc_data *data) {}
+#endif
+
/* -------------------------------------------------------------------- */
/*
* These devices are always present and don't need any board-specific
@@ -1376,6 +1437,9 @@ void __init at91_add_device_cf(struct at91_cf_data * data) {}
*/
static int __init at91_add_standard_devices(void)
{
+ if (of_have_populated_dt())
+ return 0;
+
at91_add_device_rtt();
at91_add_device_watchdog();
at91_add_device_tc();
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 7de81e6222f1..c77d503d09d1 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -239,18 +239,6 @@ static void __init at91sam9261_register_clocks(void)
clk_register(&hck1);
}
-static struct clk_lookup console_clock_lookup;
-
-void __init at91sam9261_set_console_clock(int id)
-{
- if (id >= ARRAY_SIZE(usart_clocks_lookups))
- return;
-
- console_clock_lookup.con_id = "usart";
- console_clock_lookup.clk = usart_clocks_lookups[id].clk;
- clkdev_add(&console_clock_lookup);
-}
-
/* --------------------------------------------------------------------
* GPIO
* -------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 4db961a93085..9295e90b08ff 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -1051,14 +1051,6 @@ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
at91_uarts[portnr] = pdev;
}
-void __init at91_set_serial_console(unsigned portnr)
-{
- if (portnr < ATMEL_MAX_UART) {
- atmel_default_console_device = at91_uarts[portnr];
- at91sam9261_set_console_clock(at91_uarts[portnr]->id);
- }
-}
-
void __init at91_add_device_serial(void)
{
int i;
@@ -1067,13 +1059,9 @@ void __init at91_add_device_serial(void)
if (at91_uarts[i])
platform_device_register(at91_uarts[i]);
}
-
- if (!atmel_default_console_device)
- printk(KERN_INFO "AT91: No default serial console defined.\n");
}
#else
void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
void __init at91_add_device_serial(void) {}
#endif
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index ef301be66575..ed91c7e9f7c2 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -199,6 +199,16 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_ID("pioC", &pioCDE_clk),
CLKDEV_CON_ID("pioD", &pioCDE_clk),
CLKDEV_CON_ID("pioE", &pioCDE_clk),
+ /* more usart lookup table for DT entries */
+ CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
+ CLKDEV_CON_DEV_ID("usart", "fff8c000.serial", &usart0_clk),
+ CLKDEV_CON_DEV_ID("usart", "fff90000.serial", &usart1_clk),
+ CLKDEV_CON_DEV_ID("usart", "fff94000.serial", &usart2_clk),
+ /* more tc lookup table for DT entries */
+ CLKDEV_CON_DEV_ID("t0_clk", "fff7c000.timer", &tcb_clk),
+ CLKDEV_CON_DEV_ID("hclk", "a00000.ohci", &ohci_clk),
+ CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk),
+ CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
};
static struct clk_lookup usart_clocks_lookups[] = {
@@ -255,18 +265,6 @@ static void __init at91sam9263_register_clocks(void)
clk_register(&pck3);
}
-static struct clk_lookup console_clock_lookup;
-
-void __init at91sam9263_set_console_clock(int id)
-{
- if (id >= ARRAY_SIZE(usart_clocks_lookups))
- return;
-
- console_clock_lookup.con_id = "usart";
- console_clock_lookup.clk = usart_clocks_lookups[id].clk;
- clkdev_add(&console_clock_lookup);
-}
-
/* --------------------------------------------------------------------
* GPIO
* -------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index fe99206de880..175e0009eaa9 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -953,8 +953,25 @@ static struct platform_device at91sam9263_tcb_device = {
.num_resources = ARRAY_SIZE(tcb_resources),
};
+#if defined(CONFIG_OF)
+static struct of_device_id tcb_ids[] = {
+ { .compatible = "atmel,at91rm9200-tcb" },
+ { /*sentinel*/ }
+};
+#endif
+
static void __init at91_add_device_tc(void)
{
+#if defined(CONFIG_OF)
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, tcb_ids);
+ if (np) {
+ of_node_put(np);
+ return;
+ }
+#endif
+
platform_device_register(&at91sam9263_tcb_device);
}
#else
@@ -1461,14 +1478,6 @@ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
at91_uarts[portnr] = pdev;
}
-void __init at91_set_serial_console(unsigned portnr)
-{
- if (portnr < ATMEL_MAX_UART) {
- atmel_default_console_device = at91_uarts[portnr];
- at91sam9263_set_console_clock(at91_uarts[portnr]->id);
- }
-}
-
void __init at91_add_device_serial(void)
{
int i;
@@ -1477,13 +1486,9 @@ void __init at91_add_device_serial(void)
if (at91_uarts[i])
platform_device_register(at91_uarts[i]);
}
-
- if (!atmel_default_console_device)
- printk(KERN_INFO "AT91: No default serial console defined.\n");
}
#else
void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
void __init at91_add_device_serial(void) {}
#endif
@@ -1495,6 +1500,9 @@ void __init at91_add_device_serial(void) {}
*/
static int __init at91_add_standard_devices(void)
{
+ if (of_have_populated_dt())
+ return 0;
+
at91_add_device_rtt();
at91_add_device_watchdog();
at91_add_device_tc();
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index d222f8333dab..4792682d52b9 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -176,6 +176,12 @@ static struct clk vdec_clk = {
.type = CLK_TYPE_PERIPHERAL,
};
+static struct clk adc_op_clk = {
+ .name = "adc_op_clk",
+ .type = CLK_TYPE_PERIPHERAL,
+ .rate_hz = 13200000,
+};
+
static struct clk *periph_clocks[] __initdata = {
&pioA_clk,
&pioB_clk,
@@ -204,6 +210,7 @@ static struct clk *periph_clocks[] __initdata = {
&isi_clk,
&udphs_clk,
&mmc1_clk,
+ &adc_op_clk,
// irq0
};
@@ -242,6 +249,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_ID("pioC", &pioC_clk),
CLKDEV_CON_ID("pioD", &pioDE_clk),
CLKDEV_CON_ID("pioE", &pioDE_clk),
+ /* Fake adc clock */
+ CLKDEV_CON_ID("adc_clk", &tsc_clk),
};
static struct clk_lookup usart_clocks_lookups[] = {
@@ -288,18 +297,6 @@ static void __init at91sam9g45_register_clocks(void)
clk_register(&pck1);
}
-static struct clk_lookup console_clock_lookup;
-
-void __init at91sam9g45_set_console_clock(int id)
-{
- if (id >= ARRAY_SIZE(usart_clocks_lookups))
- return;
-
- console_clock_lookup.con_id = "usart";
- console_clock_lookup.clk = usart_clocks_lookups[id].clk;
- clkdev_add(&console_clock_lookup);
-}
-
/* --------------------------------------------------------------------
* GPIO
* -------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 6b008aee1dff..f6747246d649 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -19,9 +19,12 @@
#include <linux/i2c-gpio.h>
#include <linux/atmel-mci.h>
+#include <linux/platform_data/at91_adc.h>
+
#include <linux/fb.h>
#include <video/atmel_lcdc.h>
+#include <mach/at91_adc.h>
#include <mach/board.h>
#include <mach/at91sam9g45.h>
#include <mach/at91sam9g45_matrix.h>
@@ -69,15 +72,7 @@ static struct platform_device at_hdmac_device = {
void __init at91_add_device_hdmac(void)
{
-#if defined(CONFIG_OF)
- struct device_node *of_node =
- of_find_node_by_name(NULL, "dma-controller");
-
- if (of_node)
- of_node_put(of_node);
- else
-#endif
- platform_device_register(&at_hdmac_device);
+ platform_device_register(&at_hdmac_device);
}
#else
void __init at91_add_device_hdmac(void) {}
@@ -1094,25 +1089,8 @@ static struct platform_device at91sam9g45_tcb1_device = {
.num_resources = ARRAY_SIZE(tcb1_resources),
};
-#if defined(CONFIG_OF)
-static struct of_device_id tcb_ids[] = {
- { .compatible = "atmel,at91rm9200-tcb" },
- { /*sentinel*/ }
-};
-#endif
-
static void __init at91_add_device_tc(void)
{
-#if defined(CONFIG_OF)
- struct device_node *np;
-
- np = of_find_matching_node(NULL, tcb_ids);
- if (np) {
- of_node_put(np);
- return;
- }
-#endif
-
platform_device_register(&at91sam9g45_tcb0_device);
platform_device_register(&at91sam9g45_tcb1_device);
}
@@ -1207,6 +1185,104 @@ void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
/* --------------------------------------------------------------------
+ * ADC
+ * -------------------------------------------------------------------- */
+
+#if IS_ENABLED(CONFIG_AT91_ADC)
+static struct at91_adc_data adc_data;
+
+static struct resource adc_resources[] = {
+ [0] = {
+ .start = AT91SAM9G45_BASE_TSC,
+ .end = AT91SAM9G45_BASE_TSC + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9G45_ID_TSC,
+ .end = AT91SAM9G45_ID_TSC,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device at91_adc_device = {
+ .name = "at91_adc",
+ .id = -1,
+ .dev = {
+ .platform_data = &adc_data,
+ },
+ .resource = adc_resources,
+ .num_resources = ARRAY_SIZE(adc_resources),
+};
+
+static struct at91_adc_trigger at91_adc_triggers[] = {
+ [0] = {
+ .name = "external-rising",
+ .value = 1,
+ .is_external = true,
+ },
+ [1] = {
+ .name = "external-falling",
+ .value = 2,
+ .is_external = true,
+ },
+ [2] = {
+ .name = "external-any",
+ .value = 3,
+ .is_external = true,
+ },
+ [3] = {
+ .name = "continuous",
+ .value = 6,
+ .is_external = false,
+ },
+};
+
+static struct at91_adc_reg_desc at91_adc_register_g45 = {
+ .channel_base = AT91_ADC_CHR(0),
+ .drdy_mask = AT91_ADC_DRDY,
+ .status_register = AT91_ADC_SR,
+ .trigger_register = 0x08,
+};
+
+void __init at91_add_device_adc(struct at91_adc_data *data)
+{
+ if (!data)
+ return;
+
+ if (test_bit(0, &data->channels_used))
+ at91_set_gpio_input(AT91_PIN_PD20, 0);
+ if (test_bit(1, &data->channels_used))
+ at91_set_gpio_input(AT91_PIN_PD21, 0);
+ if (test_bit(2, &data->channels_used))
+ at91_set_gpio_input(AT91_PIN_PD22, 0);
+ if (test_bit(3, &data->channels_used))
+ at91_set_gpio_input(AT91_PIN_PD23, 0);
+ if (test_bit(4, &data->channels_used))
+ at91_set_gpio_input(AT91_PIN_PD24, 0);
+ if (test_bit(5, &data->channels_used))
+ at91_set_gpio_input(AT91_PIN_PD25, 0);
+ if (test_bit(6, &data->channels_used))
+ at91_set_gpio_input(AT91_PIN_PD26, 0);
+ if (test_bit(7, &data->channels_used))
+ at91_set_gpio_input(AT91_PIN_PD27, 0);
+
+ if (data->use_external_triggers)
+ at91_set_A_periph(AT91_PIN_PD28, 0);
+
+ data->num_channels = 8;
+ data->startup_time = 40;
+ data->registers = &at91_adc_register_g45;
+ data->trigger_number = 4;
+ data->trigger_list = at91_adc_triggers;
+
+ adc_data = *data;
+ platform_device_register(&at91_adc_device);
+}
+#else
+void __init at91_add_device_adc(struct at91_adc_data *data) {}
+#endif
+
+/* --------------------------------------------------------------------
* RTT
* -------------------------------------------------------------------- */
@@ -1741,14 +1817,6 @@ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
at91_uarts[portnr] = pdev;
}
-void __init at91_set_serial_console(unsigned portnr)
-{
- if (portnr < ATMEL_MAX_UART) {
- atmel_default_console_device = at91_uarts[portnr];
- at91sam9g45_set_console_clock(at91_uarts[portnr]->id);
- }
-}
-
void __init at91_add_device_serial(void)
{
int i;
@@ -1757,13 +1825,9 @@ void __init at91_add_device_serial(void)
if (at91_uarts[i])
platform_device_register(at91_uarts[i]);
}
-
- if (!atmel_default_console_device)
- printk(KERN_INFO "AT91: No default serial console defined.\n");
}
#else
void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
void __init at91_add_device_serial(void) {}
#endif
@@ -1775,6 +1839,9 @@ void __init at91_add_device_serial(void) {}
*/
static int __init at91_add_standard_devices(void)
{
+ if (of_have_populated_dt())
+ return 0;
+
at91_add_device_hdmac();
at91_add_device_rtc();
at91_add_device_rtt();
diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c
new file mode 100644
index 000000000000..08494664ab78
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9n12.c
@@ -0,0 +1,233 @@
+/*
+ * SoC specific setup code for the AT91SAM9N12
+ *
+ * Copyright (C) 2012 Atmel Corporation.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/at91sam9n12.h>
+#include <mach/at91_pmc.h>
+#include <mach/cpu.h>
+#include <mach/board.h>
+
+#include "soc.h"
+#include "generic.h"
+#include "clock.h"
+#include "sam9_smc.h"
+
+/* --------------------------------------------------------------------
+ * Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk pioAB_clk = {
+ .name = "pioAB_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_PIOAB,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioCD_clk = {
+ .name = "pioCD_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_PIOCD,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+ .name = "usart0_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_USART0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+ .name = "usart1_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_USART1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+ .name = "usart2_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_USART2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart3_clk = {
+ .name = "usart3_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_USART3,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi0_clk = {
+ .name = "twi0_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_TWI0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi1_clk = {
+ .name = "twi1_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_TWI1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc_clk = {
+ .name = "mci_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_MCI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+ .name = "spi0_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_SPI0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi1_clk = {
+ .name = "spi1_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_SPI1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk uart0_clk = {
+ .name = "uart0_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_UART0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk uart1_clk = {
+ .name = "uart1_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_UART1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tcb_clk = {
+ .name = "tcb_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_TCB,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pwm_clk = {
+ .name = "pwm_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_PWM,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk adc_clk = {
+ .name = "adc_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_ADC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk dma_clk = {
+ .name = "dma_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_DMA,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk uhp_clk = {
+ .name = "uhp",
+ .pmc_mask = 1 << AT91SAM9N12_ID_UHP,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk udp_clk = {
+ .name = "udp_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_UDP,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk lcdc_clk = {
+ .name = "lcdc_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_LCDC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ssc_clk = {
+ .name = "ssc_clk",
+ .pmc_mask = 1 << AT91SAM9N12_ID_SSC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+ &pioAB_clk,
+ &pioCD_clk,
+ &usart0_clk,
+ &usart1_clk,
+ &usart2_clk,
+ &usart3_clk,
+ &twi0_clk,
+ &twi1_clk,
+ &mmc_clk,
+ &spi0_clk,
+ &spi1_clk,
+ &lcdc_clk,
+ &uart0_clk,
+ &uart1_clk,
+ &tcb_clk,
+ &pwm_clk,
+ &adc_clk,
+ &dma_clk,
+ &uhp_clk,
+ &udp_clk,
+ &ssc_clk,
+};
+
+static struct clk_lookup periph_clocks_lookups[] = {
+ /* lookup table for DT entries */
+ CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
+ CLKDEV_CON_DEV_ID("usart", "f801c000.serial", &usart0_clk),
+ CLKDEV_CON_DEV_ID("usart", "f8020000.serial", &usart1_clk),
+ CLKDEV_CON_DEV_ID("usart", "f8024000.serial", &usart2_clk),
+ CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
+ CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb_clk),
+ CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb_clk),
+ CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk),
+ CLKDEV_CON_ID("pioA", &pioAB_clk),
+ CLKDEV_CON_ID("pioB", &pioAB_clk),
+ CLKDEV_CON_ID("pioC", &pioCD_clk),
+ CLKDEV_CON_ID("pioD", &pioCD_clk),
+ /* additional fake clock for macb_hclk */
+ CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &uhp_clk),
+ CLKDEV_CON_DEV_ID("ohci_clk", "500000.ohci", &uhp_clk),
+};
+
+/*
+ * The two programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+ .name = "pck0",
+ .pmc_mask = AT91_PMC_PCK0,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 0,
+};
+static struct clk pck1 = {
+ .name = "pck1",
+ .pmc_mask = AT91_PMC_PCK1,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 1,
+};
+
+static void __init at91sam9n12_register_clocks(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+ clk_register(periph_clocks[i]);
+ clk_register(&pck0);
+ clk_register(&pck1);
+
+ clkdev_add_table(periph_clocks_lookups,
+ ARRAY_SIZE(periph_clocks_lookups));
+
+}
+
+/* --------------------------------------------------------------------
+ * AT91SAM9N12 processor initialization
+ * -------------------------------------------------------------------- */
+
+static void __init at91sam9n12_map_io(void)
+{
+ at91_init_sram(0, AT91SAM9N12_SRAM_BASE, AT91SAM9N12_SRAM_SIZE);
+}
+
+void __init at91sam9n12_initialize(void)
+{
+ at91_extern_irq = (1 << AT91SAM9N12_ID_IRQ0);
+
+ /* Register GPIO subsystem (using DT) */
+ at91_gpio_init(NULL, 0);
+}
+
+struct at91_init_soc __initdata at91sam9n12_soc = {
+ .map_io = at91sam9n12_map_io,
+ .register_clocks = at91sam9n12_register_clocks,
+ .init = at91sam9n12_initialize,
+};
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index d9f2774f385e..e420085a57ef 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -232,18 +232,6 @@ static void __init at91sam9rl_register_clocks(void)
clk_register(&pck1);
}
-static struct clk_lookup console_clock_lookup;
-
-void __init at91sam9rl_set_console_clock(int id)
-{
- if (id >= ARRAY_SIZE(usart_clocks_lookups))
- return;
-
- console_clock_lookup.con_id = "usart";
- console_clock_lookup.clk = usart_clocks_lookups[id].clk;
- clkdev_add(&console_clock_lookup);
-}
-
/* --------------------------------------------------------------------
* GPIO
* -------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index fe4ae22e8561..9c0b1481a9a7 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -1192,14 +1192,6 @@ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
at91_uarts[portnr] = pdev;
}
-void __init at91_set_serial_console(unsigned portnr)
-{
- if (portnr < ATMEL_MAX_UART) {
- atmel_default_console_device = at91_uarts[portnr];
- at91sam9rl_set_console_clock(at91_uarts[portnr]->id);
- }
-}
-
void __init at91_add_device_serial(void)
{
int i;
@@ -1208,13 +1200,9 @@ void __init at91_add_device_serial(void)
if (at91_uarts[i])
platform_device_register(at91_uarts[i]);
}
-
- if (!atmel_default_console_device)
- printk(KERN_INFO "AT91: No default serial console defined.\n");
}
#else
void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
void __init at91_add_device_serial(void) {}
#endif
diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
index 13c8cae60462..1b144b4d3ce1 100644
--- a/arch/arm/mach-at91/at91sam9x5.c
+++ b/arch/arm/mach-at91/at91sam9x5.c
@@ -120,6 +120,11 @@ static struct clk adc_clk = {
.pmc_mask = 1 << AT91SAM9X5_ID_ADC,
.type = CLK_TYPE_PERIPHERAL,
};
+static struct clk adc_op_clk = {
+ .name = "adc_op_clk",
+ .type = CLK_TYPE_PERIPHERAL,
+ .rate_hz = 5000000,
+};
static struct clk dma0_clk = {
.name = "dma0_clk",
.pmc_mask = 1 << AT91SAM9X5_ID_DMA0,
@@ -205,6 +210,7 @@ static struct clk *periph_clocks[] __initdata = {
&tcb0_clk,
&pwm_clk,
&adc_clk,
+ &adc_op_clk,
&dma0_clk,
&dma1_clk,
&uhphs_clk,
diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
index 2628384aaae1..271f994314a4 100644
--- a/arch/arm/mach-at91/board-1arm.c
+++ b/arch/arm/mach-at91/board-1arm.c
@@ -47,20 +47,6 @@ static void __init onearm_init_early(void)
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* USART1 on ttyS2 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
static struct macb_platform_data __initdata onearm_eth_data = {
@@ -82,6 +68,16 @@ static struct at91_udc_data __initdata onearm_udc_data = {
static void __init onearm_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
+ at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
+
+ /* USART1 on ttyS2 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
at91_add_device_serial();
/* Ethernet */
at91_add_device_eth(&onearm_eth_data);
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index 161efbaa1029..b7d8aa7b81e6 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -52,22 +52,6 @@ static void __init afeb9260_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91SAM9260_ID_US0, 1,
- ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR
- | ATMEL_UART_DCD | ATMEL_UART_RI);
-
- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9260_ID_US1, 2,
- ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -183,6 +167,18 @@ static struct at91_cf_data afeb9260_cf_data = {
static void __init afeb9260_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91SAM9260_ID_US0, 1,
+ ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR
+ | ATMEL_UART_DCD | ATMEL_UART_RI);
+
+ /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
+ at91_register_uart(AT91SAM9260_ID_US1, 2,
+ ATMEL_UART_CTS | ATMEL_UART_RTS);
at91_add_device_serial();
/* USB Host */
at91_add_device_usbh(&afeb9260_usbh_data);
diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
index c6d44ee0c77e..29d3ef0a50fb 100644
--- a/arch/arm/mach-at91/board-cam60.c
+++ b/arch/arm/mach-at91/board-cam60.c
@@ -49,12 +49,6 @@ static void __init cam60_init_early(void)
{
/* Initialize processor: 10 MHz crystal */
at91_initialize(10000000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -175,6 +169,8 @@ static void __init cam60_add_device_nand(void)
static void __init cam60_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
at91_add_device_serial();
/* SPI */
at91_add_device_spi(cam60_spi_devices, ARRAY_SIZE(cam60_spi_devices));
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index 59d9cf997537..44328a6d4609 100644
--- a/arch/arm/mach-at91/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -44,17 +44,6 @@ static void __init carmeva_init_early(void)
{
/* Initialize processor: 20.000 MHz crystal */
at91_initialize(20000000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
static struct macb_platform_data __initdata carmeva_eth_data = {
@@ -139,6 +128,13 @@ static struct gpio_led carmeva_leds[] = {
static void __init carmeva_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
at91_add_device_serial();
/* Ethernet */
at91_add_device_eth(&carmeva_eth_data);
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index 5f3680e7c883..69951ec7dbf3 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -52,34 +52,6 @@ static void __init cpu9krea_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* DGBU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS |
- ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR |
- ATMEL_UART_DCD | ATMEL_UART_RI);
-
- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS |
- ATMEL_UART_RTS);
-
- /* USART2 on ttyS3. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS |
- ATMEL_UART_RTS);
-
- /* USART3 on ttyS4. (Rx, Tx) */
- at91_register_uart(AT91SAM9260_ID_US3, 4, 0);
-
- /* USART4 on ttyS5. (Rx, Tx) */
- at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
-
- /* USART5 on ttyS6. (Rx, Tx) */
- at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -352,6 +324,30 @@ static void __init cpu9krea_board_init(void)
/* NOR */
cpu9krea_add_device_nor();
/* Serial */
+ /* DGBU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS |
+ ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR |
+ ATMEL_UART_DCD | ATMEL_UART_RI);
+
+ /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS |
+ ATMEL_UART_RTS);
+
+ /* USART2 on ttyS3. (Rx, Tx, RTS, CTS) */
+ at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS |
+ ATMEL_UART_RTS);
+
+ /* USART3 on ttyS4. (Rx, Tx) */
+ at91_register_uart(AT91SAM9260_ID_US3, 4, 0);
+
+ /* USART4 on ttyS5. (Rx, Tx) */
+ at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
+
+ /* USART5 on ttyS6. (Rx, Tx) */
+ at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
at91_add_device_serial();
/* USB Host */
at91_add_device_usbh(&cpu9krea_usbh_data);
diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
index e094cc81fe25..895cf2dba612 100644
--- a/arch/arm/mach-at91/board-cpuat91.c
+++ b/arch/arm/mach-at91/board-cpuat91.c
@@ -59,28 +59,6 @@ static void __init cpuat91_init_early(void)
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS |
- ATMEL_UART_RTS);
-
- /* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS |
- ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR |
- ATMEL_UART_DCD | ATMEL_UART_RI);
-
- /* USART2 on ttyS3 (Rx, Tx) */
- at91_register_uart(AT91RM9200_ID_US2, 3, 0);
-
- /* USART3 on ttyS4 (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_CTS |
- ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
static struct macb_platform_data __initdata cpuat91_eth_data = {
@@ -161,6 +139,24 @@ static struct platform_device *platform_devices[] __initdata = {
static void __init cpuat91_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
+ at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS |
+ ATMEL_UART_RTS);
+
+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS |
+ ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR |
+ ATMEL_UART_DCD | ATMEL_UART_RI);
+
+ /* USART2 on ttyS3 (Rx, Tx) */
+ at91_register_uart(AT91RM9200_ID_US2, 3, 0);
+
+ /* USART3 on ttyS4 (Rx, Tx, CTS, RTS) */
+ at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_CTS |
+ ATMEL_UART_RTS);
at91_add_device_serial();
/* LEDs. */
at91_gpio_leds(cpuat91_leds, ARRAY_SIZE(cpuat91_leds));
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index 1a1547b1ce4e..cd813361cd26 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -47,15 +47,6 @@ static void __init csb337_init_early(void)
{
/* Initialize processor: 3.6864 MHz crystal */
at91_initialize(3686400);
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
-
- /* DBGU on ttyS0 */
- at91_register_uart(0, 0, 0);
-
- /* make console=ttyS0 the default */
- at91_set_serial_console(0);
}
static struct macb_platform_data __initdata csb337_eth_data = {
@@ -228,7 +219,11 @@ static struct gpio_led csb_leds[] = {
static void __init csb337_board_init(void)
{
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
/* Serial */
+ /* DBGU on ttyS0 */
+ at91_register_uart(0, 0, 0);
at91_add_device_serial();
/* Ethernet */
at91_add_device_eth(&csb337_eth_data);
diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
index f650bf39455d..7c8b05a57d7f 100644
--- a/arch/arm/mach-at91/board-csb637.c
+++ b/arch/arm/mach-at91/board-csb637.c
@@ -44,12 +44,6 @@ static void __init csb637_init_early(void)
{
/* Initialize processor: 3.6864 MHz crystal */
at91_initialize(3686400);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* make console=ttyS0 (ie, DBGU) the default */
- at91_set_serial_console(0);
}
static struct macb_platform_data __initdata csb637_eth_data = {
@@ -118,6 +112,8 @@ static void __init csb637_board_init(void)
/* LED(s) */
at91_gpio_leds(csb_leds, ARRAY_SIZE(csb_leds));
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
at91_add_device_serial();
/* Ethernet */
at91_add_device_eth(&csb637_eth_data);
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
index c18d4d307801..a1fce05aa7a5 100644
--- a/arch/arm/mach-at91/board-dt.c
+++ b/arch/arm/mach-at91/board-dt.c
@@ -1,10 +1,6 @@
/*
* Setup code for AT91SAM Evaluation Kits with Device Tree support
*
- * Covers: * AT91SAM9G45-EKES board
- * * AT91SAM9M10-EKES board
- * * AT91SAM9M10G45-EK board
- *
* Copyright (C) 2011 Atmel,
* 2011 Nicolas Ferre <nicolas.ferre@atmel.com>
*
@@ -49,9 +45,7 @@ static void __init at91_dt_device_init(void)
}
static const char *at91_dt_board_compat[] __initdata = {
- "atmel,at91sam9m10g45ek",
- "atmel,at91sam9x5ek",
- "calao,usb-a9g20",
+ "atmel,at91sam9",
NULL
};
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
index d302ca3eeb64..bd1017297989 100644
--- a/arch/arm/mach-at91/board-eb9200.c
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -44,20 +44,6 @@ static void __init eb9200_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* USART2 on ttyS2. (Rx, Tx) - IRDA */
- at91_register_uart(AT91RM9200_ID_US2, 2, 0);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
static struct macb_platform_data __initdata eb9200_eth_data = {
@@ -101,6 +87,16 @@ static struct i2c_board_info __initdata eb9200_i2c_devices[] = {
static void __init eb9200_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
+
+ /* USART2 on ttyS2. (Rx, Tx) - IRDA */
+ at91_register_uart(AT91RM9200_ID_US2, 2, 0);
at91_add_device_serial();
/* Ethernet */
at91_add_device_eth(&eb9200_eth_data);
diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
index 69966ce4d776..89cc3726a9ce 100644
--- a/arch/arm/mach-at91/board-ecbat91.c
+++ b/arch/arm/mach-at91/board-ecbat91.c
@@ -50,18 +50,6 @@ static void __init ecb_at91init_early(void)
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PC7, AT91_PIN_PC7);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1. (Rx & Tx only) */
- at91_register_uart(AT91RM9200_ID_US0, 1, 0);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
static struct macb_platform_data __initdata ecb_at91eth_data = {
@@ -151,7 +139,15 @@ static struct spi_board_info __initdata ecb_at91spi_devices[] = {
static void __init ecb_at91board_init(void)
{
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PC7, AT91_PIN_PC7);
+
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1. (Rx & Tx only) */
+ at91_register_uart(AT91RM9200_ID_US0, 1, 0);
at91_add_device_serial();
/* Ethernet */
diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
index f23aabef8551..558546cf63f4 100644
--- a/arch/arm/mach-at91/board-eco920.c
+++ b/arch/arm/mach-at91/board-eco920.c
@@ -37,15 +37,6 @@ static void __init eco920_init_early(void)
at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
at91_initialize(18432000);
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
-
- /* DBGU on ttyS0. (Rx & Tx only */
- at91_register_uart(0, 0, 0);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
static struct macb_platform_data __initdata eco920_eth_data = {
@@ -103,6 +94,10 @@ static struct spi_board_info eco920_spi_devices[] = {
static void __init eco920_board_init(void)
{
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
+ /* DBGU on ttyS0. (Rx & Tx only */
+ at91_register_uart(0, 0, 0);
at91_add_device_serial();
at91_add_device_eth(&eco920_eth_data);
at91_add_device_usbh(&eco920_usbh_data);
diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
index 1815152001f7..47658f78105d 100644
--- a/arch/arm/mach-at91/board-flexibity.c
+++ b/arch/arm/mach-at91/board-flexibity.c
@@ -41,12 +41,6 @@ static void __init flexibity_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/* USB Host port */
@@ -143,6 +137,8 @@ static struct gpio_led flexibity_leds[] = {
static void __init flexibity_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
at91_add_device_serial();
/* USB Host */
at91_add_device_usbh(&flexibity_usbh_data);
diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c
index caf017f0f4ee..33411e6ecb1f 100644
--- a/arch/arm/mach-at91/board-foxg20.c
+++ b/arch/arm/mach-at91/board-foxg20.c
@@ -61,44 +61,6 @@ static void __init foxg20_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91SAM9260_ID_US0, 1,
- ATMEL_UART_CTS
- | ATMEL_UART_RTS
- | ATMEL_UART_DTR
- | ATMEL_UART_DSR
- | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9260_ID_US1, 2,
- ATMEL_UART_CTS
- | ATMEL_UART_RTS);
-
- /* USART2 on ttyS3. (Rx & Tx only) */
- at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
-
- /* USART3 on ttyS4. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9260_ID_US3, 4,
- ATMEL_UART_CTS
- | ATMEL_UART_RTS);
-
- /* USART4 on ttyS5. (Rx & Tx only) */
- at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
-
- /* USART5 on ttyS6. (Rx & Tx only) */
- at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
-
- /* Set the internal pull-up resistor on DRXD */
- at91_set_A_periph(AT91_PIN_PB14, 1);
-
}
/*
@@ -241,6 +203,39 @@ static struct i2c_board_info __initdata foxg20_i2c_devices[] = {
static void __init foxg20_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91SAM9260_ID_US0, 1,
+ ATMEL_UART_CTS
+ | ATMEL_UART_RTS
+ | ATMEL_UART_DTR
+ | ATMEL_UART_DSR
+ | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
+
+ /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
+ at91_register_uart(AT91SAM9260_ID_US1, 2,
+ ATMEL_UART_CTS
+ | ATMEL_UART_RTS);
+
+ /* USART2 on ttyS3. (Rx & Tx only) */
+ at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
+
+ /* USART3 on ttyS4. (Rx, Tx, RTS, CTS) */
+ at91_register_uart(AT91SAM9260_ID_US3, 4,
+ ATMEL_UART_CTS
+ | ATMEL_UART_RTS);
+
+ /* USART4 on ttyS5. (Rx & Tx only) */
+ at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
+
+ /* USART5 on ttyS6. (Rx & Tx only) */
+ at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
+
+ /* Set the internal pull-up resistor on DRXD */
+ at91_set_A_periph(AT91_PIN_PB14, 1);
at91_add_device_serial();
/* USB Host */
at91_add_device_usbh(&foxg20_usbh_data);
diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c
index 230e71969fb7..3e0dfa643a86 100644
--- a/arch/arm/mach-at91/board-gsia18s.c
+++ b/arch/arm/mach-at91/board-gsia18s.c
@@ -41,38 +41,6 @@
static void __init gsia18s_init_early(void)
{
stamp9g20_init_early();
-
- /*
- * USART0 on ttyS1 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI).
- * Used for Internal Analog Modem.
- */
- at91_register_uart(AT91SAM9260_ID_US0, 1,
- ATMEL_UART_CTS | ATMEL_UART_RTS |
- ATMEL_UART_DTR | ATMEL_UART_DSR |
- ATMEL_UART_DCD | ATMEL_UART_RI);
- /*
- * USART1 on ttyS2 (Rx, Tx, CTS, RTS).
- * Used for GPS or WiFi or Data stream.
- */
- at91_register_uart(AT91SAM9260_ID_US1, 2,
- ATMEL_UART_CTS | ATMEL_UART_RTS);
- /*
- * USART2 on ttyS3 (Rx, Tx, CTS, RTS).
- * Used for External Modem.
- */
- at91_register_uart(AT91SAM9260_ID_US2, 3,
- ATMEL_UART_CTS | ATMEL_UART_RTS);
- /*
- * USART3 on ttyS4 (Rx, Tx, RTS).
- * Used for RS-485.
- */
- at91_register_uart(AT91SAM9260_ID_US3, 4, ATMEL_UART_RTS);
-
- /*
- * USART4 on ttyS5 (Rx, Tx).
- * Used for TRX433 Radio Module.
- */
- at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
}
/*
@@ -558,6 +526,37 @@ static int __init gsia18s_power_off_init(void)
static void __init gsia18s_board_init(void)
{
+ /*
+ * USART0 on ttyS1 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI).
+ * Used for Internal Analog Modem.
+ */
+ at91_register_uart(AT91SAM9260_ID_US0, 1,
+ ATMEL_UART_CTS | ATMEL_UART_RTS |
+ ATMEL_UART_DTR | ATMEL_UART_DSR |
+ ATMEL_UART_DCD | ATMEL_UART_RI);
+ /*
+ * USART1 on ttyS2 (Rx, Tx, CTS, RTS).
+ * Used for GPS or WiFi or Data stream.
+ */
+ at91_register_uart(AT91SAM9260_ID_US1, 2,
+ ATMEL_UART_CTS | ATMEL_UART_RTS);
+ /*
+ * USART2 on ttyS3 (Rx, Tx, CTS, RTS).
+ * Used for External Modem.
+ */
+ at91_register_uart(AT91SAM9260_ID_US2, 3,
+ ATMEL_UART_CTS | ATMEL_UART_RTS);
+ /*
+ * USART3 on ttyS4 (Rx, Tx, RTS).
+ * Used for RS-485.
+ */
+ at91_register_uart(AT91SAM9260_ID_US3, 4, ATMEL_UART_RTS);
+
+ /*
+ * USART4 on ttyS5 (Rx, Tx).
+ * Used for TRX433 Radio Module.
+ */
+ at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
stamp9g20_board_init();
at91_add_device_usbh(&usbh_data);
at91_add_device_udc(&udc_data);
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
index efde1b2327c8..f260657f32bc 100644
--- a/arch/arm/mach-at91/board-kafa.c
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -47,18 +47,6 @@ static void __init kafa_init_early(void)
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* Set up the LEDs */
- at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
static struct macb_platform_data __initdata kafa_eth_data = {
@@ -79,7 +67,15 @@ static struct at91_udc_data __initdata kafa_udc_data = {
static void __init kafa_board_init(void)
{
+ /* Set up the LEDs */
+ at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
+
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
+ at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
at91_add_device_serial();
/* Ethernet */
at91_add_device_eth(&kafa_eth_data);
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index 59b92aab9bcf..ba39db5482b9 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -50,24 +50,6 @@ static void __init kb9202_init_early(void)
/* Initialize processor: 10 MHz crystal */
at91_initialize(10000000);
-
- /* Set up the LEDs */
- at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1 (Rx & Tx only) */
- at91_register_uart(AT91RM9200_ID_US0, 1, 0);
-
- /* USART1 on ttyS2 (Rx & Tx only) - IRDA (optional) */
- at91_register_uart(AT91RM9200_ID_US1, 2, 0);
-
- /* USART3 on ttyS3 (Rx, Tx, CTS, RTS) - RS485 (optional) */
- at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
static struct macb_platform_data __initdata kb9202_eth_data = {
@@ -115,7 +97,21 @@ static struct atmel_nand_data __initdata kb9202_nand_data = {
static void __init kb9202_board_init(void)
{
+ /* Set up the LEDs */
+ at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
+
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1 (Rx & Tx only) */
+ at91_register_uart(AT91RM9200_ID_US0, 1, 0);
+
+ /* USART1 on ttyS2 (Rx & Tx only) - IRDA (optional) */
+ at91_register_uart(AT91RM9200_ID_US1, 2, 0);
+
+ /* USART3 on ttyS3 (Rx, Tx, CTS, RTS) - RS485 (optional) */
+ at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
at91_add_device_serial();
/* Ethernet */
at91_add_device_eth(&kb9202_eth_data);
diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
index 57d5f6a4726a..d2f4cc161766 100644
--- a/arch/arm/mach-at91/board-neocore926.c
+++ b/arch/arm/mach-at91/board-neocore926.c
@@ -55,15 +55,6 @@ static void __init neocore926_init_early(void)
{
/* Initialize processor: 20 MHz crystal */
at91_initialize(20000000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -341,6 +332,11 @@ static struct ac97c_platform_data neocore926_ac97_data = {
static void __init neocore926_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
+ at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
at91_add_device_serial();
/* USB Host */
diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
index b4a12fc184c8..7fe638342421 100644
--- a/arch/arm/mach-at91/board-pcontrol-g20.c
+++ b/arch/arm/mach-at91/board-pcontrol-g20.c
@@ -40,17 +40,6 @@
static void __init pcontrol_g20_init_early(void)
{
stamp9g20_init_early();
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback A2 */
- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS
- | ATMEL_UART_RTS);
-
- /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) isolated RS485 X5 */
- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS
- | ATMEL_UART_RTS);
-
- /* USART2 on ttyS3. (Rx, Tx) 9bit-Bus Multidrop-mode X4 */
- at91_register_uart(AT91SAM9260_ID_US4, 3, 0);
}
static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
@@ -199,6 +188,16 @@ static struct spi_board_info pcontrol_g20_spi_devices[] = {
static void __init pcontrol_g20_board_init(void)
{
+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback A2 */
+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS
+ | ATMEL_UART_RTS);
+
+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) isolated RS485 X5 */
+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS
+ | ATMEL_UART_RTS);
+
+ /* USART2 on ttyS3. (Rx, Tx) 9bit-Bus Multidrop-mode X4 */
+ at91_register_uart(AT91SAM9260_ID_US4, 3, 0);
stamp9g20_board_init();
at91_add_device_usbh(&usbh_data);
at91_add_device_eth(&macb_data);
diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
index 59e35dd14863..b45c0a5d5ca7 100644
--- a/arch/arm/mach-at91/board-picotux200.c
+++ b/arch/arm/mach-at91/board-picotux200.c
@@ -48,17 +48,6 @@ static void __init picotux200_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
static struct macb_platform_data __initdata picotux200_eth_data = {
@@ -106,6 +95,13 @@ static struct platform_device picotux200_flash = {
static void __init picotux200_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
at91_add_device_serial();
/* Ethernet */
at91_add_device_eth(&picotux200_eth_data);
diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
index b6ed5ed7081a..0c61bf0d272c 100644
--- a/arch/arm/mach-at91/board-qil-a9260.c
+++ b/arch/arm/mach-at91/board-qil-a9260.c
@@ -52,24 +52,6 @@ static void __init ek_init_early(void)
{
/* Initialize processor: 12.000 MHz crystal */
at91_initialize(12000000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* USART2 on ttyS3. (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* set serial console to ttyS1 (ie, USART0) */
- at91_set_serial_console(1);
-
}
/*
@@ -235,6 +217,19 @@ static struct gpio_led ek_leds[] = {
static void __init ek_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
+
+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
+
+ /* USART2 on ttyS3. (Rx, Tx, CTS, RTS) */
+ at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
at91_add_device_serial();
/* USB Host */
at91_add_device_usbh(&ek_usbh_data);
diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
index 01332aa538b2..afd7a4713766 100644
--- a/arch/arm/mach-at91/board-rm9200dk.c
+++ b/arch/arm/mach-at91/board-rm9200dk.c
@@ -50,20 +50,6 @@ static void __init dk_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
static struct macb_platform_data __initdata dk_eth_data = {
@@ -190,7 +176,17 @@ static struct gpio_led dk_leds[] = {
static void __init dk_board_init(void)
{
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
at91_add_device_serial();
/* Ethernet */
at91_add_device_eth(&dk_eth_data);
diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
index b2e4fe21f346..2b15b8adec4c 100644
--- a/arch/arm/mach-at91/board-rm9200ek.c
+++ b/arch/arm/mach-at91/board-rm9200ek.c
@@ -50,20 +50,6 @@ static void __init ek_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
static struct macb_platform_data __initdata ek_eth_data = {
@@ -161,7 +147,17 @@ static struct gpio_led ek_leds[] = {
static void __init ek_board_init(void)
{
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
+
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
at91_add_device_serial();
/* Ethernet */
at91_add_device_eth(&ek_eth_data);
diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c
index af0750fafa29..24ab9be7510f 100644
--- a/arch/arm/mach-at91/board-rsi-ews.c
+++ b/arch/arm/mach-at91/board-rsi-ews.c
@@ -35,26 +35,6 @@ static void __init rsi_ews_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PB6, AT91_PIN_PB9);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- /* This one is for debugging */
- at91_register_uart(0, 0, 0);
-
- /* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- /* Dialin/-out modem interface */
- at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* USART3 on ttyS4. (Rx, Tx, RTS) */
- /* RS485 communication */
- at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -204,7 +184,23 @@ static struct platform_device rsiews_nor_flash = {
*/
static void __init rsi_ews_board_init(void)
{
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB6, AT91_PIN_PB9);
+
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ /* This one is for debugging */
+ at91_register_uart(0, 0, 0);
+
+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ /* Dialin/-out modem interface */
+ at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
+
+ /* USART3 on ttyS4. (Rx, Tx, RTS) */
+ /* RS485 communication */
+ at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_RTS);
at91_add_device_serial();
at91_set_gpio_output(AT91_PIN_PA21, 0);
/* Ethernet */
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index e8b116b6cba6..cdd21f2595d2 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -48,23 +48,6 @@ static void __init ek_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PA9, AT91_PIN_PA6);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -184,7 +167,20 @@ static struct at91_mmc_data __initdata ek_mmc_data = {
static void __init ek_board_init(void)
{
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PA9, AT91_PIN_PA6);
+
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
+
+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
at91_add_device_serial();
/* USB Host */
at91_add_device_usbh(&ek_usbh_data);
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index d5aec55b0eb4..7b3c3913551a 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -54,20 +54,6 @@ static void __init ek_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -320,6 +306,16 @@ static void __init ek_add_device_buttons(void) {}
static void __init ek_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
+
+ /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
at91_add_device_serial();
/* USB Host */
at91_add_device_usbh(&ek_usbh_data);
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 065fed342424..2736453821b0 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -58,15 +58,6 @@ static void __init ek_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PA13, AT91_PIN_PA14);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -577,7 +568,12 @@ static struct gpio_led ek_leds[] = {
static void __init ek_board_init(void)
{
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PA13, AT91_PIN_PA14);
+
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
at91_add_device_serial();
/* USB Host */
at91_add_device_usbh(&ek_usbh_data);
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 2ffe50f3a9e9..983cb98d2465 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -57,15 +57,6 @@ static void __init ek_init_early(void)
{
/* Initialize processor: 16.367 MHz crystal */
at91_initialize(16367660);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -412,6 +403,11 @@ static struct at91_can_data ek_can_data = {
static void __init ek_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
+ at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
at91_add_device_serial();
/* USB Host */
at91_add_device_usbh(&ek_usbh_data);
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index 8923ec9f5831..6860d3451100 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -32,6 +32,8 @@
#include <linux/regulator/fixed.h>
#include <linux/regulator/consumer.h>
+#include <linux/platform_data/at91_adc.h>
+
#include <mach/hardware.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
@@ -65,20 +67,6 @@ static void __init ek_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -318,6 +306,16 @@ static void __init ek_add_device_buttons(void)
static void __init ek_add_device_buttons(void) {}
#endif
+/*
+ * ADCs
+ */
+
+static struct at91_adc_data ek_adc_data = {
+ .channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3),
+ .use_external_triggers = true,
+ .vref = 3300,
+};
+
#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
static struct regulator_consumer_supply ek_audio_consumer_supplies[] = {
REGULATOR_SUPPLY("AVDD", "0-001b"),
@@ -372,6 +370,16 @@ static struct i2c_board_info __initdata ek_i2c_devices[] = {
static void __init ek_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
+
+ /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
at91_add_device_serial();
/* USB Host */
at91_add_device_usbh(&ek_usbh_data);
@@ -393,6 +401,8 @@ static void __init ek_board_init(void)
ek_add_device_gpio_leds();
/* Push Buttons */
ek_add_device_buttons();
+ /* ADCs */
+ at91_add_device_adc(&ek_adc_data);
/* PCK0 provides MCLK to the WM8731 */
at91_set_B_periph(AT91_PIN_PC1, 0);
/* SSC (for WM8731) */
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index c88e908ddd82..63163dc7df46 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -27,6 +27,8 @@
#include <linux/atmel-mci.h>
#include <linux/delay.h>
+#include <linux/platform_data/at91_adc.h>
+
#include <mach/hardware.h>
#include <video/atmel_lcdc.h>
#include <media/soc_camera.h>
@@ -53,16 +55,6 @@ static void __init ek_init_early(void)
{
/* Initialize processor: 12.000 MHz crystal */
at91_initialize(12000000);
-
- /* DGBU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 not connected on the -EK board */
- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9G45_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -315,6 +307,14 @@ static struct at91_tsadcc_data ek_tsadcc_data = {
.ts_sample_hold_time = 0x0a,
};
+/*
+ * ADCs
+ */
+static struct at91_adc_data ek_adc_data = {
+ .channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7),
+ .use_external_triggers = true,
+ .vref = 3300,
+};
/*
* GPIO Buttons
@@ -457,6 +457,12 @@ static struct platform_device *devices[] __initdata = {
static void __init ek_board_init(void)
{
/* Serial */
+ /* DGBU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 not connected on the -EK board */
+ /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
+ at91_register_uart(AT91SAM9G45_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
at91_add_device_serial();
/* USB HS Host */
at91_add_device_usbh_ohci(&ek_usbh_hs_data);
@@ -480,6 +486,8 @@ static void __init ek_board_init(void)
at91_add_device_lcdc(&ek_lcdc_data);
/* Touch Screen */
at91_add_device_tsadcc(&ek_tsadcc_data);
+ /* ADC */
+ at91_add_device_adc(&ek_adc_data);
/* Push Buttons */
ek_add_device_buttons();
/* AC97 */
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index b109ce2ba864..be3239f13daa 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -42,15 +42,6 @@ static void __init ek_init_early(void)
{
/* Initialize processor: 12.000 MHz crystal */
at91_initialize(12000000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91SAM9RL_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -296,6 +287,11 @@ static void __init ek_add_device_buttons(void) {}
static void __init ek_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
+ at91_register_uart(AT91SAM9RL_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
at91_add_device_serial();
/* USB HS */
at91_add_device_usba(&ek_usba_udc_data);
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index ebc9d01ce742..9d446f1bb45f 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -43,16 +43,6 @@
static void __init snapper9260_init_early(void)
{
at91_initialize(18432000);
-
- /* Debug on ttyS0 */
- at91_register_uart(0, 0, 0);
- at91_set_serial_console(0);
-
- at91_register_uart(AT91SAM9260_ID_US0, 1,
- ATMEL_UART_CTS | ATMEL_UART_RTS);
- at91_register_uart(AT91SAM9260_ID_US1, 2,
- ATMEL_UART_CTS | ATMEL_UART_RTS);
- at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
}
static struct at91_usbh_data __initdata snapper9260_usbh_data = {
@@ -168,6 +158,14 @@ static void __init snapper9260_board_init(void)
snapper9260_i2c_isl1208.irq = gpio_to_irq(AT91_PIN_PA31);
i2c_register_board_info(0, &snapper9260_i2c_isl1208, 1);
+ /* Debug on ttyS0 */
+ at91_register_uart(0, 0, 0);
+
+ at91_register_uart(AT91SAM9260_ID_US0, 1,
+ ATMEL_UART_CTS | ATMEL_UART_RTS);
+ at91_register_uart(AT91SAM9260_ID_US1, 2,
+ ATMEL_UART_CTS | ATMEL_UART_RTS);
+ at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
at91_add_device_serial();
at91_add_device_usbh(&snapper9260_usbh_data);
at91_add_device_udc(&snapper9260_udc_data);
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
index 7640049410a0..ee86f9d7ee72 100644
--- a/arch/arm/mach-at91/board-stamp9g20.c
+++ b/arch/arm/mach-at91/board-stamp9g20.c
@@ -36,44 +36,6 @@ void __init stamp9g20_init_early(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* DGBU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
-}
-
-static void __init stamp9g20evb_init_early(void)
-{
- stamp9g20_init_early();
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR
- | ATMEL_UART_DCD | ATMEL_UART_RI);
-}
-
-static void __init portuxg20_init_early(void)
-{
- stamp9g20_init_early();
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR
- | ATMEL_UART_DCD | ATMEL_UART_RI);
-
- /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* USART2 on ttyS3. (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* USART4 on ttyS5. (Rx, Tx only) */
- at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
-
- /* USART5 on ttyS6. (Rx, Tx only) */
- at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
}
/*
@@ -254,6 +216,8 @@ void add_w1(void)
void __init stamp9g20_board_init(void)
{
/* Serial */
+ /* DGBU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
at91_add_device_serial();
/* NAND */
add_device_nand();
@@ -269,6 +233,22 @@ void __init stamp9g20_board_init(void)
static void __init portuxg20_board_init(void)
{
+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR
+ | ATMEL_UART_DCD | ATMEL_UART_RI);
+
+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
+
+ /* USART2 on ttyS3. (Rx, Tx, CTS, RTS) */
+ at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
+
+ /* USART4 on ttyS5. (Rx, Tx only) */
+ at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
+
+ /* USART5 on ttyS6. (Rx, Tx only) */
+ at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
stamp9g20_board_init();
/* USB Host */
at91_add_device_usbh(&usbh_data);
@@ -286,6 +266,10 @@ static void __init portuxg20_board_init(void)
static void __init stamp9g20evb_board_init(void)
{
+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR
+ | ATMEL_UART_DCD | ATMEL_UART_RI);
stamp9g20_board_init();
/* USB Host */
at91_add_device_usbh(&usbh_data);
@@ -303,7 +287,7 @@ MACHINE_START(PORTUXG20, "taskit PortuxG20")
/* Maintainer: taskit GmbH */
.timer = &at91sam926x_timer,
.map_io = at91_map_io,
- .init_early = portuxg20_init_early,
+ .init_early = stamp9g20_init_early,
.init_irq = at91_init_irq_default,
.init_machine = portuxg20_board_init,
MACHINE_END
@@ -312,7 +296,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20")
/* Maintainer: taskit GmbH */
.timer = &at91sam926x_timer,
.map_io = at91_map_io,
- .init_early = stamp9g20evb_init_early,
+ .init_early = stamp9g20_init_early,
.init_irq = at91_init_irq_default,
.init_machine = stamp9g20evb_board_init,
MACHINE_END
diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c
index b7483a3d0980..95393fcaf199 100644
--- a/arch/arm/mach-at91/board-usb-a926x.c
+++ b/arch/arm/mach-at91/board-usb-a926x.c
@@ -53,12 +53,6 @@ static void __init ek_init_early(void)
{
/* Initialize processor: 12.00 MHz crystal */
at91_initialize(12000000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -178,6 +172,10 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
.offset = MTDPART_OFS_NXTBLK,
.size = SZ_128K,
}, {
+ .name = "oftree",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_128K,
+ }, {
.name = "kernel",
.offset = MTDPART_OFS_NXTBLK,
.size = 4 * SZ_1M,
@@ -325,6 +323,8 @@ static void __init ek_add_device_leds(void)
static void __init ek_board_init(void)
{
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
at91_add_device_serial();
/* USB Host */
at91_add_device_usbh(&ek_usbh_data);
diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
index 38dd279d30b2..d56665ea4b55 100644
--- a/arch/arm/mach-at91/board-yl-9200.c
+++ b/arch/arm/mach-at91/board-yl-9200.c
@@ -58,26 +58,6 @@ static void __init yl9200_init_early(void)
/* Initialize processor: 18.432 MHz crystal */
at91_initialize(18432000);
-
- /* Setup the LEDs D2=PB17 (timer), D3=PB16 (cpu) */
- at91_init_leds(AT91_PIN_PB16, AT91_PIN_PB17);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* USART0 on ttyS2. (Rx & Tx only to JP3) */
- at91_register_uart(AT91RM9200_ID_US0, 2, 0);
-
- /* USART3 on ttyS3. (Rx, Tx, RTS - RS485 interface) */
- at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
}
/*
@@ -560,7 +540,23 @@ void __init yl9200_add_device_video(void) {}
static void __init yl9200_board_init(void)
{
+ /* Setup the LEDs D2=PB17 (timer), D3=PB16 (cpu) */
+ at91_init_leds(AT91_PIN_PB16, AT91_PIN_PB17);
+
/* Serial */
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
+
+ /* USART0 on ttyS2. (Rx & Tx only to JP3) */
+ at91_register_uart(AT91RM9200_ID_US0, 2, 0);
+
+ /* USART3 on ttyS3. (Rx, Tx, RTS - RS485 interface) */
+ at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_RTS);
at91_add_device_serial();
/* Ethernet */
at91_add_device_eth(&yl9200_eth_data);
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index 6b692824c988..de2ec6b8fea7 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -58,13 +58,15 @@ EXPORT_SYMBOL_GPL(at91_pmc_base);
#define cpu_has_800M_plla() ( cpu_is_at91sam9g20() \
|| cpu_is_at91sam9g45() \
- || cpu_is_at91sam9x5())
+ || cpu_is_at91sam9x5() \
+ || cpu_is_at91sam9n12())
#define cpu_has_300M_plla() (cpu_is_at91sam9g10())
#define cpu_has_pllb() (!(cpu_is_at91sam9rl() \
|| cpu_is_at91sam9g45() \
- || cpu_is_at91sam9x5()))
+ || cpu_is_at91sam9x5() \
+ || cpu_is_at91sam9n12()))
#define cpu_has_upll() (cpu_is_at91sam9g45() \
|| cpu_is_at91sam9x5())
@@ -78,12 +80,15 @@ EXPORT_SYMBOL_GPL(at91_pmc_base);
|| cpu_is_at91sam9x5()))
#define cpu_has_plladiv2() (cpu_is_at91sam9g45() \
- || cpu_is_at91sam9x5())
+ || cpu_is_at91sam9x5() \
+ || cpu_is_at91sam9n12())
#define cpu_has_mdiv3() (cpu_is_at91sam9g45() \
- || cpu_is_at91sam9x5())
+ || cpu_is_at91sam9x5() \
+ || cpu_is_at91sam9n12())
-#define cpu_has_alt_prescaler() (cpu_is_at91sam9x5())
+#define cpu_has_alt_prescaler() (cpu_is_at91sam9x5() \
+ || cpu_is_at91sam9n12())
static LIST_HEAD(clocks);
static DEFINE_SPINLOCK(clk_lock);
diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c
index ece1f9aefb47..0c6381516a5a 100644
--- a/arch/arm/mach-at91/cpuidle.c
+++ b/arch/arm/mach-at91/cpuidle.c
@@ -21,6 +21,7 @@
#include <linux/export.h>
#include <asm/proc-fns.h>
#include <asm/cpuidle.h>
+#include <mach/cpu.h>
#include "pm.h"
@@ -33,7 +34,12 @@ static int at91_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
- at91_standby();
+ if (cpu_is_at91rm9200())
+ at91rm9200_standby();
+ else if (cpu_is_at91sam9g45())
+ at91sam9g45_standby();
+ else
+ at91sam9_standby();
return index;
}
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index dd9b346c451d..0a60bf837037 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -40,17 +40,6 @@ extern struct sys_timer at91sam926x_timer;
extern struct sys_timer at91x40_timer;
/* Clocks */
-/*
- * function to specify the clock of the default console. As we do not
- * use the device/driver bus, the dev_name is not intialize. So we need
- * to link the clock to a specific con_id only "usart"
- */
-extern void __init at91rm9200_set_console_clock(int id);
-extern void __init at91sam9260_set_console_clock(int id);
-extern void __init at91sam9261_set_console_clock(int id);
-extern void __init at91sam9263_set_console_clock(int id);
-extern void __init at91sam9rl_set_console_clock(int id);
-extern void __init at91sam9g45_set_console_clock(int id);
#ifdef CONFIG_AT91_PMC_UNIT
extern int __init at91_clock_init(unsigned long main_clock);
extern int __init at91_dt_clock_init(void);
diff --git a/arch/arm/mach-at91/include/mach/at91rm9200.h b/arch/arm/mach-at91/include/mach/at91rm9200.h
index 603e6aac2a4f..e67317c67761 100644
--- a/arch/arm/mach-at91/include/mach/at91rm9200.h
+++ b/arch/arm/mach-at91/include/mach/at91rm9200.h
@@ -88,11 +88,6 @@
#define AT91RM9200_BASE_RTC 0xfffffe00 /* Real-Time Clock */
#define AT91RM9200_BASE_MC 0xffffff00 /* Memory Controllers */
-#define AT91_USART0 AT91RM9200_BASE_US0
-#define AT91_USART1 AT91RM9200_BASE_US1
-#define AT91_USART2 AT91RM9200_BASE_US2
-#define AT91_USART3 AT91RM9200_BASE_US3
-
/*
* Internal Memory.
*/
diff --git a/arch/arm/mach-at91/include/mach/at91sam9260.h b/arch/arm/mach-at91/include/mach/at91sam9260.h
index 08ae9afd00fe..416c7b6c56d3 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9260.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9260.h
@@ -95,13 +95,6 @@
#define AT91SAM9260_BASE_WDT 0xfffffd40
#define AT91SAM9260_BASE_GPBR 0xfffffd50
-#define AT91_USART0 AT91SAM9260_BASE_US0
-#define AT91_USART1 AT91SAM9260_BASE_US1
-#define AT91_USART2 AT91SAM9260_BASE_US2
-#define AT91_USART3 AT91SAM9260_BASE_US3
-#define AT91_USART4 AT91SAM9260_BASE_US4
-#define AT91_USART5 AT91SAM9260_BASE_US5
-
/*
* Internal Memory.
diff --git a/arch/arm/mach-at91/include/mach/at91sam9261.h b/arch/arm/mach-at91/include/mach/at91sam9261.h
index 44fbdc12ee62..a041406d06ee 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9261.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9261.h
@@ -79,10 +79,6 @@
#define AT91SAM9261_BASE_WDT 0xfffffd40
#define AT91SAM9261_BASE_GPBR 0xfffffd50
-#define AT91_USART0 AT91SAM9261_BASE_US0
-#define AT91_USART1 AT91SAM9261_BASE_US1
-#define AT91_USART2 AT91SAM9261_BASE_US2
-
/*
* Internal Memory.
diff --git a/arch/arm/mach-at91/include/mach/at91sam9263.h b/arch/arm/mach-at91/include/mach/at91sam9263.h
index d96cbb2e03c4..d201029d60b3 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9263.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9263.h
@@ -95,10 +95,6 @@
#define AT91SAM9263_BASE_RTT1 0xfffffd50
#define AT91SAM9263_BASE_GPBR 0xfffffd60
-#define AT91_USART0 AT91SAM9263_BASE_US0
-#define AT91_USART1 AT91SAM9263_BASE_US1
-#define AT91_USART2 AT91SAM9263_BASE_US2
-
#define AT91_SMC AT91_SMC0
/*
diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h
index d052abcff852..3a4da24d5911 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9g45.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9g45.h
@@ -106,11 +106,6 @@
#define AT91SAM9G45_BASE_RTC 0xfffffdb0
#define AT91SAM9G45_BASE_GPBR 0xfffffd60
-#define AT91_USART0 AT91SAM9G45_BASE_US0
-#define AT91_USART1 AT91SAM9G45_BASE_US1
-#define AT91_USART2 AT91SAM9G45_BASE_US2
-#define AT91_USART3 AT91SAM9G45_BASE_US3
-
/*
* Internal Memory.
*/
diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12.h b/arch/arm/mach-at91/include/mach/at91sam9n12.h
new file mode 100644
index 000000000000..d374b87c0459
--- /dev/null
+++ b/arch/arm/mach-at91/include/mach/at91sam9n12.h
@@ -0,0 +1,60 @@
+/*
+ * SoC specific header file for the AT91SAM9N12
+ *
+ * Copyright (C) 2012 Atmel Corporation
+ *
+ * Common definitions, based on AT91SAM9N12 SoC datasheet
+ *
+ * Licensed under GPLv2 or later
+ */
+
+#ifndef _AT91SAM9N12_H_
+#define _AT91SAM9N12_H_
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define AT91SAM9N12_ID_PIOAB 2 /* Parallel I/O Controller A and B */
+#define AT91SAM9N12_ID_PIOCD 3 /* Parallel I/O Controller C and D */
+#define AT91SAM9N12_ID_FUSE 4 /* FUSE Controller */
+#define AT91SAM9N12_ID_USART0 5 /* USART 0 */
+#define AT91SAM9N12_ID_USART1 6 /* USART 1 */
+#define AT91SAM9N12_ID_USART2 7 /* USART 2 */
+#define AT91SAM9N12_ID_USART3 8 /* USART 3 */
+#define AT91SAM9N12_ID_TWI0 9 /* Two-Wire Interface 0 */
+#define AT91SAM9N12_ID_TWI1 10 /* Two-Wire Interface 1 */
+#define AT91SAM9N12_ID_MCI 12 /* High Speed Multimedia Card Interface */
+#define AT91SAM9N12_ID_SPI0 13 /* Serial Peripheral Interface 0 */
+#define AT91SAM9N12_ID_SPI1 14 /* Serial Peripheral Interface 1 */
+#define AT91SAM9N12_ID_UART0 15 /* UART 0 */
+#define AT91SAM9N12_ID_UART1 16 /* UART 1 */
+#define AT91SAM9N12_ID_TCB 17 /* Timer Counter 0, 1, 2, 3, 4 and 5 */
+#define AT91SAM9N12_ID_PWM 18 /* Pulse Width Modulation Controller */
+#define AT91SAM9N12_ID_ADC 19 /* ADC Controller */
+#define AT91SAM9N12_ID_DMA 20 /* DMA Controller */
+#define AT91SAM9N12_ID_UHP 22 /* USB Host High Speed */
+#define AT91SAM9N12_ID_UDP 23 /* USB Device High Speed */
+#define AT91SAM9N12_ID_LCDC 25 /* LCD Controller */
+#define AT91SAM9N12_ID_ISI 25 /* Image Sensor Interface */
+#define AT91SAM9N12_ID_SSC 28 /* Synchronous Serial Controller */
+#define AT91SAM9N12_ID_TRNG 30 /* TRNG */
+#define AT91SAM9N12_ID_IRQ0 31 /* Advanced Interrupt Controller */
+
+/*
+ * User Peripheral physical base addresses.
+ */
+#define AT91SAM9N12_BASE_USART0 0xf801c000
+#define AT91SAM9N12_BASE_USART1 0xf8020000
+#define AT91SAM9N12_BASE_USART2 0xf8024000
+#define AT91SAM9N12_BASE_USART3 0xf8028000
+
+/*
+ * Internal Memory.
+ */
+#define AT91SAM9N12_SRAM_BASE 0x00300000 /* Internal SRAM base address */
+#define AT91SAM9N12_SRAM_SIZE SZ_32K /* Internal SRAM size (32Kb) */
+
+#define AT91SAM9N12_ROM_BASE 0x00100000 /* Internal ROM base address */
+#define AT91SAM9N12_ROM_SIZE SZ_128K /* Internal ROM size (128Kb) */
+
+#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h
new file mode 100644
index 000000000000..40060cd62fa9
--- /dev/null
+++ b/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h
@@ -0,0 +1,53 @@
+/*
+ * Matrix-centric header file for the AT91SAM9N12
+ *
+ * Copyright (C) 2012 Atmel Corporation.
+ *
+ * Only EBI related registers.
+ * Write Protect register definitions may be useful.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef _AT91SAM9N12_MATRIX_H_
+#define _AT91SAM9N12_MATRIX_H_
+
+#define AT91_MATRIX_EBICSA (AT91_MATRIX + 0x118) /* EBI Chip Select Assignment Register */
+#define AT91_MATRIX_EBI_CS1A (1 << 1) /* Chip Select 1 Assignment */
+#define AT91_MATRIX_EBI_CS1A_SMC (0 << 1)
+#define AT91_MATRIX_EBI_CS1A_SDRAMC (1 << 1)
+#define AT91_MATRIX_EBI_CS3A (1 << 3) /* Chip Select 3 Assignment */
+#define AT91_MATRIX_EBI_CS3A_SMC (0 << 3)
+#define AT91_MATRIX_EBI_CS3A_SMC_NANDFLASH (1 << 3)
+#define AT91_MATRIX_EBI_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */
+#define AT91_MATRIX_EBI_DBPU_ON (0 << 8)
+#define AT91_MATRIX_EBI_DBPU_OFF (1 << 8)
+#define AT91_MATRIX_EBI_VDDIOMSEL (1 << 16) /* Memory voltage selection */
+#define AT91_MATRIX_EBI_VDDIOMSEL_1_8V (0 << 16)
+#define AT91_MATRIX_EBI_VDDIOMSEL_3_3V (1 << 16)
+#define AT91_MATRIX_EBI_EBI_IOSR (1 << 17) /* EBI I/O slew rate selection */
+#define AT91_MATRIX_EBI_EBI_IOSR_REDUCED (0 << 17)
+#define AT91_MATRIX_EBI_EBI_IOSR_NORMAL (1 << 17)
+#define AT91_MATRIX_EBI_DDR_IOSR (1 << 18) /* DDR2 dedicated port I/O slew rate selection */
+#define AT91_MATRIX_EBI_DDR_IOSR_REDUCED (0 << 18)
+#define AT91_MATRIX_EBI_DDR_IOSR_NORMAL (1 << 18)
+#define AT91_MATRIX_NFD0_SELECT (1 << 24) /* NAND Flash Data Bus Selection */
+#define AT91_MATRIX_NFD0_ON_D0 (0 << 24)
+#define AT91_MATRIX_NFD0_ON_D16 (1 << 24)
+#define AT91_MATRIX_DDR_MP_EN (1 << 25) /* DDR Multi-port Enable */
+#define AT91_MATRIX_MP_OFF (0 << 25)
+#define AT91_MATRIX_MP_ON (1 << 25)
+
+#define AT91_MATRIX_WPMR (AT91_MATRIX + 0x1E4) /* Write Protect Mode Register */
+#define AT91_MATRIX_WPMR_WPEN (1 << 0) /* Write Protect ENable */
+#define AT91_MATRIX_WPMR_WP_WPDIS (0 << 0)
+#define AT91_MATRIX_WPMR_WP_WPEN (1 << 0)
+#define AT91_MATRIX_WPMR_WPKEY (0xFFFFFF << 8) /* Write Protect KEY */
+
+#define AT91_MATRIX_WPSR (AT91_MATRIX + 0x1E8) /* Write Protect Status Register */
+#define AT91_MATRIX_WPSR_WPVS (1 << 0) /* Write Protect Violation Status */
+#define AT91_MATRIX_WPSR_NO_WPV (0 << 0)
+#define AT91_MATRIX_WPSR_WPV (1 << 0)
+#define AT91_MATRIX_WPSR_WPVSRC (0xFFFF << 8) /* Write Protect Violation Source */
+
+#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9rl.h b/arch/arm/mach-at91/include/mach/at91sam9rl.h
index e0073eb10144..a15db56d33fa 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9rl.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9rl.h
@@ -89,11 +89,6 @@
#define AT91SAM9RL_BASE_GPBR 0xfffffd60
#define AT91SAM9RL_BASE_RTC 0xfffffe00
-#define AT91_USART0 AT91SAM9RL_BASE_US0
-#define AT91_USART1 AT91SAM9RL_BASE_US1
-#define AT91_USART2 AT91SAM9RL_BASE_US2
-#define AT91_USART3 AT91SAM9RL_BASE_US3
-
/*
* Internal Memory.
diff --git a/arch/arm/mach-at91/include/mach/at91sam9x5.h b/arch/arm/mach-at91/include/mach/at91sam9x5.h
index 88e43d534cdf..c75ee19b58d3 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9x5.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9x5.h
@@ -55,14 +55,6 @@
#define AT91SAM9X5_BASE_USART2 0xf8024000
/*
- * Base addresses for early serial code (uncompress.h)
- */
-#define AT91_DBGU AT91_BASE_DBGU0
-#define AT91_USART0 AT91SAM9X5_BASE_USART0
-#define AT91_USART1 AT91SAM9X5_BASE_USART1
-#define AT91_USART2 AT91SAM9X5_BASE_USART2
-
-/*
* Internal Memory.
*/
#define AT91SAM9X5_SRAM_BASE 0x00300000 /* Internal SRAM base address */
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index 49a821192c65..369afc2ffc5b 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -121,7 +121,6 @@ extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_de
#define ATMEL_UART_RI 0x20
extern void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins);
-extern void __init at91_set_serial_console(unsigned portnr);
extern struct platform_device *atmel_default_console_device;
diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h
index 0118c3338552..b6504c19d55c 100644
--- a/arch/arm/mach-at91/include/mach/cpu.h
+++ b/arch/arm/mach-at91/include/mach/cpu.h
@@ -25,6 +25,7 @@
#define ARCH_ID_AT91SAM9G45MRL 0x819b05a2 /* aka 9G45-ES2 & non ES lots */
#define ARCH_ID_AT91SAM9G45ES 0x819b05a1 /* 9G45-ES (Engineering Sample) */
#define ARCH_ID_AT91SAM9X5 0x819a05a0
+#define ARCH_ID_AT91SAM9N12 0x819a07a0
#define ARCH_ID_AT91SAM9XE128 0x329973a0
#define ARCH_ID_AT91SAM9XE256 0x329a93a0
@@ -54,6 +55,7 @@
#define ARCH_REVISON_9200_BGA (0 << 0)
#define ARCH_REVISON_9200_PQFP (1 << 0)
+#ifndef __ASSEMBLY__
enum at91_soc_type {
/* 920T */
AT91_SOC_RM9200,
@@ -70,6 +72,9 @@ enum at91_soc_type {
/* SAM9X5 */
AT91_SOC_SAM9X5,
+ /* SAM9N12 */
+ AT91_SOC_SAM9N12,
+
/* Unknown type */
AT91_SOC_NONE
};
@@ -106,7 +111,7 @@ static inline int at91_soc_is_detected(void)
return at91_soc_initdata.type != AT91_SOC_NONE;
}
-#ifdef CONFIG_ARCH_AT91RM9200
+#ifdef CONFIG_SOC_AT91RM9200
#define cpu_is_at91rm9200() (at91_soc_initdata.type == AT91_SOC_RM9200)
#define cpu_is_at91rm9200_bga() (at91_soc_initdata.subtype == AT91_SOC_RM9200_BGA)
#define cpu_is_at91rm9200_pqfp() (at91_soc_initdata.subtype == AT91_SOC_RM9200_PQFP)
@@ -116,45 +121,37 @@ static inline int at91_soc_is_detected(void)
#define cpu_is_at91rm9200_pqfp() (0)
#endif
-#ifdef CONFIG_ARCH_AT91SAM9260
+#ifdef CONFIG_SOC_AT91SAM9260
#define cpu_is_at91sam9xe() (at91_soc_initdata.subtype == AT91_SOC_SAM9XE)
#define cpu_is_at91sam9260() (at91_soc_initdata.type == AT91_SOC_SAM9260)
+#define cpu_is_at91sam9g20() (at91_soc_initdata.type == AT91_SOC_SAM9G20)
#else
#define cpu_is_at91sam9xe() (0)
#define cpu_is_at91sam9260() (0)
-#endif
-
-#ifdef CONFIG_ARCH_AT91SAM9G20
-#define cpu_is_at91sam9g20() (at91_soc_initdata.type == AT91_SOC_SAM9G20)
-#else
#define cpu_is_at91sam9g20() (0)
#endif
-#ifdef CONFIG_ARCH_AT91SAM9261
+#ifdef CONFIG_SOC_AT91SAM9261
#define cpu_is_at91sam9261() (at91_soc_initdata.type == AT91_SOC_SAM9261)
-#else
-#define cpu_is_at91sam9261() (0)
-#endif
-
-#ifdef CONFIG_ARCH_AT91SAM9G10
#define cpu_is_at91sam9g10() (at91_soc_initdata.type == AT91_SOC_SAM9G10)
#else
+#define cpu_is_at91sam9261() (0)
#define cpu_is_at91sam9g10() (0)
#endif
-#ifdef CONFIG_ARCH_AT91SAM9263
+#ifdef CONFIG_SOC_AT91SAM9263
#define cpu_is_at91sam9263() (at91_soc_initdata.type == AT91_SOC_SAM9263)
#else
#define cpu_is_at91sam9263() (0)
#endif
-#ifdef CONFIG_ARCH_AT91SAM9RL
+#ifdef CONFIG_SOC_AT91SAM9RL
#define cpu_is_at91sam9rl() (at91_soc_initdata.type == AT91_SOC_SAM9RL)
#else
#define cpu_is_at91sam9rl() (0)
#endif
-#ifdef CONFIG_ARCH_AT91SAM9G45
+#ifdef CONFIG_SOC_AT91SAM9G45
#define cpu_is_at91sam9g45() (at91_soc_initdata.type == AT91_SOC_SAM9G45)
#define cpu_is_at91sam9g45es() (at91_soc_initdata.subtype == AT91_SOC_SAM9G45ES)
#define cpu_is_at91sam9m10() (at91_soc_initdata.subtype == AT91_SOC_SAM9M10)
@@ -168,7 +165,7 @@ static inline int at91_soc_is_detected(void)
#define cpu_is_at91sam9m11() (0)
#endif
-#ifdef CONFIG_ARCH_AT91SAM9X5
+#ifdef CONFIG_SOC_AT91SAM9X5
#define cpu_is_at91sam9x5() (at91_soc_initdata.type == AT91_SOC_SAM9X5)
#define cpu_is_at91sam9g15() (at91_soc_initdata.subtype == AT91_SOC_SAM9G15)
#define cpu_is_at91sam9g35() (at91_soc_initdata.subtype == AT91_SOC_SAM9G35)
@@ -184,10 +181,17 @@ static inline int at91_soc_is_detected(void)
#define cpu_is_at91sam9x25() (0)
#endif
+#ifdef CONFIG_SOC_AT91SAM9N12
+#define cpu_is_at91sam9n12() (at91_soc_initdata.type == AT91_SOC_SAM9N12)
+#else
+#define cpu_is_at91sam9n12() (0)
+#endif
+
/*
* Since this is ARM, we will never run on any AVR32 CPU. But these
* definitions may reduce clutter in common drivers.
*/
#define cpu_is_at32ap7000() (0)
+#endif /* __ASSEMBLY__ */
#endif /* __MACH_CPU_H__ */
diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h
index 01db372be8e5..09242b67d277 100644
--- a/arch/arm/mach-at91/include/mach/hardware.h
+++ b/arch/arm/mach-at91/include/mach/hardware.h
@@ -22,27 +22,18 @@
/* 9263, 9g45 */
#define AT91_BASE_DBGU1 0xffffee00
-#if defined(CONFIG_ARCH_AT91RM9200)
+#if defined(CONFIG_ARCH_AT91X40)
+#include <mach/at91x40.h>
+#else
#include <mach/at91rm9200.h>
-#elif defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
#include <mach/at91sam9260.h>
-#elif defined(CONFIG_ARCH_AT91SAM9261) || defined(CONFIG_ARCH_AT91SAM9G10)
#include <mach/at91sam9261.h>
-#elif defined(CONFIG_ARCH_AT91SAM9263)
#include <mach/at91sam9263.h>
-#elif defined(CONFIG_ARCH_AT91SAM9RL)
#include <mach/at91sam9rl.h>
-#elif defined(CONFIG_ARCH_AT91SAM9G45)
#include <mach/at91sam9g45.h>
-#elif defined(CONFIG_ARCH_AT91SAM9X5)
#include <mach/at91sam9x5.h>
-#elif defined(CONFIG_ARCH_AT91X40)
-#include <mach/at91x40.h>
-#else
-#error "Unsupported AT91 processor"
-#endif
+#include <mach/at91sam9n12.h>
-#if !defined(CONFIG_ARCH_AT91X40)
/*
* On all at91 except rm9200 and x40 have the System Controller starts
* at address 0xffffc000 and has a size of 16KiB.
diff --git a/arch/arm/mach-at91/include/mach/uncompress.h b/arch/arm/mach-at91/include/mach/uncompress.h
index 4218647c1fcd..6f6118d1576a 100644
--- a/arch/arm/mach-at91/include/mach/uncompress.h
+++ b/arch/arm/mach-at91/include/mach/uncompress.h
@@ -1,7 +1,8 @@
/*
* arch/arm/mach-at91/include/mach/uncompress.h
*
- * Copyright (C) 2003 SAN People
+ * Copyright (C) 2003 SAN People
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,22 +26,147 @@
#include <linux/atmel_serial.h>
#include <mach/hardware.h>
-#if defined(CONFIG_AT91_EARLY_DBGU0)
-#define UART_OFFSET AT91_BASE_DBGU0
-#elif defined(CONFIG_AT91_EARLY_DBGU1)
-#define UART_OFFSET AT91_BASE_DBGU1
-#elif defined(CONFIG_AT91_EARLY_USART0)
-#define UART_OFFSET AT91_USART0
-#elif defined(CONFIG_AT91_EARLY_USART1)
-#define UART_OFFSET AT91_USART1
-#elif defined(CONFIG_AT91_EARLY_USART2)
-#define UART_OFFSET AT91_USART2
-#elif defined(CONFIG_AT91_EARLY_USART3)
-#define UART_OFFSET AT91_USART3
-#elif defined(CONFIG_AT91_EARLY_USART4)
-#define UART_OFFSET AT91_USART4
-#elif defined(CONFIG_AT91_EARLY_USART5)
-#define UART_OFFSET AT91_USART5
+#include <mach/at91_dbgu.h>
+#include <mach/cpu.h>
+
+void __iomem *at91_uart;
+
+#if !defined(CONFIG_ARCH_AT91X40)
+static const u32 uarts_rm9200[] = {
+ AT91_BASE_DBGU0,
+ AT91RM9200_BASE_US0,
+ AT91RM9200_BASE_US1,
+ AT91RM9200_BASE_US2,
+ AT91RM9200_BASE_US3,
+ 0,
+};
+
+static const u32 uarts_sam9260[] = {
+ AT91_BASE_DBGU0,
+ AT91SAM9260_BASE_US0,
+ AT91SAM9260_BASE_US1,
+ AT91SAM9260_BASE_US2,
+ AT91SAM9260_BASE_US3,
+ AT91SAM9260_BASE_US4,
+ AT91SAM9260_BASE_US5,
+ 0,
+};
+
+static const u32 uarts_sam9261[] = {
+ AT91_BASE_DBGU0,
+ AT91SAM9261_BASE_US0,
+ AT91SAM9261_BASE_US1,
+ AT91SAM9261_BASE_US2,
+ 0,
+};
+
+static const u32 uarts_sam9263[] = {
+ AT91_BASE_DBGU1,
+ AT91SAM9263_BASE_US0,
+ AT91SAM9263_BASE_US1,
+ AT91SAM9263_BASE_US2,
+ 0,
+};
+
+static const u32 uarts_sam9g45[] = {
+ AT91_BASE_DBGU1,
+ AT91SAM9G45_BASE_US0,
+ AT91SAM9G45_BASE_US1,
+ AT91SAM9G45_BASE_US2,
+ AT91SAM9G45_BASE_US3,
+ 0,
+};
+
+static const u32 uarts_sam9rl[] = {
+ AT91_BASE_DBGU0,
+ AT91SAM9RL_BASE_US0,
+ AT91SAM9RL_BASE_US1,
+ AT91SAM9RL_BASE_US2,
+ AT91SAM9RL_BASE_US3,
+ 0,
+};
+
+static const u32 uarts_sam9x5[] = {
+ AT91_BASE_DBGU0,
+ AT91SAM9X5_BASE_USART0,
+ AT91SAM9X5_BASE_USART1,
+ AT91SAM9X5_BASE_USART2,
+ 0,
+};
+
+static inline const u32* decomp_soc_detect(u32 dbgu_base)
+{
+ u32 cidr, socid;
+
+ cidr = __raw_readl(dbgu_base + AT91_DBGU_CIDR);
+ socid = cidr & ~AT91_CIDR_VERSION;
+
+ switch (socid) {
+ case ARCH_ID_AT91RM9200:
+ return uarts_rm9200;
+
+ case ARCH_ID_AT91SAM9G20:
+ case ARCH_ID_AT91SAM9260:
+ return uarts_sam9260;
+
+ case ARCH_ID_AT91SAM9261:
+ return uarts_sam9261;
+
+ case ARCH_ID_AT91SAM9263:
+ return uarts_sam9263;
+
+ case ARCH_ID_AT91SAM9G45:
+ return uarts_sam9g45;
+
+ case ARCH_ID_AT91SAM9RL64:
+ return uarts_sam9rl;
+
+ case ARCH_ID_AT91SAM9X5:
+ return uarts_sam9x5;
+ }
+
+ /* at91sam9g10 */
+ if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
+ return uarts_sam9261;
+ }
+ /* at91sam9xe */
+ else if ((cidr & AT91_CIDR_ARCH) == ARCH_FAMILY_AT91SAM9XE) {
+ return uarts_sam9260;
+ }
+
+ return NULL;
+}
+
+static inline void arch_decomp_setup(void)
+{
+ int i = 0;
+ const u32* usarts;
+
+ usarts = decomp_soc_detect(AT91_BASE_DBGU0);
+
+ if (!usarts)
+ usarts = decomp_soc_detect(AT91_BASE_DBGU1);
+ if (!usarts) {
+ at91_uart = NULL;
+ return;
+ }
+
+ do {
+ /* physical address */
+ at91_uart = (void __iomem *)usarts[i];
+
+ if (__raw_readl(at91_uart + ATMEL_US_BRGR))
+ return;
+ i++;
+ } while (usarts[i]);
+
+ at91_uart = NULL;
+}
+#else
+static inline void arch_decomp_setup(void)
+{
+ at91_uart = NULL;
+}
#endif
/*
@@ -52,28 +178,24 @@
*/
static void putc(int c)
{
-#ifdef UART_OFFSET
- void __iomem *sys = (void __iomem *) UART_OFFSET; /* physical address */
+ if (!at91_uart)
+ return;
- while (!(__raw_readl(sys + ATMEL_US_CSR) & ATMEL_US_TXRDY))
+ while (!(__raw_readl(at91_uart + ATMEL_US_CSR) & ATMEL_US_TXRDY))
barrier();
- __raw_writel(c, sys + ATMEL_US_THR);
-#endif
+ __raw_writel(c, at91_uart + ATMEL_US_THR);
}
static inline void flush(void)
{
-#ifdef UART_OFFSET
- void __iomem *sys = (void __iomem *) UART_OFFSET; /* physical address */
+ if (!at91_uart)
+ return;
/* wait for transmission to complete */
- while (!(__raw_readl(sys + ATMEL_US_CSR) & ATMEL_US_TXEMPTY))
+ while (!(__raw_readl(at91_uart + ATMEL_US_CSR) & ATMEL_US_TXEMPTY))
barrier();
-#endif
}
-#define arch_decomp_setup()
-
#define arch_decomp_wdog()
#endif
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index f630250c6b87..1bfaad628731 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -261,7 +261,12 @@ static int at91_pm_enter(suspend_state_t state)
* For ARM 926 based chips, this requirement is weaker
* as at91sam9 can access a RAM in self-refresh mode.
*/
- at91_standby();
+ if (cpu_is_at91rm9200())
+ at91rm9200_standby();
+ else if (cpu_is_at91sam9g45())
+ at91sam9g45_standby();
+ else
+ at91sam9_standby();
break;
case PM_SUSPEND_ON:
@@ -307,10 +312,9 @@ static int __init at91_pm_init(void)
pr_info("AT91: Power Management%s\n", (slow_clock ? " (with slow clock mode)" : ""));
-#ifdef CONFIG_ARCH_AT91RM9200
/* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. */
- at91_ramc_write(0, AT91RM9200_SDRAMC_LPR, 0);
-#endif
+ if (cpu_is_at91rm9200())
+ at91_ramc_write(0, AT91RM9200_SDRAMC_LPR, 0);
suspend_set_ops(&at91_pm_ops);
diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index 89f56f3a802e..38f467c6b710 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -12,7 +12,6 @@
#define __ARCH_ARM_MACH_AT91_PM
#include <mach/at91_ramc.h>
-#ifdef CONFIG_ARCH_AT91RM9200
#include <mach/at91rm9200_sdramc.h>
/*
@@ -43,10 +42,6 @@ static inline void at91rm9200_standby(void)
"r" (lpr));
}
-#define at91_standby at91rm9200_standby
-
-#elif defined(CONFIG_ARCH_AT91SAM9G45)
-
/* We manage both DDRAM/SDRAM controllers, we need more than one value to
* remember.
*/
@@ -75,11 +70,7 @@ static inline void at91sam9g45_standby(void)
at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
}
-#define at91_standby at91sam9g45_standby
-
-#else
-
-#ifdef CONFIG_ARCH_AT91SAM9263
+#ifdef CONFIG_SOC_AT91SAM9263
/*
* FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
* handle those cases both here and in the Suspend-To-RAM support.
@@ -102,8 +93,4 @@ static inline void at91sam9_standby(void)
at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr);
}
-#define at91_standby at91sam9_standby
-
-#endif
-
#endif
diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S
index db5452123f17..098c28ddf025 100644
--- a/arch/arm/mach-at91/pm_slowclock.S
+++ b/arch/arm/mach-at91/pm_slowclock.S
@@ -18,7 +18,7 @@
#include <mach/at91_ramc.h>
-#ifdef CONFIG_ARCH_AT91SAM9263
+#ifdef CONFIG_SOC_AT91SAM9263
/*
* FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
* handle those cases both here and in the Suspend-To-RAM support.
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index f44a2e7272e3..944bffb08991 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -143,6 +143,11 @@ static void __init soc_detect(u32 dbgu_base)
at91_soc_initdata.type = AT91_SOC_SAM9X5;
at91_boot_soc = at91sam9x5_soc;
break;
+
+ case ARCH_ID_AT91SAM9N12:
+ at91_soc_initdata.type = AT91_SOC_SAM9N12;
+ at91_boot_soc = at91sam9n12_soc;
+ break;
}
/* at91sam9g10 */
@@ -210,6 +215,7 @@ static const char *soc_name[] = {
[AT91_SOC_SAM9G45] = "at91sam9g45",
[AT91_SOC_SAM9RL] = "at91sam9rl",
[AT91_SOC_SAM9X5] = "at91sam9x5",
+ [AT91_SOC_SAM9N12] = "at91sam9n12",
[AT91_SOC_NONE] = "Unknown"
};
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
index 5db4aa45404a..a9cfeb153719 100644
--- a/arch/arm/mach-at91/soc.h
+++ b/arch/arm/mach-at91/soc.h
@@ -20,36 +20,41 @@ extern struct at91_init_soc at91sam9263_soc;
extern struct at91_init_soc at91sam9g45_soc;
extern struct at91_init_soc at91sam9rl_soc;
extern struct at91_init_soc at91sam9x5_soc;
+extern struct at91_init_soc at91sam9n12_soc;
static inline int at91_soc_is_enabled(void)
{
return at91_boot_soc.init != NULL;
}
-#if !defined(CONFIG_ARCH_AT91RM9200)
+#if !defined(CONFIG_SOC_AT91RM9200)
#define at91rm9200_soc at91_boot_soc
#endif
-#if !(defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20))
+#if !defined(CONFIG_SOC_AT91SAM9260)
#define at91sam9260_soc at91_boot_soc
#endif
-#if !(defined(CONFIG_ARCH_AT91SAM9261) || defined(CONFIG_ARCH_AT91SAM9G10))
+#if !defined(CONFIG_SOC_AT91SAM9261)
#define at91sam9261_soc at91_boot_soc
#endif
-#if !defined(CONFIG_ARCH_AT91SAM9263)
+#if !defined(CONFIG_SOC_AT91SAM9263)
#define at91sam9263_soc at91_boot_soc
#endif
-#if !defined(CONFIG_ARCH_AT91SAM9G45)
+#if !defined(CONFIG_SOC_AT91SAM9G45)
#define at91sam9g45_soc at91_boot_soc
#endif
-#if !defined(CONFIG_ARCH_AT91SAM9RL)
+#if !defined(CONFIG_SOC_AT91SAM9RL)
#define at91sam9rl_soc at91_boot_soc
#endif
-#if !defined(CONFIG_ARCH_AT91SAM9X5)
+#if !defined(CONFIG_SOC_AT91SAM9X5)
#define at91sam9x5_soc at91_boot_soc
#endif
+
+#if !defined(CONFIG_SOC_AT91SAM9N12)
+#define at91sam9n12_soc at91_boot_soc
+#endif
diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig
index eb34bd1251d4..ea036d621581 100644
--- a/arch/arm/mach-clps711x/Kconfig
+++ b/arch/arm/mach-clps711x/Kconfig
@@ -1,6 +1,6 @@
if ARCH_CLPS711X
-menu "CLPS711X/EP721X Implementations"
+menu "CLPS711X/EP721X/EP731X Implementations"
config ARCH_AUTCPU12
bool "AUTCPU12"
@@ -45,26 +45,13 @@ config ARCH_P720T
config ARCH_FORTUNET
bool "FORTUNET"
-# XXX Maybe these should indicate register compatibility
-# instead of being mutually exclusive.
-config ARCH_EP7211
- bool
- depends on ARCH_EDB7211
- default y
-
-config ARCH_EP7212
- bool
- depends on ARCH_P720T || ARCH_CEIVA
- default y
-
config EP72XX_ROM_BOOT
- bool "EP72xx ROM boot"
- depends on ARCH_EP7211 || ARCH_EP7212
- ---help---
+ bool "EP721x/EP731x ROM boot"
+ help
If you say Y here, your CLPS711x-based kernel will use the bootstrap
mode memory map instead of the normal memory map.
- Processors derived from the Cirrus CLPS-711X core support two boot
+ Processors derived from the Cirrus CLPS711X core support two boot
modes. Normal mode boots from the external memory device at CS0.
Bootstrap mode rearranges parts of the memory map, placing an
internal 128 byte bootstrap ROM at CS0. This option performs the
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c
index 3c5b5bbf24e5..c965fd8eb31a 100644
--- a/arch/arm/mach-clps711x/common.c
+++ b/arch/arm/mach-clps711x/common.c
@@ -36,7 +36,6 @@
#include <asm/page.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
-#include <asm/hardware/clps7111.h>
#include <asm/system_misc.h>
/*
@@ -44,8 +43,8 @@
*/
static struct map_desc clps711x_io_desc[] __initdata = {
{
- .virtual = CLPS7111_VIRT_BASE,
- .pfn = __phys_to_pfn(CLPS7111_PHYS_BASE),
+ .virtual = (unsigned long)CLPS711X_VIRT_BASE,
+ .pfn = __phys_to_pfn(CLPS711X_PHYS_BASE),
.length = SZ_1M,
.type = MT_DEVICE
}
@@ -67,12 +66,6 @@ static void int1_mask(struct irq_data *d)
static void int1_ack(struct irq_data *d)
{
- u32 intmr1;
-
- intmr1 = clps_readl(INTMR1);
- intmr1 &= ~(1 << d->irq);
- clps_writel(intmr1, INTMR1);
-
switch (d->irq) {
case IRQ_CSINT: clps_writel(0, COEOI); break;
case IRQ_TC1OI: clps_writel(0, TC1EOI); break;
@@ -109,12 +102,6 @@ static void int2_mask(struct irq_data *d)
static void int2_ack(struct irq_data *d)
{
- u32 intmr2;
-
- intmr2 = clps_readl(INTMR2);
- intmr2 &= ~(1 << (d->irq - 16));
- clps_writel(intmr2, INTMR2);
-
switch (d->irq) {
case IRQ_KBDINT: clps_writel(0, KBDEOI); break;
}
diff --git a/arch/arm/include/asm/hardware/clps7111.h b/arch/arm/mach-clps711x/include/mach/clps711x.h
index 44477225aed6..1dd806f2847e 100644
--- a/arch/arm/include/asm/hardware/clps7111.h
+++ b/arch/arm/mach-clps711x/include/mach/clps711x.h
@@ -1,8 +1,6 @@
/*
- * arch/arm/include/asm/hardware/clps7111.h
- *
- * This file contains the hardware definitions of the CLPS7111 internal
- * registers.
+ * This file contains the hardware definitions of the Cirrus Logic
+ * ARM7 CLPS711X internal registers.
*
* Copyright (C) 2000 Deep Blue Solutions Ltd.
*
@@ -20,25 +18,18 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __ASM_HARDWARE_CLPS7111_H
-#define __ASM_HARDWARE_CLPS7111_H
-
-#define CLPS7111_PHYS_BASE (0x80000000)
+#ifndef __MACH_CLPS711X_H
+#define __MACH_CLPS711X_H
-#ifndef __ASSEMBLY__
-#define clps_readb(off) __raw_readb(CLPS7111_BASE + (off))
-#define clps_readw(off) __raw_readw(CLPS7111_BASE + (off))
-#define clps_readl(off) __raw_readl(CLPS7111_BASE + (off))
-#define clps_writeb(val,off) __raw_writeb(val, CLPS7111_BASE + (off))
-#define clps_writew(val,off) __raw_writew(val, CLPS7111_BASE + (off))
-#define clps_writel(val,off) __raw_writel(val, CLPS7111_BASE + (off))
-#endif
+#define CLPS711X_PHYS_BASE (0x80000000)
#define PADR (0x0000)
#define PBDR (0x0001)
+#define PCDR (0x0002)
#define PDDR (0x0003)
#define PADDR (0x0040)
#define PBDDR (0x0041)
+#define PCDDR (0x0042)
#define PDDDR (0x0043)
#define PEDR (0x0080)
#define PEDDR (0x00c0)
@@ -50,7 +41,7 @@
#define INTSR1 (0x0240)
#define INTMR1 (0x0280)
#define LCDCON (0x02c0)
-#define TC1D (0x0300)
+#define TC1D (0x0300)
#define TC2D (0x0340)
#define RTCDR (0x0380)
#define RTCMR (0x03c0)
@@ -85,6 +76,26 @@
#define SS2POP (0x16c0)
#define KBDEOI (0x1700)
+#define DAIR (0x2000)
+#define DAIR0 (0x2040)
+#define DAIDR1 (0x2080)
+#define DAIDR2 (0x20c0)
+#define DAISR (0x2100)
+#define SYSCON3 (0x2200)
+#define INTSR3 (0x2240)
+#define INTMR3 (0x2280)
+#define LEDFLSH (0x22c0)
+#define SDCONF (0x2300)
+#define SDRFPR (0x2340)
+#define UNIQID (0x2440)
+#define DAI64FS (0x2600)
+#define PLLW (0x2610)
+#define PLLR (0xa5a8)
+#define RANDID0 (0x2700)
+#define RANDID1 (0x2704)
+#define RANDID2 (0x2708)
+#define RANDID3 (0x270c)
+
/* common bits: SYSCON1 / SYSCON2 */
#define SYSCON_UARTEN (1 << 8)
@@ -131,6 +142,8 @@
#define SYSFLG1_CTXFF (1 << 25)
#define SYSFLG1_SSIBUSY (1 << 26)
#define SYSFLG1_ID (1 << 29)
+#define SYSFLG1_VERID(x) (((x) >> 30) & 3)
+#define SYSFLG1_VERID_MASK (3 << 30)
#define SYSFLG2_SSRXOF (1 << 0)
#define SYSFLG2_RESVAL (1 << 1)
@@ -178,7 +191,88 @@
#define UBRLCR_WRDLEN8 (3 << 17)
#define UBRLCR_WRDLEN_MASK (3 << 17)
+#define SYNCIO_FRMLEN(x) (((x) & 0x3f) << 7)
+#define SYNCIO_CFGLEN(x) ((x) & 0x7f)
#define SYNCIO_SMCKEN (1 << 13)
#define SYNCIO_TXFRMEN (1 << 14)
-#endif /* __ASM_HARDWARE_CLPS7111_H */
+#define DAIR_RESERVED (0x0404)
+#define DAIR_DAIEN (1 << 16)
+#define DAIR_ECS (1 << 17)
+#define DAIR_LCTM (1 << 19)
+#define DAIR_LCRM (1 << 20)
+#define DAIR_RCTM (1 << 21)
+#define DAIR_RCRM (1 << 22)
+#define DAIR_LBM (1 << 23)
+
+#define DAIDR2_FIFOEN (1 << 15)
+#define DAIDR2_FIFOLEFT (0x0d << 16)
+#define DAIDR2_FIFORIGHT (0x11 << 16)
+
+#define DAISR_RCTS (1 << 0)
+#define DAISR_RCRS (1 << 1)
+#define DAISR_LCTS (1 << 2)
+#define DAISR_LCRS (1 << 3)
+#define DAISR_RCTU (1 << 4)
+#define DAISR_RCRO (1 << 5)
+#define DAISR_LCTU (1 << 6)
+#define DAISR_LCRO (1 << 7)
+#define DAISR_RCNF (1 << 8)
+#define DAISR_RCNE (1 << 9)
+#define DAISR_LCNF (1 << 10)
+#define DAISR_LCNE (1 << 11)
+#define DAISR_FIFO (1 << 12)
+
+#define DAI64FS_I2SF64 (1 << 0)
+#define DAI64FS_AUDIOCLKEN (1 << 1)
+#define DAI64FS_AUDIOCLKSRC (1 << 2)
+#define DAI64FS_MCLK256EN (1 << 3)
+#define DAI64FS_LOOPBACK (1 << 5)
+
+#define SYSCON3_ADCCON (1 << 0)
+#define SYSCON3_CLKCTL0 (1 << 1)
+#define SYSCON3_CLKCTL1 (1 << 2)
+#define SYSCON3_DAISEL (1 << 3)
+#define SYSCON3_ADCCKNSEN (1 << 4)
+#define SYSCON3_VERSN(x) (((x) >> 5) & 7)
+#define SYSCON3_VERSN_MASK (7 << 5)
+#define SYSCON3_FASTWAKE (1 << 8)
+#define SYSCON3_DAIEN (1 << 9)
+#define SYSCON3_128FS SYSCON3_DAIEN
+#define SYSCON3_ENPD67 (1 << 10)
+
+#define SDCONF_ACTIVE (1 << 10)
+#define SDCONF_CLKCTL (1 << 9)
+#define SDCONF_WIDTH_4 (0 << 7)
+#define SDCONF_WIDTH_8 (1 << 7)
+#define SDCONF_WIDTH_16 (2 << 7)
+#define SDCONF_WIDTH_32 (3 << 7)
+#define SDCONF_SIZE_16 (0 << 5)
+#define SDCONF_SIZE_64 (1 << 5)
+#define SDCONF_SIZE_128 (2 << 5)
+#define SDCONF_SIZE_256 (3 << 5)
+#define SDCONF_CASLAT_2 (2)
+#define SDCONF_CASLAT_3 (3)
+
+#define MEMCFG_BUS_WIDTH_32 (1)
+#define MEMCFG_BUS_WIDTH_16 (0)
+#define MEMCFG_BUS_WIDTH_8 (3)
+
+#define MEMCFG_WAITSTATE_8_3 (0 << 2)
+#define MEMCFG_WAITSTATE_7_3 (1 << 2)
+#define MEMCFG_WAITSTATE_6_3 (2 << 2)
+#define MEMCFG_WAITSTATE_5_3 (3 << 2)
+#define MEMCFG_WAITSTATE_4_2 (4 << 2)
+#define MEMCFG_WAITSTATE_3_2 (5 << 2)
+#define MEMCFG_WAITSTATE_2_2 (6 << 2)
+#define MEMCFG_WAITSTATE_1_2 (7 << 2)
+#define MEMCFG_WAITSTATE_8_1 (8 << 2)
+#define MEMCFG_WAITSTATE_7_1 (9 << 2)
+#define MEMCFG_WAITSTATE_6_1 (10 << 2)
+#define MEMCFG_WAITSTATE_5_1 (11 << 2)
+#define MEMCFG_WAITSTATE_4_0 (12 << 2)
+#define MEMCFG_WAITSTATE_3_0 (13 << 2)
+#define MEMCFG_WAITSTATE_2_0 (14 << 2)
+#define MEMCFG_WAITSTATE_1_0 (15 << 2)
+
+#endif /* __MACH_CLPS711X_H */
diff --git a/arch/arm/mach-clps711x/include/mach/debug-macro.S b/arch/arm/mach-clps711x/include/mach/debug-macro.S
index b802e8a51831..118b3d930573 100644
--- a/arch/arm/mach-clps711x/include/mach/debug-macro.S
+++ b/arch/arm/mach-clps711x/include/mach/debug-macro.S
@@ -12,7 +12,6 @@
*/
#include <mach/hardware.h>
-#include <asm/hardware/clps7111.h>
.macro addruart, rp, rv, tmp
#ifndef CONFIG_DEBUG_CLPS711X_UART2
@@ -20,8 +19,8 @@
#else
mov \rp, #0x1000 @ UART2
#endif
- orr \rv, \rp, #CLPS7111_VIRT_BASE
- orr \rp, \rp, #CLPS7111_PHYS_BASE
+ orr \rv, \rp, #CLPS711X_VIRT_BASE
+ orr \rp, \rp, #CLPS711X_PHYS_BASE
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/mach-clps711x/include/mach/entry-macro.S b/arch/arm/mach-clps711x/include/mach/entry-macro.S
index 125af59d7a29..56e5c2c23504 100644
--- a/arch/arm/mach-clps711x/include/mach/entry-macro.S
+++ b/arch/arm/mach-clps711x/include/mach/entry-macro.S
@@ -8,7 +8,6 @@
* warranty of any kind, whether express or implied.
*/
#include <mach/hardware.h>
-#include <asm/hardware/clps7111.h>
.macro get_irqnr_preamble, base, tmp
.endm
@@ -18,7 +17,7 @@
#endif
.macro get_irqnr_and_base, irqnr, stat, base, mask
- mov \base, #CLPS7111_BASE
+ mov \base, #CLPS711X_VIRT_BASE
ldr \stat, [\base, #INTSR1]
ldr \mask, [\base, #INTMR1]
mov \irqnr, #4
diff --git a/arch/arm/mach-clps711x/include/mach/hardware.h b/arch/arm/mach-clps711x/include/mach/hardware.h
index d0b7d870be9c..13a64fcd7dd1 100644
--- a/arch/arm/mach-clps711x/include/mach/hardware.h
+++ b/arch/arm/mach-clps711x/include/mach/hardware.h
@@ -19,12 +19,21 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
+#ifndef __MACH_HARDWARE_H
+#define __MACH_HARDWARE_H
+#include <mach/clps711x.h>
-#define CLPS7111_VIRT_BASE 0xff000000
-#define CLPS7111_BASE CLPS7111_VIRT_BASE
+#define CLPS711X_VIRT_BASE IOMEM(0xff000000)
+
+#ifndef __ASSEMBLY__
+#define clps_readb(off) readb(CLPS711X_VIRT_BASE + (off))
+#define clps_readw(off) readw(CLPS711X_VIRT_BASE + (off))
+#define clps_readl(off) readl(CLPS711X_VIRT_BASE + (off))
+#define clps_writeb(val,off) writeb(val, CLPS711X_VIRT_BASE + (off))
+#define clps_writew(val,off) writew(val, CLPS711X_VIRT_BASE + (off))
+#define clps_writel(val,off) writel(val, CLPS711X_VIRT_BASE + (off))
+#endif
/*
* The physical addresses that the external chip select signals map to is
@@ -52,46 +61,11 @@
#define CS7_PHYS_BASE (0x00000000)
#endif
-#if defined (CONFIG_ARCH_EP7211)
-
-#define EP7211_VIRT_BASE CLPS7111_VIRT_BASE
-#define EP7211_BASE CLPS7111_VIRT_BASE
-#include <asm/hardware/ep7211.h>
-
-#elif defined (CONFIG_ARCH_EP7212)
-
-#define EP7212_VIRT_BASE CLPS7111_VIRT_BASE
-#define EP7212_BASE CLPS7111_VIRT_BASE
-#include <asm/hardware/ep7212.h>
-
-#endif
-
#define SYSPLD_VIRT_BASE 0xfe000000
#define SYSPLD_BASE SYSPLD_VIRT_BASE
-#if defined (CONFIG_ARCH_AUTCPU12)
-
-#define CS89712_VIRT_BASE CLPS7111_VIRT_BASE
-#define CS89712_BASE CLPS7111_VIRT_BASE
-
-#include <asm/hardware/clps7111.h>
-#include <asm/hardware/ep7212.h>
-#include <asm/hardware/cs89712.h>
-
-#endif
-
-
#if defined (CONFIG_ARCH_CDB89712)
-#include <asm/hardware/clps7111.h>
-#include <asm/hardware/ep7212.h>
-#include <asm/hardware/cs89712.h>
-
-/* static cdb89712_map_io() areas */
-#define REGISTER_START 0x80000000
-#define REGISTER_SIZE 0x4000
-#define REGISTER_BASE 0xff000000
-
#define ETHER_START 0x20000000
#define ETHER_SIZE 0x1000
#define ETHER_BASE 0xfe000000
@@ -154,13 +128,6 @@
#if defined (CONFIG_ARCH_CEIVA)
-#define CEIVA_VIRT_BASE CLPS7111_VIRT_BASE
-#define CEIVA_BASE CLPS7111_VIRT_BASE
-
-#include <asm/hardware/clps7111.h>
-#include <asm/hardware/ep7212.h>
-
-
/*
* The two flash banks are wired to chip selects 0 and 1. This is the mapping
* for them.
diff --git a/arch/arm/mach-clps711x/include/mach/irqs.h b/arch/arm/mach-clps711x/include/mach/irqs.h
index 30b7e97285a4..14d215f8ca81 100644
--- a/arch/arm/mach-clps711x/include/mach/irqs.h
+++ b/arch/arm/mach-clps711x/include/mach/irqs.h
@@ -35,7 +35,6 @@
#define IRQ_SSEOTI 15
#define INT1_IRQS (0x0000fff0)
-#define INT1_ACK_IRQS (0x00004f10)
/*
* Interrupts from INTSR2
@@ -47,7 +46,5 @@
#define IRQ_URXINT2 (16+13) /* bit 13 */
#define INT2_IRQS (0x30070000)
-#define INT2_ACK_IRQS (0x00010000)
-
-#define NR_IRQS 30
+#define NR_IRQS 30
diff --git a/arch/arm/mach-clps711x/include/mach/time.h b/arch/arm/mach-clps711x/include/mach/time.h
deleted file mode 100644
index 61fef9129c6a..000000000000
--- a/arch/arm/mach-clps711x/include/mach/time.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * arch/arm/mach-clps711x/include/mach/time.h
- *
- * Copyright (C) 2000 Deep Blue Solutions Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <asm/leds.h>
-#include <asm/hardware/clps7111.h>
-
-extern void clps711x_setup_timer(void);
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t
-p720t_timer_interrupt(int irq, void *dev_id)
-{
- struct pt_regs *regs = get_irq_regs();
- do_leds();
- xtime_update(1);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(regs));
-#endif
- do_profile(regs);
- return IRQ_HANDLED;
-}
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- */
-void __init time_init(void)
-{
- clps711x_setup_timer();
- timer_irq.handler = p720t_timer_interrupt;
- setup_irq(IRQ_TC2OI, &timer_irq);
-}
diff --git a/arch/arm/mach-clps711x/include/mach/uncompress.h b/arch/arm/mach-clps711x/include/mach/uncompress.h
index 35ed731b9f16..7b28d6a47690 100644
--- a/arch/arm/mach-clps711x/include/mach/uncompress.h
+++ b/arch/arm/mach-clps711x/include/mach/uncompress.h
@@ -17,14 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <mach/hardware.h>
-#include <asm/hardware/clps7111.h>
-
-#undef CLPS7111_BASE
-#define CLPS7111_BASE CLPS7111_PHYS_BASE
-
-#define __raw_readl(p) (*(unsigned long *)(p))
-#define __raw_writel(v,p) (*(unsigned long *)(p) = (v))
+#include <mach/clps711x.h>
#ifdef CONFIG_DEBUG_CLPS711X_UART2
#define SYSFLGx SYSFLG2
@@ -34,19 +27,25 @@
#define UARTDRx UARTDR1
#endif
+#define phys_reg(x) (*(volatile u32 *)(CLPS711X_PHYS_BASE + (x)))
+
/*
+ * The following code assumes the serial port has already been
+ * initialized by the bootloader. If you didn't setup a port in
+ * your bootloader then nothing will appear (which might be desired).
+ *
* This does not append a newline
*/
static inline void putc(int c)
{
- while (clps_readl(SYSFLGx) & SYSFLG_UTXFF)
+ while (phys_reg(SYSFLGx) & SYSFLG_UTXFF)
barrier();
- clps_writel(c, UARTDRx);
+ phys_reg(UARTDRx) = c;
}
static inline void flush(void)
{
- while (clps_readl(SYSFLGx) & SYSFLG_UBUSY)
+ while (phys_reg(SYSFLGx) & SYSFLG_UBUSY)
barrier();
}
diff --git a/arch/arm/mach-clps711x/p720t-leds.c b/arch/arm/mach-clps711x/p720t-leds.c
index dd9a6cdbeb02..bbc449fbe14a 100644
--- a/arch/arm/mach-clps711x/p720t-leds.c
+++ b/arch/arm/mach-clps711x/p720t-leds.c
@@ -27,9 +27,6 @@
#include <asm/leds.h>
#include <asm/mach-types.h>
-#include <asm/hardware/clps7111.h>
-#include <asm/hardware/ep7212.h>
-
static void p720t_leds_event(led_event_t ledevt)
{
unsigned long flags;
diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
index 79d001f831e0..311328314163 100644
--- a/arch/arm/mach-cns3xxx/pcie.c
+++ b/arch/arm/mach-cns3xxx/pcie.c
@@ -166,12 +166,6 @@ static struct pci_ops cns3xxx_pcie_ops = {
.write = cns3xxx_pci_write_config,
};
-static struct pci_bus *cns3xxx_pci_scan_bus(int nr, struct pci_sys_data *sys)
-{
- return pci_scan_root_bus(NULL, sys->busnr, &cns3xxx_pcie_ops, sys,
- &sys->resources);
-}
-
static int cns3xxx_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct cns3xxx_pcie *cnspci = pdev_to_cnspci(dev);
@@ -221,10 +215,9 @@ static struct cns3xxx_pcie cns3xxx_pcie[] = {
.irqs = { IRQ_CNS3XXX_PCIE0_RC, IRQ_CNS3XXX_PCIE0_DEVICE, },
.hw_pci = {
.domain = 0,
- .swizzle = pci_std_swizzle,
.nr_controllers = 1,
+ .ops = &cns3xxx_pcie_ops,
.setup = cns3xxx_pci_setup,
- .scan = cns3xxx_pci_scan_bus,
.map_irq = cns3xxx_pcie_map_irq,
},
},
@@ -264,10 +257,9 @@ static struct cns3xxx_pcie cns3xxx_pcie[] = {
.irqs = { IRQ_CNS3XXX_PCIE1_RC, IRQ_CNS3XXX_PCIE1_DEVICE, },
.hw_pci = {
.domain = 1,
- .swizzle = pci_std_swizzle,
.nr_controllers = 1,
+ .ops = &cns3xxx_pcie_ops,
.setup = cns3xxx_pci_setup,
- .scan = cns3xxx_pci_scan_bus,
.map_irq = cns3xxx_pcie_map_irq,
},
},
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index a70de24d1cbc..09f61073c8d9 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -284,7 +284,7 @@ static struct platform_device da850_evm_nandflash_device = {
.resource = da850_evm_nandflash_resource,
};
-static struct platform_device *da850_evm_devices[] __initdata = {
+static struct platform_device *da850_evm_devices[] = {
&da850_evm_nandflash_device,
&da850_evm_norflash_device,
};
diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h
index 3e519dad5bb9..8db0fc6809dd 100644
--- a/arch/arm/mach-davinci/davinci.h
+++ b/arch/arm/mach-davinci/davinci.h
@@ -72,7 +72,7 @@ void davinci_map_sysmod(void);
/* DM355 function declarations */
void __init dm355_init(void);
void dm355_init_spi0(unsigned chipselect_mask,
- struct spi_board_info *info, unsigned len);
+ const struct spi_board_info *info, unsigned len);
void __init dm355_init_asp1(u32 evt_enable, struct snd_platform_data *pdata);
void dm355_set_vpfe_config(struct vpfe_config *cfg);
@@ -83,7 +83,7 @@ void __init dm365_init_vc(struct snd_platform_data *pdata);
void __init dm365_init_ks(struct davinci_ks_platform_data *pdata);
void __init dm365_init_rtc(void);
void dm365_init_spi0(unsigned chipselect_mask,
- struct spi_board_info *info, unsigned len);
+ const struct spi_board_info *info, unsigned len);
void dm365_set_vpfe_config(struct vpfe_config *cfg);
/* DM644x function declarations */
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 42dbf3dc11ab..d1624a315c9a 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -831,7 +831,7 @@ static struct platform_device da8xx_spi_device[] = {
},
};
-int __init da8xx_register_spi(int instance, struct spi_board_info *info,
+int __init da8xx_register_spi(int instance, const struct spi_board_info *info,
unsigned len)
{
int ret;
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index fd3d09aa6cde..678cd99b7336 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -424,7 +424,7 @@ static struct platform_device dm355_spi0_device = {
};
void __init dm355_init_spi0(unsigned chipselect_mask,
- struct spi_board_info *info, unsigned len)
+ const struct spi_board_info *info, unsigned len)
{
/* for now, assume we need MISO */
davinci_cfg_reg(DM355_SPI0_SDI);
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 1a2e953082b3..a50d49de1883 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -676,7 +676,7 @@ static struct platform_device dm365_spi0_device = {
};
void __init dm365_init_spi0(unsigned chipselect_mask,
- struct spi_board_info *info, unsigned len)
+ const struct spi_board_info *info, unsigned len)
{
davinci_cfg_reg(DM365_SPI0_SCLK);
davinci_cfg_reg(DM365_SPI0_SDI);
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index fd33919c95d4..95ce019c9b98 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -557,9 +557,9 @@ static int reserve_contiguous_slots(int ctlr, unsigned int id,
if (i == edma_cc[ctlr]->num_slots)
stop_slot = i;
- for (j = start_slot; j < stop_slot; j++)
- if (test_bit(j, tmp_inuse))
- clear_bit(j, edma_cc[ctlr]->edma_inuse);
+ j = start_slot;
+ for_each_set_bit_from(j, tmp_inuse, stop_slot)
+ clear_bit(j, edma_cc[ctlr]->edma_inuse);
if (count)
return -EBUSY;
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index ee3461d7ec1b..a2f1f274f189 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -76,7 +76,8 @@ void __init da850_init(void);
int da830_register_edma(struct edma_rsv_info *rsv);
int da850_register_edma(struct edma_rsv_info *rsv[2]);
int da8xx_register_i2c(int instance, struct davinci_i2c_platform_data *pdata);
-int da8xx_register_spi(int instance, struct spi_board_info *info, unsigned len);
+int da8xx_register_spi(int instance,
+ const struct spi_board_info *info, unsigned len);
int da8xx_register_watchdog(void);
int da8xx_register_usb20(unsigned mA, unsigned potpgt);
int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h
index 8bc3fc256171..405318e35bf6 100644
--- a/arch/arm/mach-davinci/include/mach/psc.h
+++ b/arch/arm/mach-davinci/include/mach/psc.h
@@ -246,7 +246,7 @@
#define MDSTAT_STATE_MASK 0x3f
#define PDSTAT_STATE_MASK 0x1f
#define MDCTL_FORCE BIT(31)
-#define PDCTL_NEXT BIT(1)
+#define PDCTL_NEXT BIT(0)
#define PDCTL_EPCGOOD BIT(8)
#ifndef __ASSEMBLER__
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index bda7aca04ca0..42ab1e7c4ecc 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -181,7 +181,7 @@ static int get_tclk(void)
return 166666667;
}
-static void dove_timer_init(void)
+static void __init dove_timer_init(void)
{
orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
IRQ_DOVE_BRIDGE, get_tclk());
diff --git a/arch/arm/mach-dove/mpp.c b/arch/arm/mach-dove/mpp.c
index 51e0e411c9cb..7f70afc26f91 100644
--- a/arch/arm/mach-dove/mpp.c
+++ b/arch/arm/mach-dove/mpp.c
@@ -56,7 +56,7 @@ static void dove_mpp_gpio_mode(int start, int end, int gpio_mode)
/* Dump all the extra MPP registers. The platform code will dump the
registers for pins 0-23. */
-static void dove_mpp_dump_regs(void)
+static void __init dove_mpp_dump_regs(void)
{
pr_debug("PMU_CTRL4_CTRL: %08x\n",
readl(DOVE_MPP_CTRL4_VIRT_BASE));
@@ -67,7 +67,7 @@ static void dove_mpp_dump_regs(void)
pr_debug("MPP_GENERAL: %08x\n", readl(DOVE_MPP_GENERAL_VIRT_BASE));
}
-static void dove_mpp_cfg_nfc(int sel)
+static void __init dove_mpp_cfg_nfc(int sel)
{
u32 mpp_gen_cfg = readl(DOVE_MPP_GENERAL_VIRT_BASE);
@@ -78,7 +78,7 @@ static void dove_mpp_cfg_nfc(int sel)
dove_mpp_gpio_mode(64, 71, GPIO_OUTPUT_OK);
}
-static void dove_mpp_cfg_au1(int sel)
+static void __init dove_mpp_cfg_au1(int sel)
{
u32 mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
u32 ssp_ctrl1 = readl(DOVE_SSP_CTRL_STATUS_1);
@@ -118,7 +118,7 @@ static void dove_mpp_cfg_au1(int sel)
/* Configure the group registers, enabling GPIO if sel indicates the
pin is to be used for GPIO */
-static void dove_mpp_conf_grp(unsigned int *mpp_grp_list)
+static void __init dove_mpp_conf_grp(unsigned int *mpp_grp_list)
{
u32 mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
int gpio_mode;
diff --git a/arch/arm/mach-dove/pcie.c b/arch/arm/mach-dove/pcie.c
index 48a032005ea3..47921b0cdc65 100644
--- a/arch/arm/mach-dove/pcie.c
+++ b/arch/arm/mach-dove/pcie.c
@@ -43,6 +43,7 @@ static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
return 0;
pp = &pcie_port[nr];
+ sys->private_data = pp;
pp->root_bus_nr = sys->busnr;
/*
@@ -93,19 +94,6 @@ static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
return 1;
}
-static struct pcie_port *bus_to_port(int bus)
-{
- int i;
-
- for (i = num_pcie_ports - 1; i >= 0; i--) {
- int rbus = pcie_port[i].root_bus_nr;
- if (rbus != -1 && rbus <= bus)
- break;
- }
-
- return i >= 0 ? pcie_port + i : NULL;
-}
-
static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
{
/*
@@ -121,7 +109,8 @@ static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
int size, u32 *val)
{
- struct pcie_port *pp = bus_to_port(bus->number);
+ struct pci_sys_data *sys = bus->sysdata;
+ struct pcie_port *pp = sys->private_data;
unsigned long flags;
int ret;
@@ -140,7 +129,8 @@ static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 val)
{
- struct pcie_port *pp = bus_to_port(bus->number);
+ struct pci_sys_data *sys = bus->sysdata;
+ struct pcie_port *pp = sys->private_data;
unsigned long flags;
int ret;
@@ -194,14 +184,14 @@ dove_pcie_scan_bus(int nr, struct pci_sys_data *sys)
static int __init dove_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
- struct pcie_port *pp = bus_to_port(dev->bus->number);
+ struct pci_sys_data *sys = dev->sysdata;
+ struct pcie_port *pp = sys->private_data;
return pp->index ? IRQ_DOVE_PCIE1 : IRQ_DOVE_PCIE0;
}
static struct hw_pci dove_pci __initdata = {
.nr_controllers = 2,
- .swizzle = pci_std_swizzle,
.setup = dove_pcie_setup,
.scan = dove_pcie_scan_bus,
.map_irq = dove_pcie_map_irq,
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
index 97a249395b5a..fe3c1fa5462b 100644
--- a/arch/arm/mach-ep93xx/Kconfig
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -2,6 +2,11 @@ if ARCH_EP93XX
menu "Cirrus EP93xx Implementation Options"
+config EP93XX_SOC_COMMON
+ bool
+ default y
+ select LEDS_GPIO_REGISTER
+
config CRUNCH
bool "Support for MaverickCrunch"
help
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 8d2589588713..66b1494f23a6 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -241,11 +241,7 @@ unsigned int ep93xx_chip_revision(void)
* EP93xx GPIO
*************************************************************************/
static struct resource ep93xx_gpio_resource[] = {
- {
- .start = EP93XX_GPIO_PHYS_BASE,
- .end = EP93XX_GPIO_PHYS_BASE + 0xcc - 1,
- .flags = IORESOURCE_MEM,
- },
+ DEFINE_RES_MEM(EP93XX_GPIO_PHYS_BASE, 0xcc),
};
static struct platform_device ep93xx_gpio_device = {
@@ -288,11 +284,7 @@ static AMBA_APB_DEVICE(uart3, "apb:uart3", 0x00041010, EP93XX_UART3_PHYS_BASE,
{ IRQ_EP93XX_UART3 }, &ep93xx_uart_data);
static struct resource ep93xx_rtc_resource[] = {
- {
- .start = EP93XX_RTC_PHYS_BASE,
- .end = EP93XX_RTC_PHYS_BASE + 0x10c - 1,
- .flags = IORESOURCE_MEM,
- },
+ DEFINE_RES_MEM(EP93XX_RTC_PHYS_BASE, 0x10c),
};
static struct platform_device ep93xx_rtc_device = {
@@ -304,16 +296,8 @@ static struct platform_device ep93xx_rtc_device = {
static struct resource ep93xx_ohci_resources[] = {
- [0] = {
- .start = EP93XX_USB_PHYS_BASE,
- .end = EP93XX_USB_PHYS_BASE + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_EP93XX_USB,
- .end = IRQ_EP93XX_USB,
- .flags = IORESOURCE_IRQ,
- },
+ DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000),
+ DEFINE_RES_IRQ(IRQ_EP93XX_USB),
};
@@ -372,15 +356,8 @@ void __init ep93xx_register_flash(unsigned int width,
static struct ep93xx_eth_data ep93xx_eth_data;
static struct resource ep93xx_eth_resource[] = {
- {
- .start = EP93XX_ETHERNET_PHYS_BASE,
- .end = EP93XX_ETHERNET_PHYS_BASE + 0xffff,
- .flags = IORESOURCE_MEM,
- }, {
- .start = IRQ_EP93XX_ETHERNET,
- .end = IRQ_EP93XX_ETHERNET,
- .flags = IORESOURCE_IRQ,
- }
+ DEFINE_RES_MEM(EP93XX_ETHERNET_PHYS_BASE, 0x10000),
+ DEFINE_RES_IRQ(IRQ_EP93XX_ETHERNET),
};
static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32);
@@ -461,16 +438,8 @@ void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
static struct ep93xx_spi_info ep93xx_spi_master_data;
static struct resource ep93xx_spi_resources[] = {
- {
- .start = EP93XX_SPI_PHYS_BASE,
- .end = EP93XX_SPI_PHYS_BASE + 0x18 - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = IRQ_EP93XX_SSP,
- .end = IRQ_EP93XX_SSP,
- .flags = IORESOURCE_IRQ,
- },
+ DEFINE_RES_MEM(EP93XX_SPI_PHYS_BASE, 0x18),
+ DEFINE_RES_IRQ(IRQ_EP93XX_SSP),
};
static u64 ep93xx_spi_dma_mask = DMA_BIT_MASK(32);
@@ -513,7 +482,7 @@ void __init ep93xx_register_spi(struct ep93xx_spi_info *info,
/*************************************************************************
* EP93xx LEDs
*************************************************************************/
-static struct gpio_led ep93xx_led_pins[] = {
+static const struct gpio_led ep93xx_led_pins[] __initconst = {
{
.name = "platform:grled",
.gpio = EP93XX_GPIO_LINE_GRLED,
@@ -523,29 +492,16 @@ static struct gpio_led ep93xx_led_pins[] = {
},
};
-static struct gpio_led_platform_data ep93xx_led_data = {
+static const struct gpio_led_platform_data ep93xx_led_data __initconst = {
.num_leds = ARRAY_SIZE(ep93xx_led_pins),
.leds = ep93xx_led_pins,
};
-static struct platform_device ep93xx_leds = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &ep93xx_led_data,
- },
-};
-
-
/*************************************************************************
* EP93xx pwm peripheral handling
*************************************************************************/
static struct resource ep93xx_pwm0_resource[] = {
- {
- .start = EP93XX_PWM_PHYS_BASE,
- .end = EP93XX_PWM_PHYS_BASE + 0x10 - 1,
- .flags = IORESOURCE_MEM,
- },
+ DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE, 0x10),
};
static struct platform_device ep93xx_pwm0_device = {
@@ -556,11 +512,7 @@ static struct platform_device ep93xx_pwm0_device = {
};
static struct resource ep93xx_pwm1_resource[] = {
- {
- .start = EP93XX_PWM_PHYS_BASE + 0x20,
- .end = EP93XX_PWM_PHYS_BASE + 0x30 - 1,
- .flags = IORESOURCE_MEM,
- },
+ DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE + 0x20, 0x10),
};
static struct platform_device ep93xx_pwm1_device = {
@@ -628,11 +580,7 @@ EXPORT_SYMBOL(ep93xx_pwm_release_gpio);
static struct ep93xxfb_mach_info ep93xxfb_data;
static struct resource ep93xx_fb_resource[] = {
- {
- .start = EP93XX_RASTER_PHYS_BASE,
- .end = EP93XX_RASTER_PHYS_BASE + 0x800 - 1,
- .flags = IORESOURCE_MEM,
- },
+ DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE, 0x800),
};
static struct platform_device ep93xx_fb_device = {
@@ -680,15 +628,8 @@ void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data)
static struct ep93xx_keypad_platform_data ep93xx_keypad_data;
static struct resource ep93xx_keypad_resource[] = {
- {
- .start = EP93XX_KEY_MATRIX_PHYS_BASE,
- .end = EP93XX_KEY_MATRIX_PHYS_BASE + 0x0c - 1,
- .flags = IORESOURCE_MEM,
- }, {
- .start = IRQ_EP93XX_KEY,
- .end = IRQ_EP93XX_KEY,
- .flags = IORESOURCE_IRQ,
- },
+ DEFINE_RES_MEM(EP93XX_KEY_MATRIX_PHYS_BASE, 0x0c),
+ DEFINE_RES_IRQ(IRQ_EP93XX_KEY),
};
static struct platform_device ep93xx_keypad_device = {
@@ -761,11 +702,7 @@ EXPORT_SYMBOL(ep93xx_keypad_release_gpio);
* EP93xx I2S audio peripheral handling
*************************************************************************/
static struct resource ep93xx_i2s_resource[] = {
- {
- .start = EP93XX_I2S_PHYS_BASE,
- .end = EP93XX_I2S_PHYS_BASE + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
+ DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100),
};
static struct platform_device ep93xx_i2s_device = {
@@ -824,16 +761,8 @@ EXPORT_SYMBOL(ep93xx_i2s_release);
* EP93xx AC97 audio peripheral handling
*************************************************************************/
static struct resource ep93xx_ac97_resources[] = {
- {
- .start = EP93XX_AAC_PHYS_BASE,
- .end = EP93XX_AAC_PHYS_BASE + 0xac - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = IRQ_EP93XX_AACINTR,
- .end = IRQ_EP93XX_AACINTR,
- .flags = IORESOURCE_IRQ,
- },
+ DEFINE_RES_MEM(EP93XX_AAC_PHYS_BASE, 0xac),
+ DEFINE_RES_IRQ(IRQ_EP93XX_AACINTR),
};
static struct platform_device ep93xx_ac97_device = {
@@ -889,8 +818,9 @@ void __init ep93xx_init_devices(void)
platform_device_register(&ep93xx_rtc_device);
platform_device_register(&ep93xx_ohci_device);
- platform_device_register(&ep93xx_leds);
platform_device_register(&ep93xx_wdt_device);
+
+ gpio_led_register_device(-1, &ep93xx_led_data);
}
void ep93xx_restart(char mode, const char *cmd)
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index b8df521fb68e..15b05b89cc39 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -200,6 +200,7 @@ config MACH_SMDKV310
select S3C_DEV_HSMMC2
select S3C_DEV_HSMMC3
select SAMSUNG_DEV_BACKLIGHT
+ select EXYNOS_DEV_DRM
select EXYNOS4_DEV_AHCI
select SAMSUNG_DEV_KEYPAD
select EXYNOS4_DEV_DMA
@@ -250,11 +251,13 @@ config MACH_UNIVERSAL_C210
select S3C_DEV_I2C1
select S3C_DEV_I2C3
select S3C_DEV_I2C5
+ select S3C_DEV_USB_HSOTG
select S5P_DEV_I2C_HDMIPHY
select S5P_DEV_MFC
select S5P_DEV_ONENAND
select S5P_DEV_TV
select EXYNOS4_DEV_DMA
+ select EXYNOS_DEV_DRM
select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_I2C3
@@ -262,6 +265,7 @@ config MACH_UNIVERSAL_C210
select EXYNOS4_SETUP_SDHCI
select EXYNOS4_SETUP_FIMC
select S5P_SETUP_MIPIPHY
+ select EXYNOS4_SETUP_USB_PHY
help
Machine support for Samsung Mobile Universal S5PC210 Reference
Board.
@@ -280,6 +284,7 @@ config MACH_NURI
select S3C_DEV_I2C3
select S3C_DEV_I2C5
select S3C_DEV_I2C6
+ select S3C_DEV_USB_HSOTG
select S5P_DEV_CSIS0
select S5P_DEV_JPEG
select S5P_DEV_FIMC0
@@ -291,6 +296,7 @@ config MACH_NURI
select S5P_DEV_USB_EHCI
select S5P_SETUP_MIPIPHY
select EXYNOS4_DEV_DMA
+ select EXYNOS_DEV_DRM
select EXYNOS4_SETUP_FIMC
select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_I2C1
@@ -325,6 +331,7 @@ config MACH_ORIGEN
select S5P_DEV_USB_EHCI
select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_PWM
+ select EXYNOS_DEV_DRM
select EXYNOS4_DEV_DMA
select EXYNOS4_DEV_USB_OHCI
select EXYNOS4_SETUP_FIMD0
@@ -345,6 +352,11 @@ config MACH_SMDK4212
select S3C_DEV_I2C7
select S3C_DEV_RTC
select S3C_DEV_WDT
+ select S5P_DEV_FIMC0
+ select S5P_DEV_FIMC1
+ select S5P_DEV_FIMC2
+ select S5P_DEV_FIMC3
+ select S5P_DEV_MFC
select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_KEYPAD
select SAMSUNG_DEV_PWM
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
index 33ab4e7558af..26dac2893b8e 100644
--- a/arch/arm/mach-exynos/cpuidle.c
+++ b/arch/arm/mach-exynos/cpuidle.c
@@ -20,6 +20,7 @@
#include <asm/smp_scu.h>
#include <asm/suspend.h>
#include <asm/unified.h>
+#include <asm/cpuidle.h>
#include <mach/regs-pmu.h>
#include <mach/pmu.h>
@@ -34,22 +35,12 @@
#define S5P_CHECK_AFTR 0xFCBA0D10
-static int exynos4_enter_idle(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index);
static int exynos4_enter_lowpower(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index);
static struct cpuidle_state exynos4_cpuidle_set[] __initdata = {
- [0] = {
- .enter = exynos4_enter_idle,
- .exit_latency = 1,
- .target_residency = 100000,
- .flags = CPUIDLE_FLAG_TIME_VALID,
- .name = "C0",
- .desc = "ARM clock gating(WFI)",
- },
+ [0] = ARM_CPUIDLE_WFI_STATE,
[1] = {
.enter = exynos4_enter_lowpower,
.exit_latency = 300,
@@ -63,8 +54,9 @@ static struct cpuidle_state exynos4_cpuidle_set[] __initdata = {
static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
static struct cpuidle_driver exynos4_idle_driver = {
- .name = "exynos4_idle",
- .owner = THIS_MODULE,
+ .name = "exynos4_idle",
+ .owner = THIS_MODULE,
+ .en_core_tk_irqen = 1,
};
/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
@@ -103,13 +95,8 @@ static int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
- struct timeval before, after;
- int idle_time;
unsigned long tmp;
- local_irq_disable();
- do_gettimeofday(&before);
-
exynos4_set_wakeupmask();
/* Set value of power down register for aftr mode */
@@ -150,34 +137,6 @@ static int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
/* Clear wakeup state register */
__raw_writel(0x0, S5P_WAKEUP_STAT);
- do_gettimeofday(&after);
-
- local_irq_enable();
- idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
- (after.tv_usec - before.tv_usec);
-
- dev->last_residency = idle_time;
- return index;
-}
-
-static int exynos4_enter_idle(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- struct timeval before, after;
- int idle_time;
-
- local_irq_disable();
- do_gettimeofday(&before);
-
- cpu_do_idle();
-
- do_gettimeofday(&after);
- local_irq_enable();
- idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
- (after.tv_usec - before.tv_usec);
-
- dev->last_residency = idle_time;
return index;
}
@@ -192,7 +151,7 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
new_index = drv->safe_state_index;
if (new_index == 0)
- return exynos4_enter_idle(dev, drv, new_index);
+ return arm_cpuidle_simple_enter(dev, drv, new_index);
else
return exynos4_enter_core0_aftr(dev, drv, new_index);
}
diff --git a/arch/arm/mach-exynos/dev-ahci.c b/arch/arm/mach-exynos/dev-ahci.c
index 50ce5b0adcf1..ce1aad3eeeb9 100644
--- a/arch/arm/mach-exynos/dev-ahci.c
+++ b/arch/arm/mach-exynos/dev-ahci.c
@@ -236,16 +236,8 @@ static struct ahci_platform_data exynos4_ahci_pdata = {
};
static struct resource exynos4_ahci_resource[] = {
- [0] = {
- .start = EXYNOS4_PA_SATA,
- .end = EXYNOS4_PA_SATA + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = EXYNOS4_IRQ_SATA,
- .end = EXYNOS4_IRQ_SATA,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(EXYNOS4_PA_SATA, SZ_64K),
+ [1] = DEFINE_RES_IRQ(EXYNOS4_IRQ_SATA),
};
static u64 exynos4_ahci_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-exynos/dev-audio.c b/arch/arm/mach-exynos/dev-audio.c
index 7199e1ae79b4..b33a5b67b547 100644
--- a/arch/arm/mach-exynos/dev-audio.c
+++ b/arch/arm/mach-exynos/dev-audio.c
@@ -62,26 +62,10 @@ static struct s3c_audio_pdata i2sv5_pdata = {
};
static struct resource exynos4_i2s0_resource[] = {
- [0] = {
- .start = EXYNOS4_PA_I2S0,
- .end = EXYNOS4_PA_I2S0 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S0_TX,
- .end = DMACH_I2S0_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S0_RX,
- .end = DMACH_I2S0_RX,
- .flags = IORESOURCE_DMA,
- },
- [3] = {
- .start = DMACH_I2S0S_TX,
- .end = DMACH_I2S0S_TX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(EXYNOS4_PA_I2S0, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S0_TX),
+ [2] = DEFINE_RES_DMA(DMACH_I2S0_RX),
+ [3] = DEFINE_RES_DMA(DMACH_I2S0S_TX),
};
struct platform_device exynos4_device_i2s0 = {
@@ -110,21 +94,9 @@ static struct s3c_audio_pdata i2sv3_pdata = {
};
static struct resource exynos4_i2s1_resource[] = {
- [0] = {
- .start = EXYNOS4_PA_I2S1,
- .end = EXYNOS4_PA_I2S1 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S1_TX,
- .end = DMACH_I2S1_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S1_RX,
- .end = DMACH_I2S1_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(EXYNOS4_PA_I2S1, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S1_TX),
+ [2] = DEFINE_RES_DMA(DMACH_I2S1_RX),
};
struct platform_device exynos4_device_i2s1 = {
@@ -138,21 +110,9 @@ struct platform_device exynos4_device_i2s1 = {
};
static struct resource exynos4_i2s2_resource[] = {
- [0] = {
- .start = EXYNOS4_PA_I2S2,
- .end = EXYNOS4_PA_I2S2 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S2_TX,
- .end = DMACH_I2S2_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S2_RX,
- .end = DMACH_I2S2_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(EXYNOS4_PA_I2S2, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S2_TX),
+ [2] = DEFINE_RES_DMA(DMACH_I2S2_RX),
};
struct platform_device exynos4_device_i2s2 = {
@@ -192,21 +152,9 @@ static struct s3c_audio_pdata s3c_pcm_pdata = {
};
static struct resource exynos4_pcm0_resource[] = {
- [0] = {
- .start = EXYNOS4_PA_PCM0,
- .end = EXYNOS4_PA_PCM0 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_PCM0_TX,
- .end = DMACH_PCM0_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_PCM0_RX,
- .end = DMACH_PCM0_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(EXYNOS4_PA_PCM0, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
+ [2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
};
struct platform_device exynos4_device_pcm0 = {
@@ -220,21 +168,9 @@ struct platform_device exynos4_device_pcm0 = {
};
static struct resource exynos4_pcm1_resource[] = {
- [0] = {
- .start = EXYNOS4_PA_PCM1,
- .end = EXYNOS4_PA_PCM1 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_PCM1_TX,
- .end = DMACH_PCM1_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_PCM1_RX,
- .end = DMACH_PCM1_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(EXYNOS4_PA_PCM1, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_PCM1_TX),
+ [2] = DEFINE_RES_DMA(DMACH_PCM1_RX),
};
struct platform_device exynos4_device_pcm1 = {
@@ -248,21 +184,9 @@ struct platform_device exynos4_device_pcm1 = {
};
static struct resource exynos4_pcm2_resource[] = {
- [0] = {
- .start = EXYNOS4_PA_PCM2,
- .end = EXYNOS4_PA_PCM2 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_PCM2_TX,
- .end = DMACH_PCM2_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_PCM2_RX,
- .end = DMACH_PCM2_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(EXYNOS4_PA_PCM2, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_PCM2_TX),
+ [2] = DEFINE_RES_DMA(DMACH_PCM2_RX),
};
struct platform_device exynos4_device_pcm2 = {
@@ -283,31 +207,11 @@ static int exynos4_ac97_cfg_gpio(struct platform_device *pdev)
}
static struct resource exynos4_ac97_resource[] = {
- [0] = {
- .start = EXYNOS4_PA_AC97,
- .end = EXYNOS4_PA_AC97 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_AC97_PCMOUT,
- .end = DMACH_AC97_PCMOUT,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_AC97_PCMIN,
- .end = DMACH_AC97_PCMIN,
- .flags = IORESOURCE_DMA,
- },
- [3] = {
- .start = DMACH_AC97_MICIN,
- .end = DMACH_AC97_MICIN,
- .flags = IORESOURCE_DMA,
- },
- [4] = {
- .start = EXYNOS4_IRQ_AC97,
- .end = EXYNOS4_IRQ_AC97,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(EXYNOS4_PA_AC97, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT),
+ [2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN),
+ [3] = DEFINE_RES_DMA(DMACH_AC97_MICIN),
+ [4] = DEFINE_RES_IRQ(EXYNOS4_IRQ_AC97),
};
static struct s3c_audio_pdata s3c_ac97_pdata = {
@@ -338,16 +242,8 @@ static int exynos4_spdif_cfg_gpio(struct platform_device *pdev)
}
static struct resource exynos4_spdif_resource[] = {
- [0] = {
- .start = EXYNOS4_PA_SPDIF,
- .end = EXYNOS4_PA_SPDIF + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_SPDIF,
- .end = DMACH_SPDIF,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(EXYNOS4_PA_SPDIF, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_SPDIF),
};
static struct s3c_audio_pdata samsung_spdif_pdata = {
diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
index 591e78521a9f..c02dae7bf4a3 100644
--- a/arch/arm/mach-exynos/include/mach/irqs.h
+++ b/arch/arm/mach-exynos/include/mach/irqs.h
@@ -189,6 +189,7 @@
#define IRQ_IIC7 EXYNOS4_IRQ_IIC7
#define IRQ_USB_HOST EXYNOS4_IRQ_USB_HOST
+#define IRQ_OTG EXYNOS4_IRQ_USB_HSOTG
#define IRQ_HSMMC0 EXYNOS4_IRQ_HSMMC0
#define IRQ_HSMMC1 EXYNOS4_IRQ_HSMMC1
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 6e6d11ff352a..e009a66477f4 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -130,6 +130,9 @@
#define EXYNOS4_PA_HSMMC(x) (0x12510000 + ((x) * 0x10000))
#define EXYNOS4_PA_DWMCI 0x12550000
+#define EXYNOS4_PA_HSOTG 0x12480000
+#define EXYNOS4_PA_USB_HSPHY 0x125B0000
+
#define EXYNOS4_PA_SATA 0x12560000
#define EXYNOS4_PA_SATAPHY 0x125D0000
#define EXYNOS4_PA_SATAPHY_CTRL 0x126B0000
@@ -186,6 +189,7 @@
#define S3C_PA_SPI0 EXYNOS4_PA_SPI0
#define S3C_PA_SPI1 EXYNOS4_PA_SPI1
#define S3C_PA_SPI2 EXYNOS4_PA_SPI2
+#define S3C_PA_USB_HSOTG EXYNOS4_PA_HSOTG
#define S5P_PA_EHCI EXYNOS4_PA_EHCI
#define S5P_PA_FIMC0 EXYNOS4_PA_FIMC0
diff --git a/arch/arm/mach-exynos/include/mach/regs-pmu.h b/arch/arm/mach-exynos/include/mach/regs-pmu.h
index 4c53f38b5a9e..d457d052a420 100644
--- a/arch/arm/mach-exynos/include/mach/regs-pmu.h
+++ b/arch/arm/mach-exynos/include/mach/regs-pmu.h
@@ -163,6 +163,9 @@
#define S5P_CHECK_SLEEP 0x00000BAD
/* Only for EXYNOS4210 */
+#define S5P_USBDEVICE_PHY_CONTROL S5P_PMUREG(0x0704)
+#define S5P_USBDEVICE_PHY_ENABLE (1 << 0)
+
#define S5P_USBHOST_PHY_CONTROL S5P_PMUREG(0x0708)
#define S5P_USBHOST_PHY_ENABLE (1 << 0)
diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c
index d726fcd3acf9..fed7116418eb 100644
--- a/arch/arm/mach-exynos/mach-armlex4210.c
+++ b/arch/arm/mach-exynos/mach-armlex4210.c
@@ -77,7 +77,6 @@ static struct s3c2410_uartcfg armlex4210_uartcfgs[] __initdata = {
static struct s3c_sdhci_platdata armlex4210_hsmmc0_pdata __initdata = {
.cd_type = S3C_SDHCI_CD_PERMANENT,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
.max_width = 8,
.host_caps = MMC_CAP_8_BIT_DATA,
@@ -88,13 +87,11 @@ static struct s3c_sdhci_platdata armlex4210_hsmmc2_pdata __initdata = {
.cd_type = S3C_SDHCI_CD_GPIO,
.ext_cd_gpio = EXYNOS4_GPX2(5),
.ext_cd_gpio_invert = 1,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
.max_width = 4,
};
static struct s3c_sdhci_platdata armlex4210_hsmmc3_pdata __initdata = {
.cd_type = S3C_SDHCI_CD_PERMANENT,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
.max_width = 4,
};
@@ -121,16 +118,9 @@ static void __init armlex4210_wlan_init(void)
}
static struct resource armlex4210_smsc911x_resources[] = {
- [0] = {
- .start = EXYNOS4_PA_SROM_BANK(3),
- .end = EXYNOS4_PA_SROM_BANK(3) + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_EINT(27),
- .end = IRQ_EINT(27),
- .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
- },
+ [0] = DEFINE_RES_MEM(EXYNOS4_PA_SROM_BANK(3), SZ_64K),
+ [1] = DEFINE_RES_NAMED(IRQ_EINT(27), 1, NULL, IORESOURCE_IRQ \
+ | IRQF_TRIGGER_HIGH),
};
static struct smsc911x_platform_config smsc9215_config = {
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index ed90aef404c3..6c31f2ad765d 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -25,6 +25,8 @@
#include <linux/mmc/host.h>
#include <linux/fb.h>
#include <linux/pwm_backlight.h>
+#include <linux/platform_data/s3c-hsotg.h>
+#include <drm/exynos_drm.h>
#include <video/platform_lcd.h>
#include <media/m5mols.h>
@@ -114,7 +116,6 @@ static struct s3c_sdhci_platdata nuri_hsmmc0_data __initdata = {
MMC_CAP_ERASE),
.host_caps2 = MMC_CAP2_BROKEN_VOLTAGE,
.cd_type = S3C_SDHCI_CD_PERMANENT,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
};
static struct regulator_consumer_supply emmc_supplies[] = {
@@ -155,7 +156,6 @@ static struct s3c_sdhci_platdata nuri_hsmmc2_data __initdata = {
.ext_cd_gpio = EXYNOS4_GPX3(3), /* XEINT_27 */
.ext_cd_gpio_invert = 1,
.cd_type = S3C_SDHCI_CD_GPIO,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
};
/* WLAN */
@@ -164,7 +164,6 @@ static struct s3c_sdhci_platdata nuri_hsmmc3_data __initdata = {
.host_caps = MMC_CAP_4_BIT_DATA |
MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
.cd_type = S3C_SDHCI_CD_EXTERNAL,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
};
static void __init nuri_sdhci_init(void)
@@ -213,6 +212,29 @@ static struct platform_device nuri_gpio_keys = {
},
};
+#ifdef CONFIG_DRM_EXYNOS
+static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
+ .panel = {
+ .timing = {
+ .xres = 1024,
+ .yres = 600,
+ .hsync_len = 40,
+ .left_margin = 79,
+ .right_margin = 200,
+ .vsync_len = 10,
+ .upper_margin = 10,
+ .lower_margin = 11,
+ .refresh = 60,
+ },
+ },
+ .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
+ VIDCON0_CLKSEL_LCD,
+ .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+ .default_win = 3,
+ .bpp = 32,
+};
+
+#else
/* Frame Buffer */
static struct s3c_fb_pd_win nuri_fb_win0 = {
.win_mode = {
@@ -239,6 +261,7 @@ static struct s3c_fb_platdata nuri_fb_pdata __initdata = {
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
.setup_gpio = exynos4_fimd0_gpio_setup_24bpp,
};
+#endif
static void nuri_lcd_power_on(struct plat_lcd_data *pd, unsigned int power)
{
@@ -351,6 +374,7 @@ static struct regulator_consumer_supply __initdata max8997_ldo1_[] = {
REGULATOR_SUPPLY("vdd", "s5p-adc"), /* Used by CPU's ADC drv */
};
static struct regulator_consumer_supply __initdata max8997_ldo3_[] = {
+ REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"), /* USB */
REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
};
static struct regulator_consumer_supply __initdata max8997_ldo4_[] = {
@@ -366,7 +390,7 @@ static struct regulator_consumer_supply __initdata max8997_ldo7_[] = {
REGULATOR_SUPPLY("dig_18", "0-001f"), /* HCD803 */
};
static struct regulator_consumer_supply __initdata max8997_ldo8_[] = {
- REGULATOR_SUPPLY("vusb_d", NULL), /* Used by CPU */
+ REGULATOR_SUPPLY("vusb_a", "s3c-hsotg"), /* USB */
REGULATOR_SUPPLY("vdac", NULL), /* Used by CPU */
};
static struct regulator_consumer_supply __initdata max8997_ldo11_[] = {
@@ -822,6 +846,7 @@ static struct regulator_init_data __initdata max8997_esafeout1_data = {
.constraints = {
.name = "SAFEOUT1",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
.state_mem = {
.disabled = 1,
},
@@ -1079,6 +1104,9 @@ static void __init nuri_ehci_init(void)
s5p_ehci_set_platdata(pdata);
}
+/* USB OTG */
+static struct s3c_hsotg_plat nuri_hsotg_pdata;
+
/* CAMERA */
static struct regulator_consumer_supply cam_vt_cam15_supply =
REGULATOR_SUPPLY("vdd_core", "6-003c");
@@ -1291,6 +1319,7 @@ static struct platform_device *nuri_devices[] __initdata = {
&s5p_device_mfc_l,
&s5p_device_mfc_r,
&s5p_device_fimc_md,
+ &s3c_device_usb_hsotg,
/* NURI Devices */
&nuri_gpio_keys,
@@ -1302,6 +1331,9 @@ static struct platform_device *nuri_devices[] __initdata = {
&cam_vdda_fixed_rdev,
&cam_8m_12v_fixed_rdev,
&exynos4_bus_devfreq,
+#ifdef CONFIG_DRM_EXYNOS
+ &exynos_device_drm,
+#endif
};
static void __init nuri_map_io(void)
@@ -1334,11 +1366,17 @@ static void __init nuri_machine_init(void)
i2c_register_board_info(9, i2c9_devs, ARRAY_SIZE(i2c9_devs));
s3c_i2c6_set_platdata(&nuri_i2c6_platdata);
+#ifdef CONFIG_DRM_EXYNOS
+ s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata;
+ exynos4_fimd0_gpio_setup_24bpp();
+#else
s5p_fimd0_set_platdata(&nuri_fb_pdata);
+#endif
nuri_camera_init();
nuri_ehci_init();
+ s3c_hsotg_set_platdata(&nuri_hsotg_pdata);
/* Last */
platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 878d4c99142d..26124a38bcbd 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -45,6 +45,7 @@
#include <mach/ohci.h>
#include <mach/map.h>
+#include <drm/exynos_drm.h>
#include "common.h"
/* Following are default values for UCON, ULCON and UFCON UART registers */
@@ -472,12 +473,10 @@ static struct i2c_board_info i2c0_devs[] __initdata = {
static struct s3c_sdhci_platdata origen_hsmmc0_pdata __initdata = {
.cd_type = S3C_SDHCI_CD_INTERNAL,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
};
static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = {
.cd_type = S3C_SDHCI_CD_INTERNAL,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
};
/* USB EHCI */
@@ -583,6 +582,27 @@ static struct platform_device origen_lcd_hv070wsa = {
.dev.platform_data = &origen_lcd_hv070wsa_data,
};
+#ifdef CONFIG_DRM_EXYNOS
+static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
+ .panel = {
+ .timing = {
+ .left_margin = 64,
+ .right_margin = 16,
+ .upper_margin = 64,
+ .lower_margin = 16,
+ .hsync_len = 48,
+ .vsync_len = 3,
+ .xres = 1024,
+ .yres = 600,
+ },
+ },
+ .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+ .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC |
+ VIDCON1_INV_VCLK,
+ .default_win = 0,
+ .bpp = 32,
+};
+#else
static struct s3c_fb_pd_win origen_fb_win0 = {
.win_mode = {
.left_margin = 64,
@@ -596,6 +616,8 @@ static struct s3c_fb_pd_win origen_fb_win0 = {
},
.max_bpp = 32,
.default_bpp = 24,
+ .virtual_x = 1024,
+ .virtual_y = 2 * 600,
};
static struct s3c_fb_platdata origen_lcd_pdata __initdata = {
@@ -605,9 +627,10 @@ static struct s3c_fb_platdata origen_lcd_pdata __initdata = {
VIDCON1_INV_VCLK,
.setup_gpio = exynos4_fimd0_gpio_setup_24bpp,
};
+#endif
/* Bluetooth rfkill gpio platform data */
-struct rfkill_gpio_platform_data origen_bt_pdata = {
+static struct rfkill_gpio_platform_data origen_bt_pdata = {
.reset_gpio = EXYNOS4_GPX2(2),
.shutdown_gpio = -1,
.type = RFKILL_TYPE_BLUETOOTH,
@@ -644,6 +667,9 @@ static struct platform_device *origen_devices[] __initdata = {
&s5p_device_mfc_l,
&s5p_device_mfc_r,
&s5p_device_mixer,
+#ifdef CONFIG_DRM_EXYNOS
+ &exynos_device_drm,
+#endif
&exynos4_device_ohci,
&origen_device_gpiokeys,
&origen_lcd_hv070wsa,
@@ -719,7 +745,12 @@ static void __init origen_machine_init(void)
s5p_tv_setup();
s5p_i2c_hdmiphy_set_platdata(NULL);
+#ifdef CONFIG_DRM_EXYNOS
+ s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata;
+ exynos4_fimd0_gpio_setup_24bpp();
+#else
s5p_fimd0_set_platdata(&origen_lcd_pdata);
+#endif
platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c
index d00e4f016a68..fe772d893cc9 100644
--- a/arch/arm/mach-exynos/mach-smdk4x12.c
+++ b/arch/arm/mach-exynos/mach-smdk4x12.c
@@ -31,6 +31,7 @@
#include <plat/gpio-cfg.h>
#include <plat/iic.h>
#include <plat/keypad.h>
+#include <plat/mfc.h>
#include <plat/regs-serial.h>
#include <plat/sdhci.h>
@@ -85,7 +86,6 @@ static struct s3c2410_uartcfg smdk4x12_uartcfgs[] __initdata = {
static struct s3c_sdhci_platdata smdk4x12_hsmmc2_pdata __initdata = {
.cd_type = S3C_SDHCI_CD_INTERNAL,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
.max_width = 8,
.host_caps = MMC_CAP_8_BIT_DATA,
@@ -94,7 +94,6 @@ static struct s3c_sdhci_platdata smdk4x12_hsmmc2_pdata __initdata = {
static struct s3c_sdhci_platdata smdk4x12_hsmmc3_pdata __initdata = {
.cd_type = S3C_SDHCI_CD_INTERNAL,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
};
static struct regulator_consumer_supply max8997_buck1 =
@@ -244,6 +243,14 @@ static struct platform_device *smdk4x12_devices[] __initdata = {
&s3c_device_i2c7,
&s3c_device_rtc,
&s3c_device_wdt,
+ &s5p_device_fimc0,
+ &s5p_device_fimc1,
+ &s5p_device_fimc2,
+ &s5p_device_fimc3,
+ &s5p_device_fimc_md,
+ &s5p_device_mfc,
+ &s5p_device_mfc_l,
+ &s5p_device_mfc_r,
&samsung_device_keypad,
};
@@ -256,6 +263,11 @@ static void __init smdk4x12_map_io(void)
s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
}
+static void __init smdk4x12_reserve(void)
+{
+ s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
static void __init smdk4x12_machine_init(void)
{
s3c_i2c0_set_platdata(NULL);
@@ -293,6 +305,7 @@ MACHINE_START(SMDK4212, "SMDK4212")
.init_machine = smdk4x12_machine_init,
.timer = &exynos4_timer,
.restart = exynos4_restart,
+ .reserve = &smdk4x12_reserve,
MACHINE_END
MACHINE_START(SMDK4412, "SMDK4412")
@@ -305,4 +318,5 @@ MACHINE_START(SMDK4412, "SMDK4412")
.init_machine = smdk4x12_machine_init,
.timer = &exynos4_timer,
.restart = exynos4_restart,
+ .reserve = &smdk4x12_reserve,
MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index 83b91fa777c1..5af96064ca51 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -44,6 +44,7 @@
#include <mach/map.h>
#include <mach/ohci.h>
+#include <drm/exynos_drm.h>
#include "common.h"
/* Following are default values for UCON, ULCON and UFCON UART registers */
@@ -93,7 +94,6 @@ static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = {
static struct s3c_sdhci_platdata smdkv310_hsmmc0_pdata __initdata = {
.cd_type = S3C_SDHCI_CD_INTERNAL,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
.max_width = 8,
.host_caps = MMC_CAP_8_BIT_DATA,
@@ -104,12 +104,10 @@ static struct s3c_sdhci_platdata smdkv310_hsmmc1_pdata __initdata = {
.cd_type = S3C_SDHCI_CD_GPIO,
.ext_cd_gpio = EXYNOS4_GPK0(2),
.ext_cd_gpio_invert = 1,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
};
static struct s3c_sdhci_platdata smdkv310_hsmmc2_pdata __initdata = {
.cd_type = S3C_SDHCI_CD_INTERNAL,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
.max_width = 8,
.host_caps = MMC_CAP_8_BIT_DATA,
@@ -120,7 +118,6 @@ static struct s3c_sdhci_platdata smdkv310_hsmmc3_pdata __initdata = {
.cd_type = S3C_SDHCI_CD_GPIO,
.ext_cd_gpio = EXYNOS4_GPK2(2),
.ext_cd_gpio_invert = 1,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
};
static void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
@@ -160,6 +157,26 @@ static struct platform_device smdkv310_lcd_lte480wv = {
.dev.platform_data = &smdkv310_lcd_lte480wv_data,
};
+#ifdef CONFIG_DRM_EXYNOS
+static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
+ .panel = {
+ .timing = {
+ .left_margin = 13,
+ .right_margin = 8,
+ .upper_margin = 7,
+ .lower_margin = 5,
+ .hsync_len = 3,
+ .vsync_len = 1,
+ .xres = 800,
+ .yres = 480,
+ },
+ },
+ .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+ .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+ .default_win = 0,
+ .bpp = 32,
+};
+#else
static struct s3c_fb_pd_win smdkv310_fb_win0 = {
.win_mode = {
.left_margin = 13,
@@ -181,18 +198,12 @@ static struct s3c_fb_platdata smdkv310_lcd0_pdata __initdata = {
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
.setup_gpio = exynos4_fimd0_gpio_setup_24bpp,
};
+#endif
static struct resource smdkv310_smsc911x_resources[] = {
- [0] = {
- .start = EXYNOS4_PA_SROM_BANK(1),
- .end = EXYNOS4_PA_SROM_BANK(1) + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_EINT(5),
- .end = IRQ_EINT(5),
- .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
- },
+ [0] = DEFINE_RES_MEM(EXYNOS4_PA_SROM_BANK(1), SZ_64K),
+ [1] = DEFINE_RES_NAMED(IRQ_EINT(5), 1, NULL, IORESOURCE_IRQ \
+ | IRQF_TRIGGER_LOW),
};
static struct smsc911x_platform_config smsc9215_config = {
@@ -273,6 +284,9 @@ static struct platform_device *smdkv310_devices[] __initdata = {
&s5p_device_fimc_md,
&s5p_device_g2d,
&s5p_device_jpeg,
+#ifdef CONFIG_DRM_EXYNOS
+ &exynos_device_drm,
+#endif
&exynos4_device_ac97,
&exynos4_device_i2s0,
&exynos4_device_ohci,
@@ -364,7 +378,12 @@ static void __init smdkv310_machine_init(void)
samsung_keypad_set_platdata(&smdkv310_keypad_data);
samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
+#ifdef CONFIG_DRM_EXYNOS
+ s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata;
+ exynos4_fimd0_gpio_setup_24bpp();
+#else
s5p_fimd0_set_platdata(&smdkv310_lcd0_pdata);
+#endif
smdkv310_ehci_init();
smdkv310_ohci_init();
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index a34036eb8ba2..6b731b863275 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -23,6 +23,8 @@
#include <linux/i2c-gpio.h>
#include <linux/i2c/mcs.h>
#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/platform_data/s3c-hsotg.h>
+#include <drm/exynos_drm.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
@@ -205,6 +207,7 @@ static struct regulator_init_data lp3974_ldo2_data = {
};
static struct regulator_consumer_supply lp3974_ldo3_consumer[] = {
+ REGULATOR_SUPPLY("vusb_a", "s3c-hsotg"),
REGULATOR_SUPPLY("vdd", "exynos4-hdmi"),
REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"),
REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"),
@@ -290,6 +293,7 @@ static struct regulator_init_data lp3974_ldo7_data = {
};
static struct regulator_consumer_supply lp3974_ldo8_consumer[] = {
+ REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"),
REGULATOR_SUPPLY("vdd33a_dac", "s5p-sdo"),
};
@@ -486,7 +490,10 @@ static struct regulator_init_data lp3974_vichg_data = {
static struct regulator_init_data lp3974_esafeout1_data = {
.constraints = {
.name = "SAFEOUT1",
+ .min_uV = 4800000,
+ .max_uV = 4800000,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
.state_mem = {
.enabled = 1,
},
@@ -750,7 +757,6 @@ static struct s3c_sdhci_platdata universal_hsmmc0_data __initdata = {
MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
.host_caps2 = MMC_CAP2_BROKEN_VOLTAGE,
.cd_type = S3C_SDHCI_CD_PERMANENT,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
};
static struct regulator_consumer_supply mmc0_supplies[] = {
@@ -790,7 +796,6 @@ static struct s3c_sdhci_platdata universal_hsmmc2_data __initdata = {
.ext_cd_gpio = EXYNOS4_GPX3(4), /* XEINT_28 */
.ext_cd_gpio_invert = 1,
.cd_type = S3C_SDHCI_CD_GPIO,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
};
/* WiFi */
@@ -813,6 +818,29 @@ static struct i2c_board_info i2c1_devs[] __initdata = {
/* Gyro, To be updated */
};
+#ifdef CONFIG_DRM_EXYNOS
+static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
+ .panel = {
+ .timing = {
+ .left_margin = 16,
+ .right_margin = 16,
+ .upper_margin = 2,
+ .lower_margin = 28,
+ .hsync_len = 2,
+ .vsync_len = 1,
+ .xres = 480,
+ .yres = 800,
+ .refresh = 55,
+ },
+ },
+ .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
+ VIDCON0_CLKSEL_LCD,
+ .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN
+ | VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+ .default_win = 3,
+ .bpp = 32,
+};
+#else
/* Frame Buffer */
static struct s3c_fb_pd_win universal_fb_win0 = {
.win_mode = {
@@ -840,6 +868,7 @@ static struct s3c_fb_platdata universal_lcd_pdata __initdata = {
| VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
.setup_gpio = exynos4_fimd0_gpio_setup_24bpp,
};
+#endif
static struct regulator_consumer_supply cam_vt_dio_supply =
REGULATOR_SUPPLY("vdd_core", "0-003c");
@@ -994,6 +1023,9 @@ static struct gpio universal_camera_gpios[] = {
{ GPIO_CAM_VGA_NSTBY, GPIOF_OUT_INIT_LOW, "CAM_VGA_NSTBY" },
};
+/* USB OTG */
+static struct s3c_hsotg_plat universal_hsotg_pdata;
+
static void __init universal_camera_init(void)
{
s3c_set_platdata(&mipi_csis_platdata, sizeof(mipi_csis_platdata),
@@ -1049,6 +1081,10 @@ static struct platform_device *universal_devices[] __initdata = {
&s5p_device_onenand,
&s5p_device_fimd0,
&s5p_device_jpeg,
+#ifdef CONFIG_DRM_EXYNOS
+ &exynos_device_drm,
+#endif
+ &s3c_device_usb_hsotg,
&s5p_device_mfc,
&s5p_device_mfc_l,
&s5p_device_mfc_r,
@@ -1096,12 +1132,18 @@ static void __init universal_machine_init(void)
s5p_i2c_hdmiphy_set_platdata(NULL);
i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+#ifdef CONFIG_DRM_EXYNOS
+ s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata;
+ exynos4_fimd0_gpio_setup_24bpp();
+#else
s5p_fimd0_set_platdata(&universal_lcd_pdata);
+#endif
universal_touchkey_init();
i2c_register_board_info(I2C_GPIO_BUS_12, i2c_gpio12_devs,
ARRAY_SIZE(i2c_gpio12_devs));
+ s3c_hsotg_set_platdata(&universal_hsotg_pdata);
universal_camera_init();
/* Last */
diff --git a/arch/arm/mach-exynos/setup-usb-phy.c b/arch/arm/mach-exynos/setup-usb-phy.c
index 41743d21e8c6..1af0a7f44e00 100644
--- a/arch/arm/mach-exynos/setup-usb-phy.c
+++ b/arch/arm/mach-exynos/setup-usb-phy.c
@@ -26,11 +26,71 @@ static int exynos4_usb_host_phy_is_on(void)
return (readl(EXYNOS4_PHYPWR) & PHY1_STD_ANALOG_POWERDOWN) ? 0 : 1;
}
-static int exynos4_usb_phy1_init(struct platform_device *pdev)
+static void exynos4210_usb_phy_clkset(struct platform_device *pdev)
{
- struct clk *otg_clk;
struct clk *xusbxti_clk;
u32 phyclk;
+
+ /* set clock frequency for PLL */
+ phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
+
+ xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
+ if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
+ switch (clk_get_rate(xusbxti_clk)) {
+ case 12 * MHZ:
+ phyclk |= CLKSEL_12M;
+ break;
+ case 24 * MHZ:
+ phyclk |= CLKSEL_24M;
+ break;
+ default:
+ case 48 * MHZ:
+ /* default reference clock */
+ break;
+ }
+ clk_put(xusbxti_clk);
+ }
+
+ writel(phyclk, EXYNOS4_PHYCLK);
+}
+
+static int exynos4210_usb_phy0_init(struct platform_device *pdev)
+{
+ u32 rstcon;
+
+ writel(readl(S5P_USBDEVICE_PHY_CONTROL) | S5P_USBDEVICE_PHY_ENABLE,
+ S5P_USBDEVICE_PHY_CONTROL);
+
+ exynos4210_usb_phy_clkset(pdev);
+
+ /* set to normal PHY0 */
+ writel((readl(EXYNOS4_PHYPWR) & ~PHY0_NORMAL_MASK), EXYNOS4_PHYPWR);
+
+ /* reset PHY0 and Link */
+ rstcon = readl(EXYNOS4_RSTCON) | PHY0_SWRST_MASK;
+ writel(rstcon, EXYNOS4_RSTCON);
+ udelay(10);
+
+ rstcon &= ~PHY0_SWRST_MASK;
+ writel(rstcon, EXYNOS4_RSTCON);
+
+ return 0;
+}
+
+static int exynos4210_usb_phy0_exit(struct platform_device *pdev)
+{
+ writel((readl(EXYNOS4_PHYPWR) | PHY0_ANALOG_POWERDOWN |
+ PHY0_OTG_DISABLE), EXYNOS4_PHYPWR);
+
+ writel(readl(S5P_USBDEVICE_PHY_CONTROL) & ~S5P_USBDEVICE_PHY_ENABLE,
+ S5P_USBDEVICE_PHY_CONTROL);
+
+ return 0;
+}
+
+static int exynos4210_usb_phy1_init(struct platform_device *pdev)
+{
+ struct clk *otg_clk;
u32 rstcon;
int err;
@@ -54,27 +114,7 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev)
writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,
S5P_USBHOST_PHY_CONTROL);
- /* set clock frequency for PLL */
- phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
-
- xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
- if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
- switch (clk_get_rate(xusbxti_clk)) {
- case 12 * MHZ:
- phyclk |= CLKSEL_12M;
- break;
- case 24 * MHZ:
- phyclk |= CLKSEL_24M;
- break;
- default:
- case 48 * MHZ:
- /* default reference clock */
- break;
- }
- clk_put(xusbxti_clk);
- }
-
- writel(phyclk, EXYNOS4_PHYCLK);
+ exynos4210_usb_phy_clkset(pdev);
/* floating prevention logic: disable */
writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);
@@ -102,7 +142,7 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev)
return 0;
}
-static int exynos4_usb_phy1_exit(struct platform_device *pdev)
+static int exynos4210_usb_phy1_exit(struct platform_device *pdev)
{
struct clk *otg_clk;
int err;
@@ -136,16 +176,20 @@ static int exynos4_usb_phy1_exit(struct platform_device *pdev)
int s5p_usb_phy_init(struct platform_device *pdev, int type)
{
- if (type == S5P_USB_PHY_HOST)
- return exynos4_usb_phy1_init(pdev);
+ if (type == S5P_USB_PHY_DEVICE)
+ return exynos4210_usb_phy0_init(pdev);
+ else if (type == S5P_USB_PHY_HOST)
+ return exynos4210_usb_phy1_init(pdev);
return -EINVAL;
}
int s5p_usb_phy_exit(struct platform_device *pdev, int type)
{
- if (type == S5P_USB_PHY_HOST)
- return exynos4_usb_phy1_exit(pdev);
+ if (type == S5P_USB_PHY_DEVICE)
+ return exynos4210_usb_phy0_exit(pdev);
+ else if (type == S5P_USB_PHY_HOST)
+ return exynos4210_usb_phy1_exit(pdev);
return -EINVAL;
}
diff --git a/arch/arm/mach-footbridge/cats-pci.c b/arch/arm/mach-footbridge/cats-pci.c
index 32321f66dec4..5cec2567c9c5 100644
--- a/arch/arm/mach-footbridge/cats-pci.c
+++ b/arch/arm/mach-footbridge/cats-pci.c
@@ -16,6 +16,11 @@
/* cats host-specific stuff */
static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
+static u8 cats_no_swizzle(struct pci_dev *dev, u8 *pin)
+{
+ return 0;
+}
+
static int __init cats_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (dev->irq >= 255)
@@ -39,11 +44,11 @@ static int __init cats_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
* cards being used (ie, pci-pci bridge based cards)?
*/
static struct hw_pci cats_pci __initdata = {
- .swizzle = NULL,
+ .swizzle = cats_no_swizzle,
.map_irq = cats_map_irq,
.nr_controllers = 1,
+ .ops = &dc21285_ops,
.setup = dc21285_setup,
- .scan = dc21285_scan_bus,
.preinit = dc21285_preinit,
.postinit = dc21285_postinit,
};
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index e17e11de4f5e..9d62e3381024 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -129,7 +129,7 @@ dc21285_write_config(struct pci_bus *bus, unsigned int devfn, int where,
return PCIBIOS_SUCCESSFUL;
}
-static struct pci_ops dc21285_ops = {
+struct pci_ops dc21285_ops = {
.read = dc21285_read_config,
.write = dc21285_write_config,
};
@@ -284,11 +284,6 @@ int __init dc21285_setup(int nr, struct pci_sys_data *sys)
return 1;
}
-struct pci_bus * __init dc21285_scan_bus(int nr, struct pci_sys_data *sys)
-{
- return pci_scan_root_bus(NULL, 0, &dc21285_ops, sys, &sys->resources);
-}
-
#define dc21285_request_irq(_a, _b, _c, _d, _e) \
WARN_ON(request_irq(_a, _b, _c, _d, _e) < 0)
diff --git a/arch/arm/mach-footbridge/ebsa285-pci.c b/arch/arm/mach-footbridge/ebsa285-pci.c
index 511c673ffa9d..fd12d8a36dc5 100644
--- a/arch/arm/mach-footbridge/ebsa285-pci.c
+++ b/arch/arm/mach-footbridge/ebsa285-pci.c
@@ -29,11 +29,10 @@ static int __init ebsa285_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
}
static struct hw_pci ebsa285_pci __initdata = {
- .swizzle = pci_std_swizzle,
.map_irq = ebsa285_map_irq,
.nr_controllers = 1,
+ .ops = &dc21285_ops,
.setup = dc21285_setup,
- .scan = dc21285_scan_bus,
.preinit = dc21285_preinit,
.postinit = dc21285_postinit,
};
diff --git a/arch/arm/mach-footbridge/netwinder-pci.c b/arch/arm/mach-footbridge/netwinder-pci.c
index 62187610e17e..0fba5134e4fe 100644
--- a/arch/arm/mach-footbridge/netwinder-pci.c
+++ b/arch/arm/mach-footbridge/netwinder-pci.c
@@ -43,11 +43,10 @@ static int __init netwinder_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
}
static struct hw_pci netwinder_pci __initdata = {
- .swizzle = pci_std_swizzle,
.map_irq = netwinder_map_irq,
.nr_controllers = 1,
+ .ops = &dc21285_ops,
.setup = dc21285_setup,
- .scan = dc21285_scan_bus,
.preinit = dc21285_preinit,
.postinit = dc21285_postinit,
};
diff --git a/arch/arm/mach-footbridge/personal-pci.c b/arch/arm/mach-footbridge/personal-pci.c
index aeb651d914a6..5c9ee54613b2 100644
--- a/arch/arm/mach-footbridge/personal-pci.c
+++ b/arch/arm/mach-footbridge/personal-pci.c
@@ -41,8 +41,8 @@ static int __init personal_server_map_irq(const struct pci_dev *dev, u8 slot,
static struct hw_pci personal_server_pci __initdata = {
.map_irq = personal_server_map_irq,
.nr_controllers = 1,
+ .ops = &dc21285_ops,
.setup = dc21285_setup,
- .scan = dc21285_scan_bus,
.preinit = dc21285_preinit,
.postinit = dc21285_postinit,
};
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 7561eca131b0..cca8c0c74794 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -151,6 +151,7 @@ config MACH_MX25_3DS
select IMX_HAVE_PLATFORM_IMX2_WDT
select IMX_HAVE_PLATFORM_IMXDI_RTC
select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_SSI
select IMX_HAVE_PLATFORM_IMX_FB
select IMX_HAVE_PLATFORM_IMX_KEYPAD
select IMX_HAVE_PLATFORM_IMX_UART
@@ -163,6 +164,7 @@ config MACH_EUKREA_CPUIMX25SD
select SOC_IMX25
select IMX_HAVE_PLATFORM_FLEXCAN
select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_IMX2_WDT
select IMX_HAVE_PLATFORM_IMXDI_RTC
select IMX_HAVE_PLATFORM_IMX_FB
select IMX_HAVE_PLATFORM_IMX_I2C
@@ -181,6 +183,7 @@ config MACH_EUKREA_MBIMXSD25_BASEBOARD
bool "Eukrea MBIMXSD development board"
select IMX_HAVE_PLATFORM_GPIO_KEYS
select IMX_HAVE_PLATFORM_IMX_SSI
+ select IMX_HAVE_PLATFORM_SPI_IMX
select LEDS_GPIO_REGISTER
help
This adds board specific devices that can be found on Eukrea's
@@ -493,6 +496,7 @@ config MACH_MX31MOBOARD
select IMX_HAVE_PLATFORM_FSL_USB2_UDC
select IMX_HAVE_PLATFORM_IMX2_WDT
select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_SSI
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_IPU_CORE
select IMX_HAVE_PLATFORM_MXC_EHCI
@@ -571,8 +575,10 @@ config MACH_MX35_3DS
select MXC_DEBUG_BOARD
select IMX_HAVE_PLATFORM_FSL_USB2_UDC
select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_FB
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_IPU_CORE
select IMX_HAVE_PLATFORM_MXC_EHCI
select IMX_HAVE_PLATFORM_MXC_NAND
select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
@@ -606,6 +612,7 @@ config MACH_EUKREA_MBIMXSD35_BASEBOARD
select IMX_HAVE_PLATFORM_GPIO_KEYS
select IMX_HAVE_PLATFORM_IMX_SSI
select IMX_HAVE_PLATFORM_IPU_CORE
+ select IMX_HAVE_PLATFORM_SPI_IMX
select LEDS_GPIO_REGISTER
help
This adds board specific devices that can be found on Eukrea's
@@ -682,42 +689,13 @@ config MACH_MX51_3DS
Include support for MX51PDK (3DS) platform. This includes specific
configurations for the board and its peripherals.
-config MACH_EUKREA_CPUIMX51
- bool "Support Eukrea CPUIMX51 module"
- select SOC_IMX51
- select IMX_HAVE_PLATFORM_FSL_USB2_UDC
- select IMX_HAVE_PLATFORM_IMX_I2C
- select IMX_HAVE_PLATFORM_IMX_UART
- select IMX_HAVE_PLATFORM_MXC_EHCI
- select IMX_HAVE_PLATFORM_MXC_NAND
- select IMX_HAVE_PLATFORM_SPI_IMX
- help
- Include support for Eukrea CPUIMX51 platform. This includes
- specific configurations for the module and its peripherals.
-
-choice
- prompt "Baseboard"
- depends on MACH_EUKREA_CPUIMX51
- default MACH_EUKREA_MBIMX51_BASEBOARD
-
-config MACH_EUKREA_MBIMX51_BASEBOARD
- prompt "Eukrea MBIMX51 development board"
- bool
- select IMX_HAVE_PLATFORM_IMX_KEYPAD
- select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
- select LEDS_GPIO_REGISTER
- help
- This adds board specific devices that can be found on Eukrea's
- MBIMX51 evaluation board.
-
-endchoice
-
config MACH_EUKREA_CPUIMX51SD
bool "Support Eukrea CPUIMX51SD module"
select SOC_IMX51
select IMX_HAVE_PLATFORM_FSL_USB2_UDC
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_IMX2_WDT
select IMX_HAVE_PLATFORM_MXC_EHCI
select IMX_HAVE_PLATFORM_MXC_NAND
select IMX_HAVE_PLATFORM_SPI_IMX
@@ -733,6 +711,7 @@ choice
config MACH_EUKREA_MBIMXSD51_BASEBOARD
prompt "Eukrea MBIMXSD development board"
bool
+ select IMX_HAVE_PLATFORM_IMX_SSI
select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
select LEDS_GPIO_REGISTER
help
@@ -842,6 +821,8 @@ config SOC_IMX6Q
select HAVE_IMX_MMDC
select HAVE_IMX_SRC
select HAVE_SMP
+ select PINCTRL
+ select PINCTRL_IMX6Q
select USE_OF
help
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index ab939c5046c3..4937c070a57e 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -83,10 +83,8 @@ obj-$(CONFIG_MACH_MX53_EVK) += mach-mx53_evk.o
obj-$(CONFIG_MACH_MX53_SMD) += mach-mx53_smd.o
obj-$(CONFIG_MACH_MX53_LOCO) += mach-mx53_loco.o
obj-$(CONFIG_MACH_MX53_ARD) += mach-mx53_ard.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += mach-cpuimx51.o
-obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += mach-cpuimx51sd.o
-obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
+obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd51-baseboard.o
obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o
obj-$(CONFIG_MACH_MX51_EFIKAMX) += mach-mx51_efikamx.o
obj-$(CONFIG_MACH_MX51_EFIKASB) += mach-mx51_efikasb.o
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
index 5f2f91d1798b..b46cab0ced53 100644
--- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
@@ -243,7 +243,7 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
static void __maybe_unused ads7846_dev_init(void)
{
if (gpio_request(ADS7846_PENDOWN, "ADS7846 pendown") < 0) {
- printk(KERN_ERR "can't get ads746 pen down GPIO\n");
+ printk(KERN_ERR "can't get ads7846 pen down GPIO\n");
return;
}
gpio_direction_input(ADS7846_PENDOWN);
diff --git a/arch/arm/mach-imx/eukrea_mbimx51-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx51-baseboard.c
deleted file mode 100644
index a6a3ab8f1b1c..000000000000
--- a/arch/arm/mach-imx/eukrea_mbimx51-baseboard.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- *
- * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/i2c/tsc2007.h>
-#include <linux/leds.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/mach/arch.h>
-
-#include "devices-imx51.h"
-
-#define MBIMX51_TSC2007_GPIO IMX_GPIO_NR(3, 30)
-#define MBIMX51_LED0 IMX_GPIO_NR(3, 5)
-#define MBIMX51_LED1 IMX_GPIO_NR(3, 6)
-#define MBIMX51_LED2 IMX_GPIO_NR(3, 7)
-#define MBIMX51_LED3 IMX_GPIO_NR(3, 8)
-
-static const struct gpio_led mbimx51_leds[] __initconst = {
- {
- .name = "led0",
- .default_trigger = "heartbeat",
- .active_low = 1,
- .gpio = MBIMX51_LED0,
- },
- {
- .name = "led1",
- .default_trigger = "nand-disk",
- .active_low = 1,
- .gpio = MBIMX51_LED1,
- },
- {
- .name = "led2",
- .default_trigger = "mmc0",
- .active_low = 1,
- .gpio = MBIMX51_LED2,
- },
- {
- .name = "led3",
- .default_trigger = "default-on",
- .active_low = 1,
- .gpio = MBIMX51_LED3,
- },
-};
-
-static const struct gpio_led_platform_data mbimx51_leds_info __initconst = {
- .leds = mbimx51_leds,
- .num_leds = ARRAY_SIZE(mbimx51_leds),
-};
-
-static iomux_v3_cfg_t mbimx51_pads[] = {
- /* UART2 */
- MX51_PAD_UART2_RXD__UART2_RXD,
- MX51_PAD_UART2_TXD__UART2_TXD,
-
- /* UART3 */
- MX51_PAD_UART3_RXD__UART3_RXD,
- MX51_PAD_UART3_TXD__UART3_TXD,
- MX51_PAD_KEY_COL4__UART3_RTS,
- MX51_PAD_KEY_COL5__UART3_CTS,
-
- /* TSC2007 IRQ */
- MX51_PAD_NANDF_D10__GPIO3_30,
-
- /* LEDS */
- MX51_PAD_DISPB2_SER_DIN__GPIO3_5,
- MX51_PAD_DISPB2_SER_DIO__GPIO3_6,
- MX51_PAD_DISPB2_SER_CLK__GPIO3_7,
- MX51_PAD_DISPB2_SER_RS__GPIO3_8,
-
- /* KPP */
- MX51_PAD_KEY_ROW0__KEY_ROW0,
- MX51_PAD_KEY_ROW1__KEY_ROW1,
- MX51_PAD_KEY_ROW2__KEY_ROW2,
- MX51_PAD_KEY_ROW3__KEY_ROW3,
- MX51_PAD_KEY_COL0__KEY_COL0,
- MX51_PAD_KEY_COL1__KEY_COL1,
- MX51_PAD_KEY_COL2__KEY_COL2,
- MX51_PAD_KEY_COL3__KEY_COL3,
-
- /* SD 1 */
- MX51_PAD_SD1_CMD__SD1_CMD,
- MX51_PAD_SD1_CLK__SD1_CLK,
- MX51_PAD_SD1_DATA0__SD1_DATA0,
- MX51_PAD_SD1_DATA1__SD1_DATA1,
- MX51_PAD_SD1_DATA2__SD1_DATA2,
- MX51_PAD_SD1_DATA3__SD1_DATA3,
-
- /* SD 2 */
- MX51_PAD_SD2_CMD__SD2_CMD,
- MX51_PAD_SD2_CLK__SD2_CLK,
- MX51_PAD_SD2_DATA0__SD2_DATA0,
- MX51_PAD_SD2_DATA1__SD2_DATA1,
- MX51_PAD_SD2_DATA2__SD2_DATA2,
- MX51_PAD_SD2_DATA3__SD2_DATA3,
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
- .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static int mbimx51_keymap[] = {
- KEY(0, 0, KEY_1),
- KEY(0, 1, KEY_2),
- KEY(0, 2, KEY_3),
- KEY(0, 3, KEY_UP),
-
- KEY(1, 0, KEY_4),
- KEY(1, 1, KEY_5),
- KEY(1, 2, KEY_6),
- KEY(1, 3, KEY_LEFT),
-
- KEY(2, 0, KEY_7),
- KEY(2, 1, KEY_8),
- KEY(2, 2, KEY_9),
- KEY(2, 3, KEY_RIGHT),
-
- KEY(3, 0, KEY_0),
- KEY(3, 1, KEY_DOWN),
- KEY(3, 2, KEY_ESC),
- KEY(3, 3, KEY_ENTER),
-};
-
-static const struct matrix_keymap_data mbimx51_map_data __initconst = {
- .keymap = mbimx51_keymap,
- .keymap_size = ARRAY_SIZE(mbimx51_keymap),
-};
-
-static int tsc2007_get_pendown_state(void)
-{
- return !gpio_get_value(MBIMX51_TSC2007_GPIO);
-}
-
-struct tsc2007_platform_data tsc2007_data = {
- .model = 2007,
- .x_plate_ohms = 180,
- .get_pendown_state = tsc2007_get_pendown_state,
-};
-
-static struct i2c_board_info mbimx51_i2c_devices[] = {
- {
- I2C_BOARD_INFO("tsc2007", 0x49),
- .irq = IMX_GPIO_TO_IRQ(MBIMX51_TSC2007_GPIO),
- .platform_data = &tsc2007_data,
- }, {
- I2C_BOARD_INFO("tlv320aic23", 0x1a),
- },
-};
-
-/*
- * baseboard initialization.
- */
-void __init eukrea_mbimx51_baseboard_init(void)
-{
- mxc_iomux_v3_setup_multiple_pads(mbimx51_pads,
- ARRAY_SIZE(mbimx51_pads));
-
- imx51_add_imx_uart(1, NULL);
- imx51_add_imx_uart(2, &uart_pdata);
-
- gpio_request(MBIMX51_LED0, "LED0");
- gpio_direction_output(MBIMX51_LED0, 1);
- gpio_free(MBIMX51_LED0);
- gpio_request(MBIMX51_LED1, "LED1");
- gpio_direction_output(MBIMX51_LED1, 1);
- gpio_free(MBIMX51_LED1);
- gpio_request(MBIMX51_LED2, "LED2");
- gpio_direction_output(MBIMX51_LED2, 1);
- gpio_free(MBIMX51_LED2);
- gpio_request(MBIMX51_LED3, "LED3");
- gpio_direction_output(MBIMX51_LED3, 1);
- gpio_free(MBIMX51_LED3);
-
- gpio_led_register_device(-1, &mbimx51_leds_info);
-
- imx51_add_imx_keypad(&mbimx51_map_data);
-
- gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq");
- gpio_direction_input(MBIMX51_TSC2007_GPIO);
- irq_set_irq_type(gpio_to_irq(MBIMX51_TSC2007_GPIO),
- IRQF_TRIGGER_FALLING);
- i2c_register_board_info(1, mbimx51_i2c_devices,
- ARRAY_SIZE(mbimx51_i2c_devices));
-
- imx51_add_sdhci_esdhc_imx(0, NULL);
- imx51_add_sdhci_esdhc_imx(1, NULL);
-}
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
index 2cf603e11c4f..dfd2da87c2df 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
@@ -23,6 +23,7 @@
#include <linux/leds.h>
#include <linux/platform_device.h>
#include <linux/input.h>
+#include <linux/spi/spi.h>
#include <video/platform_lcd.h>
#include <mach/hardware.h>
@@ -87,12 +88,22 @@ static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
/* CAN */
MX25_PAD_GPIO_D__CAN2_RX,
MX25_PAD_GPIO_C__CAN2_TX,
+ /* SPI1 */
+ MX25_PAD_CSPI1_MOSI__CSPI1_MOSI,
+ MX25_PAD_CSPI1_MISO__CSPI1_MISO,
+ MX25_PAD_CSPI1_SS0__GPIO_1_16,
+ MX25_PAD_CSPI1_SS1__GPIO_1_17,
+ MX25_PAD_CSPI1_SCLK__CSPI1_SCLK,
+ MX25_PAD_CSPI1_RDY__GPIO_2_22,
};
-#define GPIO_LED1 83
-#define GPIO_SWITCH1 82
-#define GPIO_SD1CD 52
-#define GPIO_LCDPWR 26
+#define GPIO_LED1 IMX_GPIO_NR(3, 19)
+#define GPIO_SWITCH1 IMX_GPIO_NR(3, 18)
+#define GPIO_SD1CD IMX_GPIO_NR(2, 20)
+#define GPIO_LCDPWR IMX_GPIO_NR(1, 26)
+#define GPIO_SPI1_SS0 IMX_GPIO_NR(1, 16)
+#define GPIO_SPI1_SS1 IMX_GPIO_NR(1, 17)
+#define GPIO_SPI1_IRQ IMX_GPIO_NR(2, 22)
static struct imx_fb_videomode eukrea_mximxsd_modes[] = {
{
@@ -228,6 +239,30 @@ static struct esdhc_platform_data sd1_pdata = {
.wp_type = ESDHC_WP_NONE,
};
+static struct spi_board_info eukrea_mbimxsd25_spi_board_info[] __initdata = {
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .mode = SPI_MODE_0,
+ },
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .mode = SPI_MODE_0,
+ },
+};
+
+static int eukrea_mbimxsd25_spi_cs[] = {GPIO_SPI1_SS0, GPIO_SPI1_SS1};
+
+static const struct spi_imx_master eukrea_mbimxsd25_spi0_data __initconst = {
+ .chipselect = eukrea_mbimxsd25_spi_cs,
+ .num_chipselect = ARRAY_SIZE(eukrea_mbimxsd25_spi_cs),
+};
+
/*
* system init for baseboard usage. Will be called by cpuimx25 init.
*
@@ -257,11 +292,17 @@ void __init eukrea_mbimxsd25_baseboard_init(void)
gpio_request(GPIO_LCDPWR, "LCDPWR");
gpio_direction_output(GPIO_LCDPWR, 1);
- gpio_free(GPIO_SWITCH1);
i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
+ gpio_request(GPIO_SPI1_IRQ, "SPI1_IRQ");
+ gpio_direction_input(GPIO_SPI1_IRQ);
+ gpio_free(GPIO_SPI1_IRQ);
+ imx25_add_spi_imx0(&eukrea_mbimxsd25_spi0_data);
+ spi_register_board_info(eukrea_mbimxsd25_spi_board_info,
+ ARRAY_SIZE(eukrea_mbimxsd25_spi_board_info));
+
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
index fd8bf8a425a7..557f6c486053 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
@@ -27,6 +27,7 @@
#include <linux/leds.h>
#include <linux/platform_device.h>
#include <linux/input.h>
+#include <linux/spi/spi.h>
#include <video/platform_lcd.h>
#include <linux/i2c.h>
@@ -158,12 +159,22 @@ static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
/* SD1 CD */
MX35_PAD_LD18__GPIO3_24,
+ /* SPI */
+ MX35_PAD_CSPI1_MOSI__CSPI1_MOSI,
+ MX35_PAD_CSPI1_MISO__CSPI1_MISO,
+ MX35_PAD_CSPI1_SS0__GPIO1_18,
+ MX35_PAD_CSPI1_SS1__GPIO1_19,
+ MX35_PAD_CSPI1_SCLK__CSPI1_SCLK,
+ MX35_PAD_CSPI1_SPI_RDY__GPIO3_5,
};
#define GPIO_LED1 IMX_GPIO_NR(3, 29)
#define GPIO_SWITCH1 IMX_GPIO_NR(3, 25)
#define GPIO_LCDPWR IMX_GPIO_NR(1, 4)
#define GPIO_SD1CD IMX_GPIO_NR(3, 24)
+#define GPIO_SPI1_SS0 IMX_GPIO_NR(1, 18)
+#define GPIO_SPI1_SS1 IMX_GPIO_NR(1, 19)
+#define GPIO_SPI1_IRQ IMX_GPIO_NR(3, 5)
static void eukrea_mbimxsd_lcd_power_set(struct plat_lcd_data *pd,
unsigned int power)
@@ -239,6 +250,30 @@ static struct esdhc_platform_data sd1_pdata = {
.wp_type = ESDHC_WP_NONE,
};
+static struct spi_board_info eukrea_mbimxsd35_spi_board_info[] __initdata = {
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .mode = SPI_MODE_0,
+ },
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .mode = SPI_MODE_0,
+ },
+};
+
+static int eukrea_mbimxsd35_spi_cs[] = {GPIO_SPI1_SS0, GPIO_SPI1_SS1};
+
+static const struct spi_imx_master eukrea_mbimxsd35_spi0_data __initconst = {
+ .chipselect = eukrea_mbimxsd35_spi_cs,
+ .num_chipselect = ARRAY_SIZE(eukrea_mbimxsd35_spi_cs),
+};
+
/*
* system init for baseboard usage. Will be called by cpuimx35 init.
*
@@ -274,6 +309,13 @@ void __init eukrea_mbimxsd35_baseboard_init(void)
i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
+ gpio_request(GPIO_SPI1_IRQ, "SPI1_IRQ");
+ gpio_direction_input(GPIO_SPI1_IRQ);
+ gpio_free(GPIO_SPI1_IRQ);
+ imx35_add_spi_imx0(&eukrea_mbimxsd35_spi0_data);
+ spi_register_board_info(eukrea_mbimxsd35_spi_board_info,
+ ARRAY_SIZE(eukrea_mbimxsd35_spi_board_info));
+
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c
index aaa592fdb9ce..96a24b73dc23 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c
@@ -28,6 +28,8 @@
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/i2c.h>
+#include <video/platform_lcd.h>
+#include <linux/backlight.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -40,7 +42,7 @@
#include "devices-imx51.h"
-static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
+static iomux_v3_cfg_t eukrea_mbimxsd51_pads[] = {
/* LED */
MX51_PAD_NANDF_D10__GPIO3_30,
/* SWITCH */
@@ -66,12 +68,64 @@ static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP |
PAD_CTL_PKE | PAD_CTL_SRE_FAST |
PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
+ /* SSI */
+ MX51_PAD_AUD3_BB_TXD__AUD3_TXD,
+ MX51_PAD_AUD3_BB_RXD__AUD3_RXD,
+ MX51_PAD_AUD3_BB_CK__AUD3_TXC,
+ MX51_PAD_AUD3_BB_FS__AUD3_TXFS,
+ /* LCD Backlight */
+ MX51_PAD_DI1_D1_CS__GPIO3_4,
+ /* LCD RST */
+ MX51_PAD_CSI1_D9__GPIO3_13,
};
#define GPIO_LED1 IMX_GPIO_NR(3, 30)
#define GPIO_SWITCH1 IMX_GPIO_NR(3, 31)
+#define GPIO_LCDRST IMX_GPIO_NR(3, 13)
+#define GPIO_LCDBL IMX_GPIO_NR(3, 4)
-static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = {
+static void eukrea_mbimxsd51_lcd_power_set(struct plat_lcd_data *pd,
+ unsigned int power)
+{
+ if (power)
+ gpio_direction_output(GPIO_LCDRST, 1);
+ else
+ gpio_direction_output(GPIO_LCDRST, 0);
+}
+
+static struct plat_lcd_data eukrea_mbimxsd51_lcd_power_data = {
+ .set_power = eukrea_mbimxsd51_lcd_power_set,
+};
+
+static struct platform_device eukrea_mbimxsd51_lcd_powerdev = {
+ .name = "platform-lcd",
+ .dev.platform_data = &eukrea_mbimxsd51_lcd_power_data,
+};
+
+static void eukrea_mbimxsd51_bl_set_intensity(int intensity)
+{
+ if (intensity)
+ gpio_direction_output(GPIO_LCDBL, 1);
+ else
+ gpio_direction_output(GPIO_LCDBL, 0);
+}
+
+static struct generic_bl_info eukrea_mbimxsd51_bl_info = {
+ .name = "eukrea_mbimxsd51-bl",
+ .max_intensity = 0xff,
+ .default_intensity = 0xff,
+ .set_bl_intensity = eukrea_mbimxsd51_bl_set_intensity,
+};
+
+static struct platform_device eukrea_mbimxsd51_bl_dev = {
+ .name = "generic-bl",
+ .id = 1,
+ .dev = {
+ .platform_data = &eukrea_mbimxsd51_bl_info,
+ },
+};
+
+static const struct gpio_led eukrea_mbimxsd51_leds[] __initconst = {
{
.name = "led1",
.default_trigger = "heartbeat",
@@ -81,12 +135,12 @@ static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = {
};
static const struct gpio_led_platform_data
- eukrea_mbimxsd_led_info __initconst = {
- .leds = eukrea_mbimxsd_leds,
- .num_leds = ARRAY_SIZE(eukrea_mbimxsd_leds),
+ eukrea_mbimxsd51_led_info __initconst = {
+ .leds = eukrea_mbimxsd51_leds,
+ .num_leds = ARRAY_SIZE(eukrea_mbimxsd51_leds),
};
-static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
+static struct gpio_keys_button eukrea_mbimxsd51_gpio_buttons[] = {
{
.gpio = GPIO_SWITCH1,
.code = BTN_0,
@@ -97,21 +151,39 @@ static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
};
static const struct gpio_keys_platform_data
- eukrea_mbimxsd_button_data __initconst = {
- .buttons = eukrea_mbimxsd_gpio_buttons,
- .nbuttons = ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
+ eukrea_mbimxsd51_button_data __initconst = {
+ .buttons = eukrea_mbimxsd51_gpio_buttons,
+ .nbuttons = ARRAY_SIZE(eukrea_mbimxsd51_gpio_buttons),
};
static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
-static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
+static struct i2c_board_info eukrea_mbimxsd51_i2c_devices[] = {
{
I2C_BOARD_INFO("tlv320aic23", 0x1a),
},
};
+static const
+struct imx_ssi_platform_data eukrea_mbimxsd51_ssi_pdata __initconst = {
+ .flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE,
+};
+
+static int screen_type;
+
+static int __init eukrea_mbimxsd51_screen_type(char *options)
+{
+ if (!strcmp(options, "dvi"))
+ screen_type = 1;
+ else if (!strcmp(options, "tft"))
+ screen_type = 0;
+
+ return 0;
+}
+__setup("screen_type=", eukrea_mbimxsd51_screen_type);
+
/*
* system init for baseboard usage. Will be called by cpuimx51sd init.
*
@@ -120,8 +192,8 @@ static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
*/
void __init eukrea_mbimxsd51_baseboard_init(void)
{
- if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
- ARRAY_SIZE(eukrea_mbimxsd_pads)))
+ if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd51_pads,
+ ARRAY_SIZE(eukrea_mbimxsd51_pads)))
printk(KERN_ERR "error setting mbimxsd pads !\n");
imx51_add_imx_uart(1, NULL);
@@ -129,6 +201,8 @@ void __init eukrea_mbimxsd51_baseboard_init(void)
imx51_add_sdhci_esdhc_imx(0, NULL);
+ imx51_add_imx_ssi(0, &eukrea_mbimxsd51_ssi_pdata);
+
gpio_request(GPIO_LED1, "LED1");
gpio_direction_output(GPIO_LED1, 1);
gpio_free(GPIO_LED1);
@@ -137,9 +211,21 @@ void __init eukrea_mbimxsd51_baseboard_init(void)
gpio_direction_input(GPIO_SWITCH1);
gpio_free(GPIO_SWITCH1);
- i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
- ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
-
- gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
- imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
+ gpio_request(GPIO_LCDRST, "LCDRST");
+ gpio_direction_output(GPIO_LCDRST, 0);
+ gpio_request(GPIO_LCDBL, "LCDBL");
+ gpio_direction_output(GPIO_LCDBL, 0);
+ if (!screen_type) {
+ platform_device_register(&eukrea_mbimxsd51_bl_dev);
+ platform_device_register(&eukrea_mbimxsd51_lcd_powerdev);
+ } else {
+ gpio_free(GPIO_LCDRST);
+ gpio_free(GPIO_LCDBL);
+ }
+
+ i2c_register_board_info(0, eukrea_mbimxsd51_i2c_devices,
+ ARRAY_SIZE(eukrea_mbimxsd51_i2c_devices));
+
+ gpio_led_register_device(-1, &eukrea_mbimxsd51_led_info);
+ imx_add_gpio_keys(&eukrea_mbimxsd51_button_data);
}
diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c
index 5cca573964f0..5f577fbda2c8 100644
--- a/arch/arm/mach-imx/imx51-dt.c
+++ b/arch/arm/mach-imx/imx51-dt.c
@@ -14,6 +14,7 @@
#include <linux/irqdomain.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/pinctrl/machine.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <mach/common.h>
@@ -81,6 +82,8 @@ static void __init imx51_dt_init(void)
of_irq_init(imx51_irq_match);
+ pinctrl_provide_dummies();
+
node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
if (node) {
of_id = of_match_node(imx51_iomuxc_of_match, node);
diff --git a/arch/arm/mach-imx/imx53-dt.c b/arch/arm/mach-imx/imx53-dt.c
index 4172279b3900..574eca4b89a5 100644
--- a/arch/arm/mach-imx/imx53-dt.c
+++ b/arch/arm/mach-imx/imx53-dt.c
@@ -15,6 +15,7 @@
#include <linux/irqdomain.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/pinctrl/machine.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <mach/common.h>
@@ -88,6 +89,8 @@ static void __init imx53_dt_init(void)
of_irq_init(imx53_irq_match);
+ pinctrl_provide_dummies();
+
node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
if (node) {
of_id = of_match_node(imx53_iomuxc_of_match, node);
diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c
index 8ecc872b2547..c515f8ede1a1 100644
--- a/arch/arm/mach-imx/mach-cpuimx35.c
+++ b/arch/arm/mach-imx/mach-cpuimx35.c
@@ -194,7 +194,7 @@ static void __init eukrea_cpuimx35_timer_init(void)
mx35_clocks_init();
}
-struct sys_timer eukrea_cpuimx35_timer = {
+static struct sys_timer eukrea_cpuimx35_timer = {
.init = eukrea_cpuimx35_timer_init,
};
diff --git a/arch/arm/mach-imx/mach-cpuimx51.c b/arch/arm/mach-imx/mach-cpuimx51.c
deleted file mode 100644
index 944025da8333..000000000000
--- a/arch/arm/mach-imx/mach-cpuimx51.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- *
- * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
- *
- * based on board-mx51_babbage.c which is
- * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-
-#include <mach/eukrea-baseboards.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-
-#define CPUIMX51_USBH1_STP IMX_GPIO_NR(1, 27)
-#define CPUIMX51_QUARTA_GPIO IMX_GPIO_NR(3, 28)
-#define CPUIMX51_QUARTB_GPIO IMX_GPIO_NR(3, 25)
-#define CPUIMX51_QUARTC_GPIO IMX_GPIO_NR(3, 26)
-#define CPUIMX51_QUARTD_GPIO IMX_GPIO_NR(3, 27)
-#define CPUIMX51_QUART_XTAL 14745600
-#define CPUIMX51_QUART_REGSHIFT 17
-
-/* USB_CTRL_1 */
-#define MX51_USB_CTRL_1_OFFSET 0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
-
-#define MX51_USB_PLLDIV_12_MHZ 0x00
-#define MX51_USB_PLL_DIV_19_2_MHZ 0x01
-#define MX51_USB_PLL_DIV_24_MHZ 0x02
-
-static struct plat_serial8250_port serial_platform_data[] = {
- {
- .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
- .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTA_GPIO),
- .irqflags = IRQF_TRIGGER_HIGH,
- .uartclk = CPUIMX51_QUART_XTAL,
- .regshift = CPUIMX51_QUART_REGSHIFT,
- .iotype = UPIO_MEM,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
- }, {
- .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000),
- .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTB_GPIO),
- .irqflags = IRQF_TRIGGER_HIGH,
- .uartclk = CPUIMX51_QUART_XTAL,
- .regshift = CPUIMX51_QUART_REGSHIFT,
- .iotype = UPIO_MEM,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
- }, {
- .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000),
- .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTC_GPIO),
- .irqflags = IRQF_TRIGGER_HIGH,
- .uartclk = CPUIMX51_QUART_XTAL,
- .regshift = CPUIMX51_QUART_REGSHIFT,
- .iotype = UPIO_MEM,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
- }, {
- .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000),
- .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTD_GPIO),
- .irqflags = IRQF_TRIGGER_HIGH,
- .uartclk = CPUIMX51_QUART_XTAL,
- .regshift = CPUIMX51_QUART_REGSHIFT,
- .iotype = UPIO_MEM,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
- }, {
- }
-};
-
-static struct platform_device serial_device = {
- .name = "serial8250",
- .id = 0,
- .dev = {
- .platform_data = serial_platform_data,
- },
-};
-
-static struct platform_device *devices[] __initdata = {
- &serial_device,
-};
-
-static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = {
- /* UART1 */
- MX51_PAD_UART1_RXD__UART1_RXD,
- MX51_PAD_UART1_TXD__UART1_TXD,
- MX51_PAD_UART1_RTS__UART1_RTS,
- MX51_PAD_UART1_CTS__UART1_CTS,
-
- /* I2C2 */
- MX51_PAD_GPIO1_2__I2C2_SCL,
- MX51_PAD_GPIO1_3__I2C2_SDA,
- MX51_PAD_NANDF_D10__GPIO3_30,
-
- /* QUART IRQ */
- MX51_PAD_NANDF_D15__GPIO3_25,
- MX51_PAD_NANDF_D14__GPIO3_26,
- MX51_PAD_NANDF_D13__GPIO3_27,
- MX51_PAD_NANDF_D12__GPIO3_28,
-
- /* USB HOST1 */
- MX51_PAD_USBH1_CLK__USBH1_CLK,
- MX51_PAD_USBH1_DIR__USBH1_DIR,
- MX51_PAD_USBH1_NXT__USBH1_NXT,
- MX51_PAD_USBH1_DATA0__USBH1_DATA0,
- MX51_PAD_USBH1_DATA1__USBH1_DATA1,
- MX51_PAD_USBH1_DATA2__USBH1_DATA2,
- MX51_PAD_USBH1_DATA3__USBH1_DATA3,
- MX51_PAD_USBH1_DATA4__USBH1_DATA4,
- MX51_PAD_USBH1_DATA5__USBH1_DATA5,
- MX51_PAD_USBH1_DATA6__USBH1_DATA6,
- MX51_PAD_USBH1_DATA7__USBH1_DATA7,
- MX51_PAD_USBH1_STP__USBH1_STP,
-};
-
-static const struct mxc_nand_platform_data
- eukrea_cpuimx51_nand_board_info __initconst = {
- .width = 1,
- .hw_ecc = 1,
- .flash_bbt = 1,
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
- .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const
-struct imxi2c_platform_data eukrea_cpuimx51_i2c_data __initconst = {
- .bitrate = 100000,
-};
-
-static struct i2c_board_info eukrea_cpuimx51_i2c_devices[] = {
- {
- I2C_BOARD_INFO("pcf8563", 0x51),
- },
-};
-
-/* This function is board specific as the bit mask for the plldiv will also
-be different for other Freescale SoCs, thus a common bitmask is not
-possible and cannot get place in /plat-mxc/ehci.c.*/
-static int initialize_otg_port(struct platform_device *pdev)
-{
- u32 v;
- void __iomem *usb_base;
- void __iomem *usbother_base;
-
- usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
- if (!usb_base)
- return -ENOMEM;
- usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
- /* Set the PHY clock to 19.2MHz */
- v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
- v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
- v |= MX51_USB_PLL_DIV_19_2_MHZ;
- __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
- iounmap(usb_base);
-
- mdelay(10);
-
- return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
-}
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
- u32 v;
- void __iomem *usb_base;
- void __iomem *usbother_base;
-
- usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
- if (!usb_base)
- return -ENOMEM;
- usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
- /* The clock for the USBH1 ULPI port will come externally from the PHY. */
- v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
- __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
- iounmap(usb_base);
-
- mdelay(10);
-
- return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
- MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
- .init = initialize_otg_port,
- .portsc = MXC_EHCI_UTMI_16BIT,
-};
-
-static const struct fsl_usb2_platform_data usb_pdata __initconst = {
- .operating_mode = FSL_USB2_DR_DEVICE,
- .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
-};
-
-static const struct mxc_usbh_platform_data usbh1_config __initconst = {
- .init = initialize_usbh1_port,
- .portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static int otg_mode_host;
-
-static int __init eukrea_cpuimx51_otg_mode(char *options)
-{
- if (!strcmp(options, "host"))
- otg_mode_host = 1;
- else if (!strcmp(options, "device"))
- otg_mode_host = 0;
- else
- pr_info("otg_mode neither \"host\" nor \"device\". "
- "Defaulting to device\n");
- return 0;
-}
-__setup("otg_mode=", eukrea_cpuimx51_otg_mode);
-
-/*
- * Board specific initialization.
- */
-static void __init eukrea_cpuimx51_init(void)
-{
- imx51_soc_init();
-
- mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,
- ARRAY_SIZE(eukrea_cpuimx51_pads));
-
- imx51_add_imx_uart(0, &uart_pdata);
- imx51_add_mxc_nand(&eukrea_cpuimx51_nand_board_info);
-
- gpio_request(CPUIMX51_QUARTA_GPIO, "quarta_irq");
- gpio_direction_input(CPUIMX51_QUARTA_GPIO);
- gpio_free(CPUIMX51_QUARTA_GPIO);
- gpio_request(CPUIMX51_QUARTB_GPIO, "quartb_irq");
- gpio_direction_input(CPUIMX51_QUARTB_GPIO);
- gpio_free(CPUIMX51_QUARTB_GPIO);
- gpio_request(CPUIMX51_QUARTC_GPIO, "quartc_irq");
- gpio_direction_input(CPUIMX51_QUARTC_GPIO);
- gpio_free(CPUIMX51_QUARTC_GPIO);
- gpio_request(CPUIMX51_QUARTD_GPIO, "quartd_irq");
- gpio_direction_input(CPUIMX51_QUARTD_GPIO);
- gpio_free(CPUIMX51_QUARTD_GPIO);
-
- imx51_add_fec(NULL);
- platform_add_devices(devices, ARRAY_SIZE(devices));
-
- imx51_add_imx_i2c(1, &eukrea_cpuimx51_i2c_data);
- i2c_register_board_info(1, eukrea_cpuimx51_i2c_devices,
- ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
-
- if (otg_mode_host)
- imx51_add_mxc_ehci_otg(&dr_utmi_config);
- else {
- initialize_otg_port(NULL);
- imx51_add_fsl_usb2_udc(&usb_pdata);
- }
- imx51_add_mxc_ehci_hs(1, &usbh1_config);
-
-#ifdef CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD
- eukrea_mbimx51_baseboard_init();
-#endif
-}
-
-static void __init eukrea_cpuimx51_timer_init(void)
-{
- mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mxc_timer = {
- .init = eukrea_cpuimx51_timer_init,
-};
-
-MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
- /* Maintainer: Eric Bénard <eric@eukrea.com> */
- .atag_offset = 0x100,
- .map_io = mx51_map_io,
- .init_early = imx51_init_early,
- .init_irq = mx51_init_irq,
- .handle_irq = imx51_handle_irq,
- .timer = &mxc_timer,
- .init_machine = eukrea_cpuimx51_init,
- .restart = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c
index 9fbe923c8b08..ce341a6874fc 100644
--- a/arch/arm/mach-imx/mach-cpuimx51sd.c
+++ b/arch/arm/mach-imx/mach-cpuimx51sd.c
@@ -41,11 +41,13 @@
#define USBH1_RST IMX_GPIO_NR(2, 28)
#define ETH_RST IMX_GPIO_NR(2, 31)
-#define TSC2007_IRQGPIO IMX_GPIO_NR(3, 12)
+#define TSC2007_IRQGPIO_REV2 IMX_GPIO_NR(3, 12)
+#define TSC2007_IRQGPIO_REV3 IMX_GPIO_NR(4, 0)
#define CAN_IRQGPIO IMX_GPIO_NR(1, 1)
#define CAN_RST IMX_GPIO_NR(4, 15)
#define CAN_NCS IMX_GPIO_NR(4, 24)
-#define CAN_RXOBF IMX_GPIO_NR(1, 4)
+#define CAN_RXOBF_REV2 IMX_GPIO_NR(1, 4)
+#define CAN_RXOBF_REV3 IMX_GPIO_NR(3, 12)
#define CAN_RX1BF IMX_GPIO_NR(1, 6)
#define CAN_TXORTS IMX_GPIO_NR(1, 7)
#define CAN_TX1RTS IMX_GPIO_NR(1, 8)
@@ -90,6 +92,10 @@ static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = {
MX51_PAD_I2C1_CLK__GPIO4_16,
MX51_PAD_I2C1_DAT__GPIO4_17,
+ /* I2C1 */
+ MX51_PAD_SD2_CMD__I2C1_SCL,
+ MX51_PAD_SD2_CLK__I2C1_SDA,
+
/* CAN */
MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
@@ -108,15 +114,27 @@ static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = {
NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP |
PAD_CTL_PKE | PAD_CTL_SRE_FAST |
PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
+ NEW_PAD_CTRL(MX51_PAD_NANDF_D8__GPIO4_0, PAD_CTL_PUS_22K_UP |
+ PAD_CTL_PKE | PAD_CTL_SRE_FAST |
+ PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
};
static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
+static int tsc2007_get_pendown_state(void)
+{
+ if (mx51_revision() < IMX_CHIP_REVISION_3_0)
+ return !gpio_get_value(TSC2007_IRQGPIO_REV2);
+ else
+ return !gpio_get_value(TSC2007_IRQGPIO_REV3);
+}
+
static struct tsc2007_platform_data tsc2007_info = {
.model = 2007,
.x_plate_ohms = 180,
+ .get_pendown_state = tsc2007_get_pendown_state,
};
static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
@@ -126,7 +144,6 @@ static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
I2C_BOARD_INFO("tsc2007", 0x49),
.type = "tsc2007",
.platform_data = &tsc2007_info,
- .irq = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
},
};
@@ -255,10 +272,14 @@ static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = {
.num_chipselect = ARRAY_SIZE(cpuimx51sd_spi1_cs),
};
-static struct platform_device *platform_devices[] __initdata = {
+static struct platform_device *rev2_platform_devices[] __initdata = {
&hsi2c_gpio_device,
};
+static const struct imxi2c_platform_data cpuimx51sd_i2c_data __initconst = {
+ .bitrate = 100000,
+};
+
static void __init eukrea_cpuimx51sd_init(void)
{
imx51_soc_init();
@@ -272,6 +293,7 @@ static void __init eukrea_cpuimx51sd_init(void)
imx51_add_imx_uart(0, &uart_pdata);
imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
+ imx51_add_imx2_wdt(0, NULL);
gpio_request(ETH_RST, "eth_rst");
gpio_set_value(ETH_RST, 1);
@@ -291,13 +313,25 @@ static void __init eukrea_cpuimx51sd_init(void)
spi_register_board_info(cpuimx51sd_spi_device,
ARRAY_SIZE(cpuimx51sd_spi_device));
- gpio_request(TSC2007_IRQGPIO, "tsc2007_irq");
- gpio_direction_input(TSC2007_IRQGPIO);
- gpio_free(TSC2007_IRQGPIO);
+ if (mx51_revision() < IMX_CHIP_REVISION_3_0) {
+ eukrea_cpuimx51sd_i2c_devices[1].irq =
+ gpio_to_irq(TSC2007_IRQGPIO_REV2),
+ platform_add_devices(rev2_platform_devices,
+ ARRAY_SIZE(rev2_platform_devices));
+ gpio_request(TSC2007_IRQGPIO_REV2, "tsc2007_irq");
+ gpio_direction_input(TSC2007_IRQGPIO_REV2);
+ gpio_free(TSC2007_IRQGPIO_REV2);
+ } else {
+ eukrea_cpuimx51sd_i2c_devices[1].irq =
+ gpio_to_irq(TSC2007_IRQGPIO_REV3),
+ imx51_add_imx_i2c(0, &cpuimx51sd_i2c_data);
+ gpio_request(TSC2007_IRQGPIO_REV3, "tsc2007_irq");
+ gpio_direction_input(TSC2007_IRQGPIO_REV3);
+ gpio_free(TSC2007_IRQGPIO_REV3);
+ }
i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices,
ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices));
- platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
if (otg_mode_host)
imx51_add_mxc_ehci_otg(&dr_utmi_config);
diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
index 76a97a598b9e..d1e04e676e33 100644
--- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
+++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
@@ -106,6 +106,7 @@ static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
.operating_mode = FSL_USB2_DR_DEVICE,
.phy_mode = FSL_USB2_PHY_UTMI,
+ .workaround = FLS_USB2_WORKAROUND_ENGCM09152,
};
static int otg_mode_host;
@@ -135,6 +136,7 @@ static void __init eukrea_cpuimx25_init(void)
imx25_add_mxc_nand(&eukrea_cpuimx25_nand_board_info);
imx25_add_imxdi_rtc(NULL);
imx25_add_fec(&mx25_fec_pdata);
+ imx25_add_imx2_wdt(NULL);
i2c_register_board_info(0, eukrea_cpuimx25_i2c_devices,
ARRAY_SIZE(eukrea_cpuimx25_i2c_devices));
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
index f7b074f496f0..748ba2e311b5 100644
--- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -38,6 +38,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
+#include <asm/system.h>
#include <mach/common.h>
#include <mach/iomux-mx27.h>
@@ -48,6 +49,14 @@
#define OTG_PHY_CS_GPIO (GPIO_PORTF + 17)
#define SDHC1_IRQ IRQ_GPIOB(25)
+#define MOTHERBOARD_BIT2 (GPIO_PORTD + 31)
+#define MOTHERBOARD_BIT1 (GPIO_PORTD + 30)
+#define MOTHERBOARD_BIT0 (GPIO_PORTD + 29)
+
+#define EXPBOARD_BIT2 (GPIO_PORTD + 25)
+#define EXPBOARD_BIT1 (GPIO_PORTD + 27)
+#define EXPBOARD_BIT0 (GPIO_PORTD + 28)
+
static const int visstrim_m10_pins[] __initconst = {
/* UART1 (console) */
PE12_PF_UART1_TXD,
@@ -119,6 +128,23 @@ static const int visstrim_m10_pins[] __initconst = {
PB19_PF_CSI_D7,
PB20_PF_CSI_VSYNC,
PB21_PF_CSI_HSYNC,
+ /* mother board version */
+ MOTHERBOARD_BIT2 | GPIO_GPIO | GPIO_IN | GPIO_PUEN,
+ MOTHERBOARD_BIT1 | GPIO_GPIO | GPIO_IN | GPIO_PUEN,
+ MOTHERBOARD_BIT0 | GPIO_GPIO | GPIO_IN | GPIO_PUEN,
+ /* expansion board version */
+ EXPBOARD_BIT2 | GPIO_GPIO | GPIO_IN | GPIO_PUEN,
+ EXPBOARD_BIT1 | GPIO_GPIO | GPIO_IN | GPIO_PUEN,
+ EXPBOARD_BIT0 | GPIO_GPIO | GPIO_IN | GPIO_PUEN,
+};
+
+static struct gpio visstrim_m10_version_gpios[] = {
+ { EXPBOARD_BIT0, GPIOF_IN, "exp-version-0" },
+ { EXPBOARD_BIT1, GPIOF_IN, "exp-version-1" },
+ { EXPBOARD_BIT2, GPIOF_IN, "exp-version-2" },
+ { MOTHERBOARD_BIT0, GPIOF_IN, "mother-version-0" },
+ { MOTHERBOARD_BIT1, GPIOF_IN, "mother-version-1" },
+ { MOTHERBOARD_BIT2, GPIOF_IN, "mother-version-2" },
};
/* Camera */
@@ -369,11 +395,40 @@ static const struct imx_ssi_platform_data visstrim_m10_ssi_pdata __initconst = {
.flags = IMX_SSI_DMA | IMX_SSI_SYN,
};
+static void __init visstrim_m10_revision(void)
+{
+ int exp_version = 0;
+ int mo_version = 0;
+ int ret;
+
+ ret = gpio_request_array(visstrim_m10_version_gpios,
+ ARRAY_SIZE(visstrim_m10_version_gpios));
+ if (ret) {
+ pr_err("Failed to request version gpios");
+ return;
+ }
+
+ /* Get expansion board version (negative logic) */
+ exp_version |= !gpio_get_value(EXPBOARD_BIT2) << 2;
+ exp_version |= !gpio_get_value(EXPBOARD_BIT1) << 1;
+ exp_version |= !gpio_get_value(EXPBOARD_BIT0);
+
+ /* Get mother board version (negative logic) */
+ mo_version |= !gpio_get_value(MOTHERBOARD_BIT2) << 2;
+ mo_version |= !gpio_get_value(MOTHERBOARD_BIT1) << 1;
+ mo_version |= !gpio_get_value(MOTHERBOARD_BIT0);
+
+ system_rev = 0x27000;
+ system_rev |= (mo_version << 4);
+ system_rev |= exp_version;
+}
+
static void __init visstrim_m10_board_init(void)
{
int ret;
imx27_soc_init();
+ visstrim_m10_revision();
ret = mxc_gpio_setup_multiple_pins(visstrim_m10_pins,
ARRAY_SIZE(visstrim_m10_pins), "VISSTRIM_M10");
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index da6c1d9af768..3df360a52c17 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -19,6 +19,7 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/pinctrl/machine.h>
#include <linux/phy.h>
#include <linux/micrel_phy.h>
#include <asm/smp_twd.h>
@@ -77,6 +78,12 @@ static int ksz9021rn_phy_fixup(struct phy_device *phydev)
static void __init imx6q_init_machine(void)
{
+ /*
+ * This should be removed when all imx6q boards have pinctrl
+ * states for devices defined in device tree.
+ */
+ pinctrl_provide_dummies();
+
if (of_machine_is_compatible("fsl,imx6q-sabrelite"))
phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
ksz9021rn_phy_fixup);
diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c
index 97046088ff1a..7274e7928136 100644
--- a/arch/arm/mach-imx/mach-mx1ads.c
+++ b/arch/arm/mach-imx/mach-mx1ads.c
@@ -134,7 +134,7 @@ static void __init mx1ads_timer_init(void)
mx1_clocks_init(32000);
}
-struct sys_timer mx1ads_timer = {
+static struct sys_timer mx1ads_timer = {
.init = mx1ads_timer_init,
};
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index e432d4acee1f..d14bbe949a4f 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -304,8 +304,7 @@ static void __init mx21ads_board_init(void)
imx21_add_mxc_nand(&mx21ads_nand_board_info);
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
- platform_device_register_full(
- (struct platform_device_info *)&mx21ads_cs8900_devinfo);
+ platform_device_register_full(&mx21ads_cs8900_devinfo);
}
static void __init mx21ads_timer_init(void)
diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c
index 4d1aab154400..4eafdf275ea2 100644
--- a/arch/arm/mach-imx/mach-mx31_3ds.c
+++ b/arch/arm/mach-imx/mach-mx31_3ds.c
@@ -156,6 +156,11 @@ static int mx31_3ds_pins[] = {
MX31_PIN_CSI_VSYNC__CSI_VSYNC,
MX31_PIN_CSI_D5__GPIO3_5, /* CMOS PWDN */
IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_GPIO), /* CMOS reset */
+ /* SSI */
+ MX31_PIN_STXD4__STXD4,
+ MX31_PIN_SRXD4__SRXD4,
+ MX31_PIN_SCK4__SCK4,
+ MX31_PIN_SFS4__SFS4,
};
/*
@@ -488,12 +493,23 @@ static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = {
};
/* MC13783 */
+static struct mc13xxx_codec_platform_data mx31_3ds_codec = {
+ .dac_ssi_port = MC13783_SSI1_PORT,
+ .adc_ssi_port = MC13783_SSI1_PORT,
+};
+
static struct mc13xxx_platform_data mc13783_pdata = {
.regulators = {
.regulators = mx31_3ds_regulators,
.num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
},
- .flags = MC13XXX_USE_TOUCHSCREEN | MC13XXX_USE_RTC,
+ .codec = &mx31_3ds_codec,
+ .flags = MC13XXX_USE_TOUCHSCREEN | MC13XXX_USE_RTC | MC13XXX_USE_CODEC,
+
+};
+
+static struct imx_ssi_platform_data mx31_3ds_ssi_pdata = {
+ .flags = IMX_SSI_DMA | IMX_SSI_NET,
};
/* SPI */
@@ -741,6 +757,10 @@ static void __init mx31_3ds_init(void)
}
mx31_3ds_init_camera();
+
+ imx31_add_imx_ssi(0, &mx31_3ds_ssi_pdata);
+
+ imx_add_platform_device("imx_mc13783", 0, NULL, 0, NULL, 0);
}
static void __init mx31_3ds_timer_init(void)
diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c
index 0abef5f13df5..686c60587980 100644
--- a/arch/arm/mach-imx/mach-mx31lite.c
+++ b/arch/arm/mach-imx/mach-mx31lite.c
@@ -283,7 +283,7 @@ static void __init mx31lite_timer_init(void)
mx31_clocks_init(26000000);
}
-struct sys_timer mx31lite_timer = {
+static struct sys_timer mx31lite_timer = {
.init = mx31lite_timer_init,
};
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index f17a15f28316..016791f038b0 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -47,6 +47,7 @@
#include <mach/hardware.h>
#include <mach/iomux-mx3.h>
#include <mach/ulpi.h>
+#include <mach/ssi.h>
#include "devices-imx31.h"
@@ -102,6 +103,9 @@ static unsigned int moboard_pins[] = {
MX31_PIN_CSPI3_MOSI__MOSI, MX31_PIN_CSPI3_MISO__MISO,
MX31_PIN_CSPI3_SCLK__SCLK, MX31_PIN_CSPI3_SPI_RDY__SPI_RDY,
MX31_PIN_CSPI2_SS1__CSPI3_SS1,
+ /* SSI */
+ MX31_PIN_STXD4__STXD4, MX31_PIN_SRXD4__SRXD4,
+ MX31_PIN_SCK4__SCK4, MX31_PIN_SFS4__SFS4,
};
static struct physmap_flash_data mx31moboard_flash_data = {
@@ -276,6 +280,11 @@ static struct mc13xxx_buttons_platform_data moboard_buttons = {
.b1on_key = KEY_POWER,
};
+static struct mc13xxx_codec_platform_data moboard_codec = {
+ .dac_ssi_port = MC13783_SSI1_PORT,
+ .adc_ssi_port = MC13783_SSI1_PORT,
+};
+
static struct mc13xxx_platform_data moboard_pmic = {
.regulators = {
.regulators = moboard_regulators,
@@ -283,7 +292,12 @@ static struct mc13xxx_platform_data moboard_pmic = {
},
.leds = &moboard_leds,
.buttons = &moboard_buttons,
- .flags = MC13XXX_USE_RTC | MC13XXX_USE_ADC,
+ .codec = &moboard_codec,
+ .flags = MC13XXX_USE_RTC | MC13XXX_USE_ADC | MC13XXX_USE_CODEC,
+};
+
+static struct imx_ssi_platform_data moboard_ssi_pdata = {
+ .flags = IMX_SSI_DMA | IMX_SSI_NET,
};
static struct spi_board_info moboard_spi_board_info[] __initdata = {
@@ -554,6 +568,10 @@ static void __init mx31moboard_init(void)
moboard_usbh2_init();
+ imx31_add_imx_ssi(0, &moboard_ssi_pdata);
+
+ imx_add_platform_device("imx_mc13783", 0, NULL, 0, NULL, 0);
+
pm_power_off = mx31moboard_poweroff;
switch (mx31moboard_baseboard) {
@@ -580,7 +598,7 @@ static void __init mx31moboard_timer_init(void)
mx31_clocks_init(26000000);
}
-struct sys_timer mx31moboard_timer = {
+static struct sys_timer mx31moboard_timer = {
.init = mx31moboard_timer_init,
};
diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c
index 6ae51c6b95b7..86284bba46d3 100644
--- a/arch/arm/mach-imx/mach-mx35_3ds.c
+++ b/arch/arm/mach-imx/mach-mx35_3ds.c
@@ -34,6 +34,8 @@
#include <linux/usb/otg.h>
#include <linux/mtd/physmap.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -253,6 +255,8 @@ static iomux_v3_cfg_t mx35pdk_pads[] = {
MX35_PAD_CSI_MCLK__IPU_CSI_MCLK,
MX35_PAD_CSI_PIXCLK__IPU_CSI_PIXCLK,
MX35_PAD_CSI_VSYNC__IPU_CSI_VSYNC,
+ /*PMIC IRQ*/
+ MX35_PAD_GPIO2_0__GPIO2_0,
};
/*
@@ -317,6 +321,193 @@ static struct platform_device mx35_3ds_ov2640 = {
},
};
+static struct regulator_consumer_supply sw1_consumers[] = {
+ {
+ .supply = "cpu_vcc",
+ }
+};
+
+static struct regulator_consumer_supply vcam_consumers[] = {
+ /* sgtl5000 */
+ REGULATOR_SUPPLY("VDDA", "0-000a"),
+};
+
+static struct regulator_consumer_supply vaudio_consumers[] = {
+ REGULATOR_SUPPLY("cmos_vio", "soc-camera-pdrv.0"),
+};
+
+static struct regulator_init_data sw1_init = {
+ .constraints = {
+ .name = "SW1",
+ .min_uV = 600000,
+ .max_uV = 1375000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+ .consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+ .constraints = {
+ .name = "SW2",
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data sw3_init = {
+ .constraints = {
+ .name = "SW3",
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data sw4_init = {
+ .constraints = {
+ .name = "SW4",
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data viohi_init = {
+ .constraints = {
+ .name = "VIOHI",
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb_init = {
+ .constraints = {
+ .name = "VUSB",
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vdig_init = {
+ .constraints = {
+ .name = "VDIG",
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vpll_init = {
+ .constraints = {
+ .name = "VPLL",
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb2_init = {
+ .constraints = {
+ .name = "VUSB2",
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vvideo_init = {
+ .constraints = {
+ .name = "VVIDEO",
+ .boot_on = 1
+ }
+};
+
+static struct regulator_init_data vaudio_init = {
+ .constraints = {
+ .name = "VAUDIO",
+ .min_uV = 2300000,
+ .max_uV = 3000000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .boot_on = 1
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vaudio_consumers),
+ .consumer_supplies = vaudio_consumers,
+};
+
+static struct regulator_init_data vcam_init = {
+ .constraints = {
+ .name = "VCAM",
+ .min_uV = 2500000,
+ .max_uV = 3000000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_MODE,
+ .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
+ .boot_on = 1
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vcam_consumers),
+ .consumer_supplies = vcam_consumers,
+};
+
+static struct regulator_init_data vgen1_init = {
+ .constraints = {
+ .name = "VGEN1",
+ }
+};
+
+static struct regulator_init_data vgen2_init = {
+ .constraints = {
+ .name = "VGEN2",
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vgen3_init = {
+ .constraints = {
+ .name = "VGEN3",
+ }
+};
+
+static struct mc13xxx_regulator_init_data mx35_3ds_regulators[] = {
+ { .id = MC13892_SW1, .init_data = &sw1_init },
+ { .id = MC13892_SW2, .init_data = &sw2_init },
+ { .id = MC13892_SW3, .init_data = &sw3_init },
+ { .id = MC13892_SW4, .init_data = &sw4_init },
+ { .id = MC13892_VIOHI, .init_data = &viohi_init },
+ { .id = MC13892_VPLL, .init_data = &vpll_init },
+ { .id = MC13892_VDIG, .init_data = &vdig_init },
+ { .id = MC13892_VUSB2, .init_data = &vusb2_init },
+ { .id = MC13892_VVIDEO, .init_data = &vvideo_init },
+ { .id = MC13892_VAUDIO, .init_data = &vaudio_init },
+ { .id = MC13892_VCAM, .init_data = &vcam_init },
+ { .id = MC13892_VGEN1, .init_data = &vgen1_init },
+ { .id = MC13892_VGEN2, .init_data = &vgen2_init },
+ { .id = MC13892_VGEN3, .init_data = &vgen3_init },
+ { .id = MC13892_VUSB, .init_data = &vusb_init },
+};
+
+static struct mc13xxx_platform_data mx35_3ds_mc13892_data = {
+ .flags = MC13XXX_USE_RTC | MC13XXX_USE_TOUCHSCREEN,
+ .regulators = {
+ .num_regulators = ARRAY_SIZE(mx35_3ds_regulators),
+ .regulators = mx35_3ds_regulators,
+ },
+};
+
+#define GPIO_PMIC_INT IMX_GPIO_NR(2, 0)
+
+static struct i2c_board_info mx35_3ds_i2c_mc13892 = {
+
+ I2C_BOARD_INFO("mc13892", 0x08),
+ .platform_data = &mx35_3ds_mc13892_data,
+ .irq = IMX_GPIO_TO_IRQ(GPIO_PMIC_INT),
+};
+
+static void __init imx35_3ds_init_mc13892(void)
+{
+ int ret = gpio_request_one(GPIO_PMIC_INT, GPIOF_DIR_IN, "pmic irq");
+
+ if (ret) {
+ pr_err("failed to get pmic irq: %d\n", ret);
+ return;
+ }
+
+ i2c_register_board_info(0, &mx35_3ds_i2c_mc13892, 1);
+}
+
static int mx35_3ds_otg_init(struct platform_device *pdev)
{
return mx35_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
@@ -412,6 +603,8 @@ static void __init mx35_3ds_init(void)
imx35_fb_pdev = imx35_add_mx3_sdc_fb(&mx3fb_pdata);
mx35_3ds_lcd.dev.parent = &imx35_fb_pdev->dev;
platform_device_register(&mx35_3ds_lcd);
+
+ imx35_3ds_init_mc13892();
}
static void __init mx35pdk_timer_init(void)
@@ -419,7 +612,7 @@ static void __init mx35pdk_timer_init(void)
mx35_clocks_init();
}
-struct sys_timer mx35pdk_timer = {
+static struct sys_timer mx35pdk_timer = {
.init = mx35pdk_timer_init,
};
diff --git a/arch/arm/mach-imx/mach-mx51_efikamx.c b/arch/arm/mach-imx/mach-mx51_efikamx.c
index 586e9f822124..86e96ef11f9d 100644
--- a/arch/arm/mach-imx/mach-mx51_efikamx.c
+++ b/arch/arm/mach-imx/mach-mx51_efikamx.c
@@ -284,8 +284,7 @@ static struct sys_timer mx51_efikamx_timer = {
.init = mx51_efikamx_timer_init,
};
-MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
- /* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
+MACHINE_START(MX51_EFIKAMX, "Genesi Efika MX (Smarttop)")
.atag_offset = 0x100,
.map_io = mx51_map_io,
.init_early = imx51_init_early,
diff --git a/arch/arm/mach-imx/mach-mx51_efikasb.c b/arch/arm/mach-imx/mach-mx51_efikasb.c
index 24aded9e109f..88f837a6cc76 100644
--- a/arch/arm/mach-imx/mach-mx51_efikasb.c
+++ b/arch/arm/mach-imx/mach-mx51_efikasb.c
@@ -280,7 +280,7 @@ static struct sys_timer mx51_efikasb_timer = {
.init = mx51_efikasb_timer_init,
};
-MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
+MACHINE_START(MX51_EFIKASB, "Genesi Efika MX (Smartbook)")
.atag_offset = 0x100,
.map_io = mx51_map_io,
.init_early = imx51_init_early,
diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c
index 5fddf94cc969..10c9795934a3 100644
--- a/arch/arm/mach-imx/mach-pcm037.c
+++ b/arch/arm/mach-imx/mach-pcm037.c
@@ -683,7 +683,7 @@ static void __init pcm037_timer_init(void)
mx31_clocks_init(26000000);
}
-struct sys_timer pcm037_timer = {
+static struct sys_timer pcm037_timer = {
.init = pcm037_timer_init,
};
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 237474fcca23..73585f55cca0 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -399,7 +399,7 @@ static void __init pcm043_timer_init(void)
mx35_clocks_init();
}
-struct sys_timer pcm043_timer = {
+static struct sys_timer pcm043_timer = {
.init = pcm043_timer_init,
};
diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c
index 033257e553ef..add8c69c6c1a 100644
--- a/arch/arm/mach-imx/mach-vpr200.c
+++ b/arch/arm/mach-imx/mach-vpr200.c
@@ -310,7 +310,7 @@ static void __init vpr200_timer_init(void)
mx35_clocks_init();
}
-struct sys_timer vpr200_timer = {
+static struct sys_timer vpr200_timer = {
.init = vpr200_timer_init,
};
diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c
index 2bded591d5c2..fcafd3dafb8c 100644
--- a/arch/arm/mach-imx/mm-imx1.c
+++ b/arch/arm/mach-imx/mm-imx1.c
@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/pinctrl/machine.h>
#include <asm/mach/map.h>
@@ -58,4 +59,5 @@ void __init imx1_soc_init(void)
MX1_GPIO_INT_PORTC, 0);
mxc_register_gpio("imx1-gpio", 3, MX1_GPIO4_BASE_ADDR, SZ_256,
MX1_GPIO_INT_PORTD, 0);
+ pinctrl_provide_dummies();
}
diff --git a/arch/arm/mach-imx/mm-imx21.c b/arch/arm/mach-imx/mm-imx21.c
index 14d540edfd1e..5f43905e5290 100644
--- a/arch/arm/mach-imx/mm-imx21.c
+++ b/arch/arm/mach-imx/mm-imx21.c
@@ -20,6 +20,7 @@
#include <linux/mm.h>
#include <linux/init.h>
+#include <linux/pinctrl/machine.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/devices-common.h>
@@ -88,6 +89,7 @@ void __init imx21_soc_init(void)
mxc_register_gpio("imx21-gpio", 4, MX21_GPIO5_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+ pinctrl_provide_dummies();
imx_add_imx_dma();
platform_device_register_simple("imx21-audmux", 0, imx21_audmux_res,
ARRAY_SIZE(imx21_audmux_res));
diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c
index 153b457acdc0..6ff37140a4f8 100644
--- a/arch/arm/mach-imx/mm-imx25.c
+++ b/arch/arm/mach-imx/mm-imx25.c
@@ -19,6 +19,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/err.h>
+#include <linux/pinctrl/machine.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
@@ -95,6 +96,7 @@ void __init imx25_soc_init(void)
mxc_register_gpio("imx31-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0);
mxc_register_gpio("imx31-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0);
+ pinctrl_provide_dummies();
/* i.mx25 has the i.mx35 type sdma */
imx_add_imx_sdma("imx35-sdma", MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
/* i.mx25 has the i.mx31 type audmux */
diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c
index 8cb3f5e3e569..25662558e018 100644
--- a/arch/arm/mach-imx/mm-imx27.c
+++ b/arch/arm/mach-imx/mm-imx27.c
@@ -20,6 +20,7 @@
#include <linux/mm.h>
#include <linux/init.h>
+#include <linux/pinctrl/machine.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/devices-common.h>
@@ -89,6 +90,7 @@ void __init imx27_soc_init(void)
mxc_register_gpio("imx21-gpio", 4, MX27_GPIO5_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+ pinctrl_provide_dummies();
imx_add_imx_dma();
/* imx27 has the imx21 type audmux */
platform_device_register_simple("imx21-audmux", 0, imx27_audmux_res,
diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c
index 74127389e7ab..9128d15b1eb7 100644
--- a/arch/arm/mach-imx/mm-imx3.c
+++ b/arch/arm/mach-imx/mm-imx3.c
@@ -19,6 +19,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/err.h>
+#include <linux/pinctrl/machine.h>
#include <asm/pgtable.h>
#include <asm/system_misc.h>
@@ -267,6 +268,7 @@ void __init imx35_soc_init(void)
mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
+ pinctrl_provide_dummies();
if (to_version == 1) {
strncpy(imx35_sdma_pdata.fw_name, "sdma-imx35-to1.bin",
strlen(imx35_sdma_pdata.fw_name));
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
index e10f3914fcfe..ba91e6b31cf4 100644
--- a/arch/arm/mach-imx/mm-imx5.c
+++ b/arch/arm/mach-imx/mm-imx5.c
@@ -14,6 +14,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/clk.h>
+#include <linux/pinctrl/machine.h>
#include <asm/system_misc.h>
#include <asm/mach/map.h>
@@ -223,6 +224,7 @@ void __init imx53_soc_init(void)
mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
+ pinctrl_provide_dummies();
/* i.mx53 has the i.mx35 type sdma */
imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index 3e538da6cb1f..e428f3ab15c7 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -398,24 +398,16 @@ static int impd1_probe(struct lm_device *dev)
struct impd1_device *idev = impd1_devs + i;
struct amba_device *d;
unsigned long pc_base;
+ char devname[32];
pc_base = dev->resource.start + idev->offset;
-
- d = amba_device_alloc(NULL, pc_base, SZ_4K);
- if (!d)
+ snprintf(devname, 32, "lm%x:%5.5lx", dev->id, idev->offset >> 12);
+ d = amba_ahb_device_add(&dev->dev, devname, pc_base, SZ_4K,
+ dev->irq, dev->irq,
+ idev->platform_data, idev->id);
+ if (IS_ERR(d)) {
+ dev_err(&dev->dev, "unable to register device: %ld\n", PTR_ERR(d));
continue;
-
- dev_set_name(&d->dev, "lm%x:%5.5lx", dev->id, idev->offset >> 12);
- d->dev.parent = &dev->dev;
- d->irq[0] = dev->irq;
- d->irq[1] = dev->irq;
- d->periphid = idev->id;
- d->dev.platform_data = idev->platform_data;
-
- ret = amba_device_add(d, &dev->resource);
- if (ret) {
- dev_err(&d->dev, "unable to register device: %d\n", ret);
- amba_device_put(d);
}
}
diff --git a/arch/arm/mach-integrator/include/mach/entry-macro.S b/arch/arm/mach-integrator/include/mach/entry-macro.S
deleted file mode 100644
index 5cc7b85ad9df..000000000000
--- a/arch/arm/mach-integrator/include/mach/entry-macro.S
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * arch/arm/mach-integrator/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for Integrator platforms
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <mach/hardware.h>
-#include <mach/platform.h>
-#include <mach/irqs.h>
-
- .macro get_irqnr_preamble, base, tmp
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-/* FIXME: should not be using soo many LDRs here */
- ldr \base, =IO_ADDRESS(INTEGRATOR_IC_BASE)
- mov \irqnr, #IRQ_PIC_START
- ldr \irqstat, [\base, #IRQ_STATUS] @ get masked status
- ldr \base, =IO_ADDRESS(INTEGRATOR_HDR_BASE)
- teq \irqstat, #0
- ldreq \irqstat, [\base, #(INTEGRATOR_HDR_IC_OFFSET+IRQ_STATUS)]
- moveq \irqnr, #IRQ_CIC_START
-
-1001: tst \irqstat, #15
- bne 1002f
- add \irqnr, \irqnr, #4
- movs \irqstat, \irqstat, lsr #4
- bne 1001b
-1002: tst \irqstat, #1
- bne 1003f
- add \irqnr, \irqnr, #1
- movs \irqstat, \irqstat, lsr #1
- bne 1002b
-1003: /* EQ will be set if no irqs pending */
- .endm
-
diff --git a/arch/arm/mach-integrator/include/mach/irqs.h b/arch/arm/mach-integrator/include/mach/irqs.h
index a19a1a2fcf6b..7371018455d2 100644
--- a/arch/arm/mach-integrator/include/mach/irqs.h
+++ b/arch/arm/mach-integrator/include/mach/irqs.h
@@ -22,37 +22,37 @@
/*
* Interrupt numbers
*/
-#define IRQ_PIC_START 0
-#define IRQ_SOFTINT 0
-#define IRQ_UARTINT0 1
-#define IRQ_UARTINT1 2
-#define IRQ_KMIINT0 3
-#define IRQ_KMIINT1 4
-#define IRQ_TIMERINT0 5
-#define IRQ_TIMERINT1 6
-#define IRQ_TIMERINT2 7
-#define IRQ_RTCINT 8
-#define IRQ_AP_EXPINT0 9
-#define IRQ_AP_EXPINT1 10
-#define IRQ_AP_EXPINT2 11
-#define IRQ_AP_EXPINT3 12
-#define IRQ_AP_PCIINT0 13
-#define IRQ_AP_PCIINT1 14
-#define IRQ_AP_PCIINT2 15
-#define IRQ_AP_PCIINT3 16
-#define IRQ_AP_V3INT 17
-#define IRQ_AP_CPINT0 18
-#define IRQ_AP_CPINT1 19
-#define IRQ_AP_LBUSTIMEOUT 20
-#define IRQ_AP_APCINT 21
-#define IRQ_CP_CLCDCINT 22
-#define IRQ_CP_MMCIINT0 23
-#define IRQ_CP_MMCIINT1 24
-#define IRQ_CP_AACIINT 25
-#define IRQ_CP_CPPLDINT 26
-#define IRQ_CP_ETHINT 27
-#define IRQ_CP_TSPENINT 28
-#define IRQ_PIC_END 31
+#define IRQ_PIC_START 1
+#define IRQ_SOFTINT 1
+#define IRQ_UARTINT0 2
+#define IRQ_UARTINT1 3
+#define IRQ_KMIINT0 4
+#define IRQ_KMIINT1 5
+#define IRQ_TIMERINT0 6
+#define IRQ_TIMERINT1 7
+#define IRQ_TIMERINT2 8
+#define IRQ_RTCINT 9
+#define IRQ_AP_EXPINT0 10
+#define IRQ_AP_EXPINT1 11
+#define IRQ_AP_EXPINT2 12
+#define IRQ_AP_EXPINT3 13
+#define IRQ_AP_PCIINT0 14
+#define IRQ_AP_PCIINT1 15
+#define IRQ_AP_PCIINT2 16
+#define IRQ_AP_PCIINT3 17
+#define IRQ_AP_V3INT 18
+#define IRQ_AP_CPINT0 19
+#define IRQ_AP_CPINT1 20
+#define IRQ_AP_LBUSTIMEOUT 21
+#define IRQ_AP_APCINT 22
+#define IRQ_CP_CLCDCINT 23
+#define IRQ_CP_MMCIINT0 24
+#define IRQ_CP_MMCIINT1 25
+#define IRQ_CP_AACIINT 26
+#define IRQ_CP_CPPLDINT 27
+#define IRQ_CP_ETHINT 28
+#define IRQ_CP_TSPENINT 29
+#define IRQ_PIC_END 29
#define IRQ_CIC_START 32
#define IRQ_CM_SOFTINT 32
@@ -80,4 +80,3 @@
#define NR_IRQS_INTEGRATOR_AP 34
#define NR_IRQS_INTEGRATOR_CP 47
-
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 871f148ffd72..c857501c5783 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -162,12 +162,6 @@ static void __init ap_map_io(void)
#define INTEGRATOR_SC_VALID_INT 0x003fffff
-static struct fpga_irq_data sc_irq_data = {
- .base = VA_IC_BASE,
- .irq_start = 0,
- .chip.name = "SC",
-};
-
static void __init ap_init_irq(void)
{
/* Disable all interrupts initially. */
@@ -178,7 +172,8 @@ static void __init ap_init_irq(void)
writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
- fpga_irq_init(-1, INTEGRATOR_SC_VALID_INT, &sc_irq_data);
+ fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START,
+ -1, INTEGRATOR_SC_VALID_INT, NULL);
}
#ifdef CONFIG_PM
@@ -478,6 +473,7 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator")
.nr_irqs = NR_IRQS_INTEGRATOR_AP,
.init_early = integrator_init_early,
.init_irq = ap_init_irq,
+ .handle_irq = fpga_handle_irq,
.timer = &ap_timer,
.init_machine = ap_init,
.restart = integrator_restart,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 48a115a91d9d..a56c53608939 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -143,30 +143,14 @@ static void __init intcp_map_io(void)
iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
}
-static struct fpga_irq_data cic_irq_data = {
- .base = INTCP_VA_CIC_BASE,
- .irq_start = IRQ_CIC_START,
- .chip.name = "CIC",
-};
-
-static struct fpga_irq_data pic_irq_data = {
- .base = INTCP_VA_PIC_BASE,
- .irq_start = IRQ_PIC_START,
- .chip.name = "PIC",
-};
-
-static struct fpga_irq_data sic_irq_data = {
- .base = INTCP_VA_SIC_BASE,
- .irq_start = IRQ_SIC_START,
- .chip.name = "SIC",
-};
-
static void __init intcp_init_irq(void)
{
- u32 pic_mask, sic_mask;
+ u32 pic_mask, cic_mask, sic_mask;
+ /* These masks are for the HW IRQ registers */
pic_mask = ~((~0u) << (11 - IRQ_PIC_START));
pic_mask |= (~((~0u) << (29 - 22))) << 22;
+ cic_mask = ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START));
sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START));
/*
@@ -179,12 +163,14 @@ static void __init intcp_init_irq(void)
writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
- fpga_irq_init(-1, pic_mask, &pic_irq_data);
+ fpga_irq_init(INTCP_VA_PIC_BASE, "PIC", IRQ_PIC_START,
+ -1, pic_mask, NULL);
- fpga_irq_init(-1, ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START)),
- &cic_irq_data);
+ fpga_irq_init(INTCP_VA_CIC_BASE, "CIC", IRQ_CIC_START,
+ -1, cic_mask, NULL);
- fpga_irq_init(IRQ_CP_CPPLDINT, sic_mask, &sic_irq_data);
+ fpga_irq_init(INTCP_VA_SIC_BASE, "SIC", IRQ_SIC_START,
+ IRQ_CP_CPPLDINT, sic_mask, NULL);
}
/*
@@ -467,6 +453,7 @@ MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
.nr_irqs = NR_IRQS_INTEGRATOR_CP,
.init_early = intcp_init_early,
.init_irq = intcp_init_irq,
+ .handle_irq = fpga_handle_irq,
.timer = &cp_timer,
.init_machine = intcp_init,
.restart = integrator_restart,
diff --git a/arch/arm/mach-integrator/pci.c b/arch/arm/mach-integrator/pci.c
index f1ca9c122861..6c1667e728f5 100644
--- a/arch/arm/mach-integrator/pci.c
+++ b/arch/arm/mach-integrator/pci.c
@@ -70,21 +70,10 @@
*/
static u8 __init integrator_swizzle(struct pci_dev *dev, u8 *pinp)
{
- int pin = *pinp;
+ if (*pinp == 0)
+ *pinp = 1;
- if (pin == 0)
- pin = 1;
-
- while (dev->bus->self) {
- pin = pci_swizzle_interrupt_pin(dev, pin);
- /*
- * move up the chain of bridges, swizzling as we go.
- */
- dev = dev->bus->self;
- }
- *pinp = pin;
-
- return PCI_SLOT(dev->devfn);
+ return pci_common_swizzle(dev, pinp);
}
static int irq_tab[4] __initdata = {
@@ -109,7 +98,7 @@ static struct hw_pci integrator_pci __initdata = {
.map_irq = integrator_map_irq,
.setup = pci_v3_setup,
.nr_controllers = 1,
- .scan = pci_v3_scan_bus,
+ .ops = &pci_v3_ops,
.preinit = pci_v3_preinit,
.postinit = pci_v3_postinit,
};
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index 67e6f9a9d1a0..b866880e82ac 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -340,7 +340,7 @@ static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
return PCIBIOS_SUCCESSFUL;
}
-static struct pci_ops pci_v3_ops = {
+struct pci_ops pci_v3_ops = {
.read = v3_read_config,
.write = v3_write_config,
};
@@ -488,12 +488,6 @@ int __init pci_v3_setup(int nr, struct pci_sys_data *sys)
return ret;
}
-struct pci_bus * __init pci_v3_scan_bus(int nr, struct pci_sys_data *sys)
-{
- return pci_scan_root_bus(NULL, sys->busnr, &pci_v3_ops, sys,
- &sys->resources);
-}
-
/*
* V3_LB_BASE? - local bus address
* V3_LB_MAP? - pci bus address
diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c
index 5c96b73e6964..e3f3e7daa79e 100644
--- a/arch/arm/mach-iop13xx/iq81340mc.c
+++ b/arch/arm/mach-iop13xx/iq81340mc.c
@@ -54,7 +54,6 @@ iq81340mc_pcix_map_irq(const struct pci_dev *dev, u8 idsel, u8 pin)
}
static struct hw_pci iq81340mc_pci __initdata = {
- .swizzle = pci_std_swizzle,
.nr_controllers = 0,
.setup = iop13xx_pci_setup,
.map_irq = iq81340mc_pcix_map_irq,
diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c
index aa4dd750135a..060cddde2fd4 100644
--- a/arch/arm/mach-iop13xx/iq81340sc.c
+++ b/arch/arm/mach-iop13xx/iq81340sc.c
@@ -56,7 +56,6 @@ iq81340sc_atux_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
}
static struct hw_pci iq81340sc_pci __initdata = {
- .swizzle = pci_std_swizzle,
.nr_controllers = 0,
.setup = iop13xx_pci_setup,
.scan = iop13xx_scan_bus,
diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c
index 24069e03fdc1..9f369f09c29d 100644
--- a/arch/arm/mach-iop32x/em7210.c
+++ b/arch/arm/mach-iop32x/em7210.c
@@ -103,11 +103,10 @@ em7210_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
}
static struct hw_pci em7210_pci __initdata = {
- .swizzle = pci_std_swizzle,
.nr_controllers = 1,
+ .ops = &iop3xx_ops,
.setup = iop3xx_pci_setup,
.preinit = iop3xx_pci_preinit,
- .scan = iop3xx_pci_scan_bus,
.map_irq = em7210_pci_map_irq,
};
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index 204e1d1cd766..c15a100ba779 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -96,11 +96,10 @@ glantank_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
}
static struct hw_pci glantank_pci __initdata = {
- .swizzle = pci_std_swizzle,
.nr_controllers = 1,
+ .ops = &iop3xx_ops,
.setup = iop3xx_pci_setup,
.preinit = iop3xx_pci_preinit,
- .scan = iop3xx_pci_scan_bus,
.map_irq = glantank_pci_map_irq,
};
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index 3eb642af1cdc..ddd1c7ecfe57 100644
--- a/arch/arm/mach-iop32x/iq31244.c
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -130,11 +130,10 @@ ep80219_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
}
static struct hw_pci ep80219_pci __initdata = {
- .swizzle = pci_std_swizzle,
.nr_controllers = 1,
+ .ops = &iop3xx_ops,
.setup = iop3xx_pci_setup,
.preinit = iop3xx_pci_preinit,
- .scan = iop3xx_pci_scan_bus,
.map_irq = ep80219_pci_map_irq,
};
@@ -166,11 +165,10 @@ iq31244_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
}
static struct hw_pci iq31244_pci __initdata = {
- .swizzle = pci_std_swizzle,
.nr_controllers = 1,
+ .ops = &iop3xx_ops,
.setup = iop3xx_pci_setup,
.preinit = iop3xx_pci_preinit,
- .scan = iop3xx_pci_scan_bus,
.map_irq = iq31244_pci_map_irq,
};
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
index 2ec724b58a2c..bf155e6a3b45 100644
--- a/arch/arm/mach-iop32x/iq80321.c
+++ b/arch/arm/mach-iop32x/iq80321.c
@@ -101,11 +101,10 @@ iq80321_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
}
static struct hw_pci iq80321_pci __initdata = {
- .swizzle = pci_std_swizzle,
.nr_controllers = 1,
+ .ops = &iop3xx_ops,
.setup = iop3xx_pci_setup,
.preinit = iop3xx_pci_preinit_cond,
- .scan = iop3xx_pci_scan_bus,
.map_irq = iq80321_pci_map_irq,
};
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 6b6d55912444..5a7ae91e8849 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -114,11 +114,10 @@ n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
}
static struct hw_pci n2100_pci __initdata = {
- .swizzle = pci_std_swizzle,
.nr_controllers = 1,
+ .ops = &iop3xx_ops,
.setup = iop3xx_pci_setup,
.preinit = iop3xx_pci_preinit,
- .scan = iop3xx_pci_scan_bus,
.map_irq = n2100_pci_map_irq,
};
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
index abce934f3816..e74a7debe793 100644
--- a/arch/arm/mach-iop33x/iq80331.c
+++ b/arch/arm/mach-iop33x/iq80331.c
@@ -84,11 +84,10 @@ iq80331_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
}
static struct hw_pci iq80331_pci __initdata = {
- .swizzle = pci_std_swizzle,
.nr_controllers = 1,
+ .ops = &iop3xx_ops,
.setup = iop3xx_pci_setup,
.preinit = iop3xx_pci_preinit_cond,
- .scan = iop3xx_pci_scan_bus,
.map_irq = iq80331_pci_map_irq,
};
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
index 7513559e25bb..e2f5beece6e8 100644
--- a/arch/arm/mach-iop33x/iq80332.c
+++ b/arch/arm/mach-iop33x/iq80332.c
@@ -84,11 +84,10 @@ iq80332_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
}
static struct hw_pci iq80332_pci __initdata = {
- .swizzle = pci_std_swizzle,
.nr_controllers = 1,
+ .ops = &iop3xx_ops,
.setup = iop3xx_pci_setup,
.preinit = iop3xx_pci_preinit_cond,
- .scan = iop3xx_pci_scan_bus,
.map_irq = iq80332_pci_map_irq,
};
diff --git a/arch/arm/mach-ixp2000/Kconfig b/arch/arm/mach-ixp2000/Kconfig
deleted file mode 100644
index 08d2707f6ca8..000000000000
--- a/arch/arm/mach-ixp2000/Kconfig
+++ /dev/null
@@ -1,72 +0,0 @@
-
-if ARCH_IXP2000
-
-config ARCH_SUPPORTS_BIG_ENDIAN
- bool
- default y
-
-menu "Intel IXP2400/2800 Implementation Options"
-
-comment "IXP2400/2800 Platforms"
-
-config ARCH_ENP2611
- bool "Support Radisys ENP-2611"
- help
- Say 'Y' here if you want your kernel to support the Radisys
- ENP2611 PCI network processing card. For more information on
- this card, see <file:Documentation/arm/IXP2000>.
-
-config ARCH_IXDP2400
- bool "Support Intel IXDP2400"
- help
- Say 'Y' here if you want your kernel to support the Intel
- IXDP2400 reference platform. For more information on
- this platform, see <file:Documentation/arm/IXP2000>.
-
-config ARCH_IXDP2800
- bool "Support Intel IXDP2800"
- help
- Say 'Y' here if you want your kernel to support the Intel
- IXDP2800 reference platform. For more information on
- this platform, see <file:Documentation/arm/IXP2000>.
-
-config ARCH_IXDP2X00
- bool
- depends on ARCH_IXDP2400 || ARCH_IXDP2800
- default y
-
-config ARCH_IXDP2401
- bool "Support Intel IXDP2401"
- help
- Say 'Y' here if you want your kernel to support the Intel
- IXDP2401 reference platform. For more information on
- this platform, see <file:Documentation/arm/IXP2000>.
-
-config ARCH_IXDP2801
- bool "Support Intel IXDP2801 and IXDP28x5"
- help
- Say 'Y' here if you want your kernel to support the Intel
- IXDP2801/2805/2855 reference platforms. For more information on
- this platform, see <file:Documentation/arm/IXP2000>.
-
-config MACH_IXDP28X5
- bool
- depends on ARCH_IXDP2801
- default y
-
-config ARCH_IXDP2X01
- bool
- depends on ARCH_IXDP2401 || ARCH_IXDP2801
- default y
-
-config IXP2000_SUPPORT_BROKEN_PCI_IO
- bool "Support broken PCI I/O on older IXP2000s"
- default y
- help
- Say 'N' here if you only intend to run your kernel on an
- IXP2000 B0 or later model and do not need the PCI I/O
- byteswap workaround. Say 'Y' otherwise.
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-ixp2000/Makefile b/arch/arm/mach-ixp2000/Makefile
deleted file mode 100644
index 1e6139d42a92..000000000000
--- a/arch/arm/mach-ixp2000/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-obj-y := core.o pci.o
-obj-m :=
-obj-n :=
-obj- :=
-
-obj-$(CONFIG_ARCH_ENP2611) += enp2611.o
-obj-$(CONFIG_ARCH_IXDP2400) += ixdp2400.o
-obj-$(CONFIG_ARCH_IXDP2800) += ixdp2800.o
-obj-$(CONFIG_ARCH_IXDP2X00) += ixdp2x00.o
-obj-$(CONFIG_ARCH_IXDP2X01) += ixdp2x01.o
-
diff --git a/arch/arm/mach-ixp2000/Makefile.boot b/arch/arm/mach-ixp2000/Makefile.boot
deleted file mode 100644
index 9c7af91d93da..000000000000
--- a/arch/arm/mach-ixp2000/Makefile.boot
+++ /dev/null
@@ -1,3 +0,0 @@
- zreladdr-y += 0x00008000
-params_phys-y := 0x00000100
-
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
deleted file mode 100644
index f214cdff01cb..000000000000
--- a/arch/arm/mach-ixp2000/core.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/core.c
- *
- * Common routines used by all IXP2400/2800 based platforms.
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright 2004 (C) MontaVista Software, Inc.
- *
- * Based on work Copyright (C) 2002-2003 Intel Corporation
- *
- * 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/gpio.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/bitops.h>
-#include <linux/serial_8250.h>
-#include <linux/mm.h>
-#include <linux/export.h>
-
-#include <asm/types.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/tlbflush.h>
-#include <asm/pgtable.h>
-
-#include <asm/mach/map.h>
-#include <asm/mach/time.h>
-#include <asm/mach/irq.h>
-
-#include <mach/gpio-ixp2000.h>
-
-static DEFINE_SPINLOCK(ixp2000_slowport_lock);
-static unsigned long ixp2000_slowport_irq_flags;
-
-/*************************************************************************
- * Slowport access routines
- *************************************************************************/
-void ixp2000_acquire_slowport(struct slowport_cfg *new_cfg, struct slowport_cfg *old_cfg)
-{
- spin_lock_irqsave(&ixp2000_slowport_lock, ixp2000_slowport_irq_flags);
-
- old_cfg->CCR = *IXP2000_SLOWPORT_CCR;
- old_cfg->WTC = *IXP2000_SLOWPORT_WTC2;
- old_cfg->RTC = *IXP2000_SLOWPORT_RTC2;
- old_cfg->PCR = *IXP2000_SLOWPORT_PCR;
- old_cfg->ADC = *IXP2000_SLOWPORT_ADC;
-
- ixp2000_reg_write(IXP2000_SLOWPORT_CCR, new_cfg->CCR);
- ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, new_cfg->WTC);
- ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, new_cfg->RTC);
- ixp2000_reg_write(IXP2000_SLOWPORT_PCR, new_cfg->PCR);
- ixp2000_reg_wrb(IXP2000_SLOWPORT_ADC, new_cfg->ADC);
-}
-
-void ixp2000_release_slowport(struct slowport_cfg *old_cfg)
-{
- ixp2000_reg_write(IXP2000_SLOWPORT_CCR, old_cfg->CCR);
- ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, old_cfg->WTC);
- ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, old_cfg->RTC);
- ixp2000_reg_write(IXP2000_SLOWPORT_PCR, old_cfg->PCR);
- ixp2000_reg_wrb(IXP2000_SLOWPORT_ADC, old_cfg->ADC);
-
- spin_unlock_irqrestore(&ixp2000_slowport_lock,
- ixp2000_slowport_irq_flags);
-}
-
-/*************************************************************************
- * Chip specific mappings shared by all IXP2000 systems
- *************************************************************************/
-static struct map_desc ixp2000_io_desc[] __initdata = {
- {
- .virtual = IXP2000_CAP_VIRT_BASE,
- .pfn = __phys_to_pfn(IXP2000_CAP_PHYS_BASE),
- .length = IXP2000_CAP_SIZE,
- .type = MT_DEVICE,
- }, {
- .virtual = IXP2000_INTCTL_VIRT_BASE,
- .pfn = __phys_to_pfn(IXP2000_INTCTL_PHYS_BASE),
- .length = IXP2000_INTCTL_SIZE,
- .type = MT_DEVICE,
- }, {
- .virtual = IXP2000_PCI_CREG_VIRT_BASE,
- .pfn = __phys_to_pfn(IXP2000_PCI_CREG_PHYS_BASE),
- .length = IXP2000_PCI_CREG_SIZE,
- .type = MT_DEVICE,
- }, {
- .virtual = IXP2000_PCI_CSR_VIRT_BASE,
- .pfn = __phys_to_pfn(IXP2000_PCI_CSR_PHYS_BASE),
- .length = IXP2000_PCI_CSR_SIZE,
- .type = MT_DEVICE,
- }, {
- .virtual = IXP2000_MSF_VIRT_BASE,
- .pfn = __phys_to_pfn(IXP2000_MSF_PHYS_BASE),
- .length = IXP2000_MSF_SIZE,
- .type = MT_DEVICE,
- }, {
- .virtual = IXP2000_SCRATCH_RING_VIRT_BASE,
- .pfn = __phys_to_pfn(IXP2000_SCRATCH_RING_PHYS_BASE),
- .length = IXP2000_SCRATCH_RING_SIZE,
- .type = MT_DEVICE,
- }, {
- .virtual = IXP2000_SRAM0_VIRT_BASE,
- .pfn = __phys_to_pfn(IXP2000_SRAM0_PHYS_BASE),
- .length = IXP2000_SRAM0_SIZE,
- .type = MT_DEVICE,
- }, {
- .virtual = IXP2000_PCI_IO_VIRT_BASE,
- .pfn = __phys_to_pfn(IXP2000_PCI_IO_PHYS_BASE),
- .length = IXP2000_PCI_IO_SIZE,
- .type = MT_DEVICE,
- }, {
- .virtual = IXP2000_PCI_CFG0_VIRT_BASE,
- .pfn = __phys_to_pfn(IXP2000_PCI_CFG0_PHYS_BASE),
- .length = IXP2000_PCI_CFG0_SIZE,
- .type = MT_DEVICE,
- }, {
- .virtual = IXP2000_PCI_CFG1_VIRT_BASE,
- .pfn = __phys_to_pfn(IXP2000_PCI_CFG1_PHYS_BASE),
- .length = IXP2000_PCI_CFG1_SIZE,
- .type = MT_DEVICE,
- }
-};
-
-void __init ixp2000_map_io(void)
-{
- iotable_init(ixp2000_io_desc, ARRAY_SIZE(ixp2000_io_desc));
-
- /* Set slowport to 8-bit mode. */
- ixp2000_reg_wrb(IXP2000_SLOWPORT_FRM, 1);
-}
-
-
-/*************************************************************************
- * Serial port support for IXP2000
- *************************************************************************/
-static struct plat_serial8250_port ixp2000_serial_port[] = {
- {
- .mapbase = IXP2000_UART_PHYS_BASE,
- .membase = (char *)(IXP2000_UART_VIRT_BASE + 3),
- .irq = IRQ_IXP2000_UART,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = 50000000,
- },
- { },
-};
-
-static struct resource ixp2000_uart_resource = {
- .start = IXP2000_UART_PHYS_BASE,
- .end = IXP2000_UART_PHYS_BASE + 0x1f,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device ixp2000_serial_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev = {
- .platform_data = ixp2000_serial_port,
- },
- .num_resources = 1,
- .resource = &ixp2000_uart_resource,
-};
-
-void __init ixp2000_uart_init(void)
-{
- platform_device_register(&ixp2000_serial_device);
-}
-
-
-/*************************************************************************
- * Timer-tick functions for IXP2000
- *************************************************************************/
-static unsigned ticks_per_jiffy;
-static unsigned ticks_per_usec;
-static unsigned next_jiffy_time;
-static volatile unsigned long *missing_jiffy_timer_csr;
-
-unsigned long ixp2000_gettimeoffset (void)
-{
- unsigned long offset;
-
- offset = next_jiffy_time - *missing_jiffy_timer_csr;
-
- return offset / ticks_per_usec;
-}
-
-static irqreturn_t ixp2000_timer_interrupt(int irq, void *dev_id)
-{
- /* clear timer 1 */
- ixp2000_reg_wrb(IXP2000_T1_CLR, 1);
-
- while ((signed long)(next_jiffy_time - *missing_jiffy_timer_csr)
- >= ticks_per_jiffy) {
- timer_tick();
- next_jiffy_time -= ticks_per_jiffy;
- }
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction ixp2000_timer_irq = {
- .name = "IXP2000 Timer Tick",
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
- .handler = ixp2000_timer_interrupt,
-};
-
-void __init ixp2000_init_time(unsigned long tick_rate)
-{
- ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
- ticks_per_usec = tick_rate / 1000000;
-
- /*
- * We use timer 1 as our timer interrupt.
- */
- ixp2000_reg_write(IXP2000_T1_CLR, 0);
- ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1);
- ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));
-
- /*
- * We use a second timer as a monotonic counter for tracking
- * missed jiffies. The IXP2000 has four timers, but if we're
- * on an A-step IXP2800, timer 2 and 3 don't work, so on those
- * chips we use timer 4. Timer 4 is the only timer that can
- * be used for the watchdog, so we use timer 2 if we're on a
- * non-buggy chip.
- */
- if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
- printk(KERN_INFO "Enabling IXP2800 erratum #25 workaround\n");
-
- ixp2000_reg_write(IXP2000_T4_CLR, 0);
- ixp2000_reg_write(IXP2000_T4_CLD, -1);
- ixp2000_reg_wrb(IXP2000_T4_CTL, (1 << 7));
- missing_jiffy_timer_csr = IXP2000_T4_CSR;
- } else {
- ixp2000_reg_write(IXP2000_T2_CLR, 0);
- ixp2000_reg_write(IXP2000_T2_CLD, -1);
- ixp2000_reg_wrb(IXP2000_T2_CTL, (1 << 7));
- missing_jiffy_timer_csr = IXP2000_T2_CSR;
- }
- next_jiffy_time = 0xffffffff;
-
- /* register for interrupt */
- setup_irq(IRQ_IXP2000_TIMER1, &ixp2000_timer_irq);
-}
-
-/*************************************************************************
- * GPIO helpers
- *************************************************************************/
-static unsigned long GPIO_IRQ_falling_edge;
-static unsigned long GPIO_IRQ_rising_edge;
-static unsigned long GPIO_IRQ_level_low;
-static unsigned long GPIO_IRQ_level_high;
-
-static void update_gpio_int_csrs(void)
-{
- ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge);
- ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge);
- ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low);
- ixp2000_reg_wrb(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);
-}
-
-void gpio_line_config(int line, int direction)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- if (direction == GPIO_OUT) {
- /* if it's an output, it ain't an interrupt anymore */
- GPIO_IRQ_falling_edge &= ~(1 << line);
- GPIO_IRQ_rising_edge &= ~(1 << line);
- GPIO_IRQ_level_low &= ~(1 << line);
- GPIO_IRQ_level_high &= ~(1 << line);
- update_gpio_int_csrs();
-
- ixp2000_reg_wrb(IXP2000_GPIO_PDSR, 1 << line);
- } else if (direction == GPIO_IN) {
- ixp2000_reg_wrb(IXP2000_GPIO_PDCR, 1 << line);
- }
- local_irq_restore(flags);
-}
-EXPORT_SYMBOL(gpio_line_config);
-
-
-/*************************************************************************
- * IRQ handling IXP2000
- *************************************************************************/
-static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
- int i;
- unsigned long status = *IXP2000_GPIO_INST;
-
- for (i = 0; i <= 7; i++) {
- if (status & (1<<i)) {
- generic_handle_irq(i + IRQ_IXP2000_GPIO0);
- }
- }
-}
-
-static int ixp2000_GPIO_irq_type(struct irq_data *d, unsigned int type)
-{
- int line = d->irq - IRQ_IXP2000_GPIO0;
-
- /*
- * First, configure this GPIO line as an input.
- */
- ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line);
-
- /*
- * Then, set the proper trigger type.
- */
- if (type & IRQ_TYPE_EDGE_FALLING)
- GPIO_IRQ_falling_edge |= 1 << line;
- else
- GPIO_IRQ_falling_edge &= ~(1 << line);
- if (type & IRQ_TYPE_EDGE_RISING)
- GPIO_IRQ_rising_edge |= 1 << line;
- else
- GPIO_IRQ_rising_edge &= ~(1 << line);
- if (type & IRQ_TYPE_LEVEL_LOW)
- GPIO_IRQ_level_low |= 1 << line;
- else
- GPIO_IRQ_level_low &= ~(1 << line);
- if (type & IRQ_TYPE_LEVEL_HIGH)
- GPIO_IRQ_level_high |= 1 << line;
- else
- GPIO_IRQ_level_high &= ~(1 << line);
- update_gpio_int_csrs();
-
- return 0;
-}
-
-static void ixp2000_GPIO_irq_mask_ack(struct irq_data *d)
-{
- unsigned int irq = d->irq;
-
- ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
-
- ixp2000_reg_write(IXP2000_GPIO_EDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
- ixp2000_reg_write(IXP2000_GPIO_LDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
- ixp2000_reg_wrb(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));
-}
-
-static void ixp2000_GPIO_irq_mask(struct irq_data *d)
-{
- unsigned int irq = d->irq;
-
- ixp2000_reg_wrb(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
-}
-
-static void ixp2000_GPIO_irq_unmask(struct irq_data *d)
-{
- unsigned int irq = d->irq;
-
- ixp2000_reg_write(IXP2000_GPIO_INSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
-}
-
-static struct irq_chip ixp2000_GPIO_irq_chip = {
- .irq_ack = ixp2000_GPIO_irq_mask_ack,
- .irq_mask = ixp2000_GPIO_irq_mask,
- .irq_unmask = ixp2000_GPIO_irq_unmask,
- .irq_set_type = ixp2000_GPIO_irq_type,
-};
-
-static void ixp2000_pci_irq_mask(struct irq_data *d)
-{
- unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;
- if (d->irq == IRQ_IXP2000_PCIA)
- ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 26)));
- else if (d->irq == IRQ_IXP2000_PCIB)
- ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 27)));
-}
-
-static void ixp2000_pci_irq_unmask(struct irq_data *d)
-{
- unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;
- if (d->irq == IRQ_IXP2000_PCIA)
- ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 26)));
- else if (d->irq == IRQ_IXP2000_PCIB)
- ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 27)));
-}
-
-/*
- * Error interrupts. These are used extensively by the microengine drivers
- */
-static void ixp2000_err_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
- int i;
- unsigned long status = *IXP2000_IRQ_ERR_STATUS;
-
- for(i = 31; i >= 0; i--) {
- if(status & (1 << i)) {
- generic_handle_irq(IRQ_IXP2000_DRAM0_MIN_ERR + i);
- }
- }
-}
-
-static void ixp2000_err_irq_mask(struct irq_data *d)
-{
- ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_CLR,
- (1 << (d->irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
-}
-
-static void ixp2000_err_irq_unmask(struct irq_data *d)
-{
- ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_SET,
- (1 << (d->irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
-}
-
-static struct irq_chip ixp2000_err_irq_chip = {
- .irq_ack = ixp2000_err_irq_mask,
- .irq_mask = ixp2000_err_irq_mask,
- .irq_unmask = ixp2000_err_irq_unmask
-};
-
-static struct irq_chip ixp2000_pci_irq_chip = {
- .irq_ack = ixp2000_pci_irq_mask,
- .irq_mask = ixp2000_pci_irq_mask,
- .irq_unmask = ixp2000_pci_irq_unmask
-};
-
-static void ixp2000_irq_mask(struct irq_data *d)
-{
- ixp2000_reg_wrb(IXP2000_IRQ_ENABLE_CLR, (1 << d->irq));
-}
-
-static void ixp2000_irq_unmask(struct irq_data *d)
-{
- ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << d->irq));
-}
-
-static struct irq_chip ixp2000_irq_chip = {
- .irq_ack = ixp2000_irq_mask,
- .irq_mask = ixp2000_irq_mask,
- .irq_unmask = ixp2000_irq_unmask
-};
-
-void __init ixp2000_init_irq(void)
-{
- int irq;
-
- /*
- * Mask all sources
- */
- ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, 0xffffffff);
- ixp2000_reg_write(IXP2000_FIQ_ENABLE_CLR, 0xffffffff);
-
- /* clear all GPIO edge/level detects */
- ixp2000_reg_write(IXP2000_GPIO_REDR, 0);
- ixp2000_reg_write(IXP2000_GPIO_FEDR, 0);
- ixp2000_reg_write(IXP2000_GPIO_LSHR, 0);
- ixp2000_reg_write(IXP2000_GPIO_LSLR, 0);
- ixp2000_reg_write(IXP2000_GPIO_INCR, -1);
-
- /* clear PCI interrupt sources */
- ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, 0);
-
- /*
- * Certain bits in the IRQ status register of the
- * IXP2000 are reserved. Instead of trying to map
- * things non 1:1 from bit position to IRQ number,
- * we mark the reserved IRQs as invalid. This makes
- * our mask/unmask code much simpler.
- */
- for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) {
- if ((1 << irq) & IXP2000_VALID_IRQ_MASK) {
- irq_set_chip_and_handler(irq, &ixp2000_irq_chip,
- handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- } else set_irq_flags(irq, 0);
- }
-
- for (irq = IRQ_IXP2000_DRAM0_MIN_ERR; irq <= IRQ_IXP2000_SP_INT; irq++) {
- if((1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)) &
- IXP2000_VALID_ERR_IRQ_MASK) {
- irq_set_chip_and_handler(irq, &ixp2000_err_irq_chip,
- handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- }
- else
- set_irq_flags(irq, 0);
- }
- irq_set_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler);
-
- for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) {
- irq_set_chip_and_handler(irq, &ixp2000_GPIO_irq_chip,
- handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- }
- irq_set_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler);
-
- /*
- * Enable PCI irqs. The actual PCI[AB] decoding is done in
- * entry-macro.S, so we don't need a chained handler for the
- * PCI interrupt source.
- */
- ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << IRQ_IXP2000_PCI));
- for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) {
- irq_set_chip_and_handler(irq, &ixp2000_pci_irq_chip,
- handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- }
-}
-
-void ixp2000_restart(char mode, const char *cmd)
-{
- ixp2000_reg_wrb(IXP2000_RESET0, RSTALL);
-}
diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
deleted file mode 100644
index 4867f408617c..000000000000
--- a/arch/arm/mach-ixp2000/enp2611.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/enp2611.c
- *
- * Radisys ENP-2611 support.
- *
- * Created 2004 by Lennert Buytenhek from the ixdp2x01 code. The
- * original version carries the following notices:
- *
- * Original Author: Andrzej Mialkowski <andrzej.mialkowski@intel.com>
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright (C) 2002-2003 Intel Corp.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-
-#include <asm/mach/pci.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-
-/*************************************************************************
- * ENP-2611 timer tick configuration
- *************************************************************************/
-static void __init enp2611_timer_init(void)
-{
- ixp2000_init_time(50 * 1000 * 1000);
-}
-
-static struct sys_timer enp2611_timer = {
- .init = enp2611_timer_init,
- .offset = ixp2000_gettimeoffset,
-};
-
-
-/*************************************************************************
- * ENP-2611 I/O
- *************************************************************************/
-static struct map_desc enp2611_io_desc[] __initdata = {
- {
- .virtual = ENP2611_CALEB_VIRT_BASE,
- .pfn = __phys_to_pfn(ENP2611_CALEB_PHYS_BASE),
- .length = ENP2611_CALEB_SIZE,
- .type = MT_DEVICE,
- }, {
- .virtual = ENP2611_PM3386_0_VIRT_BASE,
- .pfn = __phys_to_pfn(ENP2611_PM3386_0_PHYS_BASE),
- .length = ENP2611_PM3386_0_SIZE,
- .type = MT_DEVICE,
- }, {
- .virtual = ENP2611_PM3386_1_VIRT_BASE,
- .pfn = __phys_to_pfn(ENP2611_PM3386_1_PHYS_BASE),
- .length = ENP2611_PM3386_1_SIZE,
- .type = MT_DEVICE,
- }
-};
-
-void __init enp2611_map_io(void)
-{
- ixp2000_map_io();
- iotable_init(enp2611_io_desc, ARRAY_SIZE(enp2611_io_desc));
-}
-
-
-/*************************************************************************
- * ENP-2611 PCI
- *************************************************************************/
-static int enp2611_pci_setup(int nr, struct pci_sys_data *sys)
-{
- sys->mem_offset = 0xe0000000;
- ixp2000_pci_setup(nr, sys);
- return 1;
-}
-
-static void __init enp2611_pci_preinit(void)
-{
- ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000);
- ixp2000_pci_preinit();
- pcibios_setup("firmware");
-}
-
-static inline int enp2611_pci_valid_device(struct pci_bus *bus,
- unsigned int devfn)
-{
- /* The 82559 ethernet controller appears at both PCI:1:0:0 and
- * PCI:1:2:0, so let's pretend the second one isn't there.
- */
- if (bus->number == 0x01 && devfn == 0x10)
- return 0;
-
- return 1;
-}
-
-static int enp2611_pci_read_config(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 *value)
-{
- if (enp2611_pci_valid_device(bus, devfn))
- return ixp2000_pci_read_config(bus, devfn, where, size, value);
-
- return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static int enp2611_pci_write_config(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 value)
-{
- if (enp2611_pci_valid_device(bus, devfn))
- return ixp2000_pci_write_config(bus, devfn, where, size, value);
-
- return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static struct pci_ops enp2611_pci_ops = {
- .read = enp2611_pci_read_config,
- .write = enp2611_pci_write_config
-};
-
-static struct pci_bus * __init enp2611_pci_scan_bus(int nr,
- struct pci_sys_data *sys)
-{
- return pci_scan_root_bus(NULL, sys->busnr, &enp2611_pci_ops, sys,
- &sys->resources);
-}
-
-static int __init enp2611_pci_map_irq(const struct pci_dev *dev, u8 slot,
- u8 pin)
-{
- int irq;
-
- if (dev->bus->number == 0 && PCI_SLOT(dev->devfn) == 0) {
- /* IXP2400. */
- irq = IRQ_IXP2000_PCIA;
- } else if (dev->bus->number == 0 && PCI_SLOT(dev->devfn) == 1) {
- /* 21555 non-transparent bridge. */
- irq = IRQ_IXP2000_PCIB;
- } else if (dev->bus->number == 0 && PCI_SLOT(dev->devfn) == 4) {
- /* PCI2050B transparent bridge. */
- irq = -1;
- } else if (dev->bus->number == 1 && PCI_SLOT(dev->devfn) == 0) {
- /* 82559 ethernet. */
- irq = IRQ_IXP2000_PCIA;
- } else if (dev->bus->number == 1 && PCI_SLOT(dev->devfn) == 1) {
- /* SPI-3 option board. */
- irq = IRQ_IXP2000_PCIB;
- } else {
- printk(KERN_ERR "enp2611_pci_map_irq() called for unknown "
- "device PCI:%d:%d:%d\n", dev->bus->number,
- PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
- irq = -1;
- }
-
- return irq;
-}
-
-struct hw_pci enp2611_pci __initdata = {
- .nr_controllers = 1,
- .setup = enp2611_pci_setup,
- .preinit = enp2611_pci_preinit,
- .scan = enp2611_pci_scan_bus,
- .map_irq = enp2611_pci_map_irq,
-};
-
-int __init enp2611_pci_init(void)
-{
- if (machine_is_enp2611())
- pci_common_init(&enp2611_pci);
-
- return 0;
-}
-
-subsys_initcall(enp2611_pci_init);
-
-
-/*************************************************************************
- * ENP-2611 Machine Initialization
- *************************************************************************/
-static struct flash_platform_data enp2611_flash_platform_data = {
- .map_name = "cfi_probe",
- .width = 1,
-};
-
-static struct ixp2000_flash_data enp2611_flash_data = {
- .platform_data = &enp2611_flash_platform_data,
- .nr_banks = 1
-};
-
-static struct resource enp2611_flash_resource = {
- .start = 0xc4000000,
- .end = 0xc4000000 + 0x00ffffff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device enp2611_flash = {
- .name = "IXP2000-Flash",
- .id = 0,
- .dev = {
- .platform_data = &enp2611_flash_data,
- },
- .num_resources = 1,
- .resource = &enp2611_flash_resource,
-};
-
-static struct ixp2000_i2c_pins enp2611_i2c_gpio_pins = {
- .sda_pin = ENP2611_GPIO_SDA,
- .scl_pin = ENP2611_GPIO_SCL,
-};
-
-static struct platform_device enp2611_i2c_controller = {
- .name = "IXP2000-I2C",
- .id = 0,
- .dev = {
- .platform_data = &enp2611_i2c_gpio_pins
- },
- .num_resources = 0
-};
-
-static struct platform_device *enp2611_devices[] __initdata = {
- &enp2611_flash,
- &enp2611_i2c_controller
-};
-
-static void __init enp2611_init_machine(void)
-{
- platform_add_devices(enp2611_devices, ARRAY_SIZE(enp2611_devices));
- ixp2000_uart_init();
-}
-
-
-MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
- /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .atag_offset = 0x100,
- .map_io = enp2611_map_io,
- .init_irq = ixp2000_init_irq,
- .timer = &enp2611_timer,
- .init_machine = enp2611_init_machine,
- .restart = ixp2000_restart,
-MACHINE_END
-
-
diff --git a/arch/arm/mach-ixp2000/include/mach/debug-macro.S b/arch/arm/mach-ixp2000/include/mach/debug-macro.S
deleted file mode 100644
index bdd3ccdc2890..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/debug-macro.S
+++ /dev/null
@@ -1,25 +0,0 @@
-/* arch/arm/mach-ixp2000/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- * Copyright (C) 1994-1999 Russell King
- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
- .macro addruart, rp, rv, tmp
- mov \rp, #0x00030000
-#ifdef __ARMEB__
- orr \rp, \rp, #0x00000003
-#endif
- orr \rv, \rp, #0xfe000000 @ virtual base
- orr \rv, \rv, #0x00f00000
- orr \rp, \rp, #0xc0000000 @ Physical base
- .endm
-
-#define UART_SHIFT 2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-ixp2000/include/mach/enp2611.h b/arch/arm/mach-ixp2000/include/mach/enp2611.h
deleted file mode 100644
index 9ce3690061d5..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/enp2611.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/enp2611.h
- *
- * Register and other defines for Radisys ENP-2611
- *
- * Created 2004 by Lennert Buytenhek from the ixdp2x01 code. The
- * original version carries the following notices:
- *
- * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright (C) 2002 Intel Corp.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef __ENP2611_H
-#define __ENP2611_H
-
-#define ENP2611_CALEB_PHYS_BASE 0xc5000000
-#define ENP2611_CALEB_VIRT_BASE 0xfe000000
-#define ENP2611_CALEB_SIZE 0x00100000
-
-#define ENP2611_PM3386_0_PHYS_BASE 0xc6000000
-#define ENP2611_PM3386_0_VIRT_BASE 0xfe100000
-#define ENP2611_PM3386_0_SIZE 0x00100000
-
-#define ENP2611_PM3386_1_PHYS_BASE 0xc6400000
-#define ENP2611_PM3386_1_VIRT_BASE 0xfe200000
-#define ENP2611_PM3386_1_SIZE 0x00100000
-
-#define ENP2611_GPIO_SCL 7
-#define ENP2611_GPIO_SDA 6
-
-#define IRQ_ENP2611_THERMAL IRQ_IXP2000_GPIO4
-#define IRQ_ENP2611_OPTION_BOARD IRQ_IXP2000_GPIO3
-#define IRQ_ENP2611_CALEB IRQ_IXP2000_GPIO2
-#define IRQ_ENP2611_PM3386_1 IRQ_IXP2000_GPIO1
-#define IRQ_ENP2611_PM3386_0 IRQ_IXP2000_GPIO0
-
-
-#endif
diff --git a/arch/arm/mach-ixp2000/include/mach/entry-macro.S b/arch/arm/mach-ixp2000/include/mach/entry-macro.S
deleted file mode 100644
index c4444dff9202..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/entry-macro.S
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for IXP2000-based platforms
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <mach/irqs.h>
-
- .macro get_irqnr_preamble, base, tmp
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-
- mov \irqnr, #0x0 @clear out irqnr as default
- mov \base, #0xfe000000
- orr \base, \base, #0x00e00000
- orr \base, \base, #0x08
- ldr \irqstat, [\base] @ get interrupts
-
- cmp \irqstat, #0
- beq 1001f
-
- clz \irqnr, \irqstat
- mov \base, #31
- subs \irqnr, \base, \irqnr
-
- /*
- * We handle PCIA and PCIB here so we don't have an
- * extra layer of code just to check these two bits.
- */
- cmp \irqnr, #IRQ_IXP2000_PCI
- bne 1001f
-
- mov \base, #0xfe000000
- orr \base, \base, #0x00c00000
- orr \base, \base, #0x00000100
- orr \base, \base, #0x00000058
- ldr \irqstat, [\base]
-
- mov \tmp, #(1<<26)
- tst \irqstat, \tmp
- movne \irqnr, #IRQ_IXP2000_PCIA
- bne 1001f
-
- mov \tmp, #(1<<27)
- tst \irqstat, \tmp
- movne \irqnr, #IRQ_IXP2000_PCIB
-
-1001:
- .endm
-
diff --git a/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h b/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h
deleted file mode 100644
index af836c76c3f1..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/gpio.h
- *
- * Copyright (C) 2002 Intel Corporation.
- *
- * This program is free software, you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/*
- * IXP2000 GPIO in/out, edge/level detection for IRQs:
- * IRQs are generated on Falling-edge, Rising-Edge, Level-low, Level-High
- * or both Falling-edge and Rising-edge.
- * This must be called *before* the corresponding IRQ is registerd.
- * Use this instead of directly setting the GPIO registers.
- * GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb)
- */
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#ifndef __ASSEMBLY__
-
-#define GPIO_IN 0
-#define GPIO_OUT 1
-
-#define IXP2000_GPIO_LOW 0
-#define IXP2000_GPIO_HIGH 1
-
-extern void gpio_line_config(int line, int direction);
-
-static inline int gpio_line_get(int line)
-{
- return (((*IXP2000_GPIO_PLR) >> line) & 1);
-}
-
-static inline void gpio_line_set(int line, int value)
-{
- if (value == IXP2000_GPIO_HIGH) {
- ixp2000_reg_write(IXP2000_GPIO_POSR, 1 << line);
- } else if (value == IXP2000_GPIO_LOW) {
- ixp2000_reg_write(IXP2000_GPIO_POCR, 1 << line);
- }
-}
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* ASM_ARCH_IXP2000_GPIO_H_ */
diff --git a/arch/arm/mach-ixp2000/include/mach/hardware.h b/arch/arm/mach-ixp2000/include/mach/hardware.h
deleted file mode 100644
index cdaf1db84003..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/hardware.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/hardware.h
- *
- * Hardware definitions for IXP2400/2800 based systems
- *
- * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
- *
- * Maintainer: Deepak Saxena <dsaxena@mvista.com>
- *
- * Copyright (C) 2001-2002 Intel Corp.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H__
-#define __ASM_ARCH_HARDWARE_H__
-
-#include "ixp2000-regs.h" /* Chipset Registers */
-
-/*
- * Platform helper functions
- */
-#include "platform.h"
-
-/*
- * Platform-specific bits
- */
-#include "enp2611.h" /* ENP-2611 */
-#include "ixdp2x00.h" /* IXDP2400/2800 */
-#include "ixdp2x01.h" /* IXDP2401/2801 */
-
-#endif /* _ASM_ARCH_HARDWARE_H__ */
diff --git a/arch/arm/mach-ixp2000/include/mach/io.h b/arch/arm/mach-ixp2000/include/mach/io.h
deleted file mode 100644
index f6552d6f35ab..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/io.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/io.h
- *
- * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright (C) 2002 Intel Corp.
- * Copyrgiht (C) 2003-2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#include <mach/hardware.h>
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * The A? revisions of the IXP2000s assert byte lanes for PCI I/O
- * transactions the other way round (MEM transactions don't have this
- * issue), so if we want to support those models, we need to override
- * the standard I/O functions.
- *
- * B0 and later have a bit that can be set to 1 to get the proper
- * behavior for I/O transactions, which then allows us to use the
- * standard I/O functions. This is what we do if the user does not
- * explicitly ask for support for pre-B0.
- */
-#ifdef CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO
-#define ___io(p) ((void __iomem *)((p)+IXP2000_PCI_IO_VIRT_BASE))
-
-#define alignb(addr) (void __iomem *)((unsigned long)(addr) ^ 3)
-#define alignw(addr) (void __iomem *)((unsigned long)(addr) ^ 2)
-
-#define outb(v,p) __raw_writeb((v),alignb(___io(p)))
-#define outw(v,p) __raw_writew((v),alignw(___io(p)))
-#define outl(v,p) __raw_writel((v),___io(p))
-
-#define inb(p) ({ unsigned int __v = __raw_readb(alignb(___io(p))); __v; })
-#define inw(p) \
- ({ unsigned int __v = (__raw_readw(alignw(___io(p)))); __v; })
-#define inl(p) \
- ({ unsigned int __v = (__raw_readl(___io(p))); __v; })
-
-#define outsb(p,d,l) __raw_writesb(alignb(___io(p)),d,l)
-#define outsw(p,d,l) __raw_writesw(alignw(___io(p)),d,l)
-#define outsl(p,d,l) __raw_writesl(___io(p),d,l)
-
-#define insb(p,d,l) __raw_readsb(alignb(___io(p)),d,l)
-#define insw(p,d,l) __raw_readsw(alignw(___io(p)),d,l)
-#define insl(p,d,l) __raw_readsl(___io(p),d,l)
-
-#define __is_io_address(p) ((((unsigned long)(p)) & ~(IXP2000_PCI_IO_SIZE - 1)) == IXP2000_PCI_IO_VIRT_BASE)
-
-#define ioread8(p) \
- ({ \
- unsigned int __v; \
- \
- if (__is_io_address(p)) { \
- __v = __raw_readb(alignb(p)); \
- } else { \
- __v = __raw_readb(p); \
- } \
- \
- __v; \
- }) \
-
-#define ioread16(p) \
- ({ \
- unsigned int __v; \
- \
- if (__is_io_address(p)) { \
- __v = __raw_readw(alignw(p)); \
- } else { \
- __v = le16_to_cpu(__raw_readw(p)); \
- } \
- \
- __v; \
- })
-
-#define ioread32(p) \
- ({ \
- unsigned int __v; \
- \
- if (__is_io_address(p)) { \
- __v = __raw_readl(p); \
- } else { \
- __v = le32_to_cpu(__raw_readl(p)); \
- } \
- \
- __v; \
- })
-
-#define iowrite8(v,p) \
- ({ \
- if (__is_io_address(p)) { \
- __raw_writeb((v), alignb(p)); \
- } else { \
- __raw_writeb((v), p); \
- } \
- })
-
-#define iowrite16(v,p) \
- ({ \
- if (__is_io_address(p)) { \
- __raw_writew((v), alignw(p)); \
- } else { \
- __raw_writew(cpu_to_le16(v), p); \
- } \
- })
-
-#define iowrite32(v,p) \
- ({ \
- if (__is_io_address(p)) { \
- __raw_writel((v), p); \
- } else { \
- __raw_writel(cpu_to_le32(v), p); \
- } \
- })
-
-#define ioport_map(port, nr) ___io(port)
-
-#define ioport_unmap(addr)
-#else
-#define __io(p) ((void __iomem *)((p)+IXP2000_PCI_IO_VIRT_BASE))
-#endif
-
-
-#endif
diff --git a/arch/arm/mach-ixp2000/include/mach/irqs.h b/arch/arm/mach-ixp2000/include/mach/irqs.h
deleted file mode 100644
index bee96bcafdca..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/irqs.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/irqs.h
- *
- * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright (C) 2002 Intel Corp.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _IRQS_H
-#define _IRQS_H
-
-/*
- * Do NOT add #ifdef MACHINE_FOO in here.
- * Simpy add your machine IRQs here and increase NR_IRQS if needed to
- * hold your machine's IRQ table.
- */
-
-/*
- * Some interrupt numbers go unused b/c the IRQ mask/ummask/status
- * register has those bit reserved. We just mark those interrupts
- * as invalid and this allows us to do mask/unmask with a single
- * shift operation instead of having to map the IRQ number to
- * a HW IRQ number.
- */
-#define IRQ_IXP2000_SOFT_INT 0 /* soft interrupt */
-#define IRQ_IXP2000_ERRSUM 1 /* OR of all bits in ErrorStatus reg*/
-#define IRQ_IXP2000_UART 2
-#define IRQ_IXP2000_GPIO 3
-#define IRQ_IXP2000_TIMER1 4
-#define IRQ_IXP2000_TIMER2 5
-#define IRQ_IXP2000_TIMER3 6
-#define IRQ_IXP2000_TIMER4 7
-#define IRQ_IXP2000_PMU 8
-#define IRQ_IXP2000_SPF 9 /* Slow port framer IRQ */
-#define IRQ_IXP2000_DMA1 10
-#define IRQ_IXP2000_DMA2 11
-#define IRQ_IXP2000_DMA3 12
-#define IRQ_IXP2000_PCI_DOORBELL 13
-#define IRQ_IXP2000_ME_ATTN 14
-#define IRQ_IXP2000_PCI 15 /* PCI INTA or INTB */
-#define IRQ_IXP2000_THDA0 16 /* thread 0-31A */
-#define IRQ_IXP2000_THDA1 17 /* thread 32-63A, IXP2800 only */
-#define IRQ_IXP2000_THDA2 18 /* thread 64-95A */
-#define IRQ_IXP2000_THDA3 19 /* thread 96-127A, IXP2800 only */
-#define IRQ_IXP2000_THDB0 24 /* thread 0-31B */
-#define IRQ_IXP2000_THDB1 25 /* thread 32-63B, IXP2800 only */
-#define IRQ_IXP2000_THDB2 26 /* thread 64-95B */
-#define IRQ_IXP2000_THDB3 27 /* thread 96-127B, IXP2800 only */
-
-/* define generic GPIOs */
-#define IRQ_IXP2000_GPIO0 32
-#define IRQ_IXP2000_GPIO1 33
-#define IRQ_IXP2000_GPIO2 34
-#define IRQ_IXP2000_GPIO3 35
-#define IRQ_IXP2000_GPIO4 36
-#define IRQ_IXP2000_GPIO5 37
-#define IRQ_IXP2000_GPIO6 38
-#define IRQ_IXP2000_GPIO7 39
-
-/* split off the 2 PCI sources */
-#define IRQ_IXP2000_PCIA 40
-#define IRQ_IXP2000_PCIB 41
-
-/* Int sources from IRQ_ERROR_STATUS */
-#define IRQ_IXP2000_DRAM0_MIN_ERR 42
-#define IRQ_IXP2000_DRAM0_MAJ_ERR 43
-#define IRQ_IXP2000_DRAM1_MIN_ERR 44
-#define IRQ_IXP2000_DRAM1_MAJ_ERR 45
-#define IRQ_IXP2000_DRAM2_MIN_ERR 46
-#define IRQ_IXP2000_DRAM2_MAJ_ERR 47
-/* 48-57 reserved */
-#define IRQ_IXP2000_SRAM0_ERR 58
-#define IRQ_IXP2000_SRAM1_ERR 59
-#define IRQ_IXP2000_SRAM2_ERR 60
-#define IRQ_IXP2000_SRAM3_ERR 61
-/* 62-65 reserved */
-#define IRQ_IXP2000_MEDIA_ERR 66
-#define IRQ_IXP2000_PCI_ERR 67
-#define IRQ_IXP2000_SP_INT 68
-
-#define NR_IXP2000_IRQS 69
-
-#define IXP2000_BOARD_IRQ(x) (NR_IXP2000_IRQS + (x))
-
-#define IXP2000_BOARD_IRQ_MASK(irq) (1 << (irq - NR_IXP2000_IRQS))
-
-#define IXP2000_ERR_IRQ_MASK(irq) ( 1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR))
-#define IXP2000_VALID_ERR_IRQ_MASK (\
- IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM0_MIN_ERR) | \
- IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM0_MAJ_ERR) | \
- IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM1_MIN_ERR) | \
- IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM1_MAJ_ERR) | \
- IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM2_MIN_ERR) | \
- IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM2_MAJ_ERR) | \
- IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SRAM0_ERR) | \
- IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SRAM1_ERR) | \
- IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SRAM2_ERR) | \
- IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SRAM3_ERR) | \
- IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_MEDIA_ERR) | \
- IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_PCI_ERR) | \
- IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SP_INT) )
-
-/*
- * This allows for all the on-chip sources plus up to 32 CPLD based
- * IRQs. Should be more than enough.
- */
-#define IXP2000_BOARD_IRQS 32
-#define NR_IRQS (NR_IXP2000_IRQS + IXP2000_BOARD_IRQS)
-
-
-/*
- * IXDP2400 specific IRQs
- */
-#define IRQ_IXDP2400_INGRESS_NPU IXP2000_BOARD_IRQ(0)
-#define IRQ_IXDP2400_ENET IXP2000_BOARD_IRQ(1)
-#define IRQ_IXDP2400_MEDIA_PCI IXP2000_BOARD_IRQ(2)
-#define IRQ_IXDP2400_MEDIA_SP IXP2000_BOARD_IRQ(3)
-#define IRQ_IXDP2400_SF_PCI IXP2000_BOARD_IRQ(4)
-#define IRQ_IXDP2400_SF_SP IXP2000_BOARD_IRQ(5)
-#define IRQ_IXDP2400_PMC IXP2000_BOARD_IRQ(6)
-#define IRQ_IXDP2400_TVM IXP2000_BOARD_IRQ(7)
-
-#define NR_IXDP2400_IRQS ((IRQ_IXDP2400_TVM)+1)
-#define IXDP2400_NR_IRQS NR_IXDP2400_IRQS - NR_IXP2000_IRQS
-
-/* IXDP2800 specific IRQs */
-#define IRQ_IXDP2800_EGRESS_ENET IXP2000_BOARD_IRQ(0)
-#define IRQ_IXDP2800_INGRESS_NPU IXP2000_BOARD_IRQ(1)
-#define IRQ_IXDP2800_PMC IXP2000_BOARD_IRQ(2)
-#define IRQ_IXDP2800_FABRIC_PCI IXP2000_BOARD_IRQ(3)
-#define IRQ_IXDP2800_FABRIC IXP2000_BOARD_IRQ(4)
-#define IRQ_IXDP2800_MEDIA IXP2000_BOARD_IRQ(5)
-
-#define NR_IXDP2800_IRQS ((IRQ_IXDP2800_MEDIA)+1)
-#define IXDP2800_NR_IRQS NR_IXDP2800_IRQS - NR_IXP2000_IRQS
-
-/*
- * IRQs on both IXDP2x01 boards
- */
-#define IRQ_IXDP2X01_SPCI_DB_0 IXP2000_BOARD_IRQ(2)
-#define IRQ_IXDP2X01_SPCI_DB_1 IXP2000_BOARD_IRQ(3)
-#define IRQ_IXDP2X01_SPCI_PMC_INTA IXP2000_BOARD_IRQ(4)
-#define IRQ_IXDP2X01_SPCI_PMC_INTB IXP2000_BOARD_IRQ(5)
-#define IRQ_IXDP2X01_SPCI_PMC_INTC IXP2000_BOARD_IRQ(6)
-#define IRQ_IXDP2X01_SPCI_PMC_INTD IXP2000_BOARD_IRQ(7)
-#define IRQ_IXDP2X01_SPCI_FIC_INT IXP2000_BOARD_IRQ(8)
-#define IRQ_IXDP2X01_IPMI_FROM IXP2000_BOARD_IRQ(16)
-#define IRQ_IXDP2X01_125US IXP2000_BOARD_IRQ(17)
-#define IRQ_IXDP2X01_DB_0_ADD IXP2000_BOARD_IRQ(18)
-#define IRQ_IXDP2X01_DB_1_ADD IXP2000_BOARD_IRQ(19)
-#define IRQ_IXDP2X01_UART1 IXP2000_BOARD_IRQ(21)
-#define IRQ_IXDP2X01_UART2 IXP2000_BOARD_IRQ(22)
-#define IRQ_IXDP2X01_FIC_ADD_INT IXP2000_BOARD_IRQ(24)
-#define IRQ_IXDP2X01_CS8900 IXP2000_BOARD_IRQ(25)
-#define IRQ_IXDP2X01_BBSRAM IXP2000_BOARD_IRQ(26)
-
-#define IXDP2X01_VALID_IRQ_MASK ( \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_DB_0) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_DB_1) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_PMC_INTA) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_PMC_INTB) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_PMC_INTC) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_PMC_INTD) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_FIC_INT) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_IPMI_FROM) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_125US) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_DB_0_ADD) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_DB_1_ADD) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_UART1) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_UART2) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_FIC_ADD_INT) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_CS8900) | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_BBSRAM) )
-
-/*
- * IXDP2401 specific IRQs
- */
-#define IRQ_IXDP2401_INTA_82546 IXP2000_BOARD_IRQ(0)
-#define IRQ_IXDP2401_INTB_82546 IXP2000_BOARD_IRQ(1)
-
-#define IXDP2401_VALID_IRQ_MASK ( \
- IXDP2X01_VALID_IRQ_MASK | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2401_INTA_82546) |\
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2401_INTB_82546))
-
-/*
- * IXDP2801-specific IRQs
- */
-#define IRQ_IXDP2801_RIV IXP2000_BOARD_IRQ(0)
-#define IRQ_IXDP2801_CNFG_MEDIA IXP2000_BOARD_IRQ(27)
-#define IRQ_IXDP2801_CLOCK_REF IXP2000_BOARD_IRQ(28)
-
-#define IXDP2801_VALID_IRQ_MASK ( \
- IXDP2X01_VALID_IRQ_MASK | \
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2801_RIV) |\
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2801_CNFG_MEDIA) |\
- IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2801_CLOCK_REF))
-
-#define NR_IXDP2X01_IRQS ((IRQ_IXDP2801_CLOCK_REF) + 1)
-
-#endif /*_IRQS_H*/
diff --git a/arch/arm/mach-ixp2000/include/mach/ixdp2x00.h b/arch/arm/mach-ixp2000/include/mach/ixdp2x00.h
deleted file mode 100644
index 5df8479d9481..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/ixdp2x00.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/ixdp2x00.h
- *
- * Register and other defines for IXDP2[48]00 platforms
- *
- * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright (C) 2002 Intel Corp.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#ifndef _IXDP2X00_H_
-#define _IXDP2X00_H_
-
-/*
- * On board CPLD memory map
- */
-#define IXDP2X00_PHYS_CPLD_BASE 0xc7000000
-#define IXDP2X00_VIRT_CPLD_BASE 0xfe000000
-#define IXDP2X00_CPLD_SIZE 0x00100000
-
-
-#define IXDP2X00_CPLD_REG(x) \
- (volatile unsigned long *)(IXDP2X00_VIRT_CPLD_BASE | x)
-
-/*
- * IXDP2400 CPLD registers
- */
-#define IXDP2400_CPLD_SYSLED IXDP2X00_CPLD_REG(0x0)
-#define IXDP2400_CPLD_DISP_DATA IXDP2X00_CPLD_REG(0x4)
-#define IXDP2400_CPLD_CLOCK_SPEED IXDP2X00_CPLD_REG(0x8)
-#define IXDP2400_CPLD_INT_STAT IXDP2X00_CPLD_REG(0xc)
-#define IXDP2400_CPLD_REV IXDP2X00_CPLD_REG(0x10)
-#define IXDP2400_CPLD_SYS_CLK_M IXDP2X00_CPLD_REG(0x14)
-#define IXDP2400_CPLD_SYS_CLK_N IXDP2X00_CPLD_REG(0x18)
-#define IXDP2400_CPLD_INT_MASK IXDP2X00_CPLD_REG(0x48)
-
-/*
- * IXDP2800 CPLD registers
- */
-#define IXDP2800_CPLD_INT_STAT IXDP2X00_CPLD_REG(0x0)
-#define IXDP2800_CPLD_INT_MASK IXDP2X00_CPLD_REG(0x140)
-
-
-#define IXDP2X00_GPIO_I2C_ENABLE 0x02
-#define IXDP2X00_GPIO_SCL 0x07
-#define IXDP2X00_GPIO_SDA 0x06
-
-/*
- * PCI devfns for on-board devices. We need these to be able to
- * properly translate IRQs and for device removal.
- */
-#define IXDP2400_SLAVE_ENET_DEVFN 0x18 /* Bus 1 */
-#define IXDP2400_MASTER_ENET_DEVFN 0x20 /* Bus 1 */
-#define IXDP2400_MEDIA_DEVFN 0x28 /* Bus 1 */
-#define IXDP2400_SWITCH_FABRIC_DEVFN 0x30 /* Bus 1 */
-
-#define IXDP2800_SLAVE_ENET_DEVFN 0x20 /* Bus 1 */
-#define IXDP2800_MASTER_ENET_DEVFN 0x18 /* Bus 1 */
-#define IXDP2800_SWITCH_FABRIC_DEVFN 0x30 /* Bus 1 */
-
-#define IXDP2X00_P2P_DEVFN 0x20 /* Bus 0 */
-#define IXDP2X00_21555_DEVFN 0x30 /* Bus 0 */
-#define IXDP2X00_SLAVE_NPU_DEVFN 0x28 /* Bus 1 */
-#define IXDP2X00_PMC_DEVFN 0x38 /* Bus 1 */
-#define IXDP2X00_MASTER_NPU_DEVFN 0x38 /* Bus 1 */
-
-#ifndef __ASSEMBLY__
-/*
- * The master NPU is always PCI master.
- */
-static inline unsigned int ixdp2x00_master_npu(void)
-{
- return !!ixp2000_is_pcimaster();
-}
-
-/*
- * Helper functions used by ixdp2400 and ixdp2800 specific code
- */
-void ixdp2x00_init_irq(volatile unsigned long*, volatile unsigned long *, unsigned long);
-void ixdp2x00_slave_pci_postinit(void);
-void ixdp2x00_init_machine(void);
-void ixdp2x00_map_io(void);
-
-#endif
-
-#endif /*_IXDP2X00_H_ */
diff --git a/arch/arm/mach-ixp2000/include/mach/ixdp2x01.h b/arch/arm/mach-ixp2000/include/mach/ixdp2x01.h
deleted file mode 100644
index 4c1f04083e54..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/ixdp2x01.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/ixdp2x01.h
- *
- * Platform definitions for IXDP2X01 && IXDP2801 systems
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright 2004 (c) MontaVista Software, Inc.
- *
- * Based on original code Copyright (c) 2002-2003 Intel Corporation
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __IXDP2X01_H__
-#define __IXDP2X01_H__
-
-#define IXDP2X01_PHYS_CPLD_BASE 0xc6024000
-#define IXDP2X01_VIRT_CPLD_BASE 0xfe000000
-#define IXDP2X01_CPLD_REGION_SIZE 0x00100000
-
-#define IXDP2X01_CPLD_VIRT_REG(reg) (volatile unsigned long*)(IXDP2X01_VIRT_CPLD_BASE | reg)
-#define IXDP2X01_CPLD_PHYS_REG(reg) (IXDP2X01_PHYS_CPLD_BASE | reg)
-
-#define IXDP2X01_UART1_VIRT_BASE IXDP2X01_CPLD_VIRT_REG(0x40)
-#define IXDP2X01_UART1_PHYS_BASE IXDP2X01_CPLD_PHYS_REG(0x40)
-
-#define IXDP2X01_UART2_VIRT_BASE IXDP2X01_CPLD_VIRT_REG(0x60)
-#define IXDP2X01_UART2_PHYS_BASE IXDP2X01_CPLD_PHYS_REG(0x60)
-
-#define IXDP2X01_CS8900_VIRT_BASE IXDP2X01_CPLD_VIRT_REG(0x80)
-#define IXDP2X01_CS8900_VIRT_END (IXDP2X01_CS8900_VIRT_BASE + 16)
-
-#define IXDP2X01_CPLD_RESET_REG IXDP2X01_CPLD_VIRT_REG(0x00)
-#define IXDP2X01_INT_MASK_SET_REG IXDP2X01_CPLD_VIRT_REG(0x08)
-#define IXDP2X01_INT_STAT_REG IXDP2X01_CPLD_VIRT_REG(0x0C)
-#define IXDP2X01_INT_RAW_REG IXDP2X01_CPLD_VIRT_REG(0x10)
-#define IXDP2X01_INT_MASK_CLR_REG IXDP2X01_INT_RAW_REG
-#define IXDP2X01_INT_SIM_REG IXDP2X01_CPLD_VIRT_REG(0x14)
-
-#define IXDP2X01_CPLD_FLASH_REG IXDP2X01_CPLD_VIRT_REG(0x20)
-
-#define IXDP2X01_CPLD_FLASH_INTERN 0x8000
-#define IXDP2X01_CPLD_FLASH_BANK_MASK 0xF
-#define IXDP2X01_FLASH_WINDOW_BITS 25
-#define IXDP2X01_FLASH_WINDOW_SIZE (1 << IXDP2X01_FLASH_WINDOW_BITS)
-#define IXDP2X01_FLASH_WINDOW_MASK (IXDP2X01_FLASH_WINDOW_SIZE - 1)
-
-#define IXDP2X01_UART_CLK 1843200
-
-#define IXDP2X01_GPIO_I2C_ENABLE 0x02
-#define IXDP2X01_GPIO_SCL 0x07
-#define IXDP2X01_GPIO_SDA 0x06
-
-#endif /* __IXDP2x01_H__ */
diff --git a/arch/arm/mach-ixp2000/include/mach/ixp2000-regs.h b/arch/arm/mach-ixp2000/include/mach/ixp2000-regs.h
deleted file mode 100644
index 822f63f2f4a2..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/ixp2000-regs.h
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/ixp2000-regs.h
- *
- * Chipset register definitions for IXP2400/2800 based systems.
- *
- * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
- *
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright (C) 2002 Intel Corp.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#ifndef _IXP2000_REGS_H_
-#define _IXP2000_REGS_H_
-
-/*
- * IXP2000 linux memory map:
- *
- * virt phys size
- * fb000000 db000000 16M PCI CFG1
- * fc000000 da000000 16M PCI CFG0
- * fd000000 d8000000 16M PCI I/O
- * fe[0-7]00000 8M per-platform mappings
- * fe900000 80000000 1M SRAM #0 (first MB)
- * fea00000 cb400000 1M SCRATCH ring get/put
- * feb00000 c8000000 1M MSF
- * fec00000 df000000 1M PCI CSRs
- * fed00000 de000000 1M PCI CREG
- * fee00000 d6000000 1M INTCTL
- * fef00000 c0000000 1M CAP
- */
-
-/*
- * Static I/O regions.
- *
- * Most of the registers are clumped in 4K regions spread throughout
- * the 0xc0000000 -> 0xc0100000 address range, but we just map in
- * the whole range using a single 1 MB section instead of small
- * 4K pages.
- *
- * CAP stands for CSR Access Proxy.
- *
- * If you change the virtual address of this mapping, please propagate
- * the change to arch/arm/kernel/debug.S, which hardcodes the virtual
- * address of the UART located in this region.
- */
-
-#define IXP2000_CAP_PHYS_BASE 0xc0000000
-#define IXP2000_CAP_VIRT_BASE 0xfef00000
-#define IXP2000_CAP_SIZE 0x00100000
-
-/*
- * Addresses for specific on-chip peripherals.
- */
-#define IXP2000_SLOWPORT_CSR_VIRT_BASE 0xfef80000
-#define IXP2000_GLOBAL_REG_VIRT_BASE 0xfef04000
-#define IXP2000_UART_PHYS_BASE 0xc0030000
-#define IXP2000_UART_VIRT_BASE 0xfef30000
-#define IXP2000_TIMER_VIRT_BASE 0xfef20000
-#define IXP2000_UENGINE_CSR_VIRT_BASE 0xfef18000
-#define IXP2000_GPIO_VIRT_BASE 0xfef10000
-
-/*
- * Devices outside of the 0xc0000000 -> 0xc0100000 range. The virtual
- * addresses of the INTCTL and PCI_CSR mappings are hardcoded in
- * entry-macro.S, so if you ever change these please propagate
- * the change.
- */
-#define IXP2000_INTCTL_PHYS_BASE 0xd6000000
-#define IXP2000_INTCTL_VIRT_BASE 0xfee00000
-#define IXP2000_INTCTL_SIZE 0x00100000
-
-#define IXP2000_PCI_CREG_PHYS_BASE 0xde000000
-#define IXP2000_PCI_CREG_VIRT_BASE 0xfed00000
-#define IXP2000_PCI_CREG_SIZE 0x00100000
-
-#define IXP2000_PCI_CSR_PHYS_BASE 0xdf000000
-#define IXP2000_PCI_CSR_VIRT_BASE 0xfec00000
-#define IXP2000_PCI_CSR_SIZE 0x00100000
-
-#define IXP2000_MSF_PHYS_BASE 0xc8000000
-#define IXP2000_MSF_VIRT_BASE 0xfeb00000
-#define IXP2000_MSF_SIZE 0x00100000
-
-#define IXP2000_SCRATCH_RING_PHYS_BASE 0xcb400000
-#define IXP2000_SCRATCH_RING_VIRT_BASE 0xfea00000
-#define IXP2000_SCRATCH_RING_SIZE 0x00100000
-
-#define IXP2000_SRAM0_PHYS_BASE 0x80000000
-#define IXP2000_SRAM0_VIRT_BASE 0xfe900000
-#define IXP2000_SRAM0_SIZE 0x00100000
-
-#define IXP2000_PCI_IO_PHYS_BASE 0xd8000000
-#define IXP2000_PCI_IO_VIRT_BASE 0xfd000000
-#define IXP2000_PCI_IO_SIZE 0x01000000
-
-#define IXP2000_PCI_CFG0_PHYS_BASE 0xda000000
-#define IXP2000_PCI_CFG0_VIRT_BASE 0xfc000000
-#define IXP2000_PCI_CFG0_SIZE 0x01000000
-
-#define IXP2000_PCI_CFG1_PHYS_BASE 0xdb000000
-#define IXP2000_PCI_CFG1_VIRT_BASE 0xfb000000
-#define IXP2000_PCI_CFG1_SIZE 0x01000000
-
-/*
- * Timers
- */
-#define IXP2000_TIMER_REG(x) ((volatile unsigned long*)(IXP2000_TIMER_VIRT_BASE | (x)))
-/* Timer control */
-#define IXP2000_T1_CTL IXP2000_TIMER_REG(0x00)
-#define IXP2000_T2_CTL IXP2000_TIMER_REG(0x04)
-#define IXP2000_T3_CTL IXP2000_TIMER_REG(0x08)
-#define IXP2000_T4_CTL IXP2000_TIMER_REG(0x0c)
-/* Store initial value */
-#define IXP2000_T1_CLD IXP2000_TIMER_REG(0x10)
-#define IXP2000_T2_CLD IXP2000_TIMER_REG(0x14)
-#define IXP2000_T3_CLD IXP2000_TIMER_REG(0x18)
-#define IXP2000_T4_CLD IXP2000_TIMER_REG(0x1c)
-/* Read current value */
-#define IXP2000_T1_CSR IXP2000_TIMER_REG(0x20)
-#define IXP2000_T2_CSR IXP2000_TIMER_REG(0x24)
-#define IXP2000_T3_CSR IXP2000_TIMER_REG(0x28)
-#define IXP2000_T4_CSR IXP2000_TIMER_REG(0x2c)
-/* Clear associated timer interrupt */
-#define IXP2000_T1_CLR IXP2000_TIMER_REG(0x30)
-#define IXP2000_T2_CLR IXP2000_TIMER_REG(0x34)
-#define IXP2000_T3_CLR IXP2000_TIMER_REG(0x38)
-#define IXP2000_T4_CLR IXP2000_TIMER_REG(0x3c)
-/* Timer watchdog enable for T4 */
-#define IXP2000_TWDE IXP2000_TIMER_REG(0x40)
-
-#define WDT_ENABLE 0x00000001
-#define TIMER_DIVIDER_256 0x00000008
-#define TIMER_ENABLE 0x00000080
-#define IRQ_MASK_TIMER1 (1 << 4)
-
-/*
- * Interrupt controller registers
- */
-#define IXP2000_INTCTL_REG(x) (volatile unsigned long*)(IXP2000_INTCTL_VIRT_BASE | (x))
-#define IXP2000_IRQ_STATUS IXP2000_INTCTL_REG(0x08)
-#define IXP2000_IRQ_ENABLE IXP2000_INTCTL_REG(0x10)
-#define IXP2000_IRQ_ENABLE_SET IXP2000_INTCTL_REG(0x10)
-#define IXP2000_IRQ_ENABLE_CLR IXP2000_INTCTL_REG(0x18)
-#define IXP2000_FIQ_ENABLE_CLR IXP2000_INTCTL_REG(0x14)
-#define IXP2000_IRQ_ERR_STATUS IXP2000_INTCTL_REG(0x24)
-#define IXP2000_IRQ_ERR_ENABLE_SET IXP2000_INTCTL_REG(0x2c)
-#define IXP2000_FIQ_ERR_ENABLE_CLR IXP2000_INTCTL_REG(0x30)
-#define IXP2000_IRQ_ERR_ENABLE_CLR IXP2000_INTCTL_REG(0x34)
-#define IXP2000_IRQ_THD_RAW_STATUS_A_0 IXP2000_INTCTL_REG(0x60)
-#define IXP2000_IRQ_THD_RAW_STATUS_A_1 IXP2000_INTCTL_REG(0x64)
-#define IXP2000_IRQ_THD_RAW_STATUS_A_2 IXP2000_INTCTL_REG(0x68)
-#define IXP2000_IRQ_THD_RAW_STATUS_A_3 IXP2000_INTCTL_REG(0x6c)
-#define IXP2000_IRQ_THD_RAW_STATUS_B_0 IXP2000_INTCTL_REG(0x80)
-#define IXP2000_IRQ_THD_RAW_STATUS_B_1 IXP2000_INTCTL_REG(0x84)
-#define IXP2000_IRQ_THD_RAW_STATUS_B_2 IXP2000_INTCTL_REG(0x88)
-#define IXP2000_IRQ_THD_RAW_STATUS_B_3 IXP2000_INTCTL_REG(0x8c)
-#define IXP2000_IRQ_THD_STATUS_A_0 IXP2000_INTCTL_REG(0xe0)
-#define IXP2000_IRQ_THD_STATUS_A_1 IXP2000_INTCTL_REG(0xe4)
-#define IXP2000_IRQ_THD_STATUS_A_2 IXP2000_INTCTL_REG(0xe8)
-#define IXP2000_IRQ_THD_STATUS_A_3 IXP2000_INTCTL_REG(0xec)
-#define IXP2000_IRQ_THD_STATUS_B_0 IXP2000_INTCTL_REG(0x100)
-#define IXP2000_IRQ_THD_STATUS_B_1 IXP2000_INTCTL_REG(0x104)
-#define IXP2000_IRQ_THD_STATUS_B_2 IXP2000_INTCTL_REG(0x108)
-#define IXP2000_IRQ_THD_STATUS_B_3 IXP2000_INTCTL_REG(0x10c)
-#define IXP2000_IRQ_THD_ENABLE_SET_A_0 IXP2000_INTCTL_REG(0x160)
-#define IXP2000_IRQ_THD_ENABLE_SET_A_1 IXP2000_INTCTL_REG(0x164)
-#define IXP2000_IRQ_THD_ENABLE_SET_A_2 IXP2000_INTCTL_REG(0x168)
-#define IXP2000_IRQ_THD_ENABLE_SET_A_3 IXP2000_INTCTL_REG(0x16c)
-#define IXP2000_IRQ_THD_ENABLE_SET_B_0 IXP2000_INTCTL_REG(0x180)
-#define IXP2000_IRQ_THD_ENABLE_SET_B_1 IXP2000_INTCTL_REG(0x184)
-#define IXP2000_IRQ_THD_ENABLE_SET_B_2 IXP2000_INTCTL_REG(0x188)
-#define IXP2000_IRQ_THD_ENABLE_SET_B_3 IXP2000_INTCTL_REG(0x18c)
-#define IXP2000_IRQ_THD_ENABLE_CLEAR_A_0 IXP2000_INTCTL_REG(0x1e0)
-#define IXP2000_IRQ_THD_ENABLE_CLEAR_A_1 IXP2000_INTCTL_REG(0x1e4)
-#define IXP2000_IRQ_THD_ENABLE_CLEAR_A_2 IXP2000_INTCTL_REG(0x1e8)
-#define IXP2000_IRQ_THD_ENABLE_CLEAR_A_3 IXP2000_INTCTL_REG(0x1ec)
-#define IXP2000_IRQ_THD_ENABLE_CLEAR_B_0 IXP2000_INTCTL_REG(0x200)
-#define IXP2000_IRQ_THD_ENABLE_CLEAR_B_1 IXP2000_INTCTL_REG(0x204)
-#define IXP2000_IRQ_THD_ENABLE_CLEAR_B_2 IXP2000_INTCTL_REG(0x208)
-#define IXP2000_IRQ_THD_ENABLE_CLEAR_B_3 IXP2000_INTCTL_REG(0x20c)
-
-/*
- * Mask of valid IRQs in the 32-bit IRQ register. We use
- * this to mark certain IRQs as being invalid.
- */
-#define IXP2000_VALID_IRQ_MASK 0x0f0fffff
-
-/*
- * PCI config register access from core
- */
-#define IXP2000_PCI_CREG(x) (volatile unsigned long*)(IXP2000_PCI_CREG_VIRT_BASE | (x))
-#define IXP2000_PCI_CMDSTAT IXP2000_PCI_CREG(0x04)
-#define IXP2000_PCI_CSR_BAR IXP2000_PCI_CREG(0x10)
-#define IXP2000_PCI_SRAM_BAR IXP2000_PCI_CREG(0x14)
-#define IXP2000_PCI_SDRAM_BAR IXP2000_PCI_CREG(0x18)
-
-/*
- * PCI CSRs
- */
-#define IXP2000_PCI_CSR(x) (volatile unsigned long*)(IXP2000_PCI_CSR_VIRT_BASE | (x))
-
-/*
- * PCI outbound interrupts
- */
-#define IXP2000_PCI_OUT_INT_STATUS IXP2000_PCI_CSR(0x30)
-#define IXP2000_PCI_OUT_INT_MASK IXP2000_PCI_CSR(0x34)
-/*
- * PCI communications
- */
-#define IXP2000_PCI_MAILBOX0 IXP2000_PCI_CSR(0x50)
-#define IXP2000_PCI_MAILBOX1 IXP2000_PCI_CSR(0x54)
-#define IXP2000_PCI_MAILBOX2 IXP2000_PCI_CSR(0x58)
-#define IXP2000_PCI_MAILBOX3 IXP2000_PCI_CSR(0x5C)
-#define IXP2000_XSCALE_DOORBELL IXP2000_PCI_CSR(0x60)
-#define IXP2000_XSCALE_DOORBELL_SETUP IXP2000_PCI_CSR(0x64)
-#define IXP2000_PCI_DOORBELL IXP2000_PCI_CSR(0x70)
-#define IXP2000_PCI_DOORBELL_SETUP IXP2000_PCI_CSR(0x74)
-
-/*
- * DMA engines
- */
-#define IXP2000_PCI_CH1_BYTE_CNT IXP2000_PCI_CSR(0x80)
-#define IXP2000_PCI_CH1_ADDR IXP2000_PCI_CSR(0x84)
-#define IXP2000_PCI_CH1_DRAM_ADDR IXP2000_PCI_CSR(0x88)
-#define IXP2000_PCI_CH1_DESC_PTR IXP2000_PCI_CSR(0x8C)
-#define IXP2000_PCI_CH1_CNTRL IXP2000_PCI_CSR(0x90)
-#define IXP2000_PCI_CH1_ME_PARAM IXP2000_PCI_CSR(0x94)
-#define IXP2000_PCI_CH2_BYTE_CNT IXP2000_PCI_CSR(0xA0)
-#define IXP2000_PCI_CH2_ADDR IXP2000_PCI_CSR(0xA4)
-#define IXP2000_PCI_CH2_DRAM_ADDR IXP2000_PCI_CSR(0xA8)
-#define IXP2000_PCI_CH2_DESC_PTR IXP2000_PCI_CSR(0xAC)
-#define IXP2000_PCI_CH2_CNTRL IXP2000_PCI_CSR(0xB0)
-#define IXP2000_PCI_CH2_ME_PARAM IXP2000_PCI_CSR(0xB4)
-#define IXP2000_PCI_CH3_BYTE_CNT IXP2000_PCI_CSR(0xC0)
-#define IXP2000_PCI_CH3_ADDR IXP2000_PCI_CSR(0xC4)
-#define IXP2000_PCI_CH3_DRAM_ADDR IXP2000_PCI_CSR(0xC8)
-#define IXP2000_PCI_CH3_DESC_PTR IXP2000_PCI_CSR(0xCC)
-#define IXP2000_PCI_CH3_CNTRL IXP2000_PCI_CSR(0xD0)
-#define IXP2000_PCI_CH3_ME_PARAM IXP2000_PCI_CSR(0xD4)
-#define IXP2000_DMA_INF_MODE IXP2000_PCI_CSR(0xE0)
-/*
- * Size masks for BARs
- */
-#define IXP2000_PCI_SRAM_BASE_ADDR_MASK IXP2000_PCI_CSR(0xFC)
-#define IXP2000_PCI_DRAM_BASE_ADDR_MASK IXP2000_PCI_CSR(0x100)
-/*
- * Control and uEngine related
- */
-#define IXP2000_PCI_CONTROL IXP2000_PCI_CSR(0x13C)
-#define IXP2000_PCI_ADDR_EXT IXP2000_PCI_CSR(0x140)
-#define IXP2000_PCI_ME_PUSH_STATUS IXP2000_PCI_CSR(0x148)
-#define IXP2000_PCI_ME_PUSH_EN IXP2000_PCI_CSR(0x14C)
-#define IXP2000_PCI_ERR_STATUS IXP2000_PCI_CSR(0x150)
-#define IXP2000_PCI_ERR_ENABLE IXP2000_PCI_CSR(0x154)
-/*
- * Inbound PCI interrupt control
- */
-#define IXP2000_PCI_XSCALE_INT_STATUS IXP2000_PCI_CSR(0x158)
-#define IXP2000_PCI_XSCALE_INT_ENABLE IXP2000_PCI_CSR(0x15C)
-
-#define IXP2000_PCICNTL_PNR (1<<17) /* PCI not Reset bit of PCI_CONTROL */
-#define IXP2000_PCICNTL_PCF (1<<28) /* PCI Central function bit */
-#define IXP2000_XSCALE_INT (1<<1) /* Interrupt from XScale to PCI */
-
-/* These are from the IRQ register in the PCI ISR register */
-#define PCI_CONTROL_BE_DEO (1 << 22) /* Big Endian Data Enable Out */
-#define PCI_CONTROL_BE_DEI (1 << 21) /* Big Endian Data Enable In */
-#define PCI_CONTROL_BE_BEO (1 << 20) /* Big Endian Byte Enable Out */
-#define PCI_CONTROL_BE_BEI (1 << 19) /* Big Endian Byte Enable In */
-#define PCI_CONTROL_IEE (1 << 17) /* I/O cycle Endian swap Enable */
-
-#define IXP2000_PCI_RST_REL (1 << 2)
-#define CFG_RST_DIR (*IXP2000_PCI_CONTROL & IXP2000_PCICNTL_PCF)
-#define CFG_PCI_BOOT_HOST (1 << 2)
-#define CFG_BOOT_PROM (1 << 1)
-
-/*
- * SlowPort CSRs
- *
- * The slowport is used to access things like flash, SONET framer control
- * ports, slave microprocessors, CPLDs, and others of chip memory mapped
- * peripherals.
- */
-#define SLOWPORT_CSR(x) (volatile unsigned long*)(IXP2000_SLOWPORT_CSR_VIRT_BASE | (x))
-
-#define IXP2000_SLOWPORT_CCR SLOWPORT_CSR(0x00)
-#define IXP2000_SLOWPORT_WTC1 SLOWPORT_CSR(0x04)
-#define IXP2000_SLOWPORT_WTC2 SLOWPORT_CSR(0x08)
-#define IXP2000_SLOWPORT_RTC1 SLOWPORT_CSR(0x0c)
-#define IXP2000_SLOWPORT_RTC2 SLOWPORT_CSR(0x10)
-#define IXP2000_SLOWPORT_FSR SLOWPORT_CSR(0x14)
-#define IXP2000_SLOWPORT_PCR SLOWPORT_CSR(0x18)
-#define IXP2000_SLOWPORT_ADC SLOWPORT_CSR(0x1C)
-#define IXP2000_SLOWPORT_FAC SLOWPORT_CSR(0x20)
-#define IXP2000_SLOWPORT_FRM SLOWPORT_CSR(0x24)
-#define IXP2000_SLOWPORT_FIN SLOWPORT_CSR(0x28)
-
-/*
- * CCR values.
- * The CCR configures the clock division for the slowport interface.
- */
-#define SLOWPORT_CCR_DIV_1 0x00
-#define SLOWPORT_CCR_DIV_2 0x01
-#define SLOWPORT_CCR_DIV_4 0x02
-#define SLOWPORT_CCR_DIV_6 0x03
-#define SLOWPORT_CCR_DIV_8 0x04
-#define SLOWPORT_CCR_DIV_10 0x05
-#define SLOWPORT_CCR_DIV_12 0x06
-#define SLOWPORT_CCR_DIV_14 0x07
-#define SLOWPORT_CCR_DIV_16 0x08
-#define SLOWPORT_CCR_DIV_18 0x09
-#define SLOWPORT_CCR_DIV_20 0x0a
-#define SLOWPORT_CCR_DIV_22 0x0b
-#define SLOWPORT_CCR_DIV_24 0x0c
-#define SLOWPORT_CCR_DIV_26 0x0d
-#define SLOWPORT_CCR_DIV_28 0x0e
-#define SLOWPORT_CCR_DIV_30 0x0f
-
-/*
- * PCR values. PCR configure the mode of the interface.
- */
-#define SLOWPORT_MODE_FLASH 0x00
-#define SLOWPORT_MODE_LUCENT 0x01
-#define SLOWPORT_MODE_PMC_SIERRA 0x02
-#define SLOWPORT_MODE_INTEL_UP 0x03
-#define SLOWPORT_MODE_MOTOROLA_UP 0x04
-
-/*
- * ADC values. Defines data and address bus widths.
- */
-#define SLOWPORT_ADDR_WIDTH_8 0x00
-#define SLOWPORT_ADDR_WIDTH_16 0x01
-#define SLOWPORT_ADDR_WIDTH_24 0x02
-#define SLOWPORT_ADDR_WIDTH_32 0x03
-#define SLOWPORT_DATA_WIDTH_8 0x00
-#define SLOWPORT_DATA_WIDTH_16 0x10
-#define SLOWPORT_DATA_WIDTH_24 0x20
-#define SLOWPORT_DATA_WIDTH_32 0x30
-
-/*
- * Masks and shifts for various fields in the WTC and RTC registers.
- */
-#define SLOWPORT_WRTC_MASK_HD 0x0003
-#define SLOWPORT_WRTC_MASK_PW 0x003c
-#define SLOWPORT_WRTC_MASK_SU 0x03c0
-
-#define SLOWPORT_WRTC_SHIFT_HD 0x00
-#define SLOWPORT_WRTC_SHIFT_SU 0x02
-#define SLOWPORT_WRTC_SHFIT_PW 0x06
-
-
-/*
- * GPIO registers & GPIO interface.
- */
-#define IXP2000_GPIO_REG(x) ((volatile unsigned long*)(IXP2000_GPIO_VIRT_BASE+(x)))
-#define IXP2000_GPIO_PLR IXP2000_GPIO_REG(0x00)
-#define IXP2000_GPIO_PDPR IXP2000_GPIO_REG(0x04)
-#define IXP2000_GPIO_PDSR IXP2000_GPIO_REG(0x08)
-#define IXP2000_GPIO_PDCR IXP2000_GPIO_REG(0x0c)
-#define IXP2000_GPIO_POPR IXP2000_GPIO_REG(0x10)
-#define IXP2000_GPIO_POSR IXP2000_GPIO_REG(0x14)
-#define IXP2000_GPIO_POCR IXP2000_GPIO_REG(0x18)
-#define IXP2000_GPIO_REDR IXP2000_GPIO_REG(0x1c)
-#define IXP2000_GPIO_FEDR IXP2000_GPIO_REG(0x20)
-#define IXP2000_GPIO_EDSR IXP2000_GPIO_REG(0x24)
-#define IXP2000_GPIO_LSHR IXP2000_GPIO_REG(0x28)
-#define IXP2000_GPIO_LSLR IXP2000_GPIO_REG(0x2c)
-#define IXP2000_GPIO_LDSR IXP2000_GPIO_REG(0x30)
-#define IXP2000_GPIO_INER IXP2000_GPIO_REG(0x34)
-#define IXP2000_GPIO_INSR IXP2000_GPIO_REG(0x38)
-#define IXP2000_GPIO_INCR IXP2000_GPIO_REG(0x3c)
-#define IXP2000_GPIO_INST IXP2000_GPIO_REG(0x40)
-
-/*
- * "Global" registers...whatever that's supposed to mean.
- */
-#define GLOBAL_REG_BASE (IXP2000_GLOBAL_REG_VIRT_BASE + 0x0a00)
-#define GLOBAL_REG(x) (volatile unsigned long*)(GLOBAL_REG_BASE | (x))
-
-#define IXP2000_MAJ_PROD_TYPE_MASK 0x001F0000
-#define IXP2000_MAJ_PROD_TYPE_IXP2000 0x00000000
-#define IXP2000_MIN_PROD_TYPE_MASK 0x0000FF00
-#define IXP2000_MIN_PROD_TYPE_IXP2400 0x00000200
-#define IXP2000_MIN_PROD_TYPE_IXP2850 0x00000100
-#define IXP2000_MIN_PROD_TYPE_IXP2800 0x00000000
-#define IXP2000_MAJ_REV_MASK 0x000000F0
-#define IXP2000_MIN_REV_MASK 0x0000000F
-#define IXP2000_PROD_ID_MASK 0xFFFFFFFF
-
-#define IXP2000_PRODUCT_ID GLOBAL_REG(0x00)
-#define IXP2000_MISC_CONTROL GLOBAL_REG(0x04)
-#define IXP2000_MSF_CLK_CNTRL GLOBAL_REG(0x08)
-#define IXP2000_RESET0 GLOBAL_REG(0x0c)
-#define IXP2000_RESET1 GLOBAL_REG(0x10)
-#define IXP2000_CCR GLOBAL_REG(0x14)
-#define IXP2000_STRAP_OPTIONS GLOBAL_REG(0x18)
-
-#define RSTALL (1 << 16)
-#define WDT_RESET_ENABLE 0x01000000
-
-
-/*
- * MSF registers. The IXP2400 and IXP2800 have somewhat different MSF
- * units, but the registers that differ between the two don't overlap,
- * so we can have one register list for both.
- */
-#define IXP2000_MSF_REG(x) ((volatile unsigned long*)(IXP2000_MSF_VIRT_BASE + (x)))
-#define IXP2000_MSF_RX_CONTROL IXP2000_MSF_REG(0x0000)
-#define IXP2000_MSF_TX_CONTROL IXP2000_MSF_REG(0x0004)
-#define IXP2000_MSF_INTERRUPT_STATUS IXP2000_MSF_REG(0x0008)
-#define IXP2000_MSF_INTERRUPT_ENABLE IXP2000_MSF_REG(0x000c)
-#define IXP2000_MSF_CSIX_TYPE_MAP IXP2000_MSF_REG(0x0010)
-#define IXP2000_MSF_FC_EGRESS_STATUS IXP2000_MSF_REG(0x0014)
-#define IXP2000_MSF_FC_INGRESS_STATUS IXP2000_MSF_REG(0x0018)
-#define IXP2000_MSF_HWM_CONTROL IXP2000_MSF_REG(0x0024)
-#define IXP2000_MSF_FC_STATUS_OVERRIDE IXP2000_MSF_REG(0x0028)
-#define IXP2000_MSF_CLOCK_CONTROL IXP2000_MSF_REG(0x002c)
-#define IXP2000_MSF_RX_PORT_MAP IXP2000_MSF_REG(0x0040)
-#define IXP2000_MSF_RBUF_ELEMENT_DONE IXP2000_MSF_REG(0x0044)
-#define IXP2000_MSF_RX_MPHY_POLL_LIMIT IXP2000_MSF_REG(0x0048)
-#define IXP2000_MSF_RX_CALENDAR_LENGTH IXP2000_MSF_REG(0x0048)
-#define IXP2000_MSF_RX_THREAD_FREELIST_TIMEOUT_0 IXP2000_MSF_REG(0x0050)
-#define IXP2000_MSF_RX_THREAD_FREELIST_TIMEOUT_1 IXP2000_MSF_REG(0x0054)
-#define IXP2000_MSF_RX_THREAD_FREELIST_TIMEOUT_2 IXP2000_MSF_REG(0x0058)
-#define IXP2000_MSF_TX_SEQUENCE_0 IXP2000_MSF_REG(0x0060)
-#define IXP2000_MSF_TX_SEQUENCE_1 IXP2000_MSF_REG(0x0064)
-#define IXP2000_MSF_TX_SEQUENCE_2 IXP2000_MSF_REG(0x0068)
-#define IXP2000_MSF_TX_MPHY_POLL_LIMIT IXP2000_MSF_REG(0x0070)
-#define IXP2000_MSF_TX_CALENDAR_LENGTH IXP2000_MSF_REG(0x0070)
-#define IXP2000_MSF_RX_UP_CONTROL_0 IXP2000_MSF_REG(0x0080)
-#define IXP2000_MSF_RX_UP_CONTROL_1 IXP2000_MSF_REG(0x0084)
-#define IXP2000_MSF_RX_UP_CONTROL_2 IXP2000_MSF_REG(0x0088)
-#define IXP2000_MSF_RX_UP_CONTROL_3 IXP2000_MSF_REG(0x008c)
-#define IXP2000_MSF_TX_UP_CONTROL_0 IXP2000_MSF_REG(0x0090)
-#define IXP2000_MSF_TX_UP_CONTROL_1 IXP2000_MSF_REG(0x0094)
-#define IXP2000_MSF_TX_UP_CONTROL_2 IXP2000_MSF_REG(0x0098)
-#define IXP2000_MSF_TX_UP_CONTROL_3 IXP2000_MSF_REG(0x009c)
-#define IXP2000_MSF_TRAIN_DATA IXP2000_MSF_REG(0x00a0)
-#define IXP2000_MSF_TRAIN_CALENDAR IXP2000_MSF_REG(0x00a4)
-#define IXP2000_MSF_TRAIN_FLOW_CONTROL IXP2000_MSF_REG(0x00a8)
-#define IXP2000_MSF_TX_CALENDAR_0 IXP2000_MSF_REG(0x1000)
-#define IXP2000_MSF_RX_PORT_CALENDAR_STATUS IXP2000_MSF_REG(0x1400)
-
-
-#endif /* _IXP2000_H_ */
diff --git a/arch/arm/mach-ixp2000/include/mach/memory.h b/arch/arm/mach-ixp2000/include/mach/memory.h
deleted file mode 100644
index 5f0c4fd4076a..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/memory.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/memory.h
- *
- * Copyright (c) 2002 Intel Corp.
- * Copyright (c) 2003-2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#include <mach/ixp2000-regs.h>
-
-#define IXP2000_PCI_SDRAM_OFFSET (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0)
-
-#define __phys_to_bus(x) ((x) + (IXP2000_PCI_SDRAM_OFFSET - PHYS_OFFSET))
-#define __bus_to_phys(x) ((x) - (IXP2000_PCI_SDRAM_OFFSET - PHYS_OFFSET))
-
-#define __virt_to_bus(v) __phys_to_bus(__virt_to_phys(v))
-#define __bus_to_virt(b) __phys_to_virt(__bus_to_phys(b))
-#define __pfn_to_bus(p) __phys_to_bus(__pfn_to_phys(p))
-#define __bus_to_pfn(b) __phys_to_pfn(__bus_to_phys(b))
-
-#endif
-
diff --git a/arch/arm/mach-ixp2000/include/mach/platform.h b/arch/arm/mach-ixp2000/include/mach/platform.h
deleted file mode 100644
index bb0f8dcf9ee1..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/platform.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/platform.h
- *
- * Various bits of code used by platform-level code.
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright 2004 (c) MontaVista Software, Inc.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-
-#ifndef __ASSEMBLY__
-
-static inline unsigned long ixp2000_reg_read(volatile void *reg)
-{
- return *((volatile unsigned long *)reg);
-}
-
-static inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
-{
- *((volatile unsigned long *)reg) = val;
-}
-
-/*
- * On the IXP2400, we can't use XCB=000 due to chip bugs. We use
- * XCB=101 instead, but that makes all I/O accesses bufferable. This
- * is not a problem in general, but we do have to be slightly more
- * careful because I/O writes are no longer automatically flushed out
- * of the write buffer.
- *
- * In cases where we want to make sure that a write has been flushed
- * out of the write buffer before we proceed, for example when masking
- * a device interrupt before re-enabling IRQs in CPSR, we can use this
- * function, ixp2000_reg_wrb, which performs a write, a readback, and
- * issues a dummy instruction dependent on the value of the readback
- * (mov rX, rX) to make sure that the readback has completed before we
- * continue.
- */
-static inline void ixp2000_reg_wrb(volatile void *reg, unsigned long val)
-{
- unsigned long dummy;
-
- *((volatile unsigned long *)reg) = val;
-
- dummy = *((volatile unsigned long *)reg);
- __asm__ __volatile__("mov %0, %0" : "+r" (dummy));
-}
-
-/*
- * Boards may multiplex different devices on the 2nd channel of
- * the slowport interface that each need different configuration
- * settings. For example, the IXDP2400 uses channel 2 on the interface
- * to access the CPLD, the switch fabric card, and the media card. Each
- * one needs a different mode so drivers must save/restore the mode
- * before and after each operation.
- *
- * acquire_slowport(&your_config);
- * ...
- * do slowport operations
- * ...
- * release_slowport();
- *
- * Note that while you have the slowport, you are holding a spinlock,
- * so your code should be written as if you explicitly acquired a lock.
- *
- * The configuration only affects device 2 on the slowport, so the
- * MTD map driver does not acquire/release the slowport.
- */
-struct slowport_cfg {
- unsigned long CCR; /* Clock divide */
- unsigned long WTC; /* Write Timing Control */
- unsigned long RTC; /* Read Timing Control */
- unsigned long PCR; /* Protocol Control Register */
- unsigned long ADC; /* Address/Data Width Control */
-};
-
-
-void ixp2000_acquire_slowport(struct slowport_cfg *, struct slowport_cfg *);
-void ixp2000_release_slowport(struct slowport_cfg *);
-
-/*
- * IXP2400 A0/A1 and IXP2800 A0/A1/A2 have broken slowport that requires
- * tweaking of addresses in the MTD driver.
- */
-static inline unsigned ixp2000_has_broken_slowport(void)
-{
- unsigned long id = *IXP2000_PRODUCT_ID;
- unsigned long id_prod = id & (IXP2000_MAJ_PROD_TYPE_MASK |
- IXP2000_MIN_PROD_TYPE_MASK);
- return (((id_prod ==
- /* fixed in IXP2400-B0 */
- (IXP2000_MAJ_PROD_TYPE_IXP2000 |
- IXP2000_MIN_PROD_TYPE_IXP2400)) &&
- ((id & IXP2000_MAJ_REV_MASK) == 0)) ||
- ((id_prod ==
- /* fixed in IXP2800-B0 */
- (IXP2000_MAJ_PROD_TYPE_IXP2000 |
- IXP2000_MIN_PROD_TYPE_IXP2800)) &&
- ((id & IXP2000_MAJ_REV_MASK) == 0)) ||
- ((id_prod ==
- /* fixed in IXP2850-B0 */
- (IXP2000_MAJ_PROD_TYPE_IXP2000 |
- IXP2000_MIN_PROD_TYPE_IXP2850)) &&
- ((id & IXP2000_MAJ_REV_MASK) == 0)));
-}
-
-static inline unsigned int ixp2000_has_flash(void)
-{
- return ((*IXP2000_STRAP_OPTIONS) & (CFG_BOOT_PROM));
-}
-
-static inline unsigned int ixp2000_is_pcimaster(void)
-{
- return ((*IXP2000_STRAP_OPTIONS) & (CFG_PCI_BOOT_HOST));
-}
-
-void ixp2000_map_io(void);
-void ixp2000_uart_init(void);
-void ixp2000_init_irq(void);
-void ixp2000_init_time(unsigned long);
-void ixp2000_restart(char, const char *);
-unsigned long ixp2000_gettimeoffset(void);
-
-struct pci_sys_data;
-
-u32 *ixp2000_pci_config_addr(unsigned int bus, unsigned int devfn, int where);
-void ixp2000_pci_preinit(void);
-int ixp2000_pci_setup(int, struct pci_sys_data*);
-struct pci_bus* ixp2000_pci_scan_bus(int, struct pci_sys_data*);
-int ixp2000_pci_read_config(struct pci_bus*, unsigned int, int, int, u32 *);
-int ixp2000_pci_write_config(struct pci_bus*, unsigned int, int, int, u32);
-
-/*
- * Several of the IXP2000 systems have banked flash so we need to extend the
- * flash_platform_data structure with some private pointers
- */
-struct ixp2000_flash_data {
- struct flash_platform_data *platform_data;
- int nr_banks;
- unsigned long (*bank_setup)(unsigned long);
-};
-
-struct ixp2000_i2c_pins {
- unsigned long sda_pin;
- unsigned long scl_pin;
-};
-
-
-#endif /* !__ASSEMBLY__ */
diff --git a/arch/arm/mach-ixp2000/include/mach/timex.h b/arch/arm/mach-ixp2000/include/mach/timex.h
deleted file mode 100644
index 835e659f93d4..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/timex.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/timex.h
- *
- * IXP2000 architecture timex specifications
- */
-
-
-/*
- * Default clock is 50MHz APB, but platform code can override this
- */
-#define CLOCK_TICK_RATE 50000000
-
-
diff --git a/arch/arm/mach-ixp2000/include/mach/uncompress.h b/arch/arm/mach-ixp2000/include/mach/uncompress.h
deleted file mode 100644
index ce363087df78..000000000000
--- a/arch/arm/mach-ixp2000/include/mach/uncompress.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/uncompress.h
- *
- *
- * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright 2002 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/serial_reg.h>
-
-#define UART_BASE 0xc0030000
-
-#define PHYS(x) ((volatile unsigned long *)(UART_BASE + x))
-
-#define UARTDR PHYS(0x00) /* Transmit reg dlab=0 */
-#define UARTDLL PHYS(0x00) /* Divisor Latch reg dlab=1*/
-#define UARTDLM PHYS(0x04) /* Divisor Latch reg dlab=1*/
-#define UARTIER PHYS(0x04) /* Interrupt enable reg */
-#define UARTFCR PHYS(0x08) /* FIFO control reg dlab =0*/
-#define UARTLCR PHYS(0x0c) /* Control reg */
-#define UARTSR PHYS(0x14) /* Status reg */
-
-
-static inline void putc(int c)
-{
- int j = 0x1000;
-
- while (--j && !(*UARTSR & UART_LSR_THRE))
- barrier();
-
- *UARTDR = c;
-}
-
-static inline void flush(void)
-{
-}
-
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c
deleted file mode 100644
index 915ad49e3b8f..000000000000
--- a/arch/arm/mach-ixp2000/ixdp2400.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/ixdp2400.c
- *
- * IXDP2400 platform support
- *
- * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright (C) 2002 Intel Corp.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/bitops.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-
-#include <asm/mach/pci.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-#include <asm/mach/flash.h>
-#include <asm/mach/arch.h>
-
-/*************************************************************************
- * IXDP2400 timer tick
- *************************************************************************/
-static void __init ixdp2400_timer_init(void)
-{
- int numerator, denominator;
- int denom_array[] = {2, 4, 8, 16, 1, 2, 4, 8};
-
- numerator = (*(IXDP2400_CPLD_SYS_CLK_M) & 0xFF) *2;
- denominator = denom_array[(*(IXDP2400_CPLD_SYS_CLK_N) & 0x7)];
-
- ixp2000_init_time(((3125000 * numerator) / (denominator)) / 2);
-}
-
-static struct sys_timer ixdp2400_timer = {
- .init = ixdp2400_timer_init,
- .offset = ixp2000_gettimeoffset,
-};
-
-/*************************************************************************
- * IXDP2400 PCI
- *************************************************************************/
-void __init ixdp2400_pci_preinit(void)
-{
- ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000);
- ixp2000_pci_preinit();
- pcibios_setup("firmware");
-}
-
-int ixdp2400_pci_setup(int nr, struct pci_sys_data *sys)
-{
- sys->mem_offset = 0xe0000000;
-
- ixp2000_pci_setup(nr, sys);
-
- return 1;
-}
-
-static int __init ixdp2400_pci_map_irq(const struct pci_dev *dev, u8 slot,
- u8 pin)
-{
- if (ixdp2x00_master_npu()) {
-
- /*
- * Root bus devices. Slave NPU is only one with interrupt.
- * Everything else, we just return -1 b/c nothing else
- * on the root bus has interrupts.
- */
- if(!dev->bus->self) {
- if(dev->devfn == IXDP2X00_SLAVE_NPU_DEVFN )
- return IRQ_IXDP2400_INGRESS_NPU;
-
- return -1;
- }
-
- /*
- * Bridge behind the PMC slot.
- * NOTE: Only INTA from the PMC slot is routed. VERY BAD.
- */
- if(dev->bus->self->devfn == IXDP2X00_PMC_DEVFN &&
- dev->bus->parent->self->devfn == IXDP2X00_P2P_DEVFN &&
- !dev->bus->parent->self->bus->parent)
- return IRQ_IXDP2400_PMC;
-
- /*
- * Device behind the first bridge
- */
- if(dev->bus->self->devfn == IXDP2X00_P2P_DEVFN) {
- switch(dev->devfn) {
- case IXDP2400_MASTER_ENET_DEVFN:
- return IRQ_IXDP2400_ENET;
-
- case IXDP2400_MEDIA_DEVFN:
- return IRQ_IXDP2400_MEDIA_PCI;
-
- case IXDP2400_SWITCH_FABRIC_DEVFN:
- return IRQ_IXDP2400_SF_PCI;
-
- case IXDP2X00_PMC_DEVFN:
- return IRQ_IXDP2400_PMC;
- }
- }
-
- return -1;
- } else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */
-}
-
-
-static void ixdp2400_pci_postinit(void)
-{
- struct pci_dev *dev;
-
- if (ixdp2x00_master_npu()) {
- dev = pci_get_bus_and_slot(1, IXDP2400_SLAVE_ENET_DEVFN);
- pci_stop_and_remove_bus_device(dev);
- pci_dev_put(dev);
- } else {
- dev = pci_get_bus_and_slot(1, IXDP2400_MASTER_ENET_DEVFN);
- pci_stop_and_remove_bus_device(dev);
- pci_dev_put(dev);
-
- ixdp2x00_slave_pci_postinit();
- }
-}
-
-static struct hw_pci ixdp2400_pci __initdata = {
- .nr_controllers = 1,
- .setup = ixdp2400_pci_setup,
- .preinit = ixdp2400_pci_preinit,
- .postinit = ixdp2400_pci_postinit,
- .scan = ixp2000_pci_scan_bus,
- .map_irq = ixdp2400_pci_map_irq,
-};
-
-int __init ixdp2400_pci_init(void)
-{
- if (machine_is_ixdp2400())
- pci_common_init(&ixdp2400_pci);
-
- return 0;
-}
-
-subsys_initcall(ixdp2400_pci_init);
-
-void __init ixdp2400_init_irq(void)
-{
- ixdp2x00_init_irq(IXDP2400_CPLD_INT_STAT, IXDP2400_CPLD_INT_MASK, IXDP2400_NR_IRQS);
-}
-
-MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
- /* Maintainer: MontaVista Software, Inc. */
- .atag_offset = 0x100,
- .map_io = ixdp2x00_map_io,
- .init_irq = ixdp2400_init_irq,
- .timer = &ixdp2400_timer,
- .init_machine = ixdp2x00_init_machine,
- .restart = ixp2000_restart,
-MACHINE_END
-
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
deleted file mode 100644
index a9f1819ea049..000000000000
--- a/arch/arm/mach-ixp2000/ixdp2800.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/ixdp2800.c
- *
- * IXDP2800 platform support
- *
- * Original Author: Jeffrey Daly <jeffrey.daly@intel.com>
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright (C) 2002 Intel Corp.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/bitops.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-
-#include <asm/mach/pci.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-#include <asm/mach/flash.h>
-#include <asm/mach/arch.h>
-
-/*************************************************************************
- * IXDP2800 timer tick
- *************************************************************************/
-
-static void __init ixdp2800_timer_init(void)
-{
- ixp2000_init_time(50000000);
-}
-
-static struct sys_timer ixdp2800_timer = {
- .init = ixdp2800_timer_init,
- .offset = ixp2000_gettimeoffset,
-};
-
-/*************************************************************************
- * IXDP2800 PCI
- *************************************************************************/
-static void __init ixdp2800_slave_disable_pci_master(void)
-{
- *IXP2000_PCI_CMDSTAT &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
-}
-
-static void __init ixdp2800_master_wait_for_slave(void)
-{
- volatile u32 *addr;
-
- printk(KERN_INFO "IXDP2800: waiting for slave NPU to configure "
- "its BAR sizes\n");
-
- addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN,
- PCI_BASE_ADDRESS_1);
- do {
- *addr = 0xffffffff;
- cpu_relax();
- } while (*addr != 0xfe000008);
-
- addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN,
- PCI_BASE_ADDRESS_2);
- do {
- *addr = 0xffffffff;
- cpu_relax();
- } while (*addr != 0xc0000008);
-
- /*
- * Configure the slave's SDRAM BAR by hand.
- */
- *addr = 0x40000008;
-}
-
-static void __init ixdp2800_slave_wait_for_master_enable(void)
-{
- printk(KERN_INFO "IXDP2800: waiting for master NPU to enable us\n");
-
- while ((*IXP2000_PCI_CMDSTAT & PCI_COMMAND_MASTER) == 0)
- cpu_relax();
-}
-
-void __init ixdp2800_pci_preinit(void)
-{
- printk("ixdp2x00_pci_preinit called\n");
-
- *IXP2000_PCI_ADDR_EXT = 0x0001e000;
-
- if (!ixdp2x00_master_npu())
- ixdp2800_slave_disable_pci_master();
-
- *IXP2000_PCI_SRAM_BASE_ADDR_MASK = (0x2000000 - 1) & ~0x3ffff;
- *IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff;
-
- ixp2000_pci_preinit();
-
- if (ixdp2x00_master_npu()) {
- /*
- * Wait until the slave set its SRAM/SDRAM BAR sizes
- * correctly before we proceed to scan and enumerate
- * the bus.
- */
- ixdp2800_master_wait_for_slave();
-
- /*
- * We configure the SDRAM BARs by hand because they
- * are 1G and fall outside of the regular allocated
- * PCI address space.
- */
- *IXP2000_PCI_SDRAM_BAR = 0x00000008;
- } else {
- /*
- * Wait for the master to complete scanning the bus
- * and assigning resources before we proceed to scan
- * the bus ourselves. Set pci=firmware to honor the
- * master's resource assignment.
- */
- ixdp2800_slave_wait_for_master_enable();
- pcibios_setup("firmware");
- }
-}
-
-/*
- * We assign the SDRAM BARs for the two IXP2800 CPUs by hand, outside
- * of the regular PCI window, because there's only 512M of outbound PCI
- * memory window on each IXP, while we need 1G for each of the BARs.
- */
-static void __devinit ixp2800_pci_fixup(struct pci_dev *dev)
-{
- if (machine_is_ixdp2800()) {
- dev->resource[2].start = 0;
- dev->resource[2].end = 0;
- dev->resource[2].flags = 0;
- }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IXP2800, ixp2800_pci_fixup);
-
-static int __init ixdp2800_pci_setup(int nr, struct pci_sys_data *sys)
-{
- sys->mem_offset = 0x00000000;
-
- ixp2000_pci_setup(nr, sys);
-
- return 1;
-}
-
-static int __init ixdp2800_pci_map_irq(const struct pci_dev *dev, u8 slot,
- u8 pin)
-{
- if (ixdp2x00_master_npu()) {
-
- /*
- * Root bus devices. Slave NPU is only one with interrupt.
- * Everything else, we just return -1 which is invalid.
- */
- if(!dev->bus->self) {
- if(dev->devfn == IXDP2X00_SLAVE_NPU_DEVFN )
- return IRQ_IXDP2800_INGRESS_NPU;
-
- return -1;
- }
-
- /*
- * Bridge behind the PMC slot.
- */
- if(dev->bus->self->devfn == IXDP2X00_PMC_DEVFN &&
- dev->bus->parent->self->devfn == IXDP2X00_P2P_DEVFN &&
- !dev->bus->parent->self->bus->parent)
- return IRQ_IXDP2800_PMC;
-
- /*
- * Device behind the first bridge
- */
- if(dev->bus->self->devfn == IXDP2X00_P2P_DEVFN) {
- switch(dev->devfn) {
- case IXDP2X00_PMC_DEVFN:
- return IRQ_IXDP2800_PMC;
-
- case IXDP2800_MASTER_ENET_DEVFN:
- return IRQ_IXDP2800_EGRESS_ENET;
-
- case IXDP2800_SWITCH_FABRIC_DEVFN:
- return IRQ_IXDP2800_FABRIC;
- }
- }
-
- return -1;
- } else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */
-}
-
-static void __init ixdp2800_master_enable_slave(void)
-{
- volatile u32 *addr;
-
- printk(KERN_INFO "IXDP2800: enabling slave NPU\n");
-
- addr = (volatile u32 *)ixp2000_pci_config_addr(0,
- IXDP2X00_SLAVE_NPU_DEVFN,
- PCI_COMMAND);
-
- *addr |= PCI_COMMAND_MASTER;
-}
-
-static void __init ixdp2800_master_wait_for_slave_bus_scan(void)
-{
- volatile u32 *addr;
-
- printk(KERN_INFO "IXDP2800: waiting for slave to finish bus scan\n");
-
- addr = (volatile u32 *)ixp2000_pci_config_addr(0,
- IXDP2X00_SLAVE_NPU_DEVFN,
- PCI_COMMAND);
- while ((*addr & PCI_COMMAND_MEMORY) == 0)
- cpu_relax();
-}
-
-static void __init ixdp2800_slave_signal_bus_scan_completion(void)
-{
- printk(KERN_INFO "IXDP2800: bus scan done, signaling master\n");
- *IXP2000_PCI_CMDSTAT |= PCI_COMMAND_MEMORY;
-}
-
-static void __init ixdp2800_pci_postinit(void)
-{
- if (!ixdp2x00_master_npu()) {
- ixdp2x00_slave_pci_postinit();
- ixdp2800_slave_signal_bus_scan_completion();
- }
-}
-
-struct __initdata hw_pci ixdp2800_pci __initdata = {
- .nr_controllers = 1,
- .setup = ixdp2800_pci_setup,
- .preinit = ixdp2800_pci_preinit,
- .postinit = ixdp2800_pci_postinit,
- .scan = ixp2000_pci_scan_bus,
- .map_irq = ixdp2800_pci_map_irq,
-};
-
-int __init ixdp2800_pci_init(void)
-{
- if (machine_is_ixdp2800()) {
- struct pci_dev *dev;
-
- pci_common_init(&ixdp2800_pci);
- if (ixdp2x00_master_npu()) {
- dev = pci_get_bus_and_slot(1, IXDP2800_SLAVE_ENET_DEVFN);
- pci_stop_and_remove_bus_device(dev);
- pci_dev_put(dev);
-
- ixdp2800_master_enable_slave();
- ixdp2800_master_wait_for_slave_bus_scan();
- } else {
- dev = pci_get_bus_and_slot(1, IXDP2800_MASTER_ENET_DEVFN);
- pci_stop_and_remove_bus_device(dev);
- pci_dev_put(dev);
- }
- }
-
- return 0;
-}
-
-subsys_initcall(ixdp2800_pci_init);
-
-void __init ixdp2800_init_irq(void)
-{
- ixdp2x00_init_irq(IXDP2800_CPLD_INT_STAT, IXDP2800_CPLD_INT_MASK, IXDP2800_NR_IRQS);
-}
-
-MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
- /* Maintainer: MontaVista Software, Inc. */
- .atag_offset = 0x100,
- .map_io = ixdp2x00_map_io,
- .init_irq = ixdp2800_init_irq,
- .timer = &ixdp2800_timer,
- .init_machine = ixdp2x00_init_machine,
- .restart = ixp2000_restart,
-MACHINE_END
-
diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
deleted file mode 100644
index 421e38dc0fac..000000000000
--- a/arch/arm/mach-ixp2000/ixdp2x00.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/ixdp2x00.c
- *
- * Code common to IXDP2400 and IXDP2800 platforms.
- *
- * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright (C) 2002 Intel Corp.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/bitops.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-
-#include <asm/mach/pci.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-#include <asm/mach/flash.h>
-#include <asm/mach/arch.h>
-
-#include <mach/gpio-ixp2000.h>
-
-/*************************************************************************
- * IXDP2x00 IRQ Initialization
- *************************************************************************/
-static volatile unsigned long *board_irq_mask;
-static volatile unsigned long *board_irq_stat;
-static unsigned long board_irq_count;
-
-#ifdef CONFIG_ARCH_IXDP2400
-/*
- * Slowport configuration for accessing CPLD registers on IXDP2x00
- */
-static struct slowport_cfg slowport_cpld_cfg = {
- .CCR = SLOWPORT_CCR_DIV_2,
- .WTC = 0x00000070,
- .RTC = 0x00000070,
- .PCR = SLOWPORT_MODE_FLASH,
- .ADC = SLOWPORT_ADDR_WIDTH_24 | SLOWPORT_DATA_WIDTH_8
-};
-#endif
-
-static void ixdp2x00_irq_mask(struct irq_data *d)
-{
- unsigned long dummy;
- static struct slowport_cfg old_cfg;
-
- /*
- * This is ugly in common code but really don't know
- * of a better way to handle it. :(
- */
-#ifdef CONFIG_ARCH_IXDP2400
- if (machine_is_ixdp2400())
- ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
-#endif
-
- dummy = *board_irq_mask;
- dummy |= IXP2000_BOARD_IRQ_MASK(d->irq);
- ixp2000_reg_wrb(board_irq_mask, dummy);
-
-#ifdef CONFIG_ARCH_IXDP2400
- if (machine_is_ixdp2400())
- ixp2000_release_slowport(&old_cfg);
-#endif
-}
-
-static void ixdp2x00_irq_unmask(struct irq_data *d)
-{
- unsigned long dummy;
- static struct slowport_cfg old_cfg;
-
-#ifdef CONFIG_ARCH_IXDP2400
- if (machine_is_ixdp2400())
- ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
-#endif
-
- dummy = *board_irq_mask;
- dummy &= ~IXP2000_BOARD_IRQ_MASK(d->irq);
- ixp2000_reg_wrb(board_irq_mask, dummy);
-
- if (machine_is_ixdp2400())
- ixp2000_release_slowport(&old_cfg);
-}
-
-static void ixdp2x00_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
- volatile u32 ex_interrupt = 0;
- static struct slowport_cfg old_cfg;
- int i;
-
- desc->irq_data.chip->irq_mask(&desc->irq_data);
-
-#ifdef CONFIG_ARCH_IXDP2400
- if (machine_is_ixdp2400())
- ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
-#endif
- ex_interrupt = *board_irq_stat & 0xff;
- if (machine_is_ixdp2400())
- ixp2000_release_slowport(&old_cfg);
-
- if(!ex_interrupt) {
- printk(KERN_ERR "Spurious IXDP2x00 CPLD interrupt!\n");
- return;
- }
-
- for(i = 0; i < board_irq_count; i++) {
- if(ex_interrupt & (1 << i)) {
- int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
- generic_handle_irq(cpld_irq);
- }
- }
-
- desc->irq_data.chip->irq_unmask(&desc->irq_data);
-}
-
-static struct irq_chip ixdp2x00_cpld_irq_chip = {
- .irq_ack = ixdp2x00_irq_mask,
- .irq_mask = ixdp2x00_irq_mask,
- .irq_unmask = ixdp2x00_irq_unmask
-};
-
-void __init ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_of_irqs)
-{
- unsigned int irq;
-
- ixp2000_init_irq();
-
- if (!ixdp2x00_master_npu())
- return;
-
- board_irq_stat = stat_reg;
- board_irq_mask = mask_reg;
- board_irq_count = nr_of_irqs;
-
- *board_irq_mask = 0xffffffff;
-
- for(irq = IXP2000_BOARD_IRQ(0); irq < IXP2000_BOARD_IRQ(board_irq_count); irq++) {
- irq_set_chip_and_handler(irq, &ixdp2x00_cpld_irq_chip,
- handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- }
-
- /* Hook into PCI interrupt */
- irq_set_chained_handler(IRQ_IXP2000_PCIB, ixdp2x00_irq_handler);
-}
-
-/*************************************************************************
- * IXDP2x00 memory map
- *************************************************************************/
-static struct map_desc ixdp2x00_io_desc __initdata = {
- .virtual = IXDP2X00_VIRT_CPLD_BASE,
- .pfn = __phys_to_pfn(IXDP2X00_PHYS_CPLD_BASE),
- .length = IXDP2X00_CPLD_SIZE,
- .type = MT_DEVICE
-};
-
-void __init ixdp2x00_map_io(void)
-{
- ixp2000_map_io();
-
- iotable_init(&ixdp2x00_io_desc, 1);
-}
-
-/*************************************************************************
- * IXDP2x00-common PCI init
- *
- * The IXDP2[48]00 has a horrid PCI bus layout. Basically the board
- * contains two NPUs (ingress and egress) connected over PCI, both running
- * instances of the kernel. So far so good. Peers on the PCI bus running
- * Linux is a common design in telecom systems. The problem is that instead
- * of all the devices being controlled by a single host, different
- * devices are controlled by different NPUs on the same bus, leading to
- * multiple hosts on the bus. The exact bus layout looks like:
- *
- * Bus 0
- * Master NPU <-------------------+-------------------> Slave NPU
- * |
- * |
- * P2P
- * |
- *
- * Bus 1 |
- * <--+------+---------+---------+------+-->
- * | | | | |
- * | | | | |
- * ... Dev PMC Media Eth0 Eth1 ...
- *
- * The master controls all but Eth1, which is controlled by the
- * slave. What this means is that the both the master and the slave
- * have to scan the bus, but only one of them can enumerate the bus.
- * In addition, after the bus is scanned, each kernel must remove
- * the device(s) it does not control from the PCI dev list otherwise
- * a driver on each NPU will try to manage it and we will have horrible
- * conflicts. Oh..and the slave NPU needs to see the master NPU
- * for Intel's drivers to work properly. Closed source drivers...
- *
- * The way we deal with this is fairly simple but ugly:
- *
- * 1) Let master scan and enumerate the bus completely.
- * 2) Master deletes Eth1 from device list.
- * 3) Slave scans bus and then deletes all but Eth1 (Eth0 on slave)
- * from device list.
- * 4) Find HW designers and LART them.
- *
- * The boards also do not do normal PCI IRQ routing, or any sort of
- * sensical swizzling, so we just need to check where on the bus a
- * device sits and figure out to which CPLD pin the interrupt is routed.
- * See ixdp2[48]00.c files.
- *
- *************************************************************************/
-void ixdp2x00_slave_pci_postinit(void)
-{
- struct pci_dev *dev;
-
- /*
- * Remove PMC device is there is one
- */
- if((dev = pci_get_bus_and_slot(1, IXDP2X00_PMC_DEVFN))) {
- pci_stop_and_remove_bus_device(dev);
- pci_dev_put(dev);
- }
-
- dev = pci_get_bus_and_slot(0, IXDP2X00_21555_DEVFN);
- pci_stop_and_remove_bus_device(dev);
- pci_dev_put(dev);
-}
-
-/**************************************************************************
- * IXDP2x00 Machine Setup
- *************************************************************************/
-static struct flash_platform_data ixdp2x00_platform_data = {
- .map_name = "cfi_probe",
- .width = 1,
-};
-
-static struct ixp2000_flash_data ixdp2x00_flash_data = {
- .platform_data = &ixdp2x00_platform_data,
- .nr_banks = 1
-};
-
-static struct resource ixdp2x00_flash_resource = {
- .start = 0xc4000000,
- .end = 0xc4000000 + 0x00ffffff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device ixdp2x00_flash = {
- .name = "IXP2000-Flash",
- .id = 0,
- .dev = {
- .platform_data = &ixdp2x00_flash_data,
- },
- .num_resources = 1,
- .resource = &ixdp2x00_flash_resource,
-};
-
-static struct ixp2000_i2c_pins ixdp2x00_i2c_gpio_pins = {
- .sda_pin = IXDP2X00_GPIO_SDA,
- .scl_pin = IXDP2X00_GPIO_SCL,
-};
-
-static struct platform_device ixdp2x00_i2c_controller = {
- .name = "IXP2000-I2C",
- .id = 0,
- .dev = {
- .platform_data = &ixdp2x00_i2c_gpio_pins,
- },
- .num_resources = 0
-};
-
-static struct platform_device *ixdp2x00_devices[] __initdata = {
- &ixdp2x00_flash,
- &ixdp2x00_i2c_controller
-};
-
-void __init ixdp2x00_init_machine(void)
-{
- gpio_line_set(IXDP2X00_GPIO_I2C_ENABLE, 1);
- gpio_line_config(IXDP2X00_GPIO_I2C_ENABLE, GPIO_OUT);
-
- platform_add_devices(ixdp2x00_devices, ARRAY_SIZE(ixdp2x00_devices));
- ixp2000_uart_init();
-}
-
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
deleted file mode 100644
index 5196c39cdba4..000000000000
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/ixdp2x01.c
- *
- * Code common to Intel IXDP2401 and IXDP2801 platforms
- *
- * Original Author: Andrzej Mialkowski <andrzej.mialkowski@intel.com>
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright (C) 2002-2003 Intel Corp.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-
-#include <asm/mach/pci.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-
-/*************************************************************************
- * IXDP2x01 IRQ Handling
- *************************************************************************/
-static void ixdp2x01_irq_mask(struct irq_data *d)
-{
- ixp2000_reg_wrb(IXDP2X01_INT_MASK_SET_REG,
- IXP2000_BOARD_IRQ_MASK(d->irq));
-}
-
-static void ixdp2x01_irq_unmask(struct irq_data *d)
-{
- ixp2000_reg_write(IXDP2X01_INT_MASK_CLR_REG,
- IXP2000_BOARD_IRQ_MASK(d->irq));
-}
-
-static u32 valid_irq_mask;
-
-static void ixdp2x01_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
- u32 ex_interrupt;
- int i;
-
- desc->irq_data.chip->irq_mask(&desc->irq_data);
-
- ex_interrupt = *IXDP2X01_INT_STAT_REG & valid_irq_mask;
-
- if (!ex_interrupt) {
- printk(KERN_ERR "Spurious IXDP2X01 CPLD interrupt!\n");
- return;
- }
-
- for (i = 0; i < IXP2000_BOARD_IRQS; i++) {
- if (ex_interrupt & (1 << i)) {
- int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
- generic_handle_irq(cpld_irq);
- }
- }
-
- desc->irq_data.chip->irq_unmask(&desc->irq_data);
-}
-
-static struct irq_chip ixdp2x01_irq_chip = {
- .irq_mask = ixdp2x01_irq_mask,
- .irq_ack = ixdp2x01_irq_mask,
- .irq_unmask = ixdp2x01_irq_unmask
-};
-
-/*
- * We only do anything if we are the master NPU on the board.
- * The slave NPU only has the ethernet chip going directly to
- * the PCIB interrupt input.
- */
-void __init ixdp2x01_init_irq(void)
-{
- int irq = 0;
-
- /* initialize chip specific interrupts */
- ixp2000_init_irq();
-
- if (machine_is_ixdp2401())
- valid_irq_mask = IXDP2401_VALID_IRQ_MASK;
- else
- valid_irq_mask = IXDP2801_VALID_IRQ_MASK;
-
- /* Mask all interrupts from CPLD, disable simulation */
- ixp2000_reg_write(IXDP2X01_INT_MASK_SET_REG, 0xffffffff);
- ixp2000_reg_wrb(IXDP2X01_INT_SIM_REG, 0);
-
- for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) {
- if (irq & valid_irq_mask) {
- irq_set_chip_and_handler(irq, &ixdp2x01_irq_chip,
- handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- } else {
- set_irq_flags(irq, 0);
- }
- }
-
- /* Hook into PCI interrupts */
- irq_set_chained_handler(IRQ_IXP2000_PCIB, ixdp2x01_irq_handler);
-}
-
-
-/*************************************************************************
- * IXDP2x01 memory map
- *************************************************************************/
-static struct map_desc ixdp2x01_io_desc __initdata = {
- .virtual = IXDP2X01_VIRT_CPLD_BASE,
- .pfn = __phys_to_pfn(IXDP2X01_PHYS_CPLD_BASE),
- .length = IXDP2X01_CPLD_REGION_SIZE,
- .type = MT_DEVICE
-};
-
-static void __init ixdp2x01_map_io(void)
-{
- ixp2000_map_io();
- iotable_init(&ixdp2x01_io_desc, 1);
-}
-
-
-/*************************************************************************
- * IXDP2x01 serial ports
- *************************************************************************/
-static struct plat_serial8250_port ixdp2x01_serial_port1[] = {
- {
- .mapbase = (unsigned long)IXDP2X01_UART1_PHYS_BASE,
- .membase = (char *)IXDP2X01_UART1_VIRT_BASE,
- .irq = IRQ_IXDP2X01_UART1,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM32,
- .regshift = 2,
- .uartclk = IXDP2X01_UART_CLK,
- },
- { }
-};
-
-static struct resource ixdp2x01_uart_resource1 = {
- .start = IXDP2X01_UART1_PHYS_BASE,
- .end = IXDP2X01_UART1_PHYS_BASE + 0xffff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device ixdp2x01_serial_device1 = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM1,
- .dev = {
- .platform_data = ixdp2x01_serial_port1,
- },
- .num_resources = 1,
- .resource = &ixdp2x01_uart_resource1,
-};
-
-static struct plat_serial8250_port ixdp2x01_serial_port2[] = {
- {
- .mapbase = (unsigned long)IXDP2X01_UART2_PHYS_BASE,
- .membase = (char *)IXDP2X01_UART2_VIRT_BASE,
- .irq = IRQ_IXDP2X01_UART2,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM32,
- .regshift = 2,
- .uartclk = IXDP2X01_UART_CLK,
- },
- { }
-};
-
-static struct resource ixdp2x01_uart_resource2 = {
- .start = IXDP2X01_UART2_PHYS_BASE,
- .end = IXDP2X01_UART2_PHYS_BASE + 0xffff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device ixdp2x01_serial_device2 = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM2,
- .dev = {
- .platform_data = ixdp2x01_serial_port2,
- },
- .num_resources = 1,
- .resource = &ixdp2x01_uart_resource2,
-};
-
-static void ixdp2x01_uart_init(void)
-{
- platform_device_register(&ixdp2x01_serial_device1);
- platform_device_register(&ixdp2x01_serial_device2);
-}
-
-
-/*************************************************************************
- * IXDP2x01 timer tick configuration
- *************************************************************************/
-static unsigned int ixdp2x01_clock;
-
-static int __init ixdp2x01_clock_setup(char *str)
-{
- ixdp2x01_clock = simple_strtoul(str, NULL, 10);
-
- return 1;
-}
-
-__setup("ixdp2x01_clock=", ixdp2x01_clock_setup);
-
-static void __init ixdp2x01_timer_init(void)
-{
- if (!ixdp2x01_clock)
- ixdp2x01_clock = 50000000;
-
- ixp2000_init_time(ixdp2x01_clock);
-}
-
-static struct sys_timer ixdp2x01_timer = {
- .init = ixdp2x01_timer_init,
- .offset = ixp2000_gettimeoffset,
-};
-
-/*************************************************************************
- * IXDP2x01 PCI
- *************************************************************************/
-void __init ixdp2x01_pci_preinit(void)
-{
- ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00000000);
- ixp2000_pci_preinit();
- pcibios_setup("firmware");
-}
-
-#define DEVPIN(dev, pin) ((pin) | ((dev) << 3))
-
-static int __init ixdp2x01_pci_map_irq(const struct pci_dev *dev, u8 slot,
- u8 pin)
-{
- u8 bus = dev->bus->number;
- u32 devpin = DEVPIN(PCI_SLOT(dev->devfn), pin);
- struct pci_bus *tmp_bus = dev->bus;
-
- /* Primary bus, no interrupts here */
- if (bus == 0) {
- return -1;
- }
-
- /* Lookup first leaf in bus tree */
- while ((tmp_bus->parent != NULL) && (tmp_bus->parent->parent != NULL)) {
- tmp_bus = tmp_bus->parent;
- }
-
- /* Select between known bridges */
- switch (tmp_bus->self->devfn | (tmp_bus->self->bus->number << 8)) {
- /* Device is located after first MB bridge */
- case 0x0008:
- if (tmp_bus == dev->bus) {
- /* Device is located directly after first MB bridge */
- switch (devpin) {
- case DEVPIN(1, 1): /* Onboard 82546 ch 0 */
- if (machine_is_ixdp2401())
- return IRQ_IXDP2401_INTA_82546;
- return -1;
- case DEVPIN(1, 2): /* Onboard 82546 ch 1 */
- if (machine_is_ixdp2401())
- return IRQ_IXDP2401_INTB_82546;
- return -1;
- case DEVPIN(0, 1): /* PMC INTA# */
- return IRQ_IXDP2X01_SPCI_PMC_INTA;
- case DEVPIN(0, 2): /* PMC INTB# */
- return IRQ_IXDP2X01_SPCI_PMC_INTB;
- case DEVPIN(0, 3): /* PMC INTC# */
- return IRQ_IXDP2X01_SPCI_PMC_INTC;
- case DEVPIN(0, 4): /* PMC INTD# */
- return IRQ_IXDP2X01_SPCI_PMC_INTD;
- }
- }
- break;
- case 0x0010:
- if (tmp_bus == dev->bus) {
- /* Device is located directly after second MB bridge */
- /* Secondary bus of second bridge */
- switch (devpin) {
- case DEVPIN(0, 1): /* DB#0 */
- return IRQ_IXDP2X01_SPCI_DB_0;
- case DEVPIN(1, 1): /* DB#1 */
- return IRQ_IXDP2X01_SPCI_DB_1;
- }
- } else {
- /* Device is located indirectly after second MB bridge */
- /* Not supported now */
- }
- break;
- }
-
- return -1;
-}
-
-
-static int ixdp2x01_pci_setup(int nr, struct pci_sys_data *sys)
-{
- sys->mem_offset = 0xe0000000;
-
- if (machine_is_ixdp2801() || machine_is_ixdp28x5())
- sys->mem_offset -= ((*IXP2000_PCI_ADDR_EXT & 0xE000) << 16);
-
- return ixp2000_pci_setup(nr, sys);
-}
-
-struct hw_pci ixdp2x01_pci __initdata = {
- .nr_controllers = 1,
- .setup = ixdp2x01_pci_setup,
- .preinit = ixdp2x01_pci_preinit,
- .scan = ixp2000_pci_scan_bus,
- .map_irq = ixdp2x01_pci_map_irq,
-};
-
-int __init ixdp2x01_pci_init(void)
-{
- if (machine_is_ixdp2401() || machine_is_ixdp2801() ||\
- machine_is_ixdp28x5())
- pci_common_init(&ixdp2x01_pci);
-
- return 0;
-}
-
-subsys_initcall(ixdp2x01_pci_init);
-
-/*************************************************************************
- * IXDP2x01 Machine Initialization
- *************************************************************************/
-static struct flash_platform_data ixdp2x01_flash_platform_data = {
- .map_name = "cfi_probe",
- .width = 1,
-};
-
-static unsigned long ixdp2x01_flash_bank_setup(unsigned long ofs)
-{
- ixp2000_reg_wrb(IXDP2X01_CPLD_FLASH_REG,
- ((ofs >> IXDP2X01_FLASH_WINDOW_BITS) | IXDP2X01_CPLD_FLASH_INTERN));
- return (ofs & IXDP2X01_FLASH_WINDOW_MASK);
-}
-
-static struct ixp2000_flash_data ixdp2x01_flash_data = {
- .platform_data = &ixdp2x01_flash_platform_data,
- .bank_setup = ixdp2x01_flash_bank_setup
-};
-
-static struct resource ixdp2x01_flash_resource = {
- .start = 0xc4000000,
- .end = 0xc4000000 + 0x01ffffff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device ixdp2x01_flash = {
- .name = "IXP2000-Flash",
- .id = 0,
- .dev = {
- .platform_data = &ixdp2x01_flash_data,
- },
- .num_resources = 1,
- .resource = &ixdp2x01_flash_resource,
-};
-
-static struct ixp2000_i2c_pins ixdp2x01_i2c_gpio_pins = {
- .sda_pin = IXDP2X01_GPIO_SDA,
- .scl_pin = IXDP2X01_GPIO_SCL,
-};
-
-static struct platform_device ixdp2x01_i2c_controller = {
- .name = "IXP2000-I2C",
- .id = 0,
- .dev = {
- .platform_data = &ixdp2x01_i2c_gpio_pins,
- },
- .num_resources = 0
-};
-
-static struct platform_device *ixdp2x01_devices[] __initdata = {
- &ixdp2x01_flash,
- &ixdp2x01_i2c_controller
-};
-
-static void __init ixdp2x01_init_machine(void)
-{
- ixp2000_reg_wrb(IXDP2X01_CPLD_FLASH_REG,
- (IXDP2X01_CPLD_FLASH_BANK_MASK | IXDP2X01_CPLD_FLASH_INTERN));
-
- ixdp2x01_flash_data.nr_banks =
- ((*IXDP2X01_CPLD_FLASH_REG & IXDP2X01_CPLD_FLASH_BANK_MASK) + 1);
-
- platform_add_devices(ixdp2x01_devices, ARRAY_SIZE(ixdp2x01_devices));
- ixp2000_uart_init();
- ixdp2x01_uart_init();
-}
-
-static void ixdp2401_restart(char mode, const char *cmd)
-{
- /*
- * Reset flash banking register so that we are pointing at
- * RedBoot bank.
- */
- ixp2000_reg_write(IXDP2X01_CPLD_FLASH_REG,
- ((0 >> IXDP2X01_FLASH_WINDOW_BITS)
- | IXDP2X01_CPLD_FLASH_INTERN));
- ixp2000_reg_wrb(IXDP2X01_CPLD_RESET_REG, 0xffffffff);
-
- ixp2000_restart(mode, cmd);
-}
-
-static void ixdp280x_restart(char mode, const char *cmd)
-{
- /*
- * On IXDP2801 we need to write this magic sequence to the CPLD
- * to cause a complete reset of the CPU and all external devices
- * and move the flash bank register back to 0.
- */
- unsigned long reset_reg = *IXDP2X01_CPLD_RESET_REG;
-
- reset_reg = 0x55AA0000 | (reset_reg & 0x0000FFFF);
- ixp2000_reg_write(IXDP2X01_CPLD_RESET_REG, reset_reg);
- ixp2000_reg_wrb(IXDP2X01_CPLD_RESET_REG, 0x80000000);
-
- ixp2000_restart(mode, cmd);
-}
-
-#ifdef CONFIG_ARCH_IXDP2401
-MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform")
- /* Maintainer: MontaVista Software, Inc. */
- .atag_offset = 0x100,
- .map_io = ixdp2x01_map_io,
- .init_irq = ixdp2x01_init_irq,
- .timer = &ixdp2x01_timer,
- .init_machine = ixdp2x01_init_machine,
- .restart = ixdp2401_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_ARCH_IXDP2801
-MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform")
- /* Maintainer: MontaVista Software, Inc. */
- .atag_offset = 0x100,
- .map_io = ixdp2x01_map_io,
- .init_irq = ixdp2x01_init_irq,
- .timer = &ixdp2x01_timer,
- .init_machine = ixdp2x01_init_machine,
- .restart = ixdp280x_restart,
-MACHINE_END
-
-/*
- * IXDP28x5 is basically an IXDP2801 with a different CPU but Intel
- * changed the machine ID in the bootloader
- */
-MACHINE_START(IXDP28X5, "Intel IXDP2805/2855 Development Platform")
- /* Maintainer: MontaVista Software, Inc. */
- .atag_offset = 0x100,
- .map_io = ixdp2x01_map_io,
- .init_irq = ixdp2x01_init_irq,
- .timer = &ixdp2x01_timer,
- .init_machine = ixdp2x01_init_machine,
- .restart = ixdp280x_restart,
-MACHINE_END
-#endif
-
-
diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c
deleted file mode 100644
index 9c02de932fac..000000000000
--- a/arch/arm/mach-ixp2000/pci.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/pci.c
- *
- * PCI routines for IXDP2400/IXDP2800 boards
- *
- * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
- * Maintained by: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright 2002 Intel Corp.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-#include <asm/mach/pci.h>
-
-static volatile int pci_master_aborts = 0;
-
-static int clear_master_aborts(void);
-
-u32 *
-ixp2000_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where)
-{
- u32 *paddress;
-
- if (PCI_SLOT(devfn) > 7)
- return 0;
-
- /* Must be dword aligned */
- where &= ~3;
-
- /*
- * For top bus, generate type 0, else type 1
- */
- if (!bus_nr) {
- /* only bits[23:16] are used for IDSEL */
- paddress = (u32 *) (IXP2000_PCI_CFG0_VIRT_BASE
- | (1 << (PCI_SLOT(devfn) + 16))
- | (PCI_FUNC(devfn) << 8) | where);
- } else {
- paddress = (u32 *) (IXP2000_PCI_CFG1_VIRT_BASE
- | (bus_nr << 16)
- | (PCI_SLOT(devfn) << 11)
- | (PCI_FUNC(devfn) << 8) | where);
- }
-
- return paddress;
-}
-
-/*
- * Mask table, bits to mask for quantity of size 1, 2 or 4 bytes.
- * 0 and 3 are not valid indexes...
- */
-static u32 bytemask[] = {
- /*0*/ 0,
- /*1*/ 0xff,
- /*2*/ 0xffff,
- /*3*/ 0,
- /*4*/ 0xffffffff,
-};
-
-
-int ixp2000_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where,
- int size, u32 *value)
-{
- u32 n;
- u32 *addr;
-
- n = where % 4;
-
- addr = ixp2000_pci_config_addr(bus->number, devfn, where);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- pci_master_aborts = 0;
- *value = (*addr >> (8*n)) & bytemask[size];
- if (pci_master_aborts) {
- pci_master_aborts = 0;
- *value = 0xffffffff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-/*
- * We don't do error checks by calling clear_master_aborts() b/c the
- * assumption is that the caller did a read first to make sure a device
- * exists.
- */
-int ixp2000_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where,
- int size, u32 value)
-{
- u32 mask;
- u32 *addr;
- u32 temp;
-
- mask = ~(bytemask[size] << ((where % 0x4) * 8));
- addr = ixp2000_pci_config_addr(bus->number, devfn, where);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
- temp = (u32) (value) << ((where % 0x4) * 8);
- *addr = (*addr & mask) | temp;
-
- clear_master_aborts();
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-static struct pci_ops ixp2000_pci_ops = {
- .read = ixp2000_pci_read_config,
- .write = ixp2000_pci_write_config
-};
-
-struct pci_bus *ixp2000_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
-{
- return pci_scan_root_bus(NULL, sysdata->busnr, &ixp2000_pci_ops,
- sysdata, &sysdata->resources);
-}
-
-
-int ixp2000_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
-
- volatile u32 temp;
- unsigned long flags;
-
- pci_master_aborts = 1;
-
- local_irq_save(flags);
- temp = *(IXP2000_PCI_CONTROL);
- if (temp & ((1 << 8) | (1 << 5))) {
- ixp2000_reg_wrb(IXP2000_PCI_CONTROL, temp);
- }
-
- temp = *(IXP2000_PCI_CMDSTAT);
- if (temp & (1 << 29)) {
- while (temp & (1 << 29)) {
- ixp2000_reg_write(IXP2000_PCI_CMDSTAT, temp);
- temp = *(IXP2000_PCI_CMDSTAT);
- }
- }
- local_irq_restore(flags);
-
- /*
- * If it was an imprecise abort, then we need to correct the
- * return address to be _after_ the instruction.
- */
- if (fsr & (1 << 10))
- regs->ARM_pc += 4;
-
- return 0;
-}
-
-int
-clear_master_aborts(void)
-{
- volatile u32 temp;
- unsigned long flags;
-
- local_irq_save(flags);
- temp = *(IXP2000_PCI_CONTROL);
- if (temp & ((1 << 8) | (1 << 5))) {
- ixp2000_reg_wrb(IXP2000_PCI_CONTROL, temp);
- }
-
- temp = *(IXP2000_PCI_CMDSTAT);
- if (temp & (1 << 29)) {
- while (temp & (1 << 29)) {
- ixp2000_reg_write(IXP2000_PCI_CMDSTAT, temp);
- temp = *(IXP2000_PCI_CMDSTAT);
- }
- }
- local_irq_restore(flags);
-
- return 0;
-}
-
-void __init
-ixp2000_pci_preinit(void)
-{
- pci_set_flags(0);
-
- pcibios_min_io = 0;
- pcibios_min_mem = 0;
-
-#ifndef CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO
- /*
- * Configure the PCI unit to properly byteswap I/O transactions,
- * and verify that it worked.
- */
- ixp2000_reg_write(IXP2000_PCI_CONTROL,
- (*IXP2000_PCI_CONTROL | PCI_CONTROL_IEE));
-
- if ((*IXP2000_PCI_CONTROL & PCI_CONTROL_IEE) == 0)
- panic("IXP2000: PCI I/O is broken on this ixp model, and "
- "the needed workaround has not been configured in");
-#endif
-
- hook_fault_code(16+6, ixp2000_pci_abort_handler, SIGBUS, 0,
- "PCI config cycle to non-existent device");
-}
-
-
-/*
- * IXP2000 systems often have large resource requirements, so we just
- * use our own resource space.
- */
-static struct resource ixp2000_pci_mem_space = {
- .start = 0xe0000000,
- .end = 0xffffffff,
- .flags = IORESOURCE_MEM,
- .name = "PCI Mem Space"
-};
-
-static struct resource ixp2000_pci_io_space = {
- .start = 0x00010000,
- .end = 0x0001ffff,
- .flags = IORESOURCE_IO,
- .name = "PCI I/O Space"
-};
-
-int ixp2000_pci_setup(int nr, struct pci_sys_data *sys)
-{
- if (nr >= 1)
- return 0;
-
- pci_add_resource_offset(&sys->resources,
- &ixp2000_pci_io_space, sys->io_offset);
- pci_add_resource_offset(&sys->resources,
- &ixp2000_pci_mem_space, sys->mem_offset);
-
- return 1;
-}
-
diff --git a/arch/arm/mach-ixp23xx/Kconfig b/arch/arm/mach-ixp23xx/Kconfig
deleted file mode 100644
index 982670ec3866..000000000000
--- a/arch/arm/mach-ixp23xx/Kconfig
+++ /dev/null
@@ -1,25 +0,0 @@
-if ARCH_IXP23XX
-
-config ARCH_SUPPORTS_BIG_ENDIAN
- bool
- default y
-
-menu "Intel IXP23xx Implementation Options"
-
-comment "IXP23xx Platforms"
-
-config MACH_ESPRESSO
- bool "Support IP Fabrics Double Espresso platform"
- help
-
-config MACH_IXDP2351
- bool "Support Intel IXDP2351 platform"
- help
-
-config MACH_ROADRUNNER
- bool "Support ADI RoadRunner platform"
- help
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-ixp23xx/Makefile b/arch/arm/mach-ixp23xx/Makefile
deleted file mode 100644
index 288b371b6d03..000000000000
--- a/arch/arm/mach-ixp23xx/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-obj-y := core.o pci.o
-obj-m :=
-obj-n :=
-obj- :=
-
-obj-$(CONFIG_MACH_ESPRESSO) += espresso.o
-obj-$(CONFIG_MACH_IXDP2351) += ixdp2351.o
-obj-$(CONFIG_MACH_ROADRUNNER) += roadrunner.o
diff --git a/arch/arm/mach-ixp23xx/Makefile.boot b/arch/arm/mach-ixp23xx/Makefile.boot
deleted file mode 100644
index 44fb4a717c3f..000000000000
--- a/arch/arm/mach-ixp23xx/Makefile.boot
+++ /dev/null
@@ -1,2 +0,0 @@
- zreladdr-y += 0x00008000
-params_phys-y := 0x00000100
diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c
deleted file mode 100644
index d34542425990..000000000000
--- a/arch/arm/mach-ixp23xx/core.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/core.c
- *
- * Core routines for IXP23xx chips
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright 2005 (c) MontaVista Software, Inc.
- *
- * Based on 2.4 code Copyright 2004 (c) Intel Corporation
- *
- * 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/spinlock.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/bitops.h>
-#include <linux/serial_8250.h>
-#include <linux/serial_core.h>
-#include <linux/device.h>
-#include <linux/mm.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-
-#include <asm/types.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/tlbflush.h>
-#include <asm/pgtable.h>
-#include <asm/system_misc.h>
-
-#include <asm/mach/map.h>
-#include <asm/mach/time.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/arch.h>
-
-
-/*************************************************************************
- * Chip specific mappings shared by all IXP23xx systems
- *************************************************************************/
-static struct map_desc ixp23xx_io_desc[] __initdata = {
- { /* XSI-CPP CSRs */
- .virtual = IXP23XX_XSI2CPP_CSR_VIRT,
- .pfn = __phys_to_pfn(IXP23XX_XSI2CPP_CSR_PHYS),
- .length = IXP23XX_XSI2CPP_CSR_SIZE,
- .type = MT_DEVICE,
- }, { /* Expansion Bus Config */
- .virtual = IXP23XX_EXP_CFG_VIRT,
- .pfn = __phys_to_pfn(IXP23XX_EXP_CFG_PHYS),
- .length = IXP23XX_EXP_CFG_SIZE,
- .type = MT_DEVICE,
- }, { /* UART, Interrupt ctrl, GPIO, timers, NPEs, MACS,.... */
- .virtual = IXP23XX_PERIPHERAL_VIRT,
- .pfn = __phys_to_pfn(IXP23XX_PERIPHERAL_PHYS),
- .length = IXP23XX_PERIPHERAL_SIZE,
- .type = MT_DEVICE,
- }, { /* CAP CSRs */
- .virtual = IXP23XX_CAP_CSR_VIRT,
- .pfn = __phys_to_pfn(IXP23XX_CAP_CSR_PHYS),
- .length = IXP23XX_CAP_CSR_SIZE,
- .type = MT_DEVICE,
- }, { /* MSF CSRs */
- .virtual = IXP23XX_MSF_CSR_VIRT,
- .pfn = __phys_to_pfn(IXP23XX_MSF_CSR_PHYS),
- .length = IXP23XX_MSF_CSR_SIZE,
- .type = MT_DEVICE,
- }, { /* PCI I/O Space */
- .virtual = IXP23XX_PCI_IO_VIRT,
- .pfn = __phys_to_pfn(IXP23XX_PCI_IO_PHYS),
- .length = IXP23XX_PCI_IO_SIZE,
- .type = MT_DEVICE,
- }, { /* PCI Config Space */
- .virtual = IXP23XX_PCI_CFG_VIRT,
- .pfn = __phys_to_pfn(IXP23XX_PCI_CFG_PHYS),
- .length = IXP23XX_PCI_CFG_SIZE,
- .type = MT_DEVICE,
- }, { /* PCI local CFG CSRs */
- .virtual = IXP23XX_PCI_CREG_VIRT,
- .pfn = __phys_to_pfn(IXP23XX_PCI_CREG_PHYS),
- .length = IXP23XX_PCI_CREG_SIZE,
- .type = MT_DEVICE,
- }, { /* PCI MEM Space */
- .virtual = IXP23XX_PCI_MEM_VIRT,
- .pfn = __phys_to_pfn(IXP23XX_PCI_MEM_PHYS),
- .length = IXP23XX_PCI_MEM_SIZE,
- .type = MT_DEVICE,
- }
-};
-
-void __init ixp23xx_map_io(void)
-{
- iotable_init(ixp23xx_io_desc, ARRAY_SIZE(ixp23xx_io_desc));
-}
-
-
-/***************************************************************************
- * IXP23xx Interrupt Handling
- ***************************************************************************/
-enum ixp23xx_irq_type {
- IXP23XX_IRQ_LEVEL, IXP23XX_IRQ_EDGE
-};
-
-static void ixp23xx_config_irq(unsigned int, enum ixp23xx_irq_type);
-
-static int ixp23xx_irq_set_type(struct irq_data *d, unsigned int type)
-{
- int line = d->irq - IRQ_IXP23XX_GPIO6 + 6;
- u32 int_style;
- enum ixp23xx_irq_type irq_type;
- volatile u32 *int_reg;
-
- /*
- * Only GPIOs 6-15 are wired to interrupts on IXP23xx
- */
- if (line < 6 || line > 15)
- return -EINVAL;
-
- switch (type) {
- case IRQ_TYPE_EDGE_BOTH:
- int_style = IXP23XX_GPIO_STYLE_TRANSITIONAL;
- irq_type = IXP23XX_IRQ_EDGE;
- break;
- case IRQ_TYPE_EDGE_RISING:
- int_style = IXP23XX_GPIO_STYLE_RISING_EDGE;
- irq_type = IXP23XX_IRQ_EDGE;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- int_style = IXP23XX_GPIO_STYLE_FALLING_EDGE;
- irq_type = IXP23XX_IRQ_EDGE;
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- int_style = IXP23XX_GPIO_STYLE_ACTIVE_HIGH;
- irq_type = IXP23XX_IRQ_LEVEL;
- break;
- case IRQ_TYPE_LEVEL_LOW:
- int_style = IXP23XX_GPIO_STYLE_ACTIVE_LOW;
- irq_type = IXP23XX_IRQ_LEVEL;
- break;
- default:
- return -EINVAL;
- }
-
- ixp23xx_config_irq(d->irq, irq_type);
-
- if (line >= 8) { /* pins 8-15 */
- line -= 8;
- int_reg = (volatile u32 *)IXP23XX_GPIO_GPIT2R;
- } else { /* pins 0-7 */
- int_reg = (volatile u32 *)IXP23XX_GPIO_GPIT1R;
- }
-
- /*
- * Clear pending interrupts
- */
- *IXP23XX_GPIO_GPISR = (1 << line);
-
- /* Clear the style for the appropriate pin */
- *int_reg &= ~(IXP23XX_GPIO_STYLE_MASK <<
- (line * IXP23XX_GPIO_STYLE_SIZE));
-
- /* Set the new style */
- *int_reg |= (int_style << (line * IXP23XX_GPIO_STYLE_SIZE));
-
- return 0;
-}
-
-static void ixp23xx_irq_mask(struct irq_data *d)
-{
- volatile unsigned long *intr_reg;
- unsigned int irq = d->irq;
-
- if (irq >= 56)
- irq += 8;
-
- intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
- *intr_reg &= ~(1 << (irq % 32));
-}
-
-static void ixp23xx_irq_ack(struct irq_data *d)
-{
- int line = d->irq - IRQ_IXP23XX_GPIO6 + 6;
-
- if ((line < 6) || (line > 15))
- return;
-
- *IXP23XX_GPIO_GPISR = (1 << line);
-}
-
-/*
- * Level triggered interrupts on GPIO lines can only be cleared when the
- * interrupt condition disappears.
- */
-static void ixp23xx_irq_level_unmask(struct irq_data *d)
-{
- volatile unsigned long *intr_reg;
- unsigned int irq = d->irq;
-
- ixp23xx_irq_ack(d);
-
- if (irq >= 56)
- irq += 8;
-
- intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
- *intr_reg |= (1 << (irq % 32));
-}
-
-static void ixp23xx_irq_edge_unmask(struct irq_data *d)
-{
- volatile unsigned long *intr_reg;
- unsigned int irq = d->irq;
-
- if (irq >= 56)
- irq += 8;
-
- intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
- *intr_reg |= (1 << (irq % 32));
-}
-
-static struct irq_chip ixp23xx_irq_level_chip = {
- .irq_ack = ixp23xx_irq_mask,
- .irq_mask = ixp23xx_irq_mask,
- .irq_unmask = ixp23xx_irq_level_unmask,
- .irq_set_type = ixp23xx_irq_set_type
-};
-
-static struct irq_chip ixp23xx_irq_edge_chip = {
- .irq_ack = ixp23xx_irq_ack,
- .irq_mask = ixp23xx_irq_mask,
- .irq_unmask = ixp23xx_irq_edge_unmask,
- .irq_set_type = ixp23xx_irq_set_type
-};
-
-static void ixp23xx_pci_irq_mask(struct irq_data *d)
-{
- unsigned int irq = d->irq;
-
- *IXP23XX_PCI_XSCALE_INT_ENABLE &= ~(1 << (IRQ_IXP23XX_INTA + 27 - irq));
-}
-
-static void ixp23xx_pci_irq_unmask(struct irq_data *d)
-{
- unsigned int irq = d->irq;
-
- *IXP23XX_PCI_XSCALE_INT_ENABLE |= (1 << (IRQ_IXP23XX_INTA + 27 - irq));
-}
-
-/*
- * TODO: Should this just be done at ASM level?
- */
-static void pci_handler(unsigned int irq, struct irq_desc *desc)
-{
- u32 pci_interrupt;
- unsigned int irqno;
-
- pci_interrupt = *IXP23XX_PCI_XSCALE_INT_STATUS;
-
- desc->irq_data.chip->irq_ack(&desc->irq_data);
-
- /* See which PCI_INTA, or PCI_INTB interrupted */
- if (pci_interrupt & (1 << 26)) {
- irqno = IRQ_IXP23XX_INTB;
- } else if (pci_interrupt & (1 << 27)) {
- irqno = IRQ_IXP23XX_INTA;
- } else {
- BUG();
- }
-
- generic_handle_irq(irqno);
-
- desc->irq_data.chip->irq_unmask(&desc->irq_data);
-}
-
-static struct irq_chip ixp23xx_pci_irq_chip = {
- .irq_ack = ixp23xx_pci_irq_mask,
- .irq_mask = ixp23xx_pci_irq_mask,
- .irq_unmask = ixp23xx_pci_irq_unmask
-};
-
-static void ixp23xx_config_irq(unsigned int irq, enum ixp23xx_irq_type type)
-{
- switch (type) {
- case IXP23XX_IRQ_LEVEL:
- irq_set_chip_and_handler(irq, &ixp23xx_irq_level_chip,
- handle_level_irq);
- break;
- case IXP23XX_IRQ_EDGE:
- irq_set_chip_and_handler(irq, &ixp23xx_irq_edge_chip,
- handle_edge_irq);
- break;
- }
- set_irq_flags(irq, IRQF_VALID);
-}
-
-void __init ixp23xx_init_irq(void)
-{
- int irq;
-
- /* Route everything to IRQ */
- *IXP23XX_INTR_SEL1 = 0x0;
- *IXP23XX_INTR_SEL2 = 0x0;
- *IXP23XX_INTR_SEL3 = 0x0;
- *IXP23XX_INTR_SEL4 = 0x0;
-
- /* Mask all sources */
- *IXP23XX_INTR_EN1 = 0x0;
- *IXP23XX_INTR_EN2 = 0x0;
- *IXP23XX_INTR_EN3 = 0x0;
- *IXP23XX_INTR_EN4 = 0x0;
-
- /*
- * Configure all IRQs for level-sensitive operation
- */
- for (irq = 0; irq <= NUM_IXP23XX_RAW_IRQS; irq++) {
- ixp23xx_config_irq(irq, IXP23XX_IRQ_LEVEL);
- }
-
- for (irq = IRQ_IXP23XX_INTA; irq <= IRQ_IXP23XX_INTB; irq++) {
- irq_set_chip_and_handler(irq, &ixp23xx_pci_irq_chip,
- handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- }
-
- irq_set_chained_handler(IRQ_IXP23XX_PCI_INT_RPH, pci_handler);
-}
-
-
-/*************************************************************************
- * Timer-tick functions for IXP23xx
- *************************************************************************/
-#define CLOCK_TICKS_PER_USEC (CLOCK_TICK_RATE / USEC_PER_SEC)
-
-static unsigned long next_jiffy_time;
-
-static unsigned long
-ixp23xx_gettimeoffset(void)
-{
- unsigned long elapsed;
-
- elapsed = *IXP23XX_TIMER_CONT - (next_jiffy_time - LATCH);
-
- return elapsed / CLOCK_TICKS_PER_USEC;
-}
-
-static irqreturn_t
-ixp23xx_timer_interrupt(int irq, void *dev_id)
-{
- /* Clear Pending Interrupt by writing '1' to it */
- *IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND;
- while ((signed long)(*IXP23XX_TIMER_CONT - next_jiffy_time) >= LATCH) {
- timer_tick();
- next_jiffy_time += LATCH;
- }
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction ixp23xx_timer_irq = {
- .name = "IXP23xx Timer Tick",
- .handler = ixp23xx_timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-};
-
-void __init ixp23xx_init_timer(void)
-{
- /* Clear Pending Interrupt by writing '1' to it */
- *IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND;
-
- /* Setup the Timer counter value */
- *IXP23XX_TIMER1_RELOAD =
- (LATCH & ~IXP23XX_TIMER_RELOAD_MASK) | IXP23XX_TIMER_ENABLE;
-
- *IXP23XX_TIMER_CONT = 0;
- next_jiffy_time = LATCH;
-
- /* Connect the interrupt handler and enable the interrupt */
- setup_irq(IRQ_IXP23XX_TIMER1, &ixp23xx_timer_irq);
-}
-
-struct sys_timer ixp23xx_timer = {
- .init = ixp23xx_init_timer,
- .offset = ixp23xx_gettimeoffset,
-};
-
-
-/*************************************************************************
- * IXP23xx Platform Initialization
- *************************************************************************/
-static struct resource ixp23xx_uart_resources[] = {
- {
- .start = IXP23XX_UART1_PHYS,
- .end = IXP23XX_UART1_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM
- }, {
- .start = IXP23XX_UART2_PHYS,
- .end = IXP23XX_UART2_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM
- }
-};
-
-static struct plat_serial8250_port ixp23xx_uart_data[] = {
- {
- .mapbase = IXP23XX_UART1_PHYS,
- .membase = (char *)(IXP23XX_UART1_VIRT + 3),
- .irq = IRQ_IXP23XX_UART1,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP23XX_UART_XTAL,
- }, {
- .mapbase = IXP23XX_UART2_PHYS,
- .membase = (char *)(IXP23XX_UART2_VIRT + 3),
- .irq = IRQ_IXP23XX_UART2,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP23XX_UART_XTAL,
- },
- { },
-};
-
-static struct platform_device ixp23xx_uart = {
- .name = "serial8250",
- .id = 0,
- .dev.platform_data = ixp23xx_uart_data,
- .num_resources = 2,
- .resource = ixp23xx_uart_resources,
-};
-
-static struct platform_device *ixp23xx_devices[] __initdata = {
- &ixp23xx_uart,
-};
-
-void __init ixp23xx_sys_init(void)
-{
- /* by default, the idle code is disabled */
- disable_hlt();
-
- *IXP23XX_EXP_UNIT_FUSE |= 0xf;
- platform_add_devices(ixp23xx_devices, ARRAY_SIZE(ixp23xx_devices));
-}
-
-void ixp23xx_restart(char mode, const char *cmd)
-{
- /* Use on-chip reset capability */
- *IXP23XX_RESET0 |= IXP23XX_RST_ALL;
-}
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c
deleted file mode 100644
index d142d45dea12..000000000000
--- a/arch/arm/mach-ixp23xx/espresso.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/espresso.c
- *
- * Double Espresso-specific routines
- *
- * Author: Lennert Buytenhek <buytenh@wantstofly.org>
- *
- * 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/spinlock.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/bitops.h>
-#include <linux/ioport.h>
-#include <linux/serial_8250.h>
-#include <linux/serial_core.h>
-#include <linux/device.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
-#include <linux/mtd/physmap.h>
-
-#include <asm/types.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-#include <asm/tlbflush.h>
-#include <asm/pgtable.h>
-
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/pci.h>
-
-static int __init espresso_pci_init(void)
-{
- if (machine_is_espresso())
- ixp23xx_pci_slave_init();
-
- return 0;
-};
-subsys_initcall(espresso_pci_init);
-
-static struct physmap_flash_data espresso_flash_data = {
- .width = 2,
-};
-
-static struct resource espresso_flash_resource = {
- .start = 0x90000000,
- .end = 0x91ffffff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device espresso_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &espresso_flash_data,
- },
- .num_resources = 1,
- .resource = &espresso_flash_resource,
-};
-
-static void __init espresso_init(void)
-{
- platform_device_register(&espresso_flash);
-
- /*
- * Mark flash as writeable.
- */
- IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE;
- IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE;
-
- ixp23xx_sys_init();
-}
-
-MACHINE_START(ESPRESSO, "IP Fabrics Double Espresso")
- /* Maintainer: Lennert Buytenhek */
- .map_io = ixp23xx_map_io,
- .init_irq = ixp23xx_init_irq,
- .timer = &ixp23xx_timer,
- .atag_offset = 0x100,
- .init_machine = espresso_init,
- .restart = ixp23xx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-ixp23xx/include/mach/debug-macro.S b/arch/arm/mach-ixp23xx/include/mach/debug-macro.S
deleted file mode 100644
index 5ff524c13744..000000000000
--- a/arch/arm/mach-ixp23xx/include/mach/debug-macro.S
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- * Copyright (C) 1994-1999 Russell King
- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <mach/ixp23xx.h>
-
- .macro addruart, rp, rv, tmp
- ldr \rp, =IXP23XX_PERIPHERAL_PHYS @ physical
- ldr \rv, =IXP23XX_PERIPHERAL_VIRT @ virtual
-#ifdef __ARMEB__
- orr \rp, \rp, #0x00000003
- orr \rv, \rv, #0x00000003
-#endif
- .endm
-
-#define UART_SHIFT 2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-ixp23xx/include/mach/entry-macro.S b/arch/arm/mach-ixp23xx/include/mach/entry-macro.S
deleted file mode 100644
index 3fd2cb984e42..000000000000
--- a/arch/arm/mach-ixp23xx/include/mach/entry-macro.S
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/include/mach/entry-macro.S
- */
-
- .macro get_irqnr_preamble, base, tmp
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- ldr \irqnr, =(IXP23XX_INTC_VIRT + IXP23XX_INTR_IRQ_ENC_ST_OFFSET)
- ldr \irqnr, [\irqnr] @ get interrupt number
- cmp \irqnr, #0x0 @ spurious interrupt ?
- movne \irqnr, \irqnr, lsr #2 @ skip unwanted low order bits
- subne \irqnr, \irqnr, #1 @ convert to 0 based
-
-#if 0
- cmp \irqnr, #IRQ_IXP23XX_PCI_INT_RPH
- bne 1001f
- mov \irqnr, #IRQ_IXP23XX_INTA
-
- ldr \irqnr, =0xf5000030
-
- mov \tmp, #(1<<26)
- tst \irqnr, \tmp
- movne \irqnr, #IRQ_IXP23XX_INTB
-
- mov \tmp, #(1<<27)
- tst \irqnr, \tmp
- movne \irqnr, #IRQ_IXP23XX_INTA
-1001:
-#endif
- .endm
diff --git a/arch/arm/mach-ixp23xx/include/mach/hardware.h b/arch/arm/mach-ixp23xx/include/mach/hardware.h
deleted file mode 100644
index 60e55fa10238..000000000000
--- a/arch/arm/mach-ixp23xx/include/mach/hardware.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/include/mach/hardware.h
- *
- * Copyright (C) 2002-2004 Intel Corporation.
- * Copyricht (C) 2005 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Hardware definitions for IXP23XX based systems
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-/* PCI IO info */
-
-#include "ixp23xx.h"
-
-/*
- * Platform helper functions
- */
-#include "platform.h"
-
-/*
- * Platform-specific headers
- */
-#include "ixdp2351.h"
-
-
-#endif
diff --git a/arch/arm/mach-ixp23xx/include/mach/io.h b/arch/arm/mach-ixp23xx/include/mach/io.h
deleted file mode 100644
index a7aceb55c130..000000000000
--- a/arch/arm/mach-ixp23xx/include/mach/io.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/include/mach/io.h
- *
- * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright (C) 2003-2005 Intel Corp.
- * Copyright (C) 2005 MontaVista Software, Inc
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_IO_H
-#define __ASM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(p) ((void __iomem*)((p) + IXP23XX_PCI_IO_VIRT))
-
-#endif
diff --git a/arch/arm/mach-ixp23xx/include/mach/irqs.h b/arch/arm/mach-ixp23xx/include/mach/irqs.h
deleted file mode 100644
index 3af33a04b8a2..000000000000
--- a/arch/arm/mach-ixp23xx/include/mach/irqs.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/include/mach/irqs.h
- *
- * IRQ definitions for IXP23XX based systems
- *
- * Author: Naeem Afzal <naeem.m.afzal@intel.com>
- *
- * Copyright (C) 2003-2004 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-#define NR_IXP23XX_IRQS IRQ_IXP23XX_INTB+1
-#define IRQ_IXP23XX_EXTIRQS NR_IXP23XX_IRQS
-
-
-#define IRQ_IXP23XX_DBG0 0 /* Debug/Execution/MBox */
-#define IRQ_IXP23XX_DBG1 1 /* Debug/Execution/MBox */
-#define IRQ_IXP23XX_NPE_TRG 2 /* npe_trigger */
-#define IRQ_IXP23XX_TIMER1 3 /* Timer[0] */
-#define IRQ_IXP23XX_TIMER2 4 /* Timer[1] */
-#define IRQ_IXP23XX_TIMESTAMP 5 /* Timer[2], Time-stamp */
-#define IRQ_IXP23XX_WDOG 6 /* Time[3], Watchdog Timer */
-#define IRQ_IXP23XX_PCI_DBELL 7 /* PCI Doorbell */
-#define IRQ_IXP23XX_PCI_DMA1 8 /* PCI DMA Channel 1 */
-#define IRQ_IXP23XX_PCI_DMA2 9 /* PCI DMA Channel 2 */
-#define IRQ_IXP23XX_PCI_DMA3 10 /* PCI DMA Channel 3 */
-#define IRQ_IXP23XX_PCI_INT_RPH 11 /* pcxg_pci_int_rph */
-#define IRQ_IXP23XX_CPP_PMU 12 /* xpxg_pm_int_rpl */
-#define IRQ_IXP23XX_SWINT0 13 /* S/W Interrupt0 */
-#define IRQ_IXP23XX_SWINT1 14 /* S/W Interrupt1 */
-#define IRQ_IXP23XX_UART2 15 /* UART1 Interrupt */
-#define IRQ_IXP23XX_UART1 16 /* UART0 Interrupt */
-#define IRQ_IXP23XX_XSI_PMU_ROLLOVER 17 /* AHB Performance M. Unit counter rollover */
-#define IRQ_IXP23XX_XSI_AHB_PM0 18 /* intr_pm_o */
-#define IRQ_IXP23XX_XSI_AHB_ECE0 19 /* intr_ece_o */
-#define IRQ_IXP23XX_XSI_AHB_GASKET 20 /* gas_intr_o */
-#define IRQ_IXP23XX_XSI_CPP 21 /* xsi2cpp_int */
-#define IRQ_IXP23XX_CPP_XSI 22 /* cpp2xsi_int */
-#define IRQ_IXP23XX_ME_ATTN0 23 /* ME_ATTN */
-#define IRQ_IXP23XX_ME_ATTN1 24 /* ME_ATTN */
-#define IRQ_IXP23XX_ME_ATTN2 25 /* ME_ATTN */
-#define IRQ_IXP23XX_ME_ATTN3 26 /* ME_ATTN */
-#define IRQ_IXP23XX_PCI_ERR_RPH 27 /* PCXG_PCI_ERR_RPH */
-#define IRQ_IXP23XX_D0XG_ECC_CORR 28 /* D0XG_DRAM_ECC_CORR */
-#define IRQ_IXP23XX_D0XG_ECC_UNCORR 29 /* D0XG_DRAM_ECC_UNCORR */
-#define IRQ_IXP23XX_SRAM_ERR1 30 /* SRAM1_ERR */
-#define IRQ_IXP23XX_SRAM_ERR0 31 /* SRAM0_ERR */
-#define IRQ_IXP23XX_MEDIA_ERR 32 /* MEDIA_ERR */
-#define IRQ_IXP23XX_STH_DRAM_ECC_MAJ 33 /* STH_DRAM0_ECC_MAJ */
-#define IRQ_IXP23XX_GPIO6 34 /* GPIO0 interrupts */
-#define IRQ_IXP23XX_GPIO7 35 /* GPIO1 interrupts */
-#define IRQ_IXP23XX_GPIO8 36 /* GPIO2 interrupts */
-#define IRQ_IXP23XX_GPIO9 37 /* GPIO3 interrupts */
-#define IRQ_IXP23XX_GPIO10 38 /* GPIO4 interrupts */
-#define IRQ_IXP23XX_GPIO11 39 /* GPIO5 interrupts */
-#define IRQ_IXP23XX_GPIO12 40 /* GPIO6 interrupts */
-#define IRQ_IXP23XX_GPIO13 41 /* GPIO7 interrupts */
-#define IRQ_IXP23XX_GPIO14 42 /* GPIO8 interrupts */
-#define IRQ_IXP23XX_GPIO15 43 /* GPIO9 interrupts */
-#define IRQ_IXP23XX_SHAC_RING0 44 /* SHAC Ring Full */
-#define IRQ_IXP23XX_SHAC_RING1 45 /* SHAC Ring Full */
-#define IRQ_IXP23XX_SHAC_RING2 46 /* SHAC Ring Full */
-#define IRQ_IXP23XX_SHAC_RING3 47 /* SHAC Ring Full */
-#define IRQ_IXP23XX_SHAC_RING4 48 /* SHAC Ring Full */
-#define IRQ_IXP23XX_SHAC_RING5 49 /* SHAC Ring Full */
-#define IRQ_IXP23XX_SHAC_RING6 50 /* SHAC RING Full */
-#define IRQ_IXP23XX_SHAC_RING7 51 /* SHAC Ring Full */
-#define IRQ_IXP23XX_SHAC_RING8 52 /* SHAC Ring Full */
-#define IRQ_IXP23XX_SHAC_RING9 53 /* SHAC Ring Full */
-#define IRQ_IXP23XX_SHAC_RING10 54 /* SHAC Ring Full */
-#define IRQ_IXP23XX_SHAC_RING11 55 /* SHAC Ring Full */
-#define IRQ_IXP23XX_ME_THREAD_A0_ME0 56 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A1_ME0 57 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A2_ME0 58 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A3_ME0 59 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A4_ME0 60 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A5_ME0 61 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A6_ME0 62 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A7_ME0 63 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A8_ME1 64 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A9_ME1 65 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A10_ME1 66 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A11_ME1 67 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A12_ME1 68 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A13_ME1 69 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A14_ME1 70 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A15_ME1 71 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A16_ME2 72 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A17_ME2 73 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A18_ME2 74 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A19_ME2 75 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A20_ME2 76 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A21_ME2 77 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A22_ME2 78 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A23_ME2 79 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A24_ME3 80 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A25_ME3 81 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A26_ME3 82 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A27_ME3 83 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A28_ME3 84 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A29_ME3 85 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A30_ME3 86 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_A31_ME3 87 /* ME_THREAD_A */
-#define IRQ_IXP23XX_ME_THREAD_B0_ME0 88 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B1_ME0 89 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B2_ME0 90 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B3_ME0 91 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B4_ME0 92 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B5_ME0 93 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B6_ME0 94 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B7_ME0 95 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B8_ME1 96 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B9_ME1 97 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B10_ME1 98 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B11_ME1 99 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B12_ME1 100 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B13_ME1 101 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B14_ME1 102 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B15_ME1 103 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B16_ME2 104 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B17_ME2 105 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B18_ME2 106 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B19_ME2 107 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B20_ME2 108 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B21_ME2 109 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B22_ME2 110 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B23_ME2 111 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B24_ME3 112 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B25_ME3 113 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B26_ME3 114 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B27_ME3 115 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B28_ME3 116 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B29_ME3 117 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B30_ME3 118 /* ME_THREAD_B */
-#define IRQ_IXP23XX_ME_THREAD_B31_ME3 119 /* ME_THREAD_B */
-
-#define NUM_IXP23XX_RAW_IRQS 120
-
-#define IRQ_IXP23XX_INTA 120 /* Indirect pcxg_pci_int_rph */
-#define IRQ_IXP23XX_INTB 121 /* Indirect pcxg_pci_int_rph */
-
-#define NR_IXP23XX_IRQ (IRQ_IXP23XX_INTB + 1)
-
-/*
- * We default to 32 per-board IRQs. Increase this number if you need
- * more, but keep it realistic.
- */
-#define NR_IXP23XX_MACH_IRQS 32
-
-#define NR_IRQS (NR_IXP23XX_IRQS + NR_IXP23XX_MACH_IRQS)
-
-#define IXP23XX_MACH_IRQ(irq) (NR_IXP23XX_IRQ + (irq))
-
-
-/*
- * IXDP2351-specific interrupts
- */
-
-/*
- * External PCI interrupts signaled through INTB
- *
- */
-#define IXDP2351_INTB_IRQ_BASE 0
-#define IRQ_IXDP2351_INTA_82546 IXP23XX_MACH_IRQ(0)
-#define IRQ_IXDP2351_INTB_82546 IXP23XX_MACH_IRQ(1)
-#define IRQ_IXDP2351_SPCI_DB_0 IXP23XX_MACH_IRQ(2)
-#define IRQ_IXDP2351_SPCI_DB_1 IXP23XX_MACH_IRQ(3)
-#define IRQ_IXDP2351_SPCI_PMC_INTA IXP23XX_MACH_IRQ(4)
-#define IRQ_IXDP2351_SPCI_PMC_INTB IXP23XX_MACH_IRQ(5)
-#define IRQ_IXDP2351_SPCI_PMC_INTC IXP23XX_MACH_IRQ(6)
-#define IRQ_IXDP2351_SPCI_PMC_INTD IXP23XX_MACH_IRQ(7)
-#define IRQ_IXDP2351_SPCI_FIC IXP23XX_MACH_IRQ(8)
-
-#define IXDP2351_INTB_IRQ_BIT(irq) (irq - IXP23XX_MACH_IRQ(0))
-#define IXDP2351_INTB_IRQ_MASK(irq) (1 << IXDP2351_INTB_IRQ_BIT(irq))
-#define IXDP2351_INTB_IRQ_VALID 0x01FF
-#define IXDP2351_INTB_IRQ_NUM 16
-
-/*
- * Other external interrupts signaled through INTA
- */
-#define IXDP2351_INTA_IRQ_BASE 16
-#define IRQ_IXDP2351_IPMI_FROM IXP23XX_MACH_IRQ(16)
-#define IRQ_IXDP2351_125US IXP23XX_MACH_IRQ(17)
-#define IRQ_IXDP2351_DB_0_ADD IXP23XX_MACH_IRQ(18)
-#define IRQ_IXDP2351_DB_1_ADD IXP23XX_MACH_IRQ(19)
-#define IRQ_IXDP2351_DEBUG1 IXP23XX_MACH_IRQ(20)
-#define IRQ_IXDP2351_ADD_UART IXP23XX_MACH_IRQ(21)
-#define IRQ_IXDP2351_FIC_ADD IXP23XX_MACH_IRQ(24)
-#define IRQ_IXDP2351_CS8900 IXP23XX_MACH_IRQ(25)
-#define IRQ_IXDP2351_BBSRAM IXP23XX_MACH_IRQ(26)
-#define IRQ_IXDP2351_CONFIG_MEDIA IXP23XX_MACH_IRQ(27)
-#define IRQ_IXDP2351_CLOCK_REF IXP23XX_MACH_IRQ(28)
-#define IRQ_IXDP2351_A10_NP IXP23XX_MACH_IRQ(29)
-#define IRQ_IXDP2351_A11_NP IXP23XX_MACH_IRQ(30)
-#define IRQ_IXDP2351_DEBUG_NP IXP23XX_MACH_IRQ(31)
-
-#define IXDP2351_INTA_IRQ_BIT(irq) (irq - IXP23XX_MACH_IRQ(16))
-#define IXDP2351_INTA_IRQ_MASK(irq) (1 << IXDP2351_INTA_IRQ_BIT(irq))
-#define IXDP2351_INTA_IRQ_VALID 0xFF3F
-#define IXDP2351_INTA_IRQ_NUM 16
-
-
-/*
- * ADI RoadRunner IRQs
- */
-#define IRQ_ROADRUNNER_PCI_INTA IRQ_IXP23XX_INTA
-#define IRQ_ROADRUNNER_PCI_INTB IRQ_IXP23XX_INTB
-#define IRQ_ROADRUNNER_PCI_INTC IRQ_IXP23XX_GPIO11
-#define IRQ_ROADRUNNER_PCI_INTD IRQ_IXP23XX_GPIO12
-
-/*
- * Put new board definitions here
- */
-
-
-#endif
diff --git a/arch/arm/mach-ixp23xx/include/mach/ixdp2351.h b/arch/arm/mach-ixp23xx/include/mach/ixdp2351.h
deleted file mode 100644
index 663951027de5..000000000000
--- a/arch/arm/mach-ixp23xx/include/mach/ixdp2351.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/include/mach/ixdp2351.h
- *
- * Register and other defines for IXDP2351
- *
- * Copyright (c) 2002-2004 Intel Corp.
- * Copytight (c) 2005 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef __ASM_ARCH_IXDP2351_H
-#define __ASM_ARCH_IXDP2351_H
-
-/*
- * NP module memory map
- */
-#define IXDP2351_NP_PHYS_BASE (IXP23XX_EXP_BUS_CS4_BASE)
-#define IXDP2351_NP_PHYS_SIZE 0x00100000
-#define IXDP2351_NP_VIRT_BASE 0xeff00000
-
-#define IXDP2351_VIRT_CS8900_BASE (IXDP2351_NP_VIRT_BASE)
-#define IXDP2351_VIRT_CS8900_END (IXDP2351_VIRT_CS8900_BASE + 16)
-
-#define IXDP2351_VIRT_NP_CPLD_BASE (IXP23XX_EXP_BUS_CS4_BASE_VIRT + 0x00010000)
-
-#define IXDP2351_NP_CPLD_REG(reg) ((volatile u16 *)(IXDP2351_VIRT_NP_CPLD_BASE + reg))
-
-#define IXDP2351_NP_CPLD_RESET1_REG IXDP2351_NP_CPLD_REG(0x00)
-#define IXDP2351_NP_CPLD_LED_REG IXDP2351_NP_CPLD_REG(0x02)
-#define IXDP2351_NP_CPLD_VERSION_REG IXDP2351_NP_CPLD_REG(0x04)
-
-/*
- * Base board module memory map
- */
-
-#define IXDP2351_BB_BASE_PHYS (IXP23XX_EXP_BUS_CS5_BASE)
-#define IXDP2351_BB_SIZE 0x01000000
-#define IXDP2351_BB_BASE_VIRT (0xee000000)
-
-#define IXDP2351_BB_AREA_BASE(offset) (IXDP2351_BB_BASE_VIRT + offset)
-
-#define IXDP2351_VIRT_NVRAM_BASE IXDP2351_BB_AREA_BASE(0x0)
-#define IXDP2351_NVRAM_SIZE (0x20000)
-
-#define IXDP2351_VIRT_MB_IXF1104_BASE IXDP2351_BB_AREA_BASE(0x00020000)
-#define IXDP2351_VIRT_ADD_UART_BASE IXDP2351_BB_AREA_BASE(0x000240C0)
-#define IXDP2351_VIRT_FIC_BASE IXDP2351_BB_AREA_BASE(0x00200000)
-#define IXDP2351_VIRT_DB0_BASE IXDP2351_BB_AREA_BASE(0x00400000)
-#define IXDP2351_VIRT_DB1_BASE IXDP2351_BB_AREA_BASE(0x00600000)
-#define IXDP2351_VIRT_CPLD_BASE IXDP2351_BB_AREA_BASE(0x00024000)
-
-/*
- * On board CPLD registers
- */
-#define IXDP2351_CPLD_BB_REG(reg) ((volatile u16 *)(IXDP2351_VIRT_CPLD_BASE + reg))
-
-#define IXDP2351_CPLD_RESET0_REG IXDP2351_CPLD_BB_REG(0x00)
-#define IXDP2351_CPLD_RESET1_REG IXDP2351_CPLD_BB_REG(0x04)
-
-#define IXDP2351_CPLD_RESET1_MAGIC 0x55AA
-#define IXDP2351_CPLD_RESET1_ENABLE 0x8000
-
-#define IXDP2351_CPLD_FPGA_CONFIG_REG IXDP2351_CPLD_BB_REG(0x08)
-#define IXDP2351_CPLD_INTB_MASK_SET_REG IXDP2351_CPLD_BB_REG(0x10)
-#define IXDP2351_CPLD_INTA_MASK_SET_REG IXDP2351_CPLD_BB_REG(0x14)
-#define IXDP2351_CPLD_INTB_STAT_REG IXDP2351_CPLD_BB_REG(0x18)
-#define IXDP2351_CPLD_INTA_STAT_REG IXDP2351_CPLD_BB_REG(0x1C)
-#define IXDP2351_CPLD_INTB_RAW_REG IXDP2351_CPLD_BB_REG(0x20) /* read */
-#define IXDP2351_CPLD_INTA_RAW_REG IXDP2351_CPLD_BB_REG(0x24) /* read */
-#define IXDP2351_CPLD_INTB_MASK_CLR_REG IXDP2351_CPLD_INTB_RAW_REG /* write */
-#define IXDP2351_CPLD_INTA_MASK_CLR_REG IXDP2351_CPLD_INTA_RAW_REG /* write */
-#define IXDP2351_CPLD_INTB_SIM_REG IXDP2351_CPLD_BB_REG(0x28)
-#define IXDP2351_CPLD_INTA_SIM_REG IXDP2351_CPLD_BB_REG(0x2C)
- /* Interrupt bits are defined in irqs.h */
-#define IXDP2351_CPLD_BB_GBE0_REG IXDP2351_CPLD_BB_REG(0x30)
-#define IXDP2351_CPLD_BB_GBE1_REG IXDP2351_CPLD_BB_REG(0x34)
-
-/* #define IXDP2351_CPLD_BB_MISC_REG IXDP2351_CPLD_REG(0x1C) */
-/* #define IXDP2351_CPLD_BB_MISC_REV_MASK 0xFF */
-/* #define IXDP2351_CPLD_BB_GDXCS0_REG IXDP2351_CPLD_REG(0x24) */
-/* #define IXDP2351_CPLD_BB_GDXCS1_REG IXDP2351_CPLD_REG(0x28) */
-/* #define IXDP2351_CPLD_BB_CLOCK_REG IXDP2351_CPLD_REG(0x04) */
-
-
-#endif
diff --git a/arch/arm/mach-ixp23xx/include/mach/ixp23xx.h b/arch/arm/mach-ixp23xx/include/mach/ixp23xx.h
deleted file mode 100644
index 6d02481b1d6d..000000000000
--- a/arch/arm/mach-ixp23xx/include/mach/ixp23xx.h
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/include/mach/ixp23xx.h
- *
- * Register definitions for IXP23XX
- *
- * Copyright (C) 2003-2005 Intel Corporation.
- * Copyright (C) 2005 MontaVista Software, Inc.
- *
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_IXP23XX_H
-#define __ASM_ARCH_IXP23XX_H
-
-/*
- * IXP2300 linux memory map:
- *
- * virt phys size
- * fffd0000 a0000000 64K XSI2CPP_CSR
- * fffc0000 c4000000 4K EXP_CFG
- * fff00000 c8000000 64K PERIPHERAL
- * fe000000 1c0000000 16M CAP_CSR
- * fd000000 1c8000000 16M MSF_CSR
- * fb000000 16M ---
- * fa000000 1d8000000 32M PCI_IO
- * f8000000 1da000000 32M PCI_CFG
- * f6000000 1de000000 32M PCI_CREG
- * f4000000 32M ---
- * f0000000 1e0000000 64M PCI_MEM
- * e[c-f]000000 per-platform mappings
- */
-
-
-/****************************************************************************
- * Static mappings.
- ****************************************************************************/
-#define IXP23XX_XSI2CPP_CSR_PHYS 0xa0000000
-#define IXP23XX_XSI2CPP_CSR_VIRT 0xfffd0000
-#define IXP23XX_XSI2CPP_CSR_SIZE 0x00010000
-
-#define IXP23XX_EXP_CFG_PHYS 0xc4000000
-#define IXP23XX_EXP_CFG_VIRT 0xfffc0000
-#define IXP23XX_EXP_CFG_SIZE 0x00001000
-
-#define IXP23XX_PERIPHERAL_PHYS 0xc8000000
-#define IXP23XX_PERIPHERAL_VIRT 0xfff00000
-#define IXP23XX_PERIPHERAL_SIZE 0x00010000
-
-#define IXP23XX_CAP_CSR_PHYS 0x1c0000000ULL
-#define IXP23XX_CAP_CSR_VIRT 0xfe000000
-#define IXP23XX_CAP_CSR_SIZE 0x01000000
-
-#define IXP23XX_MSF_CSR_PHYS 0x1c8000000ULL
-#define IXP23XX_MSF_CSR_VIRT 0xfd000000
-#define IXP23XX_MSF_CSR_SIZE 0x01000000
-
-#define IXP23XX_PCI_IO_PHYS 0x1d8000000ULL
-#define IXP23XX_PCI_IO_VIRT 0xfa000000
-#define IXP23XX_PCI_IO_SIZE 0x02000000
-
-#define IXP23XX_PCI_CFG_PHYS 0x1da000000ULL
-#define IXP23XX_PCI_CFG_VIRT 0xf8000000
-#define IXP23XX_PCI_CFG_SIZE 0x02000000
-#define IXP23XX_PCI_CFG0_VIRT IXP23XX_PCI_CFG_VIRT
-#define IXP23XX_PCI_CFG1_VIRT (IXP23XX_PCI_CFG_VIRT + 0x01000000)
-
-#define IXP23XX_PCI_CREG_PHYS 0x1de000000ULL
-#define IXP23XX_PCI_CREG_VIRT 0xf6000000
-#define IXP23XX_PCI_CREG_SIZE 0x02000000
-#define IXP23XX_PCI_CSR_VIRT (IXP23XX_PCI_CREG_VIRT + 0x01000000)
-
-#define IXP23XX_PCI_MEM_START 0xe0000000
-#define IXP23XX_PCI_MEM_PHYS 0x1e0000000ULL
-#define IXP23XX_PCI_MEM_VIRT 0xf0000000
-#define IXP23XX_PCI_MEM_SIZE 0x04000000
-
-
-/****************************************************************************
- * XSI2CPP CSRs.
- ****************************************************************************/
-#define IXP23XX_XSI2CPP_REG(x) ((volatile unsigned long *)(IXP23XX_XSI2CPP_CSR_VIRT + (x)))
-#define IXP23XX_CPP2XSI_CURR_XFER_REG3 IXP23XX_XSI2CPP_REG(0xf8)
-#define IXP23XX_CPP2XSI_ADDR_31 (1 << 19)
-#define IXP23XX_CPP2XSI_PSH_OFF (1 << 20)
-#define IXP23XX_CPP2XSI_COH_OFF (1 << 21)
-
-
-/****************************************************************************
- * Expansion Bus Config.
- ****************************************************************************/
-#define IXP23XX_EXP_CFG_REG(x) ((volatile unsigned long *)(IXP23XX_EXP_CFG_VIRT + (x)))
-#define IXP23XX_EXP_CS0 IXP23XX_EXP_CFG_REG(0x00)
-#define IXP23XX_EXP_CS1 IXP23XX_EXP_CFG_REG(0x04)
-#define IXP23XX_EXP_CS2 IXP23XX_EXP_CFG_REG(0x08)
-#define IXP23XX_EXP_CS3 IXP23XX_EXP_CFG_REG(0x0c)
-#define IXP23XX_EXP_CS4 IXP23XX_EXP_CFG_REG(0x10)
-#define IXP23XX_EXP_CS5 IXP23XX_EXP_CFG_REG(0x14)
-#define IXP23XX_EXP_CS6 IXP23XX_EXP_CFG_REG(0x18)
-#define IXP23XX_EXP_CS7 IXP23XX_EXP_CFG_REG(0x1c)
-#define IXP23XX_FLASH_WRITABLE (0x2)
-#define IXP23XX_FLASH_BUS8 (0x1)
-
-#define IXP23XX_EXP_CFG0 IXP23XX_EXP_CFG_REG(0x20)
-#define IXP23XX_EXP_CFG1 IXP23XX_EXP_CFG_REG(0x24)
-#define IXP23XX_EXP_CFG0_MEM_MAP (1 << 31)
-#define IXP23XX_EXP_CFG0_XSCALE_SPEED_SEL (3 << 22)
-#define IXP23XX_EXP_CFG0_XSCALE_SPEED_EN (1 << 21)
-#define IXP23XX_EXP_CFG0_CPP_SPEED_SEL (3 << 19)
-#define IXP23XX_EXP_CFG0_CPP_SPEED_EN (1 << 18)
-#define IXP23XX_EXP_CFG0_PCI_SWIN (3 << 16)
-#define IXP23XX_EXP_CFG0_PCI_DWIN (3 << 14)
-#define IXP23XX_EXP_CFG0_PCI33_MODE (1 << 13)
-#define IXP23XX_EXP_CFG0_QDR_SPEED_SEL (1 << 12)
-#define IXP23XX_EXP_CFG0_CPP_DIV_SEL (1 << 5)
-#define IXP23XX_EXP_CFG0_XSI_NOT_PRES (1 << 4)
-#define IXP23XX_EXP_CFG0_PROM_BOOT (1 << 3)
-#define IXP23XX_EXP_CFG0_PCI_ARB (1 << 2)
-#define IXP23XX_EXP_CFG0_PCI_HOST (1 << 1)
-#define IXP23XX_EXP_CFG0_FLASH_WIDTH (1 << 0)
-
-#define IXP23XX_EXP_UNIT_FUSE IXP23XX_EXP_CFG_REG(0x28)
-#define IXP23XX_EXP_MSF_MUX IXP23XX_EXP_CFG_REG(0x30)
-#define IXP23XX_EXP_CFG_FUSE IXP23XX_EXP_CFG_REG(0x34)
-
-#define IXP23XX_EXP_BUS_PHYS 0x90000000
-#define IXP23XX_EXP_BUS_WINDOW_SIZE 0x01000000
-
-#define IXP23XX_EXP_BUS_CS0_BASE (IXP23XX_EXP_BUS_PHYS + 0x00000000)
-#define IXP23XX_EXP_BUS_CS1_BASE (IXP23XX_EXP_BUS_PHYS + 0x01000000)
-#define IXP23XX_EXP_BUS_CS2_BASE (IXP23XX_EXP_BUS_PHYS + 0x02000000)
-#define IXP23XX_EXP_BUS_CS3_BASE (IXP23XX_EXP_BUS_PHYS + 0x03000000)
-#define IXP23XX_EXP_BUS_CS4_BASE (IXP23XX_EXP_BUS_PHYS + 0x04000000)
-#define IXP23XX_EXP_BUS_CS5_BASE (IXP23XX_EXP_BUS_PHYS + 0x05000000)
-#define IXP23XX_EXP_BUS_CS6_BASE (IXP23XX_EXP_BUS_PHYS + 0x06000000)
-#define IXP23XX_EXP_BUS_CS7_BASE (IXP23XX_EXP_BUS_PHYS + 0x07000000)
-
-
-/****************************************************************************
- * Peripherals.
- ****************************************************************************/
-#define IXP23XX_UART1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x0000)
-#define IXP23XX_UART2_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x1000)
-#define IXP23XX_PMU_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x2000)
-#define IXP23XX_INTC_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x3000)
-#define IXP23XX_GPIO_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x4000)
-#define IXP23XX_TIMER_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x5000)
-#define IXP23XX_NPE0_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x6000)
-#define IXP23XX_DSR_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x7000)
-#define IXP23XX_NPE1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x8000)
-#define IXP23XX_ETH0_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x9000)
-#define IXP23XX_ETH1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xA000)
-#define IXP23XX_GIG0_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xB000)
-#define IXP23XX_GIG1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xC000)
-#define IXP23XX_DDRS_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xD000)
-
-#define IXP23XX_UART1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x0000)
-#define IXP23XX_UART2_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x1000)
-#define IXP23XX_PMU_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x2000)
-#define IXP23XX_INTC_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x3000)
-#define IXP23XX_GPIO_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x4000)
-#define IXP23XX_TIMER_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x5000)
-#define IXP23XX_NPE0_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x6000)
-#define IXP23XX_DSR_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x7000)
-#define IXP23XX_NPE1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x8000)
-#define IXP23XX_ETH0_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x9000)
-#define IXP23XX_ETH1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xA000)
-#define IXP23XX_GIG0_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xB000)
-#define IXP23XX_GIG1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xC000)
-#define IXP23XX_DDRS_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xD000)
-
-
-/****************************************************************************
- * Interrupt controller.
- ****************************************************************************/
-#define IXP23XX_INTC_REG(x) ((volatile unsigned long *)(IXP23XX_INTC_VIRT + (x)))
-#define IXP23XX_INTR_ST1 IXP23XX_INTC_REG(0x00)
-#define IXP23XX_INTR_ST2 IXP23XX_INTC_REG(0x04)
-#define IXP23XX_INTR_ST3 IXP23XX_INTC_REG(0x08)
-#define IXP23XX_INTR_ST4 IXP23XX_INTC_REG(0x0c)
-#define IXP23XX_INTR_EN1 IXP23XX_INTC_REG(0x10)
-#define IXP23XX_INTR_EN2 IXP23XX_INTC_REG(0x14)
-#define IXP23XX_INTR_EN3 IXP23XX_INTC_REG(0x18)
-#define IXP23XX_INTR_EN4 IXP23XX_INTC_REG(0x1c)
-#define IXP23XX_INTR_SEL1 IXP23XX_INTC_REG(0x20)
-#define IXP23XX_INTR_SEL2 IXP23XX_INTC_REG(0x24)
-#define IXP23XX_INTR_SEL3 IXP23XX_INTC_REG(0x28)
-#define IXP23XX_INTR_SEL4 IXP23XX_INTC_REG(0x2c)
-#define IXP23XX_INTR_IRQ_ST1 IXP23XX_INTC_REG(0x30)
-#define IXP23XX_INTR_IRQ_ST2 IXP23XX_INTC_REG(0x34)
-#define IXP23XX_INTR_IRQ_ST3 IXP23XX_INTC_REG(0x38)
-#define IXP23XX_INTR_IRQ_ST4 IXP23XX_INTC_REG(0x3c)
-#define IXP23XX_INTR_IRQ_ENC_ST_OFFSET 0x54
-
-
-/****************************************************************************
- * GPIO.
- ****************************************************************************/
-#define IXP23XX_GPIO_REG(x) ((volatile unsigned long *)(IXP23XX_GPIO_VIRT + (x)))
-#define IXP23XX_GPIO_GPOUTR IXP23XX_GPIO_REG(0x00)
-#define IXP23XX_GPIO_GPOER IXP23XX_GPIO_REG(0x04)
-#define IXP23XX_GPIO_GPINR IXP23XX_GPIO_REG(0x08)
-#define IXP23XX_GPIO_GPISR IXP23XX_GPIO_REG(0x0c)
-#define IXP23XX_GPIO_GPIT1R IXP23XX_GPIO_REG(0x10)
-#define IXP23XX_GPIO_GPIT2R IXP23XX_GPIO_REG(0x14)
-#define IXP23XX_GPIO_GPCLKR IXP23XX_GPIO_REG(0x18)
-#define IXP23XX_GPIO_GPDBSELR IXP23XX_GPIO_REG(0x1c)
-
-#define IXP23XX_GPIO_STYLE_MASK 0x7
-#define IXP23XX_GPIO_STYLE_ACTIVE_HIGH 0x0
-#define IXP23XX_GPIO_STYLE_ACTIVE_LOW 0x1
-#define IXP23XX_GPIO_STYLE_RISING_EDGE 0x2
-#define IXP23XX_GPIO_STYLE_FALLING_EDGE 0x3
-#define IXP23XX_GPIO_STYLE_TRANSITIONAL 0x4
-
-#define IXP23XX_GPIO_STYLE_SIZE 3
-
-
-/****************************************************************************
- * Timer.
- ****************************************************************************/
-#define IXP23XX_TIMER_REG(x) ((volatile unsigned long *)(IXP23XX_TIMER_VIRT + (x)))
-#define IXP23XX_TIMER_CONT IXP23XX_TIMER_REG(0x00)
-#define IXP23XX_TIMER1_TIMESTAMP IXP23XX_TIMER_REG(0x04)
-#define IXP23XX_TIMER1_RELOAD IXP23XX_TIMER_REG(0x08)
-#define IXP23XX_TIMER2_TIMESTAMP IXP23XX_TIMER_REG(0x0c)
-#define IXP23XX_TIMER2_RELOAD IXP23XX_TIMER_REG(0x10)
-#define IXP23XX_TIMER_WDOG IXP23XX_TIMER_REG(0x14)
-#define IXP23XX_TIMER_WDOG_EN IXP23XX_TIMER_REG(0x18)
-#define IXP23XX_TIMER_WDOG_KEY IXP23XX_TIMER_REG(0x1c)
-#define IXP23XX_TIMER_WDOG_KEY_MAGIC 0x482e
-#define IXP23XX_TIMER_STATUS IXP23XX_TIMER_REG(0x20)
-#define IXP23XX_TIMER_SOFT_RESET IXP23XX_TIMER_REG(0x24)
-#define IXP23XX_TIMER_SOFT_RESET_EN IXP23XX_TIMER_REG(0x28)
-
-#define IXP23XX_TIMER_ENABLE (1 << 0)
-#define IXP23XX_TIMER_ONE_SHOT (1 << 1)
-/* Low order bits of reload value ignored */
-#define IXP23XX_TIMER_RELOAD_MASK (0x3)
-#define IXP23XX_TIMER_DISABLED (0x0)
-#define IXP23XX_TIMER1_INT_PEND (1 << 0)
-#define IXP23XX_TIMER2_INT_PEND (1 << 1)
-#define IXP23XX_TIMER_STATUS_TS_PEND (1 << 2)
-#define IXP23XX_TIMER_STATUS_WDOG_PEND (1 << 3)
-#define IXP23XX_TIMER_STATUS_WARM_RESET (1 << 4)
-
-
-/****************************************************************************
- * CAP CSRs.
- ****************************************************************************/
-#define IXP23XX_GLOBAL_REG(x) ((volatile unsigned long *)(IXP23XX_CAP_CSR_VIRT + 0x4a00 + (x)))
-#define IXP23XX_PRODUCT_ID IXP23XX_GLOBAL_REG(0x00)
-#define IXP23XX_MISC_CONTROL IXP23XX_GLOBAL_REG(0x04)
-#define IXP23XX_MSF_CLK_CNTRL IXP23XX_GLOBAL_REG(0x08)
-#define IXP23XX_RESET0 IXP23XX_GLOBAL_REG(0x0c)
-#define IXP23XX_RESET1 IXP23XX_GLOBAL_REG(0x10)
-#define IXP23XX_STRAP_OPTIONS IXP23XX_GLOBAL_REG(0x18)
-
-#define IXP23XX_ENABLE_WATCHDOG (1 << 24)
-#define IXP23XX_SHPC_INIT_COMP (1 << 21)
-#define IXP23XX_RST_ALL (1 << 16)
-#define IXP23XX_RESET_PCI (1 << 2)
-#define IXP23XX_PCI_UNIT_RESET (1 << 1)
-#define IXP23XX_XSCALE_RESET (1 << 0)
-
-#define IXP23XX_UENGINE_CSR_VIRT_BASE (IXP23XX_CAP_CSR_VIRT + 0x18000)
-
-
-/****************************************************************************
- * PCI CSRs.
- ****************************************************************************/
-#define IXP23XX_PCI_CREG(x) ((volatile unsigned long *)(IXP23XX_PCI_CREG_VIRT + (x)))
-#define IXP23XX_PCI_CMDSTAT IXP23XX_PCI_CREG(0x04)
-#define IXP23XX_PCI_SRAM_BAR IXP23XX_PCI_CREG(0x14)
-#define IXP23XX_PCI_SDRAM_BAR IXP23XX_PCI_CREG(0x18)
-
-
-#define IXP23XX_PCI_CSR(x) ((volatile unsigned long *)(IXP23XX_PCI_CREG_VIRT + 0x01000000 + (x)))
-#define IXP23XX_PCI_OUT_INT_STATUS IXP23XX_PCI_CSR(0x0030)
-#define IXP23XX_PCI_OUT_INT_MASK IXP23XX_PCI_CSR(0x0034)
-#define IXP23XX_PCI_SRAM_BASE_ADDR_MASK IXP23XX_PCI_CSR(0x00fc)
-#define IXP23XX_PCI_DRAM_BASE_ADDR_MASK IXP23XX_PCI_CSR(0x0100)
-#define IXP23XX_PCI_CONTROL IXP23XX_PCI_CSR(0x013c)
-#define IXP23XX_PCI_ADDR_EXT IXP23XX_PCI_CSR(0x0140)
-#define IXP23XX_PCI_ME_PUSH_STATUS IXP23XX_PCI_CSR(0x0148)
-#define IXP23XX_PCI_ME_PUSH_EN IXP23XX_PCI_CSR(0x014c)
-#define IXP23XX_PCI_ERR_STATUS IXP23XX_PCI_CSR(0x0150)
-#define IXP23XX_PCI_ERROR_STATUS IXP23XX_PCI_CSR(0x0150)
-#define IXP23XX_PCI_ERR_ENABLE IXP23XX_PCI_CSR(0x0154)
-#define IXP23XX_PCI_XSCALE_INT_STATUS IXP23XX_PCI_CSR(0x0158)
-#define IXP23XX_PCI_XSCALE_INT_ENABLE IXP23XX_PCI_CSR(0x015c)
-#define IXP23XX_PCI_CPP_ADDR_BITS IXP23XX_PCI_CSR(0x0160)
-
-
-#endif
diff --git a/arch/arm/mach-ixp23xx/include/mach/memory.h b/arch/arm/mach-ixp23xx/include/mach/memory.h
deleted file mode 100644
index 6cf0704e946a..000000000000
--- a/arch/arm/mach-ixp23xx/include/mach/memory.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/include/mach/memory.h
- *
- * Copyright (c) 2003-2004 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <mach/hardware.h>
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET (0x00000000)
-
-#define IXP23XX_PCI_SDRAM_OFFSET (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0)
-
-#define __phys_to_bus(x) ((x) + (IXP23XX_PCI_SDRAM_OFFSET - PHYS_OFFSET))
-#define __bus_to_phys(x) ((x) - (IXP23XX_PCI_SDRAM_OFFSET - PHYS_OFFSET))
-
-#define __virt_to_bus(v) __phys_to_bus(__virt_to_phys(v))
-#define __bus_to_virt(b) __phys_to_virt(__bus_to_phys(b))
-#define __pfn_to_bus(p) __phys_to_bus(__pfn_to_phys(p))
-#define __bus_to_pfn(b) __phys_to_pfn(__bus_to_phys(b))
-
-#define arch_is_coherent() 1
-
-#endif
diff --git a/arch/arm/mach-ixp23xx/include/mach/platform.h b/arch/arm/mach-ixp23xx/include/mach/platform.h
deleted file mode 100644
index 50de558e722e..000000000000
--- a/arch/arm/mach-ixp23xx/include/mach/platform.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/include/mach/platform.h
- *
- * Various bits of code used by platform-level code.
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright 2005 (c) MontaVista Software, Inc.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ASSEMBLY__
-
-static inline unsigned long ixp2000_reg_read(volatile void *reg)
-{
- return *((volatile unsigned long *)reg);
-}
-
-static inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
-{
- *((volatile unsigned long *)reg) = val;
-}
-
-static inline void ixp2000_reg_wrb(volatile void *reg, unsigned long val)
-{
- *((volatile unsigned long *)reg) = val;
-}
-
-struct pci_sys_data;
-
-void ixp23xx_map_io(void);
-void ixp23xx_init_irq(void);
-void ixp23xx_sys_init(void);
-void ixp23xx_restart(char, const char *);
-int ixp23xx_pci_setup(int, struct pci_sys_data *);
-void ixp23xx_pci_preinit(void);
-struct pci_bus *ixp23xx_pci_scan_bus(int, struct pci_sys_data*);
-void ixp23xx_pci_slave_init(void);
-
-extern struct sys_timer ixp23xx_timer;
-
-#define IXP23XX_UART_XTAL 14745600
-
-#ifndef __ASSEMBLY__
-/*
- * Is system memory on the XSI or CPP bus?
- */
-static inline unsigned ixp23xx_cpp_boot(void)
-{
- return (*IXP23XX_EXP_CFG0 & IXP23XX_EXP_CFG0_XSI_NOT_PRES);
-}
-#endif
-
-
-#endif
diff --git a/arch/arm/mach-ixp23xx/include/mach/time.h b/arch/arm/mach-ixp23xx/include/mach/time.h
deleted file mode 100644
index b61dafc884ac..000000000000
--- a/arch/arm/mach-ixp23xx/include/mach/time.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/include/mach/time.h
- */
diff --git a/arch/arm/mach-ixp23xx/include/mach/timex.h b/arch/arm/mach-ixp23xx/include/mach/timex.h
deleted file mode 100644
index e341e9cf9c37..000000000000
--- a/arch/arm/mach-ixp23xx/include/mach/timex.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/include/mach/timex.h
- *
- * XScale architecture timex specifications
- */
-
-#define CLOCK_TICK_RATE 75000000
diff --git a/arch/arm/mach-ixp23xx/include/mach/uncompress.h b/arch/arm/mach-ixp23xx/include/mach/uncompress.h
deleted file mode 100644
index 8b4c358d2c04..000000000000
--- a/arch/arm/mach-ixp23xx/include/mach/uncompress.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/include/mach/uncompress.h
- *
- * Copyright (C) 2002-2004 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-#include <mach/ixp23xx.h>
-#include <linux/serial_reg.h>
-
-#define UART_BASE ((volatile u32 *)IXP23XX_UART1_PHYS)
-
-static inline void putc(char c)
-{
- int j;
-
- for (j = 0; j < 0x1000; j++) {
- if (UART_BASE[UART_LSR] & UART_LSR_THRE)
- break;
- barrier();
- }
-
- UART_BASE[UART_TX] = c;
-}
-
-static inline void flush(void)
-{
-}
-
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
-
-
-#endif
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c
deleted file mode 100644
index b0e07db5ceaf..000000000000
--- a/arch/arm/mach-ixp23xx/ixdp2351.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/ixdp2351.c
- *
- * IXDP2351 board-specific routines
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright 2005 (c) MontaVista Software, Inc.
- *
- * Based on 2.4 code Copyright 2004 (c) Intel Corporation
- *
- * 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/spinlock.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/bitops.h>
-#include <linux/ioport.h>
-#include <linux/serial_8250.h>
-#include <linux/serial_core.h>
-#include <linux/device.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
-#include <linux/mtd/physmap.h>
-
-#include <asm/types.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/tlbflush.h>
-#include <asm/pgtable.h>
-
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/pci.h>
-
-/*
- * IXDP2351 Interrupt Handling
- */
-static void ixdp2351_inta_mask(struct irq_data *d)
-{
- *IXDP2351_CPLD_INTA_MASK_SET_REG = IXDP2351_INTA_IRQ_MASK(d->irq);
-}
-
-static void ixdp2351_inta_unmask(struct irq_data *d)
-{
- *IXDP2351_CPLD_INTA_MASK_CLR_REG = IXDP2351_INTA_IRQ_MASK(d->irq);
-}
-
-static void ixdp2351_inta_handler(unsigned int irq, struct irq_desc *desc)
-{
- u16 ex_interrupt =
- *IXDP2351_CPLD_INTA_STAT_REG & IXDP2351_INTA_IRQ_VALID;
- int i;
-
- desc->irq_data.chip->irq_mask(&desc->irq_data);
-
- for (i = 0; i < IXDP2351_INTA_IRQ_NUM; i++) {
- if (ex_interrupt & (1 << i)) {
- int cpld_irq =
- IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i);
- generic_handle_irq(cpld_irq);
- }
- }
-
- desc->irq_data.chip->irq_unmask(&desc->irq_data);
-}
-
-static struct irq_chip ixdp2351_inta_chip = {
- .irq_ack = ixdp2351_inta_mask,
- .irq_mask = ixdp2351_inta_mask,
- .irq_unmask = ixdp2351_inta_unmask
-};
-
-static void ixdp2351_intb_mask(struct irq_data *d)
-{
- *IXDP2351_CPLD_INTB_MASK_SET_REG = IXDP2351_INTB_IRQ_MASK(d->irq);
-}
-
-static void ixdp2351_intb_unmask(struct irq_data *d)
-{
- *IXDP2351_CPLD_INTB_MASK_CLR_REG = IXDP2351_INTB_IRQ_MASK(d->irq);
-}
-
-static void ixdp2351_intb_handler(unsigned int irq, struct irq_desc *desc)
-{
- u16 ex_interrupt =
- *IXDP2351_CPLD_INTB_STAT_REG & IXDP2351_INTB_IRQ_VALID;
- int i;
-
- desc->irq_data.chip->irq_ack(&desc->irq_data);
-
- for (i = 0; i < IXDP2351_INTB_IRQ_NUM; i++) {
- if (ex_interrupt & (1 << i)) {
- int cpld_irq =
- IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i);
- generic_handle_irq(cpld_irq);
- }
- }
-
- desc->irq_data.chip->irq_unmask(&desc->irq_data);
-}
-
-static struct irq_chip ixdp2351_intb_chip = {
- .irq_ack = ixdp2351_intb_mask,
- .irq_mask = ixdp2351_intb_mask,
- .irq_unmask = ixdp2351_intb_unmask
-};
-
-void __init ixdp2351_init_irq(void)
-{
- int irq;
-
- /* Mask all interrupts from CPLD, disable simulation */
- *IXDP2351_CPLD_INTA_MASK_SET_REG = (u16) -1;
- *IXDP2351_CPLD_INTB_MASK_SET_REG = (u16) -1;
- *IXDP2351_CPLD_INTA_SIM_REG = 0;
- *IXDP2351_CPLD_INTB_SIM_REG = 0;
-
- ixp23xx_init_irq();
-
- for (irq = IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE);
- irq <
- IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + IXDP2351_INTA_IRQ_NUM);
- irq++) {
- if (IXDP2351_INTA_IRQ_MASK(irq) & IXDP2351_INTA_IRQ_VALID) {
- set_irq_flags(irq, IRQF_VALID);
- irq_set_chip_and_handler(irq, &ixdp2351_inta_chip,
- handle_level_irq);
- }
- }
-
- for (irq = IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE);
- irq <
- IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + IXDP2351_INTB_IRQ_NUM);
- irq++) {
- if (IXDP2351_INTB_IRQ_MASK(irq) & IXDP2351_INTB_IRQ_VALID) {
- set_irq_flags(irq, IRQF_VALID);
- irq_set_chip_and_handler(irq, &ixdp2351_intb_chip,
- handle_level_irq);
- }
- }
-
- irq_set_chained_handler(IRQ_IXP23XX_INTA, ixdp2351_inta_handler);
- irq_set_chained_handler(IRQ_IXP23XX_INTB, ixdp2351_intb_handler);
-}
-
-/*
- * IXDP2351 PCI
- */
-
-/*
- * This board does not do normal PCI IRQ routing, or any
- * sort of swizzling, so we just need to check where on the
- * bus the device is and figure out what CPLD pin it is
- * being routed to.
- */
-#define DEVPIN(dev, pin) ((pin) | ((dev) << 3))
-
-static int __init ixdp2351_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- u8 bus = dev->bus->number;
- u32 devpin = DEVPIN(PCI_SLOT(dev->devfn), pin);
- struct pci_bus *tmp_bus = dev->bus;
-
- /* Primary bus, no interrupts here */
- if (!bus)
- return -1;
-
- /* Lookup first leaf in bus tree */
- while ((tmp_bus->parent != NULL) && (tmp_bus->parent->parent != NULL))
- tmp_bus = tmp_bus->parent;
-
- /* Select between known bridges */
- switch (tmp_bus->self->devfn | (tmp_bus->self->bus->number << 8)) {
- /* Device is located after first bridge */
- case 0x0008:
- if (tmp_bus == dev->bus) {
- /* Device is located directy after first bridge */
- switch (devpin) {
- /* Onboard 82546 */
- case DEVPIN(1, 1): /* Onboard 82546 ch 0 */
- return IRQ_IXDP2351_INTA_82546;
- case DEVPIN(1, 2): /* Onboard 82546 ch 1 */
- return IRQ_IXDP2351_INTB_82546;
- /* PMC SLOT */
- case DEVPIN(0, 1): /* PMCP INTA# */
- case DEVPIN(2, 4): /* PMCS INTD# */
- return IRQ_IXDP2351_SPCI_PMC_INTA;
- case DEVPIN(0, 2): /* PMCP INTB# */
- case DEVPIN(2, 1): /* PMCS INTA# */
- return IRQ_IXDP2351_SPCI_PMC_INTB;
- case DEVPIN(0, 3): /* PMCP INTC# */
- case DEVPIN(2, 2): /* PMCS INTB# */
- return IRQ_IXDP2351_SPCI_PMC_INTC;
- case DEVPIN(0, 4): /* PMCP INTD# */
- case DEVPIN(2, 3): /* PMCS INTC# */
- return IRQ_IXDP2351_SPCI_PMC_INTD;
- }
- } else {
- /* Device is located indirectly after first bridge */
- /* Not supported now */
- return -1;
- }
- break;
- case 0x0010:
- if (tmp_bus == dev->bus) {
- /* Device is located directy after second bridge */
- /* Secondary bus of second bridge */
- switch (devpin) {
- case DEVPIN(0, 1): /* DB#0 */
- case DEVPIN(0, 2):
- case DEVPIN(0, 3):
- case DEVPIN(0, 4):
- return IRQ_IXDP2351_SPCI_DB_0;
- case DEVPIN(1, 1): /* DB#1 */
- case DEVPIN(1, 2):
- case DEVPIN(1, 3):
- case DEVPIN(1, 4):
- return IRQ_IXDP2351_SPCI_DB_1;
- case DEVPIN(2, 1): /* FIC1 */
- case DEVPIN(2, 2):
- case DEVPIN(2, 3):
- case DEVPIN(2, 4):
- case DEVPIN(3, 1): /* FIC2 */
- case DEVPIN(3, 2):
- case DEVPIN(3, 3):
- case DEVPIN(3, 4):
- return IRQ_IXDP2351_SPCI_FIC;
- }
- } else {
- /* Device is located indirectly after second bridge */
- /* Not supported now */
- return -1;
- }
- break;
- }
-
- return -1;
-}
-
-struct hw_pci ixdp2351_pci __initdata = {
- .nr_controllers = 1,
- .preinit = ixp23xx_pci_preinit,
- .setup = ixp23xx_pci_setup,
- .scan = ixp23xx_pci_scan_bus,
- .map_irq = ixdp2351_map_irq,
-};
-
-int __init ixdp2351_pci_init(void)
-{
- if (machine_is_ixdp2351())
- pci_common_init(&ixdp2351_pci);
-
- return 0;
-}
-
-subsys_initcall(ixdp2351_pci_init);
-
-/*
- * IXDP2351 Static Mapped I/O
- */
-static struct map_desc ixdp2351_io_desc[] __initdata = {
- {
- .virtual = IXDP2351_NP_VIRT_BASE,
- .pfn = __phys_to_pfn((u64)IXDP2351_NP_PHYS_BASE),
- .length = IXDP2351_NP_PHYS_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = IXDP2351_BB_BASE_VIRT,
- .pfn = __phys_to_pfn((u64)IXDP2351_BB_BASE_PHYS),
- .length = IXDP2351_BB_SIZE,
- .type = MT_DEVICE
- }
-};
-
-static void __init ixdp2351_map_io(void)
-{
- ixp23xx_map_io();
- iotable_init(ixdp2351_io_desc, ARRAY_SIZE(ixdp2351_io_desc));
-}
-
-static struct physmap_flash_data ixdp2351_flash_data = {
- .width = 1,
-};
-
-static struct resource ixdp2351_flash_resource = {
- .start = 0x90000000,
- .end = 0x93ffffff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device ixdp2351_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &ixdp2351_flash_data,
- },
- .num_resources = 1,
- .resource = &ixdp2351_flash_resource,
-};
-
-static void __init ixdp2351_init(void)
-{
- platform_device_register(&ixdp2351_flash);
-
- /*
- * Mark flash as writeable
- */
- IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE;
- IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE;
- IXP23XX_EXP_CS0[2] |= IXP23XX_FLASH_WRITABLE;
- IXP23XX_EXP_CS0[3] |= IXP23XX_FLASH_WRITABLE;
-
- ixp23xx_sys_init();
-}
-
-static void ixdp2351_restart(char mode, const char *cmd)
-{
- /* First try machine specific support */
-
- *IXDP2351_CPLD_RESET1_REG = IXDP2351_CPLD_RESET1_MAGIC;
- (void) *IXDP2351_CPLD_RESET1_REG;
- *IXDP2351_CPLD_RESET1_REG = IXDP2351_CPLD_RESET1_ENABLE;
-
- ixp23xx_restart(mode, cmd);
-}
-
-MACHINE_START(IXDP2351, "Intel IXDP2351 Development Platform")
- /* Maintainer: MontaVista Software, Inc. */
- .map_io = ixdp2351_map_io,
- .init_irq = ixdp2351_init_irq,
- .timer = &ixp23xx_timer,
- .atag_offset = 0x100,
- .init_machine = ixdp2351_init,
- .restart = ixdp2351_restart,
-MACHINE_END
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c
deleted file mode 100644
index 911f5a58e006..000000000000
--- a/arch/arm/mach-ixp23xx/pci.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/pci.c
- *
- * PCI routines for IXP23XX based systems
- *
- * Copyright (c) 2005 MontaVista Software, Inc.
- *
- * based on original code:
- *
- * Author: Naeem Afzal <naeem.m.afzal@intel.com>
- * Copyright 2002-2005 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/sizes.h>
-#include <asm/mach/pci.h>
-#include <mach/hardware.h>
-
-extern int (*external_fault) (unsigned long, struct pt_regs *);
-
-static volatile int pci_master_aborts = 0;
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-int clear_master_aborts(void);
-
-static u32
-*ixp23xx_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where)
-{
- u32 *paddress;
-
- /*
- * Must be dword aligned
- */
- where &= ~3;
-
- /*
- * For top bus, generate type 0, else type 1
- */
- if (!bus_nr) {
- if (PCI_SLOT(devfn) >= 8)
- return 0;
-
- paddress = (u32 *) (IXP23XX_PCI_CFG0_VIRT
- | (1 << (PCI_SLOT(devfn) + 16))
- | (PCI_FUNC(devfn) << 8) | where);
- } else {
- paddress = (u32 *) (IXP23XX_PCI_CFG1_VIRT
- | (bus_nr << 16)
- | (PCI_SLOT(devfn) << 11)
- | (PCI_FUNC(devfn) << 8) | where);
- }
-
- return paddress;
-}
-
-/*
- * Mask table, bits to mask for quantity of size 1, 2 or 4 bytes.
- * 0 and 3 are not valid indexes...
- */
-static u32 bytemask[] = {
- /*0*/ 0,
- /*1*/ 0xff,
- /*2*/ 0xffff,
- /*3*/ 0,
- /*4*/ 0xffffffff,
-};
-
-static int ixp23xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 *value)
-{
- u32 n;
- u32 *addr;
-
- n = where % 4;
-
- DBG("In config_read(%d) %d from dev %d:%d:%d\n", size, where,
- bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
-
- addr = ixp23xx_pci_config_addr(bus->number, devfn, where);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- pci_master_aborts = 0;
- *value = (*addr >> (8*n)) & bytemask[size];
- if (pci_master_aborts) {
- pci_master_aborts = 0;
- *value = 0xffffffff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-/*
- * We don't do error checking on the address for writes.
- * It's assumed that the user checked for the device existing first
- * by doing a read first.
- */
-static int ixp23xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 value)
-{
- u32 mask;
- u32 *addr;
- u32 temp;
-
- mask = ~(bytemask[size] << ((where % 0x4) * 8));
- addr = ixp23xx_pci_config_addr(bus->number, devfn, where);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
- temp = (u32) (value) << ((where % 0x4) * 8);
- *addr = (*addr & mask) | temp;
-
- clear_master_aborts();
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops ixp23xx_pci_ops = {
- .read = ixp23xx_pci_read_config,
- .write = ixp23xx_pci_write_config,
-};
-
-struct pci_bus *ixp23xx_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
-{
- return pci_scan_root_bus(NULL, sysdata->busnr, &ixp23xx_pci_ops,
- sysdata, &sysdata->resources);
-}
-
-int ixp23xx_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
- volatile unsigned long temp;
- unsigned long flags;
-
- pci_master_aborts = 1;
-
- local_irq_save(flags);
- temp = *IXP23XX_PCI_CONTROL;
-
- /*
- * master abort and cmd tgt err
- */
- if (temp & ((1 << 8) | (1 << 5)))
- *IXP23XX_PCI_CONTROL = temp;
-
- temp = *IXP23XX_PCI_CMDSTAT;
-
- if (temp & (1 << 29))
- *IXP23XX_PCI_CMDSTAT = temp;
- local_irq_restore(flags);
-
- /*
- * If it was an imprecise abort, then we need to correct the
- * return address to be _after_ the instruction.
- */
- if (fsr & (1 << 10))
- regs->ARM_pc += 4;
-
- return 0;
-}
-
-int clear_master_aborts(void)
-{
- volatile u32 temp;
-
- temp = *IXP23XX_PCI_CONTROL;
-
- /*
- * master abort and cmd tgt err
- */
- if (temp & ((1 << 8) | (1 << 5)))
- *IXP23XX_PCI_CONTROL = temp;
-
- temp = *IXP23XX_PCI_CMDSTAT;
-
- if (temp & (1 << 29))
- *IXP23XX_PCI_CMDSTAT = temp;
-
- return 0;
-}
-
-static void __init ixp23xx_pci_common_init(void)
-{
-#ifdef __ARMEB__
- *IXP23XX_PCI_CONTROL |= 0x20000; /* set I/O swapping */
-#endif
- /*
- * ADDR_31 needs to be clear for PCI memory access to CPP memory
- */
- *IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_ADDR_31;
- *IXP23XX_CPP2XSI_CURR_XFER_REG3 |= IXP23XX_CPP2XSI_PSH_OFF;
-
- /*
- * Select correct memory for PCI inbound transactions
- */
- if (ixp23xx_cpp_boot()) {
- *IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1);
- } else {
- *IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1);
-
- /*
- * Enable coherency on A2 silicon.
- */
- if (arch_is_coherent())
- *IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_COH_OFF;
- }
-}
-
-void __init ixp23xx_pci_preinit(void)
-{
- pcibios_min_io = 0;
- pcibios_min_mem = 0xe0000000;
-
- pci_set_flags(0);
-
- ixp23xx_pci_common_init();
-
- hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS, 0,
- "PCI config cycle to non-existent device");
-
- *IXP23XX_PCI_ADDR_EXT = 0x0000e000;
-}
-
-/*
- * Prevent PCI layer from seeing the inbound host-bridge resources
- */
-static void __devinit pci_fixup_ixp23xx(struct pci_dev *dev)
-{
- int i;
-
- dev->class &= 0xff;
- dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- dev->resource[i].start = 0;
- dev->resource[i].end = 0;
- dev->resource[i].flags = 0;
- }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9002, pci_fixup_ixp23xx);
-
-/*
- * IXP2300 systems often have large resource requirements, so we just
- * use our own resource space.
- */
-static struct resource ixp23xx_pci_mem_space = {
- .start = IXP23XX_PCI_MEM_START,
- .end = IXP23XX_PCI_MEM_START + IXP23XX_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM,
- .name = "PCI Mem Space"
-};
-
-static struct resource ixp23xx_pci_io_space = {
- .start = 0x00000100,
- .end = 0x01ffffff,
- .flags = IORESOURCE_IO,
- .name = "PCI I/O Space"
-};
-
-int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys)
-{
- if (nr >= 1)
- return 0;
-
- pci_add_resource_offset(&sys->resources,
- &ixp23xx_pci_io_space, sys->io_offset);
- pci_add_resource_offset(&sys->resources,
- &ixp23xx_pci_mem_space, sys->mem_offset);
-
- return 1;
-}
-
-void __init ixp23xx_pci_slave_init(void)
-{
- ixp23xx_pci_common_init();
-}
diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c
deleted file mode 100644
index eaaa3fa9fd05..000000000000
--- a/arch/arm/mach-ixp23xx/roadrunner.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * arch/arm/mach-ixp23xx/roadrunner.c
- *
- * RoadRunner board-specific routines
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright 2005 (c) MontaVista Software, Inc.
- *
- * Based on 2.4 code Copyright 2005 (c) ADI Engineering Corporation
- *
- * 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/spinlock.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/bitops.h>
-#include <linux/ioport.h>
-#include <linux/serial_8250.h>
-#include <linux/serial_core.h>
-#include <linux/device.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
-#include <linux/mtd/physmap.h>
-
-#include <asm/types.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-#include <asm/tlbflush.h>
-#include <asm/pgtable.h>
-
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/pci.h>
-
-/*
- * Interrupt mapping
- */
-#define INTA IRQ_ROADRUNNER_PCI_INTA
-#define INTB IRQ_ROADRUNNER_PCI_INTB
-#define INTC IRQ_ROADRUNNER_PCI_INTC
-#define INTD IRQ_ROADRUNNER_PCI_INTD
-
-#define INTC_PIN IXP23XX_GPIO_PIN_11
-#define INTD_PIN IXP23XX_GPIO_PIN_12
-
-static int __init roadrunner_map_irq(const struct pci_dev *dev, u8 idsel,
- u8 pin)
-{
- static int pci_card_slot_irq[] = {INTB, INTC, INTD, INTA};
- static int pmc_card_slot_irq[] = {INTA, INTB, INTC, INTD};
- static int usb_irq[] = {INTB, INTC, INTD, -1};
- static int mini_pci_1_irq[] = {INTB, INTC, -1, -1};
- static int mini_pci_2_irq[] = {INTC, INTD, -1, -1};
-
- switch(dev->bus->number) {
- case 0:
- switch(dev->devfn) {
- case 0x0: // PCI-PCI bridge
- break;
- case 0x8: // PCI Card Slot
- return pci_card_slot_irq[pin - 1];
- case 0x10: // PMC Slot
- return pmc_card_slot_irq[pin - 1];
- case 0x18: // PMC Slot Secondary Agent
- break;
- case 0x20: // IXP Processor
- break;
- default:
- return NO_IRQ;
- }
- break;
-
- case 1:
- switch(dev->devfn) {
- case 0x0: // IDE Controller
- return (pin == 1) ? INTC : -1;
- case 0x8: // USB fun 0
- case 0x9: // USB fun 1
- case 0xa: // USB fun 2
- return usb_irq[pin - 1];
- case 0x10: // Mini PCI 1
- return mini_pci_1_irq[pin-1];
- case 0x18: // Mini PCI 2
- return mini_pci_2_irq[pin-1];
- case 0x20: // MEM slot
- return (pin == 1) ? INTA : -1;
- default:
- return NO_IRQ;
- }
- break;
-
- default:
- return NO_IRQ;
- }
-
- return NO_IRQ;
-}
-
-static void __init roadrunner_pci_preinit(void)
-{
- irq_set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
-
- ixp23xx_pci_preinit();
-}
-
-static struct hw_pci roadrunner_pci __initdata = {
- .nr_controllers = 1,
- .preinit = roadrunner_pci_preinit,
- .setup = ixp23xx_pci_setup,
- .scan = ixp23xx_pci_scan_bus,
- .map_irq = roadrunner_map_irq,
-};
-
-static int __init roadrunner_pci_init(void)
-{
- if (machine_is_roadrunner())
- pci_common_init(&roadrunner_pci);
-
- return 0;
-};
-
-subsys_initcall(roadrunner_pci_init);
-
-static struct physmap_flash_data roadrunner_flash_data = {
- .width = 2,
-};
-
-static struct resource roadrunner_flash_resource = {
- .start = 0x90000000,
- .end = 0x93ffffff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device roadrunner_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &roadrunner_flash_data,
- },
- .num_resources = 1,
- .resource = &roadrunner_flash_resource,
-};
-
-static void __init roadrunner_init(void)
-{
- platform_device_register(&roadrunner_flash);
-
- /*
- * Mark flash as writeable
- */
- IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE;
- IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE;
- IXP23XX_EXP_CS0[2] |= IXP23XX_FLASH_WRITABLE;
- IXP23XX_EXP_CS0[3] |= IXP23XX_FLASH_WRITABLE;
-
- ixp23xx_sys_init();
-}
-
-MACHINE_START(ROADRUNNER, "ADI Engineering RoadRunner Development Platform")
- /* Maintainer: Deepak Saxena */
- .map_io = ixp23xx_map_io,
- .init_irq = ixp23xx_init_irq,
- .timer = &ixp23xx_timer,
- .atag_offset = 0x100,
- .init_machine = roadrunner_init,
- .restart = ixp23xx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/avila-pci.c b/arch/arm/mach-ixp4xx/avila-pci.c
index 8fea0a3c5246..548c7d43ade6 100644
--- a/arch/arm/mach-ixp4xx/avila-pci.c
+++ b/arch/arm/mach-ixp4xx/avila-pci.c
@@ -65,10 +65,9 @@ static int __init avila_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
struct hw_pci avila_pci __initdata = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = avila_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = avila_map_irq,
};
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index d5719eb42591..1694f01ce2b6 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -480,12 +480,6 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys)
return 1;
}
-struct pci_bus * __devinit ixp4xx_scan_bus(int nr, struct pci_sys_data *sys)
-{
- return pci_scan_root_bus(NULL, sys->busnr, &ixp4xx_ops, sys,
- &sys->resources);
-}
-
int dma_set_coherent_mask(struct device *dev, u64 mask)
{
if (mask >= SZ_64M - 1)
diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c
index 71f5c9c60fc3..5d14ce2aee6d 100644
--- a/arch/arm/mach-ixp4xx/coyote-pci.c
+++ b/arch/arm/mach-ixp4xx/coyote-pci.c
@@ -48,10 +48,9 @@ static int __init coyote_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
struct hw_pci coyote_pci __initdata = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = coyote_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = coyote_map_irq,
};
diff --git a/arch/arm/mach-ixp4xx/dsmg600-pci.c b/arch/arm/mach-ixp4xx/dsmg600-pci.c
index 0532510b5e8c..8dca76937723 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-pci.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-pci.c
@@ -62,10 +62,9 @@ static int __init dsmg600_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
struct hw_pci __initdata dsmg600_pci = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = dsmg600_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = dsmg600_map_irq,
};
diff --git a/arch/arm/mach-ixp4xx/fsg-pci.c b/arch/arm/mach-ixp4xx/fsg-pci.c
index d2ac803328f7..fd4a8625b4ae 100644
--- a/arch/arm/mach-ixp4xx/fsg-pci.c
+++ b/arch/arm/mach-ixp4xx/fsg-pci.c
@@ -59,10 +59,9 @@ static int __init fsg_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
struct hw_pci fsg_pci __initdata = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = fsg_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = fsg_map_irq,
};
diff --git a/arch/arm/mach-ixp4xx/gateway7001-pci.c b/arch/arm/mach-ixp4xx/gateway7001-pci.c
index 76581fb467c4..d9d6cc089707 100644
--- a/arch/arm/mach-ixp4xx/gateway7001-pci.c
+++ b/arch/arm/mach-ixp4xx/gateway7001-pci.c
@@ -47,10 +47,9 @@ static int __init gateway7001_map_irq(const struct pci_dev *dev, u8 slot,
struct hw_pci gateway7001_pci __initdata = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = gateway7001_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = gateway7001_map_irq,
};
diff --git a/arch/arm/mach-ixp4xx/goramo_mlr.c b/arch/arm/mach-ixp4xx/goramo_mlr.c
index 46bb924962ee..b800a031207c 100644
--- a/arch/arm/mach-ixp4xx/goramo_mlr.c
+++ b/arch/arm/mach-ixp4xx/goramo_mlr.c
@@ -473,11 +473,10 @@ static int __init gmlr_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
static struct hw_pci gmlr_hw_pci __initdata = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = gmlr_pci_preinit,
.postinit = gmlr_pci_postinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = gmlr_map_irq,
};
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
index d68fc068c38d..551d114c9e14 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
@@ -67,10 +67,9 @@ static int __init gtwx5715_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
struct hw_pci gtwx5715_pci __initdata = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = gtwx5715_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = gtwx5715_map_irq,
};
diff --git a/arch/arm/mach-ixp4xx/include/mach/platform.h b/arch/arm/mach-ixp4xx/include/mach/platform.h
index b66bedc64de1..5bce94aacca9 100644
--- a/arch/arm/mach-ixp4xx/include/mach/platform.h
+++ b/arch/arm/mach-ixp4xx/include/mach/platform.h
@@ -130,7 +130,7 @@ extern void ixp4xx_restart(char, const char *);
extern void ixp4xx_pci_preinit(void);
struct pci_sys_data;
extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
-extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
+extern struct pci_ops ixp4xx_ops;
/*
* GPIO-functions
diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c
index fffd8c5e40bf..318424dd3c50 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c
@@ -60,10 +60,9 @@ static int __init ixdp425_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
struct hw_pci ixdp425_pci __initdata = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = ixdp425_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = ixdp425_map_irq,
};
diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
index 34efe75015ec..1f8717ba13dc 100644
--- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
@@ -42,10 +42,9 @@ static int __init ixdpg425_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
struct hw_pci ixdpg425_pci __initdata = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = ixdpg425_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = ixdpg425_map_irq,
};
diff --git a/arch/arm/mach-ixp4xx/miccpt-pci.c b/arch/arm/mach-ixp4xx/miccpt-pci.c
index ca0bae7fca90..d114ccd2017c 100644
--- a/arch/arm/mach-ixp4xx/miccpt-pci.c
+++ b/arch/arm/mach-ixp4xx/miccpt-pci.c
@@ -61,10 +61,9 @@ static int __init miccpt_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
struct hw_pci miccpt_pci __initdata = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = miccpt_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = miccpt_map_irq,
};
diff --git a/arch/arm/mach-ixp4xx/nas100d-pci.c b/arch/arm/mach-ixp4xx/nas100d-pci.c
index 5434ccf553eb..8f0eba0a6800 100644
--- a/arch/arm/mach-ixp4xx/nas100d-pci.c
+++ b/arch/arm/mach-ixp4xx/nas100d-pci.c
@@ -58,10 +58,9 @@ static int __init nas100d_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
struct hw_pci __initdata nas100d_pci = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = nas100d_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = nas100d_map_irq,
};
diff --git a/arch/arm/mach-ixp4xx/nslu2-pci.c b/arch/arm/mach-ixp4xx/nslu2-pci.c
index b57160535e47..032defe111aa 100644
--- a/arch/arm/mach-ixp4xx/nslu2-pci.c
+++ b/arch/arm/mach-ixp4xx/nslu2-pci.c
@@ -54,10 +54,9 @@ static int __init nslu2_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
struct hw_pci __initdata nslu2_pci = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = nslu2_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = nslu2_map_irq,
};
diff --git a/arch/arm/mach-ixp4xx/vulcan-pci.c b/arch/arm/mach-ixp4xx/vulcan-pci.c
index 0bc3f34c282f..a4220fa5e0c3 100644
--- a/arch/arm/mach-ixp4xx/vulcan-pci.c
+++ b/arch/arm/mach-ixp4xx/vulcan-pci.c
@@ -56,10 +56,9 @@ static int __init vulcan_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
struct hw_pci vulcan_pci __initdata = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = vulcan_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = vulcan_map_irq,
};
diff --git a/arch/arm/mach-ixp4xx/wg302v2-pci.c b/arch/arm/mach-ixp4xx/wg302v2-pci.c
index f27dfcfe811b..c92e5b82af36 100644
--- a/arch/arm/mach-ixp4xx/wg302v2-pci.c
+++ b/arch/arm/mach-ixp4xx/wg302v2-pci.c
@@ -46,10 +46,9 @@ static int __init wg302v2_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
struct hw_pci wg302v2_pci __initdata = {
.nr_controllers = 1,
+ .ops = &ixp4xx_ops,
.preinit = wg302v2_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
.map_irq = wg302v2_map_irq,
};
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index 90ceab761929..199764fe0fb0 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -58,6 +58,28 @@ config MACH_DREAMPLUG_DT
Say 'Y' here if you want your kernel to support the
Marvell DreamPlug (Flattened Device Tree).
+config MACH_ICONNECT_DT
+ bool "Iomega Iconnect (Flattened Device Tree)"
+ select ARCH_KIRKWOOD_DT
+ help
+ Say 'Y' here to enable Iomega Iconnect support.
+
+config MACH_DLINK_KIRKWOOD_DT
+ bool "D-Link Kirkwood-based NAS (Flattened Device Tree)"
+ select ARCH_KIRKWOOD_DT
+ help
+ Say 'Y' here if you want your kernel to support the
+ Kirkwood-based D-Link NASes such as DNS-320 & DNS-325,
+ using Flattened Device Tree.
+
+config MACH_IB62X0_DT
+ bool "RaidSonic IB-NAS6210, IB-NAS6220 (Flattened Device Tree)"
+ select ARCH_KIRKWOOD_DT
+ help
+ Say 'Y' here if you want your kernel to support the
+ RaidSonic IB-NAS6210 & IB-NAS6220 devices, using
+ Flattened Device Tree.
+
config MACH_TS219
bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
help
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index e299a9576bf0..d2b05907b10e 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -22,3 +22,6 @@ obj-$(CONFIG_MACH_T5325) += t5325-setup.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_ARCH_KIRKWOOD_DT) += board-dt.o
obj-$(CONFIG_MACH_DREAMPLUG_DT) += board-dreamplug.o
+obj-$(CONFIG_MACH_ICONNECT_DT) += board-iconnect.o
+obj-$(CONFIG_MACH_DLINK_KIRKWOOD_DT) += board-dnskw.o
+obj-$(CONFIG_MACH_IB62X0_DT) += board-ib62x0.o
diff --git a/arch/arm/mach-kirkwood/Makefile.boot b/arch/arm/mach-kirkwood/Makefile.boot
index 16f938522304..02edbdf5b065 100644
--- a/arch/arm/mach-kirkwood/Makefile.boot
+++ b/arch/arm/mach-kirkwood/Makefile.boot
@@ -3,3 +3,7 @@ params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
dtb-$(CONFIG_MACH_DREAMPLUG_DT) += kirkwood-dreamplug.dtb
+dtb-$(CONFIG_MACH_DLINK_KIRKWOOD_DT) += kirkwood-dns320.dtb
+dtb-$(CONFIG_MACH_DLINK_KIRKWOOD_DT) += kirkwood-dns325.dtb
+dtb-$(CONFIG_MACH_ICONNECT_DT) += kirkwood-iconnect.dtb
+dtb-$(CONFIG_MACH_IB62X0_DT) += kirkwood-ib62x0.dtb
diff --git a/arch/arm/mach-kirkwood/board-dnskw.c b/arch/arm/mach-kirkwood/board-dnskw.c
new file mode 100644
index 000000000000..58c2d68f9443
--- /dev/null
+++ b/arch/arm/mach-kirkwood/board-dnskw.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2012 (C), Jamie Lentin <jm@lentin.co.uk>
+ *
+ * arch/arm/mach-kirkwood/board-dnskw.c
+ *
+ * D-link DNS-320 & DNS-325 NAS Init for drivers not converted to
+ * flattened device tree yet.
+ *
+ * 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/i2c.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/of.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio-fan.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/kirkwood.h>
+#include <mach/bridge-regs.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data dnskw_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(8),
+};
+
+static struct mv_sata_platform_data dnskw_sata_data = {
+ .n_ports = 2,
+};
+
+static unsigned int dnskw_mpp_config[] __initdata = {
+ MPP13_UART1_TXD, /* Custom ... */
+ MPP14_UART1_RXD, /* ... Controller (DNS-320 only) */
+ MPP20_SATA1_ACTn, /* LED: White Right HDD */
+ MPP21_SATA0_ACTn, /* LED: White Left HDD */
+ MPP24_GPIO,
+ MPP25_GPIO,
+ MPP26_GPIO, /* LED: Power */
+ MPP27_GPIO, /* LED: Red Right HDD */
+ MPP28_GPIO, /* LED: Red Left HDD */
+ MPP29_GPIO, /* LED: Red USB (DNS-325 only) */
+ MPP30_GPIO,
+ MPP31_GPIO,
+ MPP32_GPIO,
+ MPP33_GPO,
+ MPP34_GPIO, /* Button: Front power */
+ MPP35_GPIO, /* LED: Red USB (DNS-320 only) */
+ MPP36_GPIO, /* Power: Turn off board */
+ MPP37_GPIO, /* Power: Turn back on after power failure */
+ MPP38_GPIO,
+ MPP39_GPIO, /* Power: SATA0 */
+ MPP40_GPIO, /* Power: SATA1 */
+ MPP41_GPIO, /* SATA0 present */
+ MPP42_GPIO, /* SATA1 present */
+ MPP43_GPIO, /* LED: White USB */
+ MPP44_GPIO, /* Fan: Tachometer Pin */
+ MPP45_GPIO, /* Fan: high speed */
+ MPP46_GPIO, /* Fan: low speed */
+ MPP47_GPIO, /* Button: Back unmount */
+ MPP48_GPIO, /* Button: Back reset */
+ MPP49_GPIO, /* Temp Alarm (DNS-325) Pin of U5 (DNS-320) */
+ 0
+};
+
+static struct gpio_led dns325_led_pins[] = {
+ {
+ .name = "dns325:white:power",
+ .gpio = 26,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "dns325:white:usb",
+ .gpio = 43,
+ .active_low = 1,
+ },
+ {
+ .name = "dns325:red:l_hdd",
+ .gpio = 28,
+ .active_low = 1,
+ },
+ {
+ .name = "dns325:red:r_hdd",
+ .gpio = 27,
+ .active_low = 1,
+ },
+ {
+ .name = "dns325:red:usb",
+ .gpio = 29,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led_platform_data dns325_led_data = {
+ .num_leds = ARRAY_SIZE(dns325_led_pins),
+ .leds = dns325_led_pins,
+};
+
+static struct platform_device dns325_led_device = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &dns325_led_data,
+ },
+};
+
+static struct gpio_led dns320_led_pins[] = {
+ {
+ .name = "dns320:blue:power",
+ .gpio = 26,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "dns320:blue:usb",
+ .gpio = 43,
+ .active_low = 1,
+ },
+ {
+ .name = "dns320:orange:l_hdd",
+ .gpio = 28,
+ .active_low = 1,
+ },
+ {
+ .name = "dns320:orange:r_hdd",
+ .gpio = 27,
+ .active_low = 1,
+ },
+ {
+ .name = "dns320:orange:usb",
+ .gpio = 35,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led_platform_data dns320_led_data = {
+ .num_leds = ARRAY_SIZE(dns320_led_pins),
+ .leds = dns320_led_pins,
+};
+
+static struct platform_device dns320_led_device = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &dns320_led_data,
+ },
+};
+
+static struct i2c_board_info dns325_i2c_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("lm75", 0x48),
+ },
+ /* Something at 0x0c also */
+};
+
+static struct gpio_keys_button dnskw_button_pins[] = {
+ {
+ .code = KEY_POWER,
+ .gpio = 34,
+ .desc = "Power button",
+ .active_low = 1,
+ },
+ {
+ .code = KEY_EJECTCD,
+ .gpio = 47,
+ .desc = "USB unmount button",
+ .active_low = 1,
+ },
+ {
+ .code = KEY_RESTART,
+ .gpio = 48,
+ .desc = "Reset button",
+ .active_low = 1,
+ },
+};
+
+static struct gpio_keys_platform_data dnskw_button_data = {
+ .buttons = dnskw_button_pins,
+ .nbuttons = ARRAY_SIZE(dnskw_button_pins),
+};
+
+static struct platform_device dnskw_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &dnskw_button_data,
+ }
+};
+
+/* Fan: ADDA AD045HB-G73 40mm 6000rpm@5v */
+static struct gpio_fan_speed dnskw_fan_speed[] = {
+ { 0, 0 },
+ { 3000, 1 },
+ { 6000, 2 },
+};
+static unsigned dnskw_fan_pins[] = {46, 45};
+
+static struct gpio_fan_platform_data dnskw_fan_data = {
+ .num_ctrl = ARRAY_SIZE(dnskw_fan_pins),
+ .ctrl = dnskw_fan_pins,
+ .num_speed = ARRAY_SIZE(dnskw_fan_speed),
+ .speed = dnskw_fan_speed,
+};
+
+static struct platform_device dnskw_fan_device = {
+ .name = "gpio-fan",
+ .id = -1,
+ .dev = {
+ .platform_data = &dnskw_fan_data,
+ },
+};
+
+static void dnskw_power_off(void)
+{
+ gpio_set_value(36, 1);
+}
+
+/* Register any GPIO for output and set the value */
+static void __init dnskw_gpio_register(unsigned gpio, char *name, int def)
+{
+ if (gpio_request(gpio, name) == 0 &&
+ gpio_direction_output(gpio, 0) == 0) {
+ gpio_set_value(gpio, def);
+ if (gpio_export(gpio, 0) != 0)
+ pr_err("dnskw: Failed to export GPIO %s\n", name);
+ } else
+ pr_err("dnskw: Failed to register %s\n", name);
+}
+
+void __init dnskw_init(void)
+{
+ kirkwood_mpp_conf(dnskw_mpp_config);
+
+ kirkwood_ehci_init();
+ kirkwood_ge00_init(&dnskw_ge00_data);
+ kirkwood_sata_init(&dnskw_sata_data);
+ kirkwood_i2c_init();
+
+ platform_device_register(&dnskw_button_device);
+ platform_device_register(&dnskw_fan_device);
+
+ if (of_machine_is_compatible("dlink,dns-325")) {
+ i2c_register_board_info(0, dns325_i2c_board_info,
+ ARRAY_SIZE(dns325_i2c_board_info));
+ platform_device_register(&dns325_led_device);
+
+ } else if (of_machine_is_compatible("dlink,dns-320"))
+ platform_device_register(&dns320_led_device);
+
+ /* Register power-off GPIO. */
+ if (gpio_request(36, "dnskw:power:off") == 0
+ && gpio_direction_output(36, 0) == 0)
+ pm_power_off = dnskw_power_off;
+ else
+ pr_err("dnskw: failed to configure power-off GPIO\n");
+
+ /* Ensure power is supplied to both HDDs */
+ dnskw_gpio_register(39, "dnskw:power:sata0", 1);
+ dnskw_gpio_register(40, "dnskw:power:sata1", 1);
+
+ /* Set NAS to turn back on after a power failure */
+ dnskw_gpio_register(37, "dnskw:power:recover", 1);
+}
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index f7fe1b9f3170..10d1969b9e3a 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -56,11 +56,24 @@ static void __init kirkwood_dt_init(void)
if (of_machine_is_compatible("globalscale,dreamplug"))
dreamplug_init();
+ if (of_machine_is_compatible("dlink,dns-kirkwood"))
+ dnskw_init();
+
+ if (of_machine_is_compatible("iom,iconnect"))
+ iconnect_init();
+
+ if (of_machine_is_compatible("raidsonic,ib-nas62x0"))
+ ib62x0_init();
+
of_platform_populate(NULL, kirkwood_dt_match_table, NULL, NULL);
}
static const char *kirkwood_dt_board_compat[] = {
"globalscale,dreamplug",
+ "dlink,dns-320",
+ "dlink,dns-325",
+ "iom,iconnect",
+ "raidsonic,ib-nas62x0",
NULL
};
diff --git a/arch/arm/mach-kirkwood/board-ib62x0.c b/arch/arm/mach-kirkwood/board-ib62x0.c
new file mode 100644
index 000000000000..eddf1df8891f
--- /dev/null
+++ b/arch/arm/mach-kirkwood/board-ib62x0.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2012 (C), Simon Baatz <gmbnomis@gmail.com>
+ *
+ * arch/arm/mach-kirkwood/board-ib62x0.c
+ *
+ * RaidSonic ICY BOX IB-NAS6210 & IB-NAS6220 init for drivers not
+ * converted to flattened device tree yet.
+ *
+ * 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/partitions.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+#define IB62X0_GPIO_POWER_OFF 24
+
+static struct mv643xx_eth_platform_data ib62x0_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(8),
+};
+
+static struct mv_sata_platform_data ib62x0_sata_data = {
+ .n_ports = 2,
+};
+
+static unsigned int ib62x0_mpp_config[] __initdata = {
+ MPP0_NF_IO2,
+ MPP1_NF_IO3,
+ MPP2_NF_IO4,
+ MPP3_NF_IO5,
+ MPP4_NF_IO6,
+ MPP5_NF_IO7,
+ MPP18_NF_IO0,
+ MPP19_NF_IO1,
+ MPP22_GPIO, /* OS LED red */
+ MPP24_GPIO, /* Power off device */
+ MPP25_GPIO, /* OS LED green */
+ MPP27_GPIO, /* USB transfer LED */
+ MPP28_GPIO, /* Reset button */
+ MPP29_GPIO, /* USB Copy button */
+ 0
+};
+
+static struct gpio_led ib62x0_led_pins[] = {
+ {
+ .name = "ib62x0:green:os",
+ .default_trigger = "default-on",
+ .gpio = 25,
+ .active_low = 0,
+ },
+ {
+ .name = "ib62x0:red:os",
+ .default_trigger = "none",
+ .gpio = 22,
+ .active_low = 0,
+ },
+ {
+ .name = "ib62x0:red:usb_copy",
+ .default_trigger = "none",
+ .gpio = 27,
+ .active_low = 0,
+ },
+};
+
+static struct gpio_led_platform_data ib62x0_led_data = {
+ .leds = ib62x0_led_pins,
+ .num_leds = ARRAY_SIZE(ib62x0_led_pins),
+};
+
+static struct platform_device ib62x0_led_device = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &ib62x0_led_data,
+ }
+};
+
+static struct gpio_keys_button ib62x0_button_pins[] = {
+ {
+ .code = KEY_COPY,
+ .gpio = 29,
+ .desc = "USB Copy",
+ .active_low = 1,
+ },
+ {
+ .code = KEY_RESTART,
+ .gpio = 28,
+ .desc = "Reset",
+ .active_low = 1,
+ },
+};
+
+static struct gpio_keys_platform_data ib62x0_button_data = {
+ .buttons = ib62x0_button_pins,
+ .nbuttons = ARRAY_SIZE(ib62x0_button_pins),
+};
+
+static struct platform_device ib62x0_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &ib62x0_button_data,
+ }
+};
+
+static void ib62x0_power_off(void)
+{
+ gpio_set_value(IB62X0_GPIO_POWER_OFF, 1);
+}
+
+void __init ib62x0_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_mpp_conf(ib62x0_mpp_config);
+
+ kirkwood_ehci_init();
+ kirkwood_ge00_init(&ib62x0_ge00_data);
+ kirkwood_sata_init(&ib62x0_sata_data);
+ platform_device_register(&ib62x0_led_device);
+ platform_device_register(&ib62x0_button_device);
+ if (gpio_request(IB62X0_GPIO_POWER_OFF, "ib62x0:power:off") == 0 &&
+ gpio_direction_output(IB62X0_GPIO_POWER_OFF, 0) == 0)
+ pm_power_off = ib62x0_power_off;
+ else
+ pr_err("board-ib62x0: failed to configure power-off GPIO\n");
+}
diff --git a/arch/arm/mach-kirkwood/board-iconnect.c b/arch/arm/mach-kirkwood/board-iconnect.c
new file mode 100644
index 000000000000..2222c5739519
--- /dev/null
+++ b/arch/arm/mach-kirkwood/board-iconnect.c
@@ -0,0 +1,165 @@
+/*
+ * arch/arm/mach-kirkwood/board-iconnect.c
+ *
+ * Iomega i-connect 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/of.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/orion_spi.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data iconnect_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(11),
+};
+
+static struct gpio_led iconnect_led_pins[] = {
+ {
+ .name = "led_level",
+ .gpio = 41,
+ .default_trigger = "default-on",
+ }, {
+ .name = "power:blue",
+ .gpio = 42,
+ .default_trigger = "timer",
+ }, {
+ .name = "power:red",
+ .gpio = 43,
+ }, {
+ .name = "usb1:blue",
+ .gpio = 44,
+ }, {
+ .name = "usb2:blue",
+ .gpio = 45,
+ }, {
+ .name = "usb3:blue",
+ .gpio = 46,
+ }, {
+ .name = "usb4:blue",
+ .gpio = 47,
+ }, {
+ .name = "otb:blue",
+ .gpio = 48,
+ },
+};
+
+static struct gpio_led_platform_data iconnect_led_data = {
+ .leds = iconnect_led_pins,
+ .num_leds = ARRAY_SIZE(iconnect_led_pins),
+ .gpio_blink_set = orion_gpio_led_blink_set,
+};
+
+static struct platform_device iconnect_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &iconnect_led_data,
+ }
+};
+
+static unsigned int iconnect_mpp_config[] __initdata = {
+ MPP12_GPIO,
+ MPP35_GPIO,
+ MPP41_GPIO,
+ MPP42_GPIO,
+ MPP43_GPIO,
+ MPP44_GPIO,
+ MPP45_GPIO,
+ MPP46_GPIO,
+ MPP47_GPIO,
+ MPP48_GPIO,
+ 0
+};
+
+static struct i2c_board_info __initdata iconnect_board_info[] = {
+ {
+ I2C_BOARD_INFO("lm63", 0x4c),
+ },
+};
+
+static struct mtd_partition iconnect_nand_parts[] = {
+ {
+ .name = "flash",
+ .offset = 0,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+/* yikes... theses are the original input buttons */
+/* but I'm not convinced by the sw event choices */
+static struct gpio_keys_button iconnect_buttons[] = {
+ {
+ .type = EV_SW,
+ .code = SW_LID,
+ .gpio = 12,
+ .desc = "Reset Button",
+ .active_low = 1,
+ .debounce_interval = 100,
+ }, {
+ .type = EV_SW,
+ .code = SW_TABLET_MODE,
+ .gpio = 35,
+ .desc = "OTB Button",
+ .active_low = 1,
+ .debounce_interval = 100,
+ },
+};
+
+static struct gpio_keys_platform_data iconnect_button_data = {
+ .buttons = iconnect_buttons,
+ .nbuttons = ARRAY_SIZE(iconnect_buttons),
+};
+
+static struct platform_device iconnect_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &iconnect_button_data,
+ },
+};
+
+void __init iconnect_init(void)
+{
+ kirkwood_mpp_conf(iconnect_mpp_config);
+ kirkwood_nand_init(ARRAY_AND_SIZE(iconnect_nand_parts), 25);
+ kirkwood_i2c_init();
+ i2c_register_board_info(0, iconnect_board_info,
+ ARRAY_SIZE(iconnect_board_info));
+
+ kirkwood_ehci_init();
+ kirkwood_ge00_init(&iconnect_ge00_data);
+
+ platform_device_register(&iconnect_button_device);
+ platform_device_register(&iconnect_leds);
+}
+
+static int __init iconnect_pci_init(void)
+{
+ if (of_machine_is_compatible("iom,iconnect"))
+ kirkwood_pcie_init(KW_PCIE0);
+ return 0;
+}
+subsys_initcall(iconnect_pci_init);
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index a02cae881f2f..3ad037385a5e 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -15,6 +15,7 @@
#include <linux/ata_platform.h>
#include <linux/mtd/nand.h>
#include <linux/dma-mapping.h>
+#include <linux/of.h>
#include <net/dsa.h>
#include <asm/page.h>
#include <asm/timex.h>
@@ -482,6 +483,9 @@ static int __init kirkwood_clock_gate(void)
unsigned int curr = readl(CLOCK_GATING_CTRL);
u32 dev, rev;
+#ifdef CONFIG_OF
+ struct device_node *np;
+#endif
kirkwood_pcie_id(&dev, &rev);
printk(KERN_DEBUG "Gating clock of unused units\n");
printk(KERN_DEBUG "before: 0x%08x\n", curr);
@@ -489,6 +493,14 @@ static int __init kirkwood_clock_gate(void)
/* Make sure those units are accessible */
writel(curr | CGC_SATA0 | CGC_SATA1 | CGC_PEX0 | CGC_PEX1, CLOCK_GATING_CTRL);
+#ifdef CONFIG_OF
+ np = of_find_compatible_node(NULL, NULL, "mrvl,orion-nand");
+ if (np && of_device_is_available(np)) {
+ kirkwood_clk_ctrl |= CGC_RUNIT;
+ of_node_put(np);
+ }
+#endif
+
/* For SATA: first shutdown the phy */
if (!(kirkwood_clk_ctrl & CGC_SATA0)) {
/* Disable PLL and IVREF */
diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
index fa8e7689c436..a34c41a5172e 100644
--- a/arch/arm/mach-kirkwood/common.h
+++ b/arch/arm/mach-kirkwood/common.h
@@ -58,6 +58,24 @@ void dreamplug_init(void);
static inline void dreamplug_init(void) {};
#endif
+#ifdef CONFIG_MACH_DLINK_KIRKWOOD_DT
+void dnskw_init(void);
+#else
+static inline void dnskw_init(void) {};
+#endif
+
+#ifdef CONFIG_MACH_ICONNECT_DT
+void iconnect_init(void);
+#else
+static inline void iconnect_init(void) {};
+#endif
+
+#ifdef CONFIG_MACH_IB62X0_DT
+void ib62x0_init(void);
+#else
+static inline void ib62x0_init(void) {};
+#endif
+
/* early init functions not converted to fdt yet */
char *kirkwood_id(void);
void kirkwood_l2_init(void);
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
index f56a0118c1bb..de373176ee67 100644
--- a/arch/arm/mach-kirkwood/pcie.c
+++ b/arch/arm/mach-kirkwood/pcie.c
@@ -44,12 +44,6 @@ struct pcie_port {
static int pcie_port_map[2];
static int num_pcie_ports;
-static inline struct pcie_port *bus_to_port(struct pci_bus *bus)
-{
- struct pci_sys_data *sys = bus->sysdata;
- return sys->private_data;
-}
-
static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
{
/*
@@ -79,7 +73,8 @@ static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
int size, u32 *val)
{
- struct pcie_port *pp = bus_to_port(bus);
+ struct pci_sys_data *sys = bus->sysdata;
+ struct pcie_port *pp = sys->private_data;
unsigned long flags;
int ret;
@@ -98,7 +93,8 @@ static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 val)
{
- struct pcie_port *pp = bus_to_port(bus);
+ struct pci_sys_data *sys = bus->sysdata;
+ struct pcie_port *pp = sys->private_data;
unsigned long flags;
int ret;
@@ -248,13 +244,13 @@ kirkwood_pcie_scan_bus(int nr, struct pci_sys_data *sys)
static int __init kirkwood_pcie_map_irq(const struct pci_dev *dev, u8 slot,
u8 pin)
{
- struct pcie_port *pp = bus_to_port(dev->bus);
+ struct pci_sys_data *sys = dev->sysdata;
+ struct pcie_port *pp = sys->private_data;
return pp->irq;
}
static struct hw_pci kirkwood_pci __initdata = {
- .swizzle = pci_std_swizzle,
.setup = kirkwood_pcie_setup,
.scan = kirkwood_pcie_scan_bus,
.map_irq = kirkwood_pcie_map_irq,
diff --git a/arch/arm/mach-ks8695/pci.c b/arch/arm/mach-ks8695/pci.c
index acc701435817..bb18193b4bac 100644
--- a/arch/arm/mach-ks8695/pci.c
+++ b/arch/arm/mach-ks8695/pci.c
@@ -141,12 +141,6 @@ static struct pci_ops ks8695_pci_ops = {
.write = ks8695_pci_writeconfig,
};
-static struct pci_bus* __init ks8695_pci_scan_bus(int nr, struct pci_sys_data *sys)
-{
- return pci_scan_root_bus(NULL, sys->busnr, &ks8695_pci_ops, sys,
- &sys->resources);
-}
-
static struct resource pci_mem = {
.name = "PCI Memory space",
.start = KS8695_PCIMEM_PA,
@@ -302,11 +296,10 @@ static void ks8695_show_pciregs(void)
static struct hw_pci ks8695_pci __initdata = {
.nr_controllers = 1,
+ .ops = &ks8695_pci_ops,
.preinit = ks8695_pci_preinit,
.setup = ks8695_pci_setup,
- .scan = ks8695_pci_scan_bus,
.postinit = NULL,
- .swizzle = pci_std_swizzle,
.map_irq = NULL,
};
diff --git a/arch/arm/mach-lpc32xx/Kconfig b/arch/arm/mach-lpc32xx/Kconfig
index 75946ac89ee9..e0b3eee83834 100644
--- a/arch/arm/mach-lpc32xx/Kconfig
+++ b/arch/arm/mach-lpc32xx/Kconfig
@@ -29,30 +29,4 @@ config ARCH_LPC32XX_UART6_SELECT
endmenu
-menu "LPC32XX chip components"
-
-config ARCH_LPC32XX_IRAM_FOR_NET
- bool "Use IRAM for network buffers"
- default y
- help
- Say Y here to use the LPC internal fast IRAM (i.e. 256KB SRAM) as
- network buffer. If the total combined required buffer sizes is
- larger than the size of IRAM, then SDRAM will be used instead.
-
- This can be enabled safely if the IRAM is not intended for other
- uses.
-
-config ARCH_LPC32XX_MII_SUPPORT
- bool "Check to enable MII support or leave disabled for RMII support"
- help
- Say Y here to enable MII support, or N for RMII support. Regardless of
- which support is selected, the ethernet interface driver needs to be
- selected in the device driver networking section.
-
- The PHY3250 reference board uses RMII, so users of this board should
- say N.
-
-endmenu
-
endif
-
diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c
index 2fc24ca12054..f6a3ffec1f4b 100644
--- a/arch/arm/mach-lpc32xx/clock.c
+++ b/arch/arm/mach-lpc32xx/clock.c
@@ -1095,49 +1095,42 @@ struct clk *clk_get_parent(struct clk *clk)
}
EXPORT_SYMBOL(clk_get_parent);
-#define _REGISTER_CLOCK(d, n, c) \
- { \
- .dev_id = (d), \
- .con_id = (n), \
- .clk = &(c), \
- },
-
static struct clk_lookup lookups[] = {
- _REGISTER_CLOCK(NULL, "osc_32KHz", osc_32KHz)
- _REGISTER_CLOCK(NULL, "osc_pll397", osc_pll397)
- _REGISTER_CLOCK(NULL, "osc_main", osc_main)
- _REGISTER_CLOCK(NULL, "sys_ck", clk_sys)
- _REGISTER_CLOCK(NULL, "arm_pll_ck", clk_armpll)
- _REGISTER_CLOCK(NULL, "ck_pll5", clk_usbpll)
- _REGISTER_CLOCK(NULL, "hclk_ck", clk_hclk)
- _REGISTER_CLOCK(NULL, "pclk_ck", clk_pclk)
- _REGISTER_CLOCK(NULL, "timer0_ck", clk_timer0)
- _REGISTER_CLOCK(NULL, "timer1_ck", clk_timer1)
- _REGISTER_CLOCK(NULL, "timer2_ck", clk_timer2)
- _REGISTER_CLOCK(NULL, "timer3_ck", clk_timer3)
- _REGISTER_CLOCK(NULL, "vfp9_ck", clk_vfp9)
- _REGISTER_CLOCK(NULL, "clk_dmac", clk_dma)
- _REGISTER_CLOCK("pnx4008-watchdog", NULL, clk_wdt)
- _REGISTER_CLOCK(NULL, "uart3_ck", clk_uart3)
- _REGISTER_CLOCK(NULL, "uart4_ck", clk_uart4)
- _REGISTER_CLOCK(NULL, "uart5_ck", clk_uart5)
- _REGISTER_CLOCK(NULL, "uart6_ck", clk_uart6)
- _REGISTER_CLOCK("pnx-i2c.0", NULL, clk_i2c0)
- _REGISTER_CLOCK("pnx-i2c.1", NULL, clk_i2c1)
- _REGISTER_CLOCK("pnx-i2c.2", NULL, clk_i2c2)
- _REGISTER_CLOCK("dev:ssp0", NULL, clk_ssp0)
- _REGISTER_CLOCK("dev:ssp1", NULL, clk_ssp1)
- _REGISTER_CLOCK("lpc32xx_keys.0", NULL, clk_kscan)
- _REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand)
- _REGISTER_CLOCK("lpc32xx-adc", NULL, clk_adc)
- _REGISTER_CLOCK(NULL, "i2s0_ck", clk_i2s0)
- _REGISTER_CLOCK(NULL, "i2s1_ck", clk_i2s1)
- _REGISTER_CLOCK("ts-lpc32xx", NULL, clk_tsc)
- _REGISTER_CLOCK("dev:mmc0", NULL, clk_mmc)
- _REGISTER_CLOCK("lpc-eth.0", NULL, clk_net)
- _REGISTER_CLOCK("dev:clcd", NULL, clk_lcd)
- _REGISTER_CLOCK("lpc32xx_udc", "ck_usbd", clk_usbd)
- _REGISTER_CLOCK("lpc32xx_rtc", NULL, clk_rtc)
+ CLKDEV_INIT(NULL, "osc_32KHz", &osc_32KHz),
+ CLKDEV_INIT(NULL, "osc_pll397", &osc_pll397),
+ CLKDEV_INIT(NULL, "osc_main", &osc_main),
+ CLKDEV_INIT(NULL, "sys_ck", &clk_sys),
+ CLKDEV_INIT(NULL, "arm_pll_ck", &clk_armpll),
+ CLKDEV_INIT(NULL, "ck_pll5", &clk_usbpll),
+ CLKDEV_INIT(NULL, "hclk_ck", &clk_hclk),
+ CLKDEV_INIT(NULL, "pclk_ck", &clk_pclk),
+ CLKDEV_INIT(NULL, "timer0_ck", &clk_timer0),
+ CLKDEV_INIT(NULL, "timer1_ck", &clk_timer1),
+ CLKDEV_INIT(NULL, "timer2_ck", &clk_timer2),
+ CLKDEV_INIT(NULL, "timer3_ck", &clk_timer3),
+ CLKDEV_INIT(NULL, "vfp9_ck", &clk_vfp9),
+ CLKDEV_INIT("pl08xdmac", NULL, &clk_dma),
+ CLKDEV_INIT("4003c000.watchdog", NULL, &clk_wdt),
+ CLKDEV_INIT(NULL, "uart3_ck", &clk_uart3),
+ CLKDEV_INIT(NULL, "uart4_ck", &clk_uart4),
+ CLKDEV_INIT(NULL, "uart5_ck", &clk_uart5),
+ CLKDEV_INIT(NULL, "uart6_ck", &clk_uart6),
+ CLKDEV_INIT("400a0000.i2c", NULL, &clk_i2c0),
+ CLKDEV_INIT("400a8000.i2c", NULL, &clk_i2c1),
+ CLKDEV_INIT("31020300.i2c", NULL, &clk_i2c2),
+ CLKDEV_INIT("dev:ssp0", NULL, &clk_ssp0),
+ CLKDEV_INIT("dev:ssp1", NULL, &clk_ssp1),
+ CLKDEV_INIT("lpc32xx_keys.0", NULL, &clk_kscan),
+ CLKDEV_INIT("lpc32xx-nand.0", "nand_ck", &clk_nand),
+ CLKDEV_INIT("40048000.adc", NULL, &clk_adc),
+ CLKDEV_INIT(NULL, "i2s0_ck", &clk_i2s0),
+ CLKDEV_INIT(NULL, "i2s1_ck", &clk_i2s1),
+ CLKDEV_INIT("40048000.tsc", NULL, &clk_tsc),
+ CLKDEV_INIT("20098000.sd", NULL, &clk_mmc),
+ CLKDEV_INIT("31060000.ethernet", NULL, &clk_net),
+ CLKDEV_INIT("dev:clcd", NULL, &clk_lcd),
+ CLKDEV_INIT("31020000.usbd", "ck_usbd", &clk_usbd),
+ CLKDEV_INIT("lpc32xx_rtc", NULL, &clk_rtc),
};
static int __init clk_init(void)
diff --git a/arch/arm/mach-lpc32xx/common.c b/arch/arm/mach-lpc32xx/common.c
index bbbf063a74c2..5c96057b6d78 100644
--- a/arch/arm/mach-lpc32xx/common.c
+++ b/arch/arm/mach-lpc32xx/common.c
@@ -27,186 +27,11 @@
#include <asm/mach/map.h>
-#include <mach/i2c.h>
#include <mach/hardware.h>
#include <mach/platform.h>
#include "common.h"
/*
- * Watchdog timer
- */
-static struct resource watchdog_resources[] = {
- [0] = {
- .start = LPC32XX_WDTIM_BASE,
- .end = LPC32XX_WDTIM_BASE + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-struct platform_device lpc32xx_watchdog_device = {
- .name = "pnx4008-watchdog",
- .id = -1,
- .num_resources = ARRAY_SIZE(watchdog_resources),
- .resource = watchdog_resources,
-};
-
-/*
- * I2C busses
- */
-static struct i2c_pnx_data i2c0_data = {
- .name = I2C_CHIP_NAME "1",
- .base = LPC32XX_I2C1_BASE,
- .irq = IRQ_LPC32XX_I2C_1,
-};
-
-static struct i2c_pnx_data i2c1_data = {
- .name = I2C_CHIP_NAME "2",
- .base = LPC32XX_I2C2_BASE,
- .irq = IRQ_LPC32XX_I2C_2,
-};
-
-static struct i2c_pnx_data i2c2_data = {
- .name = "USB-I2C",
- .base = LPC32XX_OTG_I2C_BASE,
- .irq = IRQ_LPC32XX_USB_I2C,
-};
-
-struct platform_device lpc32xx_i2c0_device = {
- .name = "pnx-i2c",
- .id = 0,
- .dev = {
- .platform_data = &i2c0_data,
- },
-};
-
-struct platform_device lpc32xx_i2c1_device = {
- .name = "pnx-i2c",
- .id = 1,
- .dev = {
- .platform_data = &i2c1_data,
- },
-};
-
-struct platform_device lpc32xx_i2c2_device = {
- .name = "pnx-i2c",
- .id = 2,
- .dev = {
- .platform_data = &i2c2_data,
- },
-};
-
-/* TSC (Touch Screen Controller) */
-
-static struct resource lpc32xx_tsc_resources[] = {
- {
- .start = LPC32XX_ADC_BASE,
- .end = LPC32XX_ADC_BASE + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
- }, {
- .start = IRQ_LPC32XX_TS_IRQ,
- .end = IRQ_LPC32XX_TS_IRQ,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device lpc32xx_tsc_device = {
- .name = "ts-lpc32xx",
- .id = -1,
- .num_resources = ARRAY_SIZE(lpc32xx_tsc_resources),
- .resource = lpc32xx_tsc_resources,
-};
-
-/* RTC */
-
-static struct resource lpc32xx_rtc_resources[] = {
- {
- .start = LPC32XX_RTC_BASE,
- .end = LPC32XX_RTC_BASE + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
- },{
- .start = IRQ_LPC32XX_RTC,
- .end = IRQ_LPC32XX_RTC,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device lpc32xx_rtc_device = {
- .name = "rtc-lpc32xx",
- .id = -1,
- .num_resources = ARRAY_SIZE(lpc32xx_rtc_resources),
- .resource = lpc32xx_rtc_resources,
-};
-
-/*
- * ADC support
- */
-static struct resource adc_resources[] = {
- {
- .start = LPC32XX_ADC_BASE,
- .end = LPC32XX_ADC_BASE + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
- }, {
- .start = IRQ_LPC32XX_TS_IRQ,
- .end = IRQ_LPC32XX_TS_IRQ,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device lpc32xx_adc_device = {
- .name = "lpc32xx-adc",
- .id = -1,
- .num_resources = ARRAY_SIZE(adc_resources),
- .resource = adc_resources,
-};
-
-/*
- * USB support
- */
-/* The dmamask must be set for OHCI to work */
-static u64 ohci_dmamask = ~(u32) 0;
-static struct resource ohci_resources[] = {
- {
- .start = IO_ADDRESS(LPC32XX_USB_BASE),
- .end = IO_ADDRESS(LPC32XX_USB_BASE + 0x100 - 1),
- .flags = IORESOURCE_MEM,
- }, {
- .start = IRQ_LPC32XX_USB_HOST,
- .flags = IORESOURCE_IRQ,
- },
-};
-struct platform_device lpc32xx_ohci_device = {
- .name = "usb-ohci",
- .id = -1,
- .dev = {
- .dma_mask = &ohci_dmamask,
- .coherent_dma_mask = 0xFFFFFFFF,
- },
- .num_resources = ARRAY_SIZE(ohci_resources),
- .resource = ohci_resources,
-};
-
-/*
- * Network Support
- */
-static struct resource net_resources[] = {
- [0] = DEFINE_RES_MEM(LPC32XX_ETHERNET_BASE, SZ_4K),
- [1] = DEFINE_RES_MEM(LPC32XX_IRAM_BASE, SZ_128K),
- [2] = DEFINE_RES_IRQ(IRQ_LPC32XX_ETHERNET),
-};
-
-static u64 lpc32xx_mac_dma_mask = 0xffffffffUL;
-struct platform_device lpc32xx_net_device = {
- .name = "lpc-eth",
- .id = 0,
- .dev = {
- .dma_mask = &lpc32xx_mac_dma_mask,
- .coherent_dma_mask = 0xffffffffUL,
- },
- .num_resources = ARRAY_SIZE(net_resources),
- .resource = net_resources,
-};
-
-/*
* Returns the unique ID for the device
*/
void lpc32xx_get_uid(u32 devid[4])
@@ -398,3 +223,16 @@ void lpc23xx_restart(char mode, const char *cmd)
while (1)
;
}
+
+static int __init lpc32xx_display_uid(void)
+{
+ u32 uid[4];
+
+ lpc32xx_get_uid(uid);
+
+ printk(KERN_INFO "LPC32XX unique ID: %08x%08x%08x%08x\n",
+ uid[3], uid[2], uid[1], uid[0]);
+
+ return 1;
+}
+arch_initcall(lpc32xx_display_uid);
diff --git a/arch/arm/mach-lpc32xx/common.h b/arch/arm/mach-lpc32xx/common.h
index 68e45e8c9486..afeac3b1fae6 100644
--- a/arch/arm/mach-lpc32xx/common.h
+++ b/arch/arm/mach-lpc32xx/common.h
@@ -23,26 +23,12 @@
#include <linux/platform_device.h>
/*
- * Arch specific platform device structures
- */
-extern struct platform_device lpc32xx_watchdog_device;
-extern struct platform_device lpc32xx_i2c0_device;
-extern struct platform_device lpc32xx_i2c1_device;
-extern struct platform_device lpc32xx_i2c2_device;
-extern struct platform_device lpc32xx_tsc_device;
-extern struct platform_device lpc32xx_adc_device;
-extern struct platform_device lpc32xx_rtc_device;
-extern struct platform_device lpc32xx_ohci_device;
-extern struct platform_device lpc32xx_net_device;
-
-/*
* Other arch specific structures and functions
*/
extern struct sys_timer lpc32xx_timer;
extern void __init lpc32xx_init_irq(void);
extern void __init lpc32xx_map_io(void);
extern void __init lpc32xx_serial_init(void);
-extern void __init lpc32xx_gpio_init(void);
extern void lpc23xx_restart(char, const char *);
diff --git a/arch/arm/mach-lpc32xx/include/mach/i2c.h b/arch/arm/mach-lpc32xx/include/mach/i2c.h
deleted file mode 100644
index 034dc9286bcc..000000000000
--- a/arch/arm/mach-lpc32xx/include/mach/i2c.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * PNX4008-specific tweaks for I2C IP3204 block
- *
- * Author: Vitaly Wool <vwool@ru.mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __ASM_ARCH_I2C_H
-#define __ASM_ARCH_I2C_H
-
-enum {
- mstatus_tdi = 0x00000001,
- mstatus_afi = 0x00000002,
- mstatus_nai = 0x00000004,
- mstatus_drmi = 0x00000008,
- mstatus_active = 0x00000020,
- mstatus_scl = 0x00000040,
- mstatus_sda = 0x00000080,
- mstatus_rff = 0x00000100,
- mstatus_rfe = 0x00000200,
- mstatus_tff = 0x00000400,
- mstatus_tfe = 0x00000800,
-};
-
-enum {
- mcntrl_tdie = 0x00000001,
- mcntrl_afie = 0x00000002,
- mcntrl_naie = 0x00000004,
- mcntrl_drmie = 0x00000008,
- mcntrl_daie = 0x00000020,
- mcntrl_rffie = 0x00000040,
- mcntrl_tffie = 0x00000080,
- mcntrl_reset = 0x00000100,
- mcntrl_cdbmode = 0x00000400,
-};
-
-enum {
- rw_bit = 1 << 0,
- start_bit = 1 << 8,
- stop_bit = 1 << 9,
-};
-
-#define I2C_REG_RX(a) ((a)->ioaddr) /* Rx FIFO reg (RO) */
-#define I2C_REG_TX(a) ((a)->ioaddr) /* Tx FIFO reg (WO) */
-#define I2C_REG_STS(a) ((a)->ioaddr + 0x04) /* Status reg (RO) */
-#define I2C_REG_CTL(a) ((a)->ioaddr + 0x08) /* Ctl reg */
-#define I2C_REG_CKL(a) ((a)->ioaddr + 0x0c) /* Clock divider low */
-#define I2C_REG_CKH(a) ((a)->ioaddr + 0x10) /* Clock divider high */
-#define I2C_REG_ADR(a) ((a)->ioaddr + 0x14) /* I2C address */
-#define I2C_REG_RFL(a) ((a)->ioaddr + 0x18) /* Rx FIFO level (RO) */
-#define I2C_REG_TFL(a) ((a)->ioaddr + 0x1c) /* Tx FIFO level (RO) */
-#define I2C_REG_RXB(a) ((a)->ioaddr + 0x20) /* Num of bytes Rx-ed (RO) */
-#define I2C_REG_TXB(a) ((a)->ioaddr + 0x24) /* Num of bytes Tx-ed (RO) */
-#define I2C_REG_TXS(a) ((a)->ioaddr + 0x28) /* Tx slave FIFO (RO) */
-#define I2C_REG_STFL(a) ((a)->ioaddr + 0x2c) /* Tx slave FIFO level (RO) */
-
-#define I2C_CHIP_NAME "PNX4008-I2C"
-
-#endif /* __ASM_ARCH_I2C_H */
diff --git a/arch/arm/mach-lpc32xx/irq.c b/arch/arm/mach-lpc32xx/irq.c
index d080cb1123dd..5b1cc35e6fba 100644
--- a/arch/arm/mach-lpc32xx/irq.c
+++ b/arch/arm/mach-lpc32xx/irq.c
@@ -22,6 +22,11 @@
#include <linux/irq.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
#include <mach/irqs.h>
#include <mach/hardware.h>
@@ -44,6 +49,9 @@
#define SIC1_ATR_DEFAULT 0x00026000
#define SIC2_ATR_DEFAULT 0x00000000
+static struct irq_domain *lpc32xx_mic_domain;
+static struct device_node *lpc32xx_mic_np;
+
struct lpc32xx_event_group_regs {
void __iomem *enab_reg;
void __iomem *edge_reg;
@@ -203,7 +211,7 @@ static void lpc32xx_mask_irq(struct irq_data *d)
{
unsigned int reg, ctrl, mask;
- get_controller(d->irq, &ctrl, &mask);
+ get_controller(d->hwirq, &ctrl, &mask);
reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) & ~mask;
__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
@@ -213,7 +221,7 @@ static void lpc32xx_unmask_irq(struct irq_data *d)
{
unsigned int reg, ctrl, mask;
- get_controller(d->irq, &ctrl, &mask);
+ get_controller(d->hwirq, &ctrl, &mask);
reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) | mask;
__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
@@ -223,14 +231,14 @@ static void lpc32xx_ack_irq(struct irq_data *d)
{
unsigned int ctrl, mask;
- get_controller(d->irq, &ctrl, &mask);
+ get_controller(d->hwirq, &ctrl, &mask);
__raw_writel(mask, LPC32XX_INTC_RAW_STAT(ctrl));
/* Also need to clear pending wake event */
- if (lpc32xx_events[d->irq].mask != 0)
- __raw_writel(lpc32xx_events[d->irq].mask,
- lpc32xx_events[d->irq].event_group->rawstat_reg);
+ if (lpc32xx_events[d->hwirq].mask != 0)
+ __raw_writel(lpc32xx_events[d->hwirq].mask,
+ lpc32xx_events[d->hwirq].event_group->rawstat_reg);
}
static void __lpc32xx_set_irq_type(unsigned int irq, int use_high_level,
@@ -274,22 +282,22 @@ static int lpc32xx_set_irq_type(struct irq_data *d, unsigned int type)
switch (type) {
case IRQ_TYPE_EDGE_RISING:
/* Rising edge sensitive */
- __lpc32xx_set_irq_type(d->irq, 1, 1);
+ __lpc32xx_set_irq_type(d->hwirq, 1, 1);
break;
case IRQ_TYPE_EDGE_FALLING:
/* Falling edge sensitive */
- __lpc32xx_set_irq_type(d->irq, 0, 1);
+ __lpc32xx_set_irq_type(d->hwirq, 0, 1);
break;
case IRQ_TYPE_LEVEL_LOW:
/* Low level sensitive */
- __lpc32xx_set_irq_type(d->irq, 0, 0);
+ __lpc32xx_set_irq_type(d->hwirq, 0, 0);
break;
case IRQ_TYPE_LEVEL_HIGH:
/* High level sensitive */
- __lpc32xx_set_irq_type(d->irq, 1, 0);
+ __lpc32xx_set_irq_type(d->hwirq, 1, 0);
break;
/* Other modes are not supported */
@@ -298,7 +306,7 @@ static int lpc32xx_set_irq_type(struct irq_data *d, unsigned int type)
}
/* Ok to use the level handler for all types */
- irq_set_handler(d->irq, handle_level_irq);
+ irq_set_handler(d->hwirq, handle_level_irq);
return 0;
}
@@ -307,33 +315,33 @@ static int lpc32xx_irq_wake(struct irq_data *d, unsigned int state)
{
unsigned long eventreg;
- if (lpc32xx_events[d->irq].mask != 0) {
- eventreg = __raw_readl(lpc32xx_events[d->irq].
+ if (lpc32xx_events[d->hwirq].mask != 0) {
+ eventreg = __raw_readl(lpc32xx_events[d->hwirq].
event_group->enab_reg);
if (state)
- eventreg |= lpc32xx_events[d->irq].mask;
+ eventreg |= lpc32xx_events[d->hwirq].mask;
else {
- eventreg &= ~lpc32xx_events[d->irq].mask;
+ eventreg &= ~lpc32xx_events[d->hwirq].mask;
/*
* When disabling the wakeup, clear the latched
* event
*/
- __raw_writel(lpc32xx_events[d->irq].mask,
- lpc32xx_events[d->irq].
+ __raw_writel(lpc32xx_events[d->hwirq].mask,
+ lpc32xx_events[d->hwirq].
event_group->rawstat_reg);
}
__raw_writel(eventreg,
- lpc32xx_events[d->irq].event_group->enab_reg);
+ lpc32xx_events[d->hwirq].event_group->enab_reg);
return 0;
}
/* Clear event */
- __raw_writel(lpc32xx_events[d->irq].mask,
- lpc32xx_events[d->irq].event_group->rawstat_reg);
+ __raw_writel(lpc32xx_events[d->hwirq].mask,
+ lpc32xx_events[d->hwirq].event_group->rawstat_reg);
return -ENODEV;
}
@@ -353,6 +361,7 @@ static void __init lpc32xx_set_default_mappings(unsigned int apr,
}
static struct irq_chip lpc32xx_irq_chip = {
+ .name = "MIC",
.irq_ack = lpc32xx_ack_irq,
.irq_mask = lpc32xx_mask_irq,
.irq_unmask = lpc32xx_unmask_irq,
@@ -386,9 +395,23 @@ static void lpc32xx_sic2_handler(unsigned int irq, struct irq_desc *desc)
}
}
+static int __init __lpc32xx_mic_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ lpc32xx_mic_np = node;
+
+ return 0;
+}
+
+static const struct of_device_id mic_of_match[] __initconst = {
+ { .compatible = "nxp,lpc3220-mic", .data = __lpc32xx_mic_of_init },
+ { }
+};
+
void __init lpc32xx_init_irq(void)
{
unsigned int i;
+ int irq_base;
/* Setup MIC */
__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
@@ -448,4 +471,19 @@ void __init lpc32xx_init_irq(void)
LPC32XX_CLKPWR_PIN_RS);
__raw_writel(__raw_readl(LPC32XX_CLKPWR_INT_RS),
LPC32XX_CLKPWR_INT_RS);
+
+ of_irq_init(mic_of_match);
+
+ irq_base = irq_alloc_descs(-1, 0, NR_IRQS, 0);
+ if (irq_base < 0) {
+ pr_warn("Cannot allocate irq_descs, assuming pre-allocated\n");
+ irq_base = 0;
+ }
+
+ lpc32xx_mic_domain = irq_domain_add_legacy(lpc32xx_mic_np, NR_IRQS,
+ irq_base, 0,
+ &irq_domain_simple_ops,
+ NULL);
+ if (!lpc32xx_mic_domain)
+ panic("Unable to add MIC irq domain\n");
}
diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c
index 7f7401ec7487..540106cdb9ec 100644
--- a/arch/arm/mach-lpc32xx/phy3250.c
+++ b/arch/arm/mach-lpc32xx/phy3250.c
@@ -1,8 +1,9 @@
/*
- * arch/arm/mach-lpc32xx/phy3250.c
+ * Platform support for LPC32xx SoC
*
* Author: Kevin Wells <kevin.wells@nxp.com>
*
+ * Copyright (C) 2012 Roland Stigge <stigge@antcom.de>
* Copyright (C) 2010 NXP Semiconductors
*
* This program is free software; you can redistribute it and/or modify
@@ -25,11 +26,16 @@
#include <linux/device.h>
#include <linux/spi/spi.h>
#include <linux/spi/eeprom.h>
-#include <linux/leds.h>
#include <linux/gpio.h>
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
#include <linux/amba/pl022.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
+#include <linux/amba/pl08x.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
@@ -47,7 +53,6 @@
#define SPI0_CS_GPIO LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
#define LCD_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 0)
#define BKL_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4)
-#define LED_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 1)
/*
* AMBA LCD controller
@@ -150,9 +155,6 @@ static struct clcd_board lpc32xx_clcd_data = {
.remove = lpc32xx_clcd_remove,
};
-static AMBA_AHB_DEVICE(lpc32xx_clcd, "dev:clcd", 0,
- LPC32XX_LCD_BASE, { IRQ_LPC32XX_LCD }, &lpc32xx_clcd_data);
-
/*
* AMBA SSP (SPI)
*/
@@ -180,8 +182,11 @@ static struct pl022_ssp_controller lpc32xx_ssp0_data = {
.enable_dma = 0,
};
-static AMBA_APB_DEVICE(lpc32xx_ssp0, "dev:ssp0", 0,
- LPC32XX_SSP0_BASE, { IRQ_LPC32XX_SSP0 }, &lpc32xx_ssp0_data);
+static struct pl022_ssp_controller lpc32xx_ssp1_data = {
+ .bus_id = 1,
+ .num_chipselect = 1,
+ .enable_dma = 0,
+};
/* AT25 driver registration */
static int __init phy3250_spi_board_register(void)
@@ -221,73 +226,20 @@ static int __init phy3250_spi_board_register(void)
}
arch_initcall(phy3250_spi_board_register);
-static struct i2c_board_info __initdata phy3250_i2c_board_info[] = {
- {
- I2C_BOARD_INFO("pcf8563", 0x51),
- },
-};
-
-static struct gpio_led phy_leds[] = {
- {
- .name = "led0",
- .gpio = LED_GPIO,
- .active_low = 1,
- .default_trigger = "heartbeat",
- },
-};
-
-static struct gpio_led_platform_data led_data = {
- .leds = phy_leds,
- .num_leds = ARRAY_SIZE(phy_leds),
-};
-
-static struct platform_device lpc32xx_gpio_led_device = {
- .name = "leds-gpio",
- .id = -1,
- .dev.platform_data = &led_data,
+static struct pl08x_platform_data pl08x_pd = {
};
-static struct platform_device *phy3250_devs[] __initdata = {
- &lpc32xx_rtc_device,
- &lpc32xx_tsc_device,
- &lpc32xx_i2c0_device,
- &lpc32xx_i2c1_device,
- &lpc32xx_i2c2_device,
- &lpc32xx_watchdog_device,
- &lpc32xx_gpio_led_device,
- &lpc32xx_adc_device,
- &lpc32xx_ohci_device,
- &lpc32xx_net_device,
+static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = {
+ OF_DEV_AUXDATA("arm,pl022", 0x20084000, "dev:ssp0", &lpc32xx_ssp0_data),
+ OF_DEV_AUXDATA("arm,pl022", 0x2008C000, "dev:ssp1", &lpc32xx_ssp1_data),
+ OF_DEV_AUXDATA("arm,pl110", 0x31040000, "dev:clcd", &lpc32xx_clcd_data),
+ OF_DEV_AUXDATA("arm,pl080", 0x31000000, "pl08xdmac", &pl08x_pd),
+ { }
};
-static struct amba_device *amba_devs[] __initdata = {
- &lpc32xx_clcd_device,
- &lpc32xx_ssp0_device,
-};
-
-/*
- * Board specific functions
- */
-static void __init phy3250_board_init(void)
+static void __init lpc3250_machine_init(void)
{
u32 tmp;
- int i;
-
- lpc32xx_gpio_init();
-
- /* Register GPIOs used on this board */
- if (gpio_request(SPI0_CS_GPIO, "spi0 cs"))
- printk(KERN_ERR "Error requesting gpio %u",
- SPI0_CS_GPIO);
- else if (gpio_direction_output(SPI0_CS_GPIO, 1))
- printk(KERN_ERR "Error setting gpio %u to output",
- SPI0_CS_GPIO);
-
- /* Setup network interface for RMII mode */
- tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL);
- tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK;
- tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS;
- __raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL);
/* Setup SLC NAND controller muxing */
__raw_writel(LPC32XX_CLKPWR_NANDCLK_SEL_SLC,
@@ -300,6 +252,12 @@ static void __init phy3250_board_init(void)
tmp |= LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16;
__raw_writel(tmp, LPC32XX_CLKPWR_LCDCLK_CTRL);
+ /* Set up USB power */
+ tmp = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
+ tmp |= LPC32XX_CLKPWR_USBCTRL_HCLK_EN |
+ LPC32XX_CLKPWR_USBCTRL_USBI2C_EN;
+ __raw_writel(tmp, LPC32XX_CLKPWR_USB_CTRL);
+
/* Set up I2C pull levels */
tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL);
tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE |
@@ -321,54 +279,51 @@ static void __init phy3250_board_init(void)
/*
* AMBA peripheral clocks need to be enabled prior to AMBA device
* detection or a data fault will occur, so enable the clocks
- * here. However, we don't want to enable them if the peripheral
- * isn't included in the image
+ * here.
*/
-#ifdef CONFIG_FB_ARMCLCD
tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
__raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN),
LPC32XX_CLKPWR_LCDCLK_CTRL);
-#endif
-#ifdef CONFIG_SPI_PL022
+
tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL);
__raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN),
LPC32XX_CLKPWR_SSP_CLK_CTRL);
-#endif
- platform_add_devices(phy3250_devs, ARRAY_SIZE(phy3250_devs));
- for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
- struct amba_device *d = amba_devs[i];
- amba_device_register(d, &iomem_resource);
- }
+ tmp = __raw_readl(LPC32XX_CLKPWR_DMA_CLK_CTRL);
+ __raw_writel((tmp | LPC32XX_CLKPWR_DMACLKCTRL_CLK_EN),
+ LPC32XX_CLKPWR_DMA_CLK_CTRL);
/* Test clock needed for UDA1380 initial init */
__raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC |
LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN,
LPC32XX_CLKPWR_TEST_CLK_SEL);
- i2c_register_board_info(0, phy3250_i2c_board_info,
- ARRAY_SIZE(phy3250_i2c_board_info));
-}
-
-static int __init lpc32xx_display_uid(void)
-{
- u32 uid[4];
-
- lpc32xx_get_uid(uid);
-
- printk(KERN_INFO "LPC32XX unique ID: %08x%08x%08x%08x\n",
- uid[3], uid[2], uid[1], uid[0]);
+ of_platform_populate(NULL, of_default_bus_match_table,
+ lpc32xx_auxdata_lookup, NULL);
- return 1;
+ /* Register GPIOs used on this board */
+ if (gpio_request(SPI0_CS_GPIO, "spi0 cs"))
+ printk(KERN_ERR "Error requesting gpio %u",
+ SPI0_CS_GPIO);
+ else if (gpio_direction_output(SPI0_CS_GPIO, 1))
+ printk(KERN_ERR "Error setting gpio %u to output",
+ SPI0_CS_GPIO);
}
-arch_initcall(lpc32xx_display_uid);
-MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller")
- /* Maintainer: Kevin Wells, NXP Semiconductors */
+static char const *lpc32xx_dt_compat[] __initdata = {
+ "nxp,lpc3220",
+ "nxp,lpc3230",
+ "nxp,lpc3240",
+ "nxp,lpc3250",
+ NULL
+};
+
+DT_MACHINE_START(LPC32XX_DT, "LPC32XX SoC (Flattened Device Tree)")
.atag_offset = 0x100,
.map_io = lpc32xx_map_io,
.init_irq = lpc32xx_init_irq,
.timer = &lpc32xx_timer,
- .init_machine = phy3250_board_init,
+ .init_machine = lpc3250_machine_init,
+ .dt_compat = lpc32xx_dt_compat,
.restart = lpc23xx_restart,
MACHINE_END
diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 5a90b9a3ab6e..7fddd01b85b9 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -2,16 +2,6 @@ if ARCH_MMP
menu "Marvell PXA168/910/MMP2 Implmentations"
-config MACH_MMP_DT
- bool "Support MMP2 platforms from device tree"
- select CPU_PXA168
- select CPU_PXA910
- select USE_OF
- help
- Include support for Marvell MMP2 based platforms using
- the device tree. Needn't select any other machine while
- MACH_MMP_DT is enabled.
-
config MACH_ASPENITE
bool "Marvell's PXA168 Aspenite Development Board"
select CPU_PXA168
@@ -94,6 +84,25 @@ config MACH_GPLUGD
Say 'Y' here if you want to support the Marvell PXA168-based
GuruPlug Display (gplugD) Board
+config MACH_MMP_DT
+ bool "Support MMP (ARMv5) platforms from device tree"
+ select CPU_PXA168
+ select CPU_PXA910
+ select USE_OF
+ help
+ Include support for Marvell MMP2 based platforms using
+ the device tree. Needn't select any other machine while
+ MACH_MMP_DT is enabled.
+
+config MACH_MMP2_DT
+ bool "Support MMP2 (ARMv7) platforms from device tree"
+ depends on !CPU_MOHAWK
+ select CPU_MMP2
+ select USE_OF
+ help
+ Include support for Marvell MMP2 based platforms using
+ the device tree.
+
endmenu
config CPU_PXA168
@@ -113,4 +122,11 @@ config CPU_MMP2
select CPU_PJ4
help
Select code specific to MMP2. MMP2 is ARMv7 compatible.
+
+config USB_EHCI_MV_U2O
+ bool "EHCI support for PXA USB OTG controller"
+ depends on USB_EHCI_MV
+ help
+ Enables support for OTG controller which can be switched to host mode.
+
endif
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index 4fc0ff5dc96d..b786f7e6cd1f 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -2,12 +2,17 @@
# Makefile for Marvell's PXA168 processors line
#
-obj-y += common.o clock.o devices.o time.o
+obj-y += common.o clock.o devices.o time.o irq.o
# SoC support
-obj-$(CONFIG_CPU_PXA168) += pxa168.o irq-pxa168.o
-obj-$(CONFIG_CPU_PXA910) += pxa910.o irq-pxa168.o
-obj-$(CONFIG_CPU_MMP2) += mmp2.o irq-mmp2.o sram.o
+obj-$(CONFIG_CPU_PXA168) += pxa168.o
+obj-$(CONFIG_CPU_PXA910) += pxa910.o
+obj-$(CONFIG_CPU_MMP2) += mmp2.o sram.o
+
+ifeq ($(CONFIG_PM),y)
+obj-$(CONFIG_CPU_PXA910) += pm-pxa910.o
+obj-$(CONFIG_CPU_MMP2) += pm-mmp2.o
+endif
# board support
obj-$(CONFIG_MACH_ASPENITE) += aspenite.o
@@ -19,5 +24,6 @@ obj-$(CONFIG_MACH_BROWNSTONE) += brownstone.o
obj-$(CONFIG_MACH_FLINT) += flint.o
obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
obj-$(CONFIG_MACH_MMP_DT) += mmp-dt.o
+obj-$(CONFIG_MACH_MMP2_DT) += mmp2-dt.o
obj-$(CONFIG_MACH_TETON_BGA) += teton_bga.o
obj-$(CONFIG_MACH_GPLUGD) += gplugd.o
diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index bf5d8e195c3e..223090b1444d 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -17,6 +17,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
#include <linux/interrupt.h>
+#include <linux/platform_data/mv_usb.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -221,6 +222,21 @@ static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = {
.debounce_interval = 30,
};
+#if defined(CONFIG_USB_EHCI_MV)
+static char *pxa168_sph_clock_name[] = {
+ [0] = "PXA168-USBCLK",
+};
+
+static struct mv_usb_platform_data pxa168_sph_pdata = {
+ .clknum = 1,
+ .clkname = pxa168_sph_clock_name,
+ .mode = MV_USB_MODE_HOST,
+ .phy_init = pxa_usb_phy_init,
+ .phy_deinit = pxa_usb_phy_deinit,
+ .set_vbus = NULL,
+};
+#endif
+
static void __init common_init(void)
{
mfp_config(ARRAY_AND_SIZE(common_pin_config));
@@ -236,6 +252,10 @@ static void __init common_init(void)
/* off-chip devices */
platform_device_register(&smc91x_device);
+
+#if defined(CONFIG_USB_EHCI_MV)
+ pxa168_add_usb_host(&pxa168_sph_pdata);
+#endif
}
MACHINE_START(ASPENITE, "PXA168-based Aspenite Development Platform")
diff --git a/arch/arm/mach-mmp/devices.c b/arch/arm/mach-mmp/devices.c
index 191d9dea8731..dd2d8b103cc8 100644
--- a/arch/arm/mach-mmp/devices.c
+++ b/arch/arm/mach-mmp/devices.c
@@ -9,9 +9,13 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/delay.h>
#include <asm/irq.h>
+#include <mach/irqs.h>
#include <mach/devices.h>
+#include <mach/cputype.h>
+#include <mach/regs-usb.h>
int __init pxa_register_device(struct pxa_device_desc *desc,
void *data, size_t size)
@@ -67,3 +71,281 @@ int __init pxa_register_device(struct pxa_device_desc *desc,
return platform_device_add(pdev);
}
+
+#if defined(CONFIG_USB) || defined(CONFIG_USB_GADGET)
+
+/*****************************************************************************
+ * The registers read/write routines
+ *****************************************************************************/
+
+static unsigned int u2o_get(void __iomem *base, unsigned int offset)
+{
+ return readl_relaxed(base + offset);
+}
+
+static void u2o_set(void __iomem *base, unsigned int offset,
+ unsigned int value)
+{
+ u32 reg;
+
+ reg = readl_relaxed(base + offset);
+ reg |= value;
+ writel_relaxed(reg, base + offset);
+ readl_relaxed(base + offset);
+}
+
+static void u2o_clear(void __iomem *base, unsigned int offset,
+ unsigned int value)
+{
+ u32 reg;
+
+ reg = readl_relaxed(base + offset);
+ reg &= ~value;
+ writel_relaxed(reg, base + offset);
+ readl_relaxed(base + offset);
+}
+
+static void u2o_write(void __iomem *base, unsigned int offset,
+ unsigned int value)
+{
+ writel_relaxed(value, base + offset);
+ readl_relaxed(base + offset);
+}
+
+#if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV)
+
+#if defined(CONFIG_CPU_PXA910) || defined(CONFIG_CPU_PXA168)
+
+static DEFINE_MUTEX(phy_lock);
+static int phy_init_cnt;
+
+static int usb_phy_init_internal(void __iomem *base)
+{
+ int loops;
+
+ pr_info("Init usb phy!!!\n");
+
+ /* Initialize the USB PHY power */
+ if (cpu_is_pxa910()) {
+ u2o_set(base, UTMI_CTRL, (1<<UTMI_CTRL_INPKT_DELAY_SOF_SHIFT)
+ | (1<<UTMI_CTRL_PU_REF_SHIFT));
+ }
+
+ u2o_set(base, UTMI_CTRL, 1<<UTMI_CTRL_PLL_PWR_UP_SHIFT);
+ u2o_set(base, UTMI_CTRL, 1<<UTMI_CTRL_PWR_UP_SHIFT);
+
+ /* UTMI_PLL settings */
+ u2o_clear(base, UTMI_PLL, UTMI_PLL_PLLVDD18_MASK
+ | UTMI_PLL_PLLVDD12_MASK | UTMI_PLL_PLLCALI12_MASK
+ | UTMI_PLL_FBDIV_MASK | UTMI_PLL_REFDIV_MASK
+ | UTMI_PLL_ICP_MASK | UTMI_PLL_KVCO_MASK);
+
+ u2o_set(base, UTMI_PLL, 0xee<<UTMI_PLL_FBDIV_SHIFT
+ | 0xb<<UTMI_PLL_REFDIV_SHIFT | 3<<UTMI_PLL_PLLVDD18_SHIFT
+ | 3<<UTMI_PLL_PLLVDD12_SHIFT | 3<<UTMI_PLL_PLLCALI12_SHIFT
+ | 1<<UTMI_PLL_ICP_SHIFT | 3<<UTMI_PLL_KVCO_SHIFT);
+
+ /* UTMI_TX */
+ u2o_clear(base, UTMI_TX, UTMI_TX_REG_EXT_FS_RCAL_EN_MASK
+ | UTMI_TX_TXVDD12_MASK | UTMI_TX_CK60_PHSEL_MASK
+ | UTMI_TX_IMPCAL_VTH_MASK | UTMI_TX_REG_EXT_FS_RCAL_MASK
+ | UTMI_TX_AMP_MASK);
+ u2o_set(base, UTMI_TX, 3<<UTMI_TX_TXVDD12_SHIFT
+ | 4<<UTMI_TX_CK60_PHSEL_SHIFT | 4<<UTMI_TX_IMPCAL_VTH_SHIFT
+ | 8<<UTMI_TX_REG_EXT_FS_RCAL_SHIFT | 3<<UTMI_TX_AMP_SHIFT);
+
+ /* UTMI_RX */
+ u2o_clear(base, UTMI_RX, UTMI_RX_SQ_THRESH_MASK
+ | UTMI_REG_SQ_LENGTH_MASK);
+ u2o_set(base, UTMI_RX, 7<<UTMI_RX_SQ_THRESH_SHIFT
+ | 2<<UTMI_REG_SQ_LENGTH_SHIFT);
+
+ /* UTMI_IVREF */
+ if (cpu_is_pxa168())
+ /* fixing Microsoft Altair board interface with NEC hub issue -
+ * Set UTMI_IVREF from 0x4a3 to 0x4bf */
+ u2o_write(base, UTMI_IVREF, 0x4bf);
+
+ /* toggle VCOCAL_START bit of UTMI_PLL */
+ udelay(200);
+ u2o_set(base, UTMI_PLL, VCOCAL_START);
+ udelay(40);
+ u2o_clear(base, UTMI_PLL, VCOCAL_START);
+
+ /* toggle REG_RCAL_START bit of UTMI_TX */
+ udelay(400);
+ u2o_set(base, UTMI_TX, REG_RCAL_START);
+ udelay(40);
+ u2o_clear(base, UTMI_TX, REG_RCAL_START);
+ udelay(400);
+
+ /* Make sure PHY PLL is ready */
+ loops = 0;
+ while ((u2o_get(base, UTMI_PLL) & PLL_READY) == 0) {
+ mdelay(1);
+ loops++;
+ if (loops > 100) {
+ printk(KERN_WARNING "calibrate timeout, UTMI_PLL %x\n",
+ u2o_get(base, UTMI_PLL));
+ break;
+ }
+ }
+
+ if (cpu_is_pxa168()) {
+ u2o_set(base, UTMI_RESERVE, 1 << 5);
+ /* Turn on UTMI PHY OTG extension */
+ u2o_write(base, UTMI_OTG_ADDON, 1);
+ }
+
+ return 0;
+}
+
+static int usb_phy_deinit_internal(void __iomem *base)
+{
+ pr_info("Deinit usb phy!!!\n");
+
+ if (cpu_is_pxa168())
+ u2o_clear(base, UTMI_OTG_ADDON, UTMI_OTG_ADDON_OTG_ON);
+
+ u2o_clear(base, UTMI_CTRL, UTMI_CTRL_RXBUF_PDWN);
+ u2o_clear(base, UTMI_CTRL, UTMI_CTRL_TXBUF_PDWN);
+ u2o_clear(base, UTMI_CTRL, UTMI_CTRL_USB_CLK_EN);
+ u2o_clear(base, UTMI_CTRL, 1<<UTMI_CTRL_PWR_UP_SHIFT);
+ u2o_clear(base, UTMI_CTRL, 1<<UTMI_CTRL_PLL_PWR_UP_SHIFT);
+
+ return 0;
+}
+
+int pxa_usb_phy_init(void __iomem *phy_reg)
+{
+ mutex_lock(&phy_lock);
+ if (phy_init_cnt++ == 0)
+ usb_phy_init_internal(phy_reg);
+ mutex_unlock(&phy_lock);
+ return 0;
+}
+
+void pxa_usb_phy_deinit(void __iomem *phy_reg)
+{
+ WARN_ON(phy_init_cnt == 0);
+
+ mutex_lock(&phy_lock);
+ if (--phy_init_cnt == 0)
+ usb_phy_deinit_internal(phy_reg);
+ mutex_unlock(&phy_lock);
+}
+#endif
+#endif
+#endif
+
+#ifdef CONFIG_USB_SUPPORT
+static u64 usb_dma_mask = ~(u32)0;
+
+#ifdef CONFIG_USB_MV_UDC
+struct resource pxa168_u2o_resources[] = {
+ /* regbase */
+ [0] = {
+ .start = PXA168_U2O_REGBASE + U2x_CAPREGS_OFFSET,
+ .end = PXA168_U2O_REGBASE + USB_REG_RANGE,
+ .flags = IORESOURCE_MEM,
+ .name = "capregs",
+ },
+ /* phybase */
+ [1] = {
+ .start = PXA168_U2O_PHYBASE,
+ .end = PXA168_U2O_PHYBASE + USB_PHY_RANGE,
+ .flags = IORESOURCE_MEM,
+ .name = "phyregs",
+ },
+ [2] = {
+ .start = IRQ_PXA168_USB1,
+ .end = IRQ_PXA168_USB1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device pxa168_device_u2o = {
+ .name = "mv-udc",
+ .id = -1,
+ .resource = pxa168_u2o_resources,
+ .num_resources = ARRAY_SIZE(pxa168_u2o_resources),
+ .dev = {
+ .dma_mask = &usb_dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ }
+};
+#endif /* CONFIG_USB_MV_UDC */
+
+#ifdef CONFIG_USB_EHCI_MV_U2O
+struct resource pxa168_u2oehci_resources[] = {
+ /* regbase */
+ [0] = {
+ .start = PXA168_U2O_REGBASE + U2x_CAPREGS_OFFSET,
+ .end = PXA168_U2O_REGBASE + USB_REG_RANGE,
+ .flags = IORESOURCE_MEM,
+ .name = "capregs",
+ },
+ /* phybase */
+ [1] = {
+ .start = PXA168_U2O_PHYBASE,
+ .end = PXA168_U2O_PHYBASE + USB_PHY_RANGE,
+ .flags = IORESOURCE_MEM,
+ .name = "phyregs",
+ },
+ [2] = {
+ .start = IRQ_PXA168_USB1,
+ .end = IRQ_PXA168_USB1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device pxa168_device_u2oehci = {
+ .name = "pxa-u2oehci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &usb_dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+
+ .num_resources = ARRAY_SIZE(pxa168_u2oehci_resources),
+ .resource = pxa168_u2oehci_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_MV_OTG)
+struct resource pxa168_u2ootg_resources[] = {
+ /* regbase */
+ [0] = {
+ .start = PXA168_U2O_REGBASE + U2x_CAPREGS_OFFSET,
+ .end = PXA168_U2O_REGBASE + USB_REG_RANGE,
+ .flags = IORESOURCE_MEM,
+ .name = "capregs",
+ },
+ /* phybase */
+ [1] = {
+ .start = PXA168_U2O_PHYBASE,
+ .end = PXA168_U2O_PHYBASE + USB_PHY_RANGE,
+ .flags = IORESOURCE_MEM,
+ .name = "phyregs",
+ },
+ [2] = {
+ .start = IRQ_PXA168_USB1,
+ .end = IRQ_PXA168_USB1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device pxa168_device_u2ootg = {
+ .name = "mv-otg",
+ .id = -1,
+ .dev = {
+ .dma_mask = &usb_dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+
+ .num_resources = ARRAY_SIZE(pxa168_u2ootg_resources),
+ .resource = pxa168_u2ootg_resources,
+};
+#endif /* CONFIG_USB_MV_OTG */
+
+#endif
diff --git a/arch/arm/mach-mmp/include/mach/addr-map.h b/arch/arm/mach-mmp/include/mach/addr-map.h
index b1ece08174e8..f88a44c0ef91 100644
--- a/arch/arm/mach-mmp/include/mach/addr-map.h
+++ b/arch/arm/mach-mmp/include/mach/addr-map.h
@@ -31,4 +31,16 @@
#define SMC_CS1_PHYS_BASE 0x90000000
#define SMC_CS1_PHYS_SIZE 0x10000000
+#define APMU_VIRT_BASE (AXI_VIRT_BASE + 0x82800)
+#define APMU_REG(x) (APMU_VIRT_BASE + (x))
+
+#define APBC_VIRT_BASE (APB_VIRT_BASE + 0x015000)
+#define APBC_REG(x) (APBC_VIRT_BASE + (x))
+
+#define MPMU_VIRT_BASE (APB_VIRT_BASE + 0x50000)
+#define MPMU_REG(x) (MPMU_VIRT_BASE + (x))
+
+#define CIU_VIRT_BASE (AXI_VIRT_BASE + 0x82c00)
+#define CIU_REG(x) (CIU_VIRT_BASE + (x))
+
#endif /* __ASM_MACH_ADDR_MAP_H */
diff --git a/arch/arm/mach-mmp/include/mach/devices.h b/arch/arm/mach-mmp/include/mach/devices.h
index d0ec7dae88e4..21217ef11b64 100644
--- a/arch/arm/mach-mmp/include/mach/devices.h
+++ b/arch/arm/mach-mmp/include/mach/devices.h
@@ -50,4 +50,7 @@ struct pxa_device_desc mmp2_device_##_name __initdata = { \
}
extern int pxa_register_device(struct pxa_device_desc *, void *, size_t);
+extern int pxa_usb_phy_init(void __iomem *phy_reg);
+extern void pxa_usb_phy_deinit(void __iomem *phy_reg);
+
#endif /* __MACH_DEVICE_H */
diff --git a/arch/arm/mach-mmp/include/mach/entry-macro.S b/arch/arm/mach-mmp/include/mach/entry-macro.S
index 9cff9e7a2b26..bd152e24e6d7 100644
--- a/arch/arm/mach-mmp/include/mach/entry-macro.S
+++ b/arch/arm/mach-mmp/include/mach/entry-macro.S
@@ -6,13 +6,15 @@
* published by the Free Software Foundation.
*/
+#include <asm/irq.h>
#include <mach/regs-icu.h>
.macro get_irqnr_preamble, base, tmp
mrc p15, 0, \tmp, c0, c0, 0 @ CPUID
and \tmp, \tmp, #0xff00
cmp \tmp, #0x5800
- ldr \base, =ICU_VIRT_BASE
+ ldr \base, =mmp_icu_base
+ ldr \base, [\base, #0]
addne \base, \base, #0x10c @ PJ1 AP INT SEL register
addeq \base, \base, #0x104 @ PJ4 IRQ SEL register
.endm
diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h
index d0e746626a3d..fb492a50a817 100644
--- a/arch/arm/mach-mmp/include/mach/irqs.h
+++ b/arch/arm/mach-mmp/include/mach/irqs.h
@@ -125,7 +125,7 @@
#define IRQ_MMP2_RTC_MUX 5
#define IRQ_MMP2_TWSI1 7
#define IRQ_MMP2_GPU 8
-#define IRQ_MMP2_KEYPAD 9
+#define IRQ_MMP2_KEYPAD_MUX 9
#define IRQ_MMP2_ROTARY 10
#define IRQ_MMP2_TRACKBALL 11
#define IRQ_MMP2_ONEWIRE 12
@@ -163,11 +163,11 @@
#define IRQ_MMP2_DMA_FIQ 47
#define IRQ_MMP2_DMA_RIQ 48
#define IRQ_MMP2_GPIO 49
-#define IRQ_MMP2_SSP_MUX 51
+#define IRQ_MMP2_MIPI_HSI1_MUX 51
#define IRQ_MMP2_MMC2 52
#define IRQ_MMP2_MMC3 53
#define IRQ_MMP2_MMC4 54
-#define IRQ_MMP2_MIPI_HSI 55
+#define IRQ_MMP2_MIPI_HSI0_MUX 55
#define IRQ_MMP2_MSP 58
#define IRQ_MMP2_MIPI_SLIM_DMA 59
#define IRQ_MMP2_PJ4_FREQ_CHG 60
@@ -186,8 +186,14 @@
#define IRQ_MMP2_RTC_ALARM (IRQ_MMP2_RTC_BASE + 0)
#define IRQ_MMP2_RTC (IRQ_MMP2_RTC_BASE + 1)
+/* secondary interrupt of INT #9 */
+#define IRQ_MMP2_KEYPAD_BASE (IRQ_MMP2_RTC_BASE + 2)
+#define IRQ_MMP2_KPC (IRQ_MMP2_KEYPAD_BASE + 0)
+#define IRQ_MMP2_ROTORY (IRQ_MMP2_KEYPAD_BASE + 1)
+#define IRQ_MMP2_TBALL (IRQ_MMP2_KEYPAD_BASE + 2)
+
/* secondary interrupt of INT #17 */
-#define IRQ_MMP2_TWSI_BASE (IRQ_MMP2_RTC_BASE + 2)
+#define IRQ_MMP2_TWSI_BASE (IRQ_MMP2_KEYPAD_BASE + 3)
#define IRQ_MMP2_TWSI2 (IRQ_MMP2_TWSI_BASE + 0)
#define IRQ_MMP2_TWSI3 (IRQ_MMP2_TWSI_BASE + 1)
#define IRQ_MMP2_TWSI4 (IRQ_MMP2_TWSI_BASE + 2)
@@ -212,11 +218,16 @@
#define IRQ_MMP2_COMMRX (IRQ_MMP2_MISC_BASE + 14)
/* secondary interrupt of INT #51 */
-#define IRQ_MMP2_SSP_BASE (IRQ_MMP2_MISC_BASE + 15)
-#define IRQ_MMP2_SSP1_SRDY (IRQ_MMP2_SSP_BASE + 0)
-#define IRQ_MMP2_SSP3_SRDY (IRQ_MMP2_SSP_BASE + 1)
+#define IRQ_MMP2_MIPI_HSI1_BASE (IRQ_MMP2_MISC_BASE + 15)
+#define IRQ_MMP2_HSI1_CAWAKE (IRQ_MMP2_MIPI_HSI1_BASE + 0)
+#define IRQ_MMP2_MIPI_HSI_INT1 (IRQ_MMP2_MIPI_HSI1_BASE + 1)
+
+/* secondary interrupt of INT #55 */
+#define IRQ_MMP2_MIPI_HSI0_BASE (IRQ_MMP2_MIPI_HSI1_BASE + 2)
+#define IRQ_MMP2_HSI0_CAWAKE (IRQ_MMP2_MIPI_HSI0_BASE + 0)
+#define IRQ_MMP2_MIPI_HSI_INT0 (IRQ_MMP2_MIPI_HSI0_BASE + 1)
-#define IRQ_MMP2_MUX_END (IRQ_MMP2_SSP_BASE + 2)
+#define IRQ_MMP2_MUX_END (IRQ_MMP2_MIPI_HSI0_BASE + 2)
#define IRQ_GPIO_START 128
#define MMP_NR_BUILTIN_GPIO 192
diff --git a/arch/arm/mach-mmp/include/mach/pm-mmp2.h b/arch/arm/mach-mmp/include/mach/pm-mmp2.h
new file mode 100644
index 000000000000..98bd66ce8006
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/pm-mmp2.h
@@ -0,0 +1,61 @@
+/*
+ * MMP2 Power Management Routines
+ *
+ * This software program is licensed subject to the GNU General Public License
+ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * (C) Copyright 2010 Marvell International Ltd.
+ * All Rights Reserved
+ */
+
+#ifndef __MMP2_PM_H__
+#define __MMP2_PM_H__
+
+#include <mach/addr-map.h>
+
+#define APMU_PJ_IDLE_CFG APMU_REG(0x018)
+#define APMU_PJ_IDLE_CFG_PJ_IDLE (1 << 1)
+#define APMU_PJ_IDLE_CFG_PJ_PWRDWN (1 << 5)
+#define APMU_PJ_IDLE_CFG_PWR_SW(x) ((x) << 16)
+#define APMU_PJ_IDLE_CFG_L2_PWR_SW (1 << 19)
+#define APMU_PJ_IDLE_CFG_ISO_MODE_CNTRL_MASK (3 << 28)
+
+#define APMU_SRAM_PWR_DWN APMU_REG(0x08c)
+
+#define MPMU_SCCR MPMU_REG(0x038)
+#define MPMU_PCR_PJ MPMU_REG(0x1000)
+#define MPMU_PCR_PJ_AXISD (1 << 31)
+#define MPMU_PCR_PJ_SLPEN (1 << 29)
+#define MPMU_PCR_PJ_SPSD (1 << 28)
+#define MPMU_PCR_PJ_DDRCORSD (1 << 27)
+#define MPMU_PCR_PJ_APBSD (1 << 26)
+#define MPMU_PCR_PJ_INTCLR (1 << 24)
+#define MPMU_PCR_PJ_SLPWP0 (1 << 23)
+#define MPMU_PCR_PJ_SLPWP1 (1 << 22)
+#define MPMU_PCR_PJ_SLPWP2 (1 << 21)
+#define MPMU_PCR_PJ_SLPWP3 (1 << 20)
+#define MPMU_PCR_PJ_VCTCXOSD (1 << 19)
+#define MPMU_PCR_PJ_SLPWP4 (1 << 18)
+#define MPMU_PCR_PJ_SLPWP5 (1 << 17)
+#define MPMU_PCR_PJ_SLPWP6 (1 << 16)
+#define MPMU_PCR_PJ_SLPWP7 (1 << 15)
+
+#define MPMU_PLL2_CTRL1 MPMU_REG(0x0414)
+#define MPMU_CGR_PJ MPMU_REG(0x1024)
+#define MPMU_WUCRM_PJ MPMU_REG(0x104c)
+#define MPMU_WUCRM_PJ_WAKEUP(x) (1 << (x))
+#define MPMU_WUCRM_PJ_RTC_ALARM (1 << 17)
+
+enum {
+ POWER_MODE_ACTIVE = 0,
+ POWER_MODE_CORE_INTIDLE,
+ POWER_MODE_CORE_EXTIDLE,
+ POWER_MODE_APPS_IDLE,
+ POWER_MODE_APPS_SLEEP,
+ POWER_MODE_CHIP_SLEEP,
+ POWER_MODE_SYS_SLEEP,
+};
+
+extern void mmp2_pm_enter_lowpower_mode(int state);
+extern int mmp2_set_wake(struct irq_data *d, unsigned int on);
+#endif
diff --git a/arch/arm/mach-mmp/include/mach/pm-pxa910.h b/arch/arm/mach-mmp/include/mach/pm-pxa910.h
new file mode 100644
index 000000000000..8cac8ab5253d
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/pm-pxa910.h
@@ -0,0 +1,77 @@
+/*
+ * PXA910 Power Management Routines
+ *
+ * This software program is licensed subject to the GNU General Public License
+ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * (C) Copyright 2009 Marvell International Ltd.
+ * All Rights Reserved
+ */
+
+#ifndef __PXA910_PM_H__
+#define __PXA910_PM_H__
+
+#define APMU_MOH_IDLE_CFG APMU_REG(0x0018)
+#define APMU_MOH_IDLE_CFG_MOH_IDLE (1 << 1)
+#define APMU_MOH_IDLE_CFG_MOH_PWRDWN (1 << 5)
+#define APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN (1 << 6)
+#define APMU_MOH_IDLE_CFG_MOH_PWR_SW(x) (((x) & 0x3) << 16)
+#define APMU_MOH_IDLE_CFG_MOH_L2_PWR_SW(x) (((x) & 0x3) << 18)
+#define APMU_MOH_IDLE_CFG_MOH_DIS_MC_SW_REQ (1 << 21)
+#define APMU_MOH_IDLE_CFG_MOH_MC_WAKE_EN (1 << 20)
+
+#define APMU_SQU_CLK_GATE_CTRL APMU_REG(0x001c)
+#define APMU_MC_HW_SLP_TYPE APMU_REG(0x00b0)
+
+#define MPMU_FCCR MPMU_REG(0x0008)
+#define MPMU_APCR MPMU_REG(0x1000)
+#define MPMU_APCR_AXISD (1 << 31)
+#define MPMU_APCR_DSPSD (1 << 30)
+#define MPMU_APCR_SLPEN (1 << 29)
+#define MPMU_APCR_DTCMSD (1 << 28)
+#define MPMU_APCR_DDRCORSD (1 << 27)
+#define MPMU_APCR_APBSD (1 << 26)
+#define MPMU_APCR_BBSD (1 << 25)
+#define MPMU_APCR_SLPWP0 (1 << 23)
+#define MPMU_APCR_SLPWP1 (1 << 22)
+#define MPMU_APCR_SLPWP2 (1 << 21)
+#define MPMU_APCR_SLPWP3 (1 << 20)
+#define MPMU_APCR_VCTCXOSD (1 << 19)
+#define MPMU_APCR_SLPWP4 (1 << 18)
+#define MPMU_APCR_SLPWP5 (1 << 17)
+#define MPMU_APCR_SLPWP6 (1 << 16)
+#define MPMU_APCR_SLPWP7 (1 << 15)
+#define MPMU_APCR_MSASLPEN (1 << 14)
+#define MPMU_APCR_STBYEN (1 << 13)
+
+#define MPMU_AWUCRM MPMU_REG(0x104c)
+#define MPMU_AWUCRM_AP_ASYNC_INT (1 << 25)
+#define MPMU_AWUCRM_AP_FULL_IDLE (1 << 24)
+#define MPMU_AWUCRM_SDH1 (1 << 23)
+#define MPMU_AWUCRM_SDH2 (1 << 22)
+#define MPMU_AWUCRM_KEYPRESS (1 << 21)
+#define MPMU_AWUCRM_TRACKBALL (1 << 20)
+#define MPMU_AWUCRM_NEWROTARY (1 << 19)
+#define MPMU_AWUCRM_RTC_ALARM (1 << 17)
+#define MPMU_AWUCRM_AP2_TIMER_3 (1 << 13)
+#define MPMU_AWUCRM_AP2_TIMER_2 (1 << 12)
+#define MPMU_AWUCRM_AP2_TIMER_1 (1 << 11)
+#define MPMU_AWUCRM_AP1_TIMER_3 (1 << 10)
+#define MPMU_AWUCRM_AP1_TIMER_2 (1 << 9)
+#define MPMU_AWUCRM_AP1_TIMER_1 (1 << 8)
+#define MPMU_AWUCRM_WAKEUP(x) (1 << ((x) & 0x7))
+
+enum {
+ POWER_MODE_ACTIVE = 0,
+ POWER_MODE_CORE_INTIDLE,
+ POWER_MODE_CORE_EXTIDLE,
+ POWER_MODE_APPS_IDLE,
+ POWER_MODE_APPS_SLEEP,
+ POWER_MODE_SYS_SLEEP,
+ POWER_MODE_HIBERNATE,
+ POWER_MODE_UDR,
+};
+
+extern int pxa910_set_wake(struct irq_data *data, unsigned int on);
+
+#endif
diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h
index dc03d580a06d..09dcd6e2b6a8 100644
--- a/arch/arm/mach-mmp/include/mach/pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/pxa168.h
@@ -16,6 +16,7 @@ extern void pxa168_clear_keypad_wakeup(void);
#include <plat/pxa27x_keypad.h>
#include <mach/cputype.h>
#include <linux/pxa168_eth.h>
+#include <linux/platform_data/mv_usb.h>
extern struct pxa_device_desc pxa168_device_uart1;
extern struct pxa_device_desc pxa168_device_uart2;
@@ -36,12 +37,9 @@ extern struct pxa_device_desc pxa168_device_fb;
extern struct pxa_device_desc pxa168_device_keypad;
extern struct pxa_device_desc pxa168_device_eth;
-struct pxa168_usb_pdata {
- /* If NULL, default phy init routine for PXA168 would be called */
- int (*phy_init)(void __iomem *usb_phy_reg_base);
-};
/* pdata can be NULL */
-int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata);
+extern int __init pxa168_add_usb_host(struct mv_usb_platform_data *pdata);
+
extern struct platform_device pxa168_device_gpio;
diff --git a/arch/arm/mach-mmp/include/mach/pxa910.h b/arch/arm/mach-mmp/include/mach/pxa910.h
index e2e1f1e5e124..793634c837ef 100644
--- a/arch/arm/mach-mmp/include/mach/pxa910.h
+++ b/arch/arm/mach-mmp/include/mach/pxa910.h
@@ -20,6 +20,9 @@ extern struct pxa_device_desc pxa910_device_pwm2;
extern struct pxa_device_desc pxa910_device_pwm3;
extern struct pxa_device_desc pxa910_device_pwm4;
extern struct pxa_device_desc pxa910_device_nand;
+extern struct platform_device pxa168_device_u2o;
+extern struct platform_device pxa168_device_u2ootg;
+extern struct platform_device pxa168_device_u2oehci;
extern struct platform_device pxa910_device_gpio;
extern struct platform_device pxa910_device_rtc;
diff --git a/arch/arm/mach-mmp/include/mach/regs-apbc.h b/arch/arm/mach-mmp/include/mach/regs-apbc.h
index 8a37fb003655..68b0c93ec6a1 100644
--- a/arch/arm/mach-mmp/include/mach/regs-apbc.h
+++ b/arch/arm/mach-mmp/include/mach/regs-apbc.h
@@ -13,9 +13,6 @@
#include <mach/addr-map.h>
-#define APBC_VIRT_BASE (APB_VIRT_BASE + 0x015000)
-#define APBC_REG(x) (APBC_VIRT_BASE + (x))
-
/*
* APB clock register offsets for PXA168
*/
diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h
index 8447ac63e28f..7af8deb63e83 100644
--- a/arch/arm/mach-mmp/include/mach/regs-apmu.h
+++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h
@@ -13,9 +13,6 @@
#include <mach/addr-map.h>
-#define APMU_VIRT_BASE (AXI_VIRT_BASE + 0x82800)
-#define APMU_REG(x) (APMU_VIRT_BASE + (x))
-
/* Clock Reset Control */
#define APMU_IRE APMU_REG(0x048)
#define APMU_LCD APMU_REG(0x04c)
diff --git a/arch/arm/mach-mmp/include/mach/regs-usb.h b/arch/arm/mach-mmp/include/mach/regs-usb.h
new file mode 100644
index 000000000000..b047bf487506
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/regs-usb.h
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_ARCH_REGS_USB_H
+#define __ASM_ARCH_REGS_USB_H
+
+#define PXA168_U2O_REGBASE (0xd4208000)
+#define PXA168_U2O_PHYBASE (0xd4207000)
+
+#define PXA168_U2H_REGBASE (0xd4209000)
+#define PXA168_U2H_PHYBASE (0xd4206000)
+
+#define MMP3_HSIC1_REGBASE (0xf0001000)
+#define MMP3_HSIC1_PHYBASE (0xf0001800)
+
+#define MMP3_HSIC2_REGBASE (0xf0002000)
+#define MMP3_HSIC2_PHYBASE (0xf0002800)
+
+#define MMP3_FSIC_REGBASE (0xf0003000)
+#define MMP3_FSIC_PHYBASE (0xf0003800)
+
+
+#define USB_REG_RANGE (0x1ff)
+#define USB_PHY_RANGE (0xff)
+
+/* registers */
+#define U2x_CAPREGS_OFFSET 0x100
+
+/* phy regs */
+#define UTMI_REVISION 0x0
+#define UTMI_CTRL 0x4
+#define UTMI_PLL 0x8
+#define UTMI_TX 0xc
+#define UTMI_RX 0x10
+#define UTMI_IVREF 0x14
+#define UTMI_T0 0x18
+#define UTMI_T1 0x1c
+#define UTMI_T2 0x20
+#define UTMI_T3 0x24
+#define UTMI_T4 0x28
+#define UTMI_T5 0x2c
+#define UTMI_RESERVE 0x30
+#define UTMI_USB_INT 0x34
+#define UTMI_DBG_CTL 0x38
+#define UTMI_OTG_ADDON 0x3c
+
+/* For UTMICTRL Register */
+#define UTMI_CTRL_USB_CLK_EN (1 << 31)
+/* pxa168 */
+#define UTMI_CTRL_SUSPEND_SET1 (1 << 30)
+#define UTMI_CTRL_SUSPEND_SET2 (1 << 29)
+#define UTMI_CTRL_RXBUF_PDWN (1 << 24)
+#define UTMI_CTRL_TXBUF_PDWN (1 << 11)
+
+#define UTMI_CTRL_INPKT_DELAY_SHIFT 30
+#define UTMI_CTRL_INPKT_DELAY_SOF_SHIFT 28
+#define UTMI_CTRL_PU_REF_SHIFT 20
+#define UTMI_CTRL_ARC_PULLDN_SHIFT 12
+#define UTMI_CTRL_PLL_PWR_UP_SHIFT 1
+#define UTMI_CTRL_PWR_UP_SHIFT 0
+
+/* For UTMI_PLL Register */
+#define UTMI_PLL_PLLCALI12_SHIFT 29
+#define UTMI_PLL_PLLCALI12_MASK (0x3 << 29)
+
+#define UTMI_PLL_PLLVDD18_SHIFT 27
+#define UTMI_PLL_PLLVDD18_MASK (0x3 << 27)
+
+#define UTMI_PLL_PLLVDD12_SHIFT 25
+#define UTMI_PLL_PLLVDD12_MASK (0x3 << 25)
+
+#define UTMI_PLL_CLK_BLK_EN_SHIFT 24
+#define CLK_BLK_EN (0x1 << 24)
+#define PLL_READY (0x1 << 23)
+#define KVCO_EXT (0x1 << 22)
+#define VCOCAL_START (0x1 << 21)
+
+#define UTMI_PLL_KVCO_SHIFT 15
+#define UTMI_PLL_KVCO_MASK (0x7 << 15)
+
+#define UTMI_PLL_ICP_SHIFT 12
+#define UTMI_PLL_ICP_MASK (0x7 << 12)
+
+#define UTMI_PLL_FBDIV_SHIFT 4
+#define UTMI_PLL_FBDIV_MASK (0xFF << 4)
+
+#define UTMI_PLL_REFDIV_SHIFT 0
+#define UTMI_PLL_REFDIV_MASK (0xF << 0)
+
+/* For UTMI_TX Register */
+#define UTMI_TX_REG_EXT_FS_RCAL_SHIFT 27
+#define UTMI_TX_REG_EXT_FS_RCAL_MASK (0xf << 27)
+
+#define UTMI_TX_REG_EXT_FS_RCAL_EN_SHIFT 26
+#define UTMI_TX_REG_EXT_FS_RCAL_EN_MASK (0x1 << 26)
+
+#define UTMI_TX_TXVDD12_SHIFT 22
+#define UTMI_TX_TXVDD12_MASK (0x3 << 22)
+
+#define UTMI_TX_CK60_PHSEL_SHIFT 17
+#define UTMI_TX_CK60_PHSEL_MASK (0xf << 17)
+
+#define UTMI_TX_IMPCAL_VTH_SHIFT 14
+#define UTMI_TX_IMPCAL_VTH_MASK (0x7 << 14)
+
+#define REG_RCAL_START (0x1 << 12)
+
+#define UTMI_TX_LOW_VDD_EN_SHIFT 11
+
+#define UTMI_TX_AMP_SHIFT 0
+#define UTMI_TX_AMP_MASK (0x7 << 0)
+
+/* For UTMI_RX Register */
+#define UTMI_REG_SQ_LENGTH_SHIFT 15
+#define UTMI_REG_SQ_LENGTH_MASK (0x3 << 15)
+
+#define UTMI_RX_SQ_THRESH_SHIFT 4
+#define UTMI_RX_SQ_THRESH_MASK (0xf << 4)
+
+#define UTMI_OTG_ADDON_OTG_ON (1 << 0)
+
+/* For MMP3 USB Phy */
+#define USB2_PLL_REG0 0x4
+#define USB2_PLL_REG1 0x8
+#define USB2_TX_REG0 0x10
+#define USB2_TX_REG1 0x14
+#define USB2_TX_REG2 0x18
+#define USB2_RX_REG0 0x20
+#define USB2_RX_REG1 0x24
+#define USB2_RX_REG2 0x28
+#define USB2_ANA_REG0 0x30
+#define USB2_ANA_REG1 0x34
+#define USB2_ANA_REG2 0x38
+#define USB2_DIG_REG0 0x3C
+#define USB2_DIG_REG1 0x40
+#define USB2_DIG_REG2 0x44
+#define USB2_DIG_REG3 0x48
+#define USB2_TEST_REG0 0x4C
+#define USB2_TEST_REG1 0x50
+#define USB2_TEST_REG2 0x54
+#define USB2_CHARGER_REG0 0x58
+#define USB2_OTG_REG0 0x5C
+#define USB2_PHY_MON0 0x60
+#define USB2_RESETVE_REG0 0x64
+#define USB2_ICID_REG0 0x78
+#define USB2_ICID_REG1 0x7C
+
+/* USB2_PLL_REG0 */
+/* This is for Ax stepping */
+#define USB2_PLL_FBDIV_SHIFT_MMP3 0
+#define USB2_PLL_FBDIV_MASK_MMP3 (0xFF << 0)
+
+#define USB2_PLL_REFDIV_SHIFT_MMP3 8
+#define USB2_PLL_REFDIV_MASK_MMP3 (0xF << 8)
+
+#define USB2_PLL_VDD12_SHIFT_MMP3 12
+#define USB2_PLL_VDD18_SHIFT_MMP3 14
+
+/* This is for B0 stepping */
+#define USB2_PLL_FBDIV_SHIFT_MMP3_B0 0
+#define USB2_PLL_REFDIV_SHIFT_MMP3_B0 9
+#define USB2_PLL_VDD18_SHIFT_MMP3_B0 14
+#define USB2_PLL_FBDIV_MASK_MMP3_B0 0x01FF
+#define USB2_PLL_REFDIV_MASK_MMP3_B0 0x3E00
+
+#define USB2_PLL_CAL12_SHIFT_MMP3 0
+#define USB2_PLL_CALI12_MASK_MMP3 (0x3 << 0)
+
+#define USB2_PLL_VCOCAL_START_SHIFT_MMP3 2
+
+#define USB2_PLL_KVCO_SHIFT_MMP3 4
+#define USB2_PLL_KVCO_MASK_MMP3 (0x7<<4)
+
+#define USB2_PLL_ICP_SHIFT_MMP3 8
+#define USB2_PLL_ICP_MASK_MMP3 (0x7<<8)
+
+#define USB2_PLL_LOCK_BYPASS_SHIFT_MMP3 12
+
+#define USB2_PLL_PU_PLL_SHIFT_MMP3 13
+#define USB2_PLL_PU_PLL_MASK (0x1 << 13)
+
+#define USB2_PLL_READY_MASK_MMP3 (0x1 << 15)
+
+/* USB2_TX_REG0 */
+#define USB2_TX_IMPCAL_VTH_SHIFT_MMP3 8
+#define USB2_TX_IMPCAL_VTH_MASK_MMP3 (0x7 << 8)
+
+#define USB2_TX_RCAL_START_SHIFT_MMP3 13
+
+/* USB2_TX_REG1 */
+#define USB2_TX_CK60_PHSEL_SHIFT_MMP3 0
+#define USB2_TX_CK60_PHSEL_MASK_MMP3 (0xf << 0)
+
+#define USB2_TX_AMP_SHIFT_MMP3 4
+#define USB2_TX_AMP_MASK_MMP3 (0x7 << 4)
+
+#define USB2_TX_VDD12_SHIFT_MMP3 8
+#define USB2_TX_VDD12_MASK_MMP3 (0x3 << 8)
+
+/* USB2_TX_REG2 */
+#define USB2_TX_DRV_SLEWRATE_SHIFT 10
+
+/* USB2_RX_REG0 */
+#define USB2_RX_SQ_THRESH_SHIFT_MMP3 4
+#define USB2_RX_SQ_THRESH_MASK_MMP3 (0xf << 4)
+
+#define USB2_RX_SQ_LENGTH_SHIFT_MMP3 10
+#define USB2_RX_SQ_LENGTH_MASK_MMP3 (0x3 << 10)
+
+/* USB2_ANA_REG1*/
+#define USB2_ANA_PU_ANA_SHIFT_MMP3 14
+
+/* USB2_OTG_REG0 */
+#define USB2_OTG_PU_OTG_SHIFT_MMP3 3
+
+/* fsic registers */
+#define FSIC_MISC 0x4
+#define FSIC_INT 0x28
+#define FSIC_CTRL 0x30
+
+/* HSIC registers */
+#define HSIC_PAD_CTRL 0x4
+
+#define HSIC_CTRL 0x8
+#define HSIC_CTRL_HSIC_ENABLE (1<<7)
+#define HSIC_CTRL_PLL_BYPASS (1<<4)
+
+#define TEST_GRP_0 0xc
+#define TEST_GRP_1 0x10
+
+#define HSIC_INT 0x14
+#define HSIC_INT_READY_INT_EN (1<<10)
+#define HSIC_INT_CONNECT_INT_EN (1<<9)
+#define HSIC_INT_CORE_INT_EN (1<<8)
+#define HSIC_INT_HS_READY (1<<2)
+#define HSIC_INT_CONNECT (1<<1)
+#define HSIC_INT_CORE (1<<0)
+
+#define HSIC_CONFIG 0x18
+#define USBHSIC_CTRL 0x20
+
+#define HSIC_USB_CTRL 0x28
+#define HSIC_USB_CTRL_CLKEN 1
+#define HSIC_USB_CLK_PHY 0x0
+#define HSIC_USB_CLK_PMU 0x1
+
+#endif /* __ASM_ARCH_PXA_U2O_H */
diff --git a/arch/arm/mach-mmp/irq-mmp2.c b/arch/arm/mach-mmp/irq-mmp2.c
deleted file mode 100644
index 7895d277421e..000000000000
--- a/arch/arm/mach-mmp/irq-mmp2.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * linux/arch/arm/mach-mmp/irq-mmp2.c
- *
- * Generic IRQ handling, GPIO IRQ demultiplexing, etc.
- *
- * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
- * Copyright: 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/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <mach/irqs.h>
-#include <mach/regs-icu.h>
-#include <mach/mmp2.h>
-
-#include "common.h"
-
-static void icu_mask_irq(struct irq_data *d)
-{
- uint32_t r = __raw_readl(ICU_INT_CONF(d->irq));
-
- r &= ~ICU_INT_ROUTE_PJ4_IRQ;
- __raw_writel(r, ICU_INT_CONF(d->irq));
-}
-
-static void icu_unmask_irq(struct irq_data *d)
-{
- uint32_t r = __raw_readl(ICU_INT_CONF(d->irq));
-
- r |= ICU_INT_ROUTE_PJ4_IRQ;
- __raw_writel(r, ICU_INT_CONF(d->irq));
-}
-
-static struct irq_chip icu_irq_chip = {
- .name = "icu_irq",
- .irq_mask = icu_mask_irq,
- .irq_mask_ack = icu_mask_irq,
- .irq_unmask = icu_unmask_irq,
-};
-
-static void pmic_irq_ack(struct irq_data *d)
-{
- if (d->irq == IRQ_MMP2_PMIC)
- mmp2_clear_pmic_int();
-}
-
-#define SECOND_IRQ_MASK(_name_, irq_base, prefix) \
-static void _name_##_mask_irq(struct irq_data *d) \
-{ \
- uint32_t r; \
- r = __raw_readl(prefix##_MASK) | (1 << (d->irq - irq_base)); \
- __raw_writel(r, prefix##_MASK); \
-}
-
-#define SECOND_IRQ_UNMASK(_name_, irq_base, prefix) \
-static void _name_##_unmask_irq(struct irq_data *d) \
-{ \
- uint32_t r; \
- r = __raw_readl(prefix##_MASK) & ~(1 << (d->irq - irq_base)); \
- __raw_writel(r, prefix##_MASK); \
-}
-
-#define SECOND_IRQ_DEMUX(_name_, irq_base, prefix) \
-static void _name_##_irq_demux(unsigned int irq, struct irq_desc *desc) \
-{ \
- unsigned long status, mask, n; \
- mask = __raw_readl(prefix##_MASK); \
- while (1) { \
- status = __raw_readl(prefix##_STATUS) & ~mask; \
- if (status == 0) \
- break; \
- n = find_first_bit(&status, BITS_PER_LONG); \
- while (n < BITS_PER_LONG) { \
- generic_handle_irq(irq_base + n); \
- n = find_next_bit(&status, BITS_PER_LONG, n+1); \
- } \
- } \
-}
-
-#define SECOND_IRQ_CHIP(_name_, irq_base, prefix) \
-SECOND_IRQ_MASK(_name_, irq_base, prefix) \
-SECOND_IRQ_UNMASK(_name_, irq_base, prefix) \
-SECOND_IRQ_DEMUX(_name_, irq_base, prefix) \
-static struct irq_chip _name_##_irq_chip = { \
- .name = #_name_, \
- .irq_mask = _name_##_mask_irq, \
- .irq_unmask = _name_##_unmask_irq, \
-}
-
-SECOND_IRQ_CHIP(pmic, IRQ_MMP2_PMIC_BASE, MMP2_ICU_INT4);
-SECOND_IRQ_CHIP(rtc, IRQ_MMP2_RTC_BASE, MMP2_ICU_INT5);
-SECOND_IRQ_CHIP(twsi, IRQ_MMP2_TWSI_BASE, MMP2_ICU_INT17);
-SECOND_IRQ_CHIP(misc, IRQ_MMP2_MISC_BASE, MMP2_ICU_INT35);
-SECOND_IRQ_CHIP(ssp, IRQ_MMP2_SSP_BASE, MMP2_ICU_INT51);
-
-static void init_mux_irq(struct irq_chip *chip, int start, int num)
-{
- int irq;
-
- for (irq = start; num > 0; irq++, num--) {
- struct irq_data *d = irq_get_irq_data(irq);
-
- /* mask and clear the IRQ */
- chip->irq_mask(d);
- if (chip->irq_ack)
- chip->irq_ack(d);
-
- irq_set_chip(irq, chip);
- set_irq_flags(irq, IRQF_VALID);
- irq_set_handler(irq, handle_level_irq);
- }
-}
-
-void __init mmp2_init_icu(void)
-{
- int irq;
-
- for (irq = 0; irq < IRQ_MMP2_MUX_BASE; irq++) {
- icu_mask_irq(irq_get_irq_data(irq));
- irq_set_chip(irq, &icu_irq_chip);
- set_irq_flags(irq, IRQF_VALID);
-
- switch (irq) {
- case IRQ_MMP2_PMIC_MUX:
- case IRQ_MMP2_RTC_MUX:
- case IRQ_MMP2_TWSI_MUX:
- case IRQ_MMP2_MISC_MUX:
- case IRQ_MMP2_SSP_MUX:
- break;
- default:
- irq_set_handler(irq, handle_level_irq);
- break;
- }
- }
-
- /* NOTE: IRQ_MMP2_PMIC requires the PMIC MFPR register
- * to be written to clear the interrupt
- */
- pmic_irq_chip.irq_ack = pmic_irq_ack;
-
- init_mux_irq(&pmic_irq_chip, IRQ_MMP2_PMIC_BASE, 2);
- init_mux_irq(&rtc_irq_chip, IRQ_MMP2_RTC_BASE, 2);
- init_mux_irq(&twsi_irq_chip, IRQ_MMP2_TWSI_BASE, 5);
- init_mux_irq(&misc_irq_chip, IRQ_MMP2_MISC_BASE, 15);
- init_mux_irq(&ssp_irq_chip, IRQ_MMP2_SSP_BASE, 2);
-
- irq_set_chained_handler(IRQ_MMP2_PMIC_MUX, pmic_irq_demux);
- irq_set_chained_handler(IRQ_MMP2_RTC_MUX, rtc_irq_demux);
- irq_set_chained_handler(IRQ_MMP2_TWSI_MUX, twsi_irq_demux);
- irq_set_chained_handler(IRQ_MMP2_MISC_MUX, misc_irq_demux);
- irq_set_chained_handler(IRQ_MMP2_SSP_MUX, ssp_irq_demux);
-}
diff --git a/arch/arm/mach-mmp/irq-pxa168.c b/arch/arm/mach-mmp/irq-pxa168.c
deleted file mode 100644
index 89706a0d08f1..000000000000
--- a/arch/arm/mach-mmp/irq-pxa168.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/arch/arm/mach-mmp/irq.c
- *
- * Generic IRQ handling, GPIO IRQ demultiplexing, etc.
- *
- * Author: Bin Yang <bin.yang@marvell.com>
- * Created: Sep 30, 2008
- * Copyright: 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/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <mach/regs-icu.h>
-
-#include "common.h"
-
-#define IRQ_ROUTE_TO_AP (ICU_INT_CONF_AP_INT | ICU_INT_CONF_IRQ)
-
-#define PRIORITY_DEFAULT 0x1
-#define PRIORITY_NONE 0x0 /* means IRQ disabled */
-
-static void icu_mask_irq(struct irq_data *d)
-{
- __raw_writel(PRIORITY_NONE, ICU_INT_CONF(d->irq));
-}
-
-static void icu_unmask_irq(struct irq_data *d)
-{
- __raw_writel(IRQ_ROUTE_TO_AP | PRIORITY_DEFAULT, ICU_INT_CONF(d->irq));
-}
-
-static struct irq_chip icu_irq_chip = {
- .name = "icu_irq",
- .irq_ack = icu_mask_irq,
- .irq_mask = icu_mask_irq,
- .irq_unmask = icu_unmask_irq,
-};
-
-void __init icu_init_irq(void)
-{
- int irq;
-
- for (irq = 0; irq < 64; irq++) {
- icu_mask_irq(irq_get_irq_data(irq));
- irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- }
-}
diff --git a/arch/arm/mach-mmp/irq.c b/arch/arm/mach-mmp/irq.c
new file mode 100644
index 000000000000..fcfe0e3bd701
--- /dev/null
+++ b/arch/arm/mach-mmp/irq.c
@@ -0,0 +1,458 @@
+/*
+ * linux/arch/arm/mach-mmp/irq.c
+ *
+ * Generic IRQ handling, GPIO IRQ demultiplexing, etc.
+ * Copyright (C) 2008 - 2012 Marvell Technology Group Ltd.
+ *
+ * Author: Bin Yang <bin.yang@marvell.com>
+ * Haojian Zhuang <haojian.zhuang@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/init.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <mach/irqs.h>
+
+#ifdef CONFIG_CPU_MMP2
+#include <mach/pm-mmp2.h>
+#endif
+#ifdef CONFIG_CPU_PXA910
+#include <mach/pm-pxa910.h>
+#endif
+
+#include "common.h"
+
+#define MAX_ICU_NR 16
+
+struct icu_chip_data {
+ int nr_irqs;
+ unsigned int virq_base;
+ unsigned int cascade_irq;
+ void __iomem *reg_status;
+ void __iomem *reg_mask;
+ unsigned int conf_enable;
+ unsigned int conf_disable;
+ unsigned int conf_mask;
+ unsigned int clr_mfp_irq_base;
+ unsigned int clr_mfp_hwirq;
+ struct irq_domain *domain;
+};
+
+struct mmp_intc_conf {
+ unsigned int conf_enable;
+ unsigned int conf_disable;
+ unsigned int conf_mask;
+};
+
+void __iomem *mmp_icu_base;
+static struct icu_chip_data icu_data[MAX_ICU_NR];
+static int max_icu_nr;
+
+extern void mmp2_clear_pmic_int(void);
+
+static void icu_mask_ack_irq(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct icu_chip_data *data = (struct icu_chip_data *)domain->host_data;
+ int hwirq;
+ u32 r;
+
+ hwirq = d->irq - data->virq_base;
+ if (data == &icu_data[0]) {
+ r = readl_relaxed(mmp_icu_base + (hwirq << 2));
+ r &= ~data->conf_mask;
+ r |= data->conf_disable;
+ writel_relaxed(r, mmp_icu_base + (hwirq << 2));
+ } else {
+#ifdef CONFIG_CPU_MMP2
+ if ((data->virq_base == data->clr_mfp_irq_base)
+ && (hwirq == data->clr_mfp_hwirq))
+ mmp2_clear_pmic_int();
+#endif
+ r = readl_relaxed(data->reg_mask) | (1 << hwirq);
+ writel_relaxed(r, data->reg_mask);
+ }
+}
+
+static void icu_mask_irq(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct icu_chip_data *data = (struct icu_chip_data *)domain->host_data;
+ int hwirq;
+ u32 r;
+
+ hwirq = d->irq - data->virq_base;
+ if (data == &icu_data[0]) {
+ r = readl_relaxed(mmp_icu_base + (hwirq << 2));
+ r &= ~data->conf_mask;
+ r |= data->conf_disable;
+ writel_relaxed(r, mmp_icu_base + (hwirq << 2));
+ } else {
+ r = readl_relaxed(data->reg_mask) | (1 << hwirq);
+ writel_relaxed(r, data->reg_mask);
+ }
+}
+
+static void icu_unmask_irq(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct icu_chip_data *data = (struct icu_chip_data *)domain->host_data;
+ int hwirq;
+ u32 r;
+
+ hwirq = d->irq - data->virq_base;
+ if (data == &icu_data[0]) {
+ r = readl_relaxed(mmp_icu_base + (hwirq << 2));
+ r &= ~data->conf_mask;
+ r |= data->conf_enable;
+ writel_relaxed(r, mmp_icu_base + (hwirq << 2));
+ } else {
+ r = readl_relaxed(data->reg_mask) & ~(1 << hwirq);
+ writel_relaxed(r, data->reg_mask);
+ }
+}
+
+static struct irq_chip icu_irq_chip = {
+ .name = "icu_irq",
+ .irq_mask = icu_mask_irq,
+ .irq_mask_ack = icu_mask_ack_irq,
+ .irq_unmask = icu_unmask_irq,
+};
+
+static void icu_mux_irq_demux(unsigned int irq, struct irq_desc *desc)
+{
+ struct irq_domain *domain;
+ struct icu_chip_data *data;
+ int i;
+ unsigned long mask, status, n;
+
+ for (i = 1; i < max_icu_nr; i++) {
+ if (irq == icu_data[i].cascade_irq) {
+ domain = icu_data[i].domain;
+ data = (struct icu_chip_data *)domain->host_data;
+ break;
+ }
+ }
+ if (i >= max_icu_nr) {
+ pr_err("Spurious irq %d in MMP INTC\n", irq);
+ return;
+ }
+
+ mask = readl_relaxed(data->reg_mask);
+ while (1) {
+ status = readl_relaxed(data->reg_status) & ~mask;
+ if (status == 0)
+ break;
+ n = find_first_bit(&status, BITS_PER_LONG);
+ while (n < BITS_PER_LONG) {
+ generic_handle_irq(icu_data[i].virq_base + n);
+ n = find_next_bit(&status, BITS_PER_LONG, n + 1);
+ }
+ }
+}
+
+static int mmp_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ return 0;
+}
+
+static int mmp_irq_domain_xlate(struct irq_domain *d, struct device_node *node,
+ const u32 *intspec, unsigned int intsize,
+ unsigned long *out_hwirq,
+ unsigned int *out_type)
+{
+ *out_hwirq = intspec[0];
+ return 0;
+}
+
+const struct irq_domain_ops mmp_irq_domain_ops = {
+ .map = mmp_irq_domain_map,
+ .xlate = mmp_irq_domain_xlate,
+};
+
+static struct mmp_intc_conf mmp_conf = {
+ .conf_enable = 0x51,
+ .conf_disable = 0x0,
+ .conf_mask = 0x7f,
+};
+
+static struct mmp_intc_conf mmp2_conf = {
+ .conf_enable = 0x20,
+ .conf_disable = 0x0,
+ .conf_mask = 0x7f,
+};
+
+/* MMP (ARMv5) */
+void __init icu_init_irq(void)
+{
+ int irq;
+
+ max_icu_nr = 1;
+ mmp_icu_base = ioremap(0xd4282000, 0x1000);
+ icu_data[0].conf_enable = mmp_conf.conf_enable;
+ icu_data[0].conf_disable = mmp_conf.conf_disable;
+ icu_data[0].conf_mask = mmp_conf.conf_mask;
+ icu_data[0].nr_irqs = 64;
+ icu_data[0].virq_base = 0;
+ icu_data[0].domain = irq_domain_add_legacy(NULL, 64, 0, 0,
+ &irq_domain_simple_ops,
+ &icu_data[0]);
+ for (irq = 0; irq < 64; irq++) {
+ icu_mask_irq(irq_get_irq_data(irq));
+ irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ }
+ irq_set_default_host(icu_data[0].domain);
+#ifdef CONFIG_CPU_PXA910
+ icu_irq_chip.irq_set_wake = pxa910_set_wake;
+#endif
+}
+
+/* MMP2 (ARMv7) */
+void __init mmp2_init_icu(void)
+{
+ int irq;
+
+ max_icu_nr = 8;
+ mmp_icu_base = ioremap(0xd4282000, 0x1000);
+ icu_data[0].conf_enable = mmp2_conf.conf_enable;
+ icu_data[0].conf_disable = mmp2_conf.conf_disable;
+ icu_data[0].conf_mask = mmp2_conf.conf_mask;
+ icu_data[0].nr_irqs = 64;
+ icu_data[0].virq_base = 0;
+ icu_data[0].domain = irq_domain_add_legacy(NULL, 64, 0, 0,
+ &irq_domain_simple_ops,
+ &icu_data[0]);
+ icu_data[1].reg_status = mmp_icu_base + 0x150;
+ icu_data[1].reg_mask = mmp_icu_base + 0x168;
+ icu_data[1].clr_mfp_irq_base = IRQ_MMP2_PMIC_BASE;
+ icu_data[1].clr_mfp_hwirq = IRQ_MMP2_PMIC - IRQ_MMP2_PMIC_BASE;
+ icu_data[1].nr_irqs = 2;
+ icu_data[1].virq_base = IRQ_MMP2_PMIC_BASE;
+ icu_data[1].domain = irq_domain_add_legacy(NULL, icu_data[1].nr_irqs,
+ icu_data[1].virq_base, 0,
+ &irq_domain_simple_ops,
+ &icu_data[1]);
+ icu_data[2].reg_status = mmp_icu_base + 0x154;
+ icu_data[2].reg_mask = mmp_icu_base + 0x16c;
+ icu_data[2].nr_irqs = 2;
+ icu_data[2].virq_base = IRQ_MMP2_RTC_BASE;
+ icu_data[2].domain = irq_domain_add_legacy(NULL, icu_data[2].nr_irqs,
+ icu_data[2].virq_base, 0,
+ &irq_domain_simple_ops,
+ &icu_data[2]);
+ icu_data[3].reg_status = mmp_icu_base + 0x180;
+ icu_data[3].reg_mask = mmp_icu_base + 0x17c;
+ icu_data[3].nr_irqs = 3;
+ icu_data[3].virq_base = IRQ_MMP2_KEYPAD_BASE;
+ icu_data[3].domain = irq_domain_add_legacy(NULL, icu_data[3].nr_irqs,
+ icu_data[3].virq_base, 0,
+ &irq_domain_simple_ops,
+ &icu_data[3]);
+ icu_data[4].reg_status = mmp_icu_base + 0x158;
+ icu_data[4].reg_mask = mmp_icu_base + 0x170;
+ icu_data[4].nr_irqs = 5;
+ icu_data[4].virq_base = IRQ_MMP2_TWSI_BASE;
+ icu_data[4].domain = irq_domain_add_legacy(NULL, icu_data[4].nr_irqs,
+ icu_data[4].virq_base, 0,
+ &irq_domain_simple_ops,
+ &icu_data[4]);
+ icu_data[5].reg_status = mmp_icu_base + 0x15c;
+ icu_data[5].reg_mask = mmp_icu_base + 0x174;
+ icu_data[5].nr_irqs = 15;
+ icu_data[5].virq_base = IRQ_MMP2_MISC_BASE;
+ icu_data[5].domain = irq_domain_add_legacy(NULL, icu_data[5].nr_irqs,
+ icu_data[5].virq_base, 0,
+ &irq_domain_simple_ops,
+ &icu_data[5]);
+ icu_data[6].reg_status = mmp_icu_base + 0x160;
+ icu_data[6].reg_mask = mmp_icu_base + 0x178;
+ icu_data[6].nr_irqs = 2;
+ icu_data[6].virq_base = IRQ_MMP2_MIPI_HSI1_BASE;
+ icu_data[6].domain = irq_domain_add_legacy(NULL, icu_data[6].nr_irqs,
+ icu_data[6].virq_base, 0,
+ &irq_domain_simple_ops,
+ &icu_data[6]);
+ icu_data[7].reg_status = mmp_icu_base + 0x188;
+ icu_data[7].reg_mask = mmp_icu_base + 0x184;
+ icu_data[7].nr_irqs = 2;
+ icu_data[7].virq_base = IRQ_MMP2_MIPI_HSI0_BASE;
+ icu_data[7].domain = irq_domain_add_legacy(NULL, icu_data[7].nr_irqs,
+ icu_data[7].virq_base, 0,
+ &irq_domain_simple_ops,
+ &icu_data[7]);
+ for (irq = 0; irq < IRQ_MMP2_MUX_END; irq++) {
+ icu_mask_irq(irq_get_irq_data(irq));
+ switch (irq) {
+ case IRQ_MMP2_PMIC_MUX:
+ case IRQ_MMP2_RTC_MUX:
+ case IRQ_MMP2_KEYPAD_MUX:
+ case IRQ_MMP2_TWSI_MUX:
+ case IRQ_MMP2_MISC_MUX:
+ case IRQ_MMP2_MIPI_HSI1_MUX:
+ case IRQ_MMP2_MIPI_HSI0_MUX:
+ irq_set_chip(irq, &icu_irq_chip);
+ irq_set_chained_handler(irq, icu_mux_irq_demux);
+ break;
+ default:
+ irq_set_chip_and_handler(irq, &icu_irq_chip,
+ handle_level_irq);
+ break;
+ }
+ set_irq_flags(irq, IRQF_VALID);
+ }
+ irq_set_default_host(icu_data[0].domain);
+#ifdef CONFIG_CPU_MMP2
+ icu_irq_chip.irq_set_wake = mmp2_set_wake;
+#endif
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id intc_ids[] __initconst = {
+ { .compatible = "mrvl,mmp-intc", .data = &mmp_conf },
+ { .compatible = "mrvl,mmp2-intc", .data = &mmp2_conf },
+ {}
+};
+
+static const struct of_device_id mmp_mux_irq_match[] __initconst = {
+ { .compatible = "mrvl,mmp2-mux-intc" },
+ {}
+};
+
+int __init mmp2_mux_init(struct device_node *parent)
+{
+ struct device_node *node;
+ const struct of_device_id *of_id;
+ struct resource res;
+ int i, irq_base, ret, irq;
+ u32 nr_irqs, mfp_irq;
+
+ node = parent;
+ max_icu_nr = 1;
+ for (i = 1; i < MAX_ICU_NR; i++) {
+ node = of_find_matching_node(node, mmp_mux_irq_match);
+ if (!node)
+ break;
+ of_id = of_match_node(&mmp_mux_irq_match[0], node);
+ ret = of_property_read_u32(node, "mrvl,intc-nr-irqs",
+ &nr_irqs);
+ if (ret) {
+ pr_err("Not found mrvl,intc-nr-irqs property\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ ret = of_address_to_resource(node, 0, &res);
+ if (ret < 0) {
+ pr_err("Not found reg property\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ icu_data[i].reg_status = mmp_icu_base + res.start;
+ ret = of_address_to_resource(node, 1, &res);
+ if (ret < 0) {
+ pr_err("Not found reg property\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ icu_data[i].reg_mask = mmp_icu_base + res.start;
+ icu_data[i].cascade_irq = irq_of_parse_and_map(node, 0);
+ if (!icu_data[i].cascade_irq) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
+ if (irq_base < 0) {
+ pr_err("Failed to allocate IRQ numbers for mux intc\n");
+ ret = irq_base;
+ goto err;
+ }
+ if (!of_property_read_u32(node, "mrvl,clr-mfp-irq",
+ &mfp_irq)) {
+ icu_data[i].clr_mfp_irq_base = irq_base;
+ icu_data[i].clr_mfp_hwirq = mfp_irq;
+ }
+ irq_set_chained_handler(icu_data[i].cascade_irq,
+ icu_mux_irq_demux);
+ icu_data[i].nr_irqs = nr_irqs;
+ icu_data[i].virq_base = irq_base;
+ icu_data[i].domain = irq_domain_add_legacy(node, nr_irqs,
+ irq_base, 0,
+ &mmp_irq_domain_ops,
+ &icu_data[i]);
+ for (irq = irq_base; irq < irq_base + nr_irqs; irq++)
+ icu_mask_irq(irq_get_irq_data(irq));
+ }
+ max_icu_nr = i;
+ return 0;
+err:
+ of_node_put(node);
+ max_icu_nr = i;
+ return ret;
+}
+
+void __init mmp_dt_irq_init(void)
+{
+ struct device_node *node;
+ const struct of_device_id *of_id;
+ struct mmp_intc_conf *conf;
+ int nr_irqs, irq_base, ret, irq;
+
+ node = of_find_matching_node(NULL, intc_ids);
+ if (!node) {
+ pr_err("Failed to find interrupt controller in arch-mmp\n");
+ return;
+ }
+ of_id = of_match_node(intc_ids, node);
+ conf = of_id->data;
+
+ ret = of_property_read_u32(node, "mrvl,intc-nr-irqs", &nr_irqs);
+ if (ret) {
+ pr_err("Not found mrvl,intc-nr-irqs property\n");
+ return;
+ }
+
+ mmp_icu_base = of_iomap(node, 0);
+ if (!mmp_icu_base) {
+ pr_err("Failed to get interrupt controller register\n");
+ return;
+ }
+
+ irq_base = irq_alloc_descs(-1, 0, nr_irqs - NR_IRQS_LEGACY, 0);
+ if (irq_base < 0) {
+ pr_err("Failed to allocate IRQ numbers\n");
+ goto err;
+ } else if (irq_base != NR_IRQS_LEGACY) {
+ pr_err("ICU's irqbase should be started from 0\n");
+ goto err;
+ }
+ icu_data[0].conf_enable = conf->conf_enable;
+ icu_data[0].conf_disable = conf->conf_disable;
+ icu_data[0].conf_mask = conf->conf_mask;
+ icu_data[0].nr_irqs = nr_irqs;
+ icu_data[0].virq_base = 0;
+ icu_data[0].domain = irq_domain_add_legacy(node, nr_irqs, 0, 0,
+ &mmp_irq_domain_ops,
+ &icu_data[0]);
+ irq_set_default_host(icu_data[0].domain);
+ for (irq = 0; irq < nr_irqs; irq++)
+ icu_mask_irq(irq_get_irq_data(irq));
+ mmp2_mux_init(node);
+ return;
+err:
+ iounmap(mmp_icu_base);
+}
+#endif
diff --git a/arch/arm/mach-mmp/mmp-dt.c b/arch/arm/mach-mmp/mmp-dt.c
index 67075395e400..033cc31b3c72 100644
--- a/arch/arm/mach-mmp/mmp-dt.c
+++ b/arch/arm/mach-mmp/mmp-dt.c
@@ -14,14 +14,19 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
#include <mach/irqs.h>
#include "common.h"
-extern struct sys_timer pxa168_timer;
-extern void __init icu_init_irq(void);
+extern void __init mmp_dt_irq_init(void);
+extern void __init mmp_dt_init_timer(void);
-static const struct of_dev_auxdata mmp_auxdata_lookup[] __initconst = {
+static struct sys_timer mmp_dt_timer = {
+ .init = mmp_dt_init_timer,
+};
+
+static const struct of_dev_auxdata pxa168_auxdata_lookup[] __initconst = {
OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.0", NULL),
OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.1", NULL),
OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4026000, "pxa2xx-uart.2", NULL),
@@ -32,44 +37,47 @@ static const struct of_dev_auxdata mmp_auxdata_lookup[] __initconst = {
{}
};
-static int __init mmp_intc_add_irq_domain(struct device_node *np,
- struct device_node *parent)
-{
- irq_domain_add_simple(np, 0);
- return 0;
-}
-
-static int __init mmp_gpio_add_irq_domain(struct device_node *np,
- struct device_node *parent)
-{
- irq_domain_add_simple(np, IRQ_GPIO_START);
- return 0;
-}
-
-static const struct of_device_id mmp_irq_match[] __initconst = {
- { .compatible = "mrvl,mmp-intc", .data = mmp_intc_add_irq_domain, },
- { .compatible = "mrvl,mmp-gpio", .data = mmp_gpio_add_irq_domain, },
+static const struct of_dev_auxdata pxa910_auxdata_lookup[] __initconst = {
+ OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.0", NULL),
+ OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.1", NULL),
+ OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4036000, "pxa2xx-uart.2", NULL),
+ OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4011000, "pxa2xx-i2c.0", NULL),
+ OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4037000, "pxa2xx-i2c.1", NULL),
+ OF_DEV_AUXDATA("mrvl,mmp-gpio", 0xd4019000, "pxa-gpio", NULL),
+ OF_DEV_AUXDATA("mrvl,mmp-rtc", 0xd4010000, "sa1100-rtc", NULL),
{}
};
-static void __init mmp_dt_init(void)
+static void __init pxa168_dt_init(void)
{
+ of_platform_populate(NULL, of_default_bus_match_table,
+ pxa168_auxdata_lookup, NULL);
+}
- of_irq_init(mmp_irq_match);
-
+static void __init pxa910_dt_init(void)
+{
of_platform_populate(NULL, of_default_bus_match_table,
- mmp_auxdata_lookup, NULL);
+ pxa910_auxdata_lookup, NULL);
}
-static const char *pxa168_dt_board_compat[] __initdata = {
+static const char *mmp_dt_board_compat[] __initdata = {
"mrvl,pxa168-aspenite",
+ "mrvl,pxa910-dkb",
NULL,
};
DT_MACHINE_START(PXA168_DT, "Marvell PXA168 (Device Tree Support)")
.map_io = mmp_map_io,
- .init_irq = icu_init_irq,
- .timer = &pxa168_timer,
- .init_machine = mmp_dt_init,
- .dt_compat = pxa168_dt_board_compat,
+ .init_irq = mmp_dt_irq_init,
+ .timer = &mmp_dt_timer,
+ .init_machine = pxa168_dt_init,
+ .dt_compat = mmp_dt_board_compat,
+MACHINE_END
+
+DT_MACHINE_START(PXA910_DT, "Marvell PXA910 (Device Tree Support)")
+ .map_io = mmp_map_io,
+ .init_irq = mmp_dt_irq_init,
+ .timer = &mmp_dt_timer,
+ .init_machine = pxa910_dt_init,
+ .dt_compat = mmp_dt_board_compat,
MACHINE_END
diff --git a/arch/arm/mach-mmp/mmp2-dt.c b/arch/arm/mach-mmp/mmp2-dt.c
new file mode 100644
index 000000000000..535a5ed5977b
--- /dev/null
+++ b/arch/arm/mach-mmp/mmp2-dt.c
@@ -0,0 +1,60 @@
+/*
+ * linux/arch/arm/mach-mmp/mmp2-dt.c
+ *
+ * Copyright (C) 2012 Marvell Technology Group Ltd.
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/regs-apbc.h>
+
+#include "common.h"
+
+extern void __init mmp_dt_irq_init(void);
+extern void __init mmp_dt_init_timer(void);
+
+static struct sys_timer mmp_dt_timer = {
+ .init = mmp_dt_init_timer,
+};
+
+static const struct of_dev_auxdata mmp2_auxdata_lookup[] __initconst = {
+ OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4030000, "pxa2xx-uart.0", NULL),
+ OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.1", NULL),
+ OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.2", NULL),
+ OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4016000, "pxa2xx-uart.3", NULL),
+ OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4011000, "pxa2xx-i2c.0", NULL),
+ OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4025000, "pxa2xx-i2c.1", NULL),
+ OF_DEV_AUXDATA("mrvl,mmp-gpio", 0xd4019000, "pxa-gpio", NULL),
+ OF_DEV_AUXDATA("mrvl,mmp-rtc", 0xd4010000, "sa1100-rtc", NULL),
+ {}
+};
+
+static void __init mmp2_dt_init(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table,
+ mmp2_auxdata_lookup, NULL);
+}
+
+static const char *mmp2_dt_board_compat[] __initdata = {
+ "mrvl,mmp2-brownstone",
+ NULL,
+};
+
+DT_MACHINE_START(MMP2_DT, "Marvell MMP2 (Device Tree Support)")
+ .map_io = mmp_map_io,
+ .init_irq = mmp_dt_irq_init,
+ .timer = &mmp_dt_timer,
+ .init_machine = mmp2_dt_init,
+ .dt_compat = mmp2_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/pm-mmp2.c b/arch/arm/mach-mmp/pm-mmp2.c
new file mode 100644
index 000000000000..461a191a32d2
--- /dev/null
+++ b/arch/arm/mach-mmp/pm-mmp2.c
@@ -0,0 +1,264 @@
+/*
+ * MMP2 Power Management Routines
+ *
+ * This software program is licensed subject to the GNU General Public License
+ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * (C) Copyright 2012 Marvell International Ltd.
+ * All Rights Reserved
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/suspend.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/cputype.h>
+#include <mach/addr-map.h>
+#include <mach/pm-mmp2.h>
+#include <mach/regs-icu.h>
+#include <mach/irqs.h>
+
+int mmp2_set_wake(struct irq_data *d, unsigned int on)
+{
+ int irq = d->irq;
+ struct irq_desc *desc = irq_to_desc(irq);
+ unsigned long data = 0;
+
+ if (unlikely(irq >= nr_irqs)) {
+ pr_err("IRQ nubmers are out of boundary!\n");
+ return -EINVAL;
+ }
+
+ if (on) {
+ if (desc->action)
+ desc->action->flags |= IRQF_NO_SUSPEND;
+ } else {
+ if (desc->action)
+ desc->action->flags &= ~IRQF_NO_SUSPEND;
+ }
+
+ /* enable wakeup sources */
+ switch (irq) {
+ case IRQ_MMP2_RTC:
+ case IRQ_MMP2_RTC_ALARM:
+ data = MPMU_WUCRM_PJ_WAKEUP(4) | MPMU_WUCRM_PJ_RTC_ALARM;
+ break;
+ case IRQ_MMP2_PMIC:
+ data = MPMU_WUCRM_PJ_WAKEUP(7);
+ break;
+ case IRQ_MMP2_MMC2:
+ /* mmc use WAKEUP2, same as GPIO wakeup source */
+ data = MPMU_WUCRM_PJ_WAKEUP(2);
+ break;
+ }
+ if (on) {
+ if (data) {
+ data |= __raw_readl(MPMU_WUCRM_PJ);
+ __raw_writel(data, MPMU_WUCRM_PJ);
+ }
+ } else {
+ if (data) {
+ data = ~data & __raw_readl(MPMU_WUCRM_PJ);
+ __raw_writel(data, MPMU_WUCRM_PJ);
+ }
+ }
+ return 0;
+}
+
+static void pm_scu_clk_disable(void)
+{
+ unsigned int val;
+
+ /* close AXI fabric clock gate */
+ __raw_writel(0x0, CIU_REG(0x64));
+ __raw_writel(0x0, CIU_REG(0x68));
+
+ /* close MCB master clock gate */
+ val = __raw_readl(CIU_REG(0x1c));
+ val |= 0xf0;
+ __raw_writel(val, CIU_REG(0x1c));
+
+ return ;
+}
+
+static void pm_scu_clk_enable(void)
+{
+ unsigned int val;
+
+ /* open AXI fabric clock gate */
+ __raw_writel(0x03003003, CIU_REG(0x64));
+ __raw_writel(0x00303030, CIU_REG(0x68));
+
+ /* open MCB master clock gate */
+ val = __raw_readl(CIU_REG(0x1c));
+ val &= ~(0xf0);
+ __raw_writel(val, CIU_REG(0x1c));
+
+ return ;
+}
+
+static void pm_mpmu_clk_disable(void)
+{
+ /*
+ * disable clocks in MPMU_CGR_PJ register
+ * except clock for APMU_PLL1, APMU_PLL1_2 and AP_26M
+ */
+ __raw_writel(0x0000a010, MPMU_CGR_PJ);
+}
+
+static void pm_mpmu_clk_enable(void)
+{
+ unsigned int val;
+
+ __raw_writel(0xdffefffe, MPMU_CGR_PJ);
+ val = __raw_readl(MPMU_PLL2_CTRL1);
+ val |= (1 << 29);
+ __raw_writel(val, MPMU_PLL2_CTRL1);
+
+ return ;
+}
+
+void mmp2_pm_enter_lowpower_mode(int state)
+{
+ uint32_t idle_cfg, apcr;
+
+ idle_cfg = __raw_readl(APMU_PJ_IDLE_CFG);
+ apcr = __raw_readl(MPMU_PCR_PJ);
+ apcr &= ~(MPMU_PCR_PJ_SLPEN | MPMU_PCR_PJ_DDRCORSD | MPMU_PCR_PJ_APBSD
+ | MPMU_PCR_PJ_AXISD | MPMU_PCR_PJ_VCTCXOSD | (1 << 13));
+ idle_cfg &= ~APMU_PJ_IDLE_CFG_PJ_IDLE;
+
+ switch (state) {
+ case POWER_MODE_SYS_SLEEP:
+ apcr |= MPMU_PCR_PJ_SLPEN; /* set the SLPEN bit */
+ apcr |= MPMU_PCR_PJ_VCTCXOSD; /* set VCTCXOSD */
+ /* fall through */
+ case POWER_MODE_CHIP_SLEEP:
+ apcr |= MPMU_PCR_PJ_SLPEN;
+ /* fall through */
+ case POWER_MODE_APPS_SLEEP:
+ apcr |= MPMU_PCR_PJ_APBSD; /* set APBSD */
+ /* fall through */
+ case POWER_MODE_APPS_IDLE:
+ apcr |= MPMU_PCR_PJ_AXISD; /* set AXISDD bit */
+ apcr |= MPMU_PCR_PJ_DDRCORSD; /* set DDRCORSD bit */
+ idle_cfg |= APMU_PJ_IDLE_CFG_PJ_PWRDWN; /* PJ power down */
+ apcr |= MPMU_PCR_PJ_SPSD;
+ /* fall through */
+ case POWER_MODE_CORE_EXTIDLE:
+ idle_cfg |= APMU_PJ_IDLE_CFG_PJ_IDLE; /* set the IDLE bit */
+ idle_cfg &= ~APMU_PJ_IDLE_CFG_ISO_MODE_CNTRL_MASK;
+ idle_cfg |= APMU_PJ_IDLE_CFG_PWR_SW(3)
+ | APMU_PJ_IDLE_CFG_L2_PWR_SW;
+ break;
+ case POWER_MODE_CORE_INTIDLE:
+ apcr &= ~MPMU_PCR_PJ_SPSD;
+ break;
+ }
+
+ /* set reserve bits */
+ apcr |= (1 << 30) | (1 << 25);
+
+ /* finally write the registers back */
+ __raw_writel(idle_cfg, APMU_PJ_IDLE_CFG);
+ __raw_writel(apcr, MPMU_PCR_PJ); /* 0xfe086000 */
+}
+
+static int mmp2_pm_enter(suspend_state_t state)
+{
+ int temp;
+
+ temp = __raw_readl(MMP2_ICU_INT4_MASK);
+ if (temp & (1 << 1)) {
+ printk(KERN_ERR "%s: PMIC interrupt is handling\n", __func__);
+ return -EAGAIN;
+ }
+
+ temp = __raw_readl(APMU_SRAM_PWR_DWN);
+ temp |= ((1 << 19) | (1 << 18));
+ __raw_writel(temp, APMU_SRAM_PWR_DWN);
+ pm_mpmu_clk_disable();
+ pm_scu_clk_disable();
+
+ printk(KERN_INFO "%s: before suspend\n", __func__);
+ cpu_do_idle();
+ printk(KERN_INFO "%s: after suspend\n", __func__);
+
+ pm_mpmu_clk_enable(); /* enable clocks in MPMU */
+ pm_scu_clk_enable(); /* enable clocks in SCU */
+
+ return 0;
+}
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int mmp2_pm_prepare(void)
+{
+ mmp2_pm_enter_lowpower_mode(POWER_MODE_SYS_SLEEP);
+
+ return 0;
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static void mmp2_pm_finish(void)
+{
+ mmp2_pm_enter_lowpower_mode(POWER_MODE_CORE_INTIDLE);
+}
+
+static int mmp2_pm_valid(suspend_state_t state)
+{
+ return ((state == PM_SUSPEND_STANDBY) || (state == PM_SUSPEND_MEM));
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static const struct platform_suspend_ops mmp2_pm_ops = {
+ .valid = mmp2_pm_valid,
+ .prepare = mmp2_pm_prepare,
+ .enter = mmp2_pm_enter,
+ .finish = mmp2_pm_finish,
+};
+
+static int __init mmp2_pm_init(void)
+{
+ uint32_t apcr;
+
+ if (!cpu_is_mmp2())
+ return -EIO;
+
+ suspend_set_ops(&mmp2_pm_ops);
+
+ /*
+ * Set bit 0, Slow clock Select 32K clock input instead of VCXO
+ * VCXO is chosen by default, which would be disabled in suspend
+ */
+ __raw_writel(0x5, MPMU_SCCR);
+
+ /*
+ * Clear bit 23 of CIU_CPU_CONF
+ * direct PJ4 to DDR access through Memory Controller slow queue
+ * fast queue has issue and cause lcd will flick
+ */
+ __raw_writel(__raw_readl(CIU_REG(0x8)) & ~(0x1 << 23), CIU_REG(0x8));
+
+ /* Clear default low power control bit */
+ apcr = __raw_readl(MPMU_PCR_PJ);
+ apcr &= ~(MPMU_PCR_PJ_SLPEN | MPMU_PCR_PJ_DDRCORSD
+ | MPMU_PCR_PJ_APBSD | MPMU_PCR_PJ_AXISD | 1 << 13);
+ __raw_writel(apcr, MPMU_PCR_PJ);
+
+ return 0;
+}
+
+late_initcall(mmp2_pm_init);
diff --git a/arch/arm/mach-mmp/pm-pxa910.c b/arch/arm/mach-mmp/pm-pxa910.c
new file mode 100644
index 000000000000..48981ca801a5
--- /dev/null
+++ b/arch/arm/mach-mmp/pm-pxa910.c
@@ -0,0 +1,285 @@
+/*
+ * PXA910 Power Management Routines
+ *
+ * This software program is licensed subject to the GNU General Public License
+ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * (C) Copyright 2009 Marvell International Ltd.
+ * All Rights Reserved
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/suspend.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/cputype.h>
+#include <mach/addr-map.h>
+#include <mach/pm-pxa910.h>
+#include <mach/regs-icu.h>
+#include <mach/irqs.h>
+
+int pxa910_set_wake(struct irq_data *data, unsigned int on)
+{
+ int irq = data->irq;
+ struct irq_desc *desc = irq_to_desc(data->irq);
+ uint32_t awucrm = 0, apcr = 0;
+
+ if (unlikely(irq >= nr_irqs)) {
+ pr_err("IRQ nubmers are out of boundary!\n");
+ return -EINVAL;
+ }
+
+ if (on) {
+ if (desc->action)
+ desc->action->flags |= IRQF_NO_SUSPEND;
+ } else {
+ if (desc->action)
+ desc->action->flags &= ~IRQF_NO_SUSPEND;
+ }
+
+ /* setting wakeup sources */
+ switch (irq) {
+ /* wakeup line 2 */
+ case IRQ_PXA910_AP_GPIO:
+ awucrm = MPMU_AWUCRM_WAKEUP(2);
+ apcr |= MPMU_APCR_SLPWP2;
+ break;
+ /* wakeup line 3 */
+ case IRQ_PXA910_KEYPAD:
+ awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_KEYPRESS;
+ apcr |= MPMU_APCR_SLPWP3;
+ break;
+ case IRQ_PXA910_ROTARY:
+ awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_NEWROTARY;
+ apcr |= MPMU_APCR_SLPWP3;
+ break;
+ case IRQ_PXA910_TRACKBALL:
+ awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_TRACKBALL;
+ apcr |= MPMU_APCR_SLPWP3;
+ break;
+ /* wakeup line 4 */
+ case IRQ_PXA910_AP1_TIMER1:
+ awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_1;
+ apcr |= MPMU_APCR_SLPWP4;
+ break;
+ case IRQ_PXA910_AP1_TIMER2:
+ awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_2;
+ apcr |= MPMU_APCR_SLPWP4;
+ break;
+ case IRQ_PXA910_AP1_TIMER3:
+ awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_3;
+ apcr |= MPMU_APCR_SLPWP4;
+ break;
+ case IRQ_PXA910_AP2_TIMER1:
+ awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_1;
+ apcr |= MPMU_APCR_SLPWP4;
+ break;
+ case IRQ_PXA910_AP2_TIMER2:
+ awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_2;
+ apcr |= MPMU_APCR_SLPWP4;
+ break;
+ case IRQ_PXA910_AP2_TIMER3:
+ awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_3;
+ apcr |= MPMU_APCR_SLPWP4;
+ break;
+ case IRQ_PXA910_RTC_ALARM:
+ awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_RTC_ALARM;
+ apcr |= MPMU_APCR_SLPWP4;
+ break;
+ /* wakeup line 5 */
+ case IRQ_PXA910_USB1:
+ case IRQ_PXA910_USB2:
+ awucrm = MPMU_AWUCRM_WAKEUP(5);
+ apcr |= MPMU_APCR_SLPWP5;
+ break;
+ /* wakeup line 6 */
+ case IRQ_PXA910_MMC:
+ awucrm = MPMU_AWUCRM_WAKEUP(6)
+ | MPMU_AWUCRM_SDH1
+ | MPMU_AWUCRM_SDH2;
+ apcr |= MPMU_APCR_SLPWP6;
+ break;
+ /* wakeup line 7 */
+ case IRQ_PXA910_PMIC_INT:
+ awucrm = MPMU_AWUCRM_WAKEUP(7);
+ apcr |= MPMU_APCR_SLPWP7;
+ break;
+ default:
+ if (irq >= IRQ_GPIO_START && irq < IRQ_BOARD_START) {
+ awucrm = MPMU_AWUCRM_WAKEUP(2);
+ apcr |= MPMU_APCR_SLPWP2;
+ } else
+ printk(KERN_ERR "Error: no defined wake up source irq: %d\n",
+ irq);
+ }
+
+ if (on) {
+ if (awucrm) {
+ awucrm |= __raw_readl(MPMU_AWUCRM);
+ __raw_writel(awucrm, MPMU_AWUCRM);
+ }
+ if (apcr) {
+ apcr = ~apcr & __raw_readl(MPMU_APCR);
+ __raw_writel(apcr, MPMU_APCR);
+ }
+ } else {
+ if (awucrm) {
+ awucrm = ~awucrm & __raw_readl(MPMU_AWUCRM);
+ __raw_writel(awucrm, MPMU_AWUCRM);
+ }
+ if (apcr) {
+ apcr |= __raw_readl(MPMU_APCR);
+ __raw_writel(apcr, MPMU_APCR);
+ }
+ }
+ return 0;
+}
+
+void pxa910_pm_enter_lowpower_mode(int state)
+{
+ uint32_t idle_cfg, apcr;
+
+ idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG);
+ apcr = __raw_readl(MPMU_APCR);
+
+ apcr &= ~(MPMU_APCR_DDRCORSD | MPMU_APCR_APBSD | MPMU_APCR_AXISD
+ | MPMU_APCR_VCTCXOSD | MPMU_APCR_STBYEN);
+ idle_cfg &= ~(APMU_MOH_IDLE_CFG_MOH_IDLE
+ | APMU_MOH_IDLE_CFG_MOH_PWRDWN);
+
+ switch (state) {
+ case POWER_MODE_UDR:
+ /* only shutdown APB in UDR */
+ apcr |= MPMU_APCR_STBYEN | MPMU_APCR_APBSD;
+ /* fall through */
+ case POWER_MODE_SYS_SLEEP:
+ apcr |= MPMU_APCR_SLPEN; /* set the SLPEN bit */
+ apcr |= MPMU_APCR_VCTCXOSD; /* set VCTCXOSD */
+ /* fall through */
+ case POWER_MODE_APPS_SLEEP:
+ apcr |= MPMU_APCR_DDRCORSD; /* set DDRCORSD */
+ /* fall through */
+ case POWER_MODE_APPS_IDLE:
+ apcr |= MPMU_APCR_AXISD; /* set AXISDD bit */
+ /* fall through */
+ case POWER_MODE_CORE_EXTIDLE:
+ idle_cfg |= APMU_MOH_IDLE_CFG_MOH_IDLE;
+ idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWRDWN;
+ idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWR_SW(3)
+ | APMU_MOH_IDLE_CFG_MOH_L2_PWR_SW(3);
+ /* fall through */
+ case POWER_MODE_CORE_INTIDLE:
+ break;
+ }
+
+ /* program the memory controller hardware sleep type and auto wakeup */
+ idle_cfg |= APMU_MOH_IDLE_CFG_MOH_DIS_MC_SW_REQ;
+ idle_cfg |= APMU_MOH_IDLE_CFG_MOH_MC_WAKE_EN;
+ __raw_writel(0x0, APMU_MC_HW_SLP_TYPE); /* auto refresh */
+
+ /* set DSPSD, DTCMSD, BBSD, MSASLPEN */
+ apcr |= MPMU_APCR_DSPSD | MPMU_APCR_DTCMSD | MPMU_APCR_BBSD
+ | MPMU_APCR_MSASLPEN;
+
+ /*always set SLEPEN bit mainly for MSA*/
+ apcr |= MPMU_APCR_SLPEN;
+
+ /* finally write the registers back */
+ __raw_writel(idle_cfg, APMU_MOH_IDLE_CFG);
+ __raw_writel(apcr, MPMU_APCR);
+
+}
+
+static int pxa910_pm_enter(suspend_state_t state)
+{
+ unsigned int idle_cfg, reg = 0;
+
+ /*pmic thread not completed,exit;otherwise system can't be waked up*/
+ reg = __raw_readl(ICU_INT_CONF(IRQ_PXA910_PMIC_INT));
+ if ((reg & 0x3) == 0)
+ return -EAGAIN;
+
+ idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG);
+ idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWRDWN
+ | APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN;
+ __raw_writel(idle_cfg, APMU_MOH_IDLE_CFG);
+
+ /* disable L2 */
+ outer_disable();
+ /* wait for l2 idle */
+ while (!(readl(CIU_REG(0x8)) & (1 << 16)))
+ udelay(1);
+
+ cpu_do_idle();
+
+ /* enable L2 */
+ outer_resume();
+ /* wait for l2 idle */
+ while (!(readl(CIU_REG(0x8)) & (1 << 16)))
+ udelay(1);
+
+ idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG);
+ idle_cfg &= ~(APMU_MOH_IDLE_CFG_MOH_PWRDWN
+ | APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN);
+ __raw_writel(idle_cfg, APMU_MOH_IDLE_CFG);
+
+ return 0;
+}
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int pxa910_pm_prepare(void)
+{
+ pxa910_pm_enter_lowpower_mode(POWER_MODE_UDR);
+ return 0;
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static void pxa910_pm_finish(void)
+{
+ pxa910_pm_enter_lowpower_mode(POWER_MODE_CORE_INTIDLE);
+}
+
+static int pxa910_pm_valid(suspend_state_t state)
+{
+ return ((state == PM_SUSPEND_STANDBY) || (state == PM_SUSPEND_MEM));
+}
+
+static const struct platform_suspend_ops pxa910_pm_ops = {
+ .valid = pxa910_pm_valid,
+ .prepare = pxa910_pm_prepare,
+ .enter = pxa910_pm_enter,
+ .finish = pxa910_pm_finish,
+};
+
+static int __init pxa910_pm_init(void)
+{
+ uint32_t awucrm = 0;
+
+ if (!cpu_is_pxa910())
+ return -EIO;
+
+ suspend_set_ops(&pxa910_pm_ops);
+
+ /* Set the following bits for MMP3 playback with VCTXO on */
+ __raw_writel(__raw_readl(APMU_SQU_CLK_GATE_CTRL) | (1 << 30),
+ APMU_SQU_CLK_GATE_CTRL);
+ __raw_writel(__raw_readl(MPMU_FCCR) | (1 << 28), MPMU_FCCR);
+
+ awucrm |= MPMU_AWUCRM_AP_ASYNC_INT | MPMU_AWUCRM_AP_FULL_IDLE;
+ __raw_writel(awucrm, MPMU_AWUCRM);
+
+ return 0;
+}
+
+late_initcall(pxa910_pm_init);
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index b24d2c32cba9..62d787c34475 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -14,6 +14,7 @@
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/platform_data/mv_usb.h>
#include <asm/mach/time.h>
#include <asm/system_misc.h>
@@ -27,6 +28,7 @@
#include <mach/mfp.h>
#include <linux/dma-mapping.h>
#include <mach/pxa168.h>
+#include <mach/regs-usb.h>
#include "common.h"
#include "clock.h"
@@ -93,7 +95,7 @@ static struct clk_lookup pxa168_clkregs[] = {
INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL),
INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"),
- INIT_CLKREG(&clk_usb, "pxa168-ehci", "PXA168-USBCLK"),
+ INIT_CLKREG(&clk_usb, NULL, "PXA168-USBCLK"),
INIT_CLKREG(&clk_rtc, "sa1100-rtc", NULL),
};
@@ -184,17 +186,17 @@ struct platform_device pxa168_device_gpio = {
struct resource pxa168_usb_host_resources[] = {
/* USB Host conroller register base */
[0] = {
- .start = 0xd4209000,
- .end = 0xd4209000 + 0x200,
+ .start = PXA168_U2H_REGBASE + U2x_CAPREGS_OFFSET,
+ .end = PXA168_U2H_REGBASE + USB_REG_RANGE,
.flags = IORESOURCE_MEM,
- .name = "pxa168-usb-host",
+ .name = "capregs",
},
/* USB PHY register base */
[1] = {
- .start = 0xd4206000,
- .end = 0xd4206000 + 0xff,
+ .start = PXA168_U2H_PHYBASE,
+ .end = PXA168_U2H_PHYBASE + USB_PHY_RANGE,
.flags = IORESOURCE_MEM,
- .name = "pxa168-usb-phy",
+ .name = "phyregs",
},
[2] = {
.start = IRQ_PXA168_USB2,
@@ -205,7 +207,7 @@ struct resource pxa168_usb_host_resources[] = {
static u64 pxa168_usb_host_dmamask = DMA_BIT_MASK(32);
struct platform_device pxa168_device_usb_host = {
- .name = "pxa168-ehci",
+ .name = "pxa-sph",
.id = -1,
.dev = {
.dma_mask = &pxa168_usb_host_dmamask,
@@ -216,7 +218,7 @@ struct platform_device pxa168_device_usb_host = {
.resource = pxa168_usb_host_resources,
};
-int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata)
+int __init pxa168_add_usb_host(struct mv_usb_platform_data *pdata)
{
pxa168_device_usb_host.dev.platform_data = pdata;
return platform_device_register(&pxa168_device_usb_host);
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index 43f8bcc29b67..6da52e9f2bdc 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -109,7 +109,7 @@ static struct clk_lookup pxa910_clkregs[] = {
INIT_CLKREG(&clk_pwm4, "pxa910-pwm.3", NULL),
INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL),
- INIT_CLKREG(&clk_u2o, "pxa-u2o", "U2OCLK"),
+ INIT_CLKREG(&clk_u2o, NULL, "U2OCLK"),
INIT_CLKREG(&clk_rtc, "sa1100-rtc", NULL),
};
diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c
index 71fc4ee4602c..936447c70977 100644
--- a/arch/arm/mach-mmp/time.c
+++ b/arch/arm/mach-mmp/time.c
@@ -25,6 +25,9 @@
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <asm/sched_clock.h>
#include <mach/addr-map.h>
@@ -41,6 +44,8 @@
#define MAX_DELTA (0xfffffffe)
#define MIN_DELTA (16)
+static void __iomem *mmp_timer_base = TIMERS_VIRT_BASE;
+
/*
* FIXME: the timer needs some delay to stablize the counter capture
*/
@@ -48,12 +53,12 @@ static inline uint32_t timer_read(void)
{
int delay = 100;
- __raw_writel(1, TIMERS_VIRT_BASE + TMR_CVWR(1));
+ __raw_writel(1, mmp_timer_base + TMR_CVWR(1));
while (delay--)
cpu_relax();
- return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(1));
+ return __raw_readl(mmp_timer_base + TMR_CVWR(1));
}
static u32 notrace mmp_read_sched_clock(void)
@@ -68,12 +73,12 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
/*
* Clear pending interrupt status.
*/
- __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0));
+ __raw_writel(0x01, mmp_timer_base + TMR_ICR(0));
/*
* Disable timer 0.
*/
- __raw_writel(0x02, TIMERS_VIRT_BASE + TMR_CER);
+ __raw_writel(0x02, mmp_timer_base + TMR_CER);
c->event_handler(c);
@@ -90,23 +95,23 @@ static int timer_set_next_event(unsigned long delta,
/*
* Disable timer 0.
*/
- __raw_writel(0x02, TIMERS_VIRT_BASE + TMR_CER);
+ __raw_writel(0x02, mmp_timer_base + TMR_CER);
/*
* Clear and enable timer match 0 interrupt.
*/
- __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0));
- __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_IER(0));
+ __raw_writel(0x01, mmp_timer_base + TMR_ICR(0));
+ __raw_writel(0x01, mmp_timer_base + TMR_IER(0));
/*
* Setup new clockevent timer value.
*/
- __raw_writel(delta - 1, TIMERS_VIRT_BASE + TMR_TN_MM(0, 0));
+ __raw_writel(delta - 1, mmp_timer_base + TMR_TN_MM(0, 0));
/*
* Enable timer 0.
*/
- __raw_writel(0x03, TIMERS_VIRT_BASE + TMR_CER);
+ __raw_writel(0x03, mmp_timer_base + TMR_CER);
local_irq_restore(flags);
@@ -124,7 +129,7 @@ static void timer_set_mode(enum clock_event_mode mode,
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
/* disable the matching interrupt */
- __raw_writel(0x00, TIMERS_VIRT_BASE + TMR_IER(0));
+ __raw_writel(0x00, mmp_timer_base + TMR_IER(0));
break;
case CLOCK_EVT_MODE_RESUME:
case CLOCK_EVT_MODE_PERIODIC:
@@ -157,27 +162,27 @@ static struct clocksource cksrc = {
static void __init timer_config(void)
{
- uint32_t ccr = __raw_readl(TIMERS_VIRT_BASE + TMR_CCR);
+ uint32_t ccr = __raw_readl(mmp_timer_base + TMR_CCR);
- __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_CER); /* disable */
+ __raw_writel(0x0, mmp_timer_base + TMR_CER); /* disable */
ccr &= (cpu_is_mmp2()) ? (TMR_CCR_CS_0(0) | TMR_CCR_CS_1(0)) :
(TMR_CCR_CS_0(3) | TMR_CCR_CS_1(3));
- __raw_writel(ccr, TIMERS_VIRT_BASE + TMR_CCR);
+ __raw_writel(ccr, mmp_timer_base + TMR_CCR);
/* set timer 0 to periodic mode, and timer 1 to free-running mode */
- __raw_writel(0x2, TIMERS_VIRT_BASE + TMR_CMR);
+ __raw_writel(0x2, mmp_timer_base + TMR_CMR);
- __raw_writel(0x1, TIMERS_VIRT_BASE + TMR_PLCR(0)); /* periodic */
- __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(0)); /* clear status */
- __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0));
+ __raw_writel(0x1, mmp_timer_base + TMR_PLCR(0)); /* periodic */
+ __raw_writel(0x7, mmp_timer_base + TMR_ICR(0)); /* clear status */
+ __raw_writel(0x0, mmp_timer_base + TMR_IER(0));
- __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_PLCR(1)); /* free-running */
- __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(1)); /* clear status */
- __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(1));
+ __raw_writel(0x0, mmp_timer_base + TMR_PLCR(1)); /* free-running */
+ __raw_writel(0x7, mmp_timer_base + TMR_ICR(1)); /* clear status */
+ __raw_writel(0x0, mmp_timer_base + TMR_IER(1));
/* enable timer 1 counter */
- __raw_writel(0x2, TIMERS_VIRT_BASE + TMR_CER);
+ __raw_writel(0x2, mmp_timer_base + TMR_CER);
}
static struct irqaction timer_irq = {
@@ -203,3 +208,37 @@ void __init timer_init(int irq)
clocksource_register_hz(&cksrc, CLOCK_TICK_RATE);
clockevents_register_device(&ckevt);
}
+
+#ifdef CONFIG_OF
+static struct of_device_id mmp_timer_dt_ids[] = {
+ { .compatible = "mrvl,mmp-timer", },
+ {}
+};
+
+void __init mmp_dt_init_timer(void)
+{
+ struct device_node *np;
+ int irq, ret;
+
+ np = of_find_matching_node(NULL, mmp_timer_dt_ids);
+ if (!np) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (!irq) {
+ ret = -EINVAL;
+ goto out;
+ }
+ mmp_timer_base = of_iomap(np, 0);
+ if (!mmp_timer_base) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ timer_init(irq);
+ return;
+out:
+ pr_err("Failed to get timer from device tree with error:%d\n", ret);
+}
+#endif
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
index 3fc9ed21f97d..7a7de2b12a62 100644
--- a/arch/arm/mach-mmp/ttc_dkb.c
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -17,6 +17,8 @@
#include <linux/interrupt.h>
#include <linux/i2c/pca953x.h>
#include <linux/gpio.h>
+#include <linux/mfd/88pm860x.h>
+#include <linux/platform_data/mv_usb.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -25,6 +27,7 @@
#include <mach/mfp-pxa910.h>
#include <mach/pxa910.h>
#include <mach/irqs.h>
+#include <mach/regs-usb.h>
#include "common.h"
@@ -135,8 +138,18 @@ static struct pca953x_platform_data max7312_data[] = {
},
};
+static struct pm860x_platform_data ttc_dkb_pm8607_info = {
+ .irq_base = IRQ_BOARD_START,
+};
+
static struct i2c_board_info ttc_dkb_i2c_info[] = {
{
+ .type = "88PM860x",
+ .addr = 0x34,
+ .platform_data = &ttc_dkb_pm8607_info,
+ .irq = IRQ_PXA910_PMIC_INT,
+ },
+ {
.type = "max7312",
.addr = 0x23,
.irq = MMP_GPIO_TO_IRQ(80),
@@ -144,6 +157,26 @@ static struct i2c_board_info ttc_dkb_i2c_info[] = {
},
};
+#ifdef CONFIG_USB_SUPPORT
+#if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O)
+
+static char *pxa910_usb_clock_name[] = {
+ [0] = "U2OCLK",
+};
+
+static struct mv_usb_platform_data ttc_usb_pdata = {
+ .clknum = 1,
+ .clkname = pxa910_usb_clock_name,
+ .vbus = NULL,
+ .mode = MV_USB_MODE_OTG,
+ .otg_force_a_bus_req = 1,
+ .phy_init = pxa_usb_phy_init,
+ .phy_deinit = pxa_usb_phy_deinit,
+ .set_vbus = NULL,
+};
+#endif
+#endif
+
static void __init ttc_dkb_init(void)
{
mfp_config(ARRAY_AND_SIZE(ttc_dkb_pin_config));
@@ -154,6 +187,21 @@ static void __init ttc_dkb_init(void)
/* off-chip devices */
pxa910_add_twsi(0, NULL, ARRAY_AND_SIZE(ttc_dkb_i2c_info));
platform_add_devices(ARRAY_AND_SIZE(ttc_dkb_devices));
+
+#ifdef CONFIG_USB_MV_UDC
+ pxa168_device_u2o.dev.platform_data = &ttc_usb_pdata;
+ platform_device_register(&pxa168_device_u2o);
+#endif
+
+#ifdef CONFIG_USB_EHCI_MV_U2O
+ pxa168_device_u2oehci.dev.platform_data = &ttc_usb_pdata;
+ platform_device_register(&pxa168_device_u2oehci);
+#endif
+
+#ifdef CONFIG_USB_MV_OTG
+ pxa168_device_u2ootg.dev.platform_data = &ttc_usb_pdata;
+ platform_device_register(&pxa168_device_u2ootg);
+#endif
}
MACHINE_START(TTC_DKB, "PXA910-based TTC_DKB Development Platform")
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index db81ed531031..75b3cfcada6d 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -17,7 +17,6 @@
#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/irq.h>
-#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/io.h>
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index 7e8909c978c3..fbaa4ed95a3c 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -17,7 +17,6 @@
#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/irq.h>
-#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/usb/msm_hsusb.h>
diff --git a/arch/arm/mach-msm/include/mach/debug-macro.S b/arch/arm/mach-msm/include/mach/debug-macro.S
index 3ffd8668c9a5..0e05f88abcd5 100644
--- a/arch/arm/mach-msm/include/mach/debug-macro.S
+++ b/arch/arm/mach-msm/include/mach/debug-macro.S
@@ -30,8 +30,7 @@
@ Write the 1 character to UARTDM_TF
str \rd, [\rx, #0x70]
#else
- teq \rx, #0
- strne \rd, [\rx, #0x0C]
+ str \rd, [\rx, #0x0C]
#endif
.endm
diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c
index bafabb502580..c536fd6bf827 100644
--- a/arch/arm/mach-msm/scm.c
+++ b/arch/arm/mach-msm/scm.c
@@ -282,6 +282,9 @@ u32 scm_get_version(void)
__asmeq("%1", "r1")
__asmeq("%2", "r0")
__asmeq("%3", "r1")
+#ifdef REQUIRES_SEC
+ ".arch_extension sec\n"
+#endif
"smc #0 @ switch to secure world\n"
: "=r" (r0), "=r" (r1)
: "r" (r0), "r" (r1)
diff --git a/arch/arm/mach-mv78xx0/pcie.c b/arch/arm/mach-mv78xx0/pcie.c
index df3e38055a24..2e56e86b6d68 100644
--- a/arch/arm/mach-mv78xx0/pcie.c
+++ b/arch/arm/mach-mv78xx0/pcie.c
@@ -147,6 +147,7 @@ static int __init mv78xx0_pcie_setup(int nr, struct pci_sys_data *sys)
return 0;
pp = &pcie_port[nr];
+ sys->private_data = pp;
pp->root_bus_nr = sys->busnr;
/*
@@ -161,19 +162,6 @@ static int __init mv78xx0_pcie_setup(int nr, struct pci_sys_data *sys)
return 1;
}
-static struct pcie_port *bus_to_port(int bus)
-{
- int i;
-
- for (i = num_pcie_ports - 1; i >= 0; i--) {
- int rbus = pcie_port[i].root_bus_nr;
- if (rbus != -1 && rbus <= bus)
- break;
- }
-
- return i >= 0 ? pcie_port + i : NULL;
-}
-
static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
{
/*
@@ -189,7 +177,8 @@ static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
int size, u32 *val)
{
- struct pcie_port *pp = bus_to_port(bus->number);
+ struct pci_sys_data *sys = bus->sysdata;
+ struct pcie_port *pp = sys->private_data;
unsigned long flags;
int ret;
@@ -208,7 +197,8 @@ static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 val)
{
- struct pcie_port *pp = bus_to_port(bus->number);
+ struct pci_sys_data *sys = bus->sysdata;
+ struct pcie_port *pp = sys->private_data;
unsigned long flags;
int ret;
@@ -263,7 +253,8 @@ mv78xx0_pcie_scan_bus(int nr, struct pci_sys_data *sys)
static int __init mv78xx0_pcie_map_irq(const struct pci_dev *dev, u8 slot,
u8 pin)
{
- struct pcie_port *pp = bus_to_port(dev->bus->number);
+ struct pci_sys_data *sys = dev->bus->sysdata;
+ struct pcie_port *pp = sys->private_data;
return IRQ_MV78XX0_PCIE_00 + (pp->maj << 2) + pp->min;
}
@@ -271,7 +262,6 @@ static int __init mv78xx0_pcie_map_irq(const struct pci_dev *dev, u8 slot,
static struct hw_pci mv78xx0_pci __initdata = {
.nr_controllers = 8,
.preinit = mv78xx0_pcie_preinit,
- .swizzle = pci_std_swizzle,
.setup = mv78xx0_pcie_setup,
.scan = mv78xx0_pcie_scan_bus,
.map_irq = mv78xx0_pcie_map_irq,
diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index c57f9964a713..07d5383d68ee 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -9,11 +9,13 @@ config SOC_IMX23
bool
select CPU_ARM926T
select HAVE_PWM
+ select PINCTRL_IMX23
config SOC_IMX28
bool
select CPU_ARM926T
select HAVE_PWM
+ select PINCTRL_IMX28
comment "MXS platforms:"
diff --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h
index 4d1329d59287..9acdd6387047 100644
--- a/arch/arm/mach-mxs/devices-mx23.h
+++ b/arch/arm/mach-mxs/devices-mx23.h
@@ -11,10 +11,16 @@
#include <mach/mx23.h>
#include <mach/devices-common.h>
#include <mach/mxsfb.h>
+#include <linux/amba/bus.h>
-extern const struct amba_device mx23_duart_device __initconst;
-#define mx23_add_duart() \
- mxs_add_duart(&mx23_duart_device)
+static inline int mx23_add_duart(void)
+{
+ struct amba_device *d;
+
+ d = amba_ahb_device_add(NULL, "duart", MX23_DUART_BASE_ADDR, SZ_8K,
+ MX23_INT_DUART, 0, 0, 0);
+ return IS_ERR(d) ? PTR_ERR(d) : 0;
+}
extern const struct mxs_auart_data mx23_auart_data[] __initconst;
#define mx23_add_auart(id) mxs_add_auart(&mx23_auart_data[id])
diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
index 9dbeae130842..84b2960df117 100644
--- a/arch/arm/mach-mxs/devices-mx28.h
+++ b/arch/arm/mach-mxs/devices-mx28.h
@@ -11,10 +11,16 @@
#include <mach/mx28.h>
#include <mach/devices-common.h>
#include <mach/mxsfb.h>
+#include <linux/amba/bus.h>
-extern const struct amba_device mx28_duart_device __initconst;
-#define mx28_add_duart() \
- mxs_add_duart(&mx28_duart_device)
+static inline int mx28_add_duart(void)
+{
+ struct amba_device *d;
+
+ d = amba_ahb_device_add(NULL, "duart", MX28_DUART_BASE_ADDR, SZ_8K,
+ MX28_INT_DUART, 0, 0, 0);
+ return IS_ERR(d) ? PTR_ERR(d) : 0;
+}
extern const struct mxs_auart_data mx28_auart_data[] __initconst;
#define mx28_add_auart(id) mxs_add_auart(&mx28_auart_data[id])
diff --git a/arch/arm/mach-mxs/devices.c b/arch/arm/mach-mxs/devices.c
index 01faffec3064..cf50b5a66dda 100644
--- a/arch/arm/mach-mxs/devices.c
+++ b/arch/arm/mach-mxs/devices.c
@@ -75,22 +75,6 @@ err:
return pdev;
}
-int __init mxs_add_amba_device(const struct amba_device *dev)
-{
- struct amba_device *adev = amba_device_alloc(dev->dev.init_name,
- dev->res.start, resource_size(&dev->res));
-
- if (!adev) {
- pr_err("%s: failed to allocate memory", __func__);
- return -ENOMEM;
- }
-
- adev->irq[0] = dev->irq[0];
- adev->irq[1] = dev->irq[1];
-
- return amba_device_add(adev, &iomem_resource);
-}
-
struct device mxs_apbh_bus = {
.init_name = "mxs_apbh",
.parent = &platform_bus,
diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
index c8f5c9541a30..5f72d9787444 100644
--- a/arch/arm/mach-mxs/devices/Makefile
+++ b/arch/arm/mach-mxs/devices/Makefile
@@ -1,4 +1,3 @@
-obj-$(CONFIG_MXS_HAVE_AMBA_DUART) += amba-duart.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
obj-y += platform-dma.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
diff --git a/arch/arm/mach-mxs/devices/amba-duart.c b/arch/arm/mach-mxs/devices/amba-duart.c
deleted file mode 100644
index a5479f766046..000000000000
--- a/arch/arm/mach-mxs/devices/amba-duart.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <asm/irq.h>
-#include <mach/mx23.h>
-#include <mach/mx28.h>
-#include <mach/devices-common.h>
-
-#define MXS_AMBA_DUART_DEVICE(name, soc) \
-const struct amba_device name##_device __initconst = { \
- .dev = { \
- .init_name = "duart", \
- }, \
- .res = { \
- .start = soc ## _DUART_BASE_ADDR, \
- .end = (soc ## _DUART_BASE_ADDR) + SZ_8K - 1, \
- .flags = IORESOURCE_MEM, \
- }, \
- .irq = {soc ## _INT_DUART}, \
-}
-
-#ifdef CONFIG_SOC_IMX23
-MXS_AMBA_DUART_DEVICE(mx23_duart, MX23);
-#endif
-
-#ifdef CONFIG_SOC_IMX28
-MXS_AMBA_DUART_DEVICE(mx28_duart, MX28);
-#endif
-
-int __init mxs_add_duart(const struct amba_device *dev)
-{
- return mxs_add_amba_device(dev);
-}
diff --git a/arch/arm/mach-mxs/include/mach/common.h b/arch/arm/mach-mxs/include/mach/common.h
index c50c3ea28a9d..8d88399b73ef 100644
--- a/arch/arm/mach-mxs/include/mach/common.h
+++ b/arch/arm/mach-mxs/include/mach/common.h
@@ -19,11 +19,13 @@ extern void mxs_timer_init(struct clk *, int);
extern void mxs_restart(char, const char *);
extern int mxs_saif_clkmux_select(unsigned int clkmux);
+extern void mx23_soc_init(void);
extern int mx23_register_gpios(void);
extern int mx23_clocks_init(void);
extern void mx23_map_io(void);
extern void mx23_init_irq(void);
+extern void mx28_soc_init(void);
extern int mx28_register_gpios(void);
extern int mx28_clocks_init(void);
extern void mx28_map_io(void);
diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
index f2e383955d88..21e45a70d344 100644
--- a/arch/arm/mach-mxs/include/mach/devices-common.h
+++ b/arch/arm/mach-mxs/include/mach/devices-common.h
@@ -27,11 +27,6 @@ static inline struct platform_device *mxs_add_platform_device(
name, id, res, num_resources, data, size_data, 0);
}
-int __init mxs_add_amba_device(const struct amba_device *dev);
-
-/* duart */
-int __init mxs_add_duart(const struct amba_device *dev);
-
/* auart */
struct mxs_auart_data {
int id;
diff --git a/arch/arm/mach-mxs/mach-apx4devkit.c b/arch/arm/mach-mxs/mach-apx4devkit.c
index 48a7fab571a6..5e90b9dcdef8 100644
--- a/arch/arm/mach-mxs/mach-apx4devkit.c
+++ b/arch/arm/mach-mxs/mach-apx4devkit.c
@@ -207,6 +207,8 @@ static int apx4devkit_phy_fixup(struct phy_device *phy)
static void __init apx4devkit_init(void)
{
+ mx28_soc_init();
+
mxs_iomux_setup_multiple_pads(apx4devkit_pads,
ARRAY_SIZE(apx4devkit_pads));
diff --git a/arch/arm/mach-mxs/mach-m28evk.c b/arch/arm/mach-mxs/mach-m28evk.c
index 06d79963611c..4c00c879b893 100644
--- a/arch/arm/mach-mxs/mach-m28evk.c
+++ b/arch/arm/mach-mxs/mach-m28evk.c
@@ -319,6 +319,8 @@ static struct mxs_mmc_platform_data m28evk_mmc_pdata[] __initdata = {
static void __init m28evk_init(void)
{
+ mx28_soc_init();
+
mxs_iomux_setup_multiple_pads(m28evk_pads, ARRAY_SIZE(m28evk_pads));
mx28_add_duart();
diff --git a/arch/arm/mach-mxs/mach-mx23evk.c b/arch/arm/mach-mxs/mach-mx23evk.c
index 5ea1c57d2606..e7272a41939d 100644
--- a/arch/arm/mach-mxs/mach-mx23evk.c
+++ b/arch/arm/mach-mxs/mach-mx23evk.c
@@ -141,6 +141,8 @@ static void __init mx23evk_init(void)
{
int ret;
+ mx23_soc_init();
+
mxs_iomux_setup_multiple_pads(mx23evk_pads, ARRAY_SIZE(mx23evk_pads));
mx23_add_duart();
diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
index e386c142f93c..da4610ebe9e6 100644
--- a/arch/arm/mach-mxs/mach-mx28evk.c
+++ b/arch/arm/mach-mxs/mach-mx28evk.c
@@ -413,6 +413,8 @@ static void __init mx28evk_init(void)
{
int ret;
+ mx28_soc_init();
+
mxs_iomux_setup_multiple_pads(mx28evk_pads, ARRAY_SIZE(mx28evk_pads));
mx28_add_duart();
diff --git a/arch/arm/mach-mxs/mach-stmp378x_devb.c b/arch/arm/mach-mxs/mach-stmp378x_devb.c
index a626c07b8713..6548965e4a76 100644
--- a/arch/arm/mach-mxs/mach-stmp378x_devb.c
+++ b/arch/arm/mach-mxs/mach-stmp378x_devb.c
@@ -85,6 +85,8 @@ static void __init stmp378x_dvb_init(void)
{
int ret;
+ mx23_soc_init();
+
mxs_iomux_setup_multiple_pads(stmp378x_dvb_pads,
ARRAY_SIZE(stmp378x_dvb_pads));
diff --git a/arch/arm/mach-mxs/mach-tx28.c b/arch/arm/mach-mxs/mach-tx28.c
index 2c0862e655ee..8837029de1a4 100644
--- a/arch/arm/mach-mxs/mach-tx28.c
+++ b/arch/arm/mach-mxs/mach-tx28.c
@@ -146,6 +146,8 @@ static struct mxs_mmc_platform_data tx28_mmc0_pdata __initdata = {
static void __init tx28_stk5v3_init(void)
{
+ mx28_soc_init();
+
mxs_iomux_setup_multiple_pads(tx28_stk5v3_pads,
ARRAY_SIZE(tx28_stk5v3_pads));
diff --git a/arch/arm/mach-mxs/mm.c b/arch/arm/mach-mxs/mm.c
index 50af5ceebf6d..67a384edcf5b 100644
--- a/arch/arm/mach-mxs/mm.c
+++ b/arch/arm/mach-mxs/mm.c
@@ -13,6 +13,7 @@
#include <linux/mm.h>
#include <linux/init.h>
+#include <linux/pinctrl/machine.h>
#include <asm/mach/map.h>
@@ -61,3 +62,13 @@ void __init mx28_init_irq(void)
{
icoll_init_irq();
}
+
+void __init mx23_soc_init(void)
+{
+ pinctrl_provide_dummies();
+}
+
+void __init mx28_soc_init(void)
+{
+ pinctrl_provide_dummies();
+}
diff --git a/arch/arm/mach-nomadik/Kconfig b/arch/arm/mach-nomadik/Kconfig
index 3c5e0f522e9c..365879b47c0e 100644
--- a/arch/arm/mach-nomadik/Kconfig
+++ b/arch/arm/mach-nomadik/Kconfig
@@ -15,6 +15,7 @@ config NOMADIK_8815
config I2C_BITBANG_8815NHK
tristate "Driver for bit-bang busses found on the 8815 NHK"
depends on I2C && MACH_NOMADIK_8815NHK
+ depends on PINCTRL_NOMADIK
select I2C_ALGOBIT
default y
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index dfab466ebd1d..cba3f7191cfc 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -132,6 +132,7 @@ config MACH_OMAP_PALMTT
config MACH_SX1
bool "Siemens SX1"
+ select I2C
depends on ARCH_OMAP1 && ARCH_OMAP15XX
help
Support for the Siemens SX1 phone. To boot the kernel,
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 9923f92b5450..398e9e53e189 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -12,6 +12,9 @@ endif
obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
+# OCPI interconnect support for 1710, 1610 and 5912
+obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
+
# Power Management
obj-$(CONFIG_PM) += pm.o sleep.o
@@ -28,13 +31,15 @@ usb-fs-$(CONFIG_USB) := usb.o
obj-y += $(usb-fs-m) $(usb-fs-y)
# Specific board support
-obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o board-h2-mmc.o
+obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o board-h2-mmc.o \
+ board-nand.o
obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o
obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
-obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
-obj-$(CONFIG_MACH_OMAP_FSAMPLE) += board-fsample.o
+obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o board-nand.o
+obj-$(CONFIG_MACH_OMAP_FSAMPLE) += board-fsample.o board-nand.o
obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
-obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o board-h3-mmc.o
+obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o board-h3-mmc.o \
+ board-nand.o
obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o
obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o
obj-$(CONFIG_MACH_OMAP_PALMZ71) += board-palmz71.o
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c b/arch/arm/mach-omap1/ams-delta-fiq.c
index cfd98b186fcc..68e8e5654c0a 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -102,7 +102,7 @@ void __init ams_delta_init_fiq(void)
}
retval = request_irq(INT_DEFERRED_FIQ, deferred_fiq,
- IRQ_TYPE_EDGE_RISING, "deferred_fiq", 0);
+ IRQ_TYPE_EDGE_RISING, "deferred_fiq", NULL);
if (retval < 0) {
pr_err("Failed to get deferred_fiq IRQ, ret=%d\n", retval);
release_fiq(&fh);
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 80bd43c7f4ec..4a4afb371022 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -185,20 +185,6 @@ static struct platform_device nor_device = {
.resource = &nor_resource,
};
-static void nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd->priv;
- unsigned long mask;
-
- if (cmd == NAND_CMD_NONE)
- return;
-
- mask = (ctrl & NAND_CLE) ? 0x02 : 0;
- if (ctrl & NAND_ALE)
- mask |= 0x04;
- writeb(cmd, (unsigned long)this->IO_ADDR_W | mask);
-}
-
#define FSAMPLE_NAND_RB_GPIO_PIN 62
static int nand_dev_ready(struct mtd_info *mtd)
@@ -216,7 +202,7 @@ static struct platform_nand_data nand_data = {
.part_probe_types = part_probes,
},
.ctrl = {
- .cmd_ctrl = nand_cmd_ctl,
+ .cmd_ctrl = omap1_nand_cmd_ctl,
.dev_ready = nand_dev_ready,
},
};
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 553a2e535764..057ec13f0649 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -179,20 +179,6 @@ static struct mtd_partition h2_nand_partitions[] = {
},
};
-static void h2_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd->priv;
- unsigned long mask;
-
- if (cmd == NAND_CMD_NONE)
- return;
-
- mask = (ctrl & NAND_CLE) ? 0x02 : 0;
- if (ctrl & NAND_ALE)
- mask |= 0x04;
- writeb(cmd, (unsigned long)this->IO_ADDR_W | mask);
-}
-
#define H2_NAND_RB_GPIO_PIN 62
static int h2_nand_dev_ready(struct mtd_info *mtd)
@@ -212,9 +198,8 @@ static struct platform_nand_data h2_nand_platdata = {
.part_probe_types = h2_part_probes,
},
.ctrl = {
- .cmd_ctrl = h2_nand_cmd_ctl,
+ .cmd_ctrl = omap1_nand_cmd_ctl,
.dev_ready = h2_nand_dev_ready,
-
},
};
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 4c19f4c06851..f6ddf8759657 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -181,20 +181,6 @@ static struct mtd_partition nand_partitions[] = {
},
};
-static void nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd->priv;
- unsigned long mask;
-
- if (cmd == NAND_CMD_NONE)
- return;
-
- mask = (ctrl & NAND_CLE) ? 0x02 : 0;
- if (ctrl & NAND_ALE)
- mask |= 0x04;
- writeb(cmd, (unsigned long)this->IO_ADDR_W | mask);
-}
-
#define H3_NAND_RB_GPIO_PIN 10
static int nand_dev_ready(struct mtd_info *mtd)
@@ -214,7 +200,7 @@ static struct platform_nand_data nand_platdata = {
.part_probe_types = part_probes,
},
.ctrl = {
- .cmd_ctrl = nand_cmd_ctl,
+ .cmd_ctrl = omap1_nand_cmd_ctl,
.dev_ready = nand_dev_ready,
},
diff --git a/arch/arm/mach-omap1/board-nand.c b/arch/arm/mach-omap1/board-nand.c
new file mode 100644
index 000000000000..4d0835327d20
--- /dev/null
+++ b/arch/arm/mach-omap1/board-nand.c
@@ -0,0 +1,37 @@
+/*
+ * linux/arch/arm/mach-omap1/board-nand.c
+ *
+ * Common OMAP1 board NAND code
+ *
+ * Copyright (C) 2004, 2012 Texas Instruments, Inc.
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ * Greg Lonnon (glonnon@ridgerun.com) or info@ridgerun.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+
+#include "common.h"
+
+void omap1_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *this = mtd->priv;
+ unsigned long mask;
+
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ mask = (ctrl & NAND_CLE) ? 0x02 : 0;
+ if (ctrl & NAND_ALE)
+ mask |= 0x04;
+
+ writeb(cmd, this->IO_ADDR_W + mask);
+}
+
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index a2c5abcd7c84..61ed4f0247ce 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -289,10 +289,10 @@ palmz71_gpio_setup(int early)
gpio_direction_input(PALMZ71_USBDETECT_GPIO);
if (request_irq(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
palmz71_powercable, IRQF_SAMPLE_RANDOM,
- "palmz71-cable", 0))
+ "palmz71-cable", NULL))
printk(KERN_ERR
"IRQ request for power cable failed!\n");
- palmz71_powercable(gpio_to_irq(PALMZ71_USBDETECT_GPIO), 0);
+ palmz71_powercable(gpio_to_irq(PALMZ71_USBDETECT_GPIO), NULL);
}
}
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 76d4ee05a814..a2c88890e767 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -143,20 +143,6 @@ static struct platform_device nor_device = {
.resource = &nor_resource,
};
-static void nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd->priv;
- unsigned long mask;
-
- if (cmd == NAND_CMD_NONE)
- return;
-
- mask = (ctrl & NAND_CLE) ? 0x02 : 0;
- if (ctrl & NAND_ALE)
- mask |= 0x04;
- writeb(cmd, (unsigned long)this->IO_ADDR_W | mask);
-}
-
#define P2_NAND_RB_GPIO_PIN 62
static int nand_dev_ready(struct mtd_info *mtd)
@@ -174,7 +160,7 @@ static struct platform_nand_data nand_data = {
.part_probe_types = part_probes,
},
.ctrl = {
- .cmd_ctrl = nand_cmd_ctl,
+ .cmd_ctrl = omap1_nand_cmd_ctl,
.dev_ready = nand_dev_ready,
},
};
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 67382ddd8c83..a9ee06b6cb42 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -194,9 +194,8 @@ int omap1_select_table_rate(struct clk *clk, unsigned long rate)
{
/* Find the highest supported frequency <= rate and switch to it */
struct mpu_rate * ptr;
- unsigned long dpll1_rate, ref_rate;
+ unsigned long ref_rate;
- dpll1_rate = ck_dpll1_p->rate;
ref_rate = ck_ref_p->rate;
for (ptr = omap1_rate_table; ptr->rate; ptr++) {
diff --git a/arch/arm/mach-omap1/common.h b/arch/arm/mach-omap1/common.h
index af658ad338ec..bb7779b57795 100644
--- a/arch/arm/mach-omap1/common.h
+++ b/arch/arm/mach-omap1/common.h
@@ -27,6 +27,7 @@
#define __ARCH_ARM_MACH_OMAP1_COMMON_H
#include <plat/common.h>
+#include <linux/mtd/mtd.h>
#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
void omap7xx_map_io(void);
@@ -56,8 +57,20 @@ void omap1_init_early(void);
void omap1_init_irq(void);
void omap1_restart(char, const char *);
+extern void __init omap_check_revision(void);
+
+extern void omap1_nand_cmd_ctl(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl);
+
extern struct sys_timer omap1_timer;
extern bool omap_32k_timer_init(void);
-extern void __init omap_init_consistent_dma_size(void);
+
+extern u32 omap_irq_flags;
+
+#ifdef CONFIG_ARCH_OMAP16XX
+extern int ocpi_enable(void);
+#else
+static inline int ocpi_enable(void) { return 0; }
+#endif
#endif /* __ARCH_ARM_MACH_OMAP1_COMMON_H */
diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c
index 76c67b3f9f61..29ec50fc688d 100644
--- a/arch/arm/mach-omap1/fpga.c
+++ b/arch/arm/mach-omap1/fpga.c
@@ -87,7 +87,7 @@ static void fpga_mask_ack_irq(struct irq_data *d)
fpga_ack_irq(d);
}
-void innovator_fpga_IRQ_demux(unsigned int irq, struct irq_desc *desc)
+static void innovator_fpga_IRQ_demux(unsigned int irq, struct irq_desc *desc)
{
u32 stat;
int fpga_irq;
diff --git a/arch/arm/mach-omap1/id.c b/arch/arm/mach-omap1/id.c
index 2b28e1da14b0..a1b846aacdaf 100644
--- a/arch/arm/mach-omap1/id.c
+++ b/arch/arm/mach-omap1/id.c
@@ -21,6 +21,8 @@
#include <mach/hardware.h>
+#include "common.h"
+
#define OMAP_DIE_ID_0 0xfffe1800
#define OMAP_DIE_ID_1 0xfffe1804
#define OMAP_PRODUCTION_ID_0 0xfffe2000
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index d969a7203d14..71ce017bf5d8 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -18,13 +18,12 @@
#include <plat/mux.h>
#include <plat/tc.h>
+#include <plat/dma.h>
#include "iomap.h"
#include "common.h"
#include "clock.h"
-extern void omap_check_revision(void);
-
/*
* The machine specific code may provide the extra mapping besides the
* default mapping provided here.
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index 4448114fab72..6995fb6a3345 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -49,6 +49,8 @@
#include <mach/hardware.h>
+#include "common.h"
+
#define IRQ_BANK(irq) ((irq) >> 5)
#define IRQ_BIT(irq) ((irq) & 0x1f)
diff --git a/arch/arm/mach-omap1/lcd_dma.c b/arch/arm/mach-omap1/lcd_dma.c
index 86ace9aaa663..5769c71815b2 100644
--- a/arch/arm/mach-omap1/lcd_dma.c
+++ b/arch/arm/mach-omap1/lcd_dma.c
@@ -57,7 +57,7 @@ static struct lcd_dma_info {
void *cb_data;
int active;
- unsigned long addr, size;
+ unsigned long addr;
int rotate, data_type, xres, yres;
int vxres;
int mirror;
@@ -77,11 +77,6 @@ void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
}
EXPORT_SYMBOL(omap_set_lcd_dma_b1);
-void omap_set_lcd_dma_src_port(int port)
-{
- lcd_dma.src_port = port;
-}
-
void omap_set_lcd_dma_ext_controller(int external)
{
lcd_dma.ext_ctrl = external;
diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/mach-omap1/ocpi.c
index ebe0c73c8901..238170cab5b7 100644
--- a/arch/arm/plat-omap/ocpi.c
+++ b/arch/arm/mach-omap1/ocpi.c
@@ -4,6 +4,7 @@
* Minimal OCP bus support for omap16xx
*
* Copyright (C) 2003 - 2005 Nokia Corporation
+ * Copyright (C) 2012 Texas Instruments, Inc.
* Written by Tony Lindgren <tony@atomide.com>
*
* Modified for clock framework by Paul Mundt <paul.mundt@nokia.com>.
@@ -35,6 +36,8 @@
#include <mach/hardware.h>
+#include "common.h"
+
#define OCPI_BASE 0xfffec320
#define OCPI_FAULT (OCPI_BASE + 0x00)
#define OCPI_CMD_FAULT (OCPI_BASE + 0x04)
@@ -64,7 +67,7 @@ int ocpi_enable(void)
/* Enable access for OHCI in OCPI */
val = omap_readl(OCPI_PROT);
val &= ~0xff;
- //val &= (1 << 0); /* Allow access only to EMIFS */
+ /* val &= (1 << 0); Allow access only to EMIFS */
omap_writel(val, OCPI_PROT);
val = omap_readl(OCPI_SEC);
@@ -86,7 +89,7 @@ static int __init omap_ocpi_init(void)
clk_enable(ocpi_ck);
ocpi_enable();
- printk("OMAP OCPI interconnect driver loaded\n");
+ pr_info("OMAP OCPI interconnect driver loaded\n");
return 0;
}
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index f66c32912b22..b2560d32b3a0 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -569,11 +569,10 @@ static int omap_pm_read_proc(
static void omap_pm_init_proc(void)
{
- struct proc_dir_entry *entry;
-
- entry = create_proc_read_entry("driver/omap_pm",
- S_IWUSR | S_IRUGO, NULL,
- omap_pm_read_proc, NULL);
+ /* XXX Appears to leak memory */
+ create_proc_read_entry("driver/omap_pm",
+ S_IWUSR | S_IRUGO, NULL,
+ omap_pm_read_proc, NULL);
}
#endif /* DEBUG && CONFIG_PROC_FS */
diff --git a/arch/arm/mach-omap1/reset.c b/arch/arm/mach-omap1/reset.c
index f255b153b863..b17709103866 100644
--- a/arch/arm/mach-omap1/reset.c
+++ b/arch/arm/mach-omap1/reset.c
@@ -8,6 +8,8 @@
#include <mach/hardware.h>
+#include "common.h"
+
void omap1_restart(char mode, const char *cmd)
{
/*
diff --git a/arch/arm/mach-omap1/timer.c b/arch/arm/mach-omap1/timer.c
index fb202af01d0d..64c65bcb2d67 100644
--- a/arch/arm/mach-omap1/timer.c
+++ b/arch/arm/mach-omap1/timer.c
@@ -54,8 +54,7 @@ static int omap1_dm_timer_set_src(struct platform_device *pdev,
return 0;
}
-
-int __init omap1_dm_timer_init(void)
+static int __init omap1_dm_timer_init(void)
{
int i;
int ret;
diff --git a/arch/arm/mach-omap1/usb.c b/arch/arm/mach-omap1/usb.c
index 19de03b074e3..e61afd922766 100644
--- a/arch/arm/mach-omap1/usb.c
+++ b/arch/arm/mach-omap1/usb.c
@@ -29,6 +29,8 @@
#include <plat/mux.h>
#include <plat/usb.h>
+#include "common.h"
+
/* These routines should handle the standard chip-specific modes
* for usb0/1/2 ports, covering basic mux and transceiver setup.
*
@@ -138,6 +140,7 @@ static inline void ohci_device_init(struct omap_usb_config *pdata)
if (cpu_is_omap7xx())
ohci_resources[1].start = INT_7XX_USB_HHC_1;
pdata->ohci_device = &ohci_device;
+ pdata->ocpi_enable = &ocpi_enable;
}
#else
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 8141b76283a6..964ee67a3b77 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -17,6 +17,7 @@ config ARCH_OMAP2PLUS_TYPICAL
select MENELAUS if ARCH_OMAP2
select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4
select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4
+ select HIGHMEM
help
Compile a kernel suitable for booting most boards
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 49f92bc1c311..385c083d24b2 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -4,7 +4,7 @@
# Common support
obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \
- common.o gpio.o dma.o wd_timer.o display.o i2c.o
+ common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o
omap-2-3-common = irq.o sdrc.o
hwmod-common = omap_hwmod.o \
@@ -118,16 +118,18 @@ obj-$(CONFIG_ARCH_OMAP4) += $(powerdomain-common) \
powerdomains44xx_data.o
# PRCM clockdomain control
-obj-$(CONFIG_ARCH_OMAP2) += clockdomain.o \
+clockdomain-common += clockdomain.o \
+ clockdomains_common_data.o
+obj-$(CONFIG_ARCH_OMAP2) += $(clockdomain-common) \
clockdomain2xxx_3xxx.o \
clockdomains2xxx_3xxx_data.o
obj-$(CONFIG_SOC_OMAP2420) += clockdomains2420_data.o
obj-$(CONFIG_SOC_OMAP2430) += clockdomains2430_data.o
-obj-$(CONFIG_ARCH_OMAP3) += clockdomain.o \
+obj-$(CONFIG_ARCH_OMAP3) += $(clockdomain-common) \
clockdomain2xxx_3xxx.o \
clockdomains2xxx_3xxx_data.o \
clockdomains3xxx_data.o
-obj-$(CONFIG_ARCH_OMAP4) += clockdomain.o \
+obj-$(CONFIG_ARCH_OMAP4) += $(clockdomain-common) \
clockdomain44xx.o \
clockdomains44xx_data.o
@@ -187,6 +189,9 @@ ifneq ($(CONFIG_TIDSPBRIDGE),)
obj-y += dsp.o
endif
+# OMAP2420 MSDI controller integration support ("MMC")
+obj-$(CONFIG_SOC_OMAP2420) += msdi.o
+
# Specific board support
obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o
diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c
index 1f97e7475206..447682c4e11c 100644
--- a/arch/arm/mach-omap2/am35xx-emac.c
+++ b/arch/arm/mach-omap2/am35xx-emac.c
@@ -39,26 +39,23 @@ static struct platform_device am35xx_emac_mdio_device = {
static void am35xx_enable_emac_int(void)
{
- u32 regval;
-
- regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
- regval = (regval | AM35XX_CPGMAC_C0_RX_PULSE_CLR |
- AM35XX_CPGMAC_C0_TX_PULSE_CLR |
- AM35XX_CPGMAC_C0_MISC_PULSE_CLR |
- AM35XX_CPGMAC_C0_RX_THRESH_CLR);
- omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
- regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+ u32 v;
+
+ v = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+ v |= (AM35XX_CPGMAC_C0_RX_PULSE_CLR | AM35XX_CPGMAC_C0_TX_PULSE_CLR |
+ AM35XX_CPGMAC_C0_MISC_PULSE_CLR | AM35XX_CPGMAC_C0_RX_THRESH_CLR);
+ omap_ctrl_writel(v, AM35XX_CONTROL_LVL_INTR_CLEAR);
+ omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); /* OCP barrier */
}
static void am35xx_disable_emac_int(void)
{
- u32 regval;
+ u32 v;
- regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
- regval = (regval | AM35XX_CPGMAC_C0_RX_PULSE_CLR |
- AM35XX_CPGMAC_C0_TX_PULSE_CLR);
- omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
- regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+ v = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+ v |= (AM35XX_CPGMAC_C0_RX_PULSE_CLR | AM35XX_CPGMAC_C0_TX_PULSE_CLR);
+ omap_ctrl_writel(v, AM35XX_CONTROL_LVL_INTR_CLEAR);
+ omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); /* OCP barrier */
}
static struct emac_platform_data am35xx_emac_pdata = {
@@ -92,7 +89,7 @@ static struct platform_device am35xx_emac_device = {
void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en)
{
- unsigned int regval;
+ u32 v;
int err;
am35xx_emac_pdata.rmii_en = rmii_en;
@@ -110,8 +107,8 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en)
return;
}
- regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
- regval = regval & (~(AM35XX_CPGMACSS_SW_RST));
- omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
- regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
+ v = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
+ v &= ~AM35XX_CPGMACSS_SW_RST;
+ omap_ctrl_writel(v, AM35XX_CONTROL_IP_SW_RESET);
+ omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); /* OCP barrier */
}
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index da75f239873e..37abb0d49b51 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -37,7 +37,7 @@
#include <plat/dma.h>
#include <plat/gpmc.h>
#include <video/omapdss.h>
-#include <video/omap-panel-dvi.h>
+#include <video/omap-panel-tfp410.h>
#include <plat/gpmc-smc91x.h>
@@ -113,9 +113,6 @@ static struct gpio sdp3430_dss_gpios[] __initdata = {
{SDP3430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW, "LCD Backlight"},
};
-static int lcd_enabled;
-static int dvi_enabled;
-
static void __init sdp3430_display_init(void)
{
int r;
@@ -129,44 +126,18 @@ static void __init sdp3430_display_init(void)
static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev)
{
- if (dvi_enabled) {
- printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
- return -EINVAL;
- }
-
gpio_direction_output(SDP3430_LCD_PANEL_ENABLE_GPIO, 1);
gpio_direction_output(SDP3430_LCD_PANEL_BACKLIGHT_GPIO, 1);
- lcd_enabled = 1;
-
return 0;
}
static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev)
{
- lcd_enabled = 0;
-
gpio_direction_output(SDP3430_LCD_PANEL_ENABLE_GPIO, 0);
gpio_direction_output(SDP3430_LCD_PANEL_BACKLIGHT_GPIO, 0);
}
-static int sdp3430_panel_enable_dvi(struct omap_dss_device *dssdev)
-{
- if (lcd_enabled) {
- printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
- return -EINVAL;
- }
-
- dvi_enabled = 1;
-
- return 0;
-}
-
-static void sdp3430_panel_disable_dvi(struct omap_dss_device *dssdev)
-{
- dvi_enabled = 0;
-}
-
static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev)
{
return 0;
@@ -186,15 +157,14 @@ static struct omap_dss_device sdp3430_lcd_device = {
.platform_disable = sdp3430_panel_disable_lcd,
};
-static struct panel_dvi_platform_data dvi_panel = {
- .platform_enable = sdp3430_panel_enable_dvi,
- .platform_disable = sdp3430_panel_disable_dvi,
+static struct tfp410_platform_data dvi_panel = {
+ .power_down_gpio = -1,
};
static struct omap_dss_device sdp3430_dvi_device = {
.name = "dvi",
.type = OMAP_DISPLAY_TYPE_DPI,
- .driver_name = "dvi",
+ .driver_name = "tfp410",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 130ab00c09a2..94af6cde2e36 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -384,6 +384,11 @@ static struct platform_device sdp4430_dmic_codec = {
.id = -1,
};
+static struct platform_device sdp4430_hdmi_audio_codec = {
+ .name = "hdmi-audio-codec",
+ .id = -1,
+};
+
static struct omap_abe_twl6040_data sdp4430_abe_audio_data = {
.card_name = "SDP4430",
.has_hs = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
@@ -418,6 +423,7 @@ static struct platform_device *sdp4430_devices[] __initdata = {
&sdp4430_vbat,
&sdp4430_dmic_codec,
&sdp4430_abe_audio,
+ &sdp4430_hdmi_audio_codec,
};
static struct omap_musb_board_data musb_board_data = {
@@ -489,50 +495,6 @@ static struct platform_device omap_vwlan_device = {
},
};
-static int omap4_twl6030_hsmmc_late_init(struct device *dev)
-{
- int irq = 0;
- struct platform_device *pdev = container_of(dev,
- struct platform_device, dev);
- struct omap_mmc_platform_data *pdata = dev->platform_data;
-
- /* Setting MMC1 Card detect Irq */
- if (pdev->id == 0) {
- irq = twl6030_mmc_card_detect_config();
- if (irq < 0) {
- pr_err("Failed configuring MMC1 card detect\n");
- return irq;
- }
- pdata->slots[0].card_detect_irq = irq;
- pdata->slots[0].card_detect = twl6030_mmc_card_detect;
- }
- return 0;
-}
-
-static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
-{
- struct omap_mmc_platform_data *pdata;
-
- /* dev can be null if CONFIG_MMC_OMAP_HS is not set */
- if (!dev) {
- pr_err("Failed %s\n", __func__);
- return;
- }
- pdata = dev->platform_data;
- pdata->init = omap4_twl6030_hsmmc_late_init;
-}
-
-static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
-{
- struct omap2_hsmmc_info *c;
-
- omap_hsmmc_init(controllers);
- for (c = controllers; c->mmc; c++)
- omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
-
- return 0;
-}
-
static struct regulator_init_data sdp4430_vaux1 = {
.constraints = {
.min_uV = 1000000,
@@ -615,7 +577,9 @@ static int __init omap4_i2c_init(void)
TWL_COMMON_REGULATOR_VANA |
TWL_COMMON_REGULATOR_VCXIO |
TWL_COMMON_REGULATOR_VUSB |
- TWL_COMMON_REGULATOR_CLK32KG);
+ TWL_COMMON_REGULATOR_CLK32KG |
+ TWL_COMMON_REGULATOR_V1V8 |
+ TWL_COMMON_REGULATOR_V2V1);
omap4_pmic_init("twl6030", &sdp4430_twldata,
&twl6040_data, OMAP44XX_IRQ_SYS_2N);
omap_register_i2c_bus(2, 400, NULL, 0);
@@ -666,6 +630,10 @@ static struct nokia_dsi_panel_data dsi1_panel = {
.use_ext_te = false,
.ext_te_gpio = 101,
.esd_interval = 0,
+ .pin_config = {
+ .num_pins = 6,
+ .pins = { 0, 1, 2, 3, 4, 5 },
+ },
};
static struct omap_dss_device sdp4430_lcd_device = {
@@ -674,13 +642,6 @@ static struct omap_dss_device sdp4430_lcd_device = {
.type = OMAP_DISPLAY_TYPE_DSI,
.data = &dsi1_panel,
.phy.dsi = {
- .clk_lane = 1,
- .clk_pol = 0,
- .data1_lane = 2,
- .data1_pol = 0,
- .data2_lane = 3,
- .data2_pol = 0,
-
.module = 0,
},
@@ -715,6 +676,10 @@ static struct nokia_dsi_panel_data dsi2_panel = {
.use_ext_te = false,
.ext_te_gpio = 103,
.esd_interval = 0,
+ .pin_config = {
+ .num_pins = 6,
+ .pins = { 0, 1, 2, 3, 4, 5 },
+ },
};
static struct omap_dss_device sdp4430_lcd2_device = {
@@ -723,12 +688,6 @@ static struct omap_dss_device sdp4430_lcd2_device = {
.type = OMAP_DISPLAY_TYPE_DSI,
.data = &dsi2_panel,
.phy.dsi = {
- .clk_lane = 1,
- .clk_pol = 0,
- .data1_lane = 2,
- .data1_pol = 0,
- .data2_lane = 3,
- .data2_pol = 0,
.module = 1,
},
@@ -758,21 +717,6 @@ static struct omap_dss_device sdp4430_lcd2_device = {
.channel = OMAP_DSS_CHANNEL_LCD2,
};
-static void sdp4430_lcd_init(void)
-{
- int r;
-
- r = gpio_request_one(dsi1_panel.reset_gpio, GPIOF_DIR_OUT,
- "lcd1_reset_gpio");
- if (r)
- pr_err("%s: Could not get lcd1_reset_gpio\n", __func__);
-
- r = gpio_request_one(dsi2_panel.reset_gpio, GPIOF_DIR_OUT,
- "lcd2_reset_gpio");
- if (r)
- pr_err("%s: Could not get lcd2_reset_gpio\n", __func__);
-}
-
static struct omap_dss_hdmi_data sdp4430_hdmi_data = {
.hpd_gpio = HDMI_GPIO_HPD,
};
@@ -858,7 +802,6 @@ static void __init omap_4430sdp_display_init(void)
if (r)
pr_err("%s: Could not get display_sel GPIO\n", __func__);
- sdp4430_lcd_init();
sdp4430_picodlp_init();
omap_display_init(&sdp4430_dss_data);
/*
diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c
index c3851e8de28b..3b8a53c1f2a8 100644
--- a/arch/arm/mach-omap2/board-am3517crane.c
+++ b/arch/arm/mach-omap2/board-am3517crane.c
@@ -30,6 +30,7 @@
#include "common.h"
#include <plat/usb.h>
+#include "am35xx-emac.h"
#include "mux.h"
#include "control.h"
@@ -90,6 +91,7 @@ static void __init am3517_crane_init(void)
}
usbhs_init(&usbhs_bdata);
+ am35xx_emac_init(AM35XX_DEFAULT_MDIO_FREQUENCY, 1);
}
MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 3645285a3e2b..99790eb646e8 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -37,7 +37,7 @@
#include <plat/usb.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
-#include <video/omap-panel-dvi.h>
+#include <video/omap-panel-tfp410.h>
#include "am35xx-emac.h"
#include "mux.h"
@@ -207,31 +207,14 @@ static struct omap_dss_device am3517_evm_tv_device = {
.platform_disable = am3517_evm_panel_disable_tv,
};
-static int am3517_evm_panel_enable_dvi(struct omap_dss_device *dssdev)
-{
- if (lcd_enabled) {
- printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
- return -EINVAL;
- }
- dvi_enabled = 1;
-
- return 0;
-}
-
-static void am3517_evm_panel_disable_dvi(struct omap_dss_device *dssdev)
-{
- dvi_enabled = 0;
-}
-
-static struct panel_dvi_platform_data dvi_panel = {
- .platform_enable = am3517_evm_panel_enable_dvi,
- .platform_disable = am3517_evm_panel_disable_dvi,
+static struct tfp410_platform_data dvi_panel = {
+ .power_down_gpio = -1,
};
static struct omap_dss_device am3517_evm_dvi_device = {
.type = OMAP_DISPLAY_TYPE_DPI,
.name = "dvi",
- .driver_name = "dvi",
+ .driver_name = "tfp410",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 909a8b91b564..c03df142ea67 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -44,7 +44,7 @@
#include <plat/usb.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
-#include <video/omap-panel-dvi.h>
+#include <video/omap-panel-tfp410.h>
#include <plat/mcspi.h>
#include <mach/hardware.h>
@@ -218,25 +218,6 @@ static void cm_t35_panel_disable_lcd(struct omap_dss_device *dssdev)
gpio_set_value(CM_T35_LCD_EN_GPIO, 0);
}
-static int cm_t35_panel_enable_dvi(struct omap_dss_device *dssdev)
-{
- if (lcd_enabled) {
- printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
- return -EINVAL;
- }
-
- gpio_set_value(CM_T35_DVI_EN_GPIO, 0);
- dvi_enabled = 1;
-
- return 0;
-}
-
-static void cm_t35_panel_disable_dvi(struct omap_dss_device *dssdev)
-{
- gpio_set_value(CM_T35_DVI_EN_GPIO, 1);
- dvi_enabled = 0;
-}
-
static int cm_t35_panel_enable_tv(struct omap_dss_device *dssdev)
{
return 0;
@@ -260,15 +241,14 @@ static struct omap_dss_device cm_t35_lcd_device = {
.phy.dpi.data_lines = 18,
};
-static struct panel_dvi_platform_data dvi_panel = {
- .platform_enable = cm_t35_panel_enable_dvi,
- .platform_disable = cm_t35_panel_disable_dvi,
+static struct tfp410_platform_data dvi_panel = {
+ .power_down_gpio = CM_T35_DVI_EN_GPIO,
};
static struct omap_dss_device cm_t35_dvi_device = {
.name = "dvi",
.type = OMAP_DISPLAY_TYPE_DPI,
- .driver_name = "dvi",
+ .driver_name = "tfp410",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
@@ -316,7 +296,6 @@ static struct spi_board_info cm_t35_lcd_spi_board_info[] __initdata = {
static struct gpio cm_t35_dss_gpios[] __initdata = {
{ CM_T35_LCD_EN_GPIO, GPIOF_OUT_INIT_LOW, "lcd enable" },
{ CM_T35_LCD_BL_GPIO, GPIOF_OUT_INIT_LOW, "lcd bl enable" },
- { CM_T35_DVI_EN_GPIO, GPIOF_OUT_INIT_HIGH, "dvi enable" },
};
static void __init cm_t35_init_display(void)
@@ -335,7 +314,6 @@ static void __init cm_t35_init_display(void)
gpio_export(CM_T35_LCD_EN_GPIO, 0);
gpio_export(CM_T35_LCD_BL_GPIO, 0);
- gpio_export(CM_T35_DVI_EN_GPIO, 0);
msleep(50);
gpio_set_value(CM_T35_LCD_EN_GPIO, 1);
@@ -498,6 +476,10 @@ static struct twl4030_gpio_platform_data cm_t35_gpio_data = {
.setup = cm_t35_twl_gpio_setup,
};
+static struct twl4030_power_data cm_t35_power_data = {
+ .use_poweroff = true,
+};
+
static struct twl4030_platform_data cm_t35_twldata = {
/* platform_data for children goes here */
.keypad = &cm_t35_kp_data,
@@ -505,6 +487,7 @@ static struct twl4030_platform_data cm_t35_twldata = {
.vmmc1 = &cm_t35_vmmc1,
.vsim = &cm_t35_vsim,
.vio = &cm_t35_vio,
+ .power = &cm_t35_power_data,
};
static void __init cm_t35_init_i2c(void)
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index a2010f07de31..b063f0d2faa6 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -47,7 +47,7 @@
#include <plat/usb.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
-#include <video/omap-panel-dvi.h>
+#include <video/omap-panel-tfp410.h>
#include <plat/mcspi.h>
#include <linux/input/matrix_keypad.h>
@@ -118,19 +118,6 @@ static void devkit8000_panel_disable_lcd(struct omap_dss_device *dssdev)
gpio_set_value_cansleep(dssdev->reset_gpio, 0);
}
-static int devkit8000_panel_enable_dvi(struct omap_dss_device *dssdev)
-{
- if (gpio_is_valid(dssdev->reset_gpio))
- gpio_set_value_cansleep(dssdev->reset_gpio, 1);
- return 0;
-}
-
-static void devkit8000_panel_disable_dvi(struct omap_dss_device *dssdev)
-{
- if (gpio_is_valid(dssdev->reset_gpio))
- gpio_set_value_cansleep(dssdev->reset_gpio, 0);
-}
-
static struct regulator_consumer_supply devkit8000_vmmc1_supply[] = {
REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
};
@@ -154,15 +141,14 @@ static struct omap_dss_device devkit8000_lcd_device = {
.phy.dpi.data_lines = 24,
};
-static struct panel_dvi_platform_data dvi_panel = {
- .platform_enable = devkit8000_panel_enable_dvi,
- .platform_disable = devkit8000_panel_disable_dvi,
+static struct tfp410_platform_data dvi_panel = {
+ .power_down_gpio = -1,
};
static struct omap_dss_device devkit8000_dvi_device = {
.name = "dvi",
.type = OMAP_DISPLAY_TYPE_DPI,
- .driver_name = "dvi",
+ .driver_name = "tfp410",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
@@ -244,13 +230,7 @@ static int devkit8000_twl_gpio_setup(struct device *dev,
}
/* gpio + 7 is "DVI_PD" (out, active low) */
- devkit8000_dvi_device.reset_gpio = gpio + 7;
- ret = gpio_request_one(devkit8000_dvi_device.reset_gpio,
- GPIOF_OUT_INIT_LOW, "DVI PowerDown");
- if (ret < 0) {
- devkit8000_dvi_device.reset_gpio = -EINVAL;
- printk(KERN_ERR "Failed to request GPIO for DVI PowerDown\n");
- }
+ dvi_panel.power_down_gpio = gpio + 7;
return 0;
}
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 0349fd2b68d8..70a81f900bb5 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -87,7 +87,7 @@ static struct omap_onenand_platform_data board_onenand_data = {
.dma_channel = -1, /* disable DMA in OMAP OneNAND driver */
};
-static void
+void
__init board_onenand_init(struct mtd_partition *onenand_parts,
u8 nr_parts, u8 cs)
{
@@ -98,7 +98,7 @@ __init board_onenand_init(struct mtd_partition *onenand_parts,
gpmc_onenand_init(&board_onenand_data);
}
#else
-static void
+void
__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
{
}
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index d25503a98417..c44b70d52021 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -47,3 +47,14 @@ static inline void board_nand_init(struct mtd_partition *nand_parts,
{
}
#endif
+
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+ defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+extern void board_onenand_init(struct mtd_partition *nand_parts,
+ u8 nr_parts, u8 cs);
+#else
+static inline void board_onenand_init(struct mtd_partition *nand_parts,
+ u8 nr_parts, u8 cs)
+{
+}
+#endif
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 098d183a0086..7302ba7ff1b9 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -15,7 +15,6 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/irqdomain.h>
-#include <linux/i2c/twl.h>
#include <mach/hardware.h>
#include <asm/hardware/gic.h>
@@ -95,22 +94,6 @@ MACHINE_END
#endif
#ifdef CONFIG_ARCH_OMAP3
-static struct twl4030_platform_data beagle_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
-};
-
-static void __init omap3_i2c_init(void)
-{
- omap3_pmic_init("twl4030", &beagle_twldata);
-}
-
-static void __init omap3_init(void)
-{
- omap3_i2c_init();
- omap_generic_init();
-}
-
static const char *omap3_boards_compat[] __initdata = {
"ti,omap3",
NULL,
@@ -122,7 +105,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
.init_early = omap3430_init_early,
.init_irq = omap_init_irq,
.handle_irq = omap3_intc_handle_irq,
- .init_machine = omap3_init,
+ .init_machine = omap_generic_init,
.timer = &omap3_timer,
.dt_compat = omap3_boards_compat,
.restart = omap_prcm_restart,
@@ -130,22 +113,6 @@ MACHINE_END
#endif
#ifdef CONFIG_ARCH_OMAP4
-static struct twl4030_platform_data sdp4430_twldata = {
- .irq_base = TWL6030_IRQ_BASE,
- .irq_end = TWL6030_IRQ_END,
-};
-
-static void __init omap4_i2c_init(void)
-{
- omap4_pmic_init("twl6030", &sdp4430_twldata, NULL, 0);
-}
-
-static void __init omap4_init(void)
-{
- omap4_i2c_init();
- omap_generic_init();
-}
-
static const char *omap4_boards_compat[] __initdata = {
"ti,omap4",
NULL,
@@ -157,7 +124,7 @@ DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
.init_early = omap4430_init_early,
.init_irq = omap_init_irq,
.handle_irq = gic_handle_irq,
- .init_machine = omap4_init,
+ .init_machine = omap_generic_init,
.timer = &omap4_timer,
.dt_compat = omap4_boards_compat,
.restart = omap_prcm_restart,
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 740cee9369ba..7a274098f67b 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -24,6 +24,8 @@
#include <linux/i2c/twl.h>
#include <linux/mmc/host.h>
+#include <linux/mtd/nand.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -32,13 +34,15 @@
#include <plat/gpmc.h>
#include <plat/usb.h>
#include <video/omapdss.h>
-#include <video/omap-panel-dvi.h>
+#include <video/omap-panel-tfp410.h>
#include <plat/onenand.h>
#include "mux.h"
#include "hsmmc.h"
#include "sdram-numonyx-m65kxxxxam.h"
#include "common-board-devices.h"
+#include "board-flash.h"
+#include "control.h"
#define IGEP2_SMSC911X_CS 5
#define IGEP2_SMSC911X_GPIO 176
@@ -60,6 +64,10 @@
#define IGEP3_GPIO_LED1_RED 16
#define IGEP3_GPIO_USBH_NRESET 183
+#define IGEP_SYSBOOT_MASK 0x1f
+#define IGEP_SYSBOOT_NAND 0x0f
+#define IGEP_SYSBOOT_ONENAND 0x10
+
/*
* IGEP2 Hardware Revision Table
*
@@ -110,8 +118,10 @@ static void __init igep2_get_revision(void)
gpio_free(IGEP2_GPIO_LED1_RED);
}
-#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
- defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+ defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) || \
+ defined(CONFIG_MTD_NAND_OMAP2) || \
+ defined(CONFIG_MTD_NAND_OMAP2_MODULE)
#define ONENAND_MAP 0x20000000
@@ -123,7 +133,7 @@ static void __init igep2_get_revision(void)
* So MTD regards it as 4KiB page size and 256KiB block size 64*(2*2048)
*/
-static struct mtd_partition igep_onenand_partitions[] = {
+static struct mtd_partition igep_flash_partitions[] = {
{
.name = "X-Loader",
.offset = 0,
@@ -151,50 +161,28 @@ static struct mtd_partition igep_onenand_partitions[] = {
},
};
-static struct omap_onenand_platform_data igep_onenand_data = {
- .parts = igep_onenand_partitions,
- .nr_parts = ARRAY_SIZE(igep_onenand_partitions),
- .dma_channel = -1, /* disable DMA in OMAP OneNAND driver */
-};
-
-static struct platform_device igep_onenand_device = {
- .name = "omap2-onenand",
- .id = -1,
- .dev = {
- .platform_data = &igep_onenand_data,
- },
-};
+static inline u32 igep_get_sysboot_value(void)
+{
+ return omap_ctrl_readl(OMAP343X_CONTROL_STATUS) & IGEP_SYSBOOT_MASK;
+}
static void __init igep_flash_init(void)
{
- u8 cs = 0;
- u8 onenandcs = GPMC_CS_NUM + 1;
-
- for (cs = 0; cs < GPMC_CS_NUM; cs++) {
- u32 ret;
- ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
- /* Check if NAND/oneNAND is configured */
- if ((ret & 0xC00) == 0x800)
- /* NAND found */
- pr_err("IGEP: Unsupported NAND found\n");
- else {
- ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
- if ((ret & 0x3F) == (ONENAND_MAP >> 24))
- /* ONENAND found */
- onenandcs = cs;
- }
- }
-
- if (onenandcs > GPMC_CS_NUM) {
- pr_err("IGEP: Unable to find configuration in GPMC\n");
- return;
+ u32 mux;
+ mux = igep_get_sysboot_value();
+
+ if (mux == IGEP_SYSBOOT_NAND) {
+ pr_info("IGEP: initializing NAND memory device\n");
+ board_nand_init(igep_flash_partitions,
+ ARRAY_SIZE(igep_flash_partitions),
+ 0, NAND_BUSWIDTH_16);
+ } else if (mux == IGEP_SYSBOOT_ONENAND) {
+ pr_info("IGEP: initializing OneNAND memory device\n");
+ board_onenand_init(igep_flash_partitions,
+ ARRAY_SIZE(igep_flash_partitions), 0);
+ } else {
+ pr_err("IGEP: Flash: unsupported sysboot sequence found\n");
}
-
- igep_onenand_data.cs = onenandcs;
-
- if (platform_device_register(&igep_onenand_device) < 0)
- pr_err("IGEP: Unable to register OneNAND device\n");
}
#else
@@ -444,28 +432,15 @@ static struct twl4030_gpio_platform_data igep_twl4030_gpio_pdata = {
.setup = igep_twl_gpio_setup,
};
-static int igep2_enable_dvi(struct omap_dss_device *dssdev)
-{
- gpio_direction_output(IGEP2_GPIO_DVI_PUP, 1);
-
- return 0;
-}
-
-static void igep2_disable_dvi(struct omap_dss_device *dssdev)
-{
- gpio_direction_output(IGEP2_GPIO_DVI_PUP, 0);
-}
-
-static struct panel_dvi_platform_data dvi_panel = {
- .platform_enable = igep2_enable_dvi,
- .platform_disable = igep2_disable_dvi,
- .i2c_bus_num = 3,
+static struct tfp410_platform_data dvi_panel = {
+ .i2c_bus_num = 3,
+ .power_down_gpio = IGEP2_GPIO_DVI_PUP,
};
static struct omap_dss_device igep2_dvi_device = {
.type = OMAP_DISPLAY_TYPE_DPI,
.name = "dvi",
- .driver_name = "dvi",
+ .driver_name = "tfp410",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
@@ -480,14 +455,6 @@ static struct omap_dss_board_info igep2_dss_data = {
.default_device = &igep2_dvi_device,
};
-static void __init igep2_display_init(void)
-{
- int err = gpio_request_one(IGEP2_GPIO_DVI_PUP, GPIOF_OUT_INIT_HIGH,
- "GPIO_DVI_PUP");
- if (err)
- pr_err("IGEP v2: Could not obtain gpio GPIO_DVI_PUP\n");
-}
-
static struct platform_device *igep_devices[] __initdata = {
&igep_vwlan_device,
};
@@ -540,7 +507,10 @@ static void __init igep_i2c_init(void)
{
int ret;
- omap3_pmic_get_config(&igep_twldata, TWL_COMMON_PDATA_USB, 0);
+ omap3_pmic_get_config(&igep_twldata, TWL_COMMON_PDATA_USB,
+ TWL_COMMON_REGULATOR_VPLL2);
+ igep_twldata.vpll2->constraints.apply_uV = true;
+ igep_twldata.vpll2->constraints.name = "VDVI";
if (machine_is_igep0020()) {
/*
@@ -554,10 +524,7 @@ static void __init igep_i2c_init(void)
igep_twldata.keypad = &igep2_keypad_pdata;
/* Get common pmic data */
- omap3_pmic_get_config(&igep_twldata, TWL_COMMON_PDATA_AUDIO,
- TWL_COMMON_REGULATOR_VPLL2);
- igep_twldata.vpll2->constraints.apply_uV = true;
- igep_twldata.vpll2->constraints.name = "VDVI";
+ omap3_pmic_get_config(&igep_twldata, TWL_COMMON_PDATA_AUDIO, 0);
}
omap3_pmic_init("twl4030", &igep_twldata);
@@ -668,7 +635,6 @@ static void __init igep_init(void)
if (machine_is_igep0020()) {
omap_display_init(&igep2_dss_data);
- igep2_display_init();
igep2_init_smsc911x();
usbhs_init(&igep2_usbhs_bdata);
} else {
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 7be8d659d91d..2a7b9a9da1db 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -42,7 +42,7 @@
#include <plat/board.h>
#include "common.h"
#include <video/omapdss.h>
-#include <video/omap-panel-dvi.h>
+#include <video/omap-panel-tfp410.h>
#include <plat/gpmc.h>
#include <plat/nand.h>
#include <plat/usb.h>
@@ -83,11 +83,13 @@ static struct {
int usb_pwr_level;
int reset_gpio;
int usr_button_gpio;
+ int mmc_caps;
} beagle_config = {
.mmc1_gpio_wp = -EINVAL,
.usb_pwr_level = GPIOF_OUT_INIT_LOW,
.reset_gpio = 129,
.usr_button_gpio = 4,
+ .mmc_caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
};
static struct gpio omap3_beagle_rev_gpios[] __initdata = {
@@ -145,10 +147,12 @@ static void __init omap3_beagle_init_rev(void)
printk(KERN_INFO "OMAP3 Beagle Rev: xM Ax/Bx\n");
omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
beagle_config.usb_pwr_level = GPIOF_OUT_INIT_HIGH;
+ beagle_config.mmc_caps &= ~MMC_CAP_8_BIT_DATA;
break;
case 2:
printk(KERN_INFO "OMAP3 Beagle Rev: xM C\n");
omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC;
+ beagle_config.mmc_caps &= ~MMC_CAP_8_BIT_DATA;
break;
default:
printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev);
@@ -189,33 +193,17 @@ static struct mtd_partition omap3beagle_nand_partitions[] = {
/* DSS */
-static int beagle_enable_dvi(struct omap_dss_device *dssdev)
-{
- if (gpio_is_valid(dssdev->reset_gpio))
- gpio_set_value(dssdev->reset_gpio, 1);
-
- return 0;
-}
-
-static void beagle_disable_dvi(struct omap_dss_device *dssdev)
-{
- if (gpio_is_valid(dssdev->reset_gpio))
- gpio_set_value(dssdev->reset_gpio, 0);
-}
-
-static struct panel_dvi_platform_data dvi_panel = {
- .platform_enable = beagle_enable_dvi,
- .platform_disable = beagle_disable_dvi,
+static struct tfp410_platform_data dvi_panel = {
.i2c_bus_num = 3,
+ .power_down_gpio = -1,
};
static struct omap_dss_device beagle_dvi_device = {
.type = OMAP_DISPLAY_TYPE_DPI,
.name = "dvi",
- .driver_name = "dvi",
+ .driver_name = "tfp410",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
- .reset_gpio = -EINVAL,
};
static struct omap_dss_device beagle_tv_device = {
@@ -236,22 +224,12 @@ static struct omap_dss_board_info beagle_dss_data = {
.default_device = &beagle_dvi_device,
};
-static void __init beagle_display_init(void)
-{
- int r;
-
- r = gpio_request_one(beagle_dvi_device.reset_gpio, GPIOF_OUT_INIT_LOW,
- "DVI reset");
- if (r < 0)
- printk(KERN_ERR "Unable to get DVI reset GPIO\n");
-}
-
#include "sdram-micron-mt46h32m32lf-6.h"
static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
- .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+ .caps = MMC_CAP_4_BIT_DATA,
.gpio_wp = -EINVAL,
.deferred = true,
},
@@ -309,7 +287,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
if (gpio_request_one(gpio + 1, GPIOF_IN, "EHCI_nOC"))
pr_err("%s: unable to configure EHCI_nOC\n", __func__);
}
- beagle_dvi_device.reset_gpio = beagle_config.reset_gpio;
+ dvi_panel.power_down_gpio = beagle_config.reset_gpio;
gpio_request_one(gpio + TWL4030_GPIO_MAX, beagle_config.usb_pwr_level,
"nEN_USB_PWR");
@@ -523,6 +501,7 @@ static void __init omap3_beagle_init(void)
if (beagle_config.mmc1_gpio_wp != -EINVAL)
omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
+ mmc[0].caps = beagle_config.mmc_caps;
omap_hsmmc_init(mmc);
omap3_beagle_i2c_init();
@@ -552,7 +531,6 @@ static void __init omap3_beagle_init(void)
omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
- beagle_display_init();
beagle_opp_init();
}
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 49df12735b41..ace3c675e9c2 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -46,7 +46,7 @@
#include "common.h"
#include <plat/mcspi.h>
#include <video/omapdss.h>
-#include <video/omap-panel-dvi.h>
+#include <video/omap-panel-tfp410.h>
#include "mux.h"
#include "sdram-micron-mt46h32m32lf-6.h"
@@ -219,35 +219,14 @@ static struct omap_dss_device omap3_evm_tv_device = {
.platform_disable = omap3_evm_disable_tv,
};
-static int omap3_evm_enable_dvi(struct omap_dss_device *dssdev)
-{
- if (lcd_enabled) {
- printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
- return -EINVAL;
- }
-
- gpio_set_value_cansleep(OMAP3EVM_DVI_PANEL_EN_GPIO, 1);
-
- dvi_enabled = 1;
- return 0;
-}
-
-static void omap3_evm_disable_dvi(struct omap_dss_device *dssdev)
-{
- gpio_set_value_cansleep(OMAP3EVM_DVI_PANEL_EN_GPIO, 0);
-
- dvi_enabled = 0;
-}
-
-static struct panel_dvi_platform_data dvi_panel = {
- .platform_enable = omap3_evm_enable_dvi,
- .platform_disable = omap3_evm_disable_dvi,
+static struct tfp410_platform_data dvi_panel = {
+ .power_down_gpio = OMAP3EVM_DVI_PANEL_EN_GPIO,
};
static struct omap_dss_device omap3_evm_dvi_device = {
.name = "dvi",
.type = OMAP_DISPLAY_TYPE_DPI,
- .driver_name = "dvi",
+ .driver_name = "tfp410",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
@@ -630,13 +609,13 @@ static struct regulator_consumer_supply dummy_supplies[] = {
static void __init omap3_evm_init(void)
{
+ struct omap_board_mux *obm;
+
omap3_evm_get_revision();
regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
- if (cpu_is_omap3630())
- omap3_mux_init(omap36x_board_mux, OMAP_PACKAGE_CBB);
- else
- omap3_mux_init(omap35x_board_mux, OMAP_PACKAGE_CBB);
+ obm = (cpu_is_omap3630()) ? omap36x_board_mux : omap35x_board_mux;
+ omap3_mux_init(obm, OMAP_PACKAGE_CBB);
omap_board_config = omap3_evm_config;
omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 9b3c141ff51b..c008bf8e1c36 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -4,8 +4,9 @@
* Copyright (C) 2010 Li-Pro.Net
* Stephan Linz <linz@li-pro.net>
*
- * Copyright (C) 2010 Logic Product Development, Inc.
+ * Copyright (C) 2010-2012 Logic Product Development, Inc.
* Peter Barada <peter.barada@logicpd.com>
+ * Ashwin BIhari <ashwin.bihari@logicpd.com>
*
* Modified from Beagle, EVM, and RX51
*
@@ -45,6 +46,7 @@
#include <plat/gpmc-smsc911x.h>
#include <plat/gpmc.h>
#include <plat/sdrc.h>
+#include <plat/usb.h>
#define OMAP3LOGIC_SMSC911X_CS 1
@@ -85,6 +87,11 @@ static struct twl4030_gpio_platform_data omap3logic_gpio_data = {
| BIT(13) | BIT(15) | BIT(16) | BIT(17),
};
+static struct twl4030_usb_data omap3logic_usb_data = {
+ .usb_mode = T2_USB_MODE_ULPI,
+};
+
+
static struct twl4030_platform_data omap3logic_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
@@ -92,6 +99,7 @@ static struct twl4030_platform_data omap3logic_twldata = {
/* platform_data for children goes here */
.gpio = &omap3logic_gpio_data,
.vmmc1 = &omap3logic_vmmc1,
+ .usb = &omap3logic_usb_data,
};
static int __init omap3logic_i2c_init(void)
@@ -185,6 +193,20 @@ static inline void __init board_smsc911x_init(void)
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
+ /* mUSB */
+ OMAP3_MUX(HSUSB0_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+ OMAP3_MUX(HSUSB0_STP, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(HSUSB0_DIR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+ OMAP3_MUX(HSUSB0_NXT, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+ OMAP3_MUX(HSUSB0_DATA0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+ OMAP3_MUX(HSUSB0_DATA1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+ OMAP3_MUX(HSUSB0_DATA2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+ OMAP3_MUX(HSUSB0_DATA3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+ OMAP3_MUX(HSUSB0_DATA4, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+ OMAP3_MUX(HSUSB0_DATA5, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+ OMAP3_MUX(HSUSB0_DATA6, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+ OMAP3_MUX(HSUSB0_DATA7, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+
{ .reg_offset = OMAP_MUX_TERMINATOR },
};
#endif
@@ -205,6 +227,8 @@ static void __init omap3logic_init(void)
board_mmc_init();
board_smsc911x_init();
+ usb_musb_init(NULL);
+
/* Ensure SDRC pins are mux'd for self-refresh */
omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 4dffc95bddd2..4396bae91677 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -42,7 +42,7 @@
#include <plat/usb.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
-#include <video/omap-panel-dvi.h>
+#include <video/omap-panel-tfp410.h>
#include <plat/mcspi.h>
#include <linux/input/matrix_keypad.h>
@@ -92,9 +92,6 @@ static inline void __init omap3stalker_init_eth(void)
#define LCD_PANEL_BKLIGHT_GPIO 210
#define ENABLE_VPLL2_DEV_GRP 0xE0
-static int lcd_enabled;
-static int dvi_enabled;
-
static void __init omap3_stalker_display_init(void)
{
return;
@@ -122,32 +119,14 @@ static struct omap_dss_device omap3_stalker_tv_device = {
.platform_disable = omap3_stalker_disable_tv,
};
-static int omap3_stalker_enable_dvi(struct omap_dss_device *dssdev)
-{
- if (lcd_enabled) {
- printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
- return -EINVAL;
- }
- gpio_set_value(DSS_ENABLE_GPIO, 1);
- dvi_enabled = 1;
- return 0;
-}
-
-static void omap3_stalker_disable_dvi(struct omap_dss_device *dssdev)
-{
- gpio_set_value(DSS_ENABLE_GPIO, 0);
- dvi_enabled = 0;
-}
-
-static struct panel_dvi_platform_data dvi_panel = {
- .platform_enable = omap3_stalker_enable_dvi,
- .platform_disable = omap3_stalker_disable_dvi,
+static struct tfp410_platform_data dvi_panel = {
+ .power_down_gpio = DSS_ENABLE_GPIO,
};
static struct omap_dss_device omap3_stalker_dvi_device = {
.name = "dvi",
.type = OMAP_DISPLAY_TYPE_DPI,
- .driver_name = "dvi",
+ .driver_name = "tfp410",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 1b782ba53433..68b8fc9ff010 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -28,6 +28,7 @@
#include <linux/mfd/twl6040.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
+#include <linux/ti_wilink_st.h>
#include <linux/wl12xx.h>
#include <linux/platform_data/omap-abe-twl6040.h>
@@ -42,7 +43,7 @@
#include "common.h"
#include <plat/usb.h>
#include <plat/mmc.h>
-#include <video/omap-panel-dvi.h>
+#include <video/omap-panel-tfp410.h>
#include "hsmmc.h"
#include "control.h"
@@ -58,12 +59,21 @@
#define HDMI_GPIO_HPD 63 /* Hotplug detect */
/* wl127x BT, FM, GPS connectivity chip */
-static int wl1271_gpios[] = {46, -1, -1};
+static struct ti_st_plat_data wilink_platform_data = {
+ .nshutdown_gpio = 46,
+ .dev_name = "/dev/ttyO1",
+ .flow_cntrl = 1,
+ .baud_rate = 3000000,
+ .chip_enable = NULL,
+ .suspend = NULL,
+ .resume = NULL,
+};
+
static struct platform_device wl1271_device = {
.name = "kim",
.id = -1,
.dev = {
- .platform_data = &wl1271_gpios,
+ .platform_data = &wilink_platform_data,
},
};
@@ -117,6 +127,11 @@ static struct platform_device panda_abe_audio = {
},
};
+static struct platform_device panda_hdmi_audio_codec = {
+ .name = "hdmi-audio-codec",
+ .id = -1,
+};
+
static struct platform_device btwilink_device = {
.name = "btwilink",
.id = -1,
@@ -126,6 +141,7 @@ static struct platform_device *panda_devices[] __initdata = {
&leds_gpio,
&wl1271_device,
&panda_abe_audio,
+ &panda_hdmi_audio_codec,
&btwilink_device,
};
@@ -231,60 +247,11 @@ static struct platform_device omap_vwlan_device = {
},
};
-struct wl12xx_platform_data omap_panda_wlan_data __initdata = {
+static struct wl12xx_platform_data omap_panda_wlan_data __initdata = {
/* PANDA ref clock is 38.4 MHz */
.board_ref_clock = 2,
};
-static int omap4_twl6030_hsmmc_late_init(struct device *dev)
-{
- int irq = 0;
- struct platform_device *pdev = container_of(dev,
- struct platform_device, dev);
- struct omap_mmc_platform_data *pdata = dev->platform_data;
-
- if (!pdata) {
- dev_err(dev, "%s: NULL platform data\n", __func__);
- return -EINVAL;
- }
- /* Setting MMC1 Card detect Irq */
- if (pdev->id == 0) {
- irq = twl6030_mmc_card_detect_config();
- if (irq < 0) {
- dev_err(dev, "%s: Error card detect config(%d)\n",
- __func__, irq);
- return irq;
- }
- pdata->slots[0].card_detect = twl6030_mmc_card_detect;
- }
- return 0;
-}
-
-static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
-{
- struct omap_mmc_platform_data *pdata;
-
- /* dev can be null if CONFIG_MMC_OMAP_HS is not set */
- if (!dev) {
- pr_err("Failed omap4_twl6030_hsmmc_set_late_init\n");
- return;
- }
- pdata = dev->platform_data;
-
- pdata->init = omap4_twl6030_hsmmc_late_init;
-}
-
-static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
-{
- struct omap2_hsmmc_info *c;
-
- omap_hsmmc_init(controllers);
- for (c = controllers; c->mmc; c++)
- omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
-
- return 0;
-}
-
static struct twl6040_codec_data twl6040_codec = {
/* single-step ramp for headset and handsfree */
.hs_left_step = 0x0f,
@@ -323,7 +290,9 @@ static int __init omap4_panda_i2c_init(void)
TWL_COMMON_REGULATOR_VANA |
TWL_COMMON_REGULATOR_VCXIO |
TWL_COMMON_REGULATOR_VUSB |
- TWL_COMMON_REGULATOR_CLK32KG);
+ TWL_COMMON_REGULATOR_CLK32KG |
+ TWL_COMMON_REGULATOR_V1V8 |
+ TWL_COMMON_REGULATOR_V2V1);
omap4_pmic_init("twl6030", &omap4_panda_twldata,
&twl6040_data, OMAP44XX_IRQ_SYS_2N);
omap_register_i2c_bus(2, 400, NULL, 0);
@@ -420,47 +389,22 @@ static struct omap_board_mux board_mux[] __initdata = {
/* Display DVI */
#define PANDA_DVI_TFP410_POWER_DOWN_GPIO 0
-static int omap4_panda_enable_dvi(struct omap_dss_device *dssdev)
-{
- gpio_set_value(dssdev->reset_gpio, 1);
- return 0;
-}
-
-static void omap4_panda_disable_dvi(struct omap_dss_device *dssdev)
-{
- gpio_set_value(dssdev->reset_gpio, 0);
-}
-
/* Using generic display panel */
-static struct panel_dvi_platform_data omap4_dvi_panel = {
- .platform_enable = omap4_panda_enable_dvi,
- .platform_disable = omap4_panda_disable_dvi,
- .i2c_bus_num = 3,
+static struct tfp410_platform_data omap4_dvi_panel = {
+ .i2c_bus_num = 3,
+ .power_down_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO,
};
-struct omap_dss_device omap4_panda_dvi_device = {
+static struct omap_dss_device omap4_panda_dvi_device = {
.type = OMAP_DISPLAY_TYPE_DPI,
.name = "dvi",
- .driver_name = "dvi",
+ .driver_name = "tfp410",
.data = &omap4_dvi_panel,
.phy.dpi.data_lines = 24,
.reset_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO,
.channel = OMAP_DSS_CHANNEL_LCD2,
};
-int __init omap4_panda_dvi_init(void)
-{
- int r;
-
- /* Requesting TFP410 DVI GPIO and disabling it, at bootup */
- r = gpio_request_one(omap4_panda_dvi_device.reset_gpio,
- GPIOF_OUT_INIT_LOW, "DVI PD");
- if (r)
- pr_err("Failed to get DVI powerdown GPIO\n");
-
- return r;
-}
-
static struct gpio panda_hdmi_gpios[] = {
{ HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
{ HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
@@ -509,13 +453,8 @@ static struct omap_dss_board_info omap4_panda_dss_data = {
.default_device = &omap4_panda_dvi_device,
};
-void __init omap4_panda_display_init(void)
+static void __init omap4_panda_display_init(void)
{
- int r;
-
- r = omap4_panda_dvi_init();
- if (r)
- pr_err("error initializing panda DVI\n");
omap_display_init(&omap4_panda_dss_data);
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 33aa3910b09e..5527c1979a16 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -46,7 +46,7 @@
#include "common.h"
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
-#include <video/omap-panel-dvi.h>
+#include <video/omap-panel-tfp410.h>
#include <plat/gpmc.h>
#include <mach/hardware.h>
#include <plat/nand.h>
@@ -167,32 +167,15 @@ static void __init overo_display_init(void)
gpio_export(OVERO_GPIO_LCD_BL, 0);
}
-static int overo_panel_enable_dvi(struct omap_dss_device *dssdev)
-{
- if (lcd_enabled) {
- printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
- return -EINVAL;
- }
- dvi_enabled = 1;
-
- return 0;
-}
-
-static void overo_panel_disable_dvi(struct omap_dss_device *dssdev)
-{
- dvi_enabled = 0;
-}
-
-static struct panel_dvi_platform_data dvi_panel = {
- .platform_enable = overo_panel_enable_dvi,
- .platform_disable = overo_panel_disable_dvi,
+static struct tfp410_platform_data dvi_panel = {
.i2c_bus_num = 3,
+ .power_down_gpio = -1,
};
static struct omap_dss_device overo_dvi_device = {
.name = "dvi",
.type = OMAP_DISPLAY_TYPE_DPI,
- .driver_name = "dvi",
+ .driver_name = "tfp410",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index d87ee0612098..ff53deccecab 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -44,6 +44,7 @@
#include <linux/leds-lp5523.h>
#include <../drivers/staging/iio/light/tsl2563.h>
+#include <linux/lis3lv02d.h>
#include "mux.h"
#include "hsmmc.h"
@@ -63,6 +64,9 @@
#define RX51_TSC2005_RESET_GPIO 104
#define RX51_TSC2005_IRQ_GPIO 100
+#define LIS302_IRQ1_GPIO 181
+#define LIS302_IRQ2_GPIO 180 /* Not yet in use */
+
/* list all spi devices here */
enum {
RX51_SPI_WL1251,
@@ -73,6 +77,77 @@ enum {
static struct wl12xx_platform_data wl1251_pdata;
static struct tsc2005_platform_data tsc2005_pdata;
+#if defined(CONFIG_SENSORS_LIS3_I2C) || defined(CONFIG_SENSORS_LIS3_I2C_MODULE)
+static int lis302_setup(void)
+{
+ int err;
+ int irq1 = LIS302_IRQ1_GPIO;
+ int irq2 = LIS302_IRQ2_GPIO;
+
+ /* gpio for interrupt pin 1 */
+ err = gpio_request(irq1, "lis3lv02dl_irq1");
+ if (err) {
+ printk(KERN_ERR "lis3lv02dl: gpio request failed\n");
+ goto out;
+ }
+
+ /* gpio for interrupt pin 2 */
+ err = gpio_request(irq2, "lis3lv02dl_irq2");
+ if (err) {
+ gpio_free(irq1);
+ printk(KERN_ERR "lis3lv02dl: gpio request failed\n");
+ goto out;
+ }
+
+ gpio_direction_input(irq1);
+ gpio_direction_input(irq2);
+
+out:
+ return err;
+}
+
+static int lis302_release(void)
+{
+ gpio_free(LIS302_IRQ1_GPIO);
+ gpio_free(LIS302_IRQ2_GPIO);
+
+ return 0;
+}
+
+static struct lis3lv02d_platform_data rx51_lis3lv02d_data = {
+ .click_flags = LIS3_CLICK_SINGLE_X | LIS3_CLICK_SINGLE_Y |
+ LIS3_CLICK_SINGLE_Z,
+ /* Limits are 0.5g * value */
+ .click_thresh_x = 8,
+ .click_thresh_y = 8,
+ .click_thresh_z = 10,
+ /* Click must be longer than time limit */
+ .click_time_limit = 9,
+ /* Kind of debounce filter */
+ .click_latency = 50,
+
+ /* Limits for all axis. millig-value / 18 to get HW values */
+ .wakeup_flags = LIS3_WAKEUP_X_HI | LIS3_WAKEUP_Y_HI,
+ .wakeup_thresh = 800 / 18,
+ .wakeup_flags2 = LIS3_WAKEUP_Z_HI ,
+ .wakeup_thresh2 = 900 / 18,
+
+ .hipass_ctrl = LIS3_HIPASS1_DISABLE | LIS3_HIPASS2_DISABLE,
+
+ /* Interrupt line 2 for click detection, line 1 for thresholds */
+ .irq_cfg = LIS3_IRQ2_CLICK | LIS3_IRQ1_FF_WU_12,
+
+ .axis_x = LIS3_DEV_X,
+ .axis_y = LIS3_INV_DEV_Y,
+ .axis_z = LIS3_INV_DEV_Z,
+ .setup_resources = lis302_setup,
+ .release_resources = lis302_release,
+ .st_min_limits = {-32, 3, 3},
+ .st_max_limits = {-3, 32, 32},
+ .irq2 = OMAP_GPIO_IRQ(LIS302_IRQ2_GPIO),
+};
+#endif
+
#if defined(CONFIG_SENSORS_TSL2563) || defined(CONFIG_SENSORS_TSL2563_MODULE)
static struct tsl2563_platform_data rx51_tsl2563_platform_data = {
.cover_comp_gain = 16,
@@ -872,11 +947,11 @@ static struct twl4030_power_data rx51_t2scripts_data __initdata = {
.resource_config = twl4030_rconfig,
};
-struct twl4030_vibra_data rx51_vibra_data __initdata = {
+static struct twl4030_vibra_data rx51_vibra_data __initdata = {
.coexist = 0,
};
-struct twl4030_audio_data rx51_audio_data __initdata = {
+static struct twl4030_audio_data rx51_audio_data __initdata = {
.audio_mclk = 26000000,
.vibra = &rx51_vibra_data,
};
@@ -950,6 +1025,16 @@ static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = {
}
};
+static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_3[] = {
+#if defined(CONFIG_SENSORS_LIS3_I2C) || defined(CONFIG_SENSORS_LIS3_I2C_MODULE)
+ {
+ I2C_BOARD_INFO("lis3lv02d", 0x1d),
+ .platform_data = &rx51_lis3lv02d_data,
+ .irq = OMAP_GPIO_IRQ(LIS302_IRQ1_GPIO),
+ },
+#endif
+};
+
static int __init rx51_i2c_init(void)
{
if ((system_rev >= SYSTEM_REV_S_USES_VAUX3 && system_rev < 0x100) ||
@@ -971,7 +1056,8 @@ static int __init rx51_i2c_init(void)
omap_pmic_init(1, 2200, "twl5030", INT_34XX_SYS_NIRQ, &rx51_twldata);
omap_register_i2c_bus(2, 100, rx51_peripherals_i2c_board_info_2,
ARRAY_SIZE(rx51_peripherals_i2c_board_info_2));
- omap_register_i2c_bus(3, 400, NULL, 0);
+ omap_register_i2c_bus(3, 400, rx51_peripherals_i2c_board_info_3,
+ ARRAY_SIZE(rx51_peripherals_i2c_board_info_3));
return 0;
}
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index 27f01f051dff..2da92a6ba40a 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -59,25 +59,24 @@ static struct platform_device leds_gpio = {
};
/*
- * cpuidle C-states definition override from the default values.
- * The 'exit_latency' field is the sum of sleep and wake-up latencies.
- */
-static struct cpuidle_params rx51_cpuidle_params[] = {
- /* C1 */
- {110 + 162, 5 , 1},
- /* C2 */
- {106 + 180, 309, 1},
- /* C3 */
- {107 + 410, 46057, 0},
- /* C4 */
- {121 + 3374, 46057, 0},
- /* C5 */
- {855 + 1146, 46057, 1},
- /* C6 */
- {7580 + 4134, 484329, 0},
- /* C7 */
- {7505 + 15274, 484329, 1},
-};
+ * cpuidle C-states definition for rx51.
+ *
+ * The 'exit_latency' field is the sum of sleep
+ * and wake-up latencies.
+
+ ---------------------------------------------
+ | state | exit_latency | target_residency |
+ ---------------------------------------------
+ | C1 | 110 + 162 | 5 |
+ | C2 | 106 + 180 | 309 |
+ | C3 | 107 + 410 | 46057 |
+ | C4 | 121 + 3374 | 46057 |
+ | C5 | 855 + 1146 | 46057 |
+ | C6 | 7580 + 4134 | 484329 |
+ | C7 | 7505 + 15274 | 484329 |
+ ---------------------------------------------
+
+*/
extern void __init rx51_peripherals_init(void);
@@ -98,7 +97,6 @@ static void __init rx51_init(void)
struct omap_sdrc_params *sdrc_params;
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
- omap3_pm_init_cpuidle(rx51_cpuidle_params);
omap_serial_init();
sdrc_params = nokia_get_sdram_timings();
diff --git a/arch/arm/mach-omap2/board-zoom-display.c b/arch/arm/mach-omap2/board-zoom-display.c
index a43a765dd092..28187f134fff 100644
--- a/arch/arm/mach-omap2/board-zoom-display.c
+++ b/arch/arm/mach-omap2/board-zoom-display.c
@@ -16,6 +16,7 @@
#include <linux/spi/spi.h>
#include <plat/mcspi.h>
#include <video/omapdss.h>
+#include <mach/board-zoom.h>
#define LCD_PANEL_RESET_GPIO_PROD 96
#define LCD_PANEL_RESET_GPIO_PILOT 55
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index d9f4931513f9..5c4e66542169 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -439,7 +439,7 @@ void omap2_clk_disable_unused(struct clk *clk)
clk->ops->disable(clk);
}
if (clk->clkdm != NULL)
- pwrdm_clkdm_state_switch(clk->clkdm);
+ pwrdm_state_switch(clk->clkdm->pwrdm.ptr);
}
#endif
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index f4a626f7c79e..4e1a3b0e8cc8 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -1,7 +1,7 @@
/*
* OMAP3 clock data
*
- * Copyright (C) 2007-2010 Texas Instruments, Inc.
+ * Copyright (C) 2007-2010, 2012 Texas Instruments, Inc.
* Copyright (C) 2007-2011 Nokia Corporation
*
* Written by Paul Walmsley
@@ -1640,6 +1640,7 @@ static struct clk hdq_fck = {
.name = "hdq_fck",
.ops = &clkops_omap2_dflt_wait,
.parent = &core_12m_fck,
+ .clkdm_name = "core_l4_clkdm",
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
.enable_bit = OMAP3430_EN_HDQ_SHIFT,
.recalc = &followparent_recalc,
@@ -3294,8 +3295,8 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "gfx_l3_ick", &gfx_l3_ick, CK_3430ES1),
CLK(NULL, "gfx_cg1_ck", &gfx_cg1_ck, CK_3430ES1),
CLK(NULL, "gfx_cg2_ck", &gfx_cg2_ck, CK_3430ES1),
- CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2PLUS | CK_3517 | CK_36XX),
- CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2PLUS | CK_3517 | CK_36XX),
+ CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK(NULL, "d2d_26m_fck", &d2d_26m_fck, CK_3430ES1),
CLK(NULL, "modem_fck", &modem_fck, CK_34XX | CK_36XX),
CLK(NULL, "sad2d_ick", &sad2d_ick, CK_34XX | CK_36XX),
@@ -3419,7 +3420,7 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "per_48m_fck", &per_48m_fck, CK_3XXX),
CLK(NULL, "uart3_fck", &uart3_fck, CK_3XXX),
CLK(NULL, "uart4_fck", &uart4_fck, CK_36XX),
- CLK(NULL, "uart4_fck", &uart4_fck_am35xx, CK_3505 | CK_3517),
+ CLK(NULL, "uart4_fck", &uart4_fck_am35xx, CK_AM35XX),
CLK(NULL, "gpt2_fck", &gpt2_fck, CK_3XXX),
CLK(NULL, "gpt3_fck", &gpt3_fck, CK_3XXX),
CLK(NULL, "gpt4_fck", &gpt4_fck, CK_3XXX),
@@ -3513,21 +3514,9 @@ int __init omap3xxx_clk_init(void)
struct omap_clk *c;
u32 cpu_clkflg = 0;
- /*
- * 3505 must be tested before 3517, since 3517 returns true
- * for both AM3517 chips and AM3517 family chips, which
- * includes 3505. Unfortunately there's no obvious family
- * test for 3517/3505 :-(
- */
- if (cpu_is_omap3505()) {
- cpu_mask = RATE_IN_34XX;
- cpu_clkflg = CK_3505;
- } else if (cpu_is_omap3517()) {
- cpu_mask = RATE_IN_34XX;
- cpu_clkflg = CK_3517;
- } else if (cpu_is_omap3505()) {
+ if (cpu_is_omap3517()) {
cpu_mask = RATE_IN_34XX;
- cpu_clkflg = CK_3505;
+ cpu_clkflg = CK_AM35XX;
} else if (cpu_is_omap3630()) {
cpu_mask = (RATE_IN_34XX | RATE_IN_36XX);
cpu_clkflg = CK_36XX;
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index fa6ea65ad44b..2172f6603848 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3355,17 +3355,6 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "auxclk5_ck", &auxclk5_ck, CK_443X),
CLK(NULL, "auxclkreq5_ck", &auxclkreq5_ck, CK_443X),
CLK(NULL, "gpmc_ck", &dummy_ck, CK_443X),
- CLK(NULL, "gpt1_ick", &dummy_ck, CK_443X),
- CLK(NULL, "gpt2_ick", &dummy_ck, CK_443X),
- CLK(NULL, "gpt3_ick", &dummy_ck, CK_443X),
- CLK(NULL, "gpt4_ick", &dummy_ck, CK_443X),
- CLK(NULL, "gpt5_ick", &dummy_ck, CK_443X),
- CLK(NULL, "gpt6_ick", &dummy_ck, CK_443X),
- CLK(NULL, "gpt7_ick", &dummy_ck, CK_443X),
- CLK(NULL, "gpt8_ick", &dummy_ck, CK_443X),
- CLK(NULL, "gpt9_ick", &dummy_ck, CK_443X),
- CLK(NULL, "gpt10_ick", &dummy_ck, CK_443X),
- CLK(NULL, "gpt11_ick", &dummy_ck, CK_443X),
CLK("omap_i2c.1", "ick", &dummy_ck, CK_443X),
CLK("omap_i2c.2", "ick", &dummy_ck, CK_443X),
CLK("omap_i2c.3", "ick", &dummy_ck, CK_443X),
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index ad07689e1563..8664f5a8bfb6 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -840,7 +840,7 @@ void clkdm_allow_idle(struct clockdomain *clkdm)
spin_lock_irqsave(&clkdm->lock, flags);
clkdm->_flags |= _CLKDM_FLAG_HWSUP_ENABLED;
arch_clkdm->clkdm_allow_idle(clkdm);
- pwrdm_clkdm_state_switch(clkdm);
+ pwrdm_state_switch(clkdm->pwrdm.ptr);
spin_unlock_irqrestore(&clkdm->lock, flags);
}
@@ -924,8 +924,7 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
spin_lock_irqsave(&clkdm->lock, flags);
arch_clkdm->clkdm_clk_enable(clkdm);
- pwrdm_wait_transition(clkdm->pwrdm.ptr);
- pwrdm_clkdm_state_switch(clkdm);
+ pwrdm_state_switch(clkdm->pwrdm.ptr);
spin_unlock_irqrestore(&clkdm->lock, flags);
pr_debug("clockdomain: clkdm %s: enabled\n", clkdm->name);
@@ -950,7 +949,7 @@ static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
spin_lock_irqsave(&clkdm->lock, flags);
arch_clkdm->clkdm_clk_disable(clkdm);
- pwrdm_clkdm_state_switch(clkdm);
+ pwrdm_state_switch(clkdm->pwrdm.ptr);
spin_unlock_irqrestore(&clkdm->lock, flags);
pr_debug("clockdomain: clkdm %s: disabled\n", clkdm->name);
diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
index 935c7f03dab9..4f04dd11d655 100644
--- a/arch/arm/mach-omap2/clockdomain44xx.c
+++ b/arch/arm/mach-omap2/clockdomain44xx.c
@@ -51,6 +51,9 @@ static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
struct clkdm_dep *cd;
u32 mask = 0;
+ if (!clkdm->prcm_partition)
+ return 0;
+
for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
if (!cd->clkdm)
continue; /* only happens if data is erroneous */
@@ -103,6 +106,9 @@ static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
{
bool hwsup = false;
+ if (!clkdm->prcm_partition)
+ return 0;
+
hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
clkdm->cm_inst, clkdm->clkdm_offs);
diff --git a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
index 0a6a04897d89..839145e1cfbe 100644
--- a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
+++ b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
@@ -89,13 +89,3 @@ struct clockdomain wkup_common_clkdm = {
.pwrdm = { .name = "wkup_pwrdm" },
.dep_bit = OMAP_EN_WKUP_SHIFT,
};
-
-struct clockdomain prm_common_clkdm = {
- .name = "prm_clkdm",
- .pwrdm = { .name = "wkup_pwrdm" },
-};
-
-struct clockdomain cm_common_clkdm = {
- .name = "cm_clkdm",
- .pwrdm = { .name = "core_pwrdm" },
-};
diff --git a/arch/arm/mach-omap2/clockdomains3xxx_data.c b/arch/arm/mach-omap2/clockdomains3xxx_data.c
index b84e138d99c8..6038adb97710 100644
--- a/arch/arm/mach-omap2/clockdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/clockdomains3xxx_data.c
@@ -53,9 +53,9 @@
* 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
*/
static struct clkdm_dep gfx_sgx_3xxx_wkdeps[] = {
- { .clkdm_name = "iva2_clkdm", },
- { .clkdm_name = "mpu_clkdm", },
- { .clkdm_name = "wkup_clkdm", },
+ { .clkdm_name = "iva2_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
{ NULL },
};
diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c
index bd7ed13515cc..c53425847493 100644
--- a/arch/arm/mach-omap2/clockdomains44xx_data.c
+++ b/arch/arm/mach-omap2/clockdomains44xx_data.c
@@ -430,6 +430,8 @@ static struct clockdomain *clockdomains_omap44xx[] __initdata = {
&l4_wkup_44xx_clkdm,
&emu_sys_44xx_clkdm,
&l3_dma_44xx_clkdm,
+ &prm_common_clkdm,
+ &cm_common_clkdm,
NULL
};
diff --git a/arch/arm/mach-omap2/clockdomains_common_data.c b/arch/arm/mach-omap2/clockdomains_common_data.c
new file mode 100644
index 000000000000..615b1f04967d
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomains_common_data.c
@@ -0,0 +1,24 @@
+/*
+ * OMAP2+-common clockdomain data
+ *
+ * Copyright (C) 2008-2012 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni Högander
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+
+/* These are implicit clockdomains - they are never defined as such in TRM */
+struct clockdomain prm_common_clkdm = {
+ .name = "prm_clkdm",
+ .pwrdm = { .name = "wkup_pwrdm" },
+};
+
+struct clockdomain cm_common_clkdm = {
+ .name = "cm_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+};
diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h
index b91275908f33..8083a8cdc55f 100644
--- a/arch/arm/mach-omap2/cm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
@@ -79,7 +79,7 @@
/* CM_CLKSEL1_PLL_IVA2 */
#define OMAP3430_IVA2_CLK_SRC_SHIFT 19
-#define OMAP3430_IVA2_CLK_SRC_MASK (0x3 << 19)
+#define OMAP3430_IVA2_CLK_SRC_MASK (0x7 << 19)
#define OMAP3430_IVA2_DPLL_MULT_SHIFT 8
#define OMAP3430_IVA2_DPLL_MULT_MASK (0x7ff << 8)
#define OMAP3430_IVA2_DPLL_DIV_SHIFT 0
@@ -124,7 +124,7 @@
/* CM_CLKSEL1_PLL_MPU */
#define OMAP3430_MPU_CLK_SRC_SHIFT 19
-#define OMAP3430_MPU_CLK_SRC_MASK (0x3 << 19)
+#define OMAP3430_MPU_CLK_SRC_MASK (0x7 << 19)
#define OMAP3430_MPU_DPLL_MULT_SHIFT 8
#define OMAP3430_MPU_DPLL_MULT_MASK (0x7ff << 8)
#define OMAP3430_MPU_DPLL_DIV_SHIFT 0
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c
index bd8810c3753f..8c86d294b1a3 100644
--- a/arch/arm/mach-omap2/cminst44xx.c
+++ b/arch/arm/mach-omap2/cminst44xx.c
@@ -32,6 +32,7 @@
#include "prcm44xx.h"
#include "prm44xx.h"
#include "prcm_mpu44xx.h"
+#include "prcm-common.h"
/*
* CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield:
@@ -49,14 +50,21 @@
#define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2
#define CLKCTRL_IDLEST_DISABLED 0x3
-static u32 _cm_bases[OMAP4_MAX_PRCM_PARTITIONS] = {
- [OMAP4430_INVALID_PRCM_PARTITION] = 0,
- [OMAP4430_PRM_PARTITION] = OMAP4430_PRM_BASE,
- [OMAP4430_CM1_PARTITION] = OMAP4430_CM1_BASE,
- [OMAP4430_CM2_PARTITION] = OMAP4430_CM2_BASE,
- [OMAP4430_SCRM_PARTITION] = 0,
- [OMAP4430_PRCM_MPU_PARTITION] = OMAP4430_PRCM_MPU_BASE,
-};
+static void __iomem *_cm_bases[OMAP4_MAX_PRCM_PARTITIONS];
+
+/**
+ * omap_cm_base_init - Populates the cm partitions
+ *
+ * Populates the base addresses of the _cm_bases
+ * array used for read/write of cm module registers.
+ */
+void omap_cm_base_init(void)
+{
+ _cm_bases[OMAP4430_PRM_PARTITION] = prm_base;
+ _cm_bases[OMAP4430_CM1_PARTITION] = cm_base;
+ _cm_bases[OMAP4430_CM2_PARTITION] = cm2_base;
+ _cm_bases[OMAP4430_PRCM_MPU_PARTITION] = prcm_mpu_base;
+}
/* Private functions */
@@ -106,7 +114,7 @@ u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx)
BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
part == OMAP4430_INVALID_PRCM_PARTITION ||
!_cm_bases[part]);
- return __raw_readl(OMAP2_L4_IO_ADDRESS(_cm_bases[part] + inst + idx));
+ return __raw_readl(_cm_bases[part] + inst + idx);
}
/* Write into a register in a CM instance */
@@ -115,7 +123,7 @@ void omap4_cminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx)
BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
part == OMAP4430_INVALID_PRCM_PARTITION ||
!_cm_bases[part]);
- __raw_writel(val, OMAP2_L4_IO_ADDRESS(_cm_bases[part] + inst + idx));
+ __raw_writel(val, _cm_bases[part] + inst + idx);
}
/* Read-modify-write a register in CM1. Caller must lock */
diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
index 1549c11000d3..8a6953a34fe2 100644
--- a/arch/arm/mach-omap2/common.c
+++ b/arch/arm/mach-omap2/common.c
@@ -166,6 +166,7 @@ static struct omap_globals omap4_globals = {
.prm = OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE),
.cm = OMAP2_L4_IO_ADDRESS(OMAP4430_CM_BASE),
.cm2 = OMAP2_L4_IO_ADDRESS(OMAP4430_CM2_BASE),
+ .prcm_mpu = OMAP2_L4_IO_ADDRESS(OMAP4430_PRCM_MPU_BASE),
};
void __init omap2_set_globals_443x(void)
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 57da7f406e28..d6c9e6180318 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -27,6 +27,7 @@
#ifndef __ASSEMBLER__
#include <linux/delay.h>
+#include <linux/i2c/twl.h>
#include <plat/common.h>
#include <asm/proc-fns.h>
@@ -111,6 +112,7 @@ struct omap_globals {
void __iomem *prm; /* Power and Reset Management */
void __iomem *cm; /* Clock Management */
void __iomem *cm2;
+ void __iomem *prcm_mpu;
};
void omap2_set_globals_242x(void);
@@ -134,8 +136,6 @@ void omap4_map_io(void);
void ti81xx_map_io(void);
void omap_barriers_init(void);
-extern void __init omap_init_consistent_dma_size(void);
-
/**
* omap_test_timeout - busy-loop, testing a condition
* @cond: condition to test until it evaluates to true
@@ -254,6 +254,8 @@ static inline u32 omap4_mpuss_read_prev_context_state(void)
struct omap_sdrc_params;
extern void omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
struct omap_sdrc_params *sdrc_cs1);
+struct omap2_hsmmc_info;
+extern int omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers);
#endif /* __ASSEMBLER__ */
#endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 535866489ce3..207bc1c7759f 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -38,40 +38,44 @@
#ifdef CONFIG_CPU_IDLE
-/*
- * The latencies/thresholds for various C states have
- * to be configured from the respective board files.
- * These are some default values (which might not provide
- * the best power savings) used on boards which do not
- * pass these details from the board file.
- */
-static struct cpuidle_params cpuidle_params_table[] = {
- /* C1 */
- {2 + 2, 5, 1},
- /* C2 */
- {10 + 10, 30, 1},
- /* C3 */
- {50 + 50, 300, 1},
- /* C4 */
- {1500 + 1800, 4000, 1},
- /* C5 */
- {2500 + 7500, 12000, 1},
- /* C6 */
- {3000 + 8500, 15000, 1},
- /* C7 */
- {10000 + 30000, 300000, 1},
-};
-#define OMAP3_NUM_STATES ARRAY_SIZE(cpuidle_params_table)
-
/* Mach specific information to be recorded in the C-state driver_data */
struct omap3_idle_statedata {
u32 mpu_state;
u32 core_state;
- u8 valid;
};
-struct omap3_idle_statedata omap3_idle_data[OMAP3_NUM_STATES];
-struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
+static struct omap3_idle_statedata omap3_idle_data[] = {
+ {
+ .mpu_state = PWRDM_POWER_ON,
+ .core_state = PWRDM_POWER_ON,
+ },
+ {
+ .mpu_state = PWRDM_POWER_ON,
+ .core_state = PWRDM_POWER_ON,
+ },
+ {
+ .mpu_state = PWRDM_POWER_RET,
+ .core_state = PWRDM_POWER_ON,
+ },
+ {
+ .mpu_state = PWRDM_POWER_OFF,
+ .core_state = PWRDM_POWER_ON,
+ },
+ {
+ .mpu_state = PWRDM_POWER_RET,
+ .core_state = PWRDM_POWER_RET,
+ },
+ {
+ .mpu_state = PWRDM_POWER_OFF,
+ .core_state = PWRDM_POWER_RET,
+ },
+ {
+ .mpu_state = PWRDM_POWER_OFF,
+ .core_state = PWRDM_POWER_OFF,
+ },
+};
+
+static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
struct clockdomain *clkdm)
@@ -91,8 +95,7 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
- struct omap3_idle_statedata *cx =
- cpuidle_get_statedata(&dev->states_usage[index]);
+ struct omap3_idle_statedata *cx = &omap3_idle_data[index];
u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
local_fiq_disable();
@@ -169,14 +172,12 @@ static inline int omap3_enter_idle(struct cpuidle_device *dev,
* if it satisfies the enable_off_mode condition.
*/
static int next_valid_state(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
+ struct cpuidle_driver *drv, int index)
{
- struct cpuidle_state_usage *curr_usage = &dev->states_usage[index];
- struct cpuidle_state *curr = &drv->states[index];
- struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
+ struct omap3_idle_statedata *cx = &omap3_idle_data[index];
u32 mpu_deepest_state = PWRDM_POWER_RET;
u32 core_deepest_state = PWRDM_POWER_RET;
+ int idx;
int next_index = -1;
if (enable_off_mode) {
@@ -191,45 +192,29 @@ static int next_valid_state(struct cpuidle_device *dev,
}
/* Check if current state is valid */
- if ((cx->valid) &&
- (cx->mpu_state >= mpu_deepest_state) &&
- (cx->core_state >= core_deepest_state)) {
+ if ((cx->mpu_state >= mpu_deepest_state) &&
+ (cx->core_state >= core_deepest_state))
return index;
- } else {
- int idx = OMAP3_NUM_STATES - 1;
-
- /* Reach the current state starting at highest C-state */
- for (; idx >= 0; idx--) {
- if (&drv->states[idx] == curr) {
- next_index = idx;
- break;
- }
- }
-
- /* Should never hit this condition */
- WARN_ON(next_index == -1);
- /*
- * Drop to next valid state.
- * Start search from the next (lower) state.
- */
- idx--;
- for (; idx >= 0; idx--) {
- cx = cpuidle_get_statedata(&dev->states_usage[idx]);
- if ((cx->valid) &&
- (cx->mpu_state >= mpu_deepest_state) &&
- (cx->core_state >= core_deepest_state)) {
- next_index = idx;
- break;
- }
+ /*
+ * Drop to next valid state.
+ * Start search from the next (lower) state.
+ */
+ for (idx = index - 1; idx >= 0; idx--) {
+ cx = &omap3_idle_data[idx];
+ if ((cx->mpu_state >= mpu_deepest_state) &&
+ (cx->core_state >= core_deepest_state)) {
+ next_index = idx;
+ break;
}
- /*
- * C1 is always valid.
- * So, no need to check for 'next_index == -1' outside
- * this loop.
- */
}
+ /*
+ * C1 is always valid.
+ * So, no need to check for 'next_index == -1' outside
+ * this loop.
+ */
+
return next_index;
}
@@ -273,7 +258,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
* Prevent PER off if CORE is not in retention or off as this
* would disable PER wakeups completely.
*/
- cx = cpuidle_get_statedata(&dev->states_usage[index]);
+ cx = &omap3_idle_data[index];
core_next_state = cx->core_state;
per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
if ((per_next_state == PWRDM_POWER_OFF) &&
@@ -298,57 +283,71 @@ select_state:
DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
-void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params)
-{
- int i;
-
- if (!cpuidle_board_params)
- return;
-
- for (i = 0; i < OMAP3_NUM_STATES; i++) {
- cpuidle_params_table[i].valid = cpuidle_board_params[i].valid;
- cpuidle_params_table[i].exit_latency =
- cpuidle_board_params[i].exit_latency;
- cpuidle_params_table[i].target_residency =
- cpuidle_board_params[i].target_residency;
- }
- return;
-}
-
struct cpuidle_driver omap3_idle_driver = {
.name = "omap3_idle",
.owner = THIS_MODULE,
+ .states = {
+ {
+ .enter = omap3_enter_idle,
+ .exit_latency = 2 + 2,
+ .target_residency = 5,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "C1",
+ .desc = "MPU ON + CORE ON",
+ },
+ {
+ .enter = omap3_enter_idle_bm,
+ .exit_latency = 10 + 10,
+ .target_residency = 30,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "C2",
+ .desc = "MPU ON + CORE ON",
+ },
+ {
+ .enter = omap3_enter_idle_bm,
+ .exit_latency = 50 + 50,
+ .target_residency = 300,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "C3",
+ .desc = "MPU RET + CORE ON",
+ },
+ {
+ .enter = omap3_enter_idle_bm,
+ .exit_latency = 1500 + 1800,
+ .target_residency = 4000,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "C4",
+ .desc = "MPU OFF + CORE ON",
+ },
+ {
+ .enter = omap3_enter_idle_bm,
+ .exit_latency = 2500 + 7500,
+ .target_residency = 12000,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "C5",
+ .desc = "MPU RET + CORE RET",
+ },
+ {
+ .enter = omap3_enter_idle_bm,
+ .exit_latency = 3000 + 8500,
+ .target_residency = 15000,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "C6",
+ .desc = "MPU OFF + CORE RET",
+ },
+ {
+ .enter = omap3_enter_idle_bm,
+ .exit_latency = 10000 + 30000,
+ .target_residency = 30000,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "C7",
+ .desc = "MPU OFF + CORE OFF",
+ },
+ },
+ .state_count = ARRAY_SIZE(omap3_idle_data),
+ .safe_state_index = 0,
};
-/* Helper to fill the C-state common data*/
-static inline void _fill_cstate(struct cpuidle_driver *drv,
- int idx, const char *descr)
-{
- struct cpuidle_state *state = &drv->states[idx];
-
- state->exit_latency = cpuidle_params_table[idx].exit_latency;
- state->target_residency = cpuidle_params_table[idx].target_residency;
- state->flags = CPUIDLE_FLAG_TIME_VALID;
- state->enter = omap3_enter_idle_bm;
- sprintf(state->name, "C%d", idx + 1);
- strncpy(state->desc, descr, CPUIDLE_DESC_LEN);
-
-}
-
-/* Helper to register the driver_data */
-static inline struct omap3_idle_statedata *_fill_cstate_usage(
- struct cpuidle_device *dev,
- int idx)
-{
- struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
- struct cpuidle_state_usage *state_usage = &dev->states_usage[idx];
-
- cx->valid = cpuidle_params_table[idx].valid;
- cpuidle_set_statedata(state_usage, cx);
-
- return cx;
-}
-
/**
* omap3_idle_init - Init routine for OMAP3 idle
*
@@ -358,77 +357,20 @@ static inline struct omap3_idle_statedata *_fill_cstate_usage(
int __init omap3_idle_init(void)
{
struct cpuidle_device *dev;
- struct cpuidle_driver *drv = &omap3_idle_driver;
- struct omap3_idle_statedata *cx;
mpu_pd = pwrdm_lookup("mpu_pwrdm");
core_pd = pwrdm_lookup("core_pwrdm");
per_pd = pwrdm_lookup("per_pwrdm");
cam_pd = pwrdm_lookup("cam_pwrdm");
+ if (!mpu_pd || !core_pd || !per_pd || !cam_pd)
+ return -ENODEV;
- drv->safe_state_index = -1;
- dev = &per_cpu(omap3_idle_dev, smp_processor_id());
-
- /* C1 . MPU WFI + Core active */
- _fill_cstate(drv, 0, "MPU ON + CORE ON");
- (&drv->states[0])->enter = omap3_enter_idle;
- drv->safe_state_index = 0;
- cx = _fill_cstate_usage(dev, 0);
- cx->valid = 1; /* C1 is always valid */
- cx->mpu_state = PWRDM_POWER_ON;
- cx->core_state = PWRDM_POWER_ON;
-
- /* C2 . MPU WFI + Core inactive */
- _fill_cstate(drv, 1, "MPU ON + CORE ON");
- cx = _fill_cstate_usage(dev, 1);
- cx->mpu_state = PWRDM_POWER_ON;
- cx->core_state = PWRDM_POWER_ON;
-
- /* C3 . MPU CSWR + Core inactive */
- _fill_cstate(drv, 2, "MPU RET + CORE ON");
- cx = _fill_cstate_usage(dev, 2);
- cx->mpu_state = PWRDM_POWER_RET;
- cx->core_state = PWRDM_POWER_ON;
-
- /* C4 . MPU OFF + Core inactive */
- _fill_cstate(drv, 3, "MPU OFF + CORE ON");
- cx = _fill_cstate_usage(dev, 3);
- cx->mpu_state = PWRDM_POWER_OFF;
- cx->core_state = PWRDM_POWER_ON;
-
- /* C5 . MPU RET + Core RET */
- _fill_cstate(drv, 4, "MPU RET + CORE RET");
- cx = _fill_cstate_usage(dev, 4);
- cx->mpu_state = PWRDM_POWER_RET;
- cx->core_state = PWRDM_POWER_RET;
-
- /* C6 . MPU OFF + Core RET */
- _fill_cstate(drv, 5, "MPU OFF + CORE RET");
- cx = _fill_cstate_usage(dev, 5);
- cx->mpu_state = PWRDM_POWER_OFF;
- cx->core_state = PWRDM_POWER_RET;
-
- /* C7 . MPU OFF + Core OFF */
- _fill_cstate(drv, 6, "MPU OFF + CORE OFF");
- cx = _fill_cstate_usage(dev, 6);
- /*
- * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
- * enable OFF mode in a stable form for previous revisions.
- * We disable C7 state as a result.
- */
- if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) {
- cx->valid = 0;
- pr_warn("%s: core off state C7 disabled due to i583\n",
- __func__);
- }
- cx->mpu_state = PWRDM_POWER_OFF;
- cx->core_state = PWRDM_POWER_OFF;
-
- drv->state_count = OMAP3_NUM_STATES;
cpuidle_register_driver(&omap3_idle_driver);
- dev->state_count = OMAP3_NUM_STATES;
+ dev = &per_cpu(omap3_idle_dev, smp_processor_id());
+ dev->cpu = 0;
+
if (cpuidle_register_device(dev)) {
printk(KERN_ERR "%s: CPUidle register device failed\n",
__func__);
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index f386cbe9c889..be1617ca84bd 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -24,26 +24,31 @@
#ifdef CONFIG_CPU_IDLE
-/* Machine specific information to be recorded in the C-state driver_data */
+/* Machine specific information */
struct omap4_idle_statedata {
u32 cpu_state;
u32 mpu_logic_state;
u32 mpu_state;
- u8 valid;
};
-static struct cpuidle_params cpuidle_params_table[] = {
- /* C1 - CPU0 ON + CPU1 ON + MPU ON */
- {.exit_latency = 2 + 2 , .target_residency = 5, .valid = 1},
- /* C2- CPU0 OFF + CPU1 OFF + MPU CSWR */
- {.exit_latency = 328 + 440 , .target_residency = 960, .valid = 1},
- /* C3 - CPU0 OFF + CPU1 OFF + MPU OSWR */
- {.exit_latency = 460 + 518 , .target_residency = 1100, .valid = 1},
+static struct omap4_idle_statedata omap4_idle_data[] = {
+ {
+ .cpu_state = PWRDM_POWER_ON,
+ .mpu_state = PWRDM_POWER_ON,
+ .mpu_logic_state = PWRDM_POWER_RET,
+ },
+ {
+ .cpu_state = PWRDM_POWER_OFF,
+ .mpu_state = PWRDM_POWER_RET,
+ .mpu_logic_state = PWRDM_POWER_RET,
+ },
+ {
+ .cpu_state = PWRDM_POWER_OFF,
+ .mpu_state = PWRDM_POWER_RET,
+ .mpu_logic_state = PWRDM_POWER_OFF,
+ },
};
-#define OMAP4_NUM_STATES ARRAY_SIZE(cpuidle_params_table)
-
-struct omap4_idle_statedata omap4_idle_data[OMAP4_NUM_STATES];
static struct powerdomain *mpu_pd, *cpu0_pd, *cpu1_pd;
/**
@@ -60,8 +65,7 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
- struct omap4_idle_statedata *cx =
- cpuidle_get_statedata(&dev->states_usage[index]);
+ struct omap4_idle_statedata *cx = &omap4_idle_data[index];
u32 cpu1_state;
int cpu_id = smp_processor_id();
@@ -78,7 +82,7 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
cpu1_state = pwrdm_read_pwrst(cpu1_pd);
if (cpu1_state != PWRDM_POWER_OFF) {
index = drv->safe_state_index;
- cx = cpuidle_get_statedata(&dev->states_usage[index]);
+ cx = &omap4_idle_data[index];
}
if (index > 0)
@@ -133,36 +137,39 @@ struct cpuidle_driver omap4_idle_driver = {
.name = "omap4_idle",
.owner = THIS_MODULE,
.en_core_tk_irqen = 1,
+ .states = {
+ {
+ /* C1 - CPU0 ON + CPU1 ON + MPU ON */
+ .exit_latency = 2 + 2,
+ .target_residency = 5,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .enter = omap4_enter_idle,
+ .name = "C1",
+ .desc = "MPUSS ON"
+ },
+ {
+ /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */
+ .exit_latency = 328 + 440,
+ .target_residency = 960,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .enter = omap4_enter_idle,
+ .name = "C2",
+ .desc = "MPUSS CSWR",
+ },
+ {
+ /* C3 - CPU0 OFF + CPU1 OFF + MPU OSWR */
+ .exit_latency = 460 + 518,
+ .target_residency = 1100,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .enter = omap4_enter_idle,
+ .name = "C3",
+ .desc = "MPUSS OSWR",
+ },
+ },
+ .state_count = ARRAY_SIZE(omap4_idle_data),
+ .safe_state_index = 0,
};
-static inline void _fill_cstate(struct cpuidle_driver *drv,
- int idx, const char *descr)
-{
- struct cpuidle_state *state = &drv->states[idx];
-
- state->exit_latency = cpuidle_params_table[idx].exit_latency;
- state->target_residency = cpuidle_params_table[idx].target_residency;
- state->flags = CPUIDLE_FLAG_TIME_VALID;
- state->enter = omap4_enter_idle;
- sprintf(state->name, "C%d", idx + 1);
- strncpy(state->desc, descr, CPUIDLE_DESC_LEN);
-}
-
-static inline struct omap4_idle_statedata *_fill_cstate_usage(
- struct cpuidle_device *dev,
- int idx)
-{
- struct omap4_idle_statedata *cx = &omap4_idle_data[idx];
- struct cpuidle_state_usage *state_usage = &dev->states_usage[idx];
-
- cx->valid = cpuidle_params_table[idx].valid;
- cpuidle_set_statedata(state_usage, cx);
-
- return cx;
-}
-
-
-
/**
* omap4_idle_init - Init routine for OMAP4 idle
*
@@ -171,9 +178,7 @@ static inline struct omap4_idle_statedata *_fill_cstate_usage(
*/
int __init omap4_idle_init(void)
{
- struct omap4_idle_statedata *cx;
struct cpuidle_device *dev;
- struct cpuidle_driver *drv = &omap4_idle_driver;
unsigned int cpu_id = 0;
mpu_pd = pwrdm_lookup("mpu_pwrdm");
@@ -182,42 +187,15 @@ int __init omap4_idle_init(void)
if ((!mpu_pd) || (!cpu0_pd) || (!cpu1_pd))
return -ENODEV;
-
- drv->safe_state_index = -1;
dev = &per_cpu(omap4_idle_dev, cpu_id);
dev->cpu = cpu_id;
- /* C1 - CPU0 ON + CPU1 ON + MPU ON */
- _fill_cstate(drv, 0, "MPUSS ON");
- drv->safe_state_index = 0;
- cx = _fill_cstate_usage(dev, 0);
- cx->valid = 1; /* C1 is always valid */
- cx->cpu_state = PWRDM_POWER_ON;
- cx->mpu_state = PWRDM_POWER_ON;
- cx->mpu_logic_state = PWRDM_POWER_RET;
-
- /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */
- _fill_cstate(drv, 1, "MPUSS CSWR");
- cx = _fill_cstate_usage(dev, 1);
- cx->cpu_state = PWRDM_POWER_OFF;
- cx->mpu_state = PWRDM_POWER_RET;
- cx->mpu_logic_state = PWRDM_POWER_RET;
-
- /* C3 - CPU0 OFF + CPU1 OFF + MPU OSWR */
- _fill_cstate(drv, 2, "MPUSS OSWR");
- cx = _fill_cstate_usage(dev, 2);
- cx->cpu_state = PWRDM_POWER_OFF;
- cx->mpu_state = PWRDM_POWER_RET;
- cx->mpu_logic_state = PWRDM_POWER_OFF;
-
- drv->state_count = OMAP4_NUM_STATES;
cpuidle_register_driver(&omap4_idle_driver);
- dev->state_count = OMAP4_NUM_STATES;
if (cpuidle_register_device(dev)) {
pr_err("%s: CPUidle register device failed\n", __func__);
- return -EIO;
- }
+ return -EIO;
+ }
return 0;
}
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index e4336035c0ea..ae62ece04ef9 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -42,7 +42,6 @@
static int __init omap3_l3_init(void)
{
- int l;
struct omap_hwmod *oh;
struct platform_device *pdev;
char oh_name[L3_MODULES_MAX_LEN];
@@ -54,7 +53,7 @@ static int __init omap3_l3_init(void)
if (!(cpu_is_omap34xx()))
return -ENODEV;
- l = snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main");
+ snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main");
oh = omap_hwmod_lookup(oh_name);
@@ -72,7 +71,7 @@ postcore_initcall(omap3_l3_init);
static int __init omap4_l3_init(void)
{
- int l, i;
+ int i;
struct omap_hwmod *oh[3];
struct platform_device *pdev;
char oh_name[L3_MODULES_MAX_LEN];
@@ -89,7 +88,7 @@ static int __init omap4_l3_init(void)
return -ENODEV;
for (i = 0; i < L3_MODULES; i++) {
- l = snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main_%d", i+1);
+ snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main_%d", i+1);
oh[i] = omap_hwmod_lookup(oh_name);
if (!(oh[i]))
@@ -355,6 +354,36 @@ static void __init omap_init_dmic(void)
static inline void omap_init_dmic(void) {}
#endif
+#if defined(CONFIG_SND_OMAP_SOC_OMAP_HDMI) || \
+ defined(CONFIG_SND_OMAP_SOC_OMAP_HDMI_MODULE)
+
+static struct platform_device omap_hdmi_audio = {
+ .name = "omap-hdmi-audio",
+ .id = -1,
+};
+
+static void __init omap_init_hdmi_audio(void)
+{
+ struct omap_hwmod *oh;
+ struct platform_device *pdev;
+
+ oh = omap_hwmod_lookup("dss_hdmi");
+ if (!oh) {
+ printk(KERN_ERR "Could not look up dss_hdmi hw_mod\n");
+ return;
+ }
+
+ pdev = omap_device_build("omap-hdmi-audio-dai",
+ -1, oh, NULL, 0, NULL, 0, 0);
+ WARN(IS_ERR(pdev),
+ "Can't build omap_device for omap-hdmi-audio-dai.\n");
+
+ platform_device_register(&omap_hdmi_audio);
+}
+#else
+static inline void omap_init_hdmi_audio(void) {}
+#endif
+
#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
#include <plat/mcspi.h>
@@ -701,11 +730,15 @@ static int __init omap2_init_devices(void)
* in alphabetical order so they're easier to sort through.
*/
omap_init_audio();
- omap_init_mcpdm();
- omap_init_dmic();
omap_init_camera();
+ omap_init_hdmi_audio();
omap_init_mbox();
- omap_init_mcspi();
+ /* If dtb is there, the devices will be created dynamically */
+ if (!of_have_populated_dt()) {
+ omap_init_dmic();
+ omap_init_mcpdm();
+ omap_init_mcspi();
+ }
omap_init_pmu();
omap_hdq_init();
omap_init_sti();
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index fc56745676fa..f0f10beeffe8 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -142,7 +142,8 @@ static int _omap3_noncore_dpll_lock(struct clk *clk)
ai = omap3_dpll_autoidle_read(clk);
- omap3_dpll_deny_idle(clk);
+ if (ai)
+ omap3_dpll_deny_idle(clk);
_omap3_dpll_write_clken(clk, DPLL_LOCKED);
@@ -186,8 +187,6 @@ static int _omap3_noncore_dpll_bypass(struct clk *clk)
if (ai)
omap3_dpll_allow_idle(clk);
- else
- omap3_dpll_deny_idle(clk);
return r;
}
@@ -216,8 +215,6 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
if (ai)
omap3_dpll_allow_idle(clk);
- else
- omap3_dpll_deny_idle(clk);
return 0;
}
@@ -519,6 +516,9 @@ u32 omap3_dpll_autoidle_read(struct clk *clk)
dd = clk->dpll_data;
+ if (!dd->autoidle_reg)
+ return -EINVAL;
+
v = __raw_readl(dd->autoidle_reg);
v &= dd->autoidle_mask;
v >>= __ffs(dd->autoidle_mask);
@@ -545,6 +545,12 @@ void omap3_dpll_allow_idle(struct clk *clk)
dd = clk->dpll_data;
+ if (!dd->autoidle_reg) {
+ pr_debug("clock: DPLL %s: autoidle not supported\n",
+ clk->name);
+ return;
+ }
+
/*
* REVISIT: CORE DPLL can optionally enter low-power bypass
* by writing 0x5 instead of 0x1. Add some mechanism to
@@ -554,6 +560,7 @@ void omap3_dpll_allow_idle(struct clk *clk)
v &= ~dd->autoidle_mask;
v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
__raw_writel(v, dd->autoidle_reg);
+
}
/**
@@ -572,6 +579,12 @@ void omap3_dpll_deny_idle(struct clk *clk)
dd = clk->dpll_data;
+ if (!dd->autoidle_reg) {
+ pr_debug("clock: DPLL %s: autoidle not supported\n",
+ clk->name);
+ return;
+ }
+
v = __raw_readl(dd->autoidle_reg);
v &= ~dd->autoidle_mask;
v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
diff --git a/arch/arm/mach-omap2/dsp.c b/arch/arm/mach-omap2/dsp.c
index 74f18f2952df..3376388b317a 100644
--- a/arch/arm/mach-omap2/dsp.c
+++ b/arch/arm/mach-omap2/dsp.c
@@ -57,8 +57,9 @@ static int __init omap_dsp_init(void)
if (pdata->phys_mempool_base) {
pdata->phys_mempool_size = CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE;
- pr_info("%s: %x bytes @ %x\n", __func__,
- pdata->phys_mempool_size, pdata->phys_mempool_base);
+ pr_info("%s: %llx bytes @ %llx\n", __func__,
+ (unsigned long long)pdata->phys_mempool_size,
+ (unsigned long long)pdata->phys_mempool_base);
}
pdev = platform_device_alloc("omap-dsp", -1);
diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
index 2f994e5194e8..a80e093b039f 100644
--- a/arch/arm/mach-omap2/gpio.c
+++ b/arch/arm/mach-omap2/gpio.c
@@ -20,6 +20,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
+#include <linux/of.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
@@ -58,7 +59,7 @@ static int __init omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
pdata->virtual_irq_start = IH_GPIO_BASE + 32 * (id - 1);
pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL);
- if (!pdata) {
+ if (!pdata->regs) {
pr_err("gpio%d: Memory allocation failed\n", id);
return -ENOMEM;
}
@@ -146,7 +147,10 @@ static int __init omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
*/
static int __init omap2_gpio_init(void)
{
- return omap_hwmod_for_each_by_class("gpio", omap2_gpio_dev_init,
- NULL);
+ /* If dtb is there, the devices will be created dynamically */
+ if (of_have_populated_dt())
+ return -ENODEV;
+
+ return omap_hwmod_for_each_by_class("gpio", omap2_gpio_dev_init, NULL);
}
postcore_initcall(omap2_gpio_init);
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index 385b3e02c4a6..a0fa9bb2bda5 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -176,7 +176,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
const int t_wpl = 40;
const int t_wph = 30;
int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
- int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
+ int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0;
int err, ticks_cez;
int cs = cfg->cs, freq = *freq_ptr;
@@ -240,7 +240,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
break;
}
- tick_ns = gpmc_ticks_to_ns(1);
div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period);
gpmc_clk_ns = gpmc_ticks_to_ns(div);
if (gpmc_clk_ns < 15) /* >66Mhz */
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 00d510858e28..580e684e8825 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -755,8 +755,7 @@ static int __init gpmc_init(void)
irq++;
}
- ret = request_irq(gpmc_irq,
- gpmc_handle_irq, IRQF_SHARED, "gpmc", gpmc_base);
+ ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
if (ret)
pr_err("gpmc: irq-%d could not claim: err %d\n",
gpmc_irq, ret);
diff --git a/arch/arm/mach-omap2/hdq1w.c b/arch/arm/mach-omap2/hdq1w.c
new file mode 100644
index 000000000000..297ebe03f09c
--- /dev/null
+++ b/arch/arm/mach-omap2/hdq1w.c
@@ -0,0 +1,72 @@
+/*
+ * IP block integration code for the HDQ1W/1-wire IP block
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * Based on the I2C reset code in arch/arm/mach-omap2/i2c.c by
+ * Avinash.H.M <avinashhm@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <plat/omap_hwmod.h>
+#include <plat/hdq1w.h>
+
+#include "common.h"
+
+/* Maximum microseconds to wait for OMAP module to softreset */
+#define MAX_MODULE_SOFTRESET_WAIT 10000
+
+/**
+ * omap_hdq1w_reset - reset the OMAP HDQ1W module
+ * @oh: struct omap_hwmod *
+ *
+ * OCP soft reset the HDQ1W IP block. Section 20.6.1.4 "HDQ1W/1-Wire
+ * Software Reset" of the OMAP34xx Technical Reference Manual Revision
+ * ZR (SWPU223R) does not include the rather important fact that, for
+ * the reset to succeed, the HDQ1W module's internal clock gate must be
+ * programmed to allow the clock to propagate to the rest of the
+ * module. In this sense, it's rather similar to the I2C custom reset
+ * function. Returns 0.
+ */
+int omap_hdq1w_reset(struct omap_hwmod *oh)
+{
+ u32 v;
+ int c = 0;
+
+ /* Write to the SOFTRESET bit */
+ omap_hwmod_softreset(oh);
+
+ /* Enable the module's internal clocks */
+ v = omap_hwmod_read(oh, HDQ_CTRL_STATUS_OFFSET);
+ v |= 1 << HDQ_CTRL_STATUS_CLOCKENABLE_SHIFT;
+ omap_hwmod_write(v, oh, HDQ_CTRL_STATUS_OFFSET);
+
+ /* Poll on RESETDONE bit */
+ omap_test_timeout((omap_hwmod_read(oh,
+ oh->class->sysc->syss_offs)
+ & SYSS_RESETDONE_MASK),
+ MAX_MODULE_SOFTRESET_WAIT, c);
+
+ if (c == MAX_MODULE_SOFTRESET_WAIT)
+ pr_warning("%s: %s: softreset failed (waited %d usec)\n",
+ __func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
+ else
+ pr_debug("%s: %s: softreset in %d usec\n", __func__,
+ oh->name, c);
+
+ return 0;
+}
diff --git a/arch/arm/mach-omap2/hwspinlock.c b/arch/arm/mach-omap2/hwspinlock.c
index 454dfce125ca..8763c8520dc2 100644
--- a/arch/arm/mach-omap2/hwspinlock.c
+++ b/arch/arm/mach-omap2/hwspinlock.c
@@ -28,7 +28,7 @@ static struct hwspinlock_pdata omap_hwspinlock_pdata __initdata = {
.base_id = 0,
};
-int __init hwspinlocks_init(void)
+static int __init hwspinlocks_init(void)
{
int retval = 0;
struct omap_hwmod *oh;
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 0e79b7bc6aa4..f1398171d8a2 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -478,9 +478,12 @@ void __init omap4xxx_check_revision(void)
case 0xb94e:
switch (rev) {
case 0:
- default:
omap_revision = OMAP4460_REV_ES1_0;
break;
+ case 2:
+ default:
+ omap_revision = OMAP4460_REV_ES1_1;
+ break;
}
break;
case 0xb975:
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 065bd768987c..4b9491aa36fa 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -31,6 +31,7 @@
#include <plat/omap-pm.h>
#include <plat/omap_hwmod.h>
#include <plat/multi.h>
+#include <plat/dma.h>
#include "iomap.h"
#include "voltage.h"
@@ -363,24 +364,6 @@ static void __init omap_hwmod_init_postsetup(void)
#endif
omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state);
- /*
- * Set the default postsetup state for unusual modules (like
- * MPU WDT).
- *
- * The postsetup_state is not actually used until
- * omap_hwmod_late_init(), so boards that desire full watchdog
- * coverage of kernel initialization can reprogram the
- * postsetup_state between the calls to
- * omap2_init_common_infra() and omap_sdrc_init().
- *
- * XXX ideally we could detect whether the MPU WDT was currently
- * enabled here and make this conditional
- */
- postsetup_state = _HWMOD_STATE_DISABLED;
- omap_hwmod_for_each_by_class("wd_timer",
- _set_hwmod_postsetup_state,
- &postsetup_state);
-
omap_pm_if_early_init();
}
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 65f0d2571c9a..1ecf54565fe2 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -25,6 +25,7 @@
#include <mach/hardware.h>
#include "iomap.h"
+#include "common.h"
/* selected INTC register offsets */
@@ -149,7 +150,6 @@ omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
ct->chip.irq_mask = irq_gc_mask_disable_reg;
ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
- ct->regs.ack = INTC_CONTROL;
ct->regs.enable = INTC_MIR_CLEAR0;
ct->regs.disable = INTC_MIR_SET0;
irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
@@ -231,7 +231,7 @@ static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs
goto out;
irqnr = readl_relaxed(base_addr + 0xd8);
-#ifdef CONFIG_SOC_OMAPTI816X
+#ifdef CONFIG_SOC_OMAPTI81XX
if (irqnr)
goto out;
irqnr = readl_relaxed(base_addr + 0xf8);
@@ -334,7 +334,7 @@ void omap_intc_restore_context(void)
void omap3_intc_suspend(void)
{
/* A pending interrupt would prevent OMAP from entering suspend */
- omap_ack_irq(0);
+ omap_ack_irq(NULL);
}
void omap3_intc_prepare_idle(void)
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
index 415a6f1cf419..19b8b6774862 100644
--- a/arch/arm/mach-omap2/mailbox.c
+++ b/arch/arm/mach-omap2/mailbox.c
@@ -26,9 +26,9 @@
#define MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u))
#define MAILBOX_IRQENABLE(u) (0x104 + 8 * (u))
-#define OMAP4_MAILBOX_IRQSTATUS(u) (0x104 + 10 * (u))
-#define OMAP4_MAILBOX_IRQENABLE(u) (0x108 + 10 * (u))
-#define OMAP4_MAILBOX_IRQENABLE_CLR(u) (0x10c + 10 * (u))
+#define OMAP4_MAILBOX_IRQSTATUS(u) (0x104 + 0x10 * (u))
+#define OMAP4_MAILBOX_IRQENABLE(u) (0x108 + 0x10 * (u))
+#define OMAP4_MAILBOX_IRQENABLE_CLR(u) (0x10c + 0x10 * (u))
#define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m)))
#define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1))
diff --git a/arch/arm/mach-omap2/msdi.c b/arch/arm/mach-omap2/msdi.c
new file mode 100644
index 000000000000..ef2a6924731a
--- /dev/null
+++ b/arch/arm/mach-omap2/msdi.c
@@ -0,0 +1,88 @@
+/*
+ * MSDI IP block reset
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * XXX What about pad muxing?
+ */
+
+#include <linux/kernel.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/mmc.h>
+
+#include "common.h"
+
+/*
+ * MSDI_CON_OFFSET: offset in bytes of the MSDI IP block's CON register
+ * from the IP block's base address
+ */
+#define MSDI_CON_OFFSET 0x0c
+
+/* Register bitfields in the CON register */
+#define MSDI_CON_POW_MASK BIT(11)
+#define MSDI_CON_CLKD_MASK (0x3f << 0)
+#define MSDI_CON_CLKD_SHIFT 0
+
+/* Maximum microseconds to wait for OMAP module to softreset */
+#define MAX_MODULE_SOFTRESET_WAIT 10000
+
+/* MSDI_TARGET_RESET_CLKD: clock divisor to use throughout the reset */
+#define MSDI_TARGET_RESET_CLKD 0x3ff
+
+/**
+ * omap_msdi_reset - reset the MSDI IP block
+ * @oh: struct omap_hwmod *
+ *
+ * The MSDI IP block on OMAP2420 has to have both the POW and CLKD
+ * fields set inside its CON register for a reset to complete
+ * successfully. This is not documented in the TRM. For CLKD, we use
+ * the value that results in the lowest possible clock rate, to attempt
+ * to avoid disturbing any cards.
+ */
+int omap_msdi_reset(struct omap_hwmod *oh)
+{
+ u16 v = 0;
+ int c = 0;
+
+ /* Write to the SOFTRESET bit */
+ omap_hwmod_softreset(oh);
+
+ /* Enable the MSDI core and internal clock */
+ v |= MSDI_CON_POW_MASK;
+ v |= MSDI_TARGET_RESET_CLKD << MSDI_CON_CLKD_SHIFT;
+ omap_hwmod_write(v, oh, MSDI_CON_OFFSET);
+
+ /* Poll on RESETDONE bit */
+ omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs)
+ & SYSS_RESETDONE_MASK),
+ MAX_MODULE_SOFTRESET_WAIT, c);
+
+ if (c == MAX_MODULE_SOFTRESET_WAIT)
+ pr_warning("%s: %s: softreset failed (waited %d usec)\n",
+ __func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
+ else
+ pr_debug("%s: %s: softreset in %d usec\n", __func__,
+ oh->name, c);
+
+ /* Disable the MSDI internal clock */
+ v &= ~MSDI_CON_CLKD_MASK;
+ omap_hwmod_write(v, oh, MSDI_CON_OFFSET);
+
+ return 0;
+}
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 65c33911341f..3268ee24eada 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -247,7 +247,7 @@ int __init omap_mux_init_signal(const char *muxname, int val)
int mux_mode;
mux_mode = omap_mux_get_by_name(muxname, &partition, &mux);
- if (mux_mode < 0)
+ if (mux_mode < 0 || !mux)
return mux_mode;
old_mode = omap_mux_read(partition, mux->reg_offset);
diff --git a/arch/arm/mach-omap2/omap-secure.c b/arch/arm/mach-omap2/omap-secure.c
index d8f8ef40290f..d9ae4a53d818 100644
--- a/arch/arm/mach-omap2/omap-secure.c
+++ b/arch/arm/mach-omap2/omap-secure.c
@@ -18,6 +18,7 @@
#include <asm/cacheflush.h>
#include <asm/memblock.h>
+#include <plat/omap-secure.h>
#include <mach/omap-secure.h>
static phys_addr_t omap_secure_memblock_base;
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index 42cd7fb52414..d811c7790350 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -259,7 +259,7 @@ static void irq_save_context(void)
/*
* Clear WakeupGen SAR backup status.
*/
-void irq_sar_clear(void)
+static void irq_sar_clear(void)
{
u32 val;
val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 70de277f5c15..a8161e5f3204 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -25,11 +25,13 @@
#include <plat/irqs.h>
#include <plat/sram.h>
#include <plat/omap-secure.h>
+#include <plat/mmc.h>
#include <mach/hardware.h>
#include <mach/omap-wakeupgen.h>
#include "common.h"
+#include "hsmmc.h"
#include "omap4-sar-layout.h"
#include <linux/export.h>
@@ -207,3 +209,59 @@ static int __init omap4_sar_ram_init(void)
return 0;
}
early_initcall(omap4_sar_ram_init);
+
+#if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
+static int omap4_twl6030_hsmmc_late_init(struct device *dev)
+{
+ int irq = 0;
+ struct platform_device *pdev = container_of(dev,
+ struct platform_device, dev);
+ struct omap_mmc_platform_data *pdata = dev->platform_data;
+
+ /* Setting MMC1 Card detect Irq */
+ if (pdev->id == 0) {
+ irq = twl6030_mmc_card_detect_config();
+ if (irq < 0) {
+ dev_err(dev, "%s: Error card detect config(%d)\n",
+ __func__, irq);
+ return irq;
+ }
+ pdata->slots[0].card_detect_irq = irq;
+ pdata->slots[0].card_detect = twl6030_mmc_card_detect;
+ }
+ return 0;
+}
+
+static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
+{
+ struct omap_mmc_platform_data *pdata;
+
+ /* dev can be null if CONFIG_MMC_OMAP_HS is not set */
+ if (!dev) {
+ pr_err("Failed %s\n", __func__);
+ return;
+ }
+ pdata = dev->platform_data;
+ pdata->init = omap4_twl6030_hsmmc_late_init;
+}
+
+int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
+{
+ struct omap2_hsmmc_info *c;
+
+ omap_hsmmc_init(controllers);
+ for (c = controllers; c->mmc; c++) {
+ /* pdev can be null if CONFIG_MMC_OMAP_HS is not set */
+ if (!c->pdev)
+ continue;
+ omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
+ }
+
+ return 0;
+}
+#else
+int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
+{
+ return 0;
+}
+#endif
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 7144ae651d3d..bf86f7e8f91f 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2,7 +2,7 @@
* omap_hwmod implementation for OMAP2/3/4
*
* Copyright (C) 2009-2011 Nokia Corporation
- * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011-2012 Texas Instruments, Inc.
*
* Paul Walmsley, Benoît Cousson, Kevin Hilman
*
@@ -137,6 +137,7 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
+#include <linux/bootmem.h>
#include "common.h"
#include <plat/cpu.h>
@@ -159,16 +160,58 @@
/* Name of the OMAP hwmod for the MPU */
#define MPU_INITIATOR_NAME "mpu"
+/*
+ * Number of struct omap_hwmod_link records per struct
+ * omap_hwmod_ocp_if record (master->slave and slave->master)
+ */
+#define LINKS_PER_OCP_IF 2
+
/* omap_hwmod_list contains all registered struct omap_hwmods */
static LIST_HEAD(omap_hwmod_list);
/* mpu_oh: used to add/remove MPU initiator from sleepdep list */
static struct omap_hwmod *mpu_oh;
+/*
+ * linkspace: ptr to a buffer that struct omap_hwmod_link records are
+ * allocated from - used to reduce the number of small memory
+ * allocations, which has a significant impact on performance
+ */
+static struct omap_hwmod_link *linkspace;
+
+/*
+ * free_ls, max_ls: array indexes into linkspace; representing the
+ * next free struct omap_hwmod_link index, and the maximum number of
+ * struct omap_hwmod_link records allocated (respectively)
+ */
+static unsigned short free_ls, max_ls, ls_supp;
/* Private functions */
/**
+ * _fetch_next_ocp_if - return the next OCP interface in a list
+ * @p: ptr to a ptr to the list_head inside the ocp_if to return
+ * @i: pointer to the index of the element pointed to by @p in the list
+ *
+ * Return a pointer to the struct omap_hwmod_ocp_if record
+ * containing the struct list_head pointed to by @p, and increment
+ * @p such that a future call to this routine will return the next
+ * record.
+ */
+static struct omap_hwmod_ocp_if *_fetch_next_ocp_if(struct list_head **p,
+ int *i)
+{
+ struct omap_hwmod_ocp_if *oi;
+
+ oi = list_entry(*p, struct omap_hwmod_link, node)->ocp_if;
+ *p = (*p)->next;
+
+ *i = *i + 1;
+
+ return oi;
+}
+
+/**
* _update_sysc_cache - return the module OCP_SYSCONFIG register, keep copy
* @oh: struct omap_hwmod *
*
@@ -582,16 +625,16 @@ static int _init_main_clk(struct omap_hwmod *oh)
*/
static int _init_interface_clks(struct omap_hwmod *oh)
{
+ struct omap_hwmod_ocp_if *os;
+ struct list_head *p;
struct clk *c;
- int i;
+ int i = 0;
int ret = 0;
- if (oh->slaves_cnt == 0)
- return 0;
-
- for (i = 0; i < oh->slaves_cnt; i++) {
- struct omap_hwmod_ocp_if *os = oh->slaves[i];
+ p = oh->slave_ports.next;
+ while (i < oh->slaves_cnt) {
+ os = _fetch_next_ocp_if(&p, &i);
if (!os->clk)
continue;
@@ -643,21 +686,22 @@ static int _init_opt_clks(struct omap_hwmod *oh)
*/
static int _enable_clocks(struct omap_hwmod *oh)
{
- int i;
+ struct omap_hwmod_ocp_if *os;
+ struct list_head *p;
+ int i = 0;
pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name);
if (oh->_clk)
clk_enable(oh->_clk);
- if (oh->slaves_cnt > 0) {
- for (i = 0; i < oh->slaves_cnt; i++) {
- struct omap_hwmod_ocp_if *os = oh->slaves[i];
- struct clk *c = os->_clk;
+ p = oh->slave_ports.next;
- if (c && (os->flags & OCPIF_SWSUP_IDLE))
- clk_enable(c);
- }
+ while (i < oh->slaves_cnt) {
+ os = _fetch_next_ocp_if(&p, &i);
+
+ if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE))
+ clk_enable(os->_clk);
}
/* The opt clocks are controlled by the device driver. */
@@ -673,21 +717,22 @@ static int _enable_clocks(struct omap_hwmod *oh)
*/
static int _disable_clocks(struct omap_hwmod *oh)
{
- int i;
+ struct omap_hwmod_ocp_if *os;
+ struct list_head *p;
+ int i = 0;
pr_debug("omap_hwmod: %s: disabling clocks\n", oh->name);
if (oh->_clk)
clk_disable(oh->_clk);
- if (oh->slaves_cnt > 0) {
- for (i = 0; i < oh->slaves_cnt; i++) {
- struct omap_hwmod_ocp_if *os = oh->slaves[i];
- struct clk *c = os->_clk;
+ p = oh->slave_ports.next;
- if (c && (os->flags & OCPIF_SWSUP_IDLE))
- clk_disable(c);
- }
+ while (i < oh->slaves_cnt) {
+ os = _fetch_next_ocp_if(&p, &i);
+
+ if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE))
+ clk_disable(os->_clk);
}
/* The opt clocks are controlled by the device driver. */
@@ -781,39 +826,6 @@ static int _omap4_wait_target_disable(struct omap_hwmod *oh)
}
/**
- * _omap4_disable_module - enable CLKCTRL modulemode on OMAP4
- * @oh: struct omap_hwmod *
- *
- * Disable the PRCM module mode related to the hwmod @oh.
- * Return EINVAL if the modulemode is not supported and 0 in case of success.
- */
-static int _omap4_disable_module(struct omap_hwmod *oh)
-{
- int v;
-
- /* The module mode does not exist prior OMAP4 */
- if (!cpu_is_omap44xx())
- return -EINVAL;
-
- if (!oh->clkdm || !oh->prcm.omap4.modulemode)
- return -EINVAL;
-
- pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
-
- omap4_cminst_module_disable(oh->clkdm->prcm_partition,
- oh->clkdm->cm_inst,
- oh->clkdm->clkdm_offs,
- oh->prcm.omap4.clkctrl_offs);
-
- v = _omap4_wait_target_disable(oh);
- if (v)
- pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
- oh->name);
-
- return 0;
-}
-
-/**
* _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh
* @oh: struct omap_hwmod *oh
*
@@ -883,59 +895,220 @@ static int _count_ocp_if_addr_spaces(struct omap_hwmod_ocp_if *os)
}
/**
- * _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use
- * @oh: struct omap_hwmod *
+ * _get_mpu_irq_by_name - fetch MPU interrupt line number by name
+ * @oh: struct omap_hwmod * to operate on
+ * @name: pointer to the name of the MPU interrupt number to fetch (optional)
+ * @irq: pointer to an unsigned int to store the MPU IRQ number to
*
- * Returns the array index of the OCP slave port that the MPU
- * addresses the device on, or -EINVAL upon error or not found.
+ * Retrieve a MPU hardware IRQ line number named by @name associated
+ * with the IP block pointed to by @oh. The IRQ number will be filled
+ * into the address pointed to by @dma. When @name is non-null, the
+ * IRQ line number associated with the named entry will be returned.
+ * If @name is null, the first matching entry will be returned. Data
+ * order is not meaningful in hwmod data, so callers are strongly
+ * encouraged to use a non-null @name whenever possible to avoid
+ * unpredictable effects if hwmod data is later added that causes data
+ * ordering to change. Returns 0 upon success or a negative error
+ * code upon error.
*/
-static int __init _find_mpu_port_index(struct omap_hwmod *oh)
+static int _get_mpu_irq_by_name(struct omap_hwmod *oh, const char *name,
+ unsigned int *irq)
{
int i;
- int found = 0;
+ bool found = false;
- if (!oh || oh->slaves_cnt == 0)
- return -EINVAL;
+ if (!oh->mpu_irqs)
+ return -ENOENT;
- for (i = 0; i < oh->slaves_cnt; i++) {
- struct omap_hwmod_ocp_if *os = oh->slaves[i];
+ i = 0;
+ while (oh->mpu_irqs[i].irq != -1) {
+ if (name == oh->mpu_irqs[i].name ||
+ !strcmp(name, oh->mpu_irqs[i].name)) {
+ found = true;
+ break;
+ }
+ i++;
+ }
- if (os->user & OCP_USER_MPU) {
- found = 1;
+ if (!found)
+ return -ENOENT;
+
+ *irq = oh->mpu_irqs[i].irq;
+
+ return 0;
+}
+
+/**
+ * _get_sdma_req_by_name - fetch SDMA request line ID by name
+ * @oh: struct omap_hwmod * to operate on
+ * @name: pointer to the name of the SDMA request line to fetch (optional)
+ * @dma: pointer to an unsigned int to store the request line ID to
+ *
+ * Retrieve an SDMA request line ID named by @name on the IP block
+ * pointed to by @oh. The ID will be filled into the address pointed
+ * to by @dma. When @name is non-null, the request line ID associated
+ * with the named entry will be returned. If @name is null, the first
+ * matching entry will be returned. Data order is not meaningful in
+ * hwmod data, so callers are strongly encouraged to use a non-null
+ * @name whenever possible to avoid unpredictable effects if hwmod
+ * data is later added that causes data ordering to change. Returns 0
+ * upon success or a negative error code upon error.
+ */
+static int _get_sdma_req_by_name(struct omap_hwmod *oh, const char *name,
+ unsigned int *dma)
+{
+ int i;
+ bool found = false;
+
+ if (!oh->sdma_reqs)
+ return -ENOENT;
+
+ i = 0;
+ while (oh->sdma_reqs[i].dma_req != -1) {
+ if (name == oh->sdma_reqs[i].name ||
+ !strcmp(name, oh->sdma_reqs[i].name)) {
+ found = true;
break;
}
+ i++;
}
- if (found)
- pr_debug("omap_hwmod: %s: MPU OCP slave port ID %d\n",
- oh->name, i);
- else
- pr_debug("omap_hwmod: %s: no MPU OCP slave port found\n",
- oh->name);
+ if (!found)
+ return -ENOENT;
+
+ *dma = oh->sdma_reqs[i].dma_req;
- return (found) ? i : -EINVAL;
+ return 0;
}
/**
- * _find_mpu_rt_base - find hwmod register target base addr accessible by MPU
- * @oh: struct omap_hwmod *
+ * _get_addr_space_by_name - fetch address space start & end by name
+ * @oh: struct omap_hwmod * to operate on
+ * @name: pointer to the name of the address space to fetch (optional)
+ * @pa_start: pointer to a u32 to store the starting address to
+ * @pa_end: pointer to a u32 to store the ending address to
*
- * Return the virtual address of the base of the register target of
- * device @oh, or NULL on error.
+ * Retrieve address space start and end addresses for the IP block
+ * pointed to by @oh. The data will be filled into the addresses
+ * pointed to by @pa_start and @pa_end. When @name is non-null, the
+ * address space data associated with the named entry will be
+ * returned. If @name is null, the first matching entry will be
+ * returned. Data order is not meaningful in hwmod data, so callers
+ * are strongly encouraged to use a non-null @name whenever possible
+ * to avoid unpredictable effects if hwmod data is later added that
+ * causes data ordering to change. Returns 0 upon success or a
+ * negative error code upon error.
*/
-static void __iomem * __init _find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
+static int _get_addr_space_by_name(struct omap_hwmod *oh, const char *name,
+ u32 *pa_start, u32 *pa_end)
{
+ int i, j;
struct omap_hwmod_ocp_if *os;
- struct omap_hwmod_addr_space *mem;
- int i = 0, found = 0;
- void __iomem *va_start;
+ struct list_head *p = NULL;
+ bool found = false;
+
+ p = oh->slave_ports.next;
+
+ i = 0;
+ while (i < oh->slaves_cnt) {
+ os = _fetch_next_ocp_if(&p, &i);
+
+ if (!os->addr)
+ return -ENOENT;
+
+ j = 0;
+ while (os->addr[j].pa_start != os->addr[j].pa_end) {
+ if (name == os->addr[j].name ||
+ !strcmp(name, os->addr[j].name)) {
+ found = true;
+ break;
+ }
+ j++;
+ }
+
+ if (found)
+ break;
+ }
+
+ if (!found)
+ return -ENOENT;
+
+ *pa_start = os->addr[j].pa_start;
+ *pa_end = os->addr[j].pa_end;
+
+ return 0;
+}
+
+/**
+ * _save_mpu_port_index - find and save the index to @oh's MPU port
+ * @oh: struct omap_hwmod *
+ *
+ * Determines the array index of the OCP slave port that the MPU uses
+ * to address the device, and saves it into the struct omap_hwmod.
+ * Intended to be called during hwmod registration only. No return
+ * value.
+ */
+static void __init _save_mpu_port_index(struct omap_hwmod *oh)
+{
+ struct omap_hwmod_ocp_if *os = NULL;
+ struct list_head *p;
+ int i = 0;
+
+ if (!oh)
+ return;
- if (!oh || oh->slaves_cnt == 0)
+ oh->_int_flags |= _HWMOD_NO_MPU_PORT;
+
+ p = oh->slave_ports.next;
+
+ while (i < oh->slaves_cnt) {
+ os = _fetch_next_ocp_if(&p, &i);
+ if (os->user & OCP_USER_MPU) {
+ oh->_mpu_port = os;
+ oh->_int_flags &= ~_HWMOD_NO_MPU_PORT;
+ break;
+ }
+ }
+
+ return;
+}
+
+/**
+ * _find_mpu_rt_port - return omap_hwmod_ocp_if accessible by the MPU
+ * @oh: struct omap_hwmod *
+ *
+ * Given a pointer to a struct omap_hwmod record @oh, return a pointer
+ * to the struct omap_hwmod_ocp_if record that is used by the MPU to
+ * communicate with the IP block. This interface need not be directly
+ * connected to the MPU (and almost certainly is not), but is directly
+ * connected to the IP block represented by @oh. Returns a pointer
+ * to the struct omap_hwmod_ocp_if * upon success, or returns NULL upon
+ * error or if there does not appear to be a path from the MPU to this
+ * IP block.
+ */
+static struct omap_hwmod_ocp_if *_find_mpu_rt_port(struct omap_hwmod *oh)
+{
+ if (!oh || oh->_int_flags & _HWMOD_NO_MPU_PORT || oh->slaves_cnt == 0)
return NULL;
- os = oh->slaves[index];
+ return oh->_mpu_port;
+};
+
+/**
+ * _find_mpu_rt_addr_space - return MPU register target address space for @oh
+ * @oh: struct omap_hwmod *
+ *
+ * Returns a pointer to the struct omap_hwmod_addr_space record representing
+ * the register target MPU address space; or returns NULL upon error.
+ */
+static struct omap_hwmod_addr_space * __init _find_mpu_rt_addr_space(struct omap_hwmod *oh)
+{
+ struct omap_hwmod_ocp_if *os;
+ struct omap_hwmod_addr_space *mem;
+ int found = 0, i = 0;
- if (!os->addr)
+ os = _find_mpu_rt_port(oh);
+ if (!os || !os->addr)
return NULL;
do {
@@ -944,20 +1117,7 @@ static void __iomem * __init _find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
found = 1;
} while (!found && mem->pa_start != mem->pa_end);
- if (found) {
- va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start);
- if (!va_start) {
- pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name);
- return NULL;
- }
- pr_debug("omap_hwmod: %s: MPU register target at va %p\n",
- oh->name, va_start);
- } else {
- pr_debug("omap_hwmod: %s: no MPU register target found\n",
- oh->name);
- }
-
- return (found) ? va_start : NULL;
+ return (found) ? mem : NULL;
}
/**
@@ -1205,12 +1365,11 @@ static int _wait_target_ready(struct omap_hwmod *oh)
if (!oh)
return -EINVAL;
- if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
+ if (oh->flags & HWMOD_NO_IDLEST)
return 0;
- os = oh->slaves[oh->_mpu_port_index];
-
- if (oh->flags & HWMOD_NO_IDLEST)
+ os = _find_mpu_rt_port(oh);
+ if (!os)
return 0;
/* XXX check module SIDLEMODE */
@@ -1378,13 +1537,73 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
}
/**
+ * _are_any_hardreset_lines_asserted - return true if part of @oh is hard-reset
+ * @oh: struct omap_hwmod *
+ *
+ * If any hardreset line associated with @oh is asserted, then return true.
+ * Otherwise, if @oh has no hardreset lines associated with it, or if
+ * no hardreset lines associated with @oh are asserted, then return false.
+ * This function is used to avoid executing some parts of the IP block
+ * enable/disable sequence if a hardreset line is set.
+ */
+static bool _are_any_hardreset_lines_asserted(struct omap_hwmod *oh)
+{
+ int i;
+
+ if (oh->rst_lines_cnt == 0)
+ return false;
+
+ for (i = 0; i < oh->rst_lines_cnt; i++)
+ if (_read_hardreset(oh, oh->rst_lines[i].name) > 0)
+ return true;
+
+ return false;
+}
+
+/**
+ * _omap4_disable_module - enable CLKCTRL modulemode on OMAP4
+ * @oh: struct omap_hwmod *
+ *
+ * Disable the PRCM module mode related to the hwmod @oh.
+ * Return EINVAL if the modulemode is not supported and 0 in case of success.
+ */
+static int _omap4_disable_module(struct omap_hwmod *oh)
+{
+ int v;
+
+ /* The module mode does not exist prior OMAP4 */
+ if (!cpu_is_omap44xx())
+ return -EINVAL;
+
+ if (!oh->clkdm || !oh->prcm.omap4.modulemode)
+ return -EINVAL;
+
+ pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
+
+ omap4_cminst_module_disable(oh->clkdm->prcm_partition,
+ oh->clkdm->cm_inst,
+ oh->clkdm->clkdm_offs,
+ oh->prcm.omap4.clkctrl_offs);
+
+ if (_are_any_hardreset_lines_asserted(oh))
+ return 0;
+
+ v = _omap4_wait_target_disable(oh);
+ if (v)
+ pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
+ oh->name);
+
+ return 0;
+}
+
+/**
* _ocp_softreset - reset an omap_hwmod via the OCP_SYSCONFIG bit
* @oh: struct omap_hwmod *
*
* Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit. hwmod must be
- * enabled for this to work. Returns -EINVAL if the hwmod cannot be
- * reset this way or if the hwmod is in the wrong state, -ETIMEDOUT if
- * the module did not reset in time, or 0 upon success.
+ * enabled for this to work. Returns -ENOENT if the hwmod cannot be
+ * reset this way, -EINVAL if the hwmod is in the wrong state,
+ * -ETIMEDOUT if the module did not reset in time, or 0 upon success.
*
* In OMAP3 a specific SYSSTATUS register is used to get the reset status.
* Starting in OMAP4, some IPs do not have SYSSTATUS registers and instead
@@ -1401,7 +1620,7 @@ static int _ocp_softreset(struct omap_hwmod *oh)
if (!oh->class->sysc ||
!(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET))
- return -EINVAL;
+ return -ENOENT;
/* clocks must be on for this operation */
if (oh->_state != _HWMOD_STATE_ENABLED) {
@@ -1462,32 +1681,60 @@ dis_opt_clks:
* _reset - reset an omap_hwmod
* @oh: struct omap_hwmod *
*
- * Resets an omap_hwmod @oh. The default software reset mechanism for
- * most OMAP IP blocks is triggered via the OCP_SYSCONFIG.SOFTRESET
- * bit. However, some hwmods cannot be reset via this method: some
- * are not targets and therefore have no OCP header registers to
- * access; others (like the IVA) have idiosyncratic reset sequences.
- * So for these relatively rare cases, custom reset code can be
- * supplied in the struct omap_hwmod_class .reset function pointer.
- * Passes along the return value from either _reset() or the custom
- * reset function - these must return -EINVAL if the hwmod cannot be
- * reset this way or if the hwmod is in the wrong state, -ETIMEDOUT if
- * the module did not reset in time, or 0 upon success.
+ * Resets an omap_hwmod @oh. If the module has a custom reset
+ * function pointer defined, then call it to reset the IP block, and
+ * pass along its return value to the caller. Otherwise, if the IP
+ * block has an OCP_SYSCONFIG register with a SOFTRESET bitfield
+ * associated with it, call a function to reset the IP block via that
+ * method, and pass along the return value to the caller. Finally, if
+ * the IP block has some hardreset lines associated with it, assert
+ * all of those, but do _not_ deassert them. (This is because driver
+ * authors have expressed an apparent requirement to control the
+ * deassertion of the hardreset lines themselves.)
+ *
+ * The default software reset mechanism for most OMAP IP blocks is
+ * triggered via the OCP_SYSCONFIG.SOFTRESET bit. However, some
+ * hwmods cannot be reset via this method. Some are not targets and
+ * therefore have no OCP header registers to access. Others (like the
+ * IVA) have idiosyncratic reset sequences. So for these relatively
+ * rare cases, custom reset code can be supplied in the struct
+ * omap_hwmod_class .reset function pointer. Passes along the return
+ * value from either _ocp_softreset() or the custom reset function -
+ * these must return -EINVAL if the hwmod cannot be reset this way or
+ * if the hwmod is in the wrong state, -ETIMEDOUT if the module did
+ * not reset in time, or 0 upon success.
*/
static int _reset(struct omap_hwmod *oh)
{
- int ret;
+ int i, r;
pr_debug("omap_hwmod: %s: resetting\n", oh->name);
- ret = (oh->class->reset) ? oh->class->reset(oh) : _ocp_softreset(oh);
+ if (oh->class->reset) {
+ r = oh->class->reset(oh);
+ } else {
+ if (oh->rst_lines_cnt > 0) {
+ for (i = 0; i < oh->rst_lines_cnt; i++)
+ _assert_hardreset(oh, oh->rst_lines[i].name);
+ return 0;
+ } else {
+ r = _ocp_softreset(oh);
+ if (r == -ENOENT)
+ r = 0;
+ }
+ }
+ /*
+ * OCP_SYSCONFIG bits need to be reprogrammed after a
+ * softreset. The _enable() function should be split to avoid
+ * the rewrite of the OCP_SYSCONFIG register.
+ */
if (oh->class->sysc) {
_update_sysc_cache(oh);
_enable_sysc(oh);
}
- return ret;
+ return r;
}
/**
@@ -1506,10 +1753,9 @@ static int _enable(struct omap_hwmod *oh)
pr_debug("omap_hwmod: %s: enabling\n", oh->name);
/*
- * hwmods with HWMOD_INIT_NO_IDLE flag set are left
- * in enabled state at init.
- * Now that someone is really trying to enable them,
- * just ensure that the hwmod mux is set.
+ * hwmods with HWMOD_INIT_NO_IDLE flag set are left in enabled
+ * state at init. Now that someone is really trying to enable
+ * them, just ensure that the hwmod mux is set.
*/
if (oh->_int_flags & _HWMOD_SKIP_ENABLE) {
/*
@@ -1532,15 +1778,17 @@ static int _enable(struct omap_hwmod *oh)
return -EINVAL;
}
-
/*
- * If an IP contains only one HW reset line, then de-assert it in order
- * to allow the module state transition. Otherwise the PRCM will return
- * Intransition status, and the init will failed.
+ * If an IP block contains HW reset lines and any of them are
+ * asserted, we let integration code associated with that
+ * block handle the enable. We've received very little
+ * information on what those driver authors need, and until
+ * detailed information is provided and the driver code is
+ * posted to the public lists, this is probably the best we
+ * can do.
*/
- if ((oh->_state == _HWMOD_STATE_INITIALIZED ||
- oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1)
- _deassert_hardreset(oh, oh->rst_lines[0].name);
+ if (_are_any_hardreset_lines_asserted(oh))
+ return 0;
/* Mux pins for device runtime if populated */
if (oh->mux && (!oh->mux->enabled ||
@@ -1615,6 +1863,9 @@ static int _idle(struct omap_hwmod *oh)
return -EINVAL;
}
+ if (_are_any_hardreset_lines_asserted(oh))
+ return 0;
+
if (oh->class->sysc)
_idle_sysc(oh);
_del_initiator_dep(oh, mpu_oh);
@@ -1687,7 +1938,7 @@ int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle)
*/
static int _shutdown(struct omap_hwmod *oh)
{
- int ret;
+ int ret, i;
u8 prev_state;
if (oh->_state != _HWMOD_STATE_IDLE &&
@@ -1697,6 +1948,9 @@ static int _shutdown(struct omap_hwmod *oh)
return -EINVAL;
}
+ if (_are_any_hardreset_lines_asserted(oh))
+ return 0;
+
pr_debug("omap_hwmod: %s: disabling\n", oh->name);
if (oh->class->pre_shutdown) {
@@ -1728,12 +1982,8 @@ static int _shutdown(struct omap_hwmod *oh)
}
/* XXX Should this code also force-disable the optional clocks? */
- /*
- * If an IP contains only one HW reset line, then assert it
- * after disabling the clocks and before shutting down the IP.
- */
- if (oh->rst_lines_cnt == 1)
- _assert_hardreset(oh, oh->rst_lines[0].name);
+ for (i = 0; i < oh->rst_lines_cnt; i++)
+ _assert_hardreset(oh, oh->rst_lines[i].name);
/* Mux pins to safe mode or use populated off mode values */
if (oh->mux)
@@ -1745,59 +1995,186 @@ static int _shutdown(struct omap_hwmod *oh)
}
/**
- * _setup - do initial configuration of omap_hwmod
- * @oh: struct omap_hwmod *
+ * _init_mpu_rt_base - populate the virtual address for a hwmod
+ * @oh: struct omap_hwmod * to locate the virtual address
*
- * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
- * OCP_SYSCONFIG register. Returns 0.
+ * Cache the virtual address used by the MPU to access this IP block's
+ * registers. This address is needed early so the OCP registers that
+ * are part of the device's address space can be ioremapped properly.
+ * No return value.
*/
-static int _setup(struct omap_hwmod *oh, void *data)
+static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data)
{
- int i, r;
- u8 postsetup_state;
+ struct omap_hwmod_addr_space *mem;
+ void __iomem *va_start;
+
+ if (!oh)
+ return;
+
+ _save_mpu_port_index(oh);
- if (oh->_state != _HWMOD_STATE_CLKS_INITED)
+ if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
+ return;
+
+ mem = _find_mpu_rt_addr_space(oh);
+ if (!mem) {
+ pr_debug("omap_hwmod: %s: no MPU register target found\n",
+ oh->name);
+ return;
+ }
+
+ va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start);
+ if (!va_start) {
+ pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name);
+ return;
+ }
+
+ pr_debug("omap_hwmod: %s: MPU register target at va %p\n",
+ oh->name, va_start);
+
+ oh->_mpu_rt_va = va_start;
+}
+
+/**
+ * _init - initialize internal data for the hwmod @oh
+ * @oh: struct omap_hwmod *
+ * @n: (unused)
+ *
+ * Look up the clocks and the address space used by the MPU to access
+ * registers belonging to the hwmod @oh. @oh must already be
+ * registered at this point. This is the first of two phases for
+ * hwmod initialization. Code called here does not touch any hardware
+ * registers, it simply prepares internal data structures. Returns 0
+ * upon success or if the hwmod isn't registered, or -EINVAL upon
+ * failure.
+ */
+static int __init _init(struct omap_hwmod *oh, void *data)
+{
+ int r;
+
+ if (oh->_state != _HWMOD_STATE_REGISTERED)
return 0;
- /* Set iclk autoidle mode */
- if (oh->slaves_cnt > 0) {
- for (i = 0; i < oh->slaves_cnt; i++) {
- struct omap_hwmod_ocp_if *os = oh->slaves[i];
- struct clk *c = os->_clk;
+ _init_mpu_rt_base(oh, NULL);
- if (!c)
- continue;
+ r = _init_clocks(oh, NULL);
+ if (IS_ERR_VALUE(r)) {
+ WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh->name);
+ return -EINVAL;
+ }
- if (os->flags & OCPIF_SWSUP_IDLE) {
- /* XXX omap_iclk_deny_idle(c); */
- } else {
- /* XXX omap_iclk_allow_idle(c); */
- clk_enable(c);
- }
+ oh->_state = _HWMOD_STATE_INITIALIZED;
+
+ return 0;
+}
+
+/**
+ * _setup_iclk_autoidle - configure an IP block's interface clocks
+ * @oh: struct omap_hwmod *
+ *
+ * Set up the module's interface clocks. XXX This function is still mostly
+ * a stub; implementing this properly requires iclk autoidle usecounting in
+ * the clock code. No return value.
+ */
+static void __init _setup_iclk_autoidle(struct omap_hwmod *oh)
+{
+ struct omap_hwmod_ocp_if *os;
+ struct list_head *p;
+ int i = 0;
+ if (oh->_state != _HWMOD_STATE_INITIALIZED)
+ return;
+
+ p = oh->slave_ports.next;
+
+ while (i < oh->slaves_cnt) {
+ os = _fetch_next_ocp_if(&p, &i);
+ if (!os->_clk)
+ continue;
+
+ if (os->flags & OCPIF_SWSUP_IDLE) {
+ /* XXX omap_iclk_deny_idle(c); */
+ } else {
+ /* XXX omap_iclk_allow_idle(c); */
+ clk_enable(os->_clk);
}
}
- oh->_state = _HWMOD_STATE_INITIALIZED;
+ return;
+}
- /*
- * In the case of hwmod with hardreset that should not be
- * de-assert at boot time, we have to keep the module
- * initialized, because we cannot enable it properly with the
- * reset asserted. Exit without warning because that behavior is
- * expected.
- */
- if ((oh->flags & HWMOD_INIT_NO_RESET) && oh->rst_lines_cnt == 1)
- return 0;
+/**
+ * _setup_reset - reset an IP block during the setup process
+ * @oh: struct omap_hwmod *
+ *
+ * Reset the IP block corresponding to the hwmod @oh during the setup
+ * process. The IP block is first enabled so it can be successfully
+ * reset. Returns 0 upon success or a negative error code upon
+ * failure.
+ */
+static int __init _setup_reset(struct omap_hwmod *oh)
+{
+ int r;
- r = _enable(oh);
- if (r) {
- pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
- oh->name, oh->_state);
- return 0;
+ if (oh->_state != _HWMOD_STATE_INITIALIZED)
+ return -EINVAL;
+
+ if (oh->rst_lines_cnt == 0) {
+ r = _enable(oh);
+ if (r) {
+ pr_warning("omap_hwmod: %s: cannot be enabled for reset (%d)\n",
+ oh->name, oh->_state);
+ return -EINVAL;
+ }
}
if (!(oh->flags & HWMOD_INIT_NO_RESET))
- _reset(oh);
+ r = _reset(oh);
+
+ return r;
+}
+
+/**
+ * _setup_postsetup - transition to the appropriate state after _setup
+ * @oh: struct omap_hwmod *
+ *
+ * Place an IP block represented by @oh into a "post-setup" state --
+ * either IDLE, ENABLED, or DISABLED. ("post-setup" simply means that
+ * this function is called at the end of _setup().) The postsetup
+ * state for an IP block can be changed by calling
+ * omap_hwmod_enter_postsetup_state() early in the boot process,
+ * before one of the omap_hwmod_setup*() functions are called for the
+ * IP block.
+ *
+ * The IP block stays in this state until a PM runtime-based driver is
+ * loaded for that IP block. A post-setup state of IDLE is
+ * appropriate for almost all IP blocks with runtime PM-enabled
+ * drivers, since those drivers are able to enable the IP block. A
+ * post-setup state of ENABLED is appropriate for kernels with PM
+ * runtime disabled. The DISABLED state is appropriate for unusual IP
+ * blocks such as the MPU WDTIMER on kernels without WDTIMER drivers
+ * included, since the WDTIMER starts running on reset and will reset
+ * the MPU if left active.
+ *
+ * This post-setup mechanism is deprecated. Once all of the OMAP
+ * drivers have been converted to use PM runtime, and all of the IP
+ * block data and interconnect data is available to the hwmod code, it
+ * should be possible to replace this mechanism with a "lazy reset"
+ * arrangement. In a "lazy reset" setup, each IP block is enabled
+ * when the driver first probes, then all remaining IP blocks without
+ * drivers are either shut down or enabled after the drivers have
+ * loaded. However, this cannot take place until the above
+ * preconditions have been met, since otherwise the late reset code
+ * has no way of knowing which IP blocks are in use by drivers, and
+ * which ones are unused.
+ *
+ * No return value.
+ */
+static void __init _setup_postsetup(struct omap_hwmod *oh)
+{
+ u8 postsetup_state;
+
+ if (oh->rst_lines_cnt > 0)
+ return;
postsetup_state = oh->_postsetup_state;
if (postsetup_state == _HWMOD_STATE_UNKNOWN)
@@ -1821,6 +2198,35 @@ static int _setup(struct omap_hwmod *oh, void *data)
WARN(1, "hwmod: %s: unknown postsetup state %d! defaulting to enabled\n",
oh->name, postsetup_state);
+ return;
+}
+
+/**
+ * _setup - prepare IP block hardware for use
+ * @oh: struct omap_hwmod *
+ * @n: (unused, pass NULL)
+ *
+ * Configure the IP block represented by @oh. This may include
+ * enabling the IP block, resetting it, and placing it into a
+ * post-setup state, depending on the type of IP block and applicable
+ * flags. IP blocks are reset to prevent any previous configuration
+ * by the bootloader or previous operating system from interfering
+ * with power management or other parts of the system. The reset can
+ * be avoided; see omap_hwmod_no_setup_reset(). This is the second of
+ * two phases for hwmod initialization. Code called here generally
+ * affects the IP block hardware, or system integration hardware
+ * associated with the IP block. Returns 0.
+ */
+static int __init _setup(struct omap_hwmod *oh, void *data)
+{
+ if (oh->_state != _HWMOD_STATE_INITIALIZED)
+ return 0;
+
+ _setup_iclk_autoidle(oh);
+
+ if (!_setup_reset(oh))
+ _setup_postsetup(oh);
+
return 0;
}
@@ -1843,8 +2249,6 @@ static int _setup(struct omap_hwmod *oh, void *data)
*/
static int __init _register(struct omap_hwmod *oh)
{
- int ms_id;
-
if (!oh || !oh->name || !oh->class || !oh->class->name ||
(oh->_state != _HWMOD_STATE_UNKNOWN))
return -EINVAL;
@@ -1854,14 +2258,10 @@ static int __init _register(struct omap_hwmod *oh)
if (_lookup(oh->name))
return -EEXIST;
- ms_id = _find_mpu_port_index(oh);
- if (!IS_ERR_VALUE(ms_id))
- oh->_mpu_port_index = ms_id;
- else
- oh->_int_flags |= _HWMOD_NO_MPU_PORT;
-
list_add_tail(&oh->node, &omap_hwmod_list);
+ INIT_LIST_HEAD(&oh->master_ports);
+ INIT_LIST_HEAD(&oh->slave_ports);
spin_lock_init(&oh->_lock);
oh->_state = _HWMOD_STATE_REGISTERED;
@@ -1876,6 +2276,160 @@ static int __init _register(struct omap_hwmod *oh)
return 0;
}
+/**
+ * _alloc_links - return allocated memory for hwmod links
+ * @ml: pointer to a struct omap_hwmod_link * for the master link
+ * @sl: pointer to a struct omap_hwmod_link * for the slave link
+ *
+ * Return pointers to two struct omap_hwmod_link records, via the
+ * addresses pointed to by @ml and @sl. Will first attempt to return
+ * memory allocated as part of a large initial block, but if that has
+ * been exhausted, will allocate memory itself. Since ideally this
+ * second allocation path will never occur, the number of these
+ * 'supplemental' allocations will be logged when debugging is
+ * enabled. Returns 0.
+ */
+static int __init _alloc_links(struct omap_hwmod_link **ml,
+ struct omap_hwmod_link **sl)
+{
+ unsigned int sz;
+
+ if ((free_ls + LINKS_PER_OCP_IF) <= max_ls) {
+ *ml = &linkspace[free_ls++];
+ *sl = &linkspace[free_ls++];
+ return 0;
+ }
+
+ sz = sizeof(struct omap_hwmod_link) * LINKS_PER_OCP_IF;
+
+ *sl = NULL;
+ *ml = alloc_bootmem(sz);
+
+ memset(*ml, 0, sz);
+
+ *sl = (void *)(*ml) + sizeof(struct omap_hwmod_link);
+
+ ls_supp++;
+ pr_debug("omap_hwmod: supplemental link allocations needed: %d\n",
+ ls_supp * LINKS_PER_OCP_IF);
+
+ return 0;
+};
+
+/**
+ * _add_link - add an interconnect between two IP blocks
+ * @oi: pointer to a struct omap_hwmod_ocp_if record
+ *
+ * Add struct omap_hwmod_link records connecting the master IP block
+ * specified in @oi->master to @oi, and connecting the slave IP block
+ * specified in @oi->slave to @oi. This code is assumed to run before
+ * preemption or SMP has been enabled, thus avoiding the need for
+ * locking in this code. Changes to this assumption will require
+ * additional locking. Returns 0.
+ */
+static int __init _add_link(struct omap_hwmod_ocp_if *oi)
+{
+ struct omap_hwmod_link *ml, *sl;
+
+ pr_debug("omap_hwmod: %s -> %s: adding link\n", oi->master->name,
+ oi->slave->name);
+
+ _alloc_links(&ml, &sl);
+
+ ml->ocp_if = oi;
+ INIT_LIST_HEAD(&ml->node);
+ list_add(&ml->node, &oi->master->master_ports);
+ oi->master->masters_cnt++;
+
+ sl->ocp_if = oi;
+ INIT_LIST_HEAD(&sl->node);
+ list_add(&sl->node, &oi->slave->slave_ports);
+ oi->slave->slaves_cnt++;
+
+ return 0;
+}
+
+/**
+ * _register_link - register a struct omap_hwmod_ocp_if
+ * @oi: struct omap_hwmod_ocp_if *
+ *
+ * Registers the omap_hwmod_ocp_if record @oi. Returns -EEXIST if it
+ * has already been registered; -EINVAL if @oi is NULL or if the
+ * record pointed to by @oi is missing required fields; or 0 upon
+ * success.
+ *
+ * XXX The data should be copied into bootmem, so the original data
+ * should be marked __initdata and freed after init. This would allow
+ * unneeded omap_hwmods to be freed on multi-OMAP configurations.
+ */
+static int __init _register_link(struct omap_hwmod_ocp_if *oi)
+{
+ if (!oi || !oi->master || !oi->slave || !oi->user)
+ return -EINVAL;
+
+ if (oi->_int_flags & _OCPIF_INT_FLAGS_REGISTERED)
+ return -EEXIST;
+
+ pr_debug("omap_hwmod: registering link from %s to %s\n",
+ oi->master->name, oi->slave->name);
+
+ /*
+ * Register the connected hwmods, if they haven't been
+ * registered already
+ */
+ if (oi->master->_state != _HWMOD_STATE_REGISTERED)
+ _register(oi->master);
+
+ if (oi->slave->_state != _HWMOD_STATE_REGISTERED)
+ _register(oi->slave);
+
+ _add_link(oi);
+
+ oi->_int_flags |= _OCPIF_INT_FLAGS_REGISTERED;
+
+ return 0;
+}
+
+/**
+ * _alloc_linkspace - allocate large block of hwmod links
+ * @ois: pointer to an array of struct omap_hwmod_ocp_if records to count
+ *
+ * Allocate a large block of struct omap_hwmod_link records. This
+ * improves boot time significantly by avoiding the need to allocate
+ * individual records one by one. If the number of records to
+ * allocate in the block hasn't been manually specified, this function
+ * will count the number of struct omap_hwmod_ocp_if records in @ois
+ * and use that to determine the allocation size. For SoC families
+ * that require multiple list registrations, such as OMAP3xxx, this
+ * estimation process isn't optimal, so manual estimation is advised
+ * in those cases. Returns -EEXIST if the allocation has already occurred
+ * or 0 upon success.
+ */
+static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois)
+{
+ unsigned int i = 0;
+ unsigned int sz;
+
+ if (linkspace) {
+ WARN(1, "linkspace already allocated\n");
+ return -EEXIST;
+ }
+
+ if (max_ls == 0)
+ while (ois[i++])
+ max_ls += LINKS_PER_OCP_IF;
+
+ sz = sizeof(struct omap_hwmod_link) * max_ls;
+
+ pr_debug("omap_hwmod: %s: allocating %d byte linkspace (%d links)\n",
+ __func__, sz, max_ls);
+
+ linkspace = alloc_bootmem(sz);
+
+ memset(linkspace, 0, sz);
+
+ return 0;
+}
/* Public functions */
@@ -2004,120 +2558,101 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
}
/**
- * omap_hwmod_register - register an array of hwmods
- * @ohs: pointer to an array of omap_hwmods to register
+ * omap_hwmod_register_links - register an array of hwmod links
+ * @ois: pointer to an array of omap_hwmod_ocp_if to register
*
* Intended to be called early in boot before the clock framework is
- * initialized. If @ohs is not null, will register all omap_hwmods
- * listed in @ohs that are valid for this chip. Returns 0.
+ * initialized. If @ois is not null, will register all omap_hwmods
+ * listed in @ois that are valid for this chip. Returns 0.
*/
-int __init omap_hwmod_register(struct omap_hwmod **ohs)
+int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois)
{
int r, i;
- if (!ohs)
+ if (!ois)
return 0;
+ if (!linkspace) {
+ if (_alloc_linkspace(ois)) {
+ pr_err("omap_hwmod: could not allocate link space\n");
+ return -ENOMEM;
+ }
+ }
+
i = 0;
do {
- r = _register(ohs[i]);
- WARN(r, "omap_hwmod: %s: _register returned %d\n", ohs[i]->name,
- r);
- } while (ohs[++i]);
+ r = _register_link(ois[i]);
+ WARN(r && r != -EEXIST,
+ "omap_hwmod: _register_link(%s -> %s) returned %d\n",
+ ois[i]->master->name, ois[i]->slave->name, r);
+ } while (ois[++i]);
return 0;
}
-/*
- * _populate_mpu_rt_base - populate the virtual address for a hwmod
+/**
+ * _ensure_mpu_hwmod_is_setup - ensure the MPU SS hwmod is init'ed and set up
+ * @oh: pointer to the hwmod currently being set up (usually not the MPU)
*
- * Must be called only from omap_hwmod_setup_*() so ioremap works properly.
- * Assumes the caller takes care of locking if needed.
+ * If the hwmod data corresponding to the MPU subsystem IP block
+ * hasn't been initialized and set up yet, do so now. This must be
+ * done first since sleep dependencies may be added from other hwmods
+ * to the MPU. Intended to be called only by omap_hwmod_setup*(). No
+ * return value.
*/
-static int __init _populate_mpu_rt_base(struct omap_hwmod *oh, void *data)
+static void __init _ensure_mpu_hwmod_is_setup(struct omap_hwmod *oh)
{
- if (oh->_state != _HWMOD_STATE_REGISTERED)
- return 0;
-
- if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
- return 0;
-
- oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
-
- return 0;
+ if (!mpu_oh || mpu_oh->_state == _HWMOD_STATE_UNKNOWN)
+ pr_err("omap_hwmod: %s: MPU initiator hwmod %s not yet registered\n",
+ __func__, MPU_INITIATOR_NAME);
+ else if (mpu_oh->_state == _HWMOD_STATE_REGISTERED && oh != mpu_oh)
+ omap_hwmod_setup_one(MPU_INITIATOR_NAME);
}
/**
* omap_hwmod_setup_one - set up a single hwmod
* @oh_name: const char * name of the already-registered hwmod to set up
*
- * Must be called after omap2_clk_init(). Resolves the struct clk
- * names to struct clk pointers for each registered omap_hwmod. Also
- * calls _setup() on each hwmod. Returns -EINVAL upon error or 0 upon
- * success.
+ * Initialize and set up a single hwmod. Intended to be used for a
+ * small number of early devices, such as the timer IP blocks used for
+ * the scheduler clock. Must be called after omap2_clk_init().
+ * Resolves the struct clk names to struct clk pointers for each
+ * registered omap_hwmod. Also calls _setup() on each hwmod. Returns
+ * -EINVAL upon error or 0 upon success.
*/
int __init omap_hwmod_setup_one(const char *oh_name)
{
struct omap_hwmod *oh;
- int r;
pr_debug("omap_hwmod: %s: %s\n", oh_name, __func__);
- if (!mpu_oh) {
- pr_err("omap_hwmod: %s: cannot setup_one: MPU initiator hwmod %s not yet registered\n",
- oh_name, MPU_INITIATOR_NAME);
- return -EINVAL;
- }
-
oh = _lookup(oh_name);
if (!oh) {
WARN(1, "omap_hwmod: %s: hwmod not yet registered\n", oh_name);
return -EINVAL;
}
- if (mpu_oh->_state == _HWMOD_STATE_REGISTERED && oh != mpu_oh)
- omap_hwmod_setup_one(MPU_INITIATOR_NAME);
-
- r = _populate_mpu_rt_base(oh, NULL);
- if (IS_ERR_VALUE(r)) {
- WARN(1, "omap_hwmod: %s: couldn't set mpu_rt_base\n", oh_name);
- return -EINVAL;
- }
-
- r = _init_clocks(oh, NULL);
- if (IS_ERR_VALUE(r)) {
- WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh_name);
- return -EINVAL;
- }
+ _ensure_mpu_hwmod_is_setup(oh);
+ _init(oh, NULL);
_setup(oh, NULL);
return 0;
}
/**
- * omap_hwmod_setup - do some post-clock framework initialization
+ * omap_hwmod_setup_all - set up all registered IP blocks
*
- * Must be called after omap2_clk_init(). Resolves the struct clk names
- * to struct clk pointers for each registered omap_hwmod. Also calls
- * _setup() on each hwmod. Returns 0 upon success.
+ * Initialize and set up all IP blocks registered with the hwmod code.
+ * Must be called after omap2_clk_init(). Resolves the struct clk
+ * names to struct clk pointers for each registered omap_hwmod. Also
+ * calls _setup() on each hwmod. Returns 0 upon success.
*/
static int __init omap_hwmod_setup_all(void)
{
- int r;
-
- if (!mpu_oh) {
- pr_err("omap_hwmod: %s: MPU initiator hwmod %s not yet registered\n",
- __func__, MPU_INITIATOR_NAME);
- return -EINVAL;
- }
-
- r = omap_hwmod_for_each(_populate_mpu_rt_base, NULL);
-
- r = omap_hwmod_for_each(_init_clocks, NULL);
- WARN(IS_ERR_VALUE(r),
- "omap_hwmod: %s: _init_clocks failed\n", __func__);
+ _ensure_mpu_hwmod_is_setup(NULL);
+ omap_hwmod_for_each(_init, NULL);
omap_hwmod_for_each(_setup, NULL);
return 0;
@@ -2274,6 +2809,10 @@ int omap_hwmod_reset(struct omap_hwmod *oh)
return r;
}
+/*
+ * IP block data retrieval functions
+ */
+
/**
* omap_hwmod_count_resources - count number of struct resources needed by hwmod
* @oh: struct omap_hwmod *
@@ -2292,12 +2831,19 @@ int omap_hwmod_reset(struct omap_hwmod *oh)
*/
int omap_hwmod_count_resources(struct omap_hwmod *oh)
{
- int ret, i;
+ struct omap_hwmod_ocp_if *os;
+ struct list_head *p;
+ int ret;
+ int i = 0;
ret = _count_mpu_irqs(oh) + _count_sdma_reqs(oh);
- for (i = 0; i < oh->slaves_cnt; i++)
- ret += _count_ocp_if_addr_spaces(oh->slaves[i]);
+ p = oh->slave_ports.next;
+
+ while (i < oh->slaves_cnt) {
+ os = _fetch_next_ocp_if(&p, &i);
+ ret += _count_ocp_if_addr_spaces(os);
+ }
return ret;
}
@@ -2314,7 +2860,9 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
*/
int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
{
- int i, j, mpu_irqs_cnt, sdma_reqs_cnt;
+ struct omap_hwmod_ocp_if *os;
+ struct list_head *p;
+ int i, j, mpu_irqs_cnt, sdma_reqs_cnt, addr_cnt;
int r = 0;
/* For each IRQ, DMA, memory area, fill in array.*/
@@ -2337,11 +2885,11 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
r++;
}
- for (i = 0; i < oh->slaves_cnt; i++) {
- struct omap_hwmod_ocp_if *os;
- int addr_cnt;
+ p = oh->slave_ports.next;
- os = oh->slaves[i];
+ i = 0;
+ while (i < oh->slaves_cnt) {
+ os = _fetch_next_ocp_if(&p, &i);
addr_cnt = _count_ocp_if_addr_spaces(os);
for (j = 0; j < addr_cnt; j++) {
@@ -2357,6 +2905,69 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
}
/**
+ * omap_hwmod_get_resource_byname - fetch IP block integration data by name
+ * @oh: struct omap_hwmod * to operate on
+ * @type: one of the IORESOURCE_* constants from include/linux/ioport.h
+ * @name: pointer to the name of the data to fetch (optional)
+ * @rsrc: pointer to a struct resource, allocated by the caller
+ *
+ * Retrieve MPU IRQ, SDMA request line, or address space start/end
+ * data for the IP block pointed to by @oh. The data will be filled
+ * into a struct resource record pointed to by @rsrc. The struct
+ * resource must be allocated by the caller. When @name is non-null,
+ * the data associated with the matching entry in the IRQ/SDMA/address
+ * space hwmod data arrays will be returned. If @name is null, the
+ * first array entry will be returned. Data order is not meaningful
+ * in hwmod data, so callers are strongly encouraged to use a non-null
+ * @name whenever possible to avoid unpredictable effects if hwmod
+ * data is later added that causes data ordering to change. This
+ * function is only intended for use by OMAP core code. Device
+ * drivers should not call this function - the appropriate bus-related
+ * data accessor functions should be used instead. Returns 0 upon
+ * success or a negative error code upon error.
+ */
+int omap_hwmod_get_resource_byname(struct omap_hwmod *oh, unsigned int type,
+ const char *name, struct resource *rsrc)
+{
+ int r;
+ unsigned int irq, dma;
+ u32 pa_start, pa_end;
+
+ if (!oh || !rsrc)
+ return -EINVAL;
+
+ if (type == IORESOURCE_IRQ) {
+ r = _get_mpu_irq_by_name(oh, name, &irq);
+ if (r)
+ return r;
+
+ rsrc->start = irq;
+ rsrc->end = irq;
+ } else if (type == IORESOURCE_DMA) {
+ r = _get_sdma_req_by_name(oh, name, &dma);
+ if (r)
+ return r;
+
+ rsrc->start = dma;
+ rsrc->end = dma;
+ } else if (type == IORESOURCE_MEM) {
+ r = _get_addr_space_by_name(oh, name, &pa_start, &pa_end);
+ if (r)
+ return r;
+
+ rsrc->start = pa_start;
+ rsrc->end = pa_end;
+ } else {
+ return -EINVAL;
+ }
+
+ rsrc->flags = type;
+ rsrc->name = name;
+
+ return 0;
+}
+
+/**
* omap_hwmod_get_pwrdm - return pointer to this module's main powerdomain
* @oh: struct omap_hwmod *
*
@@ -2370,6 +2981,7 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)
{
struct clk *c;
+ struct omap_hwmod_ocp_if *oi;
if (!oh)
return NULL;
@@ -2377,9 +2989,10 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)
if (oh->_clk) {
c = oh->_clk;
} else {
- if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
+ oi = _find_mpu_rt_port(oh);
+ if (!oi)
return NULL;
- c = oh->slaves[oh->_mpu_port_index]->_clk;
+ c = oi->_clk;
}
if (!c->clkdm)
@@ -2653,10 +3266,10 @@ int omap_hwmod_for_each_by_class(const char *classname,
* @state: state that _setup() should leave the hwmod in
*
* Sets the hwmod state that @oh will enter at the end of _setup()
- * (called by omap_hwmod_setup_*()). Only valid to call between
- * calling omap_hwmod_register() and omap_hwmod_setup_*(). Returns
- * 0 upon success or -EINVAL if there is a problem with the arguments
- * or if the hwmod is in the wrong state.
+ * (called by omap_hwmod_setup_*()). See also the documentation
+ * for _setup_postsetup(), above. Returns 0 upon success or
+ * -EINVAL if there is a problem with the arguments or if the hwmod is
+ * in the wrong state.
*/
int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state)
{
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index a6bde34e443a..a7640d1b215e 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -2,6 +2,7 @@
* omap_hwmod_2420_data.c - hardware modules present on the OMAP2420 chips
*
* Copyright (C) 2009-2011 Nokia Corporation
+ * Copyright (C) 2012 Texas Instruments, Inc.
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
@@ -22,6 +23,7 @@
#include <plat/dmtimer.h>
#include <plat/l3_2xxx.h>
#include <plat/l4_2xxx.h>
+#include <plat/mmc.h>
#include "omap_hwmod_common_data.h"
@@ -32,707 +34,329 @@
/*
* OMAP2420 hardware module integration data
*
- * ALl of the data in this section should be autogeneratable from the
+ * All of the data in this section should be autogeneratable from the
* TI hardware database or other technical documentation. Data that
* is driver-specific or driver-kernel integration-specific belongs
* elsewhere.
*/
-static struct omap_hwmod omap2420_mpu_hwmod;
-static struct omap_hwmod omap2420_iva_hwmod;
-static struct omap_hwmod omap2420_l3_main_hwmod;
-static struct omap_hwmod omap2420_l4_core_hwmod;
-static struct omap_hwmod omap2420_dss_core_hwmod;
-static struct omap_hwmod omap2420_dss_dispc_hwmod;
-static struct omap_hwmod omap2420_dss_rfbi_hwmod;
-static struct omap_hwmod omap2420_dss_venc_hwmod;
-static struct omap_hwmod omap2420_wd_timer2_hwmod;
-static struct omap_hwmod omap2420_gpio1_hwmod;
-static struct omap_hwmod omap2420_gpio2_hwmod;
-static struct omap_hwmod omap2420_gpio3_hwmod;
-static struct omap_hwmod omap2420_gpio4_hwmod;
-static struct omap_hwmod omap2420_dma_system_hwmod;
-static struct omap_hwmod omap2420_mcspi1_hwmod;
-static struct omap_hwmod omap2420_mcspi2_hwmod;
-
-/* L3 -> L4_CORE interface */
-static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
- .master = &omap2420_l3_main_hwmod,
- .slave = &omap2420_l4_core_hwmod,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* MPU -> L3 interface */
-static struct omap_hwmod_ocp_if omap2420_mpu__l3_main = {
- .master = &omap2420_mpu_hwmod,
- .slave = &omap2420_l3_main_hwmod,
- .user = OCP_USER_MPU,
-};
-
-/* Slave interfaces on the L3 interconnect */
-static struct omap_hwmod_ocp_if *omap2420_l3_main_slaves[] = {
- &omap2420_mpu__l3_main,
-};
-
-/* DSS -> l3 */
-static struct omap_hwmod_ocp_if omap2420_dss__l3 = {
- .master = &omap2420_dss_core_hwmod,
- .slave = &omap2420_l3_main_hwmod,
- .fw = {
- .omap2 = {
- .l3_perm_bit = OMAP2_L3_CORE_FW_CONNID_DSS,
- .flags = OMAP_FIREWALL_L3,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* Master interfaces on the L3 interconnect */
-static struct omap_hwmod_ocp_if *omap2420_l3_main_masters[] = {
- &omap2420_l3_main__l4_core,
-};
-
-/* L3 */
-static struct omap_hwmod omap2420_l3_main_hwmod = {
- .name = "l3_main",
- .class = &l3_hwmod_class,
- .masters = omap2420_l3_main_masters,
- .masters_cnt = ARRAY_SIZE(omap2420_l3_main_masters),
- .slaves = omap2420_l3_main_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_l3_main_slaves),
- .flags = HWMOD_NO_IDLEST,
-};
-
-static struct omap_hwmod omap2420_l4_wkup_hwmod;
-static struct omap_hwmod omap2420_uart1_hwmod;
-static struct omap_hwmod omap2420_uart2_hwmod;
-static struct omap_hwmod omap2420_uart3_hwmod;
-static struct omap_hwmod omap2420_i2c1_hwmod;
-static struct omap_hwmod omap2420_i2c2_hwmod;
-static struct omap_hwmod omap2420_mcbsp1_hwmod;
-static struct omap_hwmod omap2420_mcbsp2_hwmod;
-
-/* l4 core -> mcspi1 interface */
-static struct omap_hwmod_ocp_if omap2420_l4_core__mcspi1 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_mcspi1_hwmod,
- .clk = "mcspi1_ick",
- .addr = omap2_mcspi1_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4 core -> mcspi2 interface */
-static struct omap_hwmod_ocp_if omap2420_l4_core__mcspi2 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_mcspi2_hwmod,
- .clk = "mcspi2_ick",
- .addr = omap2_mcspi2_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4_CORE -> L4_WKUP interface */
-static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_l4_wkup_hwmod,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> UART1 interface */
-static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_uart1_hwmod,
- .clk = "uart1_ick",
- .addr = omap2xxx_uart1_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> UART2 interface */
-static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_uart2_hwmod,
- .clk = "uart2_ick",
- .addr = omap2xxx_uart2_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 PER -> UART3 interface */
-static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_uart3_hwmod,
- .clk = "uart3_ick",
- .addr = omap2xxx_uart3_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> I2C1 interface */
-static struct omap_hwmod_ocp_if omap2420_l4_core__i2c1 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_i2c1_hwmod,
- .clk = "i2c1_ick",
- .addr = omap2_i2c1_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> I2C2 interface */
-static struct omap_hwmod_ocp_if omap2420_l4_core__i2c2 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_i2c2_hwmod,
- .clk = "i2c2_ick",
- .addr = omap2_i2c2_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* Slave interfaces on the L4_CORE interconnect */
-static struct omap_hwmod_ocp_if *omap2420_l4_core_slaves[] = {
- &omap2420_l3_main__l4_core,
-};
-
-/* Master interfaces on the L4_CORE interconnect */
-static struct omap_hwmod_ocp_if *omap2420_l4_core_masters[] = {
- &omap2420_l4_core__l4_wkup,
- &omap2_l4_core__uart1,
- &omap2_l4_core__uart2,
- &omap2_l4_core__uart3,
- &omap2420_l4_core__i2c1,
- &omap2420_l4_core__i2c2
-};
-
-/* L4 CORE */
-static struct omap_hwmod omap2420_l4_core_hwmod = {
- .name = "l4_core",
- .class = &l4_hwmod_class,
- .masters = omap2420_l4_core_masters,
- .masters_cnt = ARRAY_SIZE(omap2420_l4_core_masters),
- .slaves = omap2420_l4_core_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_l4_core_slaves),
- .flags = HWMOD_NO_IDLEST,
-};
-
-/* Slave interfaces on the L4_WKUP interconnect */
-static struct omap_hwmod_ocp_if *omap2420_l4_wkup_slaves[] = {
- &omap2420_l4_core__l4_wkup,
-};
-
-/* Master interfaces on the L4_WKUP interconnect */
-static struct omap_hwmod_ocp_if *omap2420_l4_wkup_masters[] = {
-};
-
-/* L4 WKUP */
-static struct omap_hwmod omap2420_l4_wkup_hwmod = {
- .name = "l4_wkup",
- .class = &l4_hwmod_class,
- .masters = omap2420_l4_wkup_masters,
- .masters_cnt = ARRAY_SIZE(omap2420_l4_wkup_masters),
- .slaves = omap2420_l4_wkup_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_l4_wkup_slaves),
- .flags = HWMOD_NO_IDLEST,
-};
-
-/* Master interfaces on the MPU device */
-static struct omap_hwmod_ocp_if *omap2420_mpu_masters[] = {
- &omap2420_mpu__l3_main,
-};
-
-/* MPU */
-static struct omap_hwmod omap2420_mpu_hwmod = {
- .name = "mpu",
- .class = &mpu_hwmod_class,
- .main_clk = "mpu_ck",
- .masters = omap2420_mpu_masters,
- .masters_cnt = ARRAY_SIZE(omap2420_mpu_masters),
-};
-
/*
- * IVA1 interface data
+ * IP blocks
*/
-/* IVA <- L3 interface */
-static struct omap_hwmod_ocp_if omap2420_l3__iva = {
- .master = &omap2420_l3_main_hwmod,
- .slave = &omap2420_iva_hwmod,
- .clk = "iva1_ifck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
+/* IVA1 (IVA1) */
+static struct omap_hwmod_class iva1_hwmod_class = {
+ .name = "iva1",
};
-static struct omap_hwmod_ocp_if *omap2420_iva_masters[] = {
- &omap2420_l3__iva,
+static struct omap_hwmod_rst_info omap2420_iva_resets[] = {
+ { .name = "iva", .rst_shift = 8 },
};
-/*
- * IVA2 (IVA2)
- */
-
static struct omap_hwmod omap2420_iva_hwmod = {
.name = "iva",
- .class = &iva_hwmod_class,
- .masters = omap2420_iva_masters,
- .masters_cnt = ARRAY_SIZE(omap2420_iva_masters),
-};
-
-/* always-on timers dev attribute */
-static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
- .timer_capability = OMAP_TIMER_ALWON,
+ .class = &iva1_hwmod_class,
+ .clkdm_name = "iva1_clkdm",
+ .rst_lines = omap2420_iva_resets,
+ .rst_lines_cnt = ARRAY_SIZE(omap2420_iva_resets),
+ .main_clk = "iva1_ifck",
};
-/* pwm timers dev attribute */
-static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
- .timer_capability = OMAP_TIMER_HAS_PWM,
-};
-
-/* timer1 */
-static struct omap_hwmod omap2420_timer1_hwmod;
-
-static struct omap_hwmod_addr_space omap2420_timer1_addrs[] = {
- {
- .pa_start = 0x48028000,
- .pa_end = 0x48028000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
+/* DSP */
+static struct omap_hwmod_class dsp_hwmod_class = {
+ .name = "dsp",
};
-/* l4_wkup -> timer1 */
-static struct omap_hwmod_ocp_if omap2420_l4_wkup__timer1 = {
- .master = &omap2420_l4_wkup_hwmod,
- .slave = &omap2420_timer1_hwmod,
- .clk = "gpt1_ick",
- .addr = omap2420_timer1_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
+static struct omap_hwmod_rst_info omap2420_dsp_resets[] = {
+ { .name = "logic", .rst_shift = 0 },
+ { .name = "mmu", .rst_shift = 1 },
};
-/* timer1 slave port */
-static struct omap_hwmod_ocp_if *omap2420_timer1_slaves[] = {
- &omap2420_l4_wkup__timer1,
+static struct omap_hwmod omap2420_dsp_hwmod = {
+ .name = "dsp",
+ .class = &dsp_hwmod_class,
+ .clkdm_name = "dsp_clkdm",
+ .rst_lines = omap2420_dsp_resets,
+ .rst_lines_cnt = ARRAY_SIZE(omap2420_dsp_resets),
+ .main_clk = "dsp_fck",
};
-/* timer1 hwmod */
-static struct omap_hwmod omap2420_timer1_hwmod = {
- .name = "timer1",
- .mpu_irqs = omap2_timer1_mpu_irqs,
- .main_clk = "gpt1_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT1_SHIFT,
- .module_offs = WKUP_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
- },
- },
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2420_timer1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_timer1_slaves),
- .class = &omap2xxx_timer_hwmod_class,
+/* I2C common */
+static struct omap_hwmod_class_sysconfig i2c_sysc = {
+ .rev_offs = 0x00,
+ .sysc_offs = 0x20,
+ .syss_offs = 0x10,
+ .sysc_flags = (SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+ .sysc_fields = &omap_hwmod_sysc_type1,
};
-/* timer2 */
-static struct omap_hwmod omap2420_timer2_hwmod;
-
-/* l4_core -> timer2 */
-static struct omap_hwmod_ocp_if omap2420_l4_core__timer2 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_timer2_hwmod,
- .clk = "gpt2_ick",
- .addr = omap2xxx_timer2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
+static struct omap_hwmod_class i2c_class = {
+ .name = "i2c",
+ .sysc = &i2c_sysc,
+ .rev = OMAP_I2C_IP_VERSION_1,
+ .reset = &omap_i2c_reset,
};
-/* timer2 slave port */
-static struct omap_hwmod_ocp_if *omap2420_timer2_slaves[] = {
- &omap2420_l4_core__timer2,
+static struct omap_i2c_dev_attr i2c_dev_attr = {
+ .flags = OMAP_I2C_FLAG_NO_FIFO |
+ OMAP_I2C_FLAG_SIMPLE_CLOCK |
+ OMAP_I2C_FLAG_16BIT_DATA_REG |
+ OMAP_I2C_FLAG_BUS_SHIFT_2,
};
-/* timer2 hwmod */
-static struct omap_hwmod omap2420_timer2_hwmod = {
- .name = "timer2",
- .mpu_irqs = omap2_timer2_mpu_irqs,
- .main_clk = "gpt2_fck",
+/* I2C1 */
+static struct omap_hwmod omap2420_i2c1_hwmod = {
+ .name = "i2c1",
+ .mpu_irqs = omap2_i2c1_mpu_irqs,
+ .sdma_reqs = omap2_i2c1_sdma_reqs,
+ .main_clk = "i2c1_fck",
.prcm = {
.omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT2_SHIFT,
.module_offs = CORE_MOD,
+ .prcm_reg_id = 1,
+ .module_bit = OMAP2420_EN_I2C1_SHIFT,
.idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
+ .idlest_idle_bit = OMAP2420_ST_I2C1_SHIFT,
},
},
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2420_timer2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_timer2_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* timer3 */
-static struct omap_hwmod omap2420_timer3_hwmod;
-
-/* l4_core -> timer3 */
-static struct omap_hwmod_ocp_if omap2420_l4_core__timer3 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_timer3_hwmod,
- .clk = "gpt3_ick",
- .addr = omap2xxx_timer3_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer3 slave port */
-static struct omap_hwmod_ocp_if *omap2420_timer3_slaves[] = {
- &omap2420_l4_core__timer3,
+ .class = &i2c_class,
+ .dev_attr = &i2c_dev_attr,
+ .flags = HWMOD_16BIT_REG,
};
-/* timer3 hwmod */
-static struct omap_hwmod omap2420_timer3_hwmod = {
- .name = "timer3",
- .mpu_irqs = omap2_timer3_mpu_irqs,
- .main_clk = "gpt3_fck",
+/* I2C2 */
+static struct omap_hwmod omap2420_i2c2_hwmod = {
+ .name = "i2c2",
+ .mpu_irqs = omap2_i2c2_mpu_irqs,
+ .sdma_reqs = omap2_i2c2_sdma_reqs,
+ .main_clk = "i2c2_fck",
.prcm = {
.omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT3_SHIFT,
.module_offs = CORE_MOD,
+ .prcm_reg_id = 1,
+ .module_bit = OMAP2420_EN_I2C2_SHIFT,
.idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
+ .idlest_idle_bit = OMAP2420_ST_I2C2_SHIFT,
},
},
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2420_timer3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_timer3_slaves),
- .class = &omap2xxx_timer_hwmod_class,
+ .class = &i2c_class,
+ .dev_attr = &i2c_dev_attr,
+ .flags = HWMOD_16BIT_REG,
};
-/* timer4 */
-static struct omap_hwmod omap2420_timer4_hwmod;
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+ .dev_caps = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+ IS_CSSA_32 | IS_CDSA_32,
+ .lch_count = 32,
+};
-/* l4_core -> timer4 */
-static struct omap_hwmod_ocp_if omap2420_l4_core__timer4 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_timer4_hwmod,
- .clk = "gpt4_ick",
- .addr = omap2xxx_timer4_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
+static struct omap_hwmod omap2420_dma_system_hwmod = {
+ .name = "dma",
+ .class = &omap2xxx_dma_hwmod_class,
+ .mpu_irqs = omap2_dma_system_irqs,
+ .main_clk = "core_l3_ck",
+ .dev_attr = &dma_dev_attr,
+ .flags = HWMOD_NO_IDLEST,
};
-/* timer4 slave port */
-static struct omap_hwmod_ocp_if *omap2420_timer4_slaves[] = {
- &omap2420_l4_core__timer4,
+/* mailbox */
+static struct omap_hwmod_irq_info omap2420_mailbox_irqs[] = {
+ { .name = "dsp", .irq = 26 },
+ { .name = "iva", .irq = 34 },
+ { .irq = -1 }
};
-/* timer4 hwmod */
-static struct omap_hwmod omap2420_timer4_hwmod = {
- .name = "timer4",
- .mpu_irqs = omap2_timer4_mpu_irqs,
- .main_clk = "gpt4_fck",
+static struct omap_hwmod omap2420_mailbox_hwmod = {
+ .name = "mailbox",
+ .class = &omap2xxx_mailbox_hwmod_class,
+ .mpu_irqs = omap2420_mailbox_irqs,
+ .main_clk = "mailboxes_ick",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT4_SHIFT,
+ .module_bit = OMAP24XX_EN_MAILBOXES_SHIFT,
.module_offs = CORE_MOD,
.idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
+ .idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
},
},
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2420_timer4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_timer4_slaves),
- .class = &omap2xxx_timer_hwmod_class,
};
-/* timer5 */
-static struct omap_hwmod omap2420_timer5_hwmod;
+/*
+ * 'mcbsp' class
+ * multi channel buffered serial port controller
+ */
-/* l4_core -> timer5 */
-static struct omap_hwmod_ocp_if omap2420_l4_core__timer5 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_timer5_hwmod,
- .clk = "gpt5_ick",
- .addr = omap2xxx_timer5_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
+static struct omap_hwmod_class omap2420_mcbsp_hwmod_class = {
+ .name = "mcbsp",
};
-/* timer5 slave port */
-static struct omap_hwmod_ocp_if *omap2420_timer5_slaves[] = {
- &omap2420_l4_core__timer5,
+/* mcbsp1 */
+static struct omap_hwmod_irq_info omap2420_mcbsp1_irqs[] = {
+ { .name = "tx", .irq = 59 },
+ { .name = "rx", .irq = 60 },
+ { .irq = -1 }
};
-/* timer5 hwmod */
-static struct omap_hwmod omap2420_timer5_hwmod = {
- .name = "timer5",
- .mpu_irqs = omap2_timer5_mpu_irqs,
- .main_clk = "gpt5_fck",
+static struct omap_hwmod omap2420_mcbsp1_hwmod = {
+ .name = "mcbsp1",
+ .class = &omap2420_mcbsp_hwmod_class,
+ .mpu_irqs = omap2420_mcbsp1_irqs,
+ .sdma_reqs = omap2_mcbsp1_sdma_reqs,
+ .main_clk = "mcbsp1_fck",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT5_SHIFT,
+ .module_bit = OMAP24XX_EN_MCBSP1_SHIFT,
.module_offs = CORE_MOD,
.idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
+ .idlest_idle_bit = OMAP24XX_ST_MCBSP1_SHIFT,
},
},
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2420_timer5_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_timer5_slaves),
- .class = &omap2xxx_timer_hwmod_class,
};
-
-/* timer6 */
-static struct omap_hwmod omap2420_timer6_hwmod;
-
-/* l4_core -> timer6 */
-static struct omap_hwmod_ocp_if omap2420_l4_core__timer6 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_timer6_hwmod,
- .clk = "gpt6_ick",
- .addr = omap2xxx_timer6_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer6 slave port */
-static struct omap_hwmod_ocp_if *omap2420_timer6_slaves[] = {
- &omap2420_l4_core__timer6,
+/* mcbsp2 */
+static struct omap_hwmod_irq_info omap2420_mcbsp2_irqs[] = {
+ { .name = "tx", .irq = 62 },
+ { .name = "rx", .irq = 63 },
+ { .irq = -1 }
};
-/* timer6 hwmod */
-static struct omap_hwmod omap2420_timer6_hwmod = {
- .name = "timer6",
- .mpu_irqs = omap2_timer6_mpu_irqs,
- .main_clk = "gpt6_fck",
+static struct omap_hwmod omap2420_mcbsp2_hwmod = {
+ .name = "mcbsp2",
+ .class = &omap2420_mcbsp_hwmod_class,
+ .mpu_irqs = omap2420_mcbsp2_irqs,
+ .sdma_reqs = omap2_mcbsp2_sdma_reqs,
+ .main_clk = "mcbsp2_fck",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT6_SHIFT,
+ .module_bit = OMAP24XX_EN_MCBSP2_SHIFT,
.module_offs = CORE_MOD,
.idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
+ .idlest_idle_bit = OMAP24XX_ST_MCBSP2_SHIFT,
},
},
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2420_timer6_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_timer6_slaves),
- .class = &omap2xxx_timer_hwmod_class,
};
-/* timer7 */
-static struct omap_hwmod omap2420_timer7_hwmod;
-
-/* l4_core -> timer7 */
-static struct omap_hwmod_ocp_if omap2420_l4_core__timer7 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_timer7_hwmod,
- .clk = "gpt7_ick",
- .addr = omap2xxx_timer7_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer7 slave port */
-static struct omap_hwmod_ocp_if *omap2420_timer7_slaves[] = {
- &omap2420_l4_core__timer7,
+static struct omap_hwmod_class_sysconfig omap2420_msdi_sysc = {
+ .rev_offs = 0x3c,
+ .sysc_offs = 0x64,
+ .syss_offs = 0x68,
+ .sysc_flags = (SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+ .sysc_fields = &omap_hwmod_sysc_type1,
};
-/* timer7 hwmod */
-static struct omap_hwmod omap2420_timer7_hwmod = {
- .name = "timer7",
- .mpu_irqs = omap2_timer7_mpu_irqs,
- .main_clk = "gpt7_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT7_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
- },
- },
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2420_timer7_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_timer7_slaves),
- .class = &omap2xxx_timer_hwmod_class,
+static struct omap_hwmod_class omap2420_msdi_hwmod_class = {
+ .name = "msdi",
+ .sysc = &omap2420_msdi_sysc,
+ .reset = &omap_msdi_reset,
};
-/* timer8 */
-static struct omap_hwmod omap2420_timer8_hwmod;
-
-/* l4_core -> timer8 */
-static struct omap_hwmod_ocp_if omap2420_l4_core__timer8 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_timer8_hwmod,
- .clk = "gpt8_ick",
- .addr = omap2xxx_timer8_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
+/* msdi1 */
+static struct omap_hwmod_irq_info omap2420_msdi1_irqs[] = {
+ { .irq = 83 },
+ { .irq = -1 }
};
-/* timer8 slave port */
-static struct omap_hwmod_ocp_if *omap2420_timer8_slaves[] = {
- &omap2420_l4_core__timer8,
+static struct omap_hwmod_dma_info omap2420_msdi1_sdma_reqs[] = {
+ { .name = "tx", .dma_req = 61 }, /* OMAP24XX_DMA_MMC1_TX */
+ { .name = "rx", .dma_req = 62 }, /* OMAP24XX_DMA_MMC1_RX */
+ { .dma_req = -1 }
};
-/* timer8 hwmod */
-static struct omap_hwmod omap2420_timer8_hwmod = {
- .name = "timer8",
- .mpu_irqs = omap2_timer8_mpu_irqs,
- .main_clk = "gpt8_fck",
+static struct omap_hwmod omap2420_msdi1_hwmod = {
+ .name = "msdi1",
+ .class = &omap2420_msdi_hwmod_class,
+ .mpu_irqs = omap2420_msdi1_irqs,
+ .sdma_reqs = omap2420_msdi1_sdma_reqs,
+ .main_clk = "mmc_fck",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT8_SHIFT,
+ .module_bit = OMAP2420_EN_MMC_SHIFT,
.module_offs = CORE_MOD,
.idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
+ .idlest_idle_bit = OMAP2420_ST_MMC_SHIFT,
},
},
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2420_timer8_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_timer8_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* timer9 */
-static struct omap_hwmod omap2420_timer9_hwmod;
-
-/* l4_core -> timer9 */
-static struct omap_hwmod_ocp_if omap2420_l4_core__timer9 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_timer9_hwmod,
- .clk = "gpt9_ick",
- .addr = omap2xxx_timer9_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer9 slave port */
-static struct omap_hwmod_ocp_if *omap2420_timer9_slaves[] = {
- &omap2420_l4_core__timer9,
+ .flags = HWMOD_16BIT_REG,
};
-/* timer9 hwmod */
-static struct omap_hwmod omap2420_timer9_hwmod = {
- .name = "timer9",
- .mpu_irqs = omap2_timer9_mpu_irqs,
- .main_clk = "gpt9_fck",
+/* HDQ1W/1-wire */
+static struct omap_hwmod omap2420_hdq1w_hwmod = {
+ .name = "hdq1w",
+ .mpu_irqs = omap2_hdq1w_mpu_irqs,
+ .main_clk = "hdq_fck",
.prcm = {
.omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT9_SHIFT,
.module_offs = CORE_MOD,
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_HDQ_SHIFT,
.idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
+ .idlest_idle_bit = OMAP24XX_ST_HDQ_SHIFT,
},
},
- .dev_attr = &capability_pwm_dev_attr,
- .slaves = omap2420_timer9_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_timer9_slaves),
- .class = &omap2xxx_timer_hwmod_class,
+ .class = &omap2_hdq1w_class,
};
-/* timer10 */
-static struct omap_hwmod omap2420_timer10_hwmod;
+/*
+ * interfaces
+ */
-/* l4_core -> timer10 */
-static struct omap_hwmod_ocp_if omap2420_l4_core__timer10 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_timer10_hwmod,
- .clk = "gpt10_ick",
- .addr = omap2_timer10_addrs,
+/* L4 CORE -> I2C1 interface */
+static struct omap_hwmod_ocp_if omap2420_l4_core__i2c1 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2420_i2c1_hwmod,
+ .clk = "i2c1_ick",
+ .addr = omap2_i2c1_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* timer10 slave port */
-static struct omap_hwmod_ocp_if *omap2420_timer10_slaves[] = {
- &omap2420_l4_core__timer10,
-};
-
-/* timer10 hwmod */
-static struct omap_hwmod omap2420_timer10_hwmod = {
- .name = "timer10",
- .mpu_irqs = omap2_timer10_mpu_irqs,
- .main_clk = "gpt10_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT10_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
- },
- },
- .dev_attr = &capability_pwm_dev_attr,
- .slaves = omap2420_timer10_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_timer10_slaves),
- .class = &omap2xxx_timer_hwmod_class,
+/* L4 CORE -> I2C2 interface */
+static struct omap_hwmod_ocp_if omap2420_l4_core__i2c2 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2420_i2c2_hwmod,
+ .clk = "i2c2_ick",
+ .addr = omap2_i2c2_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* timer11 */
-static struct omap_hwmod omap2420_timer11_hwmod;
-
-/* l4_core -> timer11 */
-static struct omap_hwmod_ocp_if omap2420_l4_core__timer11 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_timer11_hwmod,
- .clk = "gpt11_ick",
- .addr = omap2_timer11_addrs,
+/* IVA <- L3 interface */
+static struct omap_hwmod_ocp_if omap2420_l3__iva = {
+ .master = &omap2xxx_l3_main_hwmod,
+ .slave = &omap2420_iva_hwmod,
+ .clk = "core_l3_ck",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* timer11 slave port */
-static struct omap_hwmod_ocp_if *omap2420_timer11_slaves[] = {
- &omap2420_l4_core__timer11,
+/* DSP <- L3 interface */
+static struct omap_hwmod_ocp_if omap2420_l3__dsp = {
+ .master = &omap2xxx_l3_main_hwmod,
+ .slave = &omap2420_dsp_hwmod,
+ .clk = "dsp_ick",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* timer11 hwmod */
-static struct omap_hwmod omap2420_timer11_hwmod = {
- .name = "timer11",
- .mpu_irqs = omap2_timer11_mpu_irqs,
- .main_clk = "gpt11_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT11_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
- },
+static struct omap_hwmod_addr_space omap2420_timer1_addrs[] = {
+ {
+ .pa_start = 0x48028000,
+ .pa_end = 0x48028000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
},
- .dev_attr = &capability_pwm_dev_attr,
- .slaves = omap2420_timer11_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_timer11_slaves),
- .class = &omap2xxx_timer_hwmod_class,
+ { }
};
-/* timer12 */
-static struct omap_hwmod omap2420_timer12_hwmod;
-
-/* l4_core -> timer12 */
-static struct omap_hwmod_ocp_if omap2420_l4_core__timer12 = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_timer12_hwmod,
- .clk = "gpt12_ick",
- .addr = omap2xxx_timer12_addrs,
+/* l4_wkup -> timer1 */
+static struct omap_hwmod_ocp_if omap2420_l4_wkup__timer1 = {
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_timer1_hwmod,
+ .clk = "gpt1_ick",
+ .addr = omap2420_timer1_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* timer12 slave port */
-static struct omap_hwmod_ocp_if *omap2420_timer12_slaves[] = {
- &omap2420_l4_core__timer12,
-};
-
-/* timer12 hwmod */
-static struct omap_hwmod omap2420_timer12_hwmod = {
- .name = "timer12",
- .mpu_irqs = omap2xxx_timer12_mpu_irqs,
- .main_clk = "gpt12_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT12_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
- },
- },
- .dev_attr = &capability_pwm_dev_attr,
- .slaves = omap2420_timer12_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_timer12_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
/* l4_wkup -> wd_timer2 */
static struct omap_hwmod_addr_space omap2420_wd_timer2_addrs[] = {
{
@@ -744,363 +368,13 @@ static struct omap_hwmod_addr_space omap2420_wd_timer2_addrs[] = {
};
static struct omap_hwmod_ocp_if omap2420_l4_wkup__wd_timer2 = {
- .master = &omap2420_l4_wkup_hwmod,
- .slave = &omap2420_wd_timer2_hwmod,
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_wd_timer2_hwmod,
.clk = "mpu_wdt_ick",
.addr = omap2420_wd_timer2_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* wd_timer2 */
-static struct omap_hwmod_ocp_if *omap2420_wd_timer2_slaves[] = {
- &omap2420_l4_wkup__wd_timer2,
-};
-
-static struct omap_hwmod omap2420_wd_timer2_hwmod = {
- .name = "wd_timer2",
- .class = &omap2xxx_wd_timer_hwmod_class,
- .main_clk = "mpu_wdt_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
- .module_offs = WKUP_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_MPU_WDT_SHIFT,
- },
- },
- .slaves = omap2420_wd_timer2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_wd_timer2_slaves),
-};
-
-/* UART1 */
-
-static struct omap_hwmod_ocp_if *omap2420_uart1_slaves[] = {
- &omap2_l4_core__uart1,
-};
-
-static struct omap_hwmod omap2420_uart1_hwmod = {
- .name = "uart1",
- .mpu_irqs = omap2_uart1_mpu_irqs,
- .sdma_reqs = omap2_uart1_sdma_reqs,
- .main_clk = "uart1_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_UART1_SHIFT,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT,
- },
- },
- .slaves = omap2420_uart1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_uart1_slaves),
- .class = &omap2_uart_class,
-};
-
-/* UART2 */
-
-static struct omap_hwmod_ocp_if *omap2420_uart2_slaves[] = {
- &omap2_l4_core__uart2,
-};
-
-static struct omap_hwmod omap2420_uart2_hwmod = {
- .name = "uart2",
- .mpu_irqs = omap2_uart2_mpu_irqs,
- .sdma_reqs = omap2_uart2_sdma_reqs,
- .main_clk = "uart2_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_UART2_SHIFT,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT,
- },
- },
- .slaves = omap2420_uart2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_uart2_slaves),
- .class = &omap2_uart_class,
-};
-
-/* UART3 */
-
-static struct omap_hwmod_ocp_if *omap2420_uart3_slaves[] = {
- &omap2_l4_core__uart3,
-};
-
-static struct omap_hwmod omap2420_uart3_hwmod = {
- .name = "uart3",
- .mpu_irqs = omap2_uart3_mpu_irqs,
- .sdma_reqs = omap2_uart3_sdma_reqs,
- .main_clk = "uart3_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .prcm_reg_id = 2,
- .module_bit = OMAP24XX_EN_UART3_SHIFT,
- .idlest_reg_id = 2,
- .idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT,
- },
- },
- .slaves = omap2420_uart3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_uart3_slaves),
- .class = &omap2_uart_class,
-};
-
-/* dss */
-/* dss master ports */
-static struct omap_hwmod_ocp_if *omap2420_dss_masters[] = {
- &omap2420_dss__l3,
-};
-
-/* l4_core -> dss */
-static struct omap_hwmod_ocp_if omap2420_l4_core__dss = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_dss_core_hwmod,
- .clk = "dss_ick",
- .addr = omap2_dss_addrs,
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
- .flags = OMAP_FIREWALL_L4,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss slave ports */
-static struct omap_hwmod_ocp_if *omap2420_dss_slaves[] = {
- &omap2420_l4_core__dss,
-};
-
-static struct omap_hwmod_opt_clk dss_opt_clks[] = {
- /*
- * The DSS HW needs all DSS clocks enabled during reset. The dss_core
- * driver does not use these clocks.
- */
- { .role = "tv_clk", .clk = "dss_54m_fck" },
- { .role = "sys_clk", .clk = "dss2_fck" },
-};
-
-static struct omap_hwmod omap2420_dss_core_hwmod = {
- .name = "dss_core",
- .class = &omap2_dss_hwmod_class,
- .main_clk = "dss1_fck", /* instead of dss_fck */
- .sdma_reqs = omap2xxx_dss_sdma_chs,
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_DSS1_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
- },
- },
- .opt_clks = dss_opt_clks,
- .opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
- .slaves = omap2420_dss_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_dss_slaves),
- .masters = omap2420_dss_masters,
- .masters_cnt = ARRAY_SIZE(omap2420_dss_masters),
- .flags = HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-};
-
-/* l4_core -> dss_dispc */
-static struct omap_hwmod_ocp_if omap2420_l4_core__dss_dispc = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_dss_dispc_hwmod,
- .clk = "dss_ick",
- .addr = omap2_dss_dispc_addrs,
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP2420_L4_CORE_FW_DSS_DISPC_REGION,
- .flags = OMAP_FIREWALL_L4,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss_dispc slave ports */
-static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = {
- &omap2420_l4_core__dss_dispc,
-};
-
-static struct omap_hwmod omap2420_dss_dispc_hwmod = {
- .name = "dss_dispc",
- .class = &omap2_dispc_hwmod_class,
- .mpu_irqs = omap2_dispc_irqs,
- .main_clk = "dss1_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_DSS1_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
- },
- },
- .slaves = omap2420_dss_dispc_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_dss_dispc_slaves),
- .flags = HWMOD_NO_IDLEST,
- .dev_attr = &omap2_3_dss_dispc_dev_attr
-};
-
-/* l4_core -> dss_rfbi */
-static struct omap_hwmod_ocp_if omap2420_l4_core__dss_rfbi = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_dss_rfbi_hwmod,
- .clk = "dss_ick",
- .addr = omap2_dss_rfbi_addrs,
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
- .flags = OMAP_FIREWALL_L4,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss_rfbi slave ports */
-static struct omap_hwmod_ocp_if *omap2420_dss_rfbi_slaves[] = {
- &omap2420_l4_core__dss_rfbi,
-};
-
-static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
- { .role = "ick", .clk = "dss_ick" },
-};
-
-static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
- .name = "dss_rfbi",
- .class = &omap2_rfbi_hwmod_class,
- .main_clk = "dss1_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_DSS1_SHIFT,
- .module_offs = CORE_MOD,
- },
- },
- .opt_clks = dss_rfbi_opt_clks,
- .opt_clks_cnt = ARRAY_SIZE(dss_rfbi_opt_clks),
- .slaves = omap2420_dss_rfbi_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_dss_rfbi_slaves),
- .flags = HWMOD_NO_IDLEST,
-};
-
-/* l4_core -> dss_venc */
-static struct omap_hwmod_ocp_if omap2420_l4_core__dss_venc = {
- .master = &omap2420_l4_core_hwmod,
- .slave = &omap2420_dss_venc_hwmod,
- .clk = "dss_ick",
- .addr = omap2_dss_venc_addrs,
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP2420_L4_CORE_FW_DSS_VENC_REGION,
- .flags = OMAP_FIREWALL_L4,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss_venc slave ports */
-static struct omap_hwmod_ocp_if *omap2420_dss_venc_slaves[] = {
- &omap2420_l4_core__dss_venc,
-};
-
-static struct omap_hwmod omap2420_dss_venc_hwmod = {
- .name = "dss_venc",
- .class = &omap2_venc_hwmod_class,
- .main_clk = "dss_54m_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_DSS1_SHIFT,
- .module_offs = CORE_MOD,
- },
- },
- .slaves = omap2420_dss_venc_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_dss_venc_slaves),
- .flags = HWMOD_NO_IDLEST,
-};
-
-/* I2C common */
-static struct omap_hwmod_class_sysconfig i2c_sysc = {
- .rev_offs = 0x00,
- .sysc_offs = 0x20,
- .syss_offs = 0x10,
- .sysc_flags = (SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class i2c_class = {
- .name = "i2c",
- .sysc = &i2c_sysc,
- .rev = OMAP_I2C_IP_VERSION_1,
- .reset = &omap_i2c_reset,
-};
-
-static struct omap_i2c_dev_attr i2c_dev_attr = {
- .flags = OMAP_I2C_FLAG_NO_FIFO |
- OMAP_I2C_FLAG_SIMPLE_CLOCK |
- OMAP_I2C_FLAG_16BIT_DATA_REG |
- OMAP_I2C_FLAG_BUS_SHIFT_2,
-};
-
-/* I2C1 */
-
-static struct omap_hwmod_ocp_if *omap2420_i2c1_slaves[] = {
- &omap2420_l4_core__i2c1,
-};
-
-static struct omap_hwmod omap2420_i2c1_hwmod = {
- .name = "i2c1",
- .mpu_irqs = omap2_i2c1_mpu_irqs,
- .sdma_reqs = omap2_i2c1_sdma_reqs,
- .main_clk = "i2c1_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .prcm_reg_id = 1,
- .module_bit = OMAP2420_EN_I2C1_SHIFT,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP2420_ST_I2C1_SHIFT,
- },
- },
- .slaves = omap2420_i2c1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_i2c1_slaves),
- .class = &i2c_class,
- .dev_attr = &i2c_dev_attr,
- .flags = HWMOD_16BIT_REG,
-};
-
-/* I2C2 */
-
-static struct omap_hwmod_ocp_if *omap2420_i2c2_slaves[] = {
- &omap2420_l4_core__i2c2,
-};
-
-static struct omap_hwmod omap2420_i2c2_hwmod = {
- .name = "i2c2",
- .mpu_irqs = omap2_i2c2_mpu_irqs,
- .sdma_reqs = omap2_i2c2_sdma_reqs,
- .main_clk = "i2c2_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .prcm_reg_id = 1,
- .module_bit = OMAP2420_EN_I2C2_SHIFT,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP2420_ST_I2C2_SHIFT,
- },
- },
- .slaves = omap2420_i2c2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_i2c2_slaves),
- .class = &i2c_class,
- .dev_attr = &i2c_dev_attr,
- .flags = HWMOD_16BIT_REG,
-};
-
/* l4_wkup -> gpio1 */
static struct omap_hwmod_addr_space omap2420_gpio1_addr_space[] = {
{
@@ -1112,8 +386,8 @@ static struct omap_hwmod_addr_space omap2420_gpio1_addr_space[] = {
};
static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio1 = {
- .master = &omap2420_l4_wkup_hwmod,
- .slave = &omap2420_gpio1_hwmod,
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_gpio1_hwmod,
.clk = "gpios_ick",
.addr = omap2420_gpio1_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
@@ -1130,8 +404,8 @@ static struct omap_hwmod_addr_space omap2420_gpio2_addr_space[] = {
};
static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio2 = {
- .master = &omap2420_l4_wkup_hwmod,
- .slave = &omap2420_gpio2_hwmod,
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_gpio2_hwmod,
.clk = "gpios_ick",
.addr = omap2420_gpio2_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
@@ -1148,8 +422,8 @@ static struct omap_hwmod_addr_space omap2420_gpio3_addr_space[] = {
};
static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio3 = {
- .master = &omap2420_l4_wkup_hwmod,
- .slave = &omap2420_gpio3_hwmod,
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_gpio3_hwmod,
.clk = "gpios_ick",
.addr = omap2420_gpio3_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
@@ -1166,408 +440,150 @@ static struct omap_hwmod_addr_space omap2420_gpio4_addr_space[] = {
};
static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio4 = {
- .master = &omap2420_l4_wkup_hwmod,
- .slave = &omap2420_gpio4_hwmod,
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_gpio4_hwmod,
.clk = "gpios_ick",
.addr = omap2420_gpio4_addr_space,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* gpio dev_attr */
-static struct omap_gpio_dev_attr gpio_dev_attr = {
- .bank_width = 32,
- .dbck_flag = false,
-};
-
-/* gpio1 */
-static struct omap_hwmod_ocp_if *omap2420_gpio1_slaves[] = {
- &omap2420_l4_wkup__gpio1,
-};
-
-static struct omap_hwmod omap2420_gpio1_hwmod = {
- .name = "gpio1",
- .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap2_gpio1_irqs,
- .main_clk = "gpios_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .module_offs = WKUP_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
- },
- },
- .slaves = omap2420_gpio1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_gpio1_slaves),
- .class = &omap2xxx_gpio_hwmod_class,
- .dev_attr = &gpio_dev_attr,
-};
-
-/* gpio2 */
-static struct omap_hwmod_ocp_if *omap2420_gpio2_slaves[] = {
- &omap2420_l4_wkup__gpio2,
-};
-
-static struct omap_hwmod omap2420_gpio2_hwmod = {
- .name = "gpio2",
- .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap2_gpio2_irqs,
- .main_clk = "gpios_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .module_offs = WKUP_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
- },
- },
- .slaves = omap2420_gpio2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_gpio2_slaves),
- .class = &omap2xxx_gpio_hwmod_class,
- .dev_attr = &gpio_dev_attr,
-};
-
-/* gpio3 */
-static struct omap_hwmod_ocp_if *omap2420_gpio3_slaves[] = {
- &omap2420_l4_wkup__gpio3,
-};
-
-static struct omap_hwmod omap2420_gpio3_hwmod = {
- .name = "gpio3",
- .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap2_gpio3_irqs,
- .main_clk = "gpios_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .module_offs = WKUP_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
- },
- },
- .slaves = omap2420_gpio3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_gpio3_slaves),
- .class = &omap2xxx_gpio_hwmod_class,
- .dev_attr = &gpio_dev_attr,
-};
-
-/* gpio4 */
-static struct omap_hwmod_ocp_if *omap2420_gpio4_slaves[] = {
- &omap2420_l4_wkup__gpio4,
-};
-
-static struct omap_hwmod omap2420_gpio4_hwmod = {
- .name = "gpio4",
- .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap2_gpio4_irqs,
- .main_clk = "gpios_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .module_offs = WKUP_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
- },
- },
- .slaves = omap2420_gpio4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_gpio4_slaves),
- .class = &omap2xxx_gpio_hwmod_class,
- .dev_attr = &gpio_dev_attr,
-};
-
-/* dma attributes */
-static struct omap_dma_dev_attr dma_dev_attr = {
- .dev_caps = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
- IS_CSSA_32 | IS_CDSA_32,
- .lch_count = 32,
-};
-
/* dma_system -> L3 */
static struct omap_hwmod_ocp_if omap2420_dma_system__l3 = {
.master = &omap2420_dma_system_hwmod,
- .slave = &omap2420_l3_main_hwmod,
+ .slave = &omap2xxx_l3_main_hwmod,
.clk = "core_l3_ck",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* dma_system master ports */
-static struct omap_hwmod_ocp_if *omap2420_dma_system_masters[] = {
- &omap2420_dma_system__l3,
-};
-
/* l4_core -> dma_system */
static struct omap_hwmod_ocp_if omap2420_l4_core__dma_system = {
- .master = &omap2420_l4_core_hwmod,
+ .master = &omap2xxx_l4_core_hwmod,
.slave = &omap2420_dma_system_hwmod,
.clk = "sdma_ick",
.addr = omap2_dma_system_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* dma_system slave ports */
-static struct omap_hwmod_ocp_if *omap2420_dma_system_slaves[] = {
- &omap2420_l4_core__dma_system,
-};
-
-static struct omap_hwmod omap2420_dma_system_hwmod = {
- .name = "dma",
- .class = &omap2xxx_dma_hwmod_class,
- .mpu_irqs = omap2_dma_system_irqs,
- .main_clk = "core_l3_ck",
- .slaves = omap2420_dma_system_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_dma_system_slaves),
- .masters = omap2420_dma_system_masters,
- .masters_cnt = ARRAY_SIZE(omap2420_dma_system_masters),
- .dev_attr = &dma_dev_attr,
- .flags = HWMOD_NO_IDLEST,
-};
-
-/* mailbox */
-static struct omap_hwmod omap2420_mailbox_hwmod;
-static struct omap_hwmod_irq_info omap2420_mailbox_irqs[] = {
- { .name = "dsp", .irq = 26 },
- { .name = "iva", .irq = 34 },
- { .irq = -1 }
-};
-
/* l4_core -> mailbox */
static struct omap_hwmod_ocp_if omap2420_l4_core__mailbox = {
- .master = &omap2420_l4_core_hwmod,
+ .master = &omap2xxx_l4_core_hwmod,
.slave = &omap2420_mailbox_hwmod,
.addr = omap2_mailbox_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* mailbox slave ports */
-static struct omap_hwmod_ocp_if *omap2420_mailbox_slaves[] = {
- &omap2420_l4_core__mailbox,
-};
-
-static struct omap_hwmod omap2420_mailbox_hwmod = {
- .name = "mailbox",
- .class = &omap2xxx_mailbox_hwmod_class,
- .mpu_irqs = omap2420_mailbox_irqs,
- .main_clk = "mailboxes_ick",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_MAILBOXES_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
- },
- },
- .slaves = omap2420_mailbox_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_mailbox_slaves),
-};
-
-/* mcspi1 */
-static struct omap_hwmod_ocp_if *omap2420_mcspi1_slaves[] = {
- &omap2420_l4_core__mcspi1,
-};
-
-static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
- .num_chipselect = 4,
-};
-
-static struct omap_hwmod omap2420_mcspi1_hwmod = {
- .name = "mcspi1_hwmod",
- .mpu_irqs = omap2_mcspi1_mpu_irqs,
- .sdma_reqs = omap2_mcspi1_sdma_reqs,
- .main_clk = "mcspi1_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_MCSPI1_SHIFT,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_MCSPI1_SHIFT,
- },
- },
- .slaves = omap2420_mcspi1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_mcspi1_slaves),
- .class = &omap2xxx_mcspi_class,
- .dev_attr = &omap_mcspi1_dev_attr,
-};
-
-/* mcspi2 */
-static struct omap_hwmod_ocp_if *omap2420_mcspi2_slaves[] = {
- &omap2420_l4_core__mcspi2,
-};
-
-static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
- .num_chipselect = 2,
-};
-
-static struct omap_hwmod omap2420_mcspi2_hwmod = {
- .name = "mcspi2_hwmod",
- .mpu_irqs = omap2_mcspi2_mpu_irqs,
- .sdma_reqs = omap2_mcspi2_sdma_reqs,
- .main_clk = "mcspi2_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_MCSPI2_SHIFT,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_MCSPI2_SHIFT,
- },
- },
- .slaves = omap2420_mcspi2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_mcspi2_slaves),
- .class = &omap2xxx_mcspi_class,
- .dev_attr = &omap_mcspi2_dev_attr,
-};
-
-/*
- * 'mcbsp' class
- * multi channel buffered serial port controller
- */
-
-static struct omap_hwmod_class omap2420_mcbsp_hwmod_class = {
- .name = "mcbsp",
-};
-
-/* mcbsp1 */
-static struct omap_hwmod_irq_info omap2420_mcbsp1_irqs[] = {
- { .name = "tx", .irq = 59 },
- { .name = "rx", .irq = 60 },
- { .irq = -1 }
-};
-
/* l4_core -> mcbsp1 */
static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp1 = {
- .master = &omap2420_l4_core_hwmod,
+ .master = &omap2xxx_l4_core_hwmod,
.slave = &omap2420_mcbsp1_hwmod,
.clk = "mcbsp1_ick",
.addr = omap2_mcbsp1_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* mcbsp1 slave ports */
-static struct omap_hwmod_ocp_if *omap2420_mcbsp1_slaves[] = {
- &omap2420_l4_core__mcbsp1,
-};
-
-static struct omap_hwmod omap2420_mcbsp1_hwmod = {
- .name = "mcbsp1",
- .class = &omap2420_mcbsp_hwmod_class,
- .mpu_irqs = omap2420_mcbsp1_irqs,
- .sdma_reqs = omap2_mcbsp1_sdma_reqs,
- .main_clk = "mcbsp1_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_MCBSP1_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_MCBSP1_SHIFT,
- },
- },
- .slaves = omap2420_mcbsp1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_mcbsp1_slaves),
-};
-
-/* mcbsp2 */
-static struct omap_hwmod_irq_info omap2420_mcbsp2_irqs[] = {
- { .name = "tx", .irq = 62 },
- { .name = "rx", .irq = 63 },
- { .irq = -1 }
-};
-
/* l4_core -> mcbsp2 */
static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp2 = {
- .master = &omap2420_l4_core_hwmod,
+ .master = &omap2xxx_l4_core_hwmod,
.slave = &omap2420_mcbsp2_hwmod,
.clk = "mcbsp2_ick",
.addr = omap2xxx_mcbsp2_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* mcbsp2 slave ports */
-static struct omap_hwmod_ocp_if *omap2420_mcbsp2_slaves[] = {
- &omap2420_l4_core__mcbsp2,
-};
-
-static struct omap_hwmod omap2420_mcbsp2_hwmod = {
- .name = "mcbsp2",
- .class = &omap2420_mcbsp_hwmod_class,
- .mpu_irqs = omap2420_mcbsp2_irqs,
- .sdma_reqs = omap2_mcbsp2_sdma_reqs,
- .main_clk = "mcbsp2_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_MCBSP2_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_MCBSP2_SHIFT,
- },
+static struct omap_hwmod_addr_space omap2420_msdi1_addrs[] = {
+ {
+ .pa_start = 0x4809c000,
+ .pa_end = 0x4809c000 + SZ_128 - 1,
+ .flags = ADDR_TYPE_RT,
},
- .slaves = omap2420_mcbsp2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2420_mcbsp2_slaves),
+ { }
};
-static __initdata struct omap_hwmod *omap2420_hwmods[] = {
- &omap2420_l3_main_hwmod,
- &omap2420_l4_core_hwmod,
- &omap2420_l4_wkup_hwmod,
- &omap2420_mpu_hwmod,
- &omap2420_iva_hwmod,
-
- &omap2420_timer1_hwmod,
- &omap2420_timer2_hwmod,
- &omap2420_timer3_hwmod,
- &omap2420_timer4_hwmod,
- &omap2420_timer5_hwmod,
- &omap2420_timer6_hwmod,
- &omap2420_timer7_hwmod,
- &omap2420_timer8_hwmod,
- &omap2420_timer9_hwmod,
- &omap2420_timer10_hwmod,
- &omap2420_timer11_hwmod,
- &omap2420_timer12_hwmod,
-
- &omap2420_wd_timer2_hwmod,
- &omap2420_uart1_hwmod,
- &omap2420_uart2_hwmod,
- &omap2420_uart3_hwmod,
- /* dss class */
- &omap2420_dss_core_hwmod,
- &omap2420_dss_dispc_hwmod,
- &omap2420_dss_rfbi_hwmod,
- &omap2420_dss_venc_hwmod,
- /* i2c class */
- &omap2420_i2c1_hwmod,
- &omap2420_i2c2_hwmod,
+/* l4_core -> msdi1 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__msdi1 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2420_msdi1_hwmod,
+ .clk = "mmc_ick",
+ .addr = omap2420_msdi1_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
- /* gpio class */
- &omap2420_gpio1_hwmod,
- &omap2420_gpio2_hwmod,
- &omap2420_gpio3_hwmod,
- &omap2420_gpio4_hwmod,
+/* l4_core -> hdq1w interface */
+static struct omap_hwmod_ocp_if omap2420_l4_core__hdq1w = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2420_hdq1w_hwmod,
+ .clk = "hdq_ick",
+ .addr = omap2_hdq1w_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ .flags = OMAP_FIREWALL_L4 | OCPIF_SWSUP_IDLE,
+};
- /* dma_system class*/
- &omap2420_dma_system_hwmod,
- /* mailbox class */
- &omap2420_mailbox_hwmod,
+/* l4_wkup -> 32ksync_counter */
+static struct omap_hwmod_addr_space omap2420_counter_32k_addrs[] = {
+ {
+ .pa_start = 0x48004000,
+ .pa_end = 0x4800401f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
- /* mcbsp class */
- &omap2420_mcbsp1_hwmod,
- &omap2420_mcbsp2_hwmod,
+static struct omap_hwmod_ocp_if omap2420_l4_wkup__counter_32k = {
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_counter_32k_hwmod,
+ .clk = "sync_32k_ick",
+ .addr = omap2420_counter_32k_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
- /* mcspi class */
- &omap2420_mcspi1_hwmod,
- &omap2420_mcspi2_hwmod,
+static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
+ &omap2xxx_l3_main__l4_core,
+ &omap2xxx_mpu__l3_main,
+ &omap2xxx_dss__l3,
+ &omap2xxx_l4_core__mcspi1,
+ &omap2xxx_l4_core__mcspi2,
+ &omap2xxx_l4_core__l4_wkup,
+ &omap2_l4_core__uart1,
+ &omap2_l4_core__uart2,
+ &omap2_l4_core__uart3,
+ &omap2420_l4_core__i2c1,
+ &omap2420_l4_core__i2c2,
+ &omap2420_l3__iva,
+ &omap2420_l3__dsp,
+ &omap2420_l4_wkup__timer1,
+ &omap2xxx_l4_core__timer2,
+ &omap2xxx_l4_core__timer3,
+ &omap2xxx_l4_core__timer4,
+ &omap2xxx_l4_core__timer5,
+ &omap2xxx_l4_core__timer6,
+ &omap2xxx_l4_core__timer7,
+ &omap2xxx_l4_core__timer8,
+ &omap2xxx_l4_core__timer9,
+ &omap2xxx_l4_core__timer10,
+ &omap2xxx_l4_core__timer11,
+ &omap2xxx_l4_core__timer12,
+ &omap2420_l4_wkup__wd_timer2,
+ &omap2xxx_l4_core__dss,
+ &omap2xxx_l4_core__dss_dispc,
+ &omap2xxx_l4_core__dss_rfbi,
+ &omap2xxx_l4_core__dss_venc,
+ &omap2420_l4_wkup__gpio1,
+ &omap2420_l4_wkup__gpio2,
+ &omap2420_l4_wkup__gpio3,
+ &omap2420_l4_wkup__gpio4,
+ &omap2420_dma_system__l3,
+ &omap2420_l4_core__dma_system,
+ &omap2420_l4_core__mailbox,
+ &omap2420_l4_core__mcbsp1,
+ &omap2420_l4_core__mcbsp2,
+ &omap2420_l4_core__msdi1,
+ &omap2420_l4_core__hdq1w,
+ &omap2420_l4_wkup__counter_32k,
NULL,
};
int __init omap2420_hwmod_init(void)
{
- return omap_hwmod_register(omap2420_hwmods);
+ return omap_hwmod_register_links(omap2420_hwmod_ocp_ifs);
}
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 04a3885f4475..4d7264981230 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -2,6 +2,7 @@
* omap_hwmod_2430_data.c - hardware modules present on the OMAP2430 chips
*
* Copyright (C) 2009-2011 Nokia Corporation
+ * Copyright (C) 2012 Texas Instruments, Inc.
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
@@ -33,1044 +34,29 @@
/*
* OMAP2430 hardware module integration data
*
- * ALl of the data in this section should be autogeneratable from the
+ * All of the data in this section should be autogeneratable from the
* TI hardware database or other technical documentation. Data that
* is driver-specific or driver-kernel integration-specific belongs
* elsewhere.
*/
-static struct omap_hwmod omap2430_mpu_hwmod;
-static struct omap_hwmod omap2430_iva_hwmod;
-static struct omap_hwmod omap2430_l3_main_hwmod;
-static struct omap_hwmod omap2430_l4_core_hwmod;
-static struct omap_hwmod omap2430_dss_core_hwmod;
-static struct omap_hwmod omap2430_dss_dispc_hwmod;
-static struct omap_hwmod omap2430_dss_rfbi_hwmod;
-static struct omap_hwmod omap2430_dss_venc_hwmod;
-static struct omap_hwmod omap2430_wd_timer2_hwmod;
-static struct omap_hwmod omap2430_gpio1_hwmod;
-static struct omap_hwmod omap2430_gpio2_hwmod;
-static struct omap_hwmod omap2430_gpio3_hwmod;
-static struct omap_hwmod omap2430_gpio4_hwmod;
-static struct omap_hwmod omap2430_gpio5_hwmod;
-static struct omap_hwmod omap2430_dma_system_hwmod;
-static struct omap_hwmod omap2430_mcbsp1_hwmod;
-static struct omap_hwmod omap2430_mcbsp2_hwmod;
-static struct omap_hwmod omap2430_mcbsp3_hwmod;
-static struct omap_hwmod omap2430_mcbsp4_hwmod;
-static struct omap_hwmod omap2430_mcbsp5_hwmod;
-static struct omap_hwmod omap2430_mcspi1_hwmod;
-static struct omap_hwmod omap2430_mcspi2_hwmod;
-static struct omap_hwmod omap2430_mcspi3_hwmod;
-static struct omap_hwmod omap2430_mmc1_hwmod;
-static struct omap_hwmod omap2430_mmc2_hwmod;
-
-/* L3 -> L4_CORE interface */
-static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
- .master = &omap2430_l3_main_hwmod,
- .slave = &omap2430_l4_core_hwmod,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* MPU -> L3 interface */
-static struct omap_hwmod_ocp_if omap2430_mpu__l3_main = {
- .master = &omap2430_mpu_hwmod,
- .slave = &omap2430_l3_main_hwmod,
- .user = OCP_USER_MPU,
-};
-
-/* Slave interfaces on the L3 interconnect */
-static struct omap_hwmod_ocp_if *omap2430_l3_main_slaves[] = {
- &omap2430_mpu__l3_main,
-};
-
-/* DSS -> l3 */
-static struct omap_hwmod_ocp_if omap2430_dss__l3 = {
- .master = &omap2430_dss_core_hwmod,
- .slave = &omap2430_l3_main_hwmod,
- .fw = {
- .omap2 = {
- .l3_perm_bit = OMAP2_L3_CORE_FW_CONNID_DSS,
- .flags = OMAP_FIREWALL_L3,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* Master interfaces on the L3 interconnect */
-static struct omap_hwmod_ocp_if *omap2430_l3_main_masters[] = {
- &omap2430_l3_main__l4_core,
-};
-
-/* L3 */
-static struct omap_hwmod omap2430_l3_main_hwmod = {
- .name = "l3_main",
- .class = &l3_hwmod_class,
- .masters = omap2430_l3_main_masters,
- .masters_cnt = ARRAY_SIZE(omap2430_l3_main_masters),
- .slaves = omap2430_l3_main_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_l3_main_slaves),
- .flags = HWMOD_NO_IDLEST,
-};
-
-static struct omap_hwmod omap2430_l4_wkup_hwmod;
-static struct omap_hwmod omap2430_uart1_hwmod;
-static struct omap_hwmod omap2430_uart2_hwmod;
-static struct omap_hwmod omap2430_uart3_hwmod;
-static struct omap_hwmod omap2430_i2c1_hwmod;
-static struct omap_hwmod omap2430_i2c2_hwmod;
-
-static struct omap_hwmod omap2430_usbhsotg_hwmod;
-
-/* l3_core -> usbhsotg interface */
-static struct omap_hwmod_ocp_if omap2430_usbhsotg__l3 = {
- .master = &omap2430_usbhsotg_hwmod,
- .slave = &omap2430_l3_main_hwmod,
- .clk = "core_l3_ck",
- .user = OCP_USER_MPU,
-};
-
-/* L4 CORE -> I2C1 interface */
-static struct omap_hwmod_ocp_if omap2430_l4_core__i2c1 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_i2c1_hwmod,
- .clk = "i2c1_ick",
- .addr = omap2_i2c1_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> I2C2 interface */
-static struct omap_hwmod_ocp_if omap2430_l4_core__i2c2 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_i2c2_hwmod,
- .clk = "i2c2_ick",
- .addr = omap2_i2c2_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4_CORE -> L4_WKUP interface */
-static struct omap_hwmod_ocp_if omap2430_l4_core__l4_wkup = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_l4_wkup_hwmod,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> UART1 interface */
-static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_uart1_hwmod,
- .clk = "uart1_ick",
- .addr = omap2xxx_uart1_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> UART2 interface */
-static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_uart2_hwmod,
- .clk = "uart2_ick",
- .addr = omap2xxx_uart2_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 PER -> UART3 interface */
-static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_uart3_hwmod,
- .clk = "uart3_ick",
- .addr = omap2xxx_uart3_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/*
-* usbhsotg interface data
-*/
-static struct omap_hwmod_addr_space omap2430_usbhsotg_addrs[] = {
- {
- .pa_start = OMAP243X_HS_BASE,
- .pa_end = OMAP243X_HS_BASE + SZ_4K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_core ->usbhsotg interface */
-static struct omap_hwmod_ocp_if omap2430_l4_core__usbhsotg = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_usbhsotg_hwmod,
- .clk = "usb_l4_ick",
- .addr = omap2430_usbhsotg_addrs,
- .user = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if *omap2430_usbhsotg_masters[] = {
- &omap2430_usbhsotg__l3,
-};
-
-static struct omap_hwmod_ocp_if *omap2430_usbhsotg_slaves[] = {
- &omap2430_l4_core__usbhsotg,
-};
-
-/* L4 CORE -> MMC1 interface */
-static struct omap_hwmod_ocp_if omap2430_l4_core__mmc1 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_mmc1_hwmod,
- .clk = "mmchs1_ick",
- .addr = omap2430_mmc1_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> MMC2 interface */
-static struct omap_hwmod_ocp_if omap2430_l4_core__mmc2 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_mmc2_hwmod,
- .clk = "mmchs2_ick",
- .addr = omap2430_mmc2_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* Slave interfaces on the L4_CORE interconnect */
-static struct omap_hwmod_ocp_if *omap2430_l4_core_slaves[] = {
- &omap2430_l3_main__l4_core,
-};
-
-/* Master interfaces on the L4_CORE interconnect */
-static struct omap_hwmod_ocp_if *omap2430_l4_core_masters[] = {
- &omap2430_l4_core__l4_wkup,
- &omap2430_l4_core__mmc1,
- &omap2430_l4_core__mmc2,
-};
-
-/* L4 CORE */
-static struct omap_hwmod omap2430_l4_core_hwmod = {
- .name = "l4_core",
- .class = &l4_hwmod_class,
- .masters = omap2430_l4_core_masters,
- .masters_cnt = ARRAY_SIZE(omap2430_l4_core_masters),
- .slaves = omap2430_l4_core_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_l4_core_slaves),
- .flags = HWMOD_NO_IDLEST,
-};
-
-/* Slave interfaces on the L4_WKUP interconnect */
-static struct omap_hwmod_ocp_if *omap2430_l4_wkup_slaves[] = {
- &omap2430_l4_core__l4_wkup,
- &omap2_l4_core__uart1,
- &omap2_l4_core__uart2,
- &omap2_l4_core__uart3,
-};
-
-/* Master interfaces on the L4_WKUP interconnect */
-static struct omap_hwmod_ocp_if *omap2430_l4_wkup_masters[] = {
-};
-
-/* l4 core -> mcspi1 interface */
-static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi1 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_mcspi1_hwmod,
- .clk = "mcspi1_ick",
- .addr = omap2_mcspi1_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4 core -> mcspi2 interface */
-static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi2 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_mcspi2_hwmod,
- .clk = "mcspi2_ick",
- .addr = omap2_mcspi2_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4 core -> mcspi3 interface */
-static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi3 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_mcspi3_hwmod,
- .clk = "mcspi3_ick",
- .addr = omap2430_mcspi3_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 WKUP */
-static struct omap_hwmod omap2430_l4_wkup_hwmod = {
- .name = "l4_wkup",
- .class = &l4_hwmod_class,
- .masters = omap2430_l4_wkup_masters,
- .masters_cnt = ARRAY_SIZE(omap2430_l4_wkup_masters),
- .slaves = omap2430_l4_wkup_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_l4_wkup_slaves),
- .flags = HWMOD_NO_IDLEST,
-};
-
-/* Master interfaces on the MPU device */
-static struct omap_hwmod_ocp_if *omap2430_mpu_masters[] = {
- &omap2430_mpu__l3_main,
-};
-
-/* MPU */
-static struct omap_hwmod omap2430_mpu_hwmod = {
- .name = "mpu",
- .class = &mpu_hwmod_class,
- .main_clk = "mpu_ck",
- .masters = omap2430_mpu_masters,
- .masters_cnt = ARRAY_SIZE(omap2430_mpu_masters),
-};
-
/*
- * IVA2_1 interface data
+ * IP blocks
*/
-/* IVA2 <- L3 interface */
-static struct omap_hwmod_ocp_if omap2430_l3__iva = {
- .master = &omap2430_l3_main_hwmod,
- .slave = &omap2430_iva_hwmod,
- .clk = "dsp_fck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_ocp_if *omap2430_iva_masters[] = {
- &omap2430_l3__iva,
+/* IVA2 (IVA2) */
+static struct omap_hwmod_rst_info omap2430_iva_resets[] = {
+ { .name = "logic", .rst_shift = 0 },
+ { .name = "mmu", .rst_shift = 1 },
};
-/*
- * IVA2 (IVA2)
- */
-
static struct omap_hwmod omap2430_iva_hwmod = {
.name = "iva",
.class = &iva_hwmod_class,
- .masters = omap2430_iva_masters,
- .masters_cnt = ARRAY_SIZE(omap2430_iva_masters),
-};
-
-/* always-on timers dev attribute */
-static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
- .timer_capability = OMAP_TIMER_ALWON,
-};
-
-/* pwm timers dev attribute */
-static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
- .timer_capability = OMAP_TIMER_HAS_PWM,
-};
-
-/* timer1 */
-static struct omap_hwmod omap2430_timer1_hwmod;
-
-static struct omap_hwmod_addr_space omap2430_timer1_addrs[] = {
- {
- .pa_start = 0x49018000,
- .pa_end = 0x49018000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_wkup -> timer1 */
-static struct omap_hwmod_ocp_if omap2430_l4_wkup__timer1 = {
- .master = &omap2430_l4_wkup_hwmod,
- .slave = &omap2430_timer1_hwmod,
- .clk = "gpt1_ick",
- .addr = omap2430_timer1_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer1 slave port */
-static struct omap_hwmod_ocp_if *omap2430_timer1_slaves[] = {
- &omap2430_l4_wkup__timer1,
-};
-
-/* timer1 hwmod */
-static struct omap_hwmod omap2430_timer1_hwmod = {
- .name = "timer1",
- .mpu_irqs = omap2_timer1_mpu_irqs,
- .main_clk = "gpt1_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT1_SHIFT,
- .module_offs = WKUP_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
- },
- },
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2430_timer1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_timer1_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* timer2 */
-static struct omap_hwmod omap2430_timer2_hwmod;
-
-/* l4_core -> timer2 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__timer2 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_timer2_hwmod,
- .clk = "gpt2_ick",
- .addr = omap2xxx_timer2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer2 slave port */
-static struct omap_hwmod_ocp_if *omap2430_timer2_slaves[] = {
- &omap2430_l4_core__timer2,
-};
-
-/* timer2 hwmod */
-static struct omap_hwmod omap2430_timer2_hwmod = {
- .name = "timer2",
- .mpu_irqs = omap2_timer2_mpu_irqs,
- .main_clk = "gpt2_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT2_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
- },
- },
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2430_timer2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_timer2_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* timer3 */
-static struct omap_hwmod omap2430_timer3_hwmod;
-
-/* l4_core -> timer3 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__timer3 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_timer3_hwmod,
- .clk = "gpt3_ick",
- .addr = omap2xxx_timer3_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer3 slave port */
-static struct omap_hwmod_ocp_if *omap2430_timer3_slaves[] = {
- &omap2430_l4_core__timer3,
-};
-
-/* timer3 hwmod */
-static struct omap_hwmod omap2430_timer3_hwmod = {
- .name = "timer3",
- .mpu_irqs = omap2_timer3_mpu_irqs,
- .main_clk = "gpt3_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT3_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
- },
- },
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2430_timer3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_timer3_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* timer4 */
-static struct omap_hwmod omap2430_timer4_hwmod;
-
-/* l4_core -> timer4 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__timer4 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_timer4_hwmod,
- .clk = "gpt4_ick",
- .addr = omap2xxx_timer4_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer4 slave port */
-static struct omap_hwmod_ocp_if *omap2430_timer4_slaves[] = {
- &omap2430_l4_core__timer4,
-};
-
-/* timer4 hwmod */
-static struct omap_hwmod omap2430_timer4_hwmod = {
- .name = "timer4",
- .mpu_irqs = omap2_timer4_mpu_irqs,
- .main_clk = "gpt4_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT4_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
- },
- },
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2430_timer4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_timer4_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* timer5 */
-static struct omap_hwmod omap2430_timer5_hwmod;
-
-/* l4_core -> timer5 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__timer5 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_timer5_hwmod,
- .clk = "gpt5_ick",
- .addr = omap2xxx_timer5_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer5 slave port */
-static struct omap_hwmod_ocp_if *omap2430_timer5_slaves[] = {
- &omap2430_l4_core__timer5,
-};
-
-/* timer5 hwmod */
-static struct omap_hwmod omap2430_timer5_hwmod = {
- .name = "timer5",
- .mpu_irqs = omap2_timer5_mpu_irqs,
- .main_clk = "gpt5_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT5_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
- },
- },
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2430_timer5_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_timer5_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* timer6 */
-static struct omap_hwmod omap2430_timer6_hwmod;
-
-/* l4_core -> timer6 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__timer6 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_timer6_hwmod,
- .clk = "gpt6_ick",
- .addr = omap2xxx_timer6_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer6 slave port */
-static struct omap_hwmod_ocp_if *omap2430_timer6_slaves[] = {
- &omap2430_l4_core__timer6,
-};
-
-/* timer6 hwmod */
-static struct omap_hwmod omap2430_timer6_hwmod = {
- .name = "timer6",
- .mpu_irqs = omap2_timer6_mpu_irqs,
- .main_clk = "gpt6_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT6_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
- },
- },
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2430_timer6_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_timer6_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* timer7 */
-static struct omap_hwmod omap2430_timer7_hwmod;
-
-/* l4_core -> timer7 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__timer7 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_timer7_hwmod,
- .clk = "gpt7_ick",
- .addr = omap2xxx_timer7_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer7 slave port */
-static struct omap_hwmod_ocp_if *omap2430_timer7_slaves[] = {
- &omap2430_l4_core__timer7,
-};
-
-/* timer7 hwmod */
-static struct omap_hwmod omap2430_timer7_hwmod = {
- .name = "timer7",
- .mpu_irqs = omap2_timer7_mpu_irqs,
- .main_clk = "gpt7_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT7_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
- },
- },
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2430_timer7_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_timer7_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* timer8 */
-static struct omap_hwmod omap2430_timer8_hwmod;
-
-/* l4_core -> timer8 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__timer8 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_timer8_hwmod,
- .clk = "gpt8_ick",
- .addr = omap2xxx_timer8_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer8 slave port */
-static struct omap_hwmod_ocp_if *omap2430_timer8_slaves[] = {
- &omap2430_l4_core__timer8,
-};
-
-/* timer8 hwmod */
-static struct omap_hwmod omap2430_timer8_hwmod = {
- .name = "timer8",
- .mpu_irqs = omap2_timer8_mpu_irqs,
- .main_clk = "gpt8_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT8_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
- },
- },
- .dev_attr = &capability_alwon_dev_attr,
- .slaves = omap2430_timer8_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_timer8_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* timer9 */
-static struct omap_hwmod omap2430_timer9_hwmod;
-
-/* l4_core -> timer9 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__timer9 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_timer9_hwmod,
- .clk = "gpt9_ick",
- .addr = omap2xxx_timer9_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer9 slave port */
-static struct omap_hwmod_ocp_if *omap2430_timer9_slaves[] = {
- &omap2430_l4_core__timer9,
-};
-
-/* timer9 hwmod */
-static struct omap_hwmod omap2430_timer9_hwmod = {
- .name = "timer9",
- .mpu_irqs = omap2_timer9_mpu_irqs,
- .main_clk = "gpt9_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT9_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
- },
- },
- .dev_attr = &capability_pwm_dev_attr,
- .slaves = omap2430_timer9_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_timer9_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* timer10 */
-static struct omap_hwmod omap2430_timer10_hwmod;
-
-/* l4_core -> timer10 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__timer10 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_timer10_hwmod,
- .clk = "gpt10_ick",
- .addr = omap2_timer10_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer10 slave port */
-static struct omap_hwmod_ocp_if *omap2430_timer10_slaves[] = {
- &omap2430_l4_core__timer10,
-};
-
-/* timer10 hwmod */
-static struct omap_hwmod omap2430_timer10_hwmod = {
- .name = "timer10",
- .mpu_irqs = omap2_timer10_mpu_irqs,
- .main_clk = "gpt10_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT10_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
- },
- },
- .dev_attr = &capability_pwm_dev_attr,
- .slaves = omap2430_timer10_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_timer10_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* timer11 */
-static struct omap_hwmod omap2430_timer11_hwmod;
-
-/* l4_core -> timer11 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__timer11 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_timer11_hwmod,
- .clk = "gpt11_ick",
- .addr = omap2_timer11_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer11 slave port */
-static struct omap_hwmod_ocp_if *omap2430_timer11_slaves[] = {
- &omap2430_l4_core__timer11,
-};
-
-/* timer11 hwmod */
-static struct omap_hwmod omap2430_timer11_hwmod = {
- .name = "timer11",
- .mpu_irqs = omap2_timer11_mpu_irqs,
- .main_clk = "gpt11_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT11_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
- },
- },
- .dev_attr = &capability_pwm_dev_attr,
- .slaves = omap2430_timer11_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_timer11_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* timer12 */
-static struct omap_hwmod omap2430_timer12_hwmod;
-
-/* l4_core -> timer12 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__timer12 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_timer12_hwmod,
- .clk = "gpt12_ick",
- .addr = omap2xxx_timer12_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer12 slave port */
-static struct omap_hwmod_ocp_if *omap2430_timer12_slaves[] = {
- &omap2430_l4_core__timer12,
-};
-
-/* timer12 hwmod */
-static struct omap_hwmod omap2430_timer12_hwmod = {
- .name = "timer12",
- .mpu_irqs = omap2xxx_timer12_mpu_irqs,
- .main_clk = "gpt12_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPT12_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
- },
- },
- .dev_attr = &capability_pwm_dev_attr,
- .slaves = omap2430_timer12_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_timer12_slaves),
- .class = &omap2xxx_timer_hwmod_class,
-};
-
-/* l4_wkup -> wd_timer2 */
-static struct omap_hwmod_addr_space omap2430_wd_timer2_addrs[] = {
- {
- .pa_start = 0x49016000,
- .pa_end = 0x4901607f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap2430_l4_wkup__wd_timer2 = {
- .master = &omap2430_l4_wkup_hwmod,
- .slave = &omap2430_wd_timer2_hwmod,
- .clk = "mpu_wdt_ick",
- .addr = omap2430_wd_timer2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* wd_timer2 */
-static struct omap_hwmod_ocp_if *omap2430_wd_timer2_slaves[] = {
- &omap2430_l4_wkup__wd_timer2,
-};
-
-static struct omap_hwmod omap2430_wd_timer2_hwmod = {
- .name = "wd_timer2",
- .class = &omap2xxx_wd_timer_hwmod_class,
- .main_clk = "mpu_wdt_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
- .module_offs = WKUP_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_MPU_WDT_SHIFT,
- },
- },
- .slaves = omap2430_wd_timer2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_wd_timer2_slaves),
-};
-
-/* UART1 */
-
-static struct omap_hwmod_ocp_if *omap2430_uart1_slaves[] = {
- &omap2_l4_core__uart1,
-};
-
-static struct omap_hwmod omap2430_uart1_hwmod = {
- .name = "uart1",
- .mpu_irqs = omap2_uart1_mpu_irqs,
- .sdma_reqs = omap2_uart1_sdma_reqs,
- .main_clk = "uart1_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_UART1_SHIFT,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT,
- },
- },
- .slaves = omap2430_uart1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_uart1_slaves),
- .class = &omap2_uart_class,
-};
-
-/* UART2 */
-
-static struct omap_hwmod_ocp_if *omap2430_uart2_slaves[] = {
- &omap2_l4_core__uart2,
-};
-
-static struct omap_hwmod omap2430_uart2_hwmod = {
- .name = "uart2",
- .mpu_irqs = omap2_uart2_mpu_irqs,
- .sdma_reqs = omap2_uart2_sdma_reqs,
- .main_clk = "uart2_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_UART2_SHIFT,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT,
- },
- },
- .slaves = omap2430_uart2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_uart2_slaves),
- .class = &omap2_uart_class,
-};
-
-/* UART3 */
-
-static struct omap_hwmod_ocp_if *omap2430_uart3_slaves[] = {
- &omap2_l4_core__uart3,
-};
-
-static struct omap_hwmod omap2430_uart3_hwmod = {
- .name = "uart3",
- .mpu_irqs = omap2_uart3_mpu_irqs,
- .sdma_reqs = omap2_uart3_sdma_reqs,
- .main_clk = "uart3_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .prcm_reg_id = 2,
- .module_bit = OMAP24XX_EN_UART3_SHIFT,
- .idlest_reg_id = 2,
- .idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT,
- },
- },
- .slaves = omap2430_uart3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_uart3_slaves),
- .class = &omap2_uart_class,
-};
-
-/* dss */
-/* dss master ports */
-static struct omap_hwmod_ocp_if *omap2430_dss_masters[] = {
- &omap2430_dss__l3,
-};
-
-/* l4_core -> dss */
-static struct omap_hwmod_ocp_if omap2430_l4_core__dss = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_dss_core_hwmod,
- .clk = "dss_ick",
- .addr = omap2_dss_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss slave ports */
-static struct omap_hwmod_ocp_if *omap2430_dss_slaves[] = {
- &omap2430_l4_core__dss,
-};
-
-static struct omap_hwmod_opt_clk dss_opt_clks[] = {
- /*
- * The DSS HW needs all DSS clocks enabled during reset. The dss_core
- * driver does not use these clocks.
- */
- { .role = "tv_clk", .clk = "dss_54m_fck" },
- { .role = "sys_clk", .clk = "dss2_fck" },
-};
-
-static struct omap_hwmod omap2430_dss_core_hwmod = {
- .name = "dss_core",
- .class = &omap2_dss_hwmod_class,
- .main_clk = "dss1_fck", /* instead of dss_fck */
- .sdma_reqs = omap2xxx_dss_sdma_chs,
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_DSS1_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
- },
- },
- .opt_clks = dss_opt_clks,
- .opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
- .slaves = omap2430_dss_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_dss_slaves),
- .masters = omap2430_dss_masters,
- .masters_cnt = ARRAY_SIZE(omap2430_dss_masters),
- .flags = HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-};
-
-/* l4_core -> dss_dispc */
-static struct omap_hwmod_ocp_if omap2430_l4_core__dss_dispc = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_dss_dispc_hwmod,
- .clk = "dss_ick",
- .addr = omap2_dss_dispc_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss_dispc slave ports */
-static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = {
- &omap2430_l4_core__dss_dispc,
-};
-
-static struct omap_hwmod omap2430_dss_dispc_hwmod = {
- .name = "dss_dispc",
- .class = &omap2_dispc_hwmod_class,
- .mpu_irqs = omap2_dispc_irqs,
- .main_clk = "dss1_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_DSS1_SHIFT,
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
- },
- },
- .slaves = omap2430_dss_dispc_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_dss_dispc_slaves),
- .flags = HWMOD_NO_IDLEST,
- .dev_attr = &omap2_3_dss_dispc_dev_attr
-};
-
-/* l4_core -> dss_rfbi */
-static struct omap_hwmod_ocp_if omap2430_l4_core__dss_rfbi = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_dss_rfbi_hwmod,
- .clk = "dss_ick",
- .addr = omap2_dss_rfbi_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss_rfbi slave ports */
-static struct omap_hwmod_ocp_if *omap2430_dss_rfbi_slaves[] = {
- &omap2430_l4_core__dss_rfbi,
-};
-
-static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
- { .role = "ick", .clk = "dss_ick" },
-};
-
-static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
- .name = "dss_rfbi",
- .class = &omap2_rfbi_hwmod_class,
- .main_clk = "dss1_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_DSS1_SHIFT,
- .module_offs = CORE_MOD,
- },
- },
- .opt_clks = dss_rfbi_opt_clks,
- .opt_clks_cnt = ARRAY_SIZE(dss_rfbi_opt_clks),
- .slaves = omap2430_dss_rfbi_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_dss_rfbi_slaves),
- .flags = HWMOD_NO_IDLEST,
-};
-
-/* l4_core -> dss_venc */
-static struct omap_hwmod_ocp_if omap2430_l4_core__dss_venc = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_dss_venc_hwmod,
- .clk = "dss_ick",
- .addr = omap2_dss_venc_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss_venc slave ports */
-static struct omap_hwmod_ocp_if *omap2430_dss_venc_slaves[] = {
- &omap2430_l4_core__dss_venc,
-};
-
-static struct omap_hwmod omap2430_dss_venc_hwmod = {
- .name = "dss_venc",
- .class = &omap2_venc_hwmod_class,
- .main_clk = "dss_54m_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_DSS1_SHIFT,
- .module_offs = CORE_MOD,
- },
- },
- .slaves = omap2430_dss_venc_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_dss_venc_slaves),
- .flags = HWMOD_NO_IDLEST,
+ .clkdm_name = "dsp_clkdm",
+ .rst_lines = omap2430_iva_resets,
+ .rst_lines_cnt = ARRAY_SIZE(omap2430_iva_resets),
+ .main_clk = "dsp_fck",
};
/* I2C common */
@@ -1098,11 +84,6 @@ static struct omap_i2c_dev_attr i2c_dev_attr = {
};
/* I2C1 */
-
-static struct omap_hwmod_ocp_if *omap2430_i2c1_slaves[] = {
- &omap2430_l4_core__i2c1,
-};
-
static struct omap_hwmod omap2430_i2c1_hwmod = {
.name = "i2c1",
.flags = HWMOD_16BIT_REG,
@@ -1126,18 +107,11 @@ static struct omap_hwmod omap2430_i2c1_hwmod = {
.idlest_idle_bit = OMAP2430_ST_I2CHS1_SHIFT,
},
},
- .slaves = omap2430_i2c1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_i2c1_slaves),
.class = &i2c_class,
.dev_attr = &i2c_dev_attr,
};
/* I2C2 */
-
-static struct omap_hwmod_ocp_if *omap2430_i2c2_slaves[] = {
- &omap2430_l4_core__i2c2,
-};
-
static struct omap_hwmod omap2430_i2c2_hwmod = {
.name = "i2c2",
.flags = HWMOD_16BIT_REG,
@@ -1153,218 +127,16 @@ static struct omap_hwmod omap2430_i2c2_hwmod = {
.idlest_idle_bit = OMAP2430_ST_I2CHS2_SHIFT,
},
},
- .slaves = omap2430_i2c2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_i2c2_slaves),
.class = &i2c_class,
.dev_attr = &i2c_dev_attr,
};
-/* l4_wkup -> gpio1 */
-static struct omap_hwmod_addr_space omap2430_gpio1_addr_space[] = {
- {
- .pa_start = 0x4900C000,
- .pa_end = 0x4900C1ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio1 = {
- .master = &omap2430_l4_wkup_hwmod,
- .slave = &omap2430_gpio1_hwmod,
- .clk = "gpios_ick",
- .addr = omap2430_gpio1_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_wkup -> gpio2 */
-static struct omap_hwmod_addr_space omap2430_gpio2_addr_space[] = {
- {
- .pa_start = 0x4900E000,
- .pa_end = 0x4900E1ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio2 = {
- .master = &omap2430_l4_wkup_hwmod,
- .slave = &omap2430_gpio2_hwmod,
- .clk = "gpios_ick",
- .addr = omap2430_gpio2_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_wkup -> gpio3 */
-static struct omap_hwmod_addr_space omap2430_gpio3_addr_space[] = {
- {
- .pa_start = 0x49010000,
- .pa_end = 0x490101ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio3 = {
- .master = &omap2430_l4_wkup_hwmod,
- .slave = &omap2430_gpio3_hwmod,
- .clk = "gpios_ick",
- .addr = omap2430_gpio3_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_wkup -> gpio4 */
-static struct omap_hwmod_addr_space omap2430_gpio4_addr_space[] = {
- {
- .pa_start = 0x49012000,
- .pa_end = 0x490121ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio4 = {
- .master = &omap2430_l4_wkup_hwmod,
- .slave = &omap2430_gpio4_hwmod,
- .clk = "gpios_ick",
- .addr = omap2430_gpio4_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_core -> gpio5 */
-static struct omap_hwmod_addr_space omap2430_gpio5_addr_space[] = {
- {
- .pa_start = 0x480B6000,
- .pa_end = 0x480B61ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap2430_l4_core__gpio5 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_gpio5_hwmod,
- .clk = "gpio5_ick",
- .addr = omap2430_gpio5_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* gpio dev_attr */
-static struct omap_gpio_dev_attr gpio_dev_attr = {
- .bank_width = 32,
- .dbck_flag = false,
-};
-
-/* gpio1 */
-static struct omap_hwmod_ocp_if *omap2430_gpio1_slaves[] = {
- &omap2430_l4_wkup__gpio1,
-};
-
-static struct omap_hwmod omap2430_gpio1_hwmod = {
- .name = "gpio1",
- .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap2_gpio1_irqs,
- .main_clk = "gpios_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .module_offs = WKUP_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_EN_GPIOS_SHIFT,
- },
- },
- .slaves = omap2430_gpio1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_gpio1_slaves),
- .class = &omap2xxx_gpio_hwmod_class,
- .dev_attr = &gpio_dev_attr,
-};
-
-/* gpio2 */
-static struct omap_hwmod_ocp_if *omap2430_gpio2_slaves[] = {
- &omap2430_l4_wkup__gpio2,
-};
-
-static struct omap_hwmod omap2430_gpio2_hwmod = {
- .name = "gpio2",
- .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap2_gpio2_irqs,
- .main_clk = "gpios_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .module_offs = WKUP_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
- },
- },
- .slaves = omap2430_gpio2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_gpio2_slaves),
- .class = &omap2xxx_gpio_hwmod_class,
- .dev_attr = &gpio_dev_attr,
-};
-
-/* gpio3 */
-static struct omap_hwmod_ocp_if *omap2430_gpio3_slaves[] = {
- &omap2430_l4_wkup__gpio3,
-};
-
-static struct omap_hwmod omap2430_gpio3_hwmod = {
- .name = "gpio3",
- .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap2_gpio3_irqs,
- .main_clk = "gpios_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .module_offs = WKUP_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
- },
- },
- .slaves = omap2430_gpio3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_gpio3_slaves),
- .class = &omap2xxx_gpio_hwmod_class,
- .dev_attr = &gpio_dev_attr,
-};
-
-/* gpio4 */
-static struct omap_hwmod_ocp_if *omap2430_gpio4_slaves[] = {
- &omap2430_l4_wkup__gpio4,
-};
-
-static struct omap_hwmod omap2430_gpio4_hwmod = {
- .name = "gpio4",
- .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
- .mpu_irqs = omap2_gpio4_irqs,
- .main_clk = "gpios_fck",
- .prcm = {
- .omap2 = {
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .module_offs = WKUP_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
- },
- },
- .slaves = omap2430_gpio4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_gpio4_slaves),
- .class = &omap2xxx_gpio_hwmod_class,
- .dev_attr = &gpio_dev_attr,
-};
-
/* gpio5 */
static struct omap_hwmod_irq_info omap243x_gpio5_irqs[] = {
{ .irq = 33 }, /* INT_24XX_GPIO_BANK5 */
{ .irq = -1 }
};
-static struct omap_hwmod_ocp_if *omap2430_gpio5_slaves[] = {
- &omap2430_l4_core__gpio5,
-};
-
static struct omap_hwmod omap2430_gpio5_hwmod = {
.name = "gpio5",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
@@ -1379,10 +151,8 @@ static struct omap_hwmod omap2430_gpio5_hwmod = {
.idlest_idle_bit = OMAP2430_ST_GPIO5_SHIFT,
},
},
- .slaves = omap2430_gpio5_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_gpio5_slaves),
.class = &omap2xxx_gpio_hwmod_class,
- .dev_attr = &gpio_dev_attr,
+ .dev_attr = &omap2xxx_gpio_dev_attr,
};
/* dma attributes */
@@ -1392,66 +162,21 @@ static struct omap_dma_dev_attr dma_dev_attr = {
.lch_count = 32,
};
-/* dma_system -> L3 */
-static struct omap_hwmod_ocp_if omap2430_dma_system__l3 = {
- .master = &omap2430_dma_system_hwmod,
- .slave = &omap2430_l3_main_hwmod,
- .clk = "core_l3_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dma_system master ports */
-static struct omap_hwmod_ocp_if *omap2430_dma_system_masters[] = {
- &omap2430_dma_system__l3,
-};
-
-/* l4_core -> dma_system */
-static struct omap_hwmod_ocp_if omap2430_l4_core__dma_system = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_dma_system_hwmod,
- .clk = "sdma_ick",
- .addr = omap2_dma_system_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dma_system slave ports */
-static struct omap_hwmod_ocp_if *omap2430_dma_system_slaves[] = {
- &omap2430_l4_core__dma_system,
-};
-
static struct omap_hwmod omap2430_dma_system_hwmod = {
.name = "dma",
.class = &omap2xxx_dma_hwmod_class,
.mpu_irqs = omap2_dma_system_irqs,
.main_clk = "core_l3_ck",
- .slaves = omap2430_dma_system_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_dma_system_slaves),
- .masters = omap2430_dma_system_masters,
- .masters_cnt = ARRAY_SIZE(omap2430_dma_system_masters),
.dev_attr = &dma_dev_attr,
.flags = HWMOD_NO_IDLEST,
};
/* mailbox */
-static struct omap_hwmod omap2430_mailbox_hwmod;
static struct omap_hwmod_irq_info omap2430_mailbox_irqs[] = {
{ .irq = 26 },
{ .irq = -1 }
};
-/* l4_core -> mailbox */
-static struct omap_hwmod_ocp_if omap2430_l4_core__mailbox = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_mailbox_hwmod,
- .addr = omap2_mailbox_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mailbox slave ports */
-static struct omap_hwmod_ocp_if *omap2430_mailbox_slaves[] = {
- &omap2430_l4_core__mailbox,
-};
-
static struct omap_hwmod omap2430_mailbox_hwmod = {
.name = "mailbox",
.class = &omap2xxx_mailbox_hwmod_class,
@@ -1466,66 +191,6 @@ static struct omap_hwmod omap2430_mailbox_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
},
},
- .slaves = omap2430_mailbox_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_mailbox_slaves),
-};
-
-/* mcspi1 */
-static struct omap_hwmod_ocp_if *omap2430_mcspi1_slaves[] = {
- &omap2430_l4_core__mcspi1,
-};
-
-static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
- .num_chipselect = 4,
-};
-
-static struct omap_hwmod omap2430_mcspi1_hwmod = {
- .name = "mcspi1_hwmod",
- .mpu_irqs = omap2_mcspi1_mpu_irqs,
- .sdma_reqs = omap2_mcspi1_sdma_reqs,
- .main_clk = "mcspi1_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_MCSPI1_SHIFT,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_MCSPI1_SHIFT,
- },
- },
- .slaves = omap2430_mcspi1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_mcspi1_slaves),
- .class = &omap2xxx_mcspi_class,
- .dev_attr = &omap_mcspi1_dev_attr,
-};
-
-/* mcspi2 */
-static struct omap_hwmod_ocp_if *omap2430_mcspi2_slaves[] = {
- &omap2430_l4_core__mcspi2,
-};
-
-static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
- .num_chipselect = 2,
-};
-
-static struct omap_hwmod omap2430_mcspi2_hwmod = {
- .name = "mcspi2_hwmod",
- .mpu_irqs = omap2_mcspi2_mpu_irqs,
- .sdma_reqs = omap2_mcspi2_sdma_reqs,
- .main_clk = "mcspi2_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .prcm_reg_id = 1,
- .module_bit = OMAP24XX_EN_MCSPI2_SHIFT,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP24XX_ST_MCSPI2_SHIFT,
- },
- },
- .slaves = omap2430_mcspi2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_mcspi2_slaves),
- .class = &omap2xxx_mcspi_class,
- .dev_attr = &omap_mcspi2_dev_attr,
};
/* mcspi3 */
@@ -1542,16 +207,12 @@ static struct omap_hwmod_dma_info omap2430_mcspi3_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_ocp_if *omap2430_mcspi3_slaves[] = {
- &omap2430_l4_core__mcspi3,
-};
-
static struct omap2_mcspi_dev_attr omap_mcspi3_dev_attr = {
.num_chipselect = 2,
};
static struct omap_hwmod omap2430_mcspi3_hwmod = {
- .name = "mcspi3_hwmod",
+ .name = "mcspi3",
.mpu_irqs = omap2430_mcspi3_mpu_irqs,
.sdma_reqs = omap2430_mcspi3_sdma_reqs,
.main_clk = "mcspi3_fck",
@@ -1564,15 +225,11 @@ static struct omap_hwmod omap2430_mcspi3_hwmod = {
.idlest_idle_bit = OMAP2430_ST_MCSPI3_SHIFT,
},
},
- .slaves = omap2430_mcspi3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_mcspi3_slaves),
.class = &omap2xxx_mcspi_class,
.dev_attr = &omap_mcspi3_dev_attr,
};
-/*
- * usbhsotg
- */
+/* usbhsotg */
static struct omap_hwmod_class_sysconfig omap2430_usbhsotg_sysc = {
.rev_offs = 0x0400,
.sysc_offs = 0x0404,
@@ -1611,10 +268,6 @@ static struct omap_hwmod omap2430_usbhsotg_hwmod = {
.idlest_idle_bit = OMAP2430_ST_USBHS_SHIFT,
},
},
- .masters = omap2430_usbhsotg_masters,
- .masters_cnt = ARRAY_SIZE(omap2430_usbhsotg_masters),
- .slaves = omap2430_usbhsotg_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_usbhsotg_slaves),
.class = &usbotg_class,
/*
* Erratum ID: i479 idle_req / idle_ack mechanism potentially
@@ -1652,20 +305,6 @@ static struct omap_hwmod_irq_info omap2430_mcbsp1_irqs[] = {
{ .irq = -1 }
};
-/* l4_core -> mcbsp1 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp1 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_mcbsp1_hwmod,
- .clk = "mcbsp1_ick",
- .addr = omap2_mcbsp1_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcbsp1 slave ports */
-static struct omap_hwmod_ocp_if *omap2430_mcbsp1_slaves[] = {
- &omap2430_l4_core__mcbsp1,
-};
-
static struct omap_hwmod omap2430_mcbsp1_hwmod = {
.name = "mcbsp1",
.class = &omap2430_mcbsp_hwmod_class,
@@ -1681,8 +320,6 @@ static struct omap_hwmod omap2430_mcbsp1_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_MCBSP1_SHIFT,
},
},
- .slaves = omap2430_mcbsp1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_mcbsp1_slaves),
};
/* mcbsp2 */
@@ -1693,20 +330,6 @@ static struct omap_hwmod_irq_info omap2430_mcbsp2_irqs[] = {
{ .irq = -1 }
};
-/* l4_core -> mcbsp2 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp2 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_mcbsp2_hwmod,
- .clk = "mcbsp2_ick",
- .addr = omap2xxx_mcbsp2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcbsp2 slave ports */
-static struct omap_hwmod_ocp_if *omap2430_mcbsp2_slaves[] = {
- &omap2430_l4_core__mcbsp2,
-};
-
static struct omap_hwmod omap2430_mcbsp2_hwmod = {
.name = "mcbsp2",
.class = &omap2430_mcbsp_hwmod_class,
@@ -1722,8 +345,6 @@ static struct omap_hwmod omap2430_mcbsp2_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_MCBSP2_SHIFT,
},
},
- .slaves = omap2430_mcbsp2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_mcbsp2_slaves),
};
/* mcbsp3 */
@@ -1734,30 +355,6 @@ static struct omap_hwmod_irq_info omap2430_mcbsp3_irqs[] = {
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap2430_mcbsp3_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x4808C000,
- .pa_end = 0x4808C0ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_core -> mcbsp3 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp3 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_mcbsp3_hwmod,
- .clk = "mcbsp3_ick",
- .addr = omap2430_mcbsp3_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcbsp3 slave ports */
-static struct omap_hwmod_ocp_if *omap2430_mcbsp3_slaves[] = {
- &omap2430_l4_core__mcbsp3,
-};
-
static struct omap_hwmod omap2430_mcbsp3_hwmod = {
.name = "mcbsp3",
.class = &omap2430_mcbsp_hwmod_class,
@@ -1773,8 +370,6 @@ static struct omap_hwmod omap2430_mcbsp3_hwmod = {
.idlest_idle_bit = OMAP2430_ST_MCBSP3_SHIFT,
},
},
- .slaves = omap2430_mcbsp3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_mcbsp3_slaves),
};
/* mcbsp4 */
@@ -1791,30 +386,6 @@ static struct omap_hwmod_dma_info omap2430_mcbsp4_sdma_chs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap2430_mcbsp4_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x4808E000,
- .pa_end = 0x4808E0ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_core -> mcbsp4 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp4 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_mcbsp4_hwmod,
- .clk = "mcbsp4_ick",
- .addr = omap2430_mcbsp4_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcbsp4 slave ports */
-static struct omap_hwmod_ocp_if *omap2430_mcbsp4_slaves[] = {
- &omap2430_l4_core__mcbsp4,
-};
-
static struct omap_hwmod omap2430_mcbsp4_hwmod = {
.name = "mcbsp4",
.class = &omap2430_mcbsp_hwmod_class,
@@ -1830,8 +401,6 @@ static struct omap_hwmod omap2430_mcbsp4_hwmod = {
.idlest_idle_bit = OMAP2430_ST_MCBSP4_SHIFT,
},
},
- .slaves = omap2430_mcbsp4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_mcbsp4_slaves),
};
/* mcbsp5 */
@@ -1848,30 +417,6 @@ static struct omap_hwmod_dma_info omap2430_mcbsp5_sdma_chs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap2430_mcbsp5_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x48096000,
- .pa_end = 0x480960ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_core -> mcbsp5 */
-static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp5 = {
- .master = &omap2430_l4_core_hwmod,
- .slave = &omap2430_mcbsp5_hwmod,
- .clk = "mcbsp5_ick",
- .addr = omap2430_mcbsp5_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcbsp5 slave ports */
-static struct omap_hwmod_ocp_if *omap2430_mcbsp5_slaves[] = {
- &omap2430_l4_core__mcbsp5,
-};
-
static struct omap_hwmod omap2430_mcbsp5_hwmod = {
.name = "mcbsp5",
.class = &omap2430_mcbsp_hwmod_class,
@@ -1887,12 +432,9 @@ static struct omap_hwmod omap2430_mcbsp5_hwmod = {
.idlest_idle_bit = OMAP2430_ST_MCBSP5_SHIFT,
},
},
- .slaves = omap2430_mcbsp5_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_mcbsp5_slaves),
};
/* MMC/SD/SDIO common */
-
static struct omap_hwmod_class_sysconfig omap2430_mmc_sysc = {
.rev_offs = 0x1fc,
.sysc_offs = 0x10,
@@ -1910,7 +452,6 @@ static struct omap_hwmod_class omap2430_mmc_class = {
};
/* MMC/SD/SDIO1 */
-
static struct omap_hwmod_irq_info omap2430_mmc1_mpu_irqs[] = {
{ .irq = 83 },
{ .irq = -1 }
@@ -1926,10 +467,6 @@ static struct omap_hwmod_opt_clk omap2430_mmc1_opt_clks[] = {
{ .role = "dbck", .clk = "mmchsdb1_fck" },
};
-static struct omap_hwmod_ocp_if *omap2430_mmc1_slaves[] = {
- &omap2430_l4_core__mmc1,
-};
-
static struct omap_mmc_dev_attr mmc1_dev_attr = {
.flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
};
@@ -1952,13 +489,10 @@ static struct omap_hwmod omap2430_mmc1_hwmod = {
},
},
.dev_attr = &mmc1_dev_attr,
- .slaves = omap2430_mmc1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_mmc1_slaves),
.class = &omap2430_mmc_class,
};
/* MMC/SD/SDIO2 */
-
static struct omap_hwmod_irq_info omap2430_mmc2_mpu_irqs[] = {
{ .irq = 86 },
{ .irq = -1 }
@@ -1974,10 +508,6 @@ static struct omap_hwmod_opt_clk omap2430_mmc2_opt_clks[] = {
{ .role = "dbck", .clk = "mmchsdb2_fck" },
};
-static struct omap_hwmod_ocp_if *omap2430_mmc2_slaves[] = {
- &omap2430_l4_core__mmc2,
-};
-
static struct omap_hwmod omap2430_mmc2_hwmod = {
.name = "mmc2",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
@@ -1995,78 +525,418 @@ static struct omap_hwmod omap2430_mmc2_hwmod = {
.idlest_idle_bit = OMAP2430_ST_MMCHS2_SHIFT,
},
},
- .slaves = omap2430_mmc2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap2430_mmc2_slaves),
.class = &omap2430_mmc_class,
};
-static __initdata struct omap_hwmod *omap2430_hwmods[] = {
- &omap2430_l3_main_hwmod,
- &omap2430_l4_core_hwmod,
- &omap2430_l4_wkup_hwmod,
- &omap2430_mpu_hwmod,
- &omap2430_iva_hwmod,
-
- &omap2430_timer1_hwmod,
- &omap2430_timer2_hwmod,
- &omap2430_timer3_hwmod,
- &omap2430_timer4_hwmod,
- &omap2430_timer5_hwmod,
- &omap2430_timer6_hwmod,
- &omap2430_timer7_hwmod,
- &omap2430_timer8_hwmod,
- &omap2430_timer9_hwmod,
- &omap2430_timer10_hwmod,
- &omap2430_timer11_hwmod,
- &omap2430_timer12_hwmod,
-
- &omap2430_wd_timer2_hwmod,
- &omap2430_uart1_hwmod,
- &omap2430_uart2_hwmod,
- &omap2430_uart3_hwmod,
- /* dss class */
- &omap2430_dss_core_hwmod,
- &omap2430_dss_dispc_hwmod,
- &omap2430_dss_rfbi_hwmod,
- &omap2430_dss_venc_hwmod,
- /* i2c class */
- &omap2430_i2c1_hwmod,
- &omap2430_i2c2_hwmod,
- &omap2430_mmc1_hwmod,
- &omap2430_mmc2_hwmod,
-
- /* gpio class */
- &omap2430_gpio1_hwmod,
- &omap2430_gpio2_hwmod,
- &omap2430_gpio3_hwmod,
- &omap2430_gpio4_hwmod,
- &omap2430_gpio5_hwmod,
-
- /* dma_system class*/
- &omap2430_dma_system_hwmod,
-
- /* mcbsp class */
- &omap2430_mcbsp1_hwmod,
- &omap2430_mcbsp2_hwmod,
- &omap2430_mcbsp3_hwmod,
- &omap2430_mcbsp4_hwmod,
- &omap2430_mcbsp5_hwmod,
-
- /* mailbox class */
- &omap2430_mailbox_hwmod,
-
- /* mcspi class */
- &omap2430_mcspi1_hwmod,
- &omap2430_mcspi2_hwmod,
- &omap2430_mcspi3_hwmod,
-
- /* usbotg class*/
- &omap2430_usbhsotg_hwmod,
+/* HDQ1W/1-wire */
+static struct omap_hwmod omap2430_hdq1w_hwmod = {
+ .name = "hdq1w",
+ .mpu_irqs = omap2_hdq1w_mpu_irqs,
+ .main_clk = "hdq_fck",
+ .prcm = {
+ .omap2 = {
+ .module_offs = CORE_MOD,
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_HDQ_SHIFT,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_HDQ_SHIFT,
+ },
+ },
+ .class = &omap2_hdq1w_class,
+};
+
+/*
+ * interfaces
+ */
+
+/* L3 -> L4_CORE interface */
+/* l3_core -> usbhsotg interface */
+static struct omap_hwmod_ocp_if omap2430_usbhsotg__l3 = {
+ .master = &omap2430_usbhsotg_hwmod,
+ .slave = &omap2xxx_l3_main_hwmod,
+ .clk = "core_l3_ck",
+ .user = OCP_USER_MPU,
+};
+
+/* L4 CORE -> I2C1 interface */
+static struct omap_hwmod_ocp_if omap2430_l4_core__i2c1 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_i2c1_hwmod,
+ .clk = "i2c1_ick",
+ .addr = omap2_i2c1_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> I2C2 interface */
+static struct omap_hwmod_ocp_if omap2430_l4_core__i2c2 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_i2c2_hwmod,
+ .clk = "i2c2_ick",
+ .addr = omap2_i2c2_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap2430_usbhsotg_addrs[] = {
+ {
+ .pa_start = OMAP243X_HS_BASE,
+ .pa_end = OMAP243X_HS_BASE + SZ_4K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_core ->usbhsotg interface */
+static struct omap_hwmod_ocp_if omap2430_l4_core__usbhsotg = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_usbhsotg_hwmod,
+ .clk = "usb_l4_ick",
+ .addr = omap2430_usbhsotg_addrs,
+ .user = OCP_USER_MPU,
+};
+/* L4 CORE -> MMC1 interface */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mmc1 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_mmc1_hwmod,
+ .clk = "mmchs1_ick",
+ .addr = omap2430_mmc1_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> MMC2 interface */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mmc2 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_mmc2_hwmod,
+ .clk = "mmchs2_ick",
+ .addr = omap2430_mmc2_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi3 interface */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi3 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_mcspi3_hwmod,
+ .clk = "mcspi3_ick",
+ .addr = omap2430_mcspi3_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* IVA2 <- L3 interface */
+static struct omap_hwmod_ocp_if omap2430_l3__iva = {
+ .master = &omap2xxx_l3_main_hwmod,
+ .slave = &omap2430_iva_hwmod,
+ .clk = "core_l3_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap2430_timer1_addrs[] = {
+ {
+ .pa_start = 0x49018000,
+ .pa_end = 0x49018000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_wkup -> timer1 */
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__timer1 = {
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_timer1_hwmod,
+ .clk = "gpt1_ick",
+ .addr = omap2430_timer1_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_addr_space omap2430_wd_timer2_addrs[] = {
+ {
+ .pa_start = 0x49016000,
+ .pa_end = 0x4901607f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__wd_timer2 = {
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_wd_timer2_hwmod,
+ .clk = "mpu_wdt_ick",
+ .addr = omap2430_wd_timer2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio1 */
+static struct omap_hwmod_addr_space omap2430_gpio1_addr_space[] = {
+ {
+ .pa_start = 0x4900C000,
+ .pa_end = 0x4900C1ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio1 = {
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_gpio1_hwmod,
+ .clk = "gpios_ick",
+ .addr = omap2430_gpio1_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio2 */
+static struct omap_hwmod_addr_space omap2430_gpio2_addr_space[] = {
+ {
+ .pa_start = 0x4900E000,
+ .pa_end = 0x4900E1ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio2 = {
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_gpio2_hwmod,
+ .clk = "gpios_ick",
+ .addr = omap2430_gpio2_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio3 */
+static struct omap_hwmod_addr_space omap2430_gpio3_addr_space[] = {
+ {
+ .pa_start = 0x49010000,
+ .pa_end = 0x490101ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio3 = {
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_gpio3_hwmod,
+ .clk = "gpios_ick",
+ .addr = omap2430_gpio3_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio4 */
+static struct omap_hwmod_addr_space omap2430_gpio4_addr_space[] = {
+ {
+ .pa_start = 0x49012000,
+ .pa_end = 0x490121ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio4 = {
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_gpio4_hwmod,
+ .clk = "gpios_ick",
+ .addr = omap2430_gpio4_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> gpio5 */
+static struct omap_hwmod_addr_space omap2430_gpio5_addr_space[] = {
+ {
+ .pa_start = 0x480B6000,
+ .pa_end = 0x480B61ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__gpio5 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_gpio5_hwmod,
+ .clk = "gpio5_ick",
+ .addr = omap2430_gpio5_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system -> L3 */
+static struct omap_hwmod_ocp_if omap2430_dma_system__l3 = {
+ .master = &omap2430_dma_system_hwmod,
+ .slave = &omap2xxx_l3_main_hwmod,
+ .clk = "core_l3_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> dma_system */
+static struct omap_hwmod_ocp_if omap2430_l4_core__dma_system = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_dma_system_hwmod,
+ .clk = "sdma_ick",
+ .addr = omap2_dma_system_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> mailbox */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mailbox = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_mailbox_hwmod,
+ .addr = omap2_mailbox_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> mcbsp1 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp1 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_mcbsp1_hwmod,
+ .clk = "mcbsp1_ick",
+ .addr = omap2_mcbsp1_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> mcbsp2 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp2 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_mcbsp2_hwmod,
+ .clk = "mcbsp2_ick",
+ .addr = omap2xxx_mcbsp2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap2430_mcbsp3_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x4808C000,
+ .pa_end = 0x4808C0ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_core -> mcbsp3 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp3 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_mcbsp3_hwmod,
+ .clk = "mcbsp3_ick",
+ .addr = omap2430_mcbsp3_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap2430_mcbsp4_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x4808E000,
+ .pa_end = 0x4808E0ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_core -> mcbsp4 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp4 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_mcbsp4_hwmod,
+ .clk = "mcbsp4_ick",
+ .addr = omap2430_mcbsp4_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap2430_mcbsp5_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x48096000,
+ .pa_end = 0x480960ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_core -> mcbsp5 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp5 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_mcbsp5_hwmod,
+ .clk = "mcbsp5_ick",
+ .addr = omap2430_mcbsp5_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> hdq1w */
+static struct omap_hwmod_ocp_if omap2430_l4_core__hdq1w = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2430_hdq1w_hwmod,
+ .clk = "hdq_ick",
+ .addr = omap2_hdq1w_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ .flags = OMAP_FIREWALL_L4 | OCPIF_SWSUP_IDLE,
+};
+
+/* l4_wkup -> 32ksync_counter */
+static struct omap_hwmod_addr_space omap2430_counter_32k_addrs[] = {
+ {
+ .pa_start = 0x49020000,
+ .pa_end = 0x4902001f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__counter_32k = {
+ .master = &omap2xxx_l4_wkup_hwmod,
+ .slave = &omap2xxx_counter_32k_hwmod,
+ .clk = "sync_32k_ick",
+ .addr = omap2430_counter_32k_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
+ &omap2xxx_l3_main__l4_core,
+ &omap2xxx_mpu__l3_main,
+ &omap2xxx_dss__l3,
+ &omap2430_usbhsotg__l3,
+ &omap2430_l4_core__i2c1,
+ &omap2430_l4_core__i2c2,
+ &omap2xxx_l4_core__l4_wkup,
+ &omap2_l4_core__uart1,
+ &omap2_l4_core__uart2,
+ &omap2_l4_core__uart3,
+ &omap2430_l4_core__usbhsotg,
+ &omap2430_l4_core__mmc1,
+ &omap2430_l4_core__mmc2,
+ &omap2xxx_l4_core__mcspi1,
+ &omap2xxx_l4_core__mcspi2,
+ &omap2430_l4_core__mcspi3,
+ &omap2430_l3__iva,
+ &omap2430_l4_wkup__timer1,
+ &omap2xxx_l4_core__timer2,
+ &omap2xxx_l4_core__timer3,
+ &omap2xxx_l4_core__timer4,
+ &omap2xxx_l4_core__timer5,
+ &omap2xxx_l4_core__timer6,
+ &omap2xxx_l4_core__timer7,
+ &omap2xxx_l4_core__timer8,
+ &omap2xxx_l4_core__timer9,
+ &omap2xxx_l4_core__timer10,
+ &omap2xxx_l4_core__timer11,
+ &omap2xxx_l4_core__timer12,
+ &omap2430_l4_wkup__wd_timer2,
+ &omap2xxx_l4_core__dss,
+ &omap2xxx_l4_core__dss_dispc,
+ &omap2xxx_l4_core__dss_rfbi,
+ &omap2xxx_l4_core__dss_venc,
+ &omap2430_l4_wkup__gpio1,
+ &omap2430_l4_wkup__gpio2,
+ &omap2430_l4_wkup__gpio3,
+ &omap2430_l4_wkup__gpio4,
+ &omap2430_l4_core__gpio5,
+ &omap2430_dma_system__l3,
+ &omap2430_l4_core__dma_system,
+ &omap2430_l4_core__mailbox,
+ &omap2430_l4_core__mcbsp1,
+ &omap2430_l4_core__mcbsp2,
+ &omap2430_l4_core__mcbsp3,
+ &omap2430_l4_core__mcbsp4,
+ &omap2430_l4_core__mcbsp5,
+ &omap2430_l4_core__hdq1w,
+ &omap2430_l4_wkup__counter_32k,
NULL,
};
int __init omap2430_hwmod_init(void)
{
- return omap_hwmod_register(omap2430_hwmods);
+ return omap_hwmod_register_links(omap2430_hwmod_ocp_ifs);
}
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
index 04637fabadd2..cbb4ef6544ad 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
@@ -171,3 +171,12 @@ struct omap_hwmod_addr_space omap2_mcbsp1_addrs[] = {
},
{ }
};
+
+struct omap_hwmod_addr_space omap2_hdq1w_addr_space[] = {
+ {
+ .pa_start = 0x480b2000,
+ .pa_end = 0x480b2fff,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
index f08e442af397..102d76e9e9ea 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
@@ -2,6 +2,7 @@
* omap_hwmod_2xxx_3xxx_ipblock_data.c - common IP block data for OMAP2/3
*
* Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2012 Texas Instruments, Inc.
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
@@ -12,6 +13,7 @@
#include <plat/serial.h>
#include <plat/dma.h>
#include <plat/common.h>
+#include <plat/hdq1w.h>
#include <mach/irqs.h>
@@ -302,3 +304,23 @@ struct omap_hwmod_irq_info omap2_mcspi2_mpu_irqs[] = {
{ .irq = -1 }
};
+struct omap_hwmod_class_sysconfig omap2_hdq1w_sysc = {
+ .rev_offs = 0x0,
+ .sysc_offs = 0x14,
+ .syss_offs = 0x18,
+ .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+ SYSS_HAS_RESET_STATUS),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_hdq1w_class = {
+ .name = "hdq1w",
+ .sysc = &omap2_hdq1w_sysc,
+ .reset = &omap_hdq1w_reset,
+};
+
+struct omap_hwmod_irq_info omap2_hdq1w_mpu_irqs[] = {
+ { .irq = 58, },
+ { .irq = -1 }
+};
+
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
index 4f3547c2a49e..5178e40e84f9 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
@@ -15,10 +15,12 @@
#include <plat/omap_hwmod.h>
#include <plat/serial.h>
+#include <plat/l3_2xxx.h>
+#include <plat/l4_2xxx.h>
#include "omap_hwmod_common_data.h"
-struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[] = {
+static struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[] = {
{
.pa_start = OMAP2_UART1_BASE,
.pa_end = OMAP2_UART1_BASE + SZ_8K - 1,
@@ -27,7 +29,7 @@ struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[] = {
{ }
};
-struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[] = {
+static struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[] = {
{
.pa_start = OMAP2_UART2_BASE,
.pa_end = OMAP2_UART2_BASE + SZ_1K - 1,
@@ -36,7 +38,7 @@ struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[] = {
{ }
};
-struct omap_hwmod_addr_space omap2xxx_uart3_addr_space[] = {
+static struct omap_hwmod_addr_space omap2xxx_uart3_addr_space[] = {
{
.pa_start = OMAP2_UART3_BASE,
.pa_end = OMAP2_UART3_BASE + SZ_1K - 1,
@@ -45,7 +47,7 @@ struct omap_hwmod_addr_space omap2xxx_uart3_addr_space[] = {
{ }
};
-struct omap_hwmod_addr_space omap2xxx_timer2_addrs[] = {
+static struct omap_hwmod_addr_space omap2xxx_timer2_addrs[] = {
{
.pa_start = 0x4802a000,
.pa_end = 0x4802a000 + SZ_1K - 1,
@@ -54,7 +56,7 @@ struct omap_hwmod_addr_space omap2xxx_timer2_addrs[] = {
{ }
};
-struct omap_hwmod_addr_space omap2xxx_timer3_addrs[] = {
+static struct omap_hwmod_addr_space omap2xxx_timer3_addrs[] = {
{
.pa_start = 0x48078000,
.pa_end = 0x48078000 + SZ_1K - 1,
@@ -63,7 +65,7 @@ struct omap_hwmod_addr_space omap2xxx_timer3_addrs[] = {
{ }
};
-struct omap_hwmod_addr_space omap2xxx_timer4_addrs[] = {
+static struct omap_hwmod_addr_space omap2xxx_timer4_addrs[] = {
{
.pa_start = 0x4807a000,
.pa_end = 0x4807a000 + SZ_1K - 1,
@@ -72,7 +74,7 @@ struct omap_hwmod_addr_space omap2xxx_timer4_addrs[] = {
{ }
};
-struct omap_hwmod_addr_space omap2xxx_timer5_addrs[] = {
+static struct omap_hwmod_addr_space omap2xxx_timer5_addrs[] = {
{
.pa_start = 0x4807c000,
.pa_end = 0x4807c000 + SZ_1K - 1,
@@ -81,7 +83,7 @@ struct omap_hwmod_addr_space omap2xxx_timer5_addrs[] = {
{ }
};
-struct omap_hwmod_addr_space omap2xxx_timer6_addrs[] = {
+static struct omap_hwmod_addr_space omap2xxx_timer6_addrs[] = {
{
.pa_start = 0x4807e000,
.pa_end = 0x4807e000 + SZ_1K - 1,
@@ -90,7 +92,7 @@ struct omap_hwmod_addr_space omap2xxx_timer6_addrs[] = {
{ }
};
-struct omap_hwmod_addr_space omap2xxx_timer7_addrs[] = {
+static struct omap_hwmod_addr_space omap2xxx_timer7_addrs[] = {
{
.pa_start = 0x48080000,
.pa_end = 0x48080000 + SZ_1K - 1,
@@ -99,7 +101,7 @@ struct omap_hwmod_addr_space omap2xxx_timer7_addrs[] = {
{ }
};
-struct omap_hwmod_addr_space omap2xxx_timer8_addrs[] = {
+static struct omap_hwmod_addr_space omap2xxx_timer8_addrs[] = {
{
.pa_start = 0x48082000,
.pa_end = 0x48082000 + SZ_1K - 1,
@@ -108,7 +110,7 @@ struct omap_hwmod_addr_space omap2xxx_timer8_addrs[] = {
{ }
};
-struct omap_hwmod_addr_space omap2xxx_timer9_addrs[] = {
+static struct omap_hwmod_addr_space omap2xxx_timer9_addrs[] = {
{
.pa_start = 0x48084000,
.pa_end = 0x48084000 + SZ_1K - 1,
@@ -127,4 +129,246 @@ struct omap_hwmod_addr_space omap2xxx_mcbsp2_addrs[] = {
{ }
};
+/*
+ * Common interconnect data
+ */
+
+/* L3 -> L4_CORE interface */
+struct omap_hwmod_ocp_if omap2xxx_l3_main__l4_core = {
+ .master = &omap2xxx_l3_main_hwmod,
+ .slave = &omap2xxx_l4_core_hwmod,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* MPU -> L3 interface */
+struct omap_hwmod_ocp_if omap2xxx_mpu__l3_main = {
+ .master = &omap2xxx_mpu_hwmod,
+ .slave = &omap2xxx_l3_main_hwmod,
+ .user = OCP_USER_MPU,
+};
+
+/* DSS -> l3 */
+struct omap_hwmod_ocp_if omap2xxx_dss__l3 = {
+ .master = &omap2xxx_dss_core_hwmod,
+ .slave = &omap2xxx_l3_main_hwmod,
+ .fw = {
+ .omap2 = {
+ .l3_perm_bit = OMAP2_L3_CORE_FW_CONNID_DSS,
+ .flags = OMAP_FIREWALL_L3,
+ }
+ },
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4_CORE -> L4_WKUP interface */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__l4_wkup = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_l4_wkup_hwmod,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> UART1 interface */
+struct omap_hwmod_ocp_if omap2_l4_core__uart1 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_uart1_hwmod,
+ .clk = "uart1_ick",
+ .addr = omap2xxx_uart1_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> UART2 interface */
+struct omap_hwmod_ocp_if omap2_l4_core__uart2 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_uart2_hwmod,
+ .clk = "uart2_ick",
+ .addr = omap2xxx_uart2_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART3 interface */
+struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_uart3_hwmod,
+ .clk = "uart3_ick",
+ .addr = omap2xxx_uart3_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi1 interface */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__mcspi1 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_mcspi1_hwmod,
+ .clk = "mcspi1_ick",
+ .addr = omap2_mcspi1_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi2 interface */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__mcspi2 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_mcspi2_hwmod,
+ .clk = "mcspi2_ick",
+ .addr = omap2_mcspi2_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> timer2 */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__timer2 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_timer2_hwmod,
+ .clk = "gpt2_ick",
+ .addr = omap2xxx_timer2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> timer3 */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__timer3 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_timer3_hwmod,
+ .clk = "gpt3_ick",
+ .addr = omap2xxx_timer3_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> timer4 */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__timer4 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_timer4_hwmod,
+ .clk = "gpt4_ick",
+ .addr = omap2xxx_timer4_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> timer5 */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__timer5 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_timer5_hwmod,
+ .clk = "gpt5_ick",
+ .addr = omap2xxx_timer5_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> timer6 */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__timer6 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_timer6_hwmod,
+ .clk = "gpt6_ick",
+ .addr = omap2xxx_timer6_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> timer7 */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__timer7 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_timer7_hwmod,
+ .clk = "gpt7_ick",
+ .addr = omap2xxx_timer7_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> timer8 */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__timer8 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_timer8_hwmod,
+ .clk = "gpt8_ick",
+ .addr = omap2xxx_timer8_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> timer9 */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__timer9 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_timer9_hwmod,
+ .clk = "gpt9_ick",
+ .addr = omap2xxx_timer9_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> timer10 */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__timer10 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_timer10_hwmod,
+ .clk = "gpt10_ick",
+ .addr = omap2_timer10_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> timer11 */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__timer11 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_timer11_hwmod,
+ .clk = "gpt11_ick",
+ .addr = omap2_timer11_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> timer12 */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__timer12 = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_timer12_hwmod,
+ .clk = "gpt12_ick",
+ .addr = omap2xxx_timer12_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> dss */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__dss = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_dss_core_hwmod,
+ .clk = "dss_ick",
+ .addr = omap2_dss_addrs,
+ .fw = {
+ .omap2 = {
+ .l4_fw_region = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
+ .flags = OMAP_FIREWALL_L4,
+ }
+ },
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> dss_dispc */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_dispc = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_dss_dispc_hwmod,
+ .clk = "dss_ick",
+ .addr = omap2_dss_dispc_addrs,
+ .fw = {
+ .omap2 = {
+ .l4_fw_region = OMAP2420_L4_CORE_FW_DSS_DISPC_REGION,
+ .flags = OMAP_FIREWALL_L4,
+ }
+ },
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> dss_rfbi */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_rfbi = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_dss_rfbi_hwmod,
+ .clk = "dss_ick",
+ .addr = omap2_dss_rfbi_addrs,
+ .fw = {
+ .omap2 = {
+ .l4_fw_region = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
+ .flags = OMAP_FIREWALL_L4,
+ }
+ },
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> dss_venc */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_venc = {
+ .master = &omap2xxx_l4_core_hwmod,
+ .slave = &omap2xxx_dss_venc_hwmod,
+ .clk = "dss_ick",
+ .addr = omap2_dss_venc_addrs,
+ .fw = {
+ .omap2 = {
+ .l4_fw_region = OMAP2420_L4_CORE_FW_DSS_VENC_REGION,
+ .flags = OMAP_FIREWALL_L4,
+ }
+ },
+ .flags = OCPIF_SWSUP_IDLE,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
index 2a6729741b06..83eafd96ecaa 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -10,6 +10,7 @@
*/
#include <plat/omap_hwmod.h>
#include <plat/serial.h>
+#include <plat/gpio.h>
#include <plat/dma.h>
#include <plat/dmtimer.h>
#include <plat/mcspi.h>
@@ -17,6 +18,8 @@
#include <mach/irqs.h>
#include "omap_hwmod_common_data.h"
+#include "cm-regbits-24xx.h"
+#include "prm-regbits-24xx.h"
#include "wd_timer.h"
struct omap_hwmod_irq_info omap2xxx_timer12_mpu_irqs[] = {
@@ -86,7 +89,8 @@ static struct omap_hwmod_class_sysconfig omap2xxx_wd_timer_sysc = {
struct omap_hwmod_class omap2xxx_wd_timer_hwmod_class = {
.name = "wd_timer",
.sysc = &omap2xxx_wd_timer_sysc,
- .pre_shutdown = &omap2_wd_timer_disable
+ .pre_shutdown = &omap2_wd_timer_disable,
+ .reset = &omap2_wd_timer_reset,
};
/*
@@ -170,3 +174,582 @@ struct omap_hwmod_class omap2xxx_mcspi_class = {
.sysc = &omap2xxx_mcspi_sysc,
.rev = OMAP2_MCSPI_REV,
};
+
+/*
+ * IP blocks
+ */
+
+/* L3 */
+struct omap_hwmod omap2xxx_l3_main_hwmod = {
+ .name = "l3_main",
+ .class = &l3_hwmod_class,
+ .flags = HWMOD_NO_IDLEST,
+};
+
+/* L4 CORE */
+struct omap_hwmod omap2xxx_l4_core_hwmod = {
+ .name = "l4_core",
+ .class = &l4_hwmod_class,
+ .flags = HWMOD_NO_IDLEST,
+};
+
+/* L4 WKUP */
+struct omap_hwmod omap2xxx_l4_wkup_hwmod = {
+ .name = "l4_wkup",
+ .class = &l4_hwmod_class,
+ .flags = HWMOD_NO_IDLEST,
+};
+
+/* MPU */
+struct omap_hwmod omap2xxx_mpu_hwmod = {
+ .name = "mpu",
+ .class = &mpu_hwmod_class,
+ .main_clk = "mpu_ck",
+};
+
+/* IVA2 */
+struct omap_hwmod omap2xxx_iva_hwmod = {
+ .name = "iva",
+ .class = &iva_hwmod_class,
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+ .timer_capability = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+ .timer_capability = OMAP_TIMER_HAS_PWM,
+};
+
+/* timer1 */
+
+struct omap_hwmod omap2xxx_timer1_hwmod = {
+ .name = "timer1",
+ .mpu_irqs = omap2_timer1_mpu_irqs,
+ .main_clk = "gpt1_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPT1_SHIFT,
+ .module_offs = WKUP_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
+ },
+ },
+ .dev_attr = &capability_alwon_dev_attr,
+ .class = &omap2xxx_timer_hwmod_class,
+};
+
+/* timer2 */
+
+struct omap_hwmod omap2xxx_timer2_hwmod = {
+ .name = "timer2",
+ .mpu_irqs = omap2_timer2_mpu_irqs,
+ .main_clk = "gpt2_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPT2_SHIFT,
+ .module_offs = CORE_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
+ },
+ },
+ .dev_attr = &capability_alwon_dev_attr,
+ .class = &omap2xxx_timer_hwmod_class,
+};
+
+/* timer3 */
+
+struct omap_hwmod omap2xxx_timer3_hwmod = {
+ .name = "timer3",
+ .mpu_irqs = omap2_timer3_mpu_irqs,
+ .main_clk = "gpt3_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPT3_SHIFT,
+ .module_offs = CORE_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
+ },
+ },
+ .dev_attr = &capability_alwon_dev_attr,
+ .class = &omap2xxx_timer_hwmod_class,
+};
+
+/* timer4 */
+
+struct omap_hwmod omap2xxx_timer4_hwmod = {
+ .name = "timer4",
+ .mpu_irqs = omap2_timer4_mpu_irqs,
+ .main_clk = "gpt4_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPT4_SHIFT,
+ .module_offs = CORE_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
+ },
+ },
+ .dev_attr = &capability_alwon_dev_attr,
+ .class = &omap2xxx_timer_hwmod_class,
+};
+
+/* timer5 */
+
+struct omap_hwmod omap2xxx_timer5_hwmod = {
+ .name = "timer5",
+ .mpu_irqs = omap2_timer5_mpu_irqs,
+ .main_clk = "gpt5_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPT5_SHIFT,
+ .module_offs = CORE_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
+ },
+ },
+ .dev_attr = &capability_alwon_dev_attr,
+ .class = &omap2xxx_timer_hwmod_class,
+};
+
+/* timer6 */
+
+struct omap_hwmod omap2xxx_timer6_hwmod = {
+ .name = "timer6",
+ .mpu_irqs = omap2_timer6_mpu_irqs,
+ .main_clk = "gpt6_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPT6_SHIFT,
+ .module_offs = CORE_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
+ },
+ },
+ .dev_attr = &capability_alwon_dev_attr,
+ .class = &omap2xxx_timer_hwmod_class,
+};
+
+/* timer7 */
+
+struct omap_hwmod omap2xxx_timer7_hwmod = {
+ .name = "timer7",
+ .mpu_irqs = omap2_timer7_mpu_irqs,
+ .main_clk = "gpt7_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPT7_SHIFT,
+ .module_offs = CORE_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
+ },
+ },
+ .dev_attr = &capability_alwon_dev_attr,
+ .class = &omap2xxx_timer_hwmod_class,
+};
+
+/* timer8 */
+
+struct omap_hwmod omap2xxx_timer8_hwmod = {
+ .name = "timer8",
+ .mpu_irqs = omap2_timer8_mpu_irqs,
+ .main_clk = "gpt8_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPT8_SHIFT,
+ .module_offs = CORE_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
+ },
+ },
+ .dev_attr = &capability_alwon_dev_attr,
+ .class = &omap2xxx_timer_hwmod_class,
+};
+
+/* timer9 */
+
+struct omap_hwmod omap2xxx_timer9_hwmod = {
+ .name = "timer9",
+ .mpu_irqs = omap2_timer9_mpu_irqs,
+ .main_clk = "gpt9_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPT9_SHIFT,
+ .module_offs = CORE_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
+ },
+ },
+ .dev_attr = &capability_pwm_dev_attr,
+ .class = &omap2xxx_timer_hwmod_class,
+};
+
+/* timer10 */
+
+struct omap_hwmod omap2xxx_timer10_hwmod = {
+ .name = "timer10",
+ .mpu_irqs = omap2_timer10_mpu_irqs,
+ .main_clk = "gpt10_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPT10_SHIFT,
+ .module_offs = CORE_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
+ },
+ },
+ .dev_attr = &capability_pwm_dev_attr,
+ .class = &omap2xxx_timer_hwmod_class,
+};
+
+/* timer11 */
+
+struct omap_hwmod omap2xxx_timer11_hwmod = {
+ .name = "timer11",
+ .mpu_irqs = omap2_timer11_mpu_irqs,
+ .main_clk = "gpt11_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPT11_SHIFT,
+ .module_offs = CORE_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
+ },
+ },
+ .dev_attr = &capability_pwm_dev_attr,
+ .class = &omap2xxx_timer_hwmod_class,
+};
+
+/* timer12 */
+
+struct omap_hwmod omap2xxx_timer12_hwmod = {
+ .name = "timer12",
+ .mpu_irqs = omap2xxx_timer12_mpu_irqs,
+ .main_clk = "gpt12_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPT12_SHIFT,
+ .module_offs = CORE_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
+ },
+ },
+ .dev_attr = &capability_pwm_dev_attr,
+ .class = &omap2xxx_timer_hwmod_class,
+};
+
+/* wd_timer2 */
+struct omap_hwmod omap2xxx_wd_timer2_hwmod = {
+ .name = "wd_timer2",
+ .class = &omap2xxx_wd_timer_hwmod_class,
+ .main_clk = "mpu_wdt_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
+ .module_offs = WKUP_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_MPU_WDT_SHIFT,
+ },
+ },
+};
+
+/* UART1 */
+
+struct omap_hwmod omap2xxx_uart1_hwmod = {
+ .name = "uart1",
+ .mpu_irqs = omap2_uart1_mpu_irqs,
+ .sdma_reqs = omap2_uart1_sdma_reqs,
+ .main_clk = "uart1_fck",
+ .prcm = {
+ .omap2 = {
+ .module_offs = CORE_MOD,
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_UART1_SHIFT,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT,
+ },
+ },
+ .class = &omap2_uart_class,
+};
+
+/* UART2 */
+
+struct omap_hwmod omap2xxx_uart2_hwmod = {
+ .name = "uart2",
+ .mpu_irqs = omap2_uart2_mpu_irqs,
+ .sdma_reqs = omap2_uart2_sdma_reqs,
+ .main_clk = "uart2_fck",
+ .prcm = {
+ .omap2 = {
+ .module_offs = CORE_MOD,
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_UART2_SHIFT,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT,
+ },
+ },
+ .class = &omap2_uart_class,
+};
+
+/* UART3 */
+
+struct omap_hwmod omap2xxx_uart3_hwmod = {
+ .name = "uart3",
+ .mpu_irqs = omap2_uart3_mpu_irqs,
+ .sdma_reqs = omap2_uart3_sdma_reqs,
+ .main_clk = "uart3_fck",
+ .prcm = {
+ .omap2 = {
+ .module_offs = CORE_MOD,
+ .prcm_reg_id = 2,
+ .module_bit = OMAP24XX_EN_UART3_SHIFT,
+ .idlest_reg_id = 2,
+ .idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT,
+ },
+ },
+ .class = &omap2_uart_class,
+};
+
+/* dss */
+
+static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+ /*
+ * The DSS HW needs all DSS clocks enabled during reset. The dss_core
+ * driver does not use these clocks.
+ */
+ { .role = "tv_clk", .clk = "dss_54m_fck" },
+ { .role = "sys_clk", .clk = "dss2_fck" },
+};
+
+struct omap_hwmod omap2xxx_dss_core_hwmod = {
+ .name = "dss_core",
+ .class = &omap2_dss_hwmod_class,
+ .main_clk = "dss1_fck", /* instead of dss_fck */
+ .sdma_reqs = omap2xxx_dss_sdma_chs,
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_DSS1_SHIFT,
+ .module_offs = CORE_MOD,
+ .idlest_reg_id = 1,
+ .idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
+ },
+ },
+ .opt_clks = dss_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
+ .flags = HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+};
+
+struct omap_hwmod omap2xxx_dss_dispc_hwmod = {
+ .name = "dss_dispc",
+ .class = &omap2_dispc_hwmod_class,
+ .mpu_irqs = omap2_dispc_irqs,
+ .main_clk = "dss1_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_DSS1_SHIFT,
+ .module_offs = CORE_MOD,
+ .idlest_reg_id = 1,
+ .idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
+ },
+ },
+ .flags = HWMOD_NO_IDLEST,
+ .dev_attr = &omap2_3_dss_dispc_dev_attr
+};
+
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+ { .role = "ick", .clk = "dss_ick" },
+};
+
+struct omap_hwmod omap2xxx_dss_rfbi_hwmod = {
+ .name = "dss_rfbi",
+ .class = &omap2_rfbi_hwmod_class,
+ .main_clk = "dss1_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_DSS1_SHIFT,
+ .module_offs = CORE_MOD,
+ },
+ },
+ .opt_clks = dss_rfbi_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(dss_rfbi_opt_clks),
+ .flags = HWMOD_NO_IDLEST,
+};
+
+struct omap_hwmod omap2xxx_dss_venc_hwmod = {
+ .name = "dss_venc",
+ .class = &omap2_venc_hwmod_class,
+ .main_clk = "dss_54m_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_DSS1_SHIFT,
+ .module_offs = CORE_MOD,
+ },
+ },
+ .flags = HWMOD_NO_IDLEST,
+};
+
+/* gpio dev_attr */
+struct omap_gpio_dev_attr omap2xxx_gpio_dev_attr = {
+ .bank_width = 32,
+ .dbck_flag = false,
+};
+
+/* gpio1 */
+struct omap_hwmod omap2xxx_gpio1_hwmod = {
+ .name = "gpio1",
+ .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+ .mpu_irqs = omap2_gpio1_irqs,
+ .main_clk = "gpios_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+ .module_offs = WKUP_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+ },
+ },
+ .class = &omap2xxx_gpio_hwmod_class,
+ .dev_attr = &omap2xxx_gpio_dev_attr,
+};
+
+/* gpio2 */
+struct omap_hwmod omap2xxx_gpio2_hwmod = {
+ .name = "gpio2",
+ .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+ .mpu_irqs = omap2_gpio2_irqs,
+ .main_clk = "gpios_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+ .module_offs = WKUP_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+ },
+ },
+ .class = &omap2xxx_gpio_hwmod_class,
+ .dev_attr = &omap2xxx_gpio_dev_attr,
+};
+
+/* gpio3 */
+struct omap_hwmod omap2xxx_gpio3_hwmod = {
+ .name = "gpio3",
+ .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+ .mpu_irqs = omap2_gpio3_irqs,
+ .main_clk = "gpios_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+ .module_offs = WKUP_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+ },
+ },
+ .class = &omap2xxx_gpio_hwmod_class,
+ .dev_attr = &omap2xxx_gpio_dev_attr,
+};
+
+/* gpio4 */
+struct omap_hwmod omap2xxx_gpio4_hwmod = {
+ .name = "gpio4",
+ .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+ .mpu_irqs = omap2_gpio4_irqs,
+ .main_clk = "gpios_fck",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+ .module_offs = WKUP_MOD,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+ },
+ },
+ .class = &omap2xxx_gpio_hwmod_class,
+ .dev_attr = &omap2xxx_gpio_dev_attr,
+};
+
+/* mcspi1 */
+static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
+ .num_chipselect = 4,
+};
+
+struct omap_hwmod omap2xxx_mcspi1_hwmod = {
+ .name = "mcspi1",
+ .mpu_irqs = omap2_mcspi1_mpu_irqs,
+ .sdma_reqs = omap2_mcspi1_sdma_reqs,
+ .main_clk = "mcspi1_fck",
+ .prcm = {
+ .omap2 = {
+ .module_offs = CORE_MOD,
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_MCSPI1_SHIFT,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_MCSPI1_SHIFT,
+ },
+ },
+ .class = &omap2xxx_mcspi_class,
+ .dev_attr = &omap_mcspi1_dev_attr,
+};
+
+/* mcspi2 */
+static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
+ .num_chipselect = 2,
+};
+
+struct omap_hwmod omap2xxx_mcspi2_hwmod = {
+ .name = "mcspi2",
+ .mpu_irqs = omap2_mcspi2_mpu_irqs,
+ .sdma_reqs = omap2_mcspi2_sdma_reqs,
+ .main_clk = "mcspi2_fck",
+ .prcm = {
+ .omap2 = {
+ .module_offs = CORE_MOD,
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_EN_MCSPI2_SHIFT,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_MCSPI2_SHIFT,
+ },
+ },
+ .class = &omap2xxx_mcspi_class,
+ .dev_attr = &omap_mcspi2_dev_attr,
+};
+
+
+static struct omap_hwmod_class omap2xxx_counter_hwmod_class = {
+ .name = "counter",
+};
+
+struct omap_hwmod omap2xxx_counter_32k_hwmod = {
+ .name = "counter_32k",
+ .main_clk = "func_32k_ck",
+ .prcm = {
+ .omap2 = {
+ .module_offs = WKUP_MOD,
+ .prcm_reg_id = 1,
+ .module_bit = OMAP24XX_ST_32KSYNC_SHIFT,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP24XX_ST_32KSYNC_SHIFT,
+ },
+ },
+ .class = &omap2xxx_counter_hwmod_class,
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index db86ce90c69f..fd48797fa95a 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -2,6 +2,7 @@
* omap_hwmod_3xxx_data.c - hardware modules present on the OMAP3xxx chips
*
* Copyright (C) 2009-2011 Nokia Corporation
+ * Copyright (C) 2012 Texas Instruments, Inc.
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
@@ -38,491 +39,56 @@
/*
* OMAP3xxx hardware module integration data
*
- * ALl of the data in this section should be autogeneratable from the
+ * All of the data in this section should be autogeneratable from the
* TI hardware database or other technical documentation. Data that
* is driver-specific or driver-kernel integration-specific belongs
* elsewhere.
*/
-static struct omap_hwmod omap3xxx_mpu_hwmod;
-static struct omap_hwmod omap3xxx_iva_hwmod;
-static struct omap_hwmod omap3xxx_l3_main_hwmod;
-static struct omap_hwmod omap3xxx_l4_core_hwmod;
-static struct omap_hwmod omap3xxx_l4_per_hwmod;
-static struct omap_hwmod omap3xxx_wd_timer2_hwmod;
-static struct omap_hwmod omap3430es1_dss_core_hwmod;
-static struct omap_hwmod omap3xxx_dss_core_hwmod;
-static struct omap_hwmod omap3xxx_dss_dispc_hwmod;
-static struct omap_hwmod omap3xxx_dss_dsi1_hwmod;
-static struct omap_hwmod omap3xxx_dss_rfbi_hwmod;
-static struct omap_hwmod omap3xxx_dss_venc_hwmod;
-static struct omap_hwmod omap3xxx_i2c1_hwmod;
-static struct omap_hwmod omap3xxx_i2c2_hwmod;
-static struct omap_hwmod omap3xxx_i2c3_hwmod;
-static struct omap_hwmod omap3xxx_gpio1_hwmod;
-static struct omap_hwmod omap3xxx_gpio2_hwmod;
-static struct omap_hwmod omap3xxx_gpio3_hwmod;
-static struct omap_hwmod omap3xxx_gpio4_hwmod;
-static struct omap_hwmod omap3xxx_gpio5_hwmod;
-static struct omap_hwmod omap3xxx_gpio6_hwmod;
-static struct omap_hwmod omap34xx_sr1_hwmod;
-static struct omap_hwmod omap34xx_sr2_hwmod;
-static struct omap_hwmod omap34xx_mcspi1;
-static struct omap_hwmod omap34xx_mcspi2;
-static struct omap_hwmod omap34xx_mcspi3;
-static struct omap_hwmod omap34xx_mcspi4;
-static struct omap_hwmod omap3xxx_mmc1_hwmod;
-static struct omap_hwmod omap3xxx_mmc2_hwmod;
-static struct omap_hwmod omap3xxx_mmc3_hwmod;
-static struct omap_hwmod am35xx_usbhsotg_hwmod;
-
-static struct omap_hwmod omap3xxx_dma_system_hwmod;
-
-static struct omap_hwmod omap3xxx_mcbsp1_hwmod;
-static struct omap_hwmod omap3xxx_mcbsp2_hwmod;
-static struct omap_hwmod omap3xxx_mcbsp3_hwmod;
-static struct omap_hwmod omap3xxx_mcbsp4_hwmod;
-static struct omap_hwmod omap3xxx_mcbsp5_hwmod;
-static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod;
-static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod;
-static struct omap_hwmod omap3xxx_usb_host_hs_hwmod;
-static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod;
-
-/* L3 -> L4_CORE interface */
-static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
- .master = &omap3xxx_l3_main_hwmod,
- .slave = &omap3xxx_l4_core_hwmod,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L3 -> L4_PER interface */
-static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_per = {
- .master = &omap3xxx_l3_main_hwmod,
- .slave = &omap3xxx_l4_per_hwmod,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
+/*
+ * IP blocks
+ */
-/* L3 taret configuration and error log registers */
+/* L3 */
static struct omap_hwmod_irq_info omap3xxx_l3_main_irqs[] = {
{ .irq = INT_34XX_L3_DBG_IRQ },
{ .irq = INT_34XX_L3_APP_IRQ },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap3xxx_l3_main_addrs[] = {
- {
- .pa_start = 0x68000000,
- .pa_end = 0x6800ffff,
- .flags = ADDR_TYPE_RT,
- },
- { }
-};
-
-/* MPU -> L3 interface */
-static struct omap_hwmod_ocp_if omap3xxx_mpu__l3_main = {
- .master = &omap3xxx_mpu_hwmod,
- .slave = &omap3xxx_l3_main_hwmod,
- .addr = omap3xxx_l3_main_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* Slave interfaces on the L3 interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l3_main_slaves[] = {
- &omap3xxx_mpu__l3_main,
-};
-
-/* DSS -> l3 */
-static struct omap_hwmod_ocp_if omap3xxx_dss__l3 = {
- .master = &omap3xxx_dss_core_hwmod,
- .slave = &omap3xxx_l3_main_hwmod,
- .fw = {
- .omap2 = {
- .l3_perm_bit = OMAP3_L3_CORE_FW_INIT_ID_DSS,
- .flags = OMAP_FIREWALL_L3,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* Master interfaces on the L3 interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l3_main_masters[] = {
- &omap3xxx_l3_main__l4_core,
- &omap3xxx_l3_main__l4_per,
-};
-
-/* L3 */
static struct omap_hwmod omap3xxx_l3_main_hwmod = {
.name = "l3_main",
.class = &l3_hwmod_class,
.mpu_irqs = omap3xxx_l3_main_irqs,
- .masters = omap3xxx_l3_main_masters,
- .masters_cnt = ARRAY_SIZE(omap3xxx_l3_main_masters),
- .slaves = omap3xxx_l3_main_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_l3_main_slaves),
.flags = HWMOD_NO_IDLEST,
};
-static struct omap_hwmod omap3xxx_l4_wkup_hwmod;
-static struct omap_hwmod omap3xxx_uart1_hwmod;
-static struct omap_hwmod omap3xxx_uart2_hwmod;
-static struct omap_hwmod omap3xxx_uart3_hwmod;
-static struct omap_hwmod omap3xxx_uart4_hwmod;
-static struct omap_hwmod am35xx_uart4_hwmod;
-static struct omap_hwmod omap3xxx_usbhsotg_hwmod;
-
-/* l3_core -> usbhsotg interface */
-static struct omap_hwmod_ocp_if omap3xxx_usbhsotg__l3 = {
- .master = &omap3xxx_usbhsotg_hwmod,
- .slave = &omap3xxx_l3_main_hwmod,
- .clk = "core_l3_ick",
- .user = OCP_USER_MPU,
-};
-
-/* l3_core -> am35xx_usbhsotg interface */
-static struct omap_hwmod_ocp_if am35xx_usbhsotg__l3 = {
- .master = &am35xx_usbhsotg_hwmod,
- .slave = &omap3xxx_l3_main_hwmod,
- .clk = "core_l3_ick",
- .user = OCP_USER_MPU,
-};
-/* L4_CORE -> L4_WKUP interface */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_l4_wkup_hwmod,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> MMC1 interface */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc1 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_mmc1_hwmod,
- .clk = "mmchs1_ick",
- .addr = omap2430_mmc1_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
- .flags = OMAP_FIREWALL_L4
-};
-
-/* L4 CORE -> MMC2 interface */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc2 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_mmc2_hwmod,
- .clk = "mmchs2_ick",
- .addr = omap2430_mmc2_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
- .flags = OMAP_FIREWALL_L4
-};
-
-/* L4 CORE -> MMC3 interface */
-static struct omap_hwmod_addr_space omap3xxx_mmc3_addr_space[] = {
- {
- .pa_start = 0x480ad000,
- .pa_end = 0x480ad1ff,
- .flags = ADDR_TYPE_RT,
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc3 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_mmc3_hwmod,
- .clk = "mmchs3_ick",
- .addr = omap3xxx_mmc3_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
- .flags = OMAP_FIREWALL_L4
-};
-
-/* L4 CORE -> UART1 interface */
-static struct omap_hwmod_addr_space omap3xxx_uart1_addr_space[] = {
- {
- .pa_start = OMAP3_UART1_BASE,
- .pa_end = OMAP3_UART1_BASE + SZ_8K - 1,
- .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3_l4_core__uart1 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_uart1_hwmod,
- .clk = "uart1_ick",
- .addr = omap3xxx_uart1_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> UART2 interface */
-static struct omap_hwmod_addr_space omap3xxx_uart2_addr_space[] = {
- {
- .pa_start = OMAP3_UART2_BASE,
- .pa_end = OMAP3_UART2_BASE + SZ_1K - 1,
- .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3_l4_core__uart2 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_uart2_hwmod,
- .clk = "uart2_ick",
- .addr = omap3xxx_uart2_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 PER -> UART3 interface */
-static struct omap_hwmod_addr_space omap3xxx_uart3_addr_space[] = {
- {
- .pa_start = OMAP3_UART3_BASE,
- .pa_end = OMAP3_UART3_BASE + SZ_1K - 1,
- .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3_l4_per__uart3 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_uart3_hwmod,
- .clk = "uart3_ick",
- .addr = omap3xxx_uart3_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 PER -> UART4 interface */
-static struct omap_hwmod_addr_space omap3xxx_uart4_addr_space[] = {
- {
- .pa_start = OMAP3_UART4_BASE,
- .pa_end = OMAP3_UART4_BASE + SZ_1K - 1,
- .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3_l4_per__uart4 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_uart4_hwmod,
- .clk = "uart4_ick",
- .addr = omap3xxx_uart4_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* AM35xx: L4 CORE -> UART4 interface */
-static struct omap_hwmod_addr_space am35xx_uart4_addr_space[] = {
- {
- .pa_start = OMAP3_UART4_AM35XX_BASE,
- .pa_end = OMAP3_UART4_AM35XX_BASE + SZ_1K - 1,
- .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
- },
-};
-
-static struct omap_hwmod_ocp_if am35xx_l4_core__uart4 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &am35xx_uart4_hwmod,
- .clk = "uart4_ick",
- .addr = am35xx_uart4_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> I2C1 interface */
-static struct omap_hwmod_ocp_if omap3_l4_core__i2c1 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_i2c1_hwmod,
- .clk = "i2c1_ick",
- .addr = omap2_i2c1_addr_space,
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP3_L4_CORE_FW_I2C1_REGION,
- .l4_prot_group = 7,
- .flags = OMAP_FIREWALL_L4,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> I2C2 interface */
-static struct omap_hwmod_ocp_if omap3_l4_core__i2c2 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_i2c2_hwmod,
- .clk = "i2c2_ick",
- .addr = omap2_i2c2_addr_space,
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP3_L4_CORE_FW_I2C2_REGION,
- .l4_prot_group = 7,
- .flags = OMAP_FIREWALL_L4,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* L4 CORE -> I2C3 interface */
-static struct omap_hwmod_addr_space omap3xxx_i2c3_addr_space[] = {
- {
- .pa_start = 0x48060000,
- .pa_end = 0x48060000 + SZ_128 - 1,
- .flags = ADDR_TYPE_RT,
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_i2c3_hwmod,
- .clk = "i2c3_ick",
- .addr = omap3xxx_i2c3_addr_space,
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP3_L4_CORE_FW_I2C3_REGION,
- .l4_prot_group = 7,
- .flags = OMAP_FIREWALL_L4,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = {
- { .irq = 18},
- { .irq = -1 }
-};
-
-static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = {
- { .irq = 19},
- { .irq = -1 }
-};
-
-/* L4 CORE -> SR1 interface */
-static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = {
- {
- .pa_start = OMAP34XX_SR1_BASE,
- .pa_end = OMAP34XX_SR1_BASE + SZ_1K - 1,
- .flags = ADDR_TYPE_RT,
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3_l4_core__sr1 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap34xx_sr1_hwmod,
- .clk = "sr_l4_ick",
- .addr = omap3_sr1_addr_space,
- .user = OCP_USER_MPU,
-};
-
-/* L4 CORE -> SR1 interface */
-static struct omap_hwmod_addr_space omap3_sr2_addr_space[] = {
- {
- .pa_start = OMAP34XX_SR2_BASE,
- .pa_end = OMAP34XX_SR2_BASE + SZ_1K - 1,
- .flags = ADDR_TYPE_RT,
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3_l4_core__sr2 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap34xx_sr2_hwmod,
- .clk = "sr_l4_ick",
- .addr = omap3_sr2_addr_space,
- .user = OCP_USER_MPU,
-};
-
-/*
-* usbhsotg interface data
-*/
-
-static struct omap_hwmod_addr_space omap3xxx_usbhsotg_addrs[] = {
- {
- .pa_start = OMAP34XX_HSUSB_OTG_BASE,
- .pa_end = OMAP34XX_HSUSB_OTG_BASE + SZ_4K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_core -> usbhsotg */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__usbhsotg = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_usbhsotg_hwmod,
- .clk = "l4_ick",
- .addr = omap3xxx_usbhsotg_addrs,
- .user = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if *omap3xxx_usbhsotg_masters[] = {
- &omap3xxx_usbhsotg__l3,
-};
-
-static struct omap_hwmod_ocp_if *omap3xxx_usbhsotg_slaves[] = {
- &omap3xxx_l4_core__usbhsotg,
-};
-
-static struct omap_hwmod_addr_space am35xx_usbhsotg_addrs[] = {
- {
- .pa_start = AM35XX_IPSS_USBOTGSS_BASE,
- .pa_end = AM35XX_IPSS_USBOTGSS_BASE + SZ_4K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_core -> usbhsotg */
-static struct omap_hwmod_ocp_if am35xx_l4_core__usbhsotg = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &am35xx_usbhsotg_hwmod,
- .clk = "l4_ick",
- .addr = am35xx_usbhsotg_addrs,
- .user = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if *am35xx_usbhsotg_masters[] = {
- &am35xx_usbhsotg__l3,
-};
-
-static struct omap_hwmod_ocp_if *am35xx_usbhsotg_slaves[] = {
- &am35xx_l4_core__usbhsotg,
-};
-/* Slave interfaces on the L4_CORE interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
- &omap3xxx_l3_main__l4_core,
-};
-
/* L4 CORE */
static struct omap_hwmod omap3xxx_l4_core_hwmod = {
.name = "l4_core",
.class = &l4_hwmod_class,
- .slaves = omap3xxx_l4_core_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_l4_core_slaves),
.flags = HWMOD_NO_IDLEST,
};
-/* Slave interfaces on the L4_PER interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l4_per_slaves[] = {
- &omap3xxx_l3_main__l4_per,
-};
-
/* L4 PER */
static struct omap_hwmod omap3xxx_l4_per_hwmod = {
.name = "l4_per",
.class = &l4_hwmod_class,
- .slaves = omap3xxx_l4_per_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_l4_per_slaves),
.flags = HWMOD_NO_IDLEST,
};
-/* Slave interfaces on the L4_WKUP interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l4_wkup_slaves[] = {
- &omap3xxx_l4_core__l4_wkup,
-};
-
/* L4 WKUP */
static struct omap_hwmod omap3xxx_l4_wkup_hwmod = {
.name = "l4_wkup",
.class = &l4_hwmod_class,
- .slaves = omap3xxx_l4_wkup_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_l4_wkup_slaves),
.flags = HWMOD_NO_IDLEST,
};
-/* Master interfaces on the MPU device */
-static struct omap_hwmod_ocp_if *omap3xxx_mpu_masters[] = {
- &omap3xxx_mpu__l3_main,
+/* L4 SEC */
+static struct omap_hwmod omap3xxx_l4_sec_hwmod = {
+ .name = "l4_sec",
+ .class = &l4_hwmod_class,
+ .flags = HWMOD_NO_IDLEST,
};
/* MPU */
@@ -530,35 +96,22 @@ static struct omap_hwmod omap3xxx_mpu_hwmod = {
.name = "mpu",
.class = &mpu_hwmod_class,
.main_clk = "arm_fck",
- .masters = omap3xxx_mpu_masters,
- .masters_cnt = ARRAY_SIZE(omap3xxx_mpu_masters),
};
-/*
- * IVA2_2 interface data
- */
-
-/* IVA2 <- L3 interface */
-static struct omap_hwmod_ocp_if omap3xxx_l3__iva = {
- .master = &omap3xxx_l3_main_hwmod,
- .slave = &omap3xxx_iva_hwmod,
- .clk = "iva2_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
+/* IVA2 (IVA2) */
+static struct omap_hwmod_rst_info omap3xxx_iva_resets[] = {
+ { .name = "logic", .rst_shift = 0 },
+ { .name = "seq0", .rst_shift = 1 },
+ { .name = "seq1", .rst_shift = 2 },
};
-static struct omap_hwmod_ocp_if *omap3xxx_iva_masters[] = {
- &omap3xxx_l3__iva,
-};
-
-/*
- * IVA2 (IVA2)
- */
-
static struct omap_hwmod omap3xxx_iva_hwmod = {
.name = "iva",
.class = &iva_hwmod_class,
- .masters = omap3xxx_iva_masters,
- .masters_cnt = ARRAY_SIZE(omap3xxx_iva_masters),
+ .clkdm_name = "iva2_clkdm",
+ .rst_lines = omap3xxx_iva_resets,
+ .rst_lines_cnt = ARRAY_SIZE(omap3xxx_iva_resets),
+ .main_clk = "iva2_ck",
};
/* timer class */
@@ -597,46 +150,20 @@ static struct omap_hwmod_class omap3xxx_timer_hwmod_class = {
/* secure timers dev attribute */
static struct omap_timer_capability_dev_attr capability_secure_dev_attr = {
- .timer_capability = OMAP_TIMER_SECURE,
+ .timer_capability = OMAP_TIMER_SECURE,
};
/* always-on timers dev attribute */
static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
- .timer_capability = OMAP_TIMER_ALWON,
+ .timer_capability = OMAP_TIMER_ALWON,
};
/* pwm timers dev attribute */
static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
- .timer_capability = OMAP_TIMER_HAS_PWM,
+ .timer_capability = OMAP_TIMER_HAS_PWM,
};
/* timer1 */
-static struct omap_hwmod omap3xxx_timer1_hwmod;
-
-static struct omap_hwmod_addr_space omap3xxx_timer1_addrs[] = {
- {
- .pa_start = 0x48318000,
- .pa_end = 0x48318000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_wkup -> timer1 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__timer1 = {
- .master = &omap3xxx_l4_wkup_hwmod,
- .slave = &omap3xxx_timer1_hwmod,
- .clk = "gpt1_ick",
- .addr = omap3xxx_timer1_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer1 slave port */
-static struct omap_hwmod_ocp_if *omap3xxx_timer1_slaves[] = {
- &omap3xxx_l4_wkup__timer1,
-};
-
-/* timer1 hwmod */
static struct omap_hwmod omap3xxx_timer1_hwmod = {
.name = "timer1",
.mpu_irqs = omap2_timer1_mpu_irqs,
@@ -651,38 +178,10 @@ static struct omap_hwmod omap3xxx_timer1_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap3xxx_timer1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_timer1_slaves),
.class = &omap3xxx_timer_1ms_hwmod_class,
};
/* timer2 */
-static struct omap_hwmod omap3xxx_timer2_hwmod;
-
-static struct omap_hwmod_addr_space omap3xxx_timer2_addrs[] = {
- {
- .pa_start = 0x49032000,
- .pa_end = 0x49032000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer2 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer2 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_timer2_hwmod,
- .clk = "gpt2_ick",
- .addr = omap3xxx_timer2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer2 slave port */
-static struct omap_hwmod_ocp_if *omap3xxx_timer2_slaves[] = {
- &omap3xxx_l4_per__timer2,
-};
-
-/* timer2 hwmod */
static struct omap_hwmod omap3xxx_timer2_hwmod = {
.name = "timer2",
.mpu_irqs = omap2_timer2_mpu_irqs,
@@ -697,38 +196,10 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap3xxx_timer2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_timer2_slaves),
.class = &omap3xxx_timer_1ms_hwmod_class,
};
/* timer3 */
-static struct omap_hwmod omap3xxx_timer3_hwmod;
-
-static struct omap_hwmod_addr_space omap3xxx_timer3_addrs[] = {
- {
- .pa_start = 0x49034000,
- .pa_end = 0x49034000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer3 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer3 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_timer3_hwmod,
- .clk = "gpt3_ick",
- .addr = omap3xxx_timer3_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer3 slave port */
-static struct omap_hwmod_ocp_if *omap3xxx_timer3_slaves[] = {
- &omap3xxx_l4_per__timer3,
-};
-
-/* timer3 hwmod */
static struct omap_hwmod omap3xxx_timer3_hwmod = {
.name = "timer3",
.mpu_irqs = omap2_timer3_mpu_irqs,
@@ -743,38 +214,10 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap3xxx_timer3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_timer3_slaves),
.class = &omap3xxx_timer_hwmod_class,
};
/* timer4 */
-static struct omap_hwmod omap3xxx_timer4_hwmod;
-
-static struct omap_hwmod_addr_space omap3xxx_timer4_addrs[] = {
- {
- .pa_start = 0x49036000,
- .pa_end = 0x49036000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer4 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer4 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_timer4_hwmod,
- .clk = "gpt4_ick",
- .addr = omap3xxx_timer4_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer4 slave port */
-static struct omap_hwmod_ocp_if *omap3xxx_timer4_slaves[] = {
- &omap3xxx_l4_per__timer4,
-};
-
-/* timer4 hwmod */
static struct omap_hwmod omap3xxx_timer4_hwmod = {
.name = "timer4",
.mpu_irqs = omap2_timer4_mpu_irqs,
@@ -789,38 +232,10 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap3xxx_timer4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_timer4_slaves),
.class = &omap3xxx_timer_hwmod_class,
};
/* timer5 */
-static struct omap_hwmod omap3xxx_timer5_hwmod;
-
-static struct omap_hwmod_addr_space omap3xxx_timer5_addrs[] = {
- {
- .pa_start = 0x49038000,
- .pa_end = 0x49038000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer5 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer5 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_timer5_hwmod,
- .clk = "gpt5_ick",
- .addr = omap3xxx_timer5_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer5 slave port */
-static struct omap_hwmod_ocp_if *omap3xxx_timer5_slaves[] = {
- &omap3xxx_l4_per__timer5,
-};
-
-/* timer5 hwmod */
static struct omap_hwmod omap3xxx_timer5_hwmod = {
.name = "timer5",
.mpu_irqs = omap2_timer5_mpu_irqs,
@@ -835,38 +250,10 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap3xxx_timer5_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_timer5_slaves),
.class = &omap3xxx_timer_hwmod_class,
};
/* timer6 */
-static struct omap_hwmod omap3xxx_timer6_hwmod;
-
-static struct omap_hwmod_addr_space omap3xxx_timer6_addrs[] = {
- {
- .pa_start = 0x4903A000,
- .pa_end = 0x4903A000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer6 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer6 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_timer6_hwmod,
- .clk = "gpt6_ick",
- .addr = omap3xxx_timer6_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer6 slave port */
-static struct omap_hwmod_ocp_if *omap3xxx_timer6_slaves[] = {
- &omap3xxx_l4_per__timer6,
-};
-
-/* timer6 hwmod */
static struct omap_hwmod omap3xxx_timer6_hwmod = {
.name = "timer6",
.mpu_irqs = omap2_timer6_mpu_irqs,
@@ -881,38 +268,10 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap3xxx_timer6_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_timer6_slaves),
.class = &omap3xxx_timer_hwmod_class,
};
/* timer7 */
-static struct omap_hwmod omap3xxx_timer7_hwmod;
-
-static struct omap_hwmod_addr_space omap3xxx_timer7_addrs[] = {
- {
- .pa_start = 0x4903C000,
- .pa_end = 0x4903C000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer7 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer7 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_timer7_hwmod,
- .clk = "gpt7_ick",
- .addr = omap3xxx_timer7_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer7 slave port */
-static struct omap_hwmod_ocp_if *omap3xxx_timer7_slaves[] = {
- &omap3xxx_l4_per__timer7,
-};
-
-/* timer7 hwmod */
static struct omap_hwmod omap3xxx_timer7_hwmod = {
.name = "timer7",
.mpu_irqs = omap2_timer7_mpu_irqs,
@@ -927,38 +286,10 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap3xxx_timer7_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_timer7_slaves),
.class = &omap3xxx_timer_hwmod_class,
};
/* timer8 */
-static struct omap_hwmod omap3xxx_timer8_hwmod;
-
-static struct omap_hwmod_addr_space omap3xxx_timer8_addrs[] = {
- {
- .pa_start = 0x4903E000,
- .pa_end = 0x4903E000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer8 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer8 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_timer8_hwmod,
- .clk = "gpt8_ick",
- .addr = omap3xxx_timer8_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer8 slave port */
-static struct omap_hwmod_ocp_if *omap3xxx_timer8_slaves[] = {
- &omap3xxx_l4_per__timer8,
-};
-
-/* timer8 hwmod */
static struct omap_hwmod omap3xxx_timer8_hwmod = {
.name = "timer8",
.mpu_irqs = omap2_timer8_mpu_irqs,
@@ -973,38 +304,10 @@ static struct omap_hwmod omap3xxx_timer8_hwmod = {
},
},
.dev_attr = &capability_pwm_dev_attr,
- .slaves = omap3xxx_timer8_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_timer8_slaves),
.class = &omap3xxx_timer_hwmod_class,
};
/* timer9 */
-static struct omap_hwmod omap3xxx_timer9_hwmod;
-
-static struct omap_hwmod_addr_space omap3xxx_timer9_addrs[] = {
- {
- .pa_start = 0x49040000,
- .pa_end = 0x49040000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer9 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer9 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_timer9_hwmod,
- .clk = "gpt9_ick",
- .addr = omap3xxx_timer9_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer9 slave port */
-static struct omap_hwmod_ocp_if *omap3xxx_timer9_slaves[] = {
- &omap3xxx_l4_per__timer9,
-};
-
-/* timer9 hwmod */
static struct omap_hwmod omap3xxx_timer9_hwmod = {
.name = "timer9",
.mpu_irqs = omap2_timer9_mpu_irqs,
@@ -1019,29 +322,10 @@ static struct omap_hwmod omap3xxx_timer9_hwmod = {
},
},
.dev_attr = &capability_pwm_dev_attr,
- .slaves = omap3xxx_timer9_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_timer9_slaves),
.class = &omap3xxx_timer_hwmod_class,
};
/* timer10 */
-static struct omap_hwmod omap3xxx_timer10_hwmod;
-
-/* l4_core -> timer10 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer10 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_timer10_hwmod,
- .clk = "gpt10_ick",
- .addr = omap2_timer10_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer10 slave port */
-static struct omap_hwmod_ocp_if *omap3xxx_timer10_slaves[] = {
- &omap3xxx_l4_core__timer10,
-};
-
-/* timer10 hwmod */
static struct omap_hwmod omap3xxx_timer10_hwmod = {
.name = "timer10",
.mpu_irqs = omap2_timer10_mpu_irqs,
@@ -1056,29 +340,10 @@ static struct omap_hwmod omap3xxx_timer10_hwmod = {
},
},
.dev_attr = &capability_pwm_dev_attr,
- .slaves = omap3xxx_timer10_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_timer10_slaves),
.class = &omap3xxx_timer_1ms_hwmod_class,
};
/* timer11 */
-static struct omap_hwmod omap3xxx_timer11_hwmod;
-
-/* l4_core -> timer11 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer11 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_timer11_hwmod,
- .clk = "gpt11_ick",
- .addr = omap2_timer11_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer11 slave port */
-static struct omap_hwmod_ocp_if *omap3xxx_timer11_slaves[] = {
- &omap3xxx_l4_core__timer11,
-};
-
-/* timer11 hwmod */
static struct omap_hwmod omap3xxx_timer11_hwmod = {
.name = "timer11",
.mpu_irqs = omap2_timer11_mpu_irqs,
@@ -1093,42 +358,15 @@ static struct omap_hwmod omap3xxx_timer11_hwmod = {
},
},
.dev_attr = &capability_pwm_dev_attr,
- .slaves = omap3xxx_timer11_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_timer11_slaves),
.class = &omap3xxx_timer_hwmod_class,
};
-/* timer12*/
-static struct omap_hwmod omap3xxx_timer12_hwmod;
+/* timer12 */
static struct omap_hwmod_irq_info omap3xxx_timer12_mpu_irqs[] = {
{ .irq = 95, },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap3xxx_timer12_addrs[] = {
- {
- .pa_start = 0x48304000,
- .pa_end = 0x48304000 + SZ_1K - 1,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_core -> timer12 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer12 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_timer12_hwmod,
- .clk = "gpt12_ick",
- .addr = omap3xxx_timer12_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer12 slave port */
-static struct omap_hwmod_ocp_if *omap3xxx_timer12_slaves[] = {
- &omap3xxx_l4_core__timer12,
-};
-
-/* timer12 hwmod */
static struct omap_hwmod omap3xxx_timer12_hwmod = {
.name = "timer12",
.mpu_irqs = omap3xxx_timer12_mpu_irqs,
@@ -1143,29 +381,9 @@ static struct omap_hwmod omap3xxx_timer12_hwmod = {
},
},
.dev_attr = &capability_secure_dev_attr,
- .slaves = omap3xxx_timer12_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_timer12_slaves),
.class = &omap3xxx_timer_hwmod_class,
};
-/* l4_wkup -> wd_timer2 */
-static struct omap_hwmod_addr_space omap3xxx_wd_timer2_addrs[] = {
- {
- .pa_start = 0x48314000,
- .pa_end = 0x4831407f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__wd_timer2 = {
- .master = &omap3xxx_l4_wkup_hwmod,
- .slave = &omap3xxx_wd_timer2_hwmod,
- .clk = "wdt2_ick",
- .addr = omap3xxx_wd_timer2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
/*
* 'wd_timer' class
* 32-bit watchdog upward counter that generates a pulse on the reset pin on
@@ -1200,12 +418,8 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
static struct omap_hwmod_class omap3xxx_wd_timer_hwmod_class = {
.name = "wd_timer",
.sysc = &omap3xxx_wd_timer_sysc,
- .pre_shutdown = &omap2_wd_timer_disable
-};
-
-/* wd_timer2 */
-static struct omap_hwmod_ocp_if *omap3xxx_wd_timer2_slaves[] = {
- &omap3xxx_l4_wkup__wd_timer2,
+ .pre_shutdown = &omap2_wd_timer_disable,
+ .reset = &omap2_wd_timer_reset,
};
static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
@@ -1221,8 +435,6 @@ static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
.idlest_idle_bit = OMAP3430_ST_WDT2_SHIFT,
},
},
- .slaves = omap3xxx_wd_timer2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_wd_timer2_slaves),
/*
* XXX: Use software supervised mode, HW supervised smartidle seems to
* block CORE power domain idle transitions. Maybe a HW bug in wdt2?
@@ -1231,11 +443,6 @@ static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
};
/* UART1 */
-
-static struct omap_hwmod_ocp_if *omap3xxx_uart1_slaves[] = {
- &omap3_l4_core__uart1,
-};
-
static struct omap_hwmod omap3xxx_uart1_hwmod = {
.name = "uart1",
.mpu_irqs = omap2_uart1_mpu_irqs,
@@ -1250,17 +457,10 @@ static struct omap_hwmod omap3xxx_uart1_hwmod = {
.idlest_idle_bit = OMAP3430_EN_UART1_SHIFT,
},
},
- .slaves = omap3xxx_uart1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_uart1_slaves),
.class = &omap2_uart_class,
};
/* UART2 */
-
-static struct omap_hwmod_ocp_if *omap3xxx_uart2_slaves[] = {
- &omap3_l4_core__uart2,
-};
-
static struct omap_hwmod omap3xxx_uart2_hwmod = {
.name = "uart2",
.mpu_irqs = omap2_uart2_mpu_irqs,
@@ -1275,17 +475,10 @@ static struct omap_hwmod omap3xxx_uart2_hwmod = {
.idlest_idle_bit = OMAP3430_EN_UART2_SHIFT,
},
},
- .slaves = omap3xxx_uart2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_uart2_slaves),
.class = &omap2_uart_class,
};
/* UART3 */
-
-static struct omap_hwmod_ocp_if *omap3xxx_uart3_slaves[] = {
- &omap3_l4_per__uart3,
-};
-
static struct omap_hwmod omap3xxx_uart3_hwmod = {
.name = "uart3",
.mpu_irqs = omap2_uart3_mpu_irqs,
@@ -1300,13 +493,10 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = {
.idlest_idle_bit = OMAP3430_EN_UART3_SHIFT,
},
},
- .slaves = omap3xxx_uart3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_uart3_slaves),
.class = &omap2_uart_class,
};
/* UART4 */
-
static struct omap_hwmod_irq_info uart4_mpu_irqs[] = {
{ .irq = INT_36XX_UART4_IRQ, },
{ .irq = -1 }
@@ -1318,11 +508,7 @@ static struct omap_hwmod_dma_info uart4_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
- &omap3_l4_per__uart4,
-};
-
-static struct omap_hwmod omap3xxx_uart4_hwmod = {
+static struct omap_hwmod omap36xx_uart4_hwmod = {
.name = "uart4",
.mpu_irqs = uart4_mpu_irqs,
.sdma_reqs = uart4_sdma_reqs,
@@ -1336,8 +522,6 @@ static struct omap_hwmod omap3xxx_uart4_hwmod = {
.idlest_idle_bit = OMAP3630_EN_UART4_SHIFT,
},
},
- .slaves = omap3xxx_uart4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_uart4_slaves),
.class = &omap2_uart_class,
};
@@ -1350,16 +534,12 @@ static struct omap_hwmod_dma_info am35xx_uart4_sdma_reqs[] = {
{ .name = "tx", .dma_req = AM35XX_DMA_UART4_TX, },
};
-static struct omap_hwmod_ocp_if *am35xx_uart4_slaves[] = {
- &am35xx_l4_core__uart4,
-};
-
static struct omap_hwmod am35xx_uart4_hwmod = {
- .name = "uart4",
- .mpu_irqs = am35xx_uart4_mpu_irqs,
- .sdma_reqs = am35xx_uart4_sdma_reqs,
- .main_clk = "uart4_fck",
- .prcm = {
+ .name = "uart4",
+ .mpu_irqs = am35xx_uart4_mpu_irqs,
+ .sdma_reqs = am35xx_uart4_sdma_reqs,
+ .main_clk = "uart4_fck",
+ .prcm = {
.omap2 = {
.module_offs = CORE_MOD,
.prcm_reg_id = 1,
@@ -1368,12 +548,9 @@ static struct omap_hwmod am35xx_uart4_hwmod = {
.idlest_idle_bit = OMAP3430_EN_UART4_SHIFT,
},
},
- .slaves = am35xx_uart4_slaves,
- .slaves_cnt = ARRAY_SIZE(am35xx_uart4_slaves),
- .class = &omap2_uart_class,
+ .class = &omap2_uart_class,
};
-
static struct omap_hwmod_class i2c_class = {
.name = "i2c",
.sysc = &i2c_sysc,
@@ -1388,51 +565,6 @@ static struct omap_hwmod_dma_info omap3xxx_dss_sdma_chs[] = {
};
/* dss */
-/* dss master ports */
-static struct omap_hwmod_ocp_if *omap3xxx_dss_masters[] = {
- &omap3xxx_dss__l3,
-};
-
-/* l4_core -> dss */
-static struct omap_hwmod_ocp_if omap3430es1_l4_core__dss = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3430es1_dss_core_hwmod,
- .clk = "dss_ick",
- .addr = omap2_dss_addrs,
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP3ES1_L4_CORE_FW_DSS_CORE_REGION,
- .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
- .flags = OMAP_FIREWALL_L4,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_dss_core_hwmod,
- .clk = "dss_ick",
- .addr = omap2_dss_addrs,
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP3_L4_CORE_FW_DSS_CORE_REGION,
- .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
- .flags = OMAP_FIREWALL_L4,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss slave ports */
-static struct omap_hwmod_ocp_if *omap3430es1_dss_slaves[] = {
- &omap3430es1_l4_core__dss,
-};
-
-static struct omap_hwmod_ocp_if *omap3xxx_dss_slaves[] = {
- &omap3xxx_l4_core__dss,
-};
-
static struct omap_hwmod_opt_clk dss_opt_clks[] = {
/*
* The DSS HW needs all DSS clocks enabled during reset. The dss_core
@@ -1460,10 +592,6 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = {
},
.opt_clks = dss_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
- .slaves = omap3430es1_dss_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3430es1_dss_slaves),
- .masters = omap3xxx_dss_masters,
- .masters_cnt = ARRAY_SIZE(omap3xxx_dss_masters),
.flags = HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
};
@@ -1485,10 +613,6 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = {
},
.opt_clks = dss_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
- .slaves = omap3xxx_dss_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_slaves),
- .masters = omap3xxx_dss_masters,
- .masters_cnt = ARRAY_SIZE(omap3xxx_dss_masters),
};
/*
@@ -1513,27 +637,6 @@ static struct omap_hwmod_class omap3_dispc_hwmod_class = {
.sysc = &omap3_dispc_sysc,
};
-/* l4_core -> dss_dispc */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dispc = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_dss_dispc_hwmod,
- .clk = "dss_ick",
- .addr = omap2_dss_dispc_addrs,
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP3_L4_CORE_FW_DSS_DISPC_REGION,
- .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
- .flags = OMAP_FIREWALL_L4,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss_dispc slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
- &omap3xxx_l4_core__dss_dispc,
-};
-
static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
.name = "dss_dispc",
.class = &omap3_dispc_hwmod_class,
@@ -1546,8 +649,6 @@ static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
.module_offs = OMAP3430_DSS_MOD,
},
},
- .slaves = omap3xxx_dss_dispc_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_dispc_slaves),
.flags = HWMOD_NO_IDLEST,
.dev_attr = &omap2_3_dss_dispc_dev_attr
};
@@ -1567,36 +668,6 @@ static struct omap_hwmod_irq_info omap3xxx_dsi1_irqs[] = {
};
/* dss_dsi1 */
-static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = {
- {
- .pa_start = 0x4804FC00,
- .pa_end = 0x4804FFFF,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_core -> dss_dsi1 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dsi1 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_dss_dsi1_hwmod,
- .clk = "dss_ick",
- .addr = omap3xxx_dss_dsi1_addrs,
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP3_L4_CORE_FW_DSS_DSI_REGION,
- .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
- .flags = OMAP_FIREWALL_L4,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss_dsi1 slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = {
- &omap3xxx_l4_core__dss_dsi1,
-};
-
static struct omap_hwmod_opt_clk dss_dsi1_opt_clks[] = {
{ .role = "sys_clk", .clk = "dss2_alwon_fck" },
};
@@ -1615,32 +686,9 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
},
.opt_clks = dss_dsi1_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(dss_dsi1_opt_clks),
- .slaves = omap3xxx_dss_dsi1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_dsi1_slaves),
.flags = HWMOD_NO_IDLEST,
};
-/* l4_core -> dss_rfbi */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_rfbi = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_dss_rfbi_hwmod,
- .clk = "dss_ick",
- .addr = omap2_dss_rfbi_addrs,
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP3_L4_CORE_FW_DSS_RFBI_REGION,
- .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP ,
- .flags = OMAP_FIREWALL_L4,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss_rfbi slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = {
- &omap3xxx_l4_core__dss_rfbi,
-};
-
static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
{ .role = "ick", .clk = "dss_ick" },
};
@@ -1658,32 +706,9 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
},
.opt_clks = dss_rfbi_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(dss_rfbi_opt_clks),
- .slaves = omap3xxx_dss_rfbi_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_rfbi_slaves),
.flags = HWMOD_NO_IDLEST,
};
-/* l4_core -> dss_venc */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_venc = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_dss_venc_hwmod,
- .clk = "dss_ick",
- .addr = omap2_dss_venc_addrs,
- .fw = {
- .omap2 = {
- .l4_fw_region = OMAP3_L4_CORE_FW_DSS_VENC_REGION,
- .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
- .flags = OMAP_FIREWALL_L4,
- }
- },
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss_venc slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = {
- &omap3xxx_l4_core__dss_venc,
-};
-
static struct omap_hwmod_opt_clk dss_venc_opt_clks[] = {
/* required only on OMAP3430 */
{ .role = "tv_dac_clk", .clk = "dss_96m_fck" },
@@ -1702,13 +727,10 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
},
.opt_clks = dss_venc_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(dss_venc_opt_clks),
- .slaves = omap3xxx_dss_venc_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_venc_slaves),
.flags = HWMOD_NO_IDLEST,
};
/* I2C1 */
-
static struct omap_i2c_dev_attr i2c1_dev_attr = {
.fifo_depth = 8, /* bytes */
.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
@@ -1716,10 +738,6 @@ static struct omap_i2c_dev_attr i2c1_dev_attr = {
OMAP_I2C_FLAG_BUS_SHIFT_2,
};
-static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = {
- &omap3_l4_core__i2c1,
-};
-
static struct omap_hwmod omap3xxx_i2c1_hwmod = {
.name = "i2c1",
.flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
@@ -1735,14 +753,11 @@ static struct omap_hwmod omap3xxx_i2c1_hwmod = {
.idlest_idle_bit = OMAP3430_ST_I2C1_SHIFT,
},
},
- .slaves = omap3xxx_i2c1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_i2c1_slaves),
.class = &i2c_class,
.dev_attr = &i2c1_dev_attr,
};
/* I2C2 */
-
static struct omap_i2c_dev_attr i2c2_dev_attr = {
.fifo_depth = 8, /* bytes */
.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
@@ -1750,10 +765,6 @@ static struct omap_i2c_dev_attr i2c2_dev_attr = {
OMAP_I2C_FLAG_BUS_SHIFT_2,
};
-static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = {
- &omap3_l4_core__i2c2,
-};
-
static struct omap_hwmod omap3xxx_i2c2_hwmod = {
.name = "i2c2",
.flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
@@ -1769,14 +780,11 @@ static struct omap_hwmod omap3xxx_i2c2_hwmod = {
.idlest_idle_bit = OMAP3430_ST_I2C2_SHIFT,
},
},
- .slaves = omap3xxx_i2c2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_i2c2_slaves),
.class = &i2c_class,
.dev_attr = &i2c2_dev_attr,
};
/* I2C3 */
-
static struct omap_i2c_dev_attr i2c3_dev_attr = {
.fifo_depth = 64, /* bytes */
.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
@@ -1795,10 +803,6 @@ static struct omap_hwmod_dma_info i2c3_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_ocp_if *omap3xxx_i2c3_slaves[] = {
- &omap3_l4_core__i2c3,
-};
-
static struct omap_hwmod omap3xxx_i2c3_hwmod = {
.name = "i2c3",
.flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
@@ -1814,114 +818,10 @@ static struct omap_hwmod omap3xxx_i2c3_hwmod = {
.idlest_idle_bit = OMAP3430_ST_I2C3_SHIFT,
},
},
- .slaves = omap3xxx_i2c3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_i2c3_slaves),
.class = &i2c_class,
.dev_attr = &i2c3_dev_attr,
};
-/* l4_wkup -> gpio1 */
-static struct omap_hwmod_addr_space omap3xxx_gpio1_addrs[] = {
- {
- .pa_start = 0x48310000,
- .pa_end = 0x483101ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__gpio1 = {
- .master = &omap3xxx_l4_wkup_hwmod,
- .slave = &omap3xxx_gpio1_hwmod,
- .addr = omap3xxx_gpio1_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio2 */
-static struct omap_hwmod_addr_space omap3xxx_gpio2_addrs[] = {
- {
- .pa_start = 0x49050000,
- .pa_end = 0x490501ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio2 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_gpio2_hwmod,
- .addr = omap3xxx_gpio2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio3 */
-static struct omap_hwmod_addr_space omap3xxx_gpio3_addrs[] = {
- {
- .pa_start = 0x49052000,
- .pa_end = 0x490521ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio3 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_gpio3_hwmod,
- .addr = omap3xxx_gpio3_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio4 */
-static struct omap_hwmod_addr_space omap3xxx_gpio4_addrs[] = {
- {
- .pa_start = 0x49054000,
- .pa_end = 0x490541ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio4 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_gpio4_hwmod,
- .addr = omap3xxx_gpio4_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio5 */
-static struct omap_hwmod_addr_space omap3xxx_gpio5_addrs[] = {
- {
- .pa_start = 0x49056000,
- .pa_end = 0x490561ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio5 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_gpio5_hwmod,
- .addr = omap3xxx_gpio5_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio6 */
-static struct omap_hwmod_addr_space omap3xxx_gpio6_addrs[] = {
- {
- .pa_start = 0x49058000,
- .pa_end = 0x490581ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio6 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_gpio6_hwmod,
- .addr = omap3xxx_gpio6_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
/*
* 'gpio' class
* general purpose io module
@@ -1944,7 +844,7 @@ static struct omap_hwmod_class omap3xxx_gpio_hwmod_class = {
.rev = 1,
};
-/* gpio_dev_attr*/
+/* gpio_dev_attr */
static struct omap_gpio_dev_attr gpio_dev_attr = {
.bank_width = 32,
.dbck_flag = true,
@@ -1955,10 +855,6 @@ static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio1_dbck", },
};
-static struct omap_hwmod_ocp_if *omap3xxx_gpio1_slaves[] = {
- &omap3xxx_l4_wkup__gpio1,
-};
-
static struct omap_hwmod omap3xxx_gpio1_hwmod = {
.name = "gpio1",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
@@ -1975,8 +871,6 @@ static struct omap_hwmod omap3xxx_gpio1_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPIO1_SHIFT,
},
},
- .slaves = omap3xxx_gpio1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_gpio1_slaves),
.class = &omap3xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
};
@@ -1986,10 +880,6 @@ static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio2_dbck", },
};
-static struct omap_hwmod_ocp_if *omap3xxx_gpio2_slaves[] = {
- &omap3xxx_l4_per__gpio2,
-};
-
static struct omap_hwmod omap3xxx_gpio2_hwmod = {
.name = "gpio2",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
@@ -2006,8 +896,6 @@ static struct omap_hwmod omap3xxx_gpio2_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPIO2_SHIFT,
},
},
- .slaves = omap3xxx_gpio2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_gpio2_slaves),
.class = &omap3xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
};
@@ -2017,10 +905,6 @@ static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio3_dbck", },
};
-static struct omap_hwmod_ocp_if *omap3xxx_gpio3_slaves[] = {
- &omap3xxx_l4_per__gpio3,
-};
-
static struct omap_hwmod omap3xxx_gpio3_hwmod = {
.name = "gpio3",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
@@ -2037,8 +921,6 @@ static struct omap_hwmod omap3xxx_gpio3_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPIO3_SHIFT,
},
},
- .slaves = omap3xxx_gpio3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_gpio3_slaves),
.class = &omap3xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
};
@@ -2048,10 +930,6 @@ static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio4_dbck", },
};
-static struct omap_hwmod_ocp_if *omap3xxx_gpio4_slaves[] = {
- &omap3xxx_l4_per__gpio4,
-};
-
static struct omap_hwmod omap3xxx_gpio4_hwmod = {
.name = "gpio4",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
@@ -2068,8 +946,6 @@ static struct omap_hwmod omap3xxx_gpio4_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPIO4_SHIFT,
},
},
- .slaves = omap3xxx_gpio4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_gpio4_slaves),
.class = &omap3xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
};
@@ -2084,10 +960,6 @@ static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio5_dbck", },
};
-static struct omap_hwmod_ocp_if *omap3xxx_gpio5_slaves[] = {
- &omap3xxx_l4_per__gpio5,
-};
-
static struct omap_hwmod omap3xxx_gpio5_hwmod = {
.name = "gpio5",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
@@ -2104,8 +976,6 @@ static struct omap_hwmod omap3xxx_gpio5_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPIO5_SHIFT,
},
},
- .slaves = omap3xxx_gpio5_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_gpio5_slaves),
.class = &omap3xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
};
@@ -2120,10 +990,6 @@ static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio6_dbck", },
};
-static struct omap_hwmod_ocp_if *omap3xxx_gpio6_slaves[] = {
- &omap3xxx_l4_per__gpio6,
-};
-
static struct omap_hwmod omap3xxx_gpio6_hwmod = {
.name = "gpio6",
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
@@ -2140,20 +1006,10 @@ static struct omap_hwmod omap3xxx_gpio6_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPIO6_SHIFT,
},
},
- .slaves = omap3xxx_gpio6_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_gpio6_slaves),
.class = &omap3xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
};
-/* dma_system -> L3 */
-static struct omap_hwmod_ocp_if omap3xxx_dma_system__l3 = {
- .master = &omap3xxx_dma_system_hwmod,
- .slave = &omap3xxx_l3_main_hwmod,
- .clk = "core_l3_ick",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
/* dma attributes */
static struct omap_dma_dev_attr dma_dev_attr = {
.dev_caps = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
@@ -2180,34 +1036,6 @@ static struct omap_hwmod_class omap3xxx_dma_hwmod_class = {
};
/* dma_system */
-static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = {
- {
- .pa_start = 0x48056000,
- .pa_end = 0x48056fff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* dma_system master ports */
-static struct omap_hwmod_ocp_if *omap3xxx_dma_system_masters[] = {
- &omap3xxx_dma_system__l3,
-};
-
-/* l4_cfg -> dma_system */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__dma_system = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_dma_system_hwmod,
- .clk = "core_l4_ick",
- .addr = omap3xxx_dma_system_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dma_system slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = {
- &omap3xxx_l4_core__dma_system,
-};
-
static struct omap_hwmod omap3xxx_dma_system_hwmod = {
.name = "dma",
.class = &omap3xxx_dma_hwmod_class,
@@ -2222,10 +1050,6 @@ static struct omap_hwmod omap3xxx_dma_system_hwmod = {
.idlest_idle_bit = OMAP3430_ST_SDMA_SHIFT,
},
},
- .slaves = omap3xxx_dma_system_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_dma_system_slaves),
- .masters = omap3xxx_dma_system_masters,
- .masters_cnt = ARRAY_SIZE(omap3xxx_dma_system_masters),
.dev_attr = &dma_dev_attr,
.flags = HWMOD_NO_IDLEST,
};
@@ -2252,36 +1076,12 @@ static struct omap_hwmod_class omap3xxx_mcbsp_hwmod_class = {
/* mcbsp1 */
static struct omap_hwmod_irq_info omap3xxx_mcbsp1_irqs[] = {
- { .name = "irq", .irq = 16 },
+ { .name = "common", .irq = 16 },
{ .name = "tx", .irq = 59 },
{ .name = "rx", .irq = 60 },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap3xxx_mcbsp1_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x48074000,
- .pa_end = 0x480740ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_core -> mcbsp1 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp1 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_mcbsp1_hwmod,
- .clk = "mcbsp1_ick",
- .addr = omap3xxx_mcbsp1_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcbsp1 slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_mcbsp1_slaves[] = {
- &omap3xxx_l4_core__mcbsp1,
-};
-
static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
.name = "mcbsp1",
.class = &omap3xxx_mcbsp_hwmod_class,
@@ -2297,42 +1097,16 @@ static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
.idlest_idle_bit = OMAP3430_ST_MCBSP1_SHIFT,
},
},
- .slaves = omap3xxx_mcbsp1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp1_slaves),
};
/* mcbsp2 */
static struct omap_hwmod_irq_info omap3xxx_mcbsp2_irqs[] = {
- { .name = "irq", .irq = 17 },
+ { .name = "common", .irq = 17 },
{ .name = "tx", .irq = 62 },
{ .name = "rx", .irq = 63 },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap3xxx_mcbsp2_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x49022000,
- .pa_end = 0x490220ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mcbsp2 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_mcbsp2_hwmod,
- .clk = "mcbsp2_ick",
- .addr = omap3xxx_mcbsp2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcbsp2 slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_mcbsp2_slaves[] = {
- &omap3xxx_l4_per__mcbsp2,
-};
-
static struct omap_mcbsp_dev_attr omap34xx_mcbsp2_dev_attr = {
.sidetone = "mcbsp2_sidetone",
};
@@ -2352,45 +1126,19 @@ static struct omap_hwmod omap3xxx_mcbsp2_hwmod = {
.idlest_idle_bit = OMAP3430_ST_MCBSP2_SHIFT,
},
},
- .slaves = omap3xxx_mcbsp2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp2_slaves),
.dev_attr = &omap34xx_mcbsp2_dev_attr,
};
/* mcbsp3 */
static struct omap_hwmod_irq_info omap3xxx_mcbsp3_irqs[] = {
- { .name = "irq", .irq = 22 },
+ { .name = "common", .irq = 22 },
{ .name = "tx", .irq = 89 },
{ .name = "rx", .irq = 90 },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap3xxx_mcbsp3_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x49024000,
- .pa_end = 0x490240ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mcbsp3 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_mcbsp3_hwmod,
- .clk = "mcbsp3_ick",
- .addr = omap3xxx_mcbsp3_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcbsp3 slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_mcbsp3_slaves[] = {
- &omap3xxx_l4_per__mcbsp3,
-};
-
static struct omap_mcbsp_dev_attr omap34xx_mcbsp3_dev_attr = {
- .sidetone = "mcbsp3_sidetone",
+ .sidetone = "mcbsp3_sidetone",
};
static struct omap_hwmod omap3xxx_mcbsp3_hwmod = {
@@ -2408,14 +1156,12 @@ static struct omap_hwmod omap3xxx_mcbsp3_hwmod = {
.idlest_idle_bit = OMAP3430_ST_MCBSP3_SHIFT,
},
},
- .slaves = omap3xxx_mcbsp3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp3_slaves),
.dev_attr = &omap34xx_mcbsp3_dev_attr,
};
/* mcbsp4 */
static struct omap_hwmod_irq_info omap3xxx_mcbsp4_irqs[] = {
- { .name = "irq", .irq = 23 },
+ { .name = "common", .irq = 23 },
{ .name = "tx", .irq = 54 },
{ .name = "rx", .irq = 55 },
{ .irq = -1 }
@@ -2427,30 +1173,6 @@ static struct omap_hwmod_dma_info omap3xxx_mcbsp4_sdma_chs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap3xxx_mcbsp4_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x49026000,
- .pa_end = 0x490260ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mcbsp4 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp4 = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_mcbsp4_hwmod,
- .clk = "mcbsp4_ick",
- .addr = omap3xxx_mcbsp4_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcbsp4 slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_mcbsp4_slaves[] = {
- &omap3xxx_l4_per__mcbsp4,
-};
-
static struct omap_hwmod omap3xxx_mcbsp4_hwmod = {
.name = "mcbsp4",
.class = &omap3xxx_mcbsp_hwmod_class,
@@ -2466,13 +1188,11 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod = {
.idlest_idle_bit = OMAP3430_ST_MCBSP4_SHIFT,
},
},
- .slaves = omap3xxx_mcbsp4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp4_slaves),
};
/* mcbsp5 */
static struct omap_hwmod_irq_info omap3xxx_mcbsp5_irqs[] = {
- { .name = "irq", .irq = 27 },
+ { .name = "common", .irq = 27 },
{ .name = "tx", .irq = 81 },
{ .name = "rx", .irq = 82 },
{ .irq = -1 }
@@ -2484,30 +1204,6 @@ static struct omap_hwmod_dma_info omap3xxx_mcbsp5_sdma_chs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap3xxx_mcbsp5_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x48096000,
- .pa_end = 0x480960ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_core -> mcbsp5 */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp5 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_mcbsp5_hwmod,
- .clk = "mcbsp5_ick",
- .addr = omap3xxx_mcbsp5_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcbsp5 slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_mcbsp5_slaves[] = {
- &omap3xxx_l4_core__mcbsp5,
-};
-
static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
.name = "mcbsp5",
.class = &omap3xxx_mcbsp_hwmod_class,
@@ -2523,11 +1219,9 @@ static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
.idlest_idle_bit = OMAP3430_ST_MCBSP5_SHIFT,
},
},
- .slaves = omap3xxx_mcbsp5_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp5_slaves),
};
-/* 'mcbsp sidetone' class */
+/* 'mcbsp sidetone' class */
static struct omap_hwmod_class_sysconfig omap3xxx_mcbsp_sidetone_sysc = {
.sysc_offs = 0x0010,
.sysc_flags = SYSC_HAS_AUTOIDLE,
@@ -2545,30 +1239,6 @@ static struct omap_hwmod_irq_info omap3xxx_mcbsp2_sidetone_irqs[] = {
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap3xxx_mcbsp2_sidetone_addrs[] = {
- {
- .name = "sidetone",
- .pa_start = 0x49028000,
- .pa_end = 0x490280ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mcbsp2_sidetone */
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2_sidetone = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_mcbsp2_sidetone_hwmod,
- .clk = "mcbsp2_ick",
- .addr = omap3xxx_mcbsp2_sidetone_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* mcbsp2_sidetone slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_mcbsp2_sidetone_slaves[] = {
- &omap3xxx_l4_per__mcbsp2_sidetone,
-};
-
static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
.name = "mcbsp2_sidetone",
.class = &omap3xxx_mcbsp_sidetone_hwmod_class,
@@ -2583,8 +1253,6 @@ static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
.idlest_idle_bit = OMAP3430_ST_MCBSP2_SHIFT,
},
},
- .slaves = omap3xxx_mcbsp2_sidetone_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_slaves),
};
/* mcbsp3_sidetone */
@@ -2593,30 +1261,6 @@ static struct omap_hwmod_irq_info omap3xxx_mcbsp3_sidetone_irqs[] = {
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap3xxx_mcbsp3_sidetone_addrs[] = {
- {
- .name = "sidetone",
- .pa_start = 0x4902A000,
- .pa_end = 0x4902A0ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mcbsp3_sidetone */
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3_sidetone = {
- .master = &omap3xxx_l4_per_hwmod,
- .slave = &omap3xxx_mcbsp3_sidetone_hwmod,
- .clk = "mcbsp3_ick",
- .addr = omap3xxx_mcbsp3_sidetone_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* mcbsp3_sidetone slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_mcbsp3_sidetone_slaves[] = {
- &omap3xxx_l4_per__mcbsp3_sidetone,
-};
-
static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
.name = "mcbsp3_sidetone",
.class = &omap3xxx_mcbsp_sidetone_hwmod_class,
@@ -2631,11 +1275,8 @@ static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
.idlest_idle_bit = OMAP3430_ST_MCBSP3_SHIFT,
},
},
- .slaves = omap3xxx_mcbsp3_sidetone_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_slaves),
};
-
/* SR common */
static struct omap_hwmod_sysc_fields omap34xx_sr_sysc_fields = {
.clkact_shift = 20,
@@ -2656,7 +1297,7 @@ static struct omap_hwmod_class omap34xx_smartreflex_hwmod_class = {
static struct omap_hwmod_sysc_fields omap36xx_sr_sysc_fields = {
.sidle_shift = 24,
- .enwkup_shift = 26
+ .enwkup_shift = 26,
};
static struct omap_hwmod_class_sysconfig omap36xx_sr_sysc = {
@@ -2678,12 +1319,13 @@ static struct omap_smartreflex_dev_attr sr1_dev_attr = {
.sensor_voltdm_name = "mpu_iva",
};
-static struct omap_hwmod_ocp_if *omap3_sr1_slaves[] = {
- &omap3_l4_core__sr1,
+static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = {
+ { .irq = 18 },
+ { .irq = -1 }
};
static struct omap_hwmod omap34xx_sr1_hwmod = {
- .name = "sr1_hwmod",
+ .name = "sr1",
.class = &omap34xx_smartreflex_hwmod_class,
.main_clk = "sr1_fck",
.prcm = {
@@ -2695,15 +1337,13 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
.idlest_idle_bit = OMAP3430_EN_SR1_SHIFT,
},
},
- .slaves = omap3_sr1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves),
.dev_attr = &sr1_dev_attr,
.mpu_irqs = omap3_smartreflex_mpu_irqs,
.flags = HWMOD_SET_DEFAULT_CLOCKACT,
};
static struct omap_hwmod omap36xx_sr1_hwmod = {
- .name = "sr1_hwmod",
+ .name = "sr1",
.class = &omap36xx_smartreflex_hwmod_class,
.main_clk = "sr1_fck",
.prcm = {
@@ -2715,8 +1355,6 @@ static struct omap_hwmod omap36xx_sr1_hwmod = {
.idlest_idle_bit = OMAP3430_EN_SR1_SHIFT,
},
},
- .slaves = omap3_sr1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves),
.dev_attr = &sr1_dev_attr,
.mpu_irqs = omap3_smartreflex_mpu_irqs,
};
@@ -2726,12 +1364,13 @@ static struct omap_smartreflex_dev_attr sr2_dev_attr = {
.sensor_voltdm_name = "core",
};
-static struct omap_hwmod_ocp_if *omap3_sr2_slaves[] = {
- &omap3_l4_core__sr2,
+static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = {
+ { .irq = 19 },
+ { .irq = -1 }
};
static struct omap_hwmod omap34xx_sr2_hwmod = {
- .name = "sr2_hwmod",
+ .name = "sr2",
.class = &omap34xx_smartreflex_hwmod_class,
.main_clk = "sr2_fck",
.prcm = {
@@ -2743,15 +1382,13 @@ static struct omap_hwmod omap34xx_sr2_hwmod = {
.idlest_idle_bit = OMAP3430_EN_SR2_SHIFT,
},
},
- .slaves = omap3_sr2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves),
.dev_attr = &sr2_dev_attr,
.mpu_irqs = omap3_smartreflex_core_irqs,
.flags = HWMOD_SET_DEFAULT_CLOCKACT,
};
static struct omap_hwmod omap36xx_sr2_hwmod = {
- .name = "sr2_hwmod",
+ .name = "sr2",
.class = &omap36xx_smartreflex_hwmod_class,
.main_clk = "sr2_fck",
.prcm = {
@@ -2763,8 +1400,6 @@ static struct omap_hwmod omap36xx_sr2_hwmod = {
.idlest_idle_bit = OMAP3430_EN_SR2_SHIFT,
},
},
- .slaves = omap3_sr2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves),
.dev_attr = &sr2_dev_attr,
.mpu_irqs = omap3_smartreflex_core_irqs,
};
@@ -2790,34 +1425,11 @@ static struct omap_hwmod_class omap3xxx_mailbox_hwmod_class = {
.sysc = &omap3xxx_mailbox_sysc,
};
-static struct omap_hwmod omap3xxx_mailbox_hwmod;
static struct omap_hwmod_irq_info omap3xxx_mailbox_irqs[] = {
{ .irq = 26 },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap3xxx_mailbox_addrs[] = {
- {
- .pa_start = 0x48094000,
- .pa_end = 0x480941ff,
- .flags = ADDR_TYPE_RT,
- },
- { }
-};
-
-/* l4_core -> mailbox */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__mailbox = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_mailbox_hwmod,
- .addr = omap3xxx_mailbox_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mailbox slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_mailbox_slaves[] = {
- &omap3xxx_l4_core__mailbox,
-};
-
static struct omap_hwmod omap3xxx_mailbox_hwmod = {
.name = "mailbox",
.class = &omap3xxx_mailbox_hwmod_class,
@@ -2832,53 +1444,6 @@ static struct omap_hwmod omap3xxx_mailbox_hwmod = {
.idlest_idle_bit = OMAP3430_ST_MAILBOXES_SHIFT,
},
},
- .slaves = omap3xxx_mailbox_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_mailbox_slaves),
-};
-
-/* l4 core -> mcspi1 interface */
-static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi1 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap34xx_mcspi1,
- .clk = "mcspi1_ick",
- .addr = omap2_mcspi1_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4 core -> mcspi2 interface */
-static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi2 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap34xx_mcspi2,
- .clk = "mcspi2_ick",
- .addr = omap2_mcspi2_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4 core -> mcspi3 interface */
-static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi3 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap34xx_mcspi3,
- .clk = "mcspi3_ick",
- .addr = omap2430_mcspi3_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4 core -> mcspi4 interface */
-static struct omap_hwmod_addr_space omap34xx_mcspi4_addr_space[] = {
- {
- .pa_start = 0x480ba000,
- .pa_end = 0x480ba0ff,
- .flags = ADDR_TYPE_RT,
- },
- { }
-};
-
-static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi4 = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap34xx_mcspi4,
- .clk = "mcspi4_ick",
- .addr = omap34xx_mcspi4_addr_space,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
};
/*
@@ -2905,10 +1470,6 @@ static struct omap_hwmod_class omap34xx_mcspi_class = {
};
/* mcspi1 */
-static struct omap_hwmod_ocp_if *omap34xx_mcspi1_slaves[] = {
- &omap34xx_l4_core__mcspi1,
-};
-
static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
.num_chipselect = 4,
};
@@ -2927,17 +1488,11 @@ static struct omap_hwmod omap34xx_mcspi1 = {
.idlest_idle_bit = OMAP3430_ST_MCSPI1_SHIFT,
},
},
- .slaves = omap34xx_mcspi1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap34xx_mcspi1_slaves),
.class = &omap34xx_mcspi_class,
.dev_attr = &omap_mcspi1_dev_attr,
};
/* mcspi2 */
-static struct omap_hwmod_ocp_if *omap34xx_mcspi2_slaves[] = {
- &omap34xx_l4_core__mcspi2,
-};
-
static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
.num_chipselect = 2,
};
@@ -2956,8 +1511,6 @@ static struct omap_hwmod omap34xx_mcspi2 = {
.idlest_idle_bit = OMAP3430_ST_MCSPI2_SHIFT,
},
},
- .slaves = omap34xx_mcspi2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap34xx_mcspi2_slaves),
.class = &omap34xx_mcspi_class,
.dev_attr = &omap_mcspi2_dev_attr,
};
@@ -2976,10 +1529,6 @@ static struct omap_hwmod_dma_info omap34xx_mcspi3_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_ocp_if *omap34xx_mcspi3_slaves[] = {
- &omap34xx_l4_core__mcspi3,
-};
-
static struct omap2_mcspi_dev_attr omap_mcspi3_dev_attr = {
.num_chipselect = 2,
};
@@ -2998,13 +1547,11 @@ static struct omap_hwmod omap34xx_mcspi3 = {
.idlest_idle_bit = OMAP3430_ST_MCSPI3_SHIFT,
},
},
- .slaves = omap34xx_mcspi3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap34xx_mcspi3_slaves),
.class = &omap34xx_mcspi_class,
.dev_attr = &omap_mcspi3_dev_attr,
};
-/* SPI4 */
+/* mcspi4 */
static struct omap_hwmod_irq_info omap34xx_mcspi4_mpu_irqs[] = {
{ .name = "irq", .irq = INT_34XX_SPI4_IRQ }, /* 48 */
{ .irq = -1 }
@@ -3016,10 +1563,6 @@ static struct omap_hwmod_dma_info omap34xx_mcspi4_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_ocp_if *omap34xx_mcspi4_slaves[] = {
- &omap34xx_l4_core__mcspi4,
-};
-
static struct omap2_mcspi_dev_attr omap_mcspi4_dev_attr = {
.num_chipselect = 1,
};
@@ -3038,15 +1581,11 @@ static struct omap_hwmod omap34xx_mcspi4 = {
.idlest_idle_bit = OMAP3430_ST_MCSPI4_SHIFT,
},
},
- .slaves = omap34xx_mcspi4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap34xx_mcspi4_slaves),
.class = &omap34xx_mcspi_class,
.dev_attr = &omap_mcspi4_dev_attr,
};
-/*
- * usbhsotg
- */
+/* usbhsotg */
static struct omap_hwmod_class_sysconfig omap3xxx_usbhsotg_sysc = {
.rev_offs = 0x0400,
.sysc_offs = 0x0404,
@@ -3063,6 +1602,7 @@ static struct omap_hwmod_class usbotg_class = {
.name = "usbotg",
.sysc = &omap3xxx_usbhsotg_sysc,
};
+
/* usb_otg_hs */
static struct omap_hwmod_irq_info omap3xxx_usbhsotg_mpu_irqs[] = {
@@ -3085,10 +1625,6 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
.idlest_stdby_bit = OMAP3430ES2_ST_HSOTGUSB_STDBY_SHIFT
},
},
- .masters = omap3xxx_usbhsotg_masters,
- .masters_cnt = ARRAY_SIZE(omap3xxx_usbhsotg_masters),
- .slaves = omap3xxx_usbhsotg_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_usbhsotg_slaves),
.class = &usbotg_class,
/*
@@ -3120,15 +1656,10 @@ static struct omap_hwmod am35xx_usbhsotg_hwmod = {
.omap2 = {
},
},
- .masters = am35xx_usbhsotg_masters,
- .masters_cnt = ARRAY_SIZE(am35xx_usbhsotg_masters),
- .slaves = am35xx_usbhsotg_slaves,
- .slaves_cnt = ARRAY_SIZE(am35xx_usbhsotg_slaves),
.class = &am35xx_usbotg_class,
};
/* MMC/SD/SDIO common */
-
static struct omap_hwmod_class_sysconfig omap34xx_mmc_sysc = {
.rev_offs = 0x1fc,
.sysc_offs = 0x10,
@@ -3162,10 +1693,6 @@ static struct omap_hwmod_opt_clk omap34xx_mmc1_opt_clks[] = {
{ .role = "dbck", .clk = "omap_32k_fck", },
};
-static struct omap_hwmod_ocp_if *omap3xxx_mmc1_slaves[] = {
- &omap3xxx_l4_core__mmc1,
-};
-
static struct omap_mmc_dev_attr mmc1_dev_attr = {
.flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
};
@@ -3193,8 +1720,6 @@ static struct omap_hwmod omap3xxx_pre_es3_mmc1_hwmod = {
},
},
.dev_attr = &mmc1_pre_es3_dev_attr,
- .slaves = omap3xxx_mmc1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_mmc1_slaves),
.class = &omap34xx_mmc_class,
};
@@ -3215,8 +1740,6 @@ static struct omap_hwmod omap3xxx_es3plus_mmc1_hwmod = {
},
},
.dev_attr = &mmc1_dev_attr,
- .slaves = omap3xxx_mmc1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_mmc1_slaves),
.class = &omap34xx_mmc_class,
};
@@ -3237,10 +1760,6 @@ static struct omap_hwmod_opt_clk omap34xx_mmc2_opt_clks[] = {
{ .role = "dbck", .clk = "omap_32k_fck", },
};
-static struct omap_hwmod_ocp_if *omap3xxx_mmc2_slaves[] = {
- &omap3xxx_l4_core__mmc2,
-};
-
/* See 35xx errata 2.1.1.128 in SPRZ278F */
static struct omap_mmc_dev_attr mmc2_pre_es3_dev_attr = {
.flags = OMAP_HSMMC_BROKEN_MULTIBLOCK_READ,
@@ -3263,8 +1782,6 @@ static struct omap_hwmod omap3xxx_pre_es3_mmc2_hwmod = {
},
},
.dev_attr = &mmc2_pre_es3_dev_attr,
- .slaves = omap3xxx_mmc2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_mmc2_slaves),
.class = &omap34xx_mmc_class,
};
@@ -3284,8 +1801,6 @@ static struct omap_hwmod omap3xxx_es3plus_mmc2_hwmod = {
.idlest_idle_bit = OMAP3430_ST_MMC2_SHIFT,
},
},
- .slaves = omap3xxx_mmc2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_mmc2_slaves),
.class = &omap34xx_mmc_class,
};
@@ -3306,10 +1821,6 @@ static struct omap_hwmod_opt_clk omap34xx_mmc3_opt_clks[] = {
{ .role = "dbck", .clk = "omap_32k_fck", },
};
-static struct omap_hwmod_ocp_if *omap3xxx_mmc3_slaves[] = {
- &omap3xxx_l4_core__mmc3,
-};
-
static struct omap_hwmod omap3xxx_mmc3_hwmod = {
.name = "mmc3",
.mpu_irqs = omap34xx_mmc3_mpu_irqs,
@@ -3325,8 +1836,6 @@ static struct omap_hwmod omap3xxx_mmc3_hwmod = {
.idlest_idle_bit = OMAP3430_ST_MMC3_SHIFT,
},
},
- .slaves = omap3xxx_mmc3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_mmc3_slaves),
.class = &omap34xx_mmc_class,
};
@@ -3334,12 +1843,6 @@ static struct omap_hwmod omap3xxx_mmc3_hwmod = {
* 'usb_host_hs' class
* high-speed multi-port usb host controller
*/
-static struct omap_hwmod_ocp_if omap3xxx_usb_host_hs__l3_main_2 = {
- .master = &omap3xxx_usb_host_hs_hwmod,
- .slave = &omap3xxx_l3_main_hwmod,
- .clk = "core_l3_ick",
- .user = OCP_USER_MPU,
-};
static struct omap_hwmod_class_sysconfig omap3xxx_usb_host_hs_sysc = {
.rev_offs = 0x0000,
@@ -3358,42 +1861,6 @@ static struct omap_hwmod_class omap3xxx_usb_host_hs_hwmod_class = {
.sysc = &omap3xxx_usb_host_hs_sysc,
};
-static struct omap_hwmod_ocp_if *omap3xxx_usb_host_hs_masters[] = {
- &omap3xxx_usb_host_hs__l3_main_2,
-};
-
-static struct omap_hwmod_addr_space omap3xxx_usb_host_hs_addrs[] = {
- {
- .name = "uhh",
- .pa_start = 0x48064000,
- .pa_end = 0x480643ff,
- .flags = ADDR_TYPE_RT
- },
- {
- .name = "ohci",
- .pa_start = 0x48064400,
- .pa_end = 0x480647ff,
- },
- {
- .name = "ehci",
- .pa_start = 0x48064800,
- .pa_end = 0x48064cff,
- },
- {}
-};
-
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__usb_host_hs = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_usb_host_hs_hwmod,
- .clk = "usbhost_ick",
- .addr = omap3xxx_usb_host_hs_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_ocp_if *omap3xxx_usb_host_hs_slaves[] = {
- &omap3xxx_l4_core__usb_host_hs,
-};
-
static struct omap_hwmod_opt_clk omap3xxx_usb_host_hs_opt_clks[] = {
{ .role = "ehci_logic_fck", .clk = "usbhost_120m_fck", },
};
@@ -3422,10 +1889,6 @@ static struct omap_hwmod omap3xxx_usb_host_hs_hwmod = {
},
.opt_clks = omap3xxx_usb_host_hs_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(omap3xxx_usb_host_hs_opt_clks),
- .slaves = omap3xxx_usb_host_hs_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_usb_host_hs_slaves),
- .masters = omap3xxx_usb_host_hs_masters,
- .masters_cnt = ARRAY_SIZE(omap3xxx_usb_host_hs_masters),
/*
* Errata: USBHOST Configured In Smart-Idle Can Lead To a Deadlock
@@ -3501,6 +1964,1134 @@ static struct omap_hwmod_irq_info omap3xxx_usb_tll_hs_irqs[] = {
{ .irq = -1 }
};
+static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod = {
+ .name = "usb_tll_hs",
+ .class = &omap3xxx_usb_tll_hs_hwmod_class,
+ .clkdm_name = "l3_init_clkdm",
+ .mpu_irqs = omap3xxx_usb_tll_hs_irqs,
+ .main_clk = "usbtll_fck",
+ .prcm = {
+ .omap2 = {
+ .module_offs = CORE_MOD,
+ .prcm_reg_id = 3,
+ .module_bit = OMAP3430ES2_EN_USBTLL_SHIFT,
+ .idlest_reg_id = 3,
+ .idlest_idle_bit = OMAP3430ES2_ST_USBTLL_SHIFT,
+ },
+ },
+};
+
+static struct omap_hwmod omap3xxx_hdq1w_hwmod = {
+ .name = "hdq1w",
+ .mpu_irqs = omap2_hdq1w_mpu_irqs,
+ .main_clk = "hdq_fck",
+ .prcm = {
+ .omap2 = {
+ .module_offs = CORE_MOD,
+ .prcm_reg_id = 1,
+ .module_bit = OMAP3430_EN_HDQ_SHIFT,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP3430_ST_HDQ_SHIFT,
+ },
+ },
+ .class = &omap2_hdq1w_class,
+};
+
+/*
+ * '32K sync counter' class
+ * 32-bit ordinary counter, clocked by the falling edge of the 32 khz clock
+ */
+static struct omap_hwmod_class_sysconfig omap3xxx_counter_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0004,
+ .sysc_flags = SYSC_HAS_SIDLEMODE,
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_counter_hwmod_class = {
+ .name = "counter",
+ .sysc = &omap3xxx_counter_sysc,
+};
+
+static struct omap_hwmod omap3xxx_counter_32k_hwmod = {
+ .name = "counter_32k",
+ .class = &omap3xxx_counter_hwmod_class,
+ .clkdm_name = "wkup_clkdm",
+ .flags = HWMOD_SWSUP_SIDLE,
+ .main_clk = "wkup_32k_fck",
+ .prcm = {
+ .omap2 = {
+ .module_offs = WKUP_MOD,
+ .prcm_reg_id = 1,
+ .module_bit = OMAP3430_ST_32KSYNC_SHIFT,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP3430_ST_32KSYNC_SHIFT,
+ },
+ },
+};
+
+/*
+ * interfaces
+ */
+
+/* L3 -> L4_CORE interface */
+static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
+ .master = &omap3xxx_l3_main_hwmod,
+ .slave = &omap3xxx_l4_core_hwmod,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L3 -> L4_PER interface */
+static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_per = {
+ .master = &omap3xxx_l3_main_hwmod,
+ .slave = &omap3xxx_l4_per_hwmod,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_l3_main_addrs[] = {
+ {
+ .pa_start = 0x68000000,
+ .pa_end = 0x6800ffff,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+/* MPU -> L3 interface */
+static struct omap_hwmod_ocp_if omap3xxx_mpu__l3_main = {
+ .master = &omap3xxx_mpu_hwmod,
+ .slave = &omap3xxx_l3_main_hwmod,
+ .addr = omap3xxx_l3_main_addrs,
+ .user = OCP_USER_MPU,
+};
+
+/* DSS -> l3 */
+static struct omap_hwmod_ocp_if omap3430es1_dss__l3 = {
+ .master = &omap3430es1_dss_core_hwmod,
+ .slave = &omap3xxx_l3_main_hwmod,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_dss__l3 = {
+ .master = &omap3xxx_dss_core_hwmod,
+ .slave = &omap3xxx_l3_main_hwmod,
+ .fw = {
+ .omap2 = {
+ .l3_perm_bit = OMAP3_L3_CORE_FW_INIT_ID_DSS,
+ .flags = OMAP_FIREWALL_L3,
+ }
+ },
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_core -> usbhsotg interface */
+static struct omap_hwmod_ocp_if omap3xxx_usbhsotg__l3 = {
+ .master = &omap3xxx_usbhsotg_hwmod,
+ .slave = &omap3xxx_l3_main_hwmod,
+ .clk = "core_l3_ick",
+ .user = OCP_USER_MPU,
+};
+
+/* l3_core -> am35xx_usbhsotg interface */
+static struct omap_hwmod_ocp_if am35xx_usbhsotg__l3 = {
+ .master = &am35xx_usbhsotg_hwmod,
+ .slave = &omap3xxx_l3_main_hwmod,
+ .clk = "core_l3_ick",
+ .user = OCP_USER_MPU,
+};
+/* L4_CORE -> L4_WKUP interface */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_l4_wkup_hwmod,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> MMC1 interface */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__pre_es3_mmc1 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_pre_es3_mmc1_hwmod,
+ .clk = "mmchs1_ick",
+ .addr = omap2430_mmc1_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ .flags = OMAP_FIREWALL_L4
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__es3plus_mmc1 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_es3plus_mmc1_hwmod,
+ .clk = "mmchs1_ick",
+ .addr = omap2430_mmc1_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ .flags = OMAP_FIREWALL_L4
+};
+
+/* L4 CORE -> MMC2 interface */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__pre_es3_mmc2 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_pre_es3_mmc2_hwmod,
+ .clk = "mmchs2_ick",
+ .addr = omap2430_mmc2_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ .flags = OMAP_FIREWALL_L4
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__es3plus_mmc2 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_es3plus_mmc2_hwmod,
+ .clk = "mmchs2_ick",
+ .addr = omap2430_mmc2_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ .flags = OMAP_FIREWALL_L4
+};
+
+/* L4 CORE -> MMC3 interface */
+static struct omap_hwmod_addr_space omap3xxx_mmc3_addr_space[] = {
+ {
+ .pa_start = 0x480ad000,
+ .pa_end = 0x480ad1ff,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc3 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_mmc3_hwmod,
+ .clk = "mmchs3_ick",
+ .addr = omap3xxx_mmc3_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ .flags = OMAP_FIREWALL_L4
+};
+
+/* L4 CORE -> UART1 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart1_addr_space[] = {
+ {
+ .pa_start = OMAP3_UART1_BASE,
+ .pa_end = OMAP3_UART1_BASE + SZ_8K - 1,
+ .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__uart1 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_uart1_hwmod,
+ .clk = "uart1_ick",
+ .addr = omap3xxx_uart1_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> UART2 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart2_addr_space[] = {
+ {
+ .pa_start = OMAP3_UART2_BASE,
+ .pa_end = OMAP3_UART2_BASE + SZ_1K - 1,
+ .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__uart2 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_uart2_hwmod,
+ .clk = "uart2_ick",
+ .addr = omap3xxx_uart2_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART3 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart3_addr_space[] = {
+ {
+ .pa_start = OMAP3_UART3_BASE,
+ .pa_end = OMAP3_UART3_BASE + SZ_1K - 1,
+ .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_per__uart3 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_uart3_hwmod,
+ .clk = "uart3_ick",
+ .addr = omap3xxx_uart3_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART4 interface */
+static struct omap_hwmod_addr_space omap36xx_uart4_addr_space[] = {
+ {
+ .pa_start = OMAP3_UART4_BASE,
+ .pa_end = OMAP3_UART4_BASE + SZ_1K - 1,
+ .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap36xx_l4_per__uart4 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap36xx_uart4_hwmod,
+ .clk = "uart4_ick",
+ .addr = omap36xx_uart4_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* AM35xx: L4 CORE -> UART4 interface */
+static struct omap_hwmod_addr_space am35xx_uart4_addr_space[] = {
+ {
+ .pa_start = OMAP3_UART4_AM35XX_BASE,
+ .pa_end = OMAP3_UART4_AM35XX_BASE + SZ_1K - 1,
+ .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+ },
+};
+
+static struct omap_hwmod_ocp_if am35xx_l4_core__uart4 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &am35xx_uart4_hwmod,
+ .clk = "uart4_ick",
+ .addr = am35xx_uart4_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> I2C1 interface */
+static struct omap_hwmod_ocp_if omap3_l4_core__i2c1 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_i2c1_hwmod,
+ .clk = "i2c1_ick",
+ .addr = omap2_i2c1_addr_space,
+ .fw = {
+ .omap2 = {
+ .l4_fw_region = OMAP3_L4_CORE_FW_I2C1_REGION,
+ .l4_prot_group = 7,
+ .flags = OMAP_FIREWALL_L4,
+ }
+ },
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> I2C2 interface */
+static struct omap_hwmod_ocp_if omap3_l4_core__i2c2 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_i2c2_hwmod,
+ .clk = "i2c2_ick",
+ .addr = omap2_i2c2_addr_space,
+ .fw = {
+ .omap2 = {
+ .l4_fw_region = OMAP3_L4_CORE_FW_I2C2_REGION,
+ .l4_prot_group = 7,
+ .flags = OMAP_FIREWALL_L4,
+ }
+ },
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> I2C3 interface */
+static struct omap_hwmod_addr_space omap3xxx_i2c3_addr_space[] = {
+ {
+ .pa_start = 0x48060000,
+ .pa_end = 0x48060000 + SZ_128 - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_i2c3_hwmod,
+ .clk = "i2c3_ick",
+ .addr = omap3xxx_i2c3_addr_space,
+ .fw = {
+ .omap2 = {
+ .l4_fw_region = OMAP3_L4_CORE_FW_I2C3_REGION,
+ .l4_prot_group = 7,
+ .flags = OMAP_FIREWALL_L4,
+ }
+ },
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> SR1 interface */
+static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = {
+ {
+ .pa_start = OMAP34XX_SR1_BASE,
+ .pa_end = OMAP34XX_SR1_BASE + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_core__sr1 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap34xx_sr1_hwmod,
+ .clk = "sr_l4_ick",
+ .addr = omap3_sr1_addr_space,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if omap36xx_l4_core__sr1 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap36xx_sr1_hwmod,
+ .clk = "sr_l4_ick",
+ .addr = omap3_sr1_addr_space,
+ .user = OCP_USER_MPU,
+};
+
+/* L4 CORE -> SR1 interface */
+static struct omap_hwmod_addr_space omap3_sr2_addr_space[] = {
+ {
+ .pa_start = OMAP34XX_SR2_BASE,
+ .pa_end = OMAP34XX_SR2_BASE + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_core__sr2 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap34xx_sr2_hwmod,
+ .clk = "sr_l4_ick",
+ .addr = omap3_sr2_addr_space,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if omap36xx_l4_core__sr2 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap36xx_sr2_hwmod,
+ .clk = "sr_l4_ick",
+ .addr = omap3_sr2_addr_space,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_usbhsotg_addrs[] = {
+ {
+ .pa_start = OMAP34XX_HSUSB_OTG_BASE,
+ .pa_end = OMAP34XX_HSUSB_OTG_BASE + SZ_4K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_core -> usbhsotg */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__usbhsotg = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_usbhsotg_hwmod,
+ .clk = "l4_ick",
+ .addr = omap3xxx_usbhsotg_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am35xx_usbhsotg_addrs[] = {
+ {
+ .pa_start = AM35XX_IPSS_USBOTGSS_BASE,
+ .pa_end = AM35XX_IPSS_USBOTGSS_BASE + SZ_4K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_core -> usbhsotg */
+static struct omap_hwmod_ocp_if am35xx_l4_core__usbhsotg = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &am35xx_usbhsotg_hwmod,
+ .clk = "l4_ick",
+ .addr = am35xx_usbhsotg_addrs,
+ .user = OCP_USER_MPU,
+};
+
+/* L4_WKUP -> L4_SEC interface */
+static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__l4_sec = {
+ .master = &omap3xxx_l4_wkup_hwmod,
+ .slave = &omap3xxx_l4_sec_hwmod,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* IVA2 <- L3 interface */
+static struct omap_hwmod_ocp_if omap3xxx_l3__iva = {
+ .master = &omap3xxx_l3_main_hwmod,
+ .slave = &omap3xxx_iva_hwmod,
+ .clk = "core_l3_ick",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer1_addrs[] = {
+ {
+ .pa_start = 0x48318000,
+ .pa_end = 0x48318000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_wkup -> timer1 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__timer1 = {
+ .master = &omap3xxx_l4_wkup_hwmod,
+ .slave = &omap3xxx_timer1_hwmod,
+ .clk = "gpt1_ick",
+ .addr = omap3xxx_timer1_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer2_addrs[] = {
+ {
+ .pa_start = 0x49032000,
+ .pa_end = 0x49032000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer2 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer2 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_timer2_hwmod,
+ .clk = "gpt2_ick",
+ .addr = omap3xxx_timer2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer3_addrs[] = {
+ {
+ .pa_start = 0x49034000,
+ .pa_end = 0x49034000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer3 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer3 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_timer3_hwmod,
+ .clk = "gpt3_ick",
+ .addr = omap3xxx_timer3_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer4_addrs[] = {
+ {
+ .pa_start = 0x49036000,
+ .pa_end = 0x49036000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer4 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer4 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_timer4_hwmod,
+ .clk = "gpt4_ick",
+ .addr = omap3xxx_timer4_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer5_addrs[] = {
+ {
+ .pa_start = 0x49038000,
+ .pa_end = 0x49038000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer5 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer5 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_timer5_hwmod,
+ .clk = "gpt5_ick",
+ .addr = omap3xxx_timer5_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer6_addrs[] = {
+ {
+ .pa_start = 0x4903A000,
+ .pa_end = 0x4903A000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer6 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer6 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_timer6_hwmod,
+ .clk = "gpt6_ick",
+ .addr = omap3xxx_timer6_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer7_addrs[] = {
+ {
+ .pa_start = 0x4903C000,
+ .pa_end = 0x4903C000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer7 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer7 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_timer7_hwmod,
+ .clk = "gpt7_ick",
+ .addr = omap3xxx_timer7_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer8_addrs[] = {
+ {
+ .pa_start = 0x4903E000,
+ .pa_end = 0x4903E000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer8 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer8 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_timer8_hwmod,
+ .clk = "gpt8_ick",
+ .addr = omap3xxx_timer8_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer9_addrs[] = {
+ {
+ .pa_start = 0x49040000,
+ .pa_end = 0x49040000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer9 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer9 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_timer9_hwmod,
+ .clk = "gpt9_ick",
+ .addr = omap3xxx_timer9_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> timer10 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer10 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_timer10_hwmod,
+ .clk = "gpt10_ick",
+ .addr = omap2_timer10_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> timer11 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer11 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_timer11_hwmod,
+ .clk = "gpt11_ick",
+ .addr = omap2_timer11_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer12_addrs[] = {
+ {
+ .pa_start = 0x48304000,
+ .pa_end = 0x48304000 + SZ_1K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_core -> timer12 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_sec__timer12 = {
+ .master = &omap3xxx_l4_sec_hwmod,
+ .slave = &omap3xxx_timer12_hwmod,
+ .clk = "gpt12_ick",
+ .addr = omap3xxx_timer12_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_addr_space omap3xxx_wd_timer2_addrs[] = {
+ {
+ .pa_start = 0x48314000,
+ .pa_end = 0x4831407f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__wd_timer2 = {
+ .master = &omap3xxx_l4_wkup_hwmod,
+ .slave = &omap3xxx_wd_timer2_hwmod,
+ .clk = "wdt2_ick",
+ .addr = omap3xxx_wd_timer2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> dss */
+static struct omap_hwmod_ocp_if omap3430es1_l4_core__dss = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3430es1_dss_core_hwmod,
+ .clk = "dss_ick",
+ .addr = omap2_dss_addrs,
+ .fw = {
+ .omap2 = {
+ .l4_fw_region = OMAP3ES1_L4_CORE_FW_DSS_CORE_REGION,
+ .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+ .flags = OMAP_FIREWALL_L4,
+ }
+ },
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_dss_core_hwmod,
+ .clk = "dss_ick",
+ .addr = omap2_dss_addrs,
+ .fw = {
+ .omap2 = {
+ .l4_fw_region = OMAP3_L4_CORE_FW_DSS_CORE_REGION,
+ .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+ .flags = OMAP_FIREWALL_L4,
+ }
+ },
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> dss_dispc */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dispc = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_dss_dispc_hwmod,
+ .clk = "dss_ick",
+ .addr = omap2_dss_dispc_addrs,
+ .fw = {
+ .omap2 = {
+ .l4_fw_region = OMAP3_L4_CORE_FW_DSS_DISPC_REGION,
+ .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+ .flags = OMAP_FIREWALL_L4,
+ }
+ },
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = {
+ {
+ .pa_start = 0x4804FC00,
+ .pa_end = 0x4804FFFF,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_core -> dss_dsi1 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dsi1 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_dss_dsi1_hwmod,
+ .clk = "dss_ick",
+ .addr = omap3xxx_dss_dsi1_addrs,
+ .fw = {
+ .omap2 = {
+ .l4_fw_region = OMAP3_L4_CORE_FW_DSS_DSI_REGION,
+ .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+ .flags = OMAP_FIREWALL_L4,
+ }
+ },
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> dss_rfbi */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_rfbi = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_dss_rfbi_hwmod,
+ .clk = "dss_ick",
+ .addr = omap2_dss_rfbi_addrs,
+ .fw = {
+ .omap2 = {
+ .l4_fw_region = OMAP3_L4_CORE_FW_DSS_RFBI_REGION,
+ .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP ,
+ .flags = OMAP_FIREWALL_L4,
+ }
+ },
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> dss_venc */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_venc = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_dss_venc_hwmod,
+ .clk = "dss_ick",
+ .addr = omap2_dss_venc_addrs,
+ .fw = {
+ .omap2 = {
+ .l4_fw_region = OMAP3_L4_CORE_FW_DSS_VENC_REGION,
+ .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+ .flags = OMAP_FIREWALL_L4,
+ }
+ },
+ .flags = OCPIF_SWSUP_IDLE,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio1 */
+static struct omap_hwmod_addr_space omap3xxx_gpio1_addrs[] = {
+ {
+ .pa_start = 0x48310000,
+ .pa_end = 0x483101ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__gpio1 = {
+ .master = &omap3xxx_l4_wkup_hwmod,
+ .slave = &omap3xxx_gpio1_hwmod,
+ .addr = omap3xxx_gpio1_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio2 */
+static struct omap_hwmod_addr_space omap3xxx_gpio2_addrs[] = {
+ {
+ .pa_start = 0x49050000,
+ .pa_end = 0x490501ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio2 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_gpio2_hwmod,
+ .addr = omap3xxx_gpio2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio3 */
+static struct omap_hwmod_addr_space omap3xxx_gpio3_addrs[] = {
+ {
+ .pa_start = 0x49052000,
+ .pa_end = 0x490521ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio3 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_gpio3_hwmod,
+ .addr = omap3xxx_gpio3_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio4 */
+static struct omap_hwmod_addr_space omap3xxx_gpio4_addrs[] = {
+ {
+ .pa_start = 0x49054000,
+ .pa_end = 0x490541ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio4 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_gpio4_hwmod,
+ .addr = omap3xxx_gpio4_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio5 */
+static struct omap_hwmod_addr_space omap3xxx_gpio5_addrs[] = {
+ {
+ .pa_start = 0x49056000,
+ .pa_end = 0x490561ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio5 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_gpio5_hwmod,
+ .addr = omap3xxx_gpio5_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio6 */
+static struct omap_hwmod_addr_space omap3xxx_gpio6_addrs[] = {
+ {
+ .pa_start = 0x49058000,
+ .pa_end = 0x490581ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio6 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_gpio6_hwmod,
+ .addr = omap3xxx_gpio6_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system -> L3 */
+static struct omap_hwmod_ocp_if omap3xxx_dma_system__l3 = {
+ .master = &omap3xxx_dma_system_hwmod,
+ .slave = &omap3xxx_l3_main_hwmod,
+ .clk = "core_l3_ick",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = {
+ {
+ .pa_start = 0x48056000,
+ .pa_end = 0x48056fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> dma_system */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dma_system = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_dma_system_hwmod,
+ .clk = "core_l4_ick",
+ .addr = omap3xxx_dma_system_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp1_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x48074000,
+ .pa_end = 0x480740ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_core -> mcbsp1 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp1 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_mcbsp1_hwmod,
+ .clk = "mcbsp1_ick",
+ .addr = omap3xxx_mcbsp1_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp2_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x49022000,
+ .pa_end = 0x490220ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mcbsp2 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_mcbsp2_hwmod,
+ .clk = "mcbsp2_ick",
+ .addr = omap3xxx_mcbsp2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp3_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x49024000,
+ .pa_end = 0x490240ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mcbsp3 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_mcbsp3_hwmod,
+ .clk = "mcbsp3_ick",
+ .addr = omap3xxx_mcbsp3_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp4_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x49026000,
+ .pa_end = 0x490260ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mcbsp4 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp4 = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_mcbsp4_hwmod,
+ .clk = "mcbsp4_ick",
+ .addr = omap3xxx_mcbsp4_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp5_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x48096000,
+ .pa_end = 0x480960ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_core -> mcbsp5 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp5 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_mcbsp5_hwmod,
+ .clk = "mcbsp5_ick",
+ .addr = omap3xxx_mcbsp5_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp2_sidetone_addrs[] = {
+ {
+ .name = "sidetone",
+ .pa_start = 0x49028000,
+ .pa_end = 0x490280ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mcbsp2_sidetone */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2_sidetone = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_mcbsp2_sidetone_hwmod,
+ .clk = "mcbsp2_ick",
+ .addr = omap3xxx_mcbsp2_sidetone_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp3_sidetone_addrs[] = {
+ {
+ .name = "sidetone",
+ .pa_start = 0x4902A000,
+ .pa_end = 0x4902A0ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mcbsp3_sidetone */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3_sidetone = {
+ .master = &omap3xxx_l4_per_hwmod,
+ .slave = &omap3xxx_mcbsp3_sidetone_hwmod,
+ .clk = "mcbsp3_ick",
+ .addr = omap3xxx_mcbsp3_sidetone_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mailbox_addrs[] = {
+ {
+ .pa_start = 0x48094000,
+ .pa_end = 0x480941ff,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+/* l4_core -> mailbox */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mailbox = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_mailbox_hwmod,
+ .addr = omap3xxx_mailbox_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi1 interface */
+static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi1 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap34xx_mcspi1,
+ .clk = "mcspi1_ick",
+ .addr = omap2_mcspi1_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi2 interface */
+static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi2 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap34xx_mcspi2,
+ .clk = "mcspi2_ick",
+ .addr = omap2_mcspi2_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi3 interface */
+static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi3 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap34xx_mcspi3,
+ .clk = "mcspi3_ick",
+ .addr = omap2430_mcspi3_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi4 interface */
+static struct omap_hwmod_addr_space omap34xx_mcspi4_addr_space[] = {
+ {
+ .pa_start = 0x480ba000,
+ .pa_end = 0x480ba0ff,
+ .flags = ADDR_TYPE_RT,
+ },
+ { }
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi4 = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap34xx_mcspi4,
+ .clk = "mcspi4_ick",
+ .addr = omap34xx_mcspi4_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_usb_host_hs__l3_main_2 = {
+ .master = &omap3xxx_usb_host_hs_hwmod,
+ .slave = &omap3xxx_l3_main_hwmod,
+ .clk = "core_l3_ick",
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_usb_host_hs_addrs[] = {
+ {
+ .name = "uhh",
+ .pa_start = 0x48064000,
+ .pa_end = 0x480643ff,
+ .flags = ADDR_TYPE_RT
+ },
+ {
+ .name = "ohci",
+ .pa_start = 0x48064400,
+ .pa_end = 0x480647ff,
+ },
+ {
+ .name = "ehci",
+ .pa_start = 0x48064800,
+ .pa_end = 0x48064cff,
+ },
+ {}
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__usb_host_hs = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_usb_host_hs_hwmod,
+ .clk = "usbhost_ick",
+ .addr = omap3xxx_usb_host_hs_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
static struct omap_hwmod_addr_space omap3xxx_usb_tll_hs_addrs[] = {
{
.name = "tll",
@@ -3519,183 +3110,187 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__usb_tll_hs = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-static struct omap_hwmod_ocp_if *omap3xxx_usb_tll_hs_slaves[] = {
- &omap3xxx_l4_core__usb_tll_hs,
+/* l4_core -> hdq1w interface */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__hdq1w = {
+ .master = &omap3xxx_l4_core_hwmod,
+ .slave = &omap3xxx_hdq1w_hwmod,
+ .clk = "hdq_ick",
+ .addr = omap2_hdq1w_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ .flags = OMAP_FIREWALL_L4 | OCPIF_SWSUP_IDLE,
};
-static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod = {
- .name = "usb_tll_hs",
- .class = &omap3xxx_usb_tll_hs_hwmod_class,
- .clkdm_name = "l3_init_clkdm",
- .mpu_irqs = omap3xxx_usb_tll_hs_irqs,
- .main_clk = "usbtll_fck",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .prcm_reg_id = 3,
- .module_bit = OMAP3430ES2_EN_USBTLL_SHIFT,
- .idlest_reg_id = 3,
- .idlest_idle_bit = OMAP3430ES2_ST_USBTLL_SHIFT,
- },
+/* l4_wkup -> 32ksync_counter */
+static struct omap_hwmod_addr_space omap3xxx_counter_32k_addrs[] = {
+ {
+ .pa_start = 0x48320000,
+ .pa_end = 0x4832001f,
+ .flags = ADDR_TYPE_RT
},
- .slaves = omap3xxx_usb_tll_hs_slaves,
- .slaves_cnt = ARRAY_SIZE(omap3xxx_usb_tll_hs_slaves),
-};
-
-static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
- &omap3xxx_l3_main_hwmod,
- &omap3xxx_l4_core_hwmod,
- &omap3xxx_l4_per_hwmod,
- &omap3xxx_l4_wkup_hwmod,
- &omap3xxx_mmc3_hwmod,
- &omap3xxx_mpu_hwmod,
-
- &omap3xxx_timer1_hwmod,
- &omap3xxx_timer2_hwmod,
- &omap3xxx_timer3_hwmod,
- &omap3xxx_timer4_hwmod,
- &omap3xxx_timer5_hwmod,
- &omap3xxx_timer6_hwmod,
- &omap3xxx_timer7_hwmod,
- &omap3xxx_timer8_hwmod,
- &omap3xxx_timer9_hwmod,
- &omap3xxx_timer10_hwmod,
- &omap3xxx_timer11_hwmod,
-
- &omap3xxx_wd_timer2_hwmod,
- &omap3xxx_uart1_hwmod,
- &omap3xxx_uart2_hwmod,
- &omap3xxx_uart3_hwmod,
-
- /* i2c class */
- &omap3xxx_i2c1_hwmod,
- &omap3xxx_i2c2_hwmod,
- &omap3xxx_i2c3_hwmod,
-
- /* gpio class */
- &omap3xxx_gpio1_hwmod,
- &omap3xxx_gpio2_hwmod,
- &omap3xxx_gpio3_hwmod,
- &omap3xxx_gpio4_hwmod,
- &omap3xxx_gpio5_hwmod,
- &omap3xxx_gpio6_hwmod,
-
- /* dma_system class*/
- &omap3xxx_dma_system_hwmod,
-
- /* mcbsp class */
- &omap3xxx_mcbsp1_hwmod,
- &omap3xxx_mcbsp2_hwmod,
- &omap3xxx_mcbsp3_hwmod,
- &omap3xxx_mcbsp4_hwmod,
- &omap3xxx_mcbsp5_hwmod,
- &omap3xxx_mcbsp2_sidetone_hwmod,
- &omap3xxx_mcbsp3_sidetone_hwmod,
-
-
- /* mcspi class */
- &omap34xx_mcspi1,
- &omap34xx_mcspi2,
- &omap34xx_mcspi3,
- &omap34xx_mcspi4,
+ { }
+};
+static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__counter_32k = {
+ .master = &omap3xxx_l4_wkup_hwmod,
+ .slave = &omap3xxx_counter_32k_hwmod,
+ .clk = "omap_32ksync_ick",
+ .addr = omap3xxx_counter_32k_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
+ &omap3xxx_l3_main__l4_core,
+ &omap3xxx_l3_main__l4_per,
+ &omap3xxx_mpu__l3_main,
+ &omap3xxx_l4_core__l4_wkup,
+ &omap3xxx_l4_core__mmc3,
+ &omap3_l4_core__uart1,
+ &omap3_l4_core__uart2,
+ &omap3_l4_per__uart3,
+ &omap3_l4_core__i2c1,
+ &omap3_l4_core__i2c2,
+ &omap3_l4_core__i2c3,
+ &omap3xxx_l4_wkup__l4_sec,
+ &omap3xxx_l4_wkup__timer1,
+ &omap3xxx_l4_per__timer2,
+ &omap3xxx_l4_per__timer3,
+ &omap3xxx_l4_per__timer4,
+ &omap3xxx_l4_per__timer5,
+ &omap3xxx_l4_per__timer6,
+ &omap3xxx_l4_per__timer7,
+ &omap3xxx_l4_per__timer8,
+ &omap3xxx_l4_per__timer9,
+ &omap3xxx_l4_core__timer10,
+ &omap3xxx_l4_core__timer11,
+ &omap3xxx_l4_wkup__wd_timer2,
+ &omap3xxx_l4_wkup__gpio1,
+ &omap3xxx_l4_per__gpio2,
+ &omap3xxx_l4_per__gpio3,
+ &omap3xxx_l4_per__gpio4,
+ &omap3xxx_l4_per__gpio5,
+ &omap3xxx_l4_per__gpio6,
+ &omap3xxx_dma_system__l3,
+ &omap3xxx_l4_core__dma_system,
+ &omap3xxx_l4_core__mcbsp1,
+ &omap3xxx_l4_per__mcbsp2,
+ &omap3xxx_l4_per__mcbsp3,
+ &omap3xxx_l4_per__mcbsp4,
+ &omap3xxx_l4_core__mcbsp5,
+ &omap3xxx_l4_per__mcbsp2_sidetone,
+ &omap3xxx_l4_per__mcbsp3_sidetone,
+ &omap34xx_l4_core__mcspi1,
+ &omap34xx_l4_core__mcspi2,
+ &omap34xx_l4_core__mcspi3,
+ &omap34xx_l4_core__mcspi4,
+ &omap3xxx_l4_wkup__counter_32k,
NULL,
};
-/* GP-only hwmods */
-static __initdata struct omap_hwmod *omap3xxx_gp_hwmods[] = {
- &omap3xxx_timer12_hwmod,
+/* GP-only hwmod links */
+static struct omap_hwmod_ocp_if *omap3xxx_gp_hwmod_ocp_ifs[] __initdata = {
+ &omap3xxx_l4_sec__timer12,
NULL
};
-/* 3430ES1-only hwmods */
-static __initdata struct omap_hwmod *omap3430es1_hwmods[] = {
- &omap3430es1_dss_core_hwmod,
+/* 3430ES1-only hwmod links */
+static struct omap_hwmod_ocp_if *omap3430es1_hwmod_ocp_ifs[] __initdata = {
+ &omap3430es1_dss__l3,
+ &omap3430es1_l4_core__dss,
NULL
};
-/* 3430ES2+-only hwmods */
-static __initdata struct omap_hwmod *omap3430es2plus_hwmods[] = {
- &omap3xxx_dss_core_hwmod,
- &omap3xxx_usbhsotg_hwmod,
- &omap3xxx_usb_host_hs_hwmod,
- &omap3xxx_usb_tll_hs_hwmod,
+/* 3430ES2+-only hwmod links */
+static struct omap_hwmod_ocp_if *omap3430es2plus_hwmod_ocp_ifs[] __initdata = {
+ &omap3xxx_dss__l3,
+ &omap3xxx_l4_core__dss,
+ &omap3xxx_usbhsotg__l3,
+ &omap3xxx_l4_core__usbhsotg,
+ &omap3xxx_usb_host_hs__l3_main_2,
+ &omap3xxx_l4_core__usb_host_hs,
+ &omap3xxx_l4_core__usb_tll_hs,
NULL
};
-/* <= 3430ES3-only hwmods */
-static struct omap_hwmod *omap3430_pre_es3_hwmods[] __initdata = {
- &omap3xxx_pre_es3_mmc1_hwmod,
- &omap3xxx_pre_es3_mmc2_hwmod,
+/* <= 3430ES3-only hwmod links */
+static struct omap_hwmod_ocp_if *omap3430_pre_es3_hwmod_ocp_ifs[] __initdata = {
+ &omap3xxx_l4_core__pre_es3_mmc1,
+ &omap3xxx_l4_core__pre_es3_mmc2,
NULL
};
-/* 3430ES3+-only hwmods */
-static struct omap_hwmod *omap3430_es3plus_hwmods[] __initdata = {
- &omap3xxx_es3plus_mmc1_hwmod,
- &omap3xxx_es3plus_mmc2_hwmod,
+/* 3430ES3+-only hwmod links */
+static struct omap_hwmod_ocp_if *omap3430_es3plus_hwmod_ocp_ifs[] __initdata = {
+ &omap3xxx_l4_core__es3plus_mmc1,
+ &omap3xxx_l4_core__es3plus_mmc2,
NULL
};
-/* 34xx-only hwmods (all ES revisions) */
-static __initdata struct omap_hwmod *omap34xx_hwmods[] = {
- &omap3xxx_iva_hwmod,
- &omap34xx_sr1_hwmod,
- &omap34xx_sr2_hwmod,
- &omap3xxx_mailbox_hwmod,
+/* 34xx-only hwmod links (all ES revisions) */
+static struct omap_hwmod_ocp_if *omap34xx_hwmod_ocp_ifs[] __initdata = {
+ &omap3xxx_l3__iva,
+ &omap34xx_l4_core__sr1,
+ &omap34xx_l4_core__sr2,
+ &omap3xxx_l4_core__mailbox,
+ &omap3xxx_l4_core__hdq1w,
NULL
};
-/* 36xx-only hwmods (all ES revisions) */
-static __initdata struct omap_hwmod *omap36xx_hwmods[] = {
- &omap3xxx_iva_hwmod,
- &omap3xxx_uart4_hwmod,
- &omap3xxx_dss_core_hwmod,
- &omap36xx_sr1_hwmod,
- &omap36xx_sr2_hwmod,
- &omap3xxx_usbhsotg_hwmod,
- &omap3xxx_mailbox_hwmod,
- &omap3xxx_usb_host_hs_hwmod,
- &omap3xxx_usb_tll_hs_hwmod,
- &omap3xxx_es3plus_mmc1_hwmod,
- &omap3xxx_es3plus_mmc2_hwmod,
+/* 36xx-only hwmod links (all ES revisions) */
+static struct omap_hwmod_ocp_if *omap36xx_hwmod_ocp_ifs[] __initdata = {
+ &omap3xxx_l3__iva,
+ &omap36xx_l4_per__uart4,
+ &omap3xxx_dss__l3,
+ &omap3xxx_l4_core__dss,
+ &omap36xx_l4_core__sr1,
+ &omap36xx_l4_core__sr2,
+ &omap3xxx_usbhsotg__l3,
+ &omap3xxx_l4_core__usbhsotg,
+ &omap3xxx_l4_core__mailbox,
+ &omap3xxx_usb_host_hs__l3_main_2,
+ &omap3xxx_l4_core__usb_host_hs,
+ &omap3xxx_l4_core__usb_tll_hs,
+ &omap3xxx_l4_core__es3plus_mmc1,
+ &omap3xxx_l4_core__es3plus_mmc2,
+ &omap3xxx_l4_core__hdq1w,
NULL
};
-static __initdata struct omap_hwmod *am35xx_hwmods[] = {
- &omap3xxx_dss_core_hwmod, /* XXX ??? */
- &am35xx_usbhsotg_hwmod,
- &am35xx_uart4_hwmod,
- &omap3xxx_usb_host_hs_hwmod,
- &omap3xxx_usb_tll_hs_hwmod,
- &omap3xxx_es3plus_mmc1_hwmod,
- &omap3xxx_es3plus_mmc2_hwmod,
+static struct omap_hwmod_ocp_if *am35xx_hwmod_ocp_ifs[] __initdata = {
+ &omap3xxx_dss__l3,
+ &omap3xxx_l4_core__dss,
+ &am35xx_usbhsotg__l3,
+ &am35xx_l4_core__usbhsotg,
+ &am35xx_l4_core__uart4,
+ &omap3xxx_usb_host_hs__l3_main_2,
+ &omap3xxx_l4_core__usb_host_hs,
+ &omap3xxx_l4_core__usb_tll_hs,
+ &omap3xxx_l4_core__es3plus_mmc1,
+ &omap3xxx_l4_core__es3plus_mmc2,
NULL
};
-static __initdata struct omap_hwmod *omap3xxx_dss_hwmods[] = {
- /* dss class */
- &omap3xxx_dss_dispc_hwmod,
- &omap3xxx_dss_dsi1_hwmod,
- &omap3xxx_dss_rfbi_hwmod,
- &omap3xxx_dss_venc_hwmod,
+static struct omap_hwmod_ocp_if *omap3xxx_dss_hwmod_ocp_ifs[] __initdata = {
+ &omap3xxx_l4_core__dss_dispc,
+ &omap3xxx_l4_core__dss_dsi1,
+ &omap3xxx_l4_core__dss_rfbi,
+ &omap3xxx_l4_core__dss_venc,
NULL
};
int __init omap3xxx_hwmod_init(void)
{
int r;
- struct omap_hwmod **h = NULL;
+ struct omap_hwmod_ocp_if **h = NULL;
unsigned int rev;
- /* Register hwmods common to all OMAP3 */
- r = omap_hwmod_register(omap3xxx_hwmods);
+ /* Register hwmod links common to all OMAP3 */
+ r = omap_hwmod_register_links(omap3xxx_hwmod_ocp_ifs);
if (r < 0)
return r;
- /* Register GP-only hwmods. */
+ /* Register GP-only hwmod links. */
if (omap_type() == OMAP2_DEVICE_TYPE_GP) {
- r = omap_hwmod_register(omap3xxx_gp_hwmods);
+ r = omap_hwmod_register_links(omap3xxx_gp_hwmod_ocp_ifs);
if (r < 0)
return r;
}
@@ -3703,43 +3298,43 @@ int __init omap3xxx_hwmod_init(void)
rev = omap_rev();
/*
- * Register hwmods common to individual OMAP3 families, all
+ * Register hwmod links common to individual OMAP3 families, all
* silicon revisions (e.g., 34xx, or AM3505/3517, or 36xx)
* All possible revisions should be included in this conditional.
*/
if (rev == OMAP3430_REV_ES1_0 || rev == OMAP3430_REV_ES2_0 ||
rev == OMAP3430_REV_ES2_1 || rev == OMAP3430_REV_ES3_0 ||
rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2) {
- h = omap34xx_hwmods;
+ h = omap34xx_hwmod_ocp_ifs;
} else if (rev == OMAP3517_REV_ES1_0 || rev == OMAP3517_REV_ES1_1) {
- h = am35xx_hwmods;
+ h = am35xx_hwmod_ocp_ifs;
} else if (rev == OMAP3630_REV_ES1_0 || rev == OMAP3630_REV_ES1_1 ||
rev == OMAP3630_REV_ES1_2) {
- h = omap36xx_hwmods;
+ h = omap36xx_hwmod_ocp_ifs;
} else {
WARN(1, "OMAP3 hwmod family init: unknown chip type\n");
return -EINVAL;
};
- r = omap_hwmod_register(h);
+ r = omap_hwmod_register_links(h);
if (r < 0)
return r;
/*
- * Register hwmods specific to certain ES levels of a
+ * Register hwmod links specific to certain ES levels of a
* particular family of silicon (e.g., 34xx ES1.0)
*/
h = NULL;
if (rev == OMAP3430_REV_ES1_0) {
- h = omap3430es1_hwmods;
+ h = omap3430es1_hwmod_ocp_ifs;
} else if (rev == OMAP3430_REV_ES2_0 || rev == OMAP3430_REV_ES2_1 ||
rev == OMAP3430_REV_ES3_0 || rev == OMAP3430_REV_ES3_1 ||
rev == OMAP3430_REV_ES3_1_2) {
- h = omap3430es2plus_hwmods;
+ h = omap3430es2plus_hwmod_ocp_ifs;
};
if (h) {
- r = omap_hwmod_register(h);
+ r = omap_hwmod_register_links(h);
if (r < 0)
return r;
}
@@ -3747,29 +3342,29 @@ int __init omap3xxx_hwmod_init(void)
h = NULL;
if (rev == OMAP3430_REV_ES1_0 || rev == OMAP3430_REV_ES2_0 ||
rev == OMAP3430_REV_ES2_1) {
- h = omap3430_pre_es3_hwmods;
+ h = omap3430_pre_es3_hwmod_ocp_ifs;
} else if (rev == OMAP3430_REV_ES3_0 || rev == OMAP3430_REV_ES3_1 ||
rev == OMAP3430_REV_ES3_1_2) {
- h = omap3430_es3plus_hwmods;
+ h = omap3430_es3plus_hwmod_ocp_ifs;
};
if (h)
- r = omap_hwmod_register(h);
+ r = omap_hwmod_register_links(h);
if (r < 0)
return r;
/*
* DSS code presumes that dss_core hwmod is handled first,
* _before_ any other DSS related hwmods so register common
- * DSS hwmods last to ensure that dss_core is already registered.
- * Otherwise some change things may happen, for ex. if dispc
- * is handled before dss_core and DSS is enabled in bootloader
- * DIPSC will be reset with outputs enabled which sometimes leads
- * to unrecoverable L3 error.
- * XXX The long-term fix to this is to ensure modules are set up
- * in dependency order in the hwmod core code.
+ * DSS hwmod links last to ensure that dss_core is already
+ * registered. Otherwise some change things may happen, for
+ * ex. if dispc is handled before dss_core and DSS is enabled
+ * in bootloader DISPC will be reset with outputs enabled
+ * which sometimes leads to unrecoverable L3 error. XXX The
+ * long-term fix to this is to ensure hwmods are set up in
+ * dependency order in the hwmod core code.
*/
- r = omap_hwmod_register(omap3xxx_dss_hwmods);
+ r = omap_hwmod_register_links(omap3xxx_dss_hwmod_ocp_ifs);
return r;
}
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 6abc75753e42..950454a3fa31 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1,7 +1,7 @@
/*
* Hardware modules present on the OMAP44xx chips
*
- * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ * Copyright (C) 2009-2012 Texas Instruments, Inc.
* Copyright (C) 2009-2010 Nokia Corporation
*
* Paul Walmsley
@@ -44,41 +44,34 @@
#define OMAP44XX_IRQ_GIC_START 32
/* Base offset for all OMAP4 dma requests */
-#define OMAP44XX_DMA_REQ_START 1
-
-/* Backward references (IPs with Bus Master capability) */
-static struct omap_hwmod omap44xx_aess_hwmod;
-static struct omap_hwmod omap44xx_dma_system_hwmod;
-static struct omap_hwmod omap44xx_dmm_hwmod;
-static struct omap_hwmod omap44xx_dsp_hwmod;
-static struct omap_hwmod omap44xx_dss_hwmod;
-static struct omap_hwmod omap44xx_emif_fw_hwmod;
-static struct omap_hwmod omap44xx_hsi_hwmod;
-static struct omap_hwmod omap44xx_ipu_hwmod;
-static struct omap_hwmod omap44xx_iss_hwmod;
-static struct omap_hwmod omap44xx_iva_hwmod;
-static struct omap_hwmod omap44xx_l3_instr_hwmod;
-static struct omap_hwmod omap44xx_l3_main_1_hwmod;
-static struct omap_hwmod omap44xx_l3_main_2_hwmod;
-static struct omap_hwmod omap44xx_l3_main_3_hwmod;
-static struct omap_hwmod omap44xx_l4_abe_hwmod;
-static struct omap_hwmod omap44xx_l4_cfg_hwmod;
-static struct omap_hwmod omap44xx_l4_per_hwmod;
-static struct omap_hwmod omap44xx_l4_wkup_hwmod;
-static struct omap_hwmod omap44xx_mmc1_hwmod;
-static struct omap_hwmod omap44xx_mmc2_hwmod;
-static struct omap_hwmod omap44xx_mpu_hwmod;
-static struct omap_hwmod omap44xx_mpu_private_hwmod;
-static struct omap_hwmod omap44xx_usb_otg_hs_hwmod;
-static struct omap_hwmod omap44xx_usb_host_hs_hwmod;
-static struct omap_hwmod omap44xx_usb_tll_hs_hwmod;
+#define OMAP44XX_DMA_REQ_START 1
/*
- * Interconnects omap_hwmod structures
- * hwmods that compose the global OMAP interconnect
+ * IP blocks
*/
/*
+ * 'c2c_target_fw' class
+ * instance(s): c2c_target_fw
+ */
+static struct omap_hwmod_class omap44xx_c2c_target_fw_hwmod_class = {
+ .name = "c2c_target_fw",
+};
+
+/* c2c_target_fw */
+static struct omap_hwmod omap44xx_c2c_target_fw_hwmod = {
+ .name = "c2c_target_fw",
+ .class = &omap44xx_c2c_target_fw_hwmod_class,
+ .clkdm_name = "d2d_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_D2D_SAD2D_FW_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_D2D_SAD2D_FW_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/*
* 'dmm' class
* instance(s): dmm
*/
@@ -92,51 +85,17 @@ static struct omap_hwmod_irq_info omap44xx_dmm_irqs[] = {
{ .irq = -1 }
};
-/* l3_main_1 -> dmm */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_1__dmm = {
- .master = &omap44xx_l3_main_1_hwmod,
- .slave = &omap44xx_dmm_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_addr_space omap44xx_dmm_addrs[] = {
- {
- .pa_start = 0x4e000000,
- .pa_end = 0x4e0007ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* mpu -> dmm */
-static struct omap_hwmod_ocp_if omap44xx_mpu__dmm = {
- .master = &omap44xx_mpu_hwmod,
- .slave = &omap44xx_dmm_hwmod,
- .clk = "l3_div_ck",
- .addr = omap44xx_dmm_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* dmm slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_dmm_slaves[] = {
- &omap44xx_l3_main_1__dmm,
- &omap44xx_mpu__dmm,
-};
-
static struct omap_hwmod omap44xx_dmm_hwmod = {
.name = "dmm",
.class = &omap44xx_dmm_hwmod_class,
.clkdm_name = "l3_emif_clkdm",
+ .mpu_irqs = omap44xx_dmm_irqs,
.prcm = {
.omap4 = {
.clkctrl_offs = OMAP4_CM_MEMIF_DMM_CLKCTRL_OFFSET,
.context_offs = OMAP4_RM_MEMIF_DMM_CONTEXT_OFFSET,
},
},
- .slaves = omap44xx_dmm_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_dmm_slaves),
- .mpu_irqs = omap44xx_dmm_irqs,
};
/*
@@ -148,38 +107,6 @@ static struct omap_hwmod_class omap44xx_emif_fw_hwmod_class = {
};
/* emif_fw */
-/* dmm -> emif_fw */
-static struct omap_hwmod_ocp_if omap44xx_dmm__emif_fw = {
- .master = &omap44xx_dmm_hwmod,
- .slave = &omap44xx_emif_fw_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_addr_space omap44xx_emif_fw_addrs[] = {
- {
- .pa_start = 0x4a20c000,
- .pa_end = 0x4a20c0ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_cfg -> emif_fw */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__emif_fw = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_emif_fw_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_emif_fw_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* emif_fw slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_emif_fw_slaves[] = {
- &omap44xx_dmm__emif_fw,
- &omap44xx_l4_cfg__emif_fw,
-};
-
static struct omap_hwmod omap44xx_emif_fw_hwmod = {
.name = "emif_fw",
.class = &omap44xx_emif_fw_hwmod_class,
@@ -190,8 +117,6 @@ static struct omap_hwmod omap44xx_emif_fw_hwmod = {
.context_offs = OMAP4_RM_MEMIF_EMIF_FW_CONTEXT_OFFSET,
},
},
- .slaves = omap44xx_emif_fw_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_emif_fw_slaves),
};
/*
@@ -203,28 +128,6 @@ static struct omap_hwmod_class omap44xx_l3_hwmod_class = {
};
/* l3_instr */
-/* iva -> l3_instr */
-static struct omap_hwmod_ocp_if omap44xx_iva__l3_instr = {
- .master = &omap44xx_iva_hwmod,
- .slave = &omap44xx_l3_instr_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l3_main_3 -> l3_instr */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_3__l3_instr = {
- .master = &omap44xx_l3_main_3_hwmod,
- .slave = &omap44xx_l3_instr_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l3_instr slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_l3_instr_slaves[] = {
- &omap44xx_iva__l3_instr,
- &omap44xx_l3_main_3__l3_instr,
-};
-
static struct omap_hwmod omap44xx_l3_instr_hwmod = {
.name = "l3_instr",
.class = &omap44xx_l3_hwmod_class,
@@ -236,8 +139,6 @@ static struct omap_hwmod omap44xx_l3_instr_hwmod = {
.modulemode = MODULEMODE_HWCTRL,
},
},
- .slaves = omap44xx_l3_instr_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_l3_instr_slaves),
};
/* l3_main_1 */
@@ -247,83 +148,6 @@ static struct omap_hwmod_irq_info omap44xx_l3_main_1_irqs[] = {
{ .irq = -1 }
};
-/* dsp -> l3_main_1 */
-static struct omap_hwmod_ocp_if omap44xx_dsp__l3_main_1 = {
- .master = &omap44xx_dsp_hwmod,
- .slave = &omap44xx_l3_main_1_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dss -> l3_main_1 */
-static struct omap_hwmod_ocp_if omap44xx_dss__l3_main_1 = {
- .master = &omap44xx_dss_hwmod,
- .slave = &omap44xx_l3_main_1_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l3_main_2 -> l3_main_1 */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_1 = {
- .master = &omap44xx_l3_main_2_hwmod,
- .slave = &omap44xx_l3_main_1_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_cfg -> l3_main_1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_1 = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_l3_main_1_hwmod,
- .clk = "l4_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mmc1 -> l3_main_1 */
-static struct omap_hwmod_ocp_if omap44xx_mmc1__l3_main_1 = {
- .master = &omap44xx_mmc1_hwmod,
- .slave = &omap44xx_l3_main_1_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mmc2 -> l3_main_1 */
-static struct omap_hwmod_ocp_if omap44xx_mmc2__l3_main_1 = {
- .master = &omap44xx_mmc2_hwmod,
- .slave = &omap44xx_l3_main_1_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_addr_space omap44xx_l3_main_1_addrs[] = {
- {
- .pa_start = 0x44000000,
- .pa_end = 0x44000fff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* mpu -> l3_main_1 */
-static struct omap_hwmod_ocp_if omap44xx_mpu__l3_main_1 = {
- .master = &omap44xx_mpu_hwmod,
- .slave = &omap44xx_l3_main_1_hwmod,
- .clk = "l3_div_ck",
- .addr = omap44xx_l3_main_1_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* l3_main_1 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_l3_main_1_slaves[] = {
- &omap44xx_dsp__l3_main_1,
- &omap44xx_dss__l3_main_1,
- &omap44xx_l3_main_2__l3_main_1,
- &omap44xx_l4_cfg__l3_main_1,
- &omap44xx_mmc1__l3_main_1,
- &omap44xx_mmc2__l3_main_1,
- &omap44xx_mpu__l3_main_1,
-};
-
static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
.name = "l3_main_1",
.class = &omap44xx_l3_hwmod_class,
@@ -335,97 +159,9 @@ static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
.context_offs = OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET,
},
},
- .slaves = omap44xx_l3_main_1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_l3_main_1_slaves),
};
/* l3_main_2 */
-/* dma_system -> l3_main_2 */
-static struct omap_hwmod_ocp_if omap44xx_dma_system__l3_main_2 = {
- .master = &omap44xx_dma_system_hwmod,
- .slave = &omap44xx_l3_main_2_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* hsi -> l3_main_2 */
-static struct omap_hwmod_ocp_if omap44xx_hsi__l3_main_2 = {
- .master = &omap44xx_hsi_hwmod,
- .slave = &omap44xx_l3_main_2_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* ipu -> l3_main_2 */
-static struct omap_hwmod_ocp_if omap44xx_ipu__l3_main_2 = {
- .master = &omap44xx_ipu_hwmod,
- .slave = &omap44xx_l3_main_2_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* iss -> l3_main_2 */
-static struct omap_hwmod_ocp_if omap44xx_iss__l3_main_2 = {
- .master = &omap44xx_iss_hwmod,
- .slave = &omap44xx_l3_main_2_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* iva -> l3_main_2 */
-static struct omap_hwmod_ocp_if omap44xx_iva__l3_main_2 = {
- .master = &omap44xx_iva_hwmod,
- .slave = &omap44xx_l3_main_2_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_addr_space omap44xx_l3_main_2_addrs[] = {
- {
- .pa_start = 0x44800000,
- .pa_end = 0x44801fff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l3_main_1 -> l3_main_2 */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
- .master = &omap44xx_l3_main_1_hwmod,
- .slave = &omap44xx_l3_main_2_hwmod,
- .clk = "l3_div_ck",
- .addr = omap44xx_l3_main_2_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* l4_cfg -> l3_main_2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_l3_main_2_hwmod,
- .clk = "l4_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* usb_otg_hs -> l3_main_2 */
-static struct omap_hwmod_ocp_if omap44xx_usb_otg_hs__l3_main_2 = {
- .master = &omap44xx_usb_otg_hs_hwmod,
- .slave = &omap44xx_l3_main_2_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l3_main_2 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
- &omap44xx_dma_system__l3_main_2,
- &omap44xx_hsi__l3_main_2,
- &omap44xx_ipu__l3_main_2,
- &omap44xx_iss__l3_main_2,
- &omap44xx_iva__l3_main_2,
- &omap44xx_l3_main_1__l3_main_2,
- &omap44xx_l4_cfg__l3_main_2,
- &omap44xx_usb_otg_hs__l3_main_2,
-};
-
static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
.name = "l3_main_2",
.class = &omap44xx_l3_hwmod_class,
@@ -436,52 +172,9 @@ static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
.context_offs = OMAP4_RM_L3_2_L3_2_CONTEXT_OFFSET,
},
},
- .slaves = omap44xx_l3_main_2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_l3_main_2_slaves),
};
/* l3_main_3 */
-static struct omap_hwmod_addr_space omap44xx_l3_main_3_addrs[] = {
- {
- .pa_start = 0x45000000,
- .pa_end = 0x45000fff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l3_main_1 -> l3_main_3 */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_3 = {
- .master = &omap44xx_l3_main_1_hwmod,
- .slave = &omap44xx_l3_main_3_hwmod,
- .clk = "l3_div_ck",
- .addr = omap44xx_l3_main_3_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* l3_main_2 -> l3_main_3 */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_3 = {
- .master = &omap44xx_l3_main_2_hwmod,
- .slave = &omap44xx_l3_main_3_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_cfg -> l3_main_3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_3 = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_l3_main_3_hwmod,
- .clk = "l4_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l3_main_3 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_l3_main_3_slaves[] = {
- &omap44xx_l3_main_1__l3_main_3,
- &omap44xx_l3_main_2__l3_main_3,
- &omap44xx_l4_cfg__l3_main_3,
-};
-
static struct omap_hwmod omap44xx_l3_main_3_hwmod = {
.name = "l3_main_3",
.class = &omap44xx_l3_hwmod_class,
@@ -493,8 +186,6 @@ static struct omap_hwmod omap44xx_l3_main_3_hwmod = {
.modulemode = MODULEMODE_HWCTRL,
},
},
- .slaves = omap44xx_l3_main_3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_l3_main_3_slaves),
};
/*
@@ -506,46 +197,6 @@ static struct omap_hwmod_class omap44xx_l4_hwmod_class = {
};
/* l4_abe */
-/* aess -> l4_abe */
-static struct omap_hwmod_ocp_if omap44xx_aess__l4_abe = {
- .master = &omap44xx_aess_hwmod,
- .slave = &omap44xx_l4_abe_hwmod,
- .clk = "ocp_abe_iclk",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dsp -> l4_abe */
-static struct omap_hwmod_ocp_if omap44xx_dsp__l4_abe = {
- .master = &omap44xx_dsp_hwmod,
- .slave = &omap44xx_l4_abe_hwmod,
- .clk = "ocp_abe_iclk",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l3_main_1 -> l4_abe */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_abe = {
- .master = &omap44xx_l3_main_1_hwmod,
- .slave = &omap44xx_l4_abe_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mpu -> l4_abe */
-static struct omap_hwmod_ocp_if omap44xx_mpu__l4_abe = {
- .master = &omap44xx_mpu_hwmod,
- .slave = &omap44xx_l4_abe_hwmod,
- .clk = "ocp_abe_iclk",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_abe slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_l4_abe_slaves[] = {
- &omap44xx_aess__l4_abe,
- &omap44xx_dsp__l4_abe,
- &omap44xx_l3_main_1__l4_abe,
- &omap44xx_mpu__l4_abe,
-};
-
static struct omap_hwmod omap44xx_l4_abe_hwmod = {
.name = "l4_abe",
.class = &omap44xx_l4_hwmod_class,
@@ -555,24 +206,9 @@ static struct omap_hwmod omap44xx_l4_abe_hwmod = {
.clkctrl_offs = OMAP4_CM1_ABE_L4ABE_CLKCTRL_OFFSET,
},
},
- .slaves = omap44xx_l4_abe_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_l4_abe_slaves),
};
/* l4_cfg */
-/* l3_main_1 -> l4_cfg */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_cfg = {
- .master = &omap44xx_l3_main_1_hwmod,
- .slave = &omap44xx_l4_cfg_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_cfg slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_l4_cfg_slaves[] = {
- &omap44xx_l3_main_1__l4_cfg,
-};
-
static struct omap_hwmod omap44xx_l4_cfg_hwmod = {
.name = "l4_cfg",
.class = &omap44xx_l4_hwmod_class,
@@ -583,24 +219,9 @@ static struct omap_hwmod omap44xx_l4_cfg_hwmod = {
.context_offs = OMAP4_RM_L4CFG_L4_CFG_CONTEXT_OFFSET,
},
},
- .slaves = omap44xx_l4_cfg_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_l4_cfg_slaves),
};
/* l4_per */
-/* l3_main_2 -> l4_per */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l4_per = {
- .master = &omap44xx_l3_main_2_hwmod,
- .slave = &omap44xx_l4_per_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_l4_per_slaves[] = {
- &omap44xx_l3_main_2__l4_per,
-};
-
static struct omap_hwmod omap44xx_l4_per_hwmod = {
.name = "l4_per",
.class = &omap44xx_l4_hwmod_class,
@@ -611,24 +232,9 @@ static struct omap_hwmod omap44xx_l4_per_hwmod = {
.context_offs = OMAP4_RM_L4PER_L4_PER_CONTEXT_OFFSET,
},
},
- .slaves = omap44xx_l4_per_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_l4_per_slaves),
};
/* l4_wkup */
-/* l4_cfg -> l4_wkup */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l4_wkup = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_l4_wkup_hwmod,
- .clk = "l4_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_wkup slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_l4_wkup_slaves[] = {
- &omap44xx_l4_cfg__l4_wkup,
-};
-
static struct omap_hwmod omap44xx_l4_wkup_hwmod = {
.name = "l4_wkup",
.class = &omap44xx_l4_hwmod_class,
@@ -639,8 +245,6 @@ static struct omap_hwmod omap44xx_l4_wkup_hwmod = {
.context_offs = OMAP4_RM_WKUP_L4WKUP_CONTEXT_OFFSET,
},
},
- .slaves = omap44xx_l4_wkup_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_l4_wkup_slaves),
};
/*
@@ -652,25 +256,32 @@ static struct omap_hwmod_class omap44xx_mpu_bus_hwmod_class = {
};
/* mpu_private */
-/* mpu -> mpu_private */
-static struct omap_hwmod_ocp_if omap44xx_mpu__mpu_private = {
- .master = &omap44xx_mpu_hwmod,
- .slave = &omap44xx_mpu_private_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mpu_private slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mpu_private_slaves[] = {
- &omap44xx_mpu__mpu_private,
-};
-
static struct omap_hwmod omap44xx_mpu_private_hwmod = {
.name = "mpu_private",
.class = &omap44xx_mpu_bus_hwmod_class,
.clkdm_name = "mpuss_clkdm",
- .slaves = omap44xx_mpu_private_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mpu_private_slaves),
+};
+
+/*
+ * 'ocp_wp_noc' class
+ * instance(s): ocp_wp_noc
+ */
+static struct omap_hwmod_class omap44xx_ocp_wp_noc_hwmod_class = {
+ .name = "ocp_wp_noc",
+};
+
+/* ocp_wp_noc */
+static struct omap_hwmod omap44xx_ocp_wp_noc_hwmod = {
+ .name = "ocp_wp_noc",
+ .class = &omap44xx_ocp_wp_noc_hwmod_class,
+ .clkdm_name = "l3_instr_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3INSTR_OCP_WP1_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
+ },
+ },
};
/*
@@ -681,41 +292,7 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = {
* - They still need to be validated with the driver
* properly adapted to omap_hwmod / omap_device
*
- * c2c
- * c2c_target_fw
- * cm_core
- * cm_core_aon
- * ctrl_module_core
- * ctrl_module_pad_core
- * ctrl_module_pad_wkup
- * ctrl_module_wkup
- * debugss
- * efuse_ctrl_cust
- * efuse_ctrl_std
- * elm
- * emif1
- * emif2
- * fdif
- * gpmc
- * gpu
- * hdq1w
- * mcasp
- * mpu_c0
- * mpu_c1
- * ocmc_ram
- * ocp2scp_usb_phy
- * ocp_wp_noc
- * prcm_mpu
- * prm
- * scrm
- * sl2if
- * slimbus1
- * slimbus2
- * usb_host_fs
- * usb_host_hs
- * usb_phy_cm
- * usb_tll_hs
- * usim
+ * usim
*/
/*
@@ -756,53 +333,6 @@ static struct omap_hwmod_dma_info omap44xx_aess_sdma_reqs[] = {
{ .dma_req = -1 }
};
-/* aess master ports */
-static struct omap_hwmod_ocp_if *omap44xx_aess_masters[] = {
- &omap44xx_aess__l4_abe,
-};
-
-static struct omap_hwmod_addr_space omap44xx_aess_addrs[] = {
- {
- .pa_start = 0x401f1000,
- .pa_end = 0x401f13ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> aess */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__aess = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_aess_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_aess_addrs,
- .user = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_addr_space omap44xx_aess_dma_addrs[] = {
- {
- .pa_start = 0x490f1000,
- .pa_end = 0x490f13ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> aess (dma) */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__aess_dma = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_aess_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_aess_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-/* aess slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_aess_slaves[] = {
- &omap44xx_l4_abe__aess,
- &omap44xx_l4_abe__aess_dma,
-};
-
static struct omap_hwmod omap44xx_aess_hwmod = {
.name = "aess",
.class = &omap44xx_aess_hwmod_class,
@@ -817,37 +347,41 @@ static struct omap_hwmod omap44xx_aess_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_aess_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_aess_slaves),
- .masters = omap44xx_aess_masters,
- .masters_cnt = ARRAY_SIZE(omap44xx_aess_masters),
};
/*
- * 'bandgap' class
- * bangap reference for ldo regulators
+ * 'c2c' class
+ * chip 2 chip interface used to plug the ape soc (omap) with an external modem
+ * soc
*/
-static struct omap_hwmod_class omap44xx_bandgap_hwmod_class = {
- .name = "bandgap",
+static struct omap_hwmod_class omap44xx_c2c_hwmod_class = {
+ .name = "c2c",
};
-/* bandgap */
-static struct omap_hwmod_opt_clk bandgap_opt_clks[] = {
- { .role = "fclk", .clk = "bandgap_fclk" },
+/* c2c */
+static struct omap_hwmod_irq_info omap44xx_c2c_irqs[] = {
+ { .irq = 88 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
};
-static struct omap_hwmod omap44xx_bandgap_hwmod = {
- .name = "bandgap",
- .class = &omap44xx_bandgap_hwmod_class,
- .clkdm_name = "l4_wkup_clkdm",
+static struct omap_hwmod_dma_info omap44xx_c2c_sdma_reqs[] = {
+ { .dma_req = 68 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
+};
+
+static struct omap_hwmod omap44xx_c2c_hwmod = {
+ .name = "c2c",
+ .class = &omap44xx_c2c_hwmod_class,
+ .clkdm_name = "d2d_clkdm",
+ .mpu_irqs = omap44xx_c2c_irqs,
+ .sdma_reqs = omap44xx_c2c_sdma_reqs,
.prcm = {
.omap4 = {
- .clkctrl_offs = OMAP4_CM_WKUP_BANDGAP_CLKCTRL_OFFSET,
+ .clkctrl_offs = OMAP4_CM_D2D_SAD2D_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_D2D_SAD2D_CONTEXT_OFFSET,
},
},
- .opt_clks = bandgap_opt_clks,
- .opt_clks_cnt = ARRAY_SIZE(bandgap_opt_clks),
};
/*
@@ -870,30 +404,6 @@ static struct omap_hwmod_class omap44xx_counter_hwmod_class = {
};
/* counter_32k */
-static struct omap_hwmod omap44xx_counter_32k_hwmod;
-static struct omap_hwmod_addr_space omap44xx_counter_32k_addrs[] = {
- {
- .pa_start = 0x4a304000,
- .pa_end = 0x4a30401f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_wkup -> counter_32k */
-static struct omap_hwmod_ocp_if omap44xx_l4_wkup__counter_32k = {
- .master = &omap44xx_l4_wkup_hwmod,
- .slave = &omap44xx_counter_32k_hwmod,
- .clk = "l4_wkup_clk_mux_ck",
- .addr = omap44xx_counter_32k_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* counter_32k slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_counter_32k_slaves[] = {
- &omap44xx_l4_wkup__counter_32k,
-};
-
static struct omap_hwmod omap44xx_counter_32k_hwmod = {
.name = "counter_32k",
.class = &omap44xx_counter_hwmod_class,
@@ -906,8 +416,83 @@ static struct omap_hwmod omap44xx_counter_32k_hwmod = {
.context_offs = OMAP4_RM_WKUP_SYNCTIMER_CONTEXT_OFFSET,
},
},
- .slaves = omap44xx_counter_32k_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_counter_32k_slaves),
+};
+
+/*
+ * 'ctrl_module' class
+ * attila core control module + core pad control module + wkup pad control
+ * module + attila wkup control module
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_ctrl_module_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .sysc_flags = SYSC_HAS_SIDLEMODE,
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ SIDLE_SMART_WKUP),
+ .sysc_fields = &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_ctrl_module_hwmod_class = {
+ .name = "ctrl_module",
+ .sysc = &omap44xx_ctrl_module_sysc,
+};
+
+/* ctrl_module_core */
+static struct omap_hwmod_irq_info omap44xx_ctrl_module_core_irqs[] = {
+ { .irq = 8 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod omap44xx_ctrl_module_core_hwmod = {
+ .name = "ctrl_module_core",
+ .class = &omap44xx_ctrl_module_hwmod_class,
+ .clkdm_name = "l4_cfg_clkdm",
+ .mpu_irqs = omap44xx_ctrl_module_core_irqs,
+};
+
+/* ctrl_module_pad_core */
+static struct omap_hwmod omap44xx_ctrl_module_pad_core_hwmod = {
+ .name = "ctrl_module_pad_core",
+ .class = &omap44xx_ctrl_module_hwmod_class,
+ .clkdm_name = "l4_cfg_clkdm",
+};
+
+/* ctrl_module_wkup */
+static struct omap_hwmod omap44xx_ctrl_module_wkup_hwmod = {
+ .name = "ctrl_module_wkup",
+ .class = &omap44xx_ctrl_module_hwmod_class,
+ .clkdm_name = "l4_wkup_clkdm",
+};
+
+/* ctrl_module_pad_wkup */
+static struct omap_hwmod omap44xx_ctrl_module_pad_wkup_hwmod = {
+ .name = "ctrl_module_pad_wkup",
+ .class = &omap44xx_ctrl_module_hwmod_class,
+ .clkdm_name = "l4_wkup_clkdm",
+};
+
+/*
+ * 'debugss' class
+ * debug and emulation sub system
+ */
+
+static struct omap_hwmod_class omap44xx_debugss_hwmod_class = {
+ .name = "debugss",
+};
+
+/* debugss */
+static struct omap_hwmod omap44xx_debugss_hwmod = {
+ .name = "debugss",
+ .class = &omap44xx_debugss_hwmod_class,
+ .clkdm_name = "emu_sys_clkdm",
+ .main_clk = "trace_clk_div_ck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_EMU_DEBUGSS_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_EMU_DEBUGSS_CONTEXT_OFFSET,
+ },
+ },
};
/*
@@ -950,34 +535,6 @@ static struct omap_hwmod_irq_info omap44xx_dma_system_irqs[] = {
{ .irq = -1 }
};
-/* dma_system master ports */
-static struct omap_hwmod_ocp_if *omap44xx_dma_system_masters[] = {
- &omap44xx_dma_system__l3_main_2,
-};
-
-static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = {
- {
- .pa_start = 0x4a056000,
- .pa_end = 0x4a056fff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_cfg -> dma_system */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dma_system = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_dma_system_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_dma_system_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dma_system slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_dma_system_slaves[] = {
- &omap44xx_l4_cfg__dma_system,
-};
-
static struct omap_hwmod omap44xx_dma_system_hwmod = {
.name = "dma_system",
.class = &omap44xx_dma_hwmod_class,
@@ -991,10 +548,6 @@ static struct omap_hwmod omap44xx_dma_system_hwmod = {
},
},
.dev_attr = &dma_dev_attr,
- .slaves = omap44xx_dma_system_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_dma_system_slaves),
- .masters = omap44xx_dma_system_masters,
- .masters_cnt = ARRAY_SIZE(omap44xx_dma_system_masters),
};
/*
@@ -1018,7 +571,6 @@ static struct omap_hwmod_class omap44xx_dmic_hwmod_class = {
};
/* dmic */
-static struct omap_hwmod omap44xx_dmic_hwmod;
static struct omap_hwmod_irq_info omap44xx_dmic_irqs[] = {
{ .irq = 114 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -1029,50 +581,6 @@ static struct omap_hwmod_dma_info omap44xx_dmic_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x4012e000,
- .pa_end = 0x4012e07f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> dmic */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_dmic_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_dmic_addrs,
- .user = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_addr_space omap44xx_dmic_dma_addrs[] = {
- {
- .name = "dma",
- .pa_start = 0x4902e000,
- .pa_end = 0x4902e07f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> dmic (dma) */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic_dma = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_dmic_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_dmic_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-/* dmic slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_dmic_slaves[] = {
- &omap44xx_l4_abe__dmic,
- &omap44xx_l4_abe__dmic_dma,
-};
-
static struct omap_hwmod omap44xx_dmic_hwmod = {
.name = "dmic",
.class = &omap44xx_dmic_hwmod_class,
@@ -1087,8 +595,6 @@ static struct omap_hwmod omap44xx_dmic_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_dmic_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_dmic_slaves),
};
/*
@@ -1107,53 +613,8 @@ static struct omap_hwmod_irq_info omap44xx_dsp_irqs[] = {
};
static struct omap_hwmod_rst_info omap44xx_dsp_resets[] = {
- { .name = "mmu_cache", .rst_shift = 1 },
-};
-
-static struct omap_hwmod_rst_info omap44xx_dsp_c0_resets[] = {
{ .name = "dsp", .rst_shift = 0 },
-};
-
-/* dsp -> iva */
-static struct omap_hwmod_ocp_if omap44xx_dsp__iva = {
- .master = &omap44xx_dsp_hwmod,
- .slave = &omap44xx_iva_hwmod,
- .clk = "dpll_iva_m5x2_ck",
-};
-
-/* dsp master ports */
-static struct omap_hwmod_ocp_if *omap44xx_dsp_masters[] = {
- &omap44xx_dsp__l3_main_1,
- &omap44xx_dsp__l4_abe,
- &omap44xx_dsp__iva,
-};
-
-/* l4_cfg -> dsp */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dsp = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_dsp_hwmod,
- .clk = "l4_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dsp slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_dsp_slaves[] = {
- &omap44xx_l4_cfg__dsp,
-};
-
-/* Pseudo hwmod for reset control purpose only */
-static struct omap_hwmod omap44xx_dsp_c0_hwmod = {
- .name = "dsp_c0",
- .class = &omap44xx_dsp_hwmod_class,
- .clkdm_name = "tesla_clkdm",
- .flags = HWMOD_INIT_NO_RESET,
- .rst_lines = omap44xx_dsp_c0_resets,
- .rst_lines_cnt = ARRAY_SIZE(omap44xx_dsp_c0_resets),
- .prcm = {
- .omap4 = {
- .rstctrl_offs = OMAP4_RM_TESLA_RSTCTRL_OFFSET,
- },
- },
+ { .name = "mmu_cache", .rst_shift = 1 },
};
static struct omap_hwmod omap44xx_dsp_hwmod = {
@@ -1172,10 +633,6 @@ static struct omap_hwmod omap44xx_dsp_hwmod = {
.modulemode = MODULEMODE_HWCTRL,
},
},
- .slaves = omap44xx_dsp_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_dsp_slaves),
- .masters = omap44xx_dsp_masters,
- .masters_cnt = ARRAY_SIZE(omap44xx_dsp_masters),
};
/*
@@ -1196,53 +653,6 @@ static struct omap_hwmod_class omap44xx_dss_hwmod_class = {
};
/* dss */
-/* dss master ports */
-static struct omap_hwmod_ocp_if *omap44xx_dss_masters[] = {
- &omap44xx_dss__l3_main_1,
-};
-
-static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = {
- {
- .pa_start = 0x58000000,
- .pa_end = 0x5800007f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l3_main_2 -> dss */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
- .master = &omap44xx_l3_main_2_hwmod,
- .slave = &omap44xx_dss_hwmod,
- .clk = "dss_fck",
- .addr = omap44xx_dss_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_addr_space omap44xx_dss_addrs[] = {
- {
- .pa_start = 0x48040000,
- .pa_end = 0x4804007f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> dss */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__dss = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_dss_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_dss_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* dss slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_dss_slaves[] = {
- &omap44xx_l3_main_2__dss,
- &omap44xx_l4_per__dss,
-};
-
static struct omap_hwmod_opt_clk dss_opt_clks[] = {
{ .role = "sys_clk", .clk = "dss_sys_clk" },
{ .role = "tv_clk", .clk = "dss_tv_clk" },
@@ -1263,10 +673,6 @@ static struct omap_hwmod omap44xx_dss_hwmod = {
},
.opt_clks = dss_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
- .slaves = omap44xx_dss_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_dss_slaves),
- .masters = omap44xx_dss_masters,
- .masters_cnt = ARRAY_SIZE(omap44xx_dss_masters),
};
/*
@@ -1293,7 +699,6 @@ static struct omap_hwmod_class omap44xx_dispc_hwmod_class = {
};
/* dss_dispc */
-static struct omap_hwmod omap44xx_dss_dispc_hwmod;
static struct omap_hwmod_irq_info omap44xx_dss_dispc_irqs[] = {
{ .irq = 25 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -1304,53 +709,11 @@ static struct omap_hwmod_dma_info omap44xx_dss_dispc_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
- {
- .pa_start = 0x58001000,
- .pa_end = 0x58001fff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l3_main_2 -> dss_dispc */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = {
- .master = &omap44xx_l3_main_2_hwmod,
- .slave = &omap44xx_dss_dispc_hwmod,
- .clk = "dss_fck",
- .addr = omap44xx_dss_dispc_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_addr_space omap44xx_dss_dispc_addrs[] = {
- {
- .pa_start = 0x48041000,
- .pa_end = 0x48041fff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
static struct omap_dss_dispc_dev_attr omap44xx_dss_dispc_dev_attr = {
.manager_count = 3,
.has_framedonetv_irq = 1
};
-/* l4_per -> dss_dispc */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dispc = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_dss_dispc_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_dss_dispc_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* dss_dispc slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = {
- &omap44xx_l3_main_2__dss_dispc,
- &omap44xx_l4_per__dss_dispc,
-};
-
static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
.name = "dss_dispc",
.class = &omap44xx_dispc_hwmod_class,
@@ -1364,8 +727,6 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
.context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
},
},
- .slaves = omap44xx_dss_dispc_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_dss_dispc_slaves),
.dev_attr = &omap44xx_dss_dispc_dev_attr
};
@@ -1391,7 +752,6 @@ static struct omap_hwmod_class omap44xx_dsi_hwmod_class = {
};
/* dss_dsi1 */
-static struct omap_hwmod omap44xx_dss_dsi1_hwmod;
static struct omap_hwmod_irq_info omap44xx_dss_dsi1_irqs[] = {
{ .irq = 53 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -1402,48 +762,6 @@ static struct omap_hwmod_dma_info omap44xx_dss_dsi1_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
- {
- .pa_start = 0x58004000,
- .pa_end = 0x580041ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l3_main_2 -> dss_dsi1 */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = {
- .master = &omap44xx_l3_main_2_hwmod,
- .slave = &omap44xx_dss_dsi1_hwmod,
- .clk = "dss_fck",
- .addr = omap44xx_dss_dsi1_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_addr_space omap44xx_dss_dsi1_addrs[] = {
- {
- .pa_start = 0x48044000,
- .pa_end = 0x480441ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> dss_dsi1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi1 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_dss_dsi1_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_dss_dsi1_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* dss_dsi1 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_dss_dsi1_slaves[] = {
- &omap44xx_l3_main_2__dss_dsi1,
- &omap44xx_l4_per__dss_dsi1,
-};
-
static struct omap_hwmod_opt_clk dss_dsi1_opt_clks[] = {
{ .role = "sys_clk", .clk = "dss_sys_clk" },
};
@@ -1463,12 +781,9 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
},
.opt_clks = dss_dsi1_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(dss_dsi1_opt_clks),
- .slaves = omap44xx_dss_dsi1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_slaves),
};
/* dss_dsi2 */
-static struct omap_hwmod omap44xx_dss_dsi2_hwmod;
static struct omap_hwmod_irq_info omap44xx_dss_dsi2_irqs[] = {
{ .irq = 84 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -1479,48 +794,6 @@ static struct omap_hwmod_dma_info omap44xx_dss_dsi2_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
- {
- .pa_start = 0x58005000,
- .pa_end = 0x580051ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l3_main_2 -> dss_dsi2 */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = {
- .master = &omap44xx_l3_main_2_hwmod,
- .slave = &omap44xx_dss_dsi2_hwmod,
- .clk = "dss_fck",
- .addr = omap44xx_dss_dsi2_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_addr_space omap44xx_dss_dsi2_addrs[] = {
- {
- .pa_start = 0x48045000,
- .pa_end = 0x480451ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> dss_dsi2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi2 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_dss_dsi2_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_dss_dsi2_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* dss_dsi2 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_dss_dsi2_slaves[] = {
- &omap44xx_l3_main_2__dss_dsi2,
- &omap44xx_l4_per__dss_dsi2,
-};
-
static struct omap_hwmod_opt_clk dss_dsi2_opt_clks[] = {
{ .role = "sys_clk", .clk = "dss_sys_clk" },
};
@@ -1540,8 +813,6 @@ static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
},
.opt_clks = dss_dsi2_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(dss_dsi2_opt_clks),
- .slaves = omap44xx_dss_dsi2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_slaves),
};
/*
@@ -1565,7 +836,6 @@ static struct omap_hwmod_class omap44xx_hdmi_hwmod_class = {
};
/* dss_hdmi */
-static struct omap_hwmod omap44xx_dss_hdmi_hwmod;
static struct omap_hwmod_irq_info omap44xx_dss_hdmi_irqs[] = {
{ .irq = 101 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -1576,48 +846,6 @@ static struct omap_hwmod_dma_info omap44xx_dss_hdmi_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
- {
- .pa_start = 0x58006000,
- .pa_end = 0x58006fff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l3_main_2 -> dss_hdmi */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = {
- .master = &omap44xx_l3_main_2_hwmod,
- .slave = &omap44xx_dss_hdmi_hwmod,
- .clk = "dss_fck",
- .addr = omap44xx_dss_hdmi_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_addr_space omap44xx_dss_hdmi_addrs[] = {
- {
- .pa_start = 0x48046000,
- .pa_end = 0x48046fff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> dss_hdmi */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_hdmi = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_dss_hdmi_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_dss_hdmi_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* dss_hdmi slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_dss_hdmi_slaves[] = {
- &omap44xx_l3_main_2__dss_hdmi,
- &omap44xx_l4_per__dss_hdmi,
-};
-
static struct omap_hwmod_opt_clk dss_hdmi_opt_clks[] = {
{ .role = "sys_clk", .clk = "dss_sys_clk" },
};
@@ -1637,8 +865,6 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
},
.opt_clks = dss_hdmi_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(dss_hdmi_opt_clks),
- .slaves = omap44xx_dss_hdmi_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_slaves),
};
/*
@@ -1662,54 +888,11 @@ static struct omap_hwmod_class omap44xx_rfbi_hwmod_class = {
};
/* dss_rfbi */
-static struct omap_hwmod omap44xx_dss_rfbi_hwmod;
static struct omap_hwmod_dma_info omap44xx_dss_rfbi_sdma_reqs[] = {
{ .dma_req = 13 + OMAP44XX_DMA_REQ_START },
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
- {
- .pa_start = 0x58002000,
- .pa_end = 0x580020ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l3_main_2 -> dss_rfbi */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = {
- .master = &omap44xx_l3_main_2_hwmod,
- .slave = &omap44xx_dss_rfbi_hwmod,
- .clk = "dss_fck",
- .addr = omap44xx_dss_rfbi_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_addr_space omap44xx_dss_rfbi_addrs[] = {
- {
- .pa_start = 0x48042000,
- .pa_end = 0x480420ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> dss_rfbi */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_rfbi = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_dss_rfbi_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_dss_rfbi_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* dss_rfbi slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_dss_rfbi_slaves[] = {
- &omap44xx_l3_main_2__dss_rfbi,
- &omap44xx_l4_per__dss_rfbi,
-};
-
static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
{ .role = "ick", .clk = "dss_fck" },
};
@@ -1728,8 +911,6 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
},
.opt_clks = dss_rfbi_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(dss_rfbi_opt_clks),
- .slaves = omap44xx_dss_rfbi_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_dss_rfbi_slaves),
};
/*
@@ -1742,62 +923,165 @@ static struct omap_hwmod_class omap44xx_venc_hwmod_class = {
};
/* dss_venc */
-static struct omap_hwmod omap44xx_dss_venc_hwmod;
-static struct omap_hwmod_addr_space omap44xx_dss_venc_dma_addrs[] = {
- {
- .pa_start = 0x58003000,
- .pa_end = 0x580030ff,
- .flags = ADDR_TYPE_RT
+static struct omap_hwmod omap44xx_dss_venc_hwmod = {
+ .name = "dss_venc",
+ .class = &omap44xx_venc_hwmod_class,
+ .clkdm_name = "l3_dss_clkdm",
+ .main_clk = "dss_tv_clk",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
+ },
},
- { }
};
-/* l3_main_2 -> dss_venc */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = {
- .master = &omap44xx_l3_main_2_hwmod,
- .slave = &omap44xx_dss_venc_hwmod,
- .clk = "dss_fck",
- .addr = omap44xx_dss_venc_dma_addrs,
- .user = OCP_USER_SDMA,
+/*
+ * 'elm' class
+ * bch error location module
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_elm_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+ SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+ SYSS_HAS_RESET_STATUS),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
};
-static struct omap_hwmod_addr_space omap44xx_dss_venc_addrs[] = {
- {
- .pa_start = 0x48043000,
- .pa_end = 0x480430ff,
- .flags = ADDR_TYPE_RT
+static struct omap_hwmod_class omap44xx_elm_hwmod_class = {
+ .name = "elm",
+ .sysc = &omap44xx_elm_sysc,
+};
+
+/* elm */
+static struct omap_hwmod_irq_info omap44xx_elm_irqs[] = {
+ { .irq = 4 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod omap44xx_elm_hwmod = {
+ .name = "elm",
+ .class = &omap44xx_elm_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
+ .mpu_irqs = omap44xx_elm_irqs,
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L4PER_ELM_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_ELM_CONTEXT_OFFSET,
+ },
},
- { }
};
-/* l4_per -> dss_venc */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_venc = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_dss_venc_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_dss_venc_addrs,
- .user = OCP_USER_MPU,
+/*
+ * 'emif' class
+ * external memory interface no1
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_emif_sysc = {
+ .rev_offs = 0x0000,
};
-/* dss_venc slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_dss_venc_slaves[] = {
- &omap44xx_l3_main_2__dss_venc,
- &omap44xx_l4_per__dss_venc,
+static struct omap_hwmod_class omap44xx_emif_hwmod_class = {
+ .name = "emif",
+ .sysc = &omap44xx_emif_sysc,
};
-static struct omap_hwmod omap44xx_dss_venc_hwmod = {
- .name = "dss_venc",
- .class = &omap44xx_venc_hwmod_class,
- .clkdm_name = "l3_dss_clkdm",
- .main_clk = "dss_tv_clk",
+/* emif1 */
+static struct omap_hwmod_irq_info omap44xx_emif1_irqs[] = {
+ { .irq = 110 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod omap44xx_emif1_hwmod = {
+ .name = "emif1",
+ .class = &omap44xx_emif_hwmod_class,
+ .clkdm_name = "l3_emif_clkdm",
+ .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+ .mpu_irqs = omap44xx_emif1_irqs,
+ .main_clk = "ddrphy_ck",
.prcm = {
.omap4 = {
- .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
- .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
+ .clkctrl_offs = OMAP4_CM_MEMIF_EMIF_1_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_MEMIF_EMIF_1_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
+ },
+ },
+};
+
+/* emif2 */
+static struct omap_hwmod_irq_info omap44xx_emif2_irqs[] = {
+ { .irq = 111 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod omap44xx_emif2_hwmod = {
+ .name = "emif2",
+ .class = &omap44xx_emif_hwmod_class,
+ .clkdm_name = "l3_emif_clkdm",
+ .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+ .mpu_irqs = omap44xx_emif2_irqs,
+ .main_clk = "ddrphy_ck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_MEMIF_EMIF_2_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_MEMIF_EMIF_2_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
+ },
+ },
+};
+
+/*
+ * 'fdif' class
+ * face detection hw accelerator module
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_fdif_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ /*
+ * FDIF needs 100 OCP clk cycles delay after a softreset before
+ * accessing sysconfig again.
+ * The lowest frequency at the moment for L3 bus is 100 MHz, so
+ * 1usec delay is needed. Add an x2 margin to be safe (2 usecs).
+ *
+ * TODO: Indicate errata when available.
+ */
+ .srst_udelay = 2,
+ .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS |
+ SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_fdif_hwmod_class = {
+ .name = "fdif",
+ .sysc = &omap44xx_fdif_sysc,
+};
+
+/* fdif */
+static struct omap_hwmod_irq_info omap44xx_fdif_irqs[] = {
+ { .irq = 69 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod omap44xx_fdif_hwmod = {
+ .name = "fdif",
+ .class = &omap44xx_fdif_hwmod_class,
+ .clkdm_name = "iss_clkdm",
+ .mpu_irqs = omap44xx_fdif_irqs,
+ .main_clk = "fdif_fck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_CAM_FDIF_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_CAM_FDIF_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_dss_venc_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_dss_venc_slaves),
};
/*
@@ -1830,35 +1114,11 @@ static struct omap_gpio_dev_attr gpio_dev_attr = {
};
/* gpio1 */
-static struct omap_hwmod omap44xx_gpio1_hwmod;
static struct omap_hwmod_irq_info omap44xx_gpio1_irqs[] = {
{ .irq = 29 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_gpio1_addrs[] = {
- {
- .pa_start = 0x4a310000,
- .pa_end = 0x4a3101ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_wkup -> gpio1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_wkup__gpio1 = {
- .master = &omap44xx_l4_wkup_hwmod,
- .slave = &omap44xx_gpio1_hwmod,
- .clk = "l4_wkup_clk_mux_ck",
- .addr = omap44xx_gpio1_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* gpio1 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_gpio1_slaves[] = {
- &omap44xx_l4_wkup__gpio1,
-};
-
static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio1_dbclk" },
};
@@ -1879,40 +1139,14 @@ static struct omap_hwmod omap44xx_gpio1_hwmod = {
.opt_clks = gpio1_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(gpio1_opt_clks),
.dev_attr = &gpio_dev_attr,
- .slaves = omap44xx_gpio1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_gpio1_slaves),
};
/* gpio2 */
-static struct omap_hwmod omap44xx_gpio2_hwmod;
static struct omap_hwmod_irq_info omap44xx_gpio2_irqs[] = {
{ .irq = 30 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_gpio2_addrs[] = {
- {
- .pa_start = 0x48055000,
- .pa_end = 0x480551ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> gpio2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio2 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_gpio2_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_gpio2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* gpio2 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_gpio2_slaves[] = {
- &omap44xx_l4_per__gpio2,
-};
-
static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio2_dbclk" },
};
@@ -1934,40 +1168,14 @@ static struct omap_hwmod omap44xx_gpio2_hwmod = {
.opt_clks = gpio2_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(gpio2_opt_clks),
.dev_attr = &gpio_dev_attr,
- .slaves = omap44xx_gpio2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_gpio2_slaves),
};
/* gpio3 */
-static struct omap_hwmod omap44xx_gpio3_hwmod;
static struct omap_hwmod_irq_info omap44xx_gpio3_irqs[] = {
{ .irq = 31 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_gpio3_addrs[] = {
- {
- .pa_start = 0x48057000,
- .pa_end = 0x480571ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> gpio3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio3 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_gpio3_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_gpio3_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* gpio3 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_gpio3_slaves[] = {
- &omap44xx_l4_per__gpio3,
-};
-
static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio3_dbclk" },
};
@@ -1989,40 +1197,14 @@ static struct omap_hwmod omap44xx_gpio3_hwmod = {
.opt_clks = gpio3_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(gpio3_opt_clks),
.dev_attr = &gpio_dev_attr,
- .slaves = omap44xx_gpio3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_gpio3_slaves),
};
/* gpio4 */
-static struct omap_hwmod omap44xx_gpio4_hwmod;
static struct omap_hwmod_irq_info omap44xx_gpio4_irqs[] = {
{ .irq = 32 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_gpio4_addrs[] = {
- {
- .pa_start = 0x48059000,
- .pa_end = 0x480591ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> gpio4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio4 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_gpio4_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_gpio4_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* gpio4 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_gpio4_slaves[] = {
- &omap44xx_l4_per__gpio4,
-};
-
static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio4_dbclk" },
};
@@ -2044,40 +1226,14 @@ static struct omap_hwmod omap44xx_gpio4_hwmod = {
.opt_clks = gpio4_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(gpio4_opt_clks),
.dev_attr = &gpio_dev_attr,
- .slaves = omap44xx_gpio4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_gpio4_slaves),
};
/* gpio5 */
-static struct omap_hwmod omap44xx_gpio5_hwmod;
static struct omap_hwmod_irq_info omap44xx_gpio5_irqs[] = {
{ .irq = 33 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_gpio5_addrs[] = {
- {
- .pa_start = 0x4805b000,
- .pa_end = 0x4805b1ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> gpio5 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio5 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_gpio5_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_gpio5_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* gpio5 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_gpio5_slaves[] = {
- &omap44xx_l4_per__gpio5,
-};
-
static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio5_dbclk" },
};
@@ -2099,40 +1255,14 @@ static struct omap_hwmod omap44xx_gpio5_hwmod = {
.opt_clks = gpio5_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(gpio5_opt_clks),
.dev_attr = &gpio_dev_attr,
- .slaves = omap44xx_gpio5_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_gpio5_slaves),
};
/* gpio6 */
-static struct omap_hwmod omap44xx_gpio6_hwmod;
static struct omap_hwmod_irq_info omap44xx_gpio6_irqs[] = {
{ .irq = 34 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_gpio6_addrs[] = {
- {
- .pa_start = 0x4805d000,
- .pa_end = 0x4805d1ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> gpio6 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio6 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_gpio6_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_gpio6_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* gpio6 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_gpio6_slaves[] = {
- &omap44xx_l4_per__gpio6,
-};
-
static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
{ .role = "dbclk", .clk = "gpio6_dbclk" },
};
@@ -2154,8 +1284,135 @@ static struct omap_hwmod omap44xx_gpio6_hwmod = {
.opt_clks = gpio6_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(gpio6_opt_clks),
.dev_attr = &gpio_dev_attr,
- .slaves = omap44xx_gpio6_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_gpio6_slaves),
+};
+
+/*
+ * 'gpmc' class
+ * general purpose memory controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_gpmc_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_gpmc_hwmod_class = {
+ .name = "gpmc",
+ .sysc = &omap44xx_gpmc_sysc,
+};
+
+/* gpmc */
+static struct omap_hwmod_irq_info omap44xx_gpmc_irqs[] = {
+ { .irq = 20 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod_dma_info omap44xx_gpmc_sdma_reqs[] = {
+ { .dma_req = 3 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
+};
+
+static struct omap_hwmod omap44xx_gpmc_hwmod = {
+ .name = "gpmc",
+ .class = &omap44xx_gpmc_hwmod_class,
+ .clkdm_name = "l3_2_clkdm",
+ .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+ .mpu_irqs = omap44xx_gpmc_irqs,
+ .sdma_reqs = omap44xx_gpmc_sdma_reqs,
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L3_2_GPMC_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3_2_GPMC_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
+ },
+ },
+};
+
+/*
+ * 'gpu' class
+ * 2d/3d graphics accelerator
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_gpu_sysc = {
+ .rev_offs = 0x1fc00,
+ .sysc_offs = 0x1fc10,
+ .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+ MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
+ .sysc_fields = &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_gpu_hwmod_class = {
+ .name = "gpu",
+ .sysc = &omap44xx_gpu_sysc,
+};
+
+/* gpu */
+static struct omap_hwmod_irq_info omap44xx_gpu_irqs[] = {
+ { .irq = 21 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod omap44xx_gpu_hwmod = {
+ .name = "gpu",
+ .class = &omap44xx_gpu_hwmod_class,
+ .clkdm_name = "l3_gfx_clkdm",
+ .mpu_irqs = omap44xx_gpu_irqs,
+ .main_clk = "gpu_fck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_GFX_GFX_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_GFX_GFX_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+};
+
+/*
+ * 'hdq1w' class
+ * hdq / 1-wire serial interface controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_hdq1w_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0014,
+ .syss_offs = 0x0018,
+ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SOFTRESET |
+ SYSS_HAS_RESET_STATUS),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_hdq1w_hwmod_class = {
+ .name = "hdq1w",
+ .sysc = &omap44xx_hdq1w_sysc,
+};
+
+/* hdq1w */
+static struct omap_hwmod_irq_info omap44xx_hdq1w_irqs[] = {
+ { .irq = 58 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod omap44xx_hdq1w_hwmod = {
+ .name = "hdq1w",
+ .class = &omap44xx_hdq1w_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
+ .flags = HWMOD_INIT_NO_RESET, /* XXX temporary */
+ .mpu_irqs = omap44xx_hdq1w_irqs,
+ .main_clk = "hdq1w_fck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L4PER_HDQ1W_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_HDQ1W_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
};
/*
@@ -2190,34 +1447,6 @@ static struct omap_hwmod_irq_info omap44xx_hsi_irqs[] = {
{ .irq = -1 }
};
-/* hsi master ports */
-static struct omap_hwmod_ocp_if *omap44xx_hsi_masters[] = {
- &omap44xx_hsi__l3_main_2,
-};
-
-static struct omap_hwmod_addr_space omap44xx_hsi_addrs[] = {
- {
- .pa_start = 0x4a058000,
- .pa_end = 0x4a05bfff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_cfg -> hsi */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__hsi = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_hsi_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_hsi_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* hsi slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_hsi_slaves[] = {
- &omap44xx_l4_cfg__hsi,
-};
-
static struct omap_hwmod omap44xx_hsi_hwmod = {
.name = "hsi",
.class = &omap44xx_hsi_hwmod_class,
@@ -2231,10 +1460,6 @@ static struct omap_hwmod omap44xx_hsi_hwmod = {
.modulemode = MODULEMODE_HWCTRL,
},
},
- .slaves = omap44xx_hsi_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_hsi_slaves),
- .masters = omap44xx_hsi_masters,
- .masters_cnt = ARRAY_SIZE(omap44xx_hsi_masters),
};
/*
@@ -2262,11 +1487,11 @@ static struct omap_hwmod_class omap44xx_i2c_hwmod_class = {
};
static struct omap_i2c_dev_attr i2c_dev_attr = {
- .flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
+ .flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE |
+ OMAP_I2C_FLAG_RESET_REGS_POSTIDLE,
};
/* i2c1 */
-static struct omap_hwmod omap44xx_i2c1_hwmod;
static struct omap_hwmod_irq_info omap44xx_i2c1_irqs[] = {
{ .irq = 56 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -2278,29 +1503,6 @@ static struct omap_hwmod_dma_info omap44xx_i2c1_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_i2c1_addrs[] = {
- {
- .pa_start = 0x48070000,
- .pa_end = 0x480700ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> i2c1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c1 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_i2c1_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_i2c1_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* i2c1 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_i2c1_slaves[] = {
- &omap44xx_l4_per__i2c1,
-};
-
static struct omap_hwmod omap44xx_i2c1_hwmod = {
.name = "i2c1",
.class = &omap44xx_i2c_hwmod_class,
@@ -2316,13 +1518,10 @@ static struct omap_hwmod omap44xx_i2c1_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_i2c1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_i2c1_slaves),
.dev_attr = &i2c_dev_attr,
};
/* i2c2 */
-static struct omap_hwmod omap44xx_i2c2_hwmod;
static struct omap_hwmod_irq_info omap44xx_i2c2_irqs[] = {
{ .irq = 57 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -2334,29 +1533,6 @@ static struct omap_hwmod_dma_info omap44xx_i2c2_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_i2c2_addrs[] = {
- {
- .pa_start = 0x48072000,
- .pa_end = 0x480720ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> i2c2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c2 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_i2c2_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_i2c2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* i2c2 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_i2c2_slaves[] = {
- &omap44xx_l4_per__i2c2,
-};
-
static struct omap_hwmod omap44xx_i2c2_hwmod = {
.name = "i2c2",
.class = &omap44xx_i2c_hwmod_class,
@@ -2372,13 +1548,10 @@ static struct omap_hwmod omap44xx_i2c2_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_i2c2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_i2c2_slaves),
.dev_attr = &i2c_dev_attr,
};
/* i2c3 */
-static struct omap_hwmod omap44xx_i2c3_hwmod;
static struct omap_hwmod_irq_info omap44xx_i2c3_irqs[] = {
{ .irq = 61 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -2390,29 +1563,6 @@ static struct omap_hwmod_dma_info omap44xx_i2c3_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_i2c3_addrs[] = {
- {
- .pa_start = 0x48060000,
- .pa_end = 0x480600ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> i2c3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c3 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_i2c3_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_i2c3_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* i2c3 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_i2c3_slaves[] = {
- &omap44xx_l4_per__i2c3,
-};
-
static struct omap_hwmod omap44xx_i2c3_hwmod = {
.name = "i2c3",
.class = &omap44xx_i2c_hwmod_class,
@@ -2428,13 +1578,10 @@ static struct omap_hwmod omap44xx_i2c3_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_i2c3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_i2c3_slaves),
.dev_attr = &i2c_dev_attr,
};
/* i2c4 */
-static struct omap_hwmod omap44xx_i2c4_hwmod;
static struct omap_hwmod_irq_info omap44xx_i2c4_irqs[] = {
{ .irq = 62 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -2446,29 +1593,6 @@ static struct omap_hwmod_dma_info omap44xx_i2c4_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_i2c4_addrs[] = {
- {
- .pa_start = 0x48350000,
- .pa_end = 0x483500ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> i2c4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c4 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_i2c4_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_i2c4_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* i2c4 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_i2c4_slaves[] = {
- &omap44xx_l4_per__i2c4,
-};
-
static struct omap_hwmod omap44xx_i2c4_hwmod = {
.name = "i2c4",
.class = &omap44xx_i2c_hwmod_class,
@@ -2484,8 +1608,6 @@ static struct omap_hwmod omap44xx_i2c4_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_i2c4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_i2c4_slaves),
.dev_attr = &i2c_dev_attr,
};
@@ -2504,66 +1626,12 @@ static struct omap_hwmod_irq_info omap44xx_ipu_irqs[] = {
{ .irq = -1 }
};
-static struct omap_hwmod_rst_info omap44xx_ipu_c0_resets[] = {
+static struct omap_hwmod_rst_info omap44xx_ipu_resets[] = {
{ .name = "cpu0", .rst_shift = 0 },
-};
-
-static struct omap_hwmod_rst_info omap44xx_ipu_c1_resets[] = {
{ .name = "cpu1", .rst_shift = 1 },
-};
-
-static struct omap_hwmod_rst_info omap44xx_ipu_resets[] = {
{ .name = "mmu_cache", .rst_shift = 2 },
};
-/* ipu master ports */
-static struct omap_hwmod_ocp_if *omap44xx_ipu_masters[] = {
- &omap44xx_ipu__l3_main_2,
-};
-
-/* l3_main_2 -> ipu */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__ipu = {
- .master = &omap44xx_l3_main_2_hwmod,
- .slave = &omap44xx_ipu_hwmod,
- .clk = "l3_div_ck",
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* ipu slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_ipu_slaves[] = {
- &omap44xx_l3_main_2__ipu,
-};
-
-/* Pseudo hwmod for reset control purpose only */
-static struct omap_hwmod omap44xx_ipu_c0_hwmod = {
- .name = "ipu_c0",
- .class = &omap44xx_ipu_hwmod_class,
- .clkdm_name = "ducati_clkdm",
- .flags = HWMOD_INIT_NO_RESET,
- .rst_lines = omap44xx_ipu_c0_resets,
- .rst_lines_cnt = ARRAY_SIZE(omap44xx_ipu_c0_resets),
- .prcm = {
- .omap4 = {
- .rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
- },
- },
-};
-
-/* Pseudo hwmod for reset control purpose only */
-static struct omap_hwmod omap44xx_ipu_c1_hwmod = {
- .name = "ipu_c1",
- .class = &omap44xx_ipu_hwmod_class,
- .clkdm_name = "ducati_clkdm",
- .flags = HWMOD_INIT_NO_RESET,
- .rst_lines = omap44xx_ipu_c1_resets,
- .rst_lines_cnt = ARRAY_SIZE(omap44xx_ipu_c1_resets),
- .prcm = {
- .omap4 = {
- .rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
- },
- },
-};
-
static struct omap_hwmod omap44xx_ipu_hwmod = {
.name = "ipu",
.class = &omap44xx_ipu_hwmod_class,
@@ -2580,10 +1648,6 @@ static struct omap_hwmod omap44xx_ipu_hwmod = {
.modulemode = MODULEMODE_HWCTRL,
},
},
- .slaves = omap44xx_ipu_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_ipu_slaves),
- .masters = omap44xx_ipu_masters,
- .masters_cnt = ARRAY_SIZE(omap44xx_ipu_masters),
};
/*
@@ -2630,34 +1694,6 @@ static struct omap_hwmod_dma_info omap44xx_iss_sdma_reqs[] = {
{ .dma_req = -1 }
};
-/* iss master ports */
-static struct omap_hwmod_ocp_if *omap44xx_iss_masters[] = {
- &omap44xx_iss__l3_main_2,
-};
-
-static struct omap_hwmod_addr_space omap44xx_iss_addrs[] = {
- {
- .pa_start = 0x52000000,
- .pa_end = 0x520000ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l3_main_2 -> iss */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = {
- .master = &omap44xx_l3_main_2_hwmod,
- .slave = &omap44xx_iss_hwmod,
- .clk = "l3_div_ck",
- .addr = omap44xx_iss_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* iss slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_iss_slaves[] = {
- &omap44xx_l3_main_2__iss,
-};
-
static struct omap_hwmod_opt_clk iss_opt_clks[] = {
{ .role = "ctrlclk", .clk = "iss_ctrlclk" },
};
@@ -2678,10 +1714,6 @@ static struct omap_hwmod omap44xx_iss_hwmod = {
},
.opt_clks = iss_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(iss_opt_clks),
- .slaves = omap44xx_iss_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_iss_slaves),
- .masters = omap44xx_iss_masters,
- .masters_cnt = ARRAY_SIZE(omap44xx_iss_masters),
};
/*
@@ -2702,75 +1734,9 @@ static struct omap_hwmod_irq_info omap44xx_iva_irqs[] = {
};
static struct omap_hwmod_rst_info omap44xx_iva_resets[] = {
- { .name = "logic", .rst_shift = 2 },
-};
-
-static struct omap_hwmod_rst_info omap44xx_iva_seq0_resets[] = {
{ .name = "seq0", .rst_shift = 0 },
-};
-
-static struct omap_hwmod_rst_info omap44xx_iva_seq1_resets[] = {
{ .name = "seq1", .rst_shift = 1 },
-};
-
-/* iva master ports */
-static struct omap_hwmod_ocp_if *omap44xx_iva_masters[] = {
- &omap44xx_iva__l3_main_2,
- &omap44xx_iva__l3_instr,
-};
-
-static struct omap_hwmod_addr_space omap44xx_iva_addrs[] = {
- {
- .pa_start = 0x5a000000,
- .pa_end = 0x5a07ffff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l3_main_2 -> iva */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iva = {
- .master = &omap44xx_l3_main_2_hwmod,
- .slave = &omap44xx_iva_hwmod,
- .clk = "l3_div_ck",
- .addr = omap44xx_iva_addrs,
- .user = OCP_USER_MPU,
-};
-
-/* iva slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_iva_slaves[] = {
- &omap44xx_dsp__iva,
- &omap44xx_l3_main_2__iva,
-};
-
-/* Pseudo hwmod for reset control purpose only */
-static struct omap_hwmod omap44xx_iva_seq0_hwmod = {
- .name = "iva_seq0",
- .class = &omap44xx_iva_hwmod_class,
- .clkdm_name = "ivahd_clkdm",
- .flags = HWMOD_INIT_NO_RESET,
- .rst_lines = omap44xx_iva_seq0_resets,
- .rst_lines_cnt = ARRAY_SIZE(omap44xx_iva_seq0_resets),
- .prcm = {
- .omap4 = {
- .rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
- },
- },
-};
-
-/* Pseudo hwmod for reset control purpose only */
-static struct omap_hwmod omap44xx_iva_seq1_hwmod = {
- .name = "iva_seq1",
- .class = &omap44xx_iva_hwmod_class,
- .clkdm_name = "ivahd_clkdm",
- .flags = HWMOD_INIT_NO_RESET,
- .rst_lines = omap44xx_iva_seq1_resets,
- .rst_lines_cnt = ARRAY_SIZE(omap44xx_iva_seq1_resets),
- .prcm = {
- .omap4 = {
- .rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
- },
- },
+ { .name = "logic", .rst_shift = 2 },
};
static struct omap_hwmod omap44xx_iva_hwmod = {
@@ -2789,10 +1755,6 @@ static struct omap_hwmod omap44xx_iva_hwmod = {
.modulemode = MODULEMODE_HWCTRL,
},
},
- .slaves = omap44xx_iva_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_iva_slaves),
- .masters = omap44xx_iva_masters,
- .masters_cnt = ARRAY_SIZE(omap44xx_iva_masters),
};
/*
@@ -2818,35 +1780,11 @@ static struct omap_hwmod_class omap44xx_kbd_hwmod_class = {
};
/* kbd */
-static struct omap_hwmod omap44xx_kbd_hwmod;
static struct omap_hwmod_irq_info omap44xx_kbd_irqs[] = {
{ .irq = 120 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_kbd_addrs[] = {
- {
- .pa_start = 0x4a31c000,
- .pa_end = 0x4a31c07f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_wkup -> kbd */
-static struct omap_hwmod_ocp_if omap44xx_l4_wkup__kbd = {
- .master = &omap44xx_l4_wkup_hwmod,
- .slave = &omap44xx_kbd_hwmod,
- .clk = "l4_wkup_clk_mux_ck",
- .addr = omap44xx_kbd_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* kbd slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_kbd_slaves[] = {
- &omap44xx_l4_wkup__kbd,
-};
-
static struct omap_hwmod omap44xx_kbd_hwmod = {
.name = "kbd",
.class = &omap44xx_kbd_hwmod_class,
@@ -2860,8 +1798,6 @@ static struct omap_hwmod omap44xx_kbd_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_kbd_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_kbd_slaves),
};
/*
@@ -2885,35 +1821,11 @@ static struct omap_hwmod_class omap44xx_mailbox_hwmod_class = {
};
/* mailbox */
-static struct omap_hwmod omap44xx_mailbox_hwmod;
static struct omap_hwmod_irq_info omap44xx_mailbox_irqs[] = {
{ .irq = 26 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_mailbox_addrs[] = {
- {
- .pa_start = 0x4a0f4000,
- .pa_end = 0x4a0f41ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_cfg -> mailbox */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__mailbox = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_mailbox_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_mailbox_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mailbox slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mailbox_slaves[] = {
- &omap44xx_l4_cfg__mailbox,
-};
-
static struct omap_hwmod omap44xx_mailbox_hwmod = {
.name = "mailbox",
.class = &omap44xx_mailbox_hwmod_class,
@@ -2925,8 +1837,58 @@ static struct omap_hwmod omap44xx_mailbox_hwmod = {
.context_offs = OMAP4_RM_L4CFG_MAILBOX_CONTEXT_OFFSET,
},
},
- .slaves = omap44xx_mailbox_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mailbox_slaves),
+};
+
+/*
+ * 'mcasp' class
+ * multi-channel audio serial port controller
+ */
+
+/* The IP is not compliant to type1 / type2 scheme */
+static struct omap_hwmod_sysc_fields omap_hwmod_sysc_type_mcasp = {
+ .sidle_shift = 0,
+};
+
+static struct omap_hwmod_class_sysconfig omap44xx_mcasp_sysc = {
+ .sysc_offs = 0x0004,
+ .sysc_flags = SYSC_HAS_SIDLEMODE,
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ SIDLE_SMART_WKUP),
+ .sysc_fields = &omap_hwmod_sysc_type_mcasp,
+};
+
+static struct omap_hwmod_class omap44xx_mcasp_hwmod_class = {
+ .name = "mcasp",
+ .sysc = &omap44xx_mcasp_sysc,
+};
+
+/* mcasp */
+static struct omap_hwmod_irq_info omap44xx_mcasp_irqs[] = {
+ { .name = "arevt", .irq = 108 + OMAP44XX_IRQ_GIC_START },
+ { .name = "axevt", .irq = 109 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcasp_sdma_reqs[] = {
+ { .name = "axevt", .dma_req = 7 + OMAP44XX_DMA_REQ_START },
+ { .name = "arevt", .dma_req = 10 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
+};
+
+static struct omap_hwmod omap44xx_mcasp_hwmod = {
+ .name = "mcasp",
+ .class = &omap44xx_mcasp_hwmod_class,
+ .clkdm_name = "abe_clkdm",
+ .mpu_irqs = omap44xx_mcasp_irqs,
+ .sdma_reqs = omap44xx_mcasp_sdma_reqs,
+ .main_clk = "mcasp_fck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM1_ABE_MCASP_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_MCASP_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
};
/*
@@ -2949,9 +1911,8 @@ static struct omap_hwmod_class omap44xx_mcbsp_hwmod_class = {
};
/* mcbsp1 */
-static struct omap_hwmod omap44xx_mcbsp1_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcbsp1_irqs[] = {
- { .irq = 17 + OMAP44XX_IRQ_GIC_START },
+ { .name = "common", .irq = 17 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
@@ -2961,50 +1922,6 @@ static struct omap_hwmod_dma_info omap44xx_mcbsp1_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_mcbsp1_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x40122000,
- .pa_end = 0x401220ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> mcbsp1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp1 = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_mcbsp1_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_mcbsp1_addrs,
- .user = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_addr_space omap44xx_mcbsp1_dma_addrs[] = {
- {
- .name = "dma",
- .pa_start = 0x49022000,
- .pa_end = 0x490220ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> mcbsp1 (dma) */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp1_dma = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_mcbsp1_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_mcbsp1_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-/* mcbsp1 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mcbsp1_slaves[] = {
- &omap44xx_l4_abe__mcbsp1,
- &omap44xx_l4_abe__mcbsp1_dma,
-};
-
static struct omap_hwmod_opt_clk mcbsp1_opt_clks[] = {
{ .role = "pad_fck", .clk = "pad_clks_ck" },
{ .role = "prcm_clk", .clk = "mcbsp1_sync_mux_ck" },
@@ -3024,16 +1941,13 @@ static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_mcbsp1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp1_slaves),
.opt_clks = mcbsp1_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(mcbsp1_opt_clks),
};
/* mcbsp2 */
-static struct omap_hwmod omap44xx_mcbsp2_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcbsp2_irqs[] = {
- { .irq = 22 + OMAP44XX_IRQ_GIC_START },
+ { .name = "common", .irq = 22 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
@@ -3043,50 +1957,6 @@ static struct omap_hwmod_dma_info omap44xx_mcbsp2_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_mcbsp2_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x40124000,
- .pa_end = 0x401240ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> mcbsp2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp2 = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_mcbsp2_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_mcbsp2_addrs,
- .user = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_addr_space omap44xx_mcbsp2_dma_addrs[] = {
- {
- .name = "dma",
- .pa_start = 0x49024000,
- .pa_end = 0x490240ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> mcbsp2 (dma) */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp2_dma = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_mcbsp2_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_mcbsp2_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-/* mcbsp2 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mcbsp2_slaves[] = {
- &omap44xx_l4_abe__mcbsp2,
- &omap44xx_l4_abe__mcbsp2_dma,
-};
-
static struct omap_hwmod_opt_clk mcbsp2_opt_clks[] = {
{ .role = "pad_fck", .clk = "pad_clks_ck" },
{ .role = "prcm_clk", .clk = "mcbsp2_sync_mux_ck" },
@@ -3106,16 +1976,13 @@ static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_mcbsp2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp2_slaves),
.opt_clks = mcbsp2_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(mcbsp2_opt_clks),
};
/* mcbsp3 */
-static struct omap_hwmod omap44xx_mcbsp3_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcbsp3_irqs[] = {
- { .irq = 23 + OMAP44XX_IRQ_GIC_START },
+ { .name = "common", .irq = 23 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
@@ -3125,50 +1992,6 @@ static struct omap_hwmod_dma_info omap44xx_mcbsp3_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_mcbsp3_addrs[] = {
- {
- .name = "mpu",
- .pa_start = 0x40126000,
- .pa_end = 0x401260ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> mcbsp3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp3 = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_mcbsp3_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_mcbsp3_addrs,
- .user = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_addr_space omap44xx_mcbsp3_dma_addrs[] = {
- {
- .name = "dma",
- .pa_start = 0x49026000,
- .pa_end = 0x490260ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> mcbsp3 (dma) */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp3_dma = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_mcbsp3_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_mcbsp3_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-/* mcbsp3 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mcbsp3_slaves[] = {
- &omap44xx_l4_abe__mcbsp3,
- &omap44xx_l4_abe__mcbsp3_dma,
-};
-
static struct omap_hwmod_opt_clk mcbsp3_opt_clks[] = {
{ .role = "pad_fck", .clk = "pad_clks_ck" },
{ .role = "prcm_clk", .clk = "mcbsp3_sync_mux_ck" },
@@ -3188,16 +2011,13 @@ static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_mcbsp3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp3_slaves),
.opt_clks = mcbsp3_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(mcbsp3_opt_clks),
};
/* mcbsp4 */
-static struct omap_hwmod omap44xx_mcbsp4_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcbsp4_irqs[] = {
- { .irq = 16 + OMAP44XX_IRQ_GIC_START },
+ { .name = "common", .irq = 16 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
@@ -3207,29 +2027,6 @@ static struct omap_hwmod_dma_info omap44xx_mcbsp4_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_mcbsp4_addrs[] = {
- {
- .pa_start = 0x48096000,
- .pa_end = 0x480960ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mcbsp4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mcbsp4 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_mcbsp4_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_mcbsp4_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcbsp4 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mcbsp4_slaves[] = {
- &omap44xx_l4_per__mcbsp4,
-};
-
static struct omap_hwmod_opt_clk mcbsp4_opt_clks[] = {
{ .role = "pad_fck", .clk = "pad_clks_ck" },
{ .role = "prcm_clk", .clk = "mcbsp4_sync_mux_ck" },
@@ -3249,8 +2046,6 @@ static struct omap_hwmod omap44xx_mcbsp4_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_mcbsp4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp4_slaves),
.opt_clks = mcbsp4_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(mcbsp4_opt_clks),
};
@@ -3277,7 +2072,6 @@ static struct omap_hwmod_class omap44xx_mcpdm_hwmod_class = {
};
/* mcpdm */
-static struct omap_hwmod omap44xx_mcpdm_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcpdm_irqs[] = {
{ .irq = 112 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -3289,48 +2083,6 @@ static struct omap_hwmod_dma_info omap44xx_mcpdm_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_mcpdm_addrs[] = {
- {
- .pa_start = 0x40132000,
- .pa_end = 0x4013207f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> mcpdm */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_mcpdm_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_mcpdm_addrs,
- .user = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_addr_space omap44xx_mcpdm_dma_addrs[] = {
- {
- .pa_start = 0x49032000,
- .pa_end = 0x4903207f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> mcpdm (dma) */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm_dma = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_mcpdm_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_mcpdm_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-/* mcpdm slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mcpdm_slaves[] = {
- &omap44xx_l4_abe__mcpdm,
- &omap44xx_l4_abe__mcpdm_dma,
-};
-
static struct omap_hwmod omap44xx_mcpdm_hwmod = {
.name = "mcpdm",
.class = &omap44xx_mcpdm_hwmod_class,
@@ -3345,8 +2097,6 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_mcpdm_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mcpdm_slaves),
};
/*
@@ -3372,7 +2122,6 @@ static struct omap_hwmod_class omap44xx_mcspi_hwmod_class = {
};
/* mcspi1 */
-static struct omap_hwmod omap44xx_mcspi1_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcspi1_irqs[] = {
{ .irq = 65 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -3390,29 +2139,6 @@ static struct omap_hwmod_dma_info omap44xx_mcspi1_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_mcspi1_addrs[] = {
- {
- .pa_start = 0x48098000,
- .pa_end = 0x480981ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mcspi1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi1 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_mcspi1_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_mcspi1_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcspi1 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mcspi1_slaves[] = {
- &omap44xx_l4_per__mcspi1,
-};
-
/* mcspi1 dev_attr */
static struct omap2_mcspi_dev_attr mcspi1_dev_attr = {
.num_chipselect = 4,
@@ -3433,12 +2159,9 @@ static struct omap_hwmod omap44xx_mcspi1_hwmod = {
},
},
.dev_attr = &mcspi1_dev_attr,
- .slaves = omap44xx_mcspi1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mcspi1_slaves),
};
/* mcspi2 */
-static struct omap_hwmod omap44xx_mcspi2_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcspi2_irqs[] = {
{ .irq = 66 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -3452,29 +2175,6 @@ static struct omap_hwmod_dma_info omap44xx_mcspi2_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_mcspi2_addrs[] = {
- {
- .pa_start = 0x4809a000,
- .pa_end = 0x4809a1ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mcspi2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi2 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_mcspi2_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_mcspi2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcspi2 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mcspi2_slaves[] = {
- &omap44xx_l4_per__mcspi2,
-};
-
/* mcspi2 dev_attr */
static struct omap2_mcspi_dev_attr mcspi2_dev_attr = {
.num_chipselect = 2,
@@ -3495,12 +2195,9 @@ static struct omap_hwmod omap44xx_mcspi2_hwmod = {
},
},
.dev_attr = &mcspi2_dev_attr,
- .slaves = omap44xx_mcspi2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mcspi2_slaves),
};
/* mcspi3 */
-static struct omap_hwmod omap44xx_mcspi3_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcspi3_irqs[] = {
{ .irq = 91 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -3514,29 +2211,6 @@ static struct omap_hwmod_dma_info omap44xx_mcspi3_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_mcspi3_addrs[] = {
- {
- .pa_start = 0x480b8000,
- .pa_end = 0x480b81ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mcspi3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi3 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_mcspi3_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_mcspi3_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcspi3 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mcspi3_slaves[] = {
- &omap44xx_l4_per__mcspi3,
-};
-
/* mcspi3 dev_attr */
static struct omap2_mcspi_dev_attr mcspi3_dev_attr = {
.num_chipselect = 2,
@@ -3557,12 +2231,9 @@ static struct omap_hwmod omap44xx_mcspi3_hwmod = {
},
},
.dev_attr = &mcspi3_dev_attr,
- .slaves = omap44xx_mcspi3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mcspi3_slaves),
};
/* mcspi4 */
-static struct omap_hwmod omap44xx_mcspi4_hwmod;
static struct omap_hwmod_irq_info omap44xx_mcspi4_irqs[] = {
{ .irq = 48 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -3574,29 +2245,6 @@ static struct omap_hwmod_dma_info omap44xx_mcspi4_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_mcspi4_addrs[] = {
- {
- .pa_start = 0x480ba000,
- .pa_end = 0x480ba1ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mcspi4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi4 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_mcspi4_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_mcspi4_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mcspi4 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mcspi4_slaves[] = {
- &omap44xx_l4_per__mcspi4,
-};
-
/* mcspi4 dev_attr */
static struct omap2_mcspi_dev_attr mcspi4_dev_attr = {
.num_chipselect = 1,
@@ -3617,8 +2265,6 @@ static struct omap_hwmod omap44xx_mcspi4_hwmod = {
},
},
.dev_attr = &mcspi4_dev_attr,
- .slaves = omap44xx_mcspi4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mcspi4_slaves),
};
/*
@@ -3655,34 +2301,6 @@ static struct omap_hwmod_dma_info omap44xx_mmc1_sdma_reqs[] = {
{ .dma_req = -1 }
};
-/* mmc1 master ports */
-static struct omap_hwmod_ocp_if *omap44xx_mmc1_masters[] = {
- &omap44xx_mmc1__l3_main_1,
-};
-
-static struct omap_hwmod_addr_space omap44xx_mmc1_addrs[] = {
- {
- .pa_start = 0x4809c000,
- .pa_end = 0x4809c3ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mmc1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc1 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_mmc1_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_mmc1_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mmc1 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mmc1_slaves[] = {
- &omap44xx_l4_per__mmc1,
-};
-
/* mmc1 dev_attr */
static struct omap_mmc_dev_attr mmc1_dev_attr = {
.flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
@@ -3703,10 +2321,6 @@ static struct omap_hwmod omap44xx_mmc1_hwmod = {
},
},
.dev_attr = &mmc1_dev_attr,
- .slaves = omap44xx_mmc1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mmc1_slaves),
- .masters = omap44xx_mmc1_masters,
- .masters_cnt = ARRAY_SIZE(omap44xx_mmc1_masters),
};
/* mmc2 */
@@ -3721,34 +2335,6 @@ static struct omap_hwmod_dma_info omap44xx_mmc2_sdma_reqs[] = {
{ .dma_req = -1 }
};
-/* mmc2 master ports */
-static struct omap_hwmod_ocp_if *omap44xx_mmc2_masters[] = {
- &omap44xx_mmc2__l3_main_1,
-};
-
-static struct omap_hwmod_addr_space omap44xx_mmc2_addrs[] = {
- {
- .pa_start = 0x480b4000,
- .pa_end = 0x480b43ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mmc2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc2 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_mmc2_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_mmc2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mmc2 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mmc2_slaves[] = {
- &omap44xx_l4_per__mmc2,
-};
-
static struct omap_hwmod omap44xx_mmc2_hwmod = {
.name = "mmc2",
.class = &omap44xx_mmc_hwmod_class,
@@ -3763,14 +2349,9 @@ static struct omap_hwmod omap44xx_mmc2_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_mmc2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mmc2_slaves),
- .masters = omap44xx_mmc2_masters,
- .masters_cnt = ARRAY_SIZE(omap44xx_mmc2_masters),
};
/* mmc3 */
-static struct omap_hwmod omap44xx_mmc3_hwmod;
static struct omap_hwmod_irq_info omap44xx_mmc3_irqs[] = {
{ .irq = 94 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -3782,29 +2363,6 @@ static struct omap_hwmod_dma_info omap44xx_mmc3_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_mmc3_addrs[] = {
- {
- .pa_start = 0x480ad000,
- .pa_end = 0x480ad3ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mmc3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc3 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_mmc3_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_mmc3_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mmc3 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mmc3_slaves[] = {
- &omap44xx_l4_per__mmc3,
-};
-
static struct omap_hwmod omap44xx_mmc3_hwmod = {
.name = "mmc3",
.class = &omap44xx_mmc_hwmod_class,
@@ -3819,12 +2377,9 @@ static struct omap_hwmod omap44xx_mmc3_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_mmc3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mmc3_slaves),
};
/* mmc4 */
-static struct omap_hwmod omap44xx_mmc4_hwmod;
static struct omap_hwmod_irq_info omap44xx_mmc4_irqs[] = {
{ .irq = 96 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -3836,35 +2391,11 @@ static struct omap_hwmod_dma_info omap44xx_mmc4_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_mmc4_addrs[] = {
- {
- .pa_start = 0x480d1000,
- .pa_end = 0x480d13ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mmc4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc4 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_mmc4_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_mmc4_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mmc4 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mmc4_slaves[] = {
- &omap44xx_l4_per__mmc4,
-};
-
static struct omap_hwmod omap44xx_mmc4_hwmod = {
.name = "mmc4",
.class = &omap44xx_mmc_hwmod_class,
.clkdm_name = "l4_per_clkdm",
.mpu_irqs = omap44xx_mmc4_irqs,
-
.sdma_reqs = omap44xx_mmc4_sdma_reqs,
.main_clk = "mmc4_fck",
.prcm = {
@@ -3874,12 +2405,9 @@ static struct omap_hwmod omap44xx_mmc4_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_mmc4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mmc4_slaves),
};
/* mmc5 */
-static struct omap_hwmod omap44xx_mmc5_hwmod;
static struct omap_hwmod_irq_info omap44xx_mmc5_irqs[] = {
{ .irq = 59 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -3891,29 +2419,6 @@ static struct omap_hwmod_dma_info omap44xx_mmc5_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_mmc5_addrs[] = {
- {
- .pa_start = 0x480d5000,
- .pa_end = 0x480d53ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> mmc5 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc5 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_mmc5_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_mmc5_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mmc5 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_mmc5_slaves[] = {
- &omap44xx_l4_per__mmc5,
-};
-
static struct omap_hwmod omap44xx_mmc5_hwmod = {
.name = "mmc5",
.class = &omap44xx_mmc_hwmod_class,
@@ -3928,8 +2433,6 @@ static struct omap_hwmod omap44xx_mmc5_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_mmc5_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_mmc5_slaves),
};
/*
@@ -3949,13 +2452,6 @@ static struct omap_hwmod_irq_info omap44xx_mpu_irqs[] = {
{ .irq = -1 }
};
-/* mpu master ports */
-static struct omap_hwmod_ocp_if *omap44xx_mpu_masters[] = {
- &omap44xx_mpu__l3_main_1,
- &omap44xx_mpu__l4_abe,
- &omap44xx_mpu__dmm,
-};
-
static struct omap_hwmod omap44xx_mpu_hwmod = {
.name = "mpu",
.class = &omap44xx_mpu_hwmod_class,
@@ -3969,8 +2465,252 @@ static struct omap_hwmod omap44xx_mpu_hwmod = {
.context_offs = OMAP4_RM_MPU_MPU_CONTEXT_OFFSET,
},
},
- .masters = omap44xx_mpu_masters,
- .masters_cnt = ARRAY_SIZE(omap44xx_mpu_masters),
+};
+
+/*
+ * 'ocmc_ram' class
+ * top-level core on-chip ram
+ */
+
+static struct omap_hwmod_class omap44xx_ocmc_ram_hwmod_class = {
+ .name = "ocmc_ram",
+};
+
+/* ocmc_ram */
+static struct omap_hwmod omap44xx_ocmc_ram_hwmod = {
+ .name = "ocmc_ram",
+ .class = &omap44xx_ocmc_ram_hwmod_class,
+ .clkdm_name = "l3_2_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L3_2_OCMC_RAM_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3_2_OCMC_RAM_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/*
+ * 'ocp2scp' class
+ * bridge to transform ocp interface protocol to scp (serial control port)
+ * protocol
+ */
+
+static struct omap_hwmod_class omap44xx_ocp2scp_hwmod_class = {
+ .name = "ocp2scp",
+};
+
+/* ocp2scp_usb_phy */
+static struct omap_hwmod_opt_clk ocp2scp_usb_phy_opt_clks[] = {
+ { .role = "phy_48m", .clk = "ocp2scp_usb_phy_phy_48m" },
+};
+
+static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
+ .name = "ocp2scp_usb_phy",
+ .class = &omap44xx_ocp2scp_hwmod_class,
+ .clkdm_name = "l3_init_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3INIT_USBPHYOCP2SCP_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
+ },
+ },
+ .opt_clks = ocp2scp_usb_phy_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(ocp2scp_usb_phy_opt_clks),
+};
+
+/*
+ * 'prcm' class
+ * power and reset manager (part of the prcm infrastructure) + clock manager 2
+ * + clock manager 1 (in always on power domain) + local prm in mpu
+ */
+
+static struct omap_hwmod_class omap44xx_prcm_hwmod_class = {
+ .name = "prcm",
+};
+
+/* prcm_mpu */
+static struct omap_hwmod omap44xx_prcm_mpu_hwmod = {
+ .name = "prcm_mpu",
+ .class = &omap44xx_prcm_hwmod_class,
+ .clkdm_name = "l4_wkup_clkdm",
+};
+
+/* cm_core_aon */
+static struct omap_hwmod omap44xx_cm_core_aon_hwmod = {
+ .name = "cm_core_aon",
+ .class = &omap44xx_prcm_hwmod_class,
+ .clkdm_name = "cm_clkdm",
+};
+
+/* cm_core */
+static struct omap_hwmod omap44xx_cm_core_hwmod = {
+ .name = "cm_core",
+ .class = &omap44xx_prcm_hwmod_class,
+ .clkdm_name = "cm_clkdm",
+};
+
+/* prm */
+static struct omap_hwmod_irq_info omap44xx_prm_irqs[] = {
+ { .irq = 11 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod_rst_info omap44xx_prm_resets[] = {
+ { .name = "rst_global_warm_sw", .rst_shift = 0 },
+ { .name = "rst_global_cold_sw", .rst_shift = 1 },
+};
+
+static struct omap_hwmod omap44xx_prm_hwmod = {
+ .name = "prm",
+ .class = &omap44xx_prcm_hwmod_class,
+ .clkdm_name = "prm_clkdm",
+ .mpu_irqs = omap44xx_prm_irqs,
+ .rst_lines = omap44xx_prm_resets,
+ .rst_lines_cnt = ARRAY_SIZE(omap44xx_prm_resets),
+};
+
+/*
+ * 'scrm' class
+ * system clock and reset manager
+ */
+
+static struct omap_hwmod_class omap44xx_scrm_hwmod_class = {
+ .name = "scrm",
+};
+
+/* scrm */
+static struct omap_hwmod omap44xx_scrm_hwmod = {
+ .name = "scrm",
+ .class = &omap44xx_scrm_hwmod_class,
+ .clkdm_name = "l4_wkup_clkdm",
+};
+
+/*
+ * 'sl2if' class
+ * shared level 2 memory interface
+ */
+
+static struct omap_hwmod_class omap44xx_sl2if_hwmod_class = {
+ .name = "sl2if",
+};
+
+/* sl2if */
+static struct omap_hwmod omap44xx_sl2if_hwmod = {
+ .name = "sl2if",
+ .class = &omap44xx_sl2if_hwmod_class,
+ .clkdm_name = "ivahd_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_IVAHD_SL2_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_IVAHD_SL2_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
+ },
+ },
+};
+
+/*
+ * 'slimbus' class
+ * bidirectional, multi-drop, multi-channel two-line serial interface between
+ * the device and external components
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_slimbus_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .sysc_flags = (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_SOFTRESET),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ SIDLE_SMART_WKUP),
+ .sysc_fields = &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_slimbus_hwmod_class = {
+ .name = "slimbus",
+ .sysc = &omap44xx_slimbus_sysc,
+};
+
+/* slimbus1 */
+static struct omap_hwmod_irq_info omap44xx_slimbus1_irqs[] = {
+ { .irq = 97 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod_dma_info omap44xx_slimbus1_sdma_reqs[] = {
+ { .name = "tx0", .dma_req = 84 + OMAP44XX_DMA_REQ_START },
+ { .name = "tx1", .dma_req = 85 + OMAP44XX_DMA_REQ_START },
+ { .name = "tx2", .dma_req = 86 + OMAP44XX_DMA_REQ_START },
+ { .name = "tx3", .dma_req = 87 + OMAP44XX_DMA_REQ_START },
+ { .name = "rx0", .dma_req = 88 + OMAP44XX_DMA_REQ_START },
+ { .name = "rx1", .dma_req = 89 + OMAP44XX_DMA_REQ_START },
+ { .name = "rx2", .dma_req = 90 + OMAP44XX_DMA_REQ_START },
+ { .name = "rx3", .dma_req = 91 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
+};
+
+static struct omap_hwmod_opt_clk slimbus1_opt_clks[] = {
+ { .role = "fclk_1", .clk = "slimbus1_fclk_1" },
+ { .role = "fclk_0", .clk = "slimbus1_fclk_0" },
+ { .role = "fclk_2", .clk = "slimbus1_fclk_2" },
+ { .role = "slimbus_clk", .clk = "slimbus1_slimbus_clk" },
+};
+
+static struct omap_hwmod omap44xx_slimbus1_hwmod = {
+ .name = "slimbus1",
+ .class = &omap44xx_slimbus_hwmod_class,
+ .clkdm_name = "abe_clkdm",
+ .mpu_irqs = omap44xx_slimbus1_irqs,
+ .sdma_reqs = omap44xx_slimbus1_sdma_reqs,
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM1_ABE_SLIMBUS_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_SLIMBUS_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+ .opt_clks = slimbus1_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(slimbus1_opt_clks),
+};
+
+/* slimbus2 */
+static struct omap_hwmod_irq_info omap44xx_slimbus2_irqs[] = {
+ { .irq = 98 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod_dma_info omap44xx_slimbus2_sdma_reqs[] = {
+ { .name = "tx0", .dma_req = 92 + OMAP44XX_DMA_REQ_START },
+ { .name = "tx1", .dma_req = 93 + OMAP44XX_DMA_REQ_START },
+ { .name = "tx2", .dma_req = 94 + OMAP44XX_DMA_REQ_START },
+ { .name = "tx3", .dma_req = 95 + OMAP44XX_DMA_REQ_START },
+ { .name = "rx0", .dma_req = 96 + OMAP44XX_DMA_REQ_START },
+ { .name = "rx1", .dma_req = 97 + OMAP44XX_DMA_REQ_START },
+ { .name = "rx2", .dma_req = 98 + OMAP44XX_DMA_REQ_START },
+ { .name = "rx3", .dma_req = 99 + OMAP44XX_DMA_REQ_START },
+ { .dma_req = -1 }
+};
+
+static struct omap_hwmod_opt_clk slimbus2_opt_clks[] = {
+ { .role = "fclk_1", .clk = "slimbus2_fclk_1" },
+ { .role = "fclk_0", .clk = "slimbus2_fclk_0" },
+ { .role = "slimbus_clk", .clk = "slimbus2_slimbus_clk" },
+};
+
+static struct omap_hwmod omap44xx_slimbus2_hwmod = {
+ .name = "slimbus2",
+ .class = &omap44xx_slimbus_hwmod_class,
+ .clkdm_name = "l4_per_clkdm",
+ .mpu_irqs = omap44xx_slimbus2_irqs,
+ .sdma_reqs = omap44xx_slimbus2_sdma_reqs,
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L4PER_SLIMBUS2_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L4PER_SLIMBUS2_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+ .opt_clks = slimbus2_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(slimbus2_opt_clks),
};
/*
@@ -4004,35 +2744,11 @@ static struct omap_smartreflex_dev_attr smartreflex_core_dev_attr = {
.sensor_voltdm_name = "core",
};
-static struct omap_hwmod omap44xx_smartreflex_core_hwmod;
static struct omap_hwmod_irq_info omap44xx_smartreflex_core_irqs[] = {
{ .irq = 19 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_smartreflex_core_addrs[] = {
- {
- .pa_start = 0x4a0dd000,
- .pa_end = 0x4a0dd03f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_cfg -> smartreflex_core */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_core = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_smartreflex_core_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_smartreflex_core_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* smartreflex_core slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_smartreflex_core_slaves[] = {
- &omap44xx_l4_cfg__smartreflex_core,
-};
-
static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
.name = "smartreflex_core",
.class = &omap44xx_smartreflex_hwmod_class,
@@ -4047,8 +2763,6 @@ static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_smartreflex_core_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_core_slaves),
.dev_attr = &smartreflex_core_dev_attr,
};
@@ -4057,35 +2771,11 @@ static struct omap_smartreflex_dev_attr smartreflex_iva_dev_attr = {
.sensor_voltdm_name = "iva",
};
-static struct omap_hwmod omap44xx_smartreflex_iva_hwmod;
static struct omap_hwmod_irq_info omap44xx_smartreflex_iva_irqs[] = {
{ .irq = 102 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_smartreflex_iva_addrs[] = {
- {
- .pa_start = 0x4a0db000,
- .pa_end = 0x4a0db03f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_cfg -> smartreflex_iva */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_iva = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_smartreflex_iva_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_smartreflex_iva_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* smartreflex_iva slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_smartreflex_iva_slaves[] = {
- &omap44xx_l4_cfg__smartreflex_iva,
-};
-
static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
.name = "smartreflex_iva",
.class = &omap44xx_smartreflex_hwmod_class,
@@ -4099,8 +2789,6 @@ static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_smartreflex_iva_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_iva_slaves),
.dev_attr = &smartreflex_iva_dev_attr,
};
@@ -4109,35 +2797,11 @@ static struct omap_smartreflex_dev_attr smartreflex_mpu_dev_attr = {
.sensor_voltdm_name = "mpu",
};
-static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod;
static struct omap_hwmod_irq_info omap44xx_smartreflex_mpu_irqs[] = {
{ .irq = 18 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_smartreflex_mpu_addrs[] = {
- {
- .pa_start = 0x4a0d9000,
- .pa_end = 0x4a0d903f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_cfg -> smartreflex_mpu */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_mpu = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_smartreflex_mpu_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_smartreflex_mpu_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* smartreflex_mpu slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_smartreflex_mpu_slaves[] = {
- &omap44xx_l4_cfg__smartreflex_mpu,
-};
-
static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
.name = "smartreflex_mpu",
.class = &omap44xx_smartreflex_hwmod_class,
@@ -4151,8 +2815,6 @@ static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_smartreflex_mpu_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_mpu_slaves),
.dev_attr = &smartreflex_mpu_dev_attr,
};
@@ -4180,30 +2842,6 @@ static struct omap_hwmod_class omap44xx_spinlock_hwmod_class = {
};
/* spinlock */
-static struct omap_hwmod omap44xx_spinlock_hwmod;
-static struct omap_hwmod_addr_space omap44xx_spinlock_addrs[] = {
- {
- .pa_start = 0x4a0f6000,
- .pa_end = 0x4a0f6fff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_cfg -> spinlock */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__spinlock = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_spinlock_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_spinlock_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* spinlock slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_spinlock_slaves[] = {
- &omap44xx_l4_cfg__spinlock,
-};
-
static struct omap_hwmod omap44xx_spinlock_hwmod = {
.name = "spinlock",
.class = &omap44xx_spinlock_hwmod_class,
@@ -4214,8 +2852,6 @@ static struct omap_hwmod omap44xx_spinlock_hwmod = {
.context_offs = OMAP4_RM_L4CFG_HW_SEM_CONTEXT_OFFSET,
},
},
- .slaves = omap44xx_spinlock_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_spinlock_slaves),
};
/*
@@ -4267,35 +2903,11 @@ static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
};
/* timer1 */
-static struct omap_hwmod omap44xx_timer1_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
{ .irq = 37 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_timer1_addrs[] = {
- {
- .pa_start = 0x4a318000,
- .pa_end = 0x4a31807f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_wkup -> timer1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_wkup__timer1 = {
- .master = &omap44xx_l4_wkup_hwmod,
- .slave = &omap44xx_timer1_hwmod,
- .clk = "l4_wkup_clk_mux_ck",
- .addr = omap44xx_timer1_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer1 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_timer1_slaves[] = {
- &omap44xx_l4_wkup__timer1,
-};
-
static struct omap_hwmod omap44xx_timer1_hwmod = {
.name = "timer1",
.class = &omap44xx_timer_1ms_hwmod_class,
@@ -4310,40 +2922,14 @@ static struct omap_hwmod omap44xx_timer1_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap44xx_timer1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_timer1_slaves),
};
/* timer2 */
-static struct omap_hwmod omap44xx_timer2_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer2_irqs[] = {
{ .irq = 38 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_timer2_addrs[] = {
- {
- .pa_start = 0x48032000,
- .pa_end = 0x4803207f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__timer2 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_timer2_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_timer2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer2 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_timer2_slaves[] = {
- &omap44xx_l4_per__timer2,
-};
-
static struct omap_hwmod omap44xx_timer2_hwmod = {
.name = "timer2",
.class = &omap44xx_timer_1ms_hwmod_class,
@@ -4358,40 +2944,14 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap44xx_timer2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_timer2_slaves),
};
/* timer3 */
-static struct omap_hwmod omap44xx_timer3_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer3_irqs[] = {
{ .irq = 39 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_timer3_addrs[] = {
- {
- .pa_start = 0x48034000,
- .pa_end = 0x4803407f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__timer3 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_timer3_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_timer3_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer3 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_timer3_slaves[] = {
- &omap44xx_l4_per__timer3,
-};
-
static struct omap_hwmod omap44xx_timer3_hwmod = {
.name = "timer3",
.class = &omap44xx_timer_hwmod_class,
@@ -4406,40 +2966,14 @@ static struct omap_hwmod omap44xx_timer3_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap44xx_timer3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_timer3_slaves),
};
/* timer4 */
-static struct omap_hwmod omap44xx_timer4_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer4_irqs[] = {
{ .irq = 40 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_timer4_addrs[] = {
- {
- .pa_start = 0x48036000,
- .pa_end = 0x4803607f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__timer4 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_timer4_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_timer4_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer4 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_timer4_slaves[] = {
- &omap44xx_l4_per__timer4,
-};
-
static struct omap_hwmod omap44xx_timer4_hwmod = {
.name = "timer4",
.class = &omap44xx_timer_hwmod_class,
@@ -4454,59 +2988,14 @@ static struct omap_hwmod omap44xx_timer4_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap44xx_timer4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_timer4_slaves),
};
/* timer5 */
-static struct omap_hwmod omap44xx_timer5_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer5_irqs[] = {
{ .irq = 41 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_timer5_addrs[] = {
- {
- .pa_start = 0x40138000,
- .pa_end = 0x4013807f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> timer5 */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer5 = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_timer5_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_timer5_addrs,
- .user = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_addr_space omap44xx_timer5_dma_addrs[] = {
- {
- .pa_start = 0x49038000,
- .pa_end = 0x4903807f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> timer5 (dma) */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer5_dma = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_timer5_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_timer5_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-/* timer5 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_timer5_slaves[] = {
- &omap44xx_l4_abe__timer5,
- &omap44xx_l4_abe__timer5_dma,
-};
-
static struct omap_hwmod omap44xx_timer5_hwmod = {
.name = "timer5",
.class = &omap44xx_timer_hwmod_class,
@@ -4521,59 +3010,14 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap44xx_timer5_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_timer5_slaves),
};
/* timer6 */
-static struct omap_hwmod omap44xx_timer6_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer6_irqs[] = {
{ .irq = 42 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_timer6_addrs[] = {
- {
- .pa_start = 0x4013a000,
- .pa_end = 0x4013a07f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> timer6 */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer6 = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_timer6_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_timer6_addrs,
- .user = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_addr_space omap44xx_timer6_dma_addrs[] = {
- {
- .pa_start = 0x4903a000,
- .pa_end = 0x4903a07f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> timer6 (dma) */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer6_dma = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_timer6_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_timer6_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-/* timer6 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_timer6_slaves[] = {
- &omap44xx_l4_abe__timer6,
- &omap44xx_l4_abe__timer6_dma,
-};
-
static struct omap_hwmod omap44xx_timer6_hwmod = {
.name = "timer6",
.class = &omap44xx_timer_hwmod_class,
@@ -4589,59 +3033,14 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap44xx_timer6_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_timer6_slaves),
};
/* timer7 */
-static struct omap_hwmod omap44xx_timer7_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer7_irqs[] = {
{ .irq = 43 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_timer7_addrs[] = {
- {
- .pa_start = 0x4013c000,
- .pa_end = 0x4013c07f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> timer7 */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer7 = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_timer7_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_timer7_addrs,
- .user = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_addr_space omap44xx_timer7_dma_addrs[] = {
- {
- .pa_start = 0x4903c000,
- .pa_end = 0x4903c07f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> timer7 (dma) */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer7_dma = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_timer7_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_timer7_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-/* timer7 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_timer7_slaves[] = {
- &omap44xx_l4_abe__timer7,
- &omap44xx_l4_abe__timer7_dma,
-};
-
static struct omap_hwmod omap44xx_timer7_hwmod = {
.name = "timer7",
.class = &omap44xx_timer_hwmod_class,
@@ -4656,59 +3055,14 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
},
},
.dev_attr = &capability_alwon_dev_attr,
- .slaves = omap44xx_timer7_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_timer7_slaves),
};
/* timer8 */
-static struct omap_hwmod omap44xx_timer8_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer8_irqs[] = {
{ .irq = 44 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_timer8_addrs[] = {
- {
- .pa_start = 0x4013e000,
- .pa_end = 0x4013e07f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> timer8 */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer8 = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_timer8_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_timer8_addrs,
- .user = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_addr_space omap44xx_timer8_dma_addrs[] = {
- {
- .pa_start = 0x4903e000,
- .pa_end = 0x4903e07f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_abe -> timer8 (dma) */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer8_dma = {
- .master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_timer8_hwmod,
- .clk = "ocp_abe_iclk",
- .addr = omap44xx_timer8_dma_addrs,
- .user = OCP_USER_SDMA,
-};
-
-/* timer8 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_timer8_slaves[] = {
- &omap44xx_l4_abe__timer8,
- &omap44xx_l4_abe__timer8_dma,
-};
-
static struct omap_hwmod omap44xx_timer8_hwmod = {
.name = "timer8",
.class = &omap44xx_timer_hwmod_class,
@@ -4723,40 +3077,14 @@ static struct omap_hwmod omap44xx_timer8_hwmod = {
},
},
.dev_attr = &capability_pwm_dev_attr,
- .slaves = omap44xx_timer8_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_timer8_slaves),
};
/* timer9 */
-static struct omap_hwmod omap44xx_timer9_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer9_irqs[] = {
{ .irq = 45 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_timer9_addrs[] = {
- {
- .pa_start = 0x4803e000,
- .pa_end = 0x4803e07f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer9 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__timer9 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_timer9_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_timer9_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer9 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_timer9_slaves[] = {
- &omap44xx_l4_per__timer9,
-};
-
static struct omap_hwmod omap44xx_timer9_hwmod = {
.name = "timer9",
.class = &omap44xx_timer_hwmod_class,
@@ -4771,40 +3099,14 @@ static struct omap_hwmod omap44xx_timer9_hwmod = {
},
},
.dev_attr = &capability_pwm_dev_attr,
- .slaves = omap44xx_timer9_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_timer9_slaves),
};
/* timer10 */
-static struct omap_hwmod omap44xx_timer10_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer10_irqs[] = {
{ .irq = 46 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_timer10_addrs[] = {
- {
- .pa_start = 0x48086000,
- .pa_end = 0x4808607f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer10 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__timer10 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_timer10_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_timer10_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer10 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_timer10_slaves[] = {
- &omap44xx_l4_per__timer10,
-};
-
static struct omap_hwmod omap44xx_timer10_hwmod = {
.name = "timer10",
.class = &omap44xx_timer_1ms_hwmod_class,
@@ -4819,40 +3121,14 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
},
},
.dev_attr = &capability_pwm_dev_attr,
- .slaves = omap44xx_timer10_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_timer10_slaves),
};
/* timer11 */
-static struct omap_hwmod omap44xx_timer11_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer11_irqs[] = {
{ .irq = 47 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_timer11_addrs[] = {
- {
- .pa_start = 0x48088000,
- .pa_end = 0x4808807f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> timer11 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__timer11 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_timer11_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_timer11_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* timer11 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_timer11_slaves[] = {
- &omap44xx_l4_per__timer11,
-};
-
static struct omap_hwmod omap44xx_timer11_hwmod = {
.name = "timer11",
.class = &omap44xx_timer_hwmod_class,
@@ -4867,8 +3143,6 @@ static struct omap_hwmod omap44xx_timer11_hwmod = {
},
},
.dev_attr = &capability_pwm_dev_attr,
- .slaves = omap44xx_timer11_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_timer11_slaves),
};
/*
@@ -4894,7 +3168,6 @@ static struct omap_hwmod_class omap44xx_uart_hwmod_class = {
};
/* uart1 */
-static struct omap_hwmod omap44xx_uart1_hwmod;
static struct omap_hwmod_irq_info omap44xx_uart1_irqs[] = {
{ .irq = 72 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -4906,29 +3179,6 @@ static struct omap_hwmod_dma_info omap44xx_uart1_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_uart1_addrs[] = {
- {
- .pa_start = 0x4806a000,
- .pa_end = 0x4806a0ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> uart1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__uart1 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_uart1_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_uart1_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* uart1 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_uart1_slaves[] = {
- &omap44xx_l4_per__uart1,
-};
-
static struct omap_hwmod omap44xx_uart1_hwmod = {
.name = "uart1",
.class = &omap44xx_uart_hwmod_class,
@@ -4943,12 +3193,9 @@ static struct omap_hwmod omap44xx_uart1_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_uart1_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_uart1_slaves),
};
/* uart2 */
-static struct omap_hwmod omap44xx_uart2_hwmod;
static struct omap_hwmod_irq_info omap44xx_uart2_irqs[] = {
{ .irq = 73 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -4960,29 +3207,6 @@ static struct omap_hwmod_dma_info omap44xx_uart2_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_uart2_addrs[] = {
- {
- .pa_start = 0x4806c000,
- .pa_end = 0x4806c0ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> uart2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__uart2 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_uart2_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_uart2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* uart2 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_uart2_slaves[] = {
- &omap44xx_l4_per__uart2,
-};
-
static struct omap_hwmod omap44xx_uart2_hwmod = {
.name = "uart2",
.class = &omap44xx_uart_hwmod_class,
@@ -4997,12 +3221,9 @@ static struct omap_hwmod omap44xx_uart2_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_uart2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_uart2_slaves),
};
/* uart3 */
-static struct omap_hwmod omap44xx_uart3_hwmod;
static struct omap_hwmod_irq_info omap44xx_uart3_irqs[] = {
{ .irq = 74 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -5014,29 +3235,6 @@ static struct omap_hwmod_dma_info omap44xx_uart3_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_uart3_addrs[] = {
- {
- .pa_start = 0x48020000,
- .pa_end = 0x480200ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> uart3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__uart3 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_uart3_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_uart3_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* uart3 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_uart3_slaves[] = {
- &omap44xx_l4_per__uart3,
-};
-
static struct omap_hwmod omap44xx_uart3_hwmod = {
.name = "uart3",
.class = &omap44xx_uart_hwmod_class,
@@ -5052,12 +3250,9 @@ static struct omap_hwmod omap44xx_uart3_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_uart3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_uart3_slaves),
};
/* uart4 */
-static struct omap_hwmod omap44xx_uart4_hwmod;
static struct omap_hwmod_irq_info omap44xx_uart4_irqs[] = {
{ .irq = 70 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
@@ -5069,29 +3264,6 @@ static struct omap_hwmod_dma_info omap44xx_uart4_sdma_reqs[] = {
{ .dma_req = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_uart4_addrs[] = {
- {
- .pa_start = 0x4806e000,
- .pa_end = 0x4806e0ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_per -> uart4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__uart4 = {
- .master = &omap44xx_l4_per_hwmod,
- .slave = &omap44xx_uart4_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_uart4_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* uart4 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_uart4_slaves[] = {
- &omap44xx_l4_per__uart4,
-};
-
static struct omap_hwmod omap44xx_uart4_hwmod = {
.name = "uart4",
.class = &omap44xx_uart_hwmod_class,
@@ -5106,8 +3278,147 @@ static struct omap_hwmod omap44xx_uart4_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_uart4_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_uart4_slaves),
+};
+
+/*
+ * 'usb_host_fs' class
+ * full-speed usb host controller
+ */
+
+/* The IP is not compliant to type1 / type2 scheme */
+static struct omap_hwmod_sysc_fields omap_hwmod_sysc_type_usb_host_fs = {
+ .midle_shift = 4,
+ .sidle_shift = 2,
+ .srst_shift = 1,
+};
+
+static struct omap_hwmod_class_sysconfig omap44xx_usb_host_fs_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0210,
+ .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_SOFTRESET),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ SIDLE_SMART_WKUP),
+ .sysc_fields = &omap_hwmod_sysc_type_usb_host_fs,
+};
+
+static struct omap_hwmod_class omap44xx_usb_host_fs_hwmod_class = {
+ .name = "usb_host_fs",
+ .sysc = &omap44xx_usb_host_fs_sysc,
+};
+
+/* usb_host_fs */
+static struct omap_hwmod_irq_info omap44xx_usb_host_fs_irqs[] = {
+ { .name = "std", .irq = 89 + OMAP44XX_IRQ_GIC_START },
+ { .name = "smi", .irq = 90 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod omap44xx_usb_host_fs_hwmod = {
+ .name = "usb_host_fs",
+ .class = &omap44xx_usb_host_fs_hwmod_class,
+ .clkdm_name = "l3_init_clkdm",
+ .mpu_irqs = omap44xx_usb_host_fs_irqs,
+ .main_clk = "usb_host_fs_fck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L3INIT_USB_HOST_FS_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3INIT_USB_HOST_FS_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+};
+
+/*
+ * 'usb_host_hs' class
+ * high-speed multi-port usb host controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_usb_host_hs_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_SOFTRESET),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+ MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
+ .sysc_fields = &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_usb_host_hs_hwmod_class = {
+ .name = "usb_host_hs",
+ .sysc = &omap44xx_usb_host_hs_sysc,
+};
+
+/* usb_host_hs */
+static struct omap_hwmod_irq_info omap44xx_usb_host_hs_irqs[] = {
+ { .name = "ohci-irq", .irq = 76 + OMAP44XX_IRQ_GIC_START },
+ { .name = "ehci-irq", .irq = 77 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod omap44xx_usb_host_hs_hwmod = {
+ .name = "usb_host_hs",
+ .class = &omap44xx_usb_host_hs_hwmod_class,
+ .clkdm_name = "l3_init_clkdm",
+ .main_clk = "usb_host_hs_fck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3INIT_USB_HOST_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+ .mpu_irqs = omap44xx_usb_host_hs_irqs,
+
+ /*
+ * Errata: USBHOST Configured In Smart-Idle Can Lead To a Deadlock
+ * id: i660
+ *
+ * Description:
+ * In the following configuration :
+ * - USBHOST module is set to smart-idle mode
+ * - PRCM asserts idle_req to the USBHOST module ( This typically
+ * happens when the system is going to a low power mode : all ports
+ * have been suspended, the master part of the USBHOST module has
+ * entered the standby state, and SW has cut the functional clocks)
+ * - an USBHOST interrupt occurs before the module is able to answer
+ * idle_ack, typically a remote wakeup IRQ.
+ * Then the USB HOST module will enter a deadlock situation where it
+ * is no more accessible nor functional.
+ *
+ * Workaround:
+ * Don't use smart idle; use only force idle, hence HWMOD_SWSUP_SIDLE
+ */
+
+ /*
+ * Errata: USB host EHCI may stall when entering smart-standby mode
+ * Id: i571
+ *
+ * Description:
+ * When the USBHOST module is set to smart-standby mode, and when it is
+ * ready to enter the standby state (i.e. all ports are suspended and
+ * all attached devices are in suspend mode), then it can wrongly assert
+ * the Mstandby signal too early while there are still some residual OCP
+ * transactions ongoing. If this condition occurs, the internal state
+ * machine may go to an undefined state and the USB link may be stuck
+ * upon the next resume.
+ *
+ * Workaround:
+ * Don't use smart standby; use only force standby,
+ * hence HWMOD_SWSUP_MSTANDBY
+ */
+
+ /*
+ * During system boot; If the hwmod framework resets the module
+ * the module will have smart idle settings; which can lead to deadlock
+ * (above Errata Id:i660); so, dont reset the module during boot;
+ * Use HWMOD_INIT_NO_RESET.
+ */
+
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
+ HWMOD_INIT_NO_RESET,
};
/*
@@ -5140,34 +3451,6 @@ static struct omap_hwmod_irq_info omap44xx_usb_otg_hs_irqs[] = {
{ .irq = -1 }
};
-/* usb_otg_hs master ports */
-static struct omap_hwmod_ocp_if *omap44xx_usb_otg_hs_masters[] = {
- &omap44xx_usb_otg_hs__l3_main_2,
-};
-
-static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {
- {
- .pa_start = 0x4a0ab000,
- .pa_end = 0x4a0ab003,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_cfg -> usb_otg_hs */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_otg_hs = {
- .master = &omap44xx_l4_cfg_hwmod,
- .slave = &omap44xx_usb_otg_hs_hwmod,
- .clk = "l4_div_ck",
- .addr = omap44xx_usb_otg_hs_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* usb_otg_hs slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_usb_otg_hs_slaves[] = {
- &omap44xx_l4_cfg__usb_otg_hs,
-};
-
static struct omap_hwmod_opt_clk usb_otg_hs_opt_clks[] = {
{ .role = "xclk", .clk = "usb_otg_hs_xclk" },
};
@@ -5188,10 +3471,47 @@ static struct omap_hwmod omap44xx_usb_otg_hs_hwmod = {
},
.opt_clks = usb_otg_hs_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(usb_otg_hs_opt_clks),
- .slaves = omap44xx_usb_otg_hs_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_usb_otg_hs_slaves),
- .masters = omap44xx_usb_otg_hs_masters,
- .masters_cnt = ARRAY_SIZE(omap44xx_usb_otg_hs_masters),
+};
+
+/*
+ * 'usb_tll_hs' class
+ * usb_tll_hs module is the adapter on the usb_host_hs ports
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_usb_tll_hs_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_usb_tll_hs_hwmod_class = {
+ .name = "usb_tll_hs",
+ .sysc = &omap44xx_usb_tll_hs_sysc,
+};
+
+static struct omap_hwmod_irq_info omap44xx_usb_tll_hs_irqs[] = {
+ { .name = "tll-irq", .irq = 78 + OMAP44XX_IRQ_GIC_START },
+ { .irq = -1 }
+};
+
+static struct omap_hwmod omap44xx_usb_tll_hs_hwmod = {
+ .name = "usb_tll_hs",
+ .class = &omap44xx_usb_tll_hs_hwmod_class,
+ .clkdm_name = "l3_init_clkdm",
+ .mpu_irqs = omap44xx_usb_tll_hs_irqs,
+ .main_clk = "usb_tll_hs_ick",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_L3INIT_USB_TLL_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
+ },
+ },
};
/*
@@ -5215,38 +3535,15 @@ static struct omap_hwmod_class omap44xx_wd_timer_hwmod_class = {
.name = "wd_timer",
.sysc = &omap44xx_wd_timer_sysc,
.pre_shutdown = &omap2_wd_timer_disable,
+ .reset = &omap2_wd_timer_reset,
};
/* wd_timer2 */
-static struct omap_hwmod omap44xx_wd_timer2_hwmod;
static struct omap_hwmod_irq_info omap44xx_wd_timer2_irqs[] = {
{ .irq = 80 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_wd_timer2_addrs[] = {
- {
- .pa_start = 0x4a314000,
- .pa_end = 0x4a31407f,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
-/* l4_wkup -> wd_timer2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_wkup__wd_timer2 = {
- .master = &omap44xx_l4_wkup_hwmod,
- .slave = &omap44xx_wd_timer2_hwmod,
- .clk = "l4_wkup_clk_mux_ck",
- .addr = omap44xx_wd_timer2_addrs,
- .user = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* wd_timer2 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_wd_timer2_slaves[] = {
- &omap44xx_l4_wkup__wd_timer2,
-};
-
static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
.name = "wd_timer2",
.class = &omap44xx_wd_timer_hwmod_class,
@@ -5260,106 +3557,2308 @@ static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
- .slaves = omap44xx_wd_timer2_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_wd_timer2_slaves),
};
/* wd_timer3 */
-static struct omap_hwmod omap44xx_wd_timer3_hwmod;
static struct omap_hwmod_irq_info omap44xx_wd_timer3_irqs[] = {
{ .irq = 36 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
};
-static struct omap_hwmod_addr_space omap44xx_wd_timer3_addrs[] = {
+static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
+ .name = "wd_timer3",
+ .class = &omap44xx_wd_timer_hwmod_class,
+ .clkdm_name = "abe_clkdm",
+ .mpu_irqs = omap44xx_wd_timer3_irqs,
+ .main_clk = "wd_timer3_fck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET,
+ .context_offs = OMAP4_RM_ABE_WDT3_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+};
+
+
+/*
+ * interfaces
+ */
+
+static struct omap_hwmod_addr_space omap44xx_c2c_target_fw_addrs[] = {
{
- .pa_start = 0x40130000,
- .pa_end = 0x4013007f,
+ .pa_start = 0x4a204000,
+ .pa_end = 0x4a2040ff,
.flags = ADDR_TYPE_RT
},
{ }
};
-/* l4_abe -> wd_timer3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3 = {
+/* c2c -> c2c_target_fw */
+static struct omap_hwmod_ocp_if omap44xx_c2c__c2c_target_fw = {
+ .master = &omap44xx_c2c_hwmod,
+ .slave = &omap44xx_c2c_target_fw_hwmod,
+ .clk = "div_core_ck",
+ .addr = omap44xx_c2c_target_fw_addrs,
+ .user = OCP_USER_MPU,
+};
+
+/* l4_cfg -> c2c_target_fw */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__c2c_target_fw = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_c2c_target_fw_hwmod,
+ .clk = "l4_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 -> dmm */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__dmm = {
+ .master = &omap44xx_l3_main_1_hwmod,
+ .slave = &omap44xx_dmm_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dmm_addrs[] = {
+ {
+ .pa_start = 0x4e000000,
+ .pa_end = 0x4e0007ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* mpu -> dmm */
+static struct omap_hwmod_ocp_if omap44xx_mpu__dmm = {
+ .master = &omap44xx_mpu_hwmod,
+ .slave = &omap44xx_dmm_hwmod,
+ .clk = "l3_div_ck",
+ .addr = omap44xx_dmm_addrs,
+ .user = OCP_USER_MPU,
+};
+
+/* c2c -> emif_fw */
+static struct omap_hwmod_ocp_if omap44xx_c2c__emif_fw = {
+ .master = &omap44xx_c2c_hwmod,
+ .slave = &omap44xx_emif_fw_hwmod,
+ .clk = "div_core_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dmm -> emif_fw */
+static struct omap_hwmod_ocp_if omap44xx_dmm__emif_fw = {
+ .master = &omap44xx_dmm_hwmod,
+ .slave = &omap44xx_emif_fw_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_emif_fw_addrs[] = {
+ {
+ .pa_start = 0x4a20c000,
+ .pa_end = 0x4a20c0ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> emif_fw */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__emif_fw = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_emif_fw_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_emif_fw_addrs,
+ .user = OCP_USER_MPU,
+};
+
+/* iva -> l3_instr */
+static struct omap_hwmod_ocp_if omap44xx_iva__l3_instr = {
+ .master = &omap44xx_iva_hwmod,
+ .slave = &omap44xx_l3_instr_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_3 -> l3_instr */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_3__l3_instr = {
+ .master = &omap44xx_l3_main_3_hwmod,
+ .slave = &omap44xx_l3_instr_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* ocp_wp_noc -> l3_instr */
+static struct omap_hwmod_ocp_if omap44xx_ocp_wp_noc__l3_instr = {
+ .master = &omap44xx_ocp_wp_noc_hwmod,
+ .slave = &omap44xx_l3_instr_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dsp -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_dsp__l3_main_1 = {
+ .master = &omap44xx_dsp_hwmod,
+ .slave = &omap44xx_l3_main_1_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_dss__l3_main_1 = {
+ .master = &omap44xx_dss_hwmod,
+ .slave = &omap44xx_l3_main_1_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_2 -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_1 = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_l3_main_1_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_1 = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_l3_main_1_hwmod,
+ .clk = "l4_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc1 -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_mmc1__l3_main_1 = {
+ .master = &omap44xx_mmc1_hwmod,
+ .slave = &omap44xx_l3_main_1_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc2 -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_mmc2__l3_main_1 = {
+ .master = &omap44xx_mmc2_hwmod,
+ .slave = &omap44xx_l3_main_1_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_l3_main_1_addrs[] = {
+ {
+ .pa_start = 0x44000000,
+ .pa_end = 0x44000fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* mpu -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_mpu__l3_main_1 = {
+ .master = &omap44xx_mpu_hwmod,
+ .slave = &omap44xx_l3_main_1_hwmod,
+ .clk = "l3_div_ck",
+ .addr = omap44xx_l3_main_1_addrs,
+ .user = OCP_USER_MPU,
+};
+
+/* c2c_target_fw -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_c2c_target_fw__l3_main_2 = {
+ .master = &omap44xx_c2c_target_fw_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* debugss -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_debugss__l3_main_2 = {
+ .master = &omap44xx_debugss_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "dbgclk_mux_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_dma_system__l3_main_2 = {
+ .master = &omap44xx_dma_system_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* fdif -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_fdif__l3_main_2 = {
+ .master = &omap44xx_fdif_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpu -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_gpu__l3_main_2 = {
+ .master = &omap44xx_gpu_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* hsi -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_hsi__l3_main_2 = {
+ .master = &omap44xx_hsi_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* ipu -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_ipu__l3_main_2 = {
+ .master = &omap44xx_ipu_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* iss -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_iss__l3_main_2 = {
+ .master = &omap44xx_iss_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* iva -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_iva__l3_main_2 = {
+ .master = &omap44xx_iva_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_l3_main_2_addrs[] = {
+ {
+ .pa_start = 0x44800000,
+ .pa_end = 0x44801fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_main_1 -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
+ .master = &omap44xx_l3_main_1_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .addr = omap44xx_l3_main_2_addrs,
+ .user = OCP_USER_MPU,
+};
+
+/* l4_cfg -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l4_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* usb_host_fs -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_usb_host_fs__l3_main_2 = {
+ .master = &omap44xx_usb_host_fs_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* usb_host_hs -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_usb_host_hs__l3_main_2 = {
+ .master = &omap44xx_usb_host_hs_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* usb_otg_hs -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_usb_otg_hs__l3_main_2 = {
+ .master = &omap44xx_usb_otg_hs_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_l3_main_3_addrs[] = {
+ {
+ .pa_start = 0x45000000,
+ .pa_end = 0x45000fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_main_1 -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_3 = {
+ .master = &omap44xx_l3_main_1_hwmod,
+ .slave = &omap44xx_l3_main_3_hwmod,
+ .clk = "l3_div_ck",
+ .addr = omap44xx_l3_main_3_addrs,
+ .user = OCP_USER_MPU,
+};
+
+/* l3_main_2 -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_3 = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_l3_main_3_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_3 = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_l3_main_3_hwmod,
+ .clk = "l4_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* aess -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_aess__l4_abe = {
+ .master = &omap44xx_aess_hwmod,
+ .slave = &omap44xx_l4_abe_hwmod,
+ .clk = "ocp_abe_iclk",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dsp -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_dsp__l4_abe = {
+ .master = &omap44xx_dsp_hwmod,
+ .slave = &omap44xx_l4_abe_hwmod,
+ .clk = "ocp_abe_iclk",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_abe = {
+ .master = &omap44xx_l3_main_1_hwmod,
+ .slave = &omap44xx_l4_abe_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_mpu__l4_abe = {
+ .master = &omap44xx_mpu_hwmod,
+ .slave = &omap44xx_l4_abe_hwmod,
+ .clk = "ocp_abe_iclk",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 -> l4_cfg */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_cfg = {
+ .master = &omap44xx_l3_main_1_hwmod,
+ .slave = &omap44xx_l4_cfg_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_2 -> l4_per */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l4_per = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_l4_per_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l4_wkup */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l4_wkup = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_l4_wkup_hwmod,
+ .clk = "l4_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> mpu_private */
+static struct omap_hwmod_ocp_if omap44xx_mpu__mpu_private = {
+ .master = &omap44xx_mpu_hwmod,
+ .slave = &omap44xx_mpu_private_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_ocp_wp_noc_addrs[] = {
+ {
+ .pa_start = 0x4a102000,
+ .pa_end = 0x4a10207f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> ocp_wp_noc */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__ocp_wp_noc = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_ocp_wp_noc_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_ocp_wp_noc_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_aess_addrs[] = {
+ {
+ .pa_start = 0x401f1000,
+ .pa_end = 0x401f13ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> aess */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__aess = {
.master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_wd_timer3_hwmod,
+ .slave = &omap44xx_aess_hwmod,
.clk = "ocp_abe_iclk",
- .addr = omap44xx_wd_timer3_addrs,
+ .addr = omap44xx_aess_addrs,
.user = OCP_USER_MPU,
};
-static struct omap_hwmod_addr_space omap44xx_wd_timer3_dma_addrs[] = {
+static struct omap_hwmod_addr_space omap44xx_aess_dma_addrs[] = {
{
- .pa_start = 0x49030000,
- .pa_end = 0x4903007f,
+ .pa_start = 0x490f1000,
+ .pa_end = 0x490f13ff,
.flags = ADDR_TYPE_RT
},
{ }
};
-/* l4_abe -> wd_timer3 (dma) */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3_dma = {
+/* l4_abe -> aess (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__aess_dma = {
.master = &omap44xx_l4_abe_hwmod,
- .slave = &omap44xx_wd_timer3_hwmod,
+ .slave = &omap44xx_aess_hwmod,
.clk = "ocp_abe_iclk",
- .addr = omap44xx_wd_timer3_dma_addrs,
+ .addr = omap44xx_aess_dma_addrs,
.user = OCP_USER_SDMA,
};
-/* wd_timer3 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_wd_timer3_slaves[] = {
- &omap44xx_l4_abe__wd_timer3,
- &omap44xx_l4_abe__wd_timer3_dma,
+/* l3_main_2 -> c2c */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__c2c = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_c2c_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
};
-static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
- .name = "wd_timer3",
- .class = &omap44xx_wd_timer_hwmod_class,
- .clkdm_name = "abe_clkdm",
- .mpu_irqs = omap44xx_wd_timer3_irqs,
- .main_clk = "wd_timer3_fck",
- .prcm = {
- .omap4 = {
- .clkctrl_offs = OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET,
- .context_offs = OMAP4_RM_ABE_WDT3_CONTEXT_OFFSET,
- .modulemode = MODULEMODE_SWCTRL,
- },
+static struct omap_hwmod_addr_space omap44xx_counter_32k_addrs[] = {
+ {
+ .pa_start = 0x4a304000,
+ .pa_end = 0x4a30401f,
+ .flags = ADDR_TYPE_RT
},
- .slaves = omap44xx_wd_timer3_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_wd_timer3_slaves),
+ { }
};
-/*
- * 'usb_host_hs' class
- * high-speed multi-port usb host controller
- */
-static struct omap_hwmod_ocp_if omap44xx_usb_host_hs__l3_main_2 = {
- .master = &omap44xx_usb_host_hs_hwmod,
- .slave = &omap44xx_l3_main_2_hwmod,
+/* l4_wkup -> counter_32k */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__counter_32k = {
+ .master = &omap44xx_l4_wkup_hwmod,
+ .slave = &omap44xx_counter_32k_hwmod,
+ .clk = "l4_wkup_clk_mux_ck",
+ .addr = omap44xx_counter_32k_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_ctrl_module_core_addrs[] = {
+ {
+ .pa_start = 0x4a002000,
+ .pa_end = 0x4a0027ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> ctrl_module_core */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__ctrl_module_core = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_ctrl_module_core_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_ctrl_module_core_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_ctrl_module_pad_core_addrs[] = {
+ {
+ .pa_start = 0x4a100000,
+ .pa_end = 0x4a1007ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> ctrl_module_pad_core */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__ctrl_module_pad_core = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_ctrl_module_pad_core_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_ctrl_module_pad_core_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_ctrl_module_wkup_addrs[] = {
+ {
+ .pa_start = 0x4a30c000,
+ .pa_end = 0x4a30c7ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_wkup -> ctrl_module_wkup */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__ctrl_module_wkup = {
+ .master = &omap44xx_l4_wkup_hwmod,
+ .slave = &omap44xx_ctrl_module_wkup_hwmod,
+ .clk = "l4_wkup_clk_mux_ck",
+ .addr = omap44xx_ctrl_module_wkup_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_ctrl_module_pad_wkup_addrs[] = {
+ {
+ .pa_start = 0x4a31e000,
+ .pa_end = 0x4a31e7ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_wkup -> ctrl_module_pad_wkup */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__ctrl_module_pad_wkup = {
+ .master = &omap44xx_l4_wkup_hwmod,
+ .slave = &omap44xx_ctrl_module_pad_wkup_hwmod,
+ .clk = "l4_wkup_clk_mux_ck",
+ .addr = omap44xx_ctrl_module_pad_wkup_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_debugss_addrs[] = {
+ {
+ .pa_start = 0x54160000,
+ .pa_end = 0x54167fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_instr -> debugss */
+static struct omap_hwmod_ocp_if omap44xx_l3_instr__debugss = {
+ .master = &omap44xx_l3_instr_hwmod,
+ .slave = &omap44xx_debugss_hwmod,
.clk = "l3_div_ck",
+ .addr = omap44xx_debugss_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-static struct omap_hwmod_class_sysconfig omap44xx_usb_host_hs_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE |
- SYSC_HAS_SOFTRESET),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
- SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
- MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
- .sysc_fields = &omap_hwmod_sysc_type2,
+static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = {
+ {
+ .pa_start = 0x4a056000,
+ .pa_end = 0x4a056fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
};
-static struct omap_hwmod_class omap44xx_usb_host_hs_hwmod_class = {
- .name = "usb_host_hs",
- .sysc = &omap44xx_usb_host_hs_sysc,
+/* l4_cfg -> dma_system */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dma_system = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_dma_system_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_dma_system_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
};
-static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_masters[] = {
- &omap44xx_usb_host_hs__l3_main_2,
+static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x4012e000,
+ .pa_end = 0x4012e07f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> dmic */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_dmic_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_dmic_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dmic_dma_addrs[] = {
+ {
+ .name = "dma",
+ .pa_start = 0x4902e000,
+ .pa_end = 0x4902e07f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> dmic (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic_dma = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_dmic_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_dmic_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+/* dsp -> iva */
+static struct omap_hwmod_ocp_if omap44xx_dsp__iva = {
+ .master = &omap44xx_dsp_hwmod,
+ .slave = &omap44xx_iva_hwmod,
+ .clk = "dpll_iva_m5x2_ck",
+ .user = OCP_USER_DSP,
+};
+
+/* dsp -> sl2if */
+static struct omap_hwmod_ocp_if omap44xx_dsp__sl2if = {
+ .master = &omap44xx_dsp_hwmod,
+ .slave = &omap44xx_sl2if_hwmod,
+ .clk = "dpll_iva_m5x2_ck",
+ .user = OCP_USER_DSP,
+};
+
+/* l4_cfg -> dsp */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dsp = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_dsp_hwmod,
+ .clk = "l4_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = {
+ {
+ .pa_start = 0x58000000,
+ .pa_end = 0x5800007f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_main_2 -> dss */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_dss_hwmod,
+ .clk = "dss_fck",
+ .addr = omap44xx_dss_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_addrs[] = {
+ {
+ .pa_start = 0x48040000,
+ .pa_end = 0x4804007f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> dss */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_dss_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_dss_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
+ {
+ .pa_start = 0x58001000,
+ .pa_end = 0x58001fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_main_2 -> dss_dispc */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_dss_dispc_hwmod,
+ .clk = "dss_fck",
+ .addr = omap44xx_dss_dispc_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dispc_addrs[] = {
+ {
+ .pa_start = 0x48041000,
+ .pa_end = 0x48041fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> dss_dispc */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dispc = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_dss_dispc_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_dss_dispc_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
+ {
+ .pa_start = 0x58004000,
+ .pa_end = 0x580041ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_main_2 -> dss_dsi1 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_dss_dsi1_hwmod,
+ .clk = "dss_fck",
+ .addr = omap44xx_dss_dsi1_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dsi1_addrs[] = {
+ {
+ .pa_start = 0x48044000,
+ .pa_end = 0x480441ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> dss_dsi1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi1 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_dss_dsi1_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_dss_dsi1_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
+ {
+ .pa_start = 0x58005000,
+ .pa_end = 0x580051ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_main_2 -> dss_dsi2 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_dss_dsi2_hwmod,
+ .clk = "dss_fck",
+ .addr = omap44xx_dss_dsi2_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dsi2_addrs[] = {
+ {
+ .pa_start = 0x48045000,
+ .pa_end = 0x480451ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> dss_dsi2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi2 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_dss_dsi2_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_dss_dsi2_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
+ {
+ .pa_start = 0x58006000,
+ .pa_end = 0x58006fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_main_2 -> dss_hdmi */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_dss_hdmi_hwmod,
+ .clk = "dss_fck",
+ .addr = omap44xx_dss_hdmi_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_hdmi_addrs[] = {
+ {
+ .pa_start = 0x48046000,
+ .pa_end = 0x48046fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> dss_hdmi */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_hdmi = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_dss_hdmi_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_dss_hdmi_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
+ {
+ .pa_start = 0x58002000,
+ .pa_end = 0x580020ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_main_2 -> dss_rfbi */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_dss_rfbi_hwmod,
+ .clk = "dss_fck",
+ .addr = omap44xx_dss_rfbi_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_rfbi_addrs[] = {
+ {
+ .pa_start = 0x48042000,
+ .pa_end = 0x480420ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> dss_rfbi */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_rfbi = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_dss_rfbi_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_dss_rfbi_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_venc_dma_addrs[] = {
+ {
+ .pa_start = 0x58003000,
+ .pa_end = 0x580030ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_main_2 -> dss_venc */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_dss_venc_hwmod,
+ .clk = "dss_fck",
+ .addr = omap44xx_dss_venc_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_venc_addrs[] = {
+ {
+ .pa_start = 0x48043000,
+ .pa_end = 0x480430ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> dss_venc */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_venc = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_dss_venc_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_dss_venc_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_elm_addrs[] = {
+ {
+ .pa_start = 0x48078000,
+ .pa_end = 0x48078fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> elm */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__elm = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_elm_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_elm_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_emif1_addrs[] = {
+ {
+ .pa_start = 0x4c000000,
+ .pa_end = 0x4c0000ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* emif_fw -> emif1 */
+static struct omap_hwmod_ocp_if omap44xx_emif_fw__emif1 = {
+ .master = &omap44xx_emif_fw_hwmod,
+ .slave = &omap44xx_emif1_hwmod,
+ .clk = "l3_div_ck",
+ .addr = omap44xx_emif1_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_emif2_addrs[] = {
+ {
+ .pa_start = 0x4d000000,
+ .pa_end = 0x4d0000ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* emif_fw -> emif2 */
+static struct omap_hwmod_ocp_if omap44xx_emif_fw__emif2 = {
+ .master = &omap44xx_emif_fw_hwmod,
+ .slave = &omap44xx_emif2_hwmod,
+ .clk = "l3_div_ck",
+ .addr = omap44xx_emif2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_fdif_addrs[] = {
+ {
+ .pa_start = 0x4a10a000,
+ .pa_end = 0x4a10a1ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> fdif */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__fdif = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_fdif_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_fdif_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio1_addrs[] = {
+ {
+ .pa_start = 0x4a310000,
+ .pa_end = 0x4a3101ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_wkup -> gpio1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__gpio1 = {
+ .master = &omap44xx_l4_wkup_hwmod,
+ .slave = &omap44xx_gpio1_hwmod,
+ .clk = "l4_wkup_clk_mux_ck",
+ .addr = omap44xx_gpio1_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio2_addrs[] = {
+ {
+ .pa_start = 0x48055000,
+ .pa_end = 0x480551ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> gpio2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio2 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_gpio2_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_gpio2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio3_addrs[] = {
+ {
+ .pa_start = 0x48057000,
+ .pa_end = 0x480571ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> gpio3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio3 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_gpio3_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_gpio3_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio4_addrs[] = {
+ {
+ .pa_start = 0x48059000,
+ .pa_end = 0x480591ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> gpio4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio4 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_gpio4_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_gpio4_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio5_addrs[] = {
+ {
+ .pa_start = 0x4805b000,
+ .pa_end = 0x4805b1ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> gpio5 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio5 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_gpio5_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_gpio5_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio6_addrs[] = {
+ {
+ .pa_start = 0x4805d000,
+ .pa_end = 0x4805d1ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> gpio6 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio6 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_gpio6_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_gpio6_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpmc_addrs[] = {
+ {
+ .pa_start = 0x50000000,
+ .pa_end = 0x500003ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_main_2 -> gpmc */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__gpmc = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_gpmc_hwmod,
+ .clk = "l3_div_ck",
+ .addr = omap44xx_gpmc_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpu_addrs[] = {
+ {
+ .pa_start = 0x56000000,
+ .pa_end = 0x5600ffff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_main_2 -> gpu */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__gpu = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_gpu_hwmod,
+ .clk = "l3_div_ck",
+ .addr = omap44xx_gpu_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_hdq1w_addrs[] = {
+ {
+ .pa_start = 0x480b2000,
+ .pa_end = 0x480b201f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> hdq1w */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__hdq1w = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_hdq1w_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_hdq1w_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_hsi_addrs[] = {
+ {
+ .pa_start = 0x4a058000,
+ .pa_end = 0x4a05bfff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> hsi */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__hsi = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_hsi_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_hsi_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_i2c1_addrs[] = {
+ {
+ .pa_start = 0x48070000,
+ .pa_end = 0x480700ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> i2c1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c1 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_i2c1_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_i2c1_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_i2c2_addrs[] = {
+ {
+ .pa_start = 0x48072000,
+ .pa_end = 0x480720ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> i2c2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c2 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_i2c2_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_i2c2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_i2c3_addrs[] = {
+ {
+ .pa_start = 0x48060000,
+ .pa_end = 0x480600ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> i2c3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c3 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_i2c3_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_i2c3_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_i2c4_addrs[] = {
+ {
+ .pa_start = 0x48350000,
+ .pa_end = 0x483500ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> i2c4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c4 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_i2c4_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_i2c4_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_2 -> ipu */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__ipu = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_ipu_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_iss_addrs[] = {
+ {
+ .pa_start = 0x52000000,
+ .pa_end = 0x520000ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_main_2 -> iss */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_iss_hwmod,
+ .clk = "l3_div_ck",
+ .addr = omap44xx_iss_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* iva -> sl2if */
+static struct omap_hwmod_ocp_if omap44xx_iva__sl2if = {
+ .master = &omap44xx_iva_hwmod,
+ .slave = &omap44xx_sl2if_hwmod,
+ .clk = "dpll_iva_m5x2_ck",
+ .user = OCP_USER_IVA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_iva_addrs[] = {
+ {
+ .pa_start = 0x5a000000,
+ .pa_end = 0x5a07ffff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l3_main_2 -> iva */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iva = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_iva_hwmod,
+ .clk = "l3_div_ck",
+ .addr = omap44xx_iva_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_kbd_addrs[] = {
+ {
+ .pa_start = 0x4a31c000,
+ .pa_end = 0x4a31c07f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_wkup -> kbd */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__kbd = {
+ .master = &omap44xx_l4_wkup_hwmod,
+ .slave = &omap44xx_kbd_hwmod,
+ .clk = "l4_wkup_clk_mux_ck",
+ .addr = omap44xx_kbd_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mailbox_addrs[] = {
+ {
+ .pa_start = 0x4a0f4000,
+ .pa_end = 0x4a0f41ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> mailbox */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__mailbox = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_mailbox_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_mailbox_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcasp_addrs[] = {
+ {
+ .pa_start = 0x40128000,
+ .pa_end = 0x401283ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> mcasp */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcasp = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_mcasp_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_mcasp_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcasp_dma_addrs[] = {
+ {
+ .pa_start = 0x49028000,
+ .pa_end = 0x490283ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> mcasp (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcasp_dma = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_mcasp_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_mcasp_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp1_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x40122000,
+ .pa_end = 0x401220ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> mcbsp1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp1 = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_mcbsp1_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_mcbsp1_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp1_dma_addrs[] = {
+ {
+ .name = "dma",
+ .pa_start = 0x49022000,
+ .pa_end = 0x490220ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> mcbsp1 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp1_dma = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_mcbsp1_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_mcbsp1_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp2_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x40124000,
+ .pa_end = 0x401240ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> mcbsp2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp2 = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_mcbsp2_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_mcbsp2_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp2_dma_addrs[] = {
+ {
+ .name = "dma",
+ .pa_start = 0x49024000,
+ .pa_end = 0x490240ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> mcbsp2 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp2_dma = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_mcbsp2_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_mcbsp2_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp3_addrs[] = {
+ {
+ .name = "mpu",
+ .pa_start = 0x40126000,
+ .pa_end = 0x401260ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> mcbsp3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp3 = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_mcbsp3_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_mcbsp3_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp3_dma_addrs[] = {
+ {
+ .name = "dma",
+ .pa_start = 0x49026000,
+ .pa_end = 0x490260ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> mcbsp3 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp3_dma = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_mcbsp3_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_mcbsp3_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp4_addrs[] = {
+ {
+ .pa_start = 0x48096000,
+ .pa_end = 0x480960ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mcbsp4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcbsp4 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_mcbsp4_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_mcbsp4_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcpdm_addrs[] = {
+ {
+ .pa_start = 0x40132000,
+ .pa_end = 0x4013207f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> mcpdm */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_mcpdm_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_mcpdm_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcpdm_dma_addrs[] = {
+ {
+ .pa_start = 0x49032000,
+ .pa_end = 0x4903207f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> mcpdm (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm_dma = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_mcpdm_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_mcpdm_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcspi1_addrs[] = {
+ {
+ .pa_start = 0x48098000,
+ .pa_end = 0x480981ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mcspi1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi1 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_mcspi1_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_mcspi1_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcspi2_addrs[] = {
+ {
+ .pa_start = 0x4809a000,
+ .pa_end = 0x4809a1ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mcspi2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi2 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_mcspi2_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_mcspi2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcspi3_addrs[] = {
+ {
+ .pa_start = 0x480b8000,
+ .pa_end = 0x480b81ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mcspi3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi3 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_mcspi3_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_mcspi3_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcspi4_addrs[] = {
+ {
+ .pa_start = 0x480ba000,
+ .pa_end = 0x480ba1ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mcspi4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi4 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_mcspi4_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_mcspi4_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc1_addrs[] = {
+ {
+ .pa_start = 0x4809c000,
+ .pa_end = 0x4809c3ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mmc1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc1 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_mmc1_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_mmc1_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc2_addrs[] = {
+ {
+ .pa_start = 0x480b4000,
+ .pa_end = 0x480b43ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mmc2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc2 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_mmc2_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_mmc2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc3_addrs[] = {
+ {
+ .pa_start = 0x480ad000,
+ .pa_end = 0x480ad3ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mmc3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc3 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_mmc3_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_mmc3_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc4_addrs[] = {
+ {
+ .pa_start = 0x480d1000,
+ .pa_end = 0x480d13ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mmc4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc4 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_mmc4_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_mmc4_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc5_addrs[] = {
+ {
+ .pa_start = 0x480d5000,
+ .pa_end = 0x480d53ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> mmc5 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc5 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_mmc5_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_mmc5_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_2 -> ocmc_ram */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__ocmc_ram = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_ocmc_ram_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> ocp2scp_usb_phy */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__ocp2scp_usb_phy = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_ocp2scp_usb_phy_hwmod,
+ .clk = "l4_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_prcm_mpu_addrs[] = {
+ {
+ .pa_start = 0x48243000,
+ .pa_end = 0x48243fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* mpu_private -> prcm_mpu */
+static struct omap_hwmod_ocp_if omap44xx_mpu_private__prcm_mpu = {
+ .master = &omap44xx_mpu_private_hwmod,
+ .slave = &omap44xx_prcm_mpu_hwmod,
+ .clk = "l3_div_ck",
+ .addr = omap44xx_prcm_mpu_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_cm_core_aon_addrs[] = {
+ {
+ .pa_start = 0x4a004000,
+ .pa_end = 0x4a004fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_wkup -> cm_core_aon */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__cm_core_aon = {
+ .master = &omap44xx_l4_wkup_hwmod,
+ .slave = &omap44xx_cm_core_aon_hwmod,
+ .clk = "l4_wkup_clk_mux_ck",
+ .addr = omap44xx_cm_core_aon_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_cm_core_addrs[] = {
+ {
+ .pa_start = 0x4a008000,
+ .pa_end = 0x4a009fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> cm_core */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__cm_core = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_cm_core_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_cm_core_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_prm_addrs[] = {
+ {
+ .pa_start = 0x4a306000,
+ .pa_end = 0x4a307fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_wkup -> prm */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__prm = {
+ .master = &omap44xx_l4_wkup_hwmod,
+ .slave = &omap44xx_prm_hwmod,
+ .clk = "l4_wkup_clk_mux_ck",
+ .addr = omap44xx_prm_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_scrm_addrs[] = {
+ {
+ .pa_start = 0x4a30a000,
+ .pa_end = 0x4a30a7ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_wkup -> scrm */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__scrm = {
+ .master = &omap44xx_l4_wkup_hwmod,
+ .slave = &omap44xx_scrm_hwmod,
+ .clk = "l4_wkup_clk_mux_ck",
+ .addr = omap44xx_scrm_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_2 -> sl2if */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__sl2if = {
+ .master = &omap44xx_l3_main_2_hwmod,
+ .slave = &omap44xx_sl2if_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_slimbus1_addrs[] = {
+ {
+ .pa_start = 0x4012c000,
+ .pa_end = 0x4012c3ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> slimbus1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__slimbus1 = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_slimbus1_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_slimbus1_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_slimbus1_dma_addrs[] = {
+ {
+ .pa_start = 0x4902c000,
+ .pa_end = 0x4902c3ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> slimbus1 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__slimbus1_dma = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_slimbus1_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_slimbus1_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_slimbus2_addrs[] = {
+ {
+ .pa_start = 0x48076000,
+ .pa_end = 0x480763ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> slimbus2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__slimbus2 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_slimbus2_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_slimbus2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_smartreflex_core_addrs[] = {
+ {
+ .pa_start = 0x4a0dd000,
+ .pa_end = 0x4a0dd03f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> smartreflex_core */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_core = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_smartreflex_core_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_smartreflex_core_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_smartreflex_iva_addrs[] = {
+ {
+ .pa_start = 0x4a0db000,
+ .pa_end = 0x4a0db03f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> smartreflex_iva */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_iva = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_smartreflex_iva_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_smartreflex_iva_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_smartreflex_mpu_addrs[] = {
+ {
+ .pa_start = 0x4a0d9000,
+ .pa_end = 0x4a0d903f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> smartreflex_mpu */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_mpu = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_smartreflex_mpu_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_smartreflex_mpu_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_spinlock_addrs[] = {
+ {
+ .pa_start = 0x4a0f6000,
+ .pa_end = 0x4a0f6fff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> spinlock */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__spinlock = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_spinlock_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_spinlock_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer1_addrs[] = {
+ {
+ .pa_start = 0x4a318000,
+ .pa_end = 0x4a31807f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_wkup -> timer1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__timer1 = {
+ .master = &omap44xx_l4_wkup_hwmod,
+ .slave = &omap44xx_timer1_hwmod,
+ .clk = "l4_wkup_clk_mux_ck",
+ .addr = omap44xx_timer1_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer2_addrs[] = {
+ {
+ .pa_start = 0x48032000,
+ .pa_end = 0x4803207f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer2 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_timer2_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_timer2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer3_addrs[] = {
+ {
+ .pa_start = 0x48034000,
+ .pa_end = 0x4803407f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer3 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_timer3_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_timer3_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer4_addrs[] = {
+ {
+ .pa_start = 0x48036000,
+ .pa_end = 0x4803607f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer4 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_timer4_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_timer4_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer5_addrs[] = {
+ {
+ .pa_start = 0x40138000,
+ .pa_end = 0x4013807f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> timer5 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer5 = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_timer5_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_timer5_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer5_dma_addrs[] = {
+ {
+ .pa_start = 0x49038000,
+ .pa_end = 0x4903807f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> timer5 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer5_dma = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_timer5_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_timer5_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer6_addrs[] = {
+ {
+ .pa_start = 0x4013a000,
+ .pa_end = 0x4013a07f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> timer6 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer6 = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_timer6_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_timer6_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer6_dma_addrs[] = {
+ {
+ .pa_start = 0x4903a000,
+ .pa_end = 0x4903a07f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> timer6 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer6_dma = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_timer6_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_timer6_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer7_addrs[] = {
+ {
+ .pa_start = 0x4013c000,
+ .pa_end = 0x4013c07f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> timer7 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer7 = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_timer7_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_timer7_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer7_dma_addrs[] = {
+ {
+ .pa_start = 0x4903c000,
+ .pa_end = 0x4903c07f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> timer7 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer7_dma = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_timer7_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_timer7_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer8_addrs[] = {
+ {
+ .pa_start = 0x4013e000,
+ .pa_end = 0x4013e07f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> timer8 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer8 = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_timer8_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_timer8_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer8_dma_addrs[] = {
+ {
+ .pa_start = 0x4903e000,
+ .pa_end = 0x4903e07f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> timer8 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer8_dma = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_timer8_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_timer8_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer9_addrs[] = {
+ {
+ .pa_start = 0x4803e000,
+ .pa_end = 0x4803e07f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer9 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer9 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_timer9_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_timer9_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer10_addrs[] = {
+ {
+ .pa_start = 0x48086000,
+ .pa_end = 0x4808607f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer10 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer10 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_timer10_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_timer10_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer11_addrs[] = {
+ {
+ .pa_start = 0x48088000,
+ .pa_end = 0x4808807f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> timer11 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer11 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_timer11_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_timer11_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart1_addrs[] = {
+ {
+ .pa_start = 0x4806a000,
+ .pa_end = 0x4806a0ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> uart1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart1 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_uart1_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_uart1_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart2_addrs[] = {
+ {
+ .pa_start = 0x4806c000,
+ .pa_end = 0x4806c0ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> uart2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart2 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_uart2_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_uart2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart3_addrs[] = {
+ {
+ .pa_start = 0x48020000,
+ .pa_end = 0x480200ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> uart3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart3 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_uart3_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_uart3_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart4_addrs[] = {
+ {
+ .pa_start = 0x4806e000,
+ .pa_end = 0x4806e0ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_per -> uart4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart4 = {
+ .master = &omap44xx_l4_per_hwmod,
+ .slave = &omap44xx_uart4_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_uart4_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_usb_host_fs_addrs[] = {
+ {
+ .pa_start = 0x4a0a9000,
+ .pa_end = 0x4a0a93ff,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_cfg -> usb_host_fs */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_host_fs = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_usb_host_fs_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_usb_host_fs_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
};
static struct omap_hwmod_addr_space omap44xx_usb_host_hs_addrs[] = {
@@ -5382,12 +5881,7 @@ static struct omap_hwmod_addr_space omap44xx_usb_host_hs_addrs[] = {
{}
};
-static struct omap_hwmod_irq_info omap44xx_usb_host_hs_irqs[] = {
- { .name = "ohci-irq", .irq = 76 + OMAP44XX_IRQ_GIC_START },
- { .name = "ehci-irq", .irq = 77 + OMAP44XX_IRQ_GIC_START },
- { .irq = -1 }
-};
-
+/* l4_cfg -> usb_host_hs */
static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_host_hs = {
.master = &omap44xx_l4_cfg_hwmod,
.slave = &omap44xx_usb_host_hs_hwmod,
@@ -5396,100 +5890,22 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_host_hs = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_slaves[] = {
- &omap44xx_l4_cfg__usb_host_hs,
-};
-
-static struct omap_hwmod omap44xx_usb_host_hs_hwmod = {
- .name = "usb_host_hs",
- .class = &omap44xx_usb_host_hs_hwmod_class,
- .clkdm_name = "l3_init_clkdm",
- .main_clk = "usb_host_hs_fck",
- .prcm = {
- .omap4 = {
- .clkctrl_offs = OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET,
- .context_offs = OMAP4_RM_L3INIT_USB_HOST_CONTEXT_OFFSET,
- .modulemode = MODULEMODE_SWCTRL,
- },
+static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {
+ {
+ .pa_start = 0x4a0ab000,
+ .pa_end = 0x4a0ab003,
+ .flags = ADDR_TYPE_RT
},
- .mpu_irqs = omap44xx_usb_host_hs_irqs,
- .slaves = omap44xx_usb_host_hs_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_slaves),
- .masters = omap44xx_usb_host_hs_masters,
- .masters_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_masters),
-
- /*
- * Errata: USBHOST Configured In Smart-Idle Can Lead To a Deadlock
- * id: i660
- *
- * Description:
- * In the following configuration :
- * - USBHOST module is set to smart-idle mode
- * - PRCM asserts idle_req to the USBHOST module ( This typically
- * happens when the system is going to a low power mode : all ports
- * have been suspended, the master part of the USBHOST module has
- * entered the standby state, and SW has cut the functional clocks)
- * - an USBHOST interrupt occurs before the module is able to answer
- * idle_ack, typically a remote wakeup IRQ.
- * Then the USB HOST module will enter a deadlock situation where it
- * is no more accessible nor functional.
- *
- * Workaround:
- * Don't use smart idle; use only force idle, hence HWMOD_SWSUP_SIDLE
- */
-
- /*
- * Errata: USB host EHCI may stall when entering smart-standby mode
- * Id: i571
- *
- * Description:
- * When the USBHOST module is set to smart-standby mode, and when it is
- * ready to enter the standby state (i.e. all ports are suspended and
- * all attached devices are in suspend mode), then it can wrongly assert
- * the Mstandby signal too early while there are still some residual OCP
- * transactions ongoing. If this condition occurs, the internal state
- * machine may go to an undefined state and the USB link may be stuck
- * upon the next resume.
- *
- * Workaround:
- * Don't use smart standby; use only force standby,
- * hence HWMOD_SWSUP_MSTANDBY
- */
-
- /*
- * During system boot; If the hwmod framework resets the module
- * the module will have smart idle settings; which can lead to deadlock
- * (above Errata Id:i660); so, dont reset the module during boot;
- * Use HWMOD_INIT_NO_RESET.
- */
-
- .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
- HWMOD_INIT_NO_RESET,
-};
-
-/*
- * 'usb_tll_hs' class
- * usb_tll_hs module is the adapter on the usb_host_hs ports
- */
-static struct omap_hwmod_class_sysconfig omap44xx_usb_tll_hs_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
- SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap44xx_usb_tll_hs_hwmod_class = {
- .name = "usb_tll_hs",
- .sysc = &omap44xx_usb_tll_hs_sysc,
+ { }
};
-static struct omap_hwmod_irq_info omap44xx_usb_tll_hs_irqs[] = {
- { .name = "tll-irq", .irq = 78 + OMAP44XX_IRQ_GIC_START },
- { .irq = -1 }
+/* l4_cfg -> usb_otg_hs */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_otg_hs = {
+ .master = &omap44xx_l4_cfg_hwmod,
+ .slave = &omap44xx_usb_otg_hs_hwmod,
+ .clk = "l4_div_ck",
+ .addr = omap44xx_usb_otg_hs_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
};
static struct omap_hwmod_addr_space omap44xx_usb_tll_hs_addrs[] = {
@@ -5502,6 +5918,7 @@ static struct omap_hwmod_addr_space omap44xx_usb_tll_hs_addrs[] = {
{}
};
+/* l4_cfg -> usb_tll_hs */
static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_tll_hs = {
.master = &omap44xx_l4_cfg_hwmod,
.slave = &omap44xx_usb_tll_hs_hwmod,
@@ -5510,181 +5927,223 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_tll_hs = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-static struct omap_hwmod_ocp_if *omap44xx_usb_tll_hs_slaves[] = {
- &omap44xx_l4_cfg__usb_tll_hs,
+static struct omap_hwmod_addr_space omap44xx_wd_timer2_addrs[] = {
+ {
+ .pa_start = 0x4a314000,
+ .pa_end = 0x4a31407f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
};
-static struct omap_hwmod omap44xx_usb_tll_hs_hwmod = {
- .name = "usb_tll_hs",
- .class = &omap44xx_usb_tll_hs_hwmod_class,
- .clkdm_name = "l3_init_clkdm",
- .main_clk = "usb_tll_hs_ick",
- .prcm = {
- .omap4 = {
- .clkctrl_offs = OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET,
- .context_offs = OMAP4_RM_L3INIT_USB_TLL_CONTEXT_OFFSET,
- .modulemode = MODULEMODE_HWCTRL,
- },
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__wd_timer2 = {
+ .master = &omap44xx_l4_wkup_hwmod,
+ .slave = &omap44xx_wd_timer2_hwmod,
+ .clk = "l4_wkup_clk_mux_ck",
+ .addr = omap44xx_wd_timer2_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_wd_timer3_addrs[] = {
+ {
+ .pa_start = 0x40130000,
+ .pa_end = 0x4013007f,
+ .flags = ADDR_TYPE_RT
},
- .mpu_irqs = omap44xx_usb_tll_hs_irqs,
- .slaves = omap44xx_usb_tll_hs_slaves,
- .slaves_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_slaves),
+ { }
};
-static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
-
- /* dmm class */
- &omap44xx_dmm_hwmod,
-
- /* emif_fw class */
- &omap44xx_emif_fw_hwmod,
-
- /* l3 class */
- &omap44xx_l3_instr_hwmod,
- &omap44xx_l3_main_1_hwmod,
- &omap44xx_l3_main_2_hwmod,
- &omap44xx_l3_main_3_hwmod,
-
- /* l4 class */
- &omap44xx_l4_abe_hwmod,
- &omap44xx_l4_cfg_hwmod,
- &omap44xx_l4_per_hwmod,
- &omap44xx_l4_wkup_hwmod,
-
- /* mpu_bus class */
- &omap44xx_mpu_private_hwmod,
-
- /* aess class */
-/* &omap44xx_aess_hwmod, */
-
- /* bandgap class */
- &omap44xx_bandgap_hwmod,
-
- /* counter class */
-/* &omap44xx_counter_32k_hwmod, */
-
- /* dma class */
- &omap44xx_dma_system_hwmod,
-
- /* dmic class */
- &omap44xx_dmic_hwmod,
-
- /* dsp class */
- &omap44xx_dsp_hwmod,
- &omap44xx_dsp_c0_hwmod,
-
- /* dss class */
- &omap44xx_dss_hwmod,
- &omap44xx_dss_dispc_hwmod,
- &omap44xx_dss_dsi1_hwmod,
- &omap44xx_dss_dsi2_hwmod,
- &omap44xx_dss_hdmi_hwmod,
- &omap44xx_dss_rfbi_hwmod,
- &omap44xx_dss_venc_hwmod,
-
- /* gpio class */
- &omap44xx_gpio1_hwmod,
- &omap44xx_gpio2_hwmod,
- &omap44xx_gpio3_hwmod,
- &omap44xx_gpio4_hwmod,
- &omap44xx_gpio5_hwmod,
- &omap44xx_gpio6_hwmod,
-
- /* hsi class */
-/* &omap44xx_hsi_hwmod, */
-
- /* i2c class */
- &omap44xx_i2c1_hwmod,
- &omap44xx_i2c2_hwmod,
- &omap44xx_i2c3_hwmod,
- &omap44xx_i2c4_hwmod,
-
- /* ipu class */
- &omap44xx_ipu_hwmod,
- &omap44xx_ipu_c0_hwmod,
- &omap44xx_ipu_c1_hwmod,
-
- /* iss class */
-/* &omap44xx_iss_hwmod, */
-
- /* iva class */
- &omap44xx_iva_hwmod,
- &omap44xx_iva_seq0_hwmod,
- &omap44xx_iva_seq1_hwmod,
-
- /* kbd class */
- &omap44xx_kbd_hwmod,
-
- /* mailbox class */
- &omap44xx_mailbox_hwmod,
-
- /* mcbsp class */
- &omap44xx_mcbsp1_hwmod,
- &omap44xx_mcbsp2_hwmod,
- &omap44xx_mcbsp3_hwmod,
- &omap44xx_mcbsp4_hwmod,
-
- /* mcpdm class */
- &omap44xx_mcpdm_hwmod,
-
- /* mcspi class */
- &omap44xx_mcspi1_hwmod,
- &omap44xx_mcspi2_hwmod,
- &omap44xx_mcspi3_hwmod,
- &omap44xx_mcspi4_hwmod,
-
- /* mmc class */
- &omap44xx_mmc1_hwmod,
- &omap44xx_mmc2_hwmod,
- &omap44xx_mmc3_hwmod,
- &omap44xx_mmc4_hwmod,
- &omap44xx_mmc5_hwmod,
-
- /* mpu class */
- &omap44xx_mpu_hwmod,
-
- /* smartreflex class */
- &omap44xx_smartreflex_core_hwmod,
- &omap44xx_smartreflex_iva_hwmod,
- &omap44xx_smartreflex_mpu_hwmod,
-
- /* spinlock class */
- &omap44xx_spinlock_hwmod,
-
- /* timer class */
- &omap44xx_timer1_hwmod,
- &omap44xx_timer2_hwmod,
- &omap44xx_timer3_hwmod,
- &omap44xx_timer4_hwmod,
- &omap44xx_timer5_hwmod,
- &omap44xx_timer6_hwmod,
- &omap44xx_timer7_hwmod,
- &omap44xx_timer8_hwmod,
- &omap44xx_timer9_hwmod,
- &omap44xx_timer10_hwmod,
- &omap44xx_timer11_hwmod,
-
- /* uart class */
- &omap44xx_uart1_hwmod,
- &omap44xx_uart2_hwmod,
- &omap44xx_uart3_hwmod,
- &omap44xx_uart4_hwmod,
-
- /* usb host class */
- &omap44xx_usb_host_hs_hwmod,
- &omap44xx_usb_tll_hs_hwmod,
-
- /* usb_otg_hs class */
- &omap44xx_usb_otg_hs_hwmod,
-
- /* wd_timer class */
- &omap44xx_wd_timer2_hwmod,
- &omap44xx_wd_timer3_hwmod,
+/* l4_abe -> wd_timer3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3 = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_wd_timer3_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_wd_timer3_addrs,
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_wd_timer3_dma_addrs[] = {
+ {
+ .pa_start = 0x49030000,
+ .pa_end = 0x4903007f,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+};
+
+/* l4_abe -> wd_timer3 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3_dma = {
+ .master = &omap44xx_l4_abe_hwmod,
+ .slave = &omap44xx_wd_timer3_hwmod,
+ .clk = "ocp_abe_iclk",
+ .addr = omap44xx_wd_timer3_dma_addrs,
+ .user = OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
+ &omap44xx_c2c__c2c_target_fw,
+ &omap44xx_l4_cfg__c2c_target_fw,
+ &omap44xx_l3_main_1__dmm,
+ &omap44xx_mpu__dmm,
+ &omap44xx_c2c__emif_fw,
+ &omap44xx_dmm__emif_fw,
+ &omap44xx_l4_cfg__emif_fw,
+ &omap44xx_iva__l3_instr,
+ &omap44xx_l3_main_3__l3_instr,
+ &omap44xx_ocp_wp_noc__l3_instr,
+ &omap44xx_dsp__l3_main_1,
+ &omap44xx_dss__l3_main_1,
+ &omap44xx_l3_main_2__l3_main_1,
+ &omap44xx_l4_cfg__l3_main_1,
+ &omap44xx_mmc1__l3_main_1,
+ &omap44xx_mmc2__l3_main_1,
+ &omap44xx_mpu__l3_main_1,
+ &omap44xx_c2c_target_fw__l3_main_2,
+ &omap44xx_debugss__l3_main_2,
+ &omap44xx_dma_system__l3_main_2,
+ &omap44xx_fdif__l3_main_2,
+ &omap44xx_gpu__l3_main_2,
+ &omap44xx_hsi__l3_main_2,
+ &omap44xx_ipu__l3_main_2,
+ &omap44xx_iss__l3_main_2,
+ &omap44xx_iva__l3_main_2,
+ &omap44xx_l3_main_1__l3_main_2,
+ &omap44xx_l4_cfg__l3_main_2,
+ &omap44xx_usb_host_fs__l3_main_2,
+ &omap44xx_usb_host_hs__l3_main_2,
+ &omap44xx_usb_otg_hs__l3_main_2,
+ &omap44xx_l3_main_1__l3_main_3,
+ &omap44xx_l3_main_2__l3_main_3,
+ &omap44xx_l4_cfg__l3_main_3,
+ &omap44xx_aess__l4_abe,
+ &omap44xx_dsp__l4_abe,
+ &omap44xx_l3_main_1__l4_abe,
+ &omap44xx_mpu__l4_abe,
+ &omap44xx_l3_main_1__l4_cfg,
+ &omap44xx_l3_main_2__l4_per,
+ &omap44xx_l4_cfg__l4_wkup,
+ &omap44xx_mpu__mpu_private,
+ &omap44xx_l4_cfg__ocp_wp_noc,
+ &omap44xx_l4_abe__aess,
+ &omap44xx_l4_abe__aess_dma,
+ &omap44xx_l3_main_2__c2c,
+ &omap44xx_l4_wkup__counter_32k,
+ &omap44xx_l4_cfg__ctrl_module_core,
+ &omap44xx_l4_cfg__ctrl_module_pad_core,
+ &omap44xx_l4_wkup__ctrl_module_wkup,
+ &omap44xx_l4_wkup__ctrl_module_pad_wkup,
+ &omap44xx_l3_instr__debugss,
+ &omap44xx_l4_cfg__dma_system,
+ &omap44xx_l4_abe__dmic,
+ &omap44xx_l4_abe__dmic_dma,
+ &omap44xx_dsp__iva,
+ &omap44xx_dsp__sl2if,
+ &omap44xx_l4_cfg__dsp,
+ &omap44xx_l3_main_2__dss,
+ &omap44xx_l4_per__dss,
+ &omap44xx_l3_main_2__dss_dispc,
+ &omap44xx_l4_per__dss_dispc,
+ &omap44xx_l3_main_2__dss_dsi1,
+ &omap44xx_l4_per__dss_dsi1,
+ &omap44xx_l3_main_2__dss_dsi2,
+ &omap44xx_l4_per__dss_dsi2,
+ &omap44xx_l3_main_2__dss_hdmi,
+ &omap44xx_l4_per__dss_hdmi,
+ &omap44xx_l3_main_2__dss_rfbi,
+ &omap44xx_l4_per__dss_rfbi,
+ &omap44xx_l3_main_2__dss_venc,
+ &omap44xx_l4_per__dss_venc,
+ &omap44xx_l4_per__elm,
+ &omap44xx_emif_fw__emif1,
+ &omap44xx_emif_fw__emif2,
+ &omap44xx_l4_cfg__fdif,
+ &omap44xx_l4_wkup__gpio1,
+ &omap44xx_l4_per__gpio2,
+ &omap44xx_l4_per__gpio3,
+ &omap44xx_l4_per__gpio4,
+ &omap44xx_l4_per__gpio5,
+ &omap44xx_l4_per__gpio6,
+ &omap44xx_l3_main_2__gpmc,
+ &omap44xx_l3_main_2__gpu,
+ &omap44xx_l4_per__hdq1w,
+ &omap44xx_l4_cfg__hsi,
+ &omap44xx_l4_per__i2c1,
+ &omap44xx_l4_per__i2c2,
+ &omap44xx_l4_per__i2c3,
+ &omap44xx_l4_per__i2c4,
+ &omap44xx_l3_main_2__ipu,
+ &omap44xx_l3_main_2__iss,
+ &omap44xx_iva__sl2if,
+ &omap44xx_l3_main_2__iva,
+ &omap44xx_l4_wkup__kbd,
+ &omap44xx_l4_cfg__mailbox,
+ &omap44xx_l4_abe__mcasp,
+ &omap44xx_l4_abe__mcasp_dma,
+ &omap44xx_l4_abe__mcbsp1,
+ &omap44xx_l4_abe__mcbsp1_dma,
+ &omap44xx_l4_abe__mcbsp2,
+ &omap44xx_l4_abe__mcbsp2_dma,
+ &omap44xx_l4_abe__mcbsp3,
+ &omap44xx_l4_abe__mcbsp3_dma,
+ &omap44xx_l4_per__mcbsp4,
+ &omap44xx_l4_abe__mcpdm,
+ &omap44xx_l4_abe__mcpdm_dma,
+ &omap44xx_l4_per__mcspi1,
+ &omap44xx_l4_per__mcspi2,
+ &omap44xx_l4_per__mcspi3,
+ &omap44xx_l4_per__mcspi4,
+ &omap44xx_l4_per__mmc1,
+ &omap44xx_l4_per__mmc2,
+ &omap44xx_l4_per__mmc3,
+ &omap44xx_l4_per__mmc4,
+ &omap44xx_l4_per__mmc5,
+ &omap44xx_l3_main_2__ocmc_ram,
+ &omap44xx_l4_cfg__ocp2scp_usb_phy,
+ &omap44xx_mpu_private__prcm_mpu,
+ &omap44xx_l4_wkup__cm_core_aon,
+ &omap44xx_l4_cfg__cm_core,
+ &omap44xx_l4_wkup__prm,
+ &omap44xx_l4_wkup__scrm,
+ &omap44xx_l3_main_2__sl2if,
+ &omap44xx_l4_abe__slimbus1,
+ &omap44xx_l4_abe__slimbus1_dma,
+ &omap44xx_l4_per__slimbus2,
+ &omap44xx_l4_cfg__smartreflex_core,
+ &omap44xx_l4_cfg__smartreflex_iva,
+ &omap44xx_l4_cfg__smartreflex_mpu,
+ &omap44xx_l4_cfg__spinlock,
+ &omap44xx_l4_wkup__timer1,
+ &omap44xx_l4_per__timer2,
+ &omap44xx_l4_per__timer3,
+ &omap44xx_l4_per__timer4,
+ &omap44xx_l4_abe__timer5,
+ &omap44xx_l4_abe__timer5_dma,
+ &omap44xx_l4_abe__timer6,
+ &omap44xx_l4_abe__timer6_dma,
+ &omap44xx_l4_abe__timer7,
+ &omap44xx_l4_abe__timer7_dma,
+ &omap44xx_l4_abe__timer8,
+ &omap44xx_l4_abe__timer8_dma,
+ &omap44xx_l4_per__timer9,
+ &omap44xx_l4_per__timer10,
+ &omap44xx_l4_per__timer11,
+ &omap44xx_l4_per__uart1,
+ &omap44xx_l4_per__uart2,
+ &omap44xx_l4_per__uart3,
+ &omap44xx_l4_per__uart4,
+ &omap44xx_l4_cfg__usb_host_fs,
+ &omap44xx_l4_cfg__usb_host_hs,
+ &omap44xx_l4_cfg__usb_otg_hs,
+ &omap44xx_l4_cfg__usb_tll_hs,
+ &omap44xx_l4_wkup__wd_timer2,
+ &omap44xx_l4_abe__wd_timer3,
+ &omap44xx_l4_abe__wd_timer3_dma,
NULL,
};
int __init omap44xx_hwmod_init(void)
{
- return omap_hwmod_register(omap44xx_hwmods);
+ return omap_hwmod_register_links(omap44xx_hwmod_ocp_ifs);
}
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
index ad5d8f04c0b8..e7e8eeae95e5 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
@@ -19,18 +19,6 @@
#include "display.h"
/* Common address space across OMAP2xxx */
-extern struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[];
-extern struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[];
-extern struct omap_hwmod_addr_space omap2xxx_uart3_addr_space[];
-extern struct omap_hwmod_addr_space omap2xxx_timer2_addrs[];
-extern struct omap_hwmod_addr_space omap2xxx_timer3_addrs[];
-extern struct omap_hwmod_addr_space omap2xxx_timer4_addrs[];
-extern struct omap_hwmod_addr_space omap2xxx_timer5_addrs[];
-extern struct omap_hwmod_addr_space omap2xxx_timer6_addrs[];
-extern struct omap_hwmod_addr_space omap2xxx_timer7_addrs[];
-extern struct omap_hwmod_addr_space omap2xxx_timer8_addrs[];
-extern struct omap_hwmod_addr_space omap2xxx_timer9_addrs[];
-extern struct omap_hwmod_addr_space omap2xxx_timer12_addrs[];
extern struct omap_hwmod_addr_space omap2xxx_mcbsp2_addrs[];
/* Common address space across OMAP2xxx/3xxx */
@@ -50,10 +38,70 @@ extern struct omap_hwmod_addr_space omap2430_mcspi3_addr_space[];
extern struct omap_hwmod_addr_space omap2_dma_system_addrs[];
extern struct omap_hwmod_addr_space omap2_mailbox_addrs[];
extern struct omap_hwmod_addr_space omap2_mcbsp1_addrs[];
+extern struct omap_hwmod_addr_space omap2_hdq1w_addr_space[];
/* Common IP block data across OMAP2xxx */
extern struct omap_hwmod_irq_info omap2xxx_timer12_mpu_irqs[];
extern struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[];
+extern struct omap_gpio_dev_attr omap2xxx_gpio_dev_attr;
+extern struct omap_hwmod omap2xxx_l3_main_hwmod;
+extern struct omap_hwmod omap2xxx_l4_core_hwmod;
+extern struct omap_hwmod omap2xxx_l4_wkup_hwmod;
+extern struct omap_hwmod omap2xxx_mpu_hwmod;
+extern struct omap_hwmod omap2xxx_iva_hwmod;
+extern struct omap_hwmod omap2xxx_timer1_hwmod;
+extern struct omap_hwmod omap2xxx_timer2_hwmod;
+extern struct omap_hwmod omap2xxx_timer3_hwmod;
+extern struct omap_hwmod omap2xxx_timer4_hwmod;
+extern struct omap_hwmod omap2xxx_timer5_hwmod;
+extern struct omap_hwmod omap2xxx_timer6_hwmod;
+extern struct omap_hwmod omap2xxx_timer7_hwmod;
+extern struct omap_hwmod omap2xxx_timer8_hwmod;
+extern struct omap_hwmod omap2xxx_timer9_hwmod;
+extern struct omap_hwmod omap2xxx_timer10_hwmod;
+extern struct omap_hwmod omap2xxx_timer11_hwmod;
+extern struct omap_hwmod omap2xxx_timer12_hwmod;
+extern struct omap_hwmod omap2xxx_wd_timer2_hwmod;
+extern struct omap_hwmod omap2xxx_uart1_hwmod;
+extern struct omap_hwmod omap2xxx_uart2_hwmod;
+extern struct omap_hwmod omap2xxx_uart3_hwmod;
+extern struct omap_hwmod omap2xxx_dss_core_hwmod;
+extern struct omap_hwmod omap2xxx_dss_dispc_hwmod;
+extern struct omap_hwmod omap2xxx_dss_rfbi_hwmod;
+extern struct omap_hwmod omap2xxx_dss_venc_hwmod;
+extern struct omap_hwmod omap2xxx_gpio1_hwmod;
+extern struct omap_hwmod omap2xxx_gpio2_hwmod;
+extern struct omap_hwmod omap2xxx_gpio3_hwmod;
+extern struct omap_hwmod omap2xxx_gpio4_hwmod;
+extern struct omap_hwmod omap2xxx_mcspi1_hwmod;
+extern struct omap_hwmod omap2xxx_mcspi2_hwmod;
+extern struct omap_hwmod omap2xxx_counter_32k_hwmod;
+
+/* Common interface data across OMAP2xxx */
+extern struct omap_hwmod_ocp_if omap2xxx_l3_main__l4_core;
+extern struct omap_hwmod_ocp_if omap2xxx_mpu__l3_main;
+extern struct omap_hwmod_ocp_if omap2xxx_dss__l3;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__l4_wkup;
+extern struct omap_hwmod_ocp_if omap2_l4_core__uart1;
+extern struct omap_hwmod_ocp_if omap2_l4_core__uart2;
+extern struct omap_hwmod_ocp_if omap2_l4_core__uart3;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__mcspi1;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__mcspi2;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer2;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer3;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer4;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer5;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer6;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer7;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer8;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer9;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer10;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer11;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer12;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_dispc;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_rfbi;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_venc;
/* Common IP block data */
extern struct omap_hwmod_dma_info omap2_uart1_sdma_reqs[];
@@ -94,6 +142,8 @@ extern struct omap_hwmod_irq_info omap2_gpio4_irqs[];
extern struct omap_hwmod_irq_info omap2_dma_system_irqs[];
extern struct omap_hwmod_irq_info omap2_mcspi1_mpu_irqs[];
extern struct omap_hwmod_irq_info omap2_mcspi2_mpu_irqs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer12_addrs[];
+extern struct omap_hwmod_irq_info omap2_hdq1w_mpu_irqs[];
/* OMAP hwmod classes - forward declarations */
extern struct omap_hwmod_class l3_hwmod_class;
@@ -105,6 +155,8 @@ extern struct omap_hwmod_class omap2_dss_hwmod_class;
extern struct omap_hwmod_class omap2_dispc_hwmod_class;
extern struct omap_hwmod_class omap2_rfbi_hwmod_class;
extern struct omap_hwmod_class omap2_venc_hwmod_class;
+extern struct omap_hwmod_class_sysconfig omap2_hdq1w_sysc;
+extern struct omap_hwmod_class omap2_hdq1w_class;
extern struct omap_hwmod_class omap2xxx_timer_hwmod_class;
extern struct omap_hwmod_class omap2xxx_wd_timer_hwmod_class;
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 36fa90b6ece8..78564895e914 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -38,27 +38,6 @@ static inline int omap4_opp_init(void)
}
#endif
-/*
- * cpuidle mach specific parameters
- *
- * The board code can override the default C-states definition using
- * omap3_pm_init_cpuidle
- */
-struct cpuidle_params {
- u32 exit_latency; /* exit_latency = sleep + wake-up latencies */
- u32 target_residency;
- u8 valid; /* validates the C-state */
-};
-
-#if defined(CONFIG_PM) && defined(CONFIG_CPU_IDLE)
-extern void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params);
-#else
-static
-inline void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params)
-{
-}
-#endif
-
extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm);
extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state);
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 95442b69ae27..facfffca9eac 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -171,8 +171,6 @@ static int omap2_allow_mpu_retention(void)
static void omap2_enter_mpu_retention(void)
{
- int only_idle = 0;
-
/* Putting MPU into the WFI state while a transfer is active
* seems to cause the I2C block to timeout. Why? Good question. */
if (omap2_i2c_active())
@@ -195,7 +193,6 @@ static void omap2_enter_mpu_retention(void)
omap2_prm_write_mod_reg(OMAP_LOGICRETSTATE_MASK, MPU_MOD,
OMAP2_PM_PWSTCTRL);
- only_idle = 1;
}
omap2_sram_idle();
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 703bd1099259..8b43aefba0ea 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -273,7 +273,7 @@ void omap_sram_idle(void)
int per_next_state = PWRDM_POWER_ON;
int core_next_state = PWRDM_POWER_ON;
int per_going_off;
- int core_prev_state, per_prev_state;
+ int core_prev_state;
u32 sdrc_pwr = 0;
mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
@@ -375,10 +375,8 @@ void omap_sram_idle(void)
pwrdm_post_transition();
/* PER */
- if (per_next_state < PWRDM_POWER_ON) {
- per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
+ if (per_next_state < PWRDM_POWER_ON)
omap2_gpio_resume_after_idle();
- }
/* Disable IO-PAD and IO-CHAIN wakeup */
if (omap3_has_io_wakeup() &&
@@ -702,7 +700,7 @@ static void __init pm_errata_configure(void)
static int __init omap3_pm_init(void)
{
struct power_state *pwrst, *tmp;
- struct clockdomain *neon_clkdm, *per_clkdm, *mpu_clkdm, *core_clkdm;
+ struct clockdomain *neon_clkdm, *mpu_clkdm;
int ret;
if (!cpu_is_omap34xx())
@@ -757,8 +755,6 @@ static int __init omap3_pm_init(void)
neon_clkdm = clkdm_lookup("neon_clkdm");
mpu_clkdm = clkdm_lookup("mpu_clkdm");
- per_clkdm = clkdm_lookup("per_clkdm");
- core_clkdm = clkdm_lookup("core_clkdm");
#ifdef CONFIG_SUSPEND
omap_pm_suspend = omap3_pm_suspend;
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 96ad3dbeac34..96114901b932 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -981,16 +981,6 @@ int pwrdm_state_switch(struct powerdomain *pwrdm)
return ret;
}
-int pwrdm_clkdm_state_switch(struct clockdomain *clkdm)
-{
- if (clkdm != NULL && clkdm->pwrdm.ptr != NULL) {
- pwrdm_wait_transition(clkdm->pwrdm.ptr);
- return pwrdm_state_switch(clkdm->pwrdm.ptr);
- }
-
- return -EINVAL;
-}
-
int pwrdm_pre_transition(void)
{
pwrdm_for_each(_pwrdm_pre_transition_cb, NULL);
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 0d72a8a8ce4d..8f88d65c46ea 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -213,7 +213,6 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
int pwrdm_wait_transition(struct powerdomain *pwrdm);
int pwrdm_state_switch(struct powerdomain *pwrdm);
-int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
int pwrdm_pre_transition(void);
int pwrdm_post_transition(void);
int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
index 5aa5435e3ff1..6da3ba483ad1 100644
--- a/arch/arm/mach-omap2/prcm-common.h
+++ b/arch/arm/mach-omap2/prcm-common.h
@@ -177,6 +177,8 @@
/* PM_WKST_WKUP, CM_IDLEST_WKUP shared bits */
#define OMAP24XX_ST_GPIOS_SHIFT 2
#define OMAP24XX_ST_GPIOS_MASK (1 << 2)
+#define OMAP24XX_ST_32KSYNC_SHIFT 1
+#define OMAP24XX_ST_32KSYNC_MASK (1 << 1)
#define OMAP24XX_ST_GPT1_SHIFT 0
#define OMAP24XX_ST_GPT1_MASK (1 << 0)
@@ -307,6 +309,8 @@
#define OMAP3430_ST_SR1_MASK (1 << 6)
#define OMAP3430_ST_GPIO1_SHIFT 3
#define OMAP3430_ST_GPIO1_MASK (1 << 3)
+#define OMAP3430_ST_32KSYNC_SHIFT 2
+#define OMAP3430_ST_32KSYNC_MASK (1 << 2)
#define OMAP3430_ST_GPT12_SHIFT 1
#define OMAP3430_ST_GPT12_MASK (1 << 1)
#define OMAP3430_ST_GPT1_SHIFT 0
@@ -410,6 +414,19 @@
extern void __iomem *prm_base;
extern void __iomem *cm_base;
extern void __iomem *cm2_base;
+extern void __iomem *prcm_mpu_base;
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_OMAP5)
+extern void omap_prm_base_init(void);
+extern void omap_cm_base_init(void);
+#else
+static inline void omap_prm_base_init(void)
+{
+}
+static inline void omap_cm_base_init(void)
+{
+}
+#endif
/**
* struct omap_prcm_irq - describes a PRCM interrupt bit
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index 626acfad7190..480f40a5ee42 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -42,6 +42,7 @@
void __iomem *prm_base;
void __iomem *cm_base;
void __iomem *cm2_base;
+void __iomem *prcm_mpu_base;
#define MAX_MODULE_ENABLE_WAIT 100000
@@ -155,4 +156,11 @@ void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
cm_base = omap2_globals->cm;
if (omap2_globals->cm2)
cm2_base = omap2_globals->cm2;
+ if (omap2_globals->prcm_mpu)
+ prcm_mpu_base = omap2_globals->prcm_mpu;
+
+ if (cpu_is_omap44xx()) {
+ omap_prm_base_init();
+ omap_cm_base_init();
+ }
}
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index d28f848897d6..dfe00ddb5c60 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -237,7 +237,7 @@ void omap_prcm_irq_complete(void)
*/
int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup)
{
- int nr_regs = irq_setup->nr_regs;
+ int nr_regs;
u32 mask[OMAP_PRCM_MAX_NR_PENDING_REG];
int offset, i;
struct irq_chip_generic *gc;
@@ -246,6 +246,8 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup)
if (!irq_setup)
return -EINVAL;
+ nr_regs = irq_setup->nr_regs;
+
if (prcm_irq_setup) {
pr_err("PRCM: already initialized; won't reinitialize\n");
return -EINVAL;
diff --git a/arch/arm/mach-omap2/prminst44xx.c b/arch/arm/mach-omap2/prminst44xx.c
index 9b3898a3ac9b..c12320c0ae95 100644
--- a/arch/arm/mach-omap2/prminst44xx.c
+++ b/arch/arm/mach-omap2/prminst44xx.c
@@ -18,20 +18,26 @@
#include "iomap.h"
#include "common.h"
+#include "prcm-common.h"
#include "prm44xx.h"
#include "prminst44xx.h"
#include "prm-regbits-44xx.h"
#include "prcm44xx.h"
#include "prcm_mpu44xx.h"
-static u32 _prm_bases[OMAP4_MAX_PRCM_PARTITIONS] = {
- [OMAP4430_INVALID_PRCM_PARTITION] = 0,
- [OMAP4430_PRM_PARTITION] = OMAP4430_PRM_BASE,
- [OMAP4430_CM1_PARTITION] = 0,
- [OMAP4430_CM2_PARTITION] = 0,
- [OMAP4430_SCRM_PARTITION] = 0,
- [OMAP4430_PRCM_MPU_PARTITION] = OMAP4430_PRCM_MPU_BASE,
-};
+static void __iomem *_prm_bases[OMAP4_MAX_PRCM_PARTITIONS];
+
+/**
+ * omap_prm_base_init - Populates the prm partitions
+ *
+ * Populates the base addresses of the _prm_bases
+ * array used for read/write of prm module registers.
+ */
+void omap_prm_base_init(void)
+{
+ _prm_bases[OMAP4430_PRM_PARTITION] = prm_base;
+ _prm_bases[OMAP4430_PRCM_MPU_PARTITION] = prcm_mpu_base;
+}
/* Read a register in a PRM instance */
u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx)
@@ -39,8 +45,7 @@ u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx)
BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
part == OMAP4430_INVALID_PRCM_PARTITION ||
!_prm_bases[part]);
- return __raw_readl(OMAP2_L4_IO_ADDRESS(_prm_bases[part] + inst +
- idx));
+ return __raw_readl(_prm_bases[part] + inst + idx);
}
/* Write into a register in a PRM instance */
@@ -49,7 +54,7 @@ void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx)
BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
part == OMAP4430_INVALID_PRCM_PARTITION ||
!_prm_bases[part]);
- __raw_writel(val, OMAP2_L4_IO_ADDRESS(_prm_bases[part] + inst + idx));
+ __raw_writel(val, _prm_bases[part] + inst + idx);
}
/* Read-modify-write a register in PRM. Caller must lock */
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 9fc2f44188cb..292d4aaca068 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -133,7 +133,7 @@ static void omap_serial_fill_default_pads(struct omap_board_data *bdata)
static void omap_serial_fill_default_pads(struct omap_board_data *bdata) {}
#endif
-char *cmdline_find_option(char *str)
+static char *cmdline_find_option(char *str)
{
extern char *saved_command_line;
@@ -245,14 +245,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate;
omap_up.autosuspend_timeout = info->autosuspend_timeout;
- /* Enable the MDR1 Errata i202 for OMAP2430/3xxx/44xx */
- if (!cpu_is_omap2420() && !cpu_is_ti816x())
- omap_up.errata |= UART_ERRATA_i202_MDR1_ACCESS;
-
- /* Enable DMA Mode Force Idle Errata i291 for omap34xx/3630 */
- if (cpu_is_omap34xx() || cpu_is_omap3630())
- omap_up.errata |= UART_ERRATA_i291_DMA_FORCEIDLE;
-
pdata = &omap_up;
pdata_size = sizeof(struct omap_uart_port_info);
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index c512bac69ec5..1b7835865c83 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -145,8 +145,10 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
{
char name[10]; /* 10 = sizeof("gptXX_Xck0") */
struct omap_hwmod *oh;
+ struct resource irq_rsrc, mem_rsrc;
size_t size;
int res = 0;
+ int r;
sprintf(name, "timer%d", gptimer_id);
omap_hwmod_setup_one(name);
@@ -154,9 +156,16 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
if (!oh)
return -ENODEV;
- timer->irq = oh->mpu_irqs[0].irq;
- timer->phys_base = oh->slaves[0]->addr->pa_start;
- size = oh->slaves[0]->addr->pa_end - timer->phys_base;
+ r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL, &irq_rsrc);
+ if (r)
+ return -ENXIO;
+ timer->irq = irq_rsrc.start;
+
+ r = omap_hwmod_get_resource_byname(oh, IORESOURCE_MEM, NULL, &mem_rsrc);
+ if (r)
+ return -ENXIO;
+ timer->phys_base = mem_rsrc.start;
+ size = mem_rsrc.end - mem_rsrc.start;
/* Static mapping, never released */
timer->io_base = ioremap(timer->phys_base, size);
@@ -169,13 +178,6 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
if (IS_ERR(timer->fclk))
return -ENODEV;
- sprintf(name, "gpt%d_ick", gptimer_id);
- timer->iclk = clk_get(NULL, name);
- if (IS_ERR(timer->iclk)) {
- clk_put(timer->fclk);
- return -ENODEV;
- }
-
omap_hwmod_enable(oh);
sys_timer_reserved |= (1 << (gptimer_id - 1));
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index 7a7b89304c48..119d5a910f3a 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -31,6 +31,7 @@
#include "twl-common.h"
#include "pm.h"
+#include "voltage.h"
static struct i2c_board_info __initdata pmic_i2c_board_info = {
.addr = 0x48,
@@ -47,6 +48,18 @@ static struct i2c_board_info __initdata omap4_i2c1_board_info[] = {
},
};
+static int twl_set_voltage(void *data, int target_uV)
+{
+ struct voltagedomain *voltdm = (struct voltagedomain *)data;
+ return voltdm_scale(voltdm, target_uV);
+}
+
+static int twl_get_voltage(void *data)
+{
+ struct voltagedomain *voltdm = (struct voltagedomain *)data;
+ return voltdm_get_voltage(voltdm);
+}
+
void __init omap_pmic_init(int bus, u32 clkrate,
const char *pmic_type, int pmic_irq,
struct twl4030_platform_data *pmic_data)
@@ -153,6 +166,48 @@ static struct regulator_init_data omap3_vpll2_idata = {
.consumer_supplies = omap3_vpll2_supplies,
};
+static struct regulator_consumer_supply omap3_vdd1_supply[] = {
+ REGULATOR_SUPPLY("vcc", "mpu.0"),
+};
+
+static struct regulator_consumer_supply omap3_vdd2_supply[] = {
+ REGULATOR_SUPPLY("vcc", "l3_main.0"),
+};
+
+static struct regulator_init_data omap3_vdd1 = {
+ .constraints = {
+ .name = "vdd_mpu_iva",
+ .min_uV = 600000,
+ .max_uV = 1450000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap3_vdd1_supply),
+ .consumer_supplies = omap3_vdd1_supply,
+};
+
+static struct regulator_init_data omap3_vdd2 = {
+ .constraints = {
+ .name = "vdd_core",
+ .min_uV = 600000,
+ .max_uV = 1450000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap3_vdd2_supply),
+ .consumer_supplies = omap3_vdd2_supply,
+};
+
+static struct twl_regulator_driver_data omap3_vdd1_drvdata = {
+ .get_voltage = twl_get_voltage,
+ .set_voltage = twl_set_voltage,
+};
+
+static struct twl_regulator_driver_data omap3_vdd2_drvdata = {
+ .get_voltage = twl_get_voltage,
+ .set_voltage = twl_set_voltage,
+};
+
void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
u32 pdata_flags, u32 regulators_flags)
{
@@ -160,6 +215,16 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
pmic_data->irq_base = TWL4030_IRQ_BASE;
if (!pmic_data->irq_end)
pmic_data->irq_end = TWL4030_IRQ_END;
+ if (!pmic_data->vdd1) {
+ omap3_vdd1.driver_data = &omap3_vdd1_drvdata;
+ omap3_vdd1_drvdata.data = voltdm_lookup("mpu_iva");
+ pmic_data->vdd1 = &omap3_vdd1;
+ }
+ if (!pmic_data->vdd2) {
+ omap3_vdd2.driver_data = &omap3_vdd2_drvdata;
+ omap3_vdd2_drvdata.data = voltdm_lookup("core");
+ pmic_data->vdd2 = &omap3_vdd2;
+ }
/* Common platform data configurations */
if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
@@ -201,6 +266,7 @@ static struct regulator_init_data omap4_vdac_idata = {
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
+ .supply_regulator = "V2V1",
};
static struct regulator_init_data omap4_vaux2_idata = {
@@ -291,6 +357,7 @@ static struct regulator_init_data omap4_vcxio_idata = {
},
.num_consumer_supplies = ARRAY_SIZE(omap4_vcxio_supply),
.consumer_supplies = omap4_vcxio_supply,
+ .supply_regulator = "V2V1",
};
static struct regulator_init_data omap4_vusb_idata = {
@@ -310,6 +377,105 @@ static struct regulator_init_data omap4_clk32kg_idata = {
},
};
+static struct regulator_consumer_supply omap4_vdd1_supply[] = {
+ REGULATOR_SUPPLY("vcc", "mpu.0"),
+};
+
+static struct regulator_consumer_supply omap4_vdd2_supply[] = {
+ REGULATOR_SUPPLY("vcc", "iva.0"),
+};
+
+static struct regulator_consumer_supply omap4_vdd3_supply[] = {
+ REGULATOR_SUPPLY("vcc", "l3_main.0"),
+};
+
+static struct regulator_init_data omap4_vdd1 = {
+ .constraints = {
+ .name = "vdd_mpu",
+ .min_uV = 500000,
+ .max_uV = 1500000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap4_vdd1_supply),
+ .consumer_supplies = omap4_vdd1_supply,
+};
+
+static struct regulator_init_data omap4_vdd2 = {
+ .constraints = {
+ .name = "vdd_iva",
+ .min_uV = 500000,
+ .max_uV = 1500000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap4_vdd2_supply),
+ .consumer_supplies = omap4_vdd2_supply,
+};
+
+static struct regulator_init_data omap4_vdd3 = {
+ .constraints = {
+ .name = "vdd_core",
+ .min_uV = 500000,
+ .max_uV = 1500000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap4_vdd3_supply),
+ .consumer_supplies = omap4_vdd3_supply,
+};
+
+
+static struct twl_regulator_driver_data omap4_vdd1_drvdata = {
+ .get_voltage = twl_get_voltage,
+ .set_voltage = twl_set_voltage,
+};
+
+static struct twl_regulator_driver_data omap4_vdd2_drvdata = {
+ .get_voltage = twl_get_voltage,
+ .set_voltage = twl_set_voltage,
+};
+
+static struct twl_regulator_driver_data omap4_vdd3_drvdata = {
+ .get_voltage = twl_get_voltage,
+ .set_voltage = twl_set_voltage,
+};
+
+static struct regulator_consumer_supply omap4_v1v8_supply[] = {
+ REGULATOR_SUPPLY("vio", "1-004b"),
+};
+
+static struct regulator_init_data omap4_v1v8_idata = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ .always_on = true,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap4_v1v8_supply),
+ .consumer_supplies = omap4_v1v8_supply,
+};
+
+static struct regulator_consumer_supply omap4_v2v1_supply[] = {
+ REGULATOR_SUPPLY("v2v1", "1-004b"),
+};
+
+static struct regulator_init_data omap4_v2v1_idata = {
+ .constraints = {
+ .min_uV = 2100000,
+ .max_uV = 2100000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(omap4_v2v1_supply),
+ .consumer_supplies = omap4_v2v1_supply,
+};
+
void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
u32 pdata_flags, u32 regulators_flags)
{
@@ -318,6 +484,24 @@ void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
if (!pmic_data->irq_end)
pmic_data->irq_end = TWL6030_IRQ_END;
+ if (!pmic_data->vdd1) {
+ omap4_vdd1.driver_data = &omap4_vdd1_drvdata;
+ omap4_vdd1_drvdata.data = voltdm_lookup("mpu");
+ pmic_data->vdd1 = &omap4_vdd1;
+ }
+
+ if (!pmic_data->vdd2) {
+ omap4_vdd2.driver_data = &omap4_vdd2_drvdata;
+ omap4_vdd2_drvdata.data = voltdm_lookup("iva");
+ pmic_data->vdd2 = &omap4_vdd2;
+ }
+
+ if (!pmic_data->vdd3) {
+ omap4_vdd3.driver_data = &omap4_vdd3_drvdata;
+ omap4_vdd3_drvdata.data = voltdm_lookup("core");
+ pmic_data->vdd3 = &omap4_vdd3;
+ }
+
/* Common platform data configurations */
if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
pmic_data->usb = &omap4_usb_pdata;
@@ -350,5 +534,11 @@ void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
if (regulators_flags & TWL_COMMON_REGULATOR_CLK32KG &&
!pmic_data->clk32kg)
pmic_data->clk32kg = &omap4_clk32kg_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_V1V8 && !pmic_data->v1v8)
+ pmic_data->v1v8 = &omap4_v1v8_idata;
+
+ if (regulators_flags & TWL_COMMON_REGULATOR_V2V1 && !pmic_data->v2v1)
+ pmic_data->v2v1 = &omap4_v2v1_idata;
}
#endif /* CONFIG_ARCH_OMAP4 */
diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h
index 09627483a57f..8fe71cfd002c 100644
--- a/arch/arm/mach-omap2/twl-common.h
+++ b/arch/arm/mach-omap2/twl-common.h
@@ -22,6 +22,8 @@
#define TWL_COMMON_REGULATOR_VCXIO (1 << 8)
#define TWL_COMMON_REGULATOR_VUSB (1 << 9)
#define TWL_COMMON_REGULATOR_CLK32KG (1 << 10)
+#define TWL_COMMON_REGULATOR_V1V8 (1 << 11)
+#define TWL_COMMON_REGULATOR_V2V1 (1 << 12)
/* TWL4030 LDO regulators */
#define TWL_COMMON_REGULATOR_VPLL1 (1 << 4)
diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
index 994d8f591a1d..db84a46ce7fd 100644
--- a/arch/arm/mach-omap2/usb-tusb6010.c
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -126,7 +126,7 @@ static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
tmp = (t.sync_clk + fclk_ps - 1) / fclk_ps;
if (tmp > 4)
return -ERANGE;
- if (tmp <= 0)
+ if (tmp == 0)
tmp = 1;
t.page_burst_access = (fclk_ps * tmp) / 1000;
diff --git a/arch/arm/mach-omap2/vc3xxx_data.c b/arch/arm/mach-omap2/vc3xxx_data.c
index a5ec7f8f2ea8..5d8eaf31569c 100644
--- a/arch/arm/mach-omap2/vc3xxx_data.c
+++ b/arch/arm/mach-omap2/vc3xxx_data.c
@@ -46,6 +46,7 @@ static struct omap_vc_common omap3_vc_common = {
};
struct omap_vc_channel omap3_vc_mpu = {
+ .flags = OMAP_VC_CHANNEL_DEFAULT,
.common = &omap3_vc_common,
.smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET,
.smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 8a36342e60d2..4dc60e83e00d 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -73,7 +73,8 @@ unsigned long voltdm_get_voltage(struct voltagedomain *voltdm)
int voltdm_scale(struct voltagedomain *voltdm,
unsigned long target_volt)
{
- int ret;
+ int ret, i;
+ unsigned long volt = 0;
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
@@ -86,9 +87,23 @@ int voltdm_scale(struct voltagedomain *voltdm,
return -ENODATA;
}
- ret = voltdm->scale(voltdm, target_volt);
+ /* Adjust voltage to the exact voltage from the OPP table */
+ for (i = 0; voltdm->volt_data[i].volt_nominal != 0; i++) {
+ if (voltdm->volt_data[i].volt_nominal >= target_volt) {
+ volt = voltdm->volt_data[i].volt_nominal;
+ break;
+ }
+ }
+
+ if (!volt) {
+ pr_warning("%s: not scaling. OPP voltage for %lu, not found.\n",
+ __func__, target_volt);
+ return -EINVAL;
+ }
+
+ ret = voltdm->scale(voltdm, volt);
if (!ret)
- voltdm->nominal_volt = target_volt;
+ voltdm->nominal_volt = volt;
return ret;
}
diff --git a/arch/arm/mach-omap2/wd_timer.c b/arch/arm/mach-omap2/wd_timer.c
index 4067669d96c4..b2f1c67043a2 100644
--- a/arch/arm/mach-omap2/wd_timer.c
+++ b/arch/arm/mach-omap2/wd_timer.c
@@ -14,6 +14,7 @@
#include <plat/omap_hwmod.h>
#include "wd_timer.h"
+#include "common.h"
/*
* In order to avoid any assumptions from bootloader regarding WDT
@@ -25,6 +26,8 @@
#define OMAP_WDT_WPS 0x34
#define OMAP_WDT_SPR 0x48
+/* Maximum microseconds to wait for OMAP module to softreset */
+#define MAX_MODULE_SOFTRESET_WAIT 10000
int omap2_wd_timer_disable(struct omap_hwmod *oh)
{
@@ -54,3 +57,45 @@ int omap2_wd_timer_disable(struct omap_hwmod *oh)
return 0;
}
+/**
+ * omap2_wdtimer_reset - reset and disable the WDTIMER IP block
+ * @oh: struct omap_hwmod *
+ *
+ * After the WDTIMER IP blocks are reset on OMAP2/3, we must also take
+ * care to execute the special watchdog disable sequence. This is
+ * because the watchdog is re-armed upon OCP softreset. (On OMAP4,
+ * this behavior was apparently changed and the watchdog is no longer
+ * re-armed after an OCP soft-reset.) Returns -ETIMEDOUT if the reset
+ * did not complete, or 0 upon success.
+ *
+ * XXX Most of this code should be moved to the omap_hwmod.c layer
+ * during a normal merge window. omap_hwmod_softreset() should be
+ * renamed to omap_hwmod_set_ocp_softreset(), and omap_hwmod_softreset()
+ * should call the hwmod _ocp_softreset() code.
+ */
+int omap2_wd_timer_reset(struct omap_hwmod *oh)
+{
+ int c = 0;
+
+ /* Write to the SOFTRESET bit */
+ omap_hwmod_softreset(oh);
+
+ /* Poll on RESETDONE bit */
+ omap_test_timeout((omap_hwmod_read(oh,
+ oh->class->sysc->syss_offs)
+ & SYSS_RESETDONE_MASK),
+ MAX_MODULE_SOFTRESET_WAIT, c);
+
+ if (oh->class->sysc->srst_udelay)
+ udelay(oh->class->sysc->srst_udelay);
+
+ if (c == MAX_MODULE_SOFTRESET_WAIT)
+ pr_warning("%s: %s: softreset failed (waited %d usec)\n",
+ __func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
+ else
+ pr_debug("%s: %s: softreset in %d usec\n", __func__,
+ oh->name, c);
+
+ return (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT :
+ omap2_wd_timer_disable(oh);
+}
diff --git a/arch/arm/mach-omap2/wd_timer.h b/arch/arm/mach-omap2/wd_timer.h
index e0054a2d5505..f6bbba73b535 100644
--- a/arch/arm/mach-omap2/wd_timer.h
+++ b/arch/arm/mach-omap2/wd_timer.h
@@ -13,5 +13,6 @@
#include <plat/omap_hwmod.h>
extern int omap2_wd_timer_disable(struct omap_hwmod *oh);
+extern int omap2_wd_timer_reset(struct omap_hwmod *oh);
#endif
diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
index 6604fc6ca58a..0673f0c10432 100644
--- a/arch/arm/mach-orion5x/Kconfig
+++ b/arch/arm/mach-orion5x/Kconfig
@@ -86,7 +86,6 @@ config MACH_WRT350N_V2
config MACH_TS78XX
bool "Technologic Systems TS-78xx"
- select PM
help
Say 'Y' here if you want your kernel to support the
Technologic Systems TS-78xx platform.
diff --git a/arch/arm/mach-orion5x/addr-map.c b/arch/arm/mach-orion5x/addr-map.c
index 3638e5c12b7e..eaac83d1df6f 100644
--- a/arch/arm/mach-orion5x/addr-map.c
+++ b/arch/arm/mach-orion5x/addr-map.c
@@ -76,7 +76,7 @@ static int __init cpu_win_can_remap(const struct orion_addr_map_cfg *cfg,
/*
* Description of the windows needed by the platform code
*/
-static struct __initdata orion_addr_map_cfg addr_map_cfg = {
+static struct orion_addr_map_cfg addr_map_cfg __initdata = {
.num_wins = 8,
.cpu_win_can_remap = cpu_win_can_remap,
.bridge_virt_base = ORION5X_BRIDGE_VIRT_BASE,
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 24481666d2cd..e2e9db492d0c 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -205,7 +205,7 @@ int __init orion5x_find_tclk(void)
return 166666667;
}
-static void orion5x_timer_init(void)
+static void __init orion5x_timer_init(void)
{
orion5x_tclk = orion5x_find_tclk();
diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
index 2e6454c8d4ba..31bab92ce038 100644
--- a/arch/arm/mach-orion5x/common.h
+++ b/arch/arm/mach-orion5x/common.h
@@ -45,6 +45,7 @@ void orion5x_restart(char, const char *);
*/
struct pci_bus;
struct pci_sys_data;
+struct pci_dev;
void orion5x_pcie_id(u32 *dev, u32 *rev);
void orion5x_pci_disable(void);
diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c
index e52108c9aaea..49a3fd630313 100644
--- a/arch/arm/mach-orion5x/db88f5281-setup.c
+++ b/arch/arm/mach-orion5x/db88f5281-setup.c
@@ -265,7 +265,6 @@ static int __init db88f5281_pci_map_irq(const struct pci_dev *dev, u8 slot,
static struct hw_pci db88f5281_pci __initdata = {
.nr_controllers = 2,
.preinit = db88f5281_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = orion5x_pci_sys_setup,
.scan = orion5x_pci_sys_scan_bus,
.map_irq = db88f5281_pci_map_irq,
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index c3ed15b8ea25..d470864b4e42 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -86,7 +86,6 @@ static int __init dns323_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
static struct hw_pci dns323_pci __initdata = {
.nr_controllers = 2,
- .swizzle = pci_std_swizzle,
.setup = orion5x_pci_sys_setup,
.scan = orion5x_pci_sys_scan_bus,
.map_irq = dns323_pci_map_irq,
@@ -253,27 +252,6 @@ error_fail:
* GPIO LEDs (simple - doesn't use hardware blinking support)
*/
-#define ORION_BLINK_HALF_PERIOD 100 /* ms */
-
-static int dns323_gpio_blink_set(unsigned gpio, int state,
- unsigned long *delay_on, unsigned long *delay_off)
-{
-
- if (delay_on && delay_off && !*delay_on && !*delay_off)
- *delay_on = *delay_off = ORION_BLINK_HALF_PERIOD;
-
- switch(state) {
- case GPIO_LED_NO_BLINK_LOW:
- case GPIO_LED_NO_BLINK_HIGH:
- orion_gpio_set_blink(gpio, 0);
- gpio_set_value(gpio, state);
- break;
- case GPIO_LED_BLINK:
- orion_gpio_set_blink(gpio, 1);
- }
- return 0;
-}
-
static struct gpio_led dns323ab_leds[] = {
{
.name = "power:blue",
@@ -312,13 +290,13 @@ static struct gpio_led dns323c_leds[] = {
static struct gpio_led_platform_data dns323ab_led_data = {
.num_leds = ARRAY_SIZE(dns323ab_leds),
.leds = dns323ab_leds,
- .gpio_blink_set = dns323_gpio_blink_set,
+ .gpio_blink_set = orion_gpio_led_blink_set,
};
static struct gpio_led_platform_data dns323c_led_data = {
.num_leds = ARRAY_SIZE(dns323c_leds),
.leds = dns323c_leds,
- .gpio_blink_set = dns323_gpio_blink_set,
+ .gpio_blink_set = orion_gpio_led_blink_set,
};
static struct platform_device dns323_gpio_leds = {
diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
index 47587b832842..1e458efafb9a 100644
--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
+++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
@@ -138,7 +138,6 @@ static int __init kurobox_pro_pci_map_irq(const struct pci_dev *dev, u8 slot,
static struct hw_pci kurobox_pro_pci __initdata = {
.nr_controllers = 2,
- .swizzle = pci_std_swizzle,
.setup = orion5x_pci_sys_setup,
.scan = orion5x_pci_sys_scan_bus,
.map_irq = kurobox_pro_pci_map_irq,
diff --git a/arch/arm/mach-orion5x/mss2-setup.c b/arch/arm/mach-orion5x/mss2-setup.c
index 65faaa34de61..1c16d045333e 100644
--- a/arch/arm/mach-orion5x/mss2-setup.c
+++ b/arch/arm/mach-orion5x/mss2-setup.c
@@ -89,7 +89,6 @@ static int __init mss2_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
static struct hw_pci mss2_pci __initdata = {
.nr_controllers = 2,
- .swizzle = pci_std_swizzle,
.setup = orion5x_pci_sys_setup,
.scan = orion5x_pci_sys_scan_bus,
.map_irq = mss2_pci_map_irq,
diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
index 292038fc59fd..78a6a11d8216 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
@@ -149,7 +149,6 @@ rd88f5181l_fxo_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
static struct hw_pci rd88f5181l_fxo_pci __initdata = {
.nr_controllers = 2,
- .swizzle = pci_std_swizzle,
.setup = orion5x_pci_sys_setup,
.scan = orion5x_pci_sys_scan_bus,
.map_irq = rd88f5181l_fxo_pci_map_irq,
diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
index c44eabaabc16..2f5dc54cd4cd 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
@@ -161,7 +161,6 @@ rd88f5181l_ge_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
static struct hw_pci rd88f5181l_ge_pci __initdata = {
.nr_controllers = 2,
- .swizzle = pci_std_swizzle,
.setup = orion5x_pci_sys_setup,
.scan = orion5x_pci_sys_scan_bus,
.map_irq = rd88f5181l_ge_pci_map_irq,
diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c
index e3ce61711478..399130fac0b6 100644
--- a/arch/arm/mach-orion5x/rd88f5182-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
@@ -200,7 +200,6 @@ static int __init rd88f5182_pci_map_irq(const struct pci_dev *dev, u8 slot,
static struct hw_pci rd88f5182_pci __initdata = {
.nr_controllers = 2,
.preinit = rd88f5182_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = orion5x_pci_sys_setup,
.scan = orion5x_pci_sys_scan_bus,
.map_irq = rd88f5182_pci_map_irq,
diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
index 2c5fab00d205..e91bf0ba4e8e 100644
--- a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
@@ -102,7 +102,6 @@ static void __init rd88f6183ap_ge_init(void)
static struct hw_pci rd88f6183ap_ge_pci __initdata = {
.nr_controllers = 2,
- .swizzle = pci_std_swizzle,
.setup = orion5x_pci_sys_setup,
.scan = orion5x_pci_sys_scan_bus,
.map_irq = orion5x_pci_map_irq,
diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c
index 632a861ef82b..90e571dc4deb 100644
--- a/arch/arm/mach-orion5x/terastation_pro2-setup.c
+++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c
@@ -122,7 +122,6 @@ static int __init tsp2_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
static struct hw_pci tsp2_pci __initdata = {
.nr_controllers = 2,
.preinit = tsp2_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = orion5x_pci_sys_setup,
.scan = orion5x_pci_sys_scan_bus,
.map_irq = tsp2_pci_map_irq,
diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c
index 5d6408745582..b184f680e0db 100644
--- a/arch/arm/mach-orion5x/ts209-setup.c
+++ b/arch/arm/mach-orion5x/ts209-setup.c
@@ -170,7 +170,6 @@ static int __init qnap_ts209_pci_map_irq(const struct pci_dev *dev, u8 slot,
static struct hw_pci qnap_ts209_pci __initdata = {
.nr_controllers = 2,
.preinit = qnap_ts209_pci_preinit,
- .swizzle = pci_std_swizzle,
.setup = orion5x_pci_sys_setup,
.scan = orion5x_pci_sys_scan_bus,
.map_irq = qnap_ts209_pci_map_irq,
diff --git a/arch/arm/mach-orion5x/ts409-setup.c b/arch/arm/mach-orion5x/ts409-setup.c
index 4e6ff759cd32..a5c2e64c4ece 100644
--- a/arch/arm/mach-orion5x/ts409-setup.c
+++ b/arch/arm/mach-orion5x/ts409-setup.c
@@ -140,7 +140,6 @@ static int __init qnap_ts409_pci_map_irq(const struct pci_dev *dev, u8 slot,
static struct hw_pci qnap_ts409_pci __initdata = {
.nr_controllers = 2,
- .swizzle = pci_std_swizzle,
.setup = orion5x_pci_sys_setup,
.scan = orion5x_pci_sys_scan_bus,
.map_irq = qnap_ts409_pci_map_irq,
diff --git a/arch/arm/mach-orion5x/ts78xx-fpga.h b/arch/arm/mach-orion5x/ts78xx-fpga.h
index 151e89e1e676..97c393d39ae2 100644
--- a/arch/arm/mach-orion5x/ts78xx-fpga.h
+++ b/arch/arm/mach-orion5x/ts78xx-fpga.h
@@ -28,9 +28,9 @@ struct fpga_device {
struct fpga_devices {
/* Technologic Systems */
- struct fpga_device ts_rtc;
- struct fpga_device ts_nand;
- struct fpga_device ts_rng;
+ struct fpga_device ts_rtc;
+ struct fpga_device ts_nand;
+ struct fpga_device ts_rng;
};
struct ts78xx_fpga_data {
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
index c96f37472eda..a74f3cf54cc5 100644
--- a/arch/arm/mach-orion5x/ts78xx-setup.c
+++ b/arch/arm/mach-orion5x/ts78xx-setup.c
@@ -8,6 +8,8 @@
* warranty of any kind, whether express or implied.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sysfs.h>
@@ -115,7 +117,7 @@ static struct platform_device ts78xx_ts_rtc_device = {
* I've used the method TS use in their rtc7800.c example for the detection
*
* TODO: track down a guinea pig without an RTC to see if we can work out a
- * better RTC detection routine
+ * better RTC detection routine
*/
static int ts78xx_ts_rtc_load(void)
{
@@ -141,10 +143,14 @@ static int ts78xx_ts_rtc_load(void)
} else
rc = platform_device_add(&ts78xx_ts_rtc_device);
+ if (rc)
+ pr_info("RTC could not be registered: %d\n",
+ rc);
return rc;
}
}
+ pr_info("RTC not found\n");
return -ENODEV;
};
@@ -292,11 +298,8 @@ static struct platform_nand_data ts78xx_ts_nand_data = {
},
};
-static struct resource ts78xx_ts_nand_resources = {
- .start = TS_NAND_DATA,
- .end = TS_NAND_DATA + 4,
- .flags = IORESOURCE_MEM,
-};
+static struct resource ts78xx_ts_nand_resources
+ = DEFINE_RES_MEM(TS_NAND_DATA, 4);
static struct platform_device ts78xx_ts_nand_device = {
.name = "gen_nand",
@@ -319,6 +322,8 @@ static int ts78xx_ts_nand_load(void)
} else
rc = platform_device_add(&ts78xx_ts_nand_device);
+ if (rc)
+ pr_info("NAND could not be registered: %d\n", rc);
return rc;
};
@@ -332,11 +337,8 @@ static void ts78xx_ts_nand_unload(void)
****************************************************************************/
#define TS_RNG_DATA (TS78XX_FPGA_REGS_PHYS_BASE | 0x044)
-static struct resource ts78xx_ts_rng_resource = {
- .flags = IORESOURCE_MEM,
- .start = TS_RNG_DATA,
- .end = TS_RNG_DATA + 4 - 1,
-};
+static struct resource ts78xx_ts_rng_resource
+ = DEFINE_RES_MEM(TS_RNG_DATA, 4);
static struct timeriomem_rng_data ts78xx_ts_rng_data = {
.period = 1000000, /* one second */
@@ -363,6 +365,8 @@ static int ts78xx_ts_rng_load(void)
} else
rc = platform_device_add(&ts78xx_ts_rng_device);
+ if (rc)
+ pr_info("RNG could not be registered: %d\n", rc);
return rc;
};
@@ -402,7 +406,7 @@ static void ts78xx_fpga_supports(void)
/* enable devices if magic matches */
switch ((ts78xx_fpga.id >> 8) & 0xffffff) {
case TS7800_FPGA_MAGIC:
- pr_warning("TS-7800 FPGA: unrecognized revision 0x%.2x\n",
+ pr_warning("unrecognised FPGA revision 0x%.2x\n",
ts78xx_fpga.id & 0xff);
ts78xx_fpga.supports.ts_rtc.present = 1;
ts78xx_fpga.supports.ts_nand.present = 1;
@@ -422,26 +426,20 @@ static int ts78xx_fpga_load_devices(void)
if (ts78xx_fpga.supports.ts_rtc.present == 1) {
tmp = ts78xx_ts_rtc_load();
- if (tmp) {
- pr_info("TS-78xx: RTC not registered\n");
+ if (tmp)
ts78xx_fpga.supports.ts_rtc.present = 0;
- }
ret |= tmp;
}
if (ts78xx_fpga.supports.ts_nand.present == 1) {
tmp = ts78xx_ts_nand_load();
- if (tmp) {
- pr_info("TS-78xx: NAND not registered\n");
+ if (tmp)
ts78xx_fpga.supports.ts_nand.present = 0;
- }
ret |= tmp;
}
if (ts78xx_fpga.supports.ts_rng.present == 1) {
tmp = ts78xx_ts_rng_load();
- if (tmp) {
- pr_info("TS-78xx: RNG not registered\n");
+ if (tmp)
ts78xx_fpga.supports.ts_rng.present = 0;
- }
ret |= tmp;
}
@@ -466,7 +464,7 @@ static int ts78xx_fpga_load(void)
{
ts78xx_fpga.id = readl(TS78XX_FPGA_REGS_VIRT_BASE);
- pr_info("TS-78xx FPGA: magic=0x%.6x, rev=0x%.2x\n",
+ pr_info("FPGA magic=0x%.6x, rev=0x%.2x\n",
(ts78xx_fpga.id >> 8) & 0xffffff,
ts78xx_fpga.id & 0xff);
@@ -494,7 +492,7 @@ static int ts78xx_fpga_unload(void)
* UrJTAG SVN since r1381 can be used to reprogram the FPGA
*/
if (ts78xx_fpga.id != fpga_id) {
- pr_err("TS-78xx FPGA: magic/rev mismatch\n"
+ pr_err("FPGA magic/rev mismatch\n"
"TS-78xx FPGA: was 0x%.6x/%.2x but now 0x%.6x/%.2x\n",
(ts78xx_fpga.id >> 8) & 0xffffff, ts78xx_fpga.id & 0xff,
(fpga_id >> 8) & 0xffffff, fpga_id & 0xff);
@@ -525,7 +523,7 @@ static ssize_t ts78xx_fpga_store(struct kobject *kobj,
int value, ret;
if (ts78xx_fpga.state < 0) {
- pr_err("TS-78xx FPGA: borked, you must powercycle asap\n");
+ pr_err("FPGA borked, you must powercycle ASAP\n");
return -EBUSY;
}
@@ -533,10 +531,8 @@ static ssize_t ts78xx_fpga_store(struct kobject *kobj,
value = 1;
else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
value = 0;
- else {
- pr_err("ts78xx_fpga_store: Invalid value\n");
+ else
return -EINVAL;
- }
if (ts78xx_fpga.state == value)
return n;
@@ -614,7 +610,7 @@ static void __init ts78xx_init(void)
/* FPGA init */
ts78xx_fpga_devices_zero_init();
ret = ts78xx_fpga_load();
- ret = sysfs_create_file(power_kobj, &ts78xx_fpga_attr.attr);
+ ret = sysfs_create_file(firmware_kobj, &ts78xx_fpga_attr.attr);
if (ret)
pr_err("sysfs_create_file failed: %d\n", ret);
}
diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c
index 078c03f7cd52..754c12b6abf0 100644
--- a/arch/arm/mach-orion5x/wnr854t-setup.c
+++ b/arch/arm/mach-orion5x/wnr854t-setup.c
@@ -155,7 +155,6 @@ static int __init wnr854t_pci_map_irq(const struct pci_dev *dev, u8 slot,
static struct hw_pci wnr854t_pci __initdata = {
.nr_controllers = 2,
- .swizzle = pci_std_swizzle,
.setup = orion5x_pci_sys_setup,
.scan = orion5x_pci_sys_scan_bus,
.map_irq = wnr854t_pci_map_irq,
diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
index 46a9778171ce..45c21251eb1e 100644
--- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c
+++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
@@ -243,7 +243,6 @@ static int __init wrt350n_v2_pci_map_irq(const struct pci_dev *dev, u8 slot,
static struct hw_pci wrt350n_v2_pci __initdata = {
.nr_controllers = 2,
- .swizzle = pci_std_swizzle,
.setup = orion5x_pci_sys_setup,
.scan = orion5x_pci_sys_scan_bus,
.map_irq = wrt350n_v2_pci_map_irq,
diff --git a/arch/arm/mach-pnx4008/i2c.c b/arch/arm/mach-pnx4008/i2c.c
index 8103f9644e2d..550cfc2a1f2e 100644
--- a/arch/arm/mach-pnx4008/i2c.c
+++ b/arch/arm/mach-pnx4008/i2c.c
@@ -16,48 +16,62 @@
#include <linux/err.h>
#include <mach/platform.h>
#include <mach/irqs.h>
-#include <mach/i2c.h>
-static struct i2c_pnx_data i2c0_data = {
- .name = I2C_CHIP_NAME "0",
- .base = PNX4008_I2C1_BASE,
- .irq = I2C_1_INT,
+static struct resource i2c0_resources[] = {
+ {
+ .start = PNX4008_I2C1_BASE,
+ .end = PNX4008_I2C1_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = I2C_1_INT,
+ .end = I2C_1_INT,
+ .flags = IORESOURCE_IRQ,
+ },
};
-static struct i2c_pnx_data i2c1_data = {
- .name = I2C_CHIP_NAME "1",
- .base = PNX4008_I2C2_BASE,
- .irq = I2C_2_INT,
+static struct resource i2c1_resources[] = {
+ {
+ .start = PNX4008_I2C2_BASE,
+ .end = PNX4008_I2C2_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = I2C_2_INT,
+ .end = I2C_2_INT,
+ .flags = IORESOURCE_IRQ,
+ },
};
-static struct i2c_pnx_data i2c2_data = {
- .name = "USB-I2C",
- .base = (PNX4008_USB_CONFIG_BASE + 0x300),
- .irq = USB_I2C_INT,
+static struct resource i2c2_resources[] = {
+ {
+ .start = PNX4008_USB_CONFIG_BASE + 0x300,
+ .end = PNX4008_USB_CONFIG_BASE + 0x300 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = USB_I2C_INT,
+ .end = USB_I2C_INT,
+ .flags = IORESOURCE_IRQ,
+ },
};
static struct platform_device i2c0_device = {
- .name = "pnx-i2c",
+ .name = "pnx-i2c.0",
.id = 0,
- .dev = {
- .platform_data = &i2c0_data,
- },
+ .resource = i2c0_resources,
+ .num_resources = ARRAY_SIZE(i2c0_resources),
};
static struct platform_device i2c1_device = {
- .name = "pnx-i2c",
+ .name = "pnx-i2c.1",
.id = 1,
- .dev = {
- .platform_data = &i2c1_data,
- },
+ .resource = i2c1_resources,
+ .num_resources = ARRAY_SIZE(i2c1_resources),
};
static struct platform_device i2c2_device = {
- .name = "pnx-i2c",
+ .name = "pnx-i2c.2",
.id = 2,
- .dev = {
- .platform_data = &i2c2_data,
- },
+ .resource = i2c2_resources,
+ .num_resources = ARRAY_SIZE(i2c2_resources),
};
static struct platform_device *devices[] __initdata = {
diff --git a/arch/arm/mach-pnx4008/include/mach/i2c.h b/arch/arm/mach-pnx4008/include/mach/i2c.h
deleted file mode 100644
index 259ac53abf40..000000000000
--- a/arch/arm/mach-pnx4008/include/mach/i2c.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * PNX4008-specific tweaks for I2C IP3204 block
- *
- * Author: Vitaly Wool <vwool@ru.mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __ASM_ARCH_I2C_H__
-#define __ASM_ARCH_I2C_H__
-
-enum {
- mstatus_tdi = 0x00000001,
- mstatus_afi = 0x00000002,
- mstatus_nai = 0x00000004,
- mstatus_drmi = 0x00000008,
- mstatus_active = 0x00000020,
- mstatus_scl = 0x00000040,
- mstatus_sda = 0x00000080,
- mstatus_rff = 0x00000100,
- mstatus_rfe = 0x00000200,
- mstatus_tff = 0x00000400,
- mstatus_tfe = 0x00000800,
-};
-
-enum {
- mcntrl_tdie = 0x00000001,
- mcntrl_afie = 0x00000002,
- mcntrl_naie = 0x00000004,
- mcntrl_drmie = 0x00000008,
- mcntrl_daie = 0x00000020,
- mcntrl_rffie = 0x00000040,
- mcntrl_tffie = 0x00000080,
- mcntrl_reset = 0x00000100,
- mcntrl_cdbmode = 0x00000400,
-};
-
-enum {
- rw_bit = 1 << 0,
- start_bit = 1 << 8,
- stop_bit = 1 << 9,
-};
-
-#define I2C_REG_RX(a) ((a)->ioaddr) /* Rx FIFO reg (RO) */
-#define I2C_REG_TX(a) ((a)->ioaddr) /* Tx FIFO reg (WO) */
-#define I2C_REG_STS(a) ((a)->ioaddr + 0x04) /* Status reg (RO) */
-#define I2C_REG_CTL(a) ((a)->ioaddr + 0x08) /* Ctl reg */
-#define I2C_REG_CKL(a) ((a)->ioaddr + 0x0c) /* Clock divider low */
-#define I2C_REG_CKH(a) ((a)->ioaddr + 0x10) /* Clock divider high */
-#define I2C_REG_ADR(a) ((a)->ioaddr + 0x14) /* I2C address */
-#define I2C_REG_RFL(a) ((a)->ioaddr + 0x18) /* Rx FIFO level (RO) */
-#define I2C_REG_TFL(a) ((a)->ioaddr + 0x1c) /* Tx FIFO level (RO) */
-#define I2C_REG_RXB(a) ((a)->ioaddr + 0x20) /* Num of bytes Rx-ed (RO) */
-#define I2C_REG_TXB(a) ((a)->ioaddr + 0x24) /* Num of bytes Tx-ed (RO) */
-#define I2C_REG_TXS(a) ((a)->ioaddr + 0x28) /* Tx slave FIFO (RO) */
-#define I2C_REG_STFL(a) ((a)->ioaddr + 0x2c) /* Tx slave FIFO level (RO) */
-
-#define HCLK_MHZ 13
-#define I2C_CHIP_NAME "PNX4008-I2C"
-
-#endif /* __ASM_ARCH_I2C_H___ */
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c
index 37c2de9b6f26..a7b9415d30f8 100644
--- a/arch/arm/mach-prima2/irq.c
+++ b/arch/arm/mach-prima2/irq.c
@@ -42,7 +42,8 @@ sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
static __init void sirfsoc_irq_init(void)
{
sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32);
- sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32, SIRFSOC_INTENAL_IRQ_END - 32);
+ sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32,
+ SIRFSOC_INTENAL_IRQ_END + 1 - 32);
writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
@@ -68,7 +69,8 @@ void __init sirfsoc_of_irq_init(void)
if (!sirfsoc_intc_base)
panic("unable to map intc cpu registers\n");
- irq_domain_add_legacy(np, 32, 0, 0, &irq_domain_simple_ops, NULL);
+ irq_domain_add_legacy(np, SIRFSOC_INTENAL_IRQ_END + 1, 0, 0,
+ &irq_domain_simple_ops, NULL);
of_node_put(np);
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index c35456f02acb..56e8cebeb7d5 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -732,9 +732,7 @@ static inline void balloon3_nand_init(void) {}
#if defined(CONFIG_REGULATOR_MAX1586) || \
defined(CONFIG_REGULATOR_MAX1586_MODULE)
static struct regulator_consumer_supply balloon3_max1587a_consumers[] = {
- {
- .supply = "vcc_core",
- }
+ REGULATOR_SUPPLY("vcc_core", NULL),
};
static struct regulator_init_data balloon3_max1587a_v3_info = {
diff --git a/arch/arm/mach-pxa/cm-x2xx-pci.c b/arch/arm/mach-pxa/cm-x2xx-pci.c
index ebd9259f5ac9..d8f816c24a2f 100644
--- a/arch/arm/mach-pxa/cm-x2xx-pci.c
+++ b/arch/arm/mach-pxa/cm-x2xx-pci.c
@@ -181,11 +181,10 @@ static void cmx2xx_pci_preinit(void)
}
static struct hw_pci cmx2xx_pci __initdata = {
- .swizzle = pci_std_swizzle,
.map_irq = cmx2xx_pci_map_irq,
.nr_controllers = 1,
+ .ops = &it8152_ops,
.setup = it8152_pci_setup,
- .scan = it8152_pci_scan_bus,
.preinit = cmx2xx_pci_preinit,
};
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index 313274016277..3e4e9fe2d462 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -713,9 +713,7 @@ struct da9030_battery_info cm_x300_battery_info = {
};
static struct regulator_consumer_supply buck2_consumers[] = {
- {
- .supply = "vcc_core",
- },
+ REGULATOR_SUPPLY("vcc_core", NULL),
};
static struct regulator_init_data buck2_data = {
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 16ec557b8e43..a3a4a38d4972 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -1085,10 +1085,7 @@ static void __init em_x270_userspace_consumers_init(void)
/* DA9030 related initializations */
#define REGULATOR_CONSUMER(_name, _dev_name, _supply) \
static struct regulator_consumer_supply _name##_consumers[] = { \
- { \
- .dev_name = _dev_name, \
- .supply = _supply, \
- }, \
+ REGULATOR_SUPPLY(_supply, _dev_name), \
}
REGULATOR_CONSUMER(ldo3, "reg-userspace-consumer.0", "vcc gps");
diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c
index b83b95a29503..d09da6a746b8 100644
--- a/arch/arm/mach-pxa/hx4700.c
+++ b/arch/arm/mach-pxa/hx4700.c
@@ -22,6 +22,7 @@
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
+#include <linux/input/navpoint.h>
#include <linux/lcd.h>
#include <linux/mfd/htc-egpio.h>
#include <linux/mfd/asic3.h>
@@ -102,6 +103,10 @@ static unsigned long hx4700_pin_config[] __initdata = {
GPIO44_BTUART_CTS,
GPIO45_BTUART_RTS_LPM_LOW,
+ /* STUART (IRDA) */
+ GPIO46_STUART_RXD,
+ GPIO47_STUART_TXD,
+
/* PWM 1 (Backlight) */
GPIO17_PWM1_OUT,
@@ -113,7 +118,7 @@ static unsigned long hx4700_pin_config[] __initdata = {
GPIO113_I2S_SYSCLK,
/* SSP 1 (NavPoint) */
- GPIO23_SSP1_SCLK,
+ GPIO23_SSP1_SCLK_IN,
GPIO24_SSP1_SFRM,
GPIO25_SSP1_TXD,
GPIO26_SSP1_RXD,
@@ -125,10 +130,13 @@ static unsigned long hx4700_pin_config[] __initdata = {
GPIO88_GPIO,
/* HX4700 specific input GPIOs */
- GPIO12_GPIO, /* ASIC3_IRQ */
+ GPIO12_GPIO | WAKEUP_ON_EDGE_RISE, /* ASIC3_IRQ */
GPIO13_GPIO, /* W3220_IRQ */
GPIO14_GPIO, /* nWLAN_IRQ */
+ /* HX4700 specific output GPIOs */
+ GPIO102_GPIO | MFP_LPM_DRIVE_LOW, /* SYNAPTICS_POWER_ON */
+
GPIO10_GPIO, /* GSM_IRQ */
GPIO13_GPIO, /* CPLD_IRQ */
GPIO107_GPIO, /* DS1WM_IRQ */
@@ -183,6 +191,23 @@ static struct platform_device gpio_keys = {
};
/*
+ * Synaptics NavPoint connected to SSP1
+ */
+
+static struct navpoint_platform_data navpoint_platform_data = {
+ .port = 1,
+ .gpio = GPIO102_HX4700_SYNAPTICS_POWER_ON,
+};
+
+static struct platform_device navpoint = {
+ .name = "navpoint",
+ .id = -1,
+ .dev = {
+ .platform_data = &navpoint_platform_data,
+ },
+};
+
+/*
* ASIC3
*/
@@ -227,7 +252,6 @@ static u16 asic3_gpio_config[] = {
ASIC3_GPIOC0_LED0, /* red */
ASIC3_GPIOC1_LED1, /* green */
ASIC3_GPIOC2_LED2, /* blue */
- ASIC3_GPIOC4_CF_nCD,
ASIC3_GPIOC5_nCIOW,
ASIC3_GPIOC6_nCIOR,
ASIC3_GPIOC7_nPCE_1,
@@ -241,6 +265,7 @@ static u16 asic3_gpio_config[] = {
ASIC3_GPIOC15_nPIOR,
/* GPIOD: input GPIOs, CF */
+ ASIC3_GPIOD4_CF_nCD,
ASIC3_GPIOD11_nCIOIS16,
ASIC3_GPIOD12_nCWAIT,
ASIC3_GPIOD15_nPIOW,
@@ -291,6 +316,7 @@ static struct asic3_platform_data asic3_platform_data = {
.gpio_config_num = ARRAY_SIZE(asic3_gpio_config),
.irq_base = IRQ_BOARD_START,
.gpio_base = HX4700_ASIC3_GPIO_BASE,
+ .clock_rate = 4000000,
.leds = asic3_leds,
};
@@ -680,12 +706,8 @@ static struct platform_device power_supply = {
*/
static struct regulator_consumer_supply bq24022_consumers[] = {
- {
- .supply = "vbus_draw",
- },
- {
- .supply = "ac_draw",
- },
+ REGULATOR_SUPPLY("vbus_draw", NULL),
+ REGULATOR_SUPPLY("ac_draw", NULL),
};
static struct regulator_init_data bq24022_init_data = {
@@ -764,9 +786,8 @@ static struct platform_device strataflash = {
* Maxim MAX1587A on PI2C
*/
-static struct regulator_consumer_supply max1587a_consumer = {
- .supply = "vcc_core",
-};
+static struct regulator_consumer_supply max1587a_consumer =
+ REGULATOR_SUPPLY("vcc_core", NULL);
static struct regulator_init_data max1587a_v3_info = {
.constraints = {
@@ -828,6 +849,7 @@ static struct platform_device audio = {
static struct platform_device *devices[] __initdata = {
&asic3,
&gpio_keys,
+ &navpoint,
&backlight,
&w3220,
&hx4700_lcd,
@@ -859,6 +881,7 @@ static void __init hx4700_init(void)
int ret;
pxa2xx_mfp_config(ARRAY_AND_SIZE(hx4700_pin_config));
+ gpio_set_wake(GPIO12_HX4700_ASIC3_IRQ, 1);
ret = gpio_request_array(ARRAY_AND_SIZE(global_gpios));
if (ret)
pr_err ("hx4700: Failed to request GPIOs.\n");
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
index a65867209aa0..a611ad3153c7 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
@@ -208,6 +208,7 @@
#define GPIO113_I2S_SYSCLK MFP_CFG_OUT(GPIO113, AF1, DRIVE_LOW)
/* SSP 1 */
+#define GPIO23_SSP1_SCLK_IN MFP_CFG_IN(GPIO23, AF2)
#define GPIO23_SSP1_SCLK MFP_CFG_OUT(GPIO23, AF2, DRIVE_LOW)
#define GPIO29_SSP1_SCLK MFP_CFG_IN(GPIO29, AF3)
#define GPIO27_SSP1_SYSCLK MFP_CFG_OUT(GPIO27, AF1, DRIVE_LOW)
diff --git a/arch/arm/mach-pxa/include/mach/mioa701.h b/arch/arm/mach-pxa/include/mach/mioa701.h
index 02868447b0b1..e57f5c724e8a 100644
--- a/arch/arm/mach-pxa/include/mach/mioa701.h
+++ b/arch/arm/mach-pxa/include/mach/mioa701.h
@@ -61,6 +61,9 @@
#define GPIO93_KEY_VOLUME_UP 93
#define GPIO94_KEY_VOLUME_DOWN 94
+/* Camera */
+#define GPIO56_MT9M111_nOE 56
+
extern struct input_dev *mioa701_evdev;
extern void mioa701_gpio_lpm_set(unsigned long mfp_pin);
diff --git a/arch/arm/mach-pxa/include/mach/pcm990_baseboard.h b/arch/arm/mach-pxa/include/mach/pcm990_baseboard.h
index d72791695b26..0260aaa2fc17 100644
--- a/arch/arm/mach-pxa/include/mach/pcm990_baseboard.h
+++ b/arch/arm/mach-pxa/include/mach/pcm990_baseboard.h
@@ -31,7 +31,6 @@
#define PCM990_CTRL_INT_IRQ PXA_GPIO_TO_IRQ(PCM990_CTRL_INT_IRQ_GPIO)
#define PCM990_CTRL_INT_IRQ_EDGE IRQ_TYPE_EDGE_RISING
#define PCM990_CTRL_PHYS PXA_CS1_PHYS /* 16-Bit */
-#define PCM990_CTRL_BASE 0xea000000
#define PCM990_CTRL_SIZE (1*1024*1024)
#define PCM990_CTRL_PWR_IRQ_GPIO 14
@@ -69,13 +68,13 @@
#define PCM990_CTRL_MMC2DE 0x0004 /* R MMC2 Card detect */
#define PCM990_CTRL_MMC2WP 0x0008 /* R MMC2 Card write protect */
-#define PCM990_CTRL_REG6 0x000C /* Interrupt Clear REGISTER */
+#define PCM990_CTRL_INTSETCLR 0x000C /* Interrupt Clear REGISTER */
#define PCM990_CTRL_INTC0 0x0001 /* Clear Reg BT Detect */
#define PCM990_CTRL_INTC1 0x0002 /* Clear Reg FR RI */
#define PCM990_CTRL_INTC2 0x0004 /* Clear Reg MMC1 Detect */
#define PCM990_CTRL_INTC3 0x0008 /* Clear Reg PM_5V off */
-#define PCM990_CTRL_REG7 0x000E /* Interrupt Enable REGISTER */
+#define PCM990_CTRL_INTMSKENA 0x000E /* Interrupt Enable REGISTER */
#define PCM990_CTRL_ENAINT0 0x0001 /* Enable Int BT Detect */
#define PCM990_CTRL_ENAINT1 0x0002 /* Enable Int FR RI */
#define PCM990_CTRL_ENAINT2 0x0004 /* Enable Int MMC1 Detect */
@@ -102,32 +101,6 @@
#define PCM990_CTRL_ACPRES 0x0004 /* DC Present */
#define PCM990_CTRL_ACALARM 0x0008 /* Error Akku */
-#define PCM990_CTRL_P2V(x) ((x) - PCM990_CTRL_PHYS + PCM990_CTRL_BASE)
-#define PCM990_CTRL_V2P(x) ((x) - PCM990_CTRL_BASE + PCM990_CTRL_PHYS)
-
-#ifndef __ASSEMBLY__
-# define __PCM990_CTRL_REG(x) \
- (*((volatile unsigned char *)PCM990_CTRL_P2V(x)))
-#else
-# define __PCM990_CTRL_REG(x) PCM990_CTRL_P2V(x)
-#endif
-
-#define PCM990_INTMSKENA __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG7)
-#define PCM990_INTSETCLR __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG6)
-#define PCM990_CTRL0 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG0)
-#define PCM990_CTRL1 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG1)
-#define PCM990_CTRL2 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG2)
-#define PCM990_CTRL3 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG3)
-#define PCM990_CTRL4 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG4)
-#define PCM990_CTRL5 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG5)
-#define PCM990_CTRL6 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG6)
-#define PCM990_CTRL7 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG7)
-#define PCM990_CTRL8 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG8)
-#define PCM990_CTRL9 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG9)
-#define PCM990_CTRL10 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG10)
-#define PCM990_CTRL11 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG11)
-
-
/*
* IDE
*/
@@ -166,24 +139,6 @@
#define PCM990_IDE_PLD_P2V(x) ((x) - PCM990_IDE_PLD_PHYS + PCM990_IDE_PLD_BASE)
#define PCM990_IDE_PLD_V2P(x) ((x) - PCM990_IDE_PLD_BASE + PCM990_IDE_PLD_PHYS)
-#ifndef __ASSEMBLY__
-# define __PCM990_IDE_PLD_REG(x) \
- (*((volatile unsigned char *)PCM990_IDE_PLD_P2V(x)))
-#else
-# define __PCM990_IDE_PLD_REG(x) PCM990_IDE_PLD_P2V(x)
-#endif
-
-#define PCM990_IDE0 \
- __PCM990_IDE_PLD_REG(PCM990_IDE_PLD_PHYS + PCM990_IDE_PLD_REG0)
-#define PCM990_IDE1 \
- __PCM990_IDE_PLD_REG(PCM990_IDE_PLD_PHYS + PCM990_IDE_PLD_REG1)
-#define PCM990_IDE2 \
- __PCM990_IDE_PLD_REG(PCM990_IDE_PLD_PHYS + PCM990_IDE_PLD_REG2)
-#define PCM990_IDE3 \
- __PCM990_IDE_PLD_REG(PCM990_IDE_PLD_PHYS + PCM990_IDE_PLD_REG3)
-#define PCM990_IDE4 \
- __PCM990_IDE_PLD_REG(PCM990_IDE_PLD_PHYS + PCM990_IDE_PLD_REG4)
-
/*
* Compact Flash
*/
@@ -196,10 +151,6 @@
#define PCM990_CF_CD_EDGE IRQ_TYPE_EDGE_RISING
#define PCM990_CF_PLD_PHYS 0x30000000 /* 16 bit wide */
-#define PCM990_CF_PLD_BASE 0xef000000
-#define PCM990_CF_PLD_SIZE (1*1024*1024)
-#define PCM990_CF_PLD_P2V(x) ((x) - PCM990_CF_PLD_PHYS + PCM990_CF_PLD_BASE)
-#define PCM990_CF_PLD_V2P(x) ((x) - PCM990_CF_PLD_BASE + PCM990_CF_PLD_PHYS)
/* visible CPLD (U6) registers */
#define PCM990_CF_PLD_REG0 0x1000 /* OFFSET CF REGISTER 0 */
@@ -239,21 +190,6 @@
#define PCM990_CF_REG6_CD1 0x0001 /* R CF Card_Detect1 */
#define PCM990_CF_REG6_CD2 0x0002 /* R CF Card_Detect2 */
-#ifndef __ASSEMBLY__
-# define __PCM990_CF_PLD_REG(x) \
- (*((volatile unsigned char *)PCM990_CF_PLD_P2V(x)))
-#else
-# define __PCM990_CF_PLD_REG(x) PCM990_CF_PLD_P2V(x)
-#endif
-
-#define PCM990_CF0 __PCM990_CF_PLD_REG(PCM990_CF_PLD_PHYS + PCM990_CF_PLD_REG0)
-#define PCM990_CF1 __PCM990_CF_PLD_REG(PCM990_CF_PLD_PHYS + PCM990_CF_PLD_REG1)
-#define PCM990_CF2 __PCM990_CF_PLD_REG(PCM990_CF_PLD_PHYS + PCM990_CF_PLD_REG2)
-#define PCM990_CF3 __PCM990_CF_PLD_REG(PCM990_CF_PLD_PHYS + PCM990_CF_PLD_REG3)
-#define PCM990_CF4 __PCM990_CF_PLD_REG(PCM990_CF_PLD_PHYS + PCM990_CF_PLD_REG4)
-#define PCM990_CF5 __PCM990_CF_PLD_REG(PCM990_CF_PLD_PHYS + PCM990_CF_PLD_REG5)
-#define PCM990_CF6 __PCM990_CF_PLD_REG(PCM990_CF_PLD_PHYS + PCM990_CF_PLD_REG6)
-
/*
* Wolfson AC97 Touch
*/
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index 8de0651d7efb..2db697cd2b4e 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -579,12 +579,8 @@ static struct platform_device power_supply = {
*/
static struct regulator_consumer_supply bq24022_consumers[] = {
- {
- .supply = "vbus_draw",
- },
- {
- .supply = "ac_draw",
- },
+ REGULATOR_SUPPLY("vbus_draw", NULL),
+ REGULATOR_SUPPLY("ac_draw", NULL),
};
static struct regulator_init_data bq24022_init_data = {
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 061d57009cee..bf99022b021f 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -103,6 +103,7 @@ static unsigned long mioa701_pin_config[] = {
GPIO82_CIF_DD_5,
GPIO84_CIF_FV,
GPIO85_CIF_LV,
+ MIO_CFG_OUT(GPIO56_MT9M111_nOE, AF0, DRIVE_LOW),
/* Bluetooth */
MIO_CFG_IN(GPIO14_BT_nACTIVITY, AF0),
@@ -581,9 +582,7 @@ static struct wm97xx_pdata mioa701_wm97xx_pdata = {
* Voltage regulation
*/
static struct regulator_consumer_supply max1586_consumers[] = {
- {
- .supply = "vcc_core",
- }
+ REGULATOR_SUPPLY("vcc_core", NULL),
};
static struct regulator_init_data max1586_v3_info = {
@@ -705,6 +704,7 @@ static struct gpio global_gpios[] = {
{ GPIO9_CHARGE_EN, GPIOF_OUT_INIT_HIGH, "Charger enable" },
{ GPIO18_POWEROFF, GPIOF_OUT_INIT_LOW, "Power Off" },
{ GPIO87_LCD_POWER, GPIOF_OUT_INIT_LOW, "LCD Power" },
+ { GPIO56_MT9M111_nOE, GPIOF_OUT_INIT_LOW, "Camera nOE" },
};
static void __init mioa701_machine_init(void)
diff --git a/arch/arm/mach-pxa/palm27x.c b/arch/arm/mach-pxa/palm27x.c
index fbc10d7b95d1..dad71cfa34c8 100644
--- a/arch/arm/mach-pxa/palm27x.c
+++ b/arch/arm/mach-pxa/palm27x.c
@@ -429,9 +429,7 @@ void __init palm27x_power_init(int ac, int usb)
#if defined(CONFIG_REGULATOR_MAX1586) || \
defined(CONFIG_REGULATOR_MAX1586_MODULE)
static struct regulator_consumer_supply palm27x_max1587a_consumers[] = {
- {
- .supply = "vcc_core",
- }
+ REGULATOR_SUPPLY("vcc_core", NULL),
};
static struct regulator_init_data palm27x_max1587a_v3_info = {
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index abab4e2b122c..cb723e84bc27 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -65,6 +65,18 @@ static unsigned long pcm990_pin_config[] __initdata = {
GPIO31_AC97_SYNC,
};
+static void __iomem *pcm990_cpld_base;
+
+static u8 pcm990_cpld_readb(unsigned int reg)
+{
+ return readb(pcm990_cpld_base + reg);
+}
+
+static void pcm990_cpld_writeb(u8 value, unsigned int reg)
+{
+ writeb(value, pcm990_cpld_base + reg);
+}
+
/*
* pcm990_lcd_power - control power supply to the LCD
* @on: 0 = switch off, 1 = switch on
@@ -78,13 +90,13 @@ static void pcm990_lcd_power(int on, struct fb_var_screeninfo *var)
/* enable LCD-Latches
* power on LCD
*/
- __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG3) =
- PCM990_CTRL_LCDPWR + PCM990_CTRL_LCDON;
+ pcm990_cpld_writeb(PCM990_CTRL_LCDPWR + PCM990_CTRL_LCDON,
+ PCM990_CTRL_REG3);
} else {
/* disable LCD-Latches
* power off LCD
*/
- __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG3) = 0x00;
+ pcm990_cpld_writeb(0, PCM990_CTRL_REG3);
}
}
#endif
@@ -243,15 +255,26 @@ static unsigned long pcm990_irq_enabled;
static void pcm990_mask_ack_irq(struct irq_data *d)
{
int pcm990_irq = (d->irq - PCM027_IRQ(0));
- PCM990_INTMSKENA = (pcm990_irq_enabled &= ~(1 << pcm990_irq));
+
+ pcm990_irq_enabled &= ~(1 << pcm990_irq);
+
+ pcm990_cpld_writeb(pcm990_irq_enabled, PCM990_CTRL_INTMSKENA);
}
static void pcm990_unmask_irq(struct irq_data *d)
{
int pcm990_irq = (d->irq - PCM027_IRQ(0));
+ u8 val;
+
/* the irq can be acknowledged only if deasserted, so it's done here */
- PCM990_INTSETCLR |= 1 << pcm990_irq;
- PCM990_INTMSKENA = (pcm990_irq_enabled |= (1 << pcm990_irq));
+
+ pcm990_irq_enabled |= (1 << pcm990_irq);
+
+ val = pcm990_cpld_readb(PCM990_CTRL_INTSETCLR);
+ val |= 1 << pcm990_irq;
+ pcm990_cpld_writeb(val, PCM990_CTRL_INTSETCLR);
+
+ pcm990_cpld_writeb(pcm990_irq_enabled, PCM990_CTRL_INTMSKENA);
}
static struct irq_chip pcm990_irq_chip = {
@@ -261,7 +284,10 @@ static struct irq_chip pcm990_irq_chip = {
static void pcm990_irq_handler(unsigned int irq, struct irq_desc *desc)
{
- unsigned long pending = (~PCM990_INTSETCLR) & pcm990_irq_enabled;
+ unsigned long pending;
+
+ pending = ~pcm990_cpld_readb(PCM990_CTRL_INTSETCLR);
+ pending &= pcm990_irq_enabled;
do {
/* clear our parent IRQ */
@@ -270,7 +296,8 @@ static void pcm990_irq_handler(unsigned int irq, struct irq_desc *desc)
irq = PCM027_IRQ(0) + __ffs(pending);
generic_handle_irq(irq);
}
- pending = (~PCM990_INTSETCLR) & pcm990_irq_enabled;
+ pending = ~pcm990_cpld_readb(PCM990_CTRL_INTSETCLR);
+ pending &= pcm990_irq_enabled;
} while (pending);
}
@@ -285,8 +312,9 @@ static void __init pcm990_init_irq(void)
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
- PCM990_INTMSKENA = 0x00; /* disable all Interrupts */
- PCM990_INTSETCLR = 0xFF;
+ /* disable all Interrupts */
+ pcm990_cpld_writeb(0x0, PCM990_CTRL_INTMSKENA);
+ pcm990_cpld_writeb(0xff, PCM990_CTRL_INTSETCLR);
irq_set_chained_handler(PCM990_CTRL_INT_IRQ, pcm990_irq_handler);
irq_set_irq_type(PCM990_CTRL_INT_IRQ, PCM990_CTRL_INT_IRQ_EDGE);
@@ -309,13 +337,16 @@ static int pcm990_mci_init(struct device *dev, irq_handler_t mci_detect_int,
static void pcm990_mci_setpower(struct device *dev, unsigned int vdd)
{
struct pxamci_platform_data *p_d = dev->platform_data;
+ u8 val;
+
+ val = pcm990_cpld_readb(PCM990_CTRL_REG5);
if ((1 << vdd) & p_d->ocr_mask)
- __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG5) =
- PCM990_CTRL_MMC2PWR;
+ val |= PCM990_CTRL_MMC2PWR;
else
- __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG5) =
- ~PCM990_CTRL_MMC2PWR;
+ val &= ~PCM990_CTRL_MMC2PWR;
+
+ pcm990_cpld_writeb(PCM990_CTRL_MMC2PWR, PCM990_CTRL_REG5);
}
static void pcm990_mci_exit(struct device *dev, void *data)
@@ -481,23 +512,6 @@ static struct platform_device pcm990_camera[] = {
#endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */
/*
- * enable generic access to the base board control CPLDs U6 and U7
- */
-static struct map_desc pcm990_io_desc[] __initdata = {
- {
- .virtual = PCM990_CTRL_BASE,
- .pfn = __phys_to_pfn(PCM990_CTRL_PHYS),
- .length = PCM990_CTRL_SIZE,
- .type = MT_DEVICE /* CPLD */
- }, {
- .virtual = PCM990_CF_PLD_BASE,
- .pfn = __phys_to_pfn(PCM990_CF_PLD_PHYS),
- .length = PCM990_CF_PLD_SIZE,
- .type = MT_DEVICE /* CPLD */
- }
-};
-
-/*
* system init for baseboard usage. Will be called by pcm027 init.
*
* Add platform devices present on this baseboard and init
@@ -507,8 +521,11 @@ void __init pcm990_baseboard_init(void)
{
pxa2xx_mfp_config(ARRAY_AND_SIZE(pcm990_pin_config));
- /* register CPLD access */
- iotable_init(ARRAY_AND_SIZE(pcm990_io_desc));
+ pcm990_cpld_base = ioremap(PCM990_CTRL_PHYS, PCM990_CTRL_SIZE);
+ if (!pcm990_cpld_base) {
+ pr_err("pcm990: failed to ioremap cpld\n");
+ return;
+ }
/* register CPLD's IRQ controller */
pcm990_init_irq();
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index df2ab0fb2ace..363d91b44ecb 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -877,9 +877,7 @@ static struct i2c_board_info spitz_i2c_devs[] = {
};
static struct regulator_consumer_supply isl6271a_consumers[] = {
- {
- .supply = "vcc_core",
- }
+ REGULATOR_SUPPLY("vcc_core", NULL),
};
static struct regulator_init_data isl6271a_info[] = {
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index 4cd645e29b64..30b1b0b3c7f7 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -151,10 +151,7 @@ static struct platform_device sht15 = {
};
static struct regulator_consumer_supply stargate2_sensor_3_con[] = {
- {
- .dev_name = "sht15",
- .supply = "vcc",
- },
+ REGULATOR_SUPPLY("vcc", "sht15"),
};
enum stargate2_ldos{
diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c
index c57ab636ea9c..e1740acd15f1 100644
--- a/arch/arm/mach-pxa/vpac270.c
+++ b/arch/arm/mach-pxa/vpac270.c
@@ -640,9 +640,7 @@ static inline void vpac270_ide_init(void) {}
#if defined(CONFIG_REGULATOR_MAX1586) || \
defined(CONFIG_REGULATOR_MAX1586_MODULE)
static struct regulator_consumer_supply vpac270_max1587a_consumers[] = {
- {
- .supply = "vcc_core",
- }
+ REGULATOR_SUPPLY("vcc_core", NULL),
};
static struct regulator_init_data vpac270_max1587a_v3_info = {
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index fa8619970841..b9320cb8a11f 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -615,9 +615,7 @@ static inline void z2_spi_init(void) {}
#if defined(CONFIG_REGULATOR_TPS65023) || \
defined(CONFIG_REGULATOR_TPS65023_MODULE)
static struct regulator_consumer_supply z2_tps65021_consumers[] = {
- {
- .supply = "vcc_core",
- }
+ REGULATOR_SUPPLY("vcc_core", NULL),
};
static struct regulator_init_data z2_tps65021_info[] = {
diff --git a/arch/arm/mach-s3c24xx/bast-ide.c b/arch/arm/mach-s3c24xx/bast-ide.c
index 298ececfa366..ba02cf8d80a2 100644
--- a/arch/arm/mach-s3c24xx/bast-ide.c
+++ b/arch/arm/mach-s3c24xx/bast-ide.c
@@ -37,21 +37,9 @@ static struct pata_platform_info bast_ide_platdata = {
#define IDE_CS S3C2410_CS5
static struct resource bast_ide0_resource[] = {
- [0] = {
- .start = IDE_CS + BAST_PA_IDEPRI,
- .end = IDE_CS + BAST_PA_IDEPRI + (8 * 0x20) - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IDE_CS + BAST_PA_IDEPRIAUX + (6 * 0x20) ,
- .end = IDE_CS + BAST_PA_IDEPRIAUX + (7 * 0x20) - 1,
- .flags = IORESOURCE_MEM,
- },
- [2] = {
- .start = IRQ_IDE0,
- .end = IRQ_IDE0,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(IDE_CS + BAST_PA_IDEPRI, 8 * 0x20),
+ [1] = DEFINE_RES_MEM(IDE_CS + BAST_PA_IDEPRIAUX + (6 * 0x20), 0x20),
+ [2] = DEFINE_RES_IRQ(IRQ_IDE0),
};
static struct platform_device bast_device_ide0 = {
@@ -67,21 +55,9 @@ static struct platform_device bast_device_ide0 = {
};
static struct resource bast_ide1_resource[] = {
- [0] = {
- .start = IDE_CS + BAST_PA_IDESEC,
- .end = IDE_CS + BAST_PA_IDESEC + (8 * 0x20) - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IDE_CS + BAST_PA_IDESECAUX + (6 * 0x20),
- .end = IDE_CS + BAST_PA_IDESECAUX + (7 * 0x20) - 1,
- .flags = IORESOURCE_MEM,
- },
- [2] = {
- .start = IRQ_IDE1,
- .end = IRQ_IDE1,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(IDE_CS + BAST_PA_IDESEC, 8 * 0x20),
+ [1] = DEFINE_RES_MEM(IDE_CS + BAST_PA_IDESECAUX + (6 * 0x20), 0x20),
+ [2] = DEFINE_RES_IRQ(IRQ_IDE1),
};
static struct platform_device bast_device_ide1 = {
diff --git a/arch/arm/mach-s3c24xx/mach-amlm5900.c b/arch/arm/mach-s3c24xx/mach-amlm5900.c
index 4220cc60de3c..ea2c4b003d58 100644
--- a/arch/arm/mach-s3c24xx/mach-amlm5900.c
+++ b/arch/arm/mach-s3c24xx/mach-amlm5900.c
@@ -65,13 +65,8 @@
#include "common.h"
-static struct resource amlm5900_nor_resource = {
- .start = 0x00000000,
- .end = 0x01000000 - 1,
- .flags = IORESOURCE_MEM,
-};
-
-
+static struct resource amlm5900_nor_resource =
+ DEFINE_RES_MEM(0x00000000, SZ_16M);
static struct mtd_partition amlm5900_mtd_partitions[] = {
{
diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c
index 60c72c54c21e..5a7d0c0010f7 100644
--- a/arch/arm/mach-s3c24xx/mach-anubis.c
+++ b/arch/arm/mach-s3c24xx/mach-anubis.c
@@ -235,19 +235,9 @@ static struct pata_platform_info anubis_ide_platdata = {
};
static struct resource anubis_ide0_resource[] = {
- {
- .start = S3C2410_CS3,
- .end = S3C2410_CS3 + (8*32) - 1,
- .flags = IORESOURCE_MEM,
- }, {
- .start = S3C2410_CS3 + (1<<26) + (6*32),
- .end = S3C2410_CS3 + (1<<26) + (7*32) - 1,
- .flags = IORESOURCE_MEM,
- }, {
- .start = IRQ_IDE0,
- .end = IRQ_IDE0,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(S3C2410_CS3, 8 * 32),
+ [2] = DEFINE_RES_MEM(S3C2410_CS3 + (1 << 26) + (6 * 32), 32),
+ [3] = DEFINE_RES_IRQ(IRQ_IDE0),
};
static struct platform_device anubis_device_ide0 = {
@@ -262,19 +252,9 @@ static struct platform_device anubis_device_ide0 = {
};
static struct resource anubis_ide1_resource[] = {
- {
- .start = S3C2410_CS4,
- .end = S3C2410_CS4 + (8*32) - 1,
- .flags = IORESOURCE_MEM,
- }, {
- .start = S3C2410_CS4 + (1<<26) + (6*32),
- .end = S3C2410_CS4 + (1<<26) + (7*32) - 1,
- .flags = IORESOURCE_MEM,
- }, {
- .start = IRQ_IDE0,
- .end = IRQ_IDE0,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(S3C2410_CS4, 8 * 32),
+ [1] = DEFINE_RES_MEM(S3C2410_CS4 + (1 << 26) + (6 * 32), 32),
+ [2] = DEFINE_RES_IRQ(IRQ_IDE0),
};
static struct platform_device anubis_device_ide1 = {
@@ -298,16 +278,8 @@ static struct ax_plat_data anubis_asix_platdata = {
};
static struct resource anubis_asix_resource[] = {
- [0] = {
- .start = S3C2410_CS5,
- .end = S3C2410_CS5 + (0x20 * 0x20) -1,
- .flags = IORESOURCE_MEM
- },
- [1] = {
- .start = IRQ_ASIX,
- .end = IRQ_ASIX,
- .flags = IORESOURCE_IRQ
- }
+ [0] = DEFINE_RES_MEM(S3C2410_CS5, 0x20 * 0x20),
+ [1] = DEFINE_RES_IRQ(IRQ_ASIX),
};
static struct platform_device anubis_device_asix = {
@@ -323,21 +295,9 @@ static struct platform_device anubis_device_asix = {
/* SM501 */
static struct resource anubis_sm501_resource[] = {
- [0] = {
- .start = S3C2410_CS2,
- .end = S3C2410_CS2 + SZ_8M,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = S3C2410_CS2 + SZ_64M - SZ_2M,
- .end = S3C2410_CS2 + SZ_64M - 1,
- .flags = IORESOURCE_MEM,
- },
- [2] = {
- .start = IRQ_EINT0,
- .end = IRQ_EINT0,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(S3C2410_CS2, SZ_8M),
+ [1] = DEFINE_RES_MEM(S3C2410_CS2 + SZ_64M - SZ_2M, SZ_2M),
+ [2] = DEFINE_RES_IRQ(IRQ_EINT0),
};
static struct sm501_initdata anubis_sm501_initdata = {
diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c
index d7ae49c90118..7a05abf1270b 100644
--- a/arch/arm/mach-s3c24xx/mach-at2440evb.c
+++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c
@@ -118,21 +118,10 @@ static struct s3c2410_platform_nand __initdata at2440evb_nand_info = {
/* DM9000AEP 10/100 ethernet controller */
static struct resource at2440evb_dm9k_resource[] = {
- [0] = {
- .start = S3C2410_CS3,
- .end = S3C2410_CS3 + 3,
- .flags = IORESOURCE_MEM
- },
- [1] = {
- .start = S3C2410_CS3 + 4,
- .end = S3C2410_CS3 + 7,
- .flags = IORESOURCE_MEM
- },
- [2] = {
- .start = IRQ_EINT7,
- .end = IRQ_EINT7,
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
- }
+ [0] = DEFINE_RES_MEM(S3C2410_CS3, 4),
+ [1] = DEFINE_RES_MEM(S3C2410_CS3 + 4, 4),
+ [2] = DEFINE_RES_NAMED(IRQ_EINT7, 1, NULL, IORESOURCE_IRQ \
+ | IORESOURCE_IRQ_HIGHEDGE),
};
static struct dm9000_plat_data at2440evb_dm9k_pdata = {
diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c
index 53219c02eca0..1cf1720682d3 100644
--- a/arch/arm/mach-s3c24xx/mach-bast.c
+++ b/arch/arm/mach-s3c24xx/mach-bast.c
@@ -310,22 +310,10 @@ static struct s3c2410_platform_nand __initdata bast_nand_info = {
/* DM9000 */
static struct resource bast_dm9k_resource[] = {
- [0] = {
- .start = S3C2410_CS5 + BAST_PA_DM9000,
- .end = S3C2410_CS5 + BAST_PA_DM9000 + 3,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = S3C2410_CS5 + BAST_PA_DM9000 + 0x40,
- .end = S3C2410_CS5 + BAST_PA_DM9000 + 0x40 + 0x3f,
- .flags = IORESOURCE_MEM,
- },
- [2] = {
- .start = IRQ_DM9000,
- .end = IRQ_DM9000,
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
- }
-
+ [0] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_DM9000, 4),
+ [1] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_DM9000 + 0x40, 0x40),
+ [2] = DEFINE_RES_NAMED(IRQ_DM9000 , 1, NULL, IORESOURCE_IRQ \
+ | IORESOURCE_IRQ_HIGHLEVEL),
};
/* for the moment we limit ourselves to 16bit IO until some
@@ -400,21 +388,9 @@ static struct ax_plat_data bast_asix_platdata = {
};
static struct resource bast_asix_resource[] = {
- [0] = {
- .start = S3C2410_CS5 + BAST_PA_ASIXNET,
- .end = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20) - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20),
- .end = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20),
- .flags = IORESOURCE_MEM,
- },
- [2] = {
- .start = IRQ_ASIX,
- .end = IRQ_ASIX,
- .flags = IORESOURCE_IRQ
- }
+ [0] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_ASIXNET, 0x18 * 0x20),
+ [1] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20), 1),
+ [2] = DEFINE_RES_IRQ(IRQ_ASIX),
};
static struct platform_device bast_device_asix = {
@@ -430,11 +406,8 @@ static struct platform_device bast_device_asix = {
/* Asix AX88796 10/100 ethernet controller parallel port */
static struct resource bast_asixpp_resource[] = {
- [0] = {
- .start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20),
- .end = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1b * 0x20) - 1,
- .flags = IORESOURCE_MEM,
- }
+ [0] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20), \
+ 0x30 * 0x20),
};
static struct platform_device bast_device_axpp = {
diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c
index ba5d85394105..0f29f64a3eeb 100644
--- a/arch/arm/mach-s3c24xx/mach-gta02.c
+++ b/arch/arm/mach-s3c24xx/mach-gta02.c
@@ -387,11 +387,8 @@ static struct physmap_flash_data gta02_nor_flash_data = {
.width = 2,
};
-static struct resource gta02_nor_flash_resource = {
- .start = GTA02_FLASH_BASE,
- .end = GTA02_FLASH_BASE + GTA02_FLASH_SIZE - 1,
- .flags = IORESOURCE_MEM,
-};
+static struct resource gta02_nor_flash_resource =
+ DEFINE_RES_MEM(GTA02_FLASH_BASE, GTA02_FLASH_SIZE);
static struct platform_device gta02_nor_flash = {
.name = "physmap-flash",
diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c
index 6b21ba107eab..bb8d008d5a5c 100644
--- a/arch/arm/mach-s3c24xx/mach-h1940.c
+++ b/arch/arm/mach-s3c24xx/mach-h1940.c
@@ -253,13 +253,8 @@ static struct pda_power_pdata power_supply_info = {
};
static struct resource power_supply_resources[] = {
- [0] = {
- .name = "ac",
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE |
- IORESOURCE_IRQ_HIGHEDGE,
- .start = IRQ_EINT2,
- .end = IRQ_EINT2,
- },
+ [0] = DEFINE_RES_NAMED(IRQ_EINT2, 1, "ac", IORESOURCE_IRQ \
+ | IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE),
};
static struct platform_device power_supply = {
diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c
index 5d66fb218a41..f092b188ab70 100644
--- a/arch/arm/mach-s3c24xx/mach-mini2440.c
+++ b/arch/arm/mach-s3c24xx/mach-mini2440.c
@@ -292,21 +292,10 @@ static struct s3c2410_platform_nand mini2440_nand_info __initdata = {
/* DM9000AEP 10/100 ethernet controller */
static struct resource mini2440_dm9k_resource[] = {
- [0] = {
- .start = MACH_MINI2440_DM9K_BASE,
- .end = MACH_MINI2440_DM9K_BASE + 3,
- .flags = IORESOURCE_MEM
- },
- [1] = {
- .start = MACH_MINI2440_DM9K_BASE + 4,
- .end = MACH_MINI2440_DM9K_BASE + 7,
- .flags = IORESOURCE_MEM
- },
- [2] = {
- .start = IRQ_EINT7,
- .end = IRQ_EINT7,
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
- }
+ [0] = DEFINE_RES_MEM(MACH_MINI2440_DM9K_BASE, 4),
+ [1] = DEFINE_RES_MEM(MACH_MINI2440_DM9K_BASE + 4, 4),
+ [2] = DEFINE_RES_NAMED(IRQ_EINT7, 1, NULL, IORESOURCE_IRQ \
+ | IORESOURCE_IRQ_HIGHEDGE),
};
/*
diff --git a/arch/arm/mach-s3c24xx/mach-nexcoder.c b/arch/arm/mach-s3c24xx/mach-nexcoder.c
index 5198e3e1c5be..5c05ba1c330f 100644
--- a/arch/arm/mach-s3c24xx/mach-nexcoder.c
+++ b/arch/arm/mach-s3c24xx/mach-nexcoder.c
@@ -84,11 +84,7 @@ static struct s3c2410_uartcfg nexcoder_uartcfgs[] __initdata = {
/* NOR Flash on NexVision NexCoder 2440 board */
static struct resource nexcoder_nor_resource[] = {
- [0] = {
- .start = S3C2410_CS0,
- .end = S3C2410_CS0 + (8*1024*1024) - 1,
- .flags = IORESOURCE_MEM,
- }
+ [0] = DEFINE_RES_MEM(S3C2410_CS0, SZ_8M),
};
static struct map_info nexcoder_nor_map = {
diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c
index c5daeb612a88..95d077255024 100644
--- a/arch/arm/mach-s3c24xx/mach-osiris.c
+++ b/arch/arm/mach-s3c24xx/mach-osiris.c
@@ -244,16 +244,8 @@ static struct s3c2410_platform_nand __initdata osiris_nand_info = {
/* PCMCIA control and configuration */
static struct resource osiris_pcmcia_resource[] = {
- [0] = {
- .start = 0x0f000000,
- .end = 0x0f100000,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = 0x0c000000,
- .end = 0x0c100000,
- .flags = IORESOURCE_MEM,
- }
+ [0] = DEFINE_RES_MEM(0x0f000000, SZ_1M),
+ [1] = DEFINE_RES_MEM(0x0c000000, SZ_1M),
};
static struct platform_device osiris_pcmcia = {
diff --git a/arch/arm/mach-s3c24xx/mach-otom.c b/arch/arm/mach-s3c24xx/mach-otom.c
index 5f1e0eeb38a9..bc4b6efb3b27 100644
--- a/arch/arm/mach-s3c24xx/mach-otom.c
+++ b/arch/arm/mach-s3c24xx/mach-otom.c
@@ -77,11 +77,7 @@ static struct s3c2410_uartcfg otom11_uartcfgs[] __initdata = {
/* NOR Flash on NexVision OTOM board */
static struct resource otom_nor_resource[] = {
- [0] = {
- .start = S3C2410_CS0,
- .end = S3C2410_CS0 + (4*1024*1024) - 1,
- .flags = IORESOURCE_MEM,
- }
+ [0] = DEFINE_RES_MEM(S3C2410_CS0, SZ_4M),
};
static struct platform_device otom_device_nor = {
diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c
index 91c16d9d2459..b868dddcb836 100644
--- a/arch/arm/mach-s3c24xx/mach-qt2410.c
+++ b/arch/arm/mach-s3c24xx/mach-qt2410.c
@@ -180,16 +180,8 @@ static struct s3c2410fb_mach_info qt2410_fb_info __initdata = {
/* CS8900 */
static struct resource qt2410_cs89x0_resources[] = {
- [0] = {
- .start = 0x19000000,
- .end = 0x19000000 + 16,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_EINT9,
- .end = IRQ_EINT9,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(0x19000000, 17),
+ [1] = DEFINE_RES_IRQ(IRQ_EINT9),
};
static struct platform_device qt2410_cs89x0 = {
diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c
index 200debb4c72d..a6762aae4727 100644
--- a/arch/arm/mach-s3c24xx/mach-rx1950.c
+++ b/arch/arm/mach-s3c24xx/mach-rx1950.c
@@ -152,13 +152,8 @@ static struct pda_power_pdata power_supply_info = {
};
static struct resource power_supply_resources[] = {
- [0] = {
- .name = "ac",
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE |
- IORESOURCE_IRQ_HIGHEDGE,
- .start = IRQ_EINT2,
- .end = IRQ_EINT2,
- },
+ [0] = DEFINE_RES_NAMED(IRQ_EINT2, 1, "ac", IORESOURCE_IRQ \
+ | IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE),
};
static struct platform_device power_supply = {
diff --git a/arch/arm/mach-s3c24xx/mach-tct_hammer.c b/arch/arm/mach-s3c24xx/mach-tct_hammer.c
index 1114666f0efb..fe990289ee7d 100644
--- a/arch/arm/mach-s3c24xx/mach-tct_hammer.c
+++ b/arch/arm/mach-s3c24xx/mach-tct_hammer.c
@@ -56,11 +56,8 @@
#include "common.h"
-static struct resource tct_hammer_nor_resource = {
- .start = 0x00000000,
- .end = 0x01000000 - 1,
- .flags = IORESOURCE_MEM,
-};
+static struct resource tct_hammer_nor_resource =
+ DEFINE_RES_MEM(0x00000000, SZ_16M);
static struct mtd_partition tct_hammer_mtd_partitions[] = {
{
diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c
index 87608d45dac4..bd5f189f0424 100644
--- a/arch/arm/mach-s3c24xx/mach-vr1000.c
+++ b/arch/arm/mach-s3c24xx/mach-vr1000.c
@@ -187,40 +187,17 @@ static struct platform_device serial_device = {
/* DM9000 ethernet devices */
static struct resource vr1000_dm9k0_resource[] = {
- [0] = {
- .start = S3C2410_CS5 + VR1000_PA_DM9000,
- .end = S3C2410_CS5 + VR1000_PA_DM9000 + 3,
- .flags = IORESOURCE_MEM
- },
- [1] = {
- .start = S3C2410_CS5 + VR1000_PA_DM9000 + 0x40,
- .end = S3C2410_CS5 + VR1000_PA_DM9000 + 0x7f,
- .flags = IORESOURCE_MEM
- },
- [2] = {
- .start = IRQ_VR1000_DM9000A,
- .end = IRQ_VR1000_DM9000A,
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
- }
-
+ [0] = DEFINE_RES_MEM(S3C2410_CS5 + VR1000_PA_DM9000, 4),
+ [1] = DEFINE_RES_MEM(S3C2410_CS5 + VR1000_PA_DM9000 + 0x40, 0x40),
+ [2] = DEFINE_RES_NAMED(IRQ_VR1000_DM9000A, 1, NULL, IORESOURCE_IRQ \
+ | IORESOURCE_IRQ_HIGHLEVEL),
};
static struct resource vr1000_dm9k1_resource[] = {
- [0] = {
- .start = S3C2410_CS5 + VR1000_PA_DM9000 + 0x80,
- .end = S3C2410_CS5 + VR1000_PA_DM9000 + 0x83,
- .flags = IORESOURCE_MEM
- },
- [1] = {
- .start = S3C2410_CS5 + VR1000_PA_DM9000 + 0xC0,
- .end = S3C2410_CS5 + VR1000_PA_DM9000 + 0xFF,
- .flags = IORESOURCE_MEM
- },
- [2] = {
- .start = IRQ_VR1000_DM9000N,
- .end = IRQ_VR1000_DM9000N,
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
- }
+ [0] = DEFINE_RES_MEM(S3C2410_CS5 + VR1000_PA_DM9000 + 0x80, 4),
+ [1] = DEFINE_RES_MEM(S3C2410_CS5 + VR1000_PA_DM9000 + 0xC0, 0x40),
+ [2] = DEFINE_RES_NAMED(IRQ_VR1000_DM9000N, 1, NULL, IORESOURCE_IRQ \
+ | IORESOURCE_IRQ_HIGHLEVEL),
};
/* for the moment we limit ourselves to 16bit IO until some
diff --git a/arch/arm/mach-s3c24xx/simtec-nor.c b/arch/arm/mach-s3c24xx/simtec-nor.c
index b9d6d4f92c03..029744fcaacb 100644
--- a/arch/arm/mach-s3c24xx/simtec-nor.c
+++ b/arch/arm/mach-s3c24xx/simtec-nor.c
@@ -55,11 +55,7 @@ static struct physmap_flash_data simtec_nor_pdata = {
};
static struct resource simtec_nor_resource[] = {
- [0] = {
- .start = S3C2410_CS1 + 0x4000000,
- .end = S3C2410_CS1 + 0x4000000 + SZ_8M - 1,
- .flags = IORESOURCE_MEM,
- }
+ [0] = DEFINE_RES_MEM(S3C2410_CS1 + 0x4000000, SZ_8M),
};
static struct platform_device simtec_device_nor = {
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index 82c0915729ee..06ca1cd4cae2 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -210,7 +210,7 @@ config SMDK6410_WM1190_EV1
and audio daughtercard for the Samsung SMDK6410 reference
platform. Enabling this option will build support for this
module into the kernel. The presence of the module will be
- detected at runtime so the the resulting kernel can be used
+ detected at runtime so the resulting kernel can be used
with or without the 1190-EV1 fitted.
config SMDK6410_WM1192_EV1
@@ -226,7 +226,7 @@ config SMDK6410_WM1192_EV1
daughtercard for the Samsung SMDK6410 reference platform.
Enabling this option will build support for this module into
the kernel. The presence of the daughtercard will be
- detected at runtime so the the resulting kernel can be used
+ detected at runtime so the resulting kernel can be used
with or without the 1192-EV1 fitted.
config MACH_NCP
diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c
index 93470b158a4e..124fd5d63006 100644
--- a/arch/arm/mach-s3c64xx/dev-audio.c
+++ b/arch/arm/mach-s3c64xx/dev-audio.c
@@ -57,21 +57,9 @@ static int s3c64xx_i2s_cfg_gpio(struct platform_device *pdev)
}
static struct resource s3c64xx_iis0_resource[] = {
- [0] = {
- .start = S3C64XX_PA_IIS0,
- .end = S3C64XX_PA_IIS0 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S0_OUT,
- .end = DMACH_I2S0_OUT,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S0_IN,
- .end = DMACH_I2S0_IN,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_IIS0, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S0_OUT),
+ [2] = DEFINE_RES_DMA(DMACH_I2S0_IN),
};
static struct s3c_audio_pdata i2sv3_pdata = {
@@ -95,21 +83,9 @@ struct platform_device s3c64xx_device_iis0 = {
EXPORT_SYMBOL(s3c64xx_device_iis0);
static struct resource s3c64xx_iis1_resource[] = {
- [0] = {
- .start = S3C64XX_PA_IIS1,
- .end = S3C64XX_PA_IIS1 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S1_OUT,
- .end = DMACH_I2S1_OUT,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S1_IN,
- .end = DMACH_I2S1_IN,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_IIS1, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S1_OUT),
+ [2] = DEFINE_RES_DMA(DMACH_I2S1_IN),
};
struct platform_device s3c64xx_device_iis1 = {
@@ -124,21 +100,9 @@ struct platform_device s3c64xx_device_iis1 = {
EXPORT_SYMBOL(s3c64xx_device_iis1);
static struct resource s3c64xx_iisv4_resource[] = {
- [0] = {
- .start = S3C64XX_PA_IISV4,
- .end = S3C64XX_PA_IISV4 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_HSI_I2SV40_TX,
- .end = DMACH_HSI_I2SV40_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_HSI_I2SV40_RX,
- .end = DMACH_HSI_I2SV40_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_IISV4, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_TX),
+ [2] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_RX),
};
static struct s3c_audio_pdata i2sv4_pdata = {
@@ -187,21 +151,9 @@ static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev)
}
static struct resource s3c64xx_pcm0_resource[] = {
- [0] = {
- .start = S3C64XX_PA_PCM0,
- .end = S3C64XX_PA_PCM0 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_PCM0_TX,
- .end = DMACH_PCM0_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_PCM0_RX,
- .end = DMACH_PCM0_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_PCM0, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
+ [2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
};
static struct s3c_audio_pdata s3c_pcm0_pdata = {
@@ -220,21 +172,9 @@ struct platform_device s3c64xx_device_pcm0 = {
EXPORT_SYMBOL(s3c64xx_device_pcm0);
static struct resource s3c64xx_pcm1_resource[] = {
- [0] = {
- .start = S3C64XX_PA_PCM1,
- .end = S3C64XX_PA_PCM1 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_PCM1_TX,
- .end = DMACH_PCM1_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_PCM1_RX,
- .end = DMACH_PCM1_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_PCM1, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_PCM1_TX),
+ [2] = DEFINE_RES_DMA(DMACH_PCM1_RX),
};
static struct s3c_audio_pdata s3c_pcm1_pdata = {
@@ -265,31 +205,11 @@ static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev)
}
static struct resource s3c64xx_ac97_resource[] = {
- [0] = {
- .start = S3C64XX_PA_AC97,
- .end = S3C64XX_PA_AC97 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_AC97_PCMOUT,
- .end = DMACH_AC97_PCMOUT,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_AC97_PCMIN,
- .end = DMACH_AC97_PCMIN,
- .flags = IORESOURCE_DMA,
- },
- [3] = {
- .start = DMACH_AC97_MICIN,
- .end = DMACH_AC97_MICIN,
- .flags = IORESOURCE_DMA,
- },
- [4] = {
- .start = IRQ_AC97,
- .end = IRQ_AC97,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_AC97, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT),
+ [2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN),
+ [3] = DEFINE_RES_DMA(DMACH_AC97_MICIN),
+ [4] = DEFINE_RES_IRQ(IRQ_AC97),
};
static struct s3c_audio_pdata s3c_ac97_pdata;
diff --git a/arch/arm/mach-s3c64xx/dev-uart.c b/arch/arm/mach-s3c64xx/dev-uart.c
index c681b99eda08..46e18d77ea93 100644
--- a/arch/arm/mach-s3c64xx/dev-uart.c
+++ b/arch/arm/mach-s3c64xx/dev-uart.c
@@ -31,55 +31,23 @@
/* 64xx uarts are closer together */
static struct resource s3c64xx_uart0_resource[] = {
- [0] = {
- .start = S3C_PA_UART0,
- .end = S3C_PA_UART0 + 0x100,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_UART0,
- .end = IRQ_UART0,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(S3C_PA_UART0, SZ_256),
+ [1] = DEFINE_RES_IRQ(IRQ_UART0),
};
static struct resource s3c64xx_uart1_resource[] = {
- [0] = {
- .start = S3C_PA_UART1,
- .end = S3C_PA_UART1 + 0x100,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_UART1,
- .end = IRQ_UART1,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(S3C_PA_UART1, SZ_256),
+ [1] = DEFINE_RES_IRQ(IRQ_UART1),
};
static struct resource s3c6xx_uart2_resource[] = {
- [0] = {
- .start = S3C_PA_UART2,
- .end = S3C_PA_UART2 + 0x100,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_UART2,
- .end = IRQ_UART2,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(S3C_PA_UART2, SZ_256),
+ [1] = DEFINE_RES_IRQ(IRQ_UART2),
};
static struct resource s3c64xx_uart3_resource[] = {
- [0] = {
- .start = S3C_PA_UART3,
- .end = S3C_PA_UART3 + 0x100,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_UART3,
- .end = IRQ_UART3,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(S3C_PA_UART3, SZ_256),
+ [1] = DEFINE_RES_IRQ(IRQ_UART3),
};
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index b86f2779e4e6..f252691fb209 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -165,21 +165,10 @@ static void __init anw6410_dm9000_enable(void)
}
static struct resource anw6410_dm9000_resource[] = {
- [0] = {
- .start = ANW6410_PA_DM9000,
- .end = ANW6410_PA_DM9000 + 3,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = ANW6410_PA_DM9000 + 4,
- .end = ANW6410_PA_DM9000 + 4 + 500,
- .flags = IORESOURCE_MEM,
- },
- [2] = {
- .start = IRQ_EINT(15),
- .end = IRQ_EINT(15),
- .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
- },
+ [0] = DEFINE_RES_MEM(ANW6410_PA_DM9000, 4),
+ [1] = DEFINE_RES_MEM(ANW6410_PA_DM9000 + 4, 501),
+ [2] = DEFINE_RES_NAMED(IRQ_EINT(15), 1, NULL, IORESOURCE_IRQ \
+ | IRQF_TRIGGER_HIGH),
};
static struct dm9000_plat_data anw6410_dm9000_pdata = {
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index e20bf5835365..aa1137fb47e6 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -31,6 +31,7 @@
#include <linux/spi/spi.h>
#include <linux/i2c/pca953x.h>
+#include <linux/platform_data/s3c-hsotg.h>
#include <video/platform_lcd.h>
@@ -61,7 +62,6 @@
#include <plat/sdhci.h>
#include <plat/gpio-cfg.h>
#include <plat/s3c64xx-spi.h>
-#include <plat/udc-hs.h>
#include <plat/keypad.h>
#include <plat/clock.h>
@@ -232,21 +232,10 @@ static struct platform_device crag6410_gpio_keydev = {
};
static struct resource crag6410_dm9k_resource[] = {
- [0] = {
- .start = S3C64XX_PA_XM0CSN5,
- .end = S3C64XX_PA_XM0CSN5 + 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = S3C64XX_PA_XM0CSN5 + (1 << 8),
- .end = S3C64XX_PA_XM0CSN5 + (1 << 8) + 1,
- .flags = IORESOURCE_MEM,
- },
- [2] = {
- .start = S3C_EINT(17),
- .end = S3C_EINT(17),
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
- },
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN5, 2),
+ [1] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN5 + (1 << 8), 2),
+ [2] = DEFINE_RES_NAMED(S3C_EINT(17), 1, NULL, IORESOURCE_IRQ \
+ | IORESOURCE_IRQ_HIGHLEVEL),
};
static struct dm9000_plat_data mini6410_dm9k_pdata = {
@@ -262,12 +251,7 @@ static struct platform_device crag6410_dm9k_device = {
};
static struct resource crag6410_mmgpio_resource[] = {
- [0] = {
- .name = "dat",
- .start = S3C64XX_PA_XM0CSN4 + 1,
- .end = S3C64XX_PA_XM0CSN4 + 1,
- .flags = IORESOURCE_MEM,
- },
+ [0] = DEFINE_RES_MEM_NAMED(S3C64XX_PA_XM0CSN4, 1, "dat"),
};
static struct platform_device crag6410_mmgpio = {
@@ -306,6 +290,24 @@ static struct regulator_consumer_supply wallvdd_consumers[] = {
REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
REGULATOR_SUPPLY("SPKVDDL", "1-001a"),
REGULATOR_SUPPLY("SPKVDDR", "1-001a"),
+
+ REGULATOR_SUPPLY("DC1VDD", "0-0034"),
+ REGULATOR_SUPPLY("DC2VDD", "0-0034"),
+ REGULATOR_SUPPLY("DC3VDD", "0-0034"),
+ REGULATOR_SUPPLY("LDO1VDD", "0-0034"),
+ REGULATOR_SUPPLY("LDO2VDD", "0-0034"),
+ REGULATOR_SUPPLY("LDO4VDD", "0-0034"),
+ REGULATOR_SUPPLY("LDO5VDD", "0-0034"),
+ REGULATOR_SUPPLY("LDO6VDD", "0-0034"),
+ REGULATOR_SUPPLY("LDO7VDD", "0-0034"),
+ REGULATOR_SUPPLY("LDO8VDD", "0-0034"),
+ REGULATOR_SUPPLY("LDO9VDD", "0-0034"),
+ REGULATOR_SUPPLY("LDO10VDD", "0-0034"),
+ REGULATOR_SUPPLY("LDO11VDD", "0-0034"),
+
+ REGULATOR_SUPPLY("DC1VDD", "1-0034"),
+ REGULATOR_SUPPLY("DC2VDD", "1-0034"),
+ REGULATOR_SUPPLY("DC3VDD", "1-0034"),
};
static struct regulator_init_data wallvdd_data = {
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
index c34c2ab22ead..b2166d4a5538 100644
--- a/arch/arm/mach-s3c64xx/mach-mini6410.c
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -85,21 +85,10 @@ static struct s3c2410_uartcfg mini6410_uartcfgs[] __initdata = {
/* DM9000AEP 10/100 ethernet controller */
static struct resource mini6410_dm9k_resource[] = {
- [0] = {
- .start = S3C64XX_PA_XM0CSN1,
- .end = S3C64XX_PA_XM0CSN1 + 1,
- .flags = IORESOURCE_MEM
- },
- [1] = {
- .start = S3C64XX_PA_XM0CSN1 + 4,
- .end = S3C64XX_PA_XM0CSN1 + 5,
- .flags = IORESOURCE_MEM
- },
- [2] = {
- .start = S3C_EINT(7),
- .end = S3C_EINT(7),
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL
- }
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN1, 2),
+ [1] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN1 + 4, 2),
+ [2] = DEFINE_RES_NAMED(S3C_EINT(7), 1, NULL, IORESOURCE_IRQ \
+ | IORESOURCE_IRQ_HIGHLEVEL),
};
static struct dm9000_plat_data mini6410_dm9k_pdata = {
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index be2a9a22ab74..5c08266cea21 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -86,21 +86,10 @@ static struct s3c2410_uartcfg real6410_uartcfgs[] __initdata = {
/* DM9000AEP 10/100 ethernet controller */
static struct resource real6410_dm9k_resource[] = {
- [0] = {
- .start = S3C64XX_PA_XM0CSN1,
- .end = S3C64XX_PA_XM0CSN1 + 1,
- .flags = IORESOURCE_MEM
- },
- [1] = {
- .start = S3C64XX_PA_XM0CSN1 + 4,
- .end = S3C64XX_PA_XM0CSN1 + 5,
- .flags = IORESOURCE_MEM
- },
- [2] = {
- .start = S3C_EINT(7),
- .end = S3C_EINT(7),
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL
- }
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN1, 2),
+ [1] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN1 + 4, 2),
+ [2] = DEFINE_RES_NAMED(S3C_EINT(7), 1, NULL, IORESOURCE_IRQ \
+ | IORESOURCE_IRQ_HIGHLEVEL),
};
static struct dm9000_plat_data real6410_dm9k_pdata = {
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index ce745e19aa27..ceeb1de40376 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -18,6 +18,7 @@
#include <linux/serial_core.h>
#include <linux/spi/spi_gpio.h>
#include <linux/usb/gpio_vbus.h>
+#include <linux/platform_data/s3c-hsotg.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
@@ -33,7 +34,6 @@
#include <plat/gpio-cfg.h>
#include <plat/hwmon.h>
#include <plat/regs-serial.h>
-#include <plat/udc-hs.h>
#include <plat/usb-control.h>
#include <plat/sdhci.h>
#include <plat/ts.h>
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index d55bc96d9582..7da044f738ac 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -30,6 +30,7 @@
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <linux/pwm_backlight.h>
+#include <linux/platform_data/s3c-hsotg.h>
#ifdef CONFIG_SMDK6410_WM1190_EV1
#include <linux/mfd/wm8350/core.h>
@@ -72,7 +73,6 @@
#include <plat/keypad.h>
#include <plat/backlight.h>
#include <plat/regs-fb-v4.h>
-#include <plat/udc-hs.h>
#include "common.h"
@@ -182,16 +182,9 @@ static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = {
*/
static struct resource smdk6410_smsc911x_resources[] = {
- [0] = {
- .start = S3C64XX_PA_XM0CSN1,
- .end = S3C64XX_PA_XM0CSN1 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = S3C_EINT(10),
- .end = S3C_EINT(10),
- .flags = IORESOURCE_IRQ | IRQ_TYPE_LEVEL_LOW,
- },
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN1, SZ_64K),
+ [1] = DEFINE_RES_NAMED(S3C_EINT(10), 1, NULL, IORESOURCE_IRQ \
+ | IRQ_TYPE_LEVEL_LOW),
};
static struct smsc911x_platform_config smdk6410_smsc911x_pdata = {
diff --git a/arch/arm/mach-s5p64x0/dev-audio.c b/arch/arm/mach-s5p64x0/dev-audio.c
index 35f1f226dabb..91113ddc51da 100644
--- a/arch/arm/mach-s5p64x0/dev-audio.c
+++ b/arch/arm/mach-s5p64x0/dev-audio.c
@@ -51,21 +51,9 @@ static struct s3c_audio_pdata s5p6440_i2s_pdata = {
};
static struct resource s5p64x0_i2s0_resource[] = {
- [0] = {
- .start = S5P64X0_PA_I2S,
- .end = S5P64X0_PA_I2S + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S0_TX,
- .end = DMACH_I2S0_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S0_RX,
- .end = DMACH_I2S0_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5P64X0_PA_I2S, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S0_TX),
+ [2] = DEFINE_RES_DMA(DMACH_I2S0_RX),
};
struct platform_device s5p6440_device_iis = {
@@ -130,21 +118,9 @@ static struct s3c_audio_pdata s5p6450_i2s_pdata = {
};
static struct resource s5p6450_i2s1_resource[] = {
- [0] = {
- .start = S5P6450_PA_I2S1,
- .end = S5P6450_PA_I2S1 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S1_TX,
- .end = DMACH_I2S1_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S1_RX,
- .end = DMACH_I2S1_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5P6450_PA_I2S1, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S1_TX),
+ [2] = DEFINE_RES_DMA(DMACH_I2S1_RX),
};
struct platform_device s5p6450_device_iis1 = {
@@ -158,21 +134,9 @@ struct platform_device s5p6450_device_iis1 = {
};
static struct resource s5p6450_i2s2_resource[] = {
- [0] = {
- .start = S5P6450_PA_I2S2,
- .end = S5P6450_PA_I2S2 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S2_TX,
- .end = DMACH_I2S2_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S2_RX,
- .end = DMACH_I2S2_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5P6450_PA_I2S2, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S2_TX),
+ [2] = DEFINE_RES_DMA(DMACH_I2S2_RX),
};
struct platform_device s5p6450_device_iis2 = {
@@ -208,21 +172,9 @@ static struct s3c_audio_pdata s5p6440_pcm_pdata = {
};
static struct resource s5p6440_pcm0_resource[] = {
- [0] = {
- .start = S5P64X0_PA_PCM,
- .end = S5P64X0_PA_PCM + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_PCM0_TX,
- .end = DMACH_PCM0_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_PCM0_RX,
- .end = DMACH_PCM0_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5P64X0_PA_PCM, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
+ [2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
};
struct platform_device s5p6440_device_pcm = {
diff --git a/arch/arm/mach-s5pc100/dev-audio.c b/arch/arm/mach-s5pc100/dev-audio.c
index ab2d27172cbc..9d4bde3f1110 100644
--- a/arch/arm/mach-s5pc100/dev-audio.c
+++ b/arch/arm/mach-s5pc100/dev-audio.c
@@ -56,26 +56,10 @@ static struct s3c_audio_pdata i2sv5_pdata = {
};
static struct resource s5pc100_iis0_resource[] = {
- [0] = {
- .start = S5PC100_PA_I2S0,
- .end = S5PC100_PA_I2S0 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S0_TX,
- .end = DMACH_I2S0_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S0_RX,
- .end = DMACH_I2S0_RX,
- .flags = IORESOURCE_DMA,
- },
- [3] = {
- .start = DMACH_I2S0S_TX,
- .end = DMACH_I2S0S_TX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5PC100_PA_I2S0, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S0_TX),
+ [2] = DEFINE_RES_DMA(DMACH_I2S0_RX),
+ [3] = DEFINE_RES_DMA(DMACH_I2S0S_TX),
};
struct platform_device s5pc100_device_iis0 = {
@@ -103,21 +87,9 @@ static struct s3c_audio_pdata i2sv3_pdata = {
};
static struct resource s5pc100_iis1_resource[] = {
- [0] = {
- .start = S5PC100_PA_I2S1,
- .end = S5PC100_PA_I2S1 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S1_TX,
- .end = DMACH_I2S1_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S1_RX,
- .end = DMACH_I2S1_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5PC100_PA_I2S1, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S1_TX),
+ [2] = DEFINE_RES_DMA(DMACH_I2S1_RX),
};
struct platform_device s5pc100_device_iis1 = {
@@ -131,21 +103,9 @@ struct platform_device s5pc100_device_iis1 = {
};
static struct resource s5pc100_iis2_resource[] = {
- [0] = {
- .start = S5PC100_PA_I2S2,
- .end = S5PC100_PA_I2S2 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S2_TX,
- .end = DMACH_I2S2_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S2_RX,
- .end = DMACH_I2S2_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5PC100_PA_I2S2, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S2_TX),
+ [2] = DEFINE_RES_DMA(DMACH_I2S2_RX),
};
struct platform_device s5pc100_device_iis2 = {
@@ -184,21 +144,9 @@ static struct s3c_audio_pdata s3c_pcm_pdata = {
};
static struct resource s5pc100_pcm0_resource[] = {
- [0] = {
- .start = S5PC100_PA_PCM0,
- .end = S5PC100_PA_PCM0 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_PCM0_TX,
- .end = DMACH_PCM0_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_PCM0_RX,
- .end = DMACH_PCM0_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5PC100_PA_PCM0, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
+ [2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
};
struct platform_device s5pc100_device_pcm0 = {
@@ -212,21 +160,9 @@ struct platform_device s5pc100_device_pcm0 = {
};
static struct resource s5pc100_pcm1_resource[] = {
- [0] = {
- .start = S5PC100_PA_PCM1,
- .end = S5PC100_PA_PCM1 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_PCM1_TX,
- .end = DMACH_PCM1_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_PCM1_RX,
- .end = DMACH_PCM1_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5PC100_PA_PCM1, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_PCM1_TX),
+ [2] = DEFINE_RES_DMA(DMACH_PCM1_RX),
};
struct platform_device s5pc100_device_pcm1 = {
@@ -247,31 +183,11 @@ static int s5pc100_ac97_cfg_gpio(struct platform_device *pdev)
}
static struct resource s5pc100_ac97_resource[] = {
- [0] = {
- .start = S5PC100_PA_AC97,
- .end = S5PC100_PA_AC97 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_AC97_PCMOUT,
- .end = DMACH_AC97_PCMOUT,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_AC97_PCMIN,
- .end = DMACH_AC97_PCMIN,
- .flags = IORESOURCE_DMA,
- },
- [3] = {
- .start = DMACH_AC97_MICIN,
- .end = DMACH_AC97_MICIN,
- .flags = IORESOURCE_DMA,
- },
- [4] = {
- .start = IRQ_AC97,
- .end = IRQ_AC97,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(S5PC100_PA_AC97, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT),
+ [2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN),
+ [3] = DEFINE_RES_DMA(DMACH_AC97_MICIN),
+ [4] = DEFINE_RES_IRQ(IRQ_AC97),
};
static struct s3c_audio_pdata s3c_ac97_pdata = {
@@ -308,16 +224,8 @@ static int s5pc100_spdif_cfg_gpg3(struct platform_device *pdev)
}
static struct resource s5pc100_spdif_resource[] = {
- [0] = {
- .start = S5PC100_PA_SPDIF,
- .end = S5PC100_PA_SPDIF + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_SPDIF,
- .end = DMACH_SPDIF,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5PC100_PA_SPDIF, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_SPDIF),
};
static struct s3c_audio_pdata s5p_spdif_pdata = {
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 29594fc4fdf4..88e983b0c82e 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -85,6 +85,7 @@ config MACH_AQUILA
select S5P_DEV_ONENAND
select S5PV210_SETUP_FB_24BPP
select S5PV210_SETUP_SDHCI
+ select S5PV210_SETUP_USB_PHY
help
Machine support for the Samsung Aquila target based on S5PC110 SoC
diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c
index 63f5d82004b5..8367749c3eec 100644
--- a/arch/arm/mach-s5pv210/dev-audio.c
+++ b/arch/arm/mach-s5pv210/dev-audio.c
@@ -59,26 +59,10 @@ static struct s3c_audio_pdata i2sv5_pdata = {
};
static struct resource s5pv210_iis0_resource[] = {
- [0] = {
- .start = S5PV210_PA_IIS0,
- .end = S5PV210_PA_IIS0 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S0_TX,
- .end = DMACH_I2S0_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S0_RX,
- .end = DMACH_I2S0_RX,
- .flags = IORESOURCE_DMA,
- },
- [3] = {
- .start = DMACH_I2S0S_TX,
- .end = DMACH_I2S0S_TX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5PV210_PA_IIS0, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S0_TX),
+ [2] = DEFINE_RES_DMA(DMACH_I2S0_RX),
+ [3] = DEFINE_RES_DMA(DMACH_I2S0S_TX),
};
struct platform_device s5pv210_device_iis0 = {
@@ -106,21 +90,9 @@ static struct s3c_audio_pdata i2sv3_pdata = {
};
static struct resource s5pv210_iis1_resource[] = {
- [0] = {
- .start = S5PV210_PA_IIS1,
- .end = S5PV210_PA_IIS1 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S1_TX,
- .end = DMACH_I2S1_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S1_RX,
- .end = DMACH_I2S1_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5PV210_PA_IIS1, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S1_TX),
+ [2] = DEFINE_RES_DMA(DMACH_I2S1_RX),
};
struct platform_device s5pv210_device_iis1 = {
@@ -134,21 +106,9 @@ struct platform_device s5pv210_device_iis1 = {
};
static struct resource s5pv210_iis2_resource[] = {
- [0] = {
- .start = S5PV210_PA_IIS2,
- .end = S5PV210_PA_IIS2 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S2_TX,
- .end = DMACH_I2S2_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S2_RX,
- .end = DMACH_I2S2_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5PV210_PA_IIS2, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_I2S2_TX),
+ [2] = DEFINE_RES_DMA(DMACH_I2S2_RX),
};
struct platform_device s5pv210_device_iis2 = {
@@ -188,21 +148,9 @@ static struct s3c_audio_pdata s3c_pcm_pdata = {
};
static struct resource s5pv210_pcm0_resource[] = {
- [0] = {
- .start = S5PV210_PA_PCM0,
- .end = S5PV210_PA_PCM0 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_PCM0_TX,
- .end = DMACH_PCM0_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_PCM0_RX,
- .end = DMACH_PCM0_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5PV210_PA_PCM0, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
+ [2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
};
struct platform_device s5pv210_device_pcm0 = {
@@ -216,21 +164,9 @@ struct platform_device s5pv210_device_pcm0 = {
};
static struct resource s5pv210_pcm1_resource[] = {
- [0] = {
- .start = S5PV210_PA_PCM1,
- .end = S5PV210_PA_PCM1 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_PCM1_TX,
- .end = DMACH_PCM1_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_PCM1_RX,
- .end = DMACH_PCM1_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5PV210_PA_PCM1, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_PCM1_TX),
+ [2] = DEFINE_RES_DMA(DMACH_PCM1_RX),
};
struct platform_device s5pv210_device_pcm1 = {
@@ -244,21 +180,9 @@ struct platform_device s5pv210_device_pcm1 = {
};
static struct resource s5pv210_pcm2_resource[] = {
- [0] = {
- .start = S5PV210_PA_PCM2,
- .end = S5PV210_PA_PCM2 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_PCM2_TX,
- .end = DMACH_PCM2_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_PCM2_RX,
- .end = DMACH_PCM2_RX,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5PV210_PA_PCM2, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_PCM2_TX),
+ [2] = DEFINE_RES_DMA(DMACH_PCM2_RX),
};
struct platform_device s5pv210_device_pcm2 = {
@@ -279,31 +203,11 @@ static int s5pv210_ac97_cfg_gpio(struct platform_device *pdev)
}
static struct resource s5pv210_ac97_resource[] = {
- [0] = {
- .start = S5PV210_PA_AC97,
- .end = S5PV210_PA_AC97 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_AC97_PCMOUT,
- .end = DMACH_AC97_PCMOUT,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_AC97_PCMIN,
- .end = DMACH_AC97_PCMIN,
- .flags = IORESOURCE_DMA,
- },
- [3] = {
- .start = DMACH_AC97_MICIN,
- .end = DMACH_AC97_MICIN,
- .flags = IORESOURCE_DMA,
- },
- [4] = {
- .start = IRQ_AC97,
- .end = IRQ_AC97,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(S5PV210_PA_AC97, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT),
+ [2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN),
+ [3] = DEFINE_RES_DMA(DMACH_AC97_MICIN),
+ [4] = DEFINE_RES_IRQ(IRQ_AC97),
};
static struct s3c_audio_pdata s3c_ac97_pdata = {
@@ -334,16 +238,8 @@ static int s5pv210_spdif_cfg_gpio(struct platform_device *pdev)
}
static struct resource s5pv210_spdif_resource[] = {
- [0] = {
- .start = S5PV210_PA_SPDIF,
- .end = S5PV210_PA_SPDIF + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_SPDIF,
- .end = DMACH_SPDIF,
- .flags = IORESOURCE_DMA,
- },
+ [0] = DEFINE_RES_MEM(S5PV210_PA_SPDIF, SZ_256),
+ [1] = DEFINE_RES_DMA(DMACH_SPDIF),
};
static struct s3c_audio_pdata samsung_spdif_pdata = {
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 32395664e879..f20a97c8e411 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -27,6 +27,7 @@
#include <linux/gpio.h>
#include <linux/mmc/host.h>
#include <linux/interrupt.h>
+#include <linux/platform_data/s3c-hsotg.h>
#include <asm/hardware/vic.h>
#include <asm/mach/arch.h>
@@ -278,6 +279,9 @@ static void __init goni_tsp_init(void)
i2c2_devs[0].irq = gpio_to_irq(gpio);
}
+/* USB OTG */
+static struct s3c_hsotg_plat goni_hsotg_pdata;
+
static void goni_camera_init(void)
{
s5pv210_fimc_setup_gpio(S5P_CAMPORT_A);
@@ -941,6 +945,8 @@ static void __init goni_machine_init(void)
s3c_set_platdata(&goni_fimc_md_platdata, sizeof(goni_fimc_md_platdata),
&s5p_device_fimc_md);
+ s3c_hsotg_set_platdata(&goni_hsotg_pdata);
+
goni_camera_init();
/* SPI */
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index 91d4ad8bcc73..fa1b61209fd9 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -119,21 +119,10 @@ static struct samsung_keypad_platdata smdkv210_keypad_data __initdata = {
};
static struct resource smdkv210_dm9000_resources[] = {
- [0] = {
- .start = S5PV210_PA_SROM_BANK5,
- .end = S5PV210_PA_SROM_BANK5,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = S5PV210_PA_SROM_BANK5 + 2,
- .end = S5PV210_PA_SROM_BANK5 + 2,
- .flags = IORESOURCE_MEM,
- },
- [2] = {
- .start = IRQ_EINT(9),
- .end = IRQ_EINT(9),
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
- },
+ [0] = DEFINE_RES_MEM(S5PV210_PA_SROM_BANK5, 1),
+ [1] = DEFINE_RES_MEM(S5PV210_PA_SROM_BANK5 + 2, 1),
+ [2] = DEFINE_RES_NAMED(IRQ_EINT(9), 1, NULL, IORESOURCE_IRQ \
+ | IORESOURCE_IRQ_HIGHLEVEL),
};
static struct dm9000_plat_data smdkv210_dm9000_platdata = {
diff --git a/arch/arm/mach-sa1100/pci-nanoengine.c b/arch/arm/mach-sa1100/pci-nanoengine.c
index b49108b890a8..ff02e2da99f2 100644
--- a/arch/arm/mach-sa1100/pci-nanoengine.c
+++ b/arch/arm/mach-sa1100/pci-nanoengine.c
@@ -129,12 +129,6 @@ static int __init pci_nanoengine_map_irq(const struct pci_dev *dev, u8 slot,
return NANOENGINE_IRQ_GPIO_PCI;
}
-struct pci_bus * __init pci_nanoengine_scan_bus(int nr, struct pci_sys_data *sys)
-{
- return pci_scan_root_bus(NULL, sys->busnr, &pci_nano_ops, sys,
- &sys->resources);
-}
-
static struct resource pci_io_ports =
DEFINE_RES_IO_NAMED(0x400, 0x400, "PCI IO");
@@ -274,7 +268,7 @@ int __init pci_nanoengine_setup(int nr, struct pci_sys_data *sys)
static struct hw_pci nanoengine_pci __initdata = {
.map_irq = pci_nanoengine_map_irq,
.nr_controllers = 1,
- .scan = pci_nanoengine_scan_bus,
+ .ops = &pci_nano_ops,
.setup = pci_nanoengine_setup,
};
diff --git a/arch/arm/mach-shark/pci.c b/arch/arm/mach-shark/pci.c
index 7cb79a092f31..9089407d5326 100644
--- a/arch/arm/mach-shark/pci.c
+++ b/arch/arm/mach-shark/pci.c
@@ -29,10 +29,9 @@ extern void __init via82c505_preinit(void);
static struct hw_pci shark_pci __initdata = {
.setup = via82c505_setup,
- .swizzle = pci_std_swizzle,
.map_irq = shark_map_irq,
.nr_controllers = 1,
- .scan = via82c505_scan_bus,
+ .ops = &via82c505_ops,
.preinit = via82c505_preinit,
};
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 34560cab45d9..f31383c32f9c 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -41,6 +41,12 @@ config ARCH_R8A7779
select ARM_GIC
select ARCH_WANT_OPTIONAL_GPIOLIB
+config ARCH_EMEV2
+ bool "Emma Mobile EV2"
+ select CPU_V7
+ select ARM_GIC
+ select ARCH_WANT_OPTIONAL_GPIOLIB
+
comment "SH-Mobile Board Type"
config MACH_G3EVM
@@ -58,6 +64,7 @@ config MACH_AP4EVB
depends on ARCH_SH7372
select ARCH_REQUIRE_GPIOLIB
select SH_LCD_MIPI_DSI
+ select SND_SOC_AK4642 if SND_SIMPLE_CARD
choice
prompt "AP4EVB LCD panel selection"
@@ -82,6 +89,7 @@ config MACH_MACKEREL
bool "mackerel board"
depends on ARCH_SH7372
select ARCH_REQUIRE_GPIOLIB
+ select SND_SOC_AK4642 if SND_SIMPLE_CARD
config MACH_KOTA2
bool "KOTA2 board"
@@ -93,11 +101,28 @@ config MACH_BONITO
select ARCH_REQUIRE_GPIOLIB
depends on ARCH_R8A7740
+config MACH_ARMADILLO800EVA
+ bool "Armadillo-800 EVA board"
+ depends on ARCH_R8A7740
+ select ARCH_REQUIRE_GPIOLIB
+ select USE_OF
+
config MACH_MARZEN
bool "MARZEN board"
depends on ARCH_R8A7779
select ARCH_REQUIRE_GPIOLIB
+config MACH_KZM9D
+ bool "KZM9D board"
+ depends on ARCH_EMEV2
+ select USE_OF
+
+config MACH_KZM9G
+ bool "KZM-A9-GT board"
+ depends on ARCH_SH73A0
+ select ARCH_REQUIRE_GPIOLIB
+ select USE_OF
+
comment "SH-Mobile System Configuration"
config CPU_HAS_INTEVT
@@ -110,7 +135,8 @@ config MEMORY_START
hex "Physical memory start address"
default "0x50000000" if MACH_G3EVM
default "0x40000000" if MACH_G4EVM || MACH_AP4EVB || MACH_AG5EVM || \
- MACH_MACKEREL || MACH_BONITO
+ MACH_MACKEREL || MACH_BONITO || \
+ MACH_ARMADILLO800EVA
default "0x41000000" if MACH_KOTA2
default "0x00000000"
---help---
@@ -122,7 +148,8 @@ config MEMORY_SIZE
hex "Physical memory size"
default "0x08000000" if MACH_G3EVM
default "0x08000000" if MACH_G4EVM
- default "0x20000000" if MACH_AG5EVM || MACH_BONITO
+ default "0x20000000" if MACH_AG5EVM || MACH_BONITO || \
+ MACH_ARMADILLO800EVA
default "0x1e000000" if MACH_KOTA2
default "0x10000000" if MACH_AP4EVB || MACH_MACKEREL
default "0x04000000"
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index e7c2590b75d9..e6b177bc9410 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -12,12 +12,14 @@ obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7372.o intc-sh7372.o
obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o
obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o clock-r8a7740.o intc-r8a7740.o
obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o clock-r8a7779.o intc-r8a7779.o
+obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o clock-emev2.o
# SMP objects
smp-y := platsmp.o headsmp.o
smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o
smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o
smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o
+smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o
# Pinmux setup
pfc-y :=
@@ -49,6 +51,9 @@ obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o
obj-$(CONFIG_MACH_KOTA2) += board-kota2.o
obj-$(CONFIG_MACH_BONITO) += board-bonito.o
obj-$(CONFIG_MACH_MARZEN) += board-marzen.o
+obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o
+obj-$(CONFIG_MACH_KZM9D) += board-kzm9d.o
+obj-$(CONFIG_MACH_KZM9G) += board-kzm9g.o
# Framework support
obj-$(CONFIG_SMP) += $(smp-y)
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index b56dde2732bb..b540b8eb20ca 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -50,6 +50,7 @@
#include <media/soc_camera.h>
#include <sound/sh_fsi.h>
+#include <sound/simple_card.h>
#include <video/sh_mobile_hdmi.h>
#include <video/sh_mobile_lcdc.h>
@@ -785,17 +786,25 @@ static struct platform_device fsi_device = {
},
};
-static struct fsi_ak4642_info fsi2_ak4643_info = {
+static struct asoc_simple_dai_init_info fsi2_ak4643_init_info = {
+ .fmt = SND_SOC_DAIFMT_LEFT_J,
+ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
+ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
+ .sysclk = 11289600,
+};
+
+static struct asoc_simple_card_info fsi2_ak4643_info = {
.name = "AK4643",
.card = "FSI2A-AK4643",
.cpu_dai = "fsia-dai",
.codec = "ak4642-codec.0-0013",
.platform = "sh_fsi2",
- .id = FSI_PORT_A,
+ .codec_dai = "ak4642-hifi",
+ .init = &fsi2_ak4643_init_info,
};
static struct platform_device fsi_ak4643_device = {
- .name = "fsi-ak4642-audio",
+ .name = "asoc-simple-card",
.dev = {
.platform_data = &fsi2_ak4643_info,
},
@@ -900,8 +909,26 @@ static struct platform_device lcdc1_device = {
},
};
+static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = {
+ .cpu_daifmt = SND_SOC_DAIFMT_CBM_CFM,
+};
+
+static struct asoc_simple_card_info fsi2_hdmi_info = {
+ .name = "HDMI",
+ .card = "FSI2B-HDMI",
+ .cpu_dai = "fsib-dai",
+ .codec = "sh-mobile-hdmi",
+ .platform = "sh_fsi2",
+ .codec_dai = "sh_mobile_hdmi-hifi",
+ .init = &fsi2_hdmi_init_info,
+};
+
static struct platform_device fsi_hdmi_device = {
- .name = "sh_fsi2_b_hdmi",
+ .name = "asoc-simple-card",
+ .id = 1,
+ .dev = {
+ .platform_data = &fsi2_hdmi_info,
+ },
};
static struct gpio_led ap4evb_leds[] = {
@@ -997,6 +1024,8 @@ static struct sh_mobile_ceu_companion csi2 = {
static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
.flags = SH_CEU_FLAG_USE_8BIT_BUS,
+ .max_width = 8188,
+ .max_height = 8188,
.csi2 = &csi2,
};
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
new file mode 100644
index 000000000000..9e37026ef9dd
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -0,0 +1,784 @@
+/*
+ * armadillo 800 eva board support
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/sh_eth.h>
+#include <linux/videodev2.h>
+#include <linux/usb/renesas_usbhs.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <mach/common.h>
+#include <mach/irqs.h>
+#include <asm/page.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/r8a7740.h>
+#include <video/sh_mobile_lcdc.h>
+
+/*
+ * CON1 Camera Module
+ * CON2 Extension Bus
+ * CON3 HDMI Output
+ * CON4 Composite Video Output
+ * CON5 H-UDI JTAG
+ * CON6 ARM JTAG
+ * CON7 SD1
+ * CON8 SD2
+ * CON9 RTC BackUp
+ * CON10 Monaural Mic Input
+ * CON11 Stereo Headphone Output
+ * CON12 Audio Line Output(L)
+ * CON13 Audio Line Output(R)
+ * CON14 AWL13 Module
+ * CON15 Extension
+ * CON16 LCD1
+ * CON17 LCD2
+ * CON19 Power Input
+ * CON20 USB1
+ * CON21 USB2
+ * CON22 Serial
+ * CON23 LAN
+ * CON24 USB3
+ * LED1 Camera LED(Yellow)
+ * LED2 Power LED (Green)
+ * ED3-LED6 User LED(Yellow)
+ * LED7 LAN link LED(Green)
+ * LED8 LAN activity LED(Yellow)
+ */
+
+/*
+ * DipSwitch
+ *
+ * SW1
+ *
+ * -12345678-+---------------+----------------------------
+ * 1 | boot | hermit
+ * 0 | boot | OS auto boot
+ * -12345678-+---------------+----------------------------
+ * 00 | boot device | eMMC
+ * 10 | boot device | SDHI0 (CON7)
+ * 01 | boot device | -
+ * 11 | boot device | Extension Buss (CS0)
+ * -12345678-+---------------+----------------------------
+ * 0 | Extension Bus | D8-D15 disable, eMMC enable
+ * 1 | Extension Bus | D8-D15 enable, eMMC disable
+ * -12345678-+---------------+----------------------------
+ * 0 | SDHI1 | COM8 disable, COM14 enable
+ * 1 | SDHI1 | COM8 enable, COM14 disable
+ * -12345678-+---------------+----------------------------
+ * 0 | USB0 | COM20 enable, COM24 disable
+ * 1 | USB0 | COM20 disable, COM24 enable
+ * -12345678-+---------------+----------------------------
+ * 00 | JTAG | SH-X2
+ * 10 | JTAG | ARM
+ * 01 | JTAG | -
+ * 11 | JTAG | Boundary Scan
+ *-----------+---------------+----------------------------
+ */
+
+/*
+ * USB function
+ *
+ * When you use USB Function,
+ * set SW1.6 ON, and connect cable to CN24.
+ *
+ * USBF needs workaround on R8A7740 chip.
+ * These are a little bit complex.
+ * see
+ * usbhsf_power_ctrl()
+ *
+ * CAUTION
+ *
+ * It uses autonomy mode for USB hotplug at this point
+ * (= usbhs_private.platform_callback.get_vbus is NULL),
+ * since we don't know what's happen on PM control
+ * on this workaround.
+ */
+#define USBCR1 0xe605810a
+#define USBH 0xC6700000
+#define USBH_USBCTR 0x10834
+
+struct usbhsf_private {
+ struct clk *phy;
+ struct clk *usb24;
+ struct clk *pci;
+ struct clk *func;
+ struct clk *host;
+ void __iomem *usbh_base;
+ struct renesas_usbhs_platform_info info;
+};
+
+#define usbhsf_get_priv(pdev) \
+ container_of(renesas_usbhs_get_info(pdev), \
+ struct usbhsf_private, info)
+
+static int usbhsf_get_id(struct platform_device *pdev)
+{
+ return USBHS_GADGET;
+}
+
+static void usbhsf_power_ctrl(struct platform_device *pdev,
+ void __iomem *base, int enable)
+{
+ struct usbhsf_private *priv = usbhsf_get_priv(pdev);
+
+ /*
+ * Work around for USB Function.
+ * It needs USB host clock, and settings
+ */
+ if (enable) {
+ /*
+ * enable all the related usb clocks
+ * for usb workaround
+ */
+ clk_enable(priv->usb24);
+ clk_enable(priv->pci);
+ clk_enable(priv->host);
+ clk_enable(priv->func);
+ clk_enable(priv->phy);
+
+ /*
+ * set USBCR1
+ *
+ * Port1 is driven by USB function,
+ * Port2 is driven by USB HOST
+ * One HOST (Port1 or Port2 is HOST)
+ * USB PLL input clock = 24MHz
+ */
+ __raw_writew(0xd750, USBCR1);
+ mdelay(1);
+
+ /*
+ * start USB Host
+ */
+ __raw_writel(0x0000000c, priv->usbh_base + USBH_USBCTR);
+ __raw_writel(0x00000008, priv->usbh_base + USBH_USBCTR);
+ mdelay(10);
+
+ /*
+ * USB PHY Power ON
+ */
+ __raw_writew(0xd770, USBCR1);
+ __raw_writew(0x4000, base + 0x102); /* USBF :: SUSPMODE */
+
+ } else {
+ __raw_writel(0x0000010f, priv->usbh_base + USBH_USBCTR);
+ __raw_writew(0xd7c0, USBCR1); /* GPIO */
+
+ clk_disable(priv->phy);
+ clk_disable(priv->func); /* usb work around */
+ clk_disable(priv->host); /* usb work around */
+ clk_disable(priv->pci); /* usb work around */
+ clk_disable(priv->usb24); /* usb work around */
+ }
+}
+
+static void usbhsf_hardware_exit(struct platform_device *pdev)
+{
+ struct usbhsf_private *priv = usbhsf_get_priv(pdev);
+
+ if (!IS_ERR(priv->phy))
+ clk_put(priv->phy);
+ if (!IS_ERR(priv->usb24))
+ clk_put(priv->usb24);
+ if (!IS_ERR(priv->pci))
+ clk_put(priv->pci);
+ if (!IS_ERR(priv->host))
+ clk_put(priv->host);
+ if (!IS_ERR(priv->func))
+ clk_put(priv->func);
+ if (priv->usbh_base)
+ iounmap(priv->usbh_base);
+
+ priv->phy = NULL;
+ priv->usb24 = NULL;
+ priv->pci = NULL;
+ priv->host = NULL;
+ priv->func = NULL;
+ priv->usbh_base = NULL;
+}
+
+static int usbhsf_hardware_init(struct platform_device *pdev)
+{
+ struct usbhsf_private *priv = usbhsf_get_priv(pdev);
+
+ priv->phy = clk_get(&pdev->dev, "phy");
+ priv->usb24 = clk_get(&pdev->dev, "usb24");
+ priv->pci = clk_get(&pdev->dev, "pci");
+ priv->func = clk_get(&pdev->dev, "func");
+ priv->host = clk_get(&pdev->dev, "host");
+ priv->usbh_base = ioremap_nocache(USBH, 0x20000);
+
+ if (IS_ERR(priv->phy) ||
+ IS_ERR(priv->usb24) ||
+ IS_ERR(priv->pci) ||
+ IS_ERR(priv->host) ||
+ IS_ERR(priv->func) ||
+ !priv->usbh_base) {
+ dev_err(&pdev->dev, "USB clock setting failed\n");
+ usbhsf_hardware_exit(pdev);
+ return -EIO;
+ }
+
+ /* usb24 use 1/1 of parent clock (= usb24s = 24MHz) */
+ clk_set_rate(priv->usb24,
+ clk_get_rate(clk_get_parent(priv->usb24)));
+
+ return 0;
+}
+
+static struct usbhsf_private usbhsf_private = {
+ .info = {
+ .platform_callback = {
+ .get_id = usbhsf_get_id,
+ .hardware_init = usbhsf_hardware_init,
+ .hardware_exit = usbhsf_hardware_exit,
+ .power_ctrl = usbhsf_power_ctrl,
+ },
+ .driver_param = {
+ .buswait_bwait = 5,
+ .detection_delay = 5,
+ },
+ }
+};
+
+static struct resource usbhsf_resources[] = {
+ {
+ .name = "USBHS",
+ .start = 0xe6890000,
+ .end = 0xe6890104 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = evt2irq(0x0A20),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device usbhsf_device = {
+ .name = "renesas_usbhs",
+ .dev = {
+ .platform_data = &usbhsf_private.info,
+ },
+ .id = -1,
+ .num_resources = ARRAY_SIZE(usbhsf_resources),
+ .resource = usbhsf_resources,
+};
+
+/* Ether */
+static struct sh_eth_plat_data sh_eth_platdata = {
+ .phy = 0x00, /* LAN8710A */
+ .edmac_endian = EDMAC_LITTLE_ENDIAN,
+ .register_type = SH_ETH_REG_GIGABIT,
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+};
+
+static struct resource sh_eth_resources[] = {
+ {
+ .start = 0xe9a00000,
+ .end = 0xe9a00800 - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0xe9a01800,
+ .end = 0xe9a02000 - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = evt2irq(0x0500),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sh_eth_device = {
+ .name = "sh-eth",
+ .id = -1,
+ .dev = {
+ .platform_data = &sh_eth_platdata,
+ },
+ .resource = sh_eth_resources,
+ .num_resources = ARRAY_SIZE(sh_eth_resources),
+};
+
+/* LCDC */
+static struct fb_videomode lcdc0_mode = {
+ .name = "AMPIER/AM-800480",
+ .xres = 800,
+ .yres = 480,
+ .left_margin = 88,
+ .right_margin = 40,
+ .hsync_len = 128,
+ .upper_margin = 20,
+ .lower_margin = 5,
+ .vsync_len = 5,
+ .sync = 0,
+};
+
+static struct sh_mobile_lcdc_info lcdc0_info = {
+ .clock_source = LCDC_CLK_BUS,
+ .ch[0] = {
+ .chan = LCDC_CHAN_MAINLCD,
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .interface_type = RGB24,
+ .clock_divider = 5,
+ .flags = 0,
+ .lcd_modes = &lcdc0_mode,
+ .num_modes = 1,
+ .panel_cfg = {
+ .width = 111,
+ .height = 68,
+ },
+ },
+};
+
+static struct resource lcdc0_resources[] = {
+ [0] = {
+ .name = "LCD0",
+ .start = 0xfe940000,
+ .end = 0xfe943fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = intcs_evt2irq(0x580),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device lcdc0_device = {
+ .name = "sh_mobile_lcdc_fb",
+ .num_resources = ARRAY_SIZE(lcdc0_resources),
+ .resource = lcdc0_resources,
+ .id = 0,
+ .dev = {
+ .platform_data = &lcdc0_info,
+ .coherent_dma_mask = ~0,
+ },
+};
+
+/* GPIO KEY */
+#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
+
+static struct gpio_keys_button gpio_buttons[] = {
+ GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW1"),
+ GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW2"),
+ GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW3"),
+ GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW4"),
+};
+
+static struct gpio_keys_platform_data gpio_key_info = {
+ .buttons = gpio_buttons,
+ .nbuttons = ARRAY_SIZE(gpio_buttons),
+};
+
+static struct platform_device gpio_keys_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &gpio_key_info,
+ },
+};
+
+/* SDHI0 */
+/*
+ * FIXME
+ *
+ * It use polling mode here, since
+ * CD (= Card Detect) pin is not connected to SDHI0_CD.
+ * We can use IRQ31 as card detect irq,
+ * but it needs chattering removal operation
+ */
+#define IRQ31 evt2irq(0x33E0)
+static struct sh_mobile_sdhi_info sdhi0_info = {
+ .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |\
+ MMC_CAP_NEEDS_POLL,
+ .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
+ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
+};
+
+static struct resource sdhi0_resources[] = {
+ {
+ .name = "SDHI0",
+ .start = 0xe6850000,
+ .end = 0xe6850100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ /*
+ * no SH_MOBILE_SDHI_IRQ_CARD_DETECT here
+ */
+ {
+ .name = SH_MOBILE_SDHI_IRQ_SDCARD,
+ .start = evt2irq(0x0E20),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = SH_MOBILE_SDHI_IRQ_SDIO,
+ .start = evt2irq(0x0E40),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sdhi0_device = {
+ .name = "sh_mobile_sdhi",
+ .id = 0,
+ .dev = {
+ .platform_data = &sdhi0_info,
+ },
+ .num_resources = ARRAY_SIZE(sdhi0_resources),
+ .resource = sdhi0_resources,
+};
+
+/* SDHI1 */
+static struct sh_mobile_sdhi_info sdhi1_info = {
+ .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
+ .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
+ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
+};
+
+static struct resource sdhi1_resources[] = {
+ [0] = {
+ .name = "SDHI1",
+ .start = 0xe6860000,
+ .end = 0xe6860100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x0E80),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = evt2irq(0x0EA0),
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = evt2irq(0x0EC0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sdhi1_device = {
+ .name = "sh_mobile_sdhi",
+ .id = 1,
+ .dev = {
+ .platform_data = &sdhi1_info,
+ },
+ .num_resources = ARRAY_SIZE(sdhi1_resources),
+ .resource = sdhi1_resources,
+};
+
+/* MMCIF */
+static struct sh_mmcif_plat_data sh_mmcif_plat = {
+ .sup_pclk = 0,
+ .ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
+ .caps = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_8_BIT_DATA |
+ MMC_CAP_NONREMOVABLE,
+};
+
+static struct resource sh_mmcif_resources[] = {
+ [0] = {
+ .name = "MMCIF",
+ .start = 0xe6bd0000,
+ .end = 0xe6bd0100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* MMC ERR */
+ .start = evt2irq(0x1AC0),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* MMC NOR */
+ .start = evt2irq(0x1AE0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sh_mmcif_device = {
+ .name = "sh_mmcif",
+ .id = -1,
+ .dev = {
+ .platform_data = &sh_mmcif_plat,
+ },
+ .num_resources = ARRAY_SIZE(sh_mmcif_resources),
+ .resource = sh_mmcif_resources,
+};
+
+/* I2C */
+static struct i2c_board_info i2c0_devices[] = {
+ {
+ I2C_BOARD_INFO("st1232-ts", 0x55),
+ .irq = evt2irq(0x0340),
+ },
+};
+
+/*
+ * board devices
+ */
+static struct platform_device *eva_devices[] __initdata = {
+ &lcdc0_device,
+ &gpio_keys_device,
+ &sh_eth_device,
+ &sdhi0_device,
+ &sh_mmcif_device,
+};
+
+static void __init eva_clock_init(void)
+{
+ struct clk *system = clk_get(NULL, "system_clk");
+ struct clk *xtal1 = clk_get(NULL, "extal1");
+ struct clk *usb24s = clk_get(NULL, "usb24s");
+
+ if (IS_ERR(system) ||
+ IS_ERR(xtal1) ||
+ IS_ERR(usb24s)) {
+ pr_err("armadillo800eva board clock init failed\n");
+ goto clock_error;
+ }
+
+ /* armadillo 800 eva extal1 is 24MHz */
+ clk_set_rate(xtal1, 24000000);
+
+ /* usb24s use extal1 (= system) clock (= 24MHz) */
+ clk_set_parent(usb24s, system);
+
+clock_error:
+ if (!IS_ERR(system))
+ clk_put(system);
+ if (!IS_ERR(xtal1))
+ clk_put(xtal1);
+ if (!IS_ERR(usb24s))
+ clk_put(usb24s);
+}
+
+/*
+ * board init
+ */
+static void __init eva_init(void)
+{
+ eva_clock_init();
+
+ r8a7740_pinmux_init();
+
+ /* SCIFA1 */
+ gpio_request(GPIO_FN_SCIFA1_RXD, NULL);
+ gpio_request(GPIO_FN_SCIFA1_TXD, NULL);
+
+ /* LCDC0 */
+ gpio_request(GPIO_FN_LCDC0_SELECT, NULL);
+ gpio_request(GPIO_FN_LCD0_D0, NULL);
+ gpio_request(GPIO_FN_LCD0_D1, NULL);
+ gpio_request(GPIO_FN_LCD0_D2, NULL);
+ gpio_request(GPIO_FN_LCD0_D3, NULL);
+ gpio_request(GPIO_FN_LCD0_D4, NULL);
+ gpio_request(GPIO_FN_LCD0_D5, NULL);
+ gpio_request(GPIO_FN_LCD0_D6, NULL);
+ gpio_request(GPIO_FN_LCD0_D7, NULL);
+ gpio_request(GPIO_FN_LCD0_D8, NULL);
+ gpio_request(GPIO_FN_LCD0_D9, NULL);
+ gpio_request(GPIO_FN_LCD0_D10, NULL);
+ gpio_request(GPIO_FN_LCD0_D11, NULL);
+ gpio_request(GPIO_FN_LCD0_D12, NULL);
+ gpio_request(GPIO_FN_LCD0_D13, NULL);
+ gpio_request(GPIO_FN_LCD0_D14, NULL);
+ gpio_request(GPIO_FN_LCD0_D15, NULL);
+ gpio_request(GPIO_FN_LCD0_D16, NULL);
+ gpio_request(GPIO_FN_LCD0_D17, NULL);
+ gpio_request(GPIO_FN_LCD0_D18_PORT40, NULL);
+ gpio_request(GPIO_FN_LCD0_D19_PORT4, NULL);
+ gpio_request(GPIO_FN_LCD0_D20_PORT3, NULL);
+ gpio_request(GPIO_FN_LCD0_D21_PORT2, NULL);
+ gpio_request(GPIO_FN_LCD0_D22_PORT0, NULL);
+ gpio_request(GPIO_FN_LCD0_D23_PORT1, NULL);
+ gpio_request(GPIO_FN_LCD0_DCK, NULL);
+ gpio_request(GPIO_FN_LCD0_VSYN, NULL);
+ gpio_request(GPIO_FN_LCD0_HSYN, NULL);
+ gpio_request(GPIO_FN_LCD0_DISP, NULL);
+ gpio_request(GPIO_FN_LCD0_LCLK_PORT165, NULL);
+
+ gpio_request(GPIO_PORT61, NULL); /* LCDDON */
+ gpio_direction_output(GPIO_PORT61, 1);
+
+ gpio_request(GPIO_PORT202, NULL); /* LCD0_LED_CONT */
+ gpio_direction_output(GPIO_PORT202, 0);
+
+ /* Touchscreen */
+ gpio_request(GPIO_FN_IRQ10, NULL); /* TP_INT */
+ gpio_request(GPIO_PORT166, NULL); /* TP_RST_B */
+ gpio_direction_output(GPIO_PORT166, 1);
+
+ /* GETHER */
+ gpio_request(GPIO_FN_ET_CRS, NULL);
+ gpio_request(GPIO_FN_ET_MDC, NULL);
+ gpio_request(GPIO_FN_ET_MDIO, NULL);
+ gpio_request(GPIO_FN_ET_TX_ER, NULL);
+ gpio_request(GPIO_FN_ET_RX_ER, NULL);
+ gpio_request(GPIO_FN_ET_ERXD0, NULL);
+ gpio_request(GPIO_FN_ET_ERXD1, NULL);
+ gpio_request(GPIO_FN_ET_ERXD2, NULL);
+ gpio_request(GPIO_FN_ET_ERXD3, NULL);
+ gpio_request(GPIO_FN_ET_TX_CLK, NULL);
+ gpio_request(GPIO_FN_ET_TX_EN, NULL);
+ gpio_request(GPIO_FN_ET_ETXD0, NULL);
+ gpio_request(GPIO_FN_ET_ETXD1, NULL);
+ gpio_request(GPIO_FN_ET_ETXD2, NULL);
+ gpio_request(GPIO_FN_ET_ETXD3, NULL);
+ gpio_request(GPIO_FN_ET_PHY_INT, NULL);
+ gpio_request(GPIO_FN_ET_COL, NULL);
+ gpio_request(GPIO_FN_ET_RX_DV, NULL);
+ gpio_request(GPIO_FN_ET_RX_CLK, NULL);
+
+ gpio_request(GPIO_PORT18, NULL); /* PHY_RST */
+ gpio_direction_output(GPIO_PORT18, 1);
+
+ /* USB */
+ gpio_request(GPIO_PORT159, NULL); /* USB_DEVICE_MODE */
+ gpio_direction_input(GPIO_PORT159);
+
+ if (gpio_get_value(GPIO_PORT159)) {
+ /* USB Host */
+ } else {
+ /* USB Func */
+ gpio_request(GPIO_FN_VBUS, NULL);
+ platform_device_register(&usbhsf_device);
+ }
+
+ /* SDHI0 */
+ gpio_request(GPIO_FN_SDHI0_CMD, NULL);
+ gpio_request(GPIO_FN_SDHI0_CLK, NULL);
+ gpio_request(GPIO_FN_SDHI0_D0, NULL);
+ gpio_request(GPIO_FN_SDHI0_D1, NULL);
+ gpio_request(GPIO_FN_SDHI0_D2, NULL);
+ gpio_request(GPIO_FN_SDHI0_D3, NULL);
+ gpio_request(GPIO_FN_SDHI0_WP, NULL);
+
+ gpio_request(GPIO_PORT17, NULL); /* SDHI0_18/33_B */
+ gpio_request(GPIO_PORT74, NULL); /* SDHI0_PON */
+ gpio_request(GPIO_PORT75, NULL); /* SDSLOT1_PON */
+ gpio_direction_output(GPIO_PORT17, 0);
+ gpio_direction_output(GPIO_PORT74, 1);
+ gpio_direction_output(GPIO_PORT75, 1);
+
+ /* we can use GPIO_FN_IRQ31_PORT167 here for SDHI0 CD irq */
+
+ /*
+ * MMCIF
+ *
+ * Here doesn't care SW1.4 status,
+ * since CON2 is not mounted.
+ */
+ gpio_request(GPIO_FN_MMC1_CLK_PORT103, NULL);
+ gpio_request(GPIO_FN_MMC1_CMD_PORT104, NULL);
+ gpio_request(GPIO_FN_MMC1_D0_PORT149, NULL);
+ gpio_request(GPIO_FN_MMC1_D1_PORT148, NULL);
+ gpio_request(GPIO_FN_MMC1_D2_PORT147, NULL);
+ gpio_request(GPIO_FN_MMC1_D3_PORT146, NULL);
+ gpio_request(GPIO_FN_MMC1_D4_PORT145, NULL);
+ gpio_request(GPIO_FN_MMC1_D5_PORT144, NULL);
+ gpio_request(GPIO_FN_MMC1_D6_PORT143, NULL);
+ gpio_request(GPIO_FN_MMC1_D7_PORT142, NULL);
+
+ /*
+ * CAUTION
+ *
+ * DBGMD/LCDC0/FSIA MUX
+ * DBGMD_SELECT_B should be set after setting PFC Function.
+ */
+ gpio_request(GPIO_PORT176, NULL);
+ gpio_direction_output(GPIO_PORT176, 1);
+
+ /*
+ * We can switch CON8/CON14 by SW1.5,
+ * but it needs after DBGMD_SELECT_B
+ */
+ gpio_request(GPIO_PORT6, NULL);
+ gpio_direction_input(GPIO_PORT6);
+ if (gpio_get_value(GPIO_PORT6)) {
+ /* CON14 enable */
+ } else {
+ /* CON8 (SDHI1) enable */
+ gpio_request(GPIO_FN_SDHI1_CLK, NULL);
+ gpio_request(GPIO_FN_SDHI1_CMD, NULL);
+ gpio_request(GPIO_FN_SDHI1_D0, NULL);
+ gpio_request(GPIO_FN_SDHI1_D1, NULL);
+ gpio_request(GPIO_FN_SDHI1_D2, NULL);
+ gpio_request(GPIO_FN_SDHI1_D3, NULL);
+ gpio_request(GPIO_FN_SDHI1_CD, NULL);
+ gpio_request(GPIO_FN_SDHI1_WP, NULL);
+
+ gpio_request(GPIO_PORT16, NULL); /* SDSLOT2_PON */
+ gpio_direction_output(GPIO_PORT16, 1);
+
+ platform_device_register(&sdhi1_device);
+ }
+
+
+#ifdef CONFIG_CACHE_L2X0
+ /* Early BRESP enable, Shared attribute override enable, 32K*8way */
+ l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff);
+#endif
+
+ i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices));
+
+ r8a7740_add_standard_devices();
+
+ platform_add_devices(eva_devices,
+ ARRAY_SIZE(eva_devices));
+}
+
+static void __init eva_earlytimer_init(void)
+{
+ r8a7740_clock_init(MD_CK0 | MD_CK2);
+ shmobile_earlytimer_init();
+}
+
+static void __init eva_add_early_devices(void)
+{
+ r8a7740_add_early_devices();
+
+ /* override timer setup with board-specific code */
+ shmobile_timer.init = eva_earlytimer_init;
+}
+
+static const char *eva_boards_compat_dt[] __initdata = {
+ "renesas,armadillo800eva",
+ NULL,
+};
+
+DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva")
+ .map_io = r8a7740_map_io,
+ .init_early = eva_add_early_devices,
+ .init_irq = r8a7740_init_irq,
+ .handle_irq = shmobile_handle_irq_intc,
+ .init_machine = eva_init,
+ .timer = &shmobile_timer,
+ .dt_compat = eva_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-bonito.c b/arch/arm/mach-shmobile/board-bonito.c
index 81fd95f7f52a..63ab7062bee3 100644
--- a/arch/arm/mach-shmobile/board-bonito.c
+++ b/arch/arm/mach-shmobile/board-bonito.c
@@ -486,7 +486,7 @@ static void __init bonito_earlytimer_init(void)
shmobile_earlytimer_init();
}
-void __init bonito_add_early_devices(void)
+static void __init bonito_add_early_devices(void)
{
r8a7740_add_early_devices();
diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c
new file mode 100644
index 000000000000..7bc5e7d39f9b
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-kzm9d.c
@@ -0,0 +1,85 @@
+/*
+ * kzm9d board support
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2012 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/smsc911x.h>
+#include <mach/common.h>
+#include <mach/emev2.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
+
+/* Ether */
+static struct resource smsc911x_resources[] = {
+ [0] = {
+ .start = 0x20000000,
+ .end = 0x2000ffff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = EMEV2_GPIO_IRQ(1),
+ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
+ },
+};
+
+static struct smsc911x_platform_config smsc911x_platdata = {
+ .flags = SMSC911X_USE_32BIT,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+};
+
+static struct platform_device smsc91x_device = {
+ .name = "smsc911x",
+ .id = 0,
+ .dev = {
+ .platform_data = &smsc911x_platdata,
+ },
+ .num_resources = ARRAY_SIZE(smsc911x_resources),
+ .resource = smsc911x_resources,
+};
+
+static struct platform_device *kzm9d_devices[] __initdata = {
+ &smsc91x_device,
+};
+
+void __init kzm9d_add_standard_devices(void)
+{
+ emev2_add_standard_devices();
+
+ platform_add_devices(kzm9d_devices, ARRAY_SIZE(kzm9d_devices));
+}
+
+static const char *kzm9d_boards_compat_dt[] __initdata = {
+ "renesas,kzm9d",
+ NULL,
+};
+
+DT_MACHINE_START(KZM9D_DT, "kzm9d")
+ .map_io = emev2_map_io,
+ .init_early = emev2_add_early_devices,
+ .nr_irqs = NR_IRQS_LEGACY,
+ .init_irq = emev2_init_irq,
+ .handle_irq = gic_handle_irq,
+ .init_machine = kzm9d_add_standard_devices,
+ .timer = &shmobile_timer,
+ .dt_compat = kzm9d_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
new file mode 100644
index 000000000000..d8e33b682832
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -0,0 +1,460 @@
+/*
+ * KZM-A9-GT board support
+ *
+ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pcf857x.h>
+#include <linux/input.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/mfd/tmio.h>
+#include <linux/platform_device.h>
+#include <linux/smsc911x.h>
+#include <linux/usb/r8a66597.h>
+#include <linux/videodev2.h>
+#include <mach/irqs.h>
+#include <mach/sh73a0.h>
+#include <mach/common.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <video/sh_mobile_lcdc.h>
+
+/*
+ * external GPIO
+ */
+#define GPIO_PCF8575_BASE (GPIO_NR)
+#define GPIO_PCF8575_PORT10 (GPIO_NR + 8)
+#define GPIO_PCF8575_PORT11 (GPIO_NR + 9)
+#define GPIO_PCF8575_PORT12 (GPIO_NR + 10)
+#define GPIO_PCF8575_PORT13 (GPIO_NR + 11)
+#define GPIO_PCF8575_PORT14 (GPIO_NR + 12)
+#define GPIO_PCF8575_PORT15 (GPIO_NR + 13)
+#define GPIO_PCF8575_PORT16 (GPIO_NR + 14)
+
+/* SMSC 9221 */
+static struct resource smsc9221_resources[] = {
+ [0] = {
+ .start = 0x10000000, /* CS4 */
+ .end = 0x100000ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = intcs_evt2irq(0x260), /* IRQ3 */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct smsc911x_platform_config smsc9221_platdata = {
+ .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+};
+
+static struct platform_device smsc_device = {
+ .name = "smsc911x",
+ .dev = {
+ .platform_data = &smsc9221_platdata,
+ },
+ .resource = smsc9221_resources,
+ .num_resources = ARRAY_SIZE(smsc9221_resources),
+};
+
+/* USB external chip */
+static struct r8a66597_platdata usb_host_data = {
+ .on_chip = 0,
+ .xtal = R8A66597_PLATDATA_XTAL_48MHZ,
+};
+
+static struct resource usb_resources[] = {
+ [0] = {
+ .start = 0x10010000,
+ .end = 0x1001ffff - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = intcs_evt2irq(0x220), /* IRQ1 */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device usb_host_device = {
+ .name = "r8a66597_hcd",
+ .dev = {
+ .platform_data = &usb_host_data,
+ .dma_mask = NULL,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(usb_resources),
+ .resource = usb_resources,
+};
+
+/* LCDC */
+static struct fb_videomode kzm_lcdc_mode = {
+ .name = "WVGA Panel",
+ .xres = 800,
+ .yres = 480,
+ .left_margin = 220,
+ .right_margin = 110,
+ .hsync_len = 70,
+ .upper_margin = 20,
+ .lower_margin = 5,
+ .vsync_len = 5,
+ .sync = 0,
+};
+
+static struct sh_mobile_lcdc_info lcdc_info = {
+ .clock_source = LCDC_CLK_BUS,
+ .ch[0] = {
+ .chan = LCDC_CHAN_MAINLCD,
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .interface_type = RGB24,
+ .lcd_modes = &kzm_lcdc_mode,
+ .num_modes = 1,
+ .clock_divider = 5,
+ .flags = 0,
+ .panel_cfg = {
+ .width = 152,
+ .height = 91,
+ },
+ }
+};
+
+static struct resource lcdc_resources[] = {
+ [0] = {
+ .name = "LCDC",
+ .start = 0xfe940000,
+ .end = 0xfe943fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = intcs_evt2irq(0x580),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device lcdc_device = {
+ .name = "sh_mobile_lcdc_fb",
+ .num_resources = ARRAY_SIZE(lcdc_resources),
+ .resource = lcdc_resources,
+ .dev = {
+ .platform_data = &lcdc_info,
+ .coherent_dma_mask = ~0,
+ },
+};
+
+/* MMCIF */
+static struct resource sh_mmcif_resources[] = {
+ [0] = {
+ .name = "MMCIF",
+ .start = 0xe6bd0000,
+ .end = 0xe6bd00ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(141),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = gic_spi(140),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct sh_mmcif_plat_data sh_mmcif_platdata = {
+ .ocr = MMC_VDD_165_195,
+ .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+};
+
+static struct platform_device mmc_device = {
+ .name = "sh_mmcif",
+ .dev = {
+ .dma_mask = NULL,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &sh_mmcif_platdata,
+ },
+ .num_resources = ARRAY_SIZE(sh_mmcif_resources),
+ .resource = sh_mmcif_resources,
+};
+
+/* SDHI */
+static struct sh_mobile_sdhi_info sdhi0_info = {
+ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
+ .tmio_caps = MMC_CAP_SD_HIGHSPEED,
+ .tmio_ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
+};
+
+static struct resource sdhi0_resources[] = {
+ [0] = {
+ .name = "SDHI0",
+ .start = 0xee100000,
+ .end = 0xee1000ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT,
+ .start = gic_spi(83),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDCARD,
+ .start = gic_spi(84),
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDIO,
+ .start = gic_spi(85),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sdhi0_device = {
+ .name = "sh_mobile_sdhi",
+ .num_resources = ARRAY_SIZE(sdhi0_resources),
+ .resource = sdhi0_resources,
+ .dev = {
+ .platform_data = &sdhi0_info,
+ },
+};
+
+/* KEY */
+#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
+
+static struct gpio_keys_button gpio_buttons[] = {
+ GPIO_KEY(KEY_BACK, GPIO_PCF8575_PORT10, "SW3"),
+ GPIO_KEY(KEY_RIGHT, GPIO_PCF8575_PORT11, "SW2-R"),
+ GPIO_KEY(KEY_LEFT, GPIO_PCF8575_PORT12, "SW2-L"),
+ GPIO_KEY(KEY_ENTER, GPIO_PCF8575_PORT13, "SW2-P"),
+ GPIO_KEY(KEY_UP, GPIO_PCF8575_PORT14, "SW2-U"),
+ GPIO_KEY(KEY_DOWN, GPIO_PCF8575_PORT15, "SW2-D"),
+ GPIO_KEY(KEY_HOME, GPIO_PCF8575_PORT16, "SW1"),
+};
+
+static struct gpio_keys_platform_data gpio_key_info = {
+ .buttons = gpio_buttons,
+ .nbuttons = ARRAY_SIZE(gpio_buttons),
+ .poll_interval = 250, /* poling at this point */
+};
+
+static struct platform_device gpio_keys_device = {
+ /* gpio-pcf857x.c driver doesn't support gpio_to_irq() */
+ .name = "gpio-keys-polled",
+ .dev = {
+ .platform_data = &gpio_key_info,
+ },
+};
+
+/* I2C */
+static struct pcf857x_platform_data pcf8575_pdata = {
+ .gpio_base = GPIO_PCF8575_BASE,
+};
+
+static struct i2c_board_info i2c1_devices[] = {
+ {
+ I2C_BOARD_INFO("st1232-ts", 0x55),
+ .irq = intcs_evt2irq(0x300), /* IRQ8 */
+ },
+};
+
+static struct i2c_board_info i2c3_devices[] = {
+ {
+ I2C_BOARD_INFO("pcf8575", 0x20),
+ .platform_data = &pcf8575_pdata,
+ },
+};
+
+static struct platform_device *kzm_devices[] __initdata = {
+ &smsc_device,
+ &usb_host_device,
+ &lcdc_device,
+ &mmc_device,
+ &sdhi0_device,
+ &gpio_keys_device,
+};
+
+/*
+ * FIXME
+ *
+ * This is quick hack for enabling LCDC backlight
+ */
+static int __init as3711_enable_lcdc_backlight(void)
+{
+ struct i2c_adapter *a = i2c_get_adapter(0);
+ struct i2c_msg msg;
+ int i, ret;
+ __u8 magic[] = {
+ 0x40, 0x2a,
+ 0x43, 0x3c,
+ 0x44, 0x3c,
+ 0x45, 0x3c,
+ 0x54, 0x03,
+ 0x51, 0x00,
+ 0x51, 0x01,
+ 0xff, 0x00, /* wait */
+ 0x43, 0xf0,
+ 0x44, 0xf0,
+ 0x45, 0xf0,
+ };
+
+ if (!machine_is_kzm9g())
+ return 0;
+
+ if (!a)
+ return 0;
+
+ msg.addr = 0x40;
+ msg.len = 2;
+ msg.flags = 0;
+
+ for (i = 0; i < ARRAY_SIZE(magic); i += 2) {
+ msg.buf = magic + i;
+
+ if (0xff == msg.buf[0]) {
+ udelay(500);
+ continue;
+ }
+
+ ret = i2c_transfer(a, &msg, 1);
+ if (ret < 0) {
+ pr_err("i2c transfer fail\n");
+ break;
+ }
+ }
+
+ return 0;
+}
+device_initcall(as3711_enable_lcdc_backlight);
+
+static void __init kzm_init(void)
+{
+ sh73a0_pinmux_init();
+
+ /* enable SCIFA4 */
+ gpio_request(GPIO_FN_SCIFA4_TXD, NULL);
+ gpio_request(GPIO_FN_SCIFA4_RXD, NULL);
+ gpio_request(GPIO_FN_SCIFA4_RTS_, NULL);
+ gpio_request(GPIO_FN_SCIFA4_CTS_, NULL);
+
+ /* CS4 for SMSC/USB */
+ gpio_request(GPIO_FN_CS4_, NULL); /* CS4 */
+
+ /* SMSC */
+ gpio_request(GPIO_PORT224, NULL); /* IRQ3 */
+ gpio_direction_input(GPIO_PORT224);
+
+ /* LCDC */
+ gpio_request(GPIO_FN_LCDD23, NULL);
+ gpio_request(GPIO_FN_LCDD22, NULL);
+ gpio_request(GPIO_FN_LCDD21, NULL);
+ gpio_request(GPIO_FN_LCDD20, NULL);
+ gpio_request(GPIO_FN_LCDD19, NULL);
+ gpio_request(GPIO_FN_LCDD18, NULL);
+ gpio_request(GPIO_FN_LCDD17, NULL);
+ gpio_request(GPIO_FN_LCDD16, NULL);
+ gpio_request(GPIO_FN_LCDD15, NULL);
+ gpio_request(GPIO_FN_LCDD14, NULL);
+ gpio_request(GPIO_FN_LCDD13, NULL);
+ gpio_request(GPIO_FN_LCDD12, NULL);
+ gpio_request(GPIO_FN_LCDD11, NULL);
+ gpio_request(GPIO_FN_LCDD10, NULL);
+ gpio_request(GPIO_FN_LCDD9, NULL);
+ gpio_request(GPIO_FN_LCDD8, NULL);
+ gpio_request(GPIO_FN_LCDD7, NULL);
+ gpio_request(GPIO_FN_LCDD6, NULL);
+ gpio_request(GPIO_FN_LCDD5, NULL);
+ gpio_request(GPIO_FN_LCDD4, NULL);
+ gpio_request(GPIO_FN_LCDD3, NULL);
+ gpio_request(GPIO_FN_LCDD2, NULL);
+ gpio_request(GPIO_FN_LCDD1, NULL);
+ gpio_request(GPIO_FN_LCDD0, NULL);
+ gpio_request(GPIO_FN_LCDDISP, NULL);
+ gpio_request(GPIO_FN_LCDDCK, NULL);
+
+ gpio_request(GPIO_PORT222, NULL); /* LCDCDON */
+ gpio_request(GPIO_PORT226, NULL); /* SC */
+ gpio_direction_output(GPIO_PORT222, 1);
+ gpio_direction_output(GPIO_PORT226, 1);
+
+ /* Touchscreen */
+ gpio_request(GPIO_PORT223, NULL); /* IRQ8 */
+ gpio_direction_input(GPIO_PORT223);
+
+ /* enable MMCIF */
+ gpio_request(GPIO_FN_MMCCLK0, NULL);
+ gpio_request(GPIO_FN_MMCCMD0_PU, NULL);
+ gpio_request(GPIO_FN_MMCD0_0_PU, NULL);
+ gpio_request(GPIO_FN_MMCD0_1_PU, NULL);
+ gpio_request(GPIO_FN_MMCD0_2_PU, NULL);
+ gpio_request(GPIO_FN_MMCD0_3_PU, NULL);
+ gpio_request(GPIO_FN_MMCD0_4_PU, NULL);
+ gpio_request(GPIO_FN_MMCD0_5_PU, NULL);
+ gpio_request(GPIO_FN_MMCD0_6_PU, NULL);
+ gpio_request(GPIO_FN_MMCD0_7_PU, NULL);
+
+ /* enable SD */
+ gpio_request(GPIO_FN_SDHIWP0, NULL);
+ gpio_request(GPIO_FN_SDHICD0, NULL);
+ gpio_request(GPIO_FN_SDHICMD0, NULL);
+ gpio_request(GPIO_FN_SDHICLK0, NULL);
+ gpio_request(GPIO_FN_SDHID0_3, NULL);
+ gpio_request(GPIO_FN_SDHID0_2, NULL);
+ gpio_request(GPIO_FN_SDHID0_1, NULL);
+ gpio_request(GPIO_FN_SDHID0_0, NULL);
+ gpio_request(GPIO_FN_SDHI0_VCCQ_MC0_ON, NULL);
+ gpio_request(GPIO_PORT15, NULL);
+ gpio_direction_output(GPIO_PORT15, 1); /* power */
+
+ /* I2C 3 */
+ gpio_request(GPIO_FN_PORT27_I2C_SCL3, NULL);
+ gpio_request(GPIO_FN_PORT28_I2C_SDA3, NULL);
+
+#ifdef CONFIG_CACHE_L2X0
+ /* Early BRESP enable, Shared attribute override enable, 64K*8way */
+ l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
+#endif
+
+ i2c_register_board_info(1, i2c1_devices, ARRAY_SIZE(i2c1_devices));
+ i2c_register_board_info(3, i2c3_devices, ARRAY_SIZE(i2c3_devices));
+
+ sh73a0_add_standard_devices();
+ platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices));
+}
+
+static const char *kzm9g_boards_compat_dt[] __initdata = {
+ "renesas,kzm9g",
+ NULL,
+};
+
+DT_MACHINE_START(KZM9G_DT, "kzm9g")
+ .map_io = sh73a0_map_io,
+ .init_early = sh73a0_add_early_devices,
+ .nr_irqs = NR_IRQS_LEGACY,
+ .init_irq = sh73a0_init_irq,
+ .handle_irq = gic_handle_irq,
+ .init_machine = kzm_init,
+ .timer = &shmobile_timer,
+ .dt_compat = kzm9g_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 8c6202bb6aeb..50c67b22d087 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -53,6 +53,7 @@
#include <media/soc_camera.h>
#include <media/soc_camera_platform.h>
#include <sound/sh_fsi.h>
+#include <sound/simple_card.h>
#include <mach/common.h>
#include <mach/irqs.h>
@@ -502,8 +503,26 @@ static struct platform_device hdmi_lcdc_device = {
},
};
+static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = {
+ .cpu_daifmt = SND_SOC_DAIFMT_CBM_CFM,
+};
+
+static struct asoc_simple_card_info fsi2_hdmi_info = {
+ .name = "HDMI",
+ .card = "FSI2B-HDMI",
+ .cpu_dai = "fsib-dai",
+ .codec = "sh-mobile-hdmi",
+ .platform = "sh_fsi2",
+ .codec_dai = "sh_mobile_hdmi-hifi",
+ .init = &fsi2_hdmi_init_info,
+};
+
static struct platform_device fsi_hdmi_device = {
- .name = "sh_fsi2_b_hdmi",
+ .name = "asoc-simple-card",
+ .id = 1,
+ .dev = {
+ .platform_data = &fsi2_hdmi_info,
+ },
};
static void __init hdmi_init_pm_clock(void)
@@ -908,6 +927,8 @@ fsi_set_rate_end:
static struct sh_fsi_platform_info fsi_info = {
.port_a = {
.flags = SH_FSI_BRS_INV,
+ .tx_id = SHDMA_SLAVE_FSIA_TX,
+ .rx_id = SHDMA_SLAVE_FSIA_RX,
},
.port_b = {
.flags = SH_FSI_BRS_INV |
@@ -920,9 +941,11 @@ static struct sh_fsi_platform_info fsi_info = {
static struct resource fsi_resources[] = {
[0] = {
+ /* we need 0xFE1F0000 to access DMA
+ * instead of 0xFE3C0000 */
.name = "FSI",
- .start = 0xFE3C0000,
- .end = 0xFE3C0400 - 1,
+ .start = 0xFE1F0000,
+ .end = 0xFE1F0400 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -941,17 +964,25 @@ static struct platform_device fsi_device = {
},
};
-static struct fsi_ak4642_info fsi2_ak4643_info = {
+static struct asoc_simple_dai_init_info fsi2_ak4643_init_info = {
+ .fmt = SND_SOC_DAIFMT_LEFT_J,
+ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
+ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
+ .sysclk = 11289600,
+};
+
+static struct asoc_simple_card_info fsi2_ak4643_info = {
.name = "AK4643",
.card = "FSI2A-AK4643",
.cpu_dai = "fsia-dai",
.codec = "ak4642-codec.0-0013",
.platform = "sh_fsi2",
- .id = FSI_PORT_A,
+ .codec_dai = "ak4642-hifi",
+ .init = &fsi2_ak4643_init_info,
};
static struct platform_device fsi_ak4643_device = {
- .name = "fsi-ak4642-audio",
+ .name = "asoc-simple-card",
.dev = {
.platform_data = &fsi2_ak4643_info,
},
@@ -1248,6 +1279,8 @@ static void mackerel_camera_del(struct soc_camera_device *icd)
static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
.flags = SH_CEU_FLAG_USE_8BIT_BUS,
+ .max_width = 8188,
+ .max_height = 8188,
};
static struct resource ceu_resources[] = {
diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c
new file mode 100644
index 000000000000..4710f1847bb7
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-emev2.c
@@ -0,0 +1,249 @@
+/*
+ * Emma Mobile EV2 clock framework support
+ *
+ * Copyright (C) 2012 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+#include <mach/common.h>
+
+#define EMEV2_SMU_BASE 0xe0110000
+
+/* EMEV2 SMU registers */
+#define USIAU0_RSTCTRL 0x094
+#define USIBU1_RSTCTRL 0x0ac
+#define USIBU2_RSTCTRL 0x0b0
+#define USIBU3_RSTCTRL 0x0b4
+#define STI_RSTCTRL 0x124
+#define USIAU0GCLKCTRL 0x4a0
+#define USIBU1GCLKCTRL 0x4b8
+#define USIBU2GCLKCTRL 0x4bc
+#define USIBU3GCLKCTRL 0x04c0
+#define STIGCLKCTRL 0x528
+#define USIAU0SCLKDIV 0x61c
+#define USIB2SCLKDIV 0x65c
+#define USIB3SCLKDIV 0x660
+#define STI_CLKSEL 0x688
+#define SMU_GENERAL_REG0 0x7c0
+
+/* not pretty, but hey */
+static void __iomem *smu_base;
+
+static void emev2_smu_write(unsigned long value, int offs)
+{
+ BUG_ON(!smu_base || (offs >= PAGE_SIZE));
+ iowrite32(value, smu_base + offs);
+}
+
+void emev2_set_boot_vector(unsigned long value)
+{
+ emev2_smu_write(value, SMU_GENERAL_REG0);
+}
+
+static struct clk_mapping smu_mapping = {
+ .phys = EMEV2_SMU_BASE,
+ .len = PAGE_SIZE,
+};
+
+/* Fixed 32 KHz root clock from C32K pin */
+static struct clk c32k_clk = {
+ .rate = 32768,
+ .mapping = &smu_mapping,
+};
+
+/* PLL3 multiplies C32K with 7000 */
+static unsigned long pll3_recalc(struct clk *clk)
+{
+ return clk->parent->rate * 7000;
+}
+
+static struct sh_clk_ops pll3_clk_ops = {
+ .recalc = pll3_recalc,
+};
+
+static struct clk pll3_clk = {
+ .ops = &pll3_clk_ops,
+ .parent = &c32k_clk,
+};
+
+static struct clk *main_clks[] = {
+ &c32k_clk,
+ &pll3_clk,
+};
+
+enum { SCLKDIV_USIAU0, SCLKDIV_USIBU2, SCLKDIV_USIBU1, SCLKDIV_USIBU3,
+ SCLKDIV_NR };
+
+#define SCLKDIV(_reg, _shift) \
+{ \
+ .parent = &pll3_clk, \
+ .enable_reg = IOMEM(EMEV2_SMU_BASE + (_reg)), \
+ .enable_bit = _shift, \
+}
+
+static struct clk sclkdiv_clks[SCLKDIV_NR] = {
+ [SCLKDIV_USIAU0] = SCLKDIV(USIAU0SCLKDIV, 0),
+ [SCLKDIV_USIBU2] = SCLKDIV(USIB2SCLKDIV, 16),
+ [SCLKDIV_USIBU1] = SCLKDIV(USIB2SCLKDIV, 0),
+ [SCLKDIV_USIBU3] = SCLKDIV(USIB3SCLKDIV, 0),
+};
+
+enum { GCLK_USIAU0_SCLK, GCLK_USIBU1_SCLK, GCLK_USIBU2_SCLK, GCLK_USIBU3_SCLK,
+ GCLK_STI_SCLK,
+ GCLK_NR };
+
+#define GCLK_SCLK(_parent, _reg) \
+{ \
+ .parent = _parent, \
+ .enable_reg = IOMEM(EMEV2_SMU_BASE + (_reg)), \
+ .enable_bit = 1, /* SCLK_GCC */ \
+}
+
+static struct clk gclk_clks[GCLK_NR] = {
+ [GCLK_USIAU0_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIAU0],
+ USIAU0GCLKCTRL),
+ [GCLK_USIBU1_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU1],
+ USIBU1GCLKCTRL),
+ [GCLK_USIBU2_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU2],
+ USIBU2GCLKCTRL),
+ [GCLK_USIBU3_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU3],
+ USIBU3GCLKCTRL),
+ [GCLK_STI_SCLK] = GCLK_SCLK(&c32k_clk, STIGCLKCTRL),
+};
+
+static int emev2_gclk_enable(struct clk *clk)
+{
+ iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
+ clk->mapped_reg);
+ return 0;
+}
+
+static void emev2_gclk_disable(struct clk *clk)
+{
+ iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
+ clk->mapped_reg);
+}
+
+static struct sh_clk_ops emev2_gclk_clk_ops = {
+ .enable = emev2_gclk_enable,
+ .disable = emev2_gclk_disable,
+ .recalc = followparent_recalc,
+};
+
+static int __init emev2_gclk_register(struct clk *clks, int nr)
+{
+ struct clk *clkp;
+ int ret = 0;
+ int k;
+
+ for (k = 0; !ret && (k < nr); k++) {
+ clkp = clks + k;
+ clkp->ops = &emev2_gclk_clk_ops;
+ ret |= clk_register(clkp);
+ }
+
+ return ret;
+}
+
+static unsigned long emev2_sclkdiv_recalc(struct clk *clk)
+{
+ unsigned int sclk_div;
+
+ sclk_div = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0xff;
+
+ return clk->parent->rate / (sclk_div + 1);
+}
+
+static struct sh_clk_ops emev2_sclkdiv_clk_ops = {
+ .recalc = emev2_sclkdiv_recalc,
+};
+
+static int __init emev2_sclkdiv_register(struct clk *clks, int nr)
+{
+ struct clk *clkp;
+ int ret = 0;
+ int k;
+
+ for (k = 0; !ret && (k < nr); k++) {
+ clkp = clks + k;
+ clkp->ops = &emev2_sclkdiv_clk_ops;
+ ret |= clk_register(clkp);
+ }
+
+ return ret;
+}
+
+static struct clk_lookup lookups[] = {
+ CLKDEV_DEV_ID("serial8250-em.0", &gclk_clks[GCLK_USIAU0_SCLK]),
+ CLKDEV_DEV_ID("e1020000.uart", &gclk_clks[GCLK_USIAU0_SCLK]),
+ CLKDEV_DEV_ID("serial8250-em.1", &gclk_clks[GCLK_USIBU1_SCLK]),
+ CLKDEV_DEV_ID("e1030000.uart", &gclk_clks[GCLK_USIBU1_SCLK]),
+ CLKDEV_DEV_ID("serial8250-em.2", &gclk_clks[GCLK_USIBU2_SCLK]),
+ CLKDEV_DEV_ID("e1040000.uart", &gclk_clks[GCLK_USIBU2_SCLK]),
+ CLKDEV_DEV_ID("serial8250-em.3", &gclk_clks[GCLK_USIBU3_SCLK]),
+ CLKDEV_DEV_ID("e1050000.uart", &gclk_clks[GCLK_USIBU3_SCLK]),
+ CLKDEV_DEV_ID("em_sti.0", &gclk_clks[GCLK_STI_SCLK]),
+ CLKDEV_DEV_ID("e0180000.sti", &gclk_clks[GCLK_STI_SCLK]),
+};
+
+void __init emev2_clock_init(void)
+{
+ int k, ret = 0;
+ static int is_setup;
+
+ /* yuck, this is ugly as hell, but the non-smp case of clocks
+ * code is now designed to rely on ioremap() instead of static
+ * entity maps. in the case of smp we need access to the SMU
+ * register earlier than ioremap() is actually working without
+ * any static maps. to enable SMP in ugly but with dynamic
+ * mappings we have to call emev2_clock_init() from different
+ * places depending on UP and SMP...
+ */
+ if (is_setup++)
+ return;
+
+ smu_base = ioremap(EMEV2_SMU_BASE, PAGE_SIZE);
+ BUG_ON(!smu_base);
+
+ /* setup STI timer to run on 37.768 kHz and deassert reset */
+ emev2_smu_write(0, STI_CLKSEL);
+ emev2_smu_write(1, STI_RSTCTRL);
+
+ /* deassert reset for UART0->UART3 */
+ emev2_smu_write(2, USIAU0_RSTCTRL);
+ emev2_smu_write(2, USIBU1_RSTCTRL);
+ emev2_smu_write(2, USIBU2_RSTCTRL);
+ emev2_smu_write(2, USIBU3_RSTCTRL);
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ if (!ret)
+ ret = emev2_sclkdiv_register(sclkdiv_clks, SCLKDIV_NR);
+
+ if (!ret)
+ ret = emev2_gclk_register(gclk_clks, GCLK_NR);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ shmobile_clk_init();
+ else
+ panic("failed to setup emev2 clocks\n");
+}
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index 99c4d743a99c..26eea5f21054 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -47,6 +47,7 @@
#define PLLC01CR 0xe6150028
#define SUBCKCR 0xe6150080
+#define USBCKCR 0xe615008c
#define MSTPSR0 0xe6150030
#define MSTPSR1 0xe6150038
@@ -181,6 +182,95 @@ static struct clk pllc1_div2_clk = {
.parent = &pllc1_clk,
};
+/* USB clock */
+static struct clk *usb24s_parents[] = {
+ [0] = &system_clk,
+ [1] = &extal2_clk
+};
+
+static int usb24s_enable(struct clk *clk)
+{
+ __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR);
+
+ return 0;
+}
+
+static void usb24s_disable(struct clk *clk)
+{
+ __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR);
+}
+
+static int usb24s_set_parent(struct clk *clk, struct clk *parent)
+{
+ int i, ret;
+ u32 val;
+
+ if (!clk->parent_table || !clk->parent_num)
+ return -EINVAL;
+
+ /* Search the parent */
+ for (i = 0; i < clk->parent_num; i++)
+ if (clk->parent_table[i] == parent)
+ break;
+
+ if (i == clk->parent_num)
+ return -ENODEV;
+
+ ret = clk_reparent(clk, parent);
+ if (ret < 0)
+ return ret;
+
+ val = __raw_readl(USBCKCR);
+ val &= ~(1 << 7);
+ val |= i << 7;
+ __raw_writel(val, USBCKCR);
+
+ return 0;
+}
+
+static struct sh_clk_ops usb24s_clk_ops = {
+ .recalc = followparent_recalc,
+ .enable = usb24s_enable,
+ .disable = usb24s_disable,
+ .set_parent = usb24s_set_parent,
+};
+
+static struct clk usb24s_clk = {
+ .ops = &usb24s_clk_ops,
+ .parent_table = usb24s_parents,
+ .parent_num = ARRAY_SIZE(usb24s_parents),
+ .parent = &system_clk,
+};
+
+static unsigned long usb24_recalc(struct clk *clk)
+{
+ return clk->parent->rate /
+ ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2);
+};
+
+static int usb24_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 val;
+
+ /* closer to which ? parent->rate or parent->rate/2 */
+ val = __raw_readl(USBCKCR);
+ val &= ~(1 << 6);
+ val |= (rate > (clk->parent->rate / 4) * 3) << 6;
+ __raw_writel(val, USBCKCR);
+
+ return 0;
+}
+
+static struct sh_clk_ops usb24_clk_ops = {
+ .recalc = usb24_recalc,
+ .set_rate = usb24_set_rate,
+};
+
+static struct clk usb24_clk = {
+ .ops = &usb24_clk_ops,
+ .parent = &usb24s_clk,
+};
+
struct clk *main_clks[] = {
&extalr_clk,
&extal1_clk,
@@ -196,6 +286,8 @@ struct clk *main_clks[] = {
&pllc0_clk,
&pllc1_clk,
&pllc1_div2_clk,
+ &usb24s_clk,
+ &usb24_clk,
};
static void div4_kick(struct clk *clk)
@@ -223,7 +315,7 @@ static struct clk_div4_table div4_table = {
enum {
DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
- DIV4_HPP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
+ DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
DIV4_NR
};
@@ -234,6 +326,7 @@ struct clk div4_clks[DIV4_NR] = {
[DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT),
[DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0),
[DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0),
+ [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0),
[DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0),
[DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0),
[DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0),
@@ -257,7 +350,11 @@ enum {
MSTP222,
MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
- MSTP329, MSTP323,
+ MSTP329, MSTP328, MSTP323, MSTP320,
+ MSTP314, MSTP313, MSTP312,
+ MSTP309,
+
+ MSTP416, MSTP415, MSTP407, MSTP406,
MSTP_NR
};
@@ -280,7 +377,18 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP200] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
[MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
+ [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */
[MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
+ [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */
+ [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
+ [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
+ [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */
+ [MSTP309] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 9, 0), /* GEther */
+
+ [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */
+ [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */
+ [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */
+ [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */
};
static struct clk_lookup lookups[] = {
@@ -299,6 +407,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("pllc0_clk", &pllc0_clk),
CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
+ CLKDEV_CON_ID("usb24s", &usb24s_clk),
/* DIV4 clocks */
CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
@@ -334,7 +443,22 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]),
CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]),
+ CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]),
CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]),
+ CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]),
+ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
+ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
+ CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]),
+ CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP309]),
+
+ CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]),
+
+ /* ICK */
+ CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]),
+ CLKDEV_ICK_ID("func", "renesas_usbhs", &mstp_clks[MSTP407]),
+ CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]),
+ CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]),
+ CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk),
};
void __init r8a7740_clock_init(u8 md_ck)
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index c85e6ecda606..ff5f12fd742f 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -3,6 +3,8 @@
extern void shmobile_earlytimer_init(void);
extern struct sys_timer shmobile_timer;
+extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
+ unsigned int mult, unsigned int div);
struct twd_local_timer;
extern void shmobile_setup_console(void);
extern void shmobile_secondary_vector(void);
diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h
new file mode 100644
index 000000000000..e6b0c1bf4b7e
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/emev2.h
@@ -0,0 +1,19 @@
+#ifndef __ASM_EMEV2_H__
+#define __ASM_EMEV2_H__
+
+extern void emev2_map_io(void);
+extern void emev2_init_irq(void);
+extern void emev2_add_early_devices(void);
+extern void emev2_add_standard_devices(void);
+extern void emev2_clock_init(void);
+extern void emev2_set_boot_vector(unsigned long value);
+extern unsigned int emev2_get_core_count(void);
+extern int emev2_platform_cpu_kill(unsigned int cpu);
+extern void emev2_secondary_init(unsigned int cpu);
+extern int emev2_boot_secondary(unsigned int cpu);
+extern void emev2_smp_prepare_cpus(void);
+
+#define EMEV2_GPIO_BASE 200
+#define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n))
+
+#endif /* __ASM_EMEV2_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/intc.h b/arch/arm/mach-shmobile/include/mach/intc.h
index 8b22258c8caa..a5603c76cfe0 100644
--- a/arch/arm/mach-shmobile/include/mach/intc.h
+++ b/arch/arm/mach-shmobile/include/mach/intc.h
@@ -142,6 +142,50 @@ static struct intc_desc p ## _desc __initdata = { \
p ## _sense_registers, p ## _ack_registers) \
}
+#define INTC_IRQ_PINS_16H(p, base, vect, str) \
+ \
+static struct resource p ## _resources[] __initdata = { \
+ [0] = { \
+ .start = base, \
+ .end = base + 0x64, \
+ .flags = IORESOURCE_MEM, \
+ }, \
+}; \
+ \
+enum { \
+ p ## _UNUSED = 0, \
+ INTC_IRQ_PINS_ENUM_16H(p), \
+}; \
+ \
+static struct intc_vect p ## _vectors[] __initdata = { \
+ INTC_IRQ_PINS_VECT_16H(p, vect), \
+}; \
+ \
+static struct intc_mask_reg p ## _mask_registers[] __initdata = { \
+ INTC_IRQ_PINS_MASK_16H(p, base), \
+}; \
+ \
+static struct intc_prio_reg p ## _prio_registers[] __initdata = { \
+ INTC_IRQ_PINS_PRIO_16H(p, base), \
+}; \
+ \
+static struct intc_sense_reg p ## _sense_registers[] __initdata = { \
+ INTC_IRQ_PINS_SENSE_16H(p, base), \
+}; \
+ \
+static struct intc_mask_reg p ## _ack_registers[] __initdata = { \
+ INTC_IRQ_PINS_ACK_16H(p, base), \
+}; \
+ \
+static struct intc_desc p ## _desc __initdata = { \
+ .name = str, \
+ .resource = p ## _resources, \
+ .num_resources = ARRAY_SIZE(p ## _resources), \
+ .hw = INTC_HW_DESC(p ## _vectors, NULL, \
+ p ## _mask_registers, p ## _prio_registers, \
+ p ## _sense_registers, p ## _ack_registers) \
+}
+
#define INTC_IRQ_PINS_32(p, base, vect, str) \
\
static struct resource p ## _resources[] __initdata = { \
diff --git a/arch/arm/mach-shmobile/include/mach/irqs.h b/arch/arm/mach-shmobile/include/mach/irqs.h
index 4e686cc201fc..06a5da3c3050 100644
--- a/arch/arm/mach-shmobile/include/mach/irqs.h
+++ b/arch/arm/mach-shmobile/include/mach/irqs.h
@@ -7,7 +7,7 @@
#define gic_spi(nr) ((nr) + 32)
/* INTCS */
-#define INTCS_VECT_BASE 0x2200
+#define INTCS_VECT_BASE 0x3400
#define INTCS_VECT(n, vect) INTC_VECT((n), INTCS_VECT_BASE + (vect))
#define intcs_evt2irq(evt) evt2irq(INTCS_VECT_BASE + (evt))
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index 8254ab86f6cd..915d0093da08 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -457,6 +457,8 @@ enum {
SHDMA_SLAVE_SDHI1_TX,
SHDMA_SLAVE_SDHI2_RX,
SHDMA_SLAVE_SDHI2_TX,
+ SHDMA_SLAVE_FSIA_RX,
+ SHDMA_SLAVE_FSIA_TX,
SHDMA_SLAVE_MMCIF_RX,
SHDMA_SLAVE_MMCIF_TX,
SHDMA_SLAVE_USB0_TX,
diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h
index cad57578ceed..398e2c10913b 100644
--- a/arch/arm/mach-shmobile/include/mach/sh73a0.h
+++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h
@@ -482,6 +482,9 @@ enum {
GPIO_FN_FSIAILR_PU,
GPIO_FN_FSIAIBT_PU,
GPIO_FN_FSIAISLD_PU,
+
+ /* end of GPIO */
+ GPIO_NR,
};
/* DMA slave IDs */
@@ -515,8 +518,36 @@ enum {
SHDMA_SLAVE_MMCIF_RX,
};
-/* PINT interrupts are located at Linux IRQ 800 and up */
-#define SH73A0_PINT0_IRQ(irq) ((irq) + 800)
-#define SH73A0_PINT1_IRQ(irq) ((irq) + 832)
+/*
+ * SH73A0 IRQ LOCATION TABLE
+ *
+ * 416 -----------------------------------------
+ * IRQ0-IRQ15
+ * 431 -----------------------------------------
+ * ...
+ * 448 -----------------------------------------
+ * sh73a0-intcs
+ * sh73a0-intca-irq-pins
+ * 680 -----------------------------------------
+ * ...
+ * 700 -----------------------------------------
+ * sh73a0-pint0
+ * 731 -----------------------------------------
+ * 732 -----------------------------------------
+ * sh73a0-pint1
+ * 739 -----------------------------------------
+ * ...
+ * 800 -----------------------------------------
+ * IRQ16-IRQ31
+ * 815 -----------------------------------------
+ * ...
+ * 928 -----------------------------------------
+ * sh73a0-intca-irq-pins
+ * 943 -----------------------------------------
+ */
+
+/* PINT interrupts are located at Linux IRQ 700 and up */
+#define SH73A0_PINT0_IRQ(irq) ((irq) + 700)
+#define SH73A0_PINT1_IRQ(irq) ((irq) + 732)
#endif /* __ASM_SH73A0_H__ */
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c
index 6447e0af52d4..2587a22842f2 100644
--- a/arch/arm/mach-shmobile/intc-sh7372.c
+++ b/arch/arm/mach-shmobile/intc-sh7372.c
@@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/sh_intc.h>
@@ -305,14 +306,16 @@ static DECLARE_INTC_DESC(intca_desc, "sh7372-intca",
intca_mask_registers, intca_prio_registers,
NULL);
-INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
- INTC_VECT, "sh7372-intca-irq-pins");
+INTC_IRQ_PINS_16(intca_irq_pins_lo, 0xe6900000,
+ INTC_VECT, "sh7372-intca-irq-lo");
+
+INTC_IRQ_PINS_16H(intca_irq_pins_hi, 0xe6900000,
+ INTC_VECT, "sh7372-intca-irq-hi");
+
enum {
UNUSED_INTCS = 0,
ENABLED_INTCS,
- INTCS,
-
/* interrupt sources INTCS */
/* IRQ0S - IRQ31S */
@@ -426,8 +429,6 @@ static struct intc_vect intcs_vectors[] = {
INTCS_VECT(CPORTS2R, 0x1a20),
/* CEC */
INTCS_VECT(JPU6E, 0x1a80),
-
- INTC_VECT(INTCS, 0xf80),
};
static struct intc_group intcs_groups[] __initdata = {
@@ -490,9 +491,6 @@ static struct intc_mask_reg intcs_mask_registers[] = {
{ 0xffd5019c, 0xffd501dc, 8, /* IMR7SA3 / IMCR7SA3 */
{ MFIS2_INTCS, CPORTS2R, 0, 0,
JPU6E, 0, 0, 0 } },
- { 0xffd20104, 0, 16, /* INTAMASK */
- { 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, INTCS } },
};
/* Priority is needed for INTCA to receive the INTCS interrupt */
@@ -557,18 +555,30 @@ static void __iomem *intcs_ffd5;
void __init sh7372_init_irq(void)
{
void __iomem *intevtsa;
+ int n;
intcs_ffd2 = ioremap_nocache(0xffd20000, PAGE_SIZE);
intevtsa = intcs_ffd2 + 0x100;
intcs_ffd5 = ioremap_nocache(0xffd50000, PAGE_SIZE);
register_intc_controller(&intca_desc);
- register_intc_controller(&intca_irq_pins_desc);
+ register_intc_controller(&intca_irq_pins_lo_desc);
+ register_intc_controller(&intca_irq_pins_hi_desc);
register_intc_controller(&intcs_desc);
+ /* setup dummy cascade chip for INTCS */
+ n = evt2irq(0xf80);
+ irq_alloc_desc_at(n, numa_node_id());
+ irq_set_chip_and_handler_name(n, &dummy_irq_chip,
+ handle_level_irq, "level");
+ set_irq_flags(n, IRQF_VALID); /* yuck */
+
/* demux using INTEVTSA */
- irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa);
- irq_set_chained_handler(evt2irq(0xf80), intcs_demux);
+ irq_set_handler_data(n, (void *)intevtsa);
+ irq_set_chained_handler(n, intcs_demux);
+
+ /* unmask INTCS in INTAMASK */
+ iowrite16(0, intcs_ffd2 + 0x104);
}
static unsigned short ffd2[0x200];
diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c
index a4fff6950b03..670fe1869dbc 100644
--- a/arch/arm/mach-shmobile/pfc-r8a7740.c
+++ b/arch/arm/mach-shmobile/pfc-r8a7740.c
@@ -22,6 +22,7 @@
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <mach/r8a7740.h>
+#include <mach/irqs.h>
#define CPU_ALL_PORT(fn, pfx, sfx) \
PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx), \
@@ -2527,6 +2528,41 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
{ },
};
+static struct pinmux_irq pinmux_irqs[] = {
+ PINMUX_IRQ(evt2irq(0x0200), PORT2_FN0, PORT13_FN0), /* IRQ0A */
+ PINMUX_IRQ(evt2irq(0x0220), PORT20_FN0), /* IRQ1A */
+ PINMUX_IRQ(evt2irq(0x0240), PORT11_FN0, PORT12_FN0), /* IRQ2A */
+ PINMUX_IRQ(evt2irq(0x0260), PORT10_FN0, PORT14_FN0), /* IRQ3A */
+ PINMUX_IRQ(evt2irq(0x0280), PORT15_FN0, PORT172_FN0), /* IRQ4A */
+ PINMUX_IRQ(evt2irq(0x02A0), PORT0_FN0, PORT1_FN0), /* IRQ5A */
+ PINMUX_IRQ(evt2irq(0x02C0), PORT121_FN0, PORT173_FN0), /* IRQ6A */
+ PINMUX_IRQ(evt2irq(0x02E0), PORT120_FN0, PORT209_FN0), /* IRQ7A */
+ PINMUX_IRQ(evt2irq(0x0300), PORT119_FN0), /* IRQ8A */
+ PINMUX_IRQ(evt2irq(0x0320), PORT118_FN0, PORT210_FN0), /* IRQ9A */
+ PINMUX_IRQ(evt2irq(0x0340), PORT19_FN0), /* IRQ10A */
+ PINMUX_IRQ(evt2irq(0x0360), PORT104_FN0), /* IRQ11A */
+ PINMUX_IRQ(evt2irq(0x0380), PORT42_FN0, PORT97_FN0), /* IRQ12A */
+ PINMUX_IRQ(evt2irq(0x03A0), PORT64_FN0, PORT98_FN0), /* IRQ13A */
+ PINMUX_IRQ(evt2irq(0x03C0), PORT63_FN0, PORT99_FN0), /* IRQ14A */
+ PINMUX_IRQ(evt2irq(0x03E0), PORT62_FN0, PORT100_FN0), /* IRQ15A */
+ PINMUX_IRQ(evt2irq(0x3200), PORT68_FN0, PORT211_FN0), /* IRQ16A */
+ PINMUX_IRQ(evt2irq(0x3220), PORT69_FN0), /* IRQ17A */
+ PINMUX_IRQ(evt2irq(0x3240), PORT70_FN0), /* IRQ18A */
+ PINMUX_IRQ(evt2irq(0x3260), PORT71_FN0), /* IRQ19A */
+ PINMUX_IRQ(evt2irq(0x3280), PORT67_FN0), /* IRQ20A */
+ PINMUX_IRQ(evt2irq(0x32A0), PORT202_FN0), /* IRQ21A */
+ PINMUX_IRQ(evt2irq(0x32C0), PORT95_FN0), /* IRQ22A */
+ PINMUX_IRQ(evt2irq(0x32E0), PORT96_FN0), /* IRQ23A */
+ PINMUX_IRQ(evt2irq(0x3300), PORT180_FN0), /* IRQ24A */
+ PINMUX_IRQ(evt2irq(0x3320), PORT38_FN0), /* IRQ25A */
+ PINMUX_IRQ(evt2irq(0x3340), PORT58_FN0, PORT81_FN0), /* IRQ26A */
+ PINMUX_IRQ(evt2irq(0x3360), PORT57_FN0, PORT168_FN0), /* IRQ27A */
+ PINMUX_IRQ(evt2irq(0x3380), PORT56_FN0, PORT169_FN0), /* IRQ28A */
+ PINMUX_IRQ(evt2irq(0x33A0), PORT50_FN0, PORT170_FN0), /* IRQ29A */
+ PINMUX_IRQ(evt2irq(0x33C0), PORT49_FN0, PORT171_FN0), /* IRQ30A */
+ PINMUX_IRQ(evt2irq(0x33E0), PORT41_FN0, PORT167_FN0), /* IRQ31A */
+};
+
static struct pinmux_info r8a7740_pinmux_info = {
.name = "r8a7740_pfc",
.reserved_id = PINMUX_RESERVED,
@@ -2554,6 +2590,9 @@ static struct pinmux_info r8a7740_pinmux_info = {
.gpio_data = pinmux_data,
.gpio_data_size = ARRAY_SIZE(pinmux_data),
+
+ .gpio_irq = pinmux_irqs,
+ .gpio_irq_size = ARRAY_SIZE(pinmux_irqs),
};
void r8a7740_pinmux_init(void)
diff --git a/arch/arm/mach-shmobile/pfc-sh73a0.c b/arch/arm/mach-shmobile/pfc-sh73a0.c
index e05634ce2e0d..4a547b803268 100644
--- a/arch/arm/mach-shmobile/pfc-sh73a0.c
+++ b/arch/arm/mach-shmobile/pfc-sh73a0.c
@@ -829,14 +829,14 @@ static pinmux_enum_t pinmux_data[] = {
PINMUX_DATA(PORT27_I2C_SCL2_MARK, PORT27_FN2, MSEL2CR_MSEL17_0,
MSEL2CR_MSEL16_1), \
PINMUX_DATA(PORT27_I2C_SCL3_MARK, PORT27_FN3, MSEL2CR_MSEL19_0,
- MSEL2CR_MSEL18_0), \
+ MSEL2CR_MSEL18_1), \
PINMUX_DATA(MFG0_OUT1_MARK, PORT27_FN4), \
PINMUX_DATA(PORT27_IROUT_MARK, PORT27_FN7),
PINMUX_DATA(XDVFS2_MARK, PORT28_FN1), \
PINMUX_DATA(PORT28_I2C_SDA2_MARK, PORT28_FN2, MSEL2CR_MSEL17_0,
MSEL2CR_MSEL16_1), \
PINMUX_DATA(PORT28_I2C_SDA3_MARK, PORT28_FN3, MSEL2CR_MSEL19_0,
- MSEL2CR_MSEL18_0), \
+ MSEL2CR_MSEL18_1), \
PINMUX_DATA(PORT28_TPU1TO1_MARK, PORT28_FN7),
PINMUX_DATA(SIM_RST_MARK, PORT29_FN1), \
PINMUX_DATA(PORT29_TPU1TO1_MARK, PORT29_FN4),
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index 45fa3924c6a1..bacdd667e3b1 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -16,12 +16,16 @@
#include <linux/device.h>
#include <linux/smp.h>
#include <linux/io.h>
+#include <linux/of.h>
#include <asm/hardware/gic.h>
#include <asm/mach-types.h>
#include <mach/common.h>
+#include <mach/emev2.h>
-#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2())
+#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || \
+ of_machine_is_compatible("renesas,sh73a0"))
#define is_r8a7779() machine_is_marzen()
+#define is_emev2() of_machine_is_compatible("renesas,emev2")
static unsigned int __init shmobile_smp_get_core_count(void)
{
@@ -31,6 +35,9 @@ static unsigned int __init shmobile_smp_get_core_count(void)
if (is_r8a7779())
return r8a7779_get_core_count();
+ if (is_emev2())
+ return emev2_get_core_count();
+
return 1;
}
@@ -41,6 +48,9 @@ static void __init shmobile_smp_prepare_cpus(void)
if (is_r8a7779())
r8a7779_smp_prepare_cpus();
+
+ if (is_emev2())
+ emev2_smp_prepare_cpus();
}
int shmobile_platform_cpu_kill(unsigned int cpu)
@@ -48,6 +58,9 @@ int shmobile_platform_cpu_kill(unsigned int cpu)
if (is_r8a7779())
return r8a7779_platform_cpu_kill(cpu);
+ if (is_emev2())
+ return emev2_platform_cpu_kill(cpu);
+
return 1;
}
@@ -60,6 +73,9 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
if (is_r8a7779())
r8a7779_secondary_init(cpu);
+
+ if (is_emev2())
+ emev2_secondary_init(cpu);
}
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
@@ -70,6 +86,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
if (is_r8a7779())
return r8a7779_boot_secondary(cpu);
+ if (is_emev2())
+ return emev2_boot_secondary(cpu);
+
return -ENOSYS;
}
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
new file mode 100644
index 000000000000..dae9aa68bb09
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-emev2.c
@@ -0,0 +1,452 @@
+/*
+ * Emma Mobile EV2 processor support
+ *
+ * Copyright (C) 2012 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/gpio-em.h>
+#include <linux/of_platform.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/of_irq.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/emev2.h>
+#include <mach/irqs.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/hardware/gic.h>
+
+static struct map_desc emev2_io_desc[] __initdata = {
+#ifdef CONFIG_SMP
+ /* 128K entity map for 0xe0100000 (SMU) */
+ {
+ .virtual = 0xe0100000,
+ .pfn = __phys_to_pfn(0xe0100000),
+ .length = SZ_128K,
+ .type = MT_DEVICE
+ },
+ /* 2M mapping for SCU + L2 controller */
+ {
+ .virtual = 0xf0000000,
+ .pfn = __phys_to_pfn(0x1e000000),
+ .length = SZ_2M,
+ .type = MT_DEVICE
+ },
+#endif
+};
+
+void __init emev2_map_io(void)
+{
+ iotable_init(emev2_io_desc, ARRAY_SIZE(emev2_io_desc));
+}
+
+/* UART */
+static struct resource uart0_resources[] = {
+ [0] = {
+ .start = 0xe1020000,
+ .end = 0xe1020037,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 40,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device uart0_device = {
+ .name = "serial8250-em",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(uart0_resources),
+ .resource = uart0_resources,
+};
+
+static struct resource uart1_resources[] = {
+ [0] = {
+ .start = 0xe1030000,
+ .end = 0xe1030037,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 41,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device uart1_device = {
+ .name = "serial8250-em",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(uart1_resources),
+ .resource = uart1_resources,
+};
+
+static struct resource uart2_resources[] = {
+ [0] = {
+ .start = 0xe1040000,
+ .end = 0xe1040037,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 42,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device uart2_device = {
+ .name = "serial8250-em",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(uart2_resources),
+ .resource = uart2_resources,
+};
+
+static struct resource uart3_resources[] = {
+ [0] = {
+ .start = 0xe1050000,
+ .end = 0xe1050037,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 43,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device uart3_device = {
+ .name = "serial8250-em",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(uart3_resources),
+ .resource = uart3_resources,
+};
+
+/* STI */
+static struct resource sti_resources[] = {
+ [0] = {
+ .name = "STI",
+ .start = 0xe0180000,
+ .end = 0xe0180053,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 157,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sti_device = {
+ .name = "em_sti",
+ .id = 0,
+ .resource = sti_resources,
+ .num_resources = ARRAY_SIZE(sti_resources),
+};
+
+
+/* GIO */
+static struct gpio_em_config gio0_config = {
+ .gpio_base = 0,
+ .irq_base = EMEV2_GPIO_IRQ(0),
+ .number_of_pins = 32,
+};
+
+static struct resource gio0_resources[] = {
+ [0] = {
+ .name = "GIO_000",
+ .start = 0xe0050000,
+ .end = 0xe005002b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "GIO_000",
+ .start = 0xe0050040,
+ .end = 0xe005005f,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 99,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = 100,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device gio0_device = {
+ .name = "em_gio",
+ .id = 0,
+ .resource = gio0_resources,
+ .num_resources = ARRAY_SIZE(gio0_resources),
+ .dev = {
+ .platform_data = &gio0_config,
+ },
+};
+
+static struct gpio_em_config gio1_config = {
+ .gpio_base = 32,
+ .irq_base = EMEV2_GPIO_IRQ(32),
+ .number_of_pins = 32,
+};
+
+static struct resource gio1_resources[] = {
+ [0] = {
+ .name = "GIO_032",
+ .start = 0xe0050080,
+ .end = 0xe00500ab,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "GIO_032",
+ .start = 0xe00500c0,
+ .end = 0xe00500df,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 101,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = 102,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device gio1_device = {
+ .name = "em_gio",
+ .id = 1,
+ .resource = gio1_resources,
+ .num_resources = ARRAY_SIZE(gio1_resources),
+ .dev = {
+ .platform_data = &gio1_config,
+ },
+};
+
+static struct gpio_em_config gio2_config = {
+ .gpio_base = 64,
+ .irq_base = EMEV2_GPIO_IRQ(64),
+ .number_of_pins = 32,
+};
+
+static struct resource gio2_resources[] = {
+ [0] = {
+ .name = "GIO_064",
+ .start = 0xe0050100,
+ .end = 0xe005012b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "GIO_064",
+ .start = 0xe0050140,
+ .end = 0xe005015f,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 103,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = 104,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device gio2_device = {
+ .name = "em_gio",
+ .id = 2,
+ .resource = gio2_resources,
+ .num_resources = ARRAY_SIZE(gio2_resources),
+ .dev = {
+ .platform_data = &gio2_config,
+ },
+};
+
+static struct gpio_em_config gio3_config = {
+ .gpio_base = 96,
+ .irq_base = EMEV2_GPIO_IRQ(96),
+ .number_of_pins = 32,
+};
+
+static struct resource gio3_resources[] = {
+ [0] = {
+ .name = "GIO_096",
+ .start = 0xe0050100,
+ .end = 0xe005012b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "GIO_096",
+ .start = 0xe0050140,
+ .end = 0xe005015f,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 105,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = 106,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device gio3_device = {
+ .name = "em_gio",
+ .id = 3,
+ .resource = gio3_resources,
+ .num_resources = ARRAY_SIZE(gio3_resources),
+ .dev = {
+ .platform_data = &gio3_config,
+ },
+};
+
+static struct gpio_em_config gio4_config = {
+ .gpio_base = 128,
+ .irq_base = EMEV2_GPIO_IRQ(128),
+ .number_of_pins = 31,
+};
+
+static struct resource gio4_resources[] = {
+ [0] = {
+ .name = "GIO_128",
+ .start = 0xe0050200,
+ .end = 0xe005022b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "GIO_128",
+ .start = 0xe0050240,
+ .end = 0xe005025f,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 107,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = 108,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device gio4_device = {
+ .name = "em_gio",
+ .id = 4,
+ .resource = gio4_resources,
+ .num_resources = ARRAY_SIZE(gio4_resources),
+ .dev = {
+ .platform_data = &gio4_config,
+ },
+};
+
+static struct platform_device *emev2_early_devices[] __initdata = {
+ &uart0_device,
+ &uart1_device,
+ &uart2_device,
+ &uart3_device,
+};
+
+static struct platform_device *emev2_late_devices[] __initdata = {
+ &sti_device,
+ &gio0_device,
+ &gio1_device,
+ &gio2_device,
+ &gio3_device,
+ &gio4_device,
+};
+
+void __init emev2_add_standard_devices(void)
+{
+ emev2_clock_init();
+
+ platform_add_devices(emev2_early_devices,
+ ARRAY_SIZE(emev2_early_devices));
+
+ platform_add_devices(emev2_late_devices,
+ ARRAY_SIZE(emev2_late_devices));
+}
+
+void __init emev2_init_delay(void)
+{
+ shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */
+}
+
+void __init emev2_add_early_devices(void)
+{
+ emev2_init_delay();
+
+ early_platform_add_devices(emev2_early_devices,
+ ARRAY_SIZE(emev2_early_devices));
+
+ /* setup early console here as well */
+ shmobile_setup_console();
+}
+
+void __init emev2_init_irq(void)
+{
+ void __iomem *gic_dist_base;
+ void __iomem *gic_cpu_base;
+
+ /* Static mappings, never released */
+ gic_dist_base = ioremap(0xe0028000, PAGE_SIZE);
+ gic_cpu_base = ioremap(0xe0020000, PAGE_SIZE);
+ BUG_ON(!gic_dist_base || !gic_cpu_base);
+
+ /* Use GIC to handle interrupts */
+ gic_init(0, 29, gic_dist_base, gic_cpu_base);
+}
+
+#ifdef CONFIG_USE_OF
+static const struct of_dev_auxdata emev2_auxdata_lookup[] __initconst = {
+ { }
+};
+
+void __init emev2_add_standard_devices_dt(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table,
+ emev2_auxdata_lookup, NULL);
+}
+
+static const struct of_device_id emev2_dt_irq_match[] = {
+ { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+ {},
+};
+
+static const char *emev2_boards_compat_dt[] __initdata = {
+ "renesas,emev2",
+ NULL,
+};
+
+void __init emev2_init_irq_dt(void)
+{
+ of_irq_init(emev2_dt_irq_match);
+}
+
+DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
+ .init_early = emev2_init_delay,
+ .nr_irqs = NR_IRQS_LEGACY,
+ .init_irq = emev2_init_irq_dt,
+ .handle_irq = gic_handle_irq,
+ .init_machine = emev2_add_standard_devices_dt,
+ .timer = &shmobile_timer,
+ .dt_compat = emev2_boards_compat_dt,
+MACHINE_END
+
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 14edb5cffa7f..ec4eb49c1693 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
@@ -60,6 +61,12 @@ static struct map_desc r8a7740_io_desc[] __initdata = {
void __init r8a7740_map_io(void)
{
iotable_init(r8a7740_io_desc, ARRAY_SIZE(r8a7740_io_desc));
+
+ /*
+ * DMA memory at 0xff200000 - 0xffdfffff. The default 2MB size isn't
+ * enough to allocate the frame buffer memory.
+ */
+ init_consistent_dma_size(12 << 20);
}
/* SCIFA0 */
@@ -350,19 +357,19 @@ static void r8a7740_i2c_workaround(struct platform_device *pdev)
i2c_write(reg, ICSTART, i2c_read(reg, ICSTART) | 0x10);
i2c_read(reg, ICSTART); /* dummy read */
- mdelay(100);
+ udelay(10);
i2c_write(reg, ICCR, 0x01);
- i2c_read(reg, ICCR);
i2c_write(reg, ICSTART, 0x00);
- i2c_read(reg, ICSTART);
+
+ udelay(10);
i2c_write(reg, ICCR, 0x10);
- mdelay(100);
+ udelay(10);
i2c_write(reg, ICCR, 0x00);
- mdelay(100);
+ udelay(10);
i2c_write(reg, ICCR, 0x10);
- mdelay(100);
+ udelay(10);
iounmap(reg);
}
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 2fe8f83ca124..6a4bd582c028 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -22,6 +22,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
#include <linux/uio_driver.h>
#include <linux/delay.h>
#include <linux/input.h>
@@ -461,6 +462,16 @@ static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = {
.chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xce,
}, {
+ .slave_id = SHDMA_SLAVE_FSIA_TX,
+ .addr = 0xfe1f0024,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xb1,
+ }, {
+ .slave_id = SHDMA_SLAVE_FSIA_RX,
+ .addr = 0xfe1f0020,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xb2,
+ }, {
.slave_id = SHDMA_SLAVE_MMCIF_TX,
.addr = 0xe6bd0034,
.chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
@@ -1092,3 +1103,50 @@ void __init sh7372_add_early_devices(void)
/* override timer setup with soc-specific code */
shmobile_timer.init = sh7372_earlytimer_init;
}
+
+#ifdef CONFIG_USE_OF
+
+void __init sh7372_add_early_devices_dt(void)
+{
+ shmobile_setup_delay(800, 1, 3); /* Cortex-A8 @ 800MHz */
+
+ early_platform_add_devices(sh7372_early_devices,
+ ARRAY_SIZE(sh7372_early_devices));
+
+ /* setup early console here as well */
+ shmobile_setup_console();
+}
+
+static const struct of_dev_auxdata sh7372_auxdata_lookup[] __initconst = {
+ { }
+};
+
+void __init sh7372_add_standard_devices_dt(void)
+{
+ /* clocks are setup late during boot in the case of DT */
+ sh7372_clock_init();
+
+ platform_add_devices(sh7372_early_devices,
+ ARRAY_SIZE(sh7372_early_devices));
+
+ of_platform_populate(NULL, of_default_bus_match_table,
+ sh7372_auxdata_lookup, NULL);
+}
+
+static const char *sh7372_boards_compat_dt[] __initdata = {
+ "renesas,sh7372",
+ NULL,
+};
+
+DT_MACHINE_START(SH7372_DT, "Generic SH7372 (Flattened Device Tree)")
+ .map_io = sh7372_map_io,
+ .init_early = sh7372_add_early_devices_dt,
+ .nr_irqs = NR_IRQS_LEGACY,
+ .init_irq = sh7372_init_irq,
+ .handle_irq = shmobile_handle_irq_intc,
+ .init_machine = sh7372_add_standard_devices_dt,
+ .timer = &shmobile_timer,
+ .dt_compat = sh7372_boards_compat_dt,
+MACHINE_END
+
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
new file mode 100644
index 000000000000..6a35c4a31e6c
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-emev2.c
@@ -0,0 +1,97 @@
+/*
+ * SMP support for Emma Mobile EV2
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2012 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <mach/common.h>
+#include <mach/emev2.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+#include <asm/hardware/gic.h>
+#include <asm/cacheflush.h>
+
+#define EMEV2_SCU_BASE 0x1e000000
+
+static DEFINE_SPINLOCK(scu_lock);
+static void __iomem *scu_base;
+
+static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
+{
+ unsigned long tmp;
+
+ /* we assume this code is running on a different cpu
+ * than the one that is changing coherency setting */
+ spin_lock(&scu_lock);
+ tmp = readl(scu_base + 8);
+ tmp &= ~clr;
+ tmp |= set;
+ writel(tmp, scu_base + 8);
+ spin_unlock(&scu_lock);
+
+}
+
+unsigned int __init emev2_get_core_count(void)
+{
+ if (!scu_base) {
+ scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
+ emev2_clock_init(); /* need ioremapped SMU */
+ }
+
+ WARN_ON_ONCE(!scu_base);
+
+ return scu_base ? scu_get_core_count(scu_base) : 1;
+}
+
+int emev2_platform_cpu_kill(unsigned int cpu)
+{
+ return 0; /* not supported yet */
+}
+
+void __cpuinit emev2_secondary_init(unsigned int cpu)
+{
+ gic_secondary_init(0);
+}
+
+int __cpuinit emev2_boot_secondary(unsigned int cpu)
+{
+ cpu = cpu_logical_map(cpu);
+
+ /* enable cache coherency */
+ modify_scu_cpu_psr(0, 3 << (cpu * 8));
+
+ /* Tell ROM loader about our vector (in headsmp.S) */
+ emev2_set_boot_vector(__pa(shmobile_secondary_vector));
+
+ gic_raise_softirq(cpumask_of(cpu), 1);
+ return 0;
+}
+
+void __init emev2_smp_prepare_cpus(void)
+{
+ int cpu = cpu_logical_map(0);
+
+ scu_enable(scu_base);
+
+ /* enable cache coherency on CPU0 */
+ modify_scu_cpu_psr(0, 3 << (cpu * 8));
+}
diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
index 8b79e7917a23..a68919727e24 100644
--- a/arch/arm/mach-shmobile/timer.c
+++ b/arch/arm/mach-shmobile/timer.c
@@ -19,9 +19,27 @@
*
*/
#include <linux/platform_device.h>
+#include <linux/delay.h>
#include <asm/mach/time.h>
#include <asm/smp_twd.h>
+void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,
+ unsigned int mult, unsigned int div)
+{
+ /* calculate a worst-case loops-per-jiffy value
+ * based on maximum cpu core mhz setting and the
+ * __delay() implementation in arch/arm/lib/delay.S
+ *
+ * this will result in a longer delay than expected
+ * when the cpu core runs on lower frequencies.
+ */
+
+ unsigned int value = (1000000 * mult) / (HZ * div);
+
+ if (!preset_lpj)
+ preset_lpj = max_cpu_core_mhz * value;
+}
+
static void __init shmobile_late_time_init(void)
{
/*
diff --git a/arch/arm/mach-spear3xx/Kconfig b/arch/arm/mach-spear3xx/Kconfig
index 2cee6b0de371..8bd37291fa4f 100644
--- a/arch/arm/mach-spear3xx/Kconfig
+++ b/arch/arm/mach-spear3xx/Kconfig
@@ -5,39 +5,22 @@
if ARCH_SPEAR3XX
menu "SPEAr3xx Implementations"
-config BOARD_SPEAR300_EVB
- bool "SPEAr300 Evaluation Board"
- select MACH_SPEAR300
- help
- Supports ST SPEAr300 Evaluation Board
-
-config BOARD_SPEAR310_EVB
- bool "SPEAr310 Evaluation Board"
- select MACH_SPEAR310
- help
- Supports ST SPEAr310 Evaluation Board
-
-config BOARD_SPEAR320_EVB
- bool "SPEAr320 Evaluation Board"
- select MACH_SPEAR320
- help
- Supports ST SPEAr320 Evaluation Board
-
-endmenu
-
config MACH_SPEAR300
- bool "SPEAr300"
+ bool "SPEAr300 Machine support with Device Tree"
+ select PINCTRL_SPEAR300
help
- Supports ST SPEAr300 Machine
+ Supports ST SPEAr300 machine configured via the device-tree
config MACH_SPEAR310
- bool "SPEAr310"
+ bool "SPEAr310 Machine support with Device Tree"
+ select PINCTRL_SPEAR310
help
- Supports ST SPEAr310 Machine
+ Supports ST SPEAr310 machine configured via the device-tree
config MACH_SPEAR320
- bool "SPEAr320"
+ bool "SPEAr320 Machine support with Device Tree"
+ select PINCTRL_SPEAR320
help
- Supports ST SPEAr320 Machine
-
+ Supports ST SPEAr320 machine configured via the device-tree
+endmenu
endif #ARCH_SPEAR3XX
diff --git a/arch/arm/mach-spear3xx/Makefile b/arch/arm/mach-spear3xx/Makefile
index b24862489704..17b5d83cf2d5 100644
--- a/arch/arm/mach-spear3xx/Makefile
+++ b/arch/arm/mach-spear3xx/Makefile
@@ -3,24 +3,13 @@
#
# common files
-obj-y += spear3xx.o clock.o
+obj-$(CONFIG_ARCH_SPEAR3XX) += spear3xx.o clock.o
# spear300 specific files
obj-$(CONFIG_MACH_SPEAR300) += spear300.o
-# spear300 boards files
-obj-$(CONFIG_BOARD_SPEAR300_EVB) += spear300_evb.o
-
-
# spear310 specific files
obj-$(CONFIG_MACH_SPEAR310) += spear310.o
-# spear310 boards files
-obj-$(CONFIG_BOARD_SPEAR310_EVB) += spear310_evb.o
-
-
# spear320 specific files
obj-$(CONFIG_MACH_SPEAR320) += spear320.o
-
-# spear320 boards files
-obj-$(CONFIG_BOARD_SPEAR320_EVB) += spear320_evb.o
diff --git a/arch/arm/mach-spear3xx/Makefile.boot b/arch/arm/mach-spear3xx/Makefile.boot
index 4674a4c221db..d93e2177e6ec 100644
--- a/arch/arm/mach-spear3xx/Makefile.boot
+++ b/arch/arm/mach-spear3xx/Makefile.boot
@@ -1,3 +1,7 @@
zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
+
+dtb-$(CONFIG_MACH_SPEAR300) += spear300-evb.dtb
+dtb-$(CONFIG_MACH_SPEAR310) += spear310-evb.dtb
+dtb-$(CONFIG_MACH_SPEAR320) += spear320-evb.dtb
diff --git a/arch/arm/mach-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c
index 6c4841f55223..cd6c11099083 100644
--- a/arch/arm/mach-spear3xx/clock.c
+++ b/arch/arm/mach-spear3xx/clock.c
@@ -11,12 +11,112 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/clkdev.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/of_platform.h>
#include <asm/mach-types.h>
#include <plat/clock.h>
#include <mach/misc_regs.h>
+#include <mach/spear.h>
+
+#define PLL1_CTR (MISC_BASE + 0x008)
+#define PLL1_FRQ (MISC_BASE + 0x00C)
+#define PLL1_MOD (MISC_BASE + 0x010)
+#define PLL2_CTR (MISC_BASE + 0x014)
+/* PLL_CTR register masks */
+#define PLL_ENABLE 2
+#define PLL_MODE_SHIFT 4
+#define PLL_MODE_MASK 0x3
+#define PLL_MODE_NORMAL 0
+#define PLL_MODE_FRACTION 1
+#define PLL_MODE_DITH_DSB 2
+#define PLL_MODE_DITH_SSB 3
+
+#define PLL2_FRQ (MISC_BASE + 0x018)
+/* PLL FRQ register masks */
+#define PLL_DIV_N_SHIFT 0
+#define PLL_DIV_N_MASK 0xFF
+#define PLL_DIV_P_SHIFT 8
+#define PLL_DIV_P_MASK 0x7
+#define PLL_NORM_FDBK_M_SHIFT 24
+#define PLL_NORM_FDBK_M_MASK 0xFF
+#define PLL_DITH_FDBK_M_SHIFT 16
+#define PLL_DITH_FDBK_M_MASK 0xFFFF
+
+#define PLL2_MOD (MISC_BASE + 0x01C)
+#define PLL_CLK_CFG (MISC_BASE + 0x020)
+#define CORE_CLK_CFG (MISC_BASE + 0x024)
+/* CORE CLK CFG register masks */
+#define PLL_HCLK_RATIO_SHIFT 10
+#define PLL_HCLK_RATIO_MASK 0x3
+#define HCLK_PCLK_RATIO_SHIFT 8
+#define HCLK_PCLK_RATIO_MASK 0x3
+
+#define PERIP_CLK_CFG (MISC_BASE + 0x028)
+/* PERIP_CLK_CFG register masks */
+#define UART_CLK_SHIFT 4
+#define UART_CLK_MASK 0x1
+#define FIRDA_CLK_SHIFT 5
+#define FIRDA_CLK_MASK 0x3
+#define GPT0_CLK_SHIFT 8
+#define GPT1_CLK_SHIFT 11
+#define GPT2_CLK_SHIFT 12
+#define GPT_CLK_MASK 0x1
+#define AUX_CLK_PLL3_VAL 0
+#define AUX_CLK_PLL1_VAL 1
+
+#define PERIP1_CLK_ENB (MISC_BASE + 0x02C)
+/* PERIP1_CLK_ENB register masks */
+#define UART_CLK_ENB 3
+#define SSP_CLK_ENB 5
+#define I2C_CLK_ENB 7
+#define JPEG_CLK_ENB 8
+#define FIRDA_CLK_ENB 10
+#define GPT1_CLK_ENB 11
+#define GPT2_CLK_ENB 12
+#define ADC_CLK_ENB 15
+#define RTC_CLK_ENB 17
+#define GPIO_CLK_ENB 18
+#define DMA_CLK_ENB 19
+#define SMI_CLK_ENB 21
+#define GMAC_CLK_ENB 23
+#define USBD_CLK_ENB 24
+#define USBH_CLK_ENB 25
+#define C3_CLK_ENB 31
+
+#define RAS_CLK_ENB (MISC_BASE + 0x034)
+
+#define PRSC1_CLK_CFG (MISC_BASE + 0x044)
+#define PRSC2_CLK_CFG (MISC_BASE + 0x048)
+#define PRSC3_CLK_CFG (MISC_BASE + 0x04C)
+/* gpt synthesizer register masks */
+#define GPT_MSCALE_SHIFT 0
+#define GPT_MSCALE_MASK 0xFFF
+#define GPT_NSCALE_SHIFT 12
+#define GPT_NSCALE_MASK 0xF
+
+#define AMEM_CLK_CFG (MISC_BASE + 0x050)
+#define EXPI_CLK_CFG (MISC_BASE + 0x054)
+#define CLCD_CLK_SYNT (MISC_BASE + 0x05C)
+#define FIRDA_CLK_SYNT (MISC_BASE + 0x060)
+#define UART_CLK_SYNT (MISC_BASE + 0x064)
+#define GMAC_CLK_SYNT (MISC_BASE + 0x068)
+#define RAS1_CLK_SYNT (MISC_BASE + 0x06C)
+#define RAS2_CLK_SYNT (MISC_BASE + 0x070)
+#define RAS3_CLK_SYNT (MISC_BASE + 0x074)
+#define RAS4_CLK_SYNT (MISC_BASE + 0x078)
+/* aux clk synthesiser register masks for irda to ras4 */
+#define AUX_SYNT_ENB 31
+#define AUX_EQ_SEL_SHIFT 30
+#define AUX_EQ_SEL_MASK 1
+#define AUX_EQ1_SEL 0
+#define AUX_EQ2_SEL 1
+#define AUX_XSCALE_SHIFT 16
+#define AUX_XSCALE_MASK 0xFFF
+#define AUX_YSCALE_SHIFT 0
+#define AUX_YSCALE_MASK 0xFFF
/* root clks */
/* 32 KHz oscillator clock */
@@ -411,6 +511,21 @@ static struct clk usbd_clk = {
.recalc = &follow_parent,
};
+/* clock derived from usbh clk */
+/* usbh0 clock */
+static struct clk usbh0_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &usbh_clk,
+ .recalc = &follow_parent,
+};
+
+/* usbh1 clock */
+static struct clk usbh1_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &usbh_clk,
+ .recalc = &follow_parent,
+};
+
/* clock derived from ahb clk */
/* apb masks structure */
static struct bus_clk_masks apb_masks = {
@@ -652,109 +767,126 @@ static struct clk pwm_clk = {
/* array of all spear 3xx clock lookups */
static struct clk_lookup spear_clk_lookups[] = {
- { .con_id = "apb_pclk", .clk = &dummy_apb_pclk},
+ CLKDEV_INIT(NULL, "apb_pclk", &dummy_apb_pclk),
/* root clks */
- { .con_id = "osc_32k_clk", .clk = &osc_32k_clk},
- { .con_id = "osc_24m_clk", .clk = &osc_24m_clk},
+ CLKDEV_INIT(NULL, "osc_32k_clk", &osc_32k_clk),
+ CLKDEV_INIT(NULL, "osc_24m_clk", &osc_24m_clk),
/* clock derived from 32 KHz osc clk */
- { .dev_id = "rtc-spear", .clk = &rtc_clk},
+ CLKDEV_INIT("fc900000.rtc", NULL, &rtc_clk),
/* clock derived from 24 MHz osc clk */
- { .con_id = "pll1_clk", .clk = &pll1_clk},
- { .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk},
- { .dev_id = "wdt", .clk = &wdt_clk},
+ CLKDEV_INIT(NULL, "pll1_clk", &pll1_clk),
+ CLKDEV_INIT(NULL, "pll3_48m_clk", &pll3_48m_clk),
+ CLKDEV_INIT("fc880000.wdt", NULL, &wdt_clk),
/* clock derived from pll1 clk */
- { .con_id = "cpu_clk", .clk = &cpu_clk},
- { .con_id = "ahb_clk", .clk = &ahb_clk},
- { .con_id = "uart_synth_clk", .clk = &uart_synth_clk},
- { .con_id = "firda_synth_clk", .clk = &firda_synth_clk},
- { .con_id = "gpt0_synth_clk", .clk = &gpt0_synth_clk},
- { .con_id = "gpt1_synth_clk", .clk = &gpt1_synth_clk},
- { .con_id = "gpt2_synth_clk", .clk = &gpt2_synth_clk},
- { .dev_id = "uart", .clk = &uart_clk},
- { .dev_id = "firda", .clk = &firda_clk},
- { .dev_id = "gpt0", .clk = &gpt0_clk},
- { .dev_id = "gpt1", .clk = &gpt1_clk},
- { .dev_id = "gpt2", .clk = &gpt2_clk},
+ CLKDEV_INIT(NULL, "cpu_clk", &cpu_clk),
+ CLKDEV_INIT(NULL, "ahb_clk", &ahb_clk),
+ CLKDEV_INIT(NULL, "uart_synth_clk", &uart_synth_clk),
+ CLKDEV_INIT(NULL, "firda_synth_clk", &firda_synth_clk),
+ CLKDEV_INIT(NULL, "gpt0_synth_clk", &gpt0_synth_clk),
+ CLKDEV_INIT(NULL, "gpt1_synth_clk", &gpt1_synth_clk),
+ CLKDEV_INIT(NULL, "gpt2_synth_clk", &gpt2_synth_clk),
+ CLKDEV_INIT("d0000000.serial", NULL, &uart_clk),
+ CLKDEV_INIT("firda", NULL, &firda_clk),
+ CLKDEV_INIT("gpt0", NULL, &gpt0_clk),
+ CLKDEV_INIT("gpt1", NULL, &gpt1_clk),
+ CLKDEV_INIT("gpt2", NULL, &gpt2_clk),
/* clock derived from pll3 clk */
- { .dev_id = "designware_udc", .clk = &usbd_clk},
- { .con_id = "usbh_clk", .clk = &usbh_clk},
+ CLKDEV_INIT("designware_udc", NULL, &usbd_clk),
+ CLKDEV_INIT(NULL, "usbh_clk", &usbh_clk),
+ /* clock derived from usbh clk */
+ CLKDEV_INIT(NULL, "usbh.0_clk", &usbh0_clk),
+ CLKDEV_INIT(NULL, "usbh.1_clk", &usbh1_clk),
/* clock derived from ahb clk */
- { .con_id = "apb_clk", .clk = &apb_clk},
- { .dev_id = "i2c_designware.0", .clk = &i2c_clk},
- { .dev_id = "dma", .clk = &dma_clk},
- { .dev_id = "jpeg", .clk = &jpeg_clk},
- { .dev_id = "gmac", .clk = &gmac_clk},
- { .dev_id = "smi", .clk = &smi_clk},
- { .dev_id = "c3", .clk = &c3_clk},
+ CLKDEV_INIT(NULL, "apb_clk", &apb_clk),
+ CLKDEV_INIT("d0180000.i2c", NULL, &i2c_clk),
+ CLKDEV_INIT("fc400000.dma", NULL, &dma_clk),
+ CLKDEV_INIT("jpeg", NULL, &jpeg_clk),
+ CLKDEV_INIT("e0800000.eth", NULL, &gmac_clk),
+ CLKDEV_INIT("fc000000.flash", NULL, &smi_clk),
+ CLKDEV_INIT("c3", NULL, &c3_clk),
/* clock derived from apb clk */
- { .dev_id = "adc", .clk = &adc_clk},
- { .dev_id = "ssp-pl022.0", .clk = &ssp0_clk},
- { .dev_id = "gpio", .clk = &gpio_clk},
+ CLKDEV_INIT("adc", NULL, &adc_clk),
+ CLKDEV_INIT("d0100000.spi", NULL, &ssp0_clk),
+ CLKDEV_INIT("fc980000.gpio", NULL, &gpio_clk),
};
/* array of all spear 300 clock lookups */
#ifdef CONFIG_MACH_SPEAR300
static struct clk_lookup spear300_clk_lookups[] = {
- { .dev_id = "clcd", .clk = &clcd_clk},
- { .con_id = "fsmc", .clk = &fsmc_clk},
- { .dev_id = "gpio1", .clk = &gpio1_clk},
- { .dev_id = "keyboard", .clk = &kbd_clk},
- { .dev_id = "sdhci", .clk = &sdhci_clk},
+ CLKDEV_INIT("60000000.clcd", NULL, &clcd_clk),
+ CLKDEV_INIT("94000000.flash", NULL, &fsmc_clk),
+ CLKDEV_INIT("a9000000.gpio", NULL, &gpio1_clk),
+ CLKDEV_INIT("a0000000.kbd", NULL, &kbd_clk),
+ CLKDEV_INIT("70000000.sdhci", NULL, &sdhci_clk),
};
+
+void __init spear300_clk_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
+ clk_register(&spear_clk_lookups[i]);
+
+ for (i = 0; i < ARRAY_SIZE(spear300_clk_lookups); i++)
+ clk_register(&spear300_clk_lookups[i]);
+
+ clk_init();
+}
#endif
/* array of all spear 310 clock lookups */
#ifdef CONFIG_MACH_SPEAR310
static struct clk_lookup spear310_clk_lookups[] = {
- { .con_id = "fsmc", .clk = &fsmc_clk},
- { .con_id = "emi", .clk = &emi_clk},
- { .dev_id = "uart1", .clk = &uart1_clk},
- { .dev_id = "uart2", .clk = &uart2_clk},
- { .dev_id = "uart3", .clk = &uart3_clk},
- { .dev_id = "uart4", .clk = &uart4_clk},
- { .dev_id = "uart5", .clk = &uart5_clk},
+ CLKDEV_INIT("44000000.flash", NULL, &fsmc_clk),
+ CLKDEV_INIT(NULL, "emi", &emi_clk),
+ CLKDEV_INIT("b2000000.serial", NULL, &uart1_clk),
+ CLKDEV_INIT("b2080000.serial", NULL, &uart2_clk),
+ CLKDEV_INIT("b2100000.serial", NULL, &uart3_clk),
+ CLKDEV_INIT("b2180000.serial", NULL, &uart4_clk),
+ CLKDEV_INIT("b2200000.serial", NULL, &uart5_clk),
};
+
+void __init spear310_clk_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
+ clk_register(&spear_clk_lookups[i]);
+
+ for (i = 0; i < ARRAY_SIZE(spear310_clk_lookups); i++)
+ clk_register(&spear310_clk_lookups[i]);
+
+ clk_init();
+}
#endif
/* array of all spear 320 clock lookups */
#ifdef CONFIG_MACH_SPEAR320
static struct clk_lookup spear320_clk_lookups[] = {
- { .dev_id = "clcd", .clk = &clcd_clk},
- { .con_id = "fsmc", .clk = &fsmc_clk},
- { .dev_id = "i2c_designware.1", .clk = &i2c1_clk},
- { .con_id = "emi", .clk = &emi_clk},
- { .dev_id = "pwm", .clk = &pwm_clk},
- { .dev_id = "sdhci", .clk = &sdhci_clk},
- { .dev_id = "c_can_platform.0", .clk = &can0_clk},
- { .dev_id = "c_can_platform.1", .clk = &can1_clk},
- { .dev_id = "ssp-pl022.1", .clk = &ssp1_clk},
- { .dev_id = "ssp-pl022.2", .clk = &ssp2_clk},
- { .dev_id = "uart1", .clk = &uart1_clk},
- { .dev_id = "uart2", .clk = &uart2_clk},
-};
-#endif
-
-void __init spear3xx_clk_init(void)
+ CLKDEV_INIT("90000000.clcd", NULL, &clcd_clk),
+ CLKDEV_INIT("4c000000.flash", NULL, &fsmc_clk),
+ CLKDEV_INIT("a7000000.i2c", NULL, &i2c1_clk),
+ CLKDEV_INIT(NULL, "emi", &emi_clk),
+ CLKDEV_INIT("pwm", NULL, &pwm_clk),
+ CLKDEV_INIT("70000000.sdhci", NULL, &sdhci_clk),
+ CLKDEV_INIT("c_can_platform.0", NULL, &can0_clk),
+ CLKDEV_INIT("c_can_platform.1", NULL, &can1_clk),
+ CLKDEV_INIT("a5000000.spi", NULL, &ssp1_clk),
+ CLKDEV_INIT("a6000000.spi", NULL, &ssp2_clk),
+ CLKDEV_INIT("a3000000.serial", NULL, &uart1_clk),
+ CLKDEV_INIT("a4000000.serial", NULL, &uart2_clk),
+};
+
+void __init spear320_clk_init(void)
{
- int i, cnt;
- struct clk_lookup *lookups;
-
- if (machine_is_spear300()) {
- cnt = ARRAY_SIZE(spear300_clk_lookups);
- lookups = spear300_clk_lookups;
- } else if (machine_is_spear310()) {
- cnt = ARRAY_SIZE(spear310_clk_lookups);
- lookups = spear310_clk_lookups;
- } else {
- cnt = ARRAY_SIZE(spear320_clk_lookups);
- lookups = spear320_clk_lookups;
- }
+ int i;
for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
clk_register(&spear_clk_lookups[i]);
- for (i = 0; i < cnt; i++)
- clk_register(&lookups[i]);
+ for (i = 0; i < ARRAY_SIZE(spear320_clk_lookups); i++)
+ clk_register(&spear320_clk_lookups[i]);
clk_init();
}
+#endif
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 14276e5a98d2..bdb304551caf 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -14,188 +14,40 @@
#ifndef __MACH_GENERIC_H
#define __MACH_GENERIC_H
+#include <linux/amba/pl08x.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/amba/bus.h>
#include <asm/mach/time.h>
#include <asm/mach/map.h>
-#include <plat/padmux.h>
-
-/* spear3xx declarations */
-/*
- * Each GPT has 2 timer channels
- * Following GPT channels will be used as clock source and clockevent
- */
-#define SPEAR_GPT0_BASE SPEAR3XX_ML1_TMR_BASE
-#define SPEAR_GPT0_CHAN0_IRQ SPEAR3XX_IRQ_CPU_GPT1_1
-#define SPEAR_GPT0_CHAN1_IRQ SPEAR3XX_IRQ_CPU_GPT1_2
/* Add spear3xx family device structure declarations here */
-extern struct amba_device spear3xx_gpio_device;
-extern struct amba_device spear3xx_uart_device;
extern struct sys_timer spear3xx_timer;
+extern struct pl022_ssp_controller pl022_plat_data;
+extern struct pl08x_platform_data pl080_plat_data;
/* Add spear3xx family function declarations here */
-void __init spear3xx_clk_init(void);
-void __init spear_setup_timer(void);
+void __init spear_setup_timer(resource_size_t base, int irq);
void __init spear3xx_map_io(void);
-void __init spear3xx_init_irq(void);
-void __init spear3xx_init(void);
+void __init spear3xx_dt_init_irq(void);
void spear_restart(char, const char *);
-/* pad mux declarations */
-#define PMX_FIRDA_MASK (1 << 14)
-#define PMX_I2C_MASK (1 << 13)
-#define PMX_SSP_CS_MASK (1 << 12)
-#define PMX_SSP_MASK (1 << 11)
-#define PMX_MII_MASK (1 << 10)
-#define PMX_GPIO_PIN0_MASK (1 << 9)
-#define PMX_GPIO_PIN1_MASK (1 << 8)
-#define PMX_GPIO_PIN2_MASK (1 << 7)
-#define PMX_GPIO_PIN3_MASK (1 << 6)
-#define PMX_GPIO_PIN4_MASK (1 << 5)
-#define PMX_GPIO_PIN5_MASK (1 << 4)
-#define PMX_UART0_MODEM_MASK (1 << 3)
-#define PMX_UART0_MASK (1 << 2)
-#define PMX_TIMER_3_4_MASK (1 << 1)
-#define PMX_TIMER_1_2_MASK (1 << 0)
-
-/* pad mux devices */
-extern struct pmx_dev spear3xx_pmx_firda;
-extern struct pmx_dev spear3xx_pmx_i2c;
-extern struct pmx_dev spear3xx_pmx_ssp_cs;
-extern struct pmx_dev spear3xx_pmx_ssp;
-extern struct pmx_dev spear3xx_pmx_mii;
-extern struct pmx_dev spear3xx_pmx_gpio_pin0;
-extern struct pmx_dev spear3xx_pmx_gpio_pin1;
-extern struct pmx_dev spear3xx_pmx_gpio_pin2;
-extern struct pmx_dev spear3xx_pmx_gpio_pin3;
-extern struct pmx_dev spear3xx_pmx_gpio_pin4;
-extern struct pmx_dev spear3xx_pmx_gpio_pin5;
-extern struct pmx_dev spear3xx_pmx_uart0_modem;
-extern struct pmx_dev spear3xx_pmx_uart0;
-extern struct pmx_dev spear3xx_pmx_timer_3_4;
-extern struct pmx_dev spear3xx_pmx_timer_1_2;
-
-#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
-/* padmux plgpio devices */
-extern struct pmx_dev spear3xx_pmx_plgpio_0_1;
-extern struct pmx_dev spear3xx_pmx_plgpio_2_3;
-extern struct pmx_dev spear3xx_pmx_plgpio_4_5;
-extern struct pmx_dev spear3xx_pmx_plgpio_6_9;
-extern struct pmx_dev spear3xx_pmx_plgpio_10_27;
-extern struct pmx_dev spear3xx_pmx_plgpio_28;
-extern struct pmx_dev spear3xx_pmx_plgpio_29;
-extern struct pmx_dev spear3xx_pmx_plgpio_30;
-extern struct pmx_dev spear3xx_pmx_plgpio_31;
-extern struct pmx_dev spear3xx_pmx_plgpio_32;
-extern struct pmx_dev spear3xx_pmx_plgpio_33;
-extern struct pmx_dev spear3xx_pmx_plgpio_34_36;
-extern struct pmx_dev spear3xx_pmx_plgpio_37_42;
-extern struct pmx_dev spear3xx_pmx_plgpio_43_44_47_48;
-extern struct pmx_dev spear3xx_pmx_plgpio_45_46_49_50;
-#endif
-
/* spear300 declarations */
#ifdef CONFIG_MACH_SPEAR300
-/* Add spear300 machine device structure declarations here */
-extern struct amba_device spear300_gpio1_device;
-
-/* pad mux modes */
-extern struct pmx_mode spear300_nand_mode;
-extern struct pmx_mode spear300_nor_mode;
-extern struct pmx_mode spear300_photo_frame_mode;
-extern struct pmx_mode spear300_lend_ip_phone_mode;
-extern struct pmx_mode spear300_hend_ip_phone_mode;
-extern struct pmx_mode spear300_lend_wifi_phone_mode;
-extern struct pmx_mode spear300_hend_wifi_phone_mode;
-extern struct pmx_mode spear300_ata_pabx_wi2s_mode;
-extern struct pmx_mode spear300_ata_pabx_i2s_mode;
-extern struct pmx_mode spear300_caml_lcdw_mode;
-extern struct pmx_mode spear300_camu_lcd_mode;
-extern struct pmx_mode spear300_camu_wlcd_mode;
-extern struct pmx_mode spear300_caml_lcd_mode;
-
-/* pad mux devices */
-extern struct pmx_dev spear300_pmx_fsmc_2_chips;
-extern struct pmx_dev spear300_pmx_fsmc_4_chips;
-extern struct pmx_dev spear300_pmx_keyboard;
-extern struct pmx_dev spear300_pmx_clcd;
-extern struct pmx_dev spear300_pmx_telecom_gpio;
-extern struct pmx_dev spear300_pmx_telecom_tdm;
-extern struct pmx_dev spear300_pmx_telecom_spi_cs_i2c_clk;
-extern struct pmx_dev spear300_pmx_telecom_camera;
-extern struct pmx_dev spear300_pmx_telecom_dac;
-extern struct pmx_dev spear300_pmx_telecom_i2s;
-extern struct pmx_dev spear300_pmx_telecom_boot_pins;
-extern struct pmx_dev spear300_pmx_telecom_sdhci_4bit;
-extern struct pmx_dev spear300_pmx_telecom_sdhci_8bit;
-extern struct pmx_dev spear300_pmx_gpio1;
-
-/* Add spear300 machine function declarations here */
-void __init spear300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
- u8 pmx_dev_count);
+void __init spear300_clk_init(void);
#endif /* CONFIG_MACH_SPEAR300 */
/* spear310 declarations */
#ifdef CONFIG_MACH_SPEAR310
-/* Add spear310 machine device structure declarations here */
-
-/* pad mux devices */
-extern struct pmx_dev spear310_pmx_emi_cs_0_1_4_5;
-extern struct pmx_dev spear310_pmx_emi_cs_2_3;
-extern struct pmx_dev spear310_pmx_uart1;
-extern struct pmx_dev spear310_pmx_uart2;
-extern struct pmx_dev spear310_pmx_uart3_4_5;
-extern struct pmx_dev spear310_pmx_fsmc;
-extern struct pmx_dev spear310_pmx_rs485_0_1;
-extern struct pmx_dev spear310_pmx_tdm0;
-
-/* Add spear310 machine function declarations here */
-void __init spear310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
- u8 pmx_dev_count);
+void __init spear310_clk_init(void);
#endif /* CONFIG_MACH_SPEAR310 */
/* spear320 declarations */
#ifdef CONFIG_MACH_SPEAR320
-/* Add spear320 machine device structure declarations here */
-
-/* pad mux modes */
-extern struct pmx_mode spear320_auto_net_smii_mode;
-extern struct pmx_mode spear320_auto_net_mii_mode;
-extern struct pmx_mode spear320_auto_exp_mode;
-extern struct pmx_mode spear320_small_printers_mode;
-
-/* pad mux devices */
-extern struct pmx_dev spear320_pmx_clcd;
-extern struct pmx_dev spear320_pmx_emi;
-extern struct pmx_dev spear320_pmx_fsmc;
-extern struct pmx_dev spear320_pmx_spp;
-extern struct pmx_dev spear320_pmx_sdhci;
-extern struct pmx_dev spear320_pmx_i2s;
-extern struct pmx_dev spear320_pmx_uart1;
-extern struct pmx_dev spear320_pmx_uart1_modem;
-extern struct pmx_dev spear320_pmx_uart2;
-extern struct pmx_dev spear320_pmx_touchscreen;
-extern struct pmx_dev spear320_pmx_can;
-extern struct pmx_dev spear320_pmx_sdhci_led;
-extern struct pmx_dev spear320_pmx_pwm0;
-extern struct pmx_dev spear320_pmx_pwm1;
-extern struct pmx_dev spear320_pmx_pwm2;
-extern struct pmx_dev spear320_pmx_pwm3;
-extern struct pmx_dev spear320_pmx_ssp1;
-extern struct pmx_dev spear320_pmx_ssp2;
-extern struct pmx_dev spear320_pmx_mii1;
-extern struct pmx_dev spear320_pmx_smii0;
-extern struct pmx_dev spear320_pmx_smii1;
-extern struct pmx_dev spear320_pmx_i2c1;
-
-/* Add spear320 machine function declarations here */
-void __init spear320_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
- u8 pmx_dev_count);
+void __init spear320_clk_init(void);
#endif /* CONFIG_MACH_SPEAR320 */
diff --git a/arch/arm/mach-spear3xx/include/mach/hardware.h b/arch/arm/mach-spear3xx/include/mach/hardware.h
index 4660c0d8ec0d..40a8c178f10d 100644
--- a/arch/arm/mach-spear3xx/include/mach/hardware.h
+++ b/arch/arm/mach-spear3xx/include/mach/hardware.h
@@ -1,23 +1 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/hardware.h
- *
- * Hardware definitions for SPEAr3xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __MACH_HARDWARE_H
-#define __MACH_HARDWARE_H
-
-#include <plat/hardware.h>
-#include <mach/spear.h>
-
-/* Vitual to physical translation of statically mapped space */
-#define IO_ADDRESS(x) (x | 0xF0000000)
-
-#endif /* __MACH_HARDWARE_H */
+/* empty */
diff --git a/arch/arm/mach-spear3xx/include/mach/irqs.h b/arch/arm/mach-spear3xx/include/mach/irqs.h
index 6e265442808e..319620a1afb4 100644
--- a/arch/arm/mach-spear3xx/include/mach/irqs.h
+++ b/arch/arm/mach-spear3xx/include/mach/irqs.h
@@ -14,141 +14,15 @@
#ifndef __MACH_IRQS_H
#define __MACH_IRQS_H
-/* SPEAr3xx IRQ definitions */
-#define SPEAR3XX_IRQ_HW_ACCEL_MOD_0 0
+/* FIXME: probe all these from DT */
#define SPEAR3XX_IRQ_INTRCOMM_RAS_ARM 1
#define SPEAR3XX_IRQ_CPU_GPT1_1 2
-#define SPEAR3XX_IRQ_CPU_GPT1_2 3
-#define SPEAR3XX_IRQ_BASIC_GPT1_1 4
-#define SPEAR3XX_IRQ_BASIC_GPT1_2 5
-#define SPEAR3XX_IRQ_BASIC_GPT2_1 6
-#define SPEAR3XX_IRQ_BASIC_GPT2_2 7
-#define SPEAR3XX_IRQ_BASIC_DMA 8
-#define SPEAR3XX_IRQ_BASIC_SMI 9
-#define SPEAR3XX_IRQ_BASIC_RTC 10
-#define SPEAR3XX_IRQ_BASIC_GPIO 11
-#define SPEAR3XX_IRQ_BASIC_WDT 12
-#define SPEAR3XX_IRQ_DDR_CONTROLLER 13
-#define SPEAR3XX_IRQ_SYS_ERROR 14
-#define SPEAR3XX_IRQ_WAKEUP_RCV 15
-#define SPEAR3XX_IRQ_JPEG 16
-#define SPEAR3XX_IRQ_IRDA 17
-#define SPEAR3XX_IRQ_ADC 18
-#define SPEAR3XX_IRQ_UART 19
-#define SPEAR3XX_IRQ_SSP 20
-#define SPEAR3XX_IRQ_I2C 21
-#define SPEAR3XX_IRQ_MAC_1 22
-#define SPEAR3XX_IRQ_MAC_2 23
-#define SPEAR3XX_IRQ_USB_DEV 24
-#define SPEAR3XX_IRQ_USB_H_OHCI_0 25
-#define SPEAR3XX_IRQ_USB_H_EHCI_0 26
-#define SPEAR3XX_IRQ_USB_H_EHCI_1 SPEAR3XX_IRQ_USB_H_EHCI_0
-#define SPEAR3XX_IRQ_USB_H_OHCI_1 27
#define SPEAR3XX_IRQ_GEN_RAS_1 28
#define SPEAR3XX_IRQ_GEN_RAS_2 29
#define SPEAR3XX_IRQ_GEN_RAS_3 30
-#define SPEAR3XX_IRQ_HW_ACCEL_MOD_1 31
#define SPEAR3XX_IRQ_VIC_END 32
-
#define SPEAR3XX_VIRQ_START SPEAR3XX_IRQ_VIC_END
-/* SPEAr300 Virtual irq definitions */
-/* IRQs sharing IRQ_GEN_RAS_1 */
-#define SPEAR300_VIRQ_IT_PERS_S (SPEAR3XX_VIRQ_START + 0)
-#define SPEAR300_VIRQ_IT_CHANGE_S (SPEAR3XX_VIRQ_START + 1)
-#define SPEAR300_VIRQ_I2S (SPEAR3XX_VIRQ_START + 2)
-#define SPEAR300_VIRQ_TDM (SPEAR3XX_VIRQ_START + 3)
-#define SPEAR300_VIRQ_CAMERA_L (SPEAR3XX_VIRQ_START + 4)
-#define SPEAR300_VIRQ_CAMERA_F (SPEAR3XX_VIRQ_START + 5)
-#define SPEAR300_VIRQ_CAMERA_V (SPEAR3XX_VIRQ_START + 6)
-#define SPEAR300_VIRQ_KEYBOARD (SPEAR3XX_VIRQ_START + 7)
-#define SPEAR300_VIRQ_GPIO1 (SPEAR3XX_VIRQ_START + 8)
-
-/* IRQs sharing IRQ_GEN_RAS_3 */
-#define SPEAR300_IRQ_CLCD SPEAR3XX_IRQ_GEN_RAS_3
-
-/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define SPEAR300_IRQ_SDHCI SPEAR3XX_IRQ_INTRCOMM_RAS_ARM
-
-/* SPEAr310 Virtual irq definitions */
-/* IRQs sharing IRQ_GEN_RAS_1 */
-#define SPEAR310_VIRQ_SMII0 (SPEAR3XX_VIRQ_START + 0)
-#define SPEAR310_VIRQ_SMII1 (SPEAR3XX_VIRQ_START + 1)
-#define SPEAR310_VIRQ_SMII2 (SPEAR3XX_VIRQ_START + 2)
-#define SPEAR310_VIRQ_SMII3 (SPEAR3XX_VIRQ_START + 3)
-#define SPEAR310_VIRQ_WAKEUP_SMII0 (SPEAR3XX_VIRQ_START + 4)
-#define SPEAR310_VIRQ_WAKEUP_SMII1 (SPEAR3XX_VIRQ_START + 5)
-#define SPEAR310_VIRQ_WAKEUP_SMII2 (SPEAR3XX_VIRQ_START + 6)
-#define SPEAR310_VIRQ_WAKEUP_SMII3 (SPEAR3XX_VIRQ_START + 7)
-
-/* IRQs sharing IRQ_GEN_RAS_2 */
-#define SPEAR310_VIRQ_UART1 (SPEAR3XX_VIRQ_START + 8)
-#define SPEAR310_VIRQ_UART2 (SPEAR3XX_VIRQ_START + 9)
-#define SPEAR310_VIRQ_UART3 (SPEAR3XX_VIRQ_START + 10)
-#define SPEAR310_VIRQ_UART4 (SPEAR3XX_VIRQ_START + 11)
-#define SPEAR310_VIRQ_UART5 (SPEAR3XX_VIRQ_START + 12)
-
-/* IRQs sharing IRQ_GEN_RAS_3 */
-#define SPEAR310_VIRQ_EMI (SPEAR3XX_VIRQ_START + 13)
-#define SPEAR310_VIRQ_PLGPIO (SPEAR3XX_VIRQ_START + 14)
-
-/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define SPEAR310_VIRQ_TDM_HDLC (SPEAR3XX_VIRQ_START + 15)
-#define SPEAR310_VIRQ_RS485_0 (SPEAR3XX_VIRQ_START + 16)
-#define SPEAR310_VIRQ_RS485_1 (SPEAR3XX_VIRQ_START + 17)
-
-/* SPEAr320 Virtual irq definitions */
-/* IRQs sharing IRQ_GEN_RAS_1 */
-#define SPEAR320_VIRQ_EMI (SPEAR3XX_VIRQ_START + 0)
-#define SPEAR320_VIRQ_CLCD (SPEAR3XX_VIRQ_START + 1)
-#define SPEAR320_VIRQ_SPP (SPEAR3XX_VIRQ_START + 2)
-
-/* IRQs sharing IRQ_GEN_RAS_2 */
-#define SPEAR320_IRQ_SDHCI SPEAR3XX_IRQ_GEN_RAS_2
-
-/* IRQs sharing IRQ_GEN_RAS_3 */
-#define SPEAR320_VIRQ_PLGPIO (SPEAR3XX_VIRQ_START + 3)
-#define SPEAR320_VIRQ_I2S_PLAY (SPEAR3XX_VIRQ_START + 4)
-#define SPEAR320_VIRQ_I2S_REC (SPEAR3XX_VIRQ_START + 5)
-
-/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define SPEAR320_VIRQ_CANU (SPEAR3XX_VIRQ_START + 6)
-#define SPEAR320_VIRQ_CANL (SPEAR3XX_VIRQ_START + 7)
-#define SPEAR320_VIRQ_UART1 (SPEAR3XX_VIRQ_START + 8)
-#define SPEAR320_VIRQ_UART2 (SPEAR3XX_VIRQ_START + 9)
-#define SPEAR320_VIRQ_SSP1 (SPEAR3XX_VIRQ_START + 10)
-#define SPEAR320_VIRQ_SSP2 (SPEAR3XX_VIRQ_START + 11)
-#define SPEAR320_VIRQ_SMII0 (SPEAR3XX_VIRQ_START + 12)
-#define SPEAR320_VIRQ_MII1_SMII1 (SPEAR3XX_VIRQ_START + 13)
-#define SPEAR320_VIRQ_WAKEUP_SMII0 (SPEAR3XX_VIRQ_START + 14)
-#define SPEAR320_VIRQ_WAKEUP_MII1_SMII1 (SPEAR3XX_VIRQ_START + 15)
-#define SPEAR320_VIRQ_I2C1 (SPEAR3XX_VIRQ_START + 16)
-
-/*
- * GPIO pins virtual irqs
- * Use the lowest number for the GPIO virtual IRQs base on which subarchs
- * we have compiled in
- */
-#if defined(CONFIG_MACH_SPEAR310)
-#define SPEAR3XX_GPIO_INT_BASE (SPEAR3XX_VIRQ_START + 18)
-#elif defined(CONFIG_MACH_SPEAR320)
-#define SPEAR3XX_GPIO_INT_BASE (SPEAR3XX_VIRQ_START + 17)
-#else
-#define SPEAR3XX_GPIO_INT_BASE (SPEAR3XX_VIRQ_START + 9)
-#endif
-
-#define SPEAR300_GPIO1_INT_BASE (SPEAR3XX_GPIO_INT_BASE + 8)
-#define SPEAR3XX_PLGPIO_COUNT 102
-
-#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
-#define SPEAR3XX_PLGPIO_INT_BASE (SPEAR3XX_GPIO_INT_BASE + 8)
-#define SPEAR3XX_GPIO_INT_END (SPEAR3XX_PLGPIO_INT_BASE + \
- SPEAR3XX_PLGPIO_COUNT)
-#else
-#define SPEAR3XX_GPIO_INT_END (SPEAR300_GPIO1_INT_BASE + 8)
-#endif
-
-#define SPEAR3XX_VIRQ_END SPEAR3XX_GPIO_INT_END
-#define NR_IRQS SPEAR3XX_VIRQ_END
+#define NR_IRQS 160
#endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-spear3xx/include/mach/misc_regs.h b/arch/arm/mach-spear3xx/include/mach/misc_regs.h
index 5bd8cd8d4852..e0ab72e61507 100644
--- a/arch/arm/mach-spear3xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear3xx/include/mach/misc_regs.h
@@ -14,151 +14,7 @@
#ifndef __MACH_MISC_REGS_H
#define __MACH_MISC_REGS_H
-#include <mach/hardware.h>
-
#define MISC_BASE IOMEM(VA_SPEAR3XX_ICM3_MISC_REG_BASE)
-
-#define SOC_CFG_CTR (MISC_BASE + 0x000)
-#define DIAG_CFG_CTR (MISC_BASE + 0x004)
-#define PLL1_CTR (MISC_BASE + 0x008)
-#define PLL1_FRQ (MISC_BASE + 0x00C)
-#define PLL1_MOD (MISC_BASE + 0x010)
-#define PLL2_CTR (MISC_BASE + 0x014)
-/* PLL_CTR register masks */
-#define PLL_ENABLE 2
-#define PLL_MODE_SHIFT 4
-#define PLL_MODE_MASK 0x3
-#define PLL_MODE_NORMAL 0
-#define PLL_MODE_FRACTION 1
-#define PLL_MODE_DITH_DSB 2
-#define PLL_MODE_DITH_SSB 3
-
-#define PLL2_FRQ (MISC_BASE + 0x018)
-/* PLL FRQ register masks */
-#define PLL_DIV_N_SHIFT 0
-#define PLL_DIV_N_MASK 0xFF
-#define PLL_DIV_P_SHIFT 8
-#define PLL_DIV_P_MASK 0x7
-#define PLL_NORM_FDBK_M_SHIFT 24
-#define PLL_NORM_FDBK_M_MASK 0xFF
-#define PLL_DITH_FDBK_M_SHIFT 16
-#define PLL_DITH_FDBK_M_MASK 0xFFFF
-
-#define PLL2_MOD (MISC_BASE + 0x01C)
-#define PLL_CLK_CFG (MISC_BASE + 0x020)
-#define CORE_CLK_CFG (MISC_BASE + 0x024)
-/* CORE CLK CFG register masks */
-#define PLL_HCLK_RATIO_SHIFT 10
-#define PLL_HCLK_RATIO_MASK 0x3
-#define HCLK_PCLK_RATIO_SHIFT 8
-#define HCLK_PCLK_RATIO_MASK 0x3
-
-#define PERIP_CLK_CFG (MISC_BASE + 0x028)
-/* PERIP_CLK_CFG register masks */
-#define UART_CLK_SHIFT 4
-#define UART_CLK_MASK 0x1
-#define FIRDA_CLK_SHIFT 5
-#define FIRDA_CLK_MASK 0x3
-#define GPT0_CLK_SHIFT 8
-#define GPT1_CLK_SHIFT 11
-#define GPT2_CLK_SHIFT 12
-#define GPT_CLK_MASK 0x1
-#define AUX_CLK_PLL3_VAL 0
-#define AUX_CLK_PLL1_VAL 1
-
-#define PERIP1_CLK_ENB (MISC_BASE + 0x02C)
-/* PERIP1_CLK_ENB register masks */
-#define UART_CLK_ENB 3
-#define SSP_CLK_ENB 5
-#define I2C_CLK_ENB 7
-#define JPEG_CLK_ENB 8
-#define FIRDA_CLK_ENB 10
-#define GPT1_CLK_ENB 11
-#define GPT2_CLK_ENB 12
-#define ADC_CLK_ENB 15
-#define RTC_CLK_ENB 17
-#define GPIO_CLK_ENB 18
-#define DMA_CLK_ENB 19
-#define SMI_CLK_ENB 21
-#define GMAC_CLK_ENB 23
-#define USBD_CLK_ENB 24
-#define USBH_CLK_ENB 25
-#define C3_CLK_ENB 31
-
-#define SOC_CORE_ID (MISC_BASE + 0x030)
-#define RAS_CLK_ENB (MISC_BASE + 0x034)
-#define PERIP1_SOF_RST (MISC_BASE + 0x038)
-/* PERIP1_SOF_RST register masks */
-#define JPEG_SOF_RST 8
-
-#define SOC_USER_ID (MISC_BASE + 0x03C)
-#define RAS_SOF_RST (MISC_BASE + 0x040)
-#define PRSC1_CLK_CFG (MISC_BASE + 0x044)
-#define PRSC2_CLK_CFG (MISC_BASE + 0x048)
-#define PRSC3_CLK_CFG (MISC_BASE + 0x04C)
-/* gpt synthesizer register masks */
-#define GPT_MSCALE_SHIFT 0
-#define GPT_MSCALE_MASK 0xFFF
-#define GPT_NSCALE_SHIFT 12
-#define GPT_NSCALE_MASK 0xF
-
-#define AMEM_CLK_CFG (MISC_BASE + 0x050)
-#define EXPI_CLK_CFG (MISC_BASE + 0x054)
-#define CLCD_CLK_SYNT (MISC_BASE + 0x05C)
-#define FIRDA_CLK_SYNT (MISC_BASE + 0x060)
-#define UART_CLK_SYNT (MISC_BASE + 0x064)
-#define GMAC_CLK_SYNT (MISC_BASE + 0x068)
-#define RAS1_CLK_SYNT (MISC_BASE + 0x06C)
-#define RAS2_CLK_SYNT (MISC_BASE + 0x070)
-#define RAS3_CLK_SYNT (MISC_BASE + 0x074)
-#define RAS4_CLK_SYNT (MISC_BASE + 0x078)
-/* aux clk synthesiser register masks for irda to ras4 */
-#define AUX_SYNT_ENB 31
-#define AUX_EQ_SEL_SHIFT 30
-#define AUX_EQ_SEL_MASK 1
-#define AUX_EQ1_SEL 0
-#define AUX_EQ2_SEL 1
-#define AUX_XSCALE_SHIFT 16
-#define AUX_XSCALE_MASK 0xFFF
-#define AUX_YSCALE_SHIFT 0
-#define AUX_YSCALE_MASK 0xFFF
-
-#define ICM1_ARB_CFG (MISC_BASE + 0x07C)
-#define ICM2_ARB_CFG (MISC_BASE + 0x080)
-#define ICM3_ARB_CFG (MISC_BASE + 0x084)
-#define ICM4_ARB_CFG (MISC_BASE + 0x088)
-#define ICM5_ARB_CFG (MISC_BASE + 0x08C)
-#define ICM6_ARB_CFG (MISC_BASE + 0x090)
-#define ICM7_ARB_CFG (MISC_BASE + 0x094)
-#define ICM8_ARB_CFG (MISC_BASE + 0x098)
-#define ICM9_ARB_CFG (MISC_BASE + 0x09C)
#define DMA_CHN_CFG (MISC_BASE + 0x0A0)
-#define USB2_PHY_CFG (MISC_BASE + 0x0A4)
-#define GMAC_CFG_CTR (MISC_BASE + 0x0A8)
-#define EXPI_CFG_CTR (MISC_BASE + 0x0AC)
-#define PRC1_LOCK_CTR (MISC_BASE + 0x0C0)
-#define PRC2_LOCK_CTR (MISC_BASE + 0x0C4)
-#define PRC3_LOCK_CTR (MISC_BASE + 0x0C8)
-#define PRC4_LOCK_CTR (MISC_BASE + 0x0CC)
-#define PRC1_IRQ_CTR (MISC_BASE + 0x0D0)
-#define PRC2_IRQ_CTR (MISC_BASE + 0x0D4)
-#define PRC3_IRQ_CTR (MISC_BASE + 0x0D8)
-#define PRC4_IRQ_CTR (MISC_BASE + 0x0DC)
-#define PWRDOWN_CFG_CTR (MISC_BASE + 0x0E0)
-#define COMPSSTL_1V8_CFG (MISC_BASE + 0x0E4)
-#define COMPSSTL_2V5_CFG (MISC_BASE + 0x0E8)
-#define COMPCOR_3V3_CFG (MISC_BASE + 0x0EC)
-#define SSTLPAD_CFG_CTR (MISC_BASE + 0x0F0)
-#define BIST1_CFG_CTR (MISC_BASE + 0x0F4)
-#define BIST2_CFG_CTR (MISC_BASE + 0x0F8)
-#define BIST3_CFG_CTR (MISC_BASE + 0x0FC)
-#define BIST4_CFG_CTR (MISC_BASE + 0x100)
-#define BIST5_CFG_CTR (MISC_BASE + 0x104)
-#define BIST1_STS_RES (MISC_BASE + 0x108)
-#define BIST2_STS_RES (MISC_BASE + 0x10C)
-#define BIST3_STS_RES (MISC_BASE + 0x110)
-#define BIST4_STS_RES (MISC_BASE + 0x114)
-#define BIST5_STS_RES (MISC_BASE + 0x118)
-#define SYSERR_CFG_CTR (MISC_BASE + 0x11C)
#endif /* __MACH_MISC_REGS_H */
diff --git a/arch/arm/mach-spear3xx/include/mach/spear.h b/arch/arm/mach-spear3xx/include/mach/spear.h
index 63fd98356919..6d4dadc67633 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear.h
@@ -15,60 +15,27 @@
#define __MACH_SPEAR3XX_H
#include <asm/memory.h>
-#include <mach/spear300.h>
-#include <mach/spear310.h>
-#include <mach/spear320.h>
-
-#define SPEAR3XX_ML_SDRAM_BASE UL(0x00000000)
-
-#define SPEAR3XX_ICM9_BASE UL(0xC0000000)
/* ICM1 - Low speed connection */
#define SPEAR3XX_ICM1_2_BASE UL(0xD0000000)
+#define VA_SPEAR3XX_ICM1_2_BASE UL(0xFD000000)
#define SPEAR3XX_ICM1_UART_BASE UL(0xD0000000)
-#define VA_SPEAR3XX_ICM1_UART_BASE IO_ADDRESS(SPEAR3XX_ICM1_UART_BASE)
-#define SPEAR3XX_ICM1_ADC_BASE UL(0xD0080000)
+#define VA_SPEAR3XX_ICM1_UART_BASE (VA_SPEAR3XX_ICM1_2_BASE | SPEAR3XX_ICM1_UART_BASE)
#define SPEAR3XX_ICM1_SSP_BASE UL(0xD0100000)
-#define SPEAR3XX_ICM1_I2C_BASE UL(0xD0180000)
-#define SPEAR3XX_ICM1_JPEG_BASE UL(0xD0800000)
-#define SPEAR3XX_ICM1_IRDA_BASE UL(0xD1000000)
-#define SPEAR3XX_ICM1_SRAM_BASE UL(0xD2800000)
-
-/* ICM2 - Application Subsystem */
-#define SPEAR3XX_ICM2_HWACCEL0_BASE UL(0xD8800000)
-#define SPEAR3XX_ICM2_HWACCEL1_BASE UL(0xD9000000)
-
-/* ICM4 - High Speed Connection */
-#define SPEAR3XX_ICM4_BASE UL(0xE0000000)
-#define SPEAR3XX_ICM4_MII_BASE UL(0xE0800000)
-#define SPEAR3XX_ICM4_USBD_FIFO_BASE UL(0xE1000000)
-#define SPEAR3XX_ICM4_USBD_CSR_BASE UL(0xE1100000)
-#define SPEAR3XX_ICM4_USBD_PLDT_BASE UL(0xE1200000)
-#define SPEAR3XX_ICM4_USB_EHCI0_1_BASE UL(0xE1800000)
-#define SPEAR3XX_ICM4_USB_OHCI0_BASE UL(0xE1900000)
-#define SPEAR3XX_ICM4_USB_OHCI1_BASE UL(0xE2100000)
-#define SPEAR3XX_ICM4_USB_ARB_BASE UL(0xE2800000)
/* ML1 - Multi Layer CPU Subsystem */
#define SPEAR3XX_ICM3_ML1_2_BASE UL(0xF0000000)
-#define SPEAR3XX_ML1_TMR_BASE UL(0xF0000000)
-#define SPEAR3XX_ML1_VIC_BASE UL(0xF1100000)
-#define VA_SPEAR3XX_ML1_VIC_BASE IO_ADDRESS(SPEAR3XX_ML1_VIC_BASE)
+#define VA_SPEAR6XX_ML_CPU_BASE UL(0xF0000000)
+#define SPEAR3XX_CPU_TMR_BASE UL(0xF0000000)
/* ICM3 - Basic Subsystem */
-#define SPEAR3XX_ICM3_SMEM_BASE UL(0xF8000000)
#define SPEAR3XX_ICM3_SMI_CTRL_BASE UL(0xFC000000)
+#define VA_SPEAR3XX_ICM3_SMI_CTRL_BASE UL(0xFC000000)
#define SPEAR3XX_ICM3_DMA_BASE UL(0xFC400000)
-#define SPEAR3XX_ICM3_SDRAM_CTRL_BASE UL(0xFC600000)
-#define SPEAR3XX_ICM3_TMR0_BASE UL(0xFC800000)
-#define SPEAR3XX_ICM3_WDT_BASE UL(0xFC880000)
-#define SPEAR3XX_ICM3_RTC_BASE UL(0xFC900000)
-#define SPEAR3XX_ICM3_GPIO_BASE UL(0xFC980000)
#define SPEAR3XX_ICM3_SYS_CTRL_BASE UL(0xFCA00000)
-#define VA_SPEAR3XX_ICM3_SYS_CTRL_BASE IO_ADDRESS(SPEAR3XX_ICM3_SYS_CTRL_BASE)
+#define VA_SPEAR3XX_ICM3_SYS_CTRL_BASE (VA_SPEAR3XX_ICM3_SMI_CTRL_BASE | SPEAR3XX_ICM3_SYS_CTRL_BASE)
#define SPEAR3XX_ICM3_MISC_REG_BASE UL(0xFCA80000)
-#define VA_SPEAR3XX_ICM3_MISC_REG_BASE IO_ADDRESS(SPEAR3XX_ICM3_MISC_REG_BASE)
-#define SPEAR3XX_ICM3_TMR1_BASE UL(0xFCB00000)
+#define VA_SPEAR3XX_ICM3_MISC_REG_BASE (VA_SPEAR3XX_ICM3_SMI_CTRL_BASE | SPEAR3XX_ICM3_MISC_REG_BASE)
/* Debug uart for linux, will be used for debug and uncompress messages */
#define SPEAR_DBG_UART_BASE SPEAR3XX_ICM1_UART_BASE
diff --git a/arch/arm/mach-spear3xx/include/mach/spear300.h b/arch/arm/mach-spear3xx/include/mach/spear300.h
deleted file mode 100644
index 3b6ea0729040..000000000000
--- a/arch/arm/mach-spear3xx/include/mach/spear300.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/spear300.h
- *
- * SPEAr300 Machine specific definition
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifdef CONFIG_MACH_SPEAR300
-
-#ifndef __MACH_SPEAR300_H
-#define __MACH_SPEAR300_H
-
-/* Base address of various IPs */
-#define SPEAR300_TELECOM_BASE UL(0x50000000)
-
-/* Interrupt registers offsets and masks */
-#define SPEAR300_INT_ENB_MASK_REG 0x54
-#define SPEAR300_INT_STS_MASK_REG 0x58
-#define SPEAR300_IT_PERS_S_IRQ_MASK (1 << 0)
-#define SPEAR300_IT_CHANGE_S_IRQ_MASK (1 << 1)
-#define SPEAR300_I2S_IRQ_MASK (1 << 2)
-#define SPEAR300_TDM_IRQ_MASK (1 << 3)
-#define SPEAR300_CAMERA_L_IRQ_MASK (1 << 4)
-#define SPEAR300_CAMERA_F_IRQ_MASK (1 << 5)
-#define SPEAR300_CAMERA_V_IRQ_MASK (1 << 6)
-#define SPEAR300_KEYBOARD_IRQ_MASK (1 << 7)
-#define SPEAR300_GPIO1_IRQ_MASK (1 << 8)
-
-#define SPEAR300_SHIRQ_RAS1_MASK 0x1FF
-
-#define SPEAR300_CLCD_BASE UL(0x60000000)
-#define SPEAR300_SDHCI_BASE UL(0x70000000)
-#define SPEAR300_NAND_0_BASE UL(0x80000000)
-#define SPEAR300_NAND_1_BASE UL(0x84000000)
-#define SPEAR300_NAND_2_BASE UL(0x88000000)
-#define SPEAR300_NAND_3_BASE UL(0x8c000000)
-#define SPEAR300_NOR_0_BASE UL(0x90000000)
-#define SPEAR300_NOR_1_BASE UL(0x91000000)
-#define SPEAR300_NOR_2_BASE UL(0x92000000)
-#define SPEAR300_NOR_3_BASE UL(0x93000000)
-#define SPEAR300_FSMC_BASE UL(0x94000000)
-#define SPEAR300_SOC_CONFIG_BASE UL(0x99000000)
-#define SPEAR300_KEYBOARD_BASE UL(0xA0000000)
-#define SPEAR300_GPIO_BASE UL(0xA9000000)
-
-#endif /* __MACH_SPEAR300_H */
-
-#endif /* CONFIG_MACH_SPEAR300 */
diff --git a/arch/arm/mach-spear3xx/include/mach/spear310.h b/arch/arm/mach-spear3xx/include/mach/spear310.h
deleted file mode 100644
index 1567d0da725f..000000000000
--- a/arch/arm/mach-spear3xx/include/mach/spear310.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/spear310.h
- *
- * SPEAr310 Machine specific definition
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifdef CONFIG_MACH_SPEAR310
-
-#ifndef __MACH_SPEAR310_H
-#define __MACH_SPEAR310_H
-
-#define SPEAR310_NAND_BASE UL(0x40000000)
-#define SPEAR310_FSMC_BASE UL(0x44000000)
-#define SPEAR310_UART1_BASE UL(0xB2000000)
-#define SPEAR310_UART2_BASE UL(0xB2080000)
-#define SPEAR310_UART3_BASE UL(0xB2100000)
-#define SPEAR310_UART4_BASE UL(0xB2180000)
-#define SPEAR310_UART5_BASE UL(0xB2200000)
-#define SPEAR310_HDLC_BASE UL(0xB2800000)
-#define SPEAR310_RS485_0_BASE UL(0xB3000000)
-#define SPEAR310_RS485_1_BASE UL(0xB3800000)
-#define SPEAR310_SOC_CONFIG_BASE UL(0xB4000000)
-
-/* Interrupt registers offsets and masks */
-#define SPEAR310_INT_STS_MASK_REG 0x04
-#define SPEAR310_SMII0_IRQ_MASK (1 << 0)
-#define SPEAR310_SMII1_IRQ_MASK (1 << 1)
-#define SPEAR310_SMII2_IRQ_MASK (1 << 2)
-#define SPEAR310_SMII3_IRQ_MASK (1 << 3)
-#define SPEAR310_WAKEUP_SMII0_IRQ_MASK (1 << 4)
-#define SPEAR310_WAKEUP_SMII1_IRQ_MASK (1 << 5)
-#define SPEAR310_WAKEUP_SMII2_IRQ_MASK (1 << 6)
-#define SPEAR310_WAKEUP_SMII3_IRQ_MASK (1 << 7)
-#define SPEAR310_UART1_IRQ_MASK (1 << 8)
-#define SPEAR310_UART2_IRQ_MASK (1 << 9)
-#define SPEAR310_UART3_IRQ_MASK (1 << 10)
-#define SPEAR310_UART4_IRQ_MASK (1 << 11)
-#define SPEAR310_UART5_IRQ_MASK (1 << 12)
-#define SPEAR310_EMI_IRQ_MASK (1 << 13)
-#define SPEAR310_TDM_HDLC_IRQ_MASK (1 << 14)
-#define SPEAR310_RS485_0_IRQ_MASK (1 << 15)
-#define SPEAR310_RS485_1_IRQ_MASK (1 << 16)
-
-#define SPEAR310_SHIRQ_RAS1_MASK 0x000FF
-#define SPEAR310_SHIRQ_RAS2_MASK 0x01F00
-#define SPEAR310_SHIRQ_RAS3_MASK 0x02000
-#define SPEAR310_SHIRQ_INTRCOMM_RAS_MASK 0x1C000
-
-#endif /* __MACH_SPEAR310_H */
-
-#endif /* CONFIG_MACH_SPEAR310 */
diff --git a/arch/arm/mach-spear3xx/include/mach/spear320.h b/arch/arm/mach-spear3xx/include/mach/spear320.h
deleted file mode 100644
index 8cfa83fa1296..000000000000
--- a/arch/arm/mach-spear3xx/include/mach/spear320.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/spear320.h
- *
- * SPEAr320 Machine specific definition
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifdef CONFIG_MACH_SPEAR320
-
-#ifndef __MACH_SPEAR320_H
-#define __MACH_SPEAR320_H
-
-#define SPEAR320_EMI_CTRL_BASE UL(0x40000000)
-#define SPEAR320_FSMC_BASE UL(0x4C000000)
-#define SPEAR320_NAND_BASE UL(0x50000000)
-#define SPEAR320_I2S_BASE UL(0x60000000)
-#define SPEAR320_SDHCI_BASE UL(0x70000000)
-#define SPEAR320_CLCD_BASE UL(0x90000000)
-#define SPEAR320_PAR_PORT_BASE UL(0xA0000000)
-#define SPEAR320_CAN0_BASE UL(0xA1000000)
-#define SPEAR320_CAN1_BASE UL(0xA2000000)
-#define SPEAR320_UART1_BASE UL(0xA3000000)
-#define SPEAR320_UART2_BASE UL(0xA4000000)
-#define SPEAR320_SSP0_BASE UL(0xA5000000)
-#define SPEAR320_SSP1_BASE UL(0xA6000000)
-#define SPEAR320_I2C_BASE UL(0xA7000000)
-#define SPEAR320_PWM_BASE UL(0xA8000000)
-#define SPEAR320_SMII0_BASE UL(0xAA000000)
-#define SPEAR320_SMII1_BASE UL(0xAB000000)
-#define SPEAR320_SOC_CONFIG_BASE UL(0xB3000000)
-
-/* Interrupt registers offsets and masks */
-#define SPEAR320_INT_STS_MASK_REG 0x04
-#define SPEAR320_INT_CLR_MASK_REG 0x04
-#define SPEAR320_INT_ENB_MASK_REG 0x08
-#define SPEAR320_GPIO_IRQ_MASK (1 << 0)
-#define SPEAR320_I2S_PLAY_IRQ_MASK (1 << 1)
-#define SPEAR320_I2S_REC_IRQ_MASK (1 << 2)
-#define SPEAR320_EMI_IRQ_MASK (1 << 7)
-#define SPEAR320_CLCD_IRQ_MASK (1 << 8)
-#define SPEAR320_SPP_IRQ_MASK (1 << 9)
-#define SPEAR320_SDHCI_IRQ_MASK (1 << 10)
-#define SPEAR320_CAN_U_IRQ_MASK (1 << 11)
-#define SPEAR320_CAN_L_IRQ_MASK (1 << 12)
-#define SPEAR320_UART1_IRQ_MASK (1 << 13)
-#define SPEAR320_UART2_IRQ_MASK (1 << 14)
-#define SPEAR320_SSP1_IRQ_MASK (1 << 15)
-#define SPEAR320_SSP2_IRQ_MASK (1 << 16)
-#define SPEAR320_SMII0_IRQ_MASK (1 << 17)
-#define SPEAR320_MII1_SMII1_IRQ_MASK (1 << 18)
-#define SPEAR320_WAKEUP_SMII0_IRQ_MASK (1 << 19)
-#define SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK (1 << 20)
-#define SPEAR320_I2C1_IRQ_MASK (1 << 21)
-
-#define SPEAR320_SHIRQ_RAS1_MASK 0x000380
-#define SPEAR320_SHIRQ_RAS3_MASK 0x000007
-#define SPEAR320_SHIRQ_INTRCOMM_RAS_MASK 0x3FF800
-
-#endif /* __MACH_SPEAR320_H */
-
-#endif /* CONFIG_MACH_SPEAR320 */
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index f7db66812abb..f75fe25a620c 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -3,372 +3,62 @@
*
* SPEAr300 machine source file
*
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-#include <linux/types.h>
-#include <linux/amba/pl061.h>
-#include <linux/ptrace.h>
-#include <asm/irq.h>
+#define pr_fmt(fmt) "SPEAr300: " fmt
+
+#include <linux/amba/pl08x.h>
+#include <linux/of_platform.h>
+#include <asm/hardware/vic.h>
+#include <asm/mach/arch.h>
#include <plat/shirq.h>
#include <mach/generic.h>
-#include <mach/hardware.h>
-
-/* pad multiplexing support */
-/* muxing registers */
-#define PAD_MUX_CONFIG_REG 0x00
-#define MODE_CONFIG_REG 0x04
-
-/* modes */
-#define NAND_MODE (1 << 0)
-#define NOR_MODE (1 << 1)
-#define PHOTO_FRAME_MODE (1 << 2)
-#define LEND_IP_PHONE_MODE (1 << 3)
-#define HEND_IP_PHONE_MODE (1 << 4)
-#define LEND_WIFI_PHONE_MODE (1 << 5)
-#define HEND_WIFI_PHONE_MODE (1 << 6)
-#define ATA_PABX_WI2S_MODE (1 << 7)
-#define ATA_PABX_I2S_MODE (1 << 8)
-#define CAML_LCDW_MODE (1 << 9)
-#define CAMU_LCD_MODE (1 << 10)
-#define CAMU_WLCD_MODE (1 << 11)
-#define CAML_LCD_MODE (1 << 12)
-#define ALL_MODES 0x1FFF
-
-struct pmx_mode spear300_nand_mode = {
- .id = NAND_MODE,
- .name = "nand mode",
- .mask = 0x00,
-};
-
-struct pmx_mode spear300_nor_mode = {
- .id = NOR_MODE,
- .name = "nor mode",
- .mask = 0x01,
-};
-
-struct pmx_mode spear300_photo_frame_mode = {
- .id = PHOTO_FRAME_MODE,
- .name = "photo frame mode",
- .mask = 0x02,
-};
-
-struct pmx_mode spear300_lend_ip_phone_mode = {
- .id = LEND_IP_PHONE_MODE,
- .name = "lend ip phone mode",
- .mask = 0x03,
-};
-
-struct pmx_mode spear300_hend_ip_phone_mode = {
- .id = HEND_IP_PHONE_MODE,
- .name = "hend ip phone mode",
- .mask = 0x04,
-};
-
-struct pmx_mode spear300_lend_wifi_phone_mode = {
- .id = LEND_WIFI_PHONE_MODE,
- .name = "lend wifi phone mode",
- .mask = 0x05,
-};
-
-struct pmx_mode spear300_hend_wifi_phone_mode = {
- .id = HEND_WIFI_PHONE_MODE,
- .name = "hend wifi phone mode",
- .mask = 0x06,
-};
-
-struct pmx_mode spear300_ata_pabx_wi2s_mode = {
- .id = ATA_PABX_WI2S_MODE,
- .name = "ata pabx wi2s mode",
- .mask = 0x07,
-};
-
-struct pmx_mode spear300_ata_pabx_i2s_mode = {
- .id = ATA_PABX_I2S_MODE,
- .name = "ata pabx i2s mode",
- .mask = 0x08,
-};
-
-struct pmx_mode spear300_caml_lcdw_mode = {
- .id = CAML_LCDW_MODE,
- .name = "caml lcdw mode",
- .mask = 0x0C,
-};
-
-struct pmx_mode spear300_camu_lcd_mode = {
- .id = CAMU_LCD_MODE,
- .name = "camu lcd mode",
- .mask = 0x0D,
-};
-
-struct pmx_mode spear300_camu_wlcd_mode = {
- .id = CAMU_WLCD_MODE,
- .name = "camu wlcd mode",
- .mask = 0x0E,
-};
-
-struct pmx_mode spear300_caml_lcd_mode = {
- .id = CAML_LCD_MODE,
- .name = "caml lcd mode",
- .mask = 0x0F,
-};
-
-/* devices */
-static struct pmx_dev_mode pmx_fsmc_2_chips_modes[] = {
- {
- .ids = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE |
- ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE,
- .mask = PMX_FIRDA_MASK,
- },
-};
-
-struct pmx_dev spear300_pmx_fsmc_2_chips = {
- .name = "fsmc_2_chips",
- .modes = pmx_fsmc_2_chips_modes,
- .mode_count = ARRAY_SIZE(pmx_fsmc_2_chips_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_fsmc_4_chips_modes[] = {
- {
- .ids = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE |
- ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE,
- .mask = PMX_FIRDA_MASK | PMX_UART0_MASK,
- },
-};
-
-struct pmx_dev spear300_pmx_fsmc_4_chips = {
- .name = "fsmc_4_chips",
- .modes = pmx_fsmc_4_chips_modes,
- .mode_count = ARRAY_SIZE(pmx_fsmc_4_chips_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_keyboard_modes[] = {
- {
- .ids = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE |
- LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE |
- CAML_LCDW_MODE | CAMU_LCD_MODE | CAMU_WLCD_MODE |
- CAML_LCD_MODE,
- .mask = 0x0,
- },
-};
-
-struct pmx_dev spear300_pmx_keyboard = {
- .name = "keyboard",
- .modes = pmx_keyboard_modes,
- .mode_count = ARRAY_SIZE(pmx_keyboard_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_clcd_modes[] = {
- {
- .ids = PHOTO_FRAME_MODE,
- .mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK ,
- }, {
- .ids = HEND_IP_PHONE_MODE | HEND_WIFI_PHONE_MODE |
- CAMU_LCD_MODE | CAML_LCD_MODE,
- .mask = PMX_TIMER_3_4_MASK,
- },
-};
-
-struct pmx_dev spear300_pmx_clcd = {
- .name = "clcd",
- .modes = pmx_clcd_modes,
- .mode_count = ARRAY_SIZE(pmx_clcd_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_telecom_gpio_modes[] = {
- {
- .ids = PHOTO_FRAME_MODE | CAMU_LCD_MODE | CAML_LCD_MODE,
- .mask = PMX_MII_MASK,
- }, {
- .ids = LEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE,
- .mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
- }, {
- .ids = ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_WLCD_MODE,
- .mask = PMX_MII_MASK | PMX_TIMER_3_4_MASK,
- }, {
- .ids = HEND_IP_PHONE_MODE | HEND_WIFI_PHONE_MODE,
- .mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK,
- }, {
- .ids = ATA_PABX_WI2S_MODE,
- .mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK
- | PMX_UART0_MODEM_MASK,
- },
-};
-
-struct pmx_dev spear300_pmx_telecom_gpio = {
- .name = "telecom_gpio",
- .modes = pmx_telecom_gpio_modes,
- .mode_count = ARRAY_SIZE(pmx_telecom_gpio_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_telecom_tdm_modes[] = {
- {
- .ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
- HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE
- | HEND_WIFI_PHONE_MODE | ATA_PABX_WI2S_MODE
- | ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
- | CAMU_WLCD_MODE | CAML_LCD_MODE,
- .mask = PMX_UART0_MODEM_MASK | PMX_SSP_CS_MASK,
- },
-};
-
-struct pmx_dev spear300_pmx_telecom_tdm = {
- .name = "telecom_tdm",
- .modes = pmx_telecom_tdm_modes,
- .mode_count = ARRAY_SIZE(pmx_telecom_tdm_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_telecom_spi_cs_i2c_clk_modes[] = {
- {
- .ids = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE |
- LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE
- | ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE |
- CAML_LCDW_MODE | CAML_LCD_MODE,
- .mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
- },
-};
-
-struct pmx_dev spear300_pmx_telecom_spi_cs_i2c_clk = {
- .name = "telecom_spi_cs_i2c_clk",
- .modes = pmx_telecom_spi_cs_i2c_clk_modes,
- .mode_count = ARRAY_SIZE(pmx_telecom_spi_cs_i2c_clk_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_telecom_camera_modes[] = {
- {
- .ids = CAML_LCDW_MODE | CAML_LCD_MODE,
- .mask = PMX_MII_MASK,
- }, {
- .ids = CAMU_LCD_MODE | CAMU_WLCD_MODE,
- .mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK | PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear300_pmx_telecom_camera = {
- .name = "telecom_camera",
- .modes = pmx_telecom_camera_modes,
- .mode_count = ARRAY_SIZE(pmx_telecom_camera_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_telecom_dac_modes[] = {
- {
- .ids = ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
- | CAMU_WLCD_MODE | CAML_LCD_MODE,
- .mask = PMX_TIMER_1_2_MASK,
- },
-};
-
-struct pmx_dev spear300_pmx_telecom_dac = {
- .name = "telecom_dac",
- .modes = pmx_telecom_dac_modes,
- .mode_count = ARRAY_SIZE(pmx_telecom_dac_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_telecom_i2s_modes[] = {
- {
- .ids = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE
- | LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE |
- ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
- | CAMU_WLCD_MODE | CAML_LCD_MODE,
- .mask = PMX_UART0_MODEM_MASK,
- },
-};
-
-struct pmx_dev spear300_pmx_telecom_i2s = {
- .name = "telecom_i2s",
- .modes = pmx_telecom_i2s_modes,
- .mode_count = ARRAY_SIZE(pmx_telecom_i2s_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_telecom_boot_pins_modes[] = {
- {
- .ids = NAND_MODE | NOR_MODE,
- .mask = PMX_UART0_MODEM_MASK | PMX_TIMER_1_2_MASK |
- PMX_TIMER_3_4_MASK,
- },
-};
-
-struct pmx_dev spear300_pmx_telecom_boot_pins = {
- .name = "telecom_boot_pins",
- .modes = pmx_telecom_boot_pins_modes,
- .mode_count = ARRAY_SIZE(pmx_telecom_boot_pins_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_telecom_sdhci_4bit_modes[] = {
- {
- .ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
- HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
- HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE |
- CAMU_WLCD_MODE | CAML_LCD_MODE | ATA_PABX_WI2S_MODE |
- ATA_PABX_I2S_MODE,
- .mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
- PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
- PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
- },
-};
-
-struct pmx_dev spear300_pmx_telecom_sdhci_4bit = {
- .name = "telecom_sdhci_4bit",
- .modes = pmx_telecom_sdhci_4bit_modes,
- .mode_count = ARRAY_SIZE(pmx_telecom_sdhci_4bit_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_telecom_sdhci_8bit_modes[] = {
- {
- .ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
- HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
- HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE |
- CAMU_WLCD_MODE | CAML_LCD_MODE,
- .mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
- PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
- PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK | PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear300_pmx_telecom_sdhci_8bit = {
- .name = "telecom_sdhci_8bit",
- .modes = pmx_telecom_sdhci_8bit_modes,
- .mode_count = ARRAY_SIZE(pmx_telecom_sdhci_8bit_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_gpio1_modes[] = {
- {
- .ids = PHOTO_FRAME_MODE,
- .mask = PMX_UART0_MODEM_MASK | PMX_TIMER_1_2_MASK |
- PMX_TIMER_3_4_MASK,
- },
-};
-
-struct pmx_dev spear300_pmx_gpio1 = {
- .name = "arm gpio1",
- .modes = pmx_gpio1_modes,
- .mode_count = ARRAY_SIZE(pmx_gpio1_modes),
- .enb_on_reset = 1,
-};
-
-/* pmx driver structure */
-static struct pmx_driver pmx_driver = {
- .mode_reg = {.offset = MODE_CONFIG_REG, .mask = 0x0000000f},
- .mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
-};
+#include <mach/spear.h>
+
+/* Base address of various IPs */
+#define SPEAR300_TELECOM_BASE UL(0x50000000)
+
+/* Interrupt registers offsets and masks */
+#define SPEAR300_INT_ENB_MASK_REG 0x54
+#define SPEAR300_INT_STS_MASK_REG 0x58
+#define SPEAR300_IT_PERS_S_IRQ_MASK (1 << 0)
+#define SPEAR300_IT_CHANGE_S_IRQ_MASK (1 << 1)
+#define SPEAR300_I2S_IRQ_MASK (1 << 2)
+#define SPEAR300_TDM_IRQ_MASK (1 << 3)
+#define SPEAR300_CAMERA_L_IRQ_MASK (1 << 4)
+#define SPEAR300_CAMERA_F_IRQ_MASK (1 << 5)
+#define SPEAR300_CAMERA_V_IRQ_MASK (1 << 6)
+#define SPEAR300_KEYBOARD_IRQ_MASK (1 << 7)
+#define SPEAR300_GPIO1_IRQ_MASK (1 << 8)
+
+#define SPEAR300_SHIRQ_RAS1_MASK 0x1FF
+
+#define SPEAR300_SOC_CONFIG_BASE UL(0x99000000)
+
+
+/* SPEAr300 Virtual irq definitions */
+/* IRQs sharing IRQ_GEN_RAS_1 */
+#define SPEAR300_VIRQ_IT_PERS_S (SPEAR3XX_VIRQ_START + 0)
+#define SPEAR300_VIRQ_IT_CHANGE_S (SPEAR3XX_VIRQ_START + 1)
+#define SPEAR300_VIRQ_I2S (SPEAR3XX_VIRQ_START + 2)
+#define SPEAR300_VIRQ_TDM (SPEAR3XX_VIRQ_START + 3)
+#define SPEAR300_VIRQ_CAMERA_L (SPEAR3XX_VIRQ_START + 4)
+#define SPEAR300_VIRQ_CAMERA_F (SPEAR3XX_VIRQ_START + 5)
+#define SPEAR300_VIRQ_CAMERA_V (SPEAR3XX_VIRQ_START + 6)
+#define SPEAR300_VIRQ_KEYBOARD (SPEAR3XX_VIRQ_START + 7)
+#define SPEAR300_VIRQ_GPIO1 (SPEAR3XX_VIRQ_START + 8)
+
+/* IRQs sharing IRQ_GEN_RAS_3 */
+#define SPEAR300_IRQ_CLCD SPEAR3XX_IRQ_GEN_RAS_3
+
+/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
+#define SPEAR300_IRQ_SDHCI SPEAR3XX_IRQ_INTRCOMM_RAS_ARM
/* spear3xx shared irq */
static struct shirq_dev_config shirq_ras1_config[] = {
@@ -423,45 +113,239 @@ static struct spear_shirq shirq_ras1 = {
},
};
-/* Add spear300 specific devices here */
-/* arm gpio1 device registration */
-static struct pl061_platform_data gpio1_plat_data = {
- .gpio_base = 8,
- .irq_base = SPEAR300_GPIO1_INT_BASE,
+/* DMAC platform data's slave info */
+struct pl08x_channel_data spear300_dma_info[] = {
+ {
+ .bus_id = "uart0_rx",
+ .min_signal = 2,
+ .max_signal = 2,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart0_tx",
+ .min_signal = 3,
+ .max_signal = 3,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ssp0_rx",
+ .min_signal = 8,
+ .max_signal = 8,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ssp0_tx",
+ .min_signal = 9,
+ .max_signal = 9,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "i2c_rx",
+ .min_signal = 10,
+ .max_signal = 10,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "i2c_tx",
+ .min_signal = 11,
+ .max_signal = 11,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "irda",
+ .min_signal = 12,
+ .max_signal = 12,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "adc",
+ .min_signal = 13,
+ .max_signal = 13,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "to_jpeg",
+ .min_signal = 14,
+ .max_signal = 14,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "from_jpeg",
+ .min_signal = 15,
+ .max_signal = 15,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras0_rx",
+ .min_signal = 0,
+ .max_signal = 0,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras0_tx",
+ .min_signal = 1,
+ .max_signal = 1,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras1_rx",
+ .min_signal = 2,
+ .max_signal = 2,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras1_tx",
+ .min_signal = 3,
+ .max_signal = 3,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras2_rx",
+ .min_signal = 4,
+ .max_signal = 4,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras2_tx",
+ .min_signal = 5,
+ .max_signal = 5,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras3_rx",
+ .min_signal = 6,
+ .max_signal = 6,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras3_tx",
+ .min_signal = 7,
+ .max_signal = 7,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras4_rx",
+ .min_signal = 8,
+ .max_signal = 8,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras4_tx",
+ .min_signal = 9,
+ .max_signal = 9,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras5_rx",
+ .min_signal = 10,
+ .max_signal = 10,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras5_tx",
+ .min_signal = 11,
+ .max_signal = 11,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras6_rx",
+ .min_signal = 12,
+ .max_signal = 12,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras6_tx",
+ .min_signal = 13,
+ .max_signal = 13,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras7_rx",
+ .min_signal = 14,
+ .max_signal = 14,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras7_tx",
+ .min_signal = 15,
+ .max_signal = 15,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ },
};
-AMBA_APB_DEVICE(spear300_gpio1, "gpio1", 0, SPEAR300_GPIO_BASE,
- {SPEAR300_VIRQ_GPIO1}, &gpio1_plat_data);
+/* Add SPEAr300 auxdata to pass platform data */
+static struct of_dev_auxdata spear300_auxdata_lookup[] __initdata = {
+ OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
+ &pl022_plat_data),
+ OF_DEV_AUXDATA("arm,pl080", SPEAR3XX_ICM3_DMA_BASE, NULL,
+ &pl080_plat_data),
+ {}
+};
-/* spear300 routines */
-void __init spear300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
- u8 pmx_dev_count)
+static void __init spear300_dt_init(void)
{
- int ret = 0;
+ int ret;
+
+ pl080_plat_data.slave_channels = spear300_dma_info;
+ pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear300_dma_info);
- /* call spear3xx family common init function */
- spear3xx_init();
+ of_platform_populate(NULL, of_default_bus_match_table,
+ spear300_auxdata_lookup, NULL);
/* shared irq registration */
shirq_ras1.regs.base = ioremap(SPEAR300_TELECOM_BASE, SZ_4K);
if (shirq_ras1.regs.base) {
ret = spear_shirq_register(&shirq_ras1);
if (ret)
- printk(KERN_ERR "Error registering Shared IRQ\n");
+ pr_err("Error registering Shared IRQ\n");
}
+}
- /* pmx initialization */
- pmx_driver.mode = pmx_mode;
- pmx_driver.devs = pmx_devs;
- pmx_driver.devs_count = pmx_dev_count;
+static const char * const spear300_dt_board_compat[] = {
+ "st,spear300",
+ "st,spear300-evb",
+ NULL,
+};
- pmx_driver.base = ioremap(SPEAR300_SOC_CONFIG_BASE, SZ_4K);
- if (pmx_driver.base) {
- ret = pmx_register(&pmx_driver);
- if (ret)
- printk(KERN_ERR "padmux: registration failed. err no"
- ": %d\n", ret);
- /* Free Mapping, device selection already done */
- iounmap(pmx_driver.base);
- }
+static void __init spear300_map_io(void)
+{
+ spear3xx_map_io();
+ spear300_clk_init();
}
+
+DT_MACHINE_START(SPEAR300_DT, "ST SPEAr300 SoC with Flattened Device Tree")
+ .map_io = spear300_map_io,
+ .init_irq = spear3xx_dt_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &spear3xx_timer,
+ .init_machine = spear300_dt_init,
+ .restart = spear_restart,
+ .dt_compat = spear300_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
deleted file mode 100644
index 3462ab9d6122..000000000000
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/spear300_evb.c
- *
- * SPEAr300 evaluation board source file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <asm/hardware/vic.h>
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-#include <mach/generic.h>
-#include <mach/hardware.h>
-
-/* padmux devices to enable */
-static struct pmx_dev *pmx_devs[] = {
- /* spear3xx specific devices */
- &spear3xx_pmx_i2c,
- &spear3xx_pmx_ssp_cs,
- &spear3xx_pmx_ssp,
- &spear3xx_pmx_mii,
- &spear3xx_pmx_uart0,
-
- /* spear300 specific devices */
- &spear300_pmx_fsmc_2_chips,
- &spear300_pmx_clcd,
- &spear300_pmx_telecom_sdhci_4bit,
- &spear300_pmx_gpio1,
-};
-
-static struct amba_device *amba_devs[] __initdata = {
- /* spear3xx specific devices */
- &spear3xx_gpio_device,
- &spear3xx_uart_device,
-
- /* spear300 specific devices */
- &spear300_gpio1_device,
-};
-
-static struct platform_device *plat_devs[] __initdata = {
- /* spear3xx specific devices */
-
- /* spear300 specific devices */
-};
-
-static void __init spear300_evb_init(void)
-{
- unsigned int i;
-
- /* call spear300 machine init function */
- spear300_init(&spear300_photo_frame_mode, pmx_devs,
- ARRAY_SIZE(pmx_devs));
-
- /* Add Platform Devices */
- platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
-
- /* Add Amba Devices */
- for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
- amba_device_register(amba_devs[i], &iomem_resource);
-}
-
-MACHINE_START(SPEAR300, "ST-SPEAR300-EVB")
- .atag_offset = 0x100,
- .map_io = spear3xx_map_io,
- .init_irq = spear3xx_init_irq,
- .handle_irq = vic_handle_irq,
- .timer = &spear3xx_timer,
- .init_machine = spear300_evb_init,
- .restart = spear_restart,
-MACHINE_END
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index febaa6fcfb6a..f0842a58dc02 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -3,141 +3,84 @@
*
* SPEAr310 machine source file
*
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-#include <linux/ptrace.h>
-#include <asm/irq.h>
+#define pr_fmt(fmt) "SPEAr310: " fmt
+
+#include <linux/amba/pl08x.h>
+#include <linux/amba/serial.h>
+#include <linux/of_platform.h>
+#include <asm/hardware/vic.h>
+#include <asm/mach/arch.h>
#include <plat/shirq.h>
#include <mach/generic.h>
-#include <mach/hardware.h>
-
-/* pad multiplexing support */
-/* muxing registers */
-#define PAD_MUX_CONFIG_REG 0x08
-
-/* devices */
-static struct pmx_dev_mode pmx_emi_cs_0_1_4_5_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_TIMER_3_4_MASK,
- },
-};
-
-struct pmx_dev spear310_pmx_emi_cs_0_1_4_5 = {
- .name = "emi_cs_0_1_4_5",
- .modes = pmx_emi_cs_0_1_4_5_modes,
- .mode_count = ARRAY_SIZE(pmx_emi_cs_0_1_4_5_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_emi_cs_2_3_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_TIMER_1_2_MASK,
- },
-};
-
-struct pmx_dev spear310_pmx_emi_cs_2_3 = {
- .name = "emi_cs_2_3",
- .modes = pmx_emi_cs_2_3_modes,
- .mode_count = ARRAY_SIZE(pmx_emi_cs_2_3_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_uart1_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_FIRDA_MASK,
- },
-};
-
-struct pmx_dev spear310_pmx_uart1 = {
- .name = "uart1",
- .modes = pmx_uart1_modes,
- .mode_count = ARRAY_SIZE(pmx_uart1_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_uart2_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_TIMER_1_2_MASK,
- },
-};
-
-struct pmx_dev spear310_pmx_uart2 = {
- .name = "uart2",
- .modes = pmx_uart2_modes,
- .mode_count = ARRAY_SIZE(pmx_uart2_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_uart3_4_5_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_UART0_MODEM_MASK,
- },
-};
-
-struct pmx_dev spear310_pmx_uart3_4_5 = {
- .name = "uart3_4_5",
- .modes = pmx_uart3_4_5_modes,
- .mode_count = ARRAY_SIZE(pmx_uart3_4_5_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_fsmc_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_SSP_CS_MASK,
- },
-};
-
-struct pmx_dev spear310_pmx_fsmc = {
- .name = "fsmc",
- .modes = pmx_fsmc_modes,
- .mode_count = ARRAY_SIZE(pmx_fsmc_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_rs485_0_1_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear310_pmx_rs485_0_1 = {
- .name = "rs485_0_1",
- .modes = pmx_rs485_0_1_modes,
- .mode_count = ARRAY_SIZE(pmx_rs485_0_1_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_tdm0_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear310_pmx_tdm0 = {
- .name = "tdm0",
- .modes = pmx_tdm0_modes,
- .mode_count = ARRAY_SIZE(pmx_tdm0_modes),
- .enb_on_reset = 1,
-};
+#include <mach/spear.h>
+
+#define SPEAR310_UART1_BASE UL(0xB2000000)
+#define SPEAR310_UART2_BASE UL(0xB2080000)
+#define SPEAR310_UART3_BASE UL(0xB2100000)
+#define SPEAR310_UART4_BASE UL(0xB2180000)
+#define SPEAR310_UART5_BASE UL(0xB2200000)
+#define SPEAR310_SOC_CONFIG_BASE UL(0xB4000000)
+
+/* Interrupt registers offsets and masks */
+#define SPEAR310_INT_STS_MASK_REG 0x04
+#define SPEAR310_SMII0_IRQ_MASK (1 << 0)
+#define SPEAR310_SMII1_IRQ_MASK (1 << 1)
+#define SPEAR310_SMII2_IRQ_MASK (1 << 2)
+#define SPEAR310_SMII3_IRQ_MASK (1 << 3)
+#define SPEAR310_WAKEUP_SMII0_IRQ_MASK (1 << 4)
+#define SPEAR310_WAKEUP_SMII1_IRQ_MASK (1 << 5)
+#define SPEAR310_WAKEUP_SMII2_IRQ_MASK (1 << 6)
+#define SPEAR310_WAKEUP_SMII3_IRQ_MASK (1 << 7)
+#define SPEAR310_UART1_IRQ_MASK (1 << 8)
+#define SPEAR310_UART2_IRQ_MASK (1 << 9)
+#define SPEAR310_UART3_IRQ_MASK (1 << 10)
+#define SPEAR310_UART4_IRQ_MASK (1 << 11)
+#define SPEAR310_UART5_IRQ_MASK (1 << 12)
+#define SPEAR310_EMI_IRQ_MASK (1 << 13)
+#define SPEAR310_TDM_HDLC_IRQ_MASK (1 << 14)
+#define SPEAR310_RS485_0_IRQ_MASK (1 << 15)
+#define SPEAR310_RS485_1_IRQ_MASK (1 << 16)
+
+#define SPEAR310_SHIRQ_RAS1_MASK 0x000FF
+#define SPEAR310_SHIRQ_RAS2_MASK 0x01F00
+#define SPEAR310_SHIRQ_RAS3_MASK 0x02000
+#define SPEAR310_SHIRQ_INTRCOMM_RAS_MASK 0x1C000
+
+/* SPEAr310 Virtual irq definitions */
+/* IRQs sharing IRQ_GEN_RAS_1 */
+#define SPEAR310_VIRQ_SMII0 (SPEAR3XX_VIRQ_START + 0)
+#define SPEAR310_VIRQ_SMII1 (SPEAR3XX_VIRQ_START + 1)
+#define SPEAR310_VIRQ_SMII2 (SPEAR3XX_VIRQ_START + 2)
+#define SPEAR310_VIRQ_SMII3 (SPEAR3XX_VIRQ_START + 3)
+#define SPEAR310_VIRQ_WAKEUP_SMII0 (SPEAR3XX_VIRQ_START + 4)
+#define SPEAR310_VIRQ_WAKEUP_SMII1 (SPEAR3XX_VIRQ_START + 5)
+#define SPEAR310_VIRQ_WAKEUP_SMII2 (SPEAR3XX_VIRQ_START + 6)
+#define SPEAR310_VIRQ_WAKEUP_SMII3 (SPEAR3XX_VIRQ_START + 7)
+
+/* IRQs sharing IRQ_GEN_RAS_2 */
+#define SPEAR310_VIRQ_UART1 (SPEAR3XX_VIRQ_START + 8)
+#define SPEAR310_VIRQ_UART2 (SPEAR3XX_VIRQ_START + 9)
+#define SPEAR310_VIRQ_UART3 (SPEAR3XX_VIRQ_START + 10)
+#define SPEAR310_VIRQ_UART4 (SPEAR3XX_VIRQ_START + 11)
+#define SPEAR310_VIRQ_UART5 (SPEAR3XX_VIRQ_START + 12)
+
+/* IRQs sharing IRQ_GEN_RAS_3 */
+#define SPEAR310_VIRQ_EMI (SPEAR3XX_VIRQ_START + 13)
+#define SPEAR310_VIRQ_PLGPIO (SPEAR3XX_VIRQ_START + 14)
+
+/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
+#define SPEAR310_VIRQ_TDM_HDLC (SPEAR3XX_VIRQ_START + 15)
+#define SPEAR310_VIRQ_RS485_0 (SPEAR3XX_VIRQ_START + 16)
+#define SPEAR310_VIRQ_RS485_1 (SPEAR3XX_VIRQ_START + 17)
-/* pmx driver structure */
-static struct pmx_driver pmx_driver = {
- .mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
-};
/* spear3xx shared irq */
static struct shirq_dev_config shirq_ras1_config[] = {
@@ -255,17 +198,247 @@ static struct spear_shirq shirq_intrcomm_ras = {
},
};
-/* Add spear310 specific devices here */
+/* DMAC platform data's slave info */
+struct pl08x_channel_data spear310_dma_info[] = {
+ {
+ .bus_id = "uart0_rx",
+ .min_signal = 2,
+ .max_signal = 2,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart0_tx",
+ .min_signal = 3,
+ .max_signal = 3,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ssp0_rx",
+ .min_signal = 8,
+ .max_signal = 8,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ssp0_tx",
+ .min_signal = 9,
+ .max_signal = 9,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "i2c_rx",
+ .min_signal = 10,
+ .max_signal = 10,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "i2c_tx",
+ .min_signal = 11,
+ .max_signal = 11,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "irda",
+ .min_signal = 12,
+ .max_signal = 12,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "adc",
+ .min_signal = 13,
+ .max_signal = 13,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "to_jpeg",
+ .min_signal = 14,
+ .max_signal = 14,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "from_jpeg",
+ .min_signal = 15,
+ .max_signal = 15,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart1_rx",
+ .min_signal = 0,
+ .max_signal = 0,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart1_tx",
+ .min_signal = 1,
+ .max_signal = 1,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart2_rx",
+ .min_signal = 2,
+ .max_signal = 2,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart2_tx",
+ .min_signal = 3,
+ .max_signal = 3,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart3_rx",
+ .min_signal = 4,
+ .max_signal = 4,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart3_tx",
+ .min_signal = 5,
+ .max_signal = 5,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart4_rx",
+ .min_signal = 6,
+ .max_signal = 6,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart4_tx",
+ .min_signal = 7,
+ .max_signal = 7,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart5_rx",
+ .min_signal = 8,
+ .max_signal = 8,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart5_tx",
+ .min_signal = 9,
+ .max_signal = 9,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras5_rx",
+ .min_signal = 10,
+ .max_signal = 10,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras5_tx",
+ .min_signal = 11,
+ .max_signal = 11,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras6_rx",
+ .min_signal = 12,
+ .max_signal = 12,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras6_tx",
+ .min_signal = 13,
+ .max_signal = 13,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras7_rx",
+ .min_signal = 14,
+ .max_signal = 14,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras7_tx",
+ .min_signal = 15,
+ .max_signal = 15,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ },
+};
-/* spear310 routines */
-void __init spear310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
- u8 pmx_dev_count)
+/* uart devices plat data */
+static struct amba_pl011_data spear310_uart_data[] = {
+ {
+ .dma_filter = pl08x_filter_id,
+ .dma_tx_param = "uart1_tx",
+ .dma_rx_param = "uart1_rx",
+ }, {
+ .dma_filter = pl08x_filter_id,
+ .dma_tx_param = "uart2_tx",
+ .dma_rx_param = "uart2_rx",
+ }, {
+ .dma_filter = pl08x_filter_id,
+ .dma_tx_param = "uart3_tx",
+ .dma_rx_param = "uart3_rx",
+ }, {
+ .dma_filter = pl08x_filter_id,
+ .dma_tx_param = "uart4_tx",
+ .dma_rx_param = "uart4_rx",
+ }, {
+ .dma_filter = pl08x_filter_id,
+ .dma_tx_param = "uart5_tx",
+ .dma_rx_param = "uart5_rx",
+ },
+};
+
+/* Add SPEAr310 auxdata to pass platform data */
+static struct of_dev_auxdata spear310_auxdata_lookup[] __initdata = {
+ OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
+ &pl022_plat_data),
+ OF_DEV_AUXDATA("arm,pl080", SPEAR3XX_ICM3_DMA_BASE, NULL,
+ &pl080_plat_data),
+ OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART1_BASE, NULL,
+ &spear310_uart_data[0]),
+ OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART2_BASE, NULL,
+ &spear310_uart_data[1]),
+ OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART3_BASE, NULL,
+ &spear310_uart_data[2]),
+ OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART4_BASE, NULL,
+ &spear310_uart_data[3]),
+ OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART5_BASE, NULL,
+ &spear310_uart_data[4]),
+ {}
+};
+
+static void __init spear310_dt_init(void)
{
void __iomem *base;
- int ret = 0;
+ int ret;
- /* call spear3xx family common init function */
- spear3xx_init();
+ pl080_plat_data.slave_channels = spear310_dma_info;
+ pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear310_dma_info);
+
+ of_platform_populate(NULL, of_default_bus_match_table,
+ spear310_auxdata_lookup, NULL);
/* shared irq registration */
base = ioremap(SPEAR310_SOC_CONFIG_BASE, SZ_4K);
@@ -274,35 +447,46 @@ void __init spear310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
shirq_ras1.regs.base = base;
ret = spear_shirq_register(&shirq_ras1);
if (ret)
- printk(KERN_ERR "Error registering Shared IRQ 1\n");
+ pr_err("Error registering Shared IRQ 1\n");
/* shirq 2 */
shirq_ras2.regs.base = base;
ret = spear_shirq_register(&shirq_ras2);
if (ret)
- printk(KERN_ERR "Error registering Shared IRQ 2\n");
+ pr_err("Error registering Shared IRQ 2\n");
/* shirq 3 */
shirq_ras3.regs.base = base;
ret = spear_shirq_register(&shirq_ras3);
if (ret)
- printk(KERN_ERR "Error registering Shared IRQ 3\n");
+ pr_err("Error registering Shared IRQ 3\n");
/* shirq 4 */
shirq_intrcomm_ras.regs.base = base;
ret = spear_shirq_register(&shirq_intrcomm_ras);
if (ret)
- printk(KERN_ERR "Error registering Shared IRQ 4\n");
+ pr_err("Error registering Shared IRQ 4\n");
}
+}
- /* pmx initialization */
- pmx_driver.base = base;
- pmx_driver.mode = pmx_mode;
- pmx_driver.devs = pmx_devs;
- pmx_driver.devs_count = pmx_dev_count;
+static const char * const spear310_dt_board_compat[] = {
+ "st,spear310",
+ "st,spear310-evb",
+ NULL,
+};
- ret = pmx_register(&pmx_driver);
- if (ret)
- printk(KERN_ERR "padmux: registration failed. err no: %d\n",
- ret);
+static void __init spear310_map_io(void)
+{
+ spear3xx_map_io();
+ spear310_clk_init();
}
+
+DT_MACHINE_START(SPEAR310_DT, "ST SPEAr310 SoC with Flattened Device Tree")
+ .map_io = spear310_map_io,
+ .init_irq = spear3xx_dt_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &spear3xx_timer,
+ .init_machine = spear310_dt_init,
+ .restart = spear_restart,
+ .dt_compat = spear310_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
deleted file mode 100644
index f92c4993f65a..000000000000
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/spear310_evb.c
- *
- * SPEAr310 evaluation board source file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <asm/hardware/vic.h>
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-#include <mach/generic.h>
-#include <mach/hardware.h>
-
-/* padmux devices to enable */
-static struct pmx_dev *pmx_devs[] = {
- /* spear3xx specific devices */
- &spear3xx_pmx_i2c,
- &spear3xx_pmx_ssp,
- &spear3xx_pmx_gpio_pin0,
- &spear3xx_pmx_gpio_pin1,
- &spear3xx_pmx_gpio_pin2,
- &spear3xx_pmx_gpio_pin3,
- &spear3xx_pmx_gpio_pin4,
- &spear3xx_pmx_gpio_pin5,
- &spear3xx_pmx_uart0,
-
- /* spear310 specific devices */
- &spear310_pmx_emi_cs_0_1_4_5,
- &spear310_pmx_emi_cs_2_3,
- &spear310_pmx_uart1,
- &spear310_pmx_uart2,
- &spear310_pmx_uart3_4_5,
- &spear310_pmx_fsmc,
- &spear310_pmx_rs485_0_1,
- &spear310_pmx_tdm0,
-};
-
-static struct amba_device *amba_devs[] __initdata = {
- /* spear3xx specific devices */
- &spear3xx_gpio_device,
- &spear3xx_uart_device,
-
- /* spear310 specific devices */
-};
-
-static struct platform_device *plat_devs[] __initdata = {
- /* spear3xx specific devices */
-
- /* spear310 specific devices */
-};
-
-static void __init spear310_evb_init(void)
-{
- unsigned int i;
-
- /* call spear310 machine init function */
- spear310_init(NULL, pmx_devs, ARRAY_SIZE(pmx_devs));
-
- /* Add Platform Devices */
- platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
-
- /* Add Amba Devices */
- for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
- amba_device_register(amba_devs[i], &iomem_resource);
-}
-
-MACHINE_START(SPEAR310, "ST-SPEAR310-EVB")
- .atag_offset = 0x100,
- .map_io = spear3xx_map_io,
- .init_irq = spear3xx_init_irq,
- .handle_irq = vic_handle_irq,
- .timer = &spear3xx_timer,
- .init_machine = spear310_evb_init,
- .restart = spear_restart,
-MACHINE_END
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index deaaf199612c..e8caeef50a5c 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -3,386 +3,85 @@
*
* SPEAr320 machine source file
*
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-#include <linux/ptrace.h>
-#include <asm/irq.h>
+#define pr_fmt(fmt) "SPEAr320: " fmt
+
+#include <linux/amba/pl022.h>
+#include <linux/amba/pl08x.h>
+#include <linux/amba/serial.h>
+#include <linux/of_platform.h>
+#include <asm/hardware/vic.h>
+#include <asm/mach/arch.h>
#include <plat/shirq.h>
#include <mach/generic.h>
-#include <mach/hardware.h>
-
-/* pad multiplexing support */
-/* muxing registers */
-#define PAD_MUX_CONFIG_REG 0x0C
-#define MODE_CONFIG_REG 0x10
-
-/* modes */
-#define AUTO_NET_SMII_MODE (1 << 0)
-#define AUTO_NET_MII_MODE (1 << 1)
-#define AUTO_EXP_MODE (1 << 2)
-#define SMALL_PRINTERS_MODE (1 << 3)
-#define ALL_MODES 0xF
-
-struct pmx_mode spear320_auto_net_smii_mode = {
- .id = AUTO_NET_SMII_MODE,
- .name = "Automation Networking SMII Mode",
- .mask = 0x00,
-};
-
-struct pmx_mode spear320_auto_net_mii_mode = {
- .id = AUTO_NET_MII_MODE,
- .name = "Automation Networking MII Mode",
- .mask = 0x01,
-};
-
-struct pmx_mode spear320_auto_exp_mode = {
- .id = AUTO_EXP_MODE,
- .name = "Automation Expanded Mode",
- .mask = 0x02,
-};
-
-struct pmx_mode spear320_small_printers_mode = {
- .id = SMALL_PRINTERS_MODE,
- .name = "Small Printers Mode",
- .mask = 0x03,
-};
-
-/* devices */
-static struct pmx_dev_mode pmx_clcd_modes[] = {
- {
- .ids = AUTO_NET_SMII_MODE,
- .mask = 0x0,
- },
-};
-
-struct pmx_dev spear320_pmx_clcd = {
- .name = "clcd",
- .modes = pmx_clcd_modes,
- .mode_count = ARRAY_SIZE(pmx_clcd_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_emi_modes[] = {
- {
- .ids = AUTO_EXP_MODE,
- .mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_emi = {
- .name = "emi",
- .modes = pmx_emi_modes,
- .mode_count = ARRAY_SIZE(pmx_emi_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_fsmc_modes[] = {
- {
- .ids = ALL_MODES,
- .mask = 0x0,
- },
-};
-
-struct pmx_dev spear320_pmx_fsmc = {
- .name = "fsmc",
- .modes = pmx_fsmc_modes,
- .mode_count = ARRAY_SIZE(pmx_fsmc_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_spp_modes[] = {
- {
- .ids = SMALL_PRINTERS_MODE,
- .mask = 0x0,
- },
-};
-
-struct pmx_dev spear320_pmx_spp = {
- .name = "spp",
- .modes = pmx_spp_modes,
- .mode_count = ARRAY_SIZE(pmx_spp_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_sdhci_modes[] = {
- {
- .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE |
- SMALL_PRINTERS_MODE,
- .mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_sdhci = {
- .name = "sdhci",
- .modes = pmx_sdhci_modes,
- .mode_count = ARRAY_SIZE(pmx_sdhci_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_i2s_modes[] = {
- {
- .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
- .mask = PMX_UART0_MODEM_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_i2s = {
- .name = "i2s",
- .modes = pmx_i2s_modes,
- .mode_count = ARRAY_SIZE(pmx_i2s_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_uart1_modes[] = {
- {
- .ids = ALL_MODES,
- .mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_uart1 = {
- .name = "uart1",
- .modes = pmx_uart1_modes,
- .mode_count = ARRAY_SIZE(pmx_uart1_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_uart1_modem_modes[] = {
- {
- .ids = AUTO_EXP_MODE,
- .mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK |
- PMX_SSP_CS_MASK,
- }, {
- .ids = SMALL_PRINTERS_MODE,
- .mask = PMX_GPIO_PIN3_MASK | PMX_GPIO_PIN4_MASK |
- PMX_GPIO_PIN5_MASK | PMX_SSP_CS_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_uart1_modem = {
- .name = "uart1_modem",
- .modes = pmx_uart1_modem_modes,
- .mode_count = ARRAY_SIZE(pmx_uart1_modem_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_uart2_modes[] = {
- {
- .ids = ALL_MODES,
- .mask = PMX_FIRDA_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_uart2 = {
- .name = "uart2",
- .modes = pmx_uart2_modes,
- .mode_count = ARRAY_SIZE(pmx_uart2_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_touchscreen_modes[] = {
- {
- .ids = AUTO_NET_SMII_MODE,
- .mask = PMX_SSP_CS_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_touchscreen = {
- .name = "touchscreen",
- .modes = pmx_touchscreen_modes,
- .mode_count = ARRAY_SIZE(pmx_touchscreen_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_can_modes[] = {
- {
- .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | AUTO_EXP_MODE,
- .mask = PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
- PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_can = {
- .name = "can",
- .modes = pmx_can_modes,
- .mode_count = ARRAY_SIZE(pmx_can_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_sdhci_led_modes[] = {
- {
- .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
- .mask = PMX_SSP_CS_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_sdhci_led = {
- .name = "sdhci_led",
- .modes = pmx_sdhci_led_modes,
- .mode_count = ARRAY_SIZE(pmx_sdhci_led_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_pwm0_modes[] = {
- {
- .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
- .mask = PMX_UART0_MODEM_MASK,
- }, {
- .ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE,
- .mask = PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_pwm0 = {
- .name = "pwm0",
- .modes = pmx_pwm0_modes,
- .mode_count = ARRAY_SIZE(pmx_pwm0_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_pwm1_modes[] = {
- {
- .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
- .mask = PMX_UART0_MODEM_MASK,
- }, {
- .ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE,
- .mask = PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_pwm1 = {
- .name = "pwm1",
- .modes = pmx_pwm1_modes,
- .mode_count = ARRAY_SIZE(pmx_pwm1_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_pwm2_modes[] = {
- {
- .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
- .mask = PMX_SSP_CS_MASK,
- }, {
- .ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE,
- .mask = PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_pwm2 = {
- .name = "pwm2",
- .modes = pmx_pwm2_modes,
- .mode_count = ARRAY_SIZE(pmx_pwm2_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_pwm3_modes[] = {
- {
- .ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE | AUTO_NET_SMII_MODE,
- .mask = PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_pwm3 = {
- .name = "pwm3",
- .modes = pmx_pwm3_modes,
- .mode_count = ARRAY_SIZE(pmx_pwm3_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_ssp1_modes[] = {
- {
- .ids = SMALL_PRINTERS_MODE | AUTO_NET_SMII_MODE,
- .mask = PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_ssp1 = {
- .name = "ssp1",
- .modes = pmx_ssp1_modes,
- .mode_count = ARRAY_SIZE(pmx_ssp1_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_ssp2_modes[] = {
- {
- .ids = AUTO_NET_SMII_MODE,
- .mask = PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_ssp2 = {
- .name = "ssp2",
- .modes = pmx_ssp2_modes,
- .mode_count = ARRAY_SIZE(pmx_ssp2_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_mii1_modes[] = {
- {
- .ids = AUTO_NET_MII_MODE,
- .mask = 0x0,
- },
-};
-
-struct pmx_dev spear320_pmx_mii1 = {
- .name = "mii1",
- .modes = pmx_mii1_modes,
- .mode_count = ARRAY_SIZE(pmx_mii1_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_smii0_modes[] = {
- {
- .ids = AUTO_NET_SMII_MODE | AUTO_EXP_MODE | SMALL_PRINTERS_MODE,
- .mask = PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_smii0 = {
- .name = "smii0",
- .modes = pmx_smii0_modes,
- .mode_count = ARRAY_SIZE(pmx_smii0_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_smii1_modes[] = {
- {
- .ids = AUTO_NET_SMII_MODE | SMALL_PRINTERS_MODE,
- .mask = PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear320_pmx_smii1 = {
- .name = "smii1",
- .modes = pmx_smii1_modes,
- .mode_count = ARRAY_SIZE(pmx_smii1_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_i2c1_modes[] = {
- {
- .ids = AUTO_EXP_MODE,
- .mask = 0x0,
- },
-};
-
-struct pmx_dev spear320_pmx_i2c1 = {
- .name = "i2c1",
- .modes = pmx_i2c1_modes,
- .mode_count = ARRAY_SIZE(pmx_i2c1_modes),
- .enb_on_reset = 1,
-};
-
-/* pmx driver structure */
-static struct pmx_driver pmx_driver = {
- .mode_reg = {.offset = MODE_CONFIG_REG, .mask = 0x00000007},
- .mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
-};
+#include <mach/spear.h>
+
+#define SPEAR320_UART1_BASE UL(0xA3000000)
+#define SPEAR320_UART2_BASE UL(0xA4000000)
+#define SPEAR320_SSP0_BASE UL(0xA5000000)
+#define SPEAR320_SSP1_BASE UL(0xA6000000)
+#define SPEAR320_SOC_CONFIG_BASE UL(0xB3000000)
+
+/* Interrupt registers offsets and masks */
+#define SPEAR320_INT_STS_MASK_REG 0x04
+#define SPEAR320_INT_CLR_MASK_REG 0x04
+#define SPEAR320_INT_ENB_MASK_REG 0x08
+#define SPEAR320_GPIO_IRQ_MASK (1 << 0)
+#define SPEAR320_I2S_PLAY_IRQ_MASK (1 << 1)
+#define SPEAR320_I2S_REC_IRQ_MASK (1 << 2)
+#define SPEAR320_EMI_IRQ_MASK (1 << 7)
+#define SPEAR320_CLCD_IRQ_MASK (1 << 8)
+#define SPEAR320_SPP_IRQ_MASK (1 << 9)
+#define SPEAR320_SDHCI_IRQ_MASK (1 << 10)
+#define SPEAR320_CAN_U_IRQ_MASK (1 << 11)
+#define SPEAR320_CAN_L_IRQ_MASK (1 << 12)
+#define SPEAR320_UART1_IRQ_MASK (1 << 13)
+#define SPEAR320_UART2_IRQ_MASK (1 << 14)
+#define SPEAR320_SSP1_IRQ_MASK (1 << 15)
+#define SPEAR320_SSP2_IRQ_MASK (1 << 16)
+#define SPEAR320_SMII0_IRQ_MASK (1 << 17)
+#define SPEAR320_MII1_SMII1_IRQ_MASK (1 << 18)
+#define SPEAR320_WAKEUP_SMII0_IRQ_MASK (1 << 19)
+#define SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK (1 << 20)
+#define SPEAR320_I2C1_IRQ_MASK (1 << 21)
+
+#define SPEAR320_SHIRQ_RAS1_MASK 0x000380
+#define SPEAR320_SHIRQ_RAS3_MASK 0x000007
+#define SPEAR320_SHIRQ_INTRCOMM_RAS_MASK 0x3FF800
+
+/* SPEAr320 Virtual irq definitions */
+/* IRQs sharing IRQ_GEN_RAS_1 */
+#define SPEAR320_VIRQ_EMI (SPEAR3XX_VIRQ_START + 0)
+#define SPEAR320_VIRQ_CLCD (SPEAR3XX_VIRQ_START + 1)
+#define SPEAR320_VIRQ_SPP (SPEAR3XX_VIRQ_START + 2)
+
+/* IRQs sharing IRQ_GEN_RAS_2 */
+#define SPEAR320_IRQ_SDHCI SPEAR3XX_IRQ_GEN_RAS_2
+
+/* IRQs sharing IRQ_GEN_RAS_3 */
+#define SPEAR320_VIRQ_PLGPIO (SPEAR3XX_VIRQ_START + 3)
+#define SPEAR320_VIRQ_I2S_PLAY (SPEAR3XX_VIRQ_START + 4)
+#define SPEAR320_VIRQ_I2S_REC (SPEAR3XX_VIRQ_START + 5)
+
+/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
+#define SPEAR320_VIRQ_CANU (SPEAR3XX_VIRQ_START + 6)
+#define SPEAR320_VIRQ_CANL (SPEAR3XX_VIRQ_START + 7)
+#define SPEAR320_VIRQ_UART1 (SPEAR3XX_VIRQ_START + 8)
+#define SPEAR320_VIRQ_UART2 (SPEAR3XX_VIRQ_START + 9)
+#define SPEAR320_VIRQ_SSP1 (SPEAR3XX_VIRQ_START + 10)
+#define SPEAR320_VIRQ_SSP2 (SPEAR3XX_VIRQ_START + 11)
+#define SPEAR320_VIRQ_SMII0 (SPEAR3XX_VIRQ_START + 12)
+#define SPEAR320_VIRQ_MII1_SMII1 (SPEAR3XX_VIRQ_START + 13)
+#define SPEAR320_VIRQ_WAKEUP_SMII0 (SPEAR3XX_VIRQ_START + 14)
+#define SPEAR320_VIRQ_WAKEUP_MII1_SMII1 (SPEAR3XX_VIRQ_START + 15)
+#define SPEAR320_VIRQ_I2C1 (SPEAR3XX_VIRQ_START + 16)
/* spear3xx shared irq */
static struct shirq_dev_config shirq_ras1_config[] = {
@@ -508,17 +207,250 @@ static struct spear_shirq shirq_intrcomm_ras = {
},
};
-/* Add spear320 specific devices here */
+/* DMAC platform data's slave info */
+struct pl08x_channel_data spear320_dma_info[] = {
+ {
+ .bus_id = "uart0_rx",
+ .min_signal = 2,
+ .max_signal = 2,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart0_tx",
+ .min_signal = 3,
+ .max_signal = 3,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ssp0_rx",
+ .min_signal = 8,
+ .max_signal = 8,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ssp0_tx",
+ .min_signal = 9,
+ .max_signal = 9,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "i2c0_rx",
+ .min_signal = 10,
+ .max_signal = 10,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "i2c0_tx",
+ .min_signal = 11,
+ .max_signal = 11,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "irda",
+ .min_signal = 12,
+ .max_signal = 12,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "adc",
+ .min_signal = 13,
+ .max_signal = 13,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "to_jpeg",
+ .min_signal = 14,
+ .max_signal = 14,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "from_jpeg",
+ .min_signal = 15,
+ .max_signal = 15,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ssp1_rx",
+ .min_signal = 0,
+ .max_signal = 0,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ssp1_tx",
+ .min_signal = 1,
+ .max_signal = 1,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ssp2_rx",
+ .min_signal = 2,
+ .max_signal = 2,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ssp2_tx",
+ .min_signal = 3,
+ .max_signal = 3,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "uart1_rx",
+ .min_signal = 4,
+ .max_signal = 4,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "uart1_tx",
+ .min_signal = 5,
+ .max_signal = 5,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "uart2_rx",
+ .min_signal = 6,
+ .max_signal = 6,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "uart2_tx",
+ .min_signal = 7,
+ .max_signal = 7,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "i2c1_rx",
+ .min_signal = 8,
+ .max_signal = 8,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "i2c1_tx",
+ .min_signal = 9,
+ .max_signal = 9,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "i2c2_rx",
+ .min_signal = 10,
+ .max_signal = 10,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "i2c2_tx",
+ .min_signal = 11,
+ .max_signal = 11,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "i2s_rx",
+ .min_signal = 12,
+ .max_signal = 12,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "i2s_tx",
+ .min_signal = 13,
+ .max_signal = 13,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "rs485_rx",
+ .min_signal = 14,
+ .max_signal = 14,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "rs485_tx",
+ .min_signal = 15,
+ .max_signal = 15,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ },
+};
+
+static struct pl022_ssp_controller spear320_ssp_data[] = {
+ {
+ .bus_id = 1,
+ .enable_dma = 1,
+ .dma_filter = pl08x_filter_id,
+ .dma_tx_param = "ssp1_tx",
+ .dma_rx_param = "ssp1_rx",
+ .num_chipselect = 2,
+ }, {
+ .bus_id = 2,
+ .enable_dma = 1,
+ .dma_filter = pl08x_filter_id,
+ .dma_tx_param = "ssp2_tx",
+ .dma_rx_param = "ssp2_rx",
+ .num_chipselect = 2,
+ }
+};
+
+static struct amba_pl011_data spear320_uart_data[] = {
+ {
+ .dma_filter = pl08x_filter_id,
+ .dma_tx_param = "uart1_tx",
+ .dma_rx_param = "uart1_rx",
+ }, {
+ .dma_filter = pl08x_filter_id,
+ .dma_tx_param = "uart2_tx",
+ .dma_rx_param = "uart2_rx",
+ },
+};
-/* spear320 routines */
-void __init spear320_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
- u8 pmx_dev_count)
+/* Add SPEAr310 auxdata to pass platform data */
+static struct of_dev_auxdata spear320_auxdata_lookup[] __initdata = {
+ OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
+ &pl022_plat_data),
+ OF_DEV_AUXDATA("arm,pl080", SPEAR3XX_ICM3_DMA_BASE, NULL,
+ &pl080_plat_data),
+ OF_DEV_AUXDATA("arm,pl022", SPEAR320_SSP0_BASE, NULL,
+ &spear320_ssp_data[0]),
+ OF_DEV_AUXDATA("arm,pl022", SPEAR320_SSP1_BASE, NULL,
+ &spear320_ssp_data[1]),
+ OF_DEV_AUXDATA("arm,pl011", SPEAR320_UART1_BASE, NULL,
+ &spear320_uart_data[0]),
+ OF_DEV_AUXDATA("arm,pl011", SPEAR320_UART2_BASE, NULL,
+ &spear320_uart_data[1]),
+ {}
+};
+
+static void __init spear320_dt_init(void)
{
void __iomem *base;
- int ret = 0;
+ int ret;
+
+ pl080_plat_data.slave_channels = spear320_dma_info;
+ pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear320_dma_info);
- /* call spear3xx family common init function */
- spear3xx_init();
+ of_platform_populate(NULL, of_default_bus_match_table,
+ spear320_auxdata_lookup, NULL);
/* shared irq registration */
base = ioremap(SPEAR320_SOC_CONFIG_BASE, SZ_4K);
@@ -527,29 +459,40 @@ void __init spear320_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
shirq_ras1.regs.base = base;
ret = spear_shirq_register(&shirq_ras1);
if (ret)
- printk(KERN_ERR "Error registering Shared IRQ 1\n");
+ pr_err("Error registering Shared IRQ 1\n");
/* shirq 3 */
shirq_ras3.regs.base = base;
ret = spear_shirq_register(&shirq_ras3);
if (ret)
- printk(KERN_ERR "Error registering Shared IRQ 3\n");
+ pr_err("Error registering Shared IRQ 3\n");
/* shirq 4 */
shirq_intrcomm_ras.regs.base = base;
ret = spear_shirq_register(&shirq_intrcomm_ras);
if (ret)
- printk(KERN_ERR "Error registering Shared IRQ 4\n");
+ pr_err("Error registering Shared IRQ 4\n");
}
+}
- /* pmx initialization */
- pmx_driver.base = base;
- pmx_driver.mode = pmx_mode;
- pmx_driver.devs = pmx_devs;
- pmx_driver.devs_count = pmx_dev_count;
+static const char * const spear320_dt_board_compat[] = {
+ "st,spear320",
+ "st,spear320-evb",
+ NULL,
+};
- ret = pmx_register(&pmx_driver);
- if (ret)
- printk(KERN_ERR "padmux: registration failed. err no: %d\n",
- ret);
+static void __init spear320_map_io(void)
+{
+ spear3xx_map_io();
+ spear320_clk_init();
}
+
+DT_MACHINE_START(SPEAR320_DT, "ST SPEAr320 SoC with Flattened Device Tree")
+ .map_io = spear320_map_io,
+ .init_irq = spear3xx_dt_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &spear3xx_timer,
+ .init_machine = spear320_dt_init,
+ .restart = spear_restart,
+ .dt_compat = spear320_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
deleted file mode 100644
index 105334ab7021..000000000000
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/spear320_evb.c
- *
- * SPEAr320 evaluation board source file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <asm/hardware/vic.h>
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-#include <mach/generic.h>
-#include <mach/hardware.h>
-
-/* padmux devices to enable */
-static struct pmx_dev *pmx_devs[] = {
- /* spear3xx specific devices */
- &spear3xx_pmx_i2c,
- &spear3xx_pmx_ssp,
- &spear3xx_pmx_mii,
- &spear3xx_pmx_uart0,
-
- /* spear320 specific devices */
- &spear320_pmx_fsmc,
- &spear320_pmx_sdhci,
- &spear320_pmx_i2s,
- &spear320_pmx_uart1,
- &spear320_pmx_uart2,
- &spear320_pmx_can,
- &spear320_pmx_pwm0,
- &spear320_pmx_pwm1,
- &spear320_pmx_pwm2,
- &spear320_pmx_mii1,
-};
-
-static struct amba_device *amba_devs[] __initdata = {
- /* spear3xx specific devices */
- &spear3xx_gpio_device,
- &spear3xx_uart_device,
-
- /* spear320 specific devices */
-};
-
-static struct platform_device *plat_devs[] __initdata = {
- /* spear3xx specific devices */
-
- /* spear320 specific devices */
-};
-
-static void __init spear320_evb_init(void)
-{
- unsigned int i;
-
- /* call spear320 machine init function */
- spear320_init(&spear320_auto_net_mii_mode, pmx_devs,
- ARRAY_SIZE(pmx_devs));
-
- /* Add Platform Devices */
- platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
-
- /* Add Amba Devices */
- for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
- amba_device_register(amba_devs[i], &iomem_resource);
-}
-
-MACHINE_START(SPEAR320, "ST-SPEAR320-EVB")
- .atag_offset = 0x100,
- .map_io = spear3xx_map_io,
- .init_irq = spear3xx_init_irq,
- .handle_irq = vic_handle_irq,
- .timer = &spear3xx_timer,
- .init_machine = spear320_evb_init,
- .restart = spear_restart,
-MACHINE_END
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index b1733c37f209..826ac20ef1e7 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -3,71 +3,78 @@
*
* SPEAr3XX machines common source file
*
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-#include <linux/types.h>
-#include <linux/amba/pl061.h>
-#include <linux/ptrace.h>
+#define pr_fmt(fmt) "SPEAr3xx: " fmt
+
+#include <linux/amba/pl022.h>
+#include <linux/amba/pl08x.h>
+#include <linux/of_irq.h>
#include <linux/io.h>
+#include <asm/hardware/pl080.h>
#include <asm/hardware/vic.h>
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
+#include <plat/pl080.h>
#include <mach/generic.h>
-#include <mach/hardware.h>
-
-/* Add spear3xx machines common devices here */
-/* gpio device registration */
-static struct pl061_platform_data gpio_plat_data = {
- .gpio_base = 0,
- .irq_base = SPEAR3XX_GPIO_INT_BASE,
+#include <mach/spear.h>
+
+/* ssp device registration */
+struct pl022_ssp_controller pl022_plat_data = {
+ .bus_id = 0,
+ .enable_dma = 1,
+ .dma_filter = pl08x_filter_id,
+ .dma_tx_param = "ssp0_tx",
+ .dma_rx_param = "ssp0_rx",
+ /*
+ * This is number of spi devices that can be connected to spi. There are
+ * two type of chipselects on which slave devices can work. One is chip
+ * select provided by spi masters other is controlled through external
+ * gpio's. We can't use chipselect provided from spi master (because as
+ * soon as FIFO becomes empty, CS is disabled and transfer ends). So
+ * this number now depends on number of gpios available for spi. each
+ * slave on each master requires a separate gpio pin.
+ */
+ .num_chipselect = 2,
+};
+
+/* dmac device registration */
+struct pl08x_platform_data pl080_plat_data = {
+ .memcpy_channel = {
+ .bus_id = "memcpy",
+ .cctl = (PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \
+ PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
+ PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
+ PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
+ PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
+ PL080_CONTROL_PROT_SYS),
+ },
+ .lli_buses = PL08X_AHB1,
+ .mem_buses = PL08X_AHB1,
+ .get_signal = pl080_get_signal,
+ .put_signal = pl080_put_signal,
};
-AMBA_APB_DEVICE(spear3xx_gpio, "gpio", 0, SPEAR3XX_ICM3_GPIO_BASE,
- {SPEAR3XX_IRQ_BASIC_GPIO}, &gpio_plat_data);
-
-/* uart device registration */
-AMBA_APB_DEVICE(spear3xx_uart, "uart", 0, SPEAR3XX_ICM1_UART_BASE,
- {SPEAR3XX_IRQ_UART}, NULL);
-
-/* Do spear3xx familiy common initialization part here */
-void __init spear3xx_init(void)
-{
- /* nothing to do for now */
-}
-
-/* This will initialize vic */
-void __init spear3xx_init_irq(void)
-{
- vic_init((void __iomem *)VA_SPEAR3XX_ML1_VIC_BASE, 0, ~0, 0);
-}
-
-/* Following will create static virtual/physical mappings */
+/*
+ * Following will create 16MB static virtual/physical mappings
+ * PHYSICAL VIRTUAL
+ * 0xD0000000 0xFD000000
+ * 0xFC000000 0xFC000000
+ */
struct map_desc spear3xx_io_desc[] __initdata = {
{
- .virtual = VA_SPEAR3XX_ICM1_UART_BASE,
- .pfn = __phys_to_pfn(SPEAR3XX_ICM1_UART_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE
- }, {
- .virtual = VA_SPEAR3XX_ML1_VIC_BASE,
- .pfn = __phys_to_pfn(SPEAR3XX_ML1_VIC_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE
- }, {
- .virtual = VA_SPEAR3XX_ICM3_SYS_CTRL_BASE,
- .pfn = __phys_to_pfn(SPEAR3XX_ICM3_SYS_CTRL_BASE),
- .length = SZ_4K,
+ .virtual = VA_SPEAR3XX_ICM1_2_BASE,
+ .pfn = __phys_to_pfn(SPEAR3XX_ICM1_2_BASE),
+ .length = SZ_16M,
.type = MT_DEVICE
}, {
- .virtual = VA_SPEAR3XX_ICM3_MISC_REG_BASE,
- .pfn = __phys_to_pfn(SPEAR3XX_ICM3_MISC_REG_BASE),
- .length = SZ_4K,
+ .virtual = VA_SPEAR3XX_ICM3_SMI_CTRL_BASE,
+ .pfn = __phys_to_pfn(SPEAR3XX_ICM3_SMI_CTRL_BASE),
+ .length = SZ_16M,
.type = MT_DEVICE
},
};
@@ -76,436 +83,8 @@ struct map_desc spear3xx_io_desc[] __initdata = {
void __init spear3xx_map_io(void)
{
iotable_init(spear3xx_io_desc, ARRAY_SIZE(spear3xx_io_desc));
-
- /* This will initialize clock framework */
- spear3xx_clk_init();
}
-/* pad multiplexing support */
-/* devices */
-static struct pmx_dev_mode pmx_firda_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_FIRDA_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_firda = {
- .name = "firda",
- .modes = pmx_firda_modes,
- .mode_count = ARRAY_SIZE(pmx_firda_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_i2c_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_I2C_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_i2c = {
- .name = "i2c",
- .modes = pmx_i2c_modes,
- .mode_count = ARRAY_SIZE(pmx_i2c_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_ssp_cs_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_SSP_CS_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_ssp_cs = {
- .name = "ssp_chip_selects",
- .modes = pmx_ssp_cs_modes,
- .mode_count = ARRAY_SIZE(pmx_ssp_cs_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_ssp_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_SSP_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_ssp = {
- .name = "ssp",
- .modes = pmx_ssp_modes,
- .mode_count = ARRAY_SIZE(pmx_ssp_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_mii_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_mii = {
- .name = "mii",
- .modes = pmx_mii_modes,
- .mode_count = ARRAY_SIZE(pmx_mii_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_gpio_pin0_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_GPIO_PIN0_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_gpio_pin0 = {
- .name = "gpio_pin0",
- .modes = pmx_gpio_pin0_modes,
- .mode_count = ARRAY_SIZE(pmx_gpio_pin0_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_gpio_pin1_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_GPIO_PIN1_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_gpio_pin1 = {
- .name = "gpio_pin1",
- .modes = pmx_gpio_pin1_modes,
- .mode_count = ARRAY_SIZE(pmx_gpio_pin1_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_gpio_pin2_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_GPIO_PIN2_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_gpio_pin2 = {
- .name = "gpio_pin2",
- .modes = pmx_gpio_pin2_modes,
- .mode_count = ARRAY_SIZE(pmx_gpio_pin2_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_gpio_pin3_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_GPIO_PIN3_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_gpio_pin3 = {
- .name = "gpio_pin3",
- .modes = pmx_gpio_pin3_modes,
- .mode_count = ARRAY_SIZE(pmx_gpio_pin3_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_gpio_pin4_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_GPIO_PIN4_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_gpio_pin4 = {
- .name = "gpio_pin4",
- .modes = pmx_gpio_pin4_modes,
- .mode_count = ARRAY_SIZE(pmx_gpio_pin4_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_gpio_pin5_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_GPIO_PIN5_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_gpio_pin5 = {
- .name = "gpio_pin5",
- .modes = pmx_gpio_pin5_modes,
- .mode_count = ARRAY_SIZE(pmx_gpio_pin5_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_uart0_modem_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_UART0_MODEM_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_uart0_modem = {
- .name = "uart0_modem",
- .modes = pmx_uart0_modem_modes,
- .mode_count = ARRAY_SIZE(pmx_uart0_modem_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_uart0_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_UART0_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_uart0 = {
- .name = "uart0",
- .modes = pmx_uart0_modes,
- .mode_count = ARRAY_SIZE(pmx_uart0_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_timer_3_4_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_TIMER_3_4_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_timer_3_4 = {
- .name = "timer_3_4",
- .modes = pmx_timer_3_4_modes,
- .mode_count = ARRAY_SIZE(pmx_timer_3_4_modes),
- .enb_on_reset = 0,
-};
-
-static struct pmx_dev_mode pmx_timer_1_2_modes[] = {
- {
- .ids = 0xffffffff,
- .mask = PMX_TIMER_1_2_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_timer_1_2 = {
- .name = "timer_1_2",
- .modes = pmx_timer_1_2_modes,
- .mode_count = ARRAY_SIZE(pmx_timer_1_2_modes),
- .enb_on_reset = 0,
-};
-
-#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
-/* plgpios devices */
-static struct pmx_dev_mode pmx_plgpio_0_1_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_FIRDA_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_0_1 = {
- .name = "plgpio 0 and 1",
- .modes = pmx_plgpio_0_1_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_0_1_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_2_3_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_UART0_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_2_3 = {
- .name = "plgpio 2 and 3",
- .modes = pmx_plgpio_2_3_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_2_3_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_4_5_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_I2C_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_4_5 = {
- .name = "plgpio 4 and 5",
- .modes = pmx_plgpio_4_5_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_4_5_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_6_9_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_SSP_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_6_9 = {
- .name = "plgpio 6 to 9",
- .modes = pmx_plgpio_6_9_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_6_9_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_10_27_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_MII_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_10_27 = {
- .name = "plgpio 10 to 27",
- .modes = pmx_plgpio_10_27_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_10_27_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_28_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_GPIO_PIN0_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_28 = {
- .name = "plgpio 28",
- .modes = pmx_plgpio_28_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_28_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_29_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_GPIO_PIN1_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_29 = {
- .name = "plgpio 29",
- .modes = pmx_plgpio_29_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_29_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_30_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_GPIO_PIN2_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_30 = {
- .name = "plgpio 30",
- .modes = pmx_plgpio_30_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_30_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_31_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_GPIO_PIN3_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_31 = {
- .name = "plgpio 31",
- .modes = pmx_plgpio_31_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_31_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_32_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_GPIO_PIN4_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_32 = {
- .name = "plgpio 32",
- .modes = pmx_plgpio_32_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_32_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_33_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_GPIO_PIN5_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_33 = {
- .name = "plgpio 33",
- .modes = pmx_plgpio_33_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_33_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_34_36_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_SSP_CS_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_34_36 = {
- .name = "plgpio 34 to 36",
- .modes = pmx_plgpio_34_36_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_34_36_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_37_42_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_UART0_MODEM_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_37_42 = {
- .name = "plgpio 37 to 42",
- .modes = pmx_plgpio_37_42_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_37_42_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_43_44_47_48_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_TIMER_1_2_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_43_44_47_48 = {
- .name = "plgpio 43, 44, 47 and 48",
- .modes = pmx_plgpio_43_44_47_48_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_43_44_47_48_modes),
- .enb_on_reset = 1,
-};
-
-static struct pmx_dev_mode pmx_plgpio_45_46_49_50_modes[] = {
- {
- .ids = 0x00,
- .mask = PMX_TIMER_3_4_MASK,
- },
-};
-
-struct pmx_dev spear3xx_pmx_plgpio_45_46_49_50 = {
- .name = "plgpio 45, 46, 49 and 50",
- .modes = pmx_plgpio_45_46_49_50_modes,
- .mode_count = ARRAY_SIZE(pmx_plgpio_45_46_49_50_modes),
- .enb_on_reset = 1,
-};
-#endif /* CONFIG_MACH_SPEAR310 || CONFIG_MACH_SPEAR320 */
-
static void __init spear3xx_timer_init(void)
{
char pclk_name[] = "pll3_48m_clk";
@@ -530,9 +109,19 @@ static void __init spear3xx_timer_init(void)
clk_put(gpt_clk);
clk_put(pclk);
- spear_setup_timer();
+ spear_setup_timer(SPEAR3XX_CPU_TMR_BASE, SPEAR3XX_IRQ_CPU_GPT1_1);
}
struct sys_timer spear3xx_timer = {
.init = spear3xx_timer_init,
};
+
+static const struct of_device_id vic_of_match[] __initconst = {
+ { .compatible = "arm,pl190-vic", .data = vic_of_init, },
+ { /* Sentinel */ }
+};
+
+void __init spear3xx_dt_init_irq(void)
+{
+ of_irq_init(vic_of_match);
+}
diff --git a/arch/arm/mach-spear6xx/Kconfig b/arch/arm/mach-spear6xx/Kconfig
index fbe298bd1d92..339f397dea70 100644
--- a/arch/arm/mach-spear6xx/Kconfig
+++ b/arch/arm/mach-spear6xx/Kconfig
@@ -2,21 +2,9 @@
# SPEAr6XX Machine configuration file
#
-if ARCH_SPEAR6XX
-
-menu "SPEAr6xx Implementations"
-config BOARD_SPEAR600_DT
- bool "SPEAr600 generic board configured via device-tree"
- select MACH_SPEAR600
+config MACH_SPEAR600
+ def_bool y
+ depends on ARCH_SPEAR6XX
select USE_OF
help
Supports ST SPEAr600 boards configured via the device-tree
-
-endmenu
-
-config MACH_SPEAR600
- bool "SPEAr600"
- help
- Supports ST SPEAr600 Machine
-
-endif #ARCH_SPEAR6XX
diff --git a/arch/arm/mach-spear6xx/Makefile.boot b/arch/arm/mach-spear6xx/Makefile.boot
index 4674a4c221db..af493da37ab6 100644
--- a/arch/arm/mach-spear6xx/Makefile.boot
+++ b/arch/arm/mach-spear6xx/Makefile.boot
@@ -1,3 +1,5 @@
zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
+
+dtb-$(CONFIG_BOARD_SPEAR600_DT) += spear600-evb.dtb
diff --git a/arch/arm/mach-spear6xx/clock.c b/arch/arm/mach-spear6xx/clock.c
index a86499a8a15f..bef77d43db87 100644
--- a/arch/arm/mach-spear6xx/clock.c
+++ b/arch/arm/mach-spear6xx/clock.c
@@ -16,6 +16,112 @@
#include <linux/kernel.h>
#include <plat/clock.h>
#include <mach/misc_regs.h>
+#include <mach/spear.h>
+
+#define PLL1_CTR (MISC_BASE + 0x008)
+#define PLL1_FRQ (MISC_BASE + 0x00C)
+#define PLL1_MOD (MISC_BASE + 0x010)
+#define PLL2_CTR (MISC_BASE + 0x014)
+/* PLL_CTR register masks */
+#define PLL_ENABLE 2
+#define PLL_MODE_SHIFT 4
+#define PLL_MODE_MASK 0x3
+#define PLL_MODE_NORMAL 0
+#define PLL_MODE_FRACTION 1
+#define PLL_MODE_DITH_DSB 2
+#define PLL_MODE_DITH_SSB 3
+
+#define PLL2_FRQ (MISC_BASE + 0x018)
+/* PLL FRQ register masks */
+#define PLL_DIV_N_SHIFT 0
+#define PLL_DIV_N_MASK 0xFF
+#define PLL_DIV_P_SHIFT 8
+#define PLL_DIV_P_MASK 0x7
+#define PLL_NORM_FDBK_M_SHIFT 24
+#define PLL_NORM_FDBK_M_MASK 0xFF
+#define PLL_DITH_FDBK_M_SHIFT 16
+#define PLL_DITH_FDBK_M_MASK 0xFFFF
+
+#define PLL2_MOD (MISC_BASE + 0x01C)
+#define PLL_CLK_CFG (MISC_BASE + 0x020)
+#define CORE_CLK_CFG (MISC_BASE + 0x024)
+/* CORE CLK CFG register masks */
+#define PLL_HCLK_RATIO_SHIFT 10
+#define PLL_HCLK_RATIO_MASK 0x3
+#define HCLK_PCLK_RATIO_SHIFT 8
+#define HCLK_PCLK_RATIO_MASK 0x3
+
+#define PERIP_CLK_CFG (MISC_BASE + 0x028)
+/* PERIP_CLK_CFG register masks */
+#define CLCD_CLK_SHIFT 2
+#define CLCD_CLK_MASK 0x3
+#define UART_CLK_SHIFT 4
+#define UART_CLK_MASK 0x1
+#define FIRDA_CLK_SHIFT 5
+#define FIRDA_CLK_MASK 0x3
+#define GPT0_CLK_SHIFT 8
+#define GPT1_CLK_SHIFT 10
+#define GPT2_CLK_SHIFT 11
+#define GPT3_CLK_SHIFT 12
+#define GPT_CLK_MASK 0x1
+#define AUX_CLK_PLL3_VAL 0
+#define AUX_CLK_PLL1_VAL 1
+
+#define PERIP1_CLK_ENB (MISC_BASE + 0x02C)
+/* PERIP1_CLK_ENB register masks */
+#define UART0_CLK_ENB 3
+#define UART1_CLK_ENB 4
+#define SSP0_CLK_ENB 5
+#define SSP1_CLK_ENB 6
+#define I2C_CLK_ENB 7
+#define JPEG_CLK_ENB 8
+#define FSMC_CLK_ENB 9
+#define FIRDA_CLK_ENB 10
+#define GPT2_CLK_ENB 11
+#define GPT3_CLK_ENB 12
+#define GPIO2_CLK_ENB 13
+#define SSP2_CLK_ENB 14
+#define ADC_CLK_ENB 15
+#define GPT1_CLK_ENB 11
+#define RTC_CLK_ENB 17
+#define GPIO1_CLK_ENB 18
+#define DMA_CLK_ENB 19
+#define SMI_CLK_ENB 21
+#define CLCD_CLK_ENB 22
+#define GMAC_CLK_ENB 23
+#define USBD_CLK_ENB 24
+#define USBH0_CLK_ENB 25
+#define USBH1_CLK_ENB 26
+
+#define PRSC1_CLK_CFG (MISC_BASE + 0x044)
+#define PRSC2_CLK_CFG (MISC_BASE + 0x048)
+#define PRSC3_CLK_CFG (MISC_BASE + 0x04C)
+/* gpt synthesizer register masks */
+#define GPT_MSCALE_SHIFT 0
+#define GPT_MSCALE_MASK 0xFFF
+#define GPT_NSCALE_SHIFT 12
+#define GPT_NSCALE_MASK 0xF
+
+#define AMEM_CLK_CFG (MISC_BASE + 0x050)
+#define EXPI_CLK_CFG (MISC_BASE + 0x054)
+#define CLCD_CLK_SYNT (MISC_BASE + 0x05C)
+#define FIRDA_CLK_SYNT (MISC_BASE + 0x060)
+#define UART_CLK_SYNT (MISC_BASE + 0x064)
+#define GMAC_CLK_SYNT (MISC_BASE + 0x068)
+#define RAS1_CLK_SYNT (MISC_BASE + 0x06C)
+#define RAS2_CLK_SYNT (MISC_BASE + 0x070)
+#define RAS3_CLK_SYNT (MISC_BASE + 0x074)
+#define RAS4_CLK_SYNT (MISC_BASE + 0x078)
+/* aux clk synthesiser register masks for irda to ras4 */
+#define AUX_SYNT_ENB 31
+#define AUX_EQ_SEL_SHIFT 30
+#define AUX_EQ_SEL_MASK 1
+#define AUX_EQ1_SEL 0
+#define AUX_EQ2_SEL 1
+#define AUX_XSCALE_SHIFT 16
+#define AUX_XSCALE_MASK 0xFFF
+#define AUX_YSCALE_SHIFT 0
+#define AUX_YSCALE_MASK 0xFFF
/* root clks */
/* 32 KHz oscillator clock */
@@ -623,53 +729,53 @@ static struct clk dummy_apb_pclk;
/* array of all spear 6xx clock lookups */
static struct clk_lookup spear_clk_lookups[] = {
- { .con_id = "apb_pclk", .clk = &dummy_apb_pclk},
+ CLKDEV_INIT(NULL, "apb_pclk", &dummy_apb_pclk),
/* root clks */
- { .con_id = "osc_32k_clk", .clk = &osc_32k_clk},
- { .con_id = "osc_30m_clk", .clk = &osc_30m_clk},
+ CLKDEV_INIT(NULL, "osc_32k_clk", &osc_32k_clk),
+ CLKDEV_INIT(NULL, "osc_30m_clk", &osc_30m_clk),
/* clock derived from 32 KHz os clk */
- { .dev_id = "rtc-spear", .clk = &rtc_clk},
+ CLKDEV_INIT("rtc-spear", NULL, &rtc_clk),
/* clock derived from 30 MHz os clk */
- { .con_id = "pll1_clk", .clk = &pll1_clk},
- { .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk},
- { .dev_id = "wdt", .clk = &wdt_clk},
+ CLKDEV_INIT(NULL, "pll1_clk", &pll1_clk),
+ CLKDEV_INIT(NULL, "pll3_48m_clk", &pll3_48m_clk),
+ CLKDEV_INIT("wdt", NULL, &wdt_clk),
/* clock derived from pll1 clk */
- { .con_id = "cpu_clk", .clk = &cpu_clk},
- { .con_id = "ahb_clk", .clk = &ahb_clk},
- { .con_id = "uart_synth_clk", .clk = &uart_synth_clk},
- { .con_id = "firda_synth_clk", .clk = &firda_synth_clk},
- { .con_id = "clcd_synth_clk", .clk = &clcd_synth_clk},
- { .con_id = "gpt0_synth_clk", .clk = &gpt0_synth_clk},
- { .con_id = "gpt2_synth_clk", .clk = &gpt2_synth_clk},
- { .con_id = "gpt3_synth_clk", .clk = &gpt3_synth_clk},
- { .dev_id = "d0000000.serial", .clk = &uart0_clk},
- { .dev_id = "d0080000.serial", .clk = &uart1_clk},
- { .dev_id = "firda", .clk = &firda_clk},
- { .dev_id = "clcd", .clk = &clcd_clk},
- { .dev_id = "gpt0", .clk = &gpt0_clk},
- { .dev_id = "gpt1", .clk = &gpt1_clk},
- { .dev_id = "gpt2", .clk = &gpt2_clk},
- { .dev_id = "gpt3", .clk = &gpt3_clk},
+ CLKDEV_INIT(NULL, "cpu_clk", &cpu_clk),
+ CLKDEV_INIT(NULL, "ahb_clk", &ahb_clk),
+ CLKDEV_INIT(NULL, "uart_synth_clk", &uart_synth_clk),
+ CLKDEV_INIT(NULL, "firda_synth_clk", &firda_synth_clk),
+ CLKDEV_INIT(NULL, "clcd_synth_clk", &clcd_synth_clk),
+ CLKDEV_INIT(NULL, "gpt0_synth_clk", &gpt0_synth_clk),
+ CLKDEV_INIT(NULL, "gpt2_synth_clk", &gpt2_synth_clk),
+ CLKDEV_INIT(NULL, "gpt3_synth_clk", &gpt3_synth_clk),
+ CLKDEV_INIT("d0000000.serial", NULL, &uart0_clk),
+ CLKDEV_INIT("d0080000.serial", NULL, &uart1_clk),
+ CLKDEV_INIT("firda", NULL, &firda_clk),
+ CLKDEV_INIT("clcd", NULL, &clcd_clk),
+ CLKDEV_INIT("gpt0", NULL, &gpt0_clk),
+ CLKDEV_INIT("gpt1", NULL, &gpt1_clk),
+ CLKDEV_INIT("gpt2", NULL, &gpt2_clk),
+ CLKDEV_INIT("gpt3", NULL, &gpt3_clk),
/* clock derived from pll3 clk */
- { .dev_id = "designware_udc", .clk = &usbd_clk},
- { .con_id = "usbh.0_clk", .clk = &usbh0_clk},
- { .con_id = "usbh.1_clk", .clk = &usbh1_clk},
+ CLKDEV_INIT("designware_udc", NULL, &usbd_clk),
+ CLKDEV_INIT(NULL, "usbh.0_clk", &usbh0_clk),
+ CLKDEV_INIT(NULL, "usbh.1_clk", &usbh1_clk),
/* clock derived from ahb clk */
- { .con_id = "apb_clk", .clk = &apb_clk},
- { .dev_id = "d0200000.i2c", .clk = &i2c_clk},
- { .dev_id = "dma", .clk = &dma_clk},
- { .dev_id = "jpeg", .clk = &jpeg_clk},
- { .dev_id = "gmac", .clk = &gmac_clk},
- { .dev_id = "smi", .clk = &smi_clk},
- { .dev_id = "fsmc-nand", .clk = &fsmc_clk},
+ CLKDEV_INIT(NULL, "apb_clk", &apb_clk),
+ CLKDEV_INIT("d0200000.i2c", NULL, &i2c_clk),
+ CLKDEV_INIT("fc400000.dma", NULL, &dma_clk),
+ CLKDEV_INIT("jpeg", NULL, &jpeg_clk),
+ CLKDEV_INIT("gmac", NULL, &gmac_clk),
+ CLKDEV_INIT("fc000000.flash", NULL, &smi_clk),
+ CLKDEV_INIT("d1800000.flash", NULL, &fsmc_clk),
/* clock derived from apb clk */
- { .dev_id = "adc", .clk = &adc_clk},
- { .dev_id = "ssp-pl022.0", .clk = &ssp0_clk},
- { .dev_id = "ssp-pl022.1", .clk = &ssp1_clk},
- { .dev_id = "ssp-pl022.2", .clk = &ssp2_clk},
- { .dev_id = "f0100000.gpio", .clk = &gpio0_clk},
- { .dev_id = "fc980000.gpio", .clk = &gpio1_clk},
- { .dev_id = "d8100000.gpio", .clk = &gpio2_clk},
+ CLKDEV_INIT("adc", NULL, &adc_clk),
+ CLKDEV_INIT("ssp-pl022.0", NULL, &ssp0_clk),
+ CLKDEV_INIT("ssp-pl022.1", NULL, &ssp1_clk),
+ CLKDEV_INIT("ssp-pl022.2", NULL, &ssp2_clk),
+ CLKDEV_INIT("f0100000.gpio", NULL, &gpio0_clk),
+ CLKDEV_INIT("fc980000.gpio", NULL, &gpio1_clk),
+ CLKDEV_INIT("d8100000.gpio", NULL, &gpio2_clk),
};
void __init spear6xx_clk_init(void)
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
index 116b99301cf5..7167fd331d86 100644
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ b/arch/arm/mach-spear6xx/include/mach/generic.h
@@ -15,34 +15,9 @@
#define __MACH_GENERIC_H
#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/amba/bus.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-
-/*
- * Each GPT has 2 timer channels
- * Following GPT channels will be used as clock source and clockevent
- */
-#define SPEAR_GPT0_BASE SPEAR6XX_CPU_TMR_BASE
-#define SPEAR_GPT0_CHAN0_IRQ IRQ_CPU_GPT1_1
-#define SPEAR_GPT0_CHAN1_IRQ IRQ_CPU_GPT1_2
-
-/* Add spear6xx family device structure declarations here */
-extern struct amba_device gpio_device[];
-extern struct amba_device uart_device[];
-extern struct sys_timer spear6xx_timer;
-
-/* Add spear6xx family function declarations here */
-void __init spear_setup_timer(void);
-void __init spear6xx_map_io(void);
-void __init spear6xx_init_irq(void);
-void __init spear6xx_init(void);
-void __init spear600_init(void);
-void __init spear6xx_clk_init(void);
+void __init spear_setup_timer(resource_size_t base, int irq);
void spear_restart(char, const char *);
-
-/* Add spear600 machine device structure declarations here */
+void __init spear6xx_clk_init(void);
#endif /* __MACH_GENERIC_H */
diff --git a/arch/arm/mach-spear6xx/include/mach/hardware.h b/arch/arm/mach-spear6xx/include/mach/hardware.h
index 0b3f96ae2848..40a8c178f10d 100644
--- a/arch/arm/mach-spear6xx/include/mach/hardware.h
+++ b/arch/arm/mach-spear6xx/include/mach/hardware.h
@@ -1,23 +1 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/hardware.h
- *
- * Hardware definitions for SPEAr6xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Rajeev Kumar<rajeev-dlh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __MACH_HARDWARE_H
-#define __MACH_HARDWARE_H
-
-#include <plat/hardware.h>
-#include <mach/spear.h>
-
-/* Vitual to physical translation of statically mapped space */
-#define IO_ADDRESS(x) (x | 0xF0000000)
-
-#endif /* __MACH_HARDWARE_H */
+/* empty */
diff --git a/arch/arm/mach-spear6xx/include/mach/irqs.h b/arch/arm/mach-spear6xx/include/mach/irqs.h
index 8f214b03d75d..2b735389e74b 100644
--- a/arch/arm/mach-spear6xx/include/mach/irqs.h
+++ b/arch/arm/mach-spear6xx/include/mach/irqs.h
@@ -16,82 +16,13 @@
/* IRQ definitions */
/* VIC 1 */
-#define IRQ_INTRCOMM_SW_IRQ 0
-#define IRQ_INTRCOMM_CPU_1 1
-#define IRQ_INTRCOMM_CPU_2 2
-#define IRQ_INTRCOMM_RAS2A11_1 3
-#define IRQ_INTRCOMM_RAS2A11_2 4
-#define IRQ_INTRCOMM_RAS2A12_1 5
-#define IRQ_INTRCOMM_RAS2A12_2 6
-#define IRQ_GEN_RAS_0 7
-#define IRQ_GEN_RAS_1 8
-#define IRQ_GEN_RAS_2 9
-#define IRQ_GEN_RAS_3 10
-#define IRQ_GEN_RAS_4 11
-#define IRQ_GEN_RAS_5 12
-#define IRQ_GEN_RAS_6 13
-#define IRQ_GEN_RAS_7 14
-#define IRQ_GEN_RAS_8 15
+/* FIXME: probe this from DT */
#define IRQ_CPU_GPT1_1 16
-#define IRQ_CPU_GPT1_2 17
-#define IRQ_LOCAL_GPIO 18
-#define IRQ_PLL_UNLOCK 19
-#define IRQ_JPEG 20
-#define IRQ_FSMC 21
-#define IRQ_IRDA 22
-#define IRQ_RESERVED 23
-#define IRQ_UART_0 24
-#define IRQ_UART_1 25
-#define IRQ_SSP_1 26
-#define IRQ_SSP_2 27
-#define IRQ_I2C 28
-#define IRQ_GEN_RAS_9 29
-#define IRQ_GEN_RAS_10 30
-#define IRQ_GEN_RAS_11 31
-
-/* VIC 2 */
-#define IRQ_APPL_GPT1_1 32
-#define IRQ_APPL_GPT1_2 33
-#define IRQ_APPL_GPT2_1 34
-#define IRQ_APPL_GPT2_2 35
-#define IRQ_APPL_GPIO 36
-#define IRQ_APPL_SSP 37
-#define IRQ_APPL_ADC 38
-#define IRQ_APPL_RESERVED 39
-#define IRQ_AHB_EXP_MASTER 40
-#define IRQ_DDR_CONTROLLER 41
-#define IRQ_BASIC_DMA 42
-#define IRQ_BASIC_RESERVED1 43
-#define IRQ_BASIC_SMI 44
-#define IRQ_BASIC_CLCD 45
-#define IRQ_EXP_AHB_1 46
-#define IRQ_EXP_AHB_2 47
-#define IRQ_BASIC_GPT1_1 48
-#define IRQ_BASIC_GPT1_2 49
-#define IRQ_BASIC_RTC 50
-#define IRQ_BASIC_GPIO 51
-#define IRQ_BASIC_WDT 52
-#define IRQ_BASIC_RESERVED 53
-#define IRQ_AHB_EXP_SLAVE 54
-#define IRQ_GMAC_1 55
-#define IRQ_GMAC_2 56
-#define IRQ_USB_DEV 57
-#define IRQ_USB_H_OHCI_0 58
-#define IRQ_USB_H_EHCI_0 59
-#define IRQ_USB_H_OHCI_1 60
-#define IRQ_USB_H_EHCI_1 61
-#define IRQ_EXP_AHB_3 62
-#define IRQ_EXP_AHB_4 63
#define IRQ_VIC_END 64
/* GPIO pins virtual irqs */
-#define SPEAR_GPIO_INT_BASE IRQ_VIC_END
-#define SPEAR_GPIO0_INT_BASE SPEAR_GPIO_INT_BASE
-#define SPEAR_GPIO1_INT_BASE (SPEAR_GPIO0_INT_BASE + 8)
-#define SPEAR_GPIO2_INT_BASE (SPEAR_GPIO1_INT_BASE + 8)
-#define SPEAR_GPIO_INT_END (SPEAR_GPIO2_INT_BASE + 8)
-#define VIRTUAL_IRQS (SPEAR_GPIO_INT_END - IRQ_VIC_END)
-#define NR_IRQS (IRQ_VIC_END + VIRTUAL_IRQS)
+#define VIRTUAL_IRQS 24
+#define NR_IRQS (IRQ_VIC_END + VIRTUAL_IRQS)
#endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-spear6xx/include/mach/misc_regs.h b/arch/arm/mach-spear6xx/include/mach/misc_regs.h
index 68c20a007b0d..2b9aaa6cdd11 100644
--- a/arch/arm/mach-spear6xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear6xx/include/mach/misc_regs.h
@@ -14,161 +14,7 @@
#ifndef __MACH_MISC_REGS_H
#define __MACH_MISC_REGS_H
-#include <mach/hardware.h>
-
#define MISC_BASE IOMEM(VA_SPEAR6XX_ICM3_MISC_REG_BASE)
-
-#define SOC_CFG_CTR (MISC_BASE + 0x000)
-#define DIAG_CFG_CTR (MISC_BASE + 0x004)
-#define PLL1_CTR (MISC_BASE + 0x008)
-#define PLL1_FRQ (MISC_BASE + 0x00C)
-#define PLL1_MOD (MISC_BASE + 0x010)
-#define PLL2_CTR (MISC_BASE + 0x014)
-/* PLL_CTR register masks */
-#define PLL_ENABLE 2
-#define PLL_MODE_SHIFT 4
-#define PLL_MODE_MASK 0x3
-#define PLL_MODE_NORMAL 0
-#define PLL_MODE_FRACTION 1
-#define PLL_MODE_DITH_DSB 2
-#define PLL_MODE_DITH_SSB 3
-
-#define PLL2_FRQ (MISC_BASE + 0x018)
-/* PLL FRQ register masks */
-#define PLL_DIV_N_SHIFT 0
-#define PLL_DIV_N_MASK 0xFF
-#define PLL_DIV_P_SHIFT 8
-#define PLL_DIV_P_MASK 0x7
-#define PLL_NORM_FDBK_M_SHIFT 24
-#define PLL_NORM_FDBK_M_MASK 0xFF
-#define PLL_DITH_FDBK_M_SHIFT 16
-#define PLL_DITH_FDBK_M_MASK 0xFFFF
-
-#define PLL2_MOD (MISC_BASE + 0x01C)
-#define PLL_CLK_CFG (MISC_BASE + 0x020)
-#define CORE_CLK_CFG (MISC_BASE + 0x024)
-/* CORE CLK CFG register masks */
-#define PLL_HCLK_RATIO_SHIFT 10
-#define PLL_HCLK_RATIO_MASK 0x3
-#define HCLK_PCLK_RATIO_SHIFT 8
-#define HCLK_PCLK_RATIO_MASK 0x3
-
-#define PERIP_CLK_CFG (MISC_BASE + 0x028)
-/* PERIP_CLK_CFG register masks */
-#define CLCD_CLK_SHIFT 2
-#define CLCD_CLK_MASK 0x3
-#define UART_CLK_SHIFT 4
-#define UART_CLK_MASK 0x1
-#define FIRDA_CLK_SHIFT 5
-#define FIRDA_CLK_MASK 0x3
-#define GPT0_CLK_SHIFT 8
-#define GPT1_CLK_SHIFT 10
-#define GPT2_CLK_SHIFT 11
-#define GPT3_CLK_SHIFT 12
-#define GPT_CLK_MASK 0x1
-#define AUX_CLK_PLL3_VAL 0
-#define AUX_CLK_PLL1_VAL 1
-
-#define PERIP1_CLK_ENB (MISC_BASE + 0x02C)
-/* PERIP1_CLK_ENB register masks */
-#define UART0_CLK_ENB 3
-#define UART1_CLK_ENB 4
-#define SSP0_CLK_ENB 5
-#define SSP1_CLK_ENB 6
-#define I2C_CLK_ENB 7
-#define JPEG_CLK_ENB 8
-#define FSMC_CLK_ENB 9
-#define FIRDA_CLK_ENB 10
-#define GPT2_CLK_ENB 11
-#define GPT3_CLK_ENB 12
-#define GPIO2_CLK_ENB 13
-#define SSP2_CLK_ENB 14
-#define ADC_CLK_ENB 15
-#define GPT1_CLK_ENB 11
-#define RTC_CLK_ENB 17
-#define GPIO1_CLK_ENB 18
-#define DMA_CLK_ENB 19
-#define SMI_CLK_ENB 21
-#define CLCD_CLK_ENB 22
-#define GMAC_CLK_ENB 23
-#define USBD_CLK_ENB 24
-#define USBH0_CLK_ENB 25
-#define USBH1_CLK_ENB 26
-
-#define SOC_CORE_ID (MISC_BASE + 0x030)
-#define RAS_CLK_ENB (MISC_BASE + 0x034)
-#define PERIP1_SOF_RST (MISC_BASE + 0x038)
-/* PERIP1_SOF_RST register masks */
-#define JPEG_SOF_RST 8
-
-#define SOC_USER_ID (MISC_BASE + 0x03C)
-#define RAS_SOF_RST (MISC_BASE + 0x040)
-#define PRSC1_CLK_CFG (MISC_BASE + 0x044)
-#define PRSC2_CLK_CFG (MISC_BASE + 0x048)
-#define PRSC3_CLK_CFG (MISC_BASE + 0x04C)
-/* gpt synthesizer register masks */
-#define GPT_MSCALE_SHIFT 0
-#define GPT_MSCALE_MASK 0xFFF
-#define GPT_NSCALE_SHIFT 12
-#define GPT_NSCALE_MASK 0xF
-
-#define AMEM_CLK_CFG (MISC_BASE + 0x050)
-#define EXPI_CLK_CFG (MISC_BASE + 0x054)
-#define CLCD_CLK_SYNT (MISC_BASE + 0x05C)
-#define FIRDA_CLK_SYNT (MISC_BASE + 0x060)
-#define UART_CLK_SYNT (MISC_BASE + 0x064)
-#define GMAC_CLK_SYNT (MISC_BASE + 0x068)
-#define RAS1_CLK_SYNT (MISC_BASE + 0x06C)
-#define RAS2_CLK_SYNT (MISC_BASE + 0x070)
-#define RAS3_CLK_SYNT (MISC_BASE + 0x074)
-#define RAS4_CLK_SYNT (MISC_BASE + 0x078)
-/* aux clk synthesiser register masks for irda to ras4 */
-#define AUX_SYNT_ENB 31
-#define AUX_EQ_SEL_SHIFT 30
-#define AUX_EQ_SEL_MASK 1
-#define AUX_EQ1_SEL 0
-#define AUX_EQ2_SEL 1
-#define AUX_XSCALE_SHIFT 16
-#define AUX_XSCALE_MASK 0xFFF
-#define AUX_YSCALE_SHIFT 0
-#define AUX_YSCALE_MASK 0xFFF
-
-#define ICM1_ARB_CFG (MISC_BASE + 0x07C)
-#define ICM2_ARB_CFG (MISC_BASE + 0x080)
-#define ICM3_ARB_CFG (MISC_BASE + 0x084)
-#define ICM4_ARB_CFG (MISC_BASE + 0x088)
-#define ICM5_ARB_CFG (MISC_BASE + 0x08C)
-#define ICM6_ARB_CFG (MISC_BASE + 0x090)
-#define ICM7_ARB_CFG (MISC_BASE + 0x094)
-#define ICM8_ARB_CFG (MISC_BASE + 0x098)
-#define ICM9_ARB_CFG (MISC_BASE + 0x09C)
#define DMA_CHN_CFG (MISC_BASE + 0x0A0)
-#define USB2_PHY_CFG (MISC_BASE + 0x0A4)
-#define GMAC_CFG_CTR (MISC_BASE + 0x0A8)
-#define EXPI_CFG_CTR (MISC_BASE + 0x0AC)
-#define PRC1_LOCK_CTR (MISC_BASE + 0x0C0)
-#define PRC2_LOCK_CTR (MISC_BASE + 0x0C4)
-#define PRC3_LOCK_CTR (MISC_BASE + 0x0C8)
-#define PRC4_LOCK_CTR (MISC_BASE + 0x0CC)
-#define PRC1_IRQ_CTR (MISC_BASE + 0x0D0)
-#define PRC2_IRQ_CTR (MISC_BASE + 0x0D4)
-#define PRC3_IRQ_CTR (MISC_BASE + 0x0D8)
-#define PRC4_IRQ_CTR (MISC_BASE + 0x0DC)
-#define PWRDOWN_CFG_CTR (MISC_BASE + 0x0E0)
-#define COMPSSTL_1V8_CFG (MISC_BASE + 0x0E4)
-#define COMPSSTL_2V5_CFG (MISC_BASE + 0x0E8)
-#define COMPCOR_3V3_CFG (MISC_BASE + 0x0EC)
-#define SSTLPAD_CFG_CTR (MISC_BASE + 0x0F0)
-#define BIST1_CFG_CTR (MISC_BASE + 0x0F4)
-#define BIST2_CFG_CTR (MISC_BASE + 0x0F8)
-#define BIST3_CFG_CTR (MISC_BASE + 0x0FC)
-#define BIST4_CFG_CTR (MISC_BASE + 0x100)
-#define BIST5_CFG_CTR (MISC_BASE + 0x104)
-#define BIST1_STS_RES (MISC_BASE + 0x108)
-#define BIST2_STS_RES (MISC_BASE + 0x10C)
-#define BIST3_STS_RES (MISC_BASE + 0x110)
-#define BIST4_STS_RES (MISC_BASE + 0x114)
-#define BIST5_STS_RES (MISC_BASE + 0x118)
-#define SYSERR_CFG_CTR (MISC_BASE + 0x11C)
#endif /* __MACH_MISC_REGS_H */
diff --git a/arch/arm/mach-spear6xx/include/mach/spear.h b/arch/arm/mach-spear6xx/include/mach/spear.h
index 7fd621532def..d278ed047a53 100644
--- a/arch/arm/mach-spear6xx/include/mach/spear.h
+++ b/arch/arm/mach-spear6xx/include/mach/spear.h
@@ -15,69 +15,26 @@
#define __MACH_SPEAR6XX_H
#include <asm/memory.h>
-#include <mach/spear600.h>
-#define SPEAR6XX_ML_SDRAM_BASE UL(0x00000000)
/* ICM1 - Low speed connection */
#define SPEAR6XX_ICM1_BASE UL(0xD0000000)
-
+#define VA_SPEAR6XX_ICM1_BASE UL(0xFD000000)
#define SPEAR6XX_ICM1_UART0_BASE UL(0xD0000000)
-#define VA_SPEAR6XX_ICM1_UART0_BASE IO_ADDRESS(SPEAR6XX_ICM1_UART0_BASE)
-
-#define SPEAR6XX_ICM1_UART1_BASE UL(0xD0080000)
-#define SPEAR6XX_ICM1_SSP0_BASE UL(0xD0100000)
-#define SPEAR6XX_ICM1_SSP1_BASE UL(0xD0180000)
-#define SPEAR6XX_ICM1_I2C_BASE UL(0xD0200000)
-#define SPEAR6XX_ICM1_JPEG_BASE UL(0xD0800000)
-#define SPEAR6XX_ICM1_IRDA_BASE UL(0xD1000000)
-#define SPEAR6XX_ICM1_FSMC_BASE UL(0xD1800000)
-#define SPEAR6XX_ICM1_NAND_BASE UL(0xD2000000)
-#define SPEAR6XX_ICM1_SRAM_BASE UL(0xD2800000)
-
-/* ICM2 - Application Subsystem */
-#define SPEAR6XX_ICM2_BASE UL(0xD8000000)
-#define SPEAR6XX_ICM2_TMR0_BASE UL(0xD8000000)
-#define SPEAR6XX_ICM2_TMR1_BASE UL(0xD8080000)
-#define SPEAR6XX_ICM2_GPIO_BASE UL(0xD8100000)
-#define SPEAR6XX_ICM2_SSP2_BASE UL(0xD8180000)
-#define SPEAR6XX_ICM2_ADC_BASE UL(0xD8200000)
+#define VA_SPEAR6XX_ICM1_UART0_BASE (VA_SPEAR6XX_ICM1_2_BASE | SPEAR6XX_ICM1_UART0_BASE)
/* ML-1, 2 - Multi Layer CPU Subsystem */
#define SPEAR6XX_ML_CPU_BASE UL(0xF0000000)
+#define VA_SPEAR6XX_ML_CPU_BASE UL(0xF0000000)
#define SPEAR6XX_CPU_TMR_BASE UL(0xF0000000)
-#define SPEAR6XX_CPU_GPIO_BASE UL(0xF0100000)
-#define SPEAR6XX_CPU_VIC_SEC_BASE UL(0xF1000000)
-#define VA_SPEAR6XX_CPU_VIC_SEC_BASE IO_ADDRESS(SPEAR6XX_CPU_VIC_SEC_BASE)
-#define SPEAR6XX_CPU_VIC_PRI_BASE UL(0xF1100000)
-#define VA_SPEAR6XX_CPU_VIC_PRI_BASE IO_ADDRESS(SPEAR6XX_CPU_VIC_PRI_BASE)
/* ICM3 - Basic Subsystem */
-#define SPEAR6XX_ICM3_BASE UL(0xF8000000)
-#define SPEAR6XX_ICM3_SMEM_BASE UL(0xF8000000)
#define SPEAR6XX_ICM3_SMI_CTRL_BASE UL(0xFC000000)
-#define SPEAR6XX_ICM3_CLCD_BASE UL(0xFC200000)
+#define VA_SPEAR6XX_ICM3_SMI_CTRL_BASE UL(0xFC000000)
#define SPEAR6XX_ICM3_DMA_BASE UL(0xFC400000)
-#define SPEAR6XX_ICM3_SDRAM_CTRL_BASE UL(0xFC600000)
-#define SPEAR6XX_ICM3_TMR_BASE UL(0xFC800000)
-#define SPEAR6XX_ICM3_WDT_BASE UL(0xFC880000)
-#define SPEAR6XX_ICM3_RTC_BASE UL(0xFC900000)
-#define SPEAR6XX_ICM3_GPIO_BASE UL(0xFC980000)
#define SPEAR6XX_ICM3_SYS_CTRL_BASE UL(0xFCA00000)
-#define VA_SPEAR6XX_ICM3_SYS_CTRL_BASE IO_ADDRESS(SPEAR6XX_ICM3_SYS_CTRL_BASE)
+#define VA_SPEAR6XX_ICM3_SYS_CTRL_BASE (VA_SPEAR6XX_ICM3_SMI_CTRL_BASE | SPEAR6XX_ICM3_SYS_CTRL_BASE)
#define SPEAR6XX_ICM3_MISC_REG_BASE UL(0xFCA80000)
-#define VA_SPEAR6XX_ICM3_MISC_REG_BASE IO_ADDRESS(SPEAR6XX_ICM3_MISC_REG_BASE)
-
-/* ICM4 - High Speed Connection */
-#define SPEAR6XX_ICM4_BASE UL(0xE0000000)
-#define SPEAR6XX_ICM4_GMAC_BASE UL(0xE0800000)
-#define SPEAR6XX_ICM4_USBD_FIFO_BASE UL(0xE1000000)
-#define SPEAR6XX_ICM4_USBD_CSR_BASE UL(0xE1100000)
-#define SPEAR6XX_ICM4_USBD_PLDT_BASE UL(0xE1200000)
-#define SPEAR6XX_ICM4_USB_EHCI0_BASE UL(0xE1800000)
-#define SPEAR6XX_ICM4_USB_OHCI0_BASE UL(0xE1900000)
-#define SPEAR6XX_ICM4_USB_EHCI1_BASE UL(0xE2000000)
-#define SPEAR6XX_ICM4_USB_OHCI1_BASE UL(0xE2100000)
-#define SPEAR6XX_ICM4_USB_ARB_BASE UL(0xE2800000)
+#define VA_SPEAR6XX_ICM3_MISC_REG_BASE (VA_SPEAR6XX_ICM3_SMI_CTRL_BASE | SPEAR6XX_ICM3_MISC_REG_BASE)
/* Debug uart for linux, will be used for debug and uncompress messages */
#define SPEAR_DBG_UART_BASE SPEAR6XX_ICM1_UART0_BASE
diff --git a/arch/arm/mach-spear6xx/include/mach/spear600.h b/arch/arm/mach-spear6xx/include/mach/spear600.h
deleted file mode 100644
index c068cc50b0fb..000000000000
--- a/arch/arm/mach-spear6xx/include/mach/spear600.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-spear66xx/include/mach/spear600.h
- *
- * SPEAr600 Machine specific definition
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifdef CONFIG_MACH_SPEAR600
-
-#ifndef __MACH_SPEAR600_H
-#define __MACH_SPEAR600_H
-
-#endif /* __MACH_SPEAR600_H */
-
-#endif /* CONFIG_MACH_SPEAR600 */
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index 2ed8b14c82c8..de194dbb8371 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -13,41 +13,404 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/amba/pl08x.h>
+#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <asm/hardware/pl080.h>
#include <asm/hardware/vic.h>
#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+#include <plat/pl080.h>
#include <mach/generic.h>
-#include <mach/hardware.h>
+#include <mach/spear.h>
-/* Following will create static virtual/physical mappings */
-static struct map_desc spear6xx_io_desc[] __initdata = {
+/* dmac device registration */
+static struct pl08x_channel_data spear600_dma_info[] = {
{
- .virtual = VA_SPEAR6XX_ICM1_UART0_BASE,
- .pfn = __phys_to_pfn(SPEAR6XX_ICM1_UART0_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE
+ .bus_id = "ssp1_rx",
+ .min_signal = 0,
+ .max_signal = 0,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
}, {
- .virtual = VA_SPEAR6XX_CPU_VIC_PRI_BASE,
- .pfn = __phys_to_pfn(SPEAR6XX_CPU_VIC_PRI_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE
+ .bus_id = "ssp1_tx",
+ .min_signal = 1,
+ .max_signal = 1,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
}, {
- .virtual = VA_SPEAR6XX_CPU_VIC_SEC_BASE,
- .pfn = __phys_to_pfn(SPEAR6XX_CPU_VIC_SEC_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE
+ .bus_id = "uart0_rx",
+ .min_signal = 2,
+ .max_signal = 2,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart0_tx",
+ .min_signal = 3,
+ .max_signal = 3,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart1_rx",
+ .min_signal = 4,
+ .max_signal = 4,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "uart1_tx",
+ .min_signal = 5,
+ .max_signal = 5,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ssp2_rx",
+ .min_signal = 6,
+ .max_signal = 6,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ssp2_tx",
+ .min_signal = 7,
+ .max_signal = 7,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ssp0_rx",
+ .min_signal = 8,
+ .max_signal = 8,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ssp0_tx",
+ .min_signal = 9,
+ .max_signal = 9,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "i2c_rx",
+ .min_signal = 10,
+ .max_signal = 10,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "i2c_tx",
+ .min_signal = 11,
+ .max_signal = 11,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "irda",
+ .min_signal = 12,
+ .max_signal = 12,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "adc",
+ .min_signal = 13,
+ .max_signal = 13,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "to_jpeg",
+ .min_signal = 14,
+ .max_signal = 14,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "from_jpeg",
+ .min_signal = 15,
+ .max_signal = 15,
+ .muxval = 0,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras0_rx",
+ .min_signal = 0,
+ .max_signal = 0,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras0_tx",
+ .min_signal = 1,
+ .max_signal = 1,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras1_rx",
+ .min_signal = 2,
+ .max_signal = 2,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras1_tx",
+ .min_signal = 3,
+ .max_signal = 3,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras2_rx",
+ .min_signal = 4,
+ .max_signal = 4,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras2_tx",
+ .min_signal = 5,
+ .max_signal = 5,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras3_rx",
+ .min_signal = 6,
+ .max_signal = 6,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras3_tx",
+ .min_signal = 7,
+ .max_signal = 7,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras4_rx",
+ .min_signal = 8,
+ .max_signal = 8,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras4_tx",
+ .min_signal = 9,
+ .max_signal = 9,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras5_rx",
+ .min_signal = 10,
+ .max_signal = 10,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras5_tx",
+ .min_signal = 11,
+ .max_signal = 11,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras6_rx",
+ .min_signal = 12,
+ .max_signal = 12,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras6_tx",
+ .min_signal = 13,
+ .max_signal = 13,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
}, {
- .virtual = VA_SPEAR6XX_ICM3_SYS_CTRL_BASE,
- .pfn = __phys_to_pfn(SPEAR6XX_ICM3_SYS_CTRL_BASE),
- .length = SZ_4K,
+ .bus_id = "ras7_rx",
+ .min_signal = 14,
+ .max_signal = 14,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ras7_tx",
+ .min_signal = 15,
+ .max_signal = 15,
+ .muxval = 1,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB1,
+ }, {
+ .bus_id = "ext0_rx",
+ .min_signal = 0,
+ .max_signal = 0,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext0_tx",
+ .min_signal = 1,
+ .max_signal = 1,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext1_rx",
+ .min_signal = 2,
+ .max_signal = 2,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext1_tx",
+ .min_signal = 3,
+ .max_signal = 3,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext2_rx",
+ .min_signal = 4,
+ .max_signal = 4,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext2_tx",
+ .min_signal = 5,
+ .max_signal = 5,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext3_rx",
+ .min_signal = 6,
+ .max_signal = 6,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext3_tx",
+ .min_signal = 7,
+ .max_signal = 7,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext4_rx",
+ .min_signal = 8,
+ .max_signal = 8,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext4_tx",
+ .min_signal = 9,
+ .max_signal = 9,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext5_rx",
+ .min_signal = 10,
+ .max_signal = 10,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext5_tx",
+ .min_signal = 11,
+ .max_signal = 11,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext6_rx",
+ .min_signal = 12,
+ .max_signal = 12,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext6_tx",
+ .min_signal = 13,
+ .max_signal = 13,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext7_rx",
+ .min_signal = 14,
+ .max_signal = 14,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ }, {
+ .bus_id = "ext7_tx",
+ .min_signal = 15,
+ .max_signal = 15,
+ .muxval = 2,
+ .cctl = 0,
+ .periph_buses = PL08X_AHB2,
+ },
+};
+
+struct pl08x_platform_data pl080_plat_data = {
+ .memcpy_channel = {
+ .bus_id = "memcpy",
+ .cctl = (PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \
+ PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
+ PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
+ PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
+ PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
+ PL080_CONTROL_PROT_SYS),
+ },
+ .lli_buses = PL08X_AHB1,
+ .mem_buses = PL08X_AHB1,
+ .get_signal = pl080_get_signal,
+ .put_signal = pl080_put_signal,
+ .slave_channels = spear600_dma_info,
+ .num_slave_channels = ARRAY_SIZE(spear600_dma_info),
+};
+
+/*
+ * Following will create 16MB static virtual/physical mappings
+ * PHYSICAL VIRTUAL
+ * 0xF0000000 0xF0000000
+ * 0xF1000000 0xF1000000
+ * 0xD0000000 0xFD000000
+ * 0xFC000000 0xFC000000
+ */
+struct map_desc spear6xx_io_desc[] __initdata = {
+ {
+ .virtual = VA_SPEAR6XX_ML_CPU_BASE,
+ .pfn = __phys_to_pfn(SPEAR6XX_ML_CPU_BASE),
+ .length = 2 * SZ_16M,
+ .type = MT_DEVICE
+ }, {
+ .virtual = VA_SPEAR6XX_ICM1_BASE,
+ .pfn = __phys_to_pfn(SPEAR6XX_ICM1_BASE),
+ .length = SZ_16M,
.type = MT_DEVICE
}, {
- .virtual = VA_SPEAR6XX_ICM3_MISC_REG_BASE,
- .pfn = __phys_to_pfn(SPEAR6XX_ICM3_MISC_REG_BASE),
- .length = SZ_4K,
+ .virtual = VA_SPEAR6XX_ICM3_SMI_CTRL_BASE,
+ .pfn = __phys_to_pfn(SPEAR6XX_ICM3_SMI_CTRL_BASE),
+ .length = SZ_16M,
.type = MT_DEVICE
},
};
@@ -85,16 +448,24 @@ static void __init spear6xx_timer_init(void)
clk_put(gpt_clk);
clk_put(pclk);
- spear_setup_timer();
+ spear_setup_timer(SPEAR6XX_CPU_TMR_BASE, IRQ_CPU_GPT1_1);
}
struct sys_timer spear6xx_timer = {
.init = spear6xx_timer_init,
};
+/* Add auxdata to pass platform data */
+struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = {
+ OF_DEV_AUXDATA("arm,pl080", SPEAR6XX_ICM3_DMA_BASE, NULL,
+ &pl080_plat_data),
+ {}
+};
+
static void __init spear600_dt_init(void)
{
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+ of_platform_populate(NULL, of_default_bus_match_table,
+ spear6xx_auxdata_lookup, NULL);
}
static const char *spear600_dt_board_compat[] = {
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index d87d968115ec..2eb4445ddb14 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -5,7 +5,6 @@ obj-y += io.o
obj-y += irq.o
obj-y += clock.o
obj-y += timer.o
-obj-y += pinmux.o
obj-y += fuse.o
obj-y += pmc.o
obj-y += flowctrl.o
@@ -14,8 +13,6 @@ obj-$(CONFIG_CPU_IDLE) += sleep.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += powergate.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-tegra20-tables.o
-obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pinmux-tegra30-tables.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c
index 0952494f481a..fac3eb1af17e 100644
--- a/arch/arm/mach-tegra/board-dt-tegra20.c
+++ b/arch/arm/mach-tegra/board-dt-tegra20.c
@@ -37,7 +37,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <asm/setup.h>
-#include <asm/hardware/gic.h>
#include <mach/iomap.h>
#include <mach/irqs.h>
@@ -47,15 +46,7 @@
#include "clock.h"
#include "devices.h"
-void harmony_pinmux_init(void);
-void paz00_pinmux_init(void);
-void seaboard_pinmux_init(void);
-void trimslice_pinmux_init(void);
-void ventana_pinmux_init(void);
-
struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("nvidia,tegra20-pinmux", TEGRA_APB_MISC_BASE + 0x14, "tegra-pinmux", NULL),
- OF_DEV_AUXDATA("nvidia,tegra20-gpio", TEGRA_GPIO_BASE, "tegra-gpio", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC2_BASE, "sdhci-tegra.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC3_BASE, "sdhci-tegra.2", NULL),
@@ -64,9 +55,9 @@ struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C2_BASE, "tegra-i2c.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C3_BASE, "tegra-i2c.2", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-i2c-dvc", TEGRA_DVC_BASE, "tegra-i2c.3", NULL),
- OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.0", NULL),
- OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S2_BASE, "tegra-i2s.1", NULL),
- OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra-das", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra20-i2s.0", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S2_BASE, "tegra20-i2s.1", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra20-das", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB_BASE, "tegra-ehci.0",
&tegra_ehci1_pdata),
OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB2_BASE, "tegra-ehci.1",
@@ -95,33 +86,10 @@ static struct of_device_id tegra_dt_match_table[] __initdata = {
{}
};
-static struct {
- char *machine;
- void (*init)(void);
-} pinmux_configs[] = {
- { "compulab,trimslice", trimslice_pinmux_init },
- { "nvidia,harmony", harmony_pinmux_init },
- { "compal,paz00", paz00_pinmux_init },
- { "nvidia,seaboard", seaboard_pinmux_init },
- { "nvidia,ventana", ventana_pinmux_init },
-};
-
static void __init tegra_dt_init(void)
{
- int i;
-
tegra_clk_init_from_table(tegra_dt_clk_init_table);
- for (i = 0; i < ARRAY_SIZE(pinmux_configs); i++) {
- if (of_machine_is_compatible(pinmux_configs[i].machine)) {
- pinmux_configs[i].init();
- break;
- }
- }
-
- WARN(i == ARRAY_SIZE(pinmux_configs),
- "Unknown platform! Pinmuxing not initialized\n");
-
/*
* Finished with the static registrations now; fill in the missing
* devices
diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c
index 1af85bccc0f1..83d420fbc58c 100644
--- a/arch/arm/mach-tegra/board-harmony-pinmux.c
+++ b/arch/arm/mach-tegra/board-harmony-pinmux.c
@@ -2,6 +2,7 @@
* arch/arm/mach-tegra/board-harmony-pinmux.c
*
* Copyright (C) 2010 Google, Inc.
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -15,153 +16,138 @@
*/
#include <linux/kernel.h>
-#include <linux/gpio.h>
-#include <linux/of.h>
-#include <mach/pinmux.h>
-#include <mach/pinmux-tegra20.h>
-
-#include "gpio-names.h"
#include "board-harmony.h"
#include "board-pinmux.h"
-static struct tegra_pingroup_config harmony_pinmux[] = {
- {TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_ATB, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_ATC, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_CSUS, TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DAP2, TEGRA_MUX_DAP2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DTA, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DTB, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DTC, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DTD, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DTE, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GMB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GMC, TEGRA_MUX_UARTD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GMD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GME, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GPU, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_GPU7, TEGRA_MUX_RTCK, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GPV, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_I2CP, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_IRRX, TEGRA_MUX_UARTA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_IRTX, TEGRA_MUX_UARTA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_KBCA, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCB, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCC, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCD, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCE, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCF, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LCSN, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LD0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD10, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD11, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD12, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD13, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD14, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD15, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD16, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD17, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD3, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD4, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD5, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD6, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD7, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD8, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD9, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LDC, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LHP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LHP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LHP2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LHS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LM0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LM1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LPP, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LPW0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LPW1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LPW2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LSC0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LSC1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSCK, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSDA, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSPI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LVP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LVP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LVS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_OWC, TEGRA_MUX_RSVD2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_PMC, TEGRA_MUX_PWR_ON, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PTA, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_RM, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SDB, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SDC, TEGRA_MUX_PWM, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SDD, TEGRA_MUX_PWM, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SLXA, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPID, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIE, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIF, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UAD, TEGRA_MUX_IRDA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UCA, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UCB, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UDA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_CK32, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DDRC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCA, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCB, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCD, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCE, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_XM2C, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
-};
-
-static struct tegra_gpio_table gpio_table[] = {
- { .gpio = TEGRA_GPIO_SD2_CD, .enable = true },
- { .gpio = TEGRA_GPIO_SD2_WP, .enable = true },
- { .gpio = TEGRA_GPIO_SD2_POWER, .enable = true },
- { .gpio = TEGRA_GPIO_SD4_CD, .enable = true },
- { .gpio = TEGRA_GPIO_SD4_WP, .enable = true },
- { .gpio = TEGRA_GPIO_SD4_POWER, .enable = true },
- { .gpio = TEGRA_GPIO_CDC_IRQ, .enable = true },
- { .gpio = TEGRA_GPIO_HP_DET, .enable = true },
- { .gpio = TEGRA_GPIO_INT_MIC_EN, .enable = true },
- { .gpio = TEGRA_GPIO_EXT_MIC_EN, .enable = true },
+static struct pinctrl_map harmony_map[] = {
+ TEGRA_MAP_MUXCONF("ata", "ide", none, driven),
+ TEGRA_MAP_MUXCONF("atb", "sdio4", none, driven),
+ TEGRA_MAP_MUXCONF("atc", "nand", none, driven),
+ TEGRA_MAP_MUXCONF("atd", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("ate", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("cdev1", "plla_out", none, driven),
+ TEGRA_MAP_MUXCONF("cdev2", "pllp_out4", down, tristate),
+ TEGRA_MAP_MUXCONF("crtp", "crt", none, tristate),
+ TEGRA_MAP_MUXCONF("csus", "vi_sensor_clk", down, tristate),
+ TEGRA_MAP_MUXCONF("dap1", "dap1", none, driven),
+ TEGRA_MAP_MUXCONF("dap2", "dap2", none, tristate),
+ TEGRA_MAP_MUXCONF("dap3", "dap3", none, tristate),
+ TEGRA_MAP_MUXCONF("dap4", "dap4", none, tristate),
+ TEGRA_MAP_MUXCONF("ddc", "i2c2", up, driven),
+ TEGRA_MAP_MUXCONF("dta", "sdio2", up, driven),
+ TEGRA_MAP_MUXCONF("dtb", "rsvd1", none, driven),
+ TEGRA_MAP_MUXCONF("dtc", "rsvd1", none, tristate),
+ TEGRA_MAP_MUXCONF("dtd", "sdio2", up, driven),
+ TEGRA_MAP_MUXCONF("dte", "rsvd1", none, tristate),
+ TEGRA_MAP_MUXCONF("dtf", "i2c3", none, tristate),
+ TEGRA_MAP_MUXCONF("gma", "sdio4", none, driven),
+ TEGRA_MAP_MUXCONF("gmb", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("gmc", "uartd", none, driven),
+ TEGRA_MAP_MUXCONF("gmd", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("gme", "sdio4", none, driven),
+ TEGRA_MAP_MUXCONF("gpu", "gmi", none, tristate),
+ TEGRA_MAP_MUXCONF("gpu7", "rtck", none, driven),
+ TEGRA_MAP_MUXCONF("gpv", "pcie", none, driven),
+ TEGRA_MAP_MUXCONF("hdint", "hdmi", na, tristate),
+ TEGRA_MAP_MUXCONF("i2cp", "i2cp", none, driven),
+ TEGRA_MAP_MUXCONF("irrx", "uarta", up, tristate),
+ TEGRA_MAP_MUXCONF("irtx", "uarta", up, tristate),
+ TEGRA_MAP_MUXCONF("kbca", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("kbcb", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("kbcc", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("kbcd", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("kbce", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("kbcf", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("lcsn", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("ld0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld1", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld10", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld11", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld12", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld13", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld14", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld15", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld16", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld17", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld2", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld3", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld4", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld5", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld6", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld7", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld8", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld9", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ldc", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("ldi", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lhp0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lhp1", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lhp2", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lhs", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lm0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lm1", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lpp", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lpw0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lpw1", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lpw2", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lsc0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lsc1", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lsck", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lsda", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lsdi", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lspi", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lvp0", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lvp1", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lvs", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("owc", "rsvd2", na, tristate),
+ TEGRA_MAP_MUXCONF("pmc", "pwr_on", na, driven),
+ TEGRA_MAP_MUXCONF("pta", "hdmi", none, driven),
+ TEGRA_MAP_MUXCONF("rm", "i2c1", none, driven),
+ TEGRA_MAP_MUXCONF("sdb", "pwm", na, tristate),
+ TEGRA_MAP_MUXCONF("sdc", "pwm", up, driven),
+ TEGRA_MAP_MUXCONF("sdd", "pwm", up, tristate),
+ TEGRA_MAP_MUXCONF("sdio1", "sdio1", none, tristate),
+ TEGRA_MAP_MUXCONF("slxa", "pcie", none, driven),
+ TEGRA_MAP_MUXCONF("slxc", "spdif", none, tristate),
+ TEGRA_MAP_MUXCONF("slxd", "spdif", none, tristate),
+ TEGRA_MAP_MUXCONF("slxk", "pcie", none, driven),
+ TEGRA_MAP_MUXCONF("spdi", "rsvd2", none, tristate),
+ TEGRA_MAP_MUXCONF("spdo", "rsvd2", none, tristate),
+ TEGRA_MAP_MUXCONF("spia", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("spib", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("spic", "gmi", up, tristate),
+ TEGRA_MAP_MUXCONF("spid", "spi1", down, tristate),
+ TEGRA_MAP_MUXCONF("spie", "spi1", up, tristate),
+ TEGRA_MAP_MUXCONF("spif", "spi1", down, tristate),
+ TEGRA_MAP_MUXCONF("spig", "spi2_alt", none, tristate),
+ TEGRA_MAP_MUXCONF("spih", "spi2_alt", up, tristate),
+ TEGRA_MAP_MUXCONF("uaa", "ulpi", up, tristate),
+ TEGRA_MAP_MUXCONF("uab", "ulpi", up, tristate),
+ TEGRA_MAP_MUXCONF("uac", "rsvd2", none, tristate),
+ TEGRA_MAP_MUXCONF("uad", "irda", up, tristate),
+ TEGRA_MAP_MUXCONF("uca", "uartc", up, tristate),
+ TEGRA_MAP_MUXCONF("ucb", "uartc", up, tristate),
+ TEGRA_MAP_MUXCONF("uda", "ulpi", none, tristate),
+ TEGRA_MAP_CONF("ck32", none, na),
+ TEGRA_MAP_CONF("ddrc", none, na),
+ TEGRA_MAP_CONF("pmca", none, na),
+ TEGRA_MAP_CONF("pmcb", none, na),
+ TEGRA_MAP_CONF("pmcc", none, na),
+ TEGRA_MAP_CONF("pmcd", none, na),
+ TEGRA_MAP_CONF("pmce", none, na),
+ TEGRA_MAP_CONF("xm2c", none, na),
+ TEGRA_MAP_CONF("xm2d", none, na),
+ TEGRA_MAP_CONF("ls", up, na),
+ TEGRA_MAP_CONF("lc", up, na),
+ TEGRA_MAP_CONF("ld17_0", down, na),
+ TEGRA_MAP_CONF("ld19_18", down, na),
+ TEGRA_MAP_CONF("ld21_20", down, na),
+ TEGRA_MAP_CONF("ld23_22", down, na),
};
static struct tegra_board_pinmux_conf conf = {
- .pgs = harmony_pinmux,
- .pg_count = ARRAY_SIZE(harmony_pinmux),
- .gpios = gpio_table,
- .gpio_count = ARRAY_SIZE(gpio_table),
+ .maps = harmony_map,
+ .map_count = ARRAY_SIZE(harmony_map),
};
void harmony_pinmux_init(void)
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
index c00aadb01e09..b906b3b6077b 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
+#include <linux/of_serial.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/pda_power.h>
@@ -52,6 +53,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
.irq = INT_UARTD,
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
.type = PORT_TEGRA,
+ .handle_break = tegra_serial_handle_break,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = 216000000,
@@ -122,7 +124,6 @@ static struct platform_device *harmony_devices[] __initdata = {
&tegra_ehci3_device,
&tegra_i2s_device1,
&tegra_das_device,
- &tegra_pcm_device,
&harmony_audio_device,
};
diff --git a/arch/arm/mach-tegra/board-paz00-pinmux.c b/arch/arm/mach-tegra/board-paz00-pinmux.c
index c775572dcea4..6f1111b48e7c 100644
--- a/arch/arm/mach-tegra/board-paz00-pinmux.c
+++ b/arch/arm/mach-tegra/board-paz00-pinmux.c
@@ -2,6 +2,7 @@
* arch/arm/mach-tegra/board-paz00-pinmux.c
*
* Copyright (C) 2010 Marc Dietrich <marvin24@gmx.de>
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -15,150 +16,138 @@
*/
#include <linux/kernel.h>
-#include <linux/gpio.h>
-#include <linux/of.h>
-#include <mach/pinmux.h>
-#include <mach/pinmux-tegra20.h>
-
-#include "gpio-names.h"
#include "board-paz00.h"
#include "board-pinmux.h"
-static struct tegra_pingroup_config paz00_pinmux[] = {
- {TEGRA_PINGROUP_ATA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_ATB, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_ATC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_CSUS, TEGRA_MUX_PLLC_OUT1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DAP2, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DTA, TEGRA_MUX_RSVD1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DTB, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DTC, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DTD, TEGRA_MUX_RSVD1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DTE, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GMB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GMC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GMD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GME, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GPU, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GPU7, TEGRA_MUX_RTCK, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GPV, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_I2CP, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_IRRX, TEGRA_MUX_UARTA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_IRTX, TEGRA_MUX_UARTA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCA, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCB, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCC, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCD, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCE, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCF, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LCSN, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LD0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD10, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD11, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD12, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD13, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD14, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD15, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD16, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD17, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD3, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD4, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD5, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD6, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD7, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD8, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD9, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LDC, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LHP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LHP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LHP2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LHS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LM0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LM1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LPP, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LPW0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LPW1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LPW2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSC0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LSC1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSCK, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSDA, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSPI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LVP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LVP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LVS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_OWC, TEGRA_MUX_OWR, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_PMC, TEGRA_MUX_PWR_ON, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PTA, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_RM, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SDB, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SDC, TEGRA_MUX_TWC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SDD, TEGRA_MUX_PWM, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SLXA, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPID, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIE, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIF, TEGRA_MUX_RSVD4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_UAD, TEGRA_MUX_SPDIF, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UCA, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UCB, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UDA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_CK32, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DDRC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCA, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCB, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCD, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCE, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_XM2C, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
-};
-
-static struct tegra_gpio_table gpio_table[] = {
- { .gpio = TEGRA_GPIO_SD1_CD, .enable = true },
- { .gpio = TEGRA_GPIO_SD1_WP, .enable = true },
- { .gpio = TEGRA_GPIO_SD1_POWER, .enable = true },
- { .gpio = TEGRA_ULPI_RST, .enable = true },
- { .gpio = TEGRA_WIFI_PWRN, .enable = true },
- { .gpio = TEGRA_WIFI_RST, .enable = true },
- { .gpio = TEGRA_WIFI_LED, .enable = true },
+static struct pinctrl_map paz00_map[] = {
+ TEGRA_MAP_MUXCONF("ata", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("atb", "sdio4", none, driven),
+ TEGRA_MAP_MUXCONF("atc", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("atd", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("ate", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("cdev1", "plla_out", none, driven),
+ TEGRA_MAP_MUXCONF("cdev2", "pllp_out4", down, driven),
+ TEGRA_MAP_MUXCONF("crtp", "crt", none, tristate),
+ TEGRA_MAP_MUXCONF("csus", "pllc_out1", down, tristate),
+ TEGRA_MAP_MUXCONF("dap1", "dap1", none, driven),
+ TEGRA_MAP_MUXCONF("dap2", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("dap3", "dap3", none, tristate),
+ TEGRA_MAP_MUXCONF("dap4", "dap4", none, tristate),
+ TEGRA_MAP_MUXCONF("ddc", "i2c2", up, driven),
+ TEGRA_MAP_MUXCONF("dta", "rsvd1", up, tristate),
+ TEGRA_MAP_MUXCONF("dtb", "rsvd1", none, tristate),
+ TEGRA_MAP_MUXCONF("dtc", "rsvd1", none, tristate),
+ TEGRA_MAP_MUXCONF("dtd", "rsvd1", up, tristate),
+ TEGRA_MAP_MUXCONF("dte", "rsvd1", none, tristate),
+ TEGRA_MAP_MUXCONF("dtf", "i2c3", none, driven),
+ TEGRA_MAP_MUXCONF("gma", "sdio4", none, driven),
+ TEGRA_MAP_MUXCONF("gmb", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("gmc", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("gmd", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("gme", "sdio4", none, driven),
+ TEGRA_MAP_MUXCONF("gpu", "pwm", none, driven),
+ TEGRA_MAP_MUXCONF("gpu7", "rtck", none, driven),
+ TEGRA_MAP_MUXCONF("gpv", "pcie", none, driven),
+ TEGRA_MAP_MUXCONF("hdint", "hdmi", na, driven),
+ TEGRA_MAP_MUXCONF("i2cp", "i2cp", none, driven),
+ TEGRA_MAP_MUXCONF("irrx", "uarta", up, driven),
+ TEGRA_MAP_MUXCONF("irtx", "uarta", up, driven),
+ TEGRA_MAP_MUXCONF("kbca", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("kbcb", "sdio2", up, driven),
+ TEGRA_MAP_MUXCONF("kbcc", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("kbcd", "sdio2", up, driven),
+ TEGRA_MAP_MUXCONF("kbce", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("kbcf", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("lcsn", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("ld0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld1", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld10", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld11", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld12", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld13", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld14", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld15", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld16", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld17", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld2", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld3", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld4", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld5", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld6", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld7", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld8", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld9", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ldc", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ldi", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lhp0", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lhp1", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lhp2", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lhs", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lm0", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lm1", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lpp", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lpw0", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lpw1", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lpw2", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lsc0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lsc1", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lsck", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lsda", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lsdi", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lspi", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lvp0", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lvp1", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lvs", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("owc", "owr", up, tristate),
+ TEGRA_MAP_MUXCONF("pmc", "pwr_on", na, driven),
+ TEGRA_MAP_MUXCONF("pta", "hdmi", none, driven),
+ TEGRA_MAP_MUXCONF("rm", "i2c1", none, driven),
+ TEGRA_MAP_MUXCONF("sdb", "pwm", na, tristate),
+ TEGRA_MAP_MUXCONF("sdc", "twc", up, tristate),
+ TEGRA_MAP_MUXCONF("sdd", "pwm", up, tristate),
+ TEGRA_MAP_MUXCONF("sdio1", "sdio1", none, driven),
+ TEGRA_MAP_MUXCONF("slxa", "pcie", none, tristate),
+ TEGRA_MAP_MUXCONF("slxc", "spi4", none, tristate),
+ TEGRA_MAP_MUXCONF("slxd", "spi4", none, tristate),
+ TEGRA_MAP_MUXCONF("slxk", "pcie", none, driven),
+ TEGRA_MAP_MUXCONF("spdi", "rsvd2", none, tristate),
+ TEGRA_MAP_MUXCONF("spdo", "rsvd2", none, driven),
+ TEGRA_MAP_MUXCONF("spia", "gmi", down, tristate),
+ TEGRA_MAP_MUXCONF("spib", "gmi", down, tristate),
+ TEGRA_MAP_MUXCONF("spic", "gmi", up, driven),
+ TEGRA_MAP_MUXCONF("spid", "gmi", down, tristate),
+ TEGRA_MAP_MUXCONF("spie", "gmi", up, tristate),
+ TEGRA_MAP_MUXCONF("spif", "rsvd4", down, tristate),
+ TEGRA_MAP_MUXCONF("spig", "spi2_alt", up, driven),
+ TEGRA_MAP_MUXCONF("spih", "spi2_alt", up, tristate),
+ TEGRA_MAP_MUXCONF("uaa", "ulpi", up, driven),
+ TEGRA_MAP_MUXCONF("uab", "ulpi", up, driven),
+ TEGRA_MAP_MUXCONF("uac", "rsvd4", none, driven),
+ TEGRA_MAP_MUXCONF("uad", "spdif", up, tristate),
+ TEGRA_MAP_MUXCONF("uca", "uartc", up, tristate),
+ TEGRA_MAP_MUXCONF("ucb", "uartc", up, tristate),
+ TEGRA_MAP_MUXCONF("uda", "ulpi", none, driven),
+ TEGRA_MAP_CONF("ck32", none, na),
+ TEGRA_MAP_CONF("ddrc", none, na),
+ TEGRA_MAP_CONF("pmca", none, na),
+ TEGRA_MAP_CONF("pmcb", none, na),
+ TEGRA_MAP_CONF("pmcc", none, na),
+ TEGRA_MAP_CONF("pmcd", none, na),
+ TEGRA_MAP_CONF("pmce", none, na),
+ TEGRA_MAP_CONF("xm2c", none, na),
+ TEGRA_MAP_CONF("xm2d", none, na),
+ TEGRA_MAP_CONF("ls", up, na),
+ TEGRA_MAP_CONF("lc", up, na),
+ TEGRA_MAP_CONF("ld17_0", down, na),
+ TEGRA_MAP_CONF("ld19_18", down, na),
+ TEGRA_MAP_CONF("ld21_20", down, na),
+ TEGRA_MAP_CONF("ld23_22", down, na),
};
static struct tegra_board_pinmux_conf conf = {
- .pgs = paz00_pinmux,
- .pg_count = ARRAY_SIZE(paz00_pinmux),
- .gpios = gpio_table,
- .gpio_count = ARRAY_SIZE(gpio_table),
+ .maps = paz00_map,
+ .map_count = ARRAY_SIZE(paz00_map),
};
void paz00_pinmux_init(void)
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index 330afdfa2475..d0735c70d688 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
+#include <linux/of_serial.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/gpio_keys.h>
@@ -55,6 +56,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
.irq = INT_UARTA,
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
.type = PORT_TEGRA,
+ .handle_break = tegra_serial_handle_break,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = 216000000,
@@ -65,6 +67,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
.irq = INT_UARTC,
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
.type = PORT_TEGRA,
+ .handle_break = tegra_serial_handle_break,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = 216000000,
diff --git a/arch/arm/mach-tegra/board-pinmux.c b/arch/arm/mach-tegra/board-pinmux.c
index adc3efe979b3..a5574c71b931 100644
--- a/arch/arm/mach-tegra/board-pinmux.c
+++ b/arch/arm/mach-tegra/board-pinmux.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2011,2012, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -15,75 +15,59 @@
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/notifier.h>
-#include <linux/of.h>
#include <linux/string.h>
-#include <mach/gpio-tegra.h>
-#include <mach/pinmux.h>
-
#include "board-pinmux.h"
#include "devices.h"
-struct tegra_board_pinmux_conf *confs[2];
-
-static void tegra_board_pinmux_setup_gpios(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(confs); i++) {
- if (!confs[i])
- continue;
-
- tegra_gpio_config(confs[i]->gpios, confs[i]->gpio_count);
- }
-}
-
-static void tegra_board_pinmux_setup_pinmux(void)
-{
- int i;
+unsigned long tegra_pincfg_pullnone_driven[2] = {
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_NONE),
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_DRIVEN),
+};
- for (i = 0; i < ARRAY_SIZE(confs); i++) {
- if (!confs[i])
- continue;
+unsigned long tegra_pincfg_pullnone_tristate[2] = {
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_NONE),
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_TRISTATE),
+};
- tegra_pinmux_config_table(confs[i]->pgs, confs[i]->pg_count);
+unsigned long tegra_pincfg_pullnone_na[1] = {
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_NONE),
+};
- if (confs[i]->drives)
- tegra_drive_pinmux_config_table(confs[i]->drives,
- confs[i]->drive_count);
- }
-}
+unsigned long tegra_pincfg_pullup_driven[2] = {
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_UP),
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_DRIVEN),
+};
-static int tegra_board_pinmux_bus_notify(struct notifier_block *nb,
- unsigned long event, void *vdev)
-{
- static bool had_gpio;
- static bool had_pinmux;
+unsigned long tegra_pincfg_pullup_tristate[2] = {
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_UP),
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_TRISTATE),
+};
- struct device *dev = vdev;
- const char *devname;
+unsigned long tegra_pincfg_pullup_na[1] = {
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_UP),
+};
- if (event != BUS_NOTIFY_BOUND_DRIVER)
- return NOTIFY_DONE;
+unsigned long tegra_pincfg_pulldown_driven[2] = {
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_DOWN),
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_DRIVEN),
+};
- devname = dev_name(dev);
+unsigned long tegra_pincfg_pulldown_tristate[2] = {
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_DOWN),
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_TRISTATE),
+};
- if (!had_gpio && !strcmp(devname, GPIO_DEV)) {
- tegra_board_pinmux_setup_gpios();
- had_gpio = true;
- } else if (!had_pinmux && !strcmp(devname, PINMUX_DEV)) {
- tegra_board_pinmux_setup_pinmux();
- had_pinmux = true;
- }
+unsigned long tegra_pincfg_pulldown_na[1] = {
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_DOWN),
+};
- if (had_gpio && had_pinmux)
- return NOTIFY_STOP_MASK;
- else
- return NOTIFY_DONE;
-}
+unsigned long tegra_pincfg_pullna_driven[1] = {
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_DRIVEN),
+};
-static struct notifier_block nb = {
- .notifier_call = tegra_board_pinmux_bus_notify,
+unsigned long tegra_pincfg_pullna_tristate[1] = {
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_TRISTATE),
};
static struct platform_device *devices[] = {
@@ -94,11 +78,10 @@ static struct platform_device *devices[] = {
void tegra_board_pinmux_init(struct tegra_board_pinmux_conf *conf_a,
struct tegra_board_pinmux_conf *conf_b)
{
- confs[0] = conf_a;
- confs[1] = conf_b;
-
- bus_register_notifier(&platform_bus_type, &nb);
+ if (conf_a)
+ pinctrl_register_mappings(conf_a->maps, conf_a->map_count);
+ if (conf_b)
+ pinctrl_register_mappings(conf_b->maps, conf_b->map_count);
- if (!of_machine_is_compatible("nvidia,tegra20"))
- platform_add_devices(devices, ARRAY_SIZE(devices));
+ platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-tegra/board-pinmux.h b/arch/arm/mach-tegra/board-pinmux.h
index 4aac73546f54..c5f3f3381e86 100644
--- a/arch/arm/mach-tegra/board-pinmux.h
+++ b/arch/arm/mach-tegra/board-pinmux.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2011,2012, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -15,21 +15,37 @@
#ifndef __MACH_TEGRA_BOARD_PINMUX_H
#define __MACH_TEGRA_BOARD_PINMUX_H
-#define GPIO_DEV "tegra-gpio"
-#define PINMUX_DEV "tegra-pinmux"
+#include <linux/pinctrl/machine.h>
-struct tegra_pingroup_config;
-struct tegra_gpio_table;
+#include <mach/pinconf-tegra.h>
-struct tegra_board_pinmux_conf {
- struct tegra_pingroup_config *pgs;
- int pg_count;
+#define PINMUX_DEV "tegra20-pinctrl"
+
+#define TEGRA_MAP_MUX(_group_, _function_) \
+ PIN_MAP_MUX_GROUP_HOG_DEFAULT(PINMUX_DEV, _group_, _function_)
+
+#define TEGRA_MAP_CONF(_group_, _pull_, _drive_) \
+ PIN_MAP_CONFIGS_GROUP_HOG_DEFAULT(PINMUX_DEV, _group_, tegra_pincfg_pull##_pull_##_##_drive_)
- struct tegra_drive_pingroup_config *drives;
- int drive_count;
+#define TEGRA_MAP_MUXCONF(_group_, _function_, _pull_, _drive_) \
+ TEGRA_MAP_MUX(_group_, _function_), \
+ TEGRA_MAP_CONF(_group_, _pull_, _drive_)
- struct tegra_gpio_table *gpios;
- int gpio_count;
+extern unsigned long tegra_pincfg_pullnone_driven[2];
+extern unsigned long tegra_pincfg_pullnone_tristate[2];
+extern unsigned long tegra_pincfg_pullnone_na[1];
+extern unsigned long tegra_pincfg_pullup_driven[2];
+extern unsigned long tegra_pincfg_pullup_tristate[2];
+extern unsigned long tegra_pincfg_pullup_na[1];
+extern unsigned long tegra_pincfg_pulldown_driven[2];
+extern unsigned long tegra_pincfg_pulldown_tristate[2];
+extern unsigned long tegra_pincfg_pulldown_na[1];
+extern unsigned long tegra_pincfg_pullna_driven[1];
+extern unsigned long tegra_pincfg_pullna_tristate[1];
+
+struct tegra_board_pinmux_conf {
+ struct pinctrl_map *maps;
+ int map_count;
};
void tegra_board_pinmux_init(struct tegra_board_pinmux_conf *conf_a,
diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c
index 55e7e43a14ad..11fc8a568c64 100644
--- a/arch/arm/mach-tegra/board-seaboard-pinmux.c
+++ b/arch/arm/mach-tegra/board-seaboard-pinmux.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010,2011 NVIDIA Corporation
+ * Copyright (C) 2010-2012 NVIDIA Corporation
* Copyright (C) 2011 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
@@ -14,216 +14,176 @@
*/
#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/gpio.h>
-#include <linux/of.h>
-#include <mach/pinmux.h>
-#include <mach/pinmux-tegra20.h>
-
-#include "gpio-names.h"
-#include "board-pinmux.h"
#include "board-seaboard.h"
+#include "board-pinmux.h"
-#define DEFAULT_DRIVE(_name) \
- { \
- .pingroup = TEGRA_DRIVE_PINGROUP_##_name, \
- .hsm = TEGRA_HSM_DISABLE, \
- .schmitt = TEGRA_SCHMITT_ENABLE, \
- .drive = TEGRA_DRIVE_DIV_1, \
- .pull_down = TEGRA_PULL_31, \
- .pull_up = TEGRA_PULL_31, \
- .slew_rising = TEGRA_SLEW_SLOWEST, \
- .slew_falling = TEGRA_SLEW_SLOWEST, \
- }
-
-static struct tegra_drive_pingroup_config seaboard_drive_pinmux[] = {
- DEFAULT_DRIVE(SDIO1),
-};
-
-static struct tegra_pingroup_config common_pinmux[] = {
- {TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_ATB, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_ATC, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_CSUS, TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DAP2, TEGRA_MUX_DAP2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DTA, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DTB, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DTC, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DTD, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DTE, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GMB, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_GMC, TEGRA_MUX_UARTD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GME, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GPU, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GPU7, TEGRA_MUX_RTCK, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GPV, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_I2CP, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_IRRX, TEGRA_MUX_UARTB, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_IRTX, TEGRA_MUX_UARTB, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCA, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCB, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCC, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCD, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCE, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_KBCF, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LCSN, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LD0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD10, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD11, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD12, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD13, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD14, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD15, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD16, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD17, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD3, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD4, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD5, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD6, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD7, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD8, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD9, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LDC, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LHP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LHP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LHP2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LHS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LM0, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LM1, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LPP, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LPW1, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSC0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LSDI, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSPI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LVP0, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LVP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LVS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_OWC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_PMC, TEGRA_MUX_PWR_ON, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_RM, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SDB, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SDC, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SDD, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SLXA, TEGRA_MUX_PCIE, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPID, TEGRA_MUX_SPI1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIE, TEGRA_MUX_SPI1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIF, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_UAD, TEGRA_MUX_IRDA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_UCA, TEGRA_MUX_UARTC, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_UCB, TEGRA_MUX_UARTC, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_UDA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_CK32, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DDRC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCA, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCB, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCD, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCE, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_XM2C, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
-};
-
-static struct tegra_pingroup_config seaboard_pinmux[] = {
- {TEGRA_PINGROUP_DDC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_GMD, TEGRA_MUX_SFLASH, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LPW0, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LPW2, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LSC1, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSCK, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSDA, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_PTA, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
-};
-
-static struct tegra_pingroup_config ventana_pinmux[] = {
- {TEGRA_PINGROUP_DDC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GMD, TEGRA_MUX_SFLASH, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LPW0, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LPW2, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LSC1, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LSCK, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSDA, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_PTA, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SLXK, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+static unsigned long seaboard_pincfg_drive_sdio1[] = {
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE, 0),
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_SCHMITT, 0),
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_LOW_POWER_MODE, 3),
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH, 31),
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH, 31),
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING, 3),
+ TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_SLEW_RATE_RISING, 3),
};
-static struct tegra_gpio_table common_gpio_table[] = {
- { .gpio = TEGRA_GPIO_SD2_CD, .enable = true },
- { .gpio = TEGRA_GPIO_SD2_WP, .enable = true },
- { .gpio = TEGRA_GPIO_SD2_POWER, .enable = true },
- { .gpio = TEGRA_GPIO_CDC_IRQ, .enable = true },
+static struct pinctrl_map common_map[] = {
+ TEGRA_MAP_MUXCONF("ata", "ide", none, driven),
+ TEGRA_MAP_MUXCONF("atb", "sdio4", none, driven),
+ TEGRA_MAP_MUXCONF("atc", "nand", none, driven),
+ TEGRA_MAP_MUXCONF("atd", "gmi", none, driven),
+ TEGRA_MAP_MUXCONF("ate", "gmi", none, tristate),
+ TEGRA_MAP_MUXCONF("cdev1", "plla_out", none, driven),
+ TEGRA_MAP_MUXCONF("cdev2", "pllp_out4", none, driven),
+ TEGRA_MAP_MUXCONF("crtp", "crt", up, tristate),
+ TEGRA_MAP_MUXCONF("csus", "vi_sensor_clk", none, tristate),
+ TEGRA_MAP_MUXCONF("dap1", "dap1", none, driven),
+ TEGRA_MAP_MUXCONF("dap2", "dap2", none, driven),
+ TEGRA_MAP_MUXCONF("dap3", "dap3", none, tristate),
+ TEGRA_MAP_MUXCONF("dap4", "dap4", none, driven),
+ TEGRA_MAP_MUXCONF("dta", "vi", down, driven),
+ TEGRA_MAP_MUXCONF("dtb", "vi", down, driven),
+ TEGRA_MAP_MUXCONF("dtc", "vi", down, driven),
+ TEGRA_MAP_MUXCONF("dtd", "vi", down, driven),
+ TEGRA_MAP_MUXCONF("dte", "vi", down, tristate),
+ TEGRA_MAP_MUXCONF("dtf", "i2c3", none, driven),
+ TEGRA_MAP_MUXCONF("gma", "sdio4", none, driven),
+ TEGRA_MAP_MUXCONF("gmb", "gmi", up, tristate),
+ TEGRA_MAP_MUXCONF("gmc", "uartd", none, driven),
+ TEGRA_MAP_MUXCONF("gme", "sdio4", none, driven),
+ TEGRA_MAP_MUXCONF("gpu", "pwm", none, driven),
+ TEGRA_MAP_MUXCONF("gpu7", "rtck", none, driven),
+ TEGRA_MAP_MUXCONF("gpv", "pcie", none, tristate),
+ TEGRA_MAP_MUXCONF("hdint", "hdmi", na, tristate),
+ TEGRA_MAP_MUXCONF("i2cp", "i2cp", none, driven),
+ TEGRA_MAP_MUXCONF("irrx", "uartb", none, driven),
+ TEGRA_MAP_MUXCONF("irtx", "uartb", none, driven),
+ TEGRA_MAP_MUXCONF("kbca", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("kbcb", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("kbcc", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("kbcd", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("kbce", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("kbcf", "kbc", up, driven),
+ TEGRA_MAP_MUXCONF("lcsn", "rsvd4", na, tristate),
+ TEGRA_MAP_MUXCONF("ld0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld1", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld10", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld11", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld12", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld13", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld14", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld15", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld16", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld17", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld2", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld3", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld4", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld5", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld6", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld7", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld8", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld9", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ldc", "rsvd4", na, tristate),
+ TEGRA_MAP_MUXCONF("ldi", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lhp0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lhp1", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lhp2", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lhs", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lm0", "rsvd4", na, driven),
+ TEGRA_MAP_MUXCONF("lm1", "crt", na, tristate),
+ TEGRA_MAP_MUXCONF("lpp", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lpw1", "rsvd4", na, tristate),
+ TEGRA_MAP_MUXCONF("lsc0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lsdi", "rsvd4", na, tristate),
+ TEGRA_MAP_MUXCONF("lspi", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lvp0", "rsvd4", na, tristate),
+ TEGRA_MAP_MUXCONF("lvp1", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lvs", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("owc", "rsvd2", none, tristate),
+ TEGRA_MAP_MUXCONF("pmc", "pwr_on", na, driven),
+ TEGRA_MAP_MUXCONF("pta", "hdmi", none, driven),
+ TEGRA_MAP_MUXCONF("rm", "i2c1", none, driven),
+ TEGRA_MAP_MUXCONF("sdb", "sdio3", na, driven),
+ TEGRA_MAP_MUXCONF("sdc", "sdio3", none, driven),
+ TEGRA_MAP_MUXCONF("sdd", "sdio3", none, driven),
+ TEGRA_MAP_MUXCONF("sdio1", "sdio1", up, driven),
+ TEGRA_MAP_MUXCONF("slxa", "pcie", up, tristate),
+ TEGRA_MAP_MUXCONF("slxd", "spdif", none, driven),
+ TEGRA_MAP_MUXCONF("slxk", "pcie", none, driven),
+ TEGRA_MAP_MUXCONF("spdi", "rsvd2", none, driven),
+ TEGRA_MAP_MUXCONF("spdo", "rsvd2", none, driven),
+ TEGRA_MAP_MUXCONF("spib", "gmi", none, tristate),
+ TEGRA_MAP_MUXCONF("spid", "spi1", none, tristate),
+ TEGRA_MAP_MUXCONF("spie", "spi1", none, tristate),
+ TEGRA_MAP_MUXCONF("spif", "spi1", down, tristate),
+ TEGRA_MAP_MUXCONF("spih", "spi2_alt", up, tristate),
+ TEGRA_MAP_MUXCONF("uaa", "ulpi", up, driven),
+ TEGRA_MAP_MUXCONF("uab", "ulpi", up, driven),
+ TEGRA_MAP_MUXCONF("uac", "rsvd2", none, driven),
+ TEGRA_MAP_MUXCONF("uad", "irda", none, driven),
+ TEGRA_MAP_MUXCONF("uca", "uartc", none, driven),
+ TEGRA_MAP_MUXCONF("ucb", "uartc", none, driven),
+ TEGRA_MAP_MUXCONF("uda", "ulpi", none, driven),
+ TEGRA_MAP_CONF("ck32", none, na),
+ TEGRA_MAP_CONF("ddrc", none, na),
+ TEGRA_MAP_CONF("pmca", none, na),
+ TEGRA_MAP_CONF("pmcb", none, na),
+ TEGRA_MAP_CONF("pmcc", none, na),
+ TEGRA_MAP_CONF("pmcd", none, na),
+ TEGRA_MAP_CONF("pmce", none, na),
+ TEGRA_MAP_CONF("xm2c", none, na),
+ TEGRA_MAP_CONF("xm2d", none, na),
+ TEGRA_MAP_CONF("ls", up, na),
+ TEGRA_MAP_CONF("lc", up, na),
+ TEGRA_MAP_CONF("ld17_0", down, na),
+ TEGRA_MAP_CONF("ld19_18", down, na),
+ TEGRA_MAP_CONF("ld21_20", down, na),
+ TEGRA_MAP_CONF("ld23_22", down, na),
};
-static struct tegra_gpio_table seaboard_gpio_table[] = {
- { .gpio = TEGRA_GPIO_LIDSWITCH, .enable = true },
- { .gpio = TEGRA_GPIO_POWERKEY, .enable = true },
- { .gpio = TEGRA_GPIO_HP_DET, .enable = true },
- { .gpio = TEGRA_GPIO_ISL29018_IRQ, .enable = true },
- { .gpio = TEGRA_GPIO_USB1, .enable = true },
+static struct pinctrl_map seaboard_map[] = {
+ TEGRA_MAP_MUXCONF("ddc", "rsvd2", none, tristate),
+ TEGRA_MAP_MUXCONF("gmd", "sflash", none, driven),
+ TEGRA_MAP_MUXCONF("lpw0", "hdmi", na, driven),
+ TEGRA_MAP_MUXCONF("lpw2", "hdmi", na, driven),
+ TEGRA_MAP_MUXCONF("lsc1", "hdmi", na, tristate),
+ TEGRA_MAP_MUXCONF("lsck", "hdmi", na, tristate),
+ TEGRA_MAP_MUXCONF("lsda", "hdmi", na, tristate),
+ TEGRA_MAP_MUXCONF("slxc", "spdif", none, tristate),
+ TEGRA_MAP_MUXCONF("spia", "gmi", up, tristate),
+ TEGRA_MAP_MUXCONF("spic", "gmi", up, driven),
+ TEGRA_MAP_MUXCONF("spig", "spi2_alt", up, tristate),
+ PIN_MAP_CONFIGS_GROUP_HOG_DEFAULT(PINMUX_DEV, "drive_sdio1", seaboard_pincfg_drive_sdio1),
};
-static struct tegra_gpio_table ventana_gpio_table[] = {
- /* hp_det */
- { .gpio = TEGRA_GPIO_PW2, .enable = true },
- /* int_mic_en */
- { .gpio = TEGRA_GPIO_PX0, .enable = true },
- /* ext_mic_en */
- { .gpio = TEGRA_GPIO_PX1, .enable = true },
+static struct pinctrl_map ventana_map[] = {
+ TEGRA_MAP_MUXCONF("ddc", "rsvd2", none, driven),
+ TEGRA_MAP_MUXCONF("gmd", "sflash", none, tristate),
+ TEGRA_MAP_MUXCONF("lpw0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lpw2", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lsc1", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lsck", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lsda", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("slxc", "sdio3", none, driven),
+ TEGRA_MAP_MUXCONF("spia", "gmi", none, tristate),
+ TEGRA_MAP_MUXCONF("spic", "gmi", none, tristate),
+ TEGRA_MAP_MUXCONF("spig", "spi2_alt", none, tristate),
};
static struct tegra_board_pinmux_conf common_conf = {
- .pgs = common_pinmux,
- .pg_count = ARRAY_SIZE(common_pinmux),
- .gpios = common_gpio_table,
- .gpio_count = ARRAY_SIZE(common_gpio_table),
+ .maps = common_map,
+ .map_count = ARRAY_SIZE(common_map),
};
static struct tegra_board_pinmux_conf seaboard_conf = {
- .pgs = seaboard_pinmux,
- .pg_count = ARRAY_SIZE(seaboard_pinmux),
- .drives = seaboard_drive_pinmux,
- .drive_count = ARRAY_SIZE(seaboard_drive_pinmux),
- .gpios = seaboard_gpio_table,
- .gpio_count = ARRAY_SIZE(seaboard_gpio_table),
+ .maps = seaboard_map,
+ .map_count = ARRAY_SIZE(seaboard_map),
};
static struct tegra_board_pinmux_conf ventana_conf = {
- .pgs = ventana_pinmux,
- .pg_count = ARRAY_SIZE(ventana_pinmux),
- .gpios = ventana_gpio_table,
- .gpio_count = ARRAY_SIZE(ventana_gpio_table),
+ .maps = ventana_map,
+ .map_count = ARRAY_SIZE(ventana_map),
};
void seaboard_pinmux_init(void)
diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c
index d669847f0485..79064c7a7907 100644
--- a/arch/arm/mach-tegra/board-seaboard.c
+++ b/arch/arm/mach-tegra/board-seaboard.c
@@ -18,12 +18,14 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
+#include <linux/of_serial.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
+#include <linux/platform_data/tegra_usb.h>
#include <sound/wm8903.h>
@@ -47,6 +49,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
/* Memory and IRQ filled in before registration */
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
.type = PORT_TEGRA,
+ .handle_break = tegra_serial_handle_break,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = 216000000,
@@ -153,7 +156,6 @@ static struct platform_device *seaboard_devices[] __initdata = {
&seaboard_gpio_keys_device,
&tegra_i2s_device1,
&tegra_das_device,
- &tegra_pcm_device,
&seaboard_audio_device,
};
@@ -186,20 +188,10 @@ static struct i2c_board_info __initdata wm8903_device = {
static int seaboard_ehci_init(void)
{
- int gpio_status;
+ struct tegra_ehci_platform_data *pdata;
- gpio_status = gpio_request(TEGRA_GPIO_USB1, "VBUS_USB1");
- if (gpio_status < 0) {
- pr_err("VBUS_USB1 request GPIO FAILED\n");
- WARN_ON(1);
- }
-
- gpio_status = gpio_direction_output(TEGRA_GPIO_USB1, 1);
- if (gpio_status < 0) {
- pr_err("VBUS_USB1 request GPIO DIRECTION FAILED\n");
- WARN_ON(1);
- }
- gpio_set_value(TEGRA_GPIO_USB1, 1);
+ pdata = tegra_ehci1_device.dev.platform_data;
+ pdata->vbus_gpio = TEGRA_GPIO_USB1;
platform_device_register(&tegra_ehci1_device);
platform_device_register(&tegra_ehci3_device);
@@ -209,9 +201,6 @@ static int seaboard_ehci_init(void)
static void __init seaboard_i2c_init(void)
{
- gpio_request(TEGRA_GPIO_ISL29018_IRQ, "isl29018");
- gpio_direction_input(TEGRA_GPIO_ISL29018_IRQ);
-
isl29018_device.irq = gpio_to_irq(TEGRA_GPIO_ISL29018_IRQ);
i2c_register_board_info(0, &isl29018_device, 1);
@@ -261,7 +250,6 @@ static void __init tegra_kaen_init(void)
debug_uart_platform_data[0].irq = INT_UARTB;
seaboard_audio_pdata.gpio_hp_mute = TEGRA_GPIO_KAEN_HP_MUTE;
- tegra_gpio_enable(TEGRA_GPIO_KAEN_HP_MUTE);
seaboard_common_init();
diff --git a/arch/arm/mach-tegra/board-trimslice-pinmux.c b/arch/arm/mach-tegra/board-trimslice-pinmux.c
index a21a2be57cb6..7b39511c0d4d 100644
--- a/arch/arm/mach-tegra/board-trimslice-pinmux.c
+++ b/arch/arm/mach-tegra/board-trimslice-pinmux.c
@@ -2,6 +2,7 @@
* arch/arm/mach-tegra/board-trimslice-pinmux.c
*
* Copyright (C) 2011 CompuLab, Ltd.
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -13,150 +14,139 @@
* GNU General Public License for more details.
*
*/
-#include <linux/gpio.h>
#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/of.h>
-#include <mach/pinmux.h>
-#include <mach/pinmux-tegra20.h>
-
-#include "gpio-names.h"
-#include "board-pinmux.h"
#include "board-trimslice.h"
+#include "board-pinmux.h"
-static struct tegra_pingroup_config trimslice_pinmux[] = {
- {TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_ATB, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_ATC, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_CSUS, TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DAP2, TEGRA_MUX_DAP2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DTA, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DTB, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DTC, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DTD, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DTE, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GMB, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_GMC, TEGRA_MUX_SFLASH, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GMD, TEGRA_MUX_SFLASH, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GME, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_GPU, TEGRA_MUX_UARTA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GPU7, TEGRA_MUX_RTCK, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GPV, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_I2CP, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_IRRX, TEGRA_MUX_UARTB, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_IRTX, TEGRA_MUX_UARTB, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_KBCA, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_KBCB, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_KBCC, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_KBCD, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_KBCE, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_KBCF, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LCSN, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LD0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD3, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD4, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD5, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD6, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD7, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD8, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD9, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD10, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD11, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD12, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD13, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD14, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD15, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD16, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LD17, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LDC, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LHP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LHP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LHP2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LHS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LM0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LM1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LPP, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LPW0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LPW1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LPW2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LSC0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LSC1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSCK, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSDA, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LSPI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LVP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LVP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LVS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_OWC, TEGRA_MUX_RSVD2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_PMC, TEGRA_MUX_PWR_ON, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_PTA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_RM, TEGRA_MUX_I2C, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SDB, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SDC, TEGRA_MUX_PWM, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SDD, TEGRA_MUX_PWM, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SLXA, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_SPDI, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPDO, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIA, TEGRA_MUX_SPI2, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIB, TEGRA_MUX_SPI2, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIC, TEGRA_MUX_SPI2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPID, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIE, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIF, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_UAD, TEGRA_MUX_IRDA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UCA, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UCB, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_UDA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_CK32, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DDRC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCA, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCB, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCD, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_PMCE, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_XM2C, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
-};
-
-static struct tegra_gpio_table gpio_table[] = {
- { .gpio = TRIMSLICE_GPIO_SD4_CD, .enable = true }, /* mmc4 cd */
- { .gpio = TRIMSLICE_GPIO_SD4_WP, .enable = true }, /* mmc4 wp */
-
- { .gpio = TRIMSLICE_GPIO_USB1_MODE, .enable = true }, /* USB1 mode */
- { .gpio = TRIMSLICE_GPIO_USB2_RST, .enable = true }, /* USB2 PHY rst */
+static struct pinctrl_map trimslice_map[] = {
+ TEGRA_MAP_MUXCONF("ata", "ide", none, tristate),
+ TEGRA_MAP_MUXCONF("atb", "sdio4", none, driven),
+ TEGRA_MAP_MUXCONF("atc", "nand", none, tristate),
+ TEGRA_MAP_MUXCONF("atd", "gmi", none, tristate),
+ TEGRA_MAP_MUXCONF("ate", "gmi", none, tristate),
+ TEGRA_MAP_MUXCONF("cdev1", "plla_out", none, driven),
+ TEGRA_MAP_MUXCONF("cdev2", "pllp_out4", down, tristate),
+ TEGRA_MAP_MUXCONF("crtp", "crt", none, tristate),
+ TEGRA_MAP_MUXCONF("csus", "vi_sensor_clk", down, tristate),
+ TEGRA_MAP_MUXCONF("dap1", "dap1", none, driven),
+ TEGRA_MAP_MUXCONF("dap2", "dap2", none, tristate),
+ TEGRA_MAP_MUXCONF("dap3", "dap3", none, tristate),
+ TEGRA_MAP_MUXCONF("dap4", "dap4", none, tristate),
+ TEGRA_MAP_MUXCONF("ddc", "i2c2", up, driven),
+ TEGRA_MAP_MUXCONF("dta", "vi", none, tristate),
+ TEGRA_MAP_MUXCONF("dtb", "vi", none, tristate),
+ TEGRA_MAP_MUXCONF("dtc", "vi", none, tristate),
+ TEGRA_MAP_MUXCONF("dtd", "vi", none, tristate),
+ TEGRA_MAP_MUXCONF("dte", "vi", none, tristate),
+ TEGRA_MAP_MUXCONF("dtf", "i2c3", up, driven),
+ TEGRA_MAP_MUXCONF("gma", "sdio4", none, driven),
+ TEGRA_MAP_MUXCONF("gmb", "nand", none, tristate),
+ TEGRA_MAP_MUXCONF("gmc", "sflash", none, driven),
+ TEGRA_MAP_MUXCONF("gmd", "sflash", none, driven),
+ TEGRA_MAP_MUXCONF("gme", "gmi", none, tristate),
+ TEGRA_MAP_MUXCONF("gpu", "uarta", none, driven),
+ TEGRA_MAP_MUXCONF("gpu7", "rtck", none, driven),
+ TEGRA_MAP_MUXCONF("gpv", "pcie", none, driven),
+ TEGRA_MAP_MUXCONF("hdint", "hdmi", na, tristate),
+ TEGRA_MAP_MUXCONF("i2cp", "i2cp", none, tristate),
+ TEGRA_MAP_MUXCONF("irrx", "uartb", up, tristate),
+ TEGRA_MAP_MUXCONF("irtx", "uartb", up, tristate),
+ TEGRA_MAP_MUXCONF("kbca", "kbc", up, tristate),
+ TEGRA_MAP_MUXCONF("kbcb", "kbc", up, tristate),
+ TEGRA_MAP_MUXCONF("kbcc", "kbc", up, tristate),
+ TEGRA_MAP_MUXCONF("kbcd", "kbc", up, tristate),
+ TEGRA_MAP_MUXCONF("kbce", "kbc", up, tristate),
+ TEGRA_MAP_MUXCONF("kbcf", "kbc", up, tristate),
+ TEGRA_MAP_MUXCONF("lcsn", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("ld0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld1", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld10", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld11", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld12", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld13", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld14", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld15", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld16", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld17", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld2", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld3", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld4", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld5", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld6", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld7", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld8", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ld9", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("ldc", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("ldi", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lhp0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lhp1", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lhp2", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lhs", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lm0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lm1", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lpp", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lpw0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lpw1", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lpw2", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lsc0", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lsc1", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lsck", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lsda", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lsdi", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lspi", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lvp0", "displaya", na, tristate),
+ TEGRA_MAP_MUXCONF("lvp1", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("lvs", "displaya", na, driven),
+ TEGRA_MAP_MUXCONF("owc", "rsvd2", up, tristate),
+ TEGRA_MAP_MUXCONF("pmc", "pwr_on", na, tristate),
+ TEGRA_MAP_MUXCONF("pta", "gmi", none, tristate),
+ TEGRA_MAP_MUXCONF("rm", "i2c1", up, driven),
+ TEGRA_MAP_MUXCONF("sdb", "pwm", na, driven),
+ TEGRA_MAP_MUXCONF("sdc", "pwm", up, driven),
+ TEGRA_MAP_MUXCONF("sdd", "pwm", up, driven),
+ TEGRA_MAP_MUXCONF("sdio1", "sdio1", none, driven),
+ TEGRA_MAP_MUXCONF("slxa", "pcie", none, driven),
+ TEGRA_MAP_MUXCONF("slxc", "sdio3", none, tristate),
+ TEGRA_MAP_MUXCONF("slxd", "sdio3", none, tristate),
+ TEGRA_MAP_MUXCONF("slxk", "pcie", none, driven),
+ TEGRA_MAP_MUXCONF("spdi", "spdif", none, tristate),
+ TEGRA_MAP_MUXCONF("spdo", "spdif", none, tristate),
+ TEGRA_MAP_MUXCONF("spia", "spi2", down, tristate),
+ TEGRA_MAP_MUXCONF("spib", "spi2", down, tristate),
+ TEGRA_MAP_MUXCONF("spic", "spi2", up, tristate),
+ TEGRA_MAP_MUXCONF("spid", "spi1", down, tristate),
+ TEGRA_MAP_MUXCONF("spie", "spi1", up, tristate),
+ TEGRA_MAP_MUXCONF("spif", "spi1", down, tristate),
+ TEGRA_MAP_MUXCONF("spig", "spi2_alt", up, tristate),
+ TEGRA_MAP_MUXCONF("spih", "spi2_alt", up, tristate),
+ TEGRA_MAP_MUXCONF("uaa", "ulpi", up, tristate),
+ TEGRA_MAP_MUXCONF("uab", "ulpi", up, tristate),
+ TEGRA_MAP_MUXCONF("uac", "rsvd2", none, driven),
+ TEGRA_MAP_MUXCONF("uad", "irda", up, tristate),
+ TEGRA_MAP_MUXCONF("uca", "uartc", up, tristate),
+ TEGRA_MAP_MUXCONF("ucb", "uartc", up, tristate),
+ TEGRA_MAP_MUXCONF("uda", "ulpi", none, tristate),
+ TEGRA_MAP_CONF("ck32", none, na),
+ TEGRA_MAP_CONF("ddrc", none, na),
+ TEGRA_MAP_CONF("pmca", none, na),
+ TEGRA_MAP_CONF("pmcb", none, na),
+ TEGRA_MAP_CONF("pmcc", none, na),
+ TEGRA_MAP_CONF("pmcd", none, na),
+ TEGRA_MAP_CONF("pmce", none, na),
+ TEGRA_MAP_CONF("xm2c", none, na),
+ TEGRA_MAP_CONF("xm2d", none, na),
+ TEGRA_MAP_CONF("ls", up, na),
+ TEGRA_MAP_CONF("lc", up, na),
+ TEGRA_MAP_CONF("ld17_0", down, na),
+ TEGRA_MAP_CONF("ld19_18", down, na),
+ TEGRA_MAP_CONF("ld21_20", down, na),
+ TEGRA_MAP_CONF("ld23_22", down, na),
};
static struct tegra_board_pinmux_conf conf = {
- .pgs = trimslice_pinmux,
- .pg_count = ARRAY_SIZE(trimslice_pinmux),
- .gpios = gpio_table,
- .gpio_count = ARRAY_SIZE(gpio_table),
+ .maps = trimslice_map,
+ .map_count = ARRAY_SIZE(trimslice_map),
};
void trimslice_pinmux_init(void)
diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c
index cd52820a3e37..bc59b379c6fe 100644
--- a/arch/arm/mach-tegra/board-trimslice.c
+++ b/arch/arm/mach-tegra/board-trimslice.c
@@ -22,9 +22,11 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
+#include <linux/of_serial.h>
#include <linux/io.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
+#include <linux/platform_data/tegra_usb.h>
#include <asm/hardware/gic.h>
#include <asm/mach-types.h>
@@ -48,6 +50,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
.irq = INT_UARTA,
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
.type = PORT_TEGRA,
+ .handle_break = tegra_serial_handle_break,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = 216000000,
@@ -86,7 +89,6 @@ static struct platform_device *trimslice_devices[] __initdata = {
&tegra_sdhci_device4,
&tegra_i2s_device1,
&tegra_das_device,
- &tegra_pcm_device,
&trimslice_audio_device,
};
@@ -111,19 +113,13 @@ static void trimslice_i2c_init(void)
static void trimslice_usb_init(void)
{
- int err;
+ struct tegra_ehci_platform_data *pdata;
- platform_device_register(&tegra_ehci3_device);
+ pdata = tegra_ehci1_device.dev.platform_data;
+ pdata->vbus_gpio = TRIMSLICE_GPIO_USB1_MODE;
+ platform_device_register(&tegra_ehci3_device);
platform_device_register(&tegra_ehci2_device);
-
- err = gpio_request_one(TRIMSLICE_GPIO_USB1_MODE, GPIOF_OUT_INIT_HIGH,
- "usb1mode");
- if (err) {
- pr_err("TrimSlice: failed to obtain USB1 mode gpio: %d\n", err);
- return;
- }
-
platform_device_register(&tegra_ehci1_device);
}
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index 5f6b867e20b4..2d8dfa2faf8f 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -110,7 +110,7 @@ static struct resource pinmux_resource[] = {
};
struct platform_device tegra_pinmux_device = {
- .name = "tegra-pinmux",
+ .name = "tegra20-pinctrl",
.id = -1,
.resource = pinmux_resource,
.num_resources = ARRAY_SIZE(pinmux_resource),
@@ -448,17 +448,20 @@ static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
struct tegra_ehci_platform_data tegra_ehci1_pdata = {
.operating_mode = TEGRA_USB_OTG,
.power_down_on_bus_suspend = 1,
+ .vbus_gpio = -1,
};
struct tegra_ehci_platform_data tegra_ehci2_pdata = {
.phy_config = &tegra_ehci2_ulpi_phy_config,
.operating_mode = TEGRA_USB_HOST,
.power_down_on_bus_suspend = 1,
+ .vbus_gpio = -1,
};
struct tegra_ehci_platform_data tegra_ehci3_pdata = {
.operating_mode = TEGRA_USB_HOST,
.power_down_on_bus_suspend = 1,
+ .vbus_gpio = -1,
};
static u64 tegra_ehci_dmamask = DMA_BIT_MASK(32);
@@ -671,14 +674,14 @@ static struct resource i2s_resource2[] = {
};
struct platform_device tegra_i2s_device1 = {
- .name = "tegra-i2s",
+ .name = "tegra20-i2s",
.id = 0,
.resource = i2s_resource1,
.num_resources = ARRAY_SIZE(i2s_resource1),
};
struct platform_device tegra_i2s_device2 = {
- .name = "tegra-i2s",
+ .name = "tegra20-i2s",
.id = 1,
.resource = i2s_resource2,
.num_resources = ARRAY_SIZE(i2s_resource2),
@@ -693,13 +696,8 @@ static struct resource tegra_das_resources[] = {
};
struct platform_device tegra_das_device = {
- .name = "tegra-das",
+ .name = "tegra20-das",
.id = -1,
.num_resources = ARRAY_SIZE(tegra_das_resources),
.resource = tegra_das_resources,
};
-
-struct platform_device tegra_pcm_device = {
- .name = "tegra-pcm-audio",
- .id = -1,
-};
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
index ec455679b219..138c642e59f4 100644
--- a/arch/arm/mach-tegra/devices.h
+++ b/arch/arm/mach-tegra/devices.h
@@ -52,6 +52,5 @@ extern struct platform_device tegra_pmu_device;
extern struct platform_device tegra_i2s_device1;
extern struct platform_device tegra_i2s_device2;
extern struct platform_device tegra_das_device;
-extern struct platform_device tegra_pcm_device;
#endif
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c
index fef66a7486ed..f07488e0bd32 100644
--- a/arch/arm/mach-tegra/flowctrl.c
+++ b/arch/arm/mach-tegra/flowctrl.c
@@ -53,10 +53,10 @@ static void flowctrl_update(u8 offset, u32 value)
void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value)
{
- return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value);
+ return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value);
}
void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value)
{
- return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value);
+ return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value);
}
diff --git a/arch/arm/mach-tegra/include/mach/dma.h b/arch/arm/mach-tegra/include/mach/dma.h
index 3c9339058bec..9077092812c0 100644
--- a/arch/arm/mach-tegra/include/mach/dma.h
+++ b/arch/arm/mach-tegra/include/mach/dma.h
@@ -51,8 +51,6 @@
#define TEGRA_DMA_REQ_SEL_OWR 25
#define TEGRA_DMA_REQ_SEL_INVALID 31
-#if defined(CONFIG_TEGRA_SYSTEM_DMA)
-
struct tegra_dma_req;
struct tegra_dma_channel;
@@ -151,5 +149,3 @@ void tegra_dma_free_channel(struct tegra_dma_channel *ch);
int __init tegra_dma_init(void);
#endif
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/gpio-tegra.h b/arch/arm/mach-tegra/include/mach/gpio-tegra.h
index 6140820555e1..a978b3cc3a8d 100644
--- a/arch/arm/mach-tegra/include/mach/gpio-tegra.h
+++ b/arch/arm/mach-tegra/include/mach/gpio-tegra.h
@@ -25,13 +25,4 @@
#define TEGRA_NR_GPIOS INT_GPIO_NR
-struct tegra_gpio_table {
- int gpio; /* GPIO number */
- bool enable; /* Enable for GPIO at init? */
-};
-
-void tegra_gpio_config(struct tegra_gpio_table *table, int num);
-void tegra_gpio_enable(int gpio);
-void tegra_gpio_disable(int gpio);
-
#endif
diff --git a/arch/arm/mach-tegra/include/mach/pinmux-tegra20.h b/arch/arm/mach-tegra/include/mach/pinmux-tegra20.h
deleted file mode 100644
index 6a40c1dbab17..000000000000
--- a/arch/arm/mach-tegra/include/mach/pinmux-tegra20.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * linux/arch/arm/mach-tegra/include/mach/pinmux-tegra20.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_PINMUX_TEGRA20_H
-#define __MACH_TEGRA_PINMUX_TEGRA20_H
-
-enum tegra_pingroup {
- TEGRA_PINGROUP_ATA = 0,
- TEGRA_PINGROUP_ATB,
- TEGRA_PINGROUP_ATC,
- TEGRA_PINGROUP_ATD,
- TEGRA_PINGROUP_ATE,
- TEGRA_PINGROUP_CDEV1,
- TEGRA_PINGROUP_CDEV2,
- TEGRA_PINGROUP_CRTP,
- TEGRA_PINGROUP_CSUS,
- TEGRA_PINGROUP_DAP1,
- TEGRA_PINGROUP_DAP2,
- TEGRA_PINGROUP_DAP3,
- TEGRA_PINGROUP_DAP4,
- TEGRA_PINGROUP_DDC,
- TEGRA_PINGROUP_DTA,
- TEGRA_PINGROUP_DTB,
- TEGRA_PINGROUP_DTC,
- TEGRA_PINGROUP_DTD,
- TEGRA_PINGROUP_DTE,
- TEGRA_PINGROUP_DTF,
- TEGRA_PINGROUP_GMA,
- TEGRA_PINGROUP_GMB,
- TEGRA_PINGROUP_GMC,
- TEGRA_PINGROUP_GMD,
- TEGRA_PINGROUP_GME,
- TEGRA_PINGROUP_GPU,
- TEGRA_PINGROUP_GPU7,
- TEGRA_PINGROUP_GPV,
- TEGRA_PINGROUP_HDINT,
- TEGRA_PINGROUP_I2CP,
- TEGRA_PINGROUP_IRRX,
- TEGRA_PINGROUP_IRTX,
- TEGRA_PINGROUP_KBCA,
- TEGRA_PINGROUP_KBCB,
- TEGRA_PINGROUP_KBCC,
- TEGRA_PINGROUP_KBCD,
- TEGRA_PINGROUP_KBCE,
- TEGRA_PINGROUP_KBCF,
- TEGRA_PINGROUP_LCSN,
- TEGRA_PINGROUP_LD0,
- TEGRA_PINGROUP_LD1,
- TEGRA_PINGROUP_LD10,
- TEGRA_PINGROUP_LD11,
- TEGRA_PINGROUP_LD12,
- TEGRA_PINGROUP_LD13,
- TEGRA_PINGROUP_LD14,
- TEGRA_PINGROUP_LD15,
- TEGRA_PINGROUP_LD16,
- TEGRA_PINGROUP_LD17,
- TEGRA_PINGROUP_LD2,
- TEGRA_PINGROUP_LD3,
- TEGRA_PINGROUP_LD4,
- TEGRA_PINGROUP_LD5,
- TEGRA_PINGROUP_LD6,
- TEGRA_PINGROUP_LD7,
- TEGRA_PINGROUP_LD8,
- TEGRA_PINGROUP_LD9,
- TEGRA_PINGROUP_LDC,
- TEGRA_PINGROUP_LDI,
- TEGRA_PINGROUP_LHP0,
- TEGRA_PINGROUP_LHP1,
- TEGRA_PINGROUP_LHP2,
- TEGRA_PINGROUP_LHS,
- TEGRA_PINGROUP_LM0,
- TEGRA_PINGROUP_LM1,
- TEGRA_PINGROUP_LPP,
- TEGRA_PINGROUP_LPW0,
- TEGRA_PINGROUP_LPW1,
- TEGRA_PINGROUP_LPW2,
- TEGRA_PINGROUP_LSC0,
- TEGRA_PINGROUP_LSC1,
- TEGRA_PINGROUP_LSCK,
- TEGRA_PINGROUP_LSDA,
- TEGRA_PINGROUP_LSDI,
- TEGRA_PINGROUP_LSPI,
- TEGRA_PINGROUP_LVP0,
- TEGRA_PINGROUP_LVP1,
- TEGRA_PINGROUP_LVS,
- TEGRA_PINGROUP_OWC,
- TEGRA_PINGROUP_PMC,
- TEGRA_PINGROUP_PTA,
- TEGRA_PINGROUP_RM,
- TEGRA_PINGROUP_SDB,
- TEGRA_PINGROUP_SDC,
- TEGRA_PINGROUP_SDD,
- TEGRA_PINGROUP_SDIO1,
- TEGRA_PINGROUP_SLXA,
- TEGRA_PINGROUP_SLXC,
- TEGRA_PINGROUP_SLXD,
- TEGRA_PINGROUP_SLXK,
- TEGRA_PINGROUP_SPDI,
- TEGRA_PINGROUP_SPDO,
- TEGRA_PINGROUP_SPIA,
- TEGRA_PINGROUP_SPIB,
- TEGRA_PINGROUP_SPIC,
- TEGRA_PINGROUP_SPID,
- TEGRA_PINGROUP_SPIE,
- TEGRA_PINGROUP_SPIF,
- TEGRA_PINGROUP_SPIG,
- TEGRA_PINGROUP_SPIH,
- TEGRA_PINGROUP_UAA,
- TEGRA_PINGROUP_UAB,
- TEGRA_PINGROUP_UAC,
- TEGRA_PINGROUP_UAD,
- TEGRA_PINGROUP_UCA,
- TEGRA_PINGROUP_UCB,
- TEGRA_PINGROUP_UDA,
- /* these pin groups only have pullup and pull down control */
- TEGRA_PINGROUP_CK32,
- TEGRA_PINGROUP_DDRC,
- TEGRA_PINGROUP_PMCA,
- TEGRA_PINGROUP_PMCB,
- TEGRA_PINGROUP_PMCC,
- TEGRA_PINGROUP_PMCD,
- TEGRA_PINGROUP_PMCE,
- TEGRA_PINGROUP_XM2C,
- TEGRA_PINGROUP_XM2D,
- TEGRA_MAX_PINGROUP,
-};
-
-enum tegra_drive_pingroup {
- TEGRA_DRIVE_PINGROUP_AO1 = 0,
- TEGRA_DRIVE_PINGROUP_AO2,
- TEGRA_DRIVE_PINGROUP_AT1,
- TEGRA_DRIVE_PINGROUP_AT2,
- TEGRA_DRIVE_PINGROUP_CDEV1,
- TEGRA_DRIVE_PINGROUP_CDEV2,
- TEGRA_DRIVE_PINGROUP_CSUS,
- TEGRA_DRIVE_PINGROUP_DAP1,
- TEGRA_DRIVE_PINGROUP_DAP2,
- TEGRA_DRIVE_PINGROUP_DAP3,
- TEGRA_DRIVE_PINGROUP_DAP4,
- TEGRA_DRIVE_PINGROUP_DBG,
- TEGRA_DRIVE_PINGROUP_LCD1,
- TEGRA_DRIVE_PINGROUP_LCD2,
- TEGRA_DRIVE_PINGROUP_SDMMC2,
- TEGRA_DRIVE_PINGROUP_SDMMC3,
- TEGRA_DRIVE_PINGROUP_SPI,
- TEGRA_DRIVE_PINGROUP_UAA,
- TEGRA_DRIVE_PINGROUP_UAB,
- TEGRA_DRIVE_PINGROUP_UART2,
- TEGRA_DRIVE_PINGROUP_UART3,
- TEGRA_DRIVE_PINGROUP_VI1,
- TEGRA_DRIVE_PINGROUP_VI2,
- TEGRA_DRIVE_PINGROUP_XM2A,
- TEGRA_DRIVE_PINGROUP_XM2C,
- TEGRA_DRIVE_PINGROUP_XM2D,
- TEGRA_DRIVE_PINGROUP_XM2CLK,
- TEGRA_DRIVE_PINGROUP_MEMCOMP,
- TEGRA_DRIVE_PINGROUP_SDIO1,
- TEGRA_DRIVE_PINGROUP_CRT,
- TEGRA_DRIVE_PINGROUP_DDC,
- TEGRA_DRIVE_PINGROUP_GMA,
- TEGRA_DRIVE_PINGROUP_GMB,
- TEGRA_DRIVE_PINGROUP_GMC,
- TEGRA_DRIVE_PINGROUP_GMD,
- TEGRA_DRIVE_PINGROUP_GME,
- TEGRA_DRIVE_PINGROUP_OWR,
- TEGRA_DRIVE_PINGROUP_UAD,
- TEGRA_MAX_DRIVE_PINGROUP,
-};
-
-#endif
-
diff --git a/arch/arm/mach-tegra/include/mach/pinmux-tegra30.h b/arch/arm/mach-tegra/include/mach/pinmux-tegra30.h
deleted file mode 100644
index c1aee3eb2df1..000000000000
--- a/arch/arm/mach-tegra/include/mach/pinmux-tegra30.h
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * linux/arch/arm/mach-tegra/include/mach/pinmux-tegra30.h
- *
- * Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2010,2011 Nvidia, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_PINMUX_TEGRA30_H
-#define __MACH_TEGRA_PINMUX_TEGRA30_H
-
-enum tegra_pingroup {
- TEGRA_PINGROUP_ULPI_DATA0 = 0,
- TEGRA_PINGROUP_ULPI_DATA1,
- TEGRA_PINGROUP_ULPI_DATA2,
- TEGRA_PINGROUP_ULPI_DATA3,
- TEGRA_PINGROUP_ULPI_DATA4,
- TEGRA_PINGROUP_ULPI_DATA5,
- TEGRA_PINGROUP_ULPI_DATA6,
- TEGRA_PINGROUP_ULPI_DATA7,
- TEGRA_PINGROUP_ULPI_CLK,
- TEGRA_PINGROUP_ULPI_DIR,
- TEGRA_PINGROUP_ULPI_NXT,
- TEGRA_PINGROUP_ULPI_STP,
- TEGRA_PINGROUP_DAP3_FS,
- TEGRA_PINGROUP_DAP3_DIN,
- TEGRA_PINGROUP_DAP3_DOUT,
- TEGRA_PINGROUP_DAP3_SCLK,
- TEGRA_PINGROUP_GPIO_PV0,
- TEGRA_PINGROUP_GPIO_PV1,
- TEGRA_PINGROUP_SDMMC1_CLK,
- TEGRA_PINGROUP_SDMMC1_CMD,
- TEGRA_PINGROUP_SDMMC1_DAT3,
- TEGRA_PINGROUP_SDMMC1_DAT2,
- TEGRA_PINGROUP_SDMMC1_DAT1,
- TEGRA_PINGROUP_SDMMC1_DAT0,
- TEGRA_PINGROUP_GPIO_PV2,
- TEGRA_PINGROUP_GPIO_PV3,
- TEGRA_PINGROUP_CLK2_OUT,
- TEGRA_PINGROUP_CLK2_REQ,
- TEGRA_PINGROUP_LCD_PWR1,
- TEGRA_PINGROUP_LCD_PWR2,
- TEGRA_PINGROUP_LCD_SDIN,
- TEGRA_PINGROUP_LCD_SDOUT,
- TEGRA_PINGROUP_LCD_WR_N,
- TEGRA_PINGROUP_LCD_CS0_N,
- TEGRA_PINGROUP_LCD_DC0,
- TEGRA_PINGROUP_LCD_SCK,
- TEGRA_PINGROUP_LCD_PWR0,
- TEGRA_PINGROUP_LCD_PCLK,
- TEGRA_PINGROUP_LCD_DE,
- TEGRA_PINGROUP_LCD_HSYNC,
- TEGRA_PINGROUP_LCD_VSYNC,
- TEGRA_PINGROUP_LCD_D0,
- TEGRA_PINGROUP_LCD_D1,
- TEGRA_PINGROUP_LCD_D2,
- TEGRA_PINGROUP_LCD_D3,
- TEGRA_PINGROUP_LCD_D4,
- TEGRA_PINGROUP_LCD_D5,
- TEGRA_PINGROUP_LCD_D6,
- TEGRA_PINGROUP_LCD_D7,
- TEGRA_PINGROUP_LCD_D8,
- TEGRA_PINGROUP_LCD_D9,
- TEGRA_PINGROUP_LCD_D10,
- TEGRA_PINGROUP_LCD_D11,
- TEGRA_PINGROUP_LCD_D12,
- TEGRA_PINGROUP_LCD_D13,
- TEGRA_PINGROUP_LCD_D14,
- TEGRA_PINGROUP_LCD_D15,
- TEGRA_PINGROUP_LCD_D16,
- TEGRA_PINGROUP_LCD_D17,
- TEGRA_PINGROUP_LCD_D18,
- TEGRA_PINGROUP_LCD_D19,
- TEGRA_PINGROUP_LCD_D20,
- TEGRA_PINGROUP_LCD_D21,
- TEGRA_PINGROUP_LCD_D22,
- TEGRA_PINGROUP_LCD_D23,
- TEGRA_PINGROUP_LCD_CS1_N,
- TEGRA_PINGROUP_LCD_M1,
- TEGRA_PINGROUP_LCD_DC1,
- TEGRA_PINGROUP_HDMI_INT,
- TEGRA_PINGROUP_DDC_SCL,
- TEGRA_PINGROUP_DDC_SDA,
- TEGRA_PINGROUP_CRT_HSYNC,
- TEGRA_PINGROUP_CRT_VSYNC,
- TEGRA_PINGROUP_VI_D0,
- TEGRA_PINGROUP_VI_D1,
- TEGRA_PINGROUP_VI_D2,
- TEGRA_PINGROUP_VI_D3,
- TEGRA_PINGROUP_VI_D4,
- TEGRA_PINGROUP_VI_D5,
- TEGRA_PINGROUP_VI_D6,
- TEGRA_PINGROUP_VI_D7,
- TEGRA_PINGROUP_VI_D8,
- TEGRA_PINGROUP_VI_D9,
- TEGRA_PINGROUP_VI_D10,
- TEGRA_PINGROUP_VI_D11,
- TEGRA_PINGROUP_VI_PCLK,
- TEGRA_PINGROUP_VI_MCLK,
- TEGRA_PINGROUP_VI_VSYNC,
- TEGRA_PINGROUP_VI_HSYNC,
- TEGRA_PINGROUP_UART2_RXD,
- TEGRA_PINGROUP_UART2_TXD,
- TEGRA_PINGROUP_UART2_RTS_N,
- TEGRA_PINGROUP_UART2_CTS_N,
- TEGRA_PINGROUP_UART3_TXD,
- TEGRA_PINGROUP_UART3_RXD,
- TEGRA_PINGROUP_UART3_CTS_N,
- TEGRA_PINGROUP_UART3_RTS_N,
- TEGRA_PINGROUP_GPIO_PU0,
- TEGRA_PINGROUP_GPIO_PU1,
- TEGRA_PINGROUP_GPIO_PU2,
- TEGRA_PINGROUP_GPIO_PU3,
- TEGRA_PINGROUP_GPIO_PU4,
- TEGRA_PINGROUP_GPIO_PU5,
- TEGRA_PINGROUP_GPIO_PU6,
- TEGRA_PINGROUP_GEN1_I2C_SDA,
- TEGRA_PINGROUP_GEN1_I2C_SCL,
- TEGRA_PINGROUP_DAP4_FS,
- TEGRA_PINGROUP_DAP4_DIN,
- TEGRA_PINGROUP_DAP4_DOUT,
- TEGRA_PINGROUP_DAP4_SCLK,
- TEGRA_PINGROUP_CLK3_OUT,
- TEGRA_PINGROUP_CLK3_REQ,
- TEGRA_PINGROUP_GMI_WP_N,
- TEGRA_PINGROUP_GMI_IORDY,
- TEGRA_PINGROUP_GMI_WAIT,
- TEGRA_PINGROUP_GMI_ADV_N,
- TEGRA_PINGROUP_GMI_CLK,
- TEGRA_PINGROUP_GMI_CS0_N,
- TEGRA_PINGROUP_GMI_CS1_N,
- TEGRA_PINGROUP_GMI_CS2_N,
- TEGRA_PINGROUP_GMI_CS3_N,
- TEGRA_PINGROUP_GMI_CS4_N,
- TEGRA_PINGROUP_GMI_CS6_N,
- TEGRA_PINGROUP_GMI_CS7_N,
- TEGRA_PINGROUP_GMI_AD0,
- TEGRA_PINGROUP_GMI_AD1,
- TEGRA_PINGROUP_GMI_AD2,
- TEGRA_PINGROUP_GMI_AD3,
- TEGRA_PINGROUP_GMI_AD4,
- TEGRA_PINGROUP_GMI_AD5,
- TEGRA_PINGROUP_GMI_AD6,
- TEGRA_PINGROUP_GMI_AD7,
- TEGRA_PINGROUP_GMI_AD8,
- TEGRA_PINGROUP_GMI_AD9,
- TEGRA_PINGROUP_GMI_AD10,
- TEGRA_PINGROUP_GMI_AD11,
- TEGRA_PINGROUP_GMI_AD12,
- TEGRA_PINGROUP_GMI_AD13,
- TEGRA_PINGROUP_GMI_AD14,
- TEGRA_PINGROUP_GMI_AD15,
- TEGRA_PINGROUP_GMI_A16,
- TEGRA_PINGROUP_GMI_A17,
- TEGRA_PINGROUP_GMI_A18,
- TEGRA_PINGROUP_GMI_A19,
- TEGRA_PINGROUP_GMI_WR_N,
- TEGRA_PINGROUP_GMI_OE_N,
- TEGRA_PINGROUP_GMI_DQS,
- TEGRA_PINGROUP_GMI_RST_N,
- TEGRA_PINGROUP_GEN2_I2C_SCL,
- TEGRA_PINGROUP_GEN2_I2C_SDA,
- TEGRA_PINGROUP_SDMMC4_CLK,
- TEGRA_PINGROUP_SDMMC4_CMD,
- TEGRA_PINGROUP_SDMMC4_DAT0,
- TEGRA_PINGROUP_SDMMC4_DAT1,
- TEGRA_PINGROUP_SDMMC4_DAT2,
- TEGRA_PINGROUP_SDMMC4_DAT3,
- TEGRA_PINGROUP_SDMMC4_DAT4,
- TEGRA_PINGROUP_SDMMC4_DAT5,
- TEGRA_PINGROUP_SDMMC4_DAT6,
- TEGRA_PINGROUP_SDMMC4_DAT7,
- TEGRA_PINGROUP_SDMMC4_RST_N,
- TEGRA_PINGROUP_CAM_MCLK,
- TEGRA_PINGROUP_GPIO_PCC1,
- TEGRA_PINGROUP_GPIO_PBB0,
- TEGRA_PINGROUP_CAM_I2C_SCL,
- TEGRA_PINGROUP_CAM_I2C_SDA,
- TEGRA_PINGROUP_GPIO_PBB3,
- TEGRA_PINGROUP_GPIO_PBB4,
- TEGRA_PINGROUP_GPIO_PBB5,
- TEGRA_PINGROUP_GPIO_PBB6,
- TEGRA_PINGROUP_GPIO_PBB7,
- TEGRA_PINGROUP_GPIO_PCC2,
- TEGRA_PINGROUP_JTAG_RTCK,
- TEGRA_PINGROUP_PWR_I2C_SCL,
- TEGRA_PINGROUP_PWR_I2C_SDA,
- TEGRA_PINGROUP_KB_ROW0,
- TEGRA_PINGROUP_KB_ROW1,
- TEGRA_PINGROUP_KB_ROW2,
- TEGRA_PINGROUP_KB_ROW3,
- TEGRA_PINGROUP_KB_ROW4,
- TEGRA_PINGROUP_KB_ROW5,
- TEGRA_PINGROUP_KB_ROW6,
- TEGRA_PINGROUP_KB_ROW7,
- TEGRA_PINGROUP_KB_ROW8,
- TEGRA_PINGROUP_KB_ROW9,
- TEGRA_PINGROUP_KB_ROW10,
- TEGRA_PINGROUP_KB_ROW11,
- TEGRA_PINGROUP_KB_ROW12,
- TEGRA_PINGROUP_KB_ROW13,
- TEGRA_PINGROUP_KB_ROW14,
- TEGRA_PINGROUP_KB_ROW15,
- TEGRA_PINGROUP_KB_COL0,
- TEGRA_PINGROUP_KB_COL1,
- TEGRA_PINGROUP_KB_COL2,
- TEGRA_PINGROUP_KB_COL3,
- TEGRA_PINGROUP_KB_COL4,
- TEGRA_PINGROUP_KB_COL5,
- TEGRA_PINGROUP_KB_COL6,
- TEGRA_PINGROUP_KB_COL7,
- TEGRA_PINGROUP_CLK_32K_OUT,
- TEGRA_PINGROUP_SYS_CLK_REQ,
- TEGRA_PINGROUP_CORE_PWR_REQ,
- TEGRA_PINGROUP_CPU_PWR_REQ,
- TEGRA_PINGROUP_PWR_INT_N,
- TEGRA_PINGROUP_CLK_32K_IN,
- TEGRA_PINGROUP_OWR,
- TEGRA_PINGROUP_DAP1_FS,
- TEGRA_PINGROUP_DAP1_DIN,
- TEGRA_PINGROUP_DAP1_DOUT,
- TEGRA_PINGROUP_DAP1_SCLK,
- TEGRA_PINGROUP_CLK1_REQ,
- TEGRA_PINGROUP_CLK1_OUT,
- TEGRA_PINGROUP_SPDIF_IN,
- TEGRA_PINGROUP_SPDIF_OUT,
- TEGRA_PINGROUP_DAP2_FS,
- TEGRA_PINGROUP_DAP2_DIN,
- TEGRA_PINGROUP_DAP2_DOUT,
- TEGRA_PINGROUP_DAP2_SCLK,
- TEGRA_PINGROUP_SPI2_MOSI,
- TEGRA_PINGROUP_SPI2_MISO,
- TEGRA_PINGROUP_SPI2_CS0_N,
- TEGRA_PINGROUP_SPI2_SCK,
- TEGRA_PINGROUP_SPI1_MOSI,
- TEGRA_PINGROUP_SPI1_SCK,
- TEGRA_PINGROUP_SPI1_CS0_N,
- TEGRA_PINGROUP_SPI1_MISO,
- TEGRA_PINGROUP_SPI2_CS1_N,
- TEGRA_PINGROUP_SPI2_CS2_N,
- TEGRA_PINGROUP_SDMMC3_CLK,
- TEGRA_PINGROUP_SDMMC3_CMD,
- TEGRA_PINGROUP_SDMMC3_DAT0,
- TEGRA_PINGROUP_SDMMC3_DAT1,
- TEGRA_PINGROUP_SDMMC3_DAT2,
- TEGRA_PINGROUP_SDMMC3_DAT3,
- TEGRA_PINGROUP_SDMMC3_DAT4,
- TEGRA_PINGROUP_SDMMC3_DAT5,
- TEGRA_PINGROUP_SDMMC3_DAT6,
- TEGRA_PINGROUP_SDMMC3_DAT7,
- TEGRA_PINGROUP_PEX_L0_PRSNT_N,
- TEGRA_PINGROUP_PEX_L0_RST_N,
- TEGRA_PINGROUP_PEX_L0_CLKREQ_N,
- TEGRA_PINGROUP_PEX_WAKE_N,
- TEGRA_PINGROUP_PEX_L1_PRSNT_N,
- TEGRA_PINGROUP_PEX_L1_RST_N,
- TEGRA_PINGROUP_PEX_L1_CLKREQ_N,
- TEGRA_PINGROUP_PEX_L2_PRSNT_N,
- TEGRA_PINGROUP_PEX_L2_RST_N,
- TEGRA_PINGROUP_PEX_L2_CLKREQ_N,
- TEGRA_PINGROUP_HDMI_CEC,
- TEGRA_MAX_PINGROUP,
-};
-
-enum tegra_drive_pingroup {
- TEGRA_DRIVE_PINGROUP_AO1 = 0,
- TEGRA_DRIVE_PINGROUP_AO2,
- TEGRA_DRIVE_PINGROUP_AT1,
- TEGRA_DRIVE_PINGROUP_AT2,
- TEGRA_DRIVE_PINGROUP_AT3,
- TEGRA_DRIVE_PINGROUP_AT4,
- TEGRA_DRIVE_PINGROUP_AT5,
- TEGRA_DRIVE_PINGROUP_CDEV1,
- TEGRA_DRIVE_PINGROUP_CDEV2,
- TEGRA_DRIVE_PINGROUP_CSUS,
- TEGRA_DRIVE_PINGROUP_DAP1,
- TEGRA_DRIVE_PINGROUP_DAP2,
- TEGRA_DRIVE_PINGROUP_DAP3,
- TEGRA_DRIVE_PINGROUP_DAP4,
- TEGRA_DRIVE_PINGROUP_DBG,
- TEGRA_DRIVE_PINGROUP_LCD1,
- TEGRA_DRIVE_PINGROUP_LCD2,
- TEGRA_DRIVE_PINGROUP_SDIO2,
- TEGRA_DRIVE_PINGROUP_SDIO3,
- TEGRA_DRIVE_PINGROUP_SPI,
- TEGRA_DRIVE_PINGROUP_UAA,
- TEGRA_DRIVE_PINGROUP_UAB,
- TEGRA_DRIVE_PINGROUP_UART2,
- TEGRA_DRIVE_PINGROUP_UART3,
- TEGRA_DRIVE_PINGROUP_VI1,
- TEGRA_DRIVE_PINGROUP_SDIO1,
- TEGRA_DRIVE_PINGROUP_CRT,
- TEGRA_DRIVE_PINGROUP_DDC,
- TEGRA_DRIVE_PINGROUP_GMA,
- TEGRA_DRIVE_PINGROUP_GMB,
- TEGRA_DRIVE_PINGROUP_GMC,
- TEGRA_DRIVE_PINGROUP_GMD,
- TEGRA_DRIVE_PINGROUP_GME,
- TEGRA_DRIVE_PINGROUP_GMF,
- TEGRA_DRIVE_PINGROUP_GMG,
- TEGRA_DRIVE_PINGROUP_GMH,
- TEGRA_DRIVE_PINGROUP_OWR,
- TEGRA_DRIVE_PINGROUP_UAD,
- TEGRA_DRIVE_PINGROUP_GPV,
- TEGRA_DRIVE_PINGROUP_DEV3,
- TEGRA_DRIVE_PINGROUP_CEC,
- TEGRA_MAX_DRIVE_PINGROUP,
-};
-
-#endif
-
diff --git a/arch/arm/mach-tegra/include/mach/pinmux.h b/arch/arm/mach-tegra/include/mach/pinmux.h
deleted file mode 100644
index 055f1792c8ff..000000000000
--- a/arch/arm/mach-tegra/include/mach/pinmux.h
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * linux/arch/arm/mach-tegra/include/mach/pinmux.h
- *
- * Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2010,2011 Nvidia, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_PINMUX_H
-#define __MACH_TEGRA_PINMUX_H
-
-enum tegra_mux_func {
- TEGRA_MUX_RSVD = 0x8000,
- TEGRA_MUX_RSVD1 = 0x8000,
- TEGRA_MUX_RSVD2 = 0x8001,
- TEGRA_MUX_RSVD3 = 0x8002,
- TEGRA_MUX_RSVD4 = 0x8003,
- TEGRA_MUX_INVALID = 0x4000,
- TEGRA_MUX_NONE = -1,
- TEGRA_MUX_AHB_CLK,
- TEGRA_MUX_APB_CLK,
- TEGRA_MUX_AUDIO_SYNC,
- TEGRA_MUX_CRT,
- TEGRA_MUX_DAP1,
- TEGRA_MUX_DAP2,
- TEGRA_MUX_DAP3,
- TEGRA_MUX_DAP4,
- TEGRA_MUX_DAP5,
- TEGRA_MUX_DISPLAYA,
- TEGRA_MUX_DISPLAYB,
- TEGRA_MUX_EMC_TEST0_DLL,
- TEGRA_MUX_EMC_TEST1_DLL,
- TEGRA_MUX_GMI,
- TEGRA_MUX_GMI_INT,
- TEGRA_MUX_HDMI,
- TEGRA_MUX_I2C,
- TEGRA_MUX_I2C2,
- TEGRA_MUX_I2C3,
- TEGRA_MUX_IDE,
- TEGRA_MUX_IRDA,
- TEGRA_MUX_KBC,
- TEGRA_MUX_MIO,
- TEGRA_MUX_MIPI_HS,
- TEGRA_MUX_NAND,
- TEGRA_MUX_OSC,
- TEGRA_MUX_OWR,
- TEGRA_MUX_PCIE,
- TEGRA_MUX_PLLA_OUT,
- TEGRA_MUX_PLLC_OUT1,
- TEGRA_MUX_PLLM_OUT1,
- TEGRA_MUX_PLLP_OUT2,
- TEGRA_MUX_PLLP_OUT3,
- TEGRA_MUX_PLLP_OUT4,
- TEGRA_MUX_PWM,
- TEGRA_MUX_PWR_INTR,
- TEGRA_MUX_PWR_ON,
- TEGRA_MUX_RTCK,
- TEGRA_MUX_SDIO1,
- TEGRA_MUX_SDIO2,
- TEGRA_MUX_SDIO3,
- TEGRA_MUX_SDIO4,
- TEGRA_MUX_SFLASH,
- TEGRA_MUX_SPDIF,
- TEGRA_MUX_SPI1,
- TEGRA_MUX_SPI2,
- TEGRA_MUX_SPI2_ALT,
- TEGRA_MUX_SPI3,
- TEGRA_MUX_SPI4,
- TEGRA_MUX_TRACE,
- TEGRA_MUX_TWC,
- TEGRA_MUX_UARTA,
- TEGRA_MUX_UARTB,
- TEGRA_MUX_UARTC,
- TEGRA_MUX_UARTD,
- TEGRA_MUX_UARTE,
- TEGRA_MUX_ULPI,
- TEGRA_MUX_VI,
- TEGRA_MUX_VI_SENSOR_CLK,
- TEGRA_MUX_XIO,
- TEGRA_MUX_BLINK,
- TEGRA_MUX_CEC,
- TEGRA_MUX_CLK12,
- TEGRA_MUX_DAP,
- TEGRA_MUX_DAPSDMMC2,
- TEGRA_MUX_DDR,
- TEGRA_MUX_DEV3,
- TEGRA_MUX_DTV,
- TEGRA_MUX_VI_ALT1,
- TEGRA_MUX_VI_ALT2,
- TEGRA_MUX_VI_ALT3,
- TEGRA_MUX_EMC_DLL,
- TEGRA_MUX_EXTPERIPH1,
- TEGRA_MUX_EXTPERIPH2,
- TEGRA_MUX_EXTPERIPH3,
- TEGRA_MUX_GMI_ALT,
- TEGRA_MUX_HDA,
- TEGRA_MUX_HSI,
- TEGRA_MUX_I2C4,
- TEGRA_MUX_I2C5,
- TEGRA_MUX_I2CPWR,
- TEGRA_MUX_I2S0,
- TEGRA_MUX_I2S1,
- TEGRA_MUX_I2S2,
- TEGRA_MUX_I2S3,
- TEGRA_MUX_I2S4,
- TEGRA_MUX_NAND_ALT,
- TEGRA_MUX_POPSDIO4,
- TEGRA_MUX_POPSDMMC4,
- TEGRA_MUX_PWM0,
- TEGRA_MUX_PWM1,
- TEGRA_MUX_PWM2,
- TEGRA_MUX_PWM3,
- TEGRA_MUX_SATA,
- TEGRA_MUX_SPI5,
- TEGRA_MUX_SPI6,
- TEGRA_MUX_SYSCLK,
- TEGRA_MUX_VGP1,
- TEGRA_MUX_VGP2,
- TEGRA_MUX_VGP3,
- TEGRA_MUX_VGP4,
- TEGRA_MUX_VGP5,
- TEGRA_MUX_VGP6,
- TEGRA_MUX_SAFE,
- TEGRA_MAX_MUX,
-};
-
-enum tegra_pullupdown {
- TEGRA_PUPD_NORMAL = 0,
- TEGRA_PUPD_PULL_DOWN,
- TEGRA_PUPD_PULL_UP,
-};
-
-enum tegra_tristate {
- TEGRA_TRI_NORMAL = 0,
- TEGRA_TRI_TRISTATE = 1,
-};
-
-enum tegra_pin_io {
- TEGRA_PIN_OUTPUT = 0,
- TEGRA_PIN_INPUT = 1,
-};
-
-enum tegra_vddio {
- TEGRA_VDDIO_BB = 0,
- TEGRA_VDDIO_LCD,
- TEGRA_VDDIO_VI,
- TEGRA_VDDIO_UART,
- TEGRA_VDDIO_DDR,
- TEGRA_VDDIO_NAND,
- TEGRA_VDDIO_SYS,
- TEGRA_VDDIO_AUDIO,
- TEGRA_VDDIO_SD,
- TEGRA_VDDIO_CAM,
- TEGRA_VDDIO_GMI,
- TEGRA_VDDIO_PEXCTL,
- TEGRA_VDDIO_SDMMC1,
- TEGRA_VDDIO_SDMMC3,
- TEGRA_VDDIO_SDMMC4,
-};
-
-struct tegra_pingroup_config {
- int pingroup;
- enum tegra_mux_func func;
- enum tegra_pullupdown pupd;
- enum tegra_tristate tristate;
-};
-
-enum tegra_slew {
- TEGRA_SLEW_FASTEST = 0,
- TEGRA_SLEW_FAST,
- TEGRA_SLEW_SLOW,
- TEGRA_SLEW_SLOWEST,
- TEGRA_MAX_SLEW,
-};
-
-enum tegra_pull_strength {
- TEGRA_PULL_0 = 0,
- TEGRA_PULL_1,
- TEGRA_PULL_2,
- TEGRA_PULL_3,
- TEGRA_PULL_4,
- TEGRA_PULL_5,
- TEGRA_PULL_6,
- TEGRA_PULL_7,
- TEGRA_PULL_8,
- TEGRA_PULL_9,
- TEGRA_PULL_10,
- TEGRA_PULL_11,
- TEGRA_PULL_12,
- TEGRA_PULL_13,
- TEGRA_PULL_14,
- TEGRA_PULL_15,
- TEGRA_PULL_16,
- TEGRA_PULL_17,
- TEGRA_PULL_18,
- TEGRA_PULL_19,
- TEGRA_PULL_20,
- TEGRA_PULL_21,
- TEGRA_PULL_22,
- TEGRA_PULL_23,
- TEGRA_PULL_24,
- TEGRA_PULL_25,
- TEGRA_PULL_26,
- TEGRA_PULL_27,
- TEGRA_PULL_28,
- TEGRA_PULL_29,
- TEGRA_PULL_30,
- TEGRA_PULL_31,
- TEGRA_MAX_PULL,
-};
-
-enum tegra_drive {
- TEGRA_DRIVE_DIV_8 = 0,
- TEGRA_DRIVE_DIV_4,
- TEGRA_DRIVE_DIV_2,
- TEGRA_DRIVE_DIV_1,
- TEGRA_MAX_DRIVE,
-};
-
-enum tegra_hsm {
- TEGRA_HSM_DISABLE = 0,
- TEGRA_HSM_ENABLE,
-};
-
-enum tegra_schmitt {
- TEGRA_SCHMITT_DISABLE = 0,
- TEGRA_SCHMITT_ENABLE,
-};
-
-struct tegra_drive_pingroup_config {
- int pingroup;
- enum tegra_hsm hsm;
- enum tegra_schmitt schmitt;
- enum tegra_drive drive;
- enum tegra_pull_strength pull_down;
- enum tegra_pull_strength pull_up;
- enum tegra_slew slew_rising;
- enum tegra_slew slew_falling;
-};
-
-struct tegra_drive_pingroup_desc {
- const char *name;
- s16 reg_bank;
- s16 reg;
-};
-
-struct tegra_pingroup_desc {
- const char *name;
- int funcs[4];
- int func_safe;
- int vddio;
- enum tegra_pin_io io_default;
- s16 tri_bank; /* Register bank the tri_reg exists within */
- s16 mux_bank; /* Register bank the mux_reg exists within */
- s16 pupd_bank; /* Register bank the pupd_reg exists within */
- s16 tri_reg; /* offset into the TRISTATE_REG_* register bank */
- s16 mux_reg; /* offset into the PIN_MUX_CTL_* register bank */
- s16 pupd_reg; /* offset into the PULL_UPDOWN_REG_* register bank */
- s8 tri_bit; /* offset into the TRISTATE_REG_* register bit */
- s8 mux_bit; /* offset into the PIN_MUX_CTL_* register bit */
- s8 pupd_bit; /* offset into the PULL_UPDOWN_REG_* register bit */
- s8 lock_bit; /* offset of the LOCK bit into mux register bit */
- s8 od_bit; /* offset of the OD bit into mux register bit */
- s8 ioreset_bit; /* offset of the IO_RESET bit into mux register bit */
-};
-
-typedef void (*pinmux_init) (const struct tegra_pingroup_desc **pg,
- int *pg_max, const struct tegra_drive_pingroup_desc **pgdrive,
- int *pgdrive_max);
-
-void tegra20_pinmux_init(const struct tegra_pingroup_desc **pg, int *pg_max,
- const struct tegra_drive_pingroup_desc **pgdrive, int *pgdrive_max);
-
-void tegra30_pinmux_init(const struct tegra_pingroup_desc **pg, int *pg_max,
- const struct tegra_drive_pingroup_desc **pgdrive, int *pgdrive_max);
-
-int tegra_pinmux_set_tristate(int pg, enum tegra_tristate tristate);
-int tegra_pinmux_set_pullupdown(int pg, enum tegra_pullupdown pupd);
-
-void tegra_pinmux_config_table(const struct tegra_pingroup_config *config,
- int len);
-
-void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config,
- int len);
-void tegra_pinmux_set_safe_pinmux_table(const struct tegra_pingroup_config *config,
- int len);
-void tegra_pinmux_config_pinmux_table(const struct tegra_pingroup_config *config,
- int len);
-void tegra_pinmux_config_tristate_table(const struct tegra_pingroup_config *config,
- int len, enum tegra_tristate tristate);
-void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *config,
- int len, enum tegra_pullupdown pupd);
-#endif
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index 54a816ff3847..0e09137506ec 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -475,7 +475,6 @@ static struct hw_pci tegra_pcie_hw __initdata = {
.nr_controllers = 2,
.setup = tegra_pcie_setup,
.scan = tegra_pcie_scan_bus,
- .swizzle = pci_std_swizzle,
.map_irq = tegra_pcie_map_irq,
};
diff --git a/arch/arm/mach-tegra/pinmux-tegra20-tables.c b/arch/arm/mach-tegra/pinmux-tegra20-tables.c
deleted file mode 100644
index 734add1280b7..000000000000
--- a/arch/arm/mach-tegra/pinmux-tegra20-tables.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * linux/arch/arm/mach-tegra/pinmux-tegra20-tables.c
- *
- * Common pinmux configurations for Tegra20 SoCs
- *
- * Copyright (C) 2010 NVIDIA Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/init.h>
-#include <linux/string.h>
-
-#include <mach/iomap.h>
-#include <mach/pinmux.h>
-#include <mach/pinmux-tegra20.h>
-#include <mach/suspend.h>
-
-#define TRISTATE_REG_A 0x14
-#define PIN_MUX_CTL_REG_A 0x80
-#define PULLUPDOWN_REG_A 0xa0
-#define PINGROUP_REG_A 0x868
-
-#define DRIVE_PINGROUP(pg_name, r) \
- [TEGRA_DRIVE_PINGROUP_ ## pg_name] = { \
- .name = #pg_name, \
- .reg_bank = 3, \
- .reg = ((r) - PINGROUP_REG_A) \
- }
-
-static const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = {
- DRIVE_PINGROUP(AO1, 0x868),
- DRIVE_PINGROUP(AO2, 0x86c),
- DRIVE_PINGROUP(AT1, 0x870),
- DRIVE_PINGROUP(AT2, 0x874),
- DRIVE_PINGROUP(CDEV1, 0x878),
- DRIVE_PINGROUP(CDEV2, 0x87c),
- DRIVE_PINGROUP(CSUS, 0x880),
- DRIVE_PINGROUP(DAP1, 0x884),
- DRIVE_PINGROUP(DAP2, 0x888),
- DRIVE_PINGROUP(DAP3, 0x88c),
- DRIVE_PINGROUP(DAP4, 0x890),
- DRIVE_PINGROUP(DBG, 0x894),
- DRIVE_PINGROUP(LCD1, 0x898),
- DRIVE_PINGROUP(LCD2, 0x89c),
- DRIVE_PINGROUP(SDMMC2, 0x8a0),
- DRIVE_PINGROUP(SDMMC3, 0x8a4),
- DRIVE_PINGROUP(SPI, 0x8a8),
- DRIVE_PINGROUP(UAA, 0x8ac),
- DRIVE_PINGROUP(UAB, 0x8b0),
- DRIVE_PINGROUP(UART2, 0x8b4),
- DRIVE_PINGROUP(UART3, 0x8b8),
- DRIVE_PINGROUP(VI1, 0x8bc),
- DRIVE_PINGROUP(VI2, 0x8c0),
- DRIVE_PINGROUP(XM2A, 0x8c4),
- DRIVE_PINGROUP(XM2C, 0x8c8),
- DRIVE_PINGROUP(XM2D, 0x8cc),
- DRIVE_PINGROUP(XM2CLK, 0x8d0),
- DRIVE_PINGROUP(MEMCOMP, 0x8d4),
- DRIVE_PINGROUP(SDIO1, 0x8e0),
- DRIVE_PINGROUP(CRT, 0x8ec),
- DRIVE_PINGROUP(DDC, 0x8f0),
- DRIVE_PINGROUP(GMA, 0x8f4),
- DRIVE_PINGROUP(GMB, 0x8f8),
- DRIVE_PINGROUP(GMC, 0x8fc),
- DRIVE_PINGROUP(GMD, 0x900),
- DRIVE_PINGROUP(GME, 0x904),
- DRIVE_PINGROUP(OWR, 0x908),
- DRIVE_PINGROUP(UAD, 0x90c),
-};
-
-#define PINGROUP(pg_name, vdd, f0, f1, f2, f3, f_safe, \
- tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b) \
- [TEGRA_PINGROUP_ ## pg_name] = { \
- .name = #pg_name, \
- .vddio = TEGRA_VDDIO_ ## vdd, \
- .funcs = { \
- TEGRA_MUX_ ## f0, \
- TEGRA_MUX_ ## f1, \
- TEGRA_MUX_ ## f2, \
- TEGRA_MUX_ ## f3, \
- }, \
- .func_safe = TEGRA_MUX_ ## f_safe, \
- .tri_bank = 0, \
- .tri_reg = ((tri_r) - TRISTATE_REG_A), \
- .tri_bit = tri_b, \
- .mux_bank = 1, \
- .mux_reg = ((mux_r) - PIN_MUX_CTL_REG_A), \
- .mux_bit = mux_b, \
- .pupd_bank = 2, \
- .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A), \
- .pupd_bit = pupd_b, \
- .lock_bit = -1, \
- .od_bit = -1, \
- .ioreset_bit = -1, \
- .io_default = -1, \
- }
-
-static const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = {
- PINGROUP(ATA, NAND, IDE, NAND, GMI, RSVD, IDE, 0x14, 0, 0x80, 24, 0xA0, 0),
- PINGROUP(ATB, NAND, IDE, NAND, GMI, SDIO4, IDE, 0x14, 1, 0x80, 16, 0xA0, 2),
- PINGROUP(ATC, NAND, IDE, NAND, GMI, SDIO4, IDE, 0x14, 2, 0x80, 22, 0xA0, 4),
- PINGROUP(ATD, NAND, IDE, NAND, GMI, SDIO4, IDE, 0x14, 3, 0x80, 20, 0xA0, 6),
- PINGROUP(ATE, NAND, IDE, NAND, GMI, RSVD, IDE, 0x18, 25, 0x80, 12, 0xA0, 8),
- PINGROUP(CDEV1, AUDIO, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, OSC, 0x14, 4, 0x88, 2, 0xA8, 0),
- PINGROUP(CDEV2, AUDIO, OSC, AHB_CLK, APB_CLK, PLLP_OUT4, OSC, 0x14, 5, 0x88, 4, 0xA8, 2),
- PINGROUP(CRTP, LCD, CRT, RSVD, RSVD, RSVD, RSVD, 0x20, 14, 0x98, 20, 0xA4, 24),
- PINGROUP(CSUS, VI, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, PLLC_OUT1, 0x14, 6, 0x88, 6, 0xAC, 24),
- PINGROUP(DAP1, AUDIO, DAP1, RSVD, GMI, SDIO2, DAP1, 0x14, 7, 0x88, 20, 0xA0, 10),
- PINGROUP(DAP2, AUDIO, DAP2, TWC, RSVD, GMI, DAP2, 0x14, 8, 0x88, 22, 0xA0, 12),
- PINGROUP(DAP3, BB, DAP3, RSVD, RSVD, RSVD, DAP3, 0x14, 9, 0x88, 24, 0xA0, 14),
- PINGROUP(DAP4, UART, DAP4, RSVD, GMI, RSVD, DAP4, 0x14, 10, 0x88, 26, 0xA0, 16),
- PINGROUP(DDC, LCD, I2C2, RSVD, RSVD, RSVD, RSVD4, 0x18, 31, 0x88, 0, 0xB0, 28),
- PINGROUP(DTA, VI, RSVD, SDIO2, VI, RSVD, RSVD4, 0x14, 11, 0x84, 20, 0xA0, 18),
- PINGROUP(DTB, VI, RSVD, RSVD, VI, SPI1, RSVD1, 0x14, 12, 0x84, 22, 0xA0, 20),
- PINGROUP(DTC, VI, RSVD, RSVD, VI, RSVD, RSVD1, 0x14, 13, 0x84, 26, 0xA0, 22),
- PINGROUP(DTD, VI, RSVD, SDIO2, VI, RSVD, RSVD1, 0x14, 14, 0x84, 28, 0xA0, 24),
- PINGROUP(DTE, VI, RSVD, RSVD, VI, SPI1, RSVD1, 0x14, 15, 0x84, 30, 0xA0, 26),
- PINGROUP(DTF, VI, I2C3, RSVD, VI, RSVD, RSVD4, 0x20, 12, 0x98, 30, 0xA0, 28),
- PINGROUP(GMA, NAND, UARTE, SPI3, GMI, SDIO4, SPI3, 0x14, 28, 0x84, 0, 0xB0, 20),
- PINGROUP(GMB, NAND, IDE, NAND, GMI, GMI_INT, GMI, 0x18, 29, 0x88, 28, 0xB0, 22),
- PINGROUP(GMC, NAND, UARTD, SPI4, GMI, SFLASH, SPI4, 0x14, 29, 0x84, 2, 0xB0, 24),
- PINGROUP(GMD, NAND, RSVD, NAND, GMI, SFLASH, GMI, 0x18, 30, 0x88, 30, 0xB0, 26),
- PINGROUP(GME, NAND, RSVD, DAP5, GMI, SDIO4, GMI, 0x18, 0, 0x8C, 0, 0xA8, 24),
- PINGROUP(GPU, UART, PWM, UARTA, GMI, RSVD, RSVD4, 0x14, 16, 0x8C, 4, 0xA4, 20),
- PINGROUP(GPU7, SYS, RTCK, RSVD, RSVD, RSVD, RTCK, 0x20, 11, 0x98, 28, 0xA4, 6),
- PINGROUP(GPV, SD, PCIE, RSVD, RSVD, RSVD, PCIE, 0x14, 17, 0x8C, 2, 0xA0, 30),
- PINGROUP(HDINT, LCD, HDMI, RSVD, RSVD, RSVD, HDMI, 0x1C, 23, 0x84, 4, 0xAC, 22),
- PINGROUP(I2CP, SYS, I2C, RSVD, RSVD, RSVD, RSVD4, 0x14, 18, 0x88, 8, 0xA4, 2),
- PINGROUP(IRRX, UART, UARTA, UARTB, GMI, SPI4, UARTB, 0x14, 20, 0x88, 18, 0xA8, 22),
- PINGROUP(IRTX, UART, UARTA, UARTB, GMI, SPI4, UARTB, 0x14, 19, 0x88, 16, 0xA8, 20),
- PINGROUP(KBCA, SYS, KBC, NAND, SDIO2, EMC_TEST0_DLL, KBC, 0x14, 22, 0x88, 10, 0xA4, 8),
- PINGROUP(KBCB, SYS, KBC, NAND, SDIO2, MIO, KBC, 0x14, 21, 0x88, 12, 0xA4, 10),
- PINGROUP(KBCC, SYS, KBC, NAND, TRACE, EMC_TEST1_DLL, KBC, 0x18, 26, 0x88, 14, 0xA4, 12),
- PINGROUP(KBCD, SYS, KBC, NAND, SDIO2, MIO, KBC, 0x20, 10, 0x98, 26, 0xA4, 14),
- PINGROUP(KBCE, SYS, KBC, NAND, OWR, RSVD, KBC, 0x14, 26, 0x80, 28, 0xB0, 2),
- PINGROUP(KBCF, SYS, KBC, NAND, TRACE, MIO, KBC, 0x14, 27, 0x80, 26, 0xB0, 0),
- PINGROUP(LCSN, LCD, DISPLAYA, DISPLAYB, SPI3, RSVD, RSVD4, 0x1C, 31, 0x90, 12, 0xAC, 20),
- PINGROUP(LD0, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 0, 0x94, 0, 0xAC, 12),
- PINGROUP(LD1, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 1, 0x94, 2, 0xAC, 12),
- PINGROUP(LD10, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 10, 0x94, 20, 0xAC, 12),
- PINGROUP(LD11, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 11, 0x94, 22, 0xAC, 12),
- PINGROUP(LD12, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 12, 0x94, 24, 0xAC, 12),
- PINGROUP(LD13, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 13, 0x94, 26, 0xAC, 12),
- PINGROUP(LD14, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 14, 0x94, 28, 0xAC, 12),
- PINGROUP(LD15, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 15, 0x94, 30, 0xAC, 12),
- PINGROUP(LD16, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 16, 0x98, 0, 0xAC, 12),
- PINGROUP(LD17, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 17, 0x98, 2, 0xAC, 12),
- PINGROUP(LD2, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 2, 0x94, 4, 0xAC, 12),
- PINGROUP(LD3, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 3, 0x94, 6, 0xAC, 12),
- PINGROUP(LD4, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 4, 0x94, 8, 0xAC, 12),
- PINGROUP(LD5, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 5, 0x94, 10, 0xAC, 12),
- PINGROUP(LD6, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 6, 0x94, 12, 0xAC, 12),
- PINGROUP(LD7, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 7, 0x94, 14, 0xAC, 12),
- PINGROUP(LD8, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 8, 0x94, 16, 0xAC, 12),
- PINGROUP(LD9, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 9, 0x94, 18, 0xAC, 12),
- PINGROUP(LDC, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 30, 0x90, 14, 0xAC, 20),
- PINGROUP(LDI, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x20, 6, 0x98, 16, 0xAC, 18),
- PINGROUP(LHP0, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 18, 0x98, 10, 0xAC, 16),
- PINGROUP(LHP1, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 19, 0x98, 4, 0xAC, 14),
- PINGROUP(LHP2, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 20, 0x98, 6, 0xAC, 14),
- PINGROUP(LHS, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x20, 7, 0x90, 22, 0xAC, 22),
- PINGROUP(LM0, LCD, DISPLAYA, DISPLAYB, SPI3, RSVD, RSVD4, 0x1C, 24, 0x90, 26, 0xAC, 22),
- PINGROUP(LM1, LCD, DISPLAYA, DISPLAYB, RSVD, CRT, RSVD3, 0x1C, 25, 0x90, 28, 0xAC, 22),
- PINGROUP(LPP, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x20, 8, 0x98, 14, 0xAC, 18),
- PINGROUP(LPW0, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x20, 3, 0x90, 0, 0xAC, 20),
- PINGROUP(LPW1, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x20, 4, 0x90, 2, 0xAC, 20),
- PINGROUP(LPW2, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x20, 5, 0x90, 4, 0xAC, 20),
- PINGROUP(LSC0, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 27, 0x90, 18, 0xAC, 22),
- PINGROUP(LSC1, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x1C, 28, 0x90, 20, 0xAC, 20),
- PINGROUP(LSCK, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x1C, 29, 0x90, 16, 0xAC, 20),
- PINGROUP(LSDA, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x20, 1, 0x90, 8, 0xAC, 20),
- PINGROUP(LSDI, LCD, DISPLAYA, DISPLAYB, SPI3, RSVD, DISPLAYA, 0x20, 2, 0x90, 6, 0xAC, 20),
- PINGROUP(LSPI, LCD, DISPLAYA, DISPLAYB, XIO, HDMI, DISPLAYA, 0x20, 0, 0x90, 10, 0xAC, 22),
- PINGROUP(LVP0, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 21, 0x90, 30, 0xAC, 22),
- PINGROUP(LVP1, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 22, 0x98, 8, 0xAC, 16),
- PINGROUP(LVS, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 26, 0x90, 24, 0xAC, 22),
- PINGROUP(OWC, SYS, OWR, RSVD, RSVD, RSVD, OWR, 0x14, 31, 0x84, 8, 0xB0, 30),
- PINGROUP(PMC, SYS, PWR_ON, PWR_INTR, RSVD, RSVD, PWR_ON, 0x14, 23, 0x98, 18, -1, -1),
- PINGROUP(PTA, NAND, I2C2, HDMI, GMI, RSVD, RSVD4, 0x14, 24, 0x98, 22, 0xA4, 4),
- PINGROUP(RM, UART, I2C, RSVD, RSVD, RSVD, RSVD4, 0x14, 25, 0x80, 14, 0xA4, 0),
- PINGROUP(SDB, SD, UARTA, PWM, SDIO3, SPI2, PWM, 0x20, 15, 0x8C, 10, -1, -1),
- PINGROUP(SDC, SD, PWM, TWC, SDIO3, SPI3, TWC, 0x18, 1, 0x8C, 12, 0xAC, 28),
- PINGROUP(SDD, SD, UARTA, PWM, SDIO3, SPI3, PWM, 0x18, 2, 0x8C, 14, 0xAC, 30),
- PINGROUP(SDIO1, BB, SDIO1, RSVD, UARTE, UARTA, RSVD2, 0x14, 30, 0x80, 30, 0xB0, 18),
- PINGROUP(SLXA, SD, PCIE, SPI4, SDIO3, SPI2, PCIE, 0x18, 3, 0x84, 6, 0xA4, 22),
- PINGROUP(SLXC, SD, SPDIF, SPI4, SDIO3, SPI2, SPI4, 0x18, 5, 0x84, 10, 0xA4, 26),
- PINGROUP(SLXD, SD, SPDIF, SPI4, SDIO3, SPI2, SPI4, 0x18, 6, 0x84, 12, 0xA4, 28),
- PINGROUP(SLXK, SD, PCIE, SPI4, SDIO3, SPI2, PCIE, 0x18, 7, 0x84, 14, 0xA4, 30),
- PINGROUP(SPDI, AUDIO, SPDIF, RSVD, I2C, SDIO2, RSVD2, 0x18, 8, 0x8C, 8, 0xA4, 16),
- PINGROUP(SPDO, AUDIO, SPDIF, RSVD, I2C, SDIO2, RSVD2, 0x18, 9, 0x8C, 6, 0xA4, 18),
- PINGROUP(SPIA, AUDIO, SPI1, SPI2, SPI3, GMI, GMI, 0x18, 10, 0x8C, 30, 0xA8, 4),
- PINGROUP(SPIB, AUDIO, SPI1, SPI2, SPI3, GMI, GMI, 0x18, 11, 0x8C, 28, 0xA8, 6),
- PINGROUP(SPIC, AUDIO, SPI1, SPI2, SPI3, GMI, GMI, 0x18, 12, 0x8C, 26, 0xA8, 8),
- PINGROUP(SPID, AUDIO, SPI2, SPI1, SPI2_ALT, GMI, GMI, 0x18, 13, 0x8C, 24, 0xA8, 10),
- PINGROUP(SPIE, AUDIO, SPI2, SPI1, SPI2_ALT, GMI, GMI, 0x18, 14, 0x8C, 22, 0xA8, 12),
- PINGROUP(SPIF, AUDIO, SPI3, SPI1, SPI2, RSVD, RSVD4, 0x18, 15, 0x8C, 20, 0xA8, 14),
- PINGROUP(SPIG, AUDIO, SPI3, SPI2, SPI2_ALT, I2C, SPI2_ALT, 0x18, 16, 0x8C, 18, 0xA8, 16),
- PINGROUP(SPIH, AUDIO, SPI3, SPI2, SPI2_ALT, I2C, SPI2_ALT, 0x18, 17, 0x8C, 16, 0xA8, 18),
- PINGROUP(UAA, BB, SPI3, MIPI_HS, UARTA, ULPI, MIPI_HS, 0x18, 18, 0x80, 0, 0xAC, 0),
- PINGROUP(UAB, BB, SPI2, MIPI_HS, UARTA, ULPI, MIPI_HS, 0x18, 19, 0x80, 2, 0xAC, 2),
- PINGROUP(UAC, BB, OWR, RSVD, RSVD, RSVD, RSVD4, 0x18, 20, 0x80, 4, 0xAC, 4),
- PINGROUP(UAD, UART, IRDA, SPDIF, UARTA, SPI4, SPDIF, 0x18, 21, 0x80, 6, 0xAC, 6),
- PINGROUP(UCA, UART, UARTC, RSVD, GMI, RSVD, RSVD4, 0x18, 22, 0x84, 16, 0xAC, 8),
- PINGROUP(UCB, UART, UARTC, PWM, GMI, RSVD, RSVD4, 0x18, 23, 0x84, 18, 0xAC, 10),
- PINGROUP(UDA, BB, SPI1, RSVD, UARTD, ULPI, RSVD2, 0x20, 13, 0x80, 8, 0xB0, 16),
- /* these pin groups only have pullup and pull down control */
- PINGROUP(CK32, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xB0, 14),
- PINGROUP(DDRC, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xAC, 26),
- PINGROUP(PMCA, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xB0, 4),
- PINGROUP(PMCB, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xB0, 6),
- PINGROUP(PMCC, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xB0, 8),
- PINGROUP(PMCD, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xB0, 10),
- PINGROUP(PMCE, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xB0, 12),
- PINGROUP(XM2C, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xA8, 30),
- PINGROUP(XM2D, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xA8, 28),
-};
-
-void __devinit tegra20_pinmux_init(const struct tegra_pingroup_desc **pg,
- int *pg_max, const struct tegra_drive_pingroup_desc **pgdrive,
- int *pgdrive_max)
-{
- *pg = tegra_soc_pingroups;
- *pg_max = TEGRA_MAX_PINGROUP;
- *pgdrive = tegra_soc_drive_pingroups;
- *pgdrive_max = TEGRA_MAX_DRIVE_PINGROUP;
-}
-
diff --git a/arch/arm/mach-tegra/pinmux-tegra30-tables.c b/arch/arm/mach-tegra/pinmux-tegra30-tables.c
deleted file mode 100644
index 14fc0e4c1c44..000000000000
--- a/arch/arm/mach-tegra/pinmux-tegra30-tables.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * linux/arch/arm/mach-tegra/pinmux-tegra30-tables.c
- *
- * Common pinmux configurations for Tegra30 SoCs
- *
- * Copyright (C) 2010,2011 NVIDIA Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/init.h>
-#include <linux/string.h>
-
-#include <mach/iomap.h>
-#include <mach/pinmux.h>
-#include <mach/pinmux-tegra30.h>
-#include <mach/suspend.h>
-
-#define PINGROUP_REG_A 0x868
-#define MUXCTL_REG_A 0x3000
-
-#define DRIVE_PINGROUP(pg_name, r) \
- [TEGRA_DRIVE_PINGROUP_ ## pg_name] = { \
- .name = #pg_name, \
- .reg_bank = 0, \
- .reg = ((r) - PINGROUP_REG_A) \
- }
-
-static const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = {
- DRIVE_PINGROUP(AO1, 0x868),
- DRIVE_PINGROUP(AO2, 0x86c),
- DRIVE_PINGROUP(AT1, 0x870),
- DRIVE_PINGROUP(AT2, 0x874),
- DRIVE_PINGROUP(AT3, 0x878),
- DRIVE_PINGROUP(AT4, 0x87c),
- DRIVE_PINGROUP(AT5, 0x880),
- DRIVE_PINGROUP(CDEV1, 0x884),
- DRIVE_PINGROUP(CDEV2, 0x888),
- DRIVE_PINGROUP(CSUS, 0x88c),
- DRIVE_PINGROUP(DAP1, 0x890),
- DRIVE_PINGROUP(DAP2, 0x894),
- DRIVE_PINGROUP(DAP3, 0x898),
- DRIVE_PINGROUP(DAP4, 0x89c),
- DRIVE_PINGROUP(DBG, 0x8a0),
- DRIVE_PINGROUP(LCD1, 0x8a4),
- DRIVE_PINGROUP(LCD2, 0x8a8),
- DRIVE_PINGROUP(SDIO2, 0x8ac),
- DRIVE_PINGROUP(SDIO3, 0x8b0),
- DRIVE_PINGROUP(SPI, 0x8b4),
- DRIVE_PINGROUP(UAA, 0x8b8),
- DRIVE_PINGROUP(UAB, 0x8bc),
- DRIVE_PINGROUP(UART2, 0x8c0),
- DRIVE_PINGROUP(UART3, 0x8c4),
- DRIVE_PINGROUP(VI1, 0x8c8),
- DRIVE_PINGROUP(SDIO1, 0x8ec),
- DRIVE_PINGROUP(CRT, 0x8f8),
- DRIVE_PINGROUP(DDC, 0x8fc),
- DRIVE_PINGROUP(GMA, 0x900),
- DRIVE_PINGROUP(GMB, 0x904),
- DRIVE_PINGROUP(GMC, 0x908),
- DRIVE_PINGROUP(GMD, 0x90c),
- DRIVE_PINGROUP(GME, 0x910),
- DRIVE_PINGROUP(GMF, 0x914),
- DRIVE_PINGROUP(GMG, 0x918),
- DRIVE_PINGROUP(GMH, 0x91c),
- DRIVE_PINGROUP(OWR, 0x920),
- DRIVE_PINGROUP(UAD, 0x924),
- DRIVE_PINGROUP(GPV, 0x928),
- DRIVE_PINGROUP(DEV3, 0x92c),
- DRIVE_PINGROUP(CEC, 0x938),
-};
-
-#define PINGROUP(pg_name, vdd, f0, f1, f2, f3, fs, iod, reg) \
- [TEGRA_PINGROUP_ ## pg_name] = { \
- .name = #pg_name, \
- .vddio = TEGRA_VDDIO_ ## vdd, \
- .funcs = { \
- TEGRA_MUX_ ## f0, \
- TEGRA_MUX_ ## f1, \
- TEGRA_MUX_ ## f2, \
- TEGRA_MUX_ ## f3, \
- }, \
- .func_safe = TEGRA_MUX_ ## fs, \
- .tri_bank = 1, \
- .tri_reg = ((reg) - MUXCTL_REG_A), \
- .tri_bit = 4, \
- .mux_bank = 1, \
- .mux_reg = ((reg) - MUXCTL_REG_A), \
- .mux_bit = 0, \
- .pupd_bank = 1, \
- .pupd_reg = ((reg) - MUXCTL_REG_A), \
- .pupd_bit = 2, \
- .io_default = TEGRA_PIN_ ## iod, \
- .od_bit = 6, \
- .lock_bit = 7, \
- .ioreset_bit = 8, \
- }
-
-static const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = {
- /* NAME VDD f0 f1 f2 f3 fSafe io reg */
- PINGROUP(ULPI_DATA0, BB, SPI3, HSI, UARTA, ULPI, RSVD, INPUT, 0x3000),
- PINGROUP(ULPI_DATA1, BB, SPI3, HSI, UARTA, ULPI, RSVD, INPUT, 0x3004),
- PINGROUP(ULPI_DATA2, BB, SPI3, HSI, UARTA, ULPI, RSVD, INPUT, 0x3008),
- PINGROUP(ULPI_DATA3, BB, SPI3, HSI, UARTA, ULPI, RSVD, INPUT, 0x300c),
- PINGROUP(ULPI_DATA4, BB, SPI2, HSI, UARTA, ULPI, RSVD, INPUT, 0x3010),
- PINGROUP(ULPI_DATA5, BB, SPI2, HSI, UARTA, ULPI, RSVD, INPUT, 0x3014),
- PINGROUP(ULPI_DATA6, BB, SPI2, HSI, UARTA, ULPI, RSVD, INPUT, 0x3018),
- PINGROUP(ULPI_DATA7, BB, SPI2, HSI, UARTA, ULPI, RSVD, INPUT, 0x301c),
- PINGROUP(ULPI_CLK, BB, SPI1, RSVD, UARTD, ULPI, RSVD, INPUT, 0x3020),
- PINGROUP(ULPI_DIR, BB, SPI1, RSVD, UARTD, ULPI, RSVD, INPUT, 0x3024),
- PINGROUP(ULPI_NXT, BB, SPI1, RSVD, UARTD, ULPI, RSVD, INPUT, 0x3028),
- PINGROUP(ULPI_STP, BB, SPI1, RSVD, UARTD, ULPI, RSVD, INPUT, 0x302c),
- PINGROUP(DAP3_FS, BB, I2S2, RSVD1, DISPLAYA, DISPLAYB, RSVD, INPUT, 0x3030),
- PINGROUP(DAP3_DIN, BB, I2S2, RSVD1, DISPLAYA, DISPLAYB, RSVD, INPUT, 0x3034),
- PINGROUP(DAP3_DOUT, BB, I2S2, RSVD1, DISPLAYA, DISPLAYB, RSVD, INPUT, 0x3038),
- PINGROUP(DAP3_SCLK, BB, I2S2, RSVD1, DISPLAYA, DISPLAYB, RSVD, INPUT, 0x303c),
- PINGROUP(GPIO_PV0, BB, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3040),
- PINGROUP(GPIO_PV1, BB, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3044),
- PINGROUP(SDMMC1_CLK, SDMMC1, SDIO1, RSVD1, RSVD2, INVALID, RSVD, INPUT, 0x3048),
- PINGROUP(SDMMC1_CMD, SDMMC1, SDIO1, RSVD1, RSVD2, INVALID, RSVD, INPUT, 0x304c),
- PINGROUP(SDMMC1_DAT3, SDMMC1, SDIO1, RSVD1, UARTE, INVALID, RSVD, INPUT, 0x3050),
- PINGROUP(SDMMC1_DAT2, SDMMC1, SDIO1, RSVD1, UARTE, INVALID, RSVD, INPUT, 0x3054),
- PINGROUP(SDMMC1_DAT1, SDMMC1, SDIO1, RSVD1, UARTE, INVALID, RSVD, INPUT, 0x3058),
- PINGROUP(SDMMC1_DAT0, SDMMC1, SDIO1, RSVD1, UARTE, INVALID, RSVD, INPUT, 0x305c),
- PINGROUP(GPIO_PV2, SDMMC1, OWR, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3060),
- PINGROUP(GPIO_PV3, SDMMC1, INVALID, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3064),
- PINGROUP(CLK2_OUT, SDMMC1, EXTPERIPH2, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3068),
- PINGROUP(CLK2_REQ, SDMMC1, DAP, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x306c),
- PINGROUP(LCD_PWR1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x3070),
- PINGROUP(LCD_PWR2, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, RSVD, OUTPUT, 0x3074),
- PINGROUP(LCD_SDIN, LCD, DISPLAYA, DISPLAYB, SPI5, RSVD, RSVD, OUTPUT, 0x3078),
- PINGROUP(LCD_SDOUT, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, RSVD, OUTPUT, 0x307c),
- PINGROUP(LCD_WR_N, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, RSVD, OUTPUT, 0x3080),
- PINGROUP(LCD_CS0_N, LCD, DISPLAYA, DISPLAYB, SPI5, RSVD, RSVD, OUTPUT, 0x3084),
- PINGROUP(LCD_DC0, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x3088),
- PINGROUP(LCD_SCK, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, RSVD, OUTPUT, 0x308c),
- PINGROUP(LCD_PWR0, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, RSVD, OUTPUT, 0x3090),
- PINGROUP(LCD_PCLK, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x3094),
- PINGROUP(LCD_DE, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x3098),
- PINGROUP(LCD_HSYNC, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x309c),
- PINGROUP(LCD_VSYNC, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30a0),
- PINGROUP(LCD_D0, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30a4),
- PINGROUP(LCD_D1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30a8),
- PINGROUP(LCD_D2, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30ac),
- PINGROUP(LCD_D3, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30b0),
- PINGROUP(LCD_D4, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30b4),
- PINGROUP(LCD_D5, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30b8),
- PINGROUP(LCD_D6, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30bc),
- PINGROUP(LCD_D7, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30c0),
- PINGROUP(LCD_D8, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30c4),
- PINGROUP(LCD_D9, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30c8),
- PINGROUP(LCD_D10, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30cc),
- PINGROUP(LCD_D11, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30d0),
- PINGROUP(LCD_D12, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30d4),
- PINGROUP(LCD_D13, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30d8),
- PINGROUP(LCD_D14, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30dc),
- PINGROUP(LCD_D15, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30e0),
- PINGROUP(LCD_D16, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30e4),
- PINGROUP(LCD_D17, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30e8),
- PINGROUP(LCD_D18, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30ec),
- PINGROUP(LCD_D19, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30f0),
- PINGROUP(LCD_D20, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30f4),
- PINGROUP(LCD_D21, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30f8),
- PINGROUP(LCD_D22, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30fc),
- PINGROUP(LCD_D23, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x3100),
- PINGROUP(LCD_CS1_N, LCD, DISPLAYA, DISPLAYB, SPI5, RSVD2, RSVD, OUTPUT, 0x3104),
- PINGROUP(LCD_M1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x3108),
- PINGROUP(LCD_DC1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x310c),
- PINGROUP(HDMI_INT, LCD, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3110),
- PINGROUP(DDC_SCL, LCD, I2C4, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3114),
- PINGROUP(DDC_SDA, LCD, I2C4, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3118),
- PINGROUP(CRT_HSYNC, LCD, CRT, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x311c),
- PINGROUP(CRT_VSYNC, LCD, CRT, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3120),
- PINGROUP(VI_D0, VI, INVALID, RSVD1, VI, RSVD2, RSVD, INPUT, 0x3124),
- PINGROUP(VI_D1, VI, INVALID, SDIO2, VI, RSVD1, RSVD, INPUT, 0x3128),
- PINGROUP(VI_D2, VI, INVALID, SDIO2, VI, RSVD1, RSVD, INPUT, 0x312c),
- PINGROUP(VI_D3, VI, INVALID, SDIO2, VI, RSVD1, RSVD, INPUT, 0x3130),
- PINGROUP(VI_D4, VI, INVALID, SDIO2, VI, RSVD1, RSVD, INPUT, 0x3134),
- PINGROUP(VI_D5, VI, INVALID, SDIO2, VI, RSVD1, RSVD, INPUT, 0x3138),
- PINGROUP(VI_D6, VI, INVALID, SDIO2, VI, RSVD1, RSVD, INPUT, 0x313c),
- PINGROUP(VI_D7, VI, INVALID, SDIO2, VI, RSVD1, RSVD, INPUT, 0x3140),
- PINGROUP(VI_D8, VI, INVALID, SDIO2, VI, RSVD1, RSVD, INPUT, 0x3144),
- PINGROUP(VI_D9, VI, INVALID, SDIO2, VI, RSVD1, RSVD, INPUT, 0x3148),
- PINGROUP(VI_D10, VI, INVALID, RSVD1, VI, RSVD2, RSVD, INPUT, 0x314c),
- PINGROUP(VI_D11, VI, INVALID, RSVD1, VI, RSVD2, RSVD, INPUT, 0x3150),
- PINGROUP(VI_PCLK, VI, RSVD1, SDIO2, VI, RSVD2, RSVD, INPUT, 0x3154),
- PINGROUP(VI_MCLK, VI, VI, INVALID, INVALID, INVALID, RSVD, INPUT, 0x3158),
- PINGROUP(VI_VSYNC, VI, INVALID, RSVD1, VI, RSVD2, RSVD, INPUT, 0x315c),
- PINGROUP(VI_HSYNC, VI, INVALID, RSVD1, VI, RSVD2, RSVD, INPUT, 0x3160),
- PINGROUP(UART2_RXD, UART, IRDA, SPDIF, UARTA, SPI4, RSVD, INPUT, 0x3164),
- PINGROUP(UART2_TXD, UART, IRDA, SPDIF, UARTA, SPI4, RSVD, INPUT, 0x3168),
- PINGROUP(UART2_RTS_N, UART, UARTA, UARTB, GMI, SPI4, RSVD, INPUT, 0x316c),
- PINGROUP(UART2_CTS_N, UART, UARTA, UARTB, GMI, SPI4, RSVD, INPUT, 0x3170),
- PINGROUP(UART3_TXD, UART, UARTC, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x3174),
- PINGROUP(UART3_RXD, UART, UARTC, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x3178),
- PINGROUP(UART3_CTS_N, UART, UARTC, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x317c),
- PINGROUP(UART3_RTS_N, UART, UARTC, PWM0, GMI, RSVD2, RSVD, INPUT, 0x3180),
- PINGROUP(GPIO_PU0, UART, OWR, UARTA, GMI, RSVD1, RSVD, INPUT, 0x3184),
- PINGROUP(GPIO_PU1, UART, RSVD1, UARTA, GMI, RSVD2, RSVD, INPUT, 0x3188),
- PINGROUP(GPIO_PU2, UART, RSVD1, UARTA, GMI, RSVD2, RSVD, INPUT, 0x318c),
- PINGROUP(GPIO_PU3, UART, PWM0, UARTA, GMI, RSVD1, RSVD, INPUT, 0x3190),
- PINGROUP(GPIO_PU4, UART, PWM1, UARTA, GMI, RSVD1, RSVD, INPUT, 0x3194),
- PINGROUP(GPIO_PU5, UART, PWM2, UARTA, GMI, RSVD1, RSVD, INPUT, 0x3198),
- PINGROUP(GPIO_PU6, UART, PWM3, UARTA, GMI, RSVD1, RSVD, INPUT, 0x319c),
- PINGROUP(GEN1_I2C_SDA, UART, I2C, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x31a0),
- PINGROUP(GEN1_I2C_SCL, UART, I2C, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x31a4),
- PINGROUP(DAP4_FS, UART, I2S3, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x31a8),
- PINGROUP(DAP4_DIN, UART, I2S3, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x31ac),
- PINGROUP(DAP4_DOUT, UART, I2S3, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x31b0),
- PINGROUP(DAP4_SCLK, UART, I2S3, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x31b4),
- PINGROUP(CLK3_OUT, UART, EXTPERIPH3, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x31b8),
- PINGROUP(CLK3_REQ, UART, DEV3, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x31bc),
- PINGROUP(GMI_WP_N, GMI, RSVD1, NAND, GMI, GMI_ALT, RSVD, INPUT, 0x31c0),
- PINGROUP(GMI_IORDY, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31c4),
- PINGROUP(GMI_WAIT, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31c8),
- PINGROUP(GMI_ADV_N, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31cc),
- PINGROUP(GMI_CLK, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31d0),
- PINGROUP(GMI_CS0_N, GMI, RSVD1, NAND, GMI, INVALID, RSVD, INPUT, 0x31d4),
- PINGROUP(GMI_CS1_N, GMI, RSVD1, NAND, GMI, DTV, RSVD, INPUT, 0x31d8),
- PINGROUP(GMI_CS2_N, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31dc),
- PINGROUP(GMI_CS3_N, GMI, RSVD1, NAND, GMI, GMI_ALT, RSVD, INPUT, 0x31e0),
- PINGROUP(GMI_CS4_N, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31e4),
- PINGROUP(GMI_CS6_N, GMI, NAND, NAND_ALT, GMI, SATA, RSVD, INPUT, 0x31e8),
- PINGROUP(GMI_CS7_N, GMI, NAND, NAND_ALT, GMI, GMI_ALT, RSVD, INPUT, 0x31ec),
- PINGROUP(GMI_AD0, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31f0),
- PINGROUP(GMI_AD1, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31f4),
- PINGROUP(GMI_AD2, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31f8),
- PINGROUP(GMI_AD3, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31fc),
- PINGROUP(GMI_AD4, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3200),
- PINGROUP(GMI_AD5, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3204),
- PINGROUP(GMI_AD6, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3208),
- PINGROUP(GMI_AD7, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x320c),
- PINGROUP(GMI_AD8, GMI, PWM0, NAND, GMI, RSVD2, RSVD, INPUT, 0x3210),
- PINGROUP(GMI_AD9, GMI, PWM1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3214),
- PINGROUP(GMI_AD10, GMI, PWM2, NAND, GMI, RSVD2, RSVD, INPUT, 0x3218),
- PINGROUP(GMI_AD11, GMI, PWM3, NAND, GMI, RSVD2, RSVD, INPUT, 0x321c),
- PINGROUP(GMI_AD12, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3220),
- PINGROUP(GMI_AD13, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3224),
- PINGROUP(GMI_AD14, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3228),
- PINGROUP(GMI_AD15, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x322c),
- PINGROUP(GMI_A16, GMI, UARTD, SPI4, GMI, GMI_ALT, RSVD, INPUT, 0x3230),
- PINGROUP(GMI_A17, GMI, UARTD, SPI4, GMI, INVALID, RSVD, INPUT, 0x3234),
- PINGROUP(GMI_A18, GMI, UARTD, SPI4, GMI, INVALID, RSVD, INPUT, 0x3238),
- PINGROUP(GMI_A19, GMI, UARTD, SPI4, GMI, RSVD3, RSVD, INPUT, 0x323c),
- PINGROUP(GMI_WR_N, GMI, RSVD1, NAND, GMI, RSVD3, RSVD, INPUT, 0x3240),
- PINGROUP(GMI_OE_N, GMI, RSVD1, NAND, GMI, RSVD3, RSVD, INPUT, 0x3244),
- PINGROUP(GMI_DQS, GMI, RSVD1, NAND, GMI, RSVD3, RSVD, INPUT, 0x3248),
- PINGROUP(GMI_RST_N, GMI, NAND, NAND_ALT, GMI, RSVD3, RSVD, INPUT, 0x324c),
- PINGROUP(GEN2_I2C_SCL, GMI, I2C2, INVALID, GMI, RSVD3, RSVD, INPUT, 0x3250),
- PINGROUP(GEN2_I2C_SDA, GMI, I2C2, INVALID, GMI, RSVD3, RSVD, INPUT, 0x3254),
- PINGROUP(SDMMC4_CLK, SDMMC4, INVALID, NAND, GMI, SDIO4, RSVD, INPUT, 0x3258),
- PINGROUP(SDMMC4_CMD, SDMMC4, I2C3, NAND, GMI, SDIO4, RSVD, INPUT, 0x325c),
- PINGROUP(SDMMC4_DAT0, SDMMC4, UARTE, SPI3, GMI, SDIO4, RSVD, INPUT, 0x3260),
- PINGROUP(SDMMC4_DAT1, SDMMC4, UARTE, SPI3, GMI, SDIO4, RSVD, INPUT, 0x3264),
- PINGROUP(SDMMC4_DAT2, SDMMC4, UARTE, SPI3, GMI, SDIO4, RSVD, INPUT, 0x3268),
- PINGROUP(SDMMC4_DAT3, SDMMC4, UARTE, SPI3, GMI, SDIO4, RSVD, INPUT, 0x326c),
- PINGROUP(SDMMC4_DAT4, SDMMC4, I2C3, I2S4, GMI, SDIO4, RSVD, INPUT, 0x3270),
- PINGROUP(SDMMC4_DAT5, SDMMC4, VGP3, I2S4, GMI, SDIO4, RSVD, INPUT, 0x3274),
- PINGROUP(SDMMC4_DAT6, SDMMC4, VGP4, I2S4, GMI, SDIO4, RSVD, INPUT, 0x3278),
- PINGROUP(SDMMC4_DAT7, SDMMC4, VGP5, I2S4, GMI, SDIO4, RSVD, INPUT, 0x327c),
- PINGROUP(SDMMC4_RST_N, SDMMC4, VGP6, RSVD1, RSVD2, POPSDMMC4, RSVD, INPUT, 0x3280),
- PINGROUP(CAM_MCLK, CAM, VI, INVALID, VI_ALT2, POPSDMMC4, RSVD, INPUT, 0x3284),
- PINGROUP(GPIO_PCC1, CAM, I2S4, RSVD1, RSVD2, POPSDMMC4, RSVD, INPUT, 0x3288),
- PINGROUP(GPIO_PBB0, CAM, I2S4, RSVD1, RSVD2, POPSDMMC4, RSVD, INPUT, 0x328c),
- PINGROUP(CAM_I2C_SCL, CAM, INVALID, I2C3, RSVD2, POPSDMMC4, RSVD, INPUT, 0x3290),
- PINGROUP(CAM_I2C_SDA, CAM, INVALID, I2C3, RSVD2, POPSDMMC4, RSVD, INPUT, 0x3294),
- PINGROUP(GPIO_PBB3, CAM, VGP3, DISPLAYA, DISPLAYB, POPSDMMC4, RSVD, INPUT, 0x3298),
- PINGROUP(GPIO_PBB4, CAM, VGP4, DISPLAYA, DISPLAYB, POPSDMMC4, RSVD, INPUT, 0x329c),
- PINGROUP(GPIO_PBB5, CAM, VGP5, DISPLAYA, DISPLAYB, POPSDMMC4, RSVD, INPUT, 0x32a0),
- PINGROUP(GPIO_PBB6, CAM, VGP6, DISPLAYA, DISPLAYB, POPSDMMC4, RSVD, INPUT, 0x32a4),
- PINGROUP(GPIO_PBB7, CAM, I2S4, RSVD1, RSVD2, POPSDMMC4, RSVD, INPUT, 0x32a8),
- PINGROUP(GPIO_PCC2, CAM, I2S4, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x32ac),
- PINGROUP(JTAG_RTCK, SYS, RTCK, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x32b0),
- PINGROUP(PWR_I2C_SCL, SYS, I2CPWR, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x32b4),
- PINGROUP(PWR_I2C_SDA, SYS, I2CPWR, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x32b8),
- PINGROUP(KB_ROW0, SYS, KBC, INVALID, RSVD2, RSVD3, RSVD, INPUT, 0x32bc),
- PINGROUP(KB_ROW1, SYS, KBC, INVALID, RSVD2, RSVD3, RSVD, INPUT, 0x32c0),
- PINGROUP(KB_ROW2, SYS, KBC, INVALID, RSVD2, RSVD3, RSVD, INPUT, 0x32c4),
- PINGROUP(KB_ROW3, SYS, KBC, INVALID, RSVD2, INVALID, RSVD, INPUT, 0x32c8),
- PINGROUP(KB_ROW4, SYS, KBC, INVALID, TRACE, RSVD3, RSVD, INPUT, 0x32cc),
- PINGROUP(KB_ROW5, SYS, KBC, INVALID, TRACE, OWR, RSVD, INPUT, 0x32d0),
- PINGROUP(KB_ROW6, SYS, KBC, INVALID, SDIO2, INVALID, RSVD, INPUT, 0x32d4),
- PINGROUP(KB_ROW7, SYS, KBC, INVALID, SDIO2, INVALID, RSVD, INPUT, 0x32d8),
- PINGROUP(KB_ROW8, SYS, KBC, INVALID, SDIO2, INVALID, RSVD, INPUT, 0x32dc),
- PINGROUP(KB_ROW9, SYS, KBC, INVALID, SDIO2, INVALID, RSVD, INPUT, 0x32e0),
- PINGROUP(KB_ROW10, SYS, KBC, INVALID, SDIO2, INVALID, RSVD, INPUT, 0x32e4),
- PINGROUP(KB_ROW11, SYS, KBC, INVALID, SDIO2, INVALID, RSVD, INPUT, 0x32e8),
- PINGROUP(KB_ROW12, SYS, KBC, INVALID, SDIO2, INVALID, RSVD, INPUT, 0x32ec),
- PINGROUP(KB_ROW13, SYS, KBC, INVALID, SDIO2, INVALID, RSVD, INPUT, 0x32f0),
- PINGROUP(KB_ROW14, SYS, KBC, INVALID, SDIO2, INVALID, RSVD, INPUT, 0x32f4),
- PINGROUP(KB_ROW15, SYS, KBC, INVALID, SDIO2, INVALID, RSVD, INPUT, 0x32f8),
- PINGROUP(KB_COL0, SYS, KBC, INVALID, TRACE, INVALID, RSVD, INPUT, 0x32fc),
- PINGROUP(KB_COL1, SYS, KBC, INVALID, TRACE, INVALID, RSVD, INPUT, 0x3300),
- PINGROUP(KB_COL2, SYS, KBC, INVALID, TRACE, RSVD, RSVD, INPUT, 0x3304),
- PINGROUP(KB_COL3, SYS, KBC, INVALID, TRACE, RSVD, RSVD, INPUT, 0x3308),
- PINGROUP(KB_COL4, SYS, KBC, INVALID, TRACE, RSVD, RSVD, INPUT, 0x330c),
- PINGROUP(KB_COL5, SYS, KBC, INVALID, TRACE, RSVD, RSVD, INPUT, 0x3310),
- PINGROUP(KB_COL6, SYS, KBC, INVALID, TRACE, INVALID, RSVD, INPUT, 0x3314),
- PINGROUP(KB_COL7, SYS, KBC, INVALID, TRACE, INVALID, RSVD, INPUT, 0x3318),
- PINGROUP(CLK_32K_OUT, SYS, BLINK, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x331c),
- PINGROUP(SYS_CLK_REQ, SYS, SYSCLK, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3320),
- PINGROUP(CORE_PWR_REQ, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3324),
- PINGROUP(CPU_PWR_REQ, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3328),
- PINGROUP(PWR_INT_N, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x332c),
- PINGROUP(CLK_32K_IN, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3330),
- PINGROUP(OWR, SYS, OWR, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3334),
- PINGROUP(DAP1_FS, AUDIO, I2S0, HDA, GMI, SDIO2, RSVD, INPUT, 0x3338),
- PINGROUP(DAP1_DIN, AUDIO, I2S0, HDA, GMI, SDIO2, RSVD, INPUT, 0x333c),
- PINGROUP(DAP1_DOUT, AUDIO, I2S0, HDA, GMI, SDIO2, RSVD, INPUT, 0x3340),
- PINGROUP(DAP1_SCLK, AUDIO, I2S0, HDA, GMI, SDIO2, RSVD, INPUT, 0x3344),
- PINGROUP(CLK1_REQ, AUDIO, DAP, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x3348),
- PINGROUP(CLK1_OUT, AUDIO, EXTPERIPH1, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x334c),
- PINGROUP(SPDIF_IN, AUDIO, SPDIF, HDA, INVALID, DAPSDMMC2, RSVD, INPUT, 0x3350),
- PINGROUP(SPDIF_OUT, AUDIO, SPDIF, RSVD1, INVALID, DAPSDMMC2, RSVD, INPUT, 0x3354),
- PINGROUP(DAP2_FS, AUDIO, I2S1, HDA, RSVD2, GMI, RSVD, INPUT, 0x3358),
- PINGROUP(DAP2_DIN, AUDIO, I2S1, HDA, RSVD2, GMI, RSVD, INPUT, 0x335c),
- PINGROUP(DAP2_DOUT, AUDIO, I2S1, HDA, RSVD2, GMI, RSVD, INPUT, 0x3360),
- PINGROUP(DAP2_SCLK, AUDIO, I2S1, HDA, RSVD2, GMI, RSVD, INPUT, 0x3364),
- PINGROUP(SPI2_MOSI, AUDIO, SPI6, SPI2, INVALID, GMI, RSVD, INPUT, 0x3368),
- PINGROUP(SPI2_MISO, AUDIO, SPI6, SPI2, INVALID, GMI, RSVD, INPUT, 0x336c),
- PINGROUP(SPI2_CS0_N, AUDIO, SPI6, SPI2, INVALID, GMI, RSVD, INPUT, 0x3370),
- PINGROUP(SPI2_SCK, AUDIO, SPI6, SPI2, INVALID, GMI, RSVD, INPUT, 0x3374),
- PINGROUP(SPI1_MOSI, AUDIO, SPI2, SPI1, INVALID, GMI, RSVD, INPUT, 0x3378),
- PINGROUP(SPI1_SCK, AUDIO, SPI2, SPI1, INVALID, GMI, RSVD, INPUT, 0x337c),
- PINGROUP(SPI1_CS0_N, AUDIO, SPI2, SPI1, INVALID, GMI, RSVD, INPUT, 0x3380),
- PINGROUP(SPI1_MISO, AUDIO, INVALID, SPI1, INVALID, RSVD3, RSVD, INPUT, 0x3384),
- PINGROUP(SPI2_CS1_N, AUDIO, INVALID, SPI2, INVALID, INVALID, RSVD, INPUT, 0x3388),
- PINGROUP(SPI2_CS2_N, AUDIO, INVALID, SPI2, INVALID, INVALID, RSVD, INPUT, 0x338c),
- PINGROUP(SDMMC3_CLK, SDMMC3, UARTA, PWM2, SDIO3, INVALID, RSVD, INPUT, 0x3390),
- PINGROUP(SDMMC3_CMD, SDMMC3, UARTA, PWM3, SDIO3, INVALID, RSVD, INPUT, 0x3394),
- PINGROUP(SDMMC3_DAT0, SDMMC3, RSVD, RSVD1, SDIO3, INVALID, RSVD, INPUT, 0x3398),
- PINGROUP(SDMMC3_DAT1, SDMMC3, RSVD, RSVD1, SDIO3, INVALID, RSVD, INPUT, 0x339c),
- PINGROUP(SDMMC3_DAT2, SDMMC3, RSVD, PWM1, SDIO3, INVALID, RSVD, INPUT, 0x33a0),
- PINGROUP(SDMMC3_DAT3, SDMMC3, RSVD, PWM0, SDIO3, INVALID, RSVD, INPUT, 0x33a4),
- PINGROUP(SDMMC3_DAT4, SDMMC3, PWM1, INVALID, SDIO3, INVALID, RSVD, INPUT, 0x33a8),
- PINGROUP(SDMMC3_DAT5, SDMMC3, PWM0, INVALID, SDIO3, INVALID, RSVD, INPUT, 0x33ac),
- PINGROUP(SDMMC3_DAT6, SDMMC3, SPDIF, INVALID, SDIO3, INVALID, RSVD, INPUT, 0x33b0),
- PINGROUP(SDMMC3_DAT7, SDMMC3, SPDIF, INVALID, SDIO3, INVALID, RSVD, INPUT, 0x33b4),
- PINGROUP(PEX_L0_PRSNT_N, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33b8),
- PINGROUP(PEX_L0_RST_N, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33bc),
- PINGROUP(PEX_L0_CLKREQ_N, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33c0),
- PINGROUP(PEX_WAKE_N, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33c4),
- PINGROUP(PEX_L1_PRSNT_N, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33c8),
- PINGROUP(PEX_L1_RST_N, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33cc),
- PINGROUP(PEX_L1_CLKREQ_N, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33d0),
- PINGROUP(PEX_L2_PRSNT_N, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33d4),
- PINGROUP(PEX_L2_RST_N, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33d8),
- PINGROUP(PEX_L2_CLKREQ_N, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33dc),
- PINGROUP(HDMI_CEC, SYS, CEC, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x33e0),
-};
-
-void __devinit tegra30_pinmux_init(const struct tegra_pingroup_desc **pg,
- int *pg_max, const struct tegra_drive_pingroup_desc **pgdrive,
- int *pgdrive_max)
-{
- *pg = tegra_soc_pingroups;
- *pg_max = TEGRA_MAX_PINGROUP;
- *pgdrive = tegra_soc_drive_pingroups;
- *pgdrive_max = TEGRA_MAX_DRIVE_PINGROUP;
-}
-
diff --git a/arch/arm/mach-tegra/pinmux.c b/arch/arm/mach-tegra/pinmux.c
deleted file mode 100644
index ac35d2b76850..000000000000
--- a/arch/arm/mach-tegra/pinmux.c
+++ /dev/null
@@ -1,987 +0,0 @@
-/*
- * linux/arch/arm/mach-tegra/pinmux.c
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/of_device.h>
-
-#include <mach/iomap.h>
-#include <mach/pinmux.h>
-
-#define HSM_EN(reg) (((reg) >> 2) & 0x1)
-#define SCHMT_EN(reg) (((reg) >> 3) & 0x1)
-#define LPMD(reg) (((reg) >> 4) & 0x3)
-#define DRVDN(reg) (((reg) >> 12) & 0x1f)
-#define DRVUP(reg) (((reg) >> 20) & 0x1f)
-#define SLWR(reg) (((reg) >> 28) & 0x3)
-#define SLWF(reg) (((reg) >> 30) & 0x3)
-
-static const struct tegra_pingroup_desc *pingroups;
-static const struct tegra_drive_pingroup_desc *drive_pingroups;
-static int pingroup_max;
-static int drive_max;
-
-static char *tegra_mux_names[TEGRA_MAX_MUX] = {
- [TEGRA_MUX_AHB_CLK] = "AHB_CLK",
- [TEGRA_MUX_APB_CLK] = "APB_CLK",
- [TEGRA_MUX_AUDIO_SYNC] = "AUDIO_SYNC",
- [TEGRA_MUX_CRT] = "CRT",
- [TEGRA_MUX_DAP1] = "DAP1",
- [TEGRA_MUX_DAP2] = "DAP2",
- [TEGRA_MUX_DAP3] = "DAP3",
- [TEGRA_MUX_DAP4] = "DAP4",
- [TEGRA_MUX_DAP5] = "DAP5",
- [TEGRA_MUX_DISPLAYA] = "DISPLAYA",
- [TEGRA_MUX_DISPLAYB] = "DISPLAYB",
- [TEGRA_MUX_EMC_TEST0_DLL] = "EMC_TEST0_DLL",
- [TEGRA_MUX_EMC_TEST1_DLL] = "EMC_TEST1_DLL",
- [TEGRA_MUX_GMI] = "GMI",
- [TEGRA_MUX_GMI_INT] = "GMI_INT",
- [TEGRA_MUX_HDMI] = "HDMI",
- [TEGRA_MUX_I2C] = "I2C",
- [TEGRA_MUX_I2C2] = "I2C2",
- [TEGRA_MUX_I2C3] = "I2C3",
- [TEGRA_MUX_IDE] = "IDE",
- [TEGRA_MUX_IRDA] = "IRDA",
- [TEGRA_MUX_KBC] = "KBC",
- [TEGRA_MUX_MIO] = "MIO",
- [TEGRA_MUX_MIPI_HS] = "MIPI_HS",
- [TEGRA_MUX_NAND] = "NAND",
- [TEGRA_MUX_OSC] = "OSC",
- [TEGRA_MUX_OWR] = "OWR",
- [TEGRA_MUX_PCIE] = "PCIE",
- [TEGRA_MUX_PLLA_OUT] = "PLLA_OUT",
- [TEGRA_MUX_PLLC_OUT1] = "PLLC_OUT1",
- [TEGRA_MUX_PLLM_OUT1] = "PLLM_OUT1",
- [TEGRA_MUX_PLLP_OUT2] = "PLLP_OUT2",
- [TEGRA_MUX_PLLP_OUT3] = "PLLP_OUT3",
- [TEGRA_MUX_PLLP_OUT4] = "PLLP_OUT4",
- [TEGRA_MUX_PWM] = "PWM",
- [TEGRA_MUX_PWR_INTR] = "PWR_INTR",
- [TEGRA_MUX_PWR_ON] = "PWR_ON",
- [TEGRA_MUX_RTCK] = "RTCK",
- [TEGRA_MUX_SDIO1] = "SDIO1",
- [TEGRA_MUX_SDIO2] = "SDIO2",
- [TEGRA_MUX_SDIO3] = "SDIO3",
- [TEGRA_MUX_SDIO4] = "SDIO4",
- [TEGRA_MUX_SFLASH] = "SFLASH",
- [TEGRA_MUX_SPDIF] = "SPDIF",
- [TEGRA_MUX_SPI1] = "SPI1",
- [TEGRA_MUX_SPI2] = "SPI2",
- [TEGRA_MUX_SPI2_ALT] = "SPI2_ALT",
- [TEGRA_MUX_SPI3] = "SPI3",
- [TEGRA_MUX_SPI4] = "SPI4",
- [TEGRA_MUX_TRACE] = "TRACE",
- [TEGRA_MUX_TWC] = "TWC",
- [TEGRA_MUX_UARTA] = "UARTA",
- [TEGRA_MUX_UARTB] = "UARTB",
- [TEGRA_MUX_UARTC] = "UARTC",
- [TEGRA_MUX_UARTD] = "UARTD",
- [TEGRA_MUX_UARTE] = "UARTE",
- [TEGRA_MUX_ULPI] = "ULPI",
- [TEGRA_MUX_VI] = "VI",
- [TEGRA_MUX_VI_SENSOR_CLK] = "VI_SENSOR_CLK",
- [TEGRA_MUX_XIO] = "XIO",
- [TEGRA_MUX_BLINK] = "BLINK",
- [TEGRA_MUX_CEC] = "CEC",
- [TEGRA_MUX_CLK12] = "CLK12",
- [TEGRA_MUX_DAP] = "DAP",
- [TEGRA_MUX_DAPSDMMC2] = "DAPSDMMC2",
- [TEGRA_MUX_DDR] = "DDR",
- [TEGRA_MUX_DEV3] = "DEV3",
- [TEGRA_MUX_DTV] = "DTV",
- [TEGRA_MUX_VI_ALT1] = "VI_ALT1",
- [TEGRA_MUX_VI_ALT2] = "VI_ALT2",
- [TEGRA_MUX_VI_ALT3] = "VI_ALT3",
- [TEGRA_MUX_EMC_DLL] = "EMC_DLL",
- [TEGRA_MUX_EXTPERIPH1] = "EXTPERIPH1",
- [TEGRA_MUX_EXTPERIPH2] = "EXTPERIPH2",
- [TEGRA_MUX_EXTPERIPH3] = "EXTPERIPH3",
- [TEGRA_MUX_GMI_ALT] = "GMI_ALT",
- [TEGRA_MUX_HDA] = "HDA",
- [TEGRA_MUX_HSI] = "HSI",
- [TEGRA_MUX_I2C4] = "I2C4",
- [TEGRA_MUX_I2C5] = "I2C5",
- [TEGRA_MUX_I2CPWR] = "I2CPWR",
- [TEGRA_MUX_I2S0] = "I2S0",
- [TEGRA_MUX_I2S1] = "I2S1",
- [TEGRA_MUX_I2S2] = "I2S2",
- [TEGRA_MUX_I2S3] = "I2S3",
- [TEGRA_MUX_I2S4] = "I2S4",
- [TEGRA_MUX_NAND_ALT] = "NAND_ALT",
- [TEGRA_MUX_POPSDIO4] = "POPSDIO4",
- [TEGRA_MUX_POPSDMMC4] = "POPSDMMC4",
- [TEGRA_MUX_PWM0] = "PWM0",
- [TEGRA_MUX_PWM1] = "PWM2",
- [TEGRA_MUX_PWM2] = "PWM2",
- [TEGRA_MUX_PWM3] = "PWM3",
- [TEGRA_MUX_SATA] = "SATA",
- [TEGRA_MUX_SPI5] = "SPI5",
- [TEGRA_MUX_SPI6] = "SPI6",
- [TEGRA_MUX_SYSCLK] = "SYSCLK",
- [TEGRA_MUX_VGP1] = "VGP1",
- [TEGRA_MUX_VGP2] = "VGP2",
- [TEGRA_MUX_VGP3] = "VGP3",
- [TEGRA_MUX_VGP4] = "VGP4",
- [TEGRA_MUX_VGP5] = "VGP5",
- [TEGRA_MUX_VGP6] = "VGP6",
- [TEGRA_MUX_SAFE] = "<safe>",
-};
-
-static const char *tegra_drive_names[TEGRA_MAX_DRIVE] = {
- [TEGRA_DRIVE_DIV_8] = "DIV_8",
- [TEGRA_DRIVE_DIV_4] = "DIV_4",
- [TEGRA_DRIVE_DIV_2] = "DIV_2",
- [TEGRA_DRIVE_DIV_1] = "DIV_1",
-};
-
-static const char *tegra_slew_names[TEGRA_MAX_SLEW] = {
- [TEGRA_SLEW_FASTEST] = "FASTEST",
- [TEGRA_SLEW_FAST] = "FAST",
- [TEGRA_SLEW_SLOW] = "SLOW",
- [TEGRA_SLEW_SLOWEST] = "SLOWEST",
-};
-
-static DEFINE_SPINLOCK(mux_lock);
-
-static const char *pingroup_name(int pg)
-{
- if (pg < 0 || pg >= pingroup_max)
- return "<UNKNOWN>";
-
- return pingroups[pg].name;
-}
-
-static const char *func_name(enum tegra_mux_func func)
-{
- if (func == TEGRA_MUX_RSVD1)
- return "RSVD1";
-
- if (func == TEGRA_MUX_RSVD2)
- return "RSVD2";
-
- if (func == TEGRA_MUX_RSVD3)
- return "RSVD3";
-
- if (func == TEGRA_MUX_RSVD4)
- return "RSVD4";
-
- if (func == TEGRA_MUX_NONE)
- return "NONE";
-
- if (func < 0 || func >= TEGRA_MAX_MUX)
- return "<UNKNOWN>";
-
- return tegra_mux_names[func];
-}
-
-
-static const char *tri_name(unsigned long val)
-{
- return val ? "TRISTATE" : "NORMAL";
-}
-
-static const char *pupd_name(unsigned long val)
-{
- switch (val) {
- case 0:
- return "NORMAL";
-
- case 1:
- return "PULL_DOWN";
-
- case 2:
- return "PULL_UP";
-
- default:
- return "RSVD";
- }
-}
-
-static int nbanks;
-static void __iomem **regs;
-
-static inline u32 pg_readl(u32 bank, u32 reg)
-{
- return readl(regs[bank] + reg);
-}
-
-static inline void pg_writel(u32 val, u32 bank, u32 reg)
-{
- writel(val, regs[bank] + reg);
-}
-
-static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
-{
- int mux = -1;
- int i;
- unsigned long reg;
- unsigned long flags;
- int pg = config->pingroup;
- enum tegra_mux_func func = config->func;
-
- if (pg < 0 || pg >= pingroup_max)
- return -ERANGE;
-
- if (pingroups[pg].mux_reg < 0)
- return -EINVAL;
-
- if (func < 0)
- return -ERANGE;
-
- if (func == TEGRA_MUX_SAFE)
- func = pingroups[pg].func_safe;
-
- if (func & TEGRA_MUX_RSVD) {
- mux = func & 0x3;
- } else {
- for (i = 0; i < 4; i++) {
- if (pingroups[pg].funcs[i] == func) {
- mux = i;
- break;
- }
- }
- }
-
- if (mux < 0)
- return -EINVAL;
-
- spin_lock_irqsave(&mux_lock, flags);
-
- reg = pg_readl(pingroups[pg].mux_bank, pingroups[pg].mux_reg);
- reg &= ~(0x3 << pingroups[pg].mux_bit);
- reg |= mux << pingroups[pg].mux_bit;
- pg_writel(reg, pingroups[pg].mux_bank, pingroups[pg].mux_reg);
-
- spin_unlock_irqrestore(&mux_lock, flags);
-
- return 0;
-}
-
-int tegra_pinmux_set_tristate(int pg, enum tegra_tristate tristate)
-{
- unsigned long reg;
- unsigned long flags;
-
- if (pg < 0 || pg >= pingroup_max)
- return -ERANGE;
-
- if (pingroups[pg].tri_reg < 0)
- return -EINVAL;
-
- spin_lock_irqsave(&mux_lock, flags);
-
- reg = pg_readl(pingroups[pg].tri_bank, pingroups[pg].tri_reg);
- reg &= ~(0x1 << pingroups[pg].tri_bit);
- if (tristate)
- reg |= 1 << pingroups[pg].tri_bit;
- pg_writel(reg, pingroups[pg].tri_bank, pingroups[pg].tri_reg);
-
- spin_unlock_irqrestore(&mux_lock, flags);
-
- return 0;
-}
-
-int tegra_pinmux_set_pullupdown(int pg, enum tegra_pullupdown pupd)
-{
- unsigned long reg;
- unsigned long flags;
-
- if (pg < 0 || pg >= pingroup_max)
- return -ERANGE;
-
- if (pingroups[pg].pupd_reg < 0)
- return -EINVAL;
-
- if (pupd != TEGRA_PUPD_NORMAL &&
- pupd != TEGRA_PUPD_PULL_DOWN &&
- pupd != TEGRA_PUPD_PULL_UP)
- return -EINVAL;
-
-
- spin_lock_irqsave(&mux_lock, flags);
-
- reg = pg_readl(pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
- reg &= ~(0x3 << pingroups[pg].pupd_bit);
- reg |= pupd << pingroups[pg].pupd_bit;
- pg_writel(reg, pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
-
- spin_unlock_irqrestore(&mux_lock, flags);
-
- return 0;
-}
-
-static void tegra_pinmux_config_pingroup(const struct tegra_pingroup_config *config)
-{
- int pingroup = config->pingroup;
- enum tegra_mux_func func = config->func;
- enum tegra_pullupdown pupd = config->pupd;
- enum tegra_tristate tristate = config->tristate;
- int err;
-
- if (pingroups[pingroup].mux_reg >= 0) {
- err = tegra_pinmux_set_func(config);
- if (err < 0)
- pr_err("pinmux: can't set pingroup %s func to %s: %d\n",
- pingroup_name(pingroup), func_name(func), err);
- }
-
- if (pingroups[pingroup].pupd_reg >= 0) {
- err = tegra_pinmux_set_pullupdown(pingroup, pupd);
- if (err < 0)
- pr_err("pinmux: can't set pingroup %s pullupdown to %s: %d\n",
- pingroup_name(pingroup), pupd_name(pupd), err);
- }
-
- if (pingroups[pingroup].tri_reg >= 0) {
- err = tegra_pinmux_set_tristate(pingroup, tristate);
- if (err < 0)
- pr_err("pinmux: can't set pingroup %s tristate to %s: %d\n",
- pingroup_name(pingroup), tri_name(func), err);
- }
-}
-
-void tegra_pinmux_config_table(const struct tegra_pingroup_config *config, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- tegra_pinmux_config_pingroup(&config[i]);
-}
-
-static const char *drive_pinmux_name(int pg)
-{
- if (pg < 0 || pg >= drive_max)
- return "<UNKNOWN>";
-
- return drive_pingroups[pg].name;
-}
-
-static const char *enable_name(unsigned long val)
-{
- return val ? "ENABLE" : "DISABLE";
-}
-
-static const char *drive_name(unsigned long val)
-{
- if (val >= TEGRA_MAX_DRIVE)
- return "<UNKNOWN>";
-
- return tegra_drive_names[val];
-}
-
-static const char *slew_name(unsigned long val)
-{
- if (val >= TEGRA_MAX_SLEW)
- return "<UNKNOWN>";
-
- return tegra_slew_names[val];
-}
-
-static int tegra_drive_pinmux_set_hsm(int pg, enum tegra_hsm hsm)
-{
- unsigned long flags;
- u32 reg;
- if (pg < 0 || pg >= drive_max)
- return -ERANGE;
-
- if (hsm != TEGRA_HSM_ENABLE && hsm != TEGRA_HSM_DISABLE)
- return -EINVAL;
-
- spin_lock_irqsave(&mux_lock, flags);
-
- reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
- if (hsm == TEGRA_HSM_ENABLE)
- reg |= (1 << 2);
- else
- reg &= ~(1 << 2);
- pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
-
- spin_unlock_irqrestore(&mux_lock, flags);
-
- return 0;
-}
-
-static int tegra_drive_pinmux_set_schmitt(int pg, enum tegra_schmitt schmitt)
-{
- unsigned long flags;
- u32 reg;
- if (pg < 0 || pg >= drive_max)
- return -ERANGE;
-
- if (schmitt != TEGRA_SCHMITT_ENABLE && schmitt != TEGRA_SCHMITT_DISABLE)
- return -EINVAL;
-
- spin_lock_irqsave(&mux_lock, flags);
-
- reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
- if (schmitt == TEGRA_SCHMITT_ENABLE)
- reg |= (1 << 3);
- else
- reg &= ~(1 << 3);
- pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
-
- spin_unlock_irqrestore(&mux_lock, flags);
-
- return 0;
-}
-
-static int tegra_drive_pinmux_set_drive(int pg, enum tegra_drive drive)
-{
- unsigned long flags;
- u32 reg;
- if (pg < 0 || pg >= drive_max)
- return -ERANGE;
-
- if (drive < 0 || drive >= TEGRA_MAX_DRIVE)
- return -EINVAL;
-
- spin_lock_irqsave(&mux_lock, flags);
-
- reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
- reg &= ~(0x3 << 4);
- reg |= drive << 4;
- pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
-
- spin_unlock_irqrestore(&mux_lock, flags);
-
- return 0;
-}
-
-static int tegra_drive_pinmux_set_pull_down(int pg,
- enum tegra_pull_strength pull_down)
-{
- unsigned long flags;
- u32 reg;
- if (pg < 0 || pg >= drive_max)
- return -ERANGE;
-
- if (pull_down < 0 || pull_down >= TEGRA_MAX_PULL)
- return -EINVAL;
-
- spin_lock_irqsave(&mux_lock, flags);
-
- reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
- reg &= ~(0x1f << 12);
- reg |= pull_down << 12;
- pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
-
- spin_unlock_irqrestore(&mux_lock, flags);
-
- return 0;
-}
-
-static int tegra_drive_pinmux_set_pull_up(int pg,
- enum tegra_pull_strength pull_up)
-{
- unsigned long flags;
- u32 reg;
- if (pg < 0 || pg >= drive_max)
- return -ERANGE;
-
- if (pull_up < 0 || pull_up >= TEGRA_MAX_PULL)
- return -EINVAL;
-
- spin_lock_irqsave(&mux_lock, flags);
-
- reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
- reg &= ~(0x1f << 12);
- reg |= pull_up << 12;
- pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
-
- spin_unlock_irqrestore(&mux_lock, flags);
-
- return 0;
-}
-
-static int tegra_drive_pinmux_set_slew_rising(int pg,
- enum tegra_slew slew_rising)
-{
- unsigned long flags;
- u32 reg;
- if (pg < 0 || pg >= drive_max)
- return -ERANGE;
-
- if (slew_rising < 0 || slew_rising >= TEGRA_MAX_SLEW)
- return -EINVAL;
-
- spin_lock_irqsave(&mux_lock, flags);
-
- reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
- reg &= ~(0x3 << 28);
- reg |= slew_rising << 28;
- pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
-
- spin_unlock_irqrestore(&mux_lock, flags);
-
- return 0;
-}
-
-static int tegra_drive_pinmux_set_slew_falling(int pg,
- enum tegra_slew slew_falling)
-{
- unsigned long flags;
- u32 reg;
- if (pg < 0 || pg >= drive_max)
- return -ERANGE;
-
- if (slew_falling < 0 || slew_falling >= TEGRA_MAX_SLEW)
- return -EINVAL;
-
- spin_lock_irqsave(&mux_lock, flags);
-
- reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
- reg &= ~(0x3 << 30);
- reg |= slew_falling << 30;
- pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
-
- spin_unlock_irqrestore(&mux_lock, flags);
-
- return 0;
-}
-
-static void tegra_drive_pinmux_config_pingroup(int pingroup,
- enum tegra_hsm hsm,
- enum tegra_schmitt schmitt,
- enum tegra_drive drive,
- enum tegra_pull_strength pull_down,
- enum tegra_pull_strength pull_up,
- enum tegra_slew slew_rising,
- enum tegra_slew slew_falling)
-{
- int err;
-
- err = tegra_drive_pinmux_set_hsm(pingroup, hsm);
- if (err < 0)
- pr_err("pinmux: can't set pingroup %s hsm to %s: %d\n",
- drive_pinmux_name(pingroup),
- enable_name(hsm), err);
-
- err = tegra_drive_pinmux_set_schmitt(pingroup, schmitt);
- if (err < 0)
- pr_err("pinmux: can't set pingroup %s schmitt to %s: %d\n",
- drive_pinmux_name(pingroup),
- enable_name(schmitt), err);
-
- err = tegra_drive_pinmux_set_drive(pingroup, drive);
- if (err < 0)
- pr_err("pinmux: can't set pingroup %s drive to %s: %d\n",
- drive_pinmux_name(pingroup),
- drive_name(drive), err);
-
- err = tegra_drive_pinmux_set_pull_down(pingroup, pull_down);
- if (err < 0)
- pr_err("pinmux: can't set pingroup %s pull down to %d: %d\n",
- drive_pinmux_name(pingroup),
- pull_down, err);
-
- err = tegra_drive_pinmux_set_pull_up(pingroup, pull_up);
- if (err < 0)
- pr_err("pinmux: can't set pingroup %s pull up to %d: %d\n",
- drive_pinmux_name(pingroup),
- pull_up, err);
-
- err = tegra_drive_pinmux_set_slew_rising(pingroup, slew_rising);
- if (err < 0)
- pr_err("pinmux: can't set pingroup %s rising slew to %s: %d\n",
- drive_pinmux_name(pingroup),
- slew_name(slew_rising), err);
-
- err = tegra_drive_pinmux_set_slew_falling(pingroup, slew_falling);
- if (err < 0)
- pr_err("pinmux: can't set pingroup %s falling slew to %s: %d\n",
- drive_pinmux_name(pingroup),
- slew_name(slew_falling), err);
-}
-
-void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config,
- int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- tegra_drive_pinmux_config_pingroup(config[i].pingroup,
- config[i].hsm,
- config[i].schmitt,
- config[i].drive,
- config[i].pull_down,
- config[i].pull_up,
- config[i].slew_rising,
- config[i].slew_falling);
-}
-
-void tegra_pinmux_set_safe_pinmux_table(const struct tegra_pingroup_config *config,
- int len)
-{
- int i;
- struct tegra_pingroup_config c;
-
- for (i = 0; i < len; i++) {
- int err;
- c = config[i];
- if (c.pingroup < 0 || c.pingroup >= pingroup_max) {
- WARN_ON(1);
- continue;
- }
- c.func = pingroups[c.pingroup].func_safe;
- err = tegra_pinmux_set_func(&c);
- if (err < 0)
- pr_err("%s: tegra_pinmux_set_func returned %d setting "
- "%s to %s\n", __func__, err,
- pingroup_name(c.pingroup), func_name(c.func));
- }
-}
-
-void tegra_pinmux_config_pinmux_table(const struct tegra_pingroup_config *config,
- int len)
-{
- int i;
-
- for (i = 0; i < len; i++) {
- int err;
- if (config[i].pingroup < 0 ||
- config[i].pingroup >= pingroup_max) {
- WARN_ON(1);
- continue;
- }
- err = tegra_pinmux_set_func(&config[i]);
- if (err < 0)
- pr_err("%s: tegra_pinmux_set_func returned %d setting "
- "%s to %s\n", __func__, err,
- pingroup_name(config[i].pingroup),
- func_name(config[i].func));
- }
-}
-
-void tegra_pinmux_config_tristate_table(const struct tegra_pingroup_config *config,
- int len, enum tegra_tristate tristate)
-{
- int i;
- int err;
- int pingroup;
-
- for (i = 0; i < len; i++) {
- pingroup = config[i].pingroup;
- if (pingroups[pingroup].tri_reg >= 0) {
- err = tegra_pinmux_set_tristate(pingroup, tristate);
- if (err < 0)
- pr_err("pinmux: can't set pingroup %s tristate"
- " to %s: %d\n", pingroup_name(pingroup),
- tri_name(tristate), err);
- }
- }
-}
-
-void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *config,
- int len, enum tegra_pullupdown pupd)
-{
- int i;
- int err;
- int pingroup;
-
- for (i = 0; i < len; i++) {
- pingroup = config[i].pingroup;
- if (pingroups[pingroup].pupd_reg >= 0) {
- err = tegra_pinmux_set_pullupdown(pingroup, pupd);
- if (err < 0)
- pr_err("pinmux: can't set pingroup %s pullupdown"
- " to %s: %d\n", pingroup_name(pingroup),
- pupd_name(pupd), err);
- }
- }
-}
-
-static struct of_device_id tegra_pinmux_of_match[] __devinitdata = {
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- { .compatible = "nvidia,tegra20-pinmux", tegra20_pinmux_init },
-#endif
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
- { .compatible = "nvidia,tegra30-pinmux", tegra30_pinmux_init },
-#endif
- { },
-};
-
-static int __devinit tegra_pinmux_probe(struct platform_device *pdev)
-{
- struct resource *res;
- int i;
- int config_bad = 0;
- const struct of_device_id *match;
-
- match = of_match_device(tegra_pinmux_of_match, &pdev->dev);
-
- if (match)
- ((pinmux_init)(match->data))(&pingroups, &pingroup_max,
- &drive_pingroups, &drive_max);
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- else
- /* no device tree available, so we must be on tegra20 */
- tegra20_pinmux_init(&pingroups, &pingroup_max,
- &drive_pingroups, &drive_max);
-#else
- pr_warn("non Tegra20 platform requires pinmux devicetree node\n");
-#endif
-
- for (i = 0; ; i++) {
- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
- if (!res)
- break;
- }
- nbanks = i;
-
- for (i = 0; i < pingroup_max; i++) {
- if (pingroups[i].tri_bank >= nbanks) {
- dev_err(&pdev->dev, "pingroup %d: bad tri_bank\n", i);
- config_bad = 1;
- }
-
- if (pingroups[i].mux_bank >= nbanks) {
- dev_err(&pdev->dev, "pingroup %d: bad mux_bank\n", i);
- config_bad = 1;
- }
-
- if (pingroups[i].pupd_bank >= nbanks) {
- dev_err(&pdev->dev, "pingroup %d: bad pupd_bank\n", i);
- config_bad = 1;
- }
- }
-
- for (i = 0; i < drive_max; i++) {
- if (drive_pingroups[i].reg_bank >= nbanks) {
- dev_err(&pdev->dev,
- "drive pingroup %d: bad reg_bank\n", i);
- config_bad = 1;
- }
- }
-
- if (config_bad)
- return -ENODEV;
-
- regs = devm_kzalloc(&pdev->dev, nbanks * sizeof(*regs), GFP_KERNEL);
- if (!regs) {
- dev_err(&pdev->dev, "Can't alloc regs pointer\n");
- return -ENODEV;
- }
-
- for (i = 0; i < nbanks; i++) {
- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
- if (!res) {
- dev_err(&pdev->dev, "Missing MEM resource\n");
- return -ENODEV;
- }
-
- if (!devm_request_mem_region(&pdev->dev, res->start,
- resource_size(res),
- dev_name(&pdev->dev))) {
- dev_err(&pdev->dev,
- "Couldn't request MEM resource %d\n", i);
- return -ENODEV;
- }
-
- regs[i] = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
- if (!regs) {
- dev_err(&pdev->dev, "Couldn't ioremap regs %d\n", i);
- return -ENODEV;
- }
- }
-
- return 0;
-}
-
-static struct platform_driver tegra_pinmux_driver = {
- .driver = {
- .name = "tegra-pinmux",
- .owner = THIS_MODULE,
- .of_match_table = tegra_pinmux_of_match,
- },
- .probe = tegra_pinmux_probe,
-};
-
-static int __init tegra_pinmux_init(void)
-{
- return platform_driver_register(&tegra_pinmux_driver);
-}
-postcore_initcall(tegra_pinmux_init);
-
-#ifdef CONFIG_DEBUG_FS
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-static void dbg_pad_field(struct seq_file *s, int len)
-{
- seq_putc(s, ',');
-
- while (len-- > -1)
- seq_putc(s, ' ');
-}
-
-static int dbg_pinmux_show(struct seq_file *s, void *unused)
-{
- int i;
- int len;
-
- for (i = 0; i < pingroup_max; i++) {
- unsigned long reg;
- unsigned long tri;
- unsigned long mux;
- unsigned long pupd;
-
- seq_printf(s, "\t{TEGRA_PINGROUP_%s", pingroups[i].name);
- len = strlen(pingroups[i].name);
- dbg_pad_field(s, 5 - len);
-
- if (pingroups[i].mux_reg < 0) {
- seq_printf(s, "TEGRA_MUX_NONE");
- len = strlen("NONE");
- } else {
- reg = pg_readl(pingroups[i].mux_bank,
- pingroups[i].mux_reg);
- mux = (reg >> pingroups[i].mux_bit) & 0x3;
- if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) {
- seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1);
- len = 5;
- } else {
- seq_printf(s, "TEGRA_MUX_%s",
- tegra_mux_names[pingroups[i].funcs[mux]]);
- len = strlen(tegra_mux_names[pingroups[i].funcs[mux]]);
- }
- }
- dbg_pad_field(s, 13-len);
-
- if (pingroups[i].pupd_reg < 0) {
- seq_printf(s, "TEGRA_PUPD_NORMAL");
- len = strlen("NORMAL");
- } else {
- reg = pg_readl(pingroups[i].pupd_bank,
- pingroups[i].pupd_reg);
- pupd = (reg >> pingroups[i].pupd_bit) & 0x3;
- seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd));
- len = strlen(pupd_name(pupd));
- }
- dbg_pad_field(s, 9 - len);
-
- if (pingroups[i].tri_reg < 0) {
- seq_printf(s, "TEGRA_TRI_NORMAL");
- } else {
- reg = pg_readl(pingroups[i].tri_bank,
- pingroups[i].tri_reg);
- tri = (reg >> pingroups[i].tri_bit) & 0x1;
-
- seq_printf(s, "TEGRA_TRI_%s", tri_name(tri));
- }
- seq_printf(s, "},\n");
- }
- return 0;
-}
-
-static int dbg_pinmux_open(struct inode *inode, struct file *file)
-{
- return single_open(file, dbg_pinmux_show, &inode->i_private);
-}
-
-static const struct file_operations debug_fops = {
- .open = dbg_pinmux_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int dbg_drive_pinmux_show(struct seq_file *s, void *unused)
-{
- int i;
- int len;
-
- for (i = 0; i < drive_max; i++) {
- u32 reg;
-
- seq_printf(s, "\t{TEGRA_DRIVE_PINGROUP_%s",
- drive_pingroups[i].name);
- len = strlen(drive_pingroups[i].name);
- dbg_pad_field(s, 7 - len);
-
-
- reg = pg_readl(drive_pingroups[i].reg_bank,
- drive_pingroups[i].reg);
- if (HSM_EN(reg)) {
- seq_printf(s, "TEGRA_HSM_ENABLE");
- len = 16;
- } else {
- seq_printf(s, "TEGRA_HSM_DISABLE");
- len = 17;
- }
- dbg_pad_field(s, 17 - len);
-
- if (SCHMT_EN(reg)) {
- seq_printf(s, "TEGRA_SCHMITT_ENABLE");
- len = 21;
- } else {
- seq_printf(s, "TEGRA_SCHMITT_DISABLE");
- len = 22;
- }
- dbg_pad_field(s, 22 - len);
-
- seq_printf(s, "TEGRA_DRIVE_%s", drive_name(LPMD(reg)));
- len = strlen(drive_name(LPMD(reg)));
- dbg_pad_field(s, 5 - len);
-
- seq_printf(s, "TEGRA_PULL_%d", DRVDN(reg));
- len = DRVDN(reg) < 10 ? 1 : 2;
- dbg_pad_field(s, 2 - len);
-
- seq_printf(s, "TEGRA_PULL_%d", DRVUP(reg));
- len = DRVUP(reg) < 10 ? 1 : 2;
- dbg_pad_field(s, 2 - len);
-
- seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWR(reg)));
- len = strlen(slew_name(SLWR(reg)));
- dbg_pad_field(s, 7 - len);
-
- seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWF(reg)));
-
- seq_printf(s, "},\n");
- }
- return 0;
-}
-
-static int dbg_drive_pinmux_open(struct inode *inode, struct file *file)
-{
- return single_open(file, dbg_drive_pinmux_show, &inode->i_private);
-}
-
-static const struct file_operations debug_drive_fops = {
- .open = dbg_drive_pinmux_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int __init tegra_pinmux_debuginit(void)
-{
- (void) debugfs_create_file("tegra_pinmux", S_IRUGO,
- NULL, NULL, &debug_fops);
- (void) debugfs_create_file("tegra_pinmux_drive", S_IRUGO,
- NULL, NULL, &debug_drive_fops);
- return 0;
-}
-late_initcall(tegra_pinmux_debuginit);
-#endif
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 592a4eeb5328..bae09b859891 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -1764,6 +1764,12 @@ static struct clk_pll_freq_table tegra_pll_x_freq_table[] = {
{ 19200000, 760000000, 950, 24, 1, 8},
{ 26000000, 760000000, 760, 26, 1, 12},
+ /* 750 MHz */
+ { 12000000, 750000000, 750, 12, 1, 12},
+ { 13000000, 750000000, 750, 13, 1, 12},
+ { 19200000, 750000000, 625, 16, 1, 8},
+ { 26000000, 750000000, 750, 26, 1, 12},
+
/* 608 MHz */
{ 12000000, 608000000, 608, 12, 1, 12},
{ 13000000, 608000000, 608, 13, 1, 12},
@@ -2142,8 +2148,8 @@ static struct clk tegra_list_clks[] = {
PERIPH_CLK("apbdma", "tegra-dma", NULL, 34, 0, 108000000, mux_pclk, 0),
PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 32768, mux_clk_32k, PERIPH_NO_RESET),
PERIPH_CLK("timer", "timer", NULL, 5, 0, 26000000, mux_clk_m, 0),
- PERIPH_CLK("i2s1", "tegra-i2s.0", NULL, 11, 0x100, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
- PERIPH_CLK("i2s2", "tegra-i2s.1", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
+ PERIPH_CLK("i2s1", "tegra20-i2s.0", NULL, 11, 0x100, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
+ PERIPH_CLK("i2s2", "tegra20-i2s.1", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, 100000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71),
PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71),
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
index 1eed8d4a80ef..315672c7bd48 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/arch/arm/mach-tegra/timer.c
@@ -124,7 +124,7 @@ static u64 tegra_rtc_read_ms(void)
}
/*
- * read_persistent_clock - Return time from a persistent clock.
+ * tegra_read_persistent_clock - Return time from a persistent clock.
*
* Reads the time from a source which isn't disabled during PM, the
* 32k sync timer. Convert the cycles elapsed since last read into
@@ -133,7 +133,7 @@ static u64 tegra_rtc_read_ms(void)
* tegra_rtc driver could be executing to avoid race conditions
* on the RTC shadow register
*/
-void read_persistent_clock(struct timespec *ts)
+static void tegra_read_persistent_clock(struct timespec *ts)
{
u64 delta;
struct timespec *tsp = &persistent_ts;
@@ -243,6 +243,7 @@ static void __init tegra_init_timer(void)
tegra_clockevent.irq = tegra_timer_irq.irq;
clockevents_register_device(&tegra_clockevent);
tegra_twd_init();
+ register_persistent_clock(NULL, tegra_read_persistent_clock);
}
struct sys_timer tegra_timer = {
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index c5b2ac04e2a0..d71d2fed6721 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -711,7 +711,6 @@ struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
err = -ENXIO;
goto err1;
}
- tegra_gpio_enable(ulpi_config->reset_gpio);
gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b");
gpio_direction_output(ulpi_config->reset_gpio, 0);
phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index ef7099eea0f2..53d3d46dec12 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -9,10 +9,8 @@ config UX500_SOC_COMMON
select ARM_ERRATA_754322
select ARM_ERRATA_764369
select CACHE_L2X0
-
-config UX500_SOC_DB5500
- bool
- select MFD_DB5500_PRCMU
+ select PINCTRL
+ select PINCTRL_NOMADIK
config UX500_SOC_DB8500
bool
@@ -20,6 +18,7 @@ config UX500_SOC_DB8500
select REGULATOR
select REGULATOR_DB8500_PRCMU
select CPU_FREQ_TABLE if CPU_FREQ
+ select PINCTRL_DB8500
menu "Ux500 target platform (boards)"
@@ -45,15 +44,8 @@ config MACH_SNOWBALL
help
Include support for the snowball development platform.
-config MACH_U5500
- bool "U5500 Development platform"
- select UX500_SOC_DB5500
- help
- Include support for the U5500 development platform.
-
config UX500_AUTO_PLATFORM
def_bool y
- depends on !MACH_U5500
select MACH_MOP500
help
At least one platform needs to be selected in order to build
@@ -74,18 +66,4 @@ config UX500_DEBUG_UART
Choose the UART on which kernel low-level debug messages should be
output.
-config U5500_MODEM_IRQ
- bool "Modem IRQ support"
- depends on UX500_SOC_DB5500
- default y
- help
- Add support for handling IRQ:s from modem side
-
-config U5500_MBOX
- bool "Mailbox support"
- depends on U5500_MODEM_IRQ
- default y
- help
- Add support for U5500 mailbox communication with modem side
-
endif
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index 465b9ec9510a..026086ff9e6c 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -4,17 +4,14 @@
obj-y := clock.o cpu.o devices.o devices-common.o \
id.o usb.o timer.o
+obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
-obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o
obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o
obj-$(CONFIG_MACH_MOP500) += board-mop500.o board-mop500-sdi.o \
board-mop500-regulators.o \
board-mop500-uib.o board-mop500-stuib.o \
board-mop500-u8500uib.o \
- board-mop500-pins.o
-obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o
+ board-mop500-pins.o \
+ board-mop500-msp.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
-obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o
-obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o
-
diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c
new file mode 100644
index 000000000000..996048038743
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-msp.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/consumer.h>
+
+#include <plat/gpio-nomadik.h>
+#include <plat/pincfg.h>
+#include <plat/ste_dma40.h>
+
+#include <mach/devices.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/msp.h>
+
+#include "ste-dma40-db8500.h"
+#include "board-mop500.h"
+#include "devices-db8500.h"
+#include "pins-db8500.h"
+
+/* MSP1/3 Tx/Rx usage protection */
+static DEFINE_SPINLOCK(msp_rxtx_lock);
+
+/* Reference Count */
+static int msp_rxtx_ref;
+
+/* Pin modes */
+struct pinctrl *msp1_p;
+struct pinctrl_state *msp1_def;
+struct pinctrl_state *msp1_sleep;
+
+int msp13_i2s_init(void)
+{
+ int retval = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&msp_rxtx_lock, flags);
+ if (msp_rxtx_ref == 0 && !(IS_ERR(msp1_p) || IS_ERR(msp1_def))) {
+ retval = pinctrl_select_state(msp1_p, msp1_def);
+ if (retval)
+ pr_err("could not set MSP1 defstate\n");
+ }
+ if (!retval)
+ msp_rxtx_ref++;
+ spin_unlock_irqrestore(&msp_rxtx_lock, flags);
+
+ return retval;
+}
+
+int msp13_i2s_exit(void)
+{
+ int retval = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&msp_rxtx_lock, flags);
+ WARN_ON(!msp_rxtx_ref);
+ msp_rxtx_ref--;
+ if (msp_rxtx_ref == 0 && !(IS_ERR(msp1_p) || IS_ERR(msp1_sleep))) {
+ retval = pinctrl_select_state(msp1_p, msp1_sleep);
+ if (retval)
+ pr_err("could not set MSP1 sleepstate\n");
+ }
+ spin_unlock_irqrestore(&msp_rxtx_lock, flags);
+
+ return retval;
+}
+
+static struct stedma40_chan_cfg msp0_dma_rx = {
+ .high_priority = true,
+ .dir = STEDMA40_PERIPH_TO_MEM,
+
+ .src_dev_type = DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+ /* data_width is set during configuration */
+};
+
+static struct stedma40_chan_cfg msp0_dma_tx = {
+ .high_priority = true,
+ .dir = STEDMA40_MEM_TO_PERIPH,
+
+ .src_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX,
+
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+ /* data_width is set during configuration */
+};
+
+static struct msp_i2s_platform_data msp0_platform_data = {
+ .id = MSP_I2S_0,
+ .msp_i2s_dma_rx = &msp0_dma_rx,
+ .msp_i2s_dma_tx = &msp0_dma_tx,
+};
+
+static struct stedma40_chan_cfg msp1_dma_rx = {
+ .high_priority = true,
+ .dir = STEDMA40_PERIPH_TO_MEM,
+
+ .src_dev_type = DB8500_DMA_DEV30_MSP3_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+ /* data_width is set during configuration */
+};
+
+static struct stedma40_chan_cfg msp1_dma_tx = {
+ .high_priority = true,
+ .dir = STEDMA40_MEM_TO_PERIPH,
+
+ .src_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV30_MSP1_TX,
+
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+ /* data_width is set during configuration */
+};
+
+static struct msp_i2s_platform_data msp1_platform_data = {
+ .id = MSP_I2S_1,
+ .msp_i2s_dma_rx = NULL,
+ .msp_i2s_dma_tx = &msp1_dma_tx,
+ .msp_i2s_init = msp13_i2s_init,
+ .msp_i2s_exit = msp13_i2s_exit,
+};
+
+static struct stedma40_chan_cfg msp2_dma_rx = {
+ .high_priority = true,
+ .dir = STEDMA40_PERIPH_TO_MEM,
+
+ .src_dev_type = DB8500_DMA_DEV14_MSP2_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+
+ /* MSP2 DMA doesn't work with PSIZE == 4 on DB8500v2 */
+ .src_info.psize = STEDMA40_PSIZE_LOG_1,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_1,
+
+ /* data_width is set during configuration */
+};
+
+static struct stedma40_chan_cfg msp2_dma_tx = {
+ .high_priority = true,
+ .dir = STEDMA40_MEM_TO_PERIPH,
+
+ .src_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV14_MSP2_TX,
+
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+ .use_fixed_channel = true,
+ .phy_channel = 1,
+
+ /* data_width is set during configuration */
+};
+
+static struct platform_device *db8500_add_msp_i2s(struct device *parent,
+ int id,
+ resource_size_t base, int irq,
+ struct msp_i2s_platform_data *pdata)
+{
+ struct platform_device *pdev;
+ struct resource res[] = {
+ DEFINE_RES_MEM(base, SZ_4K),
+ DEFINE_RES_IRQ(irq),
+ };
+
+ pr_info("Register platform-device 'ux500-msp-i2s', id %d, irq %d\n",
+ id, irq);
+ pdev = platform_device_register_resndata(parent, "ux500-msp-i2s", id,
+ res, ARRAY_SIZE(res),
+ pdata, sizeof(*pdata));
+ if (!pdev) {
+ pr_err("Failed to register platform-device 'ux500-msp-i2s.%d'!\n",
+ id);
+ return NULL;
+ }
+
+ return pdev;
+}
+
+/* Platform device for ASoC U8500 machine */
+static struct platform_device snd_soc_u8500 = {
+ .name = "snd-soc-u8500",
+ .id = 0,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+
+/* Platform device for Ux500-PCM */
+static struct platform_device ux500_pcm = {
+ .name = "ux500-pcm",
+ .id = 0,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+
+static struct msp_i2s_platform_data msp2_platform_data = {
+ .id = MSP_I2S_2,
+ .msp_i2s_dma_rx = &msp2_dma_rx,
+ .msp_i2s_dma_tx = &msp2_dma_tx,
+};
+
+static struct msp_i2s_platform_data msp3_platform_data = {
+ .id = MSP_I2S_3,
+ .msp_i2s_dma_rx = &msp1_dma_rx,
+ .msp_i2s_dma_tx = NULL,
+ .msp_i2s_init = msp13_i2s_init,
+ .msp_i2s_exit = msp13_i2s_exit,
+};
+
+int mop500_msp_init(struct device *parent)
+{
+ struct platform_device *msp1;
+
+ pr_info("%s: Register platform-device 'snd-soc-u8500'.\n", __func__);
+ platform_device_register(&snd_soc_u8500);
+
+ pr_info("Initialize MSP I2S-devices.\n");
+ db8500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0,
+ &msp0_platform_data);
+ msp1 = db8500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1,
+ &msp1_platform_data);
+ db8500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2,
+ &msp2_platform_data);
+ db8500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1,
+ &msp3_platform_data);
+
+ /* Get the pinctrl handle for MSP1 */
+ if (msp1) {
+ msp1_p = pinctrl_get(&msp1->dev);
+ if (IS_ERR(msp1_p))
+ dev_err(&msp1->dev, "could not get MSP1 pinctrl\n");
+ else {
+ msp1_def = pinctrl_lookup_state(msp1_p,
+ PINCTRL_STATE_DEFAULT);
+ if (IS_ERR(msp1_def)) {
+ dev_err(&msp1->dev,
+ "could not get MSP1 defstate\n");
+ }
+ msp1_sleep = pinctrl_lookup_state(msp1_p,
+ PINCTRL_STATE_SLEEP);
+ if (IS_ERR(msp1_sleep))
+ dev_err(&msp1->dev,
+ "could not get MSP1 idlestate\n");
+ }
+ }
+
+ pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__);
+ platform_device_register(&ux500_pcm);
+
+ return 0;
+}
diff --git a/arch/arm/mach-ux500/board-mop500-msp.h b/arch/arm/mach-ux500/board-mop500-msp.h
new file mode 100644
index 000000000000..6fcfb5e2cc94
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-msp.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
+ * for ST-Ericsson.
+ *
+ * License terms:
+ *
+ * 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.
+ */
+
+void mop500_msp_init(struct device *parent);
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
index f5413dca532c..32fd99204464 100644
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -7,299 +7,508 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/bug.h>
+#include <linux/string.h>
+#include <linux/pinctrl/machine.h>
#include <asm/mach-types.h>
#include <plat/pincfg.h>
#include <plat/gpio-nomadik.h>
+
#include <mach/hardware.h>
#include "pins-db8500.h"
+#include "board-mop500.h"
-static pin_cfg_t mop500_pins_common[] = {
- /* I2C */
- GPIO147_I2C0_SCL,
- GPIO148_I2C0_SDA,
- GPIO16_I2C1_SCL,
- GPIO17_I2C1_SDA,
- GPIO10_I2C2_SDA,
- GPIO11_I2C2_SCL,
- GPIO229_I2C3_SDA,
- GPIO230_I2C3_SCL,
-
- /* MSP0 */
- GPIO12_MSP0_TXD,
- GPIO13_MSP0_TFS,
- GPIO14_MSP0_TCK,
- GPIO15_MSP0_RXD,
-
- /* MSP2: HDMI */
- GPIO193_MSP2_TXD,
- GPIO194_MSP2_TCK,
- GPIO195_MSP2_TFS,
- GPIO196_MSP2_RXD | PIN_OUTPUT_LOW,
-
- /* Touch screen INTERFACE */
- GPIO84_GPIO | PIN_INPUT_PULLUP, /* TOUCH_INT1 */
-
- /* STMPE1601/tc35893 keypad IRQ */
- GPIO218_GPIO | PIN_INPUT_PULLUP,
-
- /* MMC0 (MicroSD card) */
- GPIO18_MC0_CMDDIR | PIN_OUTPUT_HIGH,
- GPIO19_MC0_DAT0DIR | PIN_OUTPUT_HIGH,
- GPIO20_MC0_DAT2DIR | PIN_OUTPUT_HIGH,
-
- GPIO22_MC0_FBCLK | PIN_INPUT_NOPULL,
- GPIO23_MC0_CLK | PIN_OUTPUT_LOW,
- GPIO24_MC0_CMD | PIN_INPUT_PULLUP,
- GPIO25_MC0_DAT0 | PIN_INPUT_PULLUP,
- GPIO26_MC0_DAT1 | PIN_INPUT_PULLUP,
- GPIO27_MC0_DAT2 | PIN_INPUT_PULLUP,
- GPIO28_MC0_DAT3 | PIN_INPUT_PULLUP,
-
- /* SDI1 (SDIO) */
- GPIO208_MC1_CLK | PIN_OUTPUT_LOW,
- GPIO209_MC1_FBCLK | PIN_INPUT_NOPULL,
- GPIO210_MC1_CMD | PIN_INPUT_PULLUP,
- GPIO211_MC1_DAT0 | PIN_INPUT_PULLUP,
- GPIO212_MC1_DAT1 | PIN_INPUT_PULLUP,
- GPIO213_MC1_DAT2 | PIN_INPUT_PULLUP,
- GPIO214_MC1_DAT3 | PIN_INPUT_PULLUP,
-
- /* MMC2 (On-board DATA INTERFACE eMMC) */
- GPIO128_MC2_CLK | PIN_OUTPUT_LOW,
- GPIO129_MC2_CMD | PIN_INPUT_PULLUP,
- GPIO130_MC2_FBCLK | PIN_INPUT_NOPULL,
- GPIO131_MC2_DAT0 | PIN_INPUT_PULLUP,
- GPIO132_MC2_DAT1 | PIN_INPUT_PULLUP,
- GPIO133_MC2_DAT2 | PIN_INPUT_PULLUP,
- GPIO134_MC2_DAT3 | PIN_INPUT_PULLUP,
- GPIO135_MC2_DAT4 | PIN_INPUT_PULLUP,
- GPIO136_MC2_DAT5 | PIN_INPUT_PULLUP,
- GPIO137_MC2_DAT6 | PIN_INPUT_PULLUP,
- GPIO138_MC2_DAT7 | PIN_INPUT_PULLUP,
-
- /* MMC4 (On-board STORAGE INTERFACE eMMC) */
- GPIO197_MC4_DAT3 | PIN_INPUT_PULLUP,
- GPIO198_MC4_DAT2 | PIN_INPUT_PULLUP,
- GPIO199_MC4_DAT1 | PIN_INPUT_PULLUP,
- GPIO200_MC4_DAT0 | PIN_INPUT_PULLUP,
- GPIO201_MC4_CMD | PIN_INPUT_PULLUP,
- GPIO202_MC4_FBCLK | PIN_INPUT_NOPULL,
- GPIO203_MC4_CLK | PIN_OUTPUT_LOW,
- GPIO204_MC4_DAT7 | PIN_INPUT_PULLUP,
- GPIO205_MC4_DAT6 | PIN_INPUT_PULLUP,
- GPIO206_MC4_DAT5 | PIN_INPUT_PULLUP,
- GPIO207_MC4_DAT4 | PIN_INPUT_PULLUP,
-
- /* SKE keypad */
- GPIO153_KP_I7,
- GPIO154_KP_I6,
- GPIO155_KP_I5,
- GPIO156_KP_I4,
- GPIO157_KP_O7,
- GPIO158_KP_O6,
- GPIO159_KP_O5,
- GPIO160_KP_O4,
- GPIO161_KP_I3,
- GPIO162_KP_I2,
- GPIO163_KP_I1,
- GPIO164_KP_I0,
- GPIO165_KP_O3,
- GPIO166_KP_O2,
- GPIO167_KP_O1,
- GPIO168_KP_O0,
+enum custom_pin_cfg_t {
+ PINS_FOR_DEFAULT,
+ PINS_FOR_U9500,
+};
- /* UART */
- /* uart-0 pins gpio configuration should be
- * kept intact to prevent glitch in tx line
- * when tty dev is opened. Later these pins
+static enum custom_pin_cfg_t pinsfor;
+
+/* These simply sets bias for pins */
+#define BIAS(a,b) static unsigned long a[] = { b }
+
+BIAS(pd, PIN_PULL_DOWN);
+BIAS(slpm_gpio_nopull, PIN_SLPM_GPIO|PIN_SLPM_INPUT_NOPULL);
+BIAS(in_nopull, PIN_INPUT_NOPULL);
+BIAS(in_nopull_sleep_nowkup, PIN_INPUT_NOPULL|PIN_SLPM_WAKEUP_DISABLE);
+BIAS(in_pu, PIN_INPUT_PULLUP);
+BIAS(in_pd, PIN_INPUT_PULLDOWN);
+BIAS(in_pd_slpm_in_pu, PIN_INPUT_PULLDOWN|PIN_SLPM_INPUT_PULLUP);
+BIAS(in_pu_slpm_out_lo, PIN_INPUT_PULLUP|PIN_SLPM_OUTPUT_LOW);
+BIAS(out_hi, PIN_OUTPUT_HIGH);
+BIAS(out_lo, PIN_OUTPUT_LOW);
+BIAS(out_lo_sleep_nowkup, PIN_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE);
+/* These also force them into GPIO mode */
+BIAS(gpio_in_pu, PIN_INPUT_PULLUP|PIN_GPIOMODE_ENABLED);
+BIAS(gpio_in_pd, PIN_INPUT_PULLDOWN|PIN_GPIOMODE_ENABLED);
+BIAS(gpio_in_pu_slpm_gpio_nopull, PIN_INPUT_PULLUP|PIN_GPIOMODE_ENABLED|PIN_SLPM_GPIO|PIN_SLPM_INPUT_NOPULL);
+BIAS(gpio_in_pd_slpm_gpio_nopull, PIN_INPUT_PULLDOWN|PIN_GPIOMODE_ENABLED|PIN_SLPM_GPIO|PIN_SLPM_INPUT_NOPULL);
+BIAS(gpio_out_hi, PIN_OUTPUT_HIGH|PIN_GPIOMODE_ENABLED);
+BIAS(gpio_out_lo, PIN_OUTPUT_LOW|PIN_GPIOMODE_ENABLED);
+/* Sleep modes */
+BIAS(sleep_in_wkup_pdis, PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(sleep_in_nopull_wkup, PIN_INPUT_NOPULL|PIN_SLPM_WAKEUP_ENABLE);
+BIAS(sleep_out_hi_wkup_pdis, PIN_SLPM_OUTPUT_HIGH|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(sleep_out_lo_wkup, PIN_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE);
+BIAS(sleep_out_wkup_pdis, PIN_SLPM_DIR_OUTPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+
+/* We use these to define hog settings that are always done on boot */
+#define DB8500_MUX_HOG(group,func) \
+ PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-db8500", group, func)
+#define DB8500_PIN_HOG(pin,conf) \
+ PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-db8500", pin, conf)
+
+/* These are default states associated with device and changed runtime */
+#define DB8500_MUX(group,func,dev) \
+ PIN_MAP_MUX_GROUP_DEFAULT(dev, "pinctrl-db8500", group, func)
+#define DB8500_PIN(pin,conf,dev) \
+ PIN_MAP_CONFIGS_PIN_DEFAULT(dev, "pinctrl-db8500", pin, conf)
+
+#define DB8500_PIN_SLEEP(pin,conf,dev) \
+ PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500", \
+ pin, conf)
+
+/* Pin control settings */
+static struct pinctrl_map __initdata mop500_family_pinmap[] = {
+ /*
+ * uMSP0, mux in 4 pins, regular placement of RX/TX
+ * explicitly set the pins to no pull
+ */
+ DB8500_MUX_HOG("msp0txrx_a_1", "msp0"),
+ DB8500_MUX_HOG("msp0tfstck_a_1", "msp0"),
+ DB8500_PIN_HOG("GPIO12_AC4", in_nopull), /* TXD */
+ DB8500_PIN_HOG("GPIO15_AC3", in_nopull), /* RXD */
+ DB8500_PIN_HOG("GPIO13_AF3", in_nopull), /* TFS */
+ DB8500_PIN_HOG("GPIO14_AE3", in_nopull), /* TCK */
+ /* MSP2 for HDMI, pull down TXD, TCK, TFS */
+ DB8500_MUX_HOG("msp2_a_1", "msp2"),
+ DB8500_PIN_HOG("GPIO193_AH27", in_pd), /* TXD */
+ DB8500_PIN_HOG("GPIO194_AF27", in_pd), /* TCK */
+ DB8500_PIN_HOG("GPIO195_AG28", in_pd), /* TFS */
+ DB8500_PIN_HOG("GPIO196_AG26", out_lo), /* RXD */
+ /*
+ * LCD, set TE0 (using LCD VSI0) and D14 (touch screen interrupt) to
+ * pull-up
+ * TODO: is this really correct? Snowball doesn't have a LCD.
+ */
+ DB8500_MUX_HOG("lcdvsi0_a_1", "lcd"),
+ DB8500_PIN_HOG("GPIO68_E1", in_pu),
+ DB8500_PIN_HOG("GPIO84_C2", gpio_in_pu),
+ /*
+ * STMPE1601/tc35893 keypad IRQ GPIO 218
+ * TODO: set for snowball and HREF really??
+ */
+ DB8500_PIN_HOG("GPIO218_AH11", gpio_in_pu),
+ /*
+ * UART0, we do not mux in u0 here.
+ * uart-0 pins gpio configuration should be kept intact to prevent
+ * a glitch in tx line when the tty dev is opened. Later these pins
* are configured to uart mop500_pins_uart0
- *
- * It will be replaced with uart configuration
- * once the issue is solved.
*/
- GPIO0_GPIO | PIN_INPUT_PULLUP,
- GPIO1_GPIO | PIN_OUTPUT_HIGH,
- GPIO2_GPIO | PIN_INPUT_PULLUP,
- GPIO3_GPIO | PIN_OUTPUT_HIGH,
-
- GPIO29_U2_RXD | PIN_INPUT_PULLUP,
- GPIO30_U2_TXD | PIN_OUTPUT_HIGH,
- GPIO31_U2_CTSn | PIN_INPUT_PULLUP,
- GPIO32_U2_RTSn | PIN_OUTPUT_HIGH,
-
- /* Display & HDMI HW sync */
- GPIO68_LCD_VSI0 | PIN_INPUT_PULLUP,
- GPIO69_LCD_VSI1 | PIN_INPUT_PULLUP,
+ DB8500_PIN_HOG("GPIO0_AJ5", in_pu), /* CTS */
+ DB8500_PIN_HOG("GPIO1_AJ3", out_hi), /* RTS */
+ DB8500_PIN_HOG("GPIO2_AH4", in_pu), /* RXD */
+ DB8500_PIN_HOG("GPIO3_AH3", out_hi), /* TXD */
+ /*
+ * Mux in UART2 on altfunction C and set pull-ups.
+ * TODO: is this used on U8500 variants and Snowball really?
+ * The setting on GPIO31 conflicts with magnetometer use on hrefv60
+ */
+ DB8500_MUX_HOG("u2rxtx_c_1", "u2"),
+ DB8500_MUX_HOG("u2ctsrts_c_1", "u2"),
+ DB8500_PIN_HOG("GPIO29_W2", in_pu), /* RXD */
+ DB8500_PIN_HOG("GPIO30_W3", out_hi), /* TXD */
+ DB8500_PIN_HOG("GPIO31_V3", in_pu), /* CTS */
+ DB8500_PIN_HOG("GPIO32_V2", out_hi), /* RTS */
+ /*
+ * The following pin sets were known as "runtime pins" before being
+ * converted to the pinctrl model. Here we model them as "default"
+ * states.
+ */
+ /* Mux in UART0 after initialization */
+ DB8500_MUX("u0_a_1", "u0", "uart0"),
+ DB8500_PIN("GPIO0_AJ5", in_pu, "uart0"), /* CTS */
+ DB8500_PIN("GPIO1_AJ3", out_hi, "uart0"), /* RTS */
+ DB8500_PIN("GPIO2_AH4", in_pu, "uart0"), /* RXD */
+ DB8500_PIN("GPIO3_AH3", out_hi, "uart0"), /* TXD */
+ /* UART0 sleep state */
+ DB8500_PIN_SLEEP("GPIO0_AJ5", sleep_in_wkup_pdis, "uart0"),
+ DB8500_PIN_SLEEP("GPIO1_AJ3", sleep_out_hi_wkup_pdis, "uart0"),
+ DB8500_PIN_SLEEP("GPIO2_AH4", sleep_in_wkup_pdis, "uart0"),
+ DB8500_PIN_SLEEP("GPIO3_AH3", sleep_out_wkup_pdis, "uart0"),
+ /* MSP1 for ALSA codec */
+ DB8500_MUX("msp1txrx_a_1", "msp1", "ux500-msp-i2s.1"),
+ DB8500_MUX("msp1_a_1", "msp1", "ux500-msp-i2s.1"),
+ DB8500_PIN("GPIO33_AF2", out_lo_sleep_nowkup, "ux500-msp-i2s.1"),
+ DB8500_PIN("GPIO34_AE1", in_nopull_sleep_nowkup, "ux500-msp-i2s.1"),
+ DB8500_PIN("GPIO35_AE2", in_nopull_sleep_nowkup, "ux500-msp-i2s.1"),
+ DB8500_PIN("GPIO36_AG2", in_nopull_sleep_nowkup, "ux500-msp-i2s.1"),
+ /* MSP1 sleep state */
+ DB8500_PIN_SLEEP("GPIO33_AF2", sleep_out_lo_wkup, "ux500-msp-i2s.1"),
+ DB8500_PIN_SLEEP("GPIO34_AE1", sleep_in_nopull_wkup, "ux500-msp-i2s.1"),
+ DB8500_PIN_SLEEP("GPIO35_AE2", sleep_in_nopull_wkup, "ux500-msp-i2s.1"),
+ DB8500_PIN_SLEEP("GPIO36_AG2", sleep_in_nopull_wkup, "ux500-msp-i2s.1"),
+ /* Mux in LCD data lines 8 thru 11 and LCDA CLK for MCDE TVOUT */
+ DB8500_MUX("lcd_d8_d11_a_1", "lcd", "mcde-tvout"),
+ DB8500_MUX("lcdaclk_b_1", "lcda", "mcde-tvout"),
+ /* Mux in LCD VSI1 and pull it up for MCDE HDMI output */
+ DB8500_MUX("lcdvsi1_a_1", "lcd", "av8100-hdmi"),
+ /* Mux in I2C blocks, put pins into GPIO in sleepmode no pull-up */
+ DB8500_MUX("i2c0_a_1", "i2c0", "nmk-i2c.0"),
+ DB8500_PIN("GPIO147_C15", slpm_gpio_nopull, "nmk-i2c.0"),
+ DB8500_PIN("GPIO148_B16", slpm_gpio_nopull, "nmk-i2c.0"),
+ DB8500_MUX("i2c1_b_2", "i2c1", "nmk-i2c.1"),
+ DB8500_PIN("GPIO16_AD3", slpm_gpio_nopull, "nmk-i2c.1"),
+ DB8500_PIN("GPIO17_AD4", slpm_gpio_nopull, "nmk-i2c.1"),
+ DB8500_MUX("i2c2_b_2", "i2c2", "nmk-i2c.2"),
+ DB8500_PIN("GPIO10_AF5", slpm_gpio_nopull, "nmk-i2c.2"),
+ DB8500_PIN("GPIO11_AG4", slpm_gpio_nopull, "nmk-i2c.2"),
+ DB8500_MUX("i2c3_c_2", "i2c3", "nmk-i2c.3"),
+ DB8500_PIN("GPIO229_AG7", slpm_gpio_nopull, "nmk-i2c.3"),
+ DB8500_PIN("GPIO230_AF7", slpm_gpio_nopull, "nmk-i2c.3"),
+ /* Mux in SDI0 (here called MC0) used for removable MMC/SD/SDIO cards */
+ DB8500_MUX("mc0_a_1", "mc0", "sdi0"),
+ DB8500_PIN("GPIO18_AC2", out_hi, "sdi0"), /* CMDDIR */
+ DB8500_PIN("GPIO19_AC1", out_hi, "sdi0"), /* DAT0DIR */
+ DB8500_PIN("GPIO20_AB4", out_hi, "sdi0"), /* DAT2DIR */
+ DB8500_PIN("GPIO22_AA3", in_nopull, "sdi0"), /* FBCLK */
+ DB8500_PIN("GPIO23_AA4", out_lo, "sdi0"), /* CLK */
+ DB8500_PIN("GPIO24_AB2", in_pu, "sdi0"), /* CMD */
+ DB8500_PIN("GPIO25_Y4", in_pu, "sdi0"), /* DAT0 */
+ DB8500_PIN("GPIO26_Y2", in_pu, "sdi0"), /* DAT1 */
+ DB8500_PIN("GPIO27_AA2", in_pu, "sdi0"), /* DAT2 */
+ DB8500_PIN("GPIO28_AA1", in_pu, "sdi0"), /* DAT3 */
+ /* Mux in SDI1 (here called MC1) used for SDIO for CW1200 WLAN */
+ DB8500_MUX("mc1_a_1", "mc1", "sdi1"),
+ DB8500_PIN("GPIO208_AH16", out_lo, "sdi1"), /* CLK */
+ DB8500_PIN("GPIO209_AG15", in_nopull, "sdi1"), /* FBCLK */
+ DB8500_PIN("GPIO210_AJ15", in_pu, "sdi1"), /* CMD */
+ DB8500_PIN("GPIO211_AG14", in_pu, "sdi1"), /* DAT0 */
+ DB8500_PIN("GPIO212_AF13", in_pu, "sdi1"), /* DAT1 */
+ DB8500_PIN("GPIO213_AG13", in_pu, "sdi1"), /* DAT2 */
+ DB8500_PIN("GPIO214_AH15", in_pu, "sdi1"), /* DAT3 */
+ /* Mux in SDI2 (here called MC2) used for for PoP eMMC */
+ DB8500_MUX("mc2_a_1", "mc2", "sdi2"),
+ DB8500_PIN("GPIO128_A5", out_lo, "sdi2"), /* CLK */
+ DB8500_PIN("GPIO129_B4", in_pu, "sdi2"), /* CMD */
+ DB8500_PIN("GPIO130_C8", in_nopull, "sdi2"), /* FBCLK */
+ DB8500_PIN("GPIO131_A12", in_pu, "sdi2"), /* DAT0 */
+ DB8500_PIN("GPIO132_C10", in_pu, "sdi2"), /* DAT1 */
+ DB8500_PIN("GPIO133_B10", in_pu, "sdi2"), /* DAT2 */
+ DB8500_PIN("GPIO134_B9", in_pu, "sdi2"), /* DAT3 */
+ DB8500_PIN("GPIO135_A9", in_pu, "sdi2"), /* DAT4 */
+ DB8500_PIN("GPIO136_C7", in_pu, "sdi2"), /* DAT5 */
+ DB8500_PIN("GPIO137_A7", in_pu, "sdi2"), /* DAT6 */
+ DB8500_PIN("GPIO138_C5", in_pu, "sdi2"), /* DAT7 */
+ /* Mux in SDI4 (here called MC4) used for for PCB-mounted eMMC */
+ DB8500_MUX("mc4_a_1", "mc4", "sdi4"),
+ DB8500_PIN("GPIO197_AH24", in_pu, "sdi4"), /* DAT3 */
+ DB8500_PIN("GPIO198_AG25", in_pu, "sdi4"), /* DAT2 */
+ DB8500_PIN("GPIO199_AH23", in_pu, "sdi4"), /* DAT1 */
+ DB8500_PIN("GPIO200_AH26", in_pu, "sdi4"), /* DAT0 */
+ DB8500_PIN("GPIO201_AF24", in_pu, "sdi4"), /* CMD */
+ DB8500_PIN("GPIO202_AF25", in_nopull, "sdi4"), /* FBCLK */
+ DB8500_PIN("GPIO203_AE23", out_lo, "sdi4"), /* CLK */
+ DB8500_PIN("GPIO204_AF23", in_pu, "sdi4"), /* DAT7 */
+ DB8500_PIN("GPIO205_AG23", in_pu, "sdi4"), /* DAT6 */
+ DB8500_PIN("GPIO206_AG24", in_pu, "sdi4"), /* DAT5 */
+ DB8500_PIN("GPIO207_AJ23", in_pu, "sdi4"), /* DAT4 */
+ /* Mux in USB pins, drive STP high */
+ DB8500_MUX("usb_a_1", "usb", "musb-ux500.0"),
+ DB8500_PIN("GPIO257_AE29", out_hi, "musb-ux500.0"), /* STP */
+ /* Mux in SPI2 pins on the "other C1" altfunction */
+ DB8500_MUX("spi2_oc1_1", "spi2", "spi2"),
+ DB8500_PIN("GPIO216_AG12", gpio_out_hi, "spi2"), /* FRM */
+ DB8500_PIN("GPIO218_AH11", in_pd, "spi2"), /* RXD */
+ DB8500_PIN("GPIO215_AH13", out_lo, "spi2"), /* TXD */
+ DB8500_PIN("GPIO217_AH12", out_lo, "spi2"), /* CLK */
};
-static pin_cfg_t mop500_pins_default[] = {
- /* SSP0 */
- GPIO143_SSP0_CLK,
- GPIO144_SSP0_FRM,
- GPIO145_SSP0_RXD | PIN_PULL_DOWN,
- GPIO146_SSP0_TXD,
-
-
- GPIO217_GPIO | PIN_INPUT_PULLUP, /* TC35892 IRQ */
-
- /* SDI0 (MicroSD card) */
- GPIO21_MC0_DAT31DIR | PIN_OUTPUT_HIGH,
-
- /* UART */
- GPIO4_U1_RXD | PIN_INPUT_PULLUP,
- GPIO5_U1_TXD | PIN_OUTPUT_HIGH,
- GPIO6_U1_CTSn | PIN_INPUT_PULLUP,
- GPIO7_U1_RTSn | PIN_OUTPUT_HIGH,
+/*
+ * These are specifically for the MOP500 and HREFP (pre-v60) version of the
+ * board, which utilized a TC35892 GPIO expander instead of using a lot of
+ * on-chip pins as the HREFv60 and later does.
+ */
+static struct pinctrl_map __initdata mop500_pinmap[] = {
+ /* Mux in SSP0, pull down RXD pin */
+ DB8500_MUX_HOG("ssp0_a_1", "ssp0"),
+ DB8500_PIN_HOG("GPIO145_C13", pd),
+ /*
+ * XENON Flashgun on image processor GPIO (controlled from image
+ * processor firmware), mux in these image processor GPIO lines 0
+ * (XENON_FLASH_ID) and 1 (XENON_READY) on altfunction C and pull up
+ * the pins.
+ */
+ DB8500_MUX_HOG("ipgpio0_c_1", "ipgpio"),
+ DB8500_MUX_HOG("ipgpio1_c_1", "ipgpio"),
+ DB8500_PIN_HOG("GPIO6_AF6", in_pu),
+ DB8500_PIN_HOG("GPIO7_AG5", in_pu),
+ /* TC35892 IRQ, pull up the line, let the driver mux in the pin */
+ DB8500_PIN_HOG("GPIO217_AH12", gpio_in_pu),
+ /* Mux in UART1 and set the pull-ups */
+ DB8500_MUX_HOG("u1rxtx_a_1", "u1"),
+ DB8500_MUX_HOG("u1ctsrts_a_1", "u1"),
+ DB8500_PIN_HOG("GPIO4_AH6", in_pu), /* RXD */
+ DB8500_PIN_HOG("GPIO5_AG6", out_hi), /* TXD */
+ DB8500_PIN_HOG("GPIO6_AF6", in_pu), /* CTS */
+ DB8500_PIN_HOG("GPIO7_AG5", out_hi), /* RTS */
+ /*
+ * Runtime stuff: make it possible to mux in the SKE keypad
+ * and bias the pins
+ */
+ DB8500_MUX("kp_a_2", "kp", "ske"),
+ DB8500_PIN("GPIO153_B17", in_pd_slpm_in_pu, "ske"), /* I7 */
+ DB8500_PIN("GPIO154_C16", in_pd_slpm_in_pu, "ske"), /* I6 */
+ DB8500_PIN("GPIO155_C19", in_pd_slpm_in_pu, "ske"), /* I5 */
+ DB8500_PIN("GPIO156_C17", in_pd_slpm_in_pu, "ske"), /* I4 */
+ DB8500_PIN("GPIO161_D21", in_pd_slpm_in_pu, "ske"), /* I3 */
+ DB8500_PIN("GPIO162_D20", in_pd_slpm_in_pu, "ske"), /* I2 */
+ DB8500_PIN("GPIO163_C20", in_pd_slpm_in_pu, "ske"), /* I1 */
+ DB8500_PIN("GPIO164_B21", in_pd_slpm_in_pu, "ske"), /* I0 */
+ DB8500_PIN("GPIO157_A18", in_pu_slpm_out_lo, "ske"), /* O7 */
+ DB8500_PIN("GPIO158_C18", in_pu_slpm_out_lo, "ske"), /* O6 */
+ DB8500_PIN("GPIO159_B19", in_pu_slpm_out_lo, "ske"), /* O5 */
+ DB8500_PIN("GPIO160_B20", in_pu_slpm_out_lo, "ske"), /* O4 */
+ DB8500_PIN("GPIO165_C21", in_pu_slpm_out_lo, "ske"), /* O3 */
+ DB8500_PIN("GPIO166_A22", in_pu_slpm_out_lo, "ske"), /* O2 */
+ DB8500_PIN("GPIO167_B24", in_pu_slpm_out_lo, "ske"), /* O1 */
+ DB8500_PIN("GPIO168_C22", in_pu_slpm_out_lo, "ske"), /* O0 */
+ /* Mux in and drive the SDI0 DAT31DIR line high at runtime */
+ DB8500_MUX("mc0dat31dir_a_1", "mc0", "sdi0"),
+ DB8500_PIN("GPIO21_AB3", out_hi, "sdi0"),
};
-static pin_cfg_t hrefv60_pins[] = {
- /* WLAN */
- GPIO4_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */
- GPIO85_GPIO | PIN_OUTPUT_LOW,/* WLAN_ENA */
-
- /* XENON Flashgun INTERFACE */
- GPIO6_IP_GPIO0 | PIN_INPUT_PULLUP,/* XENON_FLASH_ID */
- GPIO7_IP_GPIO1 | PIN_INPUT_PULLUP,/* XENON_READY */
- GPIO170_GPIO | PIN_OUTPUT_LOW, /* XENON_CHARGE */
-
- /* Assistant LED INTERFACE */
- GPIO21_GPIO | PIN_OUTPUT_LOW, /* XENON_EN1 */
- GPIO64_IP_GPIO4 | PIN_OUTPUT_LOW, /* XENON_EN2 */
-
- /* Magnetometer */
- GPIO31_GPIO | PIN_INPUT_PULLUP, /* magnetometer_INT */
- GPIO32_GPIO | PIN_INPUT_PULLDOWN, /* Magnetometer DRDY */
-
- /* Display Interface */
- GPIO65_GPIO | PIN_OUTPUT_LOW, /* DISP1 RST */
- GPIO66_GPIO | PIN_OUTPUT_LOW, /* DISP2 RST */
-
- /* Touch screen INTERFACE */
- GPIO143_GPIO | PIN_OUTPUT_LOW,/*TOUCH_RST1 */
-
- /* Touch screen INTERFACE 2 */
- GPIO67_GPIO | PIN_INPUT_PULLUP, /* TOUCH_INT2 */
- GPIO146_GPIO | PIN_OUTPUT_LOW,/*TOUCH_RST2 */
-
- /* ETM_PTM_TRACE INTERFACE */
- GPIO70_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA23 */
- GPIO71_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA22 */
- GPIO72_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA21 */
- GPIO73_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA20 */
- GPIO74_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA19 */
-
- /* NAHJ INTERFACE */
- GPIO76_GPIO | PIN_OUTPUT_LOW,/* NAHJ_CTRL */
- GPIO216_GPIO | PIN_OUTPUT_HIGH,/* NAHJ_CTRL_INV */
-
- /* NFC INTERFACE */
- GPIO77_GPIO | PIN_OUTPUT_LOW, /* NFC_ENA */
- GPIO144_GPIO | PIN_INPUT_PULLDOWN, /* NFC_IRQ */
- GPIO142_GPIO | PIN_OUTPUT_LOW, /* NFC_RESET */
-
- /* Keyboard MATRIX INTERFACE */
- GPIO90_MC5_CMD | PIN_OUTPUT_LOW, /* KP_O_1 */
- GPIO87_MC5_DAT1 | PIN_OUTPUT_LOW, /* KP_O_2 */
- GPIO86_MC5_DAT0 | PIN_OUTPUT_LOW, /* KP_O_3 */
- GPIO96_KP_O6 | PIN_OUTPUT_LOW, /* KP_O_6 */
- GPIO94_KP_O7 | PIN_OUTPUT_LOW, /* KP_O_7 */
- GPIO93_MC5_DAT4 | PIN_INPUT_PULLUP, /* KP_I_0 */
- GPIO89_MC5_DAT3 | PIN_INPUT_PULLUP, /* KP_I_2 */
- GPIO88_MC5_DAT2 | PIN_INPUT_PULLUP, /* KP_I_3 */
- GPIO91_GPIO | PIN_INPUT_PULLUP, /* FORCE_SENSING_INT */
- GPIO92_GPIO | PIN_OUTPUT_LOW, /* FORCE_SENSING_RST */
- GPIO97_GPIO | PIN_OUTPUT_LOW, /* FORCE_SENSING_WU */
-
- /* DiPro Sensor Interface */
- GPIO139_GPIO | PIN_INPUT_PULLUP, /* DIPRO_INT */
-
- /* HAL SWITCH INTERFACE */
- GPIO145_GPIO | PIN_INPUT_PULLDOWN,/* HAL_SW */
-
- /* Audio Amplifier Interface */
- GPIO149_GPIO | PIN_OUTPUT_LOW, /* VAUDIO_HF_EN */
-
- /* GBF INTERFACE */
- GPIO171_GPIO | PIN_OUTPUT_LOW, /* GBF_ENA_RESET */
-
- /* MSP : HDTV INTERFACE */
- GPIO192_GPIO | PIN_INPUT_PULLDOWN,
-
- /* ACCELEROMETER_INTERFACE */
- GPIO82_GPIO | PIN_INPUT_PULLUP, /* ACC_INT1 */
- GPIO83_GPIO | PIN_INPUT_PULLUP, /* ACC_INT2 */
-
- /* Proximity Sensor */
- GPIO217_GPIO | PIN_INPUT_PULLUP,
-
-
+/*
+ * The HREFv60 series of platforms is using available pins on the DB8500
+ * insteaf of the Toshiba I2C GPIO expander, reusing some pins like the SSP0
+ * and SSP1 ports (previously connected to the AB8500) as generic GPIO lines.
+ */
+static struct pinctrl_map __initdata hrefv60_pinmap[] = {
+ /* Drive WLAN_ENA low */
+ DB8500_PIN_HOG("GPIO85_D5", gpio_out_lo), /* WLAN_ENA */
+ /*
+ * XENON Flashgun on image processor GPIO (controlled from image
+ * processor firmware), mux in these image processor GPIO lines 0
+ * (XENON_FLASH_ID), 1 (XENON_READY) and there is an assistant
+ * LED on IP GPIO 4 (XENON_EN2) on altfunction C, that need bias
+ * from GPIO21 so pull up 0, 1 and drive 4 and GPIO21 low as output.
+ */
+ DB8500_MUX_HOG("ipgpio0_c_1", "ipgpio"),
+ DB8500_MUX_HOG("ipgpio1_c_1", "ipgpio"),
+ DB8500_MUX_HOG("ipgpio4_c_1", "ipgpio"),
+ DB8500_PIN_HOG("GPIO6_AF6", in_pu), /* XENON_FLASH_ID */
+ DB8500_PIN_HOG("GPIO7_AG5", in_pu), /* XENON_READY */
+ DB8500_PIN_HOG("GPIO21_AB3", gpio_out_lo), /* XENON_EN1 */
+ DB8500_PIN_HOG("GPIO64_F3", out_lo), /* XENON_EN2 */
+ /* Magnetometer uses GPIO 31 and 32, pull these up/down respectively */
+ DB8500_PIN_HOG("GPIO31_V3", gpio_in_pu), /* EN1 */
+ DB8500_PIN_HOG("GPIO32_V2", gpio_in_pd), /* DRDY */
+ /*
+ * Display Interface 1 uses GPIO 65 for RST (reset).
+ * Display Interface 2 uses GPIO 66 for RST (reset).
+ * Drive DISP1 reset high (not reset), driver DISP2 reset low (reset)
+ */
+ DB8500_PIN_HOG("GPIO65_F1", gpio_out_hi), /* DISP1 NO RST */
+ DB8500_PIN_HOG("GPIO66_G3", gpio_out_lo), /* DISP2 RST */
+ /*
+ * Touch screen uses GPIO 143 for RST1, GPIO 146 for RST2 and
+ * GPIO 67 for interrupts. Pull-up the IRQ line and drive both
+ * reset signals low.
+ */
+ DB8500_PIN_HOG("GPIO143_D12", gpio_out_lo), /* TOUCH_RST1 */
+ DB8500_PIN_HOG("GPIO67_G2", gpio_in_pu), /* TOUCH_INT2 */
+ DB8500_PIN_HOG("GPIO146_D13", gpio_out_lo), /* TOUCH_RST2 */
+ /*
+ * Drive D19-D23 for the ETM PTM trace interface low,
+ * (presumably pins are unconnected therefore grounded here,
+ * the "other alt C1" setting enables these pins)
+ */
+ DB8500_PIN_HOG("GPIO70_G5", gpio_out_lo),
+ DB8500_PIN_HOG("GPIO71_G4", gpio_out_lo),
+ DB8500_PIN_HOG("GPIO72_H4", gpio_out_lo),
+ DB8500_PIN_HOG("GPIO73_H3", gpio_out_lo),
+ DB8500_PIN_HOG("GPIO74_J3", gpio_out_lo),
+ /* NAHJ CTRL on GPIO 76 to low, CTRL_INV on GPIO216 to high */
+ DB8500_PIN_HOG("GPIO76_J2", gpio_out_lo), /* CTRL */
+ DB8500_PIN_HOG("GPIO216_AG12", gpio_out_hi), /* CTRL_INV */
+ /* NFC ENA and RESET to low, pulldown IRQ line */
+ DB8500_PIN_HOG("GPIO77_H1", gpio_out_lo), /* NFC_ENA */
+ DB8500_PIN_HOG("GPIO144_B13", gpio_in_pd), /* NFC_IRQ */
+ DB8500_PIN_HOG("GPIO142_C11", gpio_out_lo), /* NFC_RESET */
+ /*
+ * SKE keyboard partly on alt A and partly on "Other alt C1"
+ * Driver KP_O1,2,3,6,7 low and pull up KP_I 0,2,3 for three
+ * rows of 6 keys, then pull up force sensing interrup and
+ * drive reset and force sensing WU low.
+ */
+ DB8500_MUX_HOG("kp_a_1", "kp"),
+ DB8500_MUX_HOG("kp_oc1_1", "kp"),
+ DB8500_PIN_HOG("GPIO90_A3", out_lo), /* KP_O1 */
+ DB8500_PIN_HOG("GPIO87_B3", out_lo), /* KP_O2 */
+ DB8500_PIN_HOG("GPIO86_C6", out_lo), /* KP_O3 */
+ DB8500_PIN_HOG("GPIO96_D8", out_lo), /* KP_O6 */
+ DB8500_PIN_HOG("GPIO94_D7", out_lo), /* KP_O7 */
+ DB8500_PIN_HOG("GPIO93_B7", in_pu), /* KP_I0 */
+ DB8500_PIN_HOG("GPIO89_E6", in_pu), /* KP_I2 */
+ DB8500_PIN_HOG("GPIO88_C4", in_pu), /* KP_I3 */
+ DB8500_PIN_HOG("GPIO91_B6", gpio_in_pu), /* FORCE_SENSING_INT */
+ DB8500_PIN_HOG("GPIO92_D6", gpio_out_lo), /* FORCE_SENSING_RST */
+ DB8500_PIN_HOG("GPIO97_D9", gpio_out_lo), /* FORCE_SENSING_WU */
+ /* DiPro Sensor interrupt */
+ DB8500_PIN_HOG("GPIO139_C9", gpio_in_pu), /* DIPRO_INT */
+ /* Audio Amplifier HF enable */
+ DB8500_PIN_HOG("GPIO149_B14", gpio_out_hi), /* VAUDIO_HF_EN, enable MAX8968 */
+ /* GBF interface, pull low to reset state */
+ DB8500_PIN_HOG("GPIO171_D23", gpio_out_lo), /* GBF_ENA_RESET */
+ /* MSP : HDTV INTERFACE GPIO line */
+ DB8500_PIN_HOG("GPIO192_AJ27", gpio_in_pd),
+ /* Accelerometer interrupt lines */
+ DB8500_PIN_HOG("GPIO82_C1", gpio_in_pu), /* ACC_INT1 */
+ DB8500_PIN_HOG("GPIO83_D3", gpio_in_pu), /* ACC_INT2 */
+ /* SD card detect GPIO pin */
+ DB8500_PIN_HOG("GPIO95_E8", gpio_in_pu),
+ /*
+ * Runtime stuff
+ * Pull up/down of some sensor GPIO pins, for proximity, HAL sensor
+ * etc.
+ */
+ DB8500_PIN("GPIO217_AH12", gpio_in_pu_slpm_gpio_nopull, "gpio-keys.0"),
+ DB8500_PIN("GPIO145_C13", gpio_in_pd_slpm_gpio_nopull, "gpio-keys.0"),
+ DB8500_PIN("GPIO139_C9", gpio_in_pu_slpm_gpio_nopull, "gpio-keys.0"),
+ /*
+ * Make it possible to mux in the SKE keypad and bias the pins
+ * FIXME: what's the point with this on HREFv60? KP/SKE is already
+ * muxed in at another place! Enabling this will bork.
+ */
+ DB8500_MUX("kp_a_2", "kp", "ske"),
+ DB8500_PIN("GPIO153_B17", in_pd_slpm_in_pu, "ske"), /* I7 */
+ DB8500_PIN("GPIO154_C16", in_pd_slpm_in_pu, "ske"), /* I6 */
+ DB8500_PIN("GPIO155_C19", in_pd_slpm_in_pu, "ske"), /* I5 */
+ DB8500_PIN("GPIO156_C17", in_pd_slpm_in_pu, "ske"), /* I4 */
+ DB8500_PIN("GPIO161_D21", in_pd_slpm_in_pu, "ske"), /* I3 */
+ DB8500_PIN("GPIO162_D20", in_pd_slpm_in_pu, "ske"), /* I2 */
+ DB8500_PIN("GPIO163_C20", in_pd_slpm_in_pu, "ske"), /* I1 */
+ DB8500_PIN("GPIO164_B21", in_pd_slpm_in_pu, "ske"), /* I0 */
+ DB8500_PIN("GPIO157_A18", in_pu_slpm_out_lo, "ske"), /* O7 */
+ DB8500_PIN("GPIO158_C18", in_pu_slpm_out_lo, "ske"), /* O6 */
+ DB8500_PIN("GPIO159_B19", in_pu_slpm_out_lo, "ske"), /* O5 */
+ DB8500_PIN("GPIO160_B20", in_pu_slpm_out_lo, "ske"), /* O4 */
+ DB8500_PIN("GPIO165_C21", in_pu_slpm_out_lo, "ske"), /* O3 */
+ DB8500_PIN("GPIO166_A22", in_pu_slpm_out_lo, "ske"), /* O2 */
+ DB8500_PIN("GPIO167_B24", in_pu_slpm_out_lo, "ske"), /* O1 */
+ DB8500_PIN("GPIO168_C22", in_pu_slpm_out_lo, "ske"), /* O0 */
};
-static pin_cfg_t snowball_pins[] = {
- /* SSP0, to AB8500 */
- GPIO143_SSP0_CLK,
- GPIO144_SSP0_FRM,
- GPIO145_SSP0_RXD | PIN_PULL_DOWN,
- GPIO146_SSP0_TXD,
+static struct pinctrl_map __initdata u9500_pinmap[] = {
+ /* Mux in UART1 (just RX/TX) and set the pull-ups */
+ DB8500_MUX_HOG("u1rxtx_a_1", "u1"),
+ DB8500_PIN_HOG("GPIO4_AH6", in_pu),
+ DB8500_PIN_HOG("GPIO5_AG6", out_hi),
+ /* WLAN_IRQ line */
+ DB8500_PIN_HOG("GPIO144_B13", gpio_in_pu),
+ /* HSI */
+ DB8500_MUX_HOG("hsir_a_1", "hsi"),
+ DB8500_MUX_HOG("hsit_a_1", "hsi"),
+ DB8500_PIN_HOG("GPIO219_AG10", in_pd), /* RX FLA0 */
+ DB8500_PIN_HOG("GPIO220_AH10", in_pd), /* RX DAT0 */
+ DB8500_PIN_HOG("GPIO221_AJ11", out_lo), /* RX RDY0 */
+ DB8500_PIN_HOG("GPIO222_AJ9", out_lo), /* TX FLA0 */
+ DB8500_PIN_HOG("GPIO223_AH9", out_lo), /* TX DAT0 */
+ DB8500_PIN_HOG("GPIO224_AG9", in_pd), /* TX RDY0 */
+ DB8500_PIN_HOG("GPIO225_AG8", in_pd), /* CAWAKE0 */
+ DB8500_PIN_HOG("GPIO226_AF8", out_hi), /* ACWAKE0 */
+};
- /* MMC0: MicroSD card */
- GPIO21_MC0_DAT31DIR | PIN_OUTPUT_HIGH,
+static struct pinctrl_map __initdata u8500_pinmap[] = {
+ DB8500_PIN_HOG("GPIO226_AF8", gpio_out_lo), /* WLAN_PMU_EN */
+ DB8500_PIN_HOG("GPIO4_AH6", gpio_in_pu), /* WLAN_IRQ */
+};
- /* MMC2: LAN */
- GPIO86_SM_ADQ0,
- GPIO87_SM_ADQ1,
- GPIO88_SM_ADQ2,
- GPIO89_SM_ADQ3,
- GPIO90_SM_ADQ4,
- GPIO91_SM_ADQ5,
- GPIO92_SM_ADQ6,
- GPIO93_SM_ADQ7,
+static struct pinctrl_map __initdata snowball_pinmap[] = {
+ /* Mux in SSP0 connected to AB8500, pull down RXD pin */
+ DB8500_MUX_HOG("ssp0_a_1", "ssp0"),
+ DB8500_PIN_HOG("GPIO145_C13", pd),
+ /* Always drive the MC0 DAT31DIR line high on these boards */
+ DB8500_PIN_HOG("GPIO21_AB3", out_hi),
+ /* Mux in "SM" which is used for the SMSC911x Ethernet adapter */
+ DB8500_MUX_HOG("sm_b_1", "sm"),
+ /* Drive RSTn_LAN high */
+ DB8500_PIN_HOG("GPIO141_C12", gpio_out_hi),
+ /* Accelerometer/Magnetometer */
+ DB8500_PIN_HOG("GPIO163_C20", gpio_in_pu), /* ACCEL_IRQ1 */
+ DB8500_PIN_HOG("GPIO164_B21", gpio_in_pu), /* ACCEL_IRQ2 */
+ DB8500_PIN_HOG("GPIO165_C21", gpio_in_pu), /* MAG_DRDY */
+ /* WLAN/GBF */
+ DB8500_PIN_HOG("GPIO161_D21", gpio_out_lo), /* WLAN_PMU_EN */
+ DB8500_PIN_HOG("GPIO171_D23", gpio_out_hi), /* GBF_ENA */
+ DB8500_PIN_HOG("GPIO215_AH13", gpio_out_lo), /* WLAN_ENA */
+ DB8500_PIN_HOG("GPIO216_AG12", gpio_in_pu), /* WLAN_IRQ */
+};
- GPIO94_SM_ADVn,
- GPIO95_SM_CS0n,
- GPIO96_SM_OEn,
- GPIO97_SM_WEn,
+/*
+ * passing "pinsfor=" in kernel cmdline allows for custom
+ * configuration of GPIOs on u8500 derived boards.
+ */
+static int __init early_pinsfor(char *p)
+{
+ pinsfor = PINS_FOR_DEFAULT;
- GPIO128_SM_CKO,
- GPIO130_SM_FBCLK,
- GPIO131_SM_ADQ8,
- GPIO132_SM_ADQ9,
- GPIO133_SM_ADQ10,
- GPIO134_SM_ADQ11,
- GPIO135_SM_ADQ12,
- GPIO136_SM_ADQ13,
- GPIO137_SM_ADQ14,
- GPIO138_SM_ADQ15,
+ if (strcmp(p, "u9500-21") == 0)
+ pinsfor = PINS_FOR_U9500;
- /* RSTn_LAN */
- GPIO141_GPIO | PIN_OUTPUT_HIGH,
-};
+ return 0;
+}
+early_param("pinsfor", early_pinsfor);
-void __init mop500_pins_init(void)
+int pins_for_u9500(void)
{
- nmk_config_pins(mop500_pins_common,
- ARRAY_SIZE(mop500_pins_common));
+ if (pinsfor == PINS_FOR_U9500)
+ return 1;
- nmk_config_pins(mop500_pins_default,
- ARRAY_SIZE(mop500_pins_default));
+ return 0;
}
-void __init snowball_pins_init(void)
+static void __init mop500_href_family_pinmaps_init(void)
{
- nmk_config_pins(mop500_pins_common,
- ARRAY_SIZE(mop500_pins_common));
+ switch (pinsfor) {
+ case PINS_FOR_U9500:
+ pinctrl_register_mappings(u9500_pinmap,
+ ARRAY_SIZE(u9500_pinmap));
+ break;
+ case PINS_FOR_DEFAULT:
+ pinctrl_register_mappings(u8500_pinmap,
+ ARRAY_SIZE(u8500_pinmap));
+ default:
+ break;
+ }
+}
- nmk_config_pins(snowball_pins,
- ARRAY_SIZE(snowball_pins));
+void __init mop500_pinmaps_init(void)
+{
+ pinctrl_register_mappings(mop500_family_pinmap,
+ ARRAY_SIZE(mop500_family_pinmap));
+ pinctrl_register_mappings(mop500_pinmap,
+ ARRAY_SIZE(mop500_pinmap));
+ mop500_href_family_pinmaps_init();
}
-void __init hrefv60_pins_init(void)
+void __init snowball_pinmaps_init(void)
{
- nmk_config_pins(mop500_pins_common,
- ARRAY_SIZE(mop500_pins_common));
+ pinctrl_register_mappings(mop500_family_pinmap,
+ ARRAY_SIZE(mop500_family_pinmap));
+ pinctrl_register_mappings(snowball_pinmap,
+ ARRAY_SIZE(snowball_pinmap));
+ pinctrl_register_mappings(u8500_pinmap,
+ ARRAY_SIZE(u8500_pinmap));
+}
- nmk_config_pins(hrefv60_pins,
- ARRAY_SIZE(hrefv60_pins));
+void __init hrefv60_pinmaps_init(void)
+{
+ pinctrl_register_mappings(mop500_family_pinmap,
+ ARRAY_SIZE(mop500_family_pinmap));
+ pinctrl_register_mappings(hrefv60_pinmap,
+ ARRAY_SIZE(hrefv60_pinmap));
+ mop500_href_family_pinmaps_init();
}
diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c
index 5af36aa56c08..b29a788f498c 100644
--- a/arch/arm/mach-ux500/board-mop500-uib.c
+++ b/arch/arm/mach-ux500/board-mop500-uib.c
@@ -102,7 +102,7 @@ static int __init mop500_uib_init(void)
struct i2c_adapter *i2c0;
int ret;
- if (!cpu_is_u8500())
+ if (!cpu_is_u8500_family())
return -ENODEV;
if (uib) {
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 77d03c1fbd04..f943687acaf0 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -1,3 +1,4 @@
+
/*
* Copyright (C) 2008-2009 ST-Ericsson
*
@@ -29,30 +30,30 @@
#include <linux/smsc911x.h>
#include <linux/gpio_keys.h>
#include <linux/delay.h>
-
#include <linux/of.h>
#include <linux/of_platform.h>
-
#include <linux/leds.h>
+#include <linux/pinctrl/consumer.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
#include <plat/i2c.h>
#include <plat/ste_dma40.h>
-#include <plat/pincfg.h>
#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
#include <mach/setup.h>
#include <mach/devices.h>
#include <mach/irqs.h>
+#include <mach/crypto-ux500.h>
-#include "pins-db8500.h"
#include "ste-dma40-db8500.h"
#include "devices-db8500.h"
#include "board-mop500.h"
#include "board-mop500-regulators.h"
+#include "board-mop500-msp.h"
static struct gpio_led snowball_led_array[] = {
{
@@ -417,6 +418,45 @@ static void mop500_prox_deactivate(struct device *dev)
regulator_put(prox_regulator);
}
+static struct cryp_platform_data u8500_cryp1_platform_data = {
+ .mem_to_engine = {
+ .dir = STEDMA40_MEM_TO_PERIPH,
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV48_CAC1_TX,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+ .mode = STEDMA40_MODE_LOGICAL,
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+ },
+ .engine_to_mem = {
+ .dir = STEDMA40_PERIPH_TO_MEM,
+ .src_dev_type = DB8500_DMA_DEV48_CAC1_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+ .mode = STEDMA40_MODE_LOGICAL,
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+ }
+};
+
+static struct stedma40_chan_cfg u8500_hash_dma_cfg_tx = {
+ .dir = STEDMA40_MEM_TO_PERIPH,
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV50_HAC1_TX,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+ .mode = STEDMA40_MODE_LOGICAL,
+ .src_info.psize = STEDMA40_PSIZE_LOG_16,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_16,
+};
+
+static struct hash_platform_data u8500_hash1_platform_data = {
+ .mem_to_engine = &u8500_hash_dma_cfg_tx,
+ .dma_filter = stedma40_filter,
+};
+
/* add any platform devices here - TODO */
static struct platform_device *mop500_platform_devs[] __initdata = {
&mop500_gpio_keys_device,
@@ -520,14 +560,6 @@ static struct stedma40_chan_cfg uart2_dma_cfg_tx = {
};
#endif
-
-static pin_cfg_t mop500_pins_uart0[] = {
- GPIO0_U0_CTSn | PIN_INPUT_PULLUP,
- GPIO1_U0_RTSn | PIN_OUTPUT_HIGH,
- GPIO2_U0_RXD | PIN_INPUT_PULLUP,
- GPIO3_U0_TXD | PIN_OUTPUT_HIGH,
-};
-
#define PRCC_K_SOFTRST_SET 0x18
#define PRCC_K_SOFTRST_CLEAR 0x1C
static void ux500_uart0_reset(void)
@@ -548,24 +580,33 @@ static void ux500_uart0_reset(void)
udelay(1);
}
+/* This needs to be referenced by callbacks */
+struct pinctrl *u0_p;
+struct pinctrl_state *u0_def;
+struct pinctrl_state *u0_sleep;
+
static void ux500_uart0_init(void)
{
int ret;
- ret = nmk_config_pins(mop500_pins_uart0,
- ARRAY_SIZE(mop500_pins_uart0));
- if (ret < 0)
- pr_err("pl011: uart pins_enable failed\n");
+ if (IS_ERR(u0_p) || IS_ERR(u0_def))
+ return;
+
+ ret = pinctrl_select_state(u0_p, u0_def);
+ if (ret)
+ pr_err("could not set UART0 defstate\n");
}
static void ux500_uart0_exit(void)
{
int ret;
- ret = nmk_config_pins_sleep(mop500_pins_uart0,
- ARRAY_SIZE(mop500_pins_uart0));
- if (ret < 0)
- pr_err("pl011: uart pins_disable failed\n");
+ if (IS_ERR(u0_p) || IS_ERR(u0_sleep))
+ return;
+
+ ret = pinctrl_select_state(u0_p, u0_sleep);
+ if (ret)
+ pr_err("could not set UART0 idlestate\n");
}
static struct amba_pl011_data uart0_plat = {
@@ -597,15 +638,41 @@ static struct amba_pl011_data uart2_plat = {
static void __init mop500_uart_init(struct device *parent)
{
- db8500_add_uart0(parent, &uart0_plat);
+ struct amba_device *uart0_device;
+
+ uart0_device = db8500_add_uart0(parent, &uart0_plat);
+ if (uart0_device) {
+ u0_p = pinctrl_get(&uart0_device->dev);
+ if (IS_ERR(u0_p))
+ dev_err(&uart0_device->dev,
+ "could not get UART0 pinctrl\n");
+ else {
+ u0_def = pinctrl_lookup_state(u0_p,
+ PINCTRL_STATE_DEFAULT);
+ if (IS_ERR(u0_def)) {
+ dev_err(&uart0_device->dev,
+ "could not get UART0 defstate\n");
+ }
+ u0_sleep = pinctrl_lookup_state(u0_p,
+ PINCTRL_STATE_SLEEP);
+ if (IS_ERR(u0_sleep))
+ dev_err(&uart0_device->dev,
+ "could not get UART0 idlestate\n");
+ }
+ }
db8500_add_uart1(parent, &uart1_plat);
db8500_add_uart2(parent, &uart2_plat);
}
+static void __init u8500_cryp1_hash1_init(struct device *parent)
+{
+ db8500_add_cryp1(parent, &u8500_cryp1_platform_data);
+ db8500_add_hash1(parent, &u8500_hash1_platform_data);
+}
+
static struct platform_device *snowball_platform_devs[] __initdata = {
&snowball_led_dev,
&snowball_key_dev,
- &snowball_sbnet_dev,
&ab8500_device,
};
@@ -617,10 +684,9 @@ static void __init mop500_init_machine(void)
mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
+ mop500_pinmaps_init();
parent = u8500_init_devices();
- mop500_pins_init();
-
/* FIXME: parent of ab8500 should be prcmu */
for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
mop500_platform_devs[i]->dev.parent = parent;
@@ -631,8 +697,11 @@ static void __init mop500_init_machine(void)
mop500_i2c_init(parent);
mop500_sdi_init(parent);
mop500_spi_init(parent);
+ mop500_msp_init(parent);
mop500_uart_init(parent);
+ u8500_cryp1_hash1_init(parent);
+
i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
@@ -646,13 +715,11 @@ static void __init mop500_init_machine(void)
static void __init snowball_init_machine(void)
{
struct device *parent = NULL;
- int i2c0_devs;
int i;
+ snowball_pinmaps_init();
parent = u8500_init_devices();
- snowball_pins_init();
-
for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++)
snowball_platform_devs[i]->dev.parent = parent;
@@ -662,13 +729,9 @@ static void __init snowball_init_machine(void)
mop500_i2c_init(parent);
snowball_sdi_init(parent);
mop500_spi_init(parent);
+ mop500_msp_init(parent);
mop500_uart_init(parent);
- i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
- i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
- i2c_register_board_info(2, mop500_i2c2_devices,
- ARRAY_SIZE(mop500_i2c2_devices));
-
/* This board has full regulator constraints */
regulator_has_full_constraints();
}
@@ -686,10 +749,9 @@ static void __init hrefv60_init_machine(void)
*/
mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
+ hrefv60_pinmaps_init();
parent = u8500_init_devices();
- hrefv60_pins_init();
-
for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
mop500_platform_devs[i]->dev.parent = parent;
@@ -699,6 +761,7 @@ static void __init hrefv60_init_machine(void)
mop500_i2c_init(parent);
hrefv60_sdi_init(parent);
mop500_spi_init(parent);
+ mop500_msp_init(parent);
mop500_uart_init(parent);
i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
@@ -746,16 +809,29 @@ MACHINE_END
#ifdef CONFIG_MACH_UX500_DT
struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
+ /* Requires DMA and call-back bindings. */
OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", &uart0_plat),
OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", &uart1_plat),
OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat),
+ /* Requires DMA bindings. */
OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0", &ssp0_plat),
+ /* Requires clock name bindings. */
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e000, "gpio.0", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e080, "gpio.1", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e000, "gpio.2", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e080, "gpio.3", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e100, "gpio.4", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e180, "gpio.5", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e000, "gpio.6", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e080, "gpio.7", NULL),
+ OF_DEV_AUXDATA("st,nomadik-gpio", 0xa03fe000, "gpio.8", NULL),
{},
};
-static const struct of_device_id u8500_soc_node[] = {
+static const struct of_device_id u8500_local_bus_nodes[] = {
/* only create devices below soc node */
{ .compatible = "stericsson,db8500", },
+ { .compatible = "simple-bus"},
{ },
};
@@ -765,8 +841,15 @@ static void __init u8500_init_machine(void)
int i2c0_devs;
int i;
+ /* Pinmaps must be in place before devices register */
+ if (of_machine_is_compatible("st-ericsson,mop500"))
+ mop500_pinmaps_init();
+ else if (of_machine_is_compatible("calaosystems,snowball-a9500"))
+ snowball_pinmaps_init();
+ else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
+ hrefv60_pinmaps_init();
+
parent = u8500_init_devices();
- i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
mop500_platform_devs[i]->dev.parent = parent;
@@ -774,18 +857,22 @@ static void __init u8500_init_machine(void)
snowball_platform_devs[i]->dev.parent = parent;
/* automatically probe child nodes of db8500 device */
- of_platform_populate(NULL, u8500_soc_node, u8500_auxdata_lookup, parent);
+ of_platform_populate(NULL, u8500_local_bus_nodes, u8500_auxdata_lookup, parent);
if (of_machine_is_compatible("st-ericsson,mop500")) {
mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
- mop500_pins_init();
platform_add_devices(mop500_platform_devs,
ARRAY_SIZE(mop500_platform_devs));
mop500_sdi_init(parent);
+
+ i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
+ i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
+ i2c_register_board_info(2, mop500_i2c2_devices,
+ ARRAY_SIZE(mop500_i2c2_devices));
+
} else if (of_machine_is_compatible("calaosystems,snowball-a9500")) {
- snowball_pins_init();
platform_add_devices(snowball_platform_devs,
ARRAY_SIZE(snowball_platform_devs));
@@ -797,19 +884,20 @@ static void __init u8500_init_machine(void)
* instead.
*/
mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
- i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
- hrefv60_pins_init();
platform_add_devices(mop500_platform_devs,
ARRAY_SIZE(mop500_platform_devs));
hrefv60_sdi_init(parent);
+
+ i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
+ i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
+
+ i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
+ i2c_register_board_info(2, mop500_i2c2_devices,
+ ARRAY_SIZE(mop500_i2c2_devices));
}
mop500_i2c_init(parent);
- i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
- i2c_register_board_info(2, mop500_i2c2_devices,
- ARRAY_SIZE(mop500_i2c2_devices));
-
/* This board has full regulator constraints */
regulator_has_full_constraints();
}
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index fdcfa8721bb4..bc44c07c71a9 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -7,6 +7,9 @@
#ifndef __BOARD_MOP500_H
#define __BOARD_MOP500_H
+/* For NOMADIK_NR_GPIO */
+#include <mach/irqs.h>
+
/* Snowball specific GPIO assignments, this board has no GPIO expander */
#define SNOWBALL_ACCEL_INT1_GPIO 163
#define SNOWBALL_ACCEL_INT2_GPIO 164
@@ -73,6 +76,7 @@
#define SNOWBALL_PME_ETH_GPIO MOP500_AB8500_PIN_GPIO(24) /* SYSCLKREQ7/GPIO24 */
#define SNOWBALL_EN_3V3_ETH_GPIO MOP500_AB8500_PIN_GPIO(26) /* GPIO26 */
+struct device;
struct i2c_board_info;
extern void mop500_sdi_init(struct device *parent);
@@ -81,9 +85,9 @@ extern void hrefv60_sdi_init(struct device *parent);
extern void mop500_sdi_tc35892_init(struct device *parent);
void __init mop500_u8500uib_init(void);
void __init mop500_stuib_init(void);
-void __init mop500_pins_init(void);
-void __init hrefv60_pins_init(void);
-void __init snowball_pins_init(void);
+void __init mop500_pinmaps_init(void);
+void __init snowball_pinmaps_init(void);
+void __init hrefv60_pinmaps_init(void);
void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
unsigned n);
diff --git a/arch/arm/mach-ux500/board-u5500-sdi.c b/arch/arm/mach-ux500/board-u5500-sdi.c
deleted file mode 100644
index 836112eedde7..000000000000
--- a/arch/arm/mach-ux500/board-u5500-sdi.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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 <plat/pincfg.h>
-#include <plat/gpio-nomadik.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,
-};
-
-#ifdef CONFIG_STE_DMA40
-struct stedma40_chan_cfg u5500_sdi0_dma_cfg_rx = {
- .mode = STEDMA40_MODE_LOGICAL,
- .dir = STEDMA40_PERIPH_TO_MEM,
- .src_dev_type = DB5500_DMA_DEV24_SDMMC0_RX,
- .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
- .src_info.data_width = STEDMA40_WORD_WIDTH,
- .dst_info.data_width = STEDMA40_WORD_WIDTH,
-};
-
-static struct stedma40_chan_cfg u5500_sdi0_dma_cfg_tx = {
- .mode = STEDMA40_MODE_LOGICAL,
- .dir = STEDMA40_MEM_TO_PERIPH,
- .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
- .dst_dev_type = DB5500_DMA_DEV24_SDMMC0_TX,
- .src_info.data_width = STEDMA40_WORD_WIDTH,
- .dst_info.data_width = STEDMA40_WORD_WIDTH,
-};
-#endif
-
-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,
-#ifdef CONFIG_STE_DMA40
- .dma_filter = stedma40_filter,
- .dma_rx_param = &u5500_sdi0_dma_cfg_rx,
- .dma_tx_param = &u5500_sdi0_dma_cfg_tx,
-#endif
-};
-
-void __init u5500_sdi_init(struct device *parent)
-{
- nmk_config_pins(u5500_sdi_pins, ARRAY_SIZE(u5500_sdi_pins));
-
- db5500_add_sdi0(parent, &u5500_sdi0_data);
-}
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c
deleted file mode 100644
index 0ff4be72a809..000000000000
--- a/arch/arm/mach-ux500/board-u5500.c
+++ /dev/null
@@ -1,162 +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/init.h>
-#include <linux/platform_device.h>
-#include <linux/amba/bus.h>
-#include <linux/irq.h>
-#include <linux/i2c.h>
-#include <linux/mfd/abx500/ab5500.h>
-
-#include <asm/hardware/gic.h>
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <plat/pincfg.h>
-#include <plat/i2c.h>
-#include <plat/gpio-nomadik.h>
-
-#include <mach/hardware.h>
-#include <mach/devices.h>
-#include <mach/setup.h>
-
-#include "pins-db5500.h"
-#include "devices-db5500.h"
-#include <linux/led-lm3530.h>
-
-/*
- * GPIO
- */
-
-static pin_cfg_t u5500_pins[] = {
- /* I2C */
- GPIO218_I2C2_SCL | PIN_INPUT_PULLUP,
- GPIO219_I2C2_SDA | PIN_INPUT_PULLUP,
-
- /* DISPLAY_ENABLE */
- GPIO226_GPIO | PIN_OUTPUT_LOW,
-
- /* Backlight Enbale */
- GPIO224_GPIO | PIN_OUTPUT_HIGH,
-};
-/*
- * I2C
- */
-
-#define U5500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \
-static struct nmk_i2c_controller u5500_i2c##id##_data = { \
- /* \
- * slave data setup time, which is \
- * 250 ns,100ns,10ns which is 14,6,2 \
- * respectively for a 48 Mhz \
- * i2c clock \
- */ \
- .slsu = _slsu, \
- /* Tx FIFO threshold */ \
- .tft = _tft, \
- /* Rx FIFO threshold */ \
- .rft = _rft, \
- /* std. mode operation */ \
- .clk_freq = clk, \
- .sm = _sm, \
-}
-/*
- * The board uses TODO <3> i2c controllers, initialize all of
- * them with slave data setup time of 250 ns,
- * Tx & Rx FIFO threshold values as 1 and standard
- * mode of operation
- */
-
-U5500_I2C_CONTROLLER(2, 0xe, 1, 1, 400000, I2C_FREQ_MODE_FAST);
-
-static struct lm3530_platform_data u5500_als_platform_data = {
- .mode = LM3530_BL_MODE_MANUAL,
- .als_input_mode = LM3530_INPUT_ALS1,
- .max_current = LM3530_FS_CURR_26mA,
- .pwm_pol_hi = true,
- .als_avrg_time = LM3530_ALS_AVRG_TIME_512ms,
- .brt_ramp_law = 1, /* Linear */
- .brt_ramp_fall = LM3530_RAMP_TIME_8s,
- .brt_ramp_rise = LM3530_RAMP_TIME_8s,
- .als1_resistor_sel = LM3530_ALS_IMPD_13_53kOhm,
- .als2_resistor_sel = LM3530_ALS_IMPD_Z,
- .als_vmin = 730, /* mV */
- .als_vmax = 1020, /* mV */
- .brt_val = 0x7F, /* Max brightness */
-};
-
-static struct i2c_board_info __initdata u5500_i2c2_devices[] = {
- {
- /* Backlight */
- I2C_BOARD_INFO("lm3530-led", 0x36),
- .platform_data = &u5500_als_platform_data,
- },
-};
-
-static void __init u5500_i2c_init(struct device *parent)
-{
- db5500_add_i2c2(parent, &u5500_i2c2_data);
- i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices));
-}
-
-static struct ab5500_platform_data ab5500_plf_data = {
- .irq = {
- .base = 0,
- .count = 0,
- },
- .init_settings = NULL,
- .init_settings_sz = 0,
- .pm_power_off = false,
-};
-
-static struct platform_device ab5500_device = {
- .name = "ab5500-core",
- .id = 0,
- .dev = {
- .platform_data = &ab5500_plf_data,
- },
- .num_resources = 0,
-};
-
-static struct platform_device *u5500_platform_devices[] __initdata = {
- &ab5500_device,
-};
-
-static void __init u5500_uart_init(struct device *parent)
-{
- db5500_add_uart0(parent, NULL);
- db5500_add_uart1(parent, NULL);
- db5500_add_uart2(parent, NULL);
-}
-
-static void __init u5500_init_machine(void)
-{
- struct device *parent = NULL;
- int i;
-
- parent = u5500_init_devices();
- nmk_config_pins(u5500_pins, ARRAY_SIZE(u5500_pins));
-
- u5500_i2c_init(parent);
- u5500_sdi_init(parent);
- u5500_uart_init(parent);
-
- for (i = 0; i < ARRAY_SIZE(u5500_platform_devices); i++)
- u5500_platform_devices[i]->dev.parent = parent;
-
- platform_add_devices(u5500_platform_devices,
- ARRAY_SIZE(u5500_platform_devices));
-}
-
-MACHINE_START(U5500, "ST-Ericsson U5500 Platform")
- .atag_offset = 0x100,
- .map_io = u5500_map_io,
- .init_irq = ux500_init_irq,
- .timer = &ux500_timer,
- .handle_irq = gic_handle_irq,
- .init_machine = u5500_init_machine,
-MACHINE_END
diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c
index 77a75ed0df67..dc12394295d5 100644
--- a/arch/arm/mach-ux500/cache-l2x0.c
+++ b/arch/arm/mach-ux500/cache-l2x0.c
@@ -36,9 +36,9 @@ static int __init ux500_l2x0_unlock(void)
static int __init ux500_l2x0_init(void)
{
- if (cpu_is_u5500())
- l2x0_base = __io_address(U5500_L2CC_BASE);
- else if (cpu_is_u8500())
+ u32 aux_val = 0x3e000000;
+
+ if (cpu_is_u8500_family())
l2x0_base = __io_address(U8500_L2CC_BASE);
else
ux500_unknown_soc();
@@ -46,11 +46,19 @@ static int __init ux500_l2x0_init(void)
/* Unlock before init */
ux500_l2x0_unlock();
+ /* DB9540's L2 has 128KB way size */
+ if (cpu_is_u9540())
+ /* 128KB way size */
+ aux_val |= (0x4 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
+ else
+ /* 64KB way size */
+ aux_val |= (0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
+
/* 64KB way size, 8 way associativity, force WA */
if (of_have_populated_dt())
- l2x0_of_init(0x3e060000, 0xc0000fff);
+ l2x0_of_init(aux_val, 0xc0000fff);
else
- l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
+ l2x0_init(l2x0_base, aux_val, 0xc0000fff);
/*
* We can't disable l2 as we are in non secure mode, currently
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c
index ec35f0aa5665..1762c4728f1e 100644
--- a/arch/arm/mach-ux500/clock.c
+++ b/arch/arm/mach-ux500/clock.c
@@ -149,9 +149,7 @@ static unsigned long clk_mtu_get_rate(struct clk *clk)
unsigned long mturate;
unsigned long retclk;
- if (cpu_is_u5500())
- addr = __io_address(U5500_PRCMU_BASE);
- else if (cpu_is_u8500())
+ if (cpu_is_u8500_family())
addr = __io_address(U8500_PRCMU_BASE);
else
ux500_unknown_soc();
@@ -336,6 +334,7 @@ static DEFINE_PRCMU_CLK(uiccclk, 0x4, 1, UICCCLK); /* v1 */
*/
/* Peripheral Cluster #1 */
+static DEFINE_PRCC_CLK(1, msp3, 11, 10, &clk_msp1clk);
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);
@@ -382,14 +381,15 @@ static DEFINE_PRCC_CLK(5, usb, 0, 0, NULL);
/* Peripheral Cluster #6 */
/* MTU ID in data */
-static DEFINE_PRCC_CLK_CUSTOM(6, mtu1, 8, -1, NULL, clk_mtu_get_rate, 1);
-static DEFINE_PRCC_CLK_CUSTOM(6, mtu0, 7, -1, NULL, clk_mtu_get_rate, 0);
-static DEFINE_PRCC_CLK(6, cfgreg, 6, 6, NULL);
-static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL);
-static DEFINE_PRCC_CLK(6, unipro, 4, 1, &clk_uniproclk);
-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_CUSTOM(6, mtu1, 9, -1, NULL, clk_mtu_get_rate, 1);
+static DEFINE_PRCC_CLK_CUSTOM(6, mtu0, 8, -1, NULL, clk_mtu_get_rate, 0);
+static DEFINE_PRCC_CLK(6, cfgreg, 7, 7, NULL);
+static DEFINE_PRCC_CLK(6, hash1, 6, -1, NULL);
+static DEFINE_PRCC_CLK(6, unipro, 5, 1, &clk_uniproclk);
+static DEFINE_PRCC_CLK(6, pka, 4, -1, NULL);
+static DEFINE_PRCC_CLK(6, hash0, 3, -1, NULL);
+static DEFINE_PRCC_CLK(6, cryp0, 2, -1, NULL);
+static DEFINE_PRCC_CLK(6, cryp1, 1, -1, NULL);
static DEFINE_PRCC_CLK(6, rng, 0, 0, &clk_rngclk);
static struct clk clk_dummy_apb_pclk = {
@@ -405,7 +405,7 @@ static struct clk_lookup u8500_clks[] = {
CLK(slimbus0, "slimbus0", NULL),
CLK(i2c2, "nmk-i2c.2", NULL),
CLK(sdi0, "sdi0", NULL),
- CLK(msp0, "msp0", NULL),
+ CLK(msp0, "ux500-msp-i2s.0", NULL),
CLK(i2c1, "nmk-i2c.1", NULL),
CLK(uart1, "uart1", NULL),
CLK(uart0, "uart0", NULL),
@@ -431,6 +431,7 @@ static struct clk_lookup u8500_clks[] = {
CLK(pka, "pka", NULL),
CLK(hash0, "hash0", NULL),
CLK(cryp0, "cryp0", NULL),
+ CLK(cryp1, "cryp1", NULL),
/* PRCMU level clock gating */
@@ -455,7 +456,8 @@ static struct clk_lookup u8500_clks[] = {
/* Peripheral Cluster #1 */
CLK(i2c4, "nmk-i2c.4", NULL),
CLK(spi3, "spi3", NULL),
- CLK(msp1, "msp1", NULL),
+ CLK(msp1, "ux500-msp-i2s.1", NULL),
+ CLK(msp3, "ux500-msp-i2s.3", NULL),
/* Peripheral Cluster #2 */
CLK(gpio1, "gpio.6", NULL),
@@ -465,7 +467,7 @@ static struct clk_lookup u8500_clks[] = {
CLK(spi0, "spi0", NULL),
CLK(sdi3, "sdi3", NULL),
CLK(sdi1, "sdi1", NULL),
- CLK(msp2, "msp2", NULL),
+ CLK(msp2, "ux500-msp-i2s.2", NULL),
CLK(sdi4, "sdi4", NULL),
CLK(pwl, "pwl", NULL),
CLK(spi1, "spi1", NULL),
@@ -705,14 +707,6 @@ late_initcall(clk_init_smp_twd_cpufreq);
int __init clk_init(void)
{
- if (cpu_is_u5500()) {
- /* 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_uartclk.rate = 36360000;
- clk_sdmmcclk.rate = 99900000;
- }
-
clkdev_add_table(u8500_clks, ARRAY_SIZE(u8500_clks));
clkdev_add(&clk_smp_twd_lookup);
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c
deleted file mode 100644
index bca47f32082f..000000000000
--- a/arch/arm/mach-ux500/cpu-db5500.c
+++ /dev/null
@@ -1,247 +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/amba/bus.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-
-#include <asm/mach/map.h>
-#include <asm/pmu.h>
-
-#include <plat/gpio-nomadik.h>
-
-#include <mach/hardware.h>
-#include <mach/devices.h>
-#include <mach/setup.h>
-#include <mach/irqs.h>
-#include <mach/usb.h>
-
-#include "devices-db5500.h"
-#include "ste-dma40-db5500.h"
-
-static struct map_desc u5500_uart_io_desc[] __initdata = {
- __IO_DEV_DESC(U5500_UART0_BASE, SZ_4K),
- __IO_DEV_DESC(U5500_UART2_BASE, SZ_4K),
-};
-
-static struct map_desc u5500_io_desc[] __initdata = {
- /* SCU base also covers GIC CPU BASE and TWD with its 4K page */
- __IO_DEV_DESC(U5500_SCU_BASE, SZ_4K),
- __IO_DEV_DESC(U5500_GIC_DIST_BASE, SZ_4K),
- __IO_DEV_DESC(U5500_L2CC_BASE, SZ_4K),
- __IO_DEV_DESC(U5500_MTU0_BASE, SZ_4K),
- __IO_DEV_DESC(U5500_BACKUPRAM0_BASE, SZ_8K),
-
- __IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K),
- __IO_DEV_DESC(U5500_GPIO1_BASE, SZ_4K),
- __IO_DEV_DESC(U5500_GPIO2_BASE, SZ_4K),
- __IO_DEV_DESC(U5500_GPIO3_BASE, SZ_4K),
- __IO_DEV_DESC(U5500_GPIO4_BASE, SZ_4K),
- __IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K),
- __IO_DEV_DESC(U5500_PRCMU_TCDM_BASE, SZ_4K),
-};
-
-static struct resource mbox0_resources[] = {
- {
- .name = "mbox_peer",
- .start = U5500_MBOX0_PEER_START,
- .end = U5500_MBOX0_PEER_END,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "mbox_local",
- .start = U5500_MBOX0_LOCAL_START,
- .end = U5500_MBOX0_LOCAL_END,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "mbox_irq",
- .start = MBOX_PAIR0_VIRT_IRQ,
- .end = MBOX_PAIR0_VIRT_IRQ,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-static struct resource mbox1_resources[] = {
- {
- .name = "mbox_peer",
- .start = U5500_MBOX1_PEER_START,
- .end = U5500_MBOX1_PEER_END,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "mbox_local",
- .start = U5500_MBOX1_LOCAL_START,
- .end = U5500_MBOX1_LOCAL_END,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "mbox_irq",
- .start = MBOX_PAIR1_VIRT_IRQ,
- .end = MBOX_PAIR1_VIRT_IRQ,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-static struct resource mbox2_resources[] = {
- {
- .name = "mbox_peer",
- .start = U5500_MBOX2_PEER_START,
- .end = U5500_MBOX2_PEER_END,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "mbox_local",
- .start = U5500_MBOX2_LOCAL_START,
- .end = U5500_MBOX2_LOCAL_END,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "mbox_irq",
- .start = MBOX_PAIR2_VIRT_IRQ,
- .end = MBOX_PAIR2_VIRT_IRQ,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-static struct platform_device mbox0_device = {
- .id = 0,
- .name = "mbox",
- .resource = mbox0_resources,
- .num_resources = ARRAY_SIZE(mbox0_resources),
-};
-
-static struct platform_device mbox1_device = {
- .id = 1,
- .name = "mbox",
- .resource = mbox1_resources,
- .num_resources = ARRAY_SIZE(mbox1_resources),
-};
-
-static struct platform_device mbox2_device = {
- .id = 2,
- .name = "mbox",
- .resource = mbox2_resources,
- .num_resources = ARRAY_SIZE(mbox2_resources),
-};
-
-static struct platform_device *db5500_platform_devs[] __initdata = {
- &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(struct device *parent)
-{
- struct nmk_gpio_platform_data pdata = {
- /* No custom data yet */
- };
-
- dbx500_add_gpios(parent, ARRAY_AND_SIZE(db5500_gpio_base),
- IRQ_DB5500_GPIO0, &pdata);
-}
-
-void __init u5500_map_io(void)
-{
- /*
- * Map the UARTs early so that the DEBUG_LL stuff continues to work.
- */
- iotable_init(u5500_uart_io_desc, ARRAY_SIZE(u5500_uart_io_desc));
-
- ux500_map_io();
-
- iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc));
-
- _PRCMU_BASE = __io_address(U5500_PRCMU_BASE);
-}
-
-static void __init db5500_pmu_init(void)
-{
- struct resource res[] = {
- [0] = {
- .start = IRQ_DB5500_PMU0,
- .end = IRQ_DB5500_PMU0,
- .flags = IORESOURCE_IRQ,
- },
- [1] = {
- .start = IRQ_DB5500_PMU1,
- .end = IRQ_DB5500_PMU1,
- .flags = IORESOURCE_IRQ,
- },
- };
-
- platform_device_register_simple("arm-pmu", ARM_PMU_DEVICE_CPU,
- res, ARRAY_SIZE(res));
-}
-
-static int usb_db5500_rx_dma_cfg[] = {
- DB5500_DMA_DEV4_USB_OTG_IEP_1_9,
- DB5500_DMA_DEV5_USB_OTG_IEP_2_10,
- DB5500_DMA_DEV6_USB_OTG_IEP_3_11,
- DB5500_DMA_DEV20_USB_OTG_IEP_4_12,
- DB5500_DMA_DEV21_USB_OTG_IEP_5_13,
- DB5500_DMA_DEV22_USB_OTG_IEP_6_14,
- DB5500_DMA_DEV23_USB_OTG_IEP_7_15,
- DB5500_DMA_DEV38_USB_OTG_IEP_8
-};
-
-static int usb_db5500_tx_dma_cfg[] = {
- DB5500_DMA_DEV4_USB_OTG_OEP_1_9,
- DB5500_DMA_DEV5_USB_OTG_OEP_2_10,
- DB5500_DMA_DEV6_USB_OTG_OEP_3_11,
- DB5500_DMA_DEV20_USB_OTG_OEP_4_12,
- DB5500_DMA_DEV21_USB_OTG_OEP_5_13,
- DB5500_DMA_DEV22_USB_OTG_OEP_6_14,
- DB5500_DMA_DEV23_USB_OTG_OEP_7_15,
- DB5500_DMA_DEV38_USB_OTG_OEP_8
-};
-
-static const char *db5500_read_soc_id(void)
-{
- return kasprintf(GFP_KERNEL, "u5500 currently unsupported\n");
-}
-
-static struct device * __init db5500_soc_device_init(void)
-{
- const char *soc_id = db5500_read_soc_id();
-
- return ux500_soc_device_init(soc_id);
-}
-
-struct device * __init u5500_init_devices(void)
-{
- struct device *parent;
- int i;
-
- parent = db5500_soc_device_init();
-
- db5500_add_gpios(parent);
- db5500_pmu_init();
- db5500_dma_init(parent);
- db5500_add_rtc(parent);
- db5500_add_usb(parent, usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg);
-
- for (i = 0; i < ARRAY_SIZE(db5500_platform_devs); i++)
- db5500_platform_devs[i]->dev.parent = parent;
-
- platform_add_devices(db5500_platform_devs,
- ARRAY_SIZE(db5500_platform_devs));
-
- return parent;
-}
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 9bd8163896cf..16169c4bf6ca 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -34,8 +34,8 @@ static struct map_desc u8500_uart_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_UART0_BASE, SZ_4K),
__IO_DEV_DESC(U8500_UART2_BASE, SZ_4K),
};
-
-static struct map_desc u8500_io_desc[] __initdata = {
+/* U8500 and U9540 common io_desc */
+static struct map_desc u8500_common_io_desc[] __initdata = {
/* SCU base also covers GIC CPU BASE and TWD with its 4K page */
__IO_DEV_DESC(U8500_SCU_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K),
@@ -49,12 +49,23 @@ static struct map_desc u8500_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K),
__IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K),
- __IO_DEV_DESC(U8500_PRCMU_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),
__IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K),
+};
+
+/* U8500 IO map specific description */
+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),
+
+};
+
+/* U9540 IO map specific description */
+static struct map_desc u9540_io_desc[] __initdata = {
+ __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K + SZ_8K),
+ __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K + SZ_8K),
};
void __init u8500_map_io(void)
@@ -66,7 +77,12 @@ void __init u8500_map_io(void)
ux500_map_io();
- iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc));
+ iotable_init(u8500_common_io_desc, ARRAY_SIZE(u8500_common_io_desc));
+
+ if (cpu_is_u9540())
+ iotable_init(u9540_io_desc, ARRAY_SIZE(u9540_io_desc));
+ else
+ iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc));
_PRCMU_BASE = __io_address(U8500_PRCMU_BASE);
}
@@ -121,6 +137,12 @@ static struct platform_device *platform_devs[] __initdata = {
&db8500_prcmu_device,
};
+static struct platform_device *of_platform_devs[] __initdata = {
+ &u8500_dma40_device,
+ &db8500_pmu_device,
+ &db8500_prcmu_device,
+};
+
static resource_size_t __initdata db8500_gpio_base[] = {
U8500_GPIOBANK0_BASE,
U8500_GPIOBANK1_BASE,
@@ -141,6 +163,7 @@ static void __init db8500_add_gpios(struct device *parent)
dbx500_add_gpios(parent, ARRAY_AND_SIZE(db8500_gpio_base),
IRQ_DB8500_GPIO0, &pdata);
+ dbx500_add_pinctrl(parent, "pinctrl-db8500");
}
static int usb_db8500_rx_dma_cfg[] = {
@@ -199,10 +222,16 @@ struct device * __init u8500_init_devices(void)
platform_device_register_data(parent,
"cpufreq-u8500", -1, NULL, 0);
- for (i = 0; i < ARRAY_SIZE(platform_devs); i++)
- platform_devs[i]->dev.parent = parent;
+ for (i = 0; i < ARRAY_SIZE(of_platform_devs); i++)
+ of_platform_devs[i]->dev.parent = parent;
- platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
+ /*
+ * Devices to be DT:ed:
+ * u8500_dma40_device = todo
+ * db8500_pmu_device = todo
+ * db8500_prcmu_device = todo
+ */
+ platform_add_devices(of_platform_devs, ARRAY_SIZE(of_platform_devs));
return parent;
}
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index d11f3892a27d..a29a0e3adcf9 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -10,7 +10,6 @@
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/mfd/db8500-prcmu.h>
-#include <linux/mfd/db5500-prcmu.h>
#include <linux/clksrc-dbx500-prcmu.h>
#include <linux/sys_soc.h>
#include <linux/err.h>
@@ -30,6 +29,18 @@
void __iomem *_PRCMU_BASE;
+/*
+ * FIXME: Should we set up the GPIO domain here?
+ *
+ * The problem is that we cannot put the interrupt resources into the platform
+ * device until the irqdomain has been added. Right now, we set the GIC interrupt
+ * domain from init_irq(), then load the gpio driver from
+ * core_initcall(nmk_gpio_init) and add the platform devices from
+ * arch_initcall(customize_machine).
+ *
+ * This feels fragile because it depends on the gpio device getting probed
+ * _before_ any device uses the gpio interrupts.
+*/
static const struct of_device_id ux500_dt_irq_match[] = {
{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
{},
@@ -40,10 +51,7 @@ void __init ux500_init_irq(void)
void __iomem *dist_base;
void __iomem *cpu_base;
- if (cpu_is_u5500()) {
- dist_base = __io_address(U5500_GIC_DIST_BASE);
- cpu_base = __io_address(U5500_GIC_CPU_BASE);
- } else if (cpu_is_u8500()) {
+ if (cpu_is_u8500_family()) {
dist_base = __io_address(U8500_GIC_DIST_BASE);
cpu_base = __io_address(U8500_GIC_CPU_BASE);
} else
@@ -60,9 +68,7 @@ void __init ux500_init_irq(void)
* Init clocks here so that they are available for system timer
* initialization.
*/
- if (cpu_is_u5500())
- db5500_prcmu_early_init();
- if (cpu_is_u8500())
+ if (cpu_is_u8500_family())
db8500_prcmu_early_init();
clk_init();
}
diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c
new file mode 100644
index 000000000000..b54884bd2549
--- /dev/null
+++ b/arch/arm/mach-ux500/cpuidle.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2012 Linaro : Daniel Lezcano <daniel.lezcano@linaro.org> (IBM)
+ *
+ * Based on the work of Rickard Andersson <rickard.andersson@stericsson.com>
+ * and Jonas Aaberg <jonas.aberg@stericsson.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/cpuidle.h>
+#include <linux/clockchips.h>
+#include <linux/spinlock.h>
+#include <linux/atomic.h>
+#include <linux/smp.h>
+#include <linux/mfd/dbx500-prcmu.h>
+
+#include <asm/cpuidle.h>
+#include <asm/proc-fns.h>
+
+static atomic_t master = ATOMIC_INIT(0);
+static DEFINE_SPINLOCK(master_lock);
+static DEFINE_PER_CPU(struct cpuidle_device, ux500_cpuidle_device);
+
+static inline int ux500_enter_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ int this_cpu = smp_processor_id();
+ bool recouple = false;
+
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &this_cpu);
+
+ if (atomic_inc_return(&master) == num_online_cpus()) {
+
+ /* With this lock, we prevent the other cpu to exit and enter
+ * this function again and become the master */
+ if (!spin_trylock(&master_lock))
+ goto wfi;
+
+ /* decouple the gic from the A9 cores */
+ if (prcmu_gic_decouple())
+ goto out;
+
+ /* If an error occur, we will have to recouple the gic
+ * manually */
+ recouple = true;
+
+ /* At this state, as the gic is decoupled, if the other
+ * cpu is in WFI, we have the guarantee it won't be wake
+ * up, so we can safely go to retention */
+ if (!prcmu_is_cpu_in_wfi(this_cpu ? 0 : 1))
+ goto out;
+
+ /* The prcmu will be in charge of watching the interrupts
+ * and wake up the cpus */
+ if (prcmu_copy_gic_settings())
+ goto out;
+
+ /* Check in the meantime an interrupt did
+ * not occur on the gic ... */
+ if (prcmu_gic_pending_irq())
+ goto out;
+
+ /* ... and the prcmu */
+ if (prcmu_pending_irq())
+ goto out;
+
+ /* Go to the retention state, the prcmu will wait for the
+ * cpu to go WFI and this is what happens after exiting this
+ * 'master' critical section */
+ if (prcmu_set_power_state(PRCMU_AP_IDLE, true, true))
+ goto out;
+
+ /* When we switch to retention, the prcmu is in charge
+ * of recoupling the gic automatically */
+ recouple = false;
+
+ spin_unlock(&master_lock);
+ }
+wfi:
+ cpu_do_idle();
+out:
+ atomic_dec(&master);
+
+ if (recouple) {
+ prcmu_gic_recouple();
+ spin_unlock(&master_lock);
+ }
+
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &this_cpu);
+
+ return index;
+}
+
+static struct cpuidle_driver ux500_idle_driver = {
+ .name = "ux500_idle",
+ .owner = THIS_MODULE,
+ .en_core_tk_irqen = 1,
+ .states = {
+ ARM_CPUIDLE_WFI_STATE,
+ {
+ .enter = ux500_enter_idle,
+ .exit_latency = 70,
+ .target_residency = 260,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "ApIdle",
+ .desc = "ARM Retention",
+ },
+ },
+ .safe_state_index = 0,
+ .state_count = 2,
+};
+
+/*
+ * For each cpu, setup the broadcast timer because we will
+ * need to migrate the timers for the states >= ApIdle.
+ */
+static void ux500_setup_broadcast_timer(void *arg)
+{
+ int cpu = smp_processor_id();
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
+}
+
+int __init ux500_idle_init(void)
+{
+ int ret, cpu;
+ struct cpuidle_device *device;
+
+ /* Configure wake up reasons */
+ prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
+ PRCMU_WAKEUP(ABB));
+
+ /*
+ * Configure the timer broadcast for each cpu, that must
+ * be done from the cpu context, so we use a smp cross
+ * call with 'on_each_cpu'.
+ */
+ on_each_cpu(ux500_setup_broadcast_timer, NULL, 1);
+
+ ret = cpuidle_register_driver(&ux500_idle_driver);
+ if (ret) {
+ printk(KERN_ERR "failed to register ux500 idle driver\n");
+ return ret;
+ }
+
+ for_each_online_cpu(cpu) {
+ device = &per_cpu(ux500_cpuidle_device, cpu);
+ device->cpu = cpu;
+ ret = cpuidle_register_device(device);
+ if (ret) {
+ printk(KERN_ERR "Failed to register cpuidle "
+ "device for cpu%d\n", cpu);
+ goto out_unregister;
+ }
+ }
+out:
+ return ret;
+
+out_unregister:
+ for_each_online_cpu(cpu) {
+ device = &per_cpu(ux500_cpuidle_device, cpu);
+ cpuidle_unregister_device(device);
+ }
+
+ cpuidle_unregister_driver(&ux500_idle_driver);
+ goto out;
+}
+
+device_initcall(ux500_idle_init);
diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c
index c5312a4b49f5..dfdd4a54668d 100644
--- a/arch/arm/mach-ux500/devices-common.c
+++ b/arch/arm/mach-ux500/devices-common.c
@@ -11,7 +11,6 @@
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
-#include <linux/amba/bus.h>
#include <plat/gpio-nomadik.h>
@@ -19,38 +18,6 @@
#include "devices-common.h"
-struct amba_device *
-dbx500_add_amba_device(struct device *parent, const char *name,
- resource_size_t base, int irq, void *pdata,
- unsigned int periphid)
-{
- struct amba_device *dev;
- int ret;
-
- dev = amba_device_alloc(name, base, SZ_4K);
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- dev->dma_mask = DMA_BIT_MASK(32);
- dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-
- dev->irq[0] = irq;
-
- dev->periphid = periphid;
-
- dev->dev.platform_data = pdata;
-
- dev->dev.parent = parent;
-
- ret = amba_device_add(dev, &iomem_resource);
- if (ret) {
- amba_device_put(dev);
- return ERR_PTR(ret);
- }
-
- return dev;
-}
-
static struct platform_device *
dbx500_add_gpio(struct device *parent, int id, resource_size_t addr, int irq,
struct nmk_gpio_platform_data *pdata)
diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h
index 39c74ec82add..6e4706560266 100644
--- a/arch/arm/mach-ux500/devices-common.h
+++ b/arch/arm/mach-ux500/devices-common.h
@@ -11,12 +11,9 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/sys_soc.h>
+#include <linux/amba/bus.h>
#include <plat/i2c.h>
-
-extern struct amba_device *
-dbx500_add_amba_device(struct device *parent, const char *name,
- resource_size_t base, int irq, void *pdata,
- unsigned int periphid);
+#include <mach/crypto-ux500.h>
struct spi_master_cntlr;
@@ -25,8 +22,8 @@ dbx500_add_msp_spi(struct device *parent, const char *name,
resource_size_t base, int irq,
struct spi_master_cntlr *pdata)
{
- return dbx500_add_amba_device(parent, name, base, irq,
- pdata, 0);
+ return amba_ahb_device_add(parent, name, base, SZ_4K, irq, 0,
+ pdata, 0);
}
static inline struct amba_device *
@@ -34,8 +31,8 @@ dbx500_add_spi(struct device *parent, const char *name, resource_size_t base,
int irq, struct spi_master_cntlr *pdata,
u32 periphid)
{
- return dbx500_add_amba_device(parent, name, base, irq,
- pdata, periphid);
+ return amba_ahb_device_add(parent, name, base, SZ_4K, irq, 0,
+ pdata, periphid);
}
struct mmci_platform_data;
@@ -44,8 +41,8 @@ static inline struct amba_device *
dbx500_add_sdi(struct device *parent, const char *name, resource_size_t base,
int irq, struct mmci_platform_data *pdata, u32 periphid)
{
- return dbx500_add_amba_device(parent, name, base, irq,
- pdata, periphid);
+ return amba_ahb_device_add(parent, name, base, SZ_4K, irq, 0,
+ pdata, periphid);
}
struct amba_pl011_data;
@@ -54,7 +51,7 @@ static inline struct amba_device *
dbx500_add_uart(struct device *parent, const char *name, resource_size_t base,
int irq, struct amba_pl011_data *pdata)
{
- return dbx500_add_amba_device(parent, name, base, irq, pdata, 0);
+ return amba_ahb_device_add(parent, name, base, SZ_4K, irq, 0, pdata, 0);
}
struct nmk_i2c_controller;
@@ -85,7 +82,57 @@ dbx500_add_i2c(struct device *parent, int id, resource_size_t base, int irq,
static inline struct amba_device *
dbx500_add_rtc(struct device *parent, resource_size_t base, int irq)
{
- return dbx500_add_amba_device(parent, "rtc-pl031", base, irq, NULL, 0);
+ return amba_apb_device_add(parent, "rtc-pl031", base, SZ_4K, irq,
+ 0, NULL, 0);
+}
+
+struct cryp_platform_data;
+
+static inline struct platform_device *
+dbx500_add_cryp1(struct device *parent, int id, resource_size_t base, int irq,
+ struct cryp_platform_data *pdata)
+{
+ struct resource res[] = {
+ DEFINE_RES_MEM(base, SZ_4K),
+ DEFINE_RES_IRQ(irq),
+ };
+
+ struct platform_device_info pdevinfo = {
+ .parent = parent,
+ .name = "cryp1",
+ .id = id,
+ .res = res,
+ .num_res = ARRAY_SIZE(res),
+ .data = pdata,
+ .size_data = sizeof(*pdata),
+ .dma_mask = DMA_BIT_MASK(32),
+ };
+
+ return platform_device_register_full(&pdevinfo);
+}
+
+struct hash_platform_data;
+
+static inline struct platform_device *
+dbx500_add_hash1(struct device *parent, int id, resource_size_t base,
+ struct hash_platform_data *pdata)
+{
+ struct resource res[] = {
+ DEFINE_RES_MEM(base, SZ_4K),
+ };
+
+ struct platform_device_info pdevinfo = {
+ .parent = parent,
+ .name = "hash1",
+ .id = id,
+ .res = res,
+ .num_res = ARRAY_SIZE(res),
+ .data = pdata,
+ .size_data = sizeof(*pdata),
+ .dma_mask = DMA_BIT_MASK(32),
+ };
+
+ return platform_device_register_full(&pdevinfo);
}
struct nmk_gpio_platform_data;
@@ -93,4 +140,16 @@ struct nmk_gpio_platform_data;
void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num,
int irq, struct nmk_gpio_platform_data *pdata);
+static inline void
+dbx500_add_pinctrl(struct device *parent, const char *name)
+{
+ struct platform_device_info pdevinfo = {
+ .parent = parent,
+ .name = name,
+ .id = -1,
+ };
+
+ platform_device_register_full(&pdevinfo);
+}
+
#endif
diff --git a/arch/arm/mach-ux500/devices-db5500.h b/arch/arm/mach-ux500/devices-db5500.h
deleted file mode 100644
index e70955502c35..000000000000
--- a/arch/arm/mach-ux500/devices-db5500.h
+++ /dev/null
@@ -1,99 +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.
- */
-
-#ifndef __DEVICES_DB5500_H
-#define __DEVICES_DB5500_H
-
-#include "devices-common.h"
-
-#define db5500_add_i2c1(parent, pdata) \
- dbx500_add_i2c(parent, 1, U5500_I2C1_BASE, IRQ_DB5500_I2C1, pdata)
-#define db5500_add_i2c2(parent, pdata) \
- dbx500_add_i2c(parent, 2, U5500_I2C2_BASE, IRQ_DB5500_I2C2, pdata)
-#define db5500_add_i2c3(parent, pdata) \
- dbx500_add_i2c(parent, 3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata)
-
-#define db5500_add_msp0_spi(parent, pdata) \
- dbx500_add_msp_spi(parent, "msp0", U5500_MSP0_BASE, \
- IRQ_DB5500_MSP0, pdata)
-#define db5500_add_msp1_spi(parent, pdata) \
- dbx500_add_msp_spi(parent, "msp1", U5500_MSP1_BASE, \
- IRQ_DB5500_MSP1, pdata)
-#define db5500_add_msp2_spi(parent, pdata) \
- dbx500_add_msp_spi(parent, "msp2", U5500_MSP2_BASE, \
- IRQ_DB5500_MSP2, pdata)
-
-#define db5500_add_msp0_spi(parent, pdata) \
- dbx500_add_msp_spi(parent, "msp0", U5500_MSP0_BASE, \
- IRQ_DB5500_MSP0, pdata)
-#define db5500_add_msp1_spi(parent, pdata) \
- dbx500_add_msp_spi(parent, "msp1", U5500_MSP1_BASE, \
- IRQ_DB5500_MSP1, pdata)
-#define db5500_add_msp2_spi(parent, pdata) \
- dbx500_add_msp_spi(parent, "msp2", U5500_MSP2_BASE, \
- IRQ_DB5500_MSP2, pdata)
-
-#define db5500_add_rtc(parent) \
- dbx500_add_rtc(parent, U5500_RTC_BASE, IRQ_DB5500_RTC);
-
-#define db5500_add_usb(parent, rx_cfg, tx_cfg) \
- ux500_add_usb(parent, U5500_USBOTG_BASE, \
- IRQ_DB5500_USBOTG, rx_cfg, tx_cfg)
-
-#define db5500_add_sdi0(parent, pdata) \
- dbx500_add_sdi(parent, "sdi0", U5500_SDI0_BASE, \
- IRQ_DB5500_SDMMC0, pdata, \
- 0x10480180)
-#define db5500_add_sdi1(parent, pdata) \
- dbx500_add_sdi(parent, "sdi1", U5500_SDI1_BASE, \
- IRQ_DB5500_SDMMC1, pdata, \
- 0x10480180)
-#define db5500_add_sdi2(parent, pdata) \
- dbx500_add_sdi(parent, "sdi2", U5500_SDI2_BASE, \
- IRQ_DB5500_SDMMC2, pdata \
- 0x10480180)
-#define db5500_add_sdi3(parent, pdata) \
- dbx500_add_sdi(parent, "sdi3", U5500_SDI3_BASE, \
- IRQ_DB5500_SDMMC3, pdata \
- 0x10480180)
-#define db5500_add_sdi4(parent, pdata) \
- dbx500_add_sdi(parent, "sdi4", U5500_SDI4_BASE, \
- IRQ_DB5500_SDMMC4, pdata \
- 0x10480180)
-
-/* This one has a bad peripheral ID in the U5500 silicon */
-#define db5500_add_spi0(parent, pdata) \
- dbx500_add_spi(parent, "spi0", U5500_SPI0_BASE, \
- IRQ_DB5500_SPI0, pdata, \
- 0x10080023)
-#define db5500_add_spi1(parent, pdata) \
- dbx500_add_spi(parent, "spi1", U5500_SPI1_BASE, \
- IRQ_DB5500_SPI1, pdata, \
- 0x10080023)
-#define db5500_add_spi2(parent, pdata) \
- dbx500_add_spi(parent, "spi2", U5500_SPI2_BASE, \
- IRQ_DB5500_SPI2, pdata \
- 0x10080023)
-#define db5500_add_spi3(parent, pdata) \
- dbx500_add_spi(parent, "spi3", U5500_SPI3_BASE, \
- IRQ_DB5500_SPI3, pdata \
- 0x10080023)
-
-#define db5500_add_uart0(parent, plat) \
- dbx500_add_uart(parent, "uart0", U5500_UART0_BASE, \
- IRQ_DB5500_UART0, plat)
-#define db5500_add_uart1(parent, plat) \
- dbx500_add_uart(parent, "uart1", U5500_UART1_BASE, \
- IRQ_DB5500_UART1, plat)
-#define db5500_add_uart2(parent, plat) \
- dbx500_add_uart(parent, "uart2", U5500_UART2_BASE, \
- IRQ_DB5500_UART2, plat)
-#define db5500_add_uart3(parent, plat) \
- dbx500_add_uart(parent, "uart3", U5500_UART3_BASE, \
- IRQ_DB5500_UART3, plat)
-
-#endif
diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c
index 6e66d3777ed5..91754a8a0d49 100644
--- a/arch/arm/mach-ux500/devices-db8500.c
+++ b/arch/arm/mach-ux500/devices-db8500.c
@@ -104,6 +104,8 @@ static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV] = {
[DB8500_DMA_DEV14_MSP2_TX] = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET,
[DB8500_DMA_DEV30_MSP1_TX] = U8500_MSP1_BASE + MSP_TX_RX_REG_OFFSET,
[DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX] = U8500_MSP0_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV48_CAC1_TX] = U8500_CRYP1_BASE + CRYP1_TX_REG_OFFSET,
+ [DB8500_DMA_DEV50_HAC1_TX] = U8500_HASH1_BASE + HASH1_TX_REG_OFFSET,
};
/* Mapping between source event lines and physical device address */
@@ -139,6 +141,7 @@ static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV] = {
[DB8500_DMA_DEV14_MSP2_RX] = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET,
[DB8500_DMA_DEV30_MSP3_RX] = U8500_MSP3_BASE + MSP_TX_RX_REG_OFFSET,
[DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX] = U8500_MSP0_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV48_CAC1_RX] = U8500_CRYP1_BASE + CRYP1_RX_REG_OFFSET,
};
/* Reserved event lines for memcpy only */
diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h
index 9fd93e9da529..3c8010f4fb3f 100644
--- a/arch/arm/mach-ux500/devices-db8500.h
+++ b/arch/arm/mach-ux500/devices-db8500.h
@@ -31,10 +31,9 @@ static inline struct amba_device *
db8500_add_ssp(struct device *parent, const char *name, resource_size_t base,
int irq, struct pl022_ssp_controller *pdata)
{
- return dbx500_add_amba_device(parent, name, base, irq, pdata, 0);
+ return amba_ahb_device_add(parent, name, base, SZ_4K, irq, 0, pdata, 0);
}
-
#define db8500_add_i2c0(parent, pdata) \
dbx500_add_i2c(parent, 0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata)
#define db8500_add_i2c1(parent, pdata) \
@@ -46,15 +45,6 @@ db8500_add_ssp(struct device *parent, const char *name, resource_size_t base,
#define db8500_add_i2c4(parent, pdata) \
dbx500_add_i2c(parent, 4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata)
-#define db8500_add_msp0_i2s(parent, pdata) \
- dbx500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata)
-#define db8500_add_msp1_i2s(parent, pdata) \
- dbx500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata)
-#define db8500_add_msp2_i2s(parent, pdata) \
- dbx500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata)
-#define db8500_add_msp3_i2s(parent, pdata) \
- dbx500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata)
-
#define db8500_add_msp0_spi(parent, pdata) \
dbx500_add_msp_spi(parent, "msp0", U8500_MSP0_BASE, \
IRQ_DB8500_MSP0, pdata)
@@ -124,4 +114,8 @@ db8500_add_ssp(struct device *parent, const char *name, resource_size_t base,
dbx500_add_uart(parent, "uart2", U8500_UART2_BASE, \
IRQ_DB8500_UART2, pdata)
+#define db8500_add_cryp1(parent, pdata) \
+ dbx500_add_cryp1(parent, -1, U8500_CRYP1_BASE, IRQ_DB8500_CRYP1, pdata)
+#define db8500_add_hash1(parent, pdata) \
+ dbx500_add_hash1(parent, -1, U8500_HASH1_BASE, pdata)
#endif
diff --git a/arch/arm/mach-ux500/dma-db5500.c b/arch/arm/mach-ux500/dma-db5500.c
deleted file mode 100644
index 41e9470fa0e6..000000000000
--- a/arch/arm/mach-ux500/dma-db5500.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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,
- [DB5500_DMA_DEV38_USB_OTG_IEP_8] = -1,
- [DB5500_DMA_DEV23_USB_OTG_IEP_7_15] = -1,
- [DB5500_DMA_DEV22_USB_OTG_IEP_6_14] = -1,
- [DB5500_DMA_DEV21_USB_OTG_IEP_5_13] = -1,
- [DB5500_DMA_DEV20_USB_OTG_IEP_4_12] = -1,
- [DB5500_DMA_DEV6_USB_OTG_IEP_3_11] = -1,
- [DB5500_DMA_DEV5_USB_OTG_IEP_2_10] = -1,
- [DB5500_DMA_DEV4_USB_OTG_IEP_1_9] = -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,
- [DB5500_DMA_DEV38_USB_OTG_OEP_8] = -1,
- [DB5500_DMA_DEV23_USB_OTG_OEP_7_15] = -1,
- [DB5500_DMA_DEV22_USB_OTG_OEP_6_14] = -1,
- [DB5500_DMA_DEV21_USB_OTG_OEP_5_13] = -1,
- [DB5500_DMA_DEV20_USB_OTG_OEP_4_12] = -1,
- [DB5500_DMA_DEV6_USB_OTG_OEP_3_11] = -1,
- [DB5500_DMA_DEV5_USB_OTG_OEP_2_10] = -1,
- [DB5500_DMA_DEV4_USB_OTG_OEP_1_9] = -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(struct device *parent)
-{
- int ret;
-
- dma40_device.dev.parent = parent;
- ret = platform_device_register(&dma40_device);
- if (ret)
- dev_err(&dma40_device.dev, "unable to register device: %d\n", ret);
-
-}
diff --git a/arch/arm/mach-ux500/id.c b/arch/arm/mach-ux500/id.c
index 15a0f63b2e2b..d1579920139f 100644
--- a/arch/arm/mach-ux500/id.c
+++ b/arch/arm/mach-ux500/id.c
@@ -23,7 +23,7 @@ static unsigned int ux500_read_asicid(phys_addr_t addr)
{
phys_addr_t base = addr & ~0xfff;
struct map_desc desc = {
- .virtual = IO_ADDRESS(base),
+ .virtual = UX500_VIRT_ROM,
.pfn = __phys_to_pfn(base),
.length = SZ_16K,
.type = MT_DEVICE,
@@ -35,7 +35,7 @@ static unsigned int ux500_read_asicid(phys_addr_t addr)
local_flush_tlb_all();
flush_cache_all();
- return readl(__io_address(addr));
+ return readl(IOMEM(UX500_VIRT_ROM + (addr & 0xfff)));
}
static void ux500_print_soc_info(unsigned int asicid)
@@ -67,6 +67,7 @@ static unsigned int partnumber(unsigned int asicid)
* DB8500v2 0x412fc091 0x9001DBF4 0x008500B0
* DB8520v2.2 0x412fc091 0x9001DBF4 0x008500B2
* DB5500v1 0x412fc091 0x9001FFF4 0x005500A0
+ * DB9540 0x413fc090 0xFFFFDBF4 0x009540xx
*/
void __init ux500_map_io(void)
@@ -91,6 +92,10 @@ void __init ux500_map_io(void)
/* DB5500v1 */
addr = 0x9001FFF4;
break;
+
+ case 0x413fc090: /* DB9540 */
+ addr = 0xFFFFDBF4;
+ break;
}
if (addr)
diff --git a/arch/arm/mach-ux500/include/mach/crypto-ux500.h b/arch/arm/mach-ux500/include/mach/crypto-ux500.h
new file mode 100644
index 000000000000..5b2d0817e26a
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/crypto-ux500.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef _CRYPTO_UX500_H
+#define _CRYPTO_UX500_H
+#include <linux/dmaengine.h>
+#include <plat/ste_dma40.h>
+
+struct hash_platform_data {
+ void *mem_to_engine;
+ bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
+};
+
+struct cryp_platform_data {
+ struct stedma40_chan_cfg mem_to_engine;
+ struct stedma40_chan_cfg engine_to_mem;
+};
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h
deleted file mode 100644
index 8e714bcb099f..000000000000
--- a/arch/arm/mach-ux500/include/mach/db5500-regs.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#ifndef __MACH_DB5500_REGS_H
-#define __MACH_DB5500_REGS_H
-
-#define U5500_PER1_BASE 0xA0020000
-#define U5500_PER2_BASE 0xA0010000
-#define U5500_PER3_BASE 0x80140000
-#define U5500_PER4_BASE 0x80150000
-#define U5500_PER5_BASE 0x80100000
-#define U5500_PER6_BASE 0x80120000
-
-#define U5500_GIC_DIST_BASE 0xA0411000
-#define U5500_GIC_CPU_BASE 0xA0410100
-#define U5500_DMA_BASE 0x90030000
-#define U5500_STM_BASE 0x90020000
-#define U5500_STM_REG_BASE (U5500_STM_BASE + 0xF000)
-#define U5500_MCDE_BASE 0xA0400000
-#define U5500_MODEM_BASE 0xB0000000
-#define U5500_L2CC_BASE 0xA0412000
-#define U5500_SCU_BASE 0xA0410000
-#define U5500_DSI1_BASE 0xA0401000
-#define U5500_DSI2_BASE 0xA0402000
-#define U5500_SIA_BASE 0xA0100000
-#define U5500_SVA_BASE 0x80200000
-#define U5500_HSEM_BASE 0xA0000000
-#define U5500_NAND0_BASE 0x60000000
-#define U5500_NAND1_BASE 0x70000000
-#define U5500_TWD_BASE 0xa0410600
-#define U5500_ICN_BASE 0xA0040000
-#define U5500_B2R2_BASE 0xa0200000
-#define U5500_BOOT_ROM_BASE 0x90000000
-
-#define U5500_FSMC_BASE (U5500_PER1_BASE + 0x0000)
-#define U5500_SDI0_BASE (U5500_PER1_BASE + 0x1000)
-#define U5500_SDI2_BASE (U5500_PER1_BASE + 0x2000)
-#define U5500_UART0_BASE (U5500_PER1_BASE + 0x3000)
-#define U5500_I2C1_BASE (U5500_PER1_BASE + 0x4000)
-#define U5500_MSP0_BASE (U5500_PER1_BASE + 0x5000)
-#define U5500_GPIO0_BASE (U5500_PER1_BASE + 0xE000)
-#define U5500_CLKRST1_BASE (U5500_PER1_BASE + 0xF000)
-
-#define U5500_USBOTG_BASE (U5500_PER2_BASE + 0x0000)
-#define U5500_GPIO1_BASE (U5500_PER2_BASE + 0xE000)
-#define U5500_CLKRST2_BASE (U5500_PER2_BASE + 0xF000)
-
-#define U5500_KEYPAD_BASE (U5500_PER3_BASE + 0x0000)
-#define U5500_PWM_BASE (U5500_PER3_BASE + 0x1000)
-#define U5500_GPIO3_BASE (U5500_PER3_BASE + 0xE000)
-#define U5500_CLKRST3_BASE (U5500_PER3_BASE + 0xF000)
-
-#define U5500_BACKUPRAM0_BASE (U5500_PER4_BASE + 0x0000)
-#define U5500_BACKUPRAM1_BASE (U5500_PER4_BASE + 0x1000)
-#define U5500_RTT0_BASE (U5500_PER4_BASE + 0x2000)
-#define U5500_RTT1_BASE (U5500_PER4_BASE + 0x3000)
-#define U5500_RTC_BASE (U5500_PER4_BASE + 0x4000)
-#define U5500_SCR_BASE (U5500_PER4_BASE + 0x5000)
-#define U5500_DMC_BASE (U5500_PER4_BASE + 0x6000)
-#define U5500_PRCMU_BASE (U5500_PER4_BASE + 0x7000)
-#define U5500_PRCMU_TIMER_3_BASE (U5500_PER4_BASE + 0x07338)
-#define U5500_PRCMU_TIMER_4_BASE (U5500_PER4_BASE + 0x07450)
-#define U5500_MSP1_BASE (U5500_PER4_BASE + 0x9000)
-#define U5500_GPIO2_BASE (U5500_PER4_BASE + 0xA000)
-#define U5500_MTIMER_BASE (U5500_PER4_BASE + 0xC000)
-#define U5500_CDETECT_BASE (U5500_PER4_BASE + 0xF000)
-#define U5500_PRCMU_TCDM_BASE (U5500_PER4_BASE + 0x18000)
-#define U5500_PRCMU_TCPM_BASE (U5500_PER4_BASE + 0x10000)
-#define U5500_TPIU_BASE (U5500_PER4_BASE + 0x50000)
-
-#define U5500_SPI0_BASE (U5500_PER5_BASE + 0x0000)
-#define U5500_SPI1_BASE (U5500_PER5_BASE + 0x1000)
-#define U5500_SPI2_BASE (U5500_PER5_BASE + 0x2000)
-#define U5500_SPI3_BASE (U5500_PER5_BASE + 0x3000)
-#define U5500_UART1_BASE (U5500_PER5_BASE + 0x4000)
-#define U5500_UART2_BASE (U5500_PER5_BASE + 0x5000)
-#define U5500_UART3_BASE (U5500_PER5_BASE + 0x6000)
-#define U5500_SDI1_BASE (U5500_PER5_BASE + 0x7000)
-#define U5500_SDI3_BASE (U5500_PER5_BASE + 0x8000)
-#define U5500_SDI4_BASE (U5500_PER5_BASE + 0x9000)
-#define U5500_I2C2_BASE (U5500_PER5_BASE + 0xA000)
-#define U5500_I2C3_BASE (U5500_PER5_BASE + 0xB000)
-#define U5500_MSP2_BASE (U5500_PER5_BASE + 0xC000)
-#define U5500_IRDA_BASE (U5500_PER5_BASE + 0xD000)
-#define U5500_IRRC_BASE (U5500_PER5_BASE + 0x10000)
-#define U5500_GPIO4_BASE (U5500_PER5_BASE + 0x1E000)
-#define U5500_CLKRST5_BASE (U5500_PER5_BASE + 0x1F000)
-
-#define U5500_RNG_BASE (U5500_PER6_BASE + 0x0000)
-#define U5500_HASH0_BASE (U5500_PER6_BASE + 0x1000)
-#define U5500_HASH1_BASE (U5500_PER6_BASE + 0x2000)
-#define U5500_PKA_BASE (U5500_PER6_BASE + 0x4000)
-#define U5500_PKAM_BASE (U5500_PER6_BASE + 0x5100)
-#define U5500_MTU0_BASE (U5500_PER6_BASE + 0x6000)
-#define U5500_MTU1_BASE (U5500_PER6_BASE + 0x7000)
-#define U5500_CR_BASE (U5500_PER6_BASE + 0x8000)
-#define U5500_CRYP0_BASE (U5500_PER6_BASE + 0xA000)
-#define U5500_CRYP1_BASE (U5500_PER6_BASE + 0xB000)
-#define U5500_CLKRST6_BASE (U5500_PER6_BASE + 0xF000)
-
-#define U5500_GPIOBANK0_BASE U5500_GPIO0_BASE
-#define U5500_GPIOBANK1_BASE (U5500_GPIO0_BASE + 0x80)
-#define U5500_GPIOBANK2_BASE U5500_GPIO1_BASE
-#define U5500_GPIOBANK3_BASE U5500_GPIO2_BASE
-#define U5500_GPIOBANK4_BASE U5500_GPIO3_BASE
-#define U5500_GPIOBANK5_BASE U5500_GPIO4_BASE
-#define U5500_GPIOBANK6_BASE (U5500_GPIO4_BASE + 0x80)
-#define U5500_GPIOBANK7_BASE (U5500_GPIO4_BASE + 0x100)
-
-#define U5500_MBOX_BASE (U5500_MODEM_BASE + 0xFFD1000)
-#define U5500_MBOX0_PEER_START (U5500_MBOX_BASE + 0x40)
-#define U5500_MBOX0_PEER_END (U5500_MBOX_BASE + 0x5F)
-#define U5500_MBOX0_LOCAL_START (U5500_MBOX_BASE + 0x60)
-#define U5500_MBOX0_LOCAL_END (U5500_MBOX_BASE + 0x7F)
-#define U5500_MBOX1_PEER_START (U5500_MBOX_BASE + 0x80)
-#define U5500_MBOX1_PEER_END (U5500_MBOX_BASE + 0x9F)
-#define U5500_MBOX1_LOCAL_START (U5500_MBOX_BASE + 0xA0)
-#define U5500_MBOX1_LOCAL_END (U5500_MBOX_BASE + 0xBF)
-#define U5500_MBOX2_PEER_START (U5500_MBOX_BASE + 0x00)
-#define U5500_MBOX2_PEER_END (U5500_MBOX_BASE + 0x1F)
-#define U5500_MBOX2_LOCAL_START (U5500_MBOX_BASE + 0x20)
-#define U5500_MBOX2_LOCAL_END (U5500_MBOX_BASE + 0x3F)
-
-#define U5500_ACCCON_BASE_SEC (0xBFFF0000)
-#define U5500_ACCCON_BASE (0xBFFF1000)
-#define U5500_ACCCON_CPUVEC_RESET_ADDR_OFFSET (0x00000020)
-#define U5500_ACCCON_ACC_CPU_CTRL_OFFSET (0x000000BC)
-#define U5500_INTCON_MBOX1_INT_RESET_ADDR (0xBFFD31A4)
-
-#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)
-
-#define U5500_MCDE_SIZE 0x1000
-#define U5500_DSI_LINK_SIZE 0x1000
-#define U5500_DSI_LINK_COUNT 0x2
-#define U5500_DSI_LINK1_BASE (U5500_MCDE_BASE + U5500_MCDE_SIZE)
-#define U5500_DSI_LINK2_BASE (U5500_DSI_LINK1_BASE + U5500_DSI_LINK_SIZE)
-
-#endif
diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h
index 9ec20b96d8f2..1530d493879d 100644
--- a/arch/arm/mach-ux500/include/mach/db8500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h
@@ -41,6 +41,10 @@
/* ASIC ID is at 0xbf4 offset within this region */
#define U8500_ASIC_ID_BASE 0x9001D000
+#define U9540_BOOT_ROM_BASE 0xFFFE0000
+/* ASIC ID is at 0xbf4 offset within this region */
+#define U9540_ASIC_ID_BASE 0xFFFFD000
+
#define U8500_PER6_BASE 0xa03c0000
#define U8500_PER7_BASE 0xa03d0000
#define U8500_PER5_BASE 0xa03e0000
@@ -96,7 +100,9 @@
#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 U9540_DMC1_BASE (U8500_PER4_BASE + 0x0A000)
#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000)
+#define U9540_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x6A000)
#define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000)
#define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338)
#define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450)
diff --git a/arch/arm/mach-ux500/include/mach/debug-macro.S b/arch/arm/mach-ux500/include/mach/debug-macro.S
index 8d74d927d4e2..67035223334a 100644
--- a/arch/arm/mach-ux500/include/mach/debug-macro.S
+++ b/arch/arm/mach-ux500/include/mach/debug-macro.S
@@ -20,10 +20,6 @@
* built, so that there's some hint during the build that something is wrong.
*/
-#ifdef CONFIG_UX500_SOC_DB5500
-#define __UX500_UART(n) U5500_UART##n##_BASE
-#endif
-
#ifdef CONFIG_UX500_SOC_DB8500
#define __UX500_UART(n) U8500_UART##n##_BASE
#endif
diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h
index 5f6cb71fc62d..cbc6f1e4104d 100644
--- a/arch/arm/mach-ux500/include/mach/devices.h
+++ b/arch/arm/mach-ux500/include/mach/devices.h
@@ -10,11 +10,13 @@
struct platform_device;
struct amba_device;
-extern struct platform_device u5500_gpio_devs[];
extern struct platform_device u8500_gpio_devs[];
extern struct amba_device ux500_pl031_device;
+extern struct platform_device ux500_hash1_device;
+extern struct platform_device ux500_cryp1_device;
+
extern struct platform_device u8500_dma40_device;
extern struct platform_device ux500_ske_keypad_device;
diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h
index f84698936d36..28d16e744bfd 100644
--- a/arch/arm/mach-ux500/include/mach/hardware.h
+++ b/arch/arm/mach-ux500/include/mach/hardware.h
@@ -17,6 +17,8 @@
*/
#define U8500_IO_VIRTUAL 0xf0000000
#define U8500_IO_PHYSICAL 0xa0000000
+/* This is where we map in the ROM to check ASIC IDs */
+#define UX500_VIRT_ROM 0xf0000000
/* This macro is used in assembly, so no cast */
#define IO_ADDRESS(x) \
@@ -24,13 +26,16 @@
/* typesafe io address */
#define __io_address(n) IOMEM(IO_ADDRESS(n))
+
/* Used by some plat-nomadik code */
#define io_p2v(n) __io_address(n)
#include <mach/db8500-regs.h>
-#include <mach/db5500-regs.h>
#define MSP_TX_RX_REG_OFFSET 0
+#define CRYP1_RX_REG_OFFSET 0x10
+#define CRYP1_TX_REG_OFFSET 0x8
+#define HASH1_TX_REG_OFFSET 0x4
#ifndef __ASSEMBLY__
diff --git a/arch/arm/mach-ux500/include/mach/id.h b/arch/arm/mach-ux500/include/mach/id.h
index 833d6a6edc9b..c6e2db9e9e51 100644
--- a/arch/arm/mach-ux500/include/mach/id.h
+++ b/arch/arm/mach-ux500/include/mach/id.h
@@ -41,6 +41,16 @@ static inline bool __attribute_const__ cpu_is_u8500(void)
return dbx500_partnumber() == 0x8500;
}
+static inline bool __attribute_const__ cpu_is_u9540(void)
+{
+ return dbx500_partnumber() == 0x9540;
+}
+
+static inline bool cpu_is_u8500_family(void)
+{
+ return cpu_is_u8500() || cpu_is_u9540();
+}
+
static inline bool __attribute_const__ cpu_is_u5500(void)
{
return dbx500_partnumber() == 0x5500;
@@ -111,7 +121,12 @@ static inline bool cpu_is_u8500v21(void)
static inline bool cpu_is_u8500v20_or_later(void)
{
- return cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11();
+ /*
+ * U9540 has so much in common with U8500 that is is considered a
+ * U8500 variant.
+ */
+ return cpu_is_u9540() ||
+ (cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11());
}
static inline bool ux500_is_svp(void)
diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h b/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h
deleted file mode 100644
index 29d972c7717b..000000000000
--- a/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#ifndef __MACH_IRQS_BOARD_U5500_H
-#define __MACH_IRQS_BOARD_U5500_H
-
-#define AB5500_NR_IRQS 5
-#define IRQ_AB5500_BASE IRQ_BOARD_START
-#define IRQ_AB5500_END (IRQ_AB5500_BASE + AB5500_NR_IRQS)
-
-#define U5500_IRQ_END IRQ_AB5500_END
-
-#if IRQ_BOARD_END < U5500_IRQ_END
-#undef IRQ_BOARD_END
-#define IRQ_BOARD_END U5500_IRQ_END
-#endif
-
-#endif
diff --git a/arch/arm/mach-ux500/include/mach/irqs-db5500.h b/arch/arm/mach-ux500/include/mach/irqs-db5500.h
deleted file mode 100644
index 77239776a6f2..000000000000
--- a/arch/arm/mach-ux500/include/mach/irqs-db5500.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Rabin Vincent <rabin.vincent@stericsson.com>
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#ifndef __MACH_IRQS_DB5500_H
-#define __MACH_IRQS_DB5500_H
-
-#define IRQ_DB5500_MTU0 (IRQ_SHPI_START + 4)
-#define IRQ_DB5500_SPI2 (IRQ_SHPI_START + 6)
-#define IRQ_DB5500_PMU0 (IRQ_SHPI_START + 7)
-#define IRQ_DB5500_SPI0 (IRQ_SHPI_START + 8)
-#define IRQ_DB5500_RTT (IRQ_SHPI_START + 9)
-#define IRQ_DB5500_PKA (IRQ_SHPI_START + 10)
-#define IRQ_DB5500_UART0 (IRQ_SHPI_START + 11)
-#define IRQ_DB5500_I2C3 (IRQ_SHPI_START + 12)
-#define IRQ_DB5500_L2CC (IRQ_SHPI_START + 13)
-#define IRQ_DB5500_MSP0 (IRQ_SHPI_START + 14)
-#define IRQ_DB5500_CRYP1 (IRQ_SHPI_START + 15)
-#define IRQ_DB5500_PMU1 (IRQ_SHPI_START + 16)
-#define IRQ_DB5500_MTU1 (IRQ_SHPI_START + 17)
-#define IRQ_DB5500_RTC (IRQ_SHPI_START + 18)
-#define IRQ_DB5500_UART1 (IRQ_SHPI_START + 19)
-#define IRQ_DB5500_USB_WAKEUP (IRQ_SHPI_START + 20)
-#define IRQ_DB5500_I2C0 (IRQ_SHPI_START + 21)
-#define IRQ_DB5500_I2C1 (IRQ_SHPI_START + 22)
-#define IRQ_DB5500_USBOTG (IRQ_SHPI_START + 23)
-#define IRQ_DB5500_DMA_SECURE (IRQ_SHPI_START + 24)
-#define IRQ_DB5500_DMA (IRQ_SHPI_START + 25)
-#define IRQ_DB5500_UART2 (IRQ_SHPI_START + 26)
-#define IRQ_DB5500_ICN_PMU1 (IRQ_SHPI_START + 27)
-#define IRQ_DB5500_ICN_PMU2 (IRQ_SHPI_START + 28)
-#define IRQ_DB5500_UART3 (IRQ_SHPI_START + 29)
-#define IRQ_DB5500_SPI3 (IRQ_SHPI_START + 30)
-#define IRQ_DB5500_SDMMC4 (IRQ_SHPI_START + 31)
-#define IRQ_DB5500_IRRC (IRQ_SHPI_START + 33)
-#define IRQ_DB5500_IRDA_FT (IRQ_SHPI_START + 34)
-#define IRQ_DB5500_IRDA_SD (IRQ_SHPI_START + 35)
-#define IRQ_DB5500_IRDA_FI (IRQ_SHPI_START + 36)
-#define IRQ_DB5500_IRDA_FD (IRQ_SHPI_START + 37)
-#define IRQ_DB5500_FSMC_CODEREADY (IRQ_SHPI_START + 38)
-#define IRQ_DB5500_FSMC_NANDWAIT (IRQ_SHPI_START + 39)
-#define IRQ_DB5500_AB5500 (IRQ_SHPI_START + 40)
-#define IRQ_DB5500_SDMMC2 (IRQ_SHPI_START + 41)
-#define IRQ_DB5500_SIA (IRQ_SHPI_START + 42)
-#define IRQ_DB5500_SIA2 (IRQ_SHPI_START + 43)
-#define IRQ_DB5500_HVA (IRQ_SHPI_START + 44)
-#define IRQ_DB5500_HVA2 (IRQ_SHPI_START + 45)
-#define IRQ_DB5500_PRCMU0 (IRQ_SHPI_START + 46)
-#define IRQ_DB5500_PRCMU1 (IRQ_SHPI_START + 47)
-#define IRQ_DB5500_DISP (IRQ_SHPI_START + 48)
-#define IRQ_DB5500_SDMMC1 (IRQ_SHPI_START + 50)
-#define IRQ_DB5500_MSP1 (IRQ_SHPI_START + 52)
-#define IRQ_DB5500_KBD (IRQ_SHPI_START + 53)
-#define IRQ_DB5500_I2C2 (IRQ_SHPI_START + 55)
-#define IRQ_DB5500_B2R2 (IRQ_SHPI_START + 56)
-#define IRQ_DB5500_CRYP0 (IRQ_SHPI_START + 57)
-#define IRQ_DB5500_SDMMC3 (IRQ_SHPI_START + 59)
-#define IRQ_DB5500_SDMMC0 (IRQ_SHPI_START + 60)
-#define IRQ_DB5500_HSEM (IRQ_SHPI_START + 61)
-#define IRQ_DB5500_SBAG (IRQ_SHPI_START + 63)
-#define IRQ_DB5500_MODEM (IRQ_SHPI_START + 65)
-#define IRQ_DB5500_SPI1 (IRQ_SHPI_START + 96)
-#define IRQ_DB5500_MSP2 (IRQ_SHPI_START + 98)
-#define IRQ_DB5500_SRPTIMER (IRQ_SHPI_START + 101)
-#define IRQ_DB5500_CTI0 (IRQ_SHPI_START + 108)
-#define IRQ_DB5500_CTI1 (IRQ_SHPI_START + 109)
-#define IRQ_DB5500_ICN_ERR (IRQ_SHPI_START + 110)
-#define IRQ_DB5500_MALI_PPMMU (IRQ_SHPI_START + 112)
-#define IRQ_DB5500_MALI_PP (IRQ_SHPI_START + 113)
-#define IRQ_DB5500_MALI_GPMMU (IRQ_SHPI_START + 114)
-#define IRQ_DB5500_MALI_GP (IRQ_SHPI_START + 115)
-#define IRQ_DB5500_MALI (IRQ_SHPI_START + 116)
-#define IRQ_DB5500_PRCMU_SEM (IRQ_SHPI_START + 118)
-#define IRQ_DB5500_GPIO0 (IRQ_SHPI_START + 119)
-#define IRQ_DB5500_GPIO1 (IRQ_SHPI_START + 120)
-#define IRQ_DB5500_GPIO2 (IRQ_SHPI_START + 121)
-#define IRQ_DB5500_GPIO3 (IRQ_SHPI_START + 122)
-#define IRQ_DB5500_GPIO4 (IRQ_SHPI_START + 123)
-#define IRQ_DB5500_GPIO5 (IRQ_SHPI_START + 124)
-#define IRQ_DB5500_GPIO6 (IRQ_SHPI_START + 125)
-#define IRQ_DB5500_GPIO7 (IRQ_SHPI_START + 126)
-
-#ifdef CONFIG_UX500_SOC_DB5500
-
-/*
- * After the GPIO ones we reserve a range of IRQ:s in which virtual
- * IRQ:s representing modem IRQ:s can be allocated
- */
-#define IRQ_MODEM_EVENTS_BASE IRQ_SOC_START
-#define IRQ_MODEM_EVENTS_NBR 72
-#define IRQ_MODEM_EVENTS_END (IRQ_MODEM_EVENTS_BASE + IRQ_MODEM_EVENTS_NBR)
-
-/* List of virtual IRQ:s that are allocated from the range above */
-#define MBOX_PAIR0_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 43)
-#define MBOX_PAIR1_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 45)
-#define MBOX_PAIR2_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 41)
-
-/*
- * We may have several SoCs, but only one will run at a
- * time, so the one with most IRQs will bump this ahead,
- * but the IRQ_SOC_START remains the same for either SoC.
- */
-#if IRQ_SOC_END < IRQ_MODEM_EVENTS_END
-#undef IRQ_SOC_END
-#define IRQ_SOC_END IRQ_MODEM_EVENTS_END
-#endif
-
-#endif /* CONFIG_UX500_SOC_DB5500 */
-
-#endif
diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h
index c23a6b5f0c4e..e8928548b6a3 100644
--- a/arch/arm/mach-ux500/include/mach/irqs.h
+++ b/arch/arm/mach-ux500/include/mach/irqs.h
@@ -24,7 +24,7 @@
*/
#define IRQ_MTU0 (IRQ_SHPI_START + 4)
-#define DBX500_NR_INTERNAL_IRQS 160
+#define DBX500_NR_INTERNAL_IRQS 166
/* After chip-specific IRQ numbers we have the GPIO ones */
#define NOMADIK_NR_GPIO 288
@@ -36,7 +36,6 @@
/* This will be overridden by SoC-specific irq headers */
#define IRQ_SOC_END IRQ_SOC_START
-#include <mach/irqs-db5500.h>
#include <mach/irqs-db8500.h>
#define IRQ_BOARD_START IRQ_SOC_END
@@ -47,10 +46,6 @@
#include <mach/irqs-board-mop500.h>
#endif
-#ifdef CONFIG_MACH_U5500
-#include <mach/irqs-board-u5500.h>
-#endif
-
#define NR_IRQS IRQ_BOARD_END
#endif /* ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-ux500/include/mach/mbox-db5500.h b/arch/arm/mach-ux500/include/mach/mbox-db5500.h
deleted file mode 100644
index 7f9da4d2fbda..000000000000
--- a/arch/arm/mach-ux500/include/mach/mbox-db5500.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
- * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
- * License terms: GNU General Public License (GPL), version 2.
- */
-
-#ifndef __INC_STE_MBOX_H
-#define __INC_STE_MBOX_H
-
-#define MBOX_BUF_SIZE 16
-#define MBOX_NAME_SIZE 8
-
-/**
- * mbox_recv_cb_t - Definition of the mailbox callback.
- * @mbox_msg: The mailbox message.
- * @priv: The clients private data as specified in the call to mbox_setup.
- *
- * This function will be called upon reception of new mailbox messages.
- */
-typedef void mbox_recv_cb_t (u32 mbox_msg, void *priv);
-
-/**
- * struct mbox - Mailbox instance struct
- * @list: Linked list head.
- * @pdev: Pointer to device struct.
- * @cb: Callback function. Will be called
- * when new data is received.
- * @client_data: Clients private data. Will be sent back
- * in the callback function.
- * @virtbase_peer: Virtual address for outgoing mailbox.
- * @virtbase_local: Virtual address for incoming mailbox.
- * @buffer: Then internal queue for outgoing messages.
- * @name: Name of this mailbox.
- * @buffer_available: Completion variable to achieve "blocking send".
- * This variable will be signaled when there is
- * internal buffer space available.
- * @client_blocked: To keep track if any client is currently
- * blocked.
- * @lock: Spinlock to protect this mailbox instance.
- * @write_index: Index in internal buffer to write to.
- * @read_index: Index in internal buffer to read from.
- * @allocated: Indicates whether this particular mailbox
- * id has been allocated by someone.
- */
-struct mbox {
- struct list_head list;
- struct platform_device *pdev;
- mbox_recv_cb_t *cb;
- void *client_data;
- void __iomem *virtbase_peer;
- void __iomem *virtbase_local;
- u32 buffer[MBOX_BUF_SIZE];
- char name[MBOX_NAME_SIZE];
- struct completion buffer_available;
- u8 client_blocked;
- spinlock_t lock;
- u8 write_index;
- u8 read_index;
- bool allocated;
-};
-
-/**
- * mbox_setup - Set up a mailbox and return its instance.
- * @mbox_id: The ID number of the mailbox. 0 or 1 for modem CPU,
- * 2 for modem DSP.
- * @mbox_cb: Pointer to the callback function to be called when a new message
- * is received.
- * @priv: Client user data which will be returned in the callback.
- *
- * Returns a mailbox instance to be specified in subsequent calls to mbox_send.
- */
-struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv);
-
-/**
- * mbox_send - Send a mailbox message.
- * @mbox: Mailbox instance (returned by mbox_setup)
- * @mbox_msg: The mailbox message to send.
- * @block: Specifies whether this call will block until send is possible,
- * or return an error if the mailbox buffer is full.
- *
- * Returns 0 on success or a negative error code on error. -ENOMEM indicates
- * that the internal buffer is full and you have to try again later (or
- * specify "block" in order to block until send is possible).
- */
-int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block);
-
-#endif /*INC_STE_MBOX_H*/
diff --git a/arch/arm/mach-ux500/include/mach/msp.h b/arch/arm/mach-ux500/include/mach/msp.h
new file mode 100644
index 000000000000..798be19129ef
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/msp.h
@@ -0,0 +1,29 @@
+/*
+ * 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 __MSP_H
+#define __MSP_H
+
+#include <plat/ste_dma40.h>
+
+enum msp_i2s_id {
+ MSP_I2S_0 = 0,
+ MSP_I2S_1,
+ MSP_I2S_2,
+ MSP_I2S_3,
+};
+
+/* Platform data structure for a MSP I2S-device */
+struct msp_i2s_platform_data {
+ enum msp_i2s_id id;
+ struct stedma40_chan_cfg *msp_i2s_dma_rx;
+ struct stedma40_chan_cfg *msp_i2s_dma_tx;
+ int (*msp_i2s_init) (void);
+ int (*msp_i2s_exit) (void);
+};
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h
index 3dc00ffa7bfa..4e369f1645ec 100644
--- a/arch/arm/mach-ux500/include/mach/setup.h
+++ b/arch/arm/mach-ux500/include/mach/setup.h
@@ -15,18 +15,12 @@
#include <linux/init.h>
void __init ux500_map_io(void);
-extern void __init u5500_map_io(void);
extern void __init u8500_map_io(void);
-extern struct device * __init u5500_init_devices(void);
extern struct device * __init u8500_init_devices(void);
extern void __init ux500_init_irq(void);
-extern void __init u5500_sdi_init(struct device *parent);
-
-extern void __init db5500_dma_init(struct device *parent);
-
extern struct device *ux500_soc_device_init(const char *soc_id);
struct amba_device;
diff --git a/arch/arm/mach-ux500/include/mach/uncompress.h b/arch/arm/mach-ux500/include/mach/uncompress.h
index 6fb3c4b0105d..34775baadaea 100644
--- a/arch/arm/mach-ux500/include/mach/uncompress.h
+++ b/arch/arm/mach-ux500/include/mach/uncompress.h
@@ -50,11 +50,8 @@ static void flush(void)
static inline void arch_decomp_setup(void)
{
- /* Check in run time if we run on an U8500 or U5500 */
- if (machine_is_u5500())
- ux500_uart_base = U5500_UART0_BASE;
- else
- ux500_uart_base = U8500_UART2_BASE;
+ /* Use machine_is_foo() macro if you need to switch base someday */
+ ux500_uart_base = U8500_UART2_BASE;
}
#define arch_decomp_wdog() /* nothing to do here */
diff --git a/arch/arm/mach-ux500/mbox-db5500.c b/arch/arm/mach-ux500/mbox-db5500.c
deleted file mode 100644
index 0127490218cd..000000000000
--- a/arch/arm/mach-ux500/mbox-db5500.c
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
- * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
- * License terms: GNU General Public License (GPL), version 2.
- */
-
-/*
- * Mailbox nomenclature:
- *
- * APE MODEM
- * mbox pairX
- * ..........................
- * . .
- * . peer .
- * . send ---- .
- * . --> | | .
- * . | | .
- * . ---- .
- * . .
- * . local .
- * . rec ---- .
- * . | | <-- .
- * . | | .
- * . ---- .
- * .........................
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/completion.h>
-#include <mach/mbox-db5500.h>
-
-#define MBOX_NAME "mbox"
-
-#define MBOX_FIFO_DATA 0x000
-#define MBOX_FIFO_ADD 0x004
-#define MBOX_FIFO_REMOVE 0x008
-#define MBOX_FIFO_THRES_FREE 0x00C
-#define MBOX_FIFO_THRES_OCCUP 0x010
-#define MBOX_FIFO_STATUS 0x014
-
-#define MBOX_DISABLE_IRQ 0x4
-#define MBOX_ENABLE_IRQ 0x0
-#define MBOX_LATCH 1
-
-/* Global list of all mailboxes */
-static struct list_head mboxs = LIST_HEAD_INIT(mboxs);
-
-static struct mbox *get_mbox_with_id(u8 id)
-{
- u8 i;
- struct list_head *pos = &mboxs;
- for (i = 0; i <= id; i++)
- pos = pos->next;
-
- return (struct mbox *) list_entry(pos, struct mbox, list);
-}
-
-int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block)
-{
- int res = 0;
-
- spin_lock(&mbox->lock);
-
- dev_dbg(&(mbox->pdev->dev),
- "About to buffer 0x%X to mailbox 0x%X."
- " ri = %d, wi = %d\n",
- mbox_msg, (u32)mbox, mbox->read_index,
- mbox->write_index);
-
- /* Check if write buffer is full */
- while (((mbox->write_index + 1) % MBOX_BUF_SIZE) == mbox->read_index) {
- if (!block) {
- dev_dbg(&(mbox->pdev->dev),
- "Buffer full in non-blocking call! "
- "Returning -ENOMEM!\n");
- res = -ENOMEM;
- goto exit;
- }
- spin_unlock(&mbox->lock);
- dev_dbg(&(mbox->pdev->dev),
- "Buffer full in blocking call! Sleeping...\n");
- mbox->client_blocked = 1;
- wait_for_completion(&mbox->buffer_available);
- dev_dbg(&(mbox->pdev->dev),
- "Blocking send was woken up! Trying again...\n");
- spin_lock(&mbox->lock);
- }
-
- mbox->buffer[mbox->write_index] = mbox_msg;
- mbox->write_index = (mbox->write_index + 1) % MBOX_BUF_SIZE;
-
- /*
- * Indicate that we want an IRQ as soon as there is a slot
- * in the FIFO
- */
- writel(MBOX_ENABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
-
-exit:
- spin_unlock(&mbox->lock);
- return res;
-}
-EXPORT_SYMBOL(mbox_send);
-
-#if defined(CONFIG_DEBUG_FS)
-/*
- * Expected input: <value> <nbr sends>
- * Example: "echo 0xdeadbeef 4 > mbox-node" sends 0xdeadbeef 4 times
- */
-static ssize_t mbox_write_fifo(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- unsigned long mbox_mess;
- unsigned long nbr_sends;
- unsigned long i;
- char int_buf[16];
- char *token;
- char *val;
-
- struct mbox *mbox = (struct mbox *) dev->platform_data;
-
- strncpy((char *) &int_buf, buf, sizeof(int_buf));
- token = (char *) &int_buf;
-
- /* Parse message */
- val = strsep(&token, " ");
- if ((val == NULL) || (strict_strtoul(val, 16, &mbox_mess) != 0))
- mbox_mess = 0xDEADBEEF;
-
- val = strsep(&token, " ");
- if ((val == NULL) || (strict_strtoul(val, 10, &nbr_sends) != 0))
- nbr_sends = 1;
-
- dev_dbg(dev, "Will write 0x%lX %ld times using data struct at 0x%X\n",
- mbox_mess, nbr_sends, (u32) mbox);
-
- for (i = 0; i < nbr_sends; i++)
- mbox_send(mbox, mbox_mess, true);
-
- return count;
-}
-
-static ssize_t mbox_read_fifo(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int mbox_value;
- struct mbox *mbox = (struct mbox *) dev->platform_data;
-
- if ((readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7) <= 0)
- return sprintf(buf, "Mailbox is empty\n");
-
- mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
- writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
-
- return sprintf(buf, "0x%X\n", mbox_value);
-}
-
-static DEVICE_ATTR(fifo, S_IWUSR | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
-
-static int mbox_show(struct seq_file *s, void *data)
-{
- struct list_head *pos;
- u8 mbox_index = 0;
-
- list_for_each(pos, &mboxs) {
- struct mbox *m =
- (struct mbox *) list_entry(pos, struct mbox, list);
- if (m == NULL) {
- seq_printf(s,
- "Unable to retrieve mailbox %d\n",
- mbox_index);
- continue;
- }
-
- spin_lock(&m->lock);
- if ((m->virtbase_peer == NULL) || (m->virtbase_local == NULL)) {
- seq_printf(s, "MAILBOX %d not setup or corrupt\n",
- mbox_index);
- spin_unlock(&m->lock);
- continue;
- }
-
- seq_printf(s,
- "===========================\n"
- " MAILBOX %d\n"
- " PEER MAILBOX DUMP\n"
- "---------------------------\n"
- "FIFO: 0x%X (%d)\n"
- "Free Threshold: 0x%.2X (%d)\n"
- "Occupied Threshold: 0x%.2X (%d)\n"
- "Status: 0x%.2X (%d)\n"
- " Free spaces (ot): %d (%d)\n"
- " Occup spaces (ot): %d (%d)\n"
- "===========================\n"
- " LOCAL MAILBOX DUMP\n"
- "---------------------------\n"
- "FIFO: 0x%.X (%d)\n"
- "Free Threshold: 0x%.2X (%d)\n"
- "Occupied Threshold: 0x%.2X (%d)\n"
- "Status: 0x%.2X (%d)\n"
- " Free spaces (ot): %d (%d)\n"
- " Occup spaces (ot): %d (%d)\n"
- "===========================\n"
- "write_index: %d\n"
- "read_index : %d\n"
- "===========================\n"
- "\n",
- mbox_index,
- readl(m->virtbase_peer + MBOX_FIFO_DATA),
- readl(m->virtbase_peer + MBOX_FIFO_DATA),
- readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
- readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
- readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
- readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
- readl(m->virtbase_peer + MBOX_FIFO_STATUS),
- readl(m->virtbase_peer + MBOX_FIFO_STATUS),
- (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 4) & 0x7,
- (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 7) & 0x1,
- (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 0) & 0x7,
- (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 3) & 0x1,
- readl(m->virtbase_local + MBOX_FIFO_DATA),
- readl(m->virtbase_local + MBOX_FIFO_DATA),
- readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
- readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
- readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
- readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
- readl(m->virtbase_local + MBOX_FIFO_STATUS),
- readl(m->virtbase_local + MBOX_FIFO_STATUS),
- (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 4) & 0x7,
- (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 7) & 0x1,
- (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 0) & 0x7,
- (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 3) & 0x1,
- m->write_index, m->read_index);
- mbox_index++;
- spin_unlock(&m->lock);
- }
-
- return 0;
-}
-
-static int mbox_open(struct inode *inode, struct file *file)
-{
- return single_open(file, mbox_show, NULL);
-}
-
-static const struct file_operations mbox_operations = {
- .owner = THIS_MODULE,
- .open = mbox_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-#endif
-
-static irqreturn_t mbox_irq(int irq, void *arg)
-{
- u32 mbox_value;
- int nbr_occup;
- int nbr_free;
- struct mbox *mbox = (struct mbox *) arg;
-
- spin_lock(&mbox->lock);
-
- dev_dbg(&(mbox->pdev->dev),
- "mbox IRQ [%d] received. ri = %d, wi = %d\n",
- irq, mbox->read_index, mbox->write_index);
-
- /*
- * Check if we have any outgoing messages, and if there is space for
- * them in the FIFO.
- */
- if (mbox->read_index != mbox->write_index) {
- /*
- * Check by reading FREE for LOCAL since that indicates
- * OCCUP for PEER
- */
- nbr_free = (readl(mbox->virtbase_local + MBOX_FIFO_STATUS)
- >> 4) & 0x7;
- dev_dbg(&(mbox->pdev->dev),
- "Status indicates %d empty spaces in the FIFO!\n",
- nbr_free);
-
- while ((nbr_free > 0) &&
- (mbox->read_index != mbox->write_index)) {
- /* Write the message and latch it into the FIFO */
- writel(mbox->buffer[mbox->read_index],
- (mbox->virtbase_peer + MBOX_FIFO_DATA));
- writel(MBOX_LATCH,
- (mbox->virtbase_peer + MBOX_FIFO_ADD));
- dev_dbg(&(mbox->pdev->dev),
- "Wrote message 0x%X to addr 0x%X\n",
- mbox->buffer[mbox->read_index],
- (u32) (mbox->virtbase_peer + MBOX_FIFO_DATA));
-
- nbr_free--;
- mbox->read_index =
- (mbox->read_index + 1) % MBOX_BUF_SIZE;
- }
-
- /*
- * Check if we still want IRQ:s when there is free
- * space to send
- */
- if (mbox->read_index != mbox->write_index) {
- dev_dbg(&(mbox->pdev->dev),
- "Still have messages to send, but FIFO full. "
- "Request IRQ again!\n");
- writel(MBOX_ENABLE_IRQ,
- mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
- } else {
- dev_dbg(&(mbox->pdev->dev),
- "No more messages to send. "
- "Do not request IRQ again!\n");
- writel(MBOX_DISABLE_IRQ,
- mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
- }
-
- /*
- * Check if we can signal any blocked clients that it is OK to
- * start buffering again
- */
- if (mbox->client_blocked &&
- (((mbox->write_index + 1) % MBOX_BUF_SIZE)
- != mbox->read_index)) {
- dev_dbg(&(mbox->pdev->dev),
- "Waking up blocked client\n");
- complete(&mbox->buffer_available);
- mbox->client_blocked = 0;
- }
- }
-
- /* Check if we have any incoming messages */
- nbr_occup = readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7;
- if (nbr_occup == 0)
- goto exit;
-
- if (mbox->cb == NULL) {
- dev_dbg(&(mbox->pdev->dev), "No receive callback registered, "
- "leaving %d incoming messages in fifo!\n", nbr_occup);
- goto exit;
- }
-
- /* Read and acknowledge the message */
- mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
- writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
-
- /* Notify consumer of new mailbox message */
- dev_dbg(&(mbox->pdev->dev), "Calling callback for message 0x%X!\n",
- mbox_value);
- mbox->cb(mbox_value, mbox->client_data);
-
-exit:
- dev_dbg(&(mbox->pdev->dev), "Exit mbox IRQ. ri = %d, wi = %d\n",
- mbox->read_index, mbox->write_index);
- spin_unlock(&mbox->lock);
-
- return IRQ_HANDLED;
-}
-
-/* Setup is executed once for each mbox pair */
-struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv)
-{
- struct resource *resource;
- int irq;
- int res;
- struct mbox *mbox;
-
- mbox = get_mbox_with_id(mbox_id);
- if (mbox == NULL) {
- dev_err(&(mbox->pdev->dev), "Incorrect mailbox id: %d!\n",
- mbox_id);
- goto exit;
- }
-
- /*
- * Check if mailbox has been allocated to someone else,
- * otherwise allocate it
- */
- if (mbox->allocated) {
- dev_err(&(mbox->pdev->dev), "Mailbox number %d is busy!\n",
- mbox_id);
- mbox = NULL;
- goto exit;
- }
- mbox->allocated = true;
-
- dev_dbg(&(mbox->pdev->dev), "Initiating mailbox number %d: 0x%X...\n",
- mbox_id, (u32)mbox);
-
- mbox->client_data = priv;
- mbox->cb = mbox_cb;
-
- /* Get addr for peer mailbox and ioremap it */
- resource = platform_get_resource_byname(mbox->pdev,
- IORESOURCE_MEM,
- "mbox_peer");
- if (resource == NULL) {
- dev_err(&(mbox->pdev->dev),
- "Unable to retrieve mbox peer resource\n");
- mbox = NULL;
- goto exit;
- }
- dev_dbg(&(mbox->pdev->dev),
- "Resource name: %s start: 0x%X, end: 0x%X\n",
- resource->name, resource->start, resource->end);
- mbox->virtbase_peer = ioremap(resource->start, resource_size(resource));
- if (!mbox->virtbase_peer) {
- dev_err(&(mbox->pdev->dev), "Unable to ioremap peer mbox\n");
- mbox = NULL;
- goto exit;
- }
- dev_dbg(&(mbox->pdev->dev),
- "ioremapped peer physical: (0x%X-0x%X) to virtual: 0x%X\n",
- resource->start, resource->end, (u32) mbox->virtbase_peer);
-
- /* Get addr for local mailbox and ioremap it */
- resource = platform_get_resource_byname(mbox->pdev,
- IORESOURCE_MEM,
- "mbox_local");
- if (resource == NULL) {
- dev_err(&(mbox->pdev->dev),
- "Unable to retrieve mbox local resource\n");
- mbox = NULL;
- goto exit;
- }
- dev_dbg(&(mbox->pdev->dev),
- "Resource name: %s start: 0x%X, end: 0x%X\n",
- resource->name, resource->start, resource->end);
- mbox->virtbase_local = ioremap(resource->start, resource_size(resource));
- if (!mbox->virtbase_local) {
- dev_err(&(mbox->pdev->dev), "Unable to ioremap local mbox\n");
- mbox = NULL;
- goto exit;
- }
- dev_dbg(&(mbox->pdev->dev),
- "ioremapped local physical: (0x%X-0x%X) to virtual: 0x%X\n",
- resource->start, resource->end, (u32) mbox->virtbase_peer);
-
- init_completion(&mbox->buffer_available);
- mbox->client_blocked = 0;
-
- /* Get IRQ for mailbox and allocate it */
- irq = platform_get_irq_byname(mbox->pdev, "mbox_irq");
- if (irq < 0) {
- dev_err(&(mbox->pdev->dev),
- "Unable to retrieve mbox irq resource\n");
- mbox = NULL;
- goto exit;
- }
-
- dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", irq);
- res = request_irq(irq, mbox_irq, 0, mbox->name, (void *) mbox);
- if (res < 0) {
- dev_err(&(mbox->pdev->dev),
- "Unable to allocate mbox irq %d\n", irq);
- mbox = NULL;
- goto exit;
- }
-
- /* Set up mailbox to not launch IRQ on free space in mailbox */
- writel(MBOX_DISABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
-
- /*
- * Set up mailbox to launch IRQ on new message if we have
- * a callback set. If not, do not raise IRQ, but keep message
- * in FIFO for manual retrieval
- */
- if (mbox_cb != NULL)
- writel(MBOX_ENABLE_IRQ,
- mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
- else
- writel(MBOX_DISABLE_IRQ,
- mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
-
-#if defined(CONFIG_DEBUG_FS)
- res = device_create_file(&(mbox->pdev->dev), &dev_attr_fifo);
- if (res != 0)
- dev_warn(&(mbox->pdev->dev),
- "Unable to create mbox sysfs entry");
-
- (void) debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL,
- NULL, &mbox_operations);
-#endif
-
- dev_info(&(mbox->pdev->dev),
- "Mailbox driver with index %d initiated!\n", mbox_id);
-
-exit:
- return mbox;
-}
-EXPORT_SYMBOL(mbox_setup);
-
-
-int __init mbox_probe(struct platform_device *pdev)
-{
- struct mbox local_mbox;
- struct mbox *mbox;
- int res = 0;
- dev_dbg(&(pdev->dev), "Probing mailbox (pdev = 0x%X)...\n", (u32) pdev);
-
- memset(&local_mbox, 0x0, sizeof(struct mbox));
-
- /* Associate our mbox data with the platform device */
- res = platform_device_add_data(pdev,
- (void *) &local_mbox,
- sizeof(struct mbox));
- if (res != 0) {
- dev_err(&(pdev->dev),
- "Unable to allocate driver platform data!\n");
- goto exit;
- }
-
- mbox = (struct mbox *) pdev->dev.platform_data;
- mbox->pdev = pdev;
- mbox->write_index = 0;
- mbox->read_index = 0;
-
- INIT_LIST_HEAD(&(mbox->list));
- list_add_tail(&(mbox->list), &mboxs);
-
- sprintf(mbox->name, "%s", MBOX_NAME);
- spin_lock_init(&mbox->lock);
-
- dev_info(&(pdev->dev), "Mailbox driver loaded\n");
-
-exit:
- return res;
-}
-
-static struct platform_driver mbox_driver = {
- .driver = {
- .name = MBOX_NAME,
- .owner = THIS_MODULE,
- },
-};
-
-static int __init mbox_init(void)
-{
- return platform_driver_probe(&mbox_driver, mbox_probe);
-}
-
-module_init(mbox_init);
-
-void __exit mbox_exit(void)
-{
- platform_driver_unregister(&mbox_driver);
-}
-
-module_exit(mbox_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("MBOX driver");
diff --git a/arch/arm/mach-ux500/modem-irq-db5500.c b/arch/arm/mach-ux500/modem-irq-db5500.c
deleted file mode 100644
index 6b86416c94c9..000000000000
--- a/arch/arm/mach-ux500/modem-irq-db5500.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
- * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
- * License terms: GNU General Public License (GPL), version 2.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <mach/id.h>
-
-#define MODEM_INTCON_BASE_ADDR 0xBFFD3000
-#define MODEM_INTCON_SIZE 0xFFF
-
-#define DEST_IRQ41_OFFSET 0x2A4
-#define DEST_IRQ43_OFFSET 0x2AC
-#define DEST_IRQ45_OFFSET 0x2B4
-
-#define PRIO_IRQ41_OFFSET 0x6A4
-#define PRIO_IRQ43_OFFSET 0x6AC
-#define PRIO_IRQ45_OFFSET 0x6B4
-
-#define ALLOW_IRQ_OFFSET 0x104
-
-#define MODEM_INTCON_CPU_NBR 0x1
-#define MODEM_INTCON_PRIO_HIGH 0x0
-
-#define MODEM_INTCON_ALLOW_IRQ41 0x0200
-#define MODEM_INTCON_ALLOW_IRQ43 0x0800
-#define MODEM_INTCON_ALLOW_IRQ45 0x2000
-
-#define MODEM_IRQ_REG_OFFSET 0x4
-
-struct modem_irq {
- void __iomem *modem_intcon_base;
-};
-
-
-static void setup_modem_intcon(void __iomem *modem_intcon_base)
-{
- /* IC_DESTINATION_BASE_ARRAY - Which CPU to receive the IRQ */
- writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ41_OFFSET);
- writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ43_OFFSET);
- writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ45_OFFSET);
-
- /* IC_PRIORITY_BASE_ARRAY - IRQ priority in modem IRQ controller */
- writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ41_OFFSET);
- writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ43_OFFSET);
- writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ45_OFFSET);
-
- /* IC_ALLOW_ARRAY - IRQ enable */
- writel(MODEM_INTCON_ALLOW_IRQ41 |
- MODEM_INTCON_ALLOW_IRQ43 |
- MODEM_INTCON_ALLOW_IRQ45,
- modem_intcon_base + ALLOW_IRQ_OFFSET);
-}
-
-static irqreturn_t modem_cpu_irq_handler(int irq, void *data)
-{
- int real_irq;
- int virt_irq;
- struct modem_irq *mi = (struct modem_irq *)data;
-
- /* Read modem side IRQ number from modem IRQ controller */
- real_irq = readl(mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET) & 0xFF;
- virt_irq = IRQ_MODEM_EVENTS_BASE + real_irq;
-
- pr_debug("modem_irq: Worker read addr 0x%X and got value 0x%X "
- "which will be 0x%X (%d) which translates to "
- "virtual IRQ 0x%X (%d)!\n",
- (u32)mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET,
- real_irq,
- real_irq & 0xFF,
- real_irq & 0xFF,
- virt_irq,
- virt_irq);
-
- if (virt_irq != 0)
- generic_handle_irq(virt_irq);
-
- pr_debug("modem_irq: Done handling virtual IRQ %d!\n", virt_irq);
-
- return IRQ_HANDLED;
-}
-
-static void create_virtual_irq(int irq, struct irq_chip *modem_irq_chip)
-{
- irq_set_chip_and_handler(irq, modem_irq_chip, handle_simple_irq);
- set_irq_flags(irq, IRQF_VALID);
-
- pr_debug("modem_irq: Created virtual IRQ %d\n", irq);
-}
-
-static int modem_irq_init(void)
-{
- int err;
- static struct irq_chip modem_irq_chip;
- struct modem_irq *mi;
-
- if (!cpu_is_u5500())
- return -ENODEV;
-
- pr_info("modem_irq: Set up IRQ handler for incoming modem IRQ %d\n",
- IRQ_DB5500_MODEM);
-
- mi = kmalloc(sizeof(struct modem_irq), GFP_KERNEL);
- if (!mi) {
- pr_err("modem_irq: Could not allocate device\n");
- return -ENOMEM;
- }
-
- mi->modem_intcon_base =
- ioremap(MODEM_INTCON_BASE_ADDR, MODEM_INTCON_SIZE);
- pr_debug("modem_irq: ioremapped modem_intcon_base from "
- "phy 0x%x to virt 0x%x\n", MODEM_INTCON_BASE_ADDR,
- (u32)mi->modem_intcon_base);
-
- setup_modem_intcon(mi->modem_intcon_base);
-
- modem_irq_chip = dummy_irq_chip;
- modem_irq_chip.name = "modem_irq";
-
- /* Create the virtual IRQ:s needed */
- create_virtual_irq(MBOX_PAIR0_VIRT_IRQ, &modem_irq_chip);
- create_virtual_irq(MBOX_PAIR1_VIRT_IRQ, &modem_irq_chip);
- create_virtual_irq(MBOX_PAIR2_VIRT_IRQ, &modem_irq_chip);
-
- err = request_threaded_irq(IRQ_DB5500_MODEM, NULL,
- modem_cpu_irq_handler, IRQF_ONESHOT,
- "modem_irq", mi);
- if (err)
- pr_err("modem_irq: Could not register IRQ %d\n",
- IRQ_DB5500_MODEM);
-
- return 0;
-}
-
-arch_initcall(modem_irq_init);
diff --git a/arch/arm/mach-ux500/pins-db5500.h b/arch/arm/mach-ux500/pins-db5500.h
deleted file mode 100644
index bf50c21fe69d..000000000000
--- a/arch/arm/mach-ux500/pins-db5500.h
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License terms: GNU General Public License, version 2
- * Author: Rabin Vincent <rabin.vincent@stericsson.com>
- */
-
-#ifndef __MACH_DB5500_PINS_H
-#define __MACH_DB5500_PINS_H
-
-#define GPIO0_GPIO PIN_CFG(0, GPIO)
-#define GPIO0_SM_CS3n PIN_CFG(0, ALT_A)
-
-#define GPIO1_GPIO PIN_CFG(1, GPIO)
-#define GPIO1_SM_A3 PIN_CFG(1, ALT_A)
-
-#define GPIO2_GPIO PIN_CFG(2, GPIO)
-#define GPIO2_SM_A4 PIN_CFG(2, ALT_A)
-#define GPIO2_SM_AVD PIN_CFG(2, ALT_B)
-
-#define GPIO3_GPIO PIN_CFG(3, GPIO)
-#define GPIO3_I2C1_SCL PIN_CFG(3, ALT_A)
-
-#define GPIO4_GPIO PIN_CFG(4, GPIO)
-#define GPIO4_I2C1_SDA PIN_CFG(4, ALT_A)
-
-#define GPIO5_GPIO PIN_CFG(5, GPIO)
-#define GPIO5_MC0_DAT0 PIN_CFG(5, ALT_A)
-#define GPIO5_SM_ADQ8 PIN_CFG(5, ALT_B)
-
-#define GPIO6_GPIO PIN_CFG(6, GPIO)
-#define GPIO6_MC0_DAT1 PIN_CFG(6, ALT_A)
-#define GPIO6_SM_ADQ0 PIN_CFG(6, ALT_B)
-
-#define GPIO7_GPIO PIN_CFG(7, GPIO)
-#define GPIO7_MC0_DAT2 PIN_CFG(7, ALT_A)
-#define GPIO7_SM_ADQ9 PIN_CFG(7, ALT_B)
-
-#define GPIO8_GPIO PIN_CFG(8, GPIO)
-#define GPIO8_MC0_DAT3 PIN_CFG(8, ALT_A)
-#define GPIO8_SM_ADQ1 PIN_CFG(8, ALT_B)
-
-#define GPIO9_GPIO PIN_CFG(9, GPIO)
-#define GPIO9_MC0_DAT4 PIN_CFG(9, ALT_A)
-#define GPIO9_SM_ADQ10 PIN_CFG(9, ALT_B)
-
-#define GPIO10_GPIO PIN_CFG(10, GPIO)
-#define GPIO10_MC0_DAT5 PIN_CFG(10, ALT_A)
-#define GPIO10_SM_ADQ2 PIN_CFG(10, ALT_B)
-
-#define GPIO11_GPIO PIN_CFG(11, GPIO)
-#define GPIO11_MC0_DAT6 PIN_CFG(11, ALT_A)
-#define GPIO11_SM_ADQ11 PIN_CFG(11, ALT_B)
-
-#define GPIO12_GPIO PIN_CFG(12, GPIO)
-#define GPIO12_MC0_DAT7 PIN_CFG(12, ALT_A)
-#define GPIO12_SM_ADQ3 PIN_CFG(12, ALT_B)
-
-#define GPIO13_GPIO PIN_CFG(13, GPIO)
-#define GPIO13_MC0_CMD PIN_CFG(13, ALT_A)
-#define GPIO13_SM_BUSY0n PIN_CFG(13, ALT_B)
-#define GPIO13_SM_WAIT0n PIN_CFG(13, ALT_C)
-
-#define GPIO14_GPIO PIN_CFG(14, GPIO)
-#define GPIO14_MC0_CLK PIN_CFG(14, ALT_A)
-#define GPIO14_SM_CS1n PIN_CFG(14, ALT_B)
-#define GPIO14_SM_CKO PIN_CFG(14, ALT_C)
-
-#define GPIO15_GPIO PIN_CFG(15, GPIO)
-#define GPIO15_SM_A5 PIN_CFG(15, ALT_A)
-#define GPIO15_SM_CLE PIN_CFG(15, ALT_B)
-
-#define GPIO16_GPIO PIN_CFG(16, GPIO)
-#define GPIO16_MC2_CMD PIN_CFG(16, ALT_A)
-#define GPIO16_SM_OEn PIN_CFG(16, ALT_B)
-
-#define GPIO17_GPIO PIN_CFG(17, GPIO)
-#define GPIO17_MC2_CLK PIN_CFG(17, ALT_A)
-#define GPIO17_SM_WEn PIN_CFG(17, ALT_B)
-
-#define GPIO18_GPIO PIN_CFG(18, GPIO)
-#define GPIO18_SM_A6 PIN_CFG(18, ALT_A)
-#define GPIO18_SM_ALE PIN_CFG(18, ALT_B)
-#define GPIO18_SM_AVDn PIN_CFG(18, ALT_C)
-
-#define GPIO19_GPIO PIN_CFG(19, GPIO)
-#define GPIO19_MC2_DAT1 PIN_CFG(19, ALT_A)
-#define GPIO19_SM_ADQ4 PIN_CFG(19, ALT_B)
-
-#define GPIO20_GPIO PIN_CFG(20, GPIO)
-#define GPIO20_MC2_DAT3 PIN_CFG(20, ALT_A)
-#define GPIO20_SM_ADQ5 PIN_CFG(20, ALT_B)
-
-#define GPIO21_GPIO PIN_CFG(21, GPIO)
-#define GPIO21_MC2_DAT5 PIN_CFG(21, ALT_A)
-#define GPIO21_SM_ADQ6 PIN_CFG(21, ALT_B)
-
-#define GPIO22_GPIO PIN_CFG(22, GPIO)
-#define GPIO22_MC2_DAT7 PIN_CFG(22, ALT_A)
-#define GPIO22_SM_ADQ7 PIN_CFG(22, ALT_B)
-
-#define GPIO23_GPIO PIN_CFG(23, GPIO)
-#define GPIO23_MC2_DAT0 PIN_CFG(23, ALT_A)
-#define GPIO23_SM_ADQ12 PIN_CFG(23, ALT_B)
-#define GPIO23_MC0_DAT1 PIN_CFG(23, ALT_C)
-
-#define GPIO24_GPIO PIN_CFG(24, GPIO)
-#define GPIO24_MC2_DAT2 PIN_CFG(24, ALT_A)
-#define GPIO24_SM_ADQ13 PIN_CFG(24, ALT_B)
-#define GPIO24_MC0_DAT3 PIN_CFG(24, ALT_C)
-
-#define GPIO25_GPIO PIN_CFG(25, GPIO)
-#define GPIO25_MC2_DAT4 PIN_CFG(25, ALT_A)
-#define GPIO25_SM_ADQ14 PIN_CFG(25, ALT_B)
-#define GPIO25_MC0_CMD PIN_CFG(25, ALT_C)
-
-#define GPIO26_GPIO PIN_CFG(26, GPIO)
-#define GPIO26_MC2_DAT6 PIN_CFG(26, ALT_A)
-#define GPIO26_SM_ADQ15 PIN_CFG(26, ALT_B)
-
-#define GPIO27_GPIO PIN_CFG(27, GPIO)
-#define GPIO27_SM_CS0n PIN_CFG(27, ALT_A)
-#define GPIO27_SM_PS0n PIN_CFG(27, ALT_B)
-
-#define GPIO28_GPIO PIN_CFG(28, GPIO)
-#define GPIO28_U0_TXD PIN_CFG(28, ALT_A)
-#define GPIO28_SM_A0 PIN_CFG(28, ALT_B)
-
-#define GPIO29_GPIO PIN_CFG(29, GPIO)
-#define GPIO29_U0_RXD PIN_CFG(29, ALT_A)
-#define GPIO29_SM_A1 PIN_CFG(29, ALT_B)
-#define GPIO29_PWM_0 PIN_CFG(29, ALT_C)
-
-#define GPIO30_GPIO PIN_CFG(30, GPIO)
-#define GPIO30_MC0_DAT5 PIN_CFG(30, ALT_A)
-#define GPIO30_SM_A2 PIN_CFG(30, ALT_B)
-#define GPIO30_PWM_1 PIN_CFG(30, ALT_C)
-
-#define GPIO31_GPIO PIN_CFG(31, GPIO)
-#define GPIO31_MC0_DAT7 PIN_CFG(31, ALT_A)
-#define GPIO31_SM_CS2n PIN_CFG(31, ALT_B)
-#define GPIO31_PWM_2 PIN_CFG(31, ALT_C)
-
-#define GPIO32_GPIO PIN_CFG(32, GPIO)
-#define GPIO32_MSP0_TCK PIN_CFG(32, ALT_A)
-#define GPIO32_ACCI2S0_SCK PIN_CFG(32, ALT_B)
-
-#define GPIO33_GPIO PIN_CFG(33, GPIO)
-#define GPIO33_MSP0_TFS PIN_CFG(33, ALT_A)
-#define GPIO33_ACCI2S0_WS PIN_CFG(33, ALT_B)
-
-#define GPIO34_GPIO PIN_CFG(34, GPIO)
-#define GPIO34_MSP0_TXD PIN_CFG(34, ALT_A)
-#define GPIO34_ACCI2S0_DLD PIN_CFG(34, ALT_B)
-
-#define GPIO35_GPIO PIN_CFG(35, GPIO)
-#define GPIO35_MSP0_RXD PIN_CFG(35, ALT_A)
-#define GPIO35_ACCI2S0_ULD PIN_CFG(35, ALT_B)
-
-#define GPIO64_GPIO PIN_CFG(64, GPIO)
-#define GPIO64_USB_DAT0 PIN_CFG(64, ALT_A)
-#define GPIO64_U0_TXD PIN_CFG(64, ALT_B)
-
-#define GPIO65_GPIO PIN_CFG(65, GPIO)
-#define GPIO65_USB_DAT1 PIN_CFG(65, ALT_A)
-#define GPIO65_U0_RXD PIN_CFG(65, ALT_B)
-
-#define GPIO66_GPIO PIN_CFG(66, GPIO)
-#define GPIO66_USB_DAT2 PIN_CFG(66, ALT_A)
-
-#define GPIO67_GPIO PIN_CFG(67, GPIO)
-#define GPIO67_USB_DAT3 PIN_CFG(67, ALT_A)
-
-#define GPIO68_GPIO PIN_CFG(68, GPIO)
-#define GPIO68_USB_DAT4 PIN_CFG(68, ALT_A)
-
-#define GPIO69_GPIO PIN_CFG(69, GPIO)
-#define GPIO69_USB_DAT5 PIN_CFG(69, ALT_A)
-
-#define GPIO70_GPIO PIN_CFG(70, GPIO)
-#define GPIO70_USB_DAT6 PIN_CFG(70, ALT_A)
-
-#define GPIO71_GPIO PIN_CFG(71, GPIO)
-#define GPIO71_USB_DAT7 PIN_CFG(71, ALT_A)
-
-#define GPIO72_GPIO PIN_CFG(72, GPIO)
-#define GPIO72_USB_STP PIN_CFG(72, ALT_A)
-
-#define GPIO73_GPIO PIN_CFG(73, GPIO)
-#define GPIO73_USB_DIR PIN_CFG(73, ALT_A)
-
-#define GPIO74_GPIO PIN_CFG(74, GPIO)
-#define GPIO74_USB_NXT PIN_CFG(74, ALT_A)
-
-#define GPIO75_GPIO PIN_CFG(75, GPIO)
-#define GPIO75_USB_XCLK PIN_CFG(75, ALT_A)
-
-#define GPIO76_GPIO PIN_CFG(76, GPIO)
-
-#define GPIO77_GPIO PIN_CFG(77, GPIO)
-#define GPIO77_ACCTX_ON PIN_CFG(77, ALT_A)
-
-#define GPIO78_GPIO PIN_CFG(78, GPIO)
-#define GPIO78_IRQn PIN_CFG(78, ALT_A)
-
-#define GPIO79_GPIO PIN_CFG(79, GPIO)
-#define GPIO79_ACCSIM_Clk PIN_CFG(79, ALT_A)
-
-#define GPIO80_GPIO PIN_CFG(80, GPIO)
-#define GPIO80_ACCSIM_Da PIN_CFG(80, ALT_A)
-
-#define GPIO81_GPIO PIN_CFG(81, GPIO)
-#define GPIO81_ACCSIM_Reset PIN_CFG(81, ALT_A)
-
-#define GPIO82_GPIO PIN_CFG(82, GPIO)
-#define GPIO82_ACCSIM_DDir PIN_CFG(82, ALT_A)
-
-#define GPIO96_GPIO PIN_CFG(96, GPIO)
-#define GPIO96_MSP1_TCK PIN_CFG(96, ALT_A)
-#define GPIO96_PRCMU_DEBUG3 PIN_CFG(96, ALT_B)
-#define GPIO96_PRCMU_DEBUG7 PIN_CFG(96, ALT_C)
-
-#define GPIO97_GPIO PIN_CFG(97, GPIO)
-#define GPIO97_MSP1_TFS PIN_CFG(97, ALT_A)
-#define GPIO97_PRCMU_DEBUG2 PIN_CFG(97, ALT_B)
-#define GPIO97_PRCMU_DEBUG6 PIN_CFG(97, ALT_C)
-
-#define GPIO98_GPIO PIN_CFG(98, GPIO)
-#define GPIO98_MSP1_TXD PIN_CFG(98, ALT_A)
-#define GPIO98_PRCMU_DEBUG1 PIN_CFG(98, ALT_B)
-#define GPIO98_PRCMU_DEBUG5 PIN_CFG(98, ALT_C)
-
-#define GPIO99_GPIO PIN_CFG(99, GPIO)
-#define GPIO99_MSP1_RXD PIN_CFG(99, ALT_A)
-#define GPIO99_PRCMU_DEBUG0 PIN_CFG(99, ALT_B)
-#define GPIO99_PRCMU_DEBUG4 PIN_CFG(99, ALT_C)
-
-#define GPIO100_GPIO PIN_CFG(100, GPIO)
-#define GPIO100_I2C0_SCL PIN_CFG(100, ALT_A)
-
-#define GPIO101_GPIO PIN_CFG(101, GPIO)
-#define GPIO101_I2C0_SDA PIN_CFG(101, ALT_A)
-
-#define GPIO128_GPIO PIN_CFG(128, GPIO)
-#define GPIO128_KP_I0 PIN_CFG(128, ALT_A)
-#define GPIO128_BUSMON_D0 PIN_CFG(128, ALT_B)
-
-#define GPIO129_GPIO PIN_CFG(129, GPIO)
-#define GPIO129_KP_O0 PIN_CFG(129, ALT_A)
-#define GPIO129_BUSMON_D1 PIN_CFG(129, ALT_B)
-
-#define GPIO130_GPIO PIN_CFG(130, GPIO)
-#define GPIO130_KP_I1 PIN_CFG(130, ALT_A)
-#define GPIO130_BUSMON_D2 PIN_CFG(130, ALT_B)
-
-#define GPIO131_GPIO PIN_CFG(131, GPIO)
-#define GPIO131_KP_O1 PIN_CFG(131, ALT_A)
-#define GPIO131_BUSMON_D3 PIN_CFG(131, ALT_B)
-
-#define GPIO132_GPIO PIN_CFG(132, GPIO)
-#define GPIO132_KP_I2 PIN_CFG(132, ALT_A)
-#define GPIO132_ETM_D15 PIN_CFG(132, ALT_B)
-#define GPIO132_STMAPE_CLK PIN_CFG(132, ALT_C)
-
-#define GPIO133_GPIO PIN_CFG(133, GPIO)
-#define GPIO133_KP_O2 PIN_CFG(133, ALT_A)
-#define GPIO133_ETM_D14 PIN_CFG(133, ALT_B)
-#define GPIO133_U0_RXD PIN_CFG(133, ALT_C)
-
-#define GPIO134_GPIO PIN_CFG(134, GPIO)
-#define GPIO134_KP_I3 PIN_CFG(134, ALT_A)
-#define GPIO134_ETM_D13 PIN_CFG(134, ALT_B)
-#define GPIO134_STMAPE_DAT0 PIN_CFG(134, ALT_C)
-
-#define GPIO135_GPIO PIN_CFG(135, GPIO)
-#define GPIO135_KP_O3 PIN_CFG(135, ALT_A)
-#define GPIO135_ETM_D12 PIN_CFG(135, ALT_B)
-#define GPIO135_STMAPE_DAT1 PIN_CFG(135, ALT_C)
-
-#define GPIO136_GPIO PIN_CFG(136, GPIO)
-#define GPIO136_KP_I4 PIN_CFG(136, ALT_A)
-#define GPIO136_ETM_D11 PIN_CFG(136, ALT_B)
-#define GPIO136_STMAPE_DAT2 PIN_CFG(136, ALT_C)
-
-#define GPIO137_GPIO PIN_CFG(137, GPIO)
-#define GPIO137_KP_O4 PIN_CFG(137, ALT_A)
-#define GPIO137_ETM_D10 PIN_CFG(137, ALT_B)
-#define GPIO137_STMAPE_DAT3 PIN_CFG(137, ALT_C)
-
-#define GPIO138_GPIO PIN_CFG(138, GPIO)
-#define GPIO138_KP_I5 PIN_CFG(138, ALT_A)
-#define GPIO138_ETM_D9 PIN_CFG(138, ALT_B)
-#define GPIO138_U0_TXD PIN_CFG(138, ALT_C)
-
-#define GPIO139_GPIO PIN_CFG(139, GPIO)
-#define GPIO139_KP_O5 PIN_CFG(139, ALT_A)
-#define GPIO139_ETM_D8 PIN_CFG(139, ALT_B)
-#define GPIO139_BUSMON_D11 PIN_CFG(139, ALT_C)
-
-#define GPIO140_GPIO PIN_CFG(140, GPIO)
-#define GPIO140_KP_I6 PIN_CFG(140, ALT_A)
-#define GPIO140_ETM_D7 PIN_CFG(140, ALT_B)
-#define GPIO140_STMAPE_CLK PIN_CFG(140, ALT_C)
-
-#define GPIO141_GPIO PIN_CFG(141, GPIO)
-#define GPIO141_KP_O6 PIN_CFG(141, ALT_A)
-#define GPIO141_ETM_D6 PIN_CFG(141, ALT_B)
-#define GPIO141_U0_RXD PIN_CFG(141, ALT_C)
-
-#define GPIO142_GPIO PIN_CFG(142, GPIO)
-#define GPIO142_KP_I7 PIN_CFG(142, ALT_A)
-#define GPIO142_ETM_D5 PIN_CFG(142, ALT_B)
-#define GPIO142_STMAPE_DAT0 PIN_CFG(142, ALT_C)
-
-#define GPIO143_GPIO PIN_CFG(143, GPIO)
-#define GPIO143_KP_O7 PIN_CFG(143, ALT_A)
-#define GPIO143_ETM_D4 PIN_CFG(143, ALT_B)
-#define GPIO143_STMAPE_DAT1 PIN_CFG(143, ALT_C)
-
-#define GPIO144_GPIO PIN_CFG(144, GPIO)
-#define GPIO144_I2C3_SCL PIN_CFG(144, ALT_A)
-#define GPIO144_ETM_D3 PIN_CFG(144, ALT_B)
-#define GPIO144_STMAPE_DAT2 PIN_CFG(144, ALT_C)
-
-#define GPIO145_GPIO PIN_CFG(145, GPIO)
-#define GPIO145_I2C3_SDA PIN_CFG(145, ALT_A)
-#define GPIO145_ETM_D2 PIN_CFG(145, ALT_B)
-#define GPIO145_STMAPE_DAT3 PIN_CFG(145, ALT_C)
-
-#define GPIO146_GPIO PIN_CFG(146, GPIO)
-#define GPIO146_PWM_0 PIN_CFG(146, ALT_A)
-#define GPIO146_ETM_D1 PIN_CFG(146, ALT_B)
-
-#define GPIO147_GPIO PIN_CFG(147, GPIO)
-#define GPIO147_PWM_1 PIN_CFG(147, ALT_A)
-#define GPIO147_ETM_D0 PIN_CFG(147, ALT_B)
-
-#define GPIO148_GPIO PIN_CFG(148, GPIO)
-#define GPIO148_PWM_2 PIN_CFG(148, ALT_A)
-#define GPIO148_ETM_CLK PIN_CFG(148, ALT_B)
-
-#define GPIO160_GPIO PIN_CFG(160, GPIO)
-#define GPIO160_CLKOUT_REQn PIN_CFG(160, ALT_A)
-
-#define GPIO161_GPIO PIN_CFG(161, GPIO)
-#define GPIO161_CLKOUT_0 PIN_CFG(161, ALT_A)
-
-#define GPIO162_GPIO PIN_CFG(162, GPIO)
-#define GPIO162_CLKOUT_1 PIN_CFG(162, ALT_A)
-
-#define GPIO163_GPIO PIN_CFG(163, GPIO)
-
-#define GPIO164_GPIO PIN_CFG(164, GPIO)
-#define GPIO164_GPS_START PIN_CFG(164, ALT_A)
-
-#define GPIO165_GPIO PIN_CFG(165, GPIO)
-#define GPIO165_SPI1_CS2n PIN_CFG(165, ALT_A)
-#define GPIO165_U3_RXD PIN_CFG(165, ALT_B)
-#define GPIO165_BUSMON_D20 PIN_CFG(165, ALT_C)
-
-#define GPIO166_GPIO PIN_CFG(166, GPIO)
-#define GPIO166_SPI1_CS1n PIN_CFG(166, ALT_A)
-#define GPIO166_U3_TXD PIN_CFG(166, ALT_B)
-#define GPIO166_BUSMON_D21 PIN_CFG(166, ALT_C)
-
-#define GPIO167_GPIO PIN_CFG(167, GPIO)
-#define GPIO167_SPI1_CS0n PIN_CFG(167, ALT_A)
-#define GPIO167_U3_RTSn PIN_CFG(167, ALT_B)
-#define GPIO167_BUSMON_D22 PIN_CFG(167, ALT_C)
-
-#define GPIO168_GPIO PIN_CFG(168, GPIO)
-#define GPIO168_SPI1_RXD PIN_CFG(168, ALT_A)
-#define GPIO168_U3_CTSn PIN_CFG(168, ALT_B)
-#define GPIO168_BUSMON_D23 PIN_CFG(168, ALT_C)
-
-#define GPIO169_GPIO PIN_CFG(169, GPIO)
-#define GPIO169_SPI1_TXD PIN_CFG(169, ALT_A)
-#define GPIO169_DDR_RC PIN_CFG(169, ALT_B)
-#define GPIO169_BUSMON_D24 PIN_CFG(169, ALT_C)
-
-#define GPIO170_GPIO PIN_CFG(170, GPIO)
-#define GPIO170_SPI1_CLK PIN_CFG(170, ALT_A)
-
-#define GPIO171_GPIO PIN_CFG(171, GPIO)
-#define GPIO171_MC3_DAT0 PIN_CFG(171, ALT_A)
-#define GPIO171_SPI3_RXD PIN_CFG(171, ALT_B)
-#define GPIO171_BUSMON_D25 PIN_CFG(171, ALT_C)
-
-#define GPIO172_GPIO PIN_CFG(172, GPIO)
-#define GPIO172_MC3_DAT1 PIN_CFG(172, ALT_A)
-#define GPIO172_SPI3_CS1n PIN_CFG(172, ALT_B)
-#define GPIO172_BUSMON_D26 PIN_CFG(172, ALT_C)
-
-#define GPIO173_GPIO PIN_CFG(173, GPIO)
-#define GPIO173_MC3_DAT2 PIN_CFG(173, ALT_A)
-#define GPIO173_SPI3_CS2n PIN_CFG(173, ALT_B)
-#define GPIO173_BUSMON_D27 PIN_CFG(173, ALT_C)
-
-#define GPIO174_GPIO PIN_CFG(174, GPIO)
-#define GPIO174_MC3_DAT3 PIN_CFG(174, ALT_A)
-#define GPIO174_SPI3_CS0n PIN_CFG(174, ALT_B)
-#define GPIO174_BUSMON_D28 PIN_CFG(174, ALT_C)
-
-#define GPIO175_GPIO PIN_CFG(175, GPIO)
-#define GPIO175_MC3_CMD PIN_CFG(175, ALT_A)
-#define GPIO175_SPI3_TXD PIN_CFG(175, ALT_B)
-#define GPIO175_BUSMON_D29 PIN_CFG(175, ALT_C)
-
-#define GPIO176_GPIO PIN_CFG(176, GPIO)
-#define GPIO176_MC3_CLK PIN_CFG(176, ALT_A)
-#define GPIO176_SPI3_CLK PIN_CFG(176, ALT_B)
-
-#define GPIO177_GPIO PIN_CFG(177, GPIO)
-#define GPIO177_U2_RXD PIN_CFG(177, ALT_A)
-#define GPIO177_I2C3_SCL PIN_CFG(177, ALT_B)
-#define GPIO177_BUSMON_D30 PIN_CFG(177, ALT_C)
-
-#define GPIO178_GPIO PIN_CFG(178, GPIO)
-#define GPIO178_U2_TXD PIN_CFG(178, ALT_A)
-#define GPIO178_I2C3_SDA PIN_CFG(178, ALT_B)
-#define GPIO178_BUSMON_D31 PIN_CFG(178, ALT_C)
-
-#define GPIO179_GPIO PIN_CFG(179, GPIO)
-#define GPIO179_U2_CTSn PIN_CFG(179, ALT_A)
-#define GPIO179_U3_RXD PIN_CFG(179, ALT_B)
-#define GPIO179_BUSMON_D32 PIN_CFG(179, ALT_C)
-
-#define GPIO180_GPIO PIN_CFG(180, GPIO)
-#define GPIO180_U2_RTSn PIN_CFG(180, ALT_A)
-#define GPIO180_U3_TXD PIN_CFG(180, ALT_B)
-#define GPIO180_BUSMON_D33 PIN_CFG(180, ALT_C)
-
-#define GPIO185_GPIO PIN_CFG(185, GPIO)
-#define GPIO185_SPI3_CS2n PIN_CFG(185, ALT_A)
-#define GPIO185_MC4_DAT0 PIN_CFG(185, ALT_B)
-
-#define GPIO186_GPIO PIN_CFG(186, GPIO)
-#define GPIO186_SPI3_CS1n PIN_CFG(186, ALT_A)
-#define GPIO186_MC4_DAT1 PIN_CFG(186, ALT_B)
-
-#define GPIO187_GPIO PIN_CFG(187, GPIO)
-#define GPIO187_SPI3_CS0n PIN_CFG(187, ALT_A)
-#define GPIO187_MC4_DAT2 PIN_CFG(187, ALT_B)
-
-#define GPIO188_GPIO PIN_CFG(188, GPIO)
-#define GPIO188_SPI3_RXD PIN_CFG(188, ALT_A)
-#define GPIO188_MC4_DAT3 PIN_CFG(188, ALT_B)
-
-#define GPIO189_GPIO PIN_CFG(189, GPIO)
-#define GPIO189_SPI3_TXD PIN_CFG(189, ALT_A)
-#define GPIO189_MC4_CMD PIN_CFG(189, ALT_B)
-
-#define GPIO190_GPIO PIN_CFG(190, GPIO)
-#define GPIO190_SPI3_CLK PIN_CFG(190, ALT_A)
-#define GPIO190_MC4_CLK PIN_CFG(190, ALT_B)
-
-#define GPIO191_GPIO PIN_CFG(191, GPIO)
-#define GPIO191_MC1_DAT0 PIN_CFG(191, ALT_A)
-#define GPIO191_MC4_DAT4 PIN_CFG(191, ALT_B)
-#define GPIO191_STMAPE_DAT0 PIN_CFG(191, ALT_C)
-
-#define GPIO192_GPIO PIN_CFG(192, GPIO)
-#define GPIO192_MC1_DAT1 PIN_CFG(192, ALT_A)
-#define GPIO192_MC4_DAT5 PIN_CFG(192, ALT_B)
-#define GPIO192_STMAPE_DAT1 PIN_CFG(192, ALT_C)
-
-#define GPIO193_GPIO PIN_CFG(193, GPIO)
-#define GPIO193_MC1_DAT2 PIN_CFG(193, ALT_A)
-#define GPIO193_MC4_DAT6 PIN_CFG(193, ALT_B)
-#define GPIO193_STMAPE_DAT2 PIN_CFG(193, ALT_C)
-
-#define GPIO194_GPIO PIN_CFG(194, GPIO)
-#define GPIO194_MC1_DAT3 PIN_CFG(194, ALT_A)
-#define GPIO194_MC4_DAT7 PIN_CFG(194, ALT_B)
-#define GPIO194_STMAPE_DAT3 PIN_CFG(194, ALT_C)
-
-#define GPIO195_GPIO PIN_CFG(195, GPIO)
-#define GPIO195_MC1_CLK PIN_CFG(195, ALT_A)
-#define GPIO195_STMAPE_CLK PIN_CFG(195, ALT_B)
-#define GPIO195_BUSMON_CLK PIN_CFG(195, ALT_C)
-
-#define GPIO196_GPIO PIN_CFG(196, GPIO)
-#define GPIO196_MC1_CMD PIN_CFG(196, ALT_A)
-#define GPIO196_U0_RXD PIN_CFG(196, ALT_B)
-#define GPIO196_BUSMON_D38 PIN_CFG(196, ALT_C)
-
-#define GPIO197_GPIO PIN_CFG(197, GPIO)
-#define GPIO197_MC1_CMDDIR PIN_CFG(197, ALT_A)
-#define GPIO197_BUSMON_D39 PIN_CFG(197, ALT_B)
-
-#define GPIO198_GPIO PIN_CFG(198, GPIO)
-#define GPIO198_MC1_FBCLK PIN_CFG(198, ALT_A)
-
-#define GPIO199_GPIO PIN_CFG(199, GPIO)
-#define GPIO199_MC1_DAT0DIR PIN_CFG(199, ALT_A)
-#define GPIO199_BUSMON_D40 PIN_CFG(199, ALT_B)
-
-#define GPIO200_GPIO PIN_CFG(200, GPIO)
-#define GPIO200_U1_TXD PIN_CFG(200, ALT_A)
-#define GPIO200_ACCU0_RTSn PIN_CFG(200, ALT_B)
-
-#define GPIO201_GPIO PIN_CFG(201, GPIO)
-#define GPIO201_U1_RXD PIN_CFG(201, ALT_A)
-#define GPIO201_ACCU0_CTSn PIN_CFG(201, ALT_B)
-
-#define GPIO202_GPIO PIN_CFG(202, GPIO)
-#define GPIO202_U1_CTSn PIN_CFG(202, ALT_A)
-#define GPIO202_ACCU0_RXD PIN_CFG(202, ALT_B)
-
-#define GPIO203_GPIO PIN_CFG(203, GPIO)
-#define GPIO203_U1_RTSn PIN_CFG(203, ALT_A)
-#define GPIO203_ACCU0_TXD PIN_CFG(203, ALT_B)
-
-#define GPIO204_GPIO PIN_CFG(204, GPIO)
-#define GPIO204_SPI0_CS2n PIN_CFG(204, ALT_A)
-#define GPIO204_ACCGPIO_000 PIN_CFG(204, ALT_B)
-#define GPIO204_LCD_VSI1 PIN_CFG(204, ALT_C)
-
-#define GPIO205_GPIO PIN_CFG(205, GPIO)
-#define GPIO205_SPI0_CS1n PIN_CFG(205, ALT_A)
-#define GPIO205_ACCGPIO_001 PIN_CFG(205, ALT_B)
-#define GPIO205_LCD_D3 PIN_CFG(205, ALT_C)
-
-#define GPIO206_GPIO PIN_CFG(206, GPIO)
-#define GPIO206_SPI0_CS0n PIN_CFG(206, ALT_A)
-#define GPIO206_ACCGPIO_002 PIN_CFG(206, ALT_B)
-#define GPIO206_LCD_D2 PIN_CFG(206, ALT_C)
-
-#define GPIO207_GPIO PIN_CFG(207, GPIO)
-#define GPIO207_SPI0_RXD PIN_CFG(207, ALT_A)
-#define GPIO207_ACCGPIO_003 PIN_CFG(207, ALT_B)
-#define GPIO207_LCD_D1 PIN_CFG(207, ALT_C)
-
-#define GPIO208_GPIO PIN_CFG(208, GPIO)
-#define GPIO208_SPI0_TXD PIN_CFG(208, ALT_A)
-#define GPIO208_ACCGPIO_004 PIN_CFG(208, ALT_B)
-#define GPIO208_LCD_D0 PIN_CFG(208, ALT_C)
-
-#define GPIO209_GPIO PIN_CFG(209, GPIO)
-#define GPIO209_SPI0_CLK PIN_CFG(209, ALT_A)
-#define GPIO209_ACCGPIO_005 PIN_CFG(209, ALT_B)
-#define GPIO209_LCD_CLK PIN_CFG(209, ALT_C)
-
-#define GPIO210_GPIO PIN_CFG(210, GPIO)
-#define GPIO210_LCD_VSO PIN_CFG(210, ALT_A)
-#define GPIO210_PRCMU_PWRCTRL1 PIN_CFG(210, ALT_B)
-
-#define GPIO211_GPIO PIN_CFG(211, GPIO)
-#define GPIO211_LCD_VSI0 PIN_CFG(211, ALT_A)
-#define GPIO211_PRCMU_PWRCTRL2 PIN_CFG(211, ALT_B)
-
-#define GPIO212_GPIO PIN_CFG(212, GPIO)
-#define GPIO212_SPI2_CS2n PIN_CFG(212, ALT_A)
-#define GPIO212_LCD_HSO PIN_CFG(212, ALT_B)
-
-#define GPIO213_GPIO PIN_CFG(213, GPIO)
-#define GPIO213_SPI2_CS1n PIN_CFG(213, ALT_A)
-#define GPIO213_LCD_DE PIN_CFG(213, ALT_B)
-#define GPIO213_BUSMON_D16 PIN_CFG(213, ALT_C)
-
-#define GPIO214_GPIO PIN_CFG(214, GPIO)
-#define GPIO214_SPI2_CS0n PIN_CFG(214, ALT_A)
-#define GPIO214_LCD_D7 PIN_CFG(214, ALT_B)
-#define GPIO214_BUSMON_D17 PIN_CFG(214, ALT_C)
-
-#define GPIO215_GPIO PIN_CFG(215, GPIO)
-#define GPIO215_SPI2_RXD PIN_CFG(215, ALT_A)
-#define GPIO215_LCD_D6 PIN_CFG(215, ALT_B)
-#define GPIO215_BUSMON_D18 PIN_CFG(215, ALT_C)
-
-#define GPIO216_GPIO PIN_CFG(216, GPIO)
-#define GPIO216_SPI2_CLK PIN_CFG(216, ALT_A)
-#define GPIO216_LCD_D5 PIN_CFG(216, ALT_B)
-
-#define GPIO217_GPIO PIN_CFG(217, GPIO)
-#define GPIO217_SPI2_TXD PIN_CFG(217, ALT_A)
-#define GPIO217_LCD_D4 PIN_CFG(217, ALT_B)
-#define GPIO217_BUSMON_D19 PIN_CFG(217, ALT_C)
-
-#define GPIO218_GPIO PIN_CFG(218, GPIO)
-#define GPIO218_I2C2_SCL PIN_CFG(218, ALT_A)
-#define GPIO218_LCD_VSO PIN_CFG(218, ALT_B)
-
-#define GPIO219_GPIO PIN_CFG(219, GPIO)
-#define GPIO219_I2C2_SDA PIN_CFG(219, ALT_A)
-#define GPIO219_LCD_D3 PIN_CFG(219, ALT_B)
-
-#define GPIO220_GPIO PIN_CFG(220, GPIO)
-#define GPIO220_MSP2_TCK PIN_CFG(220, ALT_A)
-#define GPIO220_LCD_D2 PIN_CFG(220, ALT_B)
-
-#define GPIO221_GPIO PIN_CFG(221, GPIO)
-#define GPIO221_MSP2_TFS PIN_CFG(221, ALT_A)
-#define GPIO221_LCD_D1 PIN_CFG(221, ALT_B)
-
-#define GPIO222_GPIO PIN_CFG(222, GPIO)
-#define GPIO222_MSP2_TXD PIN_CFG(222, ALT_A)
-#define GPIO222_LCD_D0 PIN_CFG(222, ALT_B)
-
-#define GPIO223_GPIO PIN_CFG(223, GPIO)
-#define GPIO223_MSP2_RXD PIN_CFG(223, ALT_A)
-#define GPIO223_LCD_CLK PIN_CFG(223, ALT_B)
-
-#define GPIO224_GPIO PIN_CFG(224, GPIO)
-#define GPIO224_PRCMU_PWRCTRL0 PIN_CFG(224, ALT_A)
-#define GPIO224_LCD_VSI1 PIN_CFG(224, ALT_B)
-
-#define GPIO225_GPIO PIN_CFG(225, GPIO)
-#define GPIO225_PRCMU_PWRCTRL1 PIN_CFG(225, ALT_A)
-#define GPIO225_IRDA_RXD PIN_CFG(225, ALT_B)
-
-#define GPIO226_GPIO PIN_CFG(226, GPIO)
-#define GPIO226_PRCMU_PWRCTRL2 PIN_CFG(226, ALT_A)
-#define GPIO226_IRRC_DAT PIN_CFG(226, ALT_B)
-
-#define GPIO227_GPIO PIN_CFG(227, GPIO)
-#define GPIO227_IRRC_DAT PIN_CFG(227, ALT_A)
-#define GPIO227_IRDA_TXD PIN_CFG(227, ALT_B)
-
-#endif
diff --git a/arch/arm/mach-ux500/pins-db8500.h b/arch/arm/mach-ux500/pins-db8500.h
index 8b1d1a7a679e..062c7acf4576 100644
--- a/arch/arm/mach-ux500/pins-db8500.h
+++ b/arch/arm/mach-ux500/pins-db8500.h
@@ -35,40 +35,40 @@
#define GPIO4_GPIO PIN_CFG(4, GPIO)
#define GPIO4_U1_RXD PIN_CFG(4, ALT_A)
-#define GPIO4_I2C4_SCL PIN_CFG_INPUT(4, ALT_B, PULLUP)
+#define GPIO4_I2C4_SCL PIN_CFG(4, ALT_B)
#define GPIO4_IP_TRSTn PIN_CFG(4, ALT_C)
#define GPIO5_GPIO PIN_CFG(5, GPIO)
#define GPIO5_U1_TXD PIN_CFG(5, ALT_A)
-#define GPIO5_I2C4_SDA PIN_CFG_INPUT(5, ALT_B, PULLUP)
+#define GPIO5_I2C4_SDA PIN_CFG(5, ALT_B)
#define GPIO5_IP_GPIO6 PIN_CFG(5, ALT_C)
#define GPIO6_GPIO PIN_CFG(6, GPIO)
#define GPIO6_U1_CTSn PIN_CFG(6, ALT_A)
-#define GPIO6_I2C1_SCL PIN_CFG_INPUT(6, ALT_B, PULLUP)
+#define GPIO6_I2C1_SCL PIN_CFG(6, ALT_B)
#define GPIO6_IP_GPIO0 PIN_CFG(6, ALT_C)
#define GPIO7_GPIO PIN_CFG(7, GPIO)
#define GPIO7_U1_RTSn PIN_CFG(7, ALT_A)
-#define GPIO7_I2C1_SDA PIN_CFG_INPUT(7, ALT_B, PULLUP)
+#define GPIO7_I2C1_SDA PIN_CFG(7, ALT_B)
#define GPIO7_IP_GPIO1 PIN_CFG(7, ALT_C)
#define GPIO8_GPIO PIN_CFG(8, GPIO)
-#define GPIO8_IPI2C_SDA PIN_CFG_INPUT(8, ALT_A, PULLUP)
-#define GPIO8_I2C2_SDA PIN_CFG_INPUT(8, ALT_B, PULLUP)
+#define GPIO8_IPI2C_SDA PIN_CFG(8, ALT_A)
+#define GPIO8_I2C2_SDA PIN_CFG(8, ALT_B)
#define GPIO9_GPIO PIN_CFG(9, GPIO)
-#define GPIO9_IPI2C_SCL PIN_CFG_INPUT(9, ALT_A, PULLUP)
-#define GPIO9_I2C2_SCL PIN_CFG_INPUT(9, ALT_B, PULLUP)
+#define GPIO9_IPI2C_SCL PIN_CFG(9, ALT_A)
+#define GPIO9_I2C2_SCL PIN_CFG(9, ALT_B)
#define GPIO10_GPIO PIN_CFG(10, GPIO)
-#define GPIO10_IPI2C_SDA PIN_CFG_INPUT(10, ALT_A, PULLUP)
-#define GPIO10_I2C2_SDA PIN_CFG_INPUT(10, ALT_B, PULLUP)
+#define GPIO10_IPI2C_SDA PIN_CFG(10, ALT_A)
+#define GPIO10_I2C2_SDA PIN_CFG(10, ALT_B)
#define GPIO10_IP_GPIO3 PIN_CFG(10, ALT_C)
#define GPIO11_GPIO PIN_CFG(11, GPIO)
-#define GPIO11_IPI2C_SCL PIN_CFG_INPUT(11, ALT_A, PULLUP)
-#define GPIO11_I2C2_SCL PIN_CFG_INPUT(11, ALT_B, PULLUP)
+#define GPIO11_IPI2C_SCL PIN_CFG(11, ALT_A)
+#define GPIO11_I2C2_SCL PIN_CFG(11, ALT_B)
#define GPIO11_IP_GPIO2 PIN_CFG(11, ALT_C)
#define GPIO12_GPIO PIN_CFG(12, GPIO)
@@ -87,12 +87,12 @@
#define GPIO16_GPIO PIN_CFG(16, GPIO)
#define GPIO16_MSP0_RFS PIN_CFG(16, ALT_A)
-#define GPIO16_I2C1_SCL PIN_CFG_INPUT(16, ALT_B, PULLUP)
+#define GPIO16_I2C1_SCL PIN_CFG(16, ALT_B)
#define GPIO16_SLIM0_DAT PIN_CFG(16, ALT_C)
#define GPIO17_GPIO PIN_CFG(17, GPIO)
#define GPIO17_MSP0_RCK PIN_CFG(17, ALT_A)
-#define GPIO17_I2C1_SDA PIN_CFG_INPUT(17, ALT_B, PULLUP)
+#define GPIO17_I2C1_SDA PIN_CFG(17, ALT_B)
#define GPIO17_SLIM0_CLK PIN_CFG(17, ALT_C)
#define GPIO18_GPIO PIN_CFG(18, GPIO)
@@ -434,10 +434,10 @@
#define GPIO146_SSP0_TXD PIN_CFG(146, ALT_A)
#define GPIO147_GPIO PIN_CFG(147, GPIO)
-#define GPIO147_I2C0_SCL PIN_CFG_INPUT(147, ALT_A, PULLUP)
+#define GPIO147_I2C0_SCL PIN_CFG(147, ALT_A)
#define GPIO148_GPIO PIN_CFG(148, GPIO)
-#define GPIO148_I2C0_SDA PIN_CFG_INPUT(148, ALT_A, PULLUP)
+#define GPIO148_I2C0_SDA PIN_CFG(148, ALT_A)
#define GPIO149_GPIO PIN_CFG(149, GPIO)
#define GPIO149_IP_GPIO0 PIN_CFG(149, ALT_A)
@@ -459,82 +459,82 @@
#define GPIO152_KP_O9 PIN_CFG(152, ALT_C)
#define GPIO153_GPIO PIN_CFG(153, GPIO)
-#define GPIO153_KP_I7 PIN_CFG_INPUT(153, ALT_A, PULLDOWN)
+#define GPIO153_KP_I7 PIN_CFG(153, ALT_A)
#define GPIO153_LCD_D24 PIN_CFG(153, ALT_B)
#define GPIO153_U2_RXD PIN_CFG(153, ALT_C)
#define GPIO154_GPIO PIN_CFG(154, GPIO)
-#define GPIO154_KP_I6 PIN_CFG_INPUT(154, ALT_A, PULLDOWN)
+#define GPIO154_KP_I6 PIN_CFG(154, ALT_A)
#define GPIO154_LCD_D25 PIN_CFG(154, ALT_B)
#define GPIO154_U2_TXD PIN_CFG(154, ALT_C)
#define GPIO155_GPIO PIN_CFG(155, GPIO)
-#define GPIO155_KP_I5 PIN_CFG_INPUT(155, ALT_A, PULLDOWN)
+#define GPIO155_KP_I5 PIN_CFG(155, ALT_A)
#define GPIO155_LCD_D26 PIN_CFG(155, ALT_B)
#define GPIO155_STMAPE_CLK PIN_CFG(155, ALT_C)
#define GPIO156_GPIO PIN_CFG(156, GPIO)
-#define GPIO156_KP_I4 PIN_CFG_INPUT(156, ALT_A, PULLDOWN)
+#define GPIO156_KP_I4 PIN_CFG(156, ALT_A)
#define GPIO156_LCD_D27 PIN_CFG(156, ALT_B)
#define GPIO156_STMAPE_DAT3 PIN_CFG(156, ALT_C)
#define GPIO157_GPIO PIN_CFG(157, GPIO)
-#define GPIO157_KP_O7 PIN_CFG_INPUT(157, ALT_A, PULLUP)
+#define GPIO157_KP_O7 PIN_CFG(157, ALT_A)
#define GPIO157_LCD_D28 PIN_CFG(157, ALT_B)
#define GPIO157_STMAPE_DAT2 PIN_CFG(157, ALT_C)
#define GPIO158_GPIO PIN_CFG(158, GPIO)
-#define GPIO158_KP_O6 PIN_CFG_INPUT(158, ALT_A, PULLUP)
+#define GPIO158_KP_O6 PIN_CFG(158, ALT_A)
#define GPIO158_LCD_D29 PIN_CFG(158, ALT_B)
#define GPIO158_STMAPE_DAT1 PIN_CFG(158, ALT_C)
#define GPIO159_GPIO PIN_CFG(159, GPIO)
-#define GPIO159_KP_O5 PIN_CFG_INPUT(159, ALT_A, PULLUP)
+#define GPIO159_KP_O5 PIN_CFG(159, ALT_A)
#define GPIO159_LCD_D30 PIN_CFG(159, ALT_B)
#define GPIO159_STMAPE_DAT0 PIN_CFG(159, ALT_C)
#define GPIO160_GPIO PIN_CFG(160, GPIO)
-#define GPIO160_KP_O4 PIN_CFG_INPUT(160, ALT_A, PULLUP)
+#define GPIO160_KP_O4 PIN_CFG(160, ALT_A)
#define GPIO160_LCD_D31 PIN_CFG(160, ALT_B)
#define GPIO160_NONE PIN_CFG(160, ALT_C)
#define GPIO161_GPIO PIN_CFG(161, GPIO)
-#define GPIO161_KP_I3 PIN_CFG_INPUT(161, ALT_A, PULLDOWN)
+#define GPIO161_KP_I3 PIN_CFG(161, ALT_A)
#define GPIO161_LCD_D32 PIN_CFG(161, ALT_B)
#define GPIO161_UARTMOD_RXD PIN_CFG(161, ALT_C)
#define GPIO162_GPIO PIN_CFG(162, GPIO)
-#define GPIO162_KP_I2 PIN_CFG_INPUT(162, ALT_A, PULLDOWN)
+#define GPIO162_KP_I2 PIN_CFG(162, ALT_A)
#define GPIO162_LCD_D33 PIN_CFG(162, ALT_B)
#define GPIO162_UARTMOD_TXD PIN_CFG(162, ALT_C)
#define GPIO163_GPIO PIN_CFG(163, GPIO)
-#define GPIO163_KP_I1 PIN_CFG_INPUT(163, ALT_A, PULLDOWN)
+#define GPIO163_KP_I1 PIN_CFG(163, ALT_A)
#define GPIO163_LCD_D34 PIN_CFG(163, ALT_B)
#define GPIO163_STMMOD_CLK PIN_CFG(163, ALT_C)
#define GPIO164_GPIO PIN_CFG(164, GPIO)
-#define GPIO164_KP_I0 PIN_CFG_INPUT(164, ALT_A, PULLUP)
+#define GPIO164_KP_I0 PIN_CFG(164, ALT_A)
#define GPIO164_LCD_D35 PIN_CFG(164, ALT_B)
#define GPIO164_STMMOD_DAT3 PIN_CFG(164, ALT_C)
#define GPIO165_GPIO PIN_CFG(165, GPIO)
-#define GPIO165_KP_O3 PIN_CFG_INPUT(165, ALT_A, PULLUP)
+#define GPIO165_KP_O3 PIN_CFG(165, ALT_A)
#define GPIO165_LCD_D36 PIN_CFG(165, ALT_B)
#define GPIO165_STMMOD_DAT2 PIN_CFG(165, ALT_C)
#define GPIO166_GPIO PIN_CFG(166, GPIO)
-#define GPIO166_KP_O2 PIN_CFG_INPUT(166, ALT_A, PULLUP)
+#define GPIO166_KP_O2 PIN_CFG(166, ALT_A)
#define GPIO166_LCD_D37 PIN_CFG(166, ALT_B)
#define GPIO166_STMMOD_DAT1 PIN_CFG(166, ALT_C)
#define GPIO167_GPIO PIN_CFG(167, GPIO)
-#define GPIO167_KP_O1 PIN_CFG_INPUT(167, ALT_A, PULLUP)
+#define GPIO167_KP_O1 PIN_CFG(167, ALT_A)
#define GPIO167_LCD_D38 PIN_CFG(167, ALT_B)
#define GPIO167_STMMOD_DAT0 PIN_CFG(167, ALT_C)
#define GPIO168_GPIO PIN_CFG(168, GPIO)
-#define GPIO168_KP_O0 PIN_CFG_INPUT(168, ALT_A, PULLUP)
+#define GPIO168_KP_O0 PIN_CFG(168, ALT_A)
#define GPIO168_LCD_D39 PIN_CFG(168, ALT_B)
#define GPIO168_NONE PIN_CFG(168, ALT_C)
@@ -637,7 +637,7 @@
#define GPIO216_GPIO PIN_CFG(216, GPIO)
#define GPIO216_MC1_DAT2DIR PIN_CFG(216, ALT_A)
#define GPIO216_MC3_CMDDIR PIN_CFG(216, ALT_B)
-#define GPIO216_I2C3_SDA PIN_CFG_INPUT(216, ALT_C, PULLUP)
+#define GPIO216_I2C3_SDA PIN_CFG(216, ALT_C)
#define GPIO216_SPI2_FRM PIN_CFG(216, ALT_C)
#define GPIO217_GPIO PIN_CFG(217, GPIO)
@@ -649,7 +649,7 @@
#define GPIO218_GPIO PIN_CFG(218, GPIO)
#define GPIO218_MC1_DAT31DIR PIN_CFG(218, ALT_A)
#define GPIO218_MC3_DAT0DIR PIN_CFG(218, ALT_B)
-#define GPIO218_I2C3_SCL PIN_CFG_INPUT(218, ALT_C, PULLUP)
+#define GPIO218_I2C3_SCL PIN_CFG(218, ALT_C)
#define GPIO218_SPI2_RXD PIN_CFG(218, ALT_C)
#define GPIO219_GPIO PIN_CFG(219, GPIO)
@@ -698,12 +698,12 @@
#define GPIO229_GPIO PIN_CFG(229, GPIO)
#define GPIO229_CLKOUT1 PIN_CFG(229, ALT_A)
#define GPIO229_PWL PIN_CFG(229, ALT_B)
-#define GPIO229_I2C3_SDA PIN_CFG_INPUT(229, ALT_C, PULLUP)
+#define GPIO229_I2C3_SDA PIN_CFG(229, ALT_C)
#define GPIO230_GPIO PIN_CFG(230, GPIO)
#define GPIO230_CLKOUT2 PIN_CFG(230, ALT_A)
#define GPIO230_PWL PIN_CFG(230, ALT_B)
-#define GPIO230_I2C3_SCL PIN_CFG_INPUT(230, ALT_C, PULLUP)
+#define GPIO230_I2C3_SCL PIN_CFG(230, ALT_C)
#define GPIO256_GPIO PIN_CFG(256, GPIO)
#define GPIO256_USB_NXT PIN_CFG(256, ALT_A)
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index eff5842f6232..da1d5ad5bd45 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -48,9 +48,7 @@ static void write_pen_release(int val)
static void __iomem *scu_base_addr(void)
{
- if (cpu_is_u5500())
- return __io_address(U5500_SCU_BASE);
- else if (cpu_is_u8500())
+ if (cpu_is_u8500_family())
return __io_address(U8500_SCU_BASE);
else
ux500_unknown_soc();
@@ -120,9 +118,7 @@ static void __init wakeup_secondary(void)
{
void __iomem *backupram;
- if (cpu_is_u5500())
- backupram = __io_address(U5500_BACKUPRAM0_BASE);
- else if (cpu_is_u8500())
+ if (cpu_is_u8500_family())
backupram = __io_address(U8500_BACKUPRAM0_BASE);
else
ux500_unknown_soc();
diff --git a/arch/arm/mach-ux500/ste-dma40-db5500.h b/arch/arm/mach-ux500/ste-dma40-db5500.h
deleted file mode 100644
index cb2110c32858..000000000000
--- a/arch/arm/mach-ux500/ste-dma40-db5500.h
+++ /dev/null
@@ -1,135 +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
- *
- * DB5500-SoC-specific configuration for DMA40
- */
-
-#ifndef STE_DMA40_DB5500_H
-#define STE_DMA40_DB5500_H
-
-#define DB5500_DMA_NR_DEV 64
-
-enum dma_src_dev_type {
- DB5500_DMA_DEV0_SPI0_RX = 0,
- DB5500_DMA_DEV1_SPI1_RX = 1,
- DB5500_DMA_DEV2_SPI2_RX = 2,
- DB5500_DMA_DEV3_SPI3_RX = 3,
- DB5500_DMA_DEV4_USB_OTG_IEP_1_9 = 4,
- DB5500_DMA_DEV5_USB_OTG_IEP_2_10 = 5,
- DB5500_DMA_DEV6_USB_OTG_IEP_3_11 = 6,
- DB5500_DMA_DEV7_IRDA_RFS = 7,
- DB5500_DMA_DEV8_IRDA_FIFO_RX = 8,
- DB5500_DMA_DEV9_MSP0_RX = 9,
- DB5500_DMA_DEV10_MSP1_RX = 10,
- DB5500_DMA_DEV11_MSP2_RX = 11,
- DB5500_DMA_DEV12_UART0_RX = 12,
- DB5500_DMA_DEV13_UART1_RX = 13,
- DB5500_DMA_DEV14_UART2_RX = 14,
- DB5500_DMA_DEV15_UART3_RX = 15,
- DB5500_DMA_DEV16_USB_OTG_IEP_8 = 16,
- DB5500_DMA_DEV17_USB_OTG_IEP_1_9 = 17,
- DB5500_DMA_DEV18_USB_OTG_IEP_2_10 = 18,
- DB5500_DMA_DEV19_USB_OTG_IEP_3_11 = 19,
- DB5500_DMA_DEV20_USB_OTG_IEP_4_12 = 20,
- DB5500_DMA_DEV21_USB_OTG_IEP_5_13 = 21,
- DB5500_DMA_DEV22_USB_OTG_IEP_6_14 = 22,
- DB5500_DMA_DEV23_USB_OTG_IEP_7_15 = 23,
- DB5500_DMA_DEV24_SDMMC0_RX = 24,
- DB5500_DMA_DEV25_SDMMC1_RX = 25,
- DB5500_DMA_DEV26_SDMMC2_RX = 26,
- DB5500_DMA_DEV27_SDMMC3_RX = 27,
- DB5500_DMA_DEV28_SDMMC4_RX = 28,
- /* 29 - 32 not used */
- DB5500_DMA_DEV33_SDMMC0_RX = 33,
- DB5500_DMA_DEV34_SDMMC1_RX = 34,
- DB5500_DMA_DEV35_SDMMC2_RX = 35,
- DB5500_DMA_DEV36_SDMMC3_RX = 36,
- DB5500_DMA_DEV37_SDMMC4_RX = 37,
- DB5500_DMA_DEV38_USB_OTG_IEP_8 = 38,
- DB5500_DMA_DEV39_USB_OTG_IEP_1_9 = 39,
- DB5500_DMA_DEV40_USB_OTG_IEP_2_10 = 40,
- DB5500_DMA_DEV41_USB_OTG_IEP_3_11 = 41,
- DB5500_DMA_DEV42_USB_OTG_IEP_4_12 = 42,
- DB5500_DMA_DEV43_USB_OTG_IEP_5_13 = 43,
- DB5500_DMA_DEV44_USB_OTG_IEP_6_14 = 44,
- DB5500_DMA_DEV45_USB_OTG_IEP_7_15 = 45,
- /* 46 not used */
- DB5500_DMA_DEV47_MCDE_RX = 47,
- DB5500_DMA_DEV48_CRYPTO1_RX = 48,
- /* 49, 50 not used */
- DB5500_DMA_DEV49_I2C1_RX = 51,
- DB5500_DMA_DEV50_I2C3_RX = 52,
- DB5500_DMA_DEV51_I2C2_RX = 53,
- /* 54 - 60 not used */
- DB5500_DMA_DEV61_CRYPTO0_RX = 61,
- /* 62, 63 not used */
-};
-
-enum dma_dest_dev_type {
- DB5500_DMA_DEV0_SPI0_TX = 0,
- DB5500_DMA_DEV1_SPI1_TX = 1,
- DB5500_DMA_DEV2_SPI2_TX = 2,
- DB5500_DMA_DEV3_SPI3_TX = 3,
- DB5500_DMA_DEV4_USB_OTG_OEP_1_9 = 4,
- DB5500_DMA_DEV5_USB_OTG_OEP_2_10 = 5,
- DB5500_DMA_DEV6_USB_OTG_OEP_3_11 = 6,
- DB5500_DMA_DEV7_IRRC_TX = 7,
- DB5500_DMA_DEV8_IRDA_FIFO_TX = 8,
- DB5500_DMA_DEV9_MSP0_TX = 9,
- DB5500_DMA_DEV10_MSP1_TX = 10,
- DB5500_DMA_DEV11_MSP2_TX = 11,
- DB5500_DMA_DEV12_UART0_TX = 12,
- DB5500_DMA_DEV13_UART1_TX = 13,
- DB5500_DMA_DEV14_UART2_TX = 14,
- DB5500_DMA_DEV15_UART3_TX = 15,
- DB5500_DMA_DEV16_USB_OTG_OEP_8 = 16,
- DB5500_DMA_DEV17_USB_OTG_OEP_1_9 = 17,
- DB5500_DMA_DEV18_USB_OTG_OEP_2_10 = 18,
- DB5500_DMA_DEV19_USB_OTG_OEP_3_11 = 19,
- DB5500_DMA_DEV20_USB_OTG_OEP_4_12 = 20,
- DB5500_DMA_DEV21_USB_OTG_OEP_5_13 = 21,
- DB5500_DMA_DEV22_USB_OTG_OEP_6_14 = 22,
- DB5500_DMA_DEV23_USB_OTG_OEP_7_15 = 23,
- DB5500_DMA_DEV24_SDMMC0_TX = 24,
- DB5500_DMA_DEV25_SDMMC1_TX = 25,
- DB5500_DMA_DEV26_SDMMC2_TX = 26,
- DB5500_DMA_DEV27_SDMMC3_TX = 27,
- DB5500_DMA_DEV28_SDMMC4_TX = 28,
- /* 29 - 31 not used */
- DB5500_DMA_DEV32_FSMC_TX = 32,
- DB5500_DMA_DEV33_SDMMC0_TX = 33,
- DB5500_DMA_DEV34_SDMMC1_TX = 34,
- DB5500_DMA_DEV35_SDMMC2_TX = 35,
- DB5500_DMA_DEV36_SDMMC3_TX = 36,
- DB5500_DMA_DEV37_SDMMC4_TX = 37,
- DB5500_DMA_DEV38_USB_OTG_OEP_8 = 38,
- DB5500_DMA_DEV39_USB_OTG_OEP_1_9 = 39,
- DB5500_DMA_DEV40_USB_OTG_OEP_2_10 = 40,
- DB5500_DMA_DEV41_USB_OTG_OEP_3_11 = 41,
- DB5500_DMA_DEV42_USB_OTG_OEP_4_12 = 42,
- DB5500_DMA_DEV43_USB_OTG_OEP_5_13 = 43,
- DB5500_DMA_DEV44_USB_OTG_OEP_6_14 = 44,
- DB5500_DMA_DEV45_USB_OTG_OEP_7_15 = 45,
- /* 46 not used */
- DB5500_DMA_DEV47_STM_TX = 47,
- DB5500_DMA_DEV48_CRYPTO1_TX = 48,
- DB5500_DMA_DEV49_CRYPTO1_TX_HASH1_TX = 49,
- DB5500_DMA_DEV50_HASH1_TX = 50,
- DB5500_DMA_DEV51_I2C1_TX = 51,
- DB5500_DMA_DEV52_I2C3_TX = 52,
- DB5500_DMA_DEV53_I2C2_TX = 53,
- /* 54, 55 not used */
- DB5500_DMA_MEMCPY_TX_1 = 56,
- DB5500_DMA_MEMCPY_TX_2 = 57,
- DB5500_DMA_MEMCPY_TX_3 = 58,
- DB5500_DMA_MEMCPY_TX_4 = 59,
- DB5500_DMA_MEMCPY_TX_5 = 60,
- DB5500_DMA_DEV61_CRYPTO0_TX = 61,
- DB5500_DMA_DEV62_CRYPTO0_TX_HASH0_TX = 62,
- DB5500_DMA_DEV63_HASH0_TX = 63,
-};
-
-#endif
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
index d37df98b5c32..741e71feca78 100644
--- a/arch/arm/mach-ux500/timer.c
+++ b/arch/arm/mach-ux500/timer.c
@@ -8,6 +8,7 @@
#include <linux/errno.h>
#include <linux/clksrc-dbx500-prcmu.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <asm/smp_twd.h>
@@ -18,8 +19,6 @@
#include <mach/irqs.h>
#ifdef CONFIG_HAVE_ARM_TWD
-static DEFINE_TWD_LOCAL_TIMER(u5500_twd_local_timer,
- U5500_TWD_BASE, IRQ_LOCALTIMER);
static DEFINE_TWD_LOCAL_TIMER(u8500_twd_local_timer,
U8500_TWD_BASE, IRQ_LOCALTIMER);
@@ -28,8 +27,8 @@ static void __init ux500_twd_init(void)
struct twd_local_timer *twd_local_timer;
int err;
- twd_local_timer = cpu_is_u5500() ? &u5500_twd_local_timer :
- &u8500_twd_local_timer;
+ /* Use this to switch local timer base if changed in new ASICs */
+ twd_local_timer = &u8500_twd_local_timer;
if (of_have_populated_dt())
twd_local_timer_of_register();
@@ -43,21 +42,41 @@ static void __init ux500_twd_init(void)
#define ux500_twd_init() do { } while(0)
#endif
+const static struct of_device_id prcmu_timer_of_match[] __initconst = {
+ { .compatible = "stericsson,db8500-prcmu-timer-4", },
+ { },
+};
+
static void __init ux500_timer_init(void)
{
void __iomem *mtu_timer_base;
void __iomem *prcmu_timer_base;
+ void __iomem *tmp_base;
+ struct device_node *np;
- if (cpu_is_u5500()) {
- mtu_timer_base = __io_address(U5500_MTU0_BASE);
- prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE);
- } else if (cpu_is_u8500()) {
+ if (cpu_is_u8500_family()) {
mtu_timer_base = __io_address(U8500_MTU0_BASE);
prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
} else {
ux500_unknown_soc();
}
+ /* TODO: Once MTU has been DT:ed place code above into else. */
+ if (of_have_populated_dt()) {
+ np = of_find_matching_node(NULL, prcmu_timer_of_match);
+ if (!np)
+ goto dt_fail;
+
+ tmp_base = of_iomap(np, 0);
+ if (!tmp_base)
+ goto dt_fail;
+
+ prcmu_timer_base = tmp_base;
+ }
+
+dt_fail:
+ /* Doing it the old fashioned way. */
+
/*
* Here we register the timerblocks active in the system.
* Localtimers (twd) is started when both cpu is up and running.
@@ -70,7 +89,7 @@ static void __init ux500_timer_init(void)
* depending on delay which is not yet calibrated. RTC-RTT is in the
* always-on powerdomain and is used as clockevent instead of twd when
* sleeping.
- * The PRCMU timer 4(3 for DB5500) register a clocksource and
+ * The PRCMU timer 4 register a clocksource and
* sched_clock with higher rating then MTU since is always-on.
*
*/
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 6bbd74e950ab..cf4687ee2a7b 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -66,12 +66,6 @@
#define VA_VIC_BASE __io_address(VERSATILE_VIC_BASE)
#define VA_SIC_BASE __io_address(VERSATILE_SIC_BASE)
-static struct fpga_irq_data sic_irq = {
- .base = VA_SIC_BASE,
- .irq_start = IRQ_SIC_START,
- .chip.name = "SIC",
-};
-
#if 1
#define IRQ_MMCI0A IRQ_VICSOURCE22
#define IRQ_AACI IRQ_VICSOURCE24
@@ -105,8 +99,11 @@ void __init versatile_init_irq(void)
writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
- fpga_irq_init(IRQ_VICSOURCE31, ~PIC_MASK, &sic_irq);
- irq_domain_generate_simple(sic_of_match, VERSATILE_SIC_BASE, IRQ_SIC_START);
+ np = of_find_matching_node_by_address(NULL, sic_of_match,
+ VERSATILE_SIC_BASE);
+
+ fpga_irq_init(VA_SIC_BASE, "SIC", IRQ_SIC_START,
+ IRQ_VICSOURCE31, ~PIC_MASK, np);
/*
* Interrupts on secondary controller from 0 to 8 are routed to
@@ -666,17 +663,18 @@ static struct amba_device *amba_devs[] __initdata = {
* having a specific name.
*/
struct of_dev_auxdata versatile_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI0_BASE, "fpga:05", NULL),
+ OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI0_BASE, "fpga:05", &mmc0_plat_data),
OF_DEV_AUXDATA("arm,primecell", VERSATILE_KMI0_BASE, "fpga:06", NULL),
OF_DEV_AUXDATA("arm,primecell", VERSATILE_KMI1_BASE, "fpga:07", NULL),
OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART3_BASE, "fpga:09", NULL),
+ /* FIXME: this is buggy, the platform data is needed for this MMC instance too */
OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI1_BASE, "fpga:0b", NULL),
OF_DEV_AUXDATA("arm,primecell", VERSATILE_CLCD_BASE, "dev:20", &clcd_plat_data),
OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART0_BASE, "dev:f1", NULL),
OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART1_BASE, "dev:f2", NULL),
OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART2_BASE, "dev:f3", NULL),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_SSP_BASE, "dev:f4", NULL),
+ OF_DEV_AUXDATA("arm,primecell", VERSATILE_SSP_BASE, "dev:f4", &ssp0_plat_data),
#if 0
/*
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c
index d2268be8c34c..15c6a00000ec 100644
--- a/arch/arm/mach-versatile/pci.c
+++ b/arch/arm/mach-versatile/pci.c
@@ -303,12 +303,6 @@ int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
}
-struct pci_bus * __init pci_versatile_scan_bus(int nr, struct pci_sys_data *sys)
-{
- return pci_scan_root_bus(NULL, sys->busnr, &pci_versatile_ops, sys,
- &sys->resources);
-}
-
void __init pci_versatile_preinit(void)
{
pcibios_min_io = 0x44000000;
@@ -339,19 +333,16 @@ static int __init versatile_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
* 26 1 29
* 27 1 30
*/
- irq = 27 + ((slot + pin - 1) & 3);
-
- printk("PCI map irq: slot %d, pin %d, devslot %d, irq: %d\n",slot,pin,devslot,irq);
+ irq = 27 + ((slot - 24 + pin - 1) & 3);
return irq;
}
static struct hw_pci versatile_pci __initdata = {
- .swizzle = NULL,
.map_irq = versatile_map_irq,
.nr_controllers = 1,
+ .ops = &pci_versatile_ops,
.setup = pci_versatile_setup,
- .scan = pci_versatile_scan_bus,
.preinit = pci_versatile_preinit,
};
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 47cdcca5a7e7..04dd092211b8 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -19,8 +19,10 @@
#include <linux/clkdev.h>
#include <linux/mtd/physmap.h>
+#include <asm/arch_timer.h>
#include <asm/mach-types.h>
#include <asm/sizes.h>
+#include <asm/smp_twd.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
@@ -616,7 +618,6 @@ void __init v2m_dt_init_early(void)
}
clkdev_add_table(v2m_dt_lookups, ARRAY_SIZE(v2m_dt_lookups));
- versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
}
static struct of_device_id vexpress_irq_match[] __initdata = {
@@ -643,6 +644,11 @@ static void __init v2m_dt_timer_init(void)
return;
node = of_find_node_by_path(path);
v2m_sp804_init(of_iomap(node, 0), irq_of_parse_and_map(node, 0));
+ if (arch_timer_of_register() != 0)
+ twd_local_timer_of_register();
+
+ if (arch_timer_sched_clock_init() != 0)
+ versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
}
static struct sys_timer v2m_dt_timer = {
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 7c8a7d8467bf..101b9681c08c 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -4,23 +4,6 @@ comment "Processor Type"
# which CPUs we support in the kernel image, and the compiler instruction
# optimiser behaviour.
-# ARM610
-config CPU_ARM610
- bool "Support ARM610 processor" if ARCH_RPC
- select CPU_32v3
- select CPU_CACHE_V3
- select CPU_CACHE_VIVT
- select CPU_CP15_MMU
- select CPU_COPY_V3 if MMU
- select CPU_TLB_V3 if MMU
- select CPU_PABRT_LEGACY
- help
- The ARM610 is the successor to the ARM3 processor
- and was produced by VLSI Technology Inc.
-
- Say Y if you want support for the ARM610 processor.
- Otherwise, say N.
-
# ARM7TDMI
config CPU_ARM7TDMI
bool "Support ARM7TDMI processor"
@@ -36,25 +19,6 @@ config CPU_ARM7TDMI
Say Y if you want support for the ARM7TDMI processor.
Otherwise, say N.
-# ARM710
-config CPU_ARM710
- bool "Support ARM710 processor" if ARCH_RPC
- select CPU_32v3
- select CPU_CACHE_V3
- select CPU_CACHE_VIVT
- select CPU_CP15_MMU
- select CPU_COPY_V3 if MMU
- select CPU_TLB_V3 if MMU
- select CPU_PABRT_LEGACY
- help
- A 32-bit RISC microprocessor based on the ARM7 processor core
- designed by Advanced RISC Machines Ltd. The ARM710 is the
- successor to the ARM610 processor. It was released in
- July 1994 by VLSI Technology Inc.
-
- Say Y if you want support for the ARM710 processor.
- Otherwise, say N.
-
# ARM720T
config CPU_ARM720T
bool "Support ARM720T processor" if ARCH_INTEGRATOR
@@ -530,9 +494,6 @@ config CPU_CACHE_FA
if MMU
# The copy-page model
-config CPU_COPY_V3
- bool
-
config CPU_COPY_V4WT
bool
@@ -549,11 +510,6 @@ config CPU_COPY_V6
bool
# This selects the TLB model
-config CPU_TLB_V3
- bool
- help
- ARM Architecture Version 3 TLB.
-
config CPU_TLB_V4WT
bool
help
@@ -731,7 +687,7 @@ config CPU_HIGH_VECTOR
config CPU_ICACHE_DISABLE
bool "Disable I-Cache (I-bit)"
- depends on CPU_CP15 && !(CPU_ARM610 || CPU_ARM710 || CPU_ARM720T || CPU_ARM740T || CPU_XSCALE || CPU_XSC3)
+ depends on CPU_CP15 && !(CPU_ARM720T || CPU_ARM740T || CPU_XSCALE || CPU_XSC3)
help
Say Y here to disable the processor instruction cache. Unless
you have a reason not to or are unsure, say N.
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index bca7e61928c7..8a9c4cb50a93 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -44,7 +44,6 @@ obj-$(CONFIG_CPU_CACHE_FA) += cache-fa.o
AFLAGS_cache-v6.o :=-Wa,-march=armv6
AFLAGS_cache-v7.o :=-Wa,-march=armv7-a
-obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o
obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o
obj-$(CONFIG_CPU_COPY_V4WB) += copypage-v4wb.o
obj-$(CONFIG_CPU_COPY_FEROCEON) += copypage-feroceon.o
@@ -54,7 +53,6 @@ obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o
obj-$(CONFIG_CPU_XSC3) += copypage-xsc3.o
obj-$(CONFIG_CPU_COPY_FA) += copypage-fa.o
-obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o
obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o
obj-$(CONFIG_CPU_TLB_V4WB) += tlb-v4wb.o
obj-$(CONFIG_CPU_TLB_V4WBI) += tlb-v4wbi.o
@@ -66,8 +64,6 @@ obj-$(CONFIG_CPU_TLB_FA) += tlb-fa.o
AFLAGS_tlb-v6.o :=-Wa,-march=armv6
AFLAGS_tlb-v7.o :=-Wa,-march=armv7-a
-obj-$(CONFIG_CPU_ARM610) += proc-arm6_7.o
-obj-$(CONFIG_CPU_ARM710) += proc-arm6_7.o
obj-$(CONFIG_CPU_ARM7TDMI) += proc-arm7tdmi.o
obj-$(CONFIG_CPU_ARM720T) += proc-arm720.o
obj-$(CONFIG_CPU_ARM740T) += proc-arm740.o
diff --git a/arch/arm/mm/cache-tauros2.c b/arch/arm/mm/cache-tauros2.c
index 1fbca05fe906..23a7643e9a87 100644
--- a/arch/arm/mm/cache-tauros2.c
+++ b/arch/arm/mm/cache-tauros2.c
@@ -108,6 +108,26 @@ static void tauros2_flush_range(unsigned long start, unsigned long end)
dsb();
}
+
+static void tauros2_disable(void)
+{
+ __asm__ __volatile__ (
+ "mcr p15, 1, %0, c7, c11, 0 @L2 Cache Clean All\n\t"
+ "mrc p15, 0, %0, c1, c0, 0\n\t"
+ "bic %0, %0, #(1 << 26)\n\t"
+ "mcr p15, 0, %0, c1, c0, 0 @Disable L2 Cache\n\t"
+ : : "r" (0x0));
+}
+
+static void tauros2_resume(void)
+{
+ __asm__ __volatile__ (
+ "mcr p15, 1, %0, c7, c7, 0 @L2 Cache Invalidate All\n\t"
+ "mrc p15, 0, %0, c1, c0, 0\n\t"
+ "orr %0, %0, #(1 << 26)\n\t"
+ "mcr p15, 0, %0, c1, c0, 0 @Enable L2 Cache\n\t"
+ : : "r" (0x0));
+}
#endif
static inline u32 __init read_extra_features(void)
@@ -194,6 +214,8 @@ void __init tauros2_init(void)
outer_cache.inv_range = tauros2_inv_range;
outer_cache.clean_range = tauros2_clean_range;
outer_cache.flush_range = tauros2_flush_range;
+ outer_cache.disable = tauros2_disable;
+ outer_cache.resume = tauros2_resume;
}
#endif
@@ -219,6 +241,8 @@ void __init tauros2_init(void)
outer_cache.inv_range = tauros2_inv_range;
outer_cache.clean_range = tauros2_clean_range;
outer_cache.flush_range = tauros2_flush_range;
+ outer_cache.disable = tauros2_disable;
+ outer_cache.resume = tauros2_resume;
}
#endif
diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S
index c2301f226100..52e35f32eefb 100644
--- a/arch/arm/mm/cache-v3.S
+++ b/arch/arm/mm/cache-v3.S
@@ -78,6 +78,7 @@ ENTRY(v3_coherent_kern_range)
* - end - virtual end address
*/
ENTRY(v3_coherent_user_range)
+ mov r0, #0
mov pc, lr
/*
diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S
index fd9bb7addc8d..022135d2b7e4 100644
--- a/arch/arm/mm/cache-v4.S
+++ b/arch/arm/mm/cache-v4.S
@@ -88,6 +88,7 @@ ENTRY(v4_coherent_kern_range)
* - end - virtual end address
*/
ENTRY(v4_coherent_user_range)
+ mov r0, #0
mov pc, lr
/*
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S
index 4f2c14151ccb..8f1eeae340c8 100644
--- a/arch/arm/mm/cache-v4wb.S
+++ b/arch/arm/mm/cache-v4wb.S
@@ -167,9 +167,9 @@ ENTRY(v4wb_coherent_user_range)
add r0, r0, #CACHE_DLINESIZE
cmp r0, r1
blo 1b
- mov ip, #0
- mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
- mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
mov pc, lr
diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S
index 4d7b467631ce..b34a5f908a82 100644
--- a/arch/arm/mm/cache-v4wt.S
+++ b/arch/arm/mm/cache-v4wt.S
@@ -125,6 +125,7 @@ ENTRY(v4wt_coherent_user_range)
add r0, r0, #CACHE_DLINESIZE
cmp r0, r1
blo 1b
+ mov r0, #0
mov pc, lr
/*
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 74c2e5a33a4d..4b10760c56d6 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -12,6 +12,7 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/assembler.h>
+#include <asm/errno.h>
#include <asm/unwind.h>
#include "proc-macros.S"
@@ -135,7 +136,6 @@ ENTRY(v6_coherent_user_range)
1:
USER( mcr p15, 0, r0, c7, c10, 1 ) @ clean D line
add r0, r0, #CACHE_LINE_SIZE
-2:
cmp r0, r1
blo 1b
#endif
@@ -154,13 +154,11 @@ ENTRY(v6_coherent_user_range)
/*
* Fault handling for the cache operation above. If the virtual address in r0
- * isn't mapped, just try the next page.
+ * isn't mapped, fail with -EFAULT.
*/
9001:
- mov r0, r0, lsr #12
- mov r0, r0, lsl #12
- add r0, r0, #4096
- b 2b
+ mov r0, #-EFAULT
+ mov pc, lr
UNWIND(.fnend )
ENDPROC(v6_coherent_user_range)
ENDPROC(v6_coherent_kern_range)
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index a655d3da386d..39e3fb3db801 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -13,6 +13,7 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/assembler.h>
+#include <asm/errno.h>
#include <asm/unwind.h>
#include "proc-macros.S"
@@ -198,7 +199,6 @@ ENTRY(v7_coherent_user_range)
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
@@ -208,13 +208,11 @@ ENTRY(v7_coherent_user_range)
/*
* Fault handling for the cache operation above. If the virtual address in r0
- * isn't mapped, just try the next page.
+ * isn't mapped, fail with -EFAULT.
*/
9001:
- mov r12, r12, lsr #12
- mov r12, r12, lsl #12
- add r12, r12, #4096
- b 3b
+ mov r0, #-EFAULT
+ mov pc, lr
UNWIND(.fnend )
ENDPROC(v7_coherent_kern_range)
ENDPROC(v7_coherent_user_range)
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index ee9bb363d606..806cc4f63516 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -18,30 +18,39 @@
static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
unsigned int cpu_last_asid = ASID_FIRST_VERSION;
-#ifdef CONFIG_SMP
-DEFINE_PER_CPU(struct mm_struct *, current_mm);
-#endif
#ifdef CONFIG_ARM_LPAE
-#define cpu_set_asid(asid) { \
- unsigned long ttbl, ttbh; \
- asm volatile( \
- " mrrc p15, 0, %0, %1, c2 @ read TTBR0\n" \
- " mov %1, %2, lsl #(48 - 32) @ set ASID\n" \
- " mcrr p15, 0, %0, %1, c2 @ set TTBR0\n" \
- : "=&r" (ttbl), "=&r" (ttbh) \
- : "r" (asid & ~ASID_MASK)); \
+void cpu_set_reserved_ttbr0(void)
+{
+ unsigned long ttbl = __pa(swapper_pg_dir);
+ unsigned long ttbh = 0;
+
+ /*
+ * Set TTBR0 to swapper_pg_dir which contains only global entries. The
+ * ASID is set to 0.
+ */
+ asm volatile(
+ " mcrr p15, 0, %0, %1, c2 @ set TTBR0\n"
+ :
+ : "r" (ttbl), "r" (ttbh));
+ isb();
}
#else
-#define cpu_set_asid(asid) \
- asm(" mcr p15, 0, %0, c13, c0, 1\n" : : "r" (asid))
+void cpu_set_reserved_ttbr0(void)
+{
+ u32 ttb;
+ /* Copy TTBR1 into TTBR0 */
+ asm volatile(
+ " mrc p15, 0, %0, c2, c0, 1 @ read TTBR1\n"
+ " mcr p15, 0, %0, c2, c0, 0 @ set TTBR0\n"
+ : "=r" (ttb));
+ isb();
+}
#endif
/*
* We fork()ed a process, and we need a new context for the child
- * to run in. We reserve version 0 for initial tasks so we will
- * always allocate an ASID. The ASID 0 is reserved for the TTBR
- * register changing sequence.
+ * to run in.
*/
void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
{
@@ -51,9 +60,7 @@ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
static void flush_context(void)
{
- /* set the reserved ASID before flushing the TLB */
- cpu_set_asid(0);
- isb();
+ cpu_set_reserved_ttbr0();
local_flush_tlb_all();
if (icache_is_vivt_asid_tagged()) {
__flush_icache_all();
@@ -98,14 +105,7 @@ static void reset_context(void *info)
{
unsigned int asid;
unsigned int cpu = smp_processor_id();
- struct mm_struct *mm = per_cpu(current_mm, cpu);
-
- /*
- * Check if a current_mm was set on this CPU as it might still
- * be in the early booting stages and using the reserved ASID.
- */
- if (!mm)
- return;
+ struct mm_struct *mm = current->active_mm;
smp_rmb();
asid = cpu_last_asid + cpu + 1;
@@ -114,8 +114,7 @@ static void reset_context(void *info)
set_mm_context(mm, asid);
/* set the new ASID */
- cpu_set_asid(mm->context.id);
- isb();
+ cpu_switch_mm(mm->pgd, mm);
}
#else
diff --git a/arch/arm/mm/copypage-v3.c b/arch/arm/mm/copypage-v3.c
deleted file mode 100644
index 3935bddd4769..000000000000
--- a/arch/arm/mm/copypage-v3.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * linux/arch/arm/mm/copypage-v3.c
- *
- * Copyright (C) 1995-1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/init.h>
-#include <linux/highmem.h>
-
-/*
- * ARMv3 optimised copy_user_highpage
- *
- * FIXME: do we need to handle cache stuff...
- */
-static void __naked
-v3_copy_user_page(void *kto, const void *kfrom)
-{
- asm("\n\
- stmfd sp!, {r4, lr} @ 2\n\
- mov r2, %2 @ 1\n\
- ldmia %0!, {r3, r4, ip, lr} @ 4+1\n\
-1: stmia %1!, {r3, r4, ip, lr} @ 4\n\
- ldmia %0!, {r3, r4, ip, lr} @ 4+1\n\
- stmia %1!, {r3, r4, ip, lr} @ 4\n\
- ldmia %0!, {r3, r4, ip, lr} @ 4+1\n\
- stmia %1!, {r3, r4, ip, lr} @ 4\n\
- ldmia %0!, {r3, r4, ip, lr} @ 4\n\
- subs r2, r2, #1 @ 1\n\
- stmia %1!, {r3, r4, ip, lr} @ 4\n\
- ldmneia %0!, {r3, r4, ip, lr} @ 4\n\
- bne 1b @ 1\n\
- ldmfd sp!, {r4, pc} @ 3"
- :
- : "r" (kfrom), "r" (kto), "I" (PAGE_SIZE / 64));
-}
-
-void v3_copy_user_highpage(struct page *to, struct page *from,
- unsigned long vaddr, struct vm_area_struct *vma)
-{
- void *kto, *kfrom;
-
- kto = kmap_atomic(to);
- kfrom = kmap_atomic(from);
- v3_copy_user_page(kto, kfrom);
- kunmap_atomic(kfrom);
- kunmap_atomic(kto);
-}
-
-/*
- * ARMv3 optimised clear_user_page
- *
- * FIXME: do we need to handle cache stuff...
- */
-void v3_clear_user_highpage(struct page *page, unsigned long vaddr)
-{
- void *ptr, *kaddr = kmap_atomic(page);
- asm volatile("\n\
- mov r1, %2 @ 1\n\
- mov r2, #0 @ 1\n\
- mov r3, #0 @ 1\n\
- mov ip, #0 @ 1\n\
- mov lr, #0 @ 1\n\
-1: stmia %0!, {r2, r3, ip, lr} @ 4\n\
- stmia %0!, {r2, r3, ip, lr} @ 4\n\
- stmia %0!, {r2, r3, ip, lr} @ 4\n\
- stmia %0!, {r2, r3, ip, lr} @ 4\n\
- subs r1, r1, #1 @ 1\n\
- bne 1b @ 1"
- : "=r" (ptr)
- : "0" (kaddr), "I" (PAGE_SIZE / 64)
- : "r1", "r2", "r3", "ip", "lr");
- kunmap_atomic(kaddr);
-}
-
-struct cpu_user_fns v3_user_fns __initdata = {
- .cpu_clear_user_highpage = v3_clear_user_highpage,
- .cpu_copy_user_highpage = v3_copy_user_highpage,
-};
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index f07467533365..c3bd83450227 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -247,7 +247,9 @@ good_area:
return handle_mm_fault(mm, vma, addr & PAGE_MASK, flags);
check_stack:
- if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr))
+ /* Don't allow expansion below FIRST_USER_ADDRESS */
+ if (vma->vm_flags & VM_GROWSDOWN &&
+ addr >= FIRST_USER_ADDRESS && !expand_stack(vma, addr))
goto good_area;
out:
return fault;
@@ -430,9 +432,6 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
index = pgd_index(addr);
- /*
- * FIXME: CP15 C1 is write only on ARMv3 architectures.
- */
pgd = cpu_get_pgd() + index;
pgd_k = init_mm.pgd + index;
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 2c7cf2f9c837..aa78de8bfdd3 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -489,7 +489,8 @@ static void __init build_mem_type_table(void)
*/
for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
mem_types[i].prot_pte |= PTE_EXT_AF;
- mem_types[i].prot_sect |= PMD_SECT_AF;
+ if (mem_types[i].prot_sect)
+ mem_types[i].prot_sect |= PMD_SECT_AF;
}
kern_pgprot |= PTE_EXT_AF;
vecs_pgprot |= PTE_EXT_AF;
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index 234951345eb3..0650bb87c1e3 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -241,6 +241,7 @@ ENTRY(arm1020_coherent_user_range)
cmp r0, r1
blo 1b
mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mov r0, #0
mov pc, lr
/*
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index c244b06caac9..4188478325a6 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -235,6 +235,7 @@ ENTRY(arm1020e_coherent_user_range)
cmp r0, r1
blo 1b
mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mov r0, #0
mov pc, lr
/*
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 38fe22efd18f..33c68824bff0 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -224,6 +224,7 @@ ENTRY(arm1022_coherent_user_range)
cmp r0, r1
blo 1b
mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mov r0, #0
mov pc, lr
/*
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index 3eb9c3c26c75..fbc1d5fc24dc 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -218,6 +218,7 @@ ENTRY(arm1026_coherent_user_range)
cmp r0, r1
blo 1b
mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mov r0, #0
mov pc, lr
/*
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
deleted file mode 100644
index 4fbeb5b8e6c2..000000000000
--- a/arch/arm/mm/proc-arm6_7.S
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * linux/arch/arm/mm/proc-arm6,7.S
- *
- * Copyright (C) 1997-2000 Russell King
- * hacked for non-paged-MM by Hyok S. Choi, 2003.
- *
- * 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.
- *
- * These are the low level assembler for performing cache and TLB
- * functions on the ARM610 & ARM710.
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/assembler.h>
-#include <asm/asm-offsets.h>
-#include <asm/hwcap.h>
-#include <asm/pgtable-hwdef.h>
-#include <asm/pgtable.h>
-#include <asm/ptrace.h>
-
-#include "proc-macros.S"
-
-ENTRY(cpu_arm6_dcache_clean_area)
-ENTRY(cpu_arm7_dcache_clean_area)
- mov pc, lr
-
-/*
- * Function: arm6_7_data_abort ()
- *
- * Params : r2 = pt_regs
- * : r4 = aborted context pc
- * : r5 = aborted context psr
- *
- * Purpose : obtain information about current aborted instruction
- *
- * Returns : r4-r5, r10-r11, r13 preserved
- */
-
-ENTRY(cpu_arm7_data_abort)
- mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
- ldr r8, [r4] @ read arm instruction
- tst r8, #1 << 20 @ L = 0 -> write?
- orreq r1, r1, #1 << 11 @ yes.
- and r7, r8, #15 << 24
- add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine
- nop
-
-/* 0 */ b .data_unknown
-/* 1 */ b do_DataAbort @ swp
-/* 2 */ b .data_unknown
-/* 3 */ b .data_unknown
-/* 4 */ b .data_arm_lateldrpostconst @ ldr rd, [rn], #m
-/* 5 */ b .data_arm_lateldrpreconst @ ldr rd, [rn, #m]
-/* 6 */ b .data_arm_lateldrpostreg @ ldr rd, [rn], rm
-/* 7 */ b .data_arm_lateldrprereg @ ldr rd, [rn, rm]
-/* 8 */ b .data_arm_ldmstm @ ldm*a rn, <rlist>
-/* 9 */ b .data_arm_ldmstm @ ldm*b rn, <rlist>
-/* a */ b .data_unknown
-/* b */ b .data_unknown
-/* c */ b do_DataAbort @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m
-/* d */ b do_DataAbort @ ldc rd, [rn, #m]
-/* e */ b .data_unknown
-/* f */
-.data_unknown: @ Part of jumptable
- mov r0, r4
- mov r1, r8
- b baddataabort
-
-ENTRY(cpu_arm6_data_abort)
- mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
- ldr r8, [r4] @ read arm instruction
- tst r8, #1 << 20 @ L = 0 -> write?
- orreq r1, r1, #1 << 11 @ yes.
- and r7, r8, #14 << 24
- teq r7, #8 << 24 @ was it ldm/stm
- bne do_DataAbort
-
-.data_arm_ldmstm:
- tst r8, #1 << 21 @ check writeback bit
- beq do_DataAbort @ no writeback -> no fixup
- mov r7, #0x11
- orr r7, r7, #0x1100
- and r6, r8, r7
- and r9, r8, r7, lsl #1
- add r6, r6, r9, lsr #1
- and r9, r8, r7, lsl #2
- add r6, r6, r9, lsr #2
- and r9, r8, r7, lsl #3
- add r6, r6, r9, lsr #3
- add r6, r6, r6, lsr #8
- add r6, r6, r6, lsr #4
- and r6, r6, #15 @ r6 = no. of registers to transfer.
- and r9, r8, #15 << 16 @ Extract 'n' from instruction
- ldr r7, [r2, r9, lsr #14] @ Get register 'Rn'
- tst r8, #1 << 23 @ Check U bit
- subne r7, r7, r6, lsl #2 @ Undo increment
- addeq r7, r7, r6, lsl #2 @ Undo decrement
- str r7, [r2, r9, lsr #14] @ Put register 'Rn'
- b do_DataAbort
-
-.data_arm_apply_r6_and_rn:
- and r9, r8, #15 << 16 @ Extract 'n' from instruction
- ldr r7, [r2, r9, lsr #14] @ Get register 'Rn'
- tst r8, #1 << 23 @ Check U bit
- subne r7, r7, r6 @ Undo incrmenet
- addeq r7, r7, r6 @ Undo decrement
- str r7, [r2, r9, lsr #14] @ Put register 'Rn'
- b do_DataAbort
-
-.data_arm_lateldrpreconst:
- tst r8, #1 << 21 @ check writeback bit
- beq do_DataAbort @ no writeback -> no fixup
-.data_arm_lateldrpostconst:
- movs r6, r8, lsl #20 @ Get offset
- beq do_DataAbort @ zero -> no fixup
- and r9, r8, #15 << 16 @ Extract 'n' from instruction
- ldr r7, [r2, r9, lsr #14] @ Get register 'Rn'
- tst r8, #1 << 23 @ Check U bit
- subne r7, r7, r6, lsr #20 @ Undo increment
- addeq r7, r7, r6, lsr #20 @ Undo decrement
- str r7, [r2, r9, lsr #14] @ Put register 'Rn'
- b do_DataAbort
-
-.data_arm_lateldrprereg:
- tst r8, #1 << 21 @ check writeback bit
- beq do_DataAbort @ no writeback -> no fixup
-.data_arm_lateldrpostreg:
- and r7, r8, #15 @ Extract 'm' from instruction
- ldr r6, [r2, r7, lsl #2] @ Get register 'Rm'
- mov r9, r8, lsr #7 @ get shift count
- ands r9, r9, #31
- and r7, r8, #0x70 @ get shift type
- orreq r7, r7, #8 @ shift count = 0
- add pc, pc, r7
- nop
-
- mov r6, r6, lsl r9 @ 0: LSL #!0
- b .data_arm_apply_r6_and_rn
- b .data_arm_apply_r6_and_rn @ 1: LSL #0
- nop
- b .data_unknown @ 2: MUL?
- nop
- b .data_unknown @ 3: MUL?
- nop
- mov r6, r6, lsr r9 @ 4: LSR #!0
- b .data_arm_apply_r6_and_rn
- mov r6, r6, lsr #32 @ 5: LSR #32
- b .data_arm_apply_r6_and_rn
- b .data_unknown @ 6: MUL?
- nop
- b .data_unknown @ 7: MUL?
- nop
- mov r6, r6, asr r9 @ 8: ASR #!0
- b .data_arm_apply_r6_and_rn
- mov r6, r6, asr #32 @ 9: ASR #32
- b .data_arm_apply_r6_and_rn
- b .data_unknown @ A: MUL?
- nop
- b .data_unknown @ B: MUL?
- nop
- mov r6, r6, ror r9 @ C: ROR #!0
- b .data_arm_apply_r6_and_rn
- mov r6, r6, rrx @ D: RRX
- b .data_arm_apply_r6_and_rn
- b .data_unknown @ E: MUL?
- nop
- b .data_unknown @ F: MUL?
-
-/*
- * Function: arm6_7_proc_init (void)
- * : arm6_7_proc_fin (void)
- *
- * Notes : This processor does not require these
- */
-ENTRY(cpu_arm6_proc_init)
-ENTRY(cpu_arm7_proc_init)
- mov pc, lr
-
-ENTRY(cpu_arm6_proc_fin)
-ENTRY(cpu_arm7_proc_fin)
- mov r0, #0x31 @ ....S..DP...M
- mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
-
-ENTRY(cpu_arm6_do_idle)
-ENTRY(cpu_arm7_do_idle)
- mov pc, lr
-
-/*
- * Function: arm6_7_switch_mm(unsigned long pgd_phys)
- * Params : pgd_phys Physical address of page table
- * Purpose : Perform a task switch, saving the old processes state, and restoring
- * the new.
- */
-ENTRY(cpu_arm6_switch_mm)
-ENTRY(cpu_arm7_switch_mm)
-#ifdef CONFIG_MMU
- mov r1, #0
- mcr p15, 0, r1, c7, c0, 0 @ flush cache
- mcr p15, 0, r0, c2, c0, 0 @ update page table ptr
- mcr p15, 0, r1, c5, c0, 0 @ flush TLBs
-#endif
- mov pc, lr
-
-/*
- * Function: arm6_7_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext)
- * Params : r0 = Address to set
- * : r1 = value to set
- * Purpose : Set a PTE and flush it out of any WB cache
- */
- .align 5
-ENTRY(cpu_arm6_set_pte_ext)
-ENTRY(cpu_arm7_set_pte_ext)
-#ifdef CONFIG_MMU
- armv3_set_pte_ext wc_disable=0
-#endif /* CONFIG_MMU */
- mov pc, lr
-
-/*
- * Function: _arm6_7_reset
- * Params : r0 = address to jump to
- * Notes : This sets up everything for a reset
- */
- .pushsection .idmap.text, "ax"
-ENTRY(cpu_arm6_reset)
-ENTRY(cpu_arm7_reset)
- mov r1, #0
- mcr p15, 0, r1, c7, c0, 0 @ flush cache
-#ifdef CONFIG_MMU
- mcr p15, 0, r1, c5, c0, 0 @ flush TLB
-#endif
- mov r1, #0x30
- mcr p15, 0, r1, c1, c0, 0 @ turn off MMU etc
- mov pc, r0
-ENDPROC(cpu_arm6_reset)
-ENDPROC(cpu_arm7_reset)
- .popsection
-
- __CPUINIT
-
- .type __arm6_setup, #function
-__arm6_setup: mov r0, #0
- mcr p15, 0, r0, c7, c0 @ flush caches on v3
-#ifdef CONFIG_MMU
- mcr p15, 0, r0, c5, c0 @ flush TLBs on v3
- mov r0, #0x3d @ . ..RS BLDP WCAM
- orr r0, r0, #0x100 @ . ..01 0011 1101
-#else
- mov r0, #0x3c @ . ..RS BLDP WCA.
-#endif
- mov pc, lr
- .size __arm6_setup, . - __arm6_setup
-
- .type __arm7_setup, #function
-__arm7_setup: mov r0, #0
- mcr p15, 0, r0, c7, c0 @ flush caches on v3
-#ifdef CONFIG_MMU
- mcr p15, 0, r0, c5, c0 @ flush TLBs on v3
- mcr p15, 0, r0, c3, c0 @ load domain access register
- mov r0, #0x7d @ . ..RS BLDP WCAM
- orr r0, r0, #0x100 @ . ..01 0111 1101
-#else
- mov r0, #0x7c @ . ..RS BLDP WCA.
-#endif
- mov pc, lr
- .size __arm7_setup, . - __arm7_setup
-
- __INITDATA
-
- @ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
- define_processor_functions arm6, dabort=cpu_arm6_data_abort, pabort=legacy_pabort
- define_processor_functions arm7, dabort=cpu_arm7_data_abort, pabort=legacy_pabort
-
- .section ".rodata"
-
- string cpu_arch_name, "armv3"
- string cpu_elf_name, "v3"
- string cpu_arm6_name, "ARM6"
- string cpu_arm610_name, "ARM610"
- string cpu_arm7_name, "ARM7"
- string cpu_arm710_name, "ARM710"
-
- .align
-
- .section ".proc.info.init", #alloc, #execinstr
-
-.macro arm67_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, \
- cpu_mm_mmu_flags:req, cpu_flush:req, cpu_proc_funcs:req
- .type __\name\()_proc_info, #object
-__\name\()_proc_info:
- .long \cpu_val
- .long \cpu_mask
- .long \cpu_mm_mmu_flags
- .long PMD_TYPE_SECT | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
- b \cpu_flush
- .long cpu_arch_name
- .long cpu_elf_name
- .long HWCAP_SWP | HWCAP_26BIT
- .long \cpu_name
- .long \cpu_proc_funcs
- .long v3_tlb_fns
- .long v3_user_fns
- .long v3_cache_fns
- .size __\name\()_proc_info, . - __\name\()_proc_info
-.endm
-
- arm67_proc_info arm6, 0x41560600, 0xfffffff0, cpu_arm6_name, \
- 0x00000c1e, __arm6_setup, arm6_processor_functions
- arm67_proc_info arm610, 0x41560610, 0xfffffff0, cpu_arm610_name, \
- 0x00000c1e, __arm6_setup, arm6_processor_functions
- arm67_proc_info arm7, 0x41007000, 0xffffff00, cpu_arm7_name, \
- 0x00000c1e, __arm7_setup, arm7_processor_functions
- arm67_proc_info arm710, 0x41007100, 0xfff8ff00, cpu_arm710_name, \
- PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
- PMD_BIT4 | \
- PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ, \
- __arm7_setup, arm7_processor_functions
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index cb941ae95f66..1a8c138eb897 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -210,6 +210,7 @@ ENTRY(arm920_coherent_user_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov r0, #0
mov pc, lr
/*
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index 4ec0e074dd55..4c44d7e1c3ca 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -212,6 +212,7 @@ ENTRY(arm922_coherent_user_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov r0, #0
mov pc, lr
/*
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index 9dccd9a365b3..ec5b1180994f 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -258,6 +258,7 @@ ENTRY(arm925_coherent_user_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov r0, #0
mov pc, lr
/*
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 820259b81a1f..c31e62c606c0 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -221,6 +221,7 @@ ENTRY(arm926_coherent_user_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov r0, #0
mov pc, lr
/*
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index 9fdc0a170974..a613a7dd7146 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -160,7 +160,7 @@ ENTRY(arm940_coherent_user_range)
* - size - region size
*/
ENTRY(arm940_flush_kern_dcache_area)
- mov ip, #0
+ mov r0, #0
mov r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
1: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
2: mcr p15, 0, r3, c7, c14, 2 @ clean/flush D index
@@ -168,8 +168,8 @@ ENTRY(arm940_flush_kern_dcache_area)
bcs 2b @ entries 63 to 0
subs r1, r1, #1 << 4
bcs 1b @ segments 7 to 0
- mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
- mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
mov pc, lr
/*
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index f684cfedcca9..9f4f2999fdd0 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -190,6 +190,7 @@ ENTRY(arm946_coherent_user_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov r0, #0
mov pc, lr
/*
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index ba3c500584ac..23a8e4c7f2bd 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -232,6 +232,7 @@ ENTRY(feroceon_coherent_user_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov r0, #0
mov pc, lr
/*
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index cdfedc5b8ad8..fbb2124a547d 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -193,6 +193,7 @@ ENTRY(mohawk_coherent_user_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov r0, #0
mov pc, lr
/*
@@ -344,6 +345,41 @@ ENTRY(cpu_mohawk_set_pte_ext)
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mov pc, lr
+.globl cpu_mohawk_suspend_size
+.equ cpu_mohawk_suspend_size, 4 * 6
+#ifdef CONFIG_PM_SLEEP
+ENTRY(cpu_mohawk_do_suspend)
+ stmfd sp!, {r4 - r9, lr}
+ mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode
+ mrc p15, 0, r5, c15, c1, 0 @ CP access reg
+ mrc p15, 0, r6, c13, c0, 0 @ PID
+ mrc p15, 0, r7, c3, c0, 0 @ domain ID
+ mrc p15, 0, r8, c1, c0, 1 @ auxiliary control reg
+ mrc p15, 0, r9, c1, c0, 0 @ control reg
+ bic r4, r4, #2 @ clear frequency change bit
+ stmia r0, {r4 - r9} @ store cp regs
+ ldmia sp!, {r4 - r9, pc}
+ENDPROC(cpu_mohawk_do_suspend)
+
+ENTRY(cpu_mohawk_do_resume)
+ ldmia r0, {r4 - r9} @ load cp regs
+ mov ip, #0
+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I & D caches, BTB
+ mcr p15, 0, ip, c7, c10, 4 @ drain write (&fill) buffer
+ mcr p15, 0, ip, c7, c5, 4 @ flush prefetch buffer
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ mcr p14, 0, r4, c6, c0, 0 @ clock configuration, turbo mode.
+ mcr p15, 0, r5, c15, c1, 0 @ CP access reg
+ mcr p15, 0, r6, c13, c0, 0 @ PID
+ mcr p15, 0, r7, c3, c0, 0 @ domain ID
+ orr r1, r1, #0x18 @ cache the page table in L2
+ mcr p15, 0, r1, c2, c0, 0 @ translation table base addr
+ mcr p15, 0, r8, c1, c0, 1 @ auxiliary control reg
+ mov r0, r9 @ control register
+ b cpu_resume_mmu
+ENDPROC(cpu_mohawk_do_resume)
+#endif
+
__CPUINIT
.type __mohawk_setup, #function
diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
index 3a4b3e7b888c..42ac069c8012 100644
--- a/arch/arm/mm/proc-v7-2level.S
+++ b/arch/arm/mm/proc-v7-2level.S
@@ -49,15 +49,10 @@ ENTRY(cpu_v7_switch_mm)
#ifdef CONFIG_ARM_ERRATA_754322
dsb
#endif
- mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID
- isb
-1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
- isb
-#ifdef CONFIG_ARM_ERRATA_754322
- dsb
-#endif
mcr p15, 0, r1, c13, c0, 1 @ set context ID
isb
+ mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
+ isb
#endif
mov pc, lr
ENDPROC(cpu_v7_switch_mm)
diff --git a/arch/arm/mm/tlb-v3.S b/arch/arm/mm/tlb-v3.S
deleted file mode 100644
index d253995ec4ca..000000000000
--- a/arch/arm/mm/tlb-v3.S
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * linux/arch/arm/mm/tlbv3.S
- *
- * Copyright (C) 1997-2002 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * ARM architecture version 3 TLB handling functions.
- *
- * Processors: ARM610, ARM710.
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/asm-offsets.h>
-#include <asm/tlbflush.h>
-#include "proc-macros.S"
-
- .align 5
-/*
- * v3_flush_user_tlb_range(start, end, mm)
- *
- * Invalidate a range of TLB entries in the specified address space.
- *
- * - start - range start address
- * - end - range end address
- * - mm - mm_struct describing address space
- */
- .align 5
-ENTRY(v3_flush_user_tlb_range)
- vma_vm_mm r2, r2
- act_mm r3 @ get current->active_mm
- teq r2, r3 @ == mm ?
- movne pc, lr @ no, we dont do anything
-ENTRY(v3_flush_kern_tlb_range)
- bic r0, r0, #0x0ff
- bic r0, r0, #0xf00
-1: mcr p15, 0, r0, c6, c0, 0 @ invalidate TLB entry
- add r0, r0, #PAGE_SZ
- cmp r0, r1
- blo 1b
- mov pc, lr
-
- __INITDATA
-
- /* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
- define_tlb_functions v3, v3_tlb_flags
diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c
index cb7658e8acc5..4e729f055a81 100644
--- a/arch/arm/nwfpe/fpmodule.c
+++ b/arch/arm/nwfpe/fpmodule.c
@@ -147,7 +147,7 @@ void float_raise(signed char flags)
#ifdef CONFIG_DEBUG_USER
if (flags & debug)
printk(KERN_DEBUG
- "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n",
+ "NWFPE: %s[%d] takes exception %08x at %pf from %08lx\n",
current->comm, current->pid, flags,
__builtin_return_address(0), GET_USERREG()->ARM_pc);
#endif
diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/plat-iop/pci.c
index 0da42058a20f..8daae9b230ea 100644
--- a/arch/arm/plat-iop/pci.c
+++ b/arch/arm/plat-iop/pci.c
@@ -160,7 +160,7 @@ iop3xx_write_config(struct pci_bus *bus, unsigned int devfn, int where,
return PCIBIOS_SUCCESSFUL;
}
-static struct pci_ops iop3xx_ops = {
+struct pci_ops iop3xx_ops = {
.read = iop3xx_read_config,
.write = iop3xx_write_config,
};
@@ -220,12 +220,6 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
return 1;
}
-struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *sys)
-{
- return pci_scan_root_bus(NULL, sys->busnr, &iop3xx_ops, sys,
- &sys->resources);
-}
-
void __init iop3xx_atu_setup(void)
{
/* BAR 0 ( Disabled ) */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
index c7f5169a6a54..36c8989d9de6 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
@@ -256,13 +256,13 @@
#define MX51_PAD_NANDF_RB1__GPIO3_9 IOMUX_PAD(0x4fc, 0x120, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_NANDF_RB1__NANDF_RB1 IOMUX_PAD(0x4fc, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_RB1__PATA_IORDY IOMUX_PAD(0x4fc, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__SD4_CMD IOMUX_PAD(0x4fc, 0x120, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__SD4_CMD IOMUX_PAD(0x4fc, 0x120, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL)
#define MX51_PAD_NANDF_RB2__DISP2_WAIT IOMUX_PAD(0x500, 0x124, 5, 0x9a8, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK IOMUX_PAD(0x500, 0x124, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
#define MX51_PAD_NANDF_RB2__FEC_COL IOMUX_PAD(0x500, 0x124, 1, 0x94c, 0, MX51_PAD_CTRL_2)
#define MX51_PAD_NANDF_RB2__GPIO3_10 IOMUX_PAD(0x500, 0x124, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_NANDF_RB2__NANDF_RB2 IOMUX_PAD(0x500, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__USBH3_H3_DP IOMUX_PAD(0x500, 0x124, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__USBH3_H3_DP IOMUX_PAD(0x500, 0x124, 0x17, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_RB2__USBH3_NXT IOMUX_PAD(0x500, 0x124, 6, 0xa20, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_RB3__DISP1_WAIT IOMUX_PAD(0x504, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_RB3__ECSPI2_MISO IOMUX_PAD(0x504, 0x128, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
@@ -270,7 +270,7 @@
#define MX51_PAD_NANDF_RB3__GPIO3_11 IOMUX_PAD(0x504, 0x128, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_NANDF_RB3__NANDF_RB3 IOMUX_PAD(0x504, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_RB3__USBH3_CLK IOMUX_PAD(0x504, 0x128, 6, 0x9f8, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__USBH3_H3_DM IOMUX_PAD(0x504, 0x128, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__USBH3_H3_DM IOMUX_PAD(0x504, 0x128, 0x17, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_GPIO_NAND__GPIO_NAND IOMUX_PAD(0x514, 0x12c, 0, 0x998, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_GPIO_NAND__PATA_INTRQ IOMUX_PAD(0x514, 0x12c, 1, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_CS0__GPIO3_16 IOMUX_PAD(0x518, 0x130, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
@@ -283,13 +283,13 @@
#define MX51_PAD_NANDF_CS2__NANDF_CS2 IOMUX_PAD(0x520, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_CS2__PATA_CS_0 IOMUX_PAD(0x520, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_CS2__SD4_CLK IOMUX_PAD(0x520, 0x138, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_NANDF_CS2__USBH3_H1_DP IOMUX_PAD(0x520, 0x138, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__USBH3_H1_DP IOMUX_PAD(0x520, 0x138, 0x17, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_CS3__FEC_MDC IOMUX_PAD(0x524, 0x13c, 2, __NA_, 0, MX51_PAD_CTRL_5)
#define MX51_PAD_NANDF_CS3__GPIO3_19 IOMUX_PAD(0x524, 0x13c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_NANDF_CS3__NANDF_CS3 IOMUX_PAD(0x524, 0x13c, 0, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_CS3__PATA_CS_1 IOMUX_PAD(0x524, 0x13c, 1, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_CS3__SD4_DAT0 IOMUX_PAD(0x524, 0x13c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__USBH3_H1_DM IOMUX_PAD(0x524, 0x13c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__USBH3_H1_DM IOMUX_PAD(0x524, 0x13c, 0x17, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_CS4__FEC_TDATA1 IOMUX_PAD(0x528, 0x140, 2, __NA_, 0, MX51_PAD_CTRL_5)
#define MX51_PAD_NANDF_CS4__GPIO3_20 IOMUX_PAD(0x528, 0x140, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_NANDF_CS4__NANDF_CS4 IOMUX_PAD(0x528, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
@@ -316,7 +316,7 @@
#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK IOMUX_PAD(0x538, 0x150, 1, 0x974, 0, MX51_PAD_CTRL_4)
#define MX51_PAD_NANDF_RDY_INT__GPIO3_24 IOMUX_PAD(0x538, 0x150, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT IOMUX_PAD(0x538, 0x150, 0, 0x938, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RDY_INT__SD3_CMD IOMUX_PAD(0x538, 0x150, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__SD3_CMD IOMUX_PAD(0x538, 0x150, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL)
#define MX51_PAD_NANDF_D15__ECSPI2_MOSI IOMUX_PAD(0x53c, 0x154, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
#define MX51_PAD_NANDF_D15__GPIO3_25 IOMUX_PAD(0x53c, 0x154, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_NANDF_D15__NANDF_D15 IOMUX_PAD(0x53c, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
@@ -672,23 +672,23 @@
#define MX51_PAD_DISP2_DAT5__DISP2_DAT5 IOMUX_PAD(0x770, 0x368, 0, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT6__DISP2_DAT6 IOMUX_PAD(0x774, 0x36c, 0, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT6__FEC_TDATA1 IOMUX_PAD(0x774, 0x36c, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT6__GPIO1_19 IOMUX_PAD(0x774, 0x36c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__GPIO1_19 IOMUX_PAD(0x774, 0x36c, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT6__KEY_ROW4 IOMUX_PAD(0x774, 0x36c, 4, 0x9d0, 1, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT6__USBH3_STP IOMUX_PAD(0x774, 0x36c, 3, 0xa24, 1, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT7__DISP2_DAT7 IOMUX_PAD(0x778, 0x370, 0, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT7__FEC_TDATA2 IOMUX_PAD(0x778, 0x370, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT7__GPIO1_29 IOMUX_PAD(0x778, 0x370, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__GPIO1_29 IOMUX_PAD(0x778, 0x370, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT7__KEY_ROW5 IOMUX_PAD(0x778, 0x370, 4, 0x9d4, 1, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT7__USBH3_NXT IOMUX_PAD(0x778, 0x370, 3, 0xa20, 1, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT8__DISP2_DAT8 IOMUX_PAD(0x77c, 0x374, 0, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT8__FEC_TDATA3 IOMUX_PAD(0x77c, 0x374, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT8__GPIO1_30 IOMUX_PAD(0x77c, 0x374, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__GPIO1_30 IOMUX_PAD(0x77c, 0x374, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT8__KEY_ROW6 IOMUX_PAD(0x77c, 0x374, 4, 0x9d8, 1, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT8__USBH3_DATA0 IOMUX_PAD(0x77c, 0x374, 3, 0x9fc, 1, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT9__AUD6_RXC IOMUX_PAD(0x780, 0x378, 4, 0x8f4, 1, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT9__DISP2_DAT9 IOMUX_PAD(0x780, 0x378, 0, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT9__FEC_TX_EN IOMUX_PAD(0x780, 0x378, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT9__GPIO1_31 IOMUX_PAD(0x780, 0x378, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__GPIO1_31 IOMUX_PAD(0x780, 0x378, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT9__USBH3_DATA1 IOMUX_PAD(0x780, 0x378, 3, 0xa00, 1, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT10__DISP2_DAT10 IOMUX_PAD(0x784, 0x37c, 0, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS IOMUX_PAD(0x784, 0x37c, 5, __NA_, 0, NO_PAD_CTRL)
@@ -698,7 +698,7 @@
#define MX51_PAD_DISP2_DAT11__AUD6_TXD IOMUX_PAD(0x788, 0x380, 4, 0x8f0, 1, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT11__DISP2_DAT11 IOMUX_PAD(0x788, 0x380, 0, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK IOMUX_PAD(0x788, 0x380, 2, 0x968, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__GPIO1_10 IOMUX_PAD(0x788, 0x380, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__GPIO1_10 IOMUX_PAD(0x788, 0x380, 7, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT11__USBH3_DATA3 IOMUX_PAD(0x788, 0x380, 3, 0xa08, 1, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT12__AUD6_RXD IOMUX_PAD(0x78c, 0x384, 4, 0x8ec, 1, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT12__DISP2_DAT12 IOMUX_PAD(0x78c, 0x384, 0, __NA_, 0, NO_PAD_CTRL)
@@ -746,16 +746,16 @@
#define MX51_PAD_SD1_DATA3__CSPI_SS1 IOMUX_PAD(0x7b0, 0x3a8, 2, 0x920, 1, MX51_ECSPI_PAD_CTRL)
#define MX51_PAD_SD1_DATA3__SD1_DATA3 IOMUX_PAD(0x7b0, 0x3a8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
#define MX51_PAD_GPIO1_0__CSPI_SS2 IOMUX_PAD(0x7b4, 0x3ac, 2, 0x924, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_GPIO1_0__GPIO1_0 IOMUX_PAD(0x7b4, 0x3ac, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__GPIO1_0 IOMUX_PAD(0x7b4, 0x3ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_GPIO1_0__SD1_CD IOMUX_PAD(0x7b4, 0x3ac, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
#define MX51_PAD_GPIO1_1__CSPI_MISO IOMUX_PAD(0x7b8, 0x3b0, 2, 0x918, 2, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_GPIO1_1__GPIO1_1 IOMUX_PAD(0x7b8, 0x3b0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__GPIO1_1 IOMUX_PAD(0x7b8, 0x3b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_GPIO1_1__SD1_WP IOMUX_PAD(0x7b8, 0x3b0, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
#define MX51_PAD_EIM_DA12__EIM_DA12 IOMUX_PAD(__NA_, 0x04c, 0, 0x000, 0, NO_PAD_CTRL)
#define MX51_PAD_EIM_DA13__EIM_DA13 IOMUX_PAD(__NA_, 0x050, 0, 0x000, 0, NO_PAD_CTRL)
#define MX51_PAD_EIM_DA14__EIM_DA14 IOMUX_PAD(__NA_, 0x054, 0, 0x000, 0, NO_PAD_CTRL)
#define MX51_PAD_EIM_DA15__EIM_DA15 IOMUX_PAD(__NA_, 0x058, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__CSPI_MOSI IOMUX_PAD(__NA_, 0x3b4, 2, 0x91c, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__CSPI_MOSI IOMUX_PAD(0x7bc, 0x3b4, 2, 0x91c, 3, MX51_ECSPI_PAD_CTRL)
#define MX51_PAD_SD2_CMD__I2C1_SCL IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x9b0, 2, MX51_I2C_PAD_CTRL)
#define MX51_PAD_SD2_CMD__SD2_CMD IOMUX_PAD(0x7bc, 0x3b4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
#define MX51_PAD_SD2_CLK__CSPI_SCLK IOMUX_PAD(0x7c0, 0x3b8, 2, 0x914, 3, MX51_ECSPI_PAD_CTRL)
@@ -766,19 +766,19 @@
#define MX51_PAD_SD2_DATA0__SD2_DATA0 IOMUX_PAD(0x7c4, 0x3bc, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
#define MX51_PAD_SD2_DATA1__SD1_DAT5 IOMUX_PAD(0x7c8, 0x3c0, 1, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_SD2_DATA1__SD2_DATA1 IOMUX_PAD(0x7c8, 0x3c0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__USBH3_H2_DP IOMUX_PAD(0x7c8, 0x3c0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__USBH3_H2_DP IOMUX_PAD(0x7c8, 0x3c0, 0x12, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_SD2_DATA2__SD1_DAT6 IOMUX_PAD(0x7cc, 0x3c4, 1, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_SD2_DATA2__SD2_DATA2 IOMUX_PAD(0x7cc, 0x3c4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__USBH3_H2_DM IOMUX_PAD(0x7cc, 0x3c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__USBH3_H2_DM IOMUX_PAD(0x7cc, 0x3c4, 0x12, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_SD2_DATA3__CSPI_SS2 IOMUX_PAD(0x7d0, 0x3c8, 2, 0x924, 1, MX51_ECSPI_PAD_CTRL)
#define MX51_PAD_SD2_DATA3__SD1_DAT7 IOMUX_PAD(0x7d0, 0x3c8, 1, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_SD2_DATA3__SD2_DATA3 IOMUX_PAD(0x7d0, 0x3c8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
#define MX51_PAD_GPIO1_2__CCM_OUT_2 IOMUX_PAD(0x7d4, 0x3cc, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__GPIO1_2 IOMUX_PAD(0x7d4, 0x3cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__GPIO1_2 IOMUX_PAD(0x7d4, 0x3cc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_GPIO1_2__I2C2_SCL IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x9b8, 3, MX51_I2C_PAD_CTRL)
#define MX51_PAD_GPIO1_2__PLL1_BYP IOMUX_PAD(0x7d4, 0x3cc, 7, 0x90c, 1, NO_PAD_CTRL)
#define MX51_PAD_GPIO1_2__PWM1_PWMO IOMUX_PAD(0x7d4, 0x3cc, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__GPIO1_3 IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__GPIO1_3 IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_GPIO1_3__I2C2_SDA IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x9bc, 3, MX51_I2C_PAD_CTRL)
#define MX51_PAD_GPIO1_3__PLL2_BYP IOMUX_PAD(0x7d8, 0x3d0, 7, 0x910, 1, NO_PAD_CTRL)
#define MX51_PAD_GPIO1_3__PWM2_PWMO IOMUX_PAD(0x7d8, 0x3d0, 1, __NA_, 0, NO_PAD_CTRL)
@@ -786,27 +786,27 @@
#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B IOMUX_PAD(0x7fc, 0x3d4, 1, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK IOMUX_PAD(0x804, 0x3d8, 4, 0x908, 1, NO_PAD_CTRL)
#define MX51_PAD_GPIO1_4__EIM_RDY IOMUX_PAD(0x804, 0x3d8, 3, 0x938, 1, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__GPIO1_4 IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__GPIO1_4 IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B IOMUX_PAD(0x804, 0x3d8, 2, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_GPIO1_5__CSI2_MCLK IOMUX_PAD(0x808, 0x3dc, 6, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_GPIO1_5__DISP2_PIN16 IOMUX_PAD(0x808, 0x3dc, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__GPIO1_5 IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__GPIO1_5 IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B IOMUX_PAD(0x808, 0x3dc, 2, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_GPIO1_6__DISP2_PIN17 IOMUX_PAD(0x80c, 0x3e0, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_6__GPIO1_6 IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__GPIO1_6 IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_GPIO1_6__REF_EN_B IOMUX_PAD(0x80c, 0x3e0, 3, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_GPIO1_7__CCM_OUT_0 IOMUX_PAD(0x810, 0x3e4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_7__GPIO1_7 IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__GPIO1_7 IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_GPIO1_7__SD2_WP IOMUX_PAD(0x810, 0x3e4, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
#define MX51_PAD_GPIO1_7__SPDIF_OUT1 IOMUX_PAD(0x810, 0x3e4, 2, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_GPIO1_8__CSI2_DATA_EN IOMUX_PAD(0x814, 0x3e8, 2, 0x99c, 2, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__GPIO1_8 IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__GPIO1_8 IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_GPIO1_8__SD2_CD IOMUX_PAD(0x814, 0x3e8, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
#define MX51_PAD_GPIO1_8__USBH3_PWR IOMUX_PAD(0x814, 0x3e8, 1, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_GPIO1_9__CCM_OUT_1 IOMUX_PAD(0x818, 0x3ec, 3, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_GPIO1_9__DISP2_D1_CS IOMUX_PAD(0x818, 0x3ec, 2, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_GPIO1_9__DISP2_SER_CS IOMUX_PAD(0x818, 0x3ec, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__GPIO1_9 IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__GPIO1_9 IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_GPIO1_9__SD2_LCTL IOMUX_PAD(0x818, 0x3ec, 6, __NA_, 0, NO_PAD_CTRL)
#define MX51_PAD_GPIO1_9__USBH3_OC IOMUX_PAD(0x818, 0x3ec, 1, __NA_, 0, NO_PAD_CTRL)
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx53.h b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
index 527f8fe3e31b..9761e003bde2 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx53.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
@@ -573,7 +573,7 @@
#define MX53_PAD_EIM_D28__UART2_CTS IOMUX_PAD(0x494, 0x14C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
#define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO IOMUX_PAD(0x494, 0x14C, 3, 0x82C, 1, NO_PAD_CTRL)
#define MX53_PAD_EIM_D28__CSPI_MOSI IOMUX_PAD(0x494, 0x14C, 4, 0x788, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D28__I2C1_SDA IOMUX_PAD(0x494, 0x14C, 5 | IOMUX_CONFIG_SION, 0x818, 1, PAD_CTRL_I2C)
+#define MX53_PAD_EIM_D28__I2C1_SDA IOMUX_PAD(0x494, 0x14C, 5 | IOMUX_CONFIG_SION, 0x818, 1, NO_PAD_CTRL)
#define MX53_PAD_EIM_D28__IPU_EXT_TRIG IOMUX_PAD(0x494, 0x14C, 6, __NA_, 0, NO_PAD_CTRL)
#define MX53_PAD_EIM_D28__IPU_DI0_PIN13 IOMUX_PAD(0x494, 0x14C, 7, __NA_, 0, NO_PAD_CTRL)
#define MX53_PAD_EIM_D29__EMI_WEIM_D_29 IOMUX_PAD(0x498, 0x150, 0, __NA_, 0, NO_PAD_CTRL)
@@ -1187,7 +1187,7 @@
#define MX53_PAD_GPIO_8__ESAI1_TX5_RX0 IOMUX_PAD(0x6C8, 0x338, 0, 0x7F8, 1, NO_PAD_CTRL)
#define MX53_PAD_GPIO_8__GPIO1_8 IOMUX_PAD(0x6C8, 0x338, 1, __NA_, 0, NO_PAD_CTRL)
#define MX53_PAD_GPIO_8__EPIT2_EPITO IOMUX_PAD(0x6C8, 0x338, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_8__CAN1_RXCAN IOMUX_PAD(0x6C8, 0x338, 3, 0x760, 3, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__CAN1_RXCAN IOMUX_PAD(0x6C8, 0x338, 3, 0x760, 2, NO_PAD_CTRL)
#define MX53_PAD_GPIO_8__UART2_RXD_MUX IOMUX_PAD(0x6C8, 0x338, 4, 0x880, 5, MX53_UART_PAD_CTRL)
#define MX53_PAD_GPIO_8__FIRI_TXD IOMUX_PAD(0x6C8, 0x338, 5, __NA_, 0, NO_PAD_CTRL)
#define MX53_PAD_GPIO_8__SPDIF_SRCLK IOMUX_PAD(0x6C8, 0x338, 6, __NA_, 0, NO_PAD_CTRL)
diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
index 9605bf227df9..826de74bfdd1 100644
--- a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
+++ b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
@@ -29,6 +29,7 @@
#define NMK_GPIO_SLPC 0x1c
#define NMK_GPIO_AFSLA 0x20
#define NMK_GPIO_AFSLB 0x24
+#define NMK_GPIO_LOWEMI 0x28
#define NMK_GPIO_RIMSC 0x40
#define NMK_GPIO_FIMSC 0x44
@@ -61,7 +62,14 @@ enum nmk_gpio_slpm {
extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
+#ifdef CONFIG_PINCTRL_NOMADIK
extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
+#else
+static inline int nmk_gpio_set_mode(int gpio, int gpio_mode)
+{
+ return -ENODEV;
+}
+#endif
extern int nmk_gpio_get_mode(int gpio);
extern void nmk_gpio_wakeups_suspend(void);
diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h
index 22cb97d2d8ad..9c949c7c98a7 100644
--- a/arch/arm/plat-nomadik/include/plat/pincfg.h
+++ b/arch/arm/plat-nomadik/include/plat/pincfg.h
@@ -24,6 +24,7 @@
* bit 16..18 - SLPM pull up/down state
* bit 19..20 - SLPM direction
* bit 21..22 - SLPM Value (if output)
+ * bit 23..25 - PDIS value (if input)
*
* to facilitate the definition, the following macros are provided
*
@@ -67,6 +68,10 @@ typedef unsigned long pin_cfg_t;
/* These two replace the above in DB8500v2+ */
#define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT)
#define PIN_SLPM_WAKEUP_DISABLE (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT)
+#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE
+
+#define PIN_SLPM_GPIO PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */
+#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */
#define PIN_DIR_SHIFT 14
#define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT)
@@ -105,6 +110,33 @@ typedef unsigned long pin_cfg_t;
#define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT)
#define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_PDIS_SHIFT 23
+#define PIN_SLPM_PDIS_MASK (0x3 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS(x) \
+ (((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_NO_CHANGE (0 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_DISABLED (1 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_ENABLED (2 << PIN_SLPM_PDIS_SHIFT)
+
+#define PIN_LOWEMI_SHIFT 25
+#define PIN_LOWEMI_MASK (0x1 << PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI(x) (((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI_DISABLED (0 << PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI_ENABLED (1 << PIN_LOWEMI_SHIFT)
+
+#define PIN_GPIOMODE_SHIFT 26
+#define PIN_GPIOMODE_MASK (0x1 << PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE(x) (((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE_DISABLED (0 << PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE_ENABLED (1 << PIN_GPIOMODE_SHIFT)
+
+#define PIN_SLEEPMODE_SHIFT 27
+#define PIN_SLEEPMODE_MASK (0x1 << PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE(x) (((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE_DISABLED (0 << PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE_ENABLED (1 << PIN_SLEEPMODE_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)
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index c0fe2757b695..ed8605f01155 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -9,9 +9,6 @@ obj-m :=
obj-n :=
obj- :=
-# OCPI interconnect support for 1710, 1610 and 5912
-obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
-
# omap_device support (OMAP2+ only at the moment)
obj-$(CONFIG_ARCH_OMAP2) += omap_device.o
obj-$(CONFIG_ARCH_OMAP3) += omap_device.o
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index f1e46ea6b81d..0a9b9a970113 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -20,6 +20,7 @@
#include <plat/board.h>
#include <plat/vram.h>
#include <plat/dsp.h>
+#include <plat/dma.h>
#include <plat/omap-secure.h>
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index 5068fe5a6910..44ae077dbc28 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -19,6 +19,7 @@
#include <linux/io.h>
#include <linux/clocksource.h>
+#include <asm/mach/time.h>
#include <asm/sched_clock.h>
#include <plat/hardware.h>
@@ -43,7 +44,7 @@ static u32 notrace omap_32k_read_sched_clock(void)
}
/**
- * read_persistent_clock - Return time from a persistent clock.
+ * omap_read_persistent_clock - Return time from a persistent clock.
*
* Reads the time from a source which isn't disabled during PM, the
* 32k sync timer. Convert the cycles elapsed since last read into
@@ -52,7 +53,7 @@ static u32 notrace omap_32k_read_sched_clock(void)
static struct timespec persistent_ts;
static cycles_t cycles, last_cycles;
static unsigned int persistent_mult, persistent_shift;
-void read_persistent_clock(struct timespec *ts)
+static void omap_read_persistent_clock(struct timespec *ts)
{
unsigned long long nsecs;
cycles_t delta;
@@ -116,6 +117,7 @@ int __init omap_init_clocksource_32k(void)
printk(err, "32k_counter");
setup_sched_clock(omap_32k_read_sched_clock, 32, 32768);
+ register_persistent_clock(NULL, omap_read_persistent_clock);
}
return 0;
}
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index 60278f47c0bd..09b07d252892 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -167,8 +167,8 @@ void __init omap_dsp_reserve_sdram_memblock(void)
paddr = arm_memblock_steal(size, SZ_1M);
if (!paddr) {
- pr_err("%s: failed to reserve %x bytes\n",
- __func__, size);
+ pr_err("%s: failed to reserve %llx bytes\n",
+ __func__, (unsigned long long)size);
return;
}
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index c58d896cd5c3..987e6101267d 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -41,6 +41,15 @@
#include <plat/tc.h>
+/*
+ * MAX_LOGICAL_DMA_CH_COUNT: the maximum number of logical DMA
+ * channels that an instance of the SDMA IP block can support. Used
+ * to size arrays. (The actual maximum on a particular SoC may be less
+ * than this -- for example, OMAP1 SDMA instances only support 17 logical
+ * DMA channels.)
+ */
+#define MAX_LOGICAL_DMA_CH_COUNT 32
+
#undef DEBUG
#ifndef CONFIG_ARCH_OMAP1
@@ -883,7 +892,7 @@ void omap_start_dma(int lch)
if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
int next_lch, cur_lch;
- char dma_chan_link_map[dma_lch_count];
+ char dma_chan_link_map[MAX_LOGICAL_DMA_CH_COUNT];
dma_chan_link_map[lch] = 1;
/* Set the link register of the first channel */
@@ -981,7 +990,7 @@ void omap_stop_dma(int lch)
if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
int next_lch, cur_lch = lch;
- char dma_chan_link_map[dma_lch_count];
+ char dma_chan_link_map[MAX_LOGICAL_DMA_CH_COUNT];
memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
do {
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 652139c0339e..c4ed35e89fbd 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -349,11 +349,12 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_start);
int omap_dm_timer_stop(struct omap_dm_timer *timer)
{
unsigned long rate = 0;
- struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+ struct dmtimer_platform_data *pdata;
if (unlikely(!timer))
return -EINVAL;
+ pdata = timer->pdev->dev.platform_data;
if (!pdata->needs_manual_reset)
rate = clk_get_rate(timer->fclk);
diff --git a/arch/arm/plat-omap/include/plat/board.h b/arch/arm/plat-omap/include/plat/board.h
index d5eb4c87db9d..4814c5b65306 100644
--- a/arch/arm/plat-omap/include/plat/board.h
+++ b/arch/arm/plat-omap/include/plat/board.h
@@ -91,6 +91,8 @@ struct omap_usb_config {
u32 (*usb0_init)(unsigned nwires, unsigned is_device);
u32 (*usb1_init)(unsigned nwires);
u32 (*usb2_init)(unsigned nwires, unsigned alt_pingroup);
+
+ int (*ocpi_enable)(void);
};
struct omap_lcd_config {
diff --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h b/arch/arm/plat-omap/include/plat/clkdev_omap.h
index b299b8d201c8..d0ed8c443a63 100644
--- a/arch/arm/plat-omap/include/plat/clkdev_omap.h
+++ b/arch/arm/plat-omap/include/plat/clkdev_omap.h
@@ -34,8 +34,7 @@ struct omap_clk {
#define CK_243X (1 << 5) /* 243x, 253x */
#define CK_3430ES1 (1 << 6) /* 34xxES1 only */
#define CK_3430ES2PLUS (1 << 7) /* 34xxES2, ES3, non-Sitara 35xx only */
-#define CK_3505 (1 << 8)
-#define CK_3517 (1 << 9)
+#define CK_AM35XX (1 << 9) /* Sitara AM35xx */
#define CK_36XX (1 << 10) /* 36xx/37xx-specific clocks */
#define CK_443X (1 << 11)
#define CK_TI816X (1 << 12)
@@ -44,7 +43,6 @@ struct omap_clk {
#define CK_34XX (CK_3430ES1 | CK_3430ES2PLUS)
-#define CK_AM35XX (CK_3505 | CK_3517) /* all Sitara AM35xx */
#define CK_3XXX (CK_34XX | CK_AM35XX | CK_36XX)
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
index b4d7ec3fbfbe..a557b8484e6c 100644
--- a/arch/arm/plat-omap/include/plat/common.h
+++ b/arch/arm/plat-omap/include/plat/common.h
@@ -32,6 +32,8 @@
extern int __init omap_init_clocksource_32k(void);
+extern void __init omap_check_revision(void);
+
extern void omap_reserve(void);
extern int omap_dss_reset(struct omap_hwmod *);
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index dc6a86bf2172..4bdf14ec6747 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -445,6 +445,7 @@ IS_OMAP_TYPE(3517, 0x3517)
#define OMAP446X_CLASS 0x44600044
#define OMAP4460_REV_ES1_0 (OMAP446X_CLASS | (0x10 << 8))
+#define OMAP4460_REV_ES1_1 (OMAP446X_CLASS | (0x11 << 8))
#define OMAP447X_CLASS 0x44700044
#define OMAP4470_REV_ES1_0 (OMAP447X_CLASS | (0x10 << 8))
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index dc562a5c0a8a..42afb4c45517 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -442,6 +442,7 @@ struct omap_system_dma_plat_info {
u32 (*dma_read)(int reg, int lch);
};
+extern void __init omap_init_consistent_dma_size(void);
extern void omap_set_dma_priority(int lch, int dst_port, int priority);
extern int omap_request_dma(int dev_id, const char *dev_name,
void (*callback)(int lch, u16 ch_status, void *data),
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 9418f00b6c38..bdf871a84d62 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -259,7 +259,7 @@ struct omap_dm_timer {
unsigned long phys_base;
int id;
int irq;
- struct clk *iclk, *fclk;
+ struct clk *fclk;
void __iomem *io_base;
void __iomem *sys_stat; /* TISTAT timer status */
@@ -316,12 +316,12 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
OMAP_TIMER_V1_SYS_STAT_OFFSET;
timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
- timer->irq_dis = 0;
+ timer->irq_dis = NULL;
timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;
timer->func_base = timer->io_base;
} else {
timer->revision = 2;
- timer->sys_stat = 0;
+ timer->sys_stat = NULL;
timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR;
diff --git a/arch/arm/plat-omap/include/plat/hdq1w.h b/arch/arm/plat-omap/include/plat/hdq1w.h
new file mode 100644
index 000000000000..0c1efc846d8d
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/hdq1w.h
@@ -0,0 +1,36 @@
+/*
+ * Shared macros and function prototypes for the HDQ1W/1-wire IP block
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#ifndef ARCH_ARM_MACH_OMAP2_HDQ1W_H
+#define ARCH_ARM_MACH_OMAP2_HDQ1W_H
+
+#include <plat/omap_hwmod.h>
+
+/*
+ * XXX A future cleanup patch should modify
+ * drivers/w1/masters/omap_hdq.c to use these macros
+ */
+#define HDQ_CTRL_STATUS_OFFSET 0x0c
+#define HDQ_CTRL_STATUS_CLOCKENABLE_SHIFT 5
+
+
+extern int omap_hdq1w_reset(struct omap_hwmod *oh);
+
+#endif
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index 7a38750c0079..3e7ae0f0215f 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -16,6 +16,7 @@
#include <linux/mmc/host.h>
#include <plat/board.h>
+#include <plat/omap_hwmod.h>
#define OMAP15XX_NR_MMC 1
#define OMAP16XX_NR_MMC 2
@@ -195,4 +196,7 @@ static inline int omap_mmc_add(const char *name, int id, unsigned long base,
}
#endif
+
+extern int omap_msdi_reset(struct omap_hwmod *oh);
+
#endif
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 9ff444469f3d..1a52725ffcf2 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -65,7 +65,6 @@ struct omap_uart_port_info {
bool dma_enabled; /* To specify DMA Mode */
unsigned int uartclk; /* UART clock rate */
upf_t flags; /* UPF_* flags */
- u32 errata;
unsigned int dma_rx_buf_size;
unsigned int dma_rx_timeout;
unsigned int autosuspend_timeout;
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 3f26db4ee8e6..c835b7194ff5 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -213,11 +213,17 @@ struct omap_hwmod_addr_space {
*/
#define OCP_USER_MPU (1 << 0)
#define OCP_USER_SDMA (1 << 1)
+#define OCP_USER_DSP (1 << 2)
+#define OCP_USER_IVA (1 << 3)
/* omap_hwmod_ocp_if.flags bits */
#define OCPIF_SWSUP_IDLE (1 << 0)
#define OCPIF_CAN_BURST (1 << 1)
+/* omap_hwmod_ocp_if._int_flags possibilities */
+#define _OCPIF_INT_FLAGS_REGISTERED (1 << 0)
+
+
/**
* struct omap_hwmod_ocp_if - OCP interface data
* @master: struct omap_hwmod that initiates OCP transactions on this link
@@ -229,6 +235,7 @@ struct omap_hwmod_addr_space {
* @width: OCP data width
* @user: initiators using this interface (see OCP_USER_* macros above)
* @flags: OCP interface flags (see OCPIF_* macros above)
+ * @_int_flags: internal flags (see _OCPIF_INT_FLAGS* macros above)
*
* It may also be useful to add a tag_cnt field for OCP2.x devices.
*
@@ -247,6 +254,7 @@ struct omap_hwmod_ocp_if {
u8 width;
u8 user;
u8 flags;
+ u8 _int_flags;
};
@@ -327,9 +335,9 @@ struct omap_hwmod_sysc_fields {
* then this field has to be populated with the correct offset structure.
*/
struct omap_hwmod_class_sysconfig {
- u16 rev_offs;
- u16 sysc_offs;
- u16 syss_offs;
+ u32 rev_offs;
+ u32 sysc_offs;
+ u32 syss_offs;
u16 sysc_flags;
struct omap_hwmod_sysc_fields *sysc_fields;
u8 srst_udelay;
@@ -476,6 +484,16 @@ struct omap_hwmod_class {
};
/**
+ * struct omap_hwmod_link - internal structure linking hwmods with ocp_ifs
+ * @ocp_if: OCP interface structure record pointer
+ * @node: list_head pointing to next struct omap_hwmod_link in a list
+ */
+struct omap_hwmod_link {
+ struct omap_hwmod_ocp_if *ocp_if;
+ struct list_head node;
+};
+
+/**
* struct omap_hwmod - integration data for OMAP hardware "modules" (IP blocks)
* @name: name of the hwmod
* @class: struct omap_hwmod_class * to the class of this hwmod
@@ -487,12 +505,10 @@ struct omap_hwmod_class {
* @_clk: pointer to the main struct clk (filled in at runtime)
* @opt_clks: other device clocks that drivers can request (0..*)
* @voltdm: pointer to voltage domain (filled in at runtime)
- * @masters: ptr to array of OCP ifs that this hwmod can initiate on
- * @slaves: ptr to array of OCP ifs that this hwmod can respond on
* @dev_attr: arbitrary device attributes that can be passed to the driver
* @_sysc_cache: internal-use hwmod flags
* @_mpu_rt_va: cached register target start address (internal use)
- * @_mpu_port_index: cached MPU register target slave ID (internal use)
+ * @_mpu_port: cached MPU register target slave (internal use)
* @opt_clks_cnt: number of @opt_clks
* @master_cnt: number of @master entries
* @slaves_cnt: number of @slave entries
@@ -511,6 +527,8 @@ struct omap_hwmod_class {
*
* Parameter names beginning with an underscore are managed internally by
* the omap_hwmod code and should not be set during initialization.
+ *
+ * @masters and @slaves are now deprecated.
*/
struct omap_hwmod {
const char *name;
@@ -529,15 +547,15 @@ struct omap_hwmod {
struct omap_hwmod_opt_clk *opt_clks;
char *clkdm_name;
struct clockdomain *clkdm;
- struct omap_hwmod_ocp_if **masters; /* connect to *_IA */
- struct omap_hwmod_ocp_if **slaves; /* connect to *_TA */
+ struct list_head master_ports; /* connect to *_IA */
+ struct list_head slave_ports; /* connect to *_TA */
void *dev_attr;
u32 _sysc_cache;
void __iomem *_mpu_rt_va;
spinlock_t _lock;
struct list_head node;
+ struct omap_hwmod_ocp_if *_mpu_port;
u16 flags;
- u8 _mpu_port_index;
u8 response_lat;
u8 rst_lines_cnt;
u8 opt_clks_cnt;
@@ -549,7 +567,6 @@ struct omap_hwmod {
u8 _postsetup_state;
};
-int omap_hwmod_register(struct omap_hwmod **ohs);
struct omap_hwmod *omap_hwmod_lookup(const char *name);
int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
void *data);
@@ -581,6 +598,8 @@ int omap_hwmod_softreset(struct omap_hwmod *oh);
int omap_hwmod_count_resources(struct omap_hwmod *oh);
int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
+int omap_hwmod_get_resource_byname(struct omap_hwmod *oh, unsigned int type,
+ const char *name, struct resource *res);
struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh);
void __iomem *omap_hwmod_get_mpu_rt_va(struct omap_hwmod *oh);
@@ -619,4 +638,6 @@ extern int omap2430_hwmod_init(void);
extern int omap3xxx_hwmod_init(void);
extern int omap44xx_hwmod_init(void);
+extern int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois);
+
#endif
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index d50cbc6385bd..c490240bb82c 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -475,13 +475,11 @@ static int omap_device_count_resources(struct omap_device *od)
static int omap_device_fill_resources(struct omap_device *od,
struct resource *res)
{
- int c = 0;
int i, r;
for (i = 0; i < od->hwmods_cnt; i++) {
r = omap_hwmod_fill_resources(od->hwmods[i], res);
res += r;
- c += r;
}
return 0;
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index f9a8c5341ee9..477363c163ec 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -196,8 +196,8 @@ static void __init omap_map_sram(void)
* Looks like we need to preserve some bootloader code at the
* beginning of SRAM for jumping to flash for reboot to work...
*/
- memset((void *)omap_sram_base + SRAM_BOOTLOADER_SZ, 0,
- omap_sram_size - SRAM_BOOTLOADER_SZ);
+ memset_io(omap_sram_base + SRAM_BOOTLOADER_SZ, 0,
+ omap_sram_size - SRAM_BOOTLOADER_SZ);
}
/*
diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c
index d2bbfd1cb0b5..daa0327381b5 100644
--- a/arch/arm/plat-omap/usb.c
+++ b/arch/arm/plat-omap/usb.c
@@ -31,15 +31,12 @@
#include <mach/hardware.h>
-#include "../mach-omap2/common.h"
-
#ifdef CONFIG_ARCH_OMAP_OTG
void __init
omap_otg_init(struct omap_usb_config *config)
{
u32 syscon;
- int status;
int alt_pingroup = 0;
/* NOTE: no bus or clock setup (yet?) */
@@ -104,6 +101,7 @@ omap_otg_init(struct omap_usb_config *config)
#ifdef CONFIG_USB_GADGET_OMAP
if (config->otg || config->register_dev) {
struct platform_device *udc_device = config->udc_device;
+ int status;
syscon &= ~DEV_IDLE_EN;
udc_device->dev.platform_data = config;
@@ -116,6 +114,7 @@ omap_otg_init(struct omap_usb_config *config)
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
if (config->otg || config->register_host) {
struct platform_device *ohci_device = config->ohci_device;
+ int status;
syscon &= ~HST_IDLE_EN;
ohci_device->dev.platform_data = config;
@@ -128,6 +127,7 @@ omap_otg_init(struct omap_usb_config *config)
#ifdef CONFIG_USB_OTG
if (config->otg) {
struct platform_device *otg_device = config->otg_device;
+ int status;
syscon &= ~OTG_IDLE_EN;
otg_device->dev.platform_data = config;
@@ -138,8 +138,6 @@ omap_otg_init(struct omap_usb_config *config)
#endif
pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1));
omap_writel(syscon, OTG_SYSCON_1);
-
- status = 0;
}
#else
diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
index 10d160888133..af95af257301 100644
--- a/arch/arm/plat-orion/gpio.c
+++ b/arch/arm/plat-orion/gpio.c
@@ -16,6 +16,7 @@
#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/gpio.h>
+#include <linux/leds.h>
/*
* GPIO unit register offsets.
@@ -289,12 +290,34 @@ void orion_gpio_set_blink(unsigned pin, int blink)
return;
spin_lock_irqsave(&ochip->lock, flags);
- __set_level(ochip, pin, 0);
- __set_blinking(ochip, pin, blink);
+ __set_level(ochip, pin & 31, 0);
+ __set_blinking(ochip, pin & 31, blink);
spin_unlock_irqrestore(&ochip->lock, flags);
}
EXPORT_SYMBOL(orion_gpio_set_blink);
+#define ORION_BLINK_HALF_PERIOD 100 /* ms */
+
+int orion_gpio_led_blink_set(unsigned gpio, int state,
+ unsigned long *delay_on, unsigned long *delay_off)
+{
+
+ if (delay_on && delay_off && !*delay_on && !*delay_off)
+ *delay_on = *delay_off = ORION_BLINK_HALF_PERIOD;
+
+ switch (state) {
+ case GPIO_LED_NO_BLINK_LOW:
+ case GPIO_LED_NO_BLINK_HIGH:
+ orion_gpio_set_blink(gpio, 0);
+ gpio_set_value(gpio, state);
+ break;
+ case GPIO_LED_BLINK:
+ orion_gpio_set_blink(gpio, 1);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(orion_gpio_led_blink_set);
+
/*****************************************************************************
* Orion GPIO IRQ
diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h
index 3abf30428bee..bec0c98ce41f 100644
--- a/arch/arm/plat-orion/include/plat/gpio.h
+++ b/arch/arm/plat-orion/include/plat/gpio.h
@@ -19,6 +19,8 @@
*/
void orion_gpio_set_unused(unsigned pin);
void orion_gpio_set_blink(unsigned pin, int blink);
+int orion_gpio_led_blink_set(unsigned gpio, int state,
+ unsigned long *delay_on, unsigned long *delay_off);
#define GPIO_INPUT_OK (1 << 0)
#define GPIO_OUTPUT_OK (1 << 1)
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 8b928f9bc1c3..1d214cb9d770 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -30,6 +30,7 @@
#include <linux/mmc/host.h>
#include <linux/ioport.h>
#include <linux/platform_data/s3c-hsudc.h>
+#include <linux/platform_data/s3c-hsotg.h>
#include <asm/irq.h>
#include <asm/pmu.h>
@@ -57,7 +58,6 @@
#include <plat/sdhci.h>
#include <plat/ts.h>
#include <plat/udc.h>
-#include <plat/udc-hs.h>
#include <plat/usb-control.h>
#include <plat/usb-phy.h>
#include <plat/regs-iic.h>
@@ -272,16 +272,8 @@ struct platform_device s5p_device_fimc3 = {
#ifdef CONFIG_S5P_DEV_G2D
static struct resource s5p_g2d_resource[] = {
- [0] = {
- .start = S5P_PA_G2D,
- .end = S5P_PA_G2D + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_2D,
- .end = IRQ_2D,
- .flags = IORESOURCE_IRQ,
- },
+ [0] = DEFINE_RES_MEM(S5P_PA_G2D, SZ_4K),
+ [1] = DEFINE_RES_IRQ(IRQ_2D),
};
struct platform_device s5p_device_g2d = {
@@ -370,7 +362,6 @@ struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = {
.max_width = 4,
.host_caps = (MMC_CAP_4_BIT_DATA |
MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
- .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL,
};
struct platform_device s3c_device_hsmmc0 = {
@@ -401,7 +392,6 @@ struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = {
.max_width = 4,
.host_caps = (MMC_CAP_4_BIT_DATA |
MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
- .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL,
};
struct platform_device s3c_device_hsmmc1 = {
@@ -434,7 +424,6 @@ struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata = {
.max_width = 4,
.host_caps = (MMC_CAP_4_BIT_DATA |
MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
- .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL,
};
struct platform_device s3c_device_hsmmc2 = {
@@ -465,7 +454,6 @@ struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = {
.max_width = 4,
.host_caps = (MMC_CAP_4_BIT_DATA |
MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
- .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL,
};
struct platform_device s3c_device_hsmmc3 = {
diff --git a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
deleted file mode 100644
index dc90f5ede88f..000000000000
--- a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/regs-usb-hsotg.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C - USB2.0 Highspeed/OtG device block registers
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __PLAT_S3C64XX_REGS_USB_HSOTG_H
-#define __PLAT_S3C64XX_REGS_USB_HSOTG_H __FILE__
-
-#define S3C_HSOTG_REG(x) (x)
-
-#define S3C_GOTGCTL S3C_HSOTG_REG(0x000)
-#define S3C_GOTGCTL_BSESVLD (1 << 19)
-#define S3C_GOTGCTL_ASESVLD (1 << 18)
-#define S3C_GOTGCTL_DBNC_SHORT (1 << 17)
-#define S3C_GOTGCTL_CONID_B (1 << 16)
-#define S3C_GOTGCTL_DEVHNPEN (1 << 11)
-#define S3C_GOTGCTL_HSSETHNPEN (1 << 10)
-#define S3C_GOTGCTL_HNPREQ (1 << 9)
-#define S3C_GOTGCTL_HSTNEGSCS (1 << 8)
-#define S3C_GOTGCTL_SESREQ (1 << 1)
-#define S3C_GOTGCTL_SESREQSCS (1 << 0)
-
-#define S3C_GOTGINT S3C_HSOTG_REG(0x004)
-#define S3C_GOTGINT_DbnceDone (1 << 19)
-#define S3C_GOTGINT_ADevTOUTChg (1 << 18)
-#define S3C_GOTGINT_HstNegDet (1 << 17)
-#define S3C_GOTGINT_HstnegSucStsChng (1 << 9)
-#define S3C_GOTGINT_SesReqSucStsChng (1 << 8)
-#define S3C_GOTGINT_SesEndDet (1 << 2)
-
-#define S3C_GAHBCFG S3C_HSOTG_REG(0x008)
-#define S3C_GAHBCFG_PTxFEmpLvl (1 << 8)
-#define S3C_GAHBCFG_NPTxFEmpLvl (1 << 7)
-#define S3C_GAHBCFG_DMAEn (1 << 5)
-#define S3C_GAHBCFG_HBstLen_MASK (0xf << 1)
-#define S3C_GAHBCFG_HBstLen_SHIFT (1)
-#define S3C_GAHBCFG_HBstLen_Single (0x0 << 1)
-#define S3C_GAHBCFG_HBstLen_Incr (0x1 << 1)
-#define S3C_GAHBCFG_HBstLen_Incr4 (0x3 << 1)
-#define S3C_GAHBCFG_HBstLen_Incr8 (0x5 << 1)
-#define S3C_GAHBCFG_HBstLen_Incr16 (0x7 << 1)
-#define S3C_GAHBCFG_GlblIntrEn (1 << 0)
-
-#define S3C_GUSBCFG S3C_HSOTG_REG(0x00C)
-#define S3C_GUSBCFG_PHYLPClkSel (1 << 15)
-#define S3C_GUSBCFG_HNPCap (1 << 9)
-#define S3C_GUSBCFG_SRPCap (1 << 8)
-#define S3C_GUSBCFG_PHYIf16 (1 << 3)
-#define S3C_GUSBCFG_TOutCal_MASK (0x7 << 0)
-#define S3C_GUSBCFG_TOutCal_SHIFT (0)
-#define S3C_GUSBCFG_TOutCal_LIMIT (0x7)
-#define S3C_GUSBCFG_TOutCal(_x) ((_x) << 0)
-
-#define S3C_GRSTCTL S3C_HSOTG_REG(0x010)
-
-#define S3C_GRSTCTL_AHBIdle (1 << 31)
-#define S3C_GRSTCTL_DMAReq (1 << 30)
-#define S3C_GRSTCTL_TxFNum_MASK (0x1f << 6)
-#define S3C_GRSTCTL_TxFNum_SHIFT (6)
-#define S3C_GRSTCTL_TxFNum_LIMIT (0x1f)
-#define S3C_GRSTCTL_TxFNum(_x) ((_x) << 6)
-#define S3C_GRSTCTL_TxFFlsh (1 << 5)
-#define S3C_GRSTCTL_RxFFlsh (1 << 4)
-#define S3C_GRSTCTL_INTknQFlsh (1 << 3)
-#define S3C_GRSTCTL_FrmCntrRst (1 << 2)
-#define S3C_GRSTCTL_HSftRst (1 << 1)
-#define S3C_GRSTCTL_CSftRst (1 << 0)
-
-#define S3C_GINTSTS S3C_HSOTG_REG(0x014)
-#define S3C_GINTMSK S3C_HSOTG_REG(0x018)
-
-#define S3C_GINTSTS_WkUpInt (1 << 31)
-#define S3C_GINTSTS_SessReqInt (1 << 30)
-#define S3C_GINTSTS_DisconnInt (1 << 29)
-#define S3C_GINTSTS_ConIDStsChng (1 << 28)
-#define S3C_GINTSTS_PTxFEmp (1 << 26)
-#define S3C_GINTSTS_HChInt (1 << 25)
-#define S3C_GINTSTS_PrtInt (1 << 24)
-#define S3C_GINTSTS_FetSusp (1 << 22)
-#define S3C_GINTSTS_incompIP (1 << 21)
-#define S3C_GINTSTS_IncomplSOIN (1 << 20)
-#define S3C_GINTSTS_OEPInt (1 << 19)
-#define S3C_GINTSTS_IEPInt (1 << 18)
-#define S3C_GINTSTS_EPMis (1 << 17)
-#define S3C_GINTSTS_EOPF (1 << 15)
-#define S3C_GINTSTS_ISOutDrop (1 << 14)
-#define S3C_GINTSTS_EnumDone (1 << 13)
-#define S3C_GINTSTS_USBRst (1 << 12)
-#define S3C_GINTSTS_USBSusp (1 << 11)
-#define S3C_GINTSTS_ErlySusp (1 << 10)
-#define S3C_GINTSTS_GOUTNakEff (1 << 7)
-#define S3C_GINTSTS_GINNakEff (1 << 6)
-#define S3C_GINTSTS_NPTxFEmp (1 << 5)
-#define S3C_GINTSTS_RxFLvl (1 << 4)
-#define S3C_GINTSTS_SOF (1 << 3)
-#define S3C_GINTSTS_OTGInt (1 << 2)
-#define S3C_GINTSTS_ModeMis (1 << 1)
-#define S3C_GINTSTS_CurMod_Host (1 << 0)
-
-#define S3C_GRXSTSR S3C_HSOTG_REG(0x01C)
-#define S3C_GRXSTSP S3C_HSOTG_REG(0x020)
-
-#define S3C_GRXSTS_FN_MASK (0x7f << 25)
-#define S3C_GRXSTS_FN_SHIFT (25)
-
-#define S3C_GRXSTS_PktSts_MASK (0xf << 17)
-#define S3C_GRXSTS_PktSts_SHIFT (17)
-#define S3C_GRXSTS_PktSts_GlobalOutNAK (0x1 << 17)
-#define S3C_GRXSTS_PktSts_OutRX (0x2 << 17)
-#define S3C_GRXSTS_PktSts_OutDone (0x3 << 17)
-#define S3C_GRXSTS_PktSts_SetupDone (0x4 << 17)
-#define S3C_GRXSTS_PktSts_SetupRX (0x6 << 17)
-
-#define S3C_GRXSTS_DPID_MASK (0x3 << 15)
-#define S3C_GRXSTS_DPID_SHIFT (15)
-#define S3C_GRXSTS_ByteCnt_MASK (0x7ff << 4)
-#define S3C_GRXSTS_ByteCnt_SHIFT (4)
-#define S3C_GRXSTS_EPNum_MASK (0xf << 0)
-#define S3C_GRXSTS_EPNum_SHIFT (0)
-
-#define S3C_GRXFSIZ S3C_HSOTG_REG(0x024)
-
-#define S3C_GNPTXFSIZ S3C_HSOTG_REG(0x028)
-
-#define S3C_GNPTXFSIZ_NPTxFDep_MASK (0xffff << 16)
-#define S3C_GNPTXFSIZ_NPTxFDep_SHIFT (16)
-#define S3C_GNPTXFSIZ_NPTxFDep_LIMIT (0xffff)
-#define S3C_GNPTXFSIZ_NPTxFDep(_x) ((_x) << 16)
-#define S3C_GNPTXFSIZ_NPTxFStAddr_MASK (0xffff << 0)
-#define S3C_GNPTXFSIZ_NPTxFStAddr_SHIFT (0)
-#define S3C_GNPTXFSIZ_NPTxFStAddr_LIMIT (0xffff)
-#define S3C_GNPTXFSIZ_NPTxFStAddr(_x) ((_x) << 0)
-
-#define S3C_GNPTXSTS S3C_HSOTG_REG(0x02C)
-
-#define S3C_GNPTXSTS_NPtxQTop_MASK (0x7f << 24)
-#define S3C_GNPTXSTS_NPtxQTop_SHIFT (24)
-
-#define S3C_GNPTXSTS_NPTxQSpcAvail_MASK (0xff << 16)
-#define S3C_GNPTXSTS_NPTxQSpcAvail_SHIFT (16)
-#define S3C_GNPTXSTS_NPTxQSpcAvail_GET(_v) (((_v) >> 16) & 0xff)
-
-#define S3C_GNPTXSTS_NPTxFSpcAvail_MASK (0xffff << 0)
-#define S3C_GNPTXSTS_NPTxFSpcAvail_SHIFT (0)
-#define S3C_GNPTXSTS_NPTxFSpcAvail_GET(_v) (((_v) >> 0) & 0xffff)
-
-
-#define S3C_HPTXFSIZ S3C_HSOTG_REG(0x100)
-
-#define S3C_DPTXFSIZn(_a) S3C_HSOTG_REG(0x104 + (((_a) - 1) * 4))
-
-#define S3C_DPTXFSIZn_DPTxFSize_MASK (0xffff << 16)
-#define S3C_DPTXFSIZn_DPTxFSize_SHIFT (16)
-#define S3C_DPTXFSIZn_DPTxFSize_GET(_v) (((_v) >> 16) & 0xffff)
-#define S3C_DPTXFSIZn_DPTxFSize_LIMIT (0xffff)
-#define S3C_DPTXFSIZn_DPTxFSize(_x) ((_x) << 16)
-
-#define S3C_DPTXFSIZn_DPTxFStAddr_MASK (0xffff << 0)
-#define S3C_DPTXFSIZn_DPTxFStAddr_SHIFT (0)
-
-/* Device mode registers */
-#define S3C_DCFG S3C_HSOTG_REG(0x800)
-
-#define S3C_DCFG_EPMisCnt_MASK (0x1f << 18)
-#define S3C_DCFG_EPMisCnt_SHIFT (18)
-#define S3C_DCFG_EPMisCnt_LIMIT (0x1f)
-#define S3C_DCFG_EPMisCnt(_x) ((_x) << 18)
-
-#define S3C_DCFG_PerFrInt_MASK (0x3 << 11)
-#define S3C_DCFG_PerFrInt_SHIFT (11)
-#define S3C_DCFG_PerFrInt_LIMIT (0x3)
-#define S3C_DCFG_PerFrInt(_x) ((_x) << 11)
-
-#define S3C_DCFG_DevAddr_MASK (0x7f << 4)
-#define S3C_DCFG_DevAddr_SHIFT (4)
-#define S3C_DCFG_DevAddr_LIMIT (0x7f)
-#define S3C_DCFG_DevAddr(_x) ((_x) << 4)
-
-#define S3C_DCFG_NZStsOUTHShk (1 << 2)
-
-#define S3C_DCFG_DevSpd_MASK (0x3 << 0)
-#define S3C_DCFG_DevSpd_SHIFT (0)
-#define S3C_DCFG_DevSpd_HS (0x0 << 0)
-#define S3C_DCFG_DevSpd_FS (0x1 << 0)
-#define S3C_DCFG_DevSpd_LS (0x2 << 0)
-#define S3C_DCFG_DevSpd_FS48 (0x3 << 0)
-
-#define S3C_DCTL S3C_HSOTG_REG(0x804)
-
-#define S3C_DCTL_PWROnPrgDone (1 << 11)
-#define S3C_DCTL_CGOUTNak (1 << 10)
-#define S3C_DCTL_SGOUTNak (1 << 9)
-#define S3C_DCTL_CGNPInNAK (1 << 8)
-#define S3C_DCTL_SGNPInNAK (1 << 7)
-#define S3C_DCTL_TstCtl_MASK (0x7 << 4)
-#define S3C_DCTL_TstCtl_SHIFT (4)
-#define S3C_DCTL_GOUTNakSts (1 << 3)
-#define S3C_DCTL_GNPINNakSts (1 << 2)
-#define S3C_DCTL_SftDiscon (1 << 1)
-#define S3C_DCTL_RmtWkUpSig (1 << 0)
-
-#define S3C_DSTS S3C_HSOTG_REG(0x808)
-
-#define S3C_DSTS_SOFFN_MASK (0x3fff << 8)
-#define S3C_DSTS_SOFFN_SHIFT (8)
-#define S3C_DSTS_SOFFN_LIMIT (0x3fff)
-#define S3C_DSTS_SOFFN(_x) ((_x) << 8)
-#define S3C_DSTS_ErraticErr (1 << 3)
-#define S3C_DSTS_EnumSpd_MASK (0x3 << 1)
-#define S3C_DSTS_EnumSpd_SHIFT (1)
-#define S3C_DSTS_EnumSpd_HS (0x0 << 1)
-#define S3C_DSTS_EnumSpd_FS (0x1 << 1)
-#define S3C_DSTS_EnumSpd_LS (0x2 << 1)
-#define S3C_DSTS_EnumSpd_FS48 (0x3 << 1)
-
-#define S3C_DSTS_SuspSts (1 << 0)
-
-#define S3C_DIEPMSK S3C_HSOTG_REG(0x810)
-
-#define S3C_DIEPMSK_TxFIFOEmpty (1 << 7)
-#define S3C_DIEPMSK_INEPNakEffMsk (1 << 6)
-#define S3C_DIEPMSK_INTknEPMisMsk (1 << 5)
-#define S3C_DIEPMSK_INTknTXFEmpMsk (1 << 4)
-#define S3C_DIEPMSK_TimeOUTMsk (1 << 3)
-#define S3C_DIEPMSK_AHBErrMsk (1 << 2)
-#define S3C_DIEPMSK_EPDisbldMsk (1 << 1)
-#define S3C_DIEPMSK_XferComplMsk (1 << 0)
-
-#define S3C_DOEPMSK S3C_HSOTG_REG(0x814)
-
-#define S3C_DOEPMSK_Back2BackSetup (1 << 6)
-#define S3C_DOEPMSK_OUTTknEPdisMsk (1 << 4)
-#define S3C_DOEPMSK_SetupMsk (1 << 3)
-#define S3C_DOEPMSK_AHBErrMsk (1 << 2)
-#define S3C_DOEPMSK_EPDisbldMsk (1 << 1)
-#define S3C_DOEPMSK_XferComplMsk (1 << 0)
-
-#define S3C_DAINT S3C_HSOTG_REG(0x818)
-#define S3C_DAINTMSK S3C_HSOTG_REG(0x81C)
-
-#define S3C_DAINT_OutEP_SHIFT (16)
-#define S3C_DAINT_OutEP(x) (1 << ((x) + 16))
-#define S3C_DAINT_InEP(x) (1 << (x))
-
-#define S3C_DTKNQR1 S3C_HSOTG_REG(0x820)
-#define S3C_DTKNQR2 S3C_HSOTG_REG(0x824)
-#define S3C_DTKNQR3 S3C_HSOTG_REG(0x830)
-#define S3C_DTKNQR4 S3C_HSOTG_REG(0x834)
-
-#define S3C_DVBUSDIS S3C_HSOTG_REG(0x828)
-#define S3C_DVBUSPULSE S3C_HSOTG_REG(0x82C)
-
-#define S3C_DIEPCTL0 S3C_HSOTG_REG(0x900)
-#define S3C_DOEPCTL0 S3C_HSOTG_REG(0xB00)
-#define S3C_DIEPCTL(_a) S3C_HSOTG_REG(0x900 + ((_a) * 0x20))
-#define S3C_DOEPCTL(_a) S3C_HSOTG_REG(0xB00 + ((_a) * 0x20))
-
-/* EP0 specialness:
- * bits[29..28] - reserved (no SetD0PID, SetD1PID)
- * bits[25..22] - should always be zero, this isn't a periodic endpoint
- * bits[10..0] - MPS setting differenct for EP0
-*/
-#define S3C_D0EPCTL_MPS_MASK (0x3 << 0)
-#define S3C_D0EPCTL_MPS_SHIFT (0)
-#define S3C_D0EPCTL_MPS_64 (0x0 << 0)
-#define S3C_D0EPCTL_MPS_32 (0x1 << 0)
-#define S3C_D0EPCTL_MPS_16 (0x2 << 0)
-#define S3C_D0EPCTL_MPS_8 (0x3 << 0)
-
-#define S3C_DxEPCTL_EPEna (1 << 31)
-#define S3C_DxEPCTL_EPDis (1 << 30)
-#define S3C_DxEPCTL_SetD1PID (1 << 29)
-#define S3C_DxEPCTL_SetOddFr (1 << 29)
-#define S3C_DxEPCTL_SetD0PID (1 << 28)
-#define S3C_DxEPCTL_SetEvenFr (1 << 28)
-#define S3C_DxEPCTL_SNAK (1 << 27)
-#define S3C_DxEPCTL_CNAK (1 << 26)
-#define S3C_DxEPCTL_TxFNum_MASK (0xf << 22)
-#define S3C_DxEPCTL_TxFNum_SHIFT (22)
-#define S3C_DxEPCTL_TxFNum_LIMIT (0xf)
-#define S3C_DxEPCTL_TxFNum(_x) ((_x) << 22)
-
-#define S3C_DxEPCTL_Stall (1 << 21)
-#define S3C_DxEPCTL_Snp (1 << 20)
-#define S3C_DxEPCTL_EPType_MASK (0x3 << 18)
-#define S3C_DxEPCTL_EPType_SHIFT (18)
-#define S3C_DxEPCTL_EPType_Control (0x0 << 18)
-#define S3C_DxEPCTL_EPType_Iso (0x1 << 18)
-#define S3C_DxEPCTL_EPType_Bulk (0x2 << 18)
-#define S3C_DxEPCTL_EPType_Intterupt (0x3 << 18)
-
-#define S3C_DxEPCTL_NAKsts (1 << 17)
-#define S3C_DxEPCTL_DPID (1 << 16)
-#define S3C_DxEPCTL_EOFrNum (1 << 16)
-#define S3C_DxEPCTL_USBActEp (1 << 15)
-#define S3C_DxEPCTL_NextEp_MASK (0xf << 11)
-#define S3C_DxEPCTL_NextEp_SHIFT (11)
-#define S3C_DxEPCTL_NextEp_LIMIT (0xf)
-#define S3C_DxEPCTL_NextEp(_x) ((_x) << 11)
-
-#define S3C_DxEPCTL_MPS_MASK (0x7ff << 0)
-#define S3C_DxEPCTL_MPS_SHIFT (0)
-#define S3C_DxEPCTL_MPS_LIMIT (0x7ff)
-#define S3C_DxEPCTL_MPS(_x) ((_x) << 0)
-
-#define S3C_DIEPINT(_a) S3C_HSOTG_REG(0x908 + ((_a) * 0x20))
-#define S3C_DOEPINT(_a) S3C_HSOTG_REG(0xB08 + ((_a) * 0x20))
-
-#define S3C_DxEPINT_INEPNakEff (1 << 6)
-#define S3C_DxEPINT_Back2BackSetup (1 << 6)
-#define S3C_DxEPINT_INTknEPMis (1 << 5)
-#define S3C_DxEPINT_INTknTXFEmp (1 << 4)
-#define S3C_DxEPINT_OUTTknEPdis (1 << 4)
-#define S3C_DxEPINT_Timeout (1 << 3)
-#define S3C_DxEPINT_Setup (1 << 3)
-#define S3C_DxEPINT_AHBErr (1 << 2)
-#define S3C_DxEPINT_EPDisbld (1 << 1)
-#define S3C_DxEPINT_XferCompl (1 << 0)
-
-#define S3C_DIEPTSIZ0 S3C_HSOTG_REG(0x910)
-
-#define S3C_DIEPTSIZ0_PktCnt_MASK (0x3 << 19)
-#define S3C_DIEPTSIZ0_PktCnt_SHIFT (19)
-#define S3C_DIEPTSIZ0_PktCnt_LIMIT (0x3)
-#define S3C_DIEPTSIZ0_PktCnt(_x) ((_x) << 19)
-
-#define S3C_DIEPTSIZ0_XferSize_MASK (0x7f << 0)
-#define S3C_DIEPTSIZ0_XferSize_SHIFT (0)
-#define S3C_DIEPTSIZ0_XferSize_LIMIT (0x7f)
-#define S3C_DIEPTSIZ0_XferSize(_x) ((_x) << 0)
-
-
-#define DOEPTSIZ0 S3C_HSOTG_REG(0xB10)
-#define S3C_DOEPTSIZ0_SUPCnt_MASK (0x3 << 29)
-#define S3C_DOEPTSIZ0_SUPCnt_SHIFT (29)
-#define S3C_DOEPTSIZ0_SUPCnt_LIMIT (0x3)
-#define S3C_DOEPTSIZ0_SUPCnt(_x) ((_x) << 29)
-
-#define S3C_DOEPTSIZ0_PktCnt (1 << 19)
-#define S3C_DOEPTSIZ0_XferSize_MASK (0x7f << 0)
-#define S3C_DOEPTSIZ0_XferSize_SHIFT (0)
-
-#define S3C_DIEPTSIZ(_a) S3C_HSOTG_REG(0x910 + ((_a) * 0x20))
-#define S3C_DOEPTSIZ(_a) S3C_HSOTG_REG(0xB10 + ((_a) * 0x20))
-
-#define S3C_DxEPTSIZ_MC_MASK (0x3 << 29)
-#define S3C_DxEPTSIZ_MC_SHIFT (29)
-#define S3C_DxEPTSIZ_MC_LIMIT (0x3)
-#define S3C_DxEPTSIZ_MC(_x) ((_x) << 29)
-
-#define S3C_DxEPTSIZ_PktCnt_MASK (0x3ff << 19)
-#define S3C_DxEPTSIZ_PktCnt_SHIFT (19)
-#define S3C_DxEPTSIZ_PktCnt_GET(_v) (((_v) >> 19) & 0x3ff)
-#define S3C_DxEPTSIZ_PktCnt_LIMIT (0x3ff)
-#define S3C_DxEPTSIZ_PktCnt(_x) ((_x) << 19)
-
-#define S3C_DxEPTSIZ_XferSize_MASK (0x7ffff << 0)
-#define S3C_DxEPTSIZ_XferSize_SHIFT (0)
-#define S3C_DxEPTSIZ_XferSize_GET(_v) (((_v) >> 0) & 0x7ffff)
-#define S3C_DxEPTSIZ_XferSize_LIMIT (0x7ffff)
-#define S3C_DxEPTSIZ_XferSize(_x) ((_x) << 0)
-
-
-#define S3C_DIEPDMA(_a) S3C_HSOTG_REG(0x914 + ((_a) * 0x20))
-#define S3C_DOEPDMA(_a) S3C_HSOTG_REG(0xB14 + ((_a) * 0x20))
-#define S3C_DTXFSTS(_a) S3C_HSOTG_REG(0x918 + ((_a) * 0x20))
-
-#define S3C_EPFIFO(_a) S3C_HSOTG_REG(0x1000 + ((_a) * 0x1000))
-
-#endif /* __PLAT_S3C64XX_REGS_USB_HSOTG_H */
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h
index e834c5ef437c..151cc9195cf6 100644
--- a/arch/arm/plat-samsung/include/plat/sdhci.h
+++ b/arch/arm/plat-samsung/include/plat/sdhci.h
@@ -33,18 +33,12 @@ enum cd_types {
S3C_SDHCI_CD_PERMANENT, /* no CD line, card permanently wired to host */
};
-enum clk_types {
- S3C_SDHCI_CLK_DIV_INTERNAL, /* use mmc internal clock divider */
- S3C_SDHCI_CLK_DIV_EXTERNAL, /* use external clock divider */
-};
-
/**
* struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI
* @max_width: The maximum number of data bits supported.
* @host_caps: Standard MMC host capabilities bit field.
* @host_caps2: The second standard MMC host capabilities bit field.
* @cd_type: Type of Card Detection method (see cd_types enum above)
- * @clk_type: Type of clock divider method (see clk_types enum above)
* @ext_cd_init: Initialize external card detect subsystem. Called on
* sdhci-s3c driver probe when cd_type == S3C_SDHCI_CD_EXTERNAL.
* notify_func argument is a callback to the sdhci-s3c driver
@@ -69,7 +63,6 @@ struct s3c_sdhci_platdata {
unsigned int host_caps2;
unsigned int pm_caps;
enum cd_types cd_type;
- enum clk_types clk_type;
int ext_cd_gpio;
bool ext_cd_gpio_invert;
diff --git a/arch/arm/plat-samsung/platformdata.c b/arch/arm/plat-samsung/platformdata.c
index fa78aa710ed1..b430e9946287 100644
--- a/arch/arm/plat-samsung/platformdata.c
+++ b/arch/arm/plat-samsung/platformdata.c
@@ -57,6 +57,4 @@ void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
set->host_caps2 |= pd->host_caps2;
if (pd->pm_caps)
set->pm_caps |= pd->pm_caps;
- if (pd->clk_type)
- set->clk_type = pd->clk_type;
}
diff --git a/arch/arm/plat-spear/Kconfig b/arch/arm/plat-spear/Kconfig
index 1bb3dbce8810..387655b5ce05 100644
--- a/arch/arm/plat-spear/Kconfig
+++ b/arch/arm/plat-spear/Kconfig
@@ -9,9 +9,11 @@ choice
default ARCH_SPEAR3XX
config ARCH_SPEAR3XX
- bool "SPEAr3XX"
+ bool "ST SPEAr3xx with Device Tree"
select ARM_VIC
select CPU_ARM926T
+ select USE_OF
+ select PINCTRL
help
Supports for ARM's SPEAR3XX family
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index e0f2e5b9530c..7744802c83e7 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -3,6 +3,6 @@
#
# Common support
-obj-y := clock.o restart.o time.o
+obj-y := clock.o restart.o time.o pl080.o
-obj-$(CONFIG_ARCH_SPEAR3XX) += shirq.o padmux.o
+obj-$(CONFIG_ARCH_SPEAR3XX) += shirq.o
diff --git a/arch/arm/plat-spear/include/plat/debug-macro.S b/arch/arm/plat-spear/include/plat/debug-macro.S
index 02b160a1ec9b..ab3de721c5db 100644
--- a/arch/arm/plat-spear/include/plat/debug-macro.S
+++ b/arch/arm/plat-spear/include/plat/debug-macro.S
@@ -12,7 +12,7 @@
*/
#include <linux/amba/serial.h>
-#include <mach/hardware.h>
+#include <mach/spear.h>
.macro addruart, rp, rv, tmp
mov \rp, #SPEAR_DBG_UART_BASE @ Physical base
diff --git a/arch/arm/plat-spear/include/plat/hardware.h b/arch/arm/plat-spear/include/plat/hardware.h
deleted file mode 100644
index 70187d763e26..000000000000
--- a/arch/arm/plat-spear/include/plat/hardware.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/hardware.h
- *
- * Hardware definitions for SPEAr
- *
- * Copyright (C) 2010 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __PLAT_HARDWARE_H
-#define __PLAT_HARDWARE_H
-
-#endif /* __PLAT_HARDWARE_H */
diff --git a/arch/arm/plat-spear/include/plat/padmux.h b/arch/arm/plat-spear/include/plat/padmux.h
deleted file mode 100644
index 877f3adcf610..000000000000
--- a/arch/arm/plat-spear/include/plat/padmux.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/padmux.h
- *
- * SPEAr platform specific gpio pads muxing file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __PLAT_PADMUX_H
-#define __PLAT_PADMUX_H
-
-#include <linux/types.h>
-
-/*
- * struct pmx_reg: configuration structure for mode reg and mux reg
- *
- * offset: offset of mode reg
- * mask: mask of mode reg
- */
-struct pmx_reg {
- u32 offset;
- u32 mask;
-};
-
-/*
- * struct pmx_dev_mode: configuration structure every group of modes of a device
- *
- * ids: all modes for this configuration
- * mask: mask for supported mode
- */
-struct pmx_dev_mode {
- u32 ids;
- u32 mask;
-};
-
-/*
- * struct pmx_mode: mode definition structure
- *
- * name: mode name
- * mask: mode mask
- */
-struct pmx_mode {
- char *name;
- u32 id;
- u32 mask;
-};
-
-/*
- * struct pmx_dev: device definition structure
- *
- * name: device name
- * modes: device configuration array for different modes supported
- * mode_count: size of modes array
- * is_active: is peripheral active/enabled
- * enb_on_reset: if 1, mask bits to be cleared in reg otherwise to be set in reg
- */
-struct pmx_dev {
- char *name;
- struct pmx_dev_mode *modes;
- u8 mode_count;
- bool is_active;
- bool enb_on_reset;
-};
-
-/*
- * struct pmx_driver: driver definition structure
- *
- * mode: mode to be set
- * devs: array of pointer to pmx devices
- * devs_count: ARRAY_SIZE of devs
- * base: base address of soc config registers
- * mode_reg: structure of mode config register
- * mux_reg: structure of device mux config register
- */
-struct pmx_driver {
- struct pmx_mode *mode;
- struct pmx_dev **devs;
- u8 devs_count;
- u32 *base;
- struct pmx_reg mode_reg;
- struct pmx_reg mux_reg;
-};
-
-/* pmx functions */
-int pmx_register(struct pmx_driver *driver);
-
-#endif /* __PLAT_PADMUX_H */
diff --git a/arch/arm/plat-spear/include/plat/pl080.h b/arch/arm/plat-spear/include/plat/pl080.h
new file mode 100644
index 000000000000..e14a3e4932f9
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/pl080.h
@@ -0,0 +1,21 @@
+/*
+ * arch/arm/plat-spear/include/plat/pl080.h
+ *
+ * DMAC pl080 definitions for SPEAr platform
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_PL080_H
+#define __PLAT_PL080_H
+
+struct pl08x_dma_chan;
+int pl080_get_signal(struct pl08x_dma_chan *ch);
+void pl080_put_signal(struct pl08x_dma_chan *ch);
+
+#endif /* __PLAT_PL080_H */
diff --git a/arch/arm/plat-spear/include/plat/uncompress.h b/arch/arm/plat-spear/include/plat/uncompress.h
index 1bf84527aee4..6dd455bafdfd 100644
--- a/arch/arm/plat-spear/include/plat/uncompress.h
+++ b/arch/arm/plat-spear/include/plat/uncompress.h
@@ -13,7 +13,7 @@
#include <linux/io.h>
#include <linux/amba/serial.h>
-#include <mach/hardware.h>
+#include <mach/spear.h>
#ifndef __PLAT_UNCOMPRESS_H
#define __PLAT_UNCOMPRESS_H
diff --git a/arch/arm/plat-spear/padmux.c b/arch/arm/plat-spear/padmux.c
deleted file mode 100644
index 555eec6dc1cb..000000000000
--- a/arch/arm/plat-spear/padmux.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/padmux.c
- *
- * SPEAr platform specific gpio pads muxing source file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <plat/padmux.h>
-
-/*
- * struct pmx: pmx definition structure
- *
- * base: base address of configuration registers
- * mode_reg: mode configurations
- * mux_reg: muxing configurations
- * active_mode: pointer to current active mode
- */
-struct pmx {
- u32 base;
- struct pmx_reg mode_reg;
- struct pmx_reg mux_reg;
- struct pmx_mode *active_mode;
-};
-
-static struct pmx *pmx;
-
-/**
- * pmx_mode_set - Enables an multiplexing mode
- * @mode - pointer to pmx mode
- *
- * It will set mode of operation in hardware.
- * Returns -ve on Err otherwise 0
- */
-static int pmx_mode_set(struct pmx_mode *mode)
-{
- u32 val;
-
- if (!mode->name)
- return -EFAULT;
-
- pmx->active_mode = mode;
-
- val = readl(pmx->base + pmx->mode_reg.offset);
- val &= ~pmx->mode_reg.mask;
- val |= mode->mask & pmx->mode_reg.mask;
- writel(val, pmx->base + pmx->mode_reg.offset);
-
- return 0;
-}
-
-/**
- * pmx_devs_enable - Enables list of devices
- * @devs - pointer to pmx device array
- * @count - number of devices to enable
- *
- * It will enable pads for all required peripherals once and only once.
- * If peripheral is not supported by current mode then request is rejected.
- * Conflicts between peripherals are not handled and peripherals will be
- * enabled in the order they are present in pmx_dev array.
- * In case of conflicts last peripheral enabled will be present.
- * Returns -ve on Err otherwise 0
- */
-static int pmx_devs_enable(struct pmx_dev **devs, u8 count)
-{
- u32 val, i, mask;
-
- if (!count)
- return -EINVAL;
-
- val = readl(pmx->base + pmx->mux_reg.offset);
- for (i = 0; i < count; i++) {
- u8 j = 0;
-
- if (!devs[i]->name || !devs[i]->modes) {
- printk(KERN_ERR "padmux: dev name or modes is null\n");
- continue;
- }
- /* check if peripheral exists in active mode */
- if (pmx->active_mode) {
- bool found = false;
- for (j = 0; j < devs[i]->mode_count; j++) {
- if (devs[i]->modes[j].ids &
- pmx->active_mode->id) {
- found = true;
- break;
- }
- }
- if (found == false) {
- printk(KERN_ERR "%s device not available in %s"\
- "mode\n", devs[i]->name,
- pmx->active_mode->name);
- continue;
- }
- }
-
- /* enable peripheral */
- mask = devs[i]->modes[j].mask & pmx->mux_reg.mask;
- if (devs[i]->enb_on_reset)
- val &= ~mask;
- else
- val |= mask;
-
- devs[i]->is_active = true;
- }
- writel(val, pmx->base + pmx->mux_reg.offset);
- kfree(pmx);
-
- /* this will ensure that multiplexing can't be changed now */
- pmx = (struct pmx *)-1;
-
- return 0;
-}
-
-/**
- * pmx_register - registers a platform requesting pad mux feature
- * @driver - pointer to driver structure containing driver specific parameters
- *
- * Also this must be called only once. This will allocate memory for pmx
- * structure, will call pmx_mode_set, will call pmx_devs_enable.
- * Returns -ve on Err otherwise 0
- */
-int pmx_register(struct pmx_driver *driver)
-{
- int ret = 0;
-
- if (pmx)
- return -EPERM;
- if (!driver->base || !driver->devs)
- return -EFAULT;
-
- pmx = kzalloc(sizeof(*pmx), GFP_KERNEL);
- if (!pmx)
- return -ENOMEM;
-
- pmx->base = (u32)driver->base;
- pmx->mode_reg.offset = driver->mode_reg.offset;
- pmx->mode_reg.mask = driver->mode_reg.mask;
- pmx->mux_reg.offset = driver->mux_reg.offset;
- pmx->mux_reg.mask = driver->mux_reg.mask;
-
- /* choose mode to enable */
- if (driver->mode) {
- ret = pmx_mode_set(driver->mode);
- if (ret)
- goto pmx_fail;
- }
- ret = pmx_devs_enable(driver->devs, driver->devs_count);
- if (ret)
- goto pmx_fail;
-
- return 0;
-
-pmx_fail:
- return ret;
-}
diff --git a/arch/arm/plat-spear/pl080.c b/arch/arm/plat-spear/pl080.c
new file mode 100644
index 000000000000..a56a067717c1
--- /dev/null
+++ b/arch/arm/plat-spear/pl080.c
@@ -0,0 +1,80 @@
+/*
+ * arch/arm/plat-spear/pl080.c
+ *
+ * DMAC pl080 definitions for SPEAr platform
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/amba/pl08x.h>
+#include <linux/amba/bus.h>
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/spinlock_types.h>
+#include <mach/spear.h>
+#include <mach/misc_regs.h>
+
+static spinlock_t lock = __SPIN_LOCK_UNLOCKED(x);
+
+struct {
+ unsigned char busy;
+ unsigned char val;
+} signals[16] = {{0, 0}, };
+
+int pl080_get_signal(struct pl08x_dma_chan *ch)
+{
+ const struct pl08x_channel_data *cd = ch->cd;
+ unsigned int signal = cd->min_signal, val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&lock, flags);
+
+ /* Return if signal is already acquired by somebody else */
+ if (signals[signal].busy &&
+ (signals[signal].val != cd->muxval)) {
+ spin_unlock_irqrestore(&lock, flags);
+ return -EBUSY;
+ }
+
+ /* If acquiring for the first time, configure it */
+ if (!signals[signal].busy) {
+ val = readl(DMA_CHN_CFG);
+
+ /*
+ * Each request line has two bits in DMA_CHN_CFG register. To
+ * goto the bits of current request line, do left shift of
+ * value by 2 * signal number.
+ */
+ val &= ~(0x3 << (signal * 2));
+ val |= cd->muxval << (signal * 2);
+ writel(val, DMA_CHN_CFG);
+ }
+
+ signals[signal].busy++;
+ signals[signal].val = cd->muxval;
+ spin_unlock_irqrestore(&lock, flags);
+
+ return signal;
+}
+
+void pl080_put_signal(struct pl08x_dma_chan *ch)
+{
+ const struct pl08x_channel_data *cd = ch->cd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&lock, flags);
+
+ /* if signal is not used */
+ if (!signals[cd->min_signal].busy)
+ BUG();
+
+ signals[cd->min_signal].busy--;
+
+ spin_unlock_irqrestore(&lock, flags);
+}
diff --git a/arch/arm/plat-spear/restart.c b/arch/arm/plat-spear/restart.c
index 16f203e78d89..4471a232713a 100644
--- a/arch/arm/plat-spear/restart.c
+++ b/arch/arm/plat-spear/restart.c
@@ -13,7 +13,7 @@
#include <linux/io.h>
#include <asm/system_misc.h>
#include <asm/hardware/sp810.h>
-#include <mach/hardware.h>
+#include <mach/spear.h>
#include <mach/generic.h>
void spear_restart(char mode, const char *cmd)
diff --git a/arch/arm/plat-spear/time.c b/arch/arm/plat-spear/time.c
index abb5bdecd509..a3164d1647fd 100644
--- a/arch/arm/plat-spear/time.c
+++ b/arch/arm/plat-spear/time.c
@@ -15,14 +15,13 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/time.h>
#include <linux/irq.h>
#include <asm/mach/time.h>
#include <mach/generic.h>
-#include <mach/hardware.h>
-#include <mach/irqs.h>
/*
* We would use TIMER0 and TIMER1 as clockevent and clocksource.
@@ -175,7 +174,7 @@ static struct irqaction spear_timer_irq = {
.handler = spear_timer_interrupt
};
-static void __init spear_clockevent_init(void)
+static void __init spear_clockevent_init(int irq)
{
u32 tick_rate;
@@ -195,19 +194,19 @@ static void __init spear_clockevent_init(void)
clockevents_register_device(&clkevt);
- setup_irq(SPEAR_GPT0_CHAN0_IRQ, &spear_timer_irq);
+ setup_irq(irq, &spear_timer_irq);
}
-void __init spear_setup_timer(void)
+void __init spear_setup_timer(resource_size_t base, int irq)
{
int ret;
- if (!request_mem_region(SPEAR_GPT0_BASE, SZ_1K, "gpt0")) {
+ if (!request_mem_region(base, SZ_1K, "gpt0")) {
pr_err("%s:cannot get IO addr\n", __func__);
return;
}
- gpt_base = (void __iomem *)ioremap(SPEAR_GPT0_BASE, SZ_1K);
+ gpt_base = ioremap(base, SZ_1K);
if (!gpt_base) {
pr_err("%s:ioremap failed for gpt\n", __func__);
goto err_mem;
@@ -225,7 +224,7 @@ void __init spear_setup_timer(void)
goto err_clk;
}
- spear_clockevent_init();
+ spear_clockevent_init(irq);
spear_clocksource_init();
return;
@@ -235,5 +234,5 @@ err_clk:
err_iomap:
iounmap(gpt_base);
err_mem:
- release_mem_region(SPEAR_GPT0_BASE, SZ_1K);
+ release_mem_region(base, SZ_1K);
}
diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig
index 043f7b02a9e7..81ee7cc34457 100644
--- a/arch/arm/plat-versatile/Kconfig
+++ b/arch/arm/plat-versatile/Kconfig
@@ -5,6 +5,12 @@ config PLAT_VERSATILE_CLCD
config PLAT_VERSATILE_FPGA_IRQ
bool
+ select IRQ_DOMAIN
+
+config PLAT_VERSATILE_FPGA_IRQ_NR
+ int
+ default 4
+ depends on PLAT_VERSATILE_FPGA_IRQ
config PLAT_VERSATILE_LEDS
def_bool y if LEDS_CLASS
diff --git a/arch/arm/plat-versatile/fpga-irq.c b/arch/arm/plat-versatile/fpga-irq.c
index f0cc8e19b094..6e70d03824a1 100644
--- a/arch/arm/plat-versatile/fpga-irq.c
+++ b/arch/arm/plat-versatile/fpga-irq.c
@@ -3,7 +3,10 @@
*/
#include <linux/irq.h>
#include <linux/io.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <asm/exception.h>
#include <asm/mach/irq.h>
#include <plat/fpga-irq.h>
@@ -12,10 +15,32 @@
#define IRQ_ENABLE_SET 0x08
#define IRQ_ENABLE_CLEAR 0x0c
+/**
+ * struct fpga_irq_data - irq data container for the FPGA IRQ controller
+ * @base: memory offset in virtual memory
+ * @irq_start: first IRQ number handled by this instance
+ * @chip: chip container for this instance
+ * @domain: IRQ domain for this instance
+ * @valid: mask for valid IRQs on this controller
+ * @used_irqs: number of active IRQs on this controller
+ */
+struct fpga_irq_data {
+ void __iomem *base;
+ unsigned int irq_start;
+ struct irq_chip chip;
+ u32 valid;
+ struct irq_domain *domain;
+ u8 used_irqs;
+};
+
+/* we cannot allocate memory when the controllers are initially registered */
+static struct fpga_irq_data fpga_irq_devices[CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR];
+static int fpga_irq_id;
+
static void fpga_irq_mask(struct irq_data *d)
{
struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
- u32 mask = 1 << (d->irq - f->irq_start);
+ u32 mask = 1 << d->hwirq;
writel(mask, f->base + IRQ_ENABLE_CLEAR);
}
@@ -23,7 +48,7 @@ static void fpga_irq_mask(struct irq_data *d)
static void fpga_irq_unmask(struct irq_data *d)
{
struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
- u32 mask = 1 << (d->irq - f->irq_start);
+ u32 mask = 1 << d->hwirq;
writel(mask, f->base + IRQ_ENABLE_SET);
}
@@ -41,32 +66,93 @@ static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc)
do {
irq = ffs(status) - 1;
status &= ~(1 << irq);
-
- generic_handle_irq(irq + f->irq_start);
+ generic_handle_irq(irq_find_mapping(f->domain, irq));
} while (status);
}
-void __init fpga_irq_init(int parent_irq, u32 valid, struct fpga_irq_data *f)
+/*
+ * Handle each interrupt in a single FPGA IRQ controller. Returns non-zero
+ * if we've handled at least one interrupt. This does a single read of the
+ * status register and handles all interrupts in order from LSB first.
+ */
+static int handle_one_fpga(struct fpga_irq_data *f, struct pt_regs *regs)
+{
+ int handled = 0;
+ int irq;
+ u32 status;
+
+ while ((status = readl(f->base + IRQ_STATUS))) {
+ irq = ffs(status) - 1;
+ handle_IRQ(irq_find_mapping(f->domain, irq), regs);
+ handled = 1;
+ }
+
+ return handled;
+}
+
+/*
+ * Keep iterating over all registered FPGA IRQ controllers until there are
+ * no pending interrupts.
+ */
+asmlinkage void __exception_irq_entry fpga_handle_irq(struct pt_regs *regs)
{
- unsigned int i;
+ int i, handled;
+ do {
+ for (i = 0, handled = 0; i < fpga_irq_id; ++i)
+ handled |= handle_one_fpga(&fpga_irq_devices[i], regs);
+ } while (handled);
+}
+
+static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct fpga_irq_data *f = d->host_data;
+
+ /* Skip invalid IRQs, only register handlers for the real ones */
+ if (!(f->valid & (1 << hwirq)))
+ return -ENOTSUPP;
+ irq_set_chip_data(irq, f);
+ irq_set_chip_and_handler(irq, &f->chip,
+ handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ f->used_irqs++;
+ return 0;
+}
+
+static struct irq_domain_ops fpga_irqdomain_ops = {
+ .map = fpga_irqdomain_map,
+ .xlate = irq_domain_xlate_onetwocell,
+};
+
+void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
+ int parent_irq, u32 valid, struct device_node *node)
+{
+ struct fpga_irq_data *f;
+
+ if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) {
+ printk(KERN_ERR "%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__);
+ return;
+ }
+
+ f = &fpga_irq_devices[fpga_irq_id];
+ f->base = base;
+ f->irq_start = irq_start;
+ f->chip.name = name;
f->chip.irq_ack = fpga_irq_mask;
f->chip.irq_mask = fpga_irq_mask;
f->chip.irq_unmask = fpga_irq_unmask;
+ f->valid = valid;
if (parent_irq != -1) {
irq_set_handler_data(parent_irq, f);
irq_set_chained_handler(parent_irq, fpga_irq_handle);
}
- for (i = 0; i < 32; i++) {
- if (valid & (1 << i)) {
- unsigned int irq = f->irq_start + i;
+ f->domain = irq_domain_add_legacy(node, fls(valid), f->irq_start, 0,
+ &fpga_irqdomain_ops, f);
+ pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
+ fpga_irq_id, name, base, f->used_irqs);
- irq_set_chip_data(irq, f);
- irq_set_chip_and_handler(irq, &f->chip,
- handle_level_irq);
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
- }
- }
+ fpga_irq_id++;
}
diff --git a/arch/arm/plat-versatile/include/plat/fpga-irq.h b/arch/arm/plat-versatile/include/plat/fpga-irq.h
index 627fafd1e595..91bcfb67551d 100644
--- a/arch/arm/plat-versatile/include/plat/fpga-irq.h
+++ b/arch/arm/plat-versatile/include/plat/fpga-irq.h
@@ -1,12 +1,11 @@
#ifndef PLAT_FPGA_IRQ_H
#define PLAT_FPGA_IRQ_H
-struct fpga_irq_data {
- void __iomem *base;
- unsigned int irq_start;
- struct irq_chip chip;
-};
+struct device_node;
+struct pt_regs;
-void fpga_irq_init(int, u32, struct fpga_irq_data *);
+void fpga_handle_irq(struct pt_regs *regs);
+void fpga_irq_init(void __iomem *, const char *, int, int, u32,
+ struct device_node *node);
#endif
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index f9c9f33f8cbe..2997e56ce0dd 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -16,7 +16,7 @@
# are merged into mainline or have been edited in the machine database
# within the last 12 months. References to machine_is_NAME() do not count!
#
-# Last update: Tue Dec 6 11:07:38 2011
+# Last update: Thu Apr 26 08:44:23 2012
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -205,6 +205,7 @@ omap_fsample MACH_OMAP_FSAMPLE OMAP_FSAMPLE 970
snapper_cl15 MACH_SNAPPER_CL15 SNAPPER_CL15 986
omap_palmz71 MACH_OMAP_PALMZ71 OMAP_PALMZ71 993
smdk2412 MACH_SMDK2412 SMDK2412 1009
+bkde303 MACH_BKDE303 BKDE303 1021
smdk2413 MACH_SMDK2413 SMDK2413 1022
aml_m5900 MACH_AML_M5900 AML_M5900 1024
balloon3 MACH_BALLOON3 BALLOON3 1029
@@ -381,8 +382,6 @@ davinci_da850_evm MACH_DAVINCI_DA850_EVM DAVINCI_DA850_EVM 2157
at91sam9g10ek MACH_AT91SAM9G10EK AT91SAM9G10EK 2159
omap_4430sdp MACH_OMAP_4430SDP OMAP_4430SDP 2160
magx_zn5 MACH_MAGX_ZN5 MAGX_ZN5 2162
-btmavb101 MACH_BTMAVB101 BTMAVB101 2172
-btmawb101 MACH_BTMAWB101 BTMAWB101 2173
tx25 MACH_TX25 TX25 2177
omap3_torpedo MACH_OMAP3_TORPEDO OMAP3_TORPEDO 2178
anw6410 MACH_ANW6410 ANW6410 2183
@@ -397,7 +396,6 @@ net2big_v2 MACH_NET2BIG_V2 NET2BIG_V2 2204
net5big_v2 MACH_NET5BIG_V2 NET5BIG_V2 2206
inetspace_v2 MACH_INETSPACE_V2 INETSPACE_V2 2208
at91sam9g45ekes MACH_AT91SAM9G45EKES AT91SAM9G45EKES 2212
-pc7302 MACH_PC7302 PC7302 2220
spear600 MACH_SPEAR600 SPEAR600 2236
spear300 MACH_SPEAR300 SPEAR300 2237
lilly1131 MACH_LILLY1131 LILLY1131 2239
@@ -407,7 +405,6 @@ d2net MACH_D2NET D2NET 2282
bigdisk MACH_BIGDISK BIGDISK 2283
at91sam9g20ek_2mmc MACH_AT91SAM9G20EK_2MMC AT91SAM9G20EK_2MMC 2288
bcmring MACH_BCMRING BCMRING 2289
-dp6xx MACH_DP6XX DP6XX 2302
mahimahi MACH_MAHIMAHI MAHIMAHI 2304
smdk6442 MACH_SMDK6442 SMDK6442 2324
openrd_base MACH_OPENRD_BASE OPENRD_BASE 2325
@@ -444,8 +441,6 @@ mx28evk MACH_MX28EVK MX28EVK 2531
smartq5 MACH_SMARTQ5 SMARTQ5 2534
davinci_dm6467tevm MACH_DAVINCI_DM6467TEVM DAVINCI_DM6467TEVM 2548
mxt_td60 MACH_MXT_TD60 MXT_TD60 2550
-riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576
-riot_x37 MACH_RIOT_X37 RIOT_X37 2578
pca101 MACH_PCA101 PCA101 2595
capc7117 MACH_CAPC7117 CAPC7117 2612
icontrol MACH_ICONTROL ICONTROL 2624
@@ -460,7 +455,6 @@ spear320 MACH_SPEAR320 SPEAR320 2661
aquila MACH_AQUILA AQUILA 2676
esata_sheevaplug MACH_ESATA_SHEEVAPLUG ESATA_SHEEVAPLUG 2678
msm7x30_surf MACH_MSM7X30_SURF MSM7X30_SURF 2679
-ea2478devkit MACH_EA2478DEVKIT EA2478DEVKIT 2683
terastation_wxl MACH_TERASTATION_WXL TERASTATION_WXL 2697
msm7x25_surf MACH_MSM7X25_SURF MSM7X25_SURF 2703
msm7x25_ffa MACH_MSM7X25_FFA MSM7X25_FFA 2704
@@ -479,8 +473,6 @@ wbd222 MACH_WBD222 WBD222 2753
msm8x60_surf MACH_MSM8X60_SURF MSM8X60_SURF 2755
msm8x60_sim MACH_MSM8X60_SIM MSM8X60_SIM 2756
tcc8000_sdk MACH_TCC8000_SDK TCC8000_SDK 2758
-nanos MACH_NANOS NANOS 2759
-stamp9g45 MACH_STAMP9G45 STAMP9G45 2761
cns3420vb MACH_CNS3420VB CNS3420VB 2776
omap4_panda MACH_OMAP4_PANDA OMAP4_PANDA 2791
ti8168evm MACH_TI8168EVM TI8168EVM 2800
@@ -490,12 +482,9 @@ eukrea_cpuimx35sd MACH_EUKREA_CPUIMX35SD EUKREA_CPUIMX35SD 2821
eukrea_cpuimx51sd MACH_EUKREA_CPUIMX51SD EUKREA_CPUIMX51SD 2822
eukrea_cpuimx51 MACH_EUKREA_CPUIMX51 EUKREA_CPUIMX51 2823
smdkc210 MACH_SMDKC210 SMDKC210 2838
-pca102 MACH_PCA102 PCA102 2843
+pcaal1 MACH_PCAAL1 PCAAL1 2843
t5325 MACH_T5325 T5325 2846
income MACH_INCOME INCOME 2849
-vvbox_sdorig2 MACH_VVBOX_SDORIG2 VVBOX_SDORIG2 2857
-vvbox_sdlite2 MACH_VVBOX_SDLITE2 VVBOX_SDLITE2 2858
-vvbox_sdpro4 MACH_VVBOX_SDPRO4 VVBOX_SDPRO4 2859
mx257sx MACH_MX257SX MX257SX 2861
goni MACH_GONI GONI 2862
bv07 MACH_BV07 BV07 2882
@@ -504,6 +493,7 @@ devixp MACH_DEVIXP DEVIXP 2885
miccpt MACH_MICCPT MICCPT 2886
mic256 MACH_MIC256 MIC256 2887
u5500 MACH_U5500 U5500 2890
+pov15hd MACH_POV15HD POV15HD 2910
linkstation_lschl MACH_LINKSTATION_LSCHL LINKSTATION_LSCHL 2913
smdkv310 MACH_SMDKV310 SMDKV310 2925
wm8505_7in_netbook MACH_WM8505_7IN_NETBOOK WM8505_7IN_NETBOOK 2928
@@ -537,243 +527,24 @@ trimslice MACH_TRIMSLICE TRIMSLICE 3209
mackerel MACH_MACKEREL MACKEREL 3211
kaen MACH_KAEN KAEN 3217
nokia_rm680 MACH_NOKIA_RM680 NOKIA_RM680 3220
-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
-ts48xx MACH_TS48XX TS48XX 3239
-tonga2_tfttimer MACH_TONGA2_TFTTIMER TONGA2_TFTTIMER 3240
-whistler MACH_WHISTLER WHISTLER 3241
-asl_phoenix MACH_ASL_PHOENIX ASL_PHOENIX 3242
-at91sam9263otlite MACH_AT91SAM9263OTLITE AT91SAM9263OTLITE 3243
-ddplug MACH_DDPLUG DDPLUG 3244
-d2plug MACH_D2PLUG D2PLUG 3245
-kzm9d MACH_KZM9D KZM9D 3246
-verdi_lte MACH_VERDI_LTE VERDI_LTE 3247
-nanozoom MACH_NANOZOOM NANOZOOM 3248
-dm3730_som_lv MACH_DM3730_SOM_LV DM3730_SOM_LV 3249
-dm3730_torpedo MACH_DM3730_TORPEDO DM3730_TORPEDO 3250
-anchovy MACH_ANCHOVY ANCHOVY 3251
-re2rev20 MACH_RE2REV20 RE2REV20 3253
-re2rev21 MACH_RE2REV21 RE2REV21 3254
-cns21xx MACH_CNS21XX CNS21XX 3255
-rider MACH_RIDER RIDER 3257
-nsk330 MACH_NSK330 NSK330 3258
-cns2133evb MACH_CNS2133EVB CNS2133EVB 3259
-z3_816x_mod MACH_Z3_816X_MOD Z3_816X_MOD 3260
-z3_814x_mod MACH_Z3_814X_MOD Z3_814X_MOD 3261
-beect MACH_BEECT BEECT 3262
-dma_thunderbug MACH_DMA_THUNDERBUG DMA_THUNDERBUG 3263
-omn_at91sam9g20 MACH_OMN_AT91SAM9G20 OMN_AT91SAM9G20 3264
-mx25_e2s_uc MACH_MX25_E2S_UC MX25_E2S_UC 3265
-mione MACH_MIONE MIONE 3266
-top9000_tcu MACH_TOP9000_TCU TOP9000_TCU 3267
-top9000_bsl MACH_TOP9000_BSL TOP9000_BSL 3268
-kingdom MACH_KINGDOM KINGDOM 3269
-armadillo460 MACH_ARMADILLO460 ARMADILLO460 3270
-lq2 MACH_LQ2 LQ2 3271
-sweda_tms2 MACH_SWEDA_TMS2 SWEDA_TMS2 3272
mx53_loco MACH_MX53_LOCO MX53_LOCO 3273
-acer_a8 MACH_ACER_A8 ACER_A8 3275
-acer_gauguin MACH_ACER_GAUGUIN ACER_GAUGUIN 3276
-guppy MACH_GUPPY GUPPY 3277
-mx61_ard MACH_MX61_ARD MX61_ARD 3278
tx53 MACH_TX53 TX53 3279
-omapl138_case_a3 MACH_OMAPL138_CASE_A3 OMAPL138_CASE_A3 3280
-uemd MACH_UEMD UEMD 3281
-ccwmx51mut MACH_CCWMX51MUT CCWMX51MUT 3282
-rockhopper MACH_ROCKHOPPER ROCKHOPPER 3283
encore MACH_ENCORE ENCORE 3284
-hkdkc100 MACH_HKDKC100 HKDKC100 3285
-ts42xx MACH_TS42XX TS42XX 3286
-aebl MACH_AEBL AEBL 3287
wario MACH_WARIO WARIO 3288
-gfs_spm MACH_GFS_SPM GFS_SPM 3289
cm_t3730 MACH_CM_T3730 CM_T3730 3290
-isc3 MACH_ISC3 ISC3 3291
-rascal MACH_RASCAL RASCAL 3292
hrefv60 MACH_HREFV60 HREFV60 3293
-tpt_2_0 MACH_TPT_2_0 TPT_2_0 3294
-splendor MACH_SPLENDOR SPLENDOR 3296
-msm8x60_qt MACH_MSM8X60_QT MSM8X60_QT 3298
-htc_hd_mini MACH_HTC_HD_MINI HTC_HD_MINI 3299
-athene MACH_ATHENE ATHENE 3300
-deep_r_ek_1 MACH_DEEP_R_EK_1 DEEP_R_EK_1 3301
-vivow_ct MACH_VIVOW_CT VIVOW_CT 3302
-nery_1000 MACH_NERY_1000 NERY_1000 3303
-rfl109145_ssrv MACH_RFL109145_SSRV RFL109145_SSRV 3304
-nmh MACH_NMH NMH 3305
-wn802t MACH_WN802T WN802T 3306
-dragonet MACH_DRAGONET DRAGONET 3307
-at91sam9263desk16l MACH_AT91SAM9263DESK16L AT91SAM9263DESK16L 3309
-bcmhana_sv MACH_BCMHANA_SV BCMHANA_SV 3310
-bcmhana_tablet MACH_BCMHANA_TABLET BCMHANA_TABLET 3311
-koi MACH_KOI KOI 3312
-ts4800 MACH_TS4800 TS4800 3313
-tqma9263 MACH_TQMA9263 TQMA9263 3314
-holiday MACH_HOLIDAY HOLIDAY 3315
-pcats_overlay MACH_PCATS_OVERLAY PCATS_OVERLAY 3317
-hwgw6410 MACH_HWGW6410 HWGW6410 3318
-shenzhou MACH_SHENZHOU SHENZHOU 3319
-cwme9210 MACH_CWME9210 CWME9210 3320
-cwme9210js MACH_CWME9210JS CWME9210JS 3321
-colibri_tegra2 MACH_COLIBRI_TEGRA2 COLIBRI_TEGRA2 3323
-w21 MACH_W21 W21 3324
-polysat1 MACH_POLYSAT1 POLYSAT1 3325
-dataway MACH_DATAWAY DATAWAY 3326
-cobral138 MACH_COBRAL138 COBRAL138 3327
-roverpcs8 MACH_ROVERPCS8 ROVERPCS8 3328
-marvelc MACH_MARVELC MARVELC 3329
-navefihid MACH_NAVEFIHID NAVEFIHID 3330
-dm365_cv100 MACH_DM365_CV100 DM365_CV100 3331
-able MACH_ABLE ABLE 3332
-legacy MACH_LEGACY LEGACY 3333
-icong MACH_ICONG ICONG 3334
-rover_g8 MACH_ROVER_G8 ROVER_G8 3335
-t5388p MACH_T5388P T5388P 3336
-dingo MACH_DINGO DINGO 3337
-goflexhome MACH_GOFLEXHOME GOFLEXHOME 3338
-lanreadyfn511 MACH_LANREADYFN511 LANREADYFN511 3340
-omap3_baia MACH_OMAP3_BAIA OMAP3_BAIA 3341
-omap3smartdisplay MACH_OMAP3SMARTDISPLAY OMAP3SMARTDISPLAY 3342
-xilinx MACH_XILINX XILINX 3343
-a2f MACH_A2F A2F 3344
-sky25 MACH_SKY25 SKY25 3345
-ccmx53 MACH_CCMX53 CCMX53 3346
-ccmx53js MACH_CCMX53JS CCMX53JS 3347
-ccwmx53 MACH_CCWMX53 CCWMX53 3348
-ccwmx53js MACH_CCWMX53JS CCWMX53JS 3349
-frisms MACH_FRISMS FRISMS 3350
-msm7x27a_ffa MACH_MSM7X27A_FFA MSM7X27A_FFA 3351
-msm7x27a_surf MACH_MSM7X27A_SURF MSM7X27A_SURF 3352
-msm7x27a_rumi3 MACH_MSM7X27A_RUMI3 MSM7X27A_RUMI3 3353
-dimmsam9g20 MACH_DIMMSAM9G20 DIMMSAM9G20 3354
-dimm_imx28 MACH_DIMM_IMX28 DIMM_IMX28 3355
-amk_a4 MACH_AMK_A4 AMK_A4 3356
-gnet_sgme MACH_GNET_SGME GNET_SGME 3357
-shooter_u MACH_SHOOTER_U SHOOTER_U 3358
-vmx53 MACH_VMX53 VMX53 3359
-rhino MACH_RHINO RHINO 3360
armlex4210 MACH_ARMLEX4210 ARMLEX4210 3361
-swarcoextmodem MACH_SWARCOEXTMODEM SWARCOEXTMODEM 3362
snowball MACH_SNOWBALL SNOWBALL 3363
-pcm049 MACH_PCM049 PCM049 3364
-vigor MACH_VIGOR VIGOR 3365
-oslo_amundsen MACH_OSLO_AMUNDSEN OSLO_AMUNDSEN 3366
-gsl_diamond MACH_GSL_DIAMOND GSL_DIAMOND 3367
-cv2201 MACH_CV2201 CV2201 3368
-cv2202 MACH_CV2202 CV2202 3369
-cv2203 MACH_CV2203 CV2203 3370
-vit_ibox MACH_VIT_IBOX VIT_IBOX 3371
-dm6441_esp MACH_DM6441_ESP DM6441_ESP 3372
-at91sam9x5ek MACH_AT91SAM9X5EK AT91SAM9X5EK 3373
-libra MACH_LIBRA LIBRA 3374
-easycrrh MACH_EASYCRRH EASYCRRH 3375
-tripel MACH_TRIPEL TRIPEL 3376
-endian_mini MACH_ENDIAN_MINI ENDIAN_MINI 3377
xilinx_ep107 MACH_XILINX_EP107 XILINX_EP107 3378
nuri MACH_NURI NURI 3379
-janus MACH_JANUS JANUS 3380
-ddnas MACH_DDNAS DDNAS 3381
-tag MACH_TAG TAG 3382
-tagw MACH_TAGW TAGW 3383
-nitrogen_vm_imx51 MACH_NITROGEN_VM_IMX51 NITROGEN_VM_IMX51 3384
-viprinet MACH_VIPRINET VIPRINET 3385
-bockw MACH_BOCKW BOCKW 3386
-eva2000 MACH_EVA2000 EVA2000 3387
-steelyard MACH_STEELYARD STEELYARD 3388
-nsslsboard MACH_NSSLSBOARD NSSLSBOARD 3392
-geneva_b5 MACH_GENEVA_B5 GENEVA_B5 3393
-spear1340 MACH_SPEAR1340 SPEAR1340 3394
-rexmas MACH_REXMAS REXMAS 3395
-msm8960_cdp MACH_MSM8960_CDP MSM8960_CDP 3396
-msm8960_fluid MACH_MSM8960_FLUID MSM8960_FLUID 3398
-msm8960_apq MACH_MSM8960_APQ MSM8960_APQ 3399
-helios_v2 MACH_HELIOS_V2 HELIOS_V2 3400
-mif10p MACH_MIF10P MIF10P 3401
-iam28 MACH_IAM28 IAM28 3402
-picasso MACH_PICASSO PICASSO 3403
-mr301a MACH_MR301A MR301A 3404
-notle MACH_NOTLE NOTLE 3405
-eelx2 MACH_EELX2 EELX2 3406
-moon MACH_MOON MOON 3407
-ruby MACH_RUBY RUBY 3408
-goldengate MACH_GOLDENGATE GOLDENGATE 3409
-ctbu_gen2 MACH_CTBU_GEN2 CTBU_GEN2 3410
-kmp_am17_01 MACH_KMP_AM17_01 KMP_AM17_01 3411
wtplug MACH_WTPLUG WTPLUG 3412
-mx27su2 MACH_MX27SU2 MX27SU2 3413
-nb31 MACH_NB31 NB31 3414
-hjsdu MACH_HJSDU HJSDU 3415
-td3_rev1 MACH_TD3_REV1 TD3_REV1 3416
-eag_ci4000 MACH_EAG_CI4000 EAG_CI4000 3417
-net5big_nand_v2 MACH_NET5BIG_NAND_V2 NET5BIG_NAND_V2 3418
-cpx2 MACH_CPX2 CPX2 3419
-net2big_nand_v2 MACH_NET2BIG_NAND_V2 NET2BIG_NAND_V2 3420
-ecuv5 MACH_ECUV5 ECUV5 3421
-hsgx6d MACH_HSGX6D HSGX6D 3422
-dawad7 MACH_DAWAD7 DAWAD7 3423
-sam9repeater MACH_SAM9REPEATER SAM9REPEATER 3424
-gt_i5700 MACH_GT_I5700 GT_I5700 3425
-ctera_plug_c2 MACH_CTERA_PLUG_C2 CTERA_PLUG_C2 3426
-marvelct MACH_MARVELCT MARVELCT 3427
-ag11005 MACH_AG11005 AG11005 3428
-vangogh MACH_VANGOGH VANGOGH 3430
-matrix505 MACH_MATRIX505 MATRIX505 3431
-oce_nigma MACH_OCE_NIGMA OCE_NIGMA 3432
-t55 MACH_T55 T55 3433
-bio3k MACH_BIO3K BIO3K 3434
-expressct MACH_EXPRESSCT EXPRESSCT 3435
-cardhu MACH_CARDHU CARDHU 3436
-aruba MACH_ARUBA ARUBA 3437
-bonaire MACH_BONAIRE BONAIRE 3438
-nuc700evb MACH_NUC700EVB NUC700EVB 3439
-nuc710evb MACH_NUC710EVB NUC710EVB 3440
-nuc740evb MACH_NUC740EVB NUC740EVB 3441
-nuc745evb MACH_NUC745EVB NUC745EVB 3442
-transcede MACH_TRANSCEDE TRANSCEDE 3443
-mora MACH_MORA MORA 3444
-nda_evm MACH_NDA_EVM NDA_EVM 3445
-timu MACH_TIMU TIMU 3446
-expressh MACH_EXPRESSH EXPRESSH 3447
veridis_a300 MACH_VERIDIS_A300 VERIDIS_A300 3448
-dm368_leopard MACH_DM368_LEOPARD DM368_LEOPARD 3449
-omap_mcop MACH_OMAP_MCOP OMAP_MCOP 3450
-tritip MACH_TRITIP TRITIP 3451
-sm1k MACH_SM1K SM1K 3452
-monch MACH_MONCH MONCH 3453
-curacao MACH_CURACAO CURACAO 3454
origen MACH_ORIGEN ORIGEN 3455
-epc10 MACH_EPC10 EPC10 3456
-sgh_i740 MACH_SGH_I740 SGH_I740 3457
-tuna MACH_TUNA TUNA 3458
-mx51_tulip MACH_MX51_TULIP MX51_TULIP 3459
-mx51_aster7 MACH_MX51_ASTER7 MX51_ASTER7 3460
-acro37xbrd MACH_ACRO37XBRD ACRO37XBRD 3461
-elke MACH_ELKE ELKE 3462
-sbc6000x MACH_SBC6000X SBC6000X 3463
-r1801e MACH_R1801E R1801E 3464
-h1600 MACH_H1600 H1600 3465
-mini210 MACH_MINI210 MINI210 3466
-mini8168 MACH_MINI8168 MINI8168 3467
-pc7308 MACH_PC7308 PC7308 3468
-kmm2m01 MACH_KMM2M01 KMM2M01 3470
-mx51erebus MACH_MX51EREBUS MX51EREBUS 3471
wm8650refboard MACH_WM8650REFBOARD WM8650REFBOARD 3472
-tuxrail MACH_TUXRAIL TUXRAIL 3473
-arthur MACH_ARTHUR ARTHUR 3474
-doorboy MACH_DOORBOY DOORBOY 3475
xarina MACH_XARINA XARINA 3476
-roverx7 MACH_ROVERX7 ROVERX7 3477
sdvr MACH_SDVR SDVR 3478
acer_maya MACH_ACER_MAYA ACER_MAYA 3479
pico MACH_PICO PICO 3480
@@ -999,6 +770,7 @@ promwad_jade MACH_PROMWAD_JADE PROMWAD_JADE 3708
amp MACH_AMP AMP 3709
gnet_amp MACH_GNET_AMP GNET_AMP 3710
toques MACH_TOQUES TOQUES 3711
+apx4devkit MACH_APX4DEVKIT APX4DEVKIT 3712
dct_storm MACH_DCT_STORM DCT_STORM 3713
owl MACH_OWL OWL 3715
cogent_csb1741 MACH_COGENT_CSB1741 COGENT_CSB1741 3716
@@ -1063,7 +835,6 @@ shelter MACH_SHELTER SHELTER 3778
omap3_devkit8500 MACH_OMAP3_DEVKIT8500 OMAP3_DEVKIT8500 3779
edgetd MACH_EDGETD EDGETD 3780
copperyard MACH_COPPERYARD COPPERYARD 3781
-edge MACH_EDGE EDGE 3782
edge_u MACH_EDGE_U EDGE_U 3783
edge_td MACH_EDGE_TD EDGE_TD 3784
wdss MACH_WDSS WDSS 3785
@@ -1169,3 +940,269 @@ elite_ulk MACH_ELITE_ULK ELITE_ULK 3888
pov2 MACH_POV2 POV2 3889
ipod_touch_2g MACH_IPOD_TOUCH_2G IPOD_TOUCH_2G 3890
da850_pqab MACH_DA850_PQAB DA850_PQAB 3891
+fermi MACH_FERMI FERMI 3892
+ccardwmx28 MACH_CCARDWMX28 CCARDWMX28 3893
+ccardmx28 MACH_CCARDMX28 CCARDMX28 3894
+fs20_fcm2050 MACH_FS20_FCM2050 FS20_FCM2050 3895
+kinetis MACH_KINETIS KINETIS 3896
+kai MACH_KAI KAI 3897
+bcthb2 MACH_BCTHB2 BCTHB2 3898
+inels3_cu MACH_INELS3_CU INELS3_CU 3899
+da850_apollo MACH_DA850_APOLLO DA850_APOLLO 3901
+tracnas MACH_TRACNAS TRACNAS 3902
+mityarm335x MACH_MITYARM335X MITYARM335X 3903
+xcgz7x MACH_XCGZ7X XCGZ7X 3904
+cubox MACH_CUBOX CUBOX 3905
+terminator MACH_TERMINATOR TERMINATOR 3906
+eye03 MACH_EYE03 EYE03 3907
+kota3 MACH_KOTA3 KOTA3 3908
+pscpe MACH_PSCPE PSCPE 3910
+akt1100 MACH_AKT1100 AKT1100 3911
+pcaaxl2 MACH_PCAAXL2 PCAAXL2 3912
+primodd_ct MACH_PRIMODD_CT PRIMODD_CT 3913
+nsbc MACH_NSBC NSBC 3914
+meson2_skt MACH_MESON2_SKT MESON2_SKT 3915
+meson2_ref MACH_MESON2_REF MESON2_REF 3916
+ccardwmx28js MACH_CCARDWMX28JS CCARDWMX28JS 3917
+ccardmx28js MACH_CCARDMX28JS CCARDMX28JS 3918
+indico MACH_INDICO INDICO 3919
+msm8960dt MACH_MSM8960DT MSM8960DT 3920
+primods MACH_PRIMODS PRIMODS 3921
+beluga_m1388 MACH_BELUGA_M1388 BELUGA_M1388 3922
+primotd MACH_PRIMOTD PRIMOTD 3923
+varan_master MACH_VARAN_MASTER VARAN_MASTER 3924
+primodd MACH_PRIMODD PRIMODD 3925
+jetduo MACH_JETDUO JETDUO 3926
+mx53_umobo MACH_MX53_UMOBO MX53_UMOBO 3927
+trats MACH_TRATS TRATS 3928
+starcraft MACH_STARCRAFT STARCRAFT 3929
+qseven_tegra2 MACH_QSEVEN_TEGRA2 QSEVEN_TEGRA2 3930
+lichee_sun4i_devbd MACH_LICHEE_SUN4I_DEVBD LICHEE_SUN4I_DEVBD 3931
+movenow MACH_MOVENOW MOVENOW 3932
+golf_u MACH_GOLF_U GOLF_U 3933
+msm7627a_evb MACH_MSM7627A_EVB MSM7627A_EVB 3934
+rambo MACH_RAMBO RAMBO 3935
+golfu MACH_GOLFU GOLFU 3936
+mango310 MACH_MANGO310 MANGO310 3937
+dns343 MACH_DNS343 DNS343 3938
+var_som_om44 MACH_VAR_SOM_OM44 VAR_SOM_OM44 3939
+naon MACH_NAON NAON 3940
+vp4000 MACH_VP4000 VP4000 3941
+impcard MACH_IMPCARD IMPCARD 3942
+smoovcam MACH_SMOOVCAM SMOOVCAM 3943
+cobham3725 MACH_COBHAM3725 COBHAM3725 3944
+cobham3730 MACH_COBHAM3730 COBHAM3730 3945
+cobham3703 MACH_COBHAM3703 COBHAM3703 3946
+quetzal MACH_QUETZAL QUETZAL 3947
+apq8064_cdp MACH_APQ8064_CDP APQ8064_CDP 3948
+apq8064_mtp MACH_APQ8064_MTP APQ8064_MTP 3949
+apq8064_fluid MACH_APQ8064_FLUID APQ8064_FLUID 3950
+apq8064_liquid MACH_APQ8064_LIQUID APQ8064_LIQUID 3951
+mango210 MACH_MANGO210 MANGO210 3952
+mango100 MACH_MANGO100 MANGO100 3953
+mango24 MACH_MANGO24 MANGO24 3954
+mango64 MACH_MANGO64 MANGO64 3955
+nsa320 MACH_NSA320 NSA320 3956
+elv_ccu2 MACH_ELV_CCU2 ELV_CCU2 3957
+triton_x00 MACH_TRITON_X00 TRITON_X00 3958
+triton_1500_2000 MACH_TRITON_1500_2000 TRITON_1500_2000 3959
+pogoplugv4 MACH_POGOPLUGV4 POGOPLUGV4 3960
+venus_cl MACH_VENUS_CL VENUS_CL 3961
+vulcano_g20 MACH_VULCANO_G20 VULCANO_G20 3962
+sgs_i9100 MACH_SGS_I9100 SGS_I9100 3963
+stsv2 MACH_STSV2 STSV2 3964
+csb1724 MACH_CSB1724 CSB1724 3965
+omapl138_lcdk MACH_OMAPL138_LCDK OMAPL138_LCDK 3966
+pvd_mx25 MACH_PVD_MX25 PVD_MX25 3968
+meson6_skt MACH_MESON6_SKT MESON6_SKT 3969
+meson6_ref MACH_MESON6_REF MESON6_REF 3970
+pxm MACH_PXM PXM 3971
+pogoplugv3 MACH_POGOPLUGV3 POGOPLUGV3 3973
+mlp89626 MACH_MLP89626 MLP89626 3974
+iomegahmndce MACH_IOMEGAHMNDCE IOMEGAHMNDCE 3975
+pogoplugv3pci MACH_POGOPLUGV3PCI POGOPLUGV3PCI 3976
+bntv250 MACH_BNTV250 BNTV250 3977
+mx53_qseven MACH_MX53_QSEVEN MX53_QSEVEN 3978
+gtl_it1100 MACH_GTL_IT1100 GTL_IT1100 3979
+mx6q_sabresd MACH_MX6Q_SABRESD MX6Q_SABRESD 3980
+mt4 MACH_MT4 MT4 3981
+jumbo_d MACH_JUMBO_D JUMBO_D 3982
+jumbo_i MACH_JUMBO_I JUMBO_I 3983
+fs20_dmp MACH_FS20_DMP FS20_DMP 3984
+dns320 MACH_DNS320 DNS320 3985
+mx28bacos MACH_MX28BACOS MX28BACOS 3986
+tl80 MACH_TL80 TL80 3987
+polatis_nic_1001 MACH_POLATIS_NIC_1001 POLATIS_NIC_1001 3988
+tely MACH_TELY TELY 3989
+u8520 MACH_U8520 U8520 3990
+manta MACH_MANTA MANTA 3991
+mpq8064_cdp MACH_MPQ8064_CDP MPQ8064_CDP 3993
+mpq8064_dtv MACH_MPQ8064_DTV MPQ8064_DTV 3995
+dm368som MACH_DM368SOM DM368SOM 3996
+gprisb2 MACH_GPRISB2 GPRISB2 3997
+chammid MACH_CHAMMID CHAMMID 3998
+seoul2 MACH_SEOUL2 SEOUL2 3999
+omap4_nooktablet MACH_OMAP4_NOOKTABLET OMAP4_NOOKTABLET 4000
+aalto MACH_AALTO AALTO 4001
+metro MACH_METRO METRO 4002
+cydm3730 MACH_CYDM3730 CYDM3730 4003
+tqma53 MACH_TQMA53 TQMA53 4004
+msm7627a_qrd3 MACH_MSM7627A_QRD3 MSM7627A_QRD3 4005
+mx28_canby MACH_MX28_CANBY MX28_CANBY 4006
+tiger MACH_TIGER TIGER 4007
+pcats_9307_type_a MACH_PCATS_9307_TYPE_A PCATS_9307_TYPE_A 4008
+pcats_9307_type_o MACH_PCATS_9307_TYPE_O PCATS_9307_TYPE_O 4009
+pcats_9307_type_r MACH_PCATS_9307_TYPE_R PCATS_9307_TYPE_R 4010
+streamplug MACH_STREAMPLUG STREAMPLUG 4011
+icechicken_dev MACH_ICECHICKEN_DEV ICECHICKEN_DEV 4012
+hedgehog MACH_HEDGEHOG HEDGEHOG 4013
+yusend_obc MACH_YUSEND_OBC YUSEND_OBC 4014
+imxninja MACH_IMXNINJA IMXNINJA 4015
+omap4_jarod MACH_OMAP4_JAROD OMAP4_JAROD 4016
+eco5_pk MACH_ECO5_PK ECO5_PK 4017
+qj2440 MACH_QJ2440 QJ2440 4018
+mx6q_mercury MACH_MX6Q_MERCURY MX6Q_MERCURY 4019
+cm6810 MACH_CM6810 CM6810 4020
+omap4_torpedo MACH_OMAP4_TORPEDO OMAP4_TORPEDO 4021
+nsa310 MACH_NSA310 NSA310 4022
+tmx536 MACH_TMX536 TMX536 4023
+ktt20 MACH_KTT20 KTT20 4024
+dragonix MACH_DRAGONIX DRAGONIX 4025
+lungching MACH_LUNGCHING LUNGCHING 4026
+bulogics MACH_BULOGICS BULOGICS 4027
+mx535_sx MACH_MX535_SX MX535_SX 4028
+ngui3250 MACH_NGUI3250 NGUI3250 4029
+salutec_dac MACH_SALUTEC_DAC SALUTEC_DAC 4030
+loco MACH_LOCO LOCO 4031
+ctera_plug_usi MACH_CTERA_PLUG_USI CTERA_PLUG_USI 4032
+scepter MACH_SCEPTER SCEPTER 4033
+sga MACH_SGA SGA 4034
+p_81_j5 MACH_P_81_J5 P_81_J5 4035
+p_81_o4 MACH_P_81_O4 P_81_O4 4036
+msm8625_surf MACH_MSM8625_SURF MSM8625_SURF 4037
+carallon_shark MACH_CARALLON_SHARK CARALLON_SHARK 4038
+ordog MACH_ORDOG ORDOG 4040
+puente_io MACH_PUENTE_IO PUENTE_IO 4041
+msm8625_evb MACH_MSM8625_EVB MSM8625_EVB 4042
+ev_am1707 MACH_EV_AM1707 EV_AM1707 4043
+ev_am1707e2 MACH_EV_AM1707E2 EV_AM1707E2 4044
+ev_am3517e2 MACH_EV_AM3517E2 EV_AM3517E2 4045
+calabria MACH_CALABRIA CALABRIA 4046
+ev_imx287 MACH_EV_IMX287 EV_IMX287 4047
+erau MACH_ERAU ERAU 4048
+sichuan MACH_SICHUAN SICHUAN 4049
+davinci_da850 MACH_DAVINCI_DA850 DAVINCI_DA850 4051
+omap138_trunarc MACH_OMAP138_TRUNARC OMAP138_TRUNARC 4052
+bcm4761 MACH_BCM4761 BCM4761 4053
+picasso_e2 MACH_PICASSO_E2 PICASSO_E2 4054
+picasso_mf MACH_PICASSO_MF PICASSO_MF 4055
+miro MACH_MIRO MIRO 4056
+at91sam9g20ewon3 MACH_AT91SAM9G20EWON3 AT91SAM9G20EWON3 4057
+yoyo MACH_YOYO YOYO 4058
+windjkl MACH_WINDJKL WINDJKL 4059
+monarudo MACH_MONARUDO MONARUDO 4060
+batan MACH_BATAN BATAN 4061
+tadao MACH_TADAO TADAO 4062
+baso MACH_BASO BASO 4063
+mahon MACH_MAHON MAHON 4064
+villec2 MACH_VILLEC2 VILLEC2 4065
+asi1230 MACH_ASI1230 ASI1230 4066
+alaska MACH_ALASKA ALASKA 4067
+swarco_shdsl2 MACH_SWARCO_SHDSL2 SWARCO_SHDSL2 4068
+oxrtu MACH_OXRTU OXRTU 4069
+omap5_panda MACH_OMAP5_PANDA OMAP5_PANDA 4070
+c8000 MACH_C8000 C8000 4072
+bje_display3_5 MACH_BJE_DISPLAY3_5 BJE_DISPLAY3_5 4073
+picomod7 MACH_PICOMOD7 PICOMOD7 4074
+picocom5 MACH_PICOCOM5 PICOCOM5 4075
+qblissa8 MACH_QBLISSA8 QBLISSA8 4076
+armstonea8 MACH_ARMSTONEA8 ARMSTONEA8 4077
+netdcu14 MACH_NETDCU14 NETDCU14 4078
+at91sam9x5_epiphan MACH_AT91SAM9X5_EPIPHAN AT91SAM9X5_EPIPHAN 4079
+p2u MACH_P2U P2U 4080
+doris MACH_DORIS DORIS 4081
+j49 MACH_J49 J49 4082
+vdss2e MACH_VDSS2E VDSS2E 4083
+vc300 MACH_VC300 VC300 4084
+ns115_pad_test MACH_NS115_PAD_TEST NS115_PAD_TEST 4085
+ns115_pad_ref MACH_NS115_PAD_REF NS115_PAD_REF 4086
+ns115_phone_test MACH_NS115_PHONE_TEST NS115_PHONE_TEST 4087
+ns115_phone_ref MACH_NS115_PHONE_REF NS115_PHONE_REF 4088
+golfc MACH_GOLFC GOLFC 4089
+xerox_olympus MACH_XEROX_OLYMPUS XEROX_OLYMPUS 4090
+mx6sl_arm2 MACH_MX6SL_ARM2 MX6SL_ARM2 4091
+csb1701_csb1726 MACH_CSB1701_CSB1726 CSB1701_CSB1726 4092
+at91sam9xeek MACH_AT91SAM9XEEK AT91SAM9XEEK 4093
+ebv210 MACH_EBV210 EBV210 4094
+msm7627a_qrd7 MACH_MSM7627A_QRD7 MSM7627A_QRD7 4095
+svthin MACH_SVTHIN SVTHIN 4096
+duovero MACH_DUOVERO DUOVERO 4097
+chupacabra MACH_CHUPACABRA CHUPACABRA 4098
+scorpion MACH_SCORPION SCORPION 4099
+davinci_he_hmi10 MACH_DAVINCI_HE_HMI10 DAVINCI_HE_HMI10 4100
+topkick MACH_TOPKICK TOPKICK 4101
+m3_auguestrush MACH_M3_AUGUESTRUSH M3_AUGUESTRUSH 4102
+ipc335x MACH_IPC335X IPC335X 4103
+sun4i MACH_SUN4I SUN4I 4104
+imx233_olinuxino MACH_IMX233_OLINUXINO IMX233_OLINUXINO 4105
+k2_wl MACH_K2_WL K2_WL 4106
+k2_ul MACH_K2_UL K2_UL 4107
+k2_cl MACH_K2_CL K2_CL 4108
+minbari_w MACH_MINBARI_W MINBARI_W 4109
+minbari_m MACH_MINBARI_M MINBARI_M 4110
+k035 MACH_K035 K035 4111
+ariel MACH_ARIEL ARIEL 4112
+arielsaarc MACH_ARIELSAARC ARIELSAARC 4113
+arieldkb MACH_ARIELDKB ARIELDKB 4114
+armadillo810 MACH_ARMADILLO810 ARMADILLO810 4115
+tam335x MACH_TAM335X TAM335X 4116
+grouper MACH_GROUPER GROUPER 4117
+mpcsa21_9g20 MACH_MPCSA21_9G20 MPCSA21_9G20 4118
+m6u_cpu MACH_M6U_CPU M6U_CPU 4119
+davinci_dp10 MACH_DAVINCI_DP10 DAVINCI_DP10 4120
+ginkgo MACH_GINKGO GINKGO 4121
+cgt_qmx6 MACH_CGT_QMX6 CGT_QMX6 4122
+profpga MACH_PROFPGA PROFPGA 4123
+acfx100oc MACH_ACFX100OC ACFX100OC 4124
+acfx100nb MACH_ACFX100NB ACFX100NB 4125
+capricorn MACH_CAPRICORN CAPRICORN 4126
+pisces MACH_PISCES PISCES 4127
+aries MACH_ARIES ARIES 4128
+cancer MACH_CANCER CANCER 4129
+leo MACH_LEO LEO 4130
+virgo MACH_VIRGO VIRGO 4131
+sagittarius MACH_SAGITTARIUS SAGITTARIUS 4132
+devil MACH_DEVIL DEVIL 4133
+ballantines MACH_BALLANTINES BALLANTINES 4134
+omap3_procerusvpu MACH_OMAP3_PROCERUSVPU OMAP3_PROCERUSVPU 4135
+my27 MACH_MY27 MY27 4136
+sun6i MACH_SUN6I SUN6I 4137
+sun5i MACH_SUN5I SUN5I 4138
+mx512_mx MACH_MX512_MX MX512_MX 4139
+kzm9g MACH_KZM9G KZM9G 4140
+vdstbn MACH_VDSTBN VDSTBN 4141
+cfa10036 MACH_CFA10036 CFA10036 4142
+cfa10049 MACH_CFA10049 CFA10049 4143
+pcm051 MACH_PCM051 PCM051 4144
+vybrid_vf7xx MACH_VYBRID_VF7XX VYBRID_VF7XX 4145
+vybrid_vf6xx MACH_VYBRID_VF6XX VYBRID_VF6XX 4146
+vybrid_vf5xx MACH_VYBRID_VF5XX VYBRID_VF5XX 4147
+vybrid_vf4xx MACH_VYBRID_VF4XX VYBRID_VF4XX 4148
+aria_g25 MACH_ARIA_G25 ARIA_G25 4149
+bcm21553 MACH_BCM21553 BCM21553 4150
+smdk5410 MACH_SMDK5410 SMDK5410 4151
+lpc18xx MACH_LPC18XX LPC18XX 4152
+oratisparty MACH_ORATISPARTY ORATISPARTY 4153
+qseven MACH_QSEVEN QSEVEN 4154
+gmv_generic MACH_GMV_GENERIC GMV_GENERIC 4155
+th_link_eth MACH_TH_LINK_ETH TH_LINK_ETH 4156
+tn_muninn MACH_TN_MUNINN TN_MUNINN 4157
+rampage MACH_RAMPAGE RAMPAGE 4158
+visstrim_mv10 MACH_VISSTRIM_MV10 VISSTRIM_MV10 4159
+mx28_wilma MACH_MX28_WILMA MX28_WILMA 4164
+msm8625_ffa MACH_MSM8625_FFA MSM8625_FFA 4166
+vpu101 MACH_VPU101 VPU101 4167
+baileys MACH_BAILEYS BAILEYS 4169
+familybox MACH_FAMILYBOX FAMILYBOX 4170
+ensemble_mx35 MACH_ENSEMBLE_MX35 ENSEMBLE_MX35 4171
+sc_sps_1 MACH_SC_SPS_1 SC_SPS_1 4172
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index bc683b8219b5..586961929e96 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -11,6 +11,7 @@
#include <linux/types.h>
#include <linux/cpu.h>
#include <linux/cpu_pm.h>
+#include <linux/hardirq.h>
#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/signal.h>
@@ -240,11 +241,11 @@ static void vfp_panic(char *reason, u32 inst)
{
int i;
- printk(KERN_ERR "VFP: Error: %s\n", reason);
- printk(KERN_ERR "VFP: EXC 0x%08x SCR 0x%08x INST 0x%08x\n",
+ pr_err("VFP: Error: %s\n", reason);
+ pr_err("VFP: EXC 0x%08x SCR 0x%08x INST 0x%08x\n",
fmrx(FPEXC), fmrx(FPSCR), inst);
for (i = 0; i < 32; i += 2)
- printk(KERN_ERR "VFP: s%2u: 0x%08x s%2u: 0x%08x\n",
+ pr_err("VFP: s%2u: 0x%08x s%2u: 0x%08x\n",
i, vfp_get_float(i), i+1, vfp_get_float(i+1));
}
@@ -432,7 +433,10 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
static void vfp_enable(void *unused)
{
- u32 access = get_copro_access();
+ u32 access;
+
+ BUG_ON(preemptible());
+ access = get_copro_access();
/*
* Enable full access to VFP (cp10 and cp11)
@@ -448,7 +452,7 @@ static int vfp_pm_suspend(void)
/* if vfp is on, then save state for resumption */
if (fpexc & FPEXC_EN) {
- printk(KERN_DEBUG "%s: saving vfp state\n", __func__);
+ pr_debug("%s: saving vfp state\n", __func__);
vfp_save_state(&ti->vfpstate, fpexc);
/* disable, just in case */
@@ -573,12 +577,6 @@ int vfp_preserve_user_clear_hwstate(struct user_vfp __user *ufp,
* entry.
*/
hwstate->fpscr &= ~(FPSCR_LENGTH_MASK | FPSCR_STRIDE_MASK);
-
- /*
- * Disable VFP in the hwstate so that we can detect if it gets
- * used.
- */
- hwstate->fpexc &= ~FPEXC_EN;
return 0;
}
@@ -591,12 +589,8 @@ int vfp_restore_user_hwstate(struct user_vfp __user *ufp,
unsigned long fpexc;
int err = 0;
- /*
- * If VFP has been used, then disable it to avoid corrupting
- * the new thread state.
- */
- if (hwstate->fpexc & FPEXC_EN)
- vfp_flush_hwstate(thread);
+ /* Disable VFP to avoid corrupting the new thread state. */
+ vfp_flush_hwstate(thread);
/*
* Copy the floating point registers. There can be unused
@@ -657,7 +651,7 @@ static int __init vfp_init(void)
unsigned int cpu_arch = cpu_architecture();
if (cpu_arch >= CPU_ARCH_ARMv6)
- vfp_enable(NULL);
+ on_each_cpu(vfp_enable, NULL, 1);
/*
* First check that there is a VFP that we can use.
@@ -670,18 +664,16 @@ static int __init vfp_init(void)
barrier();
vfp_vector = vfp_null_entry;
- printk(KERN_INFO "VFP support v0.3: ");
+ pr_info("VFP support v0.3: ");
if (VFP_arch)
- printk("not present\n");
+ pr_cont("not present\n");
else if (vfpsid & FPSID_NODOUBLE) {
- printk("no double precision support\n");
+ pr_cont("no double precision support\n");
} else {
hotcpu_notifier(vfp_hotplug, 0);
- smp_call_function(vfp_enable, NULL, 1);
-
VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */
- printk("implementor %02x architecture %d part %02x variant %x rev %x\n",
+ pr_cont("implementor %02x architecture %d part %02x variant %x rev %x\n",
(vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT,
(vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT,
(vfpsid & FPSID_PART_MASK) >> FPSID_PART_BIT,
diff --git a/arch/avr32/include/asm/processor.h b/arch/avr32/include/asm/processor.h
index 108502bc6770..87d8baccc60e 100644
--- a/arch/avr32/include/asm/processor.h
+++ b/arch/avr32/include/asm/processor.h
@@ -145,9 +145,6 @@ extern void release_thread(struct task_struct *);
/* Create a kernel thread without removing it from tasklists */
extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while(0)
-
/* Return saved PC of a blocked thread */
#define thread_saved_pc(tsk) ((tsk)->thread.cpu_context.pc)
diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile
index 18229d0d1861..9e2c465ef3a6 100644
--- a/arch/avr32/kernel/Makefile
+++ b/arch/avr32/kernel/Makefile
@@ -8,7 +8,7 @@ obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o
obj-y += syscall_table.o syscall-stubs.o irq.o
obj-y += setup.o traps.o ocd.o ptrace.o
obj-y += signal.o sys_avr32.o process.o time.o
-obj-y += init_task.o switch_to.o cpu.o
+obj-y += switch_to.o cpu.o
obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff --git a/arch/avr32/kernel/init_task.c b/arch/avr32/kernel/init_task.c
deleted file mode 100644
index 6b2343e6fe33..000000000000
--- a/arch/avr32/kernel/init_task.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2004-2006 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/init_task.h>
-#include <linux/mqueue.h>
-
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial thread structure. Must be aligned on an 8192-byte boundary.
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
diff --git a/arch/blackfin/ADI_BSD.txt b/arch/blackfin/ADI_BSD.txt
deleted file mode 100644
index 501d0b645943..000000000000
--- a/arch/blackfin/ADI_BSD.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-This BSD-Style License applies to a few files in ./arch/blackfin directory,
-and is included here, so people understand which code they can use outside
-the Linux kernel, in non-GPL based projects.
-
-Using the files released under the "ADI BSD" license, must comply with
-these license terms.
-
---------------------------------------------------------------------------
-
-Copyright Analog Devices, Inc.
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- - Neither the name of Analog Devices, Inc. nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
- - The use of this software may or may not infringe the patent rights
- of one or more patent holders. This license does not release you
- from the requirement that you obtain separate licenses from these
- patent holders to use this software.
-
-THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
diff --git a/arch/blackfin/Clear_BSD.txt b/arch/blackfin/Clear_BSD.txt
new file mode 100644
index 000000000000..bfa4b378a368
--- /dev/null
+++ b/arch/blackfin/Clear_BSD.txt
@@ -0,0 +1,33 @@
+The Clear BSD license:
+
+Copyright (c) 2012, Analog Devices, Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted (subject to the limitations in the
+disclaimer below) provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of Analog Devices, Inc. nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index 373a6902d8fa..79cfe2614bcc 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -37,6 +37,7 @@ config BLACKFIN
select GENERIC_IRQ_PROBE
select IRQ_PER_CPU if SMP
select HAVE_NMI_WATCHDOG if NMI_WATCHDOG
+ select GENERIC_SMP_IDLE_THREAD
config GENERIC_CSUM
def_bool y
@@ -226,6 +227,12 @@ config BF561
help
BF561 Processor Support.
+config BF609
+ bool "BF609"
+ select CLKDEV_LOOKUP
+ help
+ BF609 Processor Support.
+
endchoice
config SMP
@@ -251,27 +258,27 @@ config HOTPLUG_CPU
config BF_REV_MIN
int
- default 0 if (BF51x || BF52x || (BF54x && !BF54xM))
+ default 0 if (BF51x || BF52x || (BF54x && !BF54xM)) || BF60x
default 2 if (BF537 || BF536 || BF534)
default 3 if (BF561 || BF533 || BF532 || BF531 || BF54xM)
default 4 if (BF538 || BF539)
config BF_REV_MAX
int
- default 2 if (BF51x || BF52x || (BF54x && !BF54xM))
+ default 2 if (BF51x || BF52x || (BF54x && !BF54xM)) || BF60x
default 3 if (BF537 || BF536 || BF534 || BF54xM)
default 5 if (BF561 || BF538 || BF539)
default 6 if (BF533 || BF532 || BF531)
choice
prompt "Silicon Rev"
- default BF_REV_0_0 if (BF51x || BF52x)
+ default BF_REV_0_0 if (BF51x || BF52x || BF60x)
default BF_REV_0_2 if (BF534 || BF536 || BF537 || (BF54x && !BF54xM))
default BF_REV_0_3 if (BF531 || BF532 || BF533 || BF54xM || BF561)
config BF_REV_0_0
bool "0.0"
- depends on (BF51x || BF52x || (BF54x && !BF54xM))
+ depends on (BF51x || BF52x || (BF54x && !BF54xM) || BF60x)
config BF_REV_0_1
bool "0.1"
@@ -350,6 +357,7 @@ source "arch/blackfin/mach-bf561/Kconfig"
source "arch/blackfin/mach-bf537/Kconfig"
source "arch/blackfin/mach-bf538/Kconfig"
source "arch/blackfin/mach-bf548/Kconfig"
+source "arch/blackfin/mach-bf609/Kconfig"
menu "Board customizations"
@@ -379,6 +387,12 @@ config BOOT_LOAD
memory region is used to capture NULL pointer references as well
as some core kernel functions.
+config PHY_RAM_BASE_ADDRESS
+ hex "Physical RAM Base"
+ default 0x0
+ help
+ set BF609 FPGA physical SRAM base address
+
config ROM_BASE
hex "Kernel ROM Base"
depends on ROMKERNEL
@@ -422,7 +436,7 @@ config BFIN_KERNEL_CLOCK
config PLL_BYPASS
bool "Bypass PLL"
- depends on BFIN_KERNEL_CLOCK
+ depends on BFIN_KERNEL_CLOCK && (!BF60x)
default n
config CLKIN_HALF
@@ -441,7 +455,7 @@ config VCO_MULT
default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN527_EZKIT_V2 || BFIN548_EZKIT || BFIN548_BLUETECHNIX_CM || BFIN538_EZKIT)
default "22" if BFIN533_BLUETECHNIX_CM
default "20" if (BFIN537_BLUETECHNIX_CM_E || BFIN537_BLUETECHNIX_CM_U || BFIN527_BLUETECHNIX_CM || BFIN561_BLUETECHNIX_CM)
- default "20" if BFIN561_EZKIT
+ default "20" if (BFIN561_EZKIT || BF609)
default "16" if (H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD || BFIN518F_EZBRD)
default "25" if BFIN527_AD7160EVAL
help
@@ -473,12 +487,45 @@ config SCLK_DIV
int "System Clock Divider"
depends on BFIN_KERNEL_CLOCK
range 1 15
- default 5
+ default 4
help
- This sets the frequency of the system clock (including SDRAM or DDR).
+ This sets the frequency of the system clock (including SDRAM or DDR) on
+ !BF60x else it set the clock for system buses and provides the
+ source from which SCLK0 and SCLK1 are derived.
This can be between 1 and 15
System Clock = (PLL frequency) / (this setting)
+config SCLK0_DIV
+ int "System Clock0 Divider"
+ depends on BFIN_KERNEL_CLOCK && BF60x
+ range 1 15
+ default 1
+ help
+ This sets the frequency of the system clock0 for PVP and all other
+ peripherals not clocked by SCLK1.
+ This can be between 1 and 15
+ System Clock0 = (System Clock) / (this setting)
+
+config SCLK1_DIV
+ int "System Clock1 Divider"
+ depends on BFIN_KERNEL_CLOCK && BF60x
+ range 1 15
+ default 1
+ help
+ This sets the frequency of the system clock1 (including SPORT, SPI and ACM).
+ This can be between 1 and 15
+ System Clock1 = (System Clock) / (this setting)
+
+config DCLK_DIV
+ int "DDR Clock Divider"
+ depends on BFIN_KERNEL_CLOCK && BF60x
+ range 1 15
+ default 2
+ help
+ This sets the frequency of the DDR memory.
+ This can be between 1 and 15
+ DDR Clock = (PLL frequency) / (this setting)
+
choice
prompt "DDR SDRAM Chip Type"
depends on BFIN_KERNEL_CLOCK
@@ -494,7 +541,7 @@ endchoice
choice
prompt "DDR/SDRAM Timing"
- depends on BFIN_KERNEL_CLOCK
+ depends on BFIN_KERNEL_CLOCK && !BF60x
default BFIN_KERNEL_CLOCK_MEMINIT_CALC
help
This option allows you to specify Blackfin SDRAM/DDR Timing parameters
@@ -576,6 +623,7 @@ config MAX_VCO_HZ
default 600000000 if BF548
default 533333333 if BF549
default 600000000 if BF561
+ default 800000000 if BF609
config MIN_VCO_HZ
int
@@ -583,6 +631,7 @@ config MIN_VCO_HZ
config MAX_SCLK_HZ
int
+ default 200000000 if BF609
default 133333333
config MIN_SCLK_HZ
@@ -1051,7 +1100,7 @@ endchoice
config BFIN_L2_DCACHEABLE
bool "Enable DCACHE for L2 SRAM"
depends on BFIN_DCACHE
- depends on (BF54x || BF561) && !SMP
+ depends on (BF54x || BF561 || BF60x) && !SMP
default n
choice
prompt "L2 SRAM DCACHE policy"
@@ -1077,6 +1126,7 @@ config MPU
comment "Asynchronous Memory Configuration"
menu "EBIU_AMGCTL Global Control"
+ depends on !BF60x
config C_AMCKEN
bool "Enable CLKOUT"
default y
@@ -1127,6 +1177,7 @@ endchoice
endmenu
menu "EBIU_AMBCTL Control"
+ depends on !BF60x
config BANK_0
hex "Bank 0 (AMBCTL0.L)"
default 0x7BB0
@@ -1206,7 +1257,7 @@ config ARCH_SUSPEND_POSSIBLE
choice
prompt "Standby Power Saving Mode"
- depends on PM
+ depends on PM && !BF60x
default PM_BFIN_SLEEP_DEEPER
config PM_BFIN_SLEEP_DEEPER
bool "Sleep Deeper"
@@ -1258,9 +1309,121 @@ config PM_BFIN_WAKE_GP
(all processors, except ADSP-BF549). This option sets
the general-purpose wake-up enable (GPWE) control bit to enable
wake-up upon detection of an active low signal on the /GPW (PH7) pin.
- On ADSP-BF549 this option enables the the same functionality on the
+ On ADSP-BF549 this option enables the same functionality on the
/MRXON pin also PH7.
+config PM_BFIN_WAKE_PA15
+ bool "Allow Wake-Up from PA15"
+ depends on PM && BF60x
+ default n
+ help
+ Enable PA15 Wake-Up
+
+config PM_BFIN_WAKE_PA15_POL
+ int "Wake-up priority"
+ depends on PM_BFIN_WAKE_PA15
+ default 0
+ help
+ Wake-Up priority 0(low) 1(high)
+
+config PM_BFIN_WAKE_PB15
+ bool "Allow Wake-Up from PB15"
+ depends on PM && BF60x
+ default n
+ help
+ Enable PB15 Wake-Up
+
+config PM_BFIN_WAKE_PB15_POL
+ int "Wake-up priority"
+ depends on PM_BFIN_WAKE_PB15
+ default 0
+ help
+ Wake-Up priority 0(low) 1(high)
+
+config PM_BFIN_WAKE_PC15
+ bool "Allow Wake-Up from PC15"
+ depends on PM && BF60x
+ default n
+ help
+ Enable PC15 Wake-Up
+
+config PM_BFIN_WAKE_PC15_POL
+ int "Wake-up priority"
+ depends on PM_BFIN_WAKE_PC15
+ default 0
+ help
+ Wake-Up priority 0(low) 1(high)
+
+config PM_BFIN_WAKE_PD06
+ bool "Allow Wake-Up from PD06(ETH0_PHYINT)"
+ depends on PM && BF60x
+ default n
+ help
+ Enable PD06(ETH0_PHYINT) Wake-up
+
+config PM_BFIN_WAKE_PD06_POL
+ int "Wake-up priority"
+ depends on PM_BFIN_WAKE_PD06
+ default 0
+ help
+ Wake-Up priority 0(low) 1(high)
+
+config PM_BFIN_WAKE_PE12
+ bool "Allow Wake-Up from PE12(ETH1_PHYINT, PUSH BUTTON)"
+ depends on PM && BF60x
+ default n
+ help
+ Enable PE12(ETH1_PHYINT, PUSH BUTTON) Wake-up
+
+config PM_BFIN_WAKE_PE12_POL
+ int "Wake-up priority"
+ depends on PM_BFIN_WAKE_PE12
+ default 0
+ help
+ Wake-Up priority 0(low) 1(high)
+
+config PM_BFIN_WAKE_PG04
+ bool "Allow Wake-Up from PG04(CAN0_RX)"
+ depends on PM && BF60x
+ default n
+ help
+ Enable PG04(CAN0_RX) Wake-up
+
+config PM_BFIN_WAKE_PG04_POL
+ int "Wake-up priority"
+ depends on PM_BFIN_WAKE_PG04
+ default 0
+ help
+ Wake-Up priority 0(low) 1(high)
+
+config PM_BFIN_WAKE_PG13
+ bool "Allow Wake-Up from PG13"
+ depends on PM && BF60x
+ default n
+ help
+ Enable PG13 Wake-Up
+
+config PM_BFIN_WAKE_PG13_POL
+ int "Wake-up priority"
+ depends on PM_BFIN_WAKE_PG13
+ default 0
+ help
+ Wake-Up priority 0(low) 1(high)
+
+config PM_BFIN_WAKE_USB
+ bool "Allow Wake-Up from (USB)"
+ depends on PM && BF60x
+ default n
+ help
+ Enable (USB) Wake-up
+
+config PM_BFIN_WAKE_USB_POL
+ int "Wake-up priority"
+ depends on PM_BFIN_WAKE_USB
+ default 0
+ help
+ Wake-Up priority 0(low) 1(high)
+
endmenu
menu "CPU Frequency scaling"
diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug
index e2a3d4c8ab9a..79594694ee90 100644
--- a/arch/blackfin/Kconfig.debug
+++ b/arch/blackfin/Kconfig.debug
@@ -253,4 +253,11 @@ config BFIN_PSEUDODBG_INSNS
Most people should say N here.
+config BFIN_PM_WAKEUP_TIME_BENCH
+ bool "Display the total time for kernel to resume from power saving mode"
+ default n
+ help
+ Display the total time when kernel resumes normal from standby or
+ suspend to mem mode.
+
endmenu
diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile
index 46f42b2066e5..d3d7e64ca96d 100644
--- a/arch/blackfin/Makefile
+++ b/arch/blackfin/Makefile
@@ -54,6 +54,7 @@ machine-$(CONFIG_BF548M) := bf548
machine-$(CONFIG_BF549) := bf548
machine-$(CONFIG_BF549M) := bf548
machine-$(CONFIG_BF561) := bf561
+machine-$(CONFIG_BF609) := bf609
MACHINE := $(machine-y)
export MACHINE
@@ -86,6 +87,7 @@ cpu-$(CONFIG_BF548M) := bf548m
cpu-$(CONFIG_BF549) := bf549
cpu-$(CONFIG_BF549M) := bf549m
cpu-$(CONFIG_BF561) := bf561
+cpu-$(CONFIG_BF609) := bf609
rev-$(CONFIG_BF_REV_0_0) := 0.0
rev-$(CONFIG_BF_REV_0_1) := 0.1
@@ -107,8 +109,6 @@ KBUILD_AFLAGS += -mcpu=$(CPU_REV)
CHECKFLAGS_SILICON = $(shell echo "" | $(CPP) $(KBUILD_CFLAGS) -dD - 2>/dev/null | awk '$$2 == "__SILICON_REVISION__" { print $$3 }')
CHECKFLAGS += -D__SILICON_REVISION__=$(CHECKFLAGS_SILICON) -D__bfin__
-head-y := arch/$(ARCH)/kernel/init_task.o
-
core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/ arch/$(ARCH)/mach-common/
# If we have a machine-specific directory, then include it in the build.
diff --git a/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig b/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig
index 680730eeaf23..e2a2fa5935ce 100644
--- a/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig
+++ b/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig
@@ -21,14 +21,12 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_IOSCHED_CFQ is not set
CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_BF561=y
+CONFIG_SMP=y
CONFIG_IRQ_TIMER0=10
CONFIG_CLKIN_HZ=30000000
CONFIG_HIGH_RES_TIMERS=y
CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
CONFIG_BFIN_GPTIMERS=m
-CONFIG_BFIN_EXTMEM_WRITETHROUGH=y
-CONFIG_BFIN_L2_DCACHEABLE=y
-CONFIG_BFIN_L2_WRITETHROUGH=y
CONFIG_C_CDPRIO=y
CONFIG_BANK_3=0xAAC2
CONFIG_BINFMT_FLAT=y
diff --git a/arch/blackfin/configs/BF609-EZKIT_defconfig b/arch/blackfin/configs/BF609-EZKIT_defconfig
new file mode 100644
index 000000000000..be9526bee4fb
--- /dev/null
+++ b/arch/blackfin/configs/BF609-EZKIT_defconfig
@@ -0,0 +1,155 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_FUTEX is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+CONFIG_SLAB=y
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_BF609=y
+CONFIG_PINT1_ASSIGN=0x01010000
+CONFIG_PINT2_ASSIGN=0x07000101
+CONFIG_PINT3_ASSIGN=0x02020303
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IP_CHECKSUM_L1=y
+CONFIG_SYSCALL_TAB_L1=y
+CONFIG_CPLB_SWITCH_TAB_L1=y
+# CONFIG_APP_STACK_L1 is not set
+# CONFIG_BFIN_INS_LOWOVERHEAD is not set
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM_BFIN_WAKE_PE12=y
+CONFIG_PM_BFIN_WAKE_PE12_POL=1
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+CONFIG_CAN=y
+CONFIG_CAN_BFIN=y
+CONFIG_IRDA=y
+CONFIG_IRTTY_SIR=y
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_FW_LOADER=m
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_UBI=m
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+CONFIG_STMMAC_ETH=y
+CONFIG_STMMAC_IEEE1588=y
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_BFIN_ROTARY=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_BFIN_SIMPLE_TIMER=m
+CONFIG_BFIN_LINKPORT=y
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
+CONFIG_SPI=y
+CONFIG_SPI_BFIN6XX=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_BFIN_WDT=y
+CONFIG_SOUND=m
+CONFIG_SND=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=m
+CONFIG_SND_BF6XX_I2S=m
+CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61=m
+CONFIG_SND_SOC_ALL_CODECS=m
+CONFIG_USB=y
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_BLACKFIN=m
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_ZERO=y
+CONFIG_MMC=y
+CONFIG_SDH_BFIN=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+# CONFIG_DNOTIFY is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_JFFS2_FS=m
+CONFIG_UBIFS_FS=m
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/include/asm/bfin-global.h b/arch/blackfin/include/asm/bfin-global.h
index 17bcbf60bcae..608be5e6d25c 100644
--- a/arch/blackfin/include/asm/bfin-global.h
+++ b/arch/blackfin/include/asm/bfin-global.h
@@ -35,6 +35,11 @@ extern void bfin_setup_cpudata(unsigned int cpu);
extern unsigned long get_cclk(void);
extern unsigned long get_sclk(void);
+#ifdef CONFIG_BF60x
+extern unsigned long get_sclk0(void);
+extern unsigned long get_sclk1(void);
+extern unsigned long get_dclk(void);
+#endif
extern unsigned long sclk_to_usecs(unsigned long sclk);
extern unsigned long usecs_to_sclk(unsigned long usecs);
diff --git a/arch/blackfin/include/asm/bfin6xx_spi.h b/arch/blackfin/include/asm/bfin6xx_spi.h
new file mode 100644
index 000000000000..89370b653dcd
--- /dev/null
+++ b/arch/blackfin/include/asm/bfin6xx_spi.h
@@ -0,0 +1,258 @@
+/*
+ * Analog Devices SPI3 controller driver
+ *
+ * Copyright (c) 2011 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _SPI_CHANNEL_H_
+#define _SPI_CHANNEL_H_
+
+#include <linux/types.h>
+
+/* SPI_CONTROL */
+#define SPI_CTL_EN 0x00000001 /* Enable */
+#define SPI_CTL_MSTR 0x00000002 /* Master/Slave */
+#define SPI_CTL_PSSE 0x00000004 /* controls modf error in master mode */
+#define SPI_CTL_ODM 0x00000008 /* Open Drain Mode */
+#define SPI_CTL_CPHA 0x00000010 /* Clock Phase */
+#define SPI_CTL_CPOL 0x00000020 /* Clock Polarity */
+#define SPI_CTL_ASSEL 0x00000040 /* Slave Select Pin Control */
+#define SPI_CTL_SELST 0x00000080 /* Slave Select Polarity in-between transfers */
+#define SPI_CTL_EMISO 0x00000100 /* Enable MISO */
+#define SPI_CTL_SIZE 0x00000600 /* Word Transfer Size */
+#define SPI_CTL_SIZE08 0x00000000 /* SIZE: 8 bits */
+#define SPI_CTL_SIZE16 0x00000200 /* SIZE: 16 bits */
+#define SPI_CTL_SIZE32 0x00000400 /* SIZE: 32 bits */
+#define SPI_CTL_LSBF 0x00001000 /* LSB First */
+#define SPI_CTL_FCEN 0x00002000 /* Flow-Control Enable */
+#define SPI_CTL_FCCH 0x00004000 /* Flow-Control Channel Selection */
+#define SPI_CTL_FCPL 0x00008000 /* Flow-Control Polarity */
+#define SPI_CTL_FCWM 0x00030000 /* Flow-Control Water-Mark */
+#define SPI_CTL_FIFO0 0x00000000 /* FCWM: TFIFO empty or RFIFO Full */
+#define SPI_CTL_FIFO1 0x00010000 /* FCWM: TFIFO 75% or more empty or RFIFO 75% or more full */
+#define SPI_CTL_FIFO2 0x00020000 /* FCWM: TFIFO 50% or more empty or RFIFO 50% or more full */
+#define SPI_CTL_FMODE 0x00040000 /* Fast-mode Enable */
+#define SPI_CTL_MIOM 0x00300000 /* Multiple I/O Mode */
+#define SPI_CTL_MIO_DIS 0x00000000 /* MIOM: Disable */
+#define SPI_CTL_MIO_DUAL 0x00100000 /* MIOM: Enable DIOM (Dual I/O Mode) */
+#define SPI_CTL_MIO_QUAD 0x00200000 /* MIOM: Enable QUAD (Quad SPI Mode) */
+#define SPI_CTL_SOSI 0x00400000 /* Start on MOSI */
+/* SPI_RX_CONTROL */
+#define SPI_RXCTL_REN 0x00000001 /* Receive Channel Enable */
+#define SPI_RXCTL_RTI 0x00000004 /* Receive Transfer Initiate */
+#define SPI_RXCTL_RWCEN 0x00000008 /* Receive Word Counter Enable */
+#define SPI_RXCTL_RDR 0x00000070 /* Receive Data Request */
+#define SPI_RXCTL_RDR_DIS 0x00000000 /* RDR: Disabled */
+#define SPI_RXCTL_RDR_NE 0x00000010 /* RDR: RFIFO not empty */
+#define SPI_RXCTL_RDR_25 0x00000020 /* RDR: RFIFO 25% full */
+#define SPI_RXCTL_RDR_50 0x00000030 /* RDR: RFIFO 50% full */
+#define SPI_RXCTL_RDR_75 0x00000040 /* RDR: RFIFO 75% full */
+#define SPI_RXCTL_RDR_FULL 0x00000050 /* RDR: RFIFO full */
+#define SPI_RXCTL_RDO 0x00000100 /* Receive Data Over-Run */
+#define SPI_RXCTL_RRWM 0x00003000 /* FIFO Regular Water-Mark */
+#define SPI_RXCTL_RWM_0 0x00000000 /* RRWM: RFIFO Empty */
+#define SPI_RXCTL_RWM_25 0x00001000 /* RRWM: RFIFO 25% full */
+#define SPI_RXCTL_RWM_50 0x00002000 /* RRWM: RFIFO 50% full */
+#define SPI_RXCTL_RWM_75 0x00003000 /* RRWM: RFIFO 75% full */
+#define SPI_RXCTL_RUWM 0x00070000 /* FIFO Urgent Water-Mark */
+#define SPI_RXCTL_UWM_DIS 0x00000000 /* RUWM: Disabled */
+#define SPI_RXCTL_UWM_25 0x00010000 /* RUWM: RFIFO 25% full */
+#define SPI_RXCTL_UWM_50 0x00020000 /* RUWM: RFIFO 50% full */
+#define SPI_RXCTL_UWM_75 0x00030000 /* RUWM: RFIFO 75% full */
+#define SPI_RXCTL_UWM_FULL 0x00040000 /* RUWM: RFIFO full */
+/* SPI_TX_CONTROL */
+#define SPI_TXCTL_TEN 0x00000001 /* Transmit Channel Enable */
+#define SPI_TXCTL_TTI 0x00000004 /* Transmit Transfer Initiate */
+#define SPI_TXCTL_TWCEN 0x00000008 /* Transmit Word Counter Enable */
+#define SPI_TXCTL_TDR 0x00000070 /* Transmit Data Request */
+#define SPI_TXCTL_TDR_DIS 0x00000000 /* TDR: Disabled */
+#define SPI_TXCTL_TDR_NF 0x00000010 /* TDR: TFIFO not full */
+#define SPI_TXCTL_TDR_25 0x00000020 /* TDR: TFIFO 25% empty */
+#define SPI_TXCTL_TDR_50 0x00000030 /* TDR: TFIFO 50% empty */
+#define SPI_TXCTL_TDR_75 0x00000040 /* TDR: TFIFO 75% empty */
+#define SPI_TXCTL_TDR_EMPTY 0x00000050 /* TDR: TFIFO empty */
+#define SPI_TXCTL_TDU 0x00000100 /* Transmit Data Under-Run */
+#define SPI_TXCTL_TRWM 0x00003000 /* FIFO Regular Water-Mark */
+#define SPI_TXCTL_RWM_FULL 0x00000000 /* TRWM: TFIFO full */
+#define SPI_TXCTL_RWM_25 0x00001000 /* TRWM: TFIFO 25% empty */
+#define SPI_TXCTL_RWM_50 0x00002000 /* TRWM: TFIFO 50% empty */
+#define SPI_TXCTL_RWM_75 0x00003000 /* TRWM: TFIFO 75% empty */
+#define SPI_TXCTL_TUWM 0x00070000 /* FIFO Urgent Water-Mark */
+#define SPI_TXCTL_UWM_DIS 0x00000000 /* TUWM: Disabled */
+#define SPI_TXCTL_UWM_25 0x00010000 /* TUWM: TFIFO 25% empty */
+#define SPI_TXCTL_UWM_50 0x00020000 /* TUWM: TFIFO 50% empty */
+#define SPI_TXCTL_UWM_75 0x00030000 /* TUWM: TFIFO 75% empty */
+#define SPI_TXCTL_UWM_EMPTY 0x00040000 /* TUWM: TFIFO empty */
+/* SPI_CLOCK */
+#define SPI_CLK_BAUD 0x0000FFFF /* Baud Rate */
+/* SPI_DELAY */
+#define SPI_DLY_STOP 0x000000FF /* Transfer delay time in multiples of SCK period */
+#define SPI_DLY_LEADX 0x00000100 /* Extended (1 SCK) LEAD Control */
+#define SPI_DLY_LAGX 0x00000200 /* Extended (1 SCK) LAG control */
+/* SPI_SSEL */
+#define SPI_SLVSEL_SSE1 0x00000002 /* SPISSEL1 Enable */
+#define SPI_SLVSEL_SSE2 0x00000004 /* SPISSEL2 Enable */
+#define SPI_SLVSEL_SSE3 0x00000008 /* SPISSEL3 Enable */
+#define SPI_SLVSEL_SSE4 0x00000010 /* SPISSEL4 Enable */
+#define SPI_SLVSEL_SSE5 0x00000020 /* SPISSEL5 Enable */
+#define SPI_SLVSEL_SSE6 0x00000040 /* SPISSEL6 Enable */
+#define SPI_SLVSEL_SSE7 0x00000080 /* SPISSEL7 Enable */
+#define SPI_SLVSEL_SSEL1 0x00000200 /* SPISSEL1 Value */
+#define SPI_SLVSEL_SSEL2 0x00000400 /* SPISSEL2 Value */
+#define SPI_SLVSEL_SSEL3 0x00000800 /* SPISSEL3 Value */
+#define SPI_SLVSEL_SSEL4 0x00001000 /* SPISSEL4 Value */
+#define SPI_SLVSEL_SSEL5 0x00002000 /* SPISSEL5 Value */
+#define SPI_SLVSEL_SSEL6 0x00004000 /* SPISSEL6 Value */
+#define SPI_SLVSEL_SSEL7 0x00008000 /* SPISSEL7 Value */
+/* SPI_RWC */
+#define SPI_RWC_VALUE 0x0000FFFF /* Received Word-Count */
+/* SPI_RWCR */
+#define SPI_RWCR_VALUE 0x0000FFFF /* Received Word-Count Reload */
+/* SPI_TWC */
+#define SPI_TWC_VALUE 0x0000FFFF /* Transmitted Word-Count */
+/* SPI_TWCR */
+#define SPI_TWCR_VALUE 0x0000FFFF /* Transmitted Word-Count Reload */
+/* SPI_IMASK */
+#define SPI_IMSK_RUWM 0x00000002 /* Receive Urgent Water-Mark Interrupt Mask */
+#define SPI_IMSK_TUWM 0x00000004 /* Transmit Urgent Water-Mark Interrupt Mask */
+#define SPI_IMSK_ROM 0x00000010 /* Receive Over-Run Error Interrupt Mask */
+#define SPI_IMSK_TUM 0x00000020 /* Transmit Under-Run Error Interrupt Mask */
+#define SPI_IMSK_TCM 0x00000040 /* Transmit Collision Error Interrupt Mask */
+#define SPI_IMSK_MFM 0x00000080 /* Mode Fault Error Interrupt Mask */
+#define SPI_IMSK_RSM 0x00000100 /* Receive Start Interrupt Mask */
+#define SPI_IMSK_TSM 0x00000200 /* Transmit Start Interrupt Mask */
+#define SPI_IMSK_RFM 0x00000400 /* Receive Finish Interrupt Mask */
+#define SPI_IMSK_TFM 0x00000800 /* Transmit Finish Interrupt Mask */
+/* SPI_IMASKCL */
+#define SPI_IMSK_CLR_RUW 0x00000002 /* Receive Urgent Water-Mark Interrupt Mask */
+#define SPI_IMSK_CLR_TUWM 0x00000004 /* Transmit Urgent Water-Mark Interrupt Mask */
+#define SPI_IMSK_CLR_ROM 0x00000010 /* Receive Over-Run Error Interrupt Mask */
+#define SPI_IMSK_CLR_TUM 0x00000020 /* Transmit Under-Run Error Interrupt Mask */
+#define SPI_IMSK_CLR_TCM 0x00000040 /* Transmit Collision Error Interrupt Mask */
+#define SPI_IMSK_CLR_MFM 0x00000080 /* Mode Fault Error Interrupt Mask */
+#define SPI_IMSK_CLR_RSM 0x00000100 /* Receive Start Interrupt Mask */
+#define SPI_IMSK_CLR_TSM 0x00000200 /* Transmit Start Interrupt Mask */
+#define SPI_IMSK_CLR_RFM 0x00000400 /* Receive Finish Interrupt Mask */
+#define SPI_IMSK_CLR_TFM 0x00000800 /* Transmit Finish Interrupt Mask */
+/* SPI_IMASKST */
+#define SPI_IMSK_SET_RUWM 0x00000002 /* Receive Urgent Water-Mark Interrupt Mask */
+#define SPI_IMSK_SET_TUWM 0x00000004 /* Transmit Urgent Water-Mark Interrupt Mask */
+#define SPI_IMSK_SET_ROM 0x00000010 /* Receive Over-Run Error Interrupt Mask */
+#define SPI_IMSK_SET_TUM 0x00000020 /* Transmit Under-Run Error Interrupt Mask */
+#define SPI_IMSK_SET_TCM 0x00000040 /* Transmit Collision Error Interrupt Mask */
+#define SPI_IMSK_SET_MFM 0x00000080 /* Mode Fault Error Interrupt Mask */
+#define SPI_IMSK_SET_RSM 0x00000100 /* Receive Start Interrupt Mask */
+#define SPI_IMSK_SET_TSM 0x00000200 /* Transmit Start Interrupt Mask */
+#define SPI_IMSK_SET_RFM 0x00000400 /* Receive Finish Interrupt Mask */
+#define SPI_IMSK_SET_TFM 0x00000800 /* Transmit Finish Interrupt Mask */
+/* SPI_STATUS */
+#define SPI_STAT_SPIF 0x00000001 /* SPI Finished */
+#define SPI_STAT_RUWM 0x00000002 /* Receive Urgent Water-Mark Breached */
+#define SPI_STAT_TUWM 0x00000004 /* Transmit Urgent Water-Mark Breached */
+#define SPI_STAT_ROE 0x00000010 /* Receive Over-Run Error Indication */
+#define SPI_STAT_TUE 0x00000020 /* Transmit Under-Run Error Indication */
+#define SPI_STAT_TCE 0x00000040 /* Transmit Collision Error Indication */
+#define SPI_STAT_MODF 0x00000080 /* Mode Fault Error Indication */
+#define SPI_STAT_RS 0x00000100 /* Receive Start Indication */
+#define SPI_STAT_TS 0x00000200 /* Transmit Start Indication */
+#define SPI_STAT_RF 0x00000400 /* Receive Finish Indication */
+#define SPI_STAT_TF 0x00000800 /* Transmit Finish Indication */
+#define SPI_STAT_RFS 0x00007000 /* SPI_RFIFO status */
+#define SPI_STAT_RFIFO_EMPTY 0x00000000 /* RFS: RFIFO Empty */
+#define SPI_STAT_RFIFO_25 0x00001000 /* RFS: RFIFO 25% Full */
+#define SPI_STAT_RFIFO_50 0x00002000 /* RFS: RFIFO 50% Full */
+#define SPI_STAT_RFIFO_75 0x00003000 /* RFS: RFIFO 75% Full */
+#define SPI_STAT_RFIFO_FULL 0x00004000 /* RFS: RFIFO Full */
+#define SPI_STAT_TFS 0x00070000 /* SPI_TFIFO status */
+#define SPI_STAT_TFIFO_FULL 0x00000000 /* TFS: TFIFO full */
+#define SPI_STAT_TFIFO_25 0x00010000 /* TFS: TFIFO 25% empty */
+#define SPI_STAT_TFIFO_50 0x00020000 /* TFS: TFIFO 50% empty */
+#define SPI_STAT_TFIFO_75 0x00030000 /* TFS: TFIFO 75% empty */
+#define SPI_STAT_TFIFO_EMPTY 0x00040000 /* TFS: TFIFO empty */
+#define SPI_STAT_FCS 0x00100000 /* Flow-Control Stall Indication */
+#define SPI_STAT_RFE 0x00400000 /* SPI_RFIFO Empty */
+#define SPI_STAT_TFF 0x00800000 /* SPI_TFIFO Full */
+/* SPI_ILAT */
+#define SPI_ILAT_RUWMI 0x00000002 /* Receive Urgent Water Mark Interrupt */
+#define SPI_ILAT_TUWMI 0x00000004 /* Transmit Urgent Water Mark Interrupt */
+#define SPI_ILAT_ROI 0x00000010 /* Receive Over-Run Error Indication */
+#define SPI_ILAT_TUI 0x00000020 /* Transmit Under-Run Error Indication */
+#define SPI_ILAT_TCI 0x00000040 /* Transmit Collision Error Indication */
+#define SPI_ILAT_MFI 0x00000080 /* Mode Fault Error Indication */
+#define SPI_ILAT_RSI 0x00000100 /* Receive Start Indication */
+#define SPI_ILAT_TSI 0x00000200 /* Transmit Start Indication */
+#define SPI_ILAT_RFI 0x00000400 /* Receive Finish Indication */
+#define SPI_ILAT_TFI 0x00000800 /* Transmit Finish Indication */
+/* SPI_ILATCL */
+#define SPI_ILAT_CLR_RUWMI 0x00000002 /* Receive Urgent Water Mark Interrupt */
+#define SPI_ILAT_CLR_TUWMI 0x00000004 /* Transmit Urgent Water Mark Interrupt */
+#define SPI_ILAT_CLR_ROI 0x00000010 /* Receive Over-Run Error Indication */
+#define SPI_ILAT_CLR_TUI 0x00000020 /* Transmit Under-Run Error Indication */
+#define SPI_ILAT_CLR_TCI 0x00000040 /* Transmit Collision Error Indication */
+#define SPI_ILAT_CLR_MFI 0x00000080 /* Mode Fault Error Indication */
+#define SPI_ILAT_CLR_RSI 0x00000100 /* Receive Start Indication */
+#define SPI_ILAT_CLR_TSI 0x00000200 /* Transmit Start Indication */
+#define SPI_ILAT_CLR_RFI 0x00000400 /* Receive Finish Indication */
+#define SPI_ILAT_CLR_TFI 0x00000800 /* Transmit Finish Indication */
+
+/*
+ * bfin spi3 registers layout
+ */
+struct bfin_spi_regs {
+ u32 revid;
+ u32 control;
+ u32 rx_control;
+ u32 tx_control;
+ u32 clock;
+ u32 delay;
+ u32 ssel;
+ u32 rwc;
+ u32 rwcr;
+ u32 twc;
+ u32 twcr;
+ u32 reserved0;
+ u32 emask;
+ u32 emaskcl;
+ u32 emaskst;
+ u32 reserved1;
+ u32 status;
+ u32 elat;
+ u32 elatcl;
+ u32 reserved2;
+ u32 rfifo;
+ u32 reserved3;
+ u32 tfifo;
+};
+
+#define MAX_CTRL_CS 8 /* cs in spi controller */
+
+/* device.platform_data for SSP controller devices */
+struct bfin6xx_spi_master {
+ u16 num_chipselect;
+ u16 pin_req[7];
+};
+
+/* spi_board_info.controller_data for SPI slave devices,
+ * copied to spi_device.platform_data ... mostly for dma tuning
+ */
+struct bfin6xx_spi_chip {
+ u32 control;
+ u16 cs_chg_udelay; /* Some devices require 16-bit delays */
+ u32 tx_dummy_val; /* tx value for rx only transfer */
+ bool enable_dma;
+};
+
+#endif /* _SPI_CHANNEL_H_ */
diff --git a/arch/blackfin/include/asm/bfin_crc.h b/arch/blackfin/include/asm/bfin_crc.h
new file mode 100644
index 000000000000..3deb4452ceed
--- /dev/null
+++ b/arch/blackfin/include/asm/bfin_crc.h
@@ -0,0 +1,139 @@
+/*
+ * bfin_crc.h - interface to Blackfin CRC controllers
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_CRC_H__
+#define __BFIN_CRC_H__
+
+/* Function driver which use hardware crc must initialize the structure */
+struct crc_info {
+ /* Input data address */
+ unsigned char *in_addr;
+ /* Output data address */
+ unsigned char *out_addr;
+ /* Input or output bytes */
+ unsigned long datasize;
+ union {
+ /* CRC to compare with that of input buffer */
+ unsigned long crc_compare;
+ /* Value to compare with input data */
+ unsigned long val_verify;
+ /* Value to fill */
+ unsigned long val_fill;
+ };
+ /* Value to program the 32b CRC Polynomial */
+ unsigned long crc_poly;
+ union {
+ /* CRC calculated from the input data */
+ unsigned long crc_result;
+ /* First failed position to verify input data */
+ unsigned long pos_verify;
+ };
+ /* CRC mirror flags */
+ unsigned int bitmirr:1;
+ unsigned int bytmirr:1;
+ unsigned int w16swp:1;
+ unsigned int fdsel:1;
+ unsigned int rsltmirr:1;
+ unsigned int polymirr:1;
+ unsigned int cmpmirr:1;
+};
+
+/* Userspace interface */
+#define CRC_IOC_MAGIC 'C'
+#define CRC_IOC_CALC_CRC _IOWR('C', 0x01, unsigned int)
+#define CRC_IOC_MEMCPY_CRC _IOWR('C', 0x02, unsigned int)
+#define CRC_IOC_VERIFY_VAL _IOWR('C', 0x03, unsigned int)
+#define CRC_IOC_FILL_VAL _IOWR('C', 0x04, unsigned int)
+
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/miscdevice.h>
+
+struct crc_register {
+ u32 control;
+ u32 datacnt;
+ u32 datacntrld;
+ u32 __pad_1[2];
+ u32 compare;
+ u32 fillval;
+ u32 datafifo;
+ u32 intren;
+ u32 intrenset;
+ u32 intrenclr;
+ u32 poly;
+ u32 __pad_2[4];
+ u32 status;
+ u32 datacntcap;
+ u32 __pad_3;
+ u32 result;
+ u32 curresult;
+ u32 __pad_4[3];
+ u32 revid;
+};
+
+struct bfin_crc {
+ struct miscdevice mdev;
+ struct list_head list;
+ int irq;
+ int dma_ch_src;
+ int dma_ch_dest;
+ volatile struct crc_register *regs;
+ struct crc_info *info;
+ struct mutex mutex;
+ struct completion c;
+ unsigned short opmode;
+ char name[20];
+};
+
+/* CRC_STATUS Masks */
+#define CMPERR 0x00000002 /* Compare error */
+#define DCNTEXP 0x00000010 /* datacnt register expired */
+#define IBR 0x00010000 /* Input buffer ready */
+#define OBR 0x00020000 /* Output buffer ready */
+#define IRR 0x00040000 /* Immediate result readt */
+#define LUTDONE 0x00080000 /* Look-up table generation done */
+#define FSTAT 0x00700000 /* FIFO status */
+#define MAX_FIFO 4 /* Max fifo size */
+
+/* CRC_CONTROL Masks */
+#define BLKEN 0x00000001 /* Block enable */
+#define OPMODE 0x000000F0 /* Operation mode */
+#define OPMODE_OFFSET 4 /* Operation mode mask offset*/
+#define MODE_DMACPY_CRC 1 /* MTM CRC compute and compare */
+#define MODE_DATA_FILL 2 /* MTM data fill */
+#define MODE_CALC_CRC 3 /* MSM CRC compute and compare */
+#define MODE_DATA_VERIFY 4 /* MSM data verify */
+#define AUTOCLRZ 0x00000100 /* Auto clear to zero */
+#define AUTOCLRF 0x00000200 /* Auto clear to one */
+#define OBRSTALL 0x00001000 /* Stall on output buffer ready */
+#define IRRSTALL 0x00002000 /* Stall on immediate result ready */
+#define BITMIRR 0x00010000 /* Mirror bits within each byte of 32-bit input data */
+#define BITMIRR_OFFSET 16 /* Mirror bits offset */
+#define BYTMIRR 0x00020000 /* Mirror bytes of 32-bit input data */
+#define BYTMIRR_OFFSET 17 /* Mirror bytes offset */
+#define W16SWP 0x00040000 /* Mirror uppper and lower 16-bit word of 32-bit input data */
+#define W16SWP_OFFSET 18 /* Mirror 16-bit word offset */
+#define FDSEL 0x00080000 /* FIFO is written after input data is mirrored */
+#define FDSEL_OFFSET 19 /* Mirror FIFO offset */
+#define RSLTMIRR 0x00100000 /* CRC result registers are mirrored. */
+#define RSLTMIRR_OFFSET 20 /* Mirror CRC result offset. */
+#define POLYMIRR 0x00200000 /* CRC poly register is mirrored. */
+#define POLYMIRR_OFFSET 21 /* Mirror CRC poly offset. */
+#define CMPMIRR 0x00400000 /* CRC compare register is mirrored. */
+#define CMPMIRR_OFFSET 22 /* Mirror CRC compare offset. */
+
+/* CRC_INTREN Masks */
+#define CMPERRI 0x02 /* CRC_ERROR_INTR */
+#define DCNTEXPI 0x10 /* CRC_STATUS_INTR */
+
+#endif
+
+#endif
diff --git a/arch/blackfin/include/asm/bfin_dma.h b/arch/blackfin/include/asm/bfin_dma.h
index d51120744148..6319f4e49083 100644
--- a/arch/blackfin/include/asm/bfin_dma.h
+++ b/arch/blackfin/include/asm/bfin_dma.h
@@ -15,12 +15,55 @@
#define DMAEN 0x0001 /* DMA Channel Enable */
#define WNR 0x0002 /* Channel Direction (W/R*) */
#define WDSIZE_8 0x0000 /* Transfer Word Size = 8 */
+#define PSIZE_8 0x00000000 /* Transfer Word Size = 16 */
+
+#ifdef CONFIG_BF60x
+
+#define PSIZE_16 0x00000010 /* Transfer Word Size = 16 */
+#define PSIZE_32 0x00000020 /* Transfer Word Size = 32 */
+#define PSIZE_64 0x00000030 /* Transfer Word Size = 32 */
+#define WDSIZE_16 0x00000100 /* Transfer Word Size = 16 */
+#define WDSIZE_32 0x00000200 /* Transfer Word Size = 32 */
+#define WDSIZE_64 0x00000300 /* Transfer Word Size = 32 */
+#define WDSIZE_128 0x00000400 /* Transfer Word Size = 32 */
+#define WDSIZE_256 0x00000500 /* Transfer Word Size = 32 */
+#define DMA2D 0x04000000 /* DMA Mode (2D/1D*) */
+#define RESTART 0x00000004 /* DMA Buffer Clear SYNC */
+#define DI_EN_X 0x00100000 /* Data Interrupt Enable in X count */
+#define DI_EN_Y 0x00200000 /* Data Interrupt Enable in Y count */
+#define DI_EN_P 0x00300000 /* Data Interrupt Enable in Peripheral */
+#define DI_EN DI_EN_X /* Data Interrupt Enable */
+#define NDSIZE_0 0x00000000 /* Next Descriptor Size = 1 */
+#define NDSIZE_1 0x00010000 /* Next Descriptor Size = 2 */
+#define NDSIZE_2 0x00020000 /* Next Descriptor Size = 3 */
+#define NDSIZE_3 0x00030000 /* Next Descriptor Size = 4 */
+#define NDSIZE_4 0x00040000 /* Next Descriptor Size = 5 */
+#define NDSIZE_5 0x00050000 /* Next Descriptor Size = 6 */
+#define NDSIZE_6 0x00060000 /* Next Descriptor Size = 7 */
+#define NDSIZE 0x00070000 /* Next Descriptor Size */
+#define NDSIZE_OFFSET 16 /* Next Descriptor Size Offset */
+#define DMAFLOW_LIST 0x00004000 /* Descriptor List Mode */
+#define DMAFLOW_LARGE DMAFLOW_LIST
+#define DMAFLOW_ARRAY 0x00005000 /* Descriptor Array Mode */
+#define DMAFLOW_LIST_DEMAND 0x00006000 /* Descriptor Demand List Mode */
+#define DMAFLOW_ARRAY_DEMAND 0x00007000 /* Descriptor Demand Array Mode */
+#define DMA_RUN_DFETCH 0x00000100 /* DMA Channel Running Indicator (DFETCH) */
+#define DMA_RUN 0x00000200 /* DMA Channel Running Indicator */
+#define DMA_RUN_WAIT_TRIG 0x00000300 /* DMA Channel Running Indicator (WAIT TRIG) */
+#define DMA_RUN_WAIT_ACK 0x00000400 /* DMA Channel Running Indicator (WAIT ACK) */
+
+#else
+
+#define PSIZE_16 0x0000 /* Transfer Word Size = 16 */
+#define PSIZE_32 0x0000 /* Transfer Word Size = 32 */
#define WDSIZE_16 0x0004 /* Transfer Word Size = 16 */
#define WDSIZE_32 0x0008 /* Transfer Word Size = 32 */
#define DMA2D 0x0010 /* DMA Mode (2D/1D*) */
#define RESTART 0x0020 /* DMA Buffer Clear */
#define DI_SEL 0x0040 /* Data Interrupt Timing Select */
#define DI_EN 0x0080 /* Data Interrupt Enable */
+#define DI_EN_X 0x00C0 /* Data Interrupt Enable in X count*/
+#define DI_EN_Y 0x0080 /* Data Interrupt Enable in Y count*/
#define NDSIZE_0 0x0000 /* Next Descriptor Size = 0 (Stop/Autobuffer) */
#define NDSIZE_1 0x0100 /* Next Descriptor Size = 1 */
#define NDSIZE_2 0x0200 /* Next Descriptor Size = 2 */
@@ -32,18 +75,26 @@
#define NDSIZE_8 0x0800 /* Next Descriptor Size = 8 */
#define NDSIZE_9 0x0900 /* Next Descriptor Size = 9 */
#define NDSIZE 0x0f00 /* Next Descriptor Size */
-#define DMAFLOW 0x7000 /* Flow Control */
-#define DMAFLOW_STOP 0x0000 /* Stop Mode */
-#define DMAFLOW_AUTO 0x1000 /* Autobuffer Mode */
+#define NDSIZE_OFFSET 8 /* Next Descriptor Size Offset */
#define DMAFLOW_ARRAY 0x4000 /* Descriptor Array Mode */
#define DMAFLOW_SMALL 0x6000 /* Small Model Descriptor List Mode */
#define DMAFLOW_LARGE 0x7000 /* Large Model Descriptor List Mode */
+#define DFETCH 0x0004 /* DMA Descriptor Fetch Indicator */
+#define DMA_RUN 0x0008 /* DMA Channel Running Indicator */
+
+#endif
+#define DMAFLOW 0x7000 /* Flow Control */
+#define DMAFLOW_STOP 0x0000 /* Stop Mode */
+#define DMAFLOW_AUTO 0x1000 /* Autobuffer Mode */
/* DMA_IRQ_STATUS Masks */
#define DMA_DONE 0x0001 /* DMA Completion Interrupt Status */
#define DMA_ERR 0x0002 /* DMA Error Interrupt Status */
-#define DFETCH 0x0004 /* DMA Descriptor Fetch Indicator */
-#define DMA_RUN 0x0008 /* DMA Channel Running Indicator */
+#ifdef CONFIG_BF60x
+#define DMA_PIRQ 0x0004 /* DMA Peripheral Error Interrupt Status */
+#else
+#define DMA_PIRQ 0
+#endif
/*
* All Blackfin system MMRs are padded to 32bits even if the register
@@ -57,6 +108,26 @@
struct bfin_dma_regs {
u32 next_desc_ptr;
u32 start_addr;
+#ifdef CONFIG_BF60x
+ u32 cfg;
+ u32 x_count;
+ u32 x_modify;
+ u32 y_count;
+ u32 y_modify;
+ u32 pad1;
+ u32 pad2;
+ u32 curr_desc_ptr;
+ u32 prev_desc_ptr;
+ u32 curr_addr;
+ u32 irq_status;
+ u32 curr_x_count;
+ u32 curr_y_count;
+ u32 pad3;
+ u32 bw_limit_count;
+ u32 curr_bw_limit_count;
+ u32 bw_monitor_count;
+ u32 curr_bw_monitor_count;
+#else
__BFP(config);
u32 __pad0;
__BFP(x_count);
@@ -71,8 +142,10 @@ struct bfin_dma_regs {
u32 __pad1;
__BFP(curr_y_count);
u32 __pad2;
+#endif
};
+#ifndef CONFIG_BF60x
/*
* bfin handshake mdma registers layout
*/
@@ -85,6 +158,7 @@ struct bfin_hmdma_regs {
__BFP(ecount);
__BFP(bcount);
};
+#endif
#undef __BFP
diff --git a/arch/blackfin/include/asm/bfin_pfmon.h b/arch/blackfin/include/asm/bfin_pfmon.h
index accd47e2db40..bf52e1f32257 100644
--- a/arch/blackfin/include/asm/bfin_pfmon.h
+++ b/arch/blackfin/include/asm/bfin_pfmon.h
@@ -3,7 +3,7 @@
*
* Copyright 2005-2011 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or GPL-2 (or later).
+ * Licensed under the Clear BSD license or GPL-2 (or later).
*/
#ifndef __ASM_BFIN_PFMON_H__
diff --git a/arch/blackfin/include/asm/bfin_ppi.h b/arch/blackfin/include/asm/bfin_ppi.h
index 3be05faa2c65..a4e872e16e75 100644
--- a/arch/blackfin/include/asm/bfin_ppi.h
+++ b/arch/blackfin/include/asm/bfin_ppi.h
@@ -10,6 +10,7 @@
#define __ASM_BFIN_PPI_H__
#include <linux/types.h>
+#include <asm/blackfin.h>
/*
* All Blackfin system MMRs are padded to 32bits even if the register
@@ -48,6 +49,133 @@ struct bfin_eppi_regs {
u32 clip;
};
+/*
+ * bfin eppi3 registers layout
+ */
+struct bfin_eppi3_regs {
+ u32 stat;
+ u32 hcnt;
+ u32 hdly;
+ u32 vcnt;
+ u32 vdly;
+ u32 frame;
+ u32 line;
+ u32 clkdiv;
+ u32 ctl;
+ u32 fs1_wlhb;
+ u32 fs1_paspl;
+ u32 fs2_wlvb;
+ u32 fs2_palpf;
+ u32 imsk;
+ u32 oddclip;
+ u32 evenclip;
+ u32 fs1_dly;
+ u32 fs2_dly;
+ u32 ctl2;
+};
+
#undef __BFP
+#ifdef EPPI0_CTL2
+#define EPPI_STAT_CFIFOERR 0x00000001 /* Chroma FIFO Error */
+#define EPPI_STAT_YFIFOERR 0x00000002 /* Luma FIFO Error */
+#define EPPI_STAT_LTERROVR 0x00000004 /* Line Track Overflow */
+#define EPPI_STAT_LTERRUNDR 0x00000008 /* Line Track Underflow */
+#define EPPI_STAT_FTERROVR 0x00000010 /* Frame Track Overflow */
+#define EPPI_STAT_FTERRUNDR 0x00000020 /* Frame Track Underflow */
+#define EPPI_STAT_ERRNCOR 0x00000040 /* Preamble Error Not Corrected */
+#define EPPI_STAT_PXPERR 0x00000080 /* PxP Ready Error */
+#define EPPI_STAT_ERRDET 0x00004000 /* Preamble Error Detected */
+#define EPPI_STAT_FLD 0x00008000 /* Current Field Received by EPPI */
+
+#define EPPI_HCNT_VALUE 0x0000FFFF /* Holds the number of samples to read in or write out per line, after PPIx_HDLY number of cycles have expired since the last assertion of PPIx_FS1 */
+
+#define EPPI_HDLY_VALUE 0x0000FFFF /* Number of PPIx_CLK cycles to delay after assertion of PPIx_FS1 before starting to read or write data */
+
+#define EPPI_VCNT_VALUE 0x0000FFFF /* Holds the number of lines to read in or write out, after PPIx_VDLY number of lines from the start of frame */
+
+#define EPPI_VDLY_VALUE 0x0000FFFF /* Number of lines to wait after the start of a new frame before starting to read/transmit data */
+
+#define EPPI_FRAME_VALUE 0x0000FFFF /* Holds the number of lines expected per frame of data */
+
+#define EPPI_LINE_VALUE 0x0000FFFF /* Holds the number of samples expected per line */
+
+#define EPPI_CLKDIV_VALUE 0x0000FFFF /* Internal clock divider */
+
+#define EPPI_CTL_EN 0x00000001 /* PPI Enable */
+#define EPPI_CTL_DIR 0x00000002 /* PPI Direction */
+#define EPPI_CTL_XFRTYPE 0x0000000C /* PPI Operating Mode */
+#define EPPI_CTL_ACTIVE656 0x00000000 /* XFRTYPE: ITU656 Active Video Only Mode */
+#define EPPI_CTL_ENTIRE656 0x00000004 /* XFRTYPE: ITU656 Entire Field Mode */
+#define EPPI_CTL_VERT656 0x00000008 /* XFRTYPE: ITU656 Vertical Blanking Only Mode */
+#define EPPI_CTL_NON656 0x0000000C /* XFRTYPE: Non-ITU656 Mode (GP Mode) */
+#define EPPI_CTL_FSCFG 0x00000030 /* Frame Sync Configuration */
+#define EPPI_CTL_SYNC0 0x00000000 /* FSCFG: Sync Mode 0 */
+#define EPPI_CTL_SYNC1 0x00000010 /* FSCFG: Sync Mode 1 */
+#define EPPI_CTL_SYNC2 0x00000020 /* FSCFG: Sync Mode 2 */
+#define EPPI_CTL_SYNC3 0x00000030 /* FSCFG: Sync Mode 3 */
+#define EPPI_CTL_FLDSEL 0x00000040 /* Field Select/Trigger */
+#define EPPI_CTL_ITUTYPE 0x00000080 /* ITU Interlace or Progressive */
+#define EPPI_CTL_BLANKGEN 0x00000100 /* ITU Output Mode with Internal Blanking Generation */
+#define EPPI_CTL_ICLKGEN 0x00000200 /* Internal Clock Generation */
+#define EPPI_CTL_IFSGEN 0x00000400 /* Internal Frame Sync Generation */
+#define EPPI_CTL_SIGNEXT 0x00000800 /* Sign Extension */
+#define EPPI_CTL_POLC 0x00003000 /* Frame Sync and Data Driving and Sampling Edges */
+#define EPPI_CTL_POLC0 0x00000000 /* POLC: Clock/Sync polarity mode 0 */
+#define EPPI_CTL_POLC1 0x00001000 /* POLC: Clock/Sync polarity mode 1 */
+#define EPPI_CTL_POLC2 0x00002000 /* POLC: Clock/Sync polarity mode 2 */
+#define EPPI_CTL_POLC3 0x00003000 /* POLC: Clock/Sync polarity mode 3 */
+#define EPPI_CTL_POLS 0x0000C000 /* Frame Sync Polarity */
+#define EPPI_CTL_FS1HI_FS2HI 0x00000000 /* POLS: FS1 and FS2 are active high */
+#define EPPI_CTL_FS1LO_FS2HI 0x00004000 /* POLS: FS1 is active low. FS2 is active high */
+#define EPPI_CTL_FS1HI_FS2LO 0x00008000 /* POLS: FS1 is active high. FS2 is active low */
+#define EPPI_CTL_FS1LO_FS2LO 0x0000C000 /* POLS: FS1 and FS2 are active low */
+#define EPPI_CTL_DLEN 0x00070000 /* Data Length */
+#define EPPI_CTL_DLEN08 0x00000000 /* DLEN: 8 bits */
+#define EPPI_CTL_DLEN10 0x00010000 /* DLEN: 10 bits */
+#define EPPI_CTL_DLEN12 0x00020000 /* DLEN: 12 bits */
+#define EPPI_CTL_DLEN14 0x00030000 /* DLEN: 14 bits */
+#define EPPI_CTL_DLEN16 0x00040000 /* DLEN: 16 bits */
+#define EPPI_CTL_DLEN18 0x00050000 /* DLEN: 18 bits */
+#define EPPI_CTL_DLEN20 0x00060000 /* DLEN: 20 bits */
+#define EPPI_CTL_DLEN24 0x00070000 /* DLEN: 24 bits */
+#define EPPI_CTL_DMIRR 0x00080000 /* Data Mirroring */
+#define EPPI_CTL_SKIPEN 0x00100000 /* Skip Enable */
+#define EPPI_CTL_SKIPEO 0x00200000 /* Skip Even or Odd */
+#define EPPI_CTL_PACKEN 0x00400000 /* Pack/Unpack Enable */
+#define EPPI_CTL_SWAPEN 0x00800000 /* Swap Enable */
+#define EPPI_CTL_SPLTEO 0x01000000 /* Split Even and Odd Data Samples */
+#define EPPI_CTL_SUBSPLTODD 0x02000000 /* Sub-Split Odd Samples */
+#define EPPI_CTL_SPLTWRD 0x04000000 /* Split Word */
+#define EPPI_CTL_RGBFMTEN 0x08000000 /* RGB Formatting Enable */
+#define EPPI_CTL_DMACFG 0x10000000 /* One or Two DMA Channels Mode */
+#define EPPI_CTL_DMAFINEN 0x20000000 /* DMA Finish Enable */
+#define EPPI_CTL_MUXSEL 0x40000000 /* MUX Select */
+#define EPPI_CTL_CLKGATEN 0x80000000 /* Clock Gating Enable */
+
+#define EPPI_FS2_WLVB_F2VBAD 0xFF000000 /* In GP transmit mode with BLANKGEN = 1, contains number of lines of vertical blanking after field 2 */
+#define EPPI_FS2_WLVB_F2VBBD 0x00FF0000 /* In GP transmit mode with BLANKGEN = 1, contains number of lines of vertical blanking before field 2 */
+#define EPPI_FS2_WLVB_F1VBAD 0x0000FF00 /* In GP transmit mode with, BLANKGEN = 1, contains number of lines of vertical blanking after field 1 */
+#define EPPI_FS2_WLVB_F1VBBD 0x000000FF /* In GP 2, or 3 FS modes used to generate PPIx_FS2 width (32-bit). In GP Transmit mode, with BLANKGEN=1, contains the number of lines of Vertical blanking before field 1. */
+
+#define EPPI_FS2_PALPF_F2ACT 0xFFFF0000 /* Number of lines of Active Data in Field 2 */
+#define EPPI_FS2_PALPF_F1ACT 0x0000FFFF /* Number of lines of Active Data in Field 1 */
+
+#define EPPI_IMSK_CFIFOERR 0x00000001 /* Mask CFIFO Underflow or Overflow Error Interrupt */
+#define EPPI_IMSK_YFIFOERR 0x00000002 /* Mask YFIFO Underflow or Overflow Error Interrupt */
+#define EPPI_IMSK_LTERROVR 0x00000004 /* Mask Line Track Overflow Error Interrupt */
+#define EPPI_IMSK_LTERRUNDR 0x00000008 /* Mask Line Track Underflow Error Interrupt */
+#define EPPI_IMSK_FTERROVR 0x00000010 /* Mask Frame Track Overflow Error Interrupt */
+#define EPPI_IMSK_FTERRUNDR 0x00000020 /* Mask Frame Track Underflow Error Interrupt */
+#define EPPI_IMSK_ERRNCOR 0x00000040 /* Mask ITU Preamble Error Not Corrected Interrupt */
+#define EPPI_IMSK_PXPERR 0x00000080 /* Mask PxP Ready Error Interrupt */
+
+#define EPPI_ODDCLIP_HIGHODD 0xFFFF0000
+#define EPPI_ODDCLIP_LOWODD 0x0000FFFF
+
+#define EPPI_EVENCLIP_HIGHEVEN 0xFFFF0000
+#define EPPI_EVENCLIP_LOWEVEN 0x0000FFFF
+
+#define EPPI_CTL2_FS1FINEN 0x00000002 /* HSYNC Finish Enable */
+#endif
#endif
diff --git a/arch/blackfin/include/asm/bfin_rotary.h b/arch/blackfin/include/asm/bfin_rotary.h
index 0b6910bdc57f..8895a750c70c 100644
--- a/arch/blackfin/include/asm/bfin_rotary.h
+++ b/arch/blackfin/include/asm/bfin_rotary.h
@@ -39,6 +39,7 @@ struct bfin_rotary_platform_data {
unsigned int rotary_rel_code;
unsigned short debounce; /* 0..17 */
unsigned short mode;
+ unsigned short pm_wakeup;
};
/* CNT_CONFIG bitmasks */
diff --git a/arch/blackfin/include/asm/bfin_serial.h b/arch/blackfin/include/asm/bfin_serial.h
index 68bcc3d119b6..8597158010b5 100644
--- a/arch/blackfin/include/asm/bfin_serial.h
+++ b/arch/blackfin/include/asm/bfin_serial.h
@@ -18,7 +18,7 @@
defined(CONFIG_BFIN_UART1_CTSRTS) || \
defined(CONFIG_BFIN_UART2_CTSRTS) || \
defined(CONFIG_BFIN_UART3_CTSRTS)
-# ifdef BFIN_UART_BF54X_STYLE
+# if defined(BFIN_UART_BF54X_STYLE) || defined(BFIN_UART_BF60X_STYLE)
# define CONFIG_SERIAL_BFIN_HARD_CTSRTS
# else
# define CONFIG_SERIAL_BFIN_CTSRTS
@@ -58,14 +58,69 @@ struct bfin_serial_port {
#endif
};
+#ifdef BFIN_UART_BF60X_STYLE
+
+/* UART_CTL Masks */
+#define UCEN 0x1 /* Enable UARTx Clocks */
+#define LOOP_ENA 0x2 /* Loopback Mode Enable */
+#define UMOD_MDB 0x10 /* Enable MDB Mode */
+#define UMOD_IRDA 0x20 /* Enable IrDA Mode */
+#define UMOD_MASK 0x30 /* Uart Mode Mask */
+#define WLS(x) (((x-5) & 0x03) << 8) /* Word Length Select */
+#define WLS_MASK 0x300 /* Word length Select Mask */
+#define WLS_OFFSET 8 /* Word length Select Offset */
+#define STB 0x1000 /* Stop Bits */
+#define STBH 0x2000 /* Half Stop Bits */
+#define PEN 0x4000 /* Parity Enable */
+#define EPS 0x8000 /* Even Parity Select */
+#define STP 0x10000 /* Stick Parity */
+#define FPE 0x20000 /* Force Parity Error On Transmit */
+#define FFE 0x40000 /* Force Framing Error On Transmit */
+#define SB 0x80000 /* Set Break */
+#define LCR_MASK (SB | STP | EPS | PEN | STB | WLS_MASK)
+#define FCPOL 0x400000 /* Flow Control Pin Polarity */
+#define RPOLC 0x800000 /* IrDA RX Polarity Change */
+#define TPOLC 0x1000000 /* IrDA TX Polarity Change */
+#define MRTS 0x2000000 /* Manual Request To Send */
+#define XOFF 0x4000000 /* Transmitter Off */
+#define ARTS 0x8000000 /* Automatic Request To Send */
+#define ACTS 0x10000000 /* Automatic Clear To Send */
+#define RFIT 0x20000000 /* Receive FIFO IRQ Threshold */
+#define RFRT 0x40000000 /* Receive FIFO RTS Threshold */
+
+/* UART_STAT Masks */
+#define DR 0x01 /* Data Ready */
+#define OE 0x02 /* Overrun Error */
+#define PE 0x04 /* Parity Error */
+#define FE 0x08 /* Framing Error */
+#define BI 0x10 /* Break Interrupt */
+#define THRE 0x20 /* THR Empty */
+#define TEMT 0x80 /* TSR and UART_THR Empty */
+#define TFI 0x100 /* Transmission Finished Indicator */
+
+#define ASTKY 0x200 /* Address Sticky */
+#define ADDR 0x400 /* Address bit status */
+#define RO 0x800 /* Reception Ongoing */
+#define SCTS 0x1000 /* Sticky CTS */
+#define CTS 0x10000 /* Clear To Send */
+#define RFCS 0x20000 /* Receive FIFO Count Status */
+
+/* UART_CLOCK Masks */
+#define EDBO 0x80000000 /* Enable Devide by One */
+
+#else /* BFIN_UART_BF60X_STYLE */
+
/* UART_LCR Masks */
#define WLS(x) (((x)-5) & 0x03) /* Word Length Select */
+#define WLS_MASK 0x03 /* Word length Select Mask */
+#define WLS_OFFSET 0 /* Word length Select Offset */
#define STB 0x04 /* Stop Bits */
#define PEN 0x08 /* Parity Enable */
#define EPS 0x10 /* Even Parity Select */
#define STP 0x20 /* Stick Parity */
#define SB 0x40 /* Set Break */
#define DLAB 0x80 /* Divisor Latch Access */
+#define LCR_MASK (SB | STP | EPS | PEN | STB | WLS_MASK)
/* UART_LSR Masks */
#define DR 0x01 /* Data Ready */
@@ -77,15 +132,6 @@ struct bfin_serial_port {
#define TEMT 0x40 /* TSR and UART_THR Empty */
#define TFI 0x80 /* Transmission Finished Indicator */
-/* UART_IER Masks */
-#define ERBFI 0x01 /* Enable Receive Buffer Full Interrupt */
-#define ETBEI 0x02 /* Enable Transmit Buffer Empty Interrupt */
-#define ELSI 0x04 /* Enable RX Status Interrupt */
-#define EDSSI 0x08 /* Enable Modem Status Interrupt */
-#define EDTPTI 0x10 /* Enable DMA Transmit PIRQ Interrupt */
-#define ETFI 0x20 /* Enable Transmission Finished Interrupt */
-#define ERFCI 0x40 /* Enable Receive FIFO Count Interrupt */
-
/* UART_MCR Masks */
#define XOFF 0x01 /* Transmitter Off */
#define MRTS 0x02 /* Manual Request To Send */
@@ -103,13 +149,36 @@ struct bfin_serial_port {
/* UART_GCTL Masks */
#define UCEN 0x01 /* Enable UARTx Clocks */
-#define IREN 0x02 /* Enable IrDA Mode */
+#define UMOD_IRDA 0x02 /* Enable IrDA Mode */
+#define UMOD_MASK 0x02 /* Uart Mode Mask */
#define TPOLC 0x04 /* IrDA TX Polarity Change */
#define RPOLC 0x08 /* IrDA RX Polarity Change */
#define FPE 0x10 /* Force Parity Error On Transmit */
#define FFE 0x20 /* Force Framing Error On Transmit */
-#ifdef BFIN_UART_BF54X_STYLE
+#endif /* BFIN_UART_BF60X_STYLE */
+
+/* UART_IER Masks */
+#define ERBFI 0x01 /* Enable Receive Buffer Full Interrupt */
+#define ETBEI 0x02 /* Enable Transmit Buffer Empty Interrupt */
+#define ELSI 0x04 /* Enable RX Status Interrupt */
+#define EDSSI 0x08 /* Enable Modem Status Interrupt */
+#define EDTPTI 0x10 /* Enable DMA Transmit PIRQ Interrupt */
+#define ETFI 0x20 /* Enable Transmission Finished Interrupt */
+#define ERFCI 0x40 /* Enable Receive FIFO Count Interrupt */
+
+#if defined(BFIN_UART_BF60X_STYLE)
+# define OFFSET_REDIV 0x00 /* Version ID Register */
+# define OFFSET_CTL 0x04 /* Control Register */
+# define OFFSET_STAT 0x08 /* Status Register */
+# define OFFSET_SCR 0x0C /* SCR Scratch Register */
+# define OFFSET_CLK 0x10 /* Clock Rate Register */
+# define OFFSET_IER 0x14 /* Interrupt Enable Register */
+# define OFFSET_IER_SET 0x18 /* Set Interrupt Enable Register */
+# define OFFSET_IER_CLEAR 0x1C /* Clear Interrupt Enable Register */
+# define OFFSET_RBR 0x20 /* Receive Buffer register */
+# define OFFSET_THR 0x24 /* Transmit Holding register */
+#elif defined(BFIN_UART_BF54X_STYLE)
# define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
# define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
# define OFFSET_GCTL 0x08 /* Global Control Register */
@@ -145,7 +214,23 @@ struct bfin_serial_port {
*/
#define __BFP(m) u16 m; u16 __pad_##m
struct bfin_uart_regs {
-#ifdef BFIN_UART_BF54X_STYLE
+#if defined(BFIN_UART_BF60X_STYLE)
+ u32 revid;
+ u32 ctl;
+ u32 stat;
+ u32 scr;
+ u32 clk;
+ u32 ier;
+ u32 ier_set;
+ u32 ier_clear;
+ u32 rbr;
+ u32 thr;
+ u32 taip;
+ u32 tsr;
+ u32 rsr;
+ u32 txdiv;
+ u32 rxdiv;
+#elif defined(BFIN_UART_BF54X_STYLE)
__BFP(dll);
__BFP(dlh);
__BFP(gctl);
@@ -182,13 +267,70 @@ struct bfin_uart_regs {
};
#undef __BFP
+#define port_membase(uart) (((struct bfin_serial_port *)(uart))->port.membase)
+
+/*
#ifndef port_membase
# define port_membase(p) 0
#endif
+*/
+#ifdef BFIN_UART_BF60X_STYLE
+
+#define UART_GET_CHAR(p) bfin_read32(port_membase(p) + OFFSET_RBR)
+#define UART_GET_CLK(p) bfin_read32(port_membase(p) + OFFSET_CLK)
+#define UART_GET_CTL(p) bfin_read32(port_membase(p) + OFFSET_CTL)
+#define UART_GET_GCTL(p) UART_GET_CTL(p)
+#define UART_GET_LCR(p) UART_GET_CTL(p)
+#define UART_GET_MCR(p) UART_GET_CTL(p)
+#if ANOMALY_05001001
+#define UART_GET_STAT(p) \
+({ \
+ u32 __ret; \
+ unsigned long flags; \
+ flags = hard_local_irq_save(); \
+ __ret = bfin_read32(port_membase(p) + OFFSET_STAT); \
+ hard_local_irq_restore(flags); \
+ __ret; \
+})
+#else
+#define UART_GET_STAT(p) bfin_read32(port_membase(p) + OFFSET_STAT)
+#endif
+#define UART_GET_MSR(p) UART_GET_STAT(p)
+
+#define UART_PUT_CHAR(p, v) bfin_write32(port_membase(p) + OFFSET_THR, v)
+#define UART_PUT_CLK(p, v) bfin_write32(port_membase(p) + OFFSET_CLK, v)
+#define UART_PUT_CTL(p, v) bfin_write32(port_membase(p) + OFFSET_CTL, v)
+#define UART_PUT_GCTL(p, v) UART_PUT_CTL(p, v)
+#define UART_PUT_LCR(p, v) UART_PUT_CTL(p, v)
+#define UART_PUT_MCR(p, v) UART_PUT_CTL(p, v)
+#define UART_PUT_STAT(p, v) bfin_write32(port_membase(p) + OFFSET_STAT, v)
+
+#define UART_CLEAR_IER(p, v) bfin_write32(port_membase(p) + OFFSET_IER_CLEAR, v)
+#define UART_GET_IER(p) bfin_read32(port_membase(p) + OFFSET_IER)
+#define UART_SET_IER(p, v) bfin_write32(port_membase(p) + OFFSET_IER_SET, v)
+
+#define UART_CLEAR_DLAB(p) /* MMRs not muxed on BF60x */
+#define UART_SET_DLAB(p) /* MMRs not muxed on BF60x */
+
+#define UART_CLEAR_LSR(p) UART_PUT_STAT(p, -1)
+#define UART_GET_LSR(p) UART_GET_STAT(p)
+#define UART_PUT_LSR(p, v) UART_PUT_STAT(p, v)
+
+/* This handles hard CTS/RTS */
+#define BFIN_UART_CTSRTS_HARD
+#define UART_CLEAR_SCTS(p) UART_PUT_STAT(p, SCTS)
+#define UART_GET_CTS(x) (UART_GET_MSR(x) & CTS)
+#define UART_DISABLE_RTS(x) UART_PUT_MCR(x, UART_GET_MCR(x) & ~(ARTS | MRTS))
+#define UART_ENABLE_RTS(x) UART_PUT_MCR(x, UART_GET_MCR(x) | MRTS | ARTS)
+#define UART_ENABLE_INTS(x, v) UART_SET_IER(x, v)
+#define UART_DISABLE_INTS(x) UART_CLEAR_IER(x, 0xF)
+
+#else /* BFIN_UART_BF60X_STYLE */
#define UART_GET_CHAR(p) bfin_read16(port_membase(p) + OFFSET_RBR)
#define UART_GET_DLL(p) bfin_read16(port_membase(p) + OFFSET_DLL)
#define UART_GET_DLH(p) bfin_read16(port_membase(p) + OFFSET_DLH)
+#define UART_GET_CLK(p) ((UART_GET_DLH(p) << 8) | UART_GET_DLL(p))
#define UART_GET_GCTL(p) bfin_read16(port_membase(p) + OFFSET_GCTL)
#define UART_GET_LCR(p) bfin_read16(port_membase(p) + OFFSET_LCR)
#define UART_GET_MCR(p) bfin_read16(port_membase(p) + OFFSET_MCR)
@@ -197,6 +339,11 @@ struct bfin_uart_regs {
#define UART_PUT_CHAR(p, v) bfin_write16(port_membase(p) + OFFSET_THR, v)
#define UART_PUT_DLL(p, v) bfin_write16(port_membase(p) + OFFSET_DLL, v)
#define UART_PUT_DLH(p, v) bfin_write16(port_membase(p) + OFFSET_DLH, v)
+#define UART_PUT_CLK(p, v) do \
+{\
+UART_PUT_DLL(p, v & 0xFF); \
+UART_PUT_DLH(p, (v >> 8) & 0xFF); } while (0);
+
#define UART_PUT_GCTL(p, v) bfin_write16(port_membase(p) + OFFSET_GCTL, v)
#define UART_PUT_LCR(p, v) bfin_write16(port_membase(p) + OFFSET_LCR, v)
#define UART_PUT_MCR(p, v) bfin_write16(port_membase(p) + OFFSET_MCR, v)
@@ -233,12 +380,17 @@ struct bfin_uart_regs {
#define UART_CLEAR_DLAB(p) do { UART_PUT_LCR(p, UART_GET_LCR(p) & ~DLAB); SSYNC(); } while (0)
#define UART_SET_DLAB(p) do { UART_PUT_LCR(p, UART_GET_LCR(p) | DLAB); SSYNC(); } while (0)
+#define get_lsr_cache(uart) (((struct bfin_serial_port *)(uart))->lsr)
+#define put_lsr_cache(uart, v) (((struct bfin_serial_port *)(uart))->lsr = (v))
+
+/*
#ifndef put_lsr_cache
# define put_lsr_cache(p, v)
#endif
#ifndef get_lsr_cache
# define get_lsr_cache(p) 0
#endif
+*/
/* The hardware clears the LSR bits upon read, so we need to cache
* some of the more fun bits in software so they don't get lost
@@ -267,7 +419,9 @@ static inline void UART_PUT_LSR(void *p, uint16_t val)
#define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
#define UART_DISABLE_INTS(x) UART_PUT_IER(x, 0)
-#endif
+#endif /* BFIN_UART_BF54X_STYLE */
+
+#endif /* BFIN_UART_BF60X_STYLE */
#ifndef BFIN_UART_TX_FIFO_SIZE
# define BFIN_UART_TX_FIFO_SIZE 2
diff --git a/arch/blackfin/include/asm/bfin_sport.h b/arch/blackfin/include/asm/bfin_sport.h
index 0afcfbd54a82..f8907ea6b5b6 100644
--- a/arch/blackfin/include/asm/bfin_sport.h
+++ b/arch/blackfin/include/asm/bfin_sport.h
@@ -24,6 +24,7 @@
struct sport_config {
/* TDM (multichannels), I2S or other mode */
unsigned int mode:3;
+ unsigned int polled; /* use poll instead of irq when set */
/* if TDM mode is selected, channels must be set */
int channels; /* Must be in 8 units */
diff --git a/arch/blackfin/include/asm/bfin_sport3.h b/arch/blackfin/include/asm/bfin_sport3.h
new file mode 100644
index 000000000000..03c00220d69b
--- /dev/null
+++ b/arch/blackfin/include/asm/bfin_sport3.h
@@ -0,0 +1,107 @@
+/*
+ * bfin_sport - Analog Devices BF6XX SPORT registers
+ *
+ * Copyright (c) 2012 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _BFIN_SPORT3_H_
+#define _BFIN_SPORT3_H_
+
+#include <linux/types.h>
+
+#define SPORT_CTL_SPENPRI 0x00000001 /* Enable Primary Channel */
+#define SPORT_CTL_DTYPE 0x00000006 /* Data type select */
+#define SPORT_CTL_RJUSTIFY_ZFILL 0x00000000 /* DTYPE: MCM mode: Right-justify, zero-fill unused MSBs */
+#define SPORT_CTL_RJUSTIFY_SFILL 0x00000002 /* DTYPE: MCM mode: Right-justify, sign-extend unused MSBs */
+#define SPORT_CTL_USE_U_LAW 0x00000004 /* DTYPE: MCM mode: Compand using u-law */
+#define SPORT_CTL_USE_A_LAW 0x00000006 /* DTYPE: MCM mode: Compand using A-law */
+#define SPORT_CTL_LSBF 0x00000008 /* Serial bit endian select */
+#define SPORT_CTL_SLEN 0x000001F0 /* Serial Word length select */
+#define SPORT_CTL_PACK 0x00000200 /* 16-bit to 32-bit packing enable */
+#define SPORT_CTL_ICLK 0x00000400 /* Internal Clock Select */
+#define SPORT_CTL_OPMODE 0x00000800 /* Operation mode */
+#define SPORT_CTL_CKRE 0x00001000 /* Clock rising edge select */
+#define SPORT_CTL_FSR 0x00002000 /* Frame Sync required */
+#define SPORT_CTL_IFS 0x00004000 /* Internal Frame Sync select */
+#define SPORT_CTL_DIFS 0x00008000 /* Data-independent frame sync select */
+#define SPORT_CTL_LFS 0x00010000 /* Active low frame sync select */
+#define SPORT_CTL_LAFS 0x00020000 /* Late Transmit frame select */
+#define SPORT_CTL_RJUST 0x00040000 /* Right Justified mode select */
+#define SPORT_CTL_FSED 0x00080000 /* External frame sync edge select */
+#define SPORT_CTL_TFIEN 0x00100000 /* Transmit finish interrrupt enable select */
+#define SPORT_CTL_GCLKEN 0x00200000 /* Gated clock mode select */
+#define SPORT_CTL_SPENSEC 0x01000000 /* Enable secondary channel */
+#define SPORT_CTL_SPTRAN 0x02000000 /* Data direction control */
+#define SPORT_CTL_DERRSEC 0x04000000 /* Secondary channel error status */
+#define SPORT_CTL_DXSSEC 0x18000000 /* Secondary channel data buffer status */
+#define SPORT_CTL_SEC_EMPTY 0x00000000 /* DXSSEC: Empty */
+#define SPORT_CTL_SEC_PART_FULL 0x10000000 /* DXSSEC: Partially full */
+#define SPORT_CTL_SEC_FULL 0x18000000 /* DXSSEC: Full */
+#define SPORT_CTL_DERRPRI 0x20000000 /* Primary channel error status */
+#define SPORT_CTL_DXSPRI 0xC0000000 /* Primary channel data buffer status */
+#define SPORT_CTL_PRM_EMPTY 0x00000000 /* DXSPRI: Empty */
+#define SPORT_CTL_PRM_PART_FULL 0x80000000 /* DXSPRI: Partially full */
+#define SPORT_CTL_PRM_FULL 0xC0000000 /* DXSPRI: Full */
+
+#define SPORT_DIV_CLKDIV 0x0000FFFF /* Clock divisor */
+#define SPORT_DIV_FSDIV 0xFFFF0000 /* Frame sync divisor */
+
+#define SPORT_MCTL_MCE 0x00000001 /* Multichannel enable */
+#define SPORT_MCTL_MCPDE 0x00000004 /* Multichannel data packing select */
+#define SPORT_MCTL_MFD 0x000000F0 /* Multichannel frame delay */
+#define SPORT_MCTL_WSIZE 0x00007F00 /* Number of multichannel slots */
+#define SPORT_MCTL_WOFFSET 0x03FF0000 /* Window offset size */
+
+#define SPORT_CNT_CLKCNT 0x0000FFFF /* Current state of clk div counter */
+#define SPORT_CNT_FSDIVCNT 0xFFFF0000 /* Current state of frame div counter */
+
+#define SPORT_ERR_DERRPMSK 0x00000001 /* Primary channel data error interrupt enable */
+#define SPORT_ERR_DERRSMSK 0x00000002 /* Secondary channel data error interrupt enable */
+#define SPORT_ERR_FSERRMSK 0x00000004 /* Frame sync error interrupt enable */
+#define SPORT_ERR_DERRPSTAT 0x00000010 /* Primary channel data error status */
+#define SPORT_ERR_DERRSSTAT 0x00000020 /* Secondary channel data error status */
+#define SPORT_ERR_FSERRSTAT 0x00000040 /* Frame sync error status */
+
+#define SPORT_MSTAT_CURCHAN 0x000003FF /* Channel which is being serviced in the multichannel operation */
+
+#define SPORT_CTL2_FSMUXSEL 0x00000001 /* Frame Sync MUX Select */
+#define SPORT_CTL2_CKMUXSEL 0x00000002 /* Clock MUX Select */
+#define SPORT_CTL2_LBSEL 0x00000004 /* Loopback Select */
+
+struct sport_register {
+ u32 spctl;
+ u32 div;
+ u32 spmctl;
+ u32 spcs0;
+ u32 spcs1;
+ u32 spcs2;
+ u32 spcs3;
+ u32 spcnt;
+ u32 sperrctl;
+ u32 spmstat;
+ u32 spctl2;
+ u32 txa;
+ u32 rxa;
+ u32 txb;
+ u32 rxb;
+ u32 revid;
+};
+
+struct bfin_snd_platform_data {
+ const unsigned short *pin_req;
+};
+
+#endif
diff --git a/arch/blackfin/include/asm/bfin_twi.h b/arch/blackfin/include/asm/bfin_twi.h
index e767d649dfc4..2f3339a47626 100644
--- a/arch/blackfin/include/asm/bfin_twi.h
+++ b/arch/blackfin/include/asm/bfin_twi.h
@@ -10,6 +10,7 @@
#define __ASM_BFIN_TWI_H__
#include <linux/types.h>
+#include <linux/i2c.h>
/*
* All Blackfin system MMRs are padded to 32bits even if the register
@@ -42,4 +43,145 @@ struct bfin_twi_regs {
#undef __BFP
+struct bfin_twi_iface {
+ int irq;
+ spinlock_t lock;
+ char read_write;
+ u8 command;
+ u8 *transPtr;
+ int readNum;
+ int writeNum;
+ int cur_mode;
+ int manual_stop;
+ int result;
+ struct i2c_adapter adap;
+ struct completion complete;
+ struct i2c_msg *pmsg;
+ int msg_num;
+ int cur_msg;
+ u16 saved_clkdiv;
+ u16 saved_control;
+ struct bfin_twi_regs *regs_base;
+};
+
+#define DEFINE_TWI_REG(reg_name, reg) \
+static inline u16 read_##reg_name(struct bfin_twi_iface *iface) \
+ { return iface->regs_base->reg; } \
+static inline void write_##reg_name(struct bfin_twi_iface *iface, u16 v) \
+ { iface->regs_base->reg = v; }
+
+DEFINE_TWI_REG(CLKDIV, clkdiv)
+DEFINE_TWI_REG(CONTROL, control)
+DEFINE_TWI_REG(SLAVE_CTL, slave_ctl)
+DEFINE_TWI_REG(SLAVE_STAT, slave_stat)
+DEFINE_TWI_REG(SLAVE_ADDR, slave_addr)
+DEFINE_TWI_REG(MASTER_CTL, master_ctl)
+DEFINE_TWI_REG(MASTER_STAT, master_stat)
+DEFINE_TWI_REG(MASTER_ADDR, master_addr)
+DEFINE_TWI_REG(INT_STAT, int_stat)
+DEFINE_TWI_REG(INT_MASK, int_mask)
+DEFINE_TWI_REG(FIFO_CTL, fifo_ctl)
+DEFINE_TWI_REG(FIFO_STAT, fifo_stat)
+DEFINE_TWI_REG(XMT_DATA8, xmt_data8)
+DEFINE_TWI_REG(XMT_DATA16, xmt_data16)
+#if !ANOMALY_05001001
+DEFINE_TWI_REG(RCV_DATA8, rcv_data8)
+DEFINE_TWI_REG(RCV_DATA16, rcv_data16)
+#else
+static inline u16 read_RCV_DATA8(struct bfin_twi_iface *iface)
+{
+ u16 ret;
+ unsigned long flags;
+
+ flags = hard_local_irq_save();
+ ret = iface->regs_base->rcv_data8;
+ hard_local_irq_restore(flags);
+
+ return ret;
+}
+
+static inline u16 read_RCV_DATA16(struct bfin_twi_iface *iface)
+{
+ u16 ret;
+ unsigned long flags;
+
+ flags = hard_local_irq_save();
+ ret = iface->regs_base->rcv_data16;
+ hard_local_irq_restore(flags);
+
+ return ret;
+}
+#endif
+
+
+/* ******************** TWO-WIRE INTERFACE (TWI) MASKS ***********************/
+/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y); ) */
+#define CLKLOW(x) ((x) & 0xFF) /* Periods Clock Is Held Low */
+#define CLKHI(y) (((y)&0xFF)<<0x8) /* Periods Before New Clock Low */
+
+/* TWI_PRESCALE Masks */
+#define PRESCALE 0x007F /* SCLKs Per Internal Time Reference (10MHz) */
+#define TWI_ENA 0x0080 /* TWI Enable */
+#define SCCB 0x0200 /* SCCB Compatibility Enable */
+
+/* TWI_SLAVE_CTL Masks */
+#define SEN 0x0001 /* Slave Enable */
+#define SADD_LEN 0x0002 /* Slave Address Length */
+#define STDVAL 0x0004 /* Slave Transmit Data Valid */
+#define NAK 0x0008 /* NAK/ACK* Generated At Conclusion Of Transfer */
+#define GEN 0x0010 /* General Call Address Matching Enabled */
+
+/* TWI_SLAVE_STAT Masks */
+#define SDIR 0x0001 /* Slave Transfer Direction (Transmit/Receive*) */
+#define GCALL 0x0002 /* General Call Indicator */
+
+/* TWI_MASTER_CTL Masks */
+#define MEN 0x0001 /* Master Mode Enable */
+#define MADD_LEN 0x0002 /* Master Address Length */
+#define MDIR 0x0004 /* Master Transmit Direction (RX/TX*) */
+#define FAST 0x0008 /* Use Fast Mode Timing Specs */
+#define STOP 0x0010 /* Issue Stop Condition */
+#define RSTART 0x0020 /* Repeat Start or Stop* At End Of Transfer */
+#define DCNT 0x3FC0 /* Data Bytes To Transfer */
+#define SDAOVR 0x4000 /* Serial Data Override */
+#define SCLOVR 0x8000 /* Serial Clock Override */
+
+/* TWI_MASTER_STAT Masks */
+#define MPROG 0x0001 /* Master Transfer In Progress */
+#define LOSTARB 0x0002 /* Lost Arbitration Indicator (Xfer Aborted) */
+#define ANAK 0x0004 /* Address Not Acknowledged */
+#define DNAK 0x0008 /* Data Not Acknowledged */
+#define BUFRDERR 0x0010 /* Buffer Read Error */
+#define BUFWRERR 0x0020 /* Buffer Write Error */
+#define SDASEN 0x0040 /* Serial Data Sense */
+#define SCLSEN 0x0080 /* Serial Clock Sense */
+#define BUSBUSY 0x0100 /* Bus Busy Indicator */
+
+/* TWI_INT_SRC and TWI_INT_ENABLE Masks */
+#define SINIT 0x0001 /* Slave Transfer Initiated */
+#define SCOMP 0x0002 /* Slave Transfer Complete */
+#define SERR 0x0004 /* Slave Transfer Error */
+#define SOVF 0x0008 /* Slave Overflow */
+#define MCOMP 0x0010 /* Master Transfer Complete */
+#define MERR 0x0020 /* Master Transfer Error */
+#define XMTSERV 0x0040 /* Transmit FIFO Service */
+#define RCVSERV 0x0080 /* Receive FIFO Service */
+
+/* TWI_FIFO_CTRL Masks */
+#define XMTFLUSH 0x0001 /* Transmit Buffer Flush */
+#define RCVFLUSH 0x0002 /* Receive Buffer Flush */
+#define XMTINTLEN 0x0004 /* Transmit Buffer Interrupt Length */
+#define RCVINTLEN 0x0008 /* Receive Buffer Interrupt Length */
+
+/* TWI_FIFO_STAT Masks */
+#define XMTSTAT 0x0003 /* Transmit FIFO Status */
+#define XMT_EMPTY 0x0000 /* Transmit FIFO Empty */
+#define XMT_HALF 0x0001 /* Transmit FIFO Has 1 Byte To Write */
+#define XMT_FULL 0x0003 /* Transmit FIFO Full (2 Bytes To Write) */
+
+#define RCVSTAT 0x000C /* Receive FIFO Status */
+#define RCV_EMPTY 0x0000 /* Receive FIFO Empty */
+#define RCV_HALF 0x0004 /* Receive FIFO Has 1 Byte To Read */
+#define RCV_FULL 0x000C /* Receive FIFO Full (2 Bytes To Read) */
+
#endif
diff --git a/arch/blackfin/include/asm/blackfin.h b/arch/blackfin/include/asm/blackfin.h
index 7be5368c0512..f111f366d758 100644
--- a/arch/blackfin/include/asm/blackfin.h
+++ b/arch/blackfin/include/asm/blackfin.h
@@ -63,20 +63,16 @@ static inline void CSYNC(void)
#if ANOMALY_05000312 || ANOMALY_05000244
#define SSYNC(scratch) \
-do { \
cli scratch; \
nop; nop; nop; \
SSYNC; \
- sti scratch; \
-} while (0)
+ sti scratch;
#define CSYNC(scratch) \
-do { \
cli scratch; \
nop; nop; nop; \
CSYNC; \
- sti scratch; \
-} while (0)
+ sti scratch;
#else
#define SSYNC(scratch) SSYNC;
diff --git a/arch/blackfin/include/asm/clkdev.h b/arch/blackfin/include/asm/clkdev.h
new file mode 100644
index 000000000000..9053beda8c50
--- /dev/null
+++ b/arch/blackfin/include/asm/clkdev.h
@@ -0,0 +1,14 @@
+#ifndef __ASM_CLKDEV__H_
+#define __ASM_CLKDEV__H_
+
+#include <linux/slab.h>
+
+static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
+{
+ return kzalloc(size, GFP_KERNEL);
+}
+
+#define __clk_put(clk)
+#define __clk_get(clk) ({ 1; })
+
+#endif
diff --git a/arch/blackfin/include/asm/clocks.h b/arch/blackfin/include/asm/clocks.h
index 6f0b61852f58..9b3c85b3c288 100644
--- a/arch/blackfin/include/asm/clocks.h
+++ b/arch/blackfin/include/asm/clocks.h
@@ -48,4 +48,27 @@
# define CONFIG_VCO_MULT 0
#endif
+#include <linux/clk.h>
+
+struct clk_ops {
+ unsigned long (*get_rate)(struct clk *clk);
+ unsigned long (*round_rate)(struct clk *clk, unsigned long rate);
+ int (*set_rate)(struct clk *clk, unsigned long rate);
+ int (*enable)(struct clk *clk);
+ int (*disable)(struct clk *clk);
+};
+
+struct clk {
+ struct clk *parent;
+ const char *name;
+ unsigned long rate;
+ spinlock_t lock;
+ u32 flags;
+ const struct clk_ops *ops;
+ void __iomem *reg;
+ u32 mask;
+ u32 shift;
+};
+
+int clk_init(void);
#endif
diff --git a/arch/blackfin/include/asm/cplb.h b/arch/blackfin/include/asm/cplb.h
index fda96261ed62..5c37f620c4b3 100644
--- a/arch/blackfin/include/asm/cplb.h
+++ b/arch/blackfin/include/asm/cplb.h
@@ -62,6 +62,10 @@
#define SIZE_4K 0x00001000 /* 4K */
#define SIZE_1M 0x00100000 /* 1M */
#define SIZE_4M 0x00400000 /* 4M */
+#define SIZE_16K 0x00004000 /* 16K */
+#define SIZE_64K 0x00010000 /* 64K */
+#define SIZE_16M 0x01000000 /* 16M */
+#define SIZE_64M 0x04000000 /* 64M */
#define MAX_CPLBS 16
diff --git a/arch/blackfin/include/asm/def_LPBlackfin.h b/arch/blackfin/include/asm/def_LPBlackfin.h
index 823679011457..fe0ca03a1cb2 100644
--- a/arch/blackfin/include/asm/def_LPBlackfin.h
+++ b/arch/blackfin/include/asm/def_LPBlackfin.h
@@ -3,7 +3,7 @@
*
* Copyright 2005-2008 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or GPL-2 (or later).
+ * Licensed under the Clear BSD license or GPL-2 (or later).
*/
#ifndef _DEF_LPBLACKFIN_H
@@ -622,6 +622,10 @@ do { \
#define PAGE_SIZE_4KB 0x00010000 /* 4 KB page size */
#define PAGE_SIZE_1MB 0x00020000 /* 1 MB page size */
#define PAGE_SIZE_4MB 0x00030000 /* 4 MB page size */
+#define PAGE_SIZE_16KB 0x00040000 /* 16 KB page size */
+#define PAGE_SIZE_64KB 0x00050000 /* 64 KB page size */
+#define PAGE_SIZE_16MB 0x00060000 /* 16 MB page size */
+#define PAGE_SIZE_64MB 0x00070000 /* 64 MB page size */
#define CPLB_L1SRAM 0x00000020 /* 0=SRAM mapped in L1, 0=SRAM not
* mapped to L1
*/
diff --git a/arch/blackfin/include/asm/dma.h b/arch/blackfin/include/asm/dma.h
index dac0c97242bb..40e9c2bbc6e3 100644
--- a/arch/blackfin/include/asm/dma.h
+++ b/arch/blackfin/include/asm/dma.h
@@ -22,12 +22,22 @@
#define DATA_SIZE_8 0
#define DATA_SIZE_16 1
#define DATA_SIZE_32 2
+#ifdef CONFIG_BF60x
+#define DATA_SIZE_64 3
+#endif
#define DMA_FLOW_STOP 0
#define DMA_FLOW_AUTO 1
+#ifdef CONFIG_BF60x
+#define DMA_FLOW_LIST 4
+#define DMA_FLOW_ARRAY 5
+#define DMA_FLOW_LIST_DEMAND 6
+#define DMA_FLOW_ARRAY_DEMAND 7
+#else
#define DMA_FLOW_ARRAY 4
#define DMA_FLOW_SMALL 6
#define DMA_FLOW_LARGE 7
+#endif
#define DIMENSION_LINEAR 0
#define DIMENSION_2D 1
@@ -36,26 +46,80 @@
#define DIR_WRITE 1
#define INTR_DISABLE 0
+#ifdef CONFIG_BF60x
+#define INTR_ON_PERI 1
+#endif
#define INTR_ON_BUF 2
#define INTR_ON_ROW 3
#define DMA_NOSYNC_KEEP_DMA_BUF 0
#define DMA_SYNC_RESTART 1
+#ifdef DMA_MMR_SIZE_32
+#define DMA_MMR_SIZE_TYPE long
+#define DMA_MMR_READ bfin_read32
+#define DMA_MMR_WRITE bfin_write32
+#else
+#define DMA_MMR_SIZE_TYPE short
+#define DMA_MMR_READ bfin_read16
+#define DMA_MMR_WRITE bfin_write16
+#endif
+
+struct dma_desc_array {
+ unsigned long start_addr;
+ unsigned DMA_MMR_SIZE_TYPE cfg;
+ unsigned DMA_MMR_SIZE_TYPE x_count;
+ DMA_MMR_SIZE_TYPE x_modify;
+} __attribute__((packed));
+
struct dmasg {
void *next_desc_addr;
unsigned long start_addr;
- unsigned short cfg;
- unsigned short x_count;
- short x_modify;
- unsigned short y_count;
- short y_modify;
+ unsigned DMA_MMR_SIZE_TYPE cfg;
+ unsigned DMA_MMR_SIZE_TYPE x_count;
+ DMA_MMR_SIZE_TYPE x_modify;
+ unsigned DMA_MMR_SIZE_TYPE y_count;
+ DMA_MMR_SIZE_TYPE y_modify;
} __attribute__((packed));
struct dma_register {
void *next_desc_ptr; /* DMA Next Descriptor Pointer register */
unsigned long start_addr; /* DMA Start address register */
+#ifdef CONFIG_BF60x
+ unsigned long cfg; /* DMA Configuration register */
+ unsigned long x_count; /* DMA x_count register */
+
+ long x_modify; /* DMA x_modify register */
+
+ unsigned long y_count; /* DMA y_count register */
+
+ long y_modify; /* DMA y_modify register */
+
+ unsigned long reserved;
+ unsigned long reserved2;
+
+ void *curr_desc_ptr; /* DMA Current Descriptor Pointer
+ register */
+ void *prev_desc_ptr; /* DMA previous initial Descriptor Pointer
+ register */
+ unsigned long curr_addr_ptr; /* DMA Current Address Pointer
+ register */
+ unsigned long irq_status; /* DMA irq status register */
+
+ unsigned long curr_x_count; /* DMA Current x-count register */
+
+ unsigned long curr_y_count; /* DMA Current y-count register */
+
+ unsigned long reserved3;
+
+ unsigned long bw_limit_count; /* DMA band width limit count register */
+ unsigned long curr_bw_limit_count; /* DMA Current band width limit
+ count register */
+ unsigned long bw_monitor_count; /* DMA band width limit count register */
+ unsigned long curr_bw_monitor_count; /* DMA Current band width limit
+ count register */
+#else
unsigned short cfg; /* DMA Configuration register */
unsigned short dummy1; /* DMA Configuration register */
@@ -92,6 +156,7 @@ struct dma_register {
unsigned short dummy9;
unsigned long reserved3;
+#endif
};
@@ -131,23 +196,23 @@ static inline void set_dma_curr_desc_addr(unsigned int channel, void *addr)
{
dma_ch[channel].regs->curr_desc_ptr = addr;
}
-static inline void set_dma_x_count(unsigned int channel, unsigned short x_count)
+static inline void set_dma_x_count(unsigned int channel, unsigned DMA_MMR_SIZE_TYPE x_count)
{
dma_ch[channel].regs->x_count = x_count;
}
-static inline void set_dma_y_count(unsigned int channel, unsigned short y_count)
+static inline void set_dma_y_count(unsigned int channel, unsigned DMA_MMR_SIZE_TYPE y_count)
{
dma_ch[channel].regs->y_count = y_count;
}
-static inline void set_dma_x_modify(unsigned int channel, short x_modify)
+static inline void set_dma_x_modify(unsigned int channel, DMA_MMR_SIZE_TYPE x_modify)
{
dma_ch[channel].regs->x_modify = x_modify;
}
-static inline void set_dma_y_modify(unsigned int channel, short y_modify)
+static inline void set_dma_y_modify(unsigned int channel, DMA_MMR_SIZE_TYPE y_modify)
{
dma_ch[channel].regs->y_modify = y_modify;
}
-static inline void set_dma_config(unsigned int channel, unsigned short config)
+static inline void set_dma_config(unsigned int channel, unsigned DMA_MMR_SIZE_TYPE config)
{
dma_ch[channel].regs->cfg = config;
}
@@ -156,23 +221,55 @@ static inline void set_dma_curr_addr(unsigned int channel, unsigned long addr)
dma_ch[channel].regs->curr_addr_ptr = addr;
}
-static inline unsigned short
+#ifdef CONFIG_BF60x
+static inline unsigned long
+set_bfin_dma_config2(char direction, char flow_mode, char intr_mode,
+ char dma_mode, char mem_width, char syncmode, char peri_width)
+{
+ unsigned long config = 0;
+
+ switch (intr_mode) {
+ case INTR_ON_BUF:
+ if (dma_mode == DIMENSION_2D)
+ config = DI_EN_Y;
+ else
+ config = DI_EN_X;
+ break;
+ case INTR_ON_ROW:
+ config = DI_EN_X;
+ break;
+ case INTR_ON_PERI:
+ config = DI_EN_P;
+ break;
+ };
+
+ return config | (direction << 1) | (mem_width << 8) | (dma_mode << 26) |
+ (flow_mode << 12) | (syncmode << 2) | (peri_width << 4);
+}
+#endif
+
+static inline unsigned DMA_MMR_SIZE_TYPE
set_bfin_dma_config(char direction, char flow_mode,
- char intr_mode, char dma_mode, char width, char syncmode)
+ char intr_mode, char dma_mode, char mem_width, char syncmode)
{
- return (direction << 1) | (width << 2) | (dma_mode << 4) |
+#ifdef CONFIG_BF60x
+ return set_bfin_dma_config2(direction, flow_mode, intr_mode, dma_mode,
+ mem_width, syncmode, mem_width);
+#else
+ return (direction << 1) | (mem_width << 2) | (dma_mode << 4) |
(intr_mode << 6) | (flow_mode << 12) | (syncmode << 5);
+#endif
}
-static inline unsigned short get_dma_curr_irqstat(unsigned int channel)
+static inline unsigned DMA_MMR_SIZE_TYPE get_dma_curr_irqstat(unsigned int channel)
{
return dma_ch[channel].regs->irq_status;
}
-static inline unsigned short get_dma_curr_xcount(unsigned int channel)
+static inline unsigned DMA_MMR_SIZE_TYPE get_dma_curr_xcount(unsigned int channel)
{
return dma_ch[channel].regs->curr_x_count;
}
-static inline unsigned short get_dma_curr_ycount(unsigned int channel)
+static inline unsigned DMA_MMR_SIZE_TYPE get_dma_curr_ycount(unsigned int channel)
{
return dma_ch[channel].regs->curr_y_count;
}
@@ -184,7 +281,7 @@ static inline void *get_dma_curr_desc_ptr(unsigned int channel)
{
return dma_ch[channel].regs->curr_desc_ptr;
}
-static inline unsigned short get_dma_config(unsigned int channel)
+static inline unsigned DMA_MMR_SIZE_TYPE get_dma_config(unsigned int channel)
{
return dma_ch[channel].regs->cfg;
}
@@ -203,8 +300,8 @@ static inline void set_dma_sg(unsigned int channel, struct dmasg *sg, int ndsize
dma_ch[channel].regs->next_desc_ptr = sg;
dma_ch[channel].regs->cfg =
- (dma_ch[channel].regs->cfg & ~(0xf << 8)) |
- ((ndsize & 0xf) << 8);
+ (dma_ch[channel].regs->cfg & ~NDSIZE) |
+ ((ndsize << NDSIZE_OFFSET) & NDSIZE);
}
static inline int dma_channel_active(unsigned int channel)
@@ -239,7 +336,7 @@ static inline void dma_enable_irq(unsigned int channel)
}
static inline void clear_dma_irqstat(unsigned int channel)
{
- dma_ch[channel].regs->irq_status = DMA_DONE | DMA_ERR;
+ dma_ch[channel].regs->irq_status = DMA_DONE | DMA_ERR | DMA_PIRQ;
}
void *dma_memcpy(void *dest, const void *src, size_t count);
diff --git a/arch/blackfin/include/asm/dpmc.h b/arch/blackfin/include/asm/dpmc.h
index c4ec959dad78..e91eae8330a6 100644
--- a/arch/blackfin/include/asm/dpmc.h
+++ b/arch/blackfin/include/asm/dpmc.h
@@ -9,6 +9,651 @@
#ifndef _BLACKFIN_DPMC_H_
#define _BLACKFIN_DPMC_H_
+#ifdef __ASSEMBLY__
+#define PM_REG0 R7
+#define PM_REG1 R6
+#define PM_REG2 R5
+#define PM_REG3 R4
+#define PM_REG4 R3
+#define PM_REG5 R2
+#define PM_REG6 R1
+#define PM_REG7 R0
+#define PM_REG8 P5
+#define PM_REG9 P4
+#define PM_REG10 P3
+#define PM_REG11 P2
+#define PM_REG12 P1
+#define PM_REG13 P0
+
+#define PM_REGSET0 R7:7
+#define PM_REGSET1 R7:6
+#define PM_REGSET2 R7:5
+#define PM_REGSET3 R7:4
+#define PM_REGSET4 R7:3
+#define PM_REGSET5 R7:2
+#define PM_REGSET6 R7:1
+#define PM_REGSET7 R7:0
+#define PM_REGSET8 R7:0, P5:5
+#define PM_REGSET9 R7:0, P5:4
+#define PM_REGSET10 R7:0, P5:3
+#define PM_REGSET11 R7:0, P5:2
+#define PM_REGSET12 R7:0, P5:1
+#define PM_REGSET13 R7:0, P5:0
+
+#define _PM_PUSH(n, x, w, base) PM_REG##n = w[FP + ((x) - (base))];
+#define _PM_POP(n, x, w, base) w[FP + ((x) - (base))] = PM_REG##n;
+#define PM_PUSH_SYNC(n) [--sp] = (PM_REGSET##n);
+#define PM_POP_SYNC(n) (PM_REGSET##n) = [sp++];
+#define PM_PUSH(n, x) PM_REG##n = [FP++];
+#define PM_POP(n, x) [FP--] = PM_REG##n;
+#define PM_CORE_PUSH(n, x) _PM_PUSH(n, x, , COREMMR_BASE)
+#define PM_CORE_POP(n, x) _PM_POP(n, x, , COREMMR_BASE)
+#define PM_SYS_PUSH(n, x) _PM_PUSH(n, x, , SYSMMR_BASE)
+#define PM_SYS_POP(n, x) _PM_POP(n, x, , SYSMMR_BASE)
+#define PM_SYS_PUSH16(n, x) _PM_PUSH(n, x, w, SYSMMR_BASE)
+#define PM_SYS_POP16(n, x) _PM_POP(n, x, w, SYSMMR_BASE)
+
+ .macro bfin_init_pm_bench_cycles
+#ifdef CONFIG_BFIN_PM_WAKEUP_TIME_BENCH
+ R4 = 0;
+ CYCLES = R4;
+ CYCLES2 = R4;
+ R4 = SYSCFG;
+ BITSET(R4, 1);
+ SYSCFG = R4;
+#endif
+ .endm
+
+ .macro bfin_cpu_reg_save
+ /*
+ * Save the core regs early so we can blow them away when
+ * saving/restoring MMR states
+ */
+ [--sp] = (R7:0, P5:0);
+ [--sp] = fp;
+ [--sp] = usp;
+
+ [--sp] = i0;
+ [--sp] = i1;
+ [--sp] = i2;
+ [--sp] = i3;
+
+ [--sp] = m0;
+ [--sp] = m1;
+ [--sp] = m2;
+ [--sp] = m3;
+
+ [--sp] = l0;
+ [--sp] = l1;
+ [--sp] = l2;
+ [--sp] = l3;
+
+ [--sp] = b0;
+ [--sp] = b1;
+ [--sp] = b2;
+ [--sp] = b3;
+ [--sp] = a0.x;
+ [--sp] = a0.w;
+ [--sp] = a1.x;
+ [--sp] = a1.w;
+
+ [--sp] = LC0;
+ [--sp] = LC1;
+ [--sp] = LT0;
+ [--sp] = LT1;
+ [--sp] = LB0;
+ [--sp] = LB1;
+
+ /* We can't push RETI directly as that'll change IPEND[4] */
+ r7 = RETI;
+ [--sp] = RETS;
+ [--sp] = ASTAT;
+#ifndef CONFIG_BFIN_PM_WAKEUP_TIME_BENCH
+ [--sp] = CYCLES;
+ [--sp] = CYCLES2;
+#endif
+ [--sp] = SYSCFG;
+ [--sp] = RETX;
+ [--sp] = SEQSTAT;
+ [--sp] = r7;
+
+ /* Save first func arg in M3 */
+ M3 = R0;
+ .endm
+
+ .macro bfin_cpu_reg_restore
+ /* Restore Core Registers */
+ RETI = [sp++];
+ SEQSTAT = [sp++];
+ RETX = [sp++];
+ SYSCFG = [sp++];
+#ifndef CONFIG_BFIN_PM_WAKEUP_TIME_BENCH
+ CYCLES2 = [sp++];
+ CYCLES = [sp++];
+#endif
+ ASTAT = [sp++];
+ RETS = [sp++];
+
+ LB1 = [sp++];
+ LB0 = [sp++];
+ LT1 = [sp++];
+ LT0 = [sp++];
+ LC1 = [sp++];
+ LC0 = [sp++];
+
+ a1.w = [sp++];
+ a1.x = [sp++];
+ a0.w = [sp++];
+ a0.x = [sp++];
+ b3 = [sp++];
+ b2 = [sp++];
+ b1 = [sp++];
+ b0 = [sp++];
+
+ l3 = [sp++];
+ l2 = [sp++];
+ l1 = [sp++];
+ l0 = [sp++];
+
+ m3 = [sp++];
+ m2 = [sp++];
+ m1 = [sp++];
+ m0 = [sp++];
+
+ i3 = [sp++];
+ i2 = [sp++];
+ i1 = [sp++];
+ i0 = [sp++];
+
+ usp = [sp++];
+ fp = [sp++];
+ (R7:0, P5:0) = [sp++];
+
+ .endm
+
+ .macro bfin_sys_mmr_save
+ /* Save system MMRs */
+ FP.H = hi(SYSMMR_BASE);
+ FP.L = lo(SYSMMR_BASE);
+#ifdef SIC_IMASK0
+ PM_SYS_PUSH(0, SIC_IMASK0)
+ PM_SYS_PUSH(1, SIC_IMASK1)
+# ifdef SIC_IMASK2
+ PM_SYS_PUSH(2, SIC_IMASK2)
+# endif
+#else
+# ifdef SIC_IMASK
+ PM_SYS_PUSH(0, SIC_IMASK)
+# endif
+#endif
+
+#ifdef SIC_IAR0
+ PM_SYS_PUSH(3, SIC_IAR0)
+ PM_SYS_PUSH(4, SIC_IAR1)
+ PM_SYS_PUSH(5, SIC_IAR2)
+#endif
+#ifdef SIC_IAR3
+ PM_SYS_PUSH(6, SIC_IAR3)
+#endif
+#ifdef SIC_IAR4
+ PM_SYS_PUSH(7, SIC_IAR4)
+ PM_SYS_PUSH(8, SIC_IAR5)
+ PM_SYS_PUSH(9, SIC_IAR6)
+#endif
+#ifdef SIC_IAR7
+ PM_SYS_PUSH(10, SIC_IAR7)
+#endif
+#ifdef SIC_IAR8
+ PM_SYS_PUSH(11, SIC_IAR8)
+ PM_SYS_PUSH(12, SIC_IAR9)
+ PM_SYS_PUSH(13, SIC_IAR10)
+#endif
+ PM_PUSH_SYNC(13)
+#ifdef SIC_IAR11
+ PM_SYS_PUSH(0, SIC_IAR11)
+#endif
+
+#ifdef SIC_IWR
+ PM_SYS_PUSH(1, SIC_IWR)
+#endif
+#ifdef SIC_IWR0
+ PM_SYS_PUSH(1, SIC_IWR0)
+#endif
+#ifdef SIC_IWR1
+ PM_SYS_PUSH(2, SIC_IWR1)
+#endif
+#ifdef SIC_IWR2
+ PM_SYS_PUSH(3, SIC_IWR2)
+#endif
+
+#ifdef PINT0_ASSIGN
+ PM_SYS_PUSH(4, PINT0_MASK_SET)
+ PM_SYS_PUSH(5, PINT1_MASK_SET)
+ PM_SYS_PUSH(6, PINT2_MASK_SET)
+ PM_SYS_PUSH(7, PINT3_MASK_SET)
+ PM_SYS_PUSH(8, PINT0_ASSIGN)
+ PM_SYS_PUSH(9, PINT1_ASSIGN)
+ PM_SYS_PUSH(10, PINT2_ASSIGN)
+ PM_SYS_PUSH(11, PINT3_ASSIGN)
+ PM_SYS_PUSH(12, PINT0_INVERT_SET)
+ PM_SYS_PUSH(13, PINT1_INVERT_SET)
+ PM_PUSH_SYNC(13)
+ PM_SYS_PUSH(0, PINT2_INVERT_SET)
+ PM_SYS_PUSH(1, PINT3_INVERT_SET)
+ PM_SYS_PUSH(2, PINT0_EDGE_SET)
+ PM_SYS_PUSH(3, PINT1_EDGE_SET)
+ PM_SYS_PUSH(4, PINT2_EDGE_SET)
+ PM_SYS_PUSH(5, PINT3_EDGE_SET)
+#endif
+
+#ifdef SYSCR
+ PM_SYS_PUSH16(6, SYSCR)
+#endif
+
+#ifdef EBIU_AMGCTL
+ PM_SYS_PUSH16(7, EBIU_AMGCTL)
+ PM_SYS_PUSH(8, EBIU_AMBCTL0)
+ PM_SYS_PUSH(9, EBIU_AMBCTL1)
+#endif
+#ifdef EBIU_FCTL
+ PM_SYS_PUSH(10, EBIU_MBSCTL)
+ PM_SYS_PUSH(11, EBIU_MODE)
+ PM_SYS_PUSH(12, EBIU_FCTL)
+ PM_PUSH_SYNC(12)
+#else
+ PM_PUSH_SYNC(9)
+#endif
+ .endm
+
+
+ .macro bfin_sys_mmr_restore
+/* Restore System MMRs */
+ FP.H = hi(SYSMMR_BASE);
+ FP.L = lo(SYSMMR_BASE);
+
+#ifdef EBIU_FCTL
+ PM_POP_SYNC(12)
+ PM_SYS_POP(12, EBIU_FCTL)
+ PM_SYS_POP(11, EBIU_MODE)
+ PM_SYS_POP(10, EBIU_MBSCTL)
+#else
+ PM_POP_SYNC(9)
+#endif
+
+#ifdef EBIU_AMBCTL
+ PM_SYS_POP(9, EBIU_AMBCTL1)
+ PM_SYS_POP(8, EBIU_AMBCTL0)
+ PM_SYS_POP16(7, EBIU_AMGCTL)
+#endif
+
+#ifdef SYSCR
+ PM_SYS_POP16(6, SYSCR)
+#endif
+
+#ifdef PINT0_ASSIGN
+ PM_SYS_POP(5, PINT3_EDGE_SET)
+ PM_SYS_POP(4, PINT2_EDGE_SET)
+ PM_SYS_POP(3, PINT1_EDGE_SET)
+ PM_SYS_POP(2, PINT0_EDGE_SET)
+ PM_SYS_POP(1, PINT3_INVERT_SET)
+ PM_SYS_POP(0, PINT2_INVERT_SET)
+ PM_POP_SYNC(13)
+ PM_SYS_POP(13, PINT1_INVERT_SET)
+ PM_SYS_POP(12, PINT0_INVERT_SET)
+ PM_SYS_POP(11, PINT3_ASSIGN)
+ PM_SYS_POP(10, PINT2_ASSIGN)
+ PM_SYS_POP(9, PINT1_ASSIGN)
+ PM_SYS_POP(8, PINT0_ASSIGN)
+ PM_SYS_POP(7, PINT3_MASK_SET)
+ PM_SYS_POP(6, PINT2_MASK_SET)
+ PM_SYS_POP(5, PINT1_MASK_SET)
+ PM_SYS_POP(4, PINT0_MASK_SET)
+#endif
+
+#ifdef SIC_IWR2
+ PM_SYS_POP(3, SIC_IWR2)
+#endif
+#ifdef SIC_IWR1
+ PM_SYS_POP(2, SIC_IWR1)
+#endif
+#ifdef SIC_IWR0
+ PM_SYS_POP(1, SIC_IWR0)
+#endif
+#ifdef SIC_IWR
+ PM_SYS_POP(1, SIC_IWR)
+#endif
+
+#ifdef SIC_IAR11
+ PM_SYS_POP(0, SIC_IAR11)
+#endif
+ PM_POP_SYNC(13)
+#ifdef SIC_IAR8
+ PM_SYS_POP(13, SIC_IAR10)
+ PM_SYS_POP(12, SIC_IAR9)
+ PM_SYS_POP(11, SIC_IAR8)
+#endif
+#ifdef SIC_IAR7
+ PM_SYS_POP(10, SIC_IAR7)
+#endif
+#ifdef SIC_IAR6
+ PM_SYS_POP(9, SIC_IAR6)
+ PM_SYS_POP(8, SIC_IAR5)
+ PM_SYS_POP(7, SIC_IAR4)
+#endif
+#ifdef SIC_IAR3
+ PM_SYS_POP(6, SIC_IAR3)
+#endif
+#ifdef SIC_IAR0
+ PM_SYS_POP(5, SIC_IAR2)
+ PM_SYS_POP(4, SIC_IAR1)
+ PM_SYS_POP(3, SIC_IAR0)
+#endif
+#ifdef SIC_IMASK0
+# ifdef SIC_IMASK2
+ PM_SYS_POP(2, SIC_IMASK2)
+# endif
+ PM_SYS_POP(1, SIC_IMASK1)
+ PM_SYS_POP(0, SIC_IMASK0)
+#else
+# ifdef SIC_IMASK
+ PM_SYS_POP(0, SIC_IMASK)
+# endif
+#endif
+ .endm
+
+ .macro bfin_core_mmr_save
+ /* Save Core MMRs */
+ I0.H = hi(COREMMR_BASE);
+ I0.L = lo(COREMMR_BASE);
+ I1 = I0;
+ I2 = I0;
+ I3 = I0;
+ B0 = I0;
+ B1 = I0;
+ B2 = I0;
+ B3 = I0;
+ I1.L = lo(DCPLB_ADDR0);
+ I2.L = lo(DCPLB_DATA0);
+ I3.L = lo(ICPLB_ADDR0);
+ B0.L = lo(ICPLB_DATA0);
+ B1.L = lo(EVT2);
+ B2.L = lo(IMASK);
+ B3.L = lo(TCNTL);
+
+ /* Event Vectors */
+ FP = B1;
+ PM_PUSH(0, EVT2)
+ PM_PUSH(1, EVT3)
+ FP += 4; /* EVT4 */
+ PM_PUSH(2, EVT5)
+ PM_PUSH(3, EVT6)
+ PM_PUSH(4, EVT7)
+ PM_PUSH(5, EVT8)
+ PM_PUSH_SYNC(5)
+
+ PM_PUSH(0, EVT9)
+ PM_PUSH(1, EVT10)
+ PM_PUSH(2, EVT11)
+ PM_PUSH(3, EVT12)
+ PM_PUSH(4, EVT13)
+ PM_PUSH(5, EVT14)
+ PM_PUSH(6, EVT15)
+
+ /* CEC */
+ FP = B2;
+ PM_PUSH(7, IMASK)
+ FP += 4; /* IPEND */
+ PM_PUSH(8, ILAT)
+ PM_PUSH(9, IPRIO)
+
+ /* Core Timer */
+ FP = B3;
+ PM_PUSH(10, TCNTL)
+ PM_PUSH(11, TPERIOD)
+ PM_PUSH(12, TSCALE)
+ PM_PUSH(13, TCOUNT)
+ PM_PUSH_SYNC(13)
+
+ /* Misc non-contiguous registers */
+ FP = I0;
+ PM_CORE_PUSH(0, DMEM_CONTROL);
+ PM_CORE_PUSH(1, IMEM_CONTROL);
+ PM_CORE_PUSH(2, TBUFCTL);
+ PM_PUSH_SYNC(2)
+
+ /* DCPLB Addr */
+ FP = I1;
+ PM_PUSH(0, DCPLB_ADDR0)
+ PM_PUSH(1, DCPLB_ADDR1)
+ PM_PUSH(2, DCPLB_ADDR2)
+ PM_PUSH(3, DCPLB_ADDR3)
+ PM_PUSH(4, DCPLB_ADDR4)
+ PM_PUSH(5, DCPLB_ADDR5)
+ PM_PUSH(6, DCPLB_ADDR6)
+ PM_PUSH(7, DCPLB_ADDR7)
+ PM_PUSH(8, DCPLB_ADDR8)
+ PM_PUSH(9, DCPLB_ADDR9)
+ PM_PUSH(10, DCPLB_ADDR10)
+ PM_PUSH(11, DCPLB_ADDR11)
+ PM_PUSH(12, DCPLB_ADDR12)
+ PM_PUSH(13, DCPLB_ADDR13)
+ PM_PUSH_SYNC(13)
+ PM_PUSH(0, DCPLB_ADDR14)
+ PM_PUSH(1, DCPLB_ADDR15)
+
+ /* DCPLB Data */
+ FP = I2;
+ PM_PUSH(2, DCPLB_DATA0)
+ PM_PUSH(3, DCPLB_DATA1)
+ PM_PUSH(4, DCPLB_DATA2)
+ PM_PUSH(5, DCPLB_DATA3)
+ PM_PUSH(6, DCPLB_DATA4)
+ PM_PUSH(7, DCPLB_DATA5)
+ PM_PUSH(8, DCPLB_DATA6)
+ PM_PUSH(9, DCPLB_DATA7)
+ PM_PUSH(10, DCPLB_DATA8)
+ PM_PUSH(11, DCPLB_DATA9)
+ PM_PUSH(12, DCPLB_DATA10)
+ PM_PUSH(13, DCPLB_DATA11)
+ PM_PUSH_SYNC(13)
+ PM_PUSH(0, DCPLB_DATA12)
+ PM_PUSH(1, DCPLB_DATA13)
+ PM_PUSH(2, DCPLB_DATA14)
+ PM_PUSH(3, DCPLB_DATA15)
+
+ /* ICPLB Addr */
+ FP = I3;
+ PM_PUSH(4, ICPLB_ADDR0)
+ PM_PUSH(5, ICPLB_ADDR1)
+ PM_PUSH(6, ICPLB_ADDR2)
+ PM_PUSH(7, ICPLB_ADDR3)
+ PM_PUSH(8, ICPLB_ADDR4)
+ PM_PUSH(9, ICPLB_ADDR5)
+ PM_PUSH(10, ICPLB_ADDR6)
+ PM_PUSH(11, ICPLB_ADDR7)
+ PM_PUSH(12, ICPLB_ADDR8)
+ PM_PUSH(13, ICPLB_ADDR9)
+ PM_PUSH_SYNC(13)
+ PM_PUSH(0, ICPLB_ADDR10)
+ PM_PUSH(1, ICPLB_ADDR11)
+ PM_PUSH(2, ICPLB_ADDR12)
+ PM_PUSH(3, ICPLB_ADDR13)
+ PM_PUSH(4, ICPLB_ADDR14)
+ PM_PUSH(5, ICPLB_ADDR15)
+
+ /* ICPLB Data */
+ FP = B0;
+ PM_PUSH(6, ICPLB_DATA0)
+ PM_PUSH(7, ICPLB_DATA1)
+ PM_PUSH(8, ICPLB_DATA2)
+ PM_PUSH(9, ICPLB_DATA3)
+ PM_PUSH(10, ICPLB_DATA4)
+ PM_PUSH(11, ICPLB_DATA5)
+ PM_PUSH(12, ICPLB_DATA6)
+ PM_PUSH(13, ICPLB_DATA7)
+ PM_PUSH_SYNC(13)
+ PM_PUSH(0, ICPLB_DATA8)
+ PM_PUSH(1, ICPLB_DATA9)
+ PM_PUSH(2, ICPLB_DATA10)
+ PM_PUSH(3, ICPLB_DATA11)
+ PM_PUSH(4, ICPLB_DATA12)
+ PM_PUSH(5, ICPLB_DATA13)
+ PM_PUSH(6, ICPLB_DATA14)
+ PM_PUSH(7, ICPLB_DATA15)
+ PM_PUSH_SYNC(7)
+ .endm
+
+ .macro bfin_core_mmr_restore
+ /* Restore Core MMRs */
+ I0.H = hi(COREMMR_BASE);
+ I0.L = lo(COREMMR_BASE);
+ I1 = I0;
+ I2 = I0;
+ I3 = I0;
+ B0 = I0;
+ B1 = I0;
+ B2 = I0;
+ B3 = I0;
+ I1.L = lo(DCPLB_ADDR15);
+ I2.L = lo(DCPLB_DATA15);
+ I3.L = lo(ICPLB_ADDR15);
+ B0.L = lo(ICPLB_DATA15);
+ B1.L = lo(EVT15);
+ B2.L = lo(IPRIO);
+ B3.L = lo(TCOUNT);
+
+ /* ICPLB Data */
+ FP = B0;
+ PM_POP_SYNC(7)
+ PM_POP(7, ICPLB_DATA15)
+ PM_POP(6, ICPLB_DATA14)
+ PM_POP(5, ICPLB_DATA13)
+ PM_POP(4, ICPLB_DATA12)
+ PM_POP(3, ICPLB_DATA11)
+ PM_POP(2, ICPLB_DATA10)
+ PM_POP(1, ICPLB_DATA9)
+ PM_POP(0, ICPLB_DATA8)
+ PM_POP_SYNC(13)
+ PM_POP(13, ICPLB_DATA7)
+ PM_POP(12, ICPLB_DATA6)
+ PM_POP(11, ICPLB_DATA5)
+ PM_POP(10, ICPLB_DATA4)
+ PM_POP(9, ICPLB_DATA3)
+ PM_POP(8, ICPLB_DATA2)
+ PM_POP(7, ICPLB_DATA1)
+ PM_POP(6, ICPLB_DATA0)
+
+ /* ICPLB Addr */
+ FP = I3;
+ PM_POP(5, ICPLB_ADDR15)
+ PM_POP(4, ICPLB_ADDR14)
+ PM_POP(3, ICPLB_ADDR13)
+ PM_POP(2, ICPLB_ADDR12)
+ PM_POP(1, ICPLB_ADDR11)
+ PM_POP(0, ICPLB_ADDR10)
+ PM_POP_SYNC(13)
+ PM_POP(13, ICPLB_ADDR9)
+ PM_POP(12, ICPLB_ADDR8)
+ PM_POP(11, ICPLB_ADDR7)
+ PM_POP(10, ICPLB_ADDR6)
+ PM_POP(9, ICPLB_ADDR5)
+ PM_POP(8, ICPLB_ADDR4)
+ PM_POP(7, ICPLB_ADDR3)
+ PM_POP(6, ICPLB_ADDR2)
+ PM_POP(5, ICPLB_ADDR1)
+ PM_POP(4, ICPLB_ADDR0)
+
+ /* DCPLB Data */
+ FP = I2;
+ PM_POP(3, DCPLB_DATA15)
+ PM_POP(2, DCPLB_DATA14)
+ PM_POP(1, DCPLB_DATA13)
+ PM_POP(0, DCPLB_DATA12)
+ PM_POP_SYNC(13)
+ PM_POP(13, DCPLB_DATA11)
+ PM_POP(12, DCPLB_DATA10)
+ PM_POP(11, DCPLB_DATA9)
+ PM_POP(10, DCPLB_DATA8)
+ PM_POP(9, DCPLB_DATA7)
+ PM_POP(8, DCPLB_DATA6)
+ PM_POP(7, DCPLB_DATA5)
+ PM_POP(6, DCPLB_DATA4)
+ PM_POP(5, DCPLB_DATA3)
+ PM_POP(4, DCPLB_DATA2)
+ PM_POP(3, DCPLB_DATA1)
+ PM_POP(2, DCPLB_DATA0)
+
+ /* DCPLB Addr */
+ FP = I1;
+ PM_POP(1, DCPLB_ADDR15)
+ PM_POP(0, DCPLB_ADDR14)
+ PM_POP_SYNC(13)
+ PM_POP(13, DCPLB_ADDR13)
+ PM_POP(12, DCPLB_ADDR12)
+ PM_POP(11, DCPLB_ADDR11)
+ PM_POP(10, DCPLB_ADDR10)
+ PM_POP(9, DCPLB_ADDR9)
+ PM_POP(8, DCPLB_ADDR8)
+ PM_POP(7, DCPLB_ADDR7)
+ PM_POP(6, DCPLB_ADDR6)
+ PM_POP(5, DCPLB_ADDR5)
+ PM_POP(4, DCPLB_ADDR4)
+ PM_POP(3, DCPLB_ADDR3)
+ PM_POP(2, DCPLB_ADDR2)
+ PM_POP(1, DCPLB_ADDR1)
+ PM_POP(0, DCPLB_ADDR0)
+
+
+ /* Misc non-contiguous registers */
+
+ /* icache & dcache will enable later
+ drop IMEM_CONTROL, DMEM_CONTROL pop
+ */
+ FP = I0;
+ PM_POP_SYNC(2)
+ PM_CORE_POP(2, TBUFCTL)
+ PM_CORE_POP(1, IMEM_CONTROL)
+ PM_CORE_POP(0, DMEM_CONTROL)
+
+ /* Core Timer */
+ FP = B3;
+ R0 = 0x1;
+ [FP - 0xC] = R0;
+
+ PM_POP_SYNC(13)
+ FP = B3;
+ PM_POP(13, TCOUNT)
+ PM_POP(12, TSCALE)
+ PM_POP(11, TPERIOD)
+ PM_POP(10, TCNTL)
+
+ /* CEC */
+ FP = B2;
+ PM_POP(9, IPRIO)
+ PM_POP(8, ILAT)
+ FP += -4; /* IPEND */
+ PM_POP(7, IMASK)
+
+ /* Event Vectors */
+ FP = B1;
+ PM_POP(6, EVT15)
+ PM_POP(5, EVT14)
+ PM_POP(4, EVT13)
+ PM_POP(3, EVT12)
+ PM_POP(2, EVT11)
+ PM_POP(1, EVT10)
+ PM_POP(0, EVT9)
+ PM_POP_SYNC(5)
+ PM_POP(5, EVT8)
+ PM_POP(4, EVT7)
+ PM_POP(3, EVT6)
+ PM_POP(2, EVT5)
+ FP += -4; /* EVT4 */
+ PM_POP(1, EVT3)
+ PM_POP(0, EVT2)
+ .endm
+#endif
+
#include <mach/pll.h>
/* PLL_CTL Masks */
@@ -98,6 +743,16 @@
#define VLEV_130 0x00F0 /* VLEV = 1.30 V (-5% - +10% Accuracy) */
#endif
+#ifdef CONFIG_BF60x
+#define PA15WE 0x00000001 /* Allow Wake-Up from PA15 */
+#define PB15WE 0x00000002 /* Allow Wake-Up from PB15 */
+#define PC15WE 0x00000004 /* Allow Wake-Up from PC15 */
+#define PD06WE 0x00000008 /* Allow Wake-Up from PD06(ETH0_PHYINT) */
+#define PE12WE 0x00000010 /* Allow Wake-Up from PE12(ETH1_PHYINT, PUSH BUTTON) */
+#define PG04WE 0x00000020 /* Allow Wake-Up from PG04(CAN0_RX) */
+#define PG13WE 0x00000040 /* Allow Wake-Up from PG13 */
+#define USBWE 0x00000080 /* Allow Wake-Up from (USB) */
+#else
#define WAKE 0x0100 /* Enable RTC/Reset Wakeup From Hibernate */
#define CANWE 0x0200 /* Enable CAN Wakeup From Hibernate */
#define PHYWE 0x0400 /* Enable PHY Wakeup From Hibernate */
@@ -113,6 +768,7 @@
#else
#define USBWE 0x0800 /* Enable USB Wakeup From Hibernate */
#endif
+#endif
#ifndef __ASSEMBLY__
diff --git a/arch/blackfin/include/asm/fixed_code.h b/arch/blackfin/include/asm/fixed_code.h
index 73fe53e7fd24..5395088b2d0e 100644
--- a/arch/blackfin/include/asm/fixed_code.h
+++ b/arch/blackfin/include/asm/fixed_code.h
@@ -29,24 +29,28 @@ extern void sigreturn_stub(void);
#endif
#endif
-#define FIXED_CODE_START 0x400
+#ifndef CONFIG_PHY_RAM_BASE_ADDRESS
+#define CONFIG_PHY_RAM_BASE_ADDRESS 0x0
+#endif
+
+#define FIXED_CODE_START (CONFIG_PHY_RAM_BASE_ADDRESS + 0x400)
-#define SIGRETURN_STUB 0x400
+#define SIGRETURN_STUB (CONFIG_PHY_RAM_BASE_ADDRESS + 0x400)
-#define ATOMIC_SEQS_START 0x410
+#define ATOMIC_SEQS_START (CONFIG_PHY_RAM_BASE_ADDRESS + 0x410)
-#define ATOMIC_XCHG32 0x410
-#define ATOMIC_CAS32 0x420
-#define ATOMIC_ADD32 0x430
-#define ATOMIC_SUB32 0x440
-#define ATOMIC_IOR32 0x450
-#define ATOMIC_AND32 0x460
-#define ATOMIC_XOR32 0x470
+#define ATOMIC_XCHG32 (CONFIG_PHY_RAM_BASE_ADDRESS + 0x410)
+#define ATOMIC_CAS32 (CONFIG_PHY_RAM_BASE_ADDRESS + 0x420)
+#define ATOMIC_ADD32 (CONFIG_PHY_RAM_BASE_ADDRESS + 0x430)
+#define ATOMIC_SUB32 (CONFIG_PHY_RAM_BASE_ADDRESS + 0x440)
+#define ATOMIC_IOR32 (CONFIG_PHY_RAM_BASE_ADDRESS + 0x450)
+#define ATOMIC_AND32 (CONFIG_PHY_RAM_BASE_ADDRESS + 0x460)
+#define ATOMIC_XOR32 (CONFIG_PHY_RAM_BASE_ADDRESS + 0x470)
-#define ATOMIC_SEQS_END 0x480
+#define ATOMIC_SEQS_END (CONFIG_PHY_RAM_BASE_ADDRESS + 0x480)
-#define SAFE_USER_INSTRUCTION 0x480
+#define SAFE_USER_INSTRUCTION (CONFIG_PHY_RAM_BASE_ADDRESS + 0x480)
-#define FIXED_CODE_END 0x490
+#define FIXED_CODE_END (CONFIG_PHY_RAM_BASE_ADDRESS + 0x490)
#endif
diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h
index 12d3571b5232..3d84d96f7c2c 100644
--- a/arch/blackfin/include/asm/gpio.h
+++ b/arch/blackfin/include/asm/gpio.h
@@ -26,6 +26,7 @@
#ifndef __ASSEMBLY__
#include <linux/compiler.h>
+#include <linux/gpio.h>
/***********************************************************
*
@@ -244,6 +245,49 @@ static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
return -EINVAL;
}
+static inline int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
+{
+ int err;
+
+ err = bfin_gpio_request(gpio, label);
+ if (err)
+ return err;
+
+ if (flags & GPIOF_DIR_IN)
+ err = bfin_gpio_direction_input(gpio);
+ else
+ err = bfin_gpio_direction_output(gpio,
+ (flags & GPIOF_INIT_HIGH) ? 1 : 0);
+
+ if (err)
+ bfin_gpio_free(gpio);
+
+ return err;
+}
+
+static inline int gpio_request_array(const struct gpio *array, size_t num)
+{
+ int i, err;
+
+ for (i = 0; i < num; i++, array++) {
+ err = gpio_request_one(array->gpio, array->flags, array->label);
+ if (err)
+ goto err_free;
+ }
+ return 0;
+
+err_free:
+ while (i--)
+ bfin_gpio_free((--array)->gpio);
+ return err;
+}
+
+static inline void gpio_free_array(const struct gpio *array, size_t num)
+{
+ while (num--)
+ bfin_gpio_free((array++)->gpio);
+}
+
static inline int __gpio_get_value(unsigned gpio)
{
return bfin_gpio_get_value(gpio);
diff --git a/arch/blackfin/include/asm/gptimers.h b/arch/blackfin/include/asm/gptimers.h
index 38bddcb190c8..381e3d621a4c 100644
--- a/arch/blackfin/include/asm/gptimers.h
+++ b/arch/blackfin/include/asm/gptimers.h
@@ -44,6 +44,13 @@
# define TIMER_GROUP2 1
#endif
/*
+ * BF609: 8 timers:
+ */
+#if defined(CONFIG_BF60x)
+# define MAX_BLACKFIN_GPTIMERS 8
+# define TIMER0_GROUP_REG TIMER_RUN
+#endif
+/*
* All others: 3 timers:
*/
#define TIMER_GROUP1 0
@@ -104,6 +111,72 @@
# define FS2_TIMER_BIT TIMER1bit
#endif
+#ifdef CONFIG_BF60x
+/*
+ * Timer Configuration Register Bits
+ */
+#define TIMER_EMU_RUN 0x8000
+#define TIMER_BPER_EN 0x4000
+#define TIMER_BWID_EN 0x2000
+#define TIMER_BDLY_EN 0x1000
+#define TIMER_OUT_DIS 0x0800
+#define TIMER_TIN_SEL 0x0400
+#define TIMER_CLK_SEL 0x0300
+#define TIMER_CLK_SCLK 0x0000
+#define TIMER_CLK_ALT_CLK0 0x0100
+#define TIMER_CLK_ALT_CLK1 0x0300
+#define TIMER_PULSE_HI 0x0080
+#define TIMER_SLAVE_TRIG 0x0040
+#define TIMER_IRQ_MODE 0x0030
+#define TIMER_IRQ_ACT_EDGE 0x0000
+#define TIMER_IRQ_DLY 0x0010
+#define TIMER_IRQ_WID_DLY 0x0020
+#define TIMER_IRQ_PER 0x0030
+#define TIMER_MODE 0x000f
+#define TIMER_MODE_WDOG_P 0x0008
+#define TIMER_MODE_WDOG_W 0x0009
+#define TIMER_MODE_PWM_CONT 0x000c
+#define TIMER_MODE_PWM 0x000d
+#define TIMER_MODE_WDTH 0x000a
+#define TIMER_MODE_WDTH_D 0x000b
+#define TIMER_MODE_EXT_CLK 0x000e
+#define TIMER_MODE_PININT 0x000f
+
+/*
+ * Timer Status Register Bits
+ */
+#define TIMER_STATUS_TIMIL0 0x0001
+#define TIMER_STATUS_TIMIL1 0x0002
+#define TIMER_STATUS_TIMIL2 0x0004
+#define TIMER_STATUS_TIMIL3 0x0008
+#define TIMER_STATUS_TIMIL4 0x0010
+#define TIMER_STATUS_TIMIL5 0x0020
+#define TIMER_STATUS_TIMIL6 0x0040
+#define TIMER_STATUS_TIMIL7 0x0080
+
+#define TIMER_STATUS_TOVF0 0x0001 /* timer 0 overflow error */
+#define TIMER_STATUS_TOVF1 0x0002
+#define TIMER_STATUS_TOVF2 0x0004
+#define TIMER_STATUS_TOVF3 0x0008
+#define TIMER_STATUS_TOVF4 0x0010
+#define TIMER_STATUS_TOVF5 0x0020
+#define TIMER_STATUS_TOVF6 0x0040
+#define TIMER_STATUS_TOVF7 0x0080
+
+/*
+ * Timer Slave Enable Status : write 1 to clear
+ */
+#define TIMER_STATUS_TRUN0 0x0001
+#define TIMER_STATUS_TRUN1 0x0002
+#define TIMER_STATUS_TRUN2 0x0004
+#define TIMER_STATUS_TRUN3 0x0008
+#define TIMER_STATUS_TRUN4 0x0010
+#define TIMER_STATUS_TRUN5 0x0020
+#define TIMER_STATUS_TRUN6 0x0040
+#define TIMER_STATUS_TRUN7 0x0080
+
+#else
+
/*
* Timer Configuration Register Bits
*/
@@ -170,12 +243,18 @@
#define TIMER_STATUS_TRUN10 0x4000
#define TIMER_STATUS_TRUN11 0x8000
+#endif
+
/* The actual gptimer API */
void set_gptimer_pwidth(unsigned int timer_id, uint32_t width);
uint32_t get_gptimer_pwidth(unsigned int timer_id);
void set_gptimer_period(unsigned int timer_id, uint32_t period);
uint32_t get_gptimer_period(unsigned int timer_id);
+#ifdef CONFIG_BF60x
+void set_gptimer_delay(unsigned int timer_id, uint32_t delay);
+uint32_t get_gptimer_delay(unsigned int timer_id);
+#endif
uint32_t get_gptimer_count(unsigned int timer_id);
int get_gptimer_intr(unsigned int timer_id);
void clear_gptimer_intr(unsigned int timer_id);
@@ -217,16 +296,41 @@ struct bfin_gptimer_regs {
u32 counter;
u32 period;
u32 width;
+#ifdef CONFIG_BF60x
+ u32 delay;
+#endif
};
/*
* bfin group timer registers layout
*/
+#ifndef CONFIG_BF60x
struct bfin_gptimer_group_regs {
__BFP(enable);
__BFP(disable);
u32 status;
};
+#else
+struct bfin_gptimer_group_regs {
+ __BFP(run);
+ __BFP(enable);
+ __BFP(disable);
+ __BFP(stop_cfg);
+ __BFP(stop_cfg_set);
+ __BFP(stop_cfg_clr);
+ __BFP(data_imsk);
+ __BFP(stat_imsk);
+ __BFP(tr_msk);
+ __BFP(tr_ie);
+ __BFP(data_ilat);
+ __BFP(stat_ilat);
+ __BFP(err_status);
+ __BFP(bcast_per);
+ __BFP(bcast_wid);
+ __BFP(bcast_dly);
+
+};
+#endif
#undef __BFP
diff --git a/arch/blackfin/include/asm/irqflags.h b/arch/blackfin/include/asm/irqflags.h
index 43eb4749de3d..07aff230a812 100644
--- a/arch/blackfin/include/asm/irqflags.h
+++ b/arch/blackfin/include/asm/irqflags.h
@@ -67,7 +67,11 @@ static inline notrace unsigned long __hard_local_irq_save(void)
static inline notrace int hard_irqs_disabled_flags(unsigned long flags)
{
+#ifdef CONFIG_BF60x
+ return (flags & IMASK_IVG11) == 0;
+#else
return (flags & ~0x3f) == 0;
+#endif
}
static inline notrace int hard_irqs_disabled(void)
@@ -224,7 +228,7 @@ static inline notrace void hard_local_irq_restore(unsigned long flags)
* Direct interface to linux/irqflags.h.
*/
#define arch_local_save_flags() hard_local_save_flags()
-#define arch_local_irq_save(flags) __hard_local_irq_save()
+#define arch_local_irq_save() __hard_local_irq_save()
#define arch_local_irq_restore(flags) __hard_local_irq_restore(flags)
#define arch_local_irq_enable() __hard_local_irq_enable()
#define arch_local_irq_disable() __hard_local_irq_disable()
diff --git a/arch/blackfin/include/asm/page.h b/arch/blackfin/include/asm/page.h
index 7202404966f6..b93474d5be75 100644
--- a/arch/blackfin/include/asm/page.h
+++ b/arch/blackfin/include/asm/page.h
@@ -7,14 +7,15 @@
#ifndef _BLACKFIN_PAGE_H
#define _BLACKFIN_PAGE_H
-#include <asm-generic/page.h>
-#define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
+#define ARCH_PFN_OFFSET (CONFIG_PHY_RAM_BASE_ADDRESS >> PAGE_SHIFT)
+#define MAP_NR(addr) ((unsigned long)(addr) >> PAGE_SHIFT)
#define VM_DATA_DEFAULT_FLAGS \
(VM_READ | VM_WRITE | \
((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+#include <asm-generic/page.h>
#include <asm-generic/memory_model.h>
#include <asm-generic/getorder.h>
diff --git a/arch/blackfin/include/asm/pda.h b/arch/blackfin/include/asm/pda.h
index 28c2498c9c98..68d6f6618f2a 100644
--- a/arch/blackfin/include/asm/pda.h
+++ b/arch/blackfin/include/asm/pda.h
@@ -13,7 +13,9 @@
#ifndef __ASSEMBLY__
struct blackfin_pda { /* Per-processor Data Area */
+#ifdef CONFIG_SMP
struct blackfin_pda *next;
+#endif
unsigned long syscfg;
#ifdef CONFIG_SMP
diff --git a/arch/blackfin/include/asm/pm.h b/arch/blackfin/include/asm/pm.h
new file mode 100644
index 000000000000..f72239bf3638
--- /dev/null
+++ b/arch/blackfin/include/asm/pm.h
@@ -0,0 +1,31 @@
+/*
+ * Blackfin bf609 power management
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2
+ */
+
+#ifndef __PM_H__
+#define __PM_H__
+
+#include <linux/suspend.h>
+
+struct bfin_cpu_pm_fns {
+ void (*save)(unsigned long *);
+ void (*restore)(unsigned long *);
+ int (*valid)(suspend_state_t state);
+ void (*enter)(suspend_state_t state);
+ int (*prepare)(void);
+ void (*finish)(void);
+};
+
+extern struct bfin_cpu_pm_fns *bfin_cpu_pm;
+
+# ifdef CONFIG_BFIN_COREB
+void bfin_coreb_start(void);
+void bfin_coreb_stop(void);
+void bfin_coreb_reset(void);
+# endif
+
+#endif
diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h
index 8af7772e84cc..4ef7cfe43ceb 100644
--- a/arch/blackfin/include/asm/processor.h
+++ b/arch/blackfin/include/asm/processor.h
@@ -75,8 +75,6 @@ static inline void release_thread(struct task_struct *dead_task)
{
}
-#define prepare_to_copy(tsk) do { } while (0)
-
extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags);
/*
diff --git a/arch/blackfin/include/asm/unistd.h b/arch/blackfin/include/asm/unistd.h
index 75ec9df5318b..3287222cba34 100644
--- a/arch/blackfin/include/asm/unistd.h
+++ b/arch/blackfin/include/asm/unistd.h
@@ -11,7 +11,7 @@
*/
#define __NR_restart_syscall 0
#define __NR_exit 1
-#define __NR_fork 2
+ /* 2 __NR_fork not supported on nommu */
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index 9a0d6d706443..08e6625106be 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -2,7 +2,7 @@
# arch/blackfin/kernel/Makefile
#
-extra-y := init_task.o vmlinux.lds
+extra-y := vmlinux.lds
obj-y := \
entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
diff --git a/arch/blackfin/kernel/bfin_dma.c b/arch/blackfin/kernel/bfin_dma.c
index 40c2ed61258e..c166939ffb2b 100644
--- a/arch/blackfin/kernel/bfin_dma.c
+++ b/arch/blackfin/kernel/bfin_dma.c
@@ -45,9 +45,15 @@ static int __init blackfin_dma_init(void)
atomic_set(&dma_ch[i].chan_status, 0);
dma_ch[i].regs = dma_io_base_addr[i];
}
+#ifdef CH_MEM_STREAM3_SRC
+ /* Mark MEMDMA Channel 3 as requested since we're using it internally */
+ request_dma(CH_MEM_STREAM3_DEST, "Blackfin dma_memcpy");
+ request_dma(CH_MEM_STREAM3_SRC, "Blackfin dma_memcpy");
+#else
/* Mark MEMDMA Channel 0 as requested since we're using it internally */
request_dma(CH_MEM_STREAM0_DEST, "Blackfin dma_memcpy");
request_dma(CH_MEM_STREAM0_SRC, "Blackfin dma_memcpy");
+#endif
#if defined(CONFIG_DEB_DMA_URGENT)
bfin_write_EBIU_DDRQUE(bfin_read_EBIU_DDRQUE()
@@ -84,7 +90,8 @@ static const struct file_operations proc_dma_operations = {
static int __init proc_dma_init(void)
{
- return proc_create("dma", 0, NULL, &proc_dma_operations) != NULL;
+ proc_create("dma", 0, NULL, &proc_dma_operations);
+ return 0;
}
late_initcall(proc_dma_init);
#endif
@@ -204,6 +211,7 @@ EXPORT_SYMBOL(free_dma);
# ifndef MAX_DMA_SUSPEND_CHANNELS
# define MAX_DMA_SUSPEND_CHANNELS MAX_DMA_CHANNELS
# endif
+# ifndef CONFIG_BF60x
int blackfin_dma_suspend(void)
{
int i;
@@ -213,7 +221,6 @@ int blackfin_dma_suspend(void)
printk(KERN_ERR "DMA Channel %d failed to suspend\n", i);
return -EBUSY;
}
-
if (i < MAX_DMA_SUSPEND_CHANNELS)
dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map;
}
@@ -230,7 +237,6 @@ void blackfin_dma_resume(void)
for (i = 0; i < MAX_DMA_CHANNELS; ++i) {
dma_ch[i].regs->cfg = 0;
-
if (i < MAX_DMA_SUSPEND_CHANNELS)
dma_ch[i].regs->peripheral_map = dma_ch[i].saved_peripheral_map;
}
@@ -238,6 +244,16 @@ void blackfin_dma_resume(void)
bfin_write_DMAC_TC_PER(0x0111);
#endif
}
+# else
+int blackfin_dma_suspend(void)
+{
+ return 0;
+}
+
+void blackfin_dma_resume(void)
+{
+}
+#endif
#endif
/**
@@ -279,10 +295,10 @@ void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size)
src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR;
}
- if (!bfin_read16(&src_ch->cfg))
+ if (!DMA_MMR_READ(&src_ch->cfg))
break;
- else if (bfin_read16(&dst_ch->irq_status) & DMA_DONE) {
- bfin_write16(&src_ch->cfg, 0);
+ else if (DMA_MMR_READ(&dst_ch->irq_status) & DMA_DONE) {
+ DMA_MMR_WRITE(&src_ch->cfg, 0);
break;
}
}
@@ -295,22 +311,31 @@ void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size)
/* Destination */
bfin_write32(&dst_ch->start_addr, dst);
- bfin_write16(&dst_ch->x_count, size >> 2);
- bfin_write16(&dst_ch->x_modify, 1 << 2);
- bfin_write16(&dst_ch->irq_status, DMA_DONE | DMA_ERR);
+ DMA_MMR_WRITE(&dst_ch->x_count, size >> 2);
+ DMA_MMR_WRITE(&dst_ch->x_modify, 1 << 2);
+ DMA_MMR_WRITE(&dst_ch->irq_status, DMA_DONE | DMA_ERR);
/* Source */
bfin_write32(&src_ch->start_addr, src);
- bfin_write16(&src_ch->x_count, size >> 2);
- bfin_write16(&src_ch->x_modify, 1 << 2);
- bfin_write16(&src_ch->irq_status, DMA_DONE | DMA_ERR);
+ DMA_MMR_WRITE(&src_ch->x_count, size >> 2);
+ DMA_MMR_WRITE(&src_ch->x_modify, 1 << 2);
+ DMA_MMR_WRITE(&src_ch->irq_status, DMA_DONE | DMA_ERR);
/* Enable */
- bfin_write16(&src_ch->cfg, DMAEN | WDSIZE_32);
- bfin_write16(&dst_ch->cfg, WNR | DI_EN | DMAEN | WDSIZE_32);
+ DMA_MMR_WRITE(&src_ch->cfg, DMAEN | WDSIZE_32);
+ DMA_MMR_WRITE(&dst_ch->cfg, WNR | DI_EN_X | DMAEN | WDSIZE_32);
/* Since we are atomic now, don't use the workaround ssync */
__builtin_bfin_ssync();
+
+#ifdef CONFIG_BF60x
+ /* Work around a possible MDMA anomaly. Running 2 MDMA channels to
+ * transfer DDR data to L1 SRAM may corrupt data.
+ * Should be reverted after this issue is root caused.
+ */
+ while (!(DMA_MMR_READ(&dst_ch->irq_status) & DMA_DONE))
+ continue;
+#endif
}
void __init early_dma_memcpy_done(void)
@@ -336,6 +361,42 @@ void __init early_dma_memcpy_done(void)
__builtin_bfin_ssync();
}
+#ifdef CH_MEM_STREAM3_SRC
+#define bfin_read_MDMA_S_CONFIG bfin_read_MDMA_S3_CONFIG
+#define bfin_write_MDMA_S_CONFIG bfin_write_MDMA_S3_CONFIG
+#define bfin_write_MDMA_S_START_ADDR bfin_write_MDMA_S3_START_ADDR
+#define bfin_write_MDMA_S_IRQ_STATUS bfin_write_MDMA_S3_IRQ_STATUS
+#define bfin_write_MDMA_S_X_COUNT bfin_write_MDMA_S3_X_COUNT
+#define bfin_write_MDMA_S_X_MODIFY bfin_write_MDMA_S3_X_MODIFY
+#define bfin_write_MDMA_S_Y_COUNT bfin_write_MDMA_S3_Y_COUNT
+#define bfin_write_MDMA_S_Y_MODIFY bfin_write_MDMA_S3_Y_MODIFY
+#define bfin_write_MDMA_D_CONFIG bfin_write_MDMA_D3_CONFIG
+#define bfin_write_MDMA_D_START_ADDR bfin_write_MDMA_D3_START_ADDR
+#define bfin_read_MDMA_D_IRQ_STATUS bfin_read_MDMA_D3_IRQ_STATUS
+#define bfin_write_MDMA_D_IRQ_STATUS bfin_write_MDMA_D3_IRQ_STATUS
+#define bfin_write_MDMA_D_X_COUNT bfin_write_MDMA_D3_X_COUNT
+#define bfin_write_MDMA_D_X_MODIFY bfin_write_MDMA_D3_X_MODIFY
+#define bfin_write_MDMA_D_Y_COUNT bfin_write_MDMA_D3_Y_COUNT
+#define bfin_write_MDMA_D_Y_MODIFY bfin_write_MDMA_D3_Y_MODIFY
+#else
+#define bfin_read_MDMA_S_CONFIG bfin_read_MDMA_S0_CONFIG
+#define bfin_write_MDMA_S_CONFIG bfin_write_MDMA_S0_CONFIG
+#define bfin_write_MDMA_S_START_ADDR bfin_write_MDMA_S0_START_ADDR
+#define bfin_write_MDMA_S_IRQ_STATUS bfin_write_MDMA_S0_IRQ_STATUS
+#define bfin_write_MDMA_S_X_COUNT bfin_write_MDMA_S0_X_COUNT
+#define bfin_write_MDMA_S_X_MODIFY bfin_write_MDMA_S0_X_MODIFY
+#define bfin_write_MDMA_S_Y_COUNT bfin_write_MDMA_S0_Y_COUNT
+#define bfin_write_MDMA_S_Y_MODIFY bfin_write_MDMA_S0_Y_MODIFY
+#define bfin_write_MDMA_D_CONFIG bfin_write_MDMA_D0_CONFIG
+#define bfin_write_MDMA_D_START_ADDR bfin_write_MDMA_D0_START_ADDR
+#define bfin_read_MDMA_D_IRQ_STATUS bfin_read_MDMA_D0_IRQ_STATUS
+#define bfin_write_MDMA_D_IRQ_STATUS bfin_write_MDMA_D0_IRQ_STATUS
+#define bfin_write_MDMA_D_X_COUNT bfin_write_MDMA_D0_X_COUNT
+#define bfin_write_MDMA_D_X_MODIFY bfin_write_MDMA_D0_X_MODIFY
+#define bfin_write_MDMA_D_Y_COUNT bfin_write_MDMA_D0_Y_COUNT
+#define bfin_write_MDMA_D_Y_MODIFY bfin_write_MDMA_D0_Y_MODIFY
+#endif
+
/**
* __dma_memcpy - program the MDMA registers
*
@@ -358,8 +419,8 @@ static void __dma_memcpy(u32 daddr, s16 dmod, u32 saddr, s16 smod, size_t cnt, u
*/
__builtin_bfin_ssync();
- if (bfin_read_MDMA_S0_CONFIG())
- while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
+ if (bfin_read_MDMA_S_CONFIG())
+ while (!(bfin_read_MDMA_D_IRQ_STATUS() & DMA_DONE))
continue;
if (conf & DMA2D) {
@@ -374,39 +435,42 @@ static void __dma_memcpy(u32 daddr, s16 dmod, u32 saddr, s16 smod, size_t cnt, u
u32 shift = abs(dmod) >> 1;
size_t ycnt = cnt >> (16 - shift);
cnt = 1 << (16 - shift);
- bfin_write_MDMA_D0_Y_COUNT(ycnt);
- bfin_write_MDMA_S0_Y_COUNT(ycnt);
- bfin_write_MDMA_D0_Y_MODIFY(dmod);
- bfin_write_MDMA_S0_Y_MODIFY(smod);
+ bfin_write_MDMA_D_Y_COUNT(ycnt);
+ bfin_write_MDMA_S_Y_COUNT(ycnt);
+ bfin_write_MDMA_D_Y_MODIFY(dmod);
+ bfin_write_MDMA_S_Y_MODIFY(smod);
}
- bfin_write_MDMA_D0_START_ADDR(daddr);
- bfin_write_MDMA_D0_X_COUNT(cnt);
- bfin_write_MDMA_D0_X_MODIFY(dmod);
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+ bfin_write_MDMA_D_START_ADDR(daddr);
+ bfin_write_MDMA_D_X_COUNT(cnt);
+ bfin_write_MDMA_D_X_MODIFY(dmod);
+ bfin_write_MDMA_D_IRQ_STATUS(DMA_DONE | DMA_ERR);
- bfin_write_MDMA_S0_START_ADDR(saddr);
- bfin_write_MDMA_S0_X_COUNT(cnt);
- bfin_write_MDMA_S0_X_MODIFY(smod);
- bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+ bfin_write_MDMA_S_START_ADDR(saddr);
+ bfin_write_MDMA_S_X_COUNT(cnt);
+ bfin_write_MDMA_S_X_MODIFY(smod);
+ bfin_write_MDMA_S_IRQ_STATUS(DMA_DONE | DMA_ERR);
- bfin_write_MDMA_S0_CONFIG(DMAEN | conf);
- bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | conf);
+ bfin_write_MDMA_S_CONFIG(DMAEN | conf);
+ if (conf & DMA2D)
+ bfin_write_MDMA_D_CONFIG(WNR | DI_EN_Y | DMAEN | conf);
+ else
+ bfin_write_MDMA_D_CONFIG(WNR | DI_EN_X | DMAEN | conf);
spin_unlock_irqrestore(&mdma_lock, flags);
SSYNC();
- while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
- if (bfin_read_MDMA_S0_CONFIG())
+ while (!(bfin_read_MDMA_D_IRQ_STATUS() & DMA_DONE))
+ if (bfin_read_MDMA_S_CONFIG())
continue;
else
return;
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+ bfin_write_MDMA_D_IRQ_STATUS(DMA_DONE | DMA_ERR);
- bfin_write_MDMA_S0_CONFIG(0);
- bfin_write_MDMA_D0_CONFIG(0);
+ bfin_write_MDMA_S_CONFIG(0);
+ bfin_write_MDMA_D_CONFIG(0);
}
/**
@@ -448,8 +512,10 @@ static void *_dma_memcpy(void *pdst, const void *psrc, size_t size)
}
size >>= shift;
+#ifndef DMA_MMR_SIZE_32
if (size > 0x10000)
conf |= DMA2D;
+#endif
__dma_memcpy(dst, mod, src, mod, size, conf);
@@ -488,6 +554,9 @@ EXPORT_SYMBOL(dma_memcpy);
*/
void *dma_memcpy_nocache(void *pdst, const void *psrc, size_t size)
{
+#ifdef DMA_MMR_SIZE_32
+ _dma_memcpy(pdst, psrc, size);
+#else
size_t bulk, rest;
bulk = size & ~0xffff;
@@ -495,6 +564,7 @@ void *dma_memcpy_nocache(void *pdst, const void *psrc, size_t size)
if (bulk)
_dma_memcpy(pdst, psrc, bulk);
_dma_memcpy(pdst + bulk, psrc + bulk, rest);
+#endif
return pdst;
}
EXPORT_SYMBOL(dma_memcpy_nocache);
@@ -514,14 +584,14 @@ void *safe_dma_memcpy(void *dst, const void *src, size_t size)
}
EXPORT_SYMBOL(safe_dma_memcpy);
-static void _dma_out(unsigned long addr, unsigned long buf, unsigned short len,
+static void _dma_out(unsigned long addr, unsigned long buf, unsigned DMA_MMR_SIZE_TYPE len,
u16 size, u16 dma_size)
{
blackfin_dcache_flush_range(buf, buf + len * size);
__dma_memcpy(addr, 0, buf, size, len, dma_size);
}
-static void _dma_in(unsigned long addr, unsigned long buf, unsigned short len,
+static void _dma_in(unsigned long addr, unsigned long buf, unsigned DMA_MMR_SIZE_TYPE len,
u16 size, u16 dma_size)
{
blackfin_dcache_invalidate_range(buf, buf + len * size);
@@ -529,7 +599,7 @@ static void _dma_in(unsigned long addr, unsigned long buf, unsigned short len,
}
#define MAKE_DMA_IO(io, bwl, isize, dmasize, cnst) \
-void dma_##io##s##bwl(unsigned long addr, cnst void *buf, unsigned short len) \
+void dma_##io##s##bwl(unsigned long addr, cnst void *buf, unsigned DMA_MMR_SIZE_TYPE len) \
{ \
_dma_##io(addr, (unsigned long)buf, len, isize, WDSIZE_##dmasize); \
} \
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index 02796b88443d..83139aaf3072 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -58,7 +58,7 @@ static struct gpio_port_t * const gpio_array[] = {
(struct gpio_port_t *) FIO0_FLAG_D,
(struct gpio_port_t *) FIO1_FLAG_D,
(struct gpio_port_t *) FIO2_FLAG_D,
-#elif defined(CONFIG_BF54x)
+#elif defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
(struct gpio_port_t *)PORTA_FER,
(struct gpio_port_t *)PORTB_FER,
(struct gpio_port_t *)PORTC_FER,
@@ -66,9 +66,11 @@ static struct gpio_port_t * const gpio_array[] = {
(struct gpio_port_t *)PORTE_FER,
(struct gpio_port_t *)PORTF_FER,
(struct gpio_port_t *)PORTG_FER,
+# if defined(CONFIG_BF54x)
(struct gpio_port_t *)PORTH_FER,
(struct gpio_port_t *)PORTI_FER,
(struct gpio_port_t *)PORTJ_FER,
+# endif
#else
# error no gpio arrays defined
#endif
@@ -210,7 +212,7 @@ static void port_setup(unsigned gpio, unsigned short usage)
else
*port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
SSYNC();
-#elif defined(CONFIG_BF54x)
+#elif defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
if (usage == GPIO_USAGE)
gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
else
@@ -299,7 +301,7 @@ static void portmux_setup(unsigned short per)
pmux |= (function << offset);
bfin_write_PORT_MUX(pmux);
}
-#elif defined(CONFIG_BF54x)
+#elif defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
inline void portmux_setup(unsigned short per)
{
u16 ident = P_IDENT(per);
@@ -377,7 +379,7 @@ static int portmux_group_check(unsigned short per)
}
#endif
-#ifndef CONFIG_BF54x
+#if !(defined(CONFIG_BF54x) || defined(CONFIG_BF60x))
/***********************************************************
*
* FUNCTIONS: Blackfin General Purpose Ports Access Functions
@@ -680,7 +682,7 @@ void bfin_gpio_pm_hibernate_restore(void)
#endif
-#else /* CONFIG_BF54x */
+#else /* CONFIG_BF54x || CONFIG_BF60x */
#ifdef CONFIG_PM
int bfin_pm_standby_ctrl(unsigned ctrl)
@@ -726,7 +728,7 @@ unsigned short get_gpio_dir(unsigned gpio)
}
EXPORT_SYMBOL(get_gpio_dir);
-#endif /* CONFIG_BF54x */
+#endif /* CONFIG_BF54x || CONFIG_BF60x */
/***********************************************************
*
@@ -783,7 +785,7 @@ int peripheral_request(unsigned short per, const char *label)
* be requested and used by several drivers
*/
-#ifdef CONFIG_BF54x
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) {
#else
if (!(per & P_MAYSHARE)) {
@@ -937,7 +939,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!"
" (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio);
}
-#ifndef CONFIG_BF54x
+#if !(defined(CONFIG_BF54x) || defined(CONFIG_BF60x))
else { /* Reset POLAR setting when acquiring a gpio for the first time */
set_gpio_polar(gpio, 0);
}
@@ -1110,7 +1112,7 @@ void bfin_gpio_irq_free(unsigned gpio)
static inline void __bfin_gpio_direction_input(unsigned gpio)
{
-#ifdef CONFIG_BF54x
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
#else
gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
@@ -1138,13 +1140,13 @@ EXPORT_SYMBOL(bfin_gpio_direction_input);
void bfin_gpio_irq_prepare(unsigned gpio)
{
-#ifdef CONFIG_BF54x
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
unsigned long flags;
#endif
port_setup(gpio, GPIO_USAGE);
-#ifdef CONFIG_BF54x
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
flags = hard_local_irq_save();
__bfin_gpio_direction_input(gpio);
hard_local_irq_restore(flags);
@@ -1173,7 +1175,7 @@ int bfin_gpio_direction_output(unsigned gpio, int value)
gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
gpio_set_value(gpio, value);
-#ifdef CONFIG_BF54x
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
#else
gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
@@ -1188,7 +1190,7 @@ EXPORT_SYMBOL(bfin_gpio_direction_output);
int bfin_gpio_get_value(unsigned gpio)
{
-#ifdef CONFIG_BF54x
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));
#else
unsigned long flags;
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
index 886e00014d75..3e366dc2d6e1 100644
--- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c
+++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
@@ -139,7 +139,7 @@ void __init generate_cplb_tables_all(void)
dcplb_bounds[i_d].eaddr = BOOT_ROM_START;
dcplb_bounds[i_d++].data = 0;
/* BootROM -- largest one should be less than 1 meg. */
- dcplb_bounds[i_d].eaddr = BOOT_ROM_START + (1 * 1024 * 1024);
+ dcplb_bounds[i_d].eaddr = BOOT_ROM_START + BOOT_ROM_LENGTH;
dcplb_bounds[i_d++].data = SDRAM_DGENERIC;
if (L2_LENGTH) {
/* Addressing hole up to L2 SRAM. */
@@ -178,7 +178,7 @@ void __init generate_cplb_tables_all(void)
icplb_bounds[i_i].eaddr = BOOT_ROM_START;
icplb_bounds[i_i++].data = 0;
/* BootROM -- largest one should be less than 1 meg. */
- icplb_bounds[i_i].eaddr = BOOT_ROM_START + (1 * 1024 * 1024);
+ icplb_bounds[i_i].eaddr = BOOT_ROM_START + BOOT_ROM_LENGTH;
icplb_bounds[i_i++].data = SDRAM_IGENERIC;
if (L2_LENGTH) {
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c
index 5b88861d6183..e854f9066cbd 100644
--- a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c
+++ b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c
@@ -179,6 +179,12 @@ MGR_ATTR static int dcplb_miss(int cpu)
addr = addr1;
}
+#ifdef CONFIG_BF60x
+ if ((addr >= ASYNC_BANK0_BASE)
+ && (addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE))
+ d_data |= PAGE_SIZE_64MB;
+#endif
+
/* Pick entry to evict */
idx = evict_one_dcplb(cpu);
diff --git a/arch/blackfin/kernel/debug-mmrs.c b/arch/blackfin/kernel/debug-mmrs.c
index 92f664826281..01232a13470d 100644
--- a/arch/blackfin/kernel/debug-mmrs.c
+++ b/arch/blackfin/kernel/debug-mmrs.c
@@ -105,6 +105,7 @@ DEFINE_SYSREG(seqstat, , );
DEFINE_SYSREG(syscfg, , CSYNC());
#define D_SYSREG(sr) debugfs_create_file(#sr, S_IRUSR|S_IWUSR, parent, NULL, &fops_sysreg_##sr)
+#ifndef CONFIG_BF60x
/*
* CAN
*/
@@ -223,8 +224,10 @@ bfin_debug_mmrs_dma(struct dentry *parent, unsigned long base, int num, char mdm
__DMA(CURR_DESC_PTR, curr_desc_ptr);
__DMA(CURR_ADDR, curr_addr);
__DMA(IRQ_STATUS, irq_status);
+#ifndef CONFIG_BF60x
if (strcmp(pfx, "IMDMA") != 0)
__DMA(PERIPHERAL_MAP, peripheral_map);
+#endif
__DMA(CURR_X_COUNT, curr_x_count);
__DMA(CURR_Y_COUNT, curr_y_count);
}
@@ -568,7 +571,7 @@ bfin_debug_mmrs_uart(struct dentry *parent, unsigned long base, int num)
#endif
}
#define UART(num) bfin_debug_mmrs_uart(parent, UART##num##_DLL, num)
-
+#endif /* CONFIG_BF60x */
/*
* The actual debugfs generation
*/
@@ -740,7 +743,7 @@ static int __init bfin_debug_mmrs_init(void)
D32(WPDACNT0);
D32(WPDACNT1);
D32(WPSTAT);
-
+#ifndef CONFIG_BF60x
/* System MMRs */
#ifdef ATAPI_CONTROL
parent = debugfs_create_dir("atapi", top);
@@ -1873,7 +1876,7 @@ static int __init bfin_debug_mmrs_init(void)
}
#endif /* BF54x */
-
+#endif /* CONFIG_BF60x */
debug_mmrs_dentry = top;
return 0;
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S
index 686478f5f66b..f33792cc1a0d 100644
--- a/arch/blackfin/kernel/entry.S
+++ b/arch/blackfin/kernel/entry.S
@@ -64,16 +64,6 @@ ENTRY(_ret_from_fork)
jump (p0);
ENDPROC(_ret_from_fork)
-ENTRY(_sys_fork)
- r0 = -EINVAL;
-#if (ANOMALY_05000371)
- nop;
- nop;
- nop;
-#endif
- rts;
-ENDPROC(_sys_fork)
-
ENTRY(_sys_vfork)
r0 = sp;
r0 += 24;
diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c
index 06459f4bf43a..d776773d3869 100644
--- a/arch/blackfin/kernel/gptimers.c
+++ b/arch/blackfin/kernel/gptimers.c
@@ -23,7 +23,11 @@
printk(KERN_DEBUG "%s:%s:%i: Assertion failed: " #expr "\n", __FILE__, __func__, __LINE__);
#endif
-#define BFIN_TIMER_NUM_GROUP (BFIN_TIMER_OCTET(MAX_BLACKFIN_GPTIMERS - 1) + 1)
+#ifndef CONFIG_BF60x
+# define BFIN_TIMER_NUM_GROUP (BFIN_TIMER_OCTET(MAX_BLACKFIN_GPTIMERS - 1) + 1)
+#else
+# define BFIN_TIMER_NUM_GROUP 1
+#endif
static struct bfin_gptimer_regs * const timer_regs[MAX_BLACKFIN_GPTIMERS] =
{
@@ -158,6 +162,74 @@ uint32_t get_gptimer_count(unsigned int timer_id)
}
EXPORT_SYMBOL(get_gptimer_count);
+#ifdef CONFIG_BF60x
+void set_gptimer_delay(unsigned int timer_id, uint32_t delay)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ bfin_write(&timer_regs[timer_id]->delay, delay);
+ SSYNC();
+}
+EXPORT_SYMBOL(set_gptimer_delay);
+
+uint32_t get_gptimer_delay(unsigned int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ return bfin_read(&timer_regs[timer_id]->delay);
+}
+EXPORT_SYMBOL(get_gptimer_delay);
+#endif
+
+#ifdef CONFIG_BF60x
+int get_gptimer_intr(unsigned int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ return !!(bfin_read(&group_regs[BFIN_TIMER_OCTET(timer_id)]->data_ilat) & timil_mask[timer_id]);
+}
+EXPORT_SYMBOL(get_gptimer_intr);
+
+void clear_gptimer_intr(unsigned int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ bfin_write(&group_regs[BFIN_TIMER_OCTET(timer_id)]->data_ilat, timil_mask[timer_id]);
+}
+EXPORT_SYMBOL(clear_gptimer_intr);
+
+int get_gptimer_over(unsigned int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ return !!(bfin_read(&group_regs[BFIN_TIMER_OCTET(timer_id)]->stat_ilat) & tovf_mask[timer_id]);
+}
+EXPORT_SYMBOL(get_gptimer_over);
+
+void clear_gptimer_over(unsigned int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ bfin_write(&group_regs[BFIN_TIMER_OCTET(timer_id)]->stat_ilat, tovf_mask[timer_id]);
+}
+EXPORT_SYMBOL(clear_gptimer_over);
+
+int get_gptimer_run(unsigned int timer_id)
+{
+ tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+ return !!(bfin_read(&group_regs[BFIN_TIMER_OCTET(timer_id)]->run) & trun_mask[timer_id]);
+}
+EXPORT_SYMBOL(get_gptimer_run);
+
+uint32_t get_gptimer_status(unsigned int group)
+{
+ tassert(group < BFIN_TIMER_NUM_GROUP);
+ return bfin_read(&group_regs[group]->data_ilat);
+}
+EXPORT_SYMBOL(get_gptimer_status);
+
+void set_gptimer_status(unsigned int group, uint32_t value)
+{
+ tassert(group < BFIN_TIMER_NUM_GROUP);
+ bfin_write(&group_regs[group]->data_ilat, value);
+ SSYNC();
+}
+EXPORT_SYMBOL(set_gptimer_status);
+#else
uint32_t get_gptimer_status(unsigned int group)
{
tassert(group < BFIN_TIMER_NUM_GROUP);
@@ -212,6 +284,7 @@ int get_gptimer_run(unsigned int timer_id)
return !!(read_gptimer_status(timer_id) & trun_mask[timer_id]);
}
EXPORT_SYMBOL(get_gptimer_run);
+#endif
void set_gptimer_config(unsigned int timer_id, uint16_t config)
{
@@ -231,6 +304,12 @@ EXPORT_SYMBOL(get_gptimer_config);
void enable_gptimers(uint16_t mask)
{
int i;
+#ifdef CONFIG_BF60x
+ uint16_t imask;
+ imask = bfin_read16(TIMER_DATA_IMSK);
+ imask &= ~mask;
+ bfin_write16(TIMER_DATA_IMSK, imask);
+#endif
tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0);
for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) {
bfin_write(&group_regs[i]->enable, mask & 0xFF);
@@ -253,12 +332,16 @@ static void _disable_gptimers(uint16_t mask)
void disable_gptimers(uint16_t mask)
{
+#ifndef CONFIG_BF60x
int i;
_disable_gptimers(mask);
for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i)
if (mask & (1 << i))
bfin_write(&group_regs[BFIN_TIMER_OCTET(i)]->status, trun_mask[i]);
SSYNC();
+#else
+ _disable_gptimers(mask);
+#endif
}
EXPORT_SYMBOL(disable_gptimers);
diff --git a/arch/blackfin/kernel/init_task.c b/arch/blackfin/kernel/init_task.c
deleted file mode 100644
index d3970e8acd1a..000000000000
--- a/arch/blackfin/kernel/init_task.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later
- */
-
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/init_task.h>
-#include <linux/mqueue.h>
-#include <linux/fs.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
-
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is 8192-byte aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry.
- */
-union thread_union init_thread_union
- __init_task_data = {
-INIT_THREAD_INFO(init_task)};
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index c0f4fe287eb6..2e3994b20169 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -95,7 +95,9 @@ void cpu_idle(void)
idle();
rcu_idle_exit();
tick_nohz_idle_exit();
- schedule_preempt_disabled();
+ preempt_enable_no_resched();
+ schedule();
+ preempt_disable();
}
}
@@ -329,12 +331,16 @@ int in_mem_const(unsigned long addr, unsigned long size,
{
return in_mem_const_off(addr, size, 0, const_addr, const_size);
}
+#ifdef CONFIG_BF60x
+#define ASYNC_ENABLED(bnum, bctlnum) 1
+#else
#define ASYNC_ENABLED(bnum, bctlnum) \
({ \
(bfin_read_EBIU_AMGCTL() & 0xe) < ((bnum + 1) << 1) ? 0 : \
bfin_read_EBIU_AMBCTL##bctlnum() & B##bnum##RDYEN ? 0 : \
1; \
})
+#endif
/*
* We can't read EBIU banks that aren't enabled or we end up hanging
* on the access to the async space. Make sure we validate accesses
diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c
index b0434f89e8de..5272e6eefd92 100644
--- a/arch/blackfin/kernel/reboot.c
+++ b/arch/blackfin/kernel/reboot.c
@@ -22,6 +22,7 @@
__attribute__ ((__l1_text__, __noreturn__))
static void bfin_reset(void)
{
+#ifndef CONFIG_BF60x
if (!ANOMALY_05000353 && !ANOMALY_05000386)
bfrom_SoftReset((void *)(L1_SCRATCH_START + L1_SCRATCH_LENGTH - 20));
@@ -57,7 +58,6 @@ static void bfin_reset(void)
if (__SILICON_REVISION__ < 1 && bfin_revid() < 1)
bfin_read_SWRST();
#endif
-
/* Wait for the SWRST write to complete. Cannot rely on SSYNC
* though as the System state is all reset now.
*/
@@ -72,6 +72,10 @@ static void bfin_reset(void)
while (1)
/* Issue core reset */
asm("raise 1");
+#else
+ while (1)
+ bfin_write_RCU0_CTL(0x1);
+#endif
}
__attribute__((weak))
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 2ad747e909fb..ada8f0fc71e4 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -25,12 +25,16 @@
#include <asm/cacheflush.h>
#include <asm/blackfin.h>
#include <asm/cplbinit.h>
+#include <asm/clocks.h>
#include <asm/div64.h>
#include <asm/cpu.h>
#include <asm/fixed_code.h>
#include <asm/early_printk.h>
#include <asm/irq_handler.h>
#include <asm/pda.h>
+#ifdef CONFIG_BF60x
+#include <mach/pm.h>
+#endif
u16 _bfin_swrst;
EXPORT_SYMBOL(_bfin_swrst);
@@ -550,7 +554,6 @@ static __init void memory_setup(void)
{
#ifdef CONFIG_MTD_UCLINUX
unsigned long mtd_phys = 0;
- unsigned long n;
#endif
unsigned long max_mem;
@@ -594,9 +597,9 @@ static __init void memory_setup(void)
mtd_size = PAGE_ALIGN(*((unsigned long *)(mtd_phys + 8)));
# if defined(CONFIG_EXT2_FS) || defined(CONFIG_EXT3_FS)
- n = ext2_image_size((void *)(mtd_phys + 0x400));
- if (n)
- mtd_size = PAGE_ALIGN(n * 1024);
+ if (*((unsigned short *)(mtd_phys + 0x438)) == EXT2_SUPER_MAGIC)
+ mtd_size =
+ PAGE_ALIGN(*((unsigned long *)(mtd_phys + 0x404)) << 10);
# endif
# if defined(CONFIG_CRAMFS)
@@ -612,7 +615,8 @@ static __init void memory_setup(void)
/* ROM_FS is XIP, so if we found it, we need to limit memory */
if (memory_end > max_mem) {
- pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", max_mem >> 20);
+ pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n",
+ (max_mem - CONFIG_PHY_RAM_BASE_ADDRESS) >> 20);
memory_end = max_mem;
}
}
@@ -642,7 +646,8 @@ static __init void memory_setup(void)
* doesn't exist, or we don't need to - then dont.
*/
if (memory_end > max_mem) {
- pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", max_mem >> 20);
+ pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n",
+ (max_mem - CONFIG_PHY_RAM_BASE_ADDRESS) >> 20);
memory_end = max_mem;
}
@@ -661,8 +666,8 @@ static __init void memory_setup(void)
init_mm.end_data = (unsigned long)_edata;
init_mm.brk = (unsigned long)0;
- printk(KERN_INFO "Board Memory: %ldMB\n", physical_mem_end >> 20);
- printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20);
+ printk(KERN_INFO "Board Memory: %ldMB\n", (physical_mem_end - CONFIG_PHY_RAM_BASE_ADDRESS) >> 20);
+ printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", (_ramend - CONFIG_PHY_RAM_BASE_ADDRESS) >> 20);
printk(KERN_INFO "Memory map:\n"
" fixedcode = 0x%p-0x%p\n"
@@ -705,7 +710,7 @@ void __init find_min_max_pfn(void)
int i;
max_pfn = 0;
- min_low_pfn = memory_end;
+ min_low_pfn = PFN_DOWN(memory_end);
for (i = 0; i < bfin_memmap.nr_map; i++) {
unsigned long start, end;
@@ -748,8 +753,7 @@ static __init void setup_bootmem_allocator(void)
/* pfn of the first usable page frame after kernel image*/
if (min_low_pfn < memory_start >> PAGE_SHIFT)
min_low_pfn = memory_start >> PAGE_SHIFT;
-
- start_pfn = PAGE_OFFSET >> PAGE_SHIFT;
+ start_pfn = CONFIG_PHY_RAM_BASE_ADDRESS >> PAGE_SHIFT;
end_pfn = memory_end >> PAGE_SHIFT;
/*
@@ -794,8 +798,8 @@ static __init void setup_bootmem_allocator(void)
}
/* reserve memory before memory_start, including bootmap */
- reserve_bootmem(PAGE_OFFSET,
- memory_start + bootmap_size + PAGE_SIZE - 1 - PAGE_OFFSET,
+ reserve_bootmem(CONFIG_PHY_RAM_BASE_ADDRESS,
+ memory_start + bootmap_size + PAGE_SIZE - 1 - CONFIG_PHY_RAM_BASE_ADDRESS,
BOOTMEM_DEFAULT);
}
@@ -844,13 +848,40 @@ static inline int __init get_mem_size(void)
break;
}
switch (ddrctl & 0x30000) {
- case DEVWD_4: ret *= 2;
- case DEVWD_8: ret *= 2;
- case DEVWD_16: break;
+ case DEVWD_4:
+ ret *= 2;
+ case DEVWD_8:
+ ret *= 2;
+ case DEVWD_16:
+ break;
}
if ((ddrctl & 0xc000) == 0x4000)
ret *= 2;
return ret;
+#elif defined(CONFIG_BF60x)
+ u32 ddrctl = bfin_read_DMC0_CFG();
+ int ret;
+ switch (ddrctl & 0xf00) {
+ case DEVSZ_64:
+ ret = 64 / 8;
+ break;
+ case DEVSZ_128:
+ ret = 128 / 8;
+ break;
+ case DEVSZ_256:
+ ret = 256 / 8;
+ break;
+ case DEVSZ_512:
+ ret = 512 / 8;
+ break;
+ case DEVSZ_1G:
+ ret = 1024 / 8;
+ break;
+ case DEVSZ_2G:
+ ret = 2048 / 8;
+ break;
+ }
+ return ret;
#endif
BUG();
}
@@ -860,6 +891,22 @@ void __init native_machine_early_platform_add_devices(void)
{
}
+#ifdef CONFIG_BF60x
+static inline u_long bfin_get_clk(char *name)
+{
+ struct clk *clk;
+ u_long clk_rate;
+
+ clk = clk_get(NULL, name);
+ if (IS_ERR(clk))
+ return 0;
+
+ clk_rate = clk_get_rate(clk);
+ clk_put(clk);
+ return clk_rate;
+}
+#endif
+
void __init setup_arch(char **cmdline_p)
{
u32 mmr;
@@ -870,6 +917,7 @@ void __init setup_arch(char **cmdline_p)
enable_shadow_console();
/* Check to make sure we are running on the right processor */
+ mmr = bfin_cpuid();
if (unlikely(CPUID != bfin_cpuid()))
printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n",
CPU, bfin_cpuid(), bfin_revid());
@@ -890,6 +938,10 @@ void __init setup_arch(char **cmdline_p)
memset(&bfin_memmap, 0, sizeof(bfin_memmap));
+#ifdef CONFIG_BF60x
+ /* Should init clock device before parse command early */
+ clk_init();
+#endif
/* If the user does not specify things on the command line, use
* what the bootloader set things up as
*/
@@ -904,6 +956,7 @@ void __init setup_arch(char **cmdline_p)
memory_setup();
+#ifndef CONFIG_BF60x
/* Initialize Async memory banks */
bfin_write_EBIU_AMBCTL0(AMBCTL0VAL);
bfin_write_EBIU_AMBCTL1(AMBCTL1VAL);
@@ -913,6 +966,7 @@ void __init setup_arch(char **cmdline_p)
bfin_write_EBIU_MODE(CONFIG_EBIU_MODEVAL);
bfin_write_EBIU_FCTL(CONFIG_EBIU_FCTLVAL);
#endif
+#endif
#ifdef CONFIG_BFIN_HYSTERESIS_CONTROL
bfin_write_PORTF_HYSTERESIS(HYST_PORTF_0_15);
bfin_write_PORTG_HYSTERESIS(HYST_PORTG_0_15);
@@ -938,7 +992,7 @@ void __init setup_arch(char **cmdline_p)
printk(KERN_INFO "Hardware Trace %s and %sabled\n",
(mmr & 0x1) ? "active" : "off",
(mmr & 0x2) ? "en" : "dis");
-
+#ifndef CONFIG_BF60x
mmr = bfin_read_SYSCR();
printk(KERN_INFO "Boot Mode: %i\n", mmr & 0xF);
@@ -980,7 +1034,7 @@ void __init setup_arch(char **cmdline_p)
printk(KERN_INFO "Recovering from Watchdog event\n");
else if (_bfin_swrst & RESET_SOFTWARE)
printk(KERN_NOTICE "Reset caused by Software reset\n");
-
+#endif
printk(KERN_INFO "Blackfin support (C) 2004-2010 Analog Devices, Inc.\n");
if (bfin_compiled_revid() == 0xffff)
printk(KERN_INFO "Compiled for ADSP-%s Rev any, running on 0.%d\n", CPU, bfin_revid());
@@ -1008,8 +1062,13 @@ void __init setup_arch(char **cmdline_p)
printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n");
+#ifdef CONFIG_BF60x
+ printk(KERN_INFO "Processor Speed: %lu MHz core clock, %lu MHz SCLk, %lu MHz SCLK0, %lu MHz SCLK1 and %lu MHz DCLK\n",
+ cclk / 1000000, bfin_get_clk("SYSCLK") / 1000000, get_sclk0() / 1000000, get_sclk1() / 1000000, get_dclk() / 1000000);
+#else
printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n",
cclk / 1000000, sclk / 1000000);
+#endif
setup_bootmem_allocator();
@@ -1060,10 +1119,12 @@ subsys_initcall(topology_init);
/* Get the input clock frequency */
static u_long cached_clkin_hz = CONFIG_CLKIN_HZ;
+#ifndef CONFIG_BF60x
static u_long get_clkin_hz(void)
{
return cached_clkin_hz;
}
+#endif
static int __init early_init_clkin_hz(char *buf)
{
cached_clkin_hz = simple_strtoul(buf, NULL, 0);
@@ -1075,6 +1136,7 @@ static int __init early_init_clkin_hz(char *buf)
}
early_param("clkin_hz=", early_init_clkin_hz);
+#ifndef CONFIG_BF60x
/* Get the voltage input multiplier */
static u_long get_vco(void)
{
@@ -1097,10 +1159,14 @@ static u_long get_vco(void)
cached_vco *= msel;
return cached_vco;
}
+#endif
/* Get the Core clock */
u_long get_cclk(void)
{
+#ifdef CONFIG_BF60x
+ return bfin_get_clk("CCLK");
+#else
static u_long cached_cclk_pll_div, cached_cclk;
u_long csel, ssel;
@@ -1120,12 +1186,39 @@ u_long get_cclk(void)
else
cached_cclk = get_vco() >> csel;
return cached_cclk;
+#endif
}
EXPORT_SYMBOL(get_cclk);
-/* Get the System clock */
+#ifdef CONFIG_BF60x
+/* Get the bf60x clock of SCLK0 domain */
+u_long get_sclk0(void)
+{
+ return bfin_get_clk("SCLK0");
+}
+EXPORT_SYMBOL(get_sclk0);
+
+/* Get the bf60x clock of SCLK1 domain */
+u_long get_sclk1(void)
+{
+ return bfin_get_clk("SCLK1");
+}
+EXPORT_SYMBOL(get_sclk1);
+
+/* Get the bf60x DRAM clock */
+u_long get_dclk(void)
+{
+ return bfin_get_clk("DCLK");
+}
+EXPORT_SYMBOL(get_dclk);
+#endif
+
+/* Get the default system clock */
u_long get_sclk(void)
{
+#ifdef CONFIG_BF60x
+ return get_sclk0();
+#else
static u_long cached_sclk;
u_long ssel;
@@ -1146,6 +1239,7 @@ u_long get_sclk(void)
cached_sclk = get_vco() / ssel;
return cached_sclk;
+#endif
}
EXPORT_SYMBOL(get_sclk);
diff --git a/arch/blackfin/kernel/shadow_console.c b/arch/blackfin/kernel/shadow_console.c
index 557e9fef406a..aeb8343eeb03 100644
--- a/arch/blackfin/kernel/shadow_console.c
+++ b/arch/blackfin/kernel/shadow_console.c
@@ -15,9 +15,9 @@
#include <asm/irq_handler.h>
#include <asm/early_printk.h>
-#define SHADOW_CONSOLE_START (0x500)
-#define SHADOW_CONSOLE_END (0x1000)
-#define SHADOW_CONSOLE_MAGIC_LOC (0x4F0)
+#define SHADOW_CONSOLE_START (CONFIG_PHY_RAM_BASE_ADDRESS + 0x500)
+#define SHADOW_CONSOLE_END (CONFIG_PHY_RAM_BASE_ADDRESS + 0x1000)
+#define SHADOW_CONSOLE_MAGIC_LOC (CONFIG_PHY_RAM_BASE_ADDRESS + 0x4F0)
#define SHADOW_CONSOLE_MAGIC (0xDEADBEEF)
static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START;
diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c
index d98f2d69b0c4..f608f02f29a3 100644
--- a/arch/blackfin/kernel/time-ts.c
+++ b/arch/blackfin/kernel/time-ts.c
@@ -66,8 +66,14 @@ void __init setup_gptimer0(void)
{
disable_gptimers(TIMER0bit);
+#ifdef CONFIG_BF60x
+ bfin_write16(TIMER_DATA_IMSK, 0);
+ set_gptimer_config(TIMER0_id, TIMER_OUT_DIS
+ | TIMER_MODE_PWM_CONT | TIMER_PULSE_HI | TIMER_IRQ_PER);
+#else
set_gptimer_config(TIMER0_id, \
TIMER_OUT_DIS | TIMER_PERIOD_CNT | TIMER_MODE_PWM);
+#endif
set_gptimer_period(TIMER0_id, -1);
set_gptimer_pwidth(TIMER0_id, -2);
SSYNC();
@@ -135,9 +141,15 @@ static void bfin_gptmr0_set_mode(enum clock_event_mode mode,
{
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC: {
+#ifndef CONFIG_BF60x
set_gptimer_config(TIMER0_id, \
TIMER_OUT_DIS | TIMER_IRQ_ENA | \
TIMER_PERIOD_CNT | TIMER_MODE_PWM);
+#else
+ set_gptimer_config(TIMER0_id, TIMER_OUT_DIS
+ | TIMER_MODE_PWM_CONT | TIMER_PULSE_HI | TIMER_IRQ_PER);
+#endif
+
set_gptimer_period(TIMER0_id, get_sclk() / HZ);
set_gptimer_pwidth(TIMER0_id, get_sclk() / HZ - 1);
enable_gptimers(TIMER0bit);
@@ -145,8 +157,14 @@ static void bfin_gptmr0_set_mode(enum clock_event_mode mode,
}
case CLOCK_EVT_MODE_ONESHOT:
disable_gptimers(TIMER0bit);
+#ifndef CONFIG_BF60x
set_gptimer_config(TIMER0_id, \
TIMER_OUT_DIS | TIMER_IRQ_ENA | TIMER_MODE_PWM);
+#else
+ set_gptimer_config(TIMER0_id, TIMER_OUT_DIS | TIMER_MODE_PWM
+ | TIMER_PULSE_HI | TIMER_IRQ_WID_DLY);
+#endif
+
set_gptimer_period(TIMER0_id, 0);
break;
case CLOCK_EVT_MODE_UNUSED:
@@ -160,7 +178,7 @@ static void bfin_gptmr0_set_mode(enum clock_event_mode mode,
static void bfin_gptmr0_ack(void)
{
- set_gptimer_status(TIMER_GROUP1, TIMER_STATUS_TIMIL0);
+ clear_gptimer_intr(TIMER0_id);
}
static void __init bfin_gptmr0_init(void)
@@ -197,7 +215,7 @@ static struct clock_event_device clockevent_gptmr0 = {
.rating = 300,
.irq = IRQ_TIMER0,
.shift = 32,
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.set_next_event = bfin_gptmr0_set_next_event,
.set_mode = bfin_gptmr0_set_mode,
};
@@ -312,6 +330,11 @@ void bfin_coretmr_clockevent_init(void)
#endif
+#ifdef CONFIG_SMP
+ evt->broadcast = smp_timer_broadcast;
+#endif
+
+
evt->name = "bfin_core_timer";
evt->rating = 350;
evt->irq = -1;
diff --git a/arch/blackfin/lib/divsi3.S b/arch/blackfin/lib/divsi3.S
index f89c5a49c47b..ef2cd99efb89 100644
--- a/arch/blackfin/lib/divsi3.S
+++ b/arch/blackfin/lib/divsi3.S
@@ -1,7 +1,7 @@
/*
* Copyright 2004-2009 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*
* 16 / 32 bit signed division.
* Special cases :
diff --git a/arch/blackfin/lib/memchr.S b/arch/blackfin/lib/memchr.S
index 542e40f8775f..bcfc8a14c3f2 100644
--- a/arch/blackfin/lib/memchr.S
+++ b/arch/blackfin/lib/memchr.S
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2009 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
diff --git a/arch/blackfin/lib/memcmp.S b/arch/blackfin/lib/memcmp.S
index ce5b9f1a8267..2e1c9477f2f7 100644
--- a/arch/blackfin/lib/memcmp.S
+++ b/arch/blackfin/lib/memcmp.S
@@ -1,7 +1,7 @@
/*
* Copyright 2004-2009 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
diff --git a/arch/blackfin/lib/memcpy.S b/arch/blackfin/lib/memcpy.S
index c31bf22aab19..53cb3698ab33 100644
--- a/arch/blackfin/lib/memcpy.S
+++ b/arch/blackfin/lib/memcpy.S
@@ -7,7 +7,7 @@
*
* Copyright 2004-2009 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
diff --git a/arch/blackfin/lib/memmove.S b/arch/blackfin/lib/memmove.S
index 4eca566237a4..e0b78208f1d6 100644
--- a/arch/blackfin/lib/memmove.S
+++ b/arch/blackfin/lib/memmove.S
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2009 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
diff --git a/arch/blackfin/lib/memset.S b/arch/blackfin/lib/memset.S
index eab1bef3f5bf..cdcf9148ea20 100644
--- a/arch/blackfin/lib/memset.S
+++ b/arch/blackfin/lib/memset.S
@@ -1,7 +1,7 @@
/*
* Copyright 2004-2009 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
diff --git a/arch/blackfin/lib/modsi3.S b/arch/blackfin/lib/modsi3.S
index 8b0c7d4052af..f7026ce1fa0e 100644
--- a/arch/blackfin/lib/modsi3.S
+++ b/arch/blackfin/lib/modsi3.S
@@ -6,7 +6,7 @@
*
* Copyright 2004-2009 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
.global ___modsi3;
diff --git a/arch/blackfin/lib/muldi3.S b/arch/blackfin/lib/muldi3.S
index 953a38a1d1d1..abf9b2a515b2 100644
--- a/arch/blackfin/lib/muldi3.S
+++ b/arch/blackfin/lib/muldi3.S
@@ -1,7 +1,7 @@
/*
* Copyright 2008 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
.align 2
diff --git a/arch/blackfin/lib/smulsi3_highpart.S b/arch/blackfin/lib/smulsi3_highpart.S
index 99ee8c5de38b..e50d6c4ac2a5 100644
--- a/arch/blackfin/lib/smulsi3_highpart.S
+++ b/arch/blackfin/lib/smulsi3_highpart.S
@@ -1,7 +1,7 @@
/*
* Copyright 2007 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
.align 2
diff --git a/arch/blackfin/lib/strcmp.S b/arch/blackfin/lib/strcmp.S
index d7c1d158973b..9c8b9863713e 100644
--- a/arch/blackfin/lib/strcmp.S
+++ b/arch/blackfin/lib/strcmp.S
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
diff --git a/arch/blackfin/lib/strcpy.S b/arch/blackfin/lib/strcpy.S
index a6a0c6363806..9495aa77cc40 100644
--- a/arch/blackfin/lib/strcpy.S
+++ b/arch/blackfin/lib/strcpy.S
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
diff --git a/arch/blackfin/lib/strncmp.S b/arch/blackfin/lib/strncmp.S
index 6da37c34a847..3bfaedce893e 100644
--- a/arch/blackfin/lib/strncmp.S
+++ b/arch/blackfin/lib/strncmp.S
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
diff --git a/arch/blackfin/lib/strncpy.S b/arch/blackfin/lib/strncpy.S
index 2c07dddac995..92fd1823bbee 100644
--- a/arch/blackfin/lib/strncpy.S
+++ b/arch/blackfin/lib/strncpy.S
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
diff --git a/arch/blackfin/lib/udivsi3.S b/arch/blackfin/lib/udivsi3.S
index 97e904315ec6..748a6a2e8c17 100644
--- a/arch/blackfin/lib/udivsi3.S
+++ b/arch/blackfin/lib/udivsi3.S
@@ -1,7 +1,7 @@
/*
* Copyright 2004-2009 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
diff --git a/arch/blackfin/lib/umodsi3.S b/arch/blackfin/lib/umodsi3.S
index 168eba7c64c8..3794c00d859d 100644
--- a/arch/blackfin/lib/umodsi3.S
+++ b/arch/blackfin/lib/umodsi3.S
@@ -3,7 +3,7 @@
*
* Copyright 2004-2009 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifdef CONFIG_ARITHMETIC_OPS_L1
diff --git a/arch/blackfin/lib/umulsi3_highpart.S b/arch/blackfin/lib/umulsi3_highpart.S
index 051824a6ed00..0dcace96e4e7 100644
--- a/arch/blackfin/lib/umulsi3_highpart.S
+++ b/arch/blackfin/lib/umulsi3_highpart.S
@@ -1,7 +1,7 @@
/*
* Copyright 2007 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
.align 2
diff --git a/arch/blackfin/mach-bf518/boards/ezbrd.c b/arch/blackfin/mach-bf518/boards/ezbrd.c
index a17395727efa..f8047ca3b339 100644
--- a/arch/blackfin/mach-bf518/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf518/boards/ezbrd.c
@@ -529,6 +529,8 @@ static struct platform_device bfin_i2s = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -547,6 +549,9 @@ static struct platform_device i2c_bfin_twi_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#endif
diff --git a/arch/blackfin/mach-bf518/boards/tcm-bf518.c b/arch/blackfin/mach-bf518/boards/tcm-bf518.c
index 6eebee4e4217..0bedc737566b 100644
--- a/arch/blackfin/mach-bf518/boards/tcm-bf518.c
+++ b/arch/blackfin/mach-bf518/boards/tcm-bf518.c
@@ -455,6 +455,8 @@ static struct platform_device bfin_sir1_device = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -473,6 +475,9 @@ static struct platform_device i2c_bfin_twi_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#endif
diff --git a/arch/blackfin/mach-bf518/include/mach/anomaly.h b/arch/blackfin/mach-bf518/include/mach/anomaly.h
index 56383f7cbc07..845e6bc8d633 100644
--- a/arch/blackfin/mach-bf518/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf518/include/mach/anomaly.h
@@ -6,8 +6,7 @@
* DO NOT EDIT THIS FILE
*
* Copyright 2004-2011 Analog Devices Inc.
- * Licensed under the ADI BSD license.
- * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd
+ * Licensed under the Clear BSD license.
*/
/* This file should be up to date with:
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF512.h b/arch/blackfin/mach-bf518/include/mach/cdefBF512.h
index bb79627f0929..1c03ad4bcb72 100644
--- a/arch/blackfin/mach-bf518/include/mach/cdefBF512.h
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF512.h
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _CDEF_BF512_H
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF514.h b/arch/blackfin/mach-bf518/include/mach/cdefBF514.h
index dc988668203e..861221d1dcc9 100644
--- a/arch/blackfin/mach-bf518/include/mach/cdefBF514.h
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF514.h
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _CDEF_BF514_H
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF516.h b/arch/blackfin/mach-bf518/include/mach/cdefBF516.h
index 142e45cbc253..cc9bf0d378c3 100644
--- a/arch/blackfin/mach-bf518/include/mach/cdefBF516.h
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF516.h
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _CDEF_BF516_H
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF518.h b/arch/blackfin/mach-bf518/include/mach/cdefBF518.h
index e638197bf8b1..96a82fd62ef1 100644
--- a/arch/blackfin/mach-bf518/include/mach/cdefBF518.h
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF518.h
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _CDEF_BF518_H
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF512.h b/arch/blackfin/mach-bf518/include/mach/defBF512.h
index 729704078cd7..e6a017faad01 100644
--- a/arch/blackfin/mach-bf518/include/mach/defBF512.h
+++ b/arch/blackfin/mach-bf518/include/mach/defBF512.h
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF512_H
@@ -1083,77 +1083,6 @@
#define ERR_NCOR 0x8000 /* Error Not Corrected Indicator */
-/* ******************** TWO-WIRE INTERFACE (TWI) MASKS ***********************/
-/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y); ) */
-#define CLKLOW(x) ((x) & 0xFF) /* Periods Clock Is Held Low */
-#define CLKHI(y) (((y)&0xFF)<<0x8) /* Periods Before New Clock Low */
-
-/* TWI_PRESCALE Masks */
-#define PRESCALE 0x007F /* SCLKs Per Internal Time Reference (10MHz) */
-#define TWI_ENA 0x0080 /* TWI Enable */
-#define SCCB 0x0200 /* SCCB Compatibility Enable */
-
-/* TWI_SLAVE_CTL Masks */
-#define SEN 0x0001 /* Slave Enable */
-#define SADD_LEN 0x0002 /* Slave Address Length */
-#define STDVAL 0x0004 /* Slave Transmit Data Valid */
-#define NAK 0x0008 /* NAK/ACK* Generated At Conclusion Of Transfer */
-#define GEN 0x0010 /* General Call Adrress Matching Enabled */
-
-/* TWI_SLAVE_STAT Masks */
-#define SDIR 0x0001 /* Slave Transfer Direction (Transmit/Receive*) */
-#define GCALL 0x0002 /* General Call Indicator */
-
-/* TWI_MASTER_CTL Masks */
-#define MEN 0x0001 /* Master Mode Enable */
-#define MADD_LEN 0x0002 /* Master Address Length */
-#define MDIR 0x0004 /* Master Transmit Direction (RX/TX*) */
-#define FAST 0x0008 /* Use Fast Mode Timing Specs */
-#define STOP 0x0010 /* Issue Stop Condition */
-#define RSTART 0x0020 /* Repeat Start or Stop* At End Of Transfer */
-#define DCNT 0x3FC0 /* Data Bytes To Transfer */
-#define SDAOVR 0x4000 /* Serial Data Override */
-#define SCLOVR 0x8000 /* Serial Clock Override */
-
-/* TWI_MASTER_STAT Masks */
-#define MPROG 0x0001 /* Master Transfer In Progress */
-#define LOSTARB 0x0002 /* Lost Arbitration Indicator (Xfer Aborted) */
-#define ANAK 0x0004 /* Address Not Acknowledged */
-#define DNAK 0x0008 /* Data Not Acknowledged */
-#define BUFRDERR 0x0010 /* Buffer Read Error */
-#define BUFWRERR 0x0020 /* Buffer Write Error */
-#define SDASEN 0x0040 /* Serial Data Sense */
-#define SCLSEN 0x0080 /* Serial Clock Sense */
-#define BUSBUSY 0x0100 /* Bus Busy Indicator */
-
-/* TWI_INT_SRC and TWI_INT_ENABLE Masks */
-#define SINIT 0x0001 /* Slave Transfer Initiated */
-#define SCOMP 0x0002 /* Slave Transfer Complete */
-#define SERR 0x0004 /* Slave Transfer Error */
-#define SOVF 0x0008 /* Slave Overflow */
-#define MCOMP 0x0010 /* Master Transfer Complete */
-#define MERR 0x0020 /* Master Transfer Error */
-#define XMTSERV 0x0040 /* Transmit FIFO Service */
-#define RCVSERV 0x0080 /* Receive FIFO Service */
-
-/* TWI_FIFO_CTRL Masks */
-#define XMTFLUSH 0x0001 /* Transmit Buffer Flush */
-#define RCVFLUSH 0x0002 /* Receive Buffer Flush */
-#define XMTINTLEN 0x0004 /* Transmit Buffer Interrupt Length */
-#define RCVINTLEN 0x0008 /* Receive Buffer Interrupt Length */
-
-/* TWI_FIFO_STAT Masks */
-#define XMTSTAT 0x0003 /* Transmit FIFO Status */
-#define XMT_EMPTY 0x0000 /* Transmit FIFO Empty */
-#define XMT_HALF 0x0001 /* Transmit FIFO Has 1 Byte To Write */
-#define XMT_FULL 0x0003 /* Transmit FIFO Full (2 Bytes To Write) */
-
-#define RCVSTAT 0x000C /* Receive FIFO Status */
-#define RCV_EMPTY 0x0000 /* Receive FIFO Empty */
-#define RCV_HALF 0x0004 /* Receive FIFO Has 1 Byte To Read */
-#define RCV_FULL 0x000C /* Receive FIFO Full (2 Bytes To Read) */
-
-
/* ******************* PIN CONTROL REGISTER MASKS ************************/
/* PORT_MUX Masks */
#define PJSE 0x0001 /* Port J SPI/SPORT Enable */
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF514.h b/arch/blackfin/mach-bf518/include/mach/defBF514.h
index cfab428e577c..97feaa629ed7 100644
--- a/arch/blackfin/mach-bf518/include/mach/defBF514.h
+++ b/arch/blackfin/mach-bf518/include/mach/defBF514.h
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2009 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF514_H
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF516.h b/arch/blackfin/mach-bf518/include/mach/defBF516.h
index 22a3aa0d2629..7c79cb6a03b1 100644
--- a/arch/blackfin/mach-bf518/include/mach/defBF516.h
+++ b/arch/blackfin/mach-bf518/include/mach/defBF516.h
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2009 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF516_H
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF518.h b/arch/blackfin/mach-bf518/include/mach/defBF518.h
index cb18270e55c2..12042ff13601 100644
--- a/arch/blackfin/mach-bf518/include/mach/defBF518.h
+++ b/arch/blackfin/mach-bf518/include/mach/defBF518.h
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2009 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF518_H
diff --git a/arch/blackfin/mach-bf527/boards/ad7160eval.c b/arch/blackfin/mach-bf527/boards/ad7160eval.c
index fad7fea1b0bf..d58f50e5aa4b 100644
--- a/arch/blackfin/mach-bf527/boards/ad7160eval.c
+++ b/arch/blackfin/mach-bf527/boards/ad7160eval.c
@@ -569,6 +569,8 @@ static const struct ad7160_platform_data bfin_ad7160_ts_info = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -587,6 +589,9 @@ static struct platform_device i2c_bfin_twi_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#endif
@@ -681,6 +686,7 @@ static struct bfin_rotary_platform_data bfin_rotary_data = {
.rotary_button_key = KEY_ENTER,
.debounce = 10, /* 0..17 */
.mode = ROT_QUAD_ENC | ROT_DEBE,
+ .pm_wakeup = 1,
};
static struct resource bfin_rotary_resources[] = {
diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c
index 65b7fbd30e16..413d0132b66f 100644
--- a/arch/blackfin/mach-bf527/boards/cm_bf527.c
+++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c
@@ -698,6 +698,8 @@ static struct platform_device bfin_sir1_device = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -716,6 +718,9 @@ static struct platform_device i2c_bfin_twi_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#endif
diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c
index 17c6a24cc076..50bda79194e5 100644
--- a/arch/blackfin/mach-bf527/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf527/boards/ezbrd.c
@@ -576,6 +576,8 @@ static struct platform_device bfin_sir1_device = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -594,6 +596,9 @@ static struct platform_device i2c_bfin_twi_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#endif
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index 2f9a2bd83ce4..af732eb3a687 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -869,6 +869,8 @@ static struct platform_device bfin_sir1_device = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -887,6 +889,9 @@ static struct platform_device i2c_bfin_twi_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#endif
@@ -1105,6 +1110,7 @@ static struct bfin_rotary_platform_data bfin_rotary_data = {
.rotary_button_key = KEY_ENTER,
.debounce = 10, /* 0..17 */
.mode = ROT_QUAD_ENC | ROT_DEBE,
+ .pm_wakeup = 1,
};
static struct resource bfin_rotary_resources[] = {
diff --git a/arch/blackfin/mach-bf527/boards/tll6527m.c b/arch/blackfin/mach-bf527/boards/tll6527m.c
index d192c0ac941c..1509c5a8a3ff 100644
--- a/arch/blackfin/mach-bf527/boards/tll6527m.c
+++ b/arch/blackfin/mach-bf527/boards/tll6527m.c
@@ -656,6 +656,8 @@ static struct platform_device bfin_sir1_device = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -674,6 +676,9 @@ static struct platform_device i2c_bfin_twi_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#endif
diff --git a/arch/blackfin/mach-bf527/include/mach/anomaly.h b/arch/blackfin/mach-bf527/include/mach/anomaly.h
index 688470611e15..aa14110be4c4 100644
--- a/arch/blackfin/mach-bf527/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf527/include/mach/anomaly.h
@@ -6,8 +6,7 @@
* DO NOT EDIT THIS FILE
*
* Copyright 2004-2011 Analog Devices Inc.
- * Licensed under the ADI BSD license.
- * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd
+ * Licensed under the Clear BSD license.
*/
/* This file should be up to date with:
diff --git a/arch/blackfin/mach-bf527/include/mach/defBF522.h b/arch/blackfin/mach-bf527/include/mach/defBF522.h
index 37d353a19722..e007017cf958 100644
--- a/arch/blackfin/mach-bf527/include/mach/defBF522.h
+++ b/arch/blackfin/mach-bf527/include/mach/defBF522.h
@@ -1,7 +1,7 @@
/*
* Copyright 2007-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF522_H
@@ -1084,77 +1084,6 @@
#define ERR_NCOR 0x8000 /* Error Not Corrected Indicator */
-/* ******************** TWO-WIRE INTERFACE (TWI) MASKS ***********************/
-/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y); ) */
-#define CLKLOW(x) ((x) & 0xFF) /* Periods Clock Is Held Low */
-#define CLKHI(y) (((y)&0xFF)<<0x8) /* Periods Before New Clock Low */
-
-/* TWI_PRESCALE Masks */
-#define PRESCALE 0x007F /* SCLKs Per Internal Time Reference (10MHz) */
-#define TWI_ENA 0x0080 /* TWI Enable */
-#define SCCB 0x0200 /* SCCB Compatibility Enable */
-
-/* TWI_SLAVE_CTL Masks */
-#define SEN 0x0001 /* Slave Enable */
-#define SADD_LEN 0x0002 /* Slave Address Length */
-#define STDVAL 0x0004 /* Slave Transmit Data Valid */
-#define NAK 0x0008 /* NAK/ACK* Generated At Conclusion Of Transfer */
-#define GEN 0x0010 /* General Call Adrress Matching Enabled */
-
-/* TWI_SLAVE_STAT Masks */
-#define SDIR 0x0001 /* Slave Transfer Direction (Transmit/Receive*) */
-#define GCALL 0x0002 /* General Call Indicator */
-
-/* TWI_MASTER_CTL Masks */
-#define MEN 0x0001 /* Master Mode Enable */
-#define MADD_LEN 0x0002 /* Master Address Length */
-#define MDIR 0x0004 /* Master Transmit Direction (RX/TX*) */
-#define FAST 0x0008 /* Use Fast Mode Timing Specs */
-#define STOP 0x0010 /* Issue Stop Condition */
-#define RSTART 0x0020 /* Repeat Start or Stop* At End Of Transfer */
-#define DCNT 0x3FC0 /* Data Bytes To Transfer */
-#define SDAOVR 0x4000 /* Serial Data Override */
-#define SCLOVR 0x8000 /* Serial Clock Override */
-
-/* TWI_MASTER_STAT Masks */
-#define MPROG 0x0001 /* Master Transfer In Progress */
-#define LOSTARB 0x0002 /* Lost Arbitration Indicator (Xfer Aborted) */
-#define ANAK 0x0004 /* Address Not Acknowledged */
-#define DNAK 0x0008 /* Data Not Acknowledged */
-#define BUFRDERR 0x0010 /* Buffer Read Error */
-#define BUFWRERR 0x0020 /* Buffer Write Error */
-#define SDASEN 0x0040 /* Serial Data Sense */
-#define SCLSEN 0x0080 /* Serial Clock Sense */
-#define BUSBUSY 0x0100 /* Bus Busy Indicator */
-
-/* TWI_INT_SRC and TWI_INT_ENABLE Masks */
-#define SINIT 0x0001 /* Slave Transfer Initiated */
-#define SCOMP 0x0002 /* Slave Transfer Complete */
-#define SERR 0x0004 /* Slave Transfer Error */
-#define SOVF 0x0008 /* Slave Overflow */
-#define MCOMP 0x0010 /* Master Transfer Complete */
-#define MERR 0x0020 /* Master Transfer Error */
-#define XMTSERV 0x0040 /* Transmit FIFO Service */
-#define RCVSERV 0x0080 /* Receive FIFO Service */
-
-/* TWI_FIFO_CTRL Masks */
-#define XMTFLUSH 0x0001 /* Transmit Buffer Flush */
-#define RCVFLUSH 0x0002 /* Receive Buffer Flush */
-#define XMTINTLEN 0x0004 /* Transmit Buffer Interrupt Length */
-#define RCVINTLEN 0x0008 /* Receive Buffer Interrupt Length */
-
-/* TWI_FIFO_STAT Masks */
-#define XMTSTAT 0x0003 /* Transmit FIFO Status */
-#define XMT_EMPTY 0x0000 /* Transmit FIFO Empty */
-#define XMT_HALF 0x0001 /* Transmit FIFO Has 1 Byte To Write */
-#define XMT_FULL 0x0003 /* Transmit FIFO Full (2 Bytes To Write) */
-
-#define RCVSTAT 0x000C /* Receive FIFO Status */
-#define RCV_EMPTY 0x0000 /* Receive FIFO Empty */
-#define RCV_HALF 0x0004 /* Receive FIFO Has 1 Byte To Read */
-#define RCV_FULL 0x000C /* Receive FIFO Full (2 Bytes To Read) */
-
-
/* Omit CAN masks from defBF534.h */
/* ******************* PIN CONTROL REGISTER MASKS ************************/
diff --git a/arch/blackfin/mach-bf527/include/mach/defBF525.h b/arch/blackfin/mach-bf527/include/mach/defBF525.h
index aab80bb1a683..71578d964d00 100644
--- a/arch/blackfin/mach-bf527/include/mach/defBF525.h
+++ b/arch/blackfin/mach-bf527/include/mach/defBF525.h
@@ -1,7 +1,7 @@
/*
* Copyright 2007-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF525_H
diff --git a/arch/blackfin/mach-bf527/include/mach/defBF527.h b/arch/blackfin/mach-bf527/include/mach/defBF527.h
index 05369a92fbc8..aeb84795b35e 100644
--- a/arch/blackfin/mach-bf527/include/mach/defBF527.h
+++ b/arch/blackfin/mach-bf527/include/mach/defBF527.h
@@ -1,7 +1,7 @@
/*
* Copyright 2007-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF527_H
diff --git a/arch/blackfin/mach-bf533/include/mach/anomaly.h b/arch/blackfin/mach-bf533/include/mach/anomaly.h
index 03f2b40912a3..3a8f73a669f0 100644
--- a/arch/blackfin/mach-bf533/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf533/include/mach/anomaly.h
@@ -6,8 +6,7 @@
* DO NOT EDIT THIS FILE
*
* Copyright 2004-2011 Analog Devices Inc.
- * Licensed under the ADI BSD license.
- * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd
+ * Licensed under the Clear BSD license.
*/
/* This file should be up to date with:
diff --git a/arch/blackfin/mach-bf533/include/mach/defBF532.h b/arch/blackfin/mach-bf533/include/mach/defBF532.h
index 2376d5393511..d438150b1025 100644
--- a/arch/blackfin/mach-bf533/include/mach/defBF532.h
+++ b/arch/blackfin/mach-bf533/include/mach/defBF532.h
@@ -3,7 +3,7 @@
*
* Copyright 2005-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF532_H
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537e.c b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
index 27fd2c32ae9a..9408ab56d87f 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537e.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
@@ -486,6 +486,8 @@ static struct platform_device bfin_sir1_device = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -504,6 +506,9 @@ static struct platform_device i2c_bfin_twi_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#endif
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537u.c b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
index 3f3abad86ec3..0143d8bef909 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537u.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
@@ -451,6 +451,8 @@ static struct platform_device bfin_sir1_device = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -469,6 +471,9 @@ static struct platform_device i2c_bfin_twi_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#endif
diff --git a/arch/blackfin/mach-bf537/boards/dnp5370.c b/arch/blackfin/mach-bf537/boards/dnp5370.c
index 6f77bf708ec0..8bbf0a23fd49 100644
--- a/arch/blackfin/mach-bf537/boards/dnp5370.c
+++ b/arch/blackfin/mach-bf537/boards/dnp5370.c
@@ -329,6 +329,8 @@ static struct platform_device bfin_uart1_device = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -347,6 +349,9 @@ static struct platform_device i2c_bfin_twi_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#endif
diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c
index d2d71282618f..a10f90e444bc 100644
--- a/arch/blackfin/mach-bf537/boards/minotaur.c
+++ b/arch/blackfin/mach-bf537/boards/minotaur.c
@@ -386,6 +386,8 @@ static struct platform_device bfin_sir1_device = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -404,6 +406,9 @@ static struct platform_device i2c_bfin_twi_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#endif
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index f3562b0922af..c9d9473a5ab2 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -1790,6 +1790,8 @@ static struct platform_device bfin_sir1_device = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -1808,6 +1810,9 @@ static struct platform_device i2c_bfin_twi_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#endif
@@ -2361,7 +2366,13 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
},
#endif
};
-
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) \
+|| defined(CONFIG_BFIN_SPORT) || defined(CONFIG_BFIN_SPORT_MODULE)
+unsigned short bfin_sport0_peripherals[] = {
+ P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
+ P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+};
+#endif
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
static struct resource bfin_sport0_uart_resources[] = {
@@ -2382,11 +2393,6 @@ static struct resource bfin_sport0_uart_resources[] = {
},
};
-static unsigned short bfin_sport0_peripherals[] = {
- P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
- P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
-};
-
static struct platform_device bfin_sport0_uart_device = {
.name = "bfin-sport-uart",
.id = 0,
@@ -2432,7 +2438,49 @@ static struct platform_device bfin_sport1_uart_device = {
};
#endif
#endif
-
+#if defined(CONFIG_BFIN_SPORT) || defined(CONFIG_BFIN_SPORT_MODULE)
+static struct resource bfin_sport0_resources[] = {
+ {
+ .start = SPORT0_TCR1,
+ .end = SPORT0_MRCS3+4,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_SPORT0_RX,
+ .end = IRQ_SPORT0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_SPORT0_TX,
+ .end = IRQ_SPORT0_TX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_SPORT0_ERROR,
+ .end = IRQ_SPORT0_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_SPORT0_TX,
+ .end = CH_SPORT0_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = CH_SPORT0_RX,
+ .end = CH_SPORT0_RX,
+ .flags = IORESOURCE_DMA,
+ },
+};
+static struct platform_device bfin_sport0_device = {
+ .name = "bfin_sport_raw",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sport0_resources),
+ .resource = bfin_sport0_resources,
+ .dev = {
+ .platform_data = &bfin_sport0_peripherals, /* Passed to driver */
+ },
+};
+#endif
#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
#define CF_IDE_NAND_CARD_USE_HDD_INTERFACE
/* #define CF_IDE_NAND_CARD_USE_CF_IN_COMMON_MEMORY_MODE */
@@ -2754,7 +2802,9 @@ static struct platform_device bf5xx_adau1701_device = {
static struct platform_device *stamp_devices[] __initdata = {
&bfin_dpmc,
-
+#if defined(CONFIG_BFIN_SPORT) || defined(CONFIG_BFIN_SPORT_MODULE)
+ &bfin_sport0_device,
+#endif
#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
&bfin_pcmcia_cf_device,
#endif
diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
index 3fb421823857..e285c3675286 100644
--- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
@@ -453,6 +453,8 @@ static struct platform_device bfin_sir1_device = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -471,6 +473,9 @@ static struct platform_device i2c_bfin_twi_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#endif
diff --git a/arch/blackfin/mach-bf537/include/mach/anomaly.h b/arch/blackfin/mach-bf537/include/mach/anomaly.h
index 543cd3fb305e..df9212696397 100644
--- a/arch/blackfin/mach-bf537/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf537/include/mach/anomaly.h
@@ -6,8 +6,7 @@
* DO NOT EDIT THIS FILE
*
* Copyright 2004-2011 Analog Devices Inc.
- * Licensed under the ADI BSD license.
- * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd
+ * Licensed under the Clear BSD license.
*/
/* This file should be up to date with:
diff --git a/arch/blackfin/mach-bf537/include/mach/defBF534.h b/arch/blackfin/mach-bf537/include/mach/defBF534.h
index 4a031dde173f..ef6a98cdfd44 100644
--- a/arch/blackfin/mach-bf537/include/mach/defBF534.h
+++ b/arch/blackfin/mach-bf537/include/mach/defBF534.h
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF534_H
@@ -1403,75 +1403,6 @@
#define ERR_DET 0x4000 /* Error Detected Indicator */
#define ERR_NCOR 0x8000 /* Error Not Corrected Indicator */
-/* ******************** TWO-WIRE INTERFACE (TWI) MASKS ***********************/
-/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y); ) */
-#define CLKLOW(x) ((x) & 0xFF) /* Periods Clock Is Held Low */
-#define CLKHI(y) (((y)&0xFF)<<0x8) /* Periods Before New Clock Low */
-
-/* TWI_PRESCALE Masks */
-#define PRESCALE 0x007F /* SCLKs Per Internal Time Reference (10MHz) */
-#define TWI_ENA 0x0080 /* TWI Enable */
-#define SCCB 0x0200 /* SCCB Compatibility Enable */
-
-/* TWI_SLAVE_CTL Masks */
-#define SEN 0x0001 /* Slave Enable */
-#define SADD_LEN 0x0002 /* Slave Address Length */
-#define STDVAL 0x0004 /* Slave Transmit Data Valid */
-#define NAK 0x0008 /* NAK/ACK* Generated At Conclusion Of Transfer */
-#define GEN 0x0010 /* General Call Address Matching Enabled */
-
-/* TWI_SLAVE_STAT Masks */
-#define SDIR 0x0001 /* Slave Transfer Direction (Transmit/Receive*) */
-#define GCALL 0x0002 /* General Call Indicator */
-
-/* TWI_MASTER_CTL Masks */
-#define MEN 0x0001 /* Master Mode Enable */
-#define MADD_LEN 0x0002 /* Master Address Length */
-#define MDIR 0x0004 /* Master Transmit Direction (RX/TX*) */
-#define FAST 0x0008 /* Use Fast Mode Timing Specs */
-#define STOP 0x0010 /* Issue Stop Condition */
-#define RSTART 0x0020 /* Repeat Start or Stop* At End Of Transfer */
-#define DCNT 0x3FC0 /* Data Bytes To Transfer */
-#define SDAOVR 0x4000 /* Serial Data Override */
-#define SCLOVR 0x8000 /* Serial Clock Override */
-
-/* TWI_MASTER_STAT Masks */
-#define MPROG 0x0001 /* Master Transfer In Progress */
-#define LOSTARB 0x0002 /* Lost Arbitration Indicator (Xfer Aborted) */
-#define ANAK 0x0004 /* Address Not Acknowledged */
-#define DNAK 0x0008 /* Data Not Acknowledged */
-#define BUFRDERR 0x0010 /* Buffer Read Error */
-#define BUFWRERR 0x0020 /* Buffer Write Error */
-#define SDASEN 0x0040 /* Serial Data Sense */
-#define SCLSEN 0x0080 /* Serial Clock Sense */
-#define BUSBUSY 0x0100 /* Bus Busy Indicator */
-
-/* TWI_INT_SRC and TWI_INT_ENABLE Masks */
-#define SINIT 0x0001 /* Slave Transfer Initiated */
-#define SCOMP 0x0002 /* Slave Transfer Complete */
-#define SERR 0x0004 /* Slave Transfer Error */
-#define SOVF 0x0008 /* Slave Overflow */
-#define MCOMP 0x0010 /* Master Transfer Complete */
-#define MERR 0x0020 /* Master Transfer Error */
-#define XMTSERV 0x0040 /* Transmit FIFO Service */
-#define RCVSERV 0x0080 /* Receive FIFO Service */
-
-/* TWI_FIFO_CTRL Masks */
-#define XMTFLUSH 0x0001 /* Transmit Buffer Flush */
-#define RCVFLUSH 0x0002 /* Receive Buffer Flush */
-#define XMTINTLEN 0x0004 /* Transmit Buffer Interrupt Length */
-#define RCVINTLEN 0x0008 /* Receive Buffer Interrupt Length */
-
-/* TWI_FIFO_STAT Masks */
-#define XMTSTAT 0x0003 /* Transmit FIFO Status */
-#define XMT_EMPTY 0x0000 /* Transmit FIFO Empty */
-#define XMT_HALF 0x0001 /* Transmit FIFO Has 1 Byte To Write */
-#define XMT_FULL 0x0003 /* Transmit FIFO Full (2 Bytes To Write) */
-
-#define RCVSTAT 0x000C /* Receive FIFO Status */
-#define RCV_EMPTY 0x0000 /* Receive FIFO Empty */
-#define RCV_HALF 0x0004 /* Receive FIFO Has 1 Byte To Read */
-#define RCV_FULL 0x000C /* Receive FIFO Full (2 Bytes To Read) */
/* ******************* PIN CONTROL REGISTER MASKS ************************/
/* PORT_MUX Masks */
diff --git a/arch/blackfin/mach-bf537/include/mach/defBF537.h b/arch/blackfin/mach-bf537/include/mach/defBF537.h
index 3d471d752684..e10332c9f660 100644
--- a/arch/blackfin/mach-bf537/include/mach/defBF537.h
+++ b/arch/blackfin/mach-bf537/include/mach/defBF537.h
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF537_H
diff --git a/arch/blackfin/mach-bf538/boards/ezkit.c b/arch/blackfin/mach-bf538/boards/ezkit.c
index 85038f54354d..a4fce0370c1d 100644
--- a/arch/blackfin/mach-bf538/boards/ezkit.c
+++ b/arch/blackfin/mach-bf538/boards/ezkit.c
@@ -718,6 +718,8 @@ static struct platform_device bf538_spi_master2 = {
};
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -736,9 +738,13 @@ static struct platform_device i2c_bfin_twi0_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
-#if !defined(CONFIG_BF542) /* The BF542 only has 1 TWI */
+static const u16 bfin_twi1_pins[] = {P_TWI1_SCL, P_TWI1_SDA, 0};
+
static struct resource bfin_twi1_resource[] = {
[0] = {
.start = TWI1_REGBASE,
diff --git a/arch/blackfin/mach-bf538/include/mach/anomaly.h b/arch/blackfin/mach-bf538/include/mach/anomaly.h
index b6ca99788710..318d922d11d4 100644
--- a/arch/blackfin/mach-bf538/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf538/include/mach/anomaly.h
@@ -6,8 +6,7 @@
* DO NOT EDIT THIS FILE
*
* Copyright 2004-2011 Analog Devices Inc.
- * Licensed under the ADI BSD license.
- * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd
+ * Licensed under the Clear BSD license.
*/
/* This file should be up to date with:
diff --git a/arch/blackfin/mach-bf538/include/mach/defBF538.h b/arch/blackfin/mach-bf538/include/mach/defBF538.h
index d27f81d6c4b1..876a77028001 100644
--- a/arch/blackfin/mach-bf538/include/mach/defBF538.h
+++ b/arch/blackfin/mach-bf538/include/mach/defBF538.h
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF538_H
@@ -1746,80 +1746,4 @@
#define SDEASE 0x00000010 /* SDRAM EAB sticky error status - W1C */
#define BGSTAT 0x00000020 /* Bus granted */
-
-/* ******************** TWO-WIRE INTERFACE (TWIx) MASKS ***********************/
-/* TWIx_CLKDIV Macros (Use: *pTWIx_CLKDIV = CLKLOW(x)|CLKHI(y); ) */
-#ifdef _MISRA_RULES
-#define CLKLOW(x) ((x) & 0xFFu) /* Periods Clock Is Held Low */
-#define CLKHI(y) (((y)&0xFFu)<<0x8) /* Periods Before New Clock Low */
-#else
-#define CLKLOW(x) ((x) & 0xFF) /* Periods Clock Is Held Low */
-#define CLKHI(y) (((y)&0xFF)<<0x8) /* Periods Before New Clock Low */
-#endif /* _MISRA_RULES */
-
-/* TWIx_PRESCALE Masks */
-#define PRESCALE 0x007F /* SCLKs Per Internal Time Reference (10MHz) */
-#define TWI_ENA 0x0080 /* TWI Enable */
-#define SCCB 0x0200 /* SCCB Compatibility Enable */
-
-/* TWIx_SLAVE_CTRL Masks */
-#define SEN 0x0001 /* Slave Enable */
-#define SADD_LEN 0x0002 /* Slave Address Length */
-#define STDVAL 0x0004 /* Slave Transmit Data Valid */
-#define NAK 0x0008 /* NAK/ACK* Generated At Conclusion Of Transfer */
-#define GEN 0x0010 /* General Call Adrress Matching Enabled */
-
-/* TWIx_SLAVE_STAT Masks */
-#define SDIR 0x0001 /* Slave Transfer Direction (Transmit/Receive*) */
-#define GCALL 0x0002 /* General Call Indicator */
-
-/* TWIx_MASTER_CTRL Masks */
-#define MEN 0x0001 /* Master Mode Enable */
-#define MADD_LEN 0x0002 /* Master Address Length */
-#define MDIR 0x0004 /* Master Transmit Direction (RX/TX*) */
-#define FAST 0x0008 /* Use Fast Mode Timing Specs */
-#define STOP 0x0010 /* Issue Stop Condition */
-#define RSTART 0x0020 /* Repeat Start or Stop* At End Of Transfer */
-#define DCNT 0x3FC0 /* Data Bytes To Transfer */
-#define SDAOVR 0x4000 /* Serial Data Override */
-#define SCLOVR 0x8000 /* Serial Clock Override */
-
-/* TWIx_MASTER_STAT Masks */
-#define MPROG 0x0001 /* Master Transfer In Progress */
-#define LOSTARB 0x0002 /* Lost Arbitration Indicator (Xfer Aborted) */
-#define ANAK 0x0004 /* Address Not Acknowledged */
-#define DNAK 0x0008 /* Data Not Acknowledged */
-#define BUFRDERR 0x0010 /* Buffer Read Error */
-#define BUFWRERR 0x0020 /* Buffer Write Error */
-#define SDASEN 0x0040 /* Serial Data Sense */
-#define SCLSEN 0x0080 /* Serial Clock Sense */
-#define BUSBUSY 0x0100 /* Bus Busy Indicator */
-
-/* TWIx_INT_SRC and TWIx_INT_ENABLE Masks */
-#define SINIT 0x0001 /* Slave Transfer Initiated */
-#define SCOMP 0x0002 /* Slave Transfer Complete */
-#define SERR 0x0004 /* Slave Transfer Error */
-#define SOVF 0x0008 /* Slave Overflow */
-#define MCOMP 0x0010 /* Master Transfer Complete */
-#define MERR 0x0020 /* Master Transfer Error */
-#define XMTSERV 0x0040 /* Transmit FIFO Service */
-#define RCVSERV 0x0080 /* Receive FIFO Service */
-
-/* TWIx_FIFO_CTL Masks */
-#define XMTFLUSH 0x0001 /* Transmit Buffer Flush */
-#define RCVFLUSH 0x0002 /* Receive Buffer Flush */
-#define XMTINTLEN 0x0004 /* Transmit Buffer Interrupt Length */
-#define RCVINTLEN 0x0008 /* Receive Buffer Interrupt Length */
-
-/* TWIx_FIFO_STAT Masks */
-#define XMTSTAT 0x0003 /* Transmit FIFO Status */
-#define XMT_EMPTY 0x0000 /* Transmit FIFO Empty */
-#define XMT_HALF 0x0001 /* Transmit FIFO Has 1 Byte To Write */
-#define XMT_FULL 0x0003 /* Transmit FIFO Full (2 Bytes To Write) */
-
-#define RCVSTAT 0x000C /* Receive FIFO Status */
-#define RCV_EMPTY 0x0000 /* Receive FIFO Empty */
-#define RCV_HALF 0x0004 /* Receive FIFO Has 1 Byte To Read */
-#define RCV_FULL 0x000C /* Receive FIFO Full (2 Bytes To Read) */
-
#endif
diff --git a/arch/blackfin/mach-bf538/include/mach/defBF539.h b/arch/blackfin/mach-bf538/include/mach/defBF539.h
index 8100bcd01a0d..199e871634b4 100644
--- a/arch/blackfin/mach-bf538/include/mach/defBF539.h
+++ b/arch/blackfin/mach-bf538/include/mach/defBF539.h
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF539_H
diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c
index 68af594db48e..e92543362f35 100644
--- a/arch/blackfin/mach-bf548/boards/cm_bf548.c
+++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c
@@ -1007,6 +1007,8 @@ static struct platform_device bf54x_spi_master1 = {
#endif /* spi master and devices */
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -1025,9 +1027,14 @@ static struct platform_device i2c_bfin_twi0_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#if !defined(CONFIG_BF542) /* The BF542 only has 1 TWI */
+static const u16 bfin_twi1_pins[] = {P_TWI1_SCL, P_TWI1_SDA, 0};
+
static struct resource bfin_twi1_resource[] = {
[0] = {
.start = TWI1_REGBASE,
@@ -1046,6 +1053,9 @@ static struct platform_device i2c_bfin_twi1_device = {
.id = 1,
.num_resources = ARRAY_SIZE(bfin_twi1_resource),
.resource = bfin_twi1_resource,
+ .dev = {
+ .platform_data = &bfin_twi1_pins,
+ },
};
#endif
#endif
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
index 4cadaf8d0b56..3bd75bae750d 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -165,6 +165,7 @@ static struct bfin_rotary_platform_data bfin_rotary_data = {
.rotary_button_key = KEY_ENTER,
.debounce = 10, /* 0..17 */
.mode = ROT_QUAD_ENC | ROT_DEBE,
+ .pm_wakeup = 1,
};
static struct resource bfin_rotary_resources[] = {
@@ -1251,6 +1252,8 @@ static struct platform_device bfin_capture_device = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
static struct resource bfin_twi0_resource[] = {
[0] = {
.start = TWI0_REGBASE,
@@ -1269,9 +1272,14 @@ static struct platform_device i2c_bfin_twi0_device = {
.id = 0,
.num_resources = ARRAY_SIZE(bfin_twi0_resource),
.resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
};
#if !defined(CONFIG_BF542) /* The BF542 only has 1 TWI */
+static const u16 bfin_twi1_pins[] = {P_TWI1_SCL, P_TWI1_SDA, 0};
+
static struct resource bfin_twi1_resource[] = {
[0] = {
.start = TWI1_REGBASE,
@@ -1290,6 +1298,9 @@ static struct platform_device i2c_bfin_twi1_device = {
.id = 1,
.num_resources = ARRAY_SIZE(bfin_twi1_resource),
.resource = bfin_twi1_resource,
+ .dev = {
+ .platform_data = &bfin_twi1_pins,
+ },
};
#endif
#endif
diff --git a/arch/blackfin/mach-bf548/include/mach/anomaly.h b/arch/blackfin/mach-bf548/include/mach/anomaly.h
index ac96ee83b00e..5b711d85b90b 100644
--- a/arch/blackfin/mach-bf548/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf548/include/mach/anomaly.h
@@ -6,8 +6,7 @@
* DO NOT EDIT THIS FILE
*
* Copyright 2004-2011 Analog Devices Inc.
- * Licensed under the ADI BSD license.
- * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd
+ * Licensed under the Clear BSD license.
*/
/* This file should be up to date with:
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF542.h b/arch/blackfin/mach-bf548/include/mach/defBF542.h
index 629bf216e2b5..51161575a163 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF542.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF542.h
@@ -1,7 +1,7 @@
/*
* Copyright 2007-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF542_H
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF544.h b/arch/blackfin/mach-bf548/include/mach/defBF544.h
index bcccab36629c..329b2c58228b 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF544.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF544.h
@@ -1,7 +1,7 @@
/*
* Copyright 2007-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF544_H
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF547.h b/arch/blackfin/mach-bf548/include/mach/defBF547.h
index 1fa41ec03f31..e18de212ba1a 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF547.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF547.h
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF547_H
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF548.h b/arch/blackfin/mach-bf548/include/mach/defBF548.h
index 3c7f1b69349e..27f29481e283 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF548.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF548.h
@@ -1,7 +1,7 @@
/*
* Copyright 2007-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF548_H
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF549.h b/arch/blackfin/mach-bf548/include/mach/defBF549.h
index 9a45cb6b30da..ac569fc12972 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF549.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF549.h
@@ -1,7 +1,7 @@
/*
* Copyright 2007-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF549_H
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h b/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
index 0867c2bedb43..8f6e1925779d 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
@@ -1,7 +1,7 @@
/*
* Copyright 2007-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF54X_H
@@ -2062,115 +2062,6 @@
#define LOW_EVEN 0xff0000 /* Lower Limit for Even Bytes (Luma) */
#define HIGH_EVEN 0xff000000 /* Upper Limit for Even Bytes (Luma) */
-/* ************************************************ */
-/* The TWI bit masks fields are from the ADSP-BF538 */
-/* and they have not been verified as the final */
-/* ones for the Moab processors ... bz 1/19/2007 */
-/* ************************************************ */
-
-/* Bit masks for TWIx_CONTROL */
-
-#define PRESCALE 0x7f /* Prescale Value */
-#define TWI_ENA 0x80 /* TWI Enable */
-#define SCCB 0x200 /* Serial Camera Control Bus */
-
-/* Bit maskes for TWIx_CLKDIV */
-
-#define CLKLOW 0xff /* Clock Low */
-#define CLKHI 0xff00 /* Clock High */
-
-/* Bit maskes for TWIx_SLAVE_CTL */
-
-#define SEN 0x1 /* Slave Enable */
-#define STDVAL 0x4 /* Slave Transmit Data Valid */
-#define NAK 0x8 /* Not Acknowledge */
-#define GEN 0x10 /* General Call Enable */
-
-/* Bit maskes for TWIx_SLAVE_ADDR */
-
-#define SADDR 0x7f /* Slave Mode Address */
-
-/* Bit maskes for TWIx_SLAVE_STAT */
-
-#define SDIR 0x1 /* Slave Transfer Direction */
-#define GCALL 0x2 /* General Call */
-
-/* Bit maskes for TWIx_MASTER_CTL */
-
-#define MEN 0x1 /* Master Mode Enable */
-#define MDIR 0x4 /* Master Transfer Direction */
-#define FAST 0x8 /* Fast Mode */
-#define STOP 0x10 /* Issue Stop Condition */
-#define RSTART 0x20 /* Repeat Start */
-#define DCNT 0x3fc0 /* Data Transfer Count */
-#define SDAOVR 0x4000 /* Serial Data Override */
-#define SCLOVR 0x8000 /* Serial Clock Override */
-
-/* Bit maskes for TWIx_MASTER_ADDR */
-
-#define MADDR 0x7f /* Master Mode Address */
-
-/* Bit maskes for TWIx_MASTER_STAT */
-
-#define MPROG 0x1 /* Master Transfer in Progress */
-#define LOSTARB 0x2 /* Lost Arbitration */
-#define ANAK 0x4 /* Address Not Acknowledged */
-#define DNAK 0x8 /* Data Not Acknowledged */
-#define BUFRDERR 0x10 /* Buffer Read Error */
-#define BUFWRERR 0x20 /* Buffer Write Error */
-#define SDASEN 0x40 /* Serial Data Sense */
-#define SCLSEN 0x80 /* Serial Clock Sense */
-#define BUSBUSY 0x100 /* Bus Busy */
-
-/* Bit maskes for TWIx_FIFO_CTL */
-
-#define XMTFLUSH 0x1 /* Transmit Buffer Flush */
-#define RCVFLUSH 0x2 /* Receive Buffer Flush */
-#define XMTINTLEN 0x4 /* Transmit Buffer Interrupt Length */
-#define RCVINTLEN 0x8 /* Receive Buffer Interrupt Length */
-
-/* Bit maskes for TWIx_FIFO_STAT */
-
-#define XMTSTAT 0x3 /* Transmit FIFO Status */
-#define RCVSTAT 0xc /* Receive FIFO Status */
-
-/* Bit maskes for TWIx_INT_MASK */
-
-#define SINITM 0x1 /* Slave Transfer Initiated Interrupt Mask */
-#define SCOMPM 0x2 /* Slave Transfer Complete Interrupt Mask */
-#define SERRM 0x4 /* Slave Transfer Error Interrupt Mask */
-#define SOVFM 0x8 /* Slave Overflow Interrupt Mask */
-#define MCOMPM 0x10 /* Master Transfer Complete Interrupt Mask */
-#define MERRM 0x20 /* Master Transfer Error Interrupt Mask */
-#define XMTSERVM 0x40 /* Transmit FIFO Service Interrupt Mask */
-#define RCVSERVM 0x80 /* Receive FIFO Service Interrupt Mask */
-
-/* Bit maskes for TWIx_INT_STAT */
-
-#define SINIT 0x1 /* Slave Transfer Initiated */
-#define SCOMP 0x2 /* Slave Transfer Complete */
-#define SERR 0x4 /* Slave Transfer Error */
-#define SOVF 0x8 /* Slave Overflow */
-#define MCOMP 0x10 /* Master Transfer Complete */
-#define MERR 0x20 /* Master Transfer Error */
-#define XMTSERV 0x40 /* Transmit FIFO Service */
-#define RCVSERV 0x80 /* Receive FIFO Service */
-
-/* Bit maskes for TWIx_XMT_DATA8 */
-
-#define XMTDATA8 0xff /* Transmit FIFO 8-Bit Data */
-
-/* Bit maskes for TWIx_XMT_DATA16 */
-
-#define XMTDATA16 0xffff /* Transmit FIFO 16-Bit Data */
-
-/* Bit maskes for TWIx_RCV_DATA8 */
-
-#define RCVDATA8 0xff /* Receive FIFO 8-Bit Data */
-
-/* Bit maskes for TWIx_RCV_DATA16 */
-
-#define RCVDATA16 0xffff /* Receive FIFO 16-Bit Data */
/* ******************************************* */
/* MULTI BIT MACRO ENUMERATIONS */
diff --git a/arch/blackfin/mach-bf561/include/mach/anomaly.h b/arch/blackfin/mach-bf561/include/mach/anomaly.h
index 836baeed303a..72476ff50335 100644
--- a/arch/blackfin/mach-bf561/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf561/include/mach/anomaly.h
@@ -6,8 +6,7 @@
* DO NOT EDIT THIS FILE
*
* Copyright 2004-2011 Analog Devices Inc.
- * Licensed under the ADI BSD license.
- * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd
+ * Licensed under the Clear BSD license.
*/
/* This file should be up to date with:
diff --git a/arch/blackfin/mach-bf561/include/mach/defBF561.h b/arch/blackfin/mach-bf561/include/mach/defBF561.h
index 5f0ac5a77a37..9f21f768c63a 100644
--- a/arch/blackfin/mach-bf561/include/mach/defBF561.h
+++ b/arch/blackfin/mach-bf561/include/mach/defBF561.h
@@ -1,7 +1,7 @@
/*
* Copyright 2005-2010 Analog Devices Inc.
*
- * Licensed under the ADI BSD license or the GPL-2 (or later)
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
*/
#ifndef _DEF_BF561_H
diff --git a/arch/blackfin/mach-bf609/Kconfig b/arch/blackfin/mach-bf609/Kconfig
new file mode 100644
index 000000000000..2cb727243778
--- /dev/null
+++ b/arch/blackfin/mach-bf609/Kconfig
@@ -0,0 +1,56 @@
+config BF60x
+ def_bool y
+ depends on (BF609)
+ select IRQ_PREFLOW_FASTEOI
+
+if (BF60x)
+
+source "arch/blackfin/mach-bf609/boards/Kconfig"
+
+menu "BF609 Specific Configuration"
+
+comment "Pin Interrupt to Port Assignment"
+menu "Assignment"
+
+config PINTx_REASSIGN
+ bool "Reprogram PINT Assignment"
+ default y
+ help
+ The interrupt assignment registers controls the pin-to-interrupt
+ assignment in a byte-wide manner. Each option allows you to select
+ a set of pins (High/Low Byte) of an specific Port being mapped
+ to one of the four PIN Interrupts IRQ_PINTx.
+
+ You shouldn't change any of these unless you know exactly what you're doing.
+ Please consult the Blackfin BF60x Processor Hardware Reference Manual.
+
+config PINT0_ASSIGN
+ hex "PINT0_ASSIGN"
+ depends on PINTx_REASSIGN
+ default 0x00000101
+config PINT1_ASSIGN
+ hex "PINT1_ASSIGN"
+ depends on PINTx_REASSIGN
+ default 0x00000101
+config PINT2_ASSIGN
+ hex "PINT2_ASSIGN"
+ depends on PINTx_REASSIGN
+ default 0x00000101
+config PINT3_ASSIGN
+ hex "PINT3_ASSIGN"
+ depends on PINTx_REASSIGN
+ default 0x00000101
+config PINT4_ASSIGN
+ hex "PINT3_ASSIGN"
+ depends on PINTx_REASSIGN
+ default 0x00000101
+config PINT5_ASSIGN
+ hex "PINT3_ASSIGN"
+ depends on PINTx_REASSIGN
+ default 0x00000101
+
+endmenu
+
+endmenu
+
+endif
diff --git a/arch/blackfin/mach-bf609/Makefile b/arch/blackfin/mach-bf609/Makefile
new file mode 100644
index 000000000000..2a27f8174543
--- /dev/null
+++ b/arch/blackfin/mach-bf609/Makefile
@@ -0,0 +1,6 @@
+#
+# arch/blackfin/mach-bf609/Makefile
+#
+
+obj-y := dma.o clock.o
+obj-$(CONFIG_PM) += pm.o hibernate.o
diff --git a/arch/blackfin/mach-bf609/boards/Kconfig b/arch/blackfin/mach-bf609/boards/Kconfig
new file mode 100644
index 000000000000..30e8b6b0d2ed
--- /dev/null
+++ b/arch/blackfin/mach-bf609/boards/Kconfig
@@ -0,0 +1,12 @@
+choice
+ prompt "System type"
+ default BFIN609_EZKIT
+ help
+ Select your board!
+
+config BFIN609_EZKIT
+ bool "BF609-EZKIT"
+ help
+ BFIN609-EZKIT board support.
+
+endchoice
diff --git a/arch/blackfin/mach-bf609/boards/Makefile b/arch/blackfin/mach-bf609/boards/Makefile
new file mode 100644
index 000000000000..11f98b0882ea
--- /dev/null
+++ b/arch/blackfin/mach-bf609/boards/Makefile
@@ -0,0 +1,5 @@
+#
+# arch/blackfin/mach-bf609/boards/Makefile
+#
+
+obj-$(CONFIG_BFIN609_EZKIT) += ezkit.o
diff --git a/arch/blackfin/mach-bf609/boards/ezkit.c b/arch/blackfin/mach-bf609/boards/ezkit.c
new file mode 100644
index 000000000000..ac64f47217c1
--- /dev/null
+++ b/arch/blackfin/mach-bf609/boards/ezkit.c
@@ -0,0 +1,1340 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ * 2005 National ICT Australia (NICTA)
+ * Aidan Williams <aidan@nicta.com.au>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/irq.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/usb/musb.h>
+#include <asm/bfin6xx_spi.h>
+#include <asm/dma.h>
+#include <asm/gpio.h>
+#include <asm/nand.h>
+#include <asm/dpmc.h>
+#include <asm/portmux.h>
+#include <asm/bfin_sdh.h>
+#include <linux/input.h>
+#include <linux/spi/ad7877.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "ADI BF609-EZKIT";
+
+/*
+ * Driver needs to know address, irq and flag pin.
+ */
+
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+#include <linux/usb/isp1760.h>
+static struct resource bfin_isp1760_resources[] = {
+ [0] = {
+ .start = 0x2C0C0000,
+ .end = 0x2C0C0000 + 0xfffff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_PG7,
+ .end = IRQ_PG7,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct isp1760_platform_data isp1760_priv = {
+ .is_isp1761 = 0,
+ .bus_width_16 = 1,
+ .port1_otg = 0,
+ .analog_oc = 0,
+ .dack_polarity_high = 0,
+ .dreq_polarity_high = 0,
+};
+
+static struct platform_device bfin_isp1760_device = {
+ .name = "isp1760",
+ .id = 0,
+ .dev = {
+ .platform_data = &isp1760_priv,
+ },
+ .num_resources = ARRAY_SIZE(bfin_isp1760_resources),
+ .resource = bfin_isp1760_resources,
+};
+#endif
+
+#if defined(CONFIG_INPUT_BFIN_ROTARY) || defined(CONFIG_INPUT_BFIN_ROTARY_MODULE)
+#include <asm/bfin_rotary.h>
+
+static struct bfin_rotary_platform_data bfin_rotary_data = {
+ /*.rotary_up_key = KEY_UP,*/
+ /*.rotary_down_key = KEY_DOWN,*/
+ .rotary_rel_code = REL_WHEEL,
+ .rotary_button_key = KEY_ENTER,
+ .debounce = 10, /* 0..17 */
+ .mode = ROT_QUAD_ENC | ROT_DEBE,
+};
+
+static struct resource bfin_rotary_resources[] = {
+ {
+ .start = IRQ_CNT,
+ .end = IRQ_CNT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_rotary_device = {
+ .name = "bfin-rotary",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(bfin_rotary_resources),
+ .resource = bfin_rotary_resources,
+ .dev = {
+ .platform_data = &bfin_rotary_data,
+ },
+};
+#endif
+
+#if defined(CONFIG_STMMAC_ETH) || defined(CONFIG_STMMAC_ETH_MODULE)
+#include <linux/stmmac.h>
+
+static unsigned short pins[] = P_RMII0;
+
+static struct stmmac_mdio_bus_data phy_private_data = {
+ .bus_id = 0,
+ .phy_mask = 1,
+};
+
+static struct plat_stmmacenet_data eth_private_data = {
+ .bus_id = 0,
+ .enh_desc = 1,
+ .phy_addr = 1,
+ .mdio_bus_data = &phy_private_data,
+};
+
+static struct platform_device bfin_eth_device = {
+ .name = "stmmaceth",
+ .id = 0,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = EMAC0_MACCFG,
+ .end = EMAC0_MACCFG + 0x1274,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "macirq",
+ .start = IRQ_EMAC0_STAT,
+ .end = IRQ_EMAC0_STAT,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ .dev = {
+ .power.can_wakeup = 1,
+ .platform_data = &eth_private_data,
+ }
+};
+#endif
+
+#if defined(CONFIG_INPUT_ADXL34X) || defined(CONFIG_INPUT_ADXL34X_MODULE)
+#include <linux/input/adxl34x.h>
+static const struct adxl34x_platform_data adxl34x_info = {
+ .x_axis_offset = 0,
+ .y_axis_offset = 0,
+ .z_axis_offset = 0,
+ .tap_threshold = 0x31,
+ .tap_duration = 0x10,
+ .tap_latency = 0x60,
+ .tap_window = 0xF0,
+ .tap_axis_control = ADXL_TAP_X_EN | ADXL_TAP_Y_EN | ADXL_TAP_Z_EN,
+ .act_axis_control = 0xFF,
+ .activity_threshold = 5,
+ .inactivity_threshold = 3,
+ .inactivity_time = 4,
+ .free_fall_threshold = 0x7,
+ .free_fall_time = 0x20,
+ .data_rate = 0x8,
+ .data_range = ADXL_FULL_RES,
+
+ .ev_type = EV_ABS,
+ .ev_code_x = ABS_X, /* EV_REL */
+ .ev_code_y = ABS_Y, /* EV_REL */
+ .ev_code_z = ABS_Z, /* EV_REL */
+
+ .ev_code_tap = {BTN_TOUCH, BTN_TOUCH, BTN_TOUCH}, /* EV_KEY x,y,z */
+
+/* .ev_code_ff = KEY_F,*/ /* EV_KEY */
+/* .ev_code_act_inactivity = KEY_A,*/ /* EV_KEY */
+ .power_mode = ADXL_AUTO_SLEEP | ADXL_LINK,
+ .fifo_mode = ADXL_FIFO_STREAM,
+ .orientation_enable = ADXL_EN_ORIENTATION_3D,
+ .deadzone_angle = ADXL_DEADZONE_ANGLE_10p8,
+ .divisor_length = ADXL_LP_FILTER_DIVISOR_16,
+ /* EV_KEY {+Z, +Y, +X, -X, -Y, -Z} */
+ .ev_codes_orient_3d = {BTN_Z, BTN_Y, BTN_X, BTN_A, BTN_B, BTN_C},
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+ .name = "rtc-bfin",
+ .id = -1,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+static struct resource bfin_uart0_resources[] = {
+ {
+ .start = UART0_REVID,
+ .end = UART0_RXDIV+4,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART0_TX,
+ .end = IRQ_UART0_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_UART0_STAT,
+ .end = IRQ_UART0_STAT,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_TX,
+ .end = CH_UART0_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX,
+ .flags = IORESOURCE_DMA,
+ },
+#ifdef CONFIG_BFIN_UART0_CTSRTS
+ { /* CTS pin -- 0 means not supported */
+ .start = GPIO_PD10,
+ .end = GPIO_PD10,
+ .flags = IORESOURCE_IO,
+ },
+ { /* RTS pin -- 0 means not supported */
+ .start = GPIO_PD9,
+ .end = GPIO_PD9,
+ .flags = IORESOURCE_IO,
+ },
+#endif
+};
+
+static unsigned short bfin_uart0_peripherals[] = {
+ P_UART0_TX, P_UART0_RX,
+#ifdef CONFIG_BFIN_UART0_CTSRTS
+ P_UART0_RTS, P_UART0_CTS,
+#endif
+ 0
+};
+
+static struct platform_device bfin_uart0_device = {
+ .name = "bfin-uart",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_uart0_resources),
+ .resource = bfin_uart0_resources,
+ .dev = {
+ .platform_data = &bfin_uart0_peripherals, /* Passed to driver */
+ },
+};
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+static struct resource bfin_uart1_resources[] = {
+ {
+ .start = UART1_REVID,
+ .end = UART1_RXDIV+4,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART1_TX,
+ .end = IRQ_UART1_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_UART1_STAT,
+ .end = IRQ_UART1_STAT,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_TX,
+ .end = CH_UART1_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX,
+ .flags = IORESOURCE_DMA,
+ },
+#ifdef CONFIG_BFIN_UART1_CTSRTS
+ { /* CTS pin -- 0 means not supported */
+ .start = GPIO_PG13,
+ .end = GPIO_PG13,
+ .flags = IORESOURCE_IO,
+ },
+ { /* RTS pin -- 0 means not supported */
+ .start = GPIO_PG10,
+ .end = GPIO_PG10,
+ .flags = IORESOURCE_IO,
+ },
+#endif
+};
+
+static unsigned short bfin_uart1_peripherals[] = {
+ P_UART1_TX, P_UART1_RX,
+#ifdef CONFIG_BFIN_UART1_CTSRTS
+ P_UART1_RTS, P_UART1_CTS,
+#endif
+ 0
+};
+
+static struct platform_device bfin_uart1_device = {
+ .name = "bfin-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_uart1_resources),
+ .resource = bfin_uart1_resources,
+ .dev = {
+ .platform_data = &bfin_uart1_peripherals, /* Passed to driver */
+ },
+};
+#endif
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART0_TX,
+ .end = IRQ_UART0_TX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_TX,
+ .end = CH_UART0_TX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
+#endif
+#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
+ {
+ .start = 0xFFC02000,
+ .end = 0xFFC020FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART1_TX,
+ .end = IRQ_UART1_TX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_TX,
+ .end = CH_UART1_TX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+static struct platform_device bfin_sir1_device = {
+ .name = "bfin_sir",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
+};
+#endif
+#endif
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+static struct resource musb_resources[] = {
+ [0] = {
+ .start = 0xFFCC1000,
+ .end = 0xFFCC1398,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = { /* general IRQ */
+ .start = IRQ_USB_STAT,
+ .end = IRQ_USB_STAT,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ .name = "mc"
+ },
+ [2] = { /* DMA IRQ */
+ .start = IRQ_USB_DMA,
+ .end = IRQ_USB_DMA,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ .name = "dma"
+ },
+};
+
+static struct musb_hdrc_config musb_config = {
+ .multipoint = 1,
+ .dyn_fifo = 0,
+ .dma = 1,
+ .num_eps = 16,
+ .dma_channels = 8,
+ .clkin = 48, /* musb CLKIN in MHZ */
+};
+
+static struct musb_hdrc_platform_data musb_plat = {
+#if defined(CONFIG_USB_MUSB_HDRC) && defined(CONFIG_USB_GADGET_MUSB_HDRC)
+ .mode = MUSB_OTG,
+#elif defined(CONFIG_USB_MUSB_HDRC)
+ .mode = MUSB_HOST,
+#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
+ .mode = MUSB_PERIPHERAL,
+#endif
+ .config = &musb_config,
+};
+
+static u64 musb_dmamask = ~(u32)0;
+
+static struct platform_device musb_device = {
+ .name = "musb-blackfin",
+ .id = 0,
+ .dev = {
+ .dma_mask = &musb_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &musb_plat,
+ },
+ .num_resources = ARRAY_SIZE(musb_resources),
+ .resource = musb_resources,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+static struct resource bfin_sport0_uart_resources[] = {
+ {
+ .start = SPORT0_TCR1,
+ .end = SPORT0_MRCS3+4,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_SPORT0_RX,
+ .end = IRQ_SPORT0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_SPORT0_ERROR,
+ .end = IRQ_SPORT0_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static unsigned short bfin_sport0_peripherals[] = {
+ P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
+ P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
+};
+
+static struct platform_device bfin_sport0_uart_device = {
+ .name = "bfin-sport-uart",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sport0_uart_resources),
+ .resource = bfin_sport0_uart_resources,
+ .dev = {
+ .platform_data = &bfin_sport0_peripherals, /* Passed to driver */
+ },
+};
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+static struct resource bfin_sport1_uart_resources[] = {
+ {
+ .start = SPORT1_TCR1,
+ .end = SPORT1_MRCS3+4,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_SPORT1_RX,
+ .end = IRQ_SPORT1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_SPORT1_ERROR,
+ .end = IRQ_SPORT1_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static unsigned short bfin_sport1_peripherals[] = {
+ P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
+ P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
+};
+
+static struct platform_device bfin_sport1_uart_device = {
+ .name = "bfin-sport-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sport1_uart_resources),
+ .resource = bfin_sport1_uart_resources,
+ .dev = {
+ .platform_data = &bfin_sport1_peripherals, /* Passed to driver */
+ },
+};
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT2_UART
+static struct resource bfin_sport2_uart_resources[] = {
+ {
+ .start = SPORT2_TCR1,
+ .end = SPORT2_MRCS3+4,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_SPORT2_RX,
+ .end = IRQ_SPORT2_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_SPORT2_ERROR,
+ .end = IRQ_SPORT2_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static unsigned short bfin_sport2_peripherals[] = {
+ P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS,
+ P_SPORT2_DRPRI, P_SPORT2_RSCLK, P_SPORT2_DRSEC, P_SPORT2_DTSEC, 0
+};
+
+static struct platform_device bfin_sport2_uart_device = {
+ .name = "bfin-sport-uart",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(bfin_sport2_uart_resources),
+ .resource = bfin_sport2_uart_resources,
+ .dev = {
+ .platform_data = &bfin_sport2_peripherals, /* Passed to driver */
+ },
+};
+#endif
+#endif
+
+#if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
+
+static unsigned short bfin_can0_peripherals[] = {
+ P_CAN0_RX, P_CAN0_TX, 0
+};
+
+static struct resource bfin_can0_resources[] = {
+ {
+ .start = 0xFFC00A00,
+ .end = 0xFFC00FFF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_CAN0_RX,
+ .end = IRQ_CAN0_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_CAN0_TX,
+ .end = IRQ_CAN0_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_CAN0_STAT,
+ .end = IRQ_CAN0_STAT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_can0_device = {
+ .name = "bfin_can",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_can0_resources),
+ .resource = bfin_can0_resources,
+ .dev = {
+ .platform_data = &bfin_can0_peripherals, /* Passed to driver */
+ },
+};
+
+#endif
+
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+static struct mtd_partition partition_info[] = {
+ {
+ .name = "bootloader(nand)",
+ .offset = 0,
+ .size = 0x80000,
+ }, {
+ .name = "linux kernel(nand)",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 4 * 1024 * 1024,
+ },
+ {
+ .name = "file system(nand)",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct bf5xx_nand_platform bfin_nand_platform = {
+ .data_width = NFC_NWIDTH_8,
+ .partitions = partition_info,
+ .nr_partitions = ARRAY_SIZE(partition_info),
+ .rd_dly = 3,
+ .wr_dly = 3,
+};
+
+static struct resource bfin_nand_resources[] = {
+ {
+ .start = 0xFFC03B00,
+ .end = 0xFFC03B4F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = CH_NFC,
+ .end = CH_NFC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_nand_device = {
+ .name = "bfin-nand",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_nand_resources),
+ .resource = bfin_nand_resources,
+ .dev = {
+ .platform_data = &bfin_nand_platform,
+ },
+};
+#endif
+
+#if defined(CONFIG_SDH_BFIN) || defined(CONFIG_SDH_BFIN_MODULE)
+
+static struct bfin_sd_host bfin_sdh_data = {
+ .dma_chan = CH_RSI,
+ .irq_int0 = IRQ_RSI_INT0,
+ .pin_req = {P_RSI_DATA0, P_RSI_DATA1, P_RSI_DATA2, P_RSI_DATA3, P_RSI_CMD, P_RSI_CLK, 0},
+};
+
+static struct platform_device bfin_sdh_device = {
+ .name = "bfin-sdh",
+ .id = 0,
+ .dev = {
+ .platform_data = &bfin_sdh_data,
+ },
+};
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+static struct mtd_partition ezkit_partitions[] = {
+ {
+ .name = "bootloader(nor)",
+ .size = 0x80000,
+ .offset = 0,
+ }, {
+ .name = "linux kernel(nor)",
+ .size = 0x400000,
+ .offset = MTDPART_OFS_APPEND,
+ }, {
+ .name = "file system(nor)",
+ .size = 0x1000000 - 0x80000 - 0x400000,
+ .offset = MTDPART_OFS_APPEND,
+ },
+};
+
+int bf609_nor_flash_init(struct platform_device *dev)
+{
+#define CONFIG_SMC_GCTL_VAL 0x00000010
+ const unsigned short pins[] = {
+ P_A3, P_A4, P_A5, P_A6, P_A7, P_A8, P_A9, P_A10, P_A11, P_A12,
+ P_A13, P_A14, P_A15, P_A16, P_A17, P_A18, P_A19, P_A20, P_A21,
+ P_A22, P_A23, P_A24, P_A25, P_NORCK, 0,
+ };
+
+ peripheral_request_list(pins, "smc0");
+
+ bfin_write32(SMC_GCTL, CONFIG_SMC_GCTL_VAL);
+ bfin_write32(SMC_B0CTL, 0x01002011);
+ bfin_write32(SMC_B0TIM, 0x08170977);
+ bfin_write32(SMC_B0ETIM, 0x00092231);
+ return 0;
+}
+
+static struct physmap_flash_data ezkit_flash_data = {
+ .width = 2,
+ .parts = ezkit_partitions,
+ .init = bf609_nor_flash_init,
+ .nr_parts = ARRAY_SIZE(ezkit_partitions),
+};
+
+static struct resource ezkit_flash_resource = {
+ .start = 0xb0000000,
+ .end = 0xb0ffffff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ezkit_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &ezkit_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &ezkit_flash_resource,
+};
+#endif
+
+#if defined(CONFIG_MTD_M25P80) \
+ || defined(CONFIG_MTD_M25P80_MODULE)
+/* SPI flash chip (w25q32) */
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+ {
+ .name = "bootloader(spi)",
+ .size = 0x00080000,
+ .offset = 0,
+ .mask_flags = MTD_CAP_ROM
+ }, {
+ .name = "linux kernel(spi)",
+ .size = 0x00180000,
+ .offset = MTDPART_OFS_APPEND,
+ }, {
+ .name = "file system(spi)",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+ .name = "m25p80",
+ .parts = bfin_spi_flash_partitions,
+ .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+ .type = "w25q32",
+};
+
+static struct bfin6xx_spi_chip spi_flash_chip_info = {
+ .enable_dma = true, /* use dma transfer with this chip*/
+};
+#endif
+
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin6xx_spi_chip spidev_chip_info = {
+ .enable_dma = true,
+};
+#endif
+
+#if defined(CONFIG_SND_BF6XX_I2S) || defined(CONFIG_SND_BF6XX_I2S_MODULE)
+static struct platform_device bfin_i2s_pcm = {
+ .name = "bfin-i2s-pcm-audio",
+ .id = -1,
+};
+#endif
+
+#if defined(CONFIG_SND_BF6XX_SOC_I2S) || \
+ defined(CONFIG_SND_BF6XX_SOC_I2S_MODULE)
+#include <asm/bfin_sport3.h>
+static struct resource bfin_snd_resources[] = {
+ {
+ .start = SPORT0_CTL_A,
+ .end = SPORT0_CTL_A,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SPORT0_CTL_B,
+ .end = SPORT0_CTL_B,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = CH_SPORT0_TX,
+ .end = CH_SPORT0_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = CH_SPORT0_RX,
+ .end = CH_SPORT0_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = IRQ_SPORT0_TX_STAT,
+ .end = IRQ_SPORT0_TX_STAT,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_SPORT0_RX_STAT,
+ .end = IRQ_SPORT0_RX_STAT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const unsigned short bfin_snd_pin[] = {
+ P_SPORT0_ACLK, P_SPORT0_AFS, P_SPORT0_AD0, P_SPORT0_BCLK,
+ P_SPORT0_BFS, P_SPORT0_BD0, 0,
+};
+
+static struct bfin_snd_platform_data bfin_snd_data = {
+ .pin_req = bfin_snd_pin,
+};
+
+static struct platform_device bfin_i2s = {
+ .name = "bfin-i2s",
+ .num_resources = ARRAY_SIZE(bfin_snd_resources),
+ .resource = bfin_snd_resources,
+ .dev = {
+ .platform_data = &bfin_snd_data,
+ },
+};
+#endif
+
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61) || \
+ defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61_MODULE)
+static struct platform_device adau1761_device = {
+ .name = "bfin-eval-adau1x61",
+};
+#endif
+
+#if defined(CONFIG_SND_SOC_ADAU1761) || defined(CONFIG_SND_SOC_ADAU1761_MODULE)
+#include <sound/adau17x1.h>
+static struct adau1761_platform_data adau1761_info = {
+ .lineout_mode = ADAU1761_OUTPUT_MODE_LINE,
+ .headphone_mode = ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS,
+};
+#endif
+
+#if defined(CONFIG_VIDEO_BLACKFIN_CAPTURE) \
+ || defined(CONFIG_VIDEO_BLACKFIN_CAPTURE_MODULE)
+#include <linux/videodev2.h>
+#include <media/blackfin/bfin_capture.h>
+#include <media/blackfin/ppi.h>
+
+static const unsigned short ppi_req[] = {
+ P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+ P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+ P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+ 0,
+};
+
+static const struct ppi_info ppi_info = {
+ .type = PPI_TYPE_EPPI3,
+ .dma_ch = CH_EPPI0_CH0,
+ .irq_err = IRQ_EPPI0_STAT,
+ .base = (void __iomem *)EPPI0_STAT,
+ .pin_req = ppi_req,
+};
+
+#if defined(CONFIG_VIDEO_VS6624) \
+ || defined(CONFIG_VIDEO_VS6624_MODULE)
+static struct v4l2_input vs6624_inputs[] = {
+ {
+ .index = 0,
+ .name = "Camera",
+ .type = V4L2_INPUT_TYPE_CAMERA,
+ .std = V4L2_STD_UNKNOWN,
+ },
+};
+
+static struct bcap_route vs6624_routes[] = {
+ {
+ .input = 0,
+ .output = 0,
+ },
+};
+
+static const unsigned vs6624_ce_pin = GPIO_PD1;
+
+static struct bfin_capture_config bfin_capture_data = {
+ .card_name = "BF609",
+ .inputs = vs6624_inputs,
+ .num_inputs = ARRAY_SIZE(vs6624_inputs),
+ .routes = vs6624_routes,
+ .i2c_adapter_id = 0,
+ .board_info = {
+ .type = "vs6624",
+ .addr = 0x10,
+ .platform_data = (void *)&vs6624_ce_pin,
+ },
+ .ppi_info = &ppi_info,
+ .ppi_control = (PACK_EN | DLEN_8 | EPPI_CTL_FS1HI_FS2HI
+ | EPPI_CTL_POLC3 | EPPI_CTL_SYNC2 | EPPI_CTL_NON656),
+ .blank_clocks = 8,
+};
+#endif
+
+static struct platform_device bfin_capture_device = {
+ .name = "bfin_capture",
+ .dev = {
+ .platform_data = &bfin_capture_data,
+ },
+};
+#endif
+
+#if defined(CONFIG_BFIN_CRC)
+#define BFIN_CRC_NAME "bfin-crc"
+
+static struct resource bfin_crc0_resources[] = {
+ {
+ .start = REG_CRC0_CTL,
+ .end = REG_CRC0_REVID+4,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_CRC0_DCNTEXP,
+ .end = IRQ_CRC0_DCNTEXP,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_MEM_STREAM0_SRC_CRC0,
+ .end = CH_MEM_STREAM0_SRC_CRC0,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = CH_MEM_STREAM0_DEST_CRC0,
+ .end = CH_MEM_STREAM0_DEST_CRC0,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_crc0_device = {
+ .name = BFIN_CRC_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_crc0_resources),
+ .resource = bfin_crc0_resources,
+};
+
+static struct resource bfin_crc1_resources[] = {
+ {
+ .start = REG_CRC1_CTL,
+ .end = REG_CRC1_REVID+4,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_CRC1_DCNTEXP,
+ .end = IRQ_CRC1_DCNTEXP,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_MEM_STREAM1_SRC_CRC1,
+ .end = CH_MEM_STREAM1_SRC_CRC1,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = CH_MEM_STREAM1_DEST_CRC1,
+ .end = CH_MEM_STREAM1_DEST_CRC1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_crc1_device = {
+ .name = BFIN_CRC_NAME,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_crc1_resources),
+ .resource = bfin_crc1_resources,
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+static const struct ad7877_platform_data bfin_ad7877_ts_info = {
+ .model = 7877,
+ .vref_delay_usecs = 50, /* internal, no capacitor */
+ .x_plate_ohms = 419,
+ .y_plate_ohms = 486,
+ .pressure_max = 1000,
+ .pressure_min = 0,
+ .stopacq_polarity = 1,
+ .first_conversion_delay = 3,
+ .acquisition_time = 1,
+ .averaging = 1,
+ .pen_down_acc_interval = 1,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) \
+ || defined(CONFIG_MTD_M25P80_MODULE)
+ {
+ /* the modalias must be the same as spi device driver name */
+ .modalias = "m25p80", /* Name of spi_driver for this device */
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0, /* Framework bus number */
+ .chip_select = 1, /* SPI_SSEL1*/
+ .platform_data = &bfin_spi_flash_data,
+ .controller_data = &spi_flash_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+ {
+ .modalias = "ad7877",
+ .platform_data = &bfin_ad7877_ts_info,
+ .irq = IRQ_PB4, /* old boards (<=Rev 1.3) use IRQ_PJ11 */
+ .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 2,
+ },
+#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &spidev_chip_info,
+ },
+#endif
+#if defined(CONFIG_INPUT_ADXL34X_SPI) || defined(CONFIG_INPUT_ADXL34X_SPI_MODULE)
+ {
+ .modalias = "adxl34x",
+ .platform_data = &adxl34x_info,
+ .irq = IRQ_PC5,
+ .max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 2,
+ .mode = SPI_MODE_3,
+ },
+#endif
+};
+#if defined(CONFIG_SPI_BFIN6XX) || defined(CONFIG_SPI_BFIN6XX_MODULE)
+/* SPI (0) */
+static struct resource bfin_spi0_resource[] = {
+ {
+ .start = SPI0_REGBASE,
+ .end = SPI0_REGBASE + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = CH_SPI0_TX,
+ .end = CH_SPI0_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = CH_SPI0_RX,
+ .end = CH_SPI0_RX,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+/* SPI (1) */
+static struct resource bfin_spi1_resource[] = {
+ {
+ .start = SPI1_REGBASE,
+ .end = SPI1_REGBASE + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = CH_SPI1_TX,
+ .end = CH_SPI1_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = CH_SPI1_RX,
+ .end = CH_SPI1_RX,
+ .flags = IORESOURCE_DMA,
+ },
+
+};
+
+/* SPI controller data */
+static struct bfin6xx_spi_master bf60x_spi_master_info0 = {
+ .num_chipselect = 4,
+ .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
+};
+
+static struct platform_device bf60x_spi_master0 = {
+ .name = "bfin-spi",
+ .id = 0, /* Bus number */
+ .num_resources = ARRAY_SIZE(bfin_spi0_resource),
+ .resource = bfin_spi0_resource,
+ .dev = {
+ .platform_data = &bf60x_spi_master_info0, /* Passed to driver */
+ },
+};
+
+static struct bfin6xx_spi_master bf60x_spi_master_info1 = {
+ .num_chipselect = 4,
+ .pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
+};
+
+static struct platform_device bf60x_spi_master1 = {
+ .name = "bfin-spi",
+ .id = 1, /* Bus number */
+ .num_resources = ARRAY_SIZE(bfin_spi1_resource),
+ .resource = bfin_spi1_resource,
+ .dev = {
+ .platform_data = &bf60x_spi_master_info1, /* Passed to driver */
+ },
+};
+#endif /* spi master and devices */
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static const u16 bfin_twi0_pins[] = {P_TWI0_SCL, P_TWI0_SDA, 0};
+
+static struct resource bfin_twi0_resource[] = {
+ [0] = {
+ .start = TWI0_CLKDIV,
+ .end = TWI0_CLKDIV + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TWI0,
+ .end = IRQ_TWI0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c_bfin_twi0_device = {
+ .name = "i2c-bfin-twi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_twi0_resource),
+ .resource = bfin_twi0_resource,
+ .dev = {
+ .platform_data = &bfin_twi0_pins,
+ },
+};
+
+static const u16 bfin_twi1_pins[] = {P_TWI1_SCL, P_TWI1_SDA, 0};
+
+static struct resource bfin_twi1_resource[] = {
+ [0] = {
+ .start = TWI1_CLKDIV,
+ .end = TWI1_CLKDIV + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TWI1,
+ .end = IRQ_TWI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c_bfin_twi1_device = {
+ .name = "i2c-bfin-twi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_twi1_resource),
+ .resource = bfin_twi1_resource,
+ .dev = {
+ .platform_data = &bfin_twi1_pins,
+ },
+};
+#endif
+
+static struct i2c_board_info __initdata bfin_i2c_board_info0[] = {
+#if defined(CONFIG_INPUT_ADXL34X_I2C) || defined(CONFIG_INPUT_ADXL34X_I2C_MODULE)
+ {
+ I2C_BOARD_INFO("adxl34x", 0x53),
+ .irq = IRQ_PC5,
+ .platform_data = (void *)&adxl34x_info,
+ },
+#endif
+#if defined(CONFIG_SND_SOC_ADAU1761) || defined(CONFIG_SND_SOC_ADAU1761_MODULE)
+ {
+ I2C_BOARD_INFO("adau1761", 0x38),
+ .platform_data = (void *)&adau1761_info
+ },
+#endif
+};
+
+static struct i2c_board_info __initdata bfin_i2c_board_info1[] = {
+};
+
+static const unsigned int cclk_vlev_datasheet[] =
+{
+/*
+ * Internal VLEV BF54XSBBC1533
+ ****temporarily using these values until data sheet is updated
+ */
+ VRPAIR(VLEV_085, 150000000),
+ VRPAIR(VLEV_090, 250000000),
+ VRPAIR(VLEV_110, 276000000),
+ VRPAIR(VLEV_115, 301000000),
+ VRPAIR(VLEV_120, 525000000),
+ VRPAIR(VLEV_125, 550000000),
+ VRPAIR(VLEV_130, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+ .tuple_tab = cclk_vlev_datasheet,
+ .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+ .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+ .name = "bfin dpmc",
+ .dev = {
+ .platform_data = &bfin_dmpc_vreg_data,
+ },
+};
+
+static struct platform_device *ezkit_devices[] __initdata = {
+
+ &bfin_dpmc,
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+ &rtc_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ &bfin_uart0_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ &bfin_uart1_device,
+#endif
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
+#endif
+
+#if defined(CONFIG_STMMAC_ETH) || defined(CONFIG_STMMAC_ETH_MODULE)
+ &bfin_eth_device,
+#endif
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+ &musb_device,
+#endif
+
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+ &bfin_isp1760_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+ &bfin_sport0_uart_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+ &bfin_sport1_uart_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT2_UART
+ &bfin_sport2_uart_device,
+#endif
+#endif
+
+#if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
+ &bfin_can0_device,
+#endif
+
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+ &bfin_nand_device,
+#endif
+
+#if defined(CONFIG_SDH_BFIN) || defined(CONFIG_SDH_BFIN_MODULE)
+ &bfin_sdh_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN6XX) || defined(CONFIG_SPI_BFIN6XX_MODULE)
+ &bf60x_spi_master0,
+ &bf60x_spi_master1,
+#endif
+
+#if defined(CONFIG_INPUT_BFIN_ROTARY) || defined(CONFIG_INPUT_BFIN_ROTARY_MODULE)
+ &bfin_rotary_device,
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ &i2c_bfin_twi0_device,
+#if !defined(CONFIG_BF542)
+ &i2c_bfin_twi1_device,
+#endif
+#endif
+
+#if defined(CONFIG_BFIN_CRC)
+ &bfin_crc0_device,
+ &bfin_crc1_device,
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+ &bfin_device_gpiokeys,
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ &ezkit_flash_device,
+#endif
+#if defined(CONFIG_SND_BF6XX_I2S) || defined(CONFIG_SND_BF6XX_I2S_MODULE)
+ &bfin_i2s_pcm,
+#endif
+#if defined(CONFIG_SND_BF6XX_SOC_I2S) || \
+ defined(CONFIG_SND_BF6XX_SOC_I2S_MODULE)
+ &bfin_i2s,
+#endif
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61) || \
+ defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61_MODULE)
+ &adau1761_device,
+#endif
+#if defined(CONFIG_VIDEO_BLACKFIN_CAPTURE) \
+ || defined(CONFIG_VIDEO_BLACKFIN_CAPTURE_MODULE)
+ &bfin_capture_device,
+#endif
+};
+
+static int __init ezkit_init(void)
+{
+ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+
+ i2c_register_board_info(0, bfin_i2c_board_info0,
+ ARRAY_SIZE(bfin_i2c_board_info0));
+ i2c_register_board_info(1, bfin_i2c_board_info1,
+ ARRAY_SIZE(bfin_i2c_board_info1));
+
+#if defined(CONFIG_STMMAC_ETH) || defined(CONFIG_STMMAC_ETH_MODULE)
+ if (!peripheral_request_list(pins, "emac0"))
+ printk(KERN_ERR "%s(): request emac pins failed\n", __func__);
+#endif
+
+ platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
+
+ spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+
+ return 0;
+}
+
+arch_initcall(ezkit_init);
+
+static struct platform_device *ezkit_early_devices[] __initdata = {
+#if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ &bfin_uart0_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ &bfin_uart1_device,
+#endif
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT_CONSOLE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+ &bfin_sport0_uart_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+ &bfin_sport1_uart_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT2_UART
+ &bfin_sport2_uart_device,
+#endif
+#endif
+};
+
+void __init native_machine_early_platform_add_devices(void)
+{
+ printk(KERN_INFO "register early platform devices\n");
+ early_platform_add_devices(ezkit_early_devices,
+ ARRAY_SIZE(ezkit_early_devices));
+}
diff --git a/arch/blackfin/mach-bf609/clock.c b/arch/blackfin/mach-bf609/clock.c
new file mode 100644
index 000000000000..7f8f529693ae
--- /dev/null
+++ b/arch/blackfin/mach-bf609/clock.c
@@ -0,0 +1,390 @@
+#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/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/io.h>
+#include <linux/seq_file.h>
+#include <linux/clkdev.h>
+
+#include <asm/clocks.h>
+
+#define CGU0_CTL_DF (1 << 0)
+
+#define CGU0_CTL_MSEL_SHIFT 8
+#define CGU0_CTL_MSEL_MASK (0x7f << 8)
+
+#define CGU0_STAT_PLLEN (1 << 0)
+#define CGU0_STAT_PLLBP (1 << 1)
+#define CGU0_STAT_PLLLK (1 << 2)
+#define CGU0_STAT_CLKSALGN (1 << 3)
+#define CGU0_STAT_CCBF0 (1 << 4)
+#define CGU0_STAT_CCBF1 (1 << 5)
+#define CGU0_STAT_SCBF0 (1 << 6)
+#define CGU0_STAT_SCBF1 (1 << 7)
+#define CGU0_STAT_DCBF (1 << 8)
+#define CGU0_STAT_OCBF (1 << 9)
+#define CGU0_STAT_ADDRERR (1 << 16)
+#define CGU0_STAT_LWERR (1 << 17)
+#define CGU0_STAT_DIVERR (1 << 18)
+#define CGU0_STAT_WDFMSERR (1 << 19)
+#define CGU0_STAT_WDIVERR (1 << 20)
+#define CGU0_STAT_PLOCKERR (1 << 21)
+
+#define CGU0_DIV_CSEL_SHIFT 0
+#define CGU0_DIV_CSEL_MASK 0x0000001F
+#define CGU0_DIV_S0SEL_SHIFT 5
+#define CGU0_DIV_S0SEL_MASK (0x3 << CGU0_DIV_S0SEL_SHIFT)
+#define CGU0_DIV_SYSSEL_SHIFT 8
+#define CGU0_DIV_SYSSEL_MASK (0x1f << CGU0_DIV_SYSSEL_SHIFT)
+#define CGU0_DIV_S1SEL_SHIFT 13
+#define CGU0_DIV_S1SEL_MASK (0x3 << CGU0_DIV_S1SEL_SHIFT)
+#define CGU0_DIV_DSEL_SHIFT 16
+#define CGU0_DIV_DSEL_MASK (0x1f << CGU0_DIV_DSEL_SHIFT)
+#define CGU0_DIV_OSEL_SHIFT 22
+#define CGU0_DIV_OSEL_MASK (0x7f << CGU0_DIV_OSEL_SHIFT)
+
+#define CLK(_clk, _devname, _conname) \
+ { \
+ .clk = &_clk, \
+ .dev_id = _devname, \
+ .con_id = _conname, \
+ }
+
+#define NEEDS_INITIALIZATION 0x11
+
+static LIST_HEAD(clk_list);
+
+static void clk_reg_write_mask(u32 reg, uint32_t val, uint32_t mask)
+{
+ u32 val2;
+
+ val2 = bfin_read32(reg);
+ val2 &= ~mask;
+ val2 |= val;
+ bfin_write32(reg, val2);
+}
+
+static void clk_reg_set_bits(u32 reg, uint32_t mask)
+{
+ u32 val;
+
+ val = bfin_read32(reg);
+ val |= mask;
+ bfin_write32(reg, val);
+}
+
+static void clk_reg_clear_bits(u32 reg, uint32_t mask)
+{
+ u32 val;
+
+ val = bfin_read32(reg);
+ val &= ~mask;
+ bfin_write32(reg, val);
+}
+
+int wait_for_pll_align(void)
+{
+ int i = 10000;
+ while (i-- && (bfin_read32(CGU0_STAT) & CGU0_STAT_CLKSALGN));
+
+ if (bfin_read32(CGU0_STAT) & CGU0_STAT_CLKSALGN) {
+ printk(KERN_DEBUG "fail to align clk\n");
+ return -1;
+ }
+ return 0;
+}
+
+int clk_enable(struct clk *clk)
+{
+ int ret = -EIO;
+ if (clk->ops && clk->ops->enable)
+ ret = clk->ops->enable(clk);
+ return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+ if (clk->ops && clk->ops->disable)
+ clk->ops->disable(clk);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ unsigned long ret = 0;
+ if (clk->ops && clk->ops->get_rate)
+ ret = clk->ops->get_rate(clk);
+ return ret;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ long ret = -EIO;
+ if (clk->ops && clk->ops->round_rate)
+ ret = clk->ops->round_rate(clk, rate);
+ return ret;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret = -EIO;
+ if (clk->ops && clk->ops->set_rate)
+ ret = clk->ops->set_rate(clk, rate);
+ return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+unsigned long vco_get_rate(struct clk *clk)
+{
+ return clk->rate;
+}
+
+unsigned long pll_get_rate(struct clk *clk)
+{
+ u32 df;
+ u32 msel;
+ u32 ctl = bfin_read32(CGU0_CTL);
+ u32 stat = bfin_read32(CGU0_STAT);
+ if (stat & CGU0_STAT_PLLBP)
+ return 0;
+ msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
+ df = (ctl & CGU0_CTL_DF);
+ clk->parent->rate = clk_get_rate(clk->parent);
+ return clk->parent->rate / (df + 1) * msel * 2;
+}
+
+unsigned long pll_round_rate(struct clk *clk, unsigned long rate)
+{
+ u32 div;
+ div = rate / clk->parent->rate;
+ return clk->parent->rate * div;
+}
+
+int pll_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 msel;
+ u32 stat = bfin_read32(CGU0_STAT);
+ if (!(stat & CGU0_STAT_PLLEN))
+ return -EBUSY;
+ if (!(stat & CGU0_STAT_PLLLK))
+ return -EBUSY;
+ if (wait_for_pll_align())
+ return -EBUSY;
+ msel = rate / clk->parent->rate / 2;
+ clk_reg_write_mask(CGU0_CTL, msel << CGU0_CTL_MSEL_SHIFT,
+ CGU0_CTL_MSEL_MASK);
+ clk->rate = rate;
+ return 0;
+}
+
+unsigned long cclk_get_rate(struct clk *clk)
+{
+ if (clk->parent)
+ return clk->parent->rate;
+ else
+ return 0;
+}
+
+unsigned long sys_clk_get_rate(struct clk *clk)
+{
+ unsigned long drate;
+ u32 msel;
+ u32 df;
+ u32 ctl = bfin_read32(CGU0_CTL);
+ u32 div = bfin_read32(CGU0_DIV);
+ div = (div & clk->mask) >> clk->shift;
+ msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
+ df = (ctl & CGU0_CTL_DF);
+
+ if (!strcmp(clk->parent->name, "SYS_CLKIN")) {
+ drate = clk->parent->rate / (df + 1);
+ drate *= msel;
+ drate /= div;
+ return drate;
+ } else {
+ clk->parent->rate = clk_get_rate(clk->parent);
+ return clk->parent->rate / div;
+ }
+}
+
+unsigned long sys_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long max_rate;
+ unsigned long drate;
+ int i;
+ u32 msel;
+ u32 df;
+ u32 ctl = bfin_read32(CGU0_CTL);
+
+ msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
+ df = (ctl & CGU0_CTL_DF);
+ max_rate = clk->parent->rate / (df + 1) * msel;
+
+ if (rate > max_rate)
+ return 0;
+
+ for (i = 1; i < clk->mask; i++) {
+ drate = max_rate / i;
+ if (rate >= drate)
+ return drate;
+ }
+ return 0;
+}
+
+int sys_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 div = bfin_read32(CGU0_DIV);
+ div = (div & clk->mask) >> clk->shift;
+
+ rate = clk_round_rate(clk, rate);
+
+ if (!rate)
+ return -EINVAL;
+
+ div = (clk_get_rate(clk) * div) / rate;
+
+ if (wait_for_pll_align())
+ return -EBUSY;
+ clk_reg_write_mask(CGU0_DIV, div << clk->shift,
+ clk->mask);
+ clk->rate = rate;
+ return 0;
+}
+
+static struct clk_ops vco_ops = {
+ .get_rate = vco_get_rate,
+};
+
+static struct clk_ops pll_ops = {
+ .get_rate = pll_get_rate,
+ .set_rate = pll_set_rate,
+};
+
+static struct clk_ops cclk_ops = {
+ .get_rate = cclk_get_rate,
+};
+
+static struct clk_ops sys_clk_ops = {
+ .get_rate = sys_clk_get_rate,
+ .set_rate = sys_clk_set_rate,
+ .round_rate = sys_clk_round_rate,
+};
+
+static struct clk sys_clkin = {
+ .name = "SYS_CLKIN",
+ .rate = CONFIG_CLKIN_HZ,
+ .ops = &vco_ops,
+};
+
+static struct clk pll_clk = {
+ .name = "PLLCLK",
+ .rate = 500000000,
+ .parent = &sys_clkin,
+ .ops = &pll_ops,
+ .flags = NEEDS_INITIALIZATION,
+};
+
+static struct clk cclk = {
+ .name = "CCLK",
+ .rate = 500000000,
+ .mask = CGU0_DIV_CSEL_MASK,
+ .shift = CGU0_DIV_CSEL_SHIFT,
+ .parent = &sys_clkin,
+ .ops = &sys_clk_ops,
+ .flags = NEEDS_INITIALIZATION,
+};
+
+static struct clk cclk0 = {
+ .name = "CCLK0",
+ .parent = &cclk,
+ .ops = &cclk_ops,
+};
+
+static struct clk cclk1 = {
+ .name = "CCLK1",
+ .parent = &cclk,
+ .ops = &cclk_ops,
+};
+
+static struct clk sysclk = {
+ .name = "SYSCLK",
+ .rate = 500000000,
+ .mask = CGU0_DIV_SYSSEL_MASK,
+ .shift = CGU0_DIV_SYSSEL_SHIFT,
+ .parent = &sys_clkin,
+ .ops = &sys_clk_ops,
+ .flags = NEEDS_INITIALIZATION,
+};
+
+static struct clk sclk0 = {
+ .name = "SCLK0",
+ .rate = 500000000,
+ .mask = CGU0_DIV_S0SEL_MASK,
+ .shift = CGU0_DIV_S0SEL_SHIFT,
+ .parent = &sysclk,
+ .ops = &sys_clk_ops,
+};
+
+static struct clk sclk1 = {
+ .name = "SCLK1",
+ .rate = 500000000,
+ .mask = CGU0_DIV_S1SEL_MASK,
+ .shift = CGU0_DIV_S1SEL_SHIFT,
+ .parent = &sysclk,
+ .ops = &sys_clk_ops,
+};
+
+static struct clk dclk = {
+ .name = "DCLK",
+ .rate = 500000000,
+ .mask = CGU0_DIV_DSEL_MASK,
+ .shift = CGU0_DIV_DSEL_SHIFT,
+ .parent = &sys_clkin,
+ .ops = &sys_clk_ops,
+};
+
+static struct clk oclk = {
+ .name = "OCLK",
+ .rate = 500000000,
+ .mask = CGU0_DIV_OSEL_MASK,
+ .shift = CGU0_DIV_OSEL_SHIFT,
+ .parent = &pll_clk,
+};
+
+static struct clk_lookup bf609_clks[] = {
+ CLK(sys_clkin, NULL, "SYS_CLKIN"),
+ CLK(pll_clk, NULL, "PLLCLK"),
+ CLK(cclk, NULL, "CCLK"),
+ CLK(cclk0, NULL, "CCLK0"),
+ CLK(cclk1, NULL, "CCLK1"),
+ CLK(sysclk, NULL, "SYSCLK"),
+ CLK(sclk0, NULL, "SCLK0"),
+ CLK(sclk1, NULL, "SCLK1"),
+ CLK(dclk, NULL, "DCLK"),
+ CLK(oclk, NULL, "OCLK"),
+};
+
+int __init clk_init(void)
+{
+ int i;
+ struct clk *clkp;
+ for (i = 0; i < ARRAY_SIZE(bf609_clks); i++) {
+ clkp = bf609_clks[i].clk;
+ if (clkp->flags & NEEDS_INITIALIZATION)
+ clk_get_rate(clkp);
+ }
+ clkdev_add_table(bf609_clks, ARRAY_SIZE(bf609_clks));
+ return 0;
+}
diff --git a/arch/blackfin/mach-bf609/dma.c b/arch/blackfin/mach-bf609/dma.c
new file mode 100644
index 000000000000..1da4b38ac22c
--- /dev/null
+++ b/arch/blackfin/mach-bf609/dma.c
@@ -0,0 +1,202 @@
+/*
+ * the simple DMA Implementation for Blackfin
+ *
+ * Copyright 2007-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+
+#include <asm/blackfin.h>
+#include <asm/dma.h>
+
+struct dma_register * const dma_io_base_addr[MAX_DMA_CHANNELS] = {
+ (struct dma_register *) DMA0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_NEXT_DESC_PTR,
+ (struct dma_register *) DMA3_NEXT_DESC_PTR,
+ (struct dma_register *) DMA4_NEXT_DESC_PTR,
+ (struct dma_register *) DMA5_NEXT_DESC_PTR,
+ (struct dma_register *) DMA6_NEXT_DESC_PTR,
+ (struct dma_register *) DMA7_NEXT_DESC_PTR,
+ (struct dma_register *) DMA8_NEXT_DESC_PTR,
+ (struct dma_register *) DMA9_NEXT_DESC_PTR,
+ (struct dma_register *) DMA10_NEXT_DESC_PTR,
+ (struct dma_register *) DMA11_NEXT_DESC_PTR,
+ (struct dma_register *) DMA12_NEXT_DESC_PTR,
+ (struct dma_register *) DMA13_NEXT_DESC_PTR,
+ (struct dma_register *) DMA14_NEXT_DESC_PTR,
+ (struct dma_register *) DMA15_NEXT_DESC_PTR,
+ (struct dma_register *) DMA16_NEXT_DESC_PTR,
+ (struct dma_register *) DMA17_NEXT_DESC_PTR,
+ (struct dma_register *) DMA18_NEXT_DESC_PTR,
+ (struct dma_register *) DMA19_NEXT_DESC_PTR,
+ (struct dma_register *) DMA20_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA0_SRC_CRC0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA0_DEST_CRC0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_SRC_CRC1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_DEST_CRC1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA2_SRC_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA2_DEST_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA3_SRC_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA3_DEST_NEXT_DESC_PTR,
+ (struct dma_register *) DMA29_NEXT_DESC_PTR,
+ (struct dma_register *) DMA30_NEXT_DESC_PTR,
+ (struct dma_register *) DMA31_NEXT_DESC_PTR,
+ (struct dma_register *) DMA32_NEXT_DESC_PTR,
+ (struct dma_register *) DMA33_NEXT_DESC_PTR,
+ (struct dma_register *) DMA34_NEXT_DESC_PTR,
+ (struct dma_register *) DMA35_NEXT_DESC_PTR,
+ (struct dma_register *) DMA36_NEXT_DESC_PTR,
+ (struct dma_register *) DMA37_NEXT_DESC_PTR,
+ (struct dma_register *) DMA38_NEXT_DESC_PTR,
+ (struct dma_register *) DMA39_NEXT_DESC_PTR,
+ (struct dma_register *) DMA40_NEXT_DESC_PTR,
+ (struct dma_register *) DMA41_NEXT_DESC_PTR,
+ (struct dma_register *) DMA42_NEXT_DESC_PTR,
+ (struct dma_register *) DMA43_NEXT_DESC_PTR,
+ (struct dma_register *) DMA44_NEXT_DESC_PTR,
+ (struct dma_register *) DMA45_NEXT_DESC_PTR,
+ (struct dma_register *) DMA46_NEXT_DESC_PTR,
+};
+EXPORT_SYMBOL(dma_io_base_addr);
+
+int channel2irq(unsigned int channel)
+{
+ int ret_irq = -1;
+
+ switch (channel) {
+ case CH_SPORT0_RX:
+ ret_irq = IRQ_SPORT0_RX;
+ break;
+ case CH_SPORT0_TX:
+ ret_irq = IRQ_SPORT0_TX;
+ break;
+ case CH_SPORT1_RX:
+ ret_irq = IRQ_SPORT1_RX;
+ break;
+ case CH_SPORT1_TX:
+ ret_irq = IRQ_SPORT1_TX;
+ break;
+ case CH_SPORT2_RX:
+ ret_irq = IRQ_SPORT2_RX;
+ break;
+ case CH_SPORT2_TX:
+ ret_irq = IRQ_SPORT2_TX;
+ break;
+ case CH_SPI0_TX:
+ ret_irq = IRQ_SPI0_TX;
+ break;
+ case CH_SPI0_RX:
+ ret_irq = IRQ_SPI0_RX;
+ break;
+ case CH_SPI1_TX:
+ ret_irq = IRQ_SPI1_TX;
+ break;
+ case CH_SPI1_RX:
+ ret_irq = IRQ_SPI1_RX;
+ break;
+ case CH_RSI:
+ ret_irq = IRQ_RSI;
+ break;
+ case CH_SDU:
+ ret_irq = IRQ_SDU;
+ break;
+ case CH_LP0:
+ ret_irq = IRQ_LP0;
+ break;
+ case CH_LP1:
+ ret_irq = IRQ_LP1;
+ break;
+ case CH_LP2:
+ ret_irq = IRQ_LP2;
+ break;
+ case CH_LP3:
+ ret_irq = IRQ_LP3;
+ break;
+ case CH_UART0_RX:
+ ret_irq = IRQ_UART0_RX;
+ break;
+ case CH_UART0_TX:
+ ret_irq = IRQ_UART0_TX;
+ break;
+ case CH_UART1_RX:
+ ret_irq = IRQ_UART1_RX;
+ break;
+ case CH_UART1_TX:
+ ret_irq = IRQ_UART1_TX;
+ break;
+ case CH_EPPI0_CH0:
+ ret_irq = IRQ_EPPI0_CH0;
+ break;
+ case CH_EPPI0_CH1:
+ ret_irq = IRQ_EPPI0_CH1;
+ break;
+ case CH_EPPI1_CH0:
+ ret_irq = IRQ_EPPI1_CH0;
+ break;
+ case CH_EPPI1_CH1:
+ ret_irq = IRQ_EPPI1_CH1;
+ break;
+ case CH_EPPI2_CH0:
+ ret_irq = IRQ_EPPI2_CH0;
+ break;
+ case CH_EPPI2_CH1:
+ ret_irq = IRQ_EPPI2_CH1;
+ break;
+ case CH_PIXC_CH0:
+ ret_irq = IRQ_PIXC_CH0;
+ break;
+ case CH_PIXC_CH1:
+ ret_irq = IRQ_PIXC_CH1;
+ break;
+ case CH_PIXC_CH2:
+ ret_irq = IRQ_PIXC_CH2;
+ break;
+ case CH_PVP_CPDOB:
+ ret_irq = IRQ_PVP_CPDOB;
+ break;
+ case CH_PVP_CPDOC:
+ ret_irq = IRQ_PVP_CPDOC;
+ break;
+ case CH_PVP_CPSTAT:
+ ret_irq = IRQ_PVP_CPSTAT;
+ break;
+ case CH_PVP_CPCI:
+ ret_irq = IRQ_PVP_CPCI;
+ break;
+ case CH_PVP_MPDO:
+ ret_irq = IRQ_PVP_MPDO;
+ break;
+ case CH_PVP_MPDI:
+ ret_irq = IRQ_PVP_MPDI;
+ break;
+ case CH_PVP_MPSTAT:
+ ret_irq = IRQ_PVP_MPSTAT;
+ break;
+ case CH_PVP_MPCI:
+ ret_irq = IRQ_PVP_MPCI;
+ break;
+ case CH_PVP_CPDOA:
+ ret_irq = IRQ_PVP_CPDOA;
+ break;
+ case CH_MEM_STREAM0_SRC:
+ case CH_MEM_STREAM0_DEST:
+ ret_irq = IRQ_MDMAS0;
+ break;
+ case CH_MEM_STREAM1_SRC:
+ case CH_MEM_STREAM1_DEST:
+ ret_irq = IRQ_MDMAS1;
+ break;
+ case CH_MEM_STREAM2_SRC:
+ case CH_MEM_STREAM2_DEST:
+ ret_irq = IRQ_MDMAS2;
+ break;
+ case CH_MEM_STREAM3_SRC:
+ case CH_MEM_STREAM3_DEST:
+ ret_irq = IRQ_MDMAS3;
+ break;
+ }
+ return ret_irq;
+}
diff --git a/arch/blackfin/mach-bf609/hibernate.S b/arch/blackfin/mach-bf609/hibernate.S
new file mode 100644
index 000000000000..d37a532519c8
--- /dev/null
+++ b/arch/blackfin/mach-bf609/hibernate.S
@@ -0,0 +1,65 @@
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+#include <asm/dpmc.h>
+
+#define PM_STACK (COREA_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
+
+.section .l1.text
+ENTRY(_enter_hibernate)
+ /* switch stack to L1 scratch, prepare for ddr srfr */
+ P0.H = HI(PM_STACK);
+ P0.L = LO(PM_STACK);
+ SP = P0;
+
+ call _bf609_ddr_sr;
+ call _bfin_hibernate_syscontrol;
+
+ P0.H = HI(DPM0_RESTORE4);
+ P0.L = LO(DPM0_RESTORE4);
+ P1.H = _bf609_pm_data;
+ P1.L = _bf609_pm_data;
+ [P0] = P1;
+
+ P0.H = HI(DPM0_CTL);
+ P0.L = LO(DPM0_CTL);
+ R3.H = HI(0x00000010);
+ R3.L = LO(0x00000010);
+
+ bfin_init_pm_bench_cycles;
+
+ [P0] = R3;
+
+ SSYNC;
+ENDPROC(_enter_hibernate_mode)
+
+.section .text
+ENTRY(_bf609_hibernate)
+ bfin_cpu_reg_save;
+ bfin_core_mmr_save;
+
+ P0.H = _bf609_pm_data;
+ P0.L = _bf609_pm_data;
+ R1.H = 0xDEAD;
+ R1.L = 0xBEEF;
+ R2.H = .Lpm_resume_here;
+ R2.L = .Lpm_resume_here;
+ [P0++] = R1;
+ [P0++] = R2;
+ [P0++] = SP;
+
+ P1.H = _enter_hibernate;
+ P1.L = _enter_hibernate;
+
+ call (P1);
+.Lpm_resume_here:
+
+ bfin_core_mmr_restore;
+ bfin_cpu_reg_restore;
+
+ [--sp] = RETI; /* Clear Global Interrupt Disable */
+ SP += 4;
+
+ RTS;
+
+ENDPROC(_bf609_hibernate)
+
diff --git a/arch/blackfin/mach-bf609/include/mach/anomaly.h b/arch/blackfin/mach-bf609/include/mach/anomaly.h
new file mode 100644
index 000000000000..bdd39aefb565
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/anomaly.h
@@ -0,0 +1,130 @@
+/*
+ * DO NOT EDIT THIS FILE
+ * This file is under version control at
+ * svn://sources.blackfin.uclinux.org/toolchain/trunk/proc-defs/header-frags/
+ * and can be replaced with that version at any time
+ * DO NOT EDIT THIS FILE
+ *
+ * Copyright 2004-2011 Analog Devices Inc.
+ * Licensed under the Clear BSD license.
+ */
+
+/* This file should be up to date with:
+ */
+
+#if __SILICON_REVISION__ < 0
+# error will not work on BF506 silicon version
+#endif
+
+#ifndef _MACH_ANOMALY_H_
+#define _MACH_ANOMALY_H_
+
+/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
+#define ANOMALY_05000074 (1)
+/* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */
+#define ANOMALY_05000119 (1)
+/* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
+#define ANOMALY_05000122 (1)
+/* False Hardware Error from an Access in the Shadow of a Conditional Branch */
+#define ANOMALY_05000245 (1)
+/* Incorrect Timer Pulse Width in Single-Shot PWM_OUT Mode with External Clock */
+#define ANOMALY_05000254 (1)
+/* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
+#define ANOMALY_05000265 (1)
+/* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
+#define ANOMALY_05000310 (1)
+/* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
+#define ANOMALY_05000366 (1)
+/* Speculative Fetches Can Cause Undesired External FIFO Operations */
+#define ANOMALY_05000416 (1)
+/* Speculative Fetches of Indirect-Pointer Instructions Can Cause False Hardware Errors */
+#define ANOMALY_05000426 (1)
+/* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
+#define ANOMALY_05000443 (1)
+/* UART IrDA Receiver Fails on Extended Bit Pulses */
+#define ANOMALY_05000447 (1)
+/* False Hardware Error when RETI Points to Invalid Memory */
+#define ANOMALY_05000461 (1)
+/* PLL Latches Incorrect Settings During Reset */
+#define ANOMALY_05000469 (1)
+/* Incorrect Default MSEL Value in PLL_CTL */
+#define ANOMALY_05000472 (1)
+/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
+#define ANOMALY_05000473 (1)
+/* TESTSET Instruction Cannot Be Interrupted */
+#define ANOMALY_05000477 (1)
+/* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
+#define ANOMALY_05000481 (1)
+/* IFLUSH sucks at life */
+#define ANOMALY_05000491 (1)
+/* Tempopary anomaly ID for data loss in MMR read operation if interrupted */
+#define ANOMALY_05001001 (__SILICON_REVISION__ < 1)
+
+/* Anomalies that don't exist on this proc */
+#define ANOMALY_05000099 (0)
+#define ANOMALY_05000120 (0)
+#define ANOMALY_05000125 (0)
+#define ANOMALY_05000149 (0)
+#define ANOMALY_05000158 (0)
+#define ANOMALY_05000171 (0)
+#define ANOMALY_05000179 (0)
+#define ANOMALY_05000182 (0)
+#define ANOMALY_05000183 (0)
+#define ANOMALY_05000189 (0)
+#define ANOMALY_05000198 (0)
+#define ANOMALY_05000202 (0)
+#define ANOMALY_05000215 (0)
+#define ANOMALY_05000219 (0)
+#define ANOMALY_05000220 (0)
+#define ANOMALY_05000227 (0)
+#define ANOMALY_05000230 (0)
+#define ANOMALY_05000231 (0)
+#define ANOMALY_05000233 (0)
+#define ANOMALY_05000234 (0)
+#define ANOMALY_05000242 (0)
+#define ANOMALY_05000244 (0)
+#define ANOMALY_05000248 (0)
+#define ANOMALY_05000250 (0)
+#define ANOMALY_05000257 (0)
+#define ANOMALY_05000261 (0)
+#define ANOMALY_05000263 (0)
+#define ANOMALY_05000266 (0)
+#define ANOMALY_05000273 (0)
+#define ANOMALY_05000274 (0)
+#define ANOMALY_05000278 (0)
+#define ANOMALY_05000281 (0)
+#define ANOMALY_05000283 (0)
+#define ANOMALY_05000285 (0)
+#define ANOMALY_05000287 (0)
+#define ANOMALY_05000301 (0)
+#define ANOMALY_05000305 (0)
+#define ANOMALY_05000307 (0)
+#define ANOMALY_05000311 (0)
+#define ANOMALY_05000312 (0)
+#define ANOMALY_05000315 (0)
+#define ANOMALY_05000323 (0)
+#define ANOMALY_05000353 (1)
+#define ANOMALY_05000357 (0)
+#define ANOMALY_05000362 (1)
+#define ANOMALY_05000363 (0)
+#define ANOMALY_05000364 (0)
+#define ANOMALY_05000371 (0)
+#define ANOMALY_05000380 (0)
+#define ANOMALY_05000386 (0)
+#define ANOMALY_05000389 (0)
+#define ANOMALY_05000400 (0)
+#define ANOMALY_05000402 (0)
+#define ANOMALY_05000412 (0)
+#define ANOMALY_05000432 (0)
+#define ANOMALY_05000440 (0)
+#define ANOMALY_05000448 (0)
+#define ANOMALY_05000456 (0)
+#define ANOMALY_05000450 (0)
+#define ANOMALY_05000465 (0)
+#define ANOMALY_05000467 (0)
+#define ANOMALY_05000474 (0)
+#define ANOMALY_05000475 (0)
+#define ANOMALY_05000480 (0)
+#define ANOMALY_05000485 (0)
+
+#endif
diff --git a/arch/blackfin/mach-bf609/include/mach/bf609.h b/arch/blackfin/mach-bf609/include/mach/bf609.h
new file mode 100644
index 000000000000..c897c2a2fbfa
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/bf609.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __MACH_BF609_H__
+#define __MACH_BF609_H__
+
+#define OFFSET_(x) ((x) & 0x0000FFFF)
+
+/*some misc defines*/
+#define IMASK_IVG15 0x8000
+#define IMASK_IVG14 0x4000
+#define IMASK_IVG13 0x2000
+#define IMASK_IVG12 0x1000
+
+#define IMASK_IVG11 0x0800
+#define IMASK_IVG10 0x0400
+#define IMASK_IVG9 0x0200
+#define IMASK_IVG8 0x0100
+
+#define IMASK_IVG7 0x0080
+#define IMASK_IVGTMR 0x0040
+#define IMASK_IVGHW 0x0020
+
+/***************************/
+
+
+#define BFIN_DSUBBANKS 4
+#define BFIN_DWAYS 2
+#define BFIN_DLINES 64
+#define BFIN_ISUBBANKS 4
+#define BFIN_IWAYS 4
+#define BFIN_ILINES 32
+
+#define WAY0_L 0x1
+#define WAY1_L 0x2
+#define WAY01_L 0x3
+#define WAY2_L 0x4
+#define WAY02_L 0x5
+#define WAY12_L 0x6
+#define WAY012_L 0x7
+
+#define WAY3_L 0x8
+#define WAY03_L 0x9
+#define WAY13_L 0xA
+#define WAY013_L 0xB
+
+#define WAY32_L 0xC
+#define WAY320_L 0xD
+#define WAY321_L 0xE
+#define WAYALL_L 0xF
+
+#define DMC_ENABLE (2<<2) /*yes, 2, not 1 */
+
+/********************************* EBIU Settings ************************************/
+#define AMBCTL0VAL ((CONFIG_BANK_1 << 16) | CONFIG_BANK_0)
+#define AMBCTL1VAL ((CONFIG_BANK_3 << 16) | CONFIG_BANK_2)
+
+#ifdef CONFIG_C_AMBEN_ALL
+#define V_AMBEN AMBEN_ALL
+#endif
+#ifdef CONFIG_C_AMBEN
+#define V_AMBEN 0x0
+#endif
+#ifdef CONFIG_C_AMBEN_B0
+#define V_AMBEN AMBEN_B0
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1
+#define V_AMBEN AMBEN_B0_B1
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1_B2
+#define V_AMBEN AMBEN_B0_B1_B2
+#endif
+#ifdef CONFIG_C_AMCKEN
+#define V_AMCKEN AMCKEN
+#else
+#define V_AMCKEN 0x0
+#endif
+
+#define AMGCTLVAL (V_AMBEN | V_AMCKEN)
+
+#if defined(CONFIG_BF609)
+# define CPU "BF609"
+# define CPUID 0x27fe /* temperary fake value */
+#endif
+
+#ifndef CPU
+#error "Unknown CPU type - This kernel doesn't seem to be configured properly"
+#endif
+
+#endif /* __MACH_BF609_H__ */
diff --git a/arch/blackfin/mach-bf609/include/mach/bfin_serial.h b/arch/blackfin/mach-bf609/include/mach/bfin_serial.h
new file mode 100644
index 000000000000..1fd398147fd9
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/bfin_serial.h
@@ -0,0 +1,17 @@
+/*
+ * mach/bfin_serial.h - Blackfin UART/Serial definitions
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_MACH_SERIAL_H__
+#define __BFIN_MACH_SERIAL_H__
+
+#define BFIN_UART_NR_PORTS 2
+#define BFIN_UART_TX_FIFO_SIZE 8
+
+#define BFIN_UART_BF60X_STYLE
+
+#endif
diff --git a/arch/blackfin/mach-bf609/include/mach/blackfin.h b/arch/blackfin/mach-bf609/include/mach/blackfin.h
new file mode 100644
index 000000000000..b1a48c410711
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/blackfin.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_BLACKFIN_H_
+#define _MACH_BLACKFIN_H_
+
+#include "bf609.h"
+#include "anomaly.h"
+
+#include <asm/def_LPBlackfin.h>
+#ifdef CONFIG_BF609
+# include "defBF609.h"
+#endif
+
+#ifndef __ASSEMBLY__
+# include <asm/cdef_LPBlackfin.h>
+# ifdef CONFIG_BF609
+# include "cdefBF609.h"
+# endif
+#endif
+
+#endif
diff --git a/arch/blackfin/mach-bf609/include/mach/cdefBF609.h b/arch/blackfin/mach-bf609/include/mach/cdefBF609.h
new file mode 100644
index 000000000000..c4f3fe19acda
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/cdefBF609.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _CDEF_BF609_H
+#define _CDEF_BF609_H
+
+/* include cdefBF60x_base.h for the set of #defines that are common to all ADSP-BF60x bfin_read_()rocessors */
+#include "cdefBF60x_base.h"
+
+/* The following are the #defines needed by ADSP-BF609 that are not in the common header */
+
+#endif /* _CDEF_BF609_H */
diff --git a/arch/blackfin/mach-bf609/include/mach/cdefBF60x_base.h b/arch/blackfin/mach-bf609/include/mach/cdefBF60x_base.h
new file mode 100644
index 000000000000..4954cf3f7e16
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/cdefBF60x_base.h
@@ -0,0 +1,3252 @@
+/*
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _CDEF_BF60X_H
+#define _CDEF_BF60X_H
+
+/* ************************************************************** */
+/* SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF60x */
+/* ************************************************************** */
+
+/* Debug/MP/Emulation Registers (0xFFC00014 - 0xFFC00014) */
+
+#define bfin_read_CHIPID() bfin_read32(CHIPID)
+#define bfin_write_CHIPID(val) bfin_write32(CHIPID, val)
+
+/* System Reset and Interrubfin_read_()t Controller (0xFFC00100 - 0xFFC00104) */
+
+/* SEC0 Registers */
+#define bfin_read_SEC0_CCTL() bfin_read32(SEC0_CCTL)
+#define bfin_write_SEC0_CCTL(val) bfin_write32(SEC0_CCTL, val)
+#define bfin_read_SEC0_CSID() bfin_read32(SEC0_CSID)
+#define bfin_write_SEC0_CSID(val) bfin_write32(SEC0_CSID, val)
+#define bfin_read_SEC_GCTL() bfin_read32(SEC_GCTL)
+#define bfin_write_SEC_GCTL(val) bfin_write32(SEC_GCTL, val)
+
+#define bfin_read_SEC_FCTL() bfin_read32(SEC_FCTL)
+#define bfin_write_SEC_FCTL(val) bfin_write32(SEC_FCTL, val)
+
+#define bfin_read_SEC_SCTL(sid) bfin_read32((SEC_SCTL0 + (sid) * 8))
+#define bfin_write_SEC_SCTL(sid, val) bfin_write32((SEC_SCTL0 + (sid) * 8), val)
+
+#define bfin_read_SEC_SSTAT(sid) bfin_read32((SEC_SSTAT0 + (sid) * 8))
+#define bfin_write_SEC_SSTAT(sid, val) bfin_write32((SEC_SSTAT0 + (sid) * 8), val)
+
+/* RCU0 Registers */
+#define bfin_read_RCU0_CTL() bfin_read32(RCU0_CTL)
+#define bfin_write_RCU0_CTL(val) bfin_write32(RCU0_CTL, val)
+
+/* Watchdog Timer Registers */
+#define bfin_read_WDOG_CTL() bfin_read16(WDOG_CTL)
+#define bfin_write_WDOG_CTL(val) bfin_write16(WDOG_CTL, val)
+#define bfin_read_WDOG_CNT() bfin_read32(WDOG_CNT)
+#define bfin_write_WDOG_CNT(val) bfin_write32(WDOG_CNT, val)
+#define bfin_read_WDOG_STAT() bfin_read32(WDOG_STAT)
+#define bfin_write_WDOG_STAT(val) bfin_write32(WDOG_STAT, val)
+
+/* RTC Registers */
+
+/* UART0 Registers */
+
+#define bfin_read_UART0_REVID() bfin_read32(UART0_REVID)
+#define bfin_write_UART0_REVID(val) bfin_write32(UART0_REVID, val)
+#define bfin_read_UART0_GCTL() bfin_read32(UART0_GCTL)
+#define bfin_write_UART0_GCTL(val) bfin_write32(UART0_GCTL, val)
+#define bfin_read_UART0_STAT() bfin_read32(UART0_STAT)
+#define bfin_write_UART0_STAT(val) bfin_write32(UART0_STAT, val)
+#define bfin_read_UART0_SCR() bfin_read32(UART0_SCR)
+#define bfin_write_UART0_SCR(val) bfin_write32(UART0_SCR, val)
+#define bfin_read_UART0_CLK() bfin_read32(UART0_CLK)
+#define bfin_write_UART0_CLK(val) bfin_write32(UART0_CLK, val)
+#define bfin_read_UART0_IER() bfin_read32(UART0_IER)
+#define bfin_write_UART0_IER(val) bfin_write32(UART0_IER, val)
+#define bfin_read_UART0_IER_SET() bfin_read32(UART0_IER_SET)
+#define bfin_write_UART0_IER_SET(val) bfin_write32(UART0_IER_SET, val)
+#define bfin_read_UART0_IER_CLEAR() bfin_read32(UART0_IER_CLEAR)
+#define bfin_write_UART0_IER_CLEAR(val) bfin_write32(UART0_IER_CLEAR, val)
+#define bfin_read_UART0_RBR() bfin_read32(UART0_RBR)
+#define bfin_write_UART0_RBR(val) bfin_write32(UART0_RBR, val)
+#define bfin_read_UART0_THR() bfin_read32(UART0_THR)
+#define bfin_write_UART0_THR(val) bfin_write32(UART0_THR, val)
+#define bfin_read_UART0_TAIP() bfin_read32(UART0_TAIP)
+#define bfin_write_UART0_TAIP(val) bfin_write32(UART0_TAIP, val)
+#define bfin_read_UART0_TSR() bfin_read32(UART0_TSR)
+#define bfin_write_UART0_TSR(val) bfin_write32(UART0_TSR, val)
+#define bfin_read_UART0_RSR() bfin_read32(UART0_RSR)
+#define bfin_write_UART0_RSR(val) bfin_write32(UART0_RSR, val)
+#define bfin_read_UART0_TXCNT() bfin_read32(UART0_TXCNT)
+#define bfin_write_UART0_TXCNT(val) bfin_write32(UART0_TXCNT, val)
+#define bfin_read_UART0_RXCNT() bfin_read32(UART0_RXCNT)
+#define bfin_write_UART0_RXCNT(val) bfin_write32(UART0_RXCNT, val)
+
+/* UART1 Registers */
+
+#define bfin_read_UART1_REVID() bfin_read32(UART1_REVID)
+#define bfin_write_UART1_REVID(val) bfin_write32(UART1_REVID, val)
+#define bfin_read_UART1_GCTL() bfin_read32(UART1_GCTL)
+#define bfin_write_UART1_GCTL(val) bfin_write32(UART1_GCTL, val)
+#define bfin_read_UART1_STAT() bfin_read32(UART1_STAT)
+#define bfin_write_UART1_STAT(val) bfin_write32(UART1_STAT, val)
+#define bfin_read_UART1_SCR() bfin_read32(UART1_SCR)
+#define bfin_write_UART1_SCR(val) bfin_write32(UART1_SCR, val)
+#define bfin_read_UART1_CLK() bfin_read32(UART1_CLK)
+#define bfin_write_UART1_CLK(val) bfin_write32(UART1_CLK, val)
+#define bfin_read_UART1_IER() bfin_read32(UART1_IER)
+#define bfin_write_UART1_IER(val) bfin_write32(UART1_IER, val)
+#define bfin_read_UART1_IER_SET() bfin_read32(UART1_IER_SET)
+#define bfin_write_UART1_IER_SET(val) bfin_write32(UART1_IER_SET, val)
+#define bfin_read_UART1_IER_CLEAR() bfin_read32(UART1_IER_CLEAR)
+#define bfin_write_UART1_IER_CLEAR(val) bfin_write32(UART1_IER_CLEAR, val)
+#define bfin_read_UART1_RBR() bfin_read32(UART1_RBR)
+#define bfin_write_UART1_RBR(val) bfin_write32(UART1_RBR, val)
+#define bfin_read_UART1_THR() bfin_read32(UART1_THR)
+#define bfin_write_UART1_THR(val) bfin_write32(UART1_THR, val)
+#define bfin_read_UART1_TAIP() bfin_read32(UART1_TAIP)
+#define bfin_write_UART1_TAIP(val) bfin_write32(UART1_TAIP, val)
+#define bfin_read_UART1_TSR() bfin_read32(UART1_TSR)
+#define bfin_write_UART1_TSR(val) bfin_write32(UART1_TSR, val)
+#define bfin_read_UART1_RSR() bfin_read32(UART1_RSR)
+#define bfin_write_UART1_RSR(val) bfin_write32(UART1_RSR, val)
+#define bfin_read_UART1_TXCNT() bfin_read32(UART1_TXCNT)
+#define bfin_write_UART1_TXCNT(val) bfin_write32(UART1_TXCNT, val)
+#define bfin_read_UART1_RXCNT() bfin_read32(UART1_RXCNT)
+#define bfin_write_UART1_RXCNT(val) bfin_write32(UART1_RXCNT, val)
+
+
+/* SPI0 Registers */
+
+#define bfin_read_SPI0_CTL() bfin_read32(SPI0_CTL)
+#define bfin_write_SPI0_CTL(val) bfin_write32(SPI0_CTL, val)
+#define bfin_read_SPI0_RXCTL() bfin_read32(SPI0_RXCTL)
+#define bfin_write_SPI0_RXCTL(val) bfin_write32(SPI0_RXCTL, val)
+#define bfin_read_SPI0_TXCTL() bfin_read32(SPI0_TXCTL)
+#define bfin_write_SPI0_TXCTL(val) bfin_write32(SPI0_TXCTL, val)
+#define bfin_read_SPI0_CLK() bfin_read32(SPI0_CLK)
+#define bfin_write_SPI0_CLK(val) bfin_write32(SPI0_CLK, val)
+#define bfin_read_SPI0_DLY() bfin_read32(SPI0_DLY)
+#define bfin_write_SPI0_DLY(val) bfin_write32(SPI0_DLY, val)
+#define bfin_read_SPI0_SLVSEL() bfin_read32(SPI0_SLVSEL)
+#define bfin_write_SPI0_SLVSEL(val) bfin_write32(SPI0_SLVSEL, val)
+#define bfin_read_SPI0_RWC() bfin_read32(SPI0_RWC)
+#define bfin_write_SPI0_RWC(val) bfin_write32(SPI0_RWC, val)
+#define bfin_read_SPI0_RWCR() bfin_read32(SPI0_RWCR)
+#define bfin_write_SPI0_RWCR(val) bfin_write32(SPI0_RWCR, val)
+#define bfin_read_SPI0_TWC() bfin_read32(SPI0_TWC)
+#define bfin_write_SPI0_TWC(val) bfin_write32(SPI0_TWC, val)
+#define bfin_read_SPI0_TWCR() bfin_read32(SPI0_TWCR)
+#define bfin_write_SPI0_TWCR(val) bfin_write32(SPI0_TWCR, val)
+#define bfin_read_SPI0_IMSK() bfin_read32(SPI0_IMSK)
+#define bfin_write_SPI0_IMSK(val) bfin_write32(SPI0_IMSK, val)
+#define bfin_read_SPI0_IMSK_CLR() bfin_read32(SPI0_IMSK_CLR)
+#define bfin_write_SPI0_IMSK_CLR(val) bfin_write32(SPI0_IMSK_CLR, val)
+#define bfin_read_SPI0_IMSK_SET() bfin_read32(SPI0_IMSK_SET)
+#define bfin_write_SPI0_IMSK_SET(val) bfin_write32(SPI0_IMSK_SET, val)
+#define bfin_read_SPI0_STAT() bfin_read32(SPI0_STAT)
+#define bfin_write_SPI0_STAT(val) bfin_write32(SPI0_STAT, val)
+#define bfin_read_SPI0_ILAT() bfin_read32(SPI0_ILAT)
+#define bfin_write_SPI0_ILAT(val) bfin_write32(SPI0_ILAT, val)
+#define bfin_read_SPI0_ILAT_CLR() bfin_read32(SPI0_ILAT_CLR)
+#define bfin_write_SPI0_ILAT_CLR(val) bfin_write32(SPI0_ILAT_CLR, val)
+#define bfin_read_SPI0_RFIFO() bfin_read32(SPI0_RFIFO)
+#define bfin_write_SPI0_RFIFO(val) bfin_write32(SPI0_RFIFO, val)
+#define bfin_read_SPI0_TFIFO() bfin_read32(SPI0_TFIFO)
+#define bfin_write_SPI0_TFIFO(val) bfin_write32(SPI0_TFIFO, val)
+
+/* SPI1 Registers */
+
+#define bfin_read_SPI1_CTL() bfin_read32(SPI1_CTL)
+#define bfin_write_SPI1_CTL(val) bfin_write32(SPI1_CTL, val)
+#define bfin_read_SPI1_RXCTL() bfin_read32(SPI1_RXCTL)
+#define bfin_write_SPI1_RXCTL(val) bfin_write32(SPI1_RXCTL, val)
+#define bfin_read_SPI1_TXCTL() bfin_read32(SPI1_TXCTL)
+#define bfin_write_SPI1_TXCTL(val) bfin_write32(SPI1_TXCTL, val)
+#define bfin_read_SPI1_CLK() bfin_read32(SPI1_CLK)
+#define bfin_write_SPI1_CLK(val) bfin_write32(SPI1_CLK, val)
+#define bfin_read_SPI1_DLY() bfin_read32(SPI1_DLY)
+#define bfin_write_SPI1_DLY(val) bfin_write32(SPI1_DLY, val)
+#define bfin_read_SPI1_SLVSEL() bfin_read32(SPI1_SLVSEL)
+#define bfin_write_SPI1_SLVSEL(val) bfin_write32(SPI1_SLVSEL, val)
+#define bfin_read_SPI1_RWC() bfin_read32(SPI1_RWC)
+#define bfin_write_SPI1_RWC(val) bfin_write32(SPI1_RWC, val)
+#define bfin_read_SPI1_RWCR() bfin_read32(SPI1_RWCR)
+#define bfin_write_SPI1_RWCR(val) bfin_write32(SPI1_RWCR, val)
+#define bfin_read_SPI1_TWC() bfin_read32(SPI1_TWC)
+#define bfin_write_SPI1_TWC(val) bfin_write32(SPI1_TWC, val)
+#define bfin_read_SPI1_TWCR() bfin_read32(SPI1_TWCR)
+#define bfin_write_SPI1_TWCR(val) bfin_write32(SPI1_TWCR, val)
+#define bfin_read_SPI1_IMSK() bfin_read32(SPI1_IMSK)
+#define bfin_write_SPI1_IMSK(val) bfin_write32(SPI1_IMSK, val)
+#define bfin_read_SPI1_IMSK_CLR() bfin_read32(SPI1_IMSK_CLR)
+#define bfin_write_SPI1_IMSK_CLR(val) bfin_write32(SPI1_IMSK_CLR, val)
+#define bfin_read_SPI1_IMSK_SET() bfin_read32(SPI1_IMSK_SET)
+#define bfin_write_SPI1_IMSK_SET(val) bfin_write32(SPI1_IMSK_SET, val)
+#define bfin_read_SPI1_STAT() bfin_read32(SPI1_STAT)
+#define bfin_write_SPI1_STAT(val) bfin_write32(SPI1_STAT, val)
+#define bfin_read_SPI1_ILAT() bfin_read32(SPI1_ILAT)
+#define bfin_write_SPI1_ILAT(val) bfin_write32(SPI1_ILAT, val)
+#define bfin_read_SPI1_ILAT_CLR() bfin_read32(SPI1_ILAT_CLR)
+#define bfin_write_SPI1_ILAT_CLR(val) bfin_write32(SPI1_ILAT_CLR, val)
+#define bfin_read_SPI1_RFIFO() bfin_read32(SPI1_RFIFO)
+#define bfin_write_SPI1_RFIFO(val) bfin_write32(SPI1_RFIFO, val)
+#define bfin_read_SPI1_TFIFO() bfin_read32(SPI1_TFIFO)
+#define bfin_write_SPI1_TFIFO(val) bfin_write32(SPI1_TFIFO, val)
+
+/* Timer 0-7 registers */
+#define bfin_read_TIMER0_CONFIG() bfin_read16(TIMER0_CONFIG)
+#define bfin_write_TIMER0_CONFIG(val) bfin_write16(TIMER0_CONFIG, val)
+#define bfin_read_TIMER0_COUNTER() bfin_read32(TIMER0_COUNTER)
+#define bfin_write_TIMER0_COUNTER(val) bfin_write32(TIMER0_COUNTER, val)
+#define bfin_read_TIMER0_PERIOD() bfin_read32(TIMER0_PERIOD)
+#define bfin_write_TIMER0_PERIOD(val) bfin_write32(TIMER0_PERIOD, val)
+#define bfin_read_TIMER0_WIDTH() bfin_read32(TIMER0_WIDTH)
+#define bfin_write_TIMER0_WIDTH(val) bfin_write32(TIMER0_WIDTH, val)
+#define bfin_read_TIMER1_CONFIG() bfin_read16(TIMER1_CONFIG)
+#define bfin_write_TIMER1_CONFIG(val) bfin_write16(TIMER1_CONFIG, val)
+#define bfin_read_TIMER1_COUNTER() bfin_read32(TIMER1_COUNTER)
+#define bfin_write_TIMER1_COUNTER(val) bfin_write32(TIMER1_COUNTER, val)
+#define bfin_read_TIMER1_PERIOD() bfin_read32(TIMER1_PERIOD)
+#define bfin_write_TIMER1_PERIOD(val) bfin_write32(TIMER1_PERIOD, val)
+#define bfin_read_TIMER1_WIDTH() bfin_read32(TIMER1_WIDTH)
+#define bfin_write_TIMER1_WIDTH(val) bfin_write32(TIMER1_WIDTH, val)
+#define bfin_read_TIMER2_CONFIG() bfin_read16(TIMER2_CONFIG)
+#define bfin_write_TIMER2_CONFIG(val) bfin_write16(TIMER2_CONFIG, val)
+#define bfin_read_TIMER2_COUNTER() bfin_read32(TIMER2_COUNTER)
+#define bfin_write_TIMER2_COUNTER(val) bfin_write32(TIMER2_COUNTER, val)
+#define bfin_read_TIMER2_PERIOD() bfin_read32(TIMER2_PERIOD)
+#define bfin_write_TIMER2_PERIOD(val) bfin_write32(TIMER2_PERIOD, val)
+#define bfin_read_TIMER2_WIDTH() bfin_read32(TIMER2_WIDTH)
+#define bfin_write_TIMER2_WIDTH(val) bfin_write32(TIMER2_WIDTH, val)
+#define bfin_read_TIMER3_CONFIG() bfin_read16(TIMER3_CONFIG)
+#define bfin_write_TIMER3_CONFIG(val) bfin_write16(TIMER3_CONFIG, val)
+#define bfin_read_TIMER3_COUNTER() bfin_read32(TIMER3_COUNTER)
+#define bfin_write_TIMER3_COUNTER(val) bfin_write32(TIMER3_COUNTER, val)
+#define bfin_read_TIMER3_PERIOD() bfin_read32(TIMER3_PERIOD)
+#define bfin_write_TIMER3_PERIOD(val) bfin_write32(TIMER3_PERIOD, val)
+#define bfin_read_TIMER3_WIDTH() bfin_read32(TIMER3_WIDTH)
+#define bfin_write_TIMER3_WIDTH(val) bfin_write32(TIMER3_WIDTH, val)
+#define bfin_read_TIMER4_CONFIG() bfin_read16(TIMER4_CONFIG)
+#define bfin_write_TIMER4_CONFIG(val) bfin_write16(TIMER4_CONFIG, val)
+#define bfin_read_TIMER4_COUNTER() bfin_read32(TIMER4_COUNTER)
+#define bfin_write_TIMER4_COUNTER(val) bfin_write32(TIMER4_COUNTER, val)
+#define bfin_read_TIMER4_PERIOD() bfin_read32(TIMER4_PERIOD)
+#define bfin_write_TIMER4_PERIOD(val) bfin_write32(TIMER4_PERIOD, val)
+#define bfin_read_TIMER4_WIDTH() bfin_read32(TIMER4_WIDTH)
+#define bfin_write_TIMER4_WIDTH(val) bfin_write32(TIMER4_WIDTH, val)
+#define bfin_read_TIMER5_CONFIG() bfin_read16(TIMER5_CONFIG)
+#define bfin_write_TIMER5_CONFIG(val) bfin_write16(TIMER5_CONFIG, val)
+#define bfin_read_TIMER5_COUNTER() bfin_read32(TIMER5_COUNTER)
+#define bfin_write_TIMER5_COUNTER(val) bfin_write32(TIMER5_COUNTER, val)
+#define bfin_read_TIMER5_PERIOD() bfin_read32(TIMER5_PERIOD)
+#define bfin_write_TIMER5_PERIOD(val) bfin_write32(TIMER5_PERIOD, val)
+#define bfin_read_TIMER5_WIDTH() bfin_read32(TIMER5_WIDTH)
+#define bfin_write_TIMER5_WIDTH(val) bfin_write32(TIMER5_WIDTH, val)
+#define bfin_read_TIMER6_CONFIG() bfin_read16(TIMER6_CONFIG)
+#define bfin_write_TIMER6_CONFIG(val) bfin_write16(TIMER6_CONFIG, val)
+#define bfin_read_TIMER6_COUNTER() bfin_read32(TIMER6_COUNTER)
+#define bfin_write_TIMER6_COUNTER(val) bfin_write32(TIMER6_COUNTER, val)
+#define bfin_read_TIMER6_PERIOD() bfin_read32(TIMER6_PERIOD)
+#define bfin_write_TIMER6_PERIOD(val) bfin_write32(TIMER6_PERIOD, val)
+#define bfin_read_TIMER6_WIDTH() bfin_read32(TIMER6_WIDTH)
+#define bfin_write_TIMER6_WIDTH(val) bfin_write32(TIMER6_WIDTH, val)
+#define bfin_read_TIMER7_CONFIG() bfin_read16(TIMER7_CONFIG)
+#define bfin_write_TIMER7_CONFIG(val) bfin_write16(TIMER7_CONFIG, val)
+#define bfin_read_TIMER7_COUNTER() bfin_read32(TIMER7_COUNTER)
+#define bfin_write_TIMER7_COUNTER(val) bfin_write32(TIMER7_COUNTER, val)
+#define bfin_read_TIMER7_PERIOD() bfin_read32(TIMER7_PERIOD)
+#define bfin_write_TIMER7_PERIOD(val) bfin_write32(TIMER7_PERIOD, val)
+#define bfin_read_TIMER7_WIDTH() bfin_read32(TIMER7_WIDTH)
+#define bfin_write_TIMER7_WIDTH(val) bfin_write32(TIMER7_WIDTH, val)
+
+
+
+
+/* Two Wire Interface Registers (TWI0) */
+
+/* SPORT1 Registers */
+
+
+/* SMC Registers */
+#define bfin_read_SMC_GCTL() bfin_read32(SMC_GCTL)
+#define bfin_write_SMC_GCTL(val) bfin_write32(SMC_GCTL, val)
+#define bfin_read_SMC_GSTAT() bfin_read32(SMC_GSTAT)
+#define bfin_read_SMC_B0CTL() bfin_read32(SMC_B0CTL)
+#define bfin_write_SMC_B0CTL(val) bfin_write32(SMC_B0CTL, val)
+#define bfin_read_SMC_B0TIM() bfin_read32(SMC_B0TIM)
+#define bfin_write_SMC_B0TIM(val) bfin_write32(SMC_B0TIM, val)
+#define bfin_read_SMC_B0ETIM() bfin_read32(SMC_B0ETIM)
+#define bfin_write_SMC_B0ETIM(val) bfin_write32(SMC_B0ETIM, val)
+#define bfin_read_SMC_B1CTL() bfin_read32(SMC_B1CTL)
+#define bfin_write_SMC_B1CTL(val) bfin_write32(SMC_B1CTL, val)
+#define bfin_read_SMC_B1TIM() bfin_read32(SMC_B1TIM)
+#define bfin_write_SMC_B1TIM(val) bfin_write32(SMC_B1TIM, val)
+#define bfin_read_SMC_B1ETIM() bfin_read32(SMC_B1ETIM)
+#define bfin_write_SMC_B1ETIM(val) bfin_write32(SMC_B1ETIM, val)
+#define bfin_read_SMC_B2CTL() bfin_read32(SMC_B2CTL)
+#define bfin_write_SMC_B2CTL(val) bfin_write32(SMC_B2CTL, val)
+#define bfin_read_SMC_B2TIM() bfin_read32(SMC_B2TIM)
+#define bfin_write_SMC_B2TIM(val) bfin_write32(SMC_B2TIM, val)
+#define bfin_read_SMC_B2ETIM() bfin_read32(SMC_B2ETIM)
+#define bfin_write_SMC_B2ETIM(val) bfin_write32(SMC_B2ETIM, val)
+#define bfin_read_SMC_B3CTL() bfin_read32(SMC_B3CTL)
+#define bfin_write_SMC_B3CTL(val) bfin_write32(SMC_B3CTL, val)
+#define bfin_read_SMC_B3TIM() bfin_read32(SMC_B3TIM)
+#define bfin_write_SMC_B3TIM(val) bfin_write32(SMC_B3TIM, val)
+#define bfin_read_SMC_B3ETIM() bfin_read32(SMC_B3ETIM)
+#define bfin_write_SMC_B3ETIM(val) bfin_write32(SMC_B3ETIM, val)
+
+/* DDR2 Memory Control Registers */
+#define bfin_read_DMC0_CFG() bfin_read32(DMC0_CFG)
+#define bfin_write_DMC0_CFG(val) bfin_write32(DMC0_CFG, val)
+#define bfin_read_DMC0_TR0() bfin_read32(DMC0_TR0)
+#define bfin_write_DMC0_TR0(val) bfin_write32(DMC0_TR0, val)
+#define bfin_read_DMC0_TR1() bfin_read32(DMC0_TR1)
+#define bfin_write_DMC0_TR1(val) bfin_write32(DMC0_TR1, val)
+#define bfin_read_DMC0_TR2() bfin_read32(DMC0_TR2)
+#define bfin_write_DMC0_TR2(val) bfin_write32(DMC0_TR2, val)
+#define bfin_read_DMC0_MR() bfin_read32(DMC0_MR)
+#define bfin_write_DMC0_MR(val) bfin_write32(DMC0_MR, val)
+#define bfin_read_DMC0_EMR1() bfin_read32(DMC0_EMR1)
+#define bfin_write_DMC0_EMR1(val) bfin_write32(DMC0_EMR1, val)
+#define bfin_read_DMC0_CTL() bfin_read32(DMC0_CTL)
+#define bfin_write_DMC0_CTL(val) bfin_write32(DMC0_CTL, val)
+#define bfin_read_DMC0_STAT() bfin_read32(DMC0_STAT)
+#define bfin_write_DMC0_STAT(val) bfin_write32(DMC0_STAT, val)
+#define bfin_read_DMC0_DLLCTL() bfin_read32(DMC0_DLLCTL)
+#define bfin_write_DMC0_DLLCTL(val) bfin_write32(DMC0_DLLCTL, val)
+
+/* DDR BankRead and Write Count Registers */
+
+
+/* DMA Channel 0 Registers */
+
+#define bfin_read_DMA0_NEXT_DESC_PTR() bfin_read32(DMA0_NEXT_DESC_PTR)
+#define bfin_write_DMA0_NEXT_DESC_PTR(val) bfin_write32(DMA0_NEXT_DESC_PTR, val)
+#define bfin_read_DMA0_START_ADDR() bfin_read32(DMA0_START_ADDR)
+#define bfin_write_DMA0_START_ADDR(val) bfin_write32(DMA0_START_ADDR, val)
+#define bfin_read_DMA0_CONFIG() bfin_read32(DMA0_CONFIG)
+#define bfin_write_DMA0_CONFIG(val) bfin_write32(DMA0_CONFIG, val)
+#define bfin_read_DMA0_X_COUNT() bfin_read32(DMA0_X_COUNT)
+#define bfin_write_DMA0_X_COUNT(val) bfin_write32(DMA0_X_COUNT, val)
+#define bfin_read_DMA0_X_MODIFY() bfin_read32(DMA0_X_MODIFY)
+#define bfin_write_DMA0_X_MODIFY(val) bfin_write32(DMA0_X_MODIFY, val)
+#define bfin_read_DMA0_Y_COUNT() bfin_read32(DMA0_Y_COUNT)
+#define bfin_write_DMA0_Y_COUNT(val) bfin_write32(DMA0_Y_COUNT, val)
+#define bfin_read_DMA0_Y_MODIFY() bfin_read32(DMA0_Y_MODIFY)
+#define bfin_write_DMA0_Y_MODIFY(val) bfin_write32(DMA0_Y_MODIFY, val)
+#define bfin_read_DMA0_CURR_DESC_PTR() bfin_read32(DMA0_CURR_DESC_PTR)
+#define bfin_write_DMA0_CURR_DESC_PTR(val) bfin_write32(DMA0_CURR_DESC_PTR, val)
+#define bfin_read_DMA0_PREV_DESC_PTR() bfin_read32(DMA0_PREV_DESC_PTR)
+#define bfin_write_DMA0_PREV_DESC_PTR(val) bfin_write32(DMA0_PREV_DESC_PTR, val)
+#define bfin_read_DMA0_CURR_ADDR() bfin_read32(DMA0_CURR_ADDR)
+#define bfin_write_DMA0_CURR_ADDR(val) bfin_write32(DMA0_CURR_ADDR, val)
+#define bfin_read_DMA0_IRQ_STATUS() bfin_read32(DMA0_IRQ_STATUS)
+#define bfin_write_DMA0_IRQ_STATUS(val) bfin_write32(DMA0_IRQ_STATUS, val)
+#define bfin_read_DMA0_CURR_X_COUNT() bfin_read32(DMA0_CURR_X_COUNT)
+#define bfin_write_DMA0_CURR_X_COUNT(val) bfin_write32(DMA0_CURR_X_COUNT, val)
+#define bfin_read_DMA0_CURR_Y_COUNT() bfin_read32(DMA0_CURR_Y_COUNT)
+#define bfin_write_DMA0_CURR_Y_COUNT(val) bfin_write32(DMA0_CURR_Y_COUNT, val)
+#define bfin_read_DMA0_BWL_COUNT() bfin_read32(DMA0_BWL_COUNT)
+#define bfin_write_DMA0_BWL_COUNT(val) bfin_write32(DMA0_BWL_COUNT, val)
+#define bfin_read_DMA0_CURR_BWL_COUNT() bfin_read32(DMA0_CURR_BWL_COUNT)
+#define bfin_write_DMA0_CURR_BWL_COUNT(val) bfin_write32(DMA0_CURR_BWL_COUNT, val)
+#define bfin_read_DMA0_BWM_COUNT() bfin_read32(DMA0_BWM_COUNT)
+#define bfin_write_DMA0_BWM_COUNT(val) bfin_write32(DMA0_BWM_COUNT, val)
+#define bfin_read_DMA0_CURR_BWM_COUNT() bfin_read32(DMA0_CURR_BWM_COUNT)
+#define bfin_write_DMA0_CURR_BWM_COUNT(val) bfin_write32(DMA0_CURR_BWM_COUNT, val)
+
+/* DMA Channel 1 Registers */
+
+#define bfin_read_DMA1_NEXT_DESC_PTR() bfin_read32(DMA1_NEXT_DESC_PTR)
+#define bfin_write_DMA1_NEXT_DESC_PTR(val) bfin_write32(DMA1_NEXT_DESC_PTR, val)
+#define bfin_read_DMA1_START_ADDR() bfin_read32(DMA1_START_ADDR)
+#define bfin_write_DMA1_START_ADDR(val) bfin_write32(DMA1_START_ADDR, val)
+#define bfin_read_DMA1_CONFIG() bfin_read32(DMA1_CONFIG)
+#define bfin_write_DMA1_CONFIG(val) bfin_write32(DMA1_CONFIG, val)
+#define bfin_read_DMA1_X_COUNT() bfin_read32(DMA1_X_COUNT)
+#define bfin_write_DMA1_X_COUNT(val) bfin_write32(DMA1_X_COUNT, val)
+#define bfin_read_DMA1_X_MODIFY() bfin_read32(DMA1_X_MODIFY)
+#define bfin_write_DMA1_X_MODIFY(val) bfin_write32(DMA1_X_MODIFY, val)
+#define bfin_read_DMA1_Y_COUNT() bfin_read32(DMA1_Y_COUNT)
+#define bfin_write_DMA1_Y_COUNT(val) bfin_write32(DMA1_Y_COUNT, val)
+#define bfin_read_DMA1_Y_MODIFY() bfin_read32(DMA1_Y_MODIFY)
+#define bfin_write_DMA1_Y_MODIFY(val) bfin_write32(DMA1_Y_MODIFY, val)
+#define bfin_read_DMA1_CURR_DESC_PTR() bfin_read32(DMA1_CURR_DESC_PTR)
+#define bfin_write_DMA1_CURR_DESC_PTR(val) bfin_write32(DMA1_CURR_DESC_PTR, val)
+#define bfin_read_DMA1_PREV_DESC_PTR() bfin_read32(DMA1_PREV_DESC_PTR)
+#define bfin_write_DMA1_PREV_DESC_PTR(val) bfin_write32(DMA1_PREV_DESC_PTR, val)
+#define bfin_read_DMA1_CURR_ADDR() bfin_read32(DMA1_CURR_ADDR)
+#define bfin_write_DMA1_CURR_ADDR(val) bfin_write32(DMA1_CURR_ADDR, val)
+#define bfin_read_DMA1_IRQ_STATUS() bfin_read32(DMA1_IRQ_STATUS)
+#define bfin_write_DMA1_IRQ_STATUS(val) bfin_write32(DMA1_IRQ_STATUS, val)
+#define bfin_read_DMA1_CURR_X_COUNT() bfin_read32(DMA1_CURR_X_COUNT)
+#define bfin_write_DMA1_CURR_X_COUNT(val) bfin_write32(DMA1_CURR_X_COUNT, val)
+#define bfin_read_DMA1_CURR_Y_COUNT() bfin_read32(DMA1_CURR_Y_COUNT)
+#define bfin_write_DMA1_CURR_Y_COUNT(val) bfin_write32(DMA1_CURR_Y_COUNT, val)
+#define bfin_read_DMA1_BWL_COUNT() bfin_read32(DMA1_BWL_COUNT)
+#define bfin_write_DMA1_BWL_COUNT(val) bfin_write32(DMA1_BWL_COUNT, val)
+#define bfin_read_DMA1_CURR_BWL_COUNT() bfin_read32(DMA1_CURR_BWL_COUNT)
+#define bfin_write_DMA1_CURR_BWL_COUNT(val) bfin_write32(DMA1_CURR_BWL_COUNT, val)
+#define bfin_read_DMA1_BWM_COUNT() bfin_read32(DMA1_BWM_COUNT)
+#define bfin_write_DMA1_BWM_COUNT(val) bfin_write32(DMA1_BWM_COUNT, val)
+#define bfin_read_DMA1_CURR_BWM_COUNT() bfin_read32(DMA1_CURR_BWM_COUNT)
+#define bfin_write_DMA1_CURR_BWM_COUNT(val) bfin_write32(DMA1_CURR_BWM_COUNT, val)
+
+/* DMA Channel 2 Registers */
+
+#define bfin_read_DMA2_NEXT_DESC_PTR() bfin_read32(DMA2_NEXT_DESC_PTR)
+#define bfin_write_DMA2_NEXT_DESC_PTR(val) bfin_write32(DMA2_NEXT_DESC_PTR, val)
+#define bfin_read_DMA2_START_ADDR() bfin_read32(DMA2_START_ADDR)
+#define bfin_write_DMA2_START_ADDR(val) bfin_write32(DMA2_START_ADDR, val)
+#define bfin_read_DMA2_CONFIG() bfin_read32(DMA2_CONFIG)
+#define bfin_write_DMA2_CONFIG(val) bfin_write32(DMA2_CONFIG, val)
+#define bfin_read_DMA2_X_COUNT() bfin_read32(DMA2_X_COUNT)
+#define bfin_write_DMA2_X_COUNT(val) bfin_write32(DMA2_X_COUNT, val)
+#define bfin_read_DMA2_X_MODIFY() bfin_read32(DMA2_X_MODIFY)
+#define bfin_write_DMA2_X_MODIFY(val) bfin_write32(DMA2_X_MODIFY, val)
+#define bfin_read_DMA2_Y_COUNT() bfin_read32(DMA2_Y_COUNT)
+#define bfin_write_DMA2_Y_COUNT(val) bfin_write32(DMA2_Y_COUNT, val)
+#define bfin_read_DMA2_Y_MODIFY() bfin_read32(DMA2_Y_MODIFY)
+#define bfin_write_DMA2_Y_MODIFY(val) bfin_write32(DMA2_Y_MODIFY, val)
+#define bfin_read_DMA2_CURR_DESC_PTR() bfin_read32(DMA2_CURR_DESC_PTR)
+#define bfin_write_DMA2_CURR_DESC_PTR(val) bfin_write32(DMA2_CURR_DESC_PTR, val)
+#define bfin_read_DMA2_PREV_DESC_PTR() bfin_read32(DMA2_PREV_DESC_PTR)
+#define bfin_write_DMA2_PREV_DESC_PTR(val) bfin_write32(DMA2_PREV_DESC_PTR, val)
+#define bfin_read_DMA2_CURR_ADDR() bfin_read32(DMA2_CURR_ADDR)
+#define bfin_write_DMA2_CURR_ADDR(val) bfin_write32(DMA2_CURR_ADDR, val)
+#define bfin_read_DMA2_IRQ_STATUS() bfin_read32(DMA2_IRQ_STATUS)
+#define bfin_write_DMA2_IRQ_STATUS(val) bfin_write32(DMA2_IRQ_STATUS, val)
+#define bfin_read_DMA2_CURR_X_COUNT() bfin_read32(DMA2_CURR_X_COUNT)
+#define bfin_write_DMA2_CURR_X_COUNT(val) bfin_write32(DMA2_CURR_X_COUNT, val)
+#define bfin_read_DMA2_CURR_Y_COUNT() bfin_read32(DMA2_CURR_Y_COUNT)
+#define bfin_write_DMA2_CURR_Y_COUNT(val) bfin_write32(DMA2_CURR_Y_COUNT, val)
+#define bfin_read_DMA2_BWL_COUNT() bfin_read32(DMA2_BWL_COUNT)
+#define bfin_write_DMA2_BWL_COUNT(val) bfin_write32(DMA2_BWL_COUNT, val)
+#define bfin_read_DMA2_CURR_BWL_COUNT() bfin_read32(DMA2_CURR_BWL_COUNT)
+#define bfin_write_DMA2_CURR_BWL_COUNT(val) bfin_write32(DMA2_CURR_BWL_COUNT, val)
+#define bfin_read_DMA2_BWM_COUNT() bfin_read32(DMA2_BWM_COUNT)
+#define bfin_write_DMA2_BWM_COUNT(val) bfin_write32(DMA2_BWM_COUNT, val)
+#define bfin_read_DMA2_CURR_BWM_COUNT() bfin_read32(DMA2_CURR_BWM_COUNT)
+#define bfin_write_DMA2_CURR_BWM_COUNT(val) bfin_write32(DMA2_CURR_BWM_COUNT, val)
+
+/* DMA Channel 3 Registers */
+
+#define bfin_read_DMA3_NEXT_DESC_PTR() bfin_read32(DMA3_NEXT_DESC_PTR)
+#define bfin_write_DMA3_NEXT_DESC_PTR(val) bfin_write32(DMA3_NEXT_DESC_PTR, val)
+#define bfin_read_DMA3_START_ADDR() bfin_read32(DMA3_START_ADDR)
+#define bfin_write_DMA3_START_ADDR(val) bfin_write32(DMA3_START_ADDR, val)
+#define bfin_read_DMA3_CONFIG() bfin_read32(DMA3_CONFIG)
+#define bfin_write_DMA3_CONFIG(val) bfin_write32(DMA3_CONFIG, val)
+#define bfin_read_DMA3_X_COUNT() bfin_read32(DMA3_X_COUNT)
+#define bfin_write_DMA3_X_COUNT(val) bfin_write32(DMA3_X_COUNT, val)
+#define bfin_read_DMA3_X_MODIFY() bfin_read32(DMA3_X_MODIFY)
+#define bfin_write_DMA3_X_MODIFY(val) bfin_write32(DMA3_X_MODIFY, val)
+#define bfin_read_DMA3_Y_COUNT() bfin_read32(DMA3_Y_COUNT)
+#define bfin_write_DMA3_Y_COUNT(val) bfin_write32(DMA3_Y_COUNT, val)
+#define bfin_read_DMA3_Y_MODIFY() bfin_read32(DMA3_Y_MODIFY)
+#define bfin_write_DMA3_Y_MODIFY(val) bfin_write32(DMA3_Y_MODIFY, val)
+#define bfin_read_DMA3_CURR_DESC_PTR() bfin_read32(DMA3_CURR_DESC_PTR)
+#define bfin_write_DMA3_CURR_DESC_PTR(val) bfin_write32(DMA3_CURR_DESC_PTR, val)
+#define bfin_read_DMA3_PREV_DESC_PTR() bfin_read32(DMA3_PREV_DESC_PTR)
+#define bfin_write_DMA3_PREV_DESC_PTR(val) bfin_write32(DMA3_PREV_DESC_PTR, val)
+#define bfin_read_DMA3_CURR_ADDR() bfin_read32(DMA3_CURR_ADDR)
+#define bfin_write_DMA3_CURR_ADDR(val) bfin_write32(DMA3_CURR_ADDR, val)
+#define bfin_read_DMA3_IRQ_STATUS() bfin_read32(DMA3_IRQ_STATUS)
+#define bfin_write_DMA3_IRQ_STATUS(val) bfin_write32(DMA3_IRQ_STATUS, val)
+#define bfin_read_DMA3_CURR_X_COUNT() bfin_read32(DMA3_CURR_X_COUNT)
+#define bfin_write_DMA3_CURR_X_COUNT(val) bfin_write32(DMA3_CURR_X_COUNT, val)
+#define bfin_read_DMA3_CURR_Y_COUNT() bfin_read32(DMA3_CURR_Y_COUNT)
+#define bfin_write_DMA3_CURR_Y_COUNT(val) bfin_write32(DMA3_CURR_Y_COUNT, val)
+#define bfin_read_DMA3_BWL_COUNT() bfin_read32(DMA3_BWL_COUNT)
+#define bfin_write_DMA3_BWL_COUNT(val) bfin_write32(DMA3_BWL_COUNT, val)
+#define bfin_read_DMA3_CURR_BWL_COUNT() bfin_read32(DMA3_CURR_BWL_COUNT)
+#define bfin_write_DMA3_CURR_BWL_COUNT(val) bfin_write32(DMA3_CURR_BWL_COUNT, val)
+#define bfin_read_DMA3_BWM_COUNT() bfin_read32(DMA3_BWM_COUNT)
+#define bfin_write_DMA3_BWM_COUNT(val) bfin_write32(DMA3_BWM_COUNT, val)
+#define bfin_read_DMA3_CURR_BWM_COUNT() bfin_read32(DMA3_CURR_BWM_COUNT)
+#define bfin_write_DMA3_CURR_BWM_COUNT(val) bfin_write32(DMA3_CURR_BWM_COUNT, val)
+
+/* DMA Channel 4 Registers */
+
+#define bfin_read_DMA4_NEXT_DESC_PTR() bfin_read32(DMA4_NEXT_DESC_PTR)
+#define bfin_write_DMA4_NEXT_DESC_PTR(val) bfin_write32(DMA4_NEXT_DESC_PTR, val)
+#define bfin_read_DMA4_START_ADDR() bfin_read32(DMA4_START_ADDR)
+#define bfin_write_DMA4_START_ADDR(val) bfin_write32(DMA4_START_ADDR, val)
+#define bfin_read_DMA4_CONFIG() bfin_read32(DMA4_CONFIG)
+#define bfin_write_DMA4_CONFIG(val) bfin_write32(DMA4_CONFIG, val)
+#define bfin_read_DMA4_X_COUNT() bfin_read32(DMA4_X_COUNT)
+#define bfin_write_DMA4_X_COUNT(val) bfin_write32(DMA4_X_COUNT, val)
+#define bfin_read_DMA4_X_MODIFY() bfin_read32(DMA4_X_MODIFY)
+#define bfin_write_DMA4_X_MODIFY(val) bfin_write32(DMA4_X_MODIFY, val)
+#define bfin_read_DMA4_Y_COUNT() bfin_read32(DMA4_Y_COUNT)
+#define bfin_write_DMA4_Y_COUNT(val) bfin_write32(DMA4_Y_COUNT, val)
+#define bfin_read_DMA4_Y_MODIFY() bfin_read32(DMA4_Y_MODIFY)
+#define bfin_write_DMA4_Y_MODIFY(val) bfin_write32(DMA4_Y_MODIFY, val)
+#define bfin_read_DMA4_CURR_DESC_PTR() bfin_read32(DMA4_CURR_DESC_PTR)
+#define bfin_write_DMA4_CURR_DESC_PTR(val) bfin_write32(DMA4_CURR_DESC_PTR, val)
+#define bfin_read_DMA4_PREV_DESC_PTR() bfin_read32(DMA4_PREV_DESC_PTR)
+#define bfin_write_DMA4_PREV_DESC_PTR(val) bfin_write32(DMA4_PREV_DESC_PTR, val)
+#define bfin_read_DMA4_CURR_ADDR() bfin_read32(DMA4_CURR_ADDR)
+#define bfin_write_DMA4_CURR_ADDR(val) bfin_write32(DMA4_CURR_ADDR, val)
+#define bfin_read_DMA4_IRQ_STATUS() bfin_read32(DMA4_IRQ_STATUS)
+#define bfin_write_DMA4_IRQ_STATUS(val) bfin_write32(DMA4_IRQ_STATUS, val)
+#define bfin_read_DMA4_CURR_X_COUNT() bfin_read32(DMA4_CURR_X_COUNT)
+#define bfin_write_DMA4_CURR_X_COUNT(val) bfin_write32(DMA4_CURR_X_COUNT, val)
+#define bfin_read_DMA4_CURR_Y_COUNT() bfin_read32(DMA4_CURR_Y_COUNT)
+#define bfin_write_DMA4_CURR_Y_COUNT(val) bfin_write32(DMA4_CURR_Y_COUNT, val)
+#define bfin_read_DMA4_BWL_COUNT() bfin_read32(DMA4_BWL_COUNT)
+#define bfin_write_DMA4_BWL_COUNT(val) bfin_write32(DMA4_BWL_COUNT, val)
+#define bfin_read_DMA4_CURR_BWL_COUNT() bfin_read32(DMA4_CURR_BWL_COUNT)
+#define bfin_write_DMA4_CURR_BWL_COUNT(val) bfin_write32(DMA4_CURR_BWL_COUNT, val)
+#define bfin_read_DMA4_BWM_COUNT() bfin_read32(DMA4_BWM_COUNT)
+#define bfin_write_DMA4_BWM_COUNT(val) bfin_write32(DMA4_BWM_COUNT, val)
+#define bfin_read_DMA4_CURR_BWM_COUNT() bfin_read32(DMA4_CURR_BWM_COUNT)
+#define bfin_write_DMA4_CURR_BWM_COUNT(val) bfin_write32(DMA4_CURR_BWM_COUNT, val)
+
+/* DMA Channel 5 Registers */
+
+#define bfin_read_DMA5_NEXT_DESC_PTR() bfin_read32(DMA5_NEXT_DESC_PTR)
+#define bfin_write_DMA5_NEXT_DESC_PTR(val) bfin_write32(DMA5_NEXT_DESC_PTR, val)
+#define bfin_read_DMA5_START_ADDR() bfin_read32(DMA5_START_ADDR)
+#define bfin_write_DMA5_START_ADDR(val) bfin_write32(DMA5_START_ADDR, val)
+#define bfin_read_DMA5_CONFIG() bfin_read32(DMA5_CONFIG)
+#define bfin_write_DMA5_CONFIG(val) bfin_write32(DMA5_CONFIG, val)
+#define bfin_read_DMA5_X_COUNT() bfin_read32(DMA5_X_COUNT)
+#define bfin_write_DMA5_X_COUNT(val) bfin_write32(DMA5_X_COUNT, val)
+#define bfin_read_DMA5_X_MODIFY() bfin_read32(DMA5_X_MODIFY)
+#define bfin_write_DMA5_X_MODIFY(val) bfin_write32(DMA5_X_MODIFY, val)
+#define bfin_read_DMA5_Y_COUNT() bfin_read32(DMA5_Y_COUNT)
+#define bfin_write_DMA5_Y_COUNT(val) bfin_write32(DMA5_Y_COUNT, val)
+#define bfin_read_DMA5_Y_MODIFY() bfin_read32(DMA5_Y_MODIFY)
+#define bfin_write_DMA5_Y_MODIFY(val) bfin_write32(DMA5_Y_MODIFY, val)
+#define bfin_read_DMA5_CURR_DESC_PTR() bfin_read32(DMA5_CURR_DESC_PTR)
+#define bfin_write_DMA5_CURR_DESC_PTR(val) bfin_write32(DMA5_CURR_DESC_PTR, val)
+#define bfin_read_DMA5_PREV_DESC_PTR() bfin_read32(DMA5_PREV_DESC_PTR)
+#define bfin_write_DMA5_PREV_DESC_PTR(val) bfin_write32(DMA5_PREV_DESC_PTR, val)
+#define bfin_read_DMA5_CURR_ADDR() bfin_read32(DMA5_CURR_ADDR)
+#define bfin_write_DMA5_CURR_ADDR(val) bfin_write32(DMA5_CURR_ADDR, val)
+#define bfin_read_DMA5_IRQ_STATUS() bfin_read32(DMA5_IRQ_STATUS)
+#define bfin_write_DMA5_IRQ_STATUS(val) bfin_write32(DMA5_IRQ_STATUS, val)
+#define bfin_read_DMA5_CURR_X_COUNT() bfin_read32(DMA5_CURR_X_COUNT)
+#define bfin_write_DMA5_CURR_X_COUNT(val) bfin_write32(DMA5_CURR_X_COUNT, val)
+#define bfin_read_DMA5_CURR_Y_COUNT() bfin_read32(DMA5_CURR_Y_COUNT)
+#define bfin_write_DMA5_CURR_Y_COUNT(val) bfin_write32(DMA5_CURR_Y_COUNT, val)
+#define bfin_read_DMA5_BWL_COUNT() bfin_read32(DMA5_BWL_COUNT)
+#define bfin_write_DMA5_BWL_COUNT(val) bfin_write32(DMA5_BWL_COUNT, val)
+#define bfin_read_DMA5_CURR_BWL_COUNT() bfin_read32(DMA5_CURR_BWL_COUNT)
+#define bfin_write_DMA5_CURR_BWL_COUNT(val) bfin_write32(DMA5_CURR_BWL_COUNT, val)
+#define bfin_read_DMA5_BWM_COUNT() bfin_read32(DMA5_BWM_COUNT)
+#define bfin_write_DMA5_BWM_COUNT(val) bfin_write32(DMA5_BWM_COUNT, val)
+#define bfin_read_DMA5_CURR_BWM_COUNT() bfin_read32(DMA5_CURR_BWM_COUNT)
+#define bfin_write_DMA5_CURR_BWM_COUNT(val) bfin_write32(DMA5_CURR_BWM_COUNT, val)
+
+/* DMA Channel 6 Registers */
+
+#define bfin_read_DMA6_NEXT_DESC_PTR() bfin_read32(DMA6_NEXT_DESC_PTR)
+#define bfin_write_DMA6_NEXT_DESC_PTR(val) bfin_write32(DMA6_NEXT_DESC_PTR, val)
+#define bfin_read_DMA6_START_ADDR() bfin_read32(DMA6_START_ADDR)
+#define bfin_write_DMA6_START_ADDR(val) bfin_write32(DMA6_START_ADDR, val)
+#define bfin_read_DMA6_CONFIG() bfin_read32(DMA6_CONFIG)
+#define bfin_write_DMA6_CONFIG(val) bfin_write32(DMA6_CONFIG, val)
+#define bfin_read_DMA6_X_COUNT() bfin_read32(DMA6_X_COUNT)
+#define bfin_write_DMA6_X_COUNT(val) bfin_write32(DMA6_X_COUNT, val)
+#define bfin_read_DMA6_X_MODIFY() bfin_read32(DMA6_X_MODIFY)
+#define bfin_write_DMA6_X_MODIFY(val) bfin_write32(DMA6_X_MODIFY, val)
+#define bfin_read_DMA6_Y_COUNT() bfin_read32(DMA6_Y_COUNT)
+#define bfin_write_DMA6_Y_COUNT(val) bfin_write32(DMA6_Y_COUNT, val)
+#define bfin_read_DMA6_Y_MODIFY() bfin_read32(DMA6_Y_MODIFY)
+#define bfin_write_DMA6_Y_MODIFY(val) bfin_write32(DMA6_Y_MODIFY, val)
+#define bfin_read_DMA6_CURR_DESC_PTR() bfin_read32(DMA6_CURR_DESC_PTR)
+#define bfin_write_DMA6_CURR_DESC_PTR(val) bfin_write32(DMA6_CURR_DESC_PTR, val)
+#define bfin_read_DMA6_PREV_DESC_PTR() bfin_read32(DMA6_PREV_DESC_PTR)
+#define bfin_write_DMA6_PREV_DESC_PTR(val) bfin_write32(DMA6_PREV_DESC_PTR, val)
+#define bfin_read_DMA6_CURR_ADDR() bfin_read32(DMA6_CURR_ADDR)
+#define bfin_write_DMA6_CURR_ADDR(val) bfin_write32(DMA6_CURR_ADDR, val)
+#define bfin_read_DMA6_IRQ_STATUS() bfin_read32(DMA6_IRQ_STATUS)
+#define bfin_write_DMA6_IRQ_STATUS(val) bfin_write32(DMA6_IRQ_STATUS, val)
+#define bfin_read_DMA6_CURR_X_COUNT() bfin_read32(DMA6_CURR_X_COUNT)
+#define bfin_write_DMA6_CURR_X_COUNT(val) bfin_write32(DMA6_CURR_X_COUNT, val)
+#define bfin_read_DMA6_CURR_Y_COUNT() bfin_read32(DMA6_CURR_Y_COUNT)
+#define bfin_write_DMA6_CURR_Y_COUNT(val) bfin_write32(DMA6_CURR_Y_COUNT, val)
+#define bfin_read_DMA6_BWL_COUNT() bfin_read32(DMA6_BWL_COUNT)
+#define bfin_write_DMA6_BWL_COUNT(val) bfin_write32(DMA6_BWL_COUNT, val)
+#define bfin_read_DMA6_CURR_BWL_COUNT() bfin_read32(DMA6_CURR_BWL_COUNT)
+#define bfin_write_DMA6_CURR_BWL_COUNT(val) bfin_write32(DMA6_CURR_BWL_COUNT, val)
+#define bfin_read_DMA6_BWM_COUNT() bfin_read32(DMA6_BWM_COUNT)
+#define bfin_write_DMA6_BWM_COUNT(val) bfin_write32(DMA6_BWM_COUNT, val)
+#define bfin_read_DMA6_CURR_BWM_COUNT() bfin_read32(DMA6_CURR_BWM_COUNT)
+#define bfin_write_DMA6_CURR_BWM_COUNT(val) bfin_write32(DMA6_CURR_BWM_COUNT, val)
+
+/* DMA Channel 7 Registers */
+
+#define bfin_read_DMA7_NEXT_DESC_PTR() bfin_read32(DMA7_NEXT_DESC_PTR)
+#define bfin_write_DMA7_NEXT_DESC_PTR(val) bfin_write32(DMA7_NEXT_DESC_PTR, val)
+#define bfin_read_DMA7_START_ADDR() bfin_read32(DMA7_START_ADDR)
+#define bfin_write_DMA7_START_ADDR(val) bfin_write32(DMA7_START_ADDR, val)
+#define bfin_read_DMA7_CONFIG() bfin_read32(DMA7_CONFIG)
+#define bfin_write_DMA7_CONFIG(val) bfin_write32(DMA7_CONFIG, val)
+#define bfin_read_DMA7_X_COUNT() bfin_read32(DMA7_X_COUNT)
+#define bfin_write_DMA7_X_COUNT(val) bfin_write32(DMA7_X_COUNT, val)
+#define bfin_read_DMA7_X_MODIFY() bfin_read32(DMA7_X_MODIFY)
+#define bfin_write_DMA7_X_MODIFY(val) bfin_write32(DMA7_X_MODIFY, val)
+#define bfin_read_DMA7_Y_COUNT() bfin_read32(DMA7_Y_COUNT)
+#define bfin_write_DMA7_Y_COUNT(val) bfin_write32(DMA7_Y_COUNT, val)
+#define bfin_read_DMA7_Y_MODIFY() bfin_read32(DMA7_Y_MODIFY)
+#define bfin_write_DMA7_Y_MODIFY(val) bfin_write32(DMA7_Y_MODIFY, val)
+#define bfin_read_DMA7_CURR_DESC_PTR() bfin_read32(DMA7_CURR_DESC_PTR)
+#define bfin_write_DMA7_CURR_DESC_PTR(val) bfin_write32(DMA7_CURR_DESC_PTR, val)
+#define bfin_read_DMA7_PREV_DESC_PTR() bfin_read32(DMA7_PREV_DESC_PTR)
+#define bfin_write_DMA7_PREV_DESC_PTR(val) bfin_write32(DMA7_PREV_DESC_PTR, val)
+#define bfin_read_DMA7_CURR_ADDR() bfin_read32(DMA7_CURR_ADDR)
+#define bfin_write_DMA7_CURR_ADDR(val) bfin_write32(DMA7_CURR_ADDR, val)
+#define bfin_read_DMA7_IRQ_STATUS() bfin_read32(DMA7_IRQ_STATUS)
+#define bfin_write_DMA7_IRQ_STATUS(val) bfin_write32(DMA7_IRQ_STATUS, val)
+#define bfin_read_DMA7_CURR_X_COUNT() bfin_read32(DMA7_CURR_X_COUNT)
+#define bfin_write_DMA7_CURR_X_COUNT(val) bfin_write32(DMA7_CURR_X_COUNT, val)
+#define bfin_read_DMA7_CURR_Y_COUNT() bfin_read32(DMA7_CURR_Y_COUNT)
+#define bfin_write_DMA7_CURR_Y_COUNT(val) bfin_write32(DMA7_CURR_Y_COUNT, val)
+#define bfin_read_DMA7_BWL_COUNT() bfin_read32(DMA7_BWL_COUNT)
+#define bfin_write_DMA7_BWL_COUNT(val) bfin_write32(DMA7_BWL_COUNT, val)
+#define bfin_read_DMA7_CURR_BWL_COUNT() bfin_read32(DMA7_CURR_BWL_COUNT)
+#define bfin_write_DMA7_CURR_BWL_COUNT(val) bfin_write32(DMA7_CURR_BWL_COUNT, val)
+#define bfin_read_DMA7_BWM_COUNT() bfin_read32(DMA7_BWM_COUNT)
+#define bfin_write_DMA7_BWM_COUNT(val) bfin_write32(DMA7_BWM_COUNT, val)
+#define bfin_read_DMA7_CURR_BWM_COUNT() bfin_read32(DMA7_CURR_BWM_COUNT)
+#define bfin_write_DMA7_CURR_BWM_COUNT(val) bfin_write32(DMA7_CURR_BWM_COUNT, val)
+
+/* DMA Channel 8 Registers */
+
+#define bfin_read_DMA8_NEXT_DESC_PTR() bfin_read32(DMA8_NEXT_DESC_PTR)
+#define bfin_write_DMA8_NEXT_DESC_PTR(val) bfin_write32(DMA8_NEXT_DESC_PTR, val)
+#define bfin_read_DMA8_START_ADDR() bfin_read32(DMA8_START_ADDR)
+#define bfin_write_DMA8_START_ADDR(val) bfin_write32(DMA8_START_ADDR, val)
+#define bfin_read_DMA8_CONFIG() bfin_read32(DMA8_CONFIG)
+#define bfin_write_DMA8_CONFIG(val) bfin_write32(DMA8_CONFIG, val)
+#define bfin_read_DMA8_X_COUNT() bfin_read32(DMA8_X_COUNT)
+#define bfin_write_DMA8_X_COUNT(val) bfin_write32(DMA8_X_COUNT, val)
+#define bfin_read_DMA8_X_MODIFY() bfin_read32(DMA8_X_MODIFY)
+#define bfin_write_DMA8_X_MODIFY(val) bfin_write32(DMA8_X_MODIFY, val)
+#define bfin_read_DMA8_Y_COUNT() bfin_read32(DMA8_Y_COUNT)
+#define bfin_write_DMA8_Y_COUNT(val) bfin_write32(DMA8_Y_COUNT, val)
+#define bfin_read_DMA8_Y_MODIFY() bfin_read32(DMA8_Y_MODIFY)
+#define bfin_write_DMA8_Y_MODIFY(val) bfin_write32(DMA8_Y_MODIFY, val)
+#define bfin_read_DMA8_CURR_DESC_PTR() bfin_read32(DMA8_CURR_DESC_PTR)
+#define bfin_write_DMA8_CURR_DESC_PTR(val) bfin_write32(DMA8_CURR_DESC_PTR, val)
+#define bfin_read_DMA8_PREV_DESC_PTR() bfin_read32(DMA8_PREV_DESC_PTR)
+#define bfin_write_DMA8_PREV_DESC_PTR(val) bfin_write32(DMA8_PREV_DESC_PTR, val)
+#define bfin_read_DMA8_CURR_ADDR() bfin_read32(DMA8_CURR_ADDR)
+#define bfin_write_DMA8_CURR_ADDR(val) bfin_write32(DMA8_CURR_ADDR, val)
+#define bfin_read_DMA8_IRQ_STATUS() bfin_read32(DMA8_IRQ_STATUS)
+#define bfin_write_DMA8_IRQ_STATUS(val) bfin_write32(DMA8_IRQ_STATUS, val)
+#define bfin_read_DMA8_CURR_X_COUNT() bfin_read32(DMA8_CURR_X_COUNT)
+#define bfin_write_DMA8_CURR_X_COUNT(val) bfin_write32(DMA8_CURR_X_COUNT, val)
+#define bfin_read_DMA8_CURR_Y_COUNT() bfin_read32(DMA8_CURR_Y_COUNT)
+#define bfin_write_DMA8_CURR_Y_COUNT(val) bfin_write32(DMA8_CURR_Y_COUNT, val)
+#define bfin_read_DMA8_BWL_COUNT() bfin_read32(DMA8_BWL_COUNT)
+#define bfin_write_DMA8_BWL_COUNT(val) bfin_write32(DMA8_BWL_COUNT, val)
+#define bfin_read_DMA8_CURR_BWL_COUNT() bfin_read32(DMA8_CURR_BWL_COUNT)
+#define bfin_write_DMA8_CURR_BWL_COUNT(val) bfin_write32(DMA8_CURR_BWL_COUNT, val)
+#define bfin_read_DMA8_BWM_COUNT() bfin_read32(DMA8_BWM_COUNT)
+#define bfin_write_DMA8_BWM_COUNT(val) bfin_write32(DMA8_BWM_COUNT, val)
+#define bfin_read_DMA8_CURR_BWM_COUNT() bfin_read32(DMA8_CURR_BWM_COUNT)
+#define bfin_write_DMA8_CURR_BWM_COUNT(val) bfin_write32(DMA8_CURR_BWM_COUNT, val)
+
+/* DMA Channel 9 Registers */
+
+#define bfin_read_DMA9_NEXT_DESC_PTR() bfin_read32(DMA9_NEXT_DESC_PTR)
+#define bfin_write_DMA9_NEXT_DESC_PTR(val) bfin_write32(DMA9_NEXT_DESC_PTR, val)
+#define bfin_read_DMA9_START_ADDR() bfin_read32(DMA9_START_ADDR)
+#define bfin_write_DMA9_START_ADDR(val) bfin_write32(DMA9_START_ADDR, val)
+#define bfin_read_DMA9_CONFIG() bfin_read32(DMA9_CONFIG)
+#define bfin_write_DMA9_CONFIG(val) bfin_write32(DMA9_CONFIG, val)
+#define bfin_read_DMA9_X_COUNT() bfin_read32(DMA9_X_COUNT)
+#define bfin_write_DMA9_X_COUNT(val) bfin_write32(DMA9_X_COUNT, val)
+#define bfin_read_DMA9_X_MODIFY() bfin_read32(DMA9_X_MODIFY)
+#define bfin_write_DMA9_X_MODIFY(val) bfin_write32(DMA9_X_MODIFY, val)
+#define bfin_read_DMA9_Y_COUNT() bfin_read32(DMA9_Y_COUNT)
+#define bfin_write_DMA9_Y_COUNT(val) bfin_write32(DMA9_Y_COUNT, val)
+#define bfin_read_DMA9_Y_MODIFY() bfin_read32(DMA9_Y_MODIFY)
+#define bfin_write_DMA9_Y_MODIFY(val) bfin_write32(DMA9_Y_MODIFY, val)
+#define bfin_read_DMA9_CURR_DESC_PTR() bfin_read32(DMA9_CURR_DESC_PTR)
+#define bfin_write_DMA9_CURR_DESC_PTR(val) bfin_write32(DMA9_CURR_DESC_PTR, val)
+#define bfin_read_DMA9_PREV_DESC_PTR() bfin_read32(DMA9_PREV_DESC_PTR)
+#define bfin_write_DMA9_PREV_DESC_PTR(val) bfin_write32(DMA9_PREV_DESC_PTR, val)
+#define bfin_read_DMA9_CURR_ADDR() bfin_read32(DMA9_CURR_ADDR)
+#define bfin_write_DMA9_CURR_ADDR(val) bfin_write32(DMA9_CURR_ADDR, val)
+#define bfin_read_DMA9_IRQ_STATUS() bfin_read32(DMA9_IRQ_STATUS)
+#define bfin_write_DMA9_IRQ_STATUS(val) bfin_write32(DMA9_IRQ_STATUS, val)
+#define bfin_read_DMA9_CURR_X_COUNT() bfin_read32(DMA9_CURR_X_COUNT)
+#define bfin_write_DMA9_CURR_X_COUNT(val) bfin_write32(DMA9_CURR_X_COUNT, val)
+#define bfin_read_DMA9_CURR_Y_COUNT() bfin_read32(DMA9_CURR_Y_COUNT)
+#define bfin_write_DMA9_CURR_Y_COUNT(val) bfin_write32(DMA9_CURR_Y_COUNT, val)
+#define bfin_read_DMA9_BWL_COUNT() bfin_read32(DMA9_BWL_COUNT)
+#define bfin_write_DMA9_BWL_COUNT(val) bfin_write32(DMA9_BWL_COUNT, val)
+#define bfin_read_DMA9_CURR_BWL_COUNT() bfin_read32(DMA9_CURR_BWL_COUNT)
+#define bfin_write_DMA9_CURR_BWL_COUNT(val) bfin_write32(DMA9_CURR_BWL_COUNT, val)
+#define bfin_read_DMA9_BWM_COUNT() bfin_read32(DMA9_BWM_COUNT)
+#define bfin_write_DMA9_BWM_COUNT(val) bfin_write32(DMA9_BWM_COUNT, val)
+#define bfin_read_DMA9_CURR_BWM_COUNT() bfin_read32(DMA9_CURR_BWM_COUNT)
+#define bfin_write_DMA9_CURR_BWM_COUNT(val) bfin_write32(DMA9_CURR_BWM_COUNT, val)
+
+/* DMA Channel 10 Registers */
+
+#define bfin_read_DMA10_NEXT_DESC_PTR() bfin_read32(DMA10_NEXT_DESC_PTR)
+#define bfin_write_DMA10_NEXT_DESC_PTR(val) bfin_write32(DMA10_NEXT_DESC_PTR, val)
+#define bfin_read_DMA10_START_ADDR() bfin_read32(DMA10_START_ADDR)
+#define bfin_write_DMA10_START_ADDR(val) bfin_write32(DMA10_START_ADDR, val)
+#define bfin_read_DMA10_CONFIG() bfin_read32(DMA10_CONFIG)
+#define bfin_write_DMA10_CONFIG(val) bfin_write32(DMA10_CONFIG, val)
+#define bfin_read_DMA10_X_COUNT() bfin_read32(DMA10_X_COUNT)
+#define bfin_write_DMA10_X_COUNT(val) bfin_write32(DMA10_X_COUNT, val)
+#define bfin_read_DMA10_X_MODIFY() bfin_read32(DMA10_X_MODIFY)
+#define bfin_write_DMA10_X_MODIFY(val) bfin_write32(DMA10_X_MODIFY, val)
+#define bfin_read_DMA10_Y_COUNT() bfin_read32(DMA10_Y_COUNT)
+#define bfin_write_DMA10_Y_COUNT(val) bfin_write32(DMA10_Y_COUNT, val)
+#define bfin_read_DMA10_Y_MODIFY() bfin_read32(DMA10_Y_MODIFY)
+#define bfin_write_DMA10_Y_MODIFY(val) bfin_write32(DMA10_Y_MODIFY, val)
+#define bfin_read_DMA10_CURR_DESC_PTR() bfin_read32(DMA10_CURR_DESC_PTR)
+#define bfin_write_DMA10_CURR_DESC_PTR(val) bfin_write32(DMA10_CURR_DESC_PTR, val)
+#define bfin_read_DMA10_PREV_DESC_PTR() bfin_read32(DMA10_PREV_DESC_PTR)
+#define bfin_write_DMA10_PREV_DESC_PTR(val) bfin_write32(DMA10_PREV_DESC_PTR, val)
+#define bfin_read_DMA10_CURR_ADDR() bfin_read32(DMA10_CURR_ADDR)
+#define bfin_write_DMA10_CURR_ADDR(val) bfin_write32(DMA10_CURR_ADDR, val)
+#define bfin_read_DMA10_IRQ_STATUS() bfin_read32(DMA10_IRQ_STATUS)
+#define bfin_write_DMA10_IRQ_STATUS(val) bfin_write32(DMA10_IRQ_STATUS, val)
+#define bfin_read_DMA10_CURR_X_COUNT() bfin_read32(DMA10_CURR_X_COUNT)
+#define bfin_write_DMA10_CURR_X_COUNT(val) bfin_write32(DMA10_CURR_X_COUNT, val)
+#define bfin_read_DMA10_CURR_Y_COUNT() bfin_read32(DMA10_CURR_Y_COUNT)
+#define bfin_write_DMA10_CURR_Y_COUNT(val) bfin_write32(DMA10_CURR_Y_COUNT, val)
+#define bfin_read_DMA10_BWL_COUNT() bfin_read32(DMA10_BWL_COUNT)
+#define bfin_write_DMA10_BWL_COUNT(val) bfin_write32(DMA10_BWL_COUNT, val)
+#define bfin_read_DMA10_CURR_BWL_COUNT() bfin_read32(DMA10_CURR_BWL_COUNT)
+#define bfin_write_DMA10_CURR_BWL_COUNT(val) bfin_write32(DMA10_CURR_BWL_COUNT, val)
+#define bfin_read_DMA10_BWM_COUNT() bfin_read32(DMA10_BWM_COUNT)
+#define bfin_write_DMA10_BWM_COUNT(val) bfin_write32(DMA10_BWM_COUNT, val)
+#define bfin_read_DMA10_CURR_BWM_COUNT() bfin_read32(DMA10_CURR_BWM_COUNT)
+#define bfin_write_DMA10_CURR_BWM_COUNT(val) bfin_write32(DMA10_CURR_BWM_COUNT, val)
+
+/* DMA Channel 11 Registers */
+
+#define bfin_read_DMA11_NEXT_DESC_PTR() bfin_read32(DMA11_NEXT_DESC_PTR)
+#define bfin_write_DMA11_NEXT_DESC_PTR(val) bfin_write32(DMA11_NEXT_DESC_PTR, val)
+#define bfin_read_DMA11_START_ADDR() bfin_read32(DMA11_START_ADDR)
+#define bfin_write_DMA11_START_ADDR(val) bfin_write32(DMA11_START_ADDR, val)
+#define bfin_read_DMA11_CONFIG() bfin_read32(DMA11_CONFIG)
+#define bfin_write_DMA11_CONFIG(val) bfin_write32(DMA11_CONFIG, val)
+#define bfin_read_DMA11_X_COUNT() bfin_read32(DMA11_X_COUNT)
+#define bfin_write_DMA11_X_COUNT(val) bfin_write32(DMA11_X_COUNT, val)
+#define bfin_read_DMA11_X_MODIFY() bfin_read32(DMA11_X_MODIFY)
+#define bfin_write_DMA11_X_MODIFY(val) bfin_write32(DMA11_X_MODIFY, val)
+#define bfin_read_DMA11_Y_COUNT() bfin_read32(DMA11_Y_COUNT)
+#define bfin_write_DMA11_Y_COUNT(val) bfin_write32(DMA11_Y_COUNT, val)
+#define bfin_read_DMA11_Y_MODIFY() bfin_read32(DMA11_Y_MODIFY)
+#define bfin_write_DMA11_Y_MODIFY(val) bfin_write32(DMA11_Y_MODIFY, val)
+#define bfin_read_DMA11_CURR_DESC_PTR() bfin_read32(DMA11_CURR_DESC_PTR)
+#define bfin_write_DMA11_CURR_DESC_PTR(val) bfin_write32(DMA11_CURR_DESC_PTR, val)
+#define bfin_read_DMA11_PREV_DESC_PTR() bfin_read32(DMA11_PREV_DESC_PTR)
+#define bfin_write_DMA11_PREV_DESC_PTR(val) bfin_write32(DMA11_PREV_DESC_PTR, val)
+#define bfin_read_DMA11_CURR_ADDR() bfin_read32(DMA11_CURR_ADDR)
+#define bfin_write_DMA11_CURR_ADDR(val) bfin_write32(DMA11_CURR_ADDR, val)
+#define bfin_read_DMA11_IRQ_STATUS() bfin_read32(DMA11_IRQ_STATUS)
+#define bfin_write_DMA11_IRQ_STATUS(val) bfin_write32(DMA11_IRQ_STATUS, val)
+#define bfin_read_DMA11_CURR_X_COUNT() bfin_read32(DMA11_CURR_X_COUNT)
+#define bfin_write_DMA11_CURR_X_COUNT(val) bfin_write32(DMA11_CURR_X_COUNT, val)
+#define bfin_read_DMA11_CURR_Y_COUNT() bfin_read32(DMA11_CURR_Y_COUNT)
+#define bfin_write_DMA11_CURR_Y_COUNT(val) bfin_write32(DMA11_CURR_Y_COUNT, val)
+#define bfin_read_DMA11_BWL_COUNT() bfin_read32(DMA11_BWL_COUNT)
+#define bfin_write_DMA11_BWL_COUNT(val) bfin_write32(DMA11_BWL_COUNT, val)
+#define bfin_read_DMA11_CURR_BWL_COUNT() bfin_read32(DMA11_CURR_BWL_COUNT)
+#define bfin_write_DMA11_CURR_BWL_COUNT(val) bfin_write32(DMA11_CURR_BWL_COUNT, val)
+#define bfin_read_DMA11_BWM_COUNT() bfin_read32(DMA11_BWM_COUNT)
+#define bfin_write_DMA11_BWM_COUNT(val) bfin_write32(DMA11_BWM_COUNT, val)
+#define bfin_read_DMA11_CURR_BWM_COUNT() bfin_read32(DMA11_CURR_BWM_COUNT)
+#define bfin_write_DMA11_CURR_BWM_COUNT(val) bfin_write32(DMA11_CURR_BWM_COUNT, val)
+
+/* DMA Channel 12 Registers */
+
+#define bfin_read_DMA12_NEXT_DESC_PTR() bfin_read32(DMA12_NEXT_DESC_PTR)
+#define bfin_write_DMA12_NEXT_DESC_PTR(val) bfin_write32(DMA12_NEXT_DESC_PTR, val)
+#define bfin_read_DMA12_START_ADDR() bfin_read32(DMA12_START_ADDR)
+#define bfin_write_DMA12_START_ADDR(val) bfin_write32(DMA12_START_ADDR, val)
+#define bfin_read_DMA12_CONFIG() bfin_read32(DMA12_CONFIG)
+#define bfin_write_DMA12_CONFIG(val) bfin_write32(DMA12_CONFIG, val)
+#define bfin_read_DMA12_X_COUNT() bfin_read32(DMA12_X_COUNT)
+#define bfin_write_DMA12_X_COUNT(val) bfin_write32(DMA12_X_COUNT, val)
+#define bfin_read_DMA12_X_MODIFY() bfin_read32(DMA12_X_MODIFY)
+#define bfin_write_DMA12_X_MODIFY(val) bfin_write32(DMA12_X_MODIFY, val)
+#define bfin_read_DMA12_Y_COUNT() bfin_read32(DMA12_Y_COUNT)
+#define bfin_write_DMA12_Y_COUNT(val) bfin_write32(DMA12_Y_COUNT, val)
+#define bfin_read_DMA12_Y_MODIFY() bfin_read32(DMA12_Y_MODIFY)
+#define bfin_write_DMA12_Y_MODIFY(val) bfin_write32(DMA12_Y_MODIFY, val)
+#define bfin_read_DMA12_CURR_DESC_PTR() bfin_read32(DMA12_CURR_DESC_PTR)
+#define bfin_write_DMA12_CURR_DESC_PTR(val) bfin_write32(DMA12_CURR_DESC_PTR, val)
+#define bfin_read_DMA12_PREV_DESC_PTR() bfin_read32(DMA12_PREV_DESC_PTR)
+#define bfin_write_DMA12_PREV_DESC_PTR(val) bfin_write32(DMA12_PREV_DESC_PTR, val)
+#define bfin_read_DMA12_CURR_ADDR() bfin_read32(DMA12_CURR_ADDR)
+#define bfin_write_DMA12_CURR_ADDR(val) bfin_write32(DMA12_CURR_ADDR, val)
+#define bfin_read_DMA12_IRQ_STATUS() bfin_read32(DMA12_IRQ_STATUS)
+#define bfin_write_DMA12_IRQ_STATUS(val) bfin_write32(DMA12_IRQ_STATUS, val)
+#define bfin_read_DMA12_CURR_X_COUNT() bfin_read32(DMA12_CURR_X_COUNT)
+#define bfin_write_DMA12_CURR_X_COUNT(val) bfin_write32(DMA12_CURR_X_COUNT, val)
+#define bfin_read_DMA12_CURR_Y_COUNT() bfin_read32(DMA12_CURR_Y_COUNT)
+#define bfin_write_DMA12_CURR_Y_COUNT(val) bfin_write32(DMA12_CURR_Y_COUNT, val)
+#define bfin_read_DMA12_BWL_COUNT() bfin_read32(DMA12_BWL_COUNT)
+#define bfin_write_DMA12_BWL_COUNT(val) bfin_write32(DMA12_BWL_COUNT, val)
+#define bfin_read_DMA12_CURR_BWL_COUNT() bfin_read32(DMA12_CURR_BWL_COUNT)
+#define bfin_write_DMA12_CURR_BWL_COUNT(val) bfin_write32(DMA12_CURR_BWL_COUNT, val)
+#define bfin_read_DMA12_BWM_COUNT() bfin_read32(DMA12_BWM_COUNT)
+#define bfin_write_DMA12_BWM_COUNT(val) bfin_write32(DMA12_BWM_COUNT, val)
+#define bfin_read_DMA12_CURR_BWM_COUNT() bfin_read32(DMA12_CURR_BWM_COUNT)
+#define bfin_write_DMA12_CURR_BWM_COUNT(val) bfin_write32(DMA12_CURR_BWM_COUNT, val)
+
+/* DMA Channel 13 Registers */
+
+#define bfin_read_DMA13_NEXT_DESC_PTR() bfin_read32(DMA13_NEXT_DESC_PTR)
+#define bfin_write_DMA13_NEXT_DESC_PTR(val) bfin_write32(DMA13_NEXT_DESC_PTR, val)
+#define bfin_read_DMA13_START_ADDR() bfin_read32(DMA13_START_ADDR)
+#define bfin_write_DMA13_START_ADDR(val) bfin_write32(DMA13_START_ADDR, val)
+#define bfin_read_DMA13_CONFIG() bfin_read32(DMA13_CONFIG)
+#define bfin_write_DMA13_CONFIG(val) bfin_write32(DMA13_CONFIG, val)
+#define bfin_read_DMA13_X_COUNT() bfin_read32(DMA13_X_COUNT)
+#define bfin_write_DMA13_X_COUNT(val) bfin_write32(DMA13_X_COUNT, val)
+#define bfin_read_DMA13_X_MODIFY() bfin_read32(DMA13_X_MODIFY)
+#define bfin_write_DMA13_X_MODIFY(val) bfin_write32(DMA13_X_MODIFY, val)
+#define bfin_read_DMA13_Y_COUNT() bfin_read32(DMA13_Y_COUNT)
+#define bfin_write_DMA13_Y_COUNT(val) bfin_write32(DMA13_Y_COUNT, val)
+#define bfin_read_DMA13_Y_MODIFY() bfin_read32(DMA13_Y_MODIFY)
+#define bfin_write_DMA13_Y_MODIFY(val) bfin_write32(DMA13_Y_MODIFY, val)
+#define bfin_read_DMA13_CURR_DESC_PTR() bfin_read32(DMA13_CURR_DESC_PTR)
+#define bfin_write_DMA13_CURR_DESC_PTR(val) bfin_write32(DMA13_CURR_DESC_PTR, val)
+#define bfin_read_DMA13_PREV_DESC_PTR() bfin_read32(DMA13_PREV_DESC_PTR)
+#define bfin_write_DMA13_PREV_DESC_PTR(val) bfin_write32(DMA13_PREV_DESC_PTR, val)
+#define bfin_read_DMA13_CURR_ADDR() bfin_read32(DMA13_CURR_ADDR)
+#define bfin_write_DMA13_CURR_ADDR(val) bfin_write32(DMA13_CURR_ADDR, val)
+#define bfin_read_DMA13_IRQ_STATUS() bfin_read32(DMA13_IRQ_STATUS)
+#define bfin_write_DMA13_IRQ_STATUS(val) bfin_write32(DMA13_IRQ_STATUS, val)
+#define bfin_read_DMA13_CURR_X_COUNT() bfin_read32(DMA13_CURR_X_COUNT)
+#define bfin_write_DMA13_CURR_X_COUNT(val) bfin_write32(DMA13_CURR_X_COUNT, val)
+#define bfin_read_DMA13_CURR_Y_COUNT() bfin_read32(DMA13_CURR_Y_COUNT)
+#define bfin_write_DMA13_CURR_Y_COUNT(val) bfin_write32(DMA13_CURR_Y_COUNT, val)
+#define bfin_read_DMA13_BWL_COUNT() bfin_read32(DMA13_BWL_COUNT)
+#define bfin_write_DMA13_BWL_COUNT(val) bfin_write32(DMA13_BWL_COUNT, val)
+#define bfin_read_DMA13_CURR_BWL_COUNT() bfin_read32(DMA13_CURR_BWL_COUNT)
+#define bfin_write_DMA13_CURR_BWL_COUNT(val) bfin_write32(DMA13_CURR_BWL_COUNT, val)
+#define bfin_read_DMA13_BWM_COUNT() bfin_read32(DMA13_BWM_COUNT)
+#define bfin_write_DMA13_BWM_COUNT(val) bfin_write32(DMA13_BWM_COUNT, val)
+#define bfin_read_DMA13_CURR_BWM_COUNT() bfin_read32(DMA13_CURR_BWM_COUNT)
+#define bfin_write_DMA13_CURR_BWM_COUNT(val) bfin_write32(DMA13_CURR_BWM_COUNT, val)
+
+/* DMA Channel 14 Registers */
+
+#define bfin_read_DMA14_NEXT_DESC_PTR() bfin_read32(DMA14_NEXT_DESC_PTR)
+#define bfin_write_DMA14_NEXT_DESC_PTR(val) bfin_write32(DMA14_NEXT_DESC_PTR, val)
+#define bfin_read_DMA14_START_ADDR() bfin_read32(DMA14_START_ADDR)
+#define bfin_write_DMA14_START_ADDR(val) bfin_write32(DMA14_START_ADDR, val)
+#define bfin_read_DMA14_CONFIG() bfin_read32(DMA14_CONFIG)
+#define bfin_write_DMA14_CONFIG(val) bfin_write32(DMA14_CONFIG, val)
+#define bfin_read_DMA14_X_COUNT() bfin_read32(DMA14_X_COUNT)
+#define bfin_write_DMA14_X_COUNT(val) bfin_write32(DMA14_X_COUNT, val)
+#define bfin_read_DMA14_X_MODIFY() bfin_read32(DMA14_X_MODIFY)
+#define bfin_write_DMA14_X_MODIFY(val) bfin_write32(DMA14_X_MODIFY, val)
+#define bfin_read_DMA14_Y_COUNT() bfin_read32(DMA14_Y_COUNT)
+#define bfin_write_DMA14_Y_COUNT(val) bfin_write32(DMA14_Y_COUNT, val)
+#define bfin_read_DMA14_Y_MODIFY() bfin_read32(DMA14_Y_MODIFY)
+#define bfin_write_DMA14_Y_MODIFY(val) bfin_write32(DMA14_Y_MODIFY, val)
+#define bfin_read_DMA14_CURR_DESC_PTR() bfin_read32(DMA14_CURR_DESC_PTR)
+#define bfin_write_DMA14_CURR_DESC_PTR(val) bfin_write32(DMA14_CURR_DESC_PTR, val)
+#define bfin_read_DMA14_PREV_DESC_PTR() bfin_read32(DMA14_PREV_DESC_PTR)
+#define bfin_write_DMA14_PREV_DESC_PTR(val) bfin_write32(DMA14_PREV_DESC_PTR, val)
+#define bfin_read_DMA14_CURR_ADDR() bfin_read32(DMA14_CURR_ADDR)
+#define bfin_write_DMA14_CURR_ADDR(val) bfin_write32(DMA14_CURR_ADDR, val)
+#define bfin_read_DMA14_IRQ_STATUS() bfin_read32(DMA14_IRQ_STATUS)
+#define bfin_write_DMA14_IRQ_STATUS(val) bfin_write32(DMA14_IRQ_STATUS, val)
+#define bfin_read_DMA14_CURR_X_COUNT() bfin_read32(DMA14_CURR_X_COUNT)
+#define bfin_write_DMA14_CURR_X_COUNT(val) bfin_write32(DMA14_CURR_X_COUNT, val)
+#define bfin_read_DMA14_CURR_Y_COUNT() bfin_read32(DMA14_CURR_Y_COUNT)
+#define bfin_write_DMA14_CURR_Y_COUNT(val) bfin_write32(DMA14_CURR_Y_COUNT, val)
+#define bfin_read_DMA14_BWL_COUNT() bfin_read32(DMA14_BWL_COUNT)
+#define bfin_write_DMA14_BWL_COUNT(val) bfin_write32(DMA14_BWL_COUNT, val)
+#define bfin_read_DMA14_CURR_BWL_COUNT() bfin_read32(DMA14_CURR_BWL_COUNT)
+#define bfin_write_DMA14_CURR_BWL_COUNT(val) bfin_write32(DMA14_CURR_BWL_COUNT, val)
+#define bfin_read_DMA14_BWM_COUNT() bfin_read32(DMA14_BWM_COUNT)
+#define bfin_write_DMA14_BWM_COUNT(val) bfin_write32(DMA14_BWM_COUNT, val)
+#define bfin_read_DMA14_CURR_BWM_COUNT() bfin_read32(DMA14_CURR_BWM_COUNT)
+#define bfin_write_DMA14_CURR_BWM_COUNT(val) bfin_write32(DMA14_CURR_BWM_COUNT, val)
+
+/* DMA Channel 15 Registers */
+
+#define bfin_read_DMA15_NEXT_DESC_PTR() bfin_read32(DMA15_NEXT_DESC_PTR)
+#define bfin_write_DMA15_NEXT_DESC_PTR(val) bfin_write32(DMA15_NEXT_DESC_PTR, val)
+#define bfin_read_DMA15_START_ADDR() bfin_read32(DMA15_START_ADDR)
+#define bfin_write_DMA15_START_ADDR(val) bfin_write32(DMA15_START_ADDR, val)
+#define bfin_read_DMA15_CONFIG() bfin_read32(DMA15_CONFIG)
+#define bfin_write_DMA15_CONFIG(val) bfin_write32(DMA15_CONFIG, val)
+#define bfin_read_DMA15_X_COUNT() bfin_read32(DMA15_X_COUNT)
+#define bfin_write_DMA15_X_COUNT(val) bfin_write32(DMA15_X_COUNT, val)
+#define bfin_read_DMA15_X_MODIFY() bfin_read32(DMA15_X_MODIFY)
+#define bfin_write_DMA15_X_MODIFY(val) bfin_write32(DMA15_X_MODIFY, val)
+#define bfin_read_DMA15_Y_COUNT() bfin_read32(DMA15_Y_COUNT)
+#define bfin_write_DMA15_Y_COUNT(val) bfin_write32(DMA15_Y_COUNT, val)
+#define bfin_read_DMA15_Y_MODIFY() bfin_read32(DMA15_Y_MODIFY)
+#define bfin_write_DMA15_Y_MODIFY(val) bfin_write32(DMA15_Y_MODIFY, val)
+#define bfin_read_DMA15_CURR_DESC_PTR() bfin_read32(DMA15_CURR_DESC_PTR)
+#define bfin_write_DMA15_CURR_DESC_PTR(val) bfin_write32(DMA15_CURR_DESC_PTR, val)
+#define bfin_read_DMA15_PREV_DESC_PTR() bfin_read32(DMA15_PREV_DESC_PTR)
+#define bfin_write_DMA15_PREV_DESC_PTR(val) bfin_write32(DMA15_PREV_DESC_PTR, val)
+#define bfin_read_DMA15_CURR_ADDR() bfin_read32(DMA15_CURR_ADDR)
+#define bfin_write_DMA15_CURR_ADDR(val) bfin_write32(DMA15_CURR_ADDR, val)
+#define bfin_read_DMA15_IRQ_STATUS() bfin_read32(DMA15_IRQ_STATUS)
+#define bfin_write_DMA15_IRQ_STATUS(val) bfin_write32(DMA15_IRQ_STATUS, val)
+#define bfin_read_DMA15_CURR_X_COUNT() bfin_read32(DMA15_CURR_X_COUNT)
+#define bfin_write_DMA15_CURR_X_COUNT(val) bfin_write32(DMA15_CURR_X_COUNT, val)
+#define bfin_read_DMA15_CURR_Y_COUNT() bfin_read32(DMA15_CURR_Y_COUNT)
+#define bfin_write_DMA15_CURR_Y_COUNT(val) bfin_write32(DMA15_CURR_Y_COUNT, val)
+#define bfin_read_DMA15_BWL_COUNT() bfin_read32(DMA15_BWL_COUNT)
+#define bfin_write_DMA15_BWL_COUNT(val) bfin_write32(DMA15_BWL_COUNT, val)
+#define bfin_read_DMA15_CURR_BWL_COUNT() bfin_read32(DMA15_CURR_BWL_COUNT)
+#define bfin_write_DMA15_CURR_BWL_COUNT(val) bfin_write32(DMA15_CURR_BWL_COUNT, val)
+#define bfin_read_DMA15_BWM_COUNT() bfin_read32(DMA15_BWM_COUNT)
+#define bfin_write_DMA15_BWM_COUNT(val) bfin_write32(DMA15_BWM_COUNT, val)
+#define bfin_read_DMA15_CURR_BWM_COUNT() bfin_read32(DMA15_CURR_BWM_COUNT)
+#define bfin_write_DMA15_CURR_BWM_COUNT(val) bfin_write32(DMA15_CURR_BWM_COUNT, val)
+
+/* DMA Channel 16 Registers */
+
+#define bfin_read_DMA16_NEXT_DESC_PTR() bfin_read32(DMA16_NEXT_DESC_PTR)
+#define bfin_write_DMA16_NEXT_DESC_PTR(val) bfin_write32(DMA16_NEXT_DESC_PTR, val)
+#define bfin_read_DMA16_START_ADDR() bfin_read32(DMA16_START_ADDR)
+#define bfin_write_DMA16_START_ADDR(val) bfin_write32(DMA16_START_ADDR, val)
+#define bfin_read_DMA16_CONFIG() bfin_read32(DMA16_CONFIG)
+#define bfin_write_DMA16_CONFIG(val) bfin_write32(DMA16_CONFIG, val)
+#define bfin_read_DMA16_X_COUNT() bfin_read32(DMA16_X_COUNT)
+#define bfin_write_DMA16_X_COUNT(val) bfin_write32(DMA16_X_COUNT, val)
+#define bfin_read_DMA16_X_MODIFY() bfin_read32(DMA16_X_MODIFY)
+#define bfin_write_DMA16_X_MODIFY(val) bfin_write32(DMA16_X_MODIFY, val)
+#define bfin_read_DMA16_Y_COUNT() bfin_read32(DMA16_Y_COUNT)
+#define bfin_write_DMA16_Y_COUNT(val) bfin_write32(DMA16_Y_COUNT, val)
+#define bfin_read_DMA16_Y_MODIFY() bfin_read32(DMA16_Y_MODIFY)
+#define bfin_write_DMA16_Y_MODIFY(val) bfin_write32(DMA16_Y_MODIFY, val)
+#define bfin_read_DMA16_CURR_DESC_PTR() bfin_read32(DMA16_CURR_DESC_PTR)
+#define bfin_write_DMA16_CURR_DESC_PTR(val) bfin_write32(DMA16_CURR_DESC_PTR, val)
+#define bfin_read_DMA16_PREV_DESC_PTR() bfin_read32(DMA16_PREV_DESC_PTR)
+#define bfin_write_DMA16_PREV_DESC_PTR(val) bfin_write32(DMA16_PREV_DESC_PTR, val)
+#define bfin_read_DMA16_CURR_ADDR() bfin_read32(DMA16_CURR_ADDR)
+#define bfin_write_DMA16_CURR_ADDR(val) bfin_write32(DMA16_CURR_ADDR, val)
+#define bfin_read_DMA16_IRQ_STATUS() bfin_read32(DMA16_IRQ_STATUS)
+#define bfin_write_DMA16_IRQ_STATUS(val) bfin_write32(DMA16_IRQ_STATUS, val)
+#define bfin_read_DMA16_CURR_X_COUNT() bfin_read32(DMA16_CURR_X_COUNT)
+#define bfin_write_DMA16_CURR_X_COUNT(val) bfin_write32(DMA16_CURR_X_COUNT, val)
+#define bfin_read_DMA16_CURR_Y_COUNT() bfin_read32(DMA16_CURR_Y_COUNT)
+#define bfin_write_DMA16_CURR_Y_COUNT(val) bfin_write32(DMA16_CURR_Y_COUNT, val)
+#define bfin_read_DMA16_BWL_COUNT() bfin_read32(DMA16_BWL_COUNT)
+#define bfin_write_DMA16_BWL_COUNT(val) bfin_write32(DMA16_BWL_COUNT, val)
+#define bfin_read_DMA16_CURR_BWL_COUNT() bfin_read32(DMA16_CURR_BWL_COUNT)
+#define bfin_write_DMA16_CURR_BWL_COUNT(val) bfin_write32(DMA16_CURR_BWL_COUNT, val)
+#define bfin_read_DMA16_BWM_COUNT() bfin_read32(DMA16_BWM_COUNT)
+#define bfin_write_DMA16_BWM_COUNT(val) bfin_write32(DMA16_BWM_COUNT, val)
+#define bfin_read_DMA16_CURR_BWM_COUNT() bfin_read32(DMA16_CURR_BWM_COUNT)
+#define bfin_write_DMA16_CURR_BWM_COUNT(val) bfin_write32(DMA16_CURR_BWM_COUNT, val)
+
+/* DMA Channel 17 Registers */
+
+#define bfin_read_DMA17_NEXT_DESC_PTR() bfin_read32(DMA17_NEXT_DESC_PTR)
+#define bfin_write_DMA17_NEXT_DESC_PTR(val) bfin_write32(DMA17_NEXT_DESC_PTR, val)
+#define bfin_read_DMA17_START_ADDR() bfin_read32(DMA17_START_ADDR)
+#define bfin_write_DMA17_START_ADDR(val) bfin_write32(DMA17_START_ADDR, val)
+#define bfin_read_DMA17_CONFIG() bfin_read32(DMA17_CONFIG)
+#define bfin_write_DMA17_CONFIG(val) bfin_write32(DMA17_CONFIG, val)
+#define bfin_read_DMA17_X_COUNT() bfin_read32(DMA17_X_COUNT)
+#define bfin_write_DMA17_X_COUNT(val) bfin_write32(DMA17_X_COUNT, val)
+#define bfin_read_DMA17_X_MODIFY() bfin_read32(DMA17_X_MODIFY)
+#define bfin_write_DMA17_X_MODIFY(val) bfin_write32(DMA17_X_MODIFY, val)
+#define bfin_read_DMA17_Y_COUNT() bfin_read32(DMA17_Y_COUNT)
+#define bfin_write_DMA17_Y_COUNT(val) bfin_write32(DMA17_Y_COUNT, val)
+#define bfin_read_DMA17_Y_MODIFY() bfin_read32(DMA17_Y_MODIFY)
+#define bfin_write_DMA17_Y_MODIFY(val) bfin_write32(DMA17_Y_MODIFY, val)
+#define bfin_read_DMA17_CURR_DESC_PTR() bfin_read32(DMA17_CURR_DESC_PTR)
+#define bfin_write_DMA17_CURR_DESC_PTR(val) bfin_write32(DMA17_CURR_DESC_PTR, val)
+#define bfin_read_DMA17_PREV_DESC_PTR() bfin_read32(DMA17_PREV_DESC_PTR)
+#define bfin_write_DMA17_PREV_DESC_PTR(val) bfin_write32(DMA17_PREV_DESC_PTR, val)
+#define bfin_read_DMA17_CURR_ADDR() bfin_read32(DMA17_CURR_ADDR)
+#define bfin_write_DMA17_CURR_ADDR(val) bfin_write32(DMA17_CURR_ADDR, val)
+#define bfin_read_DMA17_IRQ_STATUS() bfin_read32(DMA17_IRQ_STATUS)
+#define bfin_write_DMA17_IRQ_STATUS(val) bfin_write32(DMA17_IRQ_STATUS, val)
+#define bfin_read_DMA17_CURR_X_COUNT() bfin_read32(DMA17_CURR_X_COUNT)
+#define bfin_write_DMA17_CURR_X_COUNT(val) bfin_write32(DMA17_CURR_X_COUNT, val)
+#define bfin_read_DMA17_CURR_Y_COUNT() bfin_read32(DMA17_CURR_Y_COUNT)
+#define bfin_write_DMA17_CURR_Y_COUNT(val) bfin_write32(DMA17_CURR_Y_COUNT, val)
+#define bfin_read_DMA17_BWL_COUNT() bfin_read32(DMA17_BWL_COUNT)
+#define bfin_write_DMA17_BWL_COUNT(val) bfin_write32(DMA17_BWL_COUNT, val)
+#define bfin_read_DMA17_CURR_BWL_COUNT() bfin_read32(DMA17_CURR_BWL_COUNT)
+#define bfin_write_DMA17_CURR_BWL_COUNT(val) bfin_write32(DMA17_CURR_BWL_COUNT, val)
+#define bfin_read_DMA17_BWM_COUNT() bfin_read32(DMA17_BWM_COUNT)
+#define bfin_write_DMA17_BWM_COUNT(val) bfin_write32(DMA17_BWM_COUNT, val)
+#define bfin_read_DMA17_CURR_BWM_COUNT() bfin_read32(DMA17_CURR_BWM_COUNT)
+#define bfin_write_DMA17_CURR_BWM_COUNT(val) bfin_write32(DMA17_CURR_BWM_COUNT, val)
+
+/* DMA Channel 18 Registers */
+
+#define bfin_read_DMA18_NEXT_DESC_PTR() bfin_read32(DMA18_NEXT_DESC_PTR)
+#define bfin_write_DMA18_NEXT_DESC_PTR(val) bfin_write32(DMA18_NEXT_DESC_PTR, val)
+#define bfin_read_DMA18_START_ADDR() bfin_read32(DMA18_START_ADDR)
+#define bfin_write_DMA18_START_ADDR(val) bfin_write32(DMA18_START_ADDR, val)
+#define bfin_read_DMA18_CONFIG() bfin_read32(DMA18_CONFIG)
+#define bfin_write_DMA18_CONFIG(val) bfin_write32(DMA18_CONFIG, val)
+#define bfin_read_DMA18_X_COUNT() bfin_read32(DMA18_X_COUNT)
+#define bfin_write_DMA18_X_COUNT(val) bfin_write32(DMA18_X_COUNT, val)
+#define bfin_read_DMA18_X_MODIFY() bfin_read32(DMA18_X_MODIFY)
+#define bfin_write_DMA18_X_MODIFY(val) bfin_write32(DMA18_X_MODIFY, val)
+#define bfin_read_DMA18_Y_COUNT() bfin_read32(DMA18_Y_COUNT)
+#define bfin_write_DMA18_Y_COUNT(val) bfin_write32(DMA18_Y_COUNT, val)
+#define bfin_read_DMA18_Y_MODIFY() bfin_read32(DMA18_Y_MODIFY)
+#define bfin_write_DMA18_Y_MODIFY(val) bfin_write32(DMA18_Y_MODIFY, val)
+#define bfin_read_DMA18_CURR_DESC_PTR() bfin_read32(DMA18_CURR_DESC_PTR)
+#define bfin_write_DMA18_CURR_DESC_PTR(val) bfin_write32(DMA18_CURR_DESC_PTR, val)
+#define bfin_read_DMA18_PREV_DESC_PTR() bfin_read32(DMA18_PREV_DESC_PTR)
+#define bfin_write_DMA18_PREV_DESC_PTR(val) bfin_write32(DMA18_PREV_DESC_PTR, val)
+#define bfin_read_DMA18_CURR_ADDR() bfin_read32(DMA18_CURR_ADDR)
+#define bfin_write_DMA18_CURR_ADDR(val) bfin_write32(DMA18_CURR_ADDR, val)
+#define bfin_read_DMA18_IRQ_STATUS() bfin_read32(DMA18_IRQ_STATUS)
+#define bfin_write_DMA18_IRQ_STATUS(val) bfin_write32(DMA18_IRQ_STATUS, val)
+#define bfin_read_DMA18_CURR_X_COUNT() bfin_read32(DMA18_CURR_X_COUNT)
+#define bfin_write_DMA18_CURR_X_COUNT(val) bfin_write32(DMA18_CURR_X_COUNT, val)
+#define bfin_read_DMA18_CURR_Y_COUNT() bfin_read32(DMA18_CURR_Y_COUNT)
+#define bfin_write_DMA18_CURR_Y_COUNT(val) bfin_write32(DMA18_CURR_Y_COUNT, val)
+#define bfin_read_DMA18_BWL_COUNT() bfin_read32(DMA18_BWL_COUNT)
+#define bfin_write_DMA18_BWL_COUNT(val) bfin_write32(DMA18_BWL_COUNT, val)
+#define bfin_read_DMA18_CURR_BWL_COUNT() bfin_read32(DMA18_CURR_BWL_COUNT)
+#define bfin_write_DMA18_CURR_BWL_COUNT(val) bfin_write32(DMA18_CURR_BWL_COUNT, val)
+#define bfin_read_DMA18_BWM_COUNT() bfin_read32(DMA18_BWM_COUNT)
+#define bfin_write_DMA18_BWM_COUNT(val) bfin_write32(DMA18_BWM_COUNT, val)
+#define bfin_read_DMA18_CURR_BWM_COUNT() bfin_read32(DMA18_CURR_BWM_COUNT)
+#define bfin_write_DMA18_CURR_BWM_COUNT(val) bfin_write32(DMA18_CURR_BWM_COUNT, val)
+
+/* DMA Channel 19 Registers */
+
+#define bfin_read_DMA19_NEXT_DESC_PTR() bfin_read32(DMA19_NEXT_DESC_PTR)
+#define bfin_write_DMA19_NEXT_DESC_PTR(val) bfin_write32(DMA19_NEXT_DESC_PTR, val)
+#define bfin_read_DMA19_START_ADDR() bfin_read32(DMA19_START_ADDR)
+#define bfin_write_DMA19_START_ADDR(val) bfin_write32(DMA19_START_ADDR, val)
+#define bfin_read_DMA19_CONFIG() bfin_read32(DMA19_CONFIG)
+#define bfin_write_DMA19_CONFIG(val) bfin_write32(DMA19_CONFIG, val)
+#define bfin_read_DMA19_X_COUNT() bfin_read32(DMA19_X_COUNT)
+#define bfin_write_DMA19_X_COUNT(val) bfin_write32(DMA19_X_COUNT, val)
+#define bfin_read_DMA19_X_MODIFY() bfin_read32(DMA19_X_MODIFY)
+#define bfin_write_DMA19_X_MODIFY(val) bfin_write32(DMA19_X_MODIFY, val)
+#define bfin_read_DMA19_Y_COUNT() bfin_read32(DMA19_Y_COUNT)
+#define bfin_write_DMA19_Y_COUNT(val) bfin_write32(DMA19_Y_COUNT, val)
+#define bfin_read_DMA19_Y_MODIFY() bfin_read32(DMA19_Y_MODIFY)
+#define bfin_write_DMA19_Y_MODIFY(val) bfin_write32(DMA19_Y_MODIFY, val)
+#define bfin_read_DMA19_CURR_DESC_PTR() bfin_read32(DMA19_CURR_DESC_PTR)
+#define bfin_write_DMA19_CURR_DESC_PTR(val) bfin_write32(DMA19_CURR_DESC_PTR, val)
+#define bfin_read_DMA19_PREV_DESC_PTR() bfin_read32(DMA19_PREV_DESC_PTR)
+#define bfin_write_DMA19_PREV_DESC_PTR(val) bfin_write32(DMA19_PREV_DESC_PTR, val)
+#define bfin_read_DMA19_CURR_ADDR() bfin_read32(DMA19_CURR_ADDR)
+#define bfin_write_DMA19_CURR_ADDR(val) bfin_write32(DMA19_CURR_ADDR, val)
+#define bfin_read_DMA19_IRQ_STATUS() bfin_read32(DMA19_IRQ_STATUS)
+#define bfin_write_DMA19_IRQ_STATUS(val) bfin_write32(DMA19_IRQ_STATUS, val)
+#define bfin_read_DMA19_CURR_X_COUNT() bfin_read32(DMA19_CURR_X_COUNT)
+#define bfin_write_DMA19_CURR_X_COUNT(val) bfin_write32(DMA19_CURR_X_COUNT, val)
+#define bfin_read_DMA19_CURR_Y_COUNT() bfin_read32(DMA19_CURR_Y_COUNT)
+#define bfin_write_DMA19_CURR_Y_COUNT(val) bfin_write32(DMA19_CURR_Y_COUNT, val)
+#define bfin_read_DMA19_BWL_COUNT() bfin_read32(DMA19_BWL_COUNT)
+#define bfin_write_DMA19_BWL_COUNT(val) bfin_write32(DMA19_BWL_COUNT, val)
+#define bfin_read_DMA19_CURR_BWL_COUNT() bfin_read32(DMA19_CURR_BWL_COUNT)
+#define bfin_write_DMA19_CURR_BWL_COUNT(val) bfin_write32(DMA19_CURR_BWL_COUNT, val)
+#define bfin_read_DMA19_BWM_COUNT() bfin_read32(DMA19_BWM_COUNT)
+#define bfin_write_DMA19_BWM_COUNT(val) bfin_write32(DMA19_BWM_COUNT, val)
+#define bfin_read_DMA19_CURR_BWM_COUNT() bfin_read32(DMA19_CURR_BWM_COUNT)
+#define bfin_write_DMA19_CURR_BWM_COUNT(val) bfin_write32(DMA19_CURR_BWM_COUNT, val)
+
+/* DMA Channel 20 Registers */
+
+#define bfin_read_DMA20_NEXT_DESC_PTR() bfin_read32(DMA20_NEXT_DESC_PTR)
+#define bfin_write_DMA20_NEXT_DESC_PTR(val) bfin_write32(DMA20_NEXT_DESC_PTR, val)
+#define bfin_read_DMA20_START_ADDR() bfin_read32(DMA20_START_ADDR)
+#define bfin_write_DMA20_START_ADDR(val) bfin_write32(DMA20_START_ADDR, val)
+#define bfin_read_DMA20_CONFIG() bfin_read32(DMA20_CONFIG)
+#define bfin_write_DMA20_CONFIG(val) bfin_write32(DMA20_CONFIG, val)
+#define bfin_read_DMA20_X_COUNT() bfin_read32(DMA20_X_COUNT)
+#define bfin_write_DMA20_X_COUNT(val) bfin_write32(DMA20_X_COUNT, val)
+#define bfin_read_DMA20_X_MODIFY() bfin_read32(DMA20_X_MODIFY)
+#define bfin_write_DMA20_X_MODIFY(val) bfin_write32(DMA20_X_MODIFY, val)
+#define bfin_read_DMA20_Y_COUNT() bfin_read32(DMA20_Y_COUNT)
+#define bfin_write_DMA20_Y_COUNT(val) bfin_write32(DMA20_Y_COUNT, val)
+#define bfin_read_DMA20_Y_MODIFY() bfin_read32(DMA20_Y_MODIFY)
+#define bfin_write_DMA20_Y_MODIFY(val) bfin_write32(DMA20_Y_MODIFY, val)
+#define bfin_read_DMA20_CURR_DESC_PTR() bfin_read32(DMA20_CURR_DESC_PTR)
+#define bfin_write_DMA20_CURR_DESC_PTR(val) bfin_write32(DMA20_CURR_DESC_PTR, val)
+#define bfin_read_DMA20_PREV_DESC_PTR() bfin_read32(DMA20_PREV_DESC_PTR)
+#define bfin_write_DMA20_PREV_DESC_PTR(val) bfin_write32(DMA20_PREV_DESC_PTR, val)
+#define bfin_read_DMA20_CURR_ADDR() bfin_read32(DMA20_CURR_ADDR)
+#define bfin_write_DMA20_CURR_ADDR(val) bfin_write32(DMA20_CURR_ADDR, val)
+#define bfin_read_DMA20_IRQ_STATUS() bfin_read32(DMA20_IRQ_STATUS)
+#define bfin_write_DMA20_IRQ_STATUS(val) bfin_write32(DMA20_IRQ_STATUS, val)
+#define bfin_read_DMA20_CURR_X_COUNT() bfin_read32(DMA20_CURR_X_COUNT)
+#define bfin_write_DMA20_CURR_X_COUNT(val) bfin_write32(DMA20_CURR_X_COUNT, val)
+#define bfin_read_DMA20_CURR_Y_COUNT() bfin_read32(DMA20_CURR_Y_COUNT)
+#define bfin_write_DMA20_CURR_Y_COUNT(val) bfin_write32(DMA20_CURR_Y_COUNT, val)
+#define bfin_read_DMA20_BWL_COUNT() bfin_read32(DMA20_BWL_COUNT)
+#define bfin_write_DMA20_BWL_COUNT(val) bfin_write32(DMA20_BWL_COUNT, val)
+#define bfin_read_DMA20_CURR_BWL_COUNT() bfin_read32(DMA20_CURR_BWL_COUNT)
+#define bfin_write_DMA20_CURR_BWL_COUNT(val) bfin_write32(DMA20_CURR_BWL_COUNT, val)
+#define bfin_read_DMA20_BWM_COUNT() bfin_read32(DMA20_BWM_COUNT)
+#define bfin_write_DMA20_BWM_COUNT(val) bfin_write32(DMA20_BWM_COUNT, val)
+#define bfin_read_DMA20_CURR_BWM_COUNT() bfin_read32(DMA20_CURR_BWM_COUNT)
+#define bfin_write_DMA20_CURR_BWM_COUNT(val) bfin_write32(DMA20_CURR_BWM_COUNT, val)
+
+
+/* MDMA Stream 0 Registers (DMA Channel 21 and 22) */
+
+#define bfin_read_MDMA0_DEST_CRC0_NEXT_DESC_PTR() bfin_read32(MDMA0_DEST_CRC0_NEXT_DESC_PTR)
+#define bfin_write_MDMA0_DEST_CRC0_NEXT_DESC_PTR(val) bfin_write32(MDMA0_DEST_CRC0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA0_DEST_CRC0_START_ADDR() bfin_read32(MDMA0_DEST_CRC0_START_ADDR)
+#define bfin_write_MDMA0_DEST_CRC0_START_ADDR(val) bfin_write32(MDMA0_DEST_CRC0_START_ADDR, val)
+#define bfin_read_MDMA0_DEST_CRC0_CONFIG() bfin_read32(MDMA0_DEST_CRC0_CONFIG)
+#define bfin_write_MDMA0_DEST_CRC0_CONFIG(val) bfin_write32(MDMA0_DEST_CRC0_CONFIG, val)
+#define bfin_read_MDMA0_DEST_CRC0_X_COUNT() bfin_read32(MDMA0_DEST_CRC0_X_COUNT)
+#define bfin_write_MDMA0_DEST_CRC0_X_COUNT(val) bfin_write32(MDMA0_DEST_CRC0_X_COUNT, val)
+#define bfin_read_MDMA0_DEST_CRC0_X_MODIFY() bfin_read32(MDMA0_DEST_CRC0_X_MODIFY)
+#define bfin_write_MDMA0_DEST_CRC0_X_MODIFY(val) bfin_write32(MDMA0_DEST_CRC0_X_MODIFY, val)
+#define bfin_read_MDMA0_DEST_CRC0_Y_COUNT() bfin_read32(MDMA0_DEST_CRC0_Y_COUNT)
+#define bfin_write_MDMA0_DEST_CRC0_Y_COUNT(val) bfin_write32(MDMA0_DEST_CRC0_Y_COUNT, val)
+#define bfin_read_MDMA0_DEST_CRC0_Y_MODIFY() bfin_read32(MDMA0_DEST_CRC0_Y_MODIFY)
+#define bfin_write_MDMA0_DEST_CRC0_Y_MODIFY(val) bfin_write32(MDMA0_DEST_CRC0_Y_MODIFY, val)
+#define bfin_read_MDMA0_DEST_CRC0_CURR_DESC_PTR() bfin_read32(MDMA0_DEST_CRC0_CURR_DESC_PTR)
+#define bfin_write_MDMA0_DEST_CRC0_CURR_DESC_PTR(val) bfin_write32(MDMA0_DEST_CRC0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA0_DEST_CRC0_PREV_DESC_PTR() bfin_read32(MDMA0_DEST_CRC0_PREV_DESC_PTR)
+#define bfin_write_MDMA0_DEST_CRC0_PREV_DESC_PTR(val) bfin_write32(MDMA0_DEST_CRC0_PREV_DESC_PTR, val)
+#define bfin_read_MDMA0_DEST_CRC0_CURR_ADDR() bfin_read32(MDMA0_DEST_CRC0_CURR_ADDR)
+#define bfin_write_MDMA0_DEST_CRC0_CURR_ADDR(val) bfin_write32(MDMA0_DEST_CRC0_CURR_ADDR, val)
+#define bfin_read_MDMA0_DEST_CRC0_IRQ_STATUS() bfin_read32(MDMA0_DEST_CRC0_IRQ_STATUS)
+#define bfin_write_MDMA0_DEST_CRC0_IRQ_STATUS(val) bfin_write32(MDMA0_DEST_CRC0_IRQ_STATUS, val)
+#define bfin_read_MDMA0_DEST_CRC0_CURR_X_COUNT() bfin_read32(MDMA0_DEST_CRC0_CURR_X_COUNT)
+#define bfin_write_MDMA0_DEST_CRC0_CURR_X_COUNT(val) bfin_write32(MDMA0_DEST_CRC0_CURR_X_COUNT, val)
+#define bfin_read_MDMA0_DEST_CRC0_CURR_Y_COUNT() bfin_read32(MDMA0_DEST_CRC0_CURR_Y_COUNT)
+#define bfin_write_MDMA0_DEST_CRC0_CURR_Y_COUNT(val) bfin_write32(MDMA0_DEST_CRC0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA0_SRC_CRC0_NEXT_DESC_PTR() bfin_read32(MDMA0_SRC_CRC0_NEXT_DESC_PTR)
+#define bfin_write_MDMA0_SRC_CRC0_NEXT_DESC_PTR(val) bfin_write32(MDMA0_SRC_CRC0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA0_SRC_CRC0_START_ADDR() bfin_read32(MDMA0_SRC_CRC0_START_ADDR)
+#define bfin_write_MDMA0_SRC_CRC0_START_ADDR(val) bfin_write32(MDMA0_SRC_CRC0_START_ADDR, val)
+#define bfin_read_MDMA0_SRC_CRC0_CONFIG() bfin_read32(MDMA0_SRC_CRC0_CONFIG)
+#define bfin_write_MDMA0_SRC_CRC0_CONFIG(val) bfin_write32(MDMA0_SRC_CRC0_CONFIG, val)
+#define bfin_read_MDMA0_SRC_CRC0_X_COUNT() bfin_read32(MDMA0_SRC_CRC0_X_COUNT)
+#define bfin_write_MDMA0_SRC_CRC0_X_COUNT(val) bfin_write32(MDMA0_SRC_CRC0_X_COUNT, val)
+#define bfin_read_MDMA0_SRC_CRC0_X_MODIFY() bfin_read32(MDMA0_SRC_CRC0_X_MODIFY)
+#define bfin_write_MDMA0_SRC_CRC0_X_MODIFY(val) bfin_write32(MDMA0_SRC_CRC0_X_MODIFY, val)
+#define bfin_read_MDMA0_SRC_CRC0_Y_COUNT() bfin_read32(MDMA0_SRC_CRC0_Y_COUNT)
+#define bfin_write_MDMA0_SRC_CRC0_Y_COUNT(val) bfin_write32(MDMA0_SRC_CRC0_Y_COUNT, val)
+#define bfin_read_MDMA0_SRC_CRC0_Y_MODIFY() bfin_read32(MDMA0_SRC_CRC0_Y_MODIFY)
+#define bfin_write_MDMA0_SRC_CRC0_Y_MODIFY(val) bfin_write32(MDMA0_SRC_CRC0_Y_MODIFY, val)
+#define bfin_read_MDMA0_SRC_CRC0_CURR_DESC_PTR() bfin_read32(MDMA0_SRC_CRC0_CURR_DESC_PTR)
+#define bfin_write_MDMA0_SRC_CRC0_CURR_DESC_PTR(val) bfin_write32(MDMA0_SRC_CRC0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA0_SRC_CRC0_PREV_DESC_PTR() bfin_read32(MDMA0_SRC_CRC0_PREV_DESC_PTR)
+#define bfin_write_MDMA0_SRC_CRC0_PREV_DESC_PTR(val) bfin_write32(MDMA0_SRC_CRC0_PREV_DESC_PTR, val)
+#define bfin_read_MDMA0_SRC_CRC0_CURR_ADDR() bfin_read32(MDMA0_SRC_CRC0_CURR_ADDR)
+#define bfin_write_MDMA0_SRC_CRC0_CURR_ADDR(val) bfin_write32(MDMA0_SRC_CRC0_CURR_ADDR, val)
+#define bfin_read_MDMA0_SRC_CRC0_IRQ_STATUS() bfin_read32(MDMA0_SRC_CRC0_IRQ_STATUS)
+#define bfin_write_MDMA0_SRC_CRC0_IRQ_STATUS(val) bfin_write32(MDMA0_SRC_CRC0_IRQ_STATUS, val)
+#define bfin_read_MDMA0_SRC_CRC0_CURR_X_COUNT() bfin_read32(MDMA0_SRC_CRC0_CURR_X_COUNT)
+#define bfin_write_MDMA0_SRC_CRC0_CURR_X_COUNT(val) bfin_write32(MDMA0_SRC_CRC0_CURR_X_COUNT, val)
+#define bfin_read_MDMA0_SRC_CRC0_CURR_Y_COUNT() bfin_read32(MDMA0_SRC_CRC0_CURR_Y_COUNT)
+#define bfin_write_MDMA0_SRC_CRC0_CURR_Y_COUNT(val) bfin_write32(MDMA0_SRC_CRC0_CURR_Y_COUNT, val)
+
+/* MDMA Stream 1 Registers (DMA Channel 23 and 24) */
+
+#define bfin_read_MDMA1_DEST_CRC1_NEXT_DESC_PTR() bfin_read32(MDMA1_DEST_CRC1_NEXT_DESC_PTR)
+#define bfin_write_MDMA1_DEST_CRC1_NEXT_DESC_PTR(val) bfin_write32(MDMA1_DEST_CRC1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA1_DEST_CRC1_START_ADDR() bfin_read32(MDMA1_DEST_CRC1_START_ADDR)
+#define bfin_write_MDMA1_DEST_CRC1_START_ADDR(val) bfin_write32(MDMA1_DEST_CRC1_START_ADDR, val)
+#define bfin_read_MDMA1_DEST_CRC1_CONFIG() bfin_read32(MDMA1_DEST_CRC1_CONFIG)
+#define bfin_write_MDMA1_DEST_CRC1_CONFIG(val) bfin_write32(MDMA1_DEST_CRC1_CONFIG, val)
+#define bfin_read_MDMA1_DEST_CRC1_X_COUNT() bfin_read32(MDMA1_DEST_CRC1_X_COUNT)
+#define bfin_write_MDMA1_DEST_CRC1_X_COUNT(val) bfin_write32(MDMA1_DEST_CRC1_X_COUNT, val)
+#define bfin_read_MDMA1_DEST_CRC1_X_MODIFY() bfin_read32(MDMA1_DEST_CRC1_X_MODIFY)
+#define bfin_write_MDMA1_DEST_CRC1_X_MODIFY(val) bfin_write32(MDMA1_DEST_CRC1_X_MODIFY, val)
+#define bfin_read_MDMA1_DEST_CRC1_Y_COUNT() bfin_read32(MDMA1_DEST_CRC1_Y_COUNT)
+#define bfin_write_MDMA1_DEST_CRC1_Y_COUNT(val) bfin_write32(MDMA1_DEST_CRC1_Y_COUNT, val)
+#define bfin_read_MDMA1_DEST_CRC1_Y_MODIFY() bfin_read32(MDMA1_DEST_CRC1_Y_MODIFY)
+#define bfin_write_MDMA1_DEST_CRC1_Y_MODIFY(val) bfin_write32(MDMA1_DEST_CRC1_Y_MODIFY, val)
+#define bfin_read_MDMA1_DEST_CRC1_CURR_DESC_PTR() bfin_read32(MDMA1_DEST_CRC1_CURR_DESC_PTR)
+#define bfin_write_MDMA1_DEST_CRC1_CURR_DESC_PTR(val) bfin_write32(MDMA1_DEST_CRC1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA1_DEST_CRC1_PREV_DESC_PTR() bfin_read32(MDMA1_DEST_CRC1_PREV_DESC_PTR)
+#define bfin_write_MDMA1_DEST_CRC1_PREV_DESC_PTR(val) bfin_write32(MDMA1_DEST_CRC1_PREV_DESC_PTR, val)
+#define bfin_read_MDMA1_DEST_CRC1_CURR_ADDR() bfin_read32(MDMA1_DEST_CRC1_CURR_ADDR)
+#define bfin_write_MDMA1_DEST_CRC1_CURR_ADDR(val) bfin_write32(MDMA1_DEST_CRC1_CURR_ADDR, val)
+#define bfin_read_MDMA1_DEST_CRC1_IRQ_STATUS() bfin_read32(MDMA1_DEST_CRC1_IRQ_STATUS)
+#define bfin_write_MDMA1_DEST_CRC1_IRQ_STATUS(val) bfin_write32(MDMA1_DEST_CRC1_IRQ_STATUS, val)
+#define bfin_read_MDMA1_DEST_CRC1_CURR_X_COUNT() bfin_read32(MDMA1_DEST_CRC1_CURR_X_COUNT)
+#define bfin_write_MDMA1_DEST_CRC1_CURR_X_COUNT(val) bfin_write32(MDMA1_DEST_CRC1_CURR_X_COUNT, val)
+#define bfin_read_MDMA1_DEST_CRC1_CURR_Y_COUNT() bfin_read32(MDMA1_DEST_CRC1_CURR_Y_COUNT)
+#define bfin_write_MDMA1_DEST_CRC1_CURR_Y_COUNT(val) bfin_write32(MDMA1_DEST_CRC1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA1_SRC_CRC1_NEXT_DESC_PTR() bfin_read32(MDMA1_SRC_CRC1_NEXT_DESC_PTR)
+#define bfin_write_MDMA1_SRC_CRC1_NEXT_DESC_PTR(val) bfin_write32(MDMA1_SRC_CRC1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA1_SRC_CRC1_START_ADDR() bfin_read32(MDMA1_SRC_CRC1_START_ADDR)
+#define bfin_write_MDMA1_SRC_CRC1_START_ADDR(val) bfin_write32(MDMA1_SRC_CRC1_START_ADDR, val)
+#define bfin_read_MDMA1_SRC_CRC1_CONFIG() bfin_read32(MDMA1_SRC_CRC1_CONFIG)
+#define bfin_write_MDMA1_SRC_CRC1_CONFIG(val) bfin_write32(MDMA1_SRC_CRC1_CONFIG, val)
+#define bfin_read_MDMA1_SRC_CRC1_X_COUNT() bfin_read32(MDMA1_SRC_CRC1_X_COUNT)
+#define bfin_write_MDMA1_SRC_CRC1_X_COUNT(val) bfin_write32(MDMA1_SRC_CRC1_X_COUNT, val)
+#define bfin_read_MDMA1_SRC_CRC1_X_MODIFY() bfin_read32(MDMA1_SRC_CRC1_X_MODIFY)
+#define bfin_write_MDMA1_SRC_CRC1_X_MODIFY(val) bfin_write32(MDMA1_SRC_CRC1_X_MODIFY, val)
+#define bfin_read_MDMA1_SRC_CRC1_Y_COUNT() bfin_read32(MDMA1_SRC_CRC1_Y_COUNT)
+#define bfin_write_MDMA1_SRC_CRC1_Y_COUNT(val) bfin_write32(MDMA1_SRC_CRC1_Y_COUNT, val)
+#define bfin_read_MDMA1_SRC_CRC1_Y_MODIFY() bfin_read32(MDMA1_SRC_CRC1_Y_MODIFY)
+#define bfin_write_MDMA1_SRC_CRC1_Y_MODIFY(val) bfin_write32(MDMA1_SRC_CRC1_Y_MODIFY, val)
+#define bfin_read_MDMA1_SRC_CRC1_CURR_DESC_PTR() bfin_read32(MDMA1_SRC_CRC1_CURR_DESC_PTR)
+#define bfin_write_MDMA1_SRC_CRC1_CURR_DESC_PTR(val) bfin_write32(MDMA1_SRC_CRC1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA1_SRC_CRC1_PREV_DESC_PTR() bfin_read32(MDMA1_SRC_CRC1_PREV_DESC_PTR)
+#define bfin_write_MDMA1_SRC_CRC1_PREV_DESC_PTR(val) bfin_write32(MDMA1_SRC_CRC1_PREV_DESC_PTR, val)
+#define bfin_read_MDMA1_SRC_CRC1_CURR_ADDR() bfin_read32(MDMA1_SRC_CRC1_CURR_ADDR)
+#define bfin_write_MDMA1_SRC_CRC1_CURR_ADDR(val) bfin_write32(MDMA1_SRC_CRC1_CURR_ADDR, val)
+#define bfin_read_MDMA1_SRC_CRC1_IRQ_STATUS() bfin_read32(MDMA1_SRC_CRC1_IRQ_STATUS)
+#define bfin_write_MDMA1_SRC_CRC1_IRQ_STATUS(val) bfin_write32(MDMA1_SRC_CRC1_IRQ_STATUS, val)
+#define bfin_read_MDMA1_SRC_CRC1_CURR_X_COUNT() bfin_read32(MDMA1_SRC_CRC1_CURR_X_COUNT)
+#define bfin_write_MDMA1_SRC_CRC1_CURR_X_COUNT(val) bfin_write32(MDMA1_SRC_CRC1_CURR_X_COUNT, val)
+#define bfin_read_MDMA1_SRC_CRC1_CURR_Y_COUNT() bfin_read32(MDMA1_SRC_CRC1_CURR_Y_COUNT)
+#define bfin_write_MDMA1_SRC_CRC1_CURR_Y_COUNT(val) bfin_write32(MDMA1_SRC_CRC1_CURR_Y_COUNT, val)
+
+
+/* MDMA Stream 2 Registers (DMA Channel 25 and 26) */
+
+#define bfin_read_MDMA2_DEST_NEXT_DESC_PTR() bfin_read32(MDMA2_DEST_NEXT_DESC_PTR)
+#define bfin_write_MDMA2_DEST_NEXT_DESC_PTR(val) bfin_write32(MDMA2_DEST_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA2_DEST_START_ADDR() bfin_read32(MDMA2_DEST_START_ADDR)
+#define bfin_write_MDMA2_DEST_START_ADDR(val) bfin_write32(MDMA2_DEST_START_ADDR, val)
+#define bfin_read_MDMA2_DEST_CONFIG() bfin_read32(MDMA2_DEST_CONFIG)
+#define bfin_write_MDMA2_DEST_CONFIG(val) bfin_write32(MDMA2_DEST_CONFIG, val)
+#define bfin_read_MDMA2_DEST_X_COUNT() bfin_read32(MDMA2_DEST_X_COUNT)
+#define bfin_write_MDMA2_DEST_X_COUNT(val) bfin_write32(MDMA2_DEST_X_COUNT, val)
+#define bfin_read_MDMA2_DEST_X_MODIFY() bfin_read32(MDMA2_DEST_X_MODIFY)
+#define bfin_write_MDMA2_DEST_X_MODIFY(val) bfin_write32(MDMA2_DEST_X_MODIFY, val)
+#define bfin_read_MDMA2_DEST_Y_COUNT() bfin_read32(MDMA2_DEST_Y_COUNT)
+#define bfin_write_MDMA2_DEST_Y_COUNT(val) bfin_write32(MDMA2_DEST_Y_COUNT, val)
+#define bfin_read_MDMA2_DEST_Y_MODIFY() bfin_read32(MDMA2_DEST_Y_MODIFY)
+#define bfin_write_MDMA2_DEST_Y_MODIFY(val) bfin_write32(MDMA2_DEST_Y_MODIFY, val)
+#define bfin_read_MDMA2_DEST_CURR_DESC_PTR() bfin_read32(MDMA2_DEST_CURR_DESC_PTR)
+#define bfin_write_MDMA2_DEST_CURR_DESC_PTR(val) bfin_write32(MDMA2_DEST_CURR_DESC_PTR, val)
+#define bfin_read_MDMA2_DEST_PREV_DESC_PTR() bfin_read32(MDMA2_DEST_PREV_DESC_PTR)
+#define bfin_write_MDMA2_DEST_PREV_DESC_PTR(val) bfin_write32(MDMA2_DEST_PREV_DESC_PTR, val)
+#define bfin_read_MDMA2_DEST_CURR_ADDR() bfin_read32(MDMA2_DEST_CURR_ADDR)
+#define bfin_write_MDMA2_DEST_CURR_ADDR(val) bfin_write32(MDMA2_DEST_CURR_ADDR, val)
+#define bfin_read_MDMA2_DEST_IRQ_STATUS() bfin_read32(MDMA2_DEST_IRQ_STATUS)
+#define bfin_write_MDMA2_DEST_IRQ_STATUS(val) bfin_write32(MDMA2_DEST_IRQ_STATUS, val)
+#define bfin_read_MDMA2_DEST_CURR_X_COUNT() bfin_read32(MDMA2_DEST_CURR_X_COUNT)
+#define bfin_write_MDMA2_DEST_CURR_X_COUNT(val) bfin_write32(MDMA2_DEST_CURR_X_COUNT, val)
+#define bfin_read_MDMA2_DEST_CURR_Y_COUNT() bfin_read32(MDMA2_DEST_CURR_Y_COUNT)
+#define bfin_write_MDMA2_DEST_CURR_Y_COUNT(val) bfin_write32(MDMA2_DEST_CURR_Y_COUNT, val)
+#define bfin_read_MDMA2_SRC_NEXT_DESC_PTR() bfin_read32(MDMA2_SRC_NEXT_DESC_PTR)
+#define bfin_write_MDMA2_SRC_NEXT_DESC_PTR(val) bfin_write32(MDMA2_SRC_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA2_SRC_START_ADDR() bfin_read32(MDMA2_SRC_START_ADDR)
+#define bfin_write_MDMA2_SRC_START_ADDR(val) bfin_write32(MDMA2_SRC_START_ADDR, val)
+#define bfin_read_MDMA2_SRC_CONFIG() bfin_read32(MDMA2_SRC_CONFIG)
+#define bfin_write_MDMA2_SRC_CONFIG(val) bfin_write32(MDMA2_SRC_CONFIG, val)
+#define bfin_read_MDMA2_SRC_X_COUNT() bfin_read32(MDMA2_SRC_X_COUNT)
+#define bfin_write_MDMA2_SRC_X_COUNT(val) bfin_write32(MDMA2_SRC_X_COUNT, val)
+#define bfin_read_MDMA2_SRC_X_MODIFY() bfin_read32(MDMA2_SRC_X_MODIFY)
+#define bfin_write_MDMA2_SRC_X_MODIFY(val) bfin_write32(MDMA2_SRC_X_MODIFY, val)
+#define bfin_read_MDMA2_SRC_Y_COUNT() bfin_read32(MDMA2_SRC_Y_COUNT)
+#define bfin_write_MDMA2_SRC_Y_COUNT(val) bfin_write32(MDMA2_SRC_Y_COUNT, val)
+#define bfin_read_MDMA2_SRC_Y_MODIFY() bfin_read32(MDMA2_SRC_Y_MODIFY)
+#define bfin_write_MDMA2_SRC_Y_MODIFY(val) bfin_write32(MDMA2_SRC_Y_MODIFY, val)
+#define bfin_read_MDMA2_SRC_CURR_DESC_PTR() bfin_read32(MDMA2_SRC_CURR_DESC_PTR)
+#define bfin_write_MDMA2_SRC_CURR_DESC_PTR(val) bfin_write32(MDMA2_SRC_CURR_DESC_PTR, val)
+#define bfin_read_MDMA2_SRC_PREV_DESC_PTR() bfin_read32(MDMA2_SRC_PREV_DESC_PTR)
+#define bfin_write_MDMA2_SRC_PREV_DESC_PTR(val) bfin_write32(MDMA2_SRC_PREV_DESC_PTR, val)
+#define bfin_read_MDMA2_SRC_CURR_ADDR() bfin_read32(MDMA2_SRC_CURR_ADDR)
+#define bfin_write_MDMA2_SRC_CURR_ADDR(val) bfin_write32(MDMA2_SRC_CURR_ADDR, val)
+#define bfin_read_MDMA2_SRC_IRQ_STATUS() bfin_read32(MDMA2_SRC_IRQ_STATUS)
+#define bfin_write_MDMA2_SRC_IRQ_STATUS(val) bfin_write32(MDMA2_SRC_IRQ_STATUS, val)
+#define bfin_read_MDMA2_SRC_CURR_X_COUNT() bfin_read32(MDMA2_SRC_CURR_X_COUNT)
+#define bfin_write_MDMA2_SRC_CURR_X_COUNT(val) bfin_write32(MDMA2_SRC_CURR_X_COUNT, val)
+#define bfin_read_MDMA2_SRC_CURR_Y_COUNT() bfin_read32(MDMA2_SRC_CURR_Y_COUNT)
+#define bfin_write_MDMA2_SRC_CURR_Y_COUNT(val) bfin_write32(MDMA2_SRC_CURR_Y_COUNT, val)
+
+/* MDMA Stream 3 Registers (DMA Channel 27 and 28) */
+
+#define bfin_read_MDMA3_DEST_NEXT_DESC_PTR() bfin_read32(MDMA3_DEST_NEXT_DESC_PTR)
+#define bfin_write_MDMA3_DEST_NEXT_DESC_PTR(val) bfin_write32(MDMA3_DEST_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA3_DEST_START_ADDR() bfin_read32(MDMA3_DEST_START_ADDR)
+#define bfin_write_MDMA3_DEST_START_ADDR(val) bfin_write32(MDMA3_DEST_START_ADDR, val)
+#define bfin_read_MDMA3_DEST_CONFIG() bfin_read32(MDMA3_DEST_CONFIG)
+#define bfin_write_MDMA3_DEST_CONFIG(val) bfin_write32(MDMA3_DEST_CONFIG, val)
+#define bfin_read_MDMA3_DEST_X_COUNT() bfin_read32(MDMA3_DEST_X_COUNT)
+#define bfin_write_MDMA3_DEST_X_COUNT(val) bfin_write32(MDMA3_DEST_X_COUNT, val)
+#define bfin_read_MDMA3_DEST_X_MODIFY() bfin_read32(MDMA3_DEST_X_MODIFY)
+#define bfin_write_MDMA3_DEST_X_MODIFY(val) bfin_write32(MDMA3_DEST_X_MODIFY, val)
+#define bfin_read_MDMA3_DEST_Y_COUNT() bfin_read32(MDMA3_DEST_Y_COUNT)
+#define bfin_write_MDMA3_DEST_Y_COUNT(val) bfin_write32(MDMA3_DEST_Y_COUNT, val)
+#define bfin_read_MDMA3_DEST_Y_MODIFY() bfin_read32(MDMA3_DEST_Y_MODIFY)
+#define bfin_write_MDMA3_DEST_Y_MODIFY(val) bfin_write32(MDMA3_DEST_Y_MODIFY, val)
+#define bfin_read_MDMA3_DEST_CURR_DESC_PTR() bfin_read32(MDMA3_DEST_CURR_DESC_PTR)
+#define bfin_write_MDMA3_DEST_CURR_DESC_PTR(val) bfin_write32(MDMA3_DEST_CURR_DESC_PTR, val)
+#define bfin_read_MDMA3_DEST_PREV_DESC_PTR() bfin_read32(MDMA3_DEST_PREV_DESC_PTR)
+#define bfin_write_MDMA3_DEST_PREV_DESC_PTR(val) bfin_write32(MDMA3_DEST_PREV_DESC_PTR, val)
+#define bfin_read_MDMA3_DEST_CURR_ADDR() bfin_read32(MDMA3_DEST_CURR_ADDR)
+#define bfin_write_MDMA3_DEST_CURR_ADDR(val) bfin_write32(MDMA3_DEST_CURR_ADDR, val)
+#define bfin_read_MDMA3_DEST_IRQ_STATUS() bfin_read32(MDMA3_DEST_IRQ_STATUS)
+#define bfin_write_MDMA3_DEST_IRQ_STATUS(val) bfin_write32(MDMA3_DEST_IRQ_STATUS, val)
+#define bfin_read_MDMA3_DEST_CURR_X_COUNT() bfin_read32(MDMA3_DEST_CURR_X_COUNT)
+#define bfin_write_MDMA3_DEST_CURR_X_COUNT(val) bfin_write32(MDMA3_DEST_CURR_X_COUNT, val)
+#define bfin_read_MDMA3_DEST_CURR_Y_COUNT() bfin_read32(MDMA3_DEST_CURR_Y_COUNT)
+#define bfin_write_MDMA3_DEST_CURR_Y_COUNT(val) bfin_write32(MDMA3_DEST_CURR_Y_COUNT, val)
+#define bfin_read_MDMA3_SRC_NEXT_DESC_PTR() bfin_read32(MDMA3_SRC_NEXT_DESC_PTR)
+#define bfin_write_MDMA3_SRC_NEXT_DESC_PTR(val) bfin_write32(MDMA3_SRC_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA3_SRC_START_ADDR() bfin_read32(MDMA3_SRC_START_ADDR)
+#define bfin_write_MDMA3_SRC_START_ADDR(val) bfin_write32(MDMA3_SRC_START_ADDR, val)
+#define bfin_read_MDMA3_SRC_CONFIG() bfin_read32(MDMA3_SRC_CONFIG)
+#define bfin_write_MDMA3_SRC_CONFIG(val) bfin_write32(MDMA3_SRC_CONFIG, val)
+#define bfin_read_MDMA3_SRC_X_COUNT() bfin_read32(MDMA3_SRC_X_COUNT)
+#define bfin_write_MDMA3_SRC_X_COUNT(val) bfin_write32(MDMA3_SRC_X_COUNT, val)
+#define bfin_read_MDMA3_SRC_X_MODIFY() bfin_read32(MDMA3_SRC_X_MODIFY)
+#define bfin_write_MDMA3_SRC_X_MODIFY(val) bfin_write32(MDMA3_SRC_X_MODIFY, val)
+#define bfin_read_MDMA3_SRC_Y_COUNT() bfin_read32(MDMA3_SRC_Y_COUNT)
+#define bfin_write_MDMA3_SRC_Y_COUNT(val) bfin_write32(MDMA3_SRC_Y_COUNT, val)
+#define bfin_read_MDMA3_SRC_Y_MODIFY() bfin_read32(MDMA3_SRC_Y_MODIFY)
+#define bfin_write_MDMA3_SRC_Y_MODIFY(val) bfin_write32(MDMA3_SRC_Y_MODIFY, val)
+#define bfin_read_MDMA3_SRC_CURR_DESC_PTR() bfin_read32(MDMA3_SRC_CURR_DESC_PTR)
+#define bfin_write_MDMA3_SRC_CURR_DESC_PTR(val) bfin_write32(MDMA3_SRC_CURR_DESC_PTR, val)
+#define bfin_read_MDMA3_SRC_PREV_DESC_PTR() bfin_read32(MDMA3_SRC_PREV_DESC_PTR)
+#define bfin_write_MDMA3_SRC_PREV_DESC_PTR(val) bfin_write32(MDMA3_SRC_PREV_DESC_PTR, val)
+#define bfin_read_MDMA3_SRC_CURR_ADDR() bfin_read32(MDMA3_SRC_CURR_ADDR)
+#define bfin_write_MDMA3_SRC_CURR_ADDR(val) bfin_write32(MDMA3_SRC_CURR_ADDR, val)
+#define bfin_read_MDMA3_SRC_IRQ_STATUS() bfin_read32(MDMA3_SRC_IRQ_STATUS)
+#define bfin_write_MDMA3_SRC_IRQ_STATUS(val) bfin_write32(MDMA3_SRC_IRQ_STATUS, val)
+#define bfin_read_MDMA3_SRC_CURR_X_COUNT() bfin_read32(MDMA3_SRC_CURR_X_COUNT)
+#define bfin_write_MDMA3_SRC_CURR_X_COUNT(val) bfin_write32(MDMA3_SRC_CURR_X_COUNT, val)
+#define bfin_read_MDMA3_SRC_CURR_Y_COUNT() bfin_read32(MDMA3_SRC_CURR_Y_COUNT)
+#define bfin_write_MDMA3_SRC_CURR_Y_COUNT(val) bfin_write32(MDMA3_SRC_CURR_Y_COUNT, val)
+
+
+/* DMA Channel 29 Registers */
+
+#define bfin_read_DMA29_NEXT_DESC_PTR() bfin_read32(DMA29_NEXT_DESC_PTR)
+#define bfin_write_DMA29_NEXT_DESC_PTR(val) bfin_write32(DMA29_NEXT_DESC_PTR, val)
+#define bfin_read_DMA29_START_ADDR() bfin_read32(DMA29_START_ADDR)
+#define bfin_write_DMA29_START_ADDR(val) bfin_write32(DMA29_START_ADDR, val)
+#define bfin_read_DMA29_CONFIG() bfin_read32(DMA29_CONFIG)
+#define bfin_write_DMA29_CONFIG(val) bfin_write32(DMA29_CONFIG, val)
+#define bfin_read_DMA29_X_COUNT() bfin_read32(DMA29_X_COUNT)
+#define bfin_write_DMA29_X_COUNT(val) bfin_write32(DMA29_X_COUNT, val)
+#define bfin_read_DMA29_X_MODIFY() bfin_read32(DMA29_X_MODIFY)
+#define bfin_write_DMA29_X_MODIFY(val) bfin_write32(DMA29_X_MODIFY, val)
+#define bfin_read_DMA29_Y_COUNT() bfin_read32(DMA29_Y_COUNT)
+#define bfin_write_DMA29_Y_COUNT(val) bfin_write32(DMA29_Y_COUNT, val)
+#define bfin_read_DMA29_Y_MODIFY() bfin_read32(DMA29_Y_MODIFY)
+#define bfin_write_DMA29_Y_MODIFY(val) bfin_write32(DMA29_Y_MODIFY, val)
+#define bfin_read_DMA29_CURR_DESC_PTR() bfin_read32(DMA29_CURR_DESC_PTR)
+#define bfin_write_DMA29_CURR_DESC_PTR(val) bfin_write32(DMA29_CURR_DESC_PTR, val)
+#define bfin_read_DMA29_PREV_DESC_PTR() bfin_read32(DMA29_PREV_DESC_PTR)
+#define bfin_write_DMA29_PREV_DESC_PTR(val) bfin_write32(DMA29_PREV_DESC_PTR, val)
+#define bfin_read_DMA29_CURR_ADDR() bfin_read32(DMA29_CURR_ADDR)
+#define bfin_write_DMA29_CURR_ADDR(val) bfin_write32(DMA29_CURR_ADDR, val)
+#define bfin_read_DMA29_IRQ_STATUS() bfin_read32(DMA29_IRQ_STATUS)
+#define bfin_write_DMA29_IRQ_STATUS(val) bfin_write32(DMA29_IRQ_STATUS, val)
+#define bfin_read_DMA29_CURR_X_COUNT() bfin_read32(DMA29_CURR_X_COUNT)
+#define bfin_write_DMA29_CURR_X_COUNT(val) bfin_write32(DMA29_CURR_X_COUNT, val)
+#define bfin_read_DMA29_CURR_Y_COUNT() bfin_read32(DMA29_CURR_Y_COUNT)
+#define bfin_write_DMA29_CURR_Y_COUNT(val) bfin_write32(DMA29_CURR_Y_COUNT, val)
+#define bfin_read_DMA29_BWL_COUNT() bfin_read32(DMA29_BWL_COUNT)
+#define bfin_write_DMA29_BWL_COUNT(val) bfin_write32(DMA29_BWL_COUNT, val)
+#define bfin_read_DMA29_CURR_BWL_COUNT() bfin_read32(DMA29_CURR_BWL_COUNT)
+#define bfin_write_DMA29_CURR_BWL_COUNT(val) bfin_write32(DMA29_CURR_BWL_COUNT, val)
+#define bfin_read_DMA29_BWM_COUNT() bfin_read32(DMA29_BWM_COUNT)
+#define bfin_write_DMA29_BWM_COUNT(val) bfin_write32(DMA29_BWM_COUNT, val)
+#define bfin_read_DMA29_CURR_BWM_COUNT() bfin_read32(DMA29_CURR_BWM_COUNT)
+#define bfin_write_DMA29_CURR_BWM_COUNT(val) bfin_write32(DMA29_CURR_BWM_COUNT, val)
+
+/* DMA Channel 30 Registers */
+
+#define bfin_read_DMA30_NEXT_DESC_PTR() bfin_read32(DMA30_NEXT_DESC_PTR)
+#define bfin_write_DMA30_NEXT_DESC_PTR(val) bfin_write32(DMA30_NEXT_DESC_PTR, val)
+#define bfin_read_DMA30_START_ADDR() bfin_read32(DMA30_START_ADDR)
+#define bfin_write_DMA30_START_ADDR(val) bfin_write32(DMA30_START_ADDR, val)
+#define bfin_read_DMA30_CONFIG() bfin_read32(DMA30_CONFIG)
+#define bfin_write_DMA30_CONFIG(val) bfin_write32(DMA30_CONFIG, val)
+#define bfin_read_DMA30_X_COUNT() bfin_read32(DMA30_X_COUNT)
+#define bfin_write_DMA30_X_COUNT(val) bfin_write32(DMA30_X_COUNT, val)
+#define bfin_read_DMA30_X_MODIFY() bfin_read32(DMA30_X_MODIFY)
+#define bfin_write_DMA30_X_MODIFY(val) bfin_write32(DMA30_X_MODIFY, val)
+#define bfin_read_DMA30_Y_COUNT() bfin_read32(DMA30_Y_COUNT)
+#define bfin_write_DMA30_Y_COUNT(val) bfin_write32(DMA30_Y_COUNT, val)
+#define bfin_read_DMA30_Y_MODIFY() bfin_read32(DMA30_Y_MODIFY)
+#define bfin_write_DMA30_Y_MODIFY(val) bfin_write32(DMA30_Y_MODIFY, val)
+#define bfin_read_DMA30_CURR_DESC_PTR() bfin_read32(DMA30_CURR_DESC_PTR)
+#define bfin_write_DMA30_CURR_DESC_PTR(val) bfin_write32(DMA30_CURR_DESC_PTR, val)
+#define bfin_read_DMA30_PREV_DESC_PTR() bfin_read32(DMA30_PREV_DESC_PTR)
+#define bfin_write_DMA30_PREV_DESC_PTR(val) bfin_write32(DMA30_PREV_DESC_PTR, val)
+#define bfin_read_DMA30_CURR_ADDR() bfin_read32(DMA30_CURR_ADDR)
+#define bfin_write_DMA30_CURR_ADDR(val) bfin_write32(DMA30_CURR_ADDR, val)
+#define bfin_read_DMA30_IRQ_STATUS() bfin_read32(DMA30_IRQ_STATUS)
+#define bfin_write_DMA30_IRQ_STATUS(val) bfin_write32(DMA30_IRQ_STATUS, val)
+#define bfin_read_DMA30_CURR_X_COUNT() bfin_read32(DMA30_CURR_X_COUNT)
+#define bfin_write_DMA30_CURR_X_COUNT(val) bfin_write32(DMA30_CURR_X_COUNT, val)
+#define bfin_read_DMA30_CURR_Y_COUNT() bfin_read32(DMA30_CURR_Y_COUNT)
+#define bfin_write_DMA30_CURR_Y_COUNT(val) bfin_write32(DMA30_CURR_Y_COUNT, val)
+#define bfin_read_DMA30_BWL_COUNT() bfin_read32(DMA30_BWL_COUNT)
+#define bfin_write_DMA30_BWL_COUNT(val) bfin_write32(DMA30_BWL_COUNT, val)
+#define bfin_read_DMA30_CURR_BWL_COUNT() bfin_read32(DMA30_CURR_BWL_COUNT)
+#define bfin_write_DMA30_CURR_BWL_COUNT(val) bfin_write32(DMA30_CURR_BWL_COUNT, val)
+#define bfin_read_DMA30_BWM_COUNT() bfin_read32(DMA30_BWM_COUNT)
+#define bfin_write_DMA30_BWM_COUNT(val) bfin_write32(DMA30_BWM_COUNT, val)
+#define bfin_read_DMA30_CURR_BWM_COUNT() bfin_read32(DMA30_CURR_BWM_COUNT)
+#define bfin_write_DMA30_CURR_BWM_COUNT(val) bfin_write32(DMA30_CURR_BWM_COUNT, val)
+
+/* DMA Channel 31 Registers */
+
+#define bfin_read_DMA31_NEXT_DESC_PTR() bfin_read32(DMA31_NEXT_DESC_PTR)
+#define bfin_write_DMA31_NEXT_DESC_PTR(val) bfin_write32(DMA31_NEXT_DESC_PTR, val)
+#define bfin_read_DMA31_START_ADDR() bfin_read32(DMA31_START_ADDR)
+#define bfin_write_DMA31_START_ADDR(val) bfin_write32(DMA31_START_ADDR, val)
+#define bfin_read_DMA31_CONFIG() bfin_read32(DMA31_CONFIG)
+#define bfin_write_DMA31_CONFIG(val) bfin_write32(DMA31_CONFIG, val)
+#define bfin_read_DMA31_X_COUNT() bfin_read32(DMA31_X_COUNT)
+#define bfin_write_DMA31_X_COUNT(val) bfin_write32(DMA31_X_COUNT, val)
+#define bfin_read_DMA31_X_MODIFY() bfin_read32(DMA31_X_MODIFY)
+#define bfin_write_DMA31_X_MODIFY(val) bfin_write32(DMA31_X_MODIFY, val)
+#define bfin_read_DMA31_Y_COUNT() bfin_read32(DMA31_Y_COUNT)
+#define bfin_write_DMA31_Y_COUNT(val) bfin_write32(DMA31_Y_COUNT, val)
+#define bfin_read_DMA31_Y_MODIFY() bfin_read32(DMA31_Y_MODIFY)
+#define bfin_write_DMA31_Y_MODIFY(val) bfin_write32(DMA31_Y_MODIFY, val)
+#define bfin_read_DMA31_CURR_DESC_PTR() bfin_read32(DMA31_CURR_DESC_PTR)
+#define bfin_write_DMA31_CURR_DESC_PTR(val) bfin_write32(DMA31_CURR_DESC_PTR, val)
+#define bfin_read_DMA31_PREV_DESC_PTR() bfin_read32(DMA31_PREV_DESC_PTR)
+#define bfin_write_DMA31_PREV_DESC_PTR(val) bfin_write32(DMA31_PREV_DESC_PTR, val)
+#define bfin_read_DMA31_CURR_ADDR() bfin_read32(DMA31_CURR_ADDR)
+#define bfin_write_DMA31_CURR_ADDR(val) bfin_write32(DMA31_CURR_ADDR, val)
+#define bfin_read_DMA31_IRQ_STATUS() bfin_read32(DMA31_IRQ_STATUS)
+#define bfin_write_DMA31_IRQ_STATUS(val) bfin_write32(DMA31_IRQ_STATUS, val)
+#define bfin_read_DMA31_CURR_X_COUNT() bfin_read32(DMA31_CURR_X_COUNT)
+#define bfin_write_DMA31_CURR_X_COUNT(val) bfin_write32(DMA31_CURR_X_COUNT, val)
+#define bfin_read_DMA31_CURR_Y_COUNT() bfin_read32(DMA31_CURR_Y_COUNT)
+#define bfin_write_DMA31_CURR_Y_COUNT(val) bfin_write32(DMA31_CURR_Y_COUNT, val)
+#define bfin_read_DMA31_BWL_COUNT() bfin_read32(DMA31_BWL_COUNT)
+#define bfin_write_DMA31_BWL_COUNT(val) bfin_write32(DMA31_BWL_COUNT, val)
+#define bfin_read_DMA31_CURR_BWL_COUNT() bfin_read32(DMA31_CURR_BWL_COUNT)
+#define bfin_write_DMA31_CURR_BWL_COUNT(val) bfin_write32(DMA31_CURR_BWL_COUNT, val)
+#define bfin_read_DMA31_BWM_COUNT() bfin_read32(DMA31_BWM_COUNT)
+#define bfin_write_DMA31_BWM_COUNT(val) bfin_write32(DMA31_BWM_COUNT, val)
+#define bfin_read_DMA31_CURR_BWM_COUNT() bfin_read32(DMA31_CURR_BWM_COUNT)
+#define bfin_write_DMA31_CURR_BWM_COUNT(val) bfin_write32(DMA31_CURR_BWM_COUNT, val)
+
+/* DMA Channel 32 Registers */
+
+#define bfin_read_DMA32_NEXT_DESC_PTR() bfin_read32(DMA32_NEXT_DESC_PTR)
+#define bfin_write_DMA32_NEXT_DESC_PTR(val) bfin_write32(DMA32_NEXT_DESC_PTR, val)
+#define bfin_read_DMA32_START_ADDR() bfin_read32(DMA32_START_ADDR)
+#define bfin_write_DMA32_START_ADDR(val) bfin_write32(DMA32_START_ADDR, val)
+#define bfin_read_DMA32_CONFIG() bfin_read32(DMA32_CONFIG)
+#define bfin_write_DMA32_CONFIG(val) bfin_write32(DMA32_CONFIG, val)
+#define bfin_read_DMA32_X_COUNT() bfin_read32(DMA32_X_COUNT)
+#define bfin_write_DMA32_X_COUNT(val) bfin_write32(DMA32_X_COUNT, val)
+#define bfin_read_DMA32_X_MODIFY() bfin_read32(DMA32_X_MODIFY)
+#define bfin_write_DMA32_X_MODIFY(val) bfin_write32(DMA32_X_MODIFY, val)
+#define bfin_read_DMA32_Y_COUNT() bfin_read32(DMA32_Y_COUNT)
+#define bfin_write_DMA32_Y_COUNT(val) bfin_write32(DMA32_Y_COUNT, val)
+#define bfin_read_DMA32_Y_MODIFY() bfin_read32(DMA32_Y_MODIFY)
+#define bfin_write_DMA32_Y_MODIFY(val) bfin_write32(DMA32_Y_MODIFY, val)
+#define bfin_read_DMA32_CURR_DESC_PTR() bfin_read32(DMA32_CURR_DESC_PTR)
+#define bfin_write_DMA32_CURR_DESC_PTR(val) bfin_write32(DMA32_CURR_DESC_PTR, val)
+#define bfin_read_DMA32_PREV_DESC_PTR() bfin_read32(DMA32_PREV_DESC_PTR)
+#define bfin_write_DMA32_PREV_DESC_PTR(val) bfin_write32(DMA32_PREV_DESC_PTR, val)
+#define bfin_read_DMA32_CURR_ADDR() bfin_read32(DMA32_CURR_ADDR)
+#define bfin_write_DMA32_CURR_ADDR(val) bfin_write32(DMA32_CURR_ADDR, val)
+#define bfin_read_DMA32_IRQ_STATUS() bfin_read32(DMA32_IRQ_STATUS)
+#define bfin_write_DMA32_IRQ_STATUS(val) bfin_write32(DMA32_IRQ_STATUS, val)
+#define bfin_read_DMA32_CURR_X_COUNT() bfin_read32(DMA32_CURR_X_COUNT)
+#define bfin_write_DMA32_CURR_X_COUNT(val) bfin_write32(DMA32_CURR_X_COUNT, val)
+#define bfin_read_DMA32_CURR_Y_COUNT() bfin_read32(DMA32_CURR_Y_COUNT)
+#define bfin_write_DMA32_CURR_Y_COUNT(val) bfin_write32(DMA32_CURR_Y_COUNT, val)
+#define bfin_read_DMA32_BWL_COUNT() bfin_read32(DMA32_BWL_COUNT)
+#define bfin_write_DMA32_BWL_COUNT(val) bfin_write32(DMA32_BWL_COUNT, val)
+#define bfin_read_DMA32_CURR_BWL_COUNT() bfin_read32(DMA32_CURR_BWL_COUNT)
+#define bfin_write_DMA32_CURR_BWL_COUNT(val) bfin_write32(DMA32_CURR_BWL_COUNT, val)
+#define bfin_read_DMA32_BWM_COUNT() bfin_read32(DMA32_BWM_COUNT)
+#define bfin_write_DMA32_BWM_COUNT(val) bfin_write32(DMA32_BWM_COUNT, val)
+#define bfin_read_DMA32_CURR_BWM_COUNT() bfin_read32(DMA32_CURR_BWM_COUNT)
+#define bfin_write_DMA32_CURR_BWM_COUNT(val) bfin_write32(DMA32_CURR_BWM_COUNT, val)
+
+/* DMA Channel 33 Registers */
+
+#define bfin_read_DMA33_NEXT_DESC_PTR() bfin_read32(DMA33_NEXT_DESC_PTR)
+#define bfin_write_DMA33_NEXT_DESC_PTR(val) bfin_write32(DMA33_NEXT_DESC_PTR, val)
+#define bfin_read_DMA33_START_ADDR() bfin_read32(DMA33_START_ADDR)
+#define bfin_write_DMA33_START_ADDR(val) bfin_write32(DMA33_START_ADDR, val)
+#define bfin_read_DMA33_CONFIG() bfin_read32(DMA33_CONFIG)
+#define bfin_write_DMA33_CONFIG(val) bfin_write32(DMA33_CONFIG, val)
+#define bfin_read_DMA33_X_COUNT() bfin_read32(DMA33_X_COUNT)
+#define bfin_write_DMA33_X_COUNT(val) bfin_write32(DMA33_X_COUNT, val)
+#define bfin_read_DMA33_X_MODIFY() bfin_read32(DMA33_X_MODIFY)
+#define bfin_write_DMA33_X_MODIFY(val) bfin_write32(DMA33_X_MODIFY, val)
+#define bfin_read_DMA33_Y_COUNT() bfin_read32(DMA33_Y_COUNT)
+#define bfin_write_DMA33_Y_COUNT(val) bfin_write32(DMA33_Y_COUNT, val)
+#define bfin_read_DMA33_Y_MODIFY() bfin_read32(DMA33_Y_MODIFY)
+#define bfin_write_DMA33_Y_MODIFY(val) bfin_write32(DMA33_Y_MODIFY, val)
+#define bfin_read_DMA33_CURR_DESC_PTR() bfin_read32(DMA33_CURR_DESC_PTR)
+#define bfin_write_DMA33_CURR_DESC_PTR(val) bfin_write32(DMA33_CURR_DESC_PTR, val)
+#define bfin_read_DMA33_PREV_DESC_PTR() bfin_read32(DMA33_PREV_DESC_PTR)
+#define bfin_write_DMA33_PREV_DESC_PTR(val) bfin_write32(DMA33_PREV_DESC_PTR, val)
+#define bfin_read_DMA33_CURR_ADDR() bfin_read32(DMA33_CURR_ADDR)
+#define bfin_write_DMA33_CURR_ADDR(val) bfin_write32(DMA33_CURR_ADDR, val)
+#define bfin_read_DMA33_IRQ_STATUS() bfin_read32(DMA33_IRQ_STATUS)
+#define bfin_write_DMA33_IRQ_STATUS(val) bfin_write32(DMA33_IRQ_STATUS, val)
+#define bfin_read_DMA33_CURR_X_COUNT() bfin_read32(DMA33_CURR_X_COUNT)
+#define bfin_write_DMA33_CURR_X_COUNT(val) bfin_write32(DMA33_CURR_X_COUNT, val)
+#define bfin_read_DMA33_CURR_Y_COUNT() bfin_read32(DMA33_CURR_Y_COUNT)
+#define bfin_write_DMA33_CURR_Y_COUNT(val) bfin_write32(DMA33_CURR_Y_COUNT, val)
+#define bfin_read_DMA33_BWL_COUNT() bfin_read32(DMA33_BWL_COUNT)
+#define bfin_write_DMA33_BWL_COUNT(val) bfin_write32(DMA33_BWL_COUNT, val)
+#define bfin_read_DMA33_CURR_BWL_COUNT() bfin_read32(DMA33_CURR_BWL_COUNT)
+#define bfin_write_DMA33_CURR_BWL_COUNT(val) bfin_write32(DMA33_CURR_BWL_COUNT, val)
+#define bfin_read_DMA33_BWM_COUNT() bfin_read32(DMA33_BWM_COUNT)
+#define bfin_write_DMA33_BWM_COUNT(val) bfin_write32(DMA33_BWM_COUNT, val)
+#define bfin_read_DMA33_CURR_BWM_COUNT() bfin_read32(DMA33_CURR_BWM_COUNT)
+#define bfin_write_DMA33_CURR_BWM_COUNT(val) bfin_write32(DMA33_CURR_BWM_COUNT, val)
+
+/* DMA Channel 34 Registers */
+
+#define bfin_read_DMA34_NEXT_DESC_PTR() bfin_read32(DMA34_NEXT_DESC_PTR)
+#define bfin_write_DMA34_NEXT_DESC_PTR(val) bfin_write32(DMA34_NEXT_DESC_PTR, val)
+#define bfin_read_DMA34_START_ADDR() bfin_read32(DMA34_START_ADDR)
+#define bfin_write_DMA34_START_ADDR(val) bfin_write32(DMA34_START_ADDR, val)
+#define bfin_read_DMA34_CONFIG() bfin_read32(DMA34_CONFIG)
+#define bfin_write_DMA34_CONFIG(val) bfin_write32(DMA34_CONFIG, val)
+#define bfin_read_DMA34_X_COUNT() bfin_read32(DMA34_X_COUNT)
+#define bfin_write_DMA34_X_COUNT(val) bfin_write32(DMA34_X_COUNT, val)
+#define bfin_read_DMA34_X_MODIFY() bfin_read32(DMA34_X_MODIFY)
+#define bfin_write_DMA34_X_MODIFY(val) bfin_write32(DMA34_X_MODIFY, val)
+#define bfin_read_DMA34_Y_COUNT() bfin_read32(DMA34_Y_COUNT)
+#define bfin_write_DMA34_Y_COUNT(val) bfin_write32(DMA34_Y_COUNT, val)
+#define bfin_read_DMA34_Y_MODIFY() bfin_read32(DMA34_Y_MODIFY)
+#define bfin_write_DMA34_Y_MODIFY(val) bfin_write32(DMA34_Y_MODIFY, val)
+#define bfin_read_DMA34_CURR_DESC_PTR() bfin_read32(DMA34_CURR_DESC_PTR)
+#define bfin_write_DMA34_CURR_DESC_PTR(val) bfin_write32(DMA34_CURR_DESC_PTR, val)
+#define bfin_read_DMA34_PREV_DESC_PTR() bfin_read32(DMA34_PREV_DESC_PTR)
+#define bfin_write_DMA34_PREV_DESC_PTR(val) bfin_write32(DMA34_PREV_DESC_PTR, val)
+#define bfin_read_DMA34_CURR_ADDR() bfin_read32(DMA34_CURR_ADDR)
+#define bfin_write_DMA34_CURR_ADDR(val) bfin_write32(DMA34_CURR_ADDR, val)
+#define bfin_read_DMA34_IRQ_STATUS() bfin_read32(DMA34_IRQ_STATUS)
+#define bfin_write_DMA34_IRQ_STATUS(val) bfin_write32(DMA34_IRQ_STATUS, val)
+#define bfin_read_DMA34_CURR_X_COUNT() bfin_read32(DMA34_CURR_X_COUNT)
+#define bfin_write_DMA34_CURR_X_COUNT(val) bfin_write32(DMA34_CURR_X_COUNT, val)
+#define bfin_read_DMA34_CURR_Y_COUNT() bfin_read32(DMA34_CURR_Y_COUNT)
+#define bfin_write_DMA34_CURR_Y_COUNT(val) bfin_write32(DMA34_CURR_Y_COUNT, val)
+#define bfin_read_DMA34_BWL_COUNT() bfin_read32(DMA34_BWL_COUNT)
+#define bfin_write_DMA34_BWL_COUNT(val) bfin_write32(DMA34_BWL_COUNT, val)
+#define bfin_read_DMA34_CURR_BWL_COUNT() bfin_read32(DMA34_CURR_BWL_COUNT)
+#define bfin_write_DMA34_CURR_BWL_COUNT(val) bfin_write32(DMA34_CURR_BWL_COUNT, val)
+#define bfin_read_DMA34_BWM_COUNT() bfin_read32(DMA34_BWM_COUNT)
+#define bfin_write_DMA34_BWM_COUNT(val) bfin_write32(DMA34_BWM_COUNT, val)
+#define bfin_read_DMA34_CURR_BWM_COUNT() bfin_read32(DMA34_CURR_BWM_COUNT)
+#define bfin_write_DMA34_CURR_BWM_COUNT(val) bfin_write32(DMA34_CURR_BWM_COUNT, val)
+
+/* DMA Channel 35 Registers */
+
+#define bfin_read_DMA35_NEXT_DESC_PTR() bfin_read32(DMA35_NEXT_DESC_PTR)
+#define bfin_write_DMA35_NEXT_DESC_PTR(val) bfin_write32(DMA35_NEXT_DESC_PTR, val)
+#define bfin_read_DMA35_START_ADDR() bfin_read32(DMA35_START_ADDR)
+#define bfin_write_DMA35_START_ADDR(val) bfin_write32(DMA35_START_ADDR, val)
+#define bfin_read_DMA35_CONFIG() bfin_read32(DMA35_CONFIG)
+#define bfin_write_DMA35_CONFIG(val) bfin_write32(DMA35_CONFIG, val)
+#define bfin_read_DMA35_X_COUNT() bfin_read32(DMA35_X_COUNT)
+#define bfin_write_DMA35_X_COUNT(val) bfin_write32(DMA35_X_COUNT, val)
+#define bfin_read_DMA35_X_MODIFY() bfin_read32(DMA35_X_MODIFY)
+#define bfin_write_DMA35_X_MODIFY(val) bfin_write32(DMA35_X_MODIFY, val)
+#define bfin_read_DMA35_Y_COUNT() bfin_read32(DMA35_Y_COUNT)
+#define bfin_write_DMA35_Y_COUNT(val) bfin_write32(DMA35_Y_COUNT, val)
+#define bfin_read_DMA35_Y_MODIFY() bfin_read32(DMA35_Y_MODIFY)
+#define bfin_write_DMA35_Y_MODIFY(val) bfin_write32(DMA35_Y_MODIFY, val)
+#define bfin_read_DMA35_CURR_DESC_PTR() bfin_read32(DMA35_CURR_DESC_PTR)
+#define bfin_write_DMA35_CURR_DESC_PTR(val) bfin_write32(DMA35_CURR_DESC_PTR, val)
+#define bfin_read_DMA35_PREV_DESC_PTR() bfin_read32(DMA35_PREV_DESC_PTR)
+#define bfin_write_DMA35_PREV_DESC_PTR(val) bfin_write32(DMA35_PREV_DESC_PTR, val)
+#define bfin_read_DMA35_CURR_ADDR() bfin_read32(DMA35_CURR_ADDR)
+#define bfin_write_DMA35_CURR_ADDR(val) bfin_write32(DMA35_CURR_ADDR, val)
+#define bfin_read_DMA35_IRQ_STATUS() bfin_read32(DMA35_IRQ_STATUS)
+#define bfin_write_DMA35_IRQ_STATUS(val) bfin_write32(DMA35_IRQ_STATUS, val)
+#define bfin_read_DMA35_CURR_X_COUNT() bfin_read32(DMA35_CURR_X_COUNT)
+#define bfin_write_DMA35_CURR_X_COUNT(val) bfin_write32(DMA35_CURR_X_COUNT, val)
+#define bfin_read_DMA35_CURR_Y_COUNT() bfin_read32(DMA35_CURR_Y_COUNT)
+#define bfin_write_DMA35_CURR_Y_COUNT(val) bfin_write32(DMA35_CURR_Y_COUNT, val)
+#define bfin_read_DMA35_BWL_COUNT() bfin_read32(DMA35_BWL_COUNT)
+#define bfin_write_DMA35_BWL_COUNT(val) bfin_write32(DMA35_BWL_COUNT, val)
+#define bfin_read_DMA35_CURR_BWL_COUNT() bfin_read32(DMA35_CURR_BWL_COUNT)
+#define bfin_write_DMA35_CURR_BWL_COUNT(val) bfin_write32(DMA35_CURR_BWL_COUNT, val)
+#define bfin_read_DMA35_BWM_COUNT() bfin_read32(DMA35_BWM_COUNT)
+#define bfin_write_DMA35_BWM_COUNT(val) bfin_write32(DMA35_BWM_COUNT, val)
+#define bfin_read_DMA35_CURR_BWM_COUNT() bfin_read32(DMA35_CURR_BWM_COUNT)
+#define bfin_write_DMA35_CURR_BWM_COUNT(val) bfin_write32(DMA35_CURR_BWM_COUNT, val)
+
+/* DMA Channel 36 Registers */
+
+#define bfin_read_DMA36_NEXT_DESC_PTR() bfin_read32(DMA36_NEXT_DESC_PTR)
+#define bfin_write_DMA36_NEXT_DESC_PTR(val) bfin_write32(DMA36_NEXT_DESC_PTR, val)
+#define bfin_read_DMA36_START_ADDR() bfin_read32(DMA36_START_ADDR)
+#define bfin_write_DMA36_START_ADDR(val) bfin_write32(DMA36_START_ADDR, val)
+#define bfin_read_DMA36_CONFIG() bfin_read32(DMA36_CONFIG)
+#define bfin_write_DMA36_CONFIG(val) bfin_write32(DMA36_CONFIG, val)
+#define bfin_read_DMA36_X_COUNT() bfin_read32(DMA36_X_COUNT)
+#define bfin_write_DMA36_X_COUNT(val) bfin_write32(DMA36_X_COUNT, val)
+#define bfin_read_DMA36_X_MODIFY() bfin_read32(DMA36_X_MODIFY)
+#define bfin_write_DMA36_X_MODIFY(val) bfin_write32(DMA36_X_MODIFY, val)
+#define bfin_read_DMA36_Y_COUNT() bfin_read32(DMA36_Y_COUNT)
+#define bfin_write_DMA36_Y_COUNT(val) bfin_write32(DMA36_Y_COUNT, val)
+#define bfin_read_DMA36_Y_MODIFY() bfin_read32(DMA36_Y_MODIFY)
+#define bfin_write_DMA36_Y_MODIFY(val) bfin_write32(DMA36_Y_MODIFY, val)
+#define bfin_read_DMA36_CURR_DESC_PTR() bfin_read32(DMA36_CURR_DESC_PTR)
+#define bfin_write_DMA36_CURR_DESC_PTR(val) bfin_write32(DMA36_CURR_DESC_PTR, val)
+#define bfin_read_DMA36_PREV_DESC_PTR() bfin_read32(DMA36_PREV_DESC_PTR)
+#define bfin_write_DMA36_PREV_DESC_PTR(val) bfin_write32(DMA36_PREV_DESC_PTR, val)
+#define bfin_read_DMA36_CURR_ADDR() bfin_read32(DMA36_CURR_ADDR)
+#define bfin_write_DMA36_CURR_ADDR(val) bfin_write32(DMA36_CURR_ADDR, val)
+#define bfin_read_DMA36_IRQ_STATUS() bfin_read32(DMA36_IRQ_STATUS)
+#define bfin_write_DMA36_IRQ_STATUS(val) bfin_write32(DMA36_IRQ_STATUS, val)
+#define bfin_read_DMA36_CURR_X_COUNT() bfin_read32(DMA36_CURR_X_COUNT)
+#define bfin_write_DMA36_CURR_X_COUNT(val) bfin_write32(DMA36_CURR_X_COUNT, val)
+#define bfin_read_DMA36_CURR_Y_COUNT() bfin_read32(DMA36_CURR_Y_COUNT)
+#define bfin_write_DMA36_CURR_Y_COUNT(val) bfin_write32(DMA36_CURR_Y_COUNT, val)
+#define bfin_read_DMA36_BWL_COUNT() bfin_read32(DMA36_BWL_COUNT)
+#define bfin_write_DMA36_BWL_COUNT(val) bfin_write32(DMA36_BWL_COUNT, val)
+#define bfin_read_DMA36_CURR_BWL_COUNT() bfin_read32(DMA36_CURR_BWL_COUNT)
+#define bfin_write_DMA36_CURR_BWL_COUNT(val) bfin_write32(DMA36_CURR_BWL_COUNT, val)
+#define bfin_read_DMA36_BWM_COUNT() bfin_read32(DMA36_BWM_COUNT)
+#define bfin_write_DMA36_BWM_COUNT(val) bfin_write32(DMA36_BWM_COUNT, val)
+#define bfin_read_DMA36_CURR_BWM_COUNT() bfin_read32(DMA36_CURR_BWM_COUNT)
+#define bfin_write_DMA36_CURR_BWM_COUNT(val) bfin_write32(DMA36_CURR_BWM_COUNT, val)
+
+/* DMA Channel 37 Registers */
+
+#define bfin_read_DMA37_NEXT_DESC_PTR() bfin_read32(DMA37_NEXT_DESC_PTR)
+#define bfin_write_DMA37_NEXT_DESC_PTR(val) bfin_write32(DMA37_NEXT_DESC_PTR, val)
+#define bfin_read_DMA37_START_ADDR() bfin_read32(DMA37_START_ADDR)
+#define bfin_write_DMA37_START_ADDR(val) bfin_write32(DMA37_START_ADDR, val)
+#define bfin_read_DMA37_CONFIG() bfin_read32(DMA37_CONFIG)
+#define bfin_write_DMA37_CONFIG(val) bfin_write32(DMA37_CONFIG, val)
+#define bfin_read_DMA37_X_COUNT() bfin_read32(DMA37_X_COUNT)
+#define bfin_write_DMA37_X_COUNT(val) bfin_write32(DMA37_X_COUNT, val)
+#define bfin_read_DMA37_X_MODIFY() bfin_read32(DMA37_X_MODIFY)
+#define bfin_write_DMA37_X_MODIFY(val) bfin_write32(DMA37_X_MODIFY, val)
+#define bfin_read_DMA37_Y_COUNT() bfin_read32(DMA37_Y_COUNT)
+#define bfin_write_DMA37_Y_COUNT(val) bfin_write32(DMA37_Y_COUNT, val)
+#define bfin_read_DMA37_Y_MODIFY() bfin_read32(DMA37_Y_MODIFY)
+#define bfin_write_DMA37_Y_MODIFY(val) bfin_write32(DMA37_Y_MODIFY, val)
+#define bfin_read_DMA37_CURR_DESC_PTR() bfin_read32(DMA37_CURR_DESC_PTR)
+#define bfin_write_DMA37_CURR_DESC_PTR(val) bfin_write32(DMA37_CURR_DESC_PTR, val)
+#define bfin_read_DMA37_PREV_DESC_PTR() bfin_read32(DMA37_PREV_DESC_PTR)
+#define bfin_write_DMA37_PREV_DESC_PTR(val) bfin_write32(DMA37_PREV_DESC_PTR, val)
+#define bfin_read_DMA37_CURR_ADDR() bfin_read32(DMA37_CURR_ADDR)
+#define bfin_write_DMA37_CURR_ADDR(val) bfin_write32(DMA37_CURR_ADDR, val)
+#define bfin_read_DMA37_IRQ_STATUS() bfin_read32(DMA37_IRQ_STATUS)
+#define bfin_write_DMA37_IRQ_STATUS(val) bfin_write32(DMA37_IRQ_STATUS, val)
+#define bfin_read_DMA37_CURR_X_COUNT() bfin_read32(DMA37_CURR_X_COUNT)
+#define bfin_write_DMA37_CURR_X_COUNT(val) bfin_write32(DMA37_CURR_X_COUNT, val)
+#define bfin_read_DMA37_CURR_Y_COUNT() bfin_read32(DMA37_CURR_Y_COUNT)
+#define bfin_write_DMA37_CURR_Y_COUNT(val) bfin_write32(DMA37_CURR_Y_COUNT, val)
+#define bfin_read_DMA37_BWL_COUNT() bfin_read32(DMA37_BWL_COUNT)
+#define bfin_write_DMA37_BWL_COUNT(val) bfin_write32(DMA37_BWL_COUNT, val)
+#define bfin_read_DMA37_CURR_BWL_COUNT() bfin_read32(DMA37_CURR_BWL_COUNT)
+#define bfin_write_DMA37_CURR_BWL_COUNT(val) bfin_write32(DMA37_CURR_BWL_COUNT, val)
+#define bfin_read_DMA37_BWM_COUNT() bfin_read32(DMA37_BWM_COUNT)
+#define bfin_write_DMA37_BWM_COUNT(val) bfin_write32(DMA37_BWM_COUNT, val)
+#define bfin_read_DMA37_CURR_BWM_COUNT() bfin_read32(DMA37_CURR_BWM_COUNT)
+#define bfin_write_DMA37_CURR_BWM_COUNT(val) bfin_write32(DMA37_CURR_BWM_COUNT, val)
+
+/* DMA Channel 38 Registers */
+
+#define bfin_read_DMA38_NEXT_DESC_PTR() bfin_read32(DMA38_NEXT_DESC_PTR)
+#define bfin_write_DMA38_NEXT_DESC_PTR(val) bfin_write32(DMA38_NEXT_DESC_PTR, val)
+#define bfin_read_DMA38_START_ADDR() bfin_read32(DMA38_START_ADDR)
+#define bfin_write_DMA38_START_ADDR(val) bfin_write32(DMA38_START_ADDR, val)
+#define bfin_read_DMA38_CONFIG() bfin_read32(DMA38_CONFIG)
+#define bfin_write_DMA38_CONFIG(val) bfin_write32(DMA38_CONFIG, val)
+#define bfin_read_DMA38_X_COUNT() bfin_read32(DMA38_X_COUNT)
+#define bfin_write_DMA38_X_COUNT(val) bfin_write32(DMA38_X_COUNT, val)
+#define bfin_read_DMA38_X_MODIFY() bfin_read32(DMA38_X_MODIFY)
+#define bfin_write_DMA38_X_MODIFY(val) bfin_write32(DMA38_X_MODIFY, val)
+#define bfin_read_DMA38_Y_COUNT() bfin_read32(DMA38_Y_COUNT)
+#define bfin_write_DMA38_Y_COUNT(val) bfin_write32(DMA38_Y_COUNT, val)
+#define bfin_read_DMA38_Y_MODIFY() bfin_read32(DMA38_Y_MODIFY)
+#define bfin_write_DMA38_Y_MODIFY(val) bfin_write32(DMA38_Y_MODIFY, val)
+#define bfin_read_DMA38_CURR_DESC_PTR() bfin_read32(DMA38_CURR_DESC_PTR)
+#define bfin_write_DMA38_CURR_DESC_PTR(val) bfin_write32(DMA38_CURR_DESC_PTR, val)
+#define bfin_read_DMA38_PREV_DESC_PTR() bfin_read32(DMA38_PREV_DESC_PTR)
+#define bfin_write_DMA38_PREV_DESC_PTR(val) bfin_write32(DMA38_PREV_DESC_PTR, val)
+#define bfin_read_DMA38_CURR_ADDR() bfin_read32(DMA38_CURR_ADDR)
+#define bfin_write_DMA38_CURR_ADDR(val) bfin_write32(DMA38_CURR_ADDR, val)
+#define bfin_read_DMA38_IRQ_STATUS() bfin_read32(DMA38_IRQ_STATUS)
+#define bfin_write_DMA38_IRQ_STATUS(val) bfin_write32(DMA38_IRQ_STATUS, val)
+#define bfin_read_DMA38_CURR_X_COUNT() bfin_read32(DMA38_CURR_X_COUNT)
+#define bfin_write_DMA38_CURR_X_COUNT(val) bfin_write32(DMA38_CURR_X_COUNT, val)
+#define bfin_read_DMA38_CURR_Y_COUNT() bfin_read32(DMA38_CURR_Y_COUNT)
+#define bfin_write_DMA38_CURR_Y_COUNT(val) bfin_write32(DMA38_CURR_Y_COUNT, val)
+#define bfin_read_DMA38_BWL_COUNT() bfin_read32(DMA38_BWL_COUNT)
+#define bfin_write_DMA38_BWL_COUNT(val) bfin_write32(DMA38_BWL_COUNT, val)
+#define bfin_read_DMA38_CURR_BWL_COUNT() bfin_read32(DMA38_CURR_BWL_COUNT)
+#define bfin_write_DMA38_CURR_BWL_COUNT(val) bfin_write32(DMA38_CURR_BWL_COUNT, val)
+#define bfin_read_DMA38_BWM_COUNT() bfin_read32(DMA38_BWM_COUNT)
+#define bfin_write_DMA38_BWM_COUNT(val) bfin_write32(DMA38_BWM_COUNT, val)
+#define bfin_read_DMA38_CURR_BWM_COUNT() bfin_read32(DMA38_CURR_BWM_COUNT)
+#define bfin_write_DMA38_CURR_BWM_COUNT(val) bfin_write32(DMA38_CURR_BWM_COUNT, val)
+
+/* DMA Channel 39 Registers */
+
+#define bfin_read_DMA39_NEXT_DESC_PTR() bfin_read32(DMA39_NEXT_DESC_PTR)
+#define bfin_write_DMA39_NEXT_DESC_PTR(val) bfin_write32(DMA39_NEXT_DESC_PTR, val)
+#define bfin_read_DMA39_START_ADDR() bfin_read32(DMA39_START_ADDR)
+#define bfin_write_DMA39_START_ADDR(val) bfin_write32(DMA39_START_ADDR, val)
+#define bfin_read_DMA39_CONFIG() bfin_read32(DMA39_CONFIG)
+#define bfin_write_DMA39_CONFIG(val) bfin_write32(DMA39_CONFIG, val)
+#define bfin_read_DMA39_X_COUNT() bfin_read32(DMA39_X_COUNT)
+#define bfin_write_DMA39_X_COUNT(val) bfin_write32(DMA39_X_COUNT, val)
+#define bfin_read_DMA39_X_MODIFY() bfin_read32(DMA39_X_MODIFY)
+#define bfin_write_DMA39_X_MODIFY(val) bfin_write32(DMA39_X_MODIFY, val)
+#define bfin_read_DMA39_Y_COUNT() bfin_read32(DMA39_Y_COUNT)
+#define bfin_write_DMA39_Y_COUNT(val) bfin_write32(DMA39_Y_COUNT, val)
+#define bfin_read_DMA39_Y_MODIFY() bfin_read32(DMA39_Y_MODIFY)
+#define bfin_write_DMA39_Y_MODIFY(val) bfin_write32(DMA39_Y_MODIFY, val)
+#define bfin_read_DMA39_CURR_DESC_PTR() bfin_read32(DMA39_CURR_DESC_PTR)
+#define bfin_write_DMA39_CURR_DESC_PTR(val) bfin_write32(DMA39_CURR_DESC_PTR, val)
+#define bfin_read_DMA39_PREV_DESC_PTR() bfin_read32(DMA39_PREV_DESC_PTR)
+#define bfin_write_DMA39_PREV_DESC_PTR(val) bfin_write32(DMA39_PREV_DESC_PTR, val)
+#define bfin_read_DMA39_CURR_ADDR() bfin_read32(DMA39_CURR_ADDR)
+#define bfin_write_DMA39_CURR_ADDR(val) bfin_write32(DMA39_CURR_ADDR, val)
+#define bfin_read_DMA39_IRQ_STATUS() bfin_read32(DMA39_IRQ_STATUS)
+#define bfin_write_DMA39_IRQ_STATUS(val) bfin_write32(DMA39_IRQ_STATUS, val)
+#define bfin_read_DMA39_CURR_X_COUNT() bfin_read32(DMA39_CURR_X_COUNT)
+#define bfin_write_DMA39_CURR_X_COUNT(val) bfin_write32(DMA39_CURR_X_COUNT, val)
+#define bfin_read_DMA39_CURR_Y_COUNT() bfin_read32(DMA39_CURR_Y_COUNT)
+#define bfin_write_DMA39_CURR_Y_COUNT(val) bfin_write32(DMA39_CURR_Y_COUNT, val)
+#define bfin_read_DMA39_BWL_COUNT() bfin_read32(DMA39_BWL_COUNT)
+#define bfin_write_DMA39_BWL_COUNT(val) bfin_write32(DMA39_BWL_COUNT, val)
+#define bfin_read_DMA39_CURR_BWL_COUNT() bfin_read32(DMA39_CURR_BWL_COUNT)
+#define bfin_write_DMA39_CURR_BWL_COUNT(val) bfin_write32(DMA39_CURR_BWL_COUNT, val)
+#define bfin_read_DMA39_BWM_COUNT() bfin_read32(DMA39_BWM_COUNT)
+#define bfin_write_DMA39_BWM_COUNT(val) bfin_write32(DMA39_BWM_COUNT, val)
+#define bfin_read_DMA39_CURR_BWM_COUNT() bfin_read32(DMA39_CURR_BWM_COUNT)
+#define bfin_write_DMA39_CURR_BWM_COUNT(val) bfin_write32(DMA39_CURR_BWM_COUNT, val)
+
+/* DMA Channel 40 Registers */
+
+#define bfin_read_DMA40_NEXT_DESC_PTR() bfin_read32(DMA40_NEXT_DESC_PTR)
+#define bfin_write_DMA40_NEXT_DESC_PTR(val) bfin_write32(DMA40_NEXT_DESC_PTR, val)
+#define bfin_read_DMA40_START_ADDR() bfin_read32(DMA40_START_ADDR)
+#define bfin_write_DMA40_START_ADDR(val) bfin_write32(DMA40_START_ADDR, val)
+#define bfin_read_DMA40_CONFIG() bfin_read32(DMA40_CONFIG)
+#define bfin_write_DMA40_CONFIG(val) bfin_write32(DMA40_CONFIG, val)
+#define bfin_read_DMA40_X_COUNT() bfin_read32(DMA40_X_COUNT)
+#define bfin_write_DMA40_X_COUNT(val) bfin_write32(DMA40_X_COUNT, val)
+#define bfin_read_DMA40_X_MODIFY() bfin_read32(DMA40_X_MODIFY)
+#define bfin_write_DMA40_X_MODIFY(val) bfin_write32(DMA40_X_MODIFY, val)
+#define bfin_read_DMA40_Y_COUNT() bfin_read32(DMA40_Y_COUNT)
+#define bfin_write_DMA40_Y_COUNT(val) bfin_write32(DMA40_Y_COUNT, val)
+#define bfin_read_DMA40_Y_MODIFY() bfin_read32(DMA40_Y_MODIFY)
+#define bfin_write_DMA40_Y_MODIFY(val) bfin_write32(DMA40_Y_MODIFY, val)
+#define bfin_read_DMA40_CURR_DESC_PTR() bfin_read32(DMA40_CURR_DESC_PTR)
+#define bfin_write_DMA40_CURR_DESC_PTR(val) bfin_write32(DMA40_CURR_DESC_PTR, val)
+#define bfin_read_DMA40_PREV_DESC_PTR() bfin_read32(DMA40_PREV_DESC_PTR)
+#define bfin_write_DMA40_PREV_DESC_PTR(val) bfin_write32(DMA40_PREV_DESC_PTR, val)
+#define bfin_read_DMA40_CURR_ADDR() bfin_read32(DMA40_CURR_ADDR)
+#define bfin_write_DMA40_CURR_ADDR(val) bfin_write32(DMA40_CURR_ADDR, val)
+#define bfin_read_DMA40_IRQ_STATUS() bfin_read32(DMA40_IRQ_STATUS)
+#define bfin_write_DMA40_IRQ_STATUS(val) bfin_write32(DMA40_IRQ_STATUS, val)
+#define bfin_read_DMA40_CURR_X_COUNT() bfin_read32(DMA40_CURR_X_COUNT)
+#define bfin_write_DMA40_CURR_X_COUNT(val) bfin_write32(DMA40_CURR_X_COUNT, val)
+#define bfin_read_DMA40_CURR_Y_COUNT() bfin_read32(DMA40_CURR_Y_COUNT)
+#define bfin_write_DMA40_CURR_Y_COUNT(val) bfin_write32(DMA40_CURR_Y_COUNT, val)
+#define bfin_read_DMA40_BWL_COUNT() bfin_read32(DMA40_BWL_COUNT)
+#define bfin_write_DMA40_BWL_COUNT(val) bfin_write32(DMA40_BWL_COUNT, val)
+#define bfin_read_DMA40_CURR_BWL_COUNT() bfin_read32(DMA40_CURR_BWL_COUNT)
+#define bfin_write_DMA40_CURR_BWL_COUNT(val) bfin_write32(DMA40_CURR_BWL_COUNT, val)
+#define bfin_read_DMA40_BWM_COUNT() bfin_read32(DMA40_BWM_COUNT)
+#define bfin_write_DMA40_BWM_COUNT(val) bfin_write32(DMA40_BWM_COUNT, val)
+#define bfin_read_DMA40_CURR_BWM_COUNT() bfin_read32(DMA40_CURR_BWM_COUNT)
+#define bfin_write_DMA40_CURR_BWM_COUNT(val) bfin_write32(DMA40_CURR_BWM_COUNT, val)
+
+/* DMA Channel 41 Registers */
+
+#define bfin_read_DMA41_NEXT_DESC_PTR() bfin_read32(DMA41_NEXT_DESC_PTR)
+#define bfin_write_DMA41_NEXT_DESC_PTR(val) bfin_write32(DMA41_NEXT_DESC_PTR, val)
+#define bfin_read_DMA41_START_ADDR() bfin_read32(DMA41_START_ADDR)
+#define bfin_write_DMA41_START_ADDR(val) bfin_write32(DMA41_START_ADDR, val)
+#define bfin_read_DMA41_CONFIG() bfin_read32(DMA41_CONFIG)
+#define bfin_write_DMA41_CONFIG(val) bfin_write32(DMA41_CONFIG, val)
+#define bfin_read_DMA41_X_COUNT() bfin_read32(DMA41_X_COUNT)
+#define bfin_write_DMA41_X_COUNT(val) bfin_write32(DMA41_X_COUNT, val)
+#define bfin_read_DMA41_X_MODIFY() bfin_read32(DMA41_X_MODIFY)
+#define bfin_write_DMA41_X_MODIFY(val) bfin_write32(DMA41_X_MODIFY, val)
+#define bfin_read_DMA41_Y_COUNT() bfin_read32(DMA41_Y_COUNT)
+#define bfin_write_DMA41_Y_COUNT(val) bfin_write32(DMA41_Y_COUNT, val)
+#define bfin_read_DMA41_Y_MODIFY() bfin_read32(DMA41_Y_MODIFY)
+#define bfin_write_DMA41_Y_MODIFY(val) bfin_write32(DMA41_Y_MODIFY, val)
+#define bfin_read_DMA41_CURR_DESC_PTR() bfin_read32(DMA41_CURR_DESC_PTR)
+#define bfin_write_DMA41_CURR_DESC_PTR(val) bfin_write32(DMA41_CURR_DESC_PTR, val)
+#define bfin_read_DMA41_PREV_DESC_PTR() bfin_read32(DMA41_PREV_DESC_PTR)
+#define bfin_write_DMA41_PREV_DESC_PTR(val) bfin_write32(DMA41_PREV_DESC_PTR, val)
+#define bfin_read_DMA41_CURR_ADDR() bfin_read32(DMA41_CURR_ADDR)
+#define bfin_write_DMA41_CURR_ADDR(val) bfin_write32(DMA41_CURR_ADDR, val)
+#define bfin_read_DMA41_IRQ_STATUS() bfin_read32(DMA41_IRQ_STATUS)
+#define bfin_write_DMA41_IRQ_STATUS(val) bfin_write32(DMA41_IRQ_STATUS, val)
+#define bfin_read_DMA41_CURR_X_COUNT() bfin_read32(DMA41_CURR_X_COUNT)
+#define bfin_write_DMA41_CURR_X_COUNT(val) bfin_write32(DMA41_CURR_X_COUNT, val)
+#define bfin_read_DMA41_CURR_Y_COUNT() bfin_read32(DMA41_CURR_Y_COUNT)
+#define bfin_write_DMA41_CURR_Y_COUNT(val) bfin_write32(DMA41_CURR_Y_COUNT, val)
+#define bfin_read_DMA41_BWL_COUNT() bfin_read32(DMA41_BWL_COUNT)
+#define bfin_write_DMA41_BWL_COUNT(val) bfin_write32(DMA41_BWL_COUNT, val)
+#define bfin_read_DMA41_CURR_BWL_COUNT() bfin_read32(DMA41_CURR_BWL_COUNT)
+#define bfin_write_DMA41_CURR_BWL_COUNT(val) bfin_write32(DMA41_CURR_BWL_COUNT, val)
+#define bfin_read_DMA41_BWM_COUNT() bfin_read32(DMA41_BWM_COUNT)
+#define bfin_write_DMA41_BWM_COUNT(val) bfin_write32(DMA41_BWM_COUNT, val)
+#define bfin_read_DMA41_CURR_BWM_COUNT() bfin_read32(DMA41_CURR_BWM_COUNT)
+#define bfin_write_DMA41_CURR_BWM_COUNT(val) bfin_write32(DMA41_CURR_BWM_COUNT, val)
+
+/* DMA Channel 42 Registers */
+
+#define bfin_read_DMA42_NEXT_DESC_PTR() bfin_read32(DMA42_NEXT_DESC_PTR)
+#define bfin_write_DMA42_NEXT_DESC_PTR(val) bfin_write32(DMA42_NEXT_DESC_PTR, val)
+#define bfin_read_DMA42_START_ADDR() bfin_read32(DMA42_START_ADDR)
+#define bfin_write_DMA42_START_ADDR(val) bfin_write32(DMA42_START_ADDR, val)
+#define bfin_read_DMA42_CONFIG() bfin_read32(DMA42_CONFIG)
+#define bfin_write_DMA42_CONFIG(val) bfin_write32(DMA42_CONFIG, val)
+#define bfin_read_DMA42_X_COUNT() bfin_read32(DMA42_X_COUNT)
+#define bfin_write_DMA42_X_COUNT(val) bfin_write32(DMA42_X_COUNT, val)
+#define bfin_read_DMA42_X_MODIFY() bfin_read32(DMA42_X_MODIFY)
+#define bfin_write_DMA42_X_MODIFY(val) bfin_write32(DMA42_X_MODIFY, val)
+#define bfin_read_DMA42_Y_COUNT() bfin_read32(DMA42_Y_COUNT)
+#define bfin_write_DMA42_Y_COUNT(val) bfin_write32(DMA42_Y_COUNT, val)
+#define bfin_read_DMA42_Y_MODIFY() bfin_read32(DMA42_Y_MODIFY)
+#define bfin_write_DMA42_Y_MODIFY(val) bfin_write32(DMA42_Y_MODIFY, val)
+#define bfin_read_DMA42_CURR_DESC_PTR() bfin_read32(DMA42_CURR_DESC_PTR)
+#define bfin_write_DMA42_CURR_DESC_PTR(val) bfin_write32(DMA42_CURR_DESC_PTR, val)
+#define bfin_read_DMA42_PREV_DESC_PTR() bfin_read32(DMA42_PREV_DESC_PTR)
+#define bfin_write_DMA42_PREV_DESC_PTR(val) bfin_write32(DMA42_PREV_DESC_PTR, val)
+#define bfin_read_DMA42_CURR_ADDR() bfin_read32(DMA42_CURR_ADDR)
+#define bfin_write_DMA42_CURR_ADDR(val) bfin_write32(DMA42_CURR_ADDR, val)
+#define bfin_read_DMA42_IRQ_STATUS() bfin_read32(DMA42_IRQ_STATUS)
+#define bfin_write_DMA42_IRQ_STATUS(val) bfin_write32(DMA42_IRQ_STATUS, val)
+#define bfin_read_DMA42_CURR_X_COUNT() bfin_read32(DMA42_CURR_X_COUNT)
+#define bfin_write_DMA42_CURR_X_COUNT(val) bfin_write32(DMA42_CURR_X_COUNT, val)
+#define bfin_read_DMA42_CURR_Y_COUNT() bfin_read32(DMA42_CURR_Y_COUNT)
+#define bfin_write_DMA42_CURR_Y_COUNT(val) bfin_write32(DMA42_CURR_Y_COUNT, val)
+#define bfin_read_DMA42_BWL_COUNT() bfin_read32(DMA42_BWL_COUNT)
+#define bfin_write_DMA42_BWL_COUNT(val) bfin_write32(DMA42_BWL_COUNT, val)
+#define bfin_read_DMA42_CURR_BWL_COUNT() bfin_read32(DMA42_CURR_BWL_COUNT)
+#define bfin_write_DMA42_CURR_BWL_COUNT(val) bfin_write32(DMA42_CURR_BWL_COUNT, val)
+#define bfin_read_DMA42_BWM_COUNT() bfin_read32(DMA42_BWM_COUNT)
+#define bfin_write_DMA42_BWM_COUNT(val) bfin_write32(DMA42_BWM_COUNT, val)
+#define bfin_read_DMA42_CURR_BWM_COUNT() bfin_read32(DMA42_CURR_BWM_COUNT)
+#define bfin_write_DMA42_CURR_BWM_COUNT(val) bfin_write32(DMA42_CURR_BWM_COUNT, val)
+
+/* DMA Channel 43 Registers */
+
+#define bfin_read_DMA43_NEXT_DESC_PTR() bfin_read32(DMA43_NEXT_DESC_PTR)
+#define bfin_write_DMA43_NEXT_DESC_PTR(val) bfin_write32(DMA43_NEXT_DESC_PTR, val)
+#define bfin_read_DMA43_START_ADDR() bfin_read32(DMA43_START_ADDR)
+#define bfin_write_DMA43_START_ADDR(val) bfin_write32(DMA43_START_ADDR, val)
+#define bfin_read_DMA43_CONFIG() bfin_read32(DMA43_CONFIG)
+#define bfin_write_DMA43_CONFIG(val) bfin_write32(DMA43_CONFIG, val)
+#define bfin_read_DMA43_X_COUNT() bfin_read32(DMA43_X_COUNT)
+#define bfin_write_DMA43_X_COUNT(val) bfin_write32(DMA43_X_COUNT, val)
+#define bfin_read_DMA43_X_MODIFY() bfin_read32(DMA43_X_MODIFY)
+#define bfin_write_DMA43_X_MODIFY(val) bfin_write32(DMA43_X_MODIFY, val)
+#define bfin_read_DMA43_Y_COUNT() bfin_read32(DMA43_Y_COUNT)
+#define bfin_write_DMA43_Y_COUNT(val) bfin_write32(DMA43_Y_COUNT, val)
+#define bfin_read_DMA43_Y_MODIFY() bfin_read32(DMA43_Y_MODIFY)
+#define bfin_write_DMA43_Y_MODIFY(val) bfin_write32(DMA43_Y_MODIFY, val)
+#define bfin_read_DMA43_CURR_DESC_PTR() bfin_read32(DMA43_CURR_DESC_PTR)
+#define bfin_write_DMA43_CURR_DESC_PTR(val) bfin_write32(DMA43_CURR_DESC_PTR, val)
+#define bfin_read_DMA43_PREV_DESC_PTR() bfin_read32(DMA43_PREV_DESC_PTR)
+#define bfin_write_DMA43_PREV_DESC_PTR(val) bfin_write32(DMA43_PREV_DESC_PTR, val)
+#define bfin_read_DMA43_CURR_ADDR() bfin_read32(DMA43_CURR_ADDR)
+#define bfin_write_DMA43_CURR_ADDR(val) bfin_write32(DMA43_CURR_ADDR, val)
+#define bfin_read_DMA43_IRQ_STATUS() bfin_read32(DMA43_IRQ_STATUS)
+#define bfin_write_DMA43_IRQ_STATUS(val) bfin_write32(DMA43_IRQ_STATUS, val)
+#define bfin_read_DMA43_CURR_X_COUNT() bfin_read32(DMA43_CURR_X_COUNT)
+#define bfin_write_DMA43_CURR_X_COUNT(val) bfin_write32(DMA43_CURR_X_COUNT, val)
+#define bfin_read_DMA43_CURR_Y_COUNT() bfin_read32(DMA43_CURR_Y_COUNT)
+#define bfin_write_DMA43_CURR_Y_COUNT(val) bfin_write32(DMA43_CURR_Y_COUNT, val)
+#define bfin_read_DMA43_BWL_COUNT() bfin_read32(DMA43_BWL_COUNT)
+#define bfin_write_DMA43_BWL_COUNT(val) bfin_write32(DMA43_BWL_COUNT, val)
+#define bfin_read_DMA43_CURR_BWL_COUNT() bfin_read32(DMA43_CURR_BWL_COUNT)
+#define bfin_write_DMA43_CURR_BWL_COUNT(val) bfin_write32(DMA43_CURR_BWL_COUNT, val)
+#define bfin_read_DMA43_BWM_COUNT() bfin_read32(DMA43_BWM_COUNT)
+#define bfin_write_DMA43_BWM_COUNT(val) bfin_write32(DMA43_BWM_COUNT, val)
+#define bfin_read_DMA43_CURR_BWM_COUNT() bfin_read32(DMA43_CURR_BWM_COUNT)
+#define bfin_write_DMA43_CURR_BWM_COUNT(val) bfin_write32(DMA43_CURR_BWM_COUNT, val)
+
+/* DMA Channel 44 Registers */
+
+#define bfin_read_DMA44_NEXT_DESC_PTR() bfin_read32(DMA44_NEXT_DESC_PTR)
+#define bfin_write_DMA44_NEXT_DESC_PTR(val) bfin_write32(DMA44_NEXT_DESC_PTR, val)
+#define bfin_read_DMA44_START_ADDR() bfin_read32(DMA44_START_ADDR)
+#define bfin_write_DMA44_START_ADDR(val) bfin_write32(DMA44_START_ADDR, val)
+#define bfin_read_DMA44_CONFIG() bfin_read32(DMA44_CONFIG)
+#define bfin_write_DMA44_CONFIG(val) bfin_write32(DMA44_CONFIG, val)
+#define bfin_read_DMA44_X_COUNT() bfin_read32(DMA44_X_COUNT)
+#define bfin_write_DMA44_X_COUNT(val) bfin_write32(DMA44_X_COUNT, val)
+#define bfin_read_DMA44_X_MODIFY() bfin_read32(DMA44_X_MODIFY)
+#define bfin_write_DMA44_X_MODIFY(val) bfin_write32(DMA44_X_MODIFY, val)
+#define bfin_read_DMA44_Y_COUNT() bfin_read32(DMA44_Y_COUNT)
+#define bfin_write_DMA44_Y_COUNT(val) bfin_write32(DMA44_Y_COUNT, val)
+#define bfin_read_DMA44_Y_MODIFY() bfin_read32(DMA44_Y_MODIFY)
+#define bfin_write_DMA44_Y_MODIFY(val) bfin_write32(DMA44_Y_MODIFY, val)
+#define bfin_read_DMA44_CURR_DESC_PTR() bfin_read32(DMA44_CURR_DESC_PTR)
+#define bfin_write_DMA44_CURR_DESC_PTR(val) bfin_write32(DMA44_CURR_DESC_PTR, val)
+#define bfin_read_DMA44_PREV_DESC_PTR() bfin_read32(DMA44_PREV_DESC_PTR)
+#define bfin_write_DMA44_PREV_DESC_PTR(val) bfin_write32(DMA44_PREV_DESC_PTR, val)
+#define bfin_read_DMA44_CURR_ADDR() bfin_read32(DMA44_CURR_ADDR)
+#define bfin_write_DMA44_CURR_ADDR(val) bfin_write32(DMA44_CURR_ADDR, val)
+#define bfin_read_DMA44_IRQ_STATUS() bfin_read32(DMA44_IRQ_STATUS)
+#define bfin_write_DMA44_IRQ_STATUS(val) bfin_write32(DMA44_IRQ_STATUS, val)
+#define bfin_read_DMA44_CURR_X_COUNT() bfin_read32(DMA44_CURR_X_COUNT)
+#define bfin_write_DMA44_CURR_X_COUNT(val) bfin_write32(DMA44_CURR_X_COUNT, val)
+#define bfin_read_DMA44_CURR_Y_COUNT() bfin_read32(DMA44_CURR_Y_COUNT)
+#define bfin_write_DMA44_CURR_Y_COUNT(val) bfin_write32(DMA44_CURR_Y_COUNT, val)
+#define bfin_read_DMA44_BWL_COUNT() bfin_read32(DMA44_BWL_COUNT)
+#define bfin_write_DMA44_BWL_COUNT(val) bfin_write32(DMA44_BWL_COUNT, val)
+#define bfin_read_DMA44_CURR_BWL_COUNT() bfin_read32(DMA44_CURR_BWL_COUNT)
+#define bfin_write_DMA44_CURR_BWL_COUNT(val) bfin_write32(DMA44_CURR_BWL_COUNT, val)
+#define bfin_read_DMA44_BWM_COUNT() bfin_read32(DMA44_BWM_COUNT)
+#define bfin_write_DMA44_BWM_COUNT(val) bfin_write32(DMA44_BWM_COUNT, val)
+#define bfin_read_DMA44_CURR_BWM_COUNT() bfin_read32(DMA44_CURR_BWM_COUNT)
+#define bfin_write_DMA44_CURR_BWM_COUNT(val) bfin_write32(DMA44_CURR_BWM_COUNT, val)
+
+/* DMA Channel 45 Registers */
+
+#define bfin_read_DMA45_NEXT_DESC_PTR() bfin_read32(DMA45_NEXT_DESC_PTR)
+#define bfin_write_DMA45_NEXT_DESC_PTR(val) bfin_write32(DMA45_NEXT_DESC_PTR, val)
+#define bfin_read_DMA45_START_ADDR() bfin_read32(DMA45_START_ADDR)
+#define bfin_write_DMA45_START_ADDR(val) bfin_write32(DMA45_START_ADDR, val)
+#define bfin_read_DMA45_CONFIG() bfin_read32(DMA45_CONFIG)
+#define bfin_write_DMA45_CONFIG(val) bfin_write32(DMA45_CONFIG, val)
+#define bfin_read_DMA45_X_COUNT() bfin_read32(DMA45_X_COUNT)
+#define bfin_write_DMA45_X_COUNT(val) bfin_write32(DMA45_X_COUNT, val)
+#define bfin_read_DMA45_X_MODIFY() bfin_read32(DMA45_X_MODIFY)
+#define bfin_write_DMA45_X_MODIFY(val) bfin_write32(DMA45_X_MODIFY, val)
+#define bfin_read_DMA45_Y_COUNT() bfin_read32(DMA45_Y_COUNT)
+#define bfin_write_DMA45_Y_COUNT(val) bfin_write32(DMA45_Y_COUNT, val)
+#define bfin_read_DMA45_Y_MODIFY() bfin_read32(DMA45_Y_MODIFY)
+#define bfin_write_DMA45_Y_MODIFY(val) bfin_write32(DMA45_Y_MODIFY, val)
+#define bfin_read_DMA45_CURR_DESC_PTR() bfin_read32(DMA45_CURR_DESC_PTR)
+#define bfin_write_DMA45_CURR_DESC_PTR(val) bfin_write32(DMA45_CURR_DESC_PTR, val)
+#define bfin_read_DMA45_PREV_DESC_PTR() bfin_read32(DMA45_PREV_DESC_PTR)
+#define bfin_write_DMA45_PREV_DESC_PTR(val) bfin_write32(DMA45_PREV_DESC_PTR, val)
+#define bfin_read_DMA45_CURR_ADDR() bfin_read32(DMA45_CURR_ADDR)
+#define bfin_write_DMA45_CURR_ADDR(val) bfin_write32(DMA45_CURR_ADDR, val)
+#define bfin_read_DMA45_IRQ_STATUS() bfin_read32(DMA45_IRQ_STATUS)
+#define bfin_write_DMA45_IRQ_STATUS(val) bfin_write32(DMA45_IRQ_STATUS, val)
+#define bfin_read_DMA45_CURR_X_COUNT() bfin_read32(DMA45_CURR_X_COUNT)
+#define bfin_write_DMA45_CURR_X_COUNT(val) bfin_write32(DMA45_CURR_X_COUNT, val)
+#define bfin_read_DMA45_CURR_Y_COUNT() bfin_read32(DMA45_CURR_Y_COUNT)
+#define bfin_write_DMA45_CURR_Y_COUNT(val) bfin_write32(DMA45_CURR_Y_COUNT, val)
+#define bfin_read_DMA45_BWL_COUNT() bfin_read32(DMA45_BWL_COUNT)
+#define bfin_write_DMA45_BWL_COUNT(val) bfin_write32(DMA45_BWL_COUNT, val)
+#define bfin_read_DMA45_CURR_BWL_COUNT() bfin_read32(DMA45_CURR_BWL_COUNT)
+#define bfin_write_DMA45_CURR_BWL_COUNT(val) bfin_write32(DMA45_CURR_BWL_COUNT, val)
+#define bfin_read_DMA45_BWM_COUNT() bfin_read32(DMA45_BWM_COUNT)
+#define bfin_write_DMA45_BWM_COUNT(val) bfin_write32(DMA45_BWM_COUNT, val)
+#define bfin_read_DMA45_CURR_BWM_COUNT() bfin_read32(DMA45_CURR_BWM_COUNT)
+#define bfin_write_DMA45_CURR_BWM_COUNT(val) bfin_write32(DMA45_CURR_BWM_COUNT, val)
+
+/* DMA Channel 46 Registers */
+
+#define bfin_read_DMA46_NEXT_DESC_PTR() bfin_read32(DMA46_NEXT_DESC_PTR)
+#define bfin_write_DMA46_NEXT_DESC_PTR(val) bfin_write32(DMA46_NEXT_DESC_PTR, val)
+#define bfin_read_DMA46_START_ADDR() bfin_read32(DMA46_START_ADDR)
+#define bfin_write_DMA46_START_ADDR(val) bfin_write32(DMA46_START_ADDR, val)
+#define bfin_read_DMA46_CONFIG() bfin_read32(DMA46_CONFIG)
+#define bfin_write_DMA46_CONFIG(val) bfin_write32(DMA46_CONFIG, val)
+#define bfin_read_DMA46_X_COUNT() bfin_read32(DMA46_X_COUNT)
+#define bfin_write_DMA46_X_COUNT(val) bfin_write32(DMA46_X_COUNT, val)
+#define bfin_read_DMA46_X_MODIFY() bfin_read32(DMA46_X_MODIFY)
+#define bfin_write_DMA46_X_MODIFY(val) bfin_write32(DMA46_X_MODIFY, val)
+#define bfin_read_DMA46_Y_COUNT() bfin_read32(DMA46_Y_COUNT)
+#define bfin_write_DMA46_Y_COUNT(val) bfin_write32(DMA46_Y_COUNT, val)
+#define bfin_read_DMA46_Y_MODIFY() bfin_read32(DMA46_Y_MODIFY)
+#define bfin_write_DMA46_Y_MODIFY(val) bfin_write32(DMA46_Y_MODIFY, val)
+#define bfin_read_DMA46_CURR_DESC_PTR() bfin_read32(DMA46_CURR_DESC_PTR)
+#define bfin_write_DMA46_CURR_DESC_PTR(val) bfin_write32(DMA46_CURR_DESC_PTR, val)
+#define bfin_read_DMA46_PREV_DESC_PTR() bfin_read32(DMA46_PREV_DESC_PTR)
+#define bfin_write_DMA46_PREV_DESC_PTR(val) bfin_write32(DMA46_PREV_DESC_PTR, val)
+#define bfin_read_DMA46_CURR_ADDR() bfin_read32(DMA46_CURR_ADDR)
+#define bfin_write_DMA46_CURR_ADDR(val) bfin_write32(DMA46_CURR_ADDR, val)
+#define bfin_read_DMA46_IRQ_STATUS() bfin_read32(DMA46_IRQ_STATUS)
+#define bfin_write_DMA46_IRQ_STATUS(val) bfin_write32(DMA46_IRQ_STATUS, val)
+#define bfin_read_DMA46_CURR_X_COUNT() bfin_read32(DMA46_CURR_X_COUNT)
+#define bfin_write_DMA46_CURR_X_COUNT(val) bfin_write32(DMA46_CURR_X_COUNT, val)
+#define bfin_read_DMA46_CURR_Y_COUNT() bfin_read32(DMA46_CURR_Y_COUNT)
+#define bfin_write_DMA46_CURR_Y_COUNT(val) bfin_write32(DMA46_CURR_Y_COUNT, val)
+#define bfin_read_DMA46_BWL_COUNT() bfin_read32(DMA46_BWL_COUNT)
+#define bfin_write_DMA46_BWL_COUNT(val) bfin_write32(DMA46_BWL_COUNT, val)
+#define bfin_read_DMA46_CURR_BWL_COUNT() bfin_read32(DMA46_CURR_BWL_COUNT)
+#define bfin_write_DMA46_CURR_BWL_COUNT(val) bfin_write32(DMA46_CURR_BWL_COUNT, val)
+#define bfin_read_DMA46_BWM_COUNT() bfin_read32(DMA46_BWM_COUNT)
+#define bfin_write_DMA46_BWM_COUNT(val) bfin_write32(DMA46_BWM_COUNT, val)
+#define bfin_read_DMA46_CURR_BWM_COUNT() bfin_read32(DMA46_CURR_BWM_COUNT)
+#define bfin_write_DMA46_CURR_BWM_COUNT(val) bfin_write32(DMA46_CURR_BWM_COUNT, val)
+
+
+/* EPPI1 Registers */
+
+
+/* Port Interrubfin_read_()t 0 Registers (32-bit) */
+
+#define bfin_read_PINT0_MASK_SET() bfin_read32(PINT0_MASK_SET)
+#define bfin_write_PINT0_MASK_SET(val) bfin_write32(PINT0_MASK_SET, val)
+#define bfin_read_PINT0_MASK_CLEAR() bfin_read32(PINT0_MASK_CLEAR)
+#define bfin_write_PINT0_MASK_CLEAR(val) bfin_write32(PINT0_MASK_CLEAR, val)
+#define bfin_read_PINT0_REQUEST() bfin_read32(PINT0_REQUEST)
+#define bfin_write_PINT0_REQUEST(val) bfin_write32(PINT0_REQUEST, val)
+#define bfin_read_PINT0_ASSIGN() bfin_read32(PINT0_ASSIGN)
+#define bfin_write_PINT0_ASSIGN(val) bfin_write32(PINT0_ASSIGN, val)
+#define bfin_read_PINT0_EDGE_SET() bfin_read32(PINT0_EDGE_SET)
+#define bfin_write_PINT0_EDGE_SET(val) bfin_write32(PINT0_EDGE_SET, val)
+#define bfin_read_PINT0_EDGE_CLEAR() bfin_read32(PINT0_EDGE_CLEAR)
+#define bfin_write_PINT0_EDGE_CLEAR(val) bfin_write32(PINT0_EDGE_CLEAR, val)
+#define bfin_read_PINT0_INVERT_SET() bfin_read32(PINT0_INVERT_SET)
+#define bfin_write_PINT0_INVERT_SET(val) bfin_write32(PINT0_INVERT_SET, val)
+#define bfin_read_PINT0_INVERT_CLEAR() bfin_read32(PINT0_INVERT_CLEAR)
+#define bfin_write_PINT0_INVERT_CLEAR(val) bfin_write32(PINT0_INVERT_CLEAR, val)
+#define bfin_read_PINT0_PINSTATE() bfin_read32(PINT0_PINSTATE)
+#define bfin_write_PINT0_PINSTATE(val) bfin_write32(PINT0_PINSTATE, val)
+#define bfin_read_PINT0_LATCH() bfin_read32(PINT0_LATCH)
+#define bfin_write_PINT0_LATCH(val) bfin_write32(PINT0_LATCH, val)
+
+/* Port Interrubfin_read_()t 1 Registers (32-bit) */
+
+#define bfin_read_PINT1_MASK_SET() bfin_read32(PINT1_MASK_SET)
+#define bfin_write_PINT1_MASK_SET(val) bfin_write32(PINT1_MASK_SET, val)
+#define bfin_read_PINT1_MASK_CLEAR() bfin_read32(PINT1_MASK_CLEAR)
+#define bfin_write_PINT1_MASK_CLEAR(val) bfin_write32(PINT1_MASK_CLEAR, val)
+#define bfin_read_PINT1_REQUEST() bfin_read32(PINT1_REQUEST)
+#define bfin_write_PINT1_REQUEST(val) bfin_write32(PINT1_REQUEST, val)
+#define bfin_read_PINT1_ASSIGN() bfin_read32(PINT1_ASSIGN)
+#define bfin_write_PINT1_ASSIGN(val) bfin_write32(PINT1_ASSIGN, val)
+#define bfin_read_PINT1_EDGE_SET() bfin_read32(PINT1_EDGE_SET)
+#define bfin_write_PINT1_EDGE_SET(val) bfin_write32(PINT1_EDGE_SET, val)
+#define bfin_read_PINT1_EDGE_CLEAR() bfin_read32(PINT1_EDGE_CLEAR)
+#define bfin_write_PINT1_EDGE_CLEAR(val) bfin_write32(PINT1_EDGE_CLEAR, val)
+#define bfin_read_PINT1_INVERT_SET() bfin_read32(PINT1_INVERT_SET)
+#define bfin_write_PINT1_INVERT_SET(val) bfin_write32(PINT1_INVERT_SET, val)
+#define bfin_read_PINT1_INVERT_CLEAR() bfin_read32(PINT1_INVERT_CLEAR)
+#define bfin_write_PINT1_INVERT_CLEAR(val) bfin_write32(PINT1_INVERT_CLEAR, val)
+#define bfin_read_PINT1_PINSTATE() bfin_read32(PINT1_PINSTATE)
+#define bfin_write_PINT1_PINSTATE(val) bfin_write32(PINT1_PINSTATE, val)
+#define bfin_read_PINT1_LATCH() bfin_read32(PINT1_LATCH)
+#define bfin_write_PINT1_LATCH(val) bfin_write32(PINT1_LATCH, val)
+
+/* Port Interrubfin_read_()t 2 Registers (32-bit) */
+
+#define bfin_read_PINT2_MASK_SET() bfin_read32(PINT2_MASK_SET)
+#define bfin_write_PINT2_MASK_SET(val) bfin_write32(PINT2_MASK_SET, val)
+#define bfin_read_PINT2_MASK_CLEAR() bfin_read32(PINT2_MASK_CLEAR)
+#define bfin_write_PINT2_MASK_CLEAR(val) bfin_write32(PINT2_MASK_CLEAR, val)
+#define bfin_read_PINT2_REQUEST() bfin_read32(PINT2_REQUEST)
+#define bfin_write_PINT2_REQUEST(val) bfin_write32(PINT2_REQUEST, val)
+#define bfin_read_PINT2_ASSIGN() bfin_read32(PINT2_ASSIGN)
+#define bfin_write_PINT2_ASSIGN(val) bfin_write32(PINT2_ASSIGN, val)
+#define bfin_read_PINT2_EDGE_SET() bfin_read32(PINT2_EDGE_SET)
+#define bfin_write_PINT2_EDGE_SET(val) bfin_write32(PINT2_EDGE_SET, val)
+#define bfin_read_PINT2_EDGE_CLEAR() bfin_read32(PINT2_EDGE_CLEAR)
+#define bfin_write_PINT2_EDGE_CLEAR(val) bfin_write32(PINT2_EDGE_CLEAR, val)
+#define bfin_read_PINT2_INVERT_SET() bfin_read32(PINT2_INVERT_SET)
+#define bfin_write_PINT2_INVERT_SET(val) bfin_write32(PINT2_INVERT_SET, val)
+#define bfin_read_PINT2_INVERT_CLEAR() bfin_read32(PINT2_INVERT_CLEAR)
+#define bfin_write_PINT2_INVERT_CLEAR(val) bfin_write32(PINT2_INVERT_CLEAR, val)
+#define bfin_read_PINT2_PINSTATE() bfin_read32(PINT2_PINSTATE)
+#define bfin_write_PINT2_PINSTATE(val) bfin_write32(PINT2_PINSTATE, val)
+#define bfin_read_PINT2_LATCH() bfin_read32(PINT2_LATCH)
+#define bfin_write_PINT2_LATCH(val) bfin_write32(PINT2_LATCH, val)
+
+/* Port Interrubfin_read_()t 3 Registers (32-bit) */
+
+#define bfin_read_PINT3_MASK_SET() bfin_read32(PINT3_MASK_SET)
+#define bfin_write_PINT3_MASK_SET(val) bfin_write32(PINT3_MASK_SET, val)
+#define bfin_read_PINT3_MASK_CLEAR() bfin_read32(PINT3_MASK_CLEAR)
+#define bfin_write_PINT3_MASK_CLEAR(val) bfin_write32(PINT3_MASK_CLEAR, val)
+#define bfin_read_PINT3_REQUEST() bfin_read32(PINT3_REQUEST)
+#define bfin_write_PINT3_REQUEST(val) bfin_write32(PINT3_REQUEST, val)
+#define bfin_read_PINT3_ASSIGN() bfin_read32(PINT3_ASSIGN)
+#define bfin_write_PINT3_ASSIGN(val) bfin_write32(PINT3_ASSIGN, val)
+#define bfin_read_PINT3_EDGE_SET() bfin_read32(PINT3_EDGE_SET)
+#define bfin_write_PINT3_EDGE_SET(val) bfin_write32(PINT3_EDGE_SET, val)
+#define bfin_read_PINT3_EDGE_CLEAR() bfin_read32(PINT3_EDGE_CLEAR)
+#define bfin_write_PINT3_EDGE_CLEAR(val) bfin_write32(PINT3_EDGE_CLEAR, val)
+#define bfin_read_PINT3_INVERT_SET() bfin_read32(PINT3_INVERT_SET)
+#define bfin_write_PINT3_INVERT_SET(val) bfin_write32(PINT3_INVERT_SET, val)
+#define bfin_read_PINT3_INVERT_CLEAR() bfin_read32(PINT3_INVERT_CLEAR)
+#define bfin_write_PINT3_INVERT_CLEAR(val) bfin_write32(PINT3_INVERT_CLEAR, val)
+#define bfin_read_PINT3_PINSTATE() bfin_read32(PINT3_PINSTATE)
+#define bfin_write_PINT3_PINSTATE(val) bfin_write32(PINT3_PINSTATE, val)
+#define bfin_read_PINT3_LATCH() bfin_read32(PINT3_LATCH)
+#define bfin_write_PINT3_LATCH(val) bfin_write32(PINT3_LATCH, val)
+
+/* Port Interrubfin_read_()t 4 Registers (32-bit) */
+
+#define bfin_read_PINT4_MASK_SET() bfin_read32(PINT4_MASK_SET)
+#define bfin_write_PINT4_MASK_SET(val) bfin_write32(PINT4_MASK_SET, val)
+#define bfin_read_PINT4_MASK_CLEAR() bfin_read32(PINT4_MASK_CLEAR)
+#define bfin_write_PINT4_MASK_CLEAR(val) bfin_write32(PINT4_MASK_CLEAR, val)
+#define bfin_read_PINT4_REQUEST() bfin_read32(PINT4_REQUEST)
+#define bfin_write_PINT4_REQUEST(val) bfin_write32(PINT4_REQUEST, val)
+#define bfin_read_PINT4_ASSIGN() bfin_read32(PINT4_ASSIGN)
+#define bfin_write_PINT4_ASSIGN(val) bfin_write32(PINT4_ASSIGN, val)
+#define bfin_read_PINT4_EDGE_SET() bfin_read32(PINT4_EDGE_SET)
+#define bfin_write_PINT4_EDGE_SET(val) bfin_write32(PINT4_EDGE_SET, val)
+#define bfin_read_PINT4_EDGE_CLEAR() bfin_read32(PINT4_EDGE_CLEAR)
+#define bfin_write_PINT4_EDGE_CLEAR(val) bfin_write32(PINT4_EDGE_CLEAR, val)
+#define bfin_read_PINT4_INVERT_SET() bfin_read32(PINT4_INVERT_SET)
+#define bfin_write_PINT4_INVERT_SET(val) bfin_write32(PINT4_INVERT_SET, val)
+#define bfin_read_PINT4_INVERT_CLEAR() bfin_read32(PINT4_INVERT_CLEAR)
+#define bfin_write_PINT4_INVERT_CLEAR(val) bfin_write32(PINT4_INVERT_CLEAR, val)
+#define bfin_read_PINT4_PINSTATE() bfin_read32(PINT4_PINSTATE)
+#define bfin_write_PINT4_PINSTATE(val) bfin_write32(PINT4_PINSTATE, val)
+#define bfin_read_PINT4_LATCH() bfin_read32(PINT4_LATCH)
+#define bfin_write_PINT4_LATCH(val) bfin_write32(PINT4_LATCH, val)
+
+/* Port Interrubfin_read_()t 5 Registers (32-bit) */
+
+#define bfin_read_PINT5_MASK_SET() bfin_read32(PINT5_MASK_SET)
+#define bfin_write_PINT5_MASK_SET(val) bfin_write32(PINT5_MASK_SET, val)
+#define bfin_read_PINT5_MASK_CLEAR() bfin_read32(PINT5_MASK_CLEAR)
+#define bfin_write_PINT5_MASK_CLEAR(val) bfin_write32(PINT5_MASK_CLEAR, val)
+#define bfin_read_PINT5_REQUEST() bfin_read32(PINT5_REQUEST)
+#define bfin_write_PINT5_REQUEST(val) bfin_write32(PINT5_REQUEST, val)
+#define bfin_read_PINT5_ASSIGN() bfin_read32(PINT5_ASSIGN)
+#define bfin_write_PINT5_ASSIGN(val) bfin_write32(PINT5_ASSIGN, val)
+#define bfin_read_PINT5_EDGE_SET() bfin_read32(PINT5_EDGE_SET)
+#define bfin_write_PINT5_EDGE_SET(val) bfin_write32(PINT5_EDGE_SET, val)
+#define bfin_read_PINT5_EDGE_CLEAR() bfin_read32(PINT5_EDGE_CLEAR)
+#define bfin_write_PINT5_EDGE_CLEAR(val) bfin_write32(PINT5_EDGE_CLEAR, val)
+#define bfin_read_PINT5_INVERT_SET() bfin_read32(PINT5_INVERT_SET)
+#define bfin_write_PINT5_INVERT_SET(val) bfin_write32(PINT5_INVERT_SET, val)
+#define bfin_read_PINT5_INVERT_CLEAR() bfin_read32(PINT5_INVERT_CLEAR)
+#define bfin_write_PINT5_INVERT_CLEAR(val) bfin_write32(PINT5_INVERT_CLEAR, val)
+#define bfin_read_PINT5_PINSTATE() bfin_read32(PINT5_PINSTATE)
+#define bfin_write_PINT5_PINSTATE(val) bfin_write32(PINT5_PINSTATE, val)
+#define bfin_read_PINT5_LATCH() bfin_read32(PINT5_LATCH)
+#define bfin_write_PINT5_LATCH(val) bfin_write32(PINT5_LATCH, val)
+
+/* Port A Registers */
+
+#define bfin_read_PORTA_FER() bfin_read32(PORTA_FER)
+#define bfin_write_PORTA_FER(val) bfin_write32(PORTA_FER, val)
+#define bfin_read_PORTA_FER_SET() bfin_read32(PORTA_FER_SET)
+#define bfin_write_PORTA_FER_SET(val) bfin_write32(PORTA_FER_SET, val)
+#define bfin_read_PORTA_FER_CLEAR() bfin_read32(PORTA_FER_CLEAR)
+#define bfin_write_PORTA_FER_CLEAR(val) bfin_write32(PORTA_FER_CLEAR, val)
+#define bfin_read_PORTA() bfin_read32(PORTA)
+#define bfin_write_PORTA(val) bfin_write32(PORTA, val)
+#define bfin_read_PORTA_SET() bfin_read32(PORTA_SET)
+#define bfin_write_PORTA_SET(val) bfin_write32(PORTA_SET, val)
+#define bfin_read_PORTA_CLEAR() bfin_read32(PORTA_CLEAR)
+#define bfin_write_PORTA_CLEAR(val) bfin_write32(PORTA_CLEAR, val)
+#define bfin_read_PORTA_DIR() bfin_read32(PORTA_DIR)
+#define bfin_write_PORTA_DIR(val) bfin_write32(PORTA_DIR, val)
+#define bfin_read_PORTA_DIR_SET() bfin_read32(PORTA_DIR_SET)
+#define bfin_write_PORTA_DIR_SET(val) bfin_write32(PORTA_DIR_SET, val)
+#define bfin_read_PORTA_DIR_CLEAR() bfin_read32(PORTA_DIR_CLEAR)
+#define bfin_write_PORTA_DIR_CLEAR(val) bfin_write32(PORTA_DIR_CLEAR, val)
+#define bfin_read_PORTA_INEN() bfin_read32(PORTA_INEN)
+#define bfin_write_PORTA_INEN(val) bfin_write32(PORTA_INEN, val)
+#define bfin_read_PORTA_INEN_SET() bfin_read32(PORTA_INEN_SET)
+#define bfin_write_PORTA_INEN_SET(val) bfin_write32(PORTA_INEN_SET, val)
+#define bfin_read_PORTA_INEN_CLEAR() bfin_read32(PORTA_INEN_CLEAR)
+#define bfin_write_PORTA_INEN_CLEAR(val) bfin_write32(PORTA_INEN_CLEAR, val)
+#define bfin_read_PORTA_MUX() bfin_read32(PORTA_MUX)
+#define bfin_write_PORTA_MUX(val) bfin_write32(PORTA_MUX, val)
+#define bfin_read_PORTA_DATA_TGL() bfin_read32(PORTA_DATA_TGL)
+#define bfin_write_PORTA_DATA_TGL(val) bfin_write32(PORTA_DATA_TGL, val)
+#define bfin_read_PORTA_POL() bfin_read32(PORTA_POL)
+#define bfin_write_PORTA_POL(val) bfin_write32(PORTA_POL, val)
+#define bfin_read_PORTA_POL_SET() bfin_read32(PORTA_POL_SET)
+#define bfin_write_PORTA_POL_SET(val) bfin_write32(PORTA_POL_SET, val)
+#define bfin_read_PORTA_POL_CLEAR() bfin_read32(PORTA_POL_CLEAR)
+#define bfin_write_PORTA_POL_CLEAR(val) bfin_write32(PORTA_POL_CLEAR, val)
+#define bfin_read_PORTA_LOCK() bfin_read32(PORTA_LOCK)
+#define bfin_write_PORTA_LOCK(val) bfin_write32(PORTA_LOCK, val)
+#define bfin_read_PORTA_REVID() bfin_read32(PORTA_REVID)
+#define bfin_write_PORTA_REVID(val) bfin_write32(PORTA_REVID, val)
+
+
+
+/* Port B Registers */
+#define bfin_read_PORTB_FER() bfin_read32(PORTB_FER)
+#define bfin_write_PORTB_FER(val) bfin_write32(PORTB_FER, val)
+#define bfin_read_PORTB_FER_SET() bfin_read32(PORTB_FER_SET)
+#define bfin_write_PORTB_FER_SET(val) bfin_write32(PORTB_FER_SET, val)
+#define bfin_read_PORTB_FER_CLEAR() bfin_read32(PORTB_FER_CLEAR)
+#define bfin_write_PORTB_FER_CLEAR(val) bfin_write32(PORTB_FER_CLEAR, val)
+#define bfin_read_PORTB() bfin_read32(PORTB)
+#define bfin_write_PORTB(val) bfin_write32(PORTB, val)
+#define bfin_read_PORTB_SET() bfin_read32(PORTB_SET)
+#define bfin_write_PORTB_SET(val) bfin_write32(PORTB_SET, val)
+#define bfin_read_PORTB_CLEAR() bfin_read32(PORTB_CLEAR)
+#define bfin_write_PORTB_CLEAR(val) bfin_write32(PORTB_CLEAR, val)
+#define bfin_read_PORTB_DIR() bfin_read32(PORTB_DIR)
+#define bfin_write_PORTB_DIR(val) bfin_write32(PORTB_DIR, val)
+#define bfin_read_PORTB_DIR_SET() bfin_read32(PORTB_DIR_SET)
+#define bfin_write_PORTB_DIR_SET(val) bfin_write32(PORTB_DIR_SET, val)
+#define bfin_read_PORTB_DIR_CLEAR() bfin_read32(PORTB_DIR_CLEAR)
+#define bfin_write_PORTB_DIR_CLEAR(val) bfin_write32(PORTB_DIR_CLEAR, val)
+#define bfin_read_PORTB_INEN() bfin_read32(PORTB_INEN)
+#define bfin_write_PORTB_INEN(val) bfin_write32(PORTB_INEN, val)
+#define bfin_read_PORTB_INEN_SET() bfin_read32(PORTB_INEN_SET)
+#define bfin_write_PORTB_INEN_SET(val) bfin_write32(PORTB_INEN_SET, val)
+#define bfin_read_PORTB_INEN_CLEAR() bfin_read32(PORTB_INEN_CLEAR)
+#define bfin_write_PORTB_INEN_CLEAR(val) bfin_write32(PORTB_INEN_CLEAR, val)
+#define bfin_read_PORTB_MUX() bfin_read32(PORTB_MUX)
+#define bfin_write_PORTB_MUX(val) bfin_write32(PORTB_MUX, val)
+#define bfin_read_PORTB_DATA_TGL() bfin_read32(PORTB_DATA_TGL)
+#define bfin_write_PORTB_DATA_TGL(val) bfin_write32(PORTB_DATA_TGL, val)
+#define bfin_read_PORTB_POL() bfin_read32(PORTB_POL)
+#define bfin_write_PORTB_POL(val) bfin_write32(PORTB_POL, val)
+#define bfin_read_PORTB_POL_SET() bfin_read32(PORTB_POL_SET)
+#define bfin_write_PORTB_POL_SET(val) bfin_write32(PORTB_POL_SET, val)
+#define bfin_read_PORTB_POL_CLEAR() bfin_read32(PORTB_POL_CLEAR)
+#define bfin_write_PORTB_POL_CLEAR(val) bfin_write32(PORTB_POL_CLEAR, val)
+#define bfin_read_PORTB_LOCK() bfin_read32(PORTB_LOCK)
+#define bfin_write_PORTB_LOCK(val) bfin_write32(PORTB_LOCK, val)
+#define bfin_read_PORTB_REVID() bfin_read32(PORTB_REVID)
+#define bfin_write_PORTB_REVID(val) bfin_write32(PORTB_REVID, val)
+
+
+/* Port C Registers */
+#define bfin_read_PORTC_FER() bfin_read32(PORTC_FER)
+#define bfin_write_PORTC_FER(val) bfin_write32(PORTC_FER, val)
+#define bfin_read_PORTC_FER_SET() bfin_read32(PORTC_FER_SET)
+#define bfin_write_PORTC_FER_SET(val) bfin_write32(PORTC_FER_SET, val)
+#define bfin_read_PORTC_FER_CLEAR() bfin_read32(PORTC_FER_CLEAR)
+#define bfin_write_PORTC_FER_CLEAR(val) bfin_write32(PORTC_FER_CLEAR, val)
+#define bfin_read_PORTC() bfin_read32(PORTC)
+#define bfin_write_PORTC(val) bfin_write32(PORTC, val)
+#define bfin_read_PORTC_SET() bfin_read32(PORTC_SET)
+#define bfin_write_PORTC_SET(val) bfin_write32(PORTC_SET, val)
+#define bfin_read_PORTC_CLEAR() bfin_read32(PORTC_CLEAR)
+#define bfin_write_PORTC_CLEAR(val) bfin_write32(PORTC_CLEAR, val)
+#define bfin_read_PORTC_DIR() bfin_read32(PORTC_DIR)
+#define bfin_write_PORTC_DIR(val) bfin_write32(PORTC_DIR, val)
+#define bfin_read_PORTC_DIR_SET() bfin_read32(PORTC_DIR_SET)
+#define bfin_write_PORTC_DIR_SET(val) bfin_write32(PORTC_DIR_SET, val)
+#define bfin_read_PORTC_DIR_CLEAR() bfin_read32(PORTC_DIR_CLEAR)
+#define bfin_write_PORTC_DIR_CLEAR(val) bfin_write32(PORTC_DIR_CLEAR, val)
+#define bfin_read_PORTC_INEN() bfin_read32(PORTC_INEN)
+#define bfin_write_PORTC_INEN(val) bfin_write32(PORTC_INEN, val)
+#define bfin_read_PORTC_INEN_SET() bfin_read32(PORTC_INEN_SET)
+#define bfin_write_PORTC_INEN_SET(val) bfin_write32(PORTC_INEN_SET, val)
+#define bfin_read_PORTC_INEN_CLEAR() bfin_read32(PORTC_INEN_CLEAR)
+#define bfin_write_PORTC_INEN_CLEAR(val) bfin_write32(PORTC_INEN_CLEAR, val)
+#define bfin_read_PORTC_MUX() bfin_read32(PORTC_MUX)
+#define bfin_write_PORTC_MUX(val) bfin_write32(PORTC_MUX, val)
+#define bfin_read_PORTC_DATA_TGL() bfin_read32(PORTC_DATA_TGL)
+#define bfin_write_PORTC_DATA_TGL(val) bfin_write32(PORTC_DATA_TGL, val)
+#define bfin_read_PORTC_POL() bfin_read32(PORTC_POL)
+#define bfin_write_PORTC_POL(val) bfin_write32(PORTC_POL, val)
+#define bfin_read_PORTC_POL_SET() bfin_read32(PORTC_POL_SET)
+#define bfin_write_PORTC_POL_SET(val) bfin_write32(PORTC_POL_SET, val)
+#define bfin_read_PORTC_POL_CLEAR() bfin_read32(PORTC_POL_CLEAR)
+#define bfin_write_PORTC_POL_CLEAR(val) bfin_write32(PORTC_POL_CLEAR, val)
+#define bfin_read_PORTC_LOCK() bfin_read32(PORTC_LOCK)
+#define bfin_write_PORTC_LOCK(val) bfin_write32(PORTC_LOCK, val)
+#define bfin_read_PORTC_REVID() bfin_read32(PORTC_REVID)
+#define bfin_write_PORTC_REVID(val) bfin_write32(PORTC_REVID, val)
+
+
+/* Port D Registers */
+#define bfin_read_PORTD_FER() bfin_read32(PORTD_FER)
+#define bfin_write_PORTD_FER(val) bfin_write32(PORTD_FER, val)
+#define bfin_read_PORTD_FER_SET() bfin_read32(PORTD_FER_SET)
+#define bfin_write_PORTD_FER_SET(val) bfin_write32(PORTD_FER_SET, val)
+#define bfin_read_PORTD_FER_CLEAR() bfin_read32(PORTD_FER_CLEAR)
+#define bfin_write_PORTD_FER_CLEAR(val) bfin_write32(PORTD_FER_CLEAR, val)
+#define bfin_read_PORTD() bfin_read32(PORTD)
+#define bfin_write_PORTD(val) bfin_write32(PORTD, val)
+#define bfin_read_PORTD_SET() bfin_read32(PORTD_SET)
+#define bfin_write_PORTD_SET(val) bfin_write32(PORTD_SET, val)
+#define bfin_read_PORTD_CLEAR() bfin_read32(PORTD_CLEAR)
+#define bfin_write_PORTD_CLEAR(val) bfin_write32(PORTD_CLEAR, val)
+#define bfin_read_PORTD_DIR() bfin_read32(PORTD_DIR)
+#define bfin_write_PORTD_DIR(val) bfin_write32(PORTD_DIR, val)
+#define bfin_read_PORTD_DIR_SET() bfin_read32(PORTD_DIR_SET)
+#define bfin_write_PORTD_DIR_SET(val) bfin_write32(PORTD_DIR_SET, val)
+#define bfin_read_PORTD_DIR_CLEAR() bfin_read32(PORTD_DIR_CLEAR)
+#define bfin_write_PORTD_DIR_CLEAR(val) bfin_write32(PORTD_DIR_CLEAR, val)
+#define bfin_read_PORTD_INEN() bfin_read32(PORTD_INEN)
+#define bfin_write_PORTD_INEN(val) bfin_write32(PORTD_INEN, val)
+#define bfin_read_PORTD_INEN_SET() bfin_read32(PORTD_INEN_SET)
+#define bfin_write_PORTD_INEN_SET(val) bfin_write32(PORTD_INEN_SET, val)
+#define bfin_read_PORTD_INEN_CLEAR() bfin_read32(PORTD_INEN_CLEAR)
+#define bfin_write_PORTD_INEN_CLEAR(val) bfin_write32(PORTD_INEN_CLEAR, val)
+#define bfin_read_PORTD_MUX() bfin_read32(PORTD_MUX)
+#define bfin_write_PORTD_MUX(val) bfin_write32(PORTD_MUX, val)
+#define bfin_read_PORTD_DATA_TGL() bfin_read32(PORTD_DATA_TGL)
+#define bfin_write_PORTD_DATA_TGL(val) bfin_write32(PORTD_DATA_TGL, val)
+#define bfin_read_PORTD_POL() bfin_read32(PORTD_POL)
+#define bfin_write_PORTD_POL(val) bfin_write32(PORTD_POL, val)
+#define bfin_read_PORTD_POL_SET() bfin_read32(PORTD_POL_SET)
+#define bfin_write_PORTD_POL_SET(val) bfin_write32(PORTD_POL_SET, val)
+#define bfin_read_PORTD_POL_CLEAR() bfin_read32(PORTD_POL_CLEAR)
+#define bfin_write_PORTD_POL_CLEAR(val) bfin_write32(PORTD_POL_CLEAR, val)
+#define bfin_read_PORTD_LOCK() bfin_read32(PORTD_LOCK)
+#define bfin_write_PORTD_LOCK(val) bfin_write32(PORTD_LOCK, val)
+#define bfin_read_PORTD_REVID() bfin_read32(PORTD_REVID)
+#define bfin_write_PORTD_REVID(val) bfin_write32(PORTD_REVID, val)
+
+
+/* Port E Registers */
+#define bfin_read_PORTE_FER() bfin_read32(PORTE_FER)
+#define bfin_write_PORTE_FER(val) bfin_write32(PORTE_FER, val)
+#define bfin_read_PORTE_FER_SET() bfin_read32(PORTE_FER_SET)
+#define bfin_write_PORTE_FER_SET(val) bfin_write32(PORTE_FER_SET, val)
+#define bfin_read_PORTE_FER_CLEAR() bfin_read32(PORTE_FER_CLEAR)
+#define bfin_write_PORTE_FER_CLEAR(val) bfin_write32(PORTE_FER_CLEAR, val)
+#define bfin_read_PORTE() bfin_read32(PORTE)
+#define bfin_write_PORTE(val) bfin_write32(PORTE, val)
+#define bfin_read_PORTE_SET() bfin_read32(PORTE_SET)
+#define bfin_write_PORTE_SET(val) bfin_write32(PORTE_SET, val)
+#define bfin_read_PORTE_CLEAR() bfin_read32(PORTE_CLEAR)
+#define bfin_write_PORTE_CLEAR(val) bfin_write32(PORTE_CLEAR, val)
+#define bfin_read_PORTE_DIR() bfin_read32(PORTE_DIR)
+#define bfin_write_PORTE_DIR(val) bfin_write32(PORTE_DIR, val)
+#define bfin_read_PORTE_DIR_SET() bfin_read32(PORTE_DIR_SET)
+#define bfin_write_PORTE_DIR_SET(val) bfin_write32(PORTE_DIR_SET, val)
+#define bfin_read_PORTE_DIR_CLEAR() bfin_read32(PORTE_DIR_CLEAR)
+#define bfin_write_PORTE_DIR_CLEAR(val) bfin_write32(PORTE_DIR_CLEAR, val)
+#define bfin_read_PORTE_INEN() bfin_read32(PORTE_INEN)
+#define bfin_write_PORTE_INEN(val) bfin_write32(PORTE_INEN, val)
+#define bfin_read_PORTE_INEN_SET() bfin_read32(PORTE_INEN_SET)
+#define bfin_write_PORTE_INEN_SET(val) bfin_write32(PORTE_INEN_SET, val)
+#define bfin_read_PORTE_INEN_CLEAR() bfin_read32(PORTE_INEN_CLEAR)
+#define bfin_write_PORTE_INEN_CLEAR(val) bfin_write32(PORTE_INEN_CLEAR, val)
+#define bfin_read_PORTE_MUX() bfin_read32(PORTE_MUX)
+#define bfin_write_PORTE_MUX(val) bfin_write32(PORTE_MUX, val)
+#define bfin_read_PORTE_DATA_TGL() bfin_read32(PORTE_DATA_TGL)
+#define bfin_write_PORTE_DATA_TGL(val) bfin_write32(PORTE_DATA_TGL, val)
+#define bfin_read_PORTE_POL() bfin_read32(PORTE_POL)
+#define bfin_write_PORTE_POL(val) bfin_write32(PORTE_POL, val)
+#define bfin_read_PORTE_POL_SET() bfin_read32(PORTE_POL_SET)
+#define bfin_write_PORTE_POL_SET(val) bfin_write32(PORTE_POL_SET, val)
+#define bfin_read_PORTE_POL_CLEAR() bfin_read32(PORTE_POL_CLEAR)
+#define bfin_write_PORTE_POL_CLEAR(val) bfin_write32(PORTE_POL_CLEAR, val)
+#define bfin_read_PORTE_LOCK() bfin_read32(PORTE_LOCK)
+#define bfin_write_PORTE_LOCK(val) bfin_write32(PORTE_LOCK, val)
+#define bfin_read_PORTE_REVID() bfin_read32(PORTE_REVID)
+#define bfin_write_PORTE_REVID(val) bfin_write32(PORTE_REVID, val)
+
+
+/* Port F Registers */
+#define bfin_read_PORTF_FER() bfin_read32(PORTF_FER)
+#define bfin_write_PORTF_FER(val) bfin_write32(PORTF_FER, val)
+#define bfin_read_PORTF_FER_SET() bfin_read32(PORTF_FER_SET)
+#define bfin_write_PORTF_FER_SET(val) bfin_write32(PORTF_FER_SET, val)
+#define bfin_read_PORTF_FER_CLEAR() bfin_read32(PORTF_FER_CLEAR)
+#define bfin_write_PORTF_FER_CLEAR(val) bfin_write32(PORTF_FER_CLEAR, val)
+#define bfin_read_PORTF() bfin_read32(PORTF)
+#define bfin_write_PORTF(val) bfin_write32(PORTF, val)
+#define bfin_read_PORTF_SET() bfin_read32(PORTF_SET)
+#define bfin_write_PORTF_SET(val) bfin_write32(PORTF_SET, val)
+#define bfin_read_PORTF_CLEAR() bfin_read32(PORTF_CLEAR)
+#define bfin_write_PORTF_CLEAR(val) bfin_write32(PORTF_CLEAR, val)
+#define bfin_read_PORTF_DIR() bfin_read32(PORTF_DIR)
+#define bfin_write_PORTF_DIR(val) bfin_write32(PORTF_DIR, val)
+#define bfin_read_PORTF_DIR_SET() bfin_read32(PORTF_DIR_SET)
+#define bfin_write_PORTF_DIR_SET(val) bfin_write32(PORTF_DIR_SET, val)
+#define bfin_read_PORTF_DIR_CLEAR() bfin_read32(PORTF_DIR_CLEAR)
+#define bfin_write_PORTF_DIR_CLEAR(val) bfin_write32(PORTF_DIR_CLEAR, val)
+#define bfin_read_PORTF_INEN() bfin_read32(PORTF_INEN)
+#define bfin_write_PORTF_INEN(val) bfin_write32(PORTF_INEN, val)
+#define bfin_read_PORTF_INEN_SET() bfin_read32(PORTF_INEN_SET)
+#define bfin_write_PORTF_INEN_SET(val) bfin_write32(PORTF_INEN_SET, val)
+#define bfin_read_PORTF_INEN_CLEAR() bfin_read32(PORTF_INEN_CLEAR)
+#define bfin_write_PORTF_INEN_CLEAR(val) bfin_write32(PORTF_INEN_CLEAR, val)
+#define bfin_read_PORTF_MUX() bfin_read32(PORTF_MUX)
+#define bfin_write_PORTF_MUX(val) bfin_write32(PORTF_MUX, val)
+#define bfin_read_PORTF_DATA_TGL() bfin_read32(PORTF_DATA_TGL)
+#define bfin_write_PORTF_DATA_TGL(val) bfin_write32(PORTF_DATA_TGL, val)
+#define bfin_read_PORTF_POL() bfin_read32(PORTF_POL)
+#define bfin_write_PORTF_POL(val) bfin_write32(PORTF_POL, val)
+#define bfin_read_PORTF_POL_SET() bfin_read32(PORTF_POL_SET)
+#define bfin_write_PORTF_POL_SET(val) bfin_write32(PORTF_POL_SET, val)
+#define bfin_read_PORTF_POL_CLEAR() bfin_read32(PORTF_POL_CLEAR)
+#define bfin_write_PORTF_POL_CLEAR(val) bfin_write32(PORTF_POL_CLEAR, val)
+#define bfin_read_PORTF_LOCK() bfin_read32(PORTF_LOCK)
+#define bfin_write_PORTF_LOCK(val) bfin_write32(PORTF_LOCK, val)
+#define bfin_read_PORTF_REVID() bfin_read32(PORTF_REVID)
+#define bfin_write_PORTF_REVID(val) bfin_write32(PORTF_REVID, val)
+
+
+/* Port G Registers */
+#define bfin_read_PORTG_FER() bfin_read32(PORTG_FER)
+#define bfin_write_PORTG_FER(val) bfin_write32(PORTG_FER, val)
+#define bfin_read_PORTG_FER_SET() bfin_read32(PORTG_FER_SET)
+#define bfin_write_PORTG_FER_SET(val) bfin_write32(PORTG_FER_SET, val)
+#define bfin_read_PORTG_FER_CLEAR() bfin_read32(PORTG_FER_CLEAR)
+#define bfin_write_PORTG_FER_CLEAR(val) bfin_write32(PORTG_FER_CLEAR, val)
+#define bfin_read_PORTG() bfin_read32(PORTG)
+#define bfin_write_PORTG(val) bfin_write32(PORTG, val)
+#define bfin_read_PORTG_SET() bfin_read32(PORTG_SET)
+#define bfin_write_PORTG_SET(val) bfin_write32(PORTG_SET, val)
+#define bfin_read_PORTG_CLEAR() bfin_read32(PORTG_CLEAR)
+#define bfin_write_PORTG_CLEAR(val) bfin_write32(PORTG_CLEAR, val)
+#define bfin_read_PORTG_DIR() bfin_read32(PORTG_DIR)
+#define bfin_write_PORTG_DIR(val) bfin_write32(PORTG_DIR, val)
+#define bfin_read_PORTG_DIR_SET() bfin_read32(PORTG_DIR_SET)
+#define bfin_write_PORTG_DIR_SET(val) bfin_write32(PORTG_DIR_SET, val)
+#define bfin_read_PORTG_DIR_CLEAR() bfin_read32(PORTG_DIR_CLEAR)
+#define bfin_write_PORTG_DIR_CLEAR(val) bfin_write32(PORTG_DIR_CLEAR, val)
+#define bfin_read_PORTG_INEN() bfin_read32(PORTG_INEN)
+#define bfin_write_PORTG_INEN(val) bfin_write32(PORTG_INEN, val)
+#define bfin_read_PORTG_INEN_SET() bfin_read32(PORTG_INEN_SET)
+#define bfin_write_PORTG_INEN_SET(val) bfin_write32(PORTG_INEN_SET, val)
+#define bfin_read_PORTG_INEN_CLEAR() bfin_read32(PORTG_INEN_CLEAR)
+#define bfin_write_PORTG_INEN_CLEAR(val) bfin_write32(PORTG_INEN_CLEAR, val)
+#define bfin_read_PORTG_MUX() bfin_read32(PORTG_MUX)
+#define bfin_write_PORTG_MUX(val) bfin_write32(PORTG_MUX, val)
+#define bfin_read_PORTG_DATA_TGL() bfin_read32(PORTG_DATA_TGL)
+#define bfin_write_PORTG_DATA_TGL(val) bfin_write32(PORTG_DATA_TGL, val)
+#define bfin_read_PORTG_POL() bfin_read32(PORTG_POL)
+#define bfin_write_PORTG_POL(val) bfin_write32(PORTG_POL, val)
+#define bfin_read_PORTG_POL_SET() bfin_read32(PORTG_POL_SET)
+#define bfin_write_PORTG_POL_SET(val) bfin_write32(PORTG_POL_SET, val)
+#define bfin_read_PORTG_POL_CLEAR() bfin_read32(PORTG_POL_CLEAR)
+#define bfin_write_PORTG_POL_CLEAR(val) bfin_write32(PORTG_POL_CLEAR, val)
+#define bfin_read_PORTG_LOCK() bfin_read32(PORTG_LOCK)
+#define bfin_write_PORTG_LOCK(val) bfin_write32(PORTG_LOCK, val)
+#define bfin_read_PORTG_REVID() bfin_read32(PORTG_REVID)
+#define bfin_write_PORTG_REVID(val) bfin_write32(PORTG_REVID, val)
+
+
+
+
+/* CAN Controller 0 Config 1 Registers */
+
+#define bfin_read_CAN0_MC1() bfin_read16(CAN0_MC1)
+#define bfin_write_CAN0_MC1(val) bfin_write16(CAN0_MC1, val)
+#define bfin_read_CAN0_MD1() bfin_read16(CAN0_MD1)
+#define bfin_write_CAN0_MD1(val) bfin_write16(CAN0_MD1, val)
+#define bfin_read_CAN0_TRS1() bfin_read16(CAN0_TRS1)
+#define bfin_write_CAN0_TRS1(val) bfin_write16(CAN0_TRS1, val)
+#define bfin_read_CAN0_TRR1() bfin_read16(CAN0_TRR1)
+#define bfin_write_CAN0_TRR1(val) bfin_write16(CAN0_TRR1, val)
+#define bfin_read_CAN0_TA1() bfin_read16(CAN0_TA1)
+#define bfin_write_CAN0_TA1(val) bfin_write16(CAN0_TA1, val)
+#define bfin_read_CAN0_AA1() bfin_read16(CAN0_AA1)
+#define bfin_write_CAN0_AA1(val) bfin_write16(CAN0_AA1, val)
+#define bfin_read_CAN0_RMP1() bfin_read16(CAN0_RMP1)
+#define bfin_write_CAN0_RMP1(val) bfin_write16(CAN0_RMP1, val)
+#define bfin_read_CAN0_RML1() bfin_read16(CAN0_RML1)
+#define bfin_write_CAN0_RML1(val) bfin_write16(CAN0_RML1, val)
+#define bfin_read_CAN0_MBTIF1() bfin_read16(CAN0_MBTIF1)
+#define bfin_write_CAN0_MBTIF1(val) bfin_write16(CAN0_MBTIF1, val)
+#define bfin_read_CAN0_MBRIF1() bfin_read16(CAN0_MBRIF1)
+#define bfin_write_CAN0_MBRIF1(val) bfin_write16(CAN0_MBRIF1, val)
+#define bfin_read_CAN0_MBIM1() bfin_read16(CAN0_MBIM1)
+#define bfin_write_CAN0_MBIM1(val) bfin_write16(CAN0_MBIM1, val)
+#define bfin_read_CAN0_RFH1() bfin_read16(CAN0_RFH1)
+#define bfin_write_CAN0_RFH1(val) bfin_write16(CAN0_RFH1, val)
+#define bfin_read_CAN0_OPSS1() bfin_read16(CAN0_OPSS1)
+#define bfin_write_CAN0_OPSS1(val) bfin_write16(CAN0_OPSS1, val)
+
+/* CAN Controller 0 Config 2 Registers */
+
+#define bfin_read_CAN0_MC2() bfin_read16(CAN0_MC2)
+#define bfin_write_CAN0_MC2(val) bfin_write16(CAN0_MC2, val)
+#define bfin_read_CAN0_MD2() bfin_read16(CAN0_MD2)
+#define bfin_write_CAN0_MD2(val) bfin_write16(CAN0_MD2, val)
+#define bfin_read_CAN0_TRS2() bfin_read16(CAN0_TRS2)
+#define bfin_write_CAN0_TRS2(val) bfin_write16(CAN0_TRS2, val)
+#define bfin_read_CAN0_TRR2() bfin_read16(CAN0_TRR2)
+#define bfin_write_CAN0_TRR2(val) bfin_write16(CAN0_TRR2, val)
+#define bfin_read_CAN0_TA2() bfin_read16(CAN0_TA2)
+#define bfin_write_CAN0_TA2(val) bfin_write16(CAN0_TA2, val)
+#define bfin_read_CAN0_AA2() bfin_read16(CAN0_AA2)
+#define bfin_write_CAN0_AA2(val) bfin_write16(CAN0_AA2, val)
+#define bfin_read_CAN0_RMP2() bfin_read16(CAN0_RMP2)
+#define bfin_write_CAN0_RMP2(val) bfin_write16(CAN0_RMP2, val)
+#define bfin_read_CAN0_RML2() bfin_read16(CAN0_RML2)
+#define bfin_write_CAN0_RML2(val) bfin_write16(CAN0_RML2, val)
+#define bfin_read_CAN0_MBTIF2() bfin_read16(CAN0_MBTIF2)
+#define bfin_write_CAN0_MBTIF2(val) bfin_write16(CAN0_MBTIF2, val)
+#define bfin_read_CAN0_MBRIF2() bfin_read16(CAN0_MBRIF2)
+#define bfin_write_CAN0_MBRIF2(val) bfin_write16(CAN0_MBRIF2, val)
+#define bfin_read_CAN0_MBIM2() bfin_read16(CAN0_MBIM2)
+#define bfin_write_CAN0_MBIM2(val) bfin_write16(CAN0_MBIM2, val)
+#define bfin_read_CAN0_RFH2() bfin_read16(CAN0_RFH2)
+#define bfin_write_CAN0_RFH2(val) bfin_write16(CAN0_RFH2, val)
+#define bfin_read_CAN0_OPSS2() bfin_read16(CAN0_OPSS2)
+#define bfin_write_CAN0_OPSS2(val) bfin_write16(CAN0_OPSS2, val)
+
+/* CAN Controller 0 Clock/Interrubfin_read_()t/Counter Registers */
+
+#define bfin_read_CAN0_CLOCK() bfin_read16(CAN0_CLOCK)
+#define bfin_write_CAN0_CLOCK(val) bfin_write16(CAN0_CLOCK, val)
+#define bfin_read_CAN0_TIMING() bfin_read16(CAN0_TIMING)
+#define bfin_write_CAN0_TIMING(val) bfin_write16(CAN0_TIMING, val)
+#define bfin_read_CAN0_DEBUG() bfin_read16(CAN0_DEBUG)
+#define bfin_write_CAN0_DEBUG(val) bfin_write16(CAN0_DEBUG, val)
+#define bfin_read_CAN0_STATUS() bfin_read16(CAN0_STATUS)
+#define bfin_write_CAN0_STATUS(val) bfin_write16(CAN0_STATUS, val)
+#define bfin_read_CAN0_CEC() bfin_read16(CAN0_CEC)
+#define bfin_write_CAN0_CEC(val) bfin_write16(CAN0_CEC, val)
+#define bfin_read_CAN0_GIS() bfin_read16(CAN0_GIS)
+#define bfin_write_CAN0_GIS(val) bfin_write16(CAN0_GIS, val)
+#define bfin_read_CAN0_GIM() bfin_read16(CAN0_GIM)
+#define bfin_write_CAN0_GIM(val) bfin_write16(CAN0_GIM, val)
+#define bfin_read_CAN0_GIF() bfin_read16(CAN0_GIF)
+#define bfin_write_CAN0_GIF(val) bfin_write16(CAN0_GIF, val)
+#define bfin_read_CAN0_CONTROL() bfin_read16(CAN0_CONTROL)
+#define bfin_write_CAN0_CONTROL(val) bfin_write16(CAN0_CONTROL, val)
+#define bfin_read_CAN0_INTR() bfin_read16(CAN0_INTR)
+#define bfin_write_CAN0_INTR(val) bfin_write16(CAN0_INTR, val)
+#define bfin_read_CAN0_MBTD() bfin_read16(CAN0_MBTD)
+#define bfin_write_CAN0_MBTD(val) bfin_write16(CAN0_MBTD, val)
+#define bfin_read_CAN0_EWR() bfin_read16(CAN0_EWR)
+#define bfin_write_CAN0_EWR(val) bfin_write16(CAN0_EWR, val)
+#define bfin_read_CAN0_ESR() bfin_read16(CAN0_ESR)
+#define bfin_write_CAN0_ESR(val) bfin_write16(CAN0_ESR, val)
+#define bfin_read_CAN0_UCCNT() bfin_read16(CAN0_UCCNT)
+#define bfin_write_CAN0_UCCNT(val) bfin_write16(CAN0_UCCNT, val)
+#define bfin_read_CAN0_UCRC() bfin_read16(CAN0_UCRC)
+#define bfin_write_CAN0_UCRC(val) bfin_write16(CAN0_UCRC, val)
+#define bfin_read_CAN0_UCCNF() bfin_read16(CAN0_UCCNF)
+#define bfin_write_CAN0_UCCNF(val) bfin_write16(CAN0_UCCNF, val)
+
+/* CAN Controller 0 Accebfin_read_()tance Registers */
+
+#define bfin_read_CAN0_AM00L() bfin_read16(CAN0_AM00L)
+#define bfin_write_CAN0_AM00L(val) bfin_write16(CAN0_AM00L, val)
+#define bfin_read_CAN0_AM00H() bfin_read16(CAN0_AM00H)
+#define bfin_write_CAN0_AM00H(val) bfin_write16(CAN0_AM00H, val)
+#define bfin_read_CAN0_AM01L() bfin_read16(CAN0_AM01L)
+#define bfin_write_CAN0_AM01L(val) bfin_write16(CAN0_AM01L, val)
+#define bfin_read_CAN0_AM01H() bfin_read16(CAN0_AM01H)
+#define bfin_write_CAN0_AM01H(val) bfin_write16(CAN0_AM01H, val)
+#define bfin_read_CAN0_AM02L() bfin_read16(CAN0_AM02L)
+#define bfin_write_CAN0_AM02L(val) bfin_write16(CAN0_AM02L, val)
+#define bfin_read_CAN0_AM02H() bfin_read16(CAN0_AM02H)
+#define bfin_write_CAN0_AM02H(val) bfin_write16(CAN0_AM02H, val)
+#define bfin_read_CAN0_AM03L() bfin_read16(CAN0_AM03L)
+#define bfin_write_CAN0_AM03L(val) bfin_write16(CAN0_AM03L, val)
+#define bfin_read_CAN0_AM03H() bfin_read16(CAN0_AM03H)
+#define bfin_write_CAN0_AM03H(val) bfin_write16(CAN0_AM03H, val)
+#define bfin_read_CAN0_AM04L() bfin_read16(CAN0_AM04L)
+#define bfin_write_CAN0_AM04L(val) bfin_write16(CAN0_AM04L, val)
+#define bfin_read_CAN0_AM04H() bfin_read16(CAN0_AM04H)
+#define bfin_write_CAN0_AM04H(val) bfin_write16(CAN0_AM04H, val)
+#define bfin_read_CAN0_AM05L() bfin_read16(CAN0_AM05L)
+#define bfin_write_CAN0_AM05L(val) bfin_write16(CAN0_AM05L, val)
+#define bfin_read_CAN0_AM05H() bfin_read16(CAN0_AM05H)
+#define bfin_write_CAN0_AM05H(val) bfin_write16(CAN0_AM05H, val)
+#define bfin_read_CAN0_AM06L() bfin_read16(CAN0_AM06L)
+#define bfin_write_CAN0_AM06L(val) bfin_write16(CAN0_AM06L, val)
+#define bfin_read_CAN0_AM06H() bfin_read16(CAN0_AM06H)
+#define bfin_write_CAN0_AM06H(val) bfin_write16(CAN0_AM06H, val)
+#define bfin_read_CAN0_AM07L() bfin_read16(CAN0_AM07L)
+#define bfin_write_CAN0_AM07L(val) bfin_write16(CAN0_AM07L, val)
+#define bfin_read_CAN0_AM07H() bfin_read16(CAN0_AM07H)
+#define bfin_write_CAN0_AM07H(val) bfin_write16(CAN0_AM07H, val)
+#define bfin_read_CAN0_AM08L() bfin_read16(CAN0_AM08L)
+#define bfin_write_CAN0_AM08L(val) bfin_write16(CAN0_AM08L, val)
+#define bfin_read_CAN0_AM08H() bfin_read16(CAN0_AM08H)
+#define bfin_write_CAN0_AM08H(val) bfin_write16(CAN0_AM08H, val)
+#define bfin_read_CAN0_AM09L() bfin_read16(CAN0_AM09L)
+#define bfin_write_CAN0_AM09L(val) bfin_write16(CAN0_AM09L, val)
+#define bfin_read_CAN0_AM09H() bfin_read16(CAN0_AM09H)
+#define bfin_write_CAN0_AM09H(val) bfin_write16(CAN0_AM09H, val)
+#define bfin_read_CAN0_AM10L() bfin_read16(CAN0_AM10L)
+#define bfin_write_CAN0_AM10L(val) bfin_write16(CAN0_AM10L, val)
+#define bfin_read_CAN0_AM10H() bfin_read16(CAN0_AM10H)
+#define bfin_write_CAN0_AM10H(val) bfin_write16(CAN0_AM10H, val)
+#define bfin_read_CAN0_AM11L() bfin_read16(CAN0_AM11L)
+#define bfin_write_CAN0_AM11L(val) bfin_write16(CAN0_AM11L, val)
+#define bfin_read_CAN0_AM11H() bfin_read16(CAN0_AM11H)
+#define bfin_write_CAN0_AM11H(val) bfin_write16(CAN0_AM11H, val)
+#define bfin_read_CAN0_AM12L() bfin_read16(CAN0_AM12L)
+#define bfin_write_CAN0_AM12L(val) bfin_write16(CAN0_AM12L, val)
+#define bfin_read_CAN0_AM12H() bfin_read16(CAN0_AM12H)
+#define bfin_write_CAN0_AM12H(val) bfin_write16(CAN0_AM12H, val)
+#define bfin_read_CAN0_AM13L() bfin_read16(CAN0_AM13L)
+#define bfin_write_CAN0_AM13L(val) bfin_write16(CAN0_AM13L, val)
+#define bfin_read_CAN0_AM13H() bfin_read16(CAN0_AM13H)
+#define bfin_write_CAN0_AM13H(val) bfin_write16(CAN0_AM13H, val)
+#define bfin_read_CAN0_AM14L() bfin_read16(CAN0_AM14L)
+#define bfin_write_CAN0_AM14L(val) bfin_write16(CAN0_AM14L, val)
+#define bfin_read_CAN0_AM14H() bfin_read16(CAN0_AM14H)
+#define bfin_write_CAN0_AM14H(val) bfin_write16(CAN0_AM14H, val)
+#define bfin_read_CAN0_AM15L() bfin_read16(CAN0_AM15L)
+#define bfin_write_CAN0_AM15L(val) bfin_write16(CAN0_AM15L, val)
+#define bfin_read_CAN0_AM15H() bfin_read16(CAN0_AM15H)
+#define bfin_write_CAN0_AM15H(val) bfin_write16(CAN0_AM15H, val)
+
+/* CAN Controller 0 Accebfin_read_()tance Registers */
+
+#define bfin_read_CAN0_AM16L() bfin_read16(CAN0_AM16L)
+#define bfin_write_CAN0_AM16L(val) bfin_write16(CAN0_AM16L, val)
+#define bfin_read_CAN0_AM16H() bfin_read16(CAN0_AM16H)
+#define bfin_write_CAN0_AM16H(val) bfin_write16(CAN0_AM16H, val)
+#define bfin_read_CAN0_AM17L() bfin_read16(CAN0_AM17L)
+#define bfin_write_CAN0_AM17L(val) bfin_write16(CAN0_AM17L, val)
+#define bfin_read_CAN0_AM17H() bfin_read16(CAN0_AM17H)
+#define bfin_write_CAN0_AM17H(val) bfin_write16(CAN0_AM17H, val)
+#define bfin_read_CAN0_AM18L() bfin_read16(CAN0_AM18L)
+#define bfin_write_CAN0_AM18L(val) bfin_write16(CAN0_AM18L, val)
+#define bfin_read_CAN0_AM18H() bfin_read16(CAN0_AM18H)
+#define bfin_write_CAN0_AM18H(val) bfin_write16(CAN0_AM18H, val)
+#define bfin_read_CAN0_AM19L() bfin_read16(CAN0_AM19L)
+#define bfin_write_CAN0_AM19L(val) bfin_write16(CAN0_AM19L, val)
+#define bfin_read_CAN0_AM19H() bfin_read16(CAN0_AM19H)
+#define bfin_write_CAN0_AM19H(val) bfin_write16(CAN0_AM19H, val)
+#define bfin_read_CAN0_AM20L() bfin_read16(CAN0_AM20L)
+#define bfin_write_CAN0_AM20L(val) bfin_write16(CAN0_AM20L, val)
+#define bfin_read_CAN0_AM20H() bfin_read16(CAN0_AM20H)
+#define bfin_write_CAN0_AM20H(val) bfin_write16(CAN0_AM20H, val)
+#define bfin_read_CAN0_AM21L() bfin_read16(CAN0_AM21L)
+#define bfin_write_CAN0_AM21L(val) bfin_write16(CAN0_AM21L, val)
+#define bfin_read_CAN0_AM21H() bfin_read16(CAN0_AM21H)
+#define bfin_write_CAN0_AM21H(val) bfin_write16(CAN0_AM21H, val)
+#define bfin_read_CAN0_AM22L() bfin_read16(CAN0_AM22L)
+#define bfin_write_CAN0_AM22L(val) bfin_write16(CAN0_AM22L, val)
+#define bfin_read_CAN0_AM22H() bfin_read16(CAN0_AM22H)
+#define bfin_write_CAN0_AM22H(val) bfin_write16(CAN0_AM22H, val)
+#define bfin_read_CAN0_AM23L() bfin_read16(CAN0_AM23L)
+#define bfin_write_CAN0_AM23L(val) bfin_write16(CAN0_AM23L, val)
+#define bfin_read_CAN0_AM23H() bfin_read16(CAN0_AM23H)
+#define bfin_write_CAN0_AM23H(val) bfin_write16(CAN0_AM23H, val)
+#define bfin_read_CAN0_AM24L() bfin_read16(CAN0_AM24L)
+#define bfin_write_CAN0_AM24L(val) bfin_write16(CAN0_AM24L, val)
+#define bfin_read_CAN0_AM24H() bfin_read16(CAN0_AM24H)
+#define bfin_write_CAN0_AM24H(val) bfin_write16(CAN0_AM24H, val)
+#define bfin_read_CAN0_AM25L() bfin_read16(CAN0_AM25L)
+#define bfin_write_CAN0_AM25L(val) bfin_write16(CAN0_AM25L, val)
+#define bfin_read_CAN0_AM25H() bfin_read16(CAN0_AM25H)
+#define bfin_write_CAN0_AM25H(val) bfin_write16(CAN0_AM25H, val)
+#define bfin_read_CAN0_AM26L() bfin_read16(CAN0_AM26L)
+#define bfin_write_CAN0_AM26L(val) bfin_write16(CAN0_AM26L, val)
+#define bfin_read_CAN0_AM26H() bfin_read16(CAN0_AM26H)
+#define bfin_write_CAN0_AM26H(val) bfin_write16(CAN0_AM26H, val)
+#define bfin_read_CAN0_AM27L() bfin_read16(CAN0_AM27L)
+#define bfin_write_CAN0_AM27L(val) bfin_write16(CAN0_AM27L, val)
+#define bfin_read_CAN0_AM27H() bfin_read16(CAN0_AM27H)
+#define bfin_write_CAN0_AM27H(val) bfin_write16(CAN0_AM27H, val)
+#define bfin_read_CAN0_AM28L() bfin_read16(CAN0_AM28L)
+#define bfin_write_CAN0_AM28L(val) bfin_write16(CAN0_AM28L, val)
+#define bfin_read_CAN0_AM28H() bfin_read16(CAN0_AM28H)
+#define bfin_write_CAN0_AM28H(val) bfin_write16(CAN0_AM28H, val)
+#define bfin_read_CAN0_AM29L() bfin_read16(CAN0_AM29L)
+#define bfin_write_CAN0_AM29L(val) bfin_write16(CAN0_AM29L, val)
+#define bfin_read_CAN0_AM29H() bfin_read16(CAN0_AM29H)
+#define bfin_write_CAN0_AM29H(val) bfin_write16(CAN0_AM29H, val)
+#define bfin_read_CAN0_AM30L() bfin_read16(CAN0_AM30L)
+#define bfin_write_CAN0_AM30L(val) bfin_write16(CAN0_AM30L, val)
+#define bfin_read_CAN0_AM30H() bfin_read16(CAN0_AM30H)
+#define bfin_write_CAN0_AM30H(val) bfin_write16(CAN0_AM30H, val)
+#define bfin_read_CAN0_AM31L() bfin_read16(CAN0_AM31L)
+#define bfin_write_CAN0_AM31L(val) bfin_write16(CAN0_AM31L, val)
+#define bfin_read_CAN0_AM31H() bfin_read16(CAN0_AM31H)
+#define bfin_write_CAN0_AM31H(val) bfin_write16(CAN0_AM31H, val)
+
+/* CAN Controller 0 Mailbox Data Registers */
+
+#define bfin_read_CAN0_MB00_DATA0() bfin_read16(CAN0_MB00_DATA0)
+#define bfin_write_CAN0_MB00_DATA0(val) bfin_write16(CAN0_MB00_DATA0, val)
+#define bfin_read_CAN0_MB00_DATA1() bfin_read16(CAN0_MB00_DATA1)
+#define bfin_write_CAN0_MB00_DATA1(val) bfin_write16(CAN0_MB00_DATA1, val)
+#define bfin_read_CAN0_MB00_DATA2() bfin_read16(CAN0_MB00_DATA2)
+#define bfin_write_CAN0_MB00_DATA2(val) bfin_write16(CAN0_MB00_DATA2, val)
+#define bfin_read_CAN0_MB00_DATA3() bfin_read16(CAN0_MB00_DATA3)
+#define bfin_write_CAN0_MB00_DATA3(val) bfin_write16(CAN0_MB00_DATA3, val)
+#define bfin_read_CAN0_MB00_LENGTH() bfin_read16(CAN0_MB00_LENGTH)
+#define bfin_write_CAN0_MB00_LENGTH(val) bfin_write16(CAN0_MB00_LENGTH, val)
+#define bfin_read_CAN0_MB00_TIMESTAMP() bfin_read16(CAN0_MB00_TIMESTAMP)
+#define bfin_write_CAN0_MB00_TIMESTAMP(val) bfin_write16(CAN0_MB00_TIMESTAMP, val)
+#define bfin_read_CAN0_MB00_ID0() bfin_read16(CAN0_MB00_ID0)
+#define bfin_write_CAN0_MB00_ID0(val) bfin_write16(CAN0_MB00_ID0, val)
+#define bfin_read_CAN0_MB00_ID1() bfin_read16(CAN0_MB00_ID1)
+#define bfin_write_CAN0_MB00_ID1(val) bfin_write16(CAN0_MB00_ID1, val)
+#define bfin_read_CAN0_MB01_DATA0() bfin_read16(CAN0_MB01_DATA0)
+#define bfin_write_CAN0_MB01_DATA0(val) bfin_write16(CAN0_MB01_DATA0, val)
+#define bfin_read_CAN0_MB01_DATA1() bfin_read16(CAN0_MB01_DATA1)
+#define bfin_write_CAN0_MB01_DATA1(val) bfin_write16(CAN0_MB01_DATA1, val)
+#define bfin_read_CAN0_MB01_DATA2() bfin_read16(CAN0_MB01_DATA2)
+#define bfin_write_CAN0_MB01_DATA2(val) bfin_write16(CAN0_MB01_DATA2, val)
+#define bfin_read_CAN0_MB01_DATA3() bfin_read16(CAN0_MB01_DATA3)
+#define bfin_write_CAN0_MB01_DATA3(val) bfin_write16(CAN0_MB01_DATA3, val)
+#define bfin_read_CAN0_MB01_LENGTH() bfin_read16(CAN0_MB01_LENGTH)
+#define bfin_write_CAN0_MB01_LENGTH(val) bfin_write16(CAN0_MB01_LENGTH, val)
+#define bfin_read_CAN0_MB01_TIMESTAMP() bfin_read16(CAN0_MB01_TIMESTAMP)
+#define bfin_write_CAN0_MB01_TIMESTAMP(val) bfin_write16(CAN0_MB01_TIMESTAMP, val)
+#define bfin_read_CAN0_MB01_ID0() bfin_read16(CAN0_MB01_ID0)
+#define bfin_write_CAN0_MB01_ID0(val) bfin_write16(CAN0_MB01_ID0, val)
+#define bfin_read_CAN0_MB01_ID1() bfin_read16(CAN0_MB01_ID1)
+#define bfin_write_CAN0_MB01_ID1(val) bfin_write16(CAN0_MB01_ID1, val)
+#define bfin_read_CAN0_MB02_DATA0() bfin_read16(CAN0_MB02_DATA0)
+#define bfin_write_CAN0_MB02_DATA0(val) bfin_write16(CAN0_MB02_DATA0, val)
+#define bfin_read_CAN0_MB02_DATA1() bfin_read16(CAN0_MB02_DATA1)
+#define bfin_write_CAN0_MB02_DATA1(val) bfin_write16(CAN0_MB02_DATA1, val)
+#define bfin_read_CAN0_MB02_DATA2() bfin_read16(CAN0_MB02_DATA2)
+#define bfin_write_CAN0_MB02_DATA2(val) bfin_write16(CAN0_MB02_DATA2, val)
+#define bfin_read_CAN0_MB02_DATA3() bfin_read16(CAN0_MB02_DATA3)
+#define bfin_write_CAN0_MB02_DATA3(val) bfin_write16(CAN0_MB02_DATA3, val)
+#define bfin_read_CAN0_MB02_LENGTH() bfin_read16(CAN0_MB02_LENGTH)
+#define bfin_write_CAN0_MB02_LENGTH(val) bfin_write16(CAN0_MB02_LENGTH, val)
+#define bfin_read_CAN0_MB02_TIMESTAMP() bfin_read16(CAN0_MB02_TIMESTAMP)
+#define bfin_write_CAN0_MB02_TIMESTAMP(val) bfin_write16(CAN0_MB02_TIMESTAMP, val)
+#define bfin_read_CAN0_MB02_ID0() bfin_read16(CAN0_MB02_ID0)
+#define bfin_write_CAN0_MB02_ID0(val) bfin_write16(CAN0_MB02_ID0, val)
+#define bfin_read_CAN0_MB02_ID1() bfin_read16(CAN0_MB02_ID1)
+#define bfin_write_CAN0_MB02_ID1(val) bfin_write16(CAN0_MB02_ID1, val)
+#define bfin_read_CAN0_MB03_DATA0() bfin_read16(CAN0_MB03_DATA0)
+#define bfin_write_CAN0_MB03_DATA0(val) bfin_write16(CAN0_MB03_DATA0, val)
+#define bfin_read_CAN0_MB03_DATA1() bfin_read16(CAN0_MB03_DATA1)
+#define bfin_write_CAN0_MB03_DATA1(val) bfin_write16(CAN0_MB03_DATA1, val)
+#define bfin_read_CAN0_MB03_DATA2() bfin_read16(CAN0_MB03_DATA2)
+#define bfin_write_CAN0_MB03_DATA2(val) bfin_write16(CAN0_MB03_DATA2, val)
+#define bfin_read_CAN0_MB03_DATA3() bfin_read16(CAN0_MB03_DATA3)
+#define bfin_write_CAN0_MB03_DATA3(val) bfin_write16(CAN0_MB03_DATA3, val)
+#define bfin_read_CAN0_MB03_LENGTH() bfin_read16(CAN0_MB03_LENGTH)
+#define bfin_write_CAN0_MB03_LENGTH(val) bfin_write16(CAN0_MB03_LENGTH, val)
+#define bfin_read_CAN0_MB03_TIMESTAMP() bfin_read16(CAN0_MB03_TIMESTAMP)
+#define bfin_write_CAN0_MB03_TIMESTAMP(val) bfin_write16(CAN0_MB03_TIMESTAMP, val)
+#define bfin_read_CAN0_MB03_ID0() bfin_read16(CAN0_MB03_ID0)
+#define bfin_write_CAN0_MB03_ID0(val) bfin_write16(CAN0_MB03_ID0, val)
+#define bfin_read_CAN0_MB03_ID1() bfin_read16(CAN0_MB03_ID1)
+#define bfin_write_CAN0_MB03_ID1(val) bfin_write16(CAN0_MB03_ID1, val)
+#define bfin_read_CAN0_MB04_DATA0() bfin_read16(CAN0_MB04_DATA0)
+#define bfin_write_CAN0_MB04_DATA0(val) bfin_write16(CAN0_MB04_DATA0, val)
+#define bfin_read_CAN0_MB04_DATA1() bfin_read16(CAN0_MB04_DATA1)
+#define bfin_write_CAN0_MB04_DATA1(val) bfin_write16(CAN0_MB04_DATA1, val)
+#define bfin_read_CAN0_MB04_DATA2() bfin_read16(CAN0_MB04_DATA2)
+#define bfin_write_CAN0_MB04_DATA2(val) bfin_write16(CAN0_MB04_DATA2, val)
+#define bfin_read_CAN0_MB04_DATA3() bfin_read16(CAN0_MB04_DATA3)
+#define bfin_write_CAN0_MB04_DATA3(val) bfin_write16(CAN0_MB04_DATA3, val)
+#define bfin_read_CAN0_MB04_LENGTH() bfin_read16(CAN0_MB04_LENGTH)
+#define bfin_write_CAN0_MB04_LENGTH(val) bfin_write16(CAN0_MB04_LENGTH, val)
+#define bfin_read_CAN0_MB04_TIMESTAMP() bfin_read16(CAN0_MB04_TIMESTAMP)
+#define bfin_write_CAN0_MB04_TIMESTAMP(val) bfin_write16(CAN0_MB04_TIMESTAMP, val)
+#define bfin_read_CAN0_MB04_ID0() bfin_read16(CAN0_MB04_ID0)
+#define bfin_write_CAN0_MB04_ID0(val) bfin_write16(CAN0_MB04_ID0, val)
+#define bfin_read_CAN0_MB04_ID1() bfin_read16(CAN0_MB04_ID1)
+#define bfin_write_CAN0_MB04_ID1(val) bfin_write16(CAN0_MB04_ID1, val)
+#define bfin_read_CAN0_MB05_DATA0() bfin_read16(CAN0_MB05_DATA0)
+#define bfin_write_CAN0_MB05_DATA0(val) bfin_write16(CAN0_MB05_DATA0, val)
+#define bfin_read_CAN0_MB05_DATA1() bfin_read16(CAN0_MB05_DATA1)
+#define bfin_write_CAN0_MB05_DATA1(val) bfin_write16(CAN0_MB05_DATA1, val)
+#define bfin_read_CAN0_MB05_DATA2() bfin_read16(CAN0_MB05_DATA2)
+#define bfin_write_CAN0_MB05_DATA2(val) bfin_write16(CAN0_MB05_DATA2, val)
+#define bfin_read_CAN0_MB05_DATA3() bfin_read16(CAN0_MB05_DATA3)
+#define bfin_write_CAN0_MB05_DATA3(val) bfin_write16(CAN0_MB05_DATA3, val)
+#define bfin_read_CAN0_MB05_LENGTH() bfin_read16(CAN0_MB05_LENGTH)
+#define bfin_write_CAN0_MB05_LENGTH(val) bfin_write16(CAN0_MB05_LENGTH, val)
+#define bfin_read_CAN0_MB05_TIMESTAMP() bfin_read16(CAN0_MB05_TIMESTAMP)
+#define bfin_write_CAN0_MB05_TIMESTAMP(val) bfin_write16(CAN0_MB05_TIMESTAMP, val)
+#define bfin_read_CAN0_MB05_ID0() bfin_read16(CAN0_MB05_ID0)
+#define bfin_write_CAN0_MB05_ID0(val) bfin_write16(CAN0_MB05_ID0, val)
+#define bfin_read_CAN0_MB05_ID1() bfin_read16(CAN0_MB05_ID1)
+#define bfin_write_CAN0_MB05_ID1(val) bfin_write16(CAN0_MB05_ID1, val)
+#define bfin_read_CAN0_MB06_DATA0() bfin_read16(CAN0_MB06_DATA0)
+#define bfin_write_CAN0_MB06_DATA0(val) bfin_write16(CAN0_MB06_DATA0, val)
+#define bfin_read_CAN0_MB06_DATA1() bfin_read16(CAN0_MB06_DATA1)
+#define bfin_write_CAN0_MB06_DATA1(val) bfin_write16(CAN0_MB06_DATA1, val)
+#define bfin_read_CAN0_MB06_DATA2() bfin_read16(CAN0_MB06_DATA2)
+#define bfin_write_CAN0_MB06_DATA2(val) bfin_write16(CAN0_MB06_DATA2, val)
+#define bfin_read_CAN0_MB06_DATA3() bfin_read16(CAN0_MB06_DATA3)
+#define bfin_write_CAN0_MB06_DATA3(val) bfin_write16(CAN0_MB06_DATA3, val)
+#define bfin_read_CAN0_MB06_LENGTH() bfin_read16(CAN0_MB06_LENGTH)
+#define bfin_write_CAN0_MB06_LENGTH(val) bfin_write16(CAN0_MB06_LENGTH, val)
+#define bfin_read_CAN0_MB06_TIMESTAMP() bfin_read16(CAN0_MB06_TIMESTAMP)
+#define bfin_write_CAN0_MB06_TIMESTAMP(val) bfin_write16(CAN0_MB06_TIMESTAMP, val)
+#define bfin_read_CAN0_MB06_ID0() bfin_read16(CAN0_MB06_ID0)
+#define bfin_write_CAN0_MB06_ID0(val) bfin_write16(CAN0_MB06_ID0, val)
+#define bfin_read_CAN0_MB06_ID1() bfin_read16(CAN0_MB06_ID1)
+#define bfin_write_CAN0_MB06_ID1(val) bfin_write16(CAN0_MB06_ID1, val)
+#define bfin_read_CAN0_MB07_DATA0() bfin_read16(CAN0_MB07_DATA0)
+#define bfin_write_CAN0_MB07_DATA0(val) bfin_write16(CAN0_MB07_DATA0, val)
+#define bfin_read_CAN0_MB07_DATA1() bfin_read16(CAN0_MB07_DATA1)
+#define bfin_write_CAN0_MB07_DATA1(val) bfin_write16(CAN0_MB07_DATA1, val)
+#define bfin_read_CAN0_MB07_DATA2() bfin_read16(CAN0_MB07_DATA2)
+#define bfin_write_CAN0_MB07_DATA2(val) bfin_write16(CAN0_MB07_DATA2, val)
+#define bfin_read_CAN0_MB07_DATA3() bfin_read16(CAN0_MB07_DATA3)
+#define bfin_write_CAN0_MB07_DATA3(val) bfin_write16(CAN0_MB07_DATA3, val)
+#define bfin_read_CAN0_MB07_LENGTH() bfin_read16(CAN0_MB07_LENGTH)
+#define bfin_write_CAN0_MB07_LENGTH(val) bfin_write16(CAN0_MB07_LENGTH, val)
+#define bfin_read_CAN0_MB07_TIMESTAMP() bfin_read16(CAN0_MB07_TIMESTAMP)
+#define bfin_write_CAN0_MB07_TIMESTAMP(val) bfin_write16(CAN0_MB07_TIMESTAMP, val)
+#define bfin_read_CAN0_MB07_ID0() bfin_read16(CAN0_MB07_ID0)
+#define bfin_write_CAN0_MB07_ID0(val) bfin_write16(CAN0_MB07_ID0, val)
+#define bfin_read_CAN0_MB07_ID1() bfin_read16(CAN0_MB07_ID1)
+#define bfin_write_CAN0_MB07_ID1(val) bfin_write16(CAN0_MB07_ID1, val)
+#define bfin_read_CAN0_MB08_DATA0() bfin_read16(CAN0_MB08_DATA0)
+#define bfin_write_CAN0_MB08_DATA0(val) bfin_write16(CAN0_MB08_DATA0, val)
+#define bfin_read_CAN0_MB08_DATA1() bfin_read16(CAN0_MB08_DATA1)
+#define bfin_write_CAN0_MB08_DATA1(val) bfin_write16(CAN0_MB08_DATA1, val)
+#define bfin_read_CAN0_MB08_DATA2() bfin_read16(CAN0_MB08_DATA2)
+#define bfin_write_CAN0_MB08_DATA2(val) bfin_write16(CAN0_MB08_DATA2, val)
+#define bfin_read_CAN0_MB08_DATA3() bfin_read16(CAN0_MB08_DATA3)
+#define bfin_write_CAN0_MB08_DATA3(val) bfin_write16(CAN0_MB08_DATA3, val)
+#define bfin_read_CAN0_MB08_LENGTH() bfin_read16(CAN0_MB08_LENGTH)
+#define bfin_write_CAN0_MB08_LENGTH(val) bfin_write16(CAN0_MB08_LENGTH, val)
+#define bfin_read_CAN0_MB08_TIMESTAMP() bfin_read16(CAN0_MB08_TIMESTAMP)
+#define bfin_write_CAN0_MB08_TIMESTAMP(val) bfin_write16(CAN0_MB08_TIMESTAMP, val)
+#define bfin_read_CAN0_MB08_ID0() bfin_read16(CAN0_MB08_ID0)
+#define bfin_write_CAN0_MB08_ID0(val) bfin_write16(CAN0_MB08_ID0, val)
+#define bfin_read_CAN0_MB08_ID1() bfin_read16(CAN0_MB08_ID1)
+#define bfin_write_CAN0_MB08_ID1(val) bfin_write16(CAN0_MB08_ID1, val)
+#define bfin_read_CAN0_MB09_DATA0() bfin_read16(CAN0_MB09_DATA0)
+#define bfin_write_CAN0_MB09_DATA0(val) bfin_write16(CAN0_MB09_DATA0, val)
+#define bfin_read_CAN0_MB09_DATA1() bfin_read16(CAN0_MB09_DATA1)
+#define bfin_write_CAN0_MB09_DATA1(val) bfin_write16(CAN0_MB09_DATA1, val)
+#define bfin_read_CAN0_MB09_DATA2() bfin_read16(CAN0_MB09_DATA2)
+#define bfin_write_CAN0_MB09_DATA2(val) bfin_write16(CAN0_MB09_DATA2, val)
+#define bfin_read_CAN0_MB09_DATA3() bfin_read16(CAN0_MB09_DATA3)
+#define bfin_write_CAN0_MB09_DATA3(val) bfin_write16(CAN0_MB09_DATA3, val)
+#define bfin_read_CAN0_MB09_LENGTH() bfin_read16(CAN0_MB09_LENGTH)
+#define bfin_write_CAN0_MB09_LENGTH(val) bfin_write16(CAN0_MB09_LENGTH, val)
+#define bfin_read_CAN0_MB09_TIMESTAMP() bfin_read16(CAN0_MB09_TIMESTAMP)
+#define bfin_write_CAN0_MB09_TIMESTAMP(val) bfin_write16(CAN0_MB09_TIMESTAMP, val)
+#define bfin_read_CAN0_MB09_ID0() bfin_read16(CAN0_MB09_ID0)
+#define bfin_write_CAN0_MB09_ID0(val) bfin_write16(CAN0_MB09_ID0, val)
+#define bfin_read_CAN0_MB09_ID1() bfin_read16(CAN0_MB09_ID1)
+#define bfin_write_CAN0_MB09_ID1(val) bfin_write16(CAN0_MB09_ID1, val)
+#define bfin_read_CAN0_MB10_DATA0() bfin_read16(CAN0_MB10_DATA0)
+#define bfin_write_CAN0_MB10_DATA0(val) bfin_write16(CAN0_MB10_DATA0, val)
+#define bfin_read_CAN0_MB10_DATA1() bfin_read16(CAN0_MB10_DATA1)
+#define bfin_write_CAN0_MB10_DATA1(val) bfin_write16(CAN0_MB10_DATA1, val)
+#define bfin_read_CAN0_MB10_DATA2() bfin_read16(CAN0_MB10_DATA2)
+#define bfin_write_CAN0_MB10_DATA2(val) bfin_write16(CAN0_MB10_DATA2, val)
+#define bfin_read_CAN0_MB10_DATA3() bfin_read16(CAN0_MB10_DATA3)
+#define bfin_write_CAN0_MB10_DATA3(val) bfin_write16(CAN0_MB10_DATA3, val)
+#define bfin_read_CAN0_MB10_LENGTH() bfin_read16(CAN0_MB10_LENGTH)
+#define bfin_write_CAN0_MB10_LENGTH(val) bfin_write16(CAN0_MB10_LENGTH, val)
+#define bfin_read_CAN0_MB10_TIMESTAMP() bfin_read16(CAN0_MB10_TIMESTAMP)
+#define bfin_write_CAN0_MB10_TIMESTAMP(val) bfin_write16(CAN0_MB10_TIMESTAMP, val)
+#define bfin_read_CAN0_MB10_ID0() bfin_read16(CAN0_MB10_ID0)
+#define bfin_write_CAN0_MB10_ID0(val) bfin_write16(CAN0_MB10_ID0, val)
+#define bfin_read_CAN0_MB10_ID1() bfin_read16(CAN0_MB10_ID1)
+#define bfin_write_CAN0_MB10_ID1(val) bfin_write16(CAN0_MB10_ID1, val)
+#define bfin_read_CAN0_MB11_DATA0() bfin_read16(CAN0_MB11_DATA0)
+#define bfin_write_CAN0_MB11_DATA0(val) bfin_write16(CAN0_MB11_DATA0, val)
+#define bfin_read_CAN0_MB11_DATA1() bfin_read16(CAN0_MB11_DATA1)
+#define bfin_write_CAN0_MB11_DATA1(val) bfin_write16(CAN0_MB11_DATA1, val)
+#define bfin_read_CAN0_MB11_DATA2() bfin_read16(CAN0_MB11_DATA2)
+#define bfin_write_CAN0_MB11_DATA2(val) bfin_write16(CAN0_MB11_DATA2, val)
+#define bfin_read_CAN0_MB11_DATA3() bfin_read16(CAN0_MB11_DATA3)
+#define bfin_write_CAN0_MB11_DATA3(val) bfin_write16(CAN0_MB11_DATA3, val)
+#define bfin_read_CAN0_MB11_LENGTH() bfin_read16(CAN0_MB11_LENGTH)
+#define bfin_write_CAN0_MB11_LENGTH(val) bfin_write16(CAN0_MB11_LENGTH, val)
+#define bfin_read_CAN0_MB11_TIMESTAMP() bfin_read16(CAN0_MB11_TIMESTAMP)
+#define bfin_write_CAN0_MB11_TIMESTAMP(val) bfin_write16(CAN0_MB11_TIMESTAMP, val)
+#define bfin_read_CAN0_MB11_ID0() bfin_read16(CAN0_MB11_ID0)
+#define bfin_write_CAN0_MB11_ID0(val) bfin_write16(CAN0_MB11_ID0, val)
+#define bfin_read_CAN0_MB11_ID1() bfin_read16(CAN0_MB11_ID1)
+#define bfin_write_CAN0_MB11_ID1(val) bfin_write16(CAN0_MB11_ID1, val)
+#define bfin_read_CAN0_MB12_DATA0() bfin_read16(CAN0_MB12_DATA0)
+#define bfin_write_CAN0_MB12_DATA0(val) bfin_write16(CAN0_MB12_DATA0, val)
+#define bfin_read_CAN0_MB12_DATA1() bfin_read16(CAN0_MB12_DATA1)
+#define bfin_write_CAN0_MB12_DATA1(val) bfin_write16(CAN0_MB12_DATA1, val)
+#define bfin_read_CAN0_MB12_DATA2() bfin_read16(CAN0_MB12_DATA2)
+#define bfin_write_CAN0_MB12_DATA2(val) bfin_write16(CAN0_MB12_DATA2, val)
+#define bfin_read_CAN0_MB12_DATA3() bfin_read16(CAN0_MB12_DATA3)
+#define bfin_write_CAN0_MB12_DATA3(val) bfin_write16(CAN0_MB12_DATA3, val)
+#define bfin_read_CAN0_MB12_LENGTH() bfin_read16(CAN0_MB12_LENGTH)
+#define bfin_write_CAN0_MB12_LENGTH(val) bfin_write16(CAN0_MB12_LENGTH, val)
+#define bfin_read_CAN0_MB12_TIMESTAMP() bfin_read16(CAN0_MB12_TIMESTAMP)
+#define bfin_write_CAN0_MB12_TIMESTAMP(val) bfin_write16(CAN0_MB12_TIMESTAMP, val)
+#define bfin_read_CAN0_MB12_ID0() bfin_read16(CAN0_MB12_ID0)
+#define bfin_write_CAN0_MB12_ID0(val) bfin_write16(CAN0_MB12_ID0, val)
+#define bfin_read_CAN0_MB12_ID1() bfin_read16(CAN0_MB12_ID1)
+#define bfin_write_CAN0_MB12_ID1(val) bfin_write16(CAN0_MB12_ID1, val)
+#define bfin_read_CAN0_MB13_DATA0() bfin_read16(CAN0_MB13_DATA0)
+#define bfin_write_CAN0_MB13_DATA0(val) bfin_write16(CAN0_MB13_DATA0, val)
+#define bfin_read_CAN0_MB13_DATA1() bfin_read16(CAN0_MB13_DATA1)
+#define bfin_write_CAN0_MB13_DATA1(val) bfin_write16(CAN0_MB13_DATA1, val)
+#define bfin_read_CAN0_MB13_DATA2() bfin_read16(CAN0_MB13_DATA2)
+#define bfin_write_CAN0_MB13_DATA2(val) bfin_write16(CAN0_MB13_DATA2, val)
+#define bfin_read_CAN0_MB13_DATA3() bfin_read16(CAN0_MB13_DATA3)
+#define bfin_write_CAN0_MB13_DATA3(val) bfin_write16(CAN0_MB13_DATA3, val)
+#define bfin_read_CAN0_MB13_LENGTH() bfin_read16(CAN0_MB13_LENGTH)
+#define bfin_write_CAN0_MB13_LENGTH(val) bfin_write16(CAN0_MB13_LENGTH, val)
+#define bfin_read_CAN0_MB13_TIMESTAMP() bfin_read16(CAN0_MB13_TIMESTAMP)
+#define bfin_write_CAN0_MB13_TIMESTAMP(val) bfin_write16(CAN0_MB13_TIMESTAMP, val)
+#define bfin_read_CAN0_MB13_ID0() bfin_read16(CAN0_MB13_ID0)
+#define bfin_write_CAN0_MB13_ID0(val) bfin_write16(CAN0_MB13_ID0, val)
+#define bfin_read_CAN0_MB13_ID1() bfin_read16(CAN0_MB13_ID1)
+#define bfin_write_CAN0_MB13_ID1(val) bfin_write16(CAN0_MB13_ID1, val)
+#define bfin_read_CAN0_MB14_DATA0() bfin_read16(CAN0_MB14_DATA0)
+#define bfin_write_CAN0_MB14_DATA0(val) bfin_write16(CAN0_MB14_DATA0, val)
+#define bfin_read_CAN0_MB14_DATA1() bfin_read16(CAN0_MB14_DATA1)
+#define bfin_write_CAN0_MB14_DATA1(val) bfin_write16(CAN0_MB14_DATA1, val)
+#define bfin_read_CAN0_MB14_DATA2() bfin_read16(CAN0_MB14_DATA2)
+#define bfin_write_CAN0_MB14_DATA2(val) bfin_write16(CAN0_MB14_DATA2, val)
+#define bfin_read_CAN0_MB14_DATA3() bfin_read16(CAN0_MB14_DATA3)
+#define bfin_write_CAN0_MB14_DATA3(val) bfin_write16(CAN0_MB14_DATA3, val)
+#define bfin_read_CAN0_MB14_LENGTH() bfin_read16(CAN0_MB14_LENGTH)
+#define bfin_write_CAN0_MB14_LENGTH(val) bfin_write16(CAN0_MB14_LENGTH, val)
+#define bfin_read_CAN0_MB14_TIMESTAMP() bfin_read16(CAN0_MB14_TIMESTAMP)
+#define bfin_write_CAN0_MB14_TIMESTAMP(val) bfin_write16(CAN0_MB14_TIMESTAMP, val)
+#define bfin_read_CAN0_MB14_ID0() bfin_read16(CAN0_MB14_ID0)
+#define bfin_write_CAN0_MB14_ID0(val) bfin_write16(CAN0_MB14_ID0, val)
+#define bfin_read_CAN0_MB14_ID1() bfin_read16(CAN0_MB14_ID1)
+#define bfin_write_CAN0_MB14_ID1(val) bfin_write16(CAN0_MB14_ID1, val)
+#define bfin_read_CAN0_MB15_DATA0() bfin_read16(CAN0_MB15_DATA0)
+#define bfin_write_CAN0_MB15_DATA0(val) bfin_write16(CAN0_MB15_DATA0, val)
+#define bfin_read_CAN0_MB15_DATA1() bfin_read16(CAN0_MB15_DATA1)
+#define bfin_write_CAN0_MB15_DATA1(val) bfin_write16(CAN0_MB15_DATA1, val)
+#define bfin_read_CAN0_MB15_DATA2() bfin_read16(CAN0_MB15_DATA2)
+#define bfin_write_CAN0_MB15_DATA2(val) bfin_write16(CAN0_MB15_DATA2, val)
+#define bfin_read_CAN0_MB15_DATA3() bfin_read16(CAN0_MB15_DATA3)
+#define bfin_write_CAN0_MB15_DATA3(val) bfin_write16(CAN0_MB15_DATA3, val)
+#define bfin_read_CAN0_MB15_LENGTH() bfin_read16(CAN0_MB15_LENGTH)
+#define bfin_write_CAN0_MB15_LENGTH(val) bfin_write16(CAN0_MB15_LENGTH, val)
+#define bfin_read_CAN0_MB15_TIMESTAMP() bfin_read16(CAN0_MB15_TIMESTAMP)
+#define bfin_write_CAN0_MB15_TIMESTAMP(val) bfin_write16(CAN0_MB15_TIMESTAMP, val)
+#define bfin_read_CAN0_MB15_ID0() bfin_read16(CAN0_MB15_ID0)
+#define bfin_write_CAN0_MB15_ID0(val) bfin_write16(CAN0_MB15_ID0, val)
+#define bfin_read_CAN0_MB15_ID1() bfin_read16(CAN0_MB15_ID1)
+#define bfin_write_CAN0_MB15_ID1(val) bfin_write16(CAN0_MB15_ID1, val)
+
+/* CAN Controller 0 Mailbox Data Registers */
+
+#define bfin_read_CAN0_MB16_DATA0() bfin_read16(CAN0_MB16_DATA0)
+#define bfin_write_CAN0_MB16_DATA0(val) bfin_write16(CAN0_MB16_DATA0, val)
+#define bfin_read_CAN0_MB16_DATA1() bfin_read16(CAN0_MB16_DATA1)
+#define bfin_write_CAN0_MB16_DATA1(val) bfin_write16(CAN0_MB16_DATA1, val)
+#define bfin_read_CAN0_MB16_DATA2() bfin_read16(CAN0_MB16_DATA2)
+#define bfin_write_CAN0_MB16_DATA2(val) bfin_write16(CAN0_MB16_DATA2, val)
+#define bfin_read_CAN0_MB16_DATA3() bfin_read16(CAN0_MB16_DATA3)
+#define bfin_write_CAN0_MB16_DATA3(val) bfin_write16(CAN0_MB16_DATA3, val)
+#define bfin_read_CAN0_MB16_LENGTH() bfin_read16(CAN0_MB16_LENGTH)
+#define bfin_write_CAN0_MB16_LENGTH(val) bfin_write16(CAN0_MB16_LENGTH, val)
+#define bfin_read_CAN0_MB16_TIMESTAMP() bfin_read16(CAN0_MB16_TIMESTAMP)
+#define bfin_write_CAN0_MB16_TIMESTAMP(val) bfin_write16(CAN0_MB16_TIMESTAMP, val)
+#define bfin_read_CAN0_MB16_ID0() bfin_read16(CAN0_MB16_ID0)
+#define bfin_write_CAN0_MB16_ID0(val) bfin_write16(CAN0_MB16_ID0, val)
+#define bfin_read_CAN0_MB16_ID1() bfin_read16(CAN0_MB16_ID1)
+#define bfin_write_CAN0_MB16_ID1(val) bfin_write16(CAN0_MB16_ID1, val)
+#define bfin_read_CAN0_MB17_DATA0() bfin_read16(CAN0_MB17_DATA0)
+#define bfin_write_CAN0_MB17_DATA0(val) bfin_write16(CAN0_MB17_DATA0, val)
+#define bfin_read_CAN0_MB17_DATA1() bfin_read16(CAN0_MB17_DATA1)
+#define bfin_write_CAN0_MB17_DATA1(val) bfin_write16(CAN0_MB17_DATA1, val)
+#define bfin_read_CAN0_MB17_DATA2() bfin_read16(CAN0_MB17_DATA2)
+#define bfin_write_CAN0_MB17_DATA2(val) bfin_write16(CAN0_MB17_DATA2, val)
+#define bfin_read_CAN0_MB17_DATA3() bfin_read16(CAN0_MB17_DATA3)
+#define bfin_write_CAN0_MB17_DATA3(val) bfin_write16(CAN0_MB17_DATA3, val)
+#define bfin_read_CAN0_MB17_LENGTH() bfin_read16(CAN0_MB17_LENGTH)
+#define bfin_write_CAN0_MB17_LENGTH(val) bfin_write16(CAN0_MB17_LENGTH, val)
+#define bfin_read_CAN0_MB17_TIMESTAMP() bfin_read16(CAN0_MB17_TIMESTAMP)
+#define bfin_write_CAN0_MB17_TIMESTAMP(val) bfin_write16(CAN0_MB17_TIMESTAMP, val)
+#define bfin_read_CAN0_MB17_ID0() bfin_read16(CAN0_MB17_ID0)
+#define bfin_write_CAN0_MB17_ID0(val) bfin_write16(CAN0_MB17_ID0, val)
+#define bfin_read_CAN0_MB17_ID1() bfin_read16(CAN0_MB17_ID1)
+#define bfin_write_CAN0_MB17_ID1(val) bfin_write16(CAN0_MB17_ID1, val)
+#define bfin_read_CAN0_MB18_DATA0() bfin_read16(CAN0_MB18_DATA0)
+#define bfin_write_CAN0_MB18_DATA0(val) bfin_write16(CAN0_MB18_DATA0, val)
+#define bfin_read_CAN0_MB18_DATA1() bfin_read16(CAN0_MB18_DATA1)
+#define bfin_write_CAN0_MB18_DATA1(val) bfin_write16(CAN0_MB18_DATA1, val)
+#define bfin_read_CAN0_MB18_DATA2() bfin_read16(CAN0_MB18_DATA2)
+#define bfin_write_CAN0_MB18_DATA2(val) bfin_write16(CAN0_MB18_DATA2, val)
+#define bfin_read_CAN0_MB18_DATA3() bfin_read16(CAN0_MB18_DATA3)
+#define bfin_write_CAN0_MB18_DATA3(val) bfin_write16(CAN0_MB18_DATA3, val)
+#define bfin_read_CAN0_MB18_LENGTH() bfin_read16(CAN0_MB18_LENGTH)
+#define bfin_write_CAN0_MB18_LENGTH(val) bfin_write16(CAN0_MB18_LENGTH, val)
+#define bfin_read_CAN0_MB18_TIMESTAMP() bfin_read16(CAN0_MB18_TIMESTAMP)
+#define bfin_write_CAN0_MB18_TIMESTAMP(val) bfin_write16(CAN0_MB18_TIMESTAMP, val)
+#define bfin_read_CAN0_MB18_ID0() bfin_read16(CAN0_MB18_ID0)
+#define bfin_write_CAN0_MB18_ID0(val) bfin_write16(CAN0_MB18_ID0, val)
+#define bfin_read_CAN0_MB18_ID1() bfin_read16(CAN0_MB18_ID1)
+#define bfin_write_CAN0_MB18_ID1(val) bfin_write16(CAN0_MB18_ID1, val)
+#define bfin_read_CAN0_MB19_DATA0() bfin_read16(CAN0_MB19_DATA0)
+#define bfin_write_CAN0_MB19_DATA0(val) bfin_write16(CAN0_MB19_DATA0, val)
+#define bfin_read_CAN0_MB19_DATA1() bfin_read16(CAN0_MB19_DATA1)
+#define bfin_write_CAN0_MB19_DATA1(val) bfin_write16(CAN0_MB19_DATA1, val)
+#define bfin_read_CAN0_MB19_DATA2() bfin_read16(CAN0_MB19_DATA2)
+#define bfin_write_CAN0_MB19_DATA2(val) bfin_write16(CAN0_MB19_DATA2, val)
+#define bfin_read_CAN0_MB19_DATA3() bfin_read16(CAN0_MB19_DATA3)
+#define bfin_write_CAN0_MB19_DATA3(val) bfin_write16(CAN0_MB19_DATA3, val)
+#define bfin_read_CAN0_MB19_LENGTH() bfin_read16(CAN0_MB19_LENGTH)
+#define bfin_write_CAN0_MB19_LENGTH(val) bfin_write16(CAN0_MB19_LENGTH, val)
+#define bfin_read_CAN0_MB19_TIMESTAMP() bfin_read16(CAN0_MB19_TIMESTAMP)
+#define bfin_write_CAN0_MB19_TIMESTAMP(val) bfin_write16(CAN0_MB19_TIMESTAMP, val)
+#define bfin_read_CAN0_MB19_ID0() bfin_read16(CAN0_MB19_ID0)
+#define bfin_write_CAN0_MB19_ID0(val) bfin_write16(CAN0_MB19_ID0, val)
+#define bfin_read_CAN0_MB19_ID1() bfin_read16(CAN0_MB19_ID1)
+#define bfin_write_CAN0_MB19_ID1(val) bfin_write16(CAN0_MB19_ID1, val)
+#define bfin_read_CAN0_MB20_DATA0() bfin_read16(CAN0_MB20_DATA0)
+#define bfin_write_CAN0_MB20_DATA0(val) bfin_write16(CAN0_MB20_DATA0, val)
+#define bfin_read_CAN0_MB20_DATA1() bfin_read16(CAN0_MB20_DATA1)
+#define bfin_write_CAN0_MB20_DATA1(val) bfin_write16(CAN0_MB20_DATA1, val)
+#define bfin_read_CAN0_MB20_DATA2() bfin_read16(CAN0_MB20_DATA2)
+#define bfin_write_CAN0_MB20_DATA2(val) bfin_write16(CAN0_MB20_DATA2, val)
+#define bfin_read_CAN0_MB20_DATA3() bfin_read16(CAN0_MB20_DATA3)
+#define bfin_write_CAN0_MB20_DATA3(val) bfin_write16(CAN0_MB20_DATA3, val)
+#define bfin_read_CAN0_MB20_LENGTH() bfin_read16(CAN0_MB20_LENGTH)
+#define bfin_write_CAN0_MB20_LENGTH(val) bfin_write16(CAN0_MB20_LENGTH, val)
+#define bfin_read_CAN0_MB20_TIMESTAMP() bfin_read16(CAN0_MB20_TIMESTAMP)
+#define bfin_write_CAN0_MB20_TIMESTAMP(val) bfin_write16(CAN0_MB20_TIMESTAMP, val)
+#define bfin_read_CAN0_MB20_ID0() bfin_read16(CAN0_MB20_ID0)
+#define bfin_write_CAN0_MB20_ID0(val) bfin_write16(CAN0_MB20_ID0, val)
+#define bfin_read_CAN0_MB20_ID1() bfin_read16(CAN0_MB20_ID1)
+#define bfin_write_CAN0_MB20_ID1(val) bfin_write16(CAN0_MB20_ID1, val)
+#define bfin_read_CAN0_MB21_DATA0() bfin_read16(CAN0_MB21_DATA0)
+#define bfin_write_CAN0_MB21_DATA0(val) bfin_write16(CAN0_MB21_DATA0, val)
+#define bfin_read_CAN0_MB21_DATA1() bfin_read16(CAN0_MB21_DATA1)
+#define bfin_write_CAN0_MB21_DATA1(val) bfin_write16(CAN0_MB21_DATA1, val)
+#define bfin_read_CAN0_MB21_DATA2() bfin_read16(CAN0_MB21_DATA2)
+#define bfin_write_CAN0_MB21_DATA2(val) bfin_write16(CAN0_MB21_DATA2, val)
+#define bfin_read_CAN0_MB21_DATA3() bfin_read16(CAN0_MB21_DATA3)
+#define bfin_write_CAN0_MB21_DATA3(val) bfin_write16(CAN0_MB21_DATA3, val)
+#define bfin_read_CAN0_MB21_LENGTH() bfin_read16(CAN0_MB21_LENGTH)
+#define bfin_write_CAN0_MB21_LENGTH(val) bfin_write16(CAN0_MB21_LENGTH, val)
+#define bfin_read_CAN0_MB21_TIMESTAMP() bfin_read16(CAN0_MB21_TIMESTAMP)
+#define bfin_write_CAN0_MB21_TIMESTAMP(val) bfin_write16(CAN0_MB21_TIMESTAMP, val)
+#define bfin_read_CAN0_MB21_ID0() bfin_read16(CAN0_MB21_ID0)
+#define bfin_write_CAN0_MB21_ID0(val) bfin_write16(CAN0_MB21_ID0, val)
+#define bfin_read_CAN0_MB21_ID1() bfin_read16(CAN0_MB21_ID1)
+#define bfin_write_CAN0_MB21_ID1(val) bfin_write16(CAN0_MB21_ID1, val)
+#define bfin_read_CAN0_MB22_DATA0() bfin_read16(CAN0_MB22_DATA0)
+#define bfin_write_CAN0_MB22_DATA0(val) bfin_write16(CAN0_MB22_DATA0, val)
+#define bfin_read_CAN0_MB22_DATA1() bfin_read16(CAN0_MB22_DATA1)
+#define bfin_write_CAN0_MB22_DATA1(val) bfin_write16(CAN0_MB22_DATA1, val)
+#define bfin_read_CAN0_MB22_DATA2() bfin_read16(CAN0_MB22_DATA2)
+#define bfin_write_CAN0_MB22_DATA2(val) bfin_write16(CAN0_MB22_DATA2, val)
+#define bfin_read_CAN0_MB22_DATA3() bfin_read16(CAN0_MB22_DATA3)
+#define bfin_write_CAN0_MB22_DATA3(val) bfin_write16(CAN0_MB22_DATA3, val)
+#define bfin_read_CAN0_MB22_LENGTH() bfin_read16(CAN0_MB22_LENGTH)
+#define bfin_write_CAN0_MB22_LENGTH(val) bfin_write16(CAN0_MB22_LENGTH, val)
+#define bfin_read_CAN0_MB22_TIMESTAMP() bfin_read16(CAN0_MB22_TIMESTAMP)
+#define bfin_write_CAN0_MB22_TIMESTAMP(val) bfin_write16(CAN0_MB22_TIMESTAMP, val)
+#define bfin_read_CAN0_MB22_ID0() bfin_read16(CAN0_MB22_ID0)
+#define bfin_write_CAN0_MB22_ID0(val) bfin_write16(CAN0_MB22_ID0, val)
+#define bfin_read_CAN0_MB22_ID1() bfin_read16(CAN0_MB22_ID1)
+#define bfin_write_CAN0_MB22_ID1(val) bfin_write16(CAN0_MB22_ID1, val)
+#define bfin_read_CAN0_MB23_DATA0() bfin_read16(CAN0_MB23_DATA0)
+#define bfin_write_CAN0_MB23_DATA0(val) bfin_write16(CAN0_MB23_DATA0, val)
+#define bfin_read_CAN0_MB23_DATA1() bfin_read16(CAN0_MB23_DATA1)
+#define bfin_write_CAN0_MB23_DATA1(val) bfin_write16(CAN0_MB23_DATA1, val)
+#define bfin_read_CAN0_MB23_DATA2() bfin_read16(CAN0_MB23_DATA2)
+#define bfin_write_CAN0_MB23_DATA2(val) bfin_write16(CAN0_MB23_DATA2, val)
+#define bfin_read_CAN0_MB23_DATA3() bfin_read16(CAN0_MB23_DATA3)
+#define bfin_write_CAN0_MB23_DATA3(val) bfin_write16(CAN0_MB23_DATA3, val)
+#define bfin_read_CAN0_MB23_LENGTH() bfin_read16(CAN0_MB23_LENGTH)
+#define bfin_write_CAN0_MB23_LENGTH(val) bfin_write16(CAN0_MB23_LENGTH, val)
+#define bfin_read_CAN0_MB23_TIMESTAMP() bfin_read16(CAN0_MB23_TIMESTAMP)
+#define bfin_write_CAN0_MB23_TIMESTAMP(val) bfin_write16(CAN0_MB23_TIMESTAMP, val)
+#define bfin_read_CAN0_MB23_ID0() bfin_read16(CAN0_MB23_ID0)
+#define bfin_write_CAN0_MB23_ID0(val) bfin_write16(CAN0_MB23_ID0, val)
+#define bfin_read_CAN0_MB23_ID1() bfin_read16(CAN0_MB23_ID1)
+#define bfin_write_CAN0_MB23_ID1(val) bfin_write16(CAN0_MB23_ID1, val)
+#define bfin_read_CAN0_MB24_DATA0() bfin_read16(CAN0_MB24_DATA0)
+#define bfin_write_CAN0_MB24_DATA0(val) bfin_write16(CAN0_MB24_DATA0, val)
+#define bfin_read_CAN0_MB24_DATA1() bfin_read16(CAN0_MB24_DATA1)
+#define bfin_write_CAN0_MB24_DATA1(val) bfin_write16(CAN0_MB24_DATA1, val)
+#define bfin_read_CAN0_MB24_DATA2() bfin_read16(CAN0_MB24_DATA2)
+#define bfin_write_CAN0_MB24_DATA2(val) bfin_write16(CAN0_MB24_DATA2, val)
+#define bfin_read_CAN0_MB24_DATA3() bfin_read16(CAN0_MB24_DATA3)
+#define bfin_write_CAN0_MB24_DATA3(val) bfin_write16(CAN0_MB24_DATA3, val)
+#define bfin_read_CAN0_MB24_LENGTH() bfin_read16(CAN0_MB24_LENGTH)
+#define bfin_write_CAN0_MB24_LENGTH(val) bfin_write16(CAN0_MB24_LENGTH, val)
+#define bfin_read_CAN0_MB24_TIMESTAMP() bfin_read16(CAN0_MB24_TIMESTAMP)
+#define bfin_write_CAN0_MB24_TIMESTAMP(val) bfin_write16(CAN0_MB24_TIMESTAMP, val)
+#define bfin_read_CAN0_MB24_ID0() bfin_read16(CAN0_MB24_ID0)
+#define bfin_write_CAN0_MB24_ID0(val) bfin_write16(CAN0_MB24_ID0, val)
+#define bfin_read_CAN0_MB24_ID1() bfin_read16(CAN0_MB24_ID1)
+#define bfin_write_CAN0_MB24_ID1(val) bfin_write16(CAN0_MB24_ID1, val)
+#define bfin_read_CAN0_MB25_DATA0() bfin_read16(CAN0_MB25_DATA0)
+#define bfin_write_CAN0_MB25_DATA0(val) bfin_write16(CAN0_MB25_DATA0, val)
+#define bfin_read_CAN0_MB25_DATA1() bfin_read16(CAN0_MB25_DATA1)
+#define bfin_write_CAN0_MB25_DATA1(val) bfin_write16(CAN0_MB25_DATA1, val)
+#define bfin_read_CAN0_MB25_DATA2() bfin_read16(CAN0_MB25_DATA2)
+#define bfin_write_CAN0_MB25_DATA2(val) bfin_write16(CAN0_MB25_DATA2, val)
+#define bfin_read_CAN0_MB25_DATA3() bfin_read16(CAN0_MB25_DATA3)
+#define bfin_write_CAN0_MB25_DATA3(val) bfin_write16(CAN0_MB25_DATA3, val)
+#define bfin_read_CAN0_MB25_LENGTH() bfin_read16(CAN0_MB25_LENGTH)
+#define bfin_write_CAN0_MB25_LENGTH(val) bfin_write16(CAN0_MB25_LENGTH, val)
+#define bfin_read_CAN0_MB25_TIMESTAMP() bfin_read16(CAN0_MB25_TIMESTAMP)
+#define bfin_write_CAN0_MB25_TIMESTAMP(val) bfin_write16(CAN0_MB25_TIMESTAMP, val)
+#define bfin_read_CAN0_MB25_ID0() bfin_read16(CAN0_MB25_ID0)
+#define bfin_write_CAN0_MB25_ID0(val) bfin_write16(CAN0_MB25_ID0, val)
+#define bfin_read_CAN0_MB25_ID1() bfin_read16(CAN0_MB25_ID1)
+#define bfin_write_CAN0_MB25_ID1(val) bfin_write16(CAN0_MB25_ID1, val)
+#define bfin_read_CAN0_MB26_DATA0() bfin_read16(CAN0_MB26_DATA0)
+#define bfin_write_CAN0_MB26_DATA0(val) bfin_write16(CAN0_MB26_DATA0, val)
+#define bfin_read_CAN0_MB26_DATA1() bfin_read16(CAN0_MB26_DATA1)
+#define bfin_write_CAN0_MB26_DATA1(val) bfin_write16(CAN0_MB26_DATA1, val)
+#define bfin_read_CAN0_MB26_DATA2() bfin_read16(CAN0_MB26_DATA2)
+#define bfin_write_CAN0_MB26_DATA2(val) bfin_write16(CAN0_MB26_DATA2, val)
+#define bfin_read_CAN0_MB26_DATA3() bfin_read16(CAN0_MB26_DATA3)
+#define bfin_write_CAN0_MB26_DATA3(val) bfin_write16(CAN0_MB26_DATA3, val)
+#define bfin_read_CAN0_MB26_LENGTH() bfin_read16(CAN0_MB26_LENGTH)
+#define bfin_write_CAN0_MB26_LENGTH(val) bfin_write16(CAN0_MB26_LENGTH, val)
+#define bfin_read_CAN0_MB26_TIMESTAMP() bfin_read16(CAN0_MB26_TIMESTAMP)
+#define bfin_write_CAN0_MB26_TIMESTAMP(val) bfin_write16(CAN0_MB26_TIMESTAMP, val)
+#define bfin_read_CAN0_MB26_ID0() bfin_read16(CAN0_MB26_ID0)
+#define bfin_write_CAN0_MB26_ID0(val) bfin_write16(CAN0_MB26_ID0, val)
+#define bfin_read_CAN0_MB26_ID1() bfin_read16(CAN0_MB26_ID1)
+#define bfin_write_CAN0_MB26_ID1(val) bfin_write16(CAN0_MB26_ID1, val)
+#define bfin_read_CAN0_MB27_DATA0() bfin_read16(CAN0_MB27_DATA0)
+#define bfin_write_CAN0_MB27_DATA0(val) bfin_write16(CAN0_MB27_DATA0, val)
+#define bfin_read_CAN0_MB27_DATA1() bfin_read16(CAN0_MB27_DATA1)
+#define bfin_write_CAN0_MB27_DATA1(val) bfin_write16(CAN0_MB27_DATA1, val)
+#define bfin_read_CAN0_MB27_DATA2() bfin_read16(CAN0_MB27_DATA2)
+#define bfin_write_CAN0_MB27_DATA2(val) bfin_write16(CAN0_MB27_DATA2, val)
+#define bfin_read_CAN0_MB27_DATA3() bfin_read16(CAN0_MB27_DATA3)
+#define bfin_write_CAN0_MB27_DATA3(val) bfin_write16(CAN0_MB27_DATA3, val)
+#define bfin_read_CAN0_MB27_LENGTH() bfin_read16(CAN0_MB27_LENGTH)
+#define bfin_write_CAN0_MB27_LENGTH(val) bfin_write16(CAN0_MB27_LENGTH, val)
+#define bfin_read_CAN0_MB27_TIMESTAMP() bfin_read16(CAN0_MB27_TIMESTAMP)
+#define bfin_write_CAN0_MB27_TIMESTAMP(val) bfin_write16(CAN0_MB27_TIMESTAMP, val)
+#define bfin_read_CAN0_MB27_ID0() bfin_read16(CAN0_MB27_ID0)
+#define bfin_write_CAN0_MB27_ID0(val) bfin_write16(CAN0_MB27_ID0, val)
+#define bfin_read_CAN0_MB27_ID1() bfin_read16(CAN0_MB27_ID1)
+#define bfin_write_CAN0_MB27_ID1(val) bfin_write16(CAN0_MB27_ID1, val)
+#define bfin_read_CAN0_MB28_DATA0() bfin_read16(CAN0_MB28_DATA0)
+#define bfin_write_CAN0_MB28_DATA0(val) bfin_write16(CAN0_MB28_DATA0, val)
+#define bfin_read_CAN0_MB28_DATA1() bfin_read16(CAN0_MB28_DATA1)
+#define bfin_write_CAN0_MB28_DATA1(val) bfin_write16(CAN0_MB28_DATA1, val)
+#define bfin_read_CAN0_MB28_DATA2() bfin_read16(CAN0_MB28_DATA2)
+#define bfin_write_CAN0_MB28_DATA2(val) bfin_write16(CAN0_MB28_DATA2, val)
+#define bfin_read_CAN0_MB28_DATA3() bfin_read16(CAN0_MB28_DATA3)
+#define bfin_write_CAN0_MB28_DATA3(val) bfin_write16(CAN0_MB28_DATA3, val)
+#define bfin_read_CAN0_MB28_LENGTH() bfin_read16(CAN0_MB28_LENGTH)
+#define bfin_write_CAN0_MB28_LENGTH(val) bfin_write16(CAN0_MB28_LENGTH, val)
+#define bfin_read_CAN0_MB28_TIMESTAMP() bfin_read16(CAN0_MB28_TIMESTAMP)
+#define bfin_write_CAN0_MB28_TIMESTAMP(val) bfin_write16(CAN0_MB28_TIMESTAMP, val)
+#define bfin_read_CAN0_MB28_ID0() bfin_read16(CAN0_MB28_ID0)
+#define bfin_write_CAN0_MB28_ID0(val) bfin_write16(CAN0_MB28_ID0, val)
+#define bfin_read_CAN0_MB28_ID1() bfin_read16(CAN0_MB28_ID1)
+#define bfin_write_CAN0_MB28_ID1(val) bfin_write16(CAN0_MB28_ID1, val)
+#define bfin_read_CAN0_MB29_DATA0() bfin_read16(CAN0_MB29_DATA0)
+#define bfin_write_CAN0_MB29_DATA0(val) bfin_write16(CAN0_MB29_DATA0, val)
+#define bfin_read_CAN0_MB29_DATA1() bfin_read16(CAN0_MB29_DATA1)
+#define bfin_write_CAN0_MB29_DATA1(val) bfin_write16(CAN0_MB29_DATA1, val)
+#define bfin_read_CAN0_MB29_DATA2() bfin_read16(CAN0_MB29_DATA2)
+#define bfin_write_CAN0_MB29_DATA2(val) bfin_write16(CAN0_MB29_DATA2, val)
+#define bfin_read_CAN0_MB29_DATA3() bfin_read16(CAN0_MB29_DATA3)
+#define bfin_write_CAN0_MB29_DATA3(val) bfin_write16(CAN0_MB29_DATA3, val)
+#define bfin_read_CAN0_MB29_LENGTH() bfin_read16(CAN0_MB29_LENGTH)
+#define bfin_write_CAN0_MB29_LENGTH(val) bfin_write16(CAN0_MB29_LENGTH, val)
+#define bfin_read_CAN0_MB29_TIMESTAMP() bfin_read16(CAN0_MB29_TIMESTAMP)
+#define bfin_write_CAN0_MB29_TIMESTAMP(val) bfin_write16(CAN0_MB29_TIMESTAMP, val)
+#define bfin_read_CAN0_MB29_ID0() bfin_read16(CAN0_MB29_ID0)
+#define bfin_write_CAN0_MB29_ID0(val) bfin_write16(CAN0_MB29_ID0, val)
+#define bfin_read_CAN0_MB29_ID1() bfin_read16(CAN0_MB29_ID1)
+#define bfin_write_CAN0_MB29_ID1(val) bfin_write16(CAN0_MB29_ID1, val)
+#define bfin_read_CAN0_MB30_DATA0() bfin_read16(CAN0_MB30_DATA0)
+#define bfin_write_CAN0_MB30_DATA0(val) bfin_write16(CAN0_MB30_DATA0, val)
+#define bfin_read_CAN0_MB30_DATA1() bfin_read16(CAN0_MB30_DATA1)
+#define bfin_write_CAN0_MB30_DATA1(val) bfin_write16(CAN0_MB30_DATA1, val)
+#define bfin_read_CAN0_MB30_DATA2() bfin_read16(CAN0_MB30_DATA2)
+#define bfin_write_CAN0_MB30_DATA2(val) bfin_write16(CAN0_MB30_DATA2, val)
+#define bfin_read_CAN0_MB30_DATA3() bfin_read16(CAN0_MB30_DATA3)
+#define bfin_write_CAN0_MB30_DATA3(val) bfin_write16(CAN0_MB30_DATA3, val)
+#define bfin_read_CAN0_MB30_LENGTH() bfin_read16(CAN0_MB30_LENGTH)
+#define bfin_write_CAN0_MB30_LENGTH(val) bfin_write16(CAN0_MB30_LENGTH, val)
+#define bfin_read_CAN0_MB30_TIMESTAMP() bfin_read16(CAN0_MB30_TIMESTAMP)
+#define bfin_write_CAN0_MB30_TIMESTAMP(val) bfin_write16(CAN0_MB30_TIMESTAMP, val)
+#define bfin_read_CAN0_MB30_ID0() bfin_read16(CAN0_MB30_ID0)
+#define bfin_write_CAN0_MB30_ID0(val) bfin_write16(CAN0_MB30_ID0, val)
+#define bfin_read_CAN0_MB30_ID1() bfin_read16(CAN0_MB30_ID1)
+#define bfin_write_CAN0_MB30_ID1(val) bfin_write16(CAN0_MB30_ID1, val)
+#define bfin_read_CAN0_MB31_DATA0() bfin_read16(CAN0_MB31_DATA0)
+#define bfin_write_CAN0_MB31_DATA0(val) bfin_write16(CAN0_MB31_DATA0, val)
+#define bfin_read_CAN0_MB31_DATA1() bfin_read16(CAN0_MB31_DATA1)
+#define bfin_write_CAN0_MB31_DATA1(val) bfin_write16(CAN0_MB31_DATA1, val)
+#define bfin_read_CAN0_MB31_DATA2() bfin_read16(CAN0_MB31_DATA2)
+#define bfin_write_CAN0_MB31_DATA2(val) bfin_write16(CAN0_MB31_DATA2, val)
+#define bfin_read_CAN0_MB31_DATA3() bfin_read16(CAN0_MB31_DATA3)
+#define bfin_write_CAN0_MB31_DATA3(val) bfin_write16(CAN0_MB31_DATA3, val)
+#define bfin_read_CAN0_MB31_LENGTH() bfin_read16(CAN0_MB31_LENGTH)
+#define bfin_write_CAN0_MB31_LENGTH(val) bfin_write16(CAN0_MB31_LENGTH, val)
+#define bfin_read_CAN0_MB31_TIMESTAMP() bfin_read16(CAN0_MB31_TIMESTAMP)
+#define bfin_write_CAN0_MB31_TIMESTAMP(val) bfin_write16(CAN0_MB31_TIMESTAMP, val)
+#define bfin_read_CAN0_MB31_ID0() bfin_read16(CAN0_MB31_ID0)
+#define bfin_write_CAN0_MB31_ID0(val) bfin_write16(CAN0_MB31_ID0, val)
+#define bfin_read_CAN0_MB31_ID1() bfin_read16(CAN0_MB31_ID1)
+#define bfin_write_CAN0_MB31_ID1(val) bfin_write16(CAN0_MB31_ID1, val)
+
+/* Counter Registers */
+
+#define bfin_read_CNT_CONFIG() bfin_read16(CNT_CONFIG)
+#define bfin_write_CNT_CONFIG(val) bfin_write16(CNT_CONFIG, val)
+#define bfin_read_CNT_IMASK() bfin_read16(CNT_IMASK)
+#define bfin_write_CNT_IMASK(val) bfin_write16(CNT_IMASK, val)
+#define bfin_read_CNT_STATUS() bfin_read16(CNT_STATUS)
+#define bfin_write_CNT_STATUS(val) bfin_write16(CNT_STATUS, val)
+#define bfin_read_CNT_COMMAND() bfin_read16(CNT_COMMAND)
+#define bfin_write_CNT_COMMAND(val) bfin_write16(CNT_COMMAND, val)
+#define bfin_read_CNT_DEBOUNCE() bfin_read16(CNT_DEBOUNCE)
+#define bfin_write_CNT_DEBOUNCE(val) bfin_write16(CNT_DEBOUNCE, val)
+#define bfin_read_CNT_COUNTER() bfin_read32(CNT_COUNTER)
+#define bfin_write_CNT_COUNTER(val) bfin_write32(CNT_COUNTER, val)
+#define bfin_read_CNT_MAX() bfin_read32(CNT_MAX)
+#define bfin_write_CNT_MAX(val) bfin_write32(CNT_MAX, val)
+#define bfin_read_CNT_MIN() bfin_read32(CNT_MIN)
+#define bfin_write_CNT_MIN(val) bfin_write32(CNT_MIN, val)
+
+/* RSI Register */
+#define bfin_read_RSI_CLK_CTL() bfin_read16(RSI_CLK_CONTROL)
+#define bfin_write_RSI_CLK_CTL(val) bfin_write16(RSI_CLK_CONTROL, val)
+#define bfin_read_RSI_ARGUMENT() bfin_read32(RSI_ARGUMENT)
+#define bfin_write_RSI_ARGUMENT(val) bfin_write32(RSI_ARGUMENT, val)
+#define bfin_read_RSI_COMMAND() bfin_read16(RSI_COMMAND)
+#define bfin_write_RSI_COMMAND(val) bfin_write16(RSI_COMMAND, val)
+#define bfin_read_RSI_RESP_CMD() bfin_read16(RSI_RESP_CMD)
+#define bfin_write_RSI_RESP_CMD(val) bfin_write16(RSI_RESP_CMD, val)
+#define bfin_read_RSI_RESPONSE0() bfin_read32(RSI_RESPONSE0)
+#define bfin_write_RSI_RESPONSE0(val) bfin_write32(RSI_RESPONSE0, val)
+#define bfin_read_RSI_RESPONSE1() bfin_read32(RSI_RESPONSE1)
+#define bfin_write_RSI_RESPONSE1(val) bfin_write32(RSI_RESPONSE1, val)
+#define bfin_read_RSI_RESPONSE2() bfin_read32(RSI_RESPONSE2)
+#define bfin_write_RSI_RESPONSE2(val) bfin_write32(RSI_RESPONSE2, val)
+#define bfin_read_RSI_RESPONSE3() bfin_read32(RSI_RESPONSE3)
+#define bfin_write_RSI_RESPONSE3(val) bfin_write32(RSI_RESPONSE3, val)
+#define bfin_read_RSI_DATA_TIMER() bfin_read32(RSI_DATA_TIMER)
+#define bfin_write_RSI_DATA_TIMER(val) bfin_write32(RSI_DATA_TIMER, val)
+#define bfin_read_RSI_DATA_LGTH() bfin_read16(RSI_DATA_LGTH)
+#define bfin_write_RSI_DATA_LGTH(val) bfin_write16(RSI_DATA_LGTH, val)
+#define bfin_read_RSI_DATA_CTL() bfin_read16(RSI_DATA_CONTROL)
+#define bfin_write_RSI_DATA_CTL(val) bfin_write16(RSI_DATA_CONTROL, val)
+#define bfin_read_RSI_DATA_CNT() bfin_read16(RSI_DATA_CNT)
+#define bfin_write_RSI_DATA_CNT(val) bfin_write16(RSI_DATA_CNT, val)
+#define bfin_read_RSI_STATUS() bfin_read32(RSI_STATUS)
+#define bfin_write_RSI_STATUS(val) bfin_write32(RSI_STATUS, val)
+#define bfin_read_RSI_STATUS_CLR() bfin_read16(RSI_STATUSCL)
+#define bfin_write_RSI_STATUS_CLR(val) bfin_write16(RSI_STATUSCL, val)
+#define bfin_read_RSI_MASK0() bfin_read32(RSI_MASK0)
+#define bfin_write_RSI_MASK0(val) bfin_write32(RSI_MASK0, val)
+#define bfin_read_RSI_MASK1() bfin_read32(RSI_MASK1)
+#define bfin_write_RSI_MASK1(val) bfin_write32(RSI_MASK1, val)
+#define bfin_read_RSI_FIFO_CNT() bfin_read16(RSI_FIFO_CNT)
+#define bfin_write_RSI_FIFO_CNT(val) bfin_write16(RSI_FIFO_CNT, val)
+#define bfin_read_RSI_CEATA_CONTROL() bfin_read16(RSI_CEATA_CONTROL)
+#define bfin_write_RSI_CEATA_CONTROL(val) bfin_write16(RSI_CEATA_CONTROL, val)
+#define bfin_read_RSI_BLKSZ() bfin_read16(RSI_BLKSZ)
+#define bfin_write_RSI_BLKSZ(val) bfin_write16(RSI_BLKSZ, val)
+#define bfin_read_RSI_FIFO() bfin_read32(RSI_FIFO)
+#define bfin_write_RSI_FIFO(val) bfin_write32(RSI_FIFO, val)
+#define bfin_read_RSI_E_STATUS() bfin_read32(RSI_ESTAT)
+#define bfin_write_RSI_E_STATUS(val) bfin_write32(RSI_ESTAT, val)
+#define bfin_read_RSI_E_MASK() bfin_read32(RSI_EMASK)
+#define bfin_write_RSI_E_MASK(val) bfin_write32(RSI_EMASK, val)
+#define bfin_read_RSI_CFG() bfin_read16(RSI_CONFIG)
+#define bfin_write_RSI_CFG(val) bfin_write16(RSI_CONFIG, val)
+#define bfin_read_RSI_RD_WAIT_EN() bfin_read16(RSI_RD_WAIT_EN)
+#define bfin_write_RSI_RD_WAIT_EN(val) bfin_write16(RSI_RD_WAIT_EN, val)
+#define bfin_read_RSI_PID0() bfin_read16(RSI_PID0)
+#define bfin_write_RSI_PID0(val) bfin_write16(RSI_PID0, val)
+#define bfin_read_RSI_PID1() bfin_read16(RSI_PID1)
+#define bfin_write_RSI_PID1(val) bfin_write16(RSI_PID1, val)
+#define bfin_read_RSI_PID2() bfin_read16(RSI_PID2)
+#define bfin_write_RSI_PID2(val) bfin_write16(RSI_PID2, val)
+#define bfin_read_RSI_PID3() bfin_read16(RSI_PID3)
+#define bfin_write_RSI_PID3(val) bfin_write16(RSI_PID3, val)
+
+/* usb register */
+#define bfin_read_USB_PLLOSC_CTRL() bfin_read16(USB_PLL_OSC)
+#define bfin_write_USB_PLLOSC_CTRL(val) bfin_write16(USB_PLL_OSC, val)
+#define bfin_write_USB_VBUS_CTL(val) bfin_write8(USB_VBUS_CTL, val)
+#define bfin_write_USB_APHY_CNTRL(val) bfin_write8(USB_PHY_CTL, val)
+#define bfin_read_USB_APHY_CNTRL() bfin_read8(USB_PHY_CTL)
+
+#endif /* _CDEF_BF60X_H */
+
diff --git a/arch/blackfin/mach-bf609/include/mach/defBF609.h b/arch/blackfin/mach-bf609/include/mach/defBF609.h
new file mode 100644
index 000000000000..19690cc42113
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/defBF609.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
+ */
+
+#ifndef _DEF_BF609_H
+#define _DEF_BF609_H
+
+/* Include defBF60x_base.h for the set of #defines that are common to all ADSP-BF60x processors */
+#include "defBF60x_base.h"
+
+/* The following are the #defines needed by ADSP-BF609 that are not in the common header */
+
+#endif /* _DEF_BF609_H */
diff --git a/arch/blackfin/mach-bf609/include/mach/defBF60x_base.h b/arch/blackfin/mach-bf609/include/mach/defBF60x_base.h
new file mode 100644
index 000000000000..6aac38544cc9
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/defBF60x_base.h
@@ -0,0 +1,3587 @@
+/*
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the Clear BSD license or the GPL-2 (or later)
+ */
+
+#ifndef _DEF_BF60X_H
+#define _DEF_BF60X_H
+
+
+/* ************************************************************** */
+/* SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF60x */
+/* ************************************************************** */
+
+
+/* =========================
+ CNT Registers
+ ========================= */
+
+/* =========================
+ CNT0
+ ========================= */
+#define CNT_CONFIG 0xFFC00400 /* CNT0 Configuration Register */
+#define CNT_IMASK 0xFFC00404 /* CNT0 Interrupt Mask Register */
+#define CNT_STATUS 0xFFC00408 /* CNT0 Status Register */
+#define CNT_COMMAND 0xFFC0040C /* CNT0 Command Register */
+#define CNT_DEBOUNCE 0xFFC00410 /* CNT0 Debounce Register */
+#define CNT_COUNTER 0xFFC00414 /* CNT0 Counter Register */
+#define CNT_MAX 0xFFC00418 /* CNT0 Maximum Count Register */
+#define CNT_MIN 0xFFC0041C /* CNT0 Minimum Count Register */
+
+
+/* =========================
+ RSI Registers
+ ========================= */
+
+#define RSI_CLK_CONTROL 0xFFC00604 /* RSI0 Clock Control Register */
+#define RSI_ARGUMENT 0xFFC00608 /* RSI0 Argument Register */
+#define RSI_COMMAND 0xFFC0060C /* RSI0 Command Register */
+#define RSI_RESP_CMD 0xFFC00610 /* RSI0 Response Command Register */
+#define RSI_RESPONSE0 0xFFC00614 /* RSI0 Response 0 Register */
+#define RSI_RESPONSE1 0xFFC00618 /* RSI0 Response 1 Register */
+#define RSI_RESPONSE2 0xFFC0061C /* RSI0 Response 2 Register */
+#define RSI_RESPONSE3 0xFFC00620 /* RSI0 Response 3 Register */
+#define RSI_DATA_TIMER 0xFFC00624 /* RSI0 Data Timer Register */
+#define RSI_DATA_LGTH 0xFFC00628 /* RSI0 Data Length Register */
+#define RSI_DATA_CONTROL 0xFFC0062C /* RSI0 Data Control Register */
+#define RSI_DATA_CNT 0xFFC00630 /* RSI0 Data Count Register */
+#define RSI_STATUS 0xFFC00634 /* RSI0 Status Register */
+#define RSI_STATUSCL 0xFFC00638 /* RSI0 Status Clear Register */
+#define RSI_MASK0 0xFFC0063C /* RSI0 Interrupt 0 Mask Register */
+#define RSI_MASK1 0xFFC00640 /* RSI0 Interrupt 1 Mask Register */
+#define RSI_FIFO_CNT 0xFFC00648 /* RSI0 FIFO Counter Register */
+#define RSI_CEATA_CONTROL 0xFFC0064C /* RSI0 This register contains bit to dis CCS gen */
+#define RSI_BOOT_TCNTR 0xFFC00650 /* RSI0 Boot Timing Counter Register */
+#define RSI_BACK_TOUT 0xFFC00654 /* RSI0 Boot Acknowledge Timeout Register */
+#define RSI_SLP_WKUP_TOUT 0xFFC00658 /* RSI0 Sleep Wakeup Timeout Register */
+#define RSI_BLKSZ 0xFFC0065C /* RSI0 Block Size Register */
+#define RSI_FIFO 0xFFC00680 /* RSI0 Data FIFO Register */
+#define RSI_ESTAT 0xFFC006C0 /* RSI0 Exception Status Register */
+#define RSI_EMASK 0xFFC006C4 /* RSI0 Exception Mask Register */
+#define RSI_CONFIG 0xFFC006C8 /* RSI0 Configuration Register */
+#define RSI_RD_WAIT_EN 0xFFC006CC /* RSI0 Read Wait Enable Register */
+#define RSI_PID0 0xFFC006D0 /* RSI0 Peripheral Identification Register */
+#define RSI_PID1 0xFFC006D4 /* RSI0 Peripheral Identification Register */
+#define RSI_PID2 0xFFC006D8 /* RSI0 Peripheral Identification Register */
+#define RSI_PID3 0xFFC006DC /* RSI0 Peripheral Identification Register */
+
+/* =========================
+ CAN Registers
+ ========================= */
+
+/* =========================
+ CAN0
+ ========================= */
+#define CAN0_MC1 0xFFC00A00 /* CAN0 Mailbox Configuration Register 1 */
+#define CAN0_MD1 0xFFC00A04 /* CAN0 Mailbox Direction Register 1 */
+#define CAN0_TRS1 0xFFC00A08 /* CAN0 Transmission Request Set Register 1 */
+#define CAN0_TRR1 0xFFC00A0C /* CAN0 Transmission Request Reset Register 1 */
+#define CAN0_TA1 0xFFC00A10 /* CAN0 Transmission Acknowledge Register 1 */
+#define CAN0_AA1 0xFFC00A14 /* CAN0 Abort Acknowledge Register 1 */
+#define CAN0_RMP1 0xFFC00A18 /* CAN0 Receive Message Pending Register 1 */
+#define CAN0_RML1 0xFFC00A1C /* CAN0 Receive Message Lost Register 1 */
+#define CAN0_MBTIF1 0xFFC00A20 /* CAN0 Mailbox Transmit Interrupt Flag Register 1 */
+#define CAN0_MBRIF1 0xFFC00A24 /* CAN0 Mailbox Receive Interrupt Flag Register 1 */
+#define CAN0_MBIM1 0xFFC00A28 /* CAN0 Mailbox Interrupt Mask Register 1 */
+#define CAN0_RFH1 0xFFC00A2C /* CAN0 Remote Frame Handling Register 1 */
+#define CAN0_OPSS1 0xFFC00A30 /* CAN0 Overwrite Protection/Single Shot Transmission Register 1 */
+#define CAN0_MC2 0xFFC00A40 /* CAN0 Mailbox Configuration Register 2 */
+#define CAN0_MD2 0xFFC00A44 /* CAN0 Mailbox Direction Register 2 */
+#define CAN0_TRS2 0xFFC00A48 /* CAN0 Transmission Request Set Register 2 */
+#define CAN0_TRR2 0xFFC00A4C /* CAN0 Transmission Request Reset Register 2 */
+#define CAN0_TA2 0xFFC00A50 /* CAN0 Transmission Acknowledge Register 2 */
+#define CAN0_AA2 0xFFC00A54 /* CAN0 Abort Acknowledge Register 2 */
+#define CAN0_RMP2 0xFFC00A58 /* CAN0 Receive Message Pending Register 2 */
+#define CAN0_RML2 0xFFC00A5C /* CAN0 Receive Message Lost Register 2 */
+#define CAN0_MBTIF2 0xFFC00A60 /* CAN0 Mailbox Transmit Interrupt Flag Register 2 */
+#define CAN0_MBRIF2 0xFFC00A64 /* CAN0 Mailbox Receive Interrupt Flag Register 2 */
+#define CAN0_MBIM2 0xFFC00A68 /* CAN0 Mailbox Interrupt Mask Register 2 */
+#define CAN0_RFH2 0xFFC00A6C /* CAN0 Remote Frame Handling Register 2 */
+#define CAN0_OPSS2 0xFFC00A70 /* CAN0 Overwrite Protection/Single Shot Transmission Register 2 */
+#define CAN0_CLOCK 0xFFC00A80 /* CAN0 Clock Register */
+#define CAN0_TIMING 0xFFC00A84 /* CAN0 Timing Register */
+#define CAN0_DEBUG 0xFFC00A88 /* CAN0 Debug Register */
+#define CAN0_STATUS 0xFFC00A8C /* CAN0 Status Register */
+#define CAN0_CEC 0xFFC00A90 /* CAN0 Error Counter Register */
+#define CAN0_GIS 0xFFC00A94 /* CAN0 Global CAN Interrupt Status */
+#define CAN0_GIM 0xFFC00A98 /* CAN0 Global CAN Interrupt Mask */
+#define CAN0_GIF 0xFFC00A9C /* CAN0 Global CAN Interrupt Flag */
+#define CAN0_CONTROL 0xFFC00AA0 /* CAN0 CAN Master Control Register */
+#define CAN0_INTR 0xFFC00AA4 /* CAN0 Interrupt Pending Register */
+#define CAN0_MBTD 0xFFC00AAC /* CAN0 Temporary Mailbox Disable Register */
+#define CAN0_EWR 0xFFC00AB0 /* CAN0 Error Counter Warning Level Register */
+#define CAN0_ESR 0xFFC00AB4 /* CAN0 Error Status Register */
+#define CAN0_UCCNT 0xFFC00AC4 /* CAN0 Universal Counter Register */
+#define CAN0_UCRC 0xFFC00AC8 /* CAN0 Universal Counter Reload/Capture Register */
+#define CAN0_UCCNF 0xFFC00ACC /* CAN0 Universal Counter Configuration Mode Register */
+#define CAN0_AM00L 0xFFC00B00 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM01L 0xFFC00B08 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM02L 0xFFC00B10 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM03L 0xFFC00B18 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM04L 0xFFC00B20 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM05L 0xFFC00B28 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM06L 0xFFC00B30 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM07L 0xFFC00B38 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM08L 0xFFC00B40 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM09L 0xFFC00B48 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM10L 0xFFC00B50 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM11L 0xFFC00B58 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM12L 0xFFC00B60 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM13L 0xFFC00B68 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM14L 0xFFC00B70 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM15L 0xFFC00B78 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM16L 0xFFC00B80 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM17L 0xFFC00B88 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM18L 0xFFC00B90 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM19L 0xFFC00B98 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM20L 0xFFC00BA0 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM21L 0xFFC00BA8 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM22L 0xFFC00BB0 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM23L 0xFFC00BB8 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM24L 0xFFC00BC0 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM25L 0xFFC00BC8 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM26L 0xFFC00BD0 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM27L 0xFFC00BD8 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM28L 0xFFC00BE0 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM29L 0xFFC00BE8 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM30L 0xFFC00BF0 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM31L 0xFFC00BF8 /* CAN0 Acceptance Mask Register (L) */
+#define CAN0_AM00H 0xFFC00B04 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM01H 0xFFC00B0C /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM02H 0xFFC00B14 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM03H 0xFFC00B1C /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM04H 0xFFC00B24 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM05H 0xFFC00B2C /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM06H 0xFFC00B34 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM07H 0xFFC00B3C /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM08H 0xFFC00B44 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM09H 0xFFC00B4C /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM10H 0xFFC00B54 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM11H 0xFFC00B5C /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM12H 0xFFC00B64 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM13H 0xFFC00B6C /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM14H 0xFFC00B74 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM15H 0xFFC00B7C /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM16H 0xFFC00B84 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM17H 0xFFC00B8C /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM18H 0xFFC00B94 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM19H 0xFFC00B9C /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM20H 0xFFC00BA4 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM21H 0xFFC00BAC /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM22H 0xFFC00BB4 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM23H 0xFFC00BBC /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM24H 0xFFC00BC4 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM25H 0xFFC00BCC /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM26H 0xFFC00BD4 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM27H 0xFFC00BDC /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM28H 0xFFC00BE4 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM29H 0xFFC00BEC /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM30H 0xFFC00BF4 /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_AM31H 0xFFC00BFC /* CAN0 Acceptance Mask Register (H) */
+#define CAN0_MB00_DATA0 0xFFC00C00 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB01_DATA0 0xFFC00C20 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB02_DATA0 0xFFC00C40 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB03_DATA0 0xFFC00C60 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB04_DATA0 0xFFC00C80 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB05_DATA0 0xFFC00CA0 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB06_DATA0 0xFFC00CC0 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB07_DATA0 0xFFC00CE0 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB08_DATA0 0xFFC00D00 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB09_DATA0 0xFFC00D20 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB10_DATA0 0xFFC00D40 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB11_DATA0 0xFFC00D60 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB12_DATA0 0xFFC00D80 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB13_DATA0 0xFFC00DA0 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB14_DATA0 0xFFC00DC0 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB15_DATA0 0xFFC00DE0 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB16_DATA0 0xFFC00E00 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB17_DATA0 0xFFC00E20 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB18_DATA0 0xFFC00E40 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB19_DATA0 0xFFC00E60 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB20_DATA0 0xFFC00E80 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB21_DATA0 0xFFC00EA0 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB22_DATA0 0xFFC00EC0 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB23_DATA0 0xFFC00EE0 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB24_DATA0 0xFFC00F00 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB25_DATA0 0xFFC00F20 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB26_DATA0 0xFFC00F40 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB27_DATA0 0xFFC00F60 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB28_DATA0 0xFFC00F80 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB29_DATA0 0xFFC00FA0 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB30_DATA0 0xFFC00FC0 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB31_DATA0 0xFFC00FE0 /* CAN0 Mailbox Word 0 Register */
+#define CAN0_MB00_DATA1 0xFFC00C04 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB01_DATA1 0xFFC00C24 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB02_DATA1 0xFFC00C44 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB03_DATA1 0xFFC00C64 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB04_DATA1 0xFFC00C84 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB05_DATA1 0xFFC00CA4 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB06_DATA1 0xFFC00CC4 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB07_DATA1 0xFFC00CE4 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB08_DATA1 0xFFC00D04 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB09_DATA1 0xFFC00D24 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB10_DATA1 0xFFC00D44 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB11_DATA1 0xFFC00D64 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB12_DATA1 0xFFC00D84 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB13_DATA1 0xFFC00DA4 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB14_DATA1 0xFFC00DC4 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB15_DATA1 0xFFC00DE4 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB16_DATA1 0xFFC00E04 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB17_DATA1 0xFFC00E24 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB18_DATA1 0xFFC00E44 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB19_DATA1 0xFFC00E64 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB20_DATA1 0xFFC00E84 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB21_DATA1 0xFFC00EA4 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB22_DATA1 0xFFC00EC4 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB23_DATA1 0xFFC00EE4 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB24_DATA1 0xFFC00F04 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB25_DATA1 0xFFC00F24 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB26_DATA1 0xFFC00F44 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB27_DATA1 0xFFC00F64 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB28_DATA1 0xFFC00F84 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB29_DATA1 0xFFC00FA4 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB30_DATA1 0xFFC00FC4 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB31_DATA1 0xFFC00FE4 /* CAN0 Mailbox Word 1 Register */
+#define CAN0_MB00_DATA2 0xFFC00C08 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB01_DATA2 0xFFC00C28 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB02_DATA2 0xFFC00C48 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB03_DATA2 0xFFC00C68 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB04_DATA2 0xFFC00C88 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB05_DATA2 0xFFC00CA8 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB06_DATA2 0xFFC00CC8 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB07_DATA2 0xFFC00CE8 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB08_DATA2 0xFFC00D08 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB09_DATA2 0xFFC00D28 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB10_DATA2 0xFFC00D48 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB11_DATA2 0xFFC00D68 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB12_DATA2 0xFFC00D88 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB13_DATA2 0xFFC00DA8 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB14_DATA2 0xFFC00DC8 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB15_DATA2 0xFFC00DE8 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB16_DATA2 0xFFC00E08 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB17_DATA2 0xFFC00E28 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB18_DATA2 0xFFC00E48 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB19_DATA2 0xFFC00E68 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB20_DATA2 0xFFC00E88 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB21_DATA2 0xFFC00EA8 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB22_DATA2 0xFFC00EC8 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB23_DATA2 0xFFC00EE8 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB24_DATA2 0xFFC00F08 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB25_DATA2 0xFFC00F28 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB26_DATA2 0xFFC00F48 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB27_DATA2 0xFFC00F68 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB28_DATA2 0xFFC00F88 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB29_DATA2 0xFFC00FA8 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB30_DATA2 0xFFC00FC8 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB31_DATA2 0xFFC00FE8 /* CAN0 Mailbox Word 2 Register */
+#define CAN0_MB00_DATA3 0xFFC00C0C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB01_DATA3 0xFFC00C2C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB02_DATA3 0xFFC00C4C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB03_DATA3 0xFFC00C6C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB04_DATA3 0xFFC00C8C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB05_DATA3 0xFFC00CAC /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB06_DATA3 0xFFC00CCC /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB07_DATA3 0xFFC00CEC /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB08_DATA3 0xFFC00D0C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB09_DATA3 0xFFC00D2C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB10_DATA3 0xFFC00D4C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB11_DATA3 0xFFC00D6C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB12_DATA3 0xFFC00D8C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB13_DATA3 0xFFC00DAC /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB14_DATA3 0xFFC00DCC /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB15_DATA3 0xFFC00DEC /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB16_DATA3 0xFFC00E0C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB17_DATA3 0xFFC00E2C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB18_DATA3 0xFFC00E4C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB19_DATA3 0xFFC00E6C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB20_DATA3 0xFFC00E8C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB21_DATA3 0xFFC00EAC /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB22_DATA3 0xFFC00ECC /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB23_DATA3 0xFFC00EEC /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB24_DATA3 0xFFC00F0C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB25_DATA3 0xFFC00F2C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB26_DATA3 0xFFC00F4C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB27_DATA3 0xFFC00F6C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB28_DATA3 0xFFC00F8C /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB29_DATA3 0xFFC00FAC /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB30_DATA3 0xFFC00FCC /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB31_DATA3 0xFFC00FEC /* CAN0 Mailbox Word 3 Register */
+#define CAN0_MB00_LENGTH 0xFFC00C10 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB01_LENGTH 0xFFC00C30 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB02_LENGTH 0xFFC00C50 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB03_LENGTH 0xFFC00C70 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB04_LENGTH 0xFFC00C90 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB05_LENGTH 0xFFC00CB0 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB06_LENGTH 0xFFC00CD0 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB07_LENGTH 0xFFC00CF0 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB08_LENGTH 0xFFC00D10 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB09_LENGTH 0xFFC00D30 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB10_LENGTH 0xFFC00D50 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB11_LENGTH 0xFFC00D70 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB12_LENGTH 0xFFC00D90 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB13_LENGTH 0xFFC00DB0 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB14_LENGTH 0xFFC00DD0 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB15_LENGTH 0xFFC00DF0 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB16_LENGTH 0xFFC00E10 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB17_LENGTH 0xFFC00E30 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB18_LENGTH 0xFFC00E50 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB19_LENGTH 0xFFC00E70 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB20_LENGTH 0xFFC00E90 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB21_LENGTH 0xFFC00EB0 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB22_LENGTH 0xFFC00ED0 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB23_LENGTH 0xFFC00EF0 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB24_LENGTH 0xFFC00F10 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB25_LENGTH 0xFFC00F30 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB26_LENGTH 0xFFC00F50 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB27_LENGTH 0xFFC00F70 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB28_LENGTH 0xFFC00F90 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB29_LENGTH 0xFFC00FB0 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB30_LENGTH 0xFFC00FD0 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB31_LENGTH 0xFFC00FF0 /* CAN0 Mailbox Word 4 Register */
+#define CAN0_MB00_TIMESTAMP 0xFFC00C14 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB01_TIMESTAMP 0xFFC00C34 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB02_TIMESTAMP 0xFFC00C54 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB03_TIMESTAMP 0xFFC00C74 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB04_TIMESTAMP 0xFFC00C94 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB05_TIMESTAMP 0xFFC00CB4 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB06_TIMESTAMP 0xFFC00CD4 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB07_TIMESTAMP 0xFFC00CF4 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB08_TIMESTAMP 0xFFC00D14 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB09_TIMESTAMP 0xFFC00D34 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB10_TIMESTAMP 0xFFC00D54 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB11_TIMESTAMP 0xFFC00D74 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB12_TIMESTAMP 0xFFC00D94 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB13_TIMESTAMP 0xFFC00DB4 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB14_TIMESTAMP 0xFFC00DD4 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB15_TIMESTAMP 0xFFC00DF4 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB16_TIMESTAMP 0xFFC00E14 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB17_TIMESTAMP 0xFFC00E34 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB18_TIMESTAMP 0xFFC00E54 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB19_TIMESTAMP 0xFFC00E74 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB20_TIMESTAMP 0xFFC00E94 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB21_TIMESTAMP 0xFFC00EB4 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB22_TIMESTAMP 0xFFC00ED4 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB23_TIMESTAMP 0xFFC00EF4 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB24_TIMESTAMP 0xFFC00F14 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB25_TIMESTAMP 0xFFC00F34 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB26_TIMESTAMP 0xFFC00F54 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB27_TIMESTAMP 0xFFC00F74 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB28_TIMESTAMP 0xFFC00F94 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB29_TIMESTAMP 0xFFC00FB4 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB30_TIMESTAMP 0xFFC00FD4 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB31_TIMESTAMP 0xFFC00FF4 /* CAN0 Mailbox Word 5 Register */
+#define CAN0_MB00_ID0 0xFFC00C18 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB01_ID0 0xFFC00C38 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB02_ID0 0xFFC00C58 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB03_ID0 0xFFC00C78 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB04_ID0 0xFFC00C98 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB05_ID0 0xFFC00CB8 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB06_ID0 0xFFC00CD8 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB07_ID0 0xFFC00CF8 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB08_ID0 0xFFC00D18 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB09_ID0 0xFFC00D38 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB10_ID0 0xFFC00D58 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB11_ID0 0xFFC00D78 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB12_ID0 0xFFC00D98 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB13_ID0 0xFFC00DB8 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB14_ID0 0xFFC00DD8 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB15_ID0 0xFFC00DF8 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB16_ID0 0xFFC00E18 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB17_ID0 0xFFC00E38 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB18_ID0 0xFFC00E58 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB19_ID0 0xFFC00E78 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB20_ID0 0xFFC00E98 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB21_ID0 0xFFC00EB8 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB22_ID0 0xFFC00ED8 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB23_ID0 0xFFC00EF8 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB24_ID0 0xFFC00F18 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB25_ID0 0xFFC00F38 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB26_ID0 0xFFC00F58 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB27_ID0 0xFFC00F78 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB28_ID0 0xFFC00F98 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB29_ID0 0xFFC00FB8 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB30_ID0 0xFFC00FD8 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB31_ID0 0xFFC00FF8 /* CAN0 Mailbox Word 6 Register */
+#define CAN0_MB00_ID1 0xFFC00C1C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB01_ID1 0xFFC00C3C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB02_ID1 0xFFC00C5C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB03_ID1 0xFFC00C7C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB04_ID1 0xFFC00C9C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB05_ID1 0xFFC00CBC /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB06_ID1 0xFFC00CDC /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB07_ID1 0xFFC00CFC /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB08_ID1 0xFFC00D1C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB09_ID1 0xFFC00D3C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB10_ID1 0xFFC00D5C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB11_ID1 0xFFC00D7C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB12_ID1 0xFFC00D9C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB13_ID1 0xFFC00DBC /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB14_ID1 0xFFC00DDC /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB15_ID1 0xFFC00DFC /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB16_ID1 0xFFC00E1C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB17_ID1 0xFFC00E3C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB18_ID1 0xFFC00E5C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB19_ID1 0xFFC00E7C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB20_ID1 0xFFC00E9C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB21_ID1 0xFFC00EBC /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB22_ID1 0xFFC00EDC /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB23_ID1 0xFFC00EFC /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB24_ID1 0xFFC00F1C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB25_ID1 0xFFC00F3C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB26_ID1 0xFFC00F5C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB27_ID1 0xFFC00F7C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB28_ID1 0xFFC00F9C /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB29_ID1 0xFFC00FBC /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB30_ID1 0xFFC00FDC /* CAN0 Mailbox Word 7 Register */
+#define CAN0_MB31_ID1 0xFFC00FFC /* CAN0 Mailbox Word 7 Register */
+
+/* =========================
+ LINK PORT Registers
+ ========================= */
+#define LP0_CTL 0xFFC01000 /* LP0 Control Register */
+#define LP0_STAT 0xFFC01004 /* LP0 Status Register */
+#define LP0_DIV 0xFFC01008 /* LP0 Clock Divider Value */
+#define LP0_CNT 0xFFC0100C /* LP0 Current Count Value of Clock Divider */
+#define LP0_TX 0xFFC01010 /* LP0 Transmit Buffer */
+#define LP0_RX 0xFFC01014 /* LP0 Receive Buffer */
+#define LP0_TXIN_SHDW 0xFFC01018 /* LP0 Shadow Input Transmit Buffer */
+#define LP0_TXOUT_SHDW 0xFFC0101C /* LP0 Shadow Output Transmit Buffer */
+#define LP1_CTL 0xFFC01100 /* LP1 Control Register */
+#define LP1_STAT 0xFFC01104 /* LP1 Status Register */
+#define LP1_DIV 0xFFC01108 /* LP1 Clock Divider Value */
+#define LP1_CNT 0xFFC0110C /* LP1 Current Count Value of Clock Divider */
+#define LP1_TX 0xFFC01110 /* LP1 Transmit Buffer */
+#define LP1_RX 0xFFC01114 /* LP1 Receive Buffer */
+#define LP1_TXIN_SHDW 0xFFC01118 /* LP1 Shadow Input Transmit Buffer */
+#define LP1_TXOUT_SHDW 0xFFC0111C /* LP1 Shadow Output Transmit Buffer */
+#define LP2_CTL 0xFFC01200 /* LP2 Control Register */
+#define LP2_STAT 0xFFC01204 /* LP2 Status Register */
+#define LP2_DIV 0xFFC01208 /* LP2 Clock Divider Value */
+#define LP2_CNT 0xFFC0120C /* LP2 Current Count Value of Clock Divider */
+#define LP2_TX 0xFFC01210 /* LP2 Transmit Buffer */
+#define LP2_RX 0xFFC01214 /* LP2 Receive Buffer */
+#define LP2_TXIN_SHDW 0xFFC01218 /* LP2 Shadow Input Transmit Buffer */
+#define LP2_TXOUT_SHDW 0xFFC0121C /* LP2 Shadow Output Transmit Buffer */
+#define LP3_CTL 0xFFC01300 /* LP3 Control Register */
+#define LP3_STAT 0xFFC01304 /* LP3 Status Register */
+#define LP3_DIV 0xFFC01308 /* LP3 Clock Divider Value */
+#define LP3_CNT 0xFFC0130C /* LP3 Current Count Value of Clock Divider */
+#define LP3_TX 0xFFC01310 /* LP3 Transmit Buffer */
+#define LP3_RX 0xFFC01314 /* LP3 Receive Buffer */
+#define LP3_TXIN_SHDW 0xFFC01318 /* LP3 Shadow Input Transmit Buffer */
+#define LP3_TXOUT_SHDW 0xFFC0131C /* LP3 Shadow Output Transmit Buffer */
+
+/* =========================
+ TIMER Registers
+ ========================= */
+#define TIMER_REVID 0xFFC01400 /* GPTIMER Timer IP Version ID */
+#define TIMER_RUN 0xFFC01404 /* GPTIMER Timer Run Register */
+#define TIMER_RUN_SET 0xFFC01408 /* GPTIMER Run Register Alias to Set */
+#define TIMER_RUN_CLR 0xFFC0140C /* GPTIMER Run Register Alias to Clear */
+#define TIMER_STOP_CFG 0xFFC01410 /* GPTIMER Stop Config Register */
+#define TIMER_STOP_CFG_SET 0xFFC01414 /* GPTIMER Stop Config Alias to Set */
+#define TIMER_STOP_CFG_CLR 0xFFC01418 /* GPTIMER Stop Config Alias to Clear */
+#define TIMER_DATA_IMSK 0xFFC0141C /* GPTIMER Data Interrupt Mask register */
+#define TIMER_STAT_IMSK 0xFFC01420 /* GPTIMER Status Interrupt Mask register */
+#define TIMER_TRG_MSK 0xFFC01424 /* GPTIMER Output Trigger Mask register */
+#define TIMER_TRG_IE 0xFFC01428 /* GPTIMER Slave Trigger Enable register */
+#define TIMER_DATA_ILAT 0xFFC0142C /* GPTIMER Data Interrupt Register */
+#define TIMER_STAT_ILAT 0xFFC01430 /* GPTIMER Status (Error) Interrupt Register */
+#define TIMER_ERR_TYPE 0xFFC01434 /* GPTIMER Register Indicating Type of Error */
+#define TIMER_BCAST_PER 0xFFC01438 /* GPTIMER Broadcast Period */
+#define TIMER_BCAST_WID 0xFFC0143C /* GPTIMER Broadcast Width */
+#define TIMER_BCAST_DLY 0xFFC01440 /* GPTIMER Broadcast Delay */
+
+/* =========================
+ TIMER0~7
+ ========================= */
+#define TIMER0_CONFIG 0xFFC01460 /* TIMER0 Per Timer Config Register */
+#define TIMER0_COUNTER 0xFFC01464 /* TIMER0 Per Timer Counter Register */
+#define TIMER0_PERIOD 0xFFC01468 /* TIMER0 Per Timer Period Register */
+#define TIMER0_WIDTH 0xFFC0146C /* TIMER0 Per Timer Width Register */
+#define TIMER0_DELAY 0xFFC01470 /* TIMER0 Per Timer Delay Register */
+
+#define TIMER1_CONFIG 0xFFC01480 /* TIMER1 Per Timer Config Register */
+#define TIMER1_COUNTER 0xFFC01484 /* TIMER1 Per Timer Counter Register */
+#define TIMER1_PERIOD 0xFFC01488 /* TIMER1 Per Timer Period Register */
+#define TIMER1_WIDTH 0xFFC0148C /* TIMER1 Per Timer Width Register */
+#define TIMER1_DELAY 0xFFC01490 /* TIMER1 Per Timer Delay Register */
+
+#define TIMER2_CONFIG 0xFFC014A0 /* TIMER2 Per Timer Config Register */
+#define TIMER2_COUNTER 0xFFC014A4 /* TIMER2 Per Timer Counter Register */
+#define TIMER2_PERIOD 0xFFC014A8 /* TIMER2 Per Timer Period Register */
+#define TIMER2_WIDTH 0xFFC014AC /* TIMER2 Per Timer Width Register */
+#define TIMER2_DELAY 0xFFC014B0 /* TIMER2 Per Timer Delay Register */
+
+#define TIMER3_CONFIG 0xFFC014C0 /* TIMER3 Per Timer Config Register */
+#define TIMER3_COUNTER 0xFFC014C4 /* TIMER3 Per Timer Counter Register */
+#define TIMER3_PERIOD 0xFFC014C8 /* TIMER3 Per Timer Period Register */
+#define TIMER3_WIDTH 0xFFC014CC /* TIMER3 Per Timer Width Register */
+#define TIMER3_DELAY 0xFFC014D0 /* TIMER3 Per Timer Delay Register */
+
+#define TIMER4_CONFIG 0xFFC014E0 /* TIMER4 Per Timer Config Register */
+#define TIMER4_COUNTER 0xFFC014E4 /* TIMER4 Per Timer Counter Register */
+#define TIMER4_PERIOD 0xFFC014E8 /* TIMER4 Per Timer Period Register */
+#define TIMER4_WIDTH 0xFFC014EC /* TIMER4 Per Timer Width Register */
+#define TIMER4_DELAY 0xFFC014F0 /* TIMER4 Per Timer Delay Register */
+
+#define TIMER5_CONFIG 0xFFC01500 /* TIMER5 Per Timer Config Register */
+#define TIMER5_COUNTER 0xFFC01504 /* TIMER5 Per Timer Counter Register */
+#define TIMER5_PERIOD 0xFFC01508 /* TIMER5 Per Timer Period Register */
+#define TIMER5_WIDTH 0xFFC0150C /* TIMER5 Per Timer Width Register */
+#define TIMER5_DELAY 0xFFC01510 /* TIMER5 Per Timer Delay Register */
+
+#define TIMER6_CONFIG 0xFFC01520 /* TIMER6 Per Timer Config Register */
+#define TIMER6_COUNTER 0xFFC01524 /* TIMER6 Per Timer Counter Register */
+#define TIMER6_PERIOD 0xFFC01528 /* TIMER6 Per Timer Period Register */
+#define TIMER6_WIDTH 0xFFC0152C /* TIMER6 Per Timer Width Register */
+#define TIMER6_DELAY 0xFFC01530 /* TIMER6 Per Timer Delay Register */
+
+#define TIMER7_CONFIG 0xFFC01540 /* TIMER7 Per Timer Config Register */
+#define TIMER7_COUNTER 0xFFC01544 /* TIMER7 Per Timer Counter Register */
+#define TIMER7_PERIOD 0xFFC01548 /* TIMER7 Per Timer Period Register */
+#define TIMER7_WIDTH 0xFFC0154C /* TIMER7 Per Timer Width Register */
+#define TIMER7_DELAY 0xFFC01550 /* TIMER7 Per Timer Delay Register */
+
+/* =========================
+ CRC Registers
+ ========================= */
+
+/* =========================
+ CRC0
+ ========================= */
+#define REG_CRC0_CTL 0xFFC01C00 /* CRC0 Control Register */
+#define REG_CRC0_DCNT 0xFFC01C04 /* CRC0 Data Word Count Register */
+#define REG_CRC0_DCNTRLD 0xFFC01C08 /* CRC0 Data Word Count Reload Register */
+#define REG_CRC0_COMP 0xFFC01C14 /* CRC0 DATA Compare Register */
+#define REG_CRC0_FILLVAL 0xFFC01C18 /* CRC0 Fill Value Register */
+#define REG_CRC0_DFIFO 0xFFC01C1C /* CRC0 DATA FIFO Register */
+#define REG_CRC0_INEN 0xFFC01C20 /* CRC0 Interrupt Enable Register */
+#define REG_CRC0_INEN_SET 0xFFC01C24 /* CRC0 Interrupt Enable Set Register */
+#define REG_CRC0_INEN_CLR 0xFFC01C28 /* CRC0 Interrupt Enable Clear Register */
+#define REG_CRC0_POLY 0xFFC01C2C /* CRC0 Polynomial Register */
+#define REG_CRC0_STAT 0xFFC01C40 /* CRC0 Status Register */
+#define REG_CRC0_DCNTCAP 0xFFC01C44 /* CRC0 DATA Count Capture Register */
+#define REG_CRC0_RESULT_FIN 0xFFC01C4C /* CRC0 Final CRC Result Register */
+#define REG_CRC0_RESULT_CUR 0xFFC01C50 /* CRC0 Current CRC Result Register */
+#define REG_CRC0_REVID 0xFFC01C60 /* CRC0 Revision ID Register */
+
+/* =========================
+ CRC1
+ ========================= */
+#define REG_CRC1_CTL 0xFFC01D00 /* CRC1 Control Register */
+#define REG_CRC1_DCNT 0xFFC01D04 /* CRC1 Data Word Count Register */
+#define REG_CRC1_DCNTRLD 0xFFC01D08 /* CRC1 Data Word Count Reload Register */
+#define REG_CRC1_COMP 0xFFC01D14 /* CRC1 DATA Compare Register */
+#define REG_CRC1_FILLVAL 0xFFC01D18 /* CRC1 Fill Value Register */
+#define REG_CRC1_DFIFO 0xFFC01D1C /* CRC1 DATA FIFO Register */
+#define REG_CRC1_INEN 0xFFC01D20 /* CRC1 Interrupt Enable Register */
+#define REG_CRC1_INEN_SET 0xFFC01D24 /* CRC1 Interrupt Enable Set Register */
+#define REG_CRC1_INEN_CLR 0xFFC01D28 /* CRC1 Interrupt Enable Clear Register */
+#define REG_CRC1_POLY 0xFFC01D2C /* CRC1 Polynomial Register */
+#define REG_CRC1_STAT 0xFFC01D40 /* CRC1 Status Register */
+#define REG_CRC1_DCNTCAP 0xFFC01D44 /* CRC1 DATA Count Capture Register */
+#define REG_CRC1_RESULT_FIN 0xFFC01D4C /* CRC1 Final CRC Result Register */
+#define REG_CRC1_RESULT_CUR 0xFFC01D50 /* CRC1 Current CRC Result Register */
+#define REG_CRC1_REVID 0xFFC01D60 /* CRC1 Revision ID Register */
+
+/* =========================
+ TWI Registers
+ ========================= */
+
+/* =========================
+ TWI0
+ ========================= */
+#define TWI0_CLKDIV 0xFFC01E00 /* TWI0 SCL Clock Divider */
+#define TWI0_CONTROL 0xFFC01E04 /* TWI0 Control Register */
+#define TWI0_SLAVE_CTL 0xFFC01E08 /* TWI0 Slave Mode Control Register */
+#define TWI0_SLAVE_STAT 0xFFC01E0C /* TWI0 Slave Mode Status Register */
+#define TWI0_SLAVE_ADDR 0xFFC01E10 /* TWI0 Slave Mode Address Register */
+#define TWI0_MASTER_CTL 0xFFC01E14 /* TWI0 Master Mode Control Registers */
+#define TWI0_MASTER_STAT 0xFFC01E18 /* TWI0 Master Mode Status Register */
+#define TWI0_MASTER_ADDR 0xFFC01E1C /* TWI0 Master Mode Address Register */
+#define TWI0_INT_STAT 0xFFC01E20 /* TWI0 Interrupt Status Register */
+#define TWI0_INT_MASK 0xFFC01E24 /* TWI0 Interrupt Mask Register */
+#define TWI0_FIFO_CTL 0xFFC01E28 /* TWI0 FIFO Control Register */
+#define TWI0_FIFO_STAT 0xFFC01E2C /* TWI0 FIFO Status Register */
+#define TWI0_XMT_DATA8 0xFFC01E80 /* TWI0 FIFO Transmit Data Single-Byte Register */
+#define TWI0_XMT_DATA16 0xFFC01E84 /* TWI0 FIFO Transmit Data Double-Byte Register */
+#define TWI0_RCV_DATA8 0xFFC01E88 /* TWI0 FIFO Transmit Data Single-Byte Register */
+#define TWI0_RCV_DATA16 0xFFC01E8C /* TWI0 FIFO Transmit Data Double-Byte Register */
+
+/* =========================
+ TWI1
+ ========================= */
+#define TWI1_CLKDIV 0xFFC01F00 /* TWI1 SCL Clock Divider */
+#define TWI1_CONTROL 0xFFC01F04 /* TWI1 Control Register */
+#define TWI1_SLAVE_CTL 0xFFC01F08 /* TWI1 Slave Mode Control Register */
+#define TWI1_SLAVE_STAT 0xFFC01F0C /* TWI1 Slave Mode Status Register */
+#define TWI1_SLAVE_ADDR 0xFFC01F10 /* TWI1 Slave Mode Address Register */
+#define TWI1_MASTER_CTL 0xFFC01F14 /* TWI1 Master Mode Control Registers */
+#define TWI1_MASTER_STAT 0xFFC01F18 /* TWI1 Master Mode Status Register */
+#define TWI1_MASTER_ADDR 0xFFC01F1C /* TWI1 Master Mode Address Register */
+#define TWI1_INT_STAT 0xFFC01F20 /* TWI1 Interrupt Status Register */
+#define TWI1_INT_MASK 0xFFC01F24 /* TWI1 Interrupt Mask Register */
+#define TWI1_FIFO_CTL 0xFFC01F28 /* TWI1 FIFO Control Register */
+#define TWI1_FIFO_STAT 0xFFC01F2C /* TWI1 FIFO Status Register */
+#define TWI1_XMT_DATA8 0xFFC01F80 /* TWI1 FIFO Transmit Data Single-Byte Register */
+#define TWI1_XMT_DATA16 0xFFC01F84 /* TWI1 FIFO Transmit Data Double-Byte Register */
+#define TWI1_RCV_DATA8 0xFFC01F88 /* TWI1 FIFO Transmit Data Single-Byte Register */
+#define TWI1_RCV_DATA16 0xFFC01F8C /* TWI1 FIFO Transmit Data Double-Byte Register */
+
+
+/* =========================
+ UART Registers
+ ========================= */
+
+/* =========================
+ UART0
+ ========================= */
+#define UART0_REVID 0xFFC02000 /* UART0 Revision ID Register */
+#define UART0_CTL 0xFFC02004 /* UART0 Control Register */
+#define UART0_STAT 0xFFC02008 /* UART0 Status Register */
+#define UART0_SCR 0xFFC0200C /* UART0 Scratch Register */
+#define UART0_CLK 0xFFC02010 /* UART0 Clock Rate Register */
+#define UART0_IER 0xFFC02014 /* UART0 Interrupt Mask Register */
+#define UART0_IER_SET 0xFFC02018 /* UART0 Interrupt Mask Set Register */
+#define UART0_IER_CLR 0xFFC0201C /* UART0 Interrupt Mask Clear Register */
+#define UART0_RBR 0xFFC02020 /* UART0 Receive Buffer Register */
+#define UART0_THR 0xFFC02024 /* UART0 Transmit Hold Register */
+#define UART0_TAIP 0xFFC02028 /* UART0 Transmit Address/Insert Pulse Register */
+#define UART0_TSR 0xFFC0202C /* UART0 Transmit Shift Register */
+#define UART0_RSR 0xFFC02030 /* UART0 Receive Shift Register */
+#define UART0_TXDIV 0xFFC02034 /* UART0 Transmit Clock Devider Register */
+#define UART0_RXDIV 0xFFC02038 /* UART0 Receive Clock Devider Register */
+
+/* =========================
+ UART1
+ ========================= */
+#define UART1_REVID 0xFFC02400 /* UART1 Revision ID Register */
+#define UART1_CTL 0xFFC02404 /* UART1 Control Register */
+#define UART1_STAT 0xFFC02408 /* UART1 Status Register */
+#define UART1_SCR 0xFFC0240C /* UART1 Scratch Register */
+#define UART1_CLK 0xFFC02410 /* UART1 Clock Rate Register */
+#define UART1_IER 0xFFC02414 /* UART1 Interrupt Mask Register */
+#define UART1_IER_SET 0xFFC02418 /* UART1 Interrupt Mask Set Register */
+#define UART1_IER_CLR 0xFFC0241C /* UART1 Interrupt Mask Clear Register */
+#define UART1_RBR 0xFFC02420 /* UART1 Receive Buffer Register */
+#define UART1_THR 0xFFC02424 /* UART1 Transmit Hold Register */
+#define UART1_TAIP 0xFFC02428 /* UART1 Transmit Address/Insert Pulse Register */
+#define UART1_TSR 0xFFC0242C /* UART1 Transmit Shift Register */
+#define UART1_RSR 0xFFC02430 /* UART1 Receive Shift Register */
+#define UART1_TXDIV 0xFFC02434 /* UART1 Transmit Clock Devider Register */
+#define UART1_RXDIV 0xFFC02438 /* UART1 Receive Clock Devider Register */
+
+
+/* =========================
+ PORT Registers
+ ========================= */
+
+/* =========================
+ PORTA
+ ========================= */
+#define PORTA_FER 0xFFC03000 /* PORTA Port x Function Enable Register */
+#define PORTA_FER_SET 0xFFC03004 /* PORTA Port x Function Enable Set Register */
+#define PORTA_FER_CLEAR 0xFFC03008 /* PORTA Port x Function Enable Clear Register */
+#define PORTA_DATA 0xFFC0300C /* PORTA Port x GPIO Data Register */
+#define PORTA_DATA_SET 0xFFC03010 /* PORTA Port x GPIO Data Set Register */
+#define PORTA_DATA_CLEAR 0xFFC03014 /* PORTA Port x GPIO Data Clear Register */
+#define PORTA_DIR 0xFFC03018 /* PORTA Port x GPIO Direction Register */
+#define PORTA_DIR_SET 0xFFC0301C /* PORTA Port x GPIO Direction Set Register */
+#define PORTA_DIR_CLEAR 0xFFC03020 /* PORTA Port x GPIO Direction Clear Register */
+#define PORTA_INEN 0xFFC03024 /* PORTA Port x GPIO Input Enable Register */
+#define PORTA_INEN_SET 0xFFC03028 /* PORTA Port x GPIO Input Enable Set Register */
+#define PORTA_INEN_CLEAR 0xFFC0302C /* PORTA Port x GPIO Input Enable Clear Register */
+#define PORTA_MUX 0xFFC03030 /* PORTA Port x Multiplexer Control Register */
+#define PORTA_DATA_TGL 0xFFC03034 /* PORTA Port x GPIO Input Enable Toggle Register */
+#define PORTA_POL 0xFFC03038 /* PORTA Port x GPIO Programming Inversion Register */
+#define PORTA_POL_SET 0xFFC0303C /* PORTA Port x GPIO Programming Inversion Set Register */
+#define PORTA_POL_CLEAR 0xFFC03040 /* PORTA Port x GPIO Programming Inversion Clear Register */
+#define PORTA_LOCK 0xFFC03044 /* PORTA Port x GPIO Lock Register */
+#define PORTA_REVID 0xFFC0307C /* PORTA Port x GPIO Revision ID */
+
+/* =========================
+ PORTB
+ ========================= */
+#define PORTB_FER 0xFFC03080 /* PORTB Port x Function Enable Register */
+#define PORTB_FER_SET 0xFFC03084 /* PORTB Port x Function Enable Set Register */
+#define PORTB_FER_CLEAR 0xFFC03088 /* PORTB Port x Function Enable Clear Register */
+#define PORTB_DATA 0xFFC0308C /* PORTB Port x GPIO Data Register */
+#define PORTB_DATA_SET 0xFFC03090 /* PORTB Port x GPIO Data Set Register */
+#define PORTB_DATA_CLEAR 0xFFC03094 /* PORTB Port x GPIO Data Clear Register */
+#define PORTB_DIR 0xFFC03098 /* PORTB Port x GPIO Direction Register */
+#define PORTB_DIR_SET 0xFFC0309C /* PORTB Port x GPIO Direction Set Register */
+#define PORTB_DIR_CLEAR 0xFFC030A0 /* PORTB Port x GPIO Direction Clear Register */
+#define PORTB_INEN 0xFFC030A4 /* PORTB Port x GPIO Input Enable Register */
+#define PORTB_INEN_SET 0xFFC030A8 /* PORTB Port x GPIO Input Enable Set Register */
+#define PORTB_INEN_CLEAR 0xFFC030AC /* PORTB Port x GPIO Input Enable Clear Register */
+#define PORTB_MUX 0xFFC030B0 /* PORTB Port x Multiplexer Control Register */
+#define PORTB_DATA_TGL 0xFFC030B4 /* PORTB Port x GPIO Input Enable Toggle Register */
+#define PORTB_POL 0xFFC030B8 /* PORTB Port x GPIO Programming Inversion Register */
+#define PORTB_POL_SET 0xFFC030BC /* PORTB Port x GPIO Programming Inversion Set Register */
+#define PORTB_POL_CLEAR 0xFFC030C0 /* PORTB Port x GPIO Programming Inversion Clear Register */
+#define PORTB_LOCK 0xFFC030C4 /* PORTB Port x GPIO Lock Register */
+#define PORTB_REVID 0xFFC030FC /* PORTB Port x GPIO Revision ID */
+
+/* =========================
+ PORTC
+ ========================= */
+#define PORTC_FER 0xFFC03100 /* PORTC Port x Function Enable Register */
+#define PORTC_FER_SET 0xFFC03104 /* PORTC Port x Function Enable Set Register */
+#define PORTC_FER_CLEAR 0xFFC03108 /* PORTC Port x Function Enable Clear Register */
+#define PORTC_DATA 0xFFC0310C /* PORTC Port x GPIO Data Register */
+#define PORTC_DATA_SET 0xFFC03110 /* PORTC Port x GPIO Data Set Register */
+#define PORTC_DATA_CLEAR 0xFFC03114 /* PORTC Port x GPIO Data Clear Register */
+#define PORTC_DIR 0xFFC03118 /* PORTC Port x GPIO Direction Register */
+#define PORTC_DIR_SET 0xFFC0311C /* PORTC Port x GPIO Direction Set Register */
+#define PORTC_DIR_CLEAR 0xFFC03120 /* PORTC Port x GPIO Direction Clear Register */
+#define PORTC_INEN 0xFFC03124 /* PORTC Port x GPIO Input Enable Register */
+#define PORTC_INEN_SET 0xFFC03128 /* PORTC Port x GPIO Input Enable Set Register */
+#define PORTC_INEN_CLEAR 0xFFC0312C /* PORTC Port x GPIO Input Enable Clear Register */
+#define PORTC_MUX 0xFFC03130 /* PORTC Port x Multiplexer Control Register */
+#define PORTC_DATA_TGL 0xFFC03134 /* PORTC Port x GPIO Input Enable Toggle Register */
+#define PORTC_POL 0xFFC03138 /* PORTC Port x GPIO Programming Inversion Register */
+#define PORTC_POL_SET 0xFFC0313C /* PORTC Port x GPIO Programming Inversion Set Register */
+#define PORTC_POL_CLEAR 0xFFC03140 /* PORTC Port x GPIO Programming Inversion Clear Register */
+#define PORTC_LOCK 0xFFC03144 /* PORTC Port x GPIO Lock Register */
+#define PORTC_REVID 0xFFC0317C /* PORTC Port x GPIO Revision ID */
+
+/* =========================
+ PORTD
+ ========================= */
+#define PORTD_FER 0xFFC03180 /* PORTD Port x Function Enable Register */
+#define PORTD_FER_SET 0xFFC03184 /* PORTD Port x Function Enable Set Register */
+#define PORTD_FER_CLEAR 0xFFC03188 /* PORTD Port x Function Enable Clear Register */
+#define PORTD_DATA 0xFFC0318C /* PORTD Port x GPIO Data Register */
+#define PORTD_DATA_SET 0xFFC03190 /* PORTD Port x GPIO Data Set Register */
+#define PORTD_DATA_CLEAR 0xFFC03194 /* PORTD Port x GPIO Data Clear Register */
+#define PORTD_DIR 0xFFC03198 /* PORTD Port x GPIO Direction Register */
+#define PORTD_DIR_SET 0xFFC0319C /* PORTD Port x GPIO Direction Set Register */
+#define PORTD_DIR_CLEAR 0xFFC031A0 /* PORTD Port x GPIO Direction Clear Register */
+#define PORTD_INEN 0xFFC031A4 /* PORTD Port x GPIO Input Enable Register */
+#define PORTD_INEN_SET 0xFFC031A8 /* PORTD Port x GPIO Input Enable Set Register */
+#define PORTD_INEN_CLEAR 0xFFC031AC /* PORTD Port x GPIO Input Enable Clear Register */
+#define PORTD_MUX 0xFFC031B0 /* PORTD Port x Multiplexer Control Register */
+#define PORTD_DATA_TGL 0xFFC031B4 /* PORTD Port x GPIO Input Enable Toggle Register */
+#define PORTD_POL 0xFFC031B8 /* PORTD Port x GPIO Programming Inversion Register */
+#define PORTD_POL_SET 0xFFC031BC /* PORTD Port x GPIO Programming Inversion Set Register */
+#define PORTD_POL_CLEAR 0xFFC031C0 /* PORTD Port x GPIO Programming Inversion Clear Register */
+#define PORTD_LOCK 0xFFC031C4 /* PORTD Port x GPIO Lock Register */
+#define PORTD_REVID 0xFFC031FC /* PORTD Port x GPIO Revision ID */
+
+/* =========================
+ PORTE
+ ========================= */
+#define PORTE_FER 0xFFC03200 /* PORTE Port x Function Enable Register */
+#define PORTE_FER_SET 0xFFC03204 /* PORTE Port x Function Enable Set Register */
+#define PORTE_FER_CLEAR 0xFFC03208 /* PORTE Port x Function Enable Clear Register */
+#define PORTE_DATA 0xFFC0320C /* PORTE Port x GPIO Data Register */
+#define PORTE_DATA_SET 0xFFC03210 /* PORTE Port x GPIO Data Set Register */
+#define PORTE_DATA_CLEAR 0xFFC03214 /* PORTE Port x GPIO Data Clear Register */
+#define PORTE_DIR 0xFFC03218 /* PORTE Port x GPIO Direction Register */
+#define PORTE_DIR_SET 0xFFC0321C /* PORTE Port x GPIO Direction Set Register */
+#define PORTE_DIR_CLEAR 0xFFC03220 /* PORTE Port x GPIO Direction Clear Register */
+#define PORTE_INEN 0xFFC03224 /* PORTE Port x GPIO Input Enable Register */
+#define PORTE_INEN_SET 0xFFC03228 /* PORTE Port x GPIO Input Enable Set Register */
+#define PORTE_INEN_CLEAR 0xFFC0322C /* PORTE Port x GPIO Input Enable Clear Register */
+#define PORTE_MUX 0xFFC03230 /* PORTE Port x Multiplexer Control Register */
+#define PORTE_DATA_TGL 0xFFC03234 /* PORTE Port x GPIO Input Enable Toggle Register */
+#define PORTE_POL 0xFFC03238 /* PORTE Port x GPIO Programming Inversion Register */
+#define PORTE_POL_SET 0xFFC0323C /* PORTE Port x GPIO Programming Inversion Set Register */
+#define PORTE_POL_CLEAR 0xFFC03240 /* PORTE Port x GPIO Programming Inversion Clear Register */
+#define PORTE_LOCK 0xFFC03244 /* PORTE Port x GPIO Lock Register */
+#define PORTE_REVID 0xFFC0327C /* PORTE Port x GPIO Revision ID */
+
+/* =========================
+ PORTF
+ ========================= */
+#define PORTF_FER 0xFFC03280 /* PORTF Port x Function Enable Register */
+#define PORTF_FER_SET 0xFFC03284 /* PORTF Port x Function Enable Set Register */
+#define PORTF_FER_CLEAR 0xFFC03288 /* PORTF Port x Function Enable Clear Register */
+#define PORTF_DATA 0xFFC0328C /* PORTF Port x GPIO Data Register */
+#define PORTF_DATA_SET 0xFFC03290 /* PORTF Port x GPIO Data Set Register */
+#define PORTF_DATA_CLEAR 0xFFC03294 /* PORTF Port x GPIO Data Clear Register */
+#define PORTF_DIR 0xFFC03298 /* PORTF Port x GPIO Direction Register */
+#define PORTF_DIR_SET 0xFFC0329C /* PORTF Port x GPIO Direction Set Register */
+#define PORTF_DIR_CLEAR 0xFFC032A0 /* PORTF Port x GPIO Direction Clear Register */
+#define PORTF_INEN 0xFFC032A4 /* PORTF Port x GPIO Input Enable Register */
+#define PORTF_INEN_SET 0xFFC032A8 /* PORTF Port x GPIO Input Enable Set Register */
+#define PORTF_INEN_CLEAR 0xFFC032AC /* PORTF Port x GPIO Input Enable Clear Register */
+#define PORTF_MUX 0xFFC032B0 /* PORTF Port x Multiplexer Control Register */
+#define PORTF_DATA_TGL 0xFFC032B4 /* PORTF Port x GPIO Input Enable Toggle Register */
+#define PORTF_POL 0xFFC032B8 /* PORTF Port x GPIO Programming Inversion Register */
+#define PORTF_POL_SET 0xFFC032BC /* PORTF Port x GPIO Programming Inversion Set Register */
+#define PORTF_POL_CLEAR 0xFFC032C0 /* PORTF Port x GPIO Programming Inversion Clear Register */
+#define PORTF_LOCK 0xFFC032C4 /* PORTF Port x GPIO Lock Register */
+#define PORTF_REVID 0xFFC032FC /* PORTF Port x GPIO Revision ID */
+
+/* =========================
+ PORTG
+ ========================= */
+#define PORTG_FER 0xFFC03300 /* PORTG Port x Function Enable Register */
+#define PORTG_FER_SET 0xFFC03304 /* PORTG Port x Function Enable Set Register */
+#define PORTG_FER_CLEAR 0xFFC03308 /* PORTG Port x Function Enable Clear Register */
+#define PORTG_DATA 0xFFC0330C /* PORTG Port x GPIO Data Register */
+#define PORTG_DATA_SET 0xFFC03310 /* PORTG Port x GPIO Data Set Register */
+#define PORTG_DATA_CLEAR 0xFFC03314 /* PORTG Port x GPIO Data Clear Register */
+#define PORTG_DIR 0xFFC03318 /* PORTG Port x GPIO Direction Register */
+#define PORTG_DIR_SET 0xFFC0331C /* PORTG Port x GPIO Direction Set Register */
+#define PORTG_DIR_CLEAR 0xFFC03320 /* PORTG Port x GPIO Direction Clear Register */
+#define PORTG_INEN 0xFFC03324 /* PORTG Port x GPIO Input Enable Register */
+#define PORTG_INEN_SET 0xFFC03328 /* PORTG Port x GPIO Input Enable Set Register */
+#define PORTG_INEN_CLEAR 0xFFC0332C /* PORTG Port x GPIO Input Enable Clear Register */
+#define PORTG_MUX 0xFFC03330 /* PORTG Port x Multiplexer Control Register */
+#define PORTG_DATA_TGL 0xFFC03334 /* PORTG Port x GPIO Input Enable Toggle Register */
+#define PORTG_POL 0xFFC03338 /* PORTG Port x GPIO Programming Inversion Register */
+#define PORTG_POL_SET 0xFFC0333C /* PORTG Port x GPIO Programming Inversion Set Register */
+#define PORTG_POL_CLEAR 0xFFC03340 /* PORTG Port x GPIO Programming Inversion Clear Register */
+#define PORTG_LOCK 0xFFC03344 /* PORTG Port x GPIO Lock Register */
+#define PORTG_REVID 0xFFC0337C /* PORTG Port x GPIO Revision ID */
+
+
+/* =========================
+ PINT Registers
+ ========================= */
+
+/* =========================
+ PINT0
+ ========================= */
+#define PINT0_MASK_SET 0xFFC04000 /* PINT0 Pint Mask Set Register */
+#define PINT0_MASK_CLEAR 0xFFC04004 /* PINT0 Pint Mask Clear Register */
+#define PINT0_REQUEST 0xFFC04008 /* PINT0 Pint Request Register */
+#define PINT0_ASSIGN 0xFFC0400C /* PINT0 Pint Assign Register */
+#define PINT0_EDGE_SET 0xFFC04010 /* PINT0 Pint Edge Set Register */
+#define PINT0_EDGE_CLEAR 0xFFC04014 /* PINT0 Pint Edge Clear Register */
+#define PINT0_INVERT_SET 0xFFC04018 /* PINT0 Pint Invert Set Register */
+#define PINT0_INVERT_CLEAR 0xFFC0401C /* PINT0 Pint Invert Clear Register */
+#define PINT0_PINSTATE 0xFFC04020 /* PINT0 Pint Pinstate Register */
+#define PINT0_LATCH 0xFFC04024 /* PINT0 Pint Latch Register */
+
+/* =========================
+ PINT1
+ ========================= */
+#define PINT1_MASK_SET 0xFFC04100 /* PINT1 Pint Mask Set Register */
+#define PINT1_MASK_CLEAR 0xFFC04104 /* PINT1 Pint Mask Clear Register */
+#define PINT1_REQUEST 0xFFC04108 /* PINT1 Pint Request Register */
+#define PINT1_ASSIGN 0xFFC0410C /* PINT1 Pint Assign Register */
+#define PINT1_EDGE_SET 0xFFC04110 /* PINT1 Pint Edge Set Register */
+#define PINT1_EDGE_CLEAR 0xFFC04114 /* PINT1 Pint Edge Clear Register */
+#define PINT1_INVERT_SET 0xFFC04118 /* PINT1 Pint Invert Set Register */
+#define PINT1_INVERT_CLEAR 0xFFC0411C /* PINT1 Pint Invert Clear Register */
+#define PINT1_PINSTATE 0xFFC04120 /* PINT1 Pint Pinstate Register */
+#define PINT1_LATCH 0xFFC04124 /* PINT1 Pint Latch Register */
+
+/* =========================
+ PINT2
+ ========================= */
+#define PINT2_MASK_SET 0xFFC04200 /* PINT2 Pint Mask Set Register */
+#define PINT2_MASK_CLEAR 0xFFC04204 /* PINT2 Pint Mask Clear Register */
+#define PINT2_REQUEST 0xFFC04208 /* PINT2 Pint Request Register */
+#define PINT2_ASSIGN 0xFFC0420C /* PINT2 Pint Assign Register */
+#define PINT2_EDGE_SET 0xFFC04210 /* PINT2 Pint Edge Set Register */
+#define PINT2_EDGE_CLEAR 0xFFC04214 /* PINT2 Pint Edge Clear Register */
+#define PINT2_INVERT_SET 0xFFC04218 /* PINT2 Pint Invert Set Register */
+#define PINT2_INVERT_CLEAR 0xFFC0421C /* PINT2 Pint Invert Clear Register */
+#define PINT2_PINSTATE 0xFFC04220 /* PINT2 Pint Pinstate Register */
+#define PINT2_LATCH 0xFFC04224 /* PINT2 Pint Latch Register */
+
+/* =========================
+ PINT3
+ ========================= */
+#define PINT3_MASK_SET 0xFFC04300 /* PINT3 Pint Mask Set Register */
+#define PINT3_MASK_CLEAR 0xFFC04304 /* PINT3 Pint Mask Clear Register */
+#define PINT3_REQUEST 0xFFC04308 /* PINT3 Pint Request Register */
+#define PINT3_ASSIGN 0xFFC0430C /* PINT3 Pint Assign Register */
+#define PINT3_EDGE_SET 0xFFC04310 /* PINT3 Pint Edge Set Register */
+#define PINT3_EDGE_CLEAR 0xFFC04314 /* PINT3 Pint Edge Clear Register */
+#define PINT3_INVERT_SET 0xFFC04318 /* PINT3 Pint Invert Set Register */
+#define PINT3_INVERT_CLEAR 0xFFC0431C /* PINT3 Pint Invert Clear Register */
+#define PINT3_PINSTATE 0xFFC04320 /* PINT3 Pint Pinstate Register */
+#define PINT3_LATCH 0xFFC04324 /* PINT3 Pint Latch Register */
+
+/* =========================
+ PINT4
+ ========================= */
+#define PINT4_MASK_SET 0xFFC04400 /* PINT4 Pint Mask Set Register */
+#define PINT4_MASK_CLEAR 0xFFC04404 /* PINT4 Pint Mask Clear Register */
+#define PINT4_REQUEST 0xFFC04408 /* PINT4 Pint Request Register */
+#define PINT4_ASSIGN 0xFFC0440C /* PINT4 Pint Assign Register */
+#define PINT4_EDGE_SET 0xFFC04410 /* PINT4 Pint Edge Set Register */
+#define PINT4_EDGE_CLEAR 0xFFC04414 /* PINT4 Pint Edge Clear Register */
+#define PINT4_INVERT_SET 0xFFC04418 /* PINT4 Pint Invert Set Register */
+#define PINT4_INVERT_CLEAR 0xFFC0441C /* PINT4 Pint Invert Clear Register */
+#define PINT4_PINSTATE 0xFFC04420 /* PINT4 Pint Pinstate Register */
+#define PINT4_LATCH 0xFFC04424 /* PINT4 Pint Latch Register */
+
+/* =========================
+ PINT5
+ ========================= */
+#define PINT5_MASK_SET 0xFFC04500 /* PINT5 Pint Mask Set Register */
+#define PINT5_MASK_CLEAR 0xFFC04504 /* PINT5 Pint Mask Clear Register */
+#define PINT5_REQUEST 0xFFC04508 /* PINT5 Pint Request Register */
+#define PINT5_ASSIGN 0xFFC0450C /* PINT5 Pint Assign Register */
+#define PINT5_EDGE_SET 0xFFC04510 /* PINT5 Pint Edge Set Register */
+#define PINT5_EDGE_CLEAR 0xFFC04514 /* PINT5 Pint Edge Clear Register */
+#define PINT5_INVERT_SET 0xFFC04518 /* PINT5 Pint Invert Set Register */
+#define PINT5_INVERT_CLEAR 0xFFC0451C /* PINT5 Pint Invert Clear Register */
+#define PINT5_PINSTATE 0xFFC04520 /* PINT5 Pint Pinstate Register */
+#define PINT5_LATCH 0xFFC04524 /* PINT5 Pint Latch Register */
+
+
+/* =========================
+ SMC Registers
+ ========================= */
+
+/* =========================
+ SMC0
+ ========================= */
+#define SMC_GCTL 0xFFC16004 /* SMC0 SMC Control Register */
+#define SMC_GSTAT 0xFFC16008 /* SMC0 SMC Status Register */
+#define SMC_B0CTL 0xFFC1600C /* SMC0 SMC Bank0 Control Register */
+#define SMC_B0TIM 0xFFC16010 /* SMC0 SMC Bank0 Timing Register */
+#define SMC_B0ETIM 0xFFC16014 /* SMC0 SMC Bank0 Extended Timing Register */
+#define SMC_B1CTL 0xFFC1601C /* SMC0 SMC BANK1 Control Register */
+#define SMC_B1TIM 0xFFC16020 /* SMC0 SMC BANK1 Timing Register */
+#define SMC_B1ETIM 0xFFC16024 /* SMC0 SMC BANK1 Extended Timing Register */
+#define SMC_B2CTL 0xFFC1602C /* SMC0 SMC BANK2 Control Register */
+#define SMC_B2TIM 0xFFC16030 /* SMC0 SMC BANK2 Timing Register */
+#define SMC_B2ETIM 0xFFC16034 /* SMC0 SMC BANK2 Extended Timing Register */
+#define SMC_B3CTL 0xFFC1603C /* SMC0 SMC BANK3 Control Register */
+#define SMC_B3TIM 0xFFC16040 /* SMC0 SMC BANK3 Timing Register */
+#define SMC_B3ETIM 0xFFC16044 /* SMC0 SMC BANK3 Extended Timing Register */
+
+
+/* =========================
+ WDOG Registers
+ ========================= */
+
+/* =========================
+ WDOG0
+ ========================= */
+#define WDOG0_CTL 0xFFC17000 /* WDOG0 Control Register */
+#define WDOG0_CNT 0xFFC17004 /* WDOG0 Count Register */
+#define WDOG0_STAT 0xFFC17008 /* WDOG0 Watchdog Timer Status Register */
+#define WDOG_CTL WDOG0_CTL
+#define WDOG_CNT WDOG0_CNT
+#define WDOG_STAT WDOG0_STAT
+
+/* =========================
+ WDOG1
+ ========================= */
+#define WDOG1_CTL 0xFFC17800 /* WDOG1 Control Register */
+#define WDOG1_CNT 0xFFC17804 /* WDOG1 Count Register */
+#define WDOG1_STAT 0xFFC17808 /* WDOG1 Watchdog Timer Status Register */
+
+
+/* =========================
+ SDU Registers
+ ========================= */
+
+/* =========================
+ SDU0
+ ========================= */
+#define SDU0_IDCODE 0xFFC1F020 /* SDU0 ID Code Register */
+#define SDU0_CTL 0xFFC1F050 /* SDU0 Control Register */
+#define SDU0_STAT 0xFFC1F054 /* SDU0 Status Register */
+#define SDU0_MACCTL 0xFFC1F058 /* SDU0 Memory Access Control Register */
+#define SDU0_MACADDR 0xFFC1F05C /* SDU0 Memory Access Address Register */
+#define SDU0_MACDATA 0xFFC1F060 /* SDU0 Memory Access Data Register */
+#define SDU0_DMARD 0xFFC1F064 /* SDU0 DMA Read Data Register */
+#define SDU0_DMAWD 0xFFC1F068 /* SDU0 DMA Write Data Register */
+#define SDU0_MSG 0xFFC1F080 /* SDU0 Message Register */
+#define SDU0_MSG_SET 0xFFC1F084 /* SDU0 Message Set Register */
+#define SDU0_MSG_CLR 0xFFC1F088 /* SDU0 Message Clear Register */
+#define SDU0_GHLT 0xFFC1F08C /* SDU0 Group Halt Register */
+
+
+/* =========================
+ EMAC Registers
+ ========================= */
+/* =========================
+ EMAC0
+ ========================= */
+#define EMAC0_MACCFG 0xFFC20000 /* EMAC0 MAC Configuration Register */
+#define EMAC0_MACFRMFILT 0xFFC20004 /* EMAC0 Filter Register for filtering Received Frames */
+#define EMAC0_HASHTBL_HI 0xFFC20008 /* EMAC0 Contains the Upper 32 bits of the hash table */
+#define EMAC0_HASHTBL_LO 0xFFC2000C /* EMAC0 Contains the lower 32 bits of the hash table */
+#define EMAC0_GMII_ADDR 0xFFC20010 /* EMAC0 Management Address Register */
+#define EMAC0_GMII_DATA 0xFFC20014 /* EMAC0 Management Data Register */
+#define EMAC0_FLOWCTL 0xFFC20018 /* EMAC0 MAC FLow Control Register */
+#define EMAC0_VLANTAG 0xFFC2001C /* EMAC0 VLAN Tag Register */
+#define EMAC0_VER 0xFFC20020 /* EMAC0 EMAC Version Register */
+#define EMAC0_DBG 0xFFC20024 /* EMAC0 EMAC Debug Register */
+#define EMAC0_RMTWKUP 0xFFC20028 /* EMAC0 Remote wake up frame register */
+#define EMAC0_PMT_CTLSTAT 0xFFC2002C /* EMAC0 PMT Control and Status Register */
+#define EMAC0_ISTAT 0xFFC20038 /* EMAC0 EMAC Interrupt Status Register */
+#define EMAC0_IMSK 0xFFC2003C /* EMAC0 EMAC Interrupt Mask Register */
+#define EMAC0_ADDR0_HI 0xFFC20040 /* EMAC0 EMAC Address0 High Register */
+#define EMAC0_ADDR0_LO 0xFFC20044 /* EMAC0 EMAC Address0 Low Register */
+#define EMAC0_MMC_CTL 0xFFC20100 /* EMAC0 MMC Control Register */
+#define EMAC0_MMC_RXINT 0xFFC20104 /* EMAC0 MMC RX Interrupt Register */
+#define EMAC0_MMC_TXINT 0xFFC20108 /* EMAC0 MMC TX Interrupt Register */
+#define EMAC0_MMC_RXIMSK 0xFFC2010C /* EMAC0 MMC RX Interrupt Mask Register */
+#define EMAC0_MMC_TXIMSK 0xFFC20110 /* EMAC0 MMC TX Interrupt Mask Register */
+#define EMAC0_TXOCTCNT_GB 0xFFC20114 /* EMAC0 Num bytes transmitted exclusive of preamble */
+#define EMAC0_TXFRMCNT_GB 0xFFC20118 /* EMAC0 Num frames transmitted exclusive of retired */
+#define EMAC0_TXBCASTFRM_G 0xFFC2011C /* EMAC0 Number of good broadcast frames transmitted. */
+#define EMAC0_TXMCASTFRM_G 0xFFC20120 /* EMAC0 Number of good multicast frames transmitted. */
+#define EMAC0_TX64_GB 0xFFC20124 /* EMAC0 Number of 64 byte length frames */
+#define EMAC0_TX65TO127_GB 0xFFC20128 /* EMAC0 Number of frames of length b/w 65-127 (inclusive) bytes */
+#define EMAC0_TX128TO255_GB 0xFFC2012C /* EMAC0 Number of frames of length b/w 128-255 (inclusive) bytes */
+#define EMAC0_TX256TO511_GB 0xFFC20130 /* EMAC0 Number of frames of length b/w 256-511 (inclusive) bytes */
+#define EMAC0_TX512TO1023_GB 0xFFC20134 /* EMAC0 Number of frames of length b/w 512-1023 (inclusive) bytes */
+#define EMAC0_TX1024TOMAX_GB 0xFFC20138 /* EMAC0 Number of frames of length b/w 1024-max (inclusive) bytes */
+#define EMAC0_TXUCASTFRM_GB 0xFFC2013C /* EMAC0 Number of good and bad unicast frames transmitted */
+#define EMAC0_TXMCASTFRM_GB 0xFFC20140 /* EMAC0 Number of good and bad multicast frames transmitted */
+#define EMAC0_TXBCASTFRM_GB 0xFFC20144 /* EMAC0 Number of good and bad broadcast frames transmitted */
+#define EMAC0_TXUNDR_ERR 0xFFC20148 /* EMAC0 Number of frames aborted due to frame underflow error */
+#define EMAC0_TXSNGCOL_G 0xFFC2014C /* EMAC0 Number of transmitted frames after single collision */
+#define EMAC0_TXMULTCOL_G 0xFFC20150 /* EMAC0 Number of transmitted frames with more than one collision */
+#define EMAC0_TXDEFERRED 0xFFC20154 /* EMAC0 Number of transmitted frames after deferral */
+#define EMAC0_TXLATECOL 0xFFC20158 /* EMAC0 Number of frames aborted due to late collision error */
+#define EMAC0_TXEXCESSCOL 0xFFC2015C /* EMAC0 Number of aborted frames due to excessive collisions */
+#define EMAC0_TXCARR_ERR 0xFFC20160 /* EMAC0 Number of aborted frames due to carrier sense error */
+#define EMAC0_TXOCTCNT_G 0xFFC20164 /* EMAC0 Number of bytes transmitted in good frames only */
+#define EMAC0_TXFRMCNT_G 0xFFC20168 /* EMAC0 Number of good frames transmitted. */
+#define EMAC0_TXEXCESSDEF 0xFFC2016C /* EMAC0 Number of frames aborted due to excessive deferral */
+#define EMAC0_TXPAUSEFRM 0xFFC20170 /* EMAC0 Number of good PAUSE frames transmitted. */
+#define EMAC0_TXVLANFRM_G 0xFFC20174 /* EMAC0 Number of VLAN frames transmitted */
+#define EMAC0_RXFRMCNT_GB 0xFFC20180 /* EMAC0 Number of good and bad frames received. */
+#define EMAC0_RXOCTCNT_GB 0xFFC20184 /* EMAC0 Number of bytes received in good and bad frames */
+#define EMAC0_RXOCTCNT_G 0xFFC20188 /* EMAC0 Number of bytes received only in good frames */
+#define EMAC0_RXBCASTFRM_G 0xFFC2018C /* EMAC0 Number of good broadcast frames received. */
+#define EMAC0_RXMCASTFRM_G 0xFFC20190 /* EMAC0 Number of good multicast frames received */
+#define EMAC0_RXCRC_ERR 0xFFC20194 /* EMAC0 Number of frames received with CRC error */
+#define EMAC0_RXALIGN_ERR 0xFFC20198 /* EMAC0 Number of frames with alignment error */
+#define EMAC0_RXRUNT_ERR 0xFFC2019C /* EMAC0 Number of frames received with runt error. */
+#define EMAC0_RXJAB_ERR 0xFFC201A0 /* EMAC0 Number of frames received with length greater than 1518 */
+#define EMAC0_RXUSIZE_G 0xFFC201A4 /* EMAC0 Number of frames received with length 64 */
+#define EMAC0_RXOSIZE_G 0xFFC201A8 /* EMAC0 Number of frames received with length greater than maxium */
+#define EMAC0_RX64_GB 0xFFC201AC /* EMAC0 Number of good and bad frames of lengh 64 bytes */
+#define EMAC0_RX65TO127_GB 0xFFC201B0 /* EMAC0 Number of good and bad frame between 64-127(inclusive) */
+#define EMAC0_RX128TO255_GB 0xFFC201B4 /* EMAC0 Number of good and bad frames received with length between 128 and 255 (inclusive) bytes, exclusive of preamble. */
+#define EMAC0_RX256TO511_GB 0xFFC201B8 /* EMAC0 Number of good and bad frames between 256-511(inclusive) */
+#define EMAC0_RX512TO1023_GB 0xFFC201BC /* EMAC0 Number of good and bad frames received between 512-1023 */
+#define EMAC0_RX1024TOMAX_GB 0xFFC201C0 /* EMAC0 Number of frames received between 1024 and maxsize */
+#define EMAC0_RXUCASTFRM_G 0xFFC201C4 /* EMAC0 Number of good unicast frames received. */
+#define EMAC0_RXLEN_ERR 0xFFC201C8 /* EMAC0 Number of frames received with length error */
+#define EMAC0_RXOORTYPE 0xFFC201CC /* EMAC0 Number of frames with length not equal to valid frame size */
+#define EMAC0_RXPAUSEFRM 0xFFC201D0 /* EMAC0 Number of good and valid PAUSE frames received. */
+#define EMAC0_RXFIFO_OVF 0xFFC201D4 /* EMAC0 Number of missed received frames due to FIFO overflow. This counter is not present in the GMAC-CORE configuration. */
+#define EMAC0_RXVLANFRM_GB 0xFFC201D8 /* EMAC0 Number of good and bad VLAN frames received. */
+#define EMAC0_RXWDOG_ERR 0xFFC201DC /* EMAC0 Frames received with error due to watchdog timeout */
+#define EMAC0_IPC_RXIMSK 0xFFC20200 /* EMAC0 MMC IPC RX Interrupt Mask Register */
+#define EMAC0_IPC_RXINT 0xFFC20208 /* EMAC0 MMC IPC RX Interrupt Register */
+#define EMAC0_RXIPV4_GD_FRM 0xFFC20210 /* EMAC0 Number of good IPv4 datagrams */
+#define EMAC0_RXIPV4_HDR_ERR_FRM 0xFFC20214 /* EMAC0 Number of IPv4 datagrams with header errors */
+#define EMAC0_RXIPV4_NOPAY_FRM 0xFFC20218 /* EMAC0 Number of IPv4 datagrams without checksum */
+#define EMAC0_RXIPV4_FRAG_FRM 0xFFC2021C /* EMAC0 Number of good IPv4 datagrams with fragmentation */
+#define EMAC0_RXIPV4_UDSBL_FRM 0xFFC20220 /* EMAC0 Number of IPv4 UDP datagrams with disabled checksum */
+#define EMAC0_RXIPV6_GD_FRM 0xFFC20224 /* EMAC0 Number of IPv4 datagrams with TCP/UDP/ICMP payloads */
+#define EMAC0_RXIPV6_HDR_ERR_FRM 0xFFC20228 /* EMAC0 Number of IPv6 datagrams with header errors */
+#define EMAC0_RXIPV6_NOPAY_FRM 0xFFC2022C /* EMAC0 Number of IPv6 datagrams with no TCP/UDP/ICMP payload */
+#define EMAC0_RXUDP_GD_FRM 0xFFC20230 /* EMAC0 Number of good IP datagrames with good UDP payload */
+#define EMAC0_RXUDP_ERR_FRM 0xFFC20234 /* EMAC0 Number of good IP datagrams with UDP checksum errors */
+#define EMAC0_RXTCP_GD_FRM 0xFFC20238 /* EMAC0 Number of good IP datagrams with a good TCP payload */
+#define EMAC0_RXTCP_ERR_FRM 0xFFC2023C /* EMAC0 Number of good IP datagrams with TCP checksum errors */
+#define EMAC0_RXICMP_GD_FRM 0xFFC20240 /* EMAC0 Number of good IP datagrams with a good ICMP payload */
+#define EMAC0_RXICMP_ERR_FRM 0xFFC20244 /* EMAC0 Number of good IP datagrams with ICMP checksum errors */
+#define EMAC0_RXIPV4_GD_OCT 0xFFC20250 /* EMAC0 Bytes received in IPv4 datagrams including tcp,udp or icmp */
+#define EMAC0_RXIPV4_HDR_ERR_OCT 0xFFC20254 /* EMAC0 Bytes received in IPv4 datagrams with header errors */
+#define EMAC0_RXIPV4_NOPAY_OCT 0xFFC20258 /* EMAC0 Bytes received in IPv4 datagrams without tcp,udp,icmp load */
+#define EMAC0_RXIPV4_FRAG_OCT 0xFFC2025C /* EMAC0 Bytes received in fragmented IPv4 datagrams */
+#define EMAC0_RXIPV4_UDSBL_OCT 0xFFC20260 /* EMAC0 Bytes received in UDP segment with checksum disabled */
+#define EMAC0_RXIPV6_GD_OCT 0xFFC20264 /* EMAC0 Bytes received in good IPv6 including tcp,udp or icmp load */
+#define EMAC0_RXIPV6_HDR_ERR_OCT 0xFFC20268 /* EMAC0 Number of bytes received in IPv6 with header errors */
+#define EMAC0_RXIPV6_NOPAY_OCT 0xFFC2026C /* EMAC0 Bytes received in IPv6 without tcp,udp or icmp load */
+#define EMAC0_RXUDP_GD_OCT 0xFFC20270 /* EMAC0 Number of bytes received in good UDP segments */
+#define EMAC0_RXUDP_ERR_OCT 0xFFC20274 /* EMAC0 Number of bytes received in UDP segment with checksum err */
+#define EMAC0_RXTCP_GD_OCT 0xFFC20278 /* EMAC0 Number of bytes received in a good TCP segment */
+#define EMAC0_RXTCP_ERR_OCT 0xFFC2027C /* EMAC0 Number of bytes received in TCP segment with checksum err */
+#define EMAC0_RXICMP_GD_OCT 0xFFC20280 /* EMAC0 Number of bytes received in a good ICMP segment */
+#define EMAC0_RXICMP_ERR_OCT 0xFFC20284 /* EMAC0 Bytes received in an ICMP segment with checksum errors */
+#define EMAC0_TM_CTL 0xFFC20700 /* EMAC0 EMAC Time Stamp Control Register */
+#define EMAC0_TM_SUBSEC 0xFFC20704 /* EMAC0 EMAC Time Stamp Sub Second Increment */
+#define EMAC0_TM_SEC 0xFFC20708 /* EMAC0 EMAC Time Stamp Second Register */
+#define EMAC0_TM_NSEC 0xFFC2070C /* EMAC0 EMAC Time Stamp Nano Second Register */
+#define EMAC0_TM_SECUPDT 0xFFC20710 /* EMAC0 EMAC Time Stamp Seconds Update */
+#define EMAC0_TM_NSECUPDT 0xFFC20714 /* EMAC0 EMAC Time Stamp Nano Seconds Update */
+#define EMAC0_TM_ADDEND 0xFFC20718 /* EMAC0 EMAC Time Stamp Addend Register */
+#define EMAC0_TM_TGTM 0xFFC2071C /* EMAC0 EMAC Time Stamp Target Time Sec. */
+#define EMAC0_TM_NTGTM 0xFFC20720 /* EMAC0 EMAC Time Stamp Target Time Nanosec. */
+#define EMAC0_TM_HISEC 0xFFC20724 /* EMAC0 EMAC Time Stamp High Second Register */
+#define EMAC0_TM_STMPSTAT 0xFFC20728 /* EMAC0 EMAC Time Stamp Status Register */
+#define EMAC0_TM_PPSCTL 0xFFC2072C /* EMAC0 EMAC PPS Control Register */
+#define EMAC0_TM_AUXSTMP_NSEC 0xFFC20730 /* EMAC0 EMAC Auxillary Time Stamp Nano Register */
+#define EMAC0_TM_AUXSTMP_SEC 0xFFC20734 /* EMAC0 EMAC Auxillary Time Stamp Sec Register */
+#define EMAC0_DMA_BUSMODE 0xFFC21000 /* EMAC0 Bus Operating Modes for EMAC DMA */
+#define EMAC0_DMA_TXPOLL 0xFFC21004 /* EMAC0 TX DMA Poll demand register */
+#define EMAC0_DMA_RXPOLL 0xFFC21008 /* EMAC0 RX DMA Poll demand register */
+#define EMAC0_DMA_RXDSC_ADDR 0xFFC2100C /* EMAC0 RX Descriptor List Address */
+#define EMAC0_DMA_TXDSC_ADDR 0xFFC21010 /* EMAC0 TX Descriptor List Address */
+#define EMAC0_DMA_STAT 0xFFC21014 /* EMAC0 DMA Status Register */
+#define EMAC0_DMA_OPMODE 0xFFC21018 /* EMAC0 DMA Operation Mode Register */
+#define EMAC0_DMA_IEN 0xFFC2101C /* EMAC0 DMA Interrupt Enable Register */
+#define EMAC0_DMA_MISS_FRM 0xFFC21020 /* EMAC0 DMA missed frame and buffer overflow counter */
+#define EMAC0_DMA_RXIWDOG 0xFFC21024 /* EMAC0 DMA RX Interrupt Watch Dog timer */
+#define EMAC0_DMA_BMMODE 0xFFC21028 /* EMAC0 AXI Bus Mode Register */
+#define EMAC0_DMA_BMSTAT 0xFFC2102C /* EMAC0 AXI Status Register */
+#define EMAC0_DMA_TXDSC_CUR 0xFFC21048 /* EMAC0 TX current descriptor register */
+#define EMAC0_DMA_RXDSC_CUR 0xFFC2104C /* EMAC0 RX current descriptor register */
+#define EMAC0_DMA_TXBUF_CUR 0xFFC21050 /* EMAC0 TX current buffer pointer register */
+#define EMAC0_DMA_RXBUF_CUR 0xFFC21054 /* EMAC0 RX current buffer pointer register */
+#define EMAC0_HWFEAT 0xFFC21058 /* EMAC0 Hardware Feature Register */
+
+/* =========================
+ EMAC1
+ ========================= */
+#define EMAC1_MACCFG 0xFFC22000 /* EMAC1 MAC Configuration Register */
+#define EMAC1_MACFRMFILT 0xFFC22004 /* EMAC1 Filter Register for filtering Received Frames */
+#define EMAC1_HASHTBL_HI 0xFFC22008 /* EMAC1 Contains the Upper 32 bits of the hash table */
+#define EMAC1_HASHTBL_LO 0xFFC2200C /* EMAC1 Contains the lower 32 bits of the hash table */
+#define EMAC1_GMII_ADDR 0xFFC22010 /* EMAC1 Management Address Register */
+#define EMAC1_GMII_DATA 0xFFC22014 /* EMAC1 Management Data Register */
+#define EMAC1_FLOWCTL 0xFFC22018 /* EMAC1 MAC FLow Control Register */
+#define EMAC1_VLANTAG 0xFFC2201C /* EMAC1 VLAN Tag Register */
+#define EMAC1_VER 0xFFC22020 /* EMAC1 EMAC Version Register */
+#define EMAC1_DBG 0xFFC22024 /* EMAC1 EMAC Debug Register */
+#define EMAC1_RMTWKUP 0xFFC22028 /* EMAC1 Remote wake up frame register */
+#define EMAC1_PMT_CTLSTAT 0xFFC2202C /* EMAC1 PMT Control and Status Register */
+#define EMAC1_ISTAT 0xFFC22038 /* EMAC1 EMAC Interrupt Status Register */
+#define EMAC1_IMSK 0xFFC2203C /* EMAC1 EMAC Interrupt Mask Register */
+#define EMAC1_ADDR0_HI 0xFFC22040 /* EMAC1 EMAC Address0 High Register */
+#define EMAC1_ADDR0_LO 0xFFC22044 /* EMAC1 EMAC Address0 Low Register */
+#define EMAC1_MMC_CTL 0xFFC22100 /* EMAC1 MMC Control Register */
+#define EMAC1_MMC_RXINT 0xFFC22104 /* EMAC1 MMC RX Interrupt Register */
+#define EMAC1_MMC_TXINT 0xFFC22108 /* EMAC1 MMC TX Interrupt Register */
+#define EMAC1_MMC_RXIMSK 0xFFC2210C /* EMAC1 MMC RX Interrupt Mask Register */
+#define EMAC1_MMC_TXIMSK 0xFFC22110 /* EMAC1 MMC TX Interrupt Mask Register */
+#define EMAC1_TXOCTCNT_GB 0xFFC22114 /* EMAC1 Num bytes transmitted exclusive of preamble */
+#define EMAC1_TXFRMCNT_GB 0xFFC22118 /* EMAC1 Num frames transmitted exclusive of retired */
+#define EMAC1_TXBCASTFRM_G 0xFFC2211C /* EMAC1 Number of good broadcast frames transmitted. */
+#define EMAC1_TXMCASTFRM_G 0xFFC22120 /* EMAC1 Number of good multicast frames transmitted. */
+#define EMAC1_TX64_GB 0xFFC22124 /* EMAC1 Number of 64 byte length frames */
+#define EMAC1_TX65TO127_GB 0xFFC22128 /* EMAC1 Number of frames of length b/w 65-127 (inclusive) bytes */
+#define EMAC1_TX128TO255_GB 0xFFC2212C /* EMAC1 Number of frames of length b/w 128-255 (inclusive) bytes */
+#define EMAC1_TX256TO511_GB 0xFFC22130 /* EMAC1 Number of frames of length b/w 256-511 (inclusive) bytes */
+#define EMAC1_TX512TO1023_GB 0xFFC22134 /* EMAC1 Number of frames of length b/w 512-1023 (inclusive) bytes */
+#define EMAC1_TX1024TOMAX_GB 0xFFC22138 /* EMAC1 Number of frames of length b/w 1024-max (inclusive) bytes */
+#define EMAC1_TXUCASTFRM_GB 0xFFC2213C /* EMAC1 Number of good and bad unicast frames transmitted */
+#define EMAC1_TXMCASTFRM_GB 0xFFC22140 /* EMAC1 Number of good and bad multicast frames transmitted */
+#define EMAC1_TXBCASTFRM_GB 0xFFC22144 /* EMAC1 Number of good and bad broadcast frames transmitted */
+#define EMAC1_TXUNDR_ERR 0xFFC22148 /* EMAC1 Number of frames aborted due to frame underflow error */
+#define EMAC1_TXSNGCOL_G 0xFFC2214C /* EMAC1 Number of transmitted frames after single collision */
+#define EMAC1_TXMULTCOL_G 0xFFC22150 /* EMAC1 Number of transmitted frames with more than one collision */
+#define EMAC1_TXDEFERRED 0xFFC22154 /* EMAC1 Number of transmitted frames after deferral */
+#define EMAC1_TXLATECOL 0xFFC22158 /* EMAC1 Number of frames aborted due to late collision error */
+#define EMAC1_TXEXCESSCOL 0xFFC2215C /* EMAC1 Number of aborted frames due to excessive collisions */
+#define EMAC1_TXCARR_ERR 0xFFC22160 /* EMAC1 Number of aborted frames due to carrier sense error */
+#define EMAC1_TXOCTCNT_G 0xFFC22164 /* EMAC1 Number of bytes transmitted in good frames only */
+#define EMAC1_TXFRMCNT_G 0xFFC22168 /* EMAC1 Number of good frames transmitted. */
+#define EMAC1_TXEXCESSDEF 0xFFC2216C /* EMAC1 Number of frames aborted due to excessive deferral */
+#define EMAC1_TXPAUSEFRM 0xFFC22170 /* EMAC1 Number of good PAUSE frames transmitted. */
+#define EMAC1_TXVLANFRM_G 0xFFC22174 /* EMAC1 Number of VLAN frames transmitted */
+#define EMAC1_RXFRMCNT_GB 0xFFC22180 /* EMAC1 Number of good and bad frames received. */
+#define EMAC1_RXOCTCNT_GB 0xFFC22184 /* EMAC1 Number of bytes received in good and bad frames */
+#define EMAC1_RXOCTCNT_G 0xFFC22188 /* EMAC1 Number of bytes received only in good frames */
+#define EMAC1_RXBCASTFRM_G 0xFFC2218C /* EMAC1 Number of good broadcast frames received. */
+#define EMAC1_RXMCASTFRM_G 0xFFC22190 /* EMAC1 Number of good multicast frames received */
+#define EMAC1_RXCRC_ERR 0xFFC22194 /* EMAC1 Number of frames received with CRC error */
+#define EMAC1_RXALIGN_ERR 0xFFC22198 /* EMAC1 Number of frames with alignment error */
+#define EMAC1_RXRUNT_ERR 0xFFC2219C /* EMAC1 Number of frames received with runt error. */
+#define EMAC1_RXJAB_ERR 0xFFC221A0 /* EMAC1 Number of frames received with length greater than 1518 */
+#define EMAC1_RXUSIZE_G 0xFFC221A4 /* EMAC1 Number of frames received with length 64 */
+#define EMAC1_RXOSIZE_G 0xFFC221A8 /* EMAC1 Number of frames received with length greater than maxium */
+#define EMAC1_RX64_GB 0xFFC221AC /* EMAC1 Number of good and bad frames of lengh 64 bytes */
+#define EMAC1_RX65TO127_GB 0xFFC221B0 /* EMAC1 Number of good and bad frame between 64-127(inclusive) */
+#define EMAC1_RX128TO255_GB 0xFFC221B4 /* EMAC1 Number of good and bad frames received with length between 128 and 255 (inclusive) bytes, exclusive of preamble. */
+#define EMAC1_RX256TO511_GB 0xFFC221B8 /* EMAC1 Number of good and bad frames between 256-511(inclusive) */
+#define EMAC1_RX512TO1023_GB 0xFFC221BC /* EMAC1 Number of good and bad frames received between 512-1023 */
+#define EMAC1_RX1024TOMAX_GB 0xFFC221C0 /* EMAC1 Number of frames received between 1024 and maxsize */
+#define EMAC1_RXUCASTFRM_G 0xFFC221C4 /* EMAC1 Number of good unicast frames received. */
+#define EMAC1_RXLEN_ERR 0xFFC221C8 /* EMAC1 Number of frames received with length error */
+#define EMAC1_RXOORTYPE 0xFFC221CC /* EMAC1 Number of frames with length not equal to valid frame size */
+#define EMAC1_RXPAUSEFRM 0xFFC221D0 /* EMAC1 Number of good and valid PAUSE frames received. */
+#define EMAC1_RXFIFO_OVF 0xFFC221D4 /* EMAC1 Number of missed received frames due to FIFO overflow. This counter is not present in the GMAC-CORE configuration. */
+#define EMAC1_RXVLANFRM_GB 0xFFC221D8 /* EMAC1 Number of good and bad VLAN frames received. */
+#define EMAC1_RXWDOG_ERR 0xFFC221DC /* EMAC1 Frames received with error due to watchdog timeout */
+#define EMAC1_IPC_RXIMSK 0xFFC22200 /* EMAC1 MMC IPC RX Interrupt Mask Register */
+#define EMAC1_IPC_RXINT 0xFFC22208 /* EMAC1 MMC IPC RX Interrupt Register */
+#define EMAC1_RXIPV4_GD_FRM 0xFFC22210 /* EMAC1 Number of good IPv4 datagrams */
+#define EMAC1_RXIPV4_HDR_ERR_FRM 0xFFC22214 /* EMAC1 Number of IPv4 datagrams with header errors */
+#define EMAC1_RXIPV4_NOPAY_FRM 0xFFC22218 /* EMAC1 Number of IPv4 datagrams without checksum */
+#define EMAC1_RXIPV4_FRAG_FRM 0xFFC2221C /* EMAC1 Number of good IPv4 datagrams with fragmentation */
+#define EMAC1_RXIPV4_UDSBL_FRM 0xFFC22220 /* EMAC1 Number of IPv4 UDP datagrams with disabled checksum */
+#define EMAC1_RXIPV6_GD_FRM 0xFFC22224 /* EMAC1 Number of IPv4 datagrams with TCP/UDP/ICMP payloads */
+#define EMAC1_RXIPV6_HDR_ERR_FRM 0xFFC22228 /* EMAC1 Number of IPv6 datagrams with header errors */
+#define EMAC1_RXIPV6_NOPAY_FRM 0xFFC2222C /* EMAC1 Number of IPv6 datagrams with no TCP/UDP/ICMP payload */
+#define EMAC1_RXUDP_GD_FRM 0xFFC22230 /* EMAC1 Number of good IP datagrames with good UDP payload */
+#define EMAC1_RXUDP_ERR_FRM 0xFFC22234 /* EMAC1 Number of good IP datagrams with UDP checksum errors */
+#define EMAC1_RXTCP_GD_FRM 0xFFC22238 /* EMAC1 Number of good IP datagrams with a good TCP payload */
+#define EMAC1_RXTCP_ERR_FRM 0xFFC2223C /* EMAC1 Number of good IP datagrams with TCP checksum errors */
+#define EMAC1_RXICMP_GD_FRM 0xFFC22240 /* EMAC1 Number of good IP datagrams with a good ICMP payload */
+#define EMAC1_RXICMP_ERR_FRM 0xFFC22244 /* EMAC1 Number of good IP datagrams with ICMP checksum errors */
+#define EMAC1_RXIPV4_GD_OCT 0xFFC22250 /* EMAC1 Bytes received in IPv4 datagrams including tcp,udp or icmp */
+#define EMAC1_RXIPV4_HDR_ERR_OCT 0xFFC22254 /* EMAC1 Bytes received in IPv4 datagrams with header errors */
+#define EMAC1_RXIPV4_NOPAY_OCT 0xFFC22258 /* EMAC1 Bytes received in IPv4 datagrams without tcp,udp,icmp load */
+#define EMAC1_RXIPV4_FRAG_OCT 0xFFC2225C /* EMAC1 Bytes received in fragmented IPv4 datagrams */
+#define EMAC1_RXIPV4_UDSBL_OCT 0xFFC22260 /* EMAC1 Bytes received in UDP segment with checksum disabled */
+#define EMAC1_RXIPV6_GD_OCT 0xFFC22264 /* EMAC1 Bytes received in good IPv6 including tcp,udp or icmp load */
+#define EMAC1_RXIPV6_HDR_ERR_OCT 0xFFC22268 /* EMAC1 Number of bytes received in IPv6 with header errors */
+#define EMAC1_RXIPV6_NOPAY_OCT 0xFFC2226C /* EMAC1 Bytes received in IPv6 without tcp,udp or icmp load */
+#define EMAC1_RXUDP_GD_OCT 0xFFC22270 /* EMAC1 Number of bytes received in good UDP segments */
+#define EMAC1_RXUDP_ERR_OCT 0xFFC22274 /* EMAC1 Number of bytes received in UDP segment with checksum err */
+#define EMAC1_RXTCP_GD_OCT 0xFFC22278 /* EMAC1 Number of bytes received in a good TCP segment */
+#define EMAC1_RXTCP_ERR_OCT 0xFFC2227C /* EMAC1 Number of bytes received in TCP segment with checksum err */
+#define EMAC1_RXICMP_GD_OCT 0xFFC22280 /* EMAC1 Number of bytes received in a good ICMP segment */
+#define EMAC1_RXICMP_ERR_OCT 0xFFC22284 /* EMAC1 Bytes received in an ICMP segment with checksum errors */
+#define EMAC1_TM_CTL 0xFFC22700 /* EMAC1 EMAC Time Stamp Control Register */
+#define EMAC1_TM_SUBSEC 0xFFC22704 /* EMAC1 EMAC Time Stamp Sub Second Increment */
+#define EMAC1_TM_SEC 0xFFC22708 /* EMAC1 EMAC Time Stamp Second Register */
+#define EMAC1_TM_NSEC 0xFFC2270C /* EMAC1 EMAC Time Stamp Nano Second Register */
+#define EMAC1_TM_SECUPDT 0xFFC22710 /* EMAC1 EMAC Time Stamp Seconds Update */
+#define EMAC1_TM_NSECUPDT 0xFFC22714 /* EMAC1 EMAC Time Stamp Nano Seconds Update */
+#define EMAC1_TM_ADDEND 0xFFC22718 /* EMAC1 EMAC Time Stamp Addend Register */
+#define EMAC1_TM_TGTM 0xFFC2271C /* EMAC1 EMAC Time Stamp Target Time Sec. */
+#define EMAC1_TM_NTGTM 0xFFC22720 /* EMAC1 EMAC Time Stamp Target Time Nanosec. */
+#define EMAC1_TM_HISEC 0xFFC22724 /* EMAC1 EMAC Time Stamp High Second Register */
+#define EMAC1_TM_STMPSTAT 0xFFC22728 /* EMAC1 EMAC Time Stamp Status Register */
+#define EMAC1_TM_PPSCTL 0xFFC2272C /* EMAC1 EMAC PPS Control Register */
+#define EMAC1_TM_AUXSTMP_NSEC 0xFFC22730 /* EMAC1 EMAC Auxillary Time Stamp Nano Register */
+#define EMAC1_TM_AUXSTMP_SEC 0xFFC22734 /* EMAC1 EMAC Auxillary Time Stamp Sec Register */
+#define EMAC1_DMA_BUSMODE 0xFFC23000 /* EMAC1 Bus Operating Modes for EMAC DMA */
+#define EMAC1_DMA_TXPOLL 0xFFC23004 /* EMAC1 TX DMA Poll demand register */
+#define EMAC1_DMA_RXPOLL 0xFFC23008 /* EMAC1 RX DMA Poll demand register */
+#define EMAC1_DMA_RXDSC_ADDR 0xFFC2300C /* EMAC1 RX Descriptor List Address */
+#define EMAC1_DMA_TXDSC_ADDR 0xFFC23010 /* EMAC1 TX Descriptor List Address */
+#define EMAC1_DMA_STAT 0xFFC23014 /* EMAC1 DMA Status Register */
+#define EMAC1_DMA_OPMODE 0xFFC23018 /* EMAC1 DMA Operation Mode Register */
+#define EMAC1_DMA_IEN 0xFFC2301C /* EMAC1 DMA Interrupt Enable Register */
+#define EMAC1_DMA_MISS_FRM 0xFFC23020 /* EMAC1 DMA missed frame and buffer overflow counter */
+#define EMAC1_DMA_RXIWDOG 0xFFC23024 /* EMAC1 DMA RX Interrupt Watch Dog timer */
+#define EMAC1_DMA_BMMODE 0xFFC23028 /* EMAC1 AXI Bus Mode Register */
+#define EMAC1_DMA_BMSTAT 0xFFC2302C /* EMAC1 AXI Status Register */
+#define EMAC1_DMA_TXDSC_CUR 0xFFC23048 /* EMAC1 TX current descriptor register */
+#define EMAC1_DMA_RXDSC_CUR 0xFFC2304C /* EMAC1 RX current descriptor register */
+#define EMAC1_DMA_TXBUF_CUR 0xFFC23050 /* EMAC1 TX current buffer pointer register */
+#define EMAC1_DMA_RXBUF_CUR 0xFFC23054 /* EMAC1 RX current buffer pointer register */
+#define EMAC1_HWFEAT 0xFFC23058 /* EMAC1 Hardware Feature Register */
+
+
+/* =========================
+ SPI Registers
+ ========================= */
+
+/* =========================
+ SPI0
+ ========================= */
+#define SPI0_REGBASE 0xFFC40400
+#define SPI0_CTL 0xFFC40404 /* SPI0 Control Register */
+#define SPI0_RXCTL 0xFFC40408 /* SPI0 RX Control Register */
+#define SPI0_TXCTL 0xFFC4040C /* SPI0 TX Control Register */
+#define SPI0_CLK 0xFFC40410 /* SPI0 Clock Rate Register */
+#define SPI0_DLY 0xFFC40414 /* SPI0 Delay Register */
+#define SPI0_SLVSEL 0xFFC40418 /* SPI0 Slave Select Register */
+#define SPI0_RWC 0xFFC4041C /* SPI0 Received Word-Count Register */
+#define SPI0_RWCR 0xFFC40420 /* SPI0 Received Word-Count Reload Register */
+#define SPI0_TWC 0xFFC40424 /* SPI0 Transmitted Word-Count Register */
+#define SPI0_TWCR 0xFFC40428 /* SPI0 Transmitted Word-Count Reload Register */
+#define SPI0_IMSK 0xFFC40430 /* SPI0 Interrupt Mask Register */
+#define SPI0_IMSK_CLR 0xFFC40434 /* SPI0 Interrupt Mask Clear Register */
+#define SPI0_IMSK_SET 0xFFC40438 /* SPI0 Interrupt Mask Set Register */
+#define SPI0_STAT 0xFFC40440 /* SPI0 Status Register */
+#define SPI0_ILAT 0xFFC40444 /* SPI0 Masked Interrupt Condition Register */
+#define SPI0_ILAT_CLR 0xFFC40448 /* SPI0 Masked Interrupt Clear Register */
+#define SPI0_RFIFO 0xFFC40450 /* SPI0 Receive FIFO Data Register */
+#define SPI0_TFIFO 0xFFC40458 /* SPI0 Transmit FIFO Data Register */
+
+/* =========================
+ SPI1
+ ========================= */
+#define SPI1_REGBASE 0xFFC40500
+#define SPI1_CTL 0xFFC40504 /* SPI1 Control Register */
+#define SPI1_RXCTL 0xFFC40508 /* SPI1 RX Control Register */
+#define SPI1_TXCTL 0xFFC4050C /* SPI1 TX Control Register */
+#define SPI1_CLK 0xFFC40510 /* SPI1 Clock Rate Register */
+#define SPI1_DLY 0xFFC40514 /* SPI1 Delay Register */
+#define SPI1_SLVSEL 0xFFC40518 /* SPI1 Slave Select Register */
+#define SPI1_RWC 0xFFC4051C /* SPI1 Received Word-Count Register */
+#define SPI1_RWCR 0xFFC40520 /* SPI1 Received Word-Count Reload Register */
+#define SPI1_TWC 0xFFC40524 /* SPI1 Transmitted Word-Count Register */
+#define SPI1_TWCR 0xFFC40528 /* SPI1 Transmitted Word-Count Reload Register */
+#define SPI1_IMSK 0xFFC40530 /* SPI1 Interrupt Mask Register */
+#define SPI1_IMSK_CLR 0xFFC40534 /* SPI1 Interrupt Mask Clear Register */
+#define SPI1_IMSK_SET 0xFFC40538 /* SPI1 Interrupt Mask Set Register */
+#define SPI1_STAT 0xFFC40540 /* SPI1 Status Register */
+#define SPI1_ILAT 0xFFC40544 /* SPI1 Masked Interrupt Condition Register */
+#define SPI1_ILAT_CLR 0xFFC40548 /* SPI1 Masked Interrupt Clear Register */
+#define SPI1_RFIFO 0xFFC40550 /* SPI1 Receive FIFO Data Register */
+#define SPI1_TFIFO 0xFFC40558 /* SPI1 Transmit FIFO Data Register */
+
+/* =========================
+ SPORT Registers
+ ========================= */
+
+/* =========================
+ SPORT0
+ ========================= */
+#define SPORT0_CTL_A 0xFFC40000 /* SPORT0 'A' Control Register */
+#define SPORT0_DIV_A 0xFFC40004 /* SPORT0 'A' Clock and FS Divide Register */
+#define SPORT0_MCTL_A 0xFFC40008 /* SPORT0 'A' Multichannel Control Register */
+#define SPORT0_CS0_A 0xFFC4000C /* SPORT0 'A' Multichannel Select Register (Channels 0-31) */
+#define SPORT0_CS1_A 0xFFC40010 /* SPORT0 'A' Multichannel Select Register (Channels 32-63) */
+#define SPORT0_CS2_A 0xFFC40014 /* SPORT0 'A' Multichannel Select Register (Channels 64-95) */
+#define SPORT0_CS3_A 0xFFC40018 /* SPORT0 'A' Multichannel Select Register (Channels 96-127) */
+#define SPORT0_CNT_A 0xFFC4001C /* SPORT0 'A' Frame Sync And Clock Divisor Current Count */
+#define SPORT0_ERR_A 0xFFC40020 /* SPORT0 'A' Error Register */
+#define SPORT0_MSTAT_A 0xFFC40024 /* SPORT0 'A' Multichannel Mode Status Register */
+#define SPORT0_CTL2_A 0xFFC40028 /* SPORT0 'A' Control Register 2 */
+#define SPORT0_TXPRI_A 0xFFC40040 /* SPORT0 'A' Primary Channel Transmit Buffer Register */
+#define SPORT0_RXPRI_A 0xFFC40044 /* SPORT0 'A' Primary Channel Receive Buffer Register */
+#define SPORT0_TXSEC_A 0xFFC40048 /* SPORT0 'A' Secondary Channel Transmit Buffer Register */
+#define SPORT0_RXSEC_A 0xFFC4004C /* SPORT0 'A' Secondary Channel Receive Buffer Register */
+#define SPORT0_CTL_B 0xFFC40080 /* SPORT0 'B' Control Register */
+#define SPORT0_DIV_B 0xFFC40084 /* SPORT0 'B' Clock and FS Divide Register */
+#define SPORT0_MCTL_B 0xFFC40088 /* SPORT0 'B' Multichannel Control Register */
+#define SPORT0_CS0_B 0xFFC4008C /* SPORT0 'B' Multichannel Select Register (Channels 0-31) */
+#define SPORT0_CS1_B 0xFFC40090 /* SPORT0 'B' Multichannel Select Register (Channels 32-63) */
+#define SPORT0_CS2_B 0xFFC40094 /* SPORT0 'B' Multichannel Select Register (Channels 64-95) */
+#define SPORT0_CS3_B 0xFFC40098 /* SPORT0 'B' Multichannel Select Register (Channels 96-127) */
+#define SPORT0_CNT_B 0xFFC4009C /* SPORT0 'B' Frame Sync And Clock Divisor Current Count */
+#define SPORT0_ERR_B 0xFFC400A0 /* SPORT0 'B' Error Register */
+#define SPORT0_MSTAT_B 0xFFC400A4 /* SPORT0 'B' Multichannel Mode Status Register */
+#define SPORT0_CTL2_B 0xFFC400A8 /* SPORT0 'B' Control Register 2 */
+#define SPORT0_TXPRI_B 0xFFC400C0 /* SPORT0 'B' Primary Channel Transmit Buffer Register */
+#define SPORT0_RXPRI_B 0xFFC400C4 /* SPORT0 'B' Primary Channel Receive Buffer Register */
+#define SPORT0_TXSEC_B 0xFFC400C8 /* SPORT0 'B' Secondary Channel Transmit Buffer Register */
+#define SPORT0_RXSEC_B 0xFFC400CC /* SPORT0 'B' Secondary Channel Receive Buffer Register */
+
+/* =========================
+ SPORT1
+ ========================= */
+#define SPORT1_CTL_A 0xFFC40100 /* SPORT1 'A' Control Register */
+#define SPORT1_DIV_A 0xFFC40104 /* SPORT1 'A' Clock and FS Divide Register */
+#define SPORT1_MCTL_A 0xFFC40108 /* SPORT1 'A' Multichannel Control Register */
+#define SPORT1_CS0_A 0xFFC4010C /* SPORT1 'A' Multichannel Select Register (Channels 0-31) */
+#define SPORT1_CS1_A 0xFFC40110 /* SPORT1 'A' Multichannel Select Register (Channels 32-63) */
+#define SPORT1_CS2_A 0xFFC40114 /* SPORT1 'A' Multichannel Select Register (Channels 64-95) */
+#define SPORT1_CS3_A 0xFFC40118 /* SPORT1 'A' Multichannel Select Register (Channels 96-127) */
+#define SPORT1_CNT_A 0xFFC4011C /* SPORT1 'A' Frame Sync And Clock Divisor Current Count */
+#define SPORT1_ERR_A 0xFFC40120 /* SPORT1 'A' Error Register */
+#define SPORT1_MSTAT_A 0xFFC40124 /* SPORT1 'A' Multichannel Mode Status Register */
+#define SPORT1_CTL2_A 0xFFC40128 /* SPORT1 'A' Control Register 2 */
+#define SPORT1_TXPRI_A 0xFFC40140 /* SPORT1 'A' Primary Channel Transmit Buffer Register */
+#define SPORT1_RXPRI_A 0xFFC40144 /* SPORT1 'A' Primary Channel Receive Buffer Register */
+#define SPORT1_TXSEC_A 0xFFC40148 /* SPORT1 'A' Secondary Channel Transmit Buffer Register */
+#define SPORT1_RXSEC_A 0xFFC4014C /* SPORT1 'A' Secondary Channel Receive Buffer Register */
+#define SPORT1_CTL_B 0xFFC40180 /* SPORT1 'B' Control Register */
+#define SPORT1_DIV_B 0xFFC40184 /* SPORT1 'B' Clock and FS Divide Register */
+#define SPORT1_MCTL_B 0xFFC40188 /* SPORT1 'B' Multichannel Control Register */
+#define SPORT1_CS0_B 0xFFC4018C /* SPORT1 'B' Multichannel Select Register (Channels 0-31) */
+#define SPORT1_CS1_B 0xFFC40190 /* SPORT1 'B' Multichannel Select Register (Channels 32-63) */
+#define SPORT1_CS2_B 0xFFC40194 /* SPORT1 'B' Multichannel Select Register (Channels 64-95) */
+#define SPORT1_CS3_B 0xFFC40198 /* SPORT1 'B' Multichannel Select Register (Channels 96-127) */
+#define SPORT1_CNT_B 0xFFC4019C /* SPORT1 'B' Frame Sync And Clock Divisor Current Count */
+#define SPORT1_ERR_B 0xFFC401A0 /* SPORT1 'B' Error Register */
+#define SPORT1_MSTAT_B 0xFFC401A4 /* SPORT1 'B' Multichannel Mode Status Register */
+#define SPORT1_CTL2_B 0xFFC401A8 /* SPORT1 'B' Control Register 2 */
+#define SPORT1_TXPRI_B 0xFFC401C0 /* SPORT1 'B' Primary Channel Transmit Buffer Register */
+#define SPORT1_RXPRI_B 0xFFC401C4 /* SPORT1 'B' Primary Channel Receive Buffer Register */
+#define SPORT1_TXSEC_B 0xFFC401C8 /* SPORT1 'B' Secondary Channel Transmit Buffer Register */
+#define SPORT1_RXSEC_B 0xFFC401CC /* SPORT1 'B' Secondary Channel Receive Buffer Register */
+
+/* =========================
+ SPORT2
+ ========================= */
+#define SPORT2_CTL_A 0xFFC40200 /* SPORT2 'A' Control Register */
+#define SPORT2_DIV_A 0xFFC40204 /* SPORT2 'A' Clock and FS Divide Register */
+#define SPORT2_MCTL_A 0xFFC40208 /* SPORT2 'A' Multichannel Control Register */
+#define SPORT2_CS0_A 0xFFC4020C /* SPORT2 'A' Multichannel Select Register (Channels 0-31) */
+#define SPORT2_CS1_A 0xFFC40210 /* SPORT2 'A' Multichannel Select Register (Channels 32-63) */
+#define SPORT2_CS2_A 0xFFC40214 /* SPORT2 'A' Multichannel Select Register (Channels 64-95) */
+#define SPORT2_CS3_A 0xFFC40218 /* SPORT2 'A' Multichannel Select Register (Channels 96-127) */
+#define SPORT2_CNT_A 0xFFC4021C /* SPORT2 'A' Frame Sync And Clock Divisor Current Count */
+#define SPORT2_ERR_A 0xFFC40220 /* SPORT2 'A' Error Register */
+#define SPORT2_MSTAT_A 0xFFC40224 /* SPORT2 'A' Multichannel Mode Status Register */
+#define SPORT2_CTL2_A 0xFFC40228 /* SPORT2 'A' Control Register 2 */
+#define SPORT2_TXPRI_A 0xFFC40240 /* SPORT2 'A' Primary Channel Transmit Buffer Register */
+#define SPORT2_RXPRI_A 0xFFC40244 /* SPORT2 'A' Primary Channel Receive Buffer Register */
+#define SPORT2_TXSEC_A 0xFFC40248 /* SPORT2 'A' Secondary Channel Transmit Buffer Register */
+#define SPORT2_RXSEC_A 0xFFC4024C /* SPORT2 'A' Secondary Channel Receive Buffer Register */
+#define SPORT2_CTL_B 0xFFC40280 /* SPORT2 'B' Control Register */
+#define SPORT2_DIV_B 0xFFC40284 /* SPORT2 'B' Clock and FS Divide Register */
+#define SPORT2_MCTL_B 0xFFC40288 /* SPORT2 'B' Multichannel Control Register */
+#define SPORT2_CS0_B 0xFFC4028C /* SPORT2 'B' Multichannel Select Register (Channels 0-31) */
+#define SPORT2_CS1_B 0xFFC40290 /* SPORT2 'B' Multichannel Select Register (Channels 32-63) */
+#define SPORT2_CS2_B 0xFFC40294 /* SPORT2 'B' Multichannel Select Register (Channels 64-95) */
+#define SPORT2_CS3_B 0xFFC40298 /* SPORT2 'B' Multichannel Select Register (Channels 96-127) */
+#define SPORT2_CNT_B 0xFFC4029C /* SPORT2 'B' Frame Sync And Clock Divisor Current Count */
+#define SPORT2_ERR_B 0xFFC402A0 /* SPORT2 'B' Error Register */
+#define SPORT2_MSTAT_B 0xFFC402A4 /* SPORT2 'B' Multichannel Mode Status Register */
+#define SPORT2_CTL2_B 0xFFC402A8 /* SPORT2 'B' Control Register 2 */
+#define SPORT2_TXPRI_B 0xFFC402C0 /* SPORT2 'B' Primary Channel Transmit Buffer Register */
+#define SPORT2_RXPRI_B 0xFFC402C4 /* SPORT2 'B' Primary Channel Receive Buffer Register */
+#define SPORT2_TXSEC_B 0xFFC402C8 /* SPORT2 'B' Secondary Channel Transmit Buffer Register */
+#define SPORT2_RXSEC_B 0xFFC402CC /* SPORT2 'B' Secondary Channel Receive Buffer Register */
+
+/* =========================
+ EPPI Registers
+ ========================= */
+
+/* =========================
+ EPPI0
+ ========================= */
+#define EPPI0_STAT 0xFFC18000 /* EPPI0 Status Register */
+#define EPPI0_HCNT 0xFFC18004 /* EPPI0 Horizontal Transfer Count Register */
+#define EPPI0_HDLY 0xFFC18008 /* EPPI0 Horizontal Delay Count Register */
+#define EPPI0_VCNT 0xFFC1800C /* EPPI0 Vertical Transfer Count Register */
+#define EPPI0_VDLY 0xFFC18010 /* EPPI0 Vertical Delay Count Register */
+#define EPPI0_FRAME 0xFFC18014 /* EPPI0 Lines Per Frame Register */
+#define EPPI0_LINE 0xFFC18018 /* EPPI0 Samples Per Line Register */
+#define EPPI0_CLKDIV 0xFFC1801C /* EPPI0 Clock Divide Register */
+#define EPPI0_CTL 0xFFC18020 /* EPPI0 Control Register */
+#define EPPI0_FS1_WLHB 0xFFC18024 /* EPPI0 FS1 Width Register / EPPI Horizontal Blanking Samples Per Line Register */
+#define EPPI0_FS1_PASPL 0xFFC18028 /* EPPI0 FS1 Period Register / EPPI Active Samples Per Line Register */
+#define EPPI0_FS2_WLVB 0xFFC1802C /* EPPI0 FS2 Width Register / EPPI Lines Of Vertical Blanking Register */
+#define EPPI0_FS2_PALPF 0xFFC18030 /* EPPI0 FS2 Period Register / EPPI Active Lines Per Field Register */
+#define EPPI0_IMSK 0xFFC18034 /* EPPI0 Interrupt Mask Register */
+#define EPPI0_ODDCLIP 0xFFC1803C /* EPPI0 Clipping Register for ODD (Chroma) Data */
+#define EPPI0_EVENCLIP 0xFFC18040 /* EPPI0 Clipping Register for EVEN (Luma) Data */
+#define EPPI0_FS1_DLY 0xFFC18044 /* EPPI0 Frame Sync 1 Delay Value */
+#define EPPI0_FS2_DLY 0xFFC18048 /* EPPI0 Frame Sync 2 Delay Value */
+#define EPPI0_CTL2 0xFFC1804C /* EPPI0 Control Register 2 */
+
+/* =========================
+ EPPI1
+ ========================= */
+#define EPPI1_STAT 0xFFC18400 /* EPPI1 Status Register */
+#define EPPI1_HCNT 0xFFC18404 /* EPPI1 Horizontal Transfer Count Register */
+#define EPPI1_HDLY 0xFFC18408 /* EPPI1 Horizontal Delay Count Register */
+#define EPPI1_VCNT 0xFFC1840C /* EPPI1 Vertical Transfer Count Register */
+#define EPPI1_VDLY 0xFFC18410 /* EPPI1 Vertical Delay Count Register */
+#define EPPI1_FRAME 0xFFC18414 /* EPPI1 Lines Per Frame Register */
+#define EPPI1_LINE 0xFFC18418 /* EPPI1 Samples Per Line Register */
+#define EPPI1_CLKDIV 0xFFC1841C /* EPPI1 Clock Divide Register */
+#define EPPI1_CTL 0xFFC18420 /* EPPI1 Control Register */
+#define EPPI1_FS1_WLHB 0xFFC18424 /* EPPI1 FS1 Width Register / EPPI Horizontal Blanking Samples Per Line Register */
+#define EPPI1_FS1_PASPL 0xFFC18428 /* EPPI1 FS1 Period Register / EPPI Active Samples Per Line Register */
+#define EPPI1_FS2_WLVB 0xFFC1842C /* EPPI1 FS2 Width Register / EPPI Lines Of Vertical Blanking Register */
+#define EPPI1_FS2_PALPF 0xFFC18430 /* EPPI1 FS2 Period Register / EPPI Active Lines Per Field Register */
+#define EPPI1_IMSK 0xFFC18434 /* EPPI1 Interrupt Mask Register */
+#define EPPI1_ODDCLIP 0xFFC1843C /* EPPI1 Clipping Register for ODD (Chroma) Data */
+#define EPPI1_EVENCLIP 0xFFC18440 /* EPPI1 Clipping Register for EVEN (Luma) Data */
+#define EPPI1_FS1_DLY 0xFFC18444 /* EPPI1 Frame Sync 1 Delay Value */
+#define EPPI1_FS2_DLY 0xFFC18448 /* EPPI1 Frame Sync 2 Delay Value */
+#define EPPI1_CTL2 0xFFC1844C /* EPPI1 Control Register 2 */
+
+/* =========================
+ EPPI2
+ ========================= */
+#define EPPI2_STAT 0xFFC18800 /* EPPI2 Status Register */
+#define EPPI2_HCNT 0xFFC18804 /* EPPI2 Horizontal Transfer Count Register */
+#define EPPI2_HDLY 0xFFC18808 /* EPPI2 Horizontal Delay Count Register */
+#define EPPI2_VCNT 0xFFC1880C /* EPPI2 Vertical Transfer Count Register */
+#define EPPI2_VDLY 0xFFC18810 /* EPPI2 Vertical Delay Count Register */
+#define EPPI2_FRAME 0xFFC18814 /* EPPI2 Lines Per Frame Register */
+#define EPPI2_LINE 0xFFC18818 /* EPPI2 Samples Per Line Register */
+#define EPPI2_CLKDIV 0xFFC1881C /* EPPI2 Clock Divide Register */
+#define EPPI2_CTL 0xFFC18820 /* EPPI2 Control Register */
+#define EPPI2_FS1_WLHB 0xFFC18824 /* EPPI2 FS1 Width Register / EPPI Horizontal Blanking Samples Per Line Register */
+#define EPPI2_FS1_PASPL 0xFFC18828 /* EPPI2 FS1 Period Register / EPPI Active Samples Per Line Register */
+#define EPPI2_FS2_WLVB 0xFFC1882C /* EPPI2 FS2 Width Register / EPPI Lines Of Vertical Blanking Register */
+#define EPPI2_FS2_PALPF 0xFFC18830 /* EPPI2 FS2 Period Register / EPPI Active Lines Per Field Register */
+#define EPPI2_IMSK 0xFFC18834 /* EPPI2 Interrupt Mask Register */
+#define EPPI2_ODDCLIP 0xFFC1883C /* EPPI2 Clipping Register for ODD (Chroma) Data */
+#define EPPI2_EVENCLIP 0xFFC18840 /* EPPI2 Clipping Register for EVEN (Luma) Data */
+#define EPPI2_FS1_DLY 0xFFC18844 /* EPPI2 Frame Sync 1 Delay Value */
+#define EPPI2_FS2_DLY 0xFFC18848 /* EPPI2 Frame Sync 2 Delay Value */
+#define EPPI2_CTL2 0xFFC1884C /* EPPI2 Control Register 2 */
+
+
+
+/* =========================
+ DDE Registers
+ ========================= */
+
+/* =========================
+ DMA0
+ ========================= */
+#define DMA0_NEXT_DESC_PTR 0xFFC41000 /* DMA0 Pointer to Next Initial Descriptor */
+#define DMA0_START_ADDR 0xFFC41004 /* DMA0 Start Address of Current Buffer */
+#define DMA0_CONFIG 0xFFC41008 /* DMA0 Configuration Register */
+#define DMA0_X_COUNT 0xFFC4100C /* DMA0 Inner Loop Count Start Value */
+#define DMA0_X_MODIFY 0xFFC41010 /* DMA0 Inner Loop Address Increment */
+#define DMA0_Y_COUNT 0xFFC41014 /* DMA0 Outer Loop Count Start Value (2D only) */
+#define DMA0_Y_MODIFY 0xFFC41018 /* DMA0 Outer Loop Address Increment (2D only) */
+#define DMA0_CURR_DESC_PTR 0xFFC41024 /* DMA0 Current Descriptor Pointer */
+#define DMA0_PREV_DESC_PTR 0xFFC41028 /* DMA0 Previous Initial Descriptor Pointer */
+#define DMA0_CURR_ADDR 0xFFC4102C /* DMA0 Current Address */
+#define DMA0_IRQ_STATUS 0xFFC41030 /* DMA0 Status Register */
+#define DMA0_CURR_X_COUNT 0xFFC41034 /* DMA0 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA0_CURR_Y_COUNT 0xFFC41038 /* DMA0 Current Row Count (2D only) */
+#define DMA0_BWL_COUNT 0xFFC41040 /* DMA0 Bandwidth Limit Count */
+#define DMA0_CURR_BWL_COUNT 0xFFC41044 /* DMA0 Bandwidth Limit Count Current */
+#define DMA0_BWM_COUNT 0xFFC41048 /* DMA0 Bandwidth Monitor Count */
+#define DMA0_CURR_BWM_COUNT 0xFFC4104C /* DMA0 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA1
+ ========================= */
+#define DMA1_NEXT_DESC_PTR 0xFFC41080 /* DMA1 Pointer to Next Initial Descriptor */
+#define DMA1_START_ADDR 0xFFC41084 /* DMA1 Start Address of Current Buffer */
+#define DMA1_CONFIG 0xFFC41088 /* DMA1 Configuration Register */
+#define DMA1_X_COUNT 0xFFC4108C /* DMA1 Inner Loop Count Start Value */
+#define DMA1_X_MODIFY 0xFFC41090 /* DMA1 Inner Loop Address Increment */
+#define DMA1_Y_COUNT 0xFFC41094 /* DMA1 Outer Loop Count Start Value (2D only) */
+#define DMA1_Y_MODIFY 0xFFC41098 /* DMA1 Outer Loop Address Increment (2D only) */
+#define DMA1_CURR_DESC_PTR 0xFFC410A4 /* DMA1 Current Descriptor Pointer */
+#define DMA1_PREV_DESC_PTR 0xFFC410A8 /* DMA1 Previous Initial Descriptor Pointer */
+#define DMA1_CURR_ADDR 0xFFC410AC /* DMA1 Current Address */
+#define DMA1_IRQ_STATUS 0xFFC410B0 /* DMA1 Status Register */
+#define DMA1_CURR_X_COUNT 0xFFC410B4 /* DMA1 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA1_CURR_Y_COUNT 0xFFC410B8 /* DMA1 Current Row Count (2D only) */
+#define DMA1_BWL_COUNT 0xFFC410C0 /* DMA1 Bandwidth Limit Count */
+#define DMA1_CURR_BWL_COUNT 0xFFC410C4 /* DMA1 Bandwidth Limit Count Current */
+#define DMA1_BWM_COUNT 0xFFC410C8 /* DMA1 Bandwidth Monitor Count */
+#define DMA1_CURR_BWM_COUNT 0xFFC410CC /* DMA1 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA2
+ ========================= */
+#define DMA2_NEXT_DESC_PTR 0xFFC41100 /* DMA2 Pointer to Next Initial Descriptor */
+#define DMA2_START_ADDR 0xFFC41104 /* DMA2 Start Address of Current Buffer */
+#define DMA2_CONFIG 0xFFC41108 /* DMA2 Configuration Register */
+#define DMA2_X_COUNT 0xFFC4110C /* DMA2 Inner Loop Count Start Value */
+#define DMA2_X_MODIFY 0xFFC41110 /* DMA2 Inner Loop Address Increment */
+#define DMA2_Y_COUNT 0xFFC41114 /* DMA2 Outer Loop Count Start Value (2D only) */
+#define DMA2_Y_MODIFY 0xFFC41118 /* DMA2 Outer Loop Address Increment (2D only) */
+#define DMA2_CURR_DESC_PTR 0xFFC41124 /* DMA2 Current Descriptor Pointer */
+#define DMA2_PREV_DESC_PTR 0xFFC41128 /* DMA2 Previous Initial Descriptor Pointer */
+#define DMA2_CURR_ADDR 0xFFC4112C /* DMA2 Current Address */
+#define DMA2_IRQ_STATUS 0xFFC41130 /* DMA2 Status Register */
+#define DMA2_CURR_X_COUNT 0xFFC41134 /* DMA2 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA2_CURR_Y_COUNT 0xFFC41138 /* DMA2 Current Row Count (2D only) */
+#define DMA2_BWL_COUNT 0xFFC41140 /* DMA2 Bandwidth Limit Count */
+#define DMA2_CURR_BWL_COUNT 0xFFC41144 /* DMA2 Bandwidth Limit Count Current */
+#define DMA2_BWM_COUNT 0xFFC41148 /* DMA2 Bandwidth Monitor Count */
+#define DMA2_CURR_BWM_COUNT 0xFFC4114C /* DMA2 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA3
+ ========================= */
+#define DMA3_NEXT_DESC_PTR 0xFFC41180 /* DMA3 Pointer to Next Initial Descriptor */
+#define DMA3_START_ADDR 0xFFC41184 /* DMA3 Start Address of Current Buffer */
+#define DMA3_CONFIG 0xFFC41188 /* DMA3 Configuration Register */
+#define DMA3_X_COUNT 0xFFC4118C /* DMA3 Inner Loop Count Start Value */
+#define DMA3_X_MODIFY 0xFFC41190 /* DMA3 Inner Loop Address Increment */
+#define DMA3_Y_COUNT 0xFFC41194 /* DMA3 Outer Loop Count Start Value (2D only) */
+#define DMA3_Y_MODIFY 0xFFC41198 /* DMA3 Outer Loop Address Increment (2D only) */
+#define DMA3_CURR_DESC_PTR 0xFFC411A4 /* DMA3 Current Descriptor Pointer */
+#define DMA3_PREV_DESC_PTR 0xFFC411A8 /* DMA3 Previous Initial Descriptor Pointer */
+#define DMA3_CURR_ADDR 0xFFC411AC /* DMA3 Current Address */
+#define DMA3_IRQ_STATUS 0xFFC411B0 /* DMA3 Status Register */
+#define DMA3_CURR_X_COUNT 0xFFC411B4 /* DMA3 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA3_CURR_Y_COUNT 0xFFC411B8 /* DMA3 Current Row Count (2D only) */
+#define DMA3_BWL_COUNT 0xFFC411C0 /* DMA3 Bandwidth Limit Count */
+#define DMA3_CURR_BWL_COUNT 0xFFC411C4 /* DMA3 Bandwidth Limit Count Current */
+#define DMA3_BWM_COUNT 0xFFC411C8 /* DMA3 Bandwidth Monitor Count */
+#define DMA3_CURR_BWM_COUNT 0xFFC411CC /* DMA3 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA4
+ ========================= */
+#define DMA4_NEXT_DESC_PTR 0xFFC41200 /* DMA4 Pointer to Next Initial Descriptor */
+#define DMA4_START_ADDR 0xFFC41204 /* DMA4 Start Address of Current Buffer */
+#define DMA4_CONFIG 0xFFC41208 /* DMA4 Configuration Register */
+#define DMA4_X_COUNT 0xFFC4120C /* DMA4 Inner Loop Count Start Value */
+#define DMA4_X_MODIFY 0xFFC41210 /* DMA4 Inner Loop Address Increment */
+#define DMA4_Y_COUNT 0xFFC41214 /* DMA4 Outer Loop Count Start Value (2D only) */
+#define DMA4_Y_MODIFY 0xFFC41218 /* DMA4 Outer Loop Address Increment (2D only) */
+#define DMA4_CURR_DESC_PTR 0xFFC41224 /* DMA4 Current Descriptor Pointer */
+#define DMA4_PREV_DESC_PTR 0xFFC41228 /* DMA4 Previous Initial Descriptor Pointer */
+#define DMA4_CURR_ADDR 0xFFC4122C /* DMA4 Current Address */
+#define DMA4_IRQ_STATUS 0xFFC41230 /* DMA4 Status Register */
+#define DMA4_CURR_X_COUNT 0xFFC41234 /* DMA4 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA4_CURR_Y_COUNT 0xFFC41238 /* DMA4 Current Row Count (2D only) */
+#define DMA4_BWL_COUNT 0xFFC41240 /* DMA4 Bandwidth Limit Count */
+#define DMA4_CURR_BWL_COUNT 0xFFC41244 /* DMA4 Bandwidth Limit Count Current */
+#define DMA4_BWM_COUNT 0xFFC41248 /* DMA4 Bandwidth Monitor Count */
+#define DMA4_CURR_BWM_COUNT 0xFFC4124C /* DMA4 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA5
+ ========================= */
+#define DMA5_NEXT_DESC_PTR 0xFFC41280 /* DMA5 Pointer to Next Initial Descriptor */
+#define DMA5_START_ADDR 0xFFC41284 /* DMA5 Start Address of Current Buffer */
+#define DMA5_CONFIG 0xFFC41288 /* DMA5 Configuration Register */
+#define DMA5_X_COUNT 0xFFC4128C /* DMA5 Inner Loop Count Start Value */
+#define DMA5_X_MODIFY 0xFFC41290 /* DMA5 Inner Loop Address Increment */
+#define DMA5_Y_COUNT 0xFFC41294 /* DMA5 Outer Loop Count Start Value (2D only) */
+#define DMA5_Y_MODIFY 0xFFC41298 /* DMA5 Outer Loop Address Increment (2D only) */
+#define DMA5_CURR_DESC_PTR 0xFFC412A4 /* DMA5 Current Descriptor Pointer */
+#define DMA5_PREV_DESC_PTR 0xFFC412A8 /* DMA5 Previous Initial Descriptor Pointer */
+#define DMA5_CURR_ADDR 0xFFC412AC /* DMA5 Current Address */
+#define DMA5_IRQ_STATUS 0xFFC412B0 /* DMA5 Status Register */
+#define DMA5_CURR_X_COUNT 0xFFC412B4 /* DMA5 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA5_CURR_Y_COUNT 0xFFC412B8 /* DMA5 Current Row Count (2D only) */
+#define DMA5_BWL_COUNT 0xFFC412C0 /* DMA5 Bandwidth Limit Count */
+#define DMA5_CURR_BWL_COUNT 0xFFC412C4 /* DMA5 Bandwidth Limit Count Current */
+#define DMA5_BWM_COUNT 0xFFC412C8 /* DMA5 Bandwidth Monitor Count */
+#define DMA5_CURR_BWM_COUNT 0xFFC412CC /* DMA5 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA6
+ ========================= */
+#define DMA6_NEXT_DESC_PTR 0xFFC41300 /* DMA6 Pointer to Next Initial Descriptor */
+#define DMA6_START_ADDR 0xFFC41304 /* DMA6 Start Address of Current Buffer */
+#define DMA6_CONFIG 0xFFC41308 /* DMA6 Configuration Register */
+#define DMA6_X_COUNT 0xFFC4130C /* DMA6 Inner Loop Count Start Value */
+#define DMA6_X_MODIFY 0xFFC41310 /* DMA6 Inner Loop Address Increment */
+#define DMA6_Y_COUNT 0xFFC41314 /* DMA6 Outer Loop Count Start Value (2D only) */
+#define DMA6_Y_MODIFY 0xFFC41318 /* DMA6 Outer Loop Address Increment (2D only) */
+#define DMA6_CURR_DESC_PTR 0xFFC41324 /* DMA6 Current Descriptor Pointer */
+#define DMA6_PREV_DESC_PTR 0xFFC41328 /* DMA6 Previous Initial Descriptor Pointer */
+#define DMA6_CURR_ADDR 0xFFC4132C /* DMA6 Current Address */
+#define DMA6_IRQ_STATUS 0xFFC41330 /* DMA6 Status Register */
+#define DMA6_CURR_X_COUNT 0xFFC41334 /* DMA6 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA6_CURR_Y_COUNT 0xFFC41338 /* DMA6 Current Row Count (2D only) */
+#define DMA6_BWL_COUNT 0xFFC41340 /* DMA6 Bandwidth Limit Count */
+#define DMA6_CURR_BWL_COUNT 0xFFC41344 /* DMA6 Bandwidth Limit Count Current */
+#define DMA6_BWM_COUNT 0xFFC41348 /* DMA6 Bandwidth Monitor Count */
+#define DMA6_CURR_BWM_COUNT 0xFFC4134C /* DMA6 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA7
+ ========================= */
+#define DMA7_NEXT_DESC_PTR 0xFFC41380 /* DMA7 Pointer to Next Initial Descriptor */
+#define DMA7_START_ADDR 0xFFC41384 /* DMA7 Start Address of Current Buffer */
+#define DMA7_CONFIG 0xFFC41388 /* DMA7 Configuration Register */
+#define DMA7_X_COUNT 0xFFC4138C /* DMA7 Inner Loop Count Start Value */
+#define DMA7_X_MODIFY 0xFFC41390 /* DMA7 Inner Loop Address Increment */
+#define DMA7_Y_COUNT 0xFFC41394 /* DMA7 Outer Loop Count Start Value (2D only) */
+#define DMA7_Y_MODIFY 0xFFC41398 /* DMA7 Outer Loop Address Increment (2D only) */
+#define DMA7_CURR_DESC_PTR 0xFFC413A4 /* DMA7 Current Descriptor Pointer */
+#define DMA7_PREV_DESC_PTR 0xFFC413A8 /* DMA7 Previous Initial Descriptor Pointer */
+#define DMA7_CURR_ADDR 0xFFC413AC /* DMA7 Current Address */
+#define DMA7_IRQ_STATUS 0xFFC413B0 /* DMA7 Status Register */
+#define DMA7_CURR_X_COUNT 0xFFC413B4 /* DMA7 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA7_CURR_Y_COUNT 0xFFC413B8 /* DMA7 Current Row Count (2D only) */
+#define DMA7_BWL_COUNT 0xFFC413C0 /* DMA7 Bandwidth Limit Count */
+#define DMA7_CURR_BWL_COUNT 0xFFC413C4 /* DMA7 Bandwidth Limit Count Current */
+#define DMA7_BWM_COUNT 0xFFC413C8 /* DMA7 Bandwidth Monitor Count */
+#define DMA7_CURR_BWM_COUNT 0xFFC413CC /* DMA7 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA8
+ ========================= */
+#define DMA8_NEXT_DESC_PTR 0xFFC41400 /* DMA8 Pointer to Next Initial Descriptor */
+#define DMA8_START_ADDR 0xFFC41404 /* DMA8 Start Address of Current Buffer */
+#define DMA8_CONFIG 0xFFC41408 /* DMA8 Configuration Register */
+#define DMA8_X_COUNT 0xFFC4140C /* DMA8 Inner Loop Count Start Value */
+#define DMA8_X_MODIFY 0xFFC41410 /* DMA8 Inner Loop Address Increment */
+#define DMA8_Y_COUNT 0xFFC41414 /* DMA8 Outer Loop Count Start Value (2D only) */
+#define DMA8_Y_MODIFY 0xFFC41418 /* DMA8 Outer Loop Address Increment (2D only) */
+#define DMA8_CURR_DESC_PTR 0xFFC41424 /* DMA8 Current Descriptor Pointer */
+#define DMA8_PREV_DESC_PTR 0xFFC41428 /* DMA8 Previous Initial Descriptor Pointer */
+#define DMA8_CURR_ADDR 0xFFC4142C /* DMA8 Current Address */
+#define DMA8_IRQ_STATUS 0xFFC41430 /* DMA8 Status Register */
+#define DMA8_CURR_X_COUNT 0xFFC41434 /* DMA8 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA8_CURR_Y_COUNT 0xFFC41438 /* DMA8 Current Row Count (2D only) */
+#define DMA8_BWL_COUNT 0xFFC41440 /* DMA8 Bandwidth Limit Count */
+#define DMA8_CURR_BWL_COUNT 0xFFC41444 /* DMA8 Bandwidth Limit Count Current */
+#define DMA8_BWM_COUNT 0xFFC41448 /* DMA8 Bandwidth Monitor Count */
+#define DMA8_CURR_BWM_COUNT 0xFFC4144C /* DMA8 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA9
+ ========================= */
+#define DMA9_NEXT_DESC_PTR 0xFFC41480 /* DMA9 Pointer to Next Initial Descriptor */
+#define DMA9_START_ADDR 0xFFC41484 /* DMA9 Start Address of Current Buffer */
+#define DMA9_CONFIG 0xFFC41488 /* DMA9 Configuration Register */
+#define DMA9_X_COUNT 0xFFC4148C /* DMA9 Inner Loop Count Start Value */
+#define DMA9_X_MODIFY 0xFFC41490 /* DMA9 Inner Loop Address Increment */
+#define DMA9_Y_COUNT 0xFFC41494 /* DMA9 Outer Loop Count Start Value (2D only) */
+#define DMA9_Y_MODIFY 0xFFC41498 /* DMA9 Outer Loop Address Increment (2D only) */
+#define DMA9_CURR_DESC_PTR 0xFFC414A4 /* DMA9 Current Descriptor Pointer */
+#define DMA9_PREV_DESC_PTR 0xFFC414A8 /* DMA9 Previous Initial Descriptor Pointer */
+#define DMA9_CURR_ADDR 0xFFC414AC /* DMA9 Current Address */
+#define DMA9_IRQ_STATUS 0xFFC414B0 /* DMA9 Status Register */
+#define DMA9_CURR_X_COUNT 0xFFC414B4 /* DMA9 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA9_CURR_Y_COUNT 0xFFC414B8 /* DMA9 Current Row Count (2D only) */
+#define DMA9_BWL_COUNT 0xFFC414C0 /* DMA9 Bandwidth Limit Count */
+#define DMA9_CURR_BWL_COUNT 0xFFC414C4 /* DMA9 Bandwidth Limit Count Current */
+#define DMA9_BWM_COUNT 0xFFC414C8 /* DMA9 Bandwidth Monitor Count */
+#define DMA9_CURR_BWM_COUNT 0xFFC414CC /* DMA9 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA10
+ ========================= */
+#define DMA10_NEXT_DESC_PTR 0xFFC05000 /* DMA10 Pointer to Next Initial Descriptor */
+#define DMA10_START_ADDR 0xFFC05004 /* DMA10 Start Address of Current Buffer */
+#define DMA10_CONFIG 0xFFC05008 /* DMA10 Configuration Register */
+#define DMA10_X_COUNT 0xFFC0500C /* DMA10 Inner Loop Count Start Value */
+#define DMA10_X_MODIFY 0xFFC05010 /* DMA10 Inner Loop Address Increment */
+#define DMA10_Y_COUNT 0xFFC05014 /* DMA10 Outer Loop Count Start Value (2D only) */
+#define DMA10_Y_MODIFY 0xFFC05018 /* DMA10 Outer Loop Address Increment (2D only) */
+#define DMA10_CURR_DESC_PTR 0xFFC05024 /* DMA10 Current Descriptor Pointer */
+#define DMA10_PREV_DESC_PTR 0xFFC05028 /* DMA10 Previous Initial Descriptor Pointer */
+#define DMA10_CURR_ADDR 0xFFC0502C /* DMA10 Current Address */
+#define DMA10_IRQ_STATUS 0xFFC05030 /* DMA10 Status Register */
+#define DMA10_CURR_X_COUNT 0xFFC05034 /* DMA10 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA10_CURR_Y_COUNT 0xFFC05038 /* DMA10 Current Row Count (2D only) */
+#define DMA10_BWL_COUNT 0xFFC05040 /* DMA10 Bandwidth Limit Count */
+#define DMA10_CURR_BWL_COUNT 0xFFC05044 /* DMA10 Bandwidth Limit Count Current */
+#define DMA10_BWM_COUNT 0xFFC05048 /* DMA10 Bandwidth Monitor Count */
+#define DMA10_CURR_BWM_COUNT 0xFFC0504C /* DMA10 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA11
+ ========================= */
+#define DMA11_NEXT_DESC_PTR 0xFFC05080 /* DMA11 Pointer to Next Initial Descriptor */
+#define DMA11_START_ADDR 0xFFC05084 /* DMA11 Start Address of Current Buffer */
+#define DMA11_CONFIG 0xFFC05088 /* DMA11 Configuration Register */
+#define DMA11_X_COUNT 0xFFC0508C /* DMA11 Inner Loop Count Start Value */
+#define DMA11_X_MODIFY 0xFFC05090 /* DMA11 Inner Loop Address Increment */
+#define DMA11_Y_COUNT 0xFFC05094 /* DMA11 Outer Loop Count Start Value (2D only) */
+#define DMA11_Y_MODIFY 0xFFC05098 /* DMA11 Outer Loop Address Increment (2D only) */
+#define DMA11_CURR_DESC_PTR 0xFFC050A4 /* DMA11 Current Descriptor Pointer */
+#define DMA11_PREV_DESC_PTR 0xFFC050A8 /* DMA11 Previous Initial Descriptor Pointer */
+#define DMA11_CURR_ADDR 0xFFC050AC /* DMA11 Current Address */
+#define DMA11_IRQ_STATUS 0xFFC050B0 /* DMA11 Status Register */
+#define DMA11_CURR_X_COUNT 0xFFC050B4 /* DMA11 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA11_CURR_Y_COUNT 0xFFC050B8 /* DMA11 Current Row Count (2D only) */
+#define DMA11_BWL_COUNT 0xFFC050C0 /* DMA11 Bandwidth Limit Count */
+#define DMA11_CURR_BWL_COUNT 0xFFC050C4 /* DMA11 Bandwidth Limit Count Current */
+#define DMA11_BWM_COUNT 0xFFC050C8 /* DMA11 Bandwidth Monitor Count */
+#define DMA11_CURR_BWM_COUNT 0xFFC050CC /* DMA11 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA12
+ ========================= */
+#define DMA12_NEXT_DESC_PTR 0xFFC05100 /* DMA12 Pointer to Next Initial Descriptor */
+#define DMA12_START_ADDR 0xFFC05104 /* DMA12 Start Address of Current Buffer */
+#define DMA12_CONFIG 0xFFC05108 /* DMA12 Configuration Register */
+#define DMA12_X_COUNT 0xFFC0510C /* DMA12 Inner Loop Count Start Value */
+#define DMA12_X_MODIFY 0xFFC05110 /* DMA12 Inner Loop Address Increment */
+#define DMA12_Y_COUNT 0xFFC05114 /* DMA12 Outer Loop Count Start Value (2D only) */
+#define DMA12_Y_MODIFY 0xFFC05118 /* DMA12 Outer Loop Address Increment (2D only) */
+#define DMA12_CURR_DESC_PTR 0xFFC05124 /* DMA12 Current Descriptor Pointer */
+#define DMA12_PREV_DESC_PTR 0xFFC05128 /* DMA12 Previous Initial Descriptor Pointer */
+#define DMA12_CURR_ADDR 0xFFC0512C /* DMA12 Current Address */
+#define DMA12_IRQ_STATUS 0xFFC05130 /* DMA12 Status Register */
+#define DMA12_CURR_X_COUNT 0xFFC05134 /* DMA12 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA12_CURR_Y_COUNT 0xFFC05138 /* DMA12 Current Row Count (2D only) */
+#define DMA12_BWL_COUNT 0xFFC05140 /* DMA12 Bandwidth Limit Count */
+#define DMA12_CURR_BWL_COUNT 0xFFC05144 /* DMA12 Bandwidth Limit Count Current */
+#define DMA12_BWM_COUNT 0xFFC05148 /* DMA12 Bandwidth Monitor Count */
+#define DMA12_CURR_BWM_COUNT 0xFFC0514C /* DMA12 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA13
+ ========================= */
+#define DMA13_NEXT_DESC_PTR 0xFFC07000 /* DMA13 Pointer to Next Initial Descriptor */
+#define DMA13_START_ADDR 0xFFC07004 /* DMA13 Start Address of Current Buffer */
+#define DMA13_CONFIG 0xFFC07008 /* DMA13 Configuration Register */
+#define DMA13_X_COUNT 0xFFC0700C /* DMA13 Inner Loop Count Start Value */
+#define DMA13_X_MODIFY 0xFFC07010 /* DMA13 Inner Loop Address Increment */
+#define DMA13_Y_COUNT 0xFFC07014 /* DMA13 Outer Loop Count Start Value (2D only) */
+#define DMA13_Y_MODIFY 0xFFC07018 /* DMA13 Outer Loop Address Increment (2D only) */
+#define DMA13_CURR_DESC_PTR 0xFFC07024 /* DMA13 Current Descriptor Pointer */
+#define DMA13_PREV_DESC_PTR 0xFFC07028 /* DMA13 Previous Initial Descriptor Pointer */
+#define DMA13_CURR_ADDR 0xFFC0702C /* DMA13 Current Address */
+#define DMA13_IRQ_STATUS 0xFFC07030 /* DMA13 Status Register */
+#define DMA13_CURR_X_COUNT 0xFFC07034 /* DMA13 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA13_CURR_Y_COUNT 0xFFC07038 /* DMA13 Current Row Count (2D only) */
+#define DMA13_BWL_COUNT 0xFFC07040 /* DMA13 Bandwidth Limit Count */
+#define DMA13_CURR_BWL_COUNT 0xFFC07044 /* DMA13 Bandwidth Limit Count Current */
+#define DMA13_BWM_COUNT 0xFFC07048 /* DMA13 Bandwidth Monitor Count */
+#define DMA13_CURR_BWM_COUNT 0xFFC0704C /* DMA13 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA14
+ ========================= */
+#define DMA14_NEXT_DESC_PTR 0xFFC07080 /* DMA14 Pointer to Next Initial Descriptor */
+#define DMA14_START_ADDR 0xFFC07084 /* DMA14 Start Address of Current Buffer */
+#define DMA14_CONFIG 0xFFC07088 /* DMA14 Configuration Register */
+#define DMA14_X_COUNT 0xFFC0708C /* DMA14 Inner Loop Count Start Value */
+#define DMA14_X_MODIFY 0xFFC07090 /* DMA14 Inner Loop Address Increment */
+#define DMA14_Y_COUNT 0xFFC07094 /* DMA14 Outer Loop Count Start Value (2D only) */
+#define DMA14_Y_MODIFY 0xFFC07098 /* DMA14 Outer Loop Address Increment (2D only) */
+#define DMA14_CURR_DESC_PTR 0xFFC070A4 /* DMA14 Current Descriptor Pointer */
+#define DMA14_PREV_DESC_PTR 0xFFC070A8 /* DMA14 Previous Initial Descriptor Pointer */
+#define DMA14_CURR_ADDR 0xFFC070AC /* DMA14 Current Address */
+#define DMA14_IRQ_STATUS 0xFFC070B0 /* DMA14 Status Register */
+#define DMA14_CURR_X_COUNT 0xFFC070B4 /* DMA14 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA14_CURR_Y_COUNT 0xFFC070B8 /* DMA14 Current Row Count (2D only) */
+#define DMA14_BWL_COUNT 0xFFC070C0 /* DMA14 Bandwidth Limit Count */
+#define DMA14_CURR_BWL_COUNT 0xFFC070C4 /* DMA14 Bandwidth Limit Count Current */
+#define DMA14_BWM_COUNT 0xFFC070C8 /* DMA14 Bandwidth Monitor Count */
+#define DMA14_CURR_BWM_COUNT 0xFFC070CC /* DMA14 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA15
+ ========================= */
+#define DMA15_NEXT_DESC_PTR 0xFFC07100 /* DMA15 Pointer to Next Initial Descriptor */
+#define DMA15_START_ADDR 0xFFC07104 /* DMA15 Start Address of Current Buffer */
+#define DMA15_CONFIG 0xFFC07108 /* DMA15 Configuration Register */
+#define DMA15_X_COUNT 0xFFC0710C /* DMA15 Inner Loop Count Start Value */
+#define DMA15_X_MODIFY 0xFFC07110 /* DMA15 Inner Loop Address Increment */
+#define DMA15_Y_COUNT 0xFFC07114 /* DMA15 Outer Loop Count Start Value (2D only) */
+#define DMA15_Y_MODIFY 0xFFC07118 /* DMA15 Outer Loop Address Increment (2D only) */
+#define DMA15_CURR_DESC_PTR 0xFFC07124 /* DMA15 Current Descriptor Pointer */
+#define DMA15_PREV_DESC_PTR 0xFFC07128 /* DMA15 Previous Initial Descriptor Pointer */
+#define DMA15_CURR_ADDR 0xFFC0712C /* DMA15 Current Address */
+#define DMA15_IRQ_STATUS 0xFFC07130 /* DMA15 Status Register */
+#define DMA15_CURR_X_COUNT 0xFFC07134 /* DMA15 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA15_CURR_Y_COUNT 0xFFC07138 /* DMA15 Current Row Count (2D only) */
+#define DMA15_BWL_COUNT 0xFFC07140 /* DMA15 Bandwidth Limit Count */
+#define DMA15_CURR_BWL_COUNT 0xFFC07144 /* DMA15 Bandwidth Limit Count Current */
+#define DMA15_BWM_COUNT 0xFFC07148 /* DMA15 Bandwidth Monitor Count */
+#define DMA15_CURR_BWM_COUNT 0xFFC0714C /* DMA15 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA16
+ ========================= */
+#define DMA16_NEXT_DESC_PTR 0xFFC07180 /* DMA16 Pointer to Next Initial Descriptor */
+#define DMA16_START_ADDR 0xFFC07184 /* DMA16 Start Address of Current Buffer */
+#define DMA16_CONFIG 0xFFC07188 /* DMA16 Configuration Register */
+#define DMA16_X_COUNT 0xFFC0718C /* DMA16 Inner Loop Count Start Value */
+#define DMA16_X_MODIFY 0xFFC07190 /* DMA16 Inner Loop Address Increment */
+#define DMA16_Y_COUNT 0xFFC07194 /* DMA16 Outer Loop Count Start Value (2D only) */
+#define DMA16_Y_MODIFY 0xFFC07198 /* DMA16 Outer Loop Address Increment (2D only) */
+#define DMA16_CURR_DESC_PTR 0xFFC071A4 /* DMA16 Current Descriptor Pointer */
+#define DMA16_PREV_DESC_PTR 0xFFC071A8 /* DMA16 Previous Initial Descriptor Pointer */
+#define DMA16_CURR_ADDR 0xFFC071AC /* DMA16 Current Address */
+#define DMA16_IRQ_STATUS 0xFFC071B0 /* DMA16 Status Register */
+#define DMA16_CURR_X_COUNT 0xFFC071B4 /* DMA16 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA16_CURR_Y_COUNT 0xFFC071B8 /* DMA16 Current Row Count (2D only) */
+#define DMA16_BWL_COUNT 0xFFC071C0 /* DMA16 Bandwidth Limit Count */
+#define DMA16_CURR_BWL_COUNT 0xFFC071C4 /* DMA16 Bandwidth Limit Count Current */
+#define DMA16_BWM_COUNT 0xFFC071C8 /* DMA16 Bandwidth Monitor Count */
+#define DMA16_CURR_BWM_COUNT 0xFFC071CC /* DMA16 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA17
+ ========================= */
+#define DMA17_NEXT_DESC_PTR 0xFFC07200 /* DMA17 Pointer to Next Initial Descriptor */
+#define DMA17_START_ADDR 0xFFC07204 /* DMA17 Start Address of Current Buffer */
+#define DMA17_CONFIG 0xFFC07208 /* DMA17 Configuration Register */
+#define DMA17_X_COUNT 0xFFC0720C /* DMA17 Inner Loop Count Start Value */
+#define DMA17_X_MODIFY 0xFFC07210 /* DMA17 Inner Loop Address Increment */
+#define DMA17_Y_COUNT 0xFFC07214 /* DMA17 Outer Loop Count Start Value (2D only) */
+#define DMA17_Y_MODIFY 0xFFC07218 /* DMA17 Outer Loop Address Increment (2D only) */
+#define DMA17_CURR_DESC_PTR 0xFFC07224 /* DMA17 Current Descriptor Pointer */
+#define DMA17_PREV_DESC_PTR 0xFFC07228 /* DMA17 Previous Initial Descriptor Pointer */
+#define DMA17_CURR_ADDR 0xFFC0722C /* DMA17 Current Address */
+#define DMA17_IRQ_STATUS 0xFFC07230 /* DMA17 Status Register */
+#define DMA17_CURR_X_COUNT 0xFFC07234 /* DMA17 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA17_CURR_Y_COUNT 0xFFC07238 /* DMA17 Current Row Count (2D only) */
+#define DMA17_BWL_COUNT 0xFFC07240 /* DMA17 Bandwidth Limit Count */
+#define DMA17_CURR_BWL_COUNT 0xFFC07244 /* DMA17 Bandwidth Limit Count Current */
+#define DMA17_BWM_COUNT 0xFFC07248 /* DMA17 Bandwidth Monitor Count */
+#define DMA17_CURR_BWM_COUNT 0xFFC0724C /* DMA17 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA18
+ ========================= */
+#define DMA18_NEXT_DESC_PTR 0xFFC07280 /* DMA18 Pointer to Next Initial Descriptor */
+#define DMA18_START_ADDR 0xFFC07284 /* DMA18 Start Address of Current Buffer */
+#define DMA18_CONFIG 0xFFC07288 /* DMA18 Configuration Register */
+#define DMA18_X_COUNT 0xFFC0728C /* DMA18 Inner Loop Count Start Value */
+#define DMA18_X_MODIFY 0xFFC07290 /* DMA18 Inner Loop Address Increment */
+#define DMA18_Y_COUNT 0xFFC07294 /* DMA18 Outer Loop Count Start Value (2D only) */
+#define DMA18_Y_MODIFY 0xFFC07298 /* DMA18 Outer Loop Address Increment (2D only) */
+#define DMA18_CURR_DESC_PTR 0xFFC072A4 /* DMA18 Current Descriptor Pointer */
+#define DMA18_PREV_DESC_PTR 0xFFC072A8 /* DMA18 Previous Initial Descriptor Pointer */
+#define DMA18_CURR_ADDR 0xFFC072AC /* DMA18 Current Address */
+#define DMA18_IRQ_STATUS 0xFFC072B0 /* DMA18 Status Register */
+#define DMA18_CURR_X_COUNT 0xFFC072B4 /* DMA18 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA18_CURR_Y_COUNT 0xFFC072B8 /* DMA18 Current Row Count (2D only) */
+#define DMA18_BWL_COUNT 0xFFC072C0 /* DMA18 Bandwidth Limit Count */
+#define DMA18_CURR_BWL_COUNT 0xFFC072C4 /* DMA18 Bandwidth Limit Count Current */
+#define DMA18_BWM_COUNT 0xFFC072C8 /* DMA18 Bandwidth Monitor Count */
+#define DMA18_CURR_BWM_COUNT 0xFFC072CC /* DMA18 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA19
+ ========================= */
+#define DMA19_NEXT_DESC_PTR 0xFFC07300 /* DMA19 Pointer to Next Initial Descriptor */
+#define DMA19_START_ADDR 0xFFC07304 /* DMA19 Start Address of Current Buffer */
+#define DMA19_CONFIG 0xFFC07308 /* DMA19 Configuration Register */
+#define DMA19_X_COUNT 0xFFC0730C /* DMA19 Inner Loop Count Start Value */
+#define DMA19_X_MODIFY 0xFFC07310 /* DMA19 Inner Loop Address Increment */
+#define DMA19_Y_COUNT 0xFFC07314 /* DMA19 Outer Loop Count Start Value (2D only) */
+#define DMA19_Y_MODIFY 0xFFC07318 /* DMA19 Outer Loop Address Increment (2D only) */
+#define DMA19_CURR_DESC_PTR 0xFFC07324 /* DMA19 Current Descriptor Pointer */
+#define DMA19_PREV_DESC_PTR 0xFFC07328 /* DMA19 Previous Initial Descriptor Pointer */
+#define DMA19_CURR_ADDR 0xFFC0732C /* DMA19 Current Address */
+#define DMA19_IRQ_STATUS 0xFFC07330 /* DMA19 Status Register */
+#define DMA19_CURR_X_COUNT 0xFFC07334 /* DMA19 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA19_CURR_Y_COUNT 0xFFC07338 /* DMA19 Current Row Count (2D only) */
+#define DMA19_BWL_COUNT 0xFFC07340 /* DMA19 Bandwidth Limit Count */
+#define DMA19_CURR_BWL_COUNT 0xFFC07344 /* DMA19 Bandwidth Limit Count Current */
+#define DMA19_BWM_COUNT 0xFFC07348 /* DMA19 Bandwidth Monitor Count */
+#define DMA19_CURR_BWM_COUNT 0xFFC0734C /* DMA19 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA20
+ ========================= */
+#define DMA20_NEXT_DESC_PTR 0xFFC07380 /* DMA20 Pointer to Next Initial Descriptor */
+#define DMA20_START_ADDR 0xFFC07384 /* DMA20 Start Address of Current Buffer */
+#define DMA20_CONFIG 0xFFC07388 /* DMA20 Configuration Register */
+#define DMA20_X_COUNT 0xFFC0738C /* DMA20 Inner Loop Count Start Value */
+#define DMA20_X_MODIFY 0xFFC07390 /* DMA20 Inner Loop Address Increment */
+#define DMA20_Y_COUNT 0xFFC07394 /* DMA20 Outer Loop Count Start Value (2D only) */
+#define DMA20_Y_MODIFY 0xFFC07398 /* DMA20 Outer Loop Address Increment (2D only) */
+#define DMA20_CURR_DESC_PTR 0xFFC073A4 /* DMA20 Current Descriptor Pointer */
+#define DMA20_PREV_DESC_PTR 0xFFC073A8 /* DMA20 Previous Initial Descriptor Pointer */
+#define DMA20_CURR_ADDR 0xFFC073AC /* DMA20 Current Address */
+#define DMA20_IRQ_STATUS 0xFFC073B0 /* DMA20 Status Register */
+#define DMA20_CURR_X_COUNT 0xFFC073B4 /* DMA20 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA20_CURR_Y_COUNT 0xFFC073B8 /* DMA20 Current Row Count (2D only) */
+#define DMA20_BWL_COUNT 0xFFC073C0 /* DMA20 Bandwidth Limit Count */
+#define DMA20_CURR_BWL_COUNT 0xFFC073C4 /* DMA20 Bandwidth Limit Count Current */
+#define DMA20_BWM_COUNT 0xFFC073C8 /* DMA20 Bandwidth Monitor Count */
+#define DMA20_CURR_BWM_COUNT 0xFFC073CC /* DMA20 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA21
+ ========================= */
+#define DMA21_NEXT_DESC_PTR 0xFFC09000 /* DMA21 Pointer to Next Initial Descriptor */
+#define DMA21_START_ADDR 0xFFC09004 /* DMA21 Start Address of Current Buffer */
+#define DMA21_CONFIG 0xFFC09008 /* DMA21 Configuration Register */
+#define DMA21_X_COUNT 0xFFC0900C /* DMA21 Inner Loop Count Start Value */
+#define DMA21_X_MODIFY 0xFFC09010 /* DMA21 Inner Loop Address Increment */
+#define DMA21_Y_COUNT 0xFFC09014 /* DMA21 Outer Loop Count Start Value (2D only) */
+#define DMA21_Y_MODIFY 0xFFC09018 /* DMA21 Outer Loop Address Increment (2D only) */
+#define DMA21_CURR_DESC_PTR 0xFFC09024 /* DMA21 Current Descriptor Pointer */
+#define DMA21_PREV_DESC_PTR 0xFFC09028 /* DMA21 Previous Initial Descriptor Pointer */
+#define DMA21_CURR_ADDR 0xFFC0902C /* DMA21 Current Address */
+#define DMA21_IRQ_STATUS 0xFFC09030 /* DMA21 Status Register */
+#define DMA21_CURR_X_COUNT 0xFFC09034 /* DMA21 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA21_CURR_Y_COUNT 0xFFC09038 /* DMA21 Current Row Count (2D only) */
+#define DMA21_BWL_COUNT 0xFFC09040 /* DMA21 Bandwidth Limit Count */
+#define DMA21_CURR_BWL_COUNT 0xFFC09044 /* DMA21 Bandwidth Limit Count Current */
+#define DMA21_BWM_COUNT 0xFFC09048 /* DMA21 Bandwidth Monitor Count */
+#define DMA21_CURR_BWM_COUNT 0xFFC0904C /* DMA21 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA22
+ ========================= */
+#define DMA22_NEXT_DESC_PTR 0xFFC09080 /* DMA22 Pointer to Next Initial Descriptor */
+#define DMA22_START_ADDR 0xFFC09084 /* DMA22 Start Address of Current Buffer */
+#define DMA22_CONFIG 0xFFC09088 /* DMA22 Configuration Register */
+#define DMA22_X_COUNT 0xFFC0908C /* DMA22 Inner Loop Count Start Value */
+#define DMA22_X_MODIFY 0xFFC09090 /* DMA22 Inner Loop Address Increment */
+#define DMA22_Y_COUNT 0xFFC09094 /* DMA22 Outer Loop Count Start Value (2D only) */
+#define DMA22_Y_MODIFY 0xFFC09098 /* DMA22 Outer Loop Address Increment (2D only) */
+#define DMA22_CURR_DESC_PTR 0xFFC090A4 /* DMA22 Current Descriptor Pointer */
+#define DMA22_PREV_DESC_PTR 0xFFC090A8 /* DMA22 Previous Initial Descriptor Pointer */
+#define DMA22_CURR_ADDR 0xFFC090AC /* DMA22 Current Address */
+#define DMA22_IRQ_STATUS 0xFFC090B0 /* DMA22 Status Register */
+#define DMA22_CURR_X_COUNT 0xFFC090B4 /* DMA22 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA22_CURR_Y_COUNT 0xFFC090B8 /* DMA22 Current Row Count (2D only) */
+#define DMA22_BWL_COUNT 0xFFC090C0 /* DMA22 Bandwidth Limit Count */
+#define DMA22_CURR_BWL_COUNT 0xFFC090C4 /* DMA22 Bandwidth Limit Count Current */
+#define DMA22_BWM_COUNT 0xFFC090C8 /* DMA22 Bandwidth Monitor Count */
+#define DMA22_CURR_BWM_COUNT 0xFFC090CC /* DMA22 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA23
+ ========================= */
+#define DMA23_NEXT_DESC_PTR 0xFFC09100 /* DMA23 Pointer to Next Initial Descriptor */
+#define DMA23_START_ADDR 0xFFC09104 /* DMA23 Start Address of Current Buffer */
+#define DMA23_CONFIG 0xFFC09108 /* DMA23 Configuration Register */
+#define DMA23_X_COUNT 0xFFC0910C /* DMA23 Inner Loop Count Start Value */
+#define DMA23_X_MODIFY 0xFFC09110 /* DMA23 Inner Loop Address Increment */
+#define DMA23_Y_COUNT 0xFFC09114 /* DMA23 Outer Loop Count Start Value (2D only) */
+#define DMA23_Y_MODIFY 0xFFC09118 /* DMA23 Outer Loop Address Increment (2D only) */
+#define DMA23_CURR_DESC_PTR 0xFFC09124 /* DMA23 Current Descriptor Pointer */
+#define DMA23_PREV_DESC_PTR 0xFFC09128 /* DMA23 Previous Initial Descriptor Pointer */
+#define DMA23_CURR_ADDR 0xFFC0912C /* DMA23 Current Address */
+#define DMA23_IRQ_STATUS 0xFFC09130 /* DMA23 Status Register */
+#define DMA23_CURR_X_COUNT 0xFFC09134 /* DMA23 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA23_CURR_Y_COUNT 0xFFC09138 /* DMA23 Current Row Count (2D only) */
+#define DMA23_BWL_COUNT 0xFFC09140 /* DMA23 Bandwidth Limit Count */
+#define DMA23_CURR_BWL_COUNT 0xFFC09144 /* DMA23 Bandwidth Limit Count Current */
+#define DMA23_BWM_COUNT 0xFFC09148 /* DMA23 Bandwidth Monitor Count */
+#define DMA23_CURR_BWM_COUNT 0xFFC0914C /* DMA23 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA24
+ ========================= */
+#define DMA24_NEXT_DESC_PTR 0xFFC09180 /* DMA24 Pointer to Next Initial Descriptor */
+#define DMA24_START_ADDR 0xFFC09184 /* DMA24 Start Address of Current Buffer */
+#define DMA24_CONFIG 0xFFC09188 /* DMA24 Configuration Register */
+#define DMA24_X_COUNT 0xFFC0918C /* DMA24 Inner Loop Count Start Value */
+#define DMA24_X_MODIFY 0xFFC09190 /* DMA24 Inner Loop Address Increment */
+#define DMA24_Y_COUNT 0xFFC09194 /* DMA24 Outer Loop Count Start Value (2D only) */
+#define DMA24_Y_MODIFY 0xFFC09198 /* DMA24 Outer Loop Address Increment (2D only) */
+#define DMA24_CURR_DESC_PTR 0xFFC091A4 /* DMA24 Current Descriptor Pointer */
+#define DMA24_PREV_DESC_PTR 0xFFC091A8 /* DMA24 Previous Initial Descriptor Pointer */
+#define DMA24_CURR_ADDR 0xFFC091AC /* DMA24 Current Address */
+#define DMA24_IRQ_STATUS 0xFFC091B0 /* DMA24 Status Register */
+#define DMA24_CURR_X_COUNT 0xFFC091B4 /* DMA24 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA24_CURR_Y_COUNT 0xFFC091B8 /* DMA24 Current Row Count (2D only) */
+#define DMA24_BWL_COUNT 0xFFC091C0 /* DMA24 Bandwidth Limit Count */
+#define DMA24_CURR_BWL_COUNT 0xFFC091C4 /* DMA24 Bandwidth Limit Count Current */
+#define DMA24_BWM_COUNT 0xFFC091C8 /* DMA24 Bandwidth Monitor Count */
+#define DMA24_CURR_BWM_COUNT 0xFFC091CC /* DMA24 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA25
+ ========================= */
+#define DMA25_NEXT_DESC_PTR 0xFFC09200 /* DMA25 Pointer to Next Initial Descriptor */
+#define DMA25_START_ADDR 0xFFC09204 /* DMA25 Start Address of Current Buffer */
+#define DMA25_CONFIG 0xFFC09208 /* DMA25 Configuration Register */
+#define DMA25_X_COUNT 0xFFC0920C /* DMA25 Inner Loop Count Start Value */
+#define DMA25_X_MODIFY 0xFFC09210 /* DMA25 Inner Loop Address Increment */
+#define DMA25_Y_COUNT 0xFFC09214 /* DMA25 Outer Loop Count Start Value (2D only) */
+#define DMA25_Y_MODIFY 0xFFC09218 /* DMA25 Outer Loop Address Increment (2D only) */
+#define DMA25_CURR_DESC_PTR 0xFFC09224 /* DMA25 Current Descriptor Pointer */
+#define DMA25_PREV_DESC_PTR 0xFFC09228 /* DMA25 Previous Initial Descriptor Pointer */
+#define DMA25_CURR_ADDR 0xFFC0922C /* DMA25 Current Address */
+#define DMA25_IRQ_STATUS 0xFFC09230 /* DMA25 Status Register */
+#define DMA25_CURR_X_COUNT 0xFFC09234 /* DMA25 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA25_CURR_Y_COUNT 0xFFC09238 /* DMA25 Current Row Count (2D only) */
+#define DMA25_BWL_COUNT 0xFFC09240 /* DMA25 Bandwidth Limit Count */
+#define DMA25_CURR_BWL_COUNT 0xFFC09244 /* DMA25 Bandwidth Limit Count Current */
+#define DMA25_BWM_COUNT 0xFFC09248 /* DMA25 Bandwidth Monitor Count */
+#define DMA25_CURR_BWM_COUNT 0xFFC0924C /* DMA25 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA26
+ ========================= */
+#define DMA26_NEXT_DESC_PTR 0xFFC09280 /* DMA26 Pointer to Next Initial Descriptor */
+#define DMA26_START_ADDR 0xFFC09284 /* DMA26 Start Address of Current Buffer */
+#define DMA26_CONFIG 0xFFC09288 /* DMA26 Configuration Register */
+#define DMA26_X_COUNT 0xFFC0928C /* DMA26 Inner Loop Count Start Value */
+#define DMA26_X_MODIFY 0xFFC09290 /* DMA26 Inner Loop Address Increment */
+#define DMA26_Y_COUNT 0xFFC09294 /* DMA26 Outer Loop Count Start Value (2D only) */
+#define DMA26_Y_MODIFY 0xFFC09298 /* DMA26 Outer Loop Address Increment (2D only) */
+#define DMA26_CURR_DESC_PTR 0xFFC092A4 /* DMA26 Current Descriptor Pointer */
+#define DMA26_PREV_DESC_PTR 0xFFC092A8 /* DMA26 Previous Initial Descriptor Pointer */
+#define DMA26_CURR_ADDR 0xFFC092AC /* DMA26 Current Address */
+#define DMA26_IRQ_STATUS 0xFFC092B0 /* DMA26 Status Register */
+#define DMA26_CURR_X_COUNT 0xFFC092B4 /* DMA26 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA26_CURR_Y_COUNT 0xFFC092B8 /* DMA26 Current Row Count (2D only) */
+#define DMA26_BWL_COUNT 0xFFC092C0 /* DMA26 Bandwidth Limit Count */
+#define DMA26_CURR_BWL_COUNT 0xFFC092C4 /* DMA26 Bandwidth Limit Count Current */
+#define DMA26_BWM_COUNT 0xFFC092C8 /* DMA26 Bandwidth Monitor Count */
+#define DMA26_CURR_BWM_COUNT 0xFFC092CC /* DMA26 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA27
+ ========================= */
+#define DMA27_NEXT_DESC_PTR 0xFFC09300 /* DMA27 Pointer to Next Initial Descriptor */
+#define DMA27_START_ADDR 0xFFC09304 /* DMA27 Start Address of Current Buffer */
+#define DMA27_CONFIG 0xFFC09308 /* DMA27 Configuration Register */
+#define DMA27_X_COUNT 0xFFC0930C /* DMA27 Inner Loop Count Start Value */
+#define DMA27_X_MODIFY 0xFFC09310 /* DMA27 Inner Loop Address Increment */
+#define DMA27_Y_COUNT 0xFFC09314 /* DMA27 Outer Loop Count Start Value (2D only) */
+#define DMA27_Y_MODIFY 0xFFC09318 /* DMA27 Outer Loop Address Increment (2D only) */
+#define DMA27_CURR_DESC_PTR 0xFFC09324 /* DMA27 Current Descriptor Pointer */
+#define DMA27_PREV_DESC_PTR 0xFFC09328 /* DMA27 Previous Initial Descriptor Pointer */
+#define DMA27_CURR_ADDR 0xFFC0932C /* DMA27 Current Address */
+#define DMA27_IRQ_STATUS 0xFFC09330 /* DMA27 Status Register */
+#define DMA27_CURR_X_COUNT 0xFFC09334 /* DMA27 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA27_CURR_Y_COUNT 0xFFC09338 /* DMA27 Current Row Count (2D only) */
+#define DMA27_BWL_COUNT 0xFFC09340 /* DMA27 Bandwidth Limit Count */
+#define DMA27_CURR_BWL_COUNT 0xFFC09344 /* DMA27 Bandwidth Limit Count Current */
+#define DMA27_BWM_COUNT 0xFFC09348 /* DMA27 Bandwidth Monitor Count */
+#define DMA27_CURR_BWM_COUNT 0xFFC0934C /* DMA27 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA28
+ ========================= */
+#define DMA28_NEXT_DESC_PTR 0xFFC09380 /* DMA28 Pointer to Next Initial Descriptor */
+#define DMA28_START_ADDR 0xFFC09384 /* DMA28 Start Address of Current Buffer */
+#define DMA28_CONFIG 0xFFC09388 /* DMA28 Configuration Register */
+#define DMA28_X_COUNT 0xFFC0938C /* DMA28 Inner Loop Count Start Value */
+#define DMA28_X_MODIFY 0xFFC09390 /* DMA28 Inner Loop Address Increment */
+#define DMA28_Y_COUNT 0xFFC09394 /* DMA28 Outer Loop Count Start Value (2D only) */
+#define DMA28_Y_MODIFY 0xFFC09398 /* DMA28 Outer Loop Address Increment (2D only) */
+#define DMA28_CURR_DESC_PTR 0xFFC093A4 /* DMA28 Current Descriptor Pointer */
+#define DMA28_PREV_DESC_PTR 0xFFC093A8 /* DMA28 Previous Initial Descriptor Pointer */
+#define DMA28_CURR_ADDR 0xFFC093AC /* DMA28 Current Address */
+#define DMA28_IRQ_STATUS 0xFFC093B0 /* DMA28 Status Register */
+#define DMA28_CURR_X_COUNT 0xFFC093B4 /* DMA28 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA28_CURR_Y_COUNT 0xFFC093B8 /* DMA28 Current Row Count (2D only) */
+#define DMA28_BWL_COUNT 0xFFC093C0 /* DMA28 Bandwidth Limit Count */
+#define DMA28_CURR_BWL_COUNT 0xFFC093C4 /* DMA28 Bandwidth Limit Count Current */
+#define DMA28_BWM_COUNT 0xFFC093C8 /* DMA28 Bandwidth Monitor Count */
+#define DMA28_CURR_BWM_COUNT 0xFFC093CC /* DMA28 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA29
+ ========================= */
+#define DMA29_NEXT_DESC_PTR 0xFFC0B000 /* DMA29 Pointer to Next Initial Descriptor */
+#define DMA29_START_ADDR 0xFFC0B004 /* DMA29 Start Address of Current Buffer */
+#define DMA29_CONFIG 0xFFC0B008 /* DMA29 Configuration Register */
+#define DMA29_X_COUNT 0xFFC0B00C /* DMA29 Inner Loop Count Start Value */
+#define DMA29_X_MODIFY 0xFFC0B010 /* DMA29 Inner Loop Address Increment */
+#define DMA29_Y_COUNT 0xFFC0B014 /* DMA29 Outer Loop Count Start Value (2D only) */
+#define DMA29_Y_MODIFY 0xFFC0B018 /* DMA29 Outer Loop Address Increment (2D only) */
+#define DMA29_CURR_DESC_PTR 0xFFC0B024 /* DMA29 Current Descriptor Pointer */
+#define DMA29_PREV_DESC_PTR 0xFFC0B028 /* DMA29 Previous Initial Descriptor Pointer */
+#define DMA29_CURR_ADDR 0xFFC0B02C /* DMA29 Current Address */
+#define DMA29_IRQ_STATUS 0xFFC0B030 /* DMA29 Status Register */
+#define DMA29_CURR_X_COUNT 0xFFC0B034 /* DMA29 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA29_CURR_Y_COUNT 0xFFC0B038 /* DMA29 Current Row Count (2D only) */
+#define DMA29_BWL_COUNT 0xFFC0B040 /* DMA29 Bandwidth Limit Count */
+#define DMA29_CURR_BWL_COUNT 0xFFC0B044 /* DMA29 Bandwidth Limit Count Current */
+#define DMA29_BWM_COUNT 0xFFC0B048 /* DMA29 Bandwidth Monitor Count */
+#define DMA29_CURR_BWM_COUNT 0xFFC0B04C /* DMA29 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA30
+ ========================= */
+#define DMA30_NEXT_DESC_PTR 0xFFC0B080 /* DMA30 Pointer to Next Initial Descriptor */
+#define DMA30_START_ADDR 0xFFC0B084 /* DMA30 Start Address of Current Buffer */
+#define DMA30_CONFIG 0xFFC0B088 /* DMA30 Configuration Register */
+#define DMA30_X_COUNT 0xFFC0B08C /* DMA30 Inner Loop Count Start Value */
+#define DMA30_X_MODIFY 0xFFC0B090 /* DMA30 Inner Loop Address Increment */
+#define DMA30_Y_COUNT 0xFFC0B094 /* DMA30 Outer Loop Count Start Value (2D only) */
+#define DMA30_Y_MODIFY 0xFFC0B098 /* DMA30 Outer Loop Address Increment (2D only) */
+#define DMA30_CURR_DESC_PTR 0xFFC0B0A4 /* DMA30 Current Descriptor Pointer */
+#define DMA30_PREV_DESC_PTR 0xFFC0B0A8 /* DMA30 Previous Initial Descriptor Pointer */
+#define DMA30_CURR_ADDR 0xFFC0B0AC /* DMA30 Current Address */
+#define DMA30_IRQ_STATUS 0xFFC0B0B0 /* DMA30 Status Register */
+#define DMA30_CURR_X_COUNT 0xFFC0B0B4 /* DMA30 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA30_CURR_Y_COUNT 0xFFC0B0B8 /* DMA30 Current Row Count (2D only) */
+#define DMA30_BWL_COUNT 0xFFC0B0C0 /* DMA30 Bandwidth Limit Count */
+#define DMA30_CURR_BWL_COUNT 0xFFC0B0C4 /* DMA30 Bandwidth Limit Count Current */
+#define DMA30_BWM_COUNT 0xFFC0B0C8 /* DMA30 Bandwidth Monitor Count */
+#define DMA30_CURR_BWM_COUNT 0xFFC0B0CC /* DMA30 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA31
+ ========================= */
+#define DMA31_NEXT_DESC_PTR 0xFFC0B100 /* DMA31 Pointer to Next Initial Descriptor */
+#define DMA31_START_ADDR 0xFFC0B104 /* DMA31 Start Address of Current Buffer */
+#define DMA31_CONFIG 0xFFC0B108 /* DMA31 Configuration Register */
+#define DMA31_X_COUNT 0xFFC0B10C /* DMA31 Inner Loop Count Start Value */
+#define DMA31_X_MODIFY 0xFFC0B110 /* DMA31 Inner Loop Address Increment */
+#define DMA31_Y_COUNT 0xFFC0B114 /* DMA31 Outer Loop Count Start Value (2D only) */
+#define DMA31_Y_MODIFY 0xFFC0B118 /* DMA31 Outer Loop Address Increment (2D only) */
+#define DMA31_CURR_DESC_PTR 0xFFC0B124 /* DMA31 Current Descriptor Pointer */
+#define DMA31_PREV_DESC_PTR 0xFFC0B128 /* DMA31 Previous Initial Descriptor Pointer */
+#define DMA31_CURR_ADDR 0xFFC0B12C /* DMA31 Current Address */
+#define DMA31_IRQ_STATUS 0xFFC0B130 /* DMA31 Status Register */
+#define DMA31_CURR_X_COUNT 0xFFC0B134 /* DMA31 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA31_CURR_Y_COUNT 0xFFC0B138 /* DMA31 Current Row Count (2D only) */
+#define DMA31_BWL_COUNT 0xFFC0B140 /* DMA31 Bandwidth Limit Count */
+#define DMA31_CURR_BWL_COUNT 0xFFC0B144 /* DMA31 Bandwidth Limit Count Current */
+#define DMA31_BWM_COUNT 0xFFC0B148 /* DMA31 Bandwidth Monitor Count */
+#define DMA31_CURR_BWM_COUNT 0xFFC0B14C /* DMA31 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA32
+ ========================= */
+#define DMA32_NEXT_DESC_PTR 0xFFC0B180 /* DMA32 Pointer to Next Initial Descriptor */
+#define DMA32_START_ADDR 0xFFC0B184 /* DMA32 Start Address of Current Buffer */
+#define DMA32_CONFIG 0xFFC0B188 /* DMA32 Configuration Register */
+#define DMA32_X_COUNT 0xFFC0B18C /* DMA32 Inner Loop Count Start Value */
+#define DMA32_X_MODIFY 0xFFC0B190 /* DMA32 Inner Loop Address Increment */
+#define DMA32_Y_COUNT 0xFFC0B194 /* DMA32 Outer Loop Count Start Value (2D only) */
+#define DMA32_Y_MODIFY 0xFFC0B198 /* DMA32 Outer Loop Address Increment (2D only) */
+#define DMA32_CURR_DESC_PTR 0xFFC0B1A4 /* DMA32 Current Descriptor Pointer */
+#define DMA32_PREV_DESC_PTR 0xFFC0B1A8 /* DMA32 Previous Initial Descriptor Pointer */
+#define DMA32_CURR_ADDR 0xFFC0B1AC /* DMA32 Current Address */
+#define DMA32_IRQ_STATUS 0xFFC0B1B0 /* DMA32 Status Register */
+#define DMA32_CURR_X_COUNT 0xFFC0B1B4 /* DMA32 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA32_CURR_Y_COUNT 0xFFC0B1B8 /* DMA32 Current Row Count (2D only) */
+#define DMA32_BWL_COUNT 0xFFC0B1C0 /* DMA32 Bandwidth Limit Count */
+#define DMA32_CURR_BWL_COUNT 0xFFC0B1C4 /* DMA32 Bandwidth Limit Count Current */
+#define DMA32_BWM_COUNT 0xFFC0B1C8 /* DMA32 Bandwidth Monitor Count */
+#define DMA32_CURR_BWM_COUNT 0xFFC0B1CC /* DMA32 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA33
+ ========================= */
+#define DMA33_NEXT_DESC_PTR 0xFFC0D000 /* DMA33 Pointer to Next Initial Descriptor */
+#define DMA33_START_ADDR 0xFFC0D004 /* DMA33 Start Address of Current Buffer */
+#define DMA33_CONFIG 0xFFC0D008 /* DMA33 Configuration Register */
+#define DMA33_X_COUNT 0xFFC0D00C /* DMA33 Inner Loop Count Start Value */
+#define DMA33_X_MODIFY 0xFFC0D010 /* DMA33 Inner Loop Address Increment */
+#define DMA33_Y_COUNT 0xFFC0D014 /* DMA33 Outer Loop Count Start Value (2D only) */
+#define DMA33_Y_MODIFY 0xFFC0D018 /* DMA33 Outer Loop Address Increment (2D only) */
+#define DMA33_CURR_DESC_PTR 0xFFC0D024 /* DMA33 Current Descriptor Pointer */
+#define DMA33_PREV_DESC_PTR 0xFFC0D028 /* DMA33 Previous Initial Descriptor Pointer */
+#define DMA33_CURR_ADDR 0xFFC0D02C /* DMA33 Current Address */
+#define DMA33_IRQ_STATUS 0xFFC0D030 /* DMA33 Status Register */
+#define DMA33_CURR_X_COUNT 0xFFC0D034 /* DMA33 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA33_CURR_Y_COUNT 0xFFC0D038 /* DMA33 Current Row Count (2D only) */
+#define DMA33_BWL_COUNT 0xFFC0D040 /* DMA33 Bandwidth Limit Count */
+#define DMA33_CURR_BWL_COUNT 0xFFC0D044 /* DMA33 Bandwidth Limit Count Current */
+#define DMA33_BWM_COUNT 0xFFC0D048 /* DMA33 Bandwidth Monitor Count */
+#define DMA33_CURR_BWM_COUNT 0xFFC0D04C /* DMA33 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA34
+ ========================= */
+#define DMA34_NEXT_DESC_PTR 0xFFC0D080 /* DMA34 Pointer to Next Initial Descriptor */
+#define DMA34_START_ADDR 0xFFC0D084 /* DMA34 Start Address of Current Buffer */
+#define DMA34_CONFIG 0xFFC0D088 /* DMA34 Configuration Register */
+#define DMA34_X_COUNT 0xFFC0D08C /* DMA34 Inner Loop Count Start Value */
+#define DMA34_X_MODIFY 0xFFC0D090 /* DMA34 Inner Loop Address Increment */
+#define DMA34_Y_COUNT 0xFFC0D094 /* DMA34 Outer Loop Count Start Value (2D only) */
+#define DMA34_Y_MODIFY 0xFFC0D098 /* DMA34 Outer Loop Address Increment (2D only) */
+#define DMA34_CURR_DESC_PTR 0xFFC0D0A4 /* DMA34 Current Descriptor Pointer */
+#define DMA34_PREV_DESC_PTR 0xFFC0D0A8 /* DMA34 Previous Initial Descriptor Pointer */
+#define DMA34_CURR_ADDR 0xFFC0D0AC /* DMA34 Current Address */
+#define DMA34_IRQ_STATUS 0xFFC0D0B0 /* DMA34 Status Register */
+#define DMA34_CURR_X_COUNT 0xFFC0D0B4 /* DMA34 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA34_CURR_Y_COUNT 0xFFC0D0B8 /* DMA34 Current Row Count (2D only) */
+#define DMA34_BWL_COUNT 0xFFC0D0C0 /* DMA34 Bandwidth Limit Count */
+#define DMA34_CURR_BWL_COUNT 0xFFC0D0C4 /* DMA34 Bandwidth Limit Count Current */
+#define DMA34_BWM_COUNT 0xFFC0D0C8 /* DMA34 Bandwidth Monitor Count */
+#define DMA34_CURR_BWM_COUNT 0xFFC0D0CC /* DMA34 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA35
+ ========================= */
+#define DMA35_NEXT_DESC_PTR 0xFFC10000 /* DMA35 Pointer to Next Initial Descriptor */
+#define DMA35_START_ADDR 0xFFC10004 /* DMA35 Start Address of Current Buffer */
+#define DMA35_CONFIG 0xFFC10008 /* DMA35 Configuration Register */
+#define DMA35_X_COUNT 0xFFC1000C /* DMA35 Inner Loop Count Start Value */
+#define DMA35_X_MODIFY 0xFFC10010 /* DMA35 Inner Loop Address Increment */
+#define DMA35_Y_COUNT 0xFFC10014 /* DMA35 Outer Loop Count Start Value (2D only) */
+#define DMA35_Y_MODIFY 0xFFC10018 /* DMA35 Outer Loop Address Increment (2D only) */
+#define DMA35_CURR_DESC_PTR 0xFFC10024 /* DMA35 Current Descriptor Pointer */
+#define DMA35_PREV_DESC_PTR 0xFFC10028 /* DMA35 Previous Initial Descriptor Pointer */
+#define DMA35_CURR_ADDR 0xFFC1002C /* DMA35 Current Address */
+#define DMA35_IRQ_STATUS 0xFFC10030 /* DMA35 Status Register */
+#define DMA35_CURR_X_COUNT 0xFFC10034 /* DMA35 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA35_CURR_Y_COUNT 0xFFC10038 /* DMA35 Current Row Count (2D only) */
+#define DMA35_BWL_COUNT 0xFFC10040 /* DMA35 Bandwidth Limit Count */
+#define DMA35_CURR_BWL_COUNT 0xFFC10044 /* DMA35 Bandwidth Limit Count Current */
+#define DMA35_BWM_COUNT 0xFFC10048 /* DMA35 Bandwidth Monitor Count */
+#define DMA35_CURR_BWM_COUNT 0xFFC1004C /* DMA35 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA36
+ ========================= */
+#define DMA36_NEXT_DESC_PTR 0xFFC10080 /* DMA36 Pointer to Next Initial Descriptor */
+#define DMA36_START_ADDR 0xFFC10084 /* DMA36 Start Address of Current Buffer */
+#define DMA36_CONFIG 0xFFC10088 /* DMA36 Configuration Register */
+#define DMA36_X_COUNT 0xFFC1008C /* DMA36 Inner Loop Count Start Value */
+#define DMA36_X_MODIFY 0xFFC10090 /* DMA36 Inner Loop Address Increment */
+#define DMA36_Y_COUNT 0xFFC10094 /* DMA36 Outer Loop Count Start Value (2D only) */
+#define DMA36_Y_MODIFY 0xFFC10098 /* DMA36 Outer Loop Address Increment (2D only) */
+#define DMA36_CURR_DESC_PTR 0xFFC100A4 /* DMA36 Current Descriptor Pointer */
+#define DMA36_PREV_DESC_PTR 0xFFC100A8 /* DMA36 Previous Initial Descriptor Pointer */
+#define DMA36_CURR_ADDR 0xFFC100AC /* DMA36 Current Address */
+#define DMA36_IRQ_STATUS 0xFFC100B0 /* DMA36 Status Register */
+#define DMA36_CURR_X_COUNT 0xFFC100B4 /* DMA36 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA36_CURR_Y_COUNT 0xFFC100B8 /* DMA36 Current Row Count (2D only) */
+#define DMA36_BWL_COUNT 0xFFC100C0 /* DMA36 Bandwidth Limit Count */
+#define DMA36_CURR_BWL_COUNT 0xFFC100C4 /* DMA36 Bandwidth Limit Count Current */
+#define DMA36_BWM_COUNT 0xFFC100C8 /* DMA36 Bandwidth Monitor Count */
+#define DMA36_CURR_BWM_COUNT 0xFFC100CC /* DMA36 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA37
+ ========================= */
+#define DMA37_NEXT_DESC_PTR 0xFFC10100 /* DMA37 Pointer to Next Initial Descriptor */
+#define DMA37_START_ADDR 0xFFC10104 /* DMA37 Start Address of Current Buffer */
+#define DMA37_CONFIG 0xFFC10108 /* DMA37 Configuration Register */
+#define DMA37_X_COUNT 0xFFC1010C /* DMA37 Inner Loop Count Start Value */
+#define DMA37_X_MODIFY 0xFFC10110 /* DMA37 Inner Loop Address Increment */
+#define DMA37_Y_COUNT 0xFFC10114 /* DMA37 Outer Loop Count Start Value (2D only) */
+#define DMA37_Y_MODIFY 0xFFC10118 /* DMA37 Outer Loop Address Increment (2D only) */
+#define DMA37_CURR_DESC_PTR 0xFFC10124 /* DMA37 Current Descriptor Pointer */
+#define DMA37_PREV_DESC_PTR 0xFFC10128 /* DMA37 Previous Initial Descriptor Pointer */
+#define DMA37_CURR_ADDR 0xFFC1012C /* DMA37 Current Address */
+#define DMA37_IRQ_STATUS 0xFFC10130 /* DMA37 Status Register */
+#define DMA37_CURR_X_COUNT 0xFFC10134 /* DMA37 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA37_CURR_Y_COUNT 0xFFC10138 /* DMA37 Current Row Count (2D only) */
+#define DMA37_BWL_COUNT 0xFFC10140 /* DMA37 Bandwidth Limit Count */
+#define DMA37_CURR_BWL_COUNT 0xFFC10144 /* DMA37 Bandwidth Limit Count Current */
+#define DMA37_BWM_COUNT 0xFFC10148 /* DMA37 Bandwidth Monitor Count */
+#define DMA37_CURR_BWM_COUNT 0xFFC1014C /* DMA37 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA38
+ ========================= */
+#define DMA38_NEXT_DESC_PTR 0xFFC12000 /* DMA38 Pointer to Next Initial Descriptor */
+#define DMA38_START_ADDR 0xFFC12004 /* DMA38 Start Address of Current Buffer */
+#define DMA38_CONFIG 0xFFC12008 /* DMA38 Configuration Register */
+#define DMA38_X_COUNT 0xFFC1200C /* DMA38 Inner Loop Count Start Value */
+#define DMA38_X_MODIFY 0xFFC12010 /* DMA38 Inner Loop Address Increment */
+#define DMA38_Y_COUNT 0xFFC12014 /* DMA38 Outer Loop Count Start Value (2D only) */
+#define DMA38_Y_MODIFY 0xFFC12018 /* DMA38 Outer Loop Address Increment (2D only) */
+#define DMA38_CURR_DESC_PTR 0xFFC12024 /* DMA38 Current Descriptor Pointer */
+#define DMA38_PREV_DESC_PTR 0xFFC12028 /* DMA38 Previous Initial Descriptor Pointer */
+#define DMA38_CURR_ADDR 0xFFC1202C /* DMA38 Current Address */
+#define DMA38_IRQ_STATUS 0xFFC12030 /* DMA38 Status Register */
+#define DMA38_CURR_X_COUNT 0xFFC12034 /* DMA38 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA38_CURR_Y_COUNT 0xFFC12038 /* DMA38 Current Row Count (2D only) */
+#define DMA38_BWL_COUNT 0xFFC12040 /* DMA38 Bandwidth Limit Count */
+#define DMA38_CURR_BWL_COUNT 0xFFC12044 /* DMA38 Bandwidth Limit Count Current */
+#define DMA38_BWM_COUNT 0xFFC12048 /* DMA38 Bandwidth Monitor Count */
+#define DMA38_CURR_BWM_COUNT 0xFFC1204C /* DMA38 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA39
+ ========================= */
+#define DMA39_NEXT_DESC_PTR 0xFFC12080 /* DMA39 Pointer to Next Initial Descriptor */
+#define DMA39_START_ADDR 0xFFC12084 /* DMA39 Start Address of Current Buffer */
+#define DMA39_CONFIG 0xFFC12088 /* DMA39 Configuration Register */
+#define DMA39_X_COUNT 0xFFC1208C /* DMA39 Inner Loop Count Start Value */
+#define DMA39_X_MODIFY 0xFFC12090 /* DMA39 Inner Loop Address Increment */
+#define DMA39_Y_COUNT 0xFFC12094 /* DMA39 Outer Loop Count Start Value (2D only) */
+#define DMA39_Y_MODIFY 0xFFC12098 /* DMA39 Outer Loop Address Increment (2D only) */
+#define DMA39_CURR_DESC_PTR 0xFFC120A4 /* DMA39 Current Descriptor Pointer */
+#define DMA39_PREV_DESC_PTR 0xFFC120A8 /* DMA39 Previous Initial Descriptor Pointer */
+#define DMA39_CURR_ADDR 0xFFC120AC /* DMA39 Current Address */
+#define DMA39_IRQ_STATUS 0xFFC120B0 /* DMA39 Status Register */
+#define DMA39_CURR_X_COUNT 0xFFC120B4 /* DMA39 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA39_CURR_Y_COUNT 0xFFC120B8 /* DMA39 Current Row Count (2D only) */
+#define DMA39_BWL_COUNT 0xFFC120C0 /* DMA39 Bandwidth Limit Count */
+#define DMA39_CURR_BWL_COUNT 0xFFC120C4 /* DMA39 Bandwidth Limit Count Current */
+#define DMA39_BWM_COUNT 0xFFC120C8 /* DMA39 Bandwidth Monitor Count */
+#define DMA39_CURR_BWM_COUNT 0xFFC120CC /* DMA39 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA40
+ ========================= */
+#define DMA40_NEXT_DESC_PTR 0xFFC12100 /* DMA40 Pointer to Next Initial Descriptor */
+#define DMA40_START_ADDR 0xFFC12104 /* DMA40 Start Address of Current Buffer */
+#define DMA40_CONFIG 0xFFC12108 /* DMA40 Configuration Register */
+#define DMA40_X_COUNT 0xFFC1210C /* DMA40 Inner Loop Count Start Value */
+#define DMA40_X_MODIFY 0xFFC12110 /* DMA40 Inner Loop Address Increment */
+#define DMA40_Y_COUNT 0xFFC12114 /* DMA40 Outer Loop Count Start Value (2D only) */
+#define DMA40_Y_MODIFY 0xFFC12118 /* DMA40 Outer Loop Address Increment (2D only) */
+#define DMA40_CURR_DESC_PTR 0xFFC12124 /* DMA40 Current Descriptor Pointer */
+#define DMA40_PREV_DESC_PTR 0xFFC12128 /* DMA40 Previous Initial Descriptor Pointer */
+#define DMA40_CURR_ADDR 0xFFC1212C /* DMA40 Current Address */
+#define DMA40_IRQ_STATUS 0xFFC12130 /* DMA40 Status Register */
+#define DMA40_CURR_X_COUNT 0xFFC12134 /* DMA40 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA40_CURR_Y_COUNT 0xFFC12138 /* DMA40 Current Row Count (2D only) */
+#define DMA40_BWL_COUNT 0xFFC12140 /* DMA40 Bandwidth Limit Count */
+#define DMA40_CURR_BWL_COUNT 0xFFC12144 /* DMA40 Bandwidth Limit Count Current */
+#define DMA40_BWM_COUNT 0xFFC12148 /* DMA40 Bandwidth Monitor Count */
+#define DMA40_CURR_BWM_COUNT 0xFFC1214C /* DMA40 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA41
+ ========================= */
+#define DMA41_NEXT_DESC_PTR 0xFFC12180 /* DMA41 Pointer to Next Initial Descriptor */
+#define DMA41_START_ADDR 0xFFC12184 /* DMA41 Start Address of Current Buffer */
+#define DMA41_CONFIG 0xFFC12188 /* DMA41 Configuration Register */
+#define DMA41_X_COUNT 0xFFC1218C /* DMA41 Inner Loop Count Start Value */
+#define DMA41_X_MODIFY 0xFFC12190 /* DMA41 Inner Loop Address Increment */
+#define DMA41_Y_COUNT 0xFFC12194 /* DMA41 Outer Loop Count Start Value (2D only) */
+#define DMA41_Y_MODIFY 0xFFC12198 /* DMA41 Outer Loop Address Increment (2D only) */
+#define DMA41_CURR_DESC_PTR 0xFFC121A4 /* DMA41 Current Descriptor Pointer */
+#define DMA41_PREV_DESC_PTR 0xFFC121A8 /* DMA41 Previous Initial Descriptor Pointer */
+#define DMA41_CURR_ADDR 0xFFC121AC /* DMA41 Current Address */
+#define DMA41_IRQ_STATUS 0xFFC121B0 /* DMA41 Status Register */
+#define DMA41_CURR_X_COUNT 0xFFC121B4 /* DMA41 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA41_CURR_Y_COUNT 0xFFC121B8 /* DMA41 Current Row Count (2D only) */
+#define DMA41_BWL_COUNT 0xFFC121C0 /* DMA41 Bandwidth Limit Count */
+#define DMA41_CURR_BWL_COUNT 0xFFC121C4 /* DMA41 Bandwidth Limit Count Current */
+#define DMA41_BWM_COUNT 0xFFC121C8 /* DMA41 Bandwidth Monitor Count */
+#define DMA41_CURR_BWM_COUNT 0xFFC121CC /* DMA41 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA42
+ ========================= */
+#define DMA42_NEXT_DESC_PTR 0xFFC14000 /* DMA42 Pointer to Next Initial Descriptor */
+#define DMA42_START_ADDR 0xFFC14004 /* DMA42 Start Address of Current Buffer */
+#define DMA42_CONFIG 0xFFC14008 /* DMA42 Configuration Register */
+#define DMA42_X_COUNT 0xFFC1400C /* DMA42 Inner Loop Count Start Value */
+#define DMA42_X_MODIFY 0xFFC14010 /* DMA42 Inner Loop Address Increment */
+#define DMA42_Y_COUNT 0xFFC14014 /* DMA42 Outer Loop Count Start Value (2D only) */
+#define DMA42_Y_MODIFY 0xFFC14018 /* DMA42 Outer Loop Address Increment (2D only) */
+#define DMA42_CURR_DESC_PTR 0xFFC14024 /* DMA42 Current Descriptor Pointer */
+#define DMA42_PREV_DESC_PTR 0xFFC14028 /* DMA42 Previous Initial Descriptor Pointer */
+#define DMA42_CURR_ADDR 0xFFC1402C /* DMA42 Current Address */
+#define DMA42_IRQ_STATUS 0xFFC14030 /* DMA42 Status Register */
+#define DMA42_CURR_X_COUNT 0xFFC14034 /* DMA42 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA42_CURR_Y_COUNT 0xFFC14038 /* DMA42 Current Row Count (2D only) */
+#define DMA42_BWL_COUNT 0xFFC14040 /* DMA42 Bandwidth Limit Count */
+#define DMA42_CURR_BWL_COUNT 0xFFC14044 /* DMA42 Bandwidth Limit Count Current */
+#define DMA42_BWM_COUNT 0xFFC14048 /* DMA42 Bandwidth Monitor Count */
+#define DMA42_CURR_BWM_COUNT 0xFFC1404C /* DMA42 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA43
+ ========================= */
+#define DMA43_NEXT_DESC_PTR 0xFFC14080 /* DMA43 Pointer to Next Initial Descriptor */
+#define DMA43_START_ADDR 0xFFC14084 /* DMA43 Start Address of Current Buffer */
+#define DMA43_CONFIG 0xFFC14088 /* DMA43 Configuration Register */
+#define DMA43_X_COUNT 0xFFC1408C /* DMA43 Inner Loop Count Start Value */
+#define DMA43_X_MODIFY 0xFFC14090 /* DMA43 Inner Loop Address Increment */
+#define DMA43_Y_COUNT 0xFFC14094 /* DMA43 Outer Loop Count Start Value (2D only) */
+#define DMA43_Y_MODIFY 0xFFC14098 /* DMA43 Outer Loop Address Increment (2D only) */
+#define DMA43_CURR_DESC_PTR 0xFFC140A4 /* DMA43 Current Descriptor Pointer */
+#define DMA43_PREV_DESC_PTR 0xFFC140A8 /* DMA43 Previous Initial Descriptor Pointer */
+#define DMA43_CURR_ADDR 0xFFC140AC /* DMA43 Current Address */
+#define DMA43_IRQ_STATUS 0xFFC140B0 /* DMA43 Status Register */
+#define DMA43_CURR_X_COUNT 0xFFC140B4 /* DMA43 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA43_CURR_Y_COUNT 0xFFC140B8 /* DMA43 Current Row Count (2D only) */
+#define DMA43_BWL_COUNT 0xFFC140C0 /* DMA43 Bandwidth Limit Count */
+#define DMA43_CURR_BWL_COUNT 0xFFC140C4 /* DMA43 Bandwidth Limit Count Current */
+#define DMA43_BWM_COUNT 0xFFC140C8 /* DMA43 Bandwidth Monitor Count */
+#define DMA43_CURR_BWM_COUNT 0xFFC140CC /* DMA43 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA44
+ ========================= */
+#define DMA44_NEXT_DESC_PTR 0xFFC14100 /* DMA44 Pointer to Next Initial Descriptor */
+#define DMA44_START_ADDR 0xFFC14104 /* DMA44 Start Address of Current Buffer */
+#define DMA44_CONFIG 0xFFC14108 /* DMA44 Configuration Register */
+#define DMA44_X_COUNT 0xFFC1410C /* DMA44 Inner Loop Count Start Value */
+#define DMA44_X_MODIFY 0xFFC14110 /* DMA44 Inner Loop Address Increment */
+#define DMA44_Y_COUNT 0xFFC14114 /* DMA44 Outer Loop Count Start Value (2D only) */
+#define DMA44_Y_MODIFY 0xFFC14118 /* DMA44 Outer Loop Address Increment (2D only) */
+#define DMA44_CURR_DESC_PTR 0xFFC14124 /* DMA44 Current Descriptor Pointer */
+#define DMA44_PREV_DESC_PTR 0xFFC14128 /* DMA44 Previous Initial Descriptor Pointer */
+#define DMA44_CURR_ADDR 0xFFC1412C /* DMA44 Current Address */
+#define DMA44_IRQ_STATUS 0xFFC14130 /* DMA44 Status Register */
+#define DMA44_CURR_X_COUNT 0xFFC14134 /* DMA44 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA44_CURR_Y_COUNT 0xFFC14138 /* DMA44 Current Row Count (2D only) */
+#define DMA44_BWL_COUNT 0xFFC14140 /* DMA44 Bandwidth Limit Count */
+#define DMA44_CURR_BWL_COUNT 0xFFC14144 /* DMA44 Bandwidth Limit Count Current */
+#define DMA44_BWM_COUNT 0xFFC14148 /* DMA44 Bandwidth Monitor Count */
+#define DMA44_CURR_BWM_COUNT 0xFFC1414C /* DMA44 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA45
+ ========================= */
+#define DMA45_NEXT_DESC_PTR 0xFFC14180 /* DMA45 Pointer to Next Initial Descriptor */
+#define DMA45_START_ADDR 0xFFC14184 /* DMA45 Start Address of Current Buffer */
+#define DMA45_CONFIG 0xFFC14188 /* DMA45 Configuration Register */
+#define DMA45_X_COUNT 0xFFC1418C /* DMA45 Inner Loop Count Start Value */
+#define DMA45_X_MODIFY 0xFFC14190 /* DMA45 Inner Loop Address Increment */
+#define DMA45_Y_COUNT 0xFFC14194 /* DMA45 Outer Loop Count Start Value (2D only) */
+#define DMA45_Y_MODIFY 0xFFC14198 /* DMA45 Outer Loop Address Increment (2D only) */
+#define DMA45_CURR_DESC_PTR 0xFFC141A4 /* DMA45 Current Descriptor Pointer */
+#define DMA45_PREV_DESC_PTR 0xFFC141A8 /* DMA45 Previous Initial Descriptor Pointer */
+#define DMA45_CURR_ADDR 0xFFC141AC /* DMA45 Current Address */
+#define DMA45_IRQ_STATUS 0xFFC141B0 /* DMA45 Status Register */
+#define DMA45_CURR_X_COUNT 0xFFC141B4 /* DMA45 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA45_CURR_Y_COUNT 0xFFC141B8 /* DMA45 Current Row Count (2D only) */
+#define DMA45_BWL_COUNT 0xFFC141C0 /* DMA45 Bandwidth Limit Count */
+#define DMA45_CURR_BWL_COUNT 0xFFC141C4 /* DMA45 Bandwidth Limit Count Current */
+#define DMA45_BWM_COUNT 0xFFC141C8 /* DMA45 Bandwidth Monitor Count */
+#define DMA45_CURR_BWM_COUNT 0xFFC141CC /* DMA45 Bandwidth Monitor Count Current */
+
+/* =========================
+ DMA46
+ ========================= */
+#define DMA46_NEXT_DESC_PTR 0xFFC14200 /* DMA46 Pointer to Next Initial Descriptor */
+#define DMA46_START_ADDR 0xFFC14204 /* DMA46 Start Address of Current Buffer */
+#define DMA46_CONFIG 0xFFC14208 /* DMA46 Configuration Register */
+#define DMA46_X_COUNT 0xFFC1420C /* DMA46 Inner Loop Count Start Value */
+#define DMA46_X_MODIFY 0xFFC14210 /* DMA46 Inner Loop Address Increment */
+#define DMA46_Y_COUNT 0xFFC14214 /* DMA46 Outer Loop Count Start Value (2D only) */
+#define DMA46_Y_MODIFY 0xFFC14218 /* DMA46 Outer Loop Address Increment (2D only) */
+#define DMA46_CURR_DESC_PTR 0xFFC14224 /* DMA46 Current Descriptor Pointer */
+#define DMA46_PREV_DESC_PTR 0xFFC14228 /* DMA46 Previous Initial Descriptor Pointer */
+#define DMA46_CURR_ADDR 0xFFC1422C /* DMA46 Current Address */
+#define DMA46_IRQ_STATUS 0xFFC14230 /* DMA46 Status Register */
+#define DMA46_CURR_X_COUNT 0xFFC14234 /* DMA46 Current Count(1D) or intra-row XCNT (2D) */
+#define DMA46_CURR_Y_COUNT 0xFFC14238 /* DMA46 Current Row Count (2D only) */
+#define DMA46_BWL_COUNT 0xFFC14240 /* DMA46 Bandwidth Limit Count */
+#define DMA46_CURR_BWL_COUNT 0xFFC14244 /* DMA46 Bandwidth Limit Count Current */
+#define DMA46_BWM_COUNT 0xFFC14248 /* DMA46 Bandwidth Monitor Count */
+#define DMA46_CURR_BWM_COUNT 0xFFC1424C /* DMA46 Bandwidth Monitor Count Current */
+
+
+/********************************************************************************
+ DMA Alias Definitions
+ ********************************************************************************/
+#define MDMA0_DEST_CRC0_NEXT_DESC_PTR (DMA22_NEXT_DESC_PTR)
+#define MDMA0_DEST_CRC0_START_ADDR (DMA22_START_ADDR)
+#define MDMA0_DEST_CRC0_CONFIG (DMA22_CONFIG)
+#define MDMA0_DEST_CRC0_X_COUNT (DMA22_X_COUNT)
+#define MDMA0_DEST_CRC0_X_MODIFY (DMA22_X_MODIFY)
+#define MDMA0_DEST_CRC0_Y_COUNT (DMA22_Y_COUNT)
+#define MDMA0_DEST_CRC0_Y_MODIFY (DMA22_Y_MODIFY)
+#define MDMA0_DEST_CRC0_CURR_DESC_PTR (DMA22_CURR_DESC_PTR)
+#define MDMA0_DEST_CRC0_PREV_DESC_PTR (DMA22_PREV_DESC_PTR)
+#define MDMA0_DEST_CRC0_CURR_ADDR (DMA22_CURR_ADDR)
+#define MDMA0_DEST_CRC0_IRQ_STATUS (DMA22_IRQ_STATUS)
+#define MDMA0_DEST_CRC0_CURR_X_COUNT (DMA22_CURR_X_COUNT)
+#define MDMA0_DEST_CRC0_CURR_Y_COUNT (DMA22_CURR_Y_COUNT)
+#define MDMA0_DEST_CRC0_BWL_COUNT (DMA22_BWL_COUNT)
+#define MDMA0_DEST_CRC0_CURR_BWL_COUNT (DMA22_CURR_BWL_COUNT)
+#define MDMA0_DEST_CRC0_BWM_COUNT (DMA22_BWM_COUNT)
+#define MDMA0_DEST_CRC0_CURR_BWM_COUNT (DMA22_CURR_BWM_COUNT)
+#define MDMA0_SRC_CRC0_NEXT_DESC_PTR (DMA21_NEXT_DESC_PTR)
+#define MDMA0_SRC_CRC0_START_ADDR (DMA21_START_ADDR)
+#define MDMA0_SRC_CRC0_CONFIG (DMA21_CONFIG)
+#define MDMA0_SRC_CRC0_X_COUNT (DMA21_X_COUNT)
+#define MDMA0_SRC_CRC0_X_MODIFY (DMA21_X_MODIFY)
+#define MDMA0_SRC_CRC0_Y_COUNT (DMA21_Y_COUNT)
+#define MDMA0_SRC_CRC0_Y_MODIFY (DMA21_Y_MODIFY)
+#define MDMA0_SRC_CRC0_CURR_DESC_PTR (DMA21_CURR_DESC_PTR)
+#define MDMA0_SRC_CRC0_PREV_DESC_PTR (DMA21_PREV_DESC_PTR)
+#define MDMA0_SRC_CRC0_CURR_ADDR (DMA21_CURR_ADDR)
+#define MDMA0_SRC_CRC0_IRQ_STATUS (DMA21_IRQ_STATUS)
+#define MDMA0_SRC_CRC0_CURR_X_COUNT (DMA21_CURR_X_COUNT)
+#define MDMA0_SRC_CRC0_CURR_Y_COUNT (DMA21_CURR_Y_COUNT)
+#define MDMA0_SRC_CRC0_BWL_COUNT (DMA21_BWL_COUNT)
+#define MDMA0_SRC_CRC0_CURR_BWL_COUNT (DMA21_CURR_BWL_COUNT)
+#define MDMA0_SRC_CRC0_BWM_COUNT (DMA21_BWM_COUNT)
+#define MDMA0_SRC_CRC0_CURR_BWM_COUNT (DMA21_CURR_BWM_COUNT)
+#define MDMA1_DEST_CRC1_NEXT_DESC_PTR (DMA24_NEXT_DESC_PTR)
+#define MDMA1_DEST_CRC1_START_ADDR (DMA24_START_ADDR)
+#define MDMA1_DEST_CRC1_CONFIG (DMA24_CONFIG)
+#define MDMA1_DEST_CRC1_X_COUNT (DMA24_X_COUNT)
+#define MDMA1_DEST_CRC1_X_MODIFY (DMA24_X_MODIFY)
+#define MDMA1_DEST_CRC1_Y_COUNT (DMA24_Y_COUNT)
+#define MDMA1_DEST_CRC1_Y_MODIFY (DMA24_Y_MODIFY)
+#define MDMA1_DEST_CRC1_CURR_DESC_PTR (DMA24_CURR_DESC_PTR)
+#define MDMA1_DEST_CRC1_PREV_DESC_PTR (DMA24_PREV_DESC_PTR)
+#define MDMA1_DEST_CRC1_CURR_ADDR (DMA24_CURR_ADDR)
+#define MDMA1_DEST_CRC1_IRQ_STATUS (DMA24_IRQ_STATUS)
+#define MDMA1_DEST_CRC1_CURR_X_COUNT (DMA24_CURR_X_COUNT)
+#define MDMA1_DEST_CRC1_CURR_Y_COUNT (DMA24_CURR_Y_COUNT)
+#define MDMA1_DEST_CRC1_BWL_COUNT (DMA24_BWL_COUNT)
+#define MDMA1_DEST_CRC1_CURR_BWL_COUNT (DMA24_CURR_BWL_COUNT)
+#define MDMA1_DEST_CRC1_BWM_COUNT (DMA24_BWM_COUNT)
+#define MDMA1_DEST_CRC1_CURR_BWM_COUNT (DMA24_CURR_BWM_COUNT)
+#define MDMA1_SRC_CRC1_NEXT_DESC_PTR (DMA23_NEXT_DESC_PTR)
+#define MDMA1_SRC_CRC1_START_ADDR (DMA23_START_ADDR)
+#define MDMA1_SRC_CRC1_CONFIG (DMA23_CONFIG)
+#define MDMA1_SRC_CRC1_X_COUNT (DMA23_X_COUNT)
+#define MDMA1_SRC_CRC1_X_MODIFY (DMA23_X_MODIFY)
+#define MDMA1_SRC_CRC1_Y_COUNT (DMA23_Y_COUNT)
+#define MDMA1_SRC_CRC1_Y_MODIFY (DMA23_Y_MODIFY)
+#define MDMA1_SRC_CRC1_CURR_DESC_PTR (DMA23_CURR_DESC_PTR)
+#define MDMA1_SRC_CRC1_PREV_DESC_PTR (DMA23_PREV_DESC_PTR)
+#define MDMA1_SRC_CRC1_CURR_ADDR (DMA23_CURR_ADDR)
+#define MDMA1_SRC_CRC1_IRQ_STATUS (DMA23_IRQ_STATUS)
+#define MDMA1_SRC_CRC1_CURR_X_COUNT (DMA23_CURR_X_COUNT)
+#define MDMA1_SRC_CRC1_CURR_Y_COUNT (DMA23_CURR_Y_COUNT)
+#define MDMA1_SRC_CRC1_BWL_COUNT (DMA23_BWL_COUNT)
+#define MDMA1_SRC_CRC1_CURR_BWL_COUNT (DMA23_CURR_BWL_COUNT)
+#define MDMA1_SRC_CRC1_BWM_COUNT (DMA23_BWM_COUNT)
+#define MDMA1_SRC_CRC1_CURR_BWM_COUNT (DMA23_CURR_BWM_COUNT)
+#define MDMA2_DEST_NEXT_DESC_PTR (DMA26_NEXT_DESC_PTR)
+#define MDMA2_DEST_START_ADDR (DMA26_START_ADDR)
+#define MDMA2_DEST_CONFIG (DMA26_CONFIG)
+#define MDMA2_DEST_X_COUNT (DMA26_X_COUNT)
+#define MDMA2_DEST_X_MODIFY (DMA26_X_MODIFY)
+#define MDMA2_DEST_Y_COUNT (DMA26_Y_COUNT)
+#define MDMA2_DEST_Y_MODIFY (DMA26_Y_MODIFY)
+#define MDMA2_DEST_CURR_DESC_PTR (DMA26_CURR_DESC_PTR)
+#define MDMA2_DEST_PREV_DESC_PTR (DMA26_PREV_DESC_PTR)
+#define MDMA2_DEST_CURR_ADDR (DMA26_CURR_ADDR)
+#define MDMA2_DEST_IRQ_STATUS (DMA26_IRQ_STATUS)
+#define MDMA2_DEST_CURR_X_COUNT (DMA26_CURR_X_COUNT)
+#define MDMA2_DEST_CURR_Y_COUNT (DMA26_CURR_Y_COUNT)
+#define MDMA2_DEST_BWL_COUNT (DMA26_BWL_COUNT)
+#define MDMA2_DEST_CURR_BWL_COUNT (DMA26_CURR_BWL_COUNT)
+#define MDMA2_DEST_BWM_COUNT (DMA26_BWM_COUNT)
+#define MDMA2_DEST_CURR_BWM_COUNT (DMA26_CURR_BWM_COUNT)
+#define MDMA2_SRC_NEXT_DESC_PTR (DMA25_NEXT_DESC_PTR)
+#define MDMA2_SRC_START_ADDR (DMA25_START_ADDR)
+#define MDMA2_SRC_CONFIG (DMA25_CONFIG)
+#define MDMA2_SRC_X_COUNT (DMA25_X_COUNT)
+#define MDMA2_SRC_X_MODIFY (DMA25_X_MODIFY)
+#define MDMA2_SRC_Y_COUNT (DMA25_Y_COUNT)
+#define MDMA2_SRC_Y_MODIFY (DMA25_Y_MODIFY)
+#define MDMA2_SRC_CURR_DESC_PTR (DMA25_CURR_DESC_PTR)
+#define MDMA2_SRC_PREV_DESC_PTR (DMA25_PREV_DESC_PTR)
+#define MDMA2_SRC_CURR_ADDR (DMA25_CURR_ADDR)
+#define MDMA2_SRC_IRQ_STATUS (DMA25_IRQ_STATUS)
+#define MDMA2_SRC_CURR_X_COUNT (DMA25_CURR_X_COUNT)
+#define MDMA2_SRC_CURR_Y_COUNT (DMA25_CURR_Y_COUNT)
+#define MDMA2_SRC_BWL_COUNT (DMA25_BWL_COUNT)
+#define MDMA2_SRC_CURR_BWL_COUNT (DMA25_CURR_BWL_COUNT)
+#define MDMA2_SRC_BWM_COUNT (DMA25_BWM_COUNT)
+#define MDMA2_SRC_CURR_BWM_COUNT (DMA25_CURR_BWM_COUNT)
+#define MDMA3_DEST_NEXT_DESC_PTR (DMA28_NEXT_DESC_PTR)
+#define MDMA3_DEST_START_ADDR (DMA28_START_ADDR)
+#define MDMA3_DEST_CONFIG (DMA28_CONFIG)
+#define MDMA3_DEST_X_COUNT (DMA28_X_COUNT)
+#define MDMA3_DEST_X_MODIFY (DMA28_X_MODIFY)
+#define MDMA3_DEST_Y_COUNT (DMA28_Y_COUNT)
+#define MDMA3_DEST_Y_MODIFY (DMA28_Y_MODIFY)
+#define MDMA3_DEST_CURR_DESC_PTR (DMA28_CURR_DESC_PTR)
+#define MDMA3_DEST_PREV_DESC_PTR (DMA28_PREV_DESC_PTR)
+#define MDMA3_DEST_CURR_ADDR (DMA28_CURR_ADDR)
+#define MDMA3_DEST_IRQ_STATUS (DMA28_IRQ_STATUS)
+#define MDMA3_DEST_CURR_X_COUNT (DMA28_CURR_X_COUNT)
+#define MDMA3_DEST_CURR_Y_COUNT (DMA28_CURR_Y_COUNT)
+#define MDMA3_DEST_BWL_COUNT (DMA28_BWL_COUNT)
+#define MDMA3_DEST_CURR_BWL_COUNT (DMA28_CURR_BWL_COUNT)
+#define MDMA3_DEST_BWM_COUNT (DMA28_BWM_COUNT)
+#define MDMA3_DEST_CURR_BWM_COUNT (DMA28_CURR_BWM_COUNT)
+#define MDMA3_SRC_NEXT_DESC_PTR (DMA27_NEXT_DESC_PTR)
+#define MDMA3_SRC_START_ADDR (DMA27_START_ADDR)
+#define MDMA3_SRC_CONFIG (DMA27_CONFIG)
+#define MDMA3_SRC_X_COUNT (DMA27_X_COUNT)
+#define MDMA3_SRC_X_MODIFY (DMA27_X_MODIFY)
+#define MDMA3_SRC_Y_COUNT (DMA27_Y_COUNT)
+#define MDMA3_SRC_Y_MODIFY (DMA27_Y_MODIFY)
+#define MDMA3_SRC_CURR_DESC_PTR (DMA27_CURR_DESC_PTR)
+#define MDMA3_SRC_PREV_DESC_PTR (DMA27_PREV_DESC_PTR)
+#define MDMA3_SRC_CURR_ADDR (DMA27_CURR_ADDR)
+#define MDMA3_SRC_IRQ_STATUS (DMA27_IRQ_STATUS)
+#define MDMA3_SRC_CURR_X_COUNT (DMA27_CURR_X_COUNT)
+#define MDMA3_SRC_CURR_Y_COUNT (DMA27_CURR_Y_COUNT)
+#define MDMA3_SRC_BWL_COUNT (DMA27_BWL_COUNT)
+#define MDMA3_SRC_CURR_BWL_COUNT (DMA27_CURR_BWL_COUNT)
+#define MDMA3_SRC_BWM_COUNT (DMA27_BWM_COUNT)
+#define MDMA3_SRC_CURR_BWM_COUNT (DMA27_CURR_BWM_COUNT)
+
+
+/* =========================
+ DMC Registers
+ ========================= */
+
+/* =========================
+ DMC0
+ ========================= */
+#define DMC0_ID 0xFFC80000 /* DMC0 Identification Register */
+#define DMC0_CTL 0xFFC80004 /* DMC0 Control Register */
+#define DMC0_STAT 0xFFC80008 /* DMC0 Status Register */
+#define DMC0_EFFCTL 0xFFC8000C /* DMC0 Efficiency Controller */
+#define DMC0_PRIO 0xFFC80010 /* DMC0 Priority ID Register */
+#define DMC0_PRIOMSK 0xFFC80014 /* DMC0 Priority ID Mask */
+#define DMC0_CFG 0xFFC80040 /* DMC0 SDRAM Configuration */
+#define DMC0_TR0 0xFFC80044 /* DMC0 Timing Register 0 */
+#define DMC0_TR1 0xFFC80048 /* DMC0 Timing Register 1 */
+#define DMC0_TR2 0xFFC8004C /* DMC0 Timing Register 2 */
+#define DMC0_MSK 0xFFC8005C /* DMC0 Mode Register Mask */
+#define DMC0_MR 0xFFC80060 /* DMC0 Mode Shadow register */
+#define DMC0_EMR1 0xFFC80064 /* DMC0 EMR1 Shadow Register */
+#define DMC0_EMR2 0xFFC80068 /* DMC0 EMR2 Shadow Register */
+#define DMC0_EMR3 0xFFC8006C /* DMC0 EMR3 Shadow Register */
+#define DMC0_DLLCTL 0xFFC80080 /* DMC0 DLL Control Register */
+#define DMC0_PADCTL 0xFFC800C0 /* DMC0 PAD Control Register 0 */
+
+#define DEVSZ_64 0x000 /* DMC External Bank Size = 64Mbit */
+#define DEVSZ_128 0x100 /* DMC External Bank Size = 128Mbit */
+#define DEVSZ_256 0x200 /* DMC External Bank Size = 256Mbit */
+#define DEVSZ_512 0x300 /* DMC External Bank Size = 512Mbit */
+#define DEVSZ_1G 0x400 /* DMC External Bank Size = 1Gbit */
+#define DEVSZ_2G 0x500 /* DMC External Bank Size = 2Gbit */
+
+
+/* =========================
+ L2CTL Registers
+ ========================= */
+
+/* =========================
+ L2CTL0
+ ========================= */
+#define L2CTL0_CTL 0xFFCA3000 /* L2CTL0 L2 Control Register */
+#define L2CTL0_ACTL_C0 0xFFCA3004 /* L2CTL0 L2 Core 0 Access Control Register */
+#define L2CTL0_ACTL_C1 0xFFCA3008 /* L2CTL0 L2 Core 1 Access Control Register */
+#define L2CTL0_ACTL_SYS 0xFFCA300C /* L2CTL0 L2 System Access Control Register */
+#define L2CTL0_STAT 0xFFCA3010 /* L2CTL0 L2 Status Register */
+#define L2CTL0_RPCR 0xFFCA3014 /* L2CTL0 L2 Read Priority Count Register */
+#define L2CTL0_WPCR 0xFFCA3018 /* L2CTL0 L2 Write Priority Count Register */
+#define L2CTL0_RFA 0xFFCA3024 /* L2CTL0 L2 Refresh Address Regsiter */
+#define L2CTL0_ERRADDR0 0xFFCA3040 /* L2CTL0 L2 Bank 0 ECC Error Address Register */
+#define L2CTL0_ERRADDR1 0xFFCA3044 /* L2CTL0 L2 Bank 1 ECC Error Address Register */
+#define L2CTL0_ERRADDR2 0xFFCA3048 /* L2CTL0 L2 Bank 2 ECC Error Address Register */
+#define L2CTL0_ERRADDR3 0xFFCA304C /* L2CTL0 L2 Bank 3 ECC Error Address Register */
+#define L2CTL0_ERRADDR4 0xFFCA3050 /* L2CTL0 L2 Bank 4 ECC Error Address Register */
+#define L2CTL0_ERRADDR5 0xFFCA3054 /* L2CTL0 L2 Bank 5 ECC Error Address Register */
+#define L2CTL0_ERRADDR6 0xFFCA3058 /* L2CTL0 L2 Bank 6 ECC Error Address Register */
+#define L2CTL0_ERRADDR7 0xFFCA305C /* L2CTL0 L2 Bank 7 ECC Error Address Register */
+#define L2CTL0_ET0 0xFFCA3080 /* L2CTL0 L2 AXI Error 0 Type Register */
+#define L2CTL0_EADDR0 0xFFCA3084 /* L2CTL0 L2 AXI Error 0 Address Register */
+#define L2CTL0_ET1 0xFFCA3088 /* L2CTL0 L2 AXI Error 1 Type Register */
+#define L2CTL0_EADDR1 0xFFCA308C /* L2CTL0 L2 AXI Error 1 Address Register */
+
+
+/* =========================
+ SEC Registers
+ ========================= */
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC Core Interface (SCI) Register Definitions
+ ------------------------------------------------------------------------------------------------------------------------ */
+
+#define SEC_SCI_BASE 0xFFCA4400
+#define SEC_SCI_OFF 0x40
+#define SEC_CCTL 0x0 /* SEC Core Control Register n */
+#define SEC_CSTAT 0x4 /* SEC Core Status Register n */
+#define SEC_CPND 0x8 /* SEC Core Pending IRQ Register n */
+#define SEC_CACT 0xC /* SEC Core Active IRQ Register n */
+#define SEC_CPMSK 0x10 /* SEC Core IRQ Priority Mask Register n */
+#define SEC_CGMSK 0x14 /* SEC Core IRQ Group Mask Register n */
+#define SEC_CPLVL 0x18 /* SEC Core IRQ Priority Level Register n */
+#define SEC_CSID 0x1C /* SEC Core IRQ Source ID Register n */
+
+#define bfin_read_SEC_SCI(n, reg) bfin_read32(SEC_SCI_BASE + (n) * SEC_SCI_OFF + reg)
+#define bfin_write_SEC_SCI(n, reg, val) \
+ bfin_write32(SEC_SCI_BASE + (n) * SEC_SCI_OFF + reg, val)
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC Fault Management Interface (SFI) Register Definitions
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_FCTL 0xFFCA4010 /* SEC Fault Control Register */
+#define SEC_FSTAT 0xFFCA4014 /* SEC Fault Status Register */
+#define SEC_FSID 0xFFCA4018 /* SEC Fault Source ID Register */
+#define SEC_FEND 0xFFCA401C /* SEC Fault End Register */
+#define SEC_FDLY 0xFFCA4020 /* SEC Fault Delay Register */
+#define SEC_FDLY_CUR 0xFFCA4024 /* SEC Fault Delay Current Register */
+#define SEC_FSRDLY 0xFFCA4028 /* SEC Fault System Reset Delay Register */
+#define SEC_FSRDLY_CUR 0xFFCA402C /* SEC Fault System Reset Delay Current Register */
+#define SEC_FCOPP 0xFFCA4030 /* SEC Fault COP Period Register */
+#define SEC_FCOPP_CUR 0xFFCA4034 /* SEC Fault COP Period Current Register */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC Global Register Definitions
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_GCTL 0xFFCA4000 /* SEC Global Control Register */
+#define SEC_GSTAT 0xFFCA4004 /* SEC Global Status Register */
+#define SEC_RAISE 0xFFCA4008 /* SEC Global Raise Register */
+#define SEC_END 0xFFCA400C /* SEC Global End Register */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC Source Interface (SSI) Register Definitions
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_SCTL0 0xFFCA4800 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL1 0xFFCA4808 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL2 0xFFCA4810 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL3 0xFFCA4818 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL4 0xFFCA4820 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL5 0xFFCA4828 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL6 0xFFCA4830 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL7 0xFFCA4838 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL8 0xFFCA4840 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL9 0xFFCA4848 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL10 0xFFCA4850 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL11 0xFFCA4858 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL12 0xFFCA4860 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL13 0xFFCA4868 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL14 0xFFCA4870 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL15 0xFFCA4878 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL16 0xFFCA4880 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL17 0xFFCA4888 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL18 0xFFCA4890 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL19 0xFFCA4898 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL20 0xFFCA48A0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL21 0xFFCA48A8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL22 0xFFCA48B0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL23 0xFFCA48B8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL24 0xFFCA48C0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL25 0xFFCA48C8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL26 0xFFCA48D0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL27 0xFFCA48D8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL28 0xFFCA48E0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL29 0xFFCA48E8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL30 0xFFCA48F0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL31 0xFFCA48F8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL32 0xFFCA4900 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL33 0xFFCA4908 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL34 0xFFCA4910 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL35 0xFFCA4918 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL36 0xFFCA4920 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL37 0xFFCA4928 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL38 0xFFCA4930 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL39 0xFFCA4938 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL40 0xFFCA4940 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL41 0xFFCA4948 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL42 0xFFCA4950 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL43 0xFFCA4958 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL44 0xFFCA4960 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL45 0xFFCA4968 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL46 0xFFCA4970 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL47 0xFFCA4978 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL48 0xFFCA4980 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL49 0xFFCA4988 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL50 0xFFCA4990 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL51 0xFFCA4998 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL52 0xFFCA49A0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL53 0xFFCA49A8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL54 0xFFCA49B0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL55 0xFFCA49B8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL56 0xFFCA49C0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL57 0xFFCA49C8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL58 0xFFCA49D0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL59 0xFFCA49D8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL60 0xFFCA49E0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL61 0xFFCA49E8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL62 0xFFCA49F0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL63 0xFFCA49F8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL64 0xFFCA4A00 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL65 0xFFCA4A08 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL66 0xFFCA4A10 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL67 0xFFCA4A18 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL68 0xFFCA4A20 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL69 0xFFCA4A28 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL70 0xFFCA4A30 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL71 0xFFCA4A38 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL72 0xFFCA4A40 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL73 0xFFCA4A48 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL74 0xFFCA4A50 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL75 0xFFCA4A58 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL76 0xFFCA4A60 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL77 0xFFCA4A68 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL78 0xFFCA4A70 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL79 0xFFCA4A78 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL80 0xFFCA4A80 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL81 0xFFCA4A88 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL82 0xFFCA4A90 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL83 0xFFCA4A98 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL84 0xFFCA4AA0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL85 0xFFCA4AA8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL86 0xFFCA4AB0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL87 0xFFCA4AB8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL88 0xFFCA4AC0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL89 0xFFCA4AC8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL90 0xFFCA4AD0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL91 0xFFCA4AD8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL92 0xFFCA4AE0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL93 0xFFCA4AE8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL94 0xFFCA4AF0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL95 0xFFCA4AF8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL96 0xFFCA4B00 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL97 0xFFCA4B08 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL98 0xFFCA4B10 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL99 0xFFCA4B18 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL100 0xFFCA4B20 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL101 0xFFCA4B28 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL102 0xFFCA4B30 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL103 0xFFCA4B38 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL104 0xFFCA4B40 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL105 0xFFCA4B48 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL106 0xFFCA4B50 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL107 0xFFCA4B58 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL108 0xFFCA4B60 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL109 0xFFCA4B68 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL110 0xFFCA4B70 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL111 0xFFCA4B78 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL112 0xFFCA4B80 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL113 0xFFCA4B88 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL114 0xFFCA4B90 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL115 0xFFCA4B98 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL116 0xFFCA4BA0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL117 0xFFCA4BA8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL118 0xFFCA4BB0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL119 0xFFCA4BB8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL120 0xFFCA4BC0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL121 0xFFCA4BC8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL122 0xFFCA4BD0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL123 0xFFCA4BD8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL124 0xFFCA4BE0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL125 0xFFCA4BE8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL126 0xFFCA4BF0 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL127 0xFFCA4BF8 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL128 0xFFCA4C00 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL129 0xFFCA4C08 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL130 0xFFCA4C10 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL131 0xFFCA4C18 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL132 0xFFCA4C20 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL133 0xFFCA4C28 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL134 0xFFCA4C30 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL135 0xFFCA4C38 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL136 0xFFCA4C40 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL137 0xFFCA4C48 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL138 0xFFCA4C50 /* SEC IRQ Source Control Register n */
+#define SEC_SCTL139 0xFFCA4C58 /* SEC IRQ Source Control Register n */
+#define SEC_SSTAT0 0xFFCA4804 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT1 0xFFCA480C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT2 0xFFCA4814 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT3 0xFFCA481C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT4 0xFFCA4824 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT5 0xFFCA482C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT6 0xFFCA4834 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT7 0xFFCA483C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT8 0xFFCA4844 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT9 0xFFCA484C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT10 0xFFCA4854 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT11 0xFFCA485C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT12 0xFFCA4864 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT13 0xFFCA486C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT14 0xFFCA4874 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT15 0xFFCA487C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT16 0xFFCA4884 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT17 0xFFCA488C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT18 0xFFCA4894 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT19 0xFFCA489C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT20 0xFFCA48A4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT21 0xFFCA48AC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT22 0xFFCA48B4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT23 0xFFCA48BC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT24 0xFFCA48C4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT25 0xFFCA48CC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT26 0xFFCA48D4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT27 0xFFCA48DC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT28 0xFFCA48E4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT29 0xFFCA48EC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT30 0xFFCA48F4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT31 0xFFCA48FC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT32 0xFFCA4904 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT33 0xFFCA490C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT34 0xFFCA4914 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT35 0xFFCA491C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT36 0xFFCA4924 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT37 0xFFCA492C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT38 0xFFCA4934 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT39 0xFFCA493C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT40 0xFFCA4944 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT41 0xFFCA494C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT42 0xFFCA4954 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT43 0xFFCA495C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT44 0xFFCA4964 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT45 0xFFCA496C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT46 0xFFCA4974 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT47 0xFFCA497C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT48 0xFFCA4984 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT49 0xFFCA498C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT50 0xFFCA4994 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT51 0xFFCA499C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT52 0xFFCA49A4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT53 0xFFCA49AC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT54 0xFFCA49B4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT55 0xFFCA49BC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT56 0xFFCA49C4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT57 0xFFCA49CC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT58 0xFFCA49D4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT59 0xFFCA49DC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT60 0xFFCA49E4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT61 0xFFCA49EC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT62 0xFFCA49F4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT63 0xFFCA49FC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT64 0xFFCA4A04 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT65 0xFFCA4A0C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT66 0xFFCA4A14 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT67 0xFFCA4A1C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT68 0xFFCA4A24 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT69 0xFFCA4A2C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT70 0xFFCA4A34 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT71 0xFFCA4A3C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT72 0xFFCA4A44 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT73 0xFFCA4A4C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT74 0xFFCA4A54 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT75 0xFFCA4A5C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT76 0xFFCA4A64 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT77 0xFFCA4A6C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT78 0xFFCA4A74 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT79 0xFFCA4A7C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT80 0xFFCA4A84 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT81 0xFFCA4A8C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT82 0xFFCA4A94 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT83 0xFFCA4A9C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT84 0xFFCA4AA4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT85 0xFFCA4AAC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT86 0xFFCA4AB4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT87 0xFFCA4ABC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT88 0xFFCA4AC4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT89 0xFFCA4ACC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT90 0xFFCA4AD4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT91 0xFFCA4ADC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT92 0xFFCA4AE4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT93 0xFFCA4AEC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT94 0xFFCA4AF4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT95 0xFFCA4AFC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT96 0xFFCA4B04 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT97 0xFFCA4B0C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT98 0xFFCA4B14 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT99 0xFFCA4B1C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT100 0xFFCA4B24 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT101 0xFFCA4B2C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT102 0xFFCA4B34 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT103 0xFFCA4B3C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT104 0xFFCA4B44 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT105 0xFFCA4B4C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT106 0xFFCA4B54 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT107 0xFFCA4B5C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT108 0xFFCA4B64 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT109 0xFFCA4B6C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT110 0xFFCA4B74 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT111 0xFFCA4B7C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT112 0xFFCA4B84 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT113 0xFFCA4B8C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT114 0xFFCA4B94 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT115 0xFFCA4B9C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT116 0xFFCA4BA4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT117 0xFFCA4BAC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT118 0xFFCA4BB4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT119 0xFFCA4BBC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT120 0xFFCA4BC4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT121 0xFFCA4BCC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT122 0xFFCA4BD4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT123 0xFFCA4BDC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT124 0xFFCA4BE4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT125 0xFFCA4BEC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT126 0xFFCA4BF4 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT127 0xFFCA4BFC /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT128 0xFFCA4C04 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT129 0xFFCA4C0C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT130 0xFFCA4C14 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT131 0xFFCA4C1C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT132 0xFFCA4C24 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT133 0xFFCA4C2C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT134 0xFFCA4C34 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT135 0xFFCA4C3C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT136 0xFFCA4C44 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT137 0xFFCA4C4C /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT138 0xFFCA4C54 /* SEC IRQ Source Status Register n */
+#define SEC_SSTAT139 0xFFCA4C5C /* SEC IRQ Source Status Register n */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_CCTL Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_CCTL_LOCK 0x80000000 /* LOCK: Lock */
+#define SEC_CCTL_NMI_EN 0x00010000 /* NMIEN: Enable */
+#define SEC_CCTL_WAITIDLE 0x00001000 /* WFI: Wait for Idle */
+#define SEC_CCTL_RESET 0x00000002 /* RESET: Reset */
+#define SEC_CCTL_EN 0x00000001 /* EN: Enable */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_CSTAT Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_CSTAT_NMI 0x00010000 /* NMI Status */
+#define SEC_CSTAT_WAITING 0x00001000 /* WFI: Waiting */
+#define SEC_CSTAT_VALID_SID 0x00000400 /* SIDV: Valid */
+#define SEC_CSTAT_VALID_ACT 0x00000200 /* ACTV: Valid */
+#define SEC_CSTAT_VALID_PND 0x00000100 /* PNDV: Valid */
+#define SEC_CSTAT_ERRC 0x00000030 /* Error Cause */
+#define SEC_CSTAT_ACKERR 0x00000010 /* ERRC: Acknowledge Error */
+#define SEC_CSTAT_ERR 0x00000002 /* ERR: Error Occurred */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_CPND Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_CPND_PRIO 0x0000FF00 /* Highest Pending IRQ Priority */
+#define SEC_CPND_SID 0x000000FF /* Highest Pending IRQ Source ID */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_CACT Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_CACT_PRIO 0x0000FF00 /* Highest Active IRQ Priority */
+#define SEC_CACT_SID 0x000000FF /* Highest Active IRQ Source ID */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_CPMSK Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_CPMSK_LOCK 0x80000000 /* LOCK: Lock */
+#define SEC_CPMSK_PRIO 0x000000FF /* IRQ Priority Mask */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_CGMSK Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_CGMSK_LOCK 0x80000000 /* LOCK: Lock */
+#define SEC_CGMSK_MASK 0x00000100 /* UGRP: Mask Ungrouped Sources */
+#define SEC_CGMSK_GRP 0x0000000F /* Grouped Mask */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_CPLVL Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_CPLVL_LOCK 0x80000000 /* LOCK: Lock */
+#define SEC_CPLVL_PLVL 0x00000007 /* Priority Levels */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_CSID Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_CSID_SID 0x000000FF /* Source ID */
+
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_FCTL Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_FCTL_LOCK 0x80000000 /* LOCK: Lock */
+#define SEC_FCTL_FLTPND_MODE 0x00002000 /* TES: Fault Pending Mode */
+#define SEC_FCTL_COP_MODE 0x00001000 /* CMS: COP Mode */
+#define SEC_FCTL_FLTIN_EN 0x00000080 /* FIEN: Enable */
+#define SEC_FCTL_SYSRST_EN 0x00000040 /* SREN: Enable */
+#define SEC_FCTL_TRGOUT_EN 0x00000020 /* TOEN: Enable */
+#define SEC_FCTL_FLTOUT_EN 0x00000010 /* FOEN: Enable */
+#define SEC_FCTL_RESET 0x00000002 /* RESET: Reset */
+#define SEC_FCTL_EN 0x00000001 /* EN: Enable */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_FSTAT Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_FSTAT_NXTFLT 0x00000400 /* NPND: Pending */
+#define SEC_FSTAT_FLTACT 0x00000200 /* ACT: Active Fault */
+#define SEC_FSTAT_FLTPND 0x00000100 /* PND: Pending */
+#define SEC_FSTAT_ERRC 0x00000030 /* Error Cause */
+#define SEC_FSTAT_ENDERR 0x00000020 /* ERRC: End Error */
+#define SEC_FSTAT_ERR 0x00000002 /* ERR: Error Occurred */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_FSID Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_FSID_SRC_EXTFLT 0x00010000 /* FEXT: Fault External */
+#define SEC_FSID_SID 0x000000FF /* Source ID */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_FEND Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_FEND_END_EXTFLT 0x00010000 /* FEXT: Fault External */
+#define SEC_FEND_SID 0x000000FF /* Source ID */
+
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_GCTL Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_GCTL_LOCK 0x80000000 /* Lock */
+#define SEC_GCTL_RESET 0x00000002 /* Reset */
+#define SEC_GCTL_EN 0x00000001 /* Enable */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_GSTAT Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_GSTAT_LWERR 0x80000000 /* LWERR: Error Occurred */
+#define SEC_GSTAT_ADRERR 0x40000000 /* ADRERR: Error Occurred */
+#define SEC_GSTAT_SID 0x00FF0000 /* Source ID for SSI Error */
+#define SEC_GSTAT_SCI 0x00000F00 /* SCI ID for SCI Error */
+#define SEC_GSTAT_ERRC 0x00000030 /* Error Cause */
+#define SEC_GSTAT_SCIERR 0x00000010 /* ERRC: SCI Error */
+#define SEC_GSTAT_SSIERR 0x00000020 /* ERRC: SSI Error */
+#define SEC_GSTAT_ERR 0x00000002 /* ERR: Error Occurred */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_RAISE Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_RAISE_SID 0x000000FF /* Source ID IRQ Set to Pending */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_END Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_END_SID 0x000000FF /* Source ID IRQ to End */
+
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_SCTL Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_SCTL_LOCK 0x80000000 /* Lock */
+#define SEC_SCTL_CTG 0x0F000000 /* Core Target Select */
+#define SEC_SCTL_GRP 0x000F0000 /* Group Select */
+#define SEC_SCTL_PRIO 0x0000FF00 /* Priority Level Select */
+#define SEC_SCTL_ERR_EN 0x00000010 /* ERREN: Enable */
+#define SEC_SCTL_EDGE 0x00000008 /* ES: Edge Sensitive */
+#define SEC_SCTL_SRC_EN 0x00000004 /* SEN: Enable */
+#define SEC_SCTL_FAULT_EN 0x00000002 /* FEN: Enable */
+#define SEC_SCTL_INT_EN 0x00000001 /* IEN: Enable */
+
+/* ------------------------------------------------------------------------------------------------------------------------
+ SEC_SSTAT Pos/Masks Description
+ ------------------------------------------------------------------------------------------------------------------------ */
+#define SEC_SSTAT_CHID 0x00FF0000 /* Channel ID */
+#define SEC_SSTAT_ACTIVE_SRC 0x00000200 /* ACT: Active Source */
+#define SEC_SSTAT_PENDING 0x00000100 /* PND: Pending */
+#define SEC_SSTAT_ERRC 0x00000030 /* Error Cause */
+#define SEC_SSTAT_ENDERR 0x00000020 /* ERRC: End Error */
+#define SEC_SSTAT_ERR 0x00000002 /* Error */
+
+
+/* =========================
+ RCU Registers
+ ========================= */
+
+/* =========================
+ RCU0
+ ========================= */
+#define RCU0_CTL 0xFFCA6000 /* RCU0 Control Register */
+#define RCU0_STAT 0xFFCA6004 /* RCU0 Status Register */
+#define RCU0_CRCTL 0xFFCA6008 /* RCU0 Core Reset Control Register */
+#define RCU0_CRSTAT 0xFFCA600C /* RCU0 Core Reset Status Register */
+#define RCU0_SIDIS 0xFFCA6010 /* RCU0 System Interface Disable Register */
+#define RCU0_SISTAT 0xFFCA6014 /* RCU0 System Interface Status Register */
+#define RCU0_SVECT_LCK 0xFFCA6018 /* RCU0 SVECT Lock Register */
+#define RCU0_BCODE 0xFFCA601C /* RCU0 Boot Code Register */
+#define RCU0_SVECT0 0xFFCA6020 /* RCU0 Software Vector Register n */
+#define RCU0_SVECT1 0xFFCA6024 /* RCU0 Software Vector Register n */
+
+
+/* =========================
+ CGU0
+ ========================= */
+#define CGU0_CTL 0xFFCA8000 /* CGU0 Control Register */
+#define CGU0_STAT 0xFFCA8004 /* CGU0 Status Register */
+#define CGU0_DIV 0xFFCA8008 /* CGU0 Divisor Register */
+#define CGU0_CLKOUTSEL 0xFFCA800C /* CGU0 CLKOUT Select Register */
+
+
+/* =========================
+ DPM Registers
+ ========================= */
+
+/* =========================
+ DPM0
+ ========================= */
+#define DPM0_CTL 0xFFCA9000 /* DPM0 Control Register */
+#define DPM0_STAT 0xFFCA9004 /* DPM0 Status Register */
+#define DPM0_CCBF_DIS 0xFFCA9008 /* DPM0 Core Clock Buffer Disable Register */
+#define DPM0_CCBF_EN 0xFFCA900C /* DPM0 Core Clock Buffer Enable Register */
+#define DPM0_CCBF_STAT 0xFFCA9010 /* DPM0 Core Clock Buffer Status Register */
+#define DPM0_CCBF_STAT_STKY 0xFFCA9014 /* DPM0 Core Clock Buffer Status Sticky Register */
+#define DPM0_SCBF_DIS 0xFFCA9018 /* DPM0 System Clock Buffer Disable Register */
+#define DPM0_WAKE_EN 0xFFCA901C /* DPM0 Wakeup Enable Register */
+#define DPM0_WAKE_POL 0xFFCA9020 /* DPM0 Wakeup Polarity Register */
+#define DPM0_WAKE_STAT 0xFFCA9024 /* DPM0 Wakeup Status Register */
+#define DPM0_HIB_DIS 0xFFCA9028 /* DPM0 Hibernate Disable Register */
+#define DPM0_PGCNTR 0xFFCA902C /* DPM0 Power Good Counter Register */
+#define DPM0_RESTORE0 0xFFCA9030 /* DPM0 Restore Register */
+#define DPM0_RESTORE1 0xFFCA9034 /* DPM0 Restore Register */
+#define DPM0_RESTORE2 0xFFCA9038 /* DPM0 Restore Register */
+#define DPM0_RESTORE3 0xFFCA903C /* DPM0 Restore Register */
+#define DPM0_RESTORE4 0xFFCA9040 /* DPM0 Restore Register */
+#define DPM0_RESTORE5 0xFFCA9044 /* DPM0 Restore Register */
+#define DPM0_RESTORE6 0xFFCA9048 /* DPM0 Restore Register */
+#define DPM0_RESTORE7 0xFFCA904C /* DPM0 Restore Register */
+#define DPM0_RESTORE8 0xFFCA9050 /* DPM0 Restore Register */
+#define DPM0_RESTORE9 0xFFCA9054 /* DPM0 Restore Register */
+#define DPM0_RESTORE10 0xFFCA9058 /* DPM0 Restore Register */
+#define DPM0_RESTORE11 0xFFCA905C /* DPM0 Restore Register */
+#define DPM0_RESTORE12 0xFFCA9060 /* DPM0 Restore Register */
+#define DPM0_RESTORE13 0xFFCA9064 /* DPM0 Restore Register */
+#define DPM0_RESTORE14 0xFFCA9068 /* DPM0 Restore Register */
+#define DPM0_RESTORE15 0xFFCA906C /* DPM0 Restore Register */
+
+
+/* =========================
+ DBG Registers
+ ========================= */
+
+/* USB register */
+#define USB_FADDR 0xFFCC1000 /* USB Device Address in Peripheral Mode */
+#define USB_POWER 0xFFCC1001 /* USB Power and Device Control */
+#define USB_INTRTX 0xFFCC1002 /* USB Transmit Interrupt */
+#define USB_INTRRX 0xFFCC1004 /* USB Receive Interrupts */
+#define USB_INTRTXE 0xFFCC1006 /* USB Transmit Interrupt Enable */
+#define USB_INTRRXE 0xFFCC1008 /* USB Receive Interrupt Enable */
+#define USB_INTRUSB 0xFFCC100A /* USB USB Interrupts */
+#define USB_INTRUSBE 0xFFCC100B /* USB USB Interrupt Enable */
+#define USB_FRAME 0xFFCC100C /* USB Frame Number */
+#define USB_INDEX 0xFFCC100E /* USB Index */
+#define USB_TESTMODE 0xFFCC100F /* USB Testmodes */
+#define USB_EPI_TXMAXP0 0xFFCC1010 /* USB Transmit Maximum Packet Length */
+#define USB_EP_NI0_TXMAXP 0xFFCC1010
+#define USB_EP0I_CSR0_H 0xFFCC1012 /* USB Config and Status EP0 */
+#define USB_EPI_TXCSR0_H 0xFFCC1012 /* USB Transmit Configuration and Status */
+#define USB_EP0I_CSR0_P 0xFFCC1012 /* USB Config and Status EP0 */
+#define USB_EPI_TXCSR0_P 0xFFCC1012 /* USB Transmit Configuration and Status */
+#define USB_EPI_RXMAXP0 0xFFCC1014 /* USB Receive Maximum Packet Length */
+#define USB_EPI_RXCSR0_H 0xFFCC1016 /* USB Receive Configuration and Status Register */
+#define USB_EPI_RXCSR0_P 0xFFCC1016 /* USB Receive Configuration and Status Register */
+#define USB_EP0I_CNT0 0xFFCC1018 /* USB Number of Received Bytes for Endpoint 0 */
+#define USB_EPI_RXCNT0 0xFFCC1018 /* USB Number of Byte Received */
+#define USB_EP0I_TYPE0 0xFFCC101A /* USB Speed for Endpoint 0 */
+#define USB_EPI_TXTYPE0 0xFFCC101A /* USB Transmit Type */
+#define USB_EP0I_NAKLIMIT0 0xFFCC101B /* USB NAK Response Timeout for Endpoint 0 */
+#define USB_EPI_TXINTERVAL0 0xFFCC101B /* USB Transmit Polling Interval */
+#define USB_EPI_RXTYPE0 0xFFCC101C /* USB Receive Type */
+#define USB_EPI_RXINTERVAL0 0xFFCC101D /* USB Receive Polling Interval */
+#define USB_EP0I_CFGDATA0 0xFFCC101F /* USB Configuration Information */
+#define USB_FIFOB0 0xFFCC1020 /* USB FIFO Data */
+#define USB_FIFOB1 0xFFCC1024 /* USB FIFO Data */
+#define USB_FIFOB2 0xFFCC1028 /* USB FIFO Data */
+#define USB_FIFOB3 0xFFCC102C /* USB FIFO Data */
+#define USB_FIFOB4 0xFFCC1030 /* USB FIFO Data */
+#define USB_FIFOB5 0xFFCC1034 /* USB FIFO Data */
+#define USB_FIFOB6 0xFFCC1038 /* USB FIFO Data */
+#define USB_FIFOB7 0xFFCC103C /* USB FIFO Data */
+#define USB_FIFOB8 0xFFCC1040 /* USB FIFO Data */
+#define USB_FIFOB9 0xFFCC1044 /* USB FIFO Data */
+#define USB_FIFOB10 0xFFCC1048 /* USB FIFO Data */
+#define USB_FIFOB11 0xFFCC104C /* USB FIFO Data */
+#define USB_FIFOH0 0xFFCC1020 /* USB FIFO Data */
+#define USB_FIFOH1 0xFFCC1024 /* USB FIFO Data */
+#define USB_FIFOH2 0xFFCC1028 /* USB FIFO Data */
+#define USB_FIFOH3 0xFFCC102C /* USB FIFO Data */
+#define USB_FIFOH4 0xFFCC1030 /* USB FIFO Data */
+#define USB_FIFOH5 0xFFCC1034 /* USB FIFO Data */
+#define USB_FIFOH6 0xFFCC1038 /* USB FIFO Data */
+#define USB_FIFOH7 0xFFCC103C /* USB FIFO Data */
+#define USB_FIFOH8 0xFFCC1040 /* USB FIFO Data */
+#define USB_FIFOH9 0xFFCC1044 /* USB FIFO Data */
+#define USB_FIFOH10 0xFFCC1048 /* USB FIFO Data */
+#define USB_FIFOH11 0xFFCC104C /* USB FIFO Data */
+#define USB_FIFO0 0xFFCC1020 /* USB FIFO Data */
+#define USB_EP0_FIFO 0xFFCC1020
+#define USB_FIFO1 0xFFCC1024 /* USB FIFO Data */
+#define USB_FIFO2 0xFFCC1028 /* USB FIFO Data */
+#define USB_FIFO3 0xFFCC102C /* USB FIFO Data */
+#define USB_FIFO4 0xFFCC1030 /* USB FIFO Data */
+#define USB_FIFO5 0xFFCC1034 /* USB FIFO Data */
+#define USB_FIFO6 0xFFCC1038 /* USB FIFO Data */
+#define USB_FIFO7 0xFFCC103C /* USB FIFO Data */
+#define USB_FIFO8 0xFFCC1040 /* USB FIFO Data */
+#define USB_FIFO9 0xFFCC1044 /* USB FIFO Data */
+#define USB_FIFO10 0xFFCC1048 /* USB FIFO Data */
+#define USB_FIFO11 0xFFCC104C /* USB FIFO Data */
+#define USB_OTG_DEV_CTL 0xFFCC1060 /* USB Device Control */
+#define USB_TXFIFOSZ 0xFFCC1062 /* USB Transmit FIFO Size */
+#define USB_RXFIFOSZ 0xFFCC1063 /* USB Receive FIFO Size */
+#define USB_TXFIFOADDR 0xFFCC1064 /* USB Transmit FIFO Address */
+#define USB_RXFIFOADDR 0xFFCC1066 /* USB Receive FIFO Address */
+#define USB_VENDSTAT 0xFFCC1068 /* USB Vendor Status */
+#define USB_HWVERS 0xFFCC106C /* USB Hardware Version */
+#define USB_EPINFO 0xFFCC1078 /* USB Endpoint Info */
+#define USB_RAMINFO 0xFFCC1079 /* USB Ram Information */
+#define USB_LINKINFO 0xFFCC107A /* USB Programmable Delay Values */
+#define USB_VPLEN 0xFFCC107B /* USB VBus Pulse Duration */
+#define USB_HS_EOF1 0xFFCC107C /* USB High Speed End of Frame Remaining */
+#define USB_FS_EOF1 0xFFCC107D /* USB Full Speed End of Frame Remaining */
+#define USB_LS_EOF1 0xFFCC107E /* USB Low Speed End of Frame Remaining */
+#define USB_SOFT_RST 0xFFCC107F /* USB Software Reset */
+#define USB_TXFUNCADDR0 0xFFCC1080 /* USB Transmit Function Address */
+#define USB_TXFUNCADDR1 0xFFCC1088 /* USB Transmit Function Address */
+#define USB_TXFUNCADDR2 0xFFCC1090 /* USB Transmit Function Address */
+#define USB_TXFUNCADDR3 0xFFCC1098 /* USB Transmit Function Address */
+#define USB_TXFUNCADDR4 0xFFCC10A0 /* USB Transmit Function Address */
+#define USB_TXFUNCADDR5 0xFFCC10A8 /* USB Transmit Function Address */
+#define USB_TXFUNCADDR6 0xFFCC10B0 /* USB Transmit Function Address */
+#define USB_TXFUNCADDR7 0xFFCC10B8 /* USB Transmit Function Address */
+#define USB_TXFUNCADDR8 0xFFCC10C0 /* USB Transmit Function Address */
+#define USB_TXFUNCADDR9 0xFFCC10C8 /* USB Transmit Function Address */
+#define USB_TXFUNCADDR10 0xFFCC10D0 /* USB Transmit Function Address */
+#define USB_TXFUNCADDR11 0xFFCC10D8 /* USB Transmit Function Address */
+#define USB_TXHUBADDR0 0xFFCC1082 /* USB Transmit Hub Address */
+#define USB_TXHUBADDR1 0xFFCC108A /* USB Transmit Hub Address */
+#define USB_TXHUBADDR2 0xFFCC1092 /* USB Transmit Hub Address */
+#define USB_TXHUBADDR3 0xFFCC109A /* USB Transmit Hub Address */
+#define USB_TXHUBADDR4 0xFFCC10A2 /* USB Transmit Hub Address */
+#define USB_TXHUBADDR5 0xFFCC10AA /* USB Transmit Hub Address */
+#define USB_TXHUBADDR6 0xFFCC10B2 /* USB Transmit Hub Address */
+#define USB_TXHUBADDR7 0xFFCC10BA /* USB Transmit Hub Address */
+#define USB_TXHUBADDR8 0xFFCC10C2 /* USB Transmit Hub Address */
+#define USB_TXHUBADDR9 0xFFCC10CA /* USB Transmit Hub Address */
+#define USB_TXHUBADDR10 0xFFCC10D2 /* USB Transmit Hub Address */
+#define USB_TXHUBADDR11 0xFFCC10DA /* USB Transmit Hub Address */
+#define USB_TXHUBPORT0 0xFFCC1083 /* USB Transmit Hub Port */
+#define USB_TXHUBPORT1 0xFFCC108B /* USB Transmit Hub Port */
+#define USB_TXHUBPORT2 0xFFCC1093 /* USB Transmit Hub Port */
+#define USB_TXHUBPORT3 0xFFCC109B /* USB Transmit Hub Port */
+#define USB_TXHUBPORT4 0xFFCC10A3 /* USB Transmit Hub Port */
+#define USB_TXHUBPORT5 0xFFCC10AB /* USB Transmit Hub Port */
+#define USB_TXHUBPORT6 0xFFCC10B3 /* USB Transmit Hub Port */
+#define USB_TXHUBPORT7 0xFFCC10BB /* USB Transmit Hub Port */
+#define USB_TXHUBPORT8 0xFFCC10C3 /* USB Transmit Hub Port */
+#define USB_TXHUBPORT9 0xFFCC10CB /* USB Transmit Hub Port */
+#define USB_TXHUBPORT10 0xFFCC10D3 /* USB Transmit Hub Port */
+#define USB_TXHUBPORT11 0xFFCC10DB /* USB Transmit Hub Port */
+#define USB_RXFUNCADDR0 0xFFCC1084 /* USB Receive Function Address */
+#define USB_RXFUNCADDR1 0xFFCC108C /* USB Receive Function Address */
+#define USB_RXFUNCADDR2 0xFFCC1094 /* USB Receive Function Address */
+#define USB_RXFUNCADDR3 0xFFCC109C /* USB Receive Function Address */
+#define USB_RXFUNCADDR4 0xFFCC10A4 /* USB Receive Function Address */
+#define USB_RXFUNCADDR5 0xFFCC10AC /* USB Receive Function Address */
+#define USB_RXFUNCADDR6 0xFFCC10B4 /* USB Receive Function Address */
+#define USB_RXFUNCADDR7 0xFFCC10BC /* USB Receive Function Address */
+#define USB_RXFUNCADDR8 0xFFCC10C4 /* USB Receive Function Address */
+#define USB_RXFUNCADDR9 0xFFCC10CC /* USB Receive Function Address */
+#define USB_RXFUNCADDR10 0xFFCC10D4 /* USB Receive Function Address */
+#define USB_RXFUNCADDR11 0xFFCC10DC /* USB Receive Function Address */
+#define USB_RXHUBADDR0 0xFFCC1086 /* USB Receive Hub Address */
+#define USB_RXHUBADDR1 0xFFCC108E /* USB Receive Hub Address */
+#define USB_RXHUBADDR2 0xFFCC1096 /* USB Receive Hub Address */
+#define USB_RXHUBADDR3 0xFFCC109E /* USB Receive Hub Address */
+#define USB_RXHUBADDR4 0xFFCC10A6 /* USB Receive Hub Address */
+#define USB_RXHUBADDR5 0xFFCC10AE /* USB Receive Hub Address */
+#define USB_RXHUBADDR6 0xFFCC10B6 /* USB Receive Hub Address */
+#define USB_RXHUBADDR7 0xFFCC10BE /* USB Receive Hub Address */
+#define USB_RXHUBADDR8 0xFFCC10C6 /* USB Receive Hub Address */
+#define USB_RXHUBADDR9 0xFFCC10CE /* USB Receive Hub Address */
+#define USB_RXHUBADDR10 0xFFCC10D6 /* USB Receive Hub Address */
+#define USB_RXHUBADDR11 0xFFCC10DE /* USB Receive Hub Address */
+#define USB_RXHUBPORT0 0xFFCC1087 /* USB Receive Hub Port */
+#define USB_RXHUBPORT1 0xFFCC108F /* USB Receive Hub Port */
+#define USB_RXHUBPORT2 0xFFCC1097 /* USB Receive Hub Port */
+#define USB_RXHUBPORT3 0xFFCC109F /* USB Receive Hub Port */
+#define USB_RXHUBPORT4 0xFFCC10A7 /* USB Receive Hub Port */
+#define USB_RXHUBPORT5 0xFFCC10AF /* USB Receive Hub Port */
+#define USB_RXHUBPORT6 0xFFCC10B7 /* USB Receive Hub Port */
+#define USB_RXHUBPORT7 0xFFCC10BF /* USB Receive Hub Port */
+#define USB_RXHUBPORT8 0xFFCC10C7 /* USB Receive Hub Port */
+#define USB_RXHUBPORT9 0xFFCC10CF /* USB Receive Hub Port */
+#define USB_RXHUBPORT10 0xFFCC10D7 /* USB Receive Hub Port */
+#define USB_RXHUBPORT11 0xFFCC10DF /* USB Receive Hub Port */
+#define USB_EP0_CSR0_H 0xFFCC1102 /* USB Config and Status EP0 */
+#define USB_EP0_CSR0_P 0xFFCC1102 /* USB Config and Status EP0 */
+#define USB_EP0_CNT0 0xFFCC1108 /* USB Number of Received Bytes for Endpoint 0 */
+#define USB_EP0_TYPE0 0xFFCC110A /* USB Speed for Endpoint 0 */
+#define USB_EP0_NAKLIMIT0 0xFFCC110B /* USB NAK Response Timeout for Endpoint 0 */
+#define USB_EP0_CFGDATA0 0xFFCC110F /* USB Configuration Information */
+#define USB_EP_TXMAXP0 0xFFCC1110 /* USB Transmit Maximum Packet Length */
+#define USB_EP_TXMAXP1 0xFFCC1120 /* USB Transmit Maximum Packet Length */
+#define USB_EP_TXMAXP2 0xFFCC1130 /* USB Transmit Maximum Packet Length */
+#define USB_EP_TXMAXP3 0xFFCC1140 /* USB Transmit Maximum Packet Length */
+#define USB_EP_TXMAXP4 0xFFCC1150 /* USB Transmit Maximum Packet Length */
+#define USB_EP_TXMAXP5 0xFFCC1160 /* USB Transmit Maximum Packet Length */
+#define USB_EP_TXMAXP6 0xFFCC1170 /* USB Transmit Maximum Packet Length */
+#define USB_EP_TXMAXP7 0xFFCC1180 /* USB Transmit Maximum Packet Length */
+#define USB_EP_TXMAXP8 0xFFCC1190 /* USB Transmit Maximum Packet Length */
+#define USB_EP_TXMAXP9 0xFFCC11A0 /* USB Transmit Maximum Packet Length */
+#define USB_EP_TXMAXP10 0xFFCC11B0 /* USB Transmit Maximum Packet Length */
+#define USB_EP_TXCSR0_H 0xFFCC1112 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR1_H 0xFFCC1122 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR2_H 0xFFCC1132 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR3_H 0xFFCC1142 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR4_H 0xFFCC1152 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR5_H 0xFFCC1162 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR6_H 0xFFCC1172 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR7_H 0xFFCC1182 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR8_H 0xFFCC1192 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR9_H 0xFFCC11A2 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR10_H 0xFFCC11B2 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR0_P 0xFFCC1112 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR1_P 0xFFCC1122 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR2_P 0xFFCC1132 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR3_P 0xFFCC1142 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR4_P 0xFFCC1152 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR5_P 0xFFCC1162 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR6_P 0xFFCC1172 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR7_P 0xFFCC1182 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR8_P 0xFFCC1192 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR9_P 0xFFCC11A2 /* USB Transmit Configuration and Status */
+#define USB_EP_TXCSR10_P 0xFFCC11B2 /* USB Transmit Configuration and Status */
+#define USB_EP_RXMAXP0 0xFFCC1114 /* USB Receive Maximum Packet Length */
+#define USB_EP_RXMAXP1 0xFFCC1124 /* USB Receive Maximum Packet Length */
+#define USB_EP_RXMAXP2 0xFFCC1134 /* USB Receive Maximum Packet Length */
+#define USB_EP_RXMAXP3 0xFFCC1144 /* USB Receive Maximum Packet Length */
+#define USB_EP_RXMAXP4 0xFFCC1154 /* USB Receive Maximum Packet Length */
+#define USB_EP_RXMAXP5 0xFFCC1164 /* USB Receive Maximum Packet Length */
+#define USB_EP_RXMAXP6 0xFFCC1174 /* USB Receive Maximum Packet Length */
+#define USB_EP_RXMAXP7 0xFFCC1184 /* USB Receive Maximum Packet Length */
+#define USB_EP_RXMAXP8 0xFFCC1194 /* USB Receive Maximum Packet Length */
+#define USB_EP_RXMAXP9 0xFFCC11A4 /* USB Receive Maximum Packet Length */
+#define USB_EP_RXMAXP10 0xFFCC11B4 /* USB Receive Maximum Packet Length */
+#define USB_EP_RXCSR0_H 0xFFCC1116 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR1_H 0xFFCC1126 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR2_H 0xFFCC1136 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR3_H 0xFFCC1146 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR4_H 0xFFCC1156 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR5_H 0xFFCC1166 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR6_H 0xFFCC1176 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR7_H 0xFFCC1186 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR8_H 0xFFCC1196 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR9_H 0xFFCC11A6 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR10_H 0xFFCC11B6 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR0_P 0xFFCC1116 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR1_P 0xFFCC1126 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR2_P 0xFFCC1136 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR3_P 0xFFCC1146 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR4_P 0xFFCC1156 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR5_P 0xFFCC1166 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR6_P 0xFFCC1176 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR7_P 0xFFCC1186 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR8_P 0xFFCC1196 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR9_P 0xFFCC11A6 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCSR10_P 0xFFCC11B6 /* USB Receive Configuration and Status Register */
+#define USB_EP_RXCNT0 0xFFCC1118 /* USB Number of Byte Received */
+#define USB_EP_RXCNT1 0xFFCC1128 /* USB Number of Byte Received */
+#define USB_EP_RXCNT2 0xFFCC1138 /* USB Number of Byte Received */
+#define USB_EP_RXCNT3 0xFFCC1148 /* USB Number of Byte Received */
+#define USB_EP_RXCNT4 0xFFCC1158 /* USB Number of Byte Received */
+#define USB_EP_RXCNT5 0xFFCC1168 /* USB Number of Byte Received */
+#define USB_EP_RXCNT6 0xFFCC1178 /* USB Number of Byte Received */
+#define USB_EP_RXCNT7 0xFFCC1188 /* USB Number of Byte Received */
+#define USB_EP_RXCNT8 0xFFCC1198 /* USB Number of Byte Received */
+#define USB_EP_RXCNT9 0xFFCC11A8 /* USB Number of Byte Received */
+#define USB_EP_RXCNT10 0xFFCC11B8 /* USB Number of Byte Received */
+#define USB_EP_TXTYPE0 0xFFCC111A /* USB Transmit Type */
+#define USB_EP_TXTYPE1 0xFFCC112A /* USB Transmit Type */
+#define USB_EP_TXTYPE2 0xFFCC113A /* USB Transmit Type */
+#define USB_EP_TXTYPE3 0xFFCC114A /* USB Transmit Type */
+#define USB_EP_TXTYPE4 0xFFCC115A /* USB Transmit Type */
+#define USB_EP_TXTYPE5 0xFFCC116A /* USB Transmit Type */
+#define USB_EP_TXTYPE6 0xFFCC117A /* USB Transmit Type */
+#define USB_EP_TXTYPE7 0xFFCC118A /* USB Transmit Type */
+#define USB_EP_TXTYPE8 0xFFCC119A /* USB Transmit Type */
+#define USB_EP_TXTYPE9 0xFFCC11AA /* USB Transmit Type */
+#define USB_EP_TXTYPE10 0xFFCC11BA /* USB Transmit Type */
+#define USB_EP_TXINTERVAL0 0xFFCC111B /* USB Transmit Polling Interval */
+#define USB_EP_TXINTERVAL1 0xFFCC112B /* USB Transmit Polling Interval */
+#define USB_EP_TXINTERVAL2 0xFFCC113B /* USB Transmit Polling Interval */
+#define USB_EP_TXINTERVAL3 0xFFCC114B /* USB Transmit Polling Interval */
+#define USB_EP_TXINTERVAL4 0xFFCC115B /* USB Transmit Polling Interval */
+#define USB_EP_TXINTERVAL5 0xFFCC116B /* USB Transmit Polling Interval */
+#define USB_EP_TXINTERVAL6 0xFFCC117B /* USB Transmit Polling Interval */
+#define USB_EP_TXINTERVAL7 0xFFCC118B /* USB Transmit Polling Interval */
+#define USB_EP_TXINTERVAL8 0xFFCC119B /* USB Transmit Polling Interval */
+#define USB_EP_TXINTERVAL9 0xFFCC11AB /* USB Transmit Polling Interval */
+#define USB_EP_TXINTERVAL10 0xFFCC11BB /* USB Transmit Polling Interval */
+#define USB_EP_RXTYPE0 0xFFCC111C /* USB Receive Type */
+#define USB_EP_RXTYPE1 0xFFCC112C /* USB Receive Type */
+#define USB_EP_RXTYPE2 0xFFCC113C /* USB Receive Type */
+#define USB_EP_RXTYPE3 0xFFCC114C /* USB Receive Type */
+#define USB_EP_RXTYPE4 0xFFCC115C /* USB Receive Type */
+#define USB_EP_RXTYPE5 0xFFCC116C /* USB Receive Type */
+#define USB_EP_RXTYPE6 0xFFCC117C /* USB Receive Type */
+#define USB_EP_RXTYPE7 0xFFCC118C /* USB Receive Type */
+#define USB_EP_RXTYPE8 0xFFCC119C /* USB Receive Type */
+#define USB_EP_RXTYPE9 0xFFCC11AC /* USB Receive Type */
+#define USB_EP_RXTYPE10 0xFFCC11BC /* USB Receive Type */
+#define USB_EP_RXINTERVAL0 0xFFCC111D /* USB Receive Polling Interval */
+#define USB_EP_RXINTERVAL1 0xFFCC112D /* USB Receive Polling Interval */
+#define USB_EP_RXINTERVAL2 0xFFCC113D /* USB Receive Polling Interval */
+#define USB_EP_RXINTERVAL3 0xFFCC114D /* USB Receive Polling Interval */
+#define USB_EP_RXINTERVAL4 0xFFCC115D /* USB Receive Polling Interval */
+#define USB_EP_RXINTERVAL5 0xFFCC116D /* USB Receive Polling Interval */
+#define USB_EP_RXINTERVAL6 0xFFCC117D /* USB Receive Polling Interval */
+#define USB_EP_RXINTERVAL7 0xFFCC118D /* USB Receive Polling Interval */
+#define USB_EP_RXINTERVAL8 0xFFCC119D /* USB Receive Polling Interval */
+#define USB_EP_RXINTERVAL9 0xFFCC11AD /* USB Receive Polling Interval */
+#define USB_EP_RXINTERVAL10 0xFFCC11BD /* USB Receive Polling Interval */
+#define USB_DMA_IRQ 0xFFCC1200 /* USB Interrupt Register */
+#define USB_DMA_CTL0 0xFFCC1204 /* USB DMA Control */
+#define USB_DMA_CTL1 0xFFCC1214 /* USB DMA Control */
+#define USB_DMA_CTL2 0xFFCC1224 /* USB DMA Control */
+#define USB_DMA_CTL3 0xFFCC1234 /* USB DMA Control */
+#define USB_DMA_CTL4 0xFFCC1244 /* USB DMA Control */
+#define USB_DMA_CTL5 0xFFCC1254 /* USB DMA Control */
+#define USB_DMA_CTL6 0xFFCC1264 /* USB DMA Control */
+#define USB_DMA_CTL7 0xFFCC1274 /* USB DMA Control */
+#define USB_DMA_ADDR0 0xFFCC1208 /* USB DMA Address */
+#define USB_DMA_ADDR1 0xFFCC1218 /* USB DMA Address */
+#define USB_DMA_ADDR2 0xFFCC1228 /* USB DMA Address */
+#define USB_DMA_ADDR3 0xFFCC1238 /* USB DMA Address */
+#define USB_DMA_ADDR4 0xFFCC1248 /* USB DMA Address */
+#define USB_DMA_ADDR5 0xFFCC1258 /* USB DMA Address */
+#define USB_DMA_ADDR6 0xFFCC1268 /* USB DMA Address */
+#define USB_DMA_ADDR7 0xFFCC1278 /* USB DMA Address */
+#define USB_DMA_CNT0 0xFFCC120C /* USB DMA Count */
+#define USB_DMA_CNT1 0xFFCC121C /* USB DMA Count */
+#define USB_DMA_CNT2 0xFFCC122C /* USB DMA Count */
+#define USB_DMA_CNT3 0xFFCC123C /* USB DMA Count */
+#define USB_DMA_CNT4 0xFFCC124C /* USB DMA Count */
+#define USB_DMA_CNT5 0xFFCC125C /* USB DMA Count */
+#define USB_DMA_CNT6 0xFFCC126C /* USB DMA Count */
+#define USB_DMA_CNT7 0xFFCC127C /* USB DMA Count */
+#define USB_RQPKTCNT0 0xFFCC1300 /* USB Request Packet Count */
+#define USB_RQPKTCNT1 0xFFCC1304 /* USB Request Packet Count */
+#define USB_RQPKTCNT2 0xFFCC1308 /* USB Request Packet Count */
+#define USB_RQPKTCNT3 0xFFCC130C /* USB Request Packet Count */
+#define USB_RQPKTCNT4 0xFFCC1310 /* USB Request Packet Count */
+#define USB_RQPKTCNT5 0xFFCC1314 /* USB Request Packet Count */
+#define USB_RQPKTCNT6 0xFFCC1318 /* USB Request Packet Count */
+#define USB_RQPKTCNT7 0xFFCC131C /* USB Request Packet Count */
+#define USB_RQPKTCNT8 0xFFCC1320 /* USB Request Packet Count */
+#define USB_RQPKTCNT9 0xFFCC1324 /* USB Request Packet Count */
+#define USB_RQPKTCNT10 0xFFCC1328 /* USB Request Packet Count */
+#define USB_CT_UCH 0xFFCC1344 /* USB Chirp Timeout */
+#define USB_CT_HHSRTN 0xFFCC1346 /* USB High Speed Resume Return to Normal */
+#define USB_CT_HSBT 0xFFCC1348 /* USB High Speed Timeout */
+#define USB_LPM_ATTR 0xFFCC1360 /* USB LPM Attribute */
+#define USB_LPM_CTL 0xFFCC1362 /* USB LPM Control */
+#define USB_LPM_IEN 0xFFCC1363 /* USB LPM Interrupt Enable */
+#define USB_LPM_IRQ 0xFFCC1364 /* USB LPM Interrupt */
+#define USB_LPM_FADDR 0xFFCC1365 /* USB LPM Function Address */
+#define USB_VBUS_CTL 0xFFCC1380 /* USB VBus Control */
+#define USB_BAT_CHG 0xFFCC1381 /* USB Battery Charging */
+#define USB_PHY_CTL 0xFFCC1394 /* USB PHY Control */
+#define USB_TESTCTL 0xFFCC1397 /* USB Test Control */
+#define USB_PLL_OSC 0xFFCC1398 /* USB PLL and Oscillator Control */
+
+
+
+/* =========================
+ CHIPID
+ ========================= */
+
+#define CHIPID 0xffc00014
+/* CHIPID Masks */
+#define CHIPID_VERSION 0xF0000000
+#define CHIPID_FAMILY 0x0FFFF000
+#define CHIPID_MANUFACTURE 0x00000FFE
+
+
+#endif /* _DEF_BF60X_H */
diff --git a/arch/blackfin/mach-bf609/include/mach/dma.h b/arch/blackfin/mach-bf609/include/mach/dma.h
new file mode 100644
index 000000000000..872d141ca119
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/dma.h
@@ -0,0 +1,116 @@
+/* mach/dma.h - arch-specific DMA defines
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_DMA_H_
+#define _MACH_DMA_H_
+
+#define CH_SPORT0_TX 0
+#define CH_SPORT0_RX 1
+#define CH_SPORT1_TX 2
+#define CH_SPORT1_RX 3
+#define CH_SPORT2_TX 4
+#define CH_SPORT2_RX 5
+#define CH_SPI0_TX 6
+#define CH_SPI0_RX 7
+#define CH_SPI1_TX 8
+#define CH_SPI1_RX 9
+#define CH_RSI 10
+#define CH_SDU 11
+#define CH_LP0 13
+#define CH_LP1 14
+#define CH_LP2 15
+#define CH_LP3 16
+#define CH_UART0_TX 17
+#define CH_UART0_RX 18
+#define CH_UART1_TX 19
+#define CH_UART1_RX 20
+#define CH_MEM_STREAM0_SRC_CRC0 21
+#define CH_MEM_STREAM0_SRC CH_MEM_STREAM0_SRC_CRC0
+#define CH_MEM_STREAM0_DEST_CRC0 22
+#define CH_MEM_STREAM0_DEST CH_MEM_STREAM0_DEST_CRC0
+#define CH_MEM_STREAM1_SRC_CRC1 23
+#define CH_MEM_STREAM1_SRC CH_MEM_STREAM1_SRC_CRC1
+#define CH_MEM_STREAM1_DEST_CRC1 24
+#define CH_MEM_STREAM1_DEST CH_MEM_STREAM1_DEST_CRC1
+#define CH_MEM_STREAM2_SRC 25
+#define CH_MEM_STREAM2_DEST 26
+#define CH_MEM_STREAM3_SRC 27
+#define CH_MEM_STREAM3_DEST 28
+#define CH_EPPI0_CH0 29
+#define CH_EPPI0_CH1 30
+#define CH_EPPI1_CH0 31
+#define CH_EPPI1_CH1 32
+#define CH_EPPI2_CH0 33
+#define CH_EPPI2_CH1 34
+#define CH_PIXC_CH0 35
+#define CH_PIXC_CH1 36
+#define CH_PIXC_CH2 37
+#define CH_PVP_CPDOB 38
+#define CH_PVP_CPDOC 39
+#define CH_PVP_CPSTAT 40
+#define CH_PVP_CPCI 41
+#define CH_PVP_MPDO 42
+#define CH_PVP_MPDI 43
+#define CH_PVP_MPSTAT 44
+#define CH_PVP_MPCI 45
+#define CH_PVP_CPDOA 46
+
+#define MAX_DMA_CHANNELS 47
+#define MAX_DMA_SUSPEND_CHANNELS 0
+#define DMA_MMR_SIZE_32
+
+#define bfin_read_MDMA_S0_CONFIG bfin_read_MDMA0_SRC_CRC0_CONFIG
+#define bfin_write_MDMA_S0_CONFIG bfin_write_MDMA0_SRC_CRC0_CONFIG
+#define bfin_read_MDMA_S0_IRQ_STATUS bfin_read_MDMA0_SRC_CRC0_IRQ_STATUS
+#define bfin_write_MDMA_S0_IRQ_STATUS bfin_write_MDMA0_SRC_CRC0_IRQ_STATUS
+#define bfin_write_MDMA_S0_START_ADDR bfin_write_MDMA0_SRC_CRC0_START_ADDR
+#define bfin_write_MDMA_S0_X_COUNT bfin_write_MDMA0_SRC_CRC0_X_COUNT
+#define bfin_write_MDMA_S0_X_MODIFY bfin_write_MDMA0_SRC_CRC0_X_MODIFY
+#define bfin_write_MDMA_S0_Y_COUNT bfin_write_MDMA0_SRC_CRC0_Y_COUNT
+#define bfin_write_MDMA_S0_Y_MODIFY bfin_write_MDMA0_SRC_CRC0_Y_MODIFY
+#define bfin_read_MDMA_D0_CONFIG bfin_read_MDMA0_DEST_CRC0_CONFIG
+#define bfin_write_MDMA_D0_CONFIG bfin_write_MDMA0_DEST_CRC0_CONFIG
+#define bfin_read_MDMA_D0_IRQ_STATUS bfin_read_MDMA0_DEST_CRC0_IRQ_STATUS
+#define bfin_write_MDMA_D0_IRQ_STATUS bfin_write_MDMA0_DEST_CRC0_IRQ_STATUS
+#define bfin_write_MDMA_D0_START_ADDR bfin_write_MDMA0_DEST_CRC0_START_ADDR
+#define bfin_write_MDMA_D0_X_COUNT bfin_write_MDMA0_DEST_CRC0_X_COUNT
+#define bfin_write_MDMA_D0_X_MODIFY bfin_write_MDMA0_DEST_CRC0_X_MODIFY
+#define bfin_write_MDMA_D0_Y_COUNT bfin_write_MDMA0_DEST_CRC0_Y_COUNT
+#define bfin_write_MDMA_D0_Y_MODIFY bfin_write_MDMA0_DEST_CRC0_Y_MODIFY
+
+#define bfin_read_MDMA_S1_CONFIG bfin_read_MDMA1_SRC_CRC1_CONFIG
+#define bfin_write_MDMA_S1_CONFIG bfin_write_MDMA1_SRC_CRC1_CONFIG
+#define bfin_read_MDMA_D1_CONFIG bfin_read_MDMA1_DEST_CRC1_CONFIG
+#define bfin_write_MDMA_D1_CONFIG bfin_write_MDMA1_DEST_CRC1_CONFIG
+#define bfin_read_MDMA_D1_IRQ_STATUS bfin_read_MDMA1_DEST_CRC1_IRQ_STATUS
+#define bfin_write_MDMA_D1_IRQ_STATUS bfin_write_MDMA1_DEST_CRC1_IRQ_STATUS
+
+#define bfin_read_MDMA_S3_CONFIG bfin_read_MDMA3_SRC_CONFIG
+#define bfin_write_MDMA_S3_CONFIG bfin_write_MDMA3_SRC_CONFIG
+#define bfin_read_MDMA_S3_IRQ_STATUS bfin_read_MDMA3_SRC_IRQ_STATUS
+#define bfin_write_MDMA_S3_IRQ_STATUS bfin_write_MDMA3_SRC_IRQ_STATUS
+#define bfin_write_MDMA_S3_START_ADDR bfin_write_MDMA3_SRC_START_ADDR
+#define bfin_write_MDMA_S3_X_COUNT bfin_write_MDMA3_SRC_X_COUNT
+#define bfin_write_MDMA_S3_X_MODIFY bfin_write_MDMA3_SRC_X_MODIFY
+#define bfin_write_MDMA_S3_Y_COUNT bfin_write_MDMA3_SRC_Y_COUNT
+#define bfin_write_MDMA_S3_Y_MODIFY bfin_write_MDMA3_SRC_Y_MODIFY
+#define bfin_read_MDMA_D3_CONFIG bfin_read_MDMA3_DEST_CONFIG
+#define bfin_write_MDMA_D3_CONFIG bfin_write_MDMA3_DEST_CONFIG
+#define bfin_read_MDMA_D3_IRQ_STATUS bfin_read_MDMA3_DEST_IRQ_STATUS
+#define bfin_write_MDMA_D3_IRQ_STATUS bfin_write_MDMA3_DEST_IRQ_STATUS
+#define bfin_write_MDMA_D3_START_ADDR bfin_write_MDMA3_DEST_START_ADDR
+#define bfin_write_MDMA_D3_X_COUNT bfin_write_MDMA3_DEST_X_COUNT
+#define bfin_write_MDMA_D3_X_MODIFY bfin_write_MDMA3_DEST_X_MODIFY
+#define bfin_write_MDMA_D3_Y_COUNT bfin_write_MDMA3_DEST_Y_COUNT
+#define bfin_write_MDMA_D3_Y_MODIFY bfin_write_MDMA3_DEST_Y_MODIFY
+
+#define MDMA_S0_NEXT_DESC_PTR MDMA0_SRC_CRC0_NEXT_DESC_PTR
+#define MDMA_D0_NEXT_DESC_PTR MDMA0_DEST_CRC0_NEXT_DESC_PTR
+#define MDMA_S1_NEXT_DESC_PTR MDMA1_SRC_CRC1_NEXT_DESC_PTR
+#define MDMA_D1_NEXT_DESC_PTR MDMA1_DEST_CRC1_NEXT_DESC_PTR
+
+#endif
diff --git a/arch/blackfin/mach-bf609/include/mach/gpio.h b/arch/blackfin/mach-bf609/include/mach/gpio.h
new file mode 100644
index 000000000000..127586b1e04a
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/gpio.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2007-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_GPIO_H_
+#define _MACH_GPIO_H_
+
+#define MAX_BLACKFIN_GPIOS 112
+
+#define GPIO_PA0 0
+#define GPIO_PA1 1
+#define GPIO_PA2 2
+#define GPIO_PA3 3
+#define GPIO_PA4 4
+#define GPIO_PA5 5
+#define GPIO_PA6 6
+#define GPIO_PA7 7
+#define GPIO_PA8 8
+#define GPIO_PA9 9
+#define GPIO_PA10 10
+#define GPIO_PA11 11
+#define GPIO_PA12 12
+#define GPIO_PA13 13
+#define GPIO_PA14 14
+#define GPIO_PA15 15
+#define GPIO_PB0 16
+#define GPIO_PB1 17
+#define GPIO_PB2 18
+#define GPIO_PB3 19
+#define GPIO_PB4 20
+#define GPIO_PB5 21
+#define GPIO_PB6 22
+#define GPIO_PB7 23
+#define GPIO_PB8 24
+#define GPIO_PB9 25
+#define GPIO_PB10 26
+#define GPIO_PB11 27
+#define GPIO_PB12 28
+#define GPIO_PB13 29
+#define GPIO_PB14 30
+#define GPIO_PB15 31
+#define GPIO_PC0 32
+#define GPIO_PC1 33
+#define GPIO_PC2 34
+#define GPIO_PC3 35
+#define GPIO_PC4 36
+#define GPIO_PC5 37
+#define GPIO_PC6 38
+#define GPIO_PC7 39
+#define GPIO_PC8 40
+#define GPIO_PC9 41
+#define GPIO_PC10 42
+#define GPIO_PC11 43
+#define GPIO_PC12 44
+#define GPIO_PC13 45
+#define GPIO_PC14 46
+#define GPIO_PC15 47
+#define GPIO_PD0 48
+#define GPIO_PD1 49
+#define GPIO_PD2 50
+#define GPIO_PD3 51
+#define GPIO_PD4 52
+#define GPIO_PD5 53
+#define GPIO_PD6 54
+#define GPIO_PD7 55
+#define GPIO_PD8 56
+#define GPIO_PD9 57
+#define GPIO_PD10 58
+#define GPIO_PD11 59
+#define GPIO_PD12 60
+#define GPIO_PD13 61
+#define GPIO_PD14 62
+#define GPIO_PD15 63
+#define GPIO_PE0 64
+#define GPIO_PE1 65
+#define GPIO_PE2 66
+#define GPIO_PE3 67
+#define GPIO_PE4 68
+#define GPIO_PE5 69
+#define GPIO_PE6 70
+#define GPIO_PE7 71
+#define GPIO_PE8 72
+#define GPIO_PE9 73
+#define GPIO_PE10 74
+#define GPIO_PE11 75
+#define GPIO_PE12 76
+#define GPIO_PE13 77
+#define GPIO_PE14 78
+#define GPIO_PE15 79
+#define GPIO_PF0 80
+#define GPIO_PF1 81
+#define GPIO_PF2 82
+#define GPIO_PF3 83
+#define GPIO_PF4 84
+#define GPIO_PF5 85
+#define GPIO_PF6 86
+#define GPIO_PF7 87
+#define GPIO_PF8 88
+#define GPIO_PF9 89
+#define GPIO_PF10 90
+#define GPIO_PF11 91
+#define GPIO_PF12 92
+#define GPIO_PF13 93
+#define GPIO_PF14 94
+#define GPIO_PF15 95
+#define GPIO_PG0 96
+#define GPIO_PG1 97
+#define GPIO_PG2 98
+#define GPIO_PG3 99
+#define GPIO_PG4 100
+#define GPIO_PG5 101
+#define GPIO_PG6 102
+#define GPIO_PG7 103
+#define GPIO_PG8 104
+#define GPIO_PG9 105
+#define GPIO_PG10 106
+#define GPIO_PG11 107
+#define GPIO_PG12 108
+#define GPIO_PG13 109
+#define GPIO_PG14 110
+#define GPIO_PG15 111
+
+
+#define BFIN_GPIO_PINT 1
+
+
+#ifndef __ASSEMBLY__
+
+struct gpio_port_t {
+ unsigned long port_fer;
+ unsigned long port_fer_set;
+ unsigned long port_fer_clear;
+ unsigned long data;
+ unsigned long data_set;
+ unsigned long data_clear;
+ unsigned long dir;
+ unsigned long dir_set;
+ unsigned long dir_clear;
+ unsigned long inen;
+ unsigned long inen_set;
+ unsigned long inen_clear;
+ unsigned long port_mux;
+ unsigned long toggle;
+ unsigned long polar;
+ unsigned long polar_set;
+ unsigned long polar_clear;
+ unsigned long lock;
+ unsigned long spare;
+ unsigned long revid;
+};
+
+struct gpio_port_s {
+ unsigned short fer;
+ unsigned short data;
+ unsigned short dir;
+ unsigned short inen;
+ unsigned int mux;
+};
+
+#endif
+
+#include <mach-common/ports-a.h>
+#include <mach-common/ports-b.h>
+#include <mach-common/ports-c.h>
+#include <mach-common/ports-d.h>
+#include <mach-common/ports-e.h>
+#include <mach-common/ports-f.h>
+#include <mach-common/ports-g.h>
+
+#endif /* _MACH_GPIO_H_ */
diff --git a/arch/blackfin/mach-bf609/include/mach/irq.h b/arch/blackfin/mach-bf609/include/mach/irq.h
new file mode 100644
index 000000000000..0004552433b2
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/irq.h
@@ -0,0 +1,318 @@
+/*
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _BF60x_IRQ_H_
+#define _BF60x_IRQ_H_
+
+#include <mach-common/irq.h>
+
+#undef BFIN_IRQ
+#define BFIN_IRQ(x) ((x) + IVG15)
+
+#define NR_PERI_INTS (5 * 32)
+
+#define IRQ_SEC_ERR BFIN_IRQ(0) /* SEC Error */
+#define IRQ_CGU_EVT BFIN_IRQ(1) /* CGU Event */
+#define IRQ_WATCH0 BFIN_IRQ(2) /* Watchdog0 Interrupt */
+#define IRQ_WATCH1 BFIN_IRQ(3) /* Watchdog1 Interrupt */
+#define IRQ_L2CTL0_ECC_ERR BFIN_IRQ(4) /* L2 ECC Error */
+#define IRQ_L2CTL0_ECC_WARN BFIN_IRQ(5) /* L2 ECC Waring */
+#define IRQ_C0_DBL_FAULT BFIN_IRQ(6) /* Core 0 Double Fault */
+#define IRQ_C1_DBL_FAULT BFIN_IRQ(7) /* Core 1 Double Fault */
+#define IRQ_C0_HW_ERR BFIN_IRQ(8) /* Core 0 Hardware Error */
+#define IRQ_C1_HW_ERR BFIN_IRQ(9) /* Core 1 Hardware Error */
+#define IRQ_C0_NMI_L1_PARITY_ERR BFIN_IRQ(10) /* Core 0 Unhandled NMI or L1 Memory Parity Error */
+#define IRQ_C1_NMI_L1_PARITY_ERR BFIN_IRQ(11) /* Core 1 Unhandled NMI or L1 Memory Parity Error */
+#define CORE_IRQS (IRQ_C1_NMI_L1_PARITY_ERR + 1)
+
+#define IRQ_TIMER0 BFIN_IRQ(12) /* Timer 0 Interrupt */
+#define IRQ_TIMER1 BFIN_IRQ(13) /* Timer 1 Interrupt */
+#define IRQ_TIMER2 BFIN_IRQ(14) /* Timer 2 Interrupt */
+#define IRQ_TIMER3 BFIN_IRQ(15) /* Timer 3 Interrupt */
+#define IRQ_TIMER4 BFIN_IRQ(16) /* Timer 4 Interrupt */
+#define IRQ_TIMER5 BFIN_IRQ(17) /* Timer 5 Interrupt */
+#define IRQ_TIMER6 BFIN_IRQ(18) /* Timer 6 Interrupt */
+#define IRQ_TIMER7 BFIN_IRQ(19) /* Timer 7 Interrupt */
+#define IRQ_TIMER_STAT BFIN_IRQ(20) /* Timer Block Status */
+#define IRQ_PINT0 BFIN_IRQ(21) /* PINT0 Interrupt */
+#define IRQ_PINT1 BFIN_IRQ(22) /* PINT1 Interrupt */
+#define IRQ_PINT2 BFIN_IRQ(23) /* PINT2 Interrupt */
+#define IRQ_PINT3 BFIN_IRQ(24) /* PINT3 Interrupt */
+#define IRQ_PINT4 BFIN_IRQ(25) /* PINT4 Interrupt */
+#define IRQ_PINT5 BFIN_IRQ(26) /* PINT5 Interrupt */
+#define IRQ_CNT BFIN_IRQ(27) /* CNT Interrupt */
+#define IRQ_PWM0_TRIP BFIN_IRQ(28) /* PWM0 Trip Interrupt */
+#define IRQ_PWM0_SYNC BFIN_IRQ(29) /* PWM0 Sync Interrupt */
+#define IRQ_PWM1_TRIP BFIN_IRQ(30) /* PWM1 Trip Interrupt */
+#define IRQ_PWM1_SYNC BFIN_IRQ(31) /* PWM1 Sync Interrupt */
+#define IRQ_TWI0 BFIN_IRQ(32) /* TWI0 Interrupt */
+#define IRQ_TWI1 BFIN_IRQ(33) /* TWI1 Interrupt */
+#define IRQ_SOFT0 BFIN_IRQ(34) /* Software-Driven Interrupt 0 */
+#define IRQ_SOFT1 BFIN_IRQ(35) /* Software-Driven Interrupt 1 */
+#define IRQ_SOFT2 BFIN_IRQ(36) /* Software-Driven Interrupt 2 */
+#define IRQ_SOFT3 BFIN_IRQ(37) /* Software-Driven Interrupt 3 */
+#define IRQ_ACM_EVT_MISS BFIN_IRQ(38) /* ACM Event Miss */
+#define IRQ_ACM_EVT_COMPLETE BFIN_IRQ(39) /* ACM Event Complete */
+#define IRQ_CAN0_RX BFIN_IRQ(40) /* CAN0 Receive Interrupt */
+#define IRQ_CAN0_TX BFIN_IRQ(41) /* CAN0 Transmit Interrupt */
+#define IRQ_CAN0_STAT BFIN_IRQ(42) /* CAN0 Status */
+#define IRQ_SPORT0_TX BFIN_IRQ(43) /* SPORT0 TX Interrupt (DMA0) */
+#define IRQ_SPORT0_TX_STAT BFIN_IRQ(44) /* SPORT0 TX Status Interrupt */
+#define IRQ_SPORT0_RX BFIN_IRQ(45) /* SPORT0 RX Interrupt (DMA1) */
+#define IRQ_SPORT0_RX_STAT BFIN_IRQ(46) /* SPORT0 RX Status Interrupt */
+#define IRQ_SPORT1_TX BFIN_IRQ(47) /* SPORT1 TX Interrupt (DMA2) */
+#define IRQ_SPORT1_TX_STAT BFIN_IRQ(48) /* SPORT1 TX Status Interrupt */
+#define IRQ_SPORT1_RX BFIN_IRQ(49) /* SPORT1 RX Interrupt (DMA3) */
+#define IRQ_SPORT1_RX_STAT BFIN_IRQ(50) /* SPORT1 RX Status Interrupt */
+#define IRQ_SPORT2_TX BFIN_IRQ(51) /* SPORT2 TX Interrupt (DMA4) */
+#define IRQ_SPORT2_TX_STAT BFIN_IRQ(52) /* SPORT2 TX Status Interrupt */
+#define IRQ_SPORT2_RX BFIN_IRQ(53) /* SPORT2 RX Interrupt (DMA5) */
+#define IRQ_SPORT2_RX_STAT BFIN_IRQ(54) /* SPORT2 RX Status Interrupt */
+#define IRQ_SPI0_TX BFIN_IRQ(55) /* SPI0 TX Interrupt (DMA6) */
+#define IRQ_SPI0_RX BFIN_IRQ(56) /* SPI0 RX Interrupt (DMA7) */
+#define IRQ_SPI0_STAT BFIN_IRQ(57) /* SPI0 Status Interrupt */
+#define IRQ_SPI1_TX BFIN_IRQ(58) /* SPI1 TX Interrupt (DMA8) */
+#define IRQ_SPI1_RX BFIN_IRQ(59) /* SPI1 RX Interrupt (DMA9) */
+#define IRQ_SPI1_STAT BFIN_IRQ(60) /* SPI1 Status Interrupt */
+#define IRQ_RSI BFIN_IRQ(61) /* RSI (DMA10) Interrupt */
+#define IRQ_RSI_INT0 BFIN_IRQ(62) /* RSI Interrupt0 */
+#define IRQ_RSI_INT1 BFIN_IRQ(63) /* RSI Interrupt1 */
+#define IRQ_SDU BFIN_IRQ(64) /* DMA11 Data (SDU) */
+/* -- RESERVED -- 65 DMA12 Data (Reserved) */
+/* -- RESERVED -- 66 Reserved */
+/* -- RESERVED -- 67 Reserved */
+#define IRQ_EMAC0_STAT BFIN_IRQ(68) /* EMAC0 Status */
+/* -- RESERVED -- 69 EMAC0 Power (Reserved) */
+#define IRQ_EMAC1_STAT BFIN_IRQ(70) /* EMAC1 Status */
+/* -- RESERVED -- 71 EMAC1 Power (Reserved) */
+#define IRQ_LP0 BFIN_IRQ(72) /* DMA13 Data (Link Port 0) */
+#define IRQ_LP0_STAT BFIN_IRQ(73) /* Link Port 0 Status */
+#define IRQ_LP1 BFIN_IRQ(74) /* DMA14 Data (Link Port 1) */
+#define IRQ_LP1_STAT BFIN_IRQ(75) /* Link Port 1 Status */
+#define IRQ_LP2 BFIN_IRQ(76) /* DMA15 Data (Link Port 2) */
+#define IRQ_LP2_STAT BFIN_IRQ(77) /* Link Port 2 Status */
+#define IRQ_LP3 BFIN_IRQ(78) /* DMA16 Data(Link Port 3) */
+#define IRQ_LP3_STAT BFIN_IRQ(79) /* Link Port 3 Status */
+#define IRQ_UART0_TX BFIN_IRQ(80) /* UART0 TX Interrupt (DMA17) */
+#define IRQ_UART0_RX BFIN_IRQ(81) /* UART0 RX Interrupt (DMA18) */
+#define IRQ_UART0_STAT BFIN_IRQ(82) /* UART0 Status(Error) Interrupt */
+#define IRQ_UART1_TX BFIN_IRQ(83) /* UART1 TX Interrupt (DMA19) */
+#define IRQ_UART1_RX BFIN_IRQ(84) /* UART1 RX Interrupt (DMA20) */
+#define IRQ_UART1_STAT BFIN_IRQ(85) /* UART1 Status(Error) Interrupt */
+#define IRQ_MDMA0_SRC_CRC0 BFIN_IRQ(86) /* DMA21 Data (MDMA Stream 0 Source/CRC0 Input Channel) */
+#define IRQ_MDMA0_DEST_CRC0 BFIN_IRQ(87) /* DMA22 Data (MDMA Stream 0 Destination/CRC0 Output Channel) */
+#define IRQ_MDMAS0 IRQ_MDMA0_DEST_CRC0
+#define IRQ_CRC0_DCNTEXP BFIN_IRQ(88) /* CRC0 DATACOUNT Expiration */
+#define IRQ_CRC0_ERR BFIN_IRQ(89) /* CRC0 Error */
+#define IRQ_MDMA1_SRC_CRC1 BFIN_IRQ(90) /* DMA23 Data (MDMA Stream 1 Source/CRC1 Input Channel) */
+#define IRQ_MDMA1_DEST_CRC1 BFIN_IRQ(91) /* DMA24 Data (MDMA Stream 1 Destination/CRC1 Output Channel) */
+#define IRQ_MDMAS1 IRQ_MDMA1_DEST_CRC1
+#define IRQ_CRC1_DCNTEXP BFIN_IRQ(92) /* CRC1 DATACOUNT Expiration */
+#define IRQ_CRC1_ERR BFIN_IRQ(93) /* CRC1 Error */
+#define IRQ_MDMA2_SRC BFIN_IRQ(94) /* DMA25 Data (MDMA Stream 2 Source Channel) */
+#define IRQ_MDMA2_DEST BFIN_IRQ(95) /* DMA26 Data (MDMA Stream 2 Destination Channel) */
+#define IRQ_MDMAS2 IRQ_MDMA2_DEST
+#define IRQ_MDMA3_SRC BFIN_IRQ(96) /* DMA27 Data (MDMA Stream 3 Source Channel) */
+#define IRQ_MDMA3_DEST BFIN_IRQ(97) /* DMA28 Data (MDMA Stream 3 Destination Channel) */
+#define IRQ_MDMAS3 IRQ_MDMA3_DEST
+#define IRQ_EPPI0_CH0 BFIN_IRQ(98) /* DMA29 Data (EPPI0 Channel 0) */
+#define IRQ_EPPI0_CH1 BFIN_IRQ(99) /* DMA30 Data (EPPI0 Channel 1) */
+#define IRQ_EPPI0_STAT BFIN_IRQ(100) /* EPPI0 Status */
+#define IRQ_EPPI2_CH0 BFIN_IRQ(101) /* DMA31 Data (EPPI2 Channel 0) */
+#define IRQ_EPPI2_CH1 BFIN_IRQ(102) /* DMA32 Data (EPPI2 Channel 1) */
+#define IRQ_EPPI2_STAT BFIN_IRQ(103) /* EPPI2 Status */
+#define IRQ_EPPI1_CH0 BFIN_IRQ(104) /* DMA33 Data (EPPI1 Channel 0) */
+#define IRQ_EPPI1_CH1 BFIN_IRQ(105) /* DMA34 Data (EPPI1 Channel 1) */
+#define IRQ_EPPI1_STAT BFIN_IRQ(106) /* EPPI1 Status */
+#define IRQ_PIXC_CH0 BFIN_IRQ(107) /* DMA35 Data (PIXC Channel 0) */
+#define IRQ_PIXC_CH1 BFIN_IRQ(108) /* DMA36 Data (PIXC Channel 1) */
+#define IRQ_PIXC_CH2 BFIN_IRQ(109) /* DMA37 Data (PIXC Channel 2) */
+#define IRQ_PIXC_STAT BFIN_IRQ(110) /* PIXC Status */
+#define IRQ_PVP_CPDOB BFIN_IRQ(111) /* DMA38 Data (PVP0 Camera Pipe Data Out B) */
+#define IRQ_PVP_CPDOC BFIN_IRQ(112) /* DMA39 Data (PVP0 Camera Pipe Data Out C) */
+#define IRQ_PVP_CPSTAT BFIN_IRQ(113) /* DMA40 Data (PVP0 Camera Pipe Status Out) */
+#define IRQ_PVP_CPCI BFIN_IRQ(114) /* DMA41 Data (PVP0 Camera Pipe Control In) */
+#define IRQ_PVP_STAT0 BFIN_IRQ(115) /* PVP0 Status 0 */
+#define IRQ_PVP_MPDO BFIN_IRQ(116) /* DMA42 Data (PVP0 Memory Pipe Data Out) */
+#define IRQ_PVP_MPDI BFIN_IRQ(117) /* DMA43 Data (PVP0 Memory Pipe Data In) */
+#define IRQ_PVP_MPSTAT BFIN_IRQ(118) /* DMA44 Data (PVP0 Memory Pipe Status Out) */
+#define IRQ_PVP_MPCI BFIN_IRQ(119) /* DMA45 Data (PVP0 Memory Pipe Control In) */
+#define IRQ_PVP_CPDOA BFIN_IRQ(120) /* DMA46 Data (PVP0 Camera Pipe Data Out A) */
+#define IRQ_PVP_STAT1 BFIN_IRQ(121) /* PVP0 Status 1 */
+#define IRQ_USB_STAT BFIN_IRQ(122) /* USB Status Interrupt */
+#define IRQ_USB_DMA BFIN_IRQ(123) /* USB DMA Interrupt */
+#define IRQ_TRU_INT0 BFIN_IRQ(124) /* TRU0 Interrupt 0 */
+#define IRQ_TRU_INT1 BFIN_IRQ(125) /* TRU0 Interrupt 1 */
+#define IRQ_TRU_INT2 BFIN_IRQ(126) /* TRU0 Interrupt 2 */
+#define IRQ_TRU_INT3 BFIN_IRQ(127) /* TRU0 Interrupt 3 */
+#define IRQ_DMAC0_ERROR BFIN_IRQ(128) /* DMAC0 Status Interrupt */
+#define IRQ_CGU0_ERROR BFIN_IRQ(129) /* CGU0 Error */
+/* -- RESERVED -- 130 Reserved */
+#define IRQ_DPM BFIN_IRQ(131) /* DPM0 Event */
+/* -- RESERVED -- 132 Reserved */
+#define IRQ_SWU0 BFIN_IRQ(133) /* SWU0 */
+#define IRQ_SWU1 BFIN_IRQ(134) /* SWU1 */
+#define IRQ_SWU2 BFIN_IRQ(135) /* SWU2 */
+#define IRQ_SWU3 BFIN_IRQ(136) /* SWU3 */
+#define IRQ_SWU4 BFIN_IRQ(137) /* SWU4 */
+#define IRQ_SWU5 BFIN_IRQ(138) /* SWU5 */
+#define IRQ_SWU6 BFIN_IRQ(139) /* SWU6 */
+
+#define SYS_IRQS IRQ_SWU6
+
+#define BFIN_PA_IRQ(x) ((x) + SYS_IRQS + 1)
+#define IRQ_PA0 BFIN_PA_IRQ(0)
+#define IRQ_PA1 BFIN_PA_IRQ(1)
+#define IRQ_PA2 BFIN_PA_IRQ(2)
+#define IRQ_PA3 BFIN_PA_IRQ(3)
+#define IRQ_PA4 BFIN_PA_IRQ(4)
+#define IRQ_PA5 BFIN_PA_IRQ(5)
+#define IRQ_PA6 BFIN_PA_IRQ(6)
+#define IRQ_PA7 BFIN_PA_IRQ(7)
+#define IRQ_PA8 BFIN_PA_IRQ(8)
+#define IRQ_PA9 BFIN_PA_IRQ(9)
+#define IRQ_PA10 BFIN_PA_IRQ(10)
+#define IRQ_PA11 BFIN_PA_IRQ(11)
+#define IRQ_PA12 BFIN_PA_IRQ(12)
+#define IRQ_PA13 BFIN_PA_IRQ(13)
+#define IRQ_PA14 BFIN_PA_IRQ(14)
+#define IRQ_PA15 BFIN_PA_IRQ(15)
+
+#define BFIN_PB_IRQ(x) ((x) + IRQ_PA15 + 1)
+#define IRQ_PB0 BFIN_PB_IRQ(0)
+#define IRQ_PB1 BFIN_PB_IRQ(1)
+#define IRQ_PB2 BFIN_PB_IRQ(2)
+#define IRQ_PB3 BFIN_PB_IRQ(3)
+#define IRQ_PB4 BFIN_PB_IRQ(4)
+#define IRQ_PB5 BFIN_PB_IRQ(5)
+#define IRQ_PB6 BFIN_PB_IRQ(6)
+#define IRQ_PB7 BFIN_PB_IRQ(7)
+#define IRQ_PB8 BFIN_PB_IRQ(8)
+#define IRQ_PB9 BFIN_PB_IRQ(9)
+#define IRQ_PB10 BFIN_PB_IRQ(10)
+#define IRQ_PB11 BFIN_PB_IRQ(11)
+#define IRQ_PB12 BFIN_PB_IRQ(12)
+#define IRQ_PB13 BFIN_PB_IRQ(13)
+#define IRQ_PB14 BFIN_PB_IRQ(14)
+#define IRQ_PB15 BFIN_PB_IRQ(15) /* N/A */
+
+#define BFIN_PC_IRQ(x) ((x) + IRQ_PB15 + 1)
+#define IRQ_PC0 BFIN_PC_IRQ(0)
+#define IRQ_PC1 BFIN_PC_IRQ(1)
+#define IRQ_PC2 BFIN_PC_IRQ(2)
+#define IRQ_PC3 BFIN_PC_IRQ(3)
+#define IRQ_PC4 BFIN_PC_IRQ(4)
+#define IRQ_PC5 BFIN_PC_IRQ(5)
+#define IRQ_PC6 BFIN_PC_IRQ(6)
+#define IRQ_PC7 BFIN_PC_IRQ(7)
+#define IRQ_PC8 BFIN_PC_IRQ(8)
+#define IRQ_PC9 BFIN_PC_IRQ(9)
+#define IRQ_PC10 BFIN_PC_IRQ(10)
+#define IRQ_PC11 BFIN_PC_IRQ(11)
+#define IRQ_PC12 BFIN_PC_IRQ(12)
+#define IRQ_PC13 BFIN_PC_IRQ(13)
+#define IRQ_PC14 BFIN_PC_IRQ(14) /* N/A */
+#define IRQ_PC15 BFIN_PC_IRQ(15) /* N/A */
+
+#define BFIN_PD_IRQ(x) ((x) + IRQ_PC15 + 1)
+#define IRQ_PD0 BFIN_PD_IRQ(0)
+#define IRQ_PD1 BFIN_PD_IRQ(1)
+#define IRQ_PD2 BFIN_PD_IRQ(2)
+#define IRQ_PD3 BFIN_PD_IRQ(3)
+#define IRQ_PD4 BFIN_PD_IRQ(4)
+#define IRQ_PD5 BFIN_PD_IRQ(5)
+#define IRQ_PD6 BFIN_PD_IRQ(6)
+#define IRQ_PD7 BFIN_PD_IRQ(7)
+#define IRQ_PD8 BFIN_PD_IRQ(8)
+#define IRQ_PD9 BFIN_PD_IRQ(9)
+#define IRQ_PD10 BFIN_PD_IRQ(10)
+#define IRQ_PD11 BFIN_PD_IRQ(11)
+#define IRQ_PD12 BFIN_PD_IRQ(12)
+#define IRQ_PD13 BFIN_PD_IRQ(13)
+#define IRQ_PD14 BFIN_PD_IRQ(14)
+#define IRQ_PD15 BFIN_PD_IRQ(15)
+
+#define BFIN_PE_IRQ(x) ((x) + IRQ_PD15 + 1)
+#define IRQ_PE0 BFIN_PE_IRQ(0)
+#define IRQ_PE1 BFIN_PE_IRQ(1)
+#define IRQ_PE2 BFIN_PE_IRQ(2)
+#define IRQ_PE3 BFIN_PE_IRQ(3)
+#define IRQ_PE4 BFIN_PE_IRQ(4)
+#define IRQ_PE5 BFIN_PE_IRQ(5)
+#define IRQ_PE6 BFIN_PE_IRQ(6)
+#define IRQ_PE7 BFIN_PE_IRQ(7)
+#define IRQ_PE8 BFIN_PE_IRQ(8)
+#define IRQ_PE9 BFIN_PE_IRQ(9)
+#define IRQ_PE10 BFIN_PE_IRQ(10)
+#define IRQ_PE11 BFIN_PE_IRQ(11)
+#define IRQ_PE12 BFIN_PE_IRQ(12)
+#define IRQ_PE13 BFIN_PE_IRQ(13)
+#define IRQ_PE14 BFIN_PE_IRQ(14)
+#define IRQ_PE15 BFIN_PE_IRQ(15)
+
+#define BFIN_PF_IRQ(x) ((x) + IRQ_PE15 + 1)
+#define IRQ_PF0 BFIN_PF_IRQ(0)
+#define IRQ_PF1 BFIN_PF_IRQ(1)
+#define IRQ_PF2 BFIN_PF_IRQ(2)
+#define IRQ_PF3 BFIN_PF_IRQ(3)
+#define IRQ_PF4 BFIN_PF_IRQ(4)
+#define IRQ_PF5 BFIN_PF_IRQ(5)
+#define IRQ_PF6 BFIN_PF_IRQ(6)
+#define IRQ_PF7 BFIN_PF_IRQ(7)
+#define IRQ_PF8 BFIN_PF_IRQ(8)
+#define IRQ_PF9 BFIN_PF_IRQ(9)
+#define IRQ_PF10 BFIN_PF_IRQ(10)
+#define IRQ_PF11 BFIN_PF_IRQ(11)
+#define IRQ_PF12 BFIN_PF_IRQ(12)
+#define IRQ_PF13 BFIN_PF_IRQ(13)
+#define IRQ_PF14 BFIN_PF_IRQ(14)
+#define IRQ_PF15 BFIN_PF_IRQ(15)
+
+#define BFIN_PG_IRQ(x) ((x) + IRQ_PF15 + 1)
+#define IRQ_PG0 BFIN_PG_IRQ(0)
+#define IRQ_PG1 BFIN_PG_IRQ(1)
+#define IRQ_PG2 BFIN_PG_IRQ(2)
+#define IRQ_PG3 BFIN_PG_IRQ(3)
+#define IRQ_PG4 BFIN_PG_IRQ(4)
+#define IRQ_PG5 BFIN_PG_IRQ(5)
+#define IRQ_PG6 BFIN_PG_IRQ(6)
+#define IRQ_PG7 BFIN_PG_IRQ(7)
+#define IRQ_PG8 BFIN_PG_IRQ(8)
+#define IRQ_PG9 BFIN_PG_IRQ(9)
+#define IRQ_PG10 BFIN_PG_IRQ(10)
+#define IRQ_PG11 BFIN_PG_IRQ(11)
+#define IRQ_PG12 BFIN_PG_IRQ(12)
+#define IRQ_PG13 BFIN_PG_IRQ(13)
+#define IRQ_PG14 BFIN_PG_IRQ(14)
+#define IRQ_PG15 BFIN_PG_IRQ(15)
+
+#define GPIO_IRQ_BASE IRQ_PA0
+
+#define NR_MACH_IRQS (IRQ_PG15 + 1)
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+
+/*
+ * bfin pint registers layout
+ */
+struct bfin_pint_regs {
+ u32 mask_set;
+ u32 mask_clear;
+ u32 request;
+ u32 assign;
+ u32 edge_set;
+ u32 edge_clear;
+ u32 invert_set;
+ u32 invert_clear;
+ u32 pinstate;
+ u32 latch;
+ u32 __pad0[2];
+};
+
+#endif
+
+#endif
diff --git a/arch/blackfin/mach-bf609/include/mach/mem_map.h b/arch/blackfin/mach-bf609/include/mach/mem_map.h
new file mode 100644
index 000000000000..20b65bfc5311
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/mem_map.h
@@ -0,0 +1,86 @@
+/*
+ * BF60x memory map
+ *
+ * Copyright 2011 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_MACH_MEM_MAP_H__
+#define __BFIN_MACH_MEM_MAP_H__
+
+#ifndef __BFIN_MEM_MAP_H__
+# error "do not include mach/mem_map.h directly -- use asm/mem_map.h"
+#endif
+
+/* Async Memory Banks */
+#define ASYNC_BANK3_BASE 0xBC000000 /* Async Bank 3 */
+#define ASYNC_BANK3_SIZE 0x04000000 /* 64M */
+#define ASYNC_BANK2_BASE 0xB8000000 /* Async Bank 2 */
+#define ASYNC_BANK2_SIZE 0x04000000 /* 64M */
+#define ASYNC_BANK1_BASE 0xB4000000 /* Async Bank 1 */
+#define ASYNC_BANK1_SIZE 0x04000000 /* 64M */
+#define ASYNC_BANK0_BASE 0xB0000000 /* Async Bank 0 */
+#define ASYNC_BANK0_SIZE 0x04000000 /* 64M */
+
+/* Boot ROM Memory */
+
+#define BOOT_ROM_START 0xC8000000
+#define BOOT_ROM_LENGTH 0x8000
+
+/* Level 1 Memory */
+
+/* Memory Map for ADSP-BF60x processors */
+#ifdef CONFIG_BFIN_ICACHE
+#define BFIN_ICACHESIZE (16*1024)
+#define L1_CODE_LENGTH 0x10000
+#else
+#define BFIN_ICACHESIZE (0*1024)
+#define L1_CODE_LENGTH 0x14000
+#endif
+
+#define L1_CODE_START 0xFFA00000
+#define L1_DATA_A_START 0xFF800000
+#define L1_DATA_B_START 0xFF900000
+
+
+#define COREA_L1_SCRATCH_START 0xFFB00000
+#define COREB_L1_SCRATCH_START 0xFF700000
+
+#define COREB_L1_CODE_START 0xFF600000
+#define COREB_L1_DATA_A_START 0xFF400000
+#define COREB_L1_DATA_B_START 0xFF500000
+
+#define COREB_L1_CODE_LENGTH 0x14000
+#define COREB_L1_DATA_A_LENGTH 0x8000
+#define COREB_L1_DATA_B_LENGTH 0x8000
+
+
+#ifdef CONFIG_BFIN_DCACHE
+
+#ifdef CONFIG_BFIN_DCACHE_BANKA
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH 0x8000
+#define BFIN_DCACHESIZE (16*1024)
+#define BFIN_DSUPBANKS 1
+#else
+#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH (0x8000 - 0x4000)
+#define BFIN_DCACHESIZE (32*1024)
+#define BFIN_DSUPBANKS 2
+#endif
+
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH 0x8000
+#define L1_DATA_B_LENGTH 0x8000
+#define BFIN_DCACHESIZE (0*1024)
+#define BFIN_DSUPBANKS 0
+#endif /*CONFIG_BFIN_DCACHE*/
+
+/* Level 2 Memory */
+#define L2_START 0xC8080000
+#define L2_LENGTH 0x40000
+
+#endif
diff --git a/arch/blackfin/mach-bf609/include/mach/pll.h b/arch/blackfin/mach-bf609/include/mach/pll.h
new file mode 100644
index 000000000000..1857a4a0f262
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/pll.h
@@ -0,0 +1 @@
+/* #include <mach-common/pll.h> */
diff --git a/arch/blackfin/mach-bf609/include/mach/pm.h b/arch/blackfin/mach-bf609/include/mach/pm.h
new file mode 100644
index 000000000000..036d9bdc889e
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/pm.h
@@ -0,0 +1,21 @@
+/*
+ * Blackfin bf609 power management
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2
+ */
+
+#ifndef __MACH_BF609_PM_H__
+#define __MACH_BF609_PM_H__
+
+#include <linux/suspend.h>
+
+int bfin609_pm_enter(suspend_state_t state);
+int bf609_pm_prepare(void);
+void bf609_pm_finish(void);
+
+void bf609_hibernate(void);
+void bfin_sec_raise_irq(unsigned int sid);
+void coreb_enable(void);
+#endif
diff --git a/arch/blackfin/mach-bf609/include/mach/portmux.h b/arch/blackfin/mach-bf609/include/mach/portmux.h
new file mode 100644
index 000000000000..2e1a51c25098
--- /dev/null
+++ b/arch/blackfin/mach-bf609/include/mach/portmux.h
@@ -0,0 +1,347 @@
+/*
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define MAX_RESOURCES MAX_BLACKFIN_GPIOS
+
+/* EMAC RMII Port Mux */
+#define P_MII0_MDC (P_DEFINED | P_IDENT(GPIO_PC6) | P_FUNCT(0))
+#define P_MII0_MDIO (P_DEFINED | P_IDENT(GPIO_PC7) | P_FUNCT(0))
+#define P_MII0_ETxD0 (P_DEFINED | P_IDENT(GPIO_PC2) | P_FUNCT(0))
+#define P_MII0_ERxD0 (P_DEFINED | P_IDENT(GPIO_PC0) | P_FUNCT(0))
+#define P_MII0_ETxD1 (P_DEFINED | P_IDENT(GPIO_PC3) | P_FUNCT(0))
+#define P_MII0_ERxD1 (P_DEFINED | P_IDENT(GPIO_PC1) | P_FUNCT(0))
+#define P_MII0_ETxEN (P_DEFINED | P_IDENT(GPIO_PB13) | P_FUNCT(0))
+#define P_MII0_PHYINT (P_DEFINED | P_IDENT(GPIO_PD6) | P_FUNCT(0))
+#define P_MII0_CRS (P_DEFINED | P_IDENT(GPIO_PC5) | P_FUNCT(0))
+#define P_MII0_ERxER (P_DEFINED | P_IDENT(GPIO_PC4) | P_FUNCT(0))
+#define P_MII0_TxCLK (P_DEFINED | P_IDENT(GPIO_PB14) | P_FUNCT(0))
+
+#define P_RMII0 {\
+ P_MII0_ETxD0, \
+ P_MII0_ETxD1, \
+ P_MII0_ETxEN, \
+ P_MII0_ERxD0, \
+ P_MII0_ERxD1, \
+ P_MII0_ERxER, \
+ P_MII0_TxCLK, \
+ P_MII0_PHYINT, \
+ P_MII0_CRS, \
+ P_MII0_MDC, \
+ P_MII0_MDIO, 0}
+
+#define P_MII1_MDC (P_DEFINED | P_IDENT(GPIO_PE10) | P_FUNCT(0))
+#define P_MII1_MDIO (P_DEFINED | P_IDENT(GPIO_PE11) | P_FUNCT(0))
+#define P_MII1_ETxD0 (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(0))
+#define P_MII1_ERxD0 (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0))
+#define P_MII1_ETxD1 (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(0))
+#define P_MII1_ERxD1 (P_DEFINED | P_IDENT(GPIO_PE15) | P_FUNCT(0))
+#define P_MII1_ETxEN (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(0))
+#define P_MII1_PHYINT (P_DEFINED | P_IDENT(GPIO_PE12) | P_FUNCT(0))
+#define P_MII1_CRS (P_DEFINED | P_IDENT(GPIO_PE13) | P_FUNCT(0))
+#define P_MII1_ERxER (P_DEFINED | P_IDENT(GPIO_PE14) | P_FUNCT(0))
+#define P_MII1_TxCLK (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(0))
+
+#define P_RMII1 {\
+ P_MII1_ETxD0, \
+ P_MII1_ETxD1, \
+ P_MII1_ETxEN, \
+ P_MII1_ERxD0, \
+ P_MII1_ERxD1, \
+ P_MII1_ERxER, \
+ P_MII1_TxCLK, \
+ P_MII1_PHYINT, \
+ P_MII1_CRS, \
+ P_MII1_MDC, \
+ P_MII1_MDIO, 0}
+
+/* PPI Port Mux */
+#define P_PPI0_D0 (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(1))
+#define P_PPI0_D1 (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(1))
+#define P_PPI0_D2 (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(1))
+#define P_PPI0_D3 (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(1))
+#define P_PPI0_D4 (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(1))
+#define P_PPI0_D5 (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(1))
+#define P_PPI0_D6 (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(1))
+#define P_PPI0_D7 (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(1))
+#define P_PPI0_D8 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(1))
+#define P_PPI0_D9 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1))
+#define P_PPI0_D10 (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(1))
+#define P_PPI0_D11 (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(1))
+#define P_PPI0_D12 (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(1))
+#define P_PPI0_D13 (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(1))
+#define P_PPI0_D14 (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
+#define P_PPI0_D15 (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+#define P_PPI0_D16 (P_DEFINED | P_IDENT(GPIO_PE3) | P_FUNCT(1))
+#define P_PPI0_D17 (P_DEFINED | P_IDENT(GPIO_PE4) | P_FUNCT(1))
+#define P_PPI0_D18 (P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(1))
+#define P_PPI0_D19 (P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(1))
+#define P_PPI0_D20 (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(1))
+#define P_PPI0_D21 (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(1))
+#define P_PPI0_D22 (P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(1))
+#define P_PPI0_D23 (P_DEFINED | P_IDENT(GPIO_PE5) | P_FUNCT(1))
+#define P_PPI0_CLK (P_DEFINED | P_IDENT(GPIO_PE9) | P_FUNCT(1))
+#define P_PPI0_FS1 (P_DEFINED | P_IDENT(GPIO_PE8) | P_FUNCT(1))
+#define P_PPI0_FS2 (P_DEFINED | P_IDENT(GPIO_PE7) | P_FUNCT(1))
+#define P_PPI0_FS3 (P_DEFINED | P_IDENT(GPIO_PE6) | P_FUNCT(1))
+
+#define P_PPI1_D0 (P_DEFINED | P_IDENT(GPIO_PC0) | P_FUNCT(1))
+#define P_PPI1_D1 (P_DEFINED | P_IDENT(GPIO_PC1) | P_FUNCT(1))
+#define P_PPI1_D2 (P_DEFINED | P_IDENT(GPIO_PC2) | P_FUNCT(1))
+#define P_PPI1_D3 (P_DEFINED | P_IDENT(GPIO_PC3) | P_FUNCT(1))
+#define P_PPI1_D4 (P_DEFINED | P_IDENT(GPIO_PC4) | P_FUNCT(1))
+#define P_PPI1_D5 (P_DEFINED | P_IDENT(GPIO_PC5) | P_FUNCT(1))
+#define P_PPI1_D6 (P_DEFINED | P_IDENT(GPIO_PC6) | P_FUNCT(1))
+#define P_PPI1_D7 (P_DEFINED | P_IDENT(GPIO_PC7) | P_FUNCT(1))
+#define P_PPI1_D8 (P_DEFINED | P_IDENT(GPIO_PC8) | P_FUNCT(1))
+#define P_PPI1_D9 (P_DEFINED | P_IDENT(GPIO_PC9) | P_FUNCT(1))
+#define P_PPI1_D10 (P_DEFINED | P_IDENT(GPIO_PC10) | P_FUNCT(1))
+#define P_PPI1_D11 (P_DEFINED | P_IDENT(GPIO_PC11) | P_FUNCT(1))
+#define P_PPI1_D12 (P_DEFINED | P_IDENT(GPIO_PC12) | P_FUNCT(1))
+#define P_PPI1_D13 (P_DEFINED | P_IDENT(GPIO_PC13) | P_FUNCT(1))
+#define P_PPI1_D14 (P_DEFINED | P_IDENT(GPIO_PC14) | P_FUNCT(1))
+#define P_PPI1_D15 (P_DEFINED | P_IDENT(GPIO_PC15) | P_FUNCT(1))
+#define P_PPI1_D16 (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(1))
+#define P_PPI1_D17 (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(1))
+#define P_PPI1_CLK (P_DEFINED | P_IDENT(GPIO_PB14) | P_FUNCT(1))
+#define P_PPI1_FS1 (P_DEFINED | P_IDENT(GPIO_PB13) | P_FUNCT(1))
+#define P_PPI1_FS2 (P_DEFINED | P_IDENT(GPIO_PD6) | P_FUNCT(1))
+#define P_PPI1_FS3 (P_DEFINED | P_IDENT(GPIO_PB15) | P_FUNCT(1))
+
+#define P_PPI2_D0 (P_DEFINED | P_IDENT(GPIO_PA0) | P_FUNCT(1))
+#define P_PPI2_D1 (P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(1))
+#define P_PPI2_D2 (P_DEFINED | P_IDENT(GPIO_PA2) | P_FUNCT(1))
+#define P_PPI2_D3 (P_DEFINED | P_IDENT(GPIO_PA3) | P_FUNCT(1))
+#define P_PPI2_D4 (P_DEFINED | P_IDENT(GPIO_PA4) | P_FUNCT(1))
+#define P_PPI2_D5 (P_DEFINED | P_IDENT(GPIO_PA5) | P_FUNCT(1))
+#define P_PPI2_D6 (P_DEFINED | P_IDENT(GPIO_PA6) | P_FUNCT(1))
+#define P_PPI2_D7 (P_DEFINED | P_IDENT(GPIO_PA7) | P_FUNCT(1))
+#define P_PPI2_D8 (P_DEFINED | P_IDENT(GPIO_PA8) | P_FUNCT(1))
+#define P_PPI2_D9 (P_DEFINED | P_IDENT(GPIO_PA9) | P_FUNCT(1))
+#define P_PPI2_D10 (P_DEFINED | P_IDENT(GPIO_PA10) | P_FUNCT(1))
+#define P_PPI2_D11 (P_DEFINED | P_IDENT(GPIO_PA11) | P_FUNCT(1))
+#define P_PPI2_D12 (P_DEFINED | P_IDENT(GPIO_PA12) | P_FUNCT(1))
+#define P_PPI2_D13 (P_DEFINED | P_IDENT(GPIO_PA13) | P_FUNCT(1))
+#define P_PPI2_D14 (P_DEFINED | P_IDENT(GPIO_PA14) | P_FUNCT(1))
+#define P_PPI2_D15 (P_DEFINED | P_IDENT(GPIO_PA15) | P_FUNCT(1))
+#define P_PPI2_D16 (P_DEFINED | P_IDENT(GPIO_PB7) | P_FUNCT(1))
+#define P_PPI2_D17 (P_DEFINED | P_IDENT(GPIO_PB8) | P_FUNCT(1))
+#define P_PPI2_CLK (P_DEFINED | P_IDENT(GPIO_PB0) | P_FUNCT(1))
+#define P_PPI2_FS1 (P_DEFINED | P_IDENT(GPIO_PB1) | P_FUNCT(1))
+#define P_PPI2_FS2 (P_DEFINED | P_IDENT(GPIO_PB2) | P_FUNCT(1))
+#define P_PPI2_FS3 (P_DEFINED | P_IDENT(GPIO_PB3) | P_FUNCT(1))
+
+/* SPI Port Mux */
+#define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(3))
+#define P_SPI0_SCK (P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(0))
+#define P_SPI0_MISO (P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(0))
+#define P_SPI0_MOSI (P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(0))
+#define P_SPI0_RDY (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(0))
+#define P_SPI0_D2 (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(0))
+#define P_SPI0_D3 (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(0))
+
+#define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(0))
+#define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(2))
+#define P_SPI0_SSEL3 (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(2))
+#define P_SPI0_SSEL4 (P_DEFINED | P_IDENT(GPIO_PC15) | P_FUNCT(0))
+#define P_SPI0_SSEL5 (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(0))
+#define P_SPI0_SSEL6 (P_DEFINED | P_IDENT(GPIO_PC13) | P_FUNCT(0))
+#define P_SPI0_SSEL7 (P_DEFINED | P_IDENT(GPIO_PC12) | P_FUNCT(0))
+
+#define P_SPI1_SS (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(3))
+#define P_SPI1_SCK (P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(0))
+#define P_SPI1_MISO (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(0))
+#define P_SPI1_MOSI (P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(0))
+#define P_SPI1_RDY (P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(0))
+#define P_SPI1_D2 (P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(0))
+#define P_SPI1_D3 (P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(0))
+
+#define P_SPI1_SSEL1 (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(0))
+#define P_SPI1_SSEL2 (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(2))
+#define P_SPI1_SSEL3 (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(2))
+#define P_SPI1_SSEL4 (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(2))
+#define P_SPI1_SSEL5 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(0))
+#define P_SPI1_SSEL6 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(0))
+#define P_SPI1_SSEL7 (P_DEFINED | P_IDENT(GPIO_PC14) | P_FUNCT(0))
+
+#define GPIO_DEFAULT_BOOT_SPI_CS
+#define P_DEFAULT_BOOT_SPI_CS
+
+/* CORE IDLE */
+#define P_IDLEA (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(1))
+#define P_IDLEB (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(1))
+#define P_SLEEP (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(2))
+
+/* UART Port Mux */
+#define P_UART0_TX (P_DEFINED | P_IDENT(GPIO_PD7) | P_FUNCT(1))
+#define P_UART0_RX (P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(1))
+#define P_UART0_RTS (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(1))
+#define P_UART0_CTS (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(1))
+
+#define P_UART1_TX (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(0))
+#define P_UART1_RX (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(0))
+#define P_UART1_RTS (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(0))
+#define P_UART1_CTS (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(0))
+
+/* Timer */
+#define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(3))
+#define P_TMR0 (P_DEFINED | P_IDENT(GPIO_PE14) | P_FUNCT(2))
+#define P_TMR1 (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(1))
+#define P_TMR2 (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(1))
+#define P_TMR3 (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(1))
+#define P_TMR4 (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(1))
+#define P_TMR5 (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(1))
+#define P_TMR6 (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(1))
+#define P_TMR7 (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(1))
+
+/* RSI */
+#define P_RSI_DATA0 (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(2))
+#define P_RSI_DATA1 (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(2))
+#define P_RSI_DATA2 (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(2))
+#define P_RSI_DATA3 (P_DEFINED | P_IDENT(GPIO_PE15) | P_FUNCT(2))
+#define P_RSI_DATA4 (P_DEFINED | P_IDENT(GPIO_PE13) | P_FUNCT(2))
+#define P_RSI_DATA5 (P_DEFINED | P_IDENT(GPIO_PE12) | P_FUNCT(2))
+#define P_RSI_DATA6 (P_DEFINED | P_IDENT(GPIO_PE10) | P_FUNCT(2))
+#define P_RSI_DATA7 (P_DEFINED | P_IDENT(GPIO_PE11) | P_FUNCT(2))
+#define P_RSI_CMD (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(1))
+#define P_RSI_CLK (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(1))
+
+/* PTP */
+#define P_PTP0_PPS (P_DEFINED | P_IDENT(GPIO_PB15) | P_FUNCT(0))
+#define P_PTP0_CLKIN (P_DEFINED | P_IDENT(GPIO_PC13) | P_FUNCT(2))
+#define P_PTP0_AUXIN (P_DEFINED | P_IDENT(GPIO_PC11) | P_FUNCT(2))
+
+#define P_PTP1_PPS (P_DEFINED | P_IDENT(GPIO_PC9) | P_FUNCT(0))
+#define P_PTP1_CLKIN (P_DEFINED | P_IDENT(GPIO_PC13) | P_FUNCT(2))
+#define P_PTP1_AUXIN (P_DEFINED | P_IDENT(GPIO_PC11) | P_FUNCT(2))
+
+/* SMC Port Mux */
+#define P_A3 (P_DEFINED | P_IDENT(GPIO_PA0) | P_FUNCT(0))
+#define P_A4 (P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(0))
+#define P_A5 (P_DEFINED | P_IDENT(GPIO_PA2) | P_FUNCT(0))
+#define P_A6 (P_DEFINED | P_IDENT(GPIO_PA3) | P_FUNCT(0))
+#define P_A7 (P_DEFINED | P_IDENT(GPIO_PA4) | P_FUNCT(0))
+#define P_A8 (P_DEFINED | P_IDENT(GPIO_PA5) | P_FUNCT(0))
+#define P_A9 (P_DEFINED | P_IDENT(GPIO_PA6) | P_FUNCT(0))
+#define P_A10 (P_DEFINED | P_IDENT(GPIO_PA7) | P_FUNCT(0))
+#define P_A11 (P_DEFINED | P_IDENT(GPIO_PA8) | P_FUNCT(0))
+#define P_A12 (P_DEFINED | P_IDENT(GPIO_PA9) | P_FUNCT(0))
+#define P_A13 (P_DEFINED | P_IDENT(GPIO_PB2) | P_FUNCT(0))
+#define P_A14 (P_DEFINED | P_IDENT(GPIO_PA10) | P_FUNCT(0))
+#define P_A15 (P_DEFINED | P_IDENT(GPIO_PA11) | P_FUNCT(0))
+#define P_A16 (P_DEFINED | P_IDENT(GPIO_PB3) | P_FUNCT(0))
+#define P_A17 (P_DEFINED | P_IDENT(GPIO_PA12) | P_FUNCT(0))
+#define P_A18 (P_DEFINED | P_IDENT(GPIO_PA13) | P_FUNCT(0))
+#define P_A19 (P_DEFINED | P_IDENT(GPIO_PA14) | P_FUNCT(0))
+#define P_A20 (P_DEFINED | P_IDENT(GPIO_PA15) | P_FUNCT(0))
+#define P_A21 (P_DEFINED | P_IDENT(GPIO_PB6) | P_FUNCT(0))
+#define P_A22 (P_DEFINED | P_IDENT(GPIO_PB7) | P_FUNCT(0))
+#define P_A23 (P_DEFINED | P_IDENT(GPIO_PB8) | P_FUNCT(0))
+#define P_A24 (P_DEFINED | P_IDENT(GPIO_PB10) | P_FUNCT(0))
+#define P_A25 (P_DEFINED | P_IDENT(GPIO_PB11) | P_FUNCT(0))
+#define P_NORCK (P_DEFINED | P_IDENT(GPIO_PB0) | P_FUNCT(0))
+
+#define P_AMS1 (P_DEFINED | P_IDENT(GPIO_PB1) | P_FUNCT(0))
+#define P_AMS2 (P_DEFINED | P_IDENT(GPIO_PB4) | P_FUNCT(0))
+#define P_AMS3 (P_DEFINED | P_IDENT(GPIO_PB5) | P_FUNCT(0))
+
+/* CAN */
+#define P_CAN0_TX (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(2))
+#define P_CAN0_RX (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(2))
+
+/* SPORT */
+#define P_SPORT0_ACLK (P_DEFINED | P_IDENT(GPIO_PB5) | P_FUNCT(2))
+#define P_SPORT0_AFS (P_DEFINED | P_IDENT(GPIO_PB4) | P_FUNCT(2))
+#define P_SPORT0_AD0 (P_DEFINED | P_IDENT(GPIO_PB9) | P_FUNCT(2))
+#define P_SPORT0_AD1 (P_DEFINED | P_IDENT(GPIO_PB12) | P_FUNCT(2))
+#define P_SPORT0_ATDV (P_DEFINED | P_IDENT(GPIO_PB6) | P_FUNCT(1))
+#define P_SPORT0_BCLK (P_DEFINED | P_IDENT(GPIO_PB8) | P_FUNCT(2))
+#define P_SPORT0_BFS (P_DEFINED | P_IDENT(GPIO_PB7) | P_FUNCT(2))
+#define P_SPORT0_BD0 (P_DEFINED | P_IDENT(GPIO_PB11) | P_FUNCT(2))
+#define P_SPORT0_BD1 (P_DEFINED | P_IDENT(GPIO_PB10) | P_FUNCT(2))
+#define P_SPORT0_BTDV (P_DEFINED | P_IDENT(GPIO_PB12) | P_FUNCT(1))
+
+#define P_SPORT1_ACLK (P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(2))
+#define P_SPORT1_AFS (P_DEFINED | P_IDENT(GPIO_PE5) | P_FUNCT(2))
+#define P_SPORT1_AD0 (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(2))
+#define P_SPORT1_AD1 (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(2))
+#define P_SPORT1_ATDV (P_DEFINED | P_IDENT(GPIO_PE6) | P_FUNCT(0))
+#define P_SPORT1_BCLK (P_DEFINED | P_IDENT(GPIO_PE4) | P_FUNCT(2))
+#define P_SPORT1_BFS (P_DEFINED | P_IDENT(GPIO_PE3) | P_FUNCT(2))
+#define P_SPORT1_BD0 (P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(2))
+#define P_SPORT1_BD1 (P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(2))
+#define P_SPORT1_BTDV (P_DEFINED | P_IDENT(GPIO_PE7) | P_FUNCT(0))
+
+#define P_SPORT2_ACLK (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(0))
+#define P_SPORT2_AFS (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
+#define P_SPORT2_AD0 (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(0))
+#define P_SPORT2_AD1 (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(0))
+#define P_SPORT2_ATDV (P_DEFINED | P_IDENT(GPIO_PE14) | P_FUNCT(1))
+#define P_SPORT2_BCLK (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(1))
+#define P_SPORT2_BFS (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(0))
+#define P_SPORT2_BD0 (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(0))
+#define P_SPORT2_BD1 (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(0))
+#define P_SPORT2_BTDV (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(2))
+
+/* LINK PORT */
+#define P_LP0_CLK (P_DEFINED | P_IDENT(GPIO_PB0) | P_FUNCT(2))
+#define P_LP0_ACK (P_DEFINED | P_IDENT(GPIO_PB1) | P_FUNCT(2))
+#define P_LP0_D0 (P_DEFINED | P_IDENT(GPIO_PA0) | P_FUNCT(2))
+#define P_LP0_D1 (P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(2))
+#define P_LP0_D2 (P_DEFINED | P_IDENT(GPIO_PA2) | P_FUNCT(2))
+#define P_LP0_D3 (P_DEFINED | P_IDENT(GPIO_PA3) | P_FUNCT(2))
+#define P_LP0_D4 (P_DEFINED | P_IDENT(GPIO_PA4) | P_FUNCT(2))
+#define P_LP0_D5 (P_DEFINED | P_IDENT(GPIO_PA5) | P_FUNCT(2))
+#define P_LP0_D6 (P_DEFINED | P_IDENT(GPIO_PA6) | P_FUNCT(2))
+#define P_LP0_D7 (P_DEFINED | P_IDENT(GPIO_PA7) | P_FUNCT(2))
+
+#define P_LP1_CLK (P_DEFINED | P_IDENT(GPIO_PB3) | P_FUNCT(2))
+#define P_LP1_ACK (P_DEFINED | P_IDENT(GPIO_PB2) | P_FUNCT(2))
+#define P_LP1_D0 (P_DEFINED | P_IDENT(GPIO_PA8) | P_FUNCT(2))
+#define P_LP1_D1 (P_DEFINED | P_IDENT(GPIO_PA9) | P_FUNCT(2))
+#define P_LP1_D2 (P_DEFINED | P_IDENT(GPIO_PA10) | P_FUNCT(2))
+#define P_LP1_D3 (P_DEFINED | P_IDENT(GPIO_PA11) | P_FUNCT(2))
+#define P_LP1_D4 (P_DEFINED | P_IDENT(GPIO_PA12) | P_FUNCT(2))
+#define P_LP1_D5 (P_DEFINED | P_IDENT(GPIO_PA13) | P_FUNCT(2))
+#define P_LP1_D6 (P_DEFINED | P_IDENT(GPIO_PA14) | P_FUNCT(2))
+#define P_LP1_D7 (P_DEFINED | P_IDENT(GPIO_PA15) | P_FUNCT(2))
+
+#define P_LP2_CLK (P_DEFINED | P_IDENT(GPIO_PE6) | P_FUNCT(2))
+#define P_LP2_ACK (P_DEFINED | P_IDENT(GPIO_PE7) | P_FUNCT(2))
+#define P_LP2_D0 (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(2))
+#define P_LP2_D1 (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(2))
+#define P_LP2_D2 (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(2))
+#define P_LP2_D3 (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(2))
+#define P_LP2_D4 (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(2))
+#define P_LP2_D5 (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(2))
+#define P_LP2_D6 (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(2))
+#define P_LP2_D7 (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(2))
+
+#define P_LP3_CLK (P_DEFINED | P_IDENT(GPIO_PE9) | P_FUNCT(2))
+#define P_LP3_ACK (P_DEFINED | P_IDENT(GPIO_PE8) | P_FUNCT(2))
+#define P_LP3_D0 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(2))
+#define P_LP3_D1 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(2))
+#define P_LP3_D2 (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(2))
+#define P_LP3_D3 (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(2))
+#define P_LP3_D4 (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(2))
+#define P_LP3_D5 (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(2))
+#define P_LP3_D6 (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(2))
+#define P_LP3_D7 (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(2))
+
+/* TWI */
+#define P_TWI0_SCL (P_DONTCARE)
+#define P_TWI0_SDA (P_DONTCARE)
+#define P_TWI1_SCL (P_DONTCARE)
+#define P_TWI1_SDA (P_DONTCARE)
+
+/* Rotary Encoder */
+#define P_CNT_CZM (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(3))
+#define P_CNT_CUD (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(3))
+#define P_CNT_CDG (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(3))
+
+#endif /* _MACH_PORTMUX_H_ */
diff --git a/arch/blackfin/mach-bf609/pm.c b/arch/blackfin/mach-bf609/pm.c
new file mode 100644
index 000000000000..b76966eb16ad
--- /dev/null
+++ b/arch/blackfin/mach-bf609/pm.c
@@ -0,0 +1,362 @@
+/*
+ * Blackfin bf609 power management
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2
+ */
+
+#include <linux/suspend.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+
+#include <linux/delay.h>
+
+#include <asm/dpmc.h>
+#include <asm/pm.h>
+#include <mach/pm.h>
+#include <asm/blackfin.h>
+
+/***********************************************************/
+/* */
+/* Wakeup Actions for DPM_RESTORE */
+/* */
+/***********************************************************/
+#define BITP_ROM_WUA_CHKHDR 24
+#define BITP_ROM_WUA_DDRLOCK 7
+#define BITP_ROM_WUA_DDRDLLEN 6
+#define BITP_ROM_WUA_DDR 5
+#define BITP_ROM_WUA_CGU 4
+#define BITP_ROM_WUA_MEMBOOT 2
+#define BITP_ROM_WUA_EN 1
+
+#define BITM_ROM_WUA_CHKHDR (0xFF000000)
+#define ENUM_ROM_WUA_CHKHDR_AD 0xAD000000
+
+#define BITM_ROM_WUA_DDRLOCK (0x00000080)
+#define BITM_ROM_WUA_DDRDLLEN (0x00000040)
+#define BITM_ROM_WUA_DDR (0x00000020)
+#define BITM_ROM_WUA_CGU (0x00000010)
+#define BITM_ROM_WUA_MEMBOOT (0x00000002)
+#define BITM_ROM_WUA_EN (0x00000001)
+
+/***********************************************************/
+/* */
+/* Syscontrol */
+/* */
+/***********************************************************/
+#define BITP_ROM_SYSCTRL_CGU_LOCKINGEN 28 /* unlocks CGU_CTL register */
+#define BITP_ROM_SYSCTRL_WUA_OVERRIDE 24
+#define BITP_ROM_SYSCTRL_WUA_DDRDLLEN 20 /* Saves the DDR DLL and PADS registers to the DPM registers */
+#define BITP_ROM_SYSCTRL_WUA_DDR 19 /* Saves the DDR registers to the DPM registers */
+#define BITP_ROM_SYSCTRL_WUA_CGU 18 /* Saves the CGU registers into DPM registers */
+#define BITP_ROM_SYSCTRL_WUA_DPMWRITE 17 /* Saves the Syscontrol structure structure contents into DPM registers */
+#define BITP_ROM_SYSCTRL_WUA_EN 16 /* reads current PLL and DDR configuration into structure */
+#define BITP_ROM_SYSCTRL_DDR_WRITE 13 /* writes the DDR registers from Syscontrol structure for wakeup initialization of DDR */
+#define BITP_ROM_SYSCTRL_DDR_READ 12 /* Read the DDR registers into the Syscontrol structure for storing prior to hibernate */
+#define BITP_ROM_SYSCTRL_CGU_AUTODIS 11 /* Disables auto handling of UPDT and ALGN fields */
+#define BITP_ROM_SYSCTRL_CGU_CLKOUTSEL 7 /* access CGU_CLKOUTSEL register */
+#define BITP_ROM_SYSCTRL_CGU_DIV 6 /* access CGU_DIV register */
+#define BITP_ROM_SYSCTRL_CGU_STAT 5 /* access CGU_STAT register */
+#define BITP_ROM_SYSCTRL_CGU_CTL 4 /* access CGU_CTL register */
+#define BITP_ROM_SYSCTRL_CGU_RTNSTAT 2 /* Update structure STAT field upon error */
+#define BITP_ROM_SYSCTRL_WRITE 1 /* write registers */
+#define BITP_ROM_SYSCTRL_READ 0 /* read registers */
+
+#define BITM_ROM_SYSCTRL_CGU_READ (0x00000001) /* Read CGU registers */
+#define BITM_ROM_SYSCTRL_CGU_WRITE (0x00000002) /* Write registers */
+#define BITM_ROM_SYSCTRL_CGU_RTNSTAT (0x00000004) /* Update structure STAT field upon error or after a write operation */
+#define BITM_ROM_SYSCTRL_CGU_CTL (0x00000010) /* Access CGU_CTL register */
+#define BITM_ROM_SYSCTRL_CGU_STAT (0x00000020) /* Access CGU_STAT register */
+#define BITM_ROM_SYSCTRL_CGU_DIV (0x00000040) /* Access CGU_DIV register */
+#define BITM_ROM_SYSCTRL_CGU_CLKOUTSEL (0x00000080) /* Access CGU_CLKOUTSEL register */
+#define BITM_ROM_SYSCTRL_CGU_AUTODIS (0x00000800) /* Disables auto handling of UPDT and ALGN fields */
+#define BITM_ROM_SYSCTRL_DDR_READ (0x00001000) /* Reads the contents of the DDR registers and stores them into the structure */
+#define BITM_ROM_SYSCTRL_DDR_WRITE (0x00002000) /* Writes the DDR registers from the structure, only really intented for wakeup functionality and not for full DDR configuration */
+#define BITM_ROM_SYSCTRL_WUA_EN (0x00010000) /* Wakeup entry or exit opertation enable */
+#define BITM_ROM_SYSCTRL_WUA_DPMWRITE (0x00020000) /* When set indicates a restore of the PLL and DDR is to be performed otherwise a save is required */
+#define BITM_ROM_SYSCTRL_WUA_CGU (0x00040000) /* Only applicable for a PLL and DDR save operation to the DPM, saves the current settings if cleared or the contents of the structure if set */
+#define BITM_ROM_SYSCTRL_WUA_DDR (0x00080000) /* Only applicable for a PLL and DDR save operation to the DPM, saves the current settings if cleared or the contents of the structure if set */
+#define BITM_ROM_SYSCTRL_WUA_DDRDLLEN (0x00100000) /* Enables saving/restoring of the DDR DLLCTL register */
+#define BITM_ROM_SYSCTRL_WUA_OVERRIDE (0x01000000)
+#define BITM_ROM_SYSCTRL_CGU_LOCKINGEN (0x10000000) /* Unlocks the CGU_CTL register */
+
+
+/* Structures for the syscontrol() function */
+struct STRUCT_ROM_SYSCTRL {
+ uint32_t ulCGU_CTL;
+ uint32_t ulCGU_STAT;
+ uint32_t ulCGU_DIV;
+ uint32_t ulCGU_CLKOUTSEL;
+ uint32_t ulWUA_Flags;
+ uint32_t ulWUA_BootAddr;
+ uint32_t ulWUA_User;
+ uint32_t ulDDR_CTL;
+ uint32_t ulDDR_CFG;
+ uint32_t ulDDR_TR0;
+ uint32_t ulDDR_TR1;
+ uint32_t ulDDR_TR2;
+ uint32_t ulDDR_MR;
+ uint32_t ulDDR_EMR1;
+ uint32_t ulDDR_EMR2;
+ uint32_t ulDDR_PADCTL;
+ uint32_t ulDDR_DLLCTL;
+ uint32_t ulReserved;
+};
+
+struct bfin_pm_data {
+ uint32_t magic;
+ uint32_t resume_addr;
+ uint32_t sp;
+};
+
+struct bfin_pm_data bf609_pm_data;
+
+struct STRUCT_ROM_SYSCTRL configvalues;
+uint32_t dactionflags;
+
+#define FUNC_ROM_SYSCONTROL 0xC8000080
+__attribute__((l1_data))
+static uint32_t (* const bfrom_SysControl)(uint32_t action_flags, struct STRUCT_ROM_SYSCTRL *settings, void *reserved) = (void *)FUNC_ROM_SYSCONTROL;
+
+__attribute__((l1_text))
+void bfin_cpu_suspend(void)
+{
+ __asm__ __volatile__( \
+ ".align 8;" \
+ "idle;" \
+ : : \
+ );
+}
+
+__attribute__((l1_text))
+void bfin_deepsleep(unsigned long mask)
+{
+ uint32_t dpm0_ctl;
+
+ bfin_write32(DPM0_WAKE_EN, 0x10);
+ bfin_write32(DPM0_WAKE_POL, 0x10);
+ dpm0_ctl = 0x00000008;
+ bfin_write32(DPM0_CTL, dpm0_ctl);
+ SSYNC();
+ __asm__ __volatile__( \
+ ".align 8;" \
+ "idle;" \
+ : : \
+ );
+#ifdef CONFIG_BFIN_PM_WAKEUP_TIME_BENCH
+ __asm__ __volatile__(
+ "R0 = 0;"
+ "CYCLES = R0;"
+ "CYCLES2 = R0;"
+ "R0 = SYSCFG;"
+ "BITSET(R0, 1);"
+ "SYSCFG = R0;"
+ : : : "R0"
+ );
+#endif
+
+}
+
+__attribute__((l1_text))
+void bf609_ddr_sr(void)
+{
+ uint32_t reg;
+
+ reg = bfin_read_DMC0_CTL();
+ reg |= 0x8;
+ bfin_write_DMC0_CTL(reg);
+
+ while (!(bfin_read_DMC0_STAT() & 0x8))
+ continue;
+}
+
+__attribute__((l1_text))
+void bf609_ddr_sr_exit(void)
+{
+ uint32_t reg;
+ while (!(bfin_read_DMC0_STAT() & 0x1))
+ continue;
+
+ reg = bfin_read_DMC0_CTL();
+ reg &= ~0x8;
+ bfin_write_DMC0_CTL(reg);
+
+ while ((bfin_read_DMC0_STAT() & 0x8))
+ continue;
+}
+
+__attribute__((l1_text))
+void bfin_hibernate_syscontrol(void)
+{
+ configvalues.ulWUA_Flags = (0xAD000000 | BITM_ROM_WUA_EN
+ | BITM_ROM_WUA_CGU | BITM_ROM_WUA_DDR | BITM_ROM_WUA_DDRDLLEN);
+
+ dactionflags = (BITM_ROM_SYSCTRL_WUA_EN
+ | BITM_ROM_SYSCTRL_WUA_DPMWRITE | BITM_ROM_SYSCTRL_WUA_CGU
+ | BITM_ROM_SYSCTRL_WUA_DDR | BITM_ROM_SYSCTRL_WUA_DDRDLLEN);
+
+ bfrom_SysControl(dactionflags, &configvalues, NULL);
+
+ bfin_write32(DPM0_RESTORE5, bfin_read32(DPM0_RESTORE5) | 4);
+}
+
+#ifndef CONFIG_BF60x
+# define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1))
+#else
+# define SIC_SYSIRQ(irq) ((irq) - IVG15)
+#endif
+void bfin_hibernate(unsigned long mask)
+{
+ bfin_write32(DPM0_WAKE_EN, 0x10);
+ bfin_write32(DPM0_WAKE_POL, 0x10);
+ bfin_write32(DPM0_PGCNTR, 0x0000FFFF);
+ bfin_write32(DPM0_HIB_DIS, 0xFFFF);
+
+ printk(KERN_DEBUG "hibernate: restore %x pgcnt %x\n", bfin_read32(DPM0_RESTORE0), bfin_read32(DPM0_PGCNTR));
+
+ bf609_hibernate();
+}
+
+void bf609_cpu_pm_enter(suspend_state_t state)
+{
+ int error;
+ unsigned long wakeup = 0;
+ unsigned long wakeup_pol = 0;
+
+#ifdef CONFIG_PM_BFIN_WAKE_PA15
+ wakeup |= PA15WE;
+# if CONFIG_PM_BFIN_WAKE_PA15_POL
+ wakeup_pol |= PA15WE;
+# endif
+#endif
+
+#ifdef CONFIG_PM_BFIN_WAKE_PB15
+ wakeup |= PB15WE;
+# if CONFIG_PM_BFIN_WAKE_PA15_POL
+ wakeup_pol |= PB15WE;
+# endif
+#endif
+
+#ifdef CONFIG_PM_BFIN_WAKE_PC15
+ wakeup |= PC15WE;
+# if CONFIG_PM_BFIN_WAKE_PC15_POL
+ wakeup_pol |= PC15WE;
+# endif
+#endif
+
+#ifdef CONFIG_PM_BFIN_WAKE_PD06
+ wakeup |= PD06WE;
+# if CONFIG_PM_BFIN_WAKE_PD06_POL
+ wakeup_pol |= PD06WE;
+# endif
+#endif
+
+#ifdef CONFIG_PM_BFIN_WAKE_PE12
+ wakeup |= PE12WE;
+# if CONFIG_PM_BFIN_WAKE_PE12_POL
+ wakeup_pol |= PE12WE;
+# endif
+#endif
+
+#ifdef CONFIG_PM_BFIN_WAKE_PG04
+ wakeup |= PG04WE;
+# if CONFIG_PM_BFIN_WAKE_PG04_POL
+ wakeup_pol |= PG04WE;
+# endif
+#endif
+
+#ifdef CONFIG_PM_BFIN_WAKE_PG13
+ wakeup |= PG13WE;
+# if CONFIG_PM_BFIN_WAKE_PG13_POL
+ wakeup_pol |= PG13WE;
+# endif
+#endif
+
+#ifdef CONFIG_PM_BFIN_WAKE_USB
+ wakeup |= USBWE;
+# if CONFIG_PM_BFIN_WAKE_USB_POL
+ wakeup_pol |= USBWE;
+# endif
+#endif
+
+ error = irq_set_irq_wake(255, 1);
+ if(error < 0)
+ printk(KERN_DEBUG "Unable to get irq wake\n");
+ error = irq_set_irq_wake(231, 1);
+ if (error < 0)
+ printk(KERN_DEBUG "Unable to get irq wake\n");
+
+ if (state == PM_SUSPEND_STANDBY)
+ bfin_deepsleep(wakeup);
+ else {
+ bfin_hibernate(wakeup);
+ }
+}
+
+int bf609_cpu_pm_prepare(void)
+{
+ return 0;
+}
+
+void bf609_cpu_pm_finish(void)
+{
+
+}
+
+static struct bfin_cpu_pm_fns bf609_cpu_pm = {
+ .enter = bf609_cpu_pm_enter,
+ .prepare = bf609_cpu_pm_prepare,
+ .finish = bf609_cpu_pm_finish,
+};
+
+static irqreturn_t test_isr(int irq, void *dev_id)
+{
+ printk(KERN_DEBUG "gpio irq %d\n", irq);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t dpm0_isr(int irq, void *dev_id)
+{
+ uint32_t wake_stat;
+
+ wake_stat = bfin_read32(DPM0_WAKE_STAT);
+ printk(KERN_DEBUG "enter %s wake stat %08x\n", __func__, wake_stat);
+
+ bfin_write32(DPM0_WAKE_STAT, wake_stat);
+ return IRQ_HANDLED;
+}
+
+static int __init bf609_init_pm(void)
+{
+ int irq;
+ int error;
+
+#if CONFIG_PM_BFIN_WAKE_PE12
+ irq = gpio_to_irq(GPIO_PE12);
+ if (irq < 0) {
+ error = irq;
+ printk(KERN_DEBUG "Unable to get irq number for GPIO %d, error %d\n",
+ GPIO_PE12, error);
+ }
+
+ error = request_irq(irq, test_isr, IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND, "gpiope12", NULL);
+ if(error < 0)
+ printk(KERN_DEBUG "Unable to get irq\n");
+#endif
+
+ error = request_irq(IRQ_CGU_EVT, dpm0_isr, IRQF_NO_SUSPEND, "cgu0 event", NULL);
+ if(error < 0)
+ printk(KERN_DEBUG "Unable to get irq\n");
+
+ error = request_irq(IRQ_DPM, dpm0_isr, IRQF_NO_SUSPEND, "dpm0 event", NULL);
+ if (error < 0)
+ printk(KERN_DEBUG "Unable to get irq\n");
+
+ bfin_cpu_pm = &bf609_cpu_pm;
+ return 0;
+}
+
+late_initcall(bf609_init_pm);
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile
index ff299f24aba0..75f0ba29ebb9 100644
--- a/arch/blackfin/mach-common/Makefile
+++ b/arch/blackfin/mach-common/Makefile
@@ -6,7 +6,10 @@ obj-y := \
cache.o cache-c.o entry.o head.o \
interrupt.o arch_checks.o ints-priority.o
-obj-$(CONFIG_PM) += pm.o dpmc_modes.o
+obj-$(CONFIG_PM) += pm.o
+ifneq ($(CONFIG_BF60x),y)
+obj-$(CONFIG_PM) += dpmc_modes.o
+endif
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o
obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/blackfin/mach-common/clock.h b/arch/blackfin/mach-common/clock.h
new file mode 100644
index 000000000000..645ff460a1f2
--- /dev/null
+++ b/arch/blackfin/mach-common/clock.h
@@ -0,0 +1,27 @@
+#ifndef __MACH_COMMON_CLKDEV_H
+#define __MACH_COMMON_CLKDEV_H
+
+#include <linux/clk.h>
+
+struct clk_ops {
+ unsigned long (*get_rate)(struct clk *clk);
+ unsigned long (*round_rate)(struct clk *clk, unsigned long rate);
+ int (*set_rate)(struct clk *clk, unsigned long rate);
+ int (*enable)(struct clk *clk);
+ int (*disable)(struct clk *clk);
+};
+
+struct clk {
+ const char *name;
+ unsigned long rate;
+ spinlock_t lock;
+ u32 flags;
+ const struct clk_ops *ops;
+ const struct params *params;
+ void __iomem *reg;
+ u32 mask;
+ u32 shift;
+};
+
+#endif
+
diff --git a/arch/blackfin/mach-common/clocks-init.c b/arch/blackfin/mach-common/clocks-init.c
index d5cfe611b778..7ad2407d1571 100644
--- a/arch/blackfin/mach-common/clocks-init.c
+++ b/arch/blackfin/mach-common/clocks-init.c
@@ -15,10 +15,121 @@
#include <asm/mem_init.h>
#include <asm/dpmc.h>
+#ifdef CONFIG_BF60x
+#define CSEL_P 0
+#define S0SEL_P 5
+#define SYSSEL_P 8
+#define S1SEL_P 13
+#define DSEL_P 16
+#define OSEL_P 22
+#define ALGN_P 29
+#define UPDT_P 30
+#define LOCK_P 31
+
+#define CGU_CTL_VAL ((CONFIG_VCO_MULT << 8) | CLKIN_HALF)
+#define CGU_DIV_VAL \
+ ((CONFIG_CCLK_DIV << CSEL_P) | \
+ (CONFIG_SCLK_DIV << SYSSEL_P) | \
+ (CONFIG_SCLK0_DIV << S0SEL_P) | \
+ (CONFIG_SCLK1_DIV << S1SEL_P) | \
+ (CONFIG_DCLK_DIV << DSEL_P))
+
+#define CONFIG_BFIN_DCLK (((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_DCLK_DIV) / 1000000)
+#if ((CONFIG_BFIN_DCLK != 125) && \
+ (CONFIG_BFIN_DCLK != 133) && (CONFIG_BFIN_DCLK != 150) && \
+ (CONFIG_BFIN_DCLK != 166) && (CONFIG_BFIN_DCLK != 200) && \
+ (CONFIG_BFIN_DCLK != 225) && (CONFIG_BFIN_DCLK != 250))
+#error "DCLK must be in (125, 133, 150, 166, 200, 225, 250)MHz"
+#endif
+struct ddr_config {
+ u32 ddr_clk;
+ u32 dmc_ddrctl;
+ u32 dmc_ddrcfg;
+ u32 dmc_ddrtr0;
+ u32 dmc_ddrtr1;
+ u32 dmc_ddrtr2;
+ u32 dmc_ddrmr;
+ u32 dmc_ddrmr1;
+};
+
+struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) = {
+ [0] = {
+ .ddr_clk = 125,
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20705212,
+ .dmc_ddrtr1 = 0x201003CF,
+ .dmc_ddrtr2 = 0x00320107,
+ .dmc_ddrmr = 0x00000422,
+ .dmc_ddrmr1 = 0x4,
+ },
+ [1] = {
+ .ddr_clk = 133,
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20806313,
+ .dmc_ddrtr1 = 0x2013040D,
+ .dmc_ddrtr2 = 0x00320108,
+ .dmc_ddrmr = 0x00000632,
+ .dmc_ddrmr1 = 0x4,
+ },
+ [2] = {
+ .ddr_clk = 150,
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20A07323,
+ .dmc_ddrtr1 = 0x20160492,
+ .dmc_ddrtr2 = 0x00320209,
+ .dmc_ddrmr = 0x00000632,
+ .dmc_ddrmr1 = 0x4,
+ },
+ [3] = {
+ .ddr_clk = 166,
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20A07323,
+ .dmc_ddrtr1 = 0x2016050E,
+ .dmc_ddrtr2 = 0x00320209,
+ .dmc_ddrmr = 0x00000632,
+ .dmc_ddrmr1 = 0x4,
+ },
+ [4] = {
+ .ddr_clk = 200,
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20a07323,
+ .dmc_ddrtr1 = 0x2016050f,
+ .dmc_ddrtr2 = 0x00320509,
+ .dmc_ddrmr = 0x00000632,
+ .dmc_ddrmr1 = 0x4,
+ },
+ [5] = {
+ .ddr_clk = 225,
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20E0A424,
+ .dmc_ddrtr1 = 0x302006DB,
+ .dmc_ddrtr2 = 0x0032020D,
+ .dmc_ddrmr = 0x00000842,
+ .dmc_ddrmr1 = 0x4,
+ },
+ [6] = {
+ .ddr_clk = 250,
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20E0A424,
+ .dmc_ddrtr1 = 0x3020079E,
+ .dmc_ddrtr2 = 0x0032020D,
+ .dmc_ddrmr = 0x00000842,
+ .dmc_ddrmr1 = 0x4,
+ },
+};
+#else
#define SDGCTL_WIDTH (1 << 31) /* SDRAM external data path width */
#define PLL_CTL_VAL \
(((CONFIG_VCO_MULT & 63) << 9) | CLKIN_HALF | \
- (PLL_BYPASS << 8) | (ANOMALY_05000305 ? 0 : 0x8000))
+ (PLL_BYPASS << 8) | (ANOMALY_05000305 ? 0 : 0x8000))
+#endif
__attribute__((l1_text))
static void do_sync(void)
@@ -33,6 +144,44 @@ void init_clocks(void)
* in the middle of reprogramming things, and that'll screw us up.
* For example, any automatic DMAs left by U-Boot for splash screens.
*/
+
+#ifdef CONFIG_BF60x
+ int i, dlldatacycle, dll_ctl;
+ bfin_write32(CGU0_DIV, CGU_DIV_VAL);
+ bfin_write32(CGU0_CTL, CGU_CTL_VAL);
+ while ((bfin_read32(CGU0_STAT) & 0x8) || !(bfin_read32(CGU0_STAT) & 0x4))
+ continue;
+
+ bfin_write32(CGU0_DIV, CGU_DIV_VAL | (1 << UPDT_P));
+ while (bfin_read32(CGU0_STAT) & (1 << 3))
+ continue;
+
+ for (i = 0; i < 7; i++) {
+ if (ddr_config_table[i].ddr_clk == CONFIG_BFIN_DCLK) {
+ bfin_write_DDR0_CFG(ddr_config_table[i].dmc_ddrcfg);
+ bfin_write_DDR0_TR0(ddr_config_table[i].dmc_ddrtr0);
+ bfin_write_DDR0_TR1(ddr_config_table[i].dmc_ddrtr1);
+ bfin_write_DDR0_TR2(ddr_config_table[i].dmc_ddrtr2);
+ bfin_write_DDR0_MR(ddr_config_table[i].dmc_ddrmr);
+ bfin_write_DDR0_EMR1(ddr_config_table[i].dmc_ddrmr1);
+ bfin_write_DDR0_CTL(ddr_config_table[i].dmc_ddrctl);
+ break;
+ }
+ }
+
+ do_sync();
+ while (!(bfin_read_DDR0_STAT() & 0x4))
+ continue;
+
+ dlldatacycle = (bfin_read_DDR0_STAT() & 0x00f00000) >> 20;
+ dll_ctl = bfin_read_DDR0_DLLCTL();
+ dll_ctl &= 0x0ff;
+ bfin_write_DDR0_DLLCTL(dll_ctl | (dlldatacycle << 8));
+
+ do_sync();
+ while (!(bfin_read_DDR0_STAT() & 0x2000))
+ continue;
+#else
size_t i;
for (i = 0; i < MAX_DMA_CHANNELS; ++i) {
struct dma_register *dma = dma_io_base_addr[i];
@@ -91,6 +240,8 @@ void init_clocks(void)
bfin_write_EBIU_DDRQUE(CONFIG_MEM_EBIU_DDRQUE);
#endif
#endif
+#endif
do_sync();
bfin_read16(0);
+
}
diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
index 2e6eefd812f4..6e87dc13f6bf 100644
--- a/arch/blackfin/mach-common/cpufreq.c
+++ b/arch/blackfin/mach-common/cpufreq.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <linux/fs.h>
#include <linux/delay.h>
@@ -17,6 +18,7 @@
#include <asm/time.h>
#include <asm/dpmc.h>
+
/* this is the table of CCLK frequencies, in Hz */
/* .index is the entry in the auxiliary dpm_state_table[] */
static struct cpufreq_frequency_table bfin_freq_table[] = {
@@ -67,12 +69,22 @@ static void __init bfin_init_tables(unsigned long cclk, unsigned long sclk)
#else
min_cclk = sclk;
#endif
+
+#ifndef CONFIG_BF60x
csel = ((bfin_read_PLL_DIV() & CSEL) >> 4);
+#else
+ csel = bfin_read32(CGU0_DIV) & 0x1F;
+#endif
for (index = 0; (cclk >> index) >= min_cclk && csel <= 3; index++, csel++) {
bfin_freq_table[index].frequency = cclk >> index;
+#ifndef CONFIG_BF60x
dpm_state_table[index].csel = csel << 4; /* Shift now into PLL_DIV bitpos */
dpm_state_table[index].tscale = (TIME_SCALE / (1 << csel)) - 1;
+#else
+ dpm_state_table[index].csel = csel;
+ dpm_state_table[index].tscale = TIME_SCALE >> index;
+#endif
pr_debug("cpufreq: freq:%d csel:0x%x tscale:%d\n",
bfin_freq_table[index].frequency,
@@ -99,14 +111,34 @@ static unsigned int bfin_getfreq_khz(unsigned int cpu)
return get_cclk() / 1000;
}
+#ifdef CONFIG_BF60x
+unsigned long cpu_set_cclk(int cpu, unsigned long new)
+{
+ struct clk *clk;
+ int ret;
+
+ clk = clk_get(NULL, "CCLK");
+ if (IS_ERR(clk))
+ return -ENODEV;
+
+ ret = clk_set_rate(clk, new);
+ clk_put(clk);
+ return ret;
+}
+#endif
+
static int bfin_target(struct cpufreq_policy *poli,
unsigned int target_freq, unsigned int relation)
{
- unsigned int index, plldiv, cpu;
+#ifndef CONFIG_BF60x
+ unsigned int plldiv;
+#endif
+ unsigned int index, cpu;
unsigned long flags, cclk_hz;
struct cpufreq_freqs freqs;
static unsigned long lpj_ref;
static unsigned int lpj_ref_freq;
+ int ret = 0;
#if defined(CONFIG_CYCLES_CLOCKSOURCE)
cycles_t cycles;
@@ -134,9 +166,17 @@ static int bfin_target(struct cpufreq_policy *poli,
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
if (cpu == CPUFREQ_CPU) {
flags = hard_local_irq_save();
+#ifndef CONFIG_BF60x
plldiv = (bfin_read_PLL_DIV() & SSEL) |
dpm_state_table[index].csel;
bfin_write_PLL_DIV(plldiv);
+#else
+ ret = cpu_set_cclk(cpu, freqs.new * 1000);
+ if (ret != 0) {
+ pr_debug("cpufreq set freq failed %d\n", ret);
+ break;
+ }
+#endif
on_each_cpu(bfin_adjust_core_timer, &index, 1);
#if defined(CONFIG_CYCLES_CLOCKSOURCE)
cycles = get_cycles();
@@ -161,7 +201,7 @@ static int bfin_target(struct cpufreq_policy *poli,
}
pr_debug("cpufreq: done\n");
- return 0;
+ return ret;
}
static int bfin_verify_speed(struct cpufreq_policy *policy)
@@ -169,7 +209,7 @@ static int bfin_verify_speed(struct cpufreq_policy *policy)
return cpufreq_frequency_table_verify(policy, bfin_freq_table);
}
-static int __init __bfin_cpu_init(struct cpufreq_policy *policy)
+static int __bfin_cpu_init(struct cpufreq_policy *policy)
{
unsigned long cclk, sclk;
diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S
index 1c534d298de4..de99f3aac2c5 100644
--- a/arch/blackfin/mach-common/dpmc_modes.S
+++ b/arch/blackfin/mach-common/dpmc_modes.S
@@ -10,7 +10,6 @@
#include <asm/dpmc.h>
.section .l1.text
-
ENTRY(_sleep_mode)
[--SP] = (R7:4, P5:3);
[--SP] = RETS;
@@ -43,6 +42,9 @@ ENTRY(_sleep_mode)
BITCLR (R7, 5);
w[p0] = R7.L;
IDLE;
+
+ bfin_init_pm_bench_cycles;
+
call _test_pll_locked;
RETS = [SP++];
@@ -58,12 +60,13 @@ ENDPROC(_sleep_mode)
*
* We accept just one argument -- the value to write to VR_CTL.
*/
+
ENTRY(_hibernate_mode)
/* Save/setup the regs we need early for minor pipeline optimization */
R4 = R0;
+
P3.H = hi(VR_CTL);
P3.L = lo(VR_CTL);
-
/* Disable all wakeup sources */
R0 = IWR_DISABLE_ALL;
R1 = IWR_DISABLE_ALL;
@@ -74,6 +77,9 @@ ENTRY(_hibernate_mode)
/* Finally, we climb into our cave to hibernate */
W[P3] = R4.L;
+
+ bfin_init_pm_bench_cycles;
+
CLI R2;
IDLE;
.Lforever:
@@ -158,6 +164,8 @@ ENTRY(_sleep_deeper)
SSYNC;
IDLE;
+ bfin_init_pm_bench_cycles;
+
call _test_pll_locked;
P0.H = hi(PLL_DIV);
@@ -276,327 +284,10 @@ ENTRY(_test_pll_locked)
ENDPROC(_test_pll_locked)
.section .text
-
-#define PM_REG0 R7
-#define PM_REG1 R6
-#define PM_REG2 R5
-#define PM_REG3 R4
-#define PM_REG4 R3
-#define PM_REG5 R2
-#define PM_REG6 R1
-#define PM_REG7 R0
-#define PM_REG8 P5
-#define PM_REG9 P4
-#define PM_REG10 P3
-#define PM_REG11 P2
-#define PM_REG12 P1
-#define PM_REG13 P0
-
-#define PM_REGSET0 R7:7
-#define PM_REGSET1 R7:6
-#define PM_REGSET2 R7:5
-#define PM_REGSET3 R7:4
-#define PM_REGSET4 R7:3
-#define PM_REGSET5 R7:2
-#define PM_REGSET6 R7:1
-#define PM_REGSET7 R7:0
-#define PM_REGSET8 R7:0, P5:5
-#define PM_REGSET9 R7:0, P5:4
-#define PM_REGSET10 R7:0, P5:3
-#define PM_REGSET11 R7:0, P5:2
-#define PM_REGSET12 R7:0, P5:1
-#define PM_REGSET13 R7:0, P5:0
-
-#define _PM_PUSH(n, x, w, base) PM_REG##n = w[FP + ((x) - (base))];
-#define _PM_POP(n, x, w, base) w[FP + ((x) - (base))] = PM_REG##n;
-#define PM_PUSH_SYNC(n) [--sp] = (PM_REGSET##n);
-#define PM_POP_SYNC(n) (PM_REGSET##n) = [sp++];
-#define PM_PUSH(n, x) PM_REG##n = [FP++];
-#define PM_POP(n, x) [FP--] = PM_REG##n;
-#define PM_CORE_PUSH(n, x) _PM_PUSH(n, x, , COREMMR_BASE)
-#define PM_CORE_POP(n, x) _PM_POP(n, x, , COREMMR_BASE)
-#define PM_SYS_PUSH(n, x) _PM_PUSH(n, x, , SYSMMR_BASE)
-#define PM_SYS_POP(n, x) _PM_POP(n, x, , SYSMMR_BASE)
-#define PM_SYS_PUSH16(n, x) _PM_PUSH(n, x, w, SYSMMR_BASE)
-#define PM_SYS_POP16(n, x) _PM_POP(n, x, w, SYSMMR_BASE)
-
ENTRY(_do_hibernate)
- /*
- * Save the core regs early so we can blow them away when
- * saving/restoring MMR states
- */
- [--sp] = (R7:0, P5:0);
- [--sp] = fp;
- [--sp] = usp;
-
- [--sp] = i0;
- [--sp] = i1;
- [--sp] = i2;
- [--sp] = i3;
-
- [--sp] = m0;
- [--sp] = m1;
- [--sp] = m2;
- [--sp] = m3;
-
- [--sp] = l0;
- [--sp] = l1;
- [--sp] = l2;
- [--sp] = l3;
-
- [--sp] = b0;
- [--sp] = b1;
- [--sp] = b2;
- [--sp] = b3;
- [--sp] = a0.x;
- [--sp] = a0.w;
- [--sp] = a1.x;
- [--sp] = a1.w;
-
- [--sp] = LC0;
- [--sp] = LC1;
- [--sp] = LT0;
- [--sp] = LT1;
- [--sp] = LB0;
- [--sp] = LB1;
-
- /* We can't push RETI directly as that'll change IPEND[4] */
- r7 = RETI;
- [--sp] = RETS;
- [--sp] = ASTAT;
- [--sp] = CYCLES;
- [--sp] = CYCLES2;
- [--sp] = SYSCFG;
- [--sp] = RETX;
- [--sp] = SEQSTAT;
- [--sp] = r7;
-
- /* Save first func arg in M3 */
- M3 = R0;
-
- /* Save system MMRs */
- FP.H = hi(SYSMMR_BASE);
- FP.L = lo(SYSMMR_BASE);
-
-#ifdef SIC_IMASK0
- PM_SYS_PUSH(0, SIC_IMASK0)
- PM_SYS_PUSH(1, SIC_IMASK1)
-# ifdef SIC_IMASK2
- PM_SYS_PUSH(2, SIC_IMASK2)
-# endif
-#else
- PM_SYS_PUSH(0, SIC_IMASK)
-#endif
-#ifdef SIC_IAR0
- PM_SYS_PUSH(3, SIC_IAR0)
- PM_SYS_PUSH(4, SIC_IAR1)
- PM_SYS_PUSH(5, SIC_IAR2)
-#endif
-#ifdef SIC_IAR3
- PM_SYS_PUSH(6, SIC_IAR3)
-#endif
-#ifdef SIC_IAR4
- PM_SYS_PUSH(7, SIC_IAR4)
- PM_SYS_PUSH(8, SIC_IAR5)
- PM_SYS_PUSH(9, SIC_IAR6)
-#endif
-#ifdef SIC_IAR7
- PM_SYS_PUSH(10, SIC_IAR7)
-#endif
-#ifdef SIC_IAR8
- PM_SYS_PUSH(11, SIC_IAR8)
- PM_SYS_PUSH(12, SIC_IAR9)
- PM_SYS_PUSH(13, SIC_IAR10)
-#endif
- PM_PUSH_SYNC(13)
-#ifdef SIC_IAR11
- PM_SYS_PUSH(0, SIC_IAR11)
-#endif
-
-#ifdef SIC_IWR
- PM_SYS_PUSH(1, SIC_IWR)
-#endif
-#ifdef SIC_IWR0
- PM_SYS_PUSH(1, SIC_IWR0)
-#endif
-#ifdef SIC_IWR1
- PM_SYS_PUSH(2, SIC_IWR1)
-#endif
-#ifdef SIC_IWR2
- PM_SYS_PUSH(3, SIC_IWR2)
-#endif
-
-#ifdef PINT0_ASSIGN
- PM_SYS_PUSH(4, PINT0_MASK_SET)
- PM_SYS_PUSH(5, PINT1_MASK_SET)
- PM_SYS_PUSH(6, PINT2_MASK_SET)
- PM_SYS_PUSH(7, PINT3_MASK_SET)
- PM_SYS_PUSH(8, PINT0_ASSIGN)
- PM_SYS_PUSH(9, PINT1_ASSIGN)
- PM_SYS_PUSH(10, PINT2_ASSIGN)
- PM_SYS_PUSH(11, PINT3_ASSIGN)
- PM_SYS_PUSH(12, PINT0_INVERT_SET)
- PM_SYS_PUSH(13, PINT1_INVERT_SET)
- PM_PUSH_SYNC(13)
- PM_SYS_PUSH(0, PINT2_INVERT_SET)
- PM_SYS_PUSH(1, PINT3_INVERT_SET)
- PM_SYS_PUSH(2, PINT0_EDGE_SET)
- PM_SYS_PUSH(3, PINT1_EDGE_SET)
- PM_SYS_PUSH(4, PINT2_EDGE_SET)
- PM_SYS_PUSH(5, PINT3_EDGE_SET)
-#endif
-
- PM_SYS_PUSH16(6, SYSCR)
-
- PM_SYS_PUSH16(7, EBIU_AMGCTL)
- PM_SYS_PUSH(8, EBIU_AMBCTL0)
- PM_SYS_PUSH(9, EBIU_AMBCTL1)
-#ifdef EBIU_FCTL
- PM_SYS_PUSH(10, EBIU_MBSCTL)
- PM_SYS_PUSH(11, EBIU_MODE)
- PM_SYS_PUSH(12, EBIU_FCTL)
- PM_PUSH_SYNC(12)
-#else
- PM_PUSH_SYNC(9)
-#endif
-
- /* Save Core MMRs */
- I0.H = hi(COREMMR_BASE);
- I0.L = lo(COREMMR_BASE);
- I1 = I0;
- I2 = I0;
- I3 = I0;
- B0 = I0;
- B1 = I0;
- B2 = I0;
- B3 = I0;
- I1.L = lo(DCPLB_ADDR0);
- I2.L = lo(DCPLB_DATA0);
- I3.L = lo(ICPLB_ADDR0);
- B0.L = lo(ICPLB_DATA0);
- B1.L = lo(EVT2);
- B2.L = lo(IMASK);
- B3.L = lo(TCNTL);
-
- /* DCPLB Addr */
- FP = I1;
- PM_PUSH(0, DCPLB_ADDR0)
- PM_PUSH(1, DCPLB_ADDR1)
- PM_PUSH(2, DCPLB_ADDR2)
- PM_PUSH(3, DCPLB_ADDR3)
- PM_PUSH(4, DCPLB_ADDR4)
- PM_PUSH(5, DCPLB_ADDR5)
- PM_PUSH(6, DCPLB_ADDR6)
- PM_PUSH(7, DCPLB_ADDR7)
- PM_PUSH(8, DCPLB_ADDR8)
- PM_PUSH(9, DCPLB_ADDR9)
- PM_PUSH(10, DCPLB_ADDR10)
- PM_PUSH(11, DCPLB_ADDR11)
- PM_PUSH(12, DCPLB_ADDR12)
- PM_PUSH(13, DCPLB_ADDR13)
- PM_PUSH_SYNC(13)
- PM_PUSH(0, DCPLB_ADDR14)
- PM_PUSH(1, DCPLB_ADDR15)
-
- /* DCPLB Data */
- FP = I2;
- PM_PUSH(2, DCPLB_DATA0)
- PM_PUSH(3, DCPLB_DATA1)
- PM_PUSH(4, DCPLB_DATA2)
- PM_PUSH(5, DCPLB_DATA3)
- PM_PUSH(6, DCPLB_DATA4)
- PM_PUSH(7, DCPLB_DATA5)
- PM_PUSH(8, DCPLB_DATA6)
- PM_PUSH(9, DCPLB_DATA7)
- PM_PUSH(10, DCPLB_DATA8)
- PM_PUSH(11, DCPLB_DATA9)
- PM_PUSH(12, DCPLB_DATA10)
- PM_PUSH(13, DCPLB_DATA11)
- PM_PUSH_SYNC(13)
- PM_PUSH(0, DCPLB_DATA12)
- PM_PUSH(1, DCPLB_DATA13)
- PM_PUSH(2, DCPLB_DATA14)
- PM_PUSH(3, DCPLB_DATA15)
-
- /* ICPLB Addr */
- FP = I3;
- PM_PUSH(4, ICPLB_ADDR0)
- PM_PUSH(5, ICPLB_ADDR1)
- PM_PUSH(6, ICPLB_ADDR2)
- PM_PUSH(7, ICPLB_ADDR3)
- PM_PUSH(8, ICPLB_ADDR4)
- PM_PUSH(9, ICPLB_ADDR5)
- PM_PUSH(10, ICPLB_ADDR6)
- PM_PUSH(11, ICPLB_ADDR7)
- PM_PUSH(12, ICPLB_ADDR8)
- PM_PUSH(13, ICPLB_ADDR9)
- PM_PUSH_SYNC(13)
- PM_PUSH(0, ICPLB_ADDR10)
- PM_PUSH(1, ICPLB_ADDR11)
- PM_PUSH(2, ICPLB_ADDR12)
- PM_PUSH(3, ICPLB_ADDR13)
- PM_PUSH(4, ICPLB_ADDR14)
- PM_PUSH(5, ICPLB_ADDR15)
-
- /* ICPLB Data */
- FP = B0;
- PM_PUSH(6, ICPLB_DATA0)
- PM_PUSH(7, ICPLB_DATA1)
- PM_PUSH(8, ICPLB_DATA2)
- PM_PUSH(9, ICPLB_DATA3)
- PM_PUSH(10, ICPLB_DATA4)
- PM_PUSH(11, ICPLB_DATA5)
- PM_PUSH(12, ICPLB_DATA6)
- PM_PUSH(13, ICPLB_DATA7)
- PM_PUSH_SYNC(13)
- PM_PUSH(0, ICPLB_DATA8)
- PM_PUSH(1, ICPLB_DATA9)
- PM_PUSH(2, ICPLB_DATA10)
- PM_PUSH(3, ICPLB_DATA11)
- PM_PUSH(4, ICPLB_DATA12)
- PM_PUSH(5, ICPLB_DATA13)
- PM_PUSH(6, ICPLB_DATA14)
- PM_PUSH(7, ICPLB_DATA15)
-
- /* Event Vectors */
- FP = B1;
- PM_PUSH(8, EVT2)
- PM_PUSH(9, EVT3)
- FP += 4; /* EVT4 */
- PM_PUSH(10, EVT5)
- PM_PUSH(11, EVT6)
- PM_PUSH(12, EVT7)
- PM_PUSH(13, EVT8)
- PM_PUSH_SYNC(13)
- PM_PUSH(0, EVT9)
- PM_PUSH(1, EVT10)
- PM_PUSH(2, EVT11)
- PM_PUSH(3, EVT12)
- PM_PUSH(4, EVT13)
- PM_PUSH(5, EVT14)
- PM_PUSH(6, EVT15)
-
- /* CEC */
- FP = B2;
- PM_PUSH(7, IMASK)
- FP += 4; /* IPEND */
- PM_PUSH(8, ILAT)
- PM_PUSH(9, IPRIO)
-
- /* Core Timer */
- FP = B3;
- PM_PUSH(10, TCNTL)
- PM_PUSH(11, TPERIOD)
- PM_PUSH(12, TSCALE)
- PM_PUSH(13, TCOUNT)
- PM_PUSH_SYNC(13)
-
- /* Misc non-contiguous registers */
- FP = I0;
- PM_CORE_PUSH(0, DMEM_CONTROL);
- PM_CORE_PUSH(1, IMEM_CONTROL);
- PM_CORE_PUSH(2, TBUFCTL);
- PM_PUSH_SYNC(2)
+ bfin_cpu_reg_save;
+ bfin_sys_mmr_save;
+ bfin_core_mmr_save;
/* Setup args to hibernate mode early for pipeline optimization */
R0 = M3;
@@ -618,274 +309,9 @@ ENTRY(_do_hibernate)
.Lpm_resume_here:
- /* Restore Core MMRs */
- I0.H = hi(COREMMR_BASE);
- I0.L = lo(COREMMR_BASE);
- I1 = I0;
- I2 = I0;
- I3 = I0;
- B0 = I0;
- B1 = I0;
- B2 = I0;
- B3 = I0;
- I1.L = lo(DCPLB_ADDR15);
- I2.L = lo(DCPLB_DATA15);
- I3.L = lo(ICPLB_ADDR15);
- B0.L = lo(ICPLB_DATA15);
- B1.L = lo(EVT15);
- B2.L = lo(IPRIO);
- B3.L = lo(TCOUNT);
-
- /* Misc non-contiguous registers */
- FP = I0;
- PM_POP_SYNC(2)
- PM_CORE_POP(2, TBUFCTL)
- PM_CORE_POP(1, IMEM_CONTROL)
- PM_CORE_POP(0, DMEM_CONTROL)
-
- /* Core Timer */
- PM_POP_SYNC(13)
- FP = B3;
- PM_POP(13, TCOUNT)
- PM_POP(12, TSCALE)
- PM_POP(11, TPERIOD)
- PM_POP(10, TCNTL)
-
- /* CEC */
- FP = B2;
- PM_POP(9, IPRIO)
- PM_POP(8, ILAT)
- FP += -4; /* IPEND */
- PM_POP(7, IMASK)
-
- /* Event Vectors */
- FP = B1;
- PM_POP(6, EVT15)
- PM_POP(5, EVT14)
- PM_POP(4, EVT13)
- PM_POP(3, EVT12)
- PM_POP(2, EVT11)
- PM_POP(1, EVT10)
- PM_POP(0, EVT9)
- PM_POP_SYNC(13)
- PM_POP(13, EVT8)
- PM_POP(12, EVT7)
- PM_POP(11, EVT6)
- PM_POP(10, EVT5)
- FP += -4; /* EVT4 */
- PM_POP(9, EVT3)
- PM_POP(8, EVT2)
-
- /* ICPLB Data */
- FP = B0;
- PM_POP(7, ICPLB_DATA15)
- PM_POP(6, ICPLB_DATA14)
- PM_POP(5, ICPLB_DATA13)
- PM_POP(4, ICPLB_DATA12)
- PM_POP(3, ICPLB_DATA11)
- PM_POP(2, ICPLB_DATA10)
- PM_POP(1, ICPLB_DATA9)
- PM_POP(0, ICPLB_DATA8)
- PM_POP_SYNC(13)
- PM_POP(13, ICPLB_DATA7)
- PM_POP(12, ICPLB_DATA6)
- PM_POP(11, ICPLB_DATA5)
- PM_POP(10, ICPLB_DATA4)
- PM_POP(9, ICPLB_DATA3)
- PM_POP(8, ICPLB_DATA2)
- PM_POP(7, ICPLB_DATA1)
- PM_POP(6, ICPLB_DATA0)
-
- /* ICPLB Addr */
- FP = I3;
- PM_POP(5, ICPLB_ADDR15)
- PM_POP(4, ICPLB_ADDR14)
- PM_POP(3, ICPLB_ADDR13)
- PM_POP(2, ICPLB_ADDR12)
- PM_POP(1, ICPLB_ADDR11)
- PM_POP(0, ICPLB_ADDR10)
- PM_POP_SYNC(13)
- PM_POP(13, ICPLB_ADDR9)
- PM_POP(12, ICPLB_ADDR8)
- PM_POP(11, ICPLB_ADDR7)
- PM_POP(10, ICPLB_ADDR6)
- PM_POP(9, ICPLB_ADDR5)
- PM_POP(8, ICPLB_ADDR4)
- PM_POP(7, ICPLB_ADDR3)
- PM_POP(6, ICPLB_ADDR2)
- PM_POP(5, ICPLB_ADDR1)
- PM_POP(4, ICPLB_ADDR0)
-
- /* DCPLB Data */
- FP = I2;
- PM_POP(3, DCPLB_DATA15)
- PM_POP(2, DCPLB_DATA14)
- PM_POP(1, DCPLB_DATA13)
- PM_POP(0, DCPLB_DATA12)
- PM_POP_SYNC(13)
- PM_POP(13, DCPLB_DATA11)
- PM_POP(12, DCPLB_DATA10)
- PM_POP(11, DCPLB_DATA9)
- PM_POP(10, DCPLB_DATA8)
- PM_POP(9, DCPLB_DATA7)
- PM_POP(8, DCPLB_DATA6)
- PM_POP(7, DCPLB_DATA5)
- PM_POP(6, DCPLB_DATA4)
- PM_POP(5, DCPLB_DATA3)
- PM_POP(4, DCPLB_DATA2)
- PM_POP(3, DCPLB_DATA1)
- PM_POP(2, DCPLB_DATA0)
-
- /* DCPLB Addr */
- FP = I1;
- PM_POP(1, DCPLB_ADDR15)
- PM_POP(0, DCPLB_ADDR14)
- PM_POP_SYNC(13)
- PM_POP(13, DCPLB_ADDR13)
- PM_POP(12, DCPLB_ADDR12)
- PM_POP(11, DCPLB_ADDR11)
- PM_POP(10, DCPLB_ADDR10)
- PM_POP(9, DCPLB_ADDR9)
- PM_POP(8, DCPLB_ADDR8)
- PM_POP(7, DCPLB_ADDR7)
- PM_POP(6, DCPLB_ADDR6)
- PM_POP(5, DCPLB_ADDR5)
- PM_POP(4, DCPLB_ADDR4)
- PM_POP(3, DCPLB_ADDR3)
- PM_POP(2, DCPLB_ADDR2)
- PM_POP(1, DCPLB_ADDR1)
- PM_POP(0, DCPLB_ADDR0)
-
- /* Restore System MMRs */
- FP.H = hi(SYSMMR_BASE);
- FP.L = lo(SYSMMR_BASE);
-
-#ifdef EBIU_FCTL
- PM_POP_SYNC(12)
- PM_SYS_POP(12, EBIU_FCTL)
- PM_SYS_POP(11, EBIU_MODE)
- PM_SYS_POP(10, EBIU_MBSCTL)
-#else
- PM_POP_SYNC(9)
-#endif
- PM_SYS_POP(9, EBIU_AMBCTL1)
- PM_SYS_POP(8, EBIU_AMBCTL0)
- PM_SYS_POP16(7, EBIU_AMGCTL)
-
- PM_SYS_POP16(6, SYSCR)
-
-#ifdef PINT0_ASSIGN
- PM_SYS_POP(5, PINT3_EDGE_SET)
- PM_SYS_POP(4, PINT2_EDGE_SET)
- PM_SYS_POP(3, PINT1_EDGE_SET)
- PM_SYS_POP(2, PINT0_EDGE_SET)
- PM_SYS_POP(1, PINT3_INVERT_SET)
- PM_SYS_POP(0, PINT2_INVERT_SET)
- PM_POP_SYNC(13)
- PM_SYS_POP(13, PINT1_INVERT_SET)
- PM_SYS_POP(12, PINT0_INVERT_SET)
- PM_SYS_POP(11, PINT3_ASSIGN)
- PM_SYS_POP(10, PINT2_ASSIGN)
- PM_SYS_POP(9, PINT1_ASSIGN)
- PM_SYS_POP(8, PINT0_ASSIGN)
- PM_SYS_POP(7, PINT3_MASK_SET)
- PM_SYS_POP(6, PINT2_MASK_SET)
- PM_SYS_POP(5, PINT1_MASK_SET)
- PM_SYS_POP(4, PINT0_MASK_SET)
-#endif
-
-#ifdef SIC_IWR2
- PM_SYS_POP(3, SIC_IWR2)
-#endif
-#ifdef SIC_IWR1
- PM_SYS_POP(2, SIC_IWR1)
-#endif
-#ifdef SIC_IWR0
- PM_SYS_POP(1, SIC_IWR0)
-#endif
-#ifdef SIC_IWR
- PM_SYS_POP(1, SIC_IWR)
-#endif
-
-#ifdef SIC_IAR11
- PM_SYS_POP(0, SIC_IAR11)
-#endif
- PM_POP_SYNC(13)
-#ifdef SIC_IAR8
- PM_SYS_POP(13, SIC_IAR10)
- PM_SYS_POP(12, SIC_IAR9)
- PM_SYS_POP(11, SIC_IAR8)
-#endif
-#ifdef SIC_IAR7
- PM_SYS_POP(10, SIC_IAR7)
-#endif
-#ifdef SIC_IAR6
- PM_SYS_POP(9, SIC_IAR6)
- PM_SYS_POP(8, SIC_IAR5)
- PM_SYS_POP(7, SIC_IAR4)
-#endif
-#ifdef SIC_IAR3
- PM_SYS_POP(6, SIC_IAR3)
-#endif
-#ifdef SIC_IAR0
- PM_SYS_POP(5, SIC_IAR2)
- PM_SYS_POP(4, SIC_IAR1)
- PM_SYS_POP(3, SIC_IAR0)
-#endif
-#ifdef SIC_IMASK0
-# ifdef SIC_IMASK2
- PM_SYS_POP(2, SIC_IMASK2)
-# endif
- PM_SYS_POP(1, SIC_IMASK1)
- PM_SYS_POP(0, SIC_IMASK0)
-#else
- PM_SYS_POP(0, SIC_IMASK)
-#endif
-
- /* Restore Core Registers */
- RETI = [sp++];
- SEQSTAT = [sp++];
- RETX = [sp++];
- SYSCFG = [sp++];
- CYCLES2 = [sp++];
- CYCLES = [sp++];
- ASTAT = [sp++];
- RETS = [sp++];
-
- LB1 = [sp++];
- LB0 = [sp++];
- LT1 = [sp++];
- LT0 = [sp++];
- LC1 = [sp++];
- LC0 = [sp++];
-
- a1.w = [sp++];
- a1.x = [sp++];
- a0.w = [sp++];
- a0.x = [sp++];
- b3 = [sp++];
- b2 = [sp++];
- b1 = [sp++];
- b0 = [sp++];
-
- l3 = [sp++];
- l2 = [sp++];
- l1 = [sp++];
- l0 = [sp++];
-
- m3 = [sp++];
- m2 = [sp++];
- m1 = [sp++];
- m0 = [sp++];
-
- i3 = [sp++];
- i2 = [sp++];
- i1 = [sp++];
- i0 = [sp++];
-
- usp = [sp++];
- fp = [sp++];
- (R7:0, P5:0) = [sp++];
+ bfin_core_mmr_restore;
+ bfin_sys_mmr_restore;
+ bfin_cpu_reg_restore;
[--sp] = RETI; /* Clear Global Interrupt Disable */
SP += 4;
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 4698a9800522..80aa2535e2c9 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -1141,7 +1141,8 @@ ENTRY(_schedule_and_signal_from_int)
sti r0;
/* finish the userspace "atomic" functions for it */
- r1 = FIXED_CODE_END;
+ r1.l = lo(FIXED_CODE_END);
+ r1.h = hi(FIXED_CODE_END);
r2 = [sp + PT_PC];
cc = r1 <= r2;
if cc jump .Lresume_userspace (bp);
@@ -1376,7 +1377,7 @@ END(_ex_table)
ENTRY(_sys_call_table)
.long _sys_restart_syscall /* 0 */
.long _sys_exit
- .long _sys_fork
+ .long _sys_ni_syscall /* fork */
.long _sys_read
.long _sys_write
.long _sys_open /* 5 */
diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S
index 8b4d98854403..31515f0146f9 100644
--- a/arch/blackfin/mach-common/head.S
+++ b/arch/blackfin/mach-common/head.S
@@ -210,14 +210,12 @@ ENDPROC(__start)
ENTRY(_real_start)
/* Enable nested interrupts */
[--sp] = reti;
-
/* watchdog off for now */
p0.l = lo(WDOG_CTL);
p0.h = hi(WDOG_CTL);
r0 = 0xAD6(z);
w[p0] = r0;
ssync;
-
/* Pass the u-boot arguments to the global value command line */
R0 = R7;
call _cmdline_init;
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index 332dace6af34..2729cba715b0 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -16,6 +16,8 @@
#include <linux/seq_file.h>
#include <linux/irq.h>
#include <linux/sched.h>
+#include <linux/syscore_ops.h>
+#include <asm/delay.h>
#ifdef CONFIG_IPIPE
#include <linux/ipipe.h>
#endif
@@ -25,7 +27,11 @@
#include <asm/irq_handler.h>
#include <asm/dpmc.h>
-#define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1))
+#ifndef CONFIG_BF60x
+# define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1))
+#else
+# define SIC_SYSIRQ(irq) ((irq) - IVG15)
+#endif
/*
* NOTES:
@@ -50,6 +56,7 @@ unsigned long bfin_sic_iwr[3]; /* Up to 3 SIC_IWRx registers */
unsigned vr_wakeup;
#endif
+#ifndef CONFIG_BF60x
static struct ivgx {
/* irq number for request_irq, available in mach-bf5xx/irq.h */
unsigned int irqno;
@@ -78,7 +85,8 @@ static void __init search_IAR(void)
for (irqN = 0; irqN < NR_PERI_INTS; irqN += 4) {
int irqn;
- u32 iar = bfin_read32((unsigned long *)SIC_IAR0 +
+ u32 iar =
+ bfin_read32((unsigned long *)SIC_IAR0 +
#if defined(CONFIG_BF51x) || defined(CONFIG_BF52x) || \
defined(CONFIG_BF538) || defined(CONFIG_BF539)
((irqN % 32) >> 3) + ((irqN / 32) * ((SIC_IAR4 - SIC_IAR0) / 4))
@@ -86,7 +94,6 @@ static void __init search_IAR(void)
(irqN >> 3)
#endif
);
-
for (irqn = irqN; irqn < irqN + 4; ++irqn) {
int iar_shift = (irqn & 7) * 4;
if (ivg == (0xf & (iar >> iar_shift))) {
@@ -99,11 +106,11 @@ static void __init search_IAR(void)
}
}
}
+#endif
/*
* This is for core internal IRQs
*/
-
void bfin_ack_noop(struct irq_data *d)
{
/* Dummy function. */
@@ -136,21 +143,21 @@ static void bfin_core_unmask_irq(struct irq_data *d)
void bfin_internal_mask_irq(unsigned int irq)
{
unsigned long flags = hard_local_irq_save();
-
+#ifndef CONFIG_BF60x
#ifdef SIC_IMASK0
unsigned mask_bank = SIC_SYSIRQ(irq) / 32;
unsigned mask_bit = SIC_SYSIRQ(irq) % 32;
bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &
- ~(1 << mask_bit));
-# ifdef CONFIG_SMP
+ ~(1 << mask_bit));
+# if defined(CONFIG_SMP) || defined(CONFIG_ICC)
bfin_write_SICB_IMASK(mask_bank, bfin_read_SICB_IMASK(mask_bank) &
- ~(1 << mask_bit));
+ ~(1 << mask_bit));
# endif
#else
bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
- ~(1 << SIC_SYSIRQ(irq)));
+ ~(1 << SIC_SYSIRQ(irq)));
+#endif /* end of SIC_IMASK0 */
#endif
-
hard_local_irq_restore(flags);
}
@@ -160,7 +167,7 @@ static void bfin_internal_mask_irq_chip(struct irq_data *d)
}
#ifdef CONFIG_SMP
-static void bfin_internal_unmask_irq_affinity(unsigned int irq,
+void bfin_internal_unmask_irq_affinity(unsigned int irq,
const struct cpumask *affinity)
#else
void bfin_internal_unmask_irq(unsigned int irq)
@@ -168,6 +175,7 @@ void bfin_internal_unmask_irq(unsigned int irq)
{
unsigned long flags = hard_local_irq_save();
+#ifndef CONFIG_BF60x
#ifdef SIC_IMASK0
unsigned mask_bank = SIC_SYSIRQ(irq) / 32;
unsigned mask_bit = SIC_SYSIRQ(irq) % 32;
@@ -175,22 +183,239 @@ void bfin_internal_unmask_irq(unsigned int irq)
if (cpumask_test_cpu(0, affinity))
# endif
bfin_write_SIC_IMASK(mask_bank,
- bfin_read_SIC_IMASK(mask_bank) |
- (1 << mask_bit));
+ bfin_read_SIC_IMASK(mask_bank) |
+ (1 << mask_bit));
# ifdef CONFIG_SMP
if (cpumask_test_cpu(1, affinity))
bfin_write_SICB_IMASK(mask_bank,
- bfin_read_SICB_IMASK(mask_bank) |
- (1 << mask_bit));
+ bfin_read_SICB_IMASK(mask_bank) |
+ (1 << mask_bit));
# endif
#else
bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |
- (1 << SIC_SYSIRQ(irq)));
+ (1 << SIC_SYSIRQ(irq)));
+#endif
#endif
+ hard_local_irq_restore(flags);
+}
+
+#ifdef CONFIG_BF60x
+static void bfin_sec_preflow_handler(struct irq_data *d)
+{
+ unsigned long flags = hard_local_irq_save();
+ unsigned int sid = SIC_SYSIRQ(d->irq);
+
+ bfin_write_SEC_SCI(0, SEC_CSID, sid);
+
+ hard_local_irq_restore(flags);
+}
+
+static void bfin_sec_mask_ack_irq(struct irq_data *d)
+{
+ unsigned long flags = hard_local_irq_save();
+ unsigned int sid = SIC_SYSIRQ(d->irq);
+
+ bfin_write_SEC_SCI(0, SEC_CSID, sid);
hard_local_irq_restore(flags);
}
+static void bfin_sec_unmask_irq(struct irq_data *d)
+{
+ unsigned long flags = hard_local_irq_save();
+ unsigned int sid = SIC_SYSIRQ(d->irq);
+
+ bfin_write32(SEC_END, sid);
+
+ hard_local_irq_restore(flags);
+}
+
+static void bfin_sec_enable_ssi(unsigned int sid)
+{
+ unsigned long flags = hard_local_irq_save();
+ uint32_t reg_sctl = bfin_read_SEC_SCTL(sid);
+
+ reg_sctl |= SEC_SCTL_SRC_EN;
+ bfin_write_SEC_SCTL(sid, reg_sctl);
+
+ hard_local_irq_restore(flags);
+}
+
+static void bfin_sec_disable_ssi(unsigned int sid)
+{
+ unsigned long flags = hard_local_irq_save();
+ uint32_t reg_sctl = bfin_read_SEC_SCTL(sid);
+
+ reg_sctl &= ((uint32_t)~SEC_SCTL_SRC_EN);
+ bfin_write_SEC_SCTL(sid, reg_sctl);
+
+ hard_local_irq_restore(flags);
+}
+
+static void bfin_sec_set_ssi_coreid(unsigned int sid, unsigned int coreid)
+{
+ unsigned long flags = hard_local_irq_save();
+ uint32_t reg_sctl = bfin_read_SEC_SCTL(sid);
+
+ reg_sctl &= ((uint32_t)~SEC_SCTL_CTG);
+ bfin_write_SEC_SCTL(sid, reg_sctl | ((coreid << 20) & SEC_SCTL_CTG));
+
+ hard_local_irq_restore(flags);
+}
+
+static void bfin_sec_enable_sci(unsigned int sid)
+{
+ unsigned long flags = hard_local_irq_save();
+ uint32_t reg_sctl = bfin_read_SEC_SCTL(sid);
+
+ if (sid == SIC_SYSIRQ(IRQ_WATCH0))
+ reg_sctl |= SEC_SCTL_FAULT_EN;
+ else
+ reg_sctl |= SEC_SCTL_INT_EN;
+ bfin_write_SEC_SCTL(sid, reg_sctl);
+
+ hard_local_irq_restore(flags);
+}
+
+static void bfin_sec_disable_sci(unsigned int sid)
+{
+ unsigned long flags = hard_local_irq_save();
+ uint32_t reg_sctl = bfin_read_SEC_SCTL(sid);
+
+ reg_sctl &= ((uint32_t)~SEC_SCTL_INT_EN);
+ bfin_write_SEC_SCTL(sid, reg_sctl);
+
+ hard_local_irq_restore(flags);
+}
+
+static void bfin_sec_enable(struct irq_data *d)
+{
+ unsigned long flags = hard_local_irq_save();
+ unsigned int sid = SIC_SYSIRQ(d->irq);
+
+ bfin_sec_enable_sci(sid);
+ bfin_sec_enable_ssi(sid);
+
+ hard_local_irq_restore(flags);
+}
+
+static void bfin_sec_disable(struct irq_data *d)
+{
+ unsigned long flags = hard_local_irq_save();
+ unsigned int sid = SIC_SYSIRQ(d->irq);
+
+ bfin_sec_disable_sci(sid);
+ bfin_sec_disable_ssi(sid);
+
+ hard_local_irq_restore(flags);
+}
+
+static void bfin_sec_raise_irq(unsigned int sid)
+{
+ unsigned long flags = hard_local_irq_save();
+
+ bfin_write32(SEC_RAISE, sid);
+
+ hard_local_irq_restore(flags);
+}
+
+static void init_software_driven_irq(void)
+{
+ bfin_sec_set_ssi_coreid(34, 0);
+ bfin_sec_set_ssi_coreid(35, 1);
+ bfin_sec_set_ssi_coreid(36, 0);
+ bfin_sec_set_ssi_coreid(37, 1);
+}
+
+void bfin_sec_resume(void)
+{
+ bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET);
+ udelay(100);
+ bfin_write_SEC_GCTL(SEC_GCTL_EN);
+ bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
+}
+
+void handle_sec_sfi_fault(uint32_t gstat)
+{
+
+}
+
+void handle_sec_sci_fault(uint32_t gstat)
+{
+ uint32_t core_id;
+ uint32_t cstat;
+
+ core_id = gstat & SEC_GSTAT_SCI;
+ cstat = bfin_read_SEC_SCI(core_id, SEC_CSTAT);
+ if (cstat & SEC_CSTAT_ERR) {
+ switch (cstat & SEC_CSTAT_ERRC) {
+ case SEC_CSTAT_ACKERR:
+ printk(KERN_DEBUG "sec ack err\n");
+ break;
+ default:
+ printk(KERN_DEBUG "sec sci unknow err\n");
+ }
+ }
+
+}
+
+void handle_sec_ssi_fault(uint32_t gstat)
+{
+ uint32_t sid;
+ uint32_t sstat;
+
+ sid = gstat & SEC_GSTAT_SID;
+ sstat = bfin_read_SEC_SSTAT(sid);
+
+}
+
+void handle_sec_fault(unsigned int irq, struct irq_desc *desc)
+{
+ uint32_t sec_gstat;
+
+ raw_spin_lock(&desc->lock);
+
+ sec_gstat = bfin_read32(SEC_GSTAT);
+ if (sec_gstat & SEC_GSTAT_ERR) {
+
+ switch (sec_gstat & SEC_GSTAT_ERRC) {
+ case 0:
+ handle_sec_sfi_fault(sec_gstat);
+ break;
+ case SEC_GSTAT_SCIERR:
+ handle_sec_sci_fault(sec_gstat);
+ break;
+ case SEC_GSTAT_SSIERR:
+ handle_sec_ssi_fault(sec_gstat);
+ break;
+ }
+
+
+ }
+
+ raw_spin_unlock(&desc->lock);
+}
+
+static int sec_suspend(void)
+{
+ return 0;
+}
+
+static void sec_resume(void)
+{
+ bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET);
+ udelay(100);
+ bfin_write_SEC_GCTL(SEC_GCTL_EN);
+ bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
+}
+
+static struct syscore_ops sec_pm_syscore_ops = {
+ .suspend = sec_suspend,
+ .resume = sec_resume,
+};
+
+#endif
+
#ifdef CONFIG_SMP
static void bfin_internal_unmask_irq_chip(struct irq_data *d)
{
@@ -212,7 +437,7 @@ static void bfin_internal_unmask_irq_chip(struct irq_data *d)
}
#endif
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && !defined(CONFIG_BF60x)
int bfin_internal_set_wake(unsigned int irq, unsigned int state)
{
u32 bank, bit, wakeup = 0;
@@ -271,22 +496,20 @@ static int bfin_internal_set_wake_chip(struct irq_data *d, unsigned int state)
return bfin_internal_set_wake(d->irq, state);
}
#else
+# define bfin_internal_set_wake(irq, state)
# define bfin_internal_set_wake_chip NULL
#endif
static struct irq_chip bfin_core_irqchip = {
.name = "CORE",
- .irq_ack = bfin_ack_noop,
.irq_mask = bfin_core_mask_irq,
.irq_unmask = bfin_core_unmask_irq,
};
static struct irq_chip bfin_internal_irqchip = {
.name = "INTN",
- .irq_ack = bfin_ack_noop,
.irq_mask = bfin_internal_mask_irq_chip,
.irq_unmask = bfin_internal_unmask_irq_chip,
- .irq_mask_ack = bfin_internal_mask_irq_chip,
.irq_disable = bfin_internal_mask_irq_chip,
.irq_enable = bfin_internal_unmask_irq_chip,
#ifdef CONFIG_SMP
@@ -295,6 +518,18 @@ static struct irq_chip bfin_internal_irqchip = {
.irq_set_wake = bfin_internal_set_wake_chip,
};
+#ifdef CONFIG_BF60x
+static struct irq_chip bfin_sec_irqchip = {
+ .name = "SEC",
+ .irq_mask_ack = bfin_sec_mask_ack_irq,
+ .irq_mask = bfin_sec_mask_ack_irq,
+ .irq_unmask = bfin_sec_unmask_irq,
+ .irq_eoi = bfin_sec_unmask_irq,
+ .irq_disable = bfin_sec_disable,
+ .irq_enable = bfin_sec_enable,
+};
+#endif
+
void bfin_handle_irq(unsigned irq)
{
#ifdef CONFIG_IPIPE
@@ -396,8 +631,6 @@ int bfin_mac_status_set_wake(struct irq_data *d, unsigned int state)
static struct irq_chip bfin_mac_status_irqchip = {
.name = "MACST",
- .irq_ack = bfin_ack_noop,
- .irq_mask_ack = bfin_mac_status_mask_irq,
.irq_mask = bfin_mac_status_mask_irq,
.irq_unmask = bfin_mac_status_unmask_irq,
.irq_set_wake = bfin_mac_status_set_wake,
@@ -421,15 +654,15 @@ void bfin_demux_mac_status_irq(unsigned int int_err_irq,
} else {
bfin_mac_status_ack_irq(irq);
pr_debug("IRQ %d:"
- " MASKED MAC ERROR INTERRUPT ASSERTED\n",
- irq);
+ " MASKED MAC ERROR INTERRUPT ASSERTED\n",
+ irq);
}
} else
printk(KERN_ERR
- "%s : %s : LINE %d :\nIRQ ?: MAC ERROR"
- " INTERRUPT ASSERTED BUT NO SOURCE FOUND"
- "(EMAC_SYSTAT=0x%X)\n",
- __func__, __FILE__, __LINE__, status);
+ "%s : %s : LINE %d :\nIRQ ?: MAC ERROR"
+ " INTERRUPT ASSERTED BUT NO SOURCE FOUND"
+ "(EMAC_SYSTAT=0x%X)\n",
+ __func__, __FILE__, __LINE__, status);
}
#endif
@@ -583,7 +816,7 @@ static void bfin_demux_gpio_block(unsigned int irq)
}
void bfin_demux_gpio_irq(unsigned int inta_irq,
- struct irq_desc *desc)
+ struct irq_desc *desc)
{
unsigned int irq;
@@ -635,9 +868,15 @@ void bfin_demux_gpio_irq(unsigned int inta_irq,
#else
+# ifndef CONFIG_BF60x
#define NR_PINT_SYS_IRQS 4
-#define NR_PINT_BITS 32
#define NR_PINTS 160
+# else
+#define NR_PINT_SYS_IRQS 6
+#define NR_PINTS 112
+#endif
+
+#define NR_PINT_BITS 32
#define IRQ_NOT_AVAIL 0xFF
#define PINT_2_BANK(x) ((x) >> 5)
@@ -652,8 +891,13 @@ static struct bfin_pint_regs * const pint[NR_PINT_SYS_IRQS] = {
(struct bfin_pint_regs *)PINT1_MASK_SET,
(struct bfin_pint_regs *)PINT2_MASK_SET,
(struct bfin_pint_regs *)PINT3_MASK_SET,
+#ifdef CONFIG_BF60x
+ (struct bfin_pint_regs *)PINT4_MASK_SET,
+ (struct bfin_pint_regs *)PINT5_MASK_SET,
+#endif
};
+#ifndef CONFIG_BF60x
inline unsigned int get_irq_base(u32 bank, u8 bmap)
{
unsigned int irq_base;
@@ -666,6 +910,16 @@ inline unsigned int get_irq_base(u32 bank, u8 bmap)
return irq_base;
}
+#else
+inline unsigned int get_irq_base(u32 bank, u8 bmap)
+{
+ unsigned int irq_base;
+
+ irq_base = IRQ_PA0 + bank * 16 + bmap * 16;
+
+ return irq_base;
+}
+#endif
/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
void init_pint_lut(void)
@@ -854,6 +1108,14 @@ static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
case 1:
pint_irq = IRQ_PINT1;
break;
+#ifdef CONFIG_BF60x
+ case 4:
+ pint_irq = IRQ_PINT4;
+ break;
+ case 5:
+ pint_irq = IRQ_PINT5;
+ break;
+#endif
default:
return -EINVAL;
}
@@ -867,10 +1129,21 @@ static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
#endif
void bfin_demux_gpio_irq(unsigned int inta_irq,
- struct irq_desc *desc)
+ struct irq_desc *desc)
{
u32 bank, pint_val;
u32 request, irq;
+ u32 level_mask;
+ int umask = 0;
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ if (chip->irq_mask_ack) {
+ chip->irq_mask_ack(&desc->irq_data);
+ } else {
+ chip->irq_mask(&desc->irq_data);
+ if (chip->irq_ack)
+ chip->irq_ack(&desc->irq_data);
+ }
switch (inta_irq) {
case IRQ_PINT0:
@@ -885,6 +1158,14 @@ void bfin_demux_gpio_irq(unsigned int inta_irq,
case IRQ_PINT1:
bank = 1;
break;
+#ifdef CONFIG_BF60x
+ case IRQ_PINT4:
+ bank = 4;
+ break;
+ case IRQ_PINT5:
+ bank = 5;
+ break;
+#endif
default:
return;
}
@@ -893,15 +1174,23 @@ void bfin_demux_gpio_irq(unsigned int inta_irq,
request = pint[bank]->request;
+ level_mask = pint[bank]->edge_set & request;
+
while (request) {
if (request & 1) {
irq = pint2irq_lut[pint_val] + SYS_IRQS;
+ if (level_mask & PINT_BIT(pint_val)) {
+ umask = 1;
+ chip->irq_unmask(&desc->irq_data);
+ }
bfin_handle_irq(irq);
}
pint_val++;
request >>= 1;
}
+ if (!umask)
+ chip->irq_unmask(&desc->irq_data);
}
#endif
@@ -951,6 +1240,7 @@ int __init init_arch_irq(void)
int irq;
unsigned long ilat = 0;
+#ifndef CONFIG_BF60x
/* Disable all the peripheral intrs - page 4-29 HW Ref manual */
#ifdef SIC_IMASK0
bfin_write_SIC_IMASK0(SIC_UNMASK_ALL);
@@ -958,13 +1248,16 @@ int __init init_arch_irq(void)
# ifdef SIC_IMASK2
bfin_write_SIC_IMASK2(SIC_UNMASK_ALL);
# endif
-# ifdef CONFIG_SMP
+# if defined(CONFIG_SMP) || defined(CONFIG_ICC)
bfin_write_SICB_IMASK0(SIC_UNMASK_ALL);
bfin_write_SICB_IMASK1(SIC_UNMASK_ALL);
# endif
#else
bfin_write_SIC_IMASK(SIC_UNMASK_ALL);
#endif
+#else /* CONFIG_BF60x */
+ bfin_write_SEC_GCTL(SEC_GCTL_RESET);
+#endif
local_irq_disable();
@@ -974,6 +1267,10 @@ int __init init_arch_irq(void)
pint[1]->assign = CONFIG_PINT1_ASSIGN;
pint[2]->assign = CONFIG_PINT2_ASSIGN;
pint[3]->assign = CONFIG_PINT3_ASSIGN;
+# ifdef CONFIG_BF60x
+ pint[4]->assign = CONFIG_PINT4_ASSIGN;
+ pint[5]->assign = CONFIG_PINT5_ASSIGN;
+# endif
# endif
/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
init_pint_lut();
@@ -986,6 +1283,7 @@ int __init init_arch_irq(void)
irq_set_chip(irq, &bfin_internal_irqchip);
switch (irq) {
+#ifndef CONFIG_BF60x
#if BFIN_GPIO_PINT
case IRQ_PINT0:
case IRQ_PINT1:
@@ -1015,12 +1313,13 @@ int __init init_arch_irq(void)
bfin_demux_mac_status_irq);
break;
#endif
-#ifdef CONFIG_SMP
+#if defined(CONFIG_SMP) || defined(CONFIG_ICC)
case IRQ_SUPPLE_0:
case IRQ_SUPPLE_1:
irq_set_handler(irq, handle_percpu_irq);
break;
#endif
+#endif
#ifdef CONFIG_TICKSOURCE_CORETMR
case IRQ_CORETMR:
@@ -1050,7 +1349,8 @@ int __init init_arch_irq(void)
init_mach_irq();
-#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#ifndef CONFIG_BF60x
+#if (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) && !defined(CONFIG_BF60x)
for (irq = IRQ_MAC_PHYINT; irq <= IRQ_MAC_STMDONE; irq++)
irq_set_chip_and_handler(irq, &bfin_mac_status_irqchip,
handle_level_irq);
@@ -1060,7 +1360,28 @@ int __init init_arch_irq(void)
irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++)
irq_set_chip_and_handler(irq, &bfin_gpio_irqchip,
handle_level_irq);
-
+#else
+ for (irq = BFIN_IRQ(0); irq <= SYS_IRQS; irq++) {
+ if (irq < CORE_IRQS) {
+ irq_set_chip(irq, &bfin_sec_irqchip);
+ __irq_set_handler(irq, handle_sec_fault, 0, NULL);
+ } else if (irq >= BFIN_IRQ(21) && irq <= BFIN_IRQ(26)) {
+ irq_set_chip(irq, &bfin_sec_irqchip);
+ irq_set_chained_handler(irq, bfin_demux_gpio_irq);
+ } else if (irq >= BFIN_IRQ(34) && irq <= BFIN_IRQ(37)) {
+ irq_set_chip(irq, &bfin_sec_irqchip);
+ irq_set_handler(irq, handle_percpu_irq);
+ } else {
+ irq_set_chip_and_handler(irq, &bfin_sec_irqchip,
+ handle_fasteoi_irq);
+ __irq_set_preflow_handler(irq, bfin_sec_preflow_handler);
+ }
+ }
+ for (irq = GPIO_IRQ_BASE;
+ irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++)
+ irq_set_chip_and_handler(irq, &bfin_gpio_irqchip,
+ handle_level_irq);
+#endif
bfin_write_IMASK(0);
CSYNC();
ilat = bfin_read_ILAT();
@@ -1072,14 +1393,17 @@ int __init init_arch_irq(void)
/* IMASK=xxx is equivalent to STI xx or bfin_irq_flags=xx,
* local_irq_enable()
*/
+#ifndef CONFIG_BF60x
program_IAR();
/* Therefore it's better to setup IARs before interrupts enabled */
search_IAR();
/* Enable interrupts IVG7-15 */
bfin_irq_flags |= IMASK_IVG15 |
- IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
- IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
+ IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
+ IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
+
+ bfin_sti(bfin_irq_flags);
/* This implicitly covers ANOMALY_05000171
* Boot-ROM code modifies SICA_IWRx wakeup registers
@@ -1103,7 +1427,23 @@ int __init init_arch_irq(void)
#else
bfin_write_SIC_IWR(IWR_DISABLE_ALL);
#endif
+#else /* CONFIG_BF60x */
+ /* Enable interrupts IVG7-15 */
+ bfin_irq_flags |= IMASK_IVG15 |
+ IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
+ IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
+
+ bfin_write_SEC_FCTL(SEC_FCTL_EN | SEC_FCTL_SYSRST_EN | SEC_FCTL_FLTIN_EN);
+ bfin_sec_enable_sci(SIC_SYSIRQ(IRQ_WATCH0));
+ bfin_sec_enable_ssi(SIC_SYSIRQ(IRQ_WATCH0));
+ bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET);
+ udelay(100);
+ bfin_write_SEC_GCTL(SEC_GCTL_EN);
+ bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
+ init_software_driven_irq();
+ register_syscore_ops(&sec_pm_syscore_ops);
+#endif
return 0;
}
@@ -1112,13 +1452,14 @@ __attribute__((l1_text))
#endif
static int vec_to_irq(int vec)
{
+#ifndef CONFIG_BF60x
struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
unsigned long sic_status[3];
-
+#endif
if (likely(vec == EVT_IVTMR_P))
return IRQ_CORETMR;
-
+#ifndef CONFIG_BF60x
#ifdef SIC_ISR
sic_status[0] = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();
#else
@@ -1147,6 +1488,10 @@ static int vec_to_irq(int vec)
#endif
return ivg->irqno;
}
+#else
+ /* for bf60x read */
+ return BFIN_IRQ(bfin_read_SEC_SCI(0, SEC_CSID));
+#endif /* end of CONFIG_BF60x */
}
#ifdef CONFIG_DO_IRQ_L1
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index 3c648a077e75..ca6655e0d653 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -19,20 +19,33 @@
#include <asm/gpio.h>
#include <asm/dma.h>
#include <asm/dpmc.h>
+#include <asm/pm.h>
+#ifdef CONFIG_BF60x
+struct bfin_cpu_pm_fns *bfin_cpu_pm;
+#endif
void bfin_pm_suspend_standby_enter(void)
{
+#ifndef CONFIG_BF60x
bfin_pm_standby_setup();
+#endif
-#ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
- sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
+#ifdef CONFIG_BF60x
+ bfin_cpu_pm->enter(PM_SUSPEND_STANDBY);
#else
+# ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
+ sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
+# else
sleep_mode(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
+# endif
#endif
+#ifndef CONFIG_BF60x
bfin_pm_standby_restore();
+#endif
+#ifndef CONFIG_BF60x
#ifdef SIC_IWR0
bfin_write_SIC_IWR0(IWR_DISABLE_ALL);
# ifdef SIC_IWR1
@@ -52,6 +65,8 @@ void bfin_pm_suspend_standby_enter(void)
#else
bfin_write_SIC_IWR(IWR_DISABLE_ALL);
#endif
+
+#endif
}
int bf53x_suspend_l1_mem(unsigned char *memptr)
@@ -83,10 +98,13 @@ int bf53x_resume_l1_mem(unsigned char *memptr)
}
#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK)
+# ifdef CONFIG_BF60x
+__attribute__((l1_text))
+# endif
static void flushinv_all_dcache(void)
{
- u32 way, bank, subbank, set;
- u32 status, addr;
+ register u32 way, bank, subbank, set;
+ register u32 status, addr;
u32 dmem_ctl = bfin_read_DMEM_CONTROL();
for (bank = 0; bank < 2; ++bank) {
@@ -133,6 +151,7 @@ int bfin_pm_suspend_mem_enter(void)
return -ENOMEM;
}
+#ifndef CONFIG_BF60x
wakeup = bfin_read_VR_CTL() & ~FREQ;
wakeup |= SCKELOW;
@@ -142,6 +161,7 @@ int bfin_pm_suspend_mem_enter(void)
#ifdef CONFIG_PM_BFIN_WAKE_GP
wakeup |= GPWE;
#endif
+#endif
ret = blackfin_dma_suspend();
@@ -159,7 +179,11 @@ int bfin_pm_suspend_mem_enter(void)
_disable_icplb();
bf53x_suspend_l1_mem(memptr);
+#ifndef CONFIG_BF60x
do_hibernate(wakeup | vr_wakeup); /* See you later! */
+#else
+ bfin_cpu_pm->enter(PM_SUSPEND_MEM);
+#endif
bf53x_resume_l1_mem(memptr);
@@ -223,9 +247,39 @@ static int bfin_pm_enter(suspend_state_t state)
return 0;
}
+#ifdef CONFIG_BFIN_PM_WAKEUP_TIME_BENCH
+void bfin_pm_end(void)
+{
+ u32 cycle, cycle2;
+ u64 usec64;
+ u32 usec;
+
+ __asm__ __volatile__ (
+ "1: %0 = CYCLES2\n"
+ "%1 = CYCLES\n"
+ "%2 = CYCLES2\n"
+ "CC = %2 == %0\n"
+ "if ! CC jump 1b\n"
+ : "=d,a" (cycle2), "=d,a" (cycle), "=d,a" (usec) : : "CC"
+ );
+
+ usec64 = ((u64)cycle2 << 32) + cycle;
+ do_div(usec64, get_cclk() / USEC_PER_SEC);
+ usec = usec64;
+ if (usec == 0)
+ usec = 1;
+
+ pr_info("PM: resume of kernel completes after %ld msec %03ld usec\n",
+ usec / USEC_PER_MSEC, usec % USEC_PER_MSEC);
+}
+#endif
+
static const struct platform_suspend_ops bfin_pm_ops = {
.enter = bfin_pm_enter,
.valid = bfin_pm_valid,
+#ifdef CONFIG_BFIN_PM_WAKEUP_TIME_BENCH
+ .end = bfin_pm_end,
+#endif
};
static int __init bfin_pm_init(void)
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c
index ac8f8a43158c..00bbe672b3b3 100644
--- a/arch/blackfin/mach-common/smp.c
+++ b/arch/blackfin/mach-common/smp.c
@@ -340,27 +340,10 @@ void smp_send_stop(void)
return;
}
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
{
int ret;
- struct blackfin_cpudata *ci = &per_cpu(cpu_data, cpu);
- struct task_struct *idle = ci->idle;
- if (idle) {
- free_task(idle);
- idle = NULL;
- }
-
- if (!idle) {
- idle = fork_idle(cpu);
- if (IS_ERR(idle)) {
- printk(KERN_ERR "CPU%u: fork() failed\n", cpu);
- return PTR_ERR(idle);
- }
- ci->idle = idle;
- } else {
- init_idle(idle, cpu);
- }
secondary_stack = task_stack_page(idle) + THREAD_SIZE;
ret = platform_boot_secondary(cpu, idle);
diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c
index 78daae084915..9cb85537bd2b 100644
--- a/arch/blackfin/mm/init.c
+++ b/arch/blackfin/mm/init.c
@@ -48,7 +48,7 @@ void __init paging_init(void)
unsigned long zones_size[MAX_NR_ZONES] = {
[0] = 0,
- [ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT,
+ [ZONE_DMA] = (end_mem - CONFIG_PHY_RAM_BASE_ADDRESS) >> PAGE_SHIFT,
[ZONE_NORMAL] = 0,
#ifdef CONFIG_HIGHMEM
[ZONE_HIGHMEM] = 0,
@@ -60,7 +60,8 @@ void __init paging_init(void)
pr_debug("free_area_init -> start_mem is %#lx virtual_end is %#lx\n",
PAGE_ALIGN(memory_start), end_mem);
- free_area_init(zones_size);
+ free_area_init_node(0, zones_size,
+ CONFIG_PHY_RAM_BASE_ADDRESS >> PAGE_SHIFT, NULL);
}
asmlinkage void __init init_pda(void)
@@ -75,9 +76,6 @@ asmlinkage void __init init_pda(void)
valid pointers to it. */
memset(&cpu_pda[cpu], 0, sizeof(cpu_pda[cpu]));
- cpu_pda[0].next = &cpu_pda[1];
- cpu_pda[1].next = &cpu_pda[0];
-
#ifdef CONFIG_EXCEPTION_L1_SCRATCH
cpu_pda[cpu].ex_stack = (unsigned long *)(L1_SCRATCH_START + \
L1_SCRATCH_LENGTH);
@@ -109,10 +107,10 @@ void __init mem_init(void)
totalram_pages = free_all_bootmem();
reservedpages = 0;
- for (tmp = 0; tmp < max_mapnr; tmp++)
+ for (tmp = ARCH_PFN_OFFSET; tmp < max_mapnr; tmp++)
if (PageReserved(pfn_to_page(tmp)))
reservedpages++;
- freepages = max_mapnr - reservedpages;
+ freepages = max_mapnr - ARCH_PFN_OFFSET - reservedpages;
/* do not count in kernel image between _rambase and _ramstart */
reservedpages -= (_ramstart - _rambase) >> PAGE_SHIFT;
@@ -127,7 +125,7 @@ void __init mem_init(void)
printk(KERN_INFO
"Memory available: %luk/%luk RAM, "
"(%uk init code, %uk kernel code, %uk data, %uk dma, %uk reserved)\n",
- (unsigned long) freepages << (PAGE_SHIFT-10), _ramend >> 10,
+ (unsigned long) freepages << (PAGE_SHIFT-10), (_ramend - CONFIG_PHY_RAM_BASE_ADDRESS) >> 10,
initk, codek, datak, DMA_UNCACHED_REGION >> 10, (reservedpages << (PAGE_SHIFT-10)));
}
diff --git a/arch/blackfin/mm/sram-alloc.c b/arch/blackfin/mm/sram-alloc.c
index 29d98faa1efd..342e378da1ec 100644
--- a/arch/blackfin/mm/sram-alloc.c
+++ b/arch/blackfin/mm/sram-alloc.c
@@ -186,9 +186,45 @@ static void __init l1_inst_sram_init(void)
#endif
}
+#ifdef __ADSPBF60x__
+static irqreturn_t l2_ecc_err(int irq, void *dev_id)
+{
+ int status;
+
+ printk(KERN_ERR "L2 ecc error happend\n");
+ status = bfin_read32(L2CTL0_STAT);
+ if (status & 0x1)
+ printk(KERN_ERR "Core channel error type:0x%x, addr:0x%x\n",
+ bfin_read32(L2CTL0_ET0), bfin_read32(L2CTL0_EADDR0));
+ if (status & 0x2)
+ printk(KERN_ERR "System channel error type:0x%x, addr:0x%x\n",
+ bfin_read32(L2CTL0_ET1), bfin_read32(L2CTL0_EADDR1));
+
+ status = status >> 8;
+ if (status)
+ printk(KERN_ERR "L2 Bank%d error, addr:0x%x\n",
+ status, bfin_read32(L2CTL0_ERRADDR0 + status));
+
+ panic("L2 Ecc error");
+ return IRQ_HANDLED;
+}
+#endif
+
static void __init l2_sram_init(void)
{
#if L2_LENGTH != 0
+
+#ifdef __ADSPBF60x__
+ int ret;
+
+ ret = request_irq(IRQ_L2CTL0_ECC_ERR, l2_ecc_err, 0, "l2-ecc-err",
+ NULL);
+ if (unlikely(ret < 0)) {
+ printk(KERN_INFO "Fail to request l2 ecc error interrupt");
+ return;
+ }
+#endif
+
free_l2_sram_head.next =
kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
if (!free_l2_sram_head.next) {
diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig
index 1c3ccd416d50..1f15b88b537f 100644
--- a/arch/c6x/Kconfig
+++ b/arch/c6x/Kconfig
@@ -3,7 +3,7 @@
# see Documentation/kbuild/kconfig-language.txt.
#
-config TMS320C6X
+config C6X
def_bool y
select CLKDEV_LOOKUP
select GENERIC_IRQ_SHOW
@@ -19,24 +19,12 @@ config TMS320C6X
config MMU
def_bool n
-config ZONE_DMA
- def_bool y
-
config FPU
def_bool n
-config HIGHMEM
- def_bool n
-
-config NUMA
- def_bool n
-
config RWSEM_GENERIC_SPINLOCK
def_bool y
-config RWSEM_XCHGADD_ALGORITHM
- def_bool n
-
config GENERIC_CALIBRATE_DELAY
def_bool y
diff --git a/arch/c6x/include/asm/elf.h b/arch/c6x/include/asm/elf.h
index d57865ba2c44..f4552db20b4a 100644
--- a/arch/c6x/include/asm/elf.h
+++ b/arch/c6x/include/asm/elf.h
@@ -30,7 +30,19 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
*/
#define elf_check_arch(x) ((x)->e_machine == EM_TI_C6000)
-#define elf_check_const_displacement(x) (1)
+#define elf_check_fdpic(x) (1)
+#define elf_check_const_displacement(x) (0)
+
+#define ELF_FDPIC_PLAT_INIT(_regs, _exec_map, _interp_map, _dynamic_addr) \
+do { \
+ _regs->b4 = (_exec_map); \
+ _regs->a6 = (_interp_map); \
+ _regs->b6 = (_dynamic_addr); \
+} while (0)
+
+#define ELF_FDPIC_CORE_EFLAGS 0
+
+#define ELF_CORE_COPY_FPREGS(...) 0 /* No FPU regs to copy */
/*
* These are used to set parameters in the core dumps.
diff --git a/arch/c6x/include/asm/mmu.h b/arch/c6x/include/asm/mmu.h
index 41592bf16067..4467e770a1ce 100644
--- a/arch/c6x/include/asm/mmu.h
+++ b/arch/c6x/include/asm/mmu.h
@@ -13,6 +13,10 @@
typedef struct {
unsigned long end_brk;
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+ unsigned long exec_fdpic_loadmap;
+ unsigned long interp_fdpic_loadmap;
+#endif
} mm_context_t;
#endif /* _ASM_C6X_MMU_H */
diff --git a/arch/c6x/include/asm/processor.h b/arch/c6x/include/asm/processor.h
index 3ff7fab956ba..c50af7ef1c96 100644
--- a/arch/c6x/include/asm/processor.h
+++ b/arch/c6x/include/asm/processor.h
@@ -92,9 +92,6 @@ static inline void release_thread(struct task_struct *dead_task)
{
}
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
#define copy_segments(tsk, mm) do { } while (0)
diff --git a/arch/c6x/include/asm/ptrace.h b/arch/c6x/include/asm/ptrace.h
index 21e8d7931fe7..b04ff5964258 100644
--- a/arch/c6x/include/asm/ptrace.h
+++ b/arch/c6x/include/asm/ptrace.h
@@ -97,6 +97,11 @@
#define PT_DP PT_B14 /* Data Segment Pointer (B14) */
#define PT_SP PT_B15 /* Stack Pointer (B15) */
+#define PTRACE_GETFDPIC 31 /* get the ELF fdpic loadmap address */
+
+#define PTRACE_GETFDPIC_EXEC 0 /* [addr] request the executable loadmap */
+#define PTRACE_GETFDPIC_INTERP 1 /* [addr] request the interpreter loadmap */
+
#ifndef __ASSEMBLY__
#ifdef _BIG_ENDIAN
diff --git a/arch/c6x/include/asm/thread_info.h b/arch/c6x/include/asm/thread_info.h
index fd99148cda9d..1710bcbb8d09 100644
--- a/arch/c6x/include/asm/thread_info.h
+++ b/arch/c6x/include/asm/thread_info.h
@@ -20,11 +20,11 @@
#ifdef CONFIG_4KSTACKS
#define THREAD_SIZE 4096
#define THREAD_SHIFT 12
-#define THREAD_ORDER 0
+#define THREAD_SIZE_ORDER 0
#else
#define THREAD_SIZE 8192
#define THREAD_SHIFT 13
-#define THREAD_ORDER 1
+#define THREAD_SIZE_ORDER 1
#endif
#define THREAD_START_SP (THREAD_SIZE - 8)
@@ -80,19 +80,6 @@ struct thread_info *current_thread_info(void)
return ti;
}
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-
-/* thread information allocation */
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define THREAD_FLAGS (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO)
-#else
-#define THREAD_FLAGS (GFP_KERNEL | __GFP_NOTRACK)
-#endif
-
-#define alloc_thread_info_node(tsk, node) \
- ((struct thread_info *)__get_free_pages(THREAD_FLAGS, THREAD_ORDER))
-
-#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER)
#define get_thread_info(ti) get_task_struct((ti)->task)
#define put_thread_info(ti) put_task_struct((ti)->task)
#endif /* __ASSEMBLY__ */
diff --git a/arch/c6x/kernel/process.c b/arch/c6x/kernel/process.c
index 7ca8c41b03cd..45e924a636a0 100644
--- a/arch/c6x/kernel/process.c
+++ b/arch/c6x/kernel/process.c
@@ -26,22 +26,6 @@ void (*c6x_halt)(void);
extern asmlinkage void ret_from_fork(void);
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-
-/*
- * Initial thread structure.
- */
-union thread_union init_thread_union __init_task_data = {
- INIT_THREAD_INFO(init_task)
-};
-
-/*
- * Initial task structure.
- */
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
-
/*
* power off function, if any
*/
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index b3abfb08aa5c..2995035812ec 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -49,6 +49,7 @@ config CRIS
select HAVE_GENERIC_HARDIRQS
select GENERIC_IRQ_SHOW
select GENERIC_IOMAP
+ select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32
config HZ
int
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
index 0b99df72d2a4..ebe2cb30bd11 100644
--- a/arch/cris/arch-v32/kernel/smp.c
+++ b/arch/cris/arch-v32/kernel/smp.c
@@ -108,17 +108,12 @@ void __init smp_cpus_done(unsigned int max_cpus)
/* Bring one cpu online.*/
static int __init
-smp_boot_one_cpu(int cpuid)
+smp_boot_one_cpu(int cpuid, struct task_struct idle)
{
unsigned timeout;
- struct task_struct *idle;
cpumask_t cpu_mask;
cpumask_clear(&cpu_mask);
- idle = fork_idle(cpuid);
- if (IS_ERR(idle))
- panic("SMP: fork failed for CPU:%d", cpuid);
-
task_thread_info(idle)->cpu = cpuid;
/* Information to the CPU that is about to boot */
@@ -142,9 +137,6 @@ smp_boot_one_cpu(int cpuid)
barrier();
}
- put_task_struct(idle);
- idle = NULL;
-
printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid);
return -1;
}
@@ -207,9 +199,9 @@ int setup_profiling_timer(unsigned int multiplier)
*/
unsigned long cache_decay_ticks = 1;
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
- smp_boot_one_cpu(cpu);
+ smp_boot_one_cpu(cpu, tidle);
return cpu_online(cpu) ? 0 : -ENOSYS;
}
diff --git a/arch/cris/include/asm/processor.h b/arch/cris/include/asm/processor.h
index 4210d72a6667..ef4e1bc3efc8 100644
--- a/arch/cris/include/asm/processor.h
+++ b/arch/cris/include/asm/processor.h
@@ -25,13 +25,12 @@ struct task_struct;
*/
#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
-/* THREAD_SIZE is the size of the task_struct/kernel_stack combo.
+/* THREAD_SIZE is the size of the thread_info/kernel_stack combo.
* normally, the stack is found by doing something like p + THREAD_SIZE
* in CRIS, a page is 8192 bytes, which seems like a sane size
*/
-
#define THREAD_SIZE PAGE_SIZE
-#define KERNEL_STACK_SIZE PAGE_SIZE
+#define THREAD_SIZE_ORDER (0)
/*
* At user->kernel entry, the pt_regs struct is stacked on the top of the kernel-stack.
@@ -50,10 +49,6 @@ struct task_struct;
#define task_pt_regs(task) user_regs(task_thread_info(task))
#define current_regs() task_pt_regs(current)
-static inline void prepare_to_copy(struct task_struct *tsk)
-{
-}
-
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
unsigned long get_wchan(struct task_struct *p);
diff --git a/arch/cris/include/asm/thread_info.h b/arch/cris/include/asm/thread_info.h
index 29b92884d793..5b1c448df5c0 100644
--- a/arch/cris/include/asm/thread_info.h
+++ b/arch/cris/include/asm/thread_info.h
@@ -65,12 +65,6 @@ struct thread_info {
#define init_thread_info (init_thread_union.thread_info)
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-/* thread information allocation */
-#define alloc_thread_info_node(tsk, node) \
- ((struct thread_info *) __get_free_pages(GFP_KERNEL, 1))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
-
#endif /* !__ASSEMBLY__ */
/*
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index 891dad85e8bd..66fd01728790 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -29,34 +29,6 @@
//#define DEBUG
/*
- * Initial task structure. Make this a per-architecture thing,
- * because different architectures tend to have different
- * alignment requirements and potentially different initial
- * setup.
- */
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is 8192-byte aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
-
-/*
* The hlt_counter, disable_hlt and enable_hlt is just here as a hook if
* there would ever be a halt sequence (for power save when idle) with
* some largish delay when halting or resuming *and* a driver that can't
diff --git a/arch/frv/Makefile b/arch/frv/Makefile
index 7ff84575b186..4d1b1e9baef1 100644
--- a/arch/frv/Makefile
+++ b/arch/frv/Makefile
@@ -81,7 +81,7 @@ ifdef CONFIG_DEBUG_INFO
KBUILD_AFLAGS += -Wa,--gdwarf2
endif
-head-y := arch/frv/kernel/head.o arch/frv/kernel/init_task.o
+head-y := arch/frv/kernel/head.o
core-y += arch/frv/kernel/ arch/frv/mm/
libs-y += arch/frv/lib/
diff --git a/arch/frv/include/asm/processor.h b/arch/frv/include/asm/processor.h
index 4a53811cd4cd..dccb9d162318 100644
--- a/arch/frv/include/asm/processor.h
+++ b/arch/frv/include/asm/processor.h
@@ -102,8 +102,6 @@ do { \
__frame->sp = (_usp); \
} while(0)
-extern void prepare_to_copy(struct task_struct *tsk);
-
/* Free all resources held by a thread. */
static inline void release_thread(struct task_struct *dead_task)
{
@@ -134,10 +132,6 @@ unsigned long get_wchan(struct task_struct *p);
#define KSTK_EIP(tsk) ((tsk)->thread.frame0->pc)
#define KSTK_ESP(tsk) ((tsk)->thread.frame0->sp)
-/* Allocation and freeing of basic task resources. */
-extern struct task_struct *alloc_task_struct_node(int node);
-extern void free_task_struct(struct task_struct *p);
-
#define cpu_relax() barrier()
/* data cache prefetch */
diff --git a/arch/frv/include/asm/thread_info.h b/arch/frv/include/asm/thread_info.h
index 92d83ea99ae5..54ab13a0de41 100644
--- a/arch/frv/include/asm/thread_info.h
+++ b/arch/frv/include/asm/thread_info.h
@@ -21,8 +21,6 @@
#define THREAD_SIZE 8192
-#define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
-
/*
* low level task data that entry.S needs immediate access to
* - this struct should fit entirely inside of one cache line
@@ -82,19 +80,6 @@ register struct thread_info *__current_thread_info asm("gr15");
#define current_thread_info() ({ __current_thread_info; })
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-
-/* thread information allocation */
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info_node(tsk, node) \
- kzalloc_node(THREAD_SIZE, GFP_KERNEL, node)
-#else
-#define alloc_thread_info_node(tsk, node) \
- kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
-#endif
-
-#define free_thread_info(info) kfree(info)
-
#endif /* __ASSEMBLY__ */
/*
diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile
index c36f70b6699a..ad4087b69968 100644
--- a/arch/frv/kernel/Makefile
+++ b/arch/frv/kernel/Makefile
@@ -5,7 +5,7 @@
heads-y := head-uc-fr401.o head-uc-fr451.o head-uc-fr555.o
heads-$(CONFIG_MMU) := head-mmu-fr451.o
-extra-y:= head.o init_task.o vmlinux.lds
+extra-y:= head.o vmlinux.lds
obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \
kernel_execve.o process.o traps.o ptrace.o signal.o dma.o \
diff --git a/arch/frv/kernel/init_task.c b/arch/frv/kernel/init_task.c
deleted file mode 100644
index 3c3e0b336a9d..000000000000
--- a/arch/frv/kernel/init_task.c
+++ /dev/null
@@ -1,32 +0,0 @@
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is THREAD_SIZE aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index d4de48bd5efe..ff95f50efea5 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -43,21 +43,6 @@ asmlinkage void ret_from_fork(void);
void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off);
-struct task_struct *alloc_task_struct_node(int node)
-{
- struct task_struct *p = kmalloc_node(THREAD_SIZE, GFP_KERNEL, node);
-
- if (p)
- atomic_set((atomic_t *)(p+1), 1);
- return p;
-}
-
-void free_task_struct(struct task_struct *p)
-{
- if (atomic_dec_and_test((atomic_t *)(p+1)))
- kfree(p);
-}
-
static void core_sleep_idle(void)
{
#ifdef LED_DEBUG_SLEEP
@@ -180,17 +165,6 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
return do_fork(clone_flags, newsp, __frame, 0, parent_tidptr, child_tidptr);
} /* end sys_clone() */
-/*****************************************************************************/
-/*
- * This gets called before we allocate a new thread and copy
- * the current task into it.
- */
-void prepare_to_copy(struct task_struct *tsk)
-{
- //unlazy_fpu(tsk);
-} /* end prepare_to_copy() */
-
-/*****************************************************************************/
/*
* set up the kernel stack and exception frames for a new process
*/
diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h
index 61fabf1788c6..4c9f6f87b617 100644
--- a/arch/h8300/include/asm/processor.h
+++ b/arch/h8300/include/asm/processor.h
@@ -109,8 +109,6 @@ static inline void release_thread(struct task_struct *dead_task)
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-#define prepare_to_copy(tsk) do { } while (0)
-
/*
* Free current thread data structures etc..
*/
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
index 8d4d2a54be9e..1cc57f872d34 100644
--- a/arch/h8300/kernel/Makefile
+++ b/arch/h8300/kernel/Makefile
@@ -6,7 +6,7 @@ extra-y := vmlinux.lds
obj-y := process.o traps.o ptrace.o irq.o \
sys_h8300.o time.o signal.o \
- setup.o gpio.o init_task.o syscalls.o \
+ setup.o gpio.o syscalls.o \
entry.o timer/
obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o
diff --git a/arch/h8300/kernel/init_task.c b/arch/h8300/kernel/init_task.c
deleted file mode 100644
index 54c1062ee80e..000000000000
--- a/arch/h8300/kernel/init_task.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * linux/arch/h8300/kernel/init_task.c
- */
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-__asm__(".align 4");
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
-
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is 8192-byte aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index 9059e3905887..bc979f770980 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -13,13 +13,11 @@ config HEXAGON
# select ARCH_REQUIRE_GPIOLIB
# select HAVE_CLK
# select IRQ_PER_CPU
- select HAVE_IRQ_WORK
# select GENERIC_PENDING_IRQ if SMP
+ select HAVE_IRQ_WORK
select GENERIC_ATOMIC64
select HAVE_PERF_EVENTS
select HAVE_GENERIC_HARDIRQS
- select GENERIC_HARDIRQS_NO__DO_IRQ
- select GENERIC_HARDIRQS_NO_DEPRECATED
# GENERIC_ALLOCATOR is used by dma_alloc_coherent()
select GENERIC_ALLOCATOR
select GENERIC_IRQ_SHOW
@@ -27,7 +25,8 @@ config HEXAGON
select HAVE_ARCH_TRACEHOOK
select NO_IOPORT
select GENERIC_IOMAP
- # mostly generic routines, with some accelerated ones
+ select GENERIC_SMP_IDLE_THREAD
+ select STACKTRACE_SUPPORT
---help---
Qualcomm Hexagon is a processor architecture designed for high
performance and low power across a wide variety of applications.
@@ -74,15 +73,6 @@ config GENERIC_CSUM
config GENERIC_IRQ_PROBE
def_bool y
-#config ZONE_DMA
-# bool
-# default y
-
-config HAS_DMA
- bool
- select HAVE_DMA_ATTRS
- default y
-
config NEED_SG_DMA_LENGTH
def_bool y
@@ -115,14 +105,11 @@ config GENERIC_BUG
def_bool y
depends on BUG
-config BUG
- def_bool y
-
menu "Machine selection"
choice
prompt "System type"
- default HEXAGON_ARCH_V2
+ default HEXAGON_COMET
config HEXAGON_COMET
bool "Comet Board"
@@ -195,8 +182,7 @@ source "kernel/Kconfig.hz"
source "kernel/time/Kconfig"
config GENERIC_GPIO
- bool "Generic GPIO support"
- default n
+ def_bool n
endmenu
diff --git a/arch/hexagon/Makefile b/arch/hexagon/Makefile
index 0c4de8790fd5..d00d900b2566 100644
--- a/arch/hexagon/Makefile
+++ b/arch/hexagon/Makefile
@@ -45,14 +45,8 @@ KBUILD_AFLAGS += -DTHREADINFO_REG=$(TIR_NAME)
LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
libs-y += $(LIBGCC)
-head-y := arch/hexagon/kernel/head.o \
- arch/hexagon/kernel/init_task.o
+head-y := arch/hexagon/kernel/head.o
core-y += arch/hexagon/kernel/ \
arch/hexagon/mm/ \
arch/hexagon/lib/
-
-# arch/hexagon/platform/common/
-#
-#core-$(CONFIG_HEXAGON_COMET) += arch/hexagon/platform/comet/
-#machine-$(CONFIG_HEXAGON_COMET) := comet
diff --git a/arch/hexagon/include/asm/processor.h b/arch/hexagon/include/asm/processor.h
index 20c5ddabbd8b..e8ea459002a4 100644
--- a/arch/hexagon/include/asm/processor.h
+++ b/arch/hexagon/include/asm/processor.h
@@ -59,13 +59,6 @@ struct thread_struct {
#define cpu_relax() __vmyield()
/*
- * "Unlazying all lazy status" occurs here.
- */
-static inline void prepare_to_copy(struct task_struct *tsk)
-{
-}
-
-/*
* Decides where the kernel will search for a free chunk of vm space during
* mmaps.
* See also arch_get_unmapped_area.
diff --git a/arch/hexagon/include/asm/spinlock_types.h b/arch/hexagon/include/asm/spinlock_types.h
index 5e937af1c4ad..99b5a7575c21 100644
--- a/arch/hexagon/include/asm/spinlock_types.h
+++ b/arch/hexagon/include/asm/spinlock_types.h
@@ -21,8 +21,6 @@
#ifndef _ASM_SPINLOCK_TYPES_H
#define _ASM_SPINLOCK_TYPES_H
-#include <linux/version.h>
-
#ifndef __LINUX_SPINLOCK_TYPES_H
# error "please don't include this file directly"
#endif
diff --git a/arch/hexagon/include/asm/thread_info.h b/arch/hexagon/include/asm/thread_info.h
index 9c2934ff5756..4f936a7ee847 100644
--- a/arch/hexagon/include/asm/thread_info.h
+++ b/arch/hexagon/include/asm/thread_info.h
@@ -31,15 +31,7 @@
#define THREAD_SHIFT 12
#define THREAD_SIZE (1<<THREAD_SHIFT)
-
-#if THREAD_SHIFT >= PAGE_SHIFT
#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
-#else /* don't use standard allocator */
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-extern struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node);
-extern void free_thread_info(struct thread_info *ti);
-#endif
-
#ifndef __ASSEMBLY__
diff --git a/arch/hexagon/kernel/Makefile b/arch/hexagon/kernel/Makefile
index 3689f3754d09..536aec093e62 100644
--- a/arch/hexagon/kernel/Makefile
+++ b/arch/hexagon/kernel/Makefile
@@ -1,4 +1,4 @@
-extra-y := head.o vmlinux.lds init_task.o
+extra-y := head.o vmlinux.lds
obj-$(CONFIG_SMP) += smp.o topology.o
diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c
index 0f2367cc5493..2b48751aa5f7 100644
--- a/arch/hexagon/kernel/dma.c
+++ b/arch/hexagon/kernel/dma.c
@@ -54,7 +54,7 @@ static struct gen_pool *coherent_pool;
/* Allocates from a pool of uncached memory that was reserved at boot time */
-void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
+static void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addr, gfp_t flag,
struct dma_attrs *attrs)
{
diff --git a/arch/hexagon/kernel/init_task.c b/arch/hexagon/kernel/init_task.c
deleted file mode 100644
index 73283d3edf09..000000000000
--- a/arch/hexagon/kernel/init_task.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Init task definition
- *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-#include <asm/thread_info.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is 8192-byte aligned due to the
- * way process stacks are handled. This is done by making sure
- * the linker maps this in the .text segment right after head.S,
- * and making head.S ensure the proper alignment.
- */
-union thread_union init_thread_union
- __attribute__((__section__(".data.init_task"),
- __aligned__(THREAD_SIZE))) = {
- INIT_THREAD_INFO(init_task)
- };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c
index ff02821bfb7e..af51de63b835 100644
--- a/arch/hexagon/kernel/process.c
+++ b/arch/hexagon/kernel/process.c
@@ -234,43 +234,6 @@ unsigned long get_wchan(struct task_struct *p)
}
/*
- * Borrowed from PowerPC -- basically allow smaller kernel stacks if we
- * go crazy with the page sizes.
- */
-#if THREAD_SHIFT < PAGE_SHIFT
-
-static struct kmem_cache *thread_info_cache;
-
-struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
-{
- struct thread_info *ti;
-
- ti = kmem_cache_alloc_node(thread_info_cache, GFP_KERNEL, node);
- if (unlikely(ti == NULL))
- return NULL;
-#ifdef CONFIG_DEBUG_STACK_USAGE
- memset(ti, 0, THREAD_SIZE);
-#endif
- return ti;
-}
-
-void free_thread_info(struct thread_info *ti)
-{
- kmem_cache_free(thread_info_cache, ti);
-}
-
-/* Weak symbol; called by init/main.c */
-
-void thread_info_cache_init(void)
-{
- thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
- THREAD_SIZE, 0, NULL);
- BUG_ON(thread_info_cache == NULL);
-}
-
-#endif /* THREAD_SHIFT < PAGE_SHIFT */
-
-/*
* Required placeholder.
*/
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c
index 1298141874a3..f7264621e58d 100644
--- a/arch/hexagon/kernel/smp.c
+++ b/arch/hexagon/kernel/smp.c
@@ -196,18 +196,11 @@ void __cpuinit start_secondary(void)
* maintains control until "cpu_online(cpu)" is set.
*/
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
{
- struct task_struct *idle;
- struct thread_info *thread;
+ struct thread_info *thread = (struct thread_info *)idle->stack;
void *stack_start;
- /* Create new init task for the CPU */
- idle = fork_idle(cpu);
- if (IS_ERR(idle))
- panic(KERN_ERR "fork_idle failed\n");
-
- thread = (struct thread_info *)idle->stack;
thread->cpu = cpu;
/* Boot to the head. */
diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c
index 5d9b33b67935..36ba64185711 100644
--- a/arch/hexagon/kernel/time.c
+++ b/arch/hexagon/kernel/time.c
@@ -201,12 +201,10 @@ void __init time_init_deferred(void)
resource = rtos_timer_device.resource;
/* ioremap here means this has to run later, after paging init */
- rtos_timer = ioremap(resource->start, resource->end
- - resource->start + 1);
+ rtos_timer = ioremap(resource->start, resource_size(resource));
if (!rtos_timer) {
- release_mem_region(resource->start, resource->end
- - resource->start + 1);
+ release_mem_region(resource->start, resource_size(resource));
}
clocksource_register_khz(&hexagon_clocksource, pcycle_freq_mhz * 1000);
diff --git a/arch/hexagon/mm/vm_fault.c b/arch/hexagon/mm/vm_fault.c
index c10b76ff9d65..06695cc4fe58 100644
--- a/arch/hexagon/mm/vm_fault.c
+++ b/arch/hexagon/mm/vm_fault.c
@@ -53,6 +53,8 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
int si_code = SEGV_MAPERR;
int fault;
const struct exception_table_entry *fixup;
+ unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
+ (cause > 0 ? FAULT_FLAG_WRITE : 0);
/*
* If we're in an interrupt or have no user context,
@@ -63,6 +65,7 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
local_irq_enable();
+retry:
down_read(&mm->mmap_sem);
vma = find_vma(mm, address);
if (!vma)
@@ -96,14 +99,23 @@ good_area:
break;
}
- fault = handle_mm_fault(mm, vma, address, (cause > 0));
+ fault = handle_mm_fault(mm, vma, address, flags);
+
+ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+ return;
/* The most common case -- we are done. */
if (likely(!(fault & VM_FAULT_ERROR))) {
- if (fault & VM_FAULT_MAJOR)
- current->maj_flt++;
- else
- current->min_flt++;
+ if (flags & FAULT_FLAG_ALLOW_RETRY) {
+ if (fault & VM_FAULT_MAJOR)
+ current->maj_flt++;
+ else
+ current->min_flt++;
+ if (fault & VM_FAULT_RETRY) {
+ flags &= ~FAULT_FLAG_ALLOW_RETRY;
+ goto retry;
+ }
+ }
up_read(&mm->mmap_sem);
return;
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index bd7266903bf8..ba667b60f32d 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -33,6 +33,10 @@ config IA64
select ARCH_WANT_OPTIONAL_GPIOLIB
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select GENERIC_IOMAP
+ select GENERIC_SMP_IDLE_THREAD
+ select ARCH_INIT_TASK
+ select ARCH_TASK_STRUCT_ALLOCATOR
+ select ARCH_THREAD_INFO_ALLOCATOR
default y
help
The Itanium Processor Family is Intel's 64-bit successor to
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 241d1c53ba69..d4eb9383f5f6 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -1,6 +1,7 @@
include include/asm-generic/Kbuild.asm
header-y += break.h
+header-y += cmpxchg.h
header-y += fpu.h
header-y += gcc_intrin.h
header-y += ia64regs.h
diff --git a/arch/ia64/include/asm/irq_remapping.h b/arch/ia64/include/asm/irq_remapping.h
new file mode 100644
index 000000000000..a8687b1d8906
--- /dev/null
+++ b/arch/ia64/include/asm/irq_remapping.h
@@ -0,0 +1,4 @@
+#ifndef __IA64_INTR_REMAPPING_H
+#define __IA64_INTR_REMAPPING_H
+#define irq_remapping_enabled 0
+#endif
diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h
index 483f6c6a4238..832dd3789e9d 100644
--- a/arch/ia64/include/asm/processor.h
+++ b/arch/ia64/include/asm/processor.h
@@ -34,8 +34,7 @@
* each (assuming 8KB page size), for a total of 8TB of user virtual
* address space.
*/
-#define TASK_SIZE_OF(tsk) ((tsk)->thread.task_size)
-#define TASK_SIZE TASK_SIZE_OF(current)
+#define TASK_SIZE DEFAULT_TASK_SIZE
/*
* This decides where the kernel will search for a free chunk of vm
@@ -280,7 +279,6 @@ struct thread_struct {
__u8 pad[3];
__u64 ksp; /* kernel stack pointer */
__u64 map_base; /* base address for get_unmapped_area() */
- __u64 task_size; /* limit for task size */
__u64 rbs_bot; /* the base address for the RBS */
int last_fph_cpu; /* CPU that may hold the contents of f32-f127 */
@@ -303,7 +301,6 @@ struct thread_struct {
.ksp = 0, \
.map_base = DEFAULT_MAP_BASE, \
.rbs_bot = STACK_TOP - DEFAULT_USER_STACK_SIZE, \
- .task_size = DEFAULT_TASK_SIZE, \
.last_fph_cpu = -1, \
INIT_THREAD_PM \
.dbr = {0, }, \
@@ -343,9 +340,6 @@ struct task_struct;
*/
#define release_thread(dead_task)
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
/*
* This is the mechanism for creating a new kernel thread.
*
@@ -723,7 +717,6 @@ extern unsigned long boot_option_idle_override;
enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_FORCE_MWAIT,
IDLE_NOMWAIT, IDLE_POLL};
-void cpu_idle_wait(void);
void default_idle(void);
#define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
diff --git a/arch/ia64/include/asm/thread_info.h b/arch/ia64/include/asm/thread_info.h
index e054bcc4273c..310d9734f02d 100644
--- a/arch/ia64/include/asm/thread_info.h
+++ b/arch/ia64/include/asm/thread_info.h
@@ -54,8 +54,6 @@ struct thread_info {
}, \
}
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-
#ifndef ASM_OFFSETS_C
/* how to get the thread information struct from C */
#define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
@@ -84,7 +82,6 @@ struct thread_info {
#endif
#define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET)
-#define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
#define alloc_task_struct_node(node) \
({ \
struct page *page = alloc_pages_node(node, GFP_KERNEL | __GFP_COMP, \
diff --git a/arch/ia64/include/asm/topology.h b/arch/ia64/include/asm/topology.h
index 09f646753d1a..a2496e449b75 100644
--- a/arch/ia64/include/asm/topology.h
+++ b/arch/ia64/include/asm/topology.h
@@ -70,31 +70,6 @@ void build_cpu_to_node_map(void);
.nr_balance_failed = 0, \
}
-/* sched_domains SD_NODE_INIT for IA64 NUMA machines */
-#define SD_NODE_INIT (struct sched_domain) { \
- .parent = NULL, \
- .child = NULL, \
- .groups = NULL, \
- .min_interval = 8, \
- .max_interval = 8*(min(num_online_cpus(), 32U)), \
- .busy_factor = 64, \
- .imbalance_pct = 125, \
- .cache_nice_tries = 2, \
- .busy_idx = 3, \
- .idle_idx = 2, \
- .newidle_idx = 0, \
- .wake_idx = 0, \
- .forkexec_idx = 0, \
- .flags = SD_LOAD_BALANCE \
- | SD_BALANCE_NEWIDLE \
- | SD_BALANCE_EXEC \
- | SD_BALANCE_FORK \
- | SD_SERIALIZE, \
- .last_balance = jiffies, \
- .balance_interval = 64, \
- .nr_balance_failed = 0, \
-}
-
#endif /* CONFIG_NUMA */
#ifdef CONFIG_SMP
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index cc26edac0ec6..e662f178b990 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -372,175 +372,6 @@ ENTRY(fsys_clock_gettime)
END(fsys_clock_gettime)
/*
- * long fsys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset, size_t sigsetsize).
- */
-#if _NSIG_WORDS != 1
-# error Sorry, fsys_rt_sigprocmask() needs to be updated for _NSIG_WORDS != 1.
-#endif
-ENTRY(fsys_rt_sigprocmask)
- .prologue
- .altrp b6
- .body
-
- add r2=IA64_TASK_BLOCKED_OFFSET,r16
- add r9=TI_FLAGS+IA64_TASK_SIZE,r16
- cmp4.ltu p6,p0=SIG_SETMASK,r32
-
- cmp.ne p15,p0=r0,r34 // oset != NULL?
- tnat.nz p8,p0=r34
- add r31=IA64_TASK_SIGHAND_OFFSET,r16
- ;;
- ld8 r3=[r2] // read/prefetch current->blocked
- ld4 r9=[r9]
- tnat.nz.or p6,p0=r35
-
- cmp.ne.or p6,p0=_NSIG_WORDS*8,r35
- tnat.nz.or p6,p0=r32
-(p6) br.spnt.few .fail_einval // fail with EINVAL
- ;;
-#ifdef CONFIG_SMP
- ld8 r31=[r31] // r31 <- current->sighand
-#endif
- and r9=TIF_ALLWORK_MASK,r9
- tnat.nz.or p8,p0=r33
- ;;
- cmp.ne p7,p0=0,r9
- cmp.eq p6,p0=r0,r33 // set == NULL?
- add r31=IA64_SIGHAND_SIGLOCK_OFFSET,r31 // r31 <- current->sighand->siglock
-(p8) br.spnt.few .fail_efault // fail with EFAULT
-(p7) br.spnt.many fsys_fallback_syscall // got pending kernel work...
-(p6) br.dpnt.many .store_mask // -> short-circuit to just reading the signal mask
-
- /* Argh, we actually have to do some work and _update_ the signal mask: */
-
-EX(.fail_efault, probe.r.fault r33, 3) // verify user has read-access to *set
-EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set
- mov r17=(1 << (SIGKILL - 1)) | (1 << (SIGSTOP - 1))
- ;;
-
- RSM_PSR_I(p0, r18, r19) // mask interrupt delivery
- andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP
- mov r8=EINVAL // default to EINVAL
-
-#ifdef CONFIG_SMP
- // __ticket_spin_trylock(r31)
- ld4 r17=[r31]
- ;;
- mov.m ar.ccv=r17
- extr.u r9=r17,17,15
- adds r19=1,r17
- extr.u r18=r17,0,15
- ;;
- cmp.eq p6,p7=r9,r18
- ;;
-(p6) cmpxchg4.acq r9=[r31],r19,ar.ccv
-(p6) dep.z r20=r19,1,15 // next serving ticket for unlock
-(p7) br.cond.spnt.many .lock_contention
- ;;
- cmp4.eq p0,p7=r9,r17
- adds r31=2,r31
-(p7) br.cond.spnt.many .lock_contention
- ld8 r3=[r2] // re-read current->blocked now that we hold the lock
- ;;
-#else
- ld8 r3=[r2] // re-read current->blocked now that we hold the lock
-#endif
- add r18=IA64_TASK_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r16
- add r19=IA64_TASK_SIGNAL_OFFSET,r16
- cmp4.eq p6,p0=SIG_BLOCK,r32
- ;;
- ld8 r19=[r19] // r19 <- current->signal
- cmp4.eq p7,p0=SIG_UNBLOCK,r32
- cmp4.eq p8,p0=SIG_SETMASK,r32
- ;;
- ld8 r18=[r18] // r18 <- current->pending.signal
- .pred.rel.mutex p6,p7,p8
-(p6) or r14=r3,r14 // SIG_BLOCK
-(p7) andcm r14=r3,r14 // SIG_UNBLOCK
-
-(p8) mov r14=r14 // SIG_SETMASK
-(p6) mov r8=0 // clear error code
- // recalc_sigpending()
- add r17=IA64_SIGNAL_GROUP_STOP_COUNT_OFFSET,r19
-
- add r19=IA64_SIGNAL_SHARED_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r19
- ;;
- ld4 r17=[r17] // r17 <- current->signal->group_stop_count
-(p7) mov r8=0 // clear error code
-
- ld8 r19=[r19] // r19 <- current->signal->shared_pending
- ;;
- cmp4.gt p6,p7=r17,r0 // p6/p7 <- (current->signal->group_stop_count > 0)?
-(p8) mov r8=0 // clear error code
-
- or r18=r18,r19 // r18 <- current->pending | current->signal->shared_pending
- ;;
- // r18 <- (current->pending | current->signal->shared_pending) & ~current->blocked:
- andcm r18=r18,r14
- add r9=TI_FLAGS+IA64_TASK_SIZE,r16
- ;;
-
-(p7) cmp.ne.or.andcm p6,p7=r18,r0 // p6/p7 <- signal pending
- mov r19=0 // i must not leak kernel bits...
-(p6) br.cond.dpnt.many .sig_pending
- ;;
-
-1: ld4 r17=[r9] // r17 <- current->thread_info->flags
- ;;
- mov ar.ccv=r17
- and r18=~_TIF_SIGPENDING,r17 // r18 <- r17 & ~(1 << TIF_SIGPENDING)
- ;;
-
- st8 [r2]=r14 // update current->blocked with new mask
- cmpxchg4.acq r8=[r9],r18,ar.ccv // current->thread_info->flags <- r18
- ;;
- cmp.ne p6,p0=r17,r8 // update failed?
-(p6) br.cond.spnt.few 1b // yes -> retry
-
-#ifdef CONFIG_SMP
- // __ticket_spin_unlock(r31)
- st2.rel [r31]=r20
- mov r20=0 // i must not leak kernel bits...
-#endif
- SSM_PSR_I(p0, p9, r31)
- ;;
-
- srlz.d // ensure psr.i is set again
- mov r18=0 // i must not leak kernel bits...
-
-.store_mask:
-EX(.fail_efault, (p15) probe.w.fault r34, 3) // verify user has write-access to *oset
-EX(.fail_efault, (p15) st8 [r34]=r3)
- mov r2=0 // i must not leak kernel bits...
- mov r3=0 // i must not leak kernel bits...
- mov r8=0 // return 0
- mov r9=0 // i must not leak kernel bits...
- mov r14=0 // i must not leak kernel bits...
- mov r17=0 // i must not leak kernel bits...
- mov r31=0 // i must not leak kernel bits...
- FSYS_RETURN
-
-.sig_pending:
-#ifdef CONFIG_SMP
- // __ticket_spin_unlock(r31)
- st2.rel [r31]=r20 // release the lock
-#endif
- SSM_PSR_I(p0, p9, r17)
- ;;
- srlz.d
- br.sptk.many fsys_fallback_syscall // with signal pending, do the heavy-weight syscall
-
-#ifdef CONFIG_SMP
-.lock_contention:
- /* Rather than spinning here, fall back on doing a heavy-weight syscall. */
- SSM_PSR_I(p0, p9, r17)
- ;;
- srlz.d
- br.sptk.many fsys_fallback_syscall
-#endif
-END(fsys_rt_sigprocmask)
-
-/*
* fsys_getcpu doesn't use the third parameter in this implementation. It reads
* current_thread_info()->cpu and corresponding node in cpu_to_node_map.
*/
@@ -559,11 +390,15 @@ ENTRY(fsys_getcpu)
;;
tnat.nz p7,p0 = r33 // I guard against NaT argument
(p7) br.cond.spnt.few .fail_einval // B
+ ;;
+ cmp.ne p6,p0=r32,r0
+ cmp.ne p7,p0=r33,r0
+ ;;
#ifdef CONFIG_NUMA
movl r17=cpu_to_node_map
;;
-EX(.fail_efault, probe.w.fault r32, 3) // M This takes 5 cycles
-EX(.fail_efault, probe.w.fault r33, 3) // M This takes 5 cycles
+EX(.fail_efault, (p6) probe.w.fault r32, 3) // M This takes 5 cycles
+EX(.fail_efault, (p7) probe.w.fault r33, 3) // M This takes 5 cycles
shladd r18=r3,1,r17
;;
ld2 r20=[r18] // r20 = cpu_to_node_map[cpu]
@@ -573,20 +408,20 @@ EX(.fail_efault, probe.w.fault r33, 3) // M This takes 5 cycles
(p8) br.spnt.many fsys_fallback_syscall
;;
;;
-EX(.fail_efault, st4 [r32] = r3)
-EX(.fail_efault, st2 [r33] = r20)
+EX(.fail_efault, (p6) st4 [r32] = r3)
+EX(.fail_efault, (p7) st2 [r33] = r20)
mov r8=0
;;
#else
-EX(.fail_efault, probe.w.fault r32, 3) // M This takes 5 cycles
-EX(.fail_efault, probe.w.fault r33, 3) // M This takes 5 cycles
+EX(.fail_efault, (p6) probe.w.fault r32, 3) // M This takes 5 cycles
+EX(.fail_efault, (p7) probe.w.fault r33, 3) // M This takes 5 cycles
and r2 = TIF_ALLWORK_MASK,r2
;;
cmp.ne p8,p0=0,r2
(p8) br.spnt.many fsys_fallback_syscall
;;
-EX(.fail_efault, st4 [r32] = r3)
-EX(.fail_efault, st2 [r33] = r0)
+EX(.fail_efault, (p6) st4 [r32] = r3)
+EX(.fail_efault, (p7) st2 [r33] = r0)
mov r8=0
;;
#endif
@@ -916,7 +751,7 @@ paravirt_fsyscall_table:
data8 0 // sigaltstack
data8 0 // rt_sigaction
data8 0 // rt_sigpending
- data8 fsys_rt_sigprocmask // rt_sigprocmask
+ data8 0 // rt_sigprocmask
data8 0 // rt_sigqueueinfo // 1180
data8 0 // rt_sigreturn
data8 0 // rt_sigsuspend
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index ce74e143aea3..5e0e86ddb12f 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -273,26 +273,6 @@ static inline void play_dead(void)
}
#endif /* CONFIG_HOTPLUG_CPU */
-static void do_nothing(void *unused)
-{
-}
-
-/*
- * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
- * pm_idle and update to new pm_idle value. Required while changing pm_idle
- * handler on SMP systems.
- *
- * Caller must have changed pm_idle to the new value before the call. Old
- * pm_idle value will not be used by any CPU after the return of this function.
- */
-void cpu_idle_wait(void)
-{
- smp_mb();
- /* kick all the CPUs so that they exit out of pm_idle */
- smp_call_function(do_nothing, NULL, 1);
-}
-EXPORT_SYMBOL_GPL(cpu_idle_wait);
-
void __attribute__((noreturn))
cpu_idle (void)
{
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 796f6a5b966a..1113b8aba07f 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -75,13 +75,6 @@
#endif
/*
- * Store all idle threads, this can be reused instead of creating
- * a new thread. Also avoids complicated thread destroy functionality
- * for idle threads.
- */
-struct task_struct *idle_thread_array[NR_CPUS];
-
-/*
* Global array allocated for NR_CPUS at boot time
*/
struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS];
@@ -94,13 +87,7 @@ struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0];
#define set_brendez_area(x) (sal_state_for_booting_cpu = &sal_boot_rendez_state[(x)]);
-#define get_idle_for_cpu(x) (idle_thread_array[(x)])
-#define set_idle_for_cpu(x,p) (idle_thread_array[(x)] = (p))
-
#else
-
-#define get_idle_for_cpu(x) (NULL)
-#define set_idle_for_cpu(x,p)
#define set_brendez_area(x)
#endif
@@ -480,54 +467,12 @@ struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
return NULL;
}
-struct create_idle {
- struct work_struct work;
- struct task_struct *idle;
- struct completion done;
- int cpu;
-};
-
-void __cpuinit
-do_fork_idle(struct work_struct *work)
-{
- struct create_idle *c_idle =
- container_of(work, struct create_idle, work);
-
- c_idle->idle = fork_idle(c_idle->cpu);
- complete(&c_idle->done);
-}
-
static int __cpuinit
-do_boot_cpu (int sapicid, int cpu)
+do_boot_cpu (int sapicid, int cpu, struct task_struct *idle)
{
int timeout;
- struct create_idle c_idle = {
- .work = __WORK_INITIALIZER(c_idle.work, do_fork_idle),
- .cpu = cpu,
- .done = COMPLETION_INITIALIZER(c_idle.done),
- };
-
- /*
- * We can't use kernel_thread since we must avoid to
- * reschedule the child.
- */
- c_idle.idle = get_idle_for_cpu(cpu);
- if (c_idle.idle) {
- init_idle(c_idle.idle, cpu);
- goto do_rest;
- }
-
- schedule_work(&c_idle.work);
- wait_for_completion(&c_idle.done);
-
- if (IS_ERR(c_idle.idle))
- panic("failed fork for CPU %d", cpu);
-
- set_idle_for_cpu(cpu, c_idle.idle);
-
-do_rest:
- task_for_booting_cpu = c_idle.idle;
+ task_for_booting_cpu = idle;
Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
set_brendez_area(cpu);
@@ -793,7 +738,7 @@ set_cpu_sibling_map(int cpu)
}
int __cpuinit
-__cpu_up (unsigned int cpu)
+__cpu_up(unsigned int cpu, struct task_struct *tidle)
{
int ret;
int sapicid;
@@ -811,7 +756,7 @@ __cpu_up (unsigned int cpu)
per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
/* Processor goes to start_secondary(), sets online flag */
- ret = do_boot_cpu(sapicid, cpu);
+ ret = do_boot_cpu(sapicid, cpu, tidle);
if (ret < 0)
return ret;
diff --git a/arch/m32r/Makefile b/arch/m32r/Makefile
index 8ff5ba0ea26c..def8dd0b6bc5 100644
--- a/arch/m32r/Makefile
+++ b/arch/m32r/Makefile
@@ -31,7 +31,7 @@ KBUILD_AFLAGS += $(aflags-y)
CHECKFLAGS += -D__m32r__ -D__BIG_ENDIAN__=1
-head-y := arch/m32r/kernel/head.o arch/m32r/kernel/init_task.o
+head-y := arch/m32r/kernel/head.o
LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
diff --git a/arch/m32r/include/asm/processor.h b/arch/m32r/include/asm/processor.h
index e1f46d757460..da17253b5735 100644
--- a/arch/m32r/include/asm/processor.h
+++ b/arch/m32r/include/asm/processor.h
@@ -118,8 +118,6 @@ struct mm_struct;
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
-#define prepare_to_copy(tsk) do { } while (0)
-
/*
* create a kernel thread without removing it from tasklists
*/
diff --git a/arch/m32r/include/asm/thread_info.h b/arch/m32r/include/asm/thread_info.h
index bf8fa3c06f4e..c083f6073ef4 100644
--- a/arch/m32r/include/asm/thread_info.h
+++ b/arch/m32r/include/asm/thread_info.h
@@ -55,8 +55,8 @@ struct thread_info {
#define PREEMPT_ACTIVE 0x10000000
-#define THREAD_SIZE (PAGE_SIZE << 1)
-
+#define THREAD_SIZE (PAGE_SIZE << 1)
+#define THREAD_SIZE_ORDER 1
/*
* macros/functions for gaining access to the thread information structure
*/
@@ -92,19 +92,6 @@ static inline struct thread_info *current_thread_info(void)
return ti;
}
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-
-/* thread information allocation */
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info_node(tsk, node) \
- kzalloc_node(THREAD_SIZE, GFP_KERNEL, node)
-#else
-#define alloc_thread_info_node(tsk, node) \
- kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
-#endif
-
-#define free_thread_info(info) kfree(info)
-
#define TI_FLAG_FAULT_CODE_SHIFT 28
static inline void set_thread_fault_code(unsigned int val)
diff --git a/arch/m32r/kernel/Makefile b/arch/m32r/kernel/Makefile
index b1a4b6036591..0c09dad8b1f8 100644
--- a/arch/m32r/kernel/Makefile
+++ b/arch/m32r/kernel/Makefile
@@ -2,7 +2,7 @@
# Makefile for the Linux/M32R kernel.
#
-extra-y := head.o init_task.o vmlinux.lds
+extra-y := head.o vmlinux.lds
obj-y := process.o entry.o traps.o align.o irq.o setup.o time.o \
m32r_ksyms.o sys_m32r.o signal.o ptrace.o
diff --git a/arch/m32r/kernel/init_task.c b/arch/m32r/kernel/init_task.c
deleted file mode 100644
index 6c42d5f8df50..000000000000
--- a/arch/m32r/kernel/init_task.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* orig : i386 init_task.c */
-
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is 8192-byte aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
-
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
index cfdbe5d15002..a2cfc0abb05c 100644
--- a/arch/m32r/kernel/smpboot.c
+++ b/arch/m32r/kernel/smpboot.c
@@ -109,12 +109,8 @@ static unsigned int calibration_result;
/* Function Prototypes */
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
-void smp_prepare_boot_cpu(void);
-void smp_prepare_cpus(unsigned int);
static void init_ipi_lock(void);
static void do_boot_cpu(int);
-int __cpu_up(unsigned int);
-void smp_cpus_done(unsigned int);
int start_secondary(void *);
static void smp_callin(void);
@@ -347,7 +343,7 @@ static void __init do_boot_cpu(int phys_id)
}
}
-int __cpuinit __cpu_up(unsigned int cpu_id)
+int __cpuinit __cpu_up(unsigned int cpu_id, struct task_struct *tidle)
{
int timeout;
diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu
index 8a9c767125a4..51b3274cbe71 100644
--- a/arch/m68k/Kconfig.cpu
+++ b/arch/m68k/Kconfig.cpu
@@ -7,7 +7,7 @@ choice
help
The Freescale (was Motorola) M68K family of processors implements
the full 68000 processor instruction set.
- The Freescale ColdFire family of processors is a modern derivitive
+ The Freescale ColdFire family of processors is a modern derivative
of the 68000 processor family. They are mainly targeted at embedded
applications, and are all System-On-Chip (SOC) devices, as opposed
to stand alone CPUs. They implement a subset of the original 68000
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index cf318f20c64d..b7f2e2d5cd2e 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -16,6 +16,13 @@
KBUILD_DEFCONFIG := multi_defconfig
+ifneq ($(SUBARCH),$(ARCH))
+ ifeq ($(CROSS_COMPILE),)
+ CROSS_COMPILE := $(call cc-cross-prefix, \
+ m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
+ endif
+endif
+
#
# Enable processor type. Ordering of these is important - we want to
# use the minimum processor type of the range we support. The logic
@@ -62,12 +69,6 @@ endif
LDFLAGS := -m m68kelf
KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
-ifneq ($(SUBARCH),$(ARCH))
- ifeq ($(CROSS_COMPILE),)
- CROSS_COMPILE := $(call cc-cross-prefix, \
- m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
- endif
-endif
ifdef CONFIG_SUN3
LDFLAGS_vmlinux = -N
@@ -115,18 +116,6 @@ core-$(CONFIG_M68000) += arch/m68k/platform/68328/
core-$(CONFIG_M68EZ328) += arch/m68k/platform/68EZ328/
core-$(CONFIG_M68VZ328) += arch/m68k/platform/68VZ328/
core-$(CONFIG_COLDFIRE) += arch/m68k/platform/coldfire/
-core-$(CONFIG_M5206) += arch/m68k/platform/5206/
-core-$(CONFIG_M5206e) += arch/m68k/platform/5206/
-core-$(CONFIG_M520x) += arch/m68k/platform/520x/
-core-$(CONFIG_M523x) += arch/m68k/platform/523x/
-core-$(CONFIG_M5249) += arch/m68k/platform/5249/
-core-$(CONFIG_M527x) += arch/m68k/platform/527x/
-core-$(CONFIG_M5272) += arch/m68k/platform/5272/
-core-$(CONFIG_M528x) += arch/m68k/platform/528x/
-core-$(CONFIG_M5307) += arch/m68k/platform/5307/
-core-$(CONFIG_M532x) += arch/m68k/platform/532x/
-core-$(CONFIG_M5407) += arch/m68k/platform/5407/
-core-$(CONFIG_M54xx) += arch/m68k/platform/54xx/
all: zImage
diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c
index 7fd8b41723ea..80076d368b7e 100644
--- a/arch/m68k/amiga/platform.c
+++ b/arch/m68k/amiga/platform.c
@@ -6,6 +6,7 @@
* for more details.
*/
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/zorro.h>
@@ -46,18 +47,25 @@ static const struct resource zorro_resources[] __initconst = {
static int __init amiga_init_bus(void)
{
+ struct platform_device *pdev;
+ unsigned int n;
+
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO))
return -ENODEV;
- platform_device_register_simple("amiga-zorro", -1, zorro_resources,
- AMIGAHW_PRESENT(ZORRO3) ? 4 : 2);
+ n = AMIGAHW_PRESENT(ZORRO3) ? 4 : 2;
+ pdev = platform_device_register_simple("amiga-zorro", -1,
+ zorro_resources, n);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
return 0;
}
subsys_initcall(amiga_init_bus);
-static int z_dev_present(zorro_id id)
+static int __init z_dev_present(zorro_id id)
{
unsigned int i;
@@ -126,72 +134,122 @@ static const struct resource amiga_rtc_resource __initconst = {
static int __init amiga_init_devices(void)
{
struct platform_device *pdev;
+ int error;
if (!MACH_IS_AMIGA)
return -ENODEV;
/* video hardware */
- if (AMIGAHW_PRESENT(AMI_VIDEO))
- platform_device_register_simple("amiga-video", -1, NULL, 0);
+ if (AMIGAHW_PRESENT(AMI_VIDEO)) {
+ pdev = platform_device_register_simple("amiga-video", -1, NULL,
+ 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+ }
/* sound hardware */
- if (AMIGAHW_PRESENT(AMI_AUDIO))
- platform_device_register_simple("amiga-audio", -1, NULL, 0);
+ if (AMIGAHW_PRESENT(AMI_AUDIO)) {
+ pdev = platform_device_register_simple("amiga-audio", -1, NULL,
+ 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+ }
/* storage interfaces */
- if (AMIGAHW_PRESENT(AMI_FLOPPY))
- platform_device_register_simple("amiga-floppy", -1, NULL, 0);
+ if (AMIGAHW_PRESENT(AMI_FLOPPY)) {
+ pdev = platform_device_register_simple("amiga-floppy", -1,
+ NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+ }
- if (AMIGAHW_PRESENT(A3000_SCSI))
- platform_device_register_simple("amiga-a3000-scsi", -1,
- &a3000_scsi_resource, 1);
+ if (AMIGAHW_PRESENT(A3000_SCSI)) {
+ pdev = platform_device_register_simple("amiga-a3000-scsi", -1,
+ &a3000_scsi_resource, 1);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+ }
- if (AMIGAHW_PRESENT(A4000_SCSI))
- platform_device_register_simple("amiga-a4000t-scsi", -1,
- &a4000t_scsi_resource, 1);
+ if (AMIGAHW_PRESENT(A4000_SCSI)) {
+ pdev = platform_device_register_simple("amiga-a4000t-scsi", -1,
+ &a4000t_scsi_resource,
+ 1);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+ }
if (AMIGAHW_PRESENT(A1200_IDE) ||
z_dev_present(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE)) {
pdev = platform_device_register_simple("amiga-gayle-ide", -1,
&a1200_ide_resource, 1);
- platform_device_add_data(pdev, &a1200_ide_pdata,
- sizeof(a1200_ide_pdata));
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+ error = platform_device_add_data(pdev, &a1200_ide_pdata,
+ sizeof(a1200_ide_pdata));
+ if (error)
+ return error;
}
if (AMIGAHW_PRESENT(A4000_IDE)) {
pdev = platform_device_register_simple("amiga-gayle-ide", -1,
&a4000_ide_resource, 1);
- platform_device_add_data(pdev, &a4000_ide_pdata,
- sizeof(a4000_ide_pdata));
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+ error = platform_device_add_data(pdev, &a4000_ide_pdata,
+ sizeof(a4000_ide_pdata));
+ if (error)
+ return error;
}
/* other I/O hardware */
- if (AMIGAHW_PRESENT(AMI_KEYBOARD))
- platform_device_register_simple("amiga-keyboard", -1, NULL, 0);
+ if (AMIGAHW_PRESENT(AMI_KEYBOARD)) {
+ pdev = platform_device_register_simple("amiga-keyboard", -1,
+ NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+ }
- if (AMIGAHW_PRESENT(AMI_MOUSE))
- platform_device_register_simple("amiga-mouse", -1, NULL, 0);
+ if (AMIGAHW_PRESENT(AMI_MOUSE)) {
+ pdev = platform_device_register_simple("amiga-mouse", -1, NULL,
+ 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+ }
- if (AMIGAHW_PRESENT(AMI_SERIAL))
- platform_device_register_simple("amiga-serial", -1, NULL, 0);
+ if (AMIGAHW_PRESENT(AMI_SERIAL)) {
+ pdev = platform_device_register_simple("amiga-serial", -1,
+ NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+ }
- if (AMIGAHW_PRESENT(AMI_PARALLEL))
- platform_device_register_simple("amiga-parallel", -1, NULL, 0);
+ if (AMIGAHW_PRESENT(AMI_PARALLEL)) {
+ pdev = platform_device_register_simple("amiga-parallel", -1,
+ NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+ }
/* real time clocks */
- if (AMIGAHW_PRESENT(A2000_CLK))
- platform_device_register_simple("rtc-msm6242", -1,
- &amiga_rtc_resource, 1);
+ if (AMIGAHW_PRESENT(A2000_CLK)) {
+ pdev = platform_device_register_simple("rtc-msm6242", -1,
+ &amiga_rtc_resource, 1);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+ }
- if (AMIGAHW_PRESENT(A3000_CLK))
- platform_device_register_simple("rtc-rp5c01", -1,
- &amiga_rtc_resource, 1);
+ if (AMIGAHW_PRESENT(A3000_CLK)) {
+ pdev = platform_device_register_simple("rtc-rp5c01", -1,
+ &amiga_rtc_resource, 1);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+ }
return 0;
}
-device_initcall(amiga_init_devices);
+arch_initcall(amiga_init_devices);
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index 783d8f02360d..3f41092d1b70 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -206,7 +206,7 @@ void __init atari_init_IRQ(void)
* hardware with a programmable int vector (probably a VME board).
*/
-unsigned long atari_register_vme_int(void)
+unsigned int atari_register_vme_int(void)
{
int i;
@@ -223,7 +223,7 @@ unsigned long atari_register_vme_int(void)
EXPORT_SYMBOL(atari_register_vme_int);
-void atari_unregister_vme_int(unsigned long irq)
+void atari_unregister_vme_int(unsigned int irq)
{
if (irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
irq -= VME_SOURCE_BASE;
diff --git a/arch/m68k/configs/m5475evb_defconfig b/arch/m68k/configs/m5475evb_defconfig
new file mode 100644
index 000000000000..c5018a68819b
--- /dev/null
+++ b/arch/m68k/configs/m5475evb_defconfig
@@ -0,0 +1,62 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_SHMEM is not set
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+CONFIG_MODULES=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_COLDFIRE=y
+CONFIG_M547x=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=266000000
+# CONFIG_4KSTACKS is not set
+CONFIG_RAMBASE=0x0
+CONFIG_RAMSIZE=0x2000000
+CONFIG_VECTORBASE=0x0
+CONFIG_MBAR=0xff000000
+CONFIG_KERNELBASE=0x20000
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_UCLINUX=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_INPUT is not set
+# CONFIG_VT is not set
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+# CONFIG_FILE_LOCKING is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_MTD=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_BOOTPARAM=y
+CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
diff --git a/arch/m68k/include/asm/atariints.h b/arch/m68k/include/asm/atariints.h
index 656bbbf5a6ff..5fc13bdf9044 100644
--- a/arch/m68k/include/asm/atariints.h
+++ b/arch/m68k/include/asm/atariints.h
@@ -198,7 +198,7 @@ static inline int atari_irq_pending( unsigned irq )
return( get_mfp_bit( irq, MFP_PENDING ) );
}
-unsigned long atari_register_vme_int( void );
-void atari_unregister_vme_int( unsigned long );
+unsigned int atari_register_vme_int(void);
+void atari_unregister_vme_int(unsigned int);
#endif /* linux/atariints.h */
diff --git a/arch/m68k/include/asm/cacheflush_no.h b/arch/m68k/include/asm/cacheflush_no.h
index cb88aa96c4f1..7cafb537d03c 100644
--- a/arch/m68k/include/asm/cacheflush_no.h
+++ b/arch/m68k/include/asm/cacheflush_no.h
@@ -30,11 +30,8 @@
void mcf_cache_push(void);
-static inline void __flush_cache_all(void)
+static inline void __clear_cache_all(void)
{
-#ifdef CACHE_PUSH
- mcf_cache_push();
-#endif
#ifdef CACHE_INVALIDATE
__asm__ __volatile__ (
"movel %0, %%d0\n\t"
@@ -44,6 +41,14 @@ static inline void __flush_cache_all(void)
#endif
}
+static inline void __flush_cache_all(void)
+{
+#ifdef CACHE_PUSH
+ mcf_cache_push();
+#endif
+ __clear_cache_all();
+}
+
/*
* Some ColdFire parts implement separate instruction and data caches,
* on those we should just flush the appropriate cache. If we don't need
@@ -76,4 +81,23 @@ static inline void __flush_dcache_all(void)
__asm__ __volatile__ ( "nop" );
#endif
}
+
+/*
+ * Push cache entries at supplied address. We want to write back any dirty
+ * data and the invalidate the cache lines associated with this address.
+ */
+static inline void cache_push(unsigned long paddr, int len)
+{
+ __flush_cache_all();
+}
+
+/*
+ * Clear cache entries at supplied address (that is don't write back any
+ * dirty data).
+ */
+static inline void cache_clear(unsigned long paddr, int len)
+{
+ __clear_cache_all();
+}
+
#endif /* _M68KNOMMU_CACHEFLUSH_H */
diff --git a/arch/m68k/include/asm/entry.h b/arch/m68k/include/asm/entry.h
index 622138dc7288..d7de0f1a8957 100644
--- a/arch/m68k/include/asm/entry.h
+++ b/arch/m68k/include/asm/entry.h
@@ -33,13 +33,11 @@
/* the following macro is used when enabling interrupts */
#if defined(MACH_ATARI_ONLY)
- /* block out HSYNC on the atari */
-#define ALLOWINT (~0x400)
-#define MAX_NOINT_IPL 3
+ /* block out HSYNC = ipl 2 on the atari */
+#define ALLOWINT (~0x500)
#else
/* portable version */
#define ALLOWINT (~0x700)
-#define MAX_NOINT_IPL 0
#endif /* machine compilation types */
#ifdef __ASSEMBLY__
diff --git a/arch/m68k/include/asm/flat.h b/arch/m68k/include/asm/flat.h
index a0e290793978..f9454b89a51b 100644
--- a/arch/m68k/include/asm/flat.h
+++ b/arch/m68k/include/asm/flat.h
@@ -11,6 +11,11 @@
#define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp)
#define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp)
#define flat_get_relocate_addr(rel) (rel)
-#define flat_set_persistent(relval, p) 0
+
+static inline int flat_set_persistent(unsigned long relval,
+ unsigned long *persistent)
+{
+ return 0;
+}
#endif /* __M68KNOMMU_FLAT_H__ */
diff --git a/arch/m68k/include/asm/io_mm.h b/arch/m68k/include/asm/io_mm.h
index 0fb3468000e7..fa4324bcf566 100644
--- a/arch/m68k/include/asm/io_mm.h
+++ b/arch/m68k/include/asm/io_mm.h
@@ -278,6 +278,13 @@ static inline void isa_delay(void)
#define readl(addr) in_le32(addr)
#define writel(val,addr) out_le32((addr),(val))
+#define readsb(port, buf, nr) raw_insb((port), (u8 *)(buf), (nr))
+#define readsw(port, buf, nr) raw_insw((port), (u16 *)(buf), (nr))
+#define readsl(port, buf, nr) raw_insl((port), (u32 *)(buf), (nr))
+#define writesb(port, buf, nr) raw_outsb((port), (u8 *)(buf), (nr))
+#define writesw(port, buf, nr) raw_outsw((port), (u16 *)(buf), (nr))
+#define writesl(port, buf, nr) raw_outsl((port), (u32 *)(buf), (nr))
+
#define mmiowb()
static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size)
diff --git a/arch/m68k/include/asm/m528xsim.h b/arch/m68k/include/asm/m528xsim.h
index 569476fba18c..d63b99ff7ff7 100644
--- a/arch/m68k/include/asm/m528xsim.h
+++ b/arch/m68k/include/asm/m528xsim.h
@@ -97,100 +97,81 @@
/*
* GPIO registers
*/
-#define MCFGPIO_PORTA (MCF_IPSBAR + 0x00100000)
-#define MCFGPIO_PORTB (MCF_IPSBAR + 0x00100001)
-#define MCFGPIO_PORTC (MCF_IPSBAR + 0x00100002)
-#define MCFGPIO_PORTD (MCF_IPSBAR + 0x00100003)
-#define MCFGPIO_PORTE (MCF_IPSBAR + 0x00100004)
-#define MCFGPIO_PORTF (MCF_IPSBAR + 0x00100005)
-#define MCFGPIO_PORTG (MCF_IPSBAR + 0x00100006)
-#define MCFGPIO_PORTH (MCF_IPSBAR + 0x00100007)
-#define MCFGPIO_PORTJ (MCF_IPSBAR + 0x00100008)
-#define MCFGPIO_PORTDD (MCF_IPSBAR + 0x00100009)
-#define MCFGPIO_PORTEH (MCF_IPSBAR + 0x0010000A)
-#define MCFGPIO_PORTEL (MCF_IPSBAR + 0x0010000B)
-#define MCFGPIO_PORTAS (MCF_IPSBAR + 0x0010000C)
-#define MCFGPIO_PORTQS (MCF_IPSBAR + 0x0010000D)
-#define MCFGPIO_PORTSD (MCF_IPSBAR + 0x0010000E)
-#define MCFGPIO_PORTTC (MCF_IPSBAR + 0x0010000F)
-#define MCFGPIO_PORTTD (MCF_IPSBAR + 0x00100010)
-#define MCFGPIO_PORTUA (MCF_IPSBAR + 0x00100011)
-
-#define MCFGPIO_DDRA (MCF_IPSBAR + 0x00100014)
-#define MCFGPIO_DDRB (MCF_IPSBAR + 0x00100015)
-#define MCFGPIO_DDRC (MCF_IPSBAR + 0x00100016)
-#define MCFGPIO_DDRD (MCF_IPSBAR + 0x00100017)
-#define MCFGPIO_DDRE (MCF_IPSBAR + 0x00100018)
-#define MCFGPIO_DDRF (MCF_IPSBAR + 0x00100019)
-#define MCFGPIO_DDRG (MCF_IPSBAR + 0x0010001A)
-#define MCFGPIO_DDRH (MCF_IPSBAR + 0x0010001B)
-#define MCFGPIO_DDRJ (MCF_IPSBAR + 0x0010001C)
-#define MCFGPIO_DDRDD (MCF_IPSBAR + 0x0010001D)
-#define MCFGPIO_DDREH (MCF_IPSBAR + 0x0010001E)
-#define MCFGPIO_DDREL (MCF_IPSBAR + 0x0010001F)
-#define MCFGPIO_DDRAS (MCF_IPSBAR + 0x00100020)
-#define MCFGPIO_DDRQS (MCF_IPSBAR + 0x00100021)
-#define MCFGPIO_DDRSD (MCF_IPSBAR + 0x00100022)
-#define MCFGPIO_DDRTC (MCF_IPSBAR + 0x00100023)
-#define MCFGPIO_DDRTD (MCF_IPSBAR + 0x00100024)
-#define MCFGPIO_DDRUA (MCF_IPSBAR + 0x00100025)
-
-#define MCFGPIO_PORTAP (MCF_IPSBAR + 0x00100028)
-#define MCFGPIO_PORTBP (MCF_IPSBAR + 0x00100029)
-#define MCFGPIO_PORTCP (MCF_IPSBAR + 0x0010002A)
-#define MCFGPIO_PORTDP (MCF_IPSBAR + 0x0010002B)
-#define MCFGPIO_PORTEP (MCF_IPSBAR + 0x0010002C)
-#define MCFGPIO_PORTFP (MCF_IPSBAR + 0x0010002D)
-#define MCFGPIO_PORTGP (MCF_IPSBAR + 0x0010002E)
-#define MCFGPIO_PORTHP (MCF_IPSBAR + 0x0010002F)
-#define MCFGPIO_PORTJP (MCF_IPSBAR + 0x00100030)
-#define MCFGPIO_PORTDDP (MCF_IPSBAR + 0x00100031)
-#define MCFGPIO_PORTEHP (MCF_IPSBAR + 0x00100032)
-#define MCFGPIO_PORTELP (MCF_IPSBAR + 0x00100033)
-#define MCFGPIO_PORTASP (MCF_IPSBAR + 0x00100034)
-#define MCFGPIO_PORTQSP (MCF_IPSBAR + 0x00100035)
-#define MCFGPIO_PORTSDP (MCF_IPSBAR + 0x00100036)
-#define MCFGPIO_PORTTCP (MCF_IPSBAR + 0x00100037)
-#define MCFGPIO_PORTTDP (MCF_IPSBAR + 0x00100038)
-#define MCFGPIO_PORTUAP (MCF_IPSBAR + 0x00100039)
-
-#define MCFGPIO_SETA (MCF_IPSBAR + 0x00100028)
-#define MCFGPIO_SETB (MCF_IPSBAR + 0x00100029)
-#define MCFGPIO_SETC (MCF_IPSBAR + 0x0010002A)
-#define MCFGPIO_SETD (MCF_IPSBAR + 0x0010002B)
-#define MCFGPIO_SETE (MCF_IPSBAR + 0x0010002C)
-#define MCFGPIO_SETF (MCF_IPSBAR + 0x0010002D)
-#define MCFGPIO_SETG (MCF_IPSBAR + 0x0010002E)
-#define MCFGPIO_SETH (MCF_IPSBAR + 0x0010002F)
-#define MCFGPIO_SETJ (MCF_IPSBAR + 0x00100030)
-#define MCFGPIO_SETDD (MCF_IPSBAR + 0x00100031)
-#define MCFGPIO_SETEH (MCF_IPSBAR + 0x00100032)
-#define MCFGPIO_SETEL (MCF_IPSBAR + 0x00100033)
-#define MCFGPIO_SETAS (MCF_IPSBAR + 0x00100034)
-#define MCFGPIO_SETQS (MCF_IPSBAR + 0x00100035)
-#define MCFGPIO_SETSD (MCF_IPSBAR + 0x00100036)
-#define MCFGPIO_SETTC (MCF_IPSBAR + 0x00100037)
-#define MCFGPIO_SETTD (MCF_IPSBAR + 0x00100038)
-#define MCFGPIO_SETUA (MCF_IPSBAR + 0x00100039)
-
-#define MCFGPIO_CLRA (MCF_IPSBAR + 0x0010003C)
-#define MCFGPIO_CLRB (MCF_IPSBAR + 0x0010003D)
-#define MCFGPIO_CLRC (MCF_IPSBAR + 0x0010003E)
-#define MCFGPIO_CLRD (MCF_IPSBAR + 0x0010003F)
-#define MCFGPIO_CLRE (MCF_IPSBAR + 0x00100040)
-#define MCFGPIO_CLRF (MCF_IPSBAR + 0x00100041)
-#define MCFGPIO_CLRG (MCF_IPSBAR + 0x00100042)
-#define MCFGPIO_CLRH (MCF_IPSBAR + 0x00100043)
-#define MCFGPIO_CLRJ (MCF_IPSBAR + 0x00100044)
-#define MCFGPIO_CLRDD (MCF_IPSBAR + 0x00100045)
-#define MCFGPIO_CLREH (MCF_IPSBAR + 0x00100046)
-#define MCFGPIO_CLREL (MCF_IPSBAR + 0x00100047)
-#define MCFGPIO_CLRAS (MCF_IPSBAR + 0x00100048)
-#define MCFGPIO_CLRQS (MCF_IPSBAR + 0x00100049)
-#define MCFGPIO_CLRSD (MCF_IPSBAR + 0x0010004A)
-#define MCFGPIO_CLRTC (MCF_IPSBAR + 0x0010004B)
-#define MCFGPIO_CLRTD (MCF_IPSBAR + 0x0010004C)
-#define MCFGPIO_CLRUA (MCF_IPSBAR + 0x0010004D)
+#define MCFGPIO_PODR_A (MCF_IPSBAR + 0x00100000)
+#define MCFGPIO_PODR_B (MCF_IPSBAR + 0x00100001)
+#define MCFGPIO_PODR_C (MCF_IPSBAR + 0x00100002)
+#define MCFGPIO_PODR_D (MCF_IPSBAR + 0x00100003)
+#define MCFGPIO_PODR_E (MCF_IPSBAR + 0x00100004)
+#define MCFGPIO_PODR_F (MCF_IPSBAR + 0x00100005)
+#define MCFGPIO_PODR_G (MCF_IPSBAR + 0x00100006)
+#define MCFGPIO_PODR_H (MCF_IPSBAR + 0x00100007)
+#define MCFGPIO_PODR_J (MCF_IPSBAR + 0x00100008)
+#define MCFGPIO_PODR_DD (MCF_IPSBAR + 0x00100009)
+#define MCFGPIO_PODR_EH (MCF_IPSBAR + 0x0010000A)
+#define MCFGPIO_PODR_EL (MCF_IPSBAR + 0x0010000B)
+#define MCFGPIO_PODR_AS (MCF_IPSBAR + 0x0010000C)
+#define MCFGPIO_PODR_QS (MCF_IPSBAR + 0x0010000D)
+#define MCFGPIO_PODR_SD (MCF_IPSBAR + 0x0010000E)
+#define MCFGPIO_PODR_TC (MCF_IPSBAR + 0x0010000F)
+#define MCFGPIO_PODR_TD (MCF_IPSBAR + 0x00100010)
+#define MCFGPIO_PODR_UA (MCF_IPSBAR + 0x00100011)
+
+#define MCFGPIO_PDDR_A (MCF_IPSBAR + 0x00100014)
+#define MCFGPIO_PDDR_B (MCF_IPSBAR + 0x00100015)
+#define MCFGPIO_PDDR_C (MCF_IPSBAR + 0x00100016)
+#define MCFGPIO_PDDR_D (MCF_IPSBAR + 0x00100017)
+#define MCFGPIO_PDDR_E (MCF_IPSBAR + 0x00100018)
+#define MCFGPIO_PDDR_F (MCF_IPSBAR + 0x00100019)
+#define MCFGPIO_PDDR_G (MCF_IPSBAR + 0x0010001A)
+#define MCFGPIO_PDDR_H (MCF_IPSBAR + 0x0010001B)
+#define MCFGPIO_PDDR_J (MCF_IPSBAR + 0x0010001C)
+#define MCFGPIO_PDDR_DD (MCF_IPSBAR + 0x0010001D)
+#define MCFGPIO_PDDR_EH (MCF_IPSBAR + 0x0010001E)
+#define MCFGPIO_PDDR_EL (MCF_IPSBAR + 0x0010001F)
+#define MCFGPIO_PDDR_AS (MCF_IPSBAR + 0x00100020)
+#define MCFGPIO_PDDR_QS (MCF_IPSBAR + 0x00100021)
+#define MCFGPIO_PDDR_SD (MCF_IPSBAR + 0x00100022)
+#define MCFGPIO_PDDR_TC (MCF_IPSBAR + 0x00100023)
+#define MCFGPIO_PDDR_TD (MCF_IPSBAR + 0x00100024)
+#define MCFGPIO_PDDR_UA (MCF_IPSBAR + 0x00100025)
+
+#define MCFGPIO_PPDSDR_A (MCF_IPSBAR + 0x00100028)
+#define MCFGPIO_PPDSDR_B (MCF_IPSBAR + 0x00100029)
+#define MCFGPIO_PPDSDR_C (MCF_IPSBAR + 0x0010002A)
+#define MCFGPIO_PPDSDR_D (MCF_IPSBAR + 0x0010002B)
+#define MCFGPIO_PPDSDR_E (MCF_IPSBAR + 0x0010002C)
+#define MCFGPIO_PPDSDR_F (MCF_IPSBAR + 0x0010002D)
+#define MCFGPIO_PPDSDR_G (MCF_IPSBAR + 0x0010002E)
+#define MCFGPIO_PPDSDR_H (MCF_IPSBAR + 0x0010002F)
+#define MCFGPIO_PPDSDR_J (MCF_IPSBAR + 0x00100030)
+#define MCFGPIO_PPDSDR_DD (MCF_IPSBAR + 0x00100031)
+#define MCFGPIO_PPDSDR_EH (MCF_IPSBAR + 0x00100032)
+#define MCFGPIO_PPDSDR_EL (MCF_IPSBAR + 0x00100033)
+#define MCFGPIO_PPDSDR_AS (MCF_IPSBAR + 0x00100034)
+#define MCFGPIO_PPDSDR_QS (MCF_IPSBAR + 0x00100035)
+#define MCFGPIO_PPDSDR_SD (MCF_IPSBAR + 0x00100036)
+#define MCFGPIO_PPDSDR_TC (MCF_IPSBAR + 0x00100037)
+#define MCFGPIO_PPDSDR_TD (MCF_IPSBAR + 0x00100038)
+#define MCFGPIO_PPDSDR_UA (MCF_IPSBAR + 0x00100039)
+
+#define MCFGPIO_PCLRR_A (MCF_IPSBAR + 0x0010003C)
+#define MCFGPIO_PCLRR_B (MCF_IPSBAR + 0x0010003D)
+#define MCFGPIO_PCLRR_C (MCF_IPSBAR + 0x0010003E)
+#define MCFGPIO_PCLRR_D (MCF_IPSBAR + 0x0010003F)
+#define MCFGPIO_PCLRR_E (MCF_IPSBAR + 0x00100040)
+#define MCFGPIO_PCLRR_F (MCF_IPSBAR + 0x00100041)
+#define MCFGPIO_PCLRR_G (MCF_IPSBAR + 0x00100042)
+#define MCFGPIO_PCLRR_H (MCF_IPSBAR + 0x00100043)
+#define MCFGPIO_PCLRR_J (MCF_IPSBAR + 0x00100044)
+#define MCFGPIO_PCLRR_DD (MCF_IPSBAR + 0x00100045)
+#define MCFGPIO_PCLRR_EH (MCF_IPSBAR + 0x00100046)
+#define MCFGPIO_PCLRR_EL (MCF_IPSBAR + 0x00100047)
+#define MCFGPIO_PCLRR_AS (MCF_IPSBAR + 0x00100048)
+#define MCFGPIO_PCLRR_QS (MCF_IPSBAR + 0x00100049)
+#define MCFGPIO_PCLRR_SD (MCF_IPSBAR + 0x0010004A)
+#define MCFGPIO_PCLRR_TC (MCF_IPSBAR + 0x0010004B)
+#define MCFGPIO_PCLRR_TD (MCF_IPSBAR + 0x0010004C)
+#define MCFGPIO_PCLRR_UA (MCF_IPSBAR + 0x0010004D)
#define MCFGPIO_PBCDPAR (MCF_IPSBAR + 0x00100050)
#define MCFGPIO_PFPAR (MCF_IPSBAR + 0x00100051)
@@ -242,11 +223,11 @@
* definitions for generic gpio support
*
*/
-#define MCFGPIO_PODR MCFGPIO_PORTA /* port output data */
-#define MCFGPIO_PDDR MCFGPIO_DDRA /* port data direction */
-#define MCFGPIO_PPDR MCFGPIO_PORTAP /* port pin data */
-#define MCFGPIO_SETR MCFGPIO_SETA /* set output */
-#define MCFGPIO_CLRR MCFGPIO_CLRA /* clr output */
+#define MCFGPIO_PODR MCFGPIO_PODR_A /* port output data */
+#define MCFGPIO_PDDR MCFGPIO_PDDR_A /* port data direction */
+#define MCFGPIO_PPDR MCFGPIO_PPDSDR_A/* port pin data */
+#define MCFGPIO_SETR MCFGPIO_PPDSDR_A/* set output */
+#define MCFGPIO_CLRR MCFGPIO_PCLRR_A /* clr output */
#define MCFGPIO_IRQ_MAX 8
#define MCFGPIO_IRQ_VECBASE MCFINT_VECBASE
diff --git a/arch/m68k/include/asm/mcfgpio.h b/arch/m68k/include/asm/mcfgpio.h
index ee5e4ccce89e..fe468eaa51e0 100644
--- a/arch/m68k/include/asm/mcfgpio.h
+++ b/arch/m68k/include/asm/mcfgpio.h
@@ -29,6 +29,9 @@ struct mcf_gpio_chip {
const u8 *gpio_to_pinmux;
};
+extern struct mcf_gpio_chip mcf_gpio_chips[];
+extern unsigned int mcf_gpio_chips_size;
+
int mcf_gpio_direction_input(struct gpio_chip *, unsigned);
int mcf_gpio_get_value(struct gpio_chip *, unsigned);
int mcf_gpio_direction_output(struct gpio_chip *, unsigned, int);
@@ -37,4 +40,58 @@ void mcf_gpio_set_value_fast(struct gpio_chip *, unsigned, int);
int mcf_gpio_request(struct gpio_chip *, unsigned);
void mcf_gpio_free(struct gpio_chip *, unsigned);
+/*
+ * Define macros to ease the pain of setting up the GPIO tables. There
+ * are two cases we need to deal with here, they cover all currently
+ * available ColdFire GPIO hardware. There are of course minor differences
+ * in the layout and number of bits in each ColdFire part, but the macros
+ * take all that in.
+ *
+ * Firstly is the conventional GPIO registers where we toggle individual
+ * bits in a register, preserving the other bits in the register. For
+ * lack of a better term I have called this the slow method.
+ */
+#define MCFGPS(mlabel, mbase, mngpio, mpddr, mpodr, mppdr) \
+ { \
+ .gpio_chip = { \
+ .label = #mlabel, \
+ .request = mcf_gpio_request, \
+ .free = mcf_gpio_free, \
+ .direction_input = mcf_gpio_direction_input, \
+ .direction_output = mcf_gpio_direction_output,\
+ .get = mcf_gpio_get_value, \
+ .set = mcf_gpio_set_value, \
+ .base = mbase, \
+ .ngpio = mngpio, \
+ }, \
+ .pddr = (void __iomem *) mpddr, \
+ .podr = (void __iomem *) mpodr, \
+ .ppdr = (void __iomem *) mppdr, \
+ }
+
+/*
+ * Secondly is the faster case, where we have set and clear registers
+ * that allow us to set or clear a bit with a single write, not having
+ * to worry about preserving other bits.
+ */
+#define MCFGPF(mlabel, mbase, mngpio) \
+ { \
+ .gpio_chip = { \
+ .label = #mlabel, \
+ .request = mcf_gpio_request, \
+ .free = mcf_gpio_free, \
+ .direction_input = mcf_gpio_direction_input, \
+ .direction_output = mcf_gpio_direction_output,\
+ .get = mcf_gpio_get_value, \
+ .set = mcf_gpio_set_value_fast, \
+ .base = mbase, \
+ .ngpio = mngpio, \
+ }, \
+ .pddr = (void __iomem *) MCFGPIO_PDDR_##mlabel, \
+ .podr = (void __iomem *) MCFGPIO_PODR_##mlabel, \
+ .ppdr = (void __iomem *) MCFGPIO_PPDSDR_##mlabel, \
+ .setr = (void __iomem *) MCFGPIO_PPDSDR_##mlabel, \
+ .clrr = (void __iomem *) MCFGPIO_PCLRR_##mlabel, \
+ }
+
#endif
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index 46460fa15d5c..f17c42aff7ff 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -153,9 +153,6 @@ static inline void release_thread(struct task_struct *dead_task)
{
}
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
/*
diff --git a/arch/m68k/include/asm/unaligned.h b/arch/m68k/include/asm/unaligned.h
index 019caa740c21..f4043ae63db1 100644
--- a/arch/m68k/include/asm/unaligned.h
+++ b/arch/m68k/include/asm/unaligned.h
@@ -2,7 +2,7 @@
#define _ASM_M68K_UNALIGNED_H
-#ifdef CONFIG_COLDFIRE
+#if defined(CONFIG_COLDFIRE) || defined(CONFIG_M68000)
#include <linux/unaligned/be_struct.h>
#include <linux/unaligned/le_byteshift.h>
#include <linux/unaligned/generic.h>
diff --git a/arch/m68k/include/asm/vga.h b/arch/m68k/include/asm/vga.h
new file mode 100644
index 000000000000..d3aa1401e7aa
--- /dev/null
+++ b/arch/m68k/include/asm/vga.h
@@ -0,0 +1,27 @@
+#ifndef _ASM_M68K_VGA_H
+#define _ASM_M68K_VGA_H
+
+#include <asm/raw_io.h>
+
+/*
+ * FIXME
+ * Ugh, we don't have PCI space, so map readb() and friends to use raw I/O
+ * accessors, which are identical to the z_*() Zorro bus accessors.
+ * This should make cirrusfb work again on Amiga
+ */
+#undef inb_p
+#undef inw_p
+#undef outb_p
+#undef outw
+#undef readb
+#undef writeb
+#undef writew
+#define inb_p(port) 0
+#define inw_p(port) 0
+#define outb_p(port, val) do { } while (0)
+#define outw(port, val) do { } while (0)
+#define readb raw_inb
+#define writeb raw_outb
+#define writew raw_outw
+
+#endif /* _ASM_M68K_VGA_H */
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 40d29a788b05..5c7070e21eb7 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -13,7 +13,7 @@ extra-$(CONFIG_SUN3X) := head.o
extra-$(CONFIG_SUN3) := sun3-head.o
extra-y += vmlinux.lds
-obj-y := entry.o init_task.o irq.o m68k_ksyms.o module.o process.o ptrace.o
+obj-y := entry.o irq.o m68k_ksyms.o module.o process.o ptrace.o
obj-y += setup.o signal.o sys_m68k.o syscalltable.o time.o traps.o
obj-$(CONFIG_MMU_MOTOROLA) += ints.o vectors.o
diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c
index 90e8cb726c8c..f6daf6e15d2e 100644
--- a/arch/m68k/kernel/dma.c
+++ b/arch/m68k/kernel/dma.c
@@ -1,5 +1,164 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#undef DEBUG
+
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/export.h>
+
+#include <asm/pgalloc.h>
+
#ifdef CONFIG_MMU
-#include "dma_mm.c"
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *handle, gfp_t flag)
+{
+ struct page *page, **map;
+ pgprot_t pgprot;
+ void *addr;
+ int i, order;
+
+ pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
+
+ size = PAGE_ALIGN(size);
+ order = get_order(size);
+
+ page = alloc_pages(flag, order);
+ if (!page)
+ return NULL;
+
+ *handle = page_to_phys(page);
+ map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
+ if (!map) {
+ __free_pages(page, order);
+ return NULL;
+ }
+ split_page(page, order);
+
+ order = 1 << order;
+ size >>= PAGE_SHIFT;
+ map[0] = page;
+ for (i = 1; i < size; i++)
+ map[i] = page + i;
+ for (; i < order; i++)
+ __free_page(page + i);
+ pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
+ if (CPU_IS_040_OR_060)
+ pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
+ else
+ pgprot_val(pgprot) |= _PAGE_NOCACHE030;
+ addr = vmap(map, size, VM_MAP, pgprot);
+ kfree(map);
+
+ return addr;
+}
+
+void dma_free_coherent(struct device *dev, size_t size,
+ void *addr, dma_addr_t handle)
+{
+ pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
+ vfree(addr);
+}
+
#else
-#include "dma_no.c"
-#endif
+
+#include <asm/cacheflush.h>
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp)
+{
+ void *ret;
+ /* ignore region specifiers */
+ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+ if (dev == NULL || (*dev->dma_mask < 0xffffffff))
+ gfp |= GFP_DMA;
+ ret = (void *)__get_free_pages(gfp, get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *dma_handle = virt_to_phys(ret);
+ }
+ return ret;
+}
+
+void dma_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ free_pages((unsigned long)vaddr, get_order(size));
+}
+
+#endif /* CONFIG_MMU */
+
+EXPORT_SYMBOL(dma_alloc_coherent);
+EXPORT_SYMBOL(dma_free_coherent);
+
+void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
+ size_t size, enum dma_data_direction dir)
+{
+ switch (dir) {
+ case DMA_TO_DEVICE:
+ cache_push(handle, size);
+ break;
+ case DMA_FROM_DEVICE:
+ cache_clear(handle, size);
+ break;
+ default:
+ if (printk_ratelimit())
+ printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
+ break;
+ }
+}
+EXPORT_SYMBOL(dma_sync_single_for_device);
+
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ int i;
+
+ for (i = 0; i < nents; sg++, i++)
+ dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
+}
+EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
+ enum dma_data_direction dir)
+{
+ dma_addr_t handle = virt_to_bus(addr);
+
+ dma_sync_single_for_device(dev, handle, size, dir);
+ return handle;
+}
+EXPORT_SYMBOL(dma_map_single);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir)
+{
+ dma_addr_t handle = page_to_phys(page) + offset;
+
+ dma_sync_single_for_device(dev, handle, size, dir);
+ return handle;
+}
+EXPORT_SYMBOL(dma_map_page);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ int i;
+
+ for (i = 0; i < nents; sg++, i++) {
+ sg->dma_address = sg_phys(sg);
+ dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
+ }
+ return nents;
+}
+EXPORT_SYMBOL(dma_map_sg);
diff --git a/arch/m68k/kernel/dma_mm.c b/arch/m68k/kernel/dma_mm.c
deleted file mode 100644
index a3c471b523f2..000000000000
--- a/arch/m68k/kernel/dma_mm.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#undef DEBUG
-
-#include <linux/dma-mapping.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/export.h>
-
-#include <asm/pgalloc.h>
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *handle, gfp_t flag)
-{
- struct page *page, **map;
- pgprot_t pgprot;
- void *addr;
- int i, order;
-
- pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
-
- size = PAGE_ALIGN(size);
- order = get_order(size);
-
- page = alloc_pages(flag, order);
- if (!page)
- return NULL;
-
- *handle = page_to_phys(page);
- map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
- if (!map) {
- __free_pages(page, order);
- return NULL;
- }
- split_page(page, order);
-
- order = 1 << order;
- size >>= PAGE_SHIFT;
- map[0] = page;
- for (i = 1; i < size; i++)
- map[i] = page + i;
- for (; i < order; i++)
- __free_page(page + i);
- pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
- if (CPU_IS_040_OR_060)
- pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
- else
- pgprot_val(pgprot) |= _PAGE_NOCACHE030;
- addr = vmap(map, size, VM_MAP, pgprot);
- kfree(map);
-
- return addr;
-}
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_coherent(struct device *dev, size_t size,
- void *addr, dma_addr_t handle)
-{
- pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
- vfree(addr);
-}
-EXPORT_SYMBOL(dma_free_coherent);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir)
-{
- switch (dir) {
- case DMA_TO_DEVICE:
- cache_push(handle, size);
- break;
- case DMA_FROM_DEVICE:
- cache_clear(handle, size);
- break;
- default:
- if (printk_ratelimit())
- printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
- break;
- }
-}
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir)
-{
- int i;
-
- for (i = 0; i < nents; sg++, i++)
- dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
-}
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
- enum dma_data_direction dir)
-{
- dma_addr_t handle = virt_to_bus(addr);
-
- dma_sync_single_for_device(dev, handle, size, dir);
- return handle;
-}
-EXPORT_SYMBOL(dma_map_single);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir)
-{
- dma_addr_t handle = page_to_phys(page) + offset;
-
- dma_sync_single_for_device(dev, handle, size, dir);
- return handle;
-}
-EXPORT_SYMBOL(dma_map_page);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir)
-{
- int i;
-
- for (i = 0; i < nents; sg++, i++) {
- sg->dma_address = sg_phys(sg);
- dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
- }
- return nents;
-}
-EXPORT_SYMBOL(dma_map_sg);
diff --git a/arch/m68k/kernel/dma_no.c b/arch/m68k/kernel/dma_no.c
deleted file mode 100644
index f1dc3fc71bc2..000000000000
--- a/arch/m68k/kernel/dma_no.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Dynamic DMA mapping support.
- *
- * We never have any address translations to worry about, so this
- * is just alloc/free.
- */
-
-#include <linux/types.h>
-#include <linux/gfp.h>
-#include <linux/mm.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/export.h>
-#include <asm/cacheflush.h>
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
-{
- void *ret;
- /* ignore region specifiers */
- gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
- if (dev == NULL || (*dev->dma_mask < 0xffffffff))
- gfp |= GFP_DMA;
- ret = (void *)__get_free_pages(gfp, get_order(size));
-
- if (ret != NULL) {
- memset(ret, 0, size);
- *dma_handle = virt_to_phys(ret);
- }
- return ret;
-}
-
-void dma_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
-{
- free_pages((unsigned long)vaddr, get_order(size));
-}
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir)
-{
- switch (dir) {
- case DMA_TO_DEVICE:
- flush_dcache_range(handle, size);
- break;
- case DMA_FROM_DEVICE:
- /* Should be clear already */
- break;
- default:
- if (printk_ratelimit())
- printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
- break;
- }
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_device);
-dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
- enum dma_data_direction dir)
-{
- dma_addr_t handle = virt_to_phys(addr);
- flush_dcache_range(handle, size);
- return handle;
-}
-EXPORT_SYMBOL(dma_map_single);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir)
-{
- dma_addr_t handle = page_to_phys(page) + offset;
- dma_sync_single_for_device(dev, handle, size, dir);
- return handle;
-}
-EXPORT_SYMBOL(dma_map_page);
diff --git a/arch/m68k/kernel/init_task.c b/arch/m68k/kernel/init_task.c
deleted file mode 100644
index c744cfc6bfa1..000000000000
--- a/arch/m68k/kernel/init_task.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * linux/arch/m68knommu/kernel/init_task.c
- */
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
-
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is THREAD size aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 2e25713e2ead..1747c7030a33 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -1,5 +1,1202 @@
+/*
+ * linux/arch/m68k/kernel/signal.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/*
+ * Linux/m68k support by Hamish Macdonald
+ *
+ * 68060 fixes by Jesper Skov
+ *
+ * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
+ *
+ * mathemu support by Roman Zippel
+ * (Note: fpstate in the signal context is completely ignored for the emulator
+ * and the internal floating point format is put on stack)
+ */
+
+/*
+ * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
+ * Atari :-) Current limitation: Only one sigstack can be active at one time.
+ * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
+ * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
+ * signal handlers!
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/highuid.h>
+#include <linux/personality.h>
+#include <linux/tty.h>
+#include <linux/binfmts.h>
+#include <linux/module.h>
+
+#include <asm/setup.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/traps.h>
+#include <asm/ucontext.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
#ifdef CONFIG_MMU
-#include "signal_mm.c"
+
+/*
+ * Handle the slight differences in classic 68k and ColdFire trap frames.
+ */
+#ifdef CONFIG_COLDFIRE
+#define FORMAT 4
+#define FMT4SIZE 0
#else
-#include "signal_no.c"
+#define FORMAT 0
+#define FMT4SIZE sizeof(((struct frame *)0)->un.fmt4)
#endif
+
+static const int frame_size_change[16] = {
+ [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
+ [2] = sizeof(((struct frame *)0)->un.fmt2),
+ [3] = sizeof(((struct frame *)0)->un.fmt3),
+ [4] = FMT4SIZE,
+ [5] = -1, /* sizeof(((struct frame *)0)->un.fmt5), */
+ [6] = -1, /* sizeof(((struct frame *)0)->un.fmt6), */
+ [7] = sizeof(((struct frame *)0)->un.fmt7),
+ [8] = -1, /* sizeof(((struct frame *)0)->un.fmt8), */
+ [9] = sizeof(((struct frame *)0)->un.fmt9),
+ [10] = sizeof(((struct frame *)0)->un.fmta),
+ [11] = sizeof(((struct frame *)0)->un.fmtb),
+ [12] = -1, /* sizeof(((struct frame *)0)->un.fmtc), */
+ [13] = -1, /* sizeof(((struct frame *)0)->un.fmtd), */
+ [14] = -1, /* sizeof(((struct frame *)0)->un.fmte), */
+ [15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */
+};
+
+static inline int frame_extra_sizes(int f)
+{
+ return frame_size_change[f];
+}
+
+int handle_kernel_fault(struct pt_regs *regs)
+{
+ const struct exception_table_entry *fixup;
+ struct pt_regs *tregs;
+
+ /* Are we prepared to handle this kernel fault? */
+ fixup = search_exception_tables(regs->pc);
+ if (!fixup)
+ return 0;
+
+ /* Create a new four word stack frame, discarding the old one. */
+ regs->stkadj = frame_extra_sizes(regs->format);
+ tregs = (struct pt_regs *)((long)regs + regs->stkadj);
+ tregs->vector = regs->vector;
+ tregs->format = FORMAT;
+ tregs->pc = fixup->fixup;
+ tregs->sr = regs->sr;
+
+ return 1;
+}
+
+void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
+{
+ if (regs->orig_d0 < 0)
+ return;
+ switch (regs->d0) {
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ regs->d0 = regs->orig_d0;
+ regs->orig_d0 = -1;
+ regs->pc -= 2;
+ break;
+ }
+}
+
+static inline void push_cache (unsigned long vaddr)
+{
+ /*
+ * Using the old cache_push_v() was really a big waste.
+ *
+ * What we are trying to do is to flush 8 bytes to ram.
+ * Flushing 2 cache lines of 16 bytes is much cheaper than
+ * flushing 1 or 2 pages, as previously done in
+ * cache_push_v().
+ * Jes
+ */
+ if (CPU_IS_040) {
+ unsigned long temp;
+
+ __asm__ __volatile__ (".chip 68040\n\t"
+ "nop\n\t"
+ "ptestr (%1)\n\t"
+ "movec %%mmusr,%0\n\t"
+ ".chip 68k"
+ : "=r" (temp)
+ : "a" (vaddr));
+
+ temp &= PAGE_MASK;
+ temp |= vaddr & ~PAGE_MASK;
+
+ __asm__ __volatile__ (".chip 68040\n\t"
+ "nop\n\t"
+ "cpushl %%bc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (temp));
+ }
+ else if (CPU_IS_060) {
+ unsigned long temp;
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "plpar (%0)\n\t"
+ ".chip 68k"
+ : "=a" (temp)
+ : "0" (vaddr));
+ __asm__ __volatile__ (".chip 68060\n\t"
+ "cpushl %%bc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (temp));
+ } else if (!CPU_IS_COLDFIRE) {
+ /*
+ * 68030/68020 have no writeback cache;
+ * still need to clear icache.
+ * Note that vaddr is guaranteed to be long word aligned.
+ */
+ unsigned long temp;
+ asm volatile ("movec %%cacr,%0" : "=r" (temp));
+ temp += 4;
+ asm volatile ("movec %0,%%caar\n\t"
+ "movec %1,%%cacr"
+ : : "r" (vaddr), "r" (temp));
+ asm volatile ("movec %0,%%caar\n\t"
+ "movec %1,%%cacr"
+ : : "r" (vaddr + 4), "r" (temp));
+ }
+}
+
+static inline void adjustformat(struct pt_regs *regs)
+{
+}
+
+static inline void save_a5_state(struct sigcontext *sc, struct pt_regs *regs)
+{
+}
+
+#else /* CONFIG_MMU */
+
+void ret_from_user_signal(void);
+void ret_from_user_rt_signal(void);
+
+static inline int frame_extra_sizes(int f)
+{
+ /* No frame size adjustments required on non-MMU CPUs */
+ return 0;
+}
+
+static inline void adjustformat(struct pt_regs *regs)
+{
+ ((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
+ /*
+ * set format byte to make stack appear modulo 4, which it will
+ * be when doing the rte
+ */
+ regs->format = 0x4;
+}
+
+static inline void save_a5_state(struct sigcontext *sc, struct pt_regs *regs)
+{
+ sc->sc_a5 = ((struct switch_stack *)regs - 1)->a5;
+}
+
+static inline void push_cache(unsigned long vaddr)
+{
+}
+
+#endif /* CONFIG_MMU */
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int
+sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
+{
+ mask &= _BLOCKABLE;
+ spin_lock_irq(&current->sighand->siglock);
+ current->saved_sigmask = current->blocked;
+ siginitset(&current->blocked, mask);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_restore_sigmask();
+
+ return -ERESTARTNOHAND;
+}
+
+asmlinkage int
+sys_sigaction(int sig, const struct old_sigaction __user *act,
+ struct old_sigaction __user *oact)
+{
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+
+ if (act) {
+ old_sigset_t mask;
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
+ __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+ __get_user(mask, &act->sa_mask))
+ return -EFAULT;
+ siginitset(&new_ka.sa.sa_mask, mask);
+ }
+
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+ if (!ret && oact) {
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
+ return -EFAULT;
+ }
+
+ return ret;
+}
+
+asmlinkage int
+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+{
+ return do_sigaltstack(uss, uoss, rdusp());
+}
+
+
+/*
+ * Do a signal return; undo the signal stack.
+ *
+ * Keep the return code on the stack quadword aligned!
+ * That makes the cache flush below easier.
+ */
+
+struct sigframe
+{
+ char __user *pretcode;
+ int sig;
+ int code;
+ struct sigcontext __user *psc;
+ char retcode[8];
+ unsigned long extramask[_NSIG_WORDS-1];
+ struct sigcontext sc;
+};
+
+struct rt_sigframe
+{
+ char __user *pretcode;
+ int sig;
+ struct siginfo __user *pinfo;
+ void __user *puc;
+ char retcode[8];
+ struct siginfo info;
+ struct ucontext uc;
+};
+
+#define FPCONTEXT_SIZE 216
+#define uc_fpstate uc_filler[0]
+#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
+#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
+
+#ifdef CONFIG_FPU
+
+static unsigned char fpu_version; /* version number of fpu, set by setup_frame */
+
+static inline int restore_fpu_state(struct sigcontext *sc)
+{
+ int err = 1;
+
+ if (FPU_IS_EMU) {
+ /* restore registers */
+ memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
+ memcpy(current->thread.fp, sc->sc_fpregs, 24);
+ return 0;
+ }
+
+ if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
+ /* Verify the frame format. */
+ if (!(CPU_IS_060 || CPU_IS_COLDFIRE) &&
+ (sc->sc_fpstate[0] != fpu_version))
+ goto out;
+ if (CPU_IS_020_OR_030) {
+ if (m68k_fputype & FPU_68881 &&
+ !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4))
+ goto out;
+ if (m68k_fputype & FPU_68882 &&
+ !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4))
+ goto out;
+ } else if (CPU_IS_040) {
+ if (!(sc->sc_fpstate[1] == 0x00 ||
+ sc->sc_fpstate[1] == 0x28 ||
+ sc->sc_fpstate[1] == 0x60))
+ goto out;
+ } else if (CPU_IS_060) {
+ if (!(sc->sc_fpstate[3] == 0x00 ||
+ sc->sc_fpstate[3] == 0x60 ||
+ sc->sc_fpstate[3] == 0xe0))
+ goto out;
+ } else if (CPU_IS_COLDFIRE) {
+ if (!(sc->sc_fpstate[0] == 0x00 ||
+ sc->sc_fpstate[0] == 0x05 ||
+ sc->sc_fpstate[0] == 0xe5))
+ goto out;
+ } else
+ goto out;
+
+ if (CPU_IS_COLDFIRE) {
+ __asm__ volatile ("fmovemd %0,%%fp0-%%fp1\n\t"
+ "fmovel %1,%%fpcr\n\t"
+ "fmovel %2,%%fpsr\n\t"
+ "fmovel %3,%%fpiar"
+ : /* no outputs */
+ : "m" (sc->sc_fpregs[0]),
+ "m" (sc->sc_fpcntl[0]),
+ "m" (sc->sc_fpcntl[1]),
+ "m" (sc->sc_fpcntl[2]));
+ } else {
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "fmovemx %0,%%fp0-%%fp1\n\t"
+ "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
+ ".chip 68k"
+ : /* no outputs */
+ : "m" (*sc->sc_fpregs),
+ "m" (*sc->sc_fpcntl));
+ }
+ }
+
+ if (CPU_IS_COLDFIRE) {
+ __asm__ volatile ("frestore %0" : : "m" (*sc->sc_fpstate));
+ } else {
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "frestore %0\n\t"
+ ".chip 68k"
+ : : "m" (*sc->sc_fpstate));
+ }
+ err = 0;
+
+out:
+ return err;
+}
+
+static inline int rt_restore_fpu_state(struct ucontext __user *uc)
+{
+ unsigned char fpstate[FPCONTEXT_SIZE];
+ int context_size = CPU_IS_060 ? 8 : (CPU_IS_COLDFIRE ? 12 : 0);
+ fpregset_t fpregs;
+ int err = 1;
+
+ if (FPU_IS_EMU) {
+ /* restore fpu control register */
+ if (__copy_from_user(current->thread.fpcntl,
+ uc->uc_mcontext.fpregs.f_fpcntl, 12))
+ goto out;
+ /* restore all other fpu register */
+ if (__copy_from_user(current->thread.fp,
+ uc->uc_mcontext.fpregs.f_fpregs, 96))
+ goto out;
+ return 0;
+ }
+
+ if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
+ goto out;
+ if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
+ if (!(CPU_IS_060 || CPU_IS_COLDFIRE))
+ context_size = fpstate[1];
+ /* Verify the frame format. */
+ if (!(CPU_IS_060 || CPU_IS_COLDFIRE) &&
+ (fpstate[0] != fpu_version))
+ goto out;
+ if (CPU_IS_020_OR_030) {
+ if (m68k_fputype & FPU_68881 &&
+ !(context_size == 0x18 || context_size == 0xb4))
+ goto out;
+ if (m68k_fputype & FPU_68882 &&
+ !(context_size == 0x38 || context_size == 0xd4))
+ goto out;
+ } else if (CPU_IS_040) {
+ if (!(context_size == 0x00 ||
+ context_size == 0x28 ||
+ context_size == 0x60))
+ goto out;
+ } else if (CPU_IS_060) {
+ if (!(fpstate[3] == 0x00 ||
+ fpstate[3] == 0x60 ||
+ fpstate[3] == 0xe0))
+ goto out;
+ } else if (CPU_IS_COLDFIRE) {
+ if (!(fpstate[3] == 0x00 ||
+ fpstate[3] == 0x05 ||
+ fpstate[3] == 0xe5))
+ goto out;
+ } else
+ goto out;
+ if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
+ sizeof(fpregs)))
+ goto out;
+
+ if (CPU_IS_COLDFIRE) {
+ __asm__ volatile ("fmovemd %0,%%fp0-%%fp7\n\t"
+ "fmovel %1,%%fpcr\n\t"
+ "fmovel %2,%%fpsr\n\t"
+ "fmovel %3,%%fpiar"
+ : /* no outputs */
+ : "m" (fpregs.f_fpregs[0]),
+ "m" (fpregs.f_fpcntl[0]),
+ "m" (fpregs.f_fpcntl[1]),
+ "m" (fpregs.f_fpcntl[2]));
+ } else {
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "fmovemx %0,%%fp0-%%fp7\n\t"
+ "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
+ ".chip 68k"
+ : /* no outputs */
+ : "m" (*fpregs.f_fpregs),
+ "m" (*fpregs.f_fpcntl));
+ }
+ }
+ if (context_size &&
+ __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
+ context_size))
+ goto out;
+
+ if (CPU_IS_COLDFIRE) {
+ __asm__ volatile ("frestore %0" : : "m" (*fpstate));
+ } else {
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "frestore %0\n\t"
+ ".chip 68k"
+ : : "m" (*fpstate));
+ }
+ err = 0;
+
+out:
+ return err;
+}
+
+/*
+ * Set up a signal frame.
+ */
+static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
+{
+ if (FPU_IS_EMU) {
+ /* save registers */
+ memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
+ memcpy(sc->sc_fpregs, current->thread.fp, 24);
+ return;
+ }
+
+ if (CPU_IS_COLDFIRE) {
+ __asm__ volatile ("fsave %0"
+ : : "m" (*sc->sc_fpstate) : "memory");
+ } else {
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "fsave %0\n\t"
+ ".chip 68k"
+ : : "m" (*sc->sc_fpstate) : "memory");
+ }
+
+ if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
+ fpu_version = sc->sc_fpstate[0];
+ if (CPU_IS_020_OR_030 &&
+ regs->vector >= (VEC_FPBRUC * 4) &&
+ regs->vector <= (VEC_FPNAN * 4)) {
+ /* Clear pending exception in 68882 idle frame */
+ if (*(unsigned short *) sc->sc_fpstate == 0x1f38)
+ sc->sc_fpstate[0x38] |= 1 << 3;
+ }
+
+ if (CPU_IS_COLDFIRE) {
+ __asm__ volatile ("fmovemd %%fp0-%%fp1,%0\n\t"
+ "fmovel %%fpcr,%1\n\t"
+ "fmovel %%fpsr,%2\n\t"
+ "fmovel %%fpiar,%3"
+ : "=m" (sc->sc_fpregs[0]),
+ "=m" (sc->sc_fpcntl[0]),
+ "=m" (sc->sc_fpcntl[1]),
+ "=m" (sc->sc_fpcntl[2])
+ : /* no inputs */
+ : "memory");
+ } else {
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "fmovemx %%fp0-%%fp1,%0\n\t"
+ "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
+ ".chip 68k"
+ : "=m" (*sc->sc_fpregs),
+ "=m" (*sc->sc_fpcntl)
+ : /* no inputs */
+ : "memory");
+ }
+ }
+}
+
+static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
+{
+ unsigned char fpstate[FPCONTEXT_SIZE];
+ int context_size = CPU_IS_060 ? 8 : (CPU_IS_COLDFIRE ? 12 : 0);
+ int err = 0;
+
+ if (FPU_IS_EMU) {
+ /* save fpu control register */
+ err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl,
+ current->thread.fpcntl, 12);
+ /* save all other fpu register */
+ err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
+ current->thread.fp, 96);
+ return err;
+ }
+
+ if (CPU_IS_COLDFIRE) {
+ __asm__ volatile ("fsave %0" : : "m" (*fpstate) : "memory");
+ } else {
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "fsave %0\n\t"
+ ".chip 68k"
+ : : "m" (*fpstate) : "memory");
+ }
+
+ err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
+ if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
+ fpregset_t fpregs;
+ if (!(CPU_IS_060 || CPU_IS_COLDFIRE))
+ context_size = fpstate[1];
+ fpu_version = fpstate[0];
+ if (CPU_IS_020_OR_030 &&
+ regs->vector >= (VEC_FPBRUC * 4) &&
+ regs->vector <= (VEC_FPNAN * 4)) {
+ /* Clear pending exception in 68882 idle frame */
+ if (*(unsigned short *) fpstate == 0x1f38)
+ fpstate[0x38] |= 1 << 3;
+ }
+ if (CPU_IS_COLDFIRE) {
+ __asm__ volatile ("fmovemd %%fp0-%%fp7,%0\n\t"
+ "fmovel %%fpcr,%1\n\t"
+ "fmovel %%fpsr,%2\n\t"
+ "fmovel %%fpiar,%3"
+ : "=m" (fpregs.f_fpregs[0]),
+ "=m" (fpregs.f_fpcntl[0]),
+ "=m" (fpregs.f_fpcntl[1]),
+ "=m" (fpregs.f_fpcntl[2])
+ : /* no inputs */
+ : "memory");
+ } else {
+ __asm__ volatile (".chip 68k/68881\n\t"
+ "fmovemx %%fp0-%%fp7,%0\n\t"
+ "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
+ ".chip 68k"
+ : "=m" (*fpregs.f_fpregs),
+ "=m" (*fpregs.f_fpcntl)
+ : /* no inputs */
+ : "memory");
+ }
+ err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
+ sizeof(fpregs));
+ }
+ if (context_size)
+ err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
+ context_size);
+ return err;
+}
+
+#else /* CONFIG_FPU */
+
+/*
+ * For the case with no FPU configured these all do nothing.
+ */
+static inline int restore_fpu_state(struct sigcontext *sc)
+{
+ return 0;
+}
+
+static inline int rt_restore_fpu_state(struct ucontext __user *uc)
+{
+ return 0;
+}
+
+static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
+{
+}
+
+static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
+{
+ return 0;
+}
+
+#endif /* CONFIG_FPU */
+
+static int mangle_kernel_stack(struct pt_regs *regs, int formatvec,
+ void __user *fp)
+{
+ int fsize = frame_extra_sizes(formatvec >> 12);
+ if (fsize < 0) {
+ /*
+ * user process trying to return with weird frame format
+ */
+#ifdef DEBUG
+ printk("user process returning with weird frame format\n");
+#endif
+ return 1;
+ }
+ if (!fsize) {
+ regs->format = formatvec >> 12;
+ regs->vector = formatvec & 0xfff;
+ } else {
+ struct switch_stack *sw = (struct switch_stack *)regs - 1;
+ unsigned long buf[fsize / 2]; /* yes, twice as much */
+
+ /* that'll make sure that expansion won't crap over data */
+ if (copy_from_user(buf + fsize / 4, fp, fsize))
+ return 1;
+
+ /* point of no return */
+ regs->format = formatvec >> 12;
+ regs->vector = formatvec & 0xfff;
+#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
+ __asm__ __volatile__ (
+#ifdef CONFIG_COLDFIRE
+ " movel %0,%/sp\n\t"
+ " bra ret_from_signal\n"
+#else
+ " movel %0,%/a0\n\t"
+ " subl %1,%/a0\n\t" /* make room on stack */
+ " movel %/a0,%/sp\n\t" /* set stack pointer */
+ /* move switch_stack and pt_regs */
+ "1: movel %0@+,%/a0@+\n\t"
+ " dbra %2,1b\n\t"
+ " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
+ " lsrl #2,%1\n\t"
+ " subql #1,%1\n\t"
+ /* copy to the gap we'd made */
+ "2: movel %4@+,%/a0@+\n\t"
+ " dbra %1,2b\n\t"
+ " bral ret_from_signal\n"
+#endif
+ : /* no outputs, it doesn't ever return */
+ : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
+ "n" (frame_offset), "a" (buf + fsize/4)
+ : "a0");
+#undef frame_offset
+ }
+ return 0;
+}
+
+static inline int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp)
+{
+ int formatvec;
+ struct sigcontext context;
+ int err = 0;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+ /* get previous context */
+ if (copy_from_user(&context, usc, sizeof(context)))
+ goto badframe;
+
+ /* restore passed registers */
+ regs->d0 = context.sc_d0;
+ regs->d1 = context.sc_d1;
+ regs->a0 = context.sc_a0;
+ regs->a1 = context.sc_a1;
+ regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
+ regs->pc = context.sc_pc;
+ regs->orig_d0 = -1; /* disable syscall checks */
+ wrusp(context.sc_usp);
+ formatvec = context.sc_formatvec;
+
+ err = restore_fpu_state(&context);
+
+ if (err || mangle_kernel_stack(regs, formatvec, fp))
+ goto badframe;
+
+ return 0;
+
+badframe:
+ return 1;
+}
+
+static inline int
+rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
+ struct ucontext __user *uc)
+{
+ int temp;
+ greg_t __user *gregs = uc->uc_mcontext.gregs;
+ unsigned long usp;
+ int err;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+ err = __get_user(temp, &uc->uc_mcontext.version);
+ if (temp != MCONTEXT_VERSION)
+ goto badframe;
+ /* restore passed registers */
+ err |= __get_user(regs->d0, &gregs[0]);
+ err |= __get_user(regs->d1, &gregs[1]);
+ err |= __get_user(regs->d2, &gregs[2]);
+ err |= __get_user(regs->d3, &gregs[3]);
+ err |= __get_user(regs->d4, &gregs[4]);
+ err |= __get_user(regs->d5, &gregs[5]);
+ err |= __get_user(sw->d6, &gregs[6]);
+ err |= __get_user(sw->d7, &gregs[7]);
+ err |= __get_user(regs->a0, &gregs[8]);
+ err |= __get_user(regs->a1, &gregs[9]);
+ err |= __get_user(regs->a2, &gregs[10]);
+ err |= __get_user(sw->a3, &gregs[11]);
+ err |= __get_user(sw->a4, &gregs[12]);
+ err |= __get_user(sw->a5, &gregs[13]);
+ err |= __get_user(sw->a6, &gregs[14]);
+ err |= __get_user(usp, &gregs[15]);
+ wrusp(usp);
+ err |= __get_user(regs->pc, &gregs[16]);
+ err |= __get_user(temp, &gregs[17]);
+ regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
+ regs->orig_d0 = -1; /* disable syscall checks */
+ err |= __get_user(temp, &uc->uc_formatvec);
+
+ err |= rt_restore_fpu_state(uc);
+
+ if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
+ goto badframe;
+
+ if (mangle_kernel_stack(regs, temp, &uc->uc_extra))
+ goto badframe;
+
+ return 0;
+
+badframe:
+ return 1;
+}
+
+asmlinkage int do_sigreturn(unsigned long __unused)
+{
+ struct switch_stack *sw = (struct switch_stack *) &__unused;
+ struct pt_regs *regs = (struct pt_regs *) (sw + 1);
+ unsigned long usp = rdusp();
+ struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
+ sigset_t set;
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
+ (_NSIG_WORDS > 1 &&
+ __copy_from_user(&set.sig[1], &frame->extramask,
+ sizeof(frame->extramask))))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ current->blocked = set;
+ recalc_sigpending();
+
+ if (restore_sigcontext(regs, &frame->sc, frame + 1))
+ goto badframe;
+ return regs->d0;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+asmlinkage int do_rt_sigreturn(unsigned long __unused)
+{
+ struct switch_stack *sw = (struct switch_stack *) &__unused;
+ struct pt_regs *regs = (struct pt_regs *) (sw + 1);
+ unsigned long usp = rdusp();
+ struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
+ sigset_t set;
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ current->blocked = set;
+ recalc_sigpending();
+
+ if (rt_restore_ucontext(regs, sw, &frame->uc))
+ goto badframe;
+ return regs->d0;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
+ unsigned long mask)
+{
+ sc->sc_mask = mask;
+ sc->sc_usp = rdusp();
+ sc->sc_d0 = regs->d0;
+ sc->sc_d1 = regs->d1;
+ sc->sc_a0 = regs->a0;
+ sc->sc_a1 = regs->a1;
+ sc->sc_sr = regs->sr;
+ sc->sc_pc = regs->pc;
+ sc->sc_formatvec = regs->format << 12 | regs->vector;
+ save_a5_state(sc, regs);
+ save_fpu_state(sc, regs);
+}
+
+static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
+{
+ struct switch_stack *sw = (struct switch_stack *)regs - 1;
+ greg_t __user *gregs = uc->uc_mcontext.gregs;
+ int err = 0;
+
+ err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
+ err |= __put_user(regs->d0, &gregs[0]);
+ err |= __put_user(regs->d1, &gregs[1]);
+ err |= __put_user(regs->d2, &gregs[2]);
+ err |= __put_user(regs->d3, &gregs[3]);
+ err |= __put_user(regs->d4, &gregs[4]);
+ err |= __put_user(regs->d5, &gregs[5]);
+ err |= __put_user(sw->d6, &gregs[6]);
+ err |= __put_user(sw->d7, &gregs[7]);
+ err |= __put_user(regs->a0, &gregs[8]);
+ err |= __put_user(regs->a1, &gregs[9]);
+ err |= __put_user(regs->a2, &gregs[10]);
+ err |= __put_user(sw->a3, &gregs[11]);
+ err |= __put_user(sw->a4, &gregs[12]);
+ err |= __put_user(sw->a5, &gregs[13]);
+ err |= __put_user(sw->a6, &gregs[14]);
+ err |= __put_user(rdusp(), &gregs[15]);
+ err |= __put_user(regs->pc, &gregs[16]);
+ err |= __put_user(regs->sr, &gregs[17]);
+ err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
+ err |= rt_save_fpu_state(uc, regs);
+ return err;
+}
+
+static inline void __user *
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+{
+ unsigned long usp;
+
+ /* Default to using normal stack. */
+ usp = rdusp();
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (!sas_ss_flags(usp))
+ usp = current->sas_ss_sp + current->sas_ss_size;
+ }
+ return (void __user *)((usp - frame_size) & -8UL);
+}
+
+static int setup_frame (int sig, struct k_sigaction *ka,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct sigframe __user *frame;
+ int fsize = frame_extra_sizes(regs->format);
+ struct sigcontext context;
+ int err = 0;
+
+ if (fsize < 0) {
+#ifdef DEBUG
+ printk ("setup_frame: Unknown frame format %#x\n",
+ regs->format);
+#endif
+ goto give_sigsegv;
+ }
+
+ frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
+
+ if (fsize)
+ err |= copy_to_user (frame + 1, regs + 1, fsize);
+
+ err |= __put_user((current_thread_info()->exec_domain
+ && current_thread_info()->exec_domain->signal_invmap
+ && sig < 32
+ ? current_thread_info()->exec_domain->signal_invmap[sig]
+ : sig),
+ &frame->sig);
+
+ err |= __put_user(regs->vector, &frame->code);
+ err |= __put_user(&frame->sc, &frame->psc);
+
+ if (_NSIG_WORDS > 1)
+ err |= copy_to_user(frame->extramask, &set->sig[1],
+ sizeof(frame->extramask));
+
+ setup_sigcontext(&context, regs, set->sig[0]);
+ err |= copy_to_user (&frame->sc, &context, sizeof(context));
+
+ /* Set up to return from userspace. */
+#ifdef CONFIG_MMU
+ err |= __put_user(frame->retcode, &frame->pretcode);
+ /* moveq #,d0; trap #0 */
+ err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
+ (long __user *)(frame->retcode));
+#else
+ err |= __put_user((void *) ret_from_user_signal, &frame->pretcode);
+#endif
+
+ if (err)
+ goto give_sigsegv;
+
+ push_cache ((unsigned long) &frame->retcode);
+
+ /*
+ * Set up registers for signal handler. All the state we are about
+ * to destroy is successfully copied to sigframe.
+ */
+ wrusp ((unsigned long) frame);
+ regs->pc = (unsigned long) ka->sa.sa_handler;
+ adjustformat(regs);
+
+ /*
+ * This is subtle; if we build more than one sigframe, all but the
+ * first one will see frame format 0 and have fsize == 0, so we won't
+ * screw stkadj.
+ */
+ if (fsize)
+ regs->stkadj = fsize;
+
+ /* Prepare to skip over the extra stuff in the exception frame. */
+ if (regs->stkadj) {
+ struct pt_regs *tregs =
+ (struct pt_regs *)((ulong)regs + regs->stkadj);
+#ifdef DEBUG
+ printk("Performing stackadjust=%04x\n", regs->stkadj);
+#endif
+ /* This must be copied with decreasing addresses to
+ handle overlaps. */
+ tregs->vector = 0;
+ tregs->format = 0;
+ tregs->pc = regs->pc;
+ tregs->sr = regs->sr;
+ }
+ return 0;
+
+give_sigsegv:
+ force_sigsegv(sig, current);
+ return err;
+}
+
+static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct rt_sigframe __user *frame;
+ int fsize = frame_extra_sizes(regs->format);
+ int err = 0;
+
+ if (fsize < 0) {
+#ifdef DEBUG
+ printk ("setup_frame: Unknown frame format %#x\n",
+ regs->format);
+#endif
+ goto give_sigsegv;
+ }
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+
+ if (fsize)
+ err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
+
+ err |= __put_user((current_thread_info()->exec_domain
+ && current_thread_info()->exec_domain->signal_invmap
+ && sig < 32
+ ? current_thread_info()->exec_domain->signal_invmap[sig]
+ : sig),
+ &frame->sig);
+ err |= __put_user(&frame->info, &frame->pinfo);
+ err |= __put_user(&frame->uc, &frame->puc);
+ err |= copy_siginfo_to_user(&frame->info, info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(NULL, &frame->uc.uc_link);
+ err |= __put_user((void __user *)current->sas_ss_sp,
+ &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(rdusp()),
+ &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= rt_setup_ucontext(&frame->uc, regs);
+ err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
+
+ /* Set up to return from userspace. */
+#ifdef CONFIG_MMU
+ err |= __put_user(frame->retcode, &frame->pretcode);
+#ifdef __mcoldfire__
+ /* movel #__NR_rt_sigreturn,d0; trap #0 */
+ err |= __put_user(0x203c0000, (long __user *)(frame->retcode + 0));
+ err |= __put_user(0x00004e40 + (__NR_rt_sigreturn << 16),
+ (long __user *)(frame->retcode + 4));
+#else
+ /* moveq #,d0; notb d0; trap #0 */
+ err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
+ (long __user *)(frame->retcode + 0));
+ err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4));
+#endif
+#else
+ err |= __put_user((void *) ret_from_user_rt_signal, &frame->pretcode);
+#endif /* CONFIG_MMU */
+
+ if (err)
+ goto give_sigsegv;
+
+ push_cache ((unsigned long) &frame->retcode);
+
+ /*
+ * Set up registers for signal handler. All the state we are about
+ * to destroy is successfully copied to sigframe.
+ */
+ wrusp ((unsigned long) frame);
+ regs->pc = (unsigned long) ka->sa.sa_handler;
+ adjustformat(regs);
+
+ /*
+ * This is subtle; if we build more than one sigframe, all but the
+ * first one will see frame format 0 and have fsize == 0, so we won't
+ * screw stkadj.
+ */
+ if (fsize)
+ regs->stkadj = fsize;
+
+ /* Prepare to skip over the extra stuff in the exception frame. */
+ if (regs->stkadj) {
+ struct pt_regs *tregs =
+ (struct pt_regs *)((ulong)regs + regs->stkadj);
+#ifdef DEBUG
+ printk("Performing stackadjust=%04x\n", regs->stkadj);
+#endif
+ /* This must be copied with decreasing addresses to
+ handle overlaps. */
+ tregs->vector = 0;
+ tregs->format = 0;
+ tregs->pc = regs->pc;
+ tregs->sr = regs->sr;
+ }
+ return 0;
+
+give_sigsegv:
+ force_sigsegv(sig, current);
+ return err;
+}
+
+static inline void
+handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
+{
+ switch (regs->d0) {
+ case -ERESTARTNOHAND:
+ if (!has_handler)
+ goto do_restart;
+ regs->d0 = -EINTR;
+ break;
+
+ case -ERESTART_RESTARTBLOCK:
+ if (!has_handler) {
+ regs->d0 = __NR_restart_syscall;
+ regs->pc -= 2;
+ break;
+ }
+ regs->d0 = -EINTR;
+ break;
+
+ case -ERESTARTSYS:
+ if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
+ regs->d0 = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ do_restart:
+ regs->d0 = regs->orig_d0;
+ regs->pc -= 2;
+ break;
+ }
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static void
+handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *oldset, struct pt_regs *regs)
+{
+ int err;
+ /* are we from a system call? */
+ if (regs->orig_d0 >= 0)
+ /* If so, check system call restarting.. */
+ handle_restart(regs, ka, 1);
+
+ /* set up the stack frame */
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ err = setup_rt_frame(sig, ka, info, oldset, regs);
+ else
+ err = setup_frame(sig, ka, oldset, regs);
+
+ if (err)
+ return;
+
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked,sig);
+ recalc_sigpending();
+
+ if (test_thread_flag(TIF_DELAYED_TRACE)) {
+ regs->sr &= ~0x8000;
+ send_sig(SIGTRAP, current, 1);
+ }
+
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ */
+asmlinkage void do_signal(struct pt_regs *regs)
+{
+ siginfo_t info;
+ struct k_sigaction ka;
+ int signr;
+ sigset_t *oldset;
+
+ current->thread.esp0 = (unsigned long) regs;
+
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
+ oldset = &current->blocked;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ if (signr > 0) {
+ /* Whee! Actually deliver the signal. */
+ handle_signal(signr, &ka, &info, oldset, regs);
+ return;
+ }
+
+ /* Did we come from a system call? */
+ if (regs->orig_d0 >= 0)
+ /* Restart the system call - no handlers present */
+ handle_restart(regs, NULL, 0);
+
+ /* If there's no signal to deliver, we just restore the saved mask. */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
+}
diff --git a/arch/m68k/kernel/signal_mm.c b/arch/m68k/kernel/signal_mm.c
deleted file mode 100644
index cb856f9da655..000000000000
--- a/arch/m68k/kernel/signal_mm.c
+++ /dev/null
@@ -1,1115 +0,0 @@
-/*
- * linux/arch/m68k/kernel/signal.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-/*
- * Linux/m68k support by Hamish Macdonald
- *
- * 68060 fixes by Jesper Skov
- *
- * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
- *
- * mathemu support by Roman Zippel
- * (Note: fpstate in the signal context is completely ignored for the emulator
- * and the internal floating point format is put on stack)
- */
-
-/*
- * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
- * Atari :-) Current limitation: Only one sigstack can be active at one time.
- * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
- * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
- * signal handlers!
- */
-
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/syscalls.h>
-#include <linux/errno.h>
-#include <linux/wait.h>
-#include <linux/ptrace.h>
-#include <linux/unistd.h>
-#include <linux/stddef.h>
-#include <linux/highuid.h>
-#include <linux/personality.h>
-#include <linux/tty.h>
-#include <linux/binfmts.h>
-#include <linux/module.h>
-
-#include <asm/setup.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/traps.h>
-#include <asm/ucontext.h>
-
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-static const int frame_extra_sizes[16] = {
- [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
- [2] = sizeof(((struct frame *)0)->un.fmt2),
- [3] = sizeof(((struct frame *)0)->un.fmt3),
-#ifdef CONFIG_COLDFIRE
- [4] = 0,
-#else
- [4] = sizeof(((struct frame *)0)->un.fmt4),
-#endif
- [5] = -1, /* sizeof(((struct frame *)0)->un.fmt5), */
- [6] = -1, /* sizeof(((struct frame *)0)->un.fmt6), */
- [7] = sizeof(((struct frame *)0)->un.fmt7),
- [8] = -1, /* sizeof(((struct frame *)0)->un.fmt8), */
- [9] = sizeof(((struct frame *)0)->un.fmt9),
- [10] = sizeof(((struct frame *)0)->un.fmta),
- [11] = sizeof(((struct frame *)0)->un.fmtb),
- [12] = -1, /* sizeof(((struct frame *)0)->un.fmtc), */
- [13] = -1, /* sizeof(((struct frame *)0)->un.fmtd), */
- [14] = -1, /* sizeof(((struct frame *)0)->un.fmte), */
- [15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */
-};
-
-int handle_kernel_fault(struct pt_regs *regs)
-{
- const struct exception_table_entry *fixup;
- struct pt_regs *tregs;
-
- /* Are we prepared to handle this kernel fault? */
- fixup = search_exception_tables(regs->pc);
- if (!fixup)
- return 0;
-
- /* Create a new four word stack frame, discarding the old one. */
- regs->stkadj = frame_extra_sizes[regs->format];
- tregs = (struct pt_regs *)((long)regs + regs->stkadj);
- tregs->vector = regs->vector;
-#ifdef CONFIG_COLDFIRE
- tregs->format = 4;
-#else
- tregs->format = 0;
-#endif
- tregs->pc = fixup->fixup;
- tregs->sr = regs->sr;
-
- return 1;
-}
-
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage int
-sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
-{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
- current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- set_restore_sigmask();
-
- return -ERESTARTNOHAND;
-}
-
-asmlinkage int
-sys_sigaction(int sig, const struct old_sigaction __user *act,
- struct old_sigaction __user *oact)
-{
- struct k_sigaction new_ka, old_ka;
- int ret;
-
- if (act) {
- old_sigset_t mask;
- if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
- __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
- __get_user(mask, &act->sa_mask))
- return -EFAULT;
- siginitset(&new_ka.sa.sa_mask, mask);
- }
-
- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
- if (!ret && oact) {
- if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
- return -EFAULT;
- }
-
- return ret;
-}
-
-asmlinkage int
-sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
-{
- return do_sigaltstack(uss, uoss, rdusp());
-}
-
-
-/*
- * Do a signal return; undo the signal stack.
- *
- * Keep the return code on the stack quadword aligned!
- * That makes the cache flush below easier.
- */
-
-struct sigframe
-{
- char __user *pretcode;
- int sig;
- int code;
- struct sigcontext __user *psc;
- char retcode[8];
- unsigned long extramask[_NSIG_WORDS-1];
- struct sigcontext sc;
-};
-
-struct rt_sigframe
-{
- char __user *pretcode;
- int sig;
- struct siginfo __user *pinfo;
- void __user *puc;
- char retcode[8];
- struct siginfo info;
- struct ucontext uc;
-};
-
-
-static unsigned char fpu_version; /* version number of fpu, set by setup_frame */
-
-static inline int restore_fpu_state(struct sigcontext *sc)
-{
- int err = 1;
-
- if (FPU_IS_EMU) {
- /* restore registers */
- memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
- memcpy(current->thread.fp, sc->sc_fpregs, 24);
- return 0;
- }
-
- if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
- /* Verify the frame format. */
- if (!(CPU_IS_060 || CPU_IS_COLDFIRE) &&
- (sc->sc_fpstate[0] != fpu_version))
- goto out;
- if (CPU_IS_020_OR_030) {
- if (m68k_fputype & FPU_68881 &&
- !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4))
- goto out;
- if (m68k_fputype & FPU_68882 &&
- !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4))
- goto out;
- } else if (CPU_IS_040) {
- if (!(sc->sc_fpstate[1] == 0x00 ||
- sc->sc_fpstate[1] == 0x28 ||
- sc->sc_fpstate[1] == 0x60))
- goto out;
- } else if (CPU_IS_060) {
- if (!(sc->sc_fpstate[3] == 0x00 ||
- sc->sc_fpstate[3] == 0x60 ||
- sc->sc_fpstate[3] == 0xe0))
- goto out;
- } else if (CPU_IS_COLDFIRE) {
- if (!(sc->sc_fpstate[0] == 0x00 ||
- sc->sc_fpstate[0] == 0x05 ||
- sc->sc_fpstate[0] == 0xe5))
- goto out;
- } else
- goto out;
-
- if (CPU_IS_COLDFIRE) {
- __asm__ volatile ("fmovemd %0,%%fp0-%%fp1\n\t"
- "fmovel %1,%%fpcr\n\t"
- "fmovel %2,%%fpsr\n\t"
- "fmovel %3,%%fpiar"
- : /* no outputs */
- : "m" (sc->sc_fpregs[0]),
- "m" (sc->sc_fpcntl[0]),
- "m" (sc->sc_fpcntl[1]),
- "m" (sc->sc_fpcntl[2]));
- } else {
- __asm__ volatile (".chip 68k/68881\n\t"
- "fmovemx %0,%%fp0-%%fp1\n\t"
- "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
- ".chip 68k"
- : /* no outputs */
- : "m" (*sc->sc_fpregs),
- "m" (*sc->sc_fpcntl));
- }
- }
-
- if (CPU_IS_COLDFIRE) {
- __asm__ volatile ("frestore %0" : : "m" (*sc->sc_fpstate));
- } else {
- __asm__ volatile (".chip 68k/68881\n\t"
- "frestore %0\n\t"
- ".chip 68k"
- : : "m" (*sc->sc_fpstate));
- }
- err = 0;
-
-out:
- return err;
-}
-
-#define FPCONTEXT_SIZE 216
-#define uc_fpstate uc_filler[0]
-#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
-#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
-
-static inline int rt_restore_fpu_state(struct ucontext __user *uc)
-{
- unsigned char fpstate[FPCONTEXT_SIZE];
- int context_size = CPU_IS_060 ? 8 : (CPU_IS_COLDFIRE ? 12 : 0);
- fpregset_t fpregs;
- int err = 1;
-
- if (FPU_IS_EMU) {
- /* restore fpu control register */
- if (__copy_from_user(current->thread.fpcntl,
- uc->uc_mcontext.fpregs.f_fpcntl, 12))
- goto out;
- /* restore all other fpu register */
- if (__copy_from_user(current->thread.fp,
- uc->uc_mcontext.fpregs.f_fpregs, 96))
- goto out;
- return 0;
- }
-
- if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
- goto out;
- if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
- if (!(CPU_IS_060 || CPU_IS_COLDFIRE))
- context_size = fpstate[1];
- /* Verify the frame format. */
- if (!(CPU_IS_060 || CPU_IS_COLDFIRE) &&
- (fpstate[0] != fpu_version))
- goto out;
- if (CPU_IS_020_OR_030) {
- if (m68k_fputype & FPU_68881 &&
- !(context_size == 0x18 || context_size == 0xb4))
- goto out;
- if (m68k_fputype & FPU_68882 &&
- !(context_size == 0x38 || context_size == 0xd4))
- goto out;
- } else if (CPU_IS_040) {
- if (!(context_size == 0x00 ||
- context_size == 0x28 ||
- context_size == 0x60))
- goto out;
- } else if (CPU_IS_060) {
- if (!(fpstate[3] == 0x00 ||
- fpstate[3] == 0x60 ||
- fpstate[3] == 0xe0))
- goto out;
- } else if (CPU_IS_COLDFIRE) {
- if (!(fpstate[3] == 0x00 ||
- fpstate[3] == 0x05 ||
- fpstate[3] == 0xe5))
- goto out;
- } else
- goto out;
- if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
- sizeof(fpregs)))
- goto out;
-
- if (CPU_IS_COLDFIRE) {
- __asm__ volatile ("fmovemd %0,%%fp0-%%fp7\n\t"
- "fmovel %1,%%fpcr\n\t"
- "fmovel %2,%%fpsr\n\t"
- "fmovel %3,%%fpiar"
- : /* no outputs */
- : "m" (fpregs.f_fpregs[0]),
- "m" (fpregs.f_fpcntl[0]),
- "m" (fpregs.f_fpcntl[1]),
- "m" (fpregs.f_fpcntl[2]));
- } else {
- __asm__ volatile (".chip 68k/68881\n\t"
- "fmovemx %0,%%fp0-%%fp7\n\t"
- "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
- ".chip 68k"
- : /* no outputs */
- : "m" (*fpregs.f_fpregs),
- "m" (*fpregs.f_fpcntl));
- }
- }
- if (context_size &&
- __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
- context_size))
- goto out;
-
- if (CPU_IS_COLDFIRE) {
- __asm__ volatile ("frestore %0" : : "m" (*fpstate));
- } else {
- __asm__ volatile (".chip 68k/68881\n\t"
- "frestore %0\n\t"
- ".chip 68k"
- : : "m" (*fpstate));
- }
- err = 0;
-
-out:
- return err;
-}
-
-static int mangle_kernel_stack(struct pt_regs *regs, int formatvec,
- void __user *fp)
-{
- int fsize = frame_extra_sizes[formatvec >> 12];
- if (fsize < 0) {
- /*
- * user process trying to return with weird frame format
- */
-#ifdef DEBUG
- printk("user process returning with weird frame format\n");
-#endif
- return 1;
- }
- if (!fsize) {
- regs->format = formatvec >> 12;
- regs->vector = formatvec & 0xfff;
- } else {
- struct switch_stack *sw = (struct switch_stack *)regs - 1;
- unsigned long buf[fsize / 2]; /* yes, twice as much */
-
- /* that'll make sure that expansion won't crap over data */
- if (copy_from_user(buf + fsize / 4, fp, fsize))
- return 1;
-
- /* point of no return */
- regs->format = formatvec >> 12;
- regs->vector = formatvec & 0xfff;
-#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
- __asm__ __volatile__ (
-#ifdef CONFIG_COLDFIRE
- " movel %0,%/sp\n\t"
- " bra ret_from_signal\n"
-#else
- " movel %0,%/a0\n\t"
- " subl %1,%/a0\n\t" /* make room on stack */
- " movel %/a0,%/sp\n\t" /* set stack pointer */
- /* move switch_stack and pt_regs */
- "1: movel %0@+,%/a0@+\n\t"
- " dbra %2,1b\n\t"
- " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
- " lsrl #2,%1\n\t"
- " subql #1,%1\n\t"
- /* copy to the gap we'd made */
- "2: movel %4@+,%/a0@+\n\t"
- " dbra %1,2b\n\t"
- " bral ret_from_signal\n"
-#endif
- : /* no outputs, it doesn't ever return */
- : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
- "n" (frame_offset), "a" (buf + fsize/4)
- : "a0");
-#undef frame_offset
- }
- return 0;
-}
-
-static inline int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp)
-{
- int formatvec;
- struct sigcontext context;
- int err;
-
- /* Always make any pending restarted system calls return -EINTR */
- current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
- /* get previous context */
- if (copy_from_user(&context, usc, sizeof(context)))
- goto badframe;
-
- /* restore passed registers */
- regs->d0 = context.sc_d0;
- regs->d1 = context.sc_d1;
- regs->a0 = context.sc_a0;
- regs->a1 = context.sc_a1;
- regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
- regs->pc = context.sc_pc;
- regs->orig_d0 = -1; /* disable syscall checks */
- wrusp(context.sc_usp);
- formatvec = context.sc_formatvec;
-
- err = restore_fpu_state(&context);
-
- if (err || mangle_kernel_stack(regs, formatvec, fp))
- goto badframe;
-
- return 0;
-
-badframe:
- return 1;
-}
-
-static inline int
-rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
- struct ucontext __user *uc)
-{
- int temp;
- greg_t __user *gregs = uc->uc_mcontext.gregs;
- unsigned long usp;
- int err;
-
- /* Always make any pending restarted system calls return -EINTR */
- current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
- err = __get_user(temp, &uc->uc_mcontext.version);
- if (temp != MCONTEXT_VERSION)
- goto badframe;
- /* restore passed registers */
- err |= __get_user(regs->d0, &gregs[0]);
- err |= __get_user(regs->d1, &gregs[1]);
- err |= __get_user(regs->d2, &gregs[2]);
- err |= __get_user(regs->d3, &gregs[3]);
- err |= __get_user(regs->d4, &gregs[4]);
- err |= __get_user(regs->d5, &gregs[5]);
- err |= __get_user(sw->d6, &gregs[6]);
- err |= __get_user(sw->d7, &gregs[7]);
- err |= __get_user(regs->a0, &gregs[8]);
- err |= __get_user(regs->a1, &gregs[9]);
- err |= __get_user(regs->a2, &gregs[10]);
- err |= __get_user(sw->a3, &gregs[11]);
- err |= __get_user(sw->a4, &gregs[12]);
- err |= __get_user(sw->a5, &gregs[13]);
- err |= __get_user(sw->a6, &gregs[14]);
- err |= __get_user(usp, &gregs[15]);
- wrusp(usp);
- err |= __get_user(regs->pc, &gregs[16]);
- err |= __get_user(temp, &gregs[17]);
- regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
- regs->orig_d0 = -1; /* disable syscall checks */
- err |= __get_user(temp, &uc->uc_formatvec);
-
- err |= rt_restore_fpu_state(uc);
-
- if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
- goto badframe;
-
- if (mangle_kernel_stack(regs, temp, &uc->uc_extra))
- goto badframe;
-
- return 0;
-
-badframe:
- return 1;
-}
-
-asmlinkage int do_sigreturn(unsigned long __unused)
-{
- struct switch_stack *sw = (struct switch_stack *) &__unused;
- struct pt_regs *regs = (struct pt_regs *) (sw + 1);
- unsigned long usp = rdusp();
- struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
- sigset_t set;
-
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
- if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
- (_NSIG_WORDS > 1 &&
- __copy_from_user(&set.sig[1], &frame->extramask,
- sizeof(frame->extramask))))
- goto badframe;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
- current->blocked = set;
- recalc_sigpending();
-
- if (restore_sigcontext(regs, &frame->sc, frame + 1))
- goto badframe;
- return regs->d0;
-
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
-
-asmlinkage int do_rt_sigreturn(unsigned long __unused)
-{
- struct switch_stack *sw = (struct switch_stack *) &__unused;
- struct pt_regs *regs = (struct pt_regs *) (sw + 1);
- unsigned long usp = rdusp();
- struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
- sigset_t set;
-
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
- if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
- goto badframe;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
- current->blocked = set;
- recalc_sigpending();
-
- if (rt_restore_ucontext(regs, sw, &frame->uc))
- goto badframe;
- return regs->d0;
-
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
-
-/*
- * Set up a signal frame.
- */
-
-static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
-{
- if (FPU_IS_EMU) {
- /* save registers */
- memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
- memcpy(sc->sc_fpregs, current->thread.fp, 24);
- return;
- }
-
- if (CPU_IS_COLDFIRE) {
- __asm__ volatile ("fsave %0"
- : : "m" (*sc->sc_fpstate) : "memory");
- } else {
- __asm__ volatile (".chip 68k/68881\n\t"
- "fsave %0\n\t"
- ".chip 68k"
- : : "m" (*sc->sc_fpstate) : "memory");
- }
-
- if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
- fpu_version = sc->sc_fpstate[0];
- if (CPU_IS_020_OR_030 &&
- regs->vector >= (VEC_FPBRUC * 4) &&
- regs->vector <= (VEC_FPNAN * 4)) {
- /* Clear pending exception in 68882 idle frame */
- if (*(unsigned short *) sc->sc_fpstate == 0x1f38)
- sc->sc_fpstate[0x38] |= 1 << 3;
- }
-
- if (CPU_IS_COLDFIRE) {
- __asm__ volatile ("fmovemd %%fp0-%%fp1,%0\n\t"
- "fmovel %%fpcr,%1\n\t"
- "fmovel %%fpsr,%2\n\t"
- "fmovel %%fpiar,%3"
- : "=m" (sc->sc_fpregs[0]),
- "=m" (sc->sc_fpcntl[0]),
- "=m" (sc->sc_fpcntl[1]),
- "=m" (sc->sc_fpcntl[2])
- : /* no inputs */
- : "memory");
- } else {
- __asm__ volatile (".chip 68k/68881\n\t"
- "fmovemx %%fp0-%%fp1,%0\n\t"
- "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
- ".chip 68k"
- : "=m" (*sc->sc_fpregs),
- "=m" (*sc->sc_fpcntl)
- : /* no inputs */
- : "memory");
- }
- }
-}
-
-static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
-{
- unsigned char fpstate[FPCONTEXT_SIZE];
- int context_size = CPU_IS_060 ? 8 : (CPU_IS_COLDFIRE ? 12 : 0);
- int err = 0;
-
- if (FPU_IS_EMU) {
- /* save fpu control register */
- err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl,
- current->thread.fpcntl, 12);
- /* save all other fpu register */
- err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
- current->thread.fp, 96);
- return err;
- }
-
- if (CPU_IS_COLDFIRE) {
- __asm__ volatile ("fsave %0" : : "m" (*fpstate) : "memory");
- } else {
- __asm__ volatile (".chip 68k/68881\n\t"
- "fsave %0\n\t"
- ".chip 68k"
- : : "m" (*fpstate) : "memory");
- }
-
- err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
- if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
- fpregset_t fpregs;
- if (!(CPU_IS_060 || CPU_IS_COLDFIRE))
- context_size = fpstate[1];
- fpu_version = fpstate[0];
- if (CPU_IS_020_OR_030 &&
- regs->vector >= (VEC_FPBRUC * 4) &&
- regs->vector <= (VEC_FPNAN * 4)) {
- /* Clear pending exception in 68882 idle frame */
- if (*(unsigned short *) fpstate == 0x1f38)
- fpstate[0x38] |= 1 << 3;
- }
- if (CPU_IS_COLDFIRE) {
- __asm__ volatile ("fmovemd %%fp0-%%fp7,%0\n\t"
- "fmovel %%fpcr,%1\n\t"
- "fmovel %%fpsr,%2\n\t"
- "fmovel %%fpiar,%3"
- : "=m" (fpregs.f_fpregs[0]),
- "=m" (fpregs.f_fpcntl[0]),
- "=m" (fpregs.f_fpcntl[1]),
- "=m" (fpregs.f_fpcntl[2])
- : /* no inputs */
- : "memory");
- } else {
- __asm__ volatile (".chip 68k/68881\n\t"
- "fmovemx %%fp0-%%fp7,%0\n\t"
- "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
- ".chip 68k"
- : "=m" (*fpregs.f_fpregs),
- "=m" (*fpregs.f_fpcntl)
- : /* no inputs */
- : "memory");
- }
- err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
- sizeof(fpregs));
- }
- if (context_size)
- err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
- context_size);
- return err;
-}
-
-static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
- unsigned long mask)
-{
- sc->sc_mask = mask;
- sc->sc_usp = rdusp();
- sc->sc_d0 = regs->d0;
- sc->sc_d1 = regs->d1;
- sc->sc_a0 = regs->a0;
- sc->sc_a1 = regs->a1;
- sc->sc_sr = regs->sr;
- sc->sc_pc = regs->pc;
- sc->sc_formatvec = regs->format << 12 | regs->vector;
- save_fpu_state(sc, regs);
-}
-
-static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
-{
- struct switch_stack *sw = (struct switch_stack *)regs - 1;
- greg_t __user *gregs = uc->uc_mcontext.gregs;
- int err = 0;
-
- err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
- err |= __put_user(regs->d0, &gregs[0]);
- err |= __put_user(regs->d1, &gregs[1]);
- err |= __put_user(regs->d2, &gregs[2]);
- err |= __put_user(regs->d3, &gregs[3]);
- err |= __put_user(regs->d4, &gregs[4]);
- err |= __put_user(regs->d5, &gregs[5]);
- err |= __put_user(sw->d6, &gregs[6]);
- err |= __put_user(sw->d7, &gregs[7]);
- err |= __put_user(regs->a0, &gregs[8]);
- err |= __put_user(regs->a1, &gregs[9]);
- err |= __put_user(regs->a2, &gregs[10]);
- err |= __put_user(sw->a3, &gregs[11]);
- err |= __put_user(sw->a4, &gregs[12]);
- err |= __put_user(sw->a5, &gregs[13]);
- err |= __put_user(sw->a6, &gregs[14]);
- err |= __put_user(rdusp(), &gregs[15]);
- err |= __put_user(regs->pc, &gregs[16]);
- err |= __put_user(regs->sr, &gregs[17]);
- err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
- err |= rt_save_fpu_state(uc, regs);
- return err;
-}
-
-static inline void push_cache (unsigned long vaddr)
-{
- /*
- * Using the old cache_push_v() was really a big waste.
- *
- * What we are trying to do is to flush 8 bytes to ram.
- * Flushing 2 cache lines of 16 bytes is much cheaper than
- * flushing 1 or 2 pages, as previously done in
- * cache_push_v().
- * Jes
- */
- if (CPU_IS_040) {
- unsigned long temp;
-
- __asm__ __volatile__ (".chip 68040\n\t"
- "nop\n\t"
- "ptestr (%1)\n\t"
- "movec %%mmusr,%0\n\t"
- ".chip 68k"
- : "=r" (temp)
- : "a" (vaddr));
-
- temp &= PAGE_MASK;
- temp |= vaddr & ~PAGE_MASK;
-
- __asm__ __volatile__ (".chip 68040\n\t"
- "nop\n\t"
- "cpushl %%bc,(%0)\n\t"
- ".chip 68k"
- : : "a" (temp));
- }
- else if (CPU_IS_060) {
- unsigned long temp;
- __asm__ __volatile__ (".chip 68060\n\t"
- "plpar (%0)\n\t"
- ".chip 68k"
- : "=a" (temp)
- : "0" (vaddr));
- __asm__ __volatile__ (".chip 68060\n\t"
- "cpushl %%bc,(%0)\n\t"
- ".chip 68k"
- : : "a" (temp));
- } else if (!CPU_IS_COLDFIRE) {
- /*
- * 68030/68020 have no writeback cache;
- * still need to clear icache.
- * Note that vaddr is guaranteed to be long word aligned.
- */
- unsigned long temp;
- asm volatile ("movec %%cacr,%0" : "=r" (temp));
- temp += 4;
- asm volatile ("movec %0,%%caar\n\t"
- "movec %1,%%cacr"
- : : "r" (vaddr), "r" (temp));
- asm volatile ("movec %0,%%caar\n\t"
- "movec %1,%%cacr"
- : : "r" (vaddr + 4), "r" (temp));
- }
-}
-
-static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
-{
- unsigned long usp;
-
- /* Default to using normal stack. */
- usp = rdusp();
-
- /* This is the X/Open sanctioned signal stack switching. */
- if (ka->sa.sa_flags & SA_ONSTACK) {
- if (!sas_ss_flags(usp))
- usp = current->sas_ss_sp + current->sas_ss_size;
- }
- return (void __user *)((usp - frame_size) & -8UL);
-}
-
-static int setup_frame (int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs *regs)
-{
- struct sigframe __user *frame;
- int fsize = frame_extra_sizes[regs->format];
- struct sigcontext context;
- int err = 0;
-
- if (fsize < 0) {
-#ifdef DEBUG
- printk ("setup_frame: Unknown frame format %#x\n",
- regs->format);
-#endif
- goto give_sigsegv;
- }
-
- frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
-
- if (fsize)
- err |= copy_to_user (frame + 1, regs + 1, fsize);
-
- err |= __put_user((current_thread_info()->exec_domain
- && current_thread_info()->exec_domain->signal_invmap
- && sig < 32
- ? current_thread_info()->exec_domain->signal_invmap[sig]
- : sig),
- &frame->sig);
-
- err |= __put_user(regs->vector, &frame->code);
- err |= __put_user(&frame->sc, &frame->psc);
-
- if (_NSIG_WORDS > 1)
- err |= copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
-
- setup_sigcontext(&context, regs, set->sig[0]);
- err |= copy_to_user (&frame->sc, &context, sizeof(context));
-
- /* Set up to return from userspace. */
- err |= __put_user(frame->retcode, &frame->pretcode);
- /* moveq #,d0; trap #0 */
- err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
- (long __user *)(frame->retcode));
-
- if (err)
- goto give_sigsegv;
-
- push_cache ((unsigned long) &frame->retcode);
-
- /*
- * Set up registers for signal handler. All the state we are about
- * to destroy is successfully copied to sigframe.
- */
- wrusp ((unsigned long) frame);
- regs->pc = (unsigned long) ka->sa.sa_handler;
-
- /*
- * This is subtle; if we build more than one sigframe, all but the
- * first one will see frame format 0 and have fsize == 0, so we won't
- * screw stkadj.
- */
- if (fsize)
- regs->stkadj = fsize;
-
- /* Prepare to skip over the extra stuff in the exception frame. */
- if (regs->stkadj) {
- struct pt_regs *tregs =
- (struct pt_regs *)((ulong)regs + regs->stkadj);
-#ifdef DEBUG
- printk("Performing stackadjust=%04x\n", regs->stkadj);
-#endif
- /* This must be copied with decreasing addresses to
- handle overlaps. */
- tregs->vector = 0;
- tregs->format = 0;
- tregs->pc = regs->pc;
- tregs->sr = regs->sr;
- }
- return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return err;
-}
-
-static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
-{
- struct rt_sigframe __user *frame;
- int fsize = frame_extra_sizes[regs->format];
- int err = 0;
-
- if (fsize < 0) {
-#ifdef DEBUG
- printk ("setup_frame: Unknown frame format %#x\n",
- regs->format);
-#endif
- goto give_sigsegv;
- }
-
- frame = get_sigframe(ka, regs, sizeof(*frame));
-
- if (fsize)
- err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
-
- err |= __put_user((current_thread_info()->exec_domain
- && current_thread_info()->exec_domain->signal_invmap
- && sig < 32
- ? current_thread_info()->exec_domain->signal_invmap[sig]
- : sig),
- &frame->sig);
- err |= __put_user(&frame->info, &frame->pinfo);
- err |= __put_user(&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user(&frame->info, info);
-
- /* Create the ucontext. */
- err |= __put_user(0, &frame->uc.uc_flags);
- err |= __put_user(NULL, &frame->uc.uc_link);
- err |= __put_user((void __user *)current->sas_ss_sp,
- &frame->uc.uc_stack.ss_sp);
- err |= __put_user(sas_ss_flags(rdusp()),
- &frame->uc.uc_stack.ss_flags);
- err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
- err |= rt_setup_ucontext(&frame->uc, regs);
- err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
-
- /* Set up to return from userspace. */
- err |= __put_user(frame->retcode, &frame->pretcode);
-#ifdef __mcoldfire__
- /* movel #__NR_rt_sigreturn,d0; trap #0 */
- err |= __put_user(0x203c0000, (long __user *)(frame->retcode + 0));
- err |= __put_user(0x00004e40 + (__NR_rt_sigreturn << 16),
- (long __user *)(frame->retcode + 4));
-#else
- /* moveq #,d0; notb d0; trap #0 */
- err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
- (long __user *)(frame->retcode + 0));
- err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4));
-#endif
-
- if (err)
- goto give_sigsegv;
-
- push_cache ((unsigned long) &frame->retcode);
-
- /*
- * Set up registers for signal handler. All the state we are about
- * to destroy is successfully copied to sigframe.
- */
- wrusp ((unsigned long) frame);
- regs->pc = (unsigned long) ka->sa.sa_handler;
-
- /*
- * This is subtle; if we build more than one sigframe, all but the
- * first one will see frame format 0 and have fsize == 0, so we won't
- * screw stkadj.
- */
- if (fsize)
- regs->stkadj = fsize;
-
- /* Prepare to skip over the extra stuff in the exception frame. */
- if (regs->stkadj) {
- struct pt_regs *tregs =
- (struct pt_regs *)((ulong)regs + regs->stkadj);
-#ifdef DEBUG
- printk("Performing stackadjust=%04x\n", regs->stkadj);
-#endif
- /* This must be copied with decreasing addresses to
- handle overlaps. */
- tregs->vector = 0;
- tregs->format = 0;
- tregs->pc = regs->pc;
- tregs->sr = regs->sr;
- }
- return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return err;
-}
-
-static inline void
-handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
-{
- switch (regs->d0) {
- case -ERESTARTNOHAND:
- if (!has_handler)
- goto do_restart;
- regs->d0 = -EINTR;
- break;
-
- case -ERESTART_RESTARTBLOCK:
- if (!has_handler) {
- regs->d0 = __NR_restart_syscall;
- regs->pc -= 2;
- break;
- }
- regs->d0 = -EINTR;
- break;
-
- case -ERESTARTSYS:
- if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
- regs->d0 = -EINTR;
- break;
- }
- /* fallthrough */
- case -ERESTARTNOINTR:
- do_restart:
- regs->d0 = regs->orig_d0;
- regs->pc -= 2;
- break;
- }
-}
-
-void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
-{
- if (regs->orig_d0 < 0)
- return;
- switch (regs->d0) {
- case -ERESTARTNOHAND:
- case -ERESTARTSYS:
- case -ERESTARTNOINTR:
- regs->d0 = regs->orig_d0;
- regs->orig_d0 = -1;
- regs->pc -= 2;
- break;
- }
-}
-
-/*
- * OK, we're invoking a handler
- */
-static void
-handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *oldset, struct pt_regs *regs)
-{
- int err;
- /* are we from a system call? */
- if (regs->orig_d0 >= 0)
- /* If so, check system call restarting.. */
- handle_restart(regs, ka, 1);
-
- /* set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- err = setup_rt_frame(sig, ka, info, oldset, regs);
- else
- err = setup_frame(sig, ka, oldset, regs);
-
- if (err)
- return;
-
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
-
- if (test_thread_flag(TIF_DELAYED_TRACE)) {
- regs->sr &= ~0x8000;
- send_sig(SIGTRAP, current, 1);
- }
-
- clear_thread_flag(TIF_RESTORE_SIGMASK);
-}
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- */
-asmlinkage void do_signal(struct pt_regs *regs)
-{
- siginfo_t info;
- struct k_sigaction ka;
- int signr;
- sigset_t *oldset;
-
- current->thread.esp0 = (unsigned long) regs;
-
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
- oldset = &current->saved_sigmask;
- else
- oldset = &current->blocked;
-
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
- /* Whee! Actually deliver the signal. */
- handle_signal(signr, &ka, &info, oldset, regs);
- return;
- }
-
- /* Did we come from a system call? */
- if (regs->orig_d0 >= 0)
- /* Restart the system call - no handlers present */
- handle_restart(regs, NULL, 0);
-
- /* If there's no signal to deliver, we just restore the saved mask. */
- if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
- clear_thread_flag(TIF_RESTORE_SIGMASK);
- sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
- }
-}
diff --git a/arch/m68k/kernel/signal_no.c b/arch/m68k/kernel/signal_no.c
deleted file mode 100644
index 36a81bb6835a..000000000000
--- a/arch/m68k/kernel/signal_no.c
+++ /dev/null
@@ -1,765 +0,0 @@
-/*
- * linux/arch/m68knommu/kernel/signal.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-/*
- * Linux/m68k support by Hamish Macdonald
- *
- * 68060 fixes by Jesper Skov
- *
- * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
- *
- * mathemu support by Roman Zippel
- * (Note: fpstate in the signal context is completely ignored for the emulator
- * and the internal floating point format is put on stack)
- */
-
-/*
- * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
- * Atari :-) Current limitation: Only one sigstack can be active at one time.
- * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
- * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
- * signal handlers!
- */
-
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/syscalls.h>
-#include <linux/errno.h>
-#include <linux/wait.h>
-#include <linux/ptrace.h>
-#include <linux/unistd.h>
-#include <linux/stddef.h>
-#include <linux/highuid.h>
-#include <linux/tty.h>
-#include <linux/personality.h>
-#include <linux/binfmts.h>
-
-#include <asm/setup.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/traps.h>
-#include <asm/ucontext.h>
-
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-void ret_from_user_signal(void);
-void ret_from_user_rt_signal(void);
-
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage int
-sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
-{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
- current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- set_restore_sigmask();
-
- return -ERESTARTNOHAND;
-}
-
-asmlinkage int
-sys_sigaction(int sig, const struct old_sigaction __user *act,
- struct old_sigaction __user *oact)
-{
- struct k_sigaction new_ka, old_ka;
- int ret;
-
- if (act) {
- old_sigset_t mask;
- if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
- __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
- __get_user(mask, &act->sa_mask))
- return -EFAULT;
- siginitset(&new_ka.sa.sa_mask, mask);
- }
-
- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
- if (!ret && oact) {
- if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
- return -EFAULT;
- }
-
- return ret;
-}
-
-asmlinkage int
-sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
-{
- return do_sigaltstack(uss, uoss, rdusp());
-}
-
-
-/*
- * Do a signal return; undo the signal stack.
- *
- * Keep the return code on the stack quadword aligned!
- * That makes the cache flush below easier.
- */
-
-struct sigframe
-{
- char __user *pretcode;
- int sig;
- int code;
- struct sigcontext __user *psc;
- char retcode[8];
- unsigned long extramask[_NSIG_WORDS-1];
- struct sigcontext sc;
-};
-
-struct rt_sigframe
-{
- char __user *pretcode;
- int sig;
- struct siginfo __user *pinfo;
- void __user *puc;
- char retcode[8];
- struct siginfo info;
- struct ucontext uc;
-};
-
-#ifdef CONFIG_FPU
-
-static unsigned char fpu_version = 0; /* version number of fpu, set by setup_frame */
-
-static inline int restore_fpu_state(struct sigcontext *sc)
-{
- int err = 1;
-
- if (FPU_IS_EMU) {
- /* restore registers */
- memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
- memcpy(current->thread.fp, sc->sc_fpregs, 24);
- return 0;
- }
-
- if (sc->sc_fpstate[0]) {
- /* Verify the frame format. */
- if (sc->sc_fpstate[0] != fpu_version)
- goto out;
-
- __asm__ volatile (".chip 68k/68881\n\t"
- "fmovemx %0,%%fp0-%%fp1\n\t"
- "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
- ".chip 68k"
- : /* no outputs */
- : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
- }
- __asm__ volatile (".chip 68k/68881\n\t"
- "frestore %0\n\t"
- ".chip 68k" : : "m" (*sc->sc_fpstate));
- err = 0;
-
-out:
- return err;
-}
-
-#define FPCONTEXT_SIZE 216
-#define uc_fpstate uc_filler[0]
-#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
-#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
-
-static inline int rt_restore_fpu_state(struct ucontext __user *uc)
-{
- unsigned char fpstate[FPCONTEXT_SIZE];
- int context_size = 0;
- fpregset_t fpregs;
- int err = 1;
-
- if (FPU_IS_EMU) {
- /* restore fpu control register */
- if (__copy_from_user(current->thread.fpcntl,
- uc->uc_mcontext.fpregs.f_fpcntl, 12))
- goto out;
- /* restore all other fpu register */
- if (__copy_from_user(current->thread.fp,
- uc->uc_mcontext.fpregs.f_fpregs, 96))
- goto out;
- return 0;
- }
-
- if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
- goto out;
- if (fpstate[0]) {
- context_size = fpstate[1];
-
- /* Verify the frame format. */
- if (fpstate[0] != fpu_version)
- goto out;
- if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
- sizeof(fpregs)))
- goto out;
- __asm__ volatile (".chip 68k/68881\n\t"
- "fmovemx %0,%%fp0-%%fp7\n\t"
- "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
- ".chip 68k"
- : /* no outputs */
- : "m" (*fpregs.f_fpregs),
- "m" (*fpregs.f_fpcntl));
- }
- if (context_size &&
- __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
- context_size))
- goto out;
- __asm__ volatile (".chip 68k/68881\n\t"
- "frestore %0\n\t"
- ".chip 68k" : : "m" (*fpstate));
- err = 0;
-
-out:
- return err;
-}
-
-#endif
-
-static inline int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp,
- int *pd0)
-{
- int formatvec;
- struct sigcontext context;
- int err = 0;
-
- /* Always make any pending restarted system calls return -EINTR */
- current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
- /* get previous context */
- if (copy_from_user(&context, usc, sizeof(context)))
- goto badframe;
-
- /* restore passed registers */
- regs->d1 = context.sc_d1;
- regs->a0 = context.sc_a0;
- regs->a1 = context.sc_a1;
- ((struct switch_stack *)regs - 1)->a5 = context.sc_a5;
- regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
- regs->pc = context.sc_pc;
- regs->orig_d0 = -1; /* disable syscall checks */
- wrusp(context.sc_usp);
- formatvec = context.sc_formatvec;
- regs->format = formatvec >> 12;
- regs->vector = formatvec & 0xfff;
-
-#ifdef CONFIG_FPU
- err = restore_fpu_state(&context);
-#endif
-
- *pd0 = context.sc_d0;
- return err;
-
-badframe:
- return 1;
-}
-
-static inline int
-rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
- struct ucontext __user *uc, int *pd0)
-{
- int temp;
- greg_t __user *gregs = uc->uc_mcontext.gregs;
- unsigned long usp;
- int err;
-
- /* Always make any pending restarted system calls return -EINTR */
- current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
- err = __get_user(temp, &uc->uc_mcontext.version);
- if (temp != MCONTEXT_VERSION)
- goto badframe;
- /* restore passed registers */
- err |= __get_user(regs->d0, &gregs[0]);
- err |= __get_user(regs->d1, &gregs[1]);
- err |= __get_user(regs->d2, &gregs[2]);
- err |= __get_user(regs->d3, &gregs[3]);
- err |= __get_user(regs->d4, &gregs[4]);
- err |= __get_user(regs->d5, &gregs[5]);
- err |= __get_user(sw->d6, &gregs[6]);
- err |= __get_user(sw->d7, &gregs[7]);
- err |= __get_user(regs->a0, &gregs[8]);
- err |= __get_user(regs->a1, &gregs[9]);
- err |= __get_user(regs->a2, &gregs[10]);
- err |= __get_user(sw->a3, &gregs[11]);
- err |= __get_user(sw->a4, &gregs[12]);
- err |= __get_user(sw->a5, &gregs[13]);
- err |= __get_user(sw->a6, &gregs[14]);
- err |= __get_user(usp, &gregs[15]);
- wrusp(usp);
- err |= __get_user(regs->pc, &gregs[16]);
- err |= __get_user(temp, &gregs[17]);
- regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
- regs->orig_d0 = -1; /* disable syscall checks */
- regs->format = temp >> 12;
- regs->vector = temp & 0xfff;
-
- if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
- goto badframe;
-
- *pd0 = regs->d0;
- return err;
-
-badframe:
- return 1;
-}
-
-asmlinkage int do_sigreturn(unsigned long __unused)
-{
- struct switch_stack *sw = (struct switch_stack *) &__unused;
- struct pt_regs *regs = (struct pt_regs *) (sw + 1);
- unsigned long usp = rdusp();
- struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
- sigset_t set;
- int d0;
-
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
- if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
- (_NSIG_WORDS > 1 &&
- __copy_from_user(&set.sig[1], &frame->extramask,
- sizeof(frame->extramask))))
- goto badframe;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0))
- goto badframe;
- return d0;
-
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
-
-asmlinkage int do_rt_sigreturn(unsigned long __unused)
-{
- struct switch_stack *sw = (struct switch_stack *) &__unused;
- struct pt_regs *regs = (struct pt_regs *) (sw + 1);
- unsigned long usp = rdusp();
- struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
- sigset_t set;
- int d0;
-
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
- if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
- goto badframe;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
- goto badframe;
- return d0;
-
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
-
-#ifdef CONFIG_FPU
-/*
- * Set up a signal frame.
- */
-
-static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
-{
- if (FPU_IS_EMU) {
- /* save registers */
- memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
- memcpy(sc->sc_fpregs, current->thread.fp, 24);
- return;
- }
-
- __asm__ volatile (".chip 68k/68881\n\t"
- "fsave %0\n\t"
- ".chip 68k"
- : : "m" (*sc->sc_fpstate) : "memory");
-
- if (sc->sc_fpstate[0]) {
- fpu_version = sc->sc_fpstate[0];
- __asm__ volatile (".chip 68k/68881\n\t"
- "fmovemx %%fp0-%%fp1,%0\n\t"
- "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
- ".chip 68k"
- : "=m" (*sc->sc_fpregs),
- "=m" (*sc->sc_fpcntl)
- : /* no inputs */
- : "memory");
- }
-}
-
-static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
-{
- unsigned char fpstate[FPCONTEXT_SIZE];
- int context_size = 0;
- int err = 0;
-
- if (FPU_IS_EMU) {
- /* save fpu control register */
- err |= copy_to_user(uc->uc_mcontext.fpregs.f_pcntl,
- current->thread.fpcntl, 12);
- /* save all other fpu register */
- err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
- current->thread.fp, 96);
- return err;
- }
-
- __asm__ volatile (".chip 68k/68881\n\t"
- "fsave %0\n\t"
- ".chip 68k"
- : : "m" (*fpstate) : "memory");
-
- err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
- if (fpstate[0]) {
- fpregset_t fpregs;
- context_size = fpstate[1];
- fpu_version = fpstate[0];
- __asm__ volatile (".chip 68k/68881\n\t"
- "fmovemx %%fp0-%%fp7,%0\n\t"
- "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
- ".chip 68k"
- : "=m" (*fpregs.f_fpregs),
- "=m" (*fpregs.f_fpcntl)
- : /* no inputs */
- : "memory");
- err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
- sizeof(fpregs));
- }
- if (context_size)
- err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
- context_size);
- return err;
-}
-
-#endif
-
-static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
- unsigned long mask)
-{
- sc->sc_mask = mask;
- sc->sc_usp = rdusp();
- sc->sc_d0 = regs->d0;
- sc->sc_d1 = regs->d1;
- sc->sc_a0 = regs->a0;
- sc->sc_a1 = regs->a1;
- sc->sc_a5 = ((struct switch_stack *)regs - 1)->a5;
- sc->sc_sr = regs->sr;
- sc->sc_pc = regs->pc;
- sc->sc_formatvec = regs->format << 12 | regs->vector;
-#ifdef CONFIG_FPU
- save_fpu_state(sc, regs);
-#endif
-}
-
-static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
-{
- struct switch_stack *sw = (struct switch_stack *)regs - 1;
- greg_t __user *gregs = uc->uc_mcontext.gregs;
- int err = 0;
-
- err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
- err |= __put_user(regs->d0, &gregs[0]);
- err |= __put_user(regs->d1, &gregs[1]);
- err |= __put_user(regs->d2, &gregs[2]);
- err |= __put_user(regs->d3, &gregs[3]);
- err |= __put_user(regs->d4, &gregs[4]);
- err |= __put_user(regs->d5, &gregs[5]);
- err |= __put_user(sw->d6, &gregs[6]);
- err |= __put_user(sw->d7, &gregs[7]);
- err |= __put_user(regs->a0, &gregs[8]);
- err |= __put_user(regs->a1, &gregs[9]);
- err |= __put_user(regs->a2, &gregs[10]);
- err |= __put_user(sw->a3, &gregs[11]);
- err |= __put_user(sw->a4, &gregs[12]);
- err |= __put_user(sw->a5, &gregs[13]);
- err |= __put_user(sw->a6, &gregs[14]);
- err |= __put_user(rdusp(), &gregs[15]);
- err |= __put_user(regs->pc, &gregs[16]);
- err |= __put_user(regs->sr, &gregs[17]);
-#ifdef CONFIG_FPU
- err |= rt_save_fpu_state(uc, regs);
-#endif
- return err;
-}
-
-static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
-{
- unsigned long usp;
-
- /* Default to using normal stack. */
- usp = rdusp();
-
- /* This is the X/Open sanctioned signal stack switching. */
- if (ka->sa.sa_flags & SA_ONSTACK) {
- if (!sas_ss_flags(usp))
- usp = current->sas_ss_sp + current->sas_ss_size;
- }
- return (void __user *)((usp - frame_size) & -8UL);
-}
-
-static int setup_frame (int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs *regs)
-{
- struct sigframe __user *frame;
- struct sigcontext context;
- int err = 0;
-
- frame = get_sigframe(ka, regs, sizeof(*frame));
-
- err |= __put_user((current_thread_info()->exec_domain
- && current_thread_info()->exec_domain->signal_invmap
- && sig < 32
- ? current_thread_info()->exec_domain->signal_invmap[sig]
- : sig),
- &frame->sig);
-
- err |= __put_user(regs->vector, &frame->code);
- err |= __put_user(&frame->sc, &frame->psc);
-
- if (_NSIG_WORDS > 1)
- err |= copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
-
- setup_sigcontext(&context, regs, set->sig[0]);
- err |= copy_to_user (&frame->sc, &context, sizeof(context));
-
- /* Set up to return from userspace. */
- err |= __put_user((void *) ret_from_user_signal, &frame->pretcode);
-
- if (err)
- goto give_sigsegv;
-
- /* Set up registers for signal handler */
- wrusp ((unsigned long) frame);
- regs->pc = (unsigned long) ka->sa.sa_handler;
- ((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
- regs->format = 0x4; /*set format byte to make stack appear modulo 4
- which it will be when doing the rte */
-
-adjust_stack:
- /* Prepare to skip over the extra stuff in the exception frame. */
- if (regs->stkadj) {
- struct pt_regs *tregs =
- (struct pt_regs *)((ulong)regs + regs->stkadj);
-#if defined(DEBUG)
- printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
-#endif
- /* This must be copied with decreasing addresses to
- handle overlaps. */
- tregs->vector = 0;
- tregs->format = 0;
- tregs->pc = regs->pc;
- tregs->sr = regs->sr;
- }
- return err;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- goto adjust_stack;
-}
-
-static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
-{
- struct rt_sigframe __user *frame;
- int err = 0;
-
- frame = get_sigframe(ka, regs, sizeof(*frame));
-
- err |= __put_user((current_thread_info()->exec_domain
- && current_thread_info()->exec_domain->signal_invmap
- && sig < 32
- ? current_thread_info()->exec_domain->signal_invmap[sig]
- : sig),
- &frame->sig);
- err |= __put_user(&frame->info, &frame->pinfo);
- err |= __put_user(&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user(&frame->info, info);
-
- /* Create the ucontext. */
- err |= __put_user(0, &frame->uc.uc_flags);
- err |= __put_user(NULL, &frame->uc.uc_link);
- err |= __put_user((void __user *)current->sas_ss_sp,
- &frame->uc.uc_stack.ss_sp);
- err |= __put_user(sas_ss_flags(rdusp()),
- &frame->uc.uc_stack.ss_flags);
- err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
- err |= rt_setup_ucontext(&frame->uc, regs);
- err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
-
- /* Set up to return from userspace. */
- err |= __put_user((void *) ret_from_user_rt_signal, &frame->pretcode);
-
- if (err)
- goto give_sigsegv;
-
- /* Set up registers for signal handler */
- wrusp ((unsigned long) frame);
- regs->pc = (unsigned long) ka->sa.sa_handler;
- ((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
- regs->format = 0x4; /*set format byte to make stack appear modulo 4
- which it will be when doing the rte */
-
-adjust_stack:
- /* Prepare to skip over the extra stuff in the exception frame. */
- if (regs->stkadj) {
- struct pt_regs *tregs =
- (struct pt_regs *)((ulong)regs + regs->stkadj);
-#if defined(DEBUG)
- printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
-#endif
- /* This must be copied with decreasing addresses to
- handle overlaps. */
- tregs->vector = 0;
- tregs->format = 0;
- tregs->pc = regs->pc;
- tregs->sr = regs->sr;
- }
- return err;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- goto adjust_stack;
-}
-
-static inline void
-handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
-{
- switch (regs->d0) {
- case -ERESTARTNOHAND:
- if (!has_handler)
- goto do_restart;
- regs->d0 = -EINTR;
- break;
-
- case -ERESTART_RESTARTBLOCK:
- if (!has_handler) {
- regs->d0 = __NR_restart_syscall;
- regs->pc -= 2;
- break;
- }
- regs->d0 = -EINTR;
- break;
-
- case -ERESTARTSYS:
- if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
- regs->d0 = -EINTR;
- break;
- }
- /* fallthrough */
- case -ERESTARTNOINTR:
- do_restart:
- regs->d0 = regs->orig_d0;
- regs->pc -= 2;
- break;
- }
-}
-
-/*
- * OK, we're invoking a handler
- */
-static void
-handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *oldset, struct pt_regs *regs)
-{
- int err;
- /* are we from a system call? */
- if (regs->orig_d0 >= 0)
- /* If so, check system call restarting.. */
- handle_restart(regs, ka, 1);
-
- /* set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- err = setup_rt_frame(sig, ka, info, oldset, regs);
- else
- err = setup_frame(sig, ka, oldset, regs);
-
- if (err)
- return;
-
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- clear_thread_flag(TIF_RESTORE_SIGMASK);
-}
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- */
-asmlinkage void do_signal(struct pt_regs *regs)
-{
- struct k_sigaction ka;
- siginfo_t info;
- int signr;
- sigset_t *oldset;
-
- /*
- * We want the common case to go fast, which
- * is why we may in certain cases get here from
- * kernel mode. Just return without doing anything
- * if so.
- */
- if (!user_mode(regs))
- return;
-
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
- oldset = &current->saved_sigmask;
- else
- oldset = &current->blocked;
-
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
- /* Whee! Actually deliver the signal. */
- handle_signal(signr, &ka, &info, oldset, regs);
- return;
- }
-
- /* Did we come from a system call? */
- if (regs->orig_d0 >= 0) {
- /* Restart the system call - no handlers present */
- handle_restart(regs, NULL, 0);
- }
-
- /* If there's no signal to deliver, we just restore the saved mask. */
- if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
- clear_thread_flag(TIF_RESTORE_SIGMASK);
- sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
- }
-}
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index 6b020a8461e7..aeebbb7b30f0 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -72,7 +72,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
{
struct mm_struct *mm = current->mm;
struct vm_area_struct * vma;
- int write, fault;
+ int fault;
+ unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
#ifdef DEBUG
printk ("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
@@ -87,6 +88,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
if (in_atomic() || !mm)
goto no_context;
+retry:
down_read(&mm->mmap_sem);
vma = find_vma(mm, address);
@@ -117,14 +119,13 @@ good_area:
#ifdef DEBUG
printk("do_page_fault: good_area\n");
#endif
- write = 0;
switch (error_code & 3) {
default: /* 3: write, present */
/* fall through */
case 2: /* write, not present */
if (!(vma->vm_flags & VM_WRITE))
goto acc_err;
- write++;
+ flags |= FAULT_FLAG_WRITE;
break;
case 1: /* read, present */
goto acc_err;
@@ -139,10 +140,14 @@ good_area:
* the fault.
*/
- fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
+ fault = handle_mm_fault(mm, vma, address, flags);
#ifdef DEBUG
printk("handle_mm_fault returns %d\n",fault);
#endif
+
+ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+ return 0;
+
if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM)
goto out_of_memory;
@@ -150,10 +155,31 @@ good_area:
goto bus_err;
BUG();
}
- if (fault & VM_FAULT_MAJOR)
- current->maj_flt++;
- else
- current->min_flt++;
+
+ /*
+ * Major/minor page fault accounting is only done on the
+ * initial attempt. If we go through a retry, it is extremely
+ * likely that the page will be found in page cache at that point.
+ */
+ if (flags & FAULT_FLAG_ALLOW_RETRY) {
+ if (fault & VM_FAULT_MAJOR)
+ current->maj_flt++;
+ else
+ current->min_flt++;
+ if (fault & VM_FAULT_RETRY) {
+ /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
+ * of starvation. */
+ flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+ /*
+ * No need to up_read(&mm->mmap_sem) as we would
+ * have already released it in __lock_page_or_retry
+ * in mm/filemap.c.
+ */
+
+ goto retry;
+ }
+ }
up_read(&mm->mmap_sem);
return 0;
diff --git a/arch/m68k/platform/5206/Makefile b/arch/m68k/platform/5206/Makefile
deleted file mode 100644
index b5db05625cfa..000000000000
--- a/arch/m68k/platform/5206/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this, which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
-
diff --git a/arch/m68k/platform/5206/gpio.c b/arch/m68k/platform/5206/gpio.c
deleted file mode 100644
index b9ab4a120f28..000000000000
--- a/arch/m68k/platform/5206/gpio.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
- {
- .gpio_chip = {
- .label = "PP",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFSIM_PADDR,
- .podr = (void __iomem *) MCFSIM_PADAT,
- .ppdr = (void __iomem *) MCFSIM_PADAT,
- },
-};
-
-static int __init mcf_gpio_init(void)
-{
- unsigned i = 0;
- while (i < ARRAY_SIZE(mcf_gpio_chips))
- (void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
- return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff --git a/arch/m68k/platform/520x/Makefile b/arch/m68k/platform/520x/Makefile
deleted file mode 100644
index ad3f4e5a57ce..000000000000
--- a/arch/m68k/platform/520x/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Makefile for the M5208 specific file.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this, which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
diff --git a/arch/m68k/platform/520x/gpio.c b/arch/m68k/platform/520x/gpio.c
deleted file mode 100644
index 9bcc3e4b60c5..000000000000
--- a/arch/m68k/platform/520x/gpio.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
- {
- .gpio_chip = {
- .label = "PIRQ",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFEPORT_EPDDR,
- .podr = (void __iomem *) MCFEPORT_EPDR,
- .ppdr = (void __iomem *) MCFEPORT_EPPDR,
- },
- {
- .gpio_chip = {
- .label = "CS",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 9,
- .ngpio = 3,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_CS,
- .podr = (void __iomem *) MCFGPIO_PODR_CS,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_CS,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_CS,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_CS,
- },
- {
- .gpio_chip = {
- .label = "FECI2C",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 16,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_FECI2C,
- .podr = (void __iomem *) MCFGPIO_PODR_FECI2C,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_FECI2C,
- },
- {
- .gpio_chip = {
- .label = "QSPI",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 24,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_QSPI,
- .podr = (void __iomem *) MCFGPIO_PODR_QSPI,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_QSPI,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_QSPI,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_QSPI,
- },
- {
- .gpio_chip = {
- .label = "TIMER",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 32,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_TIMER,
- .podr = (void __iomem *) MCFGPIO_PODR_TIMER,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_TIMER,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_TIMER,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_TIMER,
- },
- {
- .gpio_chip = {
- .label = "UART",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 40,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_UART,
- .podr = (void __iomem *) MCFGPIO_PODR_UART,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_UART,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_UART,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_UART,
- },
- {
- .gpio_chip = {
- .label = "FECH",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 48,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_FECH,
- .podr = (void __iomem *) MCFGPIO_PODR_FECH,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_FECH,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_FECH,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_FECH,
- },
- {
- .gpio_chip = {
- .label = "FECL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 56,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_FECL,
- .podr = (void __iomem *) MCFGPIO_PODR_FECL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_FECL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_FECL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_FECL,
- },
-};
-
-static int __init mcf_gpio_init(void)
-{
- unsigned i = 0;
- while (i < ARRAY_SIZE(mcf_gpio_chips))
- (void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
- return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff --git a/arch/m68k/platform/523x/Makefile b/arch/m68k/platform/523x/Makefile
deleted file mode 100644
index c04b8f71c88c..000000000000
--- a/arch/m68k/platform/523x/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this, which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
diff --git a/arch/m68k/platform/523x/gpio.c b/arch/m68k/platform/523x/gpio.c
deleted file mode 100644
index 327ebf142c8e..000000000000
--- a/arch/m68k/platform/523x/gpio.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
- {
- .gpio_chip = {
- .label = "PIRQ",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .base = 1,
- .ngpio = 7,
- },
- .pddr = (void __iomem *) MCFEPORT_EPDDR,
- .podr = (void __iomem *) MCFEPORT_EPDR,
- .ppdr = (void __iomem *) MCFEPORT_EPPDR,
- },
- {
- .gpio_chip = {
- .label = "ADDR",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 13,
- .ngpio = 3,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_ADDR,
- .podr = (void __iomem *) MCFGPIO_PODR_ADDR,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_ADDR,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_ADDR,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_ADDR,
- },
- {
- .gpio_chip = {
- .label = "DATAH",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 16,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_DATAH,
- .podr = (void __iomem *) MCFGPIO_PODR_DATAH,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_DATAH,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_DATAH,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_DATAH,
- },
- {
- .gpio_chip = {
- .label = "DATAL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 24,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_DATAL,
- .podr = (void __iomem *) MCFGPIO_PODR_DATAL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_DATAL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_DATAL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_DATAL,
- },
- {
- .gpio_chip = {
- .label = "BUSCTL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 32,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_BUSCTL,
- .podr = (void __iomem *) MCFGPIO_PODR_BUSCTL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
- },
- {
- .gpio_chip = {
- .label = "BS",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 40,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_BS,
- .podr = (void __iomem *) MCFGPIO_PODR_BS,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_BS,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_BS,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_BS,
- },
- {
- .gpio_chip = {
- .label = "CS",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 49,
- .ngpio = 7,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_CS,
- .podr = (void __iomem *) MCFGPIO_PODR_CS,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_CS,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_CS,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_CS,
- },
- {
- .gpio_chip = {
- .label = "SDRAM",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 56,
- .ngpio = 6,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_SDRAM,
- .podr = (void __iomem *) MCFGPIO_PODR_SDRAM,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_SDRAM,
- },
- {
- .gpio_chip = {
- .label = "FECI2C",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 64,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_FECI2C,
- .podr = (void __iomem *) MCFGPIO_PODR_FECI2C,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_FECI2C,
- },
- {
- .gpio_chip = {
- .label = "UARTH",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 72,
- .ngpio = 2,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_UARTH,
- .podr = (void __iomem *) MCFGPIO_PODR_UARTH,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_UARTH,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_UARTH,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_UARTH,
- },
- {
- .gpio_chip = {
- .label = "UARTL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 80,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_UARTL,
- .podr = (void __iomem *) MCFGPIO_PODR_UARTL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_UARTL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_UARTL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_UARTL,
- },
- {
- .gpio_chip = {
- .label = "QSPI",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 88,
- .ngpio = 5,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_QSPI,
- .podr = (void __iomem *) MCFGPIO_PODR_QSPI,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_QSPI,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_QSPI,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_QSPI,
- },
- {
- .gpio_chip = {
- .label = "TIMER",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 96,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_TIMER,
- .podr = (void __iomem *) MCFGPIO_PODR_TIMER,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_TIMER,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_TIMER,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_TIMER,
- },
- {
- .gpio_chip = {
- .label = "ETPU",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 104,
- .ngpio = 3,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_ETPU,
- .podr = (void __iomem *) MCFGPIO_PODR_ETPU,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_ETPU,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_ETPU,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_ETPU,
- },
-};
-
-static int __init mcf_gpio_init(void)
-{
- unsigned i = 0;
- while (i < ARRAY_SIZE(mcf_gpio_chips))
- (void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
- return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff --git a/arch/m68k/platform/5249/Makefile b/arch/m68k/platform/5249/Makefile
deleted file mode 100644
index 4bed30fd0073..000000000000
--- a/arch/m68k/platform/5249/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this, which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o intc2.o
-
diff --git a/arch/m68k/platform/5249/gpio.c b/arch/m68k/platform/5249/gpio.c
deleted file mode 100644
index 2b56c6ef65bf..000000000000
--- a/arch/m68k/platform/5249/gpio.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
- {
- .gpio_chip = {
- .label = "GPIO0",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .ngpio = 32,
- },
- .pddr = (void __iomem *) MCFSIM2_GPIOENABLE,
- .podr = (void __iomem *) MCFSIM2_GPIOWRITE,
- .ppdr = (void __iomem *) MCFSIM2_GPIOREAD,
- },
- {
- .gpio_chip = {
- .label = "GPIO1",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .base = 32,
- .ngpio = 32,
- },
- .pddr = (void __iomem *) MCFSIM2_GPIO1ENABLE,
- .podr = (void __iomem *) MCFSIM2_GPIO1WRITE,
- .ppdr = (void __iomem *) MCFSIM2_GPIO1READ,
- },
-};
-
-static int __init mcf_gpio_init(void)
-{
- unsigned i = 0;
- while (i < ARRAY_SIZE(mcf_gpio_chips))
- (void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
- return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff --git a/arch/m68k/platform/5272/Makefile b/arch/m68k/platform/5272/Makefile
deleted file mode 100644
index 34110fc14301..000000000000
--- a/arch/m68k/platform/5272/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this, which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o intc.o
-
diff --git a/arch/m68k/platform/5272/gpio.c b/arch/m68k/platform/5272/gpio.c
deleted file mode 100644
index 57ac10a5d7f7..000000000000
--- a/arch/m68k/platform/5272/gpio.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
- {
- .gpio_chip = {
- .label = "PA",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .ngpio = 16,
- },
- .pddr = (void __iomem *) MCFSIM_PADDR,
- .podr = (void __iomem *) MCFSIM_PADAT,
- .ppdr = (void __iomem *) MCFSIM_PADAT,
- },
- {
- .gpio_chip = {
- .label = "PB",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .base = 16,
- .ngpio = 16,
- },
- .pddr = (void __iomem *) MCFSIM_PBDDR,
- .podr = (void __iomem *) MCFSIM_PBDAT,
- .ppdr = (void __iomem *) MCFSIM_PBDAT,
- },
- {
- .gpio_chip = {
- .label = "PC",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .base = 32,
- .ngpio = 16,
- },
- .pddr = (void __iomem *) MCFSIM_PCDDR,
- .podr = (void __iomem *) MCFSIM_PCDAT,
- .ppdr = (void __iomem *) MCFSIM_PCDAT,
- },
-};
-
-static int __init mcf_gpio_init(void)
-{
- unsigned i = 0;
- while (i < ARRAY_SIZE(mcf_gpio_chips))
- (void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
- return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff --git a/arch/m68k/platform/527x/Makefile b/arch/m68k/platform/527x/Makefile
deleted file mode 100644
index 6ac4b57370ea..000000000000
--- a/arch/m68k/platform/527x/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this, which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
-
diff --git a/arch/m68k/platform/527x/gpio.c b/arch/m68k/platform/527x/gpio.c
deleted file mode 100644
index 205da0aa0f2d..000000000000
--- a/arch/m68k/platform/527x/gpio.c
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
-#if defined(CONFIG_M5271)
- {
- .gpio_chip = {
- .label = "PIRQ",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .base = 1,
- .ngpio = 7,
- },
- .pddr = (void __iomem *) MCFEPORT_EPDDR,
- .podr = (void __iomem *) MCFEPORT_EPDR,
- .ppdr = (void __iomem *) MCFEPORT_EPPDR,
- },
- {
- .gpio_chip = {
- .label = "ADDR",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 13,
- .ngpio = 3,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_ADDR,
- .podr = (void __iomem *) MCFGPIO_PODR_ADDR,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_ADDR,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_ADDR,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_ADDR,
- },
- {
- .gpio_chip = {
- .label = "DATAH",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 16,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_DATAH,
- .podr = (void __iomem *) MCFGPIO_PODR_DATAH,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_DATAH,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_DATAH,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_DATAH,
- },
- {
- .gpio_chip = {
- .label = "DATAL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 24,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_DATAL,
- .podr = (void __iomem *) MCFGPIO_PODR_DATAL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_DATAL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_DATAL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_DATAL,
- },
- {
- .gpio_chip = {
- .label = "BUSCTL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 32,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_BUSCTL,
- .podr = (void __iomem *) MCFGPIO_PODR_BUSCTL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
- },
- {
- .gpio_chip = {
- .label = "BS",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 40,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_BS,
- .podr = (void __iomem *) MCFGPIO_PODR_BS,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_BS,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_BS,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_BS,
- },
- {
- .gpio_chip = {
- .label = "CS",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 49,
- .ngpio = 7,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_CS,
- .podr = (void __iomem *) MCFGPIO_PODR_CS,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_CS,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_CS,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_CS,
- },
- {
- .gpio_chip = {
- .label = "SDRAM",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 56,
- .ngpio = 6,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_SDRAM,
- .podr = (void __iomem *) MCFGPIO_PODR_SDRAM,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_SDRAM,
- },
- {
- .gpio_chip = {
- .label = "FECI2C",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 64,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_FECI2C,
- .podr = (void __iomem *) MCFGPIO_PODR_FECI2C,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_FECI2C,
- },
- {
- .gpio_chip = {
- .label = "UARTH",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 72,
- .ngpio = 2,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_UARTH,
- .podr = (void __iomem *) MCFGPIO_PODR_UARTH,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_UARTH,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_UARTH,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_UARTH,
- },
- {
- .gpio_chip = {
- .label = "UARTL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 80,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_UARTL,
- .podr = (void __iomem *) MCFGPIO_PODR_UARTL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_UARTL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_UARTL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_UARTL,
- },
- {
- .gpio_chip = {
- .label = "QSPI",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 88,
- .ngpio = 5,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_QSPI,
- .podr = (void __iomem *) MCFGPIO_PODR_QSPI,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_QSPI,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_QSPI,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_QSPI,
- },
- {
- .gpio_chip = {
- .label = "TIMER",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 96,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_TIMER,
- .podr = (void __iomem *) MCFGPIO_PODR_TIMER,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_TIMER,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_TIMER,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_TIMER,
- },
-#elif defined(CONFIG_M5275)
- {
- .gpio_chip = {
- .label = "PIRQ",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .base = 1,
- .ngpio = 7,
- },
- .pddr = (void __iomem *) MCFEPORT_EPDDR,
- .podr = (void __iomem *) MCFEPORT_EPDR,
- .ppdr = (void __iomem *) MCFEPORT_EPPDR,
- },
- {
- .gpio_chip = {
- .label = "BUSCTL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 8,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_BUSCTL,
- .podr = (void __iomem *) MCFGPIO_PODR_BUSCTL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
- },
- {
- .gpio_chip = {
- .label = "ADDR",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 21,
- .ngpio = 3,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_ADDR,
- .podr = (void __iomem *) MCFGPIO_PODR_ADDR,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_ADDR,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_ADDR,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_ADDR,
- },
- {
- .gpio_chip = {
- .label = "CS",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 25,
- .ngpio = 7,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_CS,
- .podr = (void __iomem *) MCFGPIO_PODR_CS,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_CS,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_CS,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_CS,
- },
- {
- .gpio_chip = {
- .label = "FEC0H",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 32,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_FEC0H,
- .podr = (void __iomem *) MCFGPIO_PODR_FEC0H,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_FEC0H,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_FEC0H,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_FEC0H,
- },
- {
- .gpio_chip = {
- .label = "FEC0L",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 40,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_FEC0L,
- .podr = (void __iomem *) MCFGPIO_PODR_FEC0L,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_FEC0L,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_FEC0L,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_FEC0L,
- },
- {
- .gpio_chip = {
- .label = "FECI2C",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 48,
- .ngpio = 6,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_FECI2C,
- .podr = (void __iomem *) MCFGPIO_PODR_FECI2C,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_FECI2C,
- },
- {
- .gpio_chip = {
- .label = "QSPI",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 56,
- .ngpio = 7,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_QSPI,
- .podr = (void __iomem *) MCFGPIO_PODR_QSPI,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_QSPI,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_QSPI,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_QSPI,
- },
- {
- .gpio_chip = {
- .label = "SDRAM",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 64,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_SDRAM,
- .podr = (void __iomem *) MCFGPIO_PODR_SDRAM,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_SDRAM,
- },
- {
- .gpio_chip = {
- .label = "TIMERH",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 72,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_TIMERH,
- .podr = (void __iomem *) MCFGPIO_PODR_TIMERH,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_TIMERH,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_TIMERH,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_TIMERH,
- },
- {
- .gpio_chip = {
- .label = "TIMERL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 80,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_TIMERL,
- .podr = (void __iomem *) MCFGPIO_PODR_TIMERL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_TIMERL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_TIMERL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_TIMERL,
- },
- {
- .gpio_chip = {
- .label = "UARTL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 88,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_UARTL,
- .podr = (void __iomem *) MCFGPIO_PODR_UARTL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_UARTL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_UARTL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_UARTL,
- },
- {
- .gpio_chip = {
- .label = "FEC1H",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 96,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_FEC1H,
- .podr = (void __iomem *) MCFGPIO_PODR_FEC1H,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_FEC1H,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_FEC1H,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_FEC1H,
- },
- {
- .gpio_chip = {
- .label = "FEC1L",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 104,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_FEC1L,
- .podr = (void __iomem *) MCFGPIO_PODR_FEC1L,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_FEC1L,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_FEC1L,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_FEC1L,
- },
- {
- .gpio_chip = {
- .label = "BS",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 114,
- .ngpio = 2,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_BS,
- .podr = (void __iomem *) MCFGPIO_PODR_BS,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_BS,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_BS,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_BS,
- },
- {
- .gpio_chip = {
- .label = "IRQ",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 121,
- .ngpio = 7,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_IRQ,
- .podr = (void __iomem *) MCFGPIO_PODR_IRQ,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_IRQ,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_IRQ,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_IRQ,
- },
- {
- .gpio_chip = {
- .label = "USBH",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 128,
- .ngpio = 1,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_USBH,
- .podr = (void __iomem *) MCFGPIO_PODR_USBH,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_USBH,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_USBH,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_USBH,
- },
- {
- .gpio_chip = {
- .label = "USBL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 136,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_USBL,
- .podr = (void __iomem *) MCFGPIO_PODR_USBL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_USBL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_USBL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_USBL,
- },
- {
- .gpio_chip = {
- .label = "UARTH",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 144,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_UARTH,
- .podr = (void __iomem *) MCFGPIO_PODR_UARTH,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_UARTH,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_UARTH,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_UARTH,
- },
-#endif
-};
-
-static int __init mcf_gpio_init(void)
-{
- unsigned i = 0;
- while (i < ARRAY_SIZE(mcf_gpio_chips))
- (void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
- return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff --git a/arch/m68k/platform/528x/Makefile b/arch/m68k/platform/528x/Makefile
deleted file mode 100644
index 6ac4b57370ea..000000000000
--- a/arch/m68k/platform/528x/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this, which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
-
diff --git a/arch/m68k/platform/528x/gpio.c b/arch/m68k/platform/528x/gpio.c
deleted file mode 100644
index 526db665d87e..000000000000
--- a/arch/m68k/platform/528x/gpio.c
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
- {
- .gpio_chip = {
- .label = "NQ",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .base = 1,
- .ngpio = 7,
- },
- .pddr = (void __iomem *)MCFEPORT_EPDDR,
- .podr = (void __iomem *)MCFEPORT_EPDR,
- .ppdr = (void __iomem *)MCFEPORT_EPPDR,
- },
- {
- .gpio_chip = {
- .label = "TA",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 8,
- .ngpio = 4,
- },
- .pddr = (void __iomem *)MCFGPTA_GPTDDR,
- .podr = (void __iomem *)MCFGPTA_GPTPORT,
- .ppdr = (void __iomem *)MCFGPTB_GPTPORT,
- },
- {
- .gpio_chip = {
- .label = "TB",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 16,
- .ngpio = 4,
- },
- .pddr = (void __iomem *)MCFGPTB_GPTDDR,
- .podr = (void __iomem *)MCFGPTB_GPTPORT,
- .ppdr = (void __iomem *)MCFGPTB_GPTPORT,
- },
- {
- .gpio_chip = {
- .label = "QA",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 24,
- .ngpio = 4,
- },
- .pddr = (void __iomem *)MCFQADC_DDRQA,
- .podr = (void __iomem *)MCFQADC_PORTQA,
- .ppdr = (void __iomem *)MCFQADC_PORTQA,
- },
- {
- .gpio_chip = {
- .label = "QB",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 32,
- .ngpio = 4,
- },
- .pddr = (void __iomem *)MCFQADC_DDRQB,
- .podr = (void __iomem *)MCFQADC_PORTQB,
- .ppdr = (void __iomem *)MCFQADC_PORTQB,
- },
- {
- .gpio_chip = {
- .label = "A",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 40,
- .ngpio = 8,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRA,
- .podr = (void __iomem *)MCFGPIO_PORTA,
- .ppdr = (void __iomem *)MCFGPIO_PORTAP,
- .setr = (void __iomem *)MCFGPIO_SETA,
- .clrr = (void __iomem *)MCFGPIO_CLRA,
- },
- {
- .gpio_chip = {
- .label = "B",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 48,
- .ngpio = 8,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRB,
- .podr = (void __iomem *)MCFGPIO_PORTB,
- .ppdr = (void __iomem *)MCFGPIO_PORTBP,
- .setr = (void __iomem *)MCFGPIO_SETB,
- .clrr = (void __iomem *)MCFGPIO_CLRB,
- },
- {
- .gpio_chip = {
- .label = "C",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 56,
- .ngpio = 8,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRC,
- .podr = (void __iomem *)MCFGPIO_PORTC,
- .ppdr = (void __iomem *)MCFGPIO_PORTCP,
- .setr = (void __iomem *)MCFGPIO_SETC,
- .clrr = (void __iomem *)MCFGPIO_CLRC,
- },
- {
- .gpio_chip = {
- .label = "D",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 64,
- .ngpio = 8,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRD,
- .podr = (void __iomem *)MCFGPIO_PORTD,
- .ppdr = (void __iomem *)MCFGPIO_PORTDP,
- .setr = (void __iomem *)MCFGPIO_SETD,
- .clrr = (void __iomem *)MCFGPIO_CLRD,
- },
- {
- .gpio_chip = {
- .label = "E",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 72,
- .ngpio = 8,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRE,
- .podr = (void __iomem *)MCFGPIO_PORTE,
- .ppdr = (void __iomem *)MCFGPIO_PORTEP,
- .setr = (void __iomem *)MCFGPIO_SETE,
- .clrr = (void __iomem *)MCFGPIO_CLRE,
- },
- {
- .gpio_chip = {
- .label = "F",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 80,
- .ngpio = 8,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRF,
- .podr = (void __iomem *)MCFGPIO_PORTF,
- .ppdr = (void __iomem *)MCFGPIO_PORTFP,
- .setr = (void __iomem *)MCFGPIO_SETF,
- .clrr = (void __iomem *)MCFGPIO_CLRF,
- },
- {
- .gpio_chip = {
- .label = "G",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 88,
- .ngpio = 8,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRG,
- .podr = (void __iomem *)MCFGPIO_PORTG,
- .ppdr = (void __iomem *)MCFGPIO_PORTGP,
- .setr = (void __iomem *)MCFGPIO_SETG,
- .clrr = (void __iomem *)MCFGPIO_CLRG,
- },
- {
- .gpio_chip = {
- .label = "H",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 96,
- .ngpio = 8,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRH,
- .podr = (void __iomem *)MCFGPIO_PORTH,
- .ppdr = (void __iomem *)MCFGPIO_PORTHP,
- .setr = (void __iomem *)MCFGPIO_SETH,
- .clrr = (void __iomem *)MCFGPIO_CLRH,
- },
- {
- .gpio_chip = {
- .label = "J",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 104,
- .ngpio = 8,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRJ,
- .podr = (void __iomem *)MCFGPIO_PORTJ,
- .ppdr = (void __iomem *)MCFGPIO_PORTJP,
- .setr = (void __iomem *)MCFGPIO_SETJ,
- .clrr = (void __iomem *)MCFGPIO_CLRJ,
- },
- {
- .gpio_chip = {
- .label = "DD",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 112,
- .ngpio = 8,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRDD,
- .podr = (void __iomem *)MCFGPIO_PORTDD,
- .ppdr = (void __iomem *)MCFGPIO_PORTDDP,
- .setr = (void __iomem *)MCFGPIO_SETDD,
- .clrr = (void __iomem *)MCFGPIO_CLRDD,
- },
- {
- .gpio_chip = {
- .label = "EH",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 120,
- .ngpio = 8,
- },
- .pddr = (void __iomem *)MCFGPIO_DDREH,
- .podr = (void __iomem *)MCFGPIO_PORTEH,
- .ppdr = (void __iomem *)MCFGPIO_PORTEHP,
- .setr = (void __iomem *)MCFGPIO_SETEH,
- .clrr = (void __iomem *)MCFGPIO_CLREH,
- },
- {
- .gpio_chip = {
- .label = "EL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 128,
- .ngpio = 8,
- },
- .pddr = (void __iomem *)MCFGPIO_DDREL,
- .podr = (void __iomem *)MCFGPIO_PORTEL,
- .ppdr = (void __iomem *)MCFGPIO_PORTELP,
- .setr = (void __iomem *)MCFGPIO_SETEL,
- .clrr = (void __iomem *)MCFGPIO_CLREL,
- },
- {
- .gpio_chip = {
- .label = "AS",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 136,
- .ngpio = 6,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRAS,
- .podr = (void __iomem *)MCFGPIO_PORTAS,
- .ppdr = (void __iomem *)MCFGPIO_PORTASP,
- .setr = (void __iomem *)MCFGPIO_SETAS,
- .clrr = (void __iomem *)MCFGPIO_CLRAS,
- },
- {
- .gpio_chip = {
- .label = "QS",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 144,
- .ngpio = 7,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRQS,
- .podr = (void __iomem *)MCFGPIO_PORTQS,
- .ppdr = (void __iomem *)MCFGPIO_PORTQSP,
- .setr = (void __iomem *)MCFGPIO_SETQS,
- .clrr = (void __iomem *)MCFGPIO_CLRQS,
- },
- {
- .gpio_chip = {
- .label = "SD",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 152,
- .ngpio = 6,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRSD,
- .podr = (void __iomem *)MCFGPIO_PORTSD,
- .ppdr = (void __iomem *)MCFGPIO_PORTSDP,
- .setr = (void __iomem *)MCFGPIO_SETSD,
- .clrr = (void __iomem *)MCFGPIO_CLRSD,
- },
- {
- .gpio_chip = {
- .label = "TC",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 160,
- .ngpio = 4,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRTC,
- .podr = (void __iomem *)MCFGPIO_PORTTC,
- .ppdr = (void __iomem *)MCFGPIO_PORTTCP,
- .setr = (void __iomem *)MCFGPIO_SETTC,
- .clrr = (void __iomem *)MCFGPIO_CLRTC,
- },
- {
- .gpio_chip = {
- .label = "TD",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 168,
- .ngpio = 4,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRTD,
- .podr = (void __iomem *)MCFGPIO_PORTTD,
- .ppdr = (void __iomem *)MCFGPIO_PORTTDP,
- .setr = (void __iomem *)MCFGPIO_SETTD,
- .clrr = (void __iomem *)MCFGPIO_CLRTD,
- },
- {
- .gpio_chip = {
- .label = "UA",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 176,
- .ngpio = 4,
- },
- .pddr = (void __iomem *)MCFGPIO_DDRUA,
- .podr = (void __iomem *)MCFGPIO_PORTUA,
- .ppdr = (void __iomem *)MCFGPIO_PORTUAP,
- .setr = (void __iomem *)MCFGPIO_SETUA,
- .clrr = (void __iomem *)MCFGPIO_CLRUA,
- },
-};
-
-static int __init mcf_gpio_init(void)
-{
- unsigned i = 0;
- while (i < ARRAY_SIZE(mcf_gpio_chips))
- (void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
- return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff --git a/arch/m68k/platform/5307/Makefile b/arch/m68k/platform/5307/Makefile
deleted file mode 100644
index d4293b791f2e..000000000000
--- a/arch/m68k/platform/5307/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Makefile for the m68knommu kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this, which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y += config.o gpio.o
-obj-$(CONFIG_NETtel) += nettel.o
-obj-$(CONFIG_CLEOPATRA) += nettel.o
-
diff --git a/arch/m68k/platform/5307/gpio.c b/arch/m68k/platform/5307/gpio.c
deleted file mode 100644
index 5850612b4a38..000000000000
--- a/arch/m68k/platform/5307/gpio.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
- {
- .gpio_chip = {
- .label = "PP",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .ngpio = 16,
- },
- .pddr = (void __iomem *) MCFSIM_PADDR,
- .podr = (void __iomem *) MCFSIM_PADAT,
- .ppdr = (void __iomem *) MCFSIM_PADAT,
- },
-};
-
-static int __init mcf_gpio_init(void)
-{
- unsigned i = 0;
- while (i < ARRAY_SIZE(mcf_gpio_chips))
- (void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
- return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff --git a/arch/m68k/platform/532x/Makefile b/arch/m68k/platform/532x/Makefile
deleted file mode 100644
index ce01669399c6..000000000000
--- a/arch/m68k/platform/532x/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this, which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-#obj-y := config.o usb-mcf532x.o spi-mcf532x.o
-obj-y := config.o gpio.o
diff --git a/arch/m68k/platform/532x/gpio.c b/arch/m68k/platform/532x/gpio.c
deleted file mode 100644
index 212a85deac90..000000000000
--- a/arch/m68k/platform/532x/gpio.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
- {
- .gpio_chip = {
- .label = "PIRQ",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFEPORT_EPDDR,
- .podr = (void __iomem *) MCFEPORT_EPDR,
- .ppdr = (void __iomem *) MCFEPORT_EPPDR,
- },
- {
- .gpio_chip = {
- .label = "FECH",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 8,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_FECH,
- .podr = (void __iomem *) MCFGPIO_PODR_FECH,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_FECH,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_FECH,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_FECH,
- },
- {
- .gpio_chip = {
- .label = "FECL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 16,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_FECL,
- .podr = (void __iomem *) MCFGPIO_PODR_FECL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_FECL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_FECL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_FECL,
- },
- {
- .gpio_chip = {
- .label = "SSI",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 24,
- .ngpio = 5,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_SSI,
- .podr = (void __iomem *) MCFGPIO_PODR_SSI,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_SSI,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_SSI,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_SSI,
- },
- {
- .gpio_chip = {
- .label = "BUSCTL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 32,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_BUSCTL,
- .podr = (void __iomem *) MCFGPIO_PODR_BUSCTL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
- },
- {
- .gpio_chip = {
- .label = "BE",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 40,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_BE,
- .podr = (void __iomem *) MCFGPIO_PODR_BE,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_BE,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_BE,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_BE,
- },
- {
- .gpio_chip = {
- .label = "CS",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 49,
- .ngpio = 5,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_CS,
- .podr = (void __iomem *) MCFGPIO_PODR_CS,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_CS,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_CS,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_CS,
- },
- {
- .gpio_chip = {
- .label = "PWM",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 58,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_PWM,
- .podr = (void __iomem *) MCFGPIO_PODR_PWM,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_PWM,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_PWM,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_PWM,
- },
- {
- .gpio_chip = {
- .label = "FECI2C",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 64,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_FECI2C,
- .podr = (void __iomem *) MCFGPIO_PODR_FECI2C,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_FECI2C,
- },
- {
- .gpio_chip = {
- .label = "UART",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 72,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_UART,
- .podr = (void __iomem *) MCFGPIO_PODR_UART,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_UART,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_UART,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_UART,
- },
- {
- .gpio_chip = {
- .label = "QSPI",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 80,
- .ngpio = 6,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_QSPI,
- .podr = (void __iomem *) MCFGPIO_PODR_QSPI,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_QSPI,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_QSPI,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_QSPI,
- },
- {
- .gpio_chip = {
- .label = "TIMER",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 88,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_TIMER,
- .podr = (void __iomem *) MCFGPIO_PODR_TIMER,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_TIMER,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_TIMER,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_TIMER,
- },
- {
- .gpio_chip = {
- .label = "LCDDATAH",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 96,
- .ngpio = 2,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_LCDDATAH,
- .podr = (void __iomem *) MCFGPIO_PODR_LCDDATAH,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_LCDDATAH,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_LCDDATAH,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_LCDDATAH,
- },
- {
- .gpio_chip = {
- .label = "LCDDATAM",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 104,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_LCDDATAM,
- .podr = (void __iomem *) MCFGPIO_PODR_LCDDATAM,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_LCDDATAM,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_LCDDATAM,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_LCDDATAM,
- },
- {
- .gpio_chip = {
- .label = "LCDDATAL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 112,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_LCDDATAL,
- .podr = (void __iomem *) MCFGPIO_PODR_LCDDATAL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_LCDDATAL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_LCDDATAL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_LCDDATAL,
- },
- {
- .gpio_chip = {
- .label = "LCDCTLH",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 120,
- .ngpio = 1,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_LCDCTLH,
- .podr = (void __iomem *) MCFGPIO_PODR_LCDCTLH,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_LCDCTLH,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_LCDCTLH,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_LCDCTLH,
- },
- {
- .gpio_chip = {
- .label = "LCDCTLL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 128,
- .ngpio = 8,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_LCDCTLL,
- .podr = (void __iomem *) MCFGPIO_PODR_LCDCTLL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_LCDCTLL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_LCDCTLL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_LCDCTLL,
- },
-};
-
-static int __init mcf_gpio_init(void)
-{
- unsigned i = 0;
- while (i < ARRAY_SIZE(mcf_gpio_chips))
- (void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
- return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff --git a/arch/m68k/platform/5407/Makefile b/arch/m68k/platform/5407/Makefile
deleted file mode 100644
index e83fe148eddc..000000000000
--- a/arch/m68k/platform/5407/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this, which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
-
diff --git a/arch/m68k/platform/5407/gpio.c b/arch/m68k/platform/5407/gpio.c
deleted file mode 100644
index 5850612b4a38..000000000000
--- a/arch/m68k/platform/5407/gpio.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
- {
- .gpio_chip = {
- .label = "PP",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value,
- .ngpio = 16,
- },
- .pddr = (void __iomem *) MCFSIM_PADDR,
- .podr = (void __iomem *) MCFSIM_PADAT,
- .ppdr = (void __iomem *) MCFSIM_PADAT,
- },
-};
-
-static int __init mcf_gpio_init(void)
-{
- unsigned i = 0;
- while (i < ARRAY_SIZE(mcf_gpio_chips))
- (void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
- return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff --git a/arch/m68k/platform/54xx/Makefile b/arch/m68k/platform/54xx/Makefile
deleted file mode 100644
index 6cfd090ec3cd..000000000000
--- a/arch/m68k/platform/54xx/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this, which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o
-obj-$(CONFIG_FIREBEE) += firebee.o
-
diff --git a/arch/m68k/platform/coldfire/Makefile b/arch/m68k/platform/coldfire/Makefile
index a0815c61dec1..76d389d9a84e 100644
--- a/arch/m68k/platform/coldfire/Makefile
+++ b/arch/m68k/platform/coldfire/Makefile
@@ -15,18 +15,22 @@
asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-$(CONFIG_COLDFIRE) += cache.o clk.o device.o dma.o entry.o vectors.o
-obj-$(CONFIG_M5206) += timers.o intc.o reset.o
-obj-$(CONFIG_M5206e) += timers.o intc.o reset.o
-obj-$(CONFIG_M520x) += pit.o intc-simr.o reset.o
-obj-$(CONFIG_M523x) += pit.o dma_timer.o intc-2.o reset.o
-obj-$(CONFIG_M5249) += timers.o intc.o reset.o
-obj-$(CONFIG_M527x) += pit.o intc-2.o reset.o
-obj-$(CONFIG_M5272) += timers.o
-obj-$(CONFIG_M528x) += pit.o intc-2.o reset.o
-obj-$(CONFIG_M5307) += timers.o intc.o reset.o
-obj-$(CONFIG_M532x) += timers.o intc-simr.o reset.o
-obj-$(CONFIG_M5407) += timers.o intc.o reset.o
-obj-$(CONFIG_M54xx) += sltimers.o intc-2.o
+obj-$(CONFIG_M5206) += m5206.o timers.o intc.o reset.o
+obj-$(CONFIG_M5206e) += m5206.o timers.o intc.o reset.o
+obj-$(CONFIG_M520x) += m520x.o pit.o intc-simr.o reset.o
+obj-$(CONFIG_M523x) += m523x.o pit.o dma_timer.o intc-2.o reset.o
+obj-$(CONFIG_M5249) += m5249.o timers.o intc.o intc-5249.o reset.o
+obj-$(CONFIG_M527x) += m527x.o pit.o intc-2.o reset.o
+obj-$(CONFIG_M5272) += m5272.o intc-5272.o timers.o
+obj-$(CONFIG_M528x) += m528x.o pit.o intc-2.o reset.o
+obj-$(CONFIG_M5307) += m5307.o timers.o intc.o reset.o
+obj-$(CONFIG_M532x) += m532x.o timers.o intc-simr.o reset.o
+obj-$(CONFIG_M5407) += m5407.o timers.o intc.o reset.o
+obj-$(CONFIG_M54xx) += m54xx.o sltimers.o intc-2.o
+
+obj-$(CONFIG_NETtel) += nettel.o
+obj-$(CONFIG_CLEOPATRA) += nettel.o
+obj-$(CONFIG_FIREBEE) += firebee.o
obj-y += pinmux.o gpio.o
extra-y := head.o
diff --git a/arch/m68k/platform/54xx/firebee.c b/arch/m68k/platform/coldfire/firebee.c
index 46d50534f981..46d50534f981 100644
--- a/arch/m68k/platform/54xx/firebee.c
+++ b/arch/m68k/platform/coldfire/firebee.c
diff --git a/arch/m68k/platform/coldfire/gpio.c b/arch/m68k/platform/coldfire/gpio.c
index 292a1a5a2d7c..4c8c42450a4e 100644
--- a/arch/m68k/platform/coldfire/gpio.c
+++ b/arch/m68k/platform/coldfire/gpio.c
@@ -122,6 +122,10 @@ struct bus_type mcf_gpio_subsys = {
static int __init mcf_gpio_sysinit(void)
{
+ unsigned int i = 0;
+
+ while (i < mcf_gpio_chips_size)
+ gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
return subsys_system_register(&mcf_gpio_subsys, NULL);
}
diff --git a/arch/m68k/platform/5249/intc2.c b/arch/m68k/platform/coldfire/intc-5249.c
index f343bf7bf5b0..f343bf7bf5b0 100644
--- a/arch/m68k/platform/5249/intc2.c
+++ b/arch/m68k/platform/coldfire/intc-5249.c
diff --git a/arch/m68k/platform/5272/intc.c b/arch/m68k/platform/coldfire/intc-5272.c
index 7160e618b0a9..7160e618b0a9 100644
--- a/arch/m68k/platform/5272/intc.c
+++ b/arch/m68k/platform/coldfire/intc-5272.c
diff --git a/arch/m68k/platform/5206/config.c b/arch/m68k/platform/coldfire/m5206.c
index 6bfbeebd231b..a8b81df653f0 100644
--- a/arch/m68k/platform/5206/config.c
+++ b/arch/m68k/platform/coldfire/m5206.c
@@ -16,6 +16,15 @@
#include <asm/machdep.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+/***************************************************************************/
+
+struct mcf_gpio_chip mcf_gpio_chips[] = {
+ MCFGPS(PP, 0, 8, MCFSIM_PADDR, MCFSIM_PADAT, MCFSIM_PADAT),
+};
+
+unsigned int mcf_gpio_chips_size = ARRAY_SIZE(mcf_gpio_chips);
/***************************************************************************/
diff --git a/arch/m68k/platform/520x/config.c b/arch/m68k/platform/coldfire/m520x.c
index 09df4b89e8be..3264b8883d5f 100644
--- a/arch/m68k/platform/520x/config.c
+++ b/arch/m68k/platform/coldfire/m520x.c
@@ -19,6 +19,22 @@
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include <asm/mcfuart.h>
+#include <asm/mcfgpio.h>
+
+/***************************************************************************/
+
+struct mcf_gpio_chip mcf_gpio_chips[] = {
+ MCFGPS(PIRQ, 0, 8, MCFEPORT_EPDDR, MCFEPORT_EPDR, MCFEPORT_EPPDR),
+ MCFGPF(CS, 9, 3),
+ MCFGPF(FECI2C, 16, 4),
+ MCFGPF(QSPI, 24, 4),
+ MCFGPF(TIMER, 32, 4),
+ MCFGPF(UART, 40, 8),
+ MCFGPF(FECH, 48, 8),
+ MCFGPF(FECL, 56, 8),
+};
+
+unsigned int mcf_gpio_chips_size = ARRAY_SIZE(mcf_gpio_chips);
/***************************************************************************/
diff --git a/arch/m68k/platform/523x/config.c b/arch/m68k/platform/coldfire/m523x.c
index d47dfd8f50a2..5d57a4249412 100644
--- a/arch/m68k/platform/523x/config.c
+++ b/arch/m68k/platform/coldfire/m523x.c
@@ -19,6 +19,28 @@
#include <asm/machdep.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+/***************************************************************************/
+
+struct mcf_gpio_chip mcf_gpio_chips[] = {
+ MCFGPS(PIRQ, 1, 7, MCFEPORT_EPDDR, MCFEPORT_EPDR, MCFEPORT_EPPDR),
+ MCFGPF(ADDR, 13, 3),
+ MCFGPF(DATAH, 16, 8),
+ MCFGPF(DATAL, 24, 8),
+ MCFGPF(BUSCTL, 32, 8),
+ MCFGPF(BS, 40, 4),
+ MCFGPF(CS, 49, 7),
+ MCFGPF(SDRAM, 56, 6),
+ MCFGPF(FECI2C, 64, 4),
+ MCFGPF(UARTH, 72, 2),
+ MCFGPF(UARTL, 80, 8),
+ MCFGPF(QSPI, 88, 5),
+ MCFGPF(TIMER, 96, 8),
+ MCFGPF(ETPU, 104, 3),
+};
+
+unsigned int mcf_gpio_chips_size = ARRAY_SIZE(mcf_gpio_chips);
/***************************************************************************/
diff --git a/arch/m68k/platform/5249/config.c b/arch/m68k/platform/coldfire/m5249.c
index 300e729a58d0..fdfa1edfd1ac 100644
--- a/arch/m68k/platform/5249/config.c
+++ b/arch/m68k/platform/coldfire/m5249.c
@@ -16,6 +16,16 @@
#include <asm/machdep.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+/***************************************************************************/
+
+struct mcf_gpio_chip mcf_gpio_chips[] = {
+ MCFGPS(GPIO0, 0, 32, MCFSIM2_GPIOENABLE, MCFSIM2_GPIOWRITE, MCFSIM2_GPIOREAD),
+ MCFGPS(GPIO1, 32, 32, MCFSIM2_GPIO1ENABLE, MCFSIM2_GPIO1WRITE, MCFSIM2_GPIO1READ),
+};
+
+unsigned int mcf_gpio_chips_size = ARRAY_SIZE(mcf_gpio_chips);
/***************************************************************************/
diff --git a/arch/m68k/platform/5272/config.c b/arch/m68k/platform/coldfire/m5272.c
index e68bc7a148eb..43e36060da18 100644
--- a/arch/m68k/platform/5272/config.c
+++ b/arch/m68k/platform/coldfire/m5272.c
@@ -19,6 +19,7 @@
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include <asm/mcfuart.h>
+#include <asm/mcfgpio.h>
/***************************************************************************/
@@ -30,6 +31,16 @@ unsigned char ledbank = 0xff;
/***************************************************************************/
+struct mcf_gpio_chip mcf_gpio_chips[] = {
+ MCFGPS(PA, 0, 16, MCFSIM_PADDR, MCFSIM_PADAT, MCFSIM_PADAT),
+ MCFGPS(PB, 16, 16, MCFSIM_PBDDR, MCFSIM_PBDAT, MCFSIM_PBDAT),
+ MCFGPS(Pc, 32, 16, MCFSIM_PCDDR, MCFSIM_PCDAT, MCFSIM_PCDAT),
+};
+
+unsigned int mcf_gpio_chips_size = ARRAY_SIZE(mcf_gpio_chips);
+
+/***************************************************************************/
+
static void __init m5272_uarts_init(void)
{
u32 v;
diff --git a/arch/m68k/platform/527x/config.c b/arch/m68k/platform/coldfire/m527x.c
index b3cb378c5e94..9b0b66aabd1b 100644
--- a/arch/m68k/platform/527x/config.c
+++ b/arch/m68k/platform/coldfire/m527x.c
@@ -20,6 +20,49 @@
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include <asm/mcfuart.h>
+#include <asm/mcfgpio.h>
+
+/***************************************************************************/
+
+struct mcf_gpio_chip mcf_gpio_chips[] = {
+#if defined(CONFIG_M5271)
+ MCFGPS(PIRQ, 1, 7, MCFEPORT_EPDDR, MCFEPORT_EPDR, MCFEPORT_EPPDR),
+ MCFGPF(ADDR, 13, 3),
+ MCFGPF(DATAH, 16, 8),
+ MCFGPF(DATAL, 24, 8),
+ MCFGPF(BUSCTL, 32, 8),
+ MCFGPF(BS, 40, 4),
+ MCFGPF(CS, 49, 7),
+ MCFGPF(SDRAM, 56, 6),
+ MCFGPF(FECI2C, 64, 4),
+ MCFGPF(UARTH, 72, 2),
+ MCFGPF(UARTL, 80, 8),
+ MCFGPF(QSPI, 88, 5),
+ MCFGPF(TIMER, 96, 8),
+#elif defined(CONFIG_M5275)
+ MCFGPS(PIRQ, 1, 7, MCFEPORT_EPDDR, MCFEPORT_EPDR, MCFEPORT_EPPDR),
+ MCFGPF(BUSCTL, 8, 8),
+ MCFGPF(ADDR, 21, 3),
+ MCFGPF(CS, 25, 7),
+ MCFGPF(FEC0H, 32, 8),
+ MCFGPF(FEC0L, 40, 8),
+ MCFGPF(FECI2C, 48, 6),
+ MCFGPF(QSPI, 56, 7),
+ MCFGPF(SDRAM, 64, 8),
+ MCFGPF(TIMERH, 72, 4),
+ MCFGPF(TIMERL, 80, 4),
+ MCFGPF(UARTL, 88, 8),
+ MCFGPF(FEC1H, 96, 8),
+ MCFGPF(FEC1L, 104, 8),
+ MCFGPF(BS, 114, 2),
+ MCFGPF(IRQ, 121, 7),
+ MCFGPF(USBH, 128, 1),
+ MCFGPF(USBL, 136, 8),
+ MCFGPF(UARTH, 144, 4),
+#endif
+};
+
+unsigned int mcf_gpio_chips_size = ARRAY_SIZE(mcf_gpio_chips);
/***************************************************************************/
diff --git a/arch/m68k/platform/528x/config.c b/arch/m68k/platform/coldfire/m528x.c
index c5f11ba49be5..7ed1276b29dc 100644
--- a/arch/m68k/platform/528x/config.c
+++ b/arch/m68k/platform/coldfire/m528x.c
@@ -21,6 +21,37 @@
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include <asm/mcfuart.h>
+#include <asm/mcfgpio.h>
+
+/***************************************************************************/
+
+struct mcf_gpio_chip mcf_gpio_chips[] = {
+ MCFGPS(NQ, 1, 7, MCFEPORT_EPDDR, MCFEPORT_EPDR, MCFEPORT_EPPDR),
+ MCFGPS(TA, 8, 4, MCFGPTA_GPTDDR, MCFGPTA_GPTPORT, MCFGPTB_GPTPORT),
+ MCFGPS(TB, 16, 4, MCFGPTB_GPTDDR, MCFGPTB_GPTPORT, MCFGPTB_GPTPORT),
+ MCFGPS(QA, 24, 4, MCFQADC_DDRQA, MCFQADC_PORTQA, MCFQADC_PORTQA),
+ MCFGPS(QB, 32, 4, MCFQADC_DDRQB, MCFQADC_PORTQB, MCFQADC_PORTQB),
+ MCFGPF(A, 40, 8),
+ MCFGPF(B, 48, 8),
+ MCFGPF(C, 56, 8),
+ MCFGPF(D, 64, 8),
+ MCFGPF(E, 72, 8),
+ MCFGPF(F, 80, 8),
+ MCFGPF(G, 88, 8),
+ MCFGPF(H, 96, 8),
+ MCFGPF(J, 104, 8),
+ MCFGPF(DD, 112, 8),
+ MCFGPF(EH, 120, 8),
+ MCFGPF(EL, 128, 8),
+ MCFGPF(AS, 136, 6),
+ MCFGPF(QS, 144, 7),
+ MCFGPF(SD, 152, 6),
+ MCFGPF(TC, 160, 4),
+ MCFGPF(TD, 168, 4),
+ MCFGPF(UA, 176, 4),
+};
+
+unsigned int mcf_gpio_chips_size = ARRAY_SIZE(mcf_gpio_chips);
/***************************************************************************/
diff --git a/arch/m68k/platform/5307/config.c b/arch/m68k/platform/coldfire/m5307.c
index a568d2870d15..93b484976ab3 100644
--- a/arch/m68k/platform/5307/config.c
+++ b/arch/m68k/platform/coldfire/m5307.c
@@ -16,6 +16,7 @@
#include <asm/machdep.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
#include <asm/mcfwdebug.h>
/***************************************************************************/
@@ -28,6 +29,14 @@ unsigned char ledbank = 0xff;
/***************************************************************************/
+struct mcf_gpio_chip mcf_gpio_chips[] = {
+ MCFGPS(PP, 0, 16, MCFSIM_PADDR, MCFSIM_PADAT, MCFSIM_PADAT),
+};
+
+unsigned int mcf_gpio_chips_size = ARRAY_SIZE(mcf_gpio_chips);
+
+/***************************************************************************/
+
void __init config_BSP(char *commandp, int size)
{
#if defined(CONFIG_NETtel) || \
diff --git a/arch/m68k/platform/532x/config.c b/arch/m68k/platform/coldfire/m532x.c
index 37082d02f2bd..5394223639f8 100644
--- a/arch/m68k/platform/532x/config.c
+++ b/arch/m68k/platform/coldfire/m532x.c
@@ -7,7 +7,7 @@
* Copyright (C) 2000, Lineo (www.lineo.com)
* Yaroslav Vinogradov yaroslav.vinogradov@freescale.com
* Copyright Freescale Semiconductor, Inc 2006
- * Copyright (c) 2006, emlix, Sebastian Hess <sh@emlix.com>
+ * Copyright (c) 2006, emlix, Sebastian Hess <shess@hessware.de>
*
* 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
@@ -26,10 +26,35 @@
#include <asm/mcfsim.h>
#include <asm/mcfuart.h>
#include <asm/mcfdma.h>
+#include <asm/mcfgpio.h>
#include <asm/mcfwdebug.h>
/***************************************************************************/
+struct mcf_gpio_chip mcf_gpio_chips[] = {
+ MCFGPS(PIRQ, 0, 8, MCFEPORT_EPDDR, MCFEPORT_EPDR, MCFEPORT_EPPDR),
+ MCFGPF(FECH, 8, 8),
+ MCFGPF(FECL, 16, 8),
+ MCFGPF(SSI, 24, 5),
+ MCFGPF(BUSCTL, 32, 4),
+ MCFGPF(BE, 40, 4),
+ MCFGPF(CS, 49, 5),
+ MCFGPF(PWM, 58, 4),
+ MCFGPF(FECI2C, 64, 4),
+ MCFGPF(UART, 72, 8),
+ MCFGPF(QSPI, 80, 6),
+ MCFGPF(TIMER, 88, 4),
+ MCFGPF(LCDDATAH, 96, 2),
+ MCFGPF(LCDDATAM, 104, 8),
+ MCFGPF(LCDDATAL, 112, 8),
+ MCFGPF(LCDCTLH, 120, 1),
+ MCFGPF(LCDCTLL, 128, 8),
+};
+
+unsigned int mcf_gpio_chips_size = ARRAY_SIZE(mcf_gpio_chips);
+
+/***************************************************************************/
+
#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
static void __init m532x_qspi_init(void)
diff --git a/arch/m68k/platform/5407/config.c b/arch/m68k/platform/coldfire/m5407.c
index bb6c746ae819..faa6680b3404 100644
--- a/arch/m68k/platform/5407/config.c
+++ b/arch/m68k/platform/coldfire/m5407.c
@@ -16,6 +16,15 @@
#include <asm/machdep.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+/***************************************************************************/
+
+struct mcf_gpio_chip mcf_gpio_chips[] = {
+ MCFGPS(PP, 0, 16, MCFSIM_PADDR, MCFSIM_PADAT, MCFSIM_PADAT),
+};
+
+unsigned int mcf_gpio_chips_size = ARRAY_SIZE(mcf_gpio_chips);
/***************************************************************************/
diff --git a/arch/m68k/platform/54xx/config.c b/arch/m68k/platform/coldfire/m54xx.c
index 2081c6cbb3de..20672dadb252 100644
--- a/arch/m68k/platform/54xx/config.c
+++ b/arch/m68k/platform/coldfire/m54xx.c
@@ -21,12 +21,19 @@
#include <asm/m54xxsim.h>
#include <asm/mcfuart.h>
#include <asm/m54xxgpt.h>
+#include <asm/mcfgpio.h>
#ifdef CONFIG_MMU
#include <asm/mmu_context.h>
#endif
/***************************************************************************/
+struct mcf_gpio_chip mcf_gpio_chips[] = { };
+
+unsigned int mcf_gpio_chips_size = ARRAY_SIZE(mcf_gpio_chips);
+
+/***************************************************************************/
+
static void __init m54xx_uarts_init(void)
{
/* enable io pins */
diff --git a/arch/m68k/platform/5307/nettel.c b/arch/m68k/platform/coldfire/nettel.c
index e925ea4602f8..e925ea4602f8 100644
--- a/arch/m68k/platform/5307/nettel.c
+++ b/arch/m68k/platform/coldfire/nettel.c
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h
index bffb54527299..af2bb9652392 100644
--- a/arch/microblaze/include/asm/processor.h
+++ b/arch/microblaze/include/asm/processor.h
@@ -23,7 +23,6 @@ extern const struct seq_operations cpuinfo_op;
# define cpu_relax() barrier()
# define cpu_sleep() do {} while (0)
-# define prepare_to_copy(tsk) do {} while (0)
#define task_pt_regs(tsk) \
(((struct pt_regs *)(THREAD_SIZE + task_stack_page(tsk))) - 1)
diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile
index 494b63b72dd7..928c950fc14c 100644
--- a/arch/microblaze/kernel/Makefile
+++ b/arch/microblaze/kernel/Makefile
@@ -16,7 +16,7 @@ endif
extra-y := head.o vmlinux.lds
obj-y += dma.o exceptions.o \
- hw_exception_handler.o init_task.o intc.o irq.o \
+ hw_exception_handler.o intc.o irq.o \
process.o prom.o prom_parse.o ptrace.o \
reset.o setup.o signal.o sys_microblaze.o timer.o traps.o unwind.o
diff --git a/arch/microblaze/kernel/init_task.c b/arch/microblaze/kernel/init_task.c
deleted file mode 100644
index b5d711f94ff8..000000000000
--- a/arch/microblaze/kernel/init_task.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2009 PetaLogix
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c
index 6eb2aa927d89..ab1b9db661f3 100644
--- a/arch/microblaze/kernel/ptrace.c
+++ b/arch/microblaze/kernel/ptrace.c
@@ -136,7 +136,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
{
long ret = 0;
- secure_computing(regs->r12);
+ secure_computing_strict(regs->r12);
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
tracehook_report_syscall_entry(regs))
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index d10403dadd2b..ed22bfc5db14 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -1422,6 +1422,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, struct list_head *resources)
{
+ unsigned long io_offset;
struct resource *res;
int i;
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index ce30e2f91d77..85aad0321397 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -29,6 +29,8 @@ config MIPS
select HAVE_MEMBLOCK
select HAVE_MEMBLOCK_NODE_MAP
select ARCH_DISCARD_MEMBLOCK
+ select GENERIC_SMP_IDLE_THREAD
+ select BUILDTIME_EXTABLE_SORT
menu "Machine selection"
@@ -1001,12 +1003,12 @@ config HOLES_IN_ZONE
bool
#
-# Endianess selection. Sufficiently obscure so many users don't know what to
+# Endianness selection. Sufficiently obscure so many users don't know what to
# answer,so we try hard to limit the available choices. Also the use of a
# choice statement should be more obvious to the user.
#
choice
- prompt "Endianess selection"
+ prompt "Endianness selection"
help
Some MIPS machines can be configured for either little or big endian
byte order. These modes require different kernels and a different
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 83ed00a5644a..5a43aa0798ca 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -57,7 +57,7 @@ config CMDLINE
options.
config CMDLINE_OVERRIDE
- bool "Built-in command line overrides firware arguments"
+ bool "Built-in command line overrides firmware arguments"
default n
depends on CMDLINE_BOOL
help
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 4fedf5a51d96..76017c25a9e6 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -235,7 +235,7 @@ endif
OBJCOPYFLAGS += --remove-section=.reginfo
-head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
+head-y := arch/mips/kernel/head.o
libs-y += arch/mips/lib/
diff --git a/arch/mips/include/asm/mach-ip27/topology.h b/arch/mips/include/asm/mach-ip27/topology.h
index 1b1a7d1632b9..b2cf641f206f 100644
--- a/arch/mips/include/asm/mach-ip27/topology.h
+++ b/arch/mips/include/asm/mach-ip27/topology.h
@@ -36,23 +36,6 @@ extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
#define node_distance(from, to) (__node_distances[(from)][(to)])
-/* sched_domains SD_NODE_INIT for SGI IP27 machines */
-#define SD_NODE_INIT (struct sched_domain) { \
- .parent = NULL, \
- .child = NULL, \
- .groups = NULL, \
- .min_interval = 8, \
- .max_interval = 32, \
- .busy_factor = 32, \
- .imbalance_pct = 125, \
- .cache_nice_tries = 1, \
- .flags = SD_LOAD_BALANCE | \
- SD_BALANCE_EXEC, \
- .last_balance = jiffies, \
- .balance_interval = 1, \
- .nr_balance_failed = 0, \
-}
-
#include <asm-generic/topology.h>
#endif /* _ASM_MACH_TOPOLOGY_H */
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 20e9dcf42b27..5e33fabe354d 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -310,9 +310,6 @@ struct task_struct;
/* Free all resources held by a thread. */
#define release_thread(thread) do { } while(0)
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
extern unsigned long thread_saved_pc(struct task_struct *tsk);
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 0d85d8e440c5..e2eca7d10598 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -85,18 +85,6 @@ register struct thread_info *__current_thread_info __asm__("$28");
#define STACK_WARN (THREAD_SIZE / 8)
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info_node(tsk, node) \
- kzalloc_node(THREAD_SIZE, GFP_KERNEL, node)
-#else
-#define alloc_thread_info_node(tsk, node) \
- kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
-#endif
-
-#define free_thread_info(info) kfree(info)
-
#endif /* !__ASSEMBLY__ */
#define PREEMPT_ACTIVE 0x10000000
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 0c6877ea9004..fdaf65e1a99d 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -2,7 +2,7 @@
# Makefile for the Linux/MIPS kernel.
#
-extra-y := head.o init_task.o vmlinux.lds
+extra-y := head.o vmlinux.lds
obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
ptrace.o reset.o setup.o signal.o syscall.o \
diff --git a/arch/mips/kernel/init_task.c b/arch/mips/kernel/init_task.c
deleted file mode 100644
index 5f9a76263c9a..000000000000
--- a/arch/mips/kernel/init_task.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <linux/mm.h>
-#include <linux/export.h>
-#include <linux/sched.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-
-#include <asm/thread_info.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is 8192-byte aligned due to the
- * way process stacks are handled. This is done by making sure
- * the linker maps this in the .text segment right after head.S,
- * and making head.S ensure the proper alignment.
- *
- * The things we do for performance..
- */
-union thread_union init_thread_union __init_task_data
- __attribute__((__aligned__(THREAD_SIZE))) =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
index 7f3376b1c219..6ded9bd1489c 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -209,7 +209,7 @@ void mips_mt_set_cpuoptions(void)
unsigned int nconfig7 = oconfig7;
if (mt_opt_norps) {
- printk("\"norps\" option deprectated: use \"rpsctl=\"\n");
+ printk("\"norps\" option deprecated: use \"rpsctl=\"\n");
}
if (mt_opt_rpsctl >= 0) {
printk("34K return prediction stack override set to %d.\n",
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 811084f4e422..ab73fa2fb9b5 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -1325,7 +1325,7 @@ static int mipsxx_pmu_handle_shared_irq(void)
regs = get_irq_regs();
- perf_sample_data_init(&data, 0);
+ perf_sample_data_init(&data, 0, 0);
switch (counters) {
#define HANDLE_COUNTER(n) \
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 7c24c2973c6d..4812c6d916e4 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -535,7 +535,7 @@ static inline int audit_arch(void)
asmlinkage void syscall_trace_enter(struct pt_regs *regs)
{
/* do the secure computing check first */
- secure_computing(regs->regs[2]);
+ secure_computing_strict(regs->regs[2]);
if (!(current->ptrace & PT_PTRACED))
goto out;
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index ba9376bf52a1..71a95f55a649 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -186,61 +186,9 @@ void __devinit smp_prepare_boot_cpu(void)
cpu_set(0, cpu_callin_map);
}
-/*
- * Called once for each "cpu_possible(cpu)". Needs to spin up the cpu
- * and keep control until "cpu_online(cpu)" is set. Note: cpu is
- * physical, not logical.
- */
-static struct task_struct *cpu_idle_thread[NR_CPUS];
-
-struct create_idle {
- struct work_struct work;
- struct task_struct *idle;
- struct completion done;
- int cpu;
-};
-
-static void __cpuinit do_fork_idle(struct work_struct *work)
-{
- struct create_idle *c_idle =
- container_of(work, struct create_idle, work);
-
- c_idle->idle = fork_idle(c_idle->cpu);
- complete(&c_idle->done);
-}
-
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
- struct task_struct *idle;
-
- /*
- * Processor goes to start_secondary(), sets online flag
- * The following code is purely to make sure
- * Linux can schedule processes on this slave.
- */
- if (!cpu_idle_thread[cpu]) {
- /*
- * Schedule work item to avoid forking user task
- * Ported from arch/x86/kernel/smpboot.c
- */
- struct create_idle c_idle = {
- .cpu = cpu,
- .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
- };
-
- INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle);
- schedule_work(&c_idle.work);
- wait_for_completion(&c_idle.done);
- idle = cpu_idle_thread[cpu] = c_idle.idle;
-
- if (IS_ERR(idle))
- panic(KERN_ERR "Fork failed for CPU %d", cpu);
- } else {
- idle = cpu_idle_thread[cpu];
- init_idle(idle, cpu);
- }
-
- mp_ops->boot_secondary(cpu, idle);
+ mp_ops->boot_secondary(cpu, tidle);
/*
* Trust is futile. We should really have timeouts ...
diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c
index d2fa98f3c78d..c429a5bc080f 100644
--- a/arch/mips/lantiq/xway/gpio.c
+++ b/arch/mips/lantiq/xway/gpio.c
@@ -188,7 +188,7 @@ int __init ltq_gpio_init(void)
int ret = platform_driver_register(&ltq_gpio_driver);
if (ret)
- pr_info("ltq_gpio : Error registering platfom driver!");
+ pr_info("ltq_gpio : Error registering platform driver!");
return ret;
}
diff --git a/arch/mips/lantiq/xway/gpio_ebu.c b/arch/mips/lantiq/xway/gpio_ebu.c
index b91c7f17f10f..aae17170472f 100644
--- a/arch/mips/lantiq/xway/gpio_ebu.c
+++ b/arch/mips/lantiq/xway/gpio_ebu.c
@@ -119,7 +119,7 @@ static int __init ltq_ebu_init(void)
int ret = platform_driver_register(&ltq_ebu_driver);
if (ret)
- pr_info("ltq_ebu : Error registering platfom driver!");
+ pr_info("ltq_ebu : Error registering platform driver!");
return ret;
}
diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
index ff9991cddeaa..fd07d87adaa9 100644
--- a/arch/mips/lantiq/xway/gpio_stp.c
+++ b/arch/mips/lantiq/xway/gpio_stp.c
@@ -150,7 +150,7 @@ int __init ltq_stp_init(void)
int ret = platform_driver_register(&ltq_stp_driver);
if (ret)
- pr_info("ltq_stp: error registering platfom driver");
+ pr_info("ltq_stp: error registering platform driver");
return ret;
}
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
index ed3b3d317358..cdb1417fba59 100644
--- a/arch/mips/sni/pcimt.c
+++ b/arch/mips/sni/pcimt.c
@@ -29,7 +29,7 @@ static void __init sni_pcimt_sc_init(void)
scsiz = cacheconf & 7;
if (scsiz == 0) {
- printk("Second level cache is deactived.\n");
+ printk("Second level cache is deactivated.\n");
return;
}
if (scsiz >= 6) {
diff --git a/arch/mn10300/Makefile b/arch/mn10300/Makefile
index 7120282bf0d8..33188b6e81e4 100644
--- a/arch/mn10300/Makefile
+++ b/arch/mn10300/Makefile
@@ -51,7 +51,7 @@ UNIT := asb2364
endif
-head-y := arch/mn10300/kernel/head.o arch/mn10300/kernel/init_task.o
+head-y := arch/mn10300/kernel/head.o
core-y += arch/mn10300/kernel/ arch/mn10300/mm/
diff --git a/arch/mn10300/include/asm/processor.h b/arch/mn10300/include/asm/processor.h
index f7b3c9ab2cb5..247928c9f549 100644
--- a/arch/mn10300/include/asm/processor.h
+++ b/arch/mn10300/include/asm/processor.h
@@ -139,9 +139,6 @@ static inline void start_thread(struct pt_regs *regs,
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
-/* Prepare to copy thread state - unlazy all lazy status */
-extern void prepare_to_copy(struct task_struct *tsk);
-
/*
* create a kernel thread without removing it from tasklists
*/
diff --git a/arch/mn10300/include/asm/thread_info.h b/arch/mn10300/include/asm/thread_info.h
index 28cf52100baa..08251d6f6b11 100644
--- a/arch/mn10300/include/asm/thread_info.h
+++ b/arch/mn10300/include/asm/thread_info.h
@@ -20,8 +20,10 @@
#ifdef CONFIG_4KSTACKS
#define THREAD_SIZE (4096)
+#define THREAD_SIZE_ORDER (0)
#else
#define THREAD_SIZE (8192)
+#define THREAD_SIZE_ORDER (1)
#endif
#define STACK_WARN (THREAD_SIZE / 8)
@@ -120,21 +122,8 @@ static inline unsigned long current_stack_pointer(void)
return sp;
}
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-
-/* thread information allocation */
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info_node(tsk, node) \
- kzalloc_node(THREAD_SIZE, GFP_KERNEL, node)
-#else
-#define alloc_thread_info_node(tsk, node) \
- kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
-#endif
-
#ifndef CONFIG_KGDB
-#define free_thread_info(ti) kfree((ti))
-#else
-extern void free_thread_info(struct thread_info *);
+void arch_release_thread_info(struct thread_info *ti)
#endif
#define get_thread_info(ti) get_task_struct((ti)->task)
#define put_thread_info(ti) put_task_struct((ti)->task)
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
index 47ed30fe8178..d06749173d63 100644
--- a/arch/mn10300/kernel/Makefile
+++ b/arch/mn10300/kernel/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for the MN10300-specific core kernel code
#
-extra-y := head.o init_task.o vmlinux.lds
+extra-y := head.o vmlinux.lds
fpu-obj-y := fpu-nofpu.o fpu-nofpu-low.o
fpu-obj-$(CONFIG_FPU) := fpu.o fpu-low.o
diff --git a/arch/mn10300/kernel/init_task.c b/arch/mn10300/kernel/init_task.c
deleted file mode 100644
index a481b043bea7..000000000000
--- a/arch/mn10300/kernel/init_task.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* MN10300 Initial task definitions
- *
- * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is THREAD_SIZE aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
diff --git a/arch/mn10300/kernel/kgdb.c b/arch/mn10300/kernel/kgdb.c
index f6c981db2a36..99770823451a 100644
--- a/arch/mn10300/kernel/kgdb.c
+++ b/arch/mn10300/kernel/kgdb.c
@@ -397,7 +397,7 @@ static bool kgdb_arch_undo_singlestep(struct pt_regs *regs)
* single-step state is cleared. At this point the breakpoints should have
* been removed by __switch_to().
*/
-void free_thread_info(struct thread_info *ti)
+void arch_release_thread_info(struct thread_info *ti)
{
if (kgdb_sstep_thread == ti) {
kgdb_sstep_thread = NULL;
@@ -407,7 +407,6 @@ void free_thread_info(struct thread_info *ti)
* so force immediate reentry */
kgdb_breakpoint();
}
- kfree(ti);
}
/*
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c
index 14707f25153b..7dab0cd36466 100644
--- a/arch/mn10300/kernel/process.c
+++ b/arch/mn10300/kernel/process.c
@@ -208,12 +208,14 @@ void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
}
/*
- * this gets called before we allocate a new thread and copy the current task
- * into it so that we can store lazy state into memory
+ * this gets called so that we can store lazy state into memory and copy the
+ * current task into the new thread.
*/
-void prepare_to_copy(struct task_struct *tsk)
+int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
- unlazy_fpu(tsk);
+ unlazy_fpu(src);
+ *dst = *src;
+ return 0;
}
/*
diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c
index 9cd69ad6aa02..090d35d36973 100644
--- a/arch/mn10300/kernel/smp.c
+++ b/arch/mn10300/kernel/smp.c
@@ -924,7 +924,7 @@ void initialize_secondary(void)
* __cpu_up - Set smp_commenced_mask for the nominated CPU
* @cpu: The target CPU.
*/
-int __devinit __cpu_up(unsigned int cpu)
+int __devinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
int timeout;
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index a4787197d8fe..297bd38f7c5d 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -7,6 +7,7 @@ config OPENRISC
def_bool y
select OF
select OF_EARLY_FLATTREE
+ select IRQ_DOMAIN
select HAVE_MEMBLOCK
select ARCH_WANT_OPTIONAL_GPIOLIB
select HAVE_ARCH_TRACEHOOK
@@ -141,7 +142,7 @@ config DEBUG_STACKOVERFLOW
bool "Check for kernel stack overflow"
default y
help
- Make extra checks for space avaliable on stack in some
+ Make extra checks for space available on stack in some
critical functions. This will cause kernel to run a bit slower,
but will catch most of kernel stack overruns and exit gracefuly.
diff --git a/arch/openrisc/Makefile b/arch/openrisc/Makefile
index 158ae4c0dc6c..966886c8daf5 100644
--- a/arch/openrisc/Makefile
+++ b/arch/openrisc/Makefile
@@ -38,7 +38,7 @@ else
KBUILD_CFLAGS += $(call cc-option,-msoft-div)
endif
-head-y := arch/openrisc/kernel/head.o arch/openrisc/kernel/init_task.o
+head-y := arch/openrisc/kernel/head.o
core-y += arch/openrisc/lib/ \
arch/openrisc/kernel/ \
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index dcea5a0308ae..c936483bc8e2 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -1,6 +1,7 @@
include include/asm-generic/Kbuild.asm
-header-y += spr_defs.h
+header-y += elf.h
+header-y += ucontext.h
generic-y += atomic.h
generic-y += auxvec.h
diff --git a/arch/openrisc/include/asm/dma-mapping.h b/arch/openrisc/include/asm/dma-mapping.h
index b206ba4608b2..fab8628e1b6e 100644
--- a/arch/openrisc/include/asm/dma-mapping.h
+++ b/arch/openrisc/include/asm/dma-mapping.h
@@ -20,150 +20,71 @@
/*
* See Documentation/DMA-API-HOWTO.txt and
* Documentation/DMA-API.txt for documentation.
- *
- * This file is written with the intention of eventually moving over
- * to largely using asm-generic/dma-mapping-common.h in its place.
*/
#include <linux/dma-debug.h>
#include <asm-generic/dma-coherent.h>
#include <linux/kmemcheck.h>
+#include <linux/dma-mapping.h>
#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
+extern struct dma_map_ops or1k_dma_map_ops;
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-
-void *or1k_dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag);
-void or1k_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle);
-dma_addr_t or1k_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir,
- struct dma_attrs *attrs);
-void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs);
-int or1k_map_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs);
-void or1k_unmap_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs);
-void or1k_sync_single_for_cpu(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction dir);
-void or1k_sync_single_for_device(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction dir);
-
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
{
- void *memory;
-
- memory = or1k_dma_alloc_coherent(dev, size, dma_handle, flag);
-
- debug_dma_alloc_coherent(dev, size, *dma_handle, memory);
- return memory;
+ return &or1k_dma_map_ops;
}
-static inline void dma_free_coherent(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t dma_handle)
-{
- debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
- or1k_dma_free_coherent(dev, size, cpu_addr, dma_handle);
-}
+#include <asm-generic/dma-mapping-common.h>
-static inline dma_addr_t dma_map_single(struct device *dev, void *ptr,
- size_t size,
- enum dma_data_direction dir)
-{
- dma_addr_t addr;
-
- kmemcheck_mark_initialized(ptr, size);
- BUG_ON(!valid_dma_direction(dir));
- addr = or1k_map_page(dev, virt_to_page(ptr),
- (unsigned long)ptr & ~PAGE_MASK, size,
- dir, NULL);
- debug_dma_map_page(dev, virt_to_page(ptr),
- (unsigned long)ptr & ~PAGE_MASK, size,
- dir, addr, true);
- return addr;
-}
+#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
-static inline void dma_unmap_single(struct device *dev, dma_addr_t addr,
- size_t size,
- enum dma_data_direction dir)
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp,
+ struct dma_attrs *attrs)
{
- BUG_ON(!valid_dma_direction(dir));
- or1k_unmap_page(dev, addr, size, dir, NULL);
- debug_dma_unmap_page(dev, addr, size, dir, true);
-}
+ struct dma_map_ops *ops = get_dma_ops(dev);
+ void *memory;
-static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir)
-{
- int i, ents;
- struct scatterlist *s;
+ memory = ops->alloc(dev, size, dma_handle, gfp, attrs);
- for_each_sg(sg, s, nents, i)
- kmemcheck_mark_initialized(sg_virt(s), s->length);
- BUG_ON(!valid_dma_direction(dir));
- ents = or1k_map_sg(dev, sg, nents, dir, NULL);
- debug_dma_map_sg(dev, sg, nents, ents, dir);
+ debug_dma_alloc_coherent(dev, size, *dma_handle, memory);
- return ents;
+ return memory;
}
-static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir)
-{
- BUG_ON(!valid_dma_direction(dir));
- debug_dma_unmap_sg(dev, sg, nents, dir);
- or1k_unmap_sg(dev, sg, nents, dir, NULL);
-}
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
-static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
- size_t offset, size_t size,
- enum dma_data_direction dir)
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
- dma_addr_t addr;
+ struct dma_map_ops *ops = get_dma_ops(dev);
- kmemcheck_mark_initialized(page_address(page) + offset, size);
- BUG_ON(!valid_dma_direction(dir));
- addr = or1k_map_page(dev, page, offset, size, dir, NULL);
- debug_dma_map_page(dev, page, offset, size, dir, addr, false);
+ debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
- return addr;
+ ops->free(dev, size, cpu_addr, dma_handle, attrs);
}
-static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
- size_t size, enum dma_data_direction dir)
+static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp)
{
- BUG_ON(!valid_dma_direction(dir));
- or1k_unmap_page(dev, addr, size, dir, NULL);
- debug_dma_unmap_page(dev, addr, size, dir, true);
-}
+ struct dma_attrs attrs;
-static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
- size_t size,
- enum dma_data_direction dir)
-{
- BUG_ON(!valid_dma_direction(dir));
- or1k_sync_single_for_cpu(dev, addr, size, dir);
- debug_dma_sync_single_for_cpu(dev, addr, size, dir);
+ dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
+
+ return dma_alloc_attrs(dev, size, dma_handle, gfp, &attrs);
}
-static inline void dma_sync_single_for_device(struct device *dev,
- dma_addr_t addr, size_t size,
- enum dma_data_direction dir)
+static inline void dma_free_noncoherent(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
{
- BUG_ON(!valid_dma_direction(dir));
- or1k_sync_single_for_device(dev, addr, size, dir);
- debug_dma_sync_single_for_device(dev, addr, size, dir);
+ struct dma_attrs attrs;
+
+ dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
+
+ dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
}
static inline int dma_supported(struct device *dev, u64 dma_mask)
diff --git a/arch/openrisc/include/asm/elf.h b/arch/openrisc/include/asm/elf.h
index 2ce603bbfdd3..a8fe2c513070 100644
--- a/arch/openrisc/include/asm/elf.h
+++ b/arch/openrisc/include/asm/elf.h
@@ -20,11 +20,17 @@
#define __ASM_OPENRISC_ELF_H
/*
+ * This files is partially exported to userspace. This allows us to keep
+ * the ELF bits in one place which should assist in keeping the kernel and
+ * userspace in sync.
+ */
+
+/*
* ELF register definitions..
*/
-#include <linux/types.h>
-#include <linux/ptrace.h>
+/* for struct user_regs_struct definition */
+#include <asm/ptrace.h>
/* The OR1K relocation types... not all relevant for module loader */
#define R_OR32_NONE 0
@@ -62,6 +68,8 @@ typedef unsigned long elf_fpregset_t;
#ifdef __KERNEL__
+#include <linux/types.h>
+
/*
* This is used to ensure we don't load something for the wrong architecture.
*/
diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h
index f7516fa78b58..30462f1fe959 100644
--- a/arch/openrisc/include/asm/processor.h
+++ b/arch/openrisc/include/asm/processor.h
@@ -72,10 +72,6 @@ struct thread_struct {
#define task_pt_regs(task) user_regs(task_thread_info(task))
#define current_regs() user_regs(current_thread_info())
-extern inline void prepare_to_copy(struct task_struct *tsk)
-{
-}
-
#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
#define INIT_THREAD { }
diff --git a/arch/openrisc/include/asm/ptrace.h b/arch/openrisc/include/asm/ptrace.h
index 4651a737591d..8555c0c3d4d7 100644
--- a/arch/openrisc/include/asm/ptrace.h
+++ b/arch/openrisc/include/asm/ptrace.h
@@ -19,8 +19,6 @@
#ifndef __ASM_OPENRISC_PTRACE_H
#define __ASM_OPENRISC_PTRACE_H
-#include <asm/spr_defs.h>
-
#ifndef __ASSEMBLY__
/*
* This is the layout of the regset returned by the GETREGSET ptrace call
@@ -30,13 +28,13 @@ struct user_regs_struct {
unsigned long gpr[32];
unsigned long pc;
unsigned long sr;
- unsigned long pad1;
- unsigned long pad2;
};
#endif
#ifdef __KERNEL__
+#include <asm/spr_defs.h>
+
/*
* Make kernel PTrace/register structures opaque to userspace... userspace can
* access thread state via the regset mechanism. This allows us a bit of
diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile
index 9a4c2706d795..e1ee0fa2bbda 100644
--- a/arch/openrisc/kernel/Makefile
+++ b/arch/openrisc/kernel/Makefile
@@ -2,7 +2,7 @@
# Makefile for the linux kernel.
#
-extra-y := head.o vmlinux.lds init_task.o
+extra-y := head.o vmlinux.lds
obj-y := setup.o idle.o or32_ksyms.o process.o dma.o \
traps.o time.o irq.o entry.o ptrace.o signal.o sys_or32.o \
diff --git a/arch/openrisc/kernel/dma.c b/arch/openrisc/kernel/dma.c
index f1c8ee2895d0..0b77ddb1ee07 100644
--- a/arch/openrisc/kernel/dma.c
+++ b/arch/openrisc/kernel/dma.c
@@ -21,13 +21,16 @@
#include <linux/dma-mapping.h>
#include <linux/dma-debug.h>
+#include <linux/export.h>
+#include <linux/dma-attrs.h>
#include <asm/cpuinfo.h>
#include <asm/spr_defs.h>
#include <asm/tlbflush.h>
-static int page_set_nocache(pte_t *pte, unsigned long addr,
- unsigned long next, struct mm_walk *walk)
+static int
+page_set_nocache(pte_t *pte, unsigned long addr,
+ unsigned long next, struct mm_walk *walk)
{
unsigned long cl;
@@ -46,8 +49,9 @@ static int page_set_nocache(pte_t *pte, unsigned long addr,
return 0;
}
-static int page_clear_nocache(pte_t *pte, unsigned long addr,
- unsigned long next, struct mm_walk *walk)
+static int
+page_clear_nocache(pte_t *pte, unsigned long addr,
+ unsigned long next, struct mm_walk *walk)
{
pte_val(*pte) &= ~_PAGE_CI;
@@ -67,9 +71,19 @@ static int page_clear_nocache(pte_t *pte, unsigned long addr,
* cache-inhibit bit on those pages, and makes sure that the pages are
* flushed out of the cache before they are used.
*
+ * If the NON_CONSISTENT attribute is set, then this function just
+ * returns "normal", cachable memory.
+ *
+ * There are additional flags WEAK_ORDERING and WRITE_COMBINE to take
+ * into consideration here, too. All current known implementations of
+ * the OR1K support only strongly ordered memory accesses, so that flag
+ * is being ignored for now; uncached but write-combined memory is a
+ * missing feature of the OR1K.
*/
-void *or1k_dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
+static void *
+or1k_dma_alloc(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp,
+ struct dma_attrs *attrs)
{
unsigned long va;
void *page;
@@ -87,20 +101,23 @@ void *or1k_dma_alloc_coherent(struct device *dev, size_t size,
va = (unsigned long)page;
- /*
- * We need to iterate through the pages, clearing the dcache for
- * them and setting the cache-inhibit bit.
- */
- if (walk_page_range(va, va + size, &walk)) {
- free_pages_exact(page, size);
- return NULL;
+ if (!dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs)) {
+ /*
+ * We need to iterate through the pages, clearing the dcache for
+ * them and setting the cache-inhibit bit.
+ */
+ if (walk_page_range(va, va + size, &walk)) {
+ free_pages_exact(page, size);
+ return NULL;
+ }
}
return (void *)va;
}
-void or1k_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
+static void
+or1k_dma_free(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle, struct dma_attrs *attrs)
{
unsigned long va = (unsigned long)vaddr;
struct mm_walk walk = {
@@ -108,16 +125,19 @@ void or1k_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
.mm = &init_mm
};
- /* walk_page_range shouldn't be able to fail here */
- WARN_ON(walk_page_range(va, va + size, &walk));
+ if (!dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs)) {
+ /* walk_page_range shouldn't be able to fail here */
+ WARN_ON(walk_page_range(va, va + size, &walk));
+ }
free_pages_exact(vaddr, size);
}
-dma_addr_t or1k_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir,
- struct dma_attrs *attrs)
+static dma_addr_t
+or1k_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
{
unsigned long cl;
dma_addr_t addr = page_to_phys(page) + offset;
@@ -147,16 +167,18 @@ dma_addr_t or1k_map_page(struct device *dev, struct page *page,
return addr;
}
-void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+static void
+or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
{
/* Nothing special to do here... */
}
-int or1k_map_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+static int
+or1k_map_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
{
struct scatterlist *s;
int i;
@@ -169,9 +191,10 @@ int or1k_map_sg(struct device *dev, struct scatterlist *sg,
return nents;
}
-void or1k_unmap_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+static void
+or1k_unmap_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
{
struct scatterlist *s;
int i;
@@ -181,9 +204,10 @@ void or1k_unmap_sg(struct device *dev, struct scatterlist *sg,
}
}
-void or1k_sync_single_for_cpu(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction dir)
+static void
+or1k_sync_single_for_cpu(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
{
unsigned long cl;
dma_addr_t addr = dma_handle;
@@ -193,9 +217,10 @@ void or1k_sync_single_for_cpu(struct device *dev,
mtspr(SPR_DCBIR, cl);
}
-void or1k_sync_single_for_device(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction dir)
+static void
+or1k_sync_single_for_device(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
{
unsigned long cl;
dma_addr_t addr = dma_handle;
@@ -205,6 +230,18 @@ void or1k_sync_single_for_device(struct device *dev,
mtspr(SPR_DCBFR, cl);
}
+struct dma_map_ops or1k_dma_map_ops = {
+ .alloc = or1k_dma_alloc,
+ .free = or1k_dma_free,
+ .map_page = or1k_map_page,
+ .unmap_page = or1k_unmap_page,
+ .map_sg = or1k_map_sg,
+ .unmap_sg = or1k_unmap_sg,
+ .sync_single_for_cpu = or1k_sync_single_for_cpu,
+ .sync_single_for_device = or1k_sync_single_for_device,
+};
+EXPORT_SYMBOL(or1k_dma_map_ops);
+
/* Number of entries preallocated for DMA-API debugging */
#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S
index 6e61af8682b8..ddfcaa828b0e 100644
--- a/arch/openrisc/kernel/entry.S
+++ b/arch/openrisc/kernel/entry.S
@@ -1117,10 +1117,10 @@ ENTRY(sys_rt_sigreturn)
ENTRY(sys_or1k_atomic)
/* FIXME: This ignores r3 and always does an XCHG */
DISABLE_INTERRUPTS(r17,r19)
- l.lwz r30,0(r4)
- l.lwz r28,0(r5)
- l.sw 0(r4),r28
- l.sw 0(r5),r30
+ l.lwz r29,0(r4)
+ l.lwz r27,0(r5)
+ l.sw 0(r4),r27
+ l.sw 0(r5),r29
ENABLE_INTERRUPTS(r17)
l.jr r9
l.or r11,r0,r0
diff --git a/arch/openrisc/kernel/init_task.c b/arch/openrisc/kernel/init_task.c
deleted file mode 100644
index ca534082d5f3..000000000000
--- a/arch/openrisc/kernel/init_task.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * OpenRISC init_task.c
- *
- * Linux architectural port borrowing liberally from similar works of
- * others. All original copyrights apply as per the original source
- * declaration.
- *
- * Modifications for the OpenRISC architecture:
- * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
- * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/init_task.h>
-#include <linux/mqueue.h>
-#include <linux/export.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is THREAD_SIZE aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data = {
- INIT_THREAD_INFO(init_task)
-};
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
diff --git a/arch/openrisc/kernel/irq.c b/arch/openrisc/kernel/irq.c
index 4bfead220956..e935b9d8eee1 100644
--- a/arch/openrisc/kernel/irq.c
+++ b/arch/openrisc/kernel/irq.c
@@ -14,17 +14,13 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/ptrace.h>
-#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/ftrace.h>
#include <linux/irq.h>
-#include <linux/seq_file.h>
-#include <linux/kernel_stat.h>
#include <linux/export.h>
-
+#include <linux/irqdomain.h>
#include <linux/irqflags.h>
/* read interrupt enabled status */
@@ -98,6 +94,7 @@ static void or1k_pic_mask_ack(struct irq_data *data)
#endif
}
+#if 0
static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type)
{
/* There's nothing to do in the PIC configuration when changing
@@ -107,43 +104,64 @@ static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type)
return irq_setup_alt_chip(data, flow_type);
}
+#endif
+
+static struct irq_chip or1k_dev = {
+ .name = "or1k-PIC",
+ .irq_unmask = or1k_pic_unmask,
+ .irq_mask = or1k_pic_mask,
+ .irq_ack = or1k_pic_ack,
+ .irq_mask_ack = or1k_pic_mask_ack,
+};
+
+static struct irq_domain *root_domain;
static inline int pic_get_irq(int first)
{
- int irq;
+ int hwirq;
- irq = ffs(mfspr(SPR_PICSR) >> first);
+ hwirq = ffs(mfspr(SPR_PICSR) >> first);
+ if (!hwirq)
+ return NO_IRQ;
+ else
+ hwirq = hwirq + first -1;
- return irq ? irq + first - 1 : NO_IRQ;
+ return irq_find_mapping(root_domain, hwirq);
}
-static void __init or1k_irq_init(void)
+
+static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
- struct irq_chip_generic *gc;
- struct irq_chip_type *ct;
+ irq_set_chip_and_handler_name(irq, &or1k_dev,
+ handle_level_irq, "level");
+ irq_set_status_flags(irq, IRQ_LEVEL | IRQ_NOPROBE);
- /* Disable all interrupts until explicitly requested */
- mtspr(SPR_PICMR, (0UL));
+ return 0;
+}
- gc = irq_alloc_generic_chip("or1k-PIC", 1, 0, 0, handle_level_irq);
- ct = gc->chip_types;
+static const struct irq_domain_ops or1k_irq_domain_ops = {
+ .xlate = irq_domain_xlate_onecell,
+ .map = or1k_map,
+};
- ct->chip.irq_unmask = or1k_pic_unmask;
- ct->chip.irq_mask = or1k_pic_mask;
- ct->chip.irq_ack = or1k_pic_ack;
- ct->chip.irq_mask_ack = or1k_pic_mask_ack;
- ct->chip.irq_set_type = or1k_pic_set_type;
+/*
+ * This sets up the IRQ domain for the PIC built in to the OpenRISC
+ * 1000 CPU. This is the "root" domain as these are the interrupts
+ * that directly trigger an exception in the CPU.
+ */
+static void __init or1k_irq_init(void)
+{
+ struct device_node *intc = NULL;
- /* The OR1K PIC can handle both level and edge trigged
- * interrupts in roughly the same manner
- */
-#if 0
- /* FIXME: chip.type??? */
- ct->chip.type = IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_MASK;
-#endif
+ /* The interrupt controller device node is mandatory */
+ intc = of_find_compatible_node(NULL, NULL, "opencores,or1k-pic");
+ BUG_ON(!intc);
- irq_setup_generic_chip(gc, IRQ_MSK(NR_IRQS), 0,
- IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
+ /* Disable all interrupts until explicitly requested */
+ mtspr(SPR_PICMR, (0UL));
+
+ root_domain = irq_domain_add_linear(intc, 32,
+ &or1k_irq_domain_ops, NULL);
}
void __init init_IRQ(void)
@@ -164,10 +182,3 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
irq_exit();
set_irq_regs(old_regs);
}
-
-unsigned int irq_create_of_mapping(struct device_node *controller,
- const u32 *intspec, unsigned int intsize)
-{
- return intspec[0];
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c
index a5dce82f864b..40f850e9766c 100644
--- a/arch/openrisc/mm/fault.c
+++ b/arch/openrisc/mm/fault.c
@@ -54,6 +54,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
struct vm_area_struct *vma;
siginfo_t info;
int fault;
+ unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
tsk = current;
@@ -105,6 +106,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
if (in_interrupt() || !mm)
goto no_context;
+retry:
down_read(&mm->mmap_sem);
vma = find_vma(mm, address);
@@ -143,6 +145,7 @@ good_area:
if (write_acc) {
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
+ flags |= FAULT_FLAG_WRITE;
} else {
/* not present */
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
@@ -159,7 +162,11 @@ good_area:
* the fault.
*/
- fault = handle_mm_fault(mm, vma, address, write_acc);
+ fault = handle_mm_fault(mm, vma, address, flags);
+
+ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+ return;
+
if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM)
goto out_of_memory;
@@ -167,11 +174,24 @@ good_area:
goto do_sigbus;
BUG();
}
- /*RGD modeled on Cris */
- if (fault & VM_FAULT_MAJOR)
- tsk->maj_flt++;
- else
- tsk->min_flt++;
+
+ if (flags & FAULT_FLAG_ALLOW_RETRY) {
+ /*RGD modeled on Cris */
+ if (fault & VM_FAULT_MAJOR)
+ tsk->maj_flt++;
+ else
+ tsk->min_flt++;
+ if (fault & VM_FAULT_RETRY) {
+ flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+ /* No need to up_read(&mm->mmap_sem) as we would
+ * have already released it in __lock_page_or_retry
+ * in mm/filemap.c.
+ */
+
+ goto retry;
+ }
+ }
up_read(&mm->mmap_sem);
return;
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 242a1b7ac759..ddb8b24b823d 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -17,6 +17,7 @@ config PARISC
select GENERIC_PCI_IOMAP
select IRQ_PER_CPU
select ARCH_HAVE_NMI_SAFE_CMPXCHG
+ select GENERIC_SMP_IDLE_THREAD
help
The PA-RISC microprocessor is designed by Hewlett-Packard and used
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index 19ab7b2ea1cd..dbc3850b1d0d 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -75,7 +75,7 @@ head-y := arch/parisc/kernel/head.o
KBUILD_CFLAGS += $(cflags-y)
-kernel-y := mm/ kernel/ math-emu/ kernel/init_task.o
+kernel-y := mm/ kernel/ math-emu/
kernel-$(CONFIG_HPUX) += hpux/
core-y += $(addprefix arch/parisc/, $(kernel-y))
diff --git a/arch/parisc/include/asm/kbdleds.h b/arch/parisc/include/asm/kbdleds.h
new file mode 100644
index 000000000000..2e2e75a83c28
--- /dev/null
+++ b/arch/parisc/include/asm/kbdleds.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_PARISC_KBDLEDS_H
+#define _ASM_PARISC_KBDLEDS_H
+
+/*
+ * On HIL keyboards of PARISC machines there is no NumLock key and
+ * everyone expects the keypad to be used for numbers. That's why
+ * we can safely turn on the NUMLOCK bit.
+ */
+
+static inline int kbd_defleds(void)
+{
+#if defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD)
+ return 1 << VC_NUMLOCK;
+#else
+ return 0;
+#endif
+}
+
+#endif /* _ASM_PARISC_KBDLEDS_H */
diff --git a/arch/parisc/include/asm/prefetch.h b/arch/parisc/include/asm/prefetch.h
index c5edc60c059f..1ee7c82672c1 100644
--- a/arch/parisc/include/asm/prefetch.h
+++ b/arch/parisc/include/asm/prefetch.h
@@ -21,7 +21,12 @@
#define ARCH_HAS_PREFETCH
static inline void prefetch(const void *addr)
{
- __asm__("ldw 0(%0), %%r0" : : "r" (addr));
+ __asm__(
+#ifndef CONFIG_PA20
+ /* Need to avoid prefetch of NULL on PA7300LC */
+ " extrw,u,= %0,31,32,%%r0\n"
+#endif
+ " ldw 0(%0), %%r0" : : "r" (addr));
}
/* LDD is a PA2.0 addition. */
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index acdf4cad6125..0e8b7b8ce8a2 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -328,9 +328,6 @@ struct mm_struct;
extern void release_thread(struct task_struct *);
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm);
extern unsigned long get_wchan(struct task_struct *p);
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
index 67db0722e6ca..66ee3f12df58 100644
--- a/arch/parisc/kernel/Makefile
+++ b/arch/parisc/kernel/Makefile
@@ -2,7 +2,7 @@
# Makefile for arch/parisc/kernel
#
-extra-y := init_task.o head.o vmlinux.lds
+extra-y := head.o vmlinux.lds
obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \
pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 6f0594439143..535034217021 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -581,7 +581,11 @@
*/
cmpiclr,= 0x01,\tmp,%r0
ldi (_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot
+#ifdef CONFIG_64BIT
depd,z \prot,8,7,\prot
+#else
+ depw,z \prot,8,7,\prot
+#endif
/*
* OK, it is in the temp alias region, check whether "from" or "to".
* Check "subtle" note in pacache.S re: r23/r26.
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c
deleted file mode 100644
index 4a91e433416f..000000000000
--- a/arch/parisc/kernel/init_task.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Static declaration of "init" task data structure.
- *
- * Copyright (C) 2000 Paul Bame <bame at parisc-linux.org>
- * Copyright (C) 2000-2001 John Marvin <jsm at parisc-linux.org>
- * Copyright (C) 2001 Helge Deller <deller @ parisc-linux.org>
- * Copyright (C) 2002 Matthew Wilcox <willy with parisc-linux.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/pgalloc.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial task structure.
- *
- * We need to make sure that this is 16384-byte aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data
- __attribute__((aligned(128))) =
- { INIT_THREAD_INFO(init_task) };
-
-#if PT_NLEVELS == 3
-/* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
- * with the first pmd adjacent to the pgd and below it. gcc doesn't actually
- * guarantee that global objects will be laid out in memory in the same order
- * as the order of declaration, so put these in different sections and use
- * the linker script to order them. */
-pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((__section__ (".data..vm0.pmd"), aligned(PAGE_SIZE)));
-#endif
-
-pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((__section__ (".data..vm0.pgd"), aligned(PAGE_SIZE)));
-pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data..vm0.pte"), aligned(PAGE_SIZE)));
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-EXPORT_SYMBOL(init_task);
-
-__asm__(".data");
-struct task_struct init_task = INIT_TASK(init_task);
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index 93ff3d90edd1..5d7218ad885c 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -692,7 +692,7 @@ ENTRY(flush_icache_page_asm)
/* Purge any old translation */
- pitlb (%sr0,%r28)
+ pitlb (%sr4,%r28)
ldil L%icache_stride, %r1
ldw R%icache_stride(%r1), %r1
@@ -706,27 +706,29 @@ ENTRY(flush_icache_page_asm)
sub %r25, %r1, %r25
-1: fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
+ /* fic only has the type 26 form on PA1.1, requiring an
+ * explicit space specification, so use %sr4 */
+1: fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
cmpb,COND(<<) %r28, %r25,1b
- fic,m %r1(%r28)
+ fic,m %r1(%sr4,%r28)
sync
bv %r0(%r2)
- pitlb (%sr0,%r25)
+ pitlb (%sr4,%r25)
.exit
.procend
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 4dc7b7942b4c..a47828d31fe6 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -340,26 +340,11 @@ void __init smp_callin(void)
/*
* Bring one cpu online.
*/
-int __cpuinit smp_boot_one_cpu(int cpuid)
+int __cpuinit smp_boot_one_cpu(int cpuid, struct task_struct *idle)
{
const struct cpuinfo_parisc *p = &per_cpu(cpu_data, cpuid);
- struct task_struct *idle;
long timeout;
- /*
- * Create an idle task for this CPU. Note the address wed* give
- * to kernel_thread is irrelevant -- it's going to start
- * where OS_BOOT_RENDEVZ vector in SAL says to start. But
- * this gets all the other task-y sort of data structures set
- * up like we wish. We need to pull the just created idle task
- * off the run queue and stuff it into the init_tasks[] array.
- * Sheesh . . .
- */
-
- idle = fork_idle(cpuid);
- if (IS_ERR(idle))
- panic("SMP: fork failed for CPU:%d", cpuid);
-
task_thread_info(idle)->cpu = cpuid;
/* Let _start know what logical CPU we're booting
@@ -403,10 +388,6 @@ int __cpuinit smp_boot_one_cpu(int cpuid)
udelay(100);
barrier();
}
-
- put_task_struct(idle);
- idle = NULL;
-
printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid);
return -1;
@@ -455,10 +436,10 @@ void smp_cpus_done(unsigned int cpu_max)
}
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
if (cpu != 0 && cpu < parisc_max_cpus)
- smp_boot_one_cpu(cpu);
+ smp_boot_one_cpu(cpu, tidle);
return cpu_online(cpu) ? 0 : -ENOSYS;
}
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 82f364e209fc..3ac462de53a4 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -33,6 +33,18 @@
extern int data_start;
+#if PT_NLEVELS == 3
+/* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
+ * with the first pmd adjacent to the pgd and below it. gcc doesn't actually
+ * guarantee that global objects will be laid out in memory in the same order
+ * as the order of declaration, so put these in different sections and use
+ * the linker script to order them. */
+pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((__section__ (".data..vm0.pmd"), aligned(PAGE_SIZE)));
+#endif
+
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((__section__ (".data..vm0.pgd"), aligned(PAGE_SIZE)));
+pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data..vm0.pte"), aligned(PAGE_SIZE)));
+
#ifdef CONFIG_DISCONTIGMEM
struct node_map_data node_data[MAX_NUMNODES] __read_mostly;
unsigned char pfnnid_map[PFNNID_MAP_MAX] __read_mostly;
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index feab3bad6d0f..0a947bd9c076 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -87,10 +87,6 @@ config ARCH_HAS_ILOG2_U64
bool
default y if 64BIT
-config ARCH_HAS_CPU_IDLE_WAIT
- bool
- default y
-
config GENERIC_HWEIGHT
bool
default y
@@ -141,9 +137,10 @@ config PPC
select IRQ_FORCED_THREADING
select HAVE_RCU_TABLE_FREE if SMP
select HAVE_SYSCALL_TRACEPOINTS
- select HAVE_BPF_JIT if (PPC64 && NET)
+ select HAVE_BPF_JIT if PPC64
select HAVE_ARCH_JUMP_LABEL
select ARCH_HAVE_NMI_SAFE_CMPXCHG
+ select GENERIC_SMP_IDLE_THREAD
config EARLY_PRINTK
bool
@@ -353,7 +350,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
- depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !PPC_47x)) && EXPERIMENTAL
+ depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP)) && EXPERIMENTAL
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
@@ -370,7 +367,7 @@ config KEXEC
config CRASH_DUMP
bool "Build a kdump crash kernel"
- depends on PPC64 || 6xx || FSL_BOOKE || (44x && !SMP && !PPC_47x)
+ depends on PPC64 || 6xx || FSL_BOOKE || (44x && !SMP)
select RELOCATABLE if PPC64 || 44x
select DYNAMIC_MEMSTART if FSL_BOOKE
help
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 6524c6e21896..950d1f7a5a39 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -69,6 +69,16 @@ LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y)
CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=no -mcall-aixdesc
CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple
+
+CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,-mtune=power4)
+CFLAGS-$(CONFIG_CELL_CPU) += $(call cc-option,-mcpu=cell)
+CFLAGS-$(CONFIG_POWER4_CPU) += $(call cc-option,-mcpu=power4)
+CFLAGS-$(CONFIG_POWER5_CPU) += $(call cc-option,-mcpu=power5)
+CFLAGS-$(CONFIG_POWER6_CPU) += $(call cc-option,-mcpu=power6)
+CFLAGS-$(CONFIG_POWER7_CPU) += $(call cc-option,-mcpu=power7)
+
+CFLAGS-$(CONFIG_TUNE_CELL) += $(call cc-option,-mtune=cell)
+
KBUILD_CPPFLAGS += -Iarch/$(ARCH)
KBUILD_AFLAGS += -Iarch/$(ARCH)
KBUILD_CFLAGS += -msoft-float -pipe -Iarch/$(ARCH) $(CFLAGS-y)
@@ -76,32 +86,11 @@ CPP = $(CC) -E $(KBUILD_CFLAGS)
CHECKFLAGS += -m$(CONFIG_WORD_SIZE) -D__powerpc__ -D__powerpc$(CONFIG_WORD_SIZE)__
-ifeq ($(CONFIG_PPC64),y)
-GCC_BROKEN_VEC := $(call cc-ifversion, -lt, 0400, y)
-
-ifeq ($(CONFIG_POWER4_ONLY),y)
-ifeq ($(CONFIG_ALTIVEC),y)
-ifeq ($(GCC_BROKEN_VEC),y)
- KBUILD_CFLAGS += $(call cc-option,-mcpu=970)
-else
- KBUILD_CFLAGS += $(call cc-option,-mcpu=power4)
-endif
-else
- KBUILD_CFLAGS += $(call cc-option,-mcpu=power4)
-endif
-else
- KBUILD_CFLAGS += $(call cc-option,-mtune=power4)
-endif
-endif
-
KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
-ifeq ($(CONFIG_TUNE_CELL),y)
- KBUILD_CFLAGS += $(call cc-option,-mtune=cell)
-endif
-
-# No AltiVec instruction when building kernel
+# No AltiVec or VSX instructions when building kernel
KBUILD_CFLAGS += $(call cc-option,-mno-altivec)
+KBUILD_CFLAGS += $(call cc-option,-mno-vsx)
# No SPE instruction when building kernel
# (We use all available options to help semi-broken compilers)
@@ -160,6 +149,7 @@ core-$(CONFIG_KVM) += arch/powerpc/kvm/
core-$(CONFIG_PERF_EVENTS) += arch/powerpc/perf/
drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
+drivers-$(CONFIG_CRYPTO_DEV_NX) += drivers/crypto/nx/
# Default to zImage, override when needed
all: zImage
@@ -234,10 +224,11 @@ archprepare: checkbin
# Use the file '.tmp_gas_check' for binutils tests, as gas won't output
# to stdout and these checks are run even on install targets.
TOUT := .tmp_gas_check
-# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec
-# instructions.
-# gcc-3.4 and binutils-2.14 are a fatal combination.
+# Check gcc and binutils versions:
+# - gcc-3.4 and binutils-2.14 are a fatal combination
+# - Require gcc 4.0 or above on 64-bit
+# - gcc-4.2.0 has issues compiling modules on 64-bit
checkbin:
@if test "$(call cc-version)" = "0304" ; then \
if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \
@@ -247,6 +238,12 @@ checkbin:
false; \
fi ; \
fi
+ @if test "$(call cc-version)" -lt "0400" \
+ && test "x${CONFIG_PPC64}" = "xy" ; then \
+ echo -n "Sorry, GCC v4.0 or above is required to build " ; \
+ echo "the 64-bit powerpc kernel." ; \
+ false ; \
+ fi
@if test "$(call cc-fullversion)" = "040200" \
&& test "x${CONFIG_MODULES}${CONFIG_PPC64}" = "xyy" ; then \
echo -n '*** GCC-4.2.0 cannot compile the 64-bit powerpc ' ; \
diff --git a/arch/powerpc/boot/dts/bluestone.dts b/arch/powerpc/boot/dts/bluestone.dts
index 7bda373f10ef..9d4917aebe6b 100644
--- a/arch/powerpc/boot/dts/bluestone.dts
+++ b/arch/powerpc/boot/dts/bluestone.dts
@@ -373,5 +373,30 @@
0x0 0x0 0x0 0x3 &UIC3 0xe 0x4 /* swizzled int C */
0x0 0x0 0x0 0x4 &UIC3 0xf 0x4 /* swizzled int D */>;
};
+
+ MSI: ppc4xx-msi@C10000000 {
+ compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
+ reg = < 0xC 0x10000000 0x100
+ 0xC 0x10000000 0x100>;
+ sdr-base = <0x36C>;
+ msi-data = <0x00004440>;
+ msi-mask = <0x0000ffe0>;
+ interrupts =<0 1 2 3 4 5 6 7>;
+ interrupt-parent = <&MSI>;
+ #interrupt-cells = <1>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ msi-available-ranges = <0x0 0x100>;
+ interrupt-map = <
+ 0 &UIC3 0x18 1
+ 1 &UIC3 0x19 1
+ 2 &UIC3 0x1A 1
+ 3 &UIC3 0x1B 1
+ 4 &UIC3 0x1C 1
+ 5 &UIC3 0x1D 1
+ 6 &UIC3 0x1E 1
+ 7 &UIC3 0x1F 1
+ >;
+ };
};
};
diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
index 0db9ba0423ff..c09598b31de1 100644
--- a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
+++ b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
@@ -100,6 +100,7 @@ CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_SND_SOC=y
+CONFIG_SND_POWERPC_SOC=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_CMOS=y
CONFIG_EXT2_FS=y
diff --git a/arch/powerpc/configs/chroma_defconfig b/arch/powerpc/configs/chroma_defconfig
index f104ccde6b53..b1f9597fe312 100644
--- a/arch/powerpc/configs/chroma_defconfig
+++ b/arch/powerpc/configs/chroma_defconfig
@@ -32,7 +32,7 @@ CONFIG_RD_LZMA=y
CONFIG_INITRAMFS_COMPRESSION_GZIP=y
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
-CONFIG_PERF_COUNTERS=y
+CONFIG_PERF_EVENTS=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
CONFIG_KPROBES=y
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 1196c34163b7..07b7f2af2dca 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -1,5 +1,4 @@
CONFIG_PPC64=y
-CONFIG_POWER4_ONLY=y
CONFIG_ALTIVEC=y
CONFIG_SMP=y
CONFIG_NR_CPUS=4
diff --git a/arch/powerpc/configs/gamecube_defconfig b/arch/powerpc/configs/gamecube_defconfig
index e74d3a483705..9ef2cc13e1b4 100644
--- a/arch/powerpc/configs/gamecube_defconfig
+++ b/arch/powerpc/configs/gamecube_defconfig
@@ -8,7 +8,7 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EXPERT=y
# CONFIG_ELF_CORE is not set
-CONFIG_PERF_COUNTERS=y
+CONFIG_PERF_EVENTS=y
# CONFIG_VM_EVENT_COUNTERS is not set
CONFIG_SLAB=y
CONFIG_MODULES=y
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index 2244d370f24d..02ac96b679b8 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -1,5 +1,4 @@
CONFIG_PPC64=y
-CONFIG_POWER4_ONLY=y
CONFIG_SMP=y
CONFIG_NR_CPUS=4
CONFIG_EXPERIMENTAL=y
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index d6b6df5e8743..62bb723c5b54 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -141,6 +141,7 @@ CONFIG_SND_INTEL8X0=y
# CONFIG_SND_PPC is not set
# CONFIG_SND_USB is not set
CONFIG_SND_SOC=y
+CONFIG_SND_POWERPC_SOC=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index 5b0e2926becd..d1828427ae55 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -143,6 +143,7 @@ CONFIG_SND_INTEL8X0=y
# CONFIG_SND_PPC is not set
# CONFIG_SND_USB is not set
CONFIG_SND_SOC=y
+CONFIG_SND_POWERPC_SOC=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig
index f4deb0b78cf0..840a2c2d0430 100644
--- a/arch/powerpc/configs/pasemi_defconfig
+++ b/arch/powerpc/configs/pasemi_defconfig
@@ -1,5 +1,4 @@
CONFIG_PPC64=y
-CONFIG_POWER4_ONLY=y
CONFIG_ALTIVEC=y
# CONFIG_VIRT_CPU_ACCOUNTING is not set
CONFIG_SMP=y
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index ded867871e97..c2f4b4a86ece 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -6,7 +6,6 @@ CONFIG_NR_CPUS=2
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
-CONFIG_SPARSE_IRQ=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_EMBEDDED=y
@@ -25,7 +24,6 @@ CONFIG_PS3_DISK=y
CONFIG_PS3_ROM=y
CONFIG_PS3_FLASH=y
CONFIG_PS3_VRAM=m
-CONFIG_PS3_LPM=m
# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
CONFIG_HIGH_RES_TIMERS=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
@@ -53,8 +51,6 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_INET_DIAG is not set
CONFIG_IPV6=y
CONFIG_BT=m
-CONFIG_BT_L2CAP=y
-CONFIG_BT_SCO=y
CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=m
@@ -63,7 +59,6 @@ CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=m
CONFIG_BT_HCIBTUSB=m
CONFIG_CFG80211=m
-# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_MAC80211=m
CONFIG_MAC80211_RC_PID=y
# CONFIG_MAC80211_RC_MINSTREL is not set
@@ -181,7 +176,6 @@ CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_WRITECOUNT=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_LIST=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
# CONFIG_FTRACE is not set
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_CRYPTO_CCM=m
diff --git a/arch/powerpc/configs/wii_defconfig b/arch/powerpc/configs/wii_defconfig
index 175295fbf4f3..1e2b7d062aa4 100644
--- a/arch/powerpc/configs/wii_defconfig
+++ b/arch/powerpc/configs/wii_defconfig
@@ -9,7 +9,7 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EXPERT=y
# CONFIG_ELF_CORE is not set
-CONFIG_PERF_COUNTERS=y
+CONFIG_PERF_EVENTS=y
# CONFIG_VM_EVENT_COUNTERS is not set
CONFIG_SLAB=y
CONFIG_MODULES=y
diff --git a/arch/powerpc/include/asm/asm-compat.h b/arch/powerpc/include/asm/asm-compat.h
index decad950f11a..5d7fbe1950f9 100644
--- a/arch/powerpc/include/asm/asm-compat.h
+++ b/arch/powerpc/include/asm/asm-compat.h
@@ -29,18 +29,9 @@
#define PPC_LLARX(t, a, b, eh) PPC_LDARX(t, a, b, eh)
#define PPC_STLCX stringify_in_c(stdcx.)
#define PPC_CNTLZL stringify_in_c(cntlzd)
+#define PPC_MTOCRF(FXM, RS) MTOCRF((FXM), (RS))
#define PPC_LR_STKOFF 16
#define PPC_MIN_STKFRM 112
-
-/* Move to CR, single-entry optimized version. Only available
- * on POWER4 and later.
- */
-#ifdef CONFIG_POWER4_ONLY
-#define PPC_MTOCRF stringify_in_c(mtocrf)
-#else
-#define PPC_MTOCRF stringify_in_c(mtcrf)
-#endif
-
#else /* 32-bit */
/* operations for longs and pointers */
diff --git a/arch/powerpc/include/asm/cputhreads.h b/arch/powerpc/include/asm/cputhreads.h
index ce516e5eb0d3..ac3eedb9b74a 100644
--- a/arch/powerpc/include/asm/cputhreads.h
+++ b/arch/powerpc/include/asm/cputhreads.h
@@ -9,7 +9,7 @@
* Note: This implementation is limited to a power of 2 number of
* threads per core and the same number for each core in the system
* (though it would work if some processors had less threads as long
- * as the CPU numbers are still allocated, just not brought offline).
+ * as the CPU numbers are still allocated, just not brought online).
*
* However, the API allows for a different implementation in the future
* if needed, as long as you only use the functions and not the variables
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 1c324ff55ea8..612252388190 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -77,8 +77,27 @@
#define H_MR_CONDITION -43
#define H_NOT_ENOUGH_RESOURCES -44
#define H_R_STATE -45
-#define H_RESCINDEND -46
-#define H_MULTI_THREADS_ACTIVE -9005
+#define H_RESCINDED -46
+#define H_P2 -55
+#define H_P3 -56
+#define H_P4 -57
+#define H_P5 -58
+#define H_P6 -59
+#define H_P7 -60
+#define H_P8 -61
+#define H_P9 -62
+#define H_TOO_BIG -64
+#define H_OVERLAP -68
+#define H_INTERRUPT -69
+#define H_BAD_DATA -70
+#define H_NOT_ACTIVE -71
+#define H_SG_LIST -72
+#define H_OP_MODE -73
+#define H_COP_HW -74
+#define H_UNSUPPORTED_FLAG_START -256
+#define H_UNSUPPORTED_FLAG_END -511
+#define H_MULTI_THREADS_ACTIVE -9005
+#define H_OUTSTANDING_COP_OPS -9006
/* Long Busy is a condition that can be returned by the firmware
@@ -240,6 +259,8 @@
#define H_GET_MPP 0x2D4
#define H_HOME_NODE_ASSOCIATIVITY 0x2EC
#define H_BEST_ENERGY 0x2F4
+#define H_RANDOM 0x300
+#define H_COP 0x304
#define H_GET_MPP_X 0x314
#define MAX_HCALL_OPCODE H_GET_MPP_X
diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h
index a76254af0aaa..531fe0c3108f 100644
--- a/arch/powerpc/include/asm/lppaca.h
+++ b/arch/powerpc/include/asm/lppaca.h
@@ -20,18 +20,16 @@
#define _ASM_POWERPC_LPPACA_H
#ifdef __KERNEL__
-/* These definitions relate to hypervisors that only exist when using
+/*
+ * These definitions relate to hypervisors that only exist when using
* a server type processor
*/
#ifdef CONFIG_PPC_BOOK3S
-//=============================================================================
-//
-// This control block contains the data that is shared between the
-// hypervisor (PLIC) and the OS.
-//
-//
-//----------------------------------------------------------------------------
+/*
+ * This control block contains the data that is shared between the
+ * hypervisor and the OS.
+ */
#include <linux/cache.h>
#include <linux/threads.h>
#include <asm/types.h>
@@ -43,123 +41,65 @@
*/
#define NR_LPPACAS 1
-
-/* The Hypervisor barfs if the lppaca crosses a page boundary. A 1k
- * alignment is sufficient to prevent this */
+/*
+ * The Hypervisor barfs if the lppaca crosses a page boundary. A 1k
+ * alignment is sufficient to prevent this
+ */
struct lppaca {
-//=============================================================================
-// CACHE_LINE_1 0x0000 - 0x007F Contains read-only data
-// NOTE: The xDynXyz fields are fields that will be dynamically changed by
-// PLIC when preparing to bring a processor online or when dispatching a
-// virtual processor!
-//=============================================================================
- u32 desc; // Eye catcher 0xD397D781 x00-x03
- u16 size; // Size of this struct x04-x05
- u16 reserved1; // Reserved x06-x07
- u16 reserved2:14; // Reserved x08-x09
- u8 shared_proc:1; // Shared processor indicator ...
- u8 secondary_thread:1; // Secondary thread indicator ...
- volatile u8 dyn_proc_status:8; // Dynamic Status of this proc x0A-x0A
- u8 secondary_thread_count; // Secondary thread count x0B-x0B
- volatile u16 dyn_hv_phys_proc_index;// Dynamic HV Physical Proc Index0C-x0D
- volatile u16 dyn_hv_log_proc_index;// Dynamic HV Logical Proc Indexx0E-x0F
- u32 decr_val; // Value for Decr programming x10-x13
- u32 pmc_val; // Value for PMC regs x14-x17
- volatile u32 dyn_hw_node_id; // Dynamic Hardware Node id x18-x1B
- volatile u32 dyn_hw_proc_id; // Dynamic Hardware Proc Id x1C-x1F
- volatile u32 dyn_pir; // Dynamic ProcIdReg value x20-x23
- u32 dsei_data; // DSEI data x24-x27
- u64 sprg3; // SPRG3 value x28-x2F
- u8 reserved3[40]; // Reserved x30-x57
- volatile u8 vphn_assoc_counts[8]; // Virtual processor home node
- // associativity change counters x58-x5F
- u8 reserved4[32]; // Reserved x60-x7F
-
-//=============================================================================
-// CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data
-//=============================================================================
- // This Dword contains a byte for each type of interrupt that can occur.
- // The IPI is a count while the others are just a binary 1 or 0.
- union {
- u64 any_int;
- struct {
- u16 reserved; // Reserved - cleared by #mpasmbl
- u8 xirr_int; // Indicates xXirrValue is valid or Immed IO
- u8 ipi_cnt; // IPI Count
- u8 decr_int; // DECR interrupt occurred
- u8 pdc_int; // PDC interrupt occurred
- u8 quantum_int; // Interrupt quantum reached
- u8 old_plic_deferred_ext_int; // Old PLIC has a deferred XIRR pending
- } fields;
- } int_dword;
-
- // Whenever any fields in this Dword are set then PLIC will defer the
- // processing of external interrupts. Note that PLIC will store the
- // XIRR directly into the xXirrValue field so that another XIRR will
- // not be presented until this one clears. The layout of the low
- // 4-bytes of this Dword is up to SLIC - PLIC just checks whether the
- // entire Dword is zero or not. A non-zero value in the low order
- // 2-bytes will result in SLIC being granted the highest thread
- // priority upon return. A 0 will return to SLIC as medium priority.
- u64 plic_defer_ints_area; // Entire Dword
-
- // Used to pass the real SRR0/1 from PLIC to SLIC as well as to
- // pass the target SRR0/1 from SLIC to PLIC on a SetAsrAndRfid.
- u64 saved_srr0; // Saved SRR0 x10-x17
- u64 saved_srr1; // Saved SRR1 x18-x1F
-
- // Used to pass parms from the OS to PLIC for SetAsrAndRfid
- u64 saved_gpr3; // Saved GPR3 x20-x27
- u64 saved_gpr4; // Saved GPR4 x28-x2F
- union {
- u64 saved_gpr5; /* Saved GPR5 x30-x37 */
- struct {
- u8 cede_latency_hint; /* x30 */
- u8 reserved[7]; /* x31-x36 */
- } fields;
- } gpr5_dword;
-
-
- u8 dtl_enable_mask; // Dispatch Trace Log mask x38-x38
- u8 donate_dedicated_cpu; // Donate dedicated CPU cycles x39-x39
- u8 fpregs_in_use; // FP regs in use x3A-x3A
- u8 pmcregs_in_use; // PMC regs in use x3B-x3B
- volatile u32 saved_decr; // Saved Decr Value x3C-x3F
- volatile u64 emulated_time_base;// Emulated TB for this thread x40-x47
- volatile u64 cur_plic_latency; // Unaccounted PLIC latency x48-x4F
- u64 tot_plic_latency; // Accumulated PLIC latency x50-x57
- u64 wait_state_cycles; // Wait cycles for this proc x58-x5F
- u64 end_of_quantum; // TB at end of quantum x60-x67
- u64 pdc_saved_sprg1; // Saved SPRG1 for PMC int x68-x6F
- u64 pdc_saved_srr0; // Saved SRR0 for PMC int x70-x77
- volatile u32 virtual_decr; // Virtual DECR for shared procsx78-x7B
- u16 slb_count; // # of SLBs to maintain x7C-x7D
- u8 idle; // Indicate OS is idle x7E
- u8 vmxregs_in_use; // VMX registers in use x7F
-
-
-//=============================================================================
-// CACHE_LINE_3 0x0100 - 0x017F: This line is shared with other processors
-//=============================================================================
- // This is the yield_count. An "odd" value (low bit on) means that
- // the processor is yielded (either because of an OS yield or a PLIC
- // preempt). An even value implies that the processor is currently
- // executing.
- // NOTE: This value will ALWAYS be zero for dedicated processors and
- // will NEVER be zero for shared processors (ie, initialized to a 1).
- volatile u32 yield_count; // PLIC increments each dispatchx00-x03
- volatile u32 dispersion_count; // dispatch changed phys cpu x04-x07
- volatile u64 cmo_faults; // CMO page fault count x08-x0F
- volatile u64 cmo_fault_time; // CMO page fault time x10-x17
- u8 reserved7[104]; // Reserved x18-x7F
-
-//=============================================================================
-// CACHE_LINE_4-5 0x0180 - 0x027F Contains PMC interrupt data
-//=============================================================================
- u32 page_ins; // CMO Hint - # page ins by OS x00-x03
- u8 reserved8[148]; // Reserved x04-x97
- volatile u64 dtl_idx; // Dispatch Trace Log head idx x98-x9F
- u8 reserved9[96]; // Reserved xA0-xFF
+ /* cacheline 1 contains read-only data */
+
+ u32 desc; /* Eye catcher 0xD397D781 */
+ u16 size; /* Size of this struct */
+ u16 reserved1;
+ u16 reserved2:14;
+ u8 shared_proc:1; /* Shared processor indicator */
+ u8 secondary_thread:1; /* Secondary thread indicator */
+ u8 reserved3[14];
+ volatile u32 dyn_hw_node_id; /* Dynamic hardware node id */
+ volatile u32 dyn_hw_proc_id; /* Dynamic hardware proc id */
+ u8 reserved4[56];
+ volatile u8 vphn_assoc_counts[8]; /* Virtual processor home node */
+ /* associativity change counters */
+ u8 reserved5[32];
+
+ /* cacheline 2 contains local read-write data */
+
+ u8 reserved6[48];
+ u8 cede_latency_hint;
+ u8 reserved7[7];
+ u8 dtl_enable_mask; /* Dispatch Trace Log mask */
+ u8 donate_dedicated_cpu; /* Donate dedicated CPU cycles */
+ u8 fpregs_in_use;
+ u8 pmcregs_in_use;
+ u8 reserved8[28];
+ u64 wait_state_cycles; /* Wait cycles for this proc */
+ u8 reserved9[28];
+ u16 slb_count; /* # of SLBs to maintain */
+ u8 idle; /* Indicate OS is idle */
+ u8 vmxregs_in_use;
+
+ /* cacheline 3 is shared with other processors */
+
+ /*
+ * This is the yield_count. An "odd" value (low bit on) means that
+ * the processor is yielded (either because of an OS yield or a
+ * hypervisor preempt). An even value implies that the processor is
+ * currently executing.
+ * NOTE: This value will ALWAYS be zero for dedicated processors and
+ * will NEVER be zero for shared processors (ie, initialized to a 1).
+ */
+ volatile u32 yield_count;
+ volatile u32 dispersion_count; /* dispatch changed physical cpu */
+ volatile u64 cmo_faults; /* CMO page fault count */
+ volatile u64 cmo_fault_time; /* CMO page fault time */
+ u8 reserved10[104];
+
+ /* cacheline 4-5 */
+
+ u32 page_ins; /* CMO Hint - # page ins by OS */
+ u8 reserved11[148];
+ volatile u64 dtl_idx; /* Dispatch Trace Log head index */
+ u8 reserved12[96];
} __attribute__((__aligned__(0x400)));
extern struct lppaca lppaca[];
@@ -172,13 +112,13 @@ extern struct lppaca lppaca[];
* ESID is stored in the lower 64bits, then the VSID.
*/
struct slb_shadow {
- u32 persistent; // Number of persistent SLBs x00-x03
- u32 buffer_length; // Total shadow buffer length x04-x07
- u64 reserved; // Alignment x08-x0f
+ u32 persistent; /* Number of persistent SLBs */
+ u32 buffer_length; /* Total shadow buffer length */
+ u64 reserved;
struct {
u64 esid;
u64 vsid;
- } save_area[SLB_NUM_BOLTED]; // x10-x40
+ } save_area[SLB_NUM_BOLTED];
} ____cacheline_aligned;
extern struct slb_shadow slb_shadow[];
diff --git a/arch/powerpc/include/asm/lv1call.h b/arch/powerpc/include/asm/lv1call.h
index 233f9ecae761..f5117674bf92 100644
--- a/arch/powerpc/include/asm/lv1call.h
+++ b/arch/powerpc/include/asm/lv1call.h
@@ -265,8 +265,8 @@ LV1_CALL(get_spe_irq_outlet, 2, 1, 78 )
LV1_CALL(set_spe_privilege_state_area_1_register, 3, 0, 79 )
LV1_CALL(create_repository_node, 6, 0, 90 )
LV1_CALL(read_repository_node, 5, 2, 91 )
-LV1_CALL(modify_repository_node_value, 6, 0, 92 )
-LV1_CALL(remove_repository_node, 4, 0, 93 )
+LV1_CALL(write_repository_node, 6, 0, 92 )
+LV1_CALL(delete_repository_node, 4, 0, 93 )
LV1_CALL(read_htab_entries, 2, 5, 95 )
LV1_CALL(set_dabr, 2, 0, 96 )
LV1_CALL(get_total_execution_time, 2, 1, 103 )
diff --git a/arch/powerpc/include/asm/pSeries_reconfig.h b/arch/powerpc/include/asm/pSeries_reconfig.h
index 23cd6cc30bcf..c07edfe98b98 100644
--- a/arch/powerpc/include/asm/pSeries_reconfig.h
+++ b/arch/powerpc/include/asm/pSeries_reconfig.h
@@ -13,6 +13,18 @@
#define PSERIES_RECONFIG_REMOVE 0x0002
#define PSERIES_DRCONF_MEM_ADD 0x0003
#define PSERIES_DRCONF_MEM_REMOVE 0x0004
+#define PSERIES_UPDATE_PROPERTY 0x0005
+
+/**
+ * pSeries_reconfig_notify - Notifier value structure for OFDT property updates
+ *
+ * @node: Device tree node which owns the property being updated
+ * @property: Updated property
+ */
+struct pSeries_reconfig_prop_update {
+ struct device_node *node;
+ struct property *property;
+};
#ifdef CONFIG_PPC_PSERIES
extern int pSeries_reconfig_notifier_register(struct notifier_block *);
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 50f73aa2ba21..15444204a3a1 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -369,7 +369,15 @@ BEGIN_FTR_SECTION \
END_FTR_SECTION_IFCLR(CPU_FTR_601)
#endif
-
+#ifdef CONFIG_PPC64
+#define MTOCRF(FXM, RS) \
+ BEGIN_FTR_SECTION_NESTED(848); \
+ mtcrf (FXM), (RS); \
+ FTR_SECTION_ELSE_NESTED(848); \
+ mtocrf (FXM), (RS); \
+ ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_NOEXECUTE, 848)
+#endif
+
/*
* This instruction is not implemented on the PPC 603 or 601; however, on
* the 403GCX and 405GP tlbia IS defined and tlbie is not.
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 8e2d0371fe1e..55e85631c42e 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -74,9 +74,6 @@ struct task_struct;
void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
void release_thread(struct task_struct *);
-/* Prepare to copy thread state - unlazy all lazy status */
-extern void prepare_to_copy(struct task_struct *tsk);
-
/* Create a new kernel thread. */
extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
@@ -386,7 +383,6 @@ extern unsigned long cpuidle_disable;
enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
extern int powersave_nap; /* set if nap mode can be used in idle loop */
-void cpu_idle_wait(void);
#ifdef CONFIG_PSERIES_IDLE
extern void update_smt_snooze_delay(int snooze);
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 84cc7840cd18..9c21ed42aba6 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -354,12 +354,6 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
#define PTRACE_GETREGS64 22
#define PTRACE_SETREGS64 23
-/* (old) PTRACE requests with inverted arguments */
-#define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */
-#define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */
-#define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */
-#define PPC_PTRACE_SETFPREGS 0x96 /* Set FPRs 0 - 31 */
-
/* Calls to trace a 64bit program from a 32bit program */
#define PPC_PTRACE_PEEKTEXT_3264 0x95
#define PPC_PTRACE_PEEKDATA_3264 0x94
diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h
index caf82d0a00de..1a6320290d26 100644
--- a/arch/powerpc/include/asm/switch_to.h
+++ b/arch/powerpc/include/asm/switch_to.h
@@ -21,7 +21,6 @@ extern void disable_kernel_fp(void);
extern void enable_kernel_fp(void);
extern void flush_fp_to_thread(struct task_struct *);
extern void enable_kernel_altivec(void);
-extern void giveup_altivec(struct task_struct *);
extern void load_up_altivec(struct task_struct *);
extern int emulate_altivec(struct pt_regs *);
extern void __giveup_vsx(struct task_struct *);
@@ -40,10 +39,15 @@ static inline void discard_lazy_cpu_state(void)
#ifdef CONFIG_ALTIVEC
extern void flush_altivec_to_thread(struct task_struct *);
+extern void giveup_altivec(struct task_struct *);
+extern void giveup_altivec_notask(void);
#else
static inline void flush_altivec_to_thread(struct task_struct *t)
{
}
+static inline void giveup_altivec(struct task_struct *t)
+{
+}
#endif
#ifdef CONFIG_VSX
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index 4a741c7efd02..a556ccc16b58 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -62,21 +62,8 @@ struct thread_info {
#define init_thread_info (init_thread_union.thread_info)
#define init_stack (init_thread_union.stack)
-/* thread information allocation */
-
-#if THREAD_SHIFT >= PAGE_SHIFT
-
#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
-#else /* THREAD_SHIFT < PAGE_SHIFT */
-
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-
-extern struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node);
-extern void free_thread_info(struct thread_info *ti);
-
-#endif /* THREAD_SHIFT < PAGE_SHIFT */
-
/* how to get the thread information struct from C */
static inline struct thread_info *current_thread_info(void)
{
@@ -126,7 +113,6 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NOERROR (1<<TIF_NOERROR)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
-#define _TIF_RUNLATCH (1<<TIF_RUNLATCH)
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
_TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
index c97185885c6d..852ed1b384f6 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -18,12 +18,6 @@ struct device_node;
*/
#define RECLAIM_DISTANCE 10
-/*
- * Avoid creating an extra level of balancing (SD_ALLNODES) on the largest
- * POWER7 boxes which have a maximum of 32 nodes.
- */
-#define SD_NODES_PER_DOMAIN 32
-
#include <asm/mmzone.h>
static inline int cpu_to_node(int cpu)
@@ -51,36 +45,6 @@ static inline int pcibus_to_node(struct pci_bus *bus)
cpu_all_mask : \
cpumask_of_node(pcibus_to_node(bus)))
-/* sched_domains SD_NODE_INIT for PPC64 machines */
-#define SD_NODE_INIT (struct sched_domain) { \
- .min_interval = 8, \
- .max_interval = 32, \
- .busy_factor = 32, \
- .imbalance_pct = 125, \
- .cache_nice_tries = 1, \
- .busy_idx = 3, \
- .idle_idx = 1, \
- .newidle_idx = 0, \
- .wake_idx = 0, \
- .forkexec_idx = 0, \
- \
- .flags = 1*SD_LOAD_BALANCE \
- | 0*SD_BALANCE_NEWIDLE \
- | 1*SD_BALANCE_EXEC \
- | 1*SD_BALANCE_FORK \
- | 0*SD_BALANCE_WAKE \
- | 1*SD_WAKE_AFFINE \
- | 0*SD_PREFER_LOCAL \
- | 0*SD_SHARE_CPUPOWER \
- | 0*SD_POWERSAVINGS_BALANCE \
- | 0*SD_SHARE_PKG_RESOURCES \
- | 1*SD_SERIALIZE \
- | 0*SD_PREFER_SIBLING \
- , \
- .last_balance = jiffies, \
- .balance_interval = 1, \
-}
-
extern int __node_distance(int, int);
#define node_distance(a, b) __node_distance(a, b)
diff --git a/arch/powerpc/include/asm/vio.h b/arch/powerpc/include/asm/vio.h
index 6bfd5ffe1d4f..b19adf751dd9 100644
--- a/arch/powerpc/include/asm/vio.h
+++ b/arch/powerpc/include/asm/vio.h
@@ -46,6 +46,48 @@
struct iommu_table;
+/*
+ * Platform Facilities Option (PFO)-specific data
+ */
+
+/* Starting unit address for PFO devices on the VIO BUS */
+#define VIO_BASE_PFO_UA 0x50000000
+
+/**
+ * vio_pfo_op - PFO operation parameters
+ *
+ * @flags: h_call subfunctions and modifiers
+ * @in: Input data block logical real address
+ * @inlen: If non-negative, the length of the input data block. If negative,
+ * the length of the input data descriptor list in bytes.
+ * @out: Output data block logical real address
+ * @outlen: If non-negative, the length of the input data block. If negative,
+ * the length of the input data descriptor list in bytes.
+ * @csbcpb: Logical real address of the 4k naturally-aligned storage block
+ * containing the CSB & optional FC field specific CPB
+ * @timeout: # of milliseconds to retry h_call, 0 for no timeout.
+ * @hcall_err: pointer to return the h_call return value, else NULL
+ */
+struct vio_pfo_op {
+ u64 flags;
+ s64 in;
+ s64 inlen;
+ s64 out;
+ s64 outlen;
+ u64 csbcpb;
+ void *done;
+ unsigned long handle;
+ unsigned int timeout;
+ long hcall_err;
+};
+
+/* End PFO specific data */
+
+enum vio_dev_family {
+ VDEVICE, /* The OF node is a child of /vdevice */
+ PFO, /* The OF node is a child of /ibm,platform-facilities */
+};
+
/**
* vio_dev - This structure is used to describe virtual I/O devices.
*
@@ -58,6 +100,7 @@ struct vio_dev {
const char *name;
const char *type;
uint32_t unit_address;
+ uint32_t resource_id;
unsigned int irq;
struct {
size_t desired;
@@ -65,6 +108,7 @@ struct vio_dev {
size_t allocated;
atomic_t allocs_failed;
} cmo;
+ enum vio_dev_family family;
struct device dev;
};
@@ -95,6 +139,8 @@ extern void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired);
extern void __devinit vio_unregister_device(struct vio_dev *dev);
+extern int vio_h_cop_sync(struct vio_dev *vdev, struct vio_pfo_op *op);
+
struct device_node;
extern struct vio_dev *vio_register_device_node(
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index f5808a35688c..83afacd3ba7b 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -28,7 +28,7 @@ endif
obj-y := cputable.o ptrace.o syscalls.o \
irq.o align.o signal_32.o pmc.o vdso.o \
- init_task.o process.o systbl.o idle.o \
+ process.o systbl.o idle.o \
signal.o sysfs.o cacheinfo.o time.o \
prom.o traps.o setup-common.o \
udbg.o misc.o io.o dma.o \
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 34b8afe94a50..4554dc2fe857 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -188,10 +188,6 @@ int main(void)
DEFINE(SLBSHADOW_STACKESID,
offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid));
DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area));
- DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0));
- DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1));
- DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int));
- DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int));
DEFINE(LPPACA_PMCINUSE, offsetof(struct lppaca, pmcregs_in_use));
DEFINE(LPPACA_DTLIDX, offsetof(struct lppaca, dtl_idx));
DEFINE(LPPACA_YIELDCOUNT, offsetof(struct lppaca, yield_count));
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index ef2074c3e906..ed1718feb9d9 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -63,15 +63,9 @@ system_call_common:
std r0,GPR0(r1)
std r10,GPR1(r1)
ACCOUNT_CPU_USER_ENTRY(r10, r11)
- /*
- * This "crclr so" clears CR0.SO, which is the error indication on
- * return from this system call. There must be no cmp instruction
- * between it and the "mfcr r9" below, otherwise if XER.SO is set,
- * CR0.SO will get set, causing all system calls to appear to fail.
- */
- crclr so
std r2,GPR2(r1)
std r3,GPR3(r1)
+ mfcr r2
std r4,GPR4(r1)
std r5,GPR5(r1)
std r6,GPR6(r1)
@@ -82,18 +76,20 @@ system_call_common:
std r11,GPR10(r1)
std r11,GPR11(r1)
std r11,GPR12(r1)
+ std r11,_XER(r1)
+ std r11,_CTR(r1)
std r9,GPR13(r1)
- mfcr r9
mflr r10
+ /*
+ * This clears CR0.SO (bit 28), which is the error indication on
+ * return from this system call.
+ */
+ rldimi r2,r11,28,(63-28)
li r11,0xc01
- std r9,_CCR(r1)
std r10,_LINK(r1)
std r11,_TRAP(r1)
- mfxer r9
- mfctr r10
- std r9,_XER(r1)
- std r10,_CTR(r1)
std r3,ORIG_GPR3(r1)
+ std r2,_CCR(r1)
ld r2,PACATOC(r13)
addi r9,r1,STACK_FRAME_OVERHEAD
ld r11,exception_marker@toc(r2)
@@ -154,7 +150,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
ld r10,TI_FLAGS(r11)
andi. r11,r10,_TIF_SYSCALL_T_OR_A
bne- syscall_dotrace
-syscall_dotrace_cont:
+.Lsyscall_dotrace_cont:
cmpldi 0,r0,NR_syscalls
bge- syscall_enosys
@@ -211,7 +207,7 @@ syscall_exit:
cmpld r3,r11
ld r5,_CCR(r1)
bge- syscall_error
-syscall_error_cont:
+.Lsyscall_error_cont:
ld r7,_NIP(r1)
BEGIN_FTR_SECTION
stdcx. r0,0,r1 /* to clear the reservation */
@@ -246,7 +242,7 @@ syscall_error:
oris r5,r5,0x1000 /* Set SO bit in CR */
neg r3,r3
std r5,_CCR(r1)
- b syscall_error_cont
+ b .Lsyscall_error_cont
/* Traced system call support */
syscall_dotrace:
@@ -268,7 +264,7 @@ syscall_dotrace:
addi r9,r1,STACK_FRAME_OVERHEAD
clrrdi r10,r1,THREAD_SHIFT
ld r10,TI_FLAGS(r10)
- b syscall_dotrace_cont
+ b .Lsyscall_dotrace_cont
syscall_enosys:
li r3,-ENOSYS
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 8f880bc77c56..f7bed44ee165 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -94,12 +94,10 @@ machine_check_pSeries_1:
data_access_pSeries:
HMT_MEDIUM
SET_SCRATCH0(r13)
-#ifndef CONFIG_POWER4_ONLY
BEGIN_FTR_SECTION
b data_access_check_stab
data_access_not_stab:
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
-#endif
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD,
KVMTEST, 0x300)
@@ -301,7 +299,6 @@ machine_check_fwnmi:
EXC_STD, KVMTEST, 0x200)
KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200)
-#ifndef CONFIG_POWER4_ONLY
/* moved from 0x300 */
data_access_check_stab:
GET_PACA(r13)
@@ -328,7 +325,6 @@ do_stab_bolted_pSeries:
GET_SCRATCH0(r10)
std r10,PACA_EXSLB+EX_R13(r13)
EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted, EXC_STD)
-#endif /* CONFIG_POWER4_ONLY */
KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x300)
KVM_HANDLER_SKIP(PACA_EXSLB, EXC_STD, 0x380)
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index 7dd2981bcc50..22d608e8bb7d 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -778,14 +778,6 @@ _GLOBAL(__fixup_440A_mcheck)
blr
/*
- * extern void giveup_altivec(struct task_struct *prev)
- *
- * The 44x core does not have an AltiVec unit.
- */
-_GLOBAL(giveup_altivec)
- blr
-
-/*
* extern void giveup_fpu(struct task_struct *prev)
*
* The 44x core does not have an FPU.
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 28e62598d0e8..de80e0f9a2bd 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -874,14 +874,6 @@ _GLOBAL(__setup_e500mc_ivors)
sync
blr
-/*
- * extern void giveup_altivec(struct task_struct *prev)
- *
- * The e500 core does not have an AltiVec unit.
- */
-_GLOBAL(giveup_altivec)
- blr
-
#ifdef CONFIG_SPE
/*
* extern void giveup_spe(struct task_struct *prev)
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index 6d2209ac0c44..2099d9a879e8 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -113,29 +113,6 @@ void cpu_idle(void)
}
}
-
-/*
- * cpu_idle_wait - Used to ensure that all the CPUs come out of the old
- * idle loop and start using the new idle loop.
- * Required while changing idle handler on SMP systems.
- * Caller must have changed idle handler to the new value before the call.
- * This window may be larger on shared systems.
- */
-void cpu_idle_wait(void)
-{
- int cpu;
- smp_mb();
-
- /* kick all the CPUs so that they exit out of old idle routine */
- get_online_cpus();
- for_each_online_cpu(cpu) {
- if (cpu != smp_processor_id())
- smp_send_reschedule(cpu);
- }
- put_online_cpus();
-}
-EXPORT_SYMBOL_GPL(cpu_idle_wait);
-
int powersave_nap;
#ifdef CONFIG_SYSCTL
diff --git a/arch/powerpc/kernel/init_task.c b/arch/powerpc/kernel/init_task.c
deleted file mode 100644
index d076d465dbd1..000000000000
--- a/arch/powerpc/kernel/init_task.c
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <linux/mm.h>
-#include <linux/export.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-#include <asm/uaccess.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is 16384-byte aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 641da9e868ce..7835a5e1ea5f 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -587,7 +587,7 @@ int irq_choose_cpu(const struct cpumask *mask)
{
int cpuid;
- if (cpumask_equal(mask, cpu_all_mask)) {
+ if (cpumask_equal(mask, cpu_online_mask)) {
static int irq_rover;
static DEFINE_RAW_SPINLOCK(irq_rover_lock);
unsigned long flags;
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 7cd07b42ca1a..386d57f66f28 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -738,8 +738,23 @@ relocate_new_kernel:
mr r5, r31
li r0, 0
-#elif defined(CONFIG_44x) && !defined(CONFIG_PPC_47x)
+#elif defined(CONFIG_44x)
+ /* Save our parameters */
+ mr r29, r3
+ mr r30, r4
+ mr r31, r5
+
+#ifdef CONFIG_PPC_47x
+ /* Check for 47x cores */
+ mfspr r3,SPRN_PVR
+ srwi r3,r3,16
+ cmplwi cr0,r3,PVR_476@h
+ beq setup_map_47x
+ cmplwi cr0,r3,PVR_476_ISS@h
+ beq setup_map_47x
+#endif /* CONFIG_PPC_47x */
+
/*
* Code for setting up 1:1 mapping for PPC440x for KEXEC
*
@@ -753,16 +768,15 @@ relocate_new_kernel:
* 5) Invalidate the tmp mapping.
*
* - Based on the kexec support code for FSL BookE
- * - Doesn't support 47x yet.
*
*/
- /* Save our parameters */
- mr r29, r3
- mr r30, r4
- mr r31, r5
- /* Load our MSR_IS and TID to MMUCR for TLB search */
- mfspr r3,SPRN_PID
+ /*
+ * Load the PID with kernel PID (0).
+ * Also load our MSR_IS and TID to MMUCR for TLB search.
+ */
+ li r3, 0
+ mtspr SPRN_PID, r3
mfmsr r4
andi. r4,r4,MSR_IS@l
beq wmmucr
@@ -900,6 +914,179 @@ next_tlb:
li r3, 0
tlbwe r3, r24, PPC44x_TLB_PAGEID
sync
+ b ppc44x_map_done
+
+#ifdef CONFIG_PPC_47x
+
+ /* 1:1 mapping for 47x */
+
+setup_map_47x:
+
+ /*
+ * Load the kernel pid (0) to PID and also to MMUCR[TID].
+ * Also set the MSR IS->MMUCR STS
+ */
+ li r3, 0
+ mtspr SPRN_PID, r3 /* Set PID */
+ mfmsr r4 /* Get MSR */
+ andi. r4, r4, MSR_IS@l /* TS=1? */
+ beq 1f /* If not, leave STS=0 */
+ oris r3, r3, PPC47x_MMUCR_STS@h /* Set STS=1 */
+1: mtspr SPRN_MMUCR, r3 /* Put MMUCR */
+ sync
+
+ /* Find the entry we are running from */
+ bl 2f
+2: mflr r23
+ tlbsx r23, 0, r23
+ tlbre r24, r23, 0 /* TLB Word 0 */
+ tlbre r25, r23, 1 /* TLB Word 1 */
+ tlbre r26, r23, 2 /* TLB Word 2 */
+
+
+ /*
+ * Invalidates all the tlb entries by writing to 256 RPNs(r4)
+ * of 4k page size in all 4 ways (0-3 in r3).
+ * This would invalidate the entire UTLB including the one we are
+ * running from. However the shadow TLB entries would help us
+ * to continue the execution, until we flush them (rfi/isync).
+ */
+ addis r3, 0, 0x8000 /* specify the way */
+ addi r4, 0, 0 /* TLB Word0 = (EPN=0, VALID = 0) */
+ addi r5, 0, 0
+ b clear_utlb_entry
+
+ /* Align the loop to speed things up. from head_44x.S */
+ .align 6
+
+clear_utlb_entry:
+
+ tlbwe r4, r3, 0
+ tlbwe r5, r3, 1
+ tlbwe r5, r3, 2
+ addis r3, r3, 0x2000 /* Increment the way */
+ cmpwi r3, 0
+ bne clear_utlb_entry
+ addis r3, 0, 0x8000
+ addis r4, r4, 0x100 /* Increment the EPN */
+ cmpwi r4, 0
+ bne clear_utlb_entry
+
+ /* Create the entries in the other address space */
+ mfmsr r5
+ rlwinm r7, r5, 27, 31, 31 /* Get the TS (Bit 26) from MSR */
+ xori r7, r7, 1 /* r7 = !TS */
+
+ insrwi r24, r7, 1, 21 /* Change the TS in the saved TLB word 0 */
+
+ /*
+ * write out the TLB entries for the tmp mapping
+ * Use way '0' so that we could easily invalidate it later.
+ */
+ lis r3, 0x8000 /* Way '0' */
+
+ tlbwe r24, r3, 0
+ tlbwe r25, r3, 1
+ tlbwe r26, r3, 2
+
+ /* Update the msr to the new TS */
+ insrwi r5, r7, 1, 26
+
+ bl 1f
+1: mflr r6
+ addi r6, r6, (2f-1b)
+
+ mtspr SPRN_SRR0, r6
+ mtspr SPRN_SRR1, r5
+ rfi
+
+ /*
+ * Now we are in the tmp address space.
+ * Create a 1:1 mapping for 0-2GiB in the original TS.
+ */
+2:
+ li r3, 0
+ li r4, 0 /* TLB Word 0 */
+ li r5, 0 /* TLB Word 1 */
+ li r6, 0
+ ori r6, r6, PPC47x_TLB2_S_RWX /* TLB word 2 */
+
+ li r8, 0 /* PageIndex */
+
+ xori r7, r7, 1 /* revert back to original TS */
+
+write_utlb:
+ rotlwi r5, r8, 28 /* RPN = PageIndex * 256M */
+ /* ERPN = 0 as we don't use memory above 2G */
+
+ mr r4, r5 /* EPN = RPN */
+ ori r4, r4, (PPC47x_TLB0_VALID | PPC47x_TLB0_256M)
+ insrwi r4, r7, 1, 21 /* Insert the TS to Word 0 */
+
+ tlbwe r4, r3, 0 /* Write out the entries */
+ tlbwe r5, r3, 1
+ tlbwe r6, r3, 2
+ addi r8, r8, 1
+ cmpwi r8, 8 /* Have we completed ? */
+ bne write_utlb
+
+ /* make sure we complete the TLB write up */
+ isync
+
+ /*
+ * Prepare to jump to the 1:1 mapping.
+ * 1) Extract page size of the tmp mapping
+ * DSIZ = TLB_Word0[22:27]
+ * 2) Calculate the physical address of the address
+ * to jump to.
+ */
+ rlwinm r10, r24, 0, 22, 27
+
+ cmpwi r10, PPC47x_TLB0_4K
+ bne 0f
+ li r10, 0x1000 /* r10 = 4k */
+ bl 1f
+
+0:
+ /* Defaults to 256M */
+ lis r10, 0x1000
+
+ bl 1f
+1: mflr r4
+ addi r4, r4, (2f-1b) /* virtual address of 2f */
+
+ subi r11, r10, 1 /* offsetmask = Pagesize - 1 */
+ not r10, r11 /* Pagemask = ~(offsetmask) */
+
+ and r5, r25, r10 /* Physical page */
+ and r6, r4, r11 /* offset within the current page */
+
+ or r5, r5, r6 /* Physical address for 2f */
+
+ /* Switch the TS in MSR to the original one */
+ mfmsr r8
+ insrwi r8, r7, 1, 26
+
+ mtspr SPRN_SRR1, r8
+ mtspr SPRN_SRR0, r5
+ rfi
+
+2:
+ /* Invalidate the tmp mapping */
+ lis r3, 0x8000 /* Way '0' */
+
+ clrrwi r24, r24, 12 /* Clear the valid bit */
+ tlbwe r24, r3, 0
+ tlbwe r25, r3, 1
+ tlbwe r26, r3, 2
+
+ /* Make sure we complete the TLB write and flush the shadow TLB */
+ isync
+
+#endif
+
+ppc44x_map_done:
+
/* Restore the parameters */
mr r3, r29
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 0bb1f98613ba..fbe1a12dc7f1 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -36,10 +36,7 @@ struct lppaca lppaca[] = {
[0 ... (NR_LPPACAS-1)] = {
.desc = 0xd397d781, /* "LpPa" */
.size = sizeof(struct lppaca),
- .dyn_proc_status = 2,
- .decr_val = 0x00ff0000,
.fpregs_in_use = 1,
- .end_of_quantum = 0xfffffffffffffffful,
.slb_count = 64,
.vmxregs_in_use = 0,
.page_ins = 0,
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 4937c9690090..710f400476de 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -124,7 +124,7 @@ void enable_kernel_altivec(void)
if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
giveup_altivec(current);
else
- giveup_altivec(NULL); /* just enable AltiVec for kernel - force */
+ giveup_altivec_notask();
#else
giveup_altivec(last_task_used_altivec);
#endif /* CONFIG_SMP */
@@ -711,18 +711,21 @@ release_thread(struct task_struct *t)
}
/*
- * This gets called before we allocate a new thread and copy
- * the current task into it.
+ * this gets called so that we can store coprocessor state into memory and
+ * copy the current task into the new thread.
*/
-void prepare_to_copy(struct task_struct *tsk)
+int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
- flush_fp_to_thread(current);
- flush_altivec_to_thread(current);
- flush_vsx_to_thread(current);
- flush_spe_to_thread(current);
+ flush_fp_to_thread(src);
+ flush_altivec_to_thread(src);
+ flush_vsx_to_thread(src);
+ flush_spe_to_thread(src);
#ifdef CONFIG_HAVE_HW_BREAKPOINT
- flush_ptrace_hw_breakpoint(tsk);
+ flush_ptrace_hw_breakpoint(src);
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+
+ *dst = *src;
+ return 0;
}
/*
@@ -1252,37 +1255,6 @@ void __ppc64_runlatch_off(void)
}
#endif /* CONFIG_PPC64 */
-#if THREAD_SHIFT < PAGE_SHIFT
-
-static struct kmem_cache *thread_info_cache;
-
-struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
-{
- struct thread_info *ti;
-
- ti = kmem_cache_alloc_node(thread_info_cache, GFP_KERNEL, node);
- if (unlikely(ti == NULL))
- return NULL;
-#ifdef CONFIG_DEBUG_STACK_USAGE
- memset(ti, 0, THREAD_SIZE);
-#endif
- return ti;
-}
-
-void free_thread_info(struct thread_info *ti)
-{
- kmem_cache_free(thread_info_cache, ti);
-}
-
-void thread_info_cache_init(void)
-{
- thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
- THREAD_SIZE, 0, NULL);
- BUG_ON(thread_info_cache == NULL);
-}
-
-#endif /* THREAD_SHIFT < PAGE_SHIFT */
-
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 99860273211b..1b488e5305c5 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -680,6 +680,9 @@ static void __init early_cmdline_parse(void)
#define OV3_VMX 0x40 /* VMX/Altivec */
#define OV3_DFP 0x20 /* decimal FP */
+/* Option vector 4: IBM PAPR implementation */
+#define OV4_MIN_ENT_CAP 0x01 /* minimum VP entitled capacity */
+
/* Option vector 5: PAPR/OF options supported */
#define OV5_LPAR 0x80 /* logical partitioning supported */
#define OV5_SPLPAR 0x40 /* shared-processor LPAR supported */
@@ -701,6 +704,8 @@ static void __init early_cmdline_parse(void)
#define OV5_XCMO 0x00
#endif
#define OV5_TYPE1_AFFINITY 0x80 /* Type 1 NUMA affinity */
+#define OV5_PFO_HW_RNG 0x80 /* PFO Random Number Generator */
+#define OV5_PFO_HW_ENCR 0x20 /* PFO Encryption Accelerator */
/* Option Vector 6: IBM PAPR hints */
#define OV6_LINUX 0x02 /* Linux is our OS */
@@ -744,11 +749,12 @@ static unsigned char ibm_architecture_vec[] = {
OV3_FP | OV3_VMX | OV3_DFP,
/* option vector 4: IBM PAPR implementation */
- 2 - 2, /* length */
+ 3 - 2, /* length */
0, /* don't halt */
+ OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
/* option vector 5: PAPR/OF options */
- 13 - 2, /* length */
+ 18 - 2, /* length */
0, /* don't ignore, don't halt */
OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
OV5_DONATE_DEDICATE_CPU | OV5_MSI,
@@ -762,8 +768,13 @@ static unsigned char ibm_architecture_vec[] = {
* must match by the macro below. Update the definition if
* the structure layout changes.
*/
-#define IBM_ARCH_VEC_NRCORES_OFFSET 100
+#define IBM_ARCH_VEC_NRCORES_OFFSET 101
W(NR_CPUS), /* number of cores supported */
+ 0,
+ 0,
+ 0,
+ 0,
+ OV5_PFO_HW_RNG | OV5_PFO_HW_ENCR,
/* option vector 6: IBM PAPR hints */
4 - 2, /* length */
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 8d8e028893be..c10fc28b9092 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1432,40 +1432,6 @@ static long ppc_del_hwdebug(struct task_struct *child, long addr, long data)
#endif
}
-/*
- * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
- * we mark them as obsolete now, they will be removed in a future version
- */
-static long arch_ptrace_old(struct task_struct *child, long request,
- unsigned long addr, unsigned long data)
-{
- void __user *datavp = (void __user *) data;
-
- switch (request) {
- case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
- return copy_regset_to_user(child, &user_ppc_native_view,
- REGSET_GPR, 0, 32 * sizeof(long),
- datavp);
-
- case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
- return copy_regset_from_user(child, &user_ppc_native_view,
- REGSET_GPR, 0, 32 * sizeof(long),
- datavp);
-
- case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
- return copy_regset_to_user(child, &user_ppc_native_view,
- REGSET_FPR, 0, 32 * sizeof(double),
- datavp);
-
- case PPC_PTRACE_SETFPREGS: /* Set FPRs 0 - 31. */
- return copy_regset_from_user(child, &user_ppc_native_view,
- REGSET_FPR, 0, 32 * sizeof(double),
- datavp);
- }
-
- return -EPERM;
-}
-
long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{
@@ -1687,14 +1653,6 @@ long arch_ptrace(struct task_struct *child, long request,
datavp);
#endif
- /* Old reverse args ptrace callss */
- case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
- case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
- case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
- case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */
- ret = arch_ptrace_old(child, request, addr, data);
- break;
-
default:
ret = ptrace_request(child, request, addr, data);
break;
@@ -1710,7 +1668,7 @@ long do_syscall_trace_enter(struct pt_regs *regs)
{
long ret = 0;
- secure_computing(regs->gpr[0]);
+ secure_computing_strict(regs->gpr[0]);
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
tracehook_report_syscall_entry(regs))
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index 469349d14a97..8c21658719d9 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -39,30 +39,6 @@
* in exit.c or in signal.c.
*/
-/*
- * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
- * we mark them as obsolete now, they will be removed in a future version
- */
-static long compat_ptrace_old(struct task_struct *child, long request,
- long addr, long data)
-{
- switch (request) {
- case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
- return copy_regset_to_user(child,
- task_user_regset_view(current), 0,
- 0, 32 * sizeof(compat_long_t),
- compat_ptr(data));
-
- case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
- return copy_regset_from_user(child,
- task_user_regset_view(current), 0,
- 0, 32 * sizeof(compat_long_t),
- compat_ptr(data));
- }
-
- return -EPERM;
-}
-
/* Macros to workout the correct index for the FPR in the thread struct */
#define FPRNUMBER(i) (((i) - PT_FPR0) >> 1)
#define FPRHALF(i) (((i) - PT_FPR0) & 1)
@@ -308,8 +284,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
case PTRACE_SETVSRREGS:
case PTRACE_GETREGS64:
case PTRACE_SETREGS64:
- case PPC_PTRACE_GETFPREGS:
- case PPC_PTRACE_SETFPREGS:
case PTRACE_KILL:
case PTRACE_SINGLESTEP:
case PTRACE_DETACH:
@@ -322,12 +296,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
ret = arch_ptrace(child, request, addr, data);
break;
- /* Old reverse args ptrace callss */
- case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
- case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
- ret = compat_ptrace_old(child, request, addr, data);
- break;
-
default:
ret = compat_ptrace_request(child, request, addr, data);
break;
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index d9f94410fd7f..e4cb34322de4 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -57,27 +57,9 @@
#define DBG(fmt...)
#endif
-
-/* Store all idle threads, this can be reused instead of creating
-* a new thread. Also avoids complicated thread destroy functionality
-* for idle threads.
-*/
#ifdef CONFIG_HOTPLUG_CPU
-/*
- * Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is
- * removed after init for !CONFIG_HOTPLUG_CPU.
- */
-static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
-#define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x))
-#define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p))
-
/* State of each CPU during hotplug phases */
static DEFINE_PER_CPU(int, cpu_state) = { 0 };
-
-#else
-static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
-#define get_idle_for_cpu(x) (idle_thread_array[(x)])
-#define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p))
#endif
struct thread_info *secondary_ti;
@@ -429,60 +411,19 @@ int generic_check_cpu_restart(unsigned int cpu)
}
#endif
-struct create_idle {
- struct work_struct work;
- struct task_struct *idle;
- struct completion done;
- int cpu;
-};
-
-static void __cpuinit do_fork_idle(struct work_struct *work)
+static void cpu_idle_thread_init(unsigned int cpu, struct task_struct *idle)
{
- struct create_idle *c_idle =
- container_of(work, struct create_idle, work);
-
- c_idle->idle = fork_idle(c_idle->cpu);
- complete(&c_idle->done);
-}
-
-static int __cpuinit create_idle(unsigned int cpu)
-{
- struct thread_info *ti;
- struct create_idle c_idle = {
- .cpu = cpu,
- .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
- };
- INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle);
-
- c_idle.idle = get_idle_for_cpu(cpu);
-
- /* We can't use kernel_thread since we must avoid to
- * reschedule the child. We use a workqueue because
- * we want to fork from a kernel thread, not whatever
- * userspace process happens to be trying to online us.
- */
- if (!c_idle.idle) {
- schedule_work(&c_idle.work);
- wait_for_completion(&c_idle.done);
- } else
- init_idle(c_idle.idle, cpu);
- if (IS_ERR(c_idle.idle)) {
- pr_err("Failed fork for CPU %u: %li", cpu, PTR_ERR(c_idle.idle));
- return PTR_ERR(c_idle.idle);
- }
- ti = task_thread_info(c_idle.idle);
+ struct thread_info *ti = task_thread_info(idle);
#ifdef CONFIG_PPC64
- paca[cpu].__current = c_idle.idle;
+ paca[cpu].__current = idle;
paca[cpu].kstack = (unsigned long)ti + THREAD_SIZE - STACK_FRAME_OVERHEAD;
#endif
ti->cpu = cpu;
- current_set[cpu] = ti;
-
- return 0;
+ secondary_ti = current_set[cpu] = ti;
}
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
int rc, c;
@@ -490,12 +431,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
(smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
return -EINVAL;
- /* Make sure we have an idle thread */
- rc = create_idle(cpu);
- if (rc)
- return rc;
-
- secondary_ti = current_set[cpu];
+ cpu_idle_thread_init(cpu, tidle);
/* Make sure callin-map entry is 0 (can be leftover a CPU
* hotplug
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S
index 4d5a3edff49e..e830289d2e48 100644
--- a/arch/powerpc/kernel/vector.S
+++ b/arch/powerpc/kernel/vector.S
@@ -89,6 +89,16 @@ _GLOBAL(load_up_altivec)
/* restore registers and return */
blr
+_GLOBAL(giveup_altivec_notask)
+ mfmsr r3
+ andis. r4,r3,MSR_VEC@h
+ bnelr /* Already enabled? */
+ oris r3,r3,MSR_VEC@h
+ SYNC
+ MTMSRD(r3) /* enable use of VMX now */
+ isync
+ blr
+
/*
* giveup_altivec(tsk)
* Disable VMX for the task given as the argument,
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index a3a99901c8ec..cb87301ccd55 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -14,7 +14,9 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/cpu.h>
#include <linux/types.h>
+#include <linux/delay.h>
#include <linux/stat.h>
#include <linux/device.h>
#include <linux/init.h>
@@ -709,13 +711,26 @@ static int vio_cmo_bus_probe(struct vio_dev *viodev)
struct vio_driver *viodrv = to_vio_driver(dev->driver);
unsigned long flags;
size_t size;
+ bool dma_capable = false;
+
+ /* A device requires entitlement if it has a DMA window property */
+ switch (viodev->family) {
+ case VDEVICE:
+ if (of_get_property(viodev->dev.of_node,
+ "ibm,my-dma-window", NULL))
+ dma_capable = true;
+ break;
+ case PFO:
+ dma_capable = false;
+ break;
+ default:
+ dev_warn(dev, "unknown device family: %d\n", viodev->family);
+ BUG();
+ break;
+ }
- /*
- * Check to see that device has a DMA window and configure
- * entitlement for the device.
- */
- if (of_get_property(viodev->dev.of_node,
- "ibm,my-dma-window", NULL)) {
+ /* Configure entitlement for the device. */
+ if (dma_capable) {
/* Check that the driver is CMO enabled and get desired DMA */
if (!viodrv->get_desired_dma) {
dev_err(dev, "%s: device driver does not support CMO\n",
@@ -1050,6 +1065,94 @@ static void vio_cmo_sysfs_init(void) { }
EXPORT_SYMBOL(vio_cmo_entitlement_update);
EXPORT_SYMBOL(vio_cmo_set_dev_desired);
+
+/*
+ * Platform Facilities Option (PFO) support
+ */
+
+/**
+ * vio_h_cop_sync - Perform a synchronous PFO co-processor operation
+ *
+ * @vdev - Pointer to a struct vio_dev for device
+ * @op - Pointer to a struct vio_pfo_op for the operation parameters
+ *
+ * Calls the hypervisor to synchronously perform the PFO operation
+ * described in @op. In the case of a busy response from the hypervisor,
+ * the operation will be re-submitted indefinitely unless a non-zero timeout
+ * is specified or an error occurs. The timeout places a limit on when to
+ * stop re-submitting a operation, the total time can be exceeded if an
+ * operation is in progress.
+ *
+ * If op->hcall_ret is not NULL, this will be set to the return from the
+ * last h_cop_op call or it will be 0 if an error not involving the h_call
+ * was encountered.
+ *
+ * Returns:
+ * 0 on success,
+ * -EINVAL if the h_call fails due to an invalid parameter,
+ * -E2BIG if the h_call can not be performed synchronously,
+ * -EBUSY if a timeout is specified and has elapsed,
+ * -EACCES if the memory area for data/status has been rescinded, or
+ * -EPERM if a hardware fault has been indicated
+ */
+int vio_h_cop_sync(struct vio_dev *vdev, struct vio_pfo_op *op)
+{
+ struct device *dev = &vdev->dev;
+ unsigned long deadline = 0;
+ long hret = 0;
+ int ret = 0;
+
+ if (op->timeout)
+ deadline = jiffies + msecs_to_jiffies(op->timeout);
+
+ while (true) {
+ hret = plpar_hcall_norets(H_COP, op->flags,
+ vdev->resource_id,
+ op->in, op->inlen, op->out,
+ op->outlen, op->csbcpb);
+
+ if (hret == H_SUCCESS ||
+ (hret != H_NOT_ENOUGH_RESOURCES &&
+ hret != H_BUSY && hret != H_RESOURCE) ||
+ (op->timeout && time_after(deadline, jiffies)))
+ break;
+
+ dev_dbg(dev, "%s: hcall ret(%ld), retrying.\n", __func__, hret);
+ }
+
+ switch (hret) {
+ case H_SUCCESS:
+ ret = 0;
+ break;
+ case H_OP_MODE:
+ case H_TOO_BIG:
+ ret = -E2BIG;
+ break;
+ case H_RESCINDED:
+ ret = -EACCES;
+ break;
+ case H_HARDWARE:
+ ret = -EPERM;
+ break;
+ case H_NOT_ENOUGH_RESOURCES:
+ case H_RESOURCE:
+ case H_BUSY:
+ ret = -EBUSY;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret)
+ dev_dbg(dev, "%s: Sync h_cop_op failure (ret:%d) (hret:%ld)\n",
+ __func__, ret, hret);
+
+ op->hcall_err = hret;
+ return ret;
+}
+EXPORT_SYMBOL(vio_h_cop_sync);
+
static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
{
const unsigned char *dma_window;
@@ -1211,35 +1314,87 @@ static void __devinit vio_dev_release(struct device *dev)
struct vio_dev *vio_register_device_node(struct device_node *of_node)
{
struct vio_dev *viodev;
+ struct device_node *parent_node;
const unsigned int *unit_address;
+ const unsigned int *pfo_resid = NULL;
+ enum vio_dev_family family;
+ const char *of_node_name = of_node->name ? of_node->name : "<unknown>";
- /* we need the 'device_type' property, in order to match with drivers */
- if (of_node->type == NULL) {
- printk(KERN_WARNING "%s: node %s missing 'device_type'\n",
- __func__,
- of_node->name ? of_node->name : "<unknown>");
+ /*
+ * Determine if this node is a under the /vdevice node or under the
+ * /ibm,platform-facilities node. This decides the device's family.
+ */
+ parent_node = of_get_parent(of_node);
+ if (parent_node) {
+ if (!strcmp(parent_node->full_name, "/ibm,platform-facilities"))
+ family = PFO;
+ else if (!strcmp(parent_node->full_name, "/vdevice"))
+ family = VDEVICE;
+ else {
+ pr_warn("%s: parent(%s) of %s not recognized.\n",
+ __func__,
+ parent_node->full_name,
+ of_node_name);
+ of_node_put(parent_node);
+ return NULL;
+ }
+ of_node_put(parent_node);
+ } else {
+ pr_warn("%s: could not determine the parent of node %s.\n",
+ __func__, of_node_name);
return NULL;
}
- unit_address = of_get_property(of_node, "reg", NULL);
- if (unit_address == NULL) {
- printk(KERN_WARNING "%s: node %s missing 'reg'\n",
- __func__,
- of_node->name ? of_node->name : "<unknown>");
- return NULL;
+ if (family == PFO) {
+ if (of_get_property(of_node, "interrupt-controller", NULL)) {
+ pr_debug("%s: Skipping the interrupt controller %s.\n",
+ __func__, of_node_name);
+ return NULL;
+ }
}
/* allocate a vio_dev for this node */
viodev = kzalloc(sizeof(struct vio_dev), GFP_KERNEL);
- if (viodev == NULL)
+ if (viodev == NULL) {
+ pr_warn("%s: allocation failure for VIO device.\n", __func__);
return NULL;
+ }
- viodev->irq = irq_of_parse_and_map(of_node, 0);
+ /* we need the 'device_type' property, in order to match with drivers */
+ viodev->family = family;
+ if (viodev->family == VDEVICE) {
+ if (of_node->type != NULL)
+ viodev->type = of_node->type;
+ else {
+ pr_warn("%s: node %s is missing the 'device_type' "
+ "property.\n", __func__, of_node_name);
+ goto out;
+ }
+
+ unit_address = of_get_property(of_node, "reg", NULL);
+ if (unit_address == NULL) {
+ pr_warn("%s: node %s missing 'reg'\n",
+ __func__, of_node_name);
+ goto out;
+ }
+ dev_set_name(&viodev->dev, "%x", *unit_address);
+ viodev->irq = irq_of_parse_and_map(of_node, 0);
+ viodev->unit_address = *unit_address;
+ } else {
+ /* PFO devices need their resource_id for submitting COP_OPs
+ * This is an optional field for devices, but is required when
+ * performing synchronous ops */
+ pfo_resid = of_get_property(of_node, "ibm,resource-id", NULL);
+ if (pfo_resid != NULL)
+ viodev->resource_id = *pfo_resid;
+
+ unit_address = NULL;
+ dev_set_name(&viodev->dev, "%s", of_node_name);
+ viodev->type = of_node_name;
+ viodev->irq = 0;
+ }
- dev_set_name(&viodev->dev, "%x", *unit_address);
viodev->name = of_node->name;
- viodev->type = of_node->type;
- viodev->unit_address = *unit_address;
viodev->dev.of_node = of_node_get(of_node);
if (firmware_has_feature(FW_FEATURE_CMO))
@@ -1267,16 +1422,51 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
}
return viodev;
+
+out: /* Use this exit point for any return prior to device_register */
+ kfree(viodev);
+
+ return NULL;
}
EXPORT_SYMBOL(vio_register_device_node);
+/*
+ * vio_bus_scan_for_devices - Scan OF and register each child device
+ * @root_name - OF node name for the root of the subtree to search.
+ * This must be non-NULL
+ *
+ * Starting from the root node provide, register the device node for
+ * each child beneath the root.
+ */
+static void vio_bus_scan_register_devices(char *root_name)
+{
+ struct device_node *node_root, *node_child;
+
+ if (!root_name)
+ return;
+
+ node_root = of_find_node_by_name(NULL, root_name);
+ if (node_root) {
+
+ /*
+ * Create struct vio_devices for each virtual device in
+ * the device tree. Drivers will associate with them later.
+ */
+ node_child = of_get_next_child(node_root, NULL);
+ while (node_child) {
+ vio_register_device_node(node_child);
+ node_child = of_get_next_child(node_root, node_child);
+ }
+ of_node_put(node_root);
+ }
+}
+
/**
* vio_bus_init: - Initialize the virtual IO bus
*/
static int __init vio_bus_init(void)
{
int err;
- struct device_node *node_vroot;
if (firmware_has_feature(FW_FEATURE_CMO))
vio_cmo_sysfs_init();
@@ -1301,19 +1491,8 @@ static int __init vio_bus_init(void)
if (firmware_has_feature(FW_FEATURE_CMO))
vio_cmo_bus_init();
- node_vroot = of_find_node_by_name(NULL, "vdevice");
- if (node_vroot) {
- struct device_node *of_node;
-
- /*
- * Create struct vio_devices for each virtual device in
- * the device tree. Drivers will associate with them later.
- */
- for (of_node = node_vroot->child; of_node != NULL;
- of_node = of_node->sibling)
- vio_register_device_node(of_node);
- of_node_put(node_vroot);
- }
+ vio_bus_scan_register_devices("vdevice");
+ vio_bus_scan_register_devices("ibm,platform-facilities");
return 0;
}
@@ -1436,12 +1615,28 @@ struct vio_dev *vio_find_node(struct device_node *vnode)
{
const uint32_t *unit_address;
char kobj_name[20];
+ struct device_node *vnode_parent;
+ const char *dev_type;
+
+ vnode_parent = of_get_parent(vnode);
+ if (!vnode_parent)
+ return NULL;
+
+ dev_type = of_get_property(vnode_parent, "device_type", NULL);
+ of_node_put(vnode_parent);
+ if (!dev_type)
+ return NULL;
/* construct the kobject name from the device node */
- unit_address = of_get_property(vnode, "reg", NULL);
- if (!unit_address)
+ if (!strcmp(dev_type, "vdevice")) {
+ unit_address = of_get_property(vnode, "reg", NULL);
+ if (!unit_address)
+ return NULL;
+ snprintf(kobj_name, sizeof(kobj_name), "%x", *unit_address);
+ } else if (!strcmp(dev_type, "ibm,platform-facilities"))
+ snprintf(kobj_name, sizeof(kobj_name), "%s", vnode->name);
+ else
return NULL;
- snprintf(kobj_name, sizeof(kobj_name), "%x", *unit_address);
return vio_find_name(kobj_name);
}
diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S
index 773d38f90aaa..d73a59014900 100644
--- a/arch/powerpc/lib/copyuser_64.S
+++ b/arch/powerpc/lib/copyuser_64.S
@@ -30,7 +30,7 @@ _GLOBAL(__copy_tofrom_user_base)
dcbt 0,r4
beq .Lcopy_page_4K
andi. r6,r6,7
- PPC_MTOCRF 0x01,r5
+ PPC_MTOCRF(0x01,r5)
blt cr1,.Lshort_copy
/* Below we want to nop out the bne if we're on a CPU that has the
* CPU_FTR_UNALIGNED_LD_STD bit set and the CPU_FTR_CP_USE_DCBTZ bit
@@ -186,7 +186,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
blr
.Ldst_unaligned:
- PPC_MTOCRF 0x01,r6 /* put #bytes to 8B bdry into cr7 */
+ PPC_MTOCRF(0x01,r6) /* put #bytes to 8B bdry into cr7 */
subf r5,r6,r5
li r7,0
cmpldi cr1,r5,16
@@ -201,7 +201,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
2: bf cr7*4+1,3f
37: lwzx r0,r7,r4
83: stwx r0,r7,r3
-3: PPC_MTOCRF 0x01,r5
+3: PPC_MTOCRF(0x01,r5)
add r4,r6,r4
add r3,r6,r3
b .Ldst_aligned
diff --git a/arch/powerpc/lib/mem_64.S b/arch/powerpc/lib/mem_64.S
index 11ce045e21fd..f4fcb0bc6563 100644
--- a/arch/powerpc/lib/mem_64.S
+++ b/arch/powerpc/lib/mem_64.S
@@ -19,7 +19,7 @@ _GLOBAL(memset)
rlwimi r4,r4,16,0,15
cmplw cr1,r5,r0 /* do we get that far? */
rldimi r4,r4,32,0
- PPC_MTOCRF 1,r0
+ PPC_MTOCRF(1,r0)
mr r6,r3
blt cr1,8f
beq+ 3f /* if already 8-byte aligned */
@@ -49,7 +49,7 @@ _GLOBAL(memset)
bdnz 4b
5: srwi. r0,r5,3
clrlwi r5,r5,29
- PPC_MTOCRF 1,r0
+ PPC_MTOCRF(1,r0)
beq 8f
bf 29,6f
std r4,0(r6)
@@ -65,7 +65,7 @@ _GLOBAL(memset)
std r4,0(r6)
addi r6,r6,8
8: cmpwi r5,0
- PPC_MTOCRF 1,r5
+ PPC_MTOCRF(1,r5)
beqlr+
bf 29,9f
stw r4,0(r6)
diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S
index e178922b2c21..82fea3963e15 100644
--- a/arch/powerpc/lib/memcpy_64.S
+++ b/arch/powerpc/lib/memcpy_64.S
@@ -12,7 +12,7 @@
.align 7
_GLOBAL(memcpy)
std r3,48(r1) /* save destination pointer for return value */
- PPC_MTOCRF 0x01,r5
+ PPC_MTOCRF(0x01,r5)
cmpldi cr1,r5,16
neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry
andi. r6,r6,7
@@ -154,7 +154,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
blr
.Ldst_unaligned:
- PPC_MTOCRF 0x01,r6 # put #bytes to 8B bdry into cr7
+ PPC_MTOCRF(0x01,r6) # put #bytes to 8B bdry into cr7
subf r5,r6,r5
li r7,0
cmpldi cr1,r5,16
@@ -169,7 +169,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
2: bf cr7*4+1,3f
lwzx r0,r7,r4
stwx r0,r7,r3
-3: PPC_MTOCRF 0x01,r5
+3: PPC_MTOCRF(0x01,r5)
add r4,r6,r4
add r3,r6,r3
b .Ldst_aligned
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index fb05b123218f..1a6de0a7d8eb 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -271,7 +271,8 @@ int alloc_bootmem_huge_page(struct hstate *hstate)
unsigned long gpage_npages[MMU_PAGE_COUNT];
-static int __init do_gpage_early_setup(char *param, char *val)
+static int __init do_gpage_early_setup(char *param, char *val,
+ const char *unused)
{
static phys_addr_t size;
unsigned long npages;
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 02aee03e713c..8f84bcba18da 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -1299,8 +1299,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
if (record) {
struct perf_sample_data data;
- perf_sample_data_init(&data, ~0ULL);
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, ~0ULL, event->hw.last_period);
if (event->attr.sample_type & PERF_SAMPLE_ADDR)
perf_get_data_addr(regs, &data.addr);
diff --git a/arch/powerpc/perf/core-fsl-emb.c b/arch/powerpc/perf/core-fsl-emb.c
index 0a6d2a9d569c..106c53354675 100644
--- a/arch/powerpc/perf/core-fsl-emb.c
+++ b/arch/powerpc/perf/core-fsl-emb.c
@@ -613,8 +613,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
if (record) {
struct perf_sample_data data;
- perf_sample_data_init(&data, 0);
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, 0, event->hw.last_period);
if (perf_event_overflow(event, &data, regs))
fsl_emb_pmu_stop(event, 0);
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 2e4e64abfab4..8abf6fb8f410 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -23,6 +23,8 @@ config BLUESTONE
default n
select PPC44x_SIMPLE
select APM821xx
+ select PCI_MSI
+ select PPC4xx_MSI
select PPC4xx_PCI_EXPRESS
select IBM_EMAC_RGMII
help
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 425db18580a2..61c9550819a2 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -78,6 +78,36 @@ config PPC_BOOK3E_64
endchoice
+choice
+ prompt "CPU selection"
+ depends on PPC64
+ default GENERIC_CPU
+ help
+ This will create a kernel which is optimised for a particular CPU.
+ The resulting kernel may not run on other CPUs, so use this with care.
+
+ If unsure, select Generic.
+
+config GENERIC_CPU
+ bool "Generic"
+
+config CELL_CPU
+ bool "Cell Broadband Engine"
+
+config POWER4_CPU
+ bool "POWER4"
+
+config POWER5_CPU
+ bool "POWER5"
+
+config POWER6_CPU
+ bool "POWER6"
+
+config POWER7_CPU
+ bool "POWER7"
+
+endchoice
+
config PPC_BOOK3S
def_bool y
depends on PPC_BOOK3S_32 || PPC_BOOK3S_64
@@ -86,15 +116,6 @@ config PPC_BOOK3E
def_bool y
depends on PPC_BOOK3E_64
-config POWER4_ONLY
- bool "Optimize for POWER4"
- depends on PPC64 && PPC_BOOK3S
- default n
- ---help---
- Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
- The resulting binary will not work on POWER3 or RS64 processors
- when compiled with binutils 2.15 or later.
-
config 6xx
def_bool y
depends on PPC32 && PPC_BOOK3S
@@ -258,7 +279,7 @@ config PPC_ICSWX_PID
default y
---help---
The PID register in server is used explicitly for ICSWX. In
- embedded systems PID managment is done by the system.
+ embedded systems PID management is done by the system.
config PPC_ICSWX_USE_SIGILL
bool "Should a bad CT cause a SIGILL?"
@@ -266,7 +287,7 @@ config PPC_ICSWX_USE_SIGILL
default n
---help---
Should a bad CT used for "non-record form ICSWX" cause an
- illegal intruction signal or should it be silent as
+ illegal instruction signal or should it be silent as
architected.
If in doubt, say N here.
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 03685a329d7d..fc536f2971c0 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -1503,6 +1503,7 @@ static int __init pmac_i2c_create_platform_devices(void)
if (bus->platform_dev == NULL)
return -ENOMEM;
bus->platform_dev->dev.platform_data = bus;
+ bus->platform_dev->dev.of_node = bus->busnode;
platform_device_add(bus->platform_dev);
}
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 476d9d9b2405..46b7f0232523 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -7,7 +7,6 @@ config PPC_PS3
select USB_OHCI_BIG_ENDIAN_MMIO
select USB_ARCH_HAS_EHCI
select USB_EHCI_BIG_ENDIAN_MMIO
- select MEMORY_HOTPLUG
select PPC_PCI_CHOICE
help
This option enables support for the Sony PS3 game console
@@ -74,7 +73,7 @@ config PS3_PS3AV
help
Include support for the PS3 AV Settings driver.
- This support is required for graphics and sound. In
+ This support is required for PS3 graphics and sound. In
general, all users will say Y or M.
config PS3_SYS_MANAGER
@@ -85,9 +84,22 @@ config PS3_SYS_MANAGER
help
Include support for the PS3 System Manager.
- This support is required for system control. In
+ This support is required for PS3 system control. In
general, all users will say Y or M.
+config PS3_REPOSITORY_WRITE
+ bool "PS3 Repository write support" if PS3_ADVANCED
+ depends on PPC_PS3
+ default n
+ help
+ Enables support for writing to the PS3 System Repository.
+
+ This support is intended for bootloaders that need to store data
+ in the repository for later boot stages.
+
+ If in doubt, say N here and reduce the size of the kernel by a
+ small amount.
+
config PS3_STORAGE
depends on PPC_PS3
tristate
@@ -122,7 +134,7 @@ config PS3_FLASH
This support is required to access the PS3 FLASH ROM, which
contains the boot loader and some boot options.
- In general, all users will say Y or M.
+ In general, PS3 OtherOS users will say Y or M.
As this driver needs a fixed buffer of 256 KiB of memory, it can
be disabled on the kernel command line using "ps3flash=off", to
@@ -156,7 +168,7 @@ config PS3GELIC_UDBG
via the Ethernet port (UDP port number 18194).
This driver uses a trivial implementation and is independent
- from the main network driver.
+ from the main PS3 gelic network driver.
If in doubt, say N here.
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index de2aea421707..0c9f643d9e2a 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -20,7 +20,6 @@
#include <linux/kernel.h>
#include <linux/export.h>
-#include <linux/memory_hotplug.h>
#include <linux/memblock.h>
#include <linux/slab.h>
@@ -79,12 +78,14 @@ enum {
* @base: base address
* @size: size in bytes
* @offset: difference between base and rm.size
+ * @destroy: flag if region should be destroyed upon shutdown
*/
struct mem_region {
u64 base;
u64 size;
unsigned long offset;
+ int destroy;
};
/**
@@ -96,7 +97,7 @@ struct mem_region {
* The HV virtual address space (vas) allows for hotplug memory regions.
* Memory regions can be created and destroyed in the vas at runtime.
* @rm: real mode (bootmem) region
- * @r1: hotplug memory region(s)
+ * @r1: highmem region(s)
*
* ps3 addresses
* virt_addr: a cpu 'translated' effective address
@@ -222,10 +223,6 @@ void ps3_mm_vas_destroy(void)
}
}
-/*============================================================================*/
-/* memory hotplug routines */
-/*============================================================================*/
-
/**
* ps3_mm_region_create - create a memory region in the vas
* @r: pointer to a struct mem_region to accept initialized values
@@ -262,6 +259,7 @@ static int ps3_mm_region_create(struct mem_region *r, unsigned long size)
goto zero_region;
}
+ r->destroy = 1;
r->offset = r->base - map.rm.size;
return result;
@@ -279,7 +277,14 @@ static void ps3_mm_region_destroy(struct mem_region *r)
{
int result;
+ if (!r->destroy) {
+ pr_info("%s:%d: Not destroying high region: %llxh %llxh\n",
+ __func__, __LINE__, r->base, r->size);
+ return;
+ }
+
DBG("%s:%d: r->base = %llxh\n", __func__, __LINE__, r->base);
+
if (r->base) {
result = lv1_release_memory(r->base);
BUG_ON(result);
@@ -288,50 +293,36 @@ static void ps3_mm_region_destroy(struct mem_region *r)
}
}
-/**
- * ps3_mm_add_memory - hot add memory
- */
-
-static int __init ps3_mm_add_memory(void)
+static int ps3_mm_get_repository_highmem(struct mem_region *r)
{
int result;
- unsigned long start_addr;
- unsigned long start_pfn;
- unsigned long nr_pages;
-
- if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
- return -ENODEV;
- BUG_ON(!mem_init_done);
+ /* Assume a single highmem region. */
- start_addr = map.rm.size;
- start_pfn = start_addr >> PAGE_SHIFT;
- nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ result = ps3_repository_read_highmem_info(0, &r->base, &r->size);
- DBG("%s:%d: start_addr %lxh, start_pfn %lxh, nr_pages %lxh\n",
- __func__, __LINE__, start_addr, start_pfn, nr_pages);
-
- result = add_memory(0, start_addr, map.r1.size);
+ if (result)
+ goto zero_region;
- if (result) {
- pr_err("%s:%d: add_memory failed: (%d)\n",
- __func__, __LINE__, result);
- return result;
+ if (!r->base || !r->size) {
+ result = -1;
+ goto zero_region;
}
- memblock_add(start_addr, map.r1.size);
+ r->offset = r->base - map.rm.size;
- result = online_pages(start_pfn, nr_pages);
+ DBG("%s:%d: Found high region in repository: %llxh %llxh\n",
+ __func__, __LINE__, r->base, r->size);
- if (result)
- pr_err("%s:%d: online_pages failed: (%d)\n",
- __func__, __LINE__, result);
+ return 0;
+zero_region:
+ DBG("%s:%d: No high region in repository.\n", __func__, __LINE__);
+
+ r->size = r->base = r->offset = 0;
return result;
}
-device_initcall(ps3_mm_add_memory);
-
/*============================================================================*/
/* dma routines */
/*============================================================================*/
@@ -1217,13 +1208,23 @@ void __init ps3_mm_init(void)
BUG_ON(map.rm.base);
BUG_ON(!map.rm.size);
+ /* Check if we got the highmem region from an earlier boot step */
- /* arrange to do this in ps3_mm_add_memory */
- ps3_mm_region_create(&map.r1, map.total - map.rm.size);
+ if (ps3_mm_get_repository_highmem(&map.r1))
+ ps3_mm_region_create(&map.r1, map.total - map.rm.size);
/* correct map.total for the real total amount of memory we use */
map.total = map.rm.size + map.r1.size;
+ if (!map.r1.size) {
+ DBG("%s:%d: No highmem region found\n", __func__, __LINE__);
+ } else {
+ DBG("%s:%d: Adding highmem region: %llxh %llxh\n",
+ __func__, __LINE__, map.rm.size,
+ map.total - map.rm.size);
+ memblock_add(map.rm.size, map.total - map.rm.size);
+ }
+
DBG(" <- %s:%d\n", __func__, __LINE__);
}
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h
index 1a633ed0fe98..d71329a8e325 100644
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -188,6 +188,22 @@ int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size);
int ps3_repository_read_region_total(u64 *region_total);
int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size,
u64 *region_total);
+int ps3_repository_read_highmem_region_count(unsigned int *region_count);
+int ps3_repository_read_highmem_base(unsigned int region_index,
+ u64 *highmem_base);
+int ps3_repository_read_highmem_size(unsigned int region_index,
+ u64 *highmem_size);
+int ps3_repository_read_highmem_info(unsigned int region_index,
+ u64 *highmem_base, u64 *highmem_size);
+
+int ps3_repository_write_highmem_region_count(unsigned int region_count);
+int ps3_repository_write_highmem_base(unsigned int region_index,
+ u64 highmem_base);
+int ps3_repository_write_highmem_size(unsigned int region_index,
+ u64 highmem_size);
+int ps3_repository_write_highmem_info(unsigned int region_index,
+ u64 highmem_base, u64 highmem_size);
+int ps3_repository_delete_highmem_info(unsigned int region_index);
/* repository pme info */
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c
index 7bdfea336f5e..9b47ba7a5de7 100644
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -779,6 +779,72 @@ int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total)
}
/**
+ * ps3_repository_read_highmem_region_count - Read the number of highmem regions
+ *
+ * Bootloaders must arrange the repository nodes such that regions are indexed
+ * with a region_index from 0 to region_count-1.
+ */
+
+int ps3_repository_read_highmem_region_count(unsigned int *region_count)
+{
+ int result;
+ u64 v1 = 0;
+
+ result = read_node(PS3_LPAR_ID_CURRENT,
+ make_first_field("highmem", 0),
+ make_field("region", 0),
+ make_field("count", 0),
+ 0,
+ &v1, NULL);
+ *region_count = v1;
+ return result;
+}
+
+
+int ps3_repository_read_highmem_base(unsigned int region_index,
+ u64 *highmem_base)
+{
+ return read_node(PS3_LPAR_ID_CURRENT,
+ make_first_field("highmem", 0),
+ make_field("region", region_index),
+ make_field("base", 0),
+ 0,
+ highmem_base, NULL);
+}
+
+int ps3_repository_read_highmem_size(unsigned int region_index,
+ u64 *highmem_size)
+{
+ return read_node(PS3_LPAR_ID_CURRENT,
+ make_first_field("highmem", 0),
+ make_field("region", region_index),
+ make_field("size", 0),
+ 0,
+ highmem_size, NULL);
+}
+
+/**
+ * ps3_repository_read_highmem_info - Read high memory region info
+ * @region_index: Region index, {0,..,region_count-1}.
+ * @highmem_base: High memory base address.
+ * @highmem_size: High memory size.
+ *
+ * Bootloaders that preallocate highmem regions must place the
+ * region info into the repository at these well known nodes.
+ */
+
+int ps3_repository_read_highmem_info(unsigned int region_index,
+ u64 *highmem_base, u64 *highmem_size)
+{
+ int result;
+
+ *highmem_base = 0;
+ result = ps3_repository_read_highmem_base(region_index, highmem_base);
+ return result ? result
+ : ps3_repository_read_highmem_size(region_index, highmem_size);
+}
+
+/**
* ps3_repository_read_num_spu_reserved - Number of physical spus reserved.
* @num_spu: Number of physical spus.
*/
@@ -1002,6 +1068,138 @@ int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar,
lpar, rights);
}
+#if defined(CONFIG_PS3_REPOSITORY_WRITE)
+
+static int create_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2)
+{
+ int result;
+
+ dump_node(0, n1, n2, n3, n4, v1, v2);
+
+ result = lv1_create_repository_node(n1, n2, n3, n4, v1, v2);
+
+ if (result) {
+ pr_devel("%s:%d: lv1_create_repository_node failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+static int delete_node(u64 n1, u64 n2, u64 n3, u64 n4)
+{
+ int result;
+
+ dump_node(0, n1, n2, n3, n4, 0, 0);
+
+ result = lv1_delete_repository_node(n1, n2, n3, n4);
+
+ if (result) {
+ pr_devel("%s:%d: lv1_delete_repository_node failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+static int write_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2)
+{
+ int result;
+
+ result = create_node(n1, n2, n3, n4, v1, v2);
+
+ if (!result)
+ return 0;
+
+ result = lv1_write_repository_node(n1, n2, n3, n4, v1, v2);
+
+ if (result) {
+ pr_devel("%s:%d: lv1_write_repository_node failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+int ps3_repository_write_highmem_region_count(unsigned int region_count)
+{
+ int result;
+ u64 v1 = (u64)region_count;
+
+ result = write_node(
+ make_first_field("highmem", 0),
+ make_field("region", 0),
+ make_field("count", 0),
+ 0,
+ v1, 0);
+ return result;
+}
+
+int ps3_repository_write_highmem_base(unsigned int region_index,
+ u64 highmem_base)
+{
+ return write_node(
+ make_first_field("highmem", 0),
+ make_field("region", region_index),
+ make_field("base", 0),
+ 0,
+ highmem_base, 0);
+}
+
+int ps3_repository_write_highmem_size(unsigned int region_index,
+ u64 highmem_size)
+{
+ return write_node(
+ make_first_field("highmem", 0),
+ make_field("region", region_index),
+ make_field("size", 0),
+ 0,
+ highmem_size, 0);
+}
+
+int ps3_repository_write_highmem_info(unsigned int region_index,
+ u64 highmem_base, u64 highmem_size)
+{
+ int result;
+
+ result = ps3_repository_write_highmem_base(region_index, highmem_base);
+ return result ? result
+ : ps3_repository_write_highmem_size(region_index, highmem_size);
+}
+
+static int ps3_repository_delete_highmem_base(unsigned int region_index)
+{
+ return delete_node(
+ make_first_field("highmem", 0),
+ make_field("region", region_index),
+ make_field("base", 0),
+ 0);
+}
+
+static int ps3_repository_delete_highmem_size(unsigned int region_index)
+{
+ return delete_node(
+ make_first_field("highmem", 0),
+ make_field("region", region_index),
+ make_field("size", 0),
+ 0);
+}
+
+int ps3_repository_delete_highmem_info(unsigned int region_index)
+{
+ int result;
+
+ result = ps3_repository_delete_highmem_base(region_index);
+ result += ps3_repository_delete_highmem_size(region_index);
+
+ return result ? -1 : 0;
+}
+
+#endif /* defined(CONFIG_PS3_WRITE_REPOSITORY) */
+
#if defined(DEBUG)
int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 178a5f300bc9..837cf49357ed 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -67,7 +67,7 @@ config IO_EVENT_IRQ
This option will only enable the IO event platform code. You
will still need to enable or compile the actual drivers
- that use this infrastruture to handle IO event interrupts.
+ that use this infrastructure to handle IO event interrupts.
Say Y if you are unsure.
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index a75e37dc41aa..ecd394cf34e6 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -489,7 +489,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
* a stack trace will help the device-driver authors figure
* out what happened. So print that out.
*/
- dump_stack();
+ WARN(1, "EEH: failure detected\n");
return 1;
dn_unlock:
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index 342797fc0f9c..13e8cc43adf7 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -22,12 +22,12 @@ static inline long poll_pending(void)
static inline u8 get_cede_latency_hint(void)
{
- return get_lppaca()->gpr5_dword.fields.cede_latency_hint;
+ return get_lppaca()->cede_latency_hint;
}
static inline void set_cede_latency_hint(u8 latency_hint)
{
- get_lppaca()->gpr5_dword.fields.cede_latency_hint = latency_hint;
+ get_lppaca()->cede_latency_hint = latency_hint;
}
static inline long cede_processor(void)
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 168651acdd83..7b3bf76ef834 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -103,11 +103,13 @@ int pSeries_reconfig_notifier_register(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb);
}
+EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_register);
void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
{
blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
}
+EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_unregister);
int pSeries_reconfig_notify(unsigned long action, void *p)
{
@@ -426,6 +428,7 @@ static int do_remove_property(char *buf, size_t bufsize)
static int do_update_property(char *buf, size_t bufsize)
{
struct device_node *np;
+ struct pSeries_reconfig_prop_update upd_value;
unsigned char *value;
char *name, *end, *next_prop;
int rc, length;
@@ -454,6 +457,10 @@ static int do_update_property(char *buf, size_t bufsize)
return -ENODEV;
}
+ upd_value.node = np;
+ upd_value.property = newprop;
+ pSeries_reconfig_notify(PSERIES_UPDATE_PROPERTY, &upd_value);
+
rc = prom_update_property(np, newprop, oldprop);
if (rc)
return rc;
diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c
index 1c2d7af17bbe..82c6702dcbab 100644
--- a/arch/powerpc/sysdev/ppc4xx_msi.c
+++ b/arch/powerpc/sysdev/ppc4xx_msi.c
@@ -28,10 +28,11 @@
#include <linux/of_platform.h>
#include <linux/interrupt.h>
#include <linux/export.h>
+#include <linux/kernel.h>
#include <asm/prom.h>
#include <asm/hw_irq.h>
#include <asm/ppc-pci.h>
-#include <boot/dcr.h>
+#include <asm/dcr.h>
#include <asm/dcr-regs.h>
#include <asm/msi_bitmap.h>
@@ -43,13 +44,14 @@
#define PEIH_FLUSH0 0x30
#define PEIH_FLUSH1 0x38
#define PEIH_CNTRST 0x48
-#define NR_MSI_IRQS 4
+
+static int msi_irqs;
struct ppc4xx_msi {
u32 msi_addr_lo;
u32 msi_addr_hi;
void __iomem *msi_regs;
- int msi_virqs[NR_MSI_IRQS];
+ int *msi_virqs;
struct msi_bitmap bitmap;
struct device_node *msi_dev;
};
@@ -61,7 +63,7 @@ static int ppc4xx_msi_init_allocator(struct platform_device *dev,
{
int err;
- err = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS,
+ err = msi_bitmap_alloc(&msi_data->bitmap, msi_irqs,
dev->dev.of_node);
if (err)
return err;
@@ -83,6 +85,11 @@ static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
struct msi_desc *entry;
struct ppc4xx_msi *msi_data = &ppc4xx_msi;
+ msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int),
+ GFP_KERNEL);
+ if (!msi_data->msi_virqs)
+ return -ENOMEM;
+
list_for_each_entry(entry, &dev->msi_list, list) {
int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
if (int_no >= 0)
@@ -150,12 +157,11 @@ static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
if (!sdr_addr)
return -1;
- SDR0_WRITE(sdr_addr, (u64)res.start >> 32); /*HIGH addr */
- SDR0_WRITE(sdr_addr + 1, res.start & 0xFFFFFFFF); /* Low addr */
-
+ mtdcri(SDR0, *sdr_addr, upper_32_bits(res.start)); /*HIGH addr */
+ mtdcri(SDR0, *sdr_addr + 1, lower_32_bits(res.start)); /* Low addr */
msi->msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi");
- if (msi->msi_dev)
+ if (!msi->msi_dev)
return -ENODEV;
msi->msi_regs = of_iomap(msi->msi_dev, 0);
@@ -167,9 +173,12 @@ static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
(u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs));
msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL);
- msi->msi_addr_hi = 0x0;
- msi->msi_addr_lo = (u32) msi_phys;
- dev_dbg(&dev->dev, "PCIE-MSI: msi address 0x%x\n", msi->msi_addr_lo);
+ if (!msi_virt)
+ return -ENOMEM;
+ msi->msi_addr_hi = upper_32_bits(msi_phys);
+ msi->msi_addr_lo = lower_32_bits(msi_phys & 0xffffffff);
+ dev_dbg(&dev->dev, "PCIE-MSI: msi address high 0x%x, low 0x%x\n",
+ msi->msi_addr_hi, msi->msi_addr_lo);
/* Progam the Interrupt handler Termination addr registers */
out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi);
@@ -185,6 +194,8 @@ static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
out_be32(msi->msi_regs + PEIH_MSIED, *msi_data);
out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask);
+ dma_free_coherent(&dev->dev, 64, msi_virt, msi_phys);
+
return 0;
}
@@ -194,7 +205,7 @@ static int ppc4xx_of_msi_remove(struct platform_device *dev)
int i;
int virq;
- for (i = 0; i < NR_MSI_IRQS; i++) {
+ for (i = 0; i < msi_irqs; i++) {
virq = msi->msi_virqs[i];
if (virq != NO_IRQ)
irq_dispose_mapping(virq);
@@ -215,8 +226,6 @@ static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
struct resource res;
int err = 0;
- msi = &ppc4xx_msi;/*keep the msi data for further use*/
-
dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n");
msi = kzalloc(sizeof(struct ppc4xx_msi), GFP_KERNEL);
@@ -234,6 +243,10 @@ static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
goto error_out;
}
+ msi_irqs = of_irq_count(dev->dev.of_node);
+ if (!msi_irqs)
+ return -ENODEV;
+
if (ppc4xx_setup_pcieh_hw(dev, res, msi))
goto error_out;
@@ -242,6 +255,7 @@ static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
dev_err(&dev->dev, "Error allocating MSI bitmap\n");
goto error_out;
}
+ ppc4xx_msi = *msi;
ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs;
ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs;
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 9015060919a0..e16390c0bca8 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -122,6 +122,7 @@ config S390
select ARCH_INLINE_WRITE_UNLOCK_BH
select ARCH_INLINE_WRITE_UNLOCK_IRQ
select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
+ select GENERIC_SMP_IDLE_THREAD
config SCHED_OMIT_FRAME_POINTER
def_bool y
@@ -217,7 +218,7 @@ config COMPAT
def_bool y
prompt "Kernel support for 31 bit emulation"
depends on 64BIT
- select COMPAT_BINFMT_ELF
+ select COMPAT_BINFMT_ELF if BINFMT_ELF
select ARCH_WANT_OLD_COMPAT_IPC
help
Select this option if you want to enable your system kernel to
@@ -234,6 +235,25 @@ config KEYS_COMPAT
config AUDIT_ARCH
def_bool y
+config HAVE_MARCH_Z900_FEATURES
+ def_bool n
+
+config HAVE_MARCH_Z990_FEATURES
+ def_bool n
+ select HAVE_MARCH_Z900_FEATURES
+
+config HAVE_MARCH_Z9_109_FEATURES
+ def_bool n
+ select HAVE_MARCH_Z990_FEATURES
+
+config HAVE_MARCH_Z10_FEATURES
+ def_bool n
+ select HAVE_MARCH_Z9_109_FEATURES
+
+config HAVE_MARCH_Z196_FEATURES
+ def_bool n
+ select HAVE_MARCH_Z10_FEATURES
+
comment "Code generation options"
choice
@@ -249,6 +269,7 @@ config MARCH_G5
config MARCH_Z900
bool "IBM zSeries model z800 and z900"
+ select HAVE_MARCH_Z900_FEATURES if 64BIT
help
Select this to enable optimizations for model z800/z900 (2064 and
2066 series). This will enable some optimizations that are not
@@ -256,6 +277,7 @@ config MARCH_Z900
config MARCH_Z990
bool "IBM zSeries model z890 and z990"
+ select HAVE_MARCH_Z990_FEATURES if 64BIT
help
Select this to enable optimizations for model z890/z990 (2084 and
2086 series). The kernel will be slightly faster but will not work
@@ -263,6 +285,7 @@ config MARCH_Z990
config MARCH_Z9_109
bool "IBM System z9"
+ select HAVE_MARCH_Z9_109_FEATURES if 64BIT
help
Select this to enable optimizations for IBM System z9 (2094 and
2096 series). The kernel will be slightly faster but will not work
@@ -270,6 +293,7 @@ config MARCH_Z9_109
config MARCH_Z10
bool "IBM System z10"
+ select HAVE_MARCH_Z10_FEATURES if 64BIT
help
Select this to enable optimizations for IBM System z10 (2097 and
2098 series). The kernel will be slightly faster but will not work
@@ -277,6 +301,7 @@ config MARCH_Z10
config MARCH_Z196
bool "IBM zEnterprise 114 and 196"
+ select HAVE_MARCH_Z196_FEATURES if 64BIT
help
Select this to enable optimizations for IBM zEnterprise 114 and 196
(2818 and 2817 series). The kernel will be slightly faster but will
@@ -406,33 +431,6 @@ config CHSC_SCH
comment "Misc"
-config IPL
- def_bool y
- prompt "Builtin IPL record support"
- help
- If you want to use the produced kernel to IPL directly from a
- device, you have to merge a bootsector specific to the device
- into the first bytes of the kernel. You will have to select the
- IPL device.
-
-choice
- prompt "IPL method generated into head.S"
- depends on IPL
- default IPL_VM
- help
- Select "tape" if you want to IPL the image from a Tape.
-
- Select "vm_reader" if you are running under VM/ESA and want
- to IPL the image from the emulated card reader.
-
-config IPL_TAPE
- bool "tape"
-
-config IPL_VM
- bool "vm_reader"
-
-endchoice
-
source "fs/Kconfig.binfmt"
config FORCE_MAX_ZONEORDER
@@ -569,7 +567,7 @@ config KEXEC
config CRASH_DUMP
bool "kernel crash dumps"
- depends on 64BIT
+ depends on 64BIT && SMP
select KEXEC
help
Generate crash dump after being started by kexec.
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 0ad2f1e1ce9e..49e76e8b477d 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -91,7 +91,6 @@ OBJCOPYFLAGS := -O binary
head-y := arch/s390/kernel/head.o
head-y += arch/s390/kernel/$(if $(CONFIG_64BIT),head64.o,head31.o)
-head-y += arch/s390/kernel/init_task.o
# See arch/s390/Kbuild for content of core part of the kernel
core-y += arch/s390/
diff --git a/arch/s390/boot/.gitignore b/arch/s390/boot/.gitignore
new file mode 100644
index 000000000000..017d5912ad2d
--- /dev/null
+++ b/arch/s390/boot/.gitignore
@@ -0,0 +1,2 @@
+image
+bzImage
diff --git a/arch/s390/boot/compressed/.gitignore b/arch/s390/boot/compressed/.gitignore
new file mode 100644
index 000000000000..ae06b9b4c02f
--- /dev/null
+++ b/arch/s390/boot/compressed/.gitignore
@@ -0,0 +1,3 @@
+sizes.h
+vmlinux
+vmlinux.lds
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 1957a9dd256d..37d2bf267964 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -155,7 +155,6 @@ CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SALSA20=m
diff --git a/arch/s390/include/asm/barrier.h b/arch/s390/include/asm/barrier.h
index 451273ad4d34..10a508802940 100644
--- a/arch/s390/include/asm/barrier.h
+++ b/arch/s390/include/asm/barrier.h
@@ -11,25 +11,28 @@
* Force strict CPU ordering.
* And yes, this is required on UP too when we're talking
* to devices.
- *
- * This is very similar to the ppc eieio/sync instruction in that is
- * does a checkpoint syncronisation & makes sure that
- * all memory ops have completed wrt other CPU's ( see 7-15 POP DJB ).
*/
-#define eieio() asm volatile("bcr 15,0" : : : "memory")
-#define SYNC_OTHER_CORES(x) eieio()
-#define mb() eieio()
-#define rmb() eieio()
-#define wmb() eieio()
-#define read_barrier_depends() do { } while(0)
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define smp_read_barrier_depends() read_barrier_depends()
-#define smp_mb__before_clear_bit() smp_mb()
-#define smp_mb__after_clear_bit() smp_mb()
+static inline void mb(void)
+{
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+ /* Fast-BCR without checkpoint synchronization */
+ asm volatile("bcr 14,0" : : : "memory");
+#else
+ asm volatile("bcr 15,0" : : : "memory");
+#endif
+}
+
+#define rmb() mb()
+#define wmb() mb()
+#define read_barrier_depends() do { } while(0)
+#define smp_mb() mb()
+#define smp_rmb() rmb()
+#define smp_wmb() wmb()
+#define smp_read_barrier_depends() read_barrier_depends()
+#define smp_mb__before_clear_bit() smp_mb()
+#define smp_mb__after_clear_bit() smp_mb()
-#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define set_mb(var, value) do { var = value; mb(); } while (0)
#endif /* __ASM_BARRIER_H */
diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h
index f2ea2c56a7e1..f2ef34f6d6e5 100644
--- a/arch/s390/include/asm/ccwgroup.h
+++ b/arch/s390/include/asm/ccwgroup.h
@@ -29,9 +29,7 @@ struct ccwgroup_device {
/**
* struct ccwgroup_driver - driver for ccw group devices
- * @max_slaves: maximum number of slave devices
- * @driver_id: unique id
- * @probe: function called on probe
+ * @setup: function called during device creation to setup the device
* @remove: function called on remove
* @set_online: function called when device is set online
* @set_offline: function called when device is set offline
@@ -44,10 +42,7 @@ struct ccwgroup_device {
* @driver: embedded driver structure
*/
struct ccwgroup_driver {
- int max_slaves;
- unsigned long driver_id;
-
- int (*probe) (struct ccwgroup_device *);
+ int (*setup) (struct ccwgroup_device *);
void (*remove) (struct ccwgroup_device *);
int (*set_online) (struct ccwgroup_device *);
int (*set_offline) (struct ccwgroup_device *);
@@ -63,9 +58,8 @@ struct ccwgroup_driver {
extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver);
extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver);
-int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
- struct ccw_driver *cdrv, int num_devices,
- const char *buf);
+int ccwgroup_create_dev(struct device *root, struct ccwgroup_driver *gdrv,
+ int num_devices, const char *buf);
extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev);
extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev);
diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h
index b7ff6afc3caa..27216d317991 100644
--- a/arch/s390/include/asm/io.h
+++ b/arch/s390/include/asm/io.h
@@ -38,11 +38,8 @@ static inline void * phys_to_virt(unsigned long address)
return (void *) address;
}
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p) __va(p)
+void *xlate_dev_mem_ptr(unsigned long phys);
+void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
/*
* Convert a virtual cached pointer to an uncached pointer
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index d499b30ea487..6cbf31311673 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -141,9 +141,6 @@ struct seq_file;
extern void release_thread(struct task_struct *);
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
/*
* Return saved PC of a blocked thread.
*/
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h
index d75c8e78f7e3..f039d86adf67 100644
--- a/arch/s390/include/asm/qdio.h
+++ b/arch/s390/include/asm/qdio.h
@@ -258,11 +258,6 @@ struct slsb {
u8 val[QDIO_MAX_BUFFERS_PER_Q];
} __attribute__ ((packed, aligned(256)));
-#define CHSC_AC2_MULTI_BUFFER_AVAILABLE 0x0080
-#define CHSC_AC2_MULTI_BUFFER_ENABLED 0x0040
-#define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010
-#define CHSC_AC2_DATA_DIV_ENABLED 0x0002
-
/**
* struct qdio_outbuf_state - SBAL related asynchronous operation information
* (for communication with upper layer programs)
@@ -293,6 +288,8 @@ struct qdio_outbuf_state {
#define AC1_SC_QEBSM_AVAILABLE 0x02 /* available for subchannel */
#define AC1_SC_QEBSM_ENABLED 0x01 /* enabled for subchannel */
+#define CHSC_AC2_MULTI_BUFFER_AVAILABLE 0x0080
+#define CHSC_AC2_MULTI_BUFFER_ENABLED 0x0040
#define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010
#define CHSC_AC2_DATA_DIV_ENABLED 0x0002
@@ -328,11 +325,13 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
int, int, unsigned long);
/* qdio errors reported to the upper-layer program */
-#define QDIO_ERROR_SIGA_TARGET 0x02
-#define QDIO_ERROR_SIGA_ACCESS_EXCEPTION 0x10
-#define QDIO_ERROR_SIGA_BUSY 0x20
-#define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40
-#define QDIO_ERROR_SLSB_STATE 0x80
+#define QDIO_ERROR_ACTIVATE 0x0001
+#define QDIO_ERROR_GET_BUF_STATE 0x0002
+#define QDIO_ERROR_SET_BUF_STATE 0x0004
+#define QDIO_ERROR_SLSB_STATE 0x0100
+
+#define QDIO_ERROR_FATAL 0x00ff
+#define QDIO_ERROR_TEMPORARY 0xff00
/* for qdio_cleanup */
#define QDIO_FLAG_CLEANUP_USING_CLEAR 0x01
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index b21e46e5d4b8..7244e1f64126 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -82,7 +82,6 @@ extern unsigned int user_mode;
#define MACHINE_FLAG_LPAR (1UL << 12)
#define MACHINE_FLAG_SPP (1UL << 13)
#define MACHINE_FLAG_TOPOLOGY (1UL << 14)
-#define MACHINE_FLAG_STCKF (1UL << 15)
#define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
#define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -101,7 +100,6 @@ extern unsigned int user_mode;
#define MACHINE_HAS_PFMF (0)
#define MACHINE_HAS_SPP (0)
#define MACHINE_HAS_TOPOLOGY (0)
-#define MACHINE_HAS_STCKF (0)
#else /* __s390x__ */
#define MACHINE_HAS_IEEE (1)
#define MACHINE_HAS_CSP (1)
@@ -113,7 +111,6 @@ extern unsigned int user_mode;
#define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
#define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
#define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
-#define MACHINE_HAS_STCKF (S390_lowcore.machine_flags & MACHINE_FLAG_STCKF)
#endif /* __s390x__ */
#define ZFCPDUMP_HSA_SIZE (32UL<<20)
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h
index c77c6de6f6c0..0b6f586c1383 100644
--- a/arch/s390/include/asm/smp.h
+++ b/arch/s390/include/asm/smp.h
@@ -16,7 +16,7 @@
extern struct mutex smp_cpu_state_mutex;
extern struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
-extern int __cpu_up(unsigned int cpu);
+extern int __cpu_up(unsigned int cpu, struct task_struct *tidle);
extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index a73038155e0d..003b04edcff6 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -95,7 +95,6 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */
#define TIF_SECCOMP 10 /* secure computing */
#define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */
-#define TIF_SIE 12 /* guest execution active */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
#define TIF_31BIT 17 /* 32bit process */
@@ -114,7 +113,6 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
-#define _TIF_SIE (1<<TIF_SIE)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_31BIT (1<<TIF_31BIT)
#define _TIF_SINGLE_STEP (1<<TIF_SINGLE_STEP)
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h
index c447a27a7fdb..239ece9e53c1 100644
--- a/arch/s390/include/asm/timex.h
+++ b/arch/s390/include/asm/timex.h
@@ -73,11 +73,15 @@ static inline void local_tick_enable(unsigned long long comp)
typedef unsigned long long cycles_t;
-static inline unsigned long long get_clock (void)
+static inline unsigned long long get_clock(void)
{
unsigned long long clk;
+#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
+ asm volatile(".insn s,0xb27c0000,%0" : "=Q" (clk) : : "cc");
+#else
asm volatile("stck %0" : "=Q" (clk) : : "cc");
+#endif
return clk;
}
@@ -86,17 +90,6 @@ static inline void get_clock_ext(char *clk)
asm volatile("stcke %0" : "=Q" (*clk) : : "cc");
}
-static inline unsigned long long get_clock_fast(void)
-{
- unsigned long long clk;
-
- if (MACHINE_HAS_STCKF)
- asm volatile(".insn s,0xb27c0000,%0" : "=Q" (clk) : : "cc");
- else
- clk = get_clock();
- return clk;
-}
-
static inline unsigned long long get_clock_xt(void)
{
unsigned char clk[16];
diff --git a/arch/s390/kernel/.gitignore b/arch/s390/kernel/.gitignore
new file mode 100644
index 000000000000..c5f676c3c224
--- /dev/null
+++ b/arch/s390/kernel/.gitignore
@@ -0,0 +1 @@
+vmlinux.lds
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 884b18afc864..9733b3f0eb6d 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -28,7 +28,7 @@ obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \
obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
-extra-y += head.o init_task.o vmlinux.lds
+extra-y += head.o vmlinux.lds
extra-y += $(if $(CONFIG_64BIT),head64.o,head31.o)
obj-$(CONFIG_MODULES) += s390_ksyms.o module.o
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 28040fd5e8a2..377c096ca4a7 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -437,13 +437,6 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
sp = current->sas_ss_sp + current->sas_ss_size;
}
- /* This is the legacy signal stack switching. */
- else if (!user_mode(regs) &&
- !(ka->sa.sa_flags & SA_RESTORER) &&
- ka->sa.sa_restorer) {
- sp = (unsigned long) ka->sa.sa_restorer;
- }
-
return (void __user *)((sp - frame_size) & -8ul);
}
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 9475e682727f..d84181f1f5e8 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -374,8 +374,6 @@ static __init void detect_machine_facilities(void)
S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
if (test_facility(40))
S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;
- if (test_facility(25))
- S390_lowcore.machine_flags |= MACHINE_FLAG_STCKF;
#endif
}
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 74ee563fe62b..1ae93b573d7d 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -145,22 +145,23 @@ STACK_SIZE = 1 << STACK_SHIFT
* gpr2 = prev
*/
ENTRY(__switch_to)
+ stm %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task
+ st %r15,__THREAD_ksp(%r2) # store kernel stack of prev
l %r4,__THREAD_info(%r2) # get thread_info of prev
l %r5,__THREAD_info(%r3) # get thread_info of next
+ lr %r15,%r5
+ ahi %r15,STACK_SIZE # end of kernel stack of next
+ st %r3,__LC_CURRENT # store task struct of next
+ st %r5,__LC_THREAD_INFO # store thread info of next
+ st %r15,__LC_KERNEL_STACK # store end of kernel stack
+ lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
+ mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next
+ l %r15,__THREAD_ksp(%r3) # load kernel stack of next
tm __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
jz 0f
ni __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
oi __TI_flags+3(%r5),_TIF_MCCK_PENDING # set it in next
-0: stm %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task
- st %r15,__THREAD_ksp(%r2) # store kernel stack of prev
- l %r15,__THREAD_ksp(%r3) # load kernel stack of next
- lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
- lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task
- st %r3,__LC_CURRENT # store task struct of next
- mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next
- st %r5,__LC_THREAD_INFO # store thread info of next
- ahi %r5,STACK_SIZE # end of kernel stack of next
- st %r5,__LC_KERNEL_STACK # store end of kernel stack
+0: lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task
br %r14
__critical_start:
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 4e1c292fa7e3..229fe1d07749 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -81,16 +81,14 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
.macro HANDLE_SIE_INTERCEPT scratch
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
- tm __TI_flags+6(%r12),_TIF_SIE>>8
- jz .+42
- tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_SPP
- jz .+8
- .insn s,0xb2800000,BASED(.Lhost_id) # set host id
+ tmhh %r8,0x0001 # interrupting from user ?
+ jnz .+42
lgr \scratch,%r9
slg \scratch,BASED(.Lsie_loop)
clg \scratch,BASED(.Lsie_length)
- jhe .+10
+ jhe .+22
lg %r9,BASED(.Lsie_loop)
+ SPP BASED(.Lhost_id) # set host id
#endif
.endm
@@ -148,6 +146,14 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
ssm __LC_RETURN_PSW
.endm
+ .macro STCK savearea
+#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
+ .insn s,0xb27c0000,\savearea # store clock fast
+#else
+ .insn s,0xb2050000,\savearea # store clock
+#endif
+ .endm
+
.section .kprobes.text, "ax"
/*
@@ -158,22 +164,23 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
* gpr2 = prev
*/
ENTRY(__switch_to)
+ stmg %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task
+ stg %r15,__THREAD_ksp(%r2) # store kernel stack of prev
lg %r4,__THREAD_info(%r2) # get thread_info of prev
lg %r5,__THREAD_info(%r3) # get thread_info of next
+ lgr %r15,%r5
+ aghi %r15,STACK_SIZE # end of kernel stack of next
+ stg %r3,__LC_CURRENT # store task struct of next
+ stg %r5,__LC_THREAD_INFO # store thread info of next
+ stg %r15,__LC_KERNEL_STACK # store end of kernel stack
+ lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
+ mvc __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next
+ lg %r15,__THREAD_ksp(%r3) # load kernel stack of next
tm __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
jz 0f
ni __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
oi __TI_flags+7(%r5),_TIF_MCCK_PENDING # set it in next
-0: stmg %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task
- stg %r15,__THREAD_ksp(%r2) # store kernel stack of prev
- lg %r15,__THREAD_ksp(%r3) # load kernel stack of next
- lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
- lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task
- stg %r3,__LC_CURRENT # store task struct of next
- mvc __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next
- stg %r5,__LC_THREAD_INFO # store thread info of next
- aghi %r5,STACK_SIZE # end of kernel stack of next
- stg %r5,__LC_KERNEL_STACK # store end of kernel stack
+0: lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task
br %r14
__critical_start:
@@ -458,7 +465,7 @@ pgm_svcper:
* IO interrupt handler routine
*/
ENTRY(io_int_handler)
- stck __LC_INT_CLOCK
+ STCK __LC_INT_CLOCK
stpt __LC_ASYNC_ENTER_TIMER
stmg %r8,%r15,__LC_SAVE_AREA_ASYNC
lg %r10,__LC_LAST_BREAK
@@ -604,7 +611,7 @@ io_notify_resume:
* External interrupt handler routine
*/
ENTRY(ext_int_handler)
- stck __LC_INT_CLOCK
+ STCK __LC_INT_CLOCK
stpt __LC_ASYNC_ENTER_TIMER
stmg %r8,%r15,__LC_SAVE_AREA_ASYNC
lg %r10,__LC_LAST_BREAK
@@ -622,6 +629,7 @@ ext_skip:
mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
stmg %r8,%r9,__PT_PSW(%r11)
TRACE_IRQS_OFF
+ xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
lghi %r1,4096
lgr %r2,%r11 # pass pointer to pt_regs
llgf %r3,__LC_EXT_CPU_ADDR # get cpu address + interruption code
@@ -638,7 +646,7 @@ ENTRY(psw_idle)
larl %r1,psw_idle_lpsw+4
stg %r1,__SF_EMPTY+8(%r15)
larl %r1,.Lvtimer_max
- stck __IDLE_ENTER(%r2)
+ STCK __IDLE_ENTER(%r2)
ltr %r5,%r5
stpt __VQ_IDLE_ENTER(%r3)
jz psw_idle_lpsw
@@ -654,7 +662,7 @@ __critical_end:
* Machine check handler routines
*/
ENTRY(mcck_int_handler)
- stck __LC_MCCK_CLOCK
+ STCK __LC_MCCK_CLOCK
la %r1,4095 # revalidate r1
spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer
lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
@@ -967,7 +975,6 @@ ENTRY(sie64a)
xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0
lmg %r0,%r13,0(%r3) # load guest gprs 0-13
lg %r14,__LC_THREAD_INFO # pointer thread_info struct
- oi __TI_flags+6(%r14),_TIF_SIE>>8
sie_loop:
lg %r14,__LC_THREAD_INFO # pointer thread_info struct
tm __TI_flags+7(%r14),_TIF_EXIT_SIE
@@ -985,7 +992,6 @@ sie_done:
lg %r14,__LC_THREAD_INFO # pointer thread_info struct
sie_exit:
lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
- ni __TI_flags+6(%r14),255-(_TIF_SIE>>8)
lg %r14,__SF_EMPTY+8(%r15) # load guest register save area
stmg %r0,%r13,0(%r14) # save guest gprs 0-13
lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
@@ -994,7 +1000,6 @@ sie_exit:
sie_fault:
lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
lg %r14,__LC_THREAD_INFO # pointer thread_info struct
- ni __TI_flags+6(%r14),255-(_TIF_SIE>>8)
lg %r14,__SF_EMPTY+8(%r15) # load guest register save area
stmg %r0,%r13,0(%r14) # save guest gprs 0-13
lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index adccd908ebc7..4939d15375aa 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -34,125 +34,7 @@
#endif
__HEAD
-#ifndef CONFIG_IPL
- .org 0
- .long 0x00080000,0x80000000+startup # Just a restart PSW
-#else
-#ifdef CONFIG_IPL_TAPE
-#define IPL_BS 1024
- .org 0
- .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded
- .long 0x27000000,0x60000001 # by ipl to addresses 0-23.
- .long 0x02000000,0x20000000+IPL_BS # (a PSW and two CCWs).
- .long 0x00000000,0x00000000 # external old psw
- .long 0x00000000,0x00000000 # svc old psw
- .long 0x00000000,0x00000000 # program check old psw
- .long 0x00000000,0x00000000 # machine check old psw
- .long 0x00000000,0x00000000 # io old psw
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x000a0000,0x00000058 # external new psw
- .long 0x000a0000,0x00000060 # svc new psw
- .long 0x000a0000,0x00000068 # program check new psw
- .long 0x000a0000,0x00000070 # machine check new psw
- .long 0x00080000,0x80000000+.Lioint # io new psw
- .org 0x100
-#
-# subroutine for loading from tape
-# Parameters:
-# R1 = device number
-# R2 = load address
-.Lloader:
- st %r14,.Lldret
- la %r3,.Lorbread # r3 = address of orb
- la %r5,.Lirb # r5 = address of irb
- st %r2,.Lccwread+4 # initialize CCW data addresses
- lctl %c6,%c6,.Lcr6
- slr %r2,%r2
-.Lldlp:
- la %r6,3 # 3 retries
-.Lssch:
- ssch 0(%r3) # load chunk of IPL_BS bytes
- bnz .Llderr
-.Lw4end:
- bas %r14,.Lwait4io
- tm 8(%r5),0x82 # do we have a problem ?
- bnz .Lrecov
- slr %r7,%r7
- icm %r7,3,10(%r5) # get residual count
- lcr %r7,%r7
- la %r7,IPL_BS(%r7) # IPL_BS-residual=#bytes read
- ar %r2,%r7 # add to total size
- tm 8(%r5),0x01 # found a tape mark ?
- bnz .Ldone
- l %r0,.Lccwread+4 # update CCW data addresses
- ar %r0,%r7
- st %r0,.Lccwread+4
- b .Lldlp
-.Ldone:
- l %r14,.Lldret
- br %r14 # r2 contains the total size
-.Lrecov:
- bas %r14,.Lsense # do the sensing
- bct %r6,.Lssch # dec. retry count & branch
- b .Llderr
-#
-# Sense subroutine
-#
-.Lsense:
- st %r14,.Lsnsret
- la %r7,.Lorbsense
- ssch 0(%r7) # start sense command
- bnz .Llderr
- bas %r14,.Lwait4io
- l %r14,.Lsnsret
- tm 8(%r5),0x82 # do we have a problem ?
- bnz .Llderr
- br %r14
-#
-# Wait for interrupt subroutine
-#
-.Lwait4io:
- lpsw .Lwaitpsw
-.Lioint:
- c %r1,0xb8 # compare subchannel number
- bne .Lwait4io
- tsch 0(%r5)
- slr %r0,%r0
- tm 8(%r5),0x82 # do we have a problem ?
- bnz .Lwtexit
- tm 8(%r5),0x04 # got device end ?
- bz .Lwait4io
-.Lwtexit:
- br %r14
-.Llderr:
- lpsw .Lcrash
-
- .align 8
-.Lorbread:
- .long 0x00000000,0x0080ff00,.Lccwread
- .align 8
-.Lorbsense:
- .long 0x00000000,0x0080ff00,.Lccwsense
- .align 8
-.Lccwread:
- .long 0x02200000+IPL_BS,0x00000000
-.Lccwsense:
- .long 0x04200001,0x00000000
-.Lwaitpsw:
- .long 0x020a0000,0x80000000+.Lioint
-
-.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-.Lcr6: .long 0xff000000
- .align 8
-.Lcrash:.long 0x000a0000,0x00000000
-.Lldret:.long 0
-.Lsnsret: .long 0
-#endif /* CONFIG_IPL_TAPE */
-
-#ifdef CONFIG_IPL_VM
#define IPL_BS 0x730
.org 0
.long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded
@@ -256,7 +138,6 @@ __HEAD
.long 0x02600050,0x00000000
.endr
.long 0x02200050,0x00000000
-#endif /* CONFIG_IPL_VM */
iplstart:
lh %r1,0xb8 # test if subchannel number
@@ -325,7 +206,6 @@ iplstart:
clc 0(3,%r2),.L_eof
bz .Lagain2
-#ifdef CONFIG_IPL_VM
#
# reset files in VM reader
#
@@ -358,7 +238,6 @@ iplstart:
.long 0x00080000,0x80000000+.Lrdrint
.Lrdrwaitpsw:
.long 0x020a0000,0x80000000+.Lrdrint
-#endif
#
# everything loaded, go for it
@@ -376,8 +255,6 @@ iplstart:
.L_eof: .long 0xc5d6c600 /* C'EOF' */
.L_hdr: .long 0xc8c4d900 /* C'HDR' */
-#endif /* CONFIG_IPL */
-
#
# SALIPL loader support. Based on a patch by Rob van der Heij.
# This entry point is called directly from the SALIPL loader and
diff --git a/arch/s390/kernel/init_task.c b/arch/s390/kernel/init_task.c
deleted file mode 100644
index 4d1c9fb0b540..000000000000
--- a/arch/s390/kernel/init_task.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * arch/s390/kernel/init_task.c
- *
- * S390 version
- *
- * Derived from "arch/i386/kernel/init_task.c"
- */
-
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init_task.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is THREAD_SIZE aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 02f300fbf070..4993e689b2c2 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -719,7 +719,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
long ret = 0;
/* Do the secure computing check first. */
- secure_computing(regs->gprs[2]);
+ secure_computing_strict(regs->gprs[2]);
/*
* The sysc_tracesys code in entry.S stored the system
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index f7582b27f600..8a4e2b760d56 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -235,13 +235,6 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
sp = current->sas_ss_sp + current->sas_ss_size;
}
- /* This is the legacy signal stack switching. */
- else if (!user_mode(regs) &&
- !(ka->sa.sa_flags & SA_RESTORER) &&
- ka->sa.sa_restorer) {
- sp = (unsigned long) ka->sa.sa_restorer;
- }
-
return (void __user *)((sp - frame_size) & -8ul);
}
@@ -414,15 +407,6 @@ void do_signal(struct pt_regs *regs)
struct k_sigaction ka;
sigset_t *oldset;
- /*
- * We want the common case to go fast, which
- * is why we may in certain cases get here from
- * kernel mode. Just return without doing anything
- * if so.
- */
- if (!user_mode(regs))
- return;
-
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 1f77227669e8..647ba9425893 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -85,7 +85,6 @@ enum {
struct pcpu {
struct cpu cpu;
- struct task_struct *idle; /* idle process for the cpu */
struct _lowcore *lowcore; /* lowcore page(s) for the cpu */
unsigned long async_stack; /* async stack for the cpu */
unsigned long panic_stack; /* panic stack for the cpu */
@@ -226,6 +225,8 @@ out:
return -ENOMEM;
}
+#ifdef CONFIG_HOTPLUG_CPU
+
static void pcpu_free_lowcore(struct pcpu *pcpu)
{
pcpu_sigp_retry(pcpu, sigp_set_prefix, 0);
@@ -247,6 +248,8 @@ static void pcpu_free_lowcore(struct pcpu *pcpu)
}
}
+#endif /* CONFIG_HOTPLUG_CPU */
+
static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu)
{
struct _lowcore *lc = pcpu->lowcore;
@@ -721,26 +724,9 @@ static void __cpuinit smp_start_secondary(void *cpuvoid)
cpu_idle();
}
-struct create_idle {
- struct work_struct work;
- struct task_struct *idle;
- struct completion done;
- int cpu;
-};
-
-static void __cpuinit smp_fork_idle(struct work_struct *work)
-{
- struct create_idle *c_idle;
-
- c_idle = container_of(work, struct create_idle, work);
- c_idle->idle = fork_idle(c_idle->cpu);
- complete(&c_idle->done);
-}
-
/* Upping and downing of CPUs */
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
- struct create_idle c_idle;
struct pcpu *pcpu;
int rc;
@@ -750,22 +736,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
if (pcpu_sigp_retry(pcpu, sigp_initial_cpu_reset, 0) !=
sigp_order_code_accepted)
return -EIO;
- if (!pcpu->idle) {
- c_idle.done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done);
- INIT_WORK_ONSTACK(&c_idle.work, smp_fork_idle);
- c_idle.cpu = cpu;
- schedule_work(&c_idle.work);
- wait_for_completion(&c_idle.done);
- if (IS_ERR(c_idle.idle))
- return PTR_ERR(c_idle.idle);
- pcpu->idle = c_idle.idle;
- }
- init_idle(pcpu->idle, cpu);
+
rc = pcpu_alloc_lowcore(pcpu, cpu);
if (rc)
return rc;
pcpu_prepare_secondary(pcpu, cpu);
- pcpu_attach_task(pcpu, pcpu->idle);
+ pcpu_attach_task(pcpu, tidle);
pcpu_start_fn(pcpu, smp_start_secondary, NULL);
while (!cpu_online(cpu))
cpu_relax();
@@ -852,7 +828,6 @@ void __init smp_prepare_boot_cpu(void)
struct pcpu *pcpu = pcpu_devices;
boot_cpu_address = stap();
- pcpu->idle = current;
pcpu->state = CPU_STATE_CONFIGURED;
pcpu->address = boot_cpu_address;
pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix();
diff --git a/arch/s390/kernel/vdso32/.gitignore b/arch/s390/kernel/vdso32/.gitignore
new file mode 100644
index 000000000000..e45fba9d0ced
--- /dev/null
+++ b/arch/s390/kernel/vdso32/.gitignore
@@ -0,0 +1 @@
+vdso32.lds
diff --git a/arch/s390/kernel/vdso64/.gitignore b/arch/s390/kernel/vdso64/.gitignore
new file mode 100644
index 000000000000..3fd18cf9fec2
--- /dev/null
+++ b/arch/s390/kernel/vdso64/.gitignore
@@ -0,0 +1 @@
+vdso64.lds
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 46ef3fd0663b..72cec9ecd96c 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -294,7 +294,7 @@ static inline int do_exception(struct pt_regs *regs, int access)
down_read(&mm->mmap_sem);
#ifdef CONFIG_PGSTE
- if (test_tsk_thread_flag(current, TIF_SIE) && S390_lowcore.gmap) {
+ if ((current->flags & PF_VCPU) && S390_lowcore.gmap) {
address = __gmap_fault(address,
(struct gmap *) S390_lowcore.gmap);
if (address == -EFAULT) {
@@ -549,19 +549,15 @@ static void pfault_interrupt(struct ext_code ext_code,
if ((subcode & 0xff00) != __SUBCODE_MASK)
return;
kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++;
- if (subcode & 0x0080) {
- /* Get the token (= pid of the affected task). */
- pid = sizeof(void *) == 4 ? param32 : param64;
- rcu_read_lock();
- tsk = find_task_by_pid_ns(pid, &init_pid_ns);
- if (tsk)
- get_task_struct(tsk);
- rcu_read_unlock();
- if (!tsk)
- return;
- } else {
- tsk = current;
- }
+ /* Get the token (= pid of the affected task). */
+ pid = sizeof(void *) == 4 ? param32 : param64;
+ rcu_read_lock();
+ tsk = find_task_by_pid_ns(pid, &init_pid_ns);
+ if (tsk)
+ get_task_struct(tsk);
+ rcu_read_unlock();
+ if (!tsk)
+ return;
spin_lock(&pfault_lock);
if (subcode & 0x0080) {
/* signal bit is set -> a page has been swapped in by VM */
@@ -574,6 +570,7 @@ static void pfault_interrupt(struct ext_code ext_code,
tsk->thread.pfault_wait = 0;
list_del(&tsk->thread.list);
wake_up_process(tsk);
+ put_task_struct(tsk);
} else {
/* Completion interrupt was faster than initial
* interrupt. Set pfault_wait to -1 so the initial
@@ -585,24 +582,35 @@ static void pfault_interrupt(struct ext_code ext_code,
if (tsk->state == TASK_RUNNING)
tsk->thread.pfault_wait = -1;
}
- put_task_struct(tsk);
} else {
/* signal bit not set -> a real page is missing. */
- if (tsk->thread.pfault_wait == -1) {
+ if (WARN_ON_ONCE(tsk != current))
+ goto out;
+ if (tsk->thread.pfault_wait == 1) {
+ /* Already on the list with a reference: put to sleep */
+ __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+ set_tsk_need_resched(tsk);
+ } else if (tsk->thread.pfault_wait == -1) {
/* Completion interrupt was faster than the initial
* interrupt (pfault_wait == -1). Set pfault_wait
* back to zero and exit. */
tsk->thread.pfault_wait = 0;
} else {
/* Initial interrupt arrived before completion
- * interrupt. Let the task sleep. */
+ * interrupt. Let the task sleep.
+ * An extra task reference is needed since a different
+ * cpu may set the task state to TASK_RUNNING again
+ * before the scheduler is reached. */
+ get_task_struct(tsk);
tsk->thread.pfault_wait = 1;
list_add(&tsk->thread.list, &pfault_list);
- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+ __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
set_tsk_need_resched(tsk);
}
}
+out:
spin_unlock(&pfault_lock);
+ put_task_struct(tsk);
}
static int __cpuinit pfault_cpu_notify(struct notifier_block *self,
@@ -620,6 +628,7 @@ static int __cpuinit pfault_cpu_notify(struct notifier_block *self,
list_del(&thread->list);
tsk = container_of(thread, struct task_struct, thread);
wake_up_process(tsk);
+ put_task_struct(tsk);
}
spin_unlock_irq(&pfault_lock);
break;
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index 597bb2d27c3c..900de2b3cf28 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -58,6 +58,8 @@ void arch_release_hugepage(struct page *page)
ptep = (pte_t *) page[1].index;
if (!ptep)
return;
+ clear_table((unsigned long *) ptep, _PAGE_TYPE_EMPTY,
+ PTRS_PER_PTE * sizeof(pte_t));
page_table_free(&init_mm, (unsigned long *) ptep);
page[1].index = 0;
}
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
index e1335dc2b1b7..795a0a9bb2eb 100644
--- a/arch/s390/mm/maccess.c
+++ b/arch/s390/mm/maccess.c
@@ -12,6 +12,7 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/gfp.h>
+#include <linux/cpu.h>
#include <asm/ctl_reg.h>
/*
@@ -166,3 +167,69 @@ out:
free_page((unsigned long) buf);
return rc;
}
+
+/*
+ * Check if physical address is within prefix or zero page
+ */
+static int is_swapped(unsigned long addr)
+{
+ unsigned long lc;
+ int cpu;
+
+ if (addr < sizeof(struct _lowcore))
+ return 1;
+ for_each_online_cpu(cpu) {
+ lc = (unsigned long) lowcore_ptr[cpu];
+ if (addr > lc + sizeof(struct _lowcore) - 1 || addr < lc)
+ continue;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Return swapped prefix or zero page address
+ */
+static unsigned long get_swapped(unsigned long addr)
+{
+ unsigned long prefix = store_prefix();
+
+ if (addr < sizeof(struct _lowcore))
+ return addr + prefix;
+ if (addr >= prefix && addr < prefix + sizeof(struct _lowcore))
+ return addr - prefix;
+ return addr;
+}
+
+/*
+ * Convert a physical pointer for /dev/mem access
+ *
+ * For swapped prefix pages a new buffer is returned that contains a copy of
+ * the absolute memory. The buffer size is maximum one page large.
+ */
+void *xlate_dev_mem_ptr(unsigned long addr)
+{
+ void *bounce = (void *) addr;
+ unsigned long size;
+
+ get_online_cpus();
+ preempt_disable();
+ if (is_swapped(addr)) {
+ size = PAGE_SIZE - (addr & ~PAGE_MASK);
+ bounce = (void *) __get_free_page(GFP_ATOMIC);
+ if (bounce)
+ memcpy_real(bounce, (void *) get_swapped(addr), size);
+ }
+ preempt_enable();
+ put_online_cpus();
+ return bounce;
+}
+
+/*
+ * Free converted buffer for /dev/mem access (if necessary)
+ */
+void unxlate_dev_mem_ptr(unsigned long addr, void *buf)
+{
+ if ((void *) addr != buf)
+ free_page((unsigned long) buf);
+}
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 6e765bf00670..a3db5a3ea083 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -822,6 +822,8 @@ int s390_enable_sie(void)
/* we copy the mm and let dup_mm create the page tables with_pgstes */
tsk->mm->context.alloc_pgste = 1;
+ /* make sure that both mms have a correct rss state */
+ sync_mm_rss(tsk->mm);
mm = dup_mm(tsk);
tsk->mm->context.alloc_pgste = 0;
if (!mm)
diff --git a/arch/score/include/asm/processor.h b/arch/score/include/asm/processor.h
index 7e22f216d771..ab3aceb54209 100644
--- a/arch/score/include/asm/processor.h
+++ b/arch/score/include/asm/processor.h
@@ -26,7 +26,6 @@ extern unsigned long get_wchan(struct task_struct *p);
#define cpu_relax() barrier()
#define release_thread(thread) do {} while (0)
-#define prepare_to_copy(tsk) do {} while (0)
/*
* User space process size: 2GB. This is hardcoded into a few places,
diff --git a/arch/score/include/asm/thread_info.h b/arch/score/include/asm/thread_info.h
index 2205c62284db..a18006e97f1c 100644
--- a/arch/score/include/asm/thread_info.h
+++ b/arch/score/include/asm/thread_info.h
@@ -11,10 +11,9 @@
#include <linux/const.h>
/* thread information allocation */
-#define THREAD_SIZE_ORDER (1)
-#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
-#define THREAD_MASK (THREAD_SIZE - _AC(1,UL))
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+#define THREAD_SIZE_ORDER (1)
+#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
+#define THREAD_MASK (THREAD_SIZE - _AC(1,UL))
#ifndef __ASSEMBLY__
@@ -71,9 +70,6 @@ struct thread_info {
register struct thread_info *__current_thread_info __asm__("r28");
#define current_thread_info() __current_thread_info
-#define alloc_thread_info_node(tsk, node) kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
-#define free_thread_info(info) kfree(info)
-
#endif /* !__ASSEMBLY__ */
#define PREEMPT_ACTIVE 0x10000000
diff --git a/arch/score/kernel/Makefile b/arch/score/kernel/Makefile
index f218673b5d3d..fb1802b3f542 100644
--- a/arch/score/kernel/Makefile
+++ b/arch/score/kernel/Makefile
@@ -4,7 +4,7 @@
extra-y := head.o vmlinux.lds
-obj-y += entry.o init_task.o irq.o process.o ptrace.o \
+obj-y += entry.o irq.o process.o ptrace.o \
setup.o signal.o sys_score.o time.o traps.o \
sys_call_table.o
diff --git a/arch/score/kernel/init_task.c b/arch/score/kernel/init_task.c
deleted file mode 100644
index baa03ee217d1..000000000000
--- a/arch/score/kernel/init_task.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * arch/score/kernel/init_task.c
- *
- * Score Processor version.
- *
- * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/init_task.h>
-#include <linux/mqueue.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is THREAD_SIZE aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index ff9e033ce626..3e723aaa5e18 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -28,6 +28,7 @@ config SUPERH
select RTC_LIB
select GENERIC_ATOMIC64
select GENERIC_IRQ_SHOW
+ select GENERIC_SMP_IDLE_THREAD
help
The SuperH is a RISC processor targeted for use in embedded systems
and consumer electronics; it was also used in the Sega Dreamcast
@@ -152,12 +153,10 @@ config ARCH_NO_VIRT_TO_BUS
config ARCH_HAS_DEFAULT_IDLE
def_bool y
-config ARCH_HAS_CPU_IDLE_WAIT
- def_bool y
-
config NO_IOPORT
def_bool !PCI
- depends on !SH_CAYMAN && !SH_SH4202_MICRODEV && !SH_SHMIN
+ depends on !SH_CAYMAN && !SH_SH4202_MICRODEV && !SH_SHMIN && \
+ !SH_HP6XX && !SH_SOLUTION_ENGINE
config IO_TRAPPED
bool
@@ -288,6 +287,20 @@ config CPU_SUBTYPE_SH7263
select SYS_SUPPORTS_CMT
select SYS_SUPPORTS_MTU2
+config CPU_SUBTYPE_SH7264
+ bool "Support SH7264 processor"
+ select CPU_SH2A
+ select CPU_HAS_FPU
+ select SYS_SUPPORTS_CMT
+ select SYS_SUPPORTS_MTU2
+
+config CPU_SUBTYPE_SH7269
+ bool "Support SH7269 processor"
+ select CPU_SH2A
+ select CPU_HAS_FPU
+ select SYS_SUPPORTS_CMT
+ select SYS_SUPPORTS_MTU2
+
config CPU_SUBTYPE_MXG
bool "Support MX-G processor"
select CPU_SH2A
@@ -427,6 +440,16 @@ config CPU_SUBTYPE_SH7724
help
Select SH7724 if you have an SH-MobileR2R CPU.
+config CPU_SUBTYPE_SH7734
+ bool "Support SH7734 processor"
+ select CPU_SH4A
+ select CPU_SHX2
+ select ARCH_WANT_OPTIONAL_GPIOLIB
+ select USB_ARCH_HAS_OHCI
+ select USB_ARCH_HAS_EHCI
+ help
+ Select SH7734 if you have a SH4A SH7734 CPU.
+
config CPU_SUBTYPE_SH7757
bool "Support SH7757 processor"
select CPU_SH4A
@@ -584,7 +607,9 @@ config SH_CLK_CPG
config SH_CLK_CPG_LEGACY
depends on SH_CLK_CPG
def_bool y if !CPU_SUBTYPE_SH7785 && !ARCH_SHMOBILE && \
- !CPU_SHX3 && !CPU_SUBTYPE_SH7757
+ !CPU_SHX3 && !CPU_SUBTYPE_SH7757 && \
+ !CPU_SUBTYPE_SH7734 && !CPU_SUBTYPE_SH7264 && \
+ !CPU_SUBTYPE_SH7269
source "kernel/time/Kconfig"
@@ -685,6 +710,20 @@ config SECCOMP
If unsure, say N.
+config CC_STACKPROTECTOR
+ bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
+ depends on SUPERH32 && EXPERIMENTAL
+ help
+ This option turns on the -fstack-protector GCC feature. This
+ feature puts, at the beginning of functions, a canary value on
+ the stack just before the return address, and validates
+ the value just before actually returning. Stack based buffer
+ overflows (that need to overwrite this return address) now also
+ overwrite the canary, which gets detected and the attack is then
+ neutralized via a kernel panic.
+
+ This feature requires gcc version 4.2 or above.
+
config SMP
bool "Symmetric multi-processing support"
depends on SYS_SUPPORTS_SMP
diff --git a/arch/sh/Kconfig.cpu b/arch/sh/Kconfig.cpu
index ddf096c7d8bf..770ff2d5b94d 100644
--- a/arch/sh/Kconfig.cpu
+++ b/arch/sh/Kconfig.cpu
@@ -1,7 +1,7 @@
menu "Processor features"
choice
- prompt "Endianess selection"
+ prompt "Endianness selection"
default CPU_LITTLE_ENDIAN
help
Some SuperH machines can be configured for either little or big
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 3fc0f413777c..46edf070da1c 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -124,7 +124,7 @@ endif
export ld-bfd BITS
-head-y := arch/sh/kernel/init_task.o arch/sh/kernel/head_$(BITS).o
+head-y := arch/sh/kernel/head_$(BITS).o
core-y += arch/sh/kernel/ arch/sh/mm/ arch/sh/boards/
core-$(CONFIG_SH_FPU_EMU) += arch/sh/math-emu/
@@ -199,6 +199,10 @@ ifeq ($(CONFIG_DWARF_UNWINDER),y)
KBUILD_CFLAGS += -fasynchronous-unwind-tables
endif
+ifeq ($(CONFIG_CC_STACKPROTECTOR),y)
+ KBUILD_CFLAGS += -fstack-protector
+endif
+
libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y)
libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y)
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index d893411022d5..1f56b35d3248 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -54,6 +54,7 @@ config SH_7724_SOLUTION_ENGINE
select SOLUTION_ENGINE
depends on CPU_SUBTYPE_SH7724
select ARCH_REQUIRE_GPIOLIB
+ select SND_SOC_AK4642 if SND_SIMPLE_CARD
help
Select 7724 SolutionEngine if configuring for a Hitachi SH7724
evaluation board.
@@ -133,7 +134,8 @@ config SH_RTS7751R2D
config SH_RSK
bool "Renesas Starter Kit"
- depends on CPU_SUBTYPE_SH7201 || CPU_SUBTYPE_SH7203
+ depends on CPU_SUBTYPE_SH7201 || CPU_SUBTYPE_SH7203 || \
+ CPU_SUBTYPE_SH7264 || CPU_SUBTYPE_SH7269
help
Select this option if configuring for any of the RSK+ MCU
evaluation platforms.
@@ -223,6 +225,7 @@ config SH_ECOVEC
bool "EcoVec"
depends on CPU_SUBTYPE_SH7724
select ARCH_REQUIRE_GPIOLIB
+ select SND_SOC_DA7210 if SND_SIMPLE_CARD
help
Renesas "R0P7724LC0011/21RL (EcoVec)" support.
@@ -338,8 +341,6 @@ config SH_APSH4AD0A
help
Select AP-SH4AD-0A if configuring for an ALPHAPROJECT AP-SH4AD-0A.
-endmenu
-
source "arch/sh/boards/mach-r2d/Kconfig"
source "arch/sh/boards/mach-highlander/Kconfig"
source "arch/sh/boards/mach-sdk7780/Kconfig"
@@ -359,3 +360,5 @@ config SH_MAGIC_PANEL_R2_VERSION
endmenu
endif
+
+endmenu
diff --git a/arch/sh/boards/board-edosk7705.c b/arch/sh/boards/board-edosk7705.c
index 541d8a281035..5e24c17bbdad 100644
--- a/arch/sh/boards/board-edosk7705.c
+++ b/arch/sh/boards/board-edosk7705.c
@@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/smc91x.h>
+#include <linux/sh_intc.h>
#include <asm/machvec.h>
#include <asm/sizes.h>
@@ -20,7 +21,7 @@
#define SMC_IO_OFFSET 0x300
#define SMC_IOADDR (SMC_IOBASE + SMC_IO_OFFSET)
-#define ETHERNET_IRQ 0x09
+#define ETHERNET_IRQ evt2irq(0x320)
static void __init sh_edosk7705_init_irq(void)
{
@@ -73,6 +74,5 @@ device_initcall(init_edosk7705_devices);
*/
static struct sh_machine_vector mv_edosk7705 __initmv = {
.mv_name = "EDOSK7705",
- .mv_nr_irqs = 80,
.mv_init_irq = sh_edosk7705_init_irq,
};
diff --git a/arch/sh/boards/board-edosk7760.c b/arch/sh/boards/board-edosk7760.c
index e9656a2cc4cc..bab5b9513904 100644
--- a/arch/sh/boards/board-edosk7760.c
+++ b/arch/sh/boards/board-edosk7760.c
@@ -23,6 +23,7 @@
#include <linux/platform_device.h>
#include <linux/smc91x.h>
#include <linux/interrupt.h>
+#include <linux/sh_intc.h>
#include <linux/i2c.h>
#include <linux/mtd/physmap.h>
#include <asm/machvec.h>
@@ -40,8 +41,6 @@
#define SMC_IO_OFFSET 0x300
#define SMC_IOADDR (SMC_IOBASE + SMC_IO_OFFSET)
-#define ETHERNET_IRQ 5
-
/* NOR flash */
static struct mtd_partition edosk7760_nor_flash_partitions[] = {
{
@@ -99,8 +98,8 @@ static struct resource sh7760_i2c1_res[] = {
.end = SH7760_I2C1_MMIOEND,
.flags = IORESOURCE_MEM,
},{
- .start = SH7760_I2C1_IRQ,
- .end = SH7760_I2C1_IRQ,
+ .start = evt2irq(0x9e0),
+ .end = evt2irq(0x9e0),
.flags = IORESOURCE_IRQ,
},
};
@@ -122,8 +121,8 @@ static struct resource sh7760_i2c0_res[] = {
.end = SH7760_I2C0_MMIOEND,
.flags = IORESOURCE_MEM,
}, {
- .start = SH7760_I2C0_IRQ,
- .end = SH7760_I2C0_IRQ,
+ .start = evt2irq(0x9c0),
+ .end = evt2irq(0x9c0),
.flags = IORESOURCE_IRQ,
},
};
@@ -150,8 +149,8 @@ static struct resource smc91x_res[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = ETHERNET_IRQ,
- .end = ETHERNET_IRQ,
+ .start = evt2irq(0x2a0),
+ .end = evt2irq(0x2a0),
.flags = IORESOURCE_IRQ ,
}
};
@@ -189,5 +188,4 @@ device_initcall(init_edosk7760_devices);
*/
struct sh_machine_vector mv_edosk7760 __initmv = {
.mv_name = "EDOSK7760",
- .mv_nr_irqs = 128,
};
diff --git a/arch/sh/boards/board-espt.c b/arch/sh/boards/board-espt.c
index b3ae9d38cbc0..6cba0a7068bc 100644
--- a/arch/sh/boards/board-espt.c
+++ b/arch/sh/boards/board-espt.c
@@ -14,6 +14,7 @@
#include <linux/mtd/physmap.h>
#include <linux/io.h>
#include <linux/sh_eth.h>
+#include <linux/sh_intc.h>
#include <asm/machvec.h>
#include <asm/sizes.h>
@@ -71,7 +72,7 @@ static struct resource sh_eth_resources[] = {
.flags = IORESOURCE_MEM,
}, {
- .start = 57, /* irq number */
+ .start = evt2irq(0x920), /* irq number */
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/boards/board-magicpanelr2.c b/arch/sh/boards/board-magicpanelr2.c
index b2ca1d9948fb..90568f9de3a4 100644
--- a/arch/sh/boards/board-magicpanelr2.c
+++ b/arch/sh/boards/board-magicpanelr2.c
@@ -19,6 +19,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/mtd/map.h>
+#include <linux/sh_intc.h>
#include <mach/magicpanelr2.h>
#include <asm/heartbeat.h>
#include <cpu/sh7720.h>
@@ -245,8 +246,8 @@ static struct resource smsc911x_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 35,
- .end = 35,
+ .start = evt2irq(0x660),
+ .end = evt2irq(0x660),
.flags = IORESOURCE_IRQ,
},
};
@@ -358,17 +359,17 @@ static void __init init_mpr2_IRQ(void)
{
plat_irq_setup_pins(IRQ_MODE_IRQ); /* install handlers for IRQ0-5 */
- irq_set_irq_type(32, IRQ_TYPE_LEVEL_LOW); /* IRQ0 CAN1 */
- irq_set_irq_type(33, IRQ_TYPE_LEVEL_LOW); /* IRQ1 CAN2 */
- irq_set_irq_type(34, IRQ_TYPE_LEVEL_LOW); /* IRQ2 CAN3 */
- irq_set_irq_type(35, IRQ_TYPE_LEVEL_LOW); /* IRQ3 SMSC9115 */
- irq_set_irq_type(36, IRQ_TYPE_EDGE_RISING); /* IRQ4 touchscreen */
- irq_set_irq_type(37, IRQ_TYPE_EDGE_FALLING); /* IRQ5 touchscreen */
-
- intc_set_priority(32, 13); /* IRQ0 CAN1 */
- intc_set_priority(33, 13); /* IRQ0 CAN2 */
- intc_set_priority(34, 13); /* IRQ0 CAN3 */
- intc_set_priority(35, 6); /* IRQ3 SMSC9115 */
+ irq_set_irq_type(evt2irq(0x600), IRQ_TYPE_LEVEL_LOW); /* IRQ0 CAN1 */
+ irq_set_irq_type(evt2irq(0x620), IRQ_TYPE_LEVEL_LOW); /* IRQ1 CAN2 */
+ irq_set_irq_type(evt2irq(0x640), IRQ_TYPE_LEVEL_LOW); /* IRQ2 CAN3 */
+ irq_set_irq_type(evt2irq(0x660), IRQ_TYPE_LEVEL_LOW); /* IRQ3 SMSC9115 */
+ irq_set_irq_type(evt2irq(0x680), IRQ_TYPE_EDGE_RISING); /* IRQ4 touchscreen */
+ irq_set_irq_type(evt2irq(0x6a0), IRQ_TYPE_EDGE_FALLING); /* IRQ5 touchscreen */
+
+ intc_set_priority(evt2irq(0x600), 13); /* IRQ0 CAN1 */
+ intc_set_priority(evt2irq(0x620), 13); /* IRQ0 CAN2 */
+ intc_set_priority(evt2irq(0x640), 13); /* IRQ0 CAN3 */
+ intc_set_priority(evt2irq(0x660), 6); /* IRQ3 SMSC9115 */
}
/*
diff --git a/arch/sh/boards/board-polaris.c b/arch/sh/boards/board-polaris.c
index 594866356c24..37d03c097ae9 100644
--- a/arch/sh/boards/board-polaris.c
+++ b/arch/sh/boards/board-polaris.c
@@ -141,6 +141,5 @@ static void __init init_polaris_irq(void)
static struct sh_machine_vector mv_polaris __initmv = {
.mv_name = "Polaris",
- .mv_nr_irqs = 61,
.mv_init_irq = init_polaris_irq,
};
diff --git a/arch/sh/boards/board-secureedge5410.c b/arch/sh/boards/board-secureedge5410.c
index 03820c3c93d4..98b36205aa7b 100644
--- a/arch/sh/boards/board-secureedge5410.c
+++ b/arch/sh/boards/board-secureedge5410.c
@@ -71,6 +71,5 @@ static void __init init_snapgear_IRQ(void)
*/
static struct sh_machine_vector mv_snapgear __initmv = {
.mv_name = "SnapGear SecureEdge5410",
- .mv_nr_irqs = 72,
.mv_init_irq = init_snapgear_IRQ,
};
diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c
index 24b1ee410daa..5087f8bb4cff 100644
--- a/arch/sh/boards/board-sh7757lcr.c
+++ b/arch/sh/boards/board-sh7757lcr.c
@@ -19,6 +19,7 @@
#include <linux/mmc/sh_mmcif.h>
#include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/sh_eth.h>
+#include <linux/sh_intc.h>
#include <linux/usb/renesas_usbhs.h>
#include <cpu/sh7757.h>
#include <asm/heartbeat.h>
@@ -65,8 +66,8 @@ static struct resource sh_eth0_resources[] = {
.end = 0xfef001ff,
.flags = IORESOURCE_MEM,
}, {
- .start = 84,
- .end = 84,
+ .start = evt2irq(0xc80),
+ .end = evt2irq(0xc80),
.flags = IORESOURCE_IRQ,
},
};
@@ -94,8 +95,8 @@ static struct resource sh_eth1_resources[] = {
.end = 0xfef009ff,
.flags = IORESOURCE_MEM,
}, {
- .start = 84,
- .end = 84,
+ .start = evt2irq(0xc80),
+ .end = evt2irq(0xc80),
.flags = IORESOURCE_IRQ,
},
};
@@ -139,8 +140,8 @@ static struct resource sh_eth_giga0_resources[] = {
.end = 0xfee01fff,
.flags = IORESOURCE_MEM,
}, {
- .start = 315,
- .end = 315,
+ .start = evt2irq(0x2960),
+ .end = evt2irq(0x2960),
.flags = IORESOURCE_IRQ,
},
};
@@ -174,8 +175,8 @@ static struct resource sh_eth_giga1_resources[] = {
.end = 0xfee01fff,
.flags = IORESOURCE_MEM,
}, {
- .start = 316,
- .end = 316,
+ .start = evt2irq(0x2980),
+ .end = evt2irq(0x2980),
.flags = IORESOURCE_IRQ,
},
};
@@ -206,11 +207,11 @@ static struct resource sh_mmcif_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 211,
+ .start = evt2irq(0x1c60),
.flags = IORESOURCE_IRQ,
},
[2] = {
- .start = 212,
+ .start = evt2irq(0x1c80),
.flags = IORESOURCE_IRQ,
},
};
@@ -248,7 +249,7 @@ static struct resource sdhi_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -284,8 +285,8 @@ static struct resource usb0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 50,
- .end = 50,
+ .start = evt2irq(0x840),
+ .end = evt2irq(0x840),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c
index d0d6221d7c2e..2c4771ee84cd 100644
--- a/arch/sh/boards/board-sh7785lcr.c
+++ b/arch/sh/boards/board-sh7785lcr.c
@@ -20,6 +20,7 @@
#include <linux/i2c-pca-platform.h>
#include <linux/i2c-algo-pca.h>
#include <linux/usb/r8a66597.h>
+#include <linux/sh_intc.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/clk.h>
@@ -105,8 +106,8 @@ static struct resource r8a66597_usb_host_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 2,
- .end = 2,
+ .start = evt2irq(0x240),
+ .end = evt2irq(0x240),
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
},
};
@@ -135,7 +136,7 @@ static struct resource sm501_resources[] = {
.flags = IORESOURCE_MEM,
},
[2] = {
- .start = 10,
+ .start = evt2irq(0x340),
.flags = IORESOURCE_IRQ,
},
};
@@ -223,8 +224,8 @@ static struct resource i2c_proto_resources[] = {
.flags = IORESOURCE_MEM | IORESOURCE_MEM_8BIT,
},
[1] = {
- .start = 12,
- .end = 12,
+ .start = evt2irq(0x380),
+ .end = evt2irq(0x380),
.flags = IORESOURCE_IRQ,
},
};
@@ -236,8 +237,8 @@ static struct resource i2c_resources[] = {
.flags = IORESOURCE_MEM | IORESOURCE_MEM_8BIT,
},
[1] = {
- .start = 12,
- .end = 12,
+ .start = evt2irq(0x380),
+ .end = evt2irq(0x380),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/boards/board-urquell.c b/arch/sh/boards/board-urquell.c
index 24e3316c5c17..b52abcc5259a 100644
--- a/arch/sh/boards/board-urquell.c
+++ b/arch/sh/boards/board-urquell.c
@@ -20,6 +20,7 @@
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/clk.h>
+#include <linux/sh_intc.h>
#include <mach/urquell.h>
#include <cpu/sh7786.h>
#include <asm/heartbeat.h>
@@ -78,7 +79,7 @@ static struct resource smc91x_eth_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 11,
+ .start = evt2irq(0x360),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c
index 8cf02e343333..f33ebf447073 100644
--- a/arch/sh/boards/mach-ap325rxa/setup.c
+++ b/arch/sh/boards/mach-ap325rxa/setup.c
@@ -23,6 +23,7 @@
#include <linux/smsc911x.h>
#include <linux/gpio.h>
#include <linux/videodev2.h>
+#include <linux/sh_intc.h>
#include <media/ov772x.h>
#include <media/soc_camera.h>
#include <media/soc_camera_platform.h>
@@ -47,8 +48,8 @@ static struct resource smsc9118_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 35,
- .end = 35,
+ .start = evt2irq(0x660),
+ .end = evt2irq(0x660),
.flags = IORESOURCE_IRQ,
}
};
@@ -166,7 +167,7 @@ static int ap320_wvga_set_brightness(int brightness)
__raw_writew(0, FPGA_BKLREG);
gpio_set_value(GPIO_PTS3, 1);
}
-
+
return 0;
}
@@ -236,7 +237,7 @@ static struct resource lcdc_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 28,
+ .start = evt2irq(0x580),
.flags = IORESOURCE_IRQ,
},
};
@@ -404,7 +405,7 @@ static struct resource ceu_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 52,
+ .start = evt2irq(0x880),
.flags = IORESOURCE_IRQ,
},
[2] = {
@@ -430,7 +431,7 @@ static struct resource sdhi0_cn3_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 100,
+ .start = evt2irq(0xe80),
.flags = IORESOURCE_IRQ,
},
};
@@ -457,7 +458,7 @@ static struct resource sdhi1_cn7_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 23,
+ .start = evt2irq(0x4e0),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/boards/mach-cayman/setup.c b/arch/sh/boards/mach-cayman/setup.c
index e89e8e122a26..340fd40b381d 100644
--- a/arch/sh/boards/mach-cayman/setup.c
+++ b/arch/sh/boards/mach-cayman/setup.c
@@ -181,7 +181,6 @@ extern void init_cayman_irq(void);
static struct sh_machine_vector mv_cayman __initmv = {
.mv_name = "Hitachi Cayman",
- .mv_nr_irqs = 64,
.mv_ioport_map = cayman_ioport_map,
.mv_init_irq = init_cayman_irq,
};
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index d12fe9ddf3da..4158d70c0dea 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -29,9 +29,11 @@
#include <linux/input.h>
#include <linux/input/sh_keysc.h>
#include <linux/sh_eth.h>
+#include <linux/sh_intc.h>
#include <linux/videodev2.h>
#include <video/sh_mobile_lcdc.h>
#include <sound/sh_fsi.h>
+#include <sound/simple_card.h>
#include <media/sh_mobile_ceu.h>
#include <media/soc_camera.h>
#include <media/tw9910.h>
@@ -137,7 +139,7 @@ static struct resource sh_eth_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 91,
+ .start = evt2irq(0xd60),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
},
};
@@ -178,8 +180,8 @@ static struct resource usb0_host_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 65,
- .end = 65,
+ .start = evt2irq(0xa20),
+ .end = evt2irq(0xa20),
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
},
};
@@ -214,8 +216,8 @@ static struct resource usb1_common_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 66,
- .end = 66,
+ .start = evt2irq(0xa40),
+ .end = evt2irq(0xa40),
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
},
};
@@ -261,8 +263,8 @@ static struct resource usbhs_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 66,
- .end = 66,
+ .start = evt2irq(0xa40),
+ .end = evt2irq(0xa40),
.flags = IORESOURCE_IRQ,
},
};
@@ -348,7 +350,7 @@ static struct resource lcdc_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 106,
+ .start = evt2irq(0xf40),
.flags = IORESOURCE_IRQ,
},
};
@@ -375,7 +377,7 @@ static struct resource ceu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 52,
+ .start = evt2irq(0x880),
.flags = IORESOURCE_IRQ,
},
[2] = {
@@ -406,7 +408,7 @@ static struct resource ceu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 63,
+ .start = evt2irq(0x9e0),
.flags = IORESOURCE_IRQ,
},
[2] = {
@@ -437,7 +439,7 @@ static struct i2c_board_info i2c1_devices[] = {
},
{
I2C_BOARD_INFO("lis3lv02d", 0x1c),
- .irq = 33,
+ .irq = evt2irq(0x620),
}
};
@@ -463,7 +465,7 @@ static struct resource keysc_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 79,
+ .start = evt2irq(0xbe0),
.flags = IORESOURCE_IRQ,
},
};
@@ -479,7 +481,8 @@ static struct platform_device keysc_device = {
};
/* TouchScreen */
-#define IRQ0 32
+#define IRQ0 evt2irq(0x600)
+
static int ts_get_pendown_state(void)
{
int val = 0;
@@ -544,7 +547,7 @@ static struct resource sdhi0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 100,
+ .start = evt2irq(0xe80),
.flags = IORESOURCE_IRQ,
},
};
@@ -588,7 +591,7 @@ static struct resource sdhi1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 23,
+ .start = evt2irq(0x4e0),
.flags = IORESOURCE_IRQ,
},
};
@@ -653,7 +656,7 @@ static struct resource msiof0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 84,
+ .start = evt2irq(0xc80),
.flags = IORESOURCE_IRQ,
},
};
@@ -794,7 +797,7 @@ static struct resource fsi_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 108,
+ .start = evt2irq(0xf80),
.flags = IORESOURCE_IRQ,
},
};
@@ -809,6 +812,30 @@ static struct platform_device fsi_device = {
},
};
+static struct asoc_simple_dai_init_info fsi_da7210_init_info = {
+ .fmt = SND_SOC_DAIFMT_I2S,
+ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
+ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
+};
+
+static struct asoc_simple_card_info fsi_da7210_info = {
+ .name = "DA7210",
+ .card = "FSIB-DA7210",
+ .cpu_dai = "fsib-dai",
+ .codec = "da7210.0-001a",
+ .platform = "sh_fsi.0",
+ .codec_dai = "da7210-hifi",
+ .init = &fsi_da7210_init_info,
+};
+
+static struct platform_device fsi_da7210_device = {
+ .name = "asoc-simple-card",
+ .dev = {
+ .platform_data = &fsi_da7210_info,
+ },
+};
+
+
/* IrDA */
static struct resource irda_resources[] = {
[0] = {
@@ -818,7 +845,7 @@ static struct resource irda_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -855,7 +882,7 @@ static struct resource sh_vou_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 55,
+ .start = evt2irq(0x8e0),
.flags = IORESOURCE_IRQ,
},
};
@@ -891,12 +918,12 @@ static struct resource sh_mmcif_resources[] = {
},
[1] = {
/* MMC2I */
- .start = 29,
+ .start = evt2irq(0x5a0),
.flags = IORESOURCE_IRQ,
},
[2] = {
/* MMC3I */
- .start = 30,
+ .start = evt2irq(0x5c0),
.flags = IORESOURCE_IRQ,
},
};
@@ -945,6 +972,7 @@ static struct platform_device *ecovec_devices[] __initdata = {
&camera_devices[1],
&camera_devices[2],
&fsi_device,
+ &fsi_da7210_device,
&irda_device,
&vou_device,
#if defined(CONFIG_MMC_SH_MMCIF) || defined(CONFIG_MMC_SH_MMCIF_MODULE)
diff --git a/arch/sh/boards/mach-hp6xx/setup.c b/arch/sh/boards/mach-hp6xx/setup.c
index 8c9add5f4cfa..05797b33f68e 100644
--- a/arch/sh/boards/mach-hp6xx/setup.c
+++ b/arch/sh/boards/mach-hp6xx/setup.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
+#include <linux/sh_intc.h>
#include <sound/sh_dac_audio.h>
#include <asm/hd64461.h>
#include <asm/io.h>
@@ -35,7 +36,7 @@ static struct resource cf_ide_resources[] = {
.flags = IORESOURCE_MEM,
},
[2] = {
- .start = 77,
+ .start = evt2irq(0xba0),
.flags = IORESOURCE_IRQ,
},
};
@@ -168,8 +169,6 @@ device_initcall(hp6xx_devices_setup);
static struct sh_machine_vector mv_hp6xx __initmv = {
.mv_name = "hp6xx",
.mv_setup = hp6xx_setup,
- /* IRQ's : CPU(64) + CCHIP(16) + FREE_TO_USE(6) */
- .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM + 6,
/* Enable IRQ0 -> IRQ3 in IRQ_MODE */
.mv_init_irq = hp6xx_init_irq,
};
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
index d04a55d3b877..158c9176e42a 100644
--- a/arch/sh/boards/mach-kfr2r09/setup.c
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -23,6 +23,7 @@
#include <linux/i2c.h>
#include <linux/usb/r8a66597.h>
#include <linux/videodev2.h>
+#include <linux/sh_intc.h>
#include <media/rj54n1cb0c.h>
#include <media/soc_camera.h>
#include <media/sh_mobile_ceu.h>
@@ -110,7 +111,7 @@ static struct resource kfr2r09_sh_keysc_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 79,
+ .start = evt2irq(0xbe0),
.flags = IORESOURCE_IRQ,
},
};
@@ -175,7 +176,7 @@ static struct resource kfr2r09_sh_lcdc_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 106,
+ .start = evt2irq(0xf40),
.flags = IORESOURCE_IRQ,
},
};
@@ -200,8 +201,8 @@ static struct resource kfr2r09_usb0_gadget_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 65,
- .end = 65,
+ .start = evtirq(0xa20),
+ .end = evtirq(0xa20),
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
},
};
@@ -230,8 +231,8 @@ static struct resource kfr2r09_ceu_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 52,
- .end = 52,
+ .start = evt2irq(0x880),
+ .end = evt2irq(0x880),
.flags = IORESOURCE_IRQ,
},
[2] = {
@@ -348,7 +349,7 @@ static struct resource kfr2r09_sh_sdhi0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 100,
+ .start = evt2irq(0xe80),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/boards/mach-lboxre2/setup.c b/arch/sh/boards/mach-lboxre2/setup.c
index 79b4e0d77b71..6660622aa457 100644
--- a/arch/sh/boards/mach-lboxre2/setup.c
+++ b/arch/sh/boards/mach-lboxre2/setup.c
@@ -79,6 +79,5 @@ device_initcall(lboxre2_devices_setup);
*/
static struct sh_machine_vector mv_lboxre2 __initmv = {
.mv_name = "L-BOX RE2",
- .mv_nr_irqs = 72,
.mv_init_irq = init_lboxre2_IRQ,
};
diff --git a/arch/sh/boards/mach-microdev/setup.c b/arch/sh/boards/mach-microdev/setup.c
index d8a747291e03..6c66ee4d842b 100644
--- a/arch/sh/boards/mach-microdev/setup.c
+++ b/arch/sh/boards/mach-microdev/setup.c
@@ -194,7 +194,6 @@ device_initcall(microdev_devices_setup);
*/
static struct sh_machine_vector mv_sh4202_microdev __initmv = {
.mv_name = "SH4-202 MicroDev",
- .mv_nr_irqs = 72,
.mv_ioport_map = microdev_ioport_map,
.mv_init_irq = init_microdev_irq,
};
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index ff6f69c6906e..34cd0c5ff2e1 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -22,6 +22,7 @@
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/videodev2.h>
+#include <linux/sh_intc.h>
#include <video/sh_mobile_lcdc.h>
#include <media/sh_mobile_ceu.h>
#include <media/ov772x.h>
@@ -54,7 +55,7 @@ static struct resource smc91x_eth_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 32, /* IRQ0 */
+ .start = evt2irq(0x600), /* IRQ0 */
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
},
};
@@ -88,7 +89,7 @@ static struct resource sh_keysc_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 79,
+ .start = evt2irq(0xbe0),
.flags = IORESOURCE_IRQ,
},
};
@@ -285,7 +286,7 @@ static struct resource migor_lcdc_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 28,
+ .start = evt2irq(0x580),
.flags = IORESOURCE_IRQ,
},
};
@@ -368,7 +369,7 @@ static struct resource migor_ceu_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 52,
+ .start = evt2irq(0x880),
.flags = IORESOURCE_IRQ,
},
[2] = {
@@ -394,7 +395,7 @@ static struct resource sdhi_cn9_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 100,
+ .start = evt2irq(0xe80),
.flags = IORESOURCE_IRQ,
},
};
@@ -420,7 +421,7 @@ static struct i2c_board_info migor_i2c_devices[] = {
},
{
I2C_BOARD_INFO("migor_ts", 0x51),
- .irq = 38, /* IRQ6 */
+ .irq = evt2irq(0x6c0), /* IRQ6 */
},
{
I2C_BOARD_INFO("wm8978", 0x1a),
diff --git a/arch/sh/boards/mach-rsk/Kconfig b/arch/sh/boards/mach-rsk/Kconfig
index aeff3b042205..458a11ffd022 100644
--- a/arch/sh/boards/mach-rsk/Kconfig
+++ b/arch/sh/boards/mach-rsk/Kconfig
@@ -13,6 +13,16 @@ config SH_RSK7203
select ARCH_REQUIRE_GPIOLIB
depends on CPU_SUBTYPE_SH7203
+config SH_RSK7264
+ bool "RSK2+SH7264"
+ select ARCH_REQUIRE_GPIOLIB
+ depends on CPU_SUBTYPE_SH7264
+
+config SH_RSK7269
+ bool "RSK2+SH7269"
+ select ARCH_REQUIRE_GPIOLIB
+ depends on CPU_SUBTYPE_SH7269
+
endchoice
endif
diff --git a/arch/sh/boards/mach-rsk/Makefile b/arch/sh/boards/mach-rsk/Makefile
index 498da75ce38b..6a4e1b538a62 100644
--- a/arch/sh/boards/mach-rsk/Makefile
+++ b/arch/sh/boards/mach-rsk/Makefile
@@ -1,2 +1,4 @@
obj-y := setup.o
obj-$(CONFIG_SH_RSK7203) += devices-rsk7203.o
+obj-$(CONFIG_SH_RSK7264) += devices-rsk7264.o
+obj-$(CONFIG_SH_RSK7269) += devices-rsk7269.o
diff --git a/arch/sh/boards/mach-rsk/devices-rsk7264.c b/arch/sh/boards/mach-rsk/devices-rsk7264.c
new file mode 100644
index 000000000000..7251e37a842f
--- /dev/null
+++ b/arch/sh/boards/mach-rsk/devices-rsk7264.c
@@ -0,0 +1,58 @@
+/*
+ * RSK+SH7264 Support.
+ *
+ * Copyright (C) 2012 Renesas Electronics Europe
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/smsc911x.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+
+static struct smsc911x_platform_config smsc911x_config = {
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+ .flags = SMSC911X_USE_16BIT | SMSC911X_SWAP_FIFO,
+};
+
+static struct resource smsc911x_resources[] = {
+ [0] = {
+ .start = 0x28000000,
+ .end = 0x280000ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 65,
+ .end = 65,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smsc911x_device = {
+ .name = "smsc911x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(smsc911x_resources),
+ .resource = smsc911x_resources,
+ .dev = {
+ .platform_data = &smsc911x_config,
+ },
+};
+
+static struct platform_device *rsk7264_devices[] __initdata = {
+ &smsc911x_device,
+};
+
+static int __init rsk7264_devices_setup(void)
+{
+ return platform_add_devices(rsk7264_devices,
+ ARRAY_SIZE(rsk7264_devices));
+}
+device_initcall(rsk7264_devices_setup);
diff --git a/arch/sh/boards/mach-rsk/devices-rsk7269.c b/arch/sh/boards/mach-rsk/devices-rsk7269.c
new file mode 100644
index 000000000000..4a544591d6f0
--- /dev/null
+++ b/arch/sh/boards/mach-rsk/devices-rsk7269.c
@@ -0,0 +1,60 @@
+/*
+ * RSK+SH7269 Support
+ *
+ * Copyright (C) 2012 Renesas Electronics Europe Ltd
+ * Copyright (C) 2012 Phil Edworthy
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/smsc911x.h>
+#include <linux/gpio.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+
+static struct smsc911x_platform_config smsc911x_config = {
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+ .flags = SMSC911X_USE_16BIT | SMSC911X_SWAP_FIFO,
+};
+
+static struct resource smsc911x_resources[] = {
+ [0] = {
+ .start = 0x24000000,
+ .end = 0x240000ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 85,
+ .end = 85,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smsc911x_device = {
+ .name = "smsc911x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(smsc911x_resources),
+ .resource = smsc911x_resources,
+ .dev = {
+ .platform_data = &smsc911x_config,
+ },
+};
+
+static struct platform_device *rsk7269_devices[] __initdata = {
+ &smsc911x_device,
+};
+
+static int __init rsk7269_devices_setup(void)
+{
+ return platform_add_devices(rsk7269_devices,
+ ARRAY_SIZE(rsk7269_devices));
+}
+device_initcall(rsk7269_devices_setup);
diff --git a/arch/sh/boards/mach-sdk7780/setup.c b/arch/sh/boards/mach-sdk7780/setup.c
index 4da38db4b5fe..2241659c3299 100644
--- a/arch/sh/boards/mach-sdk7780/setup.c
+++ b/arch/sh/boards/mach-sdk7780/setup.c
@@ -94,7 +94,6 @@ static void __init sdk7780_setup(char **cmdline_p)
static struct sh_machine_vector mv_se7780 __initmv = {
.mv_name = "Renesas SDK7780-R3" ,
.mv_setup = sdk7780_setup,
- .mv_nr_irqs = 111,
.mv_init_irq = init_sdk7780_IRQ,
};
diff --git a/arch/sh/boards/mach-se/7206/setup.c b/arch/sh/boards/mach-se/7206/setup.c
index 8ab8330e3fd1..68883ec95682 100644
--- a/arch/sh/boards/mach-se/7206/setup.c
+++ b/arch/sh/boards/mach-se/7206/setup.c
@@ -90,7 +90,6 @@ static int se7206_mode_pins(void)
static struct sh_machine_vector mv_se __initmv = {
.mv_name = "SolutionEngine",
- .mv_nr_irqs = 256,
.mv_init_irq = init_se7206_IRQ,
.mv_mode_pins = se7206_mode_pins,
};
diff --git a/arch/sh/boards/mach-se/770x/setup.c b/arch/sh/boards/mach-se/770x/setup.c
index 31330c65c0ce..9759d6ba7ffb 100644
--- a/arch/sh/boards/mach-se/770x/setup.c
+++ b/arch/sh/boards/mach-se/770x/setup.c
@@ -184,16 +184,5 @@ device_initcall(se_devices_setup);
static struct sh_machine_vector mv_se __initmv = {
.mv_name = "SolutionEngine",
.mv_setup = smsc_setup,
-#if defined(CONFIG_CPU_SH4)
- .mv_nr_irqs = 48,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
- .mv_nr_irqs = 32,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
- .mv_nr_irqs = 61,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
- .mv_nr_irqs = 86,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
- .mv_nr_irqs = 104,
-#endif
.mv_init_irq = init_se_IRQ,
};
diff --git a/arch/sh/boards/mach-se/7721/setup.c b/arch/sh/boards/mach-se/7721/setup.c
index 7416ad7ee53a..a0b3dba34ebf 100644
--- a/arch/sh/boards/mach-se/7721/setup.c
+++ b/arch/sh/boards/mach-se/7721/setup.c
@@ -92,6 +92,5 @@ static void __init se7721_setup(char **cmdline_p)
struct sh_machine_vector mv_se7721 __initmv = {
.mv_name = "Solution Engine 7721",
.mv_setup = se7721_setup,
- .mv_nr_irqs = 109,
.mv_init_irq = init_se7721_IRQ,
};
diff --git a/arch/sh/boards/mach-se/7722/setup.c b/arch/sh/boards/mach-se/7722/setup.c
index e1963fecd761..8f7f0550cfde 100644
--- a/arch/sh/boards/mach-se/7722/setup.c
+++ b/arch/sh/boards/mach-se/7722/setup.c
@@ -16,6 +16,7 @@
#include <linux/input.h>
#include <linux/input/sh_keysc.h>
#include <linux/smc91x.h>
+#include <linux/sh_intc.h>
#include <mach-se/mach/se7722.h>
#include <mach-se/mach/mrshpc.h>
#include <asm/machvec.h>
@@ -114,7 +115,7 @@ static struct resource sh_keysc_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 79,
+ .start = evt2irq(0xbe0),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index c540b16547c3..ffbf5bc7366b 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -24,10 +24,12 @@
#include <linux/input/sh_keysc.h>
#include <linux/usb/r8a66597.h>
#include <linux/sh_eth.h>
+#include <linux/sh_intc.h>
#include <linux/videodev2.h>
#include <video/sh_mobile_lcdc.h>
#include <media/sh_mobile_ceu.h>
#include <sound/sh_fsi.h>
+#include <sound/simple_card.h>
#include <asm/io.h>
#include <asm/heartbeat.h>
#include <asm/clock.h>
@@ -197,7 +199,7 @@ static struct resource lcdc_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 106,
+ .start = evt2irq(0xf40),
.flags = IORESOURCE_IRQ,
},
};
@@ -224,7 +226,7 @@ static struct resource ceu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 52,
+ .start = evt2irq(0x880),
.flags = IORESOURCE_IRQ,
},
[2] = {
@@ -255,7 +257,7 @@ static struct resource ceu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 63,
+ .start = evt2irq(0x9e0),
.flags = IORESOURCE_IRQ,
},
[2] = {
@@ -289,7 +291,7 @@ static struct resource fsi_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 108,
+ .start = evt2irq(0xf80),
.flags = IORESOURCE_IRQ,
},
};
@@ -304,17 +306,25 @@ static struct platform_device fsi_device = {
},
};
-static struct fsi_ak4642_info fsi_ak4642_info = {
+static struct asoc_simple_dai_init_info fsi2_ak4642_init_info = {
+ .fmt = SND_SOC_DAIFMT_LEFT_J,
+ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
+ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
+ .sysclk = 11289600,
+};
+
+static struct asoc_simple_card_info fsi_ak4642_info = {
.name = "AK4642",
.card = "FSIA-AK4642",
.cpu_dai = "fsia-dai",
.codec = "ak4642-codec.0-0012",
.platform = "sh_fsi.0",
- .id = FSI_PORT_A,
+ .codec_dai = "ak4642-hifi",
+ .init = &fsi2_ak4642_init_info,
};
static struct platform_device fsi_ak4642_device = {
- .name = "fsi-ak4642-audio",
+ .name = "asoc-simple-card",
.dev = {
.platform_data = &fsi_ak4642_info,
},
@@ -343,7 +353,7 @@ static struct resource keysc_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 79,
+ .start = evt2irq(0xbe0),
.flags = IORESOURCE_IRQ,
},
};
@@ -366,7 +376,7 @@ static struct resource sh_eth_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 91,
+ .start = evt2irq(0xd60),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
},
};
@@ -397,8 +407,8 @@ static struct resource sh7724_usb0_host_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 65,
- .end = 65,
+ .start = evt2irq(0xa20),
+ .end = evt2irq(0xa20),
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
},
};
@@ -426,8 +436,8 @@ static struct resource sh7724_usb1_gadget_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 66,
- .end = 66,
+ .start = evt2irq(0xa40),
+ .end = evt2irq(0xa40),
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
},
};
@@ -452,7 +462,7 @@ static struct resource sdhi0_cn7_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 100,
+ .start = evt2irq(0xe80),
.flags = IORESOURCE_IRQ,
},
};
@@ -481,7 +491,7 @@ static struct resource sdhi1_cn8_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 23,
+ .start = evt2irq(0x4e0),
.flags = IORESOURCE_IRQ,
},
};
@@ -511,7 +521,7 @@ static struct resource irda_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -549,7 +559,7 @@ static struct resource sh_vou_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 55,
+ .start = evt2irq(0x8e0),
.flags = IORESOURCE_IRQ,
},
};
@@ -595,6 +605,7 @@ static struct i2c_board_info i2c0_devices[] = {
#define EEPROM_DATA 0xBA20600C
#define EEPROM_STAT 0xBA206010
#define EEPROM_STRT 0xBA206014
+
static int __init sh_eth_is_eeprom_ready(void)
{
int t = 10000;
@@ -651,7 +662,6 @@ extern char ms7724se_sdram_enter_end;
extern char ms7724se_sdram_leave_start;
extern char ms7724se_sdram_leave_end;
-
static int __init arch_setup(void)
{
/* enable I2C device */
@@ -928,5 +938,4 @@ device_initcall(devices_setup);
static struct sh_machine_vector mv_ms7724se __initmv = {
.mv_name = "ms7724se",
.mv_init_irq = init_se7724_IRQ,
- .mv_nr_irqs = SE7724_FPGA_IRQ_BASE + SE7724_FPGA_IRQ_NR,
};
diff --git a/arch/sh/boards/mach-se/7751/setup.c b/arch/sh/boards/mach-se/7751/setup.c
index 4ed60c5e221f..820f4e7ba0d2 100644
--- a/arch/sh/boards/mach-se/7751/setup.c
+++ b/arch/sh/boards/mach-se/7751/setup.c
@@ -55,6 +55,5 @@ device_initcall(se7751_devices_setup);
*/
static struct sh_machine_vector mv_7751se __initmv = {
.mv_name = "7751 SolutionEngine",
- .mv_nr_irqs = 72,
.mv_init_irq = init_7751se_IRQ,
};
diff --git a/arch/sh/boards/mach-se/7780/setup.c b/arch/sh/boards/mach-se/7780/setup.c
index 6f7c207138e1..ae5a1d84fdf8 100644
--- a/arch/sh/boards/mach-se/7780/setup.c
+++ b/arch/sh/boards/mach-se/7780/setup.c
@@ -110,6 +110,5 @@ static void __init se7780_setup(char **cmdline_p)
static struct sh_machine_vector mv_se7780 __initmv = {
.mv_name = "Solution Engine 7780" ,
.mv_setup = se7780_setup ,
- .mv_nr_irqs = 111 ,
.mv_init_irq = init_se7780_IRQ,
};
diff --git a/arch/sh/boards/mach-se/board-se7619.c b/arch/sh/boards/mach-se/board-se7619.c
index 82b6d4a5dc02..958bcd7aacc5 100644
--- a/arch/sh/boards/mach-se/board-se7619.c
+++ b/arch/sh/boards/mach-se/board-se7619.c
@@ -22,6 +22,5 @@ static int se7619_mode_pins(void)
static struct sh_machine_vector mv_se __initmv = {
.mv_name = "SolutionEngine",
- .mv_nr_irqs = 108,
.mv_mode_pins = se7619_mode_pins,
};
diff --git a/arch/sh/boards/mach-sh03/setup.c b/arch/sh/boards/mach-sh03/setup.c
index d4f79b2a6514..f582dab59343 100644
--- a/arch/sh/boards/mach-sh03/setup.c
+++ b/arch/sh/boards/mach-sh03/setup.c
@@ -101,6 +101,5 @@ device_initcall(sh03_devices_setup);
static struct sh_machine_vector mv_sh03 __initmv = {
.mv_name = "Interface (CTP/PCI-SH03)",
.mv_setup = sh03_setup,
- .mv_nr_irqs = 48,
.mv_init_irq = init_sh03_IRQ,
};
diff --git a/arch/sh/boards/mach-sh7763rdp/setup.c b/arch/sh/boards/mach-sh7763rdp/setup.c
index dd036f1661db..b7c75298dfb5 100644
--- a/arch/sh/boards/mach-sh7763rdp/setup.c
+++ b/arch/sh/boards/mach-sh7763rdp/setup.c
@@ -18,6 +18,7 @@
#include <linux/fb.h>
#include <linux/io.h>
#include <linux/sh_eth.h>
+#include <linux/sh_intc.h>
#include <mach/sh7763rdp.h>
#include <asm/sh7760fb.h>
@@ -67,7 +68,7 @@ static struct platform_device sh7763rdp_nor_flash_device = {
* SH-Ether
*
* SH Ether of SH7763 has multi IRQ handling.
- * (57,58,59 -> 57)
+ * (0x920,0x940,0x960 -> 0x920)
*/
static struct resource sh_eth_resources[] = {
{
@@ -79,7 +80,7 @@ static struct resource sh_eth_resources[] = {
.end = 0xFEE01FFF,
.flags = IORESOURCE_MEM,
}, {
- .start = 57, /* irq number */
+ .start = evt2irq(0x920), /* irq number */
.flags = IORESOURCE_IRQ,
},
};
@@ -213,6 +214,5 @@ static void __init sh7763rdp_setup(char **cmdline_p)
static struct sh_machine_vector mv_sh7763rdp __initmv = {
.mv_name = "sh7763drp",
.mv_setup = sh7763rdp_setup,
- .mv_nr_irqs = 112,
.mv_init_irq = init_sh7763rdp_IRQ,
};
diff --git a/arch/sh/configs/rsk7264_defconfig b/arch/sh/configs/rsk7264_defconfig
new file mode 100644
index 000000000000..1600426224c2
--- /dev/null
+++ b/arch/sh/configs/rsk7264_defconfig
@@ -0,0 +1,80 @@
+CONFIG_LOCALVERSION="uClinux RSK2+SH7264"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_COUNTERS=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
+CONFIG_PROFILING=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_CPU_SUBTYPE_SH7264=y
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_SH_RSK=y
+# CONFIG_SH_TIMER_MTU2 is not set
+CONFIG_BINFMT_FLAT=y
+CONFIG_NET=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+CONFIG_SMSC911X=y
+CONFIG_SMSC_PHY=y
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=8
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_HWMON is not set
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_R8A66597_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_LIBUSUAL=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_VFAT_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_FTRACE is not set
diff --git a/arch/sh/configs/rsk7269_defconfig b/arch/sh/configs/rsk7269_defconfig
new file mode 100644
index 000000000000..9f062b5837d7
--- /dev/null
+++ b/arch/sh/configs/rsk7269_defconfig
@@ -0,0 +1,65 @@
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_CPU_SUBTYPE_SH7269=y
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x02000000
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_SH_RSK=y
+# CONFIG_SH_TIMER_MTU2 is not set
+CONFIG_SH_PCLK_FREQ=66700000
+CONFIG_BINFMT_FLAT=y
+CONFIG_NET=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FW_LOADER is not set
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+CONFIG_SMSC911X=y
+CONFIG_SMSC_PHY=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=8
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_HWMON is not set
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_R8A66597_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_LIBUSUAL=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_VFAT_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_FTRACE is not set
diff --git a/arch/sh/configs/sh7785lcr_32bit_defconfig b/arch/sh/configs/sh7785lcr_32bit_defconfig
index 7b9c696ac5e0..9bdcf72ec06a 100644
--- a/arch/sh/configs/sh7785lcr_32bit_defconfig
+++ b/arch/sh/configs/sh7785lcr_32bit_defconfig
@@ -5,7 +5,7 @@ CONFIG_BSD_PROCESS_ACCT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=16
-CONFIG_PERF_COUNTERS=y
+CONFIG_PERF_EVENTS=y
# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
CONFIG_PROFILING=y
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
index 4d58eb0973d4..cfd5b90a8628 100644
--- a/arch/sh/drivers/dma/Kconfig
+++ b/arch/sh/drivers/dma/Kconfig
@@ -40,23 +40,6 @@ config NR_ONCHIP_DMA_CHANNELS
DMAC supports. This will be 4 for SH7750/SH7751/Sh7750S/SH7091 and 8 for the
SH7750R/SH7751R/SH7760, 12 for the SH7723/SH7780/SH7785/SH7724, default is 6.
-config NR_DMA_CHANNELS_BOOL
- depends on SH_DMA
- bool "Override default number of maximum DMA channels"
- help
- This allows you to forcibly update the maximum number of supported
- DMA channels for a given board. If this is unset, this will default
- to the number of channels that the on-chip DMAC has.
-
-config NR_DMA_CHANNELS
- int "Maximum number of DMA channels"
- depends on SH_DMA && NR_DMA_CHANNELS_BOOL
- default NR_ONCHIP_DMA_CHANNELS
- help
- This allows you to specify the maximum number of DMA channels to
- support. Setting this to a higher value allows for cascading DMACs
- with additional channels.
-
config SH_DMABRG
bool "SH7760 DMABRG support"
depends on CPU_SUBTYPE_SH7760
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
index a60da6dd4d17..4c171f13b0e8 100644
--- a/arch/sh/drivers/dma/dma-sh.c
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -14,35 +14,72 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/io.h>
#include <mach-dreamcast/mach/dma.h>
#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/dma-sh.h>
+#include <asm/dma-register.h>
+#include <cpu/dma-register.h>
+#include <cpu/dma.h>
-#if defined(DMAE1_IRQ)
-#define NR_DMAE 2
-#else
-#define NR_DMAE 1
+/*
+ * Define the default configuration for dual address memory-memory transfer.
+ * The 0x400 value represents auto-request, external->external.
+ */
+#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_INDEX2VAL(XMIT_SZ_32BIT))
+
+static unsigned long dma_find_base(unsigned int chan)
+{
+ unsigned long base = SH_DMAC_BASE0;
+
+#ifdef SH_DMAC_BASE1
+ if (chan >= 6)
+ base = SH_DMAC_BASE1;
#endif
-static const char *dmae_name[] = {
- "DMAC Address Error0", "DMAC Address Error1"
-};
+ return base;
+}
+
+static unsigned long dma_base_addr(unsigned int chan)
+{
+ unsigned long base = dma_find_base(chan);
+
+ /* Normalize offset calculation */
+ if (chan >= 9)
+ chan -= 6;
+ if (chan >= 4)
+ base += 0x10;
+
+ return base + (chan * 0x10);
+}
+#ifdef CONFIG_SH_DMA_IRQ_MULTI
static inline unsigned int get_dmte_irq(unsigned int chan)
{
- unsigned int irq = 0;
- if (chan < ARRAY_SIZE(dmte_irq_map))
- irq = dmte_irq_map[chan];
-
-#if defined(CONFIG_SH_DMA_IRQ_MULTI)
- if (irq > DMTE6_IRQ)
- return DMTE6_IRQ;
- return DMTE0_IRQ;
+ return chan >= 6 ? DMTE6_IRQ : DMTE0_IRQ;
+}
#else
- return irq;
+
+static unsigned int dmte_irq_map[] = {
+ DMTE0_IRQ, DMTE0_IRQ + 1, DMTE0_IRQ + 2, DMTE0_IRQ + 3,
+
+#ifdef DMTE4_IRQ
+ DMTE4_IRQ, DMTE4_IRQ + 1,
+#endif
+
+#ifdef DMTE6_IRQ
+ DMTE6_IRQ, DMTE6_IRQ + 1,
+#endif
+
+#ifdef DMTE8_IRQ
+ DMTE8_IRQ, DMTE9_IRQ, DMTE10_IRQ, DMTE11_IRQ,
#endif
+};
+
+static inline unsigned int get_dmte_irq(unsigned int chan)
+{
+ return dmte_irq_map[chan];
}
+#endif
/*
* We determine the correct shift size based off of the CHCR transmit size
@@ -53,9 +90,10 @@ static inline unsigned int get_dmte_irq(unsigned int chan)
* iterations to complete the transfer.
*/
static unsigned int ts_shift[] = TS_SHIFT;
+
static inline unsigned int calc_xmit_shift(struct dma_channel *chan)
{
- u32 chcr = __raw_readl(dma_base_addr[chan->chan] + CHCR);
+ u32 chcr = __raw_readl(dma_base_addr(chan->chan) + CHCR);
int cnt = ((chcr & CHCR_TS_LOW_MASK) >> CHCR_TS_LOW_SHIFT) |
((chcr & CHCR_TS_HIGH_MASK) >> CHCR_TS_HIGH_SHIFT);
@@ -73,13 +111,13 @@ static irqreturn_t dma_tei(int irq, void *dev_id)
struct dma_channel *chan = dev_id;
u32 chcr;
- chcr = __raw_readl(dma_base_addr[chan->chan] + CHCR);
+ chcr = __raw_readl(dma_base_addr(chan->chan) + CHCR);
if (!(chcr & CHCR_TE))
return IRQ_NONE;
chcr &= ~(CHCR_IE | CHCR_DE);
- __raw_writel(chcr, (dma_base_addr[chan->chan] + CHCR));
+ __raw_writel(chcr, (dma_base_addr(chan->chan) + CHCR));
wake_up(&chan->wait_queue);
@@ -91,13 +129,8 @@ static int sh_dmac_request_dma(struct dma_channel *chan)
if (unlikely(!(chan->flags & DMA_TEI_CAPABLE)))
return 0;
- return request_irq(get_dmte_irq(chan->chan), dma_tei,
-#if defined(CONFIG_SH_DMA_IRQ_MULTI)
- IRQF_SHARED,
-#else
- 0,
-#endif
- chan->dev_id, chan);
+ return request_irq(get_dmte_irq(chan->chan), dma_tei, IRQF_SHARED,
+ chan->dev_id, chan);
}
static void sh_dmac_free_dma(struct dma_channel *chan)
@@ -118,7 +151,7 @@ sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr)
chan->flags &= ~DMA_TEI_CAPABLE;
}
- __raw_writel(chcr, (dma_base_addr[chan->chan] + CHCR));
+ __raw_writel(chcr, (dma_base_addr(chan->chan) + CHCR));
chan->flags |= DMA_CONFIGURED;
return 0;
@@ -129,13 +162,13 @@ static void sh_dmac_enable_dma(struct dma_channel *chan)
int irq;
u32 chcr;
- chcr = __raw_readl(dma_base_addr[chan->chan] + CHCR);
+ chcr = __raw_readl(dma_base_addr(chan->chan) + CHCR);
chcr |= CHCR_DE;
if (chan->flags & DMA_TEI_CAPABLE)
chcr |= CHCR_IE;
- __raw_writel(chcr, (dma_base_addr[chan->chan] + CHCR));
+ __raw_writel(chcr, (dma_base_addr(chan->chan) + CHCR));
if (chan->flags & DMA_TEI_CAPABLE) {
irq = get_dmte_irq(chan->chan);
@@ -153,9 +186,9 @@ static void sh_dmac_disable_dma(struct dma_channel *chan)
disable_irq(irq);
}
- chcr = __raw_readl(dma_base_addr[chan->chan] + CHCR);
+ chcr = __raw_readl(dma_base_addr(chan->chan) + CHCR);
chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE);
- __raw_writel(chcr, (dma_base_addr[chan->chan] + CHCR));
+ __raw_writel(chcr, (dma_base_addr(chan->chan) + CHCR));
}
static int sh_dmac_xfer_dma(struct dma_channel *chan)
@@ -186,13 +219,13 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan)
*/
if (chan->sar || (mach_is_dreamcast() &&
chan->chan == PVR2_CASCADE_CHAN))
- __raw_writel(chan->sar, (dma_base_addr[chan->chan]+SAR));
+ __raw_writel(chan->sar, (dma_base_addr(chan->chan) + SAR));
if (chan->dar || (mach_is_dreamcast() &&
chan->chan == PVR2_CASCADE_CHAN))
- __raw_writel(chan->dar, (dma_base_addr[chan->chan] + DAR));
+ __raw_writel(chan->dar, (dma_base_addr(chan->chan) + DAR));
__raw_writel(chan->count >> calc_xmit_shift(chan),
- (dma_base_addr[chan->chan] + TCR));
+ (dma_base_addr(chan->chan) + TCR));
sh_dmac_enable_dma(chan);
@@ -201,13 +234,32 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan)
static int sh_dmac_get_dma_residue(struct dma_channel *chan)
{
- if (!(__raw_readl(dma_base_addr[chan->chan] + CHCR) & CHCR_DE))
+ if (!(__raw_readl(dma_base_addr(chan->chan) + CHCR) & CHCR_DE))
return 0;
- return __raw_readl(dma_base_addr[chan->chan] + TCR)
+ return __raw_readl(dma_base_addr(chan->chan) + TCR)
<< calc_xmit_shift(chan);
}
+/*
+ * DMAOR handling
+ */
+#if defined(CONFIG_CPU_SUBTYPE_SH7723) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7724) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7785)
+#define NR_DMAOR 2
+#else
+#define NR_DMAOR 1
+#endif
+
+/*
+ * DMAOR bases are broken out amongst channel groups. DMAOR0 manages
+ * channels 0 - 5, DMAOR1 6 - 11 (optional).
+ */
+#define dmaor_read_reg(n) __raw_readw(dma_find_base((n)*6))
+#define dmaor_write_reg(n, data) __raw_writew(data, dma_find_base(n)*6)
+
static inline int dmaor_reset(int no)
{
unsigned long dmaor = dmaor_read_reg(no);
@@ -228,36 +280,86 @@ static inline int dmaor_reset(int no)
return 0;
}
-#if defined(CONFIG_CPU_SH4)
-static irqreturn_t dma_err(int irq, void *dummy)
-{
-#if defined(CONFIG_SH_DMA_IRQ_MULTI)
- int cnt = 0;
- switch (irq) {
-#if defined(DMTE6_IRQ) && defined(DMAE1_IRQ)
- case DMTE6_IRQ:
- cnt++;
+/*
+ * DMAE handling
+ */
+#ifdef CONFIG_CPU_SH4
+
+#if defined(DMAE1_IRQ)
+#define NR_DMAE 2
+#else
+#define NR_DMAE 1
#endif
- case DMTE0_IRQ:
- if (dmaor_read_reg(cnt) & (DMAOR_NMIF | DMAOR_AE)) {
- disable_irq(irq);
- /* DMA multi and error IRQ */
- return IRQ_HANDLED;
- }
- default:
- return IRQ_NONE;
- }
+
+static const char *dmae_name[] = {
+ "DMAC Address Error0",
+ "DMAC Address Error1"
+};
+
+#ifdef CONFIG_SH_DMA_IRQ_MULTI
+static inline unsigned int get_dma_error_irq(int n)
+{
+ return get_dmte_irq(n * 6);
+}
#else
- dmaor_reset(0);
-#if defined(CONFIG_CPU_SUBTYPE_SH7723) || \
- defined(CONFIG_CPU_SUBTYPE_SH7780) || \
- defined(CONFIG_CPU_SUBTYPE_SH7785)
- dmaor_reset(1);
+
+static unsigned int dmae_irq_map[] = {
+ DMAE0_IRQ,
+
+#ifdef DMAE1_IRQ
+ DMAE1_IRQ,
+#endif
+};
+
+static inline unsigned int get_dma_error_irq(int n)
+{
+ return dmae_irq_map[n];
+}
#endif
+
+static irqreturn_t dma_err(int irq, void *dummy)
+{
+ int i;
+
+ for (i = 0; i < NR_DMAOR; i++)
+ dmaor_reset(i);
+
disable_irq(irq);
return IRQ_HANDLED;
-#endif
+}
+
+static int dmae_irq_init(void)
+{
+ int n;
+
+ for (n = 0; n < NR_DMAE; n++) {
+ int i = request_irq(get_dma_error_irq(n), dma_err,
+ IRQF_SHARED, dmae_name[n], NULL);
+ if (unlikely(i < 0)) {
+ printk(KERN_ERR "%s request_irq fail\n", dmae_name[n]);
+ return i;
+ }
+ }
+
+ return 0;
+}
+
+static void dmae_irq_free(void)
+{
+ int n;
+
+ for (n = 0; n < NR_DMAE; n++)
+ free_irq(get_dma_error_irq(n), NULL);
+}
+#else
+static inline int dmae_irq_init(void)
+{
+ return 0;
+}
+
+static void dmae_irq_free(void)
+{
}
#endif
@@ -276,72 +378,34 @@ static struct dma_info sh_dmac_info = {
.flags = DMAC_CHANNELS_TEI_CAPABLE,
};
-#ifdef CONFIG_CPU_SH4
-static unsigned int get_dma_error_irq(int n)
-{
-#if defined(CONFIG_SH_DMA_IRQ_MULTI)
- return (n == 0) ? get_dmte_irq(0) : get_dmte_irq(6);
-#else
- return (n == 0) ? DMAE0_IRQ :
-#if defined(DMAE1_IRQ)
- DMAE1_IRQ;
-#else
- -1;
-#endif
-#endif
-}
-#endif
-
static int __init sh_dmac_init(void)
{
struct dma_info *info = &sh_dmac_info;
- int i;
-
-#ifdef CONFIG_CPU_SH4
- int n;
+ int i, rc;
- for (n = 0; n < NR_DMAE; n++) {
- i = request_irq(get_dma_error_irq(n), dma_err,
-#if defined(CONFIG_SH_DMA_IRQ_MULTI)
- IRQF_SHARED,
-#else
- 0,
-#endif
- dmae_name[n], (void *)dmae_name[n]);
- if (unlikely(i < 0)) {
- printk(KERN_ERR "%s request_irq fail\n", dmae_name[n]);
- return i;
- }
- }
-#endif /* CONFIG_CPU_SH4 */
+ /*
+ * Initialize DMAE, for parts that support it.
+ */
+ rc = dmae_irq_init();
+ if (unlikely(rc != 0))
+ return rc;
/*
* Initialize DMAOR, and clean up any error flags that may have
* been set.
*/
- i = dmaor_reset(0);
- if (unlikely(i != 0))
- return i;
-#if defined(CONFIG_CPU_SUBTYPE_SH7723) || \
- defined(CONFIG_CPU_SUBTYPE_SH7780) || \
- defined(CONFIG_CPU_SUBTYPE_SH7785)
- i = dmaor_reset(1);
- if (unlikely(i != 0))
- return i;
-#endif
+ for (i = 0; i < NR_DMAOR; i++) {
+ rc = dmaor_reset(i);
+ if (unlikely(rc != 0))
+ return rc;
+ }
return register_dmac(info);
}
static void __exit sh_dmac_exit(void)
{
-#ifdef CONFIG_CPU_SH4
- int n;
-
- for (n = 0; n < NR_DMAE; n++) {
- free_irq(get_dma_error_irq(n), (void *)dmae_name[n]);
- }
-#endif /* CONFIG_CPU_SH4 */
+ dmae_irq_free();
unregister_dmac(&sh_dmac_info);
}
diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c
index 67ee95603813..4b15feda54b0 100644
--- a/arch/sh/drivers/dma/dma-sysfs.c
+++ b/arch/sh/drivers/dma/dma-sysfs.c
@@ -29,7 +29,7 @@ static ssize_t dma_show_devices(struct device *dev,
ssize_t len = 0;
int i;
- for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+ for (i = 0; i < 16; i++) {
struct dma_info *info = get_dma_info(i);
struct dma_channel *channel = get_dma_channel(i);
diff --git a/arch/sh/drivers/pci/fixups-landisk.c b/arch/sh/drivers/pci/fixups-landisk.c
index ecb1d1060638..db5b40a98e62 100644
--- a/arch/sh/drivers/pci/fixups-landisk.c
+++ b/arch/sh/drivers/pci/fixups-landisk.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pci.h>
+#include <linux/sh_intc.h>
#include "pci-sh4.h"
#define PCIMCR_MRSET_OFF 0xBFFFFFFF
@@ -27,7 +28,7 @@ int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
* slot2: pin1-4 = irq7,8,5,6
* slot3: pin1-4 = irq8,5,6,7
*/
- int irq = ((slot + pin - 1) & 0x3) + 5;
+ int irq = ((slot + pin - 1) & 0x3) + evt2irq(0x2a0);
if ((slot | (pin - 1)) > 0x3) {
printk(KERN_WARNING "PCI: Bad IRQ mapping request for slot %d pin %c\n",
diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c
index f9370dce0b70..57ed3f09d0c2 100644
--- a/arch/sh/drivers/pci/fixups-r7780rp.c
+++ b/arch/sh/drivers/pci/fixups-r7780rp.c
@@ -12,13 +12,10 @@
*/
#include <linux/pci.h>
#include <linux/io.h>
+#include <linux/sh_intc.h>
#include "pci-sh4.h"
-static char irq_tab[] __initdata = {
- 65, 66, 67, 68,
-};
-
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
{
- return irq_tab[slot];
+ return evt2irq(0xa20) + slot;
}
diff --git a/arch/sh/drivers/pci/fixups-sdk7780.c b/arch/sh/drivers/pci/fixups-sdk7780.c
index 0b8472501b88..c0a015ae6ecf 100644
--- a/arch/sh/drivers/pci/fixups-sdk7780.c
+++ b/arch/sh/drivers/pci/fixups-sdk7780.c
@@ -13,18 +13,28 @@
*/
#include <linux/pci.h>
#include <linux/io.h>
+#include <linux/sh_intc.h>
#include "pci-sh4.h"
+#define IRQ_INTA evt2irq(0xa20)
+#define IRQ_INTB evt2irq(0xa40)
+#define IRQ_INTC evt2irq(0xa60)
+#define IRQ_INTD evt2irq(0xa80)
+
/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
static char sdk7780_irq_tab[4][16] __initdata = {
/* INTA */
- { 65, 68, 67, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { IRQ_INTA, IRQ_INTD, IRQ_INTC, IRQ_INTD, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1 },
/* INTB */
- { 66, 65, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { IRQ_INTB, IRQ_INTA, -1, IRQ_INTA, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1 },
/* INTC */
- { 67, 66, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { IRQ_INTC, IRQ_INTB, -1, IRQ_INTB, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1 },
/* INTD */
- { 68, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { IRQ_INTD, IRQ_INTC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1 },
};
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
diff --git a/arch/sh/drivers/pci/fixups-se7751.c b/arch/sh/drivers/pci/fixups-se7751.c
index 2ec146c3fa44..84a88ca92008 100644
--- a/arch/sh/drivers/pci/fixups-se7751.c
+++ b/arch/sh/drivers/pci/fixups-se7751.c
@@ -4,13 +4,14 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/io.h>
+#include <linux/sh_intc.h>
#include "pci-sh4.h"
int __init pcibios_map_platform_irq(const struct pci_dev *, u8 slot, u8 pin)
{
switch (slot) {
- case 0: return 13;
- case 1: return 13; /* AMD Ethernet controller */
+ case 0: return evt2irq(0x3a0);
+ case 1: return evt2irq(0x3a0); /* AMD Ethernet controller */
case 2: return -1;
case 3: return -1;
case 4: return -1;
diff --git a/arch/sh/drivers/pci/fixups-sh03.c b/arch/sh/drivers/pci/fixups-sh03.c
index 1615e5906168..16207bef9f52 100644
--- a/arch/sh/drivers/pci/fixups-sh03.c
+++ b/arch/sh/drivers/pci/fixups-sh03.c
@@ -2,6 +2,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/pci.h>
+#include <linux/sh_intc.h>
int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
@@ -9,21 +10,21 @@ int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
if (dev->bus->number == 0) {
switch (slot) {
- case 4: return 5; /* eth0 */
- case 8: return 5; /* eth1 */
- case 6: return 2; /* PCI bridge */
+ case 4: return evt2irq(0x2a0); /* eth0 */
+ case 8: return evt2irq(0x2a0); /* eth1 */
+ case 6: return evt2irq(0x240); /* PCI bridge */
default:
printk(KERN_ERR "PCI: Bad IRQ mapping request "
"for slot %d\n", slot);
- return 2;
+ return evt2irq(0x240);
}
} else {
switch (pin) {
- case 0: irq = 2; break;
- case 1: irq = 2; break;
- case 2: irq = 2; break;
- case 3: irq = 2; break;
- case 4: irq = 2; break;
+ case 0: irq = evt2irq(0x240); break;
+ case 1: irq = evt2irq(0x240); break;
+ case 2: irq = evt2irq(0x240); break;
+ case 3: irq = evt2irq(0x240); break;
+ case 4: irq = evt2irq(0x240); break;
default: irq = -1; break;
}
}
diff --git a/arch/sh/drivers/pci/fixups-snapgear.c b/arch/sh/drivers/pci/fixups-snapgear.c
index 4a093c648d12..6e33ba4cd076 100644
--- a/arch/sh/drivers/pci/fixups-snapgear.c
+++ b/arch/sh/drivers/pci/fixups-snapgear.c
@@ -16,6 +16,7 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/sh_intc.h>
#include "pci-sh4.h"
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
@@ -24,11 +25,11 @@ int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
switch (slot) {
case 8: /* the PCI bridge */ break;
- case 11: irq = 8; break; /* USB */
- case 12: irq = 11; break; /* PCMCIA */
- case 13: irq = 5; break; /* eth0 */
- case 14: irq = 8; break; /* eth1 */
- case 15: irq = 11; break; /* safenet (unused) */
+ case 11: irq = evt2irq(0x300); break; /* USB */
+ case 12: irq = evt2irq(0x360); break; /* PCMCIA */
+ case 13: irq = evt2irq(0x2a0); break; /* eth0 */
+ case 14: irq = evt2irq(0x300); break; /* eth1 */
+ case 15: irq = evt2irq(0x360); break; /* safenet (unused) */
}
printk("PCI: Mapping SnapGear IRQ for slot %d, pin %c to irq %d\n",
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c
index 4df27c4fbf99..c045142f7338 100644
--- a/arch/sh/drivers/pci/pcie-sh7786.c
+++ b/arch/sh/drivers/pci/pcie-sh7786.c
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/sh_clk.h>
+#include <linux/sh_intc.h>
#include "pcie-sh7786.h"
#include <asm/sizes.h>
@@ -468,7 +469,7 @@ static int __init pcie_init(struct sh7786_pcie_port *port)
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
{
- return 71;
+ return evt2irq(0xae0);
}
static int __init sh7786_pcie_core_init(void)
diff --git a/arch/sh/include/asm/dma-sh.h b/arch/sh/include/asm/dma-sh.h
deleted file mode 100644
index f3acb8e34c6b..000000000000
--- a/arch/sh/include/asm/dma-sh.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * arch/sh/include/asm/dma-sh.h
- *
- * Copyright (C) 2000 Takashi YOSHII
- * Copyright (C) 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef __DMA_SH_H
-#define __DMA_SH_H
-
-#include <asm/dma-register.h>
-#include <cpu/dma-register.h>
-#include <cpu/dma.h>
-
-/* DMAOR contorl: The DMAOR access size is different by CPU.*/
-#if defined(CONFIG_CPU_SUBTYPE_SH7723) || \
- defined(CONFIG_CPU_SUBTYPE_SH7724) || \
- defined(CONFIG_CPU_SUBTYPE_SH7780) || \
- defined(CONFIG_CPU_SUBTYPE_SH7785)
-#define dmaor_read_reg(n) \
- (n ? __raw_readw(SH_DMAC_BASE1 + DMAOR) \
- : __raw_readw(SH_DMAC_BASE0 + DMAOR))
-#define dmaor_write_reg(n, data) \
- (n ? __raw_writew(data, SH_DMAC_BASE1 + DMAOR) \
- : __raw_writew(data, SH_DMAC_BASE0 + DMAOR))
-#else /* Other CPU */
-#define dmaor_read_reg(n) __raw_readw(SH_DMAC_BASE0 + DMAOR)
-#define dmaor_write_reg(n, data) __raw_writew(data, SH_DMAC_BASE0 + DMAOR)
-#endif
-
-static int dmte_irq_map[] __maybe_unused = {
-#if (MAX_DMA_CHANNELS >= 4)
- DMTE0_IRQ,
- DMTE0_IRQ + 1,
- DMTE0_IRQ + 2,
- DMTE0_IRQ + 3,
-#endif
-#if (MAX_DMA_CHANNELS >= 6)
- DMTE4_IRQ,
- DMTE4_IRQ + 1,
-#endif
-#if (MAX_DMA_CHANNELS >= 8)
- DMTE6_IRQ,
- DMTE6_IRQ + 1,
-#endif
-#if (MAX_DMA_CHANNELS >= 12)
- DMTE8_IRQ,
- DMTE9_IRQ,
- DMTE10_IRQ,
- DMTE11_IRQ,
-#endif
-};
-
-/*
- * Define the default configuration for dual address memory-memory transfer.
- * The 0x400 value represents auto-request, external->external.
- */
-#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_INDEX2VAL(XMIT_SZ_32BIT))
-
-/* DMA base address */
-static u32 dma_base_addr[] __maybe_unused = {
-#if (MAX_DMA_CHANNELS >= 4)
- SH_DMAC_BASE0 + 0x00, /* channel 0 */
- SH_DMAC_BASE0 + 0x10,
- SH_DMAC_BASE0 + 0x20,
- SH_DMAC_BASE0 + 0x30,
-#endif
-#if (MAX_DMA_CHANNELS >= 6)
- SH_DMAC_BASE0 + 0x50,
- SH_DMAC_BASE0 + 0x60,
-#endif
-#if (MAX_DMA_CHANNELS >= 8)
- SH_DMAC_BASE1 + 0x00,
- SH_DMAC_BASE1 + 0x10,
-#endif
-#if (MAX_DMA_CHANNELS >= 12)
- SH_DMAC_BASE1 + 0x20,
- SH_DMAC_BASE1 + 0x30,
- SH_DMAC_BASE1 + 0x50,
- SH_DMAC_BASE1 + 0x60, /* channel 11 */
-#endif
-};
-
-#endif /* __DMA_SH_H */
diff --git a/arch/sh/include/asm/dma.h b/arch/sh/include/asm/dma.h
index 6aa2080c0065..fb6e4f7b00a2 100644
--- a/arch/sh/include/asm/dma.h
+++ b/arch/sh/include/asm/dma.h
@@ -15,17 +15,8 @@
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/device.h>
-#include <cpu/dma.h>
#include <asm-generic/dma.h>
-#ifdef CONFIG_NR_DMA_CHANNELS
-# define MAX_DMA_CHANNELS (CONFIG_NR_DMA_CHANNELS)
-#elif defined(CONFIG_NR_ONCHIP_DMA_CHANNELS)
-# define MAX_DMA_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS)
-#else
-# define MAX_DMA_CHANNELS 0
-#endif
-
/*
* Read and write modes can mean drastically different things depending on the
* channel configuration. Consult your DMAC documentation and module
diff --git a/arch/sh/include/asm/fixmap.h b/arch/sh/include/asm/fixmap.h
index bd7e79a12653..cbe0186b6794 100644
--- a/arch/sh/include/asm/fixmap.h
+++ b/arch/sh/include/asm/fixmap.h
@@ -96,7 +96,7 @@ extern void __clear_fixmap(enum fixed_addresses idx, pgprot_t flags);
#ifdef CONFIG_SUPERH32
#define FIXADDR_TOP (P4SEG - PAGE_SIZE)
#else
-#define FIXADDR_TOP (0xff000000 - PAGE_SIZE)
+#define FIXADDR_TOP ((unsigned long)(-PAGE_SIZE))
#endif
#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
diff --git a/arch/sh/include/asm/i2c-sh7760.h b/arch/sh/include/asm/i2c-sh7760.h
index 24182116711f..69fee1239b03 100644
--- a/arch/sh/include/asm/i2c-sh7760.h
+++ b/arch/sh/include/asm/i2c-sh7760.h
@@ -9,11 +9,9 @@
#define SH7760_I2C0_MMIO 0xFE140000
#define SH7760_I2C0_MMIOEND 0xFE14003B
-#define SH7760_I2C0_IRQ 62
#define SH7760_I2C1_MMIO 0xFE150000
#define SH7760_I2C1_MMIOEND 0xFE15003B
-#define SH7760_I2C1_IRQ 63
struct sh7760_i2c_platdata {
unsigned int speed_khz;
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index ec464a6b95fe..0cf60a628814 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -218,8 +218,13 @@ __BUILD_IOPORT_STRING(w, u16)
__BUILD_IOPORT_STRING(l, u32)
__BUILD_IOPORT_STRING(q, u64)
+#else /* !CONFIG_HAS_IOPORT */
+
+#include <asm/io_noioport.h>
+
#endif
+
#define IO_SPACE_LIMIT 0xffffffff
/* synco on SH-4A, otherwise a nop */
diff --git a/arch/sh/include/asm/io_noioport.h b/arch/sh/include/asm/io_noioport.h
new file mode 100644
index 000000000000..e136d28d1d2e
--- /dev/null
+++ b/arch/sh/include/asm/io_noioport.h
@@ -0,0 +1,41 @@
+#ifndef __ASM_SH_IO_NOIOPORT_H
+#define __ASM_SH_IO_NOIOPORT_H
+
+static inline u8 inb(unsigned long addr)
+{
+ BUG();
+ return -1;
+}
+
+static inline u16 inw(unsigned long addr)
+{
+ BUG();
+ return -1;
+}
+
+static inline u32 inl(unsigned long addr)
+{
+ BUG();
+ return -1;
+}
+
+#define outb(x, y) BUG()
+#define outw(x, y) BUG()
+#define outl(x, y) BUG()
+
+#define inb_p(addr) inb(addr)
+#define inw_p(addr) inw(addr)
+#define inl_p(addr) inl(addr)
+#define outb_p(x, addr) outb((x), (addr))
+#define outw_p(x, addr) outw((x), (addr))
+#define outl_p(x, addr) outl((x), (addr))
+
+#define insb(a, b, c) BUG()
+#define insw(a, b, c) BUG()
+#define insl(a, b, c) BUG()
+
+#define outsb(a, b, c) BUG()
+#define outsw(a, b, c) BUG()
+#define outsl(a, b, c) BUG()
+
+#endif /* __ASM_SH_IO_NOIOPORT_H */
diff --git a/arch/sh/include/asm/irq.h b/arch/sh/include/asm/irq.h
index 2a62017eb275..0e4f532e4737 100644
--- a/arch/sh/include/asm/irq.h
+++ b/arch/sh/include/asm/irq.h
@@ -5,12 +5,15 @@
#include <asm/machvec.h>
/*
- * A sane default based on a reasonable vector table size, platforms are
- * advised to cap this at the hard limit that they're interested in
- * through the machvec.
+ * Only legacy non-sparseirq platforms have to set a reasonably sane
+ * value here. sparseirq platforms allocate their irq_descs on the fly,
+ * so will expand automatically based on the number of registered IRQs.
*/
-#define NR_IRQS 512
-#define NR_IRQS_LEGACY 8 /* Legacy external IRQ0-7 */
+#ifdef CONFIG_SPARSE_IRQ
+# define NR_IRQS 8
+#else
+# define NR_IRQS 512
+#endif
/*
* This is a special IRQ number for indicating that no IRQ has been
diff --git a/arch/sh/include/asm/kdebug.h b/arch/sh/include/asm/kdebug.h
index 5f6d2e9ccb7c..a6201f10c273 100644
--- a/arch/sh/include/asm/kdebug.h
+++ b/arch/sh/include/asm/kdebug.h
@@ -10,4 +10,6 @@ enum die_val {
DIE_SSTEP,
};
+extern void printk_address(unsigned long address, int reliable);
+
#endif /* __ASM_SH_KDEBUG_H */
diff --git a/arch/sh/include/asm/kgdb.h b/arch/sh/include/asm/kgdb.h
index f3613952d1ae..9e7d2d1b03e0 100644
--- a/arch/sh/include/asm/kgdb.h
+++ b/arch/sh/include/asm/kgdb.h
@@ -4,18 +4,6 @@
#include <asm/cacheflush.h>
#include <asm/ptrace.h>
-/* Same as pt_regs but has vbr in place of syscall_nr */
-struct kgdb_regs {
- unsigned long regs[16];
- unsigned long pc;
- unsigned long pr;
- unsigned long sr;
- unsigned long gbr;
- unsigned long mach;
- unsigned long macl;
- unsigned long vbr;
-};
-
enum regnames {
GDB_R0, GDB_R1, GDB_R2, GDB_R3, GDB_R4, GDB_R5, GDB_R6, GDB_R7,
GDB_R8, GDB_R9, GDB_R10, GDB_R11, GDB_R12, GDB_R13, GDB_R14, GDB_R15,
@@ -23,17 +11,27 @@ enum regnames {
GDB_PC, GDB_PR, GDB_SR, GDB_GBR, GDB_MACH, GDB_MACL, GDB_VBR,
};
-#define NUMREGBYTES ((GDB_VBR + 1) * 4)
+#define _GP_REGS 16
+#define _EXTRA_REGS 7
+#define GDB_SIZEOF_REG sizeof(u32)
+
+#define DBG_MAX_REG_NUM (_GP_REGS + _EXTRA_REGS)
+#define NUMREGBYTES (DBG_MAX_REG_NUM * sizeof(GDB_SIZEOF_REG))
static inline void arch_kgdb_breakpoint(void)
{
__asm__ __volatile__ ("trapa #0x3c\n");
}
-#define BUFMAX 2048
-
-#define CACHE_FLUSH_IS_SAFE 1
#define BREAK_INSTR_SIZE 2
+#define BUFMAX 2048
+
+#ifdef CONFIG_SMP
+# define CACHE_FLUSH_IS_SAFE 0
+#else
+# define CACHE_FLUSH_IS_SAFE 1
+#endif
+
#define GDB_ADJUSTS_BREAK_OFFSET
#endif /* __ASM_SH_KGDB_H */
diff --git a/arch/sh/include/asm/machvec.h b/arch/sh/include/asm/machvec.h
index 57c5c3d0f39f..eb9c20d971dd 100644
--- a/arch/sh/include/asm/machvec.h
+++ b/arch/sh/include/asm/machvec.h
@@ -17,7 +17,6 @@
struct sh_machine_vector {
void (*mv_setup)(char **cmdline_p);
const char *mv_name;
- int mv_nr_irqs;
int (*mv_irq_demux)(int irq);
void (*mv_init_irq)(void);
diff --git a/arch/sh/include/asm/pgtable_64.h b/arch/sh/include/asm/pgtable_64.h
index 42cb9dd52161..dda8c82601b9 100644
--- a/arch/sh/include/asm/pgtable_64.h
+++ b/arch/sh/include/asm/pgtable_64.h
@@ -87,9 +87,6 @@ static __inline__ void set_pte(pte_t *pteptr, pte_t pteval)
#define pte_unmap(pte) do { } while (0)
#ifndef __ASSEMBLY__
-#define IOBASE_VADDR 0xff000000
-#define IOBASE_END 0xffffffff
-
/*
* PTEL coherent flags.
* See Chapter 17 ST50 CPU Core Volume 1, Architecture.
diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h
index a229c393826a..3d14aeaef57c 100644
--- a/arch/sh/include/asm/processor.h
+++ b/arch/sh/include/asm/processor.h
@@ -18,7 +18,8 @@ enum cpu_type {
CPU_SH7619,
/* SH-2A types */
- CPU_SH7201, CPU_SH7203, CPU_SH7206, CPU_SH7263, CPU_MXG,
+ CPU_SH7201, CPU_SH7203, CPU_SH7206, CPU_SH7263, CPU_SH7264, CPU_SH7269,
+ CPU_MXG,
/* SH-3 types */
CPU_SH7705, CPU_SH7706, CPU_SH7707,
@@ -32,7 +33,7 @@ enum cpu_type {
/* SH-4A types */
CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SH7786,
- CPU_SH7723, CPU_SH7724, CPU_SH7757, CPU_SHX3,
+ CPU_SH7723, CPU_SH7724, CPU_SH7757, CPU_SH7734, CPU_SHX3,
/* SH4AL-DSP types */
CPU_SH7343, CPU_SH7722, CPU_SH7366, CPU_SH7372,
@@ -85,10 +86,6 @@ struct sh_cpuinfo {
struct tlb_info itlb;
struct tlb_info dtlb;
-#ifdef CONFIG_SMP
- struct task_struct *idle;
-#endif
-
unsigned int phys_bits;
unsigned long flags;
} __attribute__ ((aligned(L1_CACHE_BYTES)));
@@ -102,7 +99,6 @@ extern struct sh_cpuinfo cpu_data[];
#define cpu_relax() barrier()
void default_idle(void);
-void cpu_idle_wait(void);
void stop_this_cpu(void *);
/* Forward decl */
diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h
index 900f8d72ffe2..b6311fd2d066 100644
--- a/arch/sh/include/asm/processor_32.h
+++ b/arch/sh/include/asm/processor_32.h
@@ -126,9 +126,6 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned lo
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
-/* Prepare to copy thread state - unlazy all lazy status */
-void prepare_to_copy(struct task_struct *tsk);
-
/*
* create a kernel thread without removing it from tasklists
*/
diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h
index e25c4c7d6b63..cd6029fb2c01 100644
--- a/arch/sh/include/asm/processor_64.h
+++ b/arch/sh/include/asm/processor_64.h
@@ -121,7 +121,6 @@ struct thread_struct {
NULL for a kernel thread. */
struct pt_regs *uregs;
- unsigned long trap_no, error_code;
unsigned long address;
/* Hardware debugging registers may come here */
@@ -138,8 +137,6 @@ struct thread_struct {
.pc = 0, \
.kregs = &fake_swapper_regs, \
.uregs = NULL, \
- .trap_no = 0, \
- .error_code = 0, \
.address = 0, \
.flags = 0, \
}
@@ -172,7 +169,6 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
#define copy_segments(p, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
#define forget_segments() do { } while (0)
-#define prepare_to_copy(tsk) do { } while (0)
/*
* FPU lazy state save handling.
*/
diff --git a/arch/sh/include/asm/stackprotector.h b/arch/sh/include/asm/stackprotector.h
new file mode 100644
index 000000000000..d9df3a76847c
--- /dev/null
+++ b/arch/sh/include/asm/stackprotector.h
@@ -0,0 +1,27 @@
+#ifndef __ASM_SH_STACKPROTECTOR_H
+#define __ASM_SH_STACKPROTECTOR_H
+
+#include <linux/random.h>
+#include <linux/version.h>
+
+extern unsigned long __stack_chk_guard;
+
+/*
+ * Initialize the stackprotector canary value.
+ *
+ * NOTE: this must only be called from functions that never return,
+ * and it must always be inlined.
+ */
+static __always_inline void boot_init_stack_canary(void)
+{
+ unsigned long canary;
+
+ /* Try to get a semi random initial value. */
+ get_random_bytes(&canary, sizeof(canary));
+ canary ^= LINUX_VERSION_CODE;
+
+ current->stack_canary = canary;
+ __stack_chk_guard = current->stack_canary;
+}
+
+#endif /* __ASM_SH_STACKPROTECTOR_H */
diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h
index 20ee40af16e9..0c04ffc4f12c 100644
--- a/arch/sh/include/asm/thread_info.h
+++ b/arch/sh/include/asm/thread_info.h
@@ -10,8 +10,18 @@
* - Incorporating suggestions made by Linus Torvalds and Dave Miller
*/
#ifdef __KERNEL__
+
#include <asm/page.h>
+/*
+ * Page fault error code bits
+ */
+#define FAULT_CODE_WRITE (1 << 0) /* write access */
+#define FAULT_CODE_INITIAL (1 << 1) /* initial page write */
+#define FAULT_CODE_ITLB (1 << 2) /* ITLB miss */
+#define FAULT_CODE_PROT (1 << 3) /* protection fault */
+#define FAULT_CODE_USER (1 << 4) /* user-mode access */
+
#ifndef __ASSEMBLY__
#include <asm/processor.h>
@@ -88,29 +98,23 @@ static inline struct thread_info *current_thread_info(void)
return ti;
}
-/* thread information allocation */
-#if THREAD_SHIFT >= PAGE_SHIFT
-
#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
-#endif
-
-extern struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node);
-extern void free_thread_info(struct thread_info *ti);
extern void arch_task_cache_init(void);
-#define arch_task_cache_init arch_task_cache_init
extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
+extern void arch_release_task_struct(struct task_struct *tsk);
extern void init_thread_xstate(void);
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-
#endif /* __ASSEMBLY__ */
/*
- * thread information flags
- * - these are process state flags that various assembly files may need to access
- * - pending work-to-be-done flags are in LSW
- * - other flags in MSW
+ * Thread information flags
+ *
+ * - Limited to 24 bits, upper byte used for fault code encoding.
+ *
+ * - _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within 2 bytes, or
+ * we blow the tst immediate size constraints and need to fix up
+ * arch/sh/kernel/entry-common.S.
*/
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_SIGPENDING 1 /* signal pending */
@@ -133,12 +137,6 @@ extern void init_thread_xstate(void);
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
-/*
- * _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within 2 bytes, or we
- * blow the tst immediate size constraints and need to fix up
- * arch/sh/kernel/entry-common.S.
- */
-
/* work to do in syscall trace */
#define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
_TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
@@ -165,6 +163,7 @@ extern void init_thread_xstate(void);
#define TS_USEDFPU 0x0002 /* FPU used by this task this quantum */
#ifndef __ASSEMBLY__
+
#define HAVE_SET_RESTORE_SIGMASK 1
static inline void set_restore_sigmask(void)
{
@@ -172,6 +171,24 @@ static inline void set_restore_sigmask(void)
ti->status |= TS_RESTORE_SIGMASK;
set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags);
}
+
+#define TI_FLAG_FAULT_CODE_SHIFT 24
+
+/*
+ * Additional thread flag encoding
+ */
+static inline void set_thread_fault_code(unsigned int val)
+{
+ struct thread_info *ti = current_thread_info();
+ ti->flags = (ti->flags & (~0 >> (32 - TI_FLAG_FAULT_CODE_SHIFT)))
+ | (val << TI_FLAG_FAULT_CODE_SHIFT);
+}
+
+static inline unsigned int get_thread_fault_code(void)
+{
+ struct thread_info *ti = current_thread_info();
+ return ti->flags >> TI_FLAG_FAULT_CODE_SHIFT;
+}
#endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/arch/sh/include/asm/topology.h b/arch/sh/include/asm/topology.h
index 88e734069fa6..b0a282d65f6a 100644
--- a/arch/sh/include/asm/topology.h
+++ b/arch/sh/include/asm/topology.h
@@ -3,31 +3,6 @@
#ifdef CONFIG_NUMA
-/* sched_domains SD_NODE_INIT for sh machines */
-#define SD_NODE_INIT (struct sched_domain) { \
- .parent = NULL, \
- .child = NULL, \
- .groups = NULL, \
- .min_interval = 8, \
- .max_interval = 32, \
- .busy_factor = 32, \
- .imbalance_pct = 125, \
- .cache_nice_tries = 2, \
- .busy_idx = 3, \
- .idle_idx = 2, \
- .newidle_idx = 0, \
- .wake_idx = 0, \
- .forkexec_idx = 0, \
- .flags = SD_LOAD_BALANCE \
- | SD_BALANCE_FORK \
- | SD_BALANCE_EXEC \
- | SD_BALANCE_NEWIDLE \
- | SD_SERIALIZE, \
- .last_balance = jiffies, \
- .balance_interval = 1, \
- .nr_balance_failed = 0, \
-}
-
#define cpu_to_node(cpu) ((void)(cpu),0)
#define parent_node(node) ((void)(node),0)
diff --git a/arch/sh/include/asm/traps_64.h b/arch/sh/include/asm/traps_64.h
index c52d7f9a06c1..ef5eff919449 100644
--- a/arch/sh/include/asm/traps_64.h
+++ b/arch/sh/include/asm/traps_64.h
@@ -10,8 +10,22 @@
#ifndef __ASM_SH_TRAPS_64_H
#define __ASM_SH_TRAPS_64_H
+#include <cpu/registers.h>
+
extern void phys_stext(void);
+#define lookup_exception_vector() \
+({ \
+ unsigned long _vec; \
+ \
+ __asm__ __volatile__ ( \
+ "getcon " __EXPEVT ", %0\n\t" \
+ : "=r" (_vec) \
+ ); \
+ \
+ _vec; \
+})
+
static inline void trigger_address_error(void)
{
phys_stext();
diff --git a/arch/sh/include/cpu-sh2/cpu/dma.h b/arch/sh/include/cpu-sh2/cpu/dma.h
deleted file mode 100644
index d66b43cdc637..000000000000
--- a/arch/sh/include/cpu-sh2/cpu/dma.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Definitions for the SH-2 DMAC.
- *
- * Copyright (C) 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef __ASM_CPU_SH2_DMA_H
-#define __ASM_CPU_SH2_DMA_H
-
-#define SH_MAX_DMA_CHANNELS 2
-
-#define SAR ((unsigned long[]){ 0xffffff80, 0xffffff90 })
-#define DAR ((unsigned long[]){ 0xffffff84, 0xffffff94 })
-#define DMATCR ((unsigned long[]){ 0xffffff88, 0xffffff98 })
-#define CHCR ((unsigned long[]){ 0xfffffffc, 0xffffff9c })
-
-#define DMAOR 0xffffffb0
-
-#endif /* __ASM_CPU_SH2_DMA_H */
-
diff --git a/arch/sh/include/cpu-sh2a/cpu/dma.h b/arch/sh/include/cpu-sh2a/cpu/dma.h
deleted file mode 100644
index 27a13ef4fdfc..000000000000
--- a/arch/sh/include/cpu-sh2a/cpu/dma.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <cpu-sh2/cpu/dma.h>
diff --git a/arch/sh/include/cpu-sh2a/cpu/sh7264.h b/arch/sh/include/cpu-sh2a/cpu/sh7264.h
new file mode 100644
index 000000000000..4d1ef6d74bd6
--- /dev/null
+++ b/arch/sh/include/cpu-sh2a/cpu/sh7264.h
@@ -0,0 +1,176 @@
+#ifndef __ASM_SH7264_H__
+#define __ASM_SH7264_H__
+
+enum {
+ /* Port A */
+ GPIO_PA3, GPIO_PA2, GPIO_PA1, GPIO_PA0,
+
+ /* Port B */
+ GPIO_PB22, GPIO_PB21, GPIO_PB20,
+ GPIO_PB19, GPIO_PB18, GPIO_PB17, GPIO_PB16,
+ GPIO_PB15, GPIO_PB14, GPIO_PB13, GPIO_PB12,
+ GPIO_PB11, GPIO_PB10, GPIO_PB9, GPIO_PB8,
+ GPIO_PB7, GPIO_PB6, GPIO_PB5, GPIO_PB4,
+ GPIO_PB3, GPIO_PB2, GPIO_PB1,
+
+ /* Port C */
+ GPIO_PC10, GPIO_PC9, GPIO_PC8,
+ GPIO_PC7, GPIO_PC6, GPIO_PC5, GPIO_PC4,
+ GPIO_PC3, GPIO_PC2, GPIO_PC1, GPIO_PC0,
+
+ /* Port D */
+ GPIO_PD15, GPIO_PD14, GPIO_PD13, GPIO_PD12,
+ GPIO_PD11, GPIO_PD10, GPIO_PD9, GPIO_PD8,
+ GPIO_PD7, GPIO_PD6, GPIO_PD5, GPIO_PD4,
+ GPIO_PD3, GPIO_PD2, GPIO_PD1, GPIO_PD0,
+
+ /* Port E */
+ GPIO_PE5, GPIO_PE4,
+ GPIO_PE3, GPIO_PE2, GPIO_PE1, GPIO_PE0,
+
+ /* Port F */
+ GPIO_PF12,
+ GPIO_PF11, GPIO_PF10, GPIO_PF9, GPIO_PF8,
+ GPIO_PF7, GPIO_PF6, GPIO_PF5, GPIO_PF4,
+ GPIO_PF3, GPIO_PF2, GPIO_PF1, GPIO_PF0,
+
+ /* Port G */
+ GPIO_PG24,
+ GPIO_PG23, GPIO_PG22, GPIO_PG21, GPIO_PG20,
+ GPIO_PG19, GPIO_PG18, GPIO_PG17, GPIO_PG16,
+ GPIO_PG15, GPIO_PG14, GPIO_PG13, GPIO_PG12,
+ GPIO_PG11, GPIO_PG10, GPIO_PG9, GPIO_PG8,
+ GPIO_PG7, GPIO_PG6, GPIO_PG5, GPIO_PG4,
+ GPIO_PG3, GPIO_PG2, GPIO_PG1, GPIO_PG0,
+
+ /* Port H */
+ GPIO_PH7, GPIO_PH6, GPIO_PH5, GPIO_PH4,
+ GPIO_PH3, GPIO_PH2, GPIO_PH1, GPIO_PH0,
+
+ /* Port I - not on device */
+
+ /* Port J */
+ GPIO_PJ11, GPIO_PJ10, GPIO_PJ9, GPIO_PJ8,
+ GPIO_PJ7, GPIO_PJ6, GPIO_PJ5, GPIO_PJ4,
+ GPIO_PJ3, GPIO_PJ2, GPIO_PJ1, GPIO_PJ0,
+
+ /* Port K */
+ GPIO_PK11, GPIO_PK10, GPIO_PK9, GPIO_PK8,
+ GPIO_PK7, GPIO_PK6, GPIO_PK5, GPIO_PK4,
+ GPIO_PK3, GPIO_PK2, GPIO_PK1, GPIO_PK0,
+
+ /* INTC: IRQ and PINT on PB/PD/PE */
+ GPIO_FN_PINT7_PG, GPIO_FN_PINT6_PG, GPIO_FN_PINT5_PG, GPIO_FN_PINT4_PG,
+ GPIO_FN_PINT3_PG, GPIO_FN_PINT2_PG, GPIO_FN_PINT1_PG,
+
+ GPIO_FN_IRQ7_PC, GPIO_FN_IRQ6_PC, GPIO_FN_IRQ5_PC, GPIO_FN_IRQ4_PC,
+ GPIO_FN_IRQ3_PG, GPIO_FN_IRQ2_PG, GPIO_FN_IRQ1_PJ, GPIO_FN_IRQ0_PJ,
+ GPIO_FN_IRQ3_PE, GPIO_FN_IRQ2_PE, GPIO_FN_IRQ1_PE, GPIO_FN_IRQ0_PE,
+
+ /* WDT */
+ GPIO_FN_WDTOVF,
+
+ /* CAN */
+ GPIO_FN_CTX1, GPIO_FN_CRX1, GPIO_FN_CTX0, GPIO_FN_CTX0_CTX1,
+ GPIO_FN_CRX0, GPIO_FN_CRX0_CRX1,
+
+ /* DMAC */
+ GPIO_FN_TEND0, GPIO_FN_DACK0, GPIO_FN_DREQ0,
+ GPIO_FN_TEND1, GPIO_FN_DACK1, GPIO_FN_DREQ1,
+
+ /* ADC */
+ GPIO_FN_ADTRG,
+
+ /* BSC */
+
+ GPIO_FN_A25, GPIO_FN_A24,
+ GPIO_FN_A23, GPIO_FN_A22, GPIO_FN_A21, GPIO_FN_A20,
+ GPIO_FN_A19, GPIO_FN_A18, GPIO_FN_A17, GPIO_FN_A16,
+ GPIO_FN_A15, GPIO_FN_A14, GPIO_FN_A13, GPIO_FN_A12,
+ GPIO_FN_A11, GPIO_FN_A10, GPIO_FN_A9, GPIO_FN_A8,
+ GPIO_FN_A7, GPIO_FN_A6, GPIO_FN_A5, GPIO_FN_A4,
+ GPIO_FN_A3, GPIO_FN_A2, GPIO_FN_A1, GPIO_FN_A0,
+ GPIO_FN_D15, GPIO_FN_D14, GPIO_FN_D13, GPIO_FN_D12,
+ GPIO_FN_D11, GPIO_FN_D10, GPIO_FN_D9, GPIO_FN_D8,
+ GPIO_FN_D7, GPIO_FN_D6, GPIO_FN_D5, GPIO_FN_D4,
+ GPIO_FN_D3, GPIO_FN_D2, GPIO_FN_D1, GPIO_FN_D0,
+
+ GPIO_FN_BS,
+ GPIO_FN_CS4, GPIO_FN_CS3, GPIO_FN_CS2, GPIO_FN_CS1, GPIO_FN_CS0,
+ GPIO_FN_CS6CE1B, GPIO_FN_CS5CE1A,
+ GPIO_FN_CE2A, GPIO_FN_CE2B,
+ GPIO_FN_RD, GPIO_FN_RDWR,
+ GPIO_FN_ICIOWRAH, GPIO_FN_ICIORD,
+ GPIO_FN_WE1DQMUWE, GPIO_FN_WE0DQML,
+ GPIO_FN_RAS, GPIO_FN_CAS, GPIO_FN_CKE,
+ GPIO_FN_WAIT, GPIO_FN_BREQ, GPIO_FN_BACK,
+ GPIO_FN_IOIS16,
+
+ /* TMU */
+ GPIO_FN_TIOC4D, GPIO_FN_TIOC4C, GPIO_FN_TIOC4B, GPIO_FN_TIOC4A,
+ GPIO_FN_TIOC3D, GPIO_FN_TIOC3C, GPIO_FN_TIOC3B, GPIO_FN_TIOC3A,
+ GPIO_FN_TIOC2B, GPIO_FN_TIOC1B, GPIO_FN_TIOC2A, GPIO_FN_TIOC1A,
+ GPIO_FN_TIOC0D, GPIO_FN_TIOC0C, GPIO_FN_TIOC0B, GPIO_FN_TIOC0A,
+ GPIO_FN_TCLKD, GPIO_FN_TCLKC, GPIO_FN_TCLKB, GPIO_FN_TCLKA,
+
+ /* SSU */
+ GPIO_FN_SCS0_PD, GPIO_FN_SSO0_PD, GPIO_FN_SSI0_PD, GPIO_FN_SSCK0_PD,
+ GPIO_FN_SCS0_PF, GPIO_FN_SSO0_PF, GPIO_FN_SSI0_PF, GPIO_FN_SSCK0_PF,
+ GPIO_FN_SCS1_PD, GPIO_FN_SSO1_PD, GPIO_FN_SSI1_PD, GPIO_FN_SSCK1_PD,
+ GPIO_FN_SCS1_PF, GPIO_FN_SSO1_PF, GPIO_FN_SSI1_PF, GPIO_FN_SSCK1_PF,
+
+ /* SCIF */
+ GPIO_FN_SCK0, GPIO_FN_SCK1, GPIO_FN_SCK2, GPIO_FN_SCK3,
+ GPIO_FN_RXD0, GPIO_FN_RXD1, GPIO_FN_RXD2, GPIO_FN_RXD3,
+ GPIO_FN_TXD0, GPIO_FN_TXD1, GPIO_FN_TXD2, GPIO_FN_TXD3,
+ GPIO_FN_RXD4, GPIO_FN_RXD5, GPIO_FN_RXD6, GPIO_FN_RXD7,
+ GPIO_FN_TXD4, GPIO_FN_TXD5, GPIO_FN_TXD6, GPIO_FN_TXD7,
+ GPIO_FN_RTS1, GPIO_FN_RTS3, GPIO_FN_CTS1, GPIO_FN_CTS3,
+
+ /* RSPI */
+ GPIO_FN_RSPCK0, GPIO_FN_MOSI0,
+ GPIO_FN_MISO0_PF12, GPIO_FN_MISO1,
+ GPIO_FN_SSL00,
+ GPIO_FN_RSPCK1, GPIO_FN_MOSI1,
+ GPIO_FN_MISO1_PG19, GPIO_FN_SSL10,
+
+ /* IIC3 */
+ GPIO_FN_SCL0, GPIO_FN_SCL1, GPIO_FN_SCL2,
+ GPIO_FN_SDA2, GPIO_FN_SDA1, GPIO_FN_SDA0,
+
+ /* SSI */
+ GPIO_FN_SSISCK0, GPIO_FN_SSIWS0, GPIO_FN_SSITXD0, GPIO_FN_SSIRXD0,
+ GPIO_FN_SSIWS1, GPIO_FN_SSIWS2, GPIO_FN_SSIWS3,
+ GPIO_FN_SSISCK1, GPIO_FN_SSISCK2, GPIO_FN_SSISCK3,
+ GPIO_FN_SSIDATA1, GPIO_FN_SSIDATA2, GPIO_FN_SSIDATA3,
+ GPIO_FN_AUDIO_CLK,
+
+ /* SIOF */
+ GPIO_FN_SIOFTXD, GPIO_FN_SIOFRXD, GPIO_FN_SIOFSYNC, GPIO_FN_SIOFSCK,
+
+ /* SPDIF */
+ GPIO_FN_SPDIF_IN,
+ GPIO_FN_SPDIF_OUT,
+
+ /* NANDFMC */ /* NOTE Controller is not available in boot mode 0 */
+ GPIO_FN_FCE,
+ GPIO_FN_FRB,
+
+ /* VDC3 */
+ GPIO_FN_DV_CLK, GPIO_FN_DV_VSYNC, GPIO_FN_DV_HSYNC,
+ GPIO_FN_DV_DATA7, GPIO_FN_DV_DATA6, GPIO_FN_DV_DATA5, GPIO_FN_DV_DATA4,
+ GPIO_FN_DV_DATA3, GPIO_FN_DV_DATA2, GPIO_FN_DV_DATA1, GPIO_FN_DV_DATA0,
+ GPIO_FN_LCD_CLK, GPIO_FN_LCD_EXTCLK,
+ GPIO_FN_LCD_VSYNC, GPIO_FN_LCD_HSYNC, GPIO_FN_LCD_DE,
+ GPIO_FN_LCD_DATA15, GPIO_FN_LCD_DATA14,
+ GPIO_FN_LCD_DATA13, GPIO_FN_LCD_DATA12,
+ GPIO_FN_LCD_DATA11, GPIO_FN_LCD_DATA10,
+ GPIO_FN_LCD_DATA9, GPIO_FN_LCD_DATA8,
+ GPIO_FN_LCD_DATA7, GPIO_FN_LCD_DATA6,
+ GPIO_FN_LCD_DATA5, GPIO_FN_LCD_DATA4,
+ GPIO_FN_LCD_DATA3, GPIO_FN_LCD_DATA2,
+ GPIO_FN_LCD_DATA1, GPIO_FN_LCD_DATA0,
+ GPIO_FN_LCD_M_DISP,
+};
+
+#endif /* __ASM_SH7264_H__ */
diff --git a/arch/sh/include/cpu-sh2a/cpu/sh7269.h b/arch/sh/include/cpu-sh2a/cpu/sh7269.h
new file mode 100644
index 000000000000..48d14498e774
--- /dev/null
+++ b/arch/sh/include/cpu-sh2a/cpu/sh7269.h
@@ -0,0 +1,201 @@
+#ifndef __ASM_SH7269_H__
+#define __ASM_SH7269_H__
+
+enum {
+ /* Port A */
+ GPIO_PA1, GPIO_PA0,
+
+ /* Port B */
+ GPIO_PB22, GPIO_PB21, GPIO_PB20,
+ GPIO_PB19, GPIO_PB18, GPIO_PB17, GPIO_PB16,
+ GPIO_PB15, GPIO_PB14, GPIO_PB13, GPIO_PB12,
+ GPIO_PB11, GPIO_PB10, GPIO_PB9, GPIO_PB8,
+ GPIO_PB7, GPIO_PB6, GPIO_PB5, GPIO_PB4,
+ GPIO_PB3, GPIO_PB2, GPIO_PB1,
+
+ /* Port C */
+ GPIO_PC8,
+ GPIO_PC7, GPIO_PC6, GPIO_PC5, GPIO_PC4,
+ GPIO_PC3, GPIO_PC2, GPIO_PC1, GPIO_PC0,
+
+ /* Port D */
+ GPIO_PD15, GPIO_PD14, GPIO_PD13, GPIO_PD12,
+ GPIO_PD11, GPIO_PD10, GPIO_PD9, GPIO_PD8,
+ GPIO_PD7, GPIO_PD6, GPIO_PD5, GPIO_PD4,
+ GPIO_PD3, GPIO_PD2, GPIO_PD1, GPIO_PD0,
+
+ /* Port E */
+ GPIO_PE7, GPIO_PE6, GPIO_PE5, GPIO_PE4,
+ GPIO_PE3, GPIO_PE2, GPIO_PE1, GPIO_PE0,
+
+ /* Port F */
+ GPIO_PF23, GPIO_PF22, GPIO_PF21, GPIO_PF20,
+ GPIO_PF19, GPIO_PF18, GPIO_PF17, GPIO_PF16,
+ GPIO_PF15, GPIO_PF14, GPIO_PF13, GPIO_PF12,
+ GPIO_PF11, GPIO_PF10, GPIO_PF9, GPIO_PF8,
+ GPIO_PF7, GPIO_PF6, GPIO_PF5, GPIO_PF4,
+ GPIO_PF3, GPIO_PF2, GPIO_PF1, GPIO_PF0,
+
+ /* Port G */
+ GPIO_PG27, GPIO_PG26, GPIO_PG25, GPIO_PG24,
+ GPIO_PG23, GPIO_PG22, GPIO_PG21, GPIO_PG20,
+ GPIO_PG19, GPIO_PG18, GPIO_PG17, GPIO_PG16,
+ GPIO_PG15, GPIO_PG14, GPIO_PG13, GPIO_PG12,
+ GPIO_PG11, GPIO_PG10, GPIO_PG9, GPIO_PG8,
+ GPIO_PG7, GPIO_PG6, GPIO_PG5, GPIO_PG4,
+ GPIO_PG3, GPIO_PG2, GPIO_PG1, GPIO_PG0,
+
+ /* Port H */
+ GPIO_PH7, GPIO_PH6, GPIO_PH5, GPIO_PH4,
+ GPIO_PH3, GPIO_PH2, GPIO_PH1, GPIO_PH0,
+
+ /* Port I - not on device */
+
+ /* Port J */
+ GPIO_PJ31, GPIO_PJ30, GPIO_PJ29, GPIO_PJ28,
+ GPIO_PJ27, GPIO_PJ26, GPIO_PJ25, GPIO_PJ24,
+ GPIO_PJ23, GPIO_PJ22, GPIO_PJ21, GPIO_PJ20,
+ GPIO_PJ19, GPIO_PJ18, GPIO_PJ17, GPIO_PJ16,
+ GPIO_PJ15, GPIO_PJ14, GPIO_PJ13, GPIO_PJ12,
+ GPIO_PJ11, GPIO_PJ10, GPIO_PJ9, GPIO_PJ8,
+ GPIO_PJ7, GPIO_PJ6, GPIO_PJ5, GPIO_PJ4,
+ GPIO_PJ3, GPIO_PJ2, GPIO_PJ1, GPIO_PJ0,
+
+ /* INTC: IRQ and PINT */
+ GPIO_FN_IRQ7_PG, GPIO_FN_IRQ6_PG, GPIO_FN_IRQ5_PG, GPIO_FN_IRQ4_PG,
+ GPIO_FN_IRQ3_PG, GPIO_FN_IRQ2_PG, GPIO_FN_IRQ1_PG, GPIO_FN_IRQ0_PG,
+ GPIO_FN_IRQ7_PF, GPIO_FN_IRQ6_PF, GPIO_FN_IRQ5_PF, GPIO_FN_IRQ4_PF,
+ GPIO_FN_IRQ3_PJ, GPIO_FN_IRQ2_PJ, GPIO_FN_IRQ1_PJ, GPIO_FN_IRQ0_PJ,
+ GPIO_FN_IRQ1_PC, GPIO_FN_IRQ0_PC,
+
+ GPIO_FN_PINT7_PG, GPIO_FN_PINT6_PG, GPIO_FN_PINT5_PG, GPIO_FN_PINT4_PG,
+ GPIO_FN_PINT3_PG, GPIO_FN_PINT2_PG, GPIO_FN_PINT1_PG, GPIO_FN_PINT0_PG,
+ GPIO_FN_PINT7_PH, GPIO_FN_PINT6_PH, GPIO_FN_PINT5_PH, GPIO_FN_PINT4_PH,
+ GPIO_FN_PINT3_PH, GPIO_FN_PINT2_PH, GPIO_FN_PINT1_PH, GPIO_FN_PINT0_PH,
+ GPIO_FN_PINT7_PJ, GPIO_FN_PINT6_PJ, GPIO_FN_PINT5_PJ, GPIO_FN_PINT4_PJ,
+ GPIO_FN_PINT3_PJ, GPIO_FN_PINT2_PJ, GPIO_FN_PINT1_PJ, GPIO_FN_PINT0_PJ,
+
+ /* WDT */
+ GPIO_FN_WDTOVF,
+
+ /* CAN */
+ GPIO_FN_CTX1, GPIO_FN_CRX1, GPIO_FN_CTX0, GPIO_FN_CTX0_CTX1,
+ GPIO_FN_CRX0, GPIO_FN_CRX0_CRX1, GPIO_FN_CRX0_CRX1_CRX2,
+
+ /* DMAC */
+ GPIO_FN_TEND0, GPIO_FN_DACK0, GPIO_FN_DREQ0,
+ GPIO_FN_TEND1, GPIO_FN_DACK1, GPIO_FN_DREQ1,
+
+ /* ADC */
+ GPIO_FN_ADTRG,
+
+ /* BSC */
+ GPIO_FN_A25, GPIO_FN_A24,
+ GPIO_FN_A23, GPIO_FN_A22, GPIO_FN_A21, GPIO_FN_A20,
+ GPIO_FN_A19, GPIO_FN_A18, GPIO_FN_A17, GPIO_FN_A16,
+ GPIO_FN_A15, GPIO_FN_A14, GPIO_FN_A13, GPIO_FN_A12,
+ GPIO_FN_A11, GPIO_FN_A10, GPIO_FN_A9, GPIO_FN_A8,
+ GPIO_FN_A7, GPIO_FN_A6, GPIO_FN_A5, GPIO_FN_A4,
+ GPIO_FN_A3, GPIO_FN_A2, GPIO_FN_A1, GPIO_FN_A0,
+ GPIO_FN_D15, GPIO_FN_D14, GPIO_FN_D13, GPIO_FN_D12,
+ GPIO_FN_D11, GPIO_FN_D10, GPIO_FN_D9, GPIO_FN_D8,
+ GPIO_FN_D7, GPIO_FN_D6, GPIO_FN_D5, GPIO_FN_D4,
+ GPIO_FN_D3, GPIO_FN_D2, GPIO_FN_D1, GPIO_FN_D0,
+
+ GPIO_FN_BS,
+ GPIO_FN_CS4, GPIO_FN_CS3, GPIO_FN_CS2, GPIO_FN_CS1, GPIO_FN_CS0,
+ GPIO_FN_CS5CE1A,
+ GPIO_FN_CE2A, GPIO_FN_CE2B,
+ GPIO_FN_RD, GPIO_FN_RDWR,
+ GPIO_FN_WE3ICIOWRAHDQMUU, GPIO_FN_WE2ICIORDDQMUL,
+ GPIO_FN_WE1DQMUWE, GPIO_FN_WE0DQML,
+ GPIO_FN_RAS, GPIO_FN_CAS, GPIO_FN_CKE,
+ GPIO_FN_WAIT, GPIO_FN_BREQ, GPIO_FN_BACK,
+ GPIO_FN_IOIS16,
+
+ /* TMU */
+ GPIO_FN_TIOC4D, GPIO_FN_TIOC4C, GPIO_FN_TIOC4B, GPIO_FN_TIOC4A,
+ GPIO_FN_TIOC3D, GPIO_FN_TIOC3C, GPIO_FN_TIOC3B, GPIO_FN_TIOC3A,
+ GPIO_FN_TIOC2B, GPIO_FN_TIOC1B, GPIO_FN_TIOC2A, GPIO_FN_TIOC1A,
+ GPIO_FN_TIOC0D, GPIO_FN_TIOC0C, GPIO_FN_TIOC0B, GPIO_FN_TIOC0A,
+ GPIO_FN_TCLKD, GPIO_FN_TCLKC, GPIO_FN_TCLKB, GPIO_FN_TCLKA,
+
+ /* SSU */
+ GPIO_FN_SCS0_PD, GPIO_FN_SSO0_PD, GPIO_FN_SSI0_PD, GPIO_FN_SSCK0_PD,
+ GPIO_FN_SCS0_PF, GPIO_FN_SSO0_PF, GPIO_FN_SSI0_PF, GPIO_FN_SSCK0_PF,
+ GPIO_FN_SCS1_PD, GPIO_FN_SSO1_PD, GPIO_FN_SSI1_PD, GPIO_FN_SSCK1_PD,
+ GPIO_FN_SCS1_PF, GPIO_FN_SSO1_PF, GPIO_FN_SSI1_PF, GPIO_FN_SSCK1_PF,
+
+ /* SCIF */
+ GPIO_FN_SCK0, GPIO_FN_RXD0, GPIO_FN_TXD0,
+ GPIO_FN_SCK1, GPIO_FN_RXD1, GPIO_FN_TXD1, GPIO_FN_RTS1, GPIO_FN_CTS1,
+ GPIO_FN_SCK2, GPIO_FN_RXD2, GPIO_FN_TXD2,
+ GPIO_FN_SCK3, GPIO_FN_RXD3, GPIO_FN_TXD3,
+ GPIO_FN_SCK4, GPIO_FN_RXD4, GPIO_FN_TXD4,
+ GPIO_FN_SCK5, GPIO_FN_RXD5, GPIO_FN_TXD5, GPIO_FN_RTS5, GPIO_FN_CTS5,
+ GPIO_FN_SCK6, GPIO_FN_RXD6, GPIO_FN_TXD6,
+ GPIO_FN_SCK7, GPIO_FN_RXD7, GPIO_FN_TXD7, GPIO_FN_RTS7, GPIO_FN_CTS7,
+
+ /* RSPI */
+ GPIO_FN_MISO0_PJ19, GPIO_FN_MISO0_PB20,
+ GPIO_FN_MOSI0_PJ18, GPIO_FN_MOSI0_PB19,
+ GPIO_FN_SSL00_PJ17, GPIO_FN_SSL00_PB18,
+ GPIO_FN_RSPCK0_PJ16, GPIO_FN_RSPCK0_PB17,
+ GPIO_FN_RSPCK1, GPIO_FN_MOSI1,
+ GPIO_FN_MISO1, GPIO_FN_SSL10,
+
+ /* IIC3 */
+ GPIO_FN_SCL0, GPIO_FN_SCL1, GPIO_FN_SCL2,
+ GPIO_FN_SDA2, GPIO_FN_SDA1, GPIO_FN_SDA0,
+
+ /* SSI */
+ GPIO_FN_SSISCK0, GPIO_FN_SSIWS0, GPIO_FN_SSITXD0, GPIO_FN_SSIRXD0,
+ GPIO_FN_SSIWS1, GPIO_FN_SSIWS2, GPIO_FN_SSIWS3,
+ GPIO_FN_SSISCK1, GPIO_FN_SSISCK2, GPIO_FN_SSISCK3,
+ GPIO_FN_SSIDATA1, GPIO_FN_SSIDATA2, GPIO_FN_SSIDATA3,
+ GPIO_FN_AUDIO_CLK,
+ GPIO_FN_AUDIO_XOUT,
+
+ /* SIOF */
+ GPIO_FN_SIOFTXD, GPIO_FN_SIOFRXD, GPIO_FN_SIOFSYNC, GPIO_FN_SIOFSCK,
+
+ /* SPDIF */
+ GPIO_FN_SPDIF_IN,
+ GPIO_FN_SPDIF_OUT,
+
+ /* NANDFMC */ /* NOTE Controller is not available in boot mode 0 */
+ GPIO_FN_FCE,
+ GPIO_FN_FRB,
+
+ /* VDC */
+ GPIO_FN_DV_CLK, GPIO_FN_DV_VSYNC, GPIO_FN_DV_HSYNC,
+ GPIO_FN_DV_DATA23, GPIO_FN_DV_DATA22,
+ GPIO_FN_DV_DATA21, GPIO_FN_DV_DATA20,
+ GPIO_FN_DV_DATA19, GPIO_FN_DV_DATA18,
+ GPIO_FN_DV_DATA17, GPIO_FN_DV_DATA16,
+ GPIO_FN_DV_DATA15, GPIO_FN_DV_DATA14,
+ GPIO_FN_DV_DATA13, GPIO_FN_DV_DATA12,
+ GPIO_FN_DV_DATA11, GPIO_FN_DV_DATA10,
+ GPIO_FN_DV_DATA9, GPIO_FN_DV_DATA8,
+ GPIO_FN_DV_DATA7, GPIO_FN_DV_DATA6,
+ GPIO_FN_DV_DATA5, GPIO_FN_DV_DATA4,
+ GPIO_FN_DV_DATA3, GPIO_FN_DV_DATA2,
+ GPIO_FN_DV_DATA1, GPIO_FN_DV_DATA0,
+ GPIO_FN_LCD_CLK, GPIO_FN_LCD_EXTCLK,
+ GPIO_FN_LCD_VSYNC, GPIO_FN_LCD_HSYNC, GPIO_FN_LCD_DE,
+ GPIO_FN_LCD_DATA23, GPIO_FN_LCD_DATA22,
+ GPIO_FN_LCD_DATA21, GPIO_FN_LCD_DATA20,
+ GPIO_FN_LCD_DATA19, GPIO_FN_LCD_DATA18,
+ GPIO_FN_LCD_DATA17, GPIO_FN_LCD_DATA16,
+ GPIO_FN_LCD_DATA15, GPIO_FN_LCD_DATA14,
+ GPIO_FN_LCD_DATA13, GPIO_FN_LCD_DATA12,
+ GPIO_FN_LCD_DATA11, GPIO_FN_LCD_DATA10,
+ GPIO_FN_LCD_DATA9, GPIO_FN_LCD_DATA8,
+ GPIO_FN_LCD_DATA7, GPIO_FN_LCD_DATA6,
+ GPIO_FN_LCD_DATA5, GPIO_FN_LCD_DATA4,
+ GPIO_FN_LCD_DATA3, GPIO_FN_LCD_DATA2,
+ GPIO_FN_LCD_DATA1, GPIO_FN_LCD_DATA0,
+ GPIO_FN_LCD_M_DISP,
+};
+
+#endif /* __ASM_SH7269_H__ */
diff --git a/arch/sh/include/cpu-sh3/cpu/dma.h b/arch/sh/include/cpu-sh3/cpu/dma.h
index 24e28b91c9d5..bccb4144a5e3 100644
--- a/arch/sh/include/cpu-sh3/cpu/dma.h
+++ b/arch/sh/include/cpu-sh3/cpu/dma.h
@@ -1,6 +1,8 @@
#ifndef __ASM_CPU_SH3_DMA_H
#define __ASM_CPU_SH3_DMA_H
+#include <linux/sh_intc.h>
+
#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
defined(CONFIG_CPU_SUBTYPE_SH7721) || \
defined(CONFIG_CPU_SUBTYPE_SH7710) || \
@@ -10,14 +12,7 @@
#define SH_DMAC_BASE0 0xa4000020
#endif
-#define DMTE0_IRQ 48
-#define DMTE4_IRQ 76
-
-/* Definitions for the SuperH DMAC */
-#define TM_BURST 0x00000020
-#define TS_8 0x00000000
-#define TS_16 0x00000008
-#define TS_32 0x00000010
-#define TS_128 0x00000018
+#define DMTE0_IRQ evt2irq(0x800)
+#define DMTE4_IRQ evt2irq(0xb80)
#endif /* __ASM_CPU_SH3_DMA_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
deleted file mode 100644
index 9647e681fd27..000000000000
--- a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
+++ /dev/null
@@ -1,83 +0,0 @@
-#ifndef __ASM_SH_CPU_SH4_DMA_SH7780_H
-#define __ASM_SH_CPU_SH4_DMA_SH7780_H
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7343) || \
- defined(CONFIG_CPU_SUBTYPE_SH7730)
-#define DMTE0_IRQ 48
-#define DMTE4_IRQ 76
-#define DMAE0_IRQ 78 /* DMA Error IRQ*/
-#define SH_DMAC_BASE0 0xFE008020
-#define SH_DMARS_BASE0 0xFE009000
-#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
-#define DMTE0_IRQ 48
-#define DMTE4_IRQ 76
-#define DMAE0_IRQ 78 /* DMA Error IRQ*/
-#define SH_DMAC_BASE0 0xFE008020
-#define SH_DMARS_BASE0 0xFE009000
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
- defined(CONFIG_CPU_SUBTYPE_SH7764)
-#define DMTE0_IRQ 34
-#define DMTE4_IRQ 44
-#define DMAE0_IRQ 38
-#define SH_DMAC_BASE0 0xFF608020
-#define SH_DMARS_BASE0 0xFF609000
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
-#define DMTE0_IRQ 48 /* DMAC0A*/
-#define DMTE4_IRQ 76 /* DMAC0B */
-#define DMTE6_IRQ 40
-#define DMTE8_IRQ 42 /* DMAC1A */
-#define DMTE9_IRQ 43
-#define DMTE10_IRQ 72 /* DMAC1B */
-#define DMTE11_IRQ 73
-#define DMAE0_IRQ 78 /* DMA Error IRQ*/
-#define DMAE1_IRQ 74 /* DMA Error IRQ*/
-#define SH_DMAC_BASE0 0xFE008020
-#define SH_DMAC_BASE1 0xFDC08020
-#define SH_DMARS_BASE0 0xFDC09000
-#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
-#define DMTE0_IRQ 48 /* DMAC0A*/
-#define DMTE4_IRQ 76 /* DMAC0B */
-#define DMTE6_IRQ 40
-#define DMTE8_IRQ 42 /* DMAC1A */
-#define DMTE9_IRQ 43
-#define DMTE10_IRQ 72 /* DMAC1B */
-#define DMTE11_IRQ 73
-#define DMAE0_IRQ 78 /* DMA Error IRQ*/
-#define DMAE1_IRQ 74 /* DMA Error IRQ*/
-#define SH_DMAC_BASE0 0xFE008020
-#define SH_DMAC_BASE1 0xFDC08020
-#define SH_DMARS_BASE0 0xFE009000
-#define SH_DMARS_BASE1 0xFDC09000
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
-#define DMTE0_IRQ 34
-#define DMTE4_IRQ 44
-#define DMTE6_IRQ 46
-#define DMTE8_IRQ 92
-#define DMTE9_IRQ 93
-#define DMTE10_IRQ 94
-#define DMTE11_IRQ 95
-#define DMAE0_IRQ 38 /* DMA Error IRQ */
-#define SH_DMAC_BASE0 0xFC808020
-#define SH_DMAC_BASE1 0xFC818020
-#define SH_DMARS_BASE0 0xFC809000
-#else /* SH7785 */
-#define DMTE0_IRQ 33
-#define DMTE4_IRQ 37
-#define DMTE6_IRQ 52
-#define DMTE8_IRQ 54
-#define DMTE9_IRQ 55
-#define DMTE10_IRQ 56
-#define DMTE11_IRQ 57
-#define DMAE0_IRQ 39 /* DMA Error IRQ0 */
-#define DMAE1_IRQ 58 /* DMA Error IRQ1 */
-#define SH_DMAC_BASE0 0xFC808020
-#define SH_DMAC_BASE1 0xFCC08020
-#define SH_DMARS_BASE0 0xFC809000
-#endif
-
-#define REQ_HE 0x000000C0
-#define REQ_H 0x00000080
-#define REQ_LE 0x00000040
-#define TM_BURST 0x00000020
-
-#endif /* __ASM_SH_CPU_SH4_DMA_SH7780_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/dma.h b/arch/sh/include/cpu-sh4/cpu/dma.h
index ca747e93c2ed..a520eb219621 100644
--- a/arch/sh/include/cpu-sh4/cpu/dma.h
+++ b/arch/sh/include/cpu-sh4/cpu/dma.h
@@ -1,32 +1,17 @@
#ifndef __ASM_CPU_SH4_DMA_H
#define __ASM_CPU_SH4_DMA_H
-/* SH7751/7760/7780 DMA IRQ sources */
+#include <linux/sh_intc.h>
-#ifdef CONFIG_CPU_SH4A
-
-#include <cpu/dma-sh4a.h>
-
-#else /* CONFIG_CPU_SH4A */
/*
* SH7750/SH7751/SH7760
*/
-#define DMTE0_IRQ 34
-#define DMTE4_IRQ 44
-#define DMTE6_IRQ 46
-#define DMAE0_IRQ 38
+#define DMTE0_IRQ evt2irq(0x640)
+#define DMTE4_IRQ evt2irq(0x780)
+#define DMTE6_IRQ evt2irq(0x7c0)
+#define DMAE0_IRQ evt2irq(0x6c0)
#define SH_DMAC_BASE0 0xffa00000
#define SH_DMAC_BASE1 0xffa00070
-/* Definitions for the SuperH DMAC */
-#define TM_BURST 0x00000080
-#define TS_8 0x00000010
-#define TS_16 0x00000020
-#define TS_32 0x00000030
-#define TS_64 0x00000000
-
-#define DMAOR_COD 0x00000008
-
-#endif
#endif /* __ASM_CPU_SH4_DMA_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/freq.h b/arch/sh/include/cpu-sh4/cpu/freq.h
index cffd25ed0240..1631fc238e6f 100644
--- a/arch/sh/include/cpu-sh4/cpu/freq.h
+++ b/arch/sh/include/cpu-sh4/cpu/freq.h
@@ -47,6 +47,11 @@
#define MSTPCR1 0xa4150034
#define MSTPCR2 0xa4150038
+#elif defined(CONFIG_CPU_SUBTYPE_SH7734)
+#define FRQCR0 0xffc80000
+#define FRQCR2 0xffc80008
+#define FRQMR1 0xffc80014
+#define FRQMR2 0xffc80018
#elif defined(CONFIG_CPU_SUBTYPE_SH7785)
#define FRQCR0 0xffc80000
#define FRQCR1 0xffc80004
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7734.h b/arch/sh/include/cpu-sh4/cpu/sh7734.h
new file mode 100644
index 000000000000..2fb9a7b71b41
--- /dev/null
+++ b/arch/sh/include/cpu-sh4/cpu/sh7734.h
@@ -0,0 +1,306 @@
+#ifndef __ASM_SH7734_H__
+#define __ASM_SH7734_H__
+
+/* Pin Function Controller:
+ * GPIO_FN_xx - GPIO used to select pin function
+ * GPIO_GP_x_x - GPIO mapped to real I/O pin on CPU
+ */
+enum {
+ GPIO_GP_0_0, GPIO_GP_0_1, GPIO_GP_0_2, GPIO_GP_0_3,
+ GPIO_GP_0_4, GPIO_GP_0_5, GPIO_GP_0_6, GPIO_GP_0_7,
+ GPIO_GP_0_8, GPIO_GP_0_9, GPIO_GP_0_10, GPIO_GP_0_11,
+ GPIO_GP_0_12, GPIO_GP_0_13, GPIO_GP_0_14, GPIO_GP_0_15,
+ GPIO_GP_0_16, GPIO_GP_0_17, GPIO_GP_0_18, GPIO_GP_0_19,
+ GPIO_GP_0_20, GPIO_GP_0_21, GPIO_GP_0_22, GPIO_GP_0_23,
+ GPIO_GP_0_24, GPIO_GP_0_25, GPIO_GP_0_26, GPIO_GP_0_27,
+ GPIO_GP_0_28, GPIO_GP_0_29, GPIO_GP_0_30, GPIO_GP_0_31,
+
+ GPIO_GP_1_0, GPIO_GP_1_1, GPIO_GP_1_2, GPIO_GP_1_3,
+ GPIO_GP_1_4, GPIO_GP_1_5, GPIO_GP_1_6, GPIO_GP_1_7,
+ GPIO_GP_1_8, GPIO_GP_1_9, GPIO_GP_1_10, GPIO_GP_1_11,
+ GPIO_GP_1_12, GPIO_GP_1_13, GPIO_GP_1_14, GPIO_GP_1_15,
+ GPIO_GP_1_16, GPIO_GP_1_17, GPIO_GP_1_18, GPIO_GP_1_19,
+ GPIO_GP_1_20, GPIO_GP_1_21, GPIO_GP_1_22, GPIO_GP_1_23,
+ GPIO_GP_1_24, GPIO_GP_1_25, GPIO_GP_1_26, GPIO_GP_1_27,
+ GPIO_GP_1_28, GPIO_GP_1_29, GPIO_GP_1_30, GPIO_GP_1_31,
+
+ GPIO_GP_2_0, GPIO_GP_2_1, GPIO_GP_2_2, GPIO_GP_2_3,
+ GPIO_GP_2_4, GPIO_GP_2_5, GPIO_GP_2_6, GPIO_GP_2_7,
+ GPIO_GP_2_8, GPIO_GP_2_9, GPIO_GP_2_10, GPIO_GP_2_11,
+ GPIO_GP_2_12, GPIO_GP_2_13, GPIO_GP_2_14, GPIO_GP_2_15,
+ GPIO_GP_2_16, GPIO_GP_2_17, GPIO_GP_2_18, GPIO_GP_2_19,
+ GPIO_GP_2_20, GPIO_GP_2_21, GPIO_GP_2_22, GPIO_GP_2_23,
+ GPIO_GP_2_24, GPIO_GP_2_25, GPIO_GP_2_26, GPIO_GP_2_27,
+ GPIO_GP_2_28, GPIO_GP_2_29, GPIO_GP_2_30, GPIO_GP_2_31,
+
+ GPIO_GP_3_0, GPIO_GP_3_1, GPIO_GP_3_2, GPIO_GP_3_3,
+ GPIO_GP_3_4, GPIO_GP_3_5, GPIO_GP_3_6, GPIO_GP_3_7,
+ GPIO_GP_3_8, GPIO_GP_3_9, GPIO_GP_3_10, GPIO_GP_3_11,
+ GPIO_GP_3_12, GPIO_GP_3_13, GPIO_GP_3_14, GPIO_GP_3_15,
+ GPIO_GP_3_16, GPIO_GP_3_17, GPIO_GP_3_18, GPIO_GP_3_19,
+ GPIO_GP_3_20, GPIO_GP_3_21, GPIO_GP_3_22, GPIO_GP_3_23,
+ GPIO_GP_3_24, GPIO_GP_3_25, GPIO_GP_3_26, GPIO_GP_3_27,
+ GPIO_GP_3_28, GPIO_GP_3_29, GPIO_GP_3_30, GPIO_GP_3_31,
+
+ GPIO_GP_4_0, GPIO_GP_4_1, GPIO_GP_4_2, GPIO_GP_4_3,
+ GPIO_GP_4_4, GPIO_GP_4_5, GPIO_GP_4_6, GPIO_GP_4_7,
+ GPIO_GP_4_8, GPIO_GP_4_9, GPIO_GP_4_10, GPIO_GP_4_11,
+ GPIO_GP_4_12, GPIO_GP_4_13, GPIO_GP_4_14, GPIO_GP_4_15,
+ GPIO_GP_4_16, GPIO_GP_4_17, GPIO_GP_4_18, GPIO_GP_4_19,
+ GPIO_GP_4_20, GPIO_GP_4_21, GPIO_GP_4_22, GPIO_GP_4_23,
+ GPIO_GP_4_24, GPIO_GP_4_25, GPIO_GP_4_26, GPIO_GP_4_27,
+ GPIO_GP_4_28, GPIO_GP_4_29, GPIO_GP_4_30, GPIO_GP_4_31,
+
+ GPIO_GP_5_0, GPIO_GP_5_1, GPIO_GP_5_2, GPIO_GP_5_3,
+ GPIO_GP_5_4, GPIO_GP_5_5, GPIO_GP_5_6, GPIO_GP_5_7,
+ GPIO_GP_5_8, GPIO_GP_5_9, GPIO_GP_5_10, GPIO_GP_5_11,
+
+ GPIO_FN_CLKOUT, GPIO_FN_BS, GPIO_FN_CS0, GPIO_FN_EX_CS0, GPIO_FN_RD,
+ GPIO_FN_WE0, GPIO_FN_WE1,
+
+ GPIO_FN_SCL0, GPIO_FN_PENC0, GPIO_FN_USB_OVC0,
+
+ GPIO_FN_IRQ2_B, GPIO_FN_IRQ3_B,
+
+ /* IPSR0 */
+ GPIO_FN_A15, GPIO_FN_ST0_VCO_CLKIN, GPIO_FN_LCD_DATA15_A,
+ GPIO_FN_TIOC3D_C,
+ GPIO_FN_A14, GPIO_FN_LCD_DATA14_A, GPIO_FN_TIOC3C_C,
+ GPIO_FN_A13, GPIO_FN_LCD_DATA13_A, GPIO_FN_TIOC3B_C,
+ GPIO_FN_A12, GPIO_FN_LCD_DATA12_A, GPIO_FN_TIOC3A_C,
+ GPIO_FN_A11, GPIO_FN_ST0_D7, GPIO_FN_LCD_DATA11_A,
+ GPIO_FN_TIOC2B_C,
+ GPIO_FN_A10, GPIO_FN_ST0_D6, GPIO_FN_LCD_DATA10_A,
+ GPIO_FN_TIOC2A_C,
+ GPIO_FN_A9, GPIO_FN_ST0_D5, GPIO_FN_LCD_DATA9_A,
+ GPIO_FN_TIOC1B_C,
+ GPIO_FN_A8, GPIO_FN_ST0_D4, GPIO_FN_LCD_DATA8_A,
+ GPIO_FN_TIOC1A_C,
+ GPIO_FN_A7, GPIO_FN_ST0_D3, GPIO_FN_LCD_DATA7_A, GPIO_FN_TIOC0D_C,
+ GPIO_FN_A6, GPIO_FN_ST0_D2, GPIO_FN_LCD_DATA6_A, GPIO_FN_TIOC0C_C,
+ GPIO_FN_A5, GPIO_FN_ST0_D1, GPIO_FN_LCD_DATA5_A, GPIO_FN_TIOC0B_C,
+ GPIO_FN_A4, GPIO_FN_ST0_D0, GPIO_FN_LCD_DATA4_A, GPIO_FN_TIOC0A_C,
+ GPIO_FN_A3, GPIO_FN_ST0_VLD, GPIO_FN_LCD_DATA3_A, GPIO_FN_TCLKD_C,
+ GPIO_FN_A2, GPIO_FN_ST0_SYC, GPIO_FN_LCD_DATA2_A, GPIO_FN_TCLKC_C,
+ GPIO_FN_A1, GPIO_FN_ST0_REQ, GPIO_FN_LCD_DATA1_A, GPIO_FN_TCLKB_C,
+ GPIO_FN_A0, GPIO_FN_ST0_CLKIN, GPIO_FN_LCD_DATA0_A, GPIO_FN_TCLKA_C,
+
+ /* IPSR1 */
+ GPIO_FN_D3, GPIO_FN_SD0_DAT3_A, GPIO_FN_MMC_D3_A, GPIO_FN_ST1_D6,
+ GPIO_FN_FD3_A,
+ GPIO_FN_D2, GPIO_FN_SD0_DAT2_A, GPIO_FN_MMC_D2_A, GPIO_FN_ST1_D5,
+ GPIO_FN_FD2_A,
+ GPIO_FN_D1, GPIO_FN_SD0_DAT1_A, GPIO_FN_MMC_D1_A, GPIO_FN_ST1_D4,
+ GPIO_FN_FD1_A,
+ GPIO_FN_D0, GPIO_FN_SD0_DAT0_A, GPIO_FN_MMC_D0_A, GPIO_FN_ST1_D3,
+ GPIO_FN_FD0_A,
+ GPIO_FN_A25, GPIO_FN_TX2_D, GPIO_FN_ST1_D2,
+ GPIO_FN_A24, GPIO_FN_RX2_D, GPIO_FN_ST1_D1,
+ GPIO_FN_A23, GPIO_FN_ST1_D0, GPIO_FN_LCD_M_DISP_A,
+ GPIO_FN_A22, GPIO_FN_ST1_VLD, GPIO_FN_LCD_VEPWC_A,
+ GPIO_FN_A21, GPIO_FN_ST1_SYC, GPIO_FN_LCD_VCPWC_A,
+ GPIO_FN_A20, GPIO_FN_ST1_REQ, GPIO_FN_LCD_FLM_A,
+ GPIO_FN_A19, GPIO_FN_ST1_CLKIN, GPIO_FN_LCD_CLK_A, GPIO_FN_TIOC4D_C,
+ GPIO_FN_A18, GPIO_FN_ST1_PWM, GPIO_FN_LCD_CL2_A, GPIO_FN_TIOC4C_C,
+ GPIO_FN_A17, GPIO_FN_ST1_VCO_CLKIN, GPIO_FN_LCD_CL1_A, GPIO_FN_TIOC4B_C,
+ GPIO_FN_A16, GPIO_FN_ST0_PWM, GPIO_FN_LCD_DON_A, GPIO_FN_TIOC4A_C,
+
+ /* IPSR2 */
+ GPIO_FN_D14, GPIO_FN_TX2_B, GPIO_FN_FSE_A, GPIO_FN_ET0_TX_CLK_B,
+ GPIO_FN_D13, GPIO_FN_RX2_B, GPIO_FN_FRB_A, GPIO_FN_ET0_ETXD6_B,
+ GPIO_FN_D12, GPIO_FN_FWE_A, GPIO_FN_ET0_ETXD5_B,
+ GPIO_FN_D11, GPIO_FN_RSPI_MISO_A, GPIO_FN_QMI_QIO1_A,
+ GPIO_FN_FRE_A, GPIO_FN_ET0_ETXD3_B,
+ GPIO_FN_D10, GPIO_FN_RSPI_MOSI_A, GPIO_FN_QMO_QIO0_A,
+ GPIO_FN_FALE_A, GPIO_FN_ET0_ETXD2_B,
+ GPIO_FN_D9, GPIO_FN_SD0_CMD_A, GPIO_FN_MMC_CMD_A, GPIO_FN_QIO3_A,
+ GPIO_FN_FCLE_A, GPIO_FN_ET0_ETXD1_B,
+ GPIO_FN_D8, GPIO_FN_SD0_CLK_A, GPIO_FN_MMC_CLK_A, GPIO_FN_QIO2_A,
+ GPIO_FN_FCE_A, GPIO_FN_ET0_GTX_CLK_B,
+ GPIO_FN_D7, GPIO_FN_RSPI_SSL_A, GPIO_FN_MMC_D7_A, GPIO_FN_QSSL_A,
+ GPIO_FN_FD7_A,
+ GPIO_FN_D6, GPIO_FN_RSPI_RSPCK_A, GPIO_FN_MMC_D6_A, GPIO_FN_QSPCLK_A,
+ GPIO_FN_FD6_A,
+ GPIO_FN_D5, GPIO_FN_SD0_WP_A, GPIO_FN_MMC_D5_A, GPIO_FN_FD5_A,
+ GPIO_FN_D4, GPIO_FN_SD0_CD_A, GPIO_FN_MMC_D4_A, GPIO_FN_ST1_D7,
+ GPIO_FN_FD4_A,
+
+ /* IPSR3 */
+ GPIO_FN_DRACK0, GPIO_FN_SD1_DAT2_A, GPIO_FN_ATAG, GPIO_FN_TCLK1_A,
+ GPIO_FN_ET0_ETXD7,
+ GPIO_FN_EX_WAIT2, GPIO_FN_SD1_DAT1_A, GPIO_FN_DACK2, GPIO_FN_CAN1_RX_C,
+ GPIO_FN_ET0_MAGIC_C, GPIO_FN_ET0_ETXD6_A,
+ GPIO_FN_EX_WAIT1, GPIO_FN_SD1_DAT0_A, GPIO_FN_DREQ2, GPIO_FN_CAN1_TX_C,
+ GPIO_FN_ET0_LINK_C, GPIO_FN_ET0_ETXD5_A,
+ GPIO_FN_EX_WAIT0, GPIO_FN_TCLK1_B,
+ GPIO_FN_RD_WR, GPIO_FN_TCLK0,
+ GPIO_FN_EX_CS5, GPIO_FN_SD1_CMD_A, GPIO_FN_ATADIR, GPIO_FN_QSSL_B,
+ GPIO_FN_ET0_ETXD3_A,
+ GPIO_FN_EX_CS4, GPIO_FN_SD1_WP_A, GPIO_FN_ATAWR, GPIO_FN_QMI_QIO1_B,
+ GPIO_FN_ET0_ETXD2_A,
+ GPIO_FN_EX_CS3, GPIO_FN_SD1_CD_A, GPIO_FN_ATARD, GPIO_FN_QMO_QIO0_B,
+ GPIO_FN_ET0_ETXD1_A,
+ GPIO_FN_EX_CS2, GPIO_FN_TX3_B, GPIO_FN_ATACS1, GPIO_FN_QSPCLK_B,
+ GPIO_FN_ET0_GTX_CLK_A,
+ GPIO_FN_EX_CS1, GPIO_FN_RX3_B, GPIO_FN_ATACS0, GPIO_FN_QIO2_B,
+ GPIO_FN_ET0_ETXD0,
+ GPIO_FN_CS1_A26, GPIO_FN_QIO3_B,
+ GPIO_FN_D15, GPIO_FN_SCK2_B,
+
+ /* IPSR4 */
+ GPIO_FN_SCK2_A, GPIO_FN_VI0_G3,
+ GPIO_FN_RTS1_B, GPIO_FN_VI0_G2,
+ GPIO_FN_CTS1_B, GPIO_FN_VI0_DATA7_VI0_G1,
+ GPIO_FN_TX1_B, GPIO_FN_VI0_DATA6_VI0_G0, GPIO_FN_ET0_PHY_INT_A,
+ GPIO_FN_RX1_B, GPIO_FN_VI0_DATA5_VI0_B5, GPIO_FN_ET0_MAGIC_A,
+ GPIO_FN_SCK1_B, GPIO_FN_VI0_DATA4_VI0_B4, GPIO_FN_ET0_LINK_A,
+ GPIO_FN_RTS0_B, GPIO_FN_VI0_DATA3_VI0_B3, GPIO_FN_ET0_MDIO_A,
+ GPIO_FN_CTS0_B, GPIO_FN_VI0_DATA2_VI0_B2, GPIO_FN_RMII0_MDIO_A,
+ GPIO_FN_ET0_MDC,
+ GPIO_FN_HTX0_A, GPIO_FN_TX1_A, GPIO_FN_VI0_DATA1_VI0_B1,
+ GPIO_FN_RMII0_MDC_A, GPIO_FN_ET0_COL,
+ GPIO_FN_HRX0_A, GPIO_FN_RX1_A, GPIO_FN_VI0_DATA0_VI0_B0,
+ GPIO_FN_RMII0_CRS_DV_A, GPIO_FN_ET0_CRS,
+ GPIO_FN_HSCK0_A, GPIO_FN_SCK1_A, GPIO_FN_VI0_VSYNC,
+ GPIO_FN_RMII0_RX_ER_A, GPIO_FN_ET0_RX_ER,
+ GPIO_FN_HRTS0_A, GPIO_FN_RTS1_A, GPIO_FN_VI0_HSYNC,
+ GPIO_FN_RMII0_TXD_EN_A, GPIO_FN_ET0_RX_DV,
+ GPIO_FN_HCTS0_A, GPIO_FN_CTS1_A, GPIO_FN_VI0_FIELD,
+ GPIO_FN_RMII0_RXD1_A, GPIO_FN_ET0_ERXD7,
+
+ /* IPSR5 */
+ GPIO_FN_SD2_CLK_A, GPIO_FN_RX2_A, GPIO_FN_VI0_G4, GPIO_FN_ET0_RX_CLK_B,
+ GPIO_FN_SD2_CMD_A, GPIO_FN_TX2_A, GPIO_FN_VI0_G5, GPIO_FN_ET0_ERXD2_B,
+ GPIO_FN_SD2_DAT0_A, GPIO_FN_RX3_A, GPIO_FN_VI0_R0, GPIO_FN_ET0_ERXD3_B,
+ GPIO_FN_SD2_DAT1_A, GPIO_FN_TX3_A, GPIO_FN_VI0_R1, GPIO_FN_ET0_MDIO_B,
+ GPIO_FN_SD2_DAT2_A, GPIO_FN_RX4_A, GPIO_FN_VI0_R2, GPIO_FN_ET0_LINK_B,
+ GPIO_FN_SD2_DAT3_A, GPIO_FN_TX4_A, GPIO_FN_VI0_R3, GPIO_FN_ET0_MAGIC_B,
+ GPIO_FN_SD2_CD_A, GPIO_FN_RX5_A, GPIO_FN_VI0_R4, GPIO_FN_ET0_PHY_INT_B,
+ GPIO_FN_SD2_WP_A, GPIO_FN_TX5_A, GPIO_FN_VI0_R5,
+ GPIO_FN_REF125CK, GPIO_FN_ADTRG, GPIO_FN_RX5_C,
+ GPIO_FN_REF50CK, GPIO_FN_CTS1_E, GPIO_FN_HCTS0_D,
+
+ /* IPSR6 */
+ GPIO_FN_DU0_DR0, GPIO_FN_SCIF_CLK_B, GPIO_FN_HRX0_D, GPIO_FN_IETX_A,
+ GPIO_FN_TCLKA_A, GPIO_FN_HIFD00,
+ GPIO_FN_DU0_DR1, GPIO_FN_SCK0_B, GPIO_FN_HTX0_D, GPIO_FN_IERX_A,
+ GPIO_FN_TCLKB_A, GPIO_FN_HIFD01,
+ GPIO_FN_DU0_DR2, GPIO_FN_RX0_B, GPIO_FN_TCLKC_A, GPIO_FN_HIFD02,
+ GPIO_FN_DU0_DR3, GPIO_FN_TX0_B, GPIO_FN_TCLKD_A, GPIO_FN_HIFD03,
+ GPIO_FN_DU0_DR4, GPIO_FN_CTS0_C, GPIO_FN_TIOC0A_A, GPIO_FN_HIFD04,
+ GPIO_FN_DU0_DR5, GPIO_FN_RTS0_C, GPIO_FN_TIOC0B_A, GPIO_FN_HIFD05,
+ GPIO_FN_DU0_DR6, GPIO_FN_SCK1_C, GPIO_FN_TIOC0C_A, GPIO_FN_HIFD06,
+ GPIO_FN_DU0_DR7, GPIO_FN_RX1_C, GPIO_FN_TIOC0D_A, GPIO_FN_HIFD07,
+ GPIO_FN_DU0_DG0, GPIO_FN_TX1_C, GPIO_FN_HSCK0_D, GPIO_FN_IECLK_A,
+ GPIO_FN_TIOC1A_A, GPIO_FN_HIFD08,
+ GPIO_FN_DU0_DG1, GPIO_FN_CTS1_C, GPIO_FN_HRTS0_D, GPIO_FN_TIOC1B_A,
+ GPIO_FN_HIFD09,
+
+ /* IPSR7 */
+ GPIO_FN_DU0_DG2, GPIO_FN_RTS1_C, GPIO_FN_RMII0_MDC_B, GPIO_FN_TIOC2A_A,
+ GPIO_FN_HIFD10,
+ GPIO_FN_DU0_DG3, GPIO_FN_SCK2_C, GPIO_FN_RMII0_MDIO_B, GPIO_FN_TIOC2B_A,
+ GPIO_FN_HIFD11,
+ GPIO_FN_DU0_DG4, GPIO_FN_RX2_C, GPIO_FN_RMII0_CRS_DV_B,
+ GPIO_FN_TIOC3A_A, GPIO_FN_HIFD12,
+ GPIO_FN_DU0_DG5, GPIO_FN_TX2_C, GPIO_FN_RMII0_RX_ER_B,
+ GPIO_FN_TIOC3B_A, GPIO_FN_HIFD13,
+ GPIO_FN_DU0_DG6, GPIO_FN_RX3_C, GPIO_FN_RMII0_RXD0_B,
+ GPIO_FN_TIOC3C_A, GPIO_FN_HIFD14,
+ GPIO_FN_DU0_DG7, GPIO_FN_TX3_C, GPIO_FN_RMII0_RXD1_B,
+ GPIO_FN_TIOC3D_A, GPIO_FN_HIFD15,
+ GPIO_FN_DU0_DB0, GPIO_FN_RX4_C, GPIO_FN_RMII0_TXD_EN_B,
+ GPIO_FN_TIOC4A_A, GPIO_FN_HIFCS,
+ GPIO_FN_DU0_DB1, GPIO_FN_TX4_C, GPIO_FN_RMII0_TXD0_B,
+ GPIO_FN_TIOC4B_A, GPIO_FN_HIFRS,
+ GPIO_FN_DU0_DB2, GPIO_FN_RX5_B, GPIO_FN_RMII0_TXD1_B,
+ GPIO_FN_TIOC4C_A, GPIO_FN_HIFWR,
+ GPIO_FN_DU0_DB3, GPIO_FN_TX5_B, GPIO_FN_TIOC4D_A, GPIO_FN_HIFRD,
+ GPIO_FN_DU0_DB4, GPIO_FN_HIFINT,
+
+ /* IPSR8 */
+ GPIO_FN_DU0_DB5, GPIO_FN_HIFDREQ,
+ GPIO_FN_DU0_DB6, GPIO_FN_HIFRDY,
+ GPIO_FN_DU0_DB7, GPIO_FN_SSI_SCK0_B, GPIO_FN_HIFEBL_B,
+ GPIO_FN_DU0_DOTCLKIN, GPIO_FN_HSPI_CS0_C, GPIO_FN_SSI_WS0_B,
+ GPIO_FN_DU0_DOTCLKOUT, GPIO_FN_HSPI_CLK0_C, GPIO_FN_SSI_SDATA0_B,
+ GPIO_FN_DU0_EXHSYNC_DU0_HSYNC, GPIO_FN_HSPI_TX0_C, GPIO_FN_SSI_SCK1_B,
+ GPIO_FN_DU0_EXVSYNC_DU0_VSYNC, GPIO_FN_HSPI_RX0_C, GPIO_FN_SSI_WS1_B,
+ GPIO_FN_DU0_EXODDF_DU0_ODDF, GPIO_FN_CAN0_RX_B, GPIO_FN_HSCK0_B,
+ GPIO_FN_SSI_SDATA1_B,
+ GPIO_FN_DU0_DISP, GPIO_FN_CAN0_TX_B, GPIO_FN_HRX0_B,
+ GPIO_FN_AUDIO_CLKA_B,
+ GPIO_FN_DU0_CDE, GPIO_FN_HTX0_B, GPIO_FN_AUDIO_CLKB_B,
+ GPIO_FN_LCD_VCPWC_B,
+ GPIO_FN_IRQ0_A, GPIO_FN_HSPI_TX_B, GPIO_FN_RX3_E, GPIO_FN_ET0_ERXD0,
+ GPIO_FN_IRQ1_A, GPIO_FN_HSPI_RX_B, GPIO_FN_TX3_E, GPIO_FN_ET0_ERXD1,
+ GPIO_FN_IRQ2_A, GPIO_FN_CTS0_A, GPIO_FN_HCTS0_B, GPIO_FN_ET0_ERXD2_A,
+ GPIO_FN_IRQ3_A, GPIO_FN_RTS0_A, GPIO_FN_HRTS0_B, GPIO_FN_ET0_ERXD3_A,
+
+ /* IPSR9 */
+ GPIO_FN_VI1_CLK_A, GPIO_FN_FD0_B, GPIO_FN_LCD_DATA0_B,
+ GPIO_FN_VI1_0_A, GPIO_FN_FD1_B, GPIO_FN_LCD_DATA1_B,
+ GPIO_FN_VI1_1_A, GPIO_FN_FD2_B, GPIO_FN_LCD_DATA2_B,
+ GPIO_FN_VI1_2_A, GPIO_FN_FD3_B, GPIO_FN_LCD_DATA3_B,
+ GPIO_FN_VI1_3_A, GPIO_FN_FD4_B, GPIO_FN_LCD_DATA4_B,
+ GPIO_FN_VI1_4_A, GPIO_FN_FD5_B, GPIO_FN_LCD_DATA5_B,
+ GPIO_FN_VI1_5_A, GPIO_FN_FD6_B, GPIO_FN_LCD_DATA6_B,
+ GPIO_FN_VI1_6_A, GPIO_FN_FD7_B, GPIO_FN_LCD_DATA7_B,
+ GPIO_FN_VI1_7_A, GPIO_FN_FCE_B, GPIO_FN_LCD_DATA8_B,
+ GPIO_FN_SSI_SCK0_A, GPIO_FN_TIOC1A_B, GPIO_FN_LCD_DATA9_B,
+ GPIO_FN_SSI_WS0_A, GPIO_FN_TIOC1B_B, GPIO_FN_LCD_DATA10_B,
+ GPIO_FN_SSI_SDATA0_A, GPIO_FN_VI1_0_B, GPIO_FN_TIOC2A_B,
+ GPIO_FN_LCD_DATA11_B,
+ GPIO_FN_SSI_SCK1_A, GPIO_FN_VI1_1_B, GPIO_FN_TIOC2B_B,
+ GPIO_FN_LCD_DATA12_B,
+ GPIO_FN_SSI_WS1_A, GPIO_FN_VI1_2_B, GPIO_FN_LCD_DATA13_B,
+ GPIO_FN_SSI_SDATA1_A, GPIO_FN_VI1_3_B, GPIO_FN_LCD_DATA14_B,
+
+ /* IPSR10 */
+ GPIO_FN_SSI_SCK23, GPIO_FN_VI1_4_B, GPIO_FN_RX1_D, GPIO_FN_FCLE_B,
+ GPIO_FN_LCD_DATA15_B,
+ GPIO_FN_SSI_WS23, GPIO_FN_VI1_5_B, GPIO_FN_TX1_D, GPIO_FN_HSCK0_C,
+ GPIO_FN_FALE_B, GPIO_FN_LCD_DON_B,
+ GPIO_FN_SSI_SDATA2, GPIO_FN_VI1_6_B, GPIO_FN_HRX0_C, GPIO_FN_FRE_B,
+ GPIO_FN_LCD_CL1_B,
+ GPIO_FN_SSI_SDATA3, GPIO_FN_VI1_7_B, GPIO_FN_HTX0_C, GPIO_FN_FWE_B,
+ GPIO_FN_LCD_CL2_B,
+ GPIO_FN_AUDIO_CLKA_A, GPIO_FN_VI1_CLK_B, GPIO_FN_SCK1_D,
+ GPIO_FN_IECLK_B, GPIO_FN_LCD_FLM_B,
+ GPIO_FN_AUDIO_CLKB_A, GPIO_FN_LCD_CLK_B,
+ GPIO_FN_AUDIO_CLKC, GPIO_FN_SCK1_E, GPIO_FN_HCTS0_C, GPIO_FN_FRB_B,
+ GPIO_FN_LCD_VEPWC_B,
+ GPIO_FN_AUDIO_CLKOUT, GPIO_FN_TX1_E, GPIO_FN_HRTS0_C, GPIO_FN_FSE_B,
+ GPIO_FN_LCD_M_DISP_B,
+ GPIO_FN_CAN_CLK_A, GPIO_FN_RX4_D,
+ GPIO_FN_CAN0_TX_A, GPIO_FN_TX4_D, GPIO_FN_MLB_CLK,
+ GPIO_FN_CAN1_RX_A, GPIO_FN_IRQ1_B,
+ GPIO_FN_CAN0_RX_A, GPIO_FN_IRQ0_B, GPIO_FN_MLB_SIG,
+ GPIO_FN_CAN1_TX_A, GPIO_FN_TX5_C, GPIO_FN_MLB_DAT,
+
+ /* IPSR11 */
+ GPIO_FN_SCL1, GPIO_FN_SCIF_CLK_C,
+ GPIO_FN_SDA1, GPIO_FN_RX1_E,
+ GPIO_FN_SDA0, GPIO_FN_HIFEBL_A,
+ GPIO_FN_SDSELF, GPIO_FN_RTS1_E,
+ GPIO_FN_SCIF_CLK_A, GPIO_FN_HSPI_CLK_A, GPIO_FN_VI0_CLK,
+ GPIO_FN_RMII0_TXD0_A, GPIO_FN_ET0_ERXD4,
+ GPIO_FN_SCK0_A, GPIO_FN_HSPI_CS_A, GPIO_FN_VI0_CLKENB,
+ GPIO_FN_RMII0_TXD1_A, GPIO_FN_ET0_ERXD5,
+ GPIO_FN_RX0_A, GPIO_FN_HSPI_RX_A, GPIO_FN_RMII0_RXD0_A,
+ GPIO_FN_ET0_ERXD6,
+ GPIO_FN_TX0_A, GPIO_FN_HSPI_TX_A,
+ GPIO_FN_PENC1, GPIO_FN_TX3_D, GPIO_FN_CAN1_TX_B, GPIO_FN_TX5_D,
+ GPIO_FN_IETX_B,
+ GPIO_FN_USB_OVC1, GPIO_FN_RX3_D, GPIO_FN_CAN1_RX_B, GPIO_FN_RX5_D,
+ GPIO_FN_IERX_B,
+ GPIO_FN_DREQ0, GPIO_FN_SD1_CLK_A, GPIO_FN_ET0_TX_EN,
+ GPIO_FN_DACK0, GPIO_FN_SD1_DAT3_A, GPIO_FN_ET0_TX_ER,
+ GPIO_FN_DREQ1, GPIO_FN_HSPI_CLK_B, GPIO_FN_RX4_B, GPIO_FN_ET0_PHY_INT_C,
+ GPIO_FN_ET0_TX_CLK_A,
+ GPIO_FN_DACK1, GPIO_FN_HSPI_CS_B, GPIO_FN_TX4_B, GPIO_FN_ET0_RX_CLK_A,
+ GPIO_FN_PRESETOUT, GPIO_FN_ST_CLKOUT,
+
+};
+
+#endif /* __ASM_SH7734_H__ */
diff --git a/arch/sh/include/cpu-sh4a/cpu/dma.h b/arch/sh/include/cpu-sh4a/cpu/dma.h
new file mode 100644
index 000000000000..89afb650ce25
--- /dev/null
+++ b/arch/sh/include/cpu-sh4a/cpu/dma.h
@@ -0,0 +1,72 @@
+#ifndef __ASM_SH_CPU_SH4_DMA_SH7780_H
+#define __ASM_SH_CPU_SH4_DMA_SH7780_H
+
+#include <linux/sh_intc.h>
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7343) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7730)
+#define DMTE0_IRQ evt2irq(0x800)
+#define DMTE4_IRQ evt2irq(0xb80)
+#define DMAE0_IRQ evt2irq(0xbc0) /* DMA Error IRQ*/
+#define SH_DMAC_BASE0 0xFE008020
+#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
+#define DMTE0_IRQ evt2irq(0x800)
+#define DMTE4_IRQ evt2irq(0xb80)
+#define DMAE0_IRQ evt2irq(0xbc0) /* DMA Error IRQ*/
+#define SH_DMAC_BASE0 0xFE008020
+#elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7764)
+#define DMTE0_IRQ evt2irq(0x640)
+#define DMTE4_IRQ evt2irq(0x780)
+#define DMAE0_IRQ evt2irq(0x6c0)
+#define SH_DMAC_BASE0 0xFF608020
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+#define DMTE0_IRQ evt2irq(0x800) /* DMAC0A*/
+#define DMTE4_IRQ evt2irq(0xb80) /* DMAC0B */
+#define DMTE6_IRQ evt2irq(0x700)
+#define DMTE8_IRQ evt2irq(0x740) /* DMAC1A */
+#define DMTE9_IRQ evt2irq(0x760)
+#define DMTE10_IRQ evt2irq(0xb00) /* DMAC1B */
+#define DMTE11_IRQ evt2irq(0xb20)
+#define DMAE0_IRQ evt2irq(0xbc0) /* DMA Error IRQ*/
+#define DMAE1_IRQ evt2irq(0xb40) /* DMA Error IRQ*/
+#define SH_DMAC_BASE0 0xFE008020
+#define SH_DMAC_BASE1 0xFDC08020
+#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define DMTE0_IRQ evt2irq(0x800) /* DMAC0A*/
+#define DMTE4_IRQ evt2irq(0xb80) /* DMAC0B */
+#define DMTE6_IRQ evt2irq(0x700)
+#define DMTE8_IRQ evt2irq(0x740) /* DMAC1A */
+#define DMTE9_IRQ evt2irq(0x760)
+#define DMTE10_IRQ evt2irq(0xb00) /* DMAC1B */
+#define DMTE11_IRQ evt2irq(0xb20)
+#define DMAE0_IRQ evt2irq(0xbc0) /* DMA Error IRQ*/
+#define DMAE1_IRQ evt2irq(0xb40) /* DMA Error IRQ*/
+#define SH_DMAC_BASE0 0xFE008020
+#define SH_DMAC_BASE1 0xFDC08020
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+#define DMTE0_IRQ evt2irq(0x640)
+#define DMTE4_IRQ evt2irq(0x780)
+#define DMTE6_IRQ evt2irq(0x7c0)
+#define DMTE8_IRQ evt2irq(0xd80)
+#define DMTE9_IRQ evt2irq(0xda0)
+#define DMTE10_IRQ evt2irq(0xdc0)
+#define DMTE11_IRQ evt2irq(0xde0)
+#define DMAE0_IRQ evt2irq(0x6c0) /* DMA Error IRQ */
+#define SH_DMAC_BASE0 0xFC808020
+#define SH_DMAC_BASE1 0xFC818020
+#else /* SH7785 */
+#define DMTE0_IRQ evt2irq(0x620)
+#define DMTE4_IRQ evt2irq(0x6a0)
+#define DMTE6_IRQ evt2irq(0x880)
+#define DMTE8_IRQ evt2irq(0x8c0)
+#define DMTE9_IRQ evt2irq(0x8e0)
+#define DMTE10_IRQ evt2irq(0x900)
+#define DMTE11_IRQ evt2irq(0x920)
+#define DMAE0_IRQ evt2irq(0x6e0) /* DMA Error IRQ0 */
+#define DMAE1_IRQ evt2irq(0x940) /* DMA Error IRQ1 */
+#define SH_DMAC_BASE0 0xFC808020
+#define SH_DMAC_BASE1 0xFCC08020
+#endif
+
+#endif /* __ASM_SH_CPU_SH4_DMA_SH7780_H */
diff --git a/arch/sh/include/cpu-sh5/cpu/dma.h b/arch/sh/include/cpu-sh5/cpu/dma.h
deleted file mode 100644
index 7bf6bb3d35ed..000000000000
--- a/arch/sh/include/cpu-sh5/cpu/dma.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_SH_CPU_SH5_DMA_H
-#define __ASM_SH_CPU_SH5_DMA_H
-
-/* Nothing yet */
-
-#endif /* __ASM_SH_CPU_SH5_DMA_H */
diff --git a/arch/sh/include/mach-common/mach/hp6xx.h b/arch/sh/include/mach-common/mach/hp6xx.h
index bcc301ac12f4..6aaaf8596e6a 100644
--- a/arch/sh/include/mach-common/mach/hp6xx.h
+++ b/arch/sh/include/mach-common/mach/hp6xx.h
@@ -9,10 +9,11 @@
* for more details.
*
*/
+#include <linux/sh_intc.h>
-#define HP680_BTN_IRQ 32 /* IRQ0_IRQ */
-#define HP680_TS_IRQ 35 /* IRQ3_IRQ */
-#define HP680_HD64461_IRQ 36 /* IRQ4_IRQ */
+#define HP680_BTN_IRQ evt2irq(0x600) /* IRQ0_IRQ */
+#define HP680_TS_IRQ evt2irq(0x660) /* IRQ3_IRQ */
+#define HP680_HD64461_IRQ evt2irq(0x680) /* IRQ4_IRQ */
#define DAC_LCD_BRIGHTNESS 0
#define DAC_SPEAKER_VOLUME 1
diff --git a/arch/sh/include/mach-common/mach/lboxre2.h b/arch/sh/include/mach-common/mach/lboxre2.h
index e6d160504923..3a4dcc5c74ee 100644
--- a/arch/sh/include/mach-common/mach/lboxre2.h
+++ b/arch/sh/include/mach-common/mach/lboxre2.h
@@ -11,13 +11,14 @@
* for more details.
*
*/
+#include <linux/sh_intc.h>
-#define IRQ_CF1 9 /* CF1 */
-#define IRQ_CF0 10 /* CF0 */
-#define IRQ_INTD 11 /* INTD */
-#define IRQ_ETH1 12 /* Ether1 */
-#define IRQ_ETH0 13 /* Ether0 */
-#define IRQ_INTA 14 /* INTA */
+#define IRQ_CF1 evt2irq(0x320) /* CF1 */
+#define IRQ_CF0 evt2irq(0x340) /* CF0 */
+#define IRQ_INTD evt2irq(0x360) /* INTD */
+#define IRQ_ETH1 evt2irq(0x380) /* Ether1 */
+#define IRQ_ETH0 evt2irq(0x3a0) /* Ether0 */
+#define IRQ_INTA evt2irq(0x3c0) /* INTA */
void init_lboxre2_IRQ(void);
diff --git a/arch/sh/include/mach-common/mach/sdk7780.h b/arch/sh/include/mach-common/mach/sdk7780.h
index 697dc865f21b..ce64e02e9b50 100644
--- a/arch/sh/include/mach-common/mach/sdk7780.h
+++ b/arch/sh/include/mach-common/mach/sdk7780.h
@@ -11,6 +11,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
+#include <linux/sh_intc.h>
#include <asm/addrspace.h>
/* Box specific addresses. */
@@ -67,9 +68,9 @@
#define SDK7780_NR_IRL 15
/* IDE/ATA interrupt */
-#define IRQ_CFCARD 14
+#define IRQ_CFCARD evt2irq(0x3c0)
/* SMC interrupt */
-#define IRQ_ETHERNET 6
+#define IRQ_ETHERNET evt2irq(0x2c0)
/* arch/sh/boards/renesas/sdk7780/irq.c */
diff --git a/arch/sh/include/mach-common/mach/titan.h b/arch/sh/include/mach-common/mach/titan.h
index 4a674d27cbb8..fa3cd801cf2e 100644
--- a/arch/sh/include/mach-common/mach/titan.h
+++ b/arch/sh/include/mach-common/mach/titan.h
@@ -4,14 +4,16 @@
#ifndef _ASM_SH_TITAN_H
#define _ASM_SH_TITAN_H
+#include <linux/sh_intc.h>
+
#define __IO_PREFIX titan
#include <asm/io_generic.h>
/* IRQ assignments */
-#define TITAN_IRQ_WAN 2 /* eth0 (WAN) */
-#define TITAN_IRQ_LAN 5 /* eth1 (LAN) */
-#define TITAN_IRQ_MPCIA 8 /* mPCI A */
-#define TITAN_IRQ_MPCIB 11 /* mPCI B */
-#define TITAN_IRQ_USB 11 /* USB */
+#define TITAN_IRQ_WAN evt2irq(0x240) /* eth0 (WAN) */
+#define TITAN_IRQ_LAN evt2irq(0x2a0) /* eth1 (LAN) */
+#define TITAN_IRQ_MPCIA evt2irq(0x300) /* mPCI A */
+#define TITAN_IRQ_MPCIB evt2irq(0x360) /* mPCI B */
+#define TITAN_IRQ_USB evt2irq(0x360) /* USB */
#endif /* __ASM_SH_TITAN_H */
diff --git a/arch/sh/include/mach-dreamcast/mach/dma.h b/arch/sh/include/mach-dreamcast/mach/dma.h
index ddd68e788705..1dbfdf701c9d 100644
--- a/arch/sh/include/mach-dreamcast/mach/dma.h
+++ b/arch/sh/include/mach-dreamcast/mach/dma.h
@@ -11,9 +11,7 @@
#define __ASM_SH_DREAMCAST_DMA_H
/* Number of DMA channels */
-#define ONCHIP_NR_DMA_CHANNELS 4
#define G2_NR_DMA_CHANNELS 4
-#define PVR2_NR_DMA_CHANNELS 1
/* Channels for cascading */
#define PVR2_CASCADE_CHAN 2
diff --git a/arch/sh/include/mach-landisk/mach/iodata_landisk.h b/arch/sh/include/mach-landisk/mach/iodata_landisk.h
index f432773a9571..ceeea48cc7af 100644
--- a/arch/sh/include/mach-landisk/mach/iodata_landisk.h
+++ b/arch/sh/include/mach-landisk/mach/iodata_landisk.h
@@ -8,6 +8,7 @@
*
* IO-DATA LANDISK support
*/
+#include <linux/sh_intc.h>
/* Box specific addresses. */
@@ -25,15 +26,15 @@
#define PA_PIDE_OFFSET 0x40 /* CF IDE Offset */
#define PA_SIDE_OFFSET 0x40 /* HDD IDE Offset */
-#define IRQ_PCIINTA 5 /* PCI INTA IRQ */
-#define IRQ_PCIINTB 6 /* PCI INTB IRQ */
-#define IRQ_PCIINTC 7 /* PCI INTC IRQ */
-#define IRQ_PCIINTD 8 /* PCI INTD IRQ */
-#define IRQ_ATA 9 /* ATA IRQ */
-#define IRQ_FATA 10 /* FATA IRQ */
-#define IRQ_POWER 11 /* Power Switch IRQ */
-#define IRQ_BUTTON 12 /* USL-5P Button IRQ */
-#define IRQ_FAULT 13 /* USL-5P Fault IRQ */
+#define IRQ_PCIINTA evt2irq(0x2a0) /* PCI INTA IRQ */
+#define IRQ_PCIINTB evt2irq(0x2c0) /* PCI INTB IRQ */
+#define IRQ_PCIINTC evt2irq(0x2e0) /* PCI INTC IRQ */
+#define IRQ_PCIINTD evt2irq(0x300) /* PCI INTD IRQ */
+#define IRQ_ATA evt2irq(0x320) /* ATA IRQ */
+#define IRQ_FATA evt2irq(0x340) /* FATA IRQ */
+#define IRQ_POWER evt2irq(0x360) /* Power Switch IRQ */
+#define IRQ_BUTTON evt2irq(0x380) /* USL-5P Button IRQ */
+#define IRQ_FAULT evt2irq(0x3a0) /* USL-5P Fault IRQ */
void init_landisk_IRQ(void);
diff --git a/arch/sh/include/mach-se/mach/se.h b/arch/sh/include/mach-se/mach/se.h
index 14be91c5a2f0..8a6d44b4987b 100644
--- a/arch/sh/include/mach-se/mach/se.h
+++ b/arch/sh/include/mach-se/mach/se.h
@@ -8,6 +8,7 @@
*
* Hitachi SolutionEngine support
*/
+#include <linux/sh_intc.h>
/* Box specific addresses. */
@@ -82,16 +83,16 @@
#define INTC_IPRD 0xa4000018UL
#define INTC_IPRE 0xa400001aUL
-#define IRQ0_IRQ 32
-#define IRQ1_IRQ 33
+#define IRQ0_IRQ evt2irq(0x600)
+#define IRQ1_IRQ evt2irq(0x620)
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7705)
-#define IRQ_STNIC 12
-#define IRQ_CFCARD 14
+#define IRQ_STNIC evt2irq(0x380)
+#define IRQ_CFCARD evt2irq(0x3c0)
#else
-#define IRQ_STNIC 10
-#define IRQ_CFCARD 7
+#define IRQ_STNIC evt2irq(0x340)
+#define IRQ_CFCARD evt2irq(0x2e0)
#endif
/* SH Ether support (SH7710/SH7712) */
@@ -105,9 +106,9 @@
# define PHY_ID 0x01
#endif
/* Ether IRQ */
-#define SH_ETH0_IRQ 80
-#define SH_ETH1_IRQ 81
-#define SH_TSU_IRQ 82
+#define SH_ETH0_IRQ evt2irq(0xc00)
+#define SH_ETH1_IRQ evt2irq(0xc20)
+#define SH_TSU_IRQ evt2irq(0xc40)
void init_se_IRQ(void);
diff --git a/arch/sh/include/mach-se/mach/se7343.h b/arch/sh/include/mach-se/mach/se7343.h
index 8d8170d6cc43..50b5d575dff0 100644
--- a/arch/sh/include/mach-se/mach/se7343.h
+++ b/arch/sh/include/mach-se/mach/se7343.h
@@ -8,6 +8,7 @@
*
* SH-Mobile SolutionEngine 7343 support
*/
+#include <linux/sh_intc.h>
/* Box specific addresses. */
@@ -118,10 +119,10 @@
#define FPGA_IN 0xb1400000
#define FPGA_OUT 0xb1400002
-#define IRQ0_IRQ 32
-#define IRQ1_IRQ 33
-#define IRQ4_IRQ 36
-#define IRQ5_IRQ 37
+#define IRQ0_IRQ evt2irq(0x600)
+#define IRQ1_IRQ evt2irq(0x620)
+#define IRQ4_IRQ evt2irq(0x680)
+#define IRQ5_IRQ evt2irq(0x6a0)
#define SE7343_FPGA_IRQ_MRSHPC0 0
#define SE7343_FPGA_IRQ_MRSHPC1 1
diff --git a/arch/sh/include/mach-se/mach/se7721.h b/arch/sh/include/mach-se/mach/se7721.h
index b957f6041193..eabd0538de44 100644
--- a/arch/sh/include/mach-se/mach/se7721.h
+++ b/arch/sh/include/mach-se/mach/se7721.h
@@ -11,6 +11,8 @@
#ifndef __ASM_SH_SE7721_H
#define __ASM_SH_SE7721_H
+
+#include <linux/sh_intc.h>
#include <asm/addrspace.h>
/* Box specific addresses. */
@@ -49,9 +51,9 @@
#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
#define PA_LED 0xB6800000 /* 8bit LED */
-#define PA_FPGA 0xB7000000 /* FPGA base address */
+#define PA_FPGA 0xB7000000 /* FPGA base address */
-#define MRSHPC_IRQ0 10
+#define MRSHPC_IRQ0 evt2irq(0x340)
#define FPGA_ILSR1 (PA_FPGA + 0x02)
#define FPGA_ILSR2 (PA_FPGA + 0x03)
diff --git a/arch/sh/include/mach-se/mach/se7722.h b/arch/sh/include/mach-se/mach/se7722.h
index 16505bfb8a9e..201081ebdbce 100644
--- a/arch/sh/include/mach-se/mach/se7722.h
+++ b/arch/sh/include/mach-se/mach/se7722.h
@@ -13,6 +13,7 @@
* for more details.
*
*/
+#include <linux/sh_intc.h>
#include <asm/addrspace.h>
/* Box specific addresses. */
@@ -31,7 +32,7 @@
#define PA_PERIPHERAL 0xB0000000
-#define PA_PCIC PA_PERIPHERAL /* MR-SHPC-01 PCMCIA */
+#define PA_PCIC PA_PERIPHERAL /* MR-SHPC-01 PCMCIA */
#define PA_MRSHPC (PA_PERIPHERAL + 0x003fffe0) /* MR-SHPC-01 PCMCIA controller */
#define PA_MRSHPC_MW1 (PA_PERIPHERAL + 0x00400000) /* MR-SHPC-01 memory window base */
#define PA_MRSHPC_MW2 (PA_PERIPHERAL + 0x00500000) /* MR-SHPC-01 attribute window base */
@@ -51,7 +52,7 @@
#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
#define PA_LED (PA_PERIPHERAL + 0x00800000) /* 8bit LED */
-#define PA_FPGA (PA_PERIPHERAL + 0x01800000) /* FPGA base address */
+#define PA_FPGA (PA_PERIPHERAL + 0x01800000) /* FPGA base address */
#define PA_LAN (PA_AREA6_IO + 0) /* SMC LAN91C111 */
/* GPIO */
@@ -77,8 +78,8 @@
#define PORT_HIZCRC 0xA405015CUL
/* IRQ */
-#define IRQ0_IRQ 32
-#define IRQ1_IRQ 33
+#define IRQ0_IRQ evt2irq(0x600)
+#define IRQ1_IRQ evt2irq(0x620)
#define IRQ01_MODE 0xb1800000
#define IRQ01_STS 0xb1800004
diff --git a/arch/sh/include/mach-se/mach/se7724.h b/arch/sh/include/mach-se/mach/se7724.h
index 29514a39d0f5..be842dd1ca02 100644
--- a/arch/sh/include/mach-se/mach/se7724.h
+++ b/arch/sh/include/mach-se/mach/se7724.h
@@ -18,6 +18,7 @@
* for more details.
*
*/
+#include <linux/sh_intc.h>
#include <asm/addrspace.h>
/* SH Eth */
@@ -35,9 +36,9 @@
#define IRQ2_MR (0xba200028)
/* IRQ */
-#define IRQ0_IRQ 32
-#define IRQ1_IRQ 33
-#define IRQ2_IRQ 34
+#define IRQ0_IRQ evt2irq(0x600)
+#define IRQ1_IRQ evt2irq(0x620)
+#define IRQ2_IRQ evt2irq(0x640)
/* Bits in IRQ012 registers */
#define SE7724_FPGA_IRQ_BASE 220
diff --git a/arch/sh/include/mach-se/mach/se7751.h b/arch/sh/include/mach-se/mach/se7751.h
index b36792ac5d66..271871793d59 100644
--- a/arch/sh/include/mach-se/mach/se7751.h
+++ b/arch/sh/include/mach-se/mach/se7751.h
@@ -11,6 +11,7 @@
* Modified for 7751 Solution Engine by
* Ian da Silva and Jeremy Siegel, 2001.
*/
+#include <linux/sh_intc.h>
/* Box specific addresses. */
@@ -63,7 +64,7 @@
#define BCR_ILCRF (PA_BCR + 10)
#define BCR_ILCRG (PA_BCR + 12)
-#define IRQ_79C973 13
+#define IRQ_79C973 evt2irq(0x3a0)
void init_7751se_IRQ(void);
diff --git a/arch/sh/include/mach-se/mach/se7780.h b/arch/sh/include/mach-se/mach/se7780.h
index 40e9b41458cd..bde357cf81bd 100644
--- a/arch/sh/include/mach-se/mach/se7780.h
+++ b/arch/sh/include/mach-se/mach/se7780.h
@@ -12,6 +12,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
+#include <linux/sh_intc.h>
#include <asm/addrspace.h>
/* Box specific addresses. */
@@ -80,13 +81,13 @@
#define IRQPOS_PCCPW (0 * 4)
/* IDE interrupt */
-#define IRQ_IDE0 67 /* iVDR */
+#define IRQ_IDE0 evt2irq(0xa60) /* iVDR */
/* SMC interrupt */
-#define SMC_IRQ 8
+#define SMC_IRQ evt2irq(0x300)
/* SM501 interrupt */
-#define SM501_IRQ 0
+#define SM501_IRQ evt2irq(0x200)
/* interrupt pin */
#define IRQPIN_EXTINT1 0 /* IRQ0 pin */
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 77f7ae1d4647..88571ff8eeec 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -2,7 +2,7 @@
# Makefile for the Linux/SuperH kernel.
#
-extra-y := head_$(BITS).o init_task.o vmlinux.lds
+extra-y := head_$(BITS).o vmlinux.lds
ifdef CONFIG_FUNCTION_TRACER
# Do not profile debug and lowlevel utilities
diff --git a/arch/sh/kernel/cpu/proc.c b/arch/sh/kernel/cpu/proc.c
index f47be8727b3b..9e6624c9108b 100644
--- a/arch/sh/kernel/cpu/proc.c
+++ b/arch/sh/kernel/cpu/proc.c
@@ -7,6 +7,7 @@
static const char *cpu_name[] = {
[CPU_SH7201] = "SH7201",
[CPU_SH7203] = "SH7203", [CPU_SH7263] = "SH7263",
+ [CPU_SH7264] = "SH7264", [CPU_SH7269] = "SH7269",
[CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619",
[CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706",
[CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708",
@@ -25,7 +26,8 @@ static const char *cpu_name[] = {
[CPU_SH5_101] = "SH5-101", [CPU_SH5_103] = "SH5-103",
[CPU_MXG] = "MX-G", [CPU_SH7723] = "SH7723",
[CPU_SH7366] = "SH7366", [CPU_SH7724] = "SH7724",
- [CPU_SH7372] = "SH7372", [CPU_SH_NONE] = "Unknown"
+ [CPU_SH7372] = "SH7372", [CPU_SH7734] = "SH7734",
+ [CPU_SH_NONE] = "Unknown"
};
const char *get_cpu_subtype(struct sh_cpuinfo *c)
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index 0f8befccf9fa..e0b740c831c7 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -65,7 +65,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 88, 88, 88, 88 },
+ .irqs = SCIx_IRQ_MUXED(88),
};
static struct platform_device scif0_device = {
@@ -82,7 +82,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 92, 92, 92, 92 },
+ .irqs = SCIx_IRQ_MUXED(92),
};
static struct platform_device scif1_device = {
@@ -99,7 +99,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 96, 96, 96, 96 },
+ .irqs = SCIx_IRQ_MUXED(96),
};
static struct platform_device scif2_device = {
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile
index 45f85c77ef75..7fdc102d0dd6 100644
--- a/arch/sh/kernel/cpu/sh2a/Makefile
+++ b/arch/sh/kernel/cpu/sh2a/Makefile
@@ -11,10 +11,14 @@ obj-$(CONFIG_SH_FPU) += fpu.o
obj-$(CONFIG_CPU_SUBTYPE_SH7201) += setup-sh7201.o clock-sh7201.o
obj-$(CONFIG_CPU_SUBTYPE_SH7203) += setup-sh7203.o clock-sh7203.o
obj-$(CONFIG_CPU_SUBTYPE_SH7263) += setup-sh7203.o clock-sh7203.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7264) += setup-sh7264.o clock-sh7264.o
obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7269) += setup-sh7269.o clock-sh7269.o
obj-$(CONFIG_CPU_SUBTYPE_MXG) += setup-mxg.o clock-sh7206.o
# Pinmux setup
pinmux-$(CONFIG_CPU_SUBTYPE_SH7203) := pinmux-sh7203.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7264) := pinmux-sh7264.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7269) := pinmux-sh7269.o
obj-$(CONFIG_GENERIC_GPIO) += $(pinmux-y)
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7264.c b/arch/sh/kernel/cpu/sh2a/clock-sh7264.c
new file mode 100644
index 000000000000..fdf585c95289
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7264.c
@@ -0,0 +1,153 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/clock-sh7264.c
+ *
+ * SH7264 clock framework support
+ *
+ * Copyright (C) 2012 Phil Edworthy
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <asm/clock.h>
+
+/* SH7264 registers */
+#define FRQCR 0xfffe0010
+#define STBCR3 0xfffe0408
+#define STBCR4 0xfffe040c
+#define STBCR5 0xfffe0410
+#define STBCR6 0xfffe0414
+#define STBCR7 0xfffe0418
+#define STBCR8 0xfffe041c
+
+static const unsigned int pll1rate[] = {8, 12};
+
+static unsigned int pll1_div;
+
+/* Fixed 32 KHz root clock for RTC */
+static struct clk r_clk = {
+ .rate = 32768,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+ .rate = 18000000,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+ unsigned long rate = clk->parent->rate / pll1_div;
+ return rate * pll1rate[(__raw_readw(FRQCR) >> 8) & 1];
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
+};
+
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .parent = &extal_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+struct clk *main_clks[] = {
+ &r_clk,
+ &extal_clk,
+ &pll_clk,
+};
+
+static int div2[] = { 1, 2, 3, 4, 6, 8, 12 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = div2,
+ .nr_divisors = ARRAY_SIZE(div2),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I, DIV4_P,
+ DIV4_NR };
+
+#define DIV4(_reg, _bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
+
+/* The mask field specifies the div2 entries that are valid */
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_I] = DIV4(FRQCR, 4, 0x7, CLK_ENABLE_REG_16BIT
+ | CLK_ENABLE_ON_INIT),
+ [DIV4_P] = DIV4(FRQCR, 0, 0x78, CLK_ENABLE_REG_16BIT),
+};
+
+enum { MSTP77, MSTP74, MSTP72,
+ MSTP60,
+ MSTP35, MSTP34, MSTP33, MSTP32, MSTP30,
+ MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ [MSTP77] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR7, 7, 0), /* SCIF */
+ [MSTP74] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR7, 4, 0), /* VDC */
+ [MSTP72] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR7, 2, 0), /* CMT */
+ [MSTP60] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR6, 0, 0), /* USB */
+ [MSTP35] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR3, 6, 0), /* MTU2 */
+ [MSTP34] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR3, 4, 0), /* SDHI0 */
+ [MSTP33] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR3, 3, 0), /* SDHI1 */
+ [MSTP32] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR3, 2, 0), /* ADC */
+ [MSTP30] = SH_CLK_MSTP8(&r_clk, STBCR3, 0, 0), /* RTC */
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("rclk", &r_clk),
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+
+ /* MSTP clocks */
+ CLKDEV_CON_ID("sci_ick", &mstp_clks[MSTP77]),
+ CLKDEV_CON_ID("vdc3", &mstp_clks[MSTP74]),
+ CLKDEV_CON_ID("cmt_fck", &mstp_clks[MSTP72]),
+ CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]),
+ CLKDEV_CON_ID("mtu2_fck", &mstp_clks[MSTP35]),
+ CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP34]),
+ CLKDEV_CON_ID("sdhi1", &mstp_clks[MSTP33]),
+ CLKDEV_CON_ID("adc0", &mstp_clks[MSTP32]),
+ CLKDEV_CON_ID("rtc0", &mstp_clks[MSTP30]),
+};
+
+int __init arch_clk_init(void)
+{
+ int k, ret = 0;
+
+ if (test_mode_pin(MODE_PIN0)) {
+ if (test_mode_pin(MODE_PIN1))
+ pll1_div = 3;
+ else
+ pll1_div = 4;
+ } else
+ pll1_div = 1;
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7269.c b/arch/sh/kernel/cpu/sh2a/clock-sh7269.c
new file mode 100644
index 000000000000..6b787620de99
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7269.c
@@ -0,0 +1,184 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/clock-sh7269.c
+ *
+ * SH7269 clock framework support
+ *
+ * Copyright (C) 2012 Phil Edworthy
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <asm/clock.h>
+
+/* SH7269 registers */
+#define FRQCR 0xfffe0010
+#define STBCR3 0xfffe0408
+#define STBCR4 0xfffe040c
+#define STBCR5 0xfffe0410
+#define STBCR6 0xfffe0414
+#define STBCR7 0xfffe0418
+
+#define PLL_RATE 20
+
+/* Fixed 32 KHz root clock for RTC */
+static struct clk r_clk = {
+ .rate = 32768,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+ .rate = 13340000,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+ return clk->parent->rate * PLL_RATE;
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
+};
+
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .parent = &extal_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long peripheral0_recalc(struct clk *clk)
+{
+ return clk->parent->rate / 8;
+}
+
+static struct sh_clk_ops peripheral0_clk_ops = {
+ .recalc = peripheral0_recalc,
+};
+
+static struct clk peripheral0_clk = {
+ .ops = &peripheral0_clk_ops,
+ .parent = &pll_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long peripheral1_recalc(struct clk *clk)
+{
+ return clk->parent->rate / 4;
+}
+
+static struct sh_clk_ops peripheral1_clk_ops = {
+ .recalc = peripheral1_recalc,
+};
+
+static struct clk peripheral1_clk = {
+ .ops = &peripheral1_clk_ops,
+ .parent = &pll_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+struct clk *main_clks[] = {
+ &r_clk,
+ &extal_clk,
+ &pll_clk,
+ &peripheral0_clk,
+ &peripheral1_clk,
+};
+
+static int div2[] = { 1, 2, 0, 4 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = div2,
+ .nr_divisors = ARRAY_SIZE(div2),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I, DIV4_B,
+ DIV4_NR };
+
+#define DIV4(_reg, _bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
+
+/* The mask field specifies the div2 entries that are valid */
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_I] = DIV4(FRQCR, 8, 0xB, CLK_ENABLE_REG_16BIT
+ | CLK_ENABLE_ON_INIT),
+ [DIV4_B] = DIV4(FRQCR, 4, 0xA, CLK_ENABLE_REG_16BIT
+ | CLK_ENABLE_ON_INIT),
+};
+
+enum { MSTP72,
+ MSTP60,
+ MSTP47, MSTP46, MSTP45, MSTP44, MSTP43, MSTP42, MSTP41, MSTP40,
+ MSTP35, MSTP32, MSTP30,
+ MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ [MSTP72] = SH_CLK_MSTP8(&peripheral0_clk, STBCR7, 2, 0), /* CMT */
+ [MSTP60] = SH_CLK_MSTP8(&peripheral1_clk, STBCR6, 0, 0), /* USB */
+ [MSTP47] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 7, 0), /* SCIF0 */
+ [MSTP46] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 6, 0), /* SCIF1 */
+ [MSTP45] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 5, 0), /* SCIF2 */
+ [MSTP44] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 4, 0), /* SCIF3 */
+ [MSTP43] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 3, 0), /* SCIF4 */
+ [MSTP42] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 2, 0), /* SCIF5 */
+ [MSTP41] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 1, 0), /* SCIF6 */
+ [MSTP40] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 0, 0), /* SCIF7 */
+ [MSTP35] = SH_CLK_MSTP8(&peripheral0_clk, STBCR3, 5, 0), /* MTU2 */
+ [MSTP32] = SH_CLK_MSTP8(&peripheral1_clk, STBCR3, 2, 0), /* ADC */
+ [MSTP30] = SH_CLK_MSTP8(&r_clk, STBCR3, 0, 0), /* RTC */
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("rclk", &r_clk),
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+ CLKDEV_CON_ID("peripheral_clk", &peripheral1_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+ CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+
+ /* MSTP clocks */
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP47]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP46]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP45]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP44]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP43]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP42]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.6", &mstp_clks[MSTP41]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.7", &mstp_clks[MSTP40]),
+ CLKDEV_CON_ID("cmt_fck", &mstp_clks[MSTP72]),
+ CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]),
+ CLKDEV_CON_ID("mtu2_fck", &mstp_clks[MSTP35]),
+ CLKDEV_CON_ID("adc0", &mstp_clks[MSTP32]),
+ CLKDEV_CON_ID("rtc0", &mstp_clks[MSTP30]),
+};
+
+int __init arch_clk_init(void)
+{
+ int k, ret = 0;
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c b/arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c
new file mode 100644
index 000000000000..b055b55d6f27
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c
@@ -0,0 +1,2136 @@
+/*
+ * SH7264 Pinmux
+ *
+ * Copyright (C) 2012 Renesas Electronics Europe Ltd
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <cpu/sh7264.h>
+
+enum {
+ PINMUX_RESERVED = 0,
+
+ PINMUX_DATA_BEGIN,
+ /* Port A */
+ PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA,
+ /* Port B */
+ PB22_DATA, PB21_DATA, PB20_DATA,
+ PB19_DATA, PB18_DATA, PB17_DATA, PB16_DATA,
+ PB15_DATA, PB14_DATA, PB13_DATA, PB12_DATA,
+ PB11_DATA, PB10_DATA, PB9_DATA, PB8_DATA,
+ PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
+ PB3_DATA, PB2_DATA, PB1_DATA,
+ /* Port C */
+ PC10_DATA, PC9_DATA, PC8_DATA,
+ PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
+ PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA,
+ /* Port D */
+ PD15_DATA, PD14_DATA, PD13_DATA, PD12_DATA,
+ PD11_DATA, PD10_DATA, PD9_DATA, PD8_DATA,
+ PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
+ PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA,
+ /* Port E */
+ PE5_DATA, PE4_DATA,
+ PE3_DATA, PE2_DATA, PE1_DATA, PE0_DATA,
+ /* Port F */
+ PF12_DATA,
+ PF11_DATA, PF10_DATA, PF9_DATA, PF8_DATA,
+ PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
+ PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA,
+ /* Port G */
+ PG24_DATA,
+ PG23_DATA, PG22_DATA, PG21_DATA, PG20_DATA,
+ PG19_DATA, PG18_DATA, PG17_DATA, PG16_DATA,
+ PG15_DATA, PG14_DATA, PG13_DATA, PG12_DATA,
+ PG11_DATA, PG10_DATA, PG9_DATA, PG8_DATA,
+ PG7_DATA, PG6_DATA, PG5_DATA, PG4_DATA,
+ PG3_DATA, PG2_DATA, PG1_DATA, PG0_DATA,
+ /* Port H */
+ /* NOTE - Port H does not have a Data Register, but PH Data is
+ connected to PH Port Register */
+ PH7_DATA, PH6_DATA, PH5_DATA, PH4_DATA,
+ PH3_DATA, PH2_DATA, PH1_DATA, PH0_DATA,
+ /* Port I - not on device */
+ /* Port J */
+ PJ12_DATA,
+ PJ11_DATA, PJ10_DATA, PJ9_DATA, PJ8_DATA,
+ PJ7_DATA, PJ6_DATA, PJ5_DATA, PJ4_DATA,
+ PJ3_DATA, PJ2_DATA, PJ1_DATA, PJ0_DATA,
+ /* Port K */
+ PK12_DATA,
+ PK11_DATA, PK10_DATA, PK9_DATA, PK8_DATA,
+ PK7_DATA, PK6_DATA, PK5_DATA, PK4_DATA,
+ PK3_DATA, PK2_DATA, PK1_DATA, PK0_DATA,
+ PINMUX_DATA_END,
+
+ PINMUX_INPUT_BEGIN,
+ FORCE_IN,
+ /* Port A */
+ PA3_IN, PA2_IN, PA1_IN, PA0_IN,
+ /* Port B */
+ PB22_IN, PB21_IN, PB20_IN,
+ PB19_IN, PB18_IN, PB17_IN, PB16_IN,
+ PB15_IN, PB14_IN, PB13_IN, PB12_IN,
+ PB11_IN, PB10_IN, PB9_IN, PB8_IN,
+ PB7_IN, PB6_IN, PB5_IN, PB4_IN,
+ PB3_IN, PB2_IN, PB1_IN,
+ /* Port C */
+ PC10_IN, PC9_IN, PC8_IN,
+ PC7_IN, PC6_IN, PC5_IN, PC4_IN,
+ PC3_IN, PC2_IN, PC1_IN, PC0_IN,
+ /* Port D */
+ PD15_IN, PD14_IN, PD13_IN, PD12_IN,
+ PD11_IN, PD10_IN, PD9_IN, PD8_IN,
+ PD7_IN, PD6_IN, PD5_IN, PD4_IN,
+ PD3_IN, PD2_IN, PD1_IN, PD0_IN,
+ /* Port E */
+ PE5_IN, PE4_IN,
+ PE3_IN, PE2_IN, PE1_IN, PE0_IN,
+ /* Port F */
+ PF12_IN,
+ PF11_IN, PF10_IN, PF9_IN, PF8_IN,
+ PF7_IN, PF6_IN, PF5_IN, PF4_IN,
+ PF3_IN, PF2_IN, PF1_IN, PF0_IN,
+ /* Port G */
+ PG24_IN,
+ PG23_IN, PG22_IN, PG21_IN, PG20_IN,
+ PG19_IN, PG18_IN, PG17_IN, PG16_IN,
+ PG15_IN, PG14_IN, PG13_IN, PG12_IN,
+ PG11_IN, PG10_IN, PG9_IN, PG8_IN,
+ PG7_IN, PG6_IN, PG5_IN, PG4_IN,
+ PG3_IN, PG2_IN, PG1_IN, PG0_IN,
+ /* Port H - Port H does not have a Data Register */
+ /* Port I - not on device */
+ /* Port J */
+ PJ12_IN,
+ PJ11_IN, PJ10_IN, PJ9_IN, PJ8_IN,
+ PJ7_IN, PJ6_IN, PJ5_IN, PJ4_IN,
+ PJ3_IN, PJ2_IN, PJ1_IN, PJ0_IN,
+ /* Port K */
+ PK12_IN,
+ PK11_IN, PK10_IN, PK9_IN, PK8_IN,
+ PK7_IN, PK6_IN, PK5_IN, PK4_IN,
+ PK3_IN, PK2_IN, PK1_IN, PK0_IN,
+ PINMUX_INPUT_END,
+
+ PINMUX_OUTPUT_BEGIN,
+ FORCE_OUT,
+ /* Port A */
+ PA3_OUT, PA2_OUT, PA1_OUT, PA0_OUT,
+ /* Port B */
+ PB22_OUT, PB21_OUT, PB20_OUT,
+ PB19_OUT, PB18_OUT, PB17_OUT, PB16_OUT,
+ PB15_OUT, PB14_OUT, PB13_OUT, PB12_OUT,
+ PB11_OUT, PB10_OUT, PB9_OUT, PB8_OUT,
+ PB7_OUT, PB6_OUT, PB5_OUT, PB4_OUT,
+ PB3_OUT, PB2_OUT, PB1_OUT,
+ /* Port C */
+ PC10_OUT, PC9_OUT, PC8_OUT,
+ PC7_OUT, PC6_OUT, PC5_OUT, PC4_OUT,
+ PC3_OUT, PC2_OUT, PC1_OUT, PC0_OUT,
+ /* Port D */
+ PD15_OUT, PD14_OUT, PD13_OUT, PD12_OUT,
+ PD11_OUT, PD10_OUT, PD9_OUT, PD8_OUT,
+ PD7_OUT, PD6_OUT, PD5_OUT, PD4_OUT,
+ PD3_OUT, PD2_OUT, PD1_OUT, PD0_OUT,
+ /* Port E */
+ PE5_OUT, PE4_OUT,
+ PE3_OUT, PE2_OUT, PE1_OUT, PE0_OUT,
+ /* Port F */
+ PF12_OUT,
+ PF11_OUT, PF10_OUT, PF9_OUT, PF8_OUT,
+ PF7_OUT, PF6_OUT, PF5_OUT, PF4_OUT,
+ PF3_OUT, PF2_OUT, PF1_OUT, PF0_OUT,
+ /* Port G */
+ PG24_OUT,
+ PG23_OUT, PG22_OUT, PG21_OUT, PG20_OUT,
+ PG19_OUT, PG18_OUT, PG17_OUT, PG16_OUT,
+ PG15_OUT, PG14_OUT, PG13_OUT, PG12_OUT,
+ PG11_OUT, PG10_OUT, PG9_OUT, PG8_OUT,
+ PG7_OUT, PG6_OUT, PG5_OUT, PG4_OUT,
+ PG3_OUT, PG2_OUT, PG1_OUT, PG0_OUT,
+ /* Port H - Port H does not have a Data Register */
+ /* Port I - not on device */
+ /* Port J */
+ PJ12_OUT,
+ PJ11_OUT, PJ10_OUT, PJ9_OUT, PJ8_OUT,
+ PJ7_OUT, PJ6_OUT, PJ5_OUT, PJ4_OUT,
+ PJ3_OUT, PJ2_OUT, PJ1_OUT, PJ0_OUT,
+ /* Port K */
+ PK12_OUT,
+ PK11_OUT, PK10_OUT, PK9_OUT, PK8_OUT,
+ PK7_OUT, PK6_OUT, PK5_OUT, PK4_OUT,
+ PK3_OUT, PK2_OUT, PK1_OUT, PK0_OUT,
+ PINMUX_OUTPUT_END,
+
+ PINMUX_FUNCTION_BEGIN,
+ /* Port A */
+ PA3_IOR_IN, PA3_IOR_OUT,
+ PA2_IOR_IN, PA2_IOR_OUT,
+ PA1_IOR_IN, PA1_IOR_OUT,
+ PA0_IOR_IN, PA0_IOR_OUT,
+
+ /* Port B */
+ PB11_IOR_IN, PB11_IOR_OUT,
+ PB10_IOR_IN, PB10_IOR_OUT,
+ PB9_IOR_IN, PB9_IOR_OUT,
+ PB8_IOR_IN, PB8_IOR_OUT,
+
+ PB22MD_00, PB22MD_01, PB22MD_10,
+ PB21MD_0, PB21MD_1,
+ PB20MD_0, PB20MD_1,
+ PB19MD_00, PB19MD_01, PB19MD_10, PB19MD_11,
+ PB18MD_00, PB18MD_01, PB18MD_10, PB18MD_11,
+ PB17MD_00, PB17MD_01, PB17MD_10, PB17MD_11,
+ PB16MD_00, PB16MD_01, PB16MD_10, PB16MD_11,
+ PB15MD_00, PB15MD_01, PB15MD_10, PB15MD_11,
+ PB14MD_00, PB14MD_01, PB14MD_10, PB14MD_11,
+ PB13MD_00, PB13MD_01, PB13MD_10, PB13MD_11,
+ PB12MD_00, PB12MD_01, PB12MD_10, PB12MD_11,
+ PB11MD_00, PB11MD_01, PB11MD_10, PB11MD_11,
+ PB10MD_00, PB10MD_01, PB10MD_10, PB10MD_11,
+ PB9MD_00, PB9MD_01, PB9MD_10, PB9MD_11,
+ PB8MD_00, PB8MD_01, PB8MD_10, PB8MD_11,
+ PB7MD_00, PB7MD_01, PB7MD_10, PB7MD_11,
+ PB6MD_00, PB6MD_01, PB6MD_10, PB6MD_11,
+ PB5MD_00, PB5MD_01, PB5MD_10, PB5MD_11,
+ PB4MD_00, PB4MD_01, PB4MD_10, PB4MD_11,
+ PB3MD_0, PB3MD_1,
+ PB2MD_0, PB2MD_1,
+ PB1MD_0, PB1MD_1,
+
+ /* Port C */
+ PC14_IOR_IN, PC14_IOR_OUT,
+ PC13_IOR_IN, PC13_IOR_OUT,
+ PC12_IOR_IN, PC12_IOR_OUT,
+ PC11_IOR_IN, PC11_IOR_OUT,
+ PC10_IOR_IN, PC10_IOR_OUT,
+ PC9_IOR_IN, PC9_IOR_OUT,
+ PC8_IOR_IN, PC8_IOR_OUT,
+ PC7_IOR_IN, PC7_IOR_OUT,
+ PC6_IOR_IN, PC6_IOR_OUT,
+ PC5_IOR_IN, PC5_IOR_OUT,
+ PC4_IOR_IN, PC4_IOR_OUT,
+ PC3_IOR_IN, PC3_IOR_OUT,
+ PC2_IOR_IN, PC2_IOR_OUT,
+ PC1_IOR_IN, PC1_IOR_OUT,
+ PC0_IOR_IN, PC0_IOR_OUT,
+
+ PC10MD_0, PC10MD_1,
+ PC9MD_0, PC9MD_1,
+ PC8MD_00, PC8MD_01, PC8MD_10, PC8MD_11,
+ PC7MD_00, PC7MD_01, PC7MD_10, PC7MD_11,
+ PC6MD_00, PC6MD_01, PC6MD_10, PC6MD_11,
+ PC5MD_00, PC5MD_01, PC5MD_10, PC5MD_11,
+ PC4MD_0, PC4MD_1,
+ PC3MD_0, PC3MD_1,
+ PC2MD_0, PC2MD_1,
+ PC1MD_0, PC1MD_1,
+ PC0MD_0, PC0MD_1,
+
+ /* Port D */
+ PD15_IOR_IN, PD15_IOR_OUT,
+ PD14_IOR_IN, PD14_IOR_OUT,
+ PD13_IOR_IN, PD13_IOR_OUT,
+ PD12_IOR_IN, PD12_IOR_OUT,
+ PD11_IOR_IN, PD11_IOR_OUT,
+ PD10_IOR_IN, PD10_IOR_OUT,
+ PD9_IOR_IN, PD9_IOR_OUT,
+ PD8_IOR_IN, PD8_IOR_OUT,
+ PD7_IOR_IN, PD7_IOR_OUT,
+ PD6_IOR_IN, PD6_IOR_OUT,
+ PD5_IOR_IN, PD5_IOR_OUT,
+ PD4_IOR_IN, PD4_IOR_OUT,
+ PD3_IOR_IN, PD3_IOR_OUT,
+ PD2_IOR_IN, PD2_IOR_OUT,
+ PD1_IOR_IN, PD1_IOR_OUT,
+ PD0_IOR_IN, PD0_IOR_OUT,
+
+ PD15MD_00, PD15MD_01, PD15MD_10, PD15MD_11,
+ PD14MD_00, PD14MD_01, PD14MD_10, PD14MD_11,
+ PD13MD_00, PD13MD_01, PD13MD_10, PD13MD_11,
+ PD12MD_00, PD12MD_01, PD12MD_10, PD12MD_11,
+ PD11MD_00, PD11MD_01, PD11MD_10, PD11MD_11,
+ PD10MD_00, PD10MD_01, PD10MD_10, PD10MD_11,
+ PD9MD_00, PD9MD_01, PD9MD_10, PD9MD_11,
+ PD8MD_00, PD8MD_01, PD8MD_10, PD8MD_11,
+ PD7MD_00, PD7MD_01, PD7MD_10, PD7MD_11,
+ PD6MD_00, PD6MD_01, PD6MD_10, PD6MD_11,
+ PD5MD_00, PD5MD_01, PD5MD_10, PD5MD_11,
+ PD4MD_00, PD4MD_01, PD4MD_10, PD4MD_11,
+ PD3MD_00, PD3MD_01, PD3MD_10, PD3MD_11,
+ PD2MD_00, PD2MD_01, PD2MD_10, PD2MD_11,
+ PD1MD_00, PD1MD_01, PD1MD_10, PD1MD_11,
+ PD0MD_00, PD0MD_01, PD0MD_10, PD0MD_11,
+
+ /* Port E */
+ PE5_IOR_IN, PE5_IOR_OUT,
+ PE4_IOR_IN, PE4_IOR_OUT,
+ PE3_IOR_IN, PE3_IOR_OUT,
+ PE2_IOR_IN, PE2_IOR_OUT,
+ PE1_IOR_IN, PE1_IOR_OUT,
+ PE0_IOR_IN, PE0_IOR_OUT,
+
+ PE5MD_00, PE5MD_01, PE5MD_10, PE5MD_11,
+ PE4MD_00, PE4MD_01, PE4MD_10, PE4MD_11,
+ PE3MD_00, PE3MD_01, PE3MD_10, PE3MD_11,
+ PE2MD_00, PE2MD_01, PE2MD_10, PE2MD_11,
+ PE1MD_000, PE1MD_001, PE1MD_010, PE1MD_011,
+ PE1MD_100, PE1MD_101, PE1MD_110, PE1MD_111,
+ PE0MD_00, PE0MD_01, PE0MD_10, PE0MD_11,
+
+ /* Port F */
+ PF12_IOR_IN, PF12_IOR_OUT,
+ PF11_IOR_IN, PF11_IOR_OUT,
+ PF10_IOR_IN, PF10_IOR_OUT,
+ PF9_IOR_IN, PF9_IOR_OUT,
+ PF8_IOR_IN, PF8_IOR_OUT,
+ PF7_IOR_IN, PF7_IOR_OUT,
+ PF6_IOR_IN, PF6_IOR_OUT,
+ PF5_IOR_IN, PF5_IOR_OUT,
+ PF4_IOR_IN, PF4_IOR_OUT,
+ PF3_IOR_IN, PF3_IOR_OUT,
+ PF2_IOR_IN, PF2_IOR_OUT,
+ PF1_IOR_IN, PF1_IOR_OUT,
+ PF0_IOR_IN, PF0_IOR_OUT,
+
+ PF12MD_000, PF12MD_001, PF12MD_010, PF12MD_011,
+ PF12MD_100, PF12MD_101, PF12MD_110, PF12MD_111,
+ PF11MD_000, PF11MD_001, PF11MD_010, PF11MD_011,
+ PF11MD_100, PF11MD_101, PF11MD_110, PF11MD_111,
+ PF10MD_000, PF10MD_001, PF10MD_010, PF10MD_011,
+ PF10MD_100, PF10MD_101, PF10MD_110, PF10MD_111,
+ PF9MD_000, PF9MD_001, PF9MD_010, PF9MD_011,
+ PF9MD_100, PF9MD_101, PF9MD_110, PF9MD_111,
+ PF8MD_00, PF8MD_01, PF8MD_10, PF8MD_11,
+ PF7MD_000, PF7MD_001, PF7MD_010, PF7MD_011,
+ PF7MD_100, PF7MD_101, PF7MD_110, PF7MD_111,
+ PF6MD_000, PF6MD_001, PF6MD_010, PF6MD_011,
+ PF6MD_100, PF6MD_101, PF6MD_110, PF6MD_111,
+ PF5MD_000, PF5MD_001, PF5MD_010, PF5MD_011,
+ PF5MD_100, PF5MD_101, PF5MD_110, PF5MD_111,
+ PF4MD_000, PF4MD_001, PF4MD_010, PF4MD_011,
+ PF4MD_100, PF4MD_101, PF4MD_110, PF4MD_111,
+ PF3MD_000, PF3MD_001, PF3MD_010, PF3MD_011,
+ PF3MD_100, PF3MD_101, PF3MD_110, PF3MD_111,
+ PF2MD_000, PF2MD_001, PF2MD_010, PF2MD_011,
+ PF2MD_100, PF2MD_101, PF2MD_110, PF2MD_111,
+ PF1MD_000, PF1MD_001, PF1MD_010, PF1MD_011,
+ PF1MD_100, PF1MD_101, PF1MD_110, PF1MD_111,
+ PF0MD_000, PF0MD_001, PF0MD_010, PF0MD_011,
+ PF0MD_100, PF0MD_101, PF0MD_110, PF0MD_111,
+
+ /* Port G */
+ PG24_IOR_IN, PG24_IOR_OUT,
+ PG23_IOR_IN, PG23_IOR_OUT,
+ PG22_IOR_IN, PG22_IOR_OUT,
+ PG21_IOR_IN, PG21_IOR_OUT,
+ PG20_IOR_IN, PG20_IOR_OUT,
+ PG19_IOR_IN, PG19_IOR_OUT,
+ PG18_IOR_IN, PG18_IOR_OUT,
+ PG17_IOR_IN, PG17_IOR_OUT,
+ PG16_IOR_IN, PG16_IOR_OUT,
+ PG15_IOR_IN, PG15_IOR_OUT,
+ PG14_IOR_IN, PG14_IOR_OUT,
+ PG13_IOR_IN, PG13_IOR_OUT,
+ PG12_IOR_IN, PG12_IOR_OUT,
+ PG11_IOR_IN, PG11_IOR_OUT,
+ PG10_IOR_IN, PG10_IOR_OUT,
+ PG9_IOR_IN, PG9_IOR_OUT,
+ PG8_IOR_IN, PG8_IOR_OUT,
+ PG7_IOR_IN, PG7_IOR_OUT,
+ PG6_IOR_IN, PG6_IOR_OUT,
+ PG5_IOR_IN, PG5_IOR_OUT,
+ PG4_IOR_IN, PG4_IOR_OUT,
+ PG3_IOR_IN, PG3_IOR_OUT,
+ PG2_IOR_IN, PG2_IOR_OUT,
+ PG1_IOR_IN, PG1_IOR_OUT,
+ PG0_IOR_IN, PG0_IOR_OUT,
+
+ PG24MD_00, PG24MD_01, PG24MD_10, PG24MD_11,
+ PG23MD_00, PG23MD_01, PG23MD_10, PG23MD_11,
+ PG22MD_00, PG22MD_01, PG22MD_10, PG22MD_11,
+ PG21MD_00, PG21MD_01, PG21MD_10, PG21MD_11,
+ PG20MD_000, PG20MD_001, PG20MD_010, PG20MD_011,
+ PG20MD_100, PG20MD_101, PG20MD_110, PG20MD_111,
+ PG19MD_000, PG19MD_001, PG19MD_010, PG19MD_011,
+ PG19MD_100, PG19MD_101, PG19MD_110, PG19MD_111,
+ PG18MD_000, PG18MD_001, PG18MD_010, PG18MD_011,
+ PG18MD_100, PG18MD_101, PG18MD_110, PG18MD_111,
+ PG17MD_000, PG17MD_001, PG17MD_010, PG17MD_011,
+ PG17MD_100, PG17MD_101, PG17MD_110, PG17MD_111,
+ PG16MD_000, PG16MD_001, PG16MD_010, PG16MD_011,
+ PG16MD_100, PG16MD_101, PG16MD_110, PG16MD_111,
+ PG15MD_000, PG15MD_001, PG15MD_010, PG15MD_011,
+ PG15MD_100, PG15MD_101, PG15MD_110, PG15MD_111,
+ PG14MD_000, PG14MD_001, PG14MD_010, PG14MD_011,
+ PG14MD_100, PG14MD_101, PG14MD_110, PG14MD_111,
+ PG13MD_000, PG13MD_001, PG13MD_010, PG13MD_011,
+ PG13MD_100, PG13MD_101, PG13MD_110, PG13MD_111,
+ PG12MD_000, PG12MD_001, PG12MD_010, PG12MD_011,
+ PG12MD_100, PG12MD_101, PG12MD_110, PG12MD_111,
+ PG11MD_000, PG11MD_001, PG11MD_010, PG11MD_011,
+ PG11MD_100, PG11MD_101, PG11MD_110, PG11MD_111,
+ PG10MD_000, PG10MD_001, PG10MD_010, PG10MD_011,
+ PG10MD_100, PG10MD_101, PG10MD_110, PG10MD_111,
+ PG9MD_000, PG9MD_001, PG9MD_010, PG9MD_011,
+ PG9MD_100, PG9MD_101, PG9MD_110, PG9MD_111,
+ PG8MD_000, PG8MD_001, PG8MD_010, PG8MD_011,
+ PG8MD_100, PG8MD_101, PG8MD_110, PG8MD_111,
+ PG7MD_00, PG7MD_01, PG7MD_10, PG7MD_11,
+ PG6MD_00, PG6MD_01, PG6MD_10, PG6MD_11,
+ PG5MD_00, PG5MD_01, PG5MD_10, PG5MD_11,
+ PG4MD_00, PG4MD_01, PG4MD_10, PG4MD_11,
+ PG3MD_00, PG3MD_01, PG3MD_10, PG3MD_11,
+ PG2MD_00, PG2MD_01, PG2MD_10, PG2MD_11,
+ PG1MD_00, PG1MD_01, PG1MD_10, PG1MD_11,
+ PG0MD_000, PG0MD_001, PG0MD_010, PG0MD_011,
+ PG0MD_100, PG0MD_101, PG0MD_110, PG0MD_111,
+
+ /* Port H */
+ PH7MD_0, PH7MD_1,
+ PH6MD_0, PH6MD_1,
+ PH5MD_0, PH5MD_1,
+ PH4MD_0, PH4MD_1,
+ PH3MD_0, PH3MD_1,
+ PH2MD_0, PH2MD_1,
+ PH1MD_0, PH1MD_1,
+ PH0MD_0, PH0MD_1,
+
+ /* Port I - not on device */
+
+ /* Port J */
+ PJ11_IOR_IN, PJ11_IOR_OUT,
+ PJ10_IOR_IN, PJ10_IOR_OUT,
+ PJ9_IOR_IN, PJ9_IOR_OUT,
+ PJ8_IOR_IN, PJ8_IOR_OUT,
+ PJ7_IOR_IN, PJ7_IOR_OUT,
+ PJ6_IOR_IN, PJ6_IOR_OUT,
+ PJ5_IOR_IN, PJ5_IOR_OUT,
+ PJ4_IOR_IN, PJ4_IOR_OUT,
+ PJ3_IOR_IN, PJ3_IOR_OUT,
+ PJ2_IOR_IN, PJ2_IOR_OUT,
+ PJ1_IOR_IN, PJ1_IOR_OUT,
+ PJ0_IOR_IN, PJ0_IOR_OUT,
+
+ PJ11MD_00, PJ11MD_01, PJ11MD_10, PJ11MD_11,
+ PJ10MD_00, PJ10MD_01, PJ10MD_10, PJ10MD_11,
+ PJ9MD_00, PJ9MD_01, PJ9MD_10, PJ9MD_11,
+ PJ8MD_00, PJ8MD_01, PJ8MD_10, PJ8MD_11,
+ PJ7MD_00, PJ7MD_01, PJ7MD_10, PJ7MD_11,
+ PJ6MD_00, PJ6MD_01, PJ6MD_10, PJ6MD_11,
+ PJ5MD_00, PJ5MD_01, PJ5MD_10, PJ5MD_11,
+ PJ4MD_00, PJ4MD_01, PJ4MD_10, PJ4MD_11,
+ PJ3MD_00, PJ3MD_01, PJ3MD_10, PJ3MD_11,
+ PJ2MD_000, PJ2MD_001, PJ2MD_010, PJ2MD_011,
+ PJ2MD_100, PJ2MD_101, PJ2MD_110, PJ2MD_111,
+ PJ1MD_000, PJ1MD_001, PJ1MD_010, PJ1MD_011,
+ PJ1MD_100, PJ1MD_101, PJ1MD_110, PJ1MD_111,
+ PJ0MD_000, PJ0MD_001, PJ0MD_010, PJ0MD_011,
+ PJ0MD_100, PJ0MD_101, PJ0MD_110, PJ0MD_111,
+
+ /* Port K */
+ PK11_IOR_IN, PK11_IOR_OUT,
+ PK10_IOR_IN, PK10_IOR_OUT,
+ PK9_IOR_IN, PK9_IOR_OUT,
+ PK8_IOR_IN, PK8_IOR_OUT,
+ PK7_IOR_IN, PK7_IOR_OUT,
+ PK6_IOR_IN, PK6_IOR_OUT,
+ PK5_IOR_IN, PK5_IOR_OUT,
+ PK4_IOR_IN, PK4_IOR_OUT,
+ PK3_IOR_IN, PK3_IOR_OUT,
+ PK2_IOR_IN, PK2_IOR_OUT,
+ PK1_IOR_IN, PK1_IOR_OUT,
+ PK0_IOR_IN, PK0_IOR_OUT,
+
+ PK11MD_00, PK11MD_01, PK11MD_10, PK11MD_11,
+ PK10MD_00, PK10MD_01, PK10MD_10, PK10MD_11,
+ PK9MD_00, PK9MD_01, PK9MD_10, PK9MD_11,
+ PK8MD_00, PK8MD_01, PK8MD_10, PK8MD_11,
+ PK7MD_00, PK7MD_01, PK7MD_10, PK7MD_11,
+ PK6MD_00, PK6MD_01, PK6MD_10, PK6MD_11,
+ PK5MD_00, PK5MD_01, PK5MD_10, PK5MD_11,
+ PK4MD_00, PK4MD_01, PK4MD_10, PK4MD_11,
+ PK3MD_00, PK3MD_01, PK3MD_10, PK3MD_11,
+ PK2MD_00, PK2MD_01, PK2MD_10, PK2MD_11,
+ PK1MD_00, PK1MD_01, PK1MD_10, PK1MD_11,
+ PK0MD_00, PK0MD_01, PK0MD_10, PK0MD_11,
+ PINMUX_FUNCTION_END,
+
+ PINMUX_MARK_BEGIN,
+ /* Port A */
+
+ /* Port B */
+
+ /* Port C */
+
+ /* Port D */
+
+ /* Port E */
+
+ /* Port F */
+
+ /* Port G */
+
+ /* Port H */
+ PHAN7_MARK, PHAN6_MARK, PHAN5_MARK, PHAN4_MARK,
+ PHAN3_MARK, PHAN2_MARK, PHAN1_MARK, PHAN0_MARK,
+
+ /* Port I - not on device */
+
+ /* Port J */
+
+ /* Port K */
+
+ IRQ7_PC_MARK, IRQ6_PC_MARK, IRQ5_PC_MARK, IRQ4_PC_MARK,
+ IRQ3_PG_MARK, IRQ2_PG_MARK, IRQ1_PJ_MARK, IRQ0_PJ_MARK,
+ IRQ3_PE_MARK, IRQ2_PE_MARK, IRQ1_PE_MARK, IRQ0_PE_MARK,
+
+ PINT7_PG_MARK, PINT6_PG_MARK, PINT5_PG_MARK, PINT4_PG_MARK,
+ PINT3_PG_MARK, PINT2_PG_MARK, PINT1_PG_MARK, PINT0_PG_MARK,
+
+ SD_CD_MARK, SD_D0_MARK, SD_D1_MARK, SD_D2_MARK, SD_D3_MARK,
+ SD_WP_MARK, SD_CLK_MARK, SD_CMD_MARK,
+ CRX0_MARK, CRX1_MARK,
+ CTX0_MARK, CTX1_MARK,
+
+ PWM1A_MARK, PWM1B_MARK, PWM1C_MARK, PWM1D_MARK,
+ PWM1E_MARK, PWM1F_MARK, PWM1G_MARK, PWM1H_MARK,
+ PWM2A_MARK, PWM2B_MARK, PWM2C_MARK, PWM2D_MARK,
+ PWM2E_MARK, PWM2F_MARK, PWM2G_MARK, PWM2H_MARK,
+ IERXD_MARK, IETXD_MARK,
+ CRX0CRX1_MARK,
+ WDTOVF_MARK,
+
+ CRX0X1_MARK,
+
+ /* DMAC */
+ TEND0_MARK, DACK0_MARK, DREQ0_MARK,
+ TEND1_MARK, DACK1_MARK, DREQ1_MARK,
+
+ /* ADC */
+ ADTRG_MARK,
+
+ /* BSC */
+ A25_MARK, A24_MARK,
+ A23_MARK, A22_MARK, A21_MARK, A20_MARK,
+ A19_MARK, A18_MARK, A17_MARK, A16_MARK,
+ A15_MARK, A14_MARK, A13_MARK, A12_MARK,
+ A11_MARK, A10_MARK, A9_MARK, A8_MARK,
+ A7_MARK, A6_MARK, A5_MARK, A4_MARK,
+ A3_MARK, A2_MARK, A1_MARK, A0_MARK,
+ D15_MARK, D14_MARK, D13_MARK, D12_MARK,
+ D11_MARK, D10_MARK, D9_MARK, D8_MARK,
+ D7_MARK, D6_MARK, D5_MARK, D4_MARK,
+ D3_MARK, D2_MARK, D1_MARK, D0_MARK,
+ BS_MARK,
+ CS4_MARK, CS3_MARK, CS2_MARK, CS1_MARK, CS0_MARK,
+ CS6CE1B_MARK, CS5CE1A_MARK,
+ CE2A_MARK, CE2B_MARK,
+ RD_MARK, RDWR_MARK,
+ ICIOWRAH_MARK,
+ ICIORD_MARK,
+ WE1DQMUWE_MARK,
+ WE0DQML_MARK,
+ RAS_MARK, CAS_MARK, CKE_MARK,
+ WAIT_MARK, BREQ_MARK, BACK_MARK, IOIS16_MARK,
+
+ /* TMU */
+ TIOC0A_MARK, TIOC0B_MARK, TIOC0C_MARK, TIOC0D_MARK,
+ TIOC1A_MARK, TIOC1B_MARK,
+ TIOC2A_MARK, TIOC2B_MARK,
+ TIOC3A_MARK, TIOC3B_MARK, TIOC3C_MARK, TIOC3D_MARK,
+ TIOC4A_MARK, TIOC4B_MARK, TIOC4C_MARK, TIOC4D_MARK,
+ TCLKA_MARK, TCLKB_MARK, TCLKC_MARK, TCLKD_MARK,
+
+ /* SCIF */
+ SCK0_MARK, SCK1_MARK, SCK2_MARK, SCK3_MARK,
+ RXD0_MARK, RXD1_MARK, RXD2_MARK, RXD3_MARK,
+ TXD0_MARK, TXD1_MARK, TXD2_MARK, TXD3_MARK,
+ RXD4_MARK, RXD5_MARK, RXD6_MARK, RXD7_MARK,
+ TXD4_MARK, TXD5_MARK, TXD6_MARK, TXD7_MARK,
+ RTS1_MARK, RTS3_MARK,
+ CTS1_MARK, CTS3_MARK,
+
+ /* RSPI */
+ RSPCK0_MARK, RSPCK1_MARK,
+ MOSI0_MARK, MOSI1_MARK,
+ MISO0_PF12_MARK, MISO1_MARK, MISO1_PG19_MARK,
+ SSL00_MARK, SSL10_MARK,
+
+ /* IIC3 */
+ SCL0_MARK, SCL1_MARK, SCL2_MARK,
+ SDA0_MARK, SDA1_MARK, SDA2_MARK,
+
+ /* SSI */
+ SSISCK0_MARK,
+ SSIWS0_MARK,
+ SSITXD0_MARK,
+ SSIRXD0_MARK,
+ SSIWS1_MARK, SSIWS2_MARK, SSIWS3_MARK,
+ SSISCK1_MARK, SSISCK2_MARK, SSISCK3_MARK,
+ SSIDATA1_MARK, SSIDATA2_MARK, SSIDATA3_MARK,
+ AUDIO_CLK_MARK,
+
+ /* SIOF */ /* NOTE Shares AUDIO_CLK with SSI */
+ SIOFTXD_MARK, SIOFRXD_MARK, SIOFSYNC_MARK, SIOFSCK_MARK,
+
+ /* SPDIF */ /* NOTE Shares AUDIO_CLK with SSI */
+ SPDIF_IN_MARK, SPDIF_OUT_MARK,
+
+ /* NANDFMC */ /* NOTE Controller is not available in boot mode 0 */
+ FCE_MARK,
+ FRB_MARK,
+
+ /* VDC3 */
+ DV_CLK_MARK,
+ DV_VSYNC_MARK, DV_HSYNC_MARK,
+ DV_DATA7_MARK, DV_DATA6_MARK, DV_DATA5_MARK, DV_DATA4_MARK,
+ DV_DATA3_MARK, DV_DATA2_MARK, DV_DATA1_MARK, DV_DATA0_MARK,
+ LCD_CLK_MARK, LCD_EXTCLK_MARK,
+ LCD_VSYNC_MARK, LCD_HSYNC_MARK, LCD_DE_MARK,
+ LCD_DATA15_MARK, LCD_DATA14_MARK, LCD_DATA13_MARK, LCD_DATA12_MARK,
+ LCD_DATA11_MARK, LCD_DATA10_MARK, LCD_DATA9_MARK, LCD_DATA8_MARK,
+ LCD_DATA7_MARK, LCD_DATA6_MARK, LCD_DATA5_MARK, LCD_DATA4_MARK,
+ LCD_DATA3_MARK, LCD_DATA2_MARK, LCD_DATA1_MARK, LCD_DATA0_MARK,
+ LCD_M_DISP_MARK,
+ PINMUX_MARK_END,
+};
+
+static pinmux_enum_t pinmux_data[] = {
+
+ /* Port A */
+ PINMUX_DATA(PA3_DATA, PA3_IN),
+ PINMUX_DATA(PA2_DATA, PA2_IN),
+ PINMUX_DATA(PA1_DATA, PA1_IN),
+ PINMUX_DATA(PA0_DATA, PA0_IN),
+
+ /* Port B */
+ PINMUX_DATA(PB22_DATA, PB22MD_00, PB22_IN, PB22_OUT),
+ PINMUX_DATA(A22_MARK, PB22MD_01),
+ PINMUX_DATA(CS4_MARK, PB22MD_10),
+
+ PINMUX_DATA(PB21_DATA, PB21MD_0, PB21_IN, PB21_OUT),
+ PINMUX_DATA(A21_MARK, PB21MD_1),
+ PINMUX_DATA(A20_MARK, PB20MD_1),
+ PINMUX_DATA(A19_MARK, PB19MD_01),
+ PINMUX_DATA(A18_MARK, PB18MD_01),
+ PINMUX_DATA(A17_MARK, PB17MD_01),
+ PINMUX_DATA(A16_MARK, PB16MD_01),
+ PINMUX_DATA(A15_MARK, PB15MD_01),
+ PINMUX_DATA(A14_MARK, PB14MD_01),
+ PINMUX_DATA(A13_MARK, PB13MD_01),
+ PINMUX_DATA(A12_MARK, PB12MD_01),
+ PINMUX_DATA(A11_MARK, PB11MD_01),
+ PINMUX_DATA(A10_MARK, PB10MD_01),
+ PINMUX_DATA(A9_MARK, PB9MD_01),
+ PINMUX_DATA(A8_MARK, PB8MD_01),
+ PINMUX_DATA(A7_MARK, PB7MD_01),
+ PINMUX_DATA(A6_MARK, PB6MD_01),
+ PINMUX_DATA(A5_MARK, PB5MD_01),
+ PINMUX_DATA(A4_MARK, PB4MD_01),
+ PINMUX_DATA(A3_MARK, PB3MD_1),
+ PINMUX_DATA(A2_MARK, PB2MD_1),
+ PINMUX_DATA(A1_MARK, PB1MD_1),
+
+ /* Port C */
+ PINMUX_DATA(PC10_DATA, PC10MD_0),
+ PINMUX_DATA(TIOC2B_MARK, PC1MD_1),
+ PINMUX_DATA(PC9_DATA, PC9MD_0),
+ PINMUX_DATA(TIOC2A_MARK, PC9MD_1),
+ PINMUX_DATA(PC8_DATA, PC8MD_00),
+ PINMUX_DATA(CS3_MARK, PC8MD_01),
+ PINMUX_DATA(TIOC4D_MARK, PC8MD_10),
+ PINMUX_DATA(IRQ7_PC_MARK, PC8MD_11),
+ PINMUX_DATA(PC7_DATA, PC7MD_00),
+ PINMUX_DATA(CKE_MARK, PC7MD_01),
+ PINMUX_DATA(TIOC4C_MARK, PC7MD_10),
+ PINMUX_DATA(IRQ6_PC_MARK, PC7MD_11),
+ PINMUX_DATA(PC6_DATA, PC6MD_00),
+ PINMUX_DATA(CAS_MARK, PC6MD_01),
+ PINMUX_DATA(TIOC4B_MARK, PC6MD_10),
+ PINMUX_DATA(IRQ5_PC_MARK, PC6MD_11),
+ PINMUX_DATA(PC5_DATA, PC5MD_00),
+ PINMUX_DATA(RAS_MARK, PC5MD_01),
+ PINMUX_DATA(TIOC4A_MARK, PC5MD_10),
+ PINMUX_DATA(IRQ4_PC_MARK, PC5MD_11),
+ PINMUX_DATA(PC4_DATA, PC4MD_0),
+ PINMUX_DATA(WE1DQMUWE_MARK, PC4MD_1),
+ PINMUX_DATA(PC3_DATA, PC3MD_0),
+ PINMUX_DATA(WE0DQML_MARK, PC3MD_1),
+ PINMUX_DATA(PC2_DATA, PC2MD_0),
+ PINMUX_DATA(RDWR_MARK, PC2MD_1),
+ PINMUX_DATA(PC1_DATA, PC1MD_0),
+ PINMUX_DATA(RD_MARK, PC1MD_1),
+ PINMUX_DATA(PC0_DATA, PC0MD_0),
+ PINMUX_DATA(CS0_MARK, PC0MD_1),
+
+ /* Port D */
+ PINMUX_DATA(D15_MARK, PD15MD_01),
+ PINMUX_DATA(D14_MARK, PD14MD_01),
+ PINMUX_DATA(D13_MARK, PD13MD_01),
+ PINMUX_DATA(D12_MARK, PD12MD_01),
+ PINMUX_DATA(D11_MARK, PD11MD_01),
+ PINMUX_DATA(D10_MARK, PD10MD_01),
+ PINMUX_DATA(D9_MARK, PD9MD_01),
+ PINMUX_DATA(D8_MARK, PD8MD_01),
+ PINMUX_DATA(D7_MARK, PD7MD_01),
+ PINMUX_DATA(D6_MARK, PD6MD_01),
+ PINMUX_DATA(D5_MARK, PD5MD_01),
+ PINMUX_DATA(D4_MARK, PD4MD_01),
+ PINMUX_DATA(D3_MARK, PD3MD_01),
+ PINMUX_DATA(D2_MARK, PD2MD_01),
+ PINMUX_DATA(D1_MARK, PD1MD_01),
+ PINMUX_DATA(D0_MARK, PD0MD_01),
+
+ /* Port E */
+ PINMUX_DATA(PE5_DATA, PE5MD_00),
+ PINMUX_DATA(SDA2_MARK, PE5MD_01),
+ PINMUX_DATA(DV_HSYNC_MARK, PE5MD_11),
+
+ PINMUX_DATA(PE4_DATA, PE4MD_00),
+ PINMUX_DATA(SCL2_MARK, PE4MD_01),
+ PINMUX_DATA(DV_VSYNC_MARK, PE4MD_11),
+
+ PINMUX_DATA(PE3_DATA, PE3MD_00),
+ PINMUX_DATA(SDA1_MARK, PE3MD_01),
+ PINMUX_DATA(IRQ3_PE_MARK, PE3MD_11),
+
+ PINMUX_DATA(PE2_DATA, PE2MD_00),
+ PINMUX_DATA(SCL1_MARK, PE2MD_01),
+ PINMUX_DATA(IRQ2_PE_MARK, PE2MD_11),
+
+ PINMUX_DATA(PE1_DATA, PE1MD_000),
+ PINMUX_DATA(SDA0_MARK, PE1MD_001),
+ PINMUX_DATA(IOIS16_MARK, PE1MD_010),
+ PINMUX_DATA(IRQ1_PE_MARK, PE1MD_011),
+ PINMUX_DATA(TCLKA_MARK, PE1MD_100),
+ PINMUX_DATA(ADTRG_MARK, PE1MD_101),
+
+ PINMUX_DATA(PE0_DATA, PE0MD_00),
+ PINMUX_DATA(SCL0_MARK, PE0MD_01),
+ PINMUX_DATA(AUDIO_CLK_MARK, PE0MD_10),
+ PINMUX_DATA(IRQ0_PE_MARK, PE0MD_11),
+
+ /* Port F */
+ PINMUX_DATA(PF12_DATA, PF12MD_000),
+ PINMUX_DATA(BS_MARK, PF12MD_001),
+ PINMUX_DATA(MISO0_PF12_MARK, PF12MD_011),
+ PINMUX_DATA(TIOC3D_MARK, PF12MD_100),
+ PINMUX_DATA(SPDIF_OUT_MARK, PF12MD_101),
+
+ PINMUX_DATA(PF11_DATA, PF11MD_000),
+ PINMUX_DATA(A25_MARK, PF11MD_001),
+ PINMUX_DATA(SSIDATA3_MARK, PF11MD_010),
+ PINMUX_DATA(MOSI0_MARK, PF11MD_011),
+ PINMUX_DATA(TIOC3C_MARK, PF11MD_100),
+ PINMUX_DATA(SPDIF_IN_MARK, PF11MD_101),
+
+ PINMUX_DATA(PF10_DATA, PF10MD_000),
+ PINMUX_DATA(A24_MARK, PF10MD_001),
+ PINMUX_DATA(SSIWS3_MARK, PF10MD_010),
+ PINMUX_DATA(SSL00_MARK, PF10MD_011),
+ PINMUX_DATA(TIOC3B_MARK, PF10MD_100),
+ PINMUX_DATA(FCE_MARK, PF10MD_101),
+
+ PINMUX_DATA(PF9_DATA, PF9MD_000),
+ PINMUX_DATA(A23_MARK, PF9MD_001),
+ PINMUX_DATA(SSISCK3_MARK, PF9MD_010),
+ PINMUX_DATA(RSPCK0_MARK, PF9MD_011),
+ PINMUX_DATA(TIOC3A_MARK, PF9MD_100),
+ PINMUX_DATA(FRB_MARK, PF9MD_101),
+
+ PINMUX_DATA(PF8_DATA, PF8MD_00),
+ PINMUX_DATA(CE2B_MARK, PF8MD_01),
+ PINMUX_DATA(SSIDATA3_MARK, PF8MD_10),
+ PINMUX_DATA(DV_CLK_MARK, PF8MD_11),
+
+ PINMUX_DATA(PF7_DATA, PF7MD_000),
+ PINMUX_DATA(CE2A_MARK, PF7MD_001),
+ PINMUX_DATA(SSIWS3_MARK, PF7MD_010),
+ PINMUX_DATA(DV_DATA7_MARK, PF7MD_011),
+ PINMUX_DATA(TCLKD_MARK, PF7MD_100),
+
+ PINMUX_DATA(PF6_DATA, PF6MD_000),
+ PINMUX_DATA(CS6CE1B_MARK, PF6MD_001),
+ PINMUX_DATA(SSISCK3_MARK, PF6MD_010),
+ PINMUX_DATA(DV_DATA6_MARK, PF6MD_011),
+ PINMUX_DATA(TCLKB_MARK, PF6MD_100),
+
+ PINMUX_DATA(PF5_DATA, PF5MD_000),
+ PINMUX_DATA(CS5CE1A_MARK, PF5MD_001),
+ PINMUX_DATA(SSIDATA2_MARK, PF5MD_010),
+ PINMUX_DATA(DV_DATA5_MARK, PF5MD_011),
+ PINMUX_DATA(TCLKC_MARK, PF5MD_100),
+
+ PINMUX_DATA(PF4_DATA, PF4MD_000),
+ PINMUX_DATA(ICIOWRAH_MARK, PF4MD_001),
+ PINMUX_DATA(SSIWS2_MARK, PF4MD_010),
+ PINMUX_DATA(DV_DATA4_MARK, PF4MD_011),
+ PINMUX_DATA(TXD3_MARK, PF4MD_100),
+
+ PINMUX_DATA(PF3_DATA, PF3MD_000),
+ PINMUX_DATA(ICIORD_MARK, PF3MD_001),
+ PINMUX_DATA(SSISCK2_MARK, PF3MD_010),
+ PINMUX_DATA(DV_DATA3_MARK, PF3MD_011),
+ PINMUX_DATA(RXD3_MARK, PF3MD_100),
+
+ PINMUX_DATA(PF2_DATA, PF2MD_000),
+ PINMUX_DATA(BACK_MARK, PF2MD_001),
+ PINMUX_DATA(SSIDATA1_MARK, PF2MD_010),
+ PINMUX_DATA(DV_DATA2_MARK, PF2MD_011),
+ PINMUX_DATA(TXD2_MARK, PF2MD_100),
+ PINMUX_DATA(DACK0_MARK, PF2MD_101),
+
+ PINMUX_DATA(PF1_DATA, PF1MD_000),
+ PINMUX_DATA(BREQ_MARK, PF1MD_001),
+ PINMUX_DATA(SSIWS1_MARK, PF1MD_010),
+ PINMUX_DATA(DV_DATA1_MARK, PF1MD_011),
+ PINMUX_DATA(RXD2_MARK, PF1MD_100),
+ PINMUX_DATA(DREQ0_MARK, PF1MD_101),
+
+ PINMUX_DATA(PF0_DATA, PF0MD_000),
+ PINMUX_DATA(WAIT_MARK, PF0MD_001),
+ PINMUX_DATA(SSISCK1_MARK, PF0MD_010),
+ PINMUX_DATA(DV_DATA0_MARK, PF0MD_011),
+ PINMUX_DATA(SCK2_MARK, PF0MD_100),
+ PINMUX_DATA(TEND0_MARK, PF0MD_101),
+
+ /* Port G */
+ PINMUX_DATA(PG24_DATA, PG24MD_00),
+ PINMUX_DATA(MOSI0_MARK, PG24MD_01),
+ PINMUX_DATA(TIOC0D_MARK, PG24MD_10),
+
+ PINMUX_DATA(PG23_DATA, PG23MD_00),
+ PINMUX_DATA(MOSI1_MARK, PG23MD_01),
+ PINMUX_DATA(TIOC0C_MARK, PG23MD_10),
+
+ PINMUX_DATA(PG22_DATA, PG22MD_00),
+ PINMUX_DATA(SSL10_MARK, PG22MD_01),
+ PINMUX_DATA(TIOC0B_MARK, PG22MD_10),
+
+ PINMUX_DATA(PG21_DATA, PG21MD_00),
+ PINMUX_DATA(RSPCK1_MARK, PG21MD_01),
+ PINMUX_DATA(TIOC0A_MARK, PG21MD_10),
+
+ PINMUX_DATA(PG20_DATA, PG20MD_000),
+ PINMUX_DATA(LCD_EXTCLK_MARK, PG20MD_001),
+ PINMUX_DATA(MISO1_MARK, PG20MD_011),
+ PINMUX_DATA(TXD7_MARK, PG20MD_100),
+
+ PINMUX_DATA(PG19_DATA, PG19MD_000),
+ PINMUX_DATA(LCD_CLK_MARK, PG19MD_001),
+ PINMUX_DATA(TIOC2B_MARK, PG19MD_010),
+ PINMUX_DATA(MISO1_PG19_MARK, PG19MD_011),
+ PINMUX_DATA(RXD7_MARK, PG19MD_100),
+
+ PINMUX_DATA(PG18_DATA, PG18MD_000),
+ PINMUX_DATA(LCD_DE_MARK, PG18MD_001),
+ PINMUX_DATA(TIOC2A_MARK, PG18MD_010),
+ PINMUX_DATA(SSL10_MARK, PG18MD_011),
+ PINMUX_DATA(TXD6_MARK, PG18MD_100),
+
+ PINMUX_DATA(PG17_DATA, PG17MD_000),
+ PINMUX_DATA(LCD_HSYNC_MARK, PG17MD_001),
+ PINMUX_DATA(TIOC1B_MARK, PG17MD_010),
+ PINMUX_DATA(RSPCK1_MARK, PG17MD_011),
+ PINMUX_DATA(RXD6_MARK, PG17MD_100),
+
+ PINMUX_DATA(PG16_DATA, PG16MD_000),
+ PINMUX_DATA(LCD_VSYNC_MARK, PG16MD_001),
+ PINMUX_DATA(TIOC1A_MARK, PG16MD_010),
+ PINMUX_DATA(TXD3_MARK, PG16MD_011),
+ PINMUX_DATA(CTS1_MARK, PG16MD_100),
+
+ PINMUX_DATA(PG15_DATA, PG15MD_000),
+ PINMUX_DATA(LCD_DATA15_MARK, PG15MD_001),
+ PINMUX_DATA(TIOC0D_MARK, PG15MD_010),
+ PINMUX_DATA(RXD3_MARK, PG15MD_011),
+ PINMUX_DATA(RTS1_MARK, PG15MD_100),
+
+ PINMUX_DATA(PG14_DATA, PG14MD_000),
+ PINMUX_DATA(LCD_DATA14_MARK, PG14MD_001),
+ PINMUX_DATA(TIOC0C_MARK, PG14MD_010),
+ PINMUX_DATA(SCK1_MARK, PG14MD_100),
+
+ PINMUX_DATA(PG13_DATA, PG13MD_000),
+ PINMUX_DATA(LCD_DATA13_MARK, PG13MD_001),
+ PINMUX_DATA(TIOC0B_MARK, PG13MD_010),
+ PINMUX_DATA(TXD1_MARK, PG13MD_100),
+
+ PINMUX_DATA(PG12_DATA, PG12MD_000),
+ PINMUX_DATA(LCD_DATA12_MARK, PG12MD_001),
+ PINMUX_DATA(TIOC0A_MARK, PG12MD_010),
+ PINMUX_DATA(RXD1_MARK, PG12MD_100),
+
+ PINMUX_DATA(PG11_DATA, PG11MD_000),
+ PINMUX_DATA(LCD_DATA11_MARK, PG11MD_001),
+ PINMUX_DATA(SSITXD0_MARK, PG11MD_010),
+ PINMUX_DATA(IRQ3_PG_MARK, PG11MD_011),
+ PINMUX_DATA(TXD5_MARK, PG11MD_100),
+ PINMUX_DATA(SIOFTXD_MARK, PG11MD_101),
+
+ PINMUX_DATA(PG10_DATA, PG10MD_000),
+ PINMUX_DATA(LCD_DATA10_MARK, PG10MD_001),
+ PINMUX_DATA(SSIRXD0_MARK, PG10MD_010),
+ PINMUX_DATA(IRQ2_PG_MARK, PG10MD_011),
+ PINMUX_DATA(RXD5_MARK, PG10MD_100),
+ PINMUX_DATA(SIOFRXD_MARK, PG10MD_101),
+
+ PINMUX_DATA(PG9_DATA, PG9MD_000),
+ PINMUX_DATA(LCD_DATA9_MARK, PG9MD_001),
+ PINMUX_DATA(SSIWS0_MARK, PG9MD_010),
+ PINMUX_DATA(TXD4_MARK, PG9MD_100),
+ PINMUX_DATA(SIOFSYNC_MARK, PG9MD_101),
+
+ PINMUX_DATA(PG8_DATA, PG8MD_000),
+ PINMUX_DATA(LCD_DATA8_MARK, PG8MD_001),
+ PINMUX_DATA(SSISCK0_MARK, PG8MD_010),
+ PINMUX_DATA(RXD4_MARK, PG8MD_100),
+ PINMUX_DATA(SIOFSCK_MARK, PG8MD_101),
+
+ PINMUX_DATA(PG7_DATA, PG7MD_00),
+ PINMUX_DATA(LCD_DATA7_MARK, PG7MD_01),
+ PINMUX_DATA(SD_CD_MARK, PG7MD_10),
+ PINMUX_DATA(PINT7_PG_MARK, PG7MD_11),
+
+ PINMUX_DATA(PG6_DATA, PG7MD_00),
+ PINMUX_DATA(LCD_DATA6_MARK, PG7MD_01),
+ PINMUX_DATA(SD_WP_MARK, PG7MD_10),
+ PINMUX_DATA(PINT6_PG_MARK, PG7MD_11),
+
+ PINMUX_DATA(PG5_DATA, PG5MD_00),
+ PINMUX_DATA(LCD_DATA5_MARK, PG5MD_01),
+ PINMUX_DATA(SD_D1_MARK, PG5MD_10),
+ PINMUX_DATA(PINT5_PG_MARK, PG5MD_11),
+
+ PINMUX_DATA(PG4_DATA, PG4MD_00),
+ PINMUX_DATA(LCD_DATA4_MARK, PG4MD_01),
+ PINMUX_DATA(SD_D0_MARK, PG4MD_10),
+ PINMUX_DATA(PINT4_PG_MARK, PG4MD_11),
+
+ PINMUX_DATA(PG3_DATA, PG3MD_00),
+ PINMUX_DATA(LCD_DATA3_MARK, PG3MD_01),
+ PINMUX_DATA(SD_CLK_MARK, PG3MD_10),
+ PINMUX_DATA(PINT3_PG_MARK, PG3MD_11),
+
+ PINMUX_DATA(PG2_DATA, PG2MD_00),
+ PINMUX_DATA(LCD_DATA2_MARK, PG2MD_01),
+ PINMUX_DATA(SD_CMD_MARK, PG2MD_10),
+ PINMUX_DATA(PINT2_PG_MARK, PG2MD_11),
+
+ PINMUX_DATA(PG1_DATA, PG1MD_00),
+ PINMUX_DATA(LCD_DATA1_MARK, PG1MD_01),
+ PINMUX_DATA(SD_D3_MARK, PG1MD_10),
+ PINMUX_DATA(PINT1_PG_MARK, PG1MD_11),
+
+ PINMUX_DATA(PG0_DATA, PG0MD_000),
+ PINMUX_DATA(LCD_DATA0_MARK, PG0MD_001),
+ PINMUX_DATA(SD_D2_MARK, PG0MD_010),
+ PINMUX_DATA(PINT0_PG_MARK, PG0MD_011),
+ PINMUX_DATA(WDTOVF_MARK, PG0MD_100),
+
+ /* Port H */
+ PINMUX_DATA(PH7_DATA, PH7MD_0),
+ PINMUX_DATA(PHAN7_MARK, PH7MD_1),
+
+ PINMUX_DATA(PH6_DATA, PH6MD_0),
+ PINMUX_DATA(PHAN6_MARK, PH6MD_1),
+
+ PINMUX_DATA(PH5_DATA, PH5MD_0),
+ PINMUX_DATA(PHAN5_MARK, PH5MD_1),
+
+ PINMUX_DATA(PH4_DATA, PH4MD_0),
+ PINMUX_DATA(PHAN4_MARK, PH4MD_1),
+
+ PINMUX_DATA(PH3_DATA, PH3MD_0),
+ PINMUX_DATA(PHAN3_MARK, PH3MD_1),
+
+ PINMUX_DATA(PH2_DATA, PH2MD_0),
+ PINMUX_DATA(PHAN2_MARK, PH2MD_1),
+
+ PINMUX_DATA(PH1_DATA, PH1MD_0),
+ PINMUX_DATA(PHAN1_MARK, PH1MD_1),
+
+ PINMUX_DATA(PH0_DATA, PH0MD_0),
+ PINMUX_DATA(PHAN0_MARK, PH0MD_1),
+
+ /* Port I - not on device */
+
+ /* Port J */
+ PINMUX_DATA(PJ11_DATA, PJ11MD_00),
+ PINMUX_DATA(PWM2H_MARK, PJ11MD_01),
+ PINMUX_DATA(DACK1_MARK, PJ11MD_10),
+
+ PINMUX_DATA(PJ10_DATA, PJ10MD_00),
+ PINMUX_DATA(PWM2G_MARK, PJ10MD_01),
+ PINMUX_DATA(DREQ1_MARK, PJ10MD_10),
+
+ PINMUX_DATA(PJ9_DATA, PJ9MD_00),
+ PINMUX_DATA(PWM2F_MARK, PJ9MD_01),
+ PINMUX_DATA(TEND1_MARK, PJ9MD_10),
+
+ PINMUX_DATA(PJ8_DATA, PJ8MD_00),
+ PINMUX_DATA(PWM2E_MARK, PJ8MD_01),
+ PINMUX_DATA(RTS3_MARK, PJ8MD_10),
+
+ PINMUX_DATA(PJ7_DATA, PJ7MD_00),
+ PINMUX_DATA(TIOC1B_MARK, PJ7MD_01),
+ PINMUX_DATA(CTS3_MARK, PJ7MD_10),
+
+ PINMUX_DATA(PJ6_DATA, PJ6MD_00),
+ PINMUX_DATA(TIOC1A_MARK, PJ6MD_01),
+ PINMUX_DATA(SCK3_MARK, PJ6MD_10),
+
+ PINMUX_DATA(PJ5_DATA, PJ5MD_00),
+ PINMUX_DATA(IERXD_MARK, PJ5MD_01),
+ PINMUX_DATA(TXD3_MARK, PJ5MD_10),
+
+ PINMUX_DATA(PJ4_DATA, PJ4MD_00),
+ PINMUX_DATA(IETXD_MARK, PJ4MD_01),
+ PINMUX_DATA(RXD3_MARK, PJ4MD_10),
+
+ PINMUX_DATA(PJ3_DATA, PJ3MD_00),
+ PINMUX_DATA(CRX1_MARK, PJ3MD_01),
+ PINMUX_DATA(CRX0X1_MARK, PJ3MD_10),
+ PINMUX_DATA(IRQ1_PJ_MARK, PJ3MD_11),
+
+ PINMUX_DATA(PJ2_DATA, PJ2MD_000),
+ PINMUX_DATA(CTX1_MARK, PJ2MD_001),
+ PINMUX_DATA(CRX0CRX1_MARK, PJ2MD_010),
+ PINMUX_DATA(CS2_MARK, PJ2MD_011),
+ PINMUX_DATA(SCK0_MARK, PJ2MD_100),
+ PINMUX_DATA(LCD_M_DISP_MARK, PJ2MD_101),
+
+ PINMUX_DATA(PJ1_DATA, PJ1MD_000),
+ PINMUX_DATA(CRX0_MARK, PJ1MD_001),
+ PINMUX_DATA(IERXD_MARK, PJ1MD_010),
+ PINMUX_DATA(IRQ0_PJ_MARK, PJ1MD_011),
+ PINMUX_DATA(RXD0_MARK, PJ1MD_100),
+
+ PINMUX_DATA(PJ0_DATA, PJ0MD_000),
+ PINMUX_DATA(CTX0_MARK, PJ0MD_001),
+ PINMUX_DATA(IERXD_MARK, PJ0MD_010),
+ PINMUX_DATA(CS1_MARK, PJ0MD_011),
+ PINMUX_DATA(TXD0_MARK, PJ0MD_100),
+ PINMUX_DATA(A0_MARK, PJ0MD_101),
+
+ /* Port K */
+ PINMUX_DATA(PK11_DATA, PK11MD_00),
+ PINMUX_DATA(PWM2D_MARK, PK11MD_01),
+ PINMUX_DATA(SSITXD0_MARK, PK11MD_10),
+
+ PINMUX_DATA(PK10_DATA, PK10MD_00),
+ PINMUX_DATA(PWM2C_MARK, PK10MD_01),
+ PINMUX_DATA(SSIRXD0_MARK, PK10MD_10),
+
+ PINMUX_DATA(PK9_DATA, PK9MD_00),
+ PINMUX_DATA(PWM2B_MARK, PK9MD_01),
+ PINMUX_DATA(SSIWS0_MARK, PK9MD_10),
+
+ PINMUX_DATA(PK8_DATA, PK8MD_00),
+ PINMUX_DATA(PWM2A_MARK, PK8MD_01),
+ PINMUX_DATA(SSISCK0_MARK, PK8MD_10),
+
+ PINMUX_DATA(PK7_DATA, PK7MD_00),
+ PINMUX_DATA(PWM1H_MARK, PK7MD_01),
+ PINMUX_DATA(SD_CD_MARK, PK7MD_10),
+
+ PINMUX_DATA(PK6_DATA, PK6MD_00),
+ PINMUX_DATA(PWM1G_MARK, PK6MD_01),
+ PINMUX_DATA(SD_WP_MARK, PK6MD_10),
+
+ PINMUX_DATA(PK5_DATA, PK5MD_00),
+ PINMUX_DATA(PWM1F_MARK, PK5MD_01),
+ PINMUX_DATA(SD_D1_MARK, PK5MD_10),
+
+ PINMUX_DATA(PK4_DATA, PK4MD_00),
+ PINMUX_DATA(PWM1E_MARK, PK4MD_01),
+ PINMUX_DATA(SD_D0_MARK, PK4MD_10),
+
+ PINMUX_DATA(PK3_DATA, PK3MD_00),
+ PINMUX_DATA(PWM1D_MARK, PK3MD_01),
+ PINMUX_DATA(SD_CLK_MARK, PK3MD_10),
+
+ PINMUX_DATA(PK2_DATA, PK2MD_00),
+ PINMUX_DATA(PWM1C_MARK, PK2MD_01),
+ PINMUX_DATA(SD_CMD_MARK, PK2MD_10),
+
+ PINMUX_DATA(PK1_DATA, PK1MD_00),
+ PINMUX_DATA(PWM1B_MARK, PK1MD_01),
+ PINMUX_DATA(SD_D3_MARK, PK1MD_10),
+
+ PINMUX_DATA(PK0_DATA, PK0MD_00),
+ PINMUX_DATA(PWM1A_MARK, PK0MD_01),
+ PINMUX_DATA(SD_D2_MARK, PK0MD_10),
+};
+
+static struct pinmux_gpio pinmux_gpios[] = {
+
+ /* Port A */
+ PINMUX_GPIO(GPIO_PA3, PA3_DATA),
+ PINMUX_GPIO(GPIO_PA2, PA2_DATA),
+ PINMUX_GPIO(GPIO_PA1, PA1_DATA),
+ PINMUX_GPIO(GPIO_PA0, PA0_DATA),
+
+ /* Port B */
+ PINMUX_GPIO(GPIO_PB22, PB22_DATA),
+ PINMUX_GPIO(GPIO_PB21, PB21_DATA),
+ PINMUX_GPIO(GPIO_PB20, PB20_DATA),
+ PINMUX_GPIO(GPIO_PB19, PB19_DATA),
+ PINMUX_GPIO(GPIO_PB18, PB18_DATA),
+ PINMUX_GPIO(GPIO_PB17, PB17_DATA),
+ PINMUX_GPIO(GPIO_PB16, PB16_DATA),
+ PINMUX_GPIO(GPIO_PB15, PB15_DATA),
+ PINMUX_GPIO(GPIO_PB14, PB14_DATA),
+ PINMUX_GPIO(GPIO_PB13, PB13_DATA),
+ PINMUX_GPIO(GPIO_PB12, PB12_DATA),
+ PINMUX_GPIO(GPIO_PB11, PB11_DATA),
+ PINMUX_GPIO(GPIO_PB10, PB10_DATA),
+ PINMUX_GPIO(GPIO_PB9, PB9_DATA),
+ PINMUX_GPIO(GPIO_PB8, PB8_DATA),
+ PINMUX_GPIO(GPIO_PB7, PB7_DATA),
+ PINMUX_GPIO(GPIO_PB6, PB6_DATA),
+ PINMUX_GPIO(GPIO_PB5, PB5_DATA),
+ PINMUX_GPIO(GPIO_PB4, PB4_DATA),
+ PINMUX_GPIO(GPIO_PB3, PB3_DATA),
+ PINMUX_GPIO(GPIO_PB2, PB2_DATA),
+ PINMUX_GPIO(GPIO_PB1, PB1_DATA),
+
+ /* Port C */
+ PINMUX_GPIO(GPIO_PC10, PC10_DATA),
+ PINMUX_GPIO(GPIO_PC9, PC9_DATA),
+ PINMUX_GPIO(GPIO_PC8, PC8_DATA),
+ PINMUX_GPIO(GPIO_PC7, PC7_DATA),
+ PINMUX_GPIO(GPIO_PC6, PC6_DATA),
+ PINMUX_GPIO(GPIO_PC5, PC5_DATA),
+ PINMUX_GPIO(GPIO_PC4, PC4_DATA),
+ PINMUX_GPIO(GPIO_PC3, PC3_DATA),
+ PINMUX_GPIO(GPIO_PC2, PC2_DATA),
+ PINMUX_GPIO(GPIO_PC1, PC1_DATA),
+ PINMUX_GPIO(GPIO_PC0, PC0_DATA),
+
+ /* Port D */
+ PINMUX_GPIO(GPIO_PD15, PD15_DATA),
+ PINMUX_GPIO(GPIO_PD14, PD14_DATA),
+ PINMUX_GPIO(GPIO_PD13, PD13_DATA),
+ PINMUX_GPIO(GPIO_PD12, PD12_DATA),
+ PINMUX_GPIO(GPIO_PD11, PD11_DATA),
+ PINMUX_GPIO(GPIO_PD10, PD10_DATA),
+ PINMUX_GPIO(GPIO_PD9, PD9_DATA),
+ PINMUX_GPIO(GPIO_PD8, PD8_DATA),
+ PINMUX_GPIO(GPIO_PD7, PD7_DATA),
+ PINMUX_GPIO(GPIO_PD6, PD6_DATA),
+ PINMUX_GPIO(GPIO_PD5, PD5_DATA),
+ PINMUX_GPIO(GPIO_PD4, PD4_DATA),
+ PINMUX_GPIO(GPIO_PD3, PD3_DATA),
+ PINMUX_GPIO(GPIO_PD2, PD2_DATA),
+ PINMUX_GPIO(GPIO_PD1, PD1_DATA),
+ PINMUX_GPIO(GPIO_PD0, PD0_DATA),
+
+ /* Port E */
+ PINMUX_GPIO(GPIO_PE5, PE5_DATA),
+ PINMUX_GPIO(GPIO_PE4, PE4_DATA),
+ PINMUX_GPIO(GPIO_PE3, PE3_DATA),
+ PINMUX_GPIO(GPIO_PE2, PE2_DATA),
+ PINMUX_GPIO(GPIO_PE1, PE1_DATA),
+ PINMUX_GPIO(GPIO_PE0, PE0_DATA),
+
+ /* Port F */
+ PINMUX_GPIO(GPIO_PF12, PF12_DATA),
+ PINMUX_GPIO(GPIO_PF11, PF11_DATA),
+ PINMUX_GPIO(GPIO_PF10, PF10_DATA),
+ PINMUX_GPIO(GPIO_PF9, PF9_DATA),
+ PINMUX_GPIO(GPIO_PF8, PF8_DATA),
+ PINMUX_GPIO(GPIO_PF7, PF7_DATA),
+ PINMUX_GPIO(GPIO_PF6, PF6_DATA),
+ PINMUX_GPIO(GPIO_PF5, PF5_DATA),
+ PINMUX_GPIO(GPIO_PF4, PF4_DATA),
+ PINMUX_GPIO(GPIO_PF3, PF3_DATA),
+ PINMUX_GPIO(GPIO_PF2, PF2_DATA),
+ PINMUX_GPIO(GPIO_PF1, PF1_DATA),
+ PINMUX_GPIO(GPIO_PF0, PF0_DATA),
+
+ /* Port G */
+ PINMUX_GPIO(GPIO_PG24, PG24_DATA),
+ PINMUX_GPIO(GPIO_PG23, PG23_DATA),
+ PINMUX_GPIO(GPIO_PG22, PG22_DATA),
+ PINMUX_GPIO(GPIO_PG21, PG21_DATA),
+ PINMUX_GPIO(GPIO_PG20, PG20_DATA),
+ PINMUX_GPIO(GPIO_PG19, PG19_DATA),
+ PINMUX_GPIO(GPIO_PG18, PG18_DATA),
+ PINMUX_GPIO(GPIO_PG17, PG17_DATA),
+ PINMUX_GPIO(GPIO_PG16, PG16_DATA),
+ PINMUX_GPIO(GPIO_PG15, PG15_DATA),
+ PINMUX_GPIO(GPIO_PG14, PG14_DATA),
+ PINMUX_GPIO(GPIO_PG13, PG13_DATA),
+ PINMUX_GPIO(GPIO_PG12, PG12_DATA),
+ PINMUX_GPIO(GPIO_PG11, PG11_DATA),
+ PINMUX_GPIO(GPIO_PG10, PG10_DATA),
+ PINMUX_GPIO(GPIO_PG9, PG9_DATA),
+ PINMUX_GPIO(GPIO_PG8, PG8_DATA),
+ PINMUX_GPIO(GPIO_PG7, PG7_DATA),
+ PINMUX_GPIO(GPIO_PG6, PG6_DATA),
+ PINMUX_GPIO(GPIO_PG5, PG5_DATA),
+ PINMUX_GPIO(GPIO_PG4, PG4_DATA),
+ PINMUX_GPIO(GPIO_PG3, PG3_DATA),
+ PINMUX_GPIO(GPIO_PG2, PG2_DATA),
+ PINMUX_GPIO(GPIO_PG1, PG1_DATA),
+ PINMUX_GPIO(GPIO_PG0, PG0_DATA),
+
+ /* Port H - Port H does not have a Data Register */
+
+ /* Port I - not on device */
+
+ /* Port J */
+ PINMUX_GPIO(GPIO_PJ11, PJ11_DATA),
+ PINMUX_GPIO(GPIO_PJ10, PJ10_DATA),
+ PINMUX_GPIO(GPIO_PJ9, PJ9_DATA),
+ PINMUX_GPIO(GPIO_PJ8, PJ8_DATA),
+ PINMUX_GPIO(GPIO_PJ7, PJ7_DATA),
+ PINMUX_GPIO(GPIO_PJ6, PJ6_DATA),
+ PINMUX_GPIO(GPIO_PJ5, PJ5_DATA),
+ PINMUX_GPIO(GPIO_PJ4, PJ4_DATA),
+ PINMUX_GPIO(GPIO_PJ3, PJ3_DATA),
+ PINMUX_GPIO(GPIO_PJ2, PJ2_DATA),
+ PINMUX_GPIO(GPIO_PJ1, PJ1_DATA),
+ PINMUX_GPIO(GPIO_PJ0, PJ0_DATA),
+
+ /* Port K */
+ PINMUX_GPIO(GPIO_PK11, PK11_DATA),
+ PINMUX_GPIO(GPIO_PK10, PK10_DATA),
+ PINMUX_GPIO(GPIO_PK9, PK9_DATA),
+ PINMUX_GPIO(GPIO_PK8, PK8_DATA),
+ PINMUX_GPIO(GPIO_PK7, PK7_DATA),
+ PINMUX_GPIO(GPIO_PK6, PK6_DATA),
+ PINMUX_GPIO(GPIO_PK5, PK5_DATA),
+ PINMUX_GPIO(GPIO_PK4, PK4_DATA),
+ PINMUX_GPIO(GPIO_PK3, PK3_DATA),
+ PINMUX_GPIO(GPIO_PK2, PK2_DATA),
+ PINMUX_GPIO(GPIO_PK1, PK1_DATA),
+ PINMUX_GPIO(GPIO_PK0, PK0_DATA),
+
+ /* INTC */
+ PINMUX_GPIO(GPIO_FN_PINT7_PG, PINT7_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT6_PG, PINT6_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT5_PG, PINT5_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT4_PG, PINT4_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT3_PG, PINT3_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT2_PG, PINT2_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT1_PG, PINT1_PG_MARK),
+
+ PINMUX_GPIO(GPIO_FN_IRQ7_PC, IRQ7_PC_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ6_PC, IRQ6_PC_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ5_PC, IRQ5_PC_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ4_PC, IRQ4_PC_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ3_PG, IRQ3_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ2_PG, IRQ2_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ1_PJ, IRQ1_PJ_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ0_PJ, IRQ0_PJ_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ3_PE, IRQ3_PE_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ2_PE, IRQ2_PE_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ1_PE, IRQ1_PE_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ0_PE, IRQ0_PE_MARK),
+
+ /* WDT */
+ PINMUX_GPIO(GPIO_FN_WDTOVF, WDTOVF_MARK),
+
+ /* CAN */
+ PINMUX_GPIO(GPIO_FN_CTX1, CTX1_MARK),
+ PINMUX_GPIO(GPIO_FN_CRX1, CRX1_MARK),
+ PINMUX_GPIO(GPIO_FN_CTX0, CTX0_MARK),
+ PINMUX_GPIO(GPIO_FN_CRX0, CRX0_MARK),
+ PINMUX_GPIO(GPIO_FN_CRX0_CRX1, CRX0CRX1_MARK),
+
+ /* DMAC */
+ PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK),
+ PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
+ PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
+ PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK),
+ PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
+ PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
+
+ /* ADC */
+ PINMUX_GPIO(GPIO_FN_ADTRG, ADTRG_MARK),
+
+ /* BSCh */
+ PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
+ PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
+ PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
+ PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
+ PINMUX_GPIO(GPIO_FN_A21, A21_MARK),
+ PINMUX_GPIO(GPIO_FN_A20, A20_MARK),
+ PINMUX_GPIO(GPIO_FN_A19, A19_MARK),
+ PINMUX_GPIO(GPIO_FN_A18, A18_MARK),
+ PINMUX_GPIO(GPIO_FN_A17, A17_MARK),
+ PINMUX_GPIO(GPIO_FN_A16, A16_MARK),
+ PINMUX_GPIO(GPIO_FN_A15, A15_MARK),
+ PINMUX_GPIO(GPIO_FN_A14, A14_MARK),
+ PINMUX_GPIO(GPIO_FN_A13, A13_MARK),
+ PINMUX_GPIO(GPIO_FN_A12, A12_MARK),
+ PINMUX_GPIO(GPIO_FN_A11, A11_MARK),
+ PINMUX_GPIO(GPIO_FN_A10, A10_MARK),
+ PINMUX_GPIO(GPIO_FN_A9, A9_MARK),
+ PINMUX_GPIO(GPIO_FN_A8, A8_MARK),
+ PINMUX_GPIO(GPIO_FN_A7, A7_MARK),
+ PINMUX_GPIO(GPIO_FN_A6, A6_MARK),
+ PINMUX_GPIO(GPIO_FN_A5, A5_MARK),
+ PINMUX_GPIO(GPIO_FN_A4, A4_MARK),
+ PINMUX_GPIO(GPIO_FN_A3, A3_MARK),
+ PINMUX_GPIO(GPIO_FN_A2, A2_MARK),
+ PINMUX_GPIO(GPIO_FN_A1, A1_MARK),
+ PINMUX_GPIO(GPIO_FN_A0, A0_MARK),
+
+ PINMUX_GPIO(GPIO_FN_D15, D15_MARK),
+ PINMUX_GPIO(GPIO_FN_D14, D14_MARK),
+ PINMUX_GPIO(GPIO_FN_D13, D13_MARK),
+ PINMUX_GPIO(GPIO_FN_D12, D12_MARK),
+ PINMUX_GPIO(GPIO_FN_D11, D11_MARK),
+ PINMUX_GPIO(GPIO_FN_D10, D10_MARK),
+ PINMUX_GPIO(GPIO_FN_D9, D9_MARK),
+ PINMUX_GPIO(GPIO_FN_D8, D8_MARK),
+ PINMUX_GPIO(GPIO_FN_D7, D7_MARK),
+ PINMUX_GPIO(GPIO_FN_D6, D6_MARK),
+ PINMUX_GPIO(GPIO_FN_D5, D5_MARK),
+ PINMUX_GPIO(GPIO_FN_D4, D4_MARK),
+ PINMUX_GPIO(GPIO_FN_D3, D3_MARK),
+ PINMUX_GPIO(GPIO_FN_D2, D2_MARK),
+ PINMUX_GPIO(GPIO_FN_D1, D1_MARK),
+ PINMUX_GPIO(GPIO_FN_D0, D0_MARK),
+
+ PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
+ PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK),
+ PINMUX_GPIO(GPIO_FN_CS3, CS3_MARK),
+ PINMUX_GPIO(GPIO_FN_CS2, CS2_MARK),
+ PINMUX_GPIO(GPIO_FN_CS1, CS1_MARK),
+ PINMUX_GPIO(GPIO_FN_CS0, CS0_MARK),
+ PINMUX_GPIO(GPIO_FN_CS6CE1B, CS6CE1B_MARK),
+ PINMUX_GPIO(GPIO_FN_CS5CE1A, CS5CE1A_MARK),
+ PINMUX_GPIO(GPIO_FN_CE2A, CE2A_MARK),
+ PINMUX_GPIO(GPIO_FN_CE2B, CE2B_MARK),
+ PINMUX_GPIO(GPIO_FN_RD, RD_MARK),
+ PINMUX_GPIO(GPIO_FN_RDWR, RDWR_MARK),
+ PINMUX_GPIO(GPIO_FN_ICIOWRAH, ICIOWRAH_MARK),
+ PINMUX_GPIO(GPIO_FN_ICIORD, ICIORD_MARK),
+ PINMUX_GPIO(GPIO_FN_WE1DQMUWE, WE1DQMUWE_MARK),
+ PINMUX_GPIO(GPIO_FN_WE0DQML, WE0DQML_MARK),
+ PINMUX_GPIO(GPIO_FN_RAS, RAS_MARK),
+ PINMUX_GPIO(GPIO_FN_CAS, CAS_MARK),
+ PINMUX_GPIO(GPIO_FN_CKE, CKE_MARK),
+ PINMUX_GPIO(GPIO_FN_WAIT, WAIT_MARK),
+ PINMUX_GPIO(GPIO_FN_BREQ, BREQ_MARK),
+ PINMUX_GPIO(GPIO_FN_BACK, BACK_MARK),
+ PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
+
+ /* TMU */
+ PINMUX_GPIO(GPIO_FN_TIOC4D, TIOC4D_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC4C, TIOC4C_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC4B, TIOC4B_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC4A, TIOC4A_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC3D, TIOC3D_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC3C, TIOC3C_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC3B, TIOC3B_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC3A, TIOC3A_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC2B, TIOC2B_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC1B, TIOC1B_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC2A, TIOC2A_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC1A, TIOC1A_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC0D, TIOC0D_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC0C, TIOC0C_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC0B, TIOC0B_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC0A, TIOC0A_MARK),
+ PINMUX_GPIO(GPIO_FN_TCLKD, TCLKD_MARK),
+ PINMUX_GPIO(GPIO_FN_TCLKC, TCLKC_MARK),
+ PINMUX_GPIO(GPIO_FN_TCLKB, TCLKB_MARK),
+ PINMUX_GPIO(GPIO_FN_TCLKA, TCLKA_MARK),
+
+ /* SCIF */
+ PINMUX_GPIO(GPIO_FN_TXD0, TXD0_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD0, RXD0_MARK),
+ PINMUX_GPIO(GPIO_FN_SCK0, SCK0_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD1, TXD1_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD1, RXD1_MARK),
+ PINMUX_GPIO(GPIO_FN_SCK1, SCK1_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD2, RXD2_MARK),
+ PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK),
+ PINMUX_GPIO(GPIO_FN_RTS3, RTS3_MARK),
+ PINMUX_GPIO(GPIO_FN_CTS3, CTS3_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD3, TXD3_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD3, RXD3_MARK),
+ PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD4, TXD4_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD4, RXD4_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD5, TXD5_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD5, RXD5_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD6, TXD6_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD6, RXD6_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD7, TXD7_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD7, RXD7_MARK),
+ PINMUX_GPIO(GPIO_FN_RTS1, RTS1_MARK),
+ PINMUX_GPIO(GPIO_FN_CTS1, CTS1_MARK),
+
+ /* RSPI */
+ PINMUX_GPIO(GPIO_FN_RSPCK0, RSPCK0_MARK),
+ PINMUX_GPIO(GPIO_FN_MOSI0, MOSI0_MARK),
+ PINMUX_GPIO(GPIO_FN_MISO0_PF12, MISO0_PF12_MARK),
+ PINMUX_GPIO(GPIO_FN_MISO1, MISO1_MARK),
+ PINMUX_GPIO(GPIO_FN_SSL00, SSL00_MARK),
+ PINMUX_GPIO(GPIO_FN_RSPCK1, RSPCK1_MARK),
+ PINMUX_GPIO(GPIO_FN_MOSI1, MOSI1_MARK),
+ PINMUX_GPIO(GPIO_FN_MISO1_PG19, MISO1_PG19_MARK),
+ PINMUX_GPIO(GPIO_FN_SSL10, SSL10_MARK),
+
+ /* IIC3 */
+ PINMUX_GPIO(GPIO_FN_SCL0, SCL0_MARK),
+ PINMUX_GPIO(GPIO_FN_SCL1, SCL1_MARK),
+ PINMUX_GPIO(GPIO_FN_SCL2, SCL2_MARK),
+ PINMUX_GPIO(GPIO_FN_SDA0, SDA0_MARK),
+ PINMUX_GPIO(GPIO_FN_SDA1, SDA1_MARK),
+ PINMUX_GPIO(GPIO_FN_SDA2, SDA2_MARK),
+
+ /* SSI */
+ PINMUX_GPIO(GPIO_FN_SSISCK0, SSISCK0_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIWS0, SSIWS0_MARK),
+ PINMUX_GPIO(GPIO_FN_SSITXD0, SSITXD0_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIRXD0, SSIRXD0_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIWS1, SSIWS1_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIWS2, SSIWS2_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIWS3, SSIWS3_MARK),
+ PINMUX_GPIO(GPIO_FN_SSISCK1, SSISCK1_MARK),
+ PINMUX_GPIO(GPIO_FN_SSISCK2, SSISCK2_MARK),
+ PINMUX_GPIO(GPIO_FN_SSISCK3, SSISCK3_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIDATA1, SSIDATA1_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIDATA2, SSIDATA2_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIDATA3, SSIDATA3_MARK),
+ PINMUX_GPIO(GPIO_FN_AUDIO_CLK, AUDIO_CLK_MARK),
+
+ /* SIOF */ /* NOTE Shares AUDIO_CLK with SSI */
+ PINMUX_GPIO(GPIO_FN_SIOFTXD, SIOFTXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SIOFRXD, SIOFRXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SIOFSYNC, SIOFSYNC_MARK),
+ PINMUX_GPIO(GPIO_FN_SIOFSCK, SIOFSCK_MARK),
+
+ /* SPDIF */ /* NOTE Shares AUDIO_CLK with SSI */
+ PINMUX_GPIO(GPIO_FN_SPDIF_IN, SPDIF_IN_MARK),
+ PINMUX_GPIO(GPIO_FN_SPDIF_OUT, SPDIF_OUT_MARK),
+
+ /* NANDFMC */ /* NOTE Controller is not available in boot mode 0 */
+ PINMUX_GPIO(GPIO_FN_FCE, FCE_MARK),
+ PINMUX_GPIO(GPIO_FN_FRB, FRB_MARK),
+
+ /* VDC3 */
+ PINMUX_GPIO(GPIO_FN_DV_CLK, DV_CLK_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_VSYNC, DV_VSYNC_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_HSYNC, DV_HSYNC_MARK),
+
+ PINMUX_GPIO(GPIO_FN_DV_DATA7, DV_DATA7_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA6, DV_DATA6_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA5, DV_DATA5_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA4, DV_DATA4_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA3, DV_DATA3_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA2, DV_DATA2_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA1, DV_DATA1_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA0, DV_DATA0_MARK),
+
+ PINMUX_GPIO(GPIO_FN_LCD_CLK, LCD_CLK_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_EXTCLK, LCD_EXTCLK_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_VSYNC, LCD_VSYNC_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_HSYNC, LCD_HSYNC_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DE, LCD_DE_MARK),
+
+ PINMUX_GPIO(GPIO_FN_LCD_DATA15, LCD_DATA15_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA14, LCD_DATA14_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA13, LCD_DATA13_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA12, LCD_DATA12_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA11, LCD_DATA11_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA10, LCD_DATA10_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA9, LCD_DATA9_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA8, LCD_DATA8_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA7, LCD_DATA7_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA6, LCD_DATA6_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA5, LCD_DATA5_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA4, LCD_DATA4_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA3, LCD_DATA3_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA2, LCD_DATA2_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA1, LCD_DATA1_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA0, LCD_DATA0_MARK),
+
+ PINMUX_GPIO(GPIO_FN_LCD_M_DISP, LCD_M_DISP_MARK),
+};
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+ { PINMUX_CFG_REG("PAIOR0", 0xfffe3812, 16, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PA3_IN, PA3_OUT,
+ PA2_IN, PA2_OUT,
+ PA1_IN, PA1_OUT,
+ PA0_IN, PA0_OUT }
+ },
+
+ { PINMUX_CFG_REG("PBCR5", 0xfffe3824, 16, 4) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PB22MD_00, PB22MD_01, PB22MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PB21MD_0, PB21MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB20MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+
+ },
+ { PINMUX_CFG_REG("PBCR4", 0xfffe3826, 16, 4) {
+ 0, PB19MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB18MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB17MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB16MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PBCR3", 0xfffe3828, 16, 4) {
+ 0, PB15MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB14MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB13MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB12MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PBCR2", 0xfffe382a, 16, 4) {
+ 0, PB11MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB10MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB9MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB8MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PBCR1", 0xfffe382c, 16, 4) {
+ 0, PB7MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB6MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB5MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB4MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PBCR0", 0xfffe382e, 16, 4) {
+ 0, PB3MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB2MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB1MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PBIOR1", 0xfffe3830, 16, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,
+ PB22_IN, PB22_OUT,
+ PB21_IN, PB21_OUT,
+ PB20_IN, PB20_OUT,
+ PB19_IN, PB19_OUT,
+ PB18_IN, PB18_OUT,
+ PB17_IN, PB17_OUT,
+ PB16_IN, PB16_OUT }
+ },
+
+ { PINMUX_CFG_REG("PBIOR0", 0xfffe3832, 16, 1) {
+ PB15_IN, PB15_OUT,
+ PB14_IN, PB14_OUT,
+ PB13_IN, PB13_OUT,
+ PB12_IN, PB12_OUT,
+ PB11_IN, PB11_OUT,
+ PB10_IN, PB10_OUT,
+ PB9_IN, PB9_OUT,
+ PB8_IN, PB8_OUT,
+ PB7_IN, PB7_OUT,
+ PB6_IN, PB6_OUT,
+ PB5_IN, PB5_OUT,
+ PB4_IN, PB4_OUT,
+ PB3_IN, PB3_OUT,
+ PB2_IN, PB2_OUT,
+ PB1_IN, PB1_OUT,
+ 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PCCR2", 0xfffe384a, 16, 4) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PC10MD_0, PC10MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PC9MD_0, PC9MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PC8MD_00, PC8MD_01, PC8MD_10, PC8MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PCCR1", 0xfffe384c, 16, 4) {
+ PC7MD_00, PC7MD_01, PC7MD_10, PC7MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PC6MD_00, PC6MD_01, PC6MD_10, PC6MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PC5MD_00, PC5MD_01, PC5MD_10, PC5MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PC4MD_0, PC4MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PCCR0", 0xfffe384e, 16, 4) {
+ PC3MD_0, PC3MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PC2MD_0, PC2MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PC1MD_0, PC1MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PC0MD_0, PC0MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PCIOR0", 0xfffe3852, 16, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ PC10_IN, PC10_OUT,
+ PC9_IN, PC9_OUT,
+ PC8_IN, PC8_OUT,
+ PC7_IN, PC7_OUT,
+ PC6_IN, PC6_OUT,
+ PC5_IN, PC5_OUT,
+ PC4_IN, PC4_OUT,
+ PC3_IN, PC3_OUT,
+ PC2_IN, PC2_OUT,
+ PC1_IN, PC1_OUT,
+ PC0_IN, PC0_OUT
+ }
+ },
+
+ { PINMUX_CFG_REG("PDCR3", 0xfffe3868, 16, 4) {
+ 0, PD15MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PD14MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PD13MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PD12MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PDCR2", 0xfffe386a, 16, 4) {
+ 0, PD11MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PD10MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PD9MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PD8MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PDCR1", 0xfffe386c, 16, 4) {
+ 0, PD7MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PD6MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PD5MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PD4MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PDCR0", 0xfffe386e, 16, 4) {
+ 0, PD3MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PD2MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PD1MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PD0MD_01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PDIOR0", 0xfffe3872, 16, 1) {
+ PD15_IN, PD15_OUT,
+ PD14_IN, PD14_OUT,
+ PD13_IN, PD13_OUT,
+ PD12_IN, PD12_OUT,
+ PD11_IN, PD11_OUT,
+ PD10_IN, PD10_OUT,
+ PD9_IN, PD9_OUT,
+ PD8_IN, PD8_OUT,
+ PD7_IN, PD7_OUT,
+ PD6_IN, PD6_OUT,
+ PD5_IN, PD5_OUT,
+ PD4_IN, PD4_OUT,
+ PD3_IN, PD3_OUT,
+ PD2_IN, PD2_OUT,
+ PD1_IN, PD1_OUT,
+ PD0_IN, PD0_OUT }
+ },
+
+ { PINMUX_CFG_REG("PECR1", 0xfffe388c, 16, 4) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PE5MD_00, PE5MD_01, 0, PE5MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PE4MD_00, PE4MD_01, 0, PE4MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PECR0", 0xfffe388e, 16, 4) {
+ PE3MD_00, PE3MD_01, 0, PE3MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PE2MD_00, PE2MD_01, 0, PE2MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PE1MD_000, PE1MD_001, PE1MD_010, PE1MD_011,
+ PE1MD_100, PE1MD_101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PE0MD_00, PE0MD_01, PE0MD_10, PE0MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PEIOR0", 0xfffe3892, 16, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ PE5_IN, PE5_OUT,
+ PE4_IN, PE4_OUT,
+ PE3_IN, PE3_OUT,
+ PE2_IN, PE2_OUT,
+ PE1_IN, PE1_OUT,
+ PE0_IN, PE0_OUT }
+ },
+
+ { PINMUX_CFG_REG("PFCR3", 0xfffe38a8, 16, 4) {
+ PF12MD_000, PF12MD_001, 0, PF12MD_011,
+ PF12MD_100, PF12MD_101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PFCR2", 0xfffe38aa, 16, 4) {
+ PF11MD_000, PF11MD_001, PF11MD_010, PF11MD_011,
+ PF11MD_100, PF11MD_101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PF10MD_000, PF10MD_001, PF10MD_010, PF10MD_011,
+ PF10MD_100, PF10MD_101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PF9MD_000, PF9MD_001, PF9MD_010, PF9MD_011,
+ PF9MD_100, PF9MD_101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PF8MD_00, PF8MD_01, PF8MD_10, PF8MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PFCR1", 0xfffe38ac, 16, 4) {
+ PF7MD_000, PF7MD_001, PF7MD_010, PF7MD_011,
+ PF7MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PF6MD_000, PF6MD_001, PF6MD_010, PF6MD_011,
+ PF6MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PF5MD_000, PF5MD_001, PF5MD_010, PF5MD_011,
+ PF5MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PF4MD_000, PF4MD_001, PF4MD_010, PF4MD_011,
+ PF4MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PFCR0", 0xfffe38ae, 16, 4) {
+ PF3MD_000, PF3MD_001, PF3MD_010, PF3MD_011,
+ PF3MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PF2MD_000, PF2MD_001, PF2MD_010, PF2MD_011,
+ PF2MD_100, PF2MD_101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PF1MD_000, PF1MD_001, PF1MD_010, PF1MD_011,
+ PF1MD_100, PF1MD_101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ }
+ },
+
+ { PINMUX_CFG_REG("PFIOR0", 0xfffe38b2, 16, 1) {
+ 0, 0, 0, 0, 0, 0,
+ PF12_IN, PF12_OUT,
+ PF11_IN, PF11_OUT,
+ PF10_IN, PF10_OUT,
+ PF9_IN, PF9_OUT,
+ PF8_IN, PF8_OUT,
+ PF7_IN, PF7_OUT,
+ PF6_IN, PF6_OUT,
+ PF5_IN, PF5_OUT,
+ PF4_IN, PF4_OUT,
+ PF3_IN, PF3_OUT,
+ PF2_IN, PF2_OUT,
+ PF1_IN, PF1_OUT,
+ PF0_IN, PF0_OUT }
+ },
+
+ { PINMUX_CFG_REG("PGCR7", 0xfffe38c0, 16, 4) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG0MD_000, PG0MD_001, PG0MD_010, PG0MD_011,
+ PG0MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PGCR6", 0xfffe38c2, 16, 4) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG24MD_00, PG24MD_01, PG24MD_10, PG24MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PGCR5", 0xfffe38c4, 16, 4) {
+ PG23MD_00, PG23MD_01, PG23MD_10, PG23MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG22MD_00, PG22MD_01, PG22MD_10, PG22MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG21MD_00, PG21MD_01, PG21MD_10, PG21MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG20MD_000, PG20MD_001, PG20MD_010, PG20MD_011,
+ PG20MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PGCR4", 0xfffe38c6, 16, 4) {
+ PG19MD_000, PG19MD_001, PG19MD_010, PG19MD_011,
+ PG19MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG18MD_000, PG18MD_001, PG18MD_010, PG18MD_011,
+ PG18MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG17MD_000, PG17MD_001, PG17MD_010, PG17MD_011,
+ PG17MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG16MD_000, PG16MD_001, PG16MD_010, PG16MD_011,
+ PG16MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PGCR3", 0xfffe38c8, 16, 4) {
+ PG15MD_000, PG15MD_001, PG15MD_010, PG15MD_011,
+ PG15MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG14MD_000, PG14MD_001, PG14MD_010, 0,
+ PG14MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG13MD_000, PG13MD_001, PG13MD_010, 0,
+ PG13MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG12MD_000, PG12MD_001, PG12MD_010, 0,
+ PG12MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PGCR2", 0xfffe38ca, 16, 4) {
+ PG11MD_000, PG11MD_001, PG11MD_010, PG11MD_011,
+ PG11MD_100, PG11MD_101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG10MD_000, PG10MD_001, PG10MD_010, PG10MD_011,
+ PG10MD_100, PG10MD_101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG9MD_000, PG9MD_001, PG9MD_010, PG9MD_011,
+ PG9MD_100, PG9MD_101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG8MD_000, PG8MD_001, PG8MD_010, PG8MD_011,
+ PG8MD_100, PG8MD_101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PGCR1", 0xfffe38cc, 16, 4) {
+ PG7MD_00, PG7MD_01, PG7MD_10, PG7MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG6MD_00, PG6MD_01, PG6MD_10, PG6MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG5MD_00, PG5MD_01, PG5MD_10, PG5MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG4MD_00, PG4MD_01, PG4MD_10, PG4MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PGCR0", 0xfffe38ce, 16, 4) {
+ PG3MD_00, PG3MD_01, PG3MD_10, PG3MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG2MD_00, PG2MD_01, PG2MD_10, PG2MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG1MD_00, PG1MD_01, PG1MD_10, PG1MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PGIOR1", 0xfffe38d0, 16, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ PG24_IN, PG24_OUT,
+ PG23_IN, PG23_OUT,
+ PG22_IN, PG22_OUT,
+ PG21_IN, PG21_OUT,
+ PG20_IN, PG20_OUT,
+ PG19_IN, PG19_OUT,
+ PG18_IN, PG18_OUT,
+ PG17_IN, PG17_OUT,
+ PG16_IN, PG16_OUT }
+ },
+
+ { PINMUX_CFG_REG("PGIOR0", 0xfffe38d2, 16, 1) {
+ PG15_IN, PG15_OUT,
+ PG14_IN, PG14_OUT,
+ PG13_IN, PG13_OUT,
+ PG12_IN, PG12_OUT,
+ PG11_IN, PG11_OUT,
+ PG10_IN, PG10_OUT,
+ PG9_IN, PG9_OUT,
+ PG8_IN, PG8_OUT,
+ PG7_IN, PG7_OUT,
+ PG6_IN, PG6_OUT,
+ PG5_IN, PG5_OUT,
+ PG4_IN, PG4_OUT,
+ PG3_IN, PG3_OUT,
+ PG2_IN, PG2_OUT,
+ PG1_IN, PG1_OUT,
+ PG0_IN, PG0_OUT
+ }
+ },
+
+ { PINMUX_CFG_REG("PHCR1", 0xfffe38ec, 16, 4) {
+ PH7MD_0, PH7MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PH6MD_0, PH6MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PH5MD_0, PH5MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PH4MD_0, PH4MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PHCR0", 0xfffe38ee, 16, 4) {
+ PH3MD_0, PH3MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PH2MD_0, PH2MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PH1MD_0, PH1MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PH0MD_0, PH0MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PJCR2", 0xfffe390a, 16, 4) {
+ PJ11MD_00, PJ11MD_01, PJ11MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PJ10MD_00, PJ10MD_01, PJ10MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PJ9MD_00, PJ9MD_01, PJ9MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PJ8MD_00, PJ8MD_01, PJ8MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PJCR1", 0xfffe390c, 16, 4) {
+ PJ7MD_00, PJ7MD_01, PJ7MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PJ6MD_00, PJ6MD_01, PJ6MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PJ5MD_00, PJ5MD_01, PJ5MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PJ4MD_00, PJ4MD_01, PJ4MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PJCR0", 0xfffe390e, 16, 4) {
+ PJ3MD_00, PJ3MD_01, PJ3MD_10, PJ3MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PJ2MD_000, PJ2MD_001, PJ2MD_010, PJ2MD_011,
+ PJ2MD_100, PJ2MD_101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PJ1MD_000, PJ1MD_001, PJ1MD_010, PJ1MD_011,
+ PJ1MD_100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PJ0MD_000, PJ0MD_001, PJ0MD_010, PJ0MD_011,
+ PJ0MD_100, PJ0MD_101, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, }
+ },
+ { PINMUX_CFG_REG("PJIOR0", 0xfffe3912, 16, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PJ11_IN, PJ11_OUT,
+ PJ10_IN, PJ10_OUT,
+ PJ9_IN, PJ9_OUT,
+ PJ8_IN, PJ8_OUT,
+ PJ7_IN, PJ7_OUT,
+ PJ6_IN, PJ6_OUT,
+ PJ5_IN, PJ5_OUT,
+ PJ4_IN, PJ4_OUT,
+ PJ3_IN, PJ3_OUT,
+ PJ2_IN, PJ2_OUT,
+ PJ1_IN, PJ1_OUT,
+ PJ0_IN, PJ0_OUT }
+ },
+
+ { PINMUX_CFG_REG("PKCR2", 0xfffe392a, 16, 4) {
+ PK11MD_00, PK11MD_01, PK11MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PK10MD_00, PK10MD_01, PK10MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PK9MD_00, PK9MD_01, PK9MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PK8MD_00, PK8MD_01, PK8MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PKCR1", 0xfffe392c, 16, 4) {
+ PK7MD_00, PK7MD_01, PK7MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PK6MD_00, PK6MD_01, PK6MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PK5MD_00, PK5MD_01, PK5MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PK4MD_00, PK4MD_01, PK4MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PKCR0", 0xfffe392e, 16, 4) {
+ PK3MD_00, PK3MD_01, PK3MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PK2MD_00, PK2MD_01, PK2MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PK1MD_00, PK1MD_01, PK1MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PK0MD_00, PK0MD_01, PK0MD_10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PKIOR0", 0xfffe3932, 16, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PJ11_IN, PJ11_OUT,
+ PJ10_IN, PJ10_OUT,
+ PJ9_IN, PJ9_OUT,
+ PJ8_IN, PJ8_OUT,
+ PJ7_IN, PJ7_OUT,
+ PJ6_IN, PJ6_OUT,
+ PJ5_IN, PJ5_OUT,
+ PJ4_IN, PJ4_OUT,
+ PJ3_IN, PJ3_OUT,
+ PJ2_IN, PJ2_OUT,
+ PJ1_IN, PJ1_OUT,
+ PJ0_IN, PJ0_OUT }
+ },
+ {}
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+ { PINMUX_DATA_REG("PADR1", 0xfffe3814, 16) {
+ 0, 0, 0, 0, 0, 0, 0, PA3_DATA,
+ 0, 0, 0, 0, 0, 0, 0, PA2_DATA }
+ },
+
+ { PINMUX_DATA_REG("PADR0", 0xfffe3816, 16) {
+ 0, 0, 0, 0, 0, 0, 0, PA1_DATA,
+ 0, 0, 0, 0, 0, 0, 0, PA0_DATA }
+ },
+
+ { PINMUX_DATA_REG("PBDR1", 0xfffe3834, 16) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB22_DATA, PB21_DATA, PB20_DATA,
+ PB19_DATA, PB18_DATA, PB17_DATA, PB16_DATA }
+ },
+
+ { PINMUX_DATA_REG("PBDR0", 0xfffe3836, 16) {
+ PB15_DATA, PB14_DATA, PB13_DATA, PB12_DATA,
+ PB11_DATA, PB10_DATA, PB9_DATA, PB8_DATA,
+ PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
+ PB3_DATA, PB2_DATA, PB1_DATA, 0 }
+ },
+
+ { PINMUX_DATA_REG("PCDR0", 0xfffe3856, 16) {
+ 0, 0, 0, 0,
+ 0, PC10_DATA, PC9_DATA, PC8_DATA,
+ PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
+ PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA }
+ },
+
+ { PINMUX_DATA_REG("PDDR0", 0xfffe3876, 16) {
+ PD15_DATA, PD14_DATA, PD13_DATA, PD12_DATA,
+ PD11_DATA, PD10_DATA, PD9_DATA, PD8_DATA,
+ PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
+ PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA }
+ },
+
+ { PINMUX_DATA_REG("PEDR0", 0xfffe3896, 16) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, PE5_DATA, PE4_DATA,
+ PE3_DATA, PE2_DATA, PE1_DATA, PE0_DATA }
+ },
+
+ { PINMUX_DATA_REG("PFDR0", 0xfffe38b6, 16) {
+ 0, 0, 0, PF12_DATA,
+ PF11_DATA, PF10_DATA, PF9_DATA, PF8_DATA,
+ PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
+ PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA }
+ },
+
+ { PINMUX_DATA_REG("PGDR1", 0xfffe38d4, 16) {
+ 0, 0, 0, 0, 0, 0, 0, PG24_DATA,
+ PG23_DATA, PG22_DATA, PG21_DATA, PG20_DATA,
+ PG19_DATA, PG18_DATA, PG17_DATA, PG16_DATA }
+ },
+
+ { PINMUX_DATA_REG("PGDR0", 0xfffe38d6, 16) {
+ PG15_DATA, PG14_DATA, PG13_DATA, PG12_DATA,
+ PG11_DATA, PG10_DATA, PG9_DATA, PG8_DATA,
+ PG7_DATA, PG6_DATA, PG5_DATA, PG4_DATA,
+ PG3_DATA, PG2_DATA, PG1_DATA, PG0_DATA }
+ },
+ { PINMUX_DATA_REG("PJDR0", 0xfffe3916, 16) {
+ 0, 0, 0, PJ12_DATA,
+ PJ11_DATA, PJ10_DATA, PJ9_DATA, PJ8_DATA,
+ PJ7_DATA, PJ6_DATA, PJ5_DATA, PJ4_DATA,
+ PJ3_DATA, PJ2_DATA, PJ1_DATA, PJ0_DATA }
+ },
+ { PINMUX_DATA_REG("PKDR0", 0xfffe3936, 16) {
+ 0, 0, 0, PK12_DATA,
+ PK11_DATA, PK10_DATA, PK9_DATA, PK8_DATA,
+ PK7_DATA, PK6_DATA, PK5_DATA, PK4_DATA,
+ PK3_DATA, PK2_DATA, PK1_DATA, PK0_DATA }
+ },
+ { }
+};
+
+static struct pinmux_info sh7264_pinmux_info = {
+ .name = "sh7264_pfc",
+ .reserved_id = PINMUX_RESERVED,
+ .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+ .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END, FORCE_IN },
+ .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END, FORCE_OUT },
+ .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
+ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+ .first_gpio = GPIO_PA3,
+ .last_gpio = GPIO_FN_LCD_M_DISP,
+
+ .gpios = pinmux_gpios,
+ .cfg_regs = pinmux_config_regs,
+ .data_regs = pinmux_data_regs,
+
+ .gpio_data = pinmux_data,
+ .gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return register_pinmux(&sh7264_pinmux_info);
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c b/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c
new file mode 100644
index 000000000000..f25127c46eca
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c
@@ -0,0 +1,2800 @@
+/*
+ * SH7269 Pinmux
+ *
+ * Copyright (C) 2012 Renesas Electronics Europe Ltd
+ * Copyright (C) 2012 Phil Edworthy
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <cpu/sh7269.h>
+
+enum {
+ PINMUX_RESERVED = 0,
+
+ PINMUX_DATA_BEGIN,
+ /* Port A */
+ PA1_DATA, PA0_DATA,
+ /* Port B */
+ PB22_DATA, PB21_DATA, PB20_DATA,
+ PB19_DATA, PB18_DATA, PB17_DATA, PB16_DATA,
+ PB15_DATA, PB14_DATA, PB13_DATA, PB12_DATA,
+ PB11_DATA, PB10_DATA, PB9_DATA, PB8_DATA,
+ PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
+ PB3_DATA, PB2_DATA, PB1_DATA,
+ /* Port C */
+ PC8_DATA,
+ PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
+ PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA,
+ /* Port D */
+ PD15_DATA, PD14_DATA, PD13_DATA, PD12_DATA,
+ PD11_DATA, PD10_DATA, PD9_DATA, PD8_DATA,
+ PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
+ PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA,
+ /* Port E */
+ PE7_DATA, PE6_DATA, PE5_DATA, PE4_DATA,
+ PE3_DATA, PE2_DATA, PE1_DATA, PE0_DATA,
+ /* Port F */
+ PF23_DATA, PF22_DATA, PF21_DATA, PF20_DATA,
+ PF19_DATA, PF18_DATA, PF17_DATA, PF16_DATA,
+ PF15_DATA, PF14_DATA, PF13_DATA, PF12_DATA,
+ PF11_DATA, PF10_DATA, PF9_DATA, PF8_DATA,
+ PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
+ PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA,
+ /* Port G */
+ PG27_DATA, PG26_DATA, PG25_DATA, PG24_DATA,
+ PG23_DATA, PG22_DATA, PG21_DATA, PG20_DATA,
+ PG19_DATA, PG18_DATA, PG17_DATA, PG16_DATA,
+ PG15_DATA, PG14_DATA, PG13_DATA, PG12_DATA,
+ PG11_DATA, PG10_DATA, PG9_DATA, PG8_DATA,
+ PG7_DATA, PG6_DATA, PG5_DATA, PG4_DATA,
+ PG3_DATA, PG2_DATA, PG1_DATA, PG0_DATA,
+ /* Port H */
+ /* NOTE - Port H does not have a Data Register, but PH Data is
+ connected to PH Port Register */
+ PH7_DATA, PH6_DATA, PH5_DATA, PH4_DATA,
+ PH3_DATA, PH2_DATA, PH1_DATA, PH0_DATA,
+ /* Port I - not on device */
+ /* Port J */
+ PJ31_DATA, PJ30_DATA, PJ29_DATA, PJ28_DATA,
+ PJ27_DATA, PJ26_DATA, PJ25_DATA, PJ24_DATA,
+ PJ23_DATA, PJ22_DATA, PJ21_DATA, PJ20_DATA,
+ PJ19_DATA, PJ18_DATA, PJ17_DATA, PJ16_DATA,
+ PJ15_DATA, PJ14_DATA, PJ13_DATA, PJ12_DATA,
+ PJ11_DATA, PJ10_DATA, PJ9_DATA, PJ8_DATA,
+ PJ7_DATA, PJ6_DATA, PJ5_DATA, PJ4_DATA,
+ PJ3_DATA, PJ2_DATA, PJ1_DATA, PJ0_DATA,
+ PINMUX_DATA_END,
+
+ PINMUX_INPUT_BEGIN,
+ FORCE_IN,
+ /* Port A */
+ PA1_IN, PA0_IN,
+ /* Port B */
+ PB22_IN, PB21_IN, PB20_IN,
+ PB19_IN, PB18_IN, PB17_IN, PB16_IN,
+ PB15_IN, PB14_IN, PB13_IN, PB12_IN,
+ PB11_IN, PB10_IN, PB9_IN, PB8_IN,
+ PB7_IN, PB6_IN, PB5_IN, PB4_IN,
+ PB3_IN, PB2_IN, PB1_IN,
+ /* Port C */
+ PC8_IN,
+ PC7_IN, PC6_IN, PC5_IN, PC4_IN,
+ PC3_IN, PC2_IN, PC1_IN, PC0_IN,
+ /* Port D */
+ PD15_IN, PD14_IN, PD13_IN, PD12_IN,
+ PD11_IN, PD10_IN, PD9_IN, PD8_IN,
+ PD7_IN, PD6_IN, PD5_IN, PD4_IN,
+ PD3_IN, PD2_IN, PD1_IN, PD0_IN,
+ /* Port E */
+ PE7_IN, PE6_IN, PE5_IN, PE4_IN,
+ PE3_IN, PE2_IN, PE1_IN, PE0_IN,
+ /* Port F */
+ PF23_IN, PF22_IN, PF21_IN, PF20_IN,
+ PF19_IN, PF18_IN, PF17_IN, PF16_IN,
+ PF15_IN, PF14_IN, PF13_IN, PF12_IN,
+ PF11_IN, PF10_IN, PF9_IN, PF8_IN,
+ PF7_IN, PF6_IN, PF5_IN, PF4_IN,
+ PF3_IN, PF2_IN, PF1_IN, PF0_IN,
+ /* Port G */
+ PG27_IN, PG26_IN, PG25_IN, PG24_IN,
+ PG23_IN, PG22_IN, PG21_IN, PG20_IN,
+ PG19_IN, PG18_IN, PG17_IN, PG16_IN,
+ PG15_IN, PG14_IN, PG13_IN, PG12_IN,
+ PG11_IN, PG10_IN, PG9_IN, PG8_IN,
+ PG7_IN, PG6_IN, PG5_IN, PG4_IN,
+ PG3_IN, PG2_IN, PG1_IN, PG0_IN,
+ /* Port H - Port H does not have a Data Register */
+ /* Port I - not on device */
+ /* Port J */
+ PJ31_IN, PJ30_IN, PJ29_IN, PJ28_IN,
+ PJ27_IN, PJ26_IN, PJ25_IN, PJ24_IN,
+ PJ23_IN, PJ22_IN, PJ21_IN, PJ20_IN,
+ PJ19_IN, PJ18_IN, PJ17_IN, PJ16_IN,
+ PJ15_IN, PJ14_IN, PJ13_IN, PJ12_IN,
+ PJ11_IN, PJ10_IN, PJ9_IN, PJ8_IN,
+ PJ7_IN, PJ6_IN, PJ5_IN, PJ4_IN,
+ PJ3_IN, PJ2_IN, PJ1_IN, PJ0_IN,
+ PINMUX_INPUT_END,
+
+ PINMUX_OUTPUT_BEGIN,
+ FORCE_OUT,
+ /* Port A */
+ PA1_OUT, PA0_OUT,
+ /* Port B */
+ PB22_OUT, PB21_OUT, PB20_OUT,
+ PB19_OUT, PB18_OUT, PB17_OUT, PB16_OUT,
+ PB15_OUT, PB14_OUT, PB13_OUT, PB12_OUT,
+ PB11_OUT, PB10_OUT, PB9_OUT, PB8_OUT,
+ PB7_OUT, PB6_OUT, PB5_OUT, PB4_OUT,
+ PB3_OUT, PB2_OUT, PB1_OUT,
+ /* Port C */
+ PC8_OUT,
+ PC7_OUT, PC6_OUT, PC5_OUT, PC4_OUT,
+ PC3_OUT, PC2_OUT, PC1_OUT, PC0_OUT,
+ /* Port D */
+ PD15_OUT, PD14_OUT, PD13_OUT, PD12_OUT,
+ PD11_OUT, PD10_OUT, PD9_OUT, PD8_OUT,
+ PD7_OUT, PD6_OUT, PD5_OUT, PD4_OUT,
+ PD3_OUT, PD2_OUT, PD1_OUT, PD0_OUT,
+ /* Port E */
+ PE7_OUT, PE6_OUT, PE5_OUT, PE4_OUT,
+ PE3_OUT, PE2_OUT, PE1_OUT, PE0_OUT,
+ /* Port F */
+ PF23_OUT, PF22_OUT, PF21_OUT, PF20_OUT,
+ PF19_OUT, PF18_OUT, PF17_OUT, PF16_OUT,
+ PF15_OUT, PF14_OUT, PF13_OUT, PF12_OUT,
+ PF11_OUT, PF10_OUT, PF9_OUT, PF8_OUT,
+ PF7_OUT, PF6_OUT, PF5_OUT, PF4_OUT,
+ PF3_OUT, PF2_OUT, PF1_OUT, PF0_OUT,
+ /* Port G */
+ PG27_OUT, PG26_OUT, PG25_OUT, PG24_OUT,
+ PG23_OUT, PG22_OUT, PG21_OUT, PG20_OUT,
+ PG19_OUT, PG18_OUT, PG17_OUT, PG16_OUT,
+ PG15_OUT, PG14_OUT, PG13_OUT, PG12_OUT,
+ PG11_OUT, PG10_OUT, PG9_OUT, PG8_OUT,
+ PG7_OUT, PG6_OUT, PG5_OUT, PG4_OUT,
+ PG3_OUT, PG2_OUT, PG1_OUT, PG0_OUT,
+ /* Port H - Port H does not have a Data Register */
+ /* Port I - not on device */
+ /* Port J */
+ PJ31_OUT, PJ30_OUT, PJ29_OUT, PJ28_OUT,
+ PJ27_OUT, PJ26_OUT, PJ25_OUT, PJ24_OUT,
+ PJ23_OUT, PJ22_OUT, PJ21_OUT, PJ20_OUT,
+ PJ19_OUT, PJ18_OUT, PJ17_OUT, PJ16_OUT,
+ PJ15_OUT, PJ14_OUT, PJ13_OUT, PJ12_OUT,
+ PJ11_OUT, PJ10_OUT, PJ9_OUT, PJ8_OUT,
+ PJ7_OUT, PJ6_OUT, PJ5_OUT, PJ4_OUT,
+ PJ3_OUT, PJ2_OUT, PJ1_OUT, PJ0_OUT,
+ PINMUX_OUTPUT_END,
+
+ PINMUX_FUNCTION_BEGIN,
+ /* Port A */
+ PA1_IOR_IN, PA1_IOR_OUT,
+ PA0_IOR_IN, PA0_IOR_OUT,
+
+ /* Port B */
+ PB22_IOR_IN, PB22_IOR_OUT,
+ PB21_IOR_IN, PB21_IOR_OUT,
+ PB20_IOR_IN, PB20_IOR_OUT,
+ PB19_IOR_IN, PB19_IOR_OUT,
+ PB18_IOR_IN, PB18_IOR_OUT,
+ PB17_IOR_IN, PB17_IOR_OUT,
+ PB16_IOR_IN, PB16_IOR_OUT,
+
+ PB15_IOR_IN, PB15_IOR_OUT,
+ PB14_IOR_IN, PB14_IOR_OUT,
+ PB13_IOR_IN, PB13_IOR_OUT,
+ PB12_IOR_IN, PB12_IOR_OUT,
+ PB11_IOR_IN, PB11_IOR_OUT,
+ PB10_IOR_IN, PB10_IOR_OUT,
+ PB9_IOR_IN, PB9_IOR_OUT,
+ PB8_IOR_IN, PB8_IOR_OUT,
+
+ PB7_IOR_IN, PB7_IOR_OUT,
+ PB6_IOR_IN, PB6_IOR_OUT,
+ PB5_IOR_IN, PB5_IOR_OUT,
+ PB4_IOR_IN, PB4_IOR_OUT,
+ PB3_IOR_IN, PB3_IOR_OUT,
+ PB2_IOR_IN, PB2_IOR_OUT,
+ PB1_IOR_IN, PB1_IOR_OUT,
+ PB0_IOR_IN, PB0_IOR_OUT,
+
+ PB22MD_000, PB22MD_001, PB22MD_010, PB22MD_011,
+ PB22MD_100, PB22MD_101, PB22MD_110, PB22MD_111,
+ PB21MD_00, PB21MD_01, PB21MD_10, PB21MD_11,
+ PB20MD_000, PB20MD_001, PB20MD_010, PB20MD_011,
+ PB20MD_100, PB20MD_101, PB20MD_110, PB20MD_111,
+ PB19MD_000, PB19MD_001, PB19MD_010, PB19MD_011,
+ PB19MD_100, PB19MD_101, PB19MD_110, PB19MD_111,
+ PB18MD_000, PB18MD_001, PB18MD_010, PB18MD_011,
+ PB18MD_100, PB18MD_101, PB18MD_110, PB18MD_111,
+ PB17MD_000, PB17MD_001, PB17MD_010, PB17MD_011,
+ PB17MD_100, PB17MD_101, PB17MD_110, PB17MD_111,
+ PB16MD_000, PB16MD_001, PB16MD_010, PB16MD_011,
+ PB16MD_100, PB16MD_101, PB16MD_110, PB16MD_111,
+ PB15MD_000, PB15MD_001, PB15MD_010, PB15MD_011,
+ PB15MD_100, PB15MD_101, PB15MD_110, PB15MD_111,
+ PB14MD_000, PB14MD_001, PB14MD_010, PB14MD_011,
+ PB14MD_100, PB14MD_101, PB14MD_110, PB14MD_111,
+ PB13MD_000, PB13MD_001, PB13MD_010, PB13MD_011,
+ PB13MD_100, PB13MD_101, PB13MD_110, PB13MD_111,
+ PB12MD_00, PB12MD_01, PB12MD_10, PB12MD_11,
+
+ PB11MD_00, PB11MD_01, PB11MD_10, PB11MD_11,
+ PB10MD_00, PB10MD_01, PB10MD_10, PB10MD_11,
+ PB9MD_00, PB9MD_01, PB9MD_10, PB9MD_11,
+ PB8MD_00, PB8MD_01, PB8MD_10, PB8MD_11,
+
+ PB7MD_00, PB7MD_01, PB7MD_10, PB7MD_11,
+ PB6MD_00, PB6MD_01, PB6MD_10, PB6MD_11,
+ PB5MD_00, PB5MD_01, PB5MD_10, PB5MD_11,
+ PB4MD_00, PB4MD_01, PB4MD_10, PB4MD_11,
+
+ PB3MD_00, PB3MD_01, PB3MD_10, PB3MD_11,
+ PB2MD_00, PB2MD_01, PB2MD_10, PB2MD_11,
+ PB1MD_00, PB1MD_01, PB1MD_10, PB1MD_11,
+
+ /* Port C */
+ PC8_IOR_IN, PC8_IOR_OUT,
+ PC7_IOR_IN, PC7_IOR_OUT,
+ PC6_IOR_IN, PC6_IOR_OUT,
+ PC5_IOR_IN, PC5_IOR_OUT,
+ PC4_IOR_IN, PC4_IOR_OUT,
+ PC3_IOR_IN, PC3_IOR_OUT,
+ PC2_IOR_IN, PC2_IOR_OUT,
+ PC1_IOR_IN, PC1_IOR_OUT,
+ PC0_IOR_IN, PC0_IOR_OUT,
+
+ PC8MD_000, PC8MD_001, PC8MD_010, PC8MD_011,
+ PC8MD_100, PC8MD_101, PC8MD_110, PC8MD_111,
+ PC7MD_000, PC7MD_001, PC7MD_010, PC7MD_011,
+ PC7MD_100, PC7MD_101, PC7MD_110, PC7MD_111,
+ PC6MD_000, PC6MD_001, PC6MD_010, PC6MD_011,
+ PC6MD_100, PC6MD_101, PC6MD_110, PC6MD_111,
+ PC5MD_000, PC5MD_001, PC5MD_010, PC5MD_011,
+ PC5MD_100, PC5MD_101, PC5MD_110, PC5MD_111,
+ PC4MD_00, PC4MD_01, PC4MD_10, PC4MD_11,
+
+ PC3MD_00, PC3MD_01, PC3MD_10, PC3MD_11,
+ PC2MD_00, PC2MD_01, PC2MD_10, PC2MD_11,
+ PC1MD_0, PC1MD_1,
+ PC0MD_0, PC0MD_1,
+
+ /* Port D */
+ PD15_IOR_IN, PD15_IOR_OUT,
+ PD14_IOR_IN, PD14_IOR_OUT,
+ PD13_IOR_IN, PD13_IOR_OUT,
+ PD12_IOR_IN, PD12_IOR_OUT,
+ PD11_IOR_IN, PD11_IOR_OUT,
+ PD10_IOR_IN, PD10_IOR_OUT,
+ PD9_IOR_IN, PD9_IOR_OUT,
+ PD8_IOR_IN, PD8_IOR_OUT,
+ PD7_IOR_IN, PD7_IOR_OUT,
+ PD6_IOR_IN, PD6_IOR_OUT,
+ PD5_IOR_IN, PD5_IOR_OUT,
+ PD4_IOR_IN, PD4_IOR_OUT,
+ PD3_IOR_IN, PD3_IOR_OUT,
+ PD2_IOR_IN, PD2_IOR_OUT,
+ PD1_IOR_IN, PD1_IOR_OUT,
+ PD0_IOR_IN, PD0_IOR_OUT,
+
+ PD15MD_00, PD15MD_01, PD15MD_10, PD15MD_11,
+ PD14MD_00, PD14MD_01, PD14MD_10, PD14MD_11,
+ PD13MD_00, PD13MD_01, PD13MD_10, PD13MD_11,
+ PD12MD_00, PD12MD_01, PD12MD_10, PD12MD_11,
+
+ PD11MD_00, PD11MD_01, PD11MD_10, PD11MD_11,
+ PD10MD_00, PD10MD_01, PD10MD_10, PD10MD_11,
+ PD9MD_00, PD9MD_01, PD9MD_10, PD9MD_11,
+ PD8MD_00, PD8MD_01, PD8MD_10, PD8MD_11,
+
+ PD7MD_00, PD7MD_01, PD7MD_10, PD7MD_11,
+ PD6MD_00, PD6MD_01, PD6MD_10, PD6MD_11,
+ PD5MD_00, PD5MD_01, PD5MD_10, PD5MD_11,
+ PD4MD_00, PD4MD_01, PD4MD_10, PD4MD_11,
+
+ PD3MD_00, PD3MD_01, PD3MD_10, PD3MD_11,
+ PD2MD_00, PD2MD_01, PD2MD_10, PD2MD_11,
+ PD1MD_00, PD1MD_01, PD1MD_10, PD1MD_11,
+ PD0MD_00, PD0MD_01, PD0MD_10, PD0MD_11,
+
+ /* Port E */
+ PE7_IOR_IN, PE7_IOR_OUT,
+ PE6_IOR_IN, PE6_IOR_OUT,
+ PE5_IOR_IN, PE5_IOR_OUT,
+ PE4_IOR_IN, PE4_IOR_OUT,
+ PE3_IOR_IN, PE3_IOR_OUT,
+ PE2_IOR_IN, PE2_IOR_OUT,
+ PE1_IOR_IN, PE1_IOR_OUT,
+ PE0_IOR_IN, PE0_IOR_OUT,
+
+ PE7MD_00, PE7MD_01, PE7MD_10, PE7MD_11,
+ PE6MD_00, PE6MD_01, PE6MD_10, PE6MD_11,
+ PE5MD_00, PE5MD_01, PE5MD_10, PE5MD_11,
+ PE4MD_00, PE4MD_01, PE4MD_10, PE4MD_11,
+
+ PE3MD_000, PE3MD_001, PE3MD_010, PE3MD_011,
+ PE3MD_100, PE3MD_101, PE3MD_110, PE3MD_111,
+ PE2MD_000, PE2MD_001, PE2MD_010, PE2MD_011,
+ PE2MD_100, PE2MD_101, PE2MD_110, PE2MD_111,
+ PE1MD_000, PE1MD_001, PE1MD_010, PE1MD_011,
+ PE1MD_100, PE1MD_101, PE1MD_110, PE1MD_111,
+ PE0MD_00, PE0MD_01, PE0MD_10, PE0MD_11,
+
+ /* Port F */
+ PF23_IOR_IN, PF23_IOR_OUT,
+ PF22_IOR_IN, PF22_IOR_OUT,
+ PF21_IOR_IN, PF21_IOR_OUT,
+ PF20_IOR_IN, PF20_IOR_OUT,
+ PF19_IOR_IN, PF19_IOR_OUT,
+ PF18_IOR_IN, PF18_IOR_OUT,
+ PF17_IOR_IN, PF17_IOR_OUT,
+ PF16_IOR_IN, PF16_IOR_OUT,
+ PF15_IOR_IN, PF15_IOR_OUT,
+ PF14_IOR_IN, PF14_IOR_OUT,
+ PF13_IOR_IN, PF13_IOR_OUT,
+ PF12_IOR_IN, PF12_IOR_OUT,
+ PF11_IOR_IN, PF11_IOR_OUT,
+ PF10_IOR_IN, PF10_IOR_OUT,
+ PF9_IOR_IN, PF9_IOR_OUT,
+ PF8_IOR_IN, PF8_IOR_OUT,
+ PF7_IOR_IN, PF7_IOR_OUT,
+ PF6_IOR_IN, PF6_IOR_OUT,
+ PF5_IOR_IN, PF5_IOR_OUT,
+ PF4_IOR_IN, PF4_IOR_OUT,
+ PF3_IOR_IN, PF3_IOR_OUT,
+ PF2_IOR_IN, PF2_IOR_OUT,
+ PF1_IOR_IN, PF1_IOR_OUT,
+ PF0_IOR_IN, PF0_IOR_OUT,
+
+ PF23MD_000, PF23MD_001, PF23MD_010, PF23MD_011,
+ PF23MD_100, PF23MD_101, PF23MD_110, PF23MD_111,
+ PF22MD_000, PF22MD_001, PF22MD_010, PF22MD_011,
+ PF22MD_100, PF22MD_101, PF22MD_110, PF22MD_111,
+ PF21MD_000, PF21MD_001, PF21MD_010, PF21MD_011,
+ PF21MD_100, PF21MD_101, PF21MD_110, PF21MD_111,
+ PF20MD_000, PF20MD_001, PF20MD_010, PF20MD_011,
+ PF20MD_100, PF20MD_101, PF20MD_110, PF20MD_111,
+
+ PF19MD_000, PF19MD_001, PF19MD_010, PF19MD_011,
+ PF19MD_100, PF19MD_101, PF19MD_110, PF19MD_111,
+ PF18MD_000, PF18MD_001, PF18MD_010, PF18MD_011,
+ PF18MD_100, PF18MD_101, PF18MD_110, PF18MD_111,
+ PF17MD_000, PF17MD_001, PF17MD_010, PF17MD_011,
+ PF17MD_100, PF17MD_101, PF17MD_110, PF17MD_111,
+ PF16MD_000, PF16MD_001, PF16MD_010, PF16MD_011,
+ PF16MD_100, PF16MD_101, PF16MD_110, PF16MD_111,
+
+ PF15MD_000, PF15MD_001, PF15MD_010, PF15MD_011,
+ PF15MD_100, PF15MD_101, PF15MD_110, PF15MD_111,
+ PF14MD_000, PF14MD_001, PF14MD_010, PF14MD_011,
+ PF14MD_100, PF14MD_101, PF14MD_110, PF14MD_111,
+ PF13MD_000, PF13MD_001, PF13MD_010, PF13MD_011,
+ PF13MD_100, PF13MD_101, PF13MD_110, PF13MD_111,
+ PF12MD_000, PF12MD_001, PF12MD_010, PF12MD_011,
+ PF12MD_100, PF12MD_101, PF12MD_110, PF12MD_111,
+
+ PF11MD_000, PF11MD_001, PF11MD_010, PF11MD_011,
+ PF11MD_100, PF11MD_101, PF11MD_110, PF11MD_111,
+ PF10MD_000, PF10MD_001, PF10MD_010, PF10MD_011,
+ PF10MD_100, PF10MD_101, PF10MD_110, PF10MD_111,
+ PF9MD_000, PF9MD_001, PF9MD_010, PF9MD_011,
+ PF9MD_100, PF9MD_101, PF9MD_110, PF9MD_111,
+ PF8MD_000, PF8MD_001, PF8MD_010, PF8MD_011,
+ PF8MD_100, PF8MD_101, PF8MD_110, PF8MD_111,
+
+ PF7MD_000, PF7MD_001, PF7MD_010, PF7MD_011,
+ PF7MD_100, PF7MD_101, PF7MD_110, PF7MD_111,
+ PF6MD_000, PF6MD_001, PF6MD_010, PF6MD_011,
+ PF6MD_100, PF6MD_101, PF6MD_110, PF6MD_111,
+ PF5MD_000, PF5MD_001, PF5MD_010, PF5MD_011,
+ PF5MD_100, PF5MD_101, PF5MD_110, PF5MD_111,
+ PF4MD_000, PF4MD_001, PF4MD_010, PF4MD_011,
+ PF4MD_100, PF4MD_101, PF4MD_110, PF4MD_111,
+
+ PF3MD_000, PF3MD_001, PF3MD_010, PF3MD_011,
+ PF3MD_100, PF3MD_101, PF3MD_110, PF3MD_111,
+ PF2MD_000, PF2MD_001, PF2MD_010, PF2MD_011,
+ PF2MD_100, PF2MD_101, PF2MD_110, PF2MD_111,
+ PF1MD_000, PF1MD_001, PF1MD_010, PF1MD_011,
+ PF1MD_100, PF1MD_101, PF1MD_110, PF1MD_111,
+ PF0MD_000, PF0MD_001, PF0MD_010, PF0MD_011,
+ PF0MD_100, PF0MD_101, PF0MD_110, PF0MD_111,
+
+ /* Port G */
+ PG27_IOR_IN, PG27_IOR_OUT,
+ PG26_IOR_IN, PG26_IOR_OUT,
+ PG25_IOR_IN, PG25_IOR_OUT,
+ PG24_IOR_IN, PG24_IOR_OUT,
+ PG23_IOR_IN, PG23_IOR_OUT,
+ PG22_IOR_IN, PG22_IOR_OUT,
+ PG21_IOR_IN, PG21_IOR_OUT,
+ PG20_IOR_IN, PG20_IOR_OUT,
+ PG19_IOR_IN, PG19_IOR_OUT,
+ PG18_IOR_IN, PG18_IOR_OUT,
+ PG17_IOR_IN, PG17_IOR_OUT,
+ PG16_IOR_IN, PG16_IOR_OUT,
+ PG15_IOR_IN, PG15_IOR_OUT,
+ PG14_IOR_IN, PG14_IOR_OUT,
+ PG13_IOR_IN, PG13_IOR_OUT,
+ PG12_IOR_IN, PG12_IOR_OUT,
+ PG11_IOR_IN, PG11_IOR_OUT,
+ PG10_IOR_IN, PG10_IOR_OUT,
+ PG9_IOR_IN, PG9_IOR_OUT,
+ PG8_IOR_IN, PG8_IOR_OUT,
+ PG7_IOR_IN, PG7_IOR_OUT,
+ PG6_IOR_IN, PG6_IOR_OUT,
+ PG5_IOR_IN, PG5_IOR_OUT,
+ PG4_IOR_IN, PG4_IOR_OUT,
+ PG3_IOR_IN, PG3_IOR_OUT,
+ PG2_IOR_IN, PG2_IOR_OUT,
+ PG1_IOR_IN, PG1_IOR_OUT,
+ PG0_IOR_IN, PG0_IOR_OUT,
+
+ PG27MD_00, PG27MD_01, PG27MD_10, PG27MD_11,
+ PG26MD_00, PG26MD_01, PG26MD_10, PG26MD_11,
+ PG25MD_00, PG25MD_01, PG25MD_10, PG25MD_11,
+ PG24MD_00, PG24MD_01, PG24MD_10, PG24MD_11,
+
+ PG23MD_000, PG23MD_001, PG23MD_010, PG23MD_011,
+ PG23MD_100, PG23MD_101, PG23MD_110, PG23MD_111,
+ PG22MD_000, PG22MD_001, PG22MD_010, PG22MD_011,
+ PG22MD_100, PG22MD_101, PG22MD_110, PG22MD_111,
+ PG21MD_000, PG21MD_001, PG21MD_010, PG21MD_011,
+ PG21MD_100, PG21MD_101, PG21MD_110, PG21MD_111,
+ PG20MD_000, PG20MD_001, PG20MD_010, PG20MD_011,
+ PG20MD_100, PG20MD_101, PG20MD_110, PG20MD_111,
+
+ PG19MD_000, PG19MD_001, PG19MD_010, PG19MD_011,
+ PG19MD_100, PG19MD_101, PG19MD_110, PG19MD_111,
+ PG18MD_000, PG18MD_001, PG18MD_010, PG18MD_011,
+ PG18MD_100, PG18MD_101, PG18MD_110, PG18MD_111,
+ PG17MD_00, PG17MD_01, PG17MD_10, PG17MD_11,
+ PG16MD_00, PG16MD_01, PG16MD_10, PG16MD_11,
+
+ PG15MD_00, PG15MD_01, PG15MD_10, PG15MD_11,
+ PG14MD_00, PG14MD_01, PG14MD_10, PG14MD_11,
+ PG13MD_00, PG13MD_01, PG13MD_10, PG13MD_11,
+ PG12MD_00, PG12MD_01, PG12MD_10, PG12MD_11,
+
+ PG11MD_000, PG11MD_001, PG11MD_010, PG11MD_011,
+ PG11MD_100, PG11MD_101, PG11MD_110, PG11MD_111,
+ PG10MD_000, PG10MD_001, PG10MD_010, PG10MD_011,
+ PG10MD_100, PG10MD_101, PG10MD_110, PG10MD_111,
+ PG9MD_000, PG9MD_001, PG9MD_010, PG9MD_011,
+ PG9MD_100, PG9MD_101, PG9MD_110, PG9MD_111,
+ PG8MD_000, PG8MD_001, PG8MD_010, PG8MD_011,
+ PG8MD_100, PG8MD_101, PG8MD_110, PG8MD_111,
+
+ PG7MD_000, PG7MD_001, PG7MD_010, PG7MD_011,
+ PG7MD_100, PG7MD_101, PG7MD_110, PG7MD_111,
+ PG6MD_000, PG6MD_001, PG6MD_010, PG6MD_011,
+ PG6MD_100, PG6MD_101, PG6MD_110, PG6MD_111,
+ PG5MD_000, PG5MD_001, PG5MD_010, PG5MD_011,
+ PG5MD_100, PG5MD_101, PG5MD_110, PG5MD_111,
+ PG4MD_000, PG4MD_001, PG4MD_010, PG4MD_011,
+ PG4MD_100, PG4MD_101, PG4MD_110, PG4MD_111,
+
+ PG3MD_000, PG3MD_001, PG3MD_010, PG3MD_011,
+ PG3MD_100, PG3MD_101, PG3MD_110, PG3MD_111,
+ PG2MD_000, PG2MD_001, PG2MD_010, PG2MD_011,
+ PG2MD_100, PG2MD_101, PG2MD_110, PG2MD_111,
+ PG1MD_000, PG1MD_001, PG1MD_010, PG1MD_011,
+ PG1MD_100, PG1MD_101, PG1MD_110, PG1MD_111,
+ PG0MD_000, PG0MD_001, PG0MD_010, PG0MD_011,
+ PG0MD_100, PG0MD_101, PG0MD_110, PG0MD_111,
+
+ /* Port H */
+ PH7MD_00, PH7MD_01, PH7MD_10, PH7MD_11,
+ PH6MD_00, PH6MD_01, PH6MD_10, PH6MD_11,
+ PH5MD_00, PH5MD_01, PH5MD_10, PH5MD_11,
+ PH4MD_00, PH4MD_01, PH4MD_10, PH4MD_11,
+
+ PH3MD_00, PH3MD_01, PH3MD_10, PH3MD_11,
+ PH2MD_00, PH2MD_01, PH2MD_10, PH2MD_11,
+ PH1MD_00, PH1MD_01, PH1MD_10, PH1MD_11,
+ PH0MD_00, PH0MD_01, PH0MD_10, PH0MD_11,
+
+ /* Port I - not on device */
+
+ /* Port J */
+ PJ31_IOR_IN, PJ31_IOR_OUT,
+ PJ30_IOR_IN, PJ30_IOR_OUT,
+ PJ29_IOR_IN, PJ29_IOR_OUT,
+ PJ28_IOR_IN, PJ28_IOR_OUT,
+ PJ27_IOR_IN, PJ27_IOR_OUT,
+ PJ26_IOR_IN, PJ26_IOR_OUT,
+ PJ25_IOR_IN, PJ25_IOR_OUT,
+ PJ24_IOR_IN, PJ24_IOR_OUT,
+ PJ23_IOR_IN, PJ23_IOR_OUT,
+ PJ22_IOR_IN, PJ22_IOR_OUT,
+ PJ21_IOR_IN, PJ21_IOR_OUT,
+ PJ20_IOR_IN, PJ20_IOR_OUT,
+ PJ19_IOR_IN, PJ19_IOR_OUT,
+ PJ18_IOR_IN, PJ18_IOR_OUT,
+ PJ17_IOR_IN, PJ17_IOR_OUT,
+ PJ16_IOR_IN, PJ16_IOR_OUT,
+ PJ15_IOR_IN, PJ15_IOR_OUT,
+ PJ14_IOR_IN, PJ14_IOR_OUT,
+ PJ13_IOR_IN, PJ13_IOR_OUT,
+ PJ12_IOR_IN, PJ12_IOR_OUT,
+ PJ11_IOR_IN, PJ11_IOR_OUT,
+ PJ10_IOR_IN, PJ10_IOR_OUT,
+ PJ9_IOR_IN, PJ9_IOR_OUT,
+ PJ8_IOR_IN, PJ8_IOR_OUT,
+ PJ7_IOR_IN, PJ7_IOR_OUT,
+ PJ6_IOR_IN, PJ6_IOR_OUT,
+ PJ5_IOR_IN, PJ5_IOR_OUT,
+ PJ4_IOR_IN, PJ4_IOR_OUT,
+ PJ3_IOR_IN, PJ3_IOR_OUT,
+ PJ2_IOR_IN, PJ2_IOR_OUT,
+ PJ1_IOR_IN, PJ1_IOR_OUT,
+ PJ0_IOR_IN, PJ0_IOR_OUT,
+
+ PJ31MD_0, PJ31MD_1,
+ PJ30MD_000, PJ30MD_001, PJ30MD_010, PJ30MD_011,
+ PJ30MD_100, PJ30MD_101, PJ30MD_110, PJ30MD_111,
+ PJ29MD_000, PJ29MD_001, PJ29MD_010, PJ29MD_011,
+ PJ29MD_100, PJ29MD_101, PJ29MD_110, PJ29MD_111,
+ PJ28MD_000, PJ28MD_001, PJ28MD_010, PJ28MD_011,
+ PJ28MD_100, PJ28MD_101, PJ28MD_110, PJ28MD_111,
+
+ PJ27MD_000, PJ27MD_001, PJ27MD_010, PJ27MD_011,
+ PJ27MD_100, PJ27MD_101, PJ27MD_110, PJ27MD_111,
+ PJ26MD_000, PJ26MD_001, PJ26MD_010, PJ26MD_011,
+ PJ26MD_100, PJ26MD_101, PJ26MD_110, PJ26MD_111,
+ PJ25MD_000, PJ25MD_001, PJ25MD_010, PJ25MD_011,
+ PJ25MD_100, PJ25MD_101, PJ25MD_110, PJ25MD_111,
+ PJ24MD_000, PJ24MD_001, PJ24MD_010, PJ24MD_011,
+ PJ24MD_100, PJ24MD_101, PJ24MD_110, PJ24MD_111,
+
+ PJ23MD_000, PJ23MD_001, PJ23MD_010, PJ23MD_011,
+ PJ23MD_100, PJ23MD_101, PJ23MD_110, PJ23MD_111,
+ PJ22MD_000, PJ22MD_001, PJ22MD_010, PJ22MD_011,
+ PJ22MD_100, PJ22MD_101, PJ22MD_110, PJ22MD_111,
+ PJ21MD_000, PJ21MD_001, PJ21MD_010, PJ21MD_011,
+ PJ21MD_100, PJ21MD_101, PJ21MD_110, PJ21MD_111,
+ PJ20MD_000, PJ20MD_001, PJ20MD_010, PJ20MD_011,
+ PJ20MD_100, PJ20MD_101, PJ20MD_110, PJ20MD_111,
+
+ PJ19MD_000, PJ19MD_001, PJ19MD_010, PJ19MD_011,
+ PJ19MD_100, PJ19MD_101, PJ19MD_110, PJ19MD_111,
+ PJ18MD_000, PJ18MD_001, PJ18MD_010, PJ18MD_011,
+ PJ18MD_100, PJ18MD_101, PJ18MD_110, PJ18MD_111,
+ PJ17MD_000, PJ17MD_001, PJ17MD_010, PJ17MD_011,
+ PJ17MD_100, PJ17MD_101, PJ17MD_110, PJ17MD_111,
+ PJ16MD_000, PJ16MD_001, PJ16MD_010, PJ16MD_011,
+ PJ16MD_100, PJ16MD_101, PJ16MD_110, PJ16MD_111,
+
+ PJ15MD_000, PJ15MD_001, PJ15MD_010, PJ15MD_011,
+ PJ15MD_100, PJ15MD_101, PJ15MD_110, PJ15MD_111,
+ PJ14MD_000, PJ14MD_001, PJ14MD_010, PJ14MD_011,
+ PJ14MD_100, PJ14MD_101, PJ14MD_110, PJ14MD_111,
+ PJ13MD_000, PJ13MD_001, PJ13MD_010, PJ13MD_011,
+ PJ13MD_100, PJ13MD_101, PJ13MD_110, PJ13MD_111,
+ PJ12MD_000, PJ12MD_001, PJ12MD_010, PJ12MD_011,
+ PJ12MD_100, PJ12MD_101, PJ12MD_110, PJ12MD_111,
+
+ PJ11MD_000, PJ11MD_001, PJ11MD_010, PJ11MD_011,
+ PJ11MD_100, PJ11MD_101, PJ11MD_110, PJ11MD_111,
+ PJ10MD_000, PJ10MD_001, PJ10MD_010, PJ10MD_011,
+ PJ10MD_100, PJ10MD_101, PJ10MD_110, PJ10MD_111,
+ PJ9MD_000, PJ9MD_001, PJ9MD_010, PJ9MD_011,
+ PJ9MD_100, PJ9MD_101, PJ9MD_110, PJ9MD_111,
+ PJ8MD_000, PJ8MD_001, PJ8MD_010, PJ8MD_011,
+ PJ8MD_100, PJ8MD_101, PJ8MD_110, PJ8MD_111,
+
+ PJ7MD_000, PJ7MD_001, PJ7MD_010, PJ7MD_011,
+ PJ7MD_100, PJ7MD_101, PJ7MD_110, PJ7MD_111,
+ PJ6MD_000, PJ6MD_001, PJ6MD_010, PJ6MD_011,
+ PJ6MD_100, PJ6MD_101, PJ6MD_110, PJ6MD_111,
+ PJ5MD_000, PJ5MD_001, PJ5MD_010, PJ5MD_011,
+ PJ5MD_100, PJ5MD_101, PJ5MD_110, PJ5MD_111,
+ PJ4MD_000, PJ4MD_001, PJ4MD_010, PJ4MD_011,
+ PJ4MD_100, PJ4MD_101, PJ4MD_110, PJ4MD_111,
+
+ PJ3MD_000, PJ3MD_001, PJ3MD_010, PJ3MD_011,
+ PJ3MD_100, PJ3MD_101, PJ3MD_110, PJ3MD_111,
+ PJ2MD_000, PJ2MD_001, PJ2MD_010, PJ2MD_011,
+ PJ2MD_100, PJ2MD_101, PJ2MD_110, PJ2MD_111,
+ PJ1MD_000, PJ1MD_001, PJ1MD_010, PJ1MD_011,
+ PJ1MD_100, PJ1MD_101, PJ1MD_110, PJ1MD_111,
+ PJ0MD_000, PJ0MD_001, PJ0MD_010, PJ0MD_011,
+ PJ0MD_100, PJ0MD_101, PJ0MD_110, PJ0MD_111,
+
+ PINMUX_FUNCTION_END,
+
+ PINMUX_MARK_BEGIN,
+ /* Port H */
+ PHAN7_MARK, PHAN6_MARK, PHAN5_MARK, PHAN4_MARK,
+ PHAN3_MARK, PHAN2_MARK, PHAN1_MARK, PHAN0_MARK,
+
+ /* IRQs */
+ IRQ7_PG_MARK, IRQ6_PG_MARK, IRQ5_PG_MARK, IRQ4_PG_MARK,
+ IRQ3_PG_MARK, IRQ2_PG_MARK, IRQ1_PG_MARK, IRQ0_PG_MARK,
+ IRQ7_PF_MARK, IRQ6_PF_MARK, IRQ5_PF_MARK, IRQ4_PF_MARK,
+ IRQ3_PJ_MARK, IRQ2_PJ_MARK, IRQ1_PJ_MARK, IRQ0_PJ_MARK,
+ IRQ1_PC_MARK, IRQ0_PC_MARK,
+
+ PINT7_PG_MARK, PINT6_PG_MARK, PINT5_PG_MARK, PINT4_PG_MARK,
+ PINT3_PG_MARK, PINT2_PG_MARK, PINT1_PG_MARK, PINT0_PG_MARK,
+ PINT7_PH_MARK, PINT6_PH_MARK, PINT5_PH_MARK, PINT4_PH_MARK,
+ PINT3_PH_MARK, PINT2_PH_MARK, PINT1_PH_MARK, PINT0_PH_MARK,
+ PINT7_PJ_MARK, PINT6_PJ_MARK, PINT5_PJ_MARK, PINT4_PJ_MARK,
+ PINT3_PJ_MARK, PINT2_PJ_MARK, PINT1_PJ_MARK, PINT0_PJ_MARK,
+
+ /* SD */
+ SD_D0_MARK, SD_D1_MARK, SD_D2_MARK, SD_D3_MARK,
+ SD_WP_MARK, SD_CLK_MARK, SD_CMD_MARK, SD_CD_MARK,
+
+ /* MMC */
+ MMC_D0_MARK, MMC_D1_MARK, MMC_D2_MARK, MMC_D3_MARK,
+ MMC_D4_MARK, MMC_D5_MARK, MMC_D6_MARK, MMC_D7_MARK,
+ MMC_CLK_MARK, MMC_CMD_MARK, MMC_CD_MARK,
+
+ /* PWM */
+ PWM1A_MARK, PWM1B_MARK, PWM1C_MARK, PWM1D_MARK,
+ PWM1E_MARK, PWM1F_MARK, PWM1G_MARK, PWM1H_MARK,
+ PWM2A_MARK, PWM2B_MARK, PWM2C_MARK, PWM2D_MARK,
+ PWM2E_MARK, PWM2F_MARK, PWM2G_MARK, PWM2H_MARK,
+
+ /* IEBus */
+ IERXD_MARK, IETXD_MARK,
+
+ /* WDT */
+ WDTOVF_MARK,
+
+ /* DMAC */
+ TEND0_MARK, DACK0_MARK, DREQ0_MARK,
+ TEND1_MARK, DACK1_MARK, DREQ1_MARK,
+
+ /* ADC */
+ ADTRG_MARK,
+
+ /* BSC */
+ A25_MARK, A24_MARK,
+ A23_MARK, A22_MARK, A21_MARK, A20_MARK,
+ A19_MARK, A18_MARK, A17_MARK, A16_MARK,
+ A15_MARK, A14_MARK, A13_MARK, A12_MARK,
+ A11_MARK, A10_MARK, A9_MARK, A8_MARK,
+ A7_MARK, A6_MARK, A5_MARK, A4_MARK,
+ A3_MARK, A2_MARK, A1_MARK, A0_MARK,
+ D31_MARK, D30_MARK, D29_MARK, D28_MARK,
+ D27_MARK, D26_MARK, D25_MARK, D24_MARK,
+ D23_MARK, D22_MARK, D21_MARK, D20_MARK,
+ D19_MARK, D18_MARK, D17_MARK, D16_MARK,
+ D15_MARK, D14_MARK, D13_MARK, D12_MARK,
+ D11_MARK, D10_MARK, D9_MARK, D8_MARK,
+ D7_MARK, D6_MARK, D5_MARK, D4_MARK,
+ D3_MARK, D2_MARK, D1_MARK, D0_MARK,
+ BS_MARK,
+ CS4_MARK, CS3_MARK, CS2_MARK, CS1_MARK, CS0_MARK,
+ CS5CE1A_MARK,
+ CE2A_MARK, CE2B_MARK,
+ RD_MARK, RDWR_MARK,
+ WE3ICIOWRAHDQMUU_MARK,
+ WE2ICIORDDQMUL_MARK,
+ WE1DQMUWE_MARK,
+ WE0DQML_MARK,
+ RAS_MARK, CAS_MARK, CKE_MARK,
+ WAIT_MARK, BREQ_MARK, BACK_MARK, IOIS16_MARK,
+
+ /* TMU */
+ TIOC0A_MARK, TIOC0B_MARK, TIOC0C_MARK, TIOC0D_MARK,
+ TIOC1A_MARK, TIOC1B_MARK,
+ TIOC2A_MARK, TIOC2B_MARK,
+ TIOC3A_MARK, TIOC3B_MARK, TIOC3C_MARK, TIOC3D_MARK,
+ TIOC4A_MARK, TIOC4B_MARK, TIOC4C_MARK, TIOC4D_MARK,
+ TCLKA_MARK, TCLKB_MARK, TCLKC_MARK, TCLKD_MARK,
+
+ /* SCIF */
+ SCK0_MARK, RXD0_MARK, TXD0_MARK,
+ SCK1_MARK, RXD1_MARK, TXD1_MARK, RTS1_MARK, CTS1_MARK,
+ SCK2_MARK, RXD2_MARK, TXD2_MARK,
+ SCK3_MARK, RXD3_MARK, TXD3_MARK,
+ SCK4_MARK, RXD4_MARK, TXD4_MARK,
+ SCK5_MARK, RXD5_MARK, TXD5_MARK, RTS5_MARK, CTS5_MARK,
+ SCK6_MARK, RXD6_MARK, TXD6_MARK,
+ SCK7_MARK, RXD7_MARK, TXD7_MARK, RTS7_MARK, CTS7_MARK,
+
+ /* RSPI */
+ MISO0_PB20_MARK, MOSI0_PB19_MARK, SSL00_PB18_MARK, RSPCK0_PB17_MARK,
+ MISO0_PJ19_MARK, MOSI0_PJ18_MARK, SSL00_PJ17_MARK, RSPCK0_PJ16_MARK,
+ MISO1_MARK, MOSI1_MARK, SSL10_MARK, RSPCK1_MARK,
+
+ /* IIC3 */
+ SCL0_MARK, SDA0_MARK,
+ SCL1_MARK, SDA1_MARK,
+ SCL2_MARK, SDA2_MARK,
+ SCL3_MARK, SDA3_MARK,
+
+ /* SSI */
+ SSISCK0_MARK, SSIWS0_MARK, SSITXD0_MARK, SSIRXD0_MARK,
+ SSISCK1_MARK, SSIWS1_MARK, SSIDATA1_MARK,
+ SSISCK2_MARK, SSIWS2_MARK, SSIDATA2_MARK,
+ SSISCK3_MARK, SSIWS3_MARK, SSIDATA3_MARK,
+ SSISCK4_MARK, SSIWS4_MARK, SSIDATA4_MARK,
+ SSISCK5_MARK, SSIWS5_MARK, SSIDATA5_MARK,
+ AUDIO_CLK_MARK,
+ AUDIO_XOUT_MARK,
+
+ /* SIOF */ /* NOTE Shares AUDIO_CLK with SSI */
+ SIOFTXD_MARK, SIOFRXD_MARK, SIOFSYNC_MARK, SIOFSCK_MARK,
+
+ /* SPDIF */ /* NOTE Shares AUDIO_CLK with SSI */
+ SPDIF_IN_MARK, SPDIF_OUT_MARK,
+ SPDIF_IN_PJ24_MARK, SPDIF_OUT_PJ25_MARK,
+
+ /* NANDFMC */ /* NOTE Controller is not available in boot mode 0 */
+ FCE_MARK,
+ FRB_MARK,
+
+ /* CAN */
+ CRX0_MARK, CTX0_MARK,
+ CRX1_MARK, CTX1_MARK,
+ CRX2_MARK, CTX2_MARK,
+ CRX0CRX1_MARK,
+ CRX0CRX1CRX2_MARK,
+ CTX0CTX1CTX2_MARK,
+ CRX1_PJ22_MARK, CTX1_PJ23_MARK,
+ CRX2_PJ20_MARK, CTX2_PJ21_MARK,
+ CRX0CRX1_PJ22_MARK,
+ CRX0CRX1CRX2_PJ20_MARK,
+
+ /* VDC */
+ DV_CLK_MARK,
+ DV_VSYNC_MARK, DV_HSYNC_MARK,
+ DV_DATA23_MARK, DV_DATA22_MARK, DV_DATA21_MARK, DV_DATA20_MARK,
+ DV_DATA19_MARK, DV_DATA18_MARK, DV_DATA17_MARK, DV_DATA16_MARK,
+ DV_DATA15_MARK, DV_DATA14_MARK, DV_DATA13_MARK, DV_DATA12_MARK,
+ DV_DATA11_MARK, DV_DATA10_MARK, DV_DATA9_MARK, DV_DATA8_MARK,
+ DV_DATA7_MARK, DV_DATA6_MARK, DV_DATA5_MARK, DV_DATA4_MARK,
+ DV_DATA3_MARK, DV_DATA2_MARK, DV_DATA1_MARK, DV_DATA0_MARK,
+ LCD_CLK_MARK, LCD_EXTCLK_MARK,
+ LCD_VSYNC_MARK, LCD_HSYNC_MARK, LCD_DE_MARK,
+ LCD_DATA23_MARK, LCD_DATA22_MARK, LCD_DATA21_MARK, LCD_DATA20_MARK,
+ LCD_DATA19_MARK, LCD_DATA18_MARK, LCD_DATA17_MARK, LCD_DATA16_MARK,
+ LCD_DATA15_MARK, LCD_DATA14_MARK, LCD_DATA13_MARK, LCD_DATA12_MARK,
+ LCD_DATA11_MARK, LCD_DATA10_MARK, LCD_DATA9_MARK, LCD_DATA8_MARK,
+ LCD_DATA7_MARK, LCD_DATA6_MARK, LCD_DATA5_MARK, LCD_DATA4_MARK,
+ LCD_DATA3_MARK, LCD_DATA2_MARK, LCD_DATA1_MARK, LCD_DATA0_MARK,
+ LCD_TCON6_MARK, LCD_TCON5_MARK, LCD_TCON4_MARK,
+ LCD_TCON3_MARK, LCD_TCON2_MARK, LCD_TCON1_MARK, LCD_TCON0_MARK,
+ LCD_M_DISP_MARK,
+ PINMUX_MARK_END,
+};
+
+static pinmux_enum_t pinmux_data[] = {
+
+ /* Port A */
+ PINMUX_DATA(PA1_DATA, PA1_IN),
+ PINMUX_DATA(PA0_DATA, PA0_IN),
+
+ /* Port B */
+ PINMUX_DATA(PB22_DATA, PB22MD_000, PB22_IN, PB22_OUT),
+ PINMUX_DATA(A22_MARK, PB22MD_001),
+ PINMUX_DATA(CTX2_MARK, PB22MD_010),
+ PINMUX_DATA(IETXD_MARK, PB22MD_011),
+ PINMUX_DATA(CS4_MARK, PB22MD_100),
+
+ PINMUX_DATA(PB21_DATA, PB21MD_00, PB21_IN, PB21_OUT),
+ PINMUX_DATA(A21_MARK, PB21MD_01),
+ PINMUX_DATA(CRX2_MARK, PB21MD_10),
+ PINMUX_DATA(IERXD_MARK, PB21MD_11),
+
+ PINMUX_DATA(A20_MARK, PB20MD_001),
+ PINMUX_DATA(A19_MARK, PB19MD_001),
+ PINMUX_DATA(A18_MARK, PB18MD_001),
+ PINMUX_DATA(A17_MARK, PB17MD_001),
+ PINMUX_DATA(A16_MARK, PB16MD_001),
+ PINMUX_DATA(A15_MARK, PB15MD_001),
+ PINMUX_DATA(A14_MARK, PB14MD_001),
+ PINMUX_DATA(A13_MARK, PB13MD_001),
+ PINMUX_DATA(A12_MARK, PB12MD_01),
+ PINMUX_DATA(A11_MARK, PB11MD_01),
+ PINMUX_DATA(A10_MARK, PB10MD_01),
+ PINMUX_DATA(A9_MARK, PB9MD_01),
+ PINMUX_DATA(A8_MARK, PB8MD_01),
+ PINMUX_DATA(A7_MARK, PB7MD_01),
+ PINMUX_DATA(A6_MARK, PB6MD_01),
+ PINMUX_DATA(A5_MARK, PB5MD_01),
+ PINMUX_DATA(A4_MARK, PB4MD_01),
+ PINMUX_DATA(A3_MARK, PB3MD_01),
+ PINMUX_DATA(A2_MARK, PB2MD_01),
+ PINMUX_DATA(A1_MARK, PB1MD_01),
+
+ /* Port C */
+ PINMUX_DATA(PC8_DATA, PC8MD_000),
+ PINMUX_DATA(CS3_MARK, PC8MD_001),
+ PINMUX_DATA(TXD7_MARK, PC8MD_010),
+ PINMUX_DATA(CTX1_MARK, PC8MD_011),
+
+ PINMUX_DATA(PC7_DATA, PC7MD_000),
+ PINMUX_DATA(CKE_MARK, PC7MD_001),
+ PINMUX_DATA(RXD7_MARK, PC7MD_010),
+ PINMUX_DATA(CRX1_MARK, PC7MD_011),
+ PINMUX_DATA(CRX0CRX1_MARK, PC7MD_100),
+ PINMUX_DATA(IRQ1_PC_MARK, PC7MD_101),
+
+ PINMUX_DATA(PC6_DATA, PC6MD_000),
+ PINMUX_DATA(CAS_MARK, PC6MD_001),
+ PINMUX_DATA(SCK7_MARK, PC6MD_010),
+ PINMUX_DATA(CTX0_MARK, PC6MD_011),
+
+ PINMUX_DATA(PC5_DATA, PC5MD_000),
+ PINMUX_DATA(RAS_MARK, PC5MD_001),
+ PINMUX_DATA(CRX0_MARK, PC5MD_011),
+ PINMUX_DATA(CTX0CTX1CTX2_MARK, PC5MD_100),
+ PINMUX_DATA(IRQ0_PC_MARK, PC5MD_101),
+
+ PINMUX_DATA(PC4_DATA, PC4MD_00),
+ PINMUX_DATA(WE1DQMUWE_MARK, PC4MD_01),
+ PINMUX_DATA(TXD6_MARK, PC4MD_10),
+
+ PINMUX_DATA(PC3_DATA, PC3MD_00),
+ PINMUX_DATA(WE0DQML_MARK, PC3MD_01),
+ PINMUX_DATA(RXD6_MARK, PC3MD_10),
+
+ PINMUX_DATA(PC2_DATA, PC2MD_00),
+ PINMUX_DATA(RDWR_MARK, PC2MD_01),
+ PINMUX_DATA(SCK5_MARK, PC2MD_10),
+
+ PINMUX_DATA(PC1_DATA, PC1MD_0),
+ PINMUX_DATA(RD_MARK, PC1MD_1),
+
+ PINMUX_DATA(PC0_DATA, PC0MD_0),
+ PINMUX_DATA(CS0_MARK, PC0MD_1),
+
+ /* Port D */
+ PINMUX_DATA(D15_MARK, PD15MD_01),
+ PINMUX_DATA(D14_MARK, PD14MD_01),
+
+ PINMUX_DATA(PD13_DATA, PD13MD_00),
+ PINMUX_DATA(D13_MARK, PD13MD_01),
+ PINMUX_DATA(PWM2F_MARK, PD13MD_10),
+
+ PINMUX_DATA(PD12_DATA, PD12MD_00),
+ PINMUX_DATA(D12_MARK, PD12MD_01),
+ PINMUX_DATA(PWM2E_MARK, PD12MD_10),
+
+ PINMUX_DATA(D11_MARK, PD11MD_01),
+ PINMUX_DATA(D10_MARK, PD10MD_01),
+ PINMUX_DATA(D9_MARK, PD9MD_01),
+ PINMUX_DATA(D8_MARK, PD8MD_01),
+ PINMUX_DATA(D7_MARK, PD7MD_01),
+ PINMUX_DATA(D6_MARK, PD6MD_01),
+ PINMUX_DATA(D5_MARK, PD5MD_01),
+ PINMUX_DATA(D4_MARK, PD4MD_01),
+ PINMUX_DATA(D3_MARK, PD3MD_01),
+ PINMUX_DATA(D2_MARK, PD2MD_01),
+ PINMUX_DATA(D1_MARK, PD1MD_01),
+ PINMUX_DATA(D0_MARK, PD0MD_01),
+
+ /* Port E */
+ PINMUX_DATA(PE7_DATA, PE7MD_00),
+ PINMUX_DATA(SDA3_MARK, PE7MD_01),
+ PINMUX_DATA(RXD7_MARK, PE7MD_10),
+
+ PINMUX_DATA(PE6_DATA, PE6MD_00),
+ PINMUX_DATA(SCL3_MARK, PE6MD_01),
+ PINMUX_DATA(RXD6_MARK, PE6MD_10),
+
+ PINMUX_DATA(PE5_DATA, PE5MD_00),
+ PINMUX_DATA(SDA2_MARK, PE5MD_01),
+ PINMUX_DATA(RXD5_MARK, PE5MD_10),
+ PINMUX_DATA(DV_HSYNC_MARK, PE5MD_11),
+
+ PINMUX_DATA(PE4_DATA, PE4MD_00),
+ PINMUX_DATA(SCL2_MARK, PE4MD_01),
+ PINMUX_DATA(DV_VSYNC_MARK, PE4MD_11),
+
+ PINMUX_DATA(PE3_DATA, PE3MD_000),
+ PINMUX_DATA(SDA1_MARK, PE3MD_001),
+ PINMUX_DATA(TCLKD_MARK, PE3MD_010),
+ PINMUX_DATA(ADTRG_MARK, PE3MD_011),
+ PINMUX_DATA(DV_HSYNC_MARK, PE3MD_100),
+
+ PINMUX_DATA(PE2_DATA, PE2MD_000),
+ PINMUX_DATA(SCL1_MARK, PE2MD_001),
+ PINMUX_DATA(TCLKD_MARK, PE2MD_010),
+ PINMUX_DATA(IOIS16_MARK, PE2MD_011),
+ PINMUX_DATA(DV_VSYNC_MARK, PE2MD_100),
+
+ PINMUX_DATA(PE1_DATA, PE1MD_000),
+ PINMUX_DATA(SDA0_MARK, PE1MD_001),
+ PINMUX_DATA(TCLKB_MARK, PE1MD_010),
+ PINMUX_DATA(AUDIO_CLK_MARK, PE1MD_010),
+ PINMUX_DATA(DV_CLK_MARK, PE1MD_100),
+
+ PINMUX_DATA(PE0_DATA, PE0MD_00),
+ PINMUX_DATA(SCL0_MARK, PE0MD_01),
+ PINMUX_DATA(TCLKA_MARK, PE0MD_10),
+ PINMUX_DATA(LCD_EXTCLK_MARK, PE0MD_11),
+
+ /* Port F */
+ PINMUX_DATA(PF23_DATA, PF23MD_000),
+ PINMUX_DATA(SD_D2_MARK, PF23MD_001),
+ PINMUX_DATA(TXD3_MARK, PF23MD_100),
+ PINMUX_DATA(MMC_D2_MARK, PF23MD_101),
+
+ PINMUX_DATA(PF22_DATA, PF22MD_000),
+ PINMUX_DATA(SD_D3_MARK, PF22MD_001),
+ PINMUX_DATA(RXD3_MARK, PF22MD_100),
+ PINMUX_DATA(MMC_D3_MARK, PF22MD_101),
+
+ PINMUX_DATA(PF21_DATA, PF21MD_000),
+ PINMUX_DATA(SD_CMD_MARK, PF21MD_001),
+ PINMUX_DATA(SCK3_MARK, PF21MD_100),
+ PINMUX_DATA(MMC_CMD_MARK, PF21MD_101),
+
+ PINMUX_DATA(PF20_DATA, PF20MD_000),
+ PINMUX_DATA(SD_CLK_MARK, PF20MD_001),
+ PINMUX_DATA(SSIDATA3_MARK, PF20MD_010),
+ PINMUX_DATA(MMC_CLK_MARK, PF20MD_101),
+
+ PINMUX_DATA(PF19_DATA, PF19MD_000),
+ PINMUX_DATA(SD_D0_MARK, PF19MD_001),
+ PINMUX_DATA(SSIWS3_MARK, PF19MD_010),
+ PINMUX_DATA(IRQ7_PF_MARK, PF19MD_100),
+ PINMUX_DATA(MMC_D0_MARK, PF19MD_101),
+
+ PINMUX_DATA(PF18_DATA, PF18MD_000),
+ PINMUX_DATA(SD_D1_MARK, PF18MD_001),
+ PINMUX_DATA(SSISCK3_MARK, PF18MD_010),
+ PINMUX_DATA(IRQ6_PF_MARK, PF18MD_100),
+ PINMUX_DATA(MMC_D1_MARK, PF18MD_101),
+
+ PINMUX_DATA(PF17_DATA, PF17MD_000),
+ PINMUX_DATA(SD_WP_MARK, PF17MD_001),
+ PINMUX_DATA(FRB_MARK, PF17MD_011),
+ PINMUX_DATA(IRQ5_PF_MARK, PF17MD_100),
+
+ PINMUX_DATA(PF16_DATA, PF16MD_000),
+ PINMUX_DATA(SD_CD_MARK, PF16MD_001),
+ PINMUX_DATA(FCE_MARK, PF16MD_011),
+ PINMUX_DATA(IRQ4_PF_MARK, PF16MD_100),
+ PINMUX_DATA(MMC_CD_MARK, PF16MD_101),
+
+ PINMUX_DATA(PF15_DATA, PF15MD_000),
+ PINMUX_DATA(A0_MARK, PF15MD_001),
+ PINMUX_DATA(SSIDATA2_MARK, PF15MD_010),
+ PINMUX_DATA(WDTOVF_MARK, PF15MD_011),
+ PINMUX_DATA(TXD2_MARK, PF15MD_100),
+
+ PINMUX_DATA(PF14_DATA, PF14MD_000),
+ PINMUX_DATA(A25_MARK, PF14MD_001),
+ PINMUX_DATA(SSIWS2_MARK, PF14MD_010),
+ PINMUX_DATA(RXD2_MARK, PF14MD_100),
+
+ PINMUX_DATA(PF13_DATA, PF13MD_000),
+ PINMUX_DATA(A24_MARK, PF13MD_001),
+ PINMUX_DATA(SSISCK2_MARK, PF13MD_010),
+ PINMUX_DATA(SCK2_MARK, PF13MD_100),
+
+ PINMUX_DATA(PF12_DATA, PF12MD_000),
+ PINMUX_DATA(SSIDATA1_MARK, PF12MD_010),
+ PINMUX_DATA(DV_DATA12_MARK, PF12MD_011),
+ PINMUX_DATA(TXD1_MARK, PF12MD_100),
+ PINMUX_DATA(MMC_D7_MARK, PF12MD_101),
+
+ PINMUX_DATA(PF11_DATA, PF11MD_000),
+ PINMUX_DATA(SSIWS1_MARK, PF11MD_010),
+ PINMUX_DATA(DV_DATA2_MARK, PF11MD_011),
+ PINMUX_DATA(RXD1_MARK, PF11MD_100),
+ PINMUX_DATA(MMC_D6_MARK, PF11MD_101),
+
+ PINMUX_DATA(PF10_DATA, PF10MD_000),
+ PINMUX_DATA(CS1_MARK, PF10MD_001),
+ PINMUX_DATA(SSISCK1_MARK, PF10MD_010),
+ PINMUX_DATA(DV_DATA1_MARK, PF10MD_011),
+ PINMUX_DATA(SCK1_MARK, PF10MD_100),
+ PINMUX_DATA(MMC_D5_MARK, PF10MD_101),
+
+ PINMUX_DATA(PF9_DATA, PF9MD_000),
+ PINMUX_DATA(BS_MARK, PF9MD_001),
+ PINMUX_DATA(DV_DATA0_MARK, PF9MD_011),
+ PINMUX_DATA(SCK0_MARK, PF9MD_100),
+ PINMUX_DATA(MMC_D4_MARK, PF9MD_101),
+ PINMUX_DATA(RTS1_MARK, PF9MD_110),
+
+ PINMUX_DATA(PF8_DATA, PF8MD_000),
+ PINMUX_DATA(A23_MARK, PF8MD_001),
+ PINMUX_DATA(TXD0_MARK, PF8MD_100),
+
+ PINMUX_DATA(PF7_DATA, PF7MD_000),
+ PINMUX_DATA(SSIRXD0_MARK, PF7MD_010),
+ PINMUX_DATA(RXD0_MARK, PF7MD_100),
+ PINMUX_DATA(CTS1_MARK, PF7MD_110),
+
+ PINMUX_DATA(PF6_DATA, PF6MD_000),
+ PINMUX_DATA(CE2A_MARK, PF6MD_001),
+ PINMUX_DATA(SSITXD0_MARK, PF6MD_010),
+
+ PINMUX_DATA(PF5_DATA, PF5MD_000),
+ PINMUX_DATA(SSIWS0_MARK, PF5MD_010),
+
+ PINMUX_DATA(PF4_DATA, PF4MD_000),
+ PINMUX_DATA(CS5CE1A_MARK, PF4MD_001),
+ PINMUX_DATA(SSISCK0_MARK, PF4MD_010),
+
+ PINMUX_DATA(PF3_DATA, PF3MD_000),
+ PINMUX_DATA(CS2_MARK, PF3MD_001),
+ PINMUX_DATA(MISO1_MARK, PF3MD_011),
+ PINMUX_DATA(TIOC4D_MARK, PF3MD_100),
+
+ PINMUX_DATA(PF2_DATA, PF2MD_000),
+ PINMUX_DATA(WAIT_MARK, PF2MD_001),
+ PINMUX_DATA(MOSI1_MARK, PF2MD_011),
+ PINMUX_DATA(TIOC4C_MARK, PF2MD_100),
+ PINMUX_DATA(TEND0_MARK, PF2MD_101),
+
+ PINMUX_DATA(PF1_DATA, PF1MD_000),
+ PINMUX_DATA(BACK_MARK, PF1MD_001),
+ PINMUX_DATA(TIOC4B_MARK, PF1MD_100),
+ PINMUX_DATA(DACK0_MARK, PF1MD_101),
+
+ PINMUX_DATA(PF0_DATA, PF0MD_000),
+ PINMUX_DATA(BREQ_MARK, PF0MD_001),
+ PINMUX_DATA(RSPCK1_MARK, PF0MD_011),
+ PINMUX_DATA(TIOC4A_MARK, PF0MD_100),
+ PINMUX_DATA(DREQ0_MARK, PF0MD_101),
+
+ /* Port G */
+ PINMUX_DATA(PG27_DATA, PG27MD_00),
+ PINMUX_DATA(LCD_TCON2_MARK, PG27MD_10),
+ PINMUX_DATA(LCD_EXTCLK_MARK, PG27MD_11),
+
+ PINMUX_DATA(PG26_DATA, PG26MD_00),
+ PINMUX_DATA(LCD_TCON1_MARK, PG26MD_10),
+
+ PINMUX_DATA(PG25_DATA, PG25MD_00),
+ PINMUX_DATA(LCD_TCON0_MARK, PG25MD_10),
+
+ PINMUX_DATA(PG24_DATA, PG24MD_00),
+ PINMUX_DATA(LCD_CLK_MARK, PG24MD_10),
+
+ PINMUX_DATA(PG23_DATA, PG23MD_000),
+ PINMUX_DATA(LCD_DATA23_MARK, PG23MD_010),
+ PINMUX_DATA(LCD_TCON6_MARK, PG23MD_011),
+ PINMUX_DATA(TXD5_MARK, PG23MD_100),
+
+ PINMUX_DATA(PG22_DATA, PG22MD_000),
+ PINMUX_DATA(LCD_DATA22_MARK, PG22MD_010),
+ PINMUX_DATA(LCD_TCON5_MARK, PG22MD_011),
+ PINMUX_DATA(RXD5_MARK, PG22MD_100),
+
+ PINMUX_DATA(PG21_DATA, PG21MD_000),
+ PINMUX_DATA(DV_DATA7_MARK, PG21MD_001),
+ PINMUX_DATA(LCD_DATA21_MARK, PG21MD_010),
+ PINMUX_DATA(LCD_TCON4_MARK, PG21MD_011),
+ PINMUX_DATA(TXD4_MARK, PG21MD_100),
+
+ PINMUX_DATA(PG20_DATA, PG20MD_000),
+ PINMUX_DATA(DV_DATA6_MARK, PG20MD_001),
+ PINMUX_DATA(LCD_DATA20_MARK, PG21MD_010),
+ PINMUX_DATA(LCD_TCON3_MARK, PG20MD_011),
+ PINMUX_DATA(RXD4_MARK, PG20MD_100),
+
+ PINMUX_DATA(PG19_DATA, PG19MD_000),
+ PINMUX_DATA(DV_DATA5_MARK, PG19MD_001),
+ PINMUX_DATA(LCD_DATA19_MARK, PG19MD_010),
+ PINMUX_DATA(SPDIF_OUT_MARK, PG19MD_011),
+ PINMUX_DATA(SCK5_MARK, PG19MD_100),
+
+ PINMUX_DATA(PG18_DATA, PG18MD_000),
+ PINMUX_DATA(DV_DATA4_MARK, PG18MD_001),
+ PINMUX_DATA(LCD_DATA18_MARK, PG18MD_010),
+ PINMUX_DATA(SPDIF_IN_MARK, PG18MD_011),
+ PINMUX_DATA(SCK4_MARK, PG18MD_100),
+
+// TODO hardware manual has PG17 3 bits wide in reg picture and 2 bits in description
+// we're going with 2 bits
+ PINMUX_DATA(PG17_DATA, PG17MD_00),
+ PINMUX_DATA(WE3ICIOWRAHDQMUU_MARK, PG17MD_01),
+ PINMUX_DATA(LCD_DATA17_MARK, PG17MD_10),
+
+// TODO hardware manual has PG16 3 bits wide in reg picture and 2 bits in description
+// we're going with 2 bits
+ PINMUX_DATA(PG16_DATA, PG16MD_00),
+ PINMUX_DATA(WE2ICIORDDQMUL_MARK, PG16MD_01),
+ PINMUX_DATA(LCD_DATA16_MARK, PG16MD_10),
+
+ PINMUX_DATA(PG15_DATA, PG15MD_00),
+ PINMUX_DATA(D31_MARK, PG15MD_01),
+ PINMUX_DATA(LCD_DATA15_MARK, PG15MD_10),
+ PINMUX_DATA(PINT7_PG_MARK, PG15MD_11),
+
+ PINMUX_DATA(PG14_DATA, PG14MD_00),
+ PINMUX_DATA(D30_MARK, PG14MD_01),
+ PINMUX_DATA(LCD_DATA14_MARK, PG14MD_10),
+ PINMUX_DATA(PINT6_PG_MARK, PG14MD_11),
+
+ PINMUX_DATA(PG13_DATA, PG13MD_00),
+ PINMUX_DATA(D29_MARK, PG13MD_01),
+ PINMUX_DATA(LCD_DATA13_MARK, PG13MD_10),
+ PINMUX_DATA(PINT5_PG_MARK, PG13MD_11),
+
+ PINMUX_DATA(PG12_DATA, PG12MD_00),
+ PINMUX_DATA(D28_MARK, PG12MD_01),
+ PINMUX_DATA(LCD_DATA12_MARK, PG12MD_10),
+ PINMUX_DATA(PINT4_PG_MARK, PG12MD_11),
+
+ PINMUX_DATA(PG11_DATA, PG11MD_000),
+ PINMUX_DATA(D27_MARK, PG11MD_001),
+ PINMUX_DATA(LCD_DATA11_MARK, PG11MD_010),
+ PINMUX_DATA(PINT3_PG_MARK, PG11MD_011),
+ PINMUX_DATA(TIOC3D_MARK, PG11MD_100),
+
+ PINMUX_DATA(PG10_DATA, PG10MD_000),
+ PINMUX_DATA(D26_MARK, PG10MD_001),
+ PINMUX_DATA(LCD_DATA10_MARK, PG10MD_010),
+ PINMUX_DATA(PINT2_PG_MARK, PG10MD_011),
+ PINMUX_DATA(TIOC3C_MARK, PG10MD_100),
+
+ PINMUX_DATA(PG9_DATA, PG9MD_000),
+ PINMUX_DATA(D25_MARK, PG9MD_001),
+ PINMUX_DATA(LCD_DATA9_MARK, PG9MD_010),
+ PINMUX_DATA(PINT1_PG_MARK, PG9MD_011),
+ PINMUX_DATA(TIOC3B_MARK, PG9MD_100),
+
+ PINMUX_DATA(PG8_DATA, PG8MD_000),
+ PINMUX_DATA(D24_MARK, PG8MD_001),
+ PINMUX_DATA(LCD_DATA8_MARK, PG8MD_010),
+ PINMUX_DATA(PINT0_PG_MARK, PG8MD_011),
+ PINMUX_DATA(TIOC3A_MARK, PG8MD_100),
+
+ PINMUX_DATA(PG7_DATA, PG7MD_000),
+ PINMUX_DATA(D23_MARK, PG7MD_001),
+ PINMUX_DATA(LCD_DATA7_MARK, PG7MD_010),
+ PINMUX_DATA(IRQ7_PG_MARK, PG7MD_011),
+ PINMUX_DATA(TIOC2B_MARK, PG7MD_100),
+
+ PINMUX_DATA(PG6_DATA, PG6MD_000),
+ PINMUX_DATA(D22_MARK, PG6MD_001),
+ PINMUX_DATA(LCD_DATA6_MARK, PG6MD_010),
+ PINMUX_DATA(IRQ6_PG_MARK, PG6MD_011),
+ PINMUX_DATA(TIOC2A_MARK, PG6MD_100),
+
+ PINMUX_DATA(PG5_DATA, PG5MD_000),
+ PINMUX_DATA(D21_MARK, PG5MD_001),
+ PINMUX_DATA(LCD_DATA5_MARK, PG5MD_010),
+ PINMUX_DATA(IRQ5_PG_MARK, PG5MD_011),
+ PINMUX_DATA(TIOC1B_MARK, PG5MD_100),
+
+ PINMUX_DATA(PG4_DATA, PG4MD_000),
+ PINMUX_DATA(D20_MARK, PG4MD_001),
+ PINMUX_DATA(LCD_DATA4_MARK, PG4MD_010),
+ PINMUX_DATA(IRQ4_PG_MARK, PG4MD_011),
+ PINMUX_DATA(TIOC1A_MARK, PG4MD_100),
+
+ PINMUX_DATA(PG3_DATA, PG3MD_000),
+ PINMUX_DATA(D19_MARK, PG3MD_001),
+ PINMUX_DATA(LCD_DATA3_MARK, PG3MD_010),
+ PINMUX_DATA(IRQ3_PG_MARK, PG3MD_011),
+ PINMUX_DATA(TIOC0D_MARK, PG3MD_100),
+
+ PINMUX_DATA(PG2_DATA, PG2MD_000),
+ PINMUX_DATA(D18_MARK, PG2MD_001),
+ PINMUX_DATA(LCD_DATA2_MARK, PG2MD_010),
+ PINMUX_DATA(IRQ2_PG_MARK, PG2MD_011),
+ PINMUX_DATA(TIOC0C_MARK, PG2MD_100),
+
+ PINMUX_DATA(PG1_DATA, PG1MD_000),
+ PINMUX_DATA(D17_MARK, PG1MD_001),
+ PINMUX_DATA(LCD_DATA1_MARK, PG1MD_010),
+ PINMUX_DATA(IRQ1_PG_MARK, PG1MD_011),
+ PINMUX_DATA(TIOC0B_MARK, PG1MD_100),
+
+ PINMUX_DATA(PG0_DATA, PG0MD_000),
+ PINMUX_DATA(D16_MARK, PG0MD_001),
+ PINMUX_DATA(LCD_DATA0_MARK, PG0MD_010),
+ PINMUX_DATA(IRQ0_PG_MARK, PG0MD_011),
+ PINMUX_DATA(TIOC0A_MARK, PG0MD_100),
+
+ /* Port H */
+ PINMUX_DATA(PH7_DATA, PH7MD_00),
+ PINMUX_DATA(PHAN7_MARK, PH7MD_01),
+ PINMUX_DATA(PINT7_PH_MARK, PH7MD_10),
+
+ PINMUX_DATA(PH6_DATA, PH6MD_00),
+ PINMUX_DATA(PHAN6_MARK, PH6MD_01),
+ PINMUX_DATA(PINT6_PH_MARK, PH6MD_10),
+
+ PINMUX_DATA(PH5_DATA, PH5MD_00),
+ PINMUX_DATA(PHAN5_MARK, PH5MD_01),
+ PINMUX_DATA(PINT5_PH_MARK, PH5MD_10),
+ PINMUX_DATA(LCD_EXTCLK_MARK, PH5MD_11),
+
+ PINMUX_DATA(PH4_DATA, PH4MD_00),
+ PINMUX_DATA(PHAN4_MARK, PH4MD_01),
+ PINMUX_DATA(PINT4_PH_MARK, PH4MD_10),
+
+ PINMUX_DATA(PH3_DATA, PH3MD_00),
+ PINMUX_DATA(PHAN3_MARK, PH3MD_01),
+ PINMUX_DATA(PINT3_PH_MARK, PH3MD_10),
+
+ PINMUX_DATA(PH2_DATA, PH2MD_00),
+ PINMUX_DATA(PHAN2_MARK, PH2MD_01),
+ PINMUX_DATA(PINT2_PH_MARK, PH2MD_10),
+
+ PINMUX_DATA(PH1_DATA, PH1MD_00),
+ PINMUX_DATA(PHAN1_MARK, PH1MD_01),
+ PINMUX_DATA(PINT1_PH_MARK, PH1MD_10),
+
+ PINMUX_DATA(PH0_DATA, PH0MD_00),
+ PINMUX_DATA(PHAN0_MARK, PH0MD_01),
+ PINMUX_DATA(PINT0_PH_MARK, PH0MD_10),
+
+ /* Port I - not on device */
+
+ /* Port J */
+ PINMUX_DATA(PJ31_DATA, PJ31MD_0),
+ PINMUX_DATA(DV_CLK_MARK, PJ31MD_1),
+
+ PINMUX_DATA(PJ30_DATA, PJ30MD_000),
+ PINMUX_DATA(SSIDATA5_MARK, PJ30MD_010),
+ PINMUX_DATA(TIOC2B_MARK, PJ30MD_100),
+ PINMUX_DATA(IETXD_MARK, PJ30MD_101),
+
+ PINMUX_DATA(PJ29_DATA, PJ29MD_000),
+ PINMUX_DATA(SSIWS5_MARK, PJ29MD_010),
+ PINMUX_DATA(TIOC2A_MARK, PJ29MD_100),
+ PINMUX_DATA(IERXD_MARK, PJ29MD_101),
+
+ PINMUX_DATA(PJ28_DATA, PJ28MD_000),
+ PINMUX_DATA(SSISCK5_MARK, PJ28MD_010),
+ PINMUX_DATA(TIOC1B_MARK, PJ28MD_100),
+ PINMUX_DATA(RTS7_MARK, PJ28MD_101),
+
+ PINMUX_DATA(PJ27_DATA, PJ27MD_000),
+ PINMUX_DATA(TIOC1A_MARK, PJ27MD_100),
+ PINMUX_DATA(CTS7_MARK, PJ27MD_101),
+
+ PINMUX_DATA(PJ26_DATA, PJ26MD_000),
+ PINMUX_DATA(SSIDATA4_MARK, PJ26MD_010),
+ PINMUX_DATA(LCD_TCON5_MARK, PJ26MD_011),
+ PINMUX_DATA(TXD7_MARK, PJ26MD_101),
+
+ PINMUX_DATA(PJ25_DATA, PJ25MD_000),
+ PINMUX_DATA(SSIWS4_MARK, PJ25MD_010),
+ PINMUX_DATA(LCD_TCON4_MARK, PJ25MD_011),
+ PINMUX_DATA(SPDIF_OUT_MARK, PJ25MD_100),
+ PINMUX_DATA(RXD7_MARK, PJ25MD_101),
+
+ PINMUX_DATA(PJ24_DATA, PJ24MD_000),
+ PINMUX_DATA(SSISCK4_MARK, PJ24MD_010),
+ PINMUX_DATA(LCD_TCON3_MARK, PJ24MD_011),
+ PINMUX_DATA(SPDIF_IN_MARK, PJ24MD_100),
+ PINMUX_DATA(SCK7_MARK, PJ24MD_101),
+
+ PINMUX_DATA(PJ23_DATA, PJ23MD_000),
+ PINMUX_DATA(DV_DATA23_MARK, PJ23MD_001),
+ PINMUX_DATA(LCD_DATA23_MARK, PJ23MD_010),
+ PINMUX_DATA(LCD_TCON6_MARK, PJ23MD_011),
+ PINMUX_DATA(IRQ3_PJ_MARK, PJ23MD_100),
+ PINMUX_DATA(CTX1_MARK, PJ23MD_101),
+
+ PINMUX_DATA(PJ22_DATA, PJ22MD_000),
+ PINMUX_DATA(DV_DATA22_MARK, PJ22MD_001),
+ PINMUX_DATA(LCD_DATA22_MARK, PJ22MD_010),
+ PINMUX_DATA(LCD_TCON5_MARK, PJ22MD_011),
+ PINMUX_DATA(IRQ2_PJ_MARK, PJ22MD_100),
+ PINMUX_DATA(CRX1_MARK, PJ22MD_101),
+ PINMUX_DATA(CRX0CRX1_MARK, PJ22MD_110),
+
+ PINMUX_DATA(PJ21_DATA, PJ21MD_000),
+ PINMUX_DATA(DV_DATA21_MARK, PJ21MD_001),
+ PINMUX_DATA(LCD_DATA21_MARK, PJ21MD_010),
+ PINMUX_DATA(LCD_TCON4_MARK, PJ21MD_011),
+ PINMUX_DATA(IRQ1_PJ_MARK, PJ21MD_100),
+ PINMUX_DATA(CTX2_MARK, PJ21MD_101),
+
+ PINMUX_DATA(PJ20_DATA, PJ20MD_000),
+ PINMUX_DATA(DV_DATA20_MARK, PJ20MD_001),
+ PINMUX_DATA(LCD_DATA20_MARK, PJ20MD_010),
+ PINMUX_DATA(LCD_TCON3_MARK, PJ20MD_011),
+ PINMUX_DATA(IRQ0_PJ_MARK, PJ20MD_100),
+ PINMUX_DATA(CRX2_MARK, PJ20MD_101),
+ PINMUX_DATA(CRX0CRX1CRX2_PJ20_MARK, PJ20MD_110),
+
+ PINMUX_DATA(PJ19_DATA, PJ19MD_000),
+ PINMUX_DATA(DV_DATA19_MARK, PJ19MD_001),
+ PINMUX_DATA(LCD_DATA19_MARK, PJ19MD_010),
+ PINMUX_DATA(MISO0_PJ19_MARK, PJ19MD_011),
+ PINMUX_DATA(TIOC0D_MARK, PJ19MD_100),
+ PINMUX_DATA(SIOFRXD_MARK, PJ19MD_101),
+ PINMUX_DATA(AUDIO_XOUT_MARK, PJ19MD_110),
+
+ PINMUX_DATA(PJ18_DATA, PJ18MD_000),
+ PINMUX_DATA(DV_DATA18_MARK, PJ18MD_001),
+ PINMUX_DATA(LCD_DATA18_MARK, PJ18MD_010),
+ PINMUX_DATA(MOSI0_PJ18_MARK, PJ18MD_011),
+ PINMUX_DATA(TIOC0C_MARK, PJ18MD_100),
+ PINMUX_DATA(SIOFTXD_MARK, PJ18MD_101),
+
+ PINMUX_DATA(PJ17_DATA, PJ17MD_000),
+ PINMUX_DATA(DV_DATA17_MARK, PJ17MD_001),
+ PINMUX_DATA(LCD_DATA17_MARK, PJ17MD_010),
+ PINMUX_DATA(SSL00_PJ17_MARK, PJ17MD_011),
+ PINMUX_DATA(TIOC0B_MARK, PJ17MD_100),
+ PINMUX_DATA(SIOFSYNC_MARK, PJ17MD_101),
+
+ PINMUX_DATA(PJ16_DATA, PJ16MD_000),
+ PINMUX_DATA(DV_DATA16_MARK, PJ16MD_001),
+ PINMUX_DATA(LCD_DATA16_MARK, PJ16MD_010),
+ PINMUX_DATA(RSPCK0_PJ16_MARK, PJ16MD_011),
+ PINMUX_DATA(TIOC0A_MARK, PJ16MD_100),
+ PINMUX_DATA(SIOFSCK_MARK, PJ16MD_101),
+
+ PINMUX_DATA(PJ15_DATA, PJ15MD_000),
+ PINMUX_DATA(DV_DATA15_MARK, PJ15MD_001),
+ PINMUX_DATA(LCD_DATA15_MARK, PJ15MD_010),
+ PINMUX_DATA(PINT7_PJ_MARK, PJ15MD_011),
+ PINMUX_DATA(PWM2H_MARK, PJ15MD_100),
+ PINMUX_DATA(TXD7_MARK, PJ15MD_101),
+
+ PINMUX_DATA(PJ14_DATA, PJ14MD_000),
+ PINMUX_DATA(DV_DATA14_MARK, PJ14MD_001),
+ PINMUX_DATA(LCD_DATA14_MARK, PJ14MD_010),
+ PINMUX_DATA(PINT6_PJ_MARK, PJ14MD_011),
+ PINMUX_DATA(PWM2G_MARK, PJ14MD_100),
+ PINMUX_DATA(TXD6_MARK, PJ14MD_101),
+
+ PINMUX_DATA(PJ13_DATA, PJ13MD_000),
+ PINMUX_DATA(DV_DATA13_MARK, PJ13MD_001),
+ PINMUX_DATA(LCD_DATA13_MARK, PJ13MD_010),
+ PINMUX_DATA(PINT5_PJ_MARK, PJ13MD_011),
+ PINMUX_DATA(PWM2F_MARK, PJ13MD_100),
+ PINMUX_DATA(TXD5_MARK, PJ13MD_101),
+
+ PINMUX_DATA(PJ12_DATA, PJ12MD_000),
+ PINMUX_DATA(DV_DATA12_MARK, PJ12MD_001),
+ PINMUX_DATA(LCD_DATA12_MARK, PJ12MD_010),
+ PINMUX_DATA(PINT4_PJ_MARK, PJ12MD_011),
+ PINMUX_DATA(PWM2E_MARK, PJ12MD_100),
+ PINMUX_DATA(SCK7_MARK, PJ12MD_101),
+
+ PINMUX_DATA(PJ11_DATA, PJ11MD_000),
+ PINMUX_DATA(DV_DATA11_MARK, PJ11MD_001),
+ PINMUX_DATA(LCD_DATA11_MARK, PJ11MD_010),
+ PINMUX_DATA(PINT3_PJ_MARK, PJ11MD_011),
+ PINMUX_DATA(PWM2D_MARK, PJ11MD_100),
+ PINMUX_DATA(SCK6_MARK, PJ11MD_101),
+
+ PINMUX_DATA(PJ10_DATA, PJ10MD_000),
+ PINMUX_DATA(DV_DATA10_MARK, PJ10MD_001),
+ PINMUX_DATA(LCD_DATA10_MARK, PJ10MD_010),
+ PINMUX_DATA(PINT2_PJ_MARK, PJ10MD_011),
+ PINMUX_DATA(PWM2C_MARK, PJ10MD_100),
+ PINMUX_DATA(SCK5_MARK, PJ10MD_101),
+
+ PINMUX_DATA(PJ9_DATA, PJ9MD_000),
+ PINMUX_DATA(DV_DATA9_MARK, PJ9MD_001),
+ PINMUX_DATA(LCD_DATA9_MARK, PJ9MD_010),
+ PINMUX_DATA(PINT1_PJ_MARK, PJ9MD_011),
+ PINMUX_DATA(PWM2B_MARK, PJ9MD_100),
+ PINMUX_DATA(RTS5_MARK, PJ9MD_101),
+
+ PINMUX_DATA(PJ8_DATA, PJ8MD_000),
+ PINMUX_DATA(DV_DATA8_MARK, PJ8MD_001),
+ PINMUX_DATA(LCD_DATA8_MARK, PJ8MD_010),
+ PINMUX_DATA(PINT0_PJ_MARK, PJ8MD_011),
+ PINMUX_DATA(PWM2A_MARK, PJ8MD_100),
+ PINMUX_DATA(CTS5_MARK, PJ8MD_101),
+
+ PINMUX_DATA(PJ7_DATA, PJ7MD_000),
+ PINMUX_DATA(DV_DATA7_MARK, PJ7MD_001),
+ PINMUX_DATA(LCD_DATA7_MARK, PJ7MD_010),
+ PINMUX_DATA(SD_D2_MARK, PJ7MD_011),
+ PINMUX_DATA(PWM1H_MARK, PJ7MD_100),
+
+ PINMUX_DATA(PJ6_DATA, PJ6MD_000),
+ PINMUX_DATA(DV_DATA6_MARK, PJ6MD_001),
+ PINMUX_DATA(LCD_DATA6_MARK, PJ6MD_010),
+ PINMUX_DATA(SD_D3_MARK, PJ6MD_011),
+ PINMUX_DATA(PWM1G_MARK, PJ6MD_100),
+
+ PINMUX_DATA(PJ5_DATA, PJ5MD_000),
+ PINMUX_DATA(DV_DATA5_MARK, PJ5MD_001),
+ PINMUX_DATA(LCD_DATA5_MARK, PJ5MD_010),
+ PINMUX_DATA(SD_CMD_MARK, PJ5MD_011),
+ PINMUX_DATA(PWM1F_MARK, PJ5MD_100),
+
+ PINMUX_DATA(PJ4_DATA, PJ4MD_000),
+ PINMUX_DATA(DV_DATA4_MARK, PJ4MD_001),
+ PINMUX_DATA(LCD_DATA4_MARK, PJ4MD_010),
+ PINMUX_DATA(SD_CLK_MARK, PJ4MD_011),
+ PINMUX_DATA(PWM1E_MARK, PJ4MD_100),
+
+ PINMUX_DATA(PJ3_DATA, PJ3MD_000),
+ PINMUX_DATA(DV_DATA3_MARK, PJ3MD_001),
+ PINMUX_DATA(LCD_DATA3_MARK, PJ3MD_010),
+ PINMUX_DATA(SD_D0_MARK, PJ3MD_011),
+ PINMUX_DATA(PWM1D_MARK, PJ3MD_100),
+
+ PINMUX_DATA(PJ2_DATA, PJ2MD_000),
+ PINMUX_DATA(DV_DATA2_MARK, PJ2MD_001),
+ PINMUX_DATA(LCD_DATA2_MARK, PJ2MD_010),
+ PINMUX_DATA(SD_D1_MARK, PJ2MD_011),
+ PINMUX_DATA(PWM1C_MARK, PJ2MD_100),
+
+ PINMUX_DATA(PJ1_DATA, PJ1MD_000),
+ PINMUX_DATA(DV_DATA1_MARK, PJ1MD_001),
+ PINMUX_DATA(LCD_DATA1_MARK, PJ1MD_010),
+ PINMUX_DATA(SD_WP_MARK, PJ1MD_011),
+ PINMUX_DATA(PWM1B_MARK, PJ1MD_100),
+
+ PINMUX_DATA(PJ0_DATA, PJ0MD_000),
+ PINMUX_DATA(DV_DATA0_MARK, PJ0MD_001),
+ PINMUX_DATA(LCD_DATA0_MARK, PJ0MD_010),
+ PINMUX_DATA(SD_CD_MARK, PJ0MD_011),
+ PINMUX_DATA(PWM1A_MARK, PJ0MD_100),
+};
+
+static struct pinmux_gpio pinmux_gpios[] = {
+ /* Port A */
+ PINMUX_GPIO(GPIO_PA1, PA1_DATA),
+ PINMUX_GPIO(GPIO_PA0, PA0_DATA),
+
+ /* Port B */
+ PINMUX_GPIO(GPIO_PB22, PB22_DATA),
+ PINMUX_GPIO(GPIO_PB21, PB21_DATA),
+ PINMUX_GPIO(GPIO_PB20, PB20_DATA),
+ PINMUX_GPIO(GPIO_PB19, PB19_DATA),
+ PINMUX_GPIO(GPIO_PB18, PB18_DATA),
+ PINMUX_GPIO(GPIO_PB17, PB17_DATA),
+ PINMUX_GPIO(GPIO_PB16, PB16_DATA),
+ PINMUX_GPIO(GPIO_PB15, PB15_DATA),
+ PINMUX_GPIO(GPIO_PB14, PB14_DATA),
+ PINMUX_GPIO(GPIO_PB13, PB13_DATA),
+ PINMUX_GPIO(GPIO_PB12, PB12_DATA),
+ PINMUX_GPIO(GPIO_PB11, PB11_DATA),
+ PINMUX_GPIO(GPIO_PB10, PB10_DATA),
+ PINMUX_GPIO(GPIO_PB9, PB9_DATA),
+ PINMUX_GPIO(GPIO_PB8, PB8_DATA),
+ PINMUX_GPIO(GPIO_PB7, PB7_DATA),
+ PINMUX_GPIO(GPIO_PB6, PB6_DATA),
+ PINMUX_GPIO(GPIO_PB5, PB5_DATA),
+ PINMUX_GPIO(GPIO_PB4, PB4_DATA),
+ PINMUX_GPIO(GPIO_PB3, PB3_DATA),
+ PINMUX_GPIO(GPIO_PB2, PB2_DATA),
+ PINMUX_GPIO(GPIO_PB1, PB1_DATA),
+
+ /* Port C */
+ PINMUX_GPIO(GPIO_PC8, PC8_DATA),
+ PINMUX_GPIO(GPIO_PC7, PC7_DATA),
+ PINMUX_GPIO(GPIO_PC6, PC6_DATA),
+ PINMUX_GPIO(GPIO_PC5, PC5_DATA),
+ PINMUX_GPIO(GPIO_PC4, PC4_DATA),
+ PINMUX_GPIO(GPIO_PC3, PC3_DATA),
+ PINMUX_GPIO(GPIO_PC2, PC2_DATA),
+ PINMUX_GPIO(GPIO_PC1, PC1_DATA),
+ PINMUX_GPIO(GPIO_PC0, PC0_DATA),
+
+ /* Port D */
+ PINMUX_GPIO(GPIO_PD15, PD15_DATA),
+ PINMUX_GPIO(GPIO_PD14, PD14_DATA),
+ PINMUX_GPIO(GPIO_PD13, PD13_DATA),
+ PINMUX_GPIO(GPIO_PD12, PD12_DATA),
+ PINMUX_GPIO(GPIO_PD11, PD11_DATA),
+ PINMUX_GPIO(GPIO_PD10, PD10_DATA),
+ PINMUX_GPIO(GPIO_PD9, PD9_DATA),
+ PINMUX_GPIO(GPIO_PD8, PD8_DATA),
+ PINMUX_GPIO(GPIO_PD7, PD7_DATA),
+ PINMUX_GPIO(GPIO_PD6, PD6_DATA),
+ PINMUX_GPIO(GPIO_PD5, PD5_DATA),
+ PINMUX_GPIO(GPIO_PD4, PD4_DATA),
+ PINMUX_GPIO(GPIO_PD3, PD3_DATA),
+ PINMUX_GPIO(GPIO_PD2, PD2_DATA),
+ PINMUX_GPIO(GPIO_PD1, PD1_DATA),
+ PINMUX_GPIO(GPIO_PD0, PD0_DATA),
+
+ /* Port E */
+ PINMUX_GPIO(GPIO_PE7, PE7_DATA),
+ PINMUX_GPIO(GPIO_PE6, PE6_DATA),
+ PINMUX_GPIO(GPIO_PE5, PE5_DATA),
+ PINMUX_GPIO(GPIO_PE4, PE4_DATA),
+ PINMUX_GPIO(GPIO_PE3, PE3_DATA),
+ PINMUX_GPIO(GPIO_PE2, PE2_DATA),
+ PINMUX_GPIO(GPIO_PE1, PE1_DATA),
+ PINMUX_GPIO(GPIO_PE0, PE0_DATA),
+
+ /* Port F */
+ PINMUX_GPIO(GPIO_PF23, PF23_DATA),
+ PINMUX_GPIO(GPIO_PF22, PF22_DATA),
+ PINMUX_GPIO(GPIO_PF21, PF21_DATA),
+ PINMUX_GPIO(GPIO_PF20, PF20_DATA),
+ PINMUX_GPIO(GPIO_PF19, PF19_DATA),
+ PINMUX_GPIO(GPIO_PF18, PF18_DATA),
+ PINMUX_GPIO(GPIO_PF17, PF17_DATA),
+ PINMUX_GPIO(GPIO_PF16, PF16_DATA),
+ PINMUX_GPIO(GPIO_PF15, PF15_DATA),
+ PINMUX_GPIO(GPIO_PF14, PF14_DATA),
+ PINMUX_GPIO(GPIO_PF13, PF13_DATA),
+ PINMUX_GPIO(GPIO_PF12, PF12_DATA),
+ PINMUX_GPIO(GPIO_PF11, PF11_DATA),
+ PINMUX_GPIO(GPIO_PF10, PF10_DATA),
+ PINMUX_GPIO(GPIO_PF9, PF9_DATA),
+ PINMUX_GPIO(GPIO_PF8, PF8_DATA),
+ PINMUX_GPIO(GPIO_PF7, PF7_DATA),
+ PINMUX_GPIO(GPIO_PF6, PF6_DATA),
+ PINMUX_GPIO(GPIO_PF5, PF5_DATA),
+ PINMUX_GPIO(GPIO_PF4, PF4_DATA),
+ PINMUX_GPIO(GPIO_PF3, PF3_DATA),
+ PINMUX_GPIO(GPIO_PF2, PF2_DATA),
+ PINMUX_GPIO(GPIO_PF1, PF1_DATA),
+ PINMUX_GPIO(GPIO_PF0, PF0_DATA),
+
+ /* Port G */
+ PINMUX_GPIO(GPIO_PG27, PG27_DATA),
+ PINMUX_GPIO(GPIO_PG26, PG26_DATA),
+ PINMUX_GPIO(GPIO_PG25, PG25_DATA),
+ PINMUX_GPIO(GPIO_PG24, PG24_DATA),
+ PINMUX_GPIO(GPIO_PG23, PG23_DATA),
+ PINMUX_GPIO(GPIO_PG22, PG22_DATA),
+ PINMUX_GPIO(GPIO_PG21, PG21_DATA),
+ PINMUX_GPIO(GPIO_PG20, PG20_DATA),
+ PINMUX_GPIO(GPIO_PG19, PG19_DATA),
+ PINMUX_GPIO(GPIO_PG18, PG18_DATA),
+ PINMUX_GPIO(GPIO_PG17, PG17_DATA),
+ PINMUX_GPIO(GPIO_PG16, PG16_DATA),
+ PINMUX_GPIO(GPIO_PG15, PG15_DATA),
+ PINMUX_GPIO(GPIO_PG14, PG14_DATA),
+ PINMUX_GPIO(GPIO_PG13, PG13_DATA),
+ PINMUX_GPIO(GPIO_PG12, PG12_DATA),
+ PINMUX_GPIO(GPIO_PG11, PG11_DATA),
+ PINMUX_GPIO(GPIO_PG10, PG10_DATA),
+ PINMUX_GPIO(GPIO_PG9, PG9_DATA),
+ PINMUX_GPIO(GPIO_PG8, PG8_DATA),
+ PINMUX_GPIO(GPIO_PG7, PG7_DATA),
+ PINMUX_GPIO(GPIO_PG6, PG6_DATA),
+ PINMUX_GPIO(GPIO_PG5, PG5_DATA),
+ PINMUX_GPIO(GPIO_PG4, PG4_DATA),
+ PINMUX_GPIO(GPIO_PG3, PG3_DATA),
+ PINMUX_GPIO(GPIO_PG2, PG2_DATA),
+ PINMUX_GPIO(GPIO_PG1, PG1_DATA),
+ PINMUX_GPIO(GPIO_PG0, PG0_DATA),
+
+ /* Port H - Port H does not have a Data Register */
+
+ /* Port I - not on device */
+
+ /* Port J */
+ PINMUX_GPIO(GPIO_PJ31, PJ31_DATA),
+ PINMUX_GPIO(GPIO_PJ30, PJ30_DATA),
+ PINMUX_GPIO(GPIO_PJ29, PJ29_DATA),
+ PINMUX_GPIO(GPIO_PJ28, PJ28_DATA),
+ PINMUX_GPIO(GPIO_PJ27, PJ27_DATA),
+ PINMUX_GPIO(GPIO_PJ26, PJ26_DATA),
+ PINMUX_GPIO(GPIO_PJ25, PJ25_DATA),
+ PINMUX_GPIO(GPIO_PJ24, PJ24_DATA),
+ PINMUX_GPIO(GPIO_PJ23, PJ23_DATA),
+ PINMUX_GPIO(GPIO_PJ22, PJ22_DATA),
+ PINMUX_GPIO(GPIO_PJ21, PJ21_DATA),
+ PINMUX_GPIO(GPIO_PJ20, PJ20_DATA),
+ PINMUX_GPIO(GPIO_PJ19, PJ19_DATA),
+ PINMUX_GPIO(GPIO_PJ18, PJ18_DATA),
+ PINMUX_GPIO(GPIO_PJ17, PJ17_DATA),
+ PINMUX_GPIO(GPIO_PJ16, PJ16_DATA),
+ PINMUX_GPIO(GPIO_PJ15, PJ15_DATA),
+ PINMUX_GPIO(GPIO_PJ14, PJ14_DATA),
+ PINMUX_GPIO(GPIO_PJ13, PJ13_DATA),
+ PINMUX_GPIO(GPIO_PJ12, PJ12_DATA),
+ PINMUX_GPIO(GPIO_PJ11, PJ11_DATA),
+ PINMUX_GPIO(GPIO_PJ10, PJ10_DATA),
+ PINMUX_GPIO(GPIO_PJ9, PJ9_DATA),
+ PINMUX_GPIO(GPIO_PJ8, PJ8_DATA),
+ PINMUX_GPIO(GPIO_PJ7, PJ7_DATA),
+ PINMUX_GPIO(GPIO_PJ6, PJ6_DATA),
+ PINMUX_GPIO(GPIO_PJ5, PJ5_DATA),
+ PINMUX_GPIO(GPIO_PJ4, PJ4_DATA),
+ PINMUX_GPIO(GPIO_PJ3, PJ3_DATA),
+ PINMUX_GPIO(GPIO_PJ2, PJ2_DATA),
+ PINMUX_GPIO(GPIO_PJ1, PJ1_DATA),
+ PINMUX_GPIO(GPIO_PJ0, PJ0_DATA),
+
+ /* INTC */
+ PINMUX_GPIO(GPIO_FN_IRQ7_PG, IRQ7_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ6_PG, IRQ6_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ5_PG, IRQ5_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ4_PG, IRQ4_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ3_PG, IRQ3_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ2_PG, IRQ2_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ1_PG, IRQ1_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ0_PG, IRQ0_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ7_PF, IRQ7_PF_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ6_PF, IRQ6_PF_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ5_PF, IRQ5_PF_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ4_PF, IRQ4_PF_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ3_PJ, IRQ3_PJ_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ2_PJ, IRQ2_PJ_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ1_PJ, IRQ1_PJ_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ0_PJ, IRQ0_PJ_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ1_PC, IRQ1_PC_MARK),
+ PINMUX_GPIO(GPIO_FN_IRQ0_PC, IRQ0_PC_MARK),
+
+ PINMUX_GPIO(GPIO_FN_PINT7_PG, PINT7_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT6_PG, PINT6_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT5_PG, PINT5_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT4_PG, PINT4_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT3_PG, PINT3_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT2_PG, PINT2_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT1_PG, PINT1_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT0_PG, PINT0_PG_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT7_PH, PINT7_PH_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT6_PH, PINT6_PH_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT5_PH, PINT5_PH_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT4_PH, PINT4_PH_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT3_PH, PINT3_PH_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT2_PH, PINT2_PH_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT1_PH, PINT1_PH_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT0_PH, PINT0_PH_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT7_PJ, PINT7_PJ_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT6_PJ, PINT6_PJ_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT5_PJ, PINT5_PJ_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT4_PJ, PINT4_PJ_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT3_PJ, PINT3_PJ_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT2_PJ, PINT2_PJ_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT1_PJ, PINT1_PJ_MARK),
+ PINMUX_GPIO(GPIO_FN_PINT0_PJ, PINT0_PJ_MARK),
+
+ /* WDT */
+ PINMUX_GPIO(GPIO_FN_WDTOVF, WDTOVF_MARK),
+
+ /* CAN */
+ PINMUX_GPIO(GPIO_FN_CTX1, CTX1_MARK),
+ PINMUX_GPIO(GPIO_FN_CRX1, CRX1_MARK),
+ PINMUX_GPIO(GPIO_FN_CTX0, CTX0_MARK),
+ PINMUX_GPIO(GPIO_FN_CRX0, CRX0_MARK),
+ PINMUX_GPIO(GPIO_FN_CRX0_CRX1, CRX0CRX1_MARK),
+ PINMUX_GPIO(GPIO_FN_CRX0_CRX1_CRX2, CRX0CRX1CRX2_MARK),
+
+ /* DMAC */
+ PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK),
+ PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
+ PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
+ PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK),
+ PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
+ PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
+
+ /* ADC */
+ PINMUX_GPIO(GPIO_FN_ADTRG, ADTRG_MARK),
+
+ /* BSCh */
+ PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
+ PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
+ PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
+ PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
+ PINMUX_GPIO(GPIO_FN_A21, A21_MARK),
+ PINMUX_GPIO(GPIO_FN_A20, A20_MARK),
+ PINMUX_GPIO(GPIO_FN_A19, A19_MARK),
+ PINMUX_GPIO(GPIO_FN_A18, A18_MARK),
+ PINMUX_GPIO(GPIO_FN_A17, A17_MARK),
+ PINMUX_GPIO(GPIO_FN_A16, A16_MARK),
+ PINMUX_GPIO(GPIO_FN_A15, A15_MARK),
+ PINMUX_GPIO(GPIO_FN_A14, A14_MARK),
+ PINMUX_GPIO(GPIO_FN_A13, A13_MARK),
+ PINMUX_GPIO(GPIO_FN_A12, A12_MARK),
+ PINMUX_GPIO(GPIO_FN_A11, A11_MARK),
+ PINMUX_GPIO(GPIO_FN_A10, A10_MARK),
+ PINMUX_GPIO(GPIO_FN_A9, A9_MARK),
+ PINMUX_GPIO(GPIO_FN_A8, A8_MARK),
+ PINMUX_GPIO(GPIO_FN_A7, A7_MARK),
+ PINMUX_GPIO(GPIO_FN_A6, A6_MARK),
+ PINMUX_GPIO(GPIO_FN_A5, A5_MARK),
+ PINMUX_GPIO(GPIO_FN_A4, A4_MARK),
+ PINMUX_GPIO(GPIO_FN_A3, A3_MARK),
+ PINMUX_GPIO(GPIO_FN_A2, A2_MARK),
+ PINMUX_GPIO(GPIO_FN_A1, A1_MARK),
+ PINMUX_GPIO(GPIO_FN_A0, A0_MARK),
+
+ PINMUX_GPIO(GPIO_FN_D15, D15_MARK),
+ PINMUX_GPIO(GPIO_FN_D14, D14_MARK),
+ PINMUX_GPIO(GPIO_FN_D13, D13_MARK),
+ PINMUX_GPIO(GPIO_FN_D12, D12_MARK),
+ PINMUX_GPIO(GPIO_FN_D11, D11_MARK),
+ PINMUX_GPIO(GPIO_FN_D10, D10_MARK),
+ PINMUX_GPIO(GPIO_FN_D9, D9_MARK),
+ PINMUX_GPIO(GPIO_FN_D8, D8_MARK),
+ PINMUX_GPIO(GPIO_FN_D7, D7_MARK),
+ PINMUX_GPIO(GPIO_FN_D6, D6_MARK),
+ PINMUX_GPIO(GPIO_FN_D5, D5_MARK),
+ PINMUX_GPIO(GPIO_FN_D4, D4_MARK),
+ PINMUX_GPIO(GPIO_FN_D3, D3_MARK),
+ PINMUX_GPIO(GPIO_FN_D2, D2_MARK),
+ PINMUX_GPIO(GPIO_FN_D1, D1_MARK),
+ PINMUX_GPIO(GPIO_FN_D0, D0_MARK),
+
+ PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
+ PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK),
+ PINMUX_GPIO(GPIO_FN_CS3, CS3_MARK),
+ PINMUX_GPIO(GPIO_FN_CS2, CS2_MARK),
+ PINMUX_GPIO(GPIO_FN_CS1, CS1_MARK),
+ PINMUX_GPIO(GPIO_FN_CS0, CS0_MARK),
+ PINMUX_GPIO(GPIO_FN_CS5CE1A, CS5CE1A_MARK),
+ PINMUX_GPIO(GPIO_FN_CE2A, CE2A_MARK),
+ PINMUX_GPIO(GPIO_FN_CE2B, CE2B_MARK),
+ PINMUX_GPIO(GPIO_FN_RD, RD_MARK),
+ PINMUX_GPIO(GPIO_FN_RDWR, RDWR_MARK),
+ PINMUX_GPIO(GPIO_FN_WE3ICIOWRAHDQMUU, WE3ICIOWRAHDQMUU_MARK),
+ PINMUX_GPIO(GPIO_FN_WE2ICIORDDQMUL, WE2ICIORDDQMUL_MARK),
+ PINMUX_GPIO(GPIO_FN_WE1DQMUWE, WE1DQMUWE_MARK),
+ PINMUX_GPIO(GPIO_FN_WE0DQML, WE0DQML_MARK),
+ PINMUX_GPIO(GPIO_FN_RAS, RAS_MARK),
+ PINMUX_GPIO(GPIO_FN_CAS, CAS_MARK),
+ PINMUX_GPIO(GPIO_FN_CKE, CKE_MARK),
+ PINMUX_GPIO(GPIO_FN_WAIT, WAIT_MARK),
+ PINMUX_GPIO(GPIO_FN_BREQ, BREQ_MARK),
+ PINMUX_GPIO(GPIO_FN_BACK, BACK_MARK),
+ PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
+
+ /* TMU */
+ PINMUX_GPIO(GPIO_FN_TIOC4D, TIOC4D_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC4C, TIOC4C_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC4B, TIOC4B_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC4A, TIOC4A_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC3D, TIOC3D_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC3C, TIOC3C_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC3B, TIOC3B_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC3A, TIOC3A_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC2B, TIOC2B_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC1B, TIOC1B_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC2A, TIOC2A_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC1A, TIOC1A_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC0D, TIOC0D_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC0C, TIOC0C_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC0B, TIOC0B_MARK),
+ PINMUX_GPIO(GPIO_FN_TIOC0A, TIOC0A_MARK),
+ PINMUX_GPIO(GPIO_FN_TCLKD, TCLKD_MARK),
+ PINMUX_GPIO(GPIO_FN_TCLKC, TCLKC_MARK),
+ PINMUX_GPIO(GPIO_FN_TCLKB, TCLKB_MARK),
+ PINMUX_GPIO(GPIO_FN_TCLKA, TCLKA_MARK),
+
+ /* SCIF */
+ PINMUX_GPIO(GPIO_FN_SCK0, SCK0_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD0, TXD0_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD0, RXD0_MARK),
+ PINMUX_GPIO(GPIO_FN_SCK1, SCK1_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD1, TXD1_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD1, RXD1_MARK),
+ PINMUX_GPIO(GPIO_FN_RTS1, RTS1_MARK),
+ PINMUX_GPIO(GPIO_FN_CTS1, CTS1_MARK),
+ PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD2, RXD2_MARK),
+ PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD3, TXD3_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD3, RXD3_MARK),
+ PINMUX_GPIO(GPIO_FN_SCK4, SCK4_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD4, TXD4_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD4, RXD4_MARK),
+ PINMUX_GPIO(GPIO_FN_SCK5, SCK5_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD5, TXD5_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD5, RXD5_MARK),
+ PINMUX_GPIO(GPIO_FN_RTS5, RTS5_MARK),
+ PINMUX_GPIO(GPIO_FN_CTS5, CTS5_MARK),
+ PINMUX_GPIO(GPIO_FN_SCK6, SCK6_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD6, TXD6_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD6, RXD6_MARK),
+ PINMUX_GPIO(GPIO_FN_SCK7, SCK7_MARK),
+ PINMUX_GPIO(GPIO_FN_TXD7, TXD7_MARK),
+ PINMUX_GPIO(GPIO_FN_RXD7, RXD7_MARK),
+ PINMUX_GPIO(GPIO_FN_RTS7, RTS7_MARK),
+ PINMUX_GPIO(GPIO_FN_CTS7, CTS7_MARK),
+
+ /* RSPI */
+ PINMUX_GPIO(GPIO_FN_RSPCK0_PJ16, RSPCK0_PJ16_MARK),
+ PINMUX_GPIO(GPIO_FN_SSL00_PJ17, SSL00_PJ17_MARK),
+ PINMUX_GPIO(GPIO_FN_MOSI0_PJ18, MOSI0_PJ18_MARK),
+ PINMUX_GPIO(GPIO_FN_MISO0_PJ19, MISO0_PJ19_MARK),
+ PINMUX_GPIO(GPIO_FN_RSPCK0_PB17, RSPCK0_PB17_MARK),
+ PINMUX_GPIO(GPIO_FN_SSL00_PB18, SSL00_PB18_MARK),
+ PINMUX_GPIO(GPIO_FN_MOSI0_PB19, MOSI0_PB19_MARK),
+ PINMUX_GPIO(GPIO_FN_MISO0_PB20, MISO0_PB20_MARK),
+ PINMUX_GPIO(GPIO_FN_RSPCK1, RSPCK1_MARK),
+ PINMUX_GPIO(GPIO_FN_MOSI1, MOSI1_MARK),
+ PINMUX_GPIO(GPIO_FN_MISO1, MISO1_MARK),
+ PINMUX_GPIO(GPIO_FN_SSL10, SSL10_MARK),
+
+ /* IIC3 */
+ PINMUX_GPIO(GPIO_FN_SCL0, SCL0_MARK),
+ PINMUX_GPIO(GPIO_FN_SCL1, SCL1_MARK),
+ PINMUX_GPIO(GPIO_FN_SCL2, SCL2_MARK),
+ PINMUX_GPIO(GPIO_FN_SDA0, SDA0_MARK),
+ PINMUX_GPIO(GPIO_FN_SDA1, SDA1_MARK),
+ PINMUX_GPIO(GPIO_FN_SDA2, SDA2_MARK),
+
+ /* SSI */
+ PINMUX_GPIO(GPIO_FN_SSISCK0, SSISCK0_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIWS0, SSIWS0_MARK),
+ PINMUX_GPIO(GPIO_FN_SSITXD0, SSITXD0_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIRXD0, SSIRXD0_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIWS1, SSIWS1_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIWS2, SSIWS2_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIWS3, SSIWS3_MARK),
+ PINMUX_GPIO(GPIO_FN_SSISCK1, SSISCK1_MARK),
+ PINMUX_GPIO(GPIO_FN_SSISCK2, SSISCK2_MARK),
+ PINMUX_GPIO(GPIO_FN_SSISCK3, SSISCK3_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIDATA1, SSIDATA1_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIDATA2, SSIDATA2_MARK),
+ PINMUX_GPIO(GPIO_FN_SSIDATA3, SSIDATA3_MARK),
+ PINMUX_GPIO(GPIO_FN_AUDIO_CLK, AUDIO_CLK_MARK),
+ PINMUX_GPIO(GPIO_FN_AUDIO_XOUT, AUDIO_XOUT_MARK),
+
+ /* SIOF */ /* NOTE Shares AUDIO_CLK with SSI */
+ PINMUX_GPIO(GPIO_FN_SIOFTXD, SIOFTXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SIOFRXD, SIOFRXD_MARK),
+ PINMUX_GPIO(GPIO_FN_SIOFSYNC, SIOFSYNC_MARK),
+ PINMUX_GPIO(GPIO_FN_SIOFSCK, SIOFSCK_MARK),
+
+ /* SPDIF */ /* NOTE Shares AUDIO_CLK with SSI */
+ PINMUX_GPIO(GPIO_FN_SPDIF_IN, SPDIF_IN_MARK),
+ PINMUX_GPIO(GPIO_FN_SPDIF_OUT, SPDIF_OUT_MARK),
+
+ /* NANDFMC */ /* NOTE Controller is not available in boot mode 0 */
+ PINMUX_GPIO(GPIO_FN_FCE, FCE_MARK),
+ PINMUX_GPIO(GPIO_FN_FRB, FRB_MARK),
+
+ /* VDC3 */
+ PINMUX_GPIO(GPIO_FN_DV_CLK, DV_CLK_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_VSYNC, DV_VSYNC_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_HSYNC, DV_HSYNC_MARK),
+
+ PINMUX_GPIO(GPIO_FN_DV_DATA23, DV_DATA23_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA22, DV_DATA22_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA21, DV_DATA21_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA20, DV_DATA20_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA19, DV_DATA19_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA18, DV_DATA18_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA17, DV_DATA17_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA16, DV_DATA16_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA15, DV_DATA15_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA14, DV_DATA14_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA13, DV_DATA13_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA12, DV_DATA12_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA11, DV_DATA11_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA10, DV_DATA10_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA9, DV_DATA9_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA8, DV_DATA8_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA7, DV_DATA7_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA6, DV_DATA6_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA5, DV_DATA5_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA4, DV_DATA4_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA3, DV_DATA3_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA2, DV_DATA2_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA1, DV_DATA1_MARK),
+ PINMUX_GPIO(GPIO_FN_DV_DATA0, DV_DATA0_MARK),
+
+ PINMUX_GPIO(GPIO_FN_LCD_CLK, LCD_CLK_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_EXTCLK, LCD_EXTCLK_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_VSYNC, LCD_VSYNC_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_HSYNC, LCD_HSYNC_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DE, LCD_DE_MARK),
+
+ PINMUX_GPIO(GPIO_FN_LCD_DATA23, LCD_DATA23_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA22, LCD_DATA22_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA21, LCD_DATA21_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA20, LCD_DATA20_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA19, LCD_DATA19_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA18, LCD_DATA18_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA17, LCD_DATA17_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA16, LCD_DATA16_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA15, LCD_DATA15_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA14, LCD_DATA14_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA13, LCD_DATA13_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA12, LCD_DATA12_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA11, LCD_DATA11_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA10, LCD_DATA10_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA9, LCD_DATA9_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA8, LCD_DATA8_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA7, LCD_DATA7_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA6, LCD_DATA6_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA5, LCD_DATA5_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA4, LCD_DATA4_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA3, LCD_DATA3_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA2, LCD_DATA2_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA1, LCD_DATA1_MARK),
+ PINMUX_GPIO(GPIO_FN_LCD_DATA0, LCD_DATA0_MARK),
+
+ PINMUX_GPIO(GPIO_FN_LCD_M_DISP, LCD_M_DISP_MARK),
+};
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+ /* "name" addr register_size Field_Width */
+
+ /* where Field_Width is 1 for single mode registers or 4 for upto 16
+ mode registers and modes are described in assending order [0..16] */
+
+ { PINMUX_CFG_REG("PAIOR0", 0xfffe3812, 16, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, PA1_IN, PA1_OUT,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, PA0_IN, PA0_OUT }
+ },
+ { PINMUX_CFG_REG("PBCR5", 0xfffe3824, 16, 4) {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB22MD_000, PB22MD_001, PB22MD_010, PB22MD_011,
+ PB22MD_100, PB22MD_101, PB22MD_110, PB22MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB21MD_00, PB21MD_01, PB21MD_10, PB21MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB20MD_000, PB20MD_001, PB20MD_010, PB20MD_011,
+ PB20MD_100, PB20MD_101, PB20MD_110, PB20MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PBCR4", 0xfffe3826, 16, 4) {
+ PB19MD_000, PB19MD_001, PB19MD_010, PB19MD_011,
+ PB19MD_100, PB19MD_101, PB19MD_110, PB19MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB18MD_000, PB18MD_001, PB18MD_010, PB18MD_011,
+ PB18MD_100, PB18MD_101, PB18MD_110, PB18MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB17MD_000, PB17MD_001, PB17MD_010, PB17MD_011,
+ PB17MD_100, PB17MD_101, PB17MD_110, PB17MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB16MD_000, PB16MD_001, PB16MD_010, PB16MD_011,
+ PB16MD_100, PB16MD_101, PB16MD_110, PB16MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PBCR3", 0xfffe3828, 16, 4) {
+ PB15MD_000, PB15MD_001, PB15MD_010, PB15MD_011,
+ PB15MD_100, PB15MD_101, PB15MD_110, PB15MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB14MD_000, PB14MD_001, PB14MD_010, PB14MD_011,
+ PB14MD_100, PB14MD_101, PB14MD_110, PB14MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB13MD_000, PB13MD_001, PB13MD_010, PB13MD_011,
+ PB13MD_100, PB13MD_101, PB13MD_110, PB13MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB12MD_00, PB12MD_01, PB12MD_10, PB12MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PBCR2", 0xfffe382a, 16, 4) {
+ PB11MD_00, PB11MD_01, PB11MD_10, PB11MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB10MD_00, PB10MD_01, PB10MD_10, PB10MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB9MD_00, PB9MD_01, PB9MD_10, PB9MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB8MD_00, PB8MD_01, PB8MD_10, PB8MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PBCR1", 0xfffe382c, 16, 4) {
+ PB7MD_00, PB7MD_01, PB7MD_10, PB7MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB6MD_00, PB6MD_01, PB6MD_10, PB6MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB5MD_00, PB5MD_01, PB5MD_10, PB5MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB4MD_00, PB4MD_01, PB4MD_10, PB4MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PBCR0", 0xfffe382e, 16, 4) {
+ PB3MD_00, PB3MD_01, PB3MD_10, PB3MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB2MD_00, PB2MD_01, PB2MD_10, PB2MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PB1MD_00, PB1MD_01, PB1MD_10, PB1MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PBIOR1", 0xfffe3830, 16, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,
+ PB22_IN, PB22_OUT,
+ PB21_IN, PB21_OUT,
+ PB20_IN, PB20_OUT,
+ PB19_IN, PB19_OUT,
+ PB18_IN, PB18_OUT,
+ PB17_IN, PB17_OUT,
+ PB16_IN, PB16_OUT }
+ },
+ { PINMUX_CFG_REG("PBIOR0", 0xfffe3832, 16, 1) {
+ PB15_IN, PB15_OUT,
+ PB14_IN, PB14_OUT,
+ PB13_IN, PB13_OUT,
+ PB12_IN, PB12_OUT,
+ PB11_IN, PB11_OUT,
+ PB10_IN, PB10_OUT,
+ PB9_IN, PB9_OUT,
+ PB8_IN, PB8_OUT,
+ PB7_IN, PB7_OUT,
+ PB6_IN, PB6_OUT,
+ PB5_IN, PB5_OUT,
+ PB4_IN, PB4_OUT,
+ PB3_IN, PB3_OUT,
+ PB2_IN, PB2_OUT,
+ PB1_IN, PB1_OUT,
+ 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PCCR2", 0xfffe384a, 16, 4) {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PC8MD_000, PC8MD_001, PC8MD_010, PC8MD_011,
+ PC8MD_100, PC8MD_101, PC8MD_110, PC8MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PCCR1", 0xfffe384c, 16, 4) {
+ PC7MD_000, PC7MD_001, PC7MD_010, PC7MD_011,
+ PC7MD_100, PC7MD_101, PC7MD_110, PC7MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PC6MD_000, PC6MD_001, PC6MD_010, PC6MD_011,
+ PC6MD_100, PC6MD_101, PC6MD_110, PC6MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PC5MD_000, PC5MD_001, PC5MD_010, PC5MD_011,
+ PC5MD_100, PC5MD_101, PC5MD_110, PC5MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PC4MD_00, PC4MD_01, PC4MD_10, PC4MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PCCR0", 0xfffe384e, 16, 4) {
+ PC3MD_00, PC3MD_01, PC3MD_10, PC3MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PC2MD_00, PC2MD_01, PC2MD_10, PC2MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PC1MD_0, PC1MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PC0MD_0, PC0MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PCIOR0", 0xfffe3852, 16, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ PC8_IN, PC8_OUT,
+ PC7_IN, PC7_OUT,
+ PC6_IN, PC6_OUT,
+ PC5_IN, PC5_OUT,
+ PC4_IN, PC4_OUT,
+ PC3_IN, PC3_OUT,
+ PC2_IN, PC2_OUT,
+ PC1_IN, PC1_OUT,
+ PC0_IN, PC0_OUT }
+ },
+
+ { PINMUX_CFG_REG("PDCR3", 0xfffe3868, 16, 4) {
+ PD15MD_00, PD15MD_01, PD15MD_10, PD15MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PD14MD_00, PD14MD_01, PD14MD_10, PD14MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PD13MD_00, PD13MD_01, PD13MD_10, PD13MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PD12MD_00, PD12MD_01, PD12MD_10, PD12MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PDCR2", 0xfffe386a, 16, 4) {
+ PD11MD_00, PD11MD_01, PD11MD_10, PD11MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PD10MD_00, PD10MD_01, PD10MD_10, PD10MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PD9MD_00, PD9MD_01, PD9MD_10, PD9MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PD8MD_00, PD8MD_01, PD8MD_10, PD8MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PDCR1", 0xfffe386c, 16, 4) {
+ PD7MD_00, PD7MD_01, PD7MD_10, PD7MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PD6MD_00, PD6MD_01, PD6MD_10, PD6MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PD5MD_00, PD5MD_01, PD5MD_10, PD5MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PD4MD_00, PD4MD_01, PD4MD_10, PD4MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PDCR0", 0xfffe386e, 16, 4) {
+ PD3MD_00, PD3MD_01, PD3MD_10, PD3MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PD2MD_00, PD2MD_01, PD2MD_10, PD2MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PD1MD_00, PD1MD_01, PD1MD_10, PD1MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PD0MD_00, PD0MD_01, PD0MD_10, PD0MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PDIOR0", 0xfffe3872, 16, 1) {
+ PD15_IN, PD15_OUT,
+ PD14_IN, PD14_OUT,
+ PD13_IN, PD13_OUT,
+ PD12_IN, PD12_OUT,
+ PD11_IN, PD11_OUT,
+ PD10_IN, PD10_OUT,
+ PD9_IN, PD9_OUT,
+ PD8_IN, PD8_OUT,
+ PD7_IN, PD7_OUT,
+ PD6_IN, PD6_OUT,
+ PD5_IN, PD5_OUT,
+ PD4_IN, PD4_OUT,
+ PD3_IN, PD3_OUT,
+ PD2_IN, PD2_OUT,
+ PD1_IN, PD1_OUT,
+ PD0_IN, PD0_OUT }
+ },
+
+ { PINMUX_CFG_REG("PECR1", 0xfffe388c, 16, 4) {
+ PE7MD_00, PE7MD_01, PE7MD_10, PE7MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PE6MD_00, PE6MD_01, PE6MD_10, PE6MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PE5MD_00, PE5MD_01, PE5MD_10, PE5MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PE4MD_00, PE4MD_01, PE4MD_10, PE4MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PECR0", 0xfffe388e, 16, 4) {
+ PE3MD_000, PE3MD_001, PE3MD_010, PE3MD_011,
+ PE3MD_100, PE3MD_101, PE3MD_110, PE3MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PE2MD_000, PE2MD_001, PE2MD_010, PE2MD_011,
+ PE2MD_100, PE2MD_101, PE2MD_110, PE2MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PE1MD_000, PE1MD_001, PE1MD_010, PE1MD_011,
+ PE1MD_100, PE1MD_101, PE1MD_110, PE1MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PE0MD_00, PE0MD_01, PE0MD_10, PE0MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PEIOR0", 0xfffe3892, 16, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PE7_IN, PE7_OUT,
+ PE6_IN, PE6_OUT,
+ PE5_IN, PE5_OUT,
+ PE4_IN, PE4_OUT,
+ PE3_IN, PE3_OUT,
+ PE2_IN, PE2_OUT,
+ PE1_IN, PE1_OUT,
+ PE0_IN, PE0_OUT }
+ },
+
+ { PINMUX_CFG_REG("PFCR6", 0xfffe38a2, 16, 4) {
+ PF23MD_000, PF23MD_001, PF23MD_010, PF23MD_011,
+ PF23MD_100, PF23MD_101, PF23MD_110, PF23MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF22MD_000, PF22MD_001, PF22MD_010, PF22MD_011,
+ PF22MD_100, PF22MD_101, PF22MD_110, PF22MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF21MD_000, PF21MD_001, PF21MD_010, PF21MD_011,
+ PF21MD_100, PF21MD_101, PF21MD_110, PF21MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF20MD_000, PF20MD_001, PF20MD_010, PF20MD_011,
+ PF20MD_100, PF20MD_101, PF20MD_110, PF20MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PFCR5", 0xfffe38a4, 16, 4) {
+ PF19MD_000, PF19MD_001, PF19MD_010, PF19MD_011,
+ PF19MD_100, PF19MD_101, PF19MD_110, PF19MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF18MD_000, PF18MD_001, PF18MD_010, PF18MD_011,
+ PF18MD_100, PF18MD_101, PF18MD_110, PF18MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF17MD_000, PF17MD_001, PF17MD_010, PF17MD_011,
+ PF17MD_100, PF17MD_101, PF17MD_110, PF17MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF16MD_000, PF16MD_001, PF16MD_010, PF16MD_011,
+ PF16MD_100, PF16MD_101, PF16MD_110, PF16MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PFCR4", 0xfffe38a6, 16, 4) {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF15MD_000, PF15MD_001, PF15MD_010, PF15MD_011,
+ PF15MD_100, PF15MD_101, PF15MD_110, PF15MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PFCR3", 0xfffe38a8, 16, 4) {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF14MD_000, PF14MD_001, PF14MD_010, PF14MD_011,
+ PF14MD_100, PF14MD_101, PF14MD_110, PF14MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF13MD_000, PF13MD_001, PF13MD_010, PF13MD_011,
+ PF13MD_100, PF13MD_101, PF13MD_110, PF13MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF12MD_000, PF12MD_001, PF12MD_010, PF12MD_011,
+ PF12MD_100, PF12MD_101, PF12MD_110, PF12MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PFCR2", 0xfffe38aa, 16, 4) {
+ PF11MD_000, PF11MD_001, PF11MD_010, PF11MD_011,
+ PF11MD_100, PF11MD_101, PF11MD_110, PF11MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF10MD_000, PF10MD_001, PF10MD_010, PF10MD_011,
+ PF10MD_100, PF10MD_101, PF10MD_110, PF10MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF9MD_000, PF9MD_001, PF9MD_010, PF9MD_011,
+ PF9MD_100, PF9MD_101, PF9MD_110, PF9MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF8MD_000, PF8MD_001, PF8MD_010, PF8MD_011,
+ PF8MD_100, PF8MD_101, PF8MD_110, PF8MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PFCR1", 0xfffe38ac, 16, 4) {
+ PF7MD_000, PF7MD_001, PF7MD_010, PF7MD_011,
+ PF7MD_100, PF7MD_101, PF7MD_110, PF7MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF6MD_000, PF6MD_001, PF6MD_010, PF6MD_011,
+ PF6MD_100, PF6MD_101, PF6MD_110, PF6MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF5MD_000, PF5MD_001, PF5MD_010, PF5MD_011,
+ PF5MD_100, PF5MD_101, PF5MD_110, PF5MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF4MD_000, PF4MD_001, PF4MD_010, PF4MD_011,
+ PF4MD_100, PF4MD_101, PF4MD_110, PF4MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PFCR0", 0xfffe38ae, 16, 4) {
+ PF3MD_000, PF3MD_001, PF3MD_010, PF3MD_011,
+ PF3MD_100, PF3MD_101, PF3MD_110, PF3MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF2MD_000, PF2MD_001, PF2MD_010, PF2MD_011,
+ PF2MD_100, PF2MD_101, PF2MD_110, PF2MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF1MD_000, PF1MD_001, PF1MD_010, PF1MD_011,
+ PF1MD_100, PF1MD_101, PF1MD_110, PF1MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PF0MD_000, PF0MD_001, PF0MD_010, PF0MD_011,
+ PF0MD_100, PF0MD_101, PF0MD_110, PF0MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PFIOR1", 0xfffe38b0, 16, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PF23_IN, PF23_OUT,
+ PF22_IN, PF22_OUT,
+ PF21_IN, PF21_OUT,
+ PF20_IN, PF20_OUT,
+ PF19_IN, PF19_OUT,
+ PF18_IN, PF18_OUT,
+ PF17_IN, PF17_OUT,
+ PF16_IN, PF16_OUT }
+ },
+ { PINMUX_CFG_REG("PFIOR0", 0xfffe38b2, 16, 1) {
+ PF15_IN, PF15_OUT,
+ PF14_IN, PF14_OUT,
+ PF13_IN, PF13_OUT,
+ PF12_IN, PF12_OUT,
+ PF11_IN, PF11_OUT,
+ PF10_IN, PF10_OUT,
+ PF9_IN, PF9_OUT,
+ PF8_IN, PF8_OUT,
+ PF7_IN, PF7_OUT,
+ PF6_IN, PF6_OUT,
+ PF5_IN, PF5_OUT,
+ PF4_IN, PF4_OUT,
+ PF3_IN, PF3_OUT,
+ PF2_IN, PF2_OUT,
+ PF1_IN, PF1_OUT,
+ PF0_IN, PF0_OUT }
+ },
+
+ { PINMUX_CFG_REG("PGCR6", 0xfffe38c2, 16, 4) {
+ PG27MD_00, PG27MD_01, PG27MD_10, PG27MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG26MD_00, PG26MD_01, PG26MD_10, PG26MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG25MD_00, PG25MD_01, PG25MD_10, PG25MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG24MD_00, PG24MD_01, PG24MD_10, PG24MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PGCR5", 0xfffe38c4, 16, 4) {
+ PG23MD_000, PG23MD_001, PG23MD_010, PG23MD_011,
+ PG23MD_100, PG23MD_101, PG23MD_110, PG23MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG22MD_000, PG22MD_001, PG22MD_010, PG22MD_011,
+ PG22MD_100, PG22MD_101, PG22MD_110, PG22MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG21MD_000, PG21MD_001, PG21MD_010, PG21MD_011,
+ PG21MD_100, PG21MD_101, PG21MD_110, PG21MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG20MD_000, PG20MD_001, PG20MD_010, PG20MD_011,
+ PG20MD_100, PG20MD_101, PG20MD_110, PG20MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PGCR4", 0xfffe38c6, 16, 4) {
+ PG19MD_000, PG19MD_001, PG19MD_010, PG19MD_011,
+ PG19MD_100, PG19MD_101, PG19MD_110, PG19MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG18MD_000, PG18MD_001, PG18MD_010, PG18MD_011,
+ PG18MD_100, PG18MD_101, PG18MD_110, PG18MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG17MD_00, PG17MD_01, PG17MD_10, PG17MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG16MD_00, PG16MD_01, PG16MD_10, PG16MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PGCR3", 0xfffe38c8, 16, 4) {
+ PG15MD_00, PG15MD_01, PG15MD_10, PG15MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG14MD_00, PG14MD_01, PG14MD_10, PG14MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG13MD_00, PG13MD_01, PG13MD_10, PG13MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG12MD_00, PG12MD_01, PG12MD_10, PG12MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PGCR2", 0xfffe38ca, 16, 4) {
+ PG11MD_000, PG11MD_001, PG11MD_010, PG11MD_011,
+ PG11MD_100, PG11MD_101, PG11MD_110, PG11MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG10MD_000, PG10MD_001, PG10MD_010, PG10MD_011,
+ PG10MD_100, PG10MD_101, PG10MD_110, PG10MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG9MD_000, PG9MD_001, PG9MD_010, PG9MD_011,
+ PG9MD_100, PG9MD_101, PG9MD_110, PG9MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG8MD_000, PG8MD_001, PG8MD_010, PG8MD_011,
+ PG8MD_100, PG8MD_101, PG8MD_110, PG8MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PGCR1", 0xfffe38cc, 16, 4) {
+ PG7MD_000, PG7MD_001, PG7MD_010, PG7MD_011,
+ PG7MD_100, PG7MD_101, PG7MD_110, PG7MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG6MD_000, PG6MD_001, PG6MD_010, PG6MD_011,
+ PG6MD_100, PG6MD_101, PG6MD_110, PG6MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG5MD_000, PG5MD_001, PG5MD_010, PG5MD_011,
+ PG5MD_100, PG5MD_101, PG5MD_110, PG5MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG4MD_000, PG4MD_001, PG4MD_010, PG4MD_011,
+ PG4MD_100, PG4MD_101, PG4MD_110, PG4MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PGCR0", 0xfffe38ce, 16, 4) {
+ PG3MD_000, PG3MD_001, PG3MD_010, PG3MD_011,
+ PG3MD_100, PG3MD_101, PG3MD_110, PG3MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG2MD_000, PG2MD_001, PG2MD_010, PG2MD_011,
+ PG2MD_100, PG2MD_101, PG2MD_110, PG2MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG1MD_000, PG1MD_001, PG1MD_010, PG1MD_011,
+ PG1MD_100, PG1MD_101, PG1MD_110, PG1MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PG0MD_000, PG0MD_001, PG0MD_010, PG0MD_011,
+ PG0MD_100, PG0MD_101, PG0MD_110, PG0MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PGIOR1", 0xfffe38d0, 16, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PG27_IN, PG27_OUT,
+ PG26_IN, PG26_OUT,
+ PG25_IN, PG25_OUT,
+ PG24_IN, PG24_OUT,
+ PG23_IN, PG23_OUT,
+ PG22_IN, PG22_OUT,
+ PG21_IN, PG21_OUT,
+ PG20_IN, PG20_OUT,
+ PG19_IN, PG19_OUT,
+ PG18_IN, PG18_OUT,
+ PG17_IN, PG17_OUT,
+ PG16_IN, PG16_OUT }
+ },
+ { PINMUX_CFG_REG("PGIOR0", 0xfffe38d2, 16, 1) {
+ PG15_IN, PG15_OUT,
+ PG14_IN, PG14_OUT,
+ PG13_IN, PG13_OUT,
+ PG12_IN, PG12_OUT,
+ PG11_IN, PG11_OUT,
+ PG10_IN, PG10_OUT,
+ PG9_IN, PG9_OUT,
+ PG8_IN, PG8_OUT,
+ PG7_IN, PG7_OUT,
+ PG6_IN, PG6_OUT,
+ PG5_IN, PG5_OUT,
+ PG4_IN, PG4_OUT,
+ PG3_IN, PG3_OUT,
+ PG2_IN, PG2_OUT,
+ PG1_IN, PG1_OUT,
+ PG0_IN, PG0_OUT }
+ },
+
+ { PINMUX_CFG_REG("PHCR1", 0xfffe38ec, 16, 4) {
+ PH7MD_00, PH7MD_01, PH7MD_10, PH7MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PH6MD_00, PH6MD_01, PH6MD_10, PH6MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PH5MD_00, PH5MD_01, PH5MD_10, PH5MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PH4MD_00, PH4MD_01, PH4MD_10, PH4MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PHCR0", 0xfffe38ee, 16, 4) {
+ PH3MD_00, PH3MD_01, PH3MD_10, PH3MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PH2MD_00, PH2MD_01, PH2MD_10, PH2MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PH1MD_00, PH1MD_01, PH1MD_10, PH1MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PH0MD_00, PH0MD_01, PH0MD_10, PH0MD_11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PJCR7", 0xfffe3900, 16, 4) {
+ PJ31MD_0, PJ31MD_1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ30MD_000, PJ30MD_001, PJ30MD_010, PJ30MD_011,
+ PJ30MD_100, PJ30MD_101, PJ30MD_110, PJ30MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ29MD_000, PJ29MD_001, PJ29MD_010, PJ29MD_011,
+ PJ29MD_100, PJ29MD_101, PJ29MD_110, PJ29MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ28MD_000, PJ28MD_001, PJ28MD_010, PJ28MD_011,
+ PJ28MD_100, PJ28MD_101, PJ28MD_110, PJ28MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PJCR6", 0xfffe3902, 16, 4) {
+ PJ27MD_000, PJ27MD_001, PJ27MD_010, PJ27MD_011,
+ PJ27MD_100, PJ27MD_101, PJ27MD_110, PJ27MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ26MD_000, PJ26MD_001, PJ26MD_010, PJ26MD_011,
+ PJ26MD_100, PJ26MD_101, PJ26MD_110, PJ26MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ25MD_000, PJ25MD_001, PJ25MD_010, PJ25MD_011,
+ PJ25MD_100, PJ25MD_101, PJ25MD_110, PJ25MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ24MD_000, PJ24MD_001, PJ24MD_010, PJ24MD_011,
+ PJ24MD_100, PJ24MD_101, PJ24MD_110, PJ24MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PJCR5", 0xfffe3904, 16, 4) {
+ PJ23MD_000, PJ23MD_001, PJ23MD_010, PJ23MD_011,
+ PJ23MD_100, PJ23MD_101, PJ23MD_110, PJ23MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ22MD_000, PJ22MD_001, PJ22MD_010, PJ22MD_011,
+ PJ22MD_100, PJ22MD_101, PJ22MD_110, PJ22MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ21MD_000, PJ21MD_001, PJ21MD_010, PJ21MD_011,
+ PJ21MD_100, PJ21MD_101, PJ21MD_110, PJ21MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ20MD_000, PJ20MD_001, PJ20MD_010, PJ20MD_011,
+ PJ20MD_100, PJ20MD_101, PJ20MD_110, PJ20MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PJCR4", 0xfffe3906, 16, 4) {
+ PJ19MD_000, PJ19MD_001, PJ19MD_010, PJ19MD_011,
+ PJ19MD_100, PJ19MD_101, PJ19MD_110, PJ19MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ18MD_000, PJ18MD_001, PJ18MD_010, PJ18MD_011,
+ PJ18MD_100, PJ18MD_101, PJ18MD_110, PJ18MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ17MD_000, PJ17MD_001, PJ17MD_010, PJ17MD_011,
+ PJ17MD_100, PJ17MD_101, PJ17MD_110, PJ17MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ16MD_000, PJ16MD_001, PJ16MD_010, PJ16MD_011,
+ PJ16MD_100, PJ16MD_101, PJ16MD_110, PJ16MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PJCR3", 0xfffe3908, 16, 4) {
+ PJ15MD_000, PJ15MD_001, PJ15MD_010, PJ15MD_011,
+ PJ15MD_100, PJ15MD_101, PJ15MD_110, PJ15MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ14MD_000, PJ14MD_001, PJ14MD_010, PJ14MD_011,
+ PJ14MD_100, PJ14MD_101, PJ14MD_110, PJ14MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ13MD_000, PJ13MD_001, PJ13MD_010, PJ13MD_011,
+ PJ13MD_100, PJ13MD_101, PJ13MD_110, PJ13MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ12MD_000, PJ12MD_001, PJ12MD_010, PJ12MD_011,
+ PJ12MD_100, PJ12MD_101, PJ12MD_110, PJ12MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PJCR2", 0xfffe390a, 16, 4) {
+ PJ11MD_000, PJ11MD_001, PJ11MD_010, PJ11MD_011,
+ PJ11MD_100, PJ11MD_101, PJ11MD_110, PJ11MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ10MD_000, PJ10MD_001, PJ10MD_010, PJ10MD_011,
+ PJ10MD_100, PJ10MD_101, PJ10MD_110, PJ10MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ9MD_000, PJ9MD_001, PJ9MD_010, PJ9MD_011,
+ PJ9MD_100, PJ9MD_101, PJ9MD_110, PJ9MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ8MD_000, PJ8MD_001, PJ8MD_010, PJ8MD_011,
+ PJ8MD_100, PJ8MD_101, PJ8MD_110, PJ8MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PJCR1", 0xfffe390c, 16, 4) {
+ PJ7MD_000, PJ7MD_001, PJ7MD_010, PJ7MD_011,
+ PJ7MD_100, PJ7MD_101, PJ7MD_110, PJ7MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ6MD_000, PJ6MD_001, PJ6MD_010, PJ6MD_011,
+ PJ6MD_100, PJ6MD_101, PJ6MD_110, PJ6MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ5MD_000, PJ5MD_001, PJ5MD_010, PJ5MD_011,
+ PJ5MD_100, PJ5MD_101, PJ5MD_110, PJ5MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ4MD_000, PJ4MD_001, PJ4MD_010, PJ4MD_011,
+ PJ4MD_100, PJ4MD_101, PJ4MD_110, PJ4MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG("PJCR0", 0xfffe390e, 16, 4) {
+ PJ3MD_000, PJ3MD_001, PJ3MD_010, PJ3MD_011,
+ PJ3MD_100, PJ3MD_101, PJ3MD_110, PJ3MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ2MD_000, PJ2MD_001, PJ2MD_010, PJ2MD_011,
+ PJ2MD_100, PJ2MD_101, PJ2MD_110, PJ2MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ1MD_000, PJ1MD_001, PJ1MD_010, PJ1MD_011,
+ PJ1MD_100, PJ1MD_101, PJ1MD_110, PJ1MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ PJ0MD_000, PJ0MD_001, PJ0MD_010, PJ0MD_011,
+ PJ0MD_100, PJ0MD_101, PJ0MD_110, PJ0MD_111,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+
+ { PINMUX_CFG_REG("PJIOR1", 0xfffe3910, 16, 1) {
+ PJ31_IN, PJ31_OUT,
+ PJ30_IN, PJ30_OUT,
+ PJ29_IN, PJ29_OUT,
+ PJ28_IN, PJ28_OUT,
+ PJ27_IN, PJ27_OUT,
+ PJ26_IN, PJ26_OUT,
+ PJ25_IN, PJ25_OUT,
+ PJ24_IN, PJ24_OUT,
+ PJ23_IN, PJ23_OUT,
+ PJ22_IN, PJ22_OUT,
+ PJ21_IN, PJ21_OUT,
+ PJ20_IN, PJ20_OUT,
+ PJ19_IN, PJ19_OUT,
+ PJ18_IN, PJ18_OUT,
+ PJ17_IN, PJ17_OUT,
+ PJ16_IN, PJ16_OUT }
+ },
+ { PINMUX_CFG_REG("PJIOR0", 0xfffe3912, 16, 1) {
+ PJ15_IN, PJ15_OUT,
+ PJ14_IN, PJ14_OUT,
+ PJ13_IN, PJ13_OUT,
+ PJ12_IN, PJ12_OUT,
+ PJ11_IN, PJ11_OUT,
+ PJ10_IN, PJ10_OUT,
+ PJ9_IN, PJ9_OUT,
+ PJ8_IN, PJ8_OUT,
+ PJ7_IN, PJ7_OUT,
+ PJ6_IN, PJ6_OUT,
+ PJ5_IN, PJ5_OUT,
+ PJ4_IN, PJ4_OUT,
+ PJ3_IN, PJ3_OUT,
+ PJ2_IN, PJ2_OUT,
+ PJ1_IN, PJ1_OUT,
+ PJ0_IN, PJ0_OUT }
+ },
+
+ {}
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+ { PINMUX_DATA_REG("PADR0", 0xfffe3816, 16) {
+ 0, 0, 0, 0, 0, 0, 0, PA1_DATA,
+ 0, 0, 0, 0, 0, 0, 0, PA0_DATA }
+ },
+
+ { PINMUX_DATA_REG("PBDR1", 0xfffe3834, 16) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, PB22_DATA, PB21_DATA, PB20_DATA,
+ PB19_DATA, PB18_DATA, PB17_DATA, PB16_DATA }
+ },
+ { PINMUX_DATA_REG("PBDR0", 0xfffe3836, 16) {
+ PB15_DATA, PB14_DATA, PB13_DATA, PB12_DATA,
+ PB11_DATA, PB10_DATA, PB9_DATA, PB8_DATA,
+ PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
+ PB3_DATA, PB2_DATA, PB1_DATA, 0 }
+ },
+
+ { PINMUX_DATA_REG("PCDR0", 0xfffe3856, 16) {
+ 0, 0, 0, 0,
+ 0, 0, 0, PC8_DATA,
+ PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
+ PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA }
+ },
+
+ { PINMUX_DATA_REG("PDDR0", 0xfffe3876, 16) {
+ PD15_DATA, PD14_DATA, PD13_DATA, PD12_DATA,
+ PD11_DATA, PD10_DATA, PD9_DATA, PD8_DATA,
+ PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
+ PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA }
+ },
+
+ { PINMUX_DATA_REG("PEDR0", 0xfffe3896, 16) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PE7_DATA, PE6_DATA, PE5_DATA, PE4_DATA,
+ PE3_DATA, PE2_DATA, PE1_DATA, PE0_DATA }
+ },
+
+ { PINMUX_DATA_REG("PFDR1", 0xfffe38b4, 16) {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ PF23_DATA, PF22_DATA, PF21_DATA, PF20_DATA,
+ PF19_DATA, PF18_DATA, PF17_DATA, PF16_DATA }
+ },
+ { PINMUX_DATA_REG("PFDR0", 0xfffe38b6, 16) {
+ PF15_DATA, PF14_DATA, PF13_DATA, PF12_DATA,
+ PF11_DATA, PF10_DATA, PF9_DATA, PF8_DATA,
+ PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
+ PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA }
+ },
+
+ { PINMUX_DATA_REG("PGDR1", 0xfffe38d4, 16) {
+ 0, 0, 0, 0,
+ PG27_DATA, PG26_DATA, PG25_DATA, PG24_DATA,
+ PG23_DATA, PG22_DATA, PG21_DATA, PG20_DATA,
+ PG19_DATA, PG18_DATA, PG17_DATA, PG16_DATA }
+ },
+ { PINMUX_DATA_REG("PGDR0", 0xfffe38d6, 16) {
+ PG15_DATA, PG14_DATA, PG13_DATA, PG12_DATA,
+ PG11_DATA, PG10_DATA, PG9_DATA, PG8_DATA,
+ PG7_DATA, PG6_DATA, PG5_DATA, PG4_DATA,
+ PG3_DATA, PG2_DATA, PG1_DATA, PG0_DATA }
+ },
+
+ { PINMUX_DATA_REG("PJDR1", 0xfffe3914, 16) {
+ PJ31_DATA, PJ30_DATA, PJ29_DATA, PJ28_DATA,
+ PJ27_DATA, PJ26_DATA, PJ25_DATA, PJ24_DATA,
+ PJ23_DATA, PJ22_DATA, PJ21_DATA, PJ20_DATA,
+ PJ19_DATA, PJ18_DATA, PJ17_DATA, PJ16_DATA }
+ },
+ { PINMUX_DATA_REG("PJDR0", 0xfffe3916, 16) {
+ PJ15_DATA, PJ14_DATA, PJ13_DATA, PJ12_DATA,
+ PJ11_DATA, PJ10_DATA, PJ9_DATA, PJ8_DATA,
+ PJ7_DATA, PJ6_DATA, PJ5_DATA, PJ4_DATA,
+ PJ3_DATA, PJ2_DATA, PJ1_DATA, PJ0_DATA }
+ },
+
+ { }
+};
+
+static struct pinmux_info sh7269_pinmux_info = {
+ .name = "sh7269_pfc",
+ .reserved_id = PINMUX_RESERVED,
+ .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+ .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END, FORCE_IN },
+ .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END, FORCE_OUT },
+ .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
+ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+ .first_gpio = GPIO_PA1,
+ .last_gpio = GPIO_FN_LCD_M_DISP,
+
+ .gpios = pinmux_gpios,
+ .cfg_regs = pinmux_config_regs,
+ .data_regs = pinmux_data_regs,
+
+ .gpio_data = pinmux_data,
+ .gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return register_pinmux(&sh7269_pinmux_info);
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c
index 48e97a2a0c8d..5170b6aa4129 100644
--- a/arch/sh/kernel/cpu/sh2a/probe.c
+++ b/arch/sh/kernel/cpu/sh2a/probe.c
@@ -29,6 +29,12 @@ void __cpuinit cpu_probe(void)
#elif defined(CONFIG_CPU_SUBTYPE_SH7263)
boot_cpu_data.type = CPU_SH7263;
boot_cpu_data.flags |= CPU_HAS_FPU;
+#elif defined(CONFIG_CPU_SUBTYPE_SH7264)
+ boot_cpu_data.type = CPU_SH7264;
+ boot_cpu_data.flags |= CPU_HAS_FPU;
+#elif defined(CONFIG_CPU_SUBTYPE_SH7269)
+ boot_cpu_data.type = CPU_SH7269;
+ boot_cpu_data.flags |= CPU_HAS_FPU;
#elif defined(CONFIG_CPU_SUBTYPE_SH7206)
boot_cpu_data.type = CPU_SH7206;
boot_cpu_data.flags |= CPU_HAS_DSP;
diff --git a/arch/sh/kernel/cpu/sh2a/setup-mxg.c b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
index 949bf2bac28c..f7f1cf2af302 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-mxg.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
@@ -204,7 +204,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 220, 220, 220, 220 },
+ .irqs = SCIx_IRQ_MUXED(220),
};
static struct platform_device scif0_device = {
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
index 9df558dcdb86..7b84785b8962 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
@@ -183,7 +183,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 180, 180, 180, 180 }
+ .irqs = SCIx_IRQ_MUXED(180),
};
static struct platform_device scif0_device = {
@@ -200,7 +200,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 184, 184, 184, 184 }
+ .irqs = SCIx_IRQ_MUXED(184),
};
static struct platform_device scif1_device = {
@@ -217,7 +217,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 188, 188, 188, 188 }
+ .irqs = SCIx_IRQ_MUXED(188),
};
static struct platform_device scif2_device = {
@@ -234,7 +234,7 @@ static struct plat_sci_port scif3_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 192, 192, 192, 192 }
+ .irqs = SCIx_IRQ_MUXED(192),
};
static struct platform_device scif3_device = {
@@ -251,7 +251,7 @@ static struct plat_sci_port scif4_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 196, 196, 196, 196 }
+ .irqs = SCIx_IRQ_MUXED(196),
};
static struct platform_device scif4_device = {
@@ -268,7 +268,7 @@ static struct plat_sci_port scif5_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 200, 200, 200, 200 }
+ .irqs = SCIx_IRQ_MUXED(200),
};
static struct platform_device scif5_device = {
@@ -285,7 +285,7 @@ static struct plat_sci_port scif6_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 204, 204, 204, 204 }
+ .irqs = SCIx_IRQ_MUXED(204),
};
static struct platform_device scif6_device = {
@@ -302,7 +302,7 @@ static struct plat_sci_port scif7_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 208, 208, 208, 208 }
+ .irqs = SCIx_IRQ_MUXED(208),
};
static struct platform_device scif7_device = {
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
index 0bd744f9a3b7..bfc33f6a28c3 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
@@ -180,7 +180,7 @@ static struct plat_sci_port scif0_platform_data = {
SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 192, 192, 192, 192 },
+ .irqs = SCIx_IRQ_MUXED(192),
.regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
};
@@ -199,7 +199,7 @@ static struct plat_sci_port scif1_platform_data = {
SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 196, 196, 196, 196 },
+ .irqs = SCIx_IRQ_MUXED(196),
.regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
};
@@ -218,7 +218,7 @@ static struct plat_sci_port scif2_platform_data = {
SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 200, 200, 200, 200 },
+ .irqs = SCIx_IRQ_MUXED(200),
.regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
};
@@ -237,7 +237,7 @@ static struct plat_sci_port scif3_platform_data = {
SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 204, 204, 204, 204 },
+ .irqs = SCIx_IRQ_MUXED(204),
.regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
};
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index 5d14f849aea3..a5010741de85 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -139,7 +139,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 240, 240, 240, 240 },
+ .irqs = SCIx_IRQ_MUXED(240),
};
static struct platform_device scif0_device = {
@@ -156,7 +156,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 244, 244, 244, 244 },
+ .irqs = SCIx_IRQ_MUXED(244),
};
static struct platform_device scif1_device = {
@@ -173,7 +173,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 248, 248, 248, 248 },
+ .irqs = SCIx_IRQ_MUXED(248),
};
static struct platform_device scif2_device = {
@@ -190,7 +190,7 @@ static struct plat_sci_port scif3_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 252, 252, 252, 252 },
+ .irqs = SCIx_IRQ_MUXED(252),
};
static struct platform_device scif3_device = {
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7264.c b/arch/sh/kernel/cpu/sh2a/setup-sh7264.c
new file mode 100644
index 000000000000..ce5c1b5aebfa
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7264.c
@@ -0,0 +1,606 @@
+/*
+ * SH7264 Setup
+ *
+ * Copyright (C) 2012 Renesas Electronics Europe Ltd
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_sci.h>
+#include <linux/usb/r8a66597.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
+
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+ PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7,
+
+ DMAC0, DMAC1, DMAC2, DMAC3, DMAC4, DMAC5, DMAC6, DMAC7,
+ DMAC8, DMAC9, DMAC10, DMAC11, DMAC12, DMAC13, DMAC14, DMAC15,
+ USB, VDC3, CMT0, CMT1, BSC, WDT,
+ MTU0_ABCD, MTU0_VEF, MTU1_AB, MTU1_VU, MTU2_AB, MTU2_VU,
+ MTU3_ABCD, MTU3_TCI3V, MTU4_ABCD, MTU4_TCI4V,
+ PWMT1, PWMT2, ADC_ADI,
+ SSIF0, SSII1, SSII2, SSII3,
+ RSPDIF,
+ IIC30, IIC31, IIC32, IIC33,
+ SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
+ SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI,
+ SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI,
+ SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI,
+ SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI,
+ SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI,
+ SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI,
+ SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI,
+ SIO_FIFO, RSPIC0, RSPIC1,
+ RCAN0, RCAN1, IEBC, CD_ROMD,
+ NFMC, SDHI, RTC,
+ SRCC0, SRCC1, DCOMU, OFFI, IFEI,
+
+ /* interrupt groups */
+ PINT, SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5, SCIF6, SCIF7,
+};
+
+static struct intc_vect vectors[] __initdata = {
+ INTC_IRQ(IRQ0, 64), INTC_IRQ(IRQ1, 65),
+ INTC_IRQ(IRQ2, 66), INTC_IRQ(IRQ3, 67),
+ INTC_IRQ(IRQ4, 68), INTC_IRQ(IRQ5, 69),
+ INTC_IRQ(IRQ6, 70), INTC_IRQ(IRQ7, 71),
+
+ INTC_IRQ(PINT0, 80), INTC_IRQ(PINT1, 81),
+ INTC_IRQ(PINT2, 82), INTC_IRQ(PINT3, 83),
+ INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85),
+ INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87),
+
+ INTC_IRQ(DMAC0, 108), INTC_IRQ(DMAC0, 109),
+ INTC_IRQ(DMAC1, 112), INTC_IRQ(DMAC1, 113),
+ INTC_IRQ(DMAC2, 116), INTC_IRQ(DMAC2, 117),
+ INTC_IRQ(DMAC3, 120), INTC_IRQ(DMAC3, 121),
+ INTC_IRQ(DMAC4, 124), INTC_IRQ(DMAC4, 125),
+ INTC_IRQ(DMAC5, 128), INTC_IRQ(DMAC5, 129),
+ INTC_IRQ(DMAC6, 132), INTC_IRQ(DMAC6, 133),
+ INTC_IRQ(DMAC7, 136), INTC_IRQ(DMAC7, 137),
+ INTC_IRQ(DMAC8, 140), INTC_IRQ(DMAC8, 141),
+ INTC_IRQ(DMAC9, 144), INTC_IRQ(DMAC9, 145),
+ INTC_IRQ(DMAC10, 148), INTC_IRQ(DMAC10, 149),
+ INTC_IRQ(DMAC11, 152), INTC_IRQ(DMAC11, 153),
+ INTC_IRQ(DMAC12, 156), INTC_IRQ(DMAC12, 157),
+ INTC_IRQ(DMAC13, 160), INTC_IRQ(DMAC13, 161),
+ INTC_IRQ(DMAC14, 164), INTC_IRQ(DMAC14, 165),
+ INTC_IRQ(DMAC15, 168), INTC_IRQ(DMAC15, 169),
+
+ INTC_IRQ(USB, 170),
+ INTC_IRQ(VDC3, 171), INTC_IRQ(VDC3, 172),
+ INTC_IRQ(VDC3, 173), INTC_IRQ(VDC3, 174),
+ INTC_IRQ(CMT0, 175), INTC_IRQ(CMT1, 176),
+ INTC_IRQ(BSC, 177), INTC_IRQ(WDT, 178),
+
+ INTC_IRQ(MTU0_ABCD, 179), INTC_IRQ(MTU0_ABCD, 180),
+ INTC_IRQ(MTU0_ABCD, 181), INTC_IRQ(MTU0_ABCD, 182),
+ INTC_IRQ(MTU0_VEF, 183),
+ INTC_IRQ(MTU0_VEF, 184), INTC_IRQ(MTU0_VEF, 185),
+ INTC_IRQ(MTU1_AB, 186), INTC_IRQ(MTU1_AB, 187),
+ INTC_IRQ(MTU1_VU, 188), INTC_IRQ(MTU1_VU, 189),
+ INTC_IRQ(MTU2_AB, 190), INTC_IRQ(MTU2_AB, 191),
+ INTC_IRQ(MTU2_VU, 192), INTC_IRQ(MTU2_VU, 193),
+ INTC_IRQ(MTU3_ABCD, 194), INTC_IRQ(MTU3_ABCD, 195),
+ INTC_IRQ(MTU3_ABCD, 196), INTC_IRQ(MTU3_ABCD, 197),
+ INTC_IRQ(MTU3_TCI3V, 198),
+ INTC_IRQ(MTU4_ABCD, 199), INTC_IRQ(MTU4_ABCD, 200),
+ INTC_IRQ(MTU4_ABCD, 201), INTC_IRQ(MTU4_ABCD, 202),
+ INTC_IRQ(MTU4_TCI4V, 203),
+
+ INTC_IRQ(PWMT1, 204), INTC_IRQ(PWMT2, 205),
+
+ INTC_IRQ(ADC_ADI, 206),
+
+ INTC_IRQ(SSIF0, 207), INTC_IRQ(SSIF0, 208),
+ INTC_IRQ(SSIF0, 209),
+ INTC_IRQ(SSII1, 210), INTC_IRQ(SSII1, 211),
+ INTC_IRQ(SSII2, 212), INTC_IRQ(SSII2, 213),
+ INTC_IRQ(SSII3, 214), INTC_IRQ(SSII3, 215),
+
+ INTC_IRQ(RSPDIF, 216),
+
+ INTC_IRQ(IIC30, 217), INTC_IRQ(IIC30, 218),
+ INTC_IRQ(IIC30, 219), INTC_IRQ(IIC30, 220),
+ INTC_IRQ(IIC30, 221),
+ INTC_IRQ(IIC31, 222), INTC_IRQ(IIC31, 223),
+ INTC_IRQ(IIC31, 224), INTC_IRQ(IIC31, 225),
+ INTC_IRQ(IIC31, 226),
+ INTC_IRQ(IIC32, 227), INTC_IRQ(IIC32, 228),
+ INTC_IRQ(IIC32, 229), INTC_IRQ(IIC32, 230),
+ INTC_IRQ(IIC32, 231),
+
+ INTC_IRQ(SCIF0_BRI, 232), INTC_IRQ(SCIF0_ERI, 233),
+ INTC_IRQ(SCIF0_RXI, 234), INTC_IRQ(SCIF0_TXI, 235),
+ INTC_IRQ(SCIF1_BRI, 236), INTC_IRQ(SCIF1_ERI, 237),
+ INTC_IRQ(SCIF1_RXI, 238), INTC_IRQ(SCIF1_TXI, 239),
+ INTC_IRQ(SCIF2_BRI, 240), INTC_IRQ(SCIF2_ERI, 241),
+ INTC_IRQ(SCIF2_RXI, 242), INTC_IRQ(SCIF2_TXI, 243),
+ INTC_IRQ(SCIF3_BRI, 244), INTC_IRQ(SCIF3_ERI, 245),
+ INTC_IRQ(SCIF3_RXI, 246), INTC_IRQ(SCIF3_TXI, 247),
+ INTC_IRQ(SCIF4_BRI, 248), INTC_IRQ(SCIF4_ERI, 249),
+ INTC_IRQ(SCIF4_RXI, 250), INTC_IRQ(SCIF4_TXI, 251),
+ INTC_IRQ(SCIF5_BRI, 252), INTC_IRQ(SCIF5_ERI, 253),
+ INTC_IRQ(SCIF5_RXI, 254), INTC_IRQ(SCIF5_TXI, 255),
+ INTC_IRQ(SCIF6_BRI, 256), INTC_IRQ(SCIF6_ERI, 257),
+ INTC_IRQ(SCIF6_RXI, 258), INTC_IRQ(SCIF6_TXI, 259),
+ INTC_IRQ(SCIF7_BRI, 260), INTC_IRQ(SCIF7_ERI, 261),
+ INTC_IRQ(SCIF7_RXI, 262), INTC_IRQ(SCIF7_TXI, 263),
+
+ INTC_IRQ(SIO_FIFO, 264),
+
+ INTC_IRQ(RSPIC0, 265), INTC_IRQ(RSPIC0, 266),
+ INTC_IRQ(RSPIC0, 267),
+ INTC_IRQ(RSPIC1, 268), INTC_IRQ(RSPIC1, 269),
+ INTC_IRQ(RSPIC1, 270),
+
+ INTC_IRQ(RCAN0, 271), INTC_IRQ(RCAN0, 272),
+ INTC_IRQ(RCAN0, 273), INTC_IRQ(RCAN0, 274),
+ INTC_IRQ(RCAN0, 275),
+ INTC_IRQ(RCAN1, 276), INTC_IRQ(RCAN1, 277),
+ INTC_IRQ(RCAN1, 278), INTC_IRQ(RCAN1, 279),
+ INTC_IRQ(RCAN1, 280),
+
+ INTC_IRQ(IEBC, 281),
+
+ INTC_IRQ(CD_ROMD, 282), INTC_IRQ(CD_ROMD, 283),
+ INTC_IRQ(CD_ROMD, 284), INTC_IRQ(CD_ROMD, 285),
+ INTC_IRQ(CD_ROMD, 286), INTC_IRQ(CD_ROMD, 287),
+
+ INTC_IRQ(NFMC, 288), INTC_IRQ(NFMC, 289),
+ INTC_IRQ(NFMC, 290), INTC_IRQ(NFMC, 291),
+
+ INTC_IRQ(SDHI, 292), INTC_IRQ(SDHI, 293),
+ INTC_IRQ(SDHI, 294),
+
+ INTC_IRQ(RTC, 296), INTC_IRQ(RTC, 297),
+ INTC_IRQ(RTC, 298),
+
+ INTC_IRQ(SRCC0, 299), INTC_IRQ(SRCC0, 300),
+ INTC_IRQ(SRCC0, 301), INTC_IRQ(SRCC0, 302),
+ INTC_IRQ(SRCC0, 303),
+ INTC_IRQ(SRCC1, 304), INTC_IRQ(SRCC1, 305),
+ INTC_IRQ(SRCC1, 306), INTC_IRQ(SRCC1, 307),
+ INTC_IRQ(SRCC1, 308),
+
+ INTC_IRQ(DCOMU, 310), INTC_IRQ(DCOMU, 311),
+ INTC_IRQ(DCOMU, 312),
+};
+
+static struct intc_group groups[] __initdata = {
+ INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3,
+ PINT4, PINT5, PINT6, PINT7),
+ INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
+ INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI),
+ INTC_GROUP(SCIF2, SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI),
+ INTC_GROUP(SCIF3, SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI),
+ INTC_GROUP(SCIF4, SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI),
+ INTC_GROUP(SCIF5, SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI),
+ INTC_GROUP(SCIF6, SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI),
+ INTC_GROUP(SCIF7, SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI),
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xfffe0818, 0, 16, 4, /* IPR01 */ { IRQ0, IRQ1, IRQ2, IRQ3 } },
+ { 0xfffe081a, 0, 16, 4, /* IPR02 */ { IRQ4, IRQ5, IRQ6, IRQ7 } },
+ { 0xfffe0820, 0, 16, 4, /* IPR05 */ { PINT, 0, 0, 0 } },
+ { 0xfffe0c00, 0, 16, 4, /* IPR06 */ { DMAC0, DMAC1, DMAC2, DMAC3 } },
+ { 0xfffe0c02, 0, 16, 4, /* IPR07 */ { DMAC4, DMAC5, DMAC6, DMAC7 } },
+ { 0xfffe0c04, 0, 16, 4, /* IPR08 */ { DMAC8, DMAC9,
+ DMAC10, DMAC11 } },
+ { 0xfffe0c06, 0, 16, 4, /* IPR09 */ { DMAC12, DMAC13,
+ DMAC14, DMAC15 } },
+ { 0xfffe0c08, 0, 16, 4, /* IPR10 */ { USB, VDC3, CMT0, CMT1 } },
+ { 0xfffe0c0a, 0, 16, 4, /* IPR11 */ { BSC, WDT, MTU0_ABCD, MTU0_VEF } },
+ { 0xfffe0c0c, 0, 16, 4, /* IPR12 */ { MTU1_AB, MTU1_VU,
+ MTU2_AB, MTU2_VU } },
+ { 0xfffe0c0e, 0, 16, 4, /* IPR13 */ { MTU3_ABCD, MTU3_TCI3V,
+ MTU4_ABCD, MTU4_TCI4V } },
+ { 0xfffe0c10, 0, 16, 4, /* IPR14 */ { PWMT1, PWMT2, ADC_ADI, 0 } },
+ { 0xfffe0c12, 0, 16, 4, /* IPR15 */ { SSIF0, SSII1, SSII2, SSII3 } },
+ { 0xfffe0c14, 0, 16, 4, /* IPR16 */ { RSPDIF, IIC30, IIC31, IIC32 } },
+ { 0xfffe0c16, 0, 16, 4, /* IPR17 */ { SCIF0, SCIF1, SCIF2, SCIF3 } },
+ { 0xfffe0c18, 0, 16, 4, /* IPR18 */ { SCIF4, SCIF5, SCIF6, SCIF7 } },
+ { 0xfffe0c1a, 0, 16, 4, /* IPR19 */ { SIO_FIFO, 0, RSPIC0, RSPIC1, } },
+ { 0xfffe0c1c, 0, 16, 4, /* IPR20 */ { RCAN0, RCAN1, IEBC, CD_ROMD } },
+ { 0xfffe0c1e, 0, 16, 4, /* IPR21 */ { NFMC, SDHI, RTC, 0 } },
+ { 0xfffe0c20, 0, 16, 4, /* IPR22 */ { SRCC0, SRCC1, 0, DCOMU } },
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xfffe0808, 0, 16, /* PINTER */
+ { 0, 0, 0, 0, 0, 0, 0, 0,
+ PINT7, PINT6, PINT5, PINT4, PINT3, PINT2, PINT1, PINT0 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7264", vectors, groups,
+ mask_registers, prio_registers, NULL);
+
+static struct plat_sci_port scif0_platform_data = {
+ .mapbase = 0xfffe8000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 233, 234, 235, 232 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .mapbase = 0xfffe8800,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 237, 238, 239, 236 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .mapbase = 0xfffe9000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 241, 242, 243, 240 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .mapbase = 0xfffe9800,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 245, 246, 247, 244 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .mapbase = 0xfffea000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 249, 250, 251, 248 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 4,
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct plat_sci_port scif5_platform_data = {
+ .mapbase = 0xfffea800,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 253, 254, 255, 252 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif5_device = {
+ .name = "sh-sci",
+ .id = 5,
+ .dev = {
+ .platform_data = &scif5_platform_data,
+ },
+};
+
+static struct plat_sci_port scif6_platform_data = {
+ .mapbase = 0xfffeb000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 257, 258, 259, 256 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif6_device = {
+ .name = "sh-sci",
+ .id = 6,
+ .dev = {
+ .platform_data = &scif6_platform_data,
+ },
+};
+
+static struct plat_sci_port scif7_platform_data = {
+ .mapbase = 0xfffeb800,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 261, 262, 263, 260 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif7_device = {
+ .name = "sh-sci",
+ .id = 7,
+ .dev = {
+ .platform_data = &scif7_platform_data,
+ },
+};
+
+static struct sh_timer_config cmt0_platform_data = {
+ .channel_offset = 0x02,
+ .timer_bit = 0,
+ .clockevent_rating = 125,
+ .clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt0_resources[] = {
+ [0] = {
+ .name = "CMT0",
+ .start = 0xfffec002,
+ .end = 0xfffec007,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 175,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device cmt0_device = {
+ .name = "sh_cmt",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt0_platform_data,
+ },
+ .resource = cmt0_resources,
+ .num_resources = ARRAY_SIZE(cmt0_resources),
+};
+
+static struct sh_timer_config cmt1_platform_data = {
+ .name = "CMT1",
+ .channel_offset = 0x08,
+ .timer_bit = 1,
+ .clockevent_rating = 125,
+ .clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt1_resources[] = {
+ [0] = {
+ .name = "CMT1",
+ .start = 0xfffec008,
+ .end = 0xfffec00d,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 176,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device cmt1_device = {
+ .name = "sh_cmt",
+ .id = 1,
+ .dev = {
+ .platform_data = &cmt1_platform_data,
+ },
+ .resource = cmt1_resources,
+ .num_resources = ARRAY_SIZE(cmt1_resources),
+};
+
+static struct sh_timer_config mtu2_0_platform_data = {
+ .name = "MTU2_0",
+ .channel_offset = -0x80,
+ .timer_bit = 0,
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_0_resources[] = {
+ [0] = {
+ .name = "MTU2_0",
+ .start = 0xfffe4300,
+ .end = 0xfffe4326,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 179,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_0_device = {
+ .name = "sh_mtu2",
+ .id = 0,
+ .dev = {
+ .platform_data = &mtu2_0_platform_data,
+ },
+ .resource = mtu2_0_resources,
+ .num_resources = ARRAY_SIZE(mtu2_0_resources),
+};
+
+static struct sh_timer_config mtu2_1_platform_data = {
+ .name = "MTU2_1",
+ .channel_offset = -0x100,
+ .timer_bit = 1,
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_1_resources[] = {
+ [0] = {
+ .name = "MTU2_1",
+ .start = 0xfffe4380,
+ .end = 0xfffe4390,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 186,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_1_device = {
+ .name = "sh_mtu2",
+ .id = 1,
+ .dev = {
+ .platform_data = &mtu2_1_platform_data,
+ },
+ .resource = mtu2_1_resources,
+ .num_resources = ARRAY_SIZE(mtu2_1_resources),
+};
+
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = 0xfffe6000,
+ .end = 0xfffe6000 + 0x30 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ /* Shared Period/Carry/Alarm IRQ */
+ .start = 296,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+/* USB Host */
+static void usb_port_power(int port, int power)
+{
+ __raw_writew(0x200 , 0xffffc0c2) ; /* Initialise UACS25 */
+}
+
+static struct r8a66597_platdata r8a66597_data = {
+ .on_chip = 1,
+ .endian = 1,
+ .port_power = usb_port_power,
+};
+
+static struct resource r8a66597_usb_host_resources[] = {
+ [0] = {
+ .start = 0xffffc000,
+ .end = 0xffffc0e4,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 170,
+ .end = 170,
+ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+ },
+};
+
+static struct platform_device r8a66597_usb_host_device = {
+ .name = "r8a66597_hcd",
+ .id = 0,
+ .dev = {
+ .dma_mask = NULL, /* not use dma */
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &r8a66597_data,
+ },
+ .num_resources = ARRAY_SIZE(r8a66597_usb_host_resources),
+ .resource = r8a66597_usb_host_resources,
+};
+
+static struct platform_device *sh7264_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &cmt0_device,
+ &cmt1_device,
+ &mtu2_0_device,
+ &mtu2_1_device,
+ &rtc_device,
+ &r8a66597_usb_host_device,
+};
+
+static int __init sh7264_devices_setup(void)
+{
+ return platform_add_devices(sh7264_devices,
+ ARRAY_SIZE(sh7264_devices));
+}
+arch_initcall(sh7264_devices_setup);
+
+void __init plat_irq_setup(void)
+{
+ register_intc_controller(&intc_desc);
+}
+
+static struct platform_device *sh7264_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &cmt0_device,
+ &cmt1_device,
+ &mtu2_0_device,
+ &mtu2_1_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7264_early_devices,
+ ARRAY_SIZE(sh7264_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7269.c b/arch/sh/kernel/cpu/sh2a/setup-sh7269.c
new file mode 100644
index 000000000000..e82ae9d8d3bc
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7269.c
@@ -0,0 +1,615 @@
+/*
+ * SH7269 Setup
+ *
+ * Copyright (C) 2012 Renesas Electronics Europe Ltd
+ * Copyright (C) 2012 Phil Edworthy
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_sci.h>
+#include <linux/usb/r8a66597.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
+
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+ PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7,
+
+ DMAC0, DMAC1, DMAC2, DMAC3, DMAC4, DMAC5, DMAC6, DMAC7,
+ DMAC8, DMAC9, DMAC10, DMAC11, DMAC12, DMAC13, DMAC14, DMAC15,
+ USB, VDC4, CMT0, CMT1, BSC, WDT,
+ MTU0_ABCD, MTU0_VEF, MTU1_AB, MTU1_VU, MTU2_AB, MTU2_VU,
+ MTU3_ABCD, MTU3_TCI3V, MTU4_ABCD, MTU4_TCI4V,
+ PWMT1, PWMT2, ADC_ADI,
+ SSIF0, SSII1, SSII2, SSII3, SSII4, SSII5,
+ RSPDIF,
+ IIC30, IIC31, IIC32, IIC33,
+ SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
+ SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI,
+ SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI,
+ SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI,
+ SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI,
+ SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI,
+ SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI,
+ SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI,
+ RCAN0, RCAN1, RCAN2,
+ RSPIC0, RSPIC1,
+ IEBC, CD_ROMD,
+ NFMC,
+ SDHI0, SDHI1,
+ RTC,
+ SRCC0, SRCC1, SRCC2,
+
+ /* interrupt groups */
+ PINT, SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5, SCIF6, SCIF7,
+};
+
+static struct intc_vect vectors[] __initdata = {
+ INTC_IRQ(IRQ0, 64), INTC_IRQ(IRQ1, 65),
+ INTC_IRQ(IRQ2, 66), INTC_IRQ(IRQ3, 67),
+ INTC_IRQ(IRQ4, 68), INTC_IRQ(IRQ5, 69),
+ INTC_IRQ(IRQ6, 70), INTC_IRQ(IRQ7, 71),
+
+ INTC_IRQ(PINT0, 80), INTC_IRQ(PINT1, 81),
+ INTC_IRQ(PINT2, 82), INTC_IRQ(PINT3, 83),
+ INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85),
+ INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87),
+
+ INTC_IRQ(DMAC0, 108), INTC_IRQ(DMAC0, 109),
+ INTC_IRQ(DMAC1, 112), INTC_IRQ(DMAC1, 113),
+ INTC_IRQ(DMAC2, 116), INTC_IRQ(DMAC2, 117),
+ INTC_IRQ(DMAC3, 120), INTC_IRQ(DMAC3, 121),
+ INTC_IRQ(DMAC4, 124), INTC_IRQ(DMAC4, 125),
+ INTC_IRQ(DMAC5, 128), INTC_IRQ(DMAC5, 129),
+ INTC_IRQ(DMAC6, 132), INTC_IRQ(DMAC6, 133),
+ INTC_IRQ(DMAC7, 136), INTC_IRQ(DMAC7, 137),
+ INTC_IRQ(DMAC8, 140), INTC_IRQ(DMAC8, 141),
+ INTC_IRQ(DMAC9, 144), INTC_IRQ(DMAC9, 145),
+ INTC_IRQ(DMAC10, 148), INTC_IRQ(DMAC10, 149),
+ INTC_IRQ(DMAC11, 152), INTC_IRQ(DMAC11, 153),
+ INTC_IRQ(DMAC12, 156), INTC_IRQ(DMAC12, 157),
+ INTC_IRQ(DMAC13, 160), INTC_IRQ(DMAC13, 161),
+ INTC_IRQ(DMAC14, 164), INTC_IRQ(DMAC14, 165),
+ INTC_IRQ(DMAC15, 168), INTC_IRQ(DMAC15, 169),
+
+ INTC_IRQ(USB, 170),
+
+ INTC_IRQ(VDC4, 171), INTC_IRQ(VDC4, 172),
+ INTC_IRQ(VDC4, 173), INTC_IRQ(VDC4, 174),
+ INTC_IRQ(VDC4, 175), INTC_IRQ(VDC4, 176),
+ INTC_IRQ(VDC4, 177), INTC_IRQ(VDC4, 177),
+
+ INTC_IRQ(CMT0, 188), INTC_IRQ(CMT1, 189),
+
+ INTC_IRQ(BSC, 190), INTC_IRQ(WDT, 191),
+
+ INTC_IRQ(MTU0_ABCD, 192), INTC_IRQ(MTU0_ABCD, 193),
+ INTC_IRQ(MTU0_ABCD, 194), INTC_IRQ(MTU0_ABCD, 195),
+ INTC_IRQ(MTU0_VEF, 196), INTC_IRQ(MTU0_VEF, 197),
+ INTC_IRQ(MTU0_VEF, 198),
+ INTC_IRQ(MTU1_AB, 199), INTC_IRQ(MTU1_AB, 200),
+ INTC_IRQ(MTU1_VU, 201), INTC_IRQ(MTU1_VU, 202),
+ INTC_IRQ(MTU2_AB, 203), INTC_IRQ(MTU2_AB, 204),
+ INTC_IRQ(MTU2_VU, 205), INTC_IRQ(MTU2_VU, 206),
+ INTC_IRQ(MTU3_ABCD, 207), INTC_IRQ(MTU3_ABCD, 208),
+ INTC_IRQ(MTU3_ABCD, 209), INTC_IRQ(MTU3_ABCD, 210),
+ INTC_IRQ(MTU3_TCI3V, 211),
+ INTC_IRQ(MTU4_ABCD, 212), INTC_IRQ(MTU4_ABCD, 213),
+ INTC_IRQ(MTU4_ABCD, 214), INTC_IRQ(MTU4_ABCD, 215),
+ INTC_IRQ(MTU4_TCI4V, 216),
+
+ INTC_IRQ(PWMT1, 217), INTC_IRQ(PWMT2, 218),
+
+ INTC_IRQ(ADC_ADI, 223),
+
+ INTC_IRQ(SSIF0, 224), INTC_IRQ(SSIF0, 225),
+ INTC_IRQ(SSIF0, 226),
+ INTC_IRQ(SSII1, 227), INTC_IRQ(SSII1, 228),
+ INTC_IRQ(SSII2, 229), INTC_IRQ(SSII2, 230),
+ INTC_IRQ(SSII3, 231), INTC_IRQ(SSII3, 232),
+ INTC_IRQ(SSII4, 233), INTC_IRQ(SSII4, 234),
+ INTC_IRQ(SSII5, 235), INTC_IRQ(SSII5, 236),
+
+ INTC_IRQ(RSPDIF, 237),
+
+ INTC_IRQ(IIC30, 238), INTC_IRQ(IIC30, 239),
+ INTC_IRQ(IIC30, 240), INTC_IRQ(IIC30, 241),
+ INTC_IRQ(IIC30, 242),
+ INTC_IRQ(IIC31, 243), INTC_IRQ(IIC31, 244),
+ INTC_IRQ(IIC31, 245), INTC_IRQ(IIC31, 246),
+ INTC_IRQ(IIC31, 247),
+ INTC_IRQ(IIC32, 248), INTC_IRQ(IIC32, 249),
+ INTC_IRQ(IIC32, 250), INTC_IRQ(IIC32, 251),
+ INTC_IRQ(IIC32, 252),
+ INTC_IRQ(IIC33, 253), INTC_IRQ(IIC33, 254),
+ INTC_IRQ(IIC33, 255), INTC_IRQ(IIC33, 256),
+ INTC_IRQ(IIC33, 257),
+
+ INTC_IRQ(SCIF0_BRI, 258), INTC_IRQ(SCIF0_ERI, 259),
+ INTC_IRQ(SCIF0_RXI, 260), INTC_IRQ(SCIF0_TXI, 261),
+ INTC_IRQ(SCIF1_BRI, 262), INTC_IRQ(SCIF1_ERI, 263),
+ INTC_IRQ(SCIF1_RXI, 264), INTC_IRQ(SCIF1_TXI, 265),
+ INTC_IRQ(SCIF2_BRI, 266), INTC_IRQ(SCIF2_ERI, 267),
+ INTC_IRQ(SCIF2_RXI, 268), INTC_IRQ(SCIF2_TXI, 269),
+ INTC_IRQ(SCIF3_BRI, 270), INTC_IRQ(SCIF3_ERI, 271),
+ INTC_IRQ(SCIF3_RXI, 272), INTC_IRQ(SCIF3_TXI, 273),
+ INTC_IRQ(SCIF4_BRI, 274), INTC_IRQ(SCIF4_ERI, 275),
+ INTC_IRQ(SCIF4_RXI, 276), INTC_IRQ(SCIF4_TXI, 277),
+ INTC_IRQ(SCIF5_BRI, 278), INTC_IRQ(SCIF5_ERI, 279),
+ INTC_IRQ(SCIF5_RXI, 280), INTC_IRQ(SCIF5_TXI, 281),
+ INTC_IRQ(SCIF6_BRI, 282), INTC_IRQ(SCIF6_ERI, 283),
+ INTC_IRQ(SCIF6_RXI, 284), INTC_IRQ(SCIF6_TXI, 285),
+ INTC_IRQ(SCIF7_BRI, 286), INTC_IRQ(SCIF7_ERI, 287),
+ INTC_IRQ(SCIF7_RXI, 288), INTC_IRQ(SCIF7_TXI, 289),
+
+ INTC_IRQ(RCAN0, 291), INTC_IRQ(RCAN0, 292),
+ INTC_IRQ(RCAN0, 293), INTC_IRQ(RCAN0, 294),
+ INTC_IRQ(RCAN0, 295),
+ INTC_IRQ(RCAN1, 296), INTC_IRQ(RCAN1, 297),
+ INTC_IRQ(RCAN1, 298), INTC_IRQ(RCAN1, 299),
+ INTC_IRQ(RCAN1, 300),
+ INTC_IRQ(RCAN2, 301), INTC_IRQ(RCAN2, 302),
+ INTC_IRQ(RCAN2, 303), INTC_IRQ(RCAN2, 304),
+ INTC_IRQ(RCAN2, 305),
+
+ INTC_IRQ(RSPIC0, 306), INTC_IRQ(RSPIC0, 307),
+ INTC_IRQ(RSPIC0, 308),
+ INTC_IRQ(RSPIC1, 309), INTC_IRQ(RSPIC1, 310),
+ INTC_IRQ(RSPIC1, 311),
+
+ INTC_IRQ(IEBC, 318),
+
+ INTC_IRQ(CD_ROMD, 319), INTC_IRQ(CD_ROMD, 320),
+ INTC_IRQ(CD_ROMD, 321), INTC_IRQ(CD_ROMD, 322),
+ INTC_IRQ(CD_ROMD, 323), INTC_IRQ(CD_ROMD, 324),
+
+ INTC_IRQ(NFMC, 325), INTC_IRQ(NFMC, 326),
+ INTC_IRQ(NFMC, 327), INTC_IRQ(NFMC, 328),
+
+ INTC_IRQ(SDHI0, 332), INTC_IRQ(SDHI0, 333),
+ INTC_IRQ(SDHI0, 334),
+ INTC_IRQ(SDHI1, 335), INTC_IRQ(SDHI1, 336),
+ INTC_IRQ(SDHI1, 337),
+
+ INTC_IRQ(RTC, 338), INTC_IRQ(RTC, 339),
+ INTC_IRQ(RTC, 340),
+
+ INTC_IRQ(SRCC0, 341), INTC_IRQ(SRCC0, 342),
+ INTC_IRQ(SRCC0, 343), INTC_IRQ(SRCC0, 344),
+ INTC_IRQ(SRCC0, 345),
+ INTC_IRQ(SRCC1, 346), INTC_IRQ(SRCC1, 347),
+ INTC_IRQ(SRCC1, 348), INTC_IRQ(SRCC1, 349),
+ INTC_IRQ(SRCC1, 350),
+ INTC_IRQ(SRCC2, 351), INTC_IRQ(SRCC2, 352),
+ INTC_IRQ(SRCC2, 353), INTC_IRQ(SRCC2, 354),
+ INTC_IRQ(SRCC2, 355),
+};
+
+static struct intc_group groups[] __initdata = {
+ INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3,
+ PINT4, PINT5, PINT6, PINT7),
+ INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
+ INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI),
+ INTC_GROUP(SCIF2, SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI),
+ INTC_GROUP(SCIF3, SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI),
+ INTC_GROUP(SCIF4, SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI),
+ INTC_GROUP(SCIF5, SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI),
+ INTC_GROUP(SCIF6, SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI),
+ INTC_GROUP(SCIF7, SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI),
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xfffe0818, 0, 16, 4, /* IPR01 */ { IRQ0, IRQ1, IRQ2, IRQ3 } },
+ { 0xfffe081a, 0, 16, 4, /* IPR02 */ { IRQ4, IRQ5, IRQ6, IRQ7 } },
+ { 0xfffe0820, 0, 16, 4, /* IPR05 */ { PINT, 0, 0, 0 } },
+ { 0xfffe0c00, 0, 16, 4, /* IPR06 */ { DMAC0, DMAC1, DMAC2, DMAC3 } },
+ { 0xfffe0c02, 0, 16, 4, /* IPR07 */ { DMAC4, DMAC5, DMAC6, DMAC7 } },
+ { 0xfffe0c04, 0, 16, 4, /* IPR08 */ { DMAC8, DMAC9,
+ DMAC10, DMAC11 } },
+ { 0xfffe0c06, 0, 16, 4, /* IPR09 */ { DMAC12, DMAC13,
+ DMAC14, DMAC15 } },
+ { 0xfffe0c08, 0, 16, 4, /* IPR10 */ { USB, VDC4, VDC4, VDC4 } },
+ { 0xfffe0c0a, 0, 16, 4, /* IPR11 */ { 0, 0, 0, 0 } },
+ { 0xfffe0c0c, 0, 16, 4, /* IPR12 */ { CMT0, CMT1, BSC, WDT } },
+ { 0xfffe0c0e, 0, 16, 4, /* IPR13 */ { MTU0_ABCD, MTU0_VEF,
+ MTU1_AB, MTU1_VU } },
+ { 0xfffe0c10, 0, 16, 4, /* IPR14 */ { MTU2_AB, MTU2_VU,
+ MTU3_ABCD, MTU3_TCI3V } },
+ { 0xfffe0c12, 0, 16, 4, /* IPR15 */ { MTU4_ABCD, MTU4_TCI4V,
+ PWMT1, PWMT2 } },
+ { 0xfffe0c14, 0, 16, 4, /* IPR16 */ { 0, 0, 0, 0 } },
+ { 0xfffe0c16, 0, 16, 4, /* IPR17 */ { ADC_ADI, SSIF0, SSII1, SSII2 } },
+ { 0xfffe0c18, 0, 16, 4, /* IPR18 */ { SSII3, SSII4, SSII5, RSPDIF} },
+ { 0xfffe0c1a, 0, 16, 4, /* IPR19 */ { IIC30, IIC31, IIC32, IIC33 } },
+ { 0xfffe0c1c, 0, 16, 4, /* IPR20 */ { SCIF0, SCIF1, SCIF2, SCIF3 } },
+ { 0xfffe0c1e, 0, 16, 4, /* IPR21 */ { SCIF4, SCIF5, SCIF6, SCIF7 } },
+ { 0xfffe0c20, 0, 16, 4, /* IPR22 */ { 0, RCAN0, RCAN1, RCAN2 } },
+ { 0xfffe0c22, 0, 16, 4, /* IPR23 */ { RSPIC0, RSPIC1, 0, 0 } },
+ { 0xfffe0c24, 0, 16, 4, /* IPR24 */ { IEBC, CD_ROMD, NFMC, 0 } },
+ { 0xfffe0c26, 0, 16, 4, /* IPR25 */ { SDHI0, SDHI1, RTC, 0 } },
+ { 0xfffe0c28, 0, 16, 4, /* IPR26 */ { SRCC0, SRCC1, SRCC2, 0 } },
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xfffe0808, 0, 16, /* PINTER */
+ { 0, 0, 0, 0, 0, 0, 0, 0,
+ PINT7, PINT6, PINT5, PINT4, PINT3, PINT2, PINT1, PINT0 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7269", vectors, groups,
+ mask_registers, prio_registers, NULL);
+
+static struct plat_sci_port scif0_platform_data = {
+ .mapbase = 0xe8007000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 259, 260, 261, 258 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .mapbase = 0xe8007800,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 263, 264, 265, 262 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .mapbase = 0xe8008000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 267, 268, 269, 266 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .mapbase = 0xe8008800,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 271, 272, 273, 270 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .mapbase = 0xe8009000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 275, 276, 277, 274 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 4,
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct plat_sci_port scif5_platform_data = {
+ .mapbase = 0xe8009800,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 279, 280, 281, 278 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif5_device = {
+ .name = "sh-sci",
+ .id = 5,
+ .dev = {
+ .platform_data = &scif5_platform_data,
+ },
+};
+
+static struct plat_sci_port scif6_platform_data = {
+ .mapbase = 0xe800a000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 283, 284, 285, 282 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif6_device = {
+ .name = "sh-sci",
+ .id = 6,
+ .dev = {
+ .platform_data = &scif6_platform_data,
+ },
+};
+
+static struct plat_sci_port scif7_platform_data = {
+ .mapbase = 0xe800a800,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { 287, 288, 289, 286 },
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct platform_device scif7_device = {
+ .name = "sh-sci",
+ .id = 7,
+ .dev = {
+ .platform_data = &scif7_platform_data,
+ },
+};
+
+static struct sh_timer_config cmt0_platform_data = {
+ .channel_offset = 0x02,
+ .timer_bit = 0,
+ .clockevent_rating = 125,
+ .clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt0_resources[] = {
+ [0] = {
+ .start = 0xfffec002,
+ .end = 0xfffec007,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 188,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device cmt0_device = {
+ .name = "sh_cmt",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt0_platform_data,
+ },
+ .resource = cmt0_resources,
+ .num_resources = ARRAY_SIZE(cmt0_resources),
+};
+
+static struct sh_timer_config cmt1_platform_data = {
+ .channel_offset = 0x08,
+ .timer_bit = 1,
+ .clockevent_rating = 125,
+ .clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt1_resources[] = {
+ [0] = {
+ .start = 0xfffec008,
+ .end = 0xfffec00d,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 189,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device cmt1_device = {
+ .name = "sh_cmt",
+ .id = 1,
+ .dev = {
+ .platform_data = &cmt1_platform_data,
+ },
+ .resource = cmt1_resources,
+ .num_resources = ARRAY_SIZE(cmt1_resources),
+};
+
+static struct sh_timer_config mtu2_0_platform_data = {
+ .channel_offset = -0x80,
+ .timer_bit = 0,
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_0_resources[] = {
+ [0] = {
+ .start = 0xfffe4300,
+ .end = 0xfffe4326,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 192,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_0_device = {
+ .name = "sh_mtu2",
+ .id = 0,
+ .dev = {
+ .platform_data = &mtu2_0_platform_data,
+ },
+ .resource = mtu2_0_resources,
+ .num_resources = ARRAY_SIZE(mtu2_0_resources),
+};
+
+static struct sh_timer_config mtu2_1_platform_data = {
+ .channel_offset = -0x100,
+ .timer_bit = 1,
+ .clockevent_rating = 200,
+};
+
+static struct resource mtu2_1_resources[] = {
+ [0] = {
+ .start = 0xfffe4380,
+ .end = 0xfffe4390,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 203,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mtu2_1_device = {
+ .name = "sh_mtu2",
+ .id = 1,
+ .dev = {
+ .platform_data = &mtu2_1_platform_data,
+ },
+ .resource = mtu2_1_resources,
+ .num_resources = ARRAY_SIZE(mtu2_1_resources),
+};
+
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = 0xfffe6000,
+ .end = 0xfffe6000 + 0x30 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ /* Shared Period/Carry/Alarm IRQ */
+ .start = 338,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+/* USB Host */
+static struct r8a66597_platdata r8a66597_data = {
+ .on_chip = 1,
+ .endian = 1,
+};
+
+static struct resource r8a66597_usb_host_resources[] = {
+ [0] = {
+ .start = 0xe8010000,
+ .end = 0xe80100e4,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 170,
+ .end = 170,
+ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+ },
+};
+
+static struct platform_device r8a66597_usb_host_device = {
+ .name = "r8a66597_hcd",
+ .id = 0,
+ .dev = {
+ .dma_mask = NULL, /* not use dma */
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &r8a66597_data,
+ },
+ .num_resources = ARRAY_SIZE(r8a66597_usb_host_resources),
+ .resource = r8a66597_usb_host_resources,
+};
+
+static struct platform_device *sh7269_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &cmt0_device,
+ &cmt1_device,
+ &mtu2_0_device,
+ &mtu2_1_device,
+ &rtc_device,
+ &r8a66597_usb_host_device,
+};
+
+static int __init sh7269_devices_setup(void)
+{
+ return platform_add_devices(sh7269_devices,
+ ARRAY_SIZE(sh7269_devices));
+}
+arch_initcall(sh7269_devices_setup);
+
+void __init plat_irq_setup(void)
+{
+ register_intc_controller(&intc_desc);
+}
+
+static struct platform_device *sh7269_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &cmt0_device,
+ &cmt1_device,
+ &mtu2_0_device,
+ &mtu2_1_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7269_early_devices,
+ ARRAY_SIZE(sh7269_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index f6a389c996cb..262db6ec067b 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -2,7 +2,7 @@
* arch/sh/kernel/cpu/sh3/entry.S
*
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
- * Copyright (C) 2003 - 2006 Paul Mundt
+ * Copyright (C) 2003 - 2012 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -17,6 +17,7 @@
#include <cpu/mmu_context.h>
#include <asm/page.h>
#include <asm/cache.h>
+#include <asm/thread_info.h>
! NOTE:
! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
@@ -114,22 +115,22 @@ ENTRY(tlb_miss_load)
.align 2
ENTRY(tlb_miss_store)
bra call_handle_tlbmiss
- mov #1, r5
+ mov #FAULT_CODE_WRITE, r5
.align 2
ENTRY(initial_page_write)
bra call_handle_tlbmiss
- mov #2, r5
+ mov #FAULT_CODE_INITIAL, r5
.align 2
ENTRY(tlb_protection_violation_load)
bra call_do_page_fault
- mov #0, r5
+ mov #FAULT_CODE_PROT, r5
.align 2
ENTRY(tlb_protection_violation_store)
bra call_do_page_fault
- mov #1, r5
+ mov #(FAULT_CODE_PROT | FAULT_CODE_WRITE), r5
call_handle_tlbmiss:
mov.l 1f, r0
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
index 2309618c015d..03e4c96f2b11 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
@@ -14,6 +14,7 @@
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <asm/rtc.h>
#include <cpu/serial.h>
@@ -75,7 +76,7 @@ static struct plat_sci_port scif0_platform_data = {
SCSCR_RE | SCSCR_CKE1 | SCSCR_CKE0,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIF,
- .irqs = { 56, 56, 56 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x900)),
.ops = &sh770x_sci_port_ops,
.regtype = SCIx_SH7705_SCIF_REGTYPE,
};
@@ -94,7 +95,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_TIE | SCSCR_RIE | SCSCR_TE | SCSCR_RE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIF,
- .irqs = { 52, 52, 52 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x880)),
.ops = &sh770x_sci_port_ops,
.regtype = SCIx_SH7705_SCIF_REGTYPE,
};
@@ -114,7 +115,7 @@ static struct resource rtc_resources[] = {
.flags = IORESOURCE_IO,
},
[1] = {
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -146,7 +147,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -174,7 +175,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -201,7 +202,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c
index 3f3d5fe5892d..ba26cd9ce69b 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c
@@ -19,6 +19,7 @@
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <cpu/serial.h>
enum {
@@ -95,7 +96,7 @@ static struct resource rtc_resources[] = {
.flags = IORESOURCE_IO,
},
[1] = {
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -114,7 +115,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_TE | SCSCR_RE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCI,
- .irqs = { 23, 23, 23, 0 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x4e0)),
.ops = &sh770x_sci_port_ops,
.regshift = 1,
};
@@ -135,7 +136,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_TE | SCSCR_RE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 56, 56, 56, 56 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x900)),
.ops = &sh770x_sci_port_ops,
.regtype = SCIx_SH3_SCIF_REGTYPE,
};
@@ -157,7 +158,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_TE | SCSCR_RE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_IRDA,
- .irqs = { 52, 52, 52, 52 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x880)),
.ops = &sh770x_sci_port_ops,
.regshift = 1,
};
@@ -184,7 +185,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -212,7 +213,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -239,7 +240,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
index 78f6b01d42c3..93c9c5e24a7a 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
@@ -14,6 +14,7 @@
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <asm/rtc.h>
enum {
@@ -77,7 +78,7 @@ static struct resource rtc_resources[] = {
.flags = IORESOURCE_IO,
},
[1] = {
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -103,7 +104,7 @@ static struct plat_sci_port scif0_platform_data = {
SCSCR_CKE1 | SCSCR_CKE0,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 52, 52, 52, 52 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x880)),
};
static struct platform_device scif0_device = {
@@ -121,7 +122,7 @@ static struct plat_sci_port scif1_platform_data = {
SCSCR_CKE1 | SCSCR_CKE0,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 56, 56, 56, 56 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x900)),
};
static struct platform_device scif1_device = {
@@ -145,7 +146,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -173,7 +174,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -200,7 +201,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
index 94920345c14d..0c2f1b2c2e19 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
@@ -19,6 +19,7 @@
#include <linux/io.h>
#include <linux/serial_sci.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <asm/rtc.h>
#include <cpu/serial.h>
@@ -30,7 +31,7 @@ static struct resource rtc_resources[] = {
},
[1] = {
/* Shared Period/Carry/Alarm IRQ */
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -55,7 +56,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIF,
- .irqs = { 80, 80, 80, 80 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc00)),
.ops = &sh7720_sci_port_ops,
.regtype = SCIx_SH7705_SCIF_REGTYPE,
};
@@ -74,7 +75,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIF,
- .irqs = { 81, 81, 81, 81 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc20)),
.ops = &sh7720_sci_port_ops,
.regtype = SCIx_SH7705_SCIF_REGTYPE,
};
@@ -94,13 +95,14 @@ static struct resource usb_ohci_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 67,
- .end = 67,
+ .start = evt2irq(0xa60),
+ .end = evt2irq(0xa60),
.flags = IORESOURCE_IRQ,
},
};
static u64 usb_ohci_dma_mask = 0xffffffffUL;
+
static struct platform_device usb_ohci_device = {
.name = "sh_ohci",
.id = -1,
@@ -121,8 +123,8 @@ static struct resource usbf_resources[] = {
},
[1] = {
.name = "sh_udc",
- .start = 65,
- .end = 65,
+ .start = evt2irq(0xa20),
+ .end = evt2irq(0xa20),
.flags = IORESOURCE_IRQ,
},
};
@@ -152,7 +154,7 @@ static struct resource cmt0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 104,
+ .start = evt2irq(0xf00),
.flags = IORESOURCE_IRQ,
},
};
@@ -179,7 +181,7 @@ static struct resource cmt1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 104,
+ .start = evt2irq(0xf00),
.flags = IORESOURCE_IRQ,
},
};
@@ -206,7 +208,7 @@ static struct resource cmt2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 104,
+ .start = evt2irq(0xf00),
.flags = IORESOURCE_IRQ,
},
};
@@ -233,7 +235,7 @@ static struct resource cmt3_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 104,
+ .start = evt2irq(0xf00),
.flags = IORESOURCE_IRQ,
},
};
@@ -260,7 +262,7 @@ static struct resource cmt4_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 104,
+ .start = evt2irq(0xf00),
.flags = IORESOURCE_IRQ,
},
};
@@ -288,7 +290,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -316,7 +318,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -343,7 +345,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 971cf0fce4f5..0fbbd50bc8ad 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -158,6 +158,9 @@ void __cpuinit cpu_probe(void)
case 0x40: /* yon-ten-go */
boot_cpu_data.type = CPU_SH7372;
break;
+ case 0xE0: /* 0x4E0 */
+ boot_cpu_data.type = CPU_SH7734; /* SH7733/SH7734 */
+ break;
}
break;
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
index 5b2833159b7d..2a5320aa73bb 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
@@ -13,6 +13,7 @@
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <linux/io.h>
static struct plat_sci_port scif0_platform_data = {
@@ -21,7 +22,10 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 40, 41, 43, 42 },
+ .irqs = { evt2irq(0x700),
+ evt2irq(0x720),
+ evt2irq(0x760),
+ evt2irq(0x740) },
};
static struct platform_device scif0_device = {
@@ -45,7 +49,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -73,7 +77,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -100,7 +104,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index 98cc0c794c76..04a45512596f 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -13,6 +13,7 @@
#include <linux/serial.h>
#include <linux/io.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <linux/serial_sci.h>
#include <generated/machtypes.h>
@@ -24,7 +25,7 @@ static struct resource rtc_resources[] = {
},
[1] = {
/* Shared Period/Carry/Alarm IRQ */
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -43,7 +44,7 @@ static struct plat_sci_port sci_platform_data = {
.scscr = SCSCR_TE | SCSCR_RE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCI,
- .irqs = { 23, 23, 23, 0 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x4e0)),
.regshift = 2,
};
@@ -61,7 +62,7 @@ static struct plat_sci_port scif_platform_data = {
.scscr = SCSCR_TE | SCSCR_RE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 40, 40, 40, 40 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x700)),
};
static struct platform_device scif_device = {
@@ -85,7 +86,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -113,7 +114,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -140,7 +141,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
@@ -172,7 +173,7 @@ static struct resource tmu3_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 72,
+ .start = evt2irq(0xb00),
.flags = IORESOURCE_IRQ,
},
};
@@ -199,7 +200,7 @@ static struct resource tmu4_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 76,
+ .start = evt2irq(0xb80),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index c0b4c774700e..98e075ada44e 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <linux/serial_sci.h>
#include <linux/io.h>
@@ -132,7 +133,10 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 52, 53, 55, 54 },
+ .irqs = { evt2irq(0x880),
+ evt2irq(0x8a0),
+ evt2irq(0x8e0),
+ evt2irq(0x8c0) },
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -150,7 +154,10 @@ static struct plat_sci_port scif1_platform_data = {
.type = PORT_SCIF,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
- .irqs = { 72, 73, 75, 74 },
+ .irqs = { evt2irq(0xb00),
+ evt2irq(0xb20),
+ evt2irq(0xb60),
+ evt2irq(0xb40) },
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -168,7 +175,10 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 76, 77, 79, 78 },
+ .irqs = { evt2irq(0xb80),
+ evt2irq(0xba0),
+ evt2irq(0xbe0),
+ evt2irq(0xbc0) },
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -186,7 +196,9 @@ static struct plat_sci_port scif3_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCI,
- .irqs = { 80, 81, 82, 0 },
+ .irqs = { evt2irq(0xc00),
+ evt2irq(0xc20),
+ evt2irq(0xc40), },
.regshift = 2,
};
@@ -211,7 +223,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -239,7 +251,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -266,7 +278,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index 0b22d108f4c5..8fc6ec2be2fa 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o serial-sh7722.o
obj-$(CONFIG_CPU_SUBTYPE_SH7723) += setup-sh7723.o
obj-$(CONFIG_CPU_SUBTYPE_SH7724) += setup-sh7724.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7734) += setup-sh7734.o
obj-$(CONFIG_CPU_SUBTYPE_SH7366) += setup-sh7366.o
obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o intc-shx3.o
@@ -30,6 +31,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o
clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o
clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7734) := clock-sh7734.o
clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7366.o
clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o
@@ -37,6 +39,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o
pinmux-$(CONFIG_CPU_SUBTYPE_SH7722) := pinmux-sh7722.o
pinmux-$(CONFIG_CPU_SUBTYPE_SH7723) := pinmux-sh7723.o
pinmux-$(CONFIG_CPU_SUBTYPE_SH7724) := pinmux-sh7724.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7734) := pinmux-sh7734.o
pinmux-$(CONFIG_CPU_SUBTYPE_SH7757) := pinmux-sh7757.o
pinmux-$(CONFIG_CPU_SUBTYPE_SH7785) := pinmux-sh7785.o
pinmux-$(CONFIG_CPU_SUBTYPE_SH7786) := pinmux-sh7786.o
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7734.c b/arch/sh/kernel/cpu/sh4a/clock-sh7734.c
new file mode 100644
index 000000000000..1697642c1f73
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7734.c
@@ -0,0 +1,266 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7734.c
+ *
+ * Clock framework for SH7734
+ *
+ * Copyright (C) 2011, 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ * Copyright (C) 2011, 2012 Renesas Solutions Corp.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+
+static struct clk extal_clk = {
+ .rate = 33333333,
+};
+
+#define MODEMR (0xFFCC0020)
+#define MODEMR_MASK (0x6)
+#define MODEMR_533MHZ (0x2)
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+ int mode = 12;
+ u32 r = __raw_readl(MODEMR);
+
+ if ((r & MODEMR_MASK) & MODEMR_533MHZ)
+ mode = 16;
+
+ return clk->parent->rate * mode;
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
+};
+
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .parent = &extal_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static struct clk *main_clks[] = {
+ &extal_clk,
+ &pll_clk,
+};
+
+static int multipliers[] = { 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = divisors,
+ .nr_divisors = ARRAY_SIZE(divisors),
+ .multipliers = multipliers,
+ .nr_multipliers = ARRAY_SIZE(multipliers),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I, DIV4_S, DIV4_B, DIV4_M, DIV4_S1, DIV4_P, DIV4_NR };
+
+#define DIV4(_reg, _bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_I] = DIV4(FRQMR1, 28, 0x0003, CLK_ENABLE_ON_INIT),
+ [DIV4_S] = DIV4(FRQMR1, 20, 0x000C, CLK_ENABLE_ON_INIT),
+ [DIV4_B] = DIV4(FRQMR1, 16, 0x0140, CLK_ENABLE_ON_INIT),
+ [DIV4_M] = DIV4(FRQMR1, 12, 0x0004, CLK_ENABLE_ON_INIT),
+ [DIV4_S1] = DIV4(FRQMR1, 4, 0x0030, CLK_ENABLE_ON_INIT),
+ [DIV4_P] = DIV4(FRQMR1, 0, 0x0140, CLK_ENABLE_ON_INIT),
+};
+
+#define MSTPCR0 0xFFC80030
+#define MSTPCR1 0xFFC80034
+#define MSTPCR3 0xFFC8003C
+
+enum {
+ MSTP030, MSTP029, /* IIC */
+ MSTP026, MSTP025, MSTP024, /* SCIF */
+ MSTP023,
+ MSTP022, MSTP021,
+ MSTP019, /* HSCIF */
+ MSTP016, MSTP015, MSTP014, /* TMU / TIMER */
+ MSTP012, MSTP011, MSTP010, MSTP009, MSTP008, /* SSI */
+ MSTP007, /* HSPI */
+ MSTP115, /* ADMAC */
+ MSTP114, /* GETHER */
+ MSTP111, /* DMAC */
+ MSTP109, /* VIDEOIN1 */
+ MSTP108, /* VIDEOIN0 */
+ MSTP107, /* RGPVBG */
+ MSTP106, /* 2DG */
+ MSTP103, /* VIEW */
+ MSTP100, /* USB */
+ MSTP331, /* MMC */
+ MSTP330, /* MIMLB */
+ MSTP323, /* SDHI0 */
+ MSTP322, /* SDHI1 */
+ MSTP321, /* SDHI2 */
+ MSTP320, /* RQSPI */
+ MSTP319, /* SRC0 */
+ MSTP318, /* SRC1 */
+ MSTP317, /* RSPI */
+ MSTP316, /* RCAN0 */
+ MSTP315, /* RCAN1 */
+ MSTP314, /* FLTCL */
+ MSTP313, /* ADC */
+ MSTP312, /* MTU */
+ MSTP304, /* IE-BUS */
+ MSTP303, /* RTC */
+ MSTP302, /* HIF */
+ MSTP301, /* STIF0 */
+ MSTP300, /* STIF1 */
+ MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ /* MSTPCR0 */
+ [MSTP030] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 30, 0),
+ [MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0),
+ [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0),
+ [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0),
+ [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0),
+ [MSTP023] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 23, 0),
+ [MSTP022] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 22, 0),
+ [MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
+ [MSTP019] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 19, 0),
+ [MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0),
+ [MSTP015] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
+ [MSTP014] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 14, 0),
+ [MSTP012] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 12, 0),
+ [MSTP011] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
+ [MSTP010] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
+ [MSTP009] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0),
+ [MSTP008] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0),
+ [MSTP007] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 7, 0),
+
+ /* MSTPCR1 */
+ [MSTP115] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 15, 0),
+ [MSTP114] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 14, 0),
+ [MSTP111] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 11, 0),
+ [MSTP109] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
+ [MSTP108] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 8, 0),
+ [MSTP107] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 7, 0),
+ [MSTP106] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 6, 0),
+ [MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 3, 0),
+ [MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 0, 0),
+
+ /* MSTPCR3 */
+ [MSTP331] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 31, 0),
+ [MSTP330] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 30, 0),
+ [MSTP323] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 23, 0),
+ [MSTP322] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 22, 0),
+ [MSTP321] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 21, 0),
+ [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 20, 0),
+ [MSTP319] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 19, 0),
+ [MSTP318] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 18, 0),
+ [MSTP317] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 17, 0),
+ [MSTP316] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 16, 0),
+ [MSTP315] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 15, 0),
+ [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 14, 0),
+ [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 13, 0),
+ [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 12, 0),
+ [MSTP304] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 4, 0),
+ [MSTP303] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 3, 0),
+ [MSTP302] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 2, 0),
+ [MSTP301] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 1, 0),
+ [MSTP300] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 0, 0),
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+ /* clocks */
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+ CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_S]),
+ CLKDEV_CON_ID("ddr_clk", &div4_clks[DIV4_M]),
+ CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+ CLKDEV_CON_ID("shyway_clk1", &div4_clks[DIV4_S1]),
+ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+
+ /* MSTP32 clocks */
+ CLKDEV_DEV_ID("i2c-sh7734.0", &mstp_clks[MSTP030]),
+ CLKDEV_DEV_ID("i2c-sh7734.1", &mstp_clks[MSTP029]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP026]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP024]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP023]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP022]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP021]),
+ CLKDEV_CON_ID("hscif", &mstp_clks[MSTP019]),
+ CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[MSTP016]),
+ CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[MSTP016]),
+ CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[MSTP016]),
+ CLKDEV_ICK_ID("tmu_fck", "sh_tmu.3", &mstp_clks[MSTP015]),
+ CLKDEV_ICK_ID("tmu_fck", "sh_tmu.4", &mstp_clks[MSTP015]),
+ CLKDEV_ICK_ID("tmu_fck", "sh_tmu.5", &mstp_clks[MSTP015]),
+ CLKDEV_ICK_ID("tmu_fck", "sh_tmu.6", &mstp_clks[MSTP014]),
+ CLKDEV_ICK_ID("tmu_fck", "sh_tmu.7", &mstp_clks[MSTP014]),
+ CLKDEV_ICK_ID("tmu_fck", "sh_tmu.8", &mstp_clks[MSTP014]),
+ CLKDEV_CON_ID("ssi0", &mstp_clks[MSTP012]),
+ CLKDEV_CON_ID("ssi1", &mstp_clks[MSTP011]),
+ CLKDEV_CON_ID("ssi2", &mstp_clks[MSTP010]),
+ CLKDEV_CON_ID("ssi3", &mstp_clks[MSTP009]),
+ CLKDEV_CON_ID("sss", &mstp_clks[MSTP008]),
+ CLKDEV_CON_ID("hspi", &mstp_clks[MSTP007]),
+ CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP100]),
+ CLKDEV_CON_ID("videoin0", &mstp_clks[MSTP109]),
+ CLKDEV_CON_ID("videoin1", &mstp_clks[MSTP108]),
+ CLKDEV_CON_ID("rgpvg", &mstp_clks[MSTP107]),
+ CLKDEV_CON_ID("2dg", &mstp_clks[MSTP106]),
+ CLKDEV_CON_ID("view", &mstp_clks[MSTP103]),
+
+ CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP331]),
+ CLKDEV_CON_ID("mimlb0", &mstp_clks[MSTP330]),
+ CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP323]),
+ CLKDEV_CON_ID("sdhi1", &mstp_clks[MSTP322]),
+ CLKDEV_CON_ID("sdhi2", &mstp_clks[MSTP321]),
+ CLKDEV_CON_ID("rqspi0", &mstp_clks[MSTP320]),
+ CLKDEV_CON_ID("src0", &mstp_clks[MSTP319]),
+ CLKDEV_CON_ID("src1", &mstp_clks[MSTP318]),
+ CLKDEV_CON_ID("rsp0", &mstp_clks[MSTP317]),
+ CLKDEV_CON_ID("rcan0", &mstp_clks[MSTP316]),
+ CLKDEV_CON_ID("rcan1", &mstp_clks[MSTP315]),
+ CLKDEV_CON_ID("fltcl0", &mstp_clks[MSTP314]),
+ CLKDEV_CON_ID("adc0", &mstp_clks[MSTP313]),
+ CLKDEV_CON_ID("mtu0", &mstp_clks[MSTP312]),
+ CLKDEV_CON_ID("iebus0", &mstp_clks[MSTP304]),
+ CLKDEV_DEV_ID("sh-eth.0", &mstp_clks[MSTP114]),
+ CLKDEV_CON_ID("rtc0", &mstp_clks[MSTP303]),
+ CLKDEV_CON_ID("hif0", &mstp_clks[MSTP302]),
+ CLKDEV_CON_ID("stif0", &mstp_clks[MSTP301]),
+ CLKDEV_CON_ID("stif1", &mstp_clks[MSTP300]),
+};
+
+int __init arch_clk_init(void)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < ARRAY_SIZE(main_clks); i++)
+ ret |= clk_register(main_clks[i]);
+
+ for (i = 0; i < ARRAY_SIZE(lookups); i++)
+ clkdev_add(&lookups[i]);
+
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
+ &div4_table);
+
+ if (!ret)
+ ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
+
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7734.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7734.c
new file mode 100644
index 000000000000..eed3b9d19d38
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7734.c
@@ -0,0 +1,2497 @@
+/*
+ * SH7734 processor support - PFC hardware block
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/ioport.h>
+#include <cpu/sh7734.h>
+
+#define CPU_32_PORT(fn, pfx, sfx) \
+ PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx), \
+ PORT_10(fn, pfx##2, sfx), PORT_1(fn, pfx##30, sfx), \
+ PORT_1(fn, pfx##31, sfx)
+
+#define CPU_32_PORT5(fn, pfx, sfx) \
+ PORT_1(fn, pfx##0, sfx), PORT_1(fn, pfx##1, sfx), \
+ PORT_1(fn, pfx##2, sfx), PORT_1(fn, pfx##3, sfx), \
+ PORT_1(fn, pfx##4, sfx), PORT_1(fn, pfx##5, sfx), \
+ PORT_1(fn, pfx##6, sfx), PORT_1(fn, pfx##7, sfx), \
+ PORT_1(fn, pfx##8, sfx), PORT_1(fn, pfx##9, sfx), \
+ PORT_1(fn, pfx##10, sfx), PORT_1(fn, pfx##11, sfx)
+
+/* GPSR0 - GPSR5 */
+#define CPU_ALL_PORT(fn, pfx, sfx) \
+ CPU_32_PORT(fn, pfx##_0_, sfx), \
+ CPU_32_PORT(fn, pfx##_1_, sfx), \
+ CPU_32_PORT(fn, pfx##_2_, sfx), \
+ CPU_32_PORT(fn, pfx##_3_, sfx), \
+ CPU_32_PORT(fn, pfx##_4_, sfx), \
+ CPU_32_PORT5(fn, pfx##_5_, sfx)
+
+#define _GP_GPIO(pfx, sfx) PINMUX_GPIO(GPIO_GP##pfx, GP##pfx##_DATA)
+#define _GP_DATA(pfx, sfx) PINMUX_DATA(GP##pfx##_DATA, GP##pfx##_FN, \
+ GP##pfx##_IN, GP##pfx##_OUT)
+
+#define _GP_INOUTSEL(pfx, sfx) GP##pfx##_IN, GP##pfx##_OUT
+#define _GP_INDT(pfx, sfx) GP##pfx##_DATA
+
+#define GP_ALL(str) CPU_ALL_PORT(_PORT_ALL, GP, str)
+#define PINMUX_GPIO_GP_ALL() CPU_ALL_PORT(_GP_GPIO, , unused)
+#define PINMUX_DATA_GP_ALL() CPU_ALL_PORT(_GP_DATA, , unused)
+
+#define PORT_10_REV(fn, pfx, sfx) \
+ PORT_1(fn, pfx##9, sfx), PORT_1(fn, pfx##8, sfx), \
+ PORT_1(fn, pfx##7, sfx), PORT_1(fn, pfx##6, sfx), \
+ PORT_1(fn, pfx##5, sfx), PORT_1(fn, pfx##4, sfx), \
+ PORT_1(fn, pfx##3, sfx), PORT_1(fn, pfx##2, sfx), \
+ PORT_1(fn, pfx##1, sfx), PORT_1(fn, pfx##0, sfx)
+
+#define CPU_32_PORT_REV(fn, pfx, sfx) \
+ PORT_1(fn, pfx##31, sfx), PORT_1(fn, pfx##30, sfx), \
+ PORT_10_REV(fn, pfx##2, sfx), PORT_10_REV(fn, pfx##1, sfx), \
+ PORT_10_REV(fn, pfx, sfx)
+
+#define GP_INOUTSEL(bank) CPU_32_PORT_REV(_GP_INOUTSEL, _##bank##_, unused)
+#define GP_INDT(bank) CPU_32_PORT_REV(_GP_INDT, _##bank##_, unused)
+
+#define PINMUX_IPSR_DATA(ipsr, fn) PINMUX_DATA(fn##_MARK, FN_##ipsr, FN_##fn)
+#define PINMUX_IPSR_MODSEL_DATA(ipsr, fn, ms) PINMUX_DATA(fn##_MARK, FN_##ms, \
+ FN_##ipsr, FN_##fn)
+
+enum {
+ PINMUX_RESERVED = 0,
+
+ PINMUX_DATA_BEGIN,
+ GP_ALL(DATA), /* GP_0_0_DATA -> GP_5_11_DATA */
+ PINMUX_DATA_END,
+
+ PINMUX_INPUT_BEGIN,
+ GP_ALL(IN), /* GP_0_0_IN -> GP_5_11_IN */
+ PINMUX_INPUT_END,
+
+ PINMUX_OUTPUT_BEGIN,
+ GP_ALL(OUT), /* GP_0_0_OUT -> GP_5_11_OUT */
+ PINMUX_OUTPUT_END,
+
+ PINMUX_FUNCTION_BEGIN,
+ GP_ALL(FN), /* GP_0_0_FN -> GP_5_11_FN */
+
+ /* GPSR0 */
+ FN_IP1_9_8, FN_IP1_11_10, FN_IP1_13_12, FN_IP1_15_14,
+ FN_IP0_7_6, FN_IP0_9_8, FN_IP0_11_10, FN_IP0_13_12,
+ FN_IP0_15_14, FN_IP0_17_16, FN_IP0_19_18, FN_IP0_21_20,
+ FN_IP0_23_22, FN_IP0_25_24, FN_IP0_27_26, FN_IP0_29_28,
+ FN_IP0_31_30, FN_IP1_1_0, FN_IP1_3_2, FN_IP1_5_4,
+ FN_IP1_7_6, FN_IP11_28, FN_IP0_1_0, FN_IP0_3_2,
+ FN_IP0_5_4, FN_IP1_17_16, FN_IP1_19_18, FN_IP1_22_20,
+ FN_IP1_25_23, FN_IP1_28_26, FN_IP1_31_29, FN_IP2_2_0,
+
+ /* GPSR1 */
+ FN_IP3_20, FN_IP3_29_27, FN_IP11_20_19, FN_IP11_22_21,
+ FN_IP2_16_14, FN_IP2_19_17, FN_IP2_22_20, FN_IP2_24_23,
+ FN_IP2_27_25, FN_IP2_30_28, FN_IP3_1_0, FN_CLKOUT,
+ FN_BS, FN_CS0, FN_IP3_2, FN_EX_CS0,
+ FN_IP3_5_3, FN_IP3_8_6, FN_IP3_11_9, FN_IP3_14_12,
+ FN_IP3_17_15, FN_RD, FN_IP3_19_18, FN_WE0,
+ FN_WE1, FN_IP2_4_3, FN_IP3_23_21, FN_IP3_26_24,
+ FN_IP2_7_5, FN_IP2_10_8, FN_IP2_13_11, FN_IP11_25_23,
+
+ /* GPSR2 */
+ FN_IP11_6_4, FN_IP11_9_7, FN_IP11_11_10, FN_IP4_2_0,
+ FN_IP8_29_28, FN_IP11_27_26, FN_IP8_22_20, FN_IP8_25_23,
+ FN_IP11_12, FN_IP8_27_26, FN_IP4_5_3, FN_IP4_8_6,
+ FN_IP4_11_9, FN_IP4_14_12, FN_IP4_17_15, FN_IP4_19_18,
+ FN_IP4_21_20, FN_IP4_23_22, FN_IP4_25_24, FN_IP4_27_26,
+ FN_IP4_29_28, FN_IP4_31_30, FN_IP5_2_0, FN_IP5_5_3,
+ FN_IP5_8_6, FN_IP5_11_9, FN_IP5_14_12, FN_IP5_17_15,
+ FN_IP5_20_18, FN_IP5_22_21, FN_IP5_24_23, FN_IP5_26_25,
+
+ /* GPSR3 */
+ FN_IP6_2_0, FN_IP6_5_3, FN_IP6_7_6, FN_IP6_9_8,
+ FN_IP6_11_10, FN_IP6_13_12, FN_IP6_15_14, FN_IP6_17_16,
+ FN_IP6_20_18, FN_IP6_23_21, FN_IP7_2_0, FN_IP7_5_3,
+ FN_IP7_8_6, FN_IP7_11_9, FN_IP7_14_12, FN_IP7_17_15,
+ FN_IP7_20_18, FN_IP7_23_21, FN_IP7_26_24, FN_IP7_28_27,
+ FN_IP7_30_29, FN_IP8_1_0, FN_IP8_3_2, FN_IP8_5_4,
+ FN_IP8_7_6, FN_IP8_9_8, FN_IP8_11_10, FN_IP8_13_12,
+ FN_IP8_15_14, FN_IP8_17_16, FN_IP8_19_18, FN_IP9_1_0,
+
+ /* GPSR4 */
+ FN_IP9_19_18, FN_IP9_21_20, FN_IP9_23_22, FN_IP9_25_24,
+ FN_IP9_11_10, FN_IP9_13_12, FN_IP9_15_14, FN_IP9_17_16,
+ FN_IP9_3_2, FN_IP9_5_4, FN_IP9_7_6, FN_IP9_9_8,
+ FN_IP9_27_26, FN_IP9_29_28, FN_IP10_2_0, FN_IP10_5_3,
+ FN_IP10_8_6, FN_IP10_11_9, FN_IP10_14_12, FN_IP10_15,
+ FN_IP10_18_16, FN_IP10_21_19, FN_IP11_0, FN_IP11_1,
+ FN_SCL0, FN_IP11_2, FN_PENC0, FN_IP11_15_13, /* Need check*/
+ FN_USB_OVC0, FN_IP11_18_16,
+ FN_IP10_22, FN_IP10_24_23,
+
+ /* GPSR5 */
+ FN_IP10_25, FN_IP11_3, FN_IRQ2_B, FN_IRQ3_B,
+ FN_IP10_27_26, /* 10 */
+ FN_IP10_29_28, /* 11 */
+
+ /* IPSR0 */
+ FN_A15, FN_ST0_VCO_CLKIN, FN_LCD_DATA15_A, FN_TIOC3D_C,
+ FN_A14, FN_LCD_DATA14_A, FN_TIOC3C_C,
+ FN_A13, FN_LCD_DATA13_A, FN_TIOC3B_C,
+ FN_A12, FN_LCD_DATA12_A, FN_TIOC3A_C,
+ FN_A11, FN_ST0_D7, FN_LCD_DATA11_A, FN_TIOC2B_C,
+ FN_A10, FN_ST0_D6, FN_LCD_DATA10_A, FN_TIOC2A_C,
+ FN_A9, FN_ST0_D5, FN_LCD_DATA9_A, FN_TIOC1B_C,
+ FN_A8, FN_ST0_D4, FN_LCD_DATA8_A, FN_TIOC1A_C,
+ FN_A7, FN_ST0_D3, FN_LCD_DATA7_A, FN_TIOC0D_C,
+ FN_A6, FN_ST0_D2, FN_LCD_DATA6_A, FN_TIOC0C_C,
+ FN_A5, FN_ST0_D1, FN_LCD_DATA5_A, FN_TIOC0B_C,
+ FN_A4, FN_ST0_D0, FN_LCD_DATA4_A, FN_TIOC0A_C,
+ FN_A3, FN_ST0_VLD, FN_LCD_DATA3_A, FN_TCLKD_C,
+ FN_A2, FN_ST0_SYC, FN_LCD_DATA2_A, FN_TCLKC_C,
+ FN_A1, FN_ST0_REQ, FN_LCD_DATA1_A, FN_TCLKB_C,
+ FN_A0, FN_ST0_CLKIN, FN_LCD_DATA0_A, FN_TCLKA_C,
+
+ /* IPSR1 */
+ FN_D3, FN_SD0_DAT3_A, FN_MMC_D3_A, FN_ST1_D6, FN_FD3_A,
+ FN_D2, FN_SD0_DAT2_A, FN_MMC_D2_A, FN_ST1_D5, FN_FD2_A,
+ FN_D1, FN_SD0_DAT1_A, FN_MMC_D1_A, FN_ST1_D4, FN_FD1_A,
+ FN_D0, FN_SD0_DAT0_A, FN_MMC_D0_A, FN_ST1_D3, FN_FD0_A,
+ FN_A25, FN_TX2_D, FN_ST1_D2,
+ FN_A24, FN_RX2_D, FN_ST1_D1,
+ FN_A23, FN_ST1_D0, FN_LCD_M_DISP_A,
+ FN_A22, FN_ST1_VLD, FN_LCD_VEPWC_A,
+ FN_A21, FN_ST1_SYC, FN_LCD_VCPWC_A,
+ FN_A20, FN_ST1_REQ, FN_LCD_FLM_A,
+ FN_A19, FN_ST1_CLKIN, FN_LCD_CLK_A, FN_TIOC4D_C,
+ FN_A18, FN_ST1_PWM, FN_LCD_CL2_A, FN_TIOC4C_C,
+ FN_A17, FN_ST1_VCO_CLKIN, FN_LCD_CL1_A, FN_TIOC4B_C,
+ FN_A16, FN_ST0_PWM, FN_LCD_DON_A, FN_TIOC4A_C,
+
+ /* IPSR2 */
+ FN_D14, FN_TX2_B, FN_FSE_A, FN_ET0_TX_CLK_B,
+ FN_D13, FN_RX2_B, FN_FRB_A, FN_ET0_ETXD6_B,
+ FN_D12, FN_FWE_A, FN_ET0_ETXD5_B,
+ FN_D11, FN_RSPI_MISO_A, FN_QMI_QIO1_A, FN_FRE_A,
+ FN_ET0_ETXD3_B,
+ FN_D10, FN_RSPI_MOSI_A, FN_QMO_QIO0_A, FN_FALE_A,
+ FN_ET0_ETXD2_B,
+ FN_D9, FN_SD0_CMD_A, FN_MMC_CMD_A, FN_QIO3_A, FN_FCLE_A,
+ FN_ET0_ETXD1_B,
+ FN_D8, FN_SD0_CLK_A, FN_MMC_CLK_A, FN_QIO2_A, FN_FCE_A,
+ FN_ET0_GTX_CLK_B,
+ FN_D7, FN_RSPI_SSL_A, FN_MMC_D7_A, FN_QSSL_A, FN_FD7_A,
+ FN_D6, FN_RSPI_RSPCK_A, FN_MMC_D6_A, FN_QSPCLK_A, FN_FD6_A,
+ FN_D5, FN_SD0_WP_A, FN_MMC_D5_A, FN_FD5_A,
+ FN_D4, FN_SD0_CD_A, FN_MMC_D4_A, FN_ST1_D7, FN_FD4_A,
+
+ /* IPSR3 */
+ FN_DRACK0, FN_SD1_DAT2_A, FN_ATAG, FN_TCLK1_A, FN_ET0_ETXD7,
+ FN_EX_WAIT2, FN_SD1_DAT1_A, FN_DACK2, FN_CAN1_RX_C,
+ FN_ET0_MAGIC_C, FN_ET0_ETXD6_A,
+ FN_EX_WAIT1, FN_SD1_DAT0_A, FN_DREQ2, FN_CAN1_TX_C,
+ FN_ET0_LINK_C, FN_ET0_ETXD5_A,
+ FN_EX_WAIT0, FN_TCLK1_B,
+ FN_RD_WR, FN_TCLK0, FN_CAN_CLK_B, FN_ET0_ETXD4,
+ FN_EX_CS5, FN_SD1_CMD_A, FN_ATADIR, FN_QSSL_B, FN_ET0_ETXD3_A,
+ FN_EX_CS4, FN_SD1_WP_A, FN_ATAWR, FN_QMI_QIO1_B, FN_ET0_ETXD2_A,
+ FN_EX_CS3, FN_SD1_CD_A, FN_ATARD, FN_QMO_QIO0_B, FN_ET0_ETXD1_A,
+ FN_EX_CS2, FN_TX3_B, FN_ATACS1, FN_QSPCLK_B, FN_ET0_GTX_CLK_A,
+ FN_EX_CS1, FN_RX3_B, FN_ATACS0, FN_QIO2_B, FN_ET0_ETXD0,
+ FN_CS1_A26, FN_QIO3_B,
+ FN_D15, FN_SCK2_B,
+
+ /* IPSR4 */
+ FN_SCK2_A, FN_VI0_G3,
+ FN_RTS1_B, FN_VI0_G2,
+ FN_CTS1_B, FN_VI0_DATA7_VI0_G1,
+ FN_TX1_B, FN_VI0_DATA6_VI0_G0, FN_ET0_PHY_INT_A,
+ FN_RX1_B, FN_VI0_DATA5_VI0_B5, FN_ET0_MAGIC_A,
+ FN_SCK1_B, FN_VI0_DATA4_VI0_B4, FN_ET0_LINK_A,
+ FN_RTS0_B, FN_VI0_DATA3_VI0_B3, FN_ET0_MDIO_A,
+ FN_CTS0_B, FN_VI0_DATA2_VI0_B2, FN_RMII0_MDIO_A, FN_ET0_MDC,
+ FN_HTX0_A, FN_TX1_A, FN_VI0_DATA1_VI0_B1, FN_RMII0_MDC_A, FN_ET0_COL,
+ FN_HRX0_A, FN_RX1_A, FN_VI0_DATA0_VI0_B0, FN_RMII0_CRS_DV_A, FN_ET0_CRS,
+ FN_HSCK0_A, FN_SCK1_A, FN_VI0_VSYNC, FN_RMII0_RX_ER_A, FN_ET0_RX_ER,
+ FN_HRTS0_A, FN_RTS1_A, FN_VI0_HSYNC, FN_RMII0_TXD_EN_A, FN_ET0_RX_DV,
+ FN_HCTS0_A, FN_CTS1_A, FN_VI0_FIELD, FN_RMII0_RXD1_A, FN_ET0_ERXD7,
+
+ /* IPSR5 */
+ FN_SD2_CLK_A, FN_RX2_A, FN_VI0_G4, FN_ET0_RX_CLK_B,
+ FN_SD2_CMD_A, FN_TX2_A, FN_VI0_G5, FN_ET0_ERXD2_B,
+ FN_SD2_DAT0_A, FN_RX3_A, FN_VI0_R0, FN_ET0_ERXD3_B,
+ FN_SD2_DAT1_A, FN_TX3_A, FN_VI0_R1, FN_ET0_MDIO_B,
+ FN_SD2_DAT2_A, FN_RX4_A, FN_VI0_R2, FN_ET0_LINK_B,
+ FN_SD2_DAT3_A, FN_TX4_A, FN_VI0_R3, FN_ET0_MAGIC_B,
+ FN_SD2_CD_A, FN_RX5_A, FN_VI0_R4, FN_ET0_PHY_INT_B,
+ FN_SD2_WP_A, FN_TX5_A, FN_VI0_R5,
+ FN_REF125CK, FN_ADTRG, FN_RX5_C,
+ FN_REF50CK, FN_CTS1_E, FN_HCTS0_D,
+
+ /* IPSR6 */
+ FN_DU0_DR0, FN_SCIF_CLK_B, FN_HRX0_D, FN_IETX_A, FN_TCLKA_A, FN_HIFD00,
+ FN_DU0_DR1, FN_SCK0_B, FN_HTX0_D, FN_IERX_A, FN_TCLKB_A, FN_HIFD01,
+ FN_DU0_DR2, FN_RX0_B, FN_TCLKC_A, FN_HIFD02,
+ FN_DU0_DR3, FN_TX0_B, FN_TCLKD_A, FN_HIFD03,
+ FN_DU0_DR4, FN_CTS0_C, FN_TIOC0A_A, FN_HIFD04,
+ FN_DU0_DR5, FN_RTS0_C, FN_TIOC0B_A, FN_HIFD05,
+ FN_DU0_DR6, FN_SCK1_C, FN_TIOC0C_A, FN_HIFD06,
+ FN_DU0_DR7, FN_RX1_C, FN_TIOC0D_A, FN_HIFD07,
+ FN_DU0_DG0, FN_TX1_C, FN_HSCK0_D, FN_IECLK_A, FN_TIOC1A_A, FN_HIFD08,
+ FN_DU0_DG1, FN_CTS1_C, FN_HRTS0_D, FN_TIOC1B_A, FN_HIFD09,
+
+ /* IPSR7 */
+ FN_DU0_DG2, FN_RTS1_C, FN_RMII0_MDC_B, FN_TIOC2A_A, FN_HIFD10,
+ FN_DU0_DG3, FN_SCK2_C, FN_RMII0_MDIO_B, FN_TIOC2B_A, FN_HIFD11,
+ FN_DU0_DG4, FN_RX2_C, FN_RMII0_CRS_DV_B, FN_TIOC3A_A, FN_HIFD12,
+ FN_DU0_DG5, FN_TX2_C, FN_RMII0_RX_ER_B, FN_TIOC3B_A, FN_HIFD13,
+ FN_DU0_DG6, FN_RX3_C, FN_RMII0_RXD0_B, FN_TIOC3C_A, FN_HIFD14,
+ FN_DU0_DG7, FN_TX3_C, FN_RMII0_RXD1_B, FN_TIOC3D_A, FN_HIFD15,
+ FN_DU0_DB0, FN_RX4_C, FN_RMII0_TXD_EN_B, FN_TIOC4A_A, FN_HIFCS,
+ FN_DU0_DB1, FN_TX4_C, FN_RMII0_TXD0_B, FN_TIOC4B_A, FN_HIFRS,
+ FN_DU0_DB2, FN_RX5_B, FN_RMII0_TXD1_B, FN_TIOC4C_A, FN_HIFWR,
+ FN_DU0_DB3, FN_TX5_B, FN_TIOC4D_A, FN_HIFRD,
+ FN_DU0_DB4, FN_HIFINT,
+
+ /* IPSR8 */
+ FN_DU0_DB5, FN_HIFDREQ,
+ FN_DU0_DB6, FN_HIFRDY,
+ FN_DU0_DB7, FN_SSI_SCK0_B, FN_HIFEBL_B,
+ FN_DU0_DOTCLKIN, FN_HSPI_CS0_C, FN_SSI_WS0_B,
+ FN_DU0_DOTCLKOUT, FN_HSPI_CLK0_C, FN_SSI_SDATA0_B,
+ FN_DU0_EXHSYNC_DU0_HSYNC, FN_HSPI_TX0_C, FN_SSI_SCK1_B,
+ FN_DU0_EXVSYNC_DU0_VSYNC, FN_HSPI_RX0_C, FN_SSI_WS1_B,
+ FN_DU0_EXODDF_DU0_ODDF, FN_CAN0_RX_B, FN_HSCK0_B, FN_SSI_SDATA1_B,
+ FN_DU0_DISP, FN_CAN0_TX_B, FN_HRX0_B, FN_AUDIO_CLKA_B,
+ FN_DU0_CDE, FN_HTX0_B, FN_AUDIO_CLKB_B, FN_LCD_VCPWC_B,
+ FN_IRQ0_A, FN_HSPI_TX_B, FN_RX3_E, FN_ET0_ERXD0,
+ FN_IRQ1_A, FN_HSPI_RX_B, FN_TX3_E, FN_ET0_ERXD1,
+ FN_IRQ2_A, FN_CTS0_A, FN_HCTS0_B, FN_ET0_ERXD2_A,
+ FN_IRQ3_A, FN_RTS0_A, FN_HRTS0_B, FN_ET0_ERXD3_A,
+
+ /* IPSR9 */
+ FN_VI1_CLK_A, FN_FD0_B, FN_LCD_DATA0_B,
+ FN_VI1_0_A, FN_FD1_B, FN_LCD_DATA1_B,
+ FN_VI1_1_A, FN_FD2_B, FN_LCD_DATA2_B,
+ FN_VI1_2_A, FN_FD3_B, FN_LCD_DATA3_B,
+ FN_VI1_3_A, FN_FD4_B, FN_LCD_DATA4_B,
+ FN_VI1_4_A, FN_FD5_B, FN_LCD_DATA5_B,
+ FN_VI1_5_A, FN_FD6_B, FN_LCD_DATA6_B,
+ FN_VI1_6_A, FN_FD7_B, FN_LCD_DATA7_B,
+ FN_VI1_7_A, FN_FCE_B, FN_LCD_DATA8_B,
+ FN_SSI_SCK0_A, FN_TIOC1A_B, FN_LCD_DATA9_B,
+ FN_SSI_WS0_A, FN_TIOC1B_B, FN_LCD_DATA10_B,
+ FN_SSI_SDATA0_A, FN_VI1_0_B, FN_TIOC2A_B, FN_LCD_DATA11_B,
+ FN_SSI_SCK1_A, FN_VI1_1_B, FN_TIOC2B_B, FN_LCD_DATA12_B,
+ FN_SSI_WS1_A, FN_VI1_2_B, FN_LCD_DATA13_B,
+ FN_SSI_SDATA1_A, FN_VI1_3_B, FN_LCD_DATA14_B,
+
+ /* IPSR10 */
+ FN_SSI_SCK23, FN_VI1_4_B, FN_RX1_D, FN_FCLE_B, FN_LCD_DATA15_B,
+ FN_SSI_WS23, FN_VI1_5_B, FN_TX1_D, FN_HSCK0_C, FN_FALE_B, FN_LCD_DON_B,
+ FN_SSI_SDATA2, FN_VI1_6_B, FN_HRX0_C, FN_FRE_B, FN_LCD_CL1_B,
+ FN_SSI_SDATA3, FN_VI1_7_B, FN_HTX0_C, FN_FWE_B, FN_LCD_CL2_B,
+ FN_AUDIO_CLKA_A, FN_VI1_CLK_B, FN_SCK1_D, FN_IECLK_B, FN_LCD_FLM_B,
+ FN_AUDIO_CLKB_A, FN_LCD_CLK_B,
+ FN_AUDIO_CLKC, FN_SCK1_E, FN_HCTS0_C, FN_FRB_B, FN_LCD_VEPWC_B,
+ FN_AUDIO_CLKOUT, FN_TX1_E, FN_HRTS0_C, FN_FSE_B, FN_LCD_M_DISP_B,
+ FN_CAN_CLK_A, FN_RX4_D,
+ FN_CAN0_TX_A, FN_TX4_D, FN_MLB_CLK,
+ FN_CAN1_RX_A, FN_IRQ1_B,
+ FN_CAN0_RX_A, FN_IRQ0_B, FN_MLB_SIG,
+ FN_CAN1_TX_A, FN_TX5_C, FN_MLB_DAT,
+
+ /* IPSR11 */
+ FN_SCL1, FN_SCIF_CLK_C,
+ FN_SDA1, FN_RX1_E,
+ FN_SDA0, FN_HIFEBL_A,
+ FN_SDSELF, FN_RTS1_E,
+ FN_SCIF_CLK_A, FN_HSPI_CLK_A, FN_VI0_CLK, FN_RMII0_TXD0_A, FN_ET0_ERXD4,
+ FN_SCK0_A, FN_HSPI_CS_A, FN_VI0_CLKENB, FN_RMII0_TXD1_A, FN_ET0_ERXD5,
+ FN_RX0_A, FN_HSPI_RX_A, FN_RMII0_RXD0_A, FN_ET0_ERXD6,
+ FN_TX0_A, FN_HSPI_TX_A,
+ FN_PENC1, FN_TX3_D, FN_CAN1_TX_B, FN_TX5_D, FN_IETX_B,
+ FN_USB_OVC1, FN_RX3_D, FN_CAN1_RX_B, FN_RX5_D, FN_IERX_B,
+ FN_DREQ0, FN_SD1_CLK_A, FN_ET0_TX_EN,
+ FN_DACK0, FN_SD1_DAT3_A, FN_ET0_TX_ER,
+ FN_DREQ1, FN_HSPI_CLK_B, FN_RX4_B, FN_ET0_PHY_INT_C, FN_ET0_TX_CLK_A,
+ FN_DACK1, FN_HSPI_CS_B, FN_TX4_B, FN_ET0_RX_CLK_A,
+ FN_PRESETOUT, FN_ST_CLKOUT,
+
+ /* MOD_SEL1 */
+ FN_SEL_IEBUS_0, FN_SEL_IEBUS_1,
+ FN_SEL_RQSPI_0, FN_SEL_RQSPI_1,
+ FN_SEL_VIN1_0, FN_SEL_VIN1_1,
+ FN_SEL_HIF_0, FN_SEL_HIF_1,
+ FN_SEL_RSPI_0, FN_SEL_RSPI_1,
+ FN_SEL_LCDC_0, FN_SEL_LCDC_1,
+ FN_SEL_ET0_CTL_0, FN_SEL_ET0_CTL_1, FN_SEL_ET0_CTL_2,
+ FN_SEL_ET0_0, FN_SEL_ET0_1,
+ FN_SEL_RMII_0, FN_SEL_RMII_1,
+ FN_SEL_TMU_0, FN_SEL_TMU_1,
+ FN_SEL_HSPI_0, FN_SEL_HSPI_1, FN_SEL_HSPI_2,
+ FN_SEL_HSCIF_0, FN_SEL_HSCIF_1, FN_SEL_HSCIF_2, FN_SEL_HSCIF_3,
+ FN_SEL_RCAN_CLK_0, FN_SEL_RCAN_CLK_1,
+ FN_SEL_RCAN1_0, FN_SEL_RCAN1_1, FN_SEL_RCAN1_2,
+ FN_SEL_RCAN0_0, FN_SEL_RCAN0_1,
+ FN_SEL_SDHI2_0, FN_SEL_SDHI2_1,
+ FN_SEL_SDHI1_0, FN_SEL_SDHI1_1,
+ FN_SEL_SDHI0_0, FN_SEL_SDHI0_1,
+ FN_SEL_SSI1_0, FN_SEL_SSI1_1,
+ FN_SEL_SSI0_0, FN_SEL_SSI0_1,
+ FN_SEL_AUDIO_CLKB_0, FN_SEL_AUDIO_CLKB_1,
+ FN_SEL_AUDIO_CLKA_0, FN_SEL_AUDIO_CLKA_1,
+ FN_SEL_FLCTL_0, FN_SEL_FLCTL_1,
+ FN_SEL_MMC_0, FN_SEL_MMC_1,
+ FN_SEL_INTC_0, FN_SEL_INTC_1,
+
+ /* MOD_SEL2 */
+ FN_SEL_MTU2_CLK_0, FN_SEL_MTU2_CLK_1,
+ FN_SEL_MTU2_CH4_0, FN_SEL_MTU2_CH4_1,
+ FN_SEL_MTU2_CH3_0, FN_SEL_MTU2_CH3_1,
+ FN_SEL_MTU2_CH2_0, FN_SEL_MTU2_CH2_1, FN_SEL_MTU2_CH2_2,
+ FN_SEL_MTU2_CH1_0, FN_SEL_MTU2_CH1_1, FN_SEL_MTU2_CH1_2,
+ FN_SEL_MTU2_CH0_0, FN_SEL_MTU2_CH0_1,
+ FN_SEL_SCIF5_0, FN_SEL_SCIF5_1,
+ FN_SEL_SCIF5_2, FN_SEL_SCIF5_3,
+ FN_SEL_SCIF4_0, FN_SEL_SCIF4_1,
+ FN_SEL_SCIF4_2, FN_SEL_SCIF4_3,
+ FN_SEL_SCIF3_0, FN_SEL_SCIF3_1, FN_SEL_SCIF3_2,
+ FN_SEL_SCIF3_3, FN_SEL_SCIF3_4,
+ FN_SEL_SCIF2_0, FN_SEL_SCIF2_1, FN_SEL_SCIF2_2,
+ FN_SEL_SCIF2_3,
+ FN_SEL_SCIF1_0, FN_SEL_SCIF1_1, FN_SEL_SCIF1_2,
+ FN_SEL_SCIF1_3, FN_SEL_SCIF1_4,
+ FN_SEL_SCIF0_0, FN_SEL_SCIF0_1, FN_SEL_SCIF0_2,
+ FN_SEL_SCIF_CLK_0, FN_SEL_SCIF_CLK_1, FN_SEL_SCIF_CLK_2,
+
+ PINMUX_FUNCTION_END,
+
+ PINMUX_MARK_BEGIN,
+
+ CLKOUT_MARK, BS_MARK, CS0_MARK, EX_CS0_MARK, RD_MARK,
+ WE0_MARK, WE1_MARK,
+
+ SCL0_MARK, PENC0_MARK, USB_OVC0_MARK,
+
+ IRQ2_B_MARK, IRQ3_B_MARK,
+
+ /* IPSR0 */
+ A15_MARK, ST0_VCO_CLKIN_MARK, LCD_DATA15_A_MARK, TIOC3D_C_MARK,
+ A14_MARK, LCD_DATA14_A_MARK, TIOC3C_C_MARK,
+ A13_MARK, LCD_DATA13_A_MARK, TIOC3B_C_MARK,
+ A12_MARK, LCD_DATA12_A_MARK, TIOC3A_C_MARK,
+ A11_MARK, ST0_D7_MARK, LCD_DATA11_A_MARK, TIOC2B_C_MARK,
+ A10_MARK, ST0_D6_MARK, LCD_DATA10_A_MARK, TIOC2A_C_MARK,
+ A9_MARK, ST0_D5_MARK, LCD_DATA9_A_MARK, TIOC1B_C_MARK,
+ A8_MARK, ST0_D4_MARK, LCD_DATA8_A_MARK, TIOC1A_C_MARK,
+ A7_MARK, ST0_D3_MARK, LCD_DATA7_A_MARK, TIOC0D_C_MARK,
+ A6_MARK, ST0_D2_MARK, LCD_DATA6_A_MARK, TIOC0C_C_MARK,
+ A5_MARK, ST0_D1_MARK, LCD_DATA5_A_MARK, TIOC0B_C_MARK,
+ A4_MARK, ST0_D0_MARK, LCD_DATA4_A_MARK, TIOC0A_C_MARK,
+ A3_MARK, ST0_VLD_MARK, LCD_DATA3_A_MARK, TCLKD_C_MARK,
+ A2_MARK, ST0_SYC_MARK, LCD_DATA2_A_MARK, TCLKC_C_MARK,
+ A1_MARK, ST0_REQ_MARK, LCD_DATA1_A_MARK, TCLKB_C_MARK,
+ A0_MARK, ST0_CLKIN_MARK, LCD_DATA0_A_MARK, TCLKA_C_MARK,
+
+ /* IPSR1 */
+ D3_MARK, SD0_DAT3_A_MARK, MMC_D3_A_MARK, ST1_D6_MARK, FD3_A_MARK,
+ D2_MARK, SD0_DAT2_A_MARK, MMC_D2_A_MARK, ST1_D5_MARK, FD2_A_MARK,
+ D1_MARK, SD0_DAT1_A_MARK, MMC_D1_A_MARK, ST1_D4_MARK, FD1_A_MARK,
+ D0_MARK, SD0_DAT0_A_MARK, MMC_D0_A_MARK, ST1_D3_MARK, FD0_A_MARK,
+ A25_MARK, TX2_D_MARK, ST1_D2_MARK,
+ A24_MARK, RX2_D_MARK, ST1_D1_MARK,
+ A23_MARK, ST1_D0_MARK, LCD_M_DISP_A_MARK,
+ A22_MARK, ST1_VLD_MARK, LCD_VEPWC_A_MARK,
+ A21_MARK, ST1_SYC_MARK, LCD_VCPWC_A_MARK,
+ A20_MARK, ST1_REQ_MARK, LCD_FLM_A_MARK,
+ A19_MARK, ST1_CLKIN_MARK, LCD_CLK_A_MARK, TIOC4D_C_MARK,
+ A18_MARK, ST1_PWM_MARK, LCD_CL2_A_MARK, TIOC4C_C_MARK,
+ A17_MARK, ST1_VCO_CLKIN_MARK, LCD_CL1_A_MARK, TIOC4B_C_MARK,
+ A16_MARK, ST0_PWM_MARK, LCD_DON_A_MARK, TIOC4A_C_MARK,
+
+ /* IPSR2 */
+ D14_MARK, TX2_B_MARK, FSE_A_MARK, ET0_TX_CLK_B_MARK,
+ D13_MARK, RX2_B_MARK, FRB_A_MARK, ET0_ETXD6_B_MARK,
+ D12_MARK, FWE_A_MARK, ET0_ETXD5_B_MARK,
+ D11_MARK, RSPI_MISO_A_MARK, QMI_QIO1_A_MARK, FRE_A_MARK,
+ ET0_ETXD3_B_MARK,
+ D10_MARK, RSPI_MOSI_A_MARK, QMO_QIO0_A_MARK, FALE_A_MARK,
+ ET0_ETXD2_B_MARK,
+ D9_MARK, SD0_CMD_A_MARK, MMC_CMD_A_MARK, QIO3_A_MARK,
+ FCLE_A_MARK, ET0_ETXD1_B_MARK,
+ D8_MARK, SD0_CLK_A_MARK, MMC_CLK_A_MARK, QIO2_A_MARK,
+ FCE_A_MARK, ET0_GTX_CLK_B_MARK,
+ D7_MARK, RSPI_SSL_A_MARK, MMC_D7_A_MARK, QSSL_A_MARK,
+ FD7_A_MARK,
+ D6_MARK, RSPI_RSPCK_A_MARK, MMC_D6_A_MARK, QSPCLK_A_MARK,
+ FD6_A_MARK,
+ D5_MARK, SD0_WP_A_MARK, MMC_D5_A_MARK, FD5_A_MARK,
+ D4_MARK, SD0_CD_A_MARK, MMC_D4_A_MARK, ST1_D7_MARK,
+ FD4_A_MARK,
+
+ /* IPSR3 */
+ DRACK0_MARK, SD1_DAT2_A_MARK, ATAG_MARK, TCLK1_A_MARK, ET0_ETXD7_MARK,
+ EX_WAIT2_MARK, SD1_DAT1_A_MARK, DACK2_MARK, CAN1_RX_C_MARK,
+ ET0_MAGIC_C_MARK, ET0_ETXD6_A_MARK,
+ EX_WAIT1_MARK, SD1_DAT0_A_MARK, DREQ2_MARK, CAN1_TX_C_MARK,
+ ET0_LINK_C_MARK, ET0_ETXD5_A_MARK,
+ EX_WAIT0_MARK, TCLK1_B_MARK,
+ RD_WR_MARK, TCLK0_MARK, CAN_CLK_B_MARK, ET0_ETXD4_MARK,
+ EX_CS5_MARK, SD1_CMD_A_MARK, ATADIR_MARK, QSSL_B_MARK,
+ ET0_ETXD3_A_MARK,
+ EX_CS4_MARK, SD1_WP_A_MARK, ATAWR_MARK, QMI_QIO1_B_MARK,
+ ET0_ETXD2_A_MARK,
+ EX_CS3_MARK, SD1_CD_A_MARK, ATARD_MARK, QMO_QIO0_B_MARK,
+ ET0_ETXD1_A_MARK,
+ EX_CS2_MARK, TX3_B_MARK, ATACS1_MARK, QSPCLK_B_MARK,
+ ET0_GTX_CLK_A_MARK,
+ EX_CS1_MARK, RX3_B_MARK, ATACS0_MARK, QIO2_B_MARK,
+ ET0_ETXD0_MARK,
+ CS1_A26_MARK, QIO3_B_MARK,
+ D15_MARK, SCK2_B_MARK,
+
+ /* IPSR4 */
+ SCK2_A_MARK, VI0_G3_MARK,
+ RTS1_B_MARK, VI0_G2_MARK,
+ CTS1_B_MARK, VI0_DATA7_VI0_G1_MARK,
+ TX1_B_MARK, VI0_DATA6_VI0_G0_MARK, ET0_PHY_INT_A_MARK,
+ RX1_B_MARK, VI0_DATA5_VI0_B5_MARK, ET0_MAGIC_A_MARK,
+ SCK1_B_MARK, VI0_DATA4_VI0_B4_MARK, ET0_LINK_A_MARK,
+ RTS0_B_MARK, VI0_DATA3_VI0_B3_MARK, ET0_MDIO_A_MARK,
+ CTS0_B_MARK, VI0_DATA2_VI0_B2_MARK, RMII0_MDIO_A_MARK,
+ ET0_MDC_MARK,
+ HTX0_A_MARK, TX1_A_MARK, VI0_DATA1_VI0_B1_MARK,
+ RMII0_MDC_A_MARK, ET0_COL_MARK,
+ HRX0_A_MARK, RX1_A_MARK, VI0_DATA0_VI0_B0_MARK,
+ RMII0_CRS_DV_A_MARK, ET0_CRS_MARK,
+ HSCK0_A_MARK, SCK1_A_MARK, VI0_VSYNC_MARK,
+ RMII0_RX_ER_A_MARK, ET0_RX_ER_MARK,
+ HRTS0_A_MARK, RTS1_A_MARK, VI0_HSYNC_MARK,
+ RMII0_TXD_EN_A_MARK, ET0_RX_DV_MARK,
+ HCTS0_A_MARK, CTS1_A_MARK, VI0_FIELD_MARK,
+ RMII0_RXD1_A_MARK, ET0_ERXD7_MARK,
+
+ /* IPSR5 */
+ SD2_CLK_A_MARK, RX2_A_MARK, VI0_G4_MARK, ET0_RX_CLK_B_MARK,
+ SD2_CMD_A_MARK, TX2_A_MARK, VI0_G5_MARK, ET0_ERXD2_B_MARK,
+ SD2_DAT0_A_MARK, RX3_A_MARK, VI0_R0_MARK, ET0_ERXD3_B_MARK,
+ SD2_DAT1_A_MARK, TX3_A_MARK, VI0_R1_MARK, ET0_MDIO_B_MARK,
+ SD2_DAT2_A_MARK, RX4_A_MARK, VI0_R2_MARK, ET0_LINK_B_MARK,
+ SD2_DAT3_A_MARK, TX4_A_MARK, VI0_R3_MARK, ET0_MAGIC_B_MARK,
+ SD2_CD_A_MARK, RX5_A_MARK, VI0_R4_MARK, ET0_PHY_INT_B_MARK,
+ SD2_WP_A_MARK, TX5_A_MARK, VI0_R5_MARK,
+ REF125CK_MARK, ADTRG_MARK, RX5_C_MARK,
+ REF50CK_MARK, CTS1_E_MARK, HCTS0_D_MARK,
+
+ /* IPSR6 */
+ DU0_DR0_MARK, SCIF_CLK_B_MARK, HRX0_D_MARK, IETX_A_MARK,
+ TCLKA_A_MARK, HIFD00_MARK,
+ DU0_DR1_MARK, SCK0_B_MARK, HTX0_D_MARK, IERX_A_MARK,
+ TCLKB_A_MARK, HIFD01_MARK,
+ DU0_DR2_MARK, RX0_B_MARK, TCLKC_A_MARK, HIFD02_MARK,
+ DU0_DR3_MARK, TX0_B_MARK, TCLKD_A_MARK, HIFD03_MARK,
+ DU0_DR4_MARK, CTS0_C_MARK, TIOC0A_A_MARK, HIFD04_MARK,
+ DU0_DR5_MARK, RTS0_C_MARK, TIOC0B_A_MARK, HIFD05_MARK,
+ DU0_DR6_MARK, SCK1_C_MARK, TIOC0C_A_MARK, HIFD06_MARK,
+ DU0_DR7_MARK, RX1_C_MARK, TIOC0D_A_MARK, HIFD07_MARK,
+ DU0_DG0_MARK, TX1_C_MARK, HSCK0_D_MARK, IECLK_A_MARK,
+ TIOC1A_A_MARK, HIFD08_MARK,
+ DU0_DG1_MARK, CTS1_C_MARK, HRTS0_D_MARK, TIOC1B_A_MARK,
+ HIFD09_MARK,
+
+ /* IPSR7 */
+ DU0_DG2_MARK, RTS1_C_MARK, RMII0_MDC_B_MARK, TIOC2A_A_MARK,
+ HIFD10_MARK,
+ DU0_DG3_MARK, SCK2_C_MARK, RMII0_MDIO_B_MARK, TIOC2B_A_MARK,
+ HIFD11_MARK,
+ DU0_DG4_MARK, RX2_C_MARK, RMII0_CRS_DV_B_MARK, TIOC3A_A_MARK,
+ HIFD12_MARK,
+ DU0_DG5_MARK, TX2_C_MARK, RMII0_RX_ER_B_MARK, TIOC3B_A_MARK,
+ HIFD13_MARK,
+ DU0_DG6_MARK, RX3_C_MARK, RMII0_RXD0_B_MARK, TIOC3C_A_MARK,
+ HIFD14_MARK,
+ DU0_DG7_MARK, TX3_C_MARK, RMII0_RXD1_B_MARK, TIOC3D_A_MARK,
+ HIFD15_MARK,
+ DU0_DB0_MARK, RX4_C_MARK, RMII0_TXD_EN_B_MARK, TIOC4A_A_MARK,
+ HIFCS_MARK,
+ DU0_DB1_MARK, TX4_C_MARK, RMII0_TXD0_B_MARK, TIOC4B_A_MARK,
+ HIFRS_MARK,
+ DU0_DB2_MARK, RX5_B_MARK, RMII0_TXD1_B_MARK, TIOC4C_A_MARK,
+ HIFWR_MARK,
+ DU0_DB3_MARK, TX5_B_MARK, TIOC4D_A_MARK, HIFRD_MARK,
+ DU0_DB4_MARK, HIFINT_MARK,
+
+ /* IPSR8 */
+ DU0_DB5_MARK, HIFDREQ_MARK,
+ DU0_DB6_MARK, HIFRDY_MARK,
+ DU0_DB7_MARK, SSI_SCK0_B_MARK, HIFEBL_B_MARK,
+ DU0_DOTCLKIN_MARK, HSPI_CS0_C_MARK, SSI_WS0_B_MARK,
+ DU0_DOTCLKOUT_MARK, HSPI_CLK0_C_MARK, SSI_SDATA0_B_MARK,
+ DU0_EXHSYNC_DU0_HSYNC_MARK, HSPI_TX0_C_MARK, SSI_SCK1_B_MARK,
+ DU0_EXVSYNC_DU0_VSYNC_MARK, HSPI_RX0_C_MARK, SSI_WS1_B_MARK,
+ DU0_EXODDF_DU0_ODDF_MARK, CAN0_RX_B_MARK, HSCK0_B_MARK,
+ SSI_SDATA1_B_MARK,
+ DU0_DISP_MARK, CAN0_TX_B_MARK, HRX0_B_MARK, AUDIO_CLKA_B_MARK,
+ DU0_CDE_MARK, HTX0_B_MARK, AUDIO_CLKB_B_MARK, LCD_VCPWC_B_MARK,
+ IRQ0_A_MARK, HSPI_TX_B_MARK, RX3_E_MARK, ET0_ERXD0_MARK,
+ IRQ1_A_MARK, HSPI_RX_B_MARK, TX3_E_MARK, ET0_ERXD1_MARK,
+ IRQ2_A_MARK, CTS0_A_MARK, HCTS0_B_MARK, ET0_ERXD2_A_MARK,
+ IRQ3_A_MARK, RTS0_A_MARK, HRTS0_B_MARK, ET0_ERXD3_A_MARK,
+
+ /* IPSR9 */
+ VI1_CLK_A_MARK, FD0_B_MARK, LCD_DATA0_B_MARK,
+ VI1_0_A_MARK, FD1_B_MARK, LCD_DATA1_B_MARK,
+ VI1_1_A_MARK, FD2_B_MARK, LCD_DATA2_B_MARK,
+ VI1_2_A_MARK, FD3_B_MARK, LCD_DATA3_B_MARK,
+ VI1_3_A_MARK, FD4_B_MARK, LCD_DATA4_B_MARK,
+ VI1_4_A_MARK, FD5_B_MARK, LCD_DATA5_B_MARK,
+ VI1_5_A_MARK, FD6_B_MARK, LCD_DATA6_B_MARK,
+ VI1_6_A_MARK, FD7_B_MARK, LCD_DATA7_B_MARK,
+ VI1_7_A_MARK, FCE_B_MARK, LCD_DATA8_B_MARK,
+ SSI_SCK0_A_MARK, TIOC1A_B_MARK, LCD_DATA9_B_MARK,
+ SSI_WS0_A_MARK, TIOC1B_B_MARK, LCD_DATA10_B_MARK,
+ SSI_SDATA0_A_MARK, VI1_0_B_MARK, TIOC2A_B_MARK, LCD_DATA11_B_MARK,
+ SSI_SCK1_A_MARK, VI1_1_B_MARK, TIOC2B_B_MARK, LCD_DATA12_B_MARK,
+ SSI_WS1_A_MARK, VI1_2_B_MARK, LCD_DATA13_B_MARK,
+ SSI_SDATA1_A_MARK, VI1_3_B_MARK, LCD_DATA14_B_MARK,
+
+ /* IPSR10 */
+ SSI_SCK23_MARK, VI1_4_B_MARK, RX1_D_MARK, FCLE_B_MARK,
+ LCD_DATA15_B_MARK,
+ SSI_WS23_MARK, VI1_5_B_MARK, TX1_D_MARK, HSCK0_C_MARK,
+ FALE_B_MARK, LCD_DON_B_MARK,
+ SSI_SDATA2_MARK, VI1_6_B_MARK, HRX0_C_MARK, FRE_B_MARK,
+ LCD_CL1_B_MARK,
+ SSI_SDATA3_MARK, VI1_7_B_MARK, HTX0_C_MARK, FWE_B_MARK,
+ LCD_CL2_B_MARK,
+ AUDIO_CLKA_A_MARK, VI1_CLK_B_MARK, SCK1_D_MARK, IECLK_B_MARK,
+ LCD_FLM_B_MARK,
+ AUDIO_CLKB_A_MARK, LCD_CLK_B_MARK,
+ AUDIO_CLKC_MARK, SCK1_E_MARK, HCTS0_C_MARK, FRB_B_MARK,
+ LCD_VEPWC_B_MARK,
+ AUDIO_CLKOUT_MARK, TX1_E_MARK, HRTS0_C_MARK, FSE_B_MARK,
+ LCD_M_DISP_B_MARK,
+ CAN_CLK_A_MARK, RX4_D_MARK,
+ CAN0_TX_A_MARK, TX4_D_MARK, MLB_CLK_MARK,
+ CAN1_RX_A_MARK, IRQ1_B_MARK,
+ CAN0_RX_A_MARK, IRQ0_B_MARK, MLB_SIG_MARK,
+ CAN1_TX_A_MARK, TX5_C_MARK, MLB_DAT_MARK,
+
+ /* IPSR11 */
+ SCL1_MARK, SCIF_CLK_C_MARK,
+ SDA1_MARK, RX1_E_MARK,
+ SDA0_MARK, HIFEBL_A_MARK,
+ SDSELF_MARK, RTS1_E_MARK,
+ SCIF_CLK_A_MARK, HSPI_CLK_A_MARK, VI0_CLK_MARK, RMII0_TXD0_A_MARK,
+ ET0_ERXD4_MARK,
+ SCK0_A_MARK, HSPI_CS_A_MARK, VI0_CLKENB_MARK, RMII0_TXD1_A_MARK,
+ ET0_ERXD5_MARK,
+ RX0_A_MARK, HSPI_RX_A_MARK, RMII0_RXD0_A_MARK, ET0_ERXD6_MARK,
+ TX0_A_MARK, HSPI_TX_A_MARK,
+ PENC1_MARK, TX3_D_MARK, CAN1_TX_B_MARK, TX5_D_MARK,
+ IETX_B_MARK,
+ USB_OVC1_MARK, RX3_D_MARK, CAN1_RX_B_MARK, RX5_D_MARK,
+ IERX_B_MARK,
+ DREQ0_MARK, SD1_CLK_A_MARK, ET0_TX_EN_MARK,
+ DACK0_MARK, SD1_DAT3_A_MARK, ET0_TX_ER_MARK,
+ DREQ1_MARK, HSPI_CLK_B_MARK, RX4_B_MARK, ET0_PHY_INT_C_MARK,
+ ET0_TX_CLK_A_MARK,
+ DACK1_MARK, HSPI_CS_B_MARK, TX4_B_MARK, ET0_RX_CLK_A_MARK,
+ PRESETOUT_MARK, ST_CLKOUT_MARK,
+
+ PINMUX_MARK_END,
+};
+
+static pinmux_enum_t pinmux_data[] = {
+ PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
+
+ PINMUX_DATA(CLKOUT_MARK, FN_CLKOUT),
+ PINMUX_DATA(BS_MARK, FN_BS), PINMUX_DATA(CS0_MARK, FN_CS0),
+ PINMUX_DATA(EX_CS0_MARK, FN_EX_CS0),
+ PINMUX_DATA(RD_MARK, FN_RD), PINMUX_DATA(WE0_MARK, FN_WE0),
+ PINMUX_DATA(WE1_MARK, FN_WE1),
+ PINMUX_DATA(SCL0_MARK, FN_SCL0), PINMUX_DATA(PENC0_MARK, FN_PENC0),
+ PINMUX_DATA(USB_OVC0_MARK, FN_USB_OVC0),
+ PINMUX_DATA(IRQ2_B_MARK, FN_IRQ2_B),
+ PINMUX_DATA(IRQ3_B_MARK, FN_IRQ3_B),
+
+ /* IPSR0 */
+ PINMUX_IPSR_DATA(IP0_1_0, A0),
+ PINMUX_IPSR_DATA(IP0_1_0, ST0_CLKIN),
+ PINMUX_IPSR_MODSEL_DATA(IP0_1_0, LCD_DATA0_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_1_0, TCLKA_C, SEL_MTU2_CLK_1),
+
+ PINMUX_IPSR_DATA(IP0_3_2, A1),
+ PINMUX_IPSR_DATA(IP0_3_2, ST0_REQ),
+ PINMUX_IPSR_MODSEL_DATA(IP0_3_2, LCD_DATA1_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_3_2, TCLKB_C, SEL_MTU2_CLK_1),
+
+ PINMUX_IPSR_DATA(IP0_5_4, A2),
+ PINMUX_IPSR_DATA(IP0_5_4, ST0_SYC),
+ PINMUX_IPSR_MODSEL_DATA(IP0_5_4, LCD_DATA2_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_5_4, TCLKC_C, SEL_MTU2_CLK_1),
+
+ PINMUX_IPSR_DATA(IP0_7_6, A3),
+ PINMUX_IPSR_DATA(IP0_7_6, ST0_VLD),
+ PINMUX_IPSR_MODSEL_DATA(IP0_7_6, LCD_DATA3_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_7_6, TCLKD_C, SEL_MTU2_CLK_1),
+
+ PINMUX_IPSR_DATA(IP0_9_8, A4),
+ PINMUX_IPSR_DATA(IP0_9_8, ST0_D0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_9_8, LCD_DATA4_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_9_8, TIOC0A_C, SEL_MTU2_CH0_1),
+
+ PINMUX_IPSR_DATA(IP0_11_10, A5),
+ PINMUX_IPSR_DATA(IP0_11_10, ST0_D1),
+ PINMUX_IPSR_MODSEL_DATA(IP0_11_10, LCD_DATA5_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_11_10, TIOC0B_C, SEL_MTU2_CH0_1),
+
+ PINMUX_IPSR_DATA(IP0_13_12, A6),
+ PINMUX_IPSR_DATA(IP0_13_12, ST0_D2),
+ PINMUX_IPSR_MODSEL_DATA(IP0_13_12, LCD_DATA6_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_13_12, TIOC0C_C, SEL_MTU2_CH0_1),
+
+ PINMUX_IPSR_DATA(IP0_15_14, A7),
+ PINMUX_IPSR_DATA(IP0_15_14, ST0_D3),
+ PINMUX_IPSR_MODSEL_DATA(IP0_15_14, LCD_DATA7_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_15_14, TIOC0D_C, SEL_MTU2_CH0_1),
+
+ PINMUX_IPSR_DATA(IP0_17_16, A8),
+ PINMUX_IPSR_DATA(IP0_17_16, ST0_D4),
+ PINMUX_IPSR_MODSEL_DATA(IP0_17_16, LCD_DATA8_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_17_16, TIOC1A_C, SEL_MTU2_CH1_2),
+
+ PINMUX_IPSR_DATA(IP0_19_18, A9),
+ PINMUX_IPSR_DATA(IP0_19_18, ST0_D5),
+ PINMUX_IPSR_MODSEL_DATA(IP0_19_18, LCD_DATA9_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_19_18, TIOC1B_C, SEL_MTU2_CH1_2),
+
+ PINMUX_IPSR_DATA(IP0_21_20, A10),
+ PINMUX_IPSR_DATA(IP0_21_20, ST0_D6),
+ PINMUX_IPSR_MODSEL_DATA(IP0_21_20, LCD_DATA10_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_21_20, TIOC2A_C, SEL_MTU2_CH2_2),
+
+ PINMUX_IPSR_DATA(IP0_23_22, A11),
+ PINMUX_IPSR_DATA(IP0_23_22, ST0_D7),
+ PINMUX_IPSR_MODSEL_DATA(IP0_23_22, LCD_DATA11_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_23_22, TIOC2B_C, SEL_MTU2_CH2_2),
+
+ PINMUX_IPSR_DATA(IP0_25_24, A12),
+ PINMUX_IPSR_MODSEL_DATA(IP0_25_24, LCD_DATA12_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_25_24, TIOC3A_C, SEL_MTU2_CH3_1),
+
+ PINMUX_IPSR_DATA(IP0_27_26, A13),
+ PINMUX_IPSR_MODSEL_DATA(IP0_27_26, LCD_DATA13_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_27_26, TIOC3B_C, SEL_MTU2_CH3_1),
+
+ PINMUX_IPSR_DATA(IP0_29_28, A14),
+ PINMUX_IPSR_MODSEL_DATA(IP0_29_28, LCD_DATA14_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_29_28, TIOC3C_C, SEL_MTU2_CH3_1),
+
+ PINMUX_IPSR_DATA(IP0_31_30, A15),
+ PINMUX_IPSR_DATA(IP0_31_30, ST0_VCO_CLKIN),
+ PINMUX_IPSR_MODSEL_DATA(IP0_31_30, LCD_DATA15_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP0_31_30, TIOC3D_C, SEL_MTU2_CH3_1),
+
+
+ /* IPSR1 */
+ PINMUX_IPSR_DATA(IP1_1_0, A16),
+ PINMUX_IPSR_DATA(IP1_1_0, ST0_PWM),
+ PINMUX_IPSR_MODSEL_DATA(IP1_1_0, LCD_DON_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP1_1_0, TIOC4A_C, SEL_MTU2_CH4_1),
+
+ PINMUX_IPSR_DATA(IP1_3_2, A17),
+ PINMUX_IPSR_DATA(IP1_3_2, ST1_VCO_CLKIN),
+ PINMUX_IPSR_MODSEL_DATA(IP1_3_2, LCD_CL1_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP1_3_2, TIOC4B_C, SEL_MTU2_CH4_1),
+
+ PINMUX_IPSR_DATA(IP1_5_4, A18),
+ PINMUX_IPSR_DATA(IP1_5_4, ST1_PWM),
+ PINMUX_IPSR_MODSEL_DATA(IP1_5_4, LCD_CL2_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP1_5_4, TIOC4C_C, SEL_MTU2_CH4_1),
+
+ PINMUX_IPSR_DATA(IP1_7_6, A19),
+ PINMUX_IPSR_DATA(IP1_7_6, ST1_CLKIN),
+ PINMUX_IPSR_MODSEL_DATA(IP1_7_6, LCD_CLK_A, SEL_LCDC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP1_7_6, TIOC4D_C, SEL_MTU2_CH4_1),
+
+ PINMUX_IPSR_DATA(IP1_9_8, A20),
+ PINMUX_IPSR_DATA(IP1_9_8, ST1_REQ),
+ PINMUX_IPSR_MODSEL_DATA(IP1_9_8, LCD_FLM_A, SEL_LCDC_0),
+
+ PINMUX_IPSR_DATA(IP1_11_10, A21),
+ PINMUX_IPSR_DATA(IP1_11_10, ST1_SYC),
+ PINMUX_IPSR_MODSEL_DATA(IP1_11_10, LCD_VCPWC_A, SEL_LCDC_0),
+
+ PINMUX_IPSR_DATA(IP1_13_12, A22),
+ PINMUX_IPSR_DATA(IP1_13_12, ST1_VLD),
+ PINMUX_IPSR_MODSEL_DATA(IP1_13_12, LCD_VEPWC_A, SEL_LCDC_0),
+
+ PINMUX_IPSR_DATA(IP1_15_14, A23),
+ PINMUX_IPSR_DATA(IP1_15_14, ST1_D0),
+ PINMUX_IPSR_MODSEL_DATA(IP1_15_14, LCD_M_DISP_A, SEL_LCDC_0),
+
+ PINMUX_IPSR_DATA(IP1_17_16, A24),
+ PINMUX_IPSR_MODSEL_DATA(IP1_17_16, RX2_D, SEL_SCIF2_3),
+ PINMUX_IPSR_DATA(IP1_17_16, ST1_D1),
+
+ PINMUX_IPSR_DATA(IP1_19_18, A25),
+ PINMUX_IPSR_MODSEL_DATA(IP1_17_16, RX2_D, SEL_SCIF2_3),
+ PINMUX_IPSR_DATA(IP1_17_16, ST1_D2),
+
+ PINMUX_IPSR_DATA(IP1_22_20, D0),
+ PINMUX_IPSR_MODSEL_DATA(IP1_22_20, SD0_DAT0_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP1_22_20, MMC_D0_A, SEL_MMC_0),
+ PINMUX_IPSR_DATA(IP1_22_20, ST1_D3),
+ PINMUX_IPSR_MODSEL_DATA(IP1_22_20, FD0_A, SEL_FLCTL_0),
+
+ PINMUX_IPSR_DATA(IP1_25_23, D1),
+ PINMUX_IPSR_MODSEL_DATA(IP1_25_23, SD0_DAT0_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP1_25_23, MMC_D1_A, SEL_MMC_0),
+ PINMUX_IPSR_DATA(IP1_25_23, ST1_D4),
+ PINMUX_IPSR_MODSEL_DATA(IP1_25_23, FD1_A, SEL_FLCTL_0),
+
+ PINMUX_IPSR_DATA(IP1_28_26, D2),
+ PINMUX_IPSR_MODSEL_DATA(IP1_28_26, SD0_DAT0_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP1_28_26, MMC_D2_A, SEL_MMC_0),
+ PINMUX_IPSR_DATA(IP1_28_26, ST1_D5),
+ PINMUX_IPSR_MODSEL_DATA(IP1_28_26, FD2_A, SEL_FLCTL_0),
+
+ PINMUX_IPSR_DATA(IP1_31_29, D3),
+ PINMUX_IPSR_MODSEL_DATA(IP1_31_29, SD0_DAT0_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP1_31_29, MMC_D3_A, SEL_MMC_0),
+ PINMUX_IPSR_DATA(IP1_31_29, ST1_D6),
+ PINMUX_IPSR_MODSEL_DATA(IP1_31_29, FD3_A, SEL_FLCTL_0),
+
+ /* IPSR2 */
+ PINMUX_IPSR_DATA(IP2_2_0, D4),
+ PINMUX_IPSR_MODSEL_DATA(IP2_2_0, SD0_CD_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_2_0, MMC_D4_A, SEL_MMC_0),
+ PINMUX_IPSR_DATA(IP2_2_0, ST1_D7),
+ PINMUX_IPSR_MODSEL_DATA(IP2_2_0, FD4_A, SEL_FLCTL_0),
+
+ PINMUX_IPSR_DATA(IP2_4_3, D5),
+ PINMUX_IPSR_MODSEL_DATA(IP2_4_3, SD0_WP_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_4_3, MMC_D5_A, SEL_MMC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_4_3, FD5_A, SEL_FLCTL_0),
+
+ PINMUX_IPSR_DATA(IP2_7_5, D6),
+ PINMUX_IPSR_MODSEL_DATA(IP2_7_5, RSPI_RSPCK_A, SEL_RSPI_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_7_5, MMC_D6_A, SEL_MMC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_7_5, QSPCLK_A, SEL_RQSPI_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_7_5, FD6_A, SEL_FLCTL_0),
+
+ PINMUX_IPSR_DATA(IP2_10_8, D7),
+ PINMUX_IPSR_MODSEL_DATA(IP2_10_8, RSPI_SSL_A, SEL_RSPI_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_10_8, MMC_D7_A, SEL_MMC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_10_8, QSSL_A, SEL_RQSPI_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_10_8, FD7_A, SEL_FLCTL_0),
+
+ PINMUX_IPSR_DATA(IP2_13_11, D8),
+ PINMUX_IPSR_MODSEL_DATA(IP2_13_11, SD0_CLK_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_13_11, MMC_CLK_A, SEL_MMC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_13_11, QIO2_A, SEL_RQSPI_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_13_11, FCE_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_13_11, ET0_GTX_CLK_B, SEL_ET0_1),
+
+ PINMUX_IPSR_DATA(IP2_16_14, D9),
+ PINMUX_IPSR_MODSEL_DATA(IP2_16_14, SD0_CMD_A, SEL_SDHI0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_16_14, MMC_CMD_A, SEL_MMC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_16_14, QIO3_A, SEL_RQSPI_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_16_14, FCLE_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_16_14, ET0_ETXD1_B, SEL_ET0_1),
+
+ PINMUX_IPSR_DATA(IP2_19_17, D10),
+ PINMUX_IPSR_MODSEL_DATA(IP2_19_17, RSPI_MOSI_A, SEL_RSPI_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_19_17, QMO_QIO0_A, SEL_RQSPI_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_19_17, FALE_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_19_17, ET0_ETXD2_B, SEL_ET0_1),
+
+ PINMUX_IPSR_DATA(IP2_22_20, D11),
+ PINMUX_IPSR_MODSEL_DATA(IP2_22_20, RSPI_MISO_A, SEL_RSPI_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_22_20, QMI_QIO1_A, SEL_RQSPI_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_22_20, FRE_A, SEL_FLCTL_0),
+
+ PINMUX_IPSR_DATA(IP2_24_23, D12),
+ PINMUX_IPSR_MODSEL_DATA(IP2_24_23, FWE_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_24_23, ET0_ETXD5_B, SEL_ET0_1),
+
+ PINMUX_IPSR_DATA(IP2_27_25, D13),
+ PINMUX_IPSR_MODSEL_DATA(IP2_27_25, RX2_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MODSEL_DATA(IP2_27_25, FRB_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_27_25, ET0_ETXD6_B, SEL_ET0_1),
+
+ PINMUX_IPSR_DATA(IP2_30_28, D14),
+ PINMUX_IPSR_MODSEL_DATA(IP2_30_28, TX2_B, SEL_SCIF2_1),
+ PINMUX_IPSR_MODSEL_DATA(IP2_30_28, FSE_A, SEL_FLCTL_0),
+ PINMUX_IPSR_MODSEL_DATA(IP2_30_28, ET0_TX_CLK_B, SEL_ET0_1),
+
+ /* IPSR3 */
+ PINMUX_IPSR_DATA(IP3_1_0, D15),
+ PINMUX_IPSR_MODSEL_DATA(IP3_1_0, SCK2_B, SEL_SCIF2_1),
+
+ PINMUX_IPSR_DATA(IP3_2, CS1_A26),
+ PINMUX_IPSR_MODSEL_DATA(IP3_2, QIO3_B, SEL_RQSPI_1),
+
+ PINMUX_IPSR_DATA(IP3_5_3, EX_CS1),
+ PINMUX_IPSR_MODSEL_DATA(IP3_5_3, RX3_B, SEL_SCIF2_1),
+ PINMUX_IPSR_DATA(IP3_5_3, ATACS0),
+ PINMUX_IPSR_MODSEL_DATA(IP3_5_3, QIO2_B, SEL_RQSPI_1),
+ PINMUX_IPSR_DATA(IP3_5_3, ET0_ETXD0),
+
+ PINMUX_IPSR_DATA(IP3_8_6, EX_CS2),
+ PINMUX_IPSR_MODSEL_DATA(IP3_8_6, TX3_B, SEL_SCIF3_1),
+ PINMUX_IPSR_DATA(IP3_8_6, ATACS1),
+ PINMUX_IPSR_MODSEL_DATA(IP3_8_6, QSPCLK_B, SEL_RQSPI_1),
+ PINMUX_IPSR_MODSEL_DATA(IP3_8_6, ET0_GTX_CLK_A, SEL_ET0_0),
+
+ PINMUX_IPSR_DATA(IP3_11_9, EX_CS3),
+ PINMUX_IPSR_MODSEL_DATA(IP3_11_9, SD1_CD_A, SEL_SDHI1_0),
+ PINMUX_IPSR_DATA(IP3_11_9, ATARD),
+ PINMUX_IPSR_MODSEL_DATA(IP3_11_9, QMO_QIO0_B, SEL_RQSPI_1),
+ PINMUX_IPSR_MODSEL_DATA(IP3_11_9, ET0_ETXD1_A, SEL_ET0_0),
+
+ PINMUX_IPSR_DATA(IP3_14_12, EX_CS4),
+ PINMUX_IPSR_MODSEL_DATA(IP3_14_12, SD1_WP_A, SEL_SDHI1_0),
+ PINMUX_IPSR_DATA(IP3_14_12, ATAWR),
+ PINMUX_IPSR_MODSEL_DATA(IP3_14_12, QMI_QIO1_B, SEL_RQSPI_1),
+ PINMUX_IPSR_MODSEL_DATA(IP3_14_12, ET0_ETXD2_A, SEL_ET0_0),
+
+ PINMUX_IPSR_DATA(IP3_17_15, EX_CS5),
+ PINMUX_IPSR_MODSEL_DATA(IP3_17_15, SD1_CMD_A, SEL_SDHI1_0),
+ PINMUX_IPSR_DATA(IP3_17_15, ATADIR),
+ PINMUX_IPSR_MODSEL_DATA(IP3_17_15, QSSL_B, SEL_RQSPI_1),
+ PINMUX_IPSR_MODSEL_DATA(IP3_17_15, ET0_ETXD3_A, SEL_ET0_0),
+
+ PINMUX_IPSR_DATA(IP3_19_18, RD_WR),
+ PINMUX_IPSR_DATA(IP3_19_18, TCLK0),
+ PINMUX_IPSR_MODSEL_DATA(IP3_19_18, CAN_CLK_B, SEL_RCAN_CLK_1),
+ PINMUX_IPSR_DATA(IP3_19_18, ET0_ETXD4),
+
+ PINMUX_IPSR_DATA(IP3_20, EX_WAIT0),
+ PINMUX_IPSR_MODSEL_DATA(IP3_20, TCLK1_B, SEL_TMU_1),
+
+ PINMUX_IPSR_DATA(IP3_23_21, EX_WAIT1),
+ PINMUX_IPSR_MODSEL_DATA(IP3_23_21, SD1_DAT0_A, SEL_SDHI1_0),
+ PINMUX_IPSR_DATA(IP3_23_21, DREQ2),
+ PINMUX_IPSR_MODSEL_DATA(IP3_23_21, CAN1_TX_C, SEL_RCAN1_2),
+ PINMUX_IPSR_MODSEL_DATA(IP3_23_21, ET0_LINK_C, SEL_ET0_CTL_2),
+ PINMUX_IPSR_MODSEL_DATA(IP3_23_21, ET0_ETXD5_A, SEL_ET0_0),
+
+ PINMUX_IPSR_DATA(IP3_26_24, EX_WAIT2),
+ PINMUX_IPSR_MODSEL_DATA(IP3_26_24, SD1_DAT1_A, SEL_SDHI1_0),
+ PINMUX_IPSR_DATA(IP3_26_24, DACK2),
+ PINMUX_IPSR_MODSEL_DATA(IP3_26_24, CAN1_RX_C, SEL_RCAN1_2),
+ PINMUX_IPSR_MODSEL_DATA(IP3_26_24, ET0_MAGIC_C, SEL_ET0_CTL_2),
+ PINMUX_IPSR_MODSEL_DATA(IP3_26_24, ET0_ETXD6_A, SEL_ET0_0),
+
+ PINMUX_IPSR_DATA(IP3_29_27, DRACK0),
+ PINMUX_IPSR_MODSEL_DATA(IP3_29_27, SD1_DAT2_A, SEL_SDHI1_0),
+ PINMUX_IPSR_DATA(IP3_29_27, ATAG),
+ PINMUX_IPSR_MODSEL_DATA(IP3_29_27, TCLK1_A, SEL_TMU_0),
+ PINMUX_IPSR_DATA(IP3_29_27, ET0_ETXD7),
+
+ /* IPSR4 */
+ PINMUX_IPSR_MODSEL_DATA(IP4_2_0, HCTS0_A, SEL_HSCIF_0),
+ PINMUX_IPSR_MODSEL_DATA(IP4_2_0, CTS1_A, SEL_SCIF1_0),
+ PINMUX_IPSR_DATA(IP4_2_0, VI0_FIELD),
+ PINMUX_IPSR_MODSEL_DATA(IP4_2_0, RMII0_RXD1_A, SEL_RMII_0),
+ PINMUX_IPSR_DATA(IP4_2_0, ET0_ERXD7),
+
+ PINMUX_IPSR_MODSEL_DATA(IP4_5_3, HRTS0_A, SEL_HSCIF_0),
+ PINMUX_IPSR_MODSEL_DATA(IP4_5_3, RTS1_A, SEL_SCIF1_0),
+ PINMUX_IPSR_DATA(IP4_5_3, VI0_HSYNC),
+ PINMUX_IPSR_MODSEL_DATA(IP4_5_3, RMII0_TXD_EN_A, SEL_RMII_0),
+ PINMUX_IPSR_DATA(IP4_5_3, ET0_RX_DV),
+
+ PINMUX_IPSR_MODSEL_DATA(IP4_8_6, HSCK0_A, SEL_HSCIF_0),
+ PINMUX_IPSR_MODSEL_DATA(IP4_8_6, SCK1_A, SEL_SCIF1_0),
+ PINMUX_IPSR_DATA(IP4_8_6, VI0_VSYNC),
+ PINMUX_IPSR_MODSEL_DATA(IP4_8_6, RMII0_RX_ER_A, SEL_RMII_0),
+ PINMUX_IPSR_DATA(IP4_8_6, ET0_RX_ER),
+
+ PINMUX_IPSR_MODSEL_DATA(IP4_11_9, HRX0_A, SEL_HSCIF_0),
+ PINMUX_IPSR_MODSEL_DATA(IP4_11_9, RX1_A, SEL_SCIF1_0),
+ PINMUX_IPSR_DATA(IP4_11_9, VI0_DATA0_VI0_B0),
+ PINMUX_IPSR_MODSEL_DATA(IP4_11_9, RMII0_CRS_DV_A, SEL_RMII_0),
+ PINMUX_IPSR_DATA(IP4_11_9, ET0_CRS),
+
+ PINMUX_IPSR_MODSEL_DATA(IP4_14_12, HTX0_A, SEL_HSCIF_0),
+ PINMUX_IPSR_MODSEL_DATA(IP4_14_12, TX1_A, SEL_SCIF1_0),
+ PINMUX_IPSR_DATA(IP4_14_12, VI0_DATA1_VI0_B1),
+ PINMUX_IPSR_MODSEL_DATA(IP4_14_12, RMII0_MDC_A, SEL_RMII_0),
+ PINMUX_IPSR_DATA(IP4_14_12, ET0_COL),
+
+ PINMUX_IPSR_MODSEL_DATA(IP4_17_15, CTS0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_DATA(IP4_17_15, VI0_DATA2_VI0_B2),
+ PINMUX_IPSR_MODSEL_DATA(IP4_17_15, RMII0_MDIO_A, SEL_RMII_0),
+ PINMUX_IPSR_DATA(IP4_17_15, ET0_MDC),
+
+ PINMUX_IPSR_MODSEL_DATA(IP4_19_18, RTS0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_DATA(IP4_19_18, VI0_DATA3_VI0_B3),
+ PINMUX_IPSR_MODSEL_DATA(IP4_19_18, ET0_MDIO_A, SEL_ET0_0),
+
+ PINMUX_IPSR_MODSEL_DATA(IP4_21_20, SCK1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_DATA(IP4_21_20, VI0_DATA4_VI0_B4),
+ PINMUX_IPSR_MODSEL_DATA(IP4_21_20, ET0_LINK_A, SEL_ET0_CTL_0),
+
+ PINMUX_IPSR_MODSEL_DATA(IP4_23_22, RX1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_DATA(IP4_23_22, VI0_DATA5_VI0_B5),
+ PINMUX_IPSR_MODSEL_DATA(IP4_23_22, ET0_MAGIC_A, SEL_ET0_CTL_0),
+
+ PINMUX_IPSR_MODSEL_DATA(IP4_25_24, TX1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_DATA(IP4_25_24, VI0_DATA6_VI0_G0),
+ PINMUX_IPSR_MODSEL_DATA(IP4_25_24, ET0_PHY_INT_A, SEL_ET0_CTL_0),
+
+ PINMUX_IPSR_MODSEL_DATA(IP4_27_26, CTS1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_DATA(IP4_27_26, VI0_DATA7_VI0_G1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP4_29_28, RTS1_B, SEL_SCIF1_1),
+ PINMUX_IPSR_DATA(IP4_29_28, VI0_G2),
+
+ PINMUX_IPSR_MODSEL_DATA(IP4_31_30, SCK2_A, SEL_SCIF2_0),
+ PINMUX_IPSR_DATA(IP4_31_30, VI0_G3),
+
+ /* IPSR5 */
+ PINMUX_IPSR_MODSEL_DATA(IP5_2_0, SD2_CLK_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MODSEL_DATA(IP5_2_0, RX2_A, SEL_SCIF2_0),
+ PINMUX_IPSR_DATA(IP5_2_0, VI0_G4),
+ PINMUX_IPSR_MODSEL_DATA(IP5_2_0, ET0_RX_CLK_B, SEL_ET0_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP5_5_3, SD2_CMD_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MODSEL_DATA(IP5_5_3, TX2_A, SEL_SCIF2_0),
+ PINMUX_IPSR_DATA(IP5_5_3, VI0_G5),
+ PINMUX_IPSR_MODSEL_DATA(IP5_5_3, ET0_ERXD2_B, SEL_ET0_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP5_8_6, SD2_DAT0_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MODSEL_DATA(IP5_8_6, RX3_A, SEL_SCIF3_0),
+ PINMUX_IPSR_DATA(IP4_8_6, VI0_R0),
+ PINMUX_IPSR_MODSEL_DATA(IP4_8_6, ET0_ERXD2_B, SEL_ET0_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP5_11_9, SD2_DAT1_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MODSEL_DATA(IP5_11_9, TX3_A, SEL_SCIF3_0),
+ PINMUX_IPSR_DATA(IP5_11_9, VI0_R1),
+ PINMUX_IPSR_MODSEL_DATA(IP5_11_9, ET0_MDIO_B, SEL_ET0_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP5_14_12, SD2_DAT2_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MODSEL_DATA(IP5_14_12, RX4_A, SEL_SCIF4_0),
+ PINMUX_IPSR_DATA(IP5_14_12, VI0_R2),
+ PINMUX_IPSR_MODSEL_DATA(IP5_14_12, ET0_LINK_B, SEL_ET0_CTL_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP5_17_15, SD2_DAT3_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MODSEL_DATA(IP5_17_15, TX4_A, SEL_SCIF4_0),
+ PINMUX_IPSR_DATA(IP5_17_15, VI0_R3),
+ PINMUX_IPSR_MODSEL_DATA(IP5_17_15, ET0_MAGIC_B, SEL_ET0_CTL_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP5_20_18, SD2_CD_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MODSEL_DATA(IP5_20_18, RX5_A, SEL_SCIF5_0),
+ PINMUX_IPSR_DATA(IP5_20_18, VI0_R4),
+ PINMUX_IPSR_MODSEL_DATA(IP5_20_18, ET0_PHY_INT_B, SEL_ET0_CTL_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP5_22_21, SD2_WP_A, SEL_SDHI2_0),
+ PINMUX_IPSR_MODSEL_DATA(IP5_22_21, TX5_A, SEL_SCIF5_0),
+ PINMUX_IPSR_DATA(IP5_22_21, VI0_R5),
+
+ PINMUX_IPSR_DATA(IP5_24_23, REF125CK),
+ PINMUX_IPSR_DATA(IP5_24_23, ADTRG),
+ PINMUX_IPSR_MODSEL_DATA(IP5_24_23, RX5_C, SEL_SCIF5_2),
+ PINMUX_IPSR_DATA(IP5_26_25, REF50CK),
+ PINMUX_IPSR_MODSEL_DATA(IP5_26_25, CTS1_E, SEL_SCIF1_3),
+ PINMUX_IPSR_MODSEL_DATA(IP5_26_25, HCTS0_D, SEL_HSCIF_3),
+
+ /* IPSR6 */
+ PINMUX_IPSR_DATA(IP6_2_0, DU0_DR0),
+ PINMUX_IPSR_MODSEL_DATA(IP6_2_0, SCIF_CLK_B, SEL_SCIF_CLK_1),
+ PINMUX_IPSR_MODSEL_DATA(IP6_2_0, HRX0_D, SEL_HSCIF_3),
+ PINMUX_IPSR_MODSEL_DATA(IP6_2_0, IETX_A, SEL_IEBUS_0),
+ PINMUX_IPSR_MODSEL_DATA(IP6_2_0, TCLKA_A, SEL_MTU2_CLK_0),
+ PINMUX_IPSR_DATA(IP6_2_0, HIFD00),
+
+ PINMUX_IPSR_DATA(IP6_5_3, DU0_DR1),
+ PINMUX_IPSR_MODSEL_DATA(IP6_5_3, SCK0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MODSEL_DATA(IP6_5_3, HTX0_D, SEL_HSCIF_3),
+ PINMUX_IPSR_MODSEL_DATA(IP6_5_3, IERX_A, SEL_IEBUS_0),
+ PINMUX_IPSR_MODSEL_DATA(IP6_5_3, TCLKB_A, SEL_MTU2_CLK_0),
+ PINMUX_IPSR_DATA(IP6_5_3, HIFD01),
+
+ PINMUX_IPSR_DATA(IP6_7_6, DU0_DR2),
+ PINMUX_IPSR_MODSEL_DATA(IP6_7_6, RX0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MODSEL_DATA(IP6_7_6, TCLKC_A, SEL_MTU2_CLK_0),
+ PINMUX_IPSR_DATA(IP6_7_6, HIFD02),
+
+ PINMUX_IPSR_DATA(IP6_9_8, DU0_DR3),
+ PINMUX_IPSR_MODSEL_DATA(IP6_9_8, TX0_B, SEL_SCIF0_1),
+ PINMUX_IPSR_MODSEL_DATA(IP6_9_8, TCLKD_A, SEL_MTU2_CLK_0),
+ PINMUX_IPSR_DATA(IP6_9_8, HIFD03),
+
+ PINMUX_IPSR_DATA(IP6_11_10, DU0_DR4),
+ PINMUX_IPSR_MODSEL_DATA(IP6_11_10, CTS0_C, SEL_SCIF0_2),
+ PINMUX_IPSR_MODSEL_DATA(IP6_11_10, TIOC0A_A, SEL_MTU2_CH0_0),
+ PINMUX_IPSR_DATA(IP6_11_10, HIFD04),
+
+ PINMUX_IPSR_DATA(IP6_13_12, DU0_DR5),
+ PINMUX_IPSR_MODSEL_DATA(IP6_13_12, RTS0_C, SEL_SCIF0_1),
+ PINMUX_IPSR_MODSEL_DATA(IP6_13_12, TIOC0B_A, SEL_MTU2_CH0_0),
+ PINMUX_IPSR_DATA(IP6_13_12, HIFD05),
+
+ PINMUX_IPSR_DATA(IP6_15_14, DU0_DR6),
+ PINMUX_IPSR_MODSEL_DATA(IP6_15_14, SCK1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MODSEL_DATA(IP6_15_14, TIOC0C_A, SEL_MTU2_CH0_0),
+ PINMUX_IPSR_DATA(IP6_15_14, HIFD06),
+
+ PINMUX_IPSR_DATA(IP6_17_16, DU0_DR7),
+ PINMUX_IPSR_MODSEL_DATA(IP6_17_16, RX1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MODSEL_DATA(IP6_17_16, TIOC0D_A, SEL_MTU2_CH0_0),
+ PINMUX_IPSR_DATA(IP6_17_16, HIFD07),
+
+ PINMUX_IPSR_DATA(IP6_20_18, DU0_DG0),
+ PINMUX_IPSR_MODSEL_DATA(IP6_20_18, TX1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MODSEL_DATA(IP6_20_18, HSCK0_D, SEL_HSCIF_3),
+ PINMUX_IPSR_MODSEL_DATA(IP6_20_18, IECLK_A, SEL_IEBUS_0),
+ PINMUX_IPSR_MODSEL_DATA(IP6_20_18, TIOC1A_A, SEL_MTU2_CH1_0),
+ PINMUX_IPSR_DATA(IP6_20_18, HIFD08),
+
+ PINMUX_IPSR_DATA(IP6_23_21, DU0_DG1),
+ PINMUX_IPSR_MODSEL_DATA(IP6_23_21, CTS1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MODSEL_DATA(IP6_23_21, HRTS0_D, SEL_HSCIF_3),
+ PINMUX_IPSR_MODSEL_DATA(IP6_23_21, TIOC1B_A, SEL_MTU2_CH1_0),
+ PINMUX_IPSR_DATA(IP6_23_21, HIFD09),
+
+ /* IPSR7 */
+ PINMUX_IPSR_DATA(IP7_2_0, DU0_DG2),
+ PINMUX_IPSR_MODSEL_DATA(IP7_2_0, RTS1_C, SEL_SCIF1_2),
+ PINMUX_IPSR_MODSEL_DATA(IP7_2_0, RMII0_MDC_B, SEL_RMII_1),
+ PINMUX_IPSR_MODSEL_DATA(IP7_2_0, TIOC2A_A, SEL_MTU2_CH2_0),
+ PINMUX_IPSR_DATA(IP7_2_0, HIFD10),
+
+ PINMUX_IPSR_DATA(IP7_5_3, DU0_DG3),
+ PINMUX_IPSR_MODSEL_DATA(IP7_5_3, SCK2_C, SEL_SCIF2_2),
+ PINMUX_IPSR_MODSEL_DATA(IP7_5_3, RMII0_MDIO_B, SEL_RMII_1),
+ PINMUX_IPSR_MODSEL_DATA(IP7_5_3, TIOC2B_A, SEL_MTU2_CH2_0),
+ PINMUX_IPSR_DATA(IP7_5_3, HIFD11),
+
+ PINMUX_IPSR_DATA(IP7_8_6, DU0_DG4),
+ PINMUX_IPSR_MODSEL_DATA(IP7_8_6, RX2_C, SEL_SCIF2_2),
+ PINMUX_IPSR_MODSEL_DATA(IP7_8_6, RMII0_CRS_DV_B, SEL_RMII_1),
+ PINMUX_IPSR_MODSEL_DATA(IP7_8_6, TIOC3A_A, SEL_MTU2_CH3_0),
+ PINMUX_IPSR_DATA(IP7_8_6, HIFD12),
+
+ PINMUX_IPSR_DATA(IP7_11_9, DU0_DG5),
+ PINMUX_IPSR_MODSEL_DATA(IP7_11_9, TX2_C, SEL_SCIF2_2),
+ PINMUX_IPSR_MODSEL_DATA(IP7_11_9, RMII0_RX_ER_B, SEL_RMII_1),
+ PINMUX_IPSR_MODSEL_DATA(IP7_11_9, TIOC3B_A, SEL_MTU2_CH3_0),
+ PINMUX_IPSR_DATA(IP7_11_9, HIFD13),
+
+ PINMUX_IPSR_DATA(IP7_14_12, DU0_DG6),
+ PINMUX_IPSR_MODSEL_DATA(IP7_14_12, RX3_C, SEL_SCIF3_2),
+ PINMUX_IPSR_MODSEL_DATA(IP7_14_12, RMII0_RXD0_B, SEL_RMII_1),
+ PINMUX_IPSR_MODSEL_DATA(IP7_14_12, TIOC3C_A, SEL_MTU2_CH3_0),
+ PINMUX_IPSR_DATA(IP7_14_12, HIFD14),
+
+ PINMUX_IPSR_DATA(IP7_17_15, DU0_DG7),
+ PINMUX_IPSR_MODSEL_DATA(IP7_17_15, TX3_C, SEL_SCIF3_2),
+ PINMUX_IPSR_MODSEL_DATA(IP7_17_15, RMII0_RXD1_B, SEL_RMII_1),
+ PINMUX_IPSR_MODSEL_DATA(IP7_17_15, TIOC3D_A, SEL_MTU2_CH3_0),
+ PINMUX_IPSR_DATA(IP7_17_15, HIFD15),
+
+ PINMUX_IPSR_DATA(IP7_20_18, DU0_DB0),
+ PINMUX_IPSR_MODSEL_DATA(IP7_20_18, RX4_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MODSEL_DATA(IP7_20_18, RMII0_TXD_EN_B, SEL_RMII_1),
+ PINMUX_IPSR_MODSEL_DATA(IP7_20_18, TIOC4A_A, SEL_MTU2_CH4_0),
+ PINMUX_IPSR_DATA(IP7_20_18, HIFCS),
+
+ PINMUX_IPSR_DATA(IP7_23_21, DU0_DB1),
+ PINMUX_IPSR_MODSEL_DATA(IP7_23_21, TX4_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MODSEL_DATA(IP7_23_21, RMII0_TXD0_B, SEL_RMII_1),
+ PINMUX_IPSR_MODSEL_DATA(IP7_23_21, TIOC4B_A, SEL_MTU2_CH4_0),
+ PINMUX_IPSR_DATA(IP7_23_21, HIFWR),
+
+ PINMUX_IPSR_DATA(IP7_26_24, DU0_DB2),
+ PINMUX_IPSR_MODSEL_DATA(IP7_26_24, RX5_B, SEL_SCIF5_1),
+ PINMUX_IPSR_MODSEL_DATA(IP7_26_24, RMII0_TXD1_B, SEL_RMII_1),
+ PINMUX_IPSR_MODSEL_DATA(IP7_26_24, TIOC4C_A, SEL_MTU2_CH4_0),
+
+ PINMUX_IPSR_DATA(IP7_28_27, DU0_DB3),
+ PINMUX_IPSR_MODSEL_DATA(IP7_28_27, TX5_B, SEL_SCIF5_1),
+ PINMUX_IPSR_MODSEL_DATA(IP7_28_27, TIOC4D_A, SEL_MTU2_CH4_0),
+ PINMUX_IPSR_DATA(IP7_28_27, HIFRD),
+
+ PINMUX_IPSR_DATA(IP7_30_29, DU0_DB4),
+ PINMUX_IPSR_DATA(IP7_30_29, HIFINT),
+
+ /* IPSR8 */
+ PINMUX_IPSR_DATA(IP8_1_0, DU0_DB5),
+ PINMUX_IPSR_DATA(IP8_1_0, HIFDREQ),
+
+ PINMUX_IPSR_DATA(IP8_3_2, DU0_DB6),
+ PINMUX_IPSR_DATA(IP8_3_2, HIFRDY),
+
+ PINMUX_IPSR_DATA(IP8_5_4, DU0_DB7),
+ PINMUX_IPSR_MODSEL_DATA(IP8_5_4, SSI_SCK0_B, SEL_SSI0_1),
+ PINMUX_IPSR_MODSEL_DATA(IP8_5_4, HIFEBL_B, SEL_HIF_1),
+
+ PINMUX_IPSR_DATA(IP8_7_6, DU0_DOTCLKIN),
+ PINMUX_IPSR_MODSEL_DATA(IP8_7_6, HSPI_CS0_C, SEL_HSPI_2),
+ PINMUX_IPSR_MODSEL_DATA(IP8_7_6, SSI_WS0_B, SEL_SSI0_1),
+
+ PINMUX_IPSR_DATA(IP8_9_8, DU0_DOTCLKOUT),
+ PINMUX_IPSR_MODSEL_DATA(IP8_9_8, HSPI_CLK0_C, SEL_HSPI_2),
+ PINMUX_IPSR_MODSEL_DATA(IP8_9_8, SSI_SDATA0_B, SEL_SSI0_1),
+
+ PINMUX_IPSR_DATA(IP8_11_10, DU0_EXHSYNC_DU0_HSYNC),
+ PINMUX_IPSR_MODSEL_DATA(IP8_11_10, HSPI_TX0_C, SEL_HSPI_2),
+ PINMUX_IPSR_MODSEL_DATA(IP8_11_10, SSI_SCK1_B, SEL_SSI1_1),
+
+ PINMUX_IPSR_DATA(IP8_13_12, DU0_EXVSYNC_DU0_VSYNC),
+ PINMUX_IPSR_MODSEL_DATA(IP8_13_12, HSPI_RX0_C, SEL_HSPI_2),
+ PINMUX_IPSR_MODSEL_DATA(IP8_13_12, SSI_WS1_B, SEL_SSI1_1),
+
+ PINMUX_IPSR_DATA(IP8_15_14, DU0_EXODDF_DU0_ODDF),
+ PINMUX_IPSR_MODSEL_DATA(IP8_15_14, CAN0_RX_B, SEL_RCAN0_1),
+ PINMUX_IPSR_MODSEL_DATA(IP8_15_14, HSCK0_B, SEL_HSCIF_1),
+ PINMUX_IPSR_MODSEL_DATA(IP8_15_14, SSI_SDATA1_B, SEL_SSI1_1),
+
+ PINMUX_IPSR_DATA(IP8_17_16, DU0_DISP),
+ PINMUX_IPSR_MODSEL_DATA(IP8_17_16, CAN0_TX_B, SEL_RCAN0_1),
+ PINMUX_IPSR_MODSEL_DATA(IP8_17_16, HRX0_B, SEL_HSCIF_1),
+ PINMUX_IPSR_MODSEL_DATA(IP8_17_16, AUDIO_CLKA_B, SEL_AUDIO_CLKA_1),
+
+ PINMUX_IPSR_DATA(IP8_19_18, DU0_CDE),
+ PINMUX_IPSR_MODSEL_DATA(IP8_19_18, HTX0_B, SEL_HSCIF_1),
+ PINMUX_IPSR_MODSEL_DATA(IP8_19_18, AUDIO_CLKB_B, SEL_AUDIO_CLKB_1),
+ PINMUX_IPSR_MODSEL_DATA(IP8_19_18, LCD_VCPWC_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP8_22_20, IRQ0_A, SEL_INTC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP8_22_20, HSPI_TX_B, SEL_HSPI_1),
+ PINMUX_IPSR_MODSEL_DATA(IP8_22_20, RX3_E, SEL_SCIF3_4),
+ PINMUX_IPSR_DATA(IP8_22_20, ET0_ERXD0),
+
+ PINMUX_IPSR_MODSEL_DATA(IP8_25_23, IRQ1_A, SEL_INTC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP8_25_23, HSPI_RX_B, SEL_HSPI_1),
+ PINMUX_IPSR_MODSEL_DATA(IP8_25_23, TX3_E, SEL_SCIF3_4),
+ PINMUX_IPSR_DATA(IP8_25_23, ET0_ERXD1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP8_27_26, IRQ2_A, SEL_INTC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP8_27_26, CTS0_A, SEL_SCIF0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP8_27_26, HCTS0_B, SEL_HSCIF_1),
+ PINMUX_IPSR_MODSEL_DATA(IP8_27_26, ET0_ERXD2_A, SEL_ET0_0),
+
+ PINMUX_IPSR_MODSEL_DATA(IP8_29_28, IRQ3_A, SEL_INTC_0),
+ PINMUX_IPSR_MODSEL_DATA(IP8_29_28, RTS0_A, SEL_SCIF0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP8_29_28, HRTS0_B, SEL_HSCIF_1),
+ PINMUX_IPSR_MODSEL_DATA(IP8_29_28, ET0_ERXD3_A, SEL_ET0_0),
+
+ /* IPSR9 */
+ PINMUX_IPSR_MODSEL_DATA(IP9_1_0, VI1_CLK_A, SEL_VIN1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_1_0, FD0_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_1_0, LCD_DATA0_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_3_2, VI1_0_A, SEL_VIN1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_3_2, FD1_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_3_2, LCD_DATA1_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_5_4, VI1_1_A, SEL_VIN1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_5_4, FD2_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_5_4, LCD_DATA2_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_7_6, VI1_2_A, SEL_VIN1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_7_6, FD3_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_7_6, LCD_DATA3_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_9_8, VI1_3_A, SEL_VIN1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_9_8, FD4_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_9_8, LCD_DATA4_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_11_10, VI1_4_A, SEL_VIN1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_11_10, FD5_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_11_10, LCD_DATA5_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_13_12, VI1_5_A, SEL_VIN1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_13_12, FD6_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_13_12, LCD_DATA6_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_15_14, VI1_6_A, SEL_VIN1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_15_14, FD7_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_15_14, LCD_DATA7_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_17_16, VI1_7_A, SEL_VIN1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_17_16, FCE_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_17_16, LCD_DATA8_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_19_18, SSI_SCK0_A, SEL_SSI0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_19_18, TIOC1A_B, SEL_MTU2_CH1_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_19_18, LCD_DATA9_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_21_20, SSI_WS0_A, SEL_SSI0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_21_20, TIOC1B_B, SEL_MTU2_CH1_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_21_20, LCD_DATA10_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_23_22, SSI_SDATA0_A, SEL_SSI0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_23_22, VI1_0_B, SEL_VIN1_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_23_22, TIOC2A_B, SEL_MTU2_CH2_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_23_22, LCD_DATA11_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_25_24, SSI_SCK1_A, SEL_SSI1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_25_24, VI1_1_B, SEL_VIN1_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_25_24, TIOC2B_B, SEL_MTU2_CH2_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_25_24, LCD_DATA12_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_27_26, SSI_WS1_A, SEL_SSI1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_27_26, VI1_2_B, SEL_VIN1_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_27_26, LCD_DATA13_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP9_29_28, SSI_SDATA1_A, SEL_SSI1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP9_29_28, VI1_3_B, SEL_VIN1_1),
+ PINMUX_IPSR_MODSEL_DATA(IP9_29_28, LCD_DATA14_B, SEL_LCDC_1),
+
+ /* IPSE10 */
+ PINMUX_IPSR_DATA(IP10_2_0, SSI_SCK23),
+ PINMUX_IPSR_MODSEL_DATA(IP10_2_0, VI1_4_B, SEL_VIN1_1),
+ PINMUX_IPSR_MODSEL_DATA(IP10_2_0, RX1_D, SEL_SCIF1_3),
+ PINMUX_IPSR_MODSEL_DATA(IP10_2_0, FCLE_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP10_2_0, LCD_DATA15_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_DATA(IP10_5_3, SSI_WS23),
+ PINMUX_IPSR_MODSEL_DATA(IP10_5_3, VI1_5_B, SEL_VIN1_1),
+ PINMUX_IPSR_MODSEL_DATA(IP10_5_3, TX1_D, SEL_SCIF1_3),
+ PINMUX_IPSR_MODSEL_DATA(IP10_5_3, HSCK0_C, SEL_HSCIF_2),
+ PINMUX_IPSR_MODSEL_DATA(IP10_5_3, FALE_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP10_5_3, LCD_DON_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_DATA(IP10_8_6, SSI_SDATA2),
+ PINMUX_IPSR_MODSEL_DATA(IP10_8_6, VI1_6_B, SEL_VIN1_1),
+ PINMUX_IPSR_MODSEL_DATA(IP10_8_6, HRX0_C, SEL_HSCIF_2),
+ PINMUX_IPSR_MODSEL_DATA(IP10_8_6, FRE_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP10_8_6, LCD_CL1_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_DATA(IP10_11_9, SSI_SDATA3),
+ PINMUX_IPSR_MODSEL_DATA(IP10_11_9, VI1_7_B, SEL_VIN1_1),
+ PINMUX_IPSR_MODSEL_DATA(IP10_11_9, HTX0_C, SEL_HSCIF_2),
+ PINMUX_IPSR_MODSEL_DATA(IP10_11_9, FWE_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP10_11_9, LCD_CL2_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP10_14_12, AUDIO_CLKA_A, SEL_AUDIO_CLKA_0),
+ PINMUX_IPSR_MODSEL_DATA(IP10_14_12, VI1_CLK_B, SEL_VIN1_1),
+ PINMUX_IPSR_MODSEL_DATA(IP10_14_12, SCK1_D, SEL_SCIF1_3),
+ PINMUX_IPSR_MODSEL_DATA(IP10_14_12, IECLK_B, SEL_IEBUS_1),
+ PINMUX_IPSR_MODSEL_DATA(IP10_14_12, LCD_FLM_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP10_15, AUDIO_CLKB_A, SEL_AUDIO_CLKB_0),
+ PINMUX_IPSR_MODSEL_DATA(IP10_15, LCD_CLK_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_DATA(IP10_18_16, AUDIO_CLKC),
+ PINMUX_IPSR_MODSEL_DATA(IP10_18_16, SCK1_E, SEL_SCIF1_4),
+ PINMUX_IPSR_MODSEL_DATA(IP10_18_16, HCTS0_C, SEL_HSCIF_2),
+ PINMUX_IPSR_MODSEL_DATA(IP10_18_16, FRB_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP10_18_16, LCD_VEPWC_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_DATA(IP10_21_19, AUDIO_CLKOUT),
+ PINMUX_IPSR_MODSEL_DATA(IP10_21_19, TX1_E, SEL_SCIF1_4),
+ PINMUX_IPSR_MODSEL_DATA(IP10_21_19, HRTS0_C, SEL_HSCIF_2),
+ PINMUX_IPSR_MODSEL_DATA(IP10_21_19, FSE_B, SEL_FLCTL_1),
+ PINMUX_IPSR_MODSEL_DATA(IP10_21_19, LCD_M_DISP_B, SEL_LCDC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP10_22, CAN_CLK_A, SEL_RCAN_CLK_0),
+ PINMUX_IPSR_MODSEL_DATA(IP10_22, RX4_D, SEL_SCIF4_3),
+
+ PINMUX_IPSR_MODSEL_DATA(IP10_24_23, CAN0_TX_A, SEL_RCAN0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP10_24_23, TX4_D, SEL_SCIF4_3),
+ PINMUX_IPSR_DATA(IP10_24_23, MLB_CLK),
+
+ PINMUX_IPSR_MODSEL_DATA(IP10_25, CAN1_RX_A, SEL_RCAN1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP10_25, IRQ1_B, SEL_INTC_1),
+
+ PINMUX_IPSR_MODSEL_DATA(IP10_27_26, CAN0_RX_A, SEL_RCAN0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP10_27_26, IRQ0_B, SEL_INTC_1),
+ PINMUX_IPSR_DATA(IP10_27_26, MLB_SIG),
+
+ PINMUX_IPSR_MODSEL_DATA(IP10_29_28, CAN1_TX_A, SEL_RCAN1_0),
+ PINMUX_IPSR_MODSEL_DATA(IP10_29_28, TX5_C, SEL_SCIF1_2),
+ PINMUX_IPSR_DATA(IP10_29_28, MLB_DAT),
+
+ /* IPSR11 */
+ PINMUX_IPSR_DATA(IP11_0, SCL1),
+ PINMUX_IPSR_MODSEL_DATA(IP11_0, SCIF_CLK_C, SEL_SCIF_CLK_2),
+
+ PINMUX_IPSR_DATA(IP11_1, SDA1),
+ PINMUX_IPSR_MODSEL_DATA(IP11_0, RX1_E, SEL_SCIF1_4),
+
+ PINMUX_IPSR_DATA(IP11_2, SDA0),
+ PINMUX_IPSR_MODSEL_DATA(IP11_2, HIFEBL_A, SEL_HIF_0),
+
+ PINMUX_IPSR_DATA(IP11_3, SDSELF),
+ PINMUX_IPSR_MODSEL_DATA(IP11_3, RTS1_E, SEL_SCIF1_3),
+
+ PINMUX_IPSR_MODSEL_DATA(IP11_6_4, SCIF_CLK_A, SEL_SCIF_CLK_0),
+ PINMUX_IPSR_MODSEL_DATA(IP11_6_4, HSPI_CLK_A, SEL_HSPI_0),
+ PINMUX_IPSR_DATA(IP11_6_4, VI0_CLK),
+ PINMUX_IPSR_MODSEL_DATA(IP11_6_4, RMII0_TXD0_A, SEL_RMII_0),
+ PINMUX_IPSR_DATA(IP11_6_4, ET0_ERXD4),
+
+ PINMUX_IPSR_MODSEL_DATA(IP11_9_7, SCK0_A, SEL_SCIF0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP11_9_7, HSPI_CS_A, SEL_HSPI_0),
+ PINMUX_IPSR_DATA(IP11_9_7, VI0_CLKENB),
+ PINMUX_IPSR_MODSEL_DATA(IP11_9_7, RMII0_TXD1_A, SEL_RMII_0),
+ PINMUX_IPSR_DATA(IP11_9_7, ET0_ERXD5),
+
+ PINMUX_IPSR_MODSEL_DATA(IP11_11_10, RX0_A, SEL_SCIF0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP11_11_10, HSPI_RX_A, SEL_HSPI_0),
+ PINMUX_IPSR_MODSEL_DATA(IP11_11_10, RMII0_RXD0_A, SEL_RMII_0),
+ PINMUX_IPSR_DATA(IP11_11_10, ET0_ERXD6),
+
+ PINMUX_IPSR_MODSEL_DATA(IP11_12, TX0_A, SEL_SCIF0_0),
+ PINMUX_IPSR_MODSEL_DATA(IP11_12, HSPI_TX_A, SEL_HSPI_0),
+
+ PINMUX_IPSR_DATA(IP11_15_13, PENC1),
+ PINMUX_IPSR_MODSEL_DATA(IP11_15_13, TX3_D, SEL_SCIF3_3),
+ PINMUX_IPSR_MODSEL_DATA(IP11_15_13, CAN1_TX_B, SEL_RCAN1_1),
+ PINMUX_IPSR_MODSEL_DATA(IP11_15_13, TX5_D, SEL_SCIF5_3),
+ PINMUX_IPSR_MODSEL_DATA(IP11_15_13, IETX_B, SEL_IEBUS_1),
+
+ PINMUX_IPSR_DATA(IP11_18_16, USB_OVC1),
+ PINMUX_IPSR_MODSEL_DATA(IP11_18_16, RX3_D, SEL_SCIF3_3),
+ PINMUX_IPSR_MODSEL_DATA(IP11_18_16, CAN1_RX_B, SEL_RCAN1_1),
+ PINMUX_IPSR_MODSEL_DATA(IP11_18_16, RX5_D, SEL_SCIF5_3),
+ PINMUX_IPSR_MODSEL_DATA(IP11_18_16, IERX_B, SEL_IEBUS_1),
+
+ PINMUX_IPSR_DATA(IP11_20_19, DREQ0),
+ PINMUX_IPSR_MODSEL_DATA(IP11_20_19, SD1_CLK_A, SEL_SDHI1_0),
+ PINMUX_IPSR_DATA(IP11_20_19, ET0_TX_EN),
+
+ PINMUX_IPSR_DATA(IP11_22_21, DACK0),
+ PINMUX_IPSR_MODSEL_DATA(IP11_22_21, SD1_DAT3_A, SEL_SDHI1_0),
+ PINMUX_IPSR_DATA(IP11_22_21, ET0_TX_ER),
+
+ PINMUX_IPSR_DATA(IP11_25_23, DREQ1),
+ PINMUX_IPSR_MODSEL_DATA(IP11_25_23, HSPI_CLK_B, SEL_HSPI_1),
+ PINMUX_IPSR_MODSEL_DATA(IP11_25_23, RX4_B, SEL_SCIF4_1),
+ PINMUX_IPSR_MODSEL_DATA(IP11_25_23, ET0_PHY_INT_C, SEL_ET0_CTL_0),
+ PINMUX_IPSR_MODSEL_DATA(IP11_25_23, ET0_TX_CLK_A, SEL_ET0_0),
+
+ PINMUX_IPSR_DATA(IP11_27_26, DACK1),
+ PINMUX_IPSR_MODSEL_DATA(IP11_27_26, HSPI_CS_B, SEL_HSPI_1),
+ PINMUX_IPSR_MODSEL_DATA(IP11_27_26, TX4_B, SEL_SCIF3_1),
+ PINMUX_IPSR_MODSEL_DATA(IP11_27_26, ET0_RX_CLK_A, SEL_ET0_0),
+
+ PINMUX_IPSR_DATA(IP11_28, PRESETOUT),
+ PINMUX_IPSR_DATA(IP11_28, ST_CLKOUT),
+};
+
+static struct pinmux_gpio pinmux_gpios[] = {
+ PINMUX_GPIO_GP_ALL(),
+
+ GPIO_FN(CLKOUT), GPIO_FN(BS), GPIO_FN(CS0), GPIO_FN(EX_CS0),
+ GPIO_FN(RD), GPIO_FN(WE0), GPIO_FN(WE1),
+ GPIO_FN(SCL0), GPIO_FN(PENC0), GPIO_FN(USB_OVC0),
+ GPIO_FN(IRQ2_B), GPIO_FN(IRQ3_B),
+
+ /* IPSR0 */
+ GPIO_FN(A0), GPIO_FN(ST0_CLKIN), GPIO_FN(LCD_DATA0_A),
+ GPIO_FN(TCLKA_C),
+ GPIO_FN(A1), GPIO_FN(ST0_REQ), GPIO_FN(LCD_DATA1_A),
+ GPIO_FN(TCLKB_C),
+ GPIO_FN(A2), GPIO_FN(ST0_SYC), GPIO_FN(LCD_DATA2_A),
+ GPIO_FN(TCLKC_C),
+ GPIO_FN(A3), GPIO_FN(ST0_VLD), GPIO_FN(LCD_DATA3_A),
+ GPIO_FN(TCLKD_C),
+ GPIO_FN(A4), GPIO_FN(ST0_D0), GPIO_FN(LCD_DATA4_A),
+ GPIO_FN(TIOC0A_C),
+ GPIO_FN(A5), GPIO_FN(ST0_D1), GPIO_FN(LCD_DATA5_A),
+ GPIO_FN(TIOC0B_C),
+ GPIO_FN(A6), GPIO_FN(ST0_D2), GPIO_FN(LCD_DATA6_A),
+ GPIO_FN(TIOC0C_C),
+ GPIO_FN(A7), GPIO_FN(ST0_D3), GPIO_FN(LCD_DATA7_A),
+ GPIO_FN(TIOC0D_C),
+ GPIO_FN(A8), GPIO_FN(ST0_D4), GPIO_FN(LCD_DATA8_A),
+ GPIO_FN(TIOC1A_C),
+ GPIO_FN(A9), GPIO_FN(ST0_D5), GPIO_FN(LCD_DATA9_A),
+ GPIO_FN(TIOC1B_C),
+ GPIO_FN(A10), GPIO_FN(ST0_D6), GPIO_FN(LCD_DATA10_A),
+ GPIO_FN(TIOC2A_C),
+ GPIO_FN(A11), GPIO_FN(ST0_D7), GPIO_FN(LCD_DATA11_A),
+ GPIO_FN(TIOC2B_C),
+ GPIO_FN(A12), GPIO_FN(LCD_DATA12_A), GPIO_FN(TIOC3A_C),
+ GPIO_FN(A13), GPIO_FN(LCD_DATA13_A), GPIO_FN(TIOC3B_C),
+ GPIO_FN(A14), GPIO_FN(LCD_DATA14_A), GPIO_FN(TIOC3C_C),
+ GPIO_FN(A15), GPIO_FN(ST0_VCO_CLKIN), GPIO_FN(LCD_DATA15_A),
+ GPIO_FN(TIOC3D_C),
+
+ /* IPSR1 */
+ GPIO_FN(A16), GPIO_FN(ST0_PWM), GPIO_FN(LCD_DON_A),
+ GPIO_FN(TIOC4A_C),
+ GPIO_FN(A17), GPIO_FN(ST1_VCO_CLKIN), GPIO_FN(LCD_CL1_A),
+ GPIO_FN(TIOC4B_C),
+ GPIO_FN(A18), GPIO_FN(ST1_PWM), GPIO_FN(LCD_CL2_A),
+ GPIO_FN(TIOC4C_C),
+ GPIO_FN(A19), GPIO_FN(ST1_CLKIN), GPIO_FN(LCD_CLK_A),
+ GPIO_FN(TIOC4D_C),
+ GPIO_FN(A20), GPIO_FN(ST1_REQ), GPIO_FN(LCD_FLM_A),
+ GPIO_FN(A21), GPIO_FN(ST1_SYC), GPIO_FN(LCD_VCPWC_A),
+ GPIO_FN(A22), GPIO_FN(ST1_VLD), GPIO_FN(LCD_VEPWC_A),
+ GPIO_FN(A23), GPIO_FN(ST1_D0), GPIO_FN(LCD_M_DISP_A),
+ GPIO_FN(A24), GPIO_FN(RX2_D), GPIO_FN(ST1_D1),
+ GPIO_FN(A25), GPIO_FN(TX2_D), GPIO_FN(ST1_D2),
+ GPIO_FN(D0), GPIO_FN(SD0_DAT0_A), GPIO_FN(MMC_D0_A),
+ GPIO_FN(ST1_D3), GPIO_FN(FD0_A),
+ GPIO_FN(D1), GPIO_FN(SD0_DAT1_A), GPIO_FN(MMC_D1_A),
+ GPIO_FN(ST1_D4), GPIO_FN(FD1_A),
+ GPIO_FN(D2), GPIO_FN(SD0_DAT2_A), GPIO_FN(MMC_D2_A),
+ GPIO_FN(ST1_D5), GPIO_FN(FD2_A),
+ GPIO_FN(D3), GPIO_FN(SD0_DAT3_A), GPIO_FN(MMC_D3_A),
+ GPIO_FN(ST1_D6), GPIO_FN(FD3_A),
+
+ /* IPSR2 */
+ GPIO_FN(D4), GPIO_FN(SD0_CD_A), GPIO_FN(MMC_D4_A), GPIO_FN(ST1_D7),
+ GPIO_FN(FD4_A),
+ GPIO_FN(D5), GPIO_FN(SD0_WP_A), GPIO_FN(MMC_D5_A), GPIO_FN(FD5_A),
+ GPIO_FN(D6), GPIO_FN(RSPI_RSPCK_A), GPIO_FN(MMC_D6_A),
+ GPIO_FN(QSPCLK_A),
+ GPIO_FN(FD6_A),
+ GPIO_FN(D7), GPIO_FN(RSPI_SSL_A), GPIO_FN(MMC_D7_A), GPIO_FN(QSSL_A),
+ GPIO_FN(FD7_A),
+ GPIO_FN(D8), GPIO_FN(SD0_CLK_A), GPIO_FN(MMC_CLK_A), GPIO_FN(QIO2_A),
+ GPIO_FN(FCE_A), GPIO_FN(ET0_GTX_CLK_B),
+ GPIO_FN(D9), GPIO_FN(SD0_CMD_A), GPIO_FN(MMC_CMD_A), GPIO_FN(QIO3_A),
+ GPIO_FN(FCLE_A), GPIO_FN(ET0_ETXD1_B),
+ GPIO_FN(D10), GPIO_FN(RSPI_MOSI_A), GPIO_FN(QMO_QIO0_A),
+ GPIO_FN(FALE_A), GPIO_FN(ET0_ETXD2_B),
+ GPIO_FN(D11), GPIO_FN(RSPI_MISO_A), GPIO_FN(QMI_QIO1_A), GPIO_FN(FRE_A),
+ GPIO_FN(ET0_ETXD3_B),
+ GPIO_FN(D12), GPIO_FN(FWE_A), GPIO_FN(ET0_ETXD5_B),
+ GPIO_FN(D13), GPIO_FN(RX2_B), GPIO_FN(FRB_A), GPIO_FN(ET0_ETXD6_B),
+ GPIO_FN(D14), GPIO_FN(TX2_B), GPIO_FN(FSE_A), GPIO_FN(ET0_TX_CLK_B),
+
+ /* IPSR3 */
+ GPIO_FN(D15), GPIO_FN(SCK2_B),
+ GPIO_FN(CS1_A26), GPIO_FN(QIO3_B),
+ GPIO_FN(EX_CS1), GPIO_FN(RX3_B), GPIO_FN(ATACS0), GPIO_FN(QIO2_B),
+ GPIO_FN(ET0_ETXD0),
+ GPIO_FN(EX_CS2), GPIO_FN(TX3_B), GPIO_FN(ATACS1), GPIO_FN(QSPCLK_B),
+ GPIO_FN(ET0_GTX_CLK_A),
+ GPIO_FN(EX_CS3), GPIO_FN(SD1_CD_A), GPIO_FN(ATARD), GPIO_FN(QMO_QIO0_B),
+ GPIO_FN(ET0_ETXD1_A),
+ GPIO_FN(EX_CS4), GPIO_FN(SD1_WP_A), GPIO_FN(ATAWR), GPIO_FN(QMI_QIO1_B),
+ GPIO_FN(ET0_ETXD2_A),
+ GPIO_FN(EX_CS5), GPIO_FN(SD1_CMD_A), GPIO_FN(ATADIR), GPIO_FN(QSSL_B),
+ GPIO_FN(ET0_ETXD3_A),
+ GPIO_FN(RD_WR), GPIO_FN(TCLK1_B),
+ GPIO_FN(EX_WAIT0), GPIO_FN(TCLK1_B),
+ GPIO_FN(EX_WAIT1), GPIO_FN(SD1_DAT0_A), GPIO_FN(DREQ2),
+ GPIO_FN(CAN1_TX_C), GPIO_FN(ET0_LINK_C), GPIO_FN(ET0_ETXD5_A),
+ GPIO_FN(EX_WAIT2), GPIO_FN(SD1_DAT1_A), GPIO_FN(DACK2),
+ GPIO_FN(CAN1_RX_C), GPIO_FN(ET0_MAGIC_C), GPIO_FN(ET0_ETXD6_A),
+ GPIO_FN(DRACK0), GPIO_FN(SD1_DAT2_A), GPIO_FN(ATAG), GPIO_FN(TCLK1_A),
+ GPIO_FN(ET0_ETXD7),
+
+ /* IPSR4 */
+ GPIO_FN(HCTS0_A), GPIO_FN(CTS1_A), GPIO_FN(VI0_FIELD),
+ GPIO_FN(RMII0_RXD1_A), GPIO_FN(ET0_ERXD7),
+ GPIO_FN(HRTS0_A), GPIO_FN(RTS1_A), GPIO_FN(VI0_HSYNC),
+ GPIO_FN(RMII0_TXD_EN_A), GPIO_FN(ET0_RX_DV),
+ GPIO_FN(HSCK0_A), GPIO_FN(SCK1_A), GPIO_FN(VI0_VSYNC),
+ GPIO_FN(RMII0_RX_ER_A), GPIO_FN(ET0_RX_ER),
+ GPIO_FN(HRX0_A), GPIO_FN(RX1_A), GPIO_FN(VI0_DATA0_VI0_B0),
+ GPIO_FN(RMII0_CRS_DV_A), GPIO_FN(ET0_CRS),
+ GPIO_FN(HTX0_A), GPIO_FN(TX1_A), GPIO_FN(VI0_DATA1_VI0_B1),
+ GPIO_FN(RMII0_MDC_A), GPIO_FN(ET0_COL),
+ GPIO_FN(CTS0_B), GPIO_FN(VI0_DATA2_VI0_B2), GPIO_FN(RMII0_MDIO_A),
+ GPIO_FN(ET0_MDC),
+ GPIO_FN(RTS0_B), GPIO_FN(VI0_DATA3_VI0_B3), GPIO_FN(ET0_MDIO_A),
+ GPIO_FN(SCK1_B), GPIO_FN(VI0_DATA4_VI0_B4), GPIO_FN(ET0_LINK_A),
+ GPIO_FN(RX1_B), GPIO_FN(VI0_DATA5_VI0_B5), GPIO_FN(ET0_MAGIC_A),
+ GPIO_FN(TX1_B), GPIO_FN(VI0_DATA6_VI0_G0), GPIO_FN(ET0_PHY_INT_A),
+ GPIO_FN(CTS1_B), GPIO_FN(VI0_DATA7_VI0_G1),
+ GPIO_FN(RTS1_B), GPIO_FN(VI0_G2),
+ GPIO_FN(SCK2_A), GPIO_FN(VI0_G3),
+
+ /* IPSR5 */
+ GPIO_FN(REF50CK), GPIO_FN(CTS1_E), GPIO_FN(HCTS0_D),
+ GPIO_FN(REF125CK), GPIO_FN(ADTRG), GPIO_FN(RX5_C),
+ GPIO_FN(SD2_WP_A), GPIO_FN(TX5_A), GPIO_FN(VI0_R5),
+ GPIO_FN(SD2_CD_A), GPIO_FN(RX5_A), GPIO_FN(VI0_R4),
+ GPIO_FN(ET0_PHY_INT_B),
+ GPIO_FN(SD2_DAT3_A), GPIO_FN(TX4_A), GPIO_FN(VI0_R3),
+ GPIO_FN(ET0_MAGIC_B),
+ GPIO_FN(SD2_DAT2_A), GPIO_FN(RX4_A), GPIO_FN(VI0_R2),
+ GPIO_FN(ET0_LINK_B),
+ GPIO_FN(SD2_DAT1_A), GPIO_FN(TX3_A), GPIO_FN(VI0_R1),
+ GPIO_FN(ET0_MDIO_B),
+ GPIO_FN(SD2_DAT0_A), GPIO_FN(RX3_A), GPIO_FN(VI0_R0),
+ GPIO_FN(ET0_ERXD3_B),
+ GPIO_FN(SD2_CMD_A), GPIO_FN(TX2_A), GPIO_FN(VI0_G5),
+ GPIO_FN(ET0_ERXD2_B),
+ GPIO_FN(SD2_CLK_A), GPIO_FN(RX2_A), GPIO_FN(VI0_G4),
+ GPIO_FN(ET0_RX_CLK_B),
+
+ /* IPSR6 */
+ GPIO_FN(DU0_DG1), GPIO_FN(CTS1_C), GPIO_FN(HRTS0_D),
+ GPIO_FN(TIOC1B_A), GPIO_FN(HIFD09),
+ GPIO_FN(DU0_DG0), GPIO_FN(TX1_C), GPIO_FN(HSCK0_D),
+ GPIO_FN(IECLK_A), GPIO_FN(TIOC1A_A), GPIO_FN(HIFD08),
+ GPIO_FN(DU0_DR7), GPIO_FN(RX1_C), GPIO_FN(TIOC0D_A),
+ GPIO_FN(HIFD07),
+ GPIO_FN(DU0_DR6), GPIO_FN(SCK1_C), GPIO_FN(TIOC0C_A),
+ GPIO_FN(HIFD06),
+ GPIO_FN(DU0_DR5), GPIO_FN(RTS0_C), GPIO_FN(TIOC0B_A),
+ GPIO_FN(HIFD05),
+ GPIO_FN(DU0_DR4), GPIO_FN(CTS0_C), GPIO_FN(TIOC0A_A),
+ GPIO_FN(HIFD04),
+ GPIO_FN(DU0_DR3), GPIO_FN(TX0_B), GPIO_FN(TCLKD_A), GPIO_FN(HIFD03),
+ GPIO_FN(DU0_DR2), GPIO_FN(RX0_B), GPIO_FN(TCLKC_A), GPIO_FN(HIFD02),
+ GPIO_FN(DU0_DR1), GPIO_FN(SCK0_B), GPIO_FN(HTX0_D),
+ GPIO_FN(IERX_A), GPIO_FN(TCLKB_A), GPIO_FN(HIFD01),
+ GPIO_FN(DU0_DR0), GPIO_FN(SCIF_CLK_B), GPIO_FN(HRX0_D),
+ GPIO_FN(IETX_A), GPIO_FN(TCLKA_A), GPIO_FN(HIFD00),
+
+ /* IPSR7 */
+ GPIO_FN(DU0_DB4), GPIO_FN(HIFINT),
+ GPIO_FN(DU0_DB3), GPIO_FN(TX5_B), GPIO_FN(TIOC4D_A), GPIO_FN(HIFRD),
+ GPIO_FN(DU0_DB2), GPIO_FN(RX5_B), GPIO_FN(RMII0_TXD1_B),
+ GPIO_FN(TIOC4C_A), GPIO_FN(HIFWR),
+ GPIO_FN(DU0_DB1), GPIO_FN(TX4_C), GPIO_FN(RMII0_TXD0_B),
+ GPIO_FN(TIOC4B_A), GPIO_FN(HIFRS),
+ GPIO_FN(DU0_DB0), GPIO_FN(RX4_C), GPIO_FN(RMII0_TXD_EN_B),
+ GPIO_FN(TIOC4A_A), GPIO_FN(HIFCS),
+ GPIO_FN(DU0_DG7), GPIO_FN(TX3_C), GPIO_FN(RMII0_RXD1_B),
+ GPIO_FN(TIOC3D_A), GPIO_FN(HIFD15),
+ GPIO_FN(DU0_DG6), GPIO_FN(RX3_C), GPIO_FN(RMII0_RXD0_B),
+ GPIO_FN(TIOC3C_A), GPIO_FN(HIFD14),
+ GPIO_FN(DU0_DG5), GPIO_FN(TX2_C), GPIO_FN(RMII0_RX_ER_B),
+ GPIO_FN(TIOC3B_A), GPIO_FN(HIFD13),
+ GPIO_FN(DU0_DG4), GPIO_FN(RX2_C), GPIO_FN(RMII0_CRS_DV_B),
+ GPIO_FN(TIOC3A_A), GPIO_FN(HIFD12),
+ GPIO_FN(DU0_DG3), GPIO_FN(SCK2_C), GPIO_FN(RMII0_MDIO_B),
+ GPIO_FN(TIOC2B_A), GPIO_FN(HIFD11),
+ GPIO_FN(DU0_DG2), GPIO_FN(RTS1_C), GPIO_FN(RMII0_MDC_B),
+ GPIO_FN(TIOC2A_A), GPIO_FN(HIFD10),
+
+ /* IPSR8 */
+ GPIO_FN(IRQ3_A), GPIO_FN(RTS0_A), GPIO_FN(HRTS0_B),
+ GPIO_FN(ET0_ERXD3_A),
+ GPIO_FN(IRQ2_A), GPIO_FN(CTS0_A), GPIO_FN(HCTS0_B),
+ GPIO_FN(ET0_ERXD2_A),
+ GPIO_FN(IRQ1_A), GPIO_FN(HSPI_RX_B), GPIO_FN(TX3_E),
+ GPIO_FN(ET0_ERXD1),
+ GPIO_FN(IRQ0_A), GPIO_FN(HSPI_TX_B), GPIO_FN(RX3_E),
+ GPIO_FN(ET0_ERXD0),
+ GPIO_FN(DU0_CDE), GPIO_FN(HTX0_B), GPIO_FN(AUDIO_CLKB_B),
+ GPIO_FN(LCD_VCPWC_B),
+ GPIO_FN(DU0_DISP), GPIO_FN(CAN0_TX_B), GPIO_FN(HRX0_B),
+ GPIO_FN(AUDIO_CLKA_B),
+ GPIO_FN(DU0_EXODDF_DU0_ODDF), GPIO_FN(CAN0_RX_B), GPIO_FN(HSCK0_B),
+ GPIO_FN(SSI_SDATA1_B),
+ GPIO_FN(DU0_EXVSYNC_DU0_VSYNC), GPIO_FN(HSPI_RX0_C),
+ GPIO_FN(SSI_WS1_B),
+ GPIO_FN(DU0_EXHSYNC_DU0_HSYNC), GPIO_FN(HSPI_TX0_C),
+ GPIO_FN(SSI_SCK1_B),
+ GPIO_FN(DU0_DOTCLKOUT), GPIO_FN(HSPI_CLK0_C),
+ GPIO_FN(SSI_SDATA0_B),
+ GPIO_FN(DU0_DOTCLKIN), GPIO_FN(HSPI_CS0_C),
+ GPIO_FN(SSI_WS0_B),
+ GPIO_FN(DU0_DB7), GPIO_FN(SSI_SCK0_B), GPIO_FN(HIFEBL_B),
+ GPIO_FN(DU0_DB6), GPIO_FN(HIFRDY),
+ GPIO_FN(DU0_DB5), GPIO_FN(HIFDREQ),
+
+ /* IPSR9 */
+ GPIO_FN(SSI_SDATA1_A), GPIO_FN(VI1_3_B), GPIO_FN(LCD_DATA14_B),
+ GPIO_FN(SSI_WS1_A), GPIO_FN(VI1_2_B), GPIO_FN(LCD_DATA13_B),
+ GPIO_FN(SSI_SCK1_A), GPIO_FN(VI1_1_B), GPIO_FN(TIOC2B_B),
+ GPIO_FN(LCD_DATA12_B),
+ GPIO_FN(SSI_SDATA0_A), GPIO_FN(VI1_0_B), GPIO_FN(TIOC2A_B),
+ GPIO_FN(LCD_DATA11_B),
+ GPIO_FN(SSI_WS0_A), GPIO_FN(TIOC1B_B), GPIO_FN(LCD_DATA10_B),
+ GPIO_FN(SSI_SCK0_A), GPIO_FN(TIOC1A_B), GPIO_FN(LCD_DATA9_B),
+ GPIO_FN(VI1_7_A), GPIO_FN(FCE_B), GPIO_FN(LCD_DATA8_B),
+ GPIO_FN(VI1_6_A), GPIO_FN(FD7_B), GPIO_FN(LCD_DATA7_B),
+ GPIO_FN(VI1_5_A), GPIO_FN(FD6_B), GPIO_FN(LCD_DATA6_B),
+ GPIO_FN(VI1_4_A), GPIO_FN(FD5_B), GPIO_FN(LCD_DATA5_B),
+ GPIO_FN(VI1_3_A), GPIO_FN(FD4_B), GPIO_FN(LCD_DATA4_B),
+ GPIO_FN(VI1_2_A), GPIO_FN(FD3_B), GPIO_FN(LCD_DATA3_B),
+ GPIO_FN(VI1_1_A), GPIO_FN(FD2_B), GPIO_FN(LCD_DATA2_B),
+ GPIO_FN(VI1_0_A), GPIO_FN(FD1_B), GPIO_FN(LCD_DATA1_B),
+ GPIO_FN(VI1_CLK_A), GPIO_FN(FD0_B), GPIO_FN(LCD_DATA0_B),
+
+ /* IPSR10 */
+ GPIO_FN(CAN1_TX_A), GPIO_FN(TX5_C), GPIO_FN(MLB_DAT),
+ GPIO_FN(CAN0_RX_A), GPIO_FN(IRQ0_B), GPIO_FN(MLB_SIG),
+ GPIO_FN(CAN1_RX_A), GPIO_FN(IRQ1_B),
+ GPIO_FN(CAN0_TX_A), GPIO_FN(TX4_D), GPIO_FN(MLB_CLK),
+ GPIO_FN(CAN_CLK_A), GPIO_FN(RX4_D),
+ GPIO_FN(AUDIO_CLKOUT), GPIO_FN(TX1_E), GPIO_FN(HRTS0_C),
+ GPIO_FN(FSE_B), GPIO_FN(LCD_M_DISP_B),
+ GPIO_FN(AUDIO_CLKC), GPIO_FN(SCK1_E), GPIO_FN(HCTS0_C),
+ GPIO_FN(FRB_B), GPIO_FN(LCD_VEPWC_B),
+ GPIO_FN(AUDIO_CLKB_A), GPIO_FN(LCD_CLK_B),
+ GPIO_FN(AUDIO_CLKA_A), GPIO_FN(VI1_CLK_B), GPIO_FN(SCK1_D),
+ GPIO_FN(IECLK_B), GPIO_FN(LCD_FLM_B),
+ GPIO_FN(SSI_SDATA3), GPIO_FN(VI1_7_B), GPIO_FN(HTX0_C),
+ GPIO_FN(FWE_B), GPIO_FN(LCD_CL2_B),
+ GPIO_FN(SSI_SDATA2), GPIO_FN(VI1_6_B), GPIO_FN(HRX0_C),
+ GPIO_FN(FRE_B), GPIO_FN(LCD_CL1_B),
+ GPIO_FN(SSI_WS23), GPIO_FN(VI1_5_B), GPIO_FN(TX1_D),
+ GPIO_FN(HSCK0_C), GPIO_FN(FALE_B), GPIO_FN(LCD_DON_B),
+ GPIO_FN(SSI_SCK23), GPIO_FN(VI1_4_B), GPIO_FN(RX1_D),
+ GPIO_FN(FCLE_B), GPIO_FN(LCD_DATA15_B),
+
+ /* IPSR11 */
+ GPIO_FN(PRESETOUT), GPIO_FN(ST_CLKOUT),
+ GPIO_FN(DACK1), GPIO_FN(HSPI_CS_B), GPIO_FN(TX4_B),
+ GPIO_FN(ET0_RX_CLK_A),
+ GPIO_FN(DREQ1), GPIO_FN(HSPI_CLK_B), GPIO_FN(RX4_B),
+ GPIO_FN(ET0_PHY_INT_C), GPIO_FN(ET0_TX_CLK_A),
+ GPIO_FN(DACK0), GPIO_FN(SD1_DAT3_A), GPIO_FN(ET0_TX_ER),
+ GPIO_FN(DREQ0), GPIO_FN(SD1_CLK_A), GPIO_FN(ET0_TX_EN),
+ GPIO_FN(USB_OVC1), GPIO_FN(RX3_D), GPIO_FN(CAN1_RX_B),
+ GPIO_FN(RX5_D), GPIO_FN(IERX_B),
+ GPIO_FN(PENC1), GPIO_FN(TX3_D), GPIO_FN(CAN1_TX_B),
+ GPIO_FN(TX5_D), GPIO_FN(IETX_B),
+ GPIO_FN(TX0_A), GPIO_FN(HSPI_TX_A),
+ GPIO_FN(RX0_A), GPIO_FN(HSPI_RX_A), GPIO_FN(RMII0_RXD0_A),
+ GPIO_FN(ET0_ERXD6),
+ GPIO_FN(SCK0_A), GPIO_FN(HSPI_CS_A), GPIO_FN(VI0_CLKENB),
+ GPIO_FN(RMII0_TXD1_A), GPIO_FN(ET0_ERXD5),
+ GPIO_FN(SCIF_CLK_A), GPIO_FN(HSPI_CLK_A), GPIO_FN(VI0_CLK),
+ GPIO_FN(RMII0_TXD0_A), GPIO_FN(ET0_ERXD4),
+ GPIO_FN(SDSELF), GPIO_FN(RTS1_E),
+ GPIO_FN(SDA0), GPIO_FN(HIFEBL_A),
+ GPIO_FN(SDA1), GPIO_FN(RX1_E),
+ GPIO_FN(SCL1), GPIO_FN(SCIF_CLK_C),
+};
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+ { PINMUX_CFG_REG("GPSR0", 0xFFFC0004, 32, 1) {
+ GP_0_31_FN, FN_IP2_2_0,
+ GP_0_30_FN, FN_IP1_31_29,
+ GP_0_29_FN, FN_IP1_28_26,
+ GP_0_28_FN, FN_IP1_25_23,
+ GP_0_27_FN, FN_IP1_22_20,
+ GP_0_26_FN, FN_IP1_19_18,
+ GP_0_25_FN, FN_IP1_17_16,
+ GP_0_24_FN, FN_IP0_5_4,
+ GP_0_23_FN, FN_IP0_3_2,
+ GP_0_22_FN, FN_IP0_1_0,
+ GP_0_21_FN, FN_IP11_28,
+ GP_0_20_FN, FN_IP1_7_6,
+ GP_0_19_FN, FN_IP1_5_4,
+ GP_0_18_FN, FN_IP1_3_2,
+ GP_0_17_FN, FN_IP1_1_0,
+ GP_0_16_FN, FN_IP0_31_30,
+ GP_0_15_FN, FN_IP0_29_28,
+ GP_0_14_FN, FN_IP0_27_26,
+ GP_0_13_FN, FN_IP0_25_24,
+ GP_0_12_FN, FN_IP0_23_22,
+ GP_0_11_FN, FN_IP0_21_20,
+ GP_0_10_FN, FN_IP0_19_18,
+ GP_0_9_FN, FN_IP0_17_16,
+ GP_0_8_FN, FN_IP0_15_14,
+ GP_0_7_FN, FN_IP0_13_12,
+ GP_0_6_FN, FN_IP0_11_10,
+ GP_0_5_FN, FN_IP0_9_8,
+ GP_0_4_FN, FN_IP0_7_6,
+ GP_0_3_FN, FN_IP1_15_14,
+ GP_0_2_FN, FN_IP1_13_12,
+ GP_0_1_FN, FN_IP1_11_10,
+ GP_0_0_FN, FN_IP1_9_8 }
+ },
+ { PINMUX_CFG_REG("GPSR1", 0xFFFC0008, 32, 1) {
+ GP_1_31_FN, FN_IP11_25_23,
+ GP_1_30_FN, FN_IP2_13_11,
+ GP_1_29_FN, FN_IP2_10_8,
+ GP_1_28_FN, FN_IP2_7_5,
+ GP_1_27_FN, FN_IP3_26_24,
+ GP_1_26_FN, FN_IP3_23_21,
+ GP_1_25_FN, FN_IP2_4_3,
+ GP_1_24_FN, FN_WE1,
+ GP_1_23_FN, FN_WE0,
+ GP_1_22_FN, FN_IP3_19_18,
+ GP_1_21_FN, FN_RD,
+ GP_1_20_FN, FN_IP3_17_15,
+ GP_1_19_FN, FN_IP3_14_12,
+ GP_1_18_FN, FN_IP3_11_9,
+ GP_1_17_FN, FN_IP3_8_6,
+ GP_1_16_FN, FN_IP3_5_3,
+ GP_1_15_FN, FN_EX_CS0,
+ GP_1_14_FN, FN_IP3_2,
+ GP_1_13_FN, FN_CS0,
+ GP_1_12_FN, FN_BS,
+ GP_1_11_FN, FN_CLKOUT,
+ GP_1_10_FN, FN_IP3_1_0,
+ GP_1_9_FN, FN_IP2_30_28,
+ GP_1_8_FN, FN_IP2_27_25,
+ GP_1_7_FN, FN_IP2_24_23,
+ GP_1_6_FN, FN_IP2_22_20,
+ GP_1_5_FN, FN_IP2_19_17,
+ GP_1_4_FN, FN_IP2_16_14,
+ GP_1_3_FN, FN_IP11_22_21,
+ GP_1_2_FN, FN_IP11_20_19,
+ GP_1_1_FN, FN_IP3_29_27,
+ GP_1_0_FN, FN_IP3_20 }
+ },
+ { PINMUX_CFG_REG("GPSR2", 0xFFFC000C, 32, 1) {
+ GP_2_31_FN, FN_IP4_31_30,
+ GP_2_30_FN, FN_IP5_2_0,
+ GP_2_29_FN, FN_IP5_5_3,
+ GP_2_28_FN, FN_IP5_8_6,
+ GP_2_27_FN, FN_IP5_11_9,
+ GP_2_26_FN, FN_IP5_14_12,
+ GP_2_25_FN, FN_IP5_17_15,
+ GP_2_24_FN, FN_IP5_20_18,
+ GP_2_23_FN, FN_IP5_22_21,
+ GP_2_22_FN, FN_IP5_24_23,
+ GP_2_21_FN, FN_IP5_26_25,
+ GP_2_20_FN, FN_IP4_29_28,
+ GP_2_19_FN, FN_IP4_27_26,
+ GP_2_18_FN, FN_IP4_25_24,
+ GP_2_17_FN, FN_IP4_23_22,
+ GP_2_16_FN, FN_IP4_21_20,
+ GP_2_15_FN, FN_IP4_19_18,
+ GP_2_14_FN, FN_IP4_17_15,
+ GP_2_13_FN, FN_IP4_14_12,
+ GP_2_12_FN, FN_IP4_11_9,
+ GP_2_11_FN, FN_IP4_8_6,
+ GP_2_10_FN, FN_IP4_5_3,
+ GP_2_9_FN, FN_IP8_27_26,
+ GP_2_8_FN, FN_IP11_12,
+ GP_2_7_FN, FN_IP8_25_23,
+ GP_2_6_FN, FN_IP8_22_20,
+ GP_2_5_FN, FN_IP11_27_26,
+ GP_2_4_FN, FN_IP8_29_28,
+ GP_2_3_FN, FN_IP4_2_0,
+ GP_2_2_FN, FN_IP11_11_10,
+ GP_2_1_FN, FN_IP11_9_7,
+ GP_2_0_FN, FN_IP11_6_4 }
+ },
+ { PINMUX_CFG_REG("GPSR3", 0xFFFC0010, 32, 1) {
+ GP_3_31_FN, FN_IP9_1_0,
+ GP_3_30_FN, FN_IP8_19_18,
+ GP_3_29_FN, FN_IP8_17_16,
+ GP_3_28_FN, FN_IP8_15_14,
+ GP_3_27_FN, FN_IP8_13_12,
+ GP_3_26_FN, FN_IP8_11_10,
+ GP_3_25_FN, FN_IP8_9_8,
+ GP_3_24_FN, FN_IP8_7_6,
+ GP_3_23_FN, FN_IP8_5_4,
+ GP_3_22_FN, FN_IP8_3_2,
+ GP_3_21_FN, FN_IP8_1_0,
+ GP_3_20_FN, FN_IP7_30_29,
+ GP_3_19_FN, FN_IP7_28_27,
+ GP_3_18_FN, FN_IP7_26_24,
+ GP_3_17_FN, FN_IP7_23_21,
+ GP_3_16_FN, FN_IP7_20_18,
+ GP_3_15_FN, FN_IP7_17_15,
+ GP_3_14_FN, FN_IP7_14_12,
+ GP_3_13_FN, FN_IP7_11_9,
+ GP_3_12_FN, FN_IP7_8_6,
+ GP_3_11_FN, FN_IP7_5_3,
+ GP_3_10_FN, FN_IP7_2_0,
+ GP_3_9_FN, FN_IP6_23_21,
+ GP_3_8_FN, FN_IP6_20_18,
+ GP_3_7_FN, FN_IP6_17_16,
+ GP_3_6_FN, FN_IP6_15_14,
+ GP_3_5_FN, FN_IP6_13_12,
+ GP_3_4_FN, FN_IP6_11_10,
+ GP_3_3_FN, FN_IP6_9_8,
+ GP_3_2_FN, FN_IP6_7_6,
+ GP_3_1_FN, FN_IP6_5_3,
+ GP_3_0_FN, FN_IP6_2_0 }
+ },
+
+ { PINMUX_CFG_REG("GPSR4", 0xFFFC0014, 32, 1) {
+ GP_4_31_FN, FN_IP10_24_23,
+ GP_4_30_FN, FN_IP10_22,
+ GP_4_29_FN, FN_IP11_18_16,
+ GP_4_28_FN, FN_USB_OVC0,
+ GP_4_27_FN, FN_IP11_15_13,
+ GP_4_26_FN, FN_PENC0,
+ GP_4_25_FN, FN_IP11_2,
+ GP_4_24_FN, FN_SCL0,
+ GP_4_23_FN, FN_IP11_1,
+ GP_4_22_FN, FN_IP11_0,
+ GP_4_21_FN, FN_IP10_21_19,
+ GP_4_20_FN, FN_IP10_18_16,
+ GP_4_19_FN, FN_IP10_15,
+ GP_4_18_FN, FN_IP10_14_12,
+ GP_4_17_FN, FN_IP10_11_9,
+ GP_4_16_FN, FN_IP10_8_6,
+ GP_4_15_FN, FN_IP10_5_3,
+ GP_4_14_FN, FN_IP10_2_0,
+ GP_4_13_FN, FN_IP9_29_28,
+ GP_4_12_FN, FN_IP9_27_26,
+ GP_4_11_FN, FN_IP9_9_8,
+ GP_4_10_FN, FN_IP9_7_6,
+ GP_4_9_FN, FN_IP9_5_4,
+ GP_4_8_FN, FN_IP9_3_2,
+ GP_4_7_FN, FN_IP9_17_16,
+ GP_4_6_FN, FN_IP9_15_14,
+ GP_4_5_FN, FN_IP9_13_12,
+ GP_4_4_FN, FN_IP9_11_10,
+ GP_4_3_FN, FN_IP9_25_24,
+ GP_4_2_FN, FN_IP9_23_22,
+ GP_4_1_FN, FN_IP9_21_20,
+ GP_4_0_FN, FN_IP9_19_18 }
+ },
+ { PINMUX_CFG_REG("GPSR5", 0xFFFC0018, 32, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 31 - 28 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 27 - 24 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 23 - 20 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 19 - 16 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 15 - 12 */
+ GP_5_11_FN, FN_IP10_29_28,
+ GP_5_10_FN, FN_IP10_27_26,
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 9 - 6 */
+ 0, 0, 0, 0, /* 5, 4 */
+ GP_5_3_FN, FN_IRQ3_B,
+ GP_5_2_FN, FN_IRQ2_B,
+ GP_5_1_FN, FN_IP11_3,
+ GP_5_0_FN, FN_IP10_25 }
+ },
+
+ { PINMUX_CFG_REG_VAR("IPSR0", 0xFFFC001C, 32,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2) {
+ /* IP0_31_30 [2] */
+ FN_A15, FN_ST0_VCO_CLKIN, FN_LCD_DATA15_A,
+ FN_TIOC3D_C,
+ /* IP0_29_28 [2] */
+ FN_A14, FN_LCD_DATA14_A, FN_TIOC3C_C, 0,
+ /* IP0_27_26 [2] */
+ FN_A13, FN_LCD_DATA13_A, FN_TIOC3B_C, 0,
+ /* IP0_25_24 [2] */
+ FN_A12, FN_LCD_DATA12_A, FN_TIOC3A_C, 0,
+ /* IP0_23_22 [2] */
+ FN_A11, FN_ST0_D7, FN_LCD_DATA11_A, FN_TIOC2B_C,
+ /* IP0_21_20 [2] */
+ FN_A10, FN_ST0_D6, FN_LCD_DATA10_A, FN_TIOC2A_C,
+ /* IP0_19_18 [2] */
+ FN_A9, FN_ST0_D5, FN_LCD_DATA9_A, FN_TIOC1B_C,
+ /* IP0_17_16 [2] */
+ FN_A8, FN_ST0_D4, FN_LCD_DATA8_A, FN_TIOC1A_C,
+ /* IP0_15_14 [2] */
+ FN_A7, FN_ST0_D3, FN_LCD_DATA7_A, FN_TIOC0D_C,
+ /* IP0_13_12 [2] */
+ FN_A6, FN_ST0_D2, FN_LCD_DATA6_A, FN_TIOC0C_C,
+ /* IP0_11_10 [2] */
+ FN_A5, FN_ST0_D1, FN_LCD_DATA5_A, FN_TIOC0B_C,
+ /* IP0_9_8 [2] */
+ FN_A4, FN_ST0_D0, FN_LCD_DATA4_A, FN_TIOC0A_C,
+ /* IP0_7_6 [2] */
+ FN_A3, FN_ST0_VLD, FN_LCD_DATA3_A, FN_TCLKD_C,
+ /* IP0_5_4 [2] */
+ FN_A2, FN_ST0_SYC, FN_LCD_DATA2_A, FN_TCLKC_C,
+ /* IP0_3_2 [2] */
+ FN_A1, FN_ST0_REQ, FN_LCD_DATA1_A, FN_TCLKB_C,
+ /* IP0_1_0 [2] */
+ FN_A0, FN_ST0_CLKIN, FN_LCD_DATA0_A, FN_TCLKA_C }
+ },
+ { PINMUX_CFG_REG_VAR("IPSR1", 0xFFFC0020, 32,
+ 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2) {
+ /* IP1_31_29 [3] */
+ FN_D3, FN_SD0_DAT3_A, FN_MMC_D3_A, FN_ST1_D6,
+ FN_FD3_A, 0, 0, 0,
+ /* IP1_28_26 [3] */
+ FN_D2, FN_SD0_DAT2_A, FN_MMC_D2_A, FN_ST1_D5,
+ FN_FD2_A, 0, 0, 0,
+ /* IP1_25_23 [3] */
+ FN_D1, FN_SD0_DAT1_A, FN_MMC_D1_A, FN_ST1_D4,
+ FN_FD1_A, 0, 0, 0,
+ /* IP1_22_20 [3] */
+ FN_D0, FN_SD0_DAT0_A, FN_MMC_D0_A, FN_ST1_D3,
+ FN_FD0_A, 0, 0, 0,
+ /* IP1_19_18 [2] */
+ FN_A25, FN_TX2_D, FN_ST1_D2, 0,
+ /* IP1_17_16 [2] */
+ FN_A24, FN_RX2_D, FN_ST1_D1, 0,
+ /* IP1_15_14 [2] */
+ FN_A23, FN_ST1_D0, FN_LCD_M_DISP_A, 0,
+ /* IP1_13_12 [2] */
+ FN_A22, FN_ST1_VLD, FN_LCD_VEPWC_A, 0,
+ /* IP1_11_10 [2] */
+ FN_A21, FN_ST1_SYC, FN_LCD_VCPWC_A, 0,
+ /* IP1_9_8 [2] */
+ FN_A20, FN_ST1_REQ, FN_LCD_FLM_A, 0,
+ /* IP1_7_6 [2] */
+ FN_A19, FN_ST1_CLKIN, FN_LCD_CLK_A, FN_TIOC4D_C,
+ /* IP1_5_4 [2] */
+ FN_A18, FN_ST1_PWM, FN_LCD_CL2_A, FN_TIOC4C_C,
+ /* IP1_3_2 [2] */
+ FN_A17, FN_ST1_VCO_CLKIN, FN_LCD_CL1_A, FN_TIOC4B_C,
+ /* IP1_1_0 [2] */
+ FN_A16, FN_ST0_PWM, FN_LCD_DON_A, FN_TIOC4A_C }
+ },
+ { PINMUX_CFG_REG_VAR("IPSR2", 0xFFFC0024, 32,
+ 1, 3, 3, 2, 3, 3, 3, 3, 3, 3, 2, 3) {
+ /* IP2_31 [1] */
+ 0, 0,
+ /* IP2_30_28 [3] */
+ FN_D14, FN_TX2_B, 0, FN_FSE_A,
+ FN_ET0_TX_CLK_B, 0, 0, 0,
+ /* IP2_27_25 [3] */
+ FN_D13, FN_RX2_B, 0, FN_FRB_A,
+ FN_ET0_ETXD6_B, 0, 0, 0,
+ /* IP2_24_23 [2] */
+ FN_D12, 0, FN_FWE_A, FN_ET0_ETXD5_B,
+ /* IP2_22_20 [3] */
+ FN_D11, FN_RSPI_MISO_A, 0, FN_QMI_QIO1_A,
+ FN_FRE_A, FN_ET0_ETXD3_B, 0, 0,
+ /* IP2_19_17 [3] */
+ FN_D10, FN_RSPI_MOSI_A, 0, FN_QMO_QIO0_A,
+ FN_FALE_A, FN_ET0_ETXD2_B, 0, 0,
+ /* IP2_16_14 [3] */
+ FN_D9, FN_SD0_CMD_A, FN_MMC_CMD_A, FN_QIO3_A,
+ FN_FCLE_A, FN_ET0_ETXD1_B, 0, 0,
+ /* IP2_13_11 [3] */
+ FN_D8, FN_SD0_CLK_A, FN_MMC_CLK_A, FN_QIO2_A,
+ FN_FCE_A, FN_ET0_GTX_CLK_B, 0, 0,
+ /* IP2_10_8 [3] */
+ FN_D7, FN_RSPI_SSL_A, FN_MMC_D7_A, FN_QSSL_A,
+ FN_FD7_A, 0, 0, 0,
+ /* IP2_7_5 [3] */
+ FN_D6, FN_RSPI_RSPCK_A, FN_MMC_D6_A, FN_QSPCLK_A,
+ FN_FD6_A, 0, 0, 0,
+ /* IP2_4_3 [2] */
+ FN_D5, FN_SD0_WP_A, FN_MMC_D5_A, FN_FD5_A,
+ /* IP2_2_0 [3] */
+ FN_D4, FN_SD0_CD_A, FN_MMC_D4_A, FN_ST1_D7,
+ FN_FD4_A, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG_VAR("IPSR3", 0xFFFC0028, 32,
+ 2, 3, 3, 3, 1, 2, 3, 3, 3, 3, 3, 1, 2) {
+ /* IP3_31_30 [2] */
+ 0, 0, 0, 0,
+ /* IP3_29_27 [3] */
+ FN_DRACK0, FN_SD1_DAT2_A, FN_ATAG, FN_TCLK1_A,
+ FN_ET0_ETXD7, 0, 0, 0,
+ /* IP3_26_24 [3] */
+ FN_EX_WAIT2, FN_SD1_DAT1_A, FN_DACK2, FN_CAN1_RX_C,
+ FN_ET0_MAGIC_C, FN_ET0_ETXD6_A, 0, 0,
+ /* IP3_23_21 [3] */
+ FN_EX_WAIT1, FN_SD1_DAT0_A, FN_DREQ2, FN_CAN1_TX_C,
+ FN_ET0_LINK_C, FN_ET0_ETXD5_A, 0, 0,
+ /* IP3_20 [1] */
+ FN_EX_WAIT0, FN_TCLK1_B,
+ /* IP3_19_18 [2] */
+ FN_RD_WR, FN_TCLK1_B, 0, 0,
+ /* IP3_17_15 [3] */
+ FN_EX_CS5, FN_SD1_CMD_A, FN_ATADIR, FN_QSSL_B,
+ FN_ET0_ETXD3_A, 0, 0, 0,
+ /* IP3_14_12 [3] */
+ FN_EX_CS4, FN_SD1_WP_A, FN_ATAWR, FN_QMI_QIO1_B,
+ FN_ET0_ETXD2_A, 0, 0, 0,
+ /* IP3_11_9 [3] */
+ FN_EX_CS3, FN_SD1_CD_A, FN_ATARD, FN_QMO_QIO0_B,
+ FN_ET0_ETXD1_A, 0, 0, 0,
+ /* IP3_8_6 [3] */
+ FN_EX_CS2, FN_TX3_B, FN_ATACS1, FN_QSPCLK_B,
+ FN_ET0_GTX_CLK_A, 0, 0, 0,
+ /* IP3_5_3 [3] */
+ FN_EX_CS1, FN_RX3_B, FN_ATACS0, FN_QIO2_B,
+ FN_ET0_ETXD0, 0, 0, 0,
+ /* IP3_2 [1] */
+ FN_CS1_A26, FN_QIO3_B,
+ /* IP3_1_0 [2] */
+ FN_D15, FN_SCK2_B, 0, 0 }
+ },
+ { PINMUX_CFG_REG_VAR("IPSR4", 0xFFFC002C, 32,
+ 2, 2, 2, 2, 2, 2 , 2, 3, 3, 3, 3, 3, 3) {
+ /* IP4_31_30 [2] */
+ 0, FN_SCK2_A, FN_VI0_G3, 0,
+ /* IP4_29_28 [2] */
+ 0, FN_RTS1_B, FN_VI0_G2, 0,
+ /* IP4_27_26 [2] */
+ 0, FN_CTS1_B, FN_VI0_DATA7_VI0_G1, 0,
+ /* IP4_25_24 [2] */
+ 0, FN_TX1_B, FN_VI0_DATA6_VI0_G0, FN_ET0_PHY_INT_A,
+ /* IP4_23_22 [2] */
+ 0, FN_RX1_B, FN_VI0_DATA5_VI0_B5, FN_ET0_MAGIC_A,
+ /* IP4_21_20 [2] */
+ 0, FN_SCK1_B, FN_VI0_DATA4_VI0_B4, FN_ET0_LINK_A,
+ /* IP4_19_18 [2] */
+ 0, FN_RTS0_B, FN_VI0_DATA3_VI0_B3, FN_ET0_MDIO_A,
+ /* IP4_17_15 [3] */
+ 0, FN_CTS0_B, FN_VI0_DATA2_VI0_B2, FN_RMII0_MDIO_A,
+ FN_ET0_MDC, 0, 0, 0,
+ /* IP4_14_12 [3] */
+ FN_HTX0_A, FN_TX1_A, FN_VI0_DATA1_VI0_B1, FN_RMII0_MDC_A,
+ FN_ET0_COL, 0, 0, 0,
+ /* IP4_11_9 [3] */
+ FN_HRX0_A, FN_RX1_A, FN_VI0_DATA0_VI0_B0, FN_RMII0_CRS_DV_A,
+ FN_ET0_CRS, 0, 0, 0,
+ /* IP4_8_6 [3] */
+ FN_HSCK0_A, FN_SCK1_A, FN_VI0_VSYNC, FN_RMII0_RX_ER_A,
+ FN_ET0_RX_ER, 0, 0, 0,
+ /* IP4_5_3 [3] */
+ FN_HRTS0_A, FN_RTS1_A, FN_VI0_HSYNC, FN_RMII0_TXD_EN_A,
+ FN_ET0_RX_DV, 0, 0, 0,
+ /* IP4_2_0 [3] */
+ FN_HCTS0_A, FN_CTS1_A, FN_VI0_FIELD, FN_RMII0_RXD1_A,
+ FN_ET0_ERXD7, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG_VAR("IPSR5", 0xFFFC0030, 32,
+ 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3) {
+ /* IP5_31 [1] */
+ 0, 0,
+ /* IP5_30 [1] */
+ 0, 0,
+ /* IP5_29 [1] */
+ 0, 0,
+ /* IP5_28 [1] */
+ 0, 0,
+ /* IP5_27 [1] */
+ 0, 0,
+ /* IP5_26_25 [2] */
+ FN_REF50CK, FN_CTS1_E, FN_HCTS0_D, 0,
+ /* IP5_24_23 [2] */
+ FN_REF125CK, FN_ADTRG, FN_RX5_C, 0,
+ /* IP5_22_21 [2] */
+ FN_SD2_WP_A, FN_TX5_A, FN_VI0_R5, 0,
+ /* IP5_20_18 [3] */
+ FN_SD2_CD_A, FN_RX5_A, FN_VI0_R4, 0,
+ 0, 0, 0, FN_ET0_PHY_INT_B,
+ /* IP5_17_15 [3] */
+ FN_SD2_DAT3_A, FN_TX4_A, FN_VI0_R3, 0,
+ 0, 0, 0, FN_ET0_MAGIC_B,
+ /* IP5_14_12 [3] */
+ FN_SD2_DAT2_A, FN_RX4_A, FN_VI0_R2, 0,
+ 0, 0, 0, FN_ET0_LINK_B,
+ /* IP5_11_9 [3] */
+ FN_SD2_DAT1_A, FN_TX3_A, FN_VI0_R1, 0,
+ 0, 0, 0, FN_ET0_MDIO_B,
+ /* IP5_8_6 [3] */
+ FN_SD2_DAT0_A, FN_RX3_A, FN_VI0_R0, 0,
+ 0, 0, 0, FN_ET0_ERXD3_B,
+ /* IP5_5_3 [3] */
+ FN_SD2_CMD_A, FN_TX2_A, FN_VI0_G5, 0,
+ 0, 0, 0, FN_ET0_ERXD2_B,
+ /* IP5_2_0 [3] */
+ FN_SD2_CLK_A, FN_RX2_A, FN_VI0_G4, 0,
+ FN_ET0_RX_CLK_B, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG_VAR("IPSR6", 0xFFFC0034, 32,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 3, 3, 2, 2, 2, 2, 2, 2, 3, 3) {
+ /* IP5_31 [1] */
+ 0, 0,
+ /* IP6_30 [1] */
+ 0, 0,
+ /* IP6_29 [1] */
+ 0, 0,
+ /* IP6_28 [1] */
+ 0, 0,
+ /* IP6_27 [1] */
+ 0, 0,
+ /* IP6_26 [1] */
+ 0, 0,
+ /* IP6_25 [1] */
+ 0, 0,
+ /* IP6_24 [1] */
+ 0, 0,
+ /* IP6_23_21 [3] */
+ FN_DU0_DG1, FN_CTS1_C, FN_HRTS0_D, FN_TIOC1B_A,
+ FN_HIFD09, 0, 0, 0,
+ /* IP6_20_18 [3] */
+ FN_DU0_DG0, FN_TX1_C, FN_HSCK0_D, FN_IECLK_A,
+ FN_TIOC1A_A, FN_HIFD08, 0, 0,
+ /* IP6_17_16 [2] */
+ FN_DU0_DR7, FN_RX1_C, FN_TIOC0D_A, FN_HIFD07,
+ /* IP6_15_14 [2] */
+ FN_DU0_DR6, FN_SCK1_C, FN_TIOC0C_A, FN_HIFD06,
+ /* IP6_13_12 [2] */
+ FN_DU0_DR5, FN_RTS0_C, FN_TIOC0B_A, FN_HIFD05,
+ /* IP6_11_10 [2] */
+ FN_DU0_DR4, FN_CTS0_C, FN_TIOC0A_A, FN_HIFD04,
+ /* IP6_9_8 [2] */
+ FN_DU0_DR3, FN_TX0_B, FN_TCLKD_A, FN_HIFD03,
+ /* IP6_7_6 [2] */
+ FN_DU0_DR2, FN_RX0_B, FN_TCLKC_A, FN_HIFD02,
+ /* IP6_5_3 [3] */
+ FN_DU0_DR1, FN_SCK0_B, FN_HTX0_D, FN_IERX_A,
+ FN_TCLKB_A, FN_HIFD01, 0, 0,
+ /* IP6_2_0 [3] */
+ FN_DU0_DR0, FN_SCIF_CLK_B, FN_HRX0_D, FN_IETX_A,
+ FN_TCLKA_A, FN_HIFD00, 0, 0 }
+ },
+ { PINMUX_CFG_REG_VAR("IPSR7", 0xFFFC0038, 32,
+ 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3) {
+ /* IP7_31 [1] */
+ 0, 0,
+ /* IP7_30_29 [2] */
+ FN_DU0_DB4, 0, FN_HIFINT, 0,
+ /* IP7_28_27 [2] */
+ FN_DU0_DB3, FN_TX5_B, FN_TIOC4D_A, FN_HIFRD,
+ /* IP7_26_24 [3] */
+ FN_DU0_DB2, FN_RX5_B, FN_RMII0_TXD1_B, FN_TIOC4C_A,
+ FN_HIFWR, 0, 0, 0,
+ /* IP7_23_21 [3] */
+ FN_DU0_DB1, FN_TX4_C, FN_RMII0_TXD0_B, FN_TIOC4B_A,
+ FN_HIFRS, 0, 0, 0,
+ /* IP7_20_18 [3] */
+ FN_DU0_DB0, FN_RX4_C, FN_RMII0_TXD_EN_B, FN_TIOC4A_A,
+ FN_HIFCS, 0, 0, 0,
+ /* IP7_17_15 [3] */
+ FN_DU0_DG7, FN_TX3_C, FN_RMII0_RXD1_B, FN_TIOC3D_A,
+ FN_HIFD15, 0, 0, 0,
+ /* IP7_14_12 [3] */
+ FN_DU0_DG6, FN_RX3_C, FN_RMII0_RXD0_B, FN_TIOC3C_A,
+ FN_HIFD14, 0, 0, 0,
+ /* IP7_11_9 [3] */
+ FN_DU0_DG5, FN_TX2_C, FN_RMII0_RX_ER_B, FN_TIOC3B_A,
+ FN_HIFD13, 0, 0, 0,
+ /* IP7_8_6 [3] */
+ FN_DU0_DG4, FN_RX2_C, FN_RMII0_CRS_DV_B, FN_TIOC3A_A,
+ FN_HIFD12, 0, 0, 0,
+ /* IP7_5_3 [3] */
+ FN_DU0_DG3, FN_SCK2_C, FN_RMII0_MDIO_B, FN_TIOC2B_A,
+ FN_HIFD11, 0, 0, 0,
+ /* IP7_2_0 [3] */
+ FN_DU0_DG2, FN_RTS1_C, FN_RMII0_MDC_B, FN_TIOC2A_A,
+ FN_HIFD10, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG_VAR("IPSR8", 0xFFFC003C, 32,
+ 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2) {
+ /* IP9_31_30 [2] */
+ 0, 0, 0, 0,
+ /* IP8_29_28 [2] */
+ FN_IRQ3_A, FN_RTS0_A, FN_HRTS0_B, FN_ET0_ERXD3_A,
+ /* IP8_27_26 [2] */
+ FN_IRQ2_A, FN_CTS0_A, FN_HCTS0_B, FN_ET0_ERXD2_A,
+ /* IP8_25_23 [3] */
+ FN_IRQ1_A, 0, FN_HSPI_RX_B, FN_TX3_E,
+ FN_ET0_ERXD1, 0, 0, 0,
+ /* IP8_22_20 [3] */
+ FN_IRQ0_A, 0, FN_HSPI_TX_B, FN_RX3_E,
+ FN_ET0_ERXD0, 0, 0, 0,
+ /* IP8_19_18 [2] */
+ FN_DU0_CDE, FN_HTX0_B, FN_AUDIO_CLKB_B, FN_LCD_VCPWC_B,
+ /* IP8_17_16 [2] */
+ FN_DU0_DISP, FN_CAN0_TX_B, FN_HRX0_B, FN_AUDIO_CLKA_B,
+ /* IP8_15_14 [2] */
+ FN_DU0_EXODDF_DU0_ODDF, FN_CAN0_RX_B, FN_HSCK0_B,
+ FN_SSI_SDATA1_B,
+ /* IP8_13_12 [2] */
+ FN_DU0_EXVSYNC_DU0_VSYNC, 0, FN_HSPI_RX0_C, FN_SSI_WS1_B,
+ /* IP8_11_10 [2] */
+ FN_DU0_EXHSYNC_DU0_HSYNC, 0, FN_HSPI_TX0_C, FN_SSI_SCK1_B,
+ /* IP8_9_8 [2] */
+ FN_DU0_DOTCLKOUT, 0, FN_HSPI_CLK0_C, FN_SSI_SDATA0_B,
+ /* IP8_7_6 [2] */
+ FN_DU0_DOTCLKIN, 0, FN_HSPI_CS0_C, FN_SSI_WS0_B,
+ /* IP8_5_4 [2] */
+ FN_DU0_DB7, 0, FN_SSI_SCK0_B, FN_HIFEBL_B,
+ /* IP8_3_2 [2] */
+ FN_DU0_DB6, 0, FN_HIFRDY, 0,
+ /* IP8_1_0 [2] */
+ FN_DU0_DB5, 0, FN_HIFDREQ, 0 }
+ },
+ { PINMUX_CFG_REG_VAR("IPSR9", 0xFFFC0040, 32,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2) {
+ /* IP9_31_30 [2] */
+ 0, 0, 0, 0,
+ /* IP9_29_28 [2] */
+ FN_SSI_SDATA1_A, FN_VI1_3_B, FN_LCD_DATA14_B, 0,
+ /* IP9_27_26 [2] */
+ FN_SSI_WS1_A, FN_VI1_2_B, FN_LCD_DATA13_B, 0,
+ /* IP9_25_24 [2] */
+ FN_SSI_SCK1_A, FN_VI1_1_B, FN_TIOC2B_B, FN_LCD_DATA12_B,
+ /* IP9_23_22 [2] */
+ FN_SSI_SDATA0_A, FN_VI1_0_B, FN_TIOC2A_B, FN_LCD_DATA11_B,
+ /* IP9_21_20 [2] */
+ FN_SSI_WS0_A, FN_TIOC1B_B, FN_LCD_DATA10_B, 0,
+ /* IP9_19_18 [2] */
+ FN_SSI_SCK0_A, FN_TIOC1A_B, FN_LCD_DATA9_B, 0,
+ /* IP9_17_16 [2] */
+ FN_VI1_7_A, FN_FCE_B, FN_LCD_DATA8_B, 0,
+ /* IP9_15_14 [2] */
+ FN_VI1_6_A, 0, FN_FD7_B, FN_LCD_DATA7_B,
+ /* IP9_13_12 [2] */
+ FN_VI1_5_A, 0, FN_FD6_B, FN_LCD_DATA6_B,
+ /* IP9_11_10 [2] */
+ FN_VI1_4_A, 0, FN_FD5_B, FN_LCD_DATA5_B,
+ /* IP9_9_8 [2] */
+ FN_VI1_3_A, 0, FN_FD4_B, FN_LCD_DATA4_B,
+ /* IP9_7_6 [2] */
+ FN_VI1_2_A, 0, FN_FD3_B, FN_LCD_DATA3_B,
+ /* IP9_5_4 [2] */
+ FN_VI1_1_A, 0, FN_FD2_B, FN_LCD_DATA2_B,
+ /* IP9_3_2 [2] */
+ FN_VI1_0_A, 0, FN_FD1_B, FN_LCD_DATA1_B,
+ /* IP9_1_0 [2] */
+ FN_VI1_CLK_A, 0, FN_FD0_B, FN_LCD_DATA0_B }
+ },
+ { PINMUX_CFG_REG_VAR("IPSR10", 0xFFFC0044, 32,
+ 2, 2, 2, 1, 2, 1, 3,
+ 3, 1, 3, 3, 3, 3, 3) {
+ /* IP9_31_30 [2] */
+ 0, 0, 0, 0,
+ /* IP10_29_28 [2] */
+ FN_CAN1_TX_A, FN_TX5_C, FN_MLB_DAT, 0,
+ /* IP10_27_26 [2] */
+ FN_CAN0_RX_A, FN_IRQ0_B, FN_MLB_SIG, 0,
+ /* IP10_25 [1] */
+ FN_CAN1_RX_A, FN_IRQ1_B,
+ /* IP10_24_23 [2] */
+ FN_CAN0_TX_A, FN_TX4_D, FN_MLB_CLK, 0,
+ /* IP10_22 [1] */
+ FN_CAN_CLK_A, FN_RX4_D,
+ /* IP10_21_19 [3] */
+ FN_AUDIO_CLKOUT, FN_TX1_E, FN_HRTS0_C, FN_FSE_B,
+ FN_LCD_M_DISP_B, 0, 0, 0,
+ /* IP10_18_16 [3] */
+ FN_AUDIO_CLKC, FN_SCK1_E, FN_HCTS0_C, FN_FRB_B,
+ FN_LCD_VEPWC_B, 0, 0, 0,
+ /* IP10_15 [1] */
+ FN_AUDIO_CLKB_A, FN_LCD_CLK_B,
+ /* IP10_14_12 [3] */
+ FN_AUDIO_CLKA_A, FN_VI1_CLK_B, FN_SCK1_D, FN_IECLK_B,
+ FN_LCD_FLM_B, 0, 0, 0,
+ /* IP10_11_9 [3] */
+ FN_SSI_SDATA3, FN_VI1_7_B, FN_HTX0_C, FN_FWE_B,
+ FN_LCD_CL2_B, 0, 0, 0,
+ /* IP10_8_6 [3] */
+ FN_SSI_SDATA2, FN_VI1_6_B, FN_HRX0_C, FN_FRE_B,
+ FN_LCD_CL1_B, 0, 0, 0,
+ /* IP10_5_3 [3] */
+ FN_SSI_WS23, FN_VI1_5_B, FN_TX1_D, FN_HSCK0_C, FN_FALE_B,
+ FN_LCD_DON_B, 0, 0, 0,
+ /* IP10_2_0 [3] */
+ FN_SSI_SCK23, FN_VI1_4_B, FN_RX1_D, FN_FCLE_B,
+ FN_LCD_DATA15_B, 0, 0, 0 }
+ },
+ { PINMUX_CFG_REG_VAR("IPSR11", 0xFFFC0048, 32,
+ 3, 1, 2, 2, 2, 3, 3, 1, 2, 3, 3, 1, 1, 1, 1) {
+ /* IP11_31_29 [3] */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* IP11_28 [1] */
+ FN_PRESETOUT, FN_ST_CLKOUT,
+ /* IP11_27_26 [2] */
+ FN_DACK1, FN_HSPI_CS_B, FN_TX4_B, FN_ET0_RX_CLK_A,
+ /* IP11_25_23 [3] */
+ FN_DREQ1, FN_HSPI_CLK_B, FN_RX4_B, FN_ET0_PHY_INT_C,
+ FN_ET0_TX_CLK_A, 0, 0, 0,
+ /* IP11_22_21 [2] */
+ FN_DACK0, FN_SD1_DAT3_A, FN_ET0_TX_ER, 0,
+ /* IP11_20_19 [2] */
+ FN_DREQ0, FN_SD1_CLK_A, FN_ET0_TX_EN, 0,
+ /* IP11_18_16 [3] */
+ FN_USB_OVC1, FN_RX3_D, FN_CAN1_RX_B, FN_RX5_D,
+ FN_IERX_B, 0, 0, 0,
+ /* IP11_15_13 [3] */
+ FN_PENC1, FN_TX3_D, FN_CAN1_TX_B, FN_TX5_D,
+ FN_IETX_B, 0, 0, 0,
+ /* IP11_12 [1] */
+ FN_TX0_A, FN_HSPI_TX_A,
+ /* IP11_11_10 [2] */
+ FN_RX0_A, FN_HSPI_RX_A, FN_RMII0_RXD0_A, FN_ET0_ERXD6,
+ /* IP11_9_7 [3] */
+ FN_SCK0_A, FN_HSPI_CS_A, FN_VI0_CLKENB, FN_RMII0_TXD1_A,
+ FN_ET0_ERXD5, 0, 0, 0,
+ /* IP11_6_4 [3] */
+ FN_SCIF_CLK_A, FN_HSPI_CLK_A, FN_VI0_CLK, FN_RMII0_TXD0_A,
+ FN_ET0_ERXD4, 0, 0, 0,
+ /* IP11_3 [1] */
+ FN_SDSELF, FN_RTS1_E,
+ /* IP11_2 [1] */
+ FN_SDA0, FN_HIFEBL_A,
+ /* IP11_1 [1] */
+ FN_SDA1, FN_RX1_E,
+ /* IP11_0 [1] */
+ FN_SCL1, FN_SCIF_CLK_C }
+ },
+ { PINMUX_CFG_REG_VAR("MOD_SEL1", 0xFFFC004C, 32,
+ 3, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2,
+ 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) {
+ /* SEL1_31_29 [3] */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* SEL1_28 [1] */
+ FN_SEL_IEBUS_0, FN_SEL_IEBUS_1,
+ /* SEL1_27 [1] */
+ FN_SEL_RQSPI_0, FN_SEL_RQSPI_1,
+ /* SEL1_26 [1] */
+ FN_SEL_VIN1_0, FN_SEL_VIN1_1,
+ /* SEL1_25 [1] */
+ FN_SEL_HIF_0, FN_SEL_HIF_1,
+ /* SEL1_24 [1] */
+ FN_SEL_RSPI_0, FN_SEL_RSPI_1,
+ /* SEL1_23 [1] */
+ FN_SEL_LCDC_0, FN_SEL_LCDC_1,
+ /* SEL1_22_21 [2] */
+ FN_SEL_ET0_CTL_0, FN_SEL_ET0_CTL_1, FN_SEL_ET0_CTL_2, 0,
+ /* SEL1_20 [1] */
+ FN_SEL_ET0_0, FN_SEL_ET0_1,
+ /* SEL1_19 [1] */
+ FN_SEL_RMII_0, FN_SEL_RMII_1,
+ /* SEL1_18 [1] */
+ FN_SEL_TMU_0, FN_SEL_TMU_1,
+ /* SEL1_17_16 [2] */
+ FN_SEL_HSPI_0, FN_SEL_HSPI_1, FN_SEL_HSPI_2, 0,
+ /* SEL1_15_14 [2] */
+ FN_SEL_HSCIF_0, FN_SEL_HSCIF_1, FN_SEL_HSCIF_2, FN_SEL_HSCIF_3,
+ /* SEL1_13 [1] */
+ FN_SEL_RCAN_CLK_0, FN_SEL_RCAN_CLK_1,
+ /* SEL1_12_11 [2] */
+ FN_SEL_RCAN1_0, FN_SEL_RCAN1_1, FN_SEL_RCAN1_2, 0,
+ /* SEL1_10 [1] */
+ FN_SEL_RCAN0_0, FN_SEL_RCAN0_1,
+ /* SEL1_9 [1] */
+ FN_SEL_SDHI2_0, FN_SEL_SDHI2_1,
+ /* SEL1_8 [1] */
+ FN_SEL_SDHI1_0, FN_SEL_SDHI1_1,
+ /* SEL1_7 [1] */
+ FN_SEL_SDHI0_0, FN_SEL_SDHI0_1,
+ /* SEL1_6 [1] */
+ FN_SEL_SSI1_0, FN_SEL_SSI1_1,
+ /* SEL1_5 [1] */
+ FN_SEL_SSI0_0, FN_SEL_SSI0_1,
+ /* SEL1_4 [1] */
+ FN_SEL_AUDIO_CLKB_0, FN_SEL_AUDIO_CLKB_1,
+ /* SEL1_3 [1] */
+ FN_SEL_AUDIO_CLKA_0, FN_SEL_AUDIO_CLKA_1,
+ /* SEL1_2 [1] */
+ FN_SEL_FLCTL_0, FN_SEL_FLCTL_1,
+ /* SEL1_1 [1] */
+ FN_SEL_MMC_0, FN_SEL_MMC_1,
+ /* SEL1_0 [1] */
+ FN_SEL_INTC_0, FN_SEL_INTC_1 }
+ },
+ { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xFFFC0050, 32,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 2, 2, 1, 2, 2, 3, 2, 3, 2, 2) {
+ /* SEL2_31 [1] */
+ 0, 0,
+ /* SEL2_30 [1] */
+ 0, 0,
+ /* SEL2_29 [1] */
+ 0, 0,
+ /* SEL2_28 [1] */
+ 0, 0,
+ /* SEL2_27 [1] */
+ 0, 0,
+ /* SEL2_26 [1] */
+ 0, 0,
+ /* SEL2_25 [1] */
+ 0, 0,
+ /* SEL2_24 [1] */
+ 0, 0,
+ /* SEL2_23 [1] */
+ FN_SEL_MTU2_CLK_0, FN_SEL_MTU2_CLK_1,
+ /* SEL2_22 [1] */
+ FN_SEL_MTU2_CH4_0, FN_SEL_MTU2_CH4_1,
+ /* SEL2_21 [1] */
+ FN_SEL_MTU2_CH3_0, FN_SEL_MTU2_CH3_1,
+ /* SEL2_20_19 [2] */
+ FN_SEL_MTU2_CH2_0, FN_SEL_MTU2_CH2_1, FN_SEL_MTU2_CH2_2, 0,
+ /* SEL2_18_17 [2] */
+ FN_SEL_MTU2_CH1_0, FN_SEL_MTU2_CH1_1, FN_SEL_MTU2_CH1_2, 0,
+ /* SEL2_16 [1] */
+ FN_SEL_MTU2_CH0_0, FN_SEL_MTU2_CH0_1,
+ /* SEL2_15_14 [2] */
+ FN_SEL_SCIF5_0, FN_SEL_SCIF5_1, FN_SEL_SCIF5_2, FN_SEL_SCIF5_3,
+ /* SEL2_13_12 [2] */
+ FN_SEL_SCIF4_0, FN_SEL_SCIF4_1, FN_SEL_SCIF4_2, FN_SEL_SCIF4_3,
+ /* SEL2_11_9 [3] */
+ FN_SEL_SCIF3_0, FN_SEL_SCIF3_1, FN_SEL_SCIF3_2, FN_SEL_SCIF3_3,
+ FN_SEL_SCIF3_4, 0, 0, 0,
+ /* SEL2_8_7 [2] */
+ FN_SEL_SCIF2_0, FN_SEL_SCIF2_1, FN_SEL_SCIF2_2, FN_SEL_SCIF2_3,
+ /* SEL2_6_4 [3] */
+ FN_SEL_SCIF1_0, FN_SEL_SCIF1_1, FN_SEL_SCIF1_2, FN_SEL_SCIF1_3,
+ FN_SEL_SCIF1_4, 0, 0, 0,
+ /* SEL2_3_2 [2] */
+ FN_SEL_SCIF0_0, FN_SEL_SCIF0_1, FN_SEL_SCIF0_2, 0,
+ /* SEL2_1_0 [2] */
+ FN_SEL_SCIF_CLK_0, FN_SEL_SCIF_CLK_1, FN_SEL_SCIF_CLK_2, 0 }
+ },
+ /* GPIO 0 - 5*/
+ { PINMUX_CFG_REG("INOUTSEL0", 0xFFC40004, 32, 1) { GP_INOUTSEL(0) } },
+ { PINMUX_CFG_REG("INOUTSEL1", 0xFFC41004, 32, 1) { GP_INOUTSEL(1) } },
+ { PINMUX_CFG_REG("INOUTSEL2", 0xFFC42004, 32, 1) { GP_INOUTSEL(2) } },
+ { PINMUX_CFG_REG("INOUTSEL3", 0xFFC43004, 32, 1) { GP_INOUTSEL(3) } },
+ { PINMUX_CFG_REG("INOUTSEL4", 0xFFC44004, 32, 1) { GP_INOUTSEL(4) } },
+ { PINMUX_CFG_REG("INOUTSEL5", 0xffc45004, 32, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 31 - 24 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 23 - 16 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 15 - 12 */
+ GP_5_11_IN, GP_5_11_OUT,
+ GP_5_10_IN, GP_5_10_OUT,
+ GP_5_9_IN, GP_5_9_OUT,
+ GP_5_8_IN, GP_5_8_OUT,
+ GP_5_7_IN, GP_5_7_OUT,
+ GP_5_6_IN, GP_5_6_OUT,
+ GP_5_5_IN, GP_5_5_OUT,
+ GP_5_4_IN, GP_5_4_OUT,
+ GP_5_3_IN, GP_5_3_OUT,
+ GP_5_2_IN, GP_5_2_OUT,
+ GP_5_1_IN, GP_5_1_OUT,
+ GP_5_0_IN, GP_5_0_OUT }
+ },
+ { },
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+ /* GPIO 0 - 5*/
+ { PINMUX_DATA_REG("INDT0", 0xFFC4000C, 32) { GP_INDT(0) } },
+ { PINMUX_DATA_REG("INDT1", 0xFFC4100C, 32) { GP_INDT(1) } },
+ { PINMUX_DATA_REG("INDT2", 0xFFC4200C, 32) { GP_INDT(2) } },
+ { PINMUX_DATA_REG("INDT3", 0xFFC4300C, 32) { GP_INDT(3) } },
+ { PINMUX_DATA_REG("INDT4", 0xFFC4400C, 32) { GP_INDT(4) } },
+ { PINMUX_DATA_REG("INDT5", 0xFFC4500C, 32) {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ GP_5_11_DATA, GP_5_10_DATA, GP_5_9_DATA, GP_5_8_DATA,
+ GP_5_7_DATA, GP_5_6_DATA, GP_5_5_DATA, GP_5_4_DATA,
+ GP_5_3_DATA, GP_5_2_DATA, GP_5_1_DATA, GP_5_0_DATA }
+ },
+ { },
+};
+
+static struct resource sh7734_pfc_resources[] = {
+ [0] = { /* PFC */
+ .start = 0xFFFC0000,
+ .end = 0xFFFC011C,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = { /* GPIO */
+ .start = 0xFFC40000,
+ .end = 0xFFC4502B,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct pinmux_info sh7734_pinmux_info = {
+ .name = "sh7734_pfc",
+
+ .resource = sh7734_pfc_resources,
+ .num_resources = ARRAY_SIZE(sh7734_pfc_resources),
+
+ .unlock_reg = 0xFFFC0000,
+
+ .reserved_id = PINMUX_RESERVED,
+ .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+ .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
+ .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
+ .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
+ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+ .first_gpio = GPIO_GP_0_0,
+ .last_gpio = GPIO_FN_ST_CLKOUT,
+
+ .gpios = pinmux_gpios,
+ .cfg_regs = pinmux_config_regs,
+ .data_regs = pinmux_data_regs,
+
+ .gpio_data = pinmux_data,
+ .gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return register_pinmux(&sh7734_pinmux_info);
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
index 1b8848317e9c..b91ea8300a3e 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
@@ -13,6 +13,7 @@
#include <linux/serial_sci.h>
#include <linux/uio_driver.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <asm/clock.h>
/* Serial */
@@ -22,7 +23,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 80, 80, 80, 80 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc00)),
};
static struct platform_device scif0_device = {
@@ -39,7 +40,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 81, 81, 81, 81 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc20)),
};
static struct platform_device scif1_device = {
@@ -56,7 +57,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 82, 82, 82, 82 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc40)),
};
static struct platform_device scif2_device = {
@@ -73,7 +74,7 @@ static struct plat_sci_port scif3_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 83, 83, 83, 83 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc60)),
};
static struct platform_device scif3_device = {
@@ -92,8 +93,8 @@ static struct resource iic0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 96,
- .end = 99,
+ .start = evt2irq(0xe00),
+ .end = evt2irq(0xe60),
.flags = IORESOURCE_IRQ,
},
};
@@ -113,8 +114,8 @@ static struct resource iic1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 44,
- .end = 47,
+ .start = evt2irq(0x780),
+ .end = evt2irq(0x7e0),
.flags = IORESOURCE_IRQ,
},
};
@@ -129,7 +130,7 @@ static struct platform_device iic1_device = {
static struct uio_info vpu_platform_data = {
.name = "VPU4",
.version = "0",
- .irq = 60,
+ .irq = evt2irq(0x980),
};
static struct resource vpu_resources[] = {
@@ -157,7 +158,7 @@ static struct platform_device vpu_device = {
static struct uio_info veu_platform_data = {
.name = "VEU",
.version = "0",
- .irq = 54,
+ .irq = evt2irq(0x8c0),
};
static struct resource veu_resources[] = {
@@ -185,7 +186,7 @@ static struct platform_device veu_device = {
static struct uio_info jpu_platform_data = {
.name = "JPU",
.version = "0",
- .irq = 27,
+ .irq = evt2irq(0x560),
};
static struct resource jpu_resources[] = {
@@ -224,7 +225,7 @@ static struct resource cmt_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 104,
+ .start = evt2irq(0xf00),
.flags = IORESOURCE_IRQ,
},
};
@@ -252,7 +253,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -280,7 +281,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -307,7 +308,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
index 87773869a2f3..0bd09d51419f 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
@@ -15,6 +15,7 @@
#include <linux/serial_sci.h>
#include <linux/uio_driver.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <linux/usb/r8a66597.h>
#include <asm/clock.h>
@@ -25,7 +26,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 80, 80, 80, 80 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc00)),
};
static struct platform_device scif0_device = {
@@ -44,8 +45,8 @@ static struct resource iic_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 96,
- .end = 99,
+ .start = evt2irq(0xe00),
+ .end = evt2irq(0xe60),
.flags = IORESOURCE_IRQ,
},
};
@@ -68,8 +69,8 @@ static struct resource usb_host_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 65,
- .end = 65,
+ .start = evt2irq(0xa20),
+ .end = evt2irq(0xa20),
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
},
};
@@ -89,7 +90,7 @@ static struct platform_device usb_host_device = {
static struct uio_info vpu_platform_data = {
.name = "VPU5",
.version = "0",
- .irq = 60,
+ .irq = evt2irq(0x980),
};
static struct resource vpu_resources[] = {
@@ -117,7 +118,7 @@ static struct platform_device vpu_device = {
static struct uio_info veu0_platform_data = {
.name = "VEU",
.version = "0",
- .irq = 54,
+ .irq = evt2irq(0x8c0),
};
static struct resource veu0_resources[] = {
@@ -145,7 +146,7 @@ static struct platform_device veu0_device = {
static struct uio_info veu1_platform_data = {
.name = "VEU",
.version = "0",
- .irq = 27,
+ .irq = evt2irq(0x560),
};
static struct resource veu1_resources[] = {
@@ -184,7 +185,7 @@ static struct resource cmt_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 104,
+ .start = evt2irq(0xf00),
.flags = IORESOURCE_IRQ,
},
};
@@ -240,7 +241,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -267,7 +268,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 8420d4bc8bfc..0f5a21907da6 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -13,6 +13,7 @@
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <linux/uio_driver.h>
#include <linux/usb/m66592.h>
@@ -147,20 +148,20 @@ static struct resource sh7722_dmae_resources[] = {
},
{
.name = "error_irq",
- .start = 78,
- .end = 78,
+ .start = evt2irq(0xbc0),
+ .end = evt2irq(0xbc0),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 0-3 */
- .start = 48,
- .end = 51,
+ .start = evt2irq(0x800),
+ .end = evt2irq(0x860),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 4-5 */
- .start = 76,
- .end = 77,
+ .start = evt2irq(0xb80),
+ .end = evt2irq(0xba0),
.flags = IORESOURCE_IRQ,
},
};
@@ -182,7 +183,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 80, 80, 80, 80 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc00)),
.ops = &sh7722_sci_port_ops,
.regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
};
@@ -201,7 +202,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 81, 81, 81, 81 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc20)),
.ops = &sh7722_sci_port_ops,
.regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
};
@@ -220,7 +221,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 82, 82, 82, 82 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc40)),
.ops = &sh7722_sci_port_ops,
.regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
};
@@ -241,17 +242,17 @@ static struct resource rtc_resources[] = {
},
[1] = {
/* Period IRQ */
- .start = 45,
+ .start = evt2irq(0x7a0),
.flags = IORESOURCE_IRQ,
},
[2] = {
/* Carry IRQ */
- .start = 46,
+ .start = evt2irq(0x7c0),
.flags = IORESOURCE_IRQ,
},
[3] = {
/* Alarm IRQ */
- .start = 44,
+ .start = evt2irq(0x780),
.flags = IORESOURCE_IRQ,
},
};
@@ -275,8 +276,8 @@ static struct resource usbf_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 65,
- .end = 65,
+ .start = evt2irq(0xa20),
+ .end = evt2irq(0xa20),
.flags = IORESOURCE_IRQ,
},
};
@@ -301,8 +302,8 @@ static struct resource iic_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 96,
- .end = 99,
+ .start = evt2irq(0xe00),
+ .end = evt2irq(0xe60),
.flags = IORESOURCE_IRQ,
},
};
@@ -317,7 +318,7 @@ static struct platform_device iic_device = {
static struct uio_info vpu_platform_data = {
.name = "VPU4",
.version = "0",
- .irq = 60,
+ .irq = evt2irq(0x980),
};
static struct resource vpu_resources[] = {
@@ -345,7 +346,7 @@ static struct platform_device vpu_device = {
static struct uio_info veu_platform_data = {
.name = "VEU",
.version = "0",
- .irq = 54,
+ .irq = evt2irq(0x8c0),
};
static struct resource veu_resources[] = {
@@ -373,7 +374,7 @@ static struct platform_device veu_device = {
static struct uio_info jpu_platform_data = {
.name = "JPU",
.version = "0",
- .irq = 27,
+ .irq = evt2irq(0x560),
};
static struct resource jpu_resources[] = {
@@ -412,7 +413,7 @@ static struct resource cmt_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 104,
+ .start = evt2irq(0xf00),
.flags = IORESOURCE_IRQ,
},
};
@@ -440,7 +441,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -468,7 +469,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -525,7 +526,7 @@ static struct resource siu_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 108,
+ .start = evt2irq(0xf80),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index a188c9ea4393..28d6fd835fe0 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -15,6 +15,7 @@
#include <linux/uio_driver.h>
#include <linux/usb/r8a66597.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <linux/io.h>
#include <asm/clock.h>
#include <asm/mmzone.h>
@@ -28,7 +29,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 80, 80, 80, 80 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc00)),
.regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
};
@@ -47,7 +48,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 81, 81, 81, 81 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc20)),
.regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
};
@@ -66,7 +67,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 82, 82, 82, 82 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc40)),
.regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
};
@@ -85,7 +86,7 @@ static struct plat_sci_port scif3_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_3,
.type = PORT_SCIFA,
- .irqs = { 56, 56, 56, 56 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x900)),
};
static struct platform_device scif3_device = {
@@ -103,7 +104,7 @@ static struct plat_sci_port scif4_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_3,
.type = PORT_SCIFA,
- .irqs = { 88, 88, 88, 88 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xd00)),
};
static struct platform_device scif4_device = {
@@ -121,7 +122,7 @@ static struct plat_sci_port scif5_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_3,
.type = PORT_SCIFA,
- .irqs = { 109, 109, 109, 109 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xfa0)),
};
static struct platform_device scif5_device = {
@@ -135,7 +136,7 @@ static struct platform_device scif5_device = {
static struct uio_info vpu_platform_data = {
.name = "VPU5",
.version = "0",
- .irq = 60,
+ .irq = evt2irq(0x980),
};
static struct resource vpu_resources[] = {
@@ -163,7 +164,7 @@ static struct platform_device vpu_device = {
static struct uio_info veu0_platform_data = {
.name = "VEU2H",
.version = "0",
- .irq = 54,
+ .irq = evt2irq(0x8c0),
};
static struct resource veu0_resources[] = {
@@ -191,7 +192,7 @@ static struct platform_device veu0_device = {
static struct uio_info veu1_platform_data = {
.name = "VEU2H",
.version = "0",
- .irq = 27,
+ .irq = evt2irq(0x560),
};
static struct resource veu1_resources[] = {
@@ -230,7 +231,7 @@ static struct resource cmt_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 104,
+ .start = evt2irq(0xf00),
.flags = IORESOURCE_IRQ,
},
};
@@ -258,7 +259,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -286,7 +287,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -313,7 +314,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
@@ -340,7 +341,7 @@ static struct resource tmu3_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 57,
+ .start = evt2irq(0x920),
.flags = IORESOURCE_IRQ,
},
};
@@ -367,7 +368,7 @@ static struct resource tmu4_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 58,
+ .start = evt2irq(0x940),
.flags = IORESOURCE_IRQ,
},
};
@@ -394,7 +395,7 @@ static struct resource tmu5_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 57,
+ .start = evt2irq(0x920),
.flags = IORESOURCE_IRQ,
},
};
@@ -417,17 +418,17 @@ static struct resource rtc_resources[] = {
},
[1] = {
/* Period IRQ */
- .start = 69,
+ .start = evt2irq(0xaa0),
.flags = IORESOURCE_IRQ,
},
[2] = {
/* Carry IRQ */
- .start = 70,
+ .start = evt2irq(0xac0),
.flags = IORESOURCE_IRQ,
},
[3] = {
/* Alarm IRQ */
- .start = 68,
+ .start = evt2irq(0xa80),
.flags = IORESOURCE_IRQ,
},
};
@@ -450,8 +451,8 @@ static struct resource sh7723_usb_host_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 65,
- .end = 65,
+ .start = evt2irq(0xa20),
+ .end = evt2irq(0xa20),
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
},
};
@@ -476,8 +477,8 @@ static struct resource iic_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 96,
- .end = 99,
+ .start = evt2irq(0xe00),
+ .end = evt2irq(0xe60),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index 4c671cfe68aa..26b74c2f9496 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -20,6 +20,7 @@
#include <linux/uio_driver.h>
#include <linux/sh_dma.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <linux/io.h>
#include <linux/notifier.h>
@@ -215,20 +216,20 @@ static struct resource sh7724_dmae0_resources[] = {
},
{
.name = "error_irq",
- .start = 78,
- .end = 78,
+ .start = evt2irq(0xbc0),
+ .end = evt2irq(0xbc0),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 0-3 */
- .start = 48,
- .end = 51,
+ .start = evt2irq(0x800),
+ .end = evt2irq(0x860),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 4-5 */
- .start = 76,
- .end = 77,
+ .start = evt2irq(0xb80),
+ .end = evt2irq(0xba0),
.flags = IORESOURCE_IRQ,
},
};
@@ -249,20 +250,20 @@ static struct resource sh7724_dmae1_resources[] = {
},
{
.name = "error_irq",
- .start = 74,
- .end = 74,
+ .start = evt2irq(0xb40),
+ .end = evt2irq(0xb40),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 0-3 */
- .start = 40,
- .end = 43,
+ .start = evt2irq(0x700),
+ .end = evt2irq(0x760),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 4-5 */
- .start = 72,
- .end = 73,
+ .start = evt2irq(0xb00),
+ .end = evt2irq(0xb20),
.flags = IORESOURCE_IRQ,
},
};
@@ -295,7 +296,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 80, 80, 80, 80 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc00)),
.regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
};
@@ -314,7 +315,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 81, 81, 81, 81 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc20)),
.regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
};
@@ -333,7 +334,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 82, 82, 82, 82 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xc40)),
.regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
};
@@ -352,7 +353,7 @@ static struct plat_sci_port scif3_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_3,
.type = PORT_SCIFA,
- .irqs = { 56, 56, 56, 56 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x900)),
};
static struct platform_device scif3_device = {
@@ -370,7 +371,7 @@ static struct plat_sci_port scif4_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_3,
.type = PORT_SCIFA,
- .irqs = { 88, 88, 88, 88 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xd00)),
};
static struct platform_device scif4_device = {
@@ -388,7 +389,7 @@ static struct plat_sci_port scif5_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_3,
.type = PORT_SCIFA,
- .irqs = { 109, 109, 109, 109 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xfa0)),
};
static struct platform_device scif5_device = {
@@ -408,17 +409,17 @@ static struct resource rtc_resources[] = {
},
[1] = {
/* Period IRQ */
- .start = 69,
+ .start = evt2irq(0xaa0),
.flags = IORESOURCE_IRQ,
},
[2] = {
/* Carry IRQ */
- .start = 70,
+ .start = evt2irq(0xac0),
.flags = IORESOURCE_IRQ,
},
[3] = {
/* Alarm IRQ */
- .start = 68,
+ .start = evt2irq(0xa80),
.flags = IORESOURCE_IRQ,
},
};
@@ -439,8 +440,8 @@ static struct resource iic0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 96,
- .end = 99,
+ .start = evt2irq(0xe00),
+ .end = evt2irq(0xe60),
.flags = IORESOURCE_IRQ,
},
};
@@ -461,8 +462,8 @@ static struct resource iic1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 92,
- .end = 95,
+ .start = evt2irq(0xd80),
+ .end = evt2irq(0xde0),
.flags = IORESOURCE_IRQ,
},
};
@@ -478,7 +479,7 @@ static struct platform_device iic1_device = {
static struct uio_info vpu_platform_data = {
.name = "VPU5F",
.version = "0",
- .irq = 60,
+ .irq = evt2irq(0x980),
};
static struct resource vpu_resources[] = {
@@ -507,7 +508,7 @@ static struct platform_device vpu_device = {
static struct uio_info veu0_platform_data = {
.name = "VEU3F0",
.version = "0",
- .irq = 83,
+ .irq = evt2irq(0xc60),
};
static struct resource veu0_resources[] = {
@@ -536,7 +537,7 @@ static struct platform_device veu0_device = {
static struct uio_info veu1_platform_data = {
.name = "VEU3F1",
.version = "0",
- .irq = 54,
+ .irq = evt2irq(0x8c0),
};
static struct resource veu1_resources[] = {
@@ -633,7 +634,7 @@ static struct resource cmt_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 104,
+ .start = evt2irq(0xf00),
.flags = IORESOURCE_IRQ,
},
};
@@ -661,7 +662,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -689,7 +690,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -716,7 +717,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
@@ -744,7 +745,7 @@ static struct resource tmu3_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 57,
+ .start = evt2irq(0x920),
.flags = IORESOURCE_IRQ,
},
};
@@ -771,7 +772,7 @@ static struct resource tmu4_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 58,
+ .start = evt2irq(0x940),
.flags = IORESOURCE_IRQ,
},
};
@@ -798,7 +799,7 @@ static struct resource tmu5_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 57,
+ .start = evt2irq(0x920),
.flags = IORESOURCE_IRQ,
},
};
@@ -817,7 +818,7 @@ static struct platform_device tmu5_device = {
static struct uio_info jpu_platform_data = {
.name = "JPU",
.version = "0",
- .irq = 27,
+ .irq = evt2irq(0x560),
};
static struct resource jpu_resources[] = {
@@ -846,7 +847,7 @@ static struct platform_device jpu_device = {
static struct uio_info spu0_platform_data = {
.name = "SPU2DSP0",
.version = "0",
- .irq = 86,
+ .irq = evt2irq(0xcc0),
};
static struct resource spu0_resources[] = {
@@ -875,7 +876,7 @@ static struct platform_device spu0_device = {
static struct uio_info spu1_platform_data = {
.name = "SPU2DSP1",
.version = "0",
- .irq = 87,
+ .irq = evt2irq(0xce0),
};
static struct resource spu1_resources[] = {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7734.c b/arch/sh/kernel/cpu/sh4a/setup-sh7734.c
new file mode 100644
index 000000000000..f799971d453c
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7734.c
@@ -0,0 +1,800 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/setup-sh7734.c
+
+ * SH7734 Setup
+ *
+ * Copyright (C) 2011,2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ * Copyright (C) 2011,2012 Renesas Solutions Corp.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+#include <asm/irq.h>
+#include <cpu/sh7734.h>
+
+/* SCIF */
+static struct plat_sci_port scif0_platform_data = {
+ .mapbase = 0xFFE40000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x8C0)),
+ .regtype = SCIx_SH4_SCIF_REGTYPE,
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .mapbase = 0xFFE41000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x8E0)),
+ .regtype = SCIx_SH4_SCIF_REGTYPE,
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .mapbase = 0xFFE42000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x900)),
+ .regtype = SCIx_SH4_SCIF_REGTYPE,
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .mapbase = 0xFFE43000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x920)),
+ .regtype = SCIx_SH4_SCIF_REGTYPE,
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .mapbase = 0xFFE44000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x940)),
+ .regtype = SCIx_SH4_SCIF_REGTYPE,
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 4,
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct plat_sci_port scif5_platform_data = {
+ .mapbase = 0xFFE43000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x960)),
+ .regtype = SCIx_SH4_SCIF_REGTYPE,
+};
+
+static struct platform_device scif5_device = {
+ .name = "sh-sci",
+ .id = 5,
+ .dev = {
+ .platform_data = &scif5_platform_data,
+ },
+};
+
+/* RTC */
+static struct resource rtc_resources[] = {
+ [0] = {
+ .name = "rtc",
+ .start = 0xFFFC5000,
+ .end = 0xFFFC5000 + 0x26 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ .start = evt2irq(0xC00),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+/* I2C 0 */
+static struct resource i2c0_resources[] = {
+ [0] = {
+ .name = "IIC0",
+ .start = 0xFFC70000,
+ .end = 0xFFC7000A - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x860),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c0_device = {
+ .name = "i2c-sh7734",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(i2c0_resources),
+ .resource = i2c0_resources,
+};
+
+/* TMU */
+static struct sh_timer_config tmu0_platform_data = {
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+ [0] = {
+ .start = 0xFFD80008,
+ .end = 0xFFD80014 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x400),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+ [0] = {
+ .start = 0xFFD80014,
+ .end = 0xFFD80020 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x420),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu1_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu1_platform_data,
+ },
+ .resource = tmu1_resources,
+ .num_resources = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+};
+
+static struct resource tmu2_resources[] = {
+ [0] = {
+ .start = 0xFFD80020,
+ .end = 0xFFD80030 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x440),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu2_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu2_platform_data,
+ },
+ .resource = tmu2_resources,
+ .num_resources = ARRAY_SIZE(tmu2_resources),
+};
+
+
+static struct sh_timer_config tmu3_platform_data = {
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+};
+
+static struct resource tmu3_resources[] = {
+ [0] = {
+ .start = 0xFFD81008,
+ .end = 0xFFD81014 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x480),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu3_device = {
+ .name = "sh_tmu",
+ .id = 3,
+ .dev = {
+ .platform_data = &tmu3_platform_data,
+ },
+ .resource = tmu3_resources,
+ .num_resources = ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+};
+
+static struct resource tmu4_resources[] = {
+ [0] = {
+ .start = 0xFFD81014,
+ .end = 0xFFD81020 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x4A0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu4_device = {
+ .name = "sh_tmu",
+ .id = 4,
+ .dev = {
+ .platform_data = &tmu4_platform_data,
+ },
+ .resource = tmu4_resources,
+ .num_resources = ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+};
+
+static struct resource tmu5_resources[] = {
+ [0] = {
+ .start = 0xFFD81020,
+ .end = 0xFFD81030 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x4C0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu5_device = {
+ .name = "sh_tmu",
+ .id = 5,
+ .dev = {
+ .platform_data = &tmu5_platform_data,
+ },
+ .resource = tmu5_resources,
+ .num_resources = ARRAY_SIZE(tmu5_resources),
+};
+
+static struct sh_timer_config tmu6_platform_data = {
+ .channel_offset = 0x4,
+ .timer_bit = 0,
+};
+
+static struct resource tmu6_resources[] = {
+ [0] = {
+ .start = 0xFFD82008,
+ .end = 0xFFD82014 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x500),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu6_device = {
+ .name = "sh_tmu",
+ .id = 6,
+ .dev = {
+ .platform_data = &tmu6_platform_data,
+ },
+ .resource = tmu6_resources,
+ .num_resources = ARRAY_SIZE(tmu6_resources),
+};
+
+static struct sh_timer_config tmu7_platform_data = {
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+};
+
+static struct resource tmu7_resources[] = {
+ [0] = {
+ .start = 0xFFD82014,
+ .end = 0xFFD82020 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x520),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu7_device = {
+ .name = "sh_tmu",
+ .id = 7,
+ .dev = {
+ .platform_data = &tmu7_platform_data,
+ },
+ .resource = tmu7_resources,
+ .num_resources = ARRAY_SIZE(tmu7_resources),
+};
+
+static struct sh_timer_config tmu8_platform_data = {
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+};
+
+static struct resource tmu8_resources[] = {
+ [0] = {
+ .start = 0xFFD82020,
+ .end = 0xFFD82030 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x540),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu8_device = {
+ .name = "sh_tmu",
+ .id = 8,
+ .dev = {
+ .platform_data = &tmu8_platform_data,
+ },
+ .resource = tmu8_resources,
+ .num_resources = ARRAY_SIZE(tmu8_resources),
+};
+
+static struct platform_device *sh7734_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+ &tmu3_device,
+ &tmu4_device,
+ &tmu5_device,
+ &tmu6_device,
+ &tmu7_device,
+ &tmu8_device,
+ &rtc_device,
+};
+
+static struct platform_device *sh7734_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+ &tmu3_device,
+ &tmu4_device,
+ &tmu5_device,
+ &tmu6_device,
+ &tmu7_device,
+ &tmu8_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7734_early_devices,
+ ARRAY_SIZE(sh7734_early_devices));
+}
+
+#define GROUP 0
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+
+ IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH,
+ IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH,
+ IRL0_HLLL, IRL0_HLLH, IRL0_HLHL, IRL0_HLHH,
+ IRL0_HHLL, IRL0_HHLH, IRL0_HHHL,
+
+ IRQ0, IRQ1, IRQ2, IRQ3,
+ DU,
+ TMU00, TMU10, TMU20, TMU21,
+ TMU30, TMU40, TMU50, TMU51,
+ TMU60, TMU70, TMU80,
+ RESET_WDT,
+ USB,
+ HUDI,
+ SHDMAC,
+ SSI0, SSI1, SSI2, SSI3,
+ VIN0,
+ RGPVG,
+ _2DG,
+ MMC,
+ HSPI,
+ LBSCATA,
+ I2C0,
+ RCAN0,
+ MIMLB,
+ SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5,
+ LBSCDMAC0, LBSCDMAC1, LBSCDMAC2,
+ RCAN1,
+ SDHI0, SDHI1,
+ IEBUS,
+ HPBDMAC0_3, HPBDMAC4_10, HPBDMAC11_18, HPBDMAC19_22, HPBDMAC23_25_27_28,
+ RTC,
+ VIN1,
+ LCDC,
+ SRC0, SRC1,
+ GETHER,
+ SDHI2,
+ GPIO0_3, GPIO4_5,
+ STIF0, STIF1,
+ ADMAC,
+ HIF,
+ FLCTL,
+ ADC,
+ MTU2,
+ RSPI,
+ QSPI,
+ HSCIF,
+ VEU3F_VE3,
+
+ /* Group */
+ /* Mask */
+ STIF_M,
+ GPIO_M,
+ HPBDMAC_M,
+ LBSCDMAC_M,
+ RCAN_M,
+ SRC_M,
+ SCIF_M,
+ LCDC_M,
+ _2DG_M,
+ VIN_M,
+ TMU_3_M,
+ TMU_0_M,
+
+ /* Priority */
+ RCAN_P,
+ LBSCDMAC_P,
+
+ /* Common */
+ SDHI,
+ SSI,
+ SPI,
+};
+
+static struct intc_vect vectors[] __initdata = {
+ INTC_VECT(DU, 0x3E0),
+ INTC_VECT(TMU00, 0x400),
+ INTC_VECT(TMU10, 0x420),
+ INTC_VECT(TMU20, 0x440),
+ INTC_VECT(TMU30, 0x480),
+ INTC_VECT(TMU40, 0x4A0),
+ INTC_VECT(TMU50, 0x4C0),
+ INTC_VECT(TMU51, 0x4E0),
+ INTC_VECT(TMU60, 0x500),
+ INTC_VECT(TMU70, 0x520),
+ INTC_VECT(TMU80, 0x540),
+ INTC_VECT(RESET_WDT, 0x560),
+ INTC_VECT(USB, 0x580),
+ INTC_VECT(HUDI, 0x600),
+ INTC_VECT(SHDMAC, 0x620),
+ INTC_VECT(SSI0, 0x6C0),
+ INTC_VECT(SSI1, 0x6E0),
+ INTC_VECT(SSI2, 0x700),
+ INTC_VECT(SSI3, 0x720),
+ INTC_VECT(VIN0, 0x740),
+ INTC_VECT(RGPVG, 0x760),
+ INTC_VECT(_2DG, 0x780),
+ INTC_VECT(MMC, 0x7A0),
+ INTC_VECT(HSPI, 0x7E0),
+ INTC_VECT(LBSCATA, 0x840),
+ INTC_VECT(I2C0, 0x860),
+ INTC_VECT(RCAN0, 0x880),
+ INTC_VECT(SCIF0, 0x8A0),
+ INTC_VECT(SCIF1, 0x8C0),
+ INTC_VECT(SCIF2, 0x900),
+ INTC_VECT(SCIF3, 0x920),
+ INTC_VECT(SCIF4, 0x940),
+ INTC_VECT(SCIF5, 0x960),
+ INTC_VECT(LBSCDMAC0, 0x9E0),
+ INTC_VECT(LBSCDMAC1, 0xA00),
+ INTC_VECT(LBSCDMAC2, 0xA20),
+ INTC_VECT(RCAN1, 0xA60),
+ INTC_VECT(SDHI0, 0xAE0),
+ INTC_VECT(SDHI1, 0xB00),
+ INTC_VECT(IEBUS, 0xB20),
+ INTC_VECT(HPBDMAC0_3, 0xB60),
+ INTC_VECT(HPBDMAC4_10, 0xB80),
+ INTC_VECT(HPBDMAC11_18, 0xBA0),
+ INTC_VECT(HPBDMAC19_22, 0xBC0),
+ INTC_VECT(HPBDMAC23_25_27_28, 0xBE0),
+ INTC_VECT(RTC, 0xC00),
+ INTC_VECT(VIN1, 0xC20),
+ INTC_VECT(LCDC, 0xC40),
+ INTC_VECT(SRC0, 0xC60),
+ INTC_VECT(SRC1, 0xC80),
+ INTC_VECT(GETHER, 0xCA0),
+ INTC_VECT(SDHI2, 0xCC0),
+ INTC_VECT(GPIO0_3, 0xCE0),
+ INTC_VECT(GPIO4_5, 0xD00),
+ INTC_VECT(STIF0, 0xD20),
+ INTC_VECT(STIF1, 0xD40),
+ INTC_VECT(ADMAC, 0xDA0),
+ INTC_VECT(HIF, 0xDC0),
+ INTC_VECT(FLCTL, 0xDE0),
+ INTC_VECT(ADC, 0xE00),
+ INTC_VECT(MTU2, 0xE20),
+ INTC_VECT(RSPI, 0xE40),
+ INTC_VECT(QSPI, 0xE60),
+ INTC_VECT(HSCIF, 0xFC0),
+ INTC_VECT(VEU3F_VE3, 0xF40),
+};
+
+static struct intc_group groups[] __initdata = {
+ /* Common */
+ INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2),
+ INTC_GROUP(SPI, HSPI, RSPI, QSPI),
+ INTC_GROUP(SSI, SSI0, SSI1, SSI2, SSI3),
+
+ /* Mask group */
+ INTC_GROUP(STIF_M, STIF0, STIF1), /* 22 */
+ INTC_GROUP(GPIO_M, GPIO0_3, GPIO4_5), /* 21 */
+ INTC_GROUP(HPBDMAC_M, HPBDMAC0_3, HPBDMAC4_10, HPBDMAC11_18,
+ HPBDMAC19_22, HPBDMAC23_25_27_28), /* 19 */
+ INTC_GROUP(LBSCDMAC_M, LBSCDMAC0, LBSCDMAC1, LBSCDMAC2), /* 18 */
+ INTC_GROUP(RCAN_M, RCAN0, RCAN1, IEBUS), /* 17 */
+ INTC_GROUP(SRC_M, SRC0, SRC1), /* 16 */
+ INTC_GROUP(SCIF_M, SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5,
+ HSCIF), /* 14 */
+ INTC_GROUP(LCDC_M, LCDC, MIMLB), /* 13 */
+ INTC_GROUP(_2DG_M, _2DG, RGPVG), /* 12 */
+ INTC_GROUP(VIN_M, VIN0, VIN1), /* 10 */
+ INTC_GROUP(TMU_3_M, TMU30, TMU40, TMU50, TMU51,
+ TMU60, TMU60, TMU70, TMU80), /* 2 */
+ INTC_GROUP(TMU_0_M, TMU00, TMU10, TMU20, TMU21), /* 1 */
+
+ /* Priority group*/
+ INTC_GROUP(RCAN_P, RCAN0, RCAN1), /* INT2PRI5 */
+ INTC_GROUP(LBSCDMAC_P, LBSCDMAC0, LBSCDMAC1), /* INT2PRI5 */
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xFF804040, 0xFF804044, 32, /* INT2MSKRG / INT2MSKCR */
+ { 0,
+ VEU3F_VE3,
+ SDHI, /* SDHI 0-2 */
+ ADMAC,
+ FLCTL,
+ RESET_WDT,
+ HIF,
+ ADC,
+ MTU2,
+ STIF_M, /* STIF 0,1 */
+ GPIO_M, /* GPIO 0-5*/
+ GETHER,
+ HPBDMAC_M, /* HPBDMAC 0_3 - 23_25_27_28 */
+ LBSCDMAC_M, /* LBSCDMAC 0 - 2 */
+ RCAN_M, /* RCAN, IEBUS */
+ SRC_M, /* SRC 0,1 */
+ LBSCATA,
+ SCIF_M, /* SCIF 0-5, HSCIF */
+ LCDC_M, /* LCDC, MIMLB */
+ _2DG_M, /* 2DG, RGPVG */
+ SPI, /* HSPI, RSPI, QSPI */
+ VIN_M, /* VIN0, 1 */
+ SSI, /* SSI 0-3 */
+ USB,
+ SHDMAC,
+ HUDI,
+ MMC,
+ RTC,
+ I2C0, /* I2C */ /* I2C 0, 1*/
+ TMU_3_M, /* TMU30 - TMU80 */
+ TMU_0_M, /* TMU00 - TMU21 */
+ DU } },
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xFF804000, 0, 32, 8, /* INT2PRI0 */
+ { DU, TMU00, TMU10, TMU20 } },
+ { 0xFF804004, 0, 32, 8, /* INT2PRI1 */
+ { TMU30, TMU60, RTC, SDHI } },
+ { 0xFF804008, 0, 32, 8, /* INT2PRI2 */
+ { HUDI, SHDMAC, USB, SSI } },
+ { 0xFF80400C, 0, 32, 8, /* INT2PRI3 */
+ { VIN0, SPI, _2DG, LBSCATA } },
+ { 0xFF804010, 0, 32, 8, /* INT2PRI4 */
+ { SCIF0, SCIF3, HSCIF, LCDC } },
+ { 0xFF804014, 0, 32, 8, /* INT2PRI5 */
+ { RCAN_P, LBSCDMAC_P, LBSCDMAC2, MMC } },
+ { 0xFF804018, 0, 32, 8, /* INT2PRI6 */
+ { HPBDMAC0_3, HPBDMAC4_10, HPBDMAC11_18, HPBDMAC19_22 } },
+ { 0xFF80401C, 0, 32, 8, /* INT2PRI7 */
+ { HPBDMAC23_25_27_28, I2C0, SRC0, SRC1 } },
+ { 0xFF804020, 0, 32, 8, /* INT2PRI8 */
+ { 0 /* ADIF */, VIN1, RESET_WDT, HIF } },
+ { 0xFF804024, 0, 32, 8, /* INT2PRI9 */
+ { ADMAC, FLCTL, GPIO0_3, GPIO4_5 } },
+ { 0xFF804028, 0, 32, 8, /* INT2PRI10 */
+ { STIF0, STIF1, VEU3F_VE3, GETHER } },
+ { 0xFF80402C, 0, 32, 8, /* INT2PRI11 */
+ { MTU2, RGPVG, MIMLB, IEBUS } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7734", vectors, groups,
+ mask_registers, prio_registers, NULL);
+
+/* Support for external interrupt pins in IRQ mode */
+
+static struct intc_vect irq3210_vectors[] __initdata = {
+ INTC_VECT(IRQ0, 0x240), INTC_VECT(IRQ1, 0x280),
+ INTC_VECT(IRQ2, 0x2C0), INTC_VECT(IRQ3, 0x300),
+};
+
+static struct intc_sense_reg irq3210_sense_registers[] __initdata = {
+ { 0xFF80201C, 32, 2, /* ICR1 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, } },
+};
+
+static struct intc_mask_reg irq3210_ack_registers[] __initdata = {
+ { 0xFF802024, 0, 32, /* INTREQ */
+ { IRQ0, IRQ1, IRQ2, IRQ3, } },
+};
+
+static struct intc_mask_reg irq3210_mask_registers[] __initdata = {
+ { 0xFF802044, 0xFF802064, 32, /* INTMSK0 / INTMSKCLR0 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, } },
+};
+
+static struct intc_prio_reg irq3210_prio_registers[] __initdata = {
+ { 0xFF802010, 0, 32, 4, /* INTPRI */
+ { IRQ0, IRQ1, IRQ2, IRQ3, } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq3210, "sh7734-irq3210",
+ irq3210_vectors, NULL,
+ irq3210_mask_registers, irq3210_prio_registers,
+ irq3210_sense_registers, irq3210_ack_registers);
+
+/* External interrupt pins in IRL mode */
+
+static struct intc_vect vectors_irl3210[] __initdata = {
+ INTC_VECT(IRL0_LLLL, 0x200), INTC_VECT(IRL0_LLLH, 0x220),
+ INTC_VECT(IRL0_LLHL, 0x240), INTC_VECT(IRL0_LLHH, 0x260),
+ INTC_VECT(IRL0_LHLL, 0x280), INTC_VECT(IRL0_LHLH, 0x2a0),
+ INTC_VECT(IRL0_LHHL, 0x2c0), INTC_VECT(IRL0_LHHH, 0x2e0),
+ INTC_VECT(IRL0_HLLL, 0x300), INTC_VECT(IRL0_HLLH, 0x320),
+ INTC_VECT(IRL0_HLHL, 0x340), INTC_VECT(IRL0_HLHH, 0x360),
+ INTC_VECT(IRL0_HHLL, 0x380), INTC_VECT(IRL0_HHLH, 0x3a0),
+ INTC_VECT(IRL0_HHHL, 0x3c0),
+};
+
+static DECLARE_INTC_DESC(intc_desc_irl3210, "sh7734-irl3210",
+ vectors_irl3210, NULL, mask_registers, NULL, NULL);
+
+#define INTC_ICR0 0xFF802000
+#define INTC_INTMSK0 0xFF802044
+#define INTC_INTMSK1 0xFF802048
+#define INTC_INTMSKCLR0 0xFF802064
+#define INTC_INTMSKCLR1 0xFF802068
+
+void __init plat_irq_setup(void)
+{
+ /* disable IRQ3-0 */
+ __raw_writel(0xF0000000, INTC_INTMSK0);
+
+ /* disable IRL3-0 */
+ __raw_writel(0x80000000, INTC_INTMSK1);
+
+ /* select IRL mode for IRL3-0 */
+ __raw_writel(__raw_readl(INTC_ICR0) & ~0x00800000, INTC_ICR0);
+
+ /* disable holding function, ie enable "SH-4 Mode (LVLMODE)" */
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0);
+
+ register_intc_controller(&intc_desc);
+}
+
+void __init plat_irq_setup_pins(int mode)
+{
+ switch (mode) {
+ case IRQ_MODE_IRQ3210:
+ /* select IRQ mode for IRL3-0 */
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00800000, INTC_ICR0);
+ register_intc_controller(&intc_desc_irq3210);
+ break;
+ case IRQ_MODE_IRL3210:
+ /* enable IRL0-3 but don't provide any masking */
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
+ __raw_writel(0xf0000000, INTC_INTMSKCLR0);
+ break;
+ case IRQ_MODE_IRL3210_MASK:
+ /* enable IRL0-3 and mask using cpu intc controller */
+ __raw_writel(0x80000000, INTC_INTMSKCLR0);
+ register_intc_controller(&intc_desc_irl3210);
+ break;
+ default:
+ BUG();
+ }
+}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
index c8836cffa216..a7708425afa9 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
@@ -18,7 +18,7 @@
#include <linux/dma-mapping.h>
#include <linux/sh_timer.h>
#include <linux/sh_dma.h>
-
+#include <linux/sh_intc.h>
#include <cpu/dma-register.h>
#include <cpu/sh7757.h>
@@ -28,7 +28,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 40, 40, 40, 40 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x700)),
};
static struct platform_device scif2_device = {
@@ -45,7 +45,7 @@ static struct plat_sci_port scif3_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 76, 76, 76, 76 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xb80)),
};
static struct platform_device scif3_device = {
@@ -62,7 +62,7 @@ static struct plat_sci_port scif4_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 104, 104, 104, 104 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xF00)),
};
static struct platform_device scif4_device = {
@@ -86,7 +86,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 28,
+ .start = evt2irq(0x580),
.flags = IORESOURCE_IRQ,
},
};
@@ -114,7 +114,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 29,
+ .start = evt2irq(0x5a0),
.flags = IORESOURCE_IRQ,
},
};
@@ -136,7 +136,7 @@ static struct resource spi0_resources[] = {
.flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
},
[1] = {
- .start = 86,
+ .start = evt2irq(0xcc0),
.flags = IORESOURCE_IRQ,
},
};
@@ -466,8 +466,8 @@ static struct resource sh7757_dmae0_resources[] = {
},
{
.name = "error_irq",
- .start = 34,
- .end = 34,
+ .start = evt2irq(0x640),
+ .end = evt2irq(0x640),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
};
@@ -488,56 +488,56 @@ static struct resource sh7757_dmae1_resources[] = {
},
{
.name = "error_irq",
- .start = 34,
- .end = 34,
+ .start = evt2irq(0x640),
+ .end = evt2irq(0x640),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 4 */
- .start = 46,
- .end = 46,
+ .start = evt2irq(0x7c0),
+ .end = evt2irq(0x7c0),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 5 */
- .start = 46,
- .end = 46,
+ .start = evt2irq(0x7c0),
+ .end = evt2irq(0x7c0),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 6 */
- .start = 88,
- .end = 88,
+ .start = evt2irq(0xd00),
+ .end = evt2irq(0xd00),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 7 */
- .start = 88,
- .end = 88,
+ .start = evt2irq(0xd00),
+ .end = evt2irq(0xd00),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 8 */
- .start = 88,
- .end = 88,
+ .start = evt2irq(0xd00),
+ .end = evt2irq(0xd00),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 9 */
- .start = 88,
- .end = 88,
+ .start = evt2irq(0xd00),
+ .end = evt2irq(0xd00),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 10 */
- .start = 88,
- .end = 88,
+ .start = evt2irq(0xd00),
+ .end = evt2irq(0xd00),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 11 */
- .start = 88,
- .end = 88,
+ .start = evt2irq(0xd00),
+ .end = evt2irq(0xd00),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
};
@@ -558,20 +558,20 @@ static struct resource sh7757_dmae2_resources[] = {
},
{
.name = "error_irq",
- .start = 323,
- .end = 323,
+ .start = evt2irq(0x2a60),
+ .end = evt2irq(0x2a60),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 12 to 16 */
- .start = 272,
- .end = 276,
+ .start = evt2irq(0x2400),
+ .end = evt2irq(0x2480),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channel 17 */
- .start = 279,
- .end = 279,
+ .start = evt2irq(0x24e0),
+ .end = evt2irq(0x24e0),
.flags = IORESOURCE_IRQ,
},
};
@@ -592,20 +592,20 @@ static struct resource sh7757_dmae3_resources[] = {
},
{
.name = "error_irq",
- .start = 324,
- .end = 324,
+ .start = evt2irq(0x2a80),
+ .end = evt2irq(0x2a80),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 18 to 22 */
- .start = 280,
- .end = 284,
+ .start = evt2irq(0x2500),
+ .end = evt2irq(0x2580),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channel 23 */
- .start = 288,
- .end = 288,
+ .start = evt2irq(0x2600),
+ .end = evt2irq(0x2600),
.flags = IORESOURCE_IRQ,
},
};
@@ -668,7 +668,7 @@ static struct resource spi1_resources[] = {
.flags = IORESOURCE_MEM | IORESOURCE_MEM_8BIT,
},
{
- .start = 54,
+ .start = evt2irq(0x8c0),
.flags = IORESOURCE_IRQ,
},
};
@@ -687,7 +687,7 @@ static struct resource rspi_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- .start = 220,
+ .start = evt2irq(0x1d80),
.flags = IORESOURCE_IRQ,
},
};
@@ -706,8 +706,8 @@ static struct resource usb_ehci_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 57,
- .end = 57,
+ .start = evt2irq(0x920),
+ .end = evt2irq(0x920),
.flags = IORESOURCE_IRQ,
},
};
@@ -730,8 +730,8 @@ static struct resource usb_ohci_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 57,
- .end = 57,
+ .start = evt2irq(0x920),
+ .end = evt2irq(0x920),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
index 00113515f233..bd0a8fbe610f 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <linux/io.h>
#include <linux/serial_sci.h>
@@ -22,7 +23,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 40, 40, 40, 40 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x700)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -40,7 +41,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 76, 76, 76, 76 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xb80)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -58,7 +59,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 104, 104, 104, 104 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xf00)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -78,7 +79,7 @@ static struct resource rtc_resources[] = {
},
[1] = {
/* Shared Period/Carry/Alarm IRQ */
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -97,13 +98,14 @@ static struct resource usb_ohci_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 83,
- .end = 83,
+ .start = evt2irq(0xc60),
+ .end = evt2irq(0xc60),
.flags = IORESOURCE_IRQ,
},
};
static u64 usb_ohci_dma_mask = 0xffffffffUL;
+
static struct platform_device usb_ohci_device = {
.name = "sh_ohci",
.id = -1,
@@ -122,8 +124,8 @@ static struct resource usbf_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 84,
- .end = 84,
+ .start = evt2irq(0xc80),
+ .end = evt2irq(0xc80),
.flags = IORESOURCE_IRQ,
},
};
@@ -152,7 +154,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 28,
+ .start = evt2irq(0x580),
.flags = IORESOURCE_IRQ,
},
};
@@ -180,7 +182,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 29,
+ .start = evt2irq(0x5a0),
.flags = IORESOURCE_IRQ,
},
};
@@ -207,7 +209,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 30,
+ .start = evt2irq(0x5c0),
.flags = IORESOURCE_IRQ,
},
};
@@ -234,7 +236,7 @@ static struct resource tmu3_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 96,
+ .start = evt2irq(0xe00),
.flags = IORESOURCE_IRQ,
},
};
@@ -261,7 +263,7 @@ static struct resource tmu4_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 97,
+ .start = evt2irq(0xe20),
.flags = IORESOURCE_IRQ,
},
};
@@ -288,7 +290,7 @@ static struct resource tmu5_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 98,
+ .start = evt2irq(0xe40),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
index 2c6aa22cf5f6..256ea7a45164 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
@@ -12,6 +12,7 @@
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <linux/io.h>
static struct plat_sci_port scif0_platform_data = {
@@ -20,7 +21,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 61, 61, 61, 61 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x9a0)),
};
static struct platform_device scif0_device = {
@@ -37,7 +38,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 62, 62, 62, 62 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x9c0)),
};
static struct platform_device scif1_device = {
@@ -54,7 +55,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 63, 63, 63, 63 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x9e0)),
};
static struct platform_device scif2_device = {
@@ -71,7 +72,7 @@ static struct plat_sci_port scif3_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 64, 64, 64, 64 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xa00)),
};
static struct platform_device scif3_device = {
@@ -88,7 +89,7 @@ static struct plat_sci_port scif4_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 65, 65, 65, 65 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xa20)),
};
static struct platform_device scif4_device = {
@@ -105,7 +106,7 @@ static struct plat_sci_port scif5_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 66, 66, 66, 66 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xa40)),
};
static struct platform_device scif5_device = {
@@ -122,7 +123,7 @@ static struct plat_sci_port scif6_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 67, 67, 67, 67 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xa60)),
};
static struct platform_device scif6_device = {
@@ -139,7 +140,7 @@ static struct plat_sci_port scif7_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 68, 68, 68, 68 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xa80)),
};
static struct platform_device scif7_device = {
@@ -156,7 +157,7 @@ static struct plat_sci_port scif8_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 69, 69, 69, 69 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xaa0)),
};
static struct platform_device scif8_device = {
@@ -173,7 +174,7 @@ static struct plat_sci_port scif9_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 70, 70, 70, 70 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xac0)),
};
static struct platform_device scif9_device = {
@@ -197,7 +198,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -225,7 +226,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -252,7 +253,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
@@ -279,7 +280,7 @@ static struct resource tmu3_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 19,
+ .start = evt2irq(0x460),
.flags = IORESOURCE_IRQ,
},
};
@@ -306,7 +307,7 @@ static struct resource tmu4_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -333,7 +334,7 @@ static struct resource tmu5_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 21,
+ .start = evt2irq(0x4a0),
.flags = IORESOURCE_IRQ,
},
};
@@ -360,7 +361,7 @@ static struct resource tmu6_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 22,
+ .start = evt2irq(0x4c0),
.flags = IORESOURCE_IRQ,
},
};
@@ -387,7 +388,7 @@ static struct resource tmu7_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 23,
+ .start = evt2irq(0x4e0),
.flags = IORESOURCE_IRQ,
},
};
@@ -414,7 +415,7 @@ static struct resource tmu8_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 24,
+ .start = evt2irq(0x500),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index d431b0052d0c..de45b704687a 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -14,6 +14,7 @@
#include <linux/serial_sci.h>
#include <linux/sh_dma.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <cpu/dma-register.h>
static struct plat_sci_port scif0_platform_data = {
@@ -22,7 +23,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 40, 40, 40, 40 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x700)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -40,7 +41,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 76, 76, 76, 76 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0xb80)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -65,7 +66,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 28,
+ .start = evt2irq(0x580),
.flags = IORESOURCE_IRQ,
},
};
@@ -93,7 +94,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 29,
+ .start = evt2irq(0x5a0),
.flags = IORESOURCE_IRQ,
},
};
@@ -120,7 +121,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 30,
+ .start = evt2irq(0x5c0),
.flags = IORESOURCE_IRQ,
},
};
@@ -147,7 +148,7 @@ static struct resource tmu3_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 96,
+ .start = evt2irq(0xe00),
.flags = IORESOURCE_IRQ,
},
};
@@ -174,7 +175,7 @@ static struct resource tmu4_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 97,
+ .start = evt2irq(0xe20),
.flags = IORESOURCE_IRQ,
},
};
@@ -201,7 +202,7 @@ static struct resource tmu5_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 98,
+ .start = evt2irq(0xe40),
.flags = IORESOURCE_IRQ,
},
};
@@ -224,7 +225,7 @@ static struct resource rtc_resources[] = {
},
[1] = {
/* Shared Period/Carry/Alarm IRQ */
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -321,10 +322,13 @@ static struct resource sh7780_dmae0_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- /* Real DMA error IRQ is 38, and channel IRQs are 34-37, 44-45 */
+ /*
+ * Real DMA error vector is 0x6c0, and channel
+ * vectors are 0x640-0x6a0, 0x780-0x7a0
+ */
.name = "error_irq",
- .start = 34,
- .end = 34,
+ .start = evt2irq(0x640),
+ .end = evt2irq(0x640),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
};
@@ -338,10 +342,13 @@ static struct resource sh7780_dmae1_resources[] = {
},
/* DMAC1 has no DMARS */
{
- /* Real DMA error IRQ is 38, and channel IRQs are 46-47, 92-95 */
+ /*
+ * Real DMA error vector is 0x6c0, and channel
+ * vectors are 0x7c0-0x7e0, 0xd80-0xde0
+ */
.name = "error_irq",
- .start = 46,
- .end = 46,
+ .start = evt2irq(0x7c0),
+ .end = evt2irq(0x7c0),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index 81588ef15a6c..0968ecb962e6 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -15,6 +15,7 @@
#include <linux/mm.h>
#include <linux/sh_dma.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <asm/mmzone.h>
#include <cpu/dma-register.h>
@@ -24,7 +25,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 40, 40, 40, 40 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x700)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -42,7 +43,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 44, 44, 44, 44 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x780)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -60,7 +61,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 60, 60, 60, 60 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x980)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -78,7 +79,7 @@ static struct plat_sci_port scif3_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 61, 61, 61, 61 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x9a0)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -96,7 +97,7 @@ static struct plat_sci_port scif4_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 62, 62, 62, 62 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x9c0)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -114,7 +115,7 @@ static struct plat_sci_port scif5_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 63, 63, 63, 63 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x9e0)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -139,7 +140,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 28,
+ .start = evt2irq(0x580),
.flags = IORESOURCE_IRQ,
},
};
@@ -167,7 +168,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 29,
+ .start = evt2irq(0x5a0),
.flags = IORESOURCE_IRQ,
},
};
@@ -194,7 +195,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 30,
+ .start = evt2irq(0x5c0),
.flags = IORESOURCE_IRQ,
},
};
@@ -221,7 +222,7 @@ static struct resource tmu3_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 96,
+ .start = evt2irq(0xe00),
.flags = IORESOURCE_IRQ,
},
};
@@ -248,7 +249,7 @@ static struct resource tmu4_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 97,
+ .start = evt2irq(0xe20),
.flags = IORESOURCE_IRQ,
},
};
@@ -275,7 +276,7 @@ static struct resource tmu5_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 98,
+ .start = evt2irq(0xe40),
.flags = IORESOURCE_IRQ,
},
};
@@ -375,10 +376,13 @@ static struct resource sh7785_dmae0_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- /* Real DMA error IRQ is 39, and channel IRQs are 33-38 */
+ /*
+ * Real DMA error vector is 0x6e0, and channel
+ * vectors are 0x620-0x6c0
+ */
.name = "error_irq",
- .start = 33,
- .end = 33,
+ .start = evt2irq(0x620),
+ .end = evt2irq(0x620),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
};
@@ -392,10 +396,13 @@ static struct resource sh7785_dmae1_resources[] = {
},
/* DMAC1 has no DMARS */
{
- /* Real DMA error IRQ is 58, and channel IRQs are 52-57 */
+ /*
+ * Real DMA error vector is 0x940, and channel
+ * vectors are 0x880-0x920
+ */
.name = "error_irq",
- .start = 52,
- .end = 52,
+ .start = evt2irq(0x880),
+ .end = evt2irq(0x880),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
index 599022d73b28..2e6952f87848 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
@@ -32,7 +32,10 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 40, 41, 43, 42 },
+ .irqs = { evt2irq(0x700),
+ evt2irq(0x720),
+ evt2irq(0x760),
+ evt2irq(0x740) },
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -53,7 +56,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 44, 44, 44, 44 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x780)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -71,7 +74,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 50, 50, 50, 50 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x840)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -89,7 +92,7 @@ static struct plat_sci_port scif3_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 51, 51, 51, 51 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x860)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -107,7 +110,7 @@ static struct plat_sci_port scif4_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 52, 52, 52, 52 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x880)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -125,7 +128,7 @@ static struct plat_sci_port scif5_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_1,
.type = PORT_SCIF,
- .irqs = { 53, 53, 53, 53 },
+ .irqs = SCIx_IRQ_MUXED(evt2irq(0x8a0)),
.regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
};
@@ -150,7 +153,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -178,7 +181,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -205,7 +208,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
@@ -232,7 +235,7 @@ static struct resource tmu3_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -259,7 +262,7 @@ static struct resource tmu4_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 21,
+ .start = evt2irq(0x4a0),
.flags = IORESOURCE_IRQ,
},
};
@@ -286,7 +289,7 @@ static struct resource tmu5_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 22,
+ .start = evt2irq(0x4c0),
.flags = IORESOURCE_IRQ,
},
};
@@ -313,7 +316,7 @@ static struct resource tmu6_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 45,
+ .start = evt2irq(0x7a0),
.flags = IORESOURCE_IRQ,
},
};
@@ -340,7 +343,7 @@ static struct resource tmu7_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 45,
+ .start = evt2irq(0x7a0),
.flags = IORESOURCE_IRQ,
},
};
@@ -367,7 +370,7 @@ static struct resource tmu8_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 45,
+ .start = evt2irq(0x7a0),
.flags = IORESOURCE_IRQ,
},
};
@@ -394,7 +397,7 @@ static struct resource tmu9_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 46,
+ .start = evt2irq(0x7c0),
.flags = IORESOURCE_IRQ,
},
};
@@ -421,7 +424,7 @@ static struct resource tmu10_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 46,
+ .start = evt2irq(0x7c0),
.flags = IORESOURCE_IRQ,
},
};
@@ -448,7 +451,7 @@ static struct resource tmu11_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 46,
+ .start = evt2irq(0x7c0),
.flags = IORESOURCE_IRQ,
},
};
@@ -550,8 +553,8 @@ static struct resource usb_ehci_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 77,
- .end = 77,
+ .start = evt2irq(0xba0),
+ .end = evt2irq(0xba0),
.flags = IORESOURCE_IRQ,
},
};
@@ -574,8 +577,8 @@ static struct resource usb_ohci_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 77,
- .end = 77,
+ .start = evt2irq(0xba0),
+ .end = evt2irq(0xba0),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
index bb208806dc1a..688f7ed1bab1 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
@@ -14,6 +14,7 @@
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <cpu/shx3.h>
#include <asm/mmzone.h>
@@ -32,7 +33,10 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 40, 41, 43, 42 },
+ .irqs = { evt2irq(0x700),
+ evt2irq(0x720),
+ evt2irq(0x760),
+ evt2irq(0x740) },
};
static struct platform_device scif0_device = {
@@ -49,7 +53,10 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 44, 45, 47, 46 },
+ .irqs = { evt2irq(0x780),
+ evt2irq(0x7a0),
+ evt2irq(0x7e0),
+ evt2irq(0x7c0) },
};
static struct platform_device scif1_device = {
@@ -66,7 +73,10 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = { 52, 53, 55, 54 },
+ .irqs = { evt2irq(0x880),
+ evt2irq(0x8a0),
+ evt2irq(0x8e0),
+ evt2irq(0x8c0) },
};
static struct platform_device scif2_device = {
@@ -90,7 +100,7 @@ static struct resource tmu0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 16,
+ .start = evt2irq(0x400),
.flags = IORESOURCE_IRQ,
},
};
@@ -118,7 +128,7 @@ static struct resource tmu1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 17,
+ .start = evt2irq(0x420),
.flags = IORESOURCE_IRQ,
},
};
@@ -145,7 +155,7 @@ static struct resource tmu2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 18,
+ .start = evt2irq(0x440),
.flags = IORESOURCE_IRQ,
},
};
@@ -172,7 +182,7 @@ static struct resource tmu3_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 19,
+ .start = evt2irq(0x460),
.flags = IORESOURCE_IRQ,
},
};
@@ -199,7 +209,7 @@ static struct resource tmu4_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -226,7 +236,7 @@ static struct resource tmu5_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 21,
+ .start = evt2irq(0x4a0),
.flags = IORESOURCE_IRQ,
},
};
@@ -484,9 +494,6 @@ void __init plat_irq_setup_pins(int mode)
void __init plat_irq_setup(void)
{
- reserve_intc_vectors(vectors_irq, ARRAY_SIZE(vectors_irq));
- reserve_intc_vectors(vectors_irl, ARRAY_SIZE(vectors_irl));
-
register_intc_controller(&intc_desc);
}
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S
index 6b80295dd7a4..ff1f0e6e9bec 100644
--- a/arch/sh/kernel/cpu/sh5/entry.S
+++ b/arch/sh/kernel/cpu/sh5/entry.S
@@ -335,7 +335,7 @@ tlb_miss:
/* If the fast path handler fixed the fault, just drop through quickly
to the restore code right away to return to the excepting context.
*/
- beqi/u r2, 0, tr1
+ bnei/u r2, 0, tr1
fast_tlb_miss_restore:
ld.q SP, SAVED_TR0, r2
@@ -1079,9 +1079,8 @@ restore_all:
*
* Kernel TLB fault handlers will get a slightly different interface.
* (r2) struct pt_regs *, original register's frame pointer
- * (r3) writeaccess, whether it's a store fault as opposed to load fault
- * (r4) execaccess, whether it's a ITLB fault as opposed to DTLB fault
- * (r5) Effective Address of fault
+ * (r3) page fault error code (see asm/thread_info.h)
+ * (r4) Effective Address of fault
* (LINK) return address
* (SP) = r2
*
@@ -1092,26 +1091,25 @@ restore_all:
tlb_miss_load:
or SP, ZERO, r2
or ZERO, ZERO, r3 /* Read */
- or ZERO, ZERO, r4 /* Data */
- getcon TEA, r5
+ getcon TEA, r4
pta call_do_page_fault, tr0
beq ZERO, ZERO, tr0
tlb_miss_store:
or SP, ZERO, r2
- movi 1, r3 /* Write */
- or ZERO, ZERO, r4 /* Data */
- getcon TEA, r5
+ movi FAULT_CODE_WRITE, r3 /* Write */
+ getcon TEA, r4
pta call_do_page_fault, tr0
beq ZERO, ZERO, tr0
itlb_miss_or_IRQ:
pta its_IRQ, tr0
beqi/u r4, EVENT_INTERRUPT, tr0
+
+ /* ITLB miss */
or SP, ZERO, r2
- or ZERO, ZERO, r3 /* Read */
- movi 1, r4 /* Text */
- getcon TEA, r5
+ movi FAULT_CODE_ITLB, r3
+ getcon TEA, r4
/* Fall through */
call_do_page_fault:
diff --git a/arch/sh/kernel/cpu/sh5/fpu.c b/arch/sh/kernel/cpu/sh5/fpu.c
index 4b3bb35e99f3..9f8713aa7184 100644
--- a/arch/sh/kernel/cpu/sh5/fpu.c
+++ b/arch/sh/kernel/cpu/sh5/fpu.c
@@ -107,8 +107,5 @@ asmlinkage void do_fpu_error(unsigned long ex, struct pt_regs *regs)
regs->pc += 4;
- tsk->thread.trap_no = 11;
- tsk->thread.error_code = 0;
-
force_sig(SIGFPE, tsk);
}
diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c
index ee226e20c20c..0c910163caa3 100644
--- a/arch/sh/kernel/idle.c
+++ b/arch/sh/kernel/idle.c
@@ -132,10 +132,6 @@ void __init select_idle_routine(void)
pm_idle = poll_idle;
}
-static void do_nothing(void *unused)
-{
-}
-
void stop_this_cpu(void *unused)
{
local_irq_disable();
@@ -144,19 +140,3 @@ void stop_this_cpu(void *unused)
for (;;)
cpu_sleep();
}
-
-/*
- * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
- * pm_idle and update to new pm_idle value. Required while changing pm_idle
- * handler on SMP systems.
- *
- * Caller must have changed pm_idle to the new value before the call. Old
- * pm_idle value will not be used by any CPU after the return of this function.
- */
-void cpu_idle_wait(void)
-{
- smp_mb();
- /* kick all the CPUs so that they exit out of pm_idle */
- smp_call_function(do_nothing, NULL, 1);
-}
-EXPORT_SYMBOL_GPL(cpu_idle_wait);
diff --git a/arch/sh/kernel/init_task.c b/arch/sh/kernel/init_task.c
deleted file mode 100644
index 11f2ea556a6b..000000000000
--- a/arch/sh/kernel/init_task.c
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init_task.h>
-#include <linux/mqueue.h>
-#include <linux/fs.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct pt_regs fake_swapper_regs;
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is 8192-byte aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index a3ee91971129..dadce735f746 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -234,8 +234,10 @@ void __init init_IRQ(void)
#ifdef CONFIG_SPARSE_IRQ
int __init arch_probe_nr_irqs(void)
{
- nr_irqs = sh_mv.mv_nr_irqs;
- return NR_IRQS_LEGACY;
+ /*
+ * No pre-allocated IRQs.
+ */
+ return 0;
}
#endif
diff --git a/arch/sh/kernel/kgdb.c b/arch/sh/kernel/kgdb.c
index b117781bfea2..38b313909ac9 100644
--- a/arch/sh/kernel/kgdb.c
+++ b/arch/sh/kernel/kgdb.c
@@ -1,7 +1,7 @@
/*
* SuperH KGDB support
*
- * Copyright (C) 2008 - 2009 Paul Mundt
+ * Copyright (C) 2008 - 2012 Paul Mundt
*
* Single stepping taken from the old stub by Henry Bell and Jeremy Siegel.
*
@@ -164,42 +164,89 @@ static void undo_single_step(struct pt_regs *linux_regs)
stepped_opcode = 0;
}
-void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-{
- int i;
+struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
+ { "r0", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[0]) },
+ { "r1", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[1]) },
+ { "r2", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[2]) },
+ { "r3", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[3]) },
+ { "r4", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[4]) },
+ { "r5", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[5]) },
+ { "r6", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[6]) },
+ { "r7", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[7]) },
+ { "r8", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[8]) },
+ { "r9", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[9]) },
+ { "r10", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[10]) },
+ { "r11", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[11]) },
+ { "r12", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[12]) },
+ { "r13", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[13]) },
+ { "r14", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[14]) },
+ { "r15", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[15]) },
+ { "pc", GDB_SIZEOF_REG, offsetof(struct pt_regs, pc) },
+ { "pr", GDB_SIZEOF_REG, offsetof(struct pt_regs, pr) },
+ { "sr", GDB_SIZEOF_REG, offsetof(struct pt_regs, sr) },
+ { "gbr", GDB_SIZEOF_REG, offsetof(struct pt_regs, gbr) },
+ { "mach", GDB_SIZEOF_REG, offsetof(struct pt_regs, mach) },
+ { "macl", GDB_SIZEOF_REG, offsetof(struct pt_regs, macl) },
+ { "vbr", GDB_SIZEOF_REG, -1 },
+};
- for (i = 0; i < 16; i++)
- gdb_regs[GDB_R0 + i] = regs->regs[i];
+int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
+{
+ if (regno < 0 || regno >= DBG_MAX_REG_NUM)
+ return -EINVAL;
- gdb_regs[GDB_PC] = regs->pc;
- gdb_regs[GDB_PR] = regs->pr;
- gdb_regs[GDB_SR] = regs->sr;
- gdb_regs[GDB_GBR] = regs->gbr;
- gdb_regs[GDB_MACH] = regs->mach;
- gdb_regs[GDB_MACL] = regs->macl;
+ if (dbg_reg_def[regno].offset != -1)
+ memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
+ dbg_reg_def[regno].size);
- __asm__ __volatile__ ("stc vbr, %0" : "=r" (gdb_regs[GDB_VBR]));
+ return 0;
}
-void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
{
- int i;
+ if (regno >= DBG_MAX_REG_NUM || regno < 0)
+ return NULL;
- for (i = 0; i < 16; i++)
- regs->regs[GDB_R0 + i] = gdb_regs[GDB_R0 + i];
+ if (dbg_reg_def[regno].size != -1)
+ memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
+ dbg_reg_def[regno].size);
+
+ switch (regno) {
+ case GDB_VBR:
+ __asm__ __volatile__ ("stc vbr, %0" : "=r" (mem));
+ break;
+ }
- regs->pc = gdb_regs[GDB_PC];
- regs->pr = gdb_regs[GDB_PR];
- regs->sr = gdb_regs[GDB_SR];
- regs->gbr = gdb_regs[GDB_GBR];
- regs->mach = gdb_regs[GDB_MACH];
- regs->macl = gdb_regs[GDB_MACL];
+ return dbg_reg_def[regno].name;
}
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
{
+ struct pt_regs *thread_regs = task_pt_regs(p);
+ int reg;
+
+ /* Initialize to zero */
+ for (reg = 0; reg < DBG_MAX_REG_NUM; reg++)
+ gdb_regs[reg] = 0;
+
+ /*
+ * Copy out GP regs 8 to 14.
+ *
+ * switch_to() relies on SR.RB toggling, so regs 0->7 are banked
+ * and need privileged instructions to get to. The r15 value we
+ * fetch from the thread info directly.
+ */
+ for (reg = GDB_R8; reg < GDB_R15; reg++)
+ gdb_regs[reg] = thread_regs->regs[reg];
+
gdb_regs[GDB_R15] = p->thread.sp;
gdb_regs[GDB_PC] = p->thread.pc;
+
+ /*
+ * Additional registers we have context for
+ */
+ gdb_regs[GDB_PR] = thread_regs->pr;
+ gdb_regs[GDB_GBR] = thread_regs->gbr;
}
int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
@@ -264,6 +311,18 @@ BUILD_TRAP_HANDLER(singlestep)
local_irq_restore(flags);
}
+static void kgdb_call_nmi_hook(void *ignored)
+{
+ kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
+}
+
+void kgdb_roundup_cpus(unsigned long flags)
+{
+ local_irq_enable();
+ smp_call_function(kgdb_call_nmi_hook, NULL, 0);
+ local_irq_disable();
+}
+
static int __kgdb_notify(struct die_args *args, unsigned long cmd)
{
int ret;
diff --git a/arch/sh/kernel/machvec.c b/arch/sh/kernel/machvec.c
index 3d722e49db08..ec05f491c347 100644
--- a/arch/sh/kernel/machvec.c
+++ b/arch/sh/kernel/machvec.c
@@ -121,7 +121,4 @@ void __init sh_mv_setup(void)
mv_set(irq_demux);
mv_set(mode_pins);
mv_set(mem_init);
-
- if (!sh_mv.mv_nr_irqs)
- sh_mv.mv_nr_irqs = NR_IRQS;
}
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 325f98b1736d..9b7a459a4613 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -2,12 +2,26 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sched.h>
+#include <linux/export.h>
+#include <linux/stackprotector.h>
struct kmem_cache *task_xstate_cachep = NULL;
unsigned int xstate_size;
+#ifdef CONFIG_CC_STACKPROTECTOR
+unsigned long __stack_chk_guard __read_mostly;
+EXPORT_SYMBOL(__stack_chk_guard);
+#endif
+
+/*
+ * this gets called so that we can store lazy state into memory and copy the
+ * current task into the new thread.
+ */
int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
+#ifdef CONFIG_SUPERH32
+ unlazy_fpu(src, task_pt_regs(src));
+#endif
*dst = *src;
if (src->thread.xstate) {
@@ -29,52 +43,10 @@ void free_thread_xstate(struct task_struct *tsk)
}
}
-#if THREAD_SHIFT < PAGE_SHIFT
-static struct kmem_cache *thread_info_cache;
-
-struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
-{
- struct thread_info *ti;
-#ifdef CONFIG_DEBUG_STACK_USAGE
- gfp_t mask = GFP_KERNEL | __GFP_ZERO;
-#else
- gfp_t mask = GFP_KERNEL;
-#endif
-
- ti = kmem_cache_alloc_node(thread_info_cache, mask, node);
- return ti;
-}
-
-void free_thread_info(struct thread_info *ti)
-{
- free_thread_xstate(ti->task);
- kmem_cache_free(thread_info_cache, ti);
-}
-
-void thread_info_cache_init(void)
-{
- thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
- THREAD_SIZE, SLAB_PANIC, NULL);
-}
-#else
-struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
-{
-#ifdef CONFIG_DEBUG_STACK_USAGE
- gfp_t mask = GFP_KERNEL | __GFP_ZERO;
-#else
- gfp_t mask = GFP_KERNEL;
-#endif
- struct page *page = alloc_pages_node(node, mask, THREAD_SIZE_ORDER);
-
- return page ? page_address(page) : NULL;
-}
-
-void free_thread_info(struct thread_info *ti)
+void arch_release_task_struct(struct task_struct *tsk)
{
- free_thread_xstate(ti->task);
- free_pages((unsigned long)ti, THREAD_SIZE_ORDER);
+ free_thread_xstate(tsk);
}
-#endif /* THREAD_SHIFT < PAGE_SHIFT */
void arch_task_cache_init(void)
{
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index 94273aaf78c1..59521e8a164d 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -22,6 +22,7 @@
#include <linux/ftrace.h>
#include <linux/hw_breakpoint.h>
#include <linux/prefetch.h>
+#include <linux/stackprotector.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
#include <asm/fpu.h>
@@ -155,15 +156,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
}
EXPORT_SYMBOL(dump_fpu);
-/*
- * This gets called before we allocate a new thread and copy
- * the current task into it.
- */
-void prepare_to_copy(struct task_struct *tsk)
-{
- unlazy_fpu(tsk, task_pt_regs(tsk));
-}
-
asmlinkage void ret_from_fork(void);
int copy_thread(unsigned long clone_flags, unsigned long usp,
@@ -220,6 +212,10 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
{
struct thread_struct *next_t = &next->thread;
+#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
+ __stack_chk_guard = next->stack_canary;
+#endif
+
unlazy_fpu(prev, task_pt_regs(prev));
/* we're going to use this soon, after a few expensive things */
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index 9698671444e6..81f999a672f6 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -503,7 +503,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
{
long ret = 0;
- secure_computing(regs->regs[0]);
+ secure_computing_strict(regs->regs[0]);
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
tracehook_report_syscall_entry(regs))
diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c
index bc81e07dc098..af90339dadcd 100644
--- a/arch/sh/kernel/ptrace_64.c
+++ b/arch/sh/kernel/ptrace_64.c
@@ -522,7 +522,7 @@ asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs)
{
long long ret = 0;
- secure_computing(regs->regs[9]);
+ secure_computing_strict(regs->regs[9]);
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
tracehook_report_syscall_entry(regs))
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index eaebdf6a5c77..b86e9ca79455 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -220,22 +220,10 @@ extern struct {
void *thread_info;
} stack_start;
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tsk)
{
- struct task_struct *tsk;
unsigned long timeout;
- tsk = cpu_data[cpu].idle;
- if (!tsk) {
- tsk = fork_idle(cpu);
- if (IS_ERR(tsk)) {
- pr_err("Failed forking idle task for cpu %d\n", cpu);
- return PTR_ERR(tsk);
- }
-
- cpu_data[cpu].idle = tsk;
- }
-
per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
/* Fill in data in head.S for secondary cpus */
diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c
index 6c0486094e48..8dae93ed8aff 100644
--- a/arch/sh/kernel/traps_64.c
+++ b/arch/sh/kernel/traps_64.c
@@ -283,8 +283,6 @@ static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_na
unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk)
{
show_excp_regs(fn_name, trapnr, signr, regs);
- tsk->thread.error_code = error_code;
- tsk->thread.trap_no = trapnr;
if (user_mode(regs))
force_sig(signr, tsk);
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index 2228c8cee4d6..cee6b9999d86 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -15,8 +15,8 @@ cacheops-$(CONFIG_CPU_SHX3) += cache-shx3.o
obj-y += $(cacheops-y)
mmu-y := nommu.o extable_32.o
-mmu-$(CONFIG_MMU) := extable_$(BITS).o fault_$(BITS).o gup.o \
- ioremap.o kmap.o pgtable.o tlbflush_$(BITS).o
+mmu-$(CONFIG_MMU) := extable_$(BITS).o fault.o gup.o ioremap.o kmap.o \
+ pgtable.o tlbex_$(BITS).o tlbflush_$(BITS).o
obj-y += $(mmu-y)
@@ -44,7 +44,7 @@ obj-$(CONFIG_HAVE_SRAM_POOL) += sram.o
GCOV_PROFILE_pmb.o := n
-# Special flags for fault_64.o. This puts restrictions on the number of
+# Special flags for tlbex_64.o. This puts restrictions on the number of
# caller-save registers that the compiler can target when building this file.
# This is required because the code is called from a context in entry.S where
# very few registers have been saved in the exception handler (for speed
@@ -59,7 +59,7 @@ GCOV_PROFILE_pmb.o := n
# The resources not listed below are callee save, i.e. the compiler is free to
# use any of them and will spill them to the stack itself.
-CFLAGS_fault_64.o += -ffixed-r7 \
+CFLAGS_tlbex_64.o += -ffixed-r7 \
-ffixed-r8 -ffixed-r9 -ffixed-r10 -ffixed-r11 -ffixed-r12 \
-ffixed-r13 -ffixed-r14 -ffixed-r16 -ffixed-r17 -ffixed-r19 \
-ffixed-r20 -ffixed-r21 -ffixed-r22 -ffixed-r23 \
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
new file mode 100644
index 000000000000..1fc25d85e515
--- /dev/null
+++ b/arch/sh/mm/fault.c
@@ -0,0 +1,514 @@
+/*
+ * Page fault handler for SH with an MMU.
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2003 - 2012 Paul Mundt
+ *
+ * Based on linux/arch/i386/mm/fault.c:
+ * Copyright (C) 1995 Linus Torvalds
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/hardirq.h>
+#include <linux/kprobes.h>
+#include <linux/perf_event.h>
+#include <linux/kdebug.h>
+#include <asm/io_trapped.h>
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+#include <asm/traps.h>
+
+static inline int notify_page_fault(struct pt_regs *regs, int trap)
+{
+ int ret = 0;
+
+ if (kprobes_built_in() && !user_mode(regs)) {
+ preempt_disable();
+ if (kprobe_running() && kprobe_fault_handler(regs, trap))
+ ret = 1;
+ preempt_enable();
+ }
+
+ return ret;
+}
+
+static void
+force_sig_info_fault(int si_signo, int si_code, unsigned long address,
+ struct task_struct *tsk)
+{
+ siginfo_t info;
+
+ info.si_signo = si_signo;
+ info.si_errno = 0;
+ info.si_code = si_code;
+ info.si_addr = (void __user *)address;
+
+ force_sig_info(si_signo, &info, tsk);
+}
+
+/*
+ * This is useful to dump out the page tables associated with
+ * 'addr' in mm 'mm'.
+ */
+static void show_pte(struct mm_struct *mm, unsigned long addr)
+{
+ pgd_t *pgd;
+
+ if (mm)
+ pgd = mm->pgd;
+ else
+ pgd = get_TTB();
+
+ printk(KERN_ALERT "pgd = %p\n", pgd);
+ pgd += pgd_index(addr);
+ printk(KERN_ALERT "[%08lx] *pgd=%0*Lx", addr,
+ (u32)(sizeof(*pgd) * 2), (u64)pgd_val(*pgd));
+
+ do {
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ if (pgd_none(*pgd))
+ break;
+
+ if (pgd_bad(*pgd)) {
+ printk("(bad)");
+ break;
+ }
+
+ pud = pud_offset(pgd, addr);
+ if (PTRS_PER_PUD != 1)
+ printk(", *pud=%0*Lx", (u32)(sizeof(*pud) * 2),
+ (u64)pud_val(*pud));
+
+ if (pud_none(*pud))
+ break;
+
+ if (pud_bad(*pud)) {
+ printk("(bad)");
+ break;
+ }
+
+ pmd = pmd_offset(pud, addr);
+ if (PTRS_PER_PMD != 1)
+ printk(", *pmd=%0*Lx", (u32)(sizeof(*pmd) * 2),
+ (u64)pmd_val(*pmd));
+
+ if (pmd_none(*pmd))
+ break;
+
+ if (pmd_bad(*pmd)) {
+ printk("(bad)");
+ break;
+ }
+
+ /* We must not map this if we have highmem enabled */
+ if (PageHighMem(pfn_to_page(pmd_val(*pmd) >> PAGE_SHIFT)))
+ break;
+
+ pte = pte_offset_kernel(pmd, addr);
+ printk(", *pte=%0*Lx", (u32)(sizeof(*pte) * 2),
+ (u64)pte_val(*pte));
+ } while (0);
+
+ printk("\n");
+}
+
+static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
+{
+ unsigned index = pgd_index(address);
+ pgd_t *pgd_k;
+ pud_t *pud, *pud_k;
+ pmd_t *pmd, *pmd_k;
+
+ pgd += index;
+ pgd_k = init_mm.pgd + index;
+
+ if (!pgd_present(*pgd_k))
+ return NULL;
+
+ pud = pud_offset(pgd, address);
+ pud_k = pud_offset(pgd_k, address);
+ if (!pud_present(*pud_k))
+ return NULL;
+
+ if (!pud_present(*pud))
+ set_pud(pud, *pud_k);
+
+ pmd = pmd_offset(pud, address);
+ pmd_k = pmd_offset(pud_k, address);
+ if (!pmd_present(*pmd_k))
+ return NULL;
+
+ if (!pmd_present(*pmd))
+ set_pmd(pmd, *pmd_k);
+ else {
+ /*
+ * The page tables are fully synchronised so there must
+ * be another reason for the fault. Return NULL here to
+ * signal that we have not taken care of the fault.
+ */
+ BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
+ return NULL;
+ }
+
+ return pmd_k;
+}
+
+#ifdef CONFIG_SH_STORE_QUEUES
+#define __FAULT_ADDR_LIMIT P3_ADDR_MAX
+#else
+#define __FAULT_ADDR_LIMIT VMALLOC_END
+#endif
+
+/*
+ * Handle a fault on the vmalloc or module mapping area
+ */
+static noinline int vmalloc_fault(unsigned long address)
+{
+ pgd_t *pgd_k;
+ pmd_t *pmd_k;
+ pte_t *pte_k;
+
+ /* Make sure we are in vmalloc/module/P3 area: */
+ if (!(address >= VMALLOC_START && address < __FAULT_ADDR_LIMIT))
+ return -1;
+
+ /*
+ * Synchronize this task's top level page-table
+ * with the 'reference' page table.
+ *
+ * Do _not_ use "current" here. We might be inside
+ * an interrupt in the middle of a task switch..
+ */
+ pgd_k = get_TTB();
+ pmd_k = vmalloc_sync_one(pgd_k, address);
+ if (!pmd_k)
+ return -1;
+
+ pte_k = pte_offset_kernel(pmd_k, address);
+ if (!pte_present(*pte_k))
+ return -1;
+
+ return 0;
+}
+
+static void
+show_fault_oops(struct pt_regs *regs, unsigned long address)
+{
+ if (!oops_may_print())
+ return;
+
+ printk(KERN_ALERT "BUG: unable to handle kernel ");
+ if (address < PAGE_SIZE)
+ printk(KERN_CONT "NULL pointer dereference");
+ else
+ printk(KERN_CONT "paging request");
+
+ printk(KERN_CONT " at %08lx\n", address);
+ printk(KERN_ALERT "PC:");
+ printk_address(regs->pc, 1);
+
+ show_pte(NULL, address);
+}
+
+static noinline void
+no_context(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address)
+{
+ /* Are we prepared to handle this kernel fault? */
+ if (fixup_exception(regs))
+ return;
+
+ if (handle_trapped_io(regs, address))
+ return;
+
+ /*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+ bust_spinlocks(1);
+
+ show_fault_oops(regs, address);
+
+ die("Oops", regs, error_code);
+ bust_spinlocks(0);
+ do_exit(SIGKILL);
+}
+
+static void
+__bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address, int si_code)
+{
+ struct task_struct *tsk = current;
+
+ /* User mode accesses just cause a SIGSEGV */
+ if (user_mode(regs)) {
+ /*
+ * It's possible to have interrupts off here:
+ */
+ local_irq_enable();
+
+ force_sig_info_fault(SIGSEGV, si_code, address, tsk);
+
+ return;
+ }
+
+ no_context(regs, error_code, address);
+}
+
+static noinline void
+bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address)
+{
+ __bad_area_nosemaphore(regs, error_code, address, SEGV_MAPERR);
+}
+
+static void
+__bad_area(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address, int si_code)
+{
+ struct mm_struct *mm = current->mm;
+
+ /*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+ up_read(&mm->mmap_sem);
+
+ __bad_area_nosemaphore(regs, error_code, address, si_code);
+}
+
+static noinline void
+bad_area(struct pt_regs *regs, unsigned long error_code, unsigned long address)
+{
+ __bad_area(regs, error_code, address, SEGV_MAPERR);
+}
+
+static noinline void
+bad_area_access_error(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address)
+{
+ __bad_area(regs, error_code, address, SEGV_ACCERR);
+}
+
+static void out_of_memory(void)
+{
+ /*
+ * We ran out of memory, call the OOM killer, and return the userspace
+ * (which will retry the fault, or kill us if we got oom-killed):
+ */
+ up_read(&current->mm->mmap_sem);
+
+ pagefault_out_of_memory();
+}
+
+static void
+do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address)
+{
+ struct task_struct *tsk = current;
+ struct mm_struct *mm = tsk->mm;
+
+ up_read(&mm->mmap_sem);
+
+ /* Kernel mode? Handle exceptions or die: */
+ if (!user_mode(regs))
+ no_context(regs, error_code, address);
+
+ force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
+}
+
+static noinline int
+mm_fault_error(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address, unsigned int fault)
+{
+ /*
+ * Pagefault was interrupted by SIGKILL. We have no reason to
+ * continue pagefault.
+ */
+ if (fatal_signal_pending(current)) {
+ if (!(fault & VM_FAULT_RETRY))
+ up_read(&current->mm->mmap_sem);
+ if (!user_mode(regs))
+ no_context(regs, error_code, address);
+ return 1;
+ }
+
+ if (!(fault & VM_FAULT_ERROR))
+ return 0;
+
+ if (fault & VM_FAULT_OOM) {
+ /* Kernel mode? Handle exceptions or die: */
+ if (!user_mode(regs)) {
+ up_read(&current->mm->mmap_sem);
+ no_context(regs, error_code, address);
+ return 1;
+ }
+
+ out_of_memory();
+ } else {
+ if (fault & VM_FAULT_SIGBUS)
+ do_sigbus(regs, error_code, address);
+ else
+ BUG();
+ }
+
+ return 1;
+}
+
+static inline int access_error(int error_code, struct vm_area_struct *vma)
+{
+ if (error_code & FAULT_CODE_WRITE) {
+ /* write, present and write, not present: */
+ if (unlikely(!(vma->vm_flags & VM_WRITE)))
+ return 1;
+ return 0;
+ }
+
+ /* ITLB miss on NX page */
+ if (unlikely((error_code & FAULT_CODE_ITLB) &&
+ !(vma->vm_flags & VM_EXEC)))
+ return 1;
+
+ /* read, not present: */
+ if (unlikely(!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))))
+ return 1;
+
+ return 0;
+}
+
+static int fault_in_kernel_space(unsigned long address)
+{
+ return address >= TASK_SIZE;
+}
+
+/*
+ * This routine handles page faults. It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ */
+asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
+ unsigned long error_code,
+ unsigned long address)
+{
+ unsigned long vec;
+ struct task_struct *tsk;
+ struct mm_struct *mm;
+ struct vm_area_struct * vma;
+ int fault;
+ int write = error_code & FAULT_CODE_WRITE;
+ unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
+ (write ? FAULT_FLAG_WRITE : 0));
+
+ tsk = current;
+ mm = tsk->mm;
+ vec = lookup_exception_vector();
+
+ /*
+ * We fault-in kernel-space virtual memory on-demand. The
+ * 'reference' page table is init_mm.pgd.
+ *
+ * NOTE! We MUST NOT take any locks for this case. We may
+ * be in an interrupt or a critical region, and should
+ * only copy the information from the master page table,
+ * nothing more.
+ */
+ if (unlikely(fault_in_kernel_space(address))) {
+ if (vmalloc_fault(address) >= 0)
+ return;
+ if (notify_page_fault(regs, vec))
+ return;
+
+ bad_area_nosemaphore(regs, error_code, address);
+ return;
+ }
+
+ if (unlikely(notify_page_fault(regs, vec)))
+ return;
+
+ /* Only enable interrupts if they were on before the fault */
+ if ((regs->sr & SR_IMASK) != SR_IMASK)
+ local_irq_enable();
+
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
+
+ /*
+ * If we're in an interrupt, have no user context or are running
+ * in an atomic region then we must not take the fault:
+ */
+ if (unlikely(in_atomic() || !mm)) {
+ bad_area_nosemaphore(regs, error_code, address);
+ return;
+ }
+
+retry:
+ down_read(&mm->mmap_sem);
+
+ vma = find_vma(mm, address);
+ if (unlikely(!vma)) {
+ bad_area(regs, error_code, address);
+ return;
+ }
+ if (likely(vma->vm_start <= address))
+ goto good_area;
+ if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) {
+ bad_area(regs, error_code, address);
+ return;
+ }
+ if (unlikely(expand_stack(vma, address))) {
+ bad_area(regs, error_code, address);
+ return;
+ }
+
+ /*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+good_area:
+ if (unlikely(access_error(error_code, vma))) {
+ bad_area_access_error(regs, error_code, address);
+ return;
+ }
+
+ set_thread_fault_code(error_code);
+
+ /*
+ * If for any reason at all we couldn't handle the fault,
+ * make sure we exit gracefully rather than endlessly redo
+ * the fault.
+ */
+ fault = handle_mm_fault(mm, vma, address, flags);
+
+ if (unlikely(fault & (VM_FAULT_RETRY | VM_FAULT_ERROR)))
+ if (mm_fault_error(regs, error_code, address, fault))
+ return;
+
+ if (flags & FAULT_FLAG_ALLOW_RETRY) {
+ if (fault & VM_FAULT_MAJOR) {
+ tsk->maj_flt++;
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
+ regs, address);
+ } else {
+ tsk->min_flt++;
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
+ regs, address);
+ }
+ if (fault & VM_FAULT_RETRY) {
+ flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+ /*
+ * No need to up_read(&mm->mmap_sem) as we would
+ * have already released it in __lock_page_or_retry
+ * in mm/filemap.c.
+ */
+ goto retry;
+ }
+ }
+
+ up_read(&mm->mmap_sem);
+}
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c
deleted file mode 100644
index e99b104d967a..000000000000
--- a/arch/sh/mm/fault_32.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Page fault handler for SH with an MMU.
- *
- * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2003 - 2009 Paul Mundt
- *
- * Based on linux/arch/i386/mm/fault.c:
- * Copyright (C) 1995 Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/hardirq.h>
-#include <linux/kprobes.h>
-#include <linux/perf_event.h>
-#include <asm/io_trapped.h>
-#include <asm/mmu_context.h>
-#include <asm/tlbflush.h>
-#include <asm/traps.h>
-
-static inline int notify_page_fault(struct pt_regs *regs, int trap)
-{
- int ret = 0;
-
- if (kprobes_built_in() && !user_mode(regs)) {
- preempt_disable();
- if (kprobe_running() && kprobe_fault_handler(regs, trap))
- ret = 1;
- preempt_enable();
- }
-
- return ret;
-}
-
-static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
-{
- unsigned index = pgd_index(address);
- pgd_t *pgd_k;
- pud_t *pud, *pud_k;
- pmd_t *pmd, *pmd_k;
-
- pgd += index;
- pgd_k = init_mm.pgd + index;
-
- if (!pgd_present(*pgd_k))
- return NULL;
-
- pud = pud_offset(pgd, address);
- pud_k = pud_offset(pgd_k, address);
- if (!pud_present(*pud_k))
- return NULL;
-
- if (!pud_present(*pud))
- set_pud(pud, *pud_k);
-
- pmd = pmd_offset(pud, address);
- pmd_k = pmd_offset(pud_k, address);
- if (!pmd_present(*pmd_k))
- return NULL;
-
- if (!pmd_present(*pmd))
- set_pmd(pmd, *pmd_k);
- else {
- /*
- * The page tables are fully synchronised so there must
- * be another reason for the fault. Return NULL here to
- * signal that we have not taken care of the fault.
- */
- BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
- return NULL;
- }
-
- return pmd_k;
-}
-
-/*
- * Handle a fault on the vmalloc or module mapping area
- */
-static noinline int vmalloc_fault(unsigned long address)
-{
- pgd_t *pgd_k;
- pmd_t *pmd_k;
- pte_t *pte_k;
-
- /* Make sure we are in vmalloc/module/P3 area: */
- if (!(address >= P3SEG && address < P3_ADDR_MAX))
- return -1;
-
- /*
- * Synchronize this task's top level page-table
- * with the 'reference' page table.
- *
- * Do _not_ use "current" here. We might be inside
- * an interrupt in the middle of a task switch..
- */
- pgd_k = get_TTB();
- pmd_k = vmalloc_sync_one(pgd_k, address);
- if (!pmd_k)
- return -1;
-
- pte_k = pte_offset_kernel(pmd_k, address);
- if (!pte_present(*pte_k))
- return -1;
-
- return 0;
-}
-
-static int fault_in_kernel_space(unsigned long address)
-{
- return address >= TASK_SIZE;
-}
-
-/*
- * This routine handles page faults. It determines the address,
- * and the problem, and then passes it off to one of the appropriate
- * routines.
- */
-asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
- unsigned long writeaccess,
- unsigned long address)
-{
- unsigned long vec;
- struct task_struct *tsk;
- struct mm_struct *mm;
- struct vm_area_struct * vma;
- int si_code;
- int fault;
- siginfo_t info;
-
- tsk = current;
- mm = tsk->mm;
- si_code = SEGV_MAPERR;
- vec = lookup_exception_vector();
-
- /*
- * We fault-in kernel-space virtual memory on-demand. The
- * 'reference' page table is init_mm.pgd.
- *
- * NOTE! We MUST NOT take any locks for this case. We may
- * be in an interrupt or a critical region, and should
- * only copy the information from the master page table,
- * nothing more.
- */
- if (unlikely(fault_in_kernel_space(address))) {
- if (vmalloc_fault(address) >= 0)
- return;
- if (notify_page_fault(regs, vec))
- return;
-
- goto bad_area_nosemaphore;
- }
-
- if (unlikely(notify_page_fault(regs, vec)))
- return;
-
- /* Only enable interrupts if they were on before the fault */
- if ((regs->sr & SR_IMASK) != SR_IMASK)
- local_irq_enable();
-
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
-
- /*
- * If we're in an interrupt, have no user context or are running
- * in an atomic region then we must not take the fault:
- */
- if (in_atomic() || !mm)
- goto no_context;
-
- down_read(&mm->mmap_sem);
-
- vma = find_vma(mm, address);
- if (!vma)
- goto bad_area;
- if (vma->vm_start <= address)
- goto good_area;
- if (!(vma->vm_flags & VM_GROWSDOWN))
- goto bad_area;
- if (expand_stack(vma, address))
- goto bad_area;
-
- /*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
- */
-good_area:
- si_code = SEGV_ACCERR;
- if (writeaccess) {
- if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;
- } else {
- if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
- goto bad_area;
- }
-
- /*
- * If for any reason at all we couldn't handle the fault,
- * make sure we exit gracefully rather than endlessly redo
- * the fault.
- */
- fault = handle_mm_fault(mm, vma, address, writeaccess ? FAULT_FLAG_WRITE : 0);
- if (unlikely(fault & VM_FAULT_ERROR)) {
- if (fault & VM_FAULT_OOM)
- goto out_of_memory;
- else if (fault & VM_FAULT_SIGBUS)
- goto do_sigbus;
- BUG();
- }
- if (fault & VM_FAULT_MAJOR) {
- tsk->maj_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
- regs, address);
- } else {
- tsk->min_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
- regs, address);
- }
-
- up_read(&mm->mmap_sem);
- return;
-
- /*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
-bad_area:
- up_read(&mm->mmap_sem);
-
-bad_area_nosemaphore:
- if (user_mode(regs)) {
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
- info.si_code = si_code;
- info.si_addr = (void *) address;
- force_sig_info(SIGSEGV, &info, tsk);
- return;
- }
-
-no_context:
- /* Are we prepared to handle this kernel fault? */
- if (fixup_exception(regs))
- return;
-
- if (handle_trapped_io(regs, address))
- return;
-/*
- * Oops. The kernel tried to access some bad page. We'll have to
- * terminate things with extreme prejudice.
- *
- */
-
- bust_spinlocks(1);
-
- if (oops_may_print()) {
- unsigned long page;
-
- if (address < PAGE_SIZE)
- printk(KERN_ALERT "Unable to handle kernel NULL "
- "pointer dereference");
- else
- printk(KERN_ALERT "Unable to handle kernel paging "
- "request");
- printk(" at virtual address %08lx\n", address);
- printk(KERN_ALERT "pc = %08lx\n", regs->pc);
- page = (unsigned long)get_TTB();
- if (page) {
- page = ((__typeof__(page) *)page)[address >> PGDIR_SHIFT];
- printk(KERN_ALERT "*pde = %08lx\n", page);
- if (page & _PAGE_PRESENT) {
- page &= PAGE_MASK;
- address &= 0x003ff000;
- page = ((__typeof__(page) *)
- __va(page))[address >>
- PAGE_SHIFT];
- printk(KERN_ALERT "*pte = %08lx\n", page);
- }
- }
- }
-
- die("Oops", regs, writeaccess);
- bust_spinlocks(0);
- do_exit(SIGKILL);
-
-/*
- * We ran out of memory, or some other thing happened to us that made
- * us unable to handle the page fault gracefully.
- */
-out_of_memory:
- up_read(&mm->mmap_sem);
- if (!user_mode(regs))
- goto no_context;
- pagefault_out_of_memory();
- return;
-
-do_sigbus:
- up_read(&mm->mmap_sem);
-
- /*
- * Send a sigbus, regardless of whether we were in kernel
- * or user mode.
- */
- info.si_signo = SIGBUS;
- info.si_errno = 0;
- info.si_code = BUS_ADRERR;
- info.si_addr = (void *)address;
- force_sig_info(SIGBUS, &info, tsk);
-
- /* Kernel mode? Handle exceptions or die */
- if (!user_mode(regs))
- goto no_context;
-}
-
-/*
- * Called with interrupts disabled.
- */
-asmlinkage int __kprobes
-handle_tlbmiss(struct pt_regs *regs, unsigned long writeaccess,
- unsigned long address)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- pte_t entry;
-
- /*
- * We don't take page faults for P1, P2, and parts of P4, these
- * are always mapped, whether it be due to legacy behaviour in
- * 29-bit mode, or due to PMB configuration in 32-bit mode.
- */
- if (address >= P3SEG && address < P3_ADDR_MAX) {
- pgd = pgd_offset_k(address);
- } else {
- if (unlikely(address >= TASK_SIZE || !current->mm))
- return 1;
-
- pgd = pgd_offset(current->mm, address);
- }
-
- pud = pud_offset(pgd, address);
- if (pud_none_or_clear_bad(pud))
- return 1;
- pmd = pmd_offset(pud, address);
- if (pmd_none_or_clear_bad(pmd))
- return 1;
- pte = pte_offset_kernel(pmd, address);
- entry = *pte;
- if (unlikely(pte_none(entry) || pte_not_present(entry)))
- return 1;
- if (unlikely(writeaccess && !pte_write(entry)))
- return 1;
-
- if (writeaccess)
- entry = pte_mkdirty(entry);
- entry = pte_mkyoung(entry);
-
- set_pte(pte, entry);
-
-#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SMP)
- /*
- * SH-4 does not set MMUCR.RC to the corresponding TLB entry in
- * the case of an initial page write exception, so we need to
- * flush it in order to avoid potential TLB entry duplication.
- */
- if (writeaccess == 2)
- local_flush_tlb_one(get_asid(), address & PAGE_MASK);
-#endif
-
- update_mmu_cache(NULL, address, pte);
-
- return 0;
-}
diff --git a/arch/sh/mm/fault_64.c b/arch/sh/mm/fault_64.c
deleted file mode 100644
index 44a341029e7b..000000000000
--- a/arch/sh/mm/fault_64.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * The SH64 TLB miss.
- *
- * Original code from fault.c
- * Copyright (C) 2000, 2001 Paolo Alberelli
- *
- * Fast PTE->TLB refill path
- * Copyright (C) 2003 Richard.Curnow@superh.com
- *
- * IMPORTANT NOTES :
- * The do_fast_page_fault function is called from a context in entry.S
- * where very few registers have been saved. In particular, the code in
- * this file must be compiled not to use ANY caller-save registers that
- * are not part of the restricted save set. Also, it means that code in
- * this file must not make calls to functions elsewhere in the kernel, or
- * else the excepting context will see corruption in its caller-save
- * registers. Plus, the entry.S save area is non-reentrant, so this code
- * has to run with SR.BL==1, i.e. no interrupts taken inside it and panic
- * on any exception.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <asm/tlb.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
-#include <asm/mmu_context.h>
-#include <cpu/registers.h>
-
-/* Callable from fault.c, so not static */
-inline void __do_tlb_refill(unsigned long address,
- unsigned long long is_text_not_data, pte_t *pte)
-{
- unsigned long long ptel;
- unsigned long long pteh=0;
- struct tlb_info *tlbp;
- unsigned long long next;
-
- /* Get PTEL first */
- ptel = pte_val(*pte);
-
- /*
- * Set PTEH register
- */
- pteh = neff_sign_extend(address & MMU_VPN_MASK);
-
- /* Set the ASID. */
- pteh |= get_asid() << PTEH_ASID_SHIFT;
- pteh |= PTEH_VALID;
-
- /* Set PTEL register, set_pte has performed the sign extension */
- ptel &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
-
- tlbp = is_text_not_data ? &(cpu_data->itlb) : &(cpu_data->dtlb);
- next = tlbp->next;
- __flush_tlb_slot(next);
- asm volatile ("putcfg %0,1,%2\n\n\t"
- "putcfg %0,0,%1\n"
- : : "r" (next), "r" (pteh), "r" (ptel) );
-
- next += TLB_STEP;
- if (next > tlbp->last) next = tlbp->first;
- tlbp->next = next;
-
-}
-
-static int handle_vmalloc_fault(struct mm_struct *mm,
- unsigned long protection_flags,
- unsigned long long textaccess,
- unsigned long address)
-{
- pgd_t *dir;
- pud_t *pud;
- pmd_t *pmd;
- static pte_t *pte;
- pte_t entry;
-
- dir = pgd_offset_k(address);
-
- pud = pud_offset(dir, address);
- if (pud_none_or_clear_bad(pud))
- return 0;
-
- pmd = pmd_offset(pud, address);
- if (pmd_none_or_clear_bad(pmd))
- return 0;
-
- pte = pte_offset_kernel(pmd, address);
- entry = *pte;
-
- if (pte_none(entry) || !pte_present(entry))
- return 0;
- if ((pte_val(entry) & protection_flags) != protection_flags)
- return 0;
-
- __do_tlb_refill(address, textaccess, pte);
-
- return 1;
-}
-
-static int handle_tlbmiss(struct mm_struct *mm,
- unsigned long long protection_flags,
- unsigned long long textaccess,
- unsigned long address)
-{
- pgd_t *dir;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- pte_t entry;
-
- /* NB. The PGD currently only contains a single entry - there is no
- page table tree stored for the top half of the address space since
- virtual pages in that region should never be mapped in user mode.
- (In kernel mode, the only things in that region are the 512Mb super
- page (locked in), and vmalloc (modules) + I/O device pages (handled
- by handle_vmalloc_fault), so no PGD for the upper half is required
- by kernel mode either).
-
- See how mm->pgd is allocated and initialised in pgd_alloc to see why
- the next test is necessary. - RPC */
- if (address >= (unsigned long) TASK_SIZE)
- /* upper half - never has page table entries. */
- return 0;
-
- dir = pgd_offset(mm, address);
- if (pgd_none(*dir) || !pgd_present(*dir))
- return 0;
- if (!pgd_present(*dir))
- return 0;
-
- pud = pud_offset(dir, address);
- if (pud_none(*pud) || !pud_present(*pud))
- return 0;
-
- pmd = pmd_offset(pud, address);
- if (pmd_none(*pmd) || !pmd_present(*pmd))
- return 0;
-
- pte = pte_offset_kernel(pmd, address);
- entry = *pte;
-
- if (pte_none(entry) || !pte_present(entry))
- return 0;
-
- /*
- * If the page doesn't have sufficient protection bits set to
- * service the kind of fault being handled, there's not much
- * point doing the TLB refill. Punt the fault to the general
- * handler.
- */
- if ((pte_val(entry) & protection_flags) != protection_flags)
- return 0;
-
- __do_tlb_refill(address, textaccess, pte);
-
- return 1;
-}
-
-/*
- * Put all this information into one structure so that everything is just
- * arithmetic relative to a single base address. This reduces the number
- * of movi/shori pairs needed just to load addresses of static data.
- */
-struct expevt_lookup {
- unsigned short protection_flags[8];
- unsigned char is_text_access[8];
- unsigned char is_write_access[8];
-};
-
-#define PRU (1<<9)
-#define PRW (1<<8)
-#define PRX (1<<7)
-#define PRR (1<<6)
-
-#define DIRTY (_PAGE_DIRTY | _PAGE_ACCESSED)
-#define YOUNG (_PAGE_ACCESSED)
-
-/* Sized as 8 rather than 4 to allow checking the PTE's PRU bit against whether
- the fault happened in user mode or privileged mode. */
-static struct expevt_lookup expevt_lookup_table = {
- .protection_flags = {PRX, PRX, 0, 0, PRR, PRR, PRW, PRW},
- .is_text_access = {1, 1, 0, 0, 0, 0, 0, 0}
-};
-
-/*
- This routine handles page faults that can be serviced just by refilling a
- TLB entry from an existing page table entry. (This case represents a very
- large majority of page faults.) Return 1 if the fault was successfully
- handled. Return 0 if the fault could not be handled. (This leads into the
- general fault handling in fault.c which deals with mapping file-backed
- pages, stack growth, segmentation faults, swapping etc etc)
- */
-asmlinkage int do_fast_page_fault(unsigned long long ssr_md,
- unsigned long long expevt,
- unsigned long address)
-{
- struct task_struct *tsk;
- struct mm_struct *mm;
- unsigned long long textaccess;
- unsigned long long protection_flags;
- unsigned long long index;
- unsigned long long expevt4;
-
- /* The next few lines implement a way of hashing EXPEVT into a
- * small array index which can be used to lookup parameters
- * specific to the type of TLBMISS being handled.
- *
- * Note:
- * ITLBMISS has EXPEVT==0xa40
- * RTLBMISS has EXPEVT==0x040
- * WTLBMISS has EXPEVT==0x060
- */
- expevt4 = (expevt >> 4);
- /* TODO : xor ssr_md into this expression too. Then we can check
- * that PRU is set when it needs to be. */
- index = expevt4 ^ (expevt4 >> 5);
- index &= 7;
- protection_flags = expevt_lookup_table.protection_flags[index];
- textaccess = expevt_lookup_table.is_text_access[index];
-
- /* SIM
- * Note this is now called with interrupts still disabled
- * This is to cope with being called for a missing IO port
- * address with interrupts disabled. This should be fixed as
- * soon as we have a better 'fast path' miss handler.
- *
- * Plus take care how you try and debug this stuff.
- * For example, writing debug data to a port which you
- * have just faulted on is not going to work.
- */
-
- tsk = current;
- mm = tsk->mm;
-
- if ((address >= VMALLOC_START && address < VMALLOC_END) ||
- (address >= IOBASE_VADDR && address < IOBASE_END)) {
- if (ssr_md)
- /*
- * Process-contexts can never have this address
- * range mapped
- */
- if (handle_vmalloc_fault(mm, protection_flags,
- textaccess, address))
- return 1;
- } else if (!in_interrupt() && mm) {
- if (handle_tlbmiss(mm, protection_flags, textaccess, address))
- return 1;
- }
-
- return 0;
-}
diff --git a/arch/sh/mm/tlb-sh5.c b/arch/sh/mm/tlb-sh5.c
index f27dbe1c1599..3aea25dc431a 100644
--- a/arch/sh/mm/tlb-sh5.c
+++ b/arch/sh/mm/tlb-sh5.c
@@ -182,3 +182,43 @@ void tlb_unwire_entry(void)
local_irq_restore(flags);
}
+
+void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+{
+ unsigned long long ptel;
+ unsigned long long pteh=0;
+ struct tlb_info *tlbp;
+ unsigned long long next;
+ unsigned int fault_code = get_thread_fault_code();
+
+ /* Get PTEL first */
+ ptel = pte.pte_low;
+
+ /*
+ * Set PTEH register
+ */
+ pteh = neff_sign_extend(address & MMU_VPN_MASK);
+
+ /* Set the ASID. */
+ pteh |= get_asid() << PTEH_ASID_SHIFT;
+ pteh |= PTEH_VALID;
+
+ /* Set PTEL register, set_pte has performed the sign extension */
+ ptel &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+
+ if (fault_code & FAULT_CODE_ITLB)
+ tlbp = &cpu_data->itlb;
+ else
+ tlbp = &cpu_data->dtlb;
+
+ next = tlbp->next;
+ __flush_tlb_slot(next);
+ asm volatile ("putcfg %0,1,%2\n\n\t"
+ "putcfg %0,0,%1\n"
+ : : "r" (next), "r" (pteh), "r" (ptel) );
+
+ next += TLB_STEP;
+ if (next > tlbp->last)
+ next = tlbp->first;
+ tlbp->next = next;
+}
diff --git a/arch/sh/mm/tlbex_32.c b/arch/sh/mm/tlbex_32.c
new file mode 100644
index 000000000000..382262dc0c4b
--- /dev/null
+++ b/arch/sh/mm/tlbex_32.c
@@ -0,0 +1,78 @@
+/*
+ * TLB miss handler for SH with an MMU.
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2003 - 2012 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>
+#include <asm/mmu_context.h>
+#include <asm/thread_info.h>
+
+/*
+ * Called with interrupts disabled.
+ */
+asmlinkage int __kprobes
+handle_tlbmiss(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ pte_t entry;
+
+ /*
+ * We don't take page faults for P1, P2, and parts of P4, these
+ * are always mapped, whether it be due to legacy behaviour in
+ * 29-bit mode, or due to PMB configuration in 32-bit mode.
+ */
+ if (address >= P3SEG && address < P3_ADDR_MAX) {
+ pgd = pgd_offset_k(address);
+ } else {
+ if (unlikely(address >= TASK_SIZE || !current->mm))
+ return 1;
+
+ pgd = pgd_offset(current->mm, address);
+ }
+
+ pud = pud_offset(pgd, address);
+ if (pud_none_or_clear_bad(pud))
+ return 1;
+ pmd = pmd_offset(pud, address);
+ if (pmd_none_or_clear_bad(pmd))
+ return 1;
+ pte = pte_offset_kernel(pmd, address);
+ entry = *pte;
+ if (unlikely(pte_none(entry) || pte_not_present(entry)))
+ return 1;
+ if (unlikely(error_code && !pte_write(entry)))
+ return 1;
+
+ if (error_code)
+ entry = pte_mkdirty(entry);
+ entry = pte_mkyoung(entry);
+
+ set_pte(pte, entry);
+
+#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SMP)
+ /*
+ * SH-4 does not set MMUCR.RC to the corresponding TLB entry in
+ * the case of an initial page write exception, so we need to
+ * flush it in order to avoid potential TLB entry duplication.
+ */
+ if (error_code == FAULT_CODE_INITIAL)
+ local_flush_tlb_one(get_asid(), address & PAGE_MASK);
+#endif
+
+ set_thread_fault_code(error_code);
+ update_mmu_cache(NULL, address, pte);
+
+ return 0;
+}
diff --git a/arch/sh/mm/tlbex_64.c b/arch/sh/mm/tlbex_64.c
new file mode 100644
index 000000000000..8557548fc53e
--- /dev/null
+++ b/arch/sh/mm/tlbex_64.c
@@ -0,0 +1,166 @@
+/*
+ * The SH64 TLB miss.
+ *
+ * Original code from fault.c
+ * Copyright (C) 2000, 2001 Paolo Alberelli
+ *
+ * Fast PTE->TLB refill path
+ * Copyright (C) 2003 Richard.Curnow@superh.com
+ *
+ * IMPORTANT NOTES :
+ * The do_fast_page_fault function is called from a context in entry.S
+ * where very few registers have been saved. In particular, the code in
+ * this file must be compiled not to use ANY caller-save registers that
+ * are not part of the restricted save set. Also, it means that code in
+ * this file must not make calls to functions elsewhere in the kernel, or
+ * else the excepting context will see corruption in its caller-save
+ * registers. Plus, the entry.S save area is non-reentrant, so this code
+ * has to run with SR.BL==1, i.e. no interrupts taken inside it and panic
+ * on any exception.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/kprobes.h>
+#include <asm/tlb.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+
+static int handle_tlbmiss(unsigned long long protection_flags,
+ unsigned long address)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ pte_t entry;
+
+ if (is_vmalloc_addr((void *)address)) {
+ pgd = pgd_offset_k(address);
+ } else {
+ if (unlikely(address >= TASK_SIZE || !current->mm))
+ return 1;
+
+ pgd = pgd_offset(current->mm, address);
+ }
+
+ pud = pud_offset(pgd, address);
+ if (pud_none(*pud) || !pud_present(*pud))
+ return 1;
+
+ pmd = pmd_offset(pud, address);
+ if (pmd_none(*pmd) || !pmd_present(*pmd))
+ return 1;
+
+ pte = pte_offset_kernel(pmd, address);
+ entry = *pte;
+ if (pte_none(entry) || !pte_present(entry))
+ return 1;
+
+ /*
+ * If the page doesn't have sufficient protection bits set to
+ * service the kind of fault being handled, there's not much
+ * point doing the TLB refill. Punt the fault to the general
+ * handler.
+ */
+ if ((pte_val(entry) & protection_flags) != protection_flags)
+ return 1;
+
+ update_mmu_cache(NULL, address, pte);
+
+ return 0;
+}
+
+/*
+ * Put all this information into one structure so that everything is just
+ * arithmetic relative to a single base address. This reduces the number
+ * of movi/shori pairs needed just to load addresses of static data.
+ */
+struct expevt_lookup {
+ unsigned short protection_flags[8];
+ unsigned char is_text_access[8];
+ unsigned char is_write_access[8];
+};
+
+#define PRU (1<<9)
+#define PRW (1<<8)
+#define PRX (1<<7)
+#define PRR (1<<6)
+
+/* Sized as 8 rather than 4 to allow checking the PTE's PRU bit against whether
+ the fault happened in user mode or privileged mode. */
+static struct expevt_lookup expevt_lookup_table = {
+ .protection_flags = {PRX, PRX, 0, 0, PRR, PRR, PRW, PRW},
+ .is_text_access = {1, 1, 0, 0, 0, 0, 0, 0}
+};
+
+static inline unsigned int
+expevt_to_fault_code(unsigned long expevt)
+{
+ if (expevt == 0xa40)
+ return FAULT_CODE_ITLB;
+ else if (expevt == 0x060)
+ return FAULT_CODE_WRITE;
+
+ return 0;
+}
+
+/*
+ This routine handles page faults that can be serviced just by refilling a
+ TLB entry from an existing page table entry. (This case represents a very
+ large majority of page faults.) Return 1 if the fault was successfully
+ handled. Return 0 if the fault could not be handled. (This leads into the
+ general fault handling in fault.c which deals with mapping file-backed
+ pages, stack growth, segmentation faults, swapping etc etc)
+ */
+asmlinkage int __kprobes
+do_fast_page_fault(unsigned long long ssr_md, unsigned long long expevt,
+ unsigned long address)
+{
+ unsigned long long protection_flags;
+ unsigned long long index;
+ unsigned long long expevt4;
+ unsigned int fault_code;
+
+ /* The next few lines implement a way of hashing EXPEVT into a
+ * small array index which can be used to lookup parameters
+ * specific to the type of TLBMISS being handled.
+ *
+ * Note:
+ * ITLBMISS has EXPEVT==0xa40
+ * RTLBMISS has EXPEVT==0x040
+ * WTLBMISS has EXPEVT==0x060
+ */
+ expevt4 = (expevt >> 4);
+ /* TODO : xor ssr_md into this expression too. Then we can check
+ * that PRU is set when it needs to be. */
+ index = expevt4 ^ (expevt4 >> 5);
+ index &= 7;
+
+ fault_code = expevt_to_fault_code(expevt);
+
+ protection_flags = expevt_lookup_table.protection_flags[index];
+
+ if (expevt_lookup_table.is_text_access[index])
+ fault_code |= FAULT_CODE_ITLB;
+ if (!ssr_md)
+ fault_code |= FAULT_CODE_USER;
+
+ set_thread_fault_code(fault_code);
+
+ return handle_tlbmiss(protection_flags, address);
+}
diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c
index 11c5a18f10ed..f33fdd2558e8 100644
--- a/arch/sh/mm/tlbflush_64.c
+++ b/arch/sh/mm/tlbflush_64.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2000, 2001 Paolo Alberelli
* Copyright (C) 2003 Richard Curnow (/proc/tlb, bug fixes)
- * Copyright (C) 2003 - 2009 Paul Mundt
+ * Copyright (C) 2003 - 2012 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -28,294 +28,6 @@
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
-extern void die(const char *,struct pt_regs *,long);
-
-#define PFLAG(val,flag) (( (val) & (flag) ) ? #flag : "" )
-#define PPROT(flag) PFLAG(pgprot_val(prot),flag)
-
-static inline void print_prots(pgprot_t prot)
-{
- printk("prot is 0x%016llx\n",pgprot_val(prot));
-
- printk("%s %s %s %s %s\n",PPROT(_PAGE_SHARED),PPROT(_PAGE_READ),
- PPROT(_PAGE_EXECUTE),PPROT(_PAGE_WRITE),PPROT(_PAGE_USER));
-}
-
-static inline void print_vma(struct vm_area_struct *vma)
-{
- printk("vma start 0x%08lx\n", vma->vm_start);
- printk("vma end 0x%08lx\n", vma->vm_end);
-
- print_prots(vma->vm_page_prot);
- printk("vm_flags 0x%08lx\n", vma->vm_flags);
-}
-
-static inline void print_task(struct task_struct *tsk)
-{
- printk("Task pid %d\n", task_pid_nr(tsk));
-}
-
-static pte_t *lookup_pte(struct mm_struct *mm, unsigned long address)
-{
- pgd_t *dir;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- pte_t entry;
-
- dir = pgd_offset(mm, address);
- if (pgd_none(*dir))
- return NULL;
-
- pud = pud_offset(dir, address);
- if (pud_none(*pud))
- return NULL;
-
- pmd = pmd_offset(pud, address);
- if (pmd_none(*pmd))
- return NULL;
-
- pte = pte_offset_kernel(pmd, address);
- entry = *pte;
- if (pte_none(entry) || !pte_present(entry))
- return NULL;
-
- return pte;
-}
-
-/*
- * This routine handles page faults. It determines the address,
- * and the problem, and then passes it off to one of the appropriate
- * routines.
- */
-asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
- unsigned long textaccess, unsigned long address)
-{
- struct task_struct *tsk;
- struct mm_struct *mm;
- struct vm_area_struct * vma;
- const struct exception_table_entry *fixup;
- pte_t *pte;
- int fault;
-
- /* SIM
- * Note this is now called with interrupts still disabled
- * This is to cope with being called for a missing IO port
- * address with interrupts disabled. This should be fixed as
- * soon as we have a better 'fast path' miss handler.
- *
- * Plus take care how you try and debug this stuff.
- * For example, writing debug data to a port which you
- * have just faulted on is not going to work.
- */
-
- tsk = current;
- mm = tsk->mm;
-
- /* Not an IO address, so reenable interrupts */
- local_irq_enable();
-
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
-
- /*
- * If we're in an interrupt or have no user
- * context, we must not take the fault..
- */
- if (in_atomic() || !mm)
- goto no_context;
-
- /* TLB misses upon some cache flushes get done under cli() */
- down_read(&mm->mmap_sem);
-
- vma = find_vma(mm, address);
-
- if (!vma) {
-#ifdef DEBUG_FAULT
- print_task(tsk);
- printk("%s:%d fault, address is 0x%08x PC %016Lx textaccess %d writeaccess %d\n",
- __func__, __LINE__,
- address,regs->pc,textaccess,writeaccess);
- show_regs(regs);
-#endif
- goto bad_area;
- }
- if (vma->vm_start <= address) {
- goto good_area;
- }
-
- if (!(vma->vm_flags & VM_GROWSDOWN)) {
-#ifdef DEBUG_FAULT
- print_task(tsk);
- printk("%s:%d fault, address is 0x%08x PC %016Lx textaccess %d writeaccess %d\n",
- __func__, __LINE__,
- address,regs->pc,textaccess,writeaccess);
- show_regs(regs);
-
- print_vma(vma);
-#endif
- goto bad_area;
- }
- if (expand_stack(vma, address)) {
-#ifdef DEBUG_FAULT
- print_task(tsk);
- printk("%s:%d fault, address is 0x%08x PC %016Lx textaccess %d writeaccess %d\n",
- __func__, __LINE__,
- address,regs->pc,textaccess,writeaccess);
- show_regs(regs);
-#endif
- goto bad_area;
- }
-/*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
- */
-good_area:
- if (textaccess) {
- if (!(vma->vm_flags & VM_EXEC))
- goto bad_area;
- } else {
- if (writeaccess) {
- if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;
- } else {
- if (!(vma->vm_flags & VM_READ))
- goto bad_area;
- }
- }
-
- /*
- * If for any reason at all we couldn't handle the fault,
- * make sure we exit gracefully rather than endlessly redo
- * the fault.
- */
- fault = handle_mm_fault(mm, vma, address, writeaccess ? FAULT_FLAG_WRITE : 0);
- if (unlikely(fault & VM_FAULT_ERROR)) {
- if (fault & VM_FAULT_OOM)
- goto out_of_memory;
- else if (fault & VM_FAULT_SIGBUS)
- goto do_sigbus;
- BUG();
- }
-
- if (fault & VM_FAULT_MAJOR) {
- tsk->maj_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
- regs, address);
- } else {
- tsk->min_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
- regs, address);
- }
-
- /* If we get here, the page fault has been handled. Do the TLB refill
- now from the newly-setup PTE, to avoid having to fault again right
- away on the same instruction. */
- pte = lookup_pte (mm, address);
- if (!pte) {
- /* From empirical evidence, we can get here, due to
- !pte_present(pte). (e.g. if a swap-in occurs, and the page
- is swapped back out again before the process that wanted it
- gets rescheduled?) */
- goto no_pte;
- }
-
- __do_tlb_refill(address, textaccess, pte);
-
-no_pte:
-
- up_read(&mm->mmap_sem);
- return;
-
-/*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
-bad_area:
-#ifdef DEBUG_FAULT
- printk("fault:bad area\n");
-#endif
- up_read(&mm->mmap_sem);
-
- if (user_mode(regs)) {
- static int count=0;
- siginfo_t info;
- if (count < 4) {
- /* This is really to help debug faults when starting
- * usermode, so only need a few */
- count++;
- printk("user mode bad_area address=%08lx pid=%d (%s) pc=%08lx\n",
- address, task_pid_nr(current), current->comm,
- (unsigned long) regs->pc);
-#if 0
- show_regs(regs);
-#endif
- }
- if (is_global_init(tsk)) {
- panic("INIT had user mode bad_area\n");
- }
- tsk->thread.address = address;
- tsk->thread.error_code = writeaccess;
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
- info.si_addr = (void *) address;
- force_sig_info(SIGSEGV, &info, tsk);
- return;
- }
-
-no_context:
-#ifdef DEBUG_FAULT
- printk("fault:No context\n");
-#endif
- /* Are we prepared to handle this kernel fault? */
- fixup = search_exception_tables(regs->pc);
- if (fixup) {
- regs->pc = fixup->fixup;
- return;
- }
-
-/*
- * Oops. The kernel tried to access some bad page. We'll have to
- * terminate things with extreme prejudice.
- *
- */
- if (address < PAGE_SIZE)
- printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
- else
- printk(KERN_ALERT "Unable to handle kernel paging request");
- printk(" at virtual address %08lx\n", address);
- printk(KERN_ALERT "pc = %08Lx%08Lx\n", regs->pc >> 32, regs->pc & 0xffffffff);
- die("Oops", regs, writeaccess);
- do_exit(SIGKILL);
-
-/*
- * We ran out of memory, or some other thing happened to us that made
- * us unable to handle the page fault gracefully.
- */
-out_of_memory:
- up_read(&mm->mmap_sem);
- if (!user_mode(regs))
- goto no_context;
- pagefault_out_of_memory();
- return;
-
-do_sigbus:
- printk("fault:Do sigbus\n");
- up_read(&mm->mmap_sem);
-
- /*
- * Send a sigbus, regardless of whether we were in kernel
- * or user mode.
- */
- tsk->thread.address = address;
- tsk->thread.error_code = writeaccess;
- tsk->thread.trap_no = 14;
- force_sig(SIGBUS, tsk);
-
- /* Kernel mode? Handle exceptions or die */
- if (!user_mode(regs))
- goto no_context;
-}
-
void local_flush_tlb_one(unsigned long asid, unsigned long page)
{
unsigned long long match, pteh=0, lpage;
@@ -458,7 +170,3 @@ void __flush_tlb_global(void)
{
flush_tlb_all();
}
-
-void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
-{
-}
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index 6dd56c4d0054..569977e52c91 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -51,6 +51,8 @@ SDK7780 SH_SDK7780
MIGOR SH_MIGOR
RSK7201 SH_RSK7201
RSK7203 SH_RSK7203
+RSK7264 SH_RSK7264
+RSK7269 SH_RSK7269
AP325RXA SH_AP325RXA
SH2007 SH_SH2007
SH7757LCR SH_SH7757LCR
diff --git a/arch/sparc/Kbuild b/arch/sparc/Kbuild
new file mode 100644
index 000000000000..5cd01161fd00
--- /dev/null
+++ b/arch/sparc/Kbuild
@@ -0,0 +1,8 @@
+#
+# core part of the sparc kernel
+#
+
+obj-y += kernel/
+obj-y += mm/
+obj-y += math-emu/
+obj-y += net/
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 5f6acce45a0d..1ea3fd954756 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -31,11 +31,13 @@ config SPARC
select GENERIC_PCI_IOMAP
select HAVE_NMI_WATCHDOG if SPARC64
select HAVE_BPF_JIT
+ select GENERIC_SMP_IDLE_THREAD
config SPARC32
def_bool !64BIT
select GENERIC_ATOMIC64
select CLZ_TAB
+ select ARCH_THREAD_INFO_ALLOCATOR
config SPARC64
def_bool 64BIT
@@ -62,6 +64,7 @@ config SPARC64
select IRQ_PREFLOW_FASTEOI
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select HAVE_C_RECORDMCOUNT
+ select NO_BOOTMEM
config ARCH_DEFCONFIG
string
@@ -74,17 +77,12 @@ config BITS
default 32 if SPARC32
default 64 if SPARC64
-config ARCH_USES_GETTIMEOFFSET
- bool
- default y if SPARC32
-
config GENERIC_CMOS_UPDATE
bool
default y
config GENERIC_CLOCKEVENTS
- bool
- default y if SPARC64
+ def_bool y
config IOMMU_HELPER
bool
@@ -155,7 +153,7 @@ source "kernel/Kconfig.freezer"
menu "Processor type and features"
config SMP
- bool "Symmetric multi-processing support (does not work on sun4/sun4c)"
+ bool "Symmetric multi-processing support"
---help---
This enables support for systems with more than one CPU. If you have
a system with only one CPU, say N. If you have a system with more
@@ -585,6 +583,9 @@ config SYSVIPC_COMPAT
depends on COMPAT && SYSVIPC
default y
+config KEYS_COMPAT
+ def_bool y if COMPAT && KEYS
+
endmenu
source "net/Kconfig"
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 0e5de13b56c5..541b8b075c7d 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -19,39 +19,27 @@ ifeq ($(CONFIG_SPARC32),y)
# sparc32
#
-#
-# Uncomment the first KBUILD_CFLAGS if you are doing kgdb source level
-# debugging of the kernel to get the proper debugging information.
-
-AS := $(AS) -32
-LDFLAGS := -m elf32_sparc
CHECKFLAGS += -D__sparc__
+LDFLAGS := -m elf32_sparc
export BITS := 32
UTS_MACHINE := sparc
-#KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7
-KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
-KBUILD_AFLAGS += -m32 -Wa,-Av8
-
-#LDFLAGS_vmlinux = -N -Ttext 0xf0004000
-# Since 2.5.40, the first stage is left not btfix-ed.
-# Actual linking is done with "make image".
-LDFLAGS_vmlinux = -r
+KBUILD_CFLAGS += -m32 -mcpu=v8 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
+KBUILD_AFLAGS += -m32 -Wa,-Av8
else
#####
# sparc64
#
-CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -D__arch64__ -m64
+CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -D__arch64__ -m64
+LDFLAGS := -m elf64_sparc
+export BITS := 64
+UTS_MACHINE := sparc64
-LDFLAGS := -m elf64_sparc
-export BITS := 64
-UTS_MACHINE := sparc64
-
-KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \
- -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare \
- -Wa,--undeclared-regs
+KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow
+KBUILD_CFLAGS += -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare
+KBUILD_CFLAGS += -Wa,--undeclared-regs
KBUILD_CFLAGS += $(call cc-option,-mtune=ultrasparc3)
KBUILD_AFLAGS += -m64 -mcpu=ultrasparc -Wa,--undeclared-regs
@@ -62,28 +50,15 @@ endif
endif
head-y := arch/sparc/kernel/head_$(BITS).o
-head-y += arch/sparc/kernel/init_task.o
-core-y += arch/sparc/kernel/
-core-y += arch/sparc/mm/ arch/sparc/math-emu/
-core-y += arch/sparc/net/
+# See arch/sparc/Kbuild for the core part of the kernel
+core-y += arch/sparc/
libs-y += arch/sparc/prom/
libs-y += arch/sparc/lib/
drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/
-# Export what is needed by arch/sparc/boot/Makefile
-export VMLINUX_INIT VMLINUX_MAIN
-VMLINUX_INIT := $(head-y) $(init-y)
-VMLINUX_MAIN := $(core-y) kernel/ mm/ fs/ ipc/ security/ crypto/ block/
-VMLINUX_MAIN += $(patsubst %/, %/lib.a, $(libs-y)) $(libs-y)
-VMLINUX_MAIN += $(drivers-y) $(net-y)
-
-ifdef CONFIG_KALLSYMS
-export kallsyms.o := .tmp_kallsyms2.o
-endif
-
boot := arch/sparc/boot
# Default target
diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
index d56d199c1aa8..6e63afb128d9 100644
--- a/arch/sparc/boot/Makefile
+++ b/arch/sparc/boot/Makefile
@@ -6,8 +6,8 @@
ROOT_IMG := /usr/src/root.img
ELFTOAOUT := elftoaout
-hostprogs-y := piggyback btfixupprep
-targets := tftpboot.img btfix.o btfix.S image zImage vmlinux.aout
+hostprogs-y := piggyback
+targets := tftpboot.img image zImage vmlinux.aout
clean-files := System.map
quiet_cmd_elftoaout = ELFTOAOUT $@
@@ -17,58 +17,9 @@ quiet_cmd_piggy = PIGGY $@
quiet_cmd_strip = STRIP $@
cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start $< -o $@
-ifeq ($(CONFIG_SPARC32),y)
-quiet_cmd_btfix = BTFIX $@
- cmd_btfix = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@
-quiet_cmd_sysmap = SYSMAP $(obj)/System.map
- cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
-quiet_cmd_image = LD $@
- cmd_image = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) -o $@
-
-define rule_image
- $(if $($(quiet)cmd_image), \
- echo ' $($(quiet)cmd_image)' &&) \
- $(cmd_image); \
- $(if $($(quiet)cmd_sysmap), \
- echo ' $($(quiet)cmd_sysmap)' &&) \
- $(cmd_sysmap) $@ $(obj)/System.map; \
- if [ $$? -ne 0 ]; then \
- rm -f $@; \
- /bin/false; \
- fi; \
- echo 'cmd_$@ := $(cmd_image)' > $(@D)/.$(@F).cmd
-endef
-
-BTOBJS := $(patsubst %/, %/built-in.o, $(VMLINUX_INIT))
-BTLIBS := $(patsubst %/, %/built-in.o, $(VMLINUX_MAIN))
-LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds $(BTOBJS) \
- --start-group $(BTLIBS) --end-group \
- $(kallsyms.o) $(obj)/btfix.o
-
-# Link the final image including btfixup'ed symbols.
-# This is a replacement for the link done in the top-level Makefile.
-# Note: No dependency on the prerequisite files since that would require
-# make to try check if they are updated - and due to changes
-# in gcc options (path for example) this would result in
-# these files being recompiled for each build.
-$(obj)/image: $(obj)/btfix.o FORCE
- $(call if_changed_rule,image)
-
-$(obj)/zImage: $(obj)/image
- $(call if_changed,strip)
- @echo ' kernel: $@ is ready'
-
-$(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE
- $(call if_changed,btfix)
-
-endif
-
ifeq ($(CONFIG_SPARC64),y)
# Actual linking
-$(obj)/image: vmlinux FORCE
- $(call if_changed,strip)
- @echo ' kernel: $@ is ready'
$(obj)/zImage: $(obj)/image
$(call if_changed,gzip)
@@ -79,6 +30,10 @@ $(obj)/vmlinux.aout: vmlinux FORCE
@echo ' kernel: $@ is ready'
else
+$(obj)/zImage: $(obj)/image
+ $(call if_changed,strip)
+ @echo ' kernel: $@ is ready'
+
# The following lines make a readable image for U-Boot.
# uImage - Binary file read by U-boot
# uImage.o - object file of uImage for loading with a
@@ -107,6 +62,10 @@ $(obj)/uImage: $(obj)/image.gz
endif
+$(obj)/image: vmlinux FORCE
+ $(call if_changed,strip)
+ @echo ' kernel: $@ is ready'
+
$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE
$(call if_changed,elftoaout)
$(call if_changed,piggy)
diff --git a/arch/sparc/boot/btfixupprep.c b/arch/sparc/boot/btfixupprep.c
deleted file mode 100644
index da031159e2b7..000000000000
--- a/arch/sparc/boot/btfixupprep.c
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- Simple utility to prepare vmlinux image for sparc.
- Resolves all BTFIXUP uses and settings and creates
- a special .s object to link to the image.
-
- Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
-
- 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. */
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <malloc.h>
-
-#define MAXSYMS 1024
-
-static char *symtab = "SYMBOL TABLE:";
-static char *relrec = "RELOCATION RECORDS FOR [";
-static int rellen;
-static int symlen;
-int mode;
-
-struct _btfixup;
-
-typedef struct _btfixuprel {
- char *sect;
- unsigned long offset;
- struct _btfixup *f;
- int frel;
- struct _btfixuprel *next;
-} btfixuprel;
-
-typedef struct _btfixup {
- int type;
- int setinitval;
- unsigned int initval;
- char *initvalstr;
- char *name;
- btfixuprel *rel;
-} btfixup;
-
-btfixup array[MAXSYMS];
-int last = 0;
-char buffer[1024];
-unsigned long lastfoffset = -1;
-unsigned long lastfrelno;
-btfixup *lastf;
-
-static void fatal(void) __attribute__((noreturn));
-static void fatal(void)
-{
- fprintf(stderr, "Malformed output from objdump\n%s\n", buffer);
- exit(1);
-}
-
-static btfixup *find(int type, char *name)
-{
- int i;
- for (i = 0; i < last; i++) {
- if (array[i].type == type && !strcmp(array[i].name, name))
- return array + i;
- }
- array[last].type = type;
- array[last].name = strdup(name);
- array[last].setinitval = 0;
- if (!array[last].name) fatal();
- array[last].rel = NULL;
- last++;
- if (last >= MAXSYMS) {
- fprintf(stderr, "Ugh. Something strange. More than %d different BTFIXUP symbols\n", MAXSYMS);
- exit(1);
- }
- return array + last - 1;
-}
-
-static void set_mode (char *buffer)
-{
- for (mode = 0;; mode++)
- if (buffer[mode] < '0' || buffer[mode] > '9')
- break;
- if (mode != 8 && mode != 16)
- fatal();
-}
-
-
-int main(int argc,char **argv)
-{
- char *p, *q;
- char *sect;
- int i, j, k;
- unsigned int initval;
- int shift;
- btfixup *f;
- btfixuprel *r, **rr;
- unsigned long offset;
- char *initvalstr;
-
- symlen = strlen(symtab);
- while (fgets (buffer, 1024, stdin) != NULL)
- if (!strncmp (buffer, symtab, symlen))
- goto main0;
- fatal();
-main0:
- rellen = strlen(relrec);
- while (fgets (buffer, 1024, stdin) != NULL)
- if (!strncmp (buffer, relrec, rellen))
- goto main1;
- fatal();
-main1:
- sect = malloc(strlen (buffer + rellen) + 1);
- if (!sect) fatal();
- strcpy (sect, buffer + rellen);
- p = strchr (sect, ']');
- if (!p) fatal();
- *p = 0;
- if (fgets (buffer, 1024, stdin) == NULL)
- fatal();
- while (fgets (buffer, 1024, stdin) != NULL) {
- int nbase;
- if (!strncmp (buffer, relrec, rellen))
- goto main1;
- if (mode == 0)
- set_mode (buffer);
- p = strchr (buffer, '\n');
- if (p) *p = 0;
- if (strlen (buffer) < 22+mode)
- continue;
- if (strncmp (buffer + mode, " R_SPARC_", 9))
- continue;
- nbase = 27 - 8 + mode;
- if (buffer[nbase] != '_' || buffer[nbase+1] != '_' || buffer[nbase+2] != '_')
- continue;
- switch (buffer[nbase+3]) {
- case 'f': /* CALL */
- case 'b': /* BLACKBOX */
- case 's': /* SIMM13 */
- case 'a': /* HALF */
- case 'h': /* SETHI */
- case 'i': /* INT */
- break;
- default:
- continue;
- }
- p = strchr (buffer + nbase+5, '+');
- if (p) *p = 0;
- shift = nbase + 5;
- if (buffer[nbase+4] == 's' && buffer[nbase+5] == '_') {
- shift = nbase + 6;
- if (strcmp (sect, ".init.text")) {
- fprintf(stderr,
- "Wrong use of '%s' BTFIXUPSET in '%s' section.\n"
- "BTFIXUPSET_CALL can be used only in"
- " __init sections\n",
- buffer + shift, sect);
- exit(1);
- }
- } else if (buffer[nbase+4] != '_')
- continue;
- if (!strcmp (sect, ".text.exit"))
- continue;
- if (strcmp (sect, ".text") &&
- strcmp (sect, ".init.text") &&
- strcmp (sect, ".fixup") &&
- (strcmp (sect, "__ksymtab") || buffer[nbase+3] != 'f')) {
- if (buffer[nbase+3] == 'f')
- fprintf(stderr,
- "Wrong use of '%s' in '%s' section.\n"
- " It can be used only in .text, .init.text,"
- " .fixup and __ksymtab\n",
- buffer + shift, sect);
- else
- fprintf(stderr,
- "Wrong use of '%s' in '%s' section.\n"
- " It can be only used in .text, .init.text,"
- " and .fixup\n", buffer + shift, sect);
- exit(1);
- }
- p = strstr (buffer + shift, "__btset_");
- if (p && buffer[nbase+4] == 's') {
- fprintf(stderr, "__btset_ in BTFIXUP name can only be used when defining the variable, not for setting\n%s\n", buffer);
- exit(1);
- }
- initval = 0;
- initvalstr = NULL;
- if (p) {
- if (p[8] != '0' || p[9] != 'x') {
- fprintf(stderr, "Pre-initialized values can be only initialized with hexadecimal constants starting 0x\n%s\n", buffer);
- exit(1);
- }
- initval = strtoul(p + 10, &q, 16);
- if (*q || !initval) {
- fprintf(stderr, "Pre-initialized values can be only in the form name__btset_0xXXXXXXXX where X are hex digits.\nThey cannot be name__btset_0x00000000 though. Use BTFIXUPDEF_XX instead of BTFIXUPDEF_XX_INIT then.\n%s\n", buffer);
- exit(1);
- }
- initvalstr = p + 10;
- *p = 0;
- }
- f = find(buffer[nbase+3], buffer + shift);
- if (buffer[nbase+4] == 's')
- continue;
- switch (buffer[nbase+3]) {
- case 'f':
- if (initval) {
- fprintf(stderr, "Cannot use pre-initialized fixups for calls\n%s\n", buffer);
- exit(1);
- }
- if (!strcmp (sect, "__ksymtab")) {
- if (strncmp (buffer + mode+9, "32 ", 10)) {
- fprintf(stderr, "BTFIXUP_CALL in EXPORT_SYMBOL results in relocation other than R_SPARC_32\n\%s\n", buffer);
- exit(1);
- }
- } else if (strncmp (buffer + mode+9, "WDISP30 ", 10) &&
- strncmp (buffer + mode+9, "HI22 ", 10) &&
- strncmp (buffer + mode+9, "LO10 ", 10)) {
- fprintf(stderr, "BTFIXUP_CALL results in relocation other than R_SPARC_WDISP30, R_SPARC_HI22 or R_SPARC_LO10\n%s\n", buffer);
- exit(1);
- }
- break;
- case 'b':
- if (initval) {
- fprintf(stderr, "Cannot use pre-initialized fixups for blackboxes\n%s\n", buffer);
- exit(1);
- }
- if (strncmp (buffer + mode+9, "HI22 ", 10)) {
- fprintf(stderr, "BTFIXUP_BLACKBOX results in relocation other than R_SPARC_HI22\n%s\n", buffer);
- exit(1);
- }
- break;
- case 's':
- if (initval + 0x1000 >= 0x2000) {
- fprintf(stderr, "Wrong initializer for SIMM13. Has to be from $fffff000 to $00000fff\n%s\n", buffer);
- exit(1);
- }
- if (strncmp (buffer + mode+9, "13 ", 10)) {
- fprintf(stderr, "BTFIXUP_SIMM13 results in relocation other than R_SPARC_13\n%s\n", buffer);
- exit(1);
- }
- break;
- case 'a':
- if (initval + 0x1000 >= 0x2000 && (initval & 0x3ff)) {
- fprintf(stderr, "Wrong initializer for HALF.\n%s\n", buffer);
- exit(1);
- }
- if (strncmp (buffer + mode+9, "13 ", 10)) {
- fprintf(stderr, "BTFIXUP_HALF results in relocation other than R_SPARC_13\n%s\n", buffer);
- exit(1);
- }
- break;
- case 'h':
- if (initval & 0x3ff) {
- fprintf(stderr, "Wrong initializer for SETHI. Cannot have set low 10 bits\n%s\n", buffer);
- exit(1);
- }
- if (strncmp (buffer + mode+9, "HI22 ", 10)) {
- fprintf(stderr, "BTFIXUP_SETHI results in relocation other than R_SPARC_HI22\n%s\n", buffer);
- exit(1);
- }
- break;
- case 'i':
- if (initval) {
- fprintf(stderr, "Cannot use pre-initialized fixups for INT\n%s\n", buffer);
- exit(1);
- }
- if (strncmp (buffer + mode+9, "HI22 ", 10) && strncmp (buffer + mode+9, "LO10 ", 10)) {
- fprintf(stderr, "BTFIXUP_INT results in relocation other than R_SPARC_HI22 and R_SPARC_LO10\n%s\n", buffer);
- exit(1);
- }
- break;
- }
- if (!f->setinitval) {
- f->initval = initval;
- if (initvalstr) {
- f->initvalstr = strdup(initvalstr);
- if (!f->initvalstr) fatal();
- }
- f->setinitval = 1;
- } else if (f->initval != initval) {
- fprintf(stderr, "Btfixup %s previously used with initializer %s which doesn't match with current initializer\n%s\n",
- f->name, f->initvalstr ? : "0x00000000", buffer);
- exit(1);
- } else if (initval && strcmp(f->initvalstr, initvalstr)) {
- fprintf(stderr, "Btfixup %s previously used with initializer %s which doesn't match with current initializer.\n"
- "Initializers have to match literally as well.\n%s\n",
- f->name, f->initvalstr, buffer);
- exit(1);
- }
- offset = strtoul(buffer, &q, 16);
- if (q != buffer + mode || (!offset && (mode == 8 ? strncmp (buffer, "00000000 ", 9) : strncmp (buffer, "0000000000000000 ", 17)))) {
- fprintf(stderr, "Malformed relocation address in\n%s\n", buffer);
- exit(1);
- }
- for (k = 0, r = f->rel, rr = &f->rel; r; rr = &r->next, r = r->next, k++)
- if (r->offset == offset && !strcmp(r->sect, sect)) {
- fprintf(stderr, "Ugh. One address has two relocation records\n");
- exit(1);
- }
- *rr = malloc(sizeof(btfixuprel));
- if (!*rr) fatal();
- (*rr)->offset = offset;
- (*rr)->f = NULL;
- if (buffer[nbase+3] == 'f') {
- lastf = f;
- lastfoffset = offset;
- lastfrelno = k;
- } else if (lastfoffset + 4 == offset) {
- (*rr)->f = lastf;
- (*rr)->frel = lastfrelno;
- }
- (*rr)->sect = sect;
- (*rr)->next = NULL;
- }
- printf("! Generated by btfixupprep. Do not edit.\n\n");
- printf("\t.section\t\".data..init\",#alloc,#write\n\t.align\t4\n\n");
- printf("\t.global\t___btfixup_start\n___btfixup_start:\n\n");
- for (i = 0; i < last; i++) {
- f = array + i;
- printf("\t.global\t___%cs_%s\n", f->type, f->name);
- if (f->type == 'f')
- printf("___%cs_%s:\n\t.word 0x%08x,0,0,", f->type, f->name, f->type << 24);
- else
- printf("___%cs_%s:\n\t.word 0x%08x,0,", f->type, f->name, f->type << 24);
- for (j = 0, r = f->rel; r != NULL; j++, r = r->next);
- if (j)
- printf("%d\n\t.word\t", j * 2);
- else
- printf("0\n");
- for (r = f->rel, j--; r != NULL; j--, r = r->next) {
- if (!strcmp (r->sect, ".text"))
- printf ("_stext+0x%08lx", r->offset);
- else if (!strcmp (r->sect, ".init.text"))
- printf ("__init_begin+0x%08lx", r->offset);
- else if (!strcmp (r->sect, "__ksymtab"))
- printf ("__start___ksymtab+0x%08lx", r->offset);
- else if (!strcmp (r->sect, ".fixup"))
- printf ("__start___fixup+0x%08lx", r->offset);
- else
- fatal();
- if (f->type == 'f' || !r->f)
- printf (",0");
- else
- printf (",___fs_%s+0x%08x", r->f->name, (4 + r->frel*2)*4 + 4);
- if (j) printf (",");
- else printf ("\n");
- }
- printf("\n");
- }
- printf("\n\t.global\t___btfixup_end\n___btfixup_end:\n");
- printf("\n\n! Define undefined references\n\n");
- for (i = 0; i < last; i++) {
- f = array + i;
- if (f->type == 'f') {
- printf("\t.global\t___f_%s\n", f->name);
- printf("___f_%s:\n", f->name);
- }
- }
- printf("\tretl\n\t nop\n\n");
- for (i = 0; i < last; i++) {
- f = array + i;
- if (f->type != 'f') {
- if (!f->initval) {
- printf("\t.global\t___%c_%s\n", f->type, f->name);
- printf("___%c_%s = 0\n", f->type, f->name);
- } else {
- printf("\t.global\t___%c_%s__btset_0x%s\n", f->type, f->name, f->initvalstr);
- printf("___%c_%s__btset_0x%s = 0x%08x\n", f->type, f->name, f->initvalstr, f->initval);
- }
- }
- }
- printf("\n\n");
- exit(0);
-}
diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig
index 3c1e85807403..9d8521b8c854 100644
--- a/arch/sparc/configs/sparc64_defconfig
+++ b/arch/sparc/configs/sparc64_defconfig
@@ -5,7 +5,7 @@ CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_LOG_BUF_SHIFT=18
CONFIG_BLK_DEV_INITRD=y
-CONFIG_PERF_COUNTERS=y
+CONFIG_PERF_EVENTS=y
# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
CONFIG_PROFILING=y
diff --git a/arch/sparc/include/asm/asi.h b/arch/sparc/include/asm/asi.h
index b2e3db63a64b..cbb93e5141de 100644
--- a/arch/sparc/include/asm/asi.h
+++ b/arch/sparc/include/asm/asi.h
@@ -112,6 +112,20 @@
#define ASI_M_ACTION 0x4c /* Breakpoint Action Register (GNU/Viking) */
+/* LEON ASI */
+#define ASI_LEON_NOCACHE 0x01
+
+#define ASI_LEON_DCACHE_MISS 0x01
+
+#define ASI_LEON_CACHEREGS 0x02
+#define ASI_LEON_IFLUSH 0x10
+#define ASI_LEON_DFLUSH 0x11
+
+#define ASI_LEON_MMUFLUSH 0x18
+#define ASI_LEON_MMUREGS 0x19
+#define ASI_LEON_BYPASS 0x1c
+#define ASI_LEON_FLUSH_PAGE 0x10
+
/* V9 Architecture mandary ASIs. */
#define ASI_N 0x04 /* Nucleus */
#define ASI_NL 0x0c /* Nucleus, little endian */
diff --git a/arch/sparc/include/asm/asmmacro.h b/arch/sparc/include/asm/asmmacro.h
index a995bf8aba3f..02a172fb193a 100644
--- a/arch/sparc/include/asm/asmmacro.h
+++ b/arch/sparc/include/asm/asmmacro.h
@@ -6,17 +6,6 @@
#ifndef _SPARC_ASMMACRO_H
#define _SPARC_ASMMACRO_H
-#include <asm/btfixup.h>
-#include <asm/asi.h>
-
-#define GET_PROCESSOR4M_ID(reg) \
- rd %tbr, %reg; \
- srl %reg, 12, %reg; \
- and %reg, 3, %reg;
-
-#define GET_PROCESSOR4D_ID(reg) \
- lda [%g0] ASI_M_VIKING_TMP1, %reg;
-
/* All trap entry points _must_ begin with this macro or else you
* lose. It makes sure the kernel has a proper window so that
* c-code can be called.
@@ -31,10 +20,4 @@
/* All traps low-level code here must end with this macro. */
#define RESTORE_ALL b ret_trap_entry; clr %l6;
-/* sun4 probably wants half word accesses to ASI_SEGMAP, while sun4c+
- likes byte accesses. These are to avoid ifdef mania. */
-
-#define lduXa lduba
-#define stXa stba
-
#endif /* !(_SPARC_ASMMACRO_H) */
diff --git a/arch/sparc/include/asm/btfixup.h b/arch/sparc/include/asm/btfixup.h
deleted file mode 100644
index 797722cf69f2..000000000000
--- a/arch/sparc/include/asm/btfixup.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * asm/btfixup.h: Macros for boot time linking.
- *
- * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#ifndef _SPARC_BTFIXUP_H
-#define _SPARC_BTFIXUP_H
-
-#include <linux/init.h>
-
-#ifndef __ASSEMBLY__
-
-#ifdef MODULE
-extern unsigned int ___illegal_use_of_BTFIXUP_SIMM13_in_module(void);
-extern unsigned int ___illegal_use_of_BTFIXUP_SETHI_in_module(void);
-extern unsigned int ___illegal_use_of_BTFIXUP_HALF_in_module(void);
-extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void);
-
-#define BTFIXUP_SIMM13(__name) ___illegal_use_of_BTFIXUP_SIMM13_in_module()
-#define BTFIXUP_HALF(__name) ___illegal_use_of_BTFIXUP_HALF_in_module()
-#define BTFIXUP_SETHI(__name) ___illegal_use_of_BTFIXUP_SETHI_in_module()
-#define BTFIXUP_INT(__name) ___illegal_use_of_BTFIXUP_INT_in_module()
-#define BTFIXUP_BLACKBOX(__name) ___illegal_use_of_BTFIXUP_BLACKBOX_in_module
-
-#else
-
-#define BTFIXUP_SIMM13(__name) ___sf_##__name()
-#define BTFIXUP_HALF(__name) ___af_##__name()
-#define BTFIXUP_SETHI(__name) ___hf_##__name()
-#define BTFIXUP_INT(__name) ((unsigned int)&___i_##__name)
-/* This must be written in assembly and present in a sethi */
-#define BTFIXUP_BLACKBOX(__name) ___b_##__name
-#endif /* MODULE */
-
-/* Fixup call xx */
-
-#define BTFIXUPDEF_CALL(__type, __name, __args...) \
- extern __type ___f_##__name(__args); \
- extern unsigned ___fs_##__name[3];
-#define BTFIXUPDEF_CALL_CONST(__type, __name, __args...) \
- extern __type ___f_##__name(__args) __attribute_const__; \
- extern unsigned ___fs_##__name[3];
-#define BTFIXUP_CALL(__name) ___f_##__name
-
-#define BTFIXUPDEF_BLACKBOX(__name) \
- extern unsigned ___bs_##__name[2];
-
-/* Put bottom 13bits into some register variable */
-
-#define BTFIXUPDEF_SIMM13(__name) \
- static inline unsigned int ___sf_##__name(void) __attribute_const__; \
- extern unsigned ___ss_##__name[2]; \
- static inline unsigned int ___sf_##__name(void) { \
- unsigned int ret; \
- __asm__ ("or %%g0, ___s_" #__name ", %0" : "=r"(ret)); \
- return ret; \
- }
-#define BTFIXUPDEF_SIMM13_INIT(__name,__val) \
- static inline unsigned int ___sf_##__name(void) __attribute_const__; \
- extern unsigned ___ss_##__name[2]; \
- static inline unsigned int ___sf_##__name(void) { \
- unsigned int ret; \
- __asm__ ("or %%g0, ___s_" #__name "__btset_" #__val ", %0" : "=r"(ret));\
- return ret; \
- }
-
-/* Put either bottom 13 bits, or upper 22 bits into some register variable
- * (depending on the value, this will lead into sethi FIX, reg; or
- * mov FIX, reg; )
- */
-
-#define BTFIXUPDEF_HALF(__name) \
- static inline unsigned int ___af_##__name(void) __attribute_const__; \
- extern unsigned ___as_##__name[2]; \
- static inline unsigned int ___af_##__name(void) { \
- unsigned int ret; \
- __asm__ ("or %%g0, ___a_" #__name ", %0" : "=r"(ret)); \
- return ret; \
- }
-#define BTFIXUPDEF_HALF_INIT(__name,__val) \
- static inline unsigned int ___af_##__name(void) __attribute_const__; \
- extern unsigned ___as_##__name[2]; \
- static inline unsigned int ___af_##__name(void) { \
- unsigned int ret; \
- __asm__ ("or %%g0, ___a_" #__name "__btset_" #__val ", %0" : "=r"(ret));\
- return ret; \
- }
-
-/* Put upper 22 bits into some register variable */
-
-#define BTFIXUPDEF_SETHI(__name) \
- static inline unsigned int ___hf_##__name(void) __attribute_const__; \
- extern unsigned ___hs_##__name[2]; \
- static inline unsigned int ___hf_##__name(void) { \
- unsigned int ret; \
- __asm__ ("sethi %%hi(___h_" #__name "), %0" : "=r"(ret)); \
- return ret; \
- }
-#define BTFIXUPDEF_SETHI_INIT(__name,__val) \
- static inline unsigned int ___hf_##__name(void) __attribute_const__; \
- extern unsigned ___hs_##__name[2]; \
- static inline unsigned int ___hf_##__name(void) { \
- unsigned int ret; \
- __asm__ ("sethi %%hi(___h_" #__name "__btset_" #__val "), %0" : \
- "=r"(ret)); \
- return ret; \
- }
-
-/* Put a full 32bit integer into some register variable */
-
-#define BTFIXUPDEF_INT(__name) \
- extern unsigned char ___i_##__name; \
- extern unsigned ___is_##__name[2];
-
-#define BTFIXUPCALL_NORM 0x00000000 /* Always call */
-#define BTFIXUPCALL_NOP 0x01000000 /* Possibly optimize to nop */
-#define BTFIXUPCALL_RETINT(i) (0x90102000|((i) & 0x1fff)) /* Possibly optimize to mov i, %o0 */
-#define BTFIXUPCALL_ORINT(i) (0x90122000|((i) & 0x1fff)) /* Possibly optimize to or %o0, i, %o0 */
-#define BTFIXUPCALL_RETO0 0x01000000 /* Return first parameter, actually a nop */
-#define BTFIXUPCALL_ANDNINT(i) (0x902a2000|((i) & 0x1fff)) /* Possibly optimize to andn %o0, i, %o0 */
-#define BTFIXUPCALL_SWAPO0O1 0xd27a0000 /* Possibly optimize to swap [%o0],%o1 */
-#define BTFIXUPCALL_SWAPO0G0 0xc07a0000 /* Possibly optimize to swap [%o0],%g0 */
-#define BTFIXUPCALL_SWAPG1G2 0xc4784000 /* Possibly optimize to swap [%g1],%g2 */
-#define BTFIXUPCALL_STG0O0 0xc0220000 /* Possibly optimize to st %g0,[%o0] */
-#define BTFIXUPCALL_STO1O0 0xd2220000 /* Possibly optimize to st %o1,[%o0] */
-
-#define BTFIXUPSET_CALL(__name, __addr, __insn) \
- do { \
- ___fs_##__name[0] |= 1; \
- ___fs_##__name[1] = (unsigned long)__addr; \
- ___fs_##__name[2] = __insn; \
- } while (0)
-
-#define BTFIXUPSET_BLACKBOX(__name, __func) \
- do { \
- ___bs_##__name[0] |= 1; \
- ___bs_##__name[1] = (unsigned long)__func; \
- } while (0)
-
-#define BTFIXUPCOPY_CALL(__name, __from) \
- do { \
- ___fs_##__name[0] |= 1; \
- ___fs_##__name[1] = ___fs_##__from[1]; \
- ___fs_##__name[2] = ___fs_##__from[2]; \
- } while (0)
-
-#define BTFIXUPSET_SIMM13(__name, __val) \
- do { \
- ___ss_##__name[0] |= 1; \
- ___ss_##__name[1] = (unsigned)__val; \
- } while (0)
-
-#define BTFIXUPCOPY_SIMM13(__name, __from) \
- do { \
- ___ss_##__name[0] |= 1; \
- ___ss_##__name[1] = ___ss_##__from[1]; \
- } while (0)
-
-#define BTFIXUPSET_HALF(__name, __val) \
- do { \
- ___as_##__name[0] |= 1; \
- ___as_##__name[1] = (unsigned)__val; \
- } while (0)
-
-#define BTFIXUPCOPY_HALF(__name, __from) \
- do { \
- ___as_##__name[0] |= 1; \
- ___as_##__name[1] = ___as_##__from[1]; \
- } while (0)
-
-#define BTFIXUPSET_SETHI(__name, __val) \
- do { \
- ___hs_##__name[0] |= 1; \
- ___hs_##__name[1] = (unsigned)__val; \
- } while (0)
-
-#define BTFIXUPCOPY_SETHI(__name, __from) \
- do { \
- ___hs_##__name[0] |= 1; \
- ___hs_##__name[1] = ___hs_##__from[1]; \
- } while (0)
-
-#define BTFIXUPSET_INT(__name, __val) \
- do { \
- ___is_##__name[0] |= 1; \
- ___is_##__name[1] = (unsigned)__val; \
- } while (0)
-
-#define BTFIXUPCOPY_INT(__name, __from) \
- do { \
- ___is_##__name[0] |= 1; \
- ___is_##__name[1] = ___is_##__from[1]; \
- } while (0)
-
-#define BTFIXUPVAL_CALL(__name) \
- ((unsigned long)___fs_##__name[1])
-
-extern void btfixup(void);
-
-#else /* __ASSEMBLY__ */
-
-#define BTFIXUP_SETHI(__name) %hi(___h_ ## __name)
-#define BTFIXUP_SETHI_INIT(__name,__val) %hi(___h_ ## __name ## __btset_ ## __val)
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* !(_SPARC_BTFIXUP_H) */
diff --git a/arch/sparc/include/asm/cache.h b/arch/sparc/include/asm/cache.h
index 69358b590c91..5bb6991b4857 100644
--- a/arch/sparc/include/asm/cache.h
+++ b/arch/sparc/include/asm/cache.h
@@ -22,118 +22,4 @@
#define __read_mostly __attribute__((__section__(".data..read_mostly")))
-#ifdef CONFIG_SPARC32
-#include <asm/asi.h>
-
-/* Direct access to the instruction cache is provided through and
- * alternate address space. The IDC bit must be off in the ICCR on
- * HyperSparcs for these accesses to work. The code below does not do
- * any checking, the caller must do so. These routines are for
- * diagnostics only, but could end up being useful. Use with care.
- * Also, you are asking for trouble if you execute these in one of the
- * three instructions following a %asr/%psr access or modification.
- */
-
-/* First, cache-tag access. */
-static inline unsigned int get_icache_tag(int setnum, int tagnum)
-{
- unsigned int vaddr, retval;
-
- vaddr = ((setnum&1) << 12) | ((tagnum&0x7f) << 5);
- __asm__ __volatile__("lda [%1] %2, %0\n\t" :
- "=r" (retval) :
- "r" (vaddr), "i" (ASI_M_TXTC_TAG));
- return retval;
-}
-
-static inline void put_icache_tag(int setnum, int tagnum, unsigned int entry)
-{
- unsigned int vaddr;
-
- vaddr = ((setnum&1) << 12) | ((tagnum&0x7f) << 5);
- __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
- "r" (entry), "r" (vaddr), "i" (ASI_M_TXTC_TAG) :
- "memory");
-}
-
-/* Second cache-data access. The data is returned two-32bit quantities
- * at a time.
- */
-static inline void get_icache_data(int setnum, int tagnum, int subblock,
- unsigned int *data)
-{
- unsigned int value1, value2, vaddr;
-
- vaddr = ((setnum&0x1) << 12) | ((tagnum&0x7f) << 5) |
- ((subblock&0x3) << 3);
- __asm__ __volatile__("ldda [%2] %3, %%g2\n\t"
- "or %%g0, %%g2, %0\n\t"
- "or %%g0, %%g3, %1\n\t" :
- "=r" (value1), "=r" (value2) :
- "r" (vaddr), "i" (ASI_M_TXTC_DATA) :
- "g2", "g3");
- data[0] = value1; data[1] = value2;
-}
-
-static inline void put_icache_data(int setnum, int tagnum, int subblock,
- unsigned int *data)
-{
- unsigned int value1, value2, vaddr;
-
- vaddr = ((setnum&0x1) << 12) | ((tagnum&0x7f) << 5) |
- ((subblock&0x3) << 3);
- value1 = data[0]; value2 = data[1];
- __asm__ __volatile__("or %%g0, %0, %%g2\n\t"
- "or %%g0, %1, %%g3\n\t"
- "stda %%g2, [%2] %3\n\t" : :
- "r" (value1), "r" (value2),
- "r" (vaddr), "i" (ASI_M_TXTC_DATA) :
- "g2", "g3", "memory" /* no joke */);
-}
-
-/* Different types of flushes with the ICACHE. Some of the flushes
- * affect both the ICACHE and the external cache. Others only clear
- * the ICACHE entries on the cpu itself. V8's (most) allow
- * granularity of flushes on the packet (element in line), whole line,
- * and entire cache (ie. all lines) level. The ICACHE only flushes are
- * ROSS HyperSparc specific and are in ross.h
- */
-
-/* Flushes which clear out both the on-chip and external caches */
-static inline void flush_ei_page(unsigned int addr)
-{
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
- "r" (addr), "i" (ASI_M_FLUSH_PAGE) :
- "memory");
-}
-
-static inline void flush_ei_seg(unsigned int addr)
-{
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
- "r" (addr), "i" (ASI_M_FLUSH_SEG) :
- "memory");
-}
-
-static inline void flush_ei_region(unsigned int addr)
-{
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
- "r" (addr), "i" (ASI_M_FLUSH_REGION) :
- "memory");
-}
-
-static inline void flush_ei_ctx(unsigned int addr)
-{
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
- "r" (addr), "i" (ASI_M_FLUSH_CTX) :
- "memory");
-}
-
-static inline void flush_ei_user(unsigned int addr)
-{
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
- "r" (addr), "i" (ASI_M_FLUSH_USER) :
- "memory");
-}
-#endif /* CONFIG_SPARC32 */
-
#endif /* !(_SPARC_CACHE_H) */
diff --git a/arch/sparc/include/asm/cacheflush.h b/arch/sparc/include/asm/cacheflush.h
index 049168087b19..f6c4839b8388 100644
--- a/arch/sparc/include/asm/cacheflush.h
+++ b/arch/sparc/include/asm/cacheflush.h
@@ -1,5 +1,9 @@
#ifndef ___ASM_SPARC_CACHEFLUSH_H
#define ___ASM_SPARC_CACHEFLUSH_H
+
+/* flush addr - to allow use of self-modifying code */
+#define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory")
+
#if defined(__sparc__) && defined(__arch64__)
#include <asm/cacheflush_64.h>
#else
diff --git a/arch/sparc/include/asm/cacheflush_32.h b/arch/sparc/include/asm/cacheflush_32.h
index 68431b47a22a..bb014c24f318 100644
--- a/arch/sparc/include/asm/cacheflush_32.h
+++ b/arch/sparc/include/asm/cacheflush_32.h
@@ -1,56 +1,18 @@
#ifndef _SPARC_CACHEFLUSH_H
#define _SPARC_CACHEFLUSH_H
-#include <linux/mm.h> /* Common for other includes */
-// #include <linux/kernel.h> from pgalloc.h
-// #include <linux/sched.h> from pgalloc.h
-
-// #include <asm/page.h>
-#include <asm/btfixup.h>
-
-/*
- * Fine grained cache flushing.
- */
-#ifdef CONFIG_SMP
-
-BTFIXUPDEF_CALL(void, local_flush_cache_all, void)
-BTFIXUPDEF_CALL(void, local_flush_cache_mm, struct mm_struct *)
-BTFIXUPDEF_CALL(void, local_flush_cache_range, struct vm_area_struct *, unsigned long, unsigned long)
-BTFIXUPDEF_CALL(void, local_flush_cache_page, struct vm_area_struct *, unsigned long)
-
-#define local_flush_cache_all() BTFIXUP_CALL(local_flush_cache_all)()
-#define local_flush_cache_mm(mm) BTFIXUP_CALL(local_flush_cache_mm)(mm)
-#define local_flush_cache_range(vma,start,end) BTFIXUP_CALL(local_flush_cache_range)(vma,start,end)
-#define local_flush_cache_page(vma,addr) BTFIXUP_CALL(local_flush_cache_page)(vma,addr)
-
-BTFIXUPDEF_CALL(void, local_flush_page_to_ram, unsigned long)
-BTFIXUPDEF_CALL(void, local_flush_sig_insns, struct mm_struct *, unsigned long)
-
-#define local_flush_page_to_ram(addr) BTFIXUP_CALL(local_flush_page_to_ram)(addr)
-#define local_flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(local_flush_sig_insns)(mm,insn_addr)
-
-extern void smp_flush_cache_all(void);
-extern void smp_flush_cache_mm(struct mm_struct *mm);
-extern void smp_flush_cache_range(struct vm_area_struct *vma,
- unsigned long start,
- unsigned long end);
-extern void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page);
-
-extern void smp_flush_page_to_ram(unsigned long page);
-extern void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr);
-
-#endif /* CONFIG_SMP */
-
-BTFIXUPDEF_CALL(void, flush_cache_all, void)
-BTFIXUPDEF_CALL(void, flush_cache_mm, struct mm_struct *)
-BTFIXUPDEF_CALL(void, flush_cache_range, struct vm_area_struct *, unsigned long, unsigned long)
-BTFIXUPDEF_CALL(void, flush_cache_page, struct vm_area_struct *, unsigned long)
-
-#define flush_cache_all() BTFIXUP_CALL(flush_cache_all)()
-#define flush_cache_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
-#define flush_cache_dup_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
-#define flush_cache_range(vma,start,end) BTFIXUP_CALL(flush_cache_range)(vma,start,end)
-#define flush_cache_page(vma,addr,pfn) BTFIXUP_CALL(flush_cache_page)(vma,addr)
+#include <asm/cachetlb_32.h>
+
+#define flush_cache_all() \
+ sparc32_cachetlb_ops->cache_all()
+#define flush_cache_mm(mm) \
+ sparc32_cachetlb_ops->cache_mm(mm)
+#define flush_cache_dup_mm(mm) \
+ sparc32_cachetlb_ops->cache_mm(mm)
+#define flush_cache_range(vma,start,end) \
+ sparc32_cachetlb_ops->cache_range(vma, start, end)
+#define flush_cache_page(vma,addr,pfn) \
+ sparc32_cachetlb_ops->cache_page(vma, addr)
#define flush_icache_range(start, end) do { } while (0)
#define flush_icache_page(vma, pg) do { } while (0)
@@ -67,11 +29,12 @@ BTFIXUPDEF_CALL(void, flush_cache_page, struct vm_area_struct *, unsigned long)
memcpy(dst, src, len); \
} while (0)
-BTFIXUPDEF_CALL(void, __flush_page_to_ram, unsigned long)
-BTFIXUPDEF_CALL(void, flush_sig_insns, struct mm_struct *, unsigned long)
-
-#define __flush_page_to_ram(addr) BTFIXUP_CALL(__flush_page_to_ram)(addr)
-#define flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(flush_sig_insns)(mm,insn_addr)
+#define __flush_page_to_ram(addr) \
+ sparc32_cachetlb_ops->page_to_ram(addr)
+#define flush_sig_insns(mm,insn_addr) \
+ sparc32_cachetlb_ops->sig_insns(mm, insn_addr)
+#define flush_page_for_dma(addr) \
+ sparc32_cachetlb_ops->page_for_dma(addr)
extern void sparc_flush_page_to_ram(struct page *page);
diff --git a/arch/sparc/include/asm/cacheflush_64.h b/arch/sparc/include/asm/cacheflush_64.h
index 2efea2ff88b7..301736d9e7a1 100644
--- a/arch/sparc/include/asm/cacheflush_64.h
+++ b/arch/sparc/include/asm/cacheflush_64.h
@@ -8,9 +8,6 @@
#include <linux/mm.h>
/* Cache flush operations. */
-
-
-#define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory")
#define flushw_all() __asm__ __volatile__("flushw")
extern void __flushw_user(void);
diff --git a/arch/sparc/include/asm/cachetlb_32.h b/arch/sparc/include/asm/cachetlb_32.h
new file mode 100644
index 000000000000..efb19889a083
--- /dev/null
+++ b/arch/sparc/include/asm/cachetlb_32.h
@@ -0,0 +1,29 @@
+#ifndef _SPARC_CACHETLB_H
+#define _SPARC_CACHETLB_H
+
+struct mm_struct;
+struct vm_area_struct;
+
+struct sparc32_cachetlb_ops {
+ void (*cache_all)(void);
+ void (*cache_mm)(struct mm_struct *);
+ void (*cache_range)(struct vm_area_struct *, unsigned long,
+ unsigned long);
+ void (*cache_page)(struct vm_area_struct *, unsigned long);
+
+ void (*tlb_all)(void);
+ void (*tlb_mm)(struct mm_struct *);
+ void (*tlb_range)(struct vm_area_struct *, unsigned long,
+ unsigned long);
+ void (*tlb_page)(struct vm_area_struct *, unsigned long);
+
+ void (*page_to_ram)(unsigned long);
+ void (*sig_insns)(struct mm_struct *, unsigned long);
+ void (*page_for_dma)(unsigned long);
+};
+extern const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops;
+#ifdef CONFIG_SMP
+extern const struct sparc32_cachetlb_ops *local_ops;
+#endif
+
+#endif /* SPARC_CACHETLB_H */
diff --git a/arch/sparc/include/asm/cmpxchg_32.h b/arch/sparc/include/asm/cmpxchg_32.h
index c786b0a92b51..1fae1a02e3c2 100644
--- a/arch/sparc/include/asm/cmpxchg_32.h
+++ b/arch/sparc/include/asm/cmpxchg_32.h
@@ -11,40 +11,13 @@
#ifndef __ARCH_SPARC_CMPXCHG__
#define __ARCH_SPARC_CMPXCHG__
-#include <asm/btfixup.h>
-
-/* This has special calling conventions */
-#ifndef CONFIG_SMP
-BTFIXUPDEF_CALL(void, ___xchg32, void)
-#endif
-
static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
{
-#ifdef CONFIG_SMP
__asm__ __volatile__("swap [%2], %0"
: "=&r" (val)
: "0" (val), "r" (m)
: "memory");
return val;
-#else
- register unsigned long *ptr asm("g1");
- register unsigned long ret asm("g2");
-
- ptr = (unsigned long *) m;
- ret = val;
-
- /* Note: this is magic and the nop there is
- really needed. */
- __asm__ __volatile__(
- "mov %%o7, %%g4\n\t"
- "call ___f____xchg32\n\t"
- " nop\n\t"
- : "=&r" (ret)
- : "0" (ret), "r" (ptr)
- : "g3", "g4", "g7", "memory", "cc");
-
- return ret;
-#endif
}
extern void __xchg_called_with_bad_pointer(void);
diff --git a/arch/sparc/include/asm/contregs.h b/arch/sparc/include/asm/contregs.h
index 48fa8a4ef357..b8abdfcf5555 100644
--- a/arch/sparc/include/asm/contregs.h
+++ b/arch/sparc/include/asm/contregs.h
@@ -7,28 +7,6 @@
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/
-/* 3=sun3
- 4=sun4 (as in sun4 sysmaint student book)
- c=sun4c (according to davem) */
-
-#define AC_IDPROM 0x00000000 /* 34 ID PROM, R/O, byte, 32 bytes */
-#define AC_PAGEMAP 0x10000000 /* 3 Pagemap R/W, long */
-#define AC_SEGMAP 0x20000000 /* 3 Segment map, byte */
-#define AC_CONTEXT 0x30000000 /* 34c current mmu-context */
-#define AC_SENABLE 0x40000000 /* 34c system dvma/cache/reset enable reg*/
-#define AC_UDVMA_ENB 0x50000000 /* 34 Not used on Sun boards, byte */
-#define AC_BUS_ERROR 0x60000000 /* 34 Not cleared on read, byte. */
-#define AC_SYNC_ERR 0x60000000 /* c fault type */
-#define AC_SYNC_VA 0x60000004 /* c fault virtual address */
-#define AC_ASYNC_ERR 0x60000008 /* c asynchronous fault type */
-#define AC_ASYNC_VA 0x6000000c /* c async fault virtual address */
-#define AC_LEDS 0x70000000 /* 34 Zero turns on LEDs, byte */
-#define AC_CACHETAGS 0x80000000 /* 34c direct access to the VAC tags */
-#define AC_CACHEDDATA 0x90000000 /* 3 c direct access to the VAC data */
-#define AC_UDVMA_MAP 0xD0000000 /* 4 Not used on Sun boards, byte */
-#define AC_VME_VECTOR 0xE0000000 /* 4 For non-Autovector VME, byte */
-#define AC_BOOT_SCC 0xF0000000 /* 34 bypass to access Zilog 8530. byte.*/
-
/* s=Swift, h=Ross_HyperSPARC, v=TI_Viking, t=Tsunami, r=Ross_Cypress */
#define AC_M_PCR 0x0000 /* shv Processor Control Reg */
#define AC_M_CTPR 0x0100 /* shv Context Table Pointer Reg */
diff --git a/arch/sparc/include/asm/cpu_type.h b/arch/sparc/include/asm/cpu_type.h
index 4ca184d95d82..84d7d83b8084 100644
--- a/arch/sparc/include/asm/cpu_type.h
+++ b/arch/sparc/include/asm/cpu_type.h
@@ -5,30 +5,24 @@
* Sparc (general) CPU types
*/
enum sparc_cpu {
- sun4 = 0x00,
- sun4c = 0x01,
- sun4m = 0x02,
- sun4d = 0x03,
- sun4e = 0x04,
- sun4u = 0x05, /* V8 ploos ploos */
- sun_unknown = 0x06,
- ap1000 = 0x07, /* almost a sun4m */
- sparc_leon = 0x08, /* Leon SoC */
+ sun4m = 0x00,
+ sun4d = 0x01,
+ sun4e = 0x02,
+ sun4u = 0x03, /* V8 ploos ploos */
+ sun_unknown = 0x04,
+ ap1000 = 0x05, /* almost a sun4m */
+ sparc_leon = 0x06, /* Leon SoC */
};
#ifdef CONFIG_SPARC32
extern enum sparc_cpu sparc_cpu_model;
-#define ARCH_SUN4C (sparc_cpu_model==sun4c)
-
#define SUN4M_NCPUS 4 /* Architectural limit of sun4m. */
#else
#define sparc_cpu_model sun4u
-/* This cannot ever be a sun4c :) That's just history. */
-#define ARCH_SUN4C 0
#endif
#endif /* __ASM_CPU_TYPE_H */
diff --git a/arch/sparc/include/asm/cpudata_32.h b/arch/sparc/include/asm/cpudata_32.h
index a4c5a938b936..0300d94c25b3 100644
--- a/arch/sparc/include/asm/cpudata_32.h
+++ b/arch/sparc/include/asm/cpudata_32.h
@@ -14,7 +14,6 @@
typedef struct {
unsigned long udelay_val;
unsigned long clock_tick;
- unsigned int multiplier;
unsigned int counter;
#ifdef CONFIG_SMP
unsigned int irq_resched_count;
diff --git a/arch/sparc/include/asm/cypress.h b/arch/sparc/include/asm/cypress.h
deleted file mode 100644
index 95e9772ea394..000000000000
--- a/arch/sparc/include/asm/cypress.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * cypress.h: Cypress module specific definitions and defines.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC_CYPRESS_H
-#define _SPARC_CYPRESS_H
-
-/* Cypress chips have %psr 'impl' of '0001' and 'vers' of '0001'. */
-
-/* The MMU control register fields on the Sparc Cypress 604/605 MMU's.
- *
- * ---------------------------------------------------------------
- * |implvers| MCA | MCM |MV| MID |BM| C|RSV|MR|CM|CL|CE|RSV|NF|ME|
- * ---------------------------------------------------------------
- * 31 24 23-22 21-20 19 18-15 14 13 12 11 10 9 8 7-2 1 0
- *
- * MCA: MultiChip Access -- Used for configuration of multiple
- * CY7C604/605 cache units.
- * MCM: MultiChip Mask -- Again, for multiple cache unit config.
- * MV: MultiChip Valid -- Indicates MCM and MCA have valid settings.
- * MID: ModuleID -- Unique processor ID for MBus transactions. (605 only)
- * BM: Boot Mode -- 0 = not in boot mode, 1 = in boot mode
- * C: Cacheable -- Indicates whether accesses are cacheable while
- * the MMU is off. 0=no 1=yes
- * MR: MemoryReflection -- Indicates whether the bus attached to the
- * MBus supports memory reflection. 0=no 1=yes (605 only)
- * CM: CacheMode -- Indicates whether the cache is operating in write
- * through or copy-back mode. 0=write-through 1=copy-back
- * CL: CacheLock -- Indicates if the entire cache is locked or not.
- * 0=not-locked 1=locked (604 only)
- * CE: CacheEnable -- Is the virtual cache on? 0=no 1=yes
- * NF: NoFault -- Do faults generate traps? 0=yes 1=no
- * ME: MmuEnable -- Is the MMU doing translations? 0=no 1=yes
- */
-
-#define CYPRESS_MCA 0x00c00000
-#define CYPRESS_MCM 0x00300000
-#define CYPRESS_MVALID 0x00080000
-#define CYPRESS_MIDMASK 0x00078000 /* Only on 605 */
-#define CYPRESS_BMODE 0x00004000
-#define CYPRESS_ACENABLE 0x00002000
-#define CYPRESS_MRFLCT 0x00000800 /* Only on 605 */
-#define CYPRESS_CMODE 0x00000400
-#define CYPRESS_CLOCK 0x00000200 /* Only on 604 */
-#define CYPRESS_CENABLE 0x00000100
-#define CYPRESS_NFAULT 0x00000002
-#define CYPRESS_MENABLE 0x00000001
-
-static inline void cypress_flush_page(unsigned long page)
-{
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
- "r" (page), "i" (ASI_M_FLUSH_PAGE));
-}
-
-static inline void cypress_flush_segment(unsigned long addr)
-{
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
- "r" (addr), "i" (ASI_M_FLUSH_SEG));
-}
-
-static inline void cypress_flush_region(unsigned long addr)
-{
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
- "r" (addr), "i" (ASI_M_FLUSH_REGION));
-}
-
-static inline void cypress_flush_context(void)
-{
- __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : :
- "i" (ASI_M_FLUSH_CTX));
-}
-
-/* XXX Displacement flushes for buggy chips and initial testing
- * XXX go here.
- */
-
-#endif /* !(_SPARC_CYPRESS_H) */
diff --git a/arch/sparc/include/asm/dma.h b/arch/sparc/include/asm/dma.h
index b554927bbaf6..3d434ef5eae3 100644
--- a/arch/sparc/include/asm/dma.h
+++ b/arch/sparc/include/asm/dma.h
@@ -92,27 +92,31 @@ extern int isa_dma_bridge_buggy;
#ifdef CONFIG_SPARC32
/* Routines for data transfer buffers. */
-BTFIXUPDEF_CALL(char *, mmu_lockarea, char *, unsigned long)
-BTFIXUPDEF_CALL(void, mmu_unlockarea, char *, unsigned long)
-
-#define mmu_lockarea(vaddr,len) BTFIXUP_CALL(mmu_lockarea)(vaddr,len)
-#define mmu_unlockarea(vaddr,len) BTFIXUP_CALL(mmu_unlockarea)(vaddr,len)
-
-struct page;
struct device;
struct scatterlist;
-/* These are implementations for sbus_map_sg/sbus_unmap_sg... collapse later */
-BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, struct device *, char *, unsigned long)
-BTFIXUPDEF_CALL(void, mmu_get_scsi_sgl, struct device *, struct scatterlist *, int)
-BTFIXUPDEF_CALL(void, mmu_release_scsi_one, struct device *, __u32, unsigned long)
-BTFIXUPDEF_CALL(void, mmu_release_scsi_sgl, struct device *, struct scatterlist *, int)
-
-#define mmu_get_scsi_one(dev,vaddr,len) BTFIXUP_CALL(mmu_get_scsi_one)(dev,vaddr,len)
-#define mmu_get_scsi_sgl(dev,sg,sz) BTFIXUP_CALL(mmu_get_scsi_sgl)(dev,sg,sz)
-#define mmu_release_scsi_one(dev,vaddr,len) BTFIXUP_CALL(mmu_release_scsi_one)(dev,vaddr,len)
-#define mmu_release_scsi_sgl(dev,sg,sz) BTFIXUP_CALL(mmu_release_scsi_sgl)(dev,sg,sz)
-
+struct sparc32_dma_ops {
+ __u32 (*get_scsi_one)(struct device *, char *, unsigned long);
+ void (*get_scsi_sgl)(struct device *, struct scatterlist *, int);
+ void (*release_scsi_one)(struct device *, __u32, unsigned long);
+ void (*release_scsi_sgl)(struct device *, struct scatterlist *,int);
+#ifdef CONFIG_SBUS
+ int (*map_dma_area)(struct device *, dma_addr_t *, unsigned long, unsigned long, int);
+ void (*unmap_dma_area)(struct device *, unsigned long, int);
+#endif
+};
+extern const struct sparc32_dma_ops *sparc32_dma_ops;
+
+#define mmu_get_scsi_one(dev,vaddr,len) \
+ sparc32_dma_ops->get_scsi_one(dev, vaddr, len)
+#define mmu_get_scsi_sgl(dev,sg,sz) \
+ sparc32_dma_ops->get_scsi_sgl(dev, sg, sz)
+#define mmu_release_scsi_one(dev,vaddr,len) \
+ sparc32_dma_ops->release_scsi_one(dev, vaddr,len)
+#define mmu_release_scsi_sgl(dev,sg,sz) \
+ sparc32_dma_ops->release_scsi_sgl(dev, sg, sz)
+
+#ifdef CONFIG_SBUS
/*
* mmu_map/unmap are provided by iommu/iounit; Invalid to call on IIep.
*
@@ -123,17 +127,17 @@ BTFIXUPDEF_CALL(void, mmu_release_scsi_sgl, struct device *, struct scatterlist
* Second mapping is for device visible address, or "bus" address.
* The bus address is returned at '*pba'.
*
- * These functions seem distinct, but are hard to split. On sun4c,
- * at least for now, 'a' is equal to bus address, and retured in *pba.
+ * These functions seem distinct, but are hard to split.
* On sun4m, page attributes depend on the CPU type, so we have to
* know if we are mapping RAM or I/O, so it has to be an additional argument
* to a separate mapping function for CPU visible mappings.
*/
-BTFIXUPDEF_CALL(int, mmu_map_dma_area, struct device *, dma_addr_t *, unsigned long, unsigned long, int len)
-BTFIXUPDEF_CALL(void, mmu_unmap_dma_area, struct device *, unsigned long busa, int len)
+#define sbus_map_dma_area(dev,pba,va,a,len) \
+ sparc32_dma_ops->map_dma_area(dev, pba, va, a, len)
+#define sbus_unmap_dma_area(dev,ba,len) \
+ sparc32_dma_ops->unmap_dma_area(dev, ba, len)
+#endif /* CONFIG_SBUS */
-#define mmu_map_dma_area(dev,pba,va,a,len) BTFIXUP_CALL(mmu_map_dma_area)(dev,pba,va,a,len)
-#define mmu_unmap_dma_area(dev,ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(dev,ba,len)
#endif
#endif /* !(_ASM_SPARC_DMA_H) */
diff --git a/arch/sparc/include/asm/elf_32.h b/arch/sparc/include/asm/elf_32.h
index 4269ca6ad18a..2d4d755cba9e 100644
--- a/arch/sparc/include/asm/elf_32.h
+++ b/arch/sparc/include/asm/elf_32.h
@@ -118,16 +118,9 @@ typedef struct {
instruction set this cpu supports. This can NOT be done in userspace
on Sparc. */
-/* Sun4c has none of the capabilities, most sun4m's have them all.
- * XXX This is gross, set some global variable at boot time. -DaveM
- */
-#define ELF_HWCAP ((ARCH_SUN4C) ? 0 : \
- (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \
- HWCAP_SPARC_SWAP | \
- ((srmmu_modtype != Cypress && \
- srmmu_modtype != Cypress_vE && \
- srmmu_modtype != Cypress_vD) ? \
- HWCAP_SPARC_MULDIV : 0)))
+/* Most sun4m's have them all. */
+#define ELF_HWCAP (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \
+ HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV)
/* This yields a string that ld.so will use to load implementation
specific libraries for optimization. This is more specific in
diff --git a/arch/sparc/include/asm/floppy_32.h b/arch/sparc/include/asm/floppy_32.h
index 698d9559fead..fb3f16954c69 100644
--- a/arch/sparc/include/asm/floppy_32.h
+++ b/arch/sparc/include/asm/floppy_32.h
@@ -12,7 +12,6 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/idprom.h>
-#include <asm/machines.h>
#include <asm/oplib.h>
#include <asm/auxio.h>
#include <asm/irq.h>
@@ -103,25 +102,13 @@ static struct sun_floppy_ops sun_fdops;
/* Routines unique to each controller type on a Sun. */
static void sun_set_dor(unsigned char value, int fdc_82077)
{
- if (sparc_cpu_model == sun4c) {
- unsigned int bits = 0;
- if (value & 0x10)
- bits |= AUXIO_FLPY_DSEL;
- if ((value & 0x80) == 0)
- bits |= AUXIO_FLPY_EJCT;
- set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT));
- }
- if (fdc_82077) {
+ if (fdc_82077)
sun_fdc->dor_82077 = value;
- }
}
static unsigned char sun_read_dir(void)
{
- if (sparc_cpu_model == sun4c)
- return (get_auxio() & AUXIO_FLPY_DCHG) ? 0x80 : 0;
- else
- return sun_fdc->dir_82077;
+ return sun_fdc->dir_82077;
}
static unsigned char sun_82072_fd_inb(int port)
@@ -242,10 +229,7 @@ static inline void virtual_dma_init(void)
static inline void sun_fd_disable_dma(void)
{
doing_pdma = 0;
- if (pdma_base) {
- mmu_unlockarea(pdma_base, pdma_areasize);
- pdma_base = NULL;
- }
+ pdma_base = NULL;
}
static inline void sun_fd_set_dma_mode(int mode)
@@ -275,7 +259,6 @@ static inline void sun_fd_set_dma_count(int length)
static inline void sun_fd_enable_dma(void)
{
- pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
pdma_base = pdma_vaddr;
pdma_areasize = pdma_size;
}
@@ -301,38 +284,36 @@ static int sun_floppy_init(void)
{
struct platform_device *op;
struct device_node *dp;
+ struct resource r;
char state[128];
- phandle tnode, fd_node;
+ phandle fd_node;
+ phandle tnode;
int num_regs;
- struct resource r;
use_virtual_dma = 1;
/* Forget it if we aren't on a machine that could possibly
* ever have a floppy drive.
*/
- if((sparc_cpu_model != sun4c && sparc_cpu_model != sun4m) ||
- ((idprom->id_machtype == (SM_SUN4C | SM_4C_SLC)) ||
- (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC)))) {
+ if (sparc_cpu_model != sun4m) {
/* We certainly don't have a floppy controller. */
goto no_sun_fdc;
}
/* Well, try to find one. */
tnode = prom_getchild(prom_root_node);
fd_node = prom_searchsiblings(tnode, "obio");
- if(fd_node != 0) {
+ if (fd_node != 0) {
tnode = prom_getchild(fd_node);
fd_node = prom_searchsiblings(tnode, "SUNW,fdtwo");
} else {
fd_node = prom_searchsiblings(tnode, "fd");
}
- if(fd_node == 0) {
+ if (fd_node == 0) {
goto no_sun_fdc;
}
/* The sun4m lets us know if the controller is actually usable. */
- if(sparc_cpu_model == sun4m &&
- prom_getproperty(fd_node, "status", state, sizeof(state)) != -1) {
+ if (prom_getproperty(fd_node, "status", state, sizeof(state)) != -1) {
if(!strcmp(state, "disabled")) {
goto no_sun_fdc;
}
@@ -343,12 +324,12 @@ static int sun_floppy_init(void)
memset(&r, 0, sizeof(r));
r.flags = fd_regs[0].which_io;
r.start = fd_regs[0].phys_addr;
- sun_fdc = (struct sun_flpy_controller *)
- of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy");
+ sun_fdc = of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy");
/* Look up irq in platform_device.
* We try "SUNW,fdtwo" and "fd"
*/
+ op = NULL;
for_each_node_by_name(dp, "SUNW,fdtwo") {
op = of_find_device_by_node(dp);
if (op)
@@ -367,7 +348,7 @@ static int sun_floppy_init(void)
FLOPPY_IRQ = op->archdata.irqs[0];
/* Last minute sanity check... */
- if(sun_fdc->status_82072 == 0xff) {
+ if (sun_fdc->status_82072 == 0xff) {
sun_fdc = NULL;
goto no_sun_fdc;
}
diff --git a/arch/sparc/include/asm/floppy_64.h b/arch/sparc/include/asm/floppy_64.h
index bcef1f5a2a6d..e204f902e6c9 100644
--- a/arch/sparc/include/asm/floppy_64.h
+++ b/arch/sparc/include/asm/floppy_64.h
@@ -161,10 +161,7 @@ unsigned long pdma_areasize;
static void sun_fd_disable_dma(void)
{
doing_pdma = 0;
- if (pdma_base) {
- mmu_unlockarea(pdma_base, pdma_areasize);
- pdma_base = NULL;
- }
+ pdma_base = NULL;
}
static void sun_fd_set_dma_mode(int mode)
@@ -194,7 +191,6 @@ static void sun_fd_set_dma_count(int length)
static void sun_fd_enable_dma(void)
{
- pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
pdma_base = pdma_vaddr;
pdma_areasize = pdma_size;
}
diff --git a/arch/sparc/include/asm/head_32.h b/arch/sparc/include/asm/head_32.h
index 7c35491a8b53..a76874838f61 100644
--- a/arch/sparc/include/asm/head_32.h
+++ b/arch/sparc/include/asm/head_32.h
@@ -2,15 +2,8 @@
#define __SPARC_HEAD_H
#define KERNBASE 0xf0000000 /* First address the kernel will eventually be */
-#define LOAD_ADDR 0x4000 /* prom jumps to us here unless this is elf /boot */
-#define SUN4C_SEGSZ (1 << 18)
-#define SRMMU_L1_KBASE_OFFSET ((KERNBASE>>24)<<2) /* Used in boot remapping. */
-#define INTS_ENAB 0x01 /* entry.S uses this. */
-
-#define SUN4_PROM_VECTOR 0xFFE81000 /* SUN4 PROM needs to be hardwired */
#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */
-#define NOP_INSN 0x01000000 /* Used to patch sparc_save_state */
/* Here are some trap goodies */
@@ -18,9 +11,7 @@
#define TRAP_ENTRY(type, label) \
rd %psr, %l0; b label; rd %wim, %l3; nop;
-/* Data/text faults. Defaults to sun4c version at boot time. */
-#define SPARC_TFAULT rd %psr, %l0; rd %wim, %l3; b sun4c_fault; mov 1, %l7;
-#define SPARC_DFAULT rd %psr, %l0; rd %wim, %l3; b sun4c_fault; mov 0, %l7;
+/* Data/text faults */
#define SRMMU_TFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 1, %l7;
#define SRMMU_DFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 0, %l7;
@@ -80,16 +71,6 @@
#define TRAP_ENTRY_INTERRUPT(int_level) \
mov int_level, %l7; rd %psr, %l0; b real_irq_entry; rd %wim, %l3;
-/* NMI's (Non Maskable Interrupts) are special, you can't keep them
- * from coming in, and basically if you get one, the shows over. ;(
- * On the sun4c they are usually asynchronous memory errors, on the
- * the sun4m they could be either due to mem errors or a software
- * initiated interrupt from the prom/kern on an SMP box saying "I
- * command you to do CPU tricks, read your mailbox for more info."
- */
-#define NMI_TRAP \
- rd %wim, %l3; b linux_trap_nmi_sun4c; mov %psr, %l0; nop;
-
/* Window overflows/underflows are special and we need to try to be as
* efficient as possible here....
*/
diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h
index a4e457f003ed..07659124c140 100644
--- a/arch/sparc/include/asm/leon.h
+++ b/arch/sparc/include/asm/leon.h
@@ -10,19 +10,6 @@
#ifdef CONFIG_SPARC_LEON
-#define ASI_LEON_NOCACHE 0x01
-
-#define ASI_LEON_DCACHE_MISS 0x1
-
-#define ASI_LEON_CACHEREGS 0x02
-#define ASI_LEON_IFLUSH 0x10
-#define ASI_LEON_DFLUSH 0x11
-
-#define ASI_LEON_MMUFLUSH 0x18
-#define ASI_LEON_MMUREGS 0x19
-#define ASI_LEON_BYPASS 0x1c
-#define ASI_LEON_FLUSH_PAGE 0x10
-
/* mmu register access, ASI_LEON_MMUREGS */
#define LEON_CNR_CTRL 0x000
#define LEON_CNR_CTXP 0x100
@@ -57,29 +44,6 @@
#define LEON_IRQMASK_R 0x0000fffe /* bit 15- 1 of lregs.irqmask */
#define LEON_IRQPRIO_R 0xfffe0000 /* bit 31-17 of lregs.irqmask */
-/* leon uart register definitions */
-#define LEON_OFF_UDATA 0x0
-#define LEON_OFF_USTAT 0x4
-#define LEON_OFF_UCTRL 0x8
-#define LEON_OFF_USCAL 0xc
-
-#define LEON_UCTRL_RE 0x01
-#define LEON_UCTRL_TE 0x02
-#define LEON_UCTRL_RI 0x04
-#define LEON_UCTRL_TI 0x08
-#define LEON_UCTRL_PS 0x10
-#define LEON_UCTRL_PE 0x20
-#define LEON_UCTRL_FL 0x40
-#define LEON_UCTRL_LB 0x80
-
-#define LEON_USTAT_DR 0x01
-#define LEON_USTAT_TS 0x02
-#define LEON_USTAT_TH 0x04
-#define LEON_USTAT_BR 0x08
-#define LEON_USTAT_OV 0x10
-#define LEON_USTAT_PE 0x20
-#define LEON_USTAT_FE 0x40
-
#define LEON_MCFG2_SRAMDIS 0x00002000
#define LEON_MCFG2_SDRAMEN 0x00004000
#define LEON_MCFG2_SRAMBANKSZ 0x00001e00 /* [12-9] */
@@ -89,8 +53,6 @@
#define LEON_TCNT0_MASK 0x7fffff
-#define LEON_USTAT_ERROR (LEON_USTAT_OV | LEON_USTAT_PE | LEON_USTAT_FE)
-/* no break yet */
#define ASI_LEON3_SYSCTRL 0x02
#define ASI_LEON3_SYSCTRL_ICFG 0x08
@@ -278,18 +240,11 @@ static inline int sparc_leon3_cpuid(void)
#define LEON2_CFG_SSIZE_MASK 0x00007000UL
#ifndef __ASSEMBLY__
-extern unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr);
-extern void leon_flush_icache_all(void);
-extern void leon_flush_dcache_all(void);
-extern void leon_flush_cache_all(void);
-extern void leon_flush_tlb_all(void);
-extern int leon_flush_during_switch;
-extern int leon_flush_needed(void);
-
struct vm_area_struct;
+
+extern unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr);
extern void leon_flush_icache_all(void);
extern void leon_flush_dcache_all(void);
-extern void leon_flush_pcache_all(struct vm_area_struct *vma, unsigned long page);
extern void leon_flush_cache_all(void);
extern void leon_flush_tlb_all(void);
extern int leon_flush_during_switch;
@@ -315,28 +270,19 @@ struct leon2_cacheregs {
#include <linux/interrupt.h>
struct device_node;
+struct task_struct;
extern unsigned int leon_build_device_irq(unsigned int real_irq,
irq_flow_handler_t flow_handler,
const char *name, int do_ack);
extern void leon_update_virq_handling(unsigned int virq,
irq_flow_handler_t flow_handler,
const char *name, int do_ack);
-extern void leon_clear_clock_irq(void);
-extern void leon_load_profile_irq(int cpu, unsigned int limit);
-extern void leon_init_timers(irq_handler_t counter_fn);
-extern void leon_clear_clock_irq(void);
-extern void leon_load_profile_irq(int cpu, unsigned int limit);
+extern void leon_init_timers(void);
extern void leon_trans_init(struct device_node *dp);
extern void leon_node_init(struct device_node *dp, struct device_node ***nextp);
-extern void leon_init_IRQ(void);
-extern void leon_init(void);
-extern unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr);
extern void init_leon(void);
extern void poke_leonsparc(void);
extern void leon3_getCacheRegs(struct leon3_cacheregs *regs);
-extern int leon_flush_needed(void);
-extern void leon_switch_mm(void);
-extern int srmmu_swprobe_trace;
extern int leon3_ticker_irq;
#ifdef CONFIG_SMP
@@ -344,7 +290,7 @@ extern int leon_smp_nrcpus(void);
extern void leon_clear_profile_irq(int cpu);
extern void leon_smp_done(void);
extern void leon_boot_cpus(void);
-extern int leon_boot_one_cpu(int i);
+extern int leon_boot_one_cpu(int i, struct task_struct *);
void leon_init_smp(void);
extern void cpu_idle(void);
extern void init_IRQ(void);
@@ -380,7 +326,7 @@ extern int leon_ipi_irq;
#define init_leon() do {} while (0)
#define leon_smp_done() do {} while (0)
#define leon_boot_cpus() do {} while (0)
-#define leon_boot_one_cpu(i) 1
+#define leon_boot_one_cpu(i, t) 1
#define leon_init_smp() do {} while (0)
#endif /* !defined(CONFIG_SPARC_LEON) */
diff --git a/arch/sparc/include/asm/machines.h b/arch/sparc/include/asm/machines.h
index cd9c099567e4..fd6ddb05d1b7 100644
--- a/arch/sparc/include/asm/machines.h
+++ b/arch/sparc/include/asm/machines.h
@@ -12,11 +12,6 @@ struct Sun_Machine_Models {
unsigned char id_machtype;
};
-/* Current number of machines we know about that has an IDPROM
- * machtype entry including one entry for the 0x80 OBP machines.
- */
-#define NUM_SUN_MACHINES 16
-
/* The machine type in the idprom area looks like this:
*
* ---------------
@@ -24,36 +19,20 @@ struct Sun_Machine_Models {
* ---------------
* 7 4 3 0
*
- * The ARCH field determines the architecture line (sun4, sun4c, etc).
+ * The ARCH field determines the architecture line (sun4m, etc).
* The MACH field determines the machine make within that architecture.
*/
#define SM_ARCH_MASK 0xf0
-#define SM_SUN4 0x20
#define M_LEON 0x30
-#define SM_SUN4C 0x50
#define SM_SUN4M 0x70
#define SM_SUN4M_OBP 0x80
#define SM_TYP_MASK 0x0f
-/* Sun4 machines */
-#define SM_4_260 0x01 /* Sun 4/200 series */
-#define SM_4_110 0x02 /* Sun 4/100 series */
-#define SM_4_330 0x03 /* Sun 4/300 series */
-#define SM_4_470 0x04 /* Sun 4/400 series */
/* Leon machines */
#define M_LEON3_SOC 0x02 /* Leon3 SoC */
-/* Sun4c machines Full Name - PROM NAME */
-#define SM_4C_SS1 0x01 /* Sun4c SparcStation 1 - Sun 4/60 */
-#define SM_4C_IPC 0x02 /* Sun4c SparcStation IPC - Sun 4/40 */
-#define SM_4C_SS1PLUS 0x03 /* Sun4c SparcStation 1+ - Sun 4/65 */
-#define SM_4C_SLC 0x04 /* Sun4c SparcStation SLC - Sun 4/20 */
-#define SM_4C_SS2 0x05 /* Sun4c SparcStation 2 - Sun 4/75 */
-#define SM_4C_ELC 0x06 /* Sun4c SparcStation ELC - Sun 4/25 */
-#define SM_4C_IPX 0x07 /* Sun4c SparcStation IPX - Sun 4/50 */
-
/* Sun4m machines, these predate the OpenBoot. These values only mean
* something if the value in the ARCH field is SM_SUN4M, if it is
* SM_SUN4M_OBP then you have the following situation:
diff --git a/arch/sparc/include/asm/mbus.h b/arch/sparc/include/asm/mbus.h
index 69f07a022ee6..14128bcc5821 100644
--- a/arch/sparc/include/asm/mbus.h
+++ b/arch/sparc/include/asm/mbus.h
@@ -8,14 +8,10 @@
#define _SPARC_MBUS_H
#include <asm/ross.h> /* HyperSparc stuff */
-#include <asm/cypress.h> /* Cypress Chips */
#include <asm/viking.h> /* Ugh, bug city... */
enum mbus_module {
HyperSparc = 0,
- Cypress = 1,
- Cypress_vE = 2,
- Cypress_vD = 3,
Swift_ok = 4,
Swift_bad_c = 5,
Swift_lots_o_bugs = 6,
diff --git a/arch/sparc/include/asm/memreg.h b/arch/sparc/include/asm/memreg.h
deleted file mode 100644
index 845ad2b39183..000000000000
--- a/arch/sparc/include/asm/memreg.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef _SPARC_MEMREG_H
-#define _SPARC_MEMREG_H
-/* memreg.h: Definitions of the values found in the synchronous
- * and asynchronous memory error registers when a fault
- * occurs on the sun4c.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-/* First the synchronous error codes, these are usually just
- * normal page faults.
- */
-
-#define SUN4C_SYNC_WDRESET 0x0001 /* watchdog reset */
-#define SUN4C_SYNC_SIZE 0x0002 /* bad access size? whuz this? */
-#define SUN4C_SYNC_PARITY 0x0008 /* bad ram chips caused a parity error */
-#define SUN4C_SYNC_SBUS 0x0010 /* the SBUS had some problems... */
-#define SUN4C_SYNC_NOMEM 0x0020 /* translation to non-existent ram */
-#define SUN4C_SYNC_PROT 0x0040 /* access violated pte protections */
-#define SUN4C_SYNC_NPRESENT 0x0080 /* pte said that page was not present */
-#define SUN4C_SYNC_BADWRITE 0x8000 /* while writing something went bogus */
-
-#define SUN4C_SYNC_BOLIXED \
- (SUN4C_SYNC_WDRESET | SUN4C_SYNC_SIZE | SUN4C_SYNC_SBUS | \
- SUN4C_SYNC_NOMEM | SUN4C_SYNC_PARITY)
-
-/* Now the asynchronous error codes, these are almost always produced
- * by the cache writing things back to memory and getting a bad translation.
- * Bad DVMA transactions can cause these faults too.
- */
-
-#define SUN4C_ASYNC_BADDVMA 0x0010 /* error during DVMA access */
-#define SUN4C_ASYNC_NOMEM 0x0020 /* write back pointed to bad phys addr */
-#define SUN4C_ASYNC_BADWB 0x0080 /* write back points to non-present page */
-
-/* Memory parity error register with associated bit constants. */
-#ifndef __ASSEMBLY__
-extern __volatile__ unsigned long __iomem *sun4c_memerr_reg;
-#endif
-
-#define SUN4C_MPE_ERROR 0x80 /* Parity error detected. (ro) */
-#define SUN4C_MPE_MULTI 0x40 /* Multiple parity errors detected. (ro) */
-#define SUN4C_MPE_TEST 0x20 /* Write inverse parity. (rw) */
-#define SUN4C_MPE_CHECK 0x10 /* Enable parity checking. (rw) */
-#define SUN4C_MPE_ERR00 0x08 /* Parity error in bits 0-7. (ro) */
-#define SUN4C_MPE_ERR08 0x04 /* Parity error in bits 8-15. (ro) */
-#define SUN4C_MPE_ERR16 0x02 /* Parity error in bits 16-23. (ro) */
-#define SUN4C_MPE_ERR24 0x01 /* Parity error in bits 24-31. (ro) */
-#define SUN4C_MPE_ERRS 0x0F /* Bit mask for the error bits. (ro) */
-
-#endif /* !(_SPARC_MEMREG_H) */
diff --git a/arch/sparc/include/asm/mmu_context_32.h b/arch/sparc/include/asm/mmu_context_32.h
index 671a997b9e69..01456c900720 100644
--- a/arch/sparc/include/asm/mmu_context_32.h
+++ b/arch/sparc/include/asm/mmu_context_32.h
@@ -1,8 +1,6 @@
#ifndef __SPARC_MMU_CONTEXT_H
#define __SPARC_MMU_CONTEXT_H
-#include <asm/btfixup.h>
-
#ifndef __ASSEMBLY__
#include <asm-generic/mm_hooks.h>
@@ -23,14 +21,11 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
* all the page tables have been flushed. Our job is to destroy
* any remaining processor-specific state.
*/
-BTFIXUPDEF_CALL(void, destroy_context, struct mm_struct *)
-
-#define destroy_context(mm) BTFIXUP_CALL(destroy_context)(mm)
+void destroy_context(struct mm_struct *mm);
/* Switch the current MM context. */
-BTFIXUPDEF_CALL(void, switch_mm, struct mm_struct *, struct mm_struct *, struct task_struct *)
-
-#define switch_mm(old_mm, mm, tsk) BTFIXUP_CALL(switch_mm)(old_mm, mm, tsk)
+void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm,
+ struct task_struct *tsk);
#define deactivate_mm(tsk,mm) do { } while (0)
diff --git a/arch/sparc/include/asm/obio.h b/arch/sparc/include/asm/obio.h
index 4ade0c8a2c79..910c1d9af1f8 100644
--- a/arch/sparc/include/asm/obio.h
+++ b/arch/sparc/include/asm/obio.h
@@ -220,19 +220,6 @@ static inline void cc_set_igen(unsigned gen)
"i" (ASI_M_MXCC));
}
-/* +-------+-------------+-----------+------------------------------------+
- * | bcast | devid | sid | levels mask |
- * +-------+-------------+-----------+------------------------------------+
- * 31 30 23 22 15 14 0
- */
-#define IGEN_MESSAGE(bcast, devid, sid, levels) \
- (((bcast) << 31) | ((devid) << 23) | ((sid) << 15) | (levels))
-
-static inline void sun4d_send_ipi(int cpu, int level)
-{
- cc_set_igen(IGEN_MESSAGE(0, cpu << 3, 6 + ((level >> 1) & 7), 1 << (level - 1)));
-}
-
#endif /* !__ASSEMBLY__ */
#endif /* !(_SPARC_OBIO_H) */
diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h
index 71e5e9aeb67e..27517879a6c2 100644
--- a/arch/sparc/include/asm/oplib_32.h
+++ b/arch/sparc/include/asm/oplib_32.h
@@ -105,14 +105,6 @@ extern void prom_write(const char *buf, unsigned int len);
extern int prom_startcpu(int cpunode, struct linux_prom_registers *context_table,
int context, char *program_counter);
-/* Sun4/sun4c specific memory-management startup hook. */
-
-/* Map the passed segment in the given context at the passed
- * virtual address.
- */
-extern void prom_putsegment(int context, unsigned long virt_addr,
- int physical_segment);
-
/* Initialize the memory lists based upon the prom version. */
void prom_meminit(void);
diff --git a/arch/sparc/include/asm/page_32.h b/arch/sparc/include/asm/page_32.h
index bb5c2ac4055d..fab78a308ebf 100644
--- a/arch/sparc/include/asm/page_32.h
+++ b/arch/sparc/include/asm/page_32.h
@@ -14,8 +14,6 @@
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
-#include <asm/btfixup.h>
-
#ifndef __ASSEMBLY__
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
@@ -45,12 +43,6 @@ struct sparc_phys_banks {
extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1];
-/* Cache alias structure. Entry is valid if context != -1. */
-struct cache_palias {
- unsigned long vaddr;
- int context;
-};
-
/* passing structs on the Sparc slow us down tremendously... */
/* #define STRICT_MM_TYPECHECKS */
@@ -116,10 +108,7 @@ typedef unsigned long iopgprot_t;
typedef struct page *pgtable_t;
extern unsigned long sparc_unmapped_base;
-
-BTFIXUPDEF_SETHI(sparc_unmapped_base)
-
-#define TASK_UNMAPPED_BASE BTFIXUP_SETHI(sparc_unmapped_base)
+#define TASK_UNMAPPED_BASE sparc_unmapped_base
#else /* !(__ASSEMBLY__) */
diff --git a/arch/sparc/include/asm/pgalloc_32.h b/arch/sparc/include/asm/pgalloc_32.h
index ca2b34456c4b..e5b169b46d21 100644
--- a/arch/sparc/include/asm/pgalloc_32.h
+++ b/arch/sparc/include/asm/pgalloc_32.h
@@ -4,8 +4,10 @@
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <asm/pgtsrmmu.h>
+#include <asm/pgtable.h>
+#include <asm/vaddrs.h>
#include <asm/page.h>
-#include <asm/btfixup.h>
struct page;
@@ -15,54 +17,74 @@ extern struct pgtable_cache_struct {
unsigned long pgtable_cache_sz;
unsigned long pgd_cache_sz;
} pgt_quicklists;
+
+unsigned long srmmu_get_nocache(int size, int align);
+void srmmu_free_nocache(unsigned long vaddr, int size);
+
#define pgd_quicklist (pgt_quicklists.pgd_cache)
#define pmd_quicklist ((unsigned long *)0)
#define pte_quicklist (pgt_quicklists.pte_cache)
#define pgtable_cache_size (pgt_quicklists.pgtable_cache_sz)
#define pgd_cache_size (pgt_quicklists.pgd_cache_sz)
-extern void check_pgt_cache(void);
-BTFIXUPDEF_CALL(void, do_check_pgt_cache, int, int)
-#define do_check_pgt_cache(low,high) BTFIXUP_CALL(do_check_pgt_cache)(low,high)
-
-BTFIXUPDEF_CALL(pgd_t *, get_pgd_fast, void)
-#define get_pgd_fast() BTFIXUP_CALL(get_pgd_fast)()
+#define check_pgt_cache() do { } while (0)
-BTFIXUPDEF_CALL(void, free_pgd_fast, pgd_t *)
-#define free_pgd_fast(pgd) BTFIXUP_CALL(free_pgd_fast)(pgd)
+pgd_t *get_pgd_fast(void);
+static inline void free_pgd_fast(pgd_t *pgd)
+{
+ srmmu_free_nocache((unsigned long)pgd, SRMMU_PGD_TABLE_SIZE);
+}
#define pgd_free(mm, pgd) free_pgd_fast(pgd)
#define pgd_alloc(mm) get_pgd_fast()
-BTFIXUPDEF_CALL(void, pgd_set, pgd_t *, pmd_t *)
-#define pgd_set(pgdp,pmdp) BTFIXUP_CALL(pgd_set)(pgdp,pmdp)
+static inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp)
+{
+ unsigned long pa = __nocache_pa((unsigned long)pmdp);
+
+ set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (pa >> 4)));
+}
+
#define pgd_populate(MM, PGD, PMD) pgd_set(PGD, PMD)
-BTFIXUPDEF_CALL(pmd_t *, pmd_alloc_one, struct mm_struct *, unsigned long)
-#define pmd_alloc_one(mm, address) BTFIXUP_CALL(pmd_alloc_one)(mm, address)
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm,
+ unsigned long address)
+{
+ return (pmd_t *)srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE,
+ SRMMU_PMD_TABLE_SIZE);
+}
-BTFIXUPDEF_CALL(void, free_pmd_fast, pmd_t *)
-#define free_pmd_fast(pmd) BTFIXUP_CALL(free_pmd_fast)(pmd)
+static inline void free_pmd_fast(pmd_t * pmd)
+{
+ srmmu_free_nocache((unsigned long)pmd, SRMMU_PMD_TABLE_SIZE);
+}
#define pmd_free(mm, pmd) free_pmd_fast(pmd)
#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd)
-BTFIXUPDEF_CALL(void, pmd_populate, pmd_t *, struct page *)
-#define pmd_populate(MM, PMD, PTE) BTFIXUP_CALL(pmd_populate)(PMD, PTE)
+void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep);
#define pmd_pgtable(pmd) pmd_page(pmd)
-BTFIXUPDEF_CALL(void, pmd_set, pmd_t *, pte_t *)
-#define pmd_populate_kernel(MM, PMD, PTE) BTFIXUP_CALL(pmd_set)(PMD, PTE)
-BTFIXUPDEF_CALL(pgtable_t , pte_alloc_one, struct mm_struct *, unsigned long)
-#define pte_alloc_one(mm, address) BTFIXUP_CALL(pte_alloc_one)(mm, address)
-BTFIXUPDEF_CALL(pte_t *, pte_alloc_one_kernel, struct mm_struct *, unsigned long)
-#define pte_alloc_one_kernel(mm, addr) BTFIXUP_CALL(pte_alloc_one_kernel)(mm, addr)
+void pmd_set(pmd_t *pmdp, pte_t *ptep);
+#define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE)
+
+pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address);
+
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+ unsigned long address)
+{
+ return (pte_t *)srmmu_get_nocache(PTE_SIZE, PTE_SIZE);
+}
+
+
+static inline void free_pte_fast(pte_t *pte)
+{
+ srmmu_free_nocache((unsigned long)pte, PTE_SIZE);
+}
-BTFIXUPDEF_CALL(void, free_pte_fast, pte_t *)
-#define pte_free_kernel(mm, pte) BTFIXUP_CALL(free_pte_fast)(pte)
+#define pte_free_kernel(mm, pte) free_pte_fast(pte)
-BTFIXUPDEF_CALL(void, pte_free, pgtable_t )
-#define pte_free(mm, pte) BTFIXUP_CALL(pte_free)(pte)
+void pte_free(struct mm_struct * mm, pgtable_t pte);
#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
#endif /* _SPARC_PGALLOC_H */
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h
index 3d7101860e68..cbbbed5cb3aa 100644
--- a/arch/sparc/include/asm/pgtable_32.h
+++ b/arch/sparc/include/asm/pgtable_32.h
@@ -16,11 +16,9 @@
#include <linux/spinlock.h>
#include <linux/swap.h>
#include <asm/types.h>
-#include <asm/pgtsun4c.h>
#include <asm/pgtsrmmu.h>
-#include <asm/vac-ops.h>
+#include <asm/vaddrs.h>
#include <asm/oplib.h>
-#include <asm/btfixup.h>
#include <asm/cpu_type.h>
@@ -30,87 +28,55 @@ struct page;
extern void load_mmu(void);
extern unsigned long calc_highpages(void);
-BTFIXUPDEF_SIMM13(pgdir_shift)
-BTFIXUPDEF_SETHI(pgdir_size)
-BTFIXUPDEF_SETHI(pgdir_mask)
-
-BTFIXUPDEF_SIMM13(ptrs_per_pmd)
-BTFIXUPDEF_SIMM13(ptrs_per_pgd)
-BTFIXUPDEF_SIMM13(user_ptrs_per_pgd)
-
#define pte_ERROR(e) __builtin_trap()
#define pmd_ERROR(e) __builtin_trap()
#define pgd_ERROR(e) __builtin_trap()
-BTFIXUPDEF_INT(page_none)
-BTFIXUPDEF_INT(page_copy)
-BTFIXUPDEF_INT(page_readonly)
-BTFIXUPDEF_INT(page_kernel)
-
-#define PMD_SHIFT SUN4C_PMD_SHIFT
+#define PMD_SHIFT 22
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
#define PMD_ALIGN(__addr) (((__addr) + ~PMD_MASK) & PMD_MASK)
-#define PGDIR_SHIFT BTFIXUP_SIMM13(pgdir_shift)
-#define PGDIR_SIZE BTFIXUP_SETHI(pgdir_size)
-#define PGDIR_MASK BTFIXUP_SETHI(pgdir_mask)
+#define PGDIR_SHIFT SRMMU_PGDIR_SHIFT
+#define PGDIR_SIZE SRMMU_PGDIR_SIZE
+#define PGDIR_MASK SRMMU_PGDIR_MASK
#define PTRS_PER_PTE 1024
-#define PTRS_PER_PMD BTFIXUP_SIMM13(ptrs_per_pmd)
-#define PTRS_PER_PGD BTFIXUP_SIMM13(ptrs_per_pgd)
-#define USER_PTRS_PER_PGD BTFIXUP_SIMM13(user_ptrs_per_pgd)
+#define PTRS_PER_PMD SRMMU_PTRS_PER_PMD
+#define PTRS_PER_PGD SRMMU_PTRS_PER_PGD
+#define USER_PTRS_PER_PGD PAGE_OFFSET / SRMMU_PGDIR_SIZE
#define FIRST_USER_ADDRESS 0
#define PTE_SIZE (PTRS_PER_PTE*4)
-#define PAGE_NONE __pgprot(BTFIXUP_INT(page_none))
-extern pgprot_t PAGE_SHARED;
-#define PAGE_COPY __pgprot(BTFIXUP_INT(page_copy))
-#define PAGE_READONLY __pgprot(BTFIXUP_INT(page_readonly))
-
-extern unsigned long page_kernel;
-
-#ifdef MODULE
-#define PAGE_KERNEL page_kernel
-#else
-#define PAGE_KERNEL __pgprot(BTFIXUP_INT(page_kernel))
-#endif
+#define PAGE_NONE SRMMU_PAGE_NONE
+#define PAGE_SHARED SRMMU_PAGE_SHARED
+#define PAGE_COPY SRMMU_PAGE_COPY
+#define PAGE_READONLY SRMMU_PAGE_RDONLY
+#define PAGE_KERNEL SRMMU_PAGE_KERNEL
/* Top-level page directory */
extern pgd_t swapper_pg_dir[1024];
extern void paging_init(void);
-/* Page table for 0-4MB for everybody, on the Sparc this
- * holds the same as on the i386.
- */
-extern pte_t pg0[1024];
-extern pte_t pg1[1024];
-extern pte_t pg2[1024];
-extern pte_t pg3[1024];
-
extern unsigned long ptr_in_current_pgd;
-/* Here is a trick, since mmap.c need the initializer elements for
- * protection_map[] to be constant at compile time, I set the following
- * to all zeros. I set it to the real values after I link in the
- * appropriate MMU page table routines at boot time.
- */
-#define __P000 __pgprot(0)
-#define __P001 __pgprot(0)
-#define __P010 __pgprot(0)
-#define __P011 __pgprot(0)
-#define __P100 __pgprot(0)
-#define __P101 __pgprot(0)
-#define __P110 __pgprot(0)
-#define __P111 __pgprot(0)
-
-#define __S000 __pgprot(0)
-#define __S001 __pgprot(0)
-#define __S010 __pgprot(0)
-#define __S011 __pgprot(0)
-#define __S100 __pgprot(0)
-#define __S101 __pgprot(0)
-#define __S110 __pgprot(0)
-#define __S111 __pgprot(0)
+/* xwr */
+#define __P000 PAGE_NONE
+#define __P001 PAGE_READONLY
+#define __P010 PAGE_COPY
+#define __P011 PAGE_COPY
+#define __P100 PAGE_READONLY
+#define __P101 PAGE_READONLY
+#define __P110 PAGE_COPY
+#define __P111 PAGE_COPY
+
+#define __S000 PAGE_NONE
+#define __S001 PAGE_READONLY
+#define __S010 PAGE_SHARED
+#define __S011 PAGE_SHARED
+#define __S100 PAGE_READONLY
+#define __S101 PAGE_READONLY
+#define __S110 PAGE_SHARED
+#define __S111 PAGE_SHARED
extern int num_contexts;
@@ -137,82 +103,137 @@ extern unsigned long empty_zero_page;
#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
/*
+ * In general all page table modifications should use the V8 atomic
+ * swap instruction. This insures the mmu and the cpu are in sync
+ * with respect to ref/mod bits in the page tables.
+ */
+static inline unsigned long srmmu_swap(unsigned long *addr, unsigned long value)
+{
+ __asm__ __volatile__("swap [%2], %0" : "=&r" (value) : "0" (value), "r" (addr));
+ return value;
+}
+
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified. Thus, the following
+ * hook is made available.
*/
-BTFIXUPDEF_CALL_CONST(struct page *, pmd_page, pmd_t)
-BTFIXUPDEF_CALL_CONST(unsigned long, pgd_page_vaddr, pgd_t)
-#define pmd_page(pmd) BTFIXUP_CALL(pmd_page)(pmd)
-#define pgd_page_vaddr(pgd) BTFIXUP_CALL(pgd_page_vaddr)(pgd)
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+ srmmu_swap((unsigned long *)ptep, pte_val(pteval));
+}
+
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+
+static inline int srmmu_device_memory(unsigned long x)
+{
+ return ((x & 0xF0000000) != 0);
+}
+
+static inline struct page *pmd_page(pmd_t pmd)
+{
+ if (srmmu_device_memory(pmd_val(pmd)))
+ BUG();
+ return pfn_to_page((pmd_val(pmd) & SRMMU_PTD_PMASK) >> (PAGE_SHIFT-4));
+}
+
+static inline unsigned long pgd_page_vaddr(pgd_t pgd)
+{
+ if (srmmu_device_memory(pgd_val(pgd))) {
+ return ~0;
+ } else {
+ unsigned long v = pgd_val(pgd) & SRMMU_PTD_PMASK;
+ return (unsigned long)__nocache_va(v << 4);
+ }
+}
-BTFIXUPDEF_CALL_CONST(int, pte_present, pte_t)
-BTFIXUPDEF_CALL(void, pte_clear, pte_t *)
+static inline int pte_present(pte_t pte)
+{
+ return ((pte_val(pte) & SRMMU_ET_MASK) == SRMMU_ET_PTE);
+}
static inline int pte_none(pte_t pte)
{
return !pte_val(pte);
}
-#define pte_present(pte) BTFIXUP_CALL(pte_present)(pte)
-#define pte_clear(mm,addr,pte) BTFIXUP_CALL(pte_clear)(pte)
+static inline void __pte_clear(pte_t *ptep)
+{
+ set_pte(ptep, __pte(0));
+}
+
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ __pte_clear(ptep);
+}
+
+static inline int pmd_bad(pmd_t pmd)
+{
+ return (pmd_val(pmd) & SRMMU_ET_MASK) != SRMMU_ET_PTD;
+}
-BTFIXUPDEF_CALL_CONST(int, pmd_bad, pmd_t)
-BTFIXUPDEF_CALL_CONST(int, pmd_present, pmd_t)
-BTFIXUPDEF_CALL(void, pmd_clear, pmd_t *)
+static inline int pmd_present(pmd_t pmd)
+{
+ return ((pmd_val(pmd) & SRMMU_ET_MASK) == SRMMU_ET_PTD);
+}
static inline int pmd_none(pmd_t pmd)
{
return !pmd_val(pmd);
}
-#define pmd_bad(pmd) BTFIXUP_CALL(pmd_bad)(pmd)
-#define pmd_present(pmd) BTFIXUP_CALL(pmd_present)(pmd)
-#define pmd_clear(pmd) BTFIXUP_CALL(pmd_clear)(pmd)
+static inline void pmd_clear(pmd_t *pmdp)
+{
+ int i;
+ for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++)
+ set_pte((pte_t *)&pmdp->pmdv[i], __pte(0));
+}
-BTFIXUPDEF_CALL_CONST(int, pgd_none, pgd_t)
-BTFIXUPDEF_CALL_CONST(int, pgd_bad, pgd_t)
-BTFIXUPDEF_CALL_CONST(int, pgd_present, pgd_t)
-BTFIXUPDEF_CALL(void, pgd_clear, pgd_t *)
+static inline int pgd_none(pgd_t pgd)
+{
+ return !(pgd_val(pgd) & 0xFFFFFFF);
+}
-#define pgd_none(pgd) BTFIXUP_CALL(pgd_none)(pgd)
-#define pgd_bad(pgd) BTFIXUP_CALL(pgd_bad)(pgd)
-#define pgd_present(pgd) BTFIXUP_CALL(pgd_present)(pgd)
-#define pgd_clear(pgd) BTFIXUP_CALL(pgd_clear)(pgd)
+static inline int pgd_bad(pgd_t pgd)
+{
+ return (pgd_val(pgd) & SRMMU_ET_MASK) != SRMMU_ET_PTD;
+}
+
+static inline int pgd_present(pgd_t pgd)
+{
+ return ((pgd_val(pgd) & SRMMU_ET_MASK) == SRMMU_ET_PTD);
+}
+
+static inline void pgd_clear(pgd_t *pgdp)
+{
+ set_pte((pte_t *)pgdp, __pte(0));
+}
/*
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-BTFIXUPDEF_HALF(pte_writei)
-BTFIXUPDEF_HALF(pte_dirtyi)
-BTFIXUPDEF_HALF(pte_youngi)
-
-static int pte_write(pte_t pte) __attribute_const__;
static inline int pte_write(pte_t pte)
{
- return pte_val(pte) & BTFIXUP_HALF(pte_writei);
+ return pte_val(pte) & SRMMU_WRITE;
}
-static int pte_dirty(pte_t pte) __attribute_const__;
static inline int pte_dirty(pte_t pte)
{
- return pte_val(pte) & BTFIXUP_HALF(pte_dirtyi);
+ return pte_val(pte) & SRMMU_DIRTY;
}
-static int pte_young(pte_t pte) __attribute_const__;
static inline int pte_young(pte_t pte)
{
- return pte_val(pte) & BTFIXUP_HALF(pte_youngi);
+ return pte_val(pte) & SRMMU_REF;
}
/*
* The following only work if pte_present() is not true.
*/
-BTFIXUPDEF_HALF(pte_filei)
-
-static int pte_file(pte_t pte) __attribute_const__;
static inline int pte_file(pte_t pte)
{
- return pte_val(pte) & BTFIXUP_HALF(pte_filei);
+ return pte_val(pte) & SRMMU_FILE;
}
static inline int pte_special(pte_t pte)
@@ -220,68 +241,85 @@ static inline int pte_special(pte_t pte)
return 0;
}
-/*
- */
-BTFIXUPDEF_HALF(pte_wrprotecti)
-BTFIXUPDEF_HALF(pte_mkcleani)
-BTFIXUPDEF_HALF(pte_mkoldi)
-
-static pte_t pte_wrprotect(pte_t pte) __attribute_const__;
static inline pte_t pte_wrprotect(pte_t pte)
{
- return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_wrprotecti));
+ return __pte(pte_val(pte) & ~SRMMU_WRITE);
}
-static pte_t pte_mkclean(pte_t pte) __attribute_const__;
static inline pte_t pte_mkclean(pte_t pte)
{
- return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_mkcleani));
+ return __pte(pte_val(pte) & ~SRMMU_DIRTY);
}
-static pte_t pte_mkold(pte_t pte) __attribute_const__;
static inline pte_t pte_mkold(pte_t pte)
{
- return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_mkoldi));
+ return __pte(pte_val(pte) & ~SRMMU_REF);
}
-BTFIXUPDEF_CALL_CONST(pte_t, pte_mkwrite, pte_t)
-BTFIXUPDEF_CALL_CONST(pte_t, pte_mkdirty, pte_t)
-BTFIXUPDEF_CALL_CONST(pte_t, pte_mkyoung, pte_t)
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+ return __pte(pte_val(pte) | SRMMU_WRITE);
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+ return __pte(pte_val(pte) | SRMMU_DIRTY);
+}
-#define pte_mkwrite(pte) BTFIXUP_CALL(pte_mkwrite)(pte)
-#define pte_mkdirty(pte) BTFIXUP_CALL(pte_mkdirty)(pte)
-#define pte_mkyoung(pte) BTFIXUP_CALL(pte_mkyoung)(pte)
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+ return __pte(pte_val(pte) | SRMMU_REF);
+}
#define pte_mkspecial(pte) (pte)
#define pfn_pte(pfn, prot) mk_pte(pfn_to_page(pfn), prot)
-BTFIXUPDEF_CALL(unsigned long, pte_pfn, pte_t)
-#define pte_pfn(pte) BTFIXUP_CALL(pte_pfn)(pte)
+static inline unsigned long pte_pfn(pte_t pte)
+{
+ if (srmmu_device_memory(pte_val(pte))) {
+ /* Just return something that will cause
+ * pfn_valid() to return false. This makes
+ * copy_one_pte() to just directly copy to
+ * PTE over.
+ */
+ return ~0UL;
+ }
+ return (pte_val(pte) & SRMMU_PTE_PMASK) >> (PAGE_SHIFT-4);
+}
+
#define pte_page(pte) pfn_to_page(pte_pfn(pte))
/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
*/
-BTFIXUPDEF_CALL_CONST(pte_t, mk_pte, struct page *, pgprot_t)
-
-BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_phys, unsigned long, pgprot_t)
-BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_io, unsigned long, pgprot_t, int)
-BTFIXUPDEF_CALL_CONST(pgprot_t, pgprot_noncached, pgprot_t)
+static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
+{
+ return __pte((page_to_pfn(page) << (PAGE_SHIFT-4)) | pgprot_val(pgprot));
+}
-#define mk_pte(page,pgprot) BTFIXUP_CALL(mk_pte)(page,pgprot)
-#define mk_pte_phys(page,pgprot) BTFIXUP_CALL(mk_pte_phys)(page,pgprot)
-#define mk_pte_io(page,pgprot,space) BTFIXUP_CALL(mk_pte_io)(page,pgprot,space)
+static inline pte_t mk_pte_phys(unsigned long page, pgprot_t pgprot)
+{
+ return __pte(((page) >> 4) | pgprot_val(pgprot));
+}
-#define pgprot_noncached(pgprot) BTFIXUP_CALL(pgprot_noncached)(pgprot)
+static inline pte_t mk_pte_io(unsigned long page, pgprot_t pgprot, int space)
+{
+ return __pte(((page) >> 4) | (space << 28) | pgprot_val(pgprot));
+}
-BTFIXUPDEF_INT(pte_modify_mask)
+#define pgprot_noncached pgprot_noncached
+static inline pgprot_t pgprot_noncached(pgprot_t prot)
+{
+ prot &= ~__pgprot(SRMMU_CACHE);
+ return prot;
+}
static pte_t pte_modify(pte_t pte, pgprot_t newprot) __attribute_const__;
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
- return __pte((pte_val(pte) & BTFIXUP_INT(pte_modify_mask)) |
+ return __pte((pte_val(pte) & SRMMU_CHG_MASK) |
pgprot_val(newprot));
}
@@ -294,74 +332,69 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
#define pgd_offset_k(address) pgd_offset(&init_mm, address)
/* Find an entry in the second-level page table.. */
-BTFIXUPDEF_CALL(pmd_t *, pmd_offset, pgd_t *, unsigned long)
-#define pmd_offset(dir,addr) BTFIXUP_CALL(pmd_offset)(dir,addr)
+static inline pmd_t *pmd_offset(pgd_t * dir, unsigned long address)
+{
+ return (pmd_t *) pgd_page_vaddr(*dir) +
+ ((address >> PMD_SHIFT) & (PTRS_PER_PMD - 1));
+}
/* Find an entry in the third-level page table.. */
-BTFIXUPDEF_CALL(pte_t *, pte_offset_kernel, pmd_t *, unsigned long)
-#define pte_offset_kernel(dir,addr) BTFIXUP_CALL(pte_offset_kernel)(dir,addr)
+pte_t *pte_offset_kernel(pmd_t * dir, unsigned long address);
/*
- * This shortcut works on sun4m (and sun4d) because the nocache area is static,
- * and sun4c is guaranteed to have no highmem anyway.
+ * This shortcut works on sun4m (and sun4d) because the nocache area is static.
*/
#define pte_offset_map(d, a) pte_offset_kernel(d,a)
#define pte_unmap(pte) do{}while(0)
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified. Thus, the following
- * hook is made available.
- */
-
-BTFIXUPDEF_CALL(void, set_pte, pte_t *, pte_t)
-
-#define set_pte(ptep,pteval) BTFIXUP_CALL(set_pte)(ptep,pteval)
-#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
-
struct seq_file;
-BTFIXUPDEF_CALL(void, mmu_info, struct seq_file *)
-
-#define mmu_info(p) BTFIXUP_CALL(mmu_info)(p)
+void mmu_info(struct seq_file *m);
/* Fault handler stuff... */
#define FAULT_CODE_PROT 0x1
#define FAULT_CODE_WRITE 0x2
#define FAULT_CODE_USER 0x4
-BTFIXUPDEF_CALL(void, update_mmu_cache, struct vm_area_struct *, unsigned long, pte_t *)
-
-#define update_mmu_cache(vma,addr,ptep) BTFIXUP_CALL(update_mmu_cache)(vma,addr,ptep)
-
-BTFIXUPDEF_CALL(void, sparc_mapiorange, unsigned int, unsigned long,
- unsigned long, unsigned int)
-BTFIXUPDEF_CALL(void, sparc_unmapiorange, unsigned long, unsigned int)
-#define sparc_mapiorange(bus,pa,va,len) BTFIXUP_CALL(sparc_mapiorange)(bus,pa,va,len)
-#define sparc_unmapiorange(va,len) BTFIXUP_CALL(sparc_unmapiorange)(va,len)
+#define update_mmu_cache(vma, address, ptep) do { } while (0)
-extern int invalid_segment;
+void srmmu_mapiorange(unsigned int bus, unsigned long xpa,
+ unsigned long xva, unsigned int len);
+void srmmu_unmapiorange(unsigned long virt_addr, unsigned int len);
/* Encode and de-code a swap entry */
-BTFIXUPDEF_CALL(unsigned long, __swp_type, swp_entry_t)
-BTFIXUPDEF_CALL(unsigned long, __swp_offset, swp_entry_t)
-BTFIXUPDEF_CALL(swp_entry_t, __swp_entry, unsigned long, unsigned long)
+static inline unsigned long __swp_type(swp_entry_t entry)
+{
+ return (entry.val >> SRMMU_SWP_TYPE_SHIFT) & SRMMU_SWP_TYPE_MASK;
+}
+
+static inline unsigned long __swp_offset(swp_entry_t entry)
+{
+ return (entry.val >> SRMMU_SWP_OFF_SHIFT) & SRMMU_SWP_OFF_MASK;
+}
-#define __swp_type(__x) BTFIXUP_CALL(__swp_type)(__x)
-#define __swp_offset(__x) BTFIXUP_CALL(__swp_offset)(__x)
-#define __swp_entry(__type,__off) BTFIXUP_CALL(__swp_entry)(__type,__off)
+static inline swp_entry_t __swp_entry(unsigned long type, unsigned long offset)
+{
+ return (swp_entry_t) {
+ (type & SRMMU_SWP_TYPE_MASK) << SRMMU_SWP_TYPE_SHIFT
+ | (offset & SRMMU_SWP_OFF_MASK) << SRMMU_SWP_OFF_SHIFT };
+}
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
/* file-offset-in-pte helpers */
-BTFIXUPDEF_CALL(unsigned long, pte_to_pgoff, pte_t pte);
-BTFIXUPDEF_CALL(pte_t, pgoff_to_pte, unsigned long pgoff);
+static inline unsigned long pte_to_pgoff(pte_t pte)
+{
+ return pte_val(pte) >> SRMMU_PTE_FILE_SHIFT;
+}
-#define pte_to_pgoff(pte) BTFIXUP_CALL(pte_to_pgoff)(pte)
-#define pgoff_to_pte(off) BTFIXUP_CALL(pgoff_to_pte)(off)
+static inline pte_t pgoff_to_pte(unsigned long pgoff)
+{
+ return __pte((pgoff << SRMMU_PTE_FILE_SHIFT) | SRMMU_FILE);
+}
/*
* This is made a constant because mm/fremap.c required a constant.
- * Note that layout of these bits is different between sun4c.c and srmmu.c.
*/
#define PTE_FILE_MAX_BITS 24
@@ -399,9 +432,6 @@ static inline unsigned long
__get_phys (unsigned long addr)
{
switch (sparc_cpu_model){
- case sun4:
- case sun4c:
- return sun4c_get_pte (addr) << PAGE_SHIFT;
case sun4m:
case sun4d:
return ((srmmu_get_pte (addr) & 0xffffff00) << 4);
@@ -414,9 +444,6 @@ static inline int
__get_iospace (unsigned long addr)
{
switch (sparc_cpu_model){
- case sun4:
- case sun4c:
- return -1; /* Don't check iospace on sun4c */
case sun4m:
case sun4d:
return (srmmu_get_pte (addr) >> 28);
@@ -463,7 +490,7 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
flush_tlb_page(__vma, __address); \
} \
- (sparc_cpu_model == sun4c) || __changed; \
+ __changed; \
})
#include <asm-generic/pgtable.h>
@@ -471,10 +498,8 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
#endif /* !(__ASSEMBLY__) */
#define VMALLOC_START _AC(0xfe600000,UL)
-/* XXX Alter this when I get around to fixing sun4c - Anton */
#define VMALLOC_END _AC(0xffc00000,UL)
-
/* We provide our own get_unmapped_area to cope with VA holes for userland */
#define HAVE_ARCH_UNMAPPED_AREA
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 76e4a52aa85e..61210db139fb 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -717,10 +717,6 @@ extern unsigned long find_ecache_flush_span(unsigned long size);
struct seq_file;
extern void mmu_info(struct seq_file *);
-/* These do nothing with the way I have things setup. */
-#define mmu_lockarea(vaddr, len) (vaddr)
-#define mmu_unlockarea(vaddr, len) do { } while(0)
-
struct vm_area_struct;
extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *);
diff --git a/arch/sparc/include/asm/pgtsrmmu.h b/arch/sparc/include/asm/pgtsrmmu.h
index f6ae2b2b6870..cb828703a63a 100644
--- a/arch/sparc/include/asm/pgtsrmmu.h
+++ b/arch/sparc/include/asm/pgtsrmmu.h
@@ -173,17 +173,6 @@ static inline void srmmu_set_ctable_ptr(unsigned long paddr)
"memory");
}
-static inline unsigned long srmmu_get_ctable_ptr(void)
-{
- unsigned int retval;
-
- __asm__ __volatile__("lda [%1] %2, %0\n\t" :
- "=r" (retval) :
- "r" (SRMMU_CTXTBL_PTR),
- "i" (ASI_M_MMUREGS));
- return (retval & SRMMU_CTX_PMASK) << 4;
-}
-
static inline void srmmu_set_context(int context)
{
__asm__ __volatile__("sta %0, [%1] %2\n\t" : :
@@ -231,42 +220,6 @@ static inline void srmmu_flush_whole_tlb(void)
}
/* These flush types are not available on all chips... */
-static inline void srmmu_flush_tlb_ctx(void)
-{
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
- "r" (0x300), /* Flush TLB ctx.. */
- "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
-static inline void srmmu_flush_tlb_region(unsigned long addr)
-{
- addr &= SRMMU_PGDIR_MASK;
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
- "r" (addr | 0x200), /* Flush TLB region.. */
- "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
-
-static inline void srmmu_flush_tlb_segment(unsigned long addr)
-{
- addr &= SRMMU_REAL_PMD_MASK;
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
- "r" (addr | 0x100), /* Flush TLB segment.. */
- "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
-static inline void srmmu_flush_tlb_page(unsigned long page)
-{
- page &= PAGE_MASK;
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
- "r" (page), /* Flush TLB page.. */
- "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
#ifndef CONFIG_SPARC_LEON
static inline unsigned long srmmu_hwprobe(unsigned long vaddr)
{
@@ -294,9 +247,6 @@ srmmu_get_pte (unsigned long addr)
return entry;
}
-extern unsigned long (*srmmu_read_physical)(unsigned long paddr);
-extern void (*srmmu_write_physical)(unsigned long paddr, unsigned long word);
-
#endif /* !(__ASSEMBLY__) */
#endif /* !(_SPARC_PGTSRMMU_H) */
diff --git a/arch/sparc/include/asm/pgtsun4c.h b/arch/sparc/include/asm/pgtsun4c.h
deleted file mode 100644
index aeb25e912179..000000000000
--- a/arch/sparc/include/asm/pgtsun4c.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * pgtsun4c.h: Sun4c specific pgtable.h defines and code.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-#ifndef _SPARC_PGTSUN4C_H
-#define _SPARC_PGTSUN4C_H
-
-#include <asm/contregs.h>
-
-/* PMD_SHIFT determines the size of the area a second-level page table can map */
-#define SUN4C_PMD_SHIFT 22
-
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define SUN4C_PGDIR_SHIFT 22
-#define SUN4C_PGDIR_SIZE (1UL << SUN4C_PGDIR_SHIFT)
-#define SUN4C_PGDIR_MASK (~(SUN4C_PGDIR_SIZE-1))
-#define SUN4C_PGDIR_ALIGN(addr) (((addr)+SUN4C_PGDIR_SIZE-1)&SUN4C_PGDIR_MASK)
-
-/* To represent how the sun4c mmu really lays things out. */
-#define SUN4C_REAL_PGDIR_SHIFT 18
-#define SUN4C_REAL_PGDIR_SIZE (1UL << SUN4C_REAL_PGDIR_SHIFT)
-#define SUN4C_REAL_PGDIR_MASK (~(SUN4C_REAL_PGDIR_SIZE-1))
-#define SUN4C_REAL_PGDIR_ALIGN(addr) (((addr)+SUN4C_REAL_PGDIR_SIZE-1)&SUN4C_REAL_PGDIR_MASK)
-
-/* 16 bit PFN on sun4c */
-#define SUN4C_PFN_MASK 0xffff
-
-/* Don't increase these unless the structures in sun4c.c are fixed */
-#define SUN4C_MAX_SEGMAPS 256
-#define SUN4C_MAX_CONTEXTS 16
-
-/*
- * To be efficient, and not have to worry about allocating such
- * a huge pgd, we make the kernel sun4c tables each hold 1024
- * entries and the pgd similarly just like the i386 tables.
- */
-#define SUN4C_PTRS_PER_PTE 1024
-#define SUN4C_PTRS_PER_PMD 1
-#define SUN4C_PTRS_PER_PGD 1024
-
-/*
- * Sparc SUN4C pte fields.
- */
-#define _SUN4C_PAGE_VALID 0x80000000
-#define _SUN4C_PAGE_SILENT_READ 0x80000000 /* synonym */
-#define _SUN4C_PAGE_DIRTY 0x40000000
-#define _SUN4C_PAGE_SILENT_WRITE 0x40000000 /* synonym */
-#define _SUN4C_PAGE_PRIV 0x20000000 /* privileged page */
-#define _SUN4C_PAGE_NOCACHE 0x10000000 /* non-cacheable page */
-#define _SUN4C_PAGE_PRESENT 0x08000000 /* implemented in software */
-#define _SUN4C_PAGE_IO 0x04000000 /* I/O page */
-#define _SUN4C_PAGE_FILE 0x02000000 /* implemented in software */
-#define _SUN4C_PAGE_READ 0x00800000 /* implemented in software */
-#define _SUN4C_PAGE_WRITE 0x00400000 /* implemented in software */
-#define _SUN4C_PAGE_ACCESSED 0x00200000 /* implemented in software */
-#define _SUN4C_PAGE_MODIFIED 0x00100000 /* implemented in software */
-
-#define _SUN4C_READABLE (_SUN4C_PAGE_READ|_SUN4C_PAGE_SILENT_READ|\
- _SUN4C_PAGE_ACCESSED)
-#define _SUN4C_WRITEABLE (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_SILENT_WRITE|\
- _SUN4C_PAGE_MODIFIED)
-
-#define _SUN4C_PAGE_CHG_MASK (0xffff|_SUN4C_PAGE_ACCESSED|_SUN4C_PAGE_MODIFIED)
-
-#define SUN4C_PAGE_NONE __pgprot(_SUN4C_PAGE_PRESENT)
-#define SUN4C_PAGE_SHARED __pgprot(_SUN4C_PAGE_PRESENT|_SUN4C_READABLE|\
- _SUN4C_PAGE_WRITE)
-#define SUN4C_PAGE_COPY __pgprot(_SUN4C_PAGE_PRESENT|_SUN4C_READABLE)
-#define SUN4C_PAGE_READONLY __pgprot(_SUN4C_PAGE_PRESENT|_SUN4C_READABLE)
-#define SUN4C_PAGE_KERNEL __pgprot(_SUN4C_READABLE|_SUN4C_WRITEABLE|\
- _SUN4C_PAGE_DIRTY|_SUN4C_PAGE_PRIV)
-
-/* SUN4C swap entry encoding
- *
- * We use 5 bits for the type and 19 for the offset. This gives us
- * 32 swapfiles of 4GB each. Encoding looks like:
- *
- * RRRRRRRRooooooooooooooooooottttt
- * fedcba9876543210fedcba9876543210
- *
- * The top 8 bits are reserved for protection and status bits, especially
- * FILE and PRESENT.
- */
-#define SUN4C_SWP_TYPE_MASK 0x1f
-#define SUN4C_SWP_OFF_MASK 0x7ffff
-#define SUN4C_SWP_OFF_SHIFT 5
-
-#ifndef __ASSEMBLY__
-
-static inline unsigned long sun4c_get_synchronous_error(void)
-{
- unsigned long sync_err;
-
- __asm__ __volatile__("lda [%1] %2, %0\n\t" :
- "=r" (sync_err) :
- "r" (AC_SYNC_ERR), "i" (ASI_CONTROL));
- return sync_err;
-}
-
-static inline unsigned long sun4c_get_synchronous_address(void)
-{
- unsigned long sync_addr;
-
- __asm__ __volatile__("lda [%1] %2, %0\n\t" :
- "=r" (sync_addr) :
- "r" (AC_SYNC_VA), "i" (ASI_CONTROL));
- return sync_addr;
-}
-
-/* SUN4C pte, segmap, and context manipulation */
-static inline unsigned long sun4c_get_segmap(unsigned long addr)
-{
- register unsigned long entry;
-
- __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
- "=r" (entry) :
- "r" (addr), "i" (ASI_SEGMAP));
-
- return entry;
-}
-
-static inline void sun4c_put_segmap(unsigned long addr, unsigned long entry)
-{
-
- __asm__ __volatile__("\n\tstba %1, [%0] %2; nop; nop; nop;\n\t" : :
- "r" (addr), "r" (entry),
- "i" (ASI_SEGMAP)
- : "memory");
-}
-
-static inline unsigned long sun4c_get_pte(unsigned long addr)
-{
- register unsigned long entry;
-
- __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" :
- "=r" (entry) :
- "r" (addr), "i" (ASI_PTE));
- return entry;
-}
-
-static inline void sun4c_put_pte(unsigned long addr, unsigned long entry)
-{
- __asm__ __volatile__("\n\tsta %1, [%0] %2; nop; nop; nop;\n\t" : :
- "r" (addr),
- "r" ((entry & ~(_SUN4C_PAGE_PRESENT))), "i" (ASI_PTE)
- : "memory");
-}
-
-static inline int sun4c_get_context(void)
-{
- register int ctx;
-
- __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
- "=r" (ctx) :
- "r" (AC_CONTEXT), "i" (ASI_CONTROL));
-
- return ctx;
-}
-
-static inline int sun4c_set_context(int ctx)
-{
- __asm__ __volatile__("\n\tstba %0, [%1] %2; nop; nop; nop;\n\t" : :
- "r" (ctx), "r" (AC_CONTEXT), "i" (ASI_CONTROL)
- : "memory");
-
- return ctx;
-}
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(_SPARC_PGTSUN4C_H) */
diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h
index 09521c6a5edb..f74ac9ee33a8 100644
--- a/arch/sparc/include/asm/processor_32.h
+++ b/arch/sparc/include/asm/processor_32.h
@@ -16,7 +16,6 @@
#include <asm/ptrace.h>
#include <asm/head.h>
#include <asm/signal.h>
-#include <asm/btfixup.h>
#include <asm/page.h>
/*
@@ -109,9 +108,6 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
#define release_thread(tsk) do { } while(0)
extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
extern unsigned long get_wchan(struct task_struct *);
#define task_pt_regs(tsk) ((tsk)->thread.kregs)
diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h
index e713db249931..67df5cc10011 100644
--- a/arch/sparc/include/asm/processor_64.h
+++ b/arch/sparc/include/asm/processor_64.h
@@ -186,9 +186,6 @@ do { \
/* Free all resources held by a thread. */
#define release_thread(tsk) do { } while (0)
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
extern unsigned long get_wchan(struct task_struct *task);
diff --git a/arch/sparc/include/asm/setup.h b/arch/sparc/include/asm/setup.h
index 00497abec996..8a83699a5507 100644
--- a/arch/sparc/include/asm/setup.h
+++ b/arch/sparc/include/asm/setup.h
@@ -20,10 +20,7 @@ extern char reboot_command[];
* Only sun4d + leon may have boot_cpu_id != 0
*/
extern unsigned char boot_cpu_id;
-extern unsigned char boot_cpu_id4;
-extern unsigned long empty_bad_page;
-extern unsigned long empty_bad_page_table;
extern unsigned long empty_zero_page;
extern int serial_console;
diff --git a/arch/sparc/include/asm/shmparam_32.h b/arch/sparc/include/asm/shmparam_32.h
index 59a1243c12f3..142825c8d3ac 100644
--- a/arch/sparc/include/asm/shmparam_32.h
+++ b/arch/sparc/include/asm/shmparam_32.h
@@ -4,8 +4,6 @@
#define __ARCH_FORCE_SHMLBA 1
extern int vac_cache_size;
-#define SHMLBA (vac_cache_size ? vac_cache_size : \
- (sparc_cpu_model == sun4c ? (64 * 1024) : \
- (sparc_cpu_model == sun4 ? (128 * 1024) : PAGE_SIZE)))
+#define SHMLBA (vac_cache_size ? vac_cache_size : PAGE_SIZE)
#endif /* _ASMSPARC_SHMPARAM_H */
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h
index 01c51c704341..b73da3c5f10a 100644
--- a/arch/sparc/include/asm/smp_32.h
+++ b/arch/sparc/include/asm/smp_32.h
@@ -8,7 +8,6 @@
#include <linux/threads.h>
#include <asm/head.h>
-#include <asm/btfixup.h>
#ifndef __ASSEMBLY__
@@ -58,104 +57,53 @@ struct seq_file;
void smp_bogo(struct seq_file *);
void smp_info(struct seq_file *);
-BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, cpumask_t, unsigned long, unsigned long, unsigned long, unsigned long)
-BTFIXUPDEF_CALL(int, __hard_smp_processor_id, void)
-BTFIXUPDEF_CALL(void, smp_ipi_resched, int);
-BTFIXUPDEF_CALL(void, smp_ipi_single, int);
-BTFIXUPDEF_CALL(void, smp_ipi_mask_one, int);
-BTFIXUPDEF_BLACKBOX(hard_smp_processor_id)
-BTFIXUPDEF_BLACKBOX(load_current)
-
-#define smp_cross_call(func,mask,arg1,arg2,arg3,arg4) BTFIXUP_CALL(smp_cross_call)(func,mask,arg1,arg2,arg3,arg4)
+struct sparc32_ipi_ops {
+ void (*cross_call)(smpfunc_t func, cpumask_t mask, unsigned long arg1,
+ unsigned long arg2, unsigned long arg3,
+ unsigned long arg4);
+ void (*resched)(int cpu);
+ void (*single)(int cpu);
+ void (*mask_one)(int cpu);
+};
+extern const struct sparc32_ipi_ops *sparc32_ipi_ops;
+
+static inline void xc0(smpfunc_t func)
+{
+ sparc32_ipi_ops->cross_call(func, *cpu_online_mask, 0, 0, 0, 0);
+}
-static inline void xc0(smpfunc_t func) { smp_cross_call(func, *cpu_online_mask, 0, 0, 0, 0); }
static inline void xc1(smpfunc_t func, unsigned long arg1)
-{ smp_cross_call(func, *cpu_online_mask, arg1, 0, 0, 0); }
-static inline void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2)
-{ smp_cross_call(func, *cpu_online_mask, arg1, arg2, 0, 0); }
-static inline void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2,
- unsigned long arg3)
-{ smp_cross_call(func, *cpu_online_mask, arg1, arg2, arg3, 0); }
-static inline void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2,
- unsigned long arg3, unsigned long arg4)
-{ smp_cross_call(func, *cpu_online_mask, arg1, arg2, arg3, arg4); }
-
-extern void arch_send_call_function_single_ipi(int cpu);
-extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
-
-static inline int cpu_logical_map(int cpu)
{
- return cpu;
+ sparc32_ipi_ops->cross_call(func, *cpu_online_mask, arg1, 0, 0, 0);
}
-
-static inline int hard_smp4m_processor_id(void)
+static inline void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2)
{
- int cpuid;
-
- __asm__ __volatile__("rd %%tbr, %0\n\t"
- "srl %0, 12, %0\n\t"
- "and %0, 3, %0\n\t" :
- "=&r" (cpuid));
- return cpuid;
+ sparc32_ipi_ops->cross_call(func, *cpu_online_mask, arg1, arg2, 0, 0);
}
-static inline int hard_smp4d_processor_id(void)
+static inline void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2,
+ unsigned long arg3)
{
- int cpuid;
-
- __asm__ __volatile__("lda [%%g0] %1, %0\n\t" :
- "=&r" (cpuid) : "i" (ASI_M_VIKING_TMP1));
- return cpuid;
+ sparc32_ipi_ops->cross_call(func, *cpu_online_mask,
+ arg1, arg2, arg3, 0);
}
-extern inline int hard_smpleon_processor_id(void)
+static inline void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4)
{
- int cpuid;
- __asm__ __volatile__("rd %%asr17,%0\n\t"
- "srl %0,28,%0" :
- "=&r" (cpuid) : );
- return cpuid;
+ sparc32_ipi_ops->cross_call(func, *cpu_online_mask,
+ arg1, arg2, arg3, arg4);
}
-#ifndef MODULE
-static inline int hard_smp_processor_id(void)
+extern void arch_send_call_function_single_ipi(int cpu);
+extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+
+static inline int cpu_logical_map(int cpu)
{
- int cpuid;
-
- /* Black box - sun4m
- __asm__ __volatile__("rd %%tbr, %0\n\t"
- "srl %0, 12, %0\n\t"
- "and %0, 3, %0\n\t" :
- "=&r" (cpuid));
- - sun4d
- __asm__ __volatile__("lda [%g0] ASI_M_VIKING_TMP1, %0\n\t"
- "nop; nop" :
- "=&r" (cpuid));
- - leon
- __asm__ __volatile__( "rd %asr17, %0\n\t"
- "srl %0, 0x1c, %0\n\t"
- "nop\n\t" :
- "=&r" (cpuid));
- See btfixup.h and btfixupprep.c to understand how a blackbox works.
- */
- __asm__ __volatile__("sethi %%hi(___b_hard_smp_processor_id), %0\n\t"
- "sethi %%hi(boot_cpu_id), %0\n\t"
- "ldub [%0 + %%lo(boot_cpu_id)], %0\n\t" :
- "=&r" (cpuid));
- return cpuid;
+ return cpu;
}
-#else
-static inline int hard_smp_processor_id(void)
-{
- int cpuid;
- __asm__ __volatile__("mov %%o7, %%g1\n\t"
- "call ___f___hard_smp_processor_id\n\t"
- " nop\n\t"
- "mov %%g2, %0\n\t" : "=r"(cpuid) : : "g1", "g2");
- return cpuid;
-}
-#endif
+extern int hard_smp_processor_id(void);
#define raw_smp_processor_id() (current_thread_info()->cpu)
diff --git a/arch/sparc/include/asm/smpprim.h b/arch/sparc/include/asm/smpprim.h
deleted file mode 100644
index eb849d862c64..000000000000
--- a/arch/sparc/include/asm/smpprim.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * smpprim.h: SMP locking primitives on the Sparc
- *
- * God knows we won't be actually using this code for some time
- * but I thought I'd write it since I knew how.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef __SPARC_SMPPRIM_H
-#define __SPARC_SMPPRIM_H
-
-/* Test and set the unsigned byte at ADDR to 1. Returns the previous
- * value. On the Sparc we use the ldstub instruction since it is
- * atomic.
- */
-
-static inline __volatile__ char test_and_set(void *addr)
-{
- char state = 0;
-
- __asm__ __volatile__("ldstub [%0], %1 ! test_and_set\n\t"
- "=r" (addr), "=r" (state) :
- "0" (addr), "1" (state) : "memory");
-
- return state;
-}
-
-/* Initialize a spin-lock. */
-static inline __volatile__ smp_initlock(void *spinlock)
-{
- /* Unset the lock. */
- *((unsigned char *) spinlock) = 0;
-
- return;
-}
-
-/* This routine spins until it acquires the lock at ADDR. */
-static inline __volatile__ smp_lock(void *addr)
-{
- while(test_and_set(addr) == 0xff)
- ;
-
- /* We now have the lock */
- return;
-}
-
-/* This routine releases the lock at ADDR. */
-static inline __volatile__ smp_unlock(void *addr)
-{
- *((unsigned char *) addr) = 0;
-}
-
-#endif /* !(__SPARC_SMPPRIM_H) */
diff --git a/arch/sparc/include/asm/string_32.h b/arch/sparc/include/asm/string_32.h
index edf196ee4ef8..12f67857152e 100644
--- a/arch/sparc/include/asm/string_32.h
+++ b/arch/sparc/include/asm/string_32.h
@@ -61,68 +61,7 @@ extern int memcmp(const void *,const void *,__kernel_size_t);
extern __kernel_size_t strlen(const char *);
#define __HAVE_ARCH_STRNCMP
-
-extern int __strncmp(const char *, const char *, __kernel_size_t);
-
-static inline int __constant_strncmp(const char *src, const char *dest, __kernel_size_t count)
-{
- register int retval;
- switch(count) {
- case 0: return 0;
- case 1: return (src[0] - dest[0]);
- case 2: retval = (src[0] - dest[0]);
- if(!retval && src[0])
- retval = (src[1] - dest[1]);
- return retval;
- case 3: retval = (src[0] - dest[0]);
- if(!retval && src[0]) {
- retval = (src[1] - dest[1]);
- if(!retval && src[1])
- retval = (src[2] - dest[2]);
- }
- return retval;
- case 4: retval = (src[0] - dest[0]);
- if(!retval && src[0]) {
- retval = (src[1] - dest[1]);
- if(!retval && src[1]) {
- retval = (src[2] - dest[2]);
- if (!retval && src[2])
- retval = (src[3] - dest[3]);
- }
- }
- return retval;
- case 5: retval = (src[0] - dest[0]);
- if(!retval && src[0]) {
- retval = (src[1] - dest[1]);
- if(!retval && src[1]) {
- retval = (src[2] - dest[2]);
- if (!retval && src[2]) {
- retval = (src[3] - dest[3]);
- if (!retval && src[3])
- retval = (src[4] - dest[4]);
- }
- }
- }
- return retval;
- default:
- retval = (src[0] - dest[0]);
- if(!retval && src[0]) {
- retval = (src[1] - dest[1]);
- if(!retval && src[1]) {
- retval = (src[2] - dest[2]);
- if(!retval && src[2])
- retval = __strncmp(src+3,dest+3,count-3);
- }
- }
- return retval;
- }
-}
-
-#undef strncmp
-#define strncmp(__arg0, __arg1, __arg2) \
-(__builtin_constant_p(__arg2) ? \
- __constant_strncmp(__arg0, __arg1, __arg2) : \
- __strncmp(__arg0, __arg1, __arg2))
+extern int strncmp(const char *, const char *, __kernel_size_t);
#endif /* !EXPORT_SYMTAB_STROPS */
diff --git a/arch/sparc/include/asm/sysen.h b/arch/sparc/include/asm/sysen.h
deleted file mode 100644
index 6af34abde6e7..000000000000
--- a/arch/sparc/include/asm/sysen.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * sysen.h: Bit fields within the "System Enable" register accessed via
- * the ASI_CONTROL address space at address AC_SYSENABLE.
- *
- * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC_SYSEN_H
-#define _SPARC_SYSEN_H
-
-#define SENABLE_DVMA 0x20 /* enable dvma transfers */
-#define SENABLE_CACHE 0x10 /* enable VAC cache */
-#define SENABLE_RESET 0x04 /* reset whole machine, danger Will Robinson */
-
-#endif /* _SPARC_SYSEN_H */
diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h
index c2a1080cdd3b..21a38946541d 100644
--- a/arch/sparc/include/asm/thread_info_32.h
+++ b/arch/sparc/include/asm/thread_info_32.h
@@ -15,7 +15,6 @@
#ifndef __ASSEMBLY__
-#include <asm/btfixup.h>
#include <asm/ptrace.h>
#include <asm/page.h>
@@ -80,13 +79,8 @@ register struct thread_info *current_thread_info_reg asm("g6");
*/
#define THREAD_INFO_ORDER 1
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-
-BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info_node, int)
-#define alloc_thread_info_node(tsk, node) BTFIXUP_CALL(alloc_thread_info_node)(node)
-
-BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
-#define free_thread_info(ti) BTFIXUP_CALL(free_thread_info)(ti)
+struct thread_info * alloc_thread_info_node(struct task_struct *tsk, int node);
+void free_thread_info(struct thread_info *);
#endif /* __ASSEMBLY__ */
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h
index 01d057fe6a3f..7f0981b09451 100644
--- a/arch/sparc/include/asm/thread_info_64.h
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -138,32 +138,11 @@ register struct thread_info *current_thread_info_reg asm("g6");
/* thread information allocation */
#if PAGE_SHIFT == 13
-#define __THREAD_INFO_ORDER 1
+#define THREAD_SIZE_ORDER 1
#else /* PAGE_SHIFT == 13 */
-#define __THREAD_INFO_ORDER 0
+#define THREAD_SIZE_ORDER 0
#endif /* PAGE_SHIFT == 13 */
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define THREAD_FLAGS (GFP_KERNEL | __GFP_ZERO)
-#else
-#define THREAD_FLAGS (GFP_KERNEL)
-#endif
-
-#define alloc_thread_info_node(tsk, node) \
-({ \
- struct page *page = alloc_pages_node(node, THREAD_FLAGS, \
- __THREAD_INFO_ORDER); \
- struct thread_info *ret; \
- \
- ret = page ? page_address(page) : NULL; \
- ret; \
-})
-
-#define free_thread_info(ti) \
- free_pages((unsigned long)(ti),__THREAD_INFO_ORDER)
-
#define __thread_flag_byte_ptr(ti) \
((unsigned char *)(&((ti)->flags)))
#define __cur_thread_flag_byte_ptr __thread_flag_byte_ptr(current_thread_info())
diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h
index 1a91e11dd104..72f40a546de3 100644
--- a/arch/sparc/include/asm/timer_32.h
+++ b/arch/sparc/include/asm/timer_32.h
@@ -8,14 +8,37 @@
#ifndef _SPARC_TIMER_H
#define _SPARC_TIMER_H
+#include <linux/clocksource.h>
+#include <linux/irqreturn.h>
+
+#include <asm-generic/percpu.h>
+
#include <asm/cpu_type.h> /* For SUN4M_NCPUS */
-#include <asm/btfixup.h>
+
+#define SBUS_CLOCK_RATE 2000000 /* 2MHz */
+#define TIMER_VALUE_SHIFT 9
+#define TIMER_VALUE_MASK 0x3fffff
+#define TIMER_LIMIT_BIT (1 << 31) /* Bit 31 in Counter-Timer register */
+
+/* The counter timer register has the value offset by 9 bits.
+ * From sun4m manual:
+ * When a counter reaches the value in the corresponding limit register,
+ * the Limit bit is set and the counter is set to 500 nS (i.e. 0x00000200).
+ *
+ * To compensate for this add one to the value.
+ */
+static inline unsigned int timer_value(unsigned int value)
+{
+ return (value + 1) << TIMER_VALUE_SHIFT;
+}
extern __volatile__ unsigned int *master_l10_counter;
-/* FIXME: Make do_[gs]ettimeofday btfixup calls */
-struct timespec;
-BTFIXUPDEF_CALL(int, bus_do_settimeofday, struct timespec *tv)
-#define bus_do_settimeofday(tv) BTFIXUP_CALL(bus_do_settimeofday)(tv)
+extern irqreturn_t notrace timer_interrupt(int dummy, void *dev_id);
+
+#ifdef CONFIG_SMP
+DECLARE_PER_CPU(struct clock_event_device, sparc32_clockevent);
+extern void register_percpu_ce(int cpu);
+#endif
#endif /* !(_SPARC_TIMER_H) */
diff --git a/arch/sparc/include/asm/timex_32.h b/arch/sparc/include/asm/timex_32.h
index a254750e4c03..b6ccdb0d6f7d 100644
--- a/arch/sparc/include/asm/timex_32.h
+++ b/arch/sparc/include/asm/timex_32.h
@@ -12,5 +12,4 @@
typedef unsigned long cycles_t;
#define get_cycles() (0)
-extern u32 (*do_arch_gettimeoffset)(void);
#endif
diff --git a/arch/sparc/include/asm/tlbflush_32.h b/arch/sparc/include/asm/tlbflush_32.h
index fe0a71abc9bb..a5c4142130f5 100644
--- a/arch/sparc/include/asm/tlbflush_32.h
+++ b/arch/sparc/include/asm/tlbflush_32.h
@@ -1,52 +1,16 @@
#ifndef _SPARC_TLBFLUSH_H
#define _SPARC_TLBFLUSH_H
-#include <linux/mm.h>
-// #include <asm/processor.h>
-
-/*
- * TLB flushing:
- *
- * - flush_tlb() flushes the current mm struct TLBs XXX Exists?
- * - flush_tlb_all() flushes all processes TLBs
- * - flush_tlb_mm(mm) flushes the specified mm context TLB's
- * - flush_tlb_page(vma, vmaddr) flushes one page
- * - flush_tlb_range(vma, start, end) flushes a range of pages
- * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
- */
-
-#ifdef CONFIG_SMP
-
-BTFIXUPDEF_CALL(void, local_flush_tlb_all, void)
-BTFIXUPDEF_CALL(void, local_flush_tlb_mm, struct mm_struct *)
-BTFIXUPDEF_CALL(void, local_flush_tlb_range, struct vm_area_struct *, unsigned long, unsigned long)
-BTFIXUPDEF_CALL(void, local_flush_tlb_page, struct vm_area_struct *, unsigned long)
-
-#define local_flush_tlb_all() BTFIXUP_CALL(local_flush_tlb_all)()
-#define local_flush_tlb_mm(mm) BTFIXUP_CALL(local_flush_tlb_mm)(mm)
-#define local_flush_tlb_range(vma,start,end) BTFIXUP_CALL(local_flush_tlb_range)(vma,start,end)
-#define local_flush_tlb_page(vma,addr) BTFIXUP_CALL(local_flush_tlb_page)(vma,addr)
-
-extern void smp_flush_tlb_all(void);
-extern void smp_flush_tlb_mm(struct mm_struct *mm);
-extern void smp_flush_tlb_range(struct vm_area_struct *vma,
- unsigned long start,
- unsigned long end);
-extern void smp_flush_tlb_page(struct vm_area_struct *mm, unsigned long page);
-
-#endif /* CONFIG_SMP */
-
-BTFIXUPDEF_CALL(void, flush_tlb_all, void)
-BTFIXUPDEF_CALL(void, flush_tlb_mm, struct mm_struct *)
-BTFIXUPDEF_CALL(void, flush_tlb_range, struct vm_area_struct *, unsigned long, unsigned long)
-BTFIXUPDEF_CALL(void, flush_tlb_page, struct vm_area_struct *, unsigned long)
-
-#define flush_tlb_all() BTFIXUP_CALL(flush_tlb_all)()
-#define flush_tlb_mm(mm) BTFIXUP_CALL(flush_tlb_mm)(mm)
-#define flush_tlb_range(vma,start,end) BTFIXUP_CALL(flush_tlb_range)(vma,start,end)
-#define flush_tlb_page(vma,addr) BTFIXUP_CALL(flush_tlb_page)(vma,addr)
-
-// #define flush_tlb() flush_tlb_mm(current->active_mm) /* XXX Sure? */
+#include <asm/cachetlb_32.h>
+
+#define flush_tlb_all() \
+ sparc32_cachetlb_ops->tlb_all()
+#define flush_tlb_mm(mm) \
+ sparc32_cachetlb_ops->tlb_mm(mm)
+#define flush_tlb_range(vma, start, end) \
+ sparc32_cachetlb_ops->tlb_range(vma, start, end)
+#define flush_tlb_page(vma, addr) \
+ sparc32_cachetlb_ops->tlb_page(vma, addr)
/*
* This is a kludge, until I know better. --zaitcev XXX
diff --git a/arch/sparc/include/asm/topology_64.h b/arch/sparc/include/asm/topology_64.h
index 8b9c556d630b..1754390a426f 100644
--- a/arch/sparc/include/asm/topology_64.h
+++ b/arch/sparc/include/asm/topology_64.h
@@ -31,25 +31,6 @@ static inline int pcibus_to_node(struct pci_bus *pbus)
cpu_all_mask : \
cpumask_of_node(pcibus_to_node(bus)))
-#define SD_NODE_INIT (struct sched_domain) { \
- .min_interval = 8, \
- .max_interval = 32, \
- .busy_factor = 32, \
- .imbalance_pct = 125, \
- .cache_nice_tries = 2, \
- .busy_idx = 3, \
- .idle_idx = 2, \
- .newidle_idx = 0, \
- .wake_idx = 0, \
- .forkexec_idx = 0, \
- .flags = SD_LOAD_BALANCE \
- | SD_BALANCE_FORK \
- | SD_BALANCE_EXEC \
- | SD_SERIALIZE, \
- .last_balance = jiffies, \
- .balance_interval = 1, \
-}
-
#else /* CONFIG_NUMA */
#include <asm-generic/topology.h>
diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h
index 8303ac481034..d50c310f5d38 100644
--- a/arch/sparc/include/asm/uaccess_32.h
+++ b/arch/sparc/include/asm/uaccess_32.h
@@ -12,7 +12,6 @@
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/errno.h>
-#include <asm/vac-ops.h>
#endif
#ifndef __ASSEMBLY__
diff --git a/arch/sparc/include/asm/vac-ops.h b/arch/sparc/include/asm/vac-ops.h
deleted file mode 100644
index a63e88ef0426..000000000000
--- a/arch/sparc/include/asm/vac-ops.h
+++ /dev/null
@@ -1,127 +0,0 @@
-#ifndef _SPARC_VAC_OPS_H
-#define _SPARC_VAC_OPS_H
-
-/* vac-ops.h: Inline assembly routines to do operations on the Sparc
- * VAC (virtual address cache) for the sun4c.
- *
- * Copyright (C) 1994, David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <asm/sysen.h>
-#include <asm/contregs.h>
-#include <asm/asi.h>
-
-/* The SUN4C models have a virtually addressed write-through
- * cache.
- *
- * The cache tags are directly accessible through an ASI and
- * each have the form:
- *
- * ------------------------------------------------------------
- * | MBZ | CONTEXT | WRITE | PRIV | VALID | MBZ | TagID | MBZ |
- * ------------------------------------------------------------
- * 31 25 24 22 21 20 19 18 16 15 2 1 0
- *
- * MBZ: These bits are either unused and/or reserved and should
- * be written as zeroes.
- *
- * CONTEXT: Records the context to which this cache line belongs.
- *
- * WRITE: A copy of the writable bit from the mmu pte access bits.
- *
- * PRIV: A copy of the privileged bit from the pte access bits.
- *
- * VALID: If set, this line is valid, else invalid.
- *
- * TagID: Fourteen bits of tag ID.
- *
- * Every virtual address is seen by the cache like this:
- *
- * ----------------------------------------
- * | RESV | TagID | LINE | BYTE-in-LINE |
- * ----------------------------------------
- * 31 30 29 16 15 4 3 0
- *
- * RESV: Unused/reserved.
- *
- * TagID: Used to match the Tag-ID in that vac tags.
- *
- * LINE: Which line within the cache
- *
- * BYTE-in-LINE: Which byte within the cache line.
- */
-
-/* Sun4c VAC Tags */
-#define S4CVACTAG_CID 0x01c00000
-#define S4CVACTAG_W 0x00200000
-#define S4CVACTAG_P 0x00100000
-#define S4CVACTAG_V 0x00080000
-#define S4CVACTAG_TID 0x0000fffc
-
-/* Sun4c VAC Virtual Address */
-/* These aren't used, why bother? (Anton) */
-#if 0
-#define S4CVACVA_TID 0x3fff0000
-#define S4CVACVA_LINE 0x0000fff0
-#define S4CVACVA_BIL 0x0000000f
-#endif
-
-/* The indexing of cache lines creates a problem. Because the line
- * field of a virtual address extends past the page offset within
- * the virtual address it is possible to have what are called
- * 'bad aliases' which will create inconsistencies. So we must make
- * sure that within a context that if a physical page is mapped
- * more than once, that 'extra' line bits are the same. If this is
- * not the case, and thus is a 'bad alias' we must turn off the
- * cacheable bit in the pte's of all such pages.
- */
-
-#define S4CVAC_BADBITS 0x0000f000
-
-/* The following is true if vaddr1 and vaddr2 would cause
- * a 'bad alias'.
- */
-#define S4CVAC_BADALIAS(vaddr1, vaddr2) \
- ((((unsigned long) (vaddr1)) ^ ((unsigned long) (vaddr2))) & \
- (S4CVAC_BADBITS))
-
-/* The following structure describes the characteristics of a sun4c
- * VAC as probed from the prom during boot time.
- */
-struct sun4c_vac_props {
- unsigned int num_bytes; /* Size of the cache */
- unsigned int do_hwflushes; /* Hardware flushing available? */
- unsigned int linesize; /* Size of each line in bytes */
- unsigned int log2lsize; /* log2(linesize) */
- unsigned int on; /* VAC is enabled */
-};
-
-extern struct sun4c_vac_props sun4c_vacinfo;
-
-/* sun4c_enable_vac() enables the sun4c virtual address cache. */
-static inline void sun4c_enable_vac(void)
-{
- __asm__ __volatile__("lduba [%0] %1, %%g1\n\t"
- "or %%g1, %2, %%g1\n\t"
- "stba %%g1, [%0] %1\n\t"
- : /* no outputs */
- : "r" ((unsigned int) AC_SENABLE),
- "i" (ASI_CONTROL), "i" (SENABLE_CACHE)
- : "g1", "memory");
- sun4c_vacinfo.on = 1;
-}
-
-/* sun4c_disable_vac() disables the virtual address cache. */
-static inline void sun4c_disable_vac(void)
-{
- __asm__ __volatile__("lduba [%0] %1, %%g1\n\t"
- "andn %%g1, %2, %%g1\n\t"
- "stba %%g1, [%0] %1\n\t"
- : /* no outputs */
- : "r" ((unsigned int) AC_SENABLE),
- "i" (ASI_CONTROL), "i" (SENABLE_CACHE)
- : "g1", "memory");
- sun4c_vacinfo.on = 0;
-}
-
-#endif /* !(_SPARC_VAC_OPS_H) */
diff --git a/arch/sparc/include/asm/vaddrs.h b/arch/sparc/include/asm/vaddrs.h
index 541e13755cec..da6535d88a72 100644
--- a/arch/sparc/include/asm/vaddrs.h
+++ b/arch/sparc/include/asm/vaddrs.h
@@ -34,22 +34,6 @@
#define IOBASE_VADDR 0xfe000000
#define IOBASE_END 0xfe600000
-/*
- * On the sun4/4c we need a place
- * to reliably map locked down kernel data. This includes the
- * task_struct and kernel stack pages of each process plus the
- * scsi buffers during dvma IO transfers, also the floppy buffers
- * during pseudo dma which runs with traps off (no faults allowed).
- * Some quick calculations yield:
- * NR_TASKS <512> * (3 * PAGE_SIZE) == 0x600000
- * Subtract this from 0xc00000 and you get 0x927C0 of vm left
- * over to map SCSI dvma + floppy pseudo-dma buffers. So be
- * careful if you change NR_TASKS or else there won't be enough
- * room for it all.
- */
-#define SUN4C_LOCK_VADDR 0xff000000
-#define SUN4C_LOCK_END 0xffc00000
-
#define KADB_DEBUGGER_BEGVM 0xffc00000 /* Where kern debugger is in virt-mem */
#define KADB_DEBUGGER_ENDVM 0xffd00000
#define DEBUG_FIRSTVADDR KADB_DEBUGGER_BEGVM
diff --git a/arch/sparc/include/asm/winmacro.h b/arch/sparc/include/asm/winmacro.h
index a9be04b0d049..9b7b21764cde 100644
--- a/arch/sparc/include/asm/winmacro.h
+++ b/arch/sparc/include/asm/winmacro.h
@@ -103,37 +103,24 @@
st %scratch, [%cur_reg + TI_W_SAVED];
#ifdef CONFIG_SMP
-/* Results of LOAD_CURRENT() after BTFIXUP for SUN4M, SUN4D & LEON (comments) */
-#define LOAD_CURRENT4M(dest_reg, idreg) \
- rd %tbr, %idreg; \
- sethi %hi(current_set), %dest_reg; \
- srl %idreg, 10, %idreg; \
- or %dest_reg, %lo(current_set), %dest_reg; \
- and %idreg, 0xc, %idreg; \
- ld [%idreg + %dest_reg], %dest_reg;
-
-#define LOAD_CURRENT4D(dest_reg, idreg) \
- lda [%g0] ASI_M_VIKING_TMP1, %idreg; \
- sethi %hi(C_LABEL(current_set)), %dest_reg; \
- sll %idreg, 2, %idreg; \
- or %dest_reg, %lo(C_LABEL(current_set)), %dest_reg; \
- ld [%idreg + %dest_reg], %dest_reg;
-
-#define LOAD_CURRENT_LEON(dest_reg, idreg) \
- rd %asr17, %idreg; \
- sethi %hi(current_set), %dest_reg; \
- srl %idreg, 0x1c, %idreg; \
- or %dest_reg, %lo(current_set), %dest_reg; \
- sll %idreg, 0x2, %idreg; \
- ld [%idreg + %dest_reg], %dest_reg;
-
-/* Blackbox - take care with this... - check smp4m and smp4d before changing this. */
-#define LOAD_CURRENT(dest_reg, idreg) \
- sethi %hi(___b_load_current), %idreg; \
- sethi %hi(current_set), %dest_reg; \
- sethi %hi(boot_cpu_id4), %idreg; \
- or %dest_reg, %lo(current_set), %dest_reg; \
- ldub [%idreg + %lo(boot_cpu_id4)], %idreg; \
+#define LOAD_CURRENT(dest_reg, idreg) \
+661: rd %tbr, %idreg; \
+ srl %idreg, 10, %idreg; \
+ and %idreg, 0xc, %idreg; \
+ .section .cpuid_patch, "ax"; \
+ /* Instruction location. */ \
+ .word 661b; \
+ /* SUN4D implementation. */ \
+ lda [%g0] ASI_M_VIKING_TMP1, %idreg; \
+ sll %idreg, 2, %idreg; \
+ nop; \
+ /* LEON implementation. */ \
+ rd %asr17, %idreg; \
+ srl %idreg, 0x1c, %idreg; \
+ sll %idreg, 0x02, %idreg; \
+ .previous; \
+ sethi %hi(current_set), %dest_reg; \
+ or %dest_reg, %lo(current_set), %dest_reg;\
ld [%idreg + %dest_reg], %dest_reg;
#else
#define LOAD_CURRENT(dest_reg, idreg) \
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index cb85458f89d2..72308f9b0096 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -6,7 +6,6 @@ asflags-y := -ansi
ccflags-y := -Werror
extra-y := head_$(BITS).o
-extra-y += init_task.o
# Undefine sparc when processing vmlinux.lds - it is used
# And teach CPP we are doing $(BITS) builds (for this case)
@@ -28,7 +27,7 @@ obj-y += traps_$(BITS).o
# IRQ
obj-y += irq_$(BITS).o
-obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4c_irq.o sun4d_irq.o
+obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4d_irq.o
obj-y += process_$(BITS).o
obj-y += signal_$(BITS).o
@@ -46,7 +45,6 @@ obj-$(CONFIG_SPARC32) += tadpole.o
obj-y += ptrace_$(BITS).o
obj-y += unaligned_$(BITS).o
obj-y += una_asm_$(BITS).o
-obj-$(CONFIG_SPARC32) += muldiv.o
obj-y += prom_common.o
obj-y += prom_$(BITS).o
obj-y += of_device_common.o
diff --git a/arch/sparc/kernel/auxio_32.c b/arch/sparc/kernel/auxio_32.c
index 56d0f52c3e62..e20cc55fb768 100644
--- a/arch/sparc/kernel/auxio_32.c
+++ b/arch/sparc/kernel/auxio_32.c
@@ -32,7 +32,6 @@ void __init auxio_probe(void)
switch (sparc_cpu_model) {
case sparc_leon:
case sun4d:
- case sun4:
return;
default:
break;
@@ -65,9 +64,8 @@ void __init auxio_probe(void)
r.start = auxregs[0].phys_addr;
r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1;
auxio_register = of_ioremap(&r, 0, auxregs[0].reg_size, "auxio");
- /* Fix the address on sun4m and sun4c. */
- if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 ||
- sparc_cpu_model == sun4c)
+ /* Fix the address on sun4m. */
+ if ((((unsigned long) auxregs[0].phys_addr) & 3) == 3)
auxio_register += (3 - ((unsigned long)auxio_register & 3));
set_auxio(AUXIO_LED, 0);
@@ -86,12 +84,7 @@ void set_auxio(unsigned char bits_on, unsigned char bits_off)
unsigned char regval;
unsigned long flags;
spin_lock_irqsave(&auxio_lock, flags);
- switch(sparc_cpu_model) {
- case sun4c:
- regval = sbus_readb(auxio_register);
- sbus_writeb(((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN,
- auxio_register);
- break;
+ switch (sparc_cpu_model) {
case sun4m:
if(!auxio_register)
break; /* VME chassis sun4m, no auxio. */
diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c
index 6b2f56a6f8af..3d465e87f7e2 100644
--- a/arch/sparc/kernel/devices.c
+++ b/arch/sparc/kernel/devices.c
@@ -21,7 +21,6 @@
#include <asm/cpu_type.h>
extern void clock_stop_probe(void); /* tadpole.c */
-extern void sun4c_probe_memerr_reg(void);
static char *cpu_mid_prop(void)
{
@@ -139,7 +138,4 @@ void __init device_scan(void)
auxio_power_probe();
}
clock_stop_probe();
-
- if (ARCH_SUN4C)
- sun4c_probe_memerr_reg();
}
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c
index b93c2c9ccb1d..f09257c86107 100644
--- a/arch/sparc/kernel/ds.c
+++ b/arch/sparc/kernel/ds.c
@@ -868,7 +868,7 @@ void ldom_power_off(void)
static void ds_conn_reset(struct ds_info *dp)
{
- printk(KERN_ERR "ds-%llu: ds_conn_reset() from %p\n",
+ printk(KERN_ERR "ds-%llu: ds_conn_reset() from %pf\n",
dp->id, __builtin_return_address(0));
}
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index f445e98463e6..2dbe1806e530 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -7,6 +7,7 @@
* Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au)
*/
+#include <linux/linkage.h>
#include <linux/errno.h>
#include <asm/head.h>
@@ -17,10 +18,8 @@
#include <asm/asm-offsets.h>
#include <asm/psr.h>
#include <asm/vaddrs.h>
-#include <asm/memreg.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <asm/pgtsun4c.h>
#include <asm/winmacro.h>
#include <asm/signal.h>
#include <asm/obio.h>
@@ -125,22 +124,11 @@ floppy_tdone:
set auxio_register, %l7
ld [%l7], %l7
- set sparc_cpu_model, %l5
- ld [%l5], %l5
- subcc %l5, 1, %g0 /* enum { sun4c = 1 }; */
- be 1f
- ldub [%l7], %l5
+ ldub [%l7], %l5
or %l5, 0xc2, %l5
stb %l5, [%l7]
andn %l5, 0x02, %l5
- b 2f
- nop
-
-1:
- or %l5, 0xf4, %l5
- stb %l5, [%l7]
- andn %l5, 0x04, %l5
2:
/* Kill some time so the bits set */
@@ -266,6 +254,11 @@ smp4m_ticker:
WRITE_PAUSE
RESTORE_ALL
+#define GET_PROCESSOR4M_ID(reg) \
+ rd %tbr, %reg; \
+ srl %reg, 12, %reg; \
+ and %reg, 3, %reg;
+
/* Here is where we check for possible SMP IPI passed to us
* on some level other than 15 which is the NMI and only used
* for cross calls. That has a separate entry point below.
@@ -328,7 +321,7 @@ linux_trap_ipi15_sun4m:
ld [%o5 + %o0], %o5
ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending
andcc %o3, %o2, %g0
- be 1f ! Must be an NMI async memory error
+ be sun4m_nmi_error ! Must be an NMI async memory error
st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000
WRITE_PAUSE
ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending
@@ -342,27 +335,6 @@ linux_trap_ipi15_sun4m:
nop
b ret_trap_lockless_ipi
clr %l6
-1:
- /* NMI async memory error handling. */
- sethi %hi(0x80000000), %l4
- sethi %hi(sun4m_irq_global), %o5
- ld [%o5 + %lo(sun4m_irq_global)], %l5
- st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x80000000
- WRITE_PAUSE
- ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
- WRITE_PAUSE
- or %l0, PSR_PIL, %l4
- wr %l4, 0x0, %psr
- WRITE_PAUSE
- wr %l4, PSR_ET, %psr
- WRITE_PAUSE
- call sun4m_nmi
- nop
- st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x80000000
- WRITE_PAUSE
- ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
- WRITE_PAUSE
- RESTORE_ALL
.globl smp4d_ticker
/* SMP per-cpu ticker interrupts are handled specially. */
@@ -760,326 +732,37 @@ setcc_trap_handler:
jmp %l2 ! advance over trap instruction
rett %l2 + 0x4 ! like this...
- .align 4
- .globl linux_trap_nmi_sun4c
-linux_trap_nmi_sun4c:
- SAVE_ALL
-
- /* Ugh, we need to clear the IRQ line. This is now
- * a very sun4c specific trap handler...
- */
- sethi %hi(interrupt_enable), %l5
- ld [%l5 + %lo(interrupt_enable)], %l5
- ldub [%l5], %l6
- andn %l6, INTS_ENAB, %l6
- stb %l6, [%l5]
-
- /* Now it is safe to re-enable traps without recursion. */
- or %l0, PSR_PIL, %l0
- wr %l0, PSR_ET, %psr
+sun4m_nmi_error:
+ /* NMI async memory error handling. */
+ sethi %hi(0x80000000), %l4
+ sethi %hi(sun4m_irq_global), %o5
+ ld [%o5 + %lo(sun4m_irq_global)], %l5
+ st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x80000000
WRITE_PAUSE
-
- /* Now call the c-code with the pt_regs frame ptr and the
- * memory error registers as arguments. The ordering chosen
- * here is due to unlatching semantics.
- */
- sethi %hi(AC_SYNC_ERR), %o0
- add %o0, 0x4, %o0
- lda [%o0] ASI_CONTROL, %o2 ! sync vaddr
- sub %o0, 0x4, %o0
- lda [%o0] ASI_CONTROL, %o1 ! sync error
- add %o0, 0xc, %o0
- lda [%o0] ASI_CONTROL, %o4 ! async vaddr
- sub %o0, 0x4, %o0
- lda [%o0] ASI_CONTROL, %o3 ! async error
- call sparc_lvl15_nmi
- add %sp, STACKFRAME_SZ, %o0
-
- RESTORE_ALL
-
- .align 4
- .globl invalid_segment_patch1_ff
- .globl invalid_segment_patch2_ff
-invalid_segment_patch1_ff: cmp %l4, 0xff
-invalid_segment_patch2_ff: mov 0xff, %l3
-
- .align 4
- .globl invalid_segment_patch1_1ff
- .globl invalid_segment_patch2_1ff
-invalid_segment_patch1_1ff: cmp %l4, 0x1ff
-invalid_segment_patch2_1ff: mov 0x1ff, %l3
-
- .align 4
- .globl num_context_patch1_16, num_context_patch2_16
-num_context_patch1_16: mov 0x10, %l7
-num_context_patch2_16: mov 0x10, %l7
-
- .align 4
- .globl vac_linesize_patch_32
-vac_linesize_patch_32: subcc %l7, 32, %l7
-
- .align 4
- .globl vac_hwflush_patch1_on, vac_hwflush_patch2_on
-
-/*
- * Ugly, but we can't use hardware flushing on the sun4 and we'd require
- * two instructions (Anton)
- */
-vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7
-
-vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG
-
- .globl invalid_segment_patch1, invalid_segment_patch2
- .globl num_context_patch1
- .globl vac_linesize_patch, vac_hwflush_patch1
- .globl vac_hwflush_patch2
-
- .align 4
- .globl sun4c_fault
-
-! %l0 = %psr
-! %l1 = %pc
-! %l2 = %npc
-! %l3 = %wim
-! %l7 = 1 for textfault
-! We want error in %l5, vaddr in %l6
-sun4c_fault:
- sethi %hi(AC_SYNC_ERR), %l4
- add %l4, 0x4, %l6 ! AC_SYNC_VA in %l6
- lda [%l6] ASI_CONTROL, %l5 ! Address
- lda [%l4] ASI_CONTROL, %l6 ! Error, retained for a bit
-
- andn %l5, 0xfff, %l5 ! Encode all info into l7
- srl %l6, 14, %l4
-
- and %l4, 2, %l4
- or %l5, %l4, %l4
-
- or %l4, %l7, %l7 ! l7 = [addr,write,txtfault]
-
- andcc %l0, PSR_PS, %g0
- be sun4c_fault_fromuser
- andcc %l7, 1, %g0 ! Text fault?
-
- be 1f
- sethi %hi(KERNBASE), %l4
-
- mov %l1, %l5 ! PC
-
-1:
- cmp %l5, %l4
- blu sun4c_fault_fromuser
- sethi %hi(~((1 << SUN4C_REAL_PGDIR_SHIFT) - 1)), %l4
-
- /* If the kernel references a bum kernel pointer, or a pte which
- * points to a non existent page in ram, we will run this code
- * _forever_ and lock up the machine!!!!! So we must check for
- * this condition, the AC_SYNC_ERR bits are what we must examine.
- * Also a parity error would make this happen as well. So we just
- * check that we are in fact servicing a tlb miss and not some
- * other type of fault for the kernel.
- */
- andcc %l6, 0x80, %g0
- be sun4c_fault_fromuser
- and %l5, %l4, %l5
-
- /* Test for NULL pte_t * in vmalloc area. */
- sethi %hi(VMALLOC_START), %l4
- cmp %l5, %l4
- blu,a invalid_segment_patch1
- lduXa [%l5] ASI_SEGMAP, %l4
-
- sethi %hi(swapper_pg_dir), %l4
- srl %l5, SUN4C_PGDIR_SHIFT, %l6
- or %l4, %lo(swapper_pg_dir), %l4
- sll %l6, 2, %l6
- ld [%l4 + %l6], %l4
- andcc %l4, PAGE_MASK, %g0
- be sun4c_fault_fromuser
- lduXa [%l5] ASI_SEGMAP, %l4
-
-invalid_segment_patch1:
- cmp %l4, 0x7f
- bne 1f
- sethi %hi(sun4c_kfree_ring), %l4
- or %l4, %lo(sun4c_kfree_ring), %l4
- ld [%l4 + 0x18], %l3
- deccc %l3 ! do we have a free entry?
- bcs,a 2f ! no, unmap one.
- sethi %hi(sun4c_kernel_ring), %l4
-
- st %l3, [%l4 + 0x18] ! sun4c_kfree_ring.num_entries--
-
- ld [%l4 + 0x00], %l6 ! entry = sun4c_kfree_ring.ringhd.next
- st %l5, [%l6 + 0x08] ! entry->vaddr = address
-
- ld [%l6 + 0x00], %l3 ! next = entry->next
- ld [%l6 + 0x04], %l7 ! entry->prev
-
- st %l7, [%l3 + 0x04] ! next->prev = entry->prev
- st %l3, [%l7 + 0x00] ! entry->prev->next = next
-
- sethi %hi(sun4c_kernel_ring), %l4
- or %l4, %lo(sun4c_kernel_ring), %l4
- ! head = &sun4c_kernel_ring.ringhd
-
- ld [%l4 + 0x00], %l7 ! head->next
-
- st %l4, [%l6 + 0x04] ! entry->prev = head
- st %l7, [%l6 + 0x00] ! entry->next = head->next
- st %l6, [%l7 + 0x04] ! head->next->prev = entry
-
- st %l6, [%l4 + 0x00] ! head->next = entry
-
- ld [%l4 + 0x18], %l3
- inc %l3 ! sun4c_kernel_ring.num_entries++
- st %l3, [%l4 + 0x18]
- b 4f
- ld [%l6 + 0x08], %l5
-
-2:
- or %l4, %lo(sun4c_kernel_ring), %l4
- ! head = &sun4c_kernel_ring.ringhd
-
- ld [%l4 + 0x04], %l6 ! entry = head->prev
-
- ld [%l6 + 0x08], %l3 ! tmp = entry->vaddr
-
- ! Flush segment from the cache.
- sethi %hi((64 * 1024)), %l7
-9:
-vac_hwflush_patch1:
-vac_linesize_patch:
- subcc %l7, 16, %l7
- bne 9b
-vac_hwflush_patch2:
- sta %g0, [%l3 + %l7] ASI_FLUSHSEG
-
- st %l5, [%l6 + 0x08] ! entry->vaddr = address
-
- ld [%l6 + 0x00], %l5 ! next = entry->next
- ld [%l6 + 0x04], %l7 ! entry->prev
-
- st %l7, [%l5 + 0x04] ! next->prev = entry->prev
- st %l5, [%l7 + 0x00] ! entry->prev->next = next
- st %l4, [%l6 + 0x04] ! entry->prev = head
-
- ld [%l4 + 0x00], %l7 ! head->next
-
- st %l7, [%l6 + 0x00] ! entry->next = head->next
- st %l6, [%l7 + 0x04] ! head->next->prev = entry
- st %l6, [%l4 + 0x00] ! head->next = entry
-
- mov %l3, %l5 ! address = tmp
-
-4:
-num_context_patch1:
- mov 0x08, %l7
-
- ld [%l6 + 0x08], %l4
- ldub [%l6 + 0x0c], %l3
- or %l4, %l3, %l4 ! encode new vaddr/pseg into l4
-
- sethi %hi(AC_CONTEXT), %l3
- lduba [%l3] ASI_CONTROL, %l6
-
- /* Invalidate old mapping, instantiate new mapping,
- * for each context. Registers l6/l7 are live across
- * this loop.
- */
-3: deccc %l7
- sethi %hi(AC_CONTEXT), %l3
- stba %l7, [%l3] ASI_CONTROL
-invalid_segment_patch2:
- mov 0x7f, %l3
- stXa %l3, [%l5] ASI_SEGMAP
- andn %l4, 0x1ff, %l3
- bne 3b
- stXa %l4, [%l3] ASI_SEGMAP
-
- sethi %hi(AC_CONTEXT), %l3
- stba %l6, [%l3] ASI_CONTROL
-
- andn %l4, 0x1ff, %l5
-
-1:
- sethi %hi(VMALLOC_START), %l4
- cmp %l5, %l4
-
- bgeu 1f
- mov 1 << (SUN4C_REAL_PGDIR_SHIFT - PAGE_SHIFT), %l7
-
- sethi %hi(KERNBASE), %l6
-
- sub %l5, %l6, %l4
- srl %l4, PAGE_SHIFT, %l4
- sethi %hi((SUN4C_PAGE_KERNEL & 0xf4000000)), %l3
- or %l3, %l4, %l3
-
- sethi %hi(PAGE_SIZE), %l4
-
-2:
- sta %l3, [%l5] ASI_PTE
- deccc %l7
- inc %l3
- bne 2b
- add %l5, %l4, %l5
-
- b 7f
- sethi %hi(sun4c_kernel_faults), %l4
-
-1:
- srl %l5, SUN4C_PGDIR_SHIFT, %l3
- sethi %hi(swapper_pg_dir), %l4
- or %l4, %lo(swapper_pg_dir), %l4
- sll %l3, 2, %l3
- ld [%l4 + %l3], %l4
- and %l4, PAGE_MASK, %l4
-
- srl %l5, (PAGE_SHIFT - 2), %l6
- and %l6, ((SUN4C_PTRS_PER_PTE - 1) << 2), %l6
- add %l6, %l4, %l6
-
- sethi %hi(PAGE_SIZE), %l4
-
-2:
- ld [%l6], %l3
- deccc %l7
- sta %l3, [%l5] ASI_PTE
- add %l6, 0x4, %l6
- bne 2b
- add %l5, %l4, %l5
-
- sethi %hi(sun4c_kernel_faults), %l4
-7:
- ld [%l4 + %lo(sun4c_kernel_faults)], %l3
- inc %l3
- st %l3, [%l4 + %lo(sun4c_kernel_faults)]
-
- /* Restore condition codes */
- wr %l0, 0x0, %psr
+ ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
WRITE_PAUSE
- jmp %l1
- rett %l2
-
-sun4c_fault_fromuser:
- SAVE_ALL
+ or %l0, PSR_PIL, %l4
+ wr %l4, 0x0, %psr
+ WRITE_PAUSE
+ wr %l4, PSR_ET, %psr
+ WRITE_PAUSE
+ call sun4m_nmi
nop
-
- mov %l7, %o1 ! Decode the info from %l7
- mov %l7, %o2
- and %o1, 1, %o1 ! arg2 = text_faultp
- mov %l7, %o3
- and %o2, 2, %o2 ! arg3 = writep
- andn %o3, 0xfff, %o3 ! arg4 = faulting address
-
- wr %l0, PSR_ET, %psr
+ st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x80000000
WRITE_PAUSE
+ ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
+ WRITE_PAUSE
+ RESTORE_ALL
- call do_sun4c_fault
- add %sp, STACKFRAME_SZ, %o0 ! arg1 = pt_regs ptr
+#ifndef CONFIG_SMP
+ .align 4
+ .globl linux_trap_ipi15_sun4m
+linux_trap_ipi15_sun4m:
+ SAVE_ALL
- RESTORE_ALL
+ ba sun4m_nmi_error
+ nop
+#endif /* CONFIG_SMP */
.align 4
.globl srmmu_fault
@@ -1483,11 +1166,13 @@ fpload:
.globl __ndelay
__ndelay:
save %sp, -STACKFRAME_SZ, %sp
- mov %i0, %o0
- call .umul ! round multiplier up so large ns ok
- mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ)
- call .umul
- mov %i1, %o1 ! udelay_val
+ mov %i0, %o0 ! round multiplier up so large ns ok
+ mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ)
+ umul %o0, %o1, %o0
+ rd %y, %o1
+ mov %i1, %o1 ! udelay_val
+ umul %o0, %o1, %o0
+ rd %y, %o1
ba delay_continue
mov %o1, %o0 ! >>32 later for better resolution
@@ -1496,18 +1181,21 @@ __udelay:
save %sp, -STACKFRAME_SZ, %sp
mov %i0, %o0
sethi %hi(0x10c7), %o1 ! round multiplier up so large us ok
- call .umul
- or %o1, %lo(0x10c7), %o1 ! 2**32 / 1 000 000
- call .umul
- mov %i1, %o1 ! udelay_val
+ or %o1, %lo(0x10c7), %o1 ! 2**32 / 1 000 000
+ umul %o0, %o1, %o0
+ rd %y, %o1
+ mov %i1, %o1 ! udelay_val
+ umul %o0, %o1, %o0
+ rd %y, %o1
sethi %hi(0x028f4b62), %l0 ! Add in rounding constant * 2**32,
or %g0, %lo(0x028f4b62), %l0
addcc %o0, %l0, %o0 ! 2**32 * 0.009 999
bcs,a 3f
add %o1, 0x01, %o1
3:
- call .umul
- mov HZ, %o0 ! >>32 earlier for wider range
+ mov HZ, %o0 ! >>32 earlier for wider range
+ umul %o0, %o1, %o0
+ rd %y, %o1
delay_continue:
cmp %o0, 0x0
@@ -1670,4 +1358,26 @@ flushw_all:
ret
restore
+#ifdef CONFIG_SMP
+ENTRY(hard_smp_processor_id)
+661: rd %tbr, %g1
+ srl %g1, 12, %o0
+ and %o0, 3, %o0
+ .section .cpuid_patch, "ax"
+ /* Instruction location. */
+ .word 661b
+ /* SUN4D implementation. */
+ lda [%g0] ASI_M_VIKING_TMP1, %o0
+ nop
+ nop
+ /* LEON implementation. */
+ rd %asr17, %o0
+ srl %o0, 0x1c, %o0
+ nop
+ .previous
+ retl
+ nop
+ENDPROC(hard_smp_processor_id)
+#endif
+
/* End of entry.S */
diff --git a/arch/sparc/kernel/etrap_32.S b/arch/sparc/kernel/etrap_32.S
index e806fcdc46db..84b5f0d2afde 100644
--- a/arch/sparc/kernel/etrap_32.S
+++ b/arch/sparc/kernel/etrap_32.S
@@ -216,9 +216,7 @@ tsetup_patch6:
/* Call MMU-architecture dependent stack checking
* routine.
*/
- .globl tsetup_mmu_patchme
-tsetup_mmu_patchme:
- b tsetup_sun4c_stackchk
+ b tsetup_srmmu_stackchk
andcc %sp, 0x7, %g0
/* Architecture specific stack checking routines. When either
@@ -228,52 +226,6 @@ tsetup_mmu_patchme:
*/
#define glob_tmp g1
-tsetup_sun4c_stackchk:
- /* Done by caller: andcc %sp, 0x7, %g0 */
- bne trap_setup_user_stack_is_bolixed
- sra %sp, 29, %glob_tmp
-
- add %glob_tmp, 0x1, %glob_tmp
- andncc %glob_tmp, 0x1, %g0
- bne trap_setup_user_stack_is_bolixed
- and %sp, 0xfff, %glob_tmp ! delay slot
-
- /* See if our dump area will be on more than one
- * page.
- */
- add %glob_tmp, 0x38, %glob_tmp
- andncc %glob_tmp, 0xff8, %g0
- be tsetup_sun4c_onepage ! only one page to check
- lda [%sp] ASI_PTE, %glob_tmp ! have to check first page anyways
-
-tsetup_sun4c_twopages:
- /* Is first page ok permission wise? */
- srl %glob_tmp, 29, %glob_tmp
- cmp %glob_tmp, 0x6
- bne trap_setup_user_stack_is_bolixed
- add %sp, 0x38, %glob_tmp /* Is second page in vma hole? */
-
- sra %glob_tmp, 29, %glob_tmp
- add %glob_tmp, 0x1, %glob_tmp
- andncc %glob_tmp, 0x1, %g0
- bne trap_setup_user_stack_is_bolixed
- add %sp, 0x38, %glob_tmp
-
- lda [%glob_tmp] ASI_PTE, %glob_tmp
-
-tsetup_sun4c_onepage:
- srl %glob_tmp, 29, %glob_tmp
- cmp %glob_tmp, 0x6 ! can user write to it?
- bne trap_setup_user_stack_is_bolixed ! failure
- nop
-
- STORE_WINDOW(sp)
-
- restore %g0, %g0, %g0
-
- jmpl %t_retpc + 0x8, %g0
- mov %t_kstack, %sp
-
.globl tsetup_srmmu_stackchk
tsetup_srmmu_stackchk:
/* Check results of callers andcc %sp, 0x7, %g0 */
diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S
index 587785759838..a0f5c20e4b9c 100644
--- a/arch/sparc/kernel/head_32.S
+++ b/arch/sparc/kernel/head_32.S
@@ -26,11 +26,9 @@
#include <asm/pgtsrmmu.h> /* SRMMU_PGDIR_SHIFT */
.data
-/*
- * The following are used with the prom_vector node-ops to figure out
- * the cpu-type
+/* The following are used with the prom_vector node-ops to figure out
+ * the cpu-type
*/
-
.align 4
cputyp:
.word 1
@@ -38,384 +36,35 @@ cputyp:
.align 4
.globl cputypval
cputypval:
- .asciz "sun4c"
+ .asciz "sun4m"
.ascii " "
-cputypvalend:
-cputypvallen = cputypvar - cputypval
-
+/* Tested on SS-5, SS-10 */
.align 4
-/*
- * Sun people can't spell worth damn. "compatability" indeed.
- * At least we *know* we can't spell, and use a spell-checker.
- */
-
-/* Uh, actually Linus it is I who cannot spell. Too much murky
- * Sparc assembly will do this to ya.
- */
cputypvar:
- .asciz "compatability"
-
-/* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */
- .align 4
-cputypvar_sun4m:
.asciz "compatible"
.align 4
-sun4_notsup:
- .asciz "Sparc-Linux sun4 support does no longer exist.\n\n"
+sun4c_notsup:
+ .asciz "Sparc-Linux sun4/sun4c support does no longer exist.\n\n"
.align 4
sun4e_notsup:
.asciz "Sparc-Linux sun4e support does not exist\n\n"
.align 4
- /* The Sparc trap table, bootloader gives us control at _start. */
- __HEAD
- .globl _stext, _start, __stext
- .globl trapbase
-_start: /* danger danger */
-__stext:
-_stext:
-trapbase:
-#ifdef CONFIG_SMP
-trapbase_cpu0:
-#endif
-/* We get control passed to us here at t_zero. */
-t_zero: b gokernel; nop; nop; nop;
-t_tflt: SPARC_TFAULT /* Inst. Access Exception */
-t_bins: TRAP_ENTRY(0x2, bad_instruction) /* Illegal Instruction */
-t_pins: TRAP_ENTRY(0x3, priv_instruction) /* Privileged Instruction */
-t_fpd: TRAP_ENTRY(0x4, fpd_trap_handler) /* Floating Point Disabled */
-t_wovf: WINDOW_SPILL /* Window Overflow */
-t_wunf: WINDOW_FILL /* Window Underflow */
-t_mna: TRAP_ENTRY(0x7, mna_handler) /* Memory Address Not Aligned */
-t_fpe: TRAP_ENTRY(0x8, fpe_trap_handler) /* Floating Point Exception */
-t_dflt: SPARC_DFAULT /* Data Miss Exception */
-t_tio: TRAP_ENTRY(0xa, do_tag_overflow) /* Tagged Instruction Ovrflw */
-t_wpt: TRAP_ENTRY(0xb, do_watchpoint) /* Watchpoint Detected */
-t_badc: BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
-t_irq1: TRAP_ENTRY_INTERRUPT(1) /* IRQ Software/SBUS Level 1 */
-t_irq2: TRAP_ENTRY_INTERRUPT(2) /* IRQ SBUS Level 2 */
-t_irq3: TRAP_ENTRY_INTERRUPT(3) /* IRQ SCSI/DMA/SBUS Level 3 */
-t_irq4: TRAP_ENTRY_INTERRUPT(4) /* IRQ Software Level 4 */
-t_irq5: TRAP_ENTRY_INTERRUPT(5) /* IRQ SBUS/Ethernet Level 5 */
-t_irq6: TRAP_ENTRY_INTERRUPT(6) /* IRQ Software Level 6 */
-t_irq7: TRAP_ENTRY_INTERRUPT(7) /* IRQ Video/SBUS Level 5 */
-t_irq8: TRAP_ENTRY_INTERRUPT(8) /* IRQ SBUS Level 6 */
-t_irq9: TRAP_ENTRY_INTERRUPT(9) /* IRQ SBUS Level 7 */
-t_irq10:TRAP_ENTRY_INTERRUPT(10) /* IRQ Timer #1 (one we use) */
-t_irq11:TRAP_ENTRY_INTERRUPT(11) /* IRQ Floppy Intr. */
-t_irq12:TRAP_ENTRY_INTERRUPT(12) /* IRQ Zilog serial chip */
-t_irq13:TRAP_ENTRY_INTERRUPT(13) /* IRQ Audio Intr. */
-t_irq14:TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */
- .globl t_nmi
-#ifndef CONFIG_SMP
-t_nmi: NMI_TRAP /* Level 15 (NMI) */
-#else
-t_nmi: TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
-#endif
-t_racc: TRAP_ENTRY(0x20, do_reg_access) /* General Register Access Error */
-t_iacce:BAD_TRAP(0x21) /* Instr Access Error */
-t_bad22:BAD_TRAP(0x22) BAD_TRAP(0x23)
-t_cpdis:TRAP_ENTRY(0x24, do_cp_disabled) /* Co-Processor Disabled */
-t_uflsh:SKIP_TRAP(0x25, unimp_flush) /* Unimplemented FLUSH inst. */
-t_bad26:BAD_TRAP(0x26) BAD_TRAP(0x27)
-t_cpexc:TRAP_ENTRY(0x28, do_cp_exception) /* Co-Processor Exception */
-t_dacce:SPARC_DFAULT /* Data Access Error */
-t_hwdz: TRAP_ENTRY(0x2a, do_hw_divzero) /* Division by zero, you lose... */
-t_dserr:BAD_TRAP(0x2b) /* Data Store Error */
-t_daccm:BAD_TRAP(0x2c) /* Data Access MMU-Miss */
-t_bad2d:BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
-t_bad32:BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
-t_bad37:BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
-t_iaccm:BAD_TRAP(0x3c) /* Instr Access MMU-Miss */
-t_bad3d:BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40) BAD_TRAP(0x41)
-t_bad42:BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45) BAD_TRAP(0x46)
-t_bad47:BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a) BAD_TRAP(0x4b)
-t_bad4c:BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f) BAD_TRAP(0x50)
-t_bad51:BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
-t_bad56:BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
-t_bad5b:BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
-t_bad60:BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
-t_bad65:BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
-t_bad6a:BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
-t_bad6f:BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
-t_bad74:BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
-t_bad79:BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
-t_bad7e:BAD_TRAP(0x7e) BAD_TRAP(0x7f)
-t_bad80:BAD_TRAP(0x80) /* SunOS System Call */
-t_sbkpt:BREAKPOINT_TRAP /* Software Breakpoint/KGDB */
-t_divz: TRAP_ENTRY(0x82, do_hw_divzero) /* Divide by zero trap */
-t_flwin:TRAP_ENTRY(0x83, do_flush_windows) /* Flush Windows Trap */
-t_clwin:BAD_TRAP(0x84) /* Clean Windows Trap */
-t_rchk: BAD_TRAP(0x85) /* Range Check */
-t_funal:BAD_TRAP(0x86) /* Fix Unaligned Access Trap */
-t_iovf: BAD_TRAP(0x87) /* Integer Overflow Trap */
-t_bad88:BAD_TRAP(0x88) /* Slowaris System Call */
-t_bad89:BAD_TRAP(0x89) /* Net-B.S. System Call */
-t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e)
-t_bad8f:BAD_TRAP(0x8f)
-t_linux:LINUX_SYSCALL_TRAP /* Linux System Call */
-t_bad91:BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95)
-t_bad96:BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a)
-t_bad9b:BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f)
-t_getcc:GETCC_TRAP /* Get Condition Codes */
-t_setcc:SETCC_TRAP /* Set Condition Codes */
-t_getpsr:GETPSR_TRAP /* Get PSR Register */
-t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
-t_bada7:BAD_TRAP(0xa7)
-t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
-t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
-t_badb1:BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
-t_badb6:BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
-t_badbb:BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
-t_badc0:BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
-t_badc5:BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
-t_badca:BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
-t_badcf:BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
-t_badd4:BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
-t_badd9:BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
-t_badde:BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
-t_bade3:BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
-t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
-t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
-t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
-t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
-t_badfc:BAD_TRAP(0xfc)
-t_kgdb: KGDB_TRAP(0xfd)
-dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */
-dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */
-
- .globl end_traptable
-end_traptable:
-
-#ifdef CONFIG_SMP
- /* Trap tables for the other cpus. */
- .globl trapbase_cpu1, trapbase_cpu2, trapbase_cpu3
-trapbase_cpu1:
- BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
- TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler)
- WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler)
- TRAP_ENTRY(0x8, fpe_trap_handler) SRMMU_DFAULT
- TRAP_ENTRY(0xa, do_tag_overflow) TRAP_ENTRY(0xb, do_watchpoint)
- BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
- TRAP_ENTRY_INTERRUPT(1) TRAP_ENTRY_INTERRUPT(2)
- TRAP_ENTRY_INTERRUPT(3) TRAP_ENTRY_INTERRUPT(4)
- TRAP_ENTRY_INTERRUPT(5) TRAP_ENTRY_INTERRUPT(6)
- TRAP_ENTRY_INTERRUPT(7) TRAP_ENTRY_INTERRUPT(8)
- TRAP_ENTRY_INTERRUPT(9) TRAP_ENTRY_INTERRUPT(10)
- TRAP_ENTRY_INTERRUPT(11) TRAP_ENTRY_INTERRUPT(12)
- TRAP_ENTRY_INTERRUPT(13) TRAP_ENTRY_INTERRUPT(14)
- TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
- TRAP_ENTRY(0x20, do_reg_access) BAD_TRAP(0x21) BAD_TRAP(0x22)
- BAD_TRAP(0x23) TRAP_ENTRY(0x24, do_cp_disabled) SKIP_TRAP(0x25, unimp_flush)
- BAD_TRAP(0x26) BAD_TRAP(0x27) TRAP_ENTRY(0x28, do_cp_exception)
- SRMMU_DFAULT TRAP_ENTRY(0x2a, do_hw_divzero) BAD_TRAP(0x2b) BAD_TRAP(0x2c)
- BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
- BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
- BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
- BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
- BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
- BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
- BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
- BAD_TRAP(0x50)
- BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
- BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
- BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
- BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
- BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
- BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
- BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
- BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
- BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
- BAD_TRAP(0x7e) BAD_TRAP(0x7f)
- BAD_TRAP(0x80)
- BREAKPOINT_TRAP
- TRAP_ENTRY(0x82, do_hw_divzero)
- TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
- BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
- BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
- BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
- LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
- BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
- BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
- BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
- BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
- BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
- BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
- BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
- BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
- BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
- BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
- BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
- BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
- BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
- BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
- BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
- BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
- BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
- BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
- BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
- BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
- BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
- BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
-
-trapbase_cpu2:
- BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
- TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler)
- WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler)
- TRAP_ENTRY(0x8, fpe_trap_handler) SRMMU_DFAULT
- TRAP_ENTRY(0xa, do_tag_overflow) TRAP_ENTRY(0xb, do_watchpoint)
- BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
- TRAP_ENTRY_INTERRUPT(1) TRAP_ENTRY_INTERRUPT(2)
- TRAP_ENTRY_INTERRUPT(3) TRAP_ENTRY_INTERRUPT(4)
- TRAP_ENTRY_INTERRUPT(5) TRAP_ENTRY_INTERRUPT(6)
- TRAP_ENTRY_INTERRUPT(7) TRAP_ENTRY_INTERRUPT(8)
- TRAP_ENTRY_INTERRUPT(9) TRAP_ENTRY_INTERRUPT(10)
- TRAP_ENTRY_INTERRUPT(11) TRAP_ENTRY_INTERRUPT(12)
- TRAP_ENTRY_INTERRUPT(13) TRAP_ENTRY_INTERRUPT(14)
- TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
- TRAP_ENTRY(0x20, do_reg_access) BAD_TRAP(0x21) BAD_TRAP(0x22)
- BAD_TRAP(0x23) TRAP_ENTRY(0x24, do_cp_disabled) SKIP_TRAP(0x25, unimp_flush)
- BAD_TRAP(0x26) BAD_TRAP(0x27) TRAP_ENTRY(0x28, do_cp_exception)
- SRMMU_DFAULT TRAP_ENTRY(0x2a, do_hw_divzero) BAD_TRAP(0x2b) BAD_TRAP(0x2c)
- BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
- BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
- BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
- BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
- BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
- BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
- BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
- BAD_TRAP(0x50)
- BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
- BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
- BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
- BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
- BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
- BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
- BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
- BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
- BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
- BAD_TRAP(0x7e) BAD_TRAP(0x7f)
- BAD_TRAP(0x80)
- BREAKPOINT_TRAP
- TRAP_ENTRY(0x82, do_hw_divzero)
- TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
- BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
- BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
- BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
- LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
- BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
- BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
- BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
- BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
- BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
- BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
- BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
- BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
- BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
- BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
- BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
- BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
- BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
- BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
- BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
- BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
- BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
- BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
- BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
- BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
- BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
- BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
-
-trapbase_cpu3:
- BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
- TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler)
- WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler)
- TRAP_ENTRY(0x8, fpe_trap_handler) SRMMU_DFAULT
- TRAP_ENTRY(0xa, do_tag_overflow) TRAP_ENTRY(0xb, do_watchpoint)
- BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
- TRAP_ENTRY_INTERRUPT(1) TRAP_ENTRY_INTERRUPT(2)
- TRAP_ENTRY_INTERRUPT(3) TRAP_ENTRY_INTERRUPT(4)
- TRAP_ENTRY_INTERRUPT(5) TRAP_ENTRY_INTERRUPT(6)
- TRAP_ENTRY_INTERRUPT(7) TRAP_ENTRY_INTERRUPT(8)
- TRAP_ENTRY_INTERRUPT(9) TRAP_ENTRY_INTERRUPT(10)
- TRAP_ENTRY_INTERRUPT(11) TRAP_ENTRY_INTERRUPT(12)
- TRAP_ENTRY_INTERRUPT(13) TRAP_ENTRY_INTERRUPT(14)
- TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
- TRAP_ENTRY(0x20, do_reg_access) BAD_TRAP(0x21) BAD_TRAP(0x22)
- BAD_TRAP(0x23) TRAP_ENTRY(0x24, do_cp_disabled) SKIP_TRAP(0x25, unimp_flush)
- BAD_TRAP(0x26) BAD_TRAP(0x27) TRAP_ENTRY(0x28, do_cp_exception)
- SRMMU_DFAULT TRAP_ENTRY(0x2a, do_hw_divzero) BAD_TRAP(0x2b) BAD_TRAP(0x2c)
- BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
- BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
- BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
- BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
- BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
- BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
- BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
- BAD_TRAP(0x50)
- BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
- BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
- BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
- BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
- BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
- BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
- BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
- BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
- BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
- BAD_TRAP(0x7e) BAD_TRAP(0x7f)
- BAD_TRAP(0x80)
- BREAKPOINT_TRAP
- TRAP_ENTRY(0x82, do_hw_divzero)
- TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
- BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
- BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
- BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
- LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
- BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
- BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
- BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
- BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
- BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
- BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
- BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
- BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
- BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
- BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
- BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
- BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
- BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
- BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
- BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
- BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
- BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
- BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
- BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
- BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
- BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
- BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
+/* The trap-table - located in the __HEAD section */
+#include "ttable_32.S"
-#endif
.align PAGE_SIZE
/* This was the only reasonable way I could think of to properly align
* these page-table data structures.
*/
- .globl pg0, pg1, pg2, pg3
- .globl empty_bad_page
- .globl empty_bad_page_table
- .globl empty_zero_page
.globl swapper_pg_dir
swapper_pg_dir: .skip PAGE_SIZE
-pg0: .skip PAGE_SIZE
-pg1: .skip PAGE_SIZE
-pg2: .skip PAGE_SIZE
-pg3: .skip PAGE_SIZE
-empty_bad_page: .skip PAGE_SIZE
-empty_bad_page_table: .skip PAGE_SIZE
+ .globl empty_zero_page
empty_zero_page: .skip PAGE_SIZE
.global root_flags
@@ -523,10 +172,10 @@ copy_prom_lvl14:
ldd [%g2 + 0x8], %g4
std %g4, [%g3 + 0x8] ! Copy proms handler
-/* Must determine whether we are on a sun4c MMU, SRMMU, or SUN4/400 MUTANT
- * MMU so we can remap ourselves properly. DON'T TOUCH %l0 thru %l5 in these
- * remapping routines, we need their values afterwards!
+/* DON'T TOUCH %l0 thru %l5 in these remapping routines,
+ * we need their values afterwards!
*/
+
/* Now check whether we are already mapped, if we
* are we can skip all this garbage coming up.
*/
@@ -535,26 +184,29 @@ copy_prom_done:
be go_to_highmem ! this will be a nop then
nop
- set LOAD_ADDR, %g6
+ /* Validate that we are in fact running on an
+ * SRMMU based cpu.
+ */
+ set 0x4000, %g6
cmp %g7, %g6
- bne remap_not_a_sun4 ! This is not a Sun4
+ bne not_a_sun4
nop
- or %g0, 0x1, %g1
- lduba [%g1] ASI_CONTROL, %g1 ! Only safe to try on Sun4.
- subcc %g1, 0x24, %g0 ! Is this a mutant Sun4/400???
- be sun4_mutant_remap ! Ugh, it is...
+halt_sun4_or_sun4c:
+ ld [%g7 + 0x68], %o1
+ set sun4c_notsup, %o0
+ sub %o0, %l6, %o0
+ call %o1
nop
-
- b sun4_normal_remap ! regular sun4, 2 level mmu
+ ba halt_me
nop
-remap_not_a_sun4:
- lda [%g0] ASI_M_MMUREGS, %g1 ! same as ASI_PTE on sun4c
- and %g1, 0x1, %g1 ! Test SRMMU Enable bit ;-)
- cmp %g1, 0x0
- be sun4c_remap ! A sun4c MMU or normal Sun4
+not_a_sun4:
+ lda [%g0] ASI_M_MMUREGS, %g1
+ andcc %g1, 1, %g0
+ be halt_sun4_or_sun4c
nop
+
srmmu_remap:
/* First, check for a viking (TI) module. */
set 0x40000000, %g2
@@ -660,72 +312,6 @@ srmmu_nviking:
b go_to_highmem
nop ! wheee....
- /* This remaps the kernel on Sun4/4xx machines
- * that have the Sun Mutant Three Level MMU.
- * It's like a platypus, Sun didn't have the
- * SRMMU in conception so they kludged the three
- * level logic in the regular Sun4 MMU probably.
- *
- * Basically, you take each entry in the top level
- * directory that maps the low 3MB starting at
- * address zero and put the mapping in the KERNBASE
- * slots. These top level pgd's are called regmaps.
- */
-sun4_mutant_remap:
- or %g0, %g0, %g3 ! source base
- sethi %hi(KERNBASE), %g4 ! destination base
- or %g4, %lo(KERNBASE), %g4
- sethi %hi(0x300000), %g5
- or %g5, %lo(0x300000), %g5 ! upper bound 3MB
- or %g0, 0x1, %l6
- sll %l6, 24, %l6 ! Regmap mapping size
- add %g3, 0x2, %g3 ! Base magic
- add %g4, 0x2, %g4 ! Base magic
-
- /* Main remapping loop on Sun4-Mutant-MMU.
- * "I am not an animal..." -Famous Mutant Person
- */
-sun4_mutant_loop:
- lduha [%g3] ASI_REGMAP, %g2 ! Get lower entry
- stha %g2, [%g4] ASI_REGMAP ! Store in high entry
- add %g4, %l6, %g4 ! Move up high memory ptr
- subcc %g3, %g5, %g0 ! Reached our limit?
- blu sun4_mutant_loop ! Nope, loop again
- add %g3, %l6, %g3 ! delay, Move up low ptr
- b go_to_highmem ! Jump to high memory.
- nop
-
- /* The following is for non-4/4xx sun4 MMU's. */
-sun4_normal_remap:
- mov 0, %g3 ! source base
- set KERNBASE, %g4 ! destination base
- set 0x300000, %g5 ! upper bound 3MB
- mov 1, %l6
- sll %l6, 18, %l6 ! sun4 mmu segmap size
-sun4_normal_loop:
- lduha [%g3] ASI_SEGMAP, %g6 ! load phys_seg
- stha %g6, [%g4] ASI_SEGMAP ! stort new virt mapping
- add %g3, %l6, %g3 ! increment source pointer
- subcc %g3, %g5, %g0 ! reached limit?
- blu sun4_normal_loop ! nope, loop again
- add %g4, %l6, %g4 ! delay, increment dest ptr
- b go_to_highmem
- nop
-
- /* The following works for Sun4c MMU's */
-sun4c_remap:
- mov 0, %g3 ! source base
- set KERNBASE, %g4 ! destination base
- set 0x300000, %g5 ! upper bound 3MB
- mov 1, %l6
- sll %l6, 18, %l6 ! sun4c mmu segmap size
-sun4c_remap_loop:
- lda [%g3] ASI_SEGMAP, %g6 ! load phys_seg
- sta %g6, [%g4] ASI_SEGMAP ! store new virt mapping
- add %g3, %l6, %g3 ! Increment source ptr
- subcc %g3, %g5, %g0 ! Reached limit?
- bl sun4c_remap_loop ! Nope, loop again
- add %g4, %l6, %g4 ! delay, Increment dest ptr
/* Now do a non-relative jump so that PC is in high-memory */
go_to_highmem:
@@ -750,35 +336,12 @@ execute_in_high_mem:
sethi %hi(linux_dbvec), %g1
st %o1, [%g1 + %lo(linux_dbvec)]
- ld [%o0 + 0x4], %o3
- and %o3, 0x3, %o5 ! get the version
-
- cmp %o3, 0x2 ! a v2 prom?
- be found_version
- nop
-
- /* paul@sfe.com.au */
- cmp %o3, 0x3 ! a v3 prom?
- be found_version
- nop
-
-/* Old sun4's pass our load address into %o0 instead of the prom
- * pointer. On sun4's you have to hard code the romvec pointer into
- * your code. Sun probably still does that because they don't even
- * trust their own "OpenBoot" specifications.
- */
- set LOAD_ADDR, %g6
- cmp %o0, %g6 ! an old sun4?
- be sun4_init
- nop
-
-found_version:
/* Get the machine type via the mysterious romvec node operations. */
- add %g7, 0x1c, %l1
+ add %g7, 0x1c, %l1
ld [%l1], %l0
ld [%l0], %l0
- call %l0
+ call %l0
or %g0, %g0, %o0 ! next_node(0) = first_node
or %o0, %g0, %g6
@@ -786,28 +349,13 @@ found_version:
or %o1, %lo(cputypvar), %o1
sethi %hi(cputypval), %o2 ! information, the string
or %o2, %lo(cputypval), %o2
- ld [%l1], %l0 ! 'compatibility' tells
+ ld [%l1], %l0 ! 'compatible' tells
ld [%l0 + 0xc], %l0 ! that we want 'sun4x' where
- call %l0 ! x is one of '', 'c', 'm',
- nop ! 'd' or 'e'. %o2 holds pointer
+ call %l0 ! x is one of 'm', 'd' or 'e'.
+ nop ! %o2 holds pointer
! to a buf where above string
! will get stored by the prom.
- subcc %o0, %g0, %g0
- bpos got_prop ! Got the property
- nop
-
- or %g6, %g0, %o0
- sethi %hi(cputypvar_sun4m), %o1
- or %o1, %lo(cputypvar_sun4m), %o1
- sethi %hi(cputypval), %o2
- or %o2, %lo(cputypval), %o2
- ld [%l1], %l0
- ld [%l0 + 0xc], %l0
- call %l0
- nop
-
-got_prop:
#ifdef CONFIG_SPARC_LEON
/* no cpu-type check is needed, it is a SPARC-LEON */
@@ -826,45 +374,29 @@ got_prop:
/* Update boot_cpu_id only on boot cpu */
stub %g1, [%g2 + %lo(boot_cpu_id)]
- ba sun4c_continue_boot
+ ba continue_boot
nop
#endif
+
+/* Check to cputype. We may be booted on a sun4u (64 bit box),
+ * and sun4d needs special treatment.
+ */
+
set cputypval, %o2
ldub [%o2 + 0x4], %l1
- cmp %l1, ' '
- be 1f
- cmp %l1, 'c'
- be 1f
- cmp %l1, 'm'
- be 1f
+ cmp %l1, 'm'
+ be sun4m_init
cmp %l1, 's'
- be 1f
+ be sun4m_init
cmp %l1, 'd'
- be 1f
+ be sun4d_init
cmp %l1, 'e'
be no_sun4e_here ! Could be a sun4e.
nop
b no_sun4u_here ! AIEEE, a V9 sun4u... Get our BIG BROTHER kernel :))
nop
-1: set cputypval, %l1
- ldub [%l1 + 0x4], %l1
- cmp %l1, 'm' ! Test for sun4d, sun4e ?
- be sun4m_init
- cmp %l1, 's' ! Treat sun4s as sun4m
- be sun4m_init
- cmp %l1, 'd' ! Let us see how the beast will die
- be sun4d_init
- nop
-
- /* Jump into mmu context zero. */
- set AC_CONTEXT, %g1
- stba %g0, [%g1] ASI_CONTROL
-
- b sun4c_continue_boot
- nop
-
/* CPUID in bootbus can be found at PA 0xff0140000 */
#define SUN4D_BOOTBUS_CPUID 0xf0140000
@@ -892,66 +424,6 @@ sun4d_init:
/* Fall through to sun4m_init */
sun4m_init:
- /* XXX Fucking Cypress... */
- lda [%g0] ASI_M_MMUREGS, %g5
- srl %g5, 28, %g4
-
- cmp %g4, 1
- bne 1f
- srl %g5, 24, %g4
-
- and %g4, 0xf, %g4
- cmp %g4, 7 /* This would be a HyperSparc. */
-
- bne 2f
- nop
-
-1:
-
-#define PATCH_IT(dst, src) \
- set (dst), %g5; \
- set (src), %g4; \
- ld [%g4], %g3; \
- st %g3, [%g5]; \
- ld [%g4+0x4], %g3; \
- st %g3, [%g5+0x4];
-
- /* Signed multiply. */
- PATCH_IT(.mul, .mul_patch)
- PATCH_IT(.mul+0x08, .mul_patch+0x08)
-
- /* Signed remainder. */
- PATCH_IT(.rem, .rem_patch)
- PATCH_IT(.rem+0x08, .rem_patch+0x08)
- PATCH_IT(.rem+0x10, .rem_patch+0x10)
- PATCH_IT(.rem+0x18, .rem_patch+0x18)
- PATCH_IT(.rem+0x20, .rem_patch+0x20)
- PATCH_IT(.rem+0x28, .rem_patch+0x28)
-
- /* Signed division. */
- PATCH_IT(.div, .div_patch)
- PATCH_IT(.div+0x08, .div_patch+0x08)
- PATCH_IT(.div+0x10, .div_patch+0x10)
- PATCH_IT(.div+0x18, .div_patch+0x18)
- PATCH_IT(.div+0x20, .div_patch+0x20)
-
- /* Unsigned multiply. */
- PATCH_IT(.umul, .umul_patch)
- PATCH_IT(.umul+0x08, .umul_patch+0x08)
-
- /* Unsigned remainder. */
- PATCH_IT(.urem, .urem_patch)
- PATCH_IT(.urem+0x08, .urem_patch+0x08)
- PATCH_IT(.urem+0x10, .urem_patch+0x10)
- PATCH_IT(.urem+0x18, .urem_patch+0x18)
-
- /* Unsigned division. */
- PATCH_IT(.udiv, .udiv_patch)
- PATCH_IT(.udiv+0x08, .udiv_patch+0x08)
- PATCH_IT(.udiv+0x10, .udiv_patch+0x10)
-
-#undef PATCH_IT
-
/* Ok, the PROM could have done funny things and apple cider could still
* be sitting in the fault status/address registers. Read them all to
* clear them so we don't get magic faults later on.
@@ -962,7 +434,7 @@ sun4m_init:
srl %o1, 28, %o1 ! Get a type of the CPU
subcc %o1, 4, %g0 ! TI: Viking or MicroSPARC
- be sun4c_continue_boot
+ be continue_boot
nop
set AC_M_SFSR, %o0
@@ -972,7 +444,7 @@ sun4m_init:
/* Fujitsu MicroSPARC-II has no asynchronous flavors of FARs */
subcc %o1, 0, %g0
- be sun4c_continue_boot
+ be continue_boot
nop
set AC_M_AFSR, %o0
@@ -982,8 +454,7 @@ sun4m_init:
nop
-sun4c_continue_boot:
-
+continue_boot:
/* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's
* show-time!
@@ -1026,10 +497,7 @@ sun4c_continue_boot:
mov %g0, %g3
stub %g3, [%g2 + %lo(boot_cpu_id)]
-1: /* boot_cpu_id set. calculate boot_cpu_id4 = boot_cpu_id*4 */
- sll %g3, 2, %g3
- sethi %hi(boot_cpu_id4), %g2
- stub %g3, [%g2 + %lo(boot_cpu_id4)]
+1: sll %g3, 2, %g3
/* Initialize the uwinmask value for init task just in case.
* But first make current_set[boot_cpu_id] point to something useful.
@@ -1165,19 +633,6 @@ sun4c_continue_boot:
call halt_me
nop
-sun4_init:
- sethi %hi(SUN4_PROM_VECTOR+0x84), %o1
- ld [%o1 + %lo(SUN4_PROM_VECTOR+0x84)], %o1
- set sun4_notsup, %o0
- call %o1 /* printf */
- nop
- sethi %hi(SUN4_PROM_VECTOR+0xc4), %o1
- ld [%o1 + %lo(SUN4_PROM_VECTOR+0xc4)], %o1
- call %o1 /* exittomon */
- nop
-1: ba 1b ! Cannot exit into KMON
- nop
-
no_sun4e_here:
ld [%g7 + 0x68], %o1
set sun4e_notsup, %o0
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S
index 0d810c2f1d00..b42ddbf9651e 100644
--- a/arch/sparc/kernel/head_64.S
+++ b/arch/sparc/kernel/head_64.S
@@ -906,7 +906,7 @@ swapper_4m_tsb:
* error and will instead write junk into the relocation and
* you'll have an unbootable kernel.
*/
-#include "ttable.S"
+#include "ttable_64.S"
! 0x0000000000428000
diff --git a/arch/sparc/kernel/idprom.c b/arch/sparc/kernel/idprom.c
index 9167db40720e..6bd75012109d 100644
--- a/arch/sparc/kernel/idprom.c
+++ b/arch/sparc/kernel/idprom.c
@@ -25,22 +25,9 @@ static struct idprom idprom_buffer;
* of the Sparc CPU and have a meaningful IDPROM machtype value that we
* know about. See asm-sparc/machines.h for empirical constants.
*/
-static struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES] = {
-/* First, Sun4's */
-{ .name = "Sun 4/100 Series", .id_machtype = (SM_SUN4 | SM_4_110) },
-{ .name = "Sun 4/200 Series", .id_machtype = (SM_SUN4 | SM_4_260) },
-{ .name = "Sun 4/300 Series", .id_machtype = (SM_SUN4 | SM_4_330) },
-{ .name = "Sun 4/400 Series", .id_machtype = (SM_SUN4 | SM_4_470) },
-/* Now Leon */
+static struct Sun_Machine_Models Sun_Machines[] = {
+/* First, Leon */
{ .name = "Leon3 System-on-a-Chip", .id_machtype = (M_LEON | M_LEON3_SOC) },
-/* Now, Sun4c's */
-{ .name = "Sun4c SparcStation 1", .id_machtype = (SM_SUN4C | SM_4C_SS1) },
-{ .name = "Sun4c SparcStation IPC", .id_machtype = (SM_SUN4C | SM_4C_IPC) },
-{ .name = "Sun4c SparcStation 1+", .id_machtype = (SM_SUN4C | SM_4C_SS1PLUS) },
-{ .name = "Sun4c SparcStation SLC", .id_machtype = (SM_SUN4C | SM_4C_SLC) },
-{ .name = "Sun4c SparcStation 2", .id_machtype = (SM_SUN4C | SM_4C_SS2) },
-{ .name = "Sun4c SparcStation ELC", .id_machtype = (SM_SUN4C | SM_4C_ELC) },
-{ .name = "Sun4c SparcStation IPX", .id_machtype = (SM_SUN4C | SM_4C_IPX) },
/* Finally, early Sun4m's */
{ .name = "Sun4m SparcSystem600", .id_machtype = (SM_SUN4M | SM_4M_SS60) },
{ .name = "Sun4m SparcStation10/20", .id_machtype = (SM_SUN4M | SM_4M_SS50) },
@@ -53,7 +40,7 @@ static void __init display_system_type(unsigned char machtype)
char sysname[128];
register int i;
- for (i = 0; i < NUM_SUN_MACHINES; i++) {
+ for (i = 0; i < ARRAY_SIZE(Sun_Machines); i++) {
if (Sun_Machines[i].id_machtype == machtype) {
if (machtype != (SM_SUN4M_OBP | 0x00) ||
prom_getproperty(prom_root_node, "banner-name",
diff --git a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c
deleted file mode 100644
index 35f141a9f506..000000000000
--- a/arch/sparc/kernel/init_task.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init_task.h>
-#include <linux/mqueue.h>
-
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
-
-/* .text section in head.S is aligned at 8k boundary and this gets linked
- * right after that so that the init_thread_union is aligned properly as well.
- * If this is not aligned on a 8k boundary, then you should change code
- * in etrap.S which assumes it.
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 21bd73943f7f..a2846f5e32d8 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -50,6 +50,8 @@
#include <asm/io-unit.h>
#include <asm/leon.h>
+const struct sparc32_dma_ops *sparc32_dma_ops;
+
/* This function must make sure that caches and memory are coherent after DMA
* On LEON systems without cache snooping it flushes the entire D-CACHE.
*/
@@ -229,7 +231,7 @@ _sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz)
}
pa &= PAGE_MASK;
- sparc_mapiorange(bus, pa, res->start, resource_size(res));
+ srmmu_mapiorange(bus, pa, res->start, resource_size(res));
return (void __iomem *)(unsigned long)(res->start + offset);
}
@@ -243,7 +245,7 @@ static void _sparc_free_io(struct resource *res)
plen = resource_size(res);
BUG_ON((plen & (PAGE_SIZE-1)) != 0);
- sparc_unmapiorange(res->start, plen);
+ srmmu_unmapiorange(res->start, plen);
release_resource(res);
}
@@ -292,13 +294,13 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
goto err_nova;
}
- // XXX The mmu_map_dma_area does this for us below, see comments.
- // sparc_mapiorange(0, virt_to_phys(va), res->start, len_total);
+ // XXX The sbus_map_dma_area does this for us below, see comments.
+ // srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
/*
* XXX That's where sdev would be used. Currently we load
* all iommu tables with the same translations.
*/
- if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0)
+ if (sbus_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0)
goto err_noiommu;
res->name = op->dev.of_node->name;
@@ -343,7 +345,7 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p,
kfree(res);
pgv = virt_to_page(p);
- mmu_unmap_dma_area(dev, ba, n);
+ sbus_unmap_dma_area(dev, ba, n);
__free_pages(pgv, get_order(n));
}
@@ -381,11 +383,6 @@ static int sbus_map_sg(struct device *dev, struct scatterlist *sg, int n,
enum dma_data_direction dir, struct dma_attrs *attrs)
{
mmu_get_scsi_sgl(dev, sg, n);
-
- /*
- * XXX sparc64 can return a partial length here. sun4c should do this
- * but it currently panics if it can't fulfill the request - Anton
- */
return n;
}
@@ -469,7 +466,7 @@ static void *pci32_alloc_coherent(struct device *dev, size_t len,
printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total);
goto err_nova;
}
- sparc_mapiorange(0, virt_to_phys(va), res->start, len_total);
+ srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
*pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */
return (void *) res->start;
@@ -514,7 +511,7 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
}
dma_make_coherent(ba, n);
- sparc_unmapiorange((unsigned long)p, n);
+ srmmu_unmapiorange((unsigned long)p, n);
release_resource(res);
kfree(res);
diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h
index 5a021dd2f854..b66b6aad1d6d 100644
--- a/arch/sparc/kernel/irq.h
+++ b/arch/sparc/kernel/irq.h
@@ -1,6 +1,5 @@
#include <linux/platform_device.h>
-#include <asm/btfixup.h>
#include <asm/cpu_type.h>
struct irq_bucket {
@@ -10,6 +9,9 @@ struct irq_bucket {
unsigned int pil;
};
+#define SUN4M_HARD_INT(x) (0x000000001 << (x))
+#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
+
#define SUN4D_MAX_BOARD 10
#define SUN4D_MAX_IRQ ((SUN4D_MAX_BOARD + 2) << 5)
@@ -41,52 +43,46 @@ struct sun4m_irq_global {
extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
extern struct sun4m_irq_global __iomem *sun4m_irq_global;
+/* The following definitions describe the individual platform features: */
+#define FEAT_L10_CLOCKSOURCE (1 << 0) /* L10 timer is used as a clocksource */
+#define FEAT_L10_CLOCKEVENT (1 << 1) /* L10 timer is used as a clockevent */
+#define FEAT_L14_ONESHOT (1 << 2) /* L14 timer clockevent can oneshot */
+
/*
- * Platform specific irq configuration
+ * Platform specific configuration
* The individual platforms assign their platform
* specifics in their init functions.
*/
-struct sparc_irq_config {
- void (*init_timers)(irq_handler_t);
+struct sparc_config {
+ void (*init_timers)(void);
unsigned int (*build_device_irq)(struct platform_device *op,
unsigned int real_irq);
+
+ /* generic clockevent features - see FEAT_* above */
+ int features;
+
+ /* clock rate used for clock event timer */
+ int clock_rate;
+
+ /* one period for clock source timer */
+ unsigned int cs_period;
+
+ /* function to obtain offsett for cs period */
+ unsigned int (*get_cycles_offset)(void);
+
+ void (*clear_clock_irq)(void);
+ void (*load_profile_irq)(int cpu, unsigned int limit);
};
-extern struct sparc_irq_config sparc_irq_config;
+extern struct sparc_config sparc_config;
unsigned int irq_alloc(unsigned int real_irq, unsigned int pil);
void irq_link(unsigned int irq);
void irq_unlink(unsigned int irq);
void handler_irq(unsigned int pil, struct pt_regs *regs);
-/* Dave Redman (djhr@tadpole.co.uk)
- * changed these to function pointers.. it saves cycles and will allow
- * the irq dependencies to be split into different files at a later date
- * sun4c_irq.c, sun4m_irq.c etc so we could reduce the kernel size.
- * Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Changed these to btfixup entities... It saves cycles :)
- */
-
-BTFIXUPDEF_CALL(void, clear_clock_irq, void)
-BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int)
-
-static inline void clear_clock_irq(void)
-{
- BTFIXUP_CALL(clear_clock_irq)();
-}
-
-static inline void load_profile_irq(int cpu, int limit)
-{
- BTFIXUP_CALL(load_profile_irq)(cpu, limit);
-}
+unsigned long leon_get_irqmask(unsigned int irq);
#ifdef CONFIG_SMP
-BTFIXUPDEF_CALL(void, set_cpu_int, int, int)
-BTFIXUPDEF_CALL(void, clear_cpu_int, int, int)
-BTFIXUPDEF_CALL(void, set_irq_udt, int)
-
-#define set_cpu_int(cpu,level) BTFIXUP_CALL(set_cpu_int)(cpu,level)
-#define clear_cpu_int(cpu,level) BTFIXUP_CALL(clear_cpu_int)(cpu,level)
-#define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu)
/* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */
#define SUN4D_IPI_IRQ 13
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c
index b2668afd1c34..ae04914f7774 100644
--- a/arch/sparc/kernel/irq_32.c
+++ b/arch/sparc/kernel/irq_32.c
@@ -23,16 +23,8 @@
#include "kernel.h"
#include "irq.h"
-#ifdef CONFIG_SMP
-#define SMP_NOP2 "nop; nop;\n\t"
-#define SMP_NOP3 "nop; nop; nop;\n\t"
-#else
-#define SMP_NOP2
-#define SMP_NOP3
-#endif /* SMP */
-
/* platform specific irq setup */
-struct sparc_irq_config sparc_irq_config;
+struct sparc_config sparc_config;
unsigned long arch_local_irq_save(void)
{
@@ -41,7 +33,6 @@ unsigned long arch_local_irq_save(void)
__asm__ __volatile__(
"rd %%psr, %0\n\t"
- SMP_NOP3 /* Sun4m + Cypress + SMP bug */
"or %0, %2, %1\n\t"
"wr %1, 0, %%psr\n\t"
"nop; nop; nop\n"
@@ -59,7 +50,6 @@ void arch_local_irq_enable(void)
__asm__ __volatile__(
"rd %%psr, %0\n\t"
- SMP_NOP3 /* Sun4m + Cypress + SMP bug */
"andn %0, %1, %0\n\t"
"wr %0, 0, %%psr\n\t"
"nop; nop; nop\n"
@@ -76,7 +66,6 @@ void arch_local_irq_restore(unsigned long old_psr)
__asm__ __volatile__(
"rd %%psr, %0\n\t"
"and %2, %1, %2\n\t"
- SMP_NOP2 /* Sun4m + Cypress + SMP bug */
"andn %0, %1, %0\n\t"
"wr %0, %2, %%psr\n\t"
"nop; nop; nop\n"
@@ -346,11 +335,6 @@ void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
void __init init_IRQ(void)
{
switch (sparc_cpu_model) {
- case sun4c:
- case sun4:
- sun4c_init_IRQ();
- break;
-
case sun4m:
pcic_probe();
if (pcic_present())
@@ -371,6 +355,5 @@ void __init init_IRQ(void)
prom_printf("Cannot initialize IRQs on this Sun machine...");
break;
}
- btfixup();
}
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index dff2c3d7d370..9bcbbe2c4e7e 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -799,7 +799,7 @@ static void kill_prom_timer(void)
prom_limit0 = prom_timers->limit0;
prom_limit1 = prom_timers->limit1;
- /* Just as in sun4c/sun4m PROM uses timer which ticks at IRQ 14.
+ /* Just as in sun4c PROM uses timer which ticks at IRQ 14.
* We turn both off here just to be paranoid.
*/
prom_timers->limit0 = 0;
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h
index fd6c36b1df74..a86372d34587 100644
--- a/arch/sparc/kernel/kernel.h
+++ b/arch/sparc/kernel/kernel.h
@@ -32,9 +32,6 @@ extern void cpu_probe(void);
/* traps_32.c */
extern void handle_hw_divzero(struct pt_regs *regs, unsigned long pc,
unsigned long npc, unsigned long psr);
-/* muldiv.c */
-extern int do_user_muldiv (struct pt_regs *, unsigned long);
-
/* irq_32.c */
extern struct irqaction static_irqaction[];
extern int static_irq_count;
@@ -43,12 +40,7 @@ extern spinlock_t irq_action_lock;
extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs);
extern void init_IRQ(void);
-/* sun4c_irq.c */
-extern void sun4c_init_IRQ(void);
-
/* sun4m_irq.c */
-extern unsigned int lvl14_resolution;
-
extern void sun4m_init_IRQ(void);
extern void sun4m_unmask_profile_irq(void);
extern void sun4m_clear_profile_irq(int cpu);
@@ -85,8 +77,6 @@ extern unsigned int patchme_maybe_smp_msg[];
extern void floppy_hardint(void);
/* trampoline_32.S */
-extern int __smp4m_processor_id(void);
-extern int __smp4d_processor_id(void);
extern unsigned long sun4m_cpu_startup;
extern unsigned long sun4d_cpu_startup;
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index 35e43673c453..77c1b916e4dd 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -10,6 +10,8 @@
#include <linux/of_platform.h>
#include <linux/interrupt.h>
#include <linux/of_device.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
#include <asm/oplib.h>
#include <asm/timer.h>
@@ -84,7 +86,7 @@ void leon_eirq_setup(unsigned int eirq)
sparc_leon_eirq = eirq;
}
-static inline unsigned long get_irqmask(unsigned int irq)
+unsigned long leon_get_irqmask(unsigned int irq)
{
unsigned long mask;
@@ -210,7 +212,7 @@ unsigned int leon_build_device_irq(unsigned int real_irq,
unsigned long mask;
irq = 0;
- mask = get_irqmask(real_irq);
+ mask = leon_get_irqmask(real_irq);
if (mask == 0)
goto out;
@@ -250,7 +252,38 @@ void leon_update_virq_handling(unsigned int virq,
irq_set_chip_data(virq, (void *)mask);
}
-void __init leon_init_timers(irq_handler_t counter_fn)
+static u32 leon_cycles_offset(void)
+{
+ u32 rld, val, off;
+ rld = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld);
+ val = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val);
+ off = rld - val;
+ return rld - val;
+}
+
+#ifdef CONFIG_SMP
+
+/* smp clockevent irq */
+irqreturn_t leon_percpu_timer_ce_interrupt(int irq, void *unused)
+{
+ struct clock_event_device *ce;
+ int cpu = smp_processor_id();
+
+ leon_clear_profile_irq(cpu);
+
+ ce = &per_cpu(sparc32_clockevent, cpu);
+
+ irq_enter();
+ if (ce->event_handler)
+ ce->event_handler(ce);
+ irq_exit();
+
+ return IRQ_HANDLED;
+}
+
+#endif /* CONFIG_SMP */
+
+void __init leon_init_timers(void)
{
int irq, eirq;
struct device_node *rootnp, *np, *nnp;
@@ -260,6 +293,14 @@ void __init leon_init_timers(irq_handler_t counter_fn)
int ampopts;
int err;
+ sparc_config.get_cycles_offset = leon_cycles_offset;
+ sparc_config.cs_period = 1000000 / HZ;
+ sparc_config.features |= FEAT_L10_CLOCKSOURCE;
+
+#ifndef CONFIG_SMP
+ sparc_config.features |= FEAT_L10_CLOCKEVENT;
+#endif
+
leondebug_irq_disable = 0;
leon_debug_irqout = 0;
master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
@@ -369,7 +410,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
leon_eirq_setup(eirq);
irq = _leon_build_device_irq(NULL, leon3_gptimer_irq+leon3_gptimer_idx);
- err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
+ err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
if (err) {
printk(KERN_ERR "unable to attach timer IRQ%d\n", irq);
prom_halt();
@@ -386,7 +427,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
*/
local_irq_save(flags);
patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
- local_flush_cache_all();
+ local_ops->cache_all();
local_irq_restore(flags);
}
#endif
@@ -401,7 +442,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
/* Install per-cpu IRQ handler for broadcasted ticker */
irq = leon_build_device_irq(leon3_ticker_irq, handle_percpu_irq,
"per-cpu", 0);
- err = request_irq(irq, leon_percpu_timer_interrupt,
+ err = request_irq(irq, leon_percpu_timer_ce_interrupt,
IRQF_PERCPU | IRQF_TIMER, "ticker",
NULL);
if (err) {
@@ -422,13 +463,12 @@ bad:
return;
}
-void leon_clear_clock_irq(void)
+static void leon_clear_clock_irq(void)
{
}
-void leon_load_profile_irq(int cpu, unsigned int limit)
+static void leon_load_profile_irq(int cpu, unsigned int limit)
{
- BUG();
}
void __init leon_trans_init(struct device_node *dp)
@@ -457,25 +497,6 @@ void __init leon_node_init(struct device_node *dp, struct device_node ***nextp)
}
#ifdef CONFIG_SMP
-
-void leon_set_cpu_int(int cpu, int level)
-{
- unsigned long mask;
- mask = get_irqmask(level);
- LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask);
-}
-
-static void leon_clear_ipi(int cpu, int level)
-{
- unsigned long mask;
- mask = get_irqmask(level);
- LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask<<16);
-}
-
-static void leon_set_udt(int cpu)
-{
-}
-
void leon_clear_profile_irq(int cpu)
{
}
@@ -483,7 +504,7 @@ void leon_clear_profile_irq(int cpu)
void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu)
{
unsigned long mask, flags, *addr;
- mask = get_irqmask(irq_nr);
+ mask = leon_get_irqmask(irq_nr);
spin_lock_irqsave(&leon_irq_lock, flags);
addr = (unsigned long *)LEON_IMASK(cpu);
LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | mask));
@@ -494,20 +515,11 @@ void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu)
void __init leon_init_IRQ(void)
{
- sparc_irq_config.init_timers = leon_init_timers;
- sparc_irq_config.build_device_irq = _leon_build_device_irq;
-
- BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq,
- BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(load_profile_irq, leon_load_profile_irq,
- BTFIXUPCALL_NOP);
-
-#ifdef CONFIG_SMP
- BTFIXUPSET_CALL(set_cpu_int, leon_set_cpu_int, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(clear_cpu_int, leon_clear_ipi, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(set_irq_udt, leon_set_udt, BTFIXUPCALL_NORM);
-#endif
-
+ sparc_config.init_timers = leon_init_timers;
+ sparc_config.build_device_irq = _leon_build_device_irq;
+ sparc_config.clock_rate = 1000000;
+ sparc_config.clear_clock_irq = leon_clear_clock_irq;
+ sparc_config.load_profile_irq = leon_load_profile_irq;
}
void __init leon_init(void)
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
index 160cac9c4036..a469090faf9f 100644
--- a/arch/sparc/kernel/leon_smp.c
+++ b/arch/sparc/kernel/leon_smp.c
@@ -24,6 +24,7 @@
#include <linux/delay.h>
#include <linux/gfp.h>
#include <linux/cpu.h>
+#include <linux/clockchips.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
@@ -43,6 +44,7 @@
#include <asm/asi.h>
#include <asm/leon.h>
#include <asm/leon_amba.h>
+#include <asm/timer.h>
#include "kernel.h"
@@ -69,26 +71,24 @@ static inline unsigned long do_swap(volatile unsigned long *ptr,
return val;
}
-static void smp_setup_percpu_timer(void);
-
void __cpuinit leon_callin(void)
{
- int cpuid = hard_smpleon_processor_id();
+ int cpuid = hard_smp_processor_id();
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
leon_configure_cache_smp();
notify_cpu_starting(cpuid);
/* Get our local ticker going. */
- smp_setup_percpu_timer();
+ register_percpu_ce(cpuid);
calibrate_delay();
smp_store_cpu_info(cpuid);
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
/*
* Unblock the master CPU _only_ when the scheduler state
@@ -99,8 +99,8 @@ void __cpuinit leon_callin(void)
*/
do_swap(&cpu_callin_map[cpuid], 1);
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
/* Fix idle thread fields. */
__asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(&current_set[cpuid])
@@ -143,8 +143,8 @@ void __init leon_configure_cache_smp(void)
}
}
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
}
void leon_smp_setbroadcast(unsigned int mask)
@@ -199,21 +199,15 @@ void __init leon_boot_cpus(void)
leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER);
leon_configure_cache_smp();
- smp_setup_percpu_timer();
- local_flush_cache_all();
+ local_ops->cache_all();
}
-int __cpuinit leon_boot_one_cpu(int i)
+int __cpuinit leon_boot_one_cpu(int i, struct task_struct *idle)
{
-
- struct task_struct *p;
int timeout;
- /* Cook up an idler for this guy. */
- p = fork_idle(i);
-
- current_set[i] = task_thread_info(p);
+ current_set[i] = task_thread_info(idle);
/* See trampoline.S:leon_smp_cpu_startup for details...
* Initialize the contexts table
@@ -227,7 +221,7 @@ int __cpuinit leon_boot_one_cpu(int i)
/* whirrr, whirrr, whirrrrrrrrr... */
printk(KERN_INFO "Starting CPU %d : (irqmp: 0x%x)\n", (unsigned int)i,
(unsigned int)&leon3_irqctrl_regs->mpstatus);
- local_flush_cache_all();
+ local_ops->cache_all();
/* Make sure all IRQs are of from the start for this new CPU */
LEON_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[i], 0);
@@ -252,7 +246,7 @@ int __cpuinit leon_boot_one_cpu(int i)
leon_enable_irq_cpu(leon_ipi_irq, i);
}
- local_flush_cache_all();
+ local_ops->cache_all();
return 0;
}
@@ -272,7 +266,7 @@ void __init leon_smp_done(void)
}
}
*prev = first;
- local_flush_cache_all();
+ local_ops->cache_all();
/* Free unneeded trap tables */
if (!cpu_present(1)) {
@@ -338,7 +332,7 @@ static void __init leon_ipi_init(void)
local_irq_save(flags);
trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_ipi_irq - 1)];
trap_table->inst_three += smpleon_ipi - real_irq_entry;
- local_flush_cache_all();
+ local_ops->cache_all();
local_irq_restore(flags);
for_each_possible_cpu(cpu) {
@@ -347,6 +341,13 @@ static void __init leon_ipi_init(void)
}
}
+static void leon_send_ipi(int cpu, int level)
+{
+ unsigned long mask;
+ mask = leon_get_irqmask(level);
+ LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask);
+}
+
static void leon_ipi_single(int cpu)
{
struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu);
@@ -355,7 +356,7 @@ static void leon_ipi_single(int cpu)
work->single = 1;
/* Generate IRQ on the CPU */
- set_cpu_int(cpu, leon_ipi_irq);
+ leon_send_ipi(cpu, leon_ipi_irq);
}
static void leon_ipi_mask_one(int cpu)
@@ -366,7 +367,7 @@ static void leon_ipi_mask_one(int cpu)
work->msk = 1;
/* Generate IRQ on the CPU */
- set_cpu_int(cpu, leon_ipi_irq);
+ leon_send_ipi(cpu, leon_ipi_irq);
}
static void leon_ipi_resched(int cpu)
@@ -377,7 +378,7 @@ static void leon_ipi_resched(int cpu)
work->resched = 1;
/* Generate IRQ on the CPU (any IRQ will cause resched) */
- set_cpu_int(cpu, leon_ipi_irq);
+ leon_send_ipi(cpu, leon_ipi_irq);
}
void leonsmp_ipi_interrupt(void)
@@ -449,7 +450,7 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
if (cpumask_test_cpu(i, &mask)) {
ccall_info.processors_in[i] = 0;
ccall_info.processors_out[i] = 0;
- set_cpu_int(i, LEON3_IRQ_CROSS_CALL);
+ leon_send_ipi(i, LEON3_IRQ_CROSS_CALL);
}
}
@@ -492,68 +493,19 @@ void leon_cross_call_irq(void)
ccall_info.processors_out[i] = 1;
}
-irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused)
-{
- int cpu = smp_processor_id();
-
- leon_clear_profile_irq(cpu);
-
- profile_tick(CPU_PROFILING);
-
- if (!--prof_counter(cpu)) {
- int user = user_mode(get_irq_regs());
-
- update_process_times(user);
-
- prof_counter(cpu) = prof_multiplier(cpu);
- }
-
- return IRQ_HANDLED;
-}
-
-static void __init smp_setup_percpu_timer(void)
-{
- int cpu = smp_processor_id();
-
- prof_counter(cpu) = prof_multiplier(cpu) = 1;
-}
-
-void __init leon_blackbox_id(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
- int rs1 = rd >> 11;
-
- /* patch places where ___b_hard_smp_processor_id appears */
- addr[0] = 0x81444000 | rd; /* rd %asr17, reg */
- addr[1] = 0x8130201c | rd | rs1; /* srl reg, 0x1c, reg */
- addr[2] = 0x01000000; /* nop */
-}
-
-void __init leon_blackbox_current(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
- int rs1 = rd >> 11;
-
- /* patch LOAD_CURRENT macro where ___b_load_current appears */
- addr[0] = 0x81444000 | rd; /* rd %asr17, reg */
- addr[2] = 0x8130201c | rd | rs1; /* srl reg, 0x1c, reg */
- addr[4] = 0x81282002 | rd | rs1; /* sll reg, 0x2, reg */
-
-}
+static const struct sparc32_ipi_ops leon_ipi_ops = {
+ .cross_call = leon_cross_call,
+ .resched = leon_ipi_resched,
+ .single = leon_ipi_single,
+ .mask_one = leon_ipi_mask_one,
+};
void __init leon_init_smp(void)
{
/* Patch ipi15 trap table */
t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_leon - linux_trap_ipi15_sun4m);
- BTFIXUPSET_BLACKBOX(hard_smp_processor_id, leon_blackbox_id);
- BTFIXUPSET_BLACKBOX(load_current, leon_blackbox_current);
- BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id,
- BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(smp_ipi_resched, leon_ipi_resched, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(smp_ipi_single, leon_ipi_single, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(smp_ipi_mask_one, leon_ipi_mask_one, BTFIXUPCALL_NORM);
+ sparc32_ipi_ops = &leon_ipi_ops;
}
#endif /* CONFIG_SPARC_LEON */
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index 276359e1ff56..15e0a1693976 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -32,26 +32,11 @@ static void *module_map(unsigned long size)
GFP_KERNEL, PAGE_KERNEL, -1,
__builtin_return_address(0));
}
-
-static char *dot2underscore(char *name)
-{
- return name;
-}
#else
static void *module_map(unsigned long size)
{
return vmalloc(size);
}
-
-/* Replace references to .func with _Func */
-static char *dot2underscore(char *name)
-{
- if (name[0] == '.') {
- name[0] = '_';
- name[1] = toupper(name[1]);
- }
- return name;
-}
#endif /* CONFIG_SPARC64 */
void *module_alloc(unsigned long size)
@@ -93,12 +78,8 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
for (i = 1; i < sechdrs[symidx].sh_size / sizeof(Elf_Sym); i++) {
if (sym[i].st_shndx == SHN_UNDEF) {
- if (ELF_ST_TYPE(sym[i].st_info) == STT_REGISTER) {
+ if (ELF_ST_TYPE(sym[i].st_info) == STT_REGISTER)
sym[i].st_shndx = SHN_ABS;
- } else {
- char *name = strtab + sym[i].st_name;
- dot2underscore(name);
- }
}
}
return 0;
diff --git a/arch/sparc/kernel/muldiv.c b/arch/sparc/kernel/muldiv.c
deleted file mode 100644
index f7db516b07d8..000000000000
--- a/arch/sparc/kernel/muldiv.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * muldiv.c: Hardware multiply/division illegal instruction trap
- * for sun4c/sun4 (which do not have those instructions)
- *
- * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- *
- * 2004-12-25 Krzysztof Helt (krzysztof.h1@wp.pl)
- * - fixed registers constrains in inline assembly declarations
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-
-#include "kernel.h"
-
-/* #define DEBUG_MULDIV */
-
-static inline int has_imm13(int insn)
-{
- return (insn & 0x2000);
-}
-
-static inline int is_foocc(int insn)
-{
- return (insn & 0x800000);
-}
-
-static inline int sign_extend_imm13(int imm)
-{
- return imm << 19 >> 19;
-}
-
-static inline void advance(struct pt_regs *regs)
-{
- regs->pc = regs->npc;
- regs->npc += 4;
-}
-
-static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
- unsigned int rd)
-{
- if(rs2 >= 16 || rs1 >= 16 || rd >= 16) {
- /* Wheee... */
- __asm__ __volatile__("save %sp, -0x40, %sp\n\t"
- "save %sp, -0x40, %sp\n\t"
- "save %sp, -0x40, %sp\n\t"
- "save %sp, -0x40, %sp\n\t"
- "save %sp, -0x40, %sp\n\t"
- "save %sp, -0x40, %sp\n\t"
- "save %sp, -0x40, %sp\n\t"
- "restore; restore; restore; restore;\n\t"
- "restore; restore; restore;\n\t");
- }
-}
-
-#define fetch_reg(reg, regs) ({ \
- struct reg_window32 __user *win; \
- register unsigned long ret; \
- \
- if (!(reg)) ret = 0; \
- else if ((reg) < 16) { \
- ret = regs->u_regs[(reg)]; \
- } else { \
- /* Ho hum, the slightly complicated case. */ \
- win = (struct reg_window32 __user *)regs->u_regs[UREG_FP];\
- if (get_user (ret, &win->locals[(reg) - 16])) return -1;\
- } \
- ret; \
-})
-
-static inline int
-store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs)
-{
- struct reg_window32 __user *win;
-
- if (!reg)
- return 0;
- if (reg < 16) {
- regs->u_regs[reg] = result;
- return 0;
- } else {
- /* need to use put_user() in this case: */
- win = (struct reg_window32 __user *) regs->u_regs[UREG_FP];
- return (put_user(result, &win->locals[reg - 16]));
- }
-}
-
-/* Should return 0 if mul/div emulation succeeded and SIGILL should
- * not be issued.
- */
-int do_user_muldiv(struct pt_regs *regs, unsigned long pc)
-{
- unsigned int insn;
- int inst;
- unsigned int rs1, rs2, rdv;
-
- if (!pc)
- return -1; /* This happens to often, I think */
- if (get_user (insn, (unsigned int __user *)pc))
- return -1;
- if ((insn & 0xc1400000) != 0x80400000)
- return -1;
- inst = ((insn >> 19) & 0xf);
- if ((inst & 0xe) != 10 && (inst & 0xe) != 14)
- return -1;
-
- /* Now we know we have to do something with umul, smul, udiv or sdiv */
- rs1 = (insn >> 14) & 0x1f;
- rs2 = insn & 0x1f;
- rdv = (insn >> 25) & 0x1f;
- if (has_imm13(insn)) {
- maybe_flush_windows(rs1, 0, rdv);
- rs2 = sign_extend_imm13(insn);
- } else {
- maybe_flush_windows(rs1, rs2, rdv);
- rs2 = fetch_reg(rs2, regs);
- }
- rs1 = fetch_reg(rs1, regs);
- switch (inst) {
- case 10: /* umul */
-#ifdef DEBUG_MULDIV
- printk ("unsigned muldiv: 0x%x * 0x%x = ", rs1, rs2);
-#endif
- __asm__ __volatile__ ("\n\t"
- "mov %0, %%o0\n\t"
- "call .umul\n\t"
- " mov %1, %%o1\n\t"
- "mov %%o0, %0\n\t"
- "mov %%o1, %1\n\t"
- : "=r" (rs1), "=r" (rs2)
- : "0" (rs1), "1" (rs2)
- : "o0", "o1", "o2", "o3", "o4", "o5", "o7", "cc");
-#ifdef DEBUG_MULDIV
- printk ("0x%x%08x\n", rs2, rs1);
-#endif
- if (store_reg(rs1, rdv, regs))
- return -1;
- regs->y = rs2;
- break;
- case 11: /* smul */
-#ifdef DEBUG_MULDIV
- printk ("signed muldiv: 0x%x * 0x%x = ", rs1, rs2);
-#endif
- __asm__ __volatile__ ("\n\t"
- "mov %0, %%o0\n\t"
- "call .mul\n\t"
- " mov %1, %%o1\n\t"
- "mov %%o0, %0\n\t"
- "mov %%o1, %1\n\t"
- : "=r" (rs1), "=r" (rs2)
- : "0" (rs1), "1" (rs2)
- : "o0", "o1", "o2", "o3", "o4", "o5", "o7", "cc");
-#ifdef DEBUG_MULDIV
- printk ("0x%x%08x\n", rs2, rs1);
-#endif
- if (store_reg(rs1, rdv, regs))
- return -1;
- regs->y = rs2;
- break;
- case 14: /* udiv */
-#ifdef DEBUG_MULDIV
- printk ("unsigned muldiv: 0x%x%08x / 0x%x = ", regs->y, rs1, rs2);
-#endif
- if (!rs2) {
-#ifdef DEBUG_MULDIV
- printk ("DIVISION BY ZERO\n");
-#endif
- handle_hw_divzero (regs, pc, regs->npc, regs->psr);
- return 0;
- }
- __asm__ __volatile__ ("\n\t"
- "mov %2, %%o0\n\t"
- "mov %0, %%o1\n\t"
- "mov %%g0, %%o2\n\t"
- "call __udivdi3\n\t"
- " mov %1, %%o3\n\t"
- "mov %%o1, %0\n\t"
- "mov %%o0, %1\n\t"
- : "=r" (rs1), "=r" (rs2)
- : "r" (regs->y), "0" (rs1), "1" (rs2)
- : "o0", "o1", "o2", "o3", "o4", "o5", "o7",
- "g1", "g2", "g3", "cc");
-#ifdef DEBUG_MULDIV
- printk ("0x%x\n", rs1);
-#endif
- if (store_reg(rs1, rdv, regs))
- return -1;
- break;
- case 15: /* sdiv */
-#ifdef DEBUG_MULDIV
- printk ("signed muldiv: 0x%x%08x / 0x%x = ", regs->y, rs1, rs2);
-#endif
- if (!rs2) {
-#ifdef DEBUG_MULDIV
- printk ("DIVISION BY ZERO\n");
-#endif
- handle_hw_divzero (regs, pc, regs->npc, regs->psr);
- return 0;
- }
- __asm__ __volatile__ ("\n\t"
- "mov %2, %%o0\n\t"
- "mov %0, %%o1\n\t"
- "mov %%g0, %%o2\n\t"
- "call __divdi3\n\t"
- " mov %1, %%o3\n\t"
- "mov %%o1, %0\n\t"
- "mov %%o0, %1\n\t"
- : "=r" (rs1), "=r" (rs2)
- : "r" (regs->y), "0" (rs1), "1" (rs2)
- : "o0", "o1", "o2", "o3", "o4", "o5", "o7",
- "g1", "g2", "g3", "cc");
-#ifdef DEBUG_MULDIV
- printk ("0x%x\n", rs1);
-#endif
- if (store_reg(rs1, rdv, regs))
- return -1;
- break;
- }
- if (is_foocc (insn)) {
- regs->psr &= ~PSR_ICC;
- if ((inst & 0xe) == 14) {
- /* ?div */
- if (rs2) regs->psr |= PSR_V;
- }
- if (!rs1) regs->psr |= PSR_Z;
- if (((int)rs1) < 0) regs->psr |= PSR_N;
-#ifdef DEBUG_MULDIV
- printk ("psr muldiv: %08x\n", regs->psr);
-#endif
- }
- advance(regs);
- return 0;
-}
diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c
index 4ee8ce0d5d8d..185aa96fa5be 100644
--- a/arch/sparc/kernel/of_device_32.c
+++ b/arch/sparc/kernel/of_device_32.c
@@ -356,7 +356,7 @@ static struct platform_device * __init scan_one_device(struct device_node *dp,
op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs);
for (i = 0; i < op->archdata.num_irqs; i++)
op->archdata.irqs[i] =
- sparc_irq_config.build_device_irq(op, intr[i].pri);
+ sparc_config.build_device_irq(op, intr[i].pri);
} else {
const unsigned int *irq =
of_get_property(dp, "interrupts", &len);
@@ -365,7 +365,7 @@ static struct platform_device * __init scan_one_device(struct device_node *dp,
op->archdata.num_irqs = len / sizeof(unsigned int);
for (i = 0; i < op->archdata.num_irqs; i++)
op->archdata.irqs[i] =
- sparc_irq_config.build_device_irq(op, irq[i]);
+ sparc_config.build_device_irq(op, irq[i]);
} else {
op->archdata.num_irqs = 0;
}
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index fcc148effaac..ded3f6090c3f 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -703,31 +703,28 @@ static void pcic_clear_clock_irq(void)
pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT);
}
-static irqreturn_t pcic_timer_handler (int irq, void *h)
+/* CPU frequency is 100 MHz, timer increments every 4 CPU clocks */
+#define USECS_PER_JIFFY (1000000 / HZ)
+#define TICK_TIMER_LIMIT ((100 * 1000000 / 4) / HZ)
+
+static unsigned int pcic_cycles_offset(void)
{
- pcic_clear_clock_irq();
- xtime_update(1);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
- return IRQ_HANDLED;
-}
+ u32 value, count;
-#define USECS_PER_JIFFY 10000 /* We have 100HZ "standard" timer for sparc */
-#define TICK_TIMER_LIMIT ((100*1000000/4)/100)
+ value = readl(pcic0.pcic_regs + PCI_SYS_COUNTER);
+ count = value & ~PCI_SYS_COUNTER_OVERFLOW;
-u32 pci_gettimeoffset(void)
-{
+ if (value & PCI_SYS_COUNTER_OVERFLOW)
+ count += TICK_TIMER_LIMIT;
/*
- * We divide all by 100
+ * We divide all by HZ
* to have microsecond resolution and to avoid overflow
*/
- unsigned long count =
- readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW;
- count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100);
- return count * 1000;
-}
+ count = ((count / HZ) * USECS_PER_JIFFY) / (TICK_TIMER_LIMIT / HZ);
+ /* Coordinate with the sparc_config.clock_rate setting */
+ return count * 2;
+}
void __init pci_time_init(void)
{
@@ -736,9 +733,16 @@ void __init pci_time_init(void)
int timer_irq, irq;
int err;
- do_arch_gettimeoffset = pci_gettimeoffset;
-
- btfixup();
+#ifndef CONFIG_SMP
+ /*
+ * The clock_rate is in SBUS dimension.
+ * We take into account this in pcic_cycles_offset()
+ */
+ sparc_config.clock_rate = SBUS_CLOCK_RATE / HZ;
+ sparc_config.features |= FEAT_L10_CLOCKEVENT;
+#endif
+ sparc_config.features |= FEAT_L10_CLOCKSOURCE;
+ sparc_config.get_cycles_offset = pcic_cycles_offset;
writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT);
/* PROM should set appropriate irq */
@@ -747,7 +751,7 @@ void __init pci_time_init(void)
writel (PCI_COUNTER_IRQ_SET(timer_irq, 0),
pcic->pcic_regs+PCI_COUNTER_IRQ);
irq = pcic_build_device_irq(NULL, timer_irq);
- err = request_irq(irq, pcic_timer_handler,
+ err = request_irq(irq, timer_interrupt,
IRQF_TIMER, "timer", NULL);
if (err) {
prom_printf("time_init: unable to attach IRQ%d\n", timer_irq);
@@ -875,10 +879,9 @@ static void pcic_load_profile_irq(int cpu, unsigned int limit)
void __init sun4m_pci_init_IRQ(void)
{
- sparc_irq_config.build_device_irq = pcic_build_device_irq;
-
- BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM);
+ sparc_config.build_device_irq = pcic_build_device_irq;
+ sparc_config.clear_clock_irq = pcic_clear_clock_irq;
+ sparc_config.load_profile_irq = pcic_load_profile_irq;
}
int pcibios_assign_resource(struct pci_dev *pdev, int resource)
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 28559ce5eeb5..5713957dcb8a 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -1296,8 +1296,6 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
regs = args->regs;
- perf_sample_data_init(&data, 0);
-
cpuc = &__get_cpu_var(cpu_hw_events);
/* If the PMU has the TOE IRQ enable bits, we need to do a
@@ -1321,7 +1319,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
if (val & (1ULL << 31))
continue;
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, 0, hwc->last_period);
if (!sparc_perf_event_set_period(event, hwc, idx))
continue;
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
index efa07542e85f..fe6787cc62fc 100644
--- a/arch/sparc/kernel/process_32.c
+++ b/arch/sparc/kernel/process_32.c
@@ -67,8 +67,6 @@ struct thread_info *current_set[NR_CPUS];
#ifndef CONFIG_SMP
-#define SUN4C_FAULT_HIGH 100
-
/*
* the idle loop on a Sparc... ;)
*/
@@ -76,36 +74,6 @@ void cpu_idle(void)
{
/* endless idle loop with no priority at all */
for (;;) {
- if (ARCH_SUN4C) {
- static int count = HZ;
- static unsigned long last_jiffies;
- static unsigned long last_faults;
- static unsigned long fps;
- unsigned long now;
- unsigned long faults;
-
- extern unsigned long sun4c_kernel_faults;
- extern void sun4c_grow_kernel_ring(void);
-
- local_irq_disable();
- now = jiffies;
- count -= (now - last_jiffies);
- last_jiffies = now;
- if (count < 0) {
- count += HZ;
- faults = sun4c_kernel_faults;
- fps = (fps + (faults - last_faults)) >> 1;
- last_faults = faults;
-#if 0
- printk("kernel faults / second = %ld\n", fps);
-#endif
- if (fps >= SUN4C_FAULT_HIGH) {
- sun4c_grow_kernel_ring();
- }
- }
- local_irq_enable();
- }
-
if (pm_idle) {
while (!need_resched())
(*pm_idle)();
@@ -114,7 +82,6 @@ void cpu_idle(void)
cpu_relax();
}
schedule_preempt_disabled();
- check_pgt_cache();
}
}
@@ -137,7 +104,6 @@ void cpu_idle(void)
cpu_relax();
}
schedule_preempt_disabled();
- check_pgt_cache();
}
}
@@ -179,88 +145,6 @@ void machine_power_off(void)
machine_halt();
}
-#if 0
-
-static DEFINE_SPINLOCK(sparc_backtrace_lock);
-
-void __show_backtrace(unsigned long fp)
-{
- struct reg_window32 *rw;
- unsigned long flags;
- int cpu = smp_processor_id();
-
- spin_lock_irqsave(&sparc_backtrace_lock, flags);
-
- rw = (struct reg_window32 *)fp;
- while(rw && (((unsigned long) rw) >= PAGE_OFFSET) &&
- !(((unsigned long) rw) & 0x7)) {
- printk("CPU[%d]: ARGS[%08lx,%08lx,%08lx,%08lx,%08lx,%08lx] "
- "FP[%08lx] CALLER[%08lx]: ", cpu,
- rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
- rw->ins[4], rw->ins[5],
- rw->ins[6],
- rw->ins[7]);
- printk("%pS\n", (void *) rw->ins[7]);
- rw = (struct reg_window32 *) rw->ins[6];
- }
- spin_unlock_irqrestore(&sparc_backtrace_lock, flags);
-}
-
-#define __SAVE __asm__ __volatile__("save %sp, -0x40, %sp\n\t")
-#define __RESTORE __asm__ __volatile__("restore %g0, %g0, %g0\n\t")
-#define __GET_FP(fp) __asm__ __volatile__("mov %%i6, %0" : "=r" (fp))
-
-void show_backtrace(void)
-{
- unsigned long fp;
-
- __SAVE; __SAVE; __SAVE; __SAVE;
- __SAVE; __SAVE; __SAVE; __SAVE;
- __RESTORE; __RESTORE; __RESTORE; __RESTORE;
- __RESTORE; __RESTORE; __RESTORE; __RESTORE;
-
- __GET_FP(fp);
-
- __show_backtrace(fp);
-}
-
-#ifdef CONFIG_SMP
-void smp_show_backtrace_all_cpus(void)
-{
- xc0((smpfunc_t) show_backtrace);
- show_backtrace();
-}
-#endif
-
-void show_stackframe(struct sparc_stackf *sf)
-{
- unsigned long size;
- unsigned long *stk;
- int i;
-
- printk("l0: %08lx l1: %08lx l2: %08lx l3: %08lx "
- "l4: %08lx l5: %08lx l6: %08lx l7: %08lx\n",
- sf->locals[0], sf->locals[1], sf->locals[2], sf->locals[3],
- sf->locals[4], sf->locals[5], sf->locals[6], sf->locals[7]);
- printk("i0: %08lx i1: %08lx i2: %08lx i3: %08lx "
- "i4: %08lx i5: %08lx fp: %08lx i7: %08lx\n",
- sf->ins[0], sf->ins[1], sf->ins[2], sf->ins[3],
- sf->ins[4], sf->ins[5], (unsigned long)sf->fp, sf->callers_pc);
- printk("sp: %08lx x0: %08lx x1: %08lx x2: %08lx "
- "x3: %08lx x4: %08lx x5: %08lx xx: %08lx\n",
- (unsigned long)sf->structptr, sf->xargs[0], sf->xargs[1],
- sf->xargs[2], sf->xargs[3], sf->xargs[4], sf->xargs[5],
- sf->xxargs[0]);
- size = ((unsigned long)sf->fp) - ((unsigned long)sf);
- size -= STACKFRAME_SZ;
- stk = (unsigned long *)((unsigned long)sf + STACKFRAME_SZ);
- i = 0;
- do {
- printk("s%d: %08lx\n", i++, *stk++);
- } while ((size -= sizeof(unsigned long)));
-}
-#endif
-
void show_regs(struct pt_regs *r)
{
struct reg_window32 *rw = (struct reg_window32 *) r->u_regs[14];
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
index 6f97c0767995..484dabac7045 100644
--- a/arch/sparc/kernel/ptrace_64.c
+++ b/arch/sparc/kernel/ptrace_64.c
@@ -1062,7 +1062,7 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
int ret = 0;
/* do the secure computing check first */
- secure_computing(regs->u_regs[UREG_G1]);
+ secure_computing_strict(regs->u_regs[UREG_G1]);
if (test_thread_flag(TIF_SYSCALL_TRACE))
ret = tracehook_report_syscall_entry(regs);
diff --git a/arch/sparc/kernel/rtrap_32.S b/arch/sparc/kernel/rtrap_32.S
index 5f5f74c2c2ca..7abc24e2bf1a 100644
--- a/arch/sparc/kernel/rtrap_32.S
+++ b/arch/sparc/kernel/rtrap_32.S
@@ -128,13 +128,12 @@ rtrap_patch2: and %glob_tmp, 0xff, %glob_tmp
wr %glob_tmp, 0x0, %wim
- /* Here comes the architecture specific
- * branch to the user stack checking routine
- * for return from traps.
- */
- .globl rtrap_mmu_patchme
-rtrap_mmu_patchme: b sun4c_rett_stackchk
- andcc %fp, 0x7, %g0
+ /* Here comes the architecture specific
+ * branch to the user stack checking routine
+ * for return from traps.
+ */
+ b srmmu_rett_stackchk
+ andcc %fp, 0x7, %g0
ret_trap_userwins_ok:
LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc)
@@ -225,69 +224,6 @@ ret_trap_user_stack_is_bolixed:
b signal_p
ld [%curptr + TI_FLAGS], %g2
-sun4c_rett_stackchk:
- be 1f
- and %fp, 0xfff, %g1 ! delay slot
-
- b ret_trap_user_stack_is_bolixed + 0x4
- wr %t_wim, 0x0, %wim
-
- /* See if we have to check the sanity of one page or two */
-1:
- add %g1, 0x38, %g1
- sra %fp, 29, %g2
- add %g2, 0x1, %g2
- andncc %g2, 0x1, %g0
- be 1f
- andncc %g1, 0xff8, %g0
-
- /* %sp is in vma hole, yuck */
- b ret_trap_user_stack_is_bolixed + 0x4
- wr %t_wim, 0x0, %wim
-
-1:
- be sun4c_rett_onepage /* Only one page to check */
- lda [%fp] ASI_PTE, %g2
-
-sun4c_rett_twopages:
- add %fp, 0x38, %g1
- sra %g1, 29, %g2
- add %g2, 0x1, %g2
- andncc %g2, 0x1, %g0
- be 1f
- lda [%g1] ASI_PTE, %g2
-
- /* Second page is in vma hole */
- b ret_trap_user_stack_is_bolixed + 0x4
- wr %t_wim, 0x0, %wim
-
-1:
- srl %g2, 29, %g2
- andcc %g2, 0x4, %g0
- bne sun4c_rett_onepage
- lda [%fp] ASI_PTE, %g2
-
- /* Second page has bad perms */
- b ret_trap_user_stack_is_bolixed + 0x4
- wr %t_wim, 0x0, %wim
-
-sun4c_rett_onepage:
- srl %g2, 29, %g2
- andcc %g2, 0x4, %g0
- bne,a 1f
- restore %g0, %g0, %g0
-
- /* A page had bad page permissions, losing... */
- b ret_trap_user_stack_is_bolixed + 0x4
- wr %t_wim, 0x0, %wim
-
- /* Whee, things are ok, load the window and continue. */
-1:
- LOAD_WINDOW(sp)
-
- b ret_trap_userwins_ok
- save %g0, %g0, %g0
-
.globl srmmu_rett_stackchk
srmmu_rett_stackchk:
bne ret_trap_user_stack_is_bolixed
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S
index 9171fc238def..afa2a9e3d0a0 100644
--- a/arch/sparc/kernel/rtrap_64.S
+++ b/arch/sparc/kernel/rtrap_64.S
@@ -73,18 +73,8 @@ rtrap_nmi: ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
.globl rtrap_irq, rtrap, irqsz_patchme, rtrap_xcall
rtrap_irq:
rtrap:
-#ifndef CONFIG_SMP
- sethi %hi(__cpu_data), %l0
- lduw [%l0 + %lo(__cpu_data)], %l1
-#else
- sethi %hi(__cpu_data), %l0
- or %l0, %lo(__cpu_data), %l0
- lduw [%l0 + %g5], %l1
-#endif
- cmp %l1, 0
-
/* mm/ultra.S:xcall_report_regs KNOWS about this load. */
- ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
+ ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
rtrap_xcall:
sethi %hi(0xf << 20), %l4
and %l1, %l4, %l4
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index d444468b27f6..c052313f4dc5 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -42,7 +42,6 @@
#include <asm/vaddrs.h>
#include <asm/mbus.h>
#include <asm/idprom.h>
-#include <asm/machines.h>
#include <asm/cpudata.h>
#include <asm/setup.h>
#include <asm/cacheflush.h>
@@ -106,7 +105,6 @@ unsigned long cmdline_memory_size __initdata = 0;
/* which CPU booted us (0xff = not set) */
unsigned char boot_cpu_id = 0xff; /* 0xff will make it into DATA section... */
-unsigned char boot_cpu_id4; /* boot_cpu_id << 2 */
static void
prom_console_write(struct console *con, const char *s, unsigned n)
@@ -182,13 +180,6 @@ static void __init boot_flags_init(char *commands)
}
}
-/* This routine will in the future do all the nasty prom stuff
- * to probe for the mmu type and its parameters, etc. This will
- * also be where SMP things happen.
- */
-
-extern void sun4c_probe_vac(void);
-
extern unsigned short root_flags;
extern unsigned short root_dev;
extern unsigned short ram_flags;
@@ -200,6 +191,52 @@ extern int root_mountflags;
char reboot_command[COMMAND_LINE_SIZE];
+struct cpuid_patch_entry {
+ unsigned int addr;
+ unsigned int sun4d[3];
+ unsigned int leon[3];
+};
+extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
+
+static void __init per_cpu_patch(void)
+{
+ struct cpuid_patch_entry *p;
+
+ if (sparc_cpu_model == sun4m) {
+ /* Nothing to do, this is what the unpatched code
+ * targets.
+ */
+ return;
+ }
+
+ p = &__cpuid_patch;
+ while (p < &__cpuid_patch_end) {
+ unsigned long addr = p->addr;
+ unsigned int *insns;
+
+ switch (sparc_cpu_model) {
+ case sun4d:
+ insns = &p->sun4d[0];
+ break;
+
+ case sparc_leon:
+ insns = &p->leon[0];
+ break;
+ default:
+ prom_printf("Unknown cpu type, halting.\n");
+ prom_halt();
+ }
+ *(unsigned int *) (addr + 0) = insns[0];
+ flushi(addr + 0);
+ *(unsigned int *) (addr + 4) = insns[1];
+ flushi(addr + 4);
+ *(unsigned int *) (addr + 8) = insns[2];
+ flushi(addr + 8);
+
+ p++;
+ }
+}
+
enum sparc_cpu sparc_cpu_model;
EXPORT_SYMBOL(sparc_cpu_model);
@@ -225,10 +262,6 @@ void __init setup_arch(char **cmdline_p)
/* Set sparc_cpu_model */
sparc_cpu_model = sun_unknown;
- if (!strcmp(&cputypval[0], "sun4 "))
- sparc_cpu_model = sun4;
- if (!strcmp(&cputypval[0], "sun4c"))
- sparc_cpu_model = sun4c;
if (!strcmp(&cputypval[0], "sun4m"))
sparc_cpu_model = sun4m;
if (!strcmp(&cputypval[0], "sun4s"))
@@ -244,12 +277,6 @@ void __init setup_arch(char **cmdline_p)
printk("ARCH: ");
switch(sparc_cpu_model) {
- case sun4:
- printk("SUN4\n");
- break;
- case sun4c:
- printk("SUN4C\n");
- break;
case sun4m:
printk("SUN4M\n");
break;
@@ -275,8 +302,6 @@ void __init setup_arch(char **cmdline_p)
#endif
idprom_init();
- if (ARCH_SUN4C)
- sun4c_probe_vac();
load_mmu();
phys_base = 0xffffffffUL;
@@ -313,6 +338,9 @@ void __init setup_arch(char **cmdline_p)
init_mm.context = (unsigned long) NO_CONTEXT;
init_task.thread.kregs = &fake_swapper_regs;
+ /* Run-time patch instructions to match the cpu model */
+ per_cpu_patch();
+
paging_init();
smp_setup_cpu_possible_map();
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index 1e750e415d7a..ac8e66b50f07 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -217,12 +217,9 @@ segv:
/* Checks if the fp is valid */
static inline int invalid_frame_pointer(void __user *fp, int fplen)
{
- if ((((unsigned long) fp) & 7) ||
- !__access_ok((unsigned long)fp, fplen) ||
- ((sparc_cpu_model == sun4 || sparc_cpu_model == sun4c) &&
- ((unsigned long) fp < 0xe0000000 && (unsigned long) fp >= 0x20000000)))
+ if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen))
return 1;
-
+
return 0;
}
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c
index f671e7fd6ddc..79db45e5134a 100644
--- a/arch/sparc/kernel/smp_32.c
+++ b/arch/sparc/kernel/smp_32.c
@@ -40,6 +40,8 @@ volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,};
cpumask_t smp_commenced_mask = CPU_MASK_NONE;
+const struct sparc32_ipi_ops *sparc32_ipi_ops;
+
/* The only guaranteed locking primitive available on all Sparc
* processors is 'ldstub [%reg + immediate], %dest_reg' which atomically
* places the current byte at the effective address into dest_reg and
@@ -85,14 +87,6 @@ void __init smp_cpus_done(unsigned int max_cpus)
(bogosum/(5000/HZ))%100);
switch(sparc_cpu_model) {
- case sun4:
- printk("SUN4\n");
- BUG();
- break;
- case sun4c:
- printk("SUN4C\n");
- BUG();
- break;
case sun4m:
smp4m_smp_done();
break;
@@ -132,7 +126,7 @@ void smp_send_reschedule(int cpu)
* a single CPU. The trap handler needs only to do trap entry/return
* to call schedule.
*/
- BTFIXUP_CALL(smp_ipi_resched)(cpu);
+ sparc32_ipi_ops->resched(cpu);
}
void smp_send_stop(void)
@@ -142,7 +136,7 @@ void smp_send_stop(void)
void arch_send_call_function_single_ipi(int cpu)
{
/* trigger one IPI single call on one CPU */
- BTFIXUP_CALL(smp_ipi_single)(cpu);
+ sparc32_ipi_ops->single(cpu);
}
void arch_send_call_function_ipi_mask(const struct cpumask *mask)
@@ -151,7 +145,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
/* trigger IPI mask call on each CPU */
for_each_cpu(cpu, mask)
- BTFIXUP_CALL(smp_ipi_mask_one)(cpu);
+ sparc32_ipi_ops->mask_one(cpu);
}
void smp_resched_interrupt(void)
@@ -179,150 +173,9 @@ void smp_call_function_interrupt(void)
irq_exit();
}
-void smp_flush_cache_all(void)
-{
- xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all));
- local_flush_cache_all();
-}
-
-void smp_flush_tlb_all(void)
-{
- xc0((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_all));
- local_flush_tlb_all();
-}
-
-void smp_flush_cache_mm(struct mm_struct *mm)
-{
- if(mm->context != NO_CONTEXT) {
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask))
- xc1((smpfunc_t) BTFIXUP_CALL(local_flush_cache_mm), (unsigned long) mm);
- local_flush_cache_mm(mm);
- }
-}
-
-void smp_flush_tlb_mm(struct mm_struct *mm)
-{
- if(mm->context != NO_CONTEXT) {
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask)) {
- xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm);
- if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm)
- cpumask_copy(mm_cpumask(mm),
- cpumask_of(smp_processor_id()));
- }
- local_flush_tlb_mm(mm);
- }
-}
-
-void smp_flush_cache_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
-
- if (mm->context != NO_CONTEXT) {
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask))
- xc3((smpfunc_t) BTFIXUP_CALL(local_flush_cache_range), (unsigned long) vma, start, end);
- local_flush_cache_range(vma, start, end);
- }
-}
-
-void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
-
- if (mm->context != NO_CONTEXT) {
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask))
- xc3((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_range), (unsigned long) vma, start, end);
- local_flush_tlb_range(vma, start, end);
- }
-}
-
-void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
-{
- struct mm_struct *mm = vma->vm_mm;
-
- if(mm->context != NO_CONTEXT) {
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask))
- xc2((smpfunc_t) BTFIXUP_CALL(local_flush_cache_page), (unsigned long) vma, page);
- local_flush_cache_page(vma, page);
- }
-}
-
-void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
- struct mm_struct *mm = vma->vm_mm;
-
- if(mm->context != NO_CONTEXT) {
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask))
- xc2((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_page), (unsigned long) vma, page);
- local_flush_tlb_page(vma, page);
- }
-}
-
-void smp_flush_page_to_ram(unsigned long page)
-{
- /* Current theory is that those who call this are the one's
- * who have just dirtied their cache with the pages contents
- * in kernel space, therefore we only run this on local cpu.
- *
- * XXX This experiment failed, research further... -DaveM
- */
-#if 1
- xc1((smpfunc_t) BTFIXUP_CALL(local_flush_page_to_ram), page);
-#endif
- local_flush_page_to_ram(page);
-}
-
-void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
-{
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask))
- xc2((smpfunc_t) BTFIXUP_CALL(local_flush_sig_insns), (unsigned long) mm, insn_addr);
- local_flush_sig_insns(mm, insn_addr);
-}
-
-extern unsigned int lvl14_resolution;
-
-/* /proc/profile writes can call this, don't __init it please. */
-static DEFINE_SPINLOCK(prof_setup_lock);
-
int setup_profiling_timer(unsigned int multiplier)
{
- int i;
- unsigned long flags;
-
- /* Prevent level14 ticker IRQ flooding. */
- if((!multiplier) || (lvl14_resolution / multiplier) < 500)
- return -EINVAL;
-
- spin_lock_irqsave(&prof_setup_lock, flags);
- for_each_possible_cpu(i) {
- load_profile_irq(i, lvl14_resolution / multiplier);
- prof_multiplier(i) = multiplier;
- }
- spin_unlock_irqrestore(&prof_setup_lock, flags);
-
- return 0;
+ return -EINVAL;
}
void __init smp_prepare_cpus(unsigned int max_cpus)
@@ -345,14 +198,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
smp_store_cpu_info(boot_cpu_id);
switch(sparc_cpu_model) {
- case sun4:
- printk("SUN4\n");
- BUG();
- break;
- case sun4c:
- printk("SUN4C\n");
- BUG();
- break;
case sun4m:
smp4m_boot_cpus();
break;
@@ -411,29 +256,21 @@ void __init smp_prepare_boot_cpu(void)
set_cpu_possible(cpuid, true);
}
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
- extern int __cpuinit smp4m_boot_one_cpu(int);
- extern int __cpuinit smp4d_boot_one_cpu(int);
+ extern int __cpuinit smp4m_boot_one_cpu(int, struct task_struct *);
+ extern int __cpuinit smp4d_boot_one_cpu(int, struct task_struct *);
int ret=0;
switch(sparc_cpu_model) {
- case sun4:
- printk("SUN4\n");
- BUG();
- break;
- case sun4c:
- printk("SUN4C\n");
- BUG();
- break;
case sun4m:
- ret = smp4m_boot_one_cpu(cpu);
+ ret = smp4m_boot_one_cpu(cpu, tidle);
break;
case sun4d:
- ret = smp4d_boot_one_cpu(cpu);
+ ret = smp4d_boot_one_cpu(cpu, tidle);
break;
case sparc_leon:
- ret = leon_boot_one_cpu(cpu);
+ ret = leon_boot_one_cpu(cpu, tidle);
break;
case sun4e:
printk("SUN4E\n");
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 3b1bd7c50164..f591598d92f6 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -343,21 +343,17 @@ extern unsigned long sparc64_cpu_startup;
*/
static struct thread_info *cpu_new_thread = NULL;
-static int __cpuinit smp_boot_one_cpu(unsigned int cpu)
+static int __cpuinit smp_boot_one_cpu(unsigned int cpu, struct task_struct *idle)
{
unsigned long entry =
(unsigned long)(&sparc64_cpu_startup);
unsigned long cookie =
(unsigned long)(&cpu_new_thread);
- struct task_struct *p;
void *descr = NULL;
int timeout, ret;
- p = fork_idle(cpu);
- if (IS_ERR(p))
- return PTR_ERR(p);
callin_flag = 0;
- cpu_new_thread = task_thread_info(p);
+ cpu_new_thread = task_thread_info(idle);
if (tlb_type == hypervisor) {
#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU)
@@ -1227,9 +1223,9 @@ void __devinit smp_fill_in_sib_core_maps(void)
}
}
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
- int ret = smp_boot_one_cpu(cpu);
+ int ret = smp_boot_one_cpu(cpu, tidle);
if (!ret) {
cpumask_set_cpu(cpu, &smp_commenced_mask);
diff --git a/arch/sparc/kernel/sparc_ksyms_32.c b/arch/sparc/kernel/sparc_ksyms_32.c
index baeab8720237..e521c54560f9 100644
--- a/arch/sparc/kernel/sparc_ksyms_32.c
+++ b/arch/sparc/kernel/sparc_ksyms_32.c
@@ -28,19 +28,5 @@ EXPORT_SYMBOL(__ndelay);
EXPORT_SYMBOL(__ret_efault);
EXPORT_SYMBOL(empty_zero_page);
-/* Defined using magic */
-#ifndef CONFIG_SMP
-EXPORT_SYMBOL(BTFIXUP_CALL(___xchg32));
-#else
-EXPORT_SYMBOL(BTFIXUP_CALL(__hard_smp_processor_id));
-#endif
-EXPORT_SYMBOL(BTFIXUP_CALL(mmu_unlockarea));
-EXPORT_SYMBOL(BTFIXUP_CALL(mmu_lockarea));
-EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_sgl));
-EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_one));
-EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_sgl));
-EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_one));
-EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached));
-
/* Exporting a symbol from /init/main.c */
EXPORT_SYMBOL(saved_command_line);
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c
deleted file mode 100644
index f6bf25a2ff80..000000000000
--- a/arch/sparc/kernel/sun4c_irq.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * sun4c irq support
- *
- * djhr: Hacked out of irq.c into a CPU dependent version.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
- * Copyright (C) 1995 Pete A. Zaitcev (zaitcev@yahoo.com)
- * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
- */
-
-#include <linux/init.h>
-
-#include <asm/oplib.h>
-#include <asm/timer.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include "irq.h"
-
-/* Sun4c interrupts are typically laid out as follows:
- *
- * 1 - Software interrupt, SBUS level 1
- * 2 - SBUS level 2
- * 3 - ESP SCSI, SBUS level 3
- * 4 - Software interrupt
- * 5 - Lance ethernet, SBUS level 4
- * 6 - Software interrupt
- * 7 - Graphics card, SBUS level 5
- * 8 - SBUS level 6
- * 9 - SBUS level 7
- * 10 - Counter timer
- * 11 - Floppy
- * 12 - Zilog uart
- * 13 - CS4231 audio
- * 14 - Profiling timer
- * 15 - NMI
- *
- * The interrupt enable bits in the interrupt mask register are
- * really only used to enable/disable the timer interrupts, and
- * for signalling software interrupts. There is also a master
- * interrupt enable bit in this register.
- *
- * Interrupts are enabled by setting the SUN4C_INT_* bits, they
- * are disabled by clearing those bits.
- */
-
-/*
- * Bit field defines for the interrupt registers on various
- * Sparc machines.
- */
-
-/* The sun4c interrupt register. */
-#define SUN4C_INT_ENABLE 0x01 /* Allow interrupts. */
-#define SUN4C_INT_E14 0x80 /* Enable level 14 IRQ. */
-#define SUN4C_INT_E10 0x20 /* Enable level 10 IRQ. */
-#define SUN4C_INT_E8 0x10 /* Enable level 8 IRQ. */
-#define SUN4C_INT_E6 0x08 /* Enable level 6 IRQ. */
-#define SUN4C_INT_E4 0x04 /* Enable level 4 IRQ. */
-#define SUN4C_INT_E1 0x02 /* Enable level 1 IRQ. */
-
-/*
- * Pointer to the interrupt enable byte
- * Used by entry.S
- */
-unsigned char __iomem *interrupt_enable;
-
-static void sun4c_mask_irq(struct irq_data *data)
-{
- unsigned long mask = (unsigned long)data->chip_data;
-
- if (mask) {
- unsigned long flags;
-
- local_irq_save(flags);
- mask = sbus_readb(interrupt_enable) & ~mask;
- sbus_writeb(mask, interrupt_enable);
- local_irq_restore(flags);
- }
-}
-
-static void sun4c_unmask_irq(struct irq_data *data)
-{
- unsigned long mask = (unsigned long)data->chip_data;
-
- if (mask) {
- unsigned long flags;
-
- local_irq_save(flags);
- mask = sbus_readb(interrupt_enable) | mask;
- sbus_writeb(mask, interrupt_enable);
- local_irq_restore(flags);
- }
-}
-
-static unsigned int sun4c_startup_irq(struct irq_data *data)
-{
- irq_link(data->irq);
- sun4c_unmask_irq(data);
-
- return 0;
-}
-
-static void sun4c_shutdown_irq(struct irq_data *data)
-{
- sun4c_mask_irq(data);
- irq_unlink(data->irq);
-}
-
-static struct irq_chip sun4c_irq = {
- .name = "sun4c",
- .irq_startup = sun4c_startup_irq,
- .irq_shutdown = sun4c_shutdown_irq,
- .irq_mask = sun4c_mask_irq,
- .irq_unmask = sun4c_unmask_irq,
-};
-
-static unsigned int sun4c_build_device_irq(struct platform_device *op,
- unsigned int real_irq)
-{
- unsigned int irq;
-
- if (real_irq >= 16) {
- prom_printf("Bogus sun4c IRQ %u\n", real_irq);
- prom_halt();
- }
-
- irq = irq_alloc(real_irq, real_irq);
- if (irq) {
- unsigned long mask = 0UL;
-
- switch (real_irq) {
- case 1:
- mask = SUN4C_INT_E1;
- break;
- case 8:
- mask = SUN4C_INT_E8;
- break;
- case 10:
- mask = SUN4C_INT_E10;
- break;
- case 14:
- mask = SUN4C_INT_E14;
- break;
- default:
- /* All the rest are either always enabled,
- * or are for signalling software interrupts.
- */
- break;
- }
- irq_set_chip_and_handler_name(irq, &sun4c_irq,
- handle_level_irq, "level");
- irq_set_chip_data(irq, (void *)mask);
- }
- return irq;
-}
-
-struct sun4c_timer_info {
- u32 l10_count;
- u32 l10_limit;
- u32 l14_count;
- u32 l14_limit;
-};
-
-static struct sun4c_timer_info __iomem *sun4c_timers;
-
-static void sun4c_clear_clock_irq(void)
-{
- sbus_readl(&sun4c_timers->l10_limit);
-}
-
-static void sun4c_load_profile_irq(int cpu, unsigned int limit)
-{
- /* Errm.. not sure how to do this.. */
-}
-
-static void __init sun4c_init_timers(irq_handler_t counter_fn)
-{
- const struct linux_prom_irqs *prom_irqs;
- struct device_node *dp;
- unsigned int irq;
- const u32 *addr;
- int err;
-
- dp = of_find_node_by_name(NULL, "counter-timer");
- if (!dp) {
- prom_printf("sun4c_init_timers: Unable to find counter-timer\n");
- prom_halt();
- }
-
- addr = of_get_property(dp, "address", NULL);
- if (!addr) {
- prom_printf("sun4c_init_timers: No address property\n");
- prom_halt();
- }
-
- sun4c_timers = (void __iomem *) (unsigned long) addr[0];
-
- prom_irqs = of_get_property(dp, "intr", NULL);
- of_node_put(dp);
- if (!prom_irqs) {
- prom_printf("sun4c_init_timers: No intr property\n");
- prom_halt();
- }
-
- /* Have the level 10 timer tick at 100HZ. We don't touch the
- * level 14 timer limit since we are letting the prom handle
- * them until we have a real console driver so L1-A works.
- */
- sbus_writel((((1000000/HZ) + 1) << 10), &sun4c_timers->l10_limit);
-
- master_l10_counter = &sun4c_timers->l10_count;
-
- irq = sun4c_build_device_irq(NULL, prom_irqs[0].pri);
- err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
- if (err) {
- prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err);
- prom_halt();
- }
-
- /* disable timer interrupt */
- sun4c_mask_irq(irq_get_irq_data(irq));
-}
-
-#ifdef CONFIG_SMP
-static void sun4c_nop(void)
-{
-}
-#endif
-
-void __init sun4c_init_IRQ(void)
-{
- struct device_node *dp;
- const u32 *addr;
-
- dp = of_find_node_by_name(NULL, "interrupt-enable");
- if (!dp) {
- prom_printf("sun4c_init_IRQ: Unable to find interrupt-enable\n");
- prom_halt();
- }
-
- addr = of_get_property(dp, "address", NULL);
- of_node_put(dp);
- if (!addr) {
- prom_printf("sun4c_init_IRQ: No address property\n");
- prom_halt();
- }
-
- interrupt_enable = (void __iomem *) (unsigned long) addr[0];
-
- BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP);
-
- sparc_irq_config.init_timers = sun4c_init_timers;
- sparc_irq_config.build_device_irq = sun4c_build_device_irq;
-
-#ifdef CONFIG_SMP
- BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(set_irq_udt, sun4c_nop, BTFIXUPCALL_NOP);
-#endif
- sbus_writeb(SUN4C_INT_ENABLE, interrupt_enable);
- /* Cannot enable interrupts until OBP ticker is disabled. */
-}
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index 1d13c5bda0b1..e490ac9327c7 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -15,6 +15,7 @@
#include <asm/sbi.h>
#include <asm/cacheflush.h>
#include <asm/setup.h>
+#include <asm/oplib.h>
#include "kernel.h"
#include "irq.h"
@@ -243,19 +244,6 @@ struct irq_chip sun4d_irq = {
};
#ifdef CONFIG_SMP
-static void sun4d_set_cpu_int(int cpu, int level)
-{
- sun4d_send_ipi(cpu, level);
-}
-
-static void sun4d_clear_ipi(int cpu, int level)
-{
-}
-
-static void sun4d_set_udt(int cpu)
-{
-}
-
/* Setup IRQ distribution scheme. */
void __init sun4d_distribute_irqs(void)
{
@@ -282,7 +270,8 @@ static void sun4d_clear_clock_irq(void)
static void sun4d_load_profile_irq(int cpu, unsigned int limit)
{
- bw_set_prof_limit(cpu, limit);
+ unsigned int value = limit ? timer_value(limit) : 0;
+ bw_set_prof_limit(cpu, value);
}
static void __init sun4d_load_profile_irqs(void)
@@ -418,12 +407,12 @@ static void __init sun4d_fixup_trap_table(void)
trap_table->inst_two = lvl14_save[1];
trap_table->inst_three = lvl14_save[2];
trap_table->inst_four = lvl14_save[3];
- local_flush_cache_all();
+ local_ops->cache_all();
local_irq_restore(flags);
#endif
}
-static void __init sun4d_init_timers(irq_handler_t counter_fn)
+static void __init sun4d_init_timers(void)
{
struct device_node *dp;
struct resource res;
@@ -466,12 +455,20 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn)
prom_halt();
}
- sbus_writel((((1000000/HZ) + 1) << 10), &sun4d_timers->l10_timer_limit);
+#ifdef CONFIG_SMP
+ sparc_config.cs_period = SBUS_CLOCK_RATE * 2; /* 2 seconds */
+#else
+ sparc_config.cs_period = SBUS_CLOCK_RATE / HZ; /* 1/HZ sec */
+ sparc_config.features |= FEAT_L10_CLOCKEVENT;
+#endif
+ sparc_config.features |= FEAT_L10_CLOCKSOURCE;
+ sbus_writel(timer_value(sparc_config.cs_period),
+ &sun4d_timers->l10_timer_limit);
master_l10_counter = &sun4d_timers->l10_cur_count;
irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ);
- err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
+ err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
if (err) {
prom_printf("sun4d_init_timers: request_irq() failed with %d\n",
err);
@@ -509,16 +506,11 @@ void __init sun4d_init_IRQ(void)
{
local_irq_disable();
- BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM);
+ sparc_config.init_timers = sun4d_init_timers;
+ sparc_config.build_device_irq = sun4d_build_device_irq;
+ sparc_config.clock_rate = SBUS_CLOCK_RATE;
+ sparc_config.clear_clock_irq = sun4d_clear_clock_irq;
+ sparc_config.load_profile_irq = sun4d_load_profile_irq;
- sparc_irq_config.init_timers = sun4d_init_timers;
- sparc_irq_config.build_device_irq = sun4d_build_device_irq;
-
-#ifdef CONFIG_SMP
- BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(set_irq_udt, sun4d_set_udt, BTFIXUPCALL_NOP);
-#endif
/* Cannot enable interrupts until OBP ticker is disabled. */
}
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 540b2fec09f0..ddaea31de586 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -6,16 +6,20 @@
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/profile.h>
#include <linux/delay.h>
+#include <linux/sched.h>
#include <linux/cpu.h>
+#include <asm/cacheflush.h>
+#include <asm/switch_to.h>
+#include <asm/tlbflush.h>
+#include <asm/timer.h>
+#include <asm/oplib.h>
#include <asm/sbi.h>
#include <asm/mmu.h>
-#include <asm/tlbflush.h>
-#include <asm/switch_to.h>
-#include <asm/cacheflush.h>
#include "kernel.h"
#include "irq.h"
@@ -34,7 +38,6 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon
}
static void smp4d_ipi_init(void);
-static void smp_setup_percpu_timer(void);
static unsigned char cpu_leds[32];
@@ -49,7 +52,7 @@ static inline void show_leds(int cpuid)
void __cpuinit smp4d_callin(void)
{
- int cpuid = hard_smp4d_processor_id();
+ int cpuid = hard_smp_processor_id();
unsigned long flags;
/* Show we are alive */
@@ -59,8 +62,8 @@ void __cpuinit smp4d_callin(void)
/* Enable level15 interrupt, disable level14 interrupt for now */
cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000);
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
notify_cpu_starting(cpuid);
/*
@@ -70,17 +73,17 @@ void __cpuinit smp4d_callin(void)
* to call the scheduler code.
*/
/* Get our local ticker going. */
- smp_setup_percpu_timer();
+ register_percpu_ce(cpuid);
calibrate_delay();
smp_store_cpu_info(cpuid);
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
/* Allow master to continue. */
sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1);
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
while ((unsigned long)current_set[cpuid] < PAGE_OFFSET)
barrier();
@@ -100,8 +103,8 @@ void __cpuinit smp4d_callin(void)
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
local_irq_enable(); /* We don't allow PIL 14 yet */
@@ -123,22 +126,17 @@ void __init smp4d_boot_cpus(void)
smp4d_ipi_init();
if (boot_cpu_id)
current_set[0] = NULL;
- smp_setup_percpu_timer();
- local_flush_cache_all();
+ local_ops->cache_all();
}
-int __cpuinit smp4d_boot_one_cpu(int i)
+int __cpuinit smp4d_boot_one_cpu(int i, struct task_struct *idle)
{
unsigned long *entry = &sun4d_cpu_startup;
- struct task_struct *p;
int timeout;
int cpu_node;
cpu_find_by_instance(i, &cpu_node, NULL);
- /* Cook up an idler for this guy. */
- p = fork_idle(i);
- current_set[i] = task_thread_info(p);
-
+ current_set[i] = task_thread_info(idle);
/*
* Initialize the contexts table
* Since the call to prom_startcpu() trashes the structure,
@@ -150,7 +148,7 @@ int __cpuinit smp4d_boot_one_cpu(int i)
/* whirrr, whirrr, whirrrrrrrrr... */
printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
- local_flush_cache_all();
+ local_ops->cache_all();
prom_startcpu(cpu_node,
&smp_penguin_ctable, 0, (char *)entry);
@@ -168,7 +166,7 @@ int __cpuinit smp4d_boot_one_cpu(int i)
return -ENODEV;
}
- local_flush_cache_all();
+ local_ops->cache_all();
return 0;
}
@@ -185,7 +183,7 @@ void __init smp4d_smp_done(void)
prev = &cpu_data(i).next;
}
*prev = first;
- local_flush_cache_all();
+ local_ops->cache_all();
/* Ok, they are spinning and ready to go. */
smp_processors_ready = 1;
@@ -233,7 +231,20 @@ void sun4d_ipi_interrupt(void)
}
}
-static void smp4d_ipi_single(int cpu)
+/* +-------+-------------+-----------+------------------------------------+
+ * | bcast | devid | sid | levels mask |
+ * +-------+-------------+-----------+------------------------------------+
+ * 31 30 23 22 15 14 0
+ */
+#define IGEN_MESSAGE(bcast, devid, sid, levels) \
+ (((bcast) << 31) | ((devid) << 23) | ((sid) << 15) | (levels))
+
+static void sun4d_send_ipi(int cpu, int level)
+{
+ cc_set_igen(IGEN_MESSAGE(0, cpu << 3, 6 + ((level >> 1) & 7), 1 << (level - 1)));
+}
+
+static void sun4d_ipi_single(int cpu)
{
struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
@@ -244,7 +255,7 @@ static void smp4d_ipi_single(int cpu)
sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
}
-static void smp4d_ipi_mask_one(int cpu)
+static void sun4d_ipi_mask_one(int cpu)
{
struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
@@ -255,7 +266,7 @@ static void smp4d_ipi_mask_one(int cpu)
sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
}
-static void smp4d_ipi_resched(int cpu)
+static void sun4d_ipi_resched(int cpu)
{
struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
@@ -280,7 +291,7 @@ static struct smp_funcall {
static DEFINE_SPINLOCK(cross_call_lock);
/* Cross calls must be serialized, at least currently. */
-static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
+static void sun4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
unsigned long arg2, unsigned long arg3,
unsigned long arg4)
{
@@ -352,7 +363,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
/* Running cross calls. */
void smp4d_cross_call_irq(void)
{
- int i = hard_smp4d_processor_id();
+ int i = hard_smp_processor_id();
ccall_info.processors_in[i] = 1;
ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3,
@@ -363,7 +374,8 @@ void smp4d_cross_call_irq(void)
void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
{
struct pt_regs *old_regs;
- int cpu = hard_smp4d_processor_id();
+ int cpu = hard_smp_processor_id();
+ struct clock_event_device *ce;
static int cpu_tick[NR_CPUS];
static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd };
@@ -379,45 +391,21 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
show_leds(cpu);
}
- profile_tick(CPU_PROFILING);
-
- if (!--prof_counter(cpu)) {
- int user = user_mode(regs);
+ ce = &per_cpu(sparc32_clockevent, cpu);
- irq_enter();
- update_process_times(user);
- irq_exit();
+ irq_enter();
+ ce->event_handler(ce);
+ irq_exit();
- prof_counter(cpu) = prof_multiplier(cpu);
- }
set_irq_regs(old_regs);
}
-static void __cpuinit smp_setup_percpu_timer(void)
-{
- int cpu = hard_smp4d_processor_id();
-
- prof_counter(cpu) = prof_multiplier(cpu) = 1;
- load_profile_irq(cpu, lvl14_resolution);
-}
-
-void __init smp4d_blackbox_id(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
-
- addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */
- addr[1] = 0x01000000; /* nop */
- addr[2] = 0x01000000; /* nop */
-}
-
-void __init smp4d_blackbox_current(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
-
- addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */
- addr[2] = 0x81282002 | rd | (rd >> 11); /* sll reg, 2, reg */
- addr[4] = 0x01000000; /* nop */
-}
+static const struct sparc32_ipi_ops sun4d_ipi_ops = {
+ .cross_call = sun4d_cross_call,
+ .resched = sun4d_ipi_resched,
+ .single = sun4d_ipi_single,
+ .mask_one = sun4d_ipi_mask_one,
+};
void __init sun4d_init_smp(void)
{
@@ -426,14 +414,7 @@ void __init sun4d_init_smp(void)
/* Patch ipi15 trap table */
t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m);
- /* And set btfixup... */
- BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id);
- BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
- BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(smp_ipi_resched, smp4d_ipi_resched, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(smp_ipi_single, smp4d_ipi_single, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(smp_ipi_mask_one, smp4d_ipi_mask_one, BTFIXUPCALL_NORM);
+ sparc32_ipi_ops = &sun4d_ipi_ops;
for (i = 0; i < NR_CPUS; i++) {
ccall_info.processors_in[i] = 1;
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index e61165161dd3..c5ade9d27a1d 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -112,9 +112,6 @@ struct sun4m_handler_data {
#define SUN4M_INT_E14 0x00000080
#define SUN4M_INT_E10 0x00080000
-#define SUN4M_HARD_INT(x) (0x000000001 << (x))
-#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
-
#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */
#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */
#define SUN4M_INT_M2S_WRITE_ERR 0x20000000 /* write buffer error */
@@ -282,23 +279,6 @@ out:
return irq;
}
-#ifdef CONFIG_SMP
-static void sun4m_send_ipi(int cpu, int level)
-{
- sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set);
-}
-
-static void sun4m_clear_ipi(int cpu, int level)
-{
- sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->clear);
-}
-
-static void sun4m_set_udt(int cpu)
-{
- sbus_writel(cpu, &sun4m_irq_global->interrupt_target);
-}
-#endif
-
struct sun4m_timer_percpu {
u32 l14_limit;
u32 l14_count;
@@ -318,9 +298,6 @@ struct sun4m_timer_global {
static struct sun4m_timer_global __iomem *timers_global;
-
-unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10);
-
static void sun4m_clear_clock_irq(void)
{
sbus_readl(&timers_global->l10_limit);
@@ -369,10 +346,11 @@ void sun4m_clear_profile_irq(int cpu)
static void sun4m_load_profile_irq(int cpu, unsigned int limit)
{
- sbus_writel(limit, &timers_percpu[cpu]->l14_limit);
+ unsigned int value = limit ? timer_value(limit) : 0;
+ sbus_writel(value, &timers_percpu[cpu]->l14_limit);
}
-static void __init sun4m_init_timers(irq_handler_t counter_fn)
+static void __init sun4m_init_timers(void)
{
struct device_node *dp = of_find_node_by_name(NULL, "counter");
int i, err, len, num_cpu_timers;
@@ -402,13 +380,22 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
/* Every per-cpu timer works in timer mode */
sbus_writel(0x00000000, &timers_global->timer_config);
- sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit);
+#ifdef CONFIG_SMP
+ sparc_config.cs_period = SBUS_CLOCK_RATE * 2; /* 2 seconds */
+ sparc_config.features |= FEAT_L14_ONESHOT;
+#else
+ sparc_config.cs_period = SBUS_CLOCK_RATE / HZ; /* 1/HZ sec */
+ sparc_config.features |= FEAT_L10_CLOCKEVENT;
+#endif
+ sparc_config.features |= FEAT_L10_CLOCKSOURCE;
+ sbus_writel(timer_value(sparc_config.cs_period),
+ &timers_global->l10_limit);
master_l10_counter = &timers_global->l10_count;
irq = sun4m_build_device_irq(NULL, SUN4M_TIMER_IRQ);
- err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
+ err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
if (err) {
printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n",
err);
@@ -434,7 +421,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
trap_table->inst_two = lvl14_save[1];
trap_table->inst_three = lvl14_save[2];
trap_table->inst_four = lvl14_save[3];
- local_flush_cache_all();
+ local_ops->cache_all();
local_irq_restore(flags);
}
#endif
@@ -475,17 +462,12 @@ void __init sun4m_init_IRQ(void)
if (num_cpu_iregs == 4)
sbus_writel(0, &sun4m_irq_global->interrupt_target);
- BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM);
-
- sparc_irq_config.init_timers = sun4m_init_timers;
- sparc_irq_config.build_device_irq = sun4m_build_device_irq;
+ sparc_config.init_timers = sun4m_init_timers;
+ sparc_config.build_device_irq = sun4m_build_device_irq;
+ sparc_config.clock_rate = SBUS_CLOCK_RATE;
+ sparc_config.clear_clock_irq = sun4m_clear_clock_irq;
+ sparc_config.load_profile_irq = sun4m_load_profile_irq;
-#ifdef CONFIG_SMP
- BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM);
-#endif
/* Cannot enable interrupts until OBP ticker is disabled. */
}
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 02db9a0412ce..128af7304288 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -4,14 +4,18 @@
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/profile.h>
#include <linux/delay.h>
+#include <linux/sched.h>
#include <linux/cpu.h>
#include <asm/cacheflush.h>
#include <asm/switch_to.h>
#include <asm/tlbflush.h>
+#include <asm/timer.h>
+#include <asm/oplib.h>
#include "irq.h"
#include "kernel.h"
@@ -30,26 +34,22 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val)
return val;
}
-static void smp4m_ipi_init(void);
-static void smp_setup_percpu_timer(void);
-
void __cpuinit smp4m_callin(void)
{
int cpuid = hard_smp_processor_id();
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
notify_cpu_starting(cpuid);
- /* Get our local ticker going. */
- smp_setup_percpu_timer();
+ register_percpu_ce(cpuid);
calibrate_delay();
smp_store_cpu_info(cpuid);
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
/*
* Unblock the master CPU _only_ when the scheduler state
@@ -61,8 +61,8 @@ void __cpuinit smp4m_callin(void)
swap_ulong(&cpu_callin_map[cpuid], 1);
/* XXX: What's up with all the flushes? */
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
/* Fix idle thread fields. */
__asm__ __volatile__("ld [%0], %%g6\n\t"
@@ -86,23 +86,19 @@ void __cpuinit smp4m_callin(void)
*/
void __init smp4m_boot_cpus(void)
{
- smp4m_ipi_init();
- smp_setup_percpu_timer();
- local_flush_cache_all();
+ sun4m_unmask_profile_irq();
+ local_ops->cache_all();
}
-int __cpuinit smp4m_boot_one_cpu(int i)
+int __cpuinit smp4m_boot_one_cpu(int i, struct task_struct *idle)
{
unsigned long *entry = &sun4m_cpu_startup;
- struct task_struct *p;
int timeout;
int cpu_node;
cpu_find_by_mid(i, &cpu_node);
+ current_set[i] = task_thread_info(idle);
- /* Cook up an idler for this guy. */
- p = fork_idle(i);
- current_set[i] = task_thread_info(p);
/* See trampoline.S for details... */
entry += ((i - 1) * 3);
@@ -117,7 +113,7 @@ int __cpuinit smp4m_boot_one_cpu(int i)
/* whirrr, whirrr, whirrrrrrrrr... */
printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
- local_flush_cache_all();
+ local_ops->cache_all();
prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry);
/* wheee... it's going... */
@@ -132,7 +128,7 @@ int __cpuinit smp4m_boot_one_cpu(int i)
return -ENODEV;
}
- local_flush_cache_all();
+ local_ops->cache_all();
return 0;
}
@@ -149,30 +145,29 @@ void __init smp4m_smp_done(void)
prev = &cpu_data(i).next;
}
*prev = first;
- local_flush_cache_all();
+ local_ops->cache_all();
/* Ok, they are spinning and ready to go. */
}
-
-/* Initialize IPIs on the SUN4M SMP machine */
-static void __init smp4m_ipi_init(void)
+static void sun4m_send_ipi(int cpu, int level)
{
+ sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set);
}
-static void smp4m_ipi_resched(int cpu)
+static void sun4m_ipi_resched(int cpu)
{
- set_cpu_int(cpu, IRQ_IPI_RESCHED);
+ sun4m_send_ipi(cpu, IRQ_IPI_RESCHED);
}
-static void smp4m_ipi_single(int cpu)
+static void sun4m_ipi_single(int cpu)
{
- set_cpu_int(cpu, IRQ_IPI_SINGLE);
+ sun4m_send_ipi(cpu, IRQ_IPI_SINGLE);
}
-static void smp4m_ipi_mask_one(int cpu)
+static void sun4m_ipi_mask_one(int cpu)
{
- set_cpu_int(cpu, IRQ_IPI_MASK);
+ sun4m_send_ipi(cpu, IRQ_IPI_MASK);
}
static struct smp_funcall {
@@ -189,7 +184,7 @@ static struct smp_funcall {
static DEFINE_SPINLOCK(cross_call_lock);
/* Cross calls must be serialized, at least currently. */
-static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
+static void sun4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
unsigned long arg2, unsigned long arg3,
unsigned long arg4)
{
@@ -216,7 +211,7 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
if (cpumask_test_cpu(i, &mask)) {
ccall_info.processors_in[i] = 0;
ccall_info.processors_out[i] = 0;
- set_cpu_int(i, IRQ_CROSS_CALL);
+ sun4m_send_ipi(i, IRQ_CROSS_CALL);
} else {
ccall_info.processors_in[i] = 1;
ccall_info.processors_out[i] = 1;
@@ -260,64 +255,33 @@ void smp4m_cross_call_irq(void)
void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
{
struct pt_regs *old_regs;
+ struct clock_event_device *ce;
int cpu = smp_processor_id();
old_regs = set_irq_regs(regs);
- sun4m_clear_profile_irq(cpu);
-
- profile_tick(CPU_PROFILING);
+ ce = &per_cpu(sparc32_clockevent, cpu);
- if (!--prof_counter(cpu)) {
- int user = user_mode(regs);
+ if (ce->mode & CLOCK_EVT_MODE_PERIODIC)
+ sun4m_clear_profile_irq(cpu);
+ else
+ sparc_config.load_profile_irq(cpu, 0); /* Is this needless? */
- irq_enter();
- update_process_times(user);
- irq_exit();
+ irq_enter();
+ ce->event_handler(ce);
+ irq_exit();
- prof_counter(cpu) = prof_multiplier(cpu);
- }
set_irq_regs(old_regs);
}
-static void __cpuinit smp_setup_percpu_timer(void)
-{
- int cpu = smp_processor_id();
-
- prof_counter(cpu) = prof_multiplier(cpu) = 1;
- load_profile_irq(cpu, lvl14_resolution);
-
- if (cpu == boot_cpu_id)
- sun4m_unmask_profile_irq();
-}
-
-static void __init smp4m_blackbox_id(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
- int rs1 = rd >> 11;
-
- addr[0] = 0x81580000 | rd; /* rd %tbr, reg */
- addr[1] = 0x8130200c | rd | rs1; /* srl reg, 0xc, reg */
- addr[2] = 0x80082003 | rd | rs1; /* and reg, 3, reg */
-}
-
-static void __init smp4m_blackbox_current(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
- int rs1 = rd >> 11;
-
- addr[0] = 0x81580000 | rd; /* rd %tbr, reg */
- addr[2] = 0x8130200a | rd | rs1; /* srl reg, 0xa, reg */
- addr[4] = 0x8008200c | rd | rs1; /* and reg, 0xc, reg */
-}
+static const struct sparc32_ipi_ops sun4m_ipi_ops = {
+ .cross_call = sun4m_cross_call,
+ .resched = sun4m_ipi_resched,
+ .single = sun4m_ipi_single,
+ .mask_one = sun4m_ipi_mask_one,
+};
void __init sun4m_init_smp(void)
{
- BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4m_blackbox_id);
- BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
- BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(smp_ipi_resched, smp4m_ipi_resched, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(smp_ipi_single, smp4m_ipi_single, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(smp_ipi_mask_one, smp4m_ipi_mask_one, BTFIXUPCALL_NORM);
+ sparc32_ipi_ops = &sun4m_ipi_ops;
}
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c
index 42b282fa6112..627e89af1d71 100644
--- a/arch/sparc/kernel/sys_sparc_32.c
+++ b/arch/sparc/kernel/sys_sparc_32.c
@@ -53,8 +53,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
/* See asm-sparc/uaccess.h */
if (len > TASK_SIZE - PAGE_SIZE)
return -ENOMEM;
- if (ARCH_SUN4C && len > 0x20000000)
- return -ENOMEM;
if (!addr)
addr = TASK_UNMAPPED_BASE;
@@ -65,10 +63,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
/* At this point: (!vmm || addr < vmm->vm_end). */
- if (ARCH_SUN4C && addr < 0xe0000000 && 0x20000000 - len < addr) {
- addr = PAGE_OFFSET;
- vmm = find_vma(current->mm, PAGE_OFFSET);
- }
if (TASK_SIZE - PAGE_SIZE - len < addr)
return -ENOMEM;
if (!vmm || addr + len <= vmm->vm_start)
@@ -99,11 +93,6 @@ out:
int sparc_mmap_check(unsigned long addr, unsigned long len)
{
- if (ARCH_SUN4C &&
- (len > 0x20000000 ||
- (addr < 0xe0000000 && addr + len > 0x20000000)))
- return -EINVAL;
-
/* See asm-sparc/uaccess.h */
if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE)
return -EINVAL;
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index db86b1a0e9a9..3a58e0d66f51 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -74,7 +74,7 @@ sys_call_table32:
.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
-/*280*/ .word sys32_tee, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
+/*280*/ .word sys32_tee, sys_add_key, sys_request_key, compat_sys_keyctl, compat_sys_openat
.word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64
/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c
index 7d0c088e8aba..953641549e82 100644
--- a/arch/sparc/kernel/time_32.c
+++ b/arch/sparc/kernel/time_32.c
@@ -26,6 +26,8 @@
#include <linux/rtc.h>
#include <linux/rtc/m48t59.h>
#include <linux/timex.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ioport.h>
@@ -40,13 +42,24 @@
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/idprom.h>
-#include <asm/machines.h>
#include <asm/page.h>
#include <asm/pcic.h>
#include <asm/irq_regs.h>
+#include <asm/setup.h>
#include "irq.h"
+static __cacheline_aligned_in_smp DEFINE_SEQLOCK(timer_cs_lock);
+static __volatile__ u64 timer_cs_internal_counter = 0;
+static char timer_cs_enabled = 0;
+
+static struct clock_event_device timer_ce;
+static char timer_ce_enabled = 0;
+
+#ifdef CONFIG_SMP
+DEFINE_PER_CPU(struct clock_event_device, sparc32_clockevent);
+#endif
+
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL(rtc_lock);
@@ -55,7 +68,6 @@ static int set_rtc_mmss(unsigned long);
unsigned long profile_pc(struct pt_regs *regs)
{
extern char __copy_user_begin[], __copy_user_end[];
- extern char __atomic_begin[], __atomic_end[];
extern char __bzero_begin[], __bzero_end[];
unsigned long pc = regs->pc;
@@ -63,8 +75,6 @@ unsigned long profile_pc(struct pt_regs *regs)
if (in_lock_functions(pc) ||
(pc >= (unsigned long) __copy_user_begin &&
pc < (unsigned long) __copy_user_end) ||
- (pc >= (unsigned long) __atomic_begin &&
- pc < (unsigned long) __atomic_end) ||
(pc >= (unsigned long) __bzero_begin &&
pc < (unsigned long) __bzero_end))
pc = regs->u_regs[UREG_RETPC];
@@ -75,36 +85,168 @@ EXPORT_SYMBOL(profile_pc);
__volatile__ unsigned int *master_l10_counter;
-u32 (*do_arch_gettimeoffset)(void);
-
int update_persistent_clock(struct timespec now)
{
return set_rtc_mmss(now.tv_sec);
}
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "xtime_update()" routine every clocktick
- */
+irqreturn_t notrace timer_interrupt(int dummy, void *dev_id)
+{
+ if (timer_cs_enabled) {
+ write_seqlock(&timer_cs_lock);
+ timer_cs_internal_counter++;
+ sparc_config.clear_clock_irq();
+ write_sequnlock(&timer_cs_lock);
+ } else {
+ sparc_config.clear_clock_irq();
+ }
-#define TICK_SIZE (tick_nsec / 1000)
+ if (timer_ce_enabled)
+ timer_ce.event_handler(&timer_ce);
-static irqreturn_t timer_interrupt(int dummy, void *dev_id)
+ return IRQ_HANDLED;
+}
+
+static void timer_ce_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
{
-#ifndef CONFIG_SMP
- profile_tick(CPU_PROFILING);
-#endif
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ case CLOCK_EVT_MODE_RESUME:
+ timer_ce_enabled = 1;
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ timer_ce_enabled = 0;
+ break;
+ default:
+ break;
+ }
+ smp_mb();
+}
- clear_clock_irq();
+static __init void setup_timer_ce(void)
+{
+ struct clock_event_device *ce = &timer_ce;
+
+ BUG_ON(smp_processor_id() != boot_cpu_id);
+
+ ce->name = "timer_ce";
+ ce->rating = 100;
+ ce->features = CLOCK_EVT_FEAT_PERIODIC;
+ ce->set_mode = timer_ce_set_mode;
+ ce->cpumask = cpu_possible_mask;
+ ce->shift = 32;
+ ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC,
+ ce->shift);
+ clockevents_register_device(ce);
+}
- xtime_update(1);
+static unsigned int sbus_cycles_offset(void)
+{
+ unsigned int val, offset;
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
- return IRQ_HANDLED;
+ val = *master_l10_counter;
+ offset = (val >> TIMER_VALUE_SHIFT) & TIMER_VALUE_MASK;
+
+ /* Limit hit? */
+ if (val & TIMER_LIMIT_BIT)
+ offset += sparc_config.cs_period;
+
+ return offset;
+}
+
+static cycle_t timer_cs_read(struct clocksource *cs)
+{
+ unsigned int seq, offset;
+ u64 cycles;
+
+ do {
+ seq = read_seqbegin(&timer_cs_lock);
+
+ cycles = timer_cs_internal_counter;
+ offset = sparc_config.get_cycles_offset();
+ } while (read_seqretry(&timer_cs_lock, seq));
+
+ /* Count absolute cycles */
+ cycles *= sparc_config.cs_period;
+ cycles += offset;
+
+ return cycles;
+}
+
+static struct clocksource timer_cs = {
+ .name = "timer_cs",
+ .rating = 100,
+ .read = timer_cs_read,
+ .mask = CLOCKSOURCE_MASK(64),
+ .shift = 2,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static __init int setup_timer_cs(void)
+{
+ timer_cs_enabled = 1;
+ timer_cs.mult = clocksource_hz2mult(sparc_config.clock_rate,
+ timer_cs.shift);
+
+ return clocksource_register(&timer_cs);
}
+#ifdef CONFIG_SMP
+static void percpu_ce_setup(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ int cpu = __first_cpu(evt->cpumask);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ sparc_config.load_profile_irq(cpu,
+ SBUS_CLOCK_RATE / HZ);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_UNUSED:
+ sparc_config.load_profile_irq(cpu, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+static int percpu_ce_set_next_event(unsigned long delta,
+ struct clock_event_device *evt)
+{
+ int cpu = __first_cpu(evt->cpumask);
+ unsigned int next = (unsigned int)delta;
+
+ sparc_config.load_profile_irq(cpu, next);
+ return 0;
+}
+
+void register_percpu_ce(int cpu)
+{
+ struct clock_event_device *ce = &per_cpu(sparc32_clockevent, cpu);
+ unsigned int features = CLOCK_EVT_FEAT_PERIODIC;
+
+ if (sparc_config.features & FEAT_L14_ONESHOT)
+ features |= CLOCK_EVT_FEAT_ONESHOT;
+
+ ce->name = "percpu_ce";
+ ce->rating = 200;
+ ce->features = features;
+ ce->set_mode = percpu_ce_setup;
+ ce->set_next_event = percpu_ce_set_next_event;
+ ce->cpumask = cpumask_of(cpu);
+ ce->shift = 32;
+ ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC,
+ ce->shift);
+ ce->max_delta_ns = clockevent_delta2ns(sparc_config.clock_rate, ce);
+ ce->min_delta_ns = clockevent_delta2ns(100, ce);
+
+ clockevents_register_device(ce);
+}
+#endif
+
static unsigned char mostek_read_byte(struct device *dev, u32 ofs)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -195,38 +337,28 @@ static int __init clock_init(void)
*/
fs_initcall(clock_init);
-
-u32 sbus_do_gettimeoffset(void)
-{
- unsigned long val = *master_l10_counter;
- unsigned long usec = (val >> 10) & 0x1fffff;
-
- /* Limit hit? */
- if (val & 0x80000000)
- usec += 1000000 / HZ;
-
- return usec * 1000;
-}
-
-
-u32 arch_gettimeoffset(void)
+static void __init sparc32_late_time_init(void)
{
- if (unlikely(!do_arch_gettimeoffset))
- return 0;
- return do_arch_gettimeoffset();
+ if (sparc_config.features & FEAT_L10_CLOCKEVENT)
+ setup_timer_ce();
+ if (sparc_config.features & FEAT_L10_CLOCKSOURCE)
+ setup_timer_cs();
+#ifdef CONFIG_SMP
+ register_percpu_ce(smp_processor_id());
+#endif
}
static void __init sbus_time_init(void)
{
- do_arch_gettimeoffset = sbus_do_gettimeoffset;
-
- btfixup();
-
- sparc_irq_config.init_timers(timer_interrupt);
+ sparc_config.get_cycles_offset = sbus_cycles_offset;
+ sparc_config.init_timers();
}
void __init time_init(void)
{
+ sparc_config.features = 0;
+ late_time_init = sparc32_late_time_init;
+
if (pcic_present())
pci_time_init();
else
diff --git a/arch/sparc/kernel/trampoline_32.S b/arch/sparc/kernel/trampoline_32.S
index 691f484e03b3..7364ddc9e5aa 100644
--- a/arch/sparc/kernel/trampoline_32.S
+++ b/arch/sparc/kernel/trampoline_32.S
@@ -15,8 +15,8 @@
#include <asm/contregs.h>
#include <asm/thread_info.h>
- .globl sun4m_cpu_startup, __smp4m_processor_id, __leon_processor_id
- .globl sun4d_cpu_startup, __smp4d_processor_id
+ .globl sun4m_cpu_startup
+ .globl sun4d_cpu_startup
__CPUINIT
.align 4
@@ -94,24 +94,6 @@ smp_do_cpu_idle:
call cpu_panic
nop
-__smp4m_processor_id:
- rd %tbr, %g2
- srl %g2, 12, %g2
- and %g2, 3, %g2
- retl
- mov %g1, %o7
-
-__smp4d_processor_id:
- lda [%g0] ASI_M_VIKING_TMP1, %g2
- retl
- mov %g1, %o7
-
-__leon_processor_id:
- rd %asr17,%g2
- srl %g2,28,%g2
- retl
- mov %g1, %o7
-
/* CPUID in bootbus can be found at PA 0xff0140000 */
#define SUN4D_BOOTBUS_CPUID 0xf0140000
diff --git a/arch/sparc/kernel/traps_32.c b/arch/sparc/kernel/traps_32.c
index d2de21333146..a5785ea2a85d 100644
--- a/arch/sparc/kernel/traps_32.c
+++ b/arch/sparc/kernel/traps_32.c
@@ -120,8 +120,6 @@ void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned lon
printk("Ill instr. at pc=%08lx instruction is %08lx\n",
regs->pc, *(unsigned long *)regs->pc);
#endif
- if (!do_user_muldiv (regs, pc))
- return;
info.si_signo = SIGILL;
info.si_errno = 0;
diff --git a/arch/sparc/kernel/ttable_32.S b/arch/sparc/kernel/ttable_32.S
new file mode 100644
index 000000000000..8a7a96ca676f
--- /dev/null
+++ b/arch/sparc/kernel/ttable_32.S
@@ -0,0 +1,417 @@
+/* The Sparc trap table, bootloader gives us control at _start. */
+ __HEAD
+
+ .globl _start
+_start:
+
+ .globl _stext
+_stext:
+
+ .globl trapbase
+trapbase:
+
+#ifdef CONFIG_SMP
+trapbase_cpu0:
+#endif
+/* We get control passed to us here at t_zero. */
+t_zero: b gokernel; nop; nop; nop;
+t_tflt: SRMMU_TFAULT /* Inst. Access Exception */
+t_bins: TRAP_ENTRY(0x2, bad_instruction) /* Illegal Instruction */
+t_pins: TRAP_ENTRY(0x3, priv_instruction) /* Privileged Instruction */
+t_fpd: TRAP_ENTRY(0x4, fpd_trap_handler) /* Floating Point Disabled */
+t_wovf: WINDOW_SPILL /* Window Overflow */
+t_wunf: WINDOW_FILL /* Window Underflow */
+t_mna: TRAP_ENTRY(0x7, mna_handler) /* Memory Address Not Aligned */
+t_fpe: TRAP_ENTRY(0x8, fpe_trap_handler) /* Floating Point Exception */
+t_dflt: SRMMU_DFAULT /* Data Miss Exception */
+t_tio: TRAP_ENTRY(0xa, do_tag_overflow) /* Tagged Instruction Ovrflw */
+t_wpt: TRAP_ENTRY(0xb, do_watchpoint) /* Watchpoint Detected */
+t_badc: BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
+t_irq1: TRAP_ENTRY_INTERRUPT(1) /* IRQ Software/SBUS Level 1 */
+t_irq2: TRAP_ENTRY_INTERRUPT(2) /* IRQ SBUS Level 2 */
+t_irq3: TRAP_ENTRY_INTERRUPT(3) /* IRQ SCSI/DMA/SBUS Level 3 */
+t_irq4: TRAP_ENTRY_INTERRUPT(4) /* IRQ Software Level 4 */
+t_irq5: TRAP_ENTRY_INTERRUPT(5) /* IRQ SBUS/Ethernet Level 5 */
+t_irq6: TRAP_ENTRY_INTERRUPT(6) /* IRQ Software Level 6 */
+t_irq7: TRAP_ENTRY_INTERRUPT(7) /* IRQ Video/SBUS Level 5 */
+t_irq8: TRAP_ENTRY_INTERRUPT(8) /* IRQ SBUS Level 6 */
+t_irq9: TRAP_ENTRY_INTERRUPT(9) /* IRQ SBUS Level 7 */
+t_irq10:TRAP_ENTRY_INTERRUPT(10) /* IRQ Timer #1 (one we use) */
+t_irq11:TRAP_ENTRY_INTERRUPT(11) /* IRQ Floppy Intr. */
+t_irq12:TRAP_ENTRY_INTERRUPT(12) /* IRQ Zilog serial chip */
+t_irq13:TRAP_ENTRY_INTERRUPT(13) /* IRQ Audio Intr. */
+t_irq14:TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */
+
+ .globl t_nmi
+t_nmi: TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
+
+t_racc: TRAP_ENTRY(0x20, do_reg_access) /* General Register Access Error */
+t_iacce:BAD_TRAP(0x21) /* Instr Access Error */
+t_bad22:BAD_TRAP(0x22)
+ BAD_TRAP(0x23)
+t_cpdis:TRAP_ENTRY(0x24, do_cp_disabled) /* Co-Processor Disabled */
+t_uflsh:SKIP_TRAP(0x25, unimp_flush) /* Unimplemented FLUSH inst. */
+t_bad26:BAD_TRAP(0x26) BAD_TRAP(0x27)
+t_cpexc:TRAP_ENTRY(0x28, do_cp_exception) /* Co-Processor Exception */
+t_dacce:SRMMU_DFAULT /* Data Access Error */
+t_hwdz: TRAP_ENTRY(0x2a, do_hw_divzero) /* Division by zero, you lose... */
+t_dserr:BAD_TRAP(0x2b) /* Data Store Error */
+t_daccm:BAD_TRAP(0x2c) /* Data Access MMU-Miss */
+t_bad2d:BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
+t_bad32:BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
+t_bad37:BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
+t_iaccm:BAD_TRAP(0x3c) /* Instr Access MMU-Miss */
+t_bad3d:BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40) BAD_TRAP(0x41)
+t_bad42:BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45) BAD_TRAP(0x46)
+t_bad47:BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a) BAD_TRAP(0x4b)
+t_bad4c:BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f) BAD_TRAP(0x50)
+t_bad51:BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
+t_bad56:BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
+t_bad5b:BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
+t_bad60:BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
+t_bad65:BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
+t_bad6a:BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
+t_bad6f:BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
+t_bad74:BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
+t_bad79:BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
+t_bad7e:BAD_TRAP(0x7e) BAD_TRAP(0x7f)
+t_bad80:BAD_TRAP(0x80) /* SunOS System Call */
+t_sbkpt:BREAKPOINT_TRAP /* Software Breakpoint/KGDB */
+t_divz: TRAP_ENTRY(0x82, do_hw_divzero) /* Divide by zero trap */
+t_flwin:TRAP_ENTRY(0x83, do_flush_windows) /* Flush Windows Trap */
+t_clwin:BAD_TRAP(0x84) /* Clean Windows Trap */
+t_rchk: BAD_TRAP(0x85) /* Range Check */
+t_funal:BAD_TRAP(0x86) /* Fix Unaligned Access Trap */
+t_iovf: BAD_TRAP(0x87) /* Integer Overflow Trap */
+t_bad88:BAD_TRAP(0x88) /* Slowaris System Call */
+t_bad89:BAD_TRAP(0x89) /* Net-B.S. System Call */
+t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e)
+t_bad8f:BAD_TRAP(0x8f)
+t_linux:LINUX_SYSCALL_TRAP /* Linux System Call */
+t_bad91:BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95)
+t_bad96:BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a)
+t_bad9b:BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f)
+t_getcc:GETCC_TRAP /* Get Condition Codes */
+t_setcc:SETCC_TRAP /* Set Condition Codes */
+t_getpsr:GETPSR_TRAP /* Get PSR Register */
+t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+t_bada7:BAD_TRAP(0xa7)
+t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
+t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
+t_badb1:BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
+t_badb6:BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
+t_badbb:BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
+t_badc0:BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
+t_badc5:BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
+t_badca:BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
+t_badcf:BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
+t_badd4:BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
+t_badd9:BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
+t_badde:BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
+t_bade3:BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
+t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
+t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
+t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
+t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
+t_badfc:BAD_TRAP(0xfc)
+t_kgdb: KGDB_TRAP(0xfd)
+dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */
+dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */
+
+ .globl end_traptable
+end_traptable:
+
+#ifdef CONFIG_SMP
+ /* Trap tables for the other cpus. */
+ .globl trapbase_cpu1, trapbase_cpu2, trapbase_cpu3
+trapbase_cpu1:
+ BAD_TRAP(0x0)
+ SRMMU_TFAULT
+ TRAP_ENTRY(0x2, bad_instruction)
+ TRAP_ENTRY(0x3, priv_instruction)
+ TRAP_ENTRY(0x4, fpd_trap_handler)
+ WINDOW_SPILL
+ WINDOW_FILL
+ TRAP_ENTRY(0x7, mna_handler)
+ TRAP_ENTRY(0x8, fpe_trap_handler)
+ SRMMU_DFAULT
+ TRAP_ENTRY(0xa, do_tag_overflow)
+ TRAP_ENTRY(0xb, do_watchpoint)
+ BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
+ TRAP_ENTRY_INTERRUPT(1) TRAP_ENTRY_INTERRUPT(2)
+ TRAP_ENTRY_INTERRUPT(3) TRAP_ENTRY_INTERRUPT(4)
+ TRAP_ENTRY_INTERRUPT(5) TRAP_ENTRY_INTERRUPT(6)
+ TRAP_ENTRY_INTERRUPT(7) TRAP_ENTRY_INTERRUPT(8)
+ TRAP_ENTRY_INTERRUPT(9) TRAP_ENTRY_INTERRUPT(10)
+ TRAP_ENTRY_INTERRUPT(11) TRAP_ENTRY_INTERRUPT(12)
+ TRAP_ENTRY_INTERRUPT(13) TRAP_ENTRY_INTERRUPT(14)
+ TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
+ TRAP_ENTRY(0x20, do_reg_access)
+ BAD_TRAP(0x21)
+ BAD_TRAP(0x22)
+ BAD_TRAP(0x23)
+ TRAP_ENTRY(0x24, do_cp_disabled)
+ SKIP_TRAP(0x25, unimp_flush)
+ BAD_TRAP(0x26)
+ BAD_TRAP(0x27)
+ TRAP_ENTRY(0x28, do_cp_exception)
+ SRMMU_DFAULT
+ TRAP_ENTRY(0x2a, do_hw_divzero)
+ BAD_TRAP(0x2b)
+ BAD_TRAP(0x2c)
+ BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
+ BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
+ BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
+ BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
+ BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
+ BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
+ BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
+ BAD_TRAP(0x50)
+ BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
+ BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
+ BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
+ BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
+ BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
+ BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
+ BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
+ BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
+ BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
+ BAD_TRAP(0x7e) BAD_TRAP(0x7f)
+ BAD_TRAP(0x80)
+ BREAKPOINT_TRAP
+ TRAP_ENTRY(0x82, do_hw_divzero)
+ TRAP_ENTRY(0x83, do_flush_windows)
+ BAD_TRAP(0x84) BAD_TRAP(0x85) BAD_TRAP(0x86)
+ BAD_TRAP(0x87) BAD_TRAP(0x88) BAD_TRAP(0x89)
+ BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
+ BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
+ LINUX_SYSCALL_TRAP BAD_TRAP(0x91)
+ BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
+ BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
+ BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
+ BAD_TRAP(0x9f)
+ GETCC_TRAP
+ SETCC_TRAP
+ GETPSR_TRAP
+ BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+ BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
+ BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
+ BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
+ BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
+ BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
+ BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
+ BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
+ BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
+ BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
+ BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
+ BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
+ BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
+ BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
+ BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
+ BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
+ BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
+ BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
+ BAD_TRAP(0xfc)
+ KGDB_TRAP(0xfd)
+ BAD_TRAP(0xfe)
+ BAD_TRAP(0xff)
+
+trapbase_cpu2:
+ BAD_TRAP(0x0)
+ SRMMU_TFAULT
+ TRAP_ENTRY(0x2, bad_instruction)
+ TRAP_ENTRY(0x3, priv_instruction)
+ TRAP_ENTRY(0x4, fpd_trap_handler)
+ WINDOW_SPILL
+ WINDOW_FILL
+ TRAP_ENTRY(0x7, mna_handler)
+ TRAP_ENTRY(0x8, fpe_trap_handler)
+ SRMMU_DFAULT
+ TRAP_ENTRY(0xa, do_tag_overflow)
+ TRAP_ENTRY(0xb, do_watchpoint)
+ BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
+ TRAP_ENTRY_INTERRUPT(1)
+ TRAP_ENTRY_INTERRUPT(2)
+ TRAP_ENTRY_INTERRUPT(3)
+ TRAP_ENTRY_INTERRUPT(4)
+ TRAP_ENTRY_INTERRUPT(5)
+ TRAP_ENTRY_INTERRUPT(6)
+ TRAP_ENTRY_INTERRUPT(7)
+ TRAP_ENTRY_INTERRUPT(8)
+ TRAP_ENTRY_INTERRUPT(9)
+ TRAP_ENTRY_INTERRUPT(10)
+ TRAP_ENTRY_INTERRUPT(11)
+ TRAP_ENTRY_INTERRUPT(12)
+ TRAP_ENTRY_INTERRUPT(13)
+ TRAP_ENTRY_INTERRUPT(14)
+ TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
+ TRAP_ENTRY(0x20, do_reg_access)
+ BAD_TRAP(0x21)
+ BAD_TRAP(0x22)
+ BAD_TRAP(0x23)
+ TRAP_ENTRY(0x24, do_cp_disabled)
+ SKIP_TRAP(0x25, unimp_flush)
+ BAD_TRAP(0x26)
+ BAD_TRAP(0x27)
+ TRAP_ENTRY(0x28, do_cp_exception)
+ SRMMU_DFAULT
+ TRAP_ENTRY(0x2a, do_hw_divzero)
+ BAD_TRAP(0x2b)
+ BAD_TRAP(0x2c)
+ BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
+ BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
+ BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
+ BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
+ BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
+ BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
+ BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
+ BAD_TRAP(0x50)
+ BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
+ BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
+ BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
+ BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
+ BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
+ BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
+ BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
+ BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
+ BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
+ BAD_TRAP(0x7e) BAD_TRAP(0x7f)
+ BAD_TRAP(0x80)
+ BREAKPOINT_TRAP
+ TRAP_ENTRY(0x82, do_hw_divzero)
+ TRAP_ENTRY(0x83, do_flush_windows)
+ BAD_TRAP(0x84)
+ BAD_TRAP(0x85)
+ BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
+ BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
+ BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
+ LINUX_SYSCALL_TRAP BAD_TRAP(0x91)
+ BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
+ BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
+ BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
+ BAD_TRAP(0x9f)
+ GETCC_TRAP
+ SETCC_TRAP
+ GETPSR_TRAP
+ BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+ BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
+ BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
+ BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
+ BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
+ BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
+ BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
+ BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
+ BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
+ BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
+ BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
+ BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
+ BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
+ BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
+ BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
+ BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
+ BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
+ BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
+ BAD_TRAP(0xfc)
+ KGDB_TRAP(0xfd)
+ BAD_TRAP(0xfe)
+ BAD_TRAP(0xff)
+
+trapbase_cpu3:
+ BAD_TRAP(0x0)
+ SRMMU_TFAULT
+ TRAP_ENTRY(0x2, bad_instruction)
+ TRAP_ENTRY(0x3, priv_instruction)
+ TRAP_ENTRY(0x4, fpd_trap_handler)
+ WINDOW_SPILL
+ WINDOW_FILL
+ TRAP_ENTRY(0x7, mna_handler)
+ TRAP_ENTRY(0x8, fpe_trap_handler)
+ SRMMU_DFAULT
+ TRAP_ENTRY(0xa, do_tag_overflow)
+ TRAP_ENTRY(0xb, do_watchpoint)
+ BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
+ TRAP_ENTRY_INTERRUPT(1)
+ TRAP_ENTRY_INTERRUPT(2)
+ TRAP_ENTRY_INTERRUPT(3)
+ TRAP_ENTRY_INTERRUPT(4)
+ TRAP_ENTRY_INTERRUPT(5)
+ TRAP_ENTRY_INTERRUPT(6)
+ TRAP_ENTRY_INTERRUPT(7)
+ TRAP_ENTRY_INTERRUPT(8)
+ TRAP_ENTRY_INTERRUPT(9)
+ TRAP_ENTRY_INTERRUPT(10)
+ TRAP_ENTRY_INTERRUPT(11)
+ TRAP_ENTRY_INTERRUPT(12)
+ TRAP_ENTRY_INTERRUPT(13)
+ TRAP_ENTRY_INTERRUPT(14)
+ TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
+ TRAP_ENTRY(0x20, do_reg_access)
+ BAD_TRAP(0x21)
+ BAD_TRAP(0x22)
+ BAD_TRAP(0x23)
+ TRAP_ENTRY(0x24, do_cp_disabled)
+ SKIP_TRAP(0x25, unimp_flush)
+ BAD_TRAP(0x26)
+ BAD_TRAP(0x27)
+ TRAP_ENTRY(0x28, do_cp_exception)
+ SRMMU_DFAULT
+ TRAP_ENTRY(0x2a, do_hw_divzero)
+ BAD_TRAP(0x2b) BAD_TRAP(0x2c)
+ BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
+ BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
+ BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
+ BAD_TRAP(0x3c) BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40)
+ BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45)
+ BAD_TRAP(0x46) BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a)
+ BAD_TRAP(0x4b) BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
+ BAD_TRAP(0x50)
+ BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
+ BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
+ BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
+ BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
+ BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
+ BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
+ BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
+ BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
+ BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
+ BAD_TRAP(0x7e) BAD_TRAP(0x7f)
+ BAD_TRAP(0x80)
+ BREAKPOINT_TRAP
+ TRAP_ENTRY(0x82, do_hw_divzero)
+ TRAP_ENTRY(0x83, do_flush_windows)
+ BAD_TRAP(0x84) BAD_TRAP(0x85)
+ BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
+ BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
+ BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
+ LINUX_SYSCALL_TRAP
+ BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
+ BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
+ BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
+ BAD_TRAP(0x9f)
+ GETCC_TRAP
+ SETCC_TRAP
+ GETPSR_TRAP
+ BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+ BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
+ BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
+ BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
+ BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
+ BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
+ BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
+ BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
+ BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
+ BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
+ BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
+ BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
+ BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
+ BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
+ BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
+ BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
+ BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
+ BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
+ BAD_TRAP(0xfc)
+ KGDB_TRAP(0xfd)
+ BAD_TRAP(0xfe)
+ BAD_TRAP(0xff)
+
+#endif
diff --git a/arch/sparc/kernel/ttable.S b/arch/sparc/kernel/ttable_64.S
index c6dfdaa29e20..c6dfdaa29e20 100644
--- a/arch/sparc/kernel/ttable.S
+++ b/arch/sparc/kernel/ttable_64.S
diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c
index dae85bc2eda5..f81d038f7340 100644
--- a/arch/sparc/kernel/unaligned_64.c
+++ b/arch/sparc/kernel/unaligned_64.c
@@ -21,7 +21,6 @@
#include <linux/bitops.h>
#include <linux/perf_event.h>
#include <linux/ratelimit.h>
-#include <linux/bitops.h>
#include <asm/fpumacro.h>
#include <asm/cacheflush.h>
diff --git a/arch/sparc/kernel/wof.S b/arch/sparc/kernel/wof.S
index 3bbcd8dc9abf..4c2de3cf309b 100644
--- a/arch/sparc/kernel/wof.S
+++ b/arch/sparc/kernel/wof.S
@@ -163,9 +163,8 @@ spwin_fromuser:
* the label 'spwin_user_stack_is_bolixed' which will take
* care of things at that point.
*/
- .globl spwin_mmu_patchme
-spwin_mmu_patchme: b spwin_sun4c_stackchk
- andcc %sp, 0x7, %g0
+ b spwin_srmmu_stackchk
+ andcc %sp, 0x7, %g0
spwin_good_ustack:
/* LOCATION: Window to be saved */
@@ -306,73 +305,6 @@ spwin_bad_ustack_from_kernel:
* As noted above %curptr cannot be touched by this routine at all.
*/
-spwin_sun4c_stackchk:
- /* LOCATION: Window to be saved on the stack */
-
- /* See if the stack is in the address space hole but first,
- * check results of callers andcc %sp, 0x7, %g0
- */
- be 1f
- sra %sp, 29, %glob_tmp
-
- rd %psr, %glob_tmp
- b spwin_user_stack_is_bolixed + 0x4
- nop
-
-1:
- add %glob_tmp, 0x1, %glob_tmp
- andncc %glob_tmp, 0x1, %g0
- be 1f
- and %sp, 0xfff, %glob_tmp ! delay slot
-
- rd %psr, %glob_tmp
- b spwin_user_stack_is_bolixed + 0x4
- nop
-
- /* See if our dump area will be on more than one
- * page.
- */
-1:
- add %glob_tmp, 0x38, %glob_tmp
- andncc %glob_tmp, 0xff8, %g0
- be spwin_sun4c_onepage ! only one page to check
- lda [%sp] ASI_PTE, %glob_tmp ! have to check first page anyways
-
-spwin_sun4c_twopages:
- /* Is first page ok permission wise? */
- srl %glob_tmp, 29, %glob_tmp
- cmp %glob_tmp, 0x6
- be 1f
- add %sp, 0x38, %glob_tmp /* Is second page in vma hole? */
-
- rd %psr, %glob_tmp
- b spwin_user_stack_is_bolixed + 0x4
- nop
-
-1:
- sra %glob_tmp, 29, %glob_tmp
- add %glob_tmp, 0x1, %glob_tmp
- andncc %glob_tmp, 0x1, %g0
- be 1f
- add %sp, 0x38, %glob_tmp
-
- rd %psr, %glob_tmp
- b spwin_user_stack_is_bolixed + 0x4
- nop
-
-1:
- lda [%glob_tmp] ASI_PTE, %glob_tmp
-
-spwin_sun4c_onepage:
- srl %glob_tmp, 29, %glob_tmp
- cmp %glob_tmp, 0x6 ! can user write to it?
- be spwin_good_ustack ! success
- nop
-
- rd %psr, %glob_tmp
- b spwin_user_stack_is_bolixed + 0x4
- nop
-
/* This is a generic SRMMU routine. As far as I know this
* works for all current v8/srmmu implementations, we'll
* see...
diff --git a/arch/sparc/kernel/wuf.S b/arch/sparc/kernel/wuf.S
index 779ff750603d..9fde91a249e0 100644
--- a/arch/sparc/kernel/wuf.S
+++ b/arch/sparc/kernel/wuf.S
@@ -131,12 +131,9 @@ fwin_from_user:
/* LOCATION: Window 'W' */
- /* Branch to the architecture specific stack validation
- * routine. They can be found below...
- */
- .globl fwin_mmu_patchme
-fwin_mmu_patchme: b sun4c_fwin_stackchk
- andcc %sp, 0x7, %g0
+ /* Branch to the stack validation routine */
+ b srmmu_fwin_stackchk
+ andcc %sp, 0x7, %g0
#define STACK_OFFSET (THREAD_SIZE - TRACEREG_SZ - STACKFRAME_SZ)
@@ -242,57 +239,6 @@ fwin_user_finish_up:
* 'someone elses' window possibly.
*/
- .align 4
-sun4c_fwin_stackchk:
- /* LOCATION: Window 'W' */
-
- /* Caller did 'andcc %sp, 0x7, %g0' */
- be 1f
- and %sp, 0xfff, %l0 ! delay slot
-
- b,a fwin_user_stack_is_bolixed
-
- /* See if we have to check the sanity of one page or two */
-1:
- add %l0, 0x38, %l0
- sra %sp, 29, %l5
- add %l5, 0x1, %l5
- andncc %l5, 0x1, %g0
- be 1f
- andncc %l0, 0xff8, %g0
-
- b,a fwin_user_stack_is_bolixed /* %sp is in vma hole, yuck */
-
-1:
- be sun4c_fwin_onepage /* Only one page to check */
- lda [%sp] ASI_PTE, %l1
-sun4c_fwin_twopages:
- add %sp, 0x38, %l0
- sra %l0, 29, %l5
- add %l5, 0x1, %l5
- andncc %l5, 0x1, %g0
- be 1f
- lda [%l0] ASI_PTE, %l1
-
- b,a fwin_user_stack_is_bolixed /* Second page in vma hole */
-
-1:
- srl %l1, 29, %l1
- andcc %l1, 0x4, %g0
- bne sun4c_fwin_onepage
- lda [%sp] ASI_PTE, %l1
-
- b,a fwin_user_stack_is_bolixed /* Second page has bad perms */
-
-sun4c_fwin_onepage:
- srl %l1, 29, %l1
- andcc %l1, 0x4, %g0
- bne fwin_user_stack_is_ok
- nop
-
- /* A page had bad page permissions, losing... */
- b,a fwin_user_stack_is_bolixed
-
.globl srmmu_fwin_stackchk
srmmu_fwin_stackchk:
/* LOCATION: Window 'W' */
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index a3fc4375a150..389628f50a15 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -4,7 +4,7 @@
asflags-y := -ansi -DST_DIV0=0x02
ccflags-y := -Werror
-lib-$(CONFIG_SPARC32) += mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o
+lib-$(CONFIG_SPARC32) += ashrdi3.o
lib-$(CONFIG_SPARC32) += memcpy.o memset.o
lib-y += strlen.o
lib-y += checksum_$(BITS).o
@@ -13,7 +13,7 @@ lib-y += memscan_$(BITS).o memcmp.o strncmp_$(BITS).o
lib-y += strncpy_from_user_$(BITS).o strlen_user_$(BITS).o
lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o
lib-$(CONFIG_SPARC32) += copy_user.o locks.o
-lib-y += atomic_$(BITS).o
+lib-$(CONFIG_SPARC64) += atomic_64.o
lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o
lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o
@@ -40,7 +40,7 @@ lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o
lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o
obj-y += iomap.o
-obj-$(CONFIG_SPARC32) += atomic32.o
+obj-$(CONFIG_SPARC32) += atomic32.o ucmpdi2.o
obj-y += ksyms.o
obj-$(CONFIG_SPARC64) += PeeCeeI.o
obj-y += usercopy.o
diff --git a/arch/sparc/lib/ashldi3.S b/arch/sparc/lib/ashldi3.S
index 17912e608716..86f60de07b0a 100644
--- a/arch/sparc/lib/ashldi3.S
+++ b/arch/sparc/lib/ashldi3.S
@@ -5,10 +5,10 @@
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
*/
+#include <linux/linkage.h>
+
.text
- .align 4
- .globl __ashldi3
-__ashldi3:
+ENTRY(__ashldi3)
cmp %o2, 0
be 9f
mov 0x20, %g2
@@ -32,3 +32,4 @@ __ashldi3:
9:
retl
nop
+ENDPROC(__ashldi3)
diff --git a/arch/sparc/lib/ashrdi3.S b/arch/sparc/lib/ashrdi3.S
index 85398fd6dcc9..6eb8ba2dd50e 100644
--- a/arch/sparc/lib/ashrdi3.S
+++ b/arch/sparc/lib/ashrdi3.S
@@ -5,10 +5,10 @@
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/linkage.h>
+
.text
- .align 4
- .globl __ashrdi3
-__ashrdi3:
+ENTRY(__ashrdi3)
tst %o2
be 3f
or %g0, 32, %g2
@@ -34,3 +34,4 @@ __ashrdi3:
3:
jmpl %o7 + 8, %g0
nop
+ENDPROC(__ashrdi3)
diff --git a/arch/sparc/lib/atomic_32.S b/arch/sparc/lib/atomic_32.S
deleted file mode 100644
index eb6c7359cbd1..000000000000
--- a/arch/sparc/lib/atomic_32.S
+++ /dev/null
@@ -1,44 +0,0 @@
-/* atomic.S: Move this stuff here for better ICACHE hit rates.
- *
- * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
- */
-
-#include <asm/ptrace.h>
-#include <asm/psr.h>
-
- .text
- .align 4
-
- .globl __atomic_begin
-__atomic_begin:
-
-#ifndef CONFIG_SMP
- .globl ___xchg32_sun4c
-___xchg32_sun4c:
- rd %psr, %g3
- andcc %g3, PSR_PIL, %g0
- bne 1f
- nop
- wr %g3, PSR_PIL, %psr
- nop; nop; nop
-1:
- andcc %g3, PSR_PIL, %g0
- ld [%g1], %g7
- bne 1f
- st %g2, [%g1]
- wr %g3, 0x0, %psr
- nop; nop; nop
-1:
- mov %g7, %g2
- jmpl %o7 + 8, %g0
- mov %g4, %o7
-
- .globl ___xchg32_sun4md
-___xchg32_sun4md:
- swap [%g1], %g2
- jmpl %o7 + 8, %g0
- mov %g4, %o7
-#endif
-
- .globl __atomic_end
-__atomic_end:
diff --git a/arch/sparc/lib/atomic_64.S b/arch/sparc/lib/atomic_64.S
index 59186e0fcf39..4d502da3de78 100644
--- a/arch/sparc/lib/atomic_64.S
+++ b/arch/sparc/lib/atomic_64.S
@@ -3,6 +3,7 @@
* Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
*/
+#include <linux/linkage.h>
#include <asm/asi.h>
#include <asm/backoff.h>
@@ -13,9 +14,7 @@
* memory barriers, and a second which returns
* a value and does the barriers.
*/
- .globl atomic_add
- .type atomic_add,#function
-atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
+ENTRY(atomic_add) /* %o0 = increment, %o1 = atomic_ptr */
BACKOFF_SETUP(%o2)
1: lduw [%o1], %g1
add %g1, %o0, %g7
@@ -26,11 +25,9 @@ atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
retl
nop
2: BACKOFF_SPIN(%o2, %o3, 1b)
- .size atomic_add, .-atomic_add
+ENDPROC(atomic_add)
- .globl atomic_sub
- .type atomic_sub,#function
-atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
+ENTRY(atomic_sub) /* %o0 = decrement, %o1 = atomic_ptr */
BACKOFF_SETUP(%o2)
1: lduw [%o1], %g1
sub %g1, %o0, %g7
@@ -41,11 +38,9 @@ atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
retl
nop
2: BACKOFF_SPIN(%o2, %o3, 1b)
- .size atomic_sub, .-atomic_sub
+ENDPROC(atomic_sub)
- .globl atomic_add_ret
- .type atomic_add_ret,#function
-atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
+ENTRY(atomic_add_ret) /* %o0 = increment, %o1 = atomic_ptr */
BACKOFF_SETUP(%o2)
1: lduw [%o1], %g1
add %g1, %o0, %g7
@@ -56,11 +51,9 @@ atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
retl
sra %g1, 0, %o0
2: BACKOFF_SPIN(%o2, %o3, 1b)
- .size atomic_add_ret, .-atomic_add_ret
+ENDPROC(atomic_add_ret)
- .globl atomic_sub_ret
- .type atomic_sub_ret,#function
-atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
+ENTRY(atomic_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */
BACKOFF_SETUP(%o2)
1: lduw [%o1], %g1
sub %g1, %o0, %g7
@@ -71,11 +64,9 @@ atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
retl
sra %g1, 0, %o0
2: BACKOFF_SPIN(%o2, %o3, 1b)
- .size atomic_sub_ret, .-atomic_sub_ret
+ENDPROC(atomic_sub_ret)
- .globl atomic64_add
- .type atomic64_add,#function
-atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
+ENTRY(atomic64_add) /* %o0 = increment, %o1 = atomic_ptr */
BACKOFF_SETUP(%o2)
1: ldx [%o1], %g1
add %g1, %o0, %g7
@@ -86,11 +77,9 @@ atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
retl
nop
2: BACKOFF_SPIN(%o2, %o3, 1b)
- .size atomic64_add, .-atomic64_add
+ENDPROC(atomic64_add)
- .globl atomic64_sub
- .type atomic64_sub,#function
-atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */
+ENTRY(atomic64_sub) /* %o0 = decrement, %o1 = atomic_ptr */
BACKOFF_SETUP(%o2)
1: ldx [%o1], %g1
sub %g1, %o0, %g7
@@ -101,11 +90,9 @@ atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */
retl
nop
2: BACKOFF_SPIN(%o2, %o3, 1b)
- .size atomic64_sub, .-atomic64_sub
+ENDPROC(atomic64_sub)
- .globl atomic64_add_ret
- .type atomic64_add_ret,#function
-atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
+ENTRY(atomic64_add_ret) /* %o0 = increment, %o1 = atomic_ptr */
BACKOFF_SETUP(%o2)
1: ldx [%o1], %g1
add %g1, %o0, %g7
@@ -116,11 +103,9 @@ atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
retl
add %g1, %o0, %o0
2: BACKOFF_SPIN(%o2, %o3, 1b)
- .size atomic64_add_ret, .-atomic64_add_ret
+ENDPROC(atomic64_add_ret)
- .globl atomic64_sub_ret
- .type atomic64_sub_ret,#function
-atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
+ENTRY(atomic64_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */
BACKOFF_SETUP(%o2)
1: ldx [%o1], %g1
sub %g1, %o0, %g7
@@ -131,4 +116,4 @@ atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
retl
sub %g1, %o0, %o0
2: BACKOFF_SPIN(%o2, %o3, 1b)
- .size atomic64_sub_ret, .-atomic64_sub_ret
+ENDPROC(atomic64_sub_ret)
diff --git a/arch/sparc/lib/bitops.S b/arch/sparc/lib/bitops.S
index 3dc61d5537c0..36f72cc0e67e 100644
--- a/arch/sparc/lib/bitops.S
+++ b/arch/sparc/lib/bitops.S
@@ -3,14 +3,13 @@
* Copyright (C) 2000, 2007 David S. Miller (davem@davemloft.net)
*/
+#include <linux/linkage.h>
#include <asm/asi.h>
#include <asm/backoff.h>
.text
- .globl test_and_set_bit
- .type test_and_set_bit,#function
-test_and_set_bit: /* %o0=nr, %o1=addr */
+ENTRY(test_and_set_bit) /* %o0=nr, %o1=addr */
BACKOFF_SETUP(%o3)
srlx %o0, 6, %g1
mov 1, %o2
@@ -29,11 +28,9 @@ test_and_set_bit: /* %o0=nr, %o1=addr */
retl
nop
2: BACKOFF_SPIN(%o3, %o4, 1b)
- .size test_and_set_bit, .-test_and_set_bit
+ENDPROC(test_and_set_bit)
- .globl test_and_clear_bit
- .type test_and_clear_bit,#function
-test_and_clear_bit: /* %o0=nr, %o1=addr */
+ENTRY(test_and_clear_bit) /* %o0=nr, %o1=addr */
BACKOFF_SETUP(%o3)
srlx %o0, 6, %g1
mov 1, %o2
@@ -52,11 +49,9 @@ test_and_clear_bit: /* %o0=nr, %o1=addr */
retl
nop
2: BACKOFF_SPIN(%o3, %o4, 1b)
- .size test_and_clear_bit, .-test_and_clear_bit
+ENDPROC(test_and_clear_bit)
- .globl test_and_change_bit
- .type test_and_change_bit,#function
-test_and_change_bit: /* %o0=nr, %o1=addr */
+ENTRY(test_and_change_bit) /* %o0=nr, %o1=addr */
BACKOFF_SETUP(%o3)
srlx %o0, 6, %g1
mov 1, %o2
@@ -75,11 +70,9 @@ test_and_change_bit: /* %o0=nr, %o1=addr */
retl
nop
2: BACKOFF_SPIN(%o3, %o4, 1b)
- .size test_and_change_bit, .-test_and_change_bit
+ENDPROC(test_and_change_bit)
- .globl set_bit
- .type set_bit,#function
-set_bit: /* %o0=nr, %o1=addr */
+ENTRY(set_bit) /* %o0=nr, %o1=addr */
BACKOFF_SETUP(%o3)
srlx %o0, 6, %g1
mov 1, %o2
@@ -96,11 +89,9 @@ set_bit: /* %o0=nr, %o1=addr */
retl
nop
2: BACKOFF_SPIN(%o3, %o4, 1b)
- .size set_bit, .-set_bit
+ENDPROC(set_bit)
- .globl clear_bit
- .type clear_bit,#function
-clear_bit: /* %o0=nr, %o1=addr */
+ENTRY(clear_bit) /* %o0=nr, %o1=addr */
BACKOFF_SETUP(%o3)
srlx %o0, 6, %g1
mov 1, %o2
@@ -117,11 +108,9 @@ clear_bit: /* %o0=nr, %o1=addr */
retl
nop
2: BACKOFF_SPIN(%o3, %o4, 1b)
- .size clear_bit, .-clear_bit
+ENDPROC(clear_bit)
- .globl change_bit
- .type change_bit,#function
-change_bit: /* %o0=nr, %o1=addr */
+ENTRY(change_bit) /* %o0=nr, %o1=addr */
BACKOFF_SETUP(%o3)
srlx %o0, 6, %g1
mov 1, %o2
@@ -138,4 +127,4 @@ change_bit: /* %o0=nr, %o1=addr */
retl
nop
2: BACKOFF_SPIN(%o3, %o4, 1b)
- .size change_bit, .-change_bit
+ENDPROC(change_bit)
diff --git a/arch/sparc/lib/blockops.S b/arch/sparc/lib/blockops.S
index 804be87f9a42..3c771011ff4b 100644
--- a/arch/sparc/lib/blockops.S
+++ b/arch/sparc/lib/blockops.S
@@ -4,6 +4,7 @@
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/linkage.h>
#include <asm/page.h>
/* Zero out 64 bytes of memory at (buf + offset).
@@ -44,10 +45,7 @@
*/
.text
- .align 4
- .globl bzero_1page, __copy_1page
-
-bzero_1page:
+ENTRY(bzero_1page)
/* NOTE: If you change the number of insns of this routine, please check
* arch/sparc/mm/hypersparc.S */
/* %o0 = buf */
@@ -65,8 +63,9 @@ bzero_1page:
retl
nop
+ENDPROC(bzero_1page)
-__copy_1page:
+ENTRY(__copy_1page)
/* NOTE: If you change the number of insns of this routine, please check
* arch/sparc/mm/hypersparc.S */
/* %o0 = dst, %o1 = src */
@@ -87,3 +86,4 @@ __copy_1page:
retl
nop
+ENDPROC(__copy_1page)
diff --git a/arch/sparc/lib/bzero.S b/arch/sparc/lib/bzero.S
index 615f401edf69..8c058114b649 100644
--- a/arch/sparc/lib/bzero.S
+++ b/arch/sparc/lib/bzero.S
@@ -4,11 +4,11 @@
* Copyright (C) 2005 David S. Miller <davem@davemloft.net>
*/
+#include <linux/linkage.h>
+
.text
- .globl memset
- .type memset, #function
-memset: /* %o0=buf, %o1=pat, %o2=len */
+ENTRY(memset) /* %o0=buf, %o1=pat, %o2=len */
and %o1, 0xff, %o3
mov %o2, %o1
sllx %o3, 8, %g1
@@ -19,9 +19,7 @@ memset: /* %o0=buf, %o1=pat, %o2=len */
ba,pt %xcc, 1f
or %g1, %o2, %o2
- .globl __bzero
- .type __bzero, #function
-__bzero: /* %o0=buf, %o1=len */
+ENTRY(__bzero) /* %o0=buf, %o1=len */
clr %o2
1: mov %o0, %o3
brz,pn %o1, __bzero_done
@@ -78,8 +76,8 @@ __bzero_tiny:
__bzero_done:
retl
mov %o3, %o0
- .size __bzero, .-__bzero
- .size memset, .-memset
+ENDPROC(__bzero)
+ENDPROC(memset)
#define EX_ST(x,y) \
98: x,y; \
@@ -89,9 +87,7 @@ __bzero_done:
.text; \
.align 4;
- .globl __clear_user
- .type __clear_user, #function
-__clear_user: /* %o0=buf, %o1=len */
+ENTRY(__clear_user) /* %o0=buf, %o1=len */
brz,pn %o1, __clear_user_done
cmp %o1, 16
bl,pn %icc, __clear_user_tiny
@@ -146,4 +142,4 @@ __clear_user_tiny:
__clear_user_done:
retl
clr %o0
- .size __clear_user, .-__clear_user
+ENDPROC(__clear_user)
diff --git a/arch/sparc/lib/divdi3.S b/arch/sparc/lib/divdi3.S
index d74bc0925f2d..9614b48b6ef8 100644
--- a/arch/sparc/lib/divdi3.S
+++ b/arch/sparc/lib/divdi3.S
@@ -19,7 +19,6 @@ Boston, MA 02111-1307, USA. */
.text
.align 4
- .global .udiv
.globl __divdi3
__divdi3:
save %sp,-104,%sp
@@ -83,8 +82,9 @@ __divdi3:
bne .LL85
mov %i0,%o2
mov 1,%o0
- call .udiv,0
mov 0,%o1
+ wr %g0, 0, %y
+ udiv %o0, %o1, %o0
mov %o0,%o4
mov %i0,%o2
.LL85:
diff --git a/arch/sparc/lib/ipcsum.S b/arch/sparc/lib/ipcsum.S
index 58ca5b9a8778..4742d59029ee 100644
--- a/arch/sparc/lib/ipcsum.S
+++ b/arch/sparc/lib/ipcsum.S
@@ -1,8 +1,7 @@
+#include <linux/linkage.h>
+
.text
- .align 32
- .globl ip_fast_csum
- .type ip_fast_csum,#function
-ip_fast_csum: /* %o0 = iph, %o1 = ihl */
+ENTRY(ip_fast_csum) /* %o0 = iph, %o1 = ihl */
sub %o1, 4, %g7
lduw [%o0 + 0x00], %o2
lduw [%o0 + 0x04], %g2
@@ -31,4 +30,4 @@ ip_fast_csum: /* %o0 = iph, %o1 = ihl */
set 0xffff, %o1
retl
and %o2, %o1, %o0
- .size ip_fast_csum, .-ip_fast_csum
+ENDPROC(ip_fast_csum)
diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c
index f73c2240fe60..2dc30875c8bc 100644
--- a/arch/sparc/lib/ksyms.c
+++ b/arch/sparc/lib/ksyms.c
@@ -56,23 +56,11 @@ extern int __divdi3(int, int);
extern void (*__copy_1page)(void *, const void *);
extern void (*bzero_1page)(void *);
-extern int __strncmp(const char *, const char *, __kernel_size_t);
-
extern void ___rw_read_enter(void);
extern void ___rw_read_try(void);
extern void ___rw_read_exit(void);
extern void ___rw_write_enter(void);
-/* Alias functions whose names begin with "." and export the aliases.
- * The module references will be fixed up by module_frob_arch_sections.
- */
-extern int _Div(int, int);
-extern int _Mul(int, int);
-extern int _Rem(int, int);
-extern unsigned _Udiv(unsigned, unsigned);
-extern unsigned _Umul(unsigned, unsigned);
-extern unsigned _Urem(unsigned, unsigned);
-
/* Networking helper routines. */
EXPORT_SYMBOL(__csum_partial_copy_sparc_generic);
@@ -81,9 +69,6 @@ EXPORT_SYMBOL(__copy_1page);
EXPORT_SYMBOL(__memmove);
EXPORT_SYMBOL(bzero_1page);
-/* string functions */
-EXPORT_SYMBOL(__strncmp);
-
/* Moving data to/from/in userspace. */
EXPORT_SYMBOL(__copy_user);
@@ -100,13 +85,6 @@ EXPORT_SYMBOL(__ashldi3);
EXPORT_SYMBOL(__lshrdi3);
EXPORT_SYMBOL(__muldi3);
EXPORT_SYMBOL(__divdi3);
-
-EXPORT_SYMBOL(_Rem);
-EXPORT_SYMBOL(_Urem);
-EXPORT_SYMBOL(_Mul);
-EXPORT_SYMBOL(_Umul);
-EXPORT_SYMBOL(_Div);
-EXPORT_SYMBOL(_Udiv);
#endif
/*
diff --git a/arch/sparc/lib/lshrdi3.S b/arch/sparc/lib/lshrdi3.S
index 47a1354c1602..60ebc7cdbee0 100644
--- a/arch/sparc/lib/lshrdi3.S
+++ b/arch/sparc/lib/lshrdi3.S
@@ -1,6 +1,6 @@
+#include <linux/linkage.h>
- .globl __lshrdi3
-__lshrdi3:
+ENTRY(__lshrdi3)
cmp %o2, 0
be 3f
mov 0x20, %g2
@@ -24,3 +24,4 @@ __lshrdi3:
3:
retl
nop
+ENDPROC(__lshrdi3)
diff --git a/arch/sparc/lib/memmove.S b/arch/sparc/lib/memmove.S
index 97395802c23c..b7f6334e159f 100644
--- a/arch/sparc/lib/memmove.S
+++ b/arch/sparc/lib/memmove.S
@@ -4,11 +4,10 @@
* Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz)
*/
+#include <linux/linkage.h>
+
.text
- .align 32
- .globl memmove
- .type memmove,#function
-memmove: /* o0=dst o1=src o2=len */
+ENTRY(memmove) /* o0=dst o1=src o2=len */
mov %o0, %g1
cmp %o0, %o1
bleu,pt %xcc, memcpy
@@ -28,4 +27,4 @@ memmove: /* o0=dst o1=src o2=len */
retl
mov %g1, %o0
- .size memmove, .-memmove
+ENDPROC(memmove)
diff --git a/arch/sparc/lib/mul.S b/arch/sparc/lib/mul.S
deleted file mode 100644
index c45470d0b0ce..000000000000
--- a/arch/sparc/lib/mul.S
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * mul.S: This routine was taken from glibc-1.09 and is covered
- * by the GNU Library General Public License Version 2.
- */
-
-/*
- * Signed multiply, from Appendix E of the Sparc Version 8
- * Architecture Manual.
- */
-
-/*
- * Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the upper 32 bits of
- * the 64-bit product).
- *
- * This code optimizes short (less than 13-bit) multiplies.
- */
-
- .globl .mul
- .globl _Mul
-.mul:
-_Mul: /* needed for export */
- mov %o0, %y ! multiplier -> Y
- andncc %o0, 0xfff, %g0 ! test bits 12..31
- be Lmul_shortway ! if zero, can do it the short way
- andcc %g0, %g0, %o4 ! zero the partial product and clear N and V
-
- /*
- * Long multiply. 32 steps, followed by a final shift step.
- */
- mulscc %o4, %o1, %o4 ! 1
- mulscc %o4, %o1, %o4 ! 2
- mulscc %o4, %o1, %o4 ! 3
- mulscc %o4, %o1, %o4 ! 4
- mulscc %o4, %o1, %o4 ! 5
- mulscc %o4, %o1, %o4 ! 6
- mulscc %o4, %o1, %o4 ! 7
- mulscc %o4, %o1, %o4 ! 8
- mulscc %o4, %o1, %o4 ! 9
- mulscc %o4, %o1, %o4 ! 10
- mulscc %o4, %o1, %o4 ! 11
- mulscc %o4, %o1, %o4 ! 12
- mulscc %o4, %o1, %o4 ! 13
- mulscc %o4, %o1, %o4 ! 14
- mulscc %o4, %o1, %o4 ! 15
- mulscc %o4, %o1, %o4 ! 16
- mulscc %o4, %o1, %o4 ! 17
- mulscc %o4, %o1, %o4 ! 18
- mulscc %o4, %o1, %o4 ! 19
- mulscc %o4, %o1, %o4 ! 20
- mulscc %o4, %o1, %o4 ! 21
- mulscc %o4, %o1, %o4 ! 22
- mulscc %o4, %o1, %o4 ! 23
- mulscc %o4, %o1, %o4 ! 24
- mulscc %o4, %o1, %o4 ! 25
- mulscc %o4, %o1, %o4 ! 26
- mulscc %o4, %o1, %o4 ! 27
- mulscc %o4, %o1, %o4 ! 28
- mulscc %o4, %o1, %o4 ! 29
- mulscc %o4, %o1, %o4 ! 30
- mulscc %o4, %o1, %o4 ! 31
- mulscc %o4, %o1, %o4 ! 32
- mulscc %o4, %g0, %o4 ! final shift
-
- ! If %o0 was negative, the result is
- ! (%o0 * %o1) + (%o1 << 32))
- ! We fix that here.
-
-#if 0
- tst %o0
- bge 1f
- rd %y, %o0
-
- ! %o0 was indeed negative; fix upper 32 bits of result by subtracting
- ! %o1 (i.e., return %o4 - %o1 in %o1).
- retl
- sub %o4, %o1, %o1
-
-1:
- retl
- mov %o4, %o1
-#else
- /* Faster code adapted from tege@sics.se's code for umul.S. */
- sra %o0, 31, %o2 ! make mask from sign bit
- and %o1, %o2, %o2 ! %o2 = 0 or %o1, depending on sign of %o0
- rd %y, %o0 ! get lower half of product
- retl
- sub %o4, %o2, %o1 ! subtract compensation
- ! and put upper half in place
-#endif
-
-Lmul_shortway:
- /*
- * Short multiply. 12 steps, followed by a final shift step.
- * The resulting bits are off by 12 and (32-12) = 20 bit positions,
- * but there is no problem with %o0 being negative (unlike above).
- */
- mulscc %o4, %o1, %o4 ! 1
- mulscc %o4, %o1, %o4 ! 2
- mulscc %o4, %o1, %o4 ! 3
- mulscc %o4, %o1, %o4 ! 4
- mulscc %o4, %o1, %o4 ! 5
- mulscc %o4, %o1, %o4 ! 6
- mulscc %o4, %o1, %o4 ! 7
- mulscc %o4, %o1, %o4 ! 8
- mulscc %o4, %o1, %o4 ! 9
- mulscc %o4, %o1, %o4 ! 10
- mulscc %o4, %o1, %o4 ! 11
- mulscc %o4, %o1, %o4 ! 12
- mulscc %o4, %g0, %o4 ! final shift
-
- /*
- * %o4 has 20 of the bits that should be in the low part of the
- * result; %y has the bottom 12 (as %y's top 12). That is:
- *
- * %o4 %y
- * +----------------+----------------+
- * | -12- | -20- | -12- | -20- |
- * +------(---------+------)---------+
- * --hi-- ----low-part----
- *
- * The upper 12 bits of %o4 should be sign-extended to form the
- * high part of the product (i.e., highpart = %o4 >> 20).
- */
-
- rd %y, %o5
- sll %o4, 12, %o0 ! shift middle bits left 12
- srl %o5, 20, %o5 ! shift low bits right 20, zero fill at left
- or %o5, %o0, %o0 ! construct low part of result
- retl
- sra %o4, 20, %o1 ! ... and extract high part of result
-
- .globl .mul_patch
-.mul_patch:
- smul %o0, %o1, %o0
- retl
- rd %y, %o1
- nop
diff --git a/arch/sparc/lib/muldi3.S b/arch/sparc/lib/muldi3.S
index 7f17872d0603..9794939d1c12 100644
--- a/arch/sparc/lib/muldi3.S
+++ b/arch/sparc/lib/muldi3.S
@@ -63,12 +63,12 @@ __muldi3:
rd %y, %o1
mov %o1, %l3
mov %i1, %o0
- call .umul
mov %i2, %o1
+ umul %o0, %o1, %o0
mov %o0, %l0
mov %i0, %o0
- call .umul
mov %i3, %o1
+ umul %o0, %o1, %o0
add %l0, %o0, %l0
mov %l2, %i0
add %l2, %l0, %i0
diff --git a/arch/sparc/lib/rem.S b/arch/sparc/lib/rem.S
deleted file mode 100644
index 42fb86252815..000000000000
--- a/arch/sparc/lib/rem.S
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * rem.S: This routine was taken from glibc-1.09 and is covered
- * by the GNU Library General Public License Version 2.
- */
-
-
-/* This file is generated from divrem.m4; DO NOT EDIT! */
-/*
- * Division and remainder, from Appendix E of the Sparc Version 8
- * Architecture Manual, with fixes from Gordon Irlam.
- */
-
-/*
- * Input: dividend and divisor in %o0 and %o1 respectively.
- *
- * m4 parameters:
- * .rem name of function to generate
- * rem rem=div => %o0 / %o1; rem=rem => %o0 % %o1
- * true true=true => signed; true=false => unsigned
- *
- * Algorithm parameters:
- * N how many bits per iteration we try to get (4)
- * WORDSIZE total number of bits (32)
- *
- * Derived constants:
- * TOPBITS number of bits in the top decade of a number
- *
- * Important variables:
- * Q the partial quotient under development (initially 0)
- * R the remainder so far, initially the dividend
- * ITER number of main division loop iterations required;
- * equal to ceil(log2(quotient) / N). Note that this
- * is the log base (2^N) of the quotient.
- * V the current comparand, initially divisor*2^(ITER*N-1)
- *
- * Cost:
- * Current estimate for non-large dividend is
- * ceil(log2(quotient) / N) * (10 + 7N/2) + C
- * A large dividend is one greater than 2^(31-TOPBITS) and takes a
- * different path, as the upper bits of the quotient must be developed
- * one bit at a time.
- */
-
-
- .globl .rem
- .globl _Rem
-.rem:
-_Rem: /* needed for export */
- ! compute sign of result; if neither is negative, no problem
- orcc %o1, %o0, %g0 ! either negative?
- bge 2f ! no, go do the divide
- mov %o0, %g2 ! compute sign in any case
-
- tst %o1
- bge 1f
- tst %o0
- ! %o1 is definitely negative; %o0 might also be negative
- bge 2f ! if %o0 not negative...
- sub %g0, %o1, %o1 ! in any case, make %o1 nonneg
-1: ! %o0 is negative, %o1 is nonnegative
- sub %g0, %o0, %o0 ! make %o0 nonnegative
-2:
-
- ! Ready to divide. Compute size of quotient; scale comparand.
- orcc %o1, %g0, %o5
- bne 1f
- mov %o0, %o3
-
- ! Divide by zero trap. If it returns, return 0 (about as
- ! wrong as possible, but that is what SunOS does...).
- ta ST_DIV0
- retl
- clr %o0
-
-1:
- cmp %o3, %o5 ! if %o1 exceeds %o0, done
- blu Lgot_result ! (and algorithm fails otherwise)
- clr %o2
-
- sethi %hi(1 << (32 - 4 - 1)), %g1
-
- cmp %o3, %g1
- blu Lnot_really_big
- clr %o4
-
- ! Here the dividend is >= 2**(31-N) or so. We must be careful here,
- ! as our usual N-at-a-shot divide step will cause overflow and havoc.
- ! The number of bits in the result here is N*ITER+SC, where SC <= N.
- ! Compute ITER in an unorthodox manner: know we need to shift V into
- ! the top decade: so do not even bother to compare to R.
- 1:
- cmp %o5, %g1
- bgeu 3f
- mov 1, %g7
-
- sll %o5, 4, %o5
-
- b 1b
- add %o4, 1, %o4
-
- ! Now compute %g7.
- 2:
- addcc %o5, %o5, %o5
-
- bcc Lnot_too_big
- add %g7, 1, %g7
-
- ! We get here if the %o1 overflowed while shifting.
- ! This means that %o3 has the high-order bit set.
- ! Restore %o5 and subtract from %o3.
- sll %g1, 4, %g1 ! high order bit
- srl %o5, 1, %o5 ! rest of %o5
- add %o5, %g1, %o5
-
- b Ldo_single_div
- sub %g7, 1, %g7
-
- Lnot_too_big:
- 3:
- cmp %o5, %o3
- blu 2b
- nop
-
- be Ldo_single_div
- nop
- /* NB: these are commented out in the V8-Sparc manual as well */
- /* (I do not understand this) */
- ! %o5 > %o3: went too far: back up 1 step
- ! srl %o5, 1, %o5
- ! dec %g7
- ! do single-bit divide steps
- !
- ! We have to be careful here. We know that %o3 >= %o5, so we can do the
- ! first divide step without thinking. BUT, the others are conditional,
- ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high-
- ! order bit set in the first step, just falling into the regular
- ! division loop will mess up the first time around.
- ! So we unroll slightly...
- Ldo_single_div:
- subcc %g7, 1, %g7
- bl Lend_regular_divide
- nop
-
- sub %o3, %o5, %o3
- mov 1, %o2
-
- b Lend_single_divloop
- nop
- Lsingle_divloop:
- sll %o2, 1, %o2
-
- bl 1f
- srl %o5, 1, %o5
- ! %o3 >= 0
- sub %o3, %o5, %o3
-
- b 2f
- add %o2, 1, %o2
- 1: ! %o3 < 0
- add %o3, %o5, %o3
- sub %o2, 1, %o2
- 2:
- Lend_single_divloop:
- subcc %g7, 1, %g7
- bge Lsingle_divloop
- tst %o3
-
- b,a Lend_regular_divide
-
-Lnot_really_big:
-1:
- sll %o5, 4, %o5
- cmp %o5, %o3
- bleu 1b
- addcc %o4, 1, %o4
- be Lgot_result
- sub %o4, 1, %o4
-
- tst %o3 ! set up for initial iteration
-Ldivloop:
- sll %o2, 4, %o2
- ! depth 1, accumulated bits 0
- bl L.1.16
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 2, accumulated bits 1
- bl L.2.17
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 3, accumulated bits 3
- bl L.3.19
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits 7
- bl L.4.23
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
-
- b 9f
- add %o2, (7*2+1), %o2
-
-L.4.23:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (7*2-1), %o2
-
-L.3.19:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits 5
- bl L.4.21
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (5*2+1), %o2
-
-L.4.21:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (5*2-1), %o2
-
-L.2.17:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 3, accumulated bits 1
- bl L.3.17
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits 3
- bl L.4.19
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (3*2+1), %o2
-
-L.4.19:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (3*2-1), %o2
-
-L.3.17:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits 1
- bl L.4.17
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (1*2+1), %o2
-
-L.4.17:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (1*2-1), %o2
-
-L.1.16:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 2, accumulated bits -1
- bl L.2.15
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 3, accumulated bits -1
- bl L.3.15
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits -1
- bl L.4.15
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-1*2+1), %o2
-
-L.4.15:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-1*2-1), %o2
-
-L.3.15:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits -3
- bl L.4.13
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-3*2+1), %o2
-
-L.4.13:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-3*2-1), %o2
-
-L.2.15:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 3, accumulated bits -3
- bl L.3.13
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits -5
- bl L.4.11
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-5*2+1), %o2
-
-L.4.11:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-5*2-1), %o2
-
-
-L.3.13:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits -7
- bl L.4.9
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-7*2+1), %o2
-
-L.4.9:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-7*2-1), %o2
-
- 9:
-Lend_regular_divide:
- subcc %o4, 1, %o4
- bge Ldivloop
- tst %o3
-
- bl,a Lgot_result
- ! non-restoring fixup here (one instruction only!)
- add %o3, %o1, %o3
-
-Lgot_result:
- ! check to see if answer should be < 0
- tst %g2
- bl,a 1f
- sub %g0, %o3, %o3
-1:
- retl
- mov %o3, %o0
-
- .globl .rem_patch
-.rem_patch:
- sra %o0, 0x1f, %o4
- wr %o4, 0x0, %y
- nop
- nop
- nop
- sdivcc %o0, %o1, %o2
- bvs,a 1f
- xnor %o2, %g0, %o2
-1: smul %o2, %o1, %o2
- retl
- sub %o0, %o2, %o0
- nop
diff --git a/arch/sparc/lib/sdiv.S b/arch/sparc/lib/sdiv.S
deleted file mode 100644
index f0a0d4e4db78..000000000000
--- a/arch/sparc/lib/sdiv.S
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * sdiv.S: This routine was taken from glibc-1.09 and is covered
- * by the GNU Library General Public License Version 2.
- */
-
-
-/* This file is generated from divrem.m4; DO NOT EDIT! */
-/*
- * Division and remainder, from Appendix E of the Sparc Version 8
- * Architecture Manual, with fixes from Gordon Irlam.
- */
-
-/*
- * Input: dividend and divisor in %o0 and %o1 respectively.
- *
- * m4 parameters:
- * .div name of function to generate
- * div div=div => %o0 / %o1; div=rem => %o0 % %o1
- * true true=true => signed; true=false => unsigned
- *
- * Algorithm parameters:
- * N how many bits per iteration we try to get (4)
- * WORDSIZE total number of bits (32)
- *
- * Derived constants:
- * TOPBITS number of bits in the top decade of a number
- *
- * Important variables:
- * Q the partial quotient under development (initially 0)
- * R the remainder so far, initially the dividend
- * ITER number of main division loop iterations required;
- * equal to ceil(log2(quotient) / N). Note that this
- * is the log base (2^N) of the quotient.
- * V the current comparand, initially divisor*2^(ITER*N-1)
- *
- * Cost:
- * Current estimate for non-large dividend is
- * ceil(log2(quotient) / N) * (10 + 7N/2) + C
- * A large dividend is one greater than 2^(31-TOPBITS) and takes a
- * different path, as the upper bits of the quotient must be developed
- * one bit at a time.
- */
-
-
- .globl .div
- .globl _Div
-.div:
-_Div: /* needed for export */
- ! compute sign of result; if neither is negative, no problem
- orcc %o1, %o0, %g0 ! either negative?
- bge 2f ! no, go do the divide
- xor %o1, %o0, %g2 ! compute sign in any case
-
- tst %o1
- bge 1f
- tst %o0
- ! %o1 is definitely negative; %o0 might also be negative
- bge 2f ! if %o0 not negative...
- sub %g0, %o1, %o1 ! in any case, make %o1 nonneg
-1: ! %o0 is negative, %o1 is nonnegative
- sub %g0, %o0, %o0 ! make %o0 nonnegative
-2:
-
- ! Ready to divide. Compute size of quotient; scale comparand.
- orcc %o1, %g0, %o5
- bne 1f
- mov %o0, %o3
-
- ! Divide by zero trap. If it returns, return 0 (about as
- ! wrong as possible, but that is what SunOS does...).
- ta ST_DIV0
- retl
- clr %o0
-
-1:
- cmp %o3, %o5 ! if %o1 exceeds %o0, done
- blu Lgot_result ! (and algorithm fails otherwise)
- clr %o2
-
- sethi %hi(1 << (32 - 4 - 1)), %g1
-
- cmp %o3, %g1
- blu Lnot_really_big
- clr %o4
-
- ! Here the dividend is >= 2**(31-N) or so. We must be careful here,
- ! as our usual N-at-a-shot divide step will cause overflow and havoc.
- ! The number of bits in the result here is N*ITER+SC, where SC <= N.
- ! Compute ITER in an unorthodox manner: know we need to shift V into
- ! the top decade: so do not even bother to compare to R.
- 1:
- cmp %o5, %g1
- bgeu 3f
- mov 1, %g7
-
- sll %o5, 4, %o5
-
- b 1b
- add %o4, 1, %o4
-
- ! Now compute %g7.
- 2:
- addcc %o5, %o5, %o5
- bcc Lnot_too_big
- add %g7, 1, %g7
-
- ! We get here if the %o1 overflowed while shifting.
- ! This means that %o3 has the high-order bit set.
- ! Restore %o5 and subtract from %o3.
- sll %g1, 4, %g1 ! high order bit
- srl %o5, 1, %o5 ! rest of %o5
- add %o5, %g1, %o5
-
- b Ldo_single_div
- sub %g7, 1, %g7
-
- Lnot_too_big:
- 3:
- cmp %o5, %o3
- blu 2b
- nop
-
- be Ldo_single_div
- nop
- /* NB: these are commented out in the V8-Sparc manual as well */
- /* (I do not understand this) */
- ! %o5 > %o3: went too far: back up 1 step
- ! srl %o5, 1, %o5
- ! dec %g7
- ! do single-bit divide steps
- !
- ! We have to be careful here. We know that %o3 >= %o5, so we can do the
- ! first divide step without thinking. BUT, the others are conditional,
- ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high-
- ! order bit set in the first step, just falling into the regular
- ! division loop will mess up the first time around.
- ! So we unroll slightly...
- Ldo_single_div:
- subcc %g7, 1, %g7
- bl Lend_regular_divide
- nop
-
- sub %o3, %o5, %o3
- mov 1, %o2
-
- b Lend_single_divloop
- nop
- Lsingle_divloop:
- sll %o2, 1, %o2
-
- bl 1f
- srl %o5, 1, %o5
- ! %o3 >= 0
- sub %o3, %o5, %o3
-
- b 2f
- add %o2, 1, %o2
- 1: ! %o3 < 0
- add %o3, %o5, %o3
- sub %o2, 1, %o2
- 2:
- Lend_single_divloop:
- subcc %g7, 1, %g7
- bge Lsingle_divloop
- tst %o3
-
- b,a Lend_regular_divide
-
-Lnot_really_big:
-1:
- sll %o5, 4, %o5
- cmp %o5, %o3
- bleu 1b
- addcc %o4, 1, %o4
-
- be Lgot_result
- sub %o4, 1, %o4
-
- tst %o3 ! set up for initial iteration
-Ldivloop:
- sll %o2, 4, %o2
- ! depth 1, accumulated bits 0
- bl L.1.16
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 2, accumulated bits 1
- bl L.2.17
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 3, accumulated bits 3
- bl L.3.19
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits 7
- bl L.4.23
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (7*2+1), %o2
-
-L.4.23:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (7*2-1), %o2
-
-L.3.19:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits 5
- bl L.4.21
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (5*2+1), %o2
-
-L.4.21:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (5*2-1), %o2
-
-L.2.17:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 3, accumulated bits 1
- bl L.3.17
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits 3
- bl L.4.19
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (3*2+1), %o2
-
-L.4.19:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (3*2-1), %o2
-
-
-L.3.17:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits 1
- bl L.4.17
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (1*2+1), %o2
-
-L.4.17:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (1*2-1), %o2
-
-L.1.16:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 2, accumulated bits -1
- bl L.2.15
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 3, accumulated bits -1
- bl L.3.15
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits -1
- bl L.4.15
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-1*2+1), %o2
-
-L.4.15:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-1*2-1), %o2
-
-L.3.15:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits -3
- bl L.4.13
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-3*2+1), %o2
-
-L.4.13:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-3*2-1), %o2
-
-L.2.15:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 3, accumulated bits -3
- bl L.3.13
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits -5
- bl L.4.11
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-5*2+1), %o2
-
-L.4.11:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-5*2-1), %o2
-
-L.3.13:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits -7
- bl L.4.9
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-7*2+1), %o2
-
-L.4.9:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-7*2-1), %o2
-
- 9:
-Lend_regular_divide:
- subcc %o4, 1, %o4
- bge Ldivloop
- tst %o3
-
- bl,a Lgot_result
- ! non-restoring fixup here (one instruction only!)
- sub %o2, 1, %o2
-
-Lgot_result:
- ! check to see if answer should be < 0
- tst %g2
- bl,a 1f
- sub %g0, %o2, %o2
-1:
- retl
- mov %o2, %o0
-
- .globl .div_patch
-.div_patch:
- sra %o0, 0x1f, %o2
- wr %o2, 0x0, %y
- nop
- nop
- nop
- sdivcc %o0, %o1, %o0
- bvs,a 1f
- xnor %o0, %g0, %o0
-1: retl
- nop
diff --git a/arch/sparc/lib/strlen_user_64.S b/arch/sparc/lib/strlen_user_64.S
index 114ed111e251..c3df71fa4928 100644
--- a/arch/sparc/lib/strlen_user_64.S
+++ b/arch/sparc/lib/strlen_user_64.S
@@ -8,16 +8,16 @@
* Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
+#include <linux/linkage.h>
#include <asm/asi.h>
#define LO_MAGIC 0x01010101
#define HI_MAGIC 0x80808080
.align 4
- .global __strlen_user, __strnlen_user
-__strlen_user:
+ENTRY(__strlen_user)
sethi %hi(32768), %o1
-__strnlen_user:
+ENTRY(__strnlen_user)
mov %o1, %g1
mov %o0, %o1
andcc %o0, 3, %g0
@@ -78,6 +78,8 @@ __strnlen_user:
mov 2, %o0
23: retl
mov 3, %o0
+ENDPROC(__strlen_user)
+ENDPROC(__strnlen_user)
.section .fixup,#alloc,#execinstr
.align 4
diff --git a/arch/sparc/lib/strncmp_32.S b/arch/sparc/lib/strncmp_32.S
index 494ec664537a..c0d1b568c1c5 100644
--- a/arch/sparc/lib/strncmp_32.S
+++ b/arch/sparc/lib/strncmp_32.S
@@ -3,11 +3,10 @@
* generic strncmp routine.
*/
+#include <linux/linkage.h>
+
.text
- .align 4
- .global __strncmp, strncmp
-__strncmp:
-strncmp:
+ENTRY(strncmp)
mov %o0, %g3
mov 0, %o3
@@ -116,3 +115,4 @@ strncmp:
and %g2, 0xff, %o0
retl
sub %o3, %o0, %o0
+ENDPROC(strncmp)
diff --git a/arch/sparc/lib/strncmp_64.S b/arch/sparc/lib/strncmp_64.S
index 980e83751556..0656627166f3 100644
--- a/arch/sparc/lib/strncmp_64.S
+++ b/arch/sparc/lib/strncmp_64.S
@@ -4,13 +4,11 @@
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
+#include <linux/linkage.h>
#include <asm/asi.h>
.text
- .align 32
- .globl strncmp
- .type strncmp,#function
-strncmp:
+ENTRY(strncmp)
brlez,pn %o2, 3f
lduba [%o0] (ASI_PNF), %o3
1:
@@ -29,4 +27,4 @@ strncmp:
3:
retl
clr %o0
- .size strncmp, .-strncmp
+ENDPROC(strncmp)
diff --git a/arch/sparc/lib/strncpy_from_user_32.S b/arch/sparc/lib/strncpy_from_user_32.S
index d77198976a66..db0ed2964bdb 100644
--- a/arch/sparc/lib/strncpy_from_user_32.S
+++ b/arch/sparc/lib/strncpy_from_user_32.S
@@ -3,11 +3,11 @@
* Copyright(C) 1996 David S. Miller
*/
+#include <linux/linkage.h>
#include <asm/ptrace.h>
#include <asm/errno.h>
.text
- .align 4
/* Must return:
*
@@ -16,8 +16,7 @@
* bytes copied if we hit a null byte
*/
- .globl __strncpy_from_user
-__strncpy_from_user:
+ENTRY(__strncpy_from_user)
/* %o0=dest, %o1=src, %o2=count */
mov %o2, %o3
1:
@@ -35,6 +34,7 @@ __strncpy_from_user:
add %o2, 1, %o0
retl
sub %o3, %o0, %o0
+ENDPROC(__strncpy_from_user)
.section .fixup,#alloc,#execinstr
.align 4
diff --git a/arch/sparc/lib/strncpy_from_user_64.S b/arch/sparc/lib/strncpy_from_user_64.S
index 511c8f136f95..d1246b713077 100644
--- a/arch/sparc/lib/strncpy_from_user_64.S
+++ b/arch/sparc/lib/strncpy_from_user_64.S
@@ -4,6 +4,7 @@
* Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
*/
+#include <linux/linkage.h>
#include <asm/asi.h>
#include <asm/errno.h>
@@ -12,7 +13,6 @@
0: .xword 0x0101010101010101
.text
- .align 32
/* Must return:
*
@@ -30,9 +30,7 @@
* and average length is 18 or so.
*/
- .globl __strncpy_from_user
- .type __strncpy_from_user,#function
-__strncpy_from_user:
+ENTRY(__strncpy_from_user)
/* %o0=dest, %o1=src, %o2=count */
andcc %o1, 7, %g0 ! IEU1 Group
bne,pn %icc, 30f ! CTI
@@ -123,7 +121,7 @@ __strncpy_from_user:
mov %o2, %o0
2: retl
add %o2, %o3, %o0
- .size __strncpy_from_user, .-__strncpy_from_user
+ENDPROC(__strncpy_from_user)
.section __ex_table,"a"
.align 4
diff --git a/arch/sparc/lib/ucmpdi2.c b/arch/sparc/lib/ucmpdi2.c
new file mode 100644
index 000000000000..1e06ed500682
--- /dev/null
+++ b/arch/sparc/lib/ucmpdi2.c
@@ -0,0 +1,19 @@
+#include <linux/module.h>
+#include "libgcc.h"
+
+word_type __ucmpdi2(unsigned long long a, unsigned long long b)
+{
+ const DWunion au = {.ll = a};
+ const DWunion bu = {.ll = b};
+
+ if ((unsigned int) au.s.high < (unsigned int) bu.s.high)
+ return 0;
+ else if ((unsigned int) au.s.high > (unsigned int) bu.s.high)
+ return 2;
+ if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
+ return 0;
+ else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
+ return 2;
+ return 1;
+}
+EXPORT_SYMBOL(__ucmpdi2);
diff --git a/arch/sparc/lib/udiv.S b/arch/sparc/lib/udiv.S
deleted file mode 100644
index 2101405bdfcb..000000000000
--- a/arch/sparc/lib/udiv.S
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * udiv.S: This routine was taken from glibc-1.09 and is covered
- * by the GNU Library General Public License Version 2.
- */
-
-
-/* This file is generated from divrem.m4; DO NOT EDIT! */
-/*
- * Division and remainder, from Appendix E of the Sparc Version 8
- * Architecture Manual, with fixes from Gordon Irlam.
- */
-
-/*
- * Input: dividend and divisor in %o0 and %o1 respectively.
- *
- * m4 parameters:
- * .udiv name of function to generate
- * div div=div => %o0 / %o1; div=rem => %o0 % %o1
- * false false=true => signed; false=false => unsigned
- *
- * Algorithm parameters:
- * N how many bits per iteration we try to get (4)
- * WORDSIZE total number of bits (32)
- *
- * Derived constants:
- * TOPBITS number of bits in the top decade of a number
- *
- * Important variables:
- * Q the partial quotient under development (initially 0)
- * R the remainder so far, initially the dividend
- * ITER number of main division loop iterations required;
- * equal to ceil(log2(quotient) / N). Note that this
- * is the log base (2^N) of the quotient.
- * V the current comparand, initially divisor*2^(ITER*N-1)
- *
- * Cost:
- * Current estimate for non-large dividend is
- * ceil(log2(quotient) / N) * (10 + 7N/2) + C
- * A large dividend is one greater than 2^(31-TOPBITS) and takes a
- * different path, as the upper bits of the quotient must be developed
- * one bit at a time.
- */
-
-
- .globl .udiv
- .globl _Udiv
-.udiv:
-_Udiv: /* needed for export */
-
- ! Ready to divide. Compute size of quotient; scale comparand.
- orcc %o1, %g0, %o5
- bne 1f
- mov %o0, %o3
-
- ! Divide by zero trap. If it returns, return 0 (about as
- ! wrong as possible, but that is what SunOS does...).
- ta ST_DIV0
- retl
- clr %o0
-
-1:
- cmp %o3, %o5 ! if %o1 exceeds %o0, done
- blu Lgot_result ! (and algorithm fails otherwise)
- clr %o2
-
- sethi %hi(1 << (32 - 4 - 1)), %g1
-
- cmp %o3, %g1
- blu Lnot_really_big
- clr %o4
-
- ! Here the dividend is >= 2**(31-N) or so. We must be careful here,
- ! as our usual N-at-a-shot divide step will cause overflow and havoc.
- ! The number of bits in the result here is N*ITER+SC, where SC <= N.
- ! Compute ITER in an unorthodox manner: know we need to shift V into
- ! the top decade: so do not even bother to compare to R.
- 1:
- cmp %o5, %g1
- bgeu 3f
- mov 1, %g7
-
- sll %o5, 4, %o5
-
- b 1b
- add %o4, 1, %o4
-
- ! Now compute %g7.
- 2:
- addcc %o5, %o5, %o5
- bcc Lnot_too_big
- add %g7, 1, %g7
-
- ! We get here if the %o1 overflowed while shifting.
- ! This means that %o3 has the high-order bit set.
- ! Restore %o5 and subtract from %o3.
- sll %g1, 4, %g1 ! high order bit
- srl %o5, 1, %o5 ! rest of %o5
- add %o5, %g1, %o5
-
- b Ldo_single_div
- sub %g7, 1, %g7
-
- Lnot_too_big:
- 3:
- cmp %o5, %o3
- blu 2b
- nop
-
- be Ldo_single_div
- nop
- /* NB: these are commented out in the V8-Sparc manual as well */
- /* (I do not understand this) */
- ! %o5 > %o3: went too far: back up 1 step
- ! srl %o5, 1, %o5
- ! dec %g7
- ! do single-bit divide steps
- !
- ! We have to be careful here. We know that %o3 >= %o5, so we can do the
- ! first divide step without thinking. BUT, the others are conditional,
- ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high-
- ! order bit set in the first step, just falling into the regular
- ! division loop will mess up the first time around.
- ! So we unroll slightly...
- Ldo_single_div:
- subcc %g7, 1, %g7
- bl Lend_regular_divide
- nop
-
- sub %o3, %o5, %o3
- mov 1, %o2
-
- b Lend_single_divloop
- nop
- Lsingle_divloop:
- sll %o2, 1, %o2
- bl 1f
- srl %o5, 1, %o5
- ! %o3 >= 0
- sub %o3, %o5, %o3
- b 2f
- add %o2, 1, %o2
- 1: ! %o3 < 0
- add %o3, %o5, %o3
- sub %o2, 1, %o2
- 2:
- Lend_single_divloop:
- subcc %g7, 1, %g7
- bge Lsingle_divloop
- tst %o3
-
- b,a Lend_regular_divide
-
-Lnot_really_big:
-1:
- sll %o5, 4, %o5
-
- cmp %o5, %o3
- bleu 1b
- addcc %o4, 1, %o4
-
- be Lgot_result
- sub %o4, 1, %o4
-
- tst %o3 ! set up for initial iteration
-Ldivloop:
- sll %o2, 4, %o2
- ! depth 1, accumulated bits 0
- bl L.1.16
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 2, accumulated bits 1
- bl L.2.17
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 3, accumulated bits 3
- bl L.3.19
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits 7
- bl L.4.23
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (7*2+1), %o2
-
-L.4.23:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (7*2-1), %o2
-
-L.3.19:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits 5
- bl L.4.21
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (5*2+1), %o2
-
-L.4.21:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (5*2-1), %o2
-
-L.2.17:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 3, accumulated bits 1
- bl L.3.17
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits 3
- bl L.4.19
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (3*2+1), %o2
-
-L.4.19:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (3*2-1), %o2
-
-L.3.17:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits 1
- bl L.4.17
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (1*2+1), %o2
-
-L.4.17:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (1*2-1), %o2
-
-L.1.16:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 2, accumulated bits -1
- bl L.2.15
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 3, accumulated bits -1
- bl L.3.15
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits -1
- bl L.4.15
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-1*2+1), %o2
-
-L.4.15:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-1*2-1), %o2
-
-L.3.15:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits -3
- bl L.4.13
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-3*2+1), %o2
-
-L.4.13:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-3*2-1), %o2
-
-L.2.15:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 3, accumulated bits -3
- bl L.3.13
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits -5
- bl L.4.11
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-5*2+1), %o2
-
-L.4.11:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-5*2-1), %o2
-
-L.3.13:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits -7
- bl L.4.9
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-7*2+1), %o2
-
-L.4.9:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-7*2-1), %o2
-
- 9:
-Lend_regular_divide:
- subcc %o4, 1, %o4
- bge Ldivloop
- tst %o3
-
- bl,a Lgot_result
- ! non-restoring fixup here (one instruction only!)
- sub %o2, 1, %o2
-
-Lgot_result:
-
- retl
- mov %o2, %o0
-
- .globl .udiv_patch
-.udiv_patch:
- wr %g0, 0x0, %y
- nop
- nop
- retl
- udiv %o0, %o1, %o0
- nop
diff --git a/arch/sparc/lib/udivdi3.S b/arch/sparc/lib/udivdi3.S
index b430f1f0ef62..24e0a355e2e8 100644
--- a/arch/sparc/lib/udivdi3.S
+++ b/arch/sparc/lib/udivdi3.S
@@ -60,8 +60,9 @@ __udivdi3:
bne .LL77
mov %i0,%o2
mov 1,%o0
- call .udiv,0
mov 0,%o1
+ wr %g0, 0, %y
+ udiv %o0, %o1, %o0
mov %o0,%o3
mov %i0,%o2
.LL77:
diff --git a/arch/sparc/lib/umul.S b/arch/sparc/lib/umul.S
deleted file mode 100644
index 1f36ae682529..000000000000
--- a/arch/sparc/lib/umul.S
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * umul.S: This routine was taken from glibc-1.09 and is covered
- * by the GNU Library General Public License Version 2.
- */
-
-
-/*
- * Unsigned multiply. Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the
- * upper 32 bits of the 64-bit product).
- *
- * This code optimizes short (less than 13-bit) multiplies. Short
- * multiplies require 25 instruction cycles, and long ones require
- * 45 instruction cycles.
- *
- * On return, overflow has occurred (%o1 is not zero) if and only if
- * the Z condition code is clear, allowing, e.g., the following:
- *
- * call .umul
- * nop
- * bnz overflow (or tnz)
- */
-
- .globl .umul
- .globl _Umul
-.umul:
-_Umul: /* needed for export */
- or %o0, %o1, %o4
- mov %o0, %y ! multiplier -> Y
-
- andncc %o4, 0xfff, %g0 ! test bits 12..31 of *both* args
- be Lmul_shortway ! if zero, can do it the short way
- andcc %g0, %g0, %o4 ! zero the partial product and clear N and V
-
- /*
- * Long multiply. 32 steps, followed by a final shift step.
- */
- mulscc %o4, %o1, %o4 ! 1
- mulscc %o4, %o1, %o4 ! 2
- mulscc %o4, %o1, %o4 ! 3
- mulscc %o4, %o1, %o4 ! 4
- mulscc %o4, %o1, %o4 ! 5
- mulscc %o4, %o1, %o4 ! 6
- mulscc %o4, %o1, %o4 ! 7
- mulscc %o4, %o1, %o4 ! 8
- mulscc %o4, %o1, %o4 ! 9
- mulscc %o4, %o1, %o4 ! 10
- mulscc %o4, %o1, %o4 ! 11
- mulscc %o4, %o1, %o4 ! 12
- mulscc %o4, %o1, %o4 ! 13
- mulscc %o4, %o1, %o4 ! 14
- mulscc %o4, %o1, %o4 ! 15
- mulscc %o4, %o1, %o4 ! 16
- mulscc %o4, %o1, %o4 ! 17
- mulscc %o4, %o1, %o4 ! 18
- mulscc %o4, %o1, %o4 ! 19
- mulscc %o4, %o1, %o4 ! 20
- mulscc %o4, %o1, %o4 ! 21
- mulscc %o4, %o1, %o4 ! 22
- mulscc %o4, %o1, %o4 ! 23
- mulscc %o4, %o1, %o4 ! 24
- mulscc %o4, %o1, %o4 ! 25
- mulscc %o4, %o1, %o4 ! 26
- mulscc %o4, %o1, %o4 ! 27
- mulscc %o4, %o1, %o4 ! 28
- mulscc %o4, %o1, %o4 ! 29
- mulscc %o4, %o1, %o4 ! 30
- mulscc %o4, %o1, %o4 ! 31
- mulscc %o4, %o1, %o4 ! 32
- mulscc %o4, %g0, %o4 ! final shift
-
-
- /*
- * Normally, with the shift-and-add approach, if both numbers are
- * positive you get the correct result. With 32-bit two's-complement
- * numbers, -x is represented as
- *
- * x 32
- * ( 2 - ------ ) mod 2 * 2
- * 32
- * 2
- *
- * (the `mod 2' subtracts 1 from 1.bbbb). To avoid lots of 2^32s,
- * we can treat this as if the radix point were just to the left
- * of the sign bit (multiply by 2^32), and get
- *
- * -x = (2 - x) mod 2
- *
- * Then, ignoring the `mod 2's for convenience:
- *
- * x * y = xy
- * -x * y = 2y - xy
- * x * -y = 2x - xy
- * -x * -y = 4 - 2x - 2y + xy
- *
- * For signed multiplies, we subtract (x << 32) from the partial
- * product to fix this problem for negative multipliers (see mul.s).
- * Because of the way the shift into the partial product is calculated
- * (N xor V), this term is automatically removed for the multiplicand,
- * so we don't have to adjust.
- *
- * But for unsigned multiplies, the high order bit wasn't a sign bit,
- * and the correction is wrong. So for unsigned multiplies where the
- * high order bit is one, we end up with xy - (y << 32). To fix it
- * we add y << 32.
- */
-#if 0
- tst %o1
- bl,a 1f ! if %o1 < 0 (high order bit = 1),
- add %o4, %o0, %o4 ! %o4 += %o0 (add y to upper half)
-
-1:
- rd %y, %o0 ! get lower half of product
- retl
- addcc %o4, %g0, %o1 ! put upper half in place and set Z for %o1==0
-#else
- /* Faster code from tege@sics.se. */
- sra %o1, 31, %o2 ! make mask from sign bit
- and %o0, %o2, %o2 ! %o2 = 0 or %o0, depending on sign of %o1
- rd %y, %o0 ! get lower half of product
- retl
- addcc %o4, %o2, %o1 ! add compensation and put upper half in place
-#endif
-
-Lmul_shortway:
- /*
- * Short multiply. 12 steps, followed by a final shift step.
- * The resulting bits are off by 12 and (32-12) = 20 bit positions,
- * but there is no problem with %o0 being negative (unlike above),
- * and overflow is impossible (the answer is at most 24 bits long).
- */
- mulscc %o4, %o1, %o4 ! 1
- mulscc %o4, %o1, %o4 ! 2
- mulscc %o4, %o1, %o4 ! 3
- mulscc %o4, %o1, %o4 ! 4
- mulscc %o4, %o1, %o4 ! 5
- mulscc %o4, %o1, %o4 ! 6
- mulscc %o4, %o1, %o4 ! 7
- mulscc %o4, %o1, %o4 ! 8
- mulscc %o4, %o1, %o4 ! 9
- mulscc %o4, %o1, %o4 ! 10
- mulscc %o4, %o1, %o4 ! 11
- mulscc %o4, %o1, %o4 ! 12
- mulscc %o4, %g0, %o4 ! final shift
-
- /*
- * %o4 has 20 of the bits that should be in the result; %y has
- * the bottom 12 (as %y's top 12). That is:
- *
- * %o4 %y
- * +----------------+----------------+
- * | -12- | -20- | -12- | -20- |
- * +------(---------+------)---------+
- * -----result-----
- *
- * The 12 bits of %o4 left of the `result' area are all zero;
- * in fact, all top 20 bits of %o4 are zero.
- */
-
- rd %y, %o5
- sll %o4, 12, %o0 ! shift middle bits left 12
- srl %o5, 20, %o5 ! shift low bits right 20
- or %o5, %o0, %o0
- retl
- addcc %g0, %g0, %o1 ! %o1 = zero, and set Z
-
- .globl .umul_patch
-.umul_patch:
- umul %o0, %o1, %o0
- retl
- rd %y, %o1
- nop
diff --git a/arch/sparc/lib/urem.S b/arch/sparc/lib/urem.S
deleted file mode 100644
index 77123eb83c44..000000000000
--- a/arch/sparc/lib/urem.S
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * urem.S: This routine was taken from glibc-1.09 and is covered
- * by the GNU Library General Public License Version 2.
- */
-
-/* This file is generated from divrem.m4; DO NOT EDIT! */
-/*
- * Division and remainder, from Appendix E of the Sparc Version 8
- * Architecture Manual, with fixes from Gordon Irlam.
- */
-
-/*
- * Input: dividend and divisor in %o0 and %o1 respectively.
- *
- * m4 parameters:
- * .urem name of function to generate
- * rem rem=div => %o0 / %o1; rem=rem => %o0 % %o1
- * false false=true => signed; false=false => unsigned
- *
- * Algorithm parameters:
- * N how many bits per iteration we try to get (4)
- * WORDSIZE total number of bits (32)
- *
- * Derived constants:
- * TOPBITS number of bits in the top decade of a number
- *
- * Important variables:
- * Q the partial quotient under development (initially 0)
- * R the remainder so far, initially the dividend
- * ITER number of main division loop iterations required;
- * equal to ceil(log2(quotient) / N). Note that this
- * is the log base (2^N) of the quotient.
- * V the current comparand, initially divisor*2^(ITER*N-1)
- *
- * Cost:
- * Current estimate for non-large dividend is
- * ceil(log2(quotient) / N) * (10 + 7N/2) + C
- * A large dividend is one greater than 2^(31-TOPBITS) and takes a
- * different path, as the upper bits of the quotient must be developed
- * one bit at a time.
- */
-
- .globl .urem
- .globl _Urem
-.urem:
-_Urem: /* needed for export */
-
- ! Ready to divide. Compute size of quotient; scale comparand.
- orcc %o1, %g0, %o5
- bne 1f
- mov %o0, %o3
-
- ! Divide by zero trap. If it returns, return 0 (about as
- ! wrong as possible, but that is what SunOS does...).
- ta ST_DIV0
- retl
- clr %o0
-
-1:
- cmp %o3, %o5 ! if %o1 exceeds %o0, done
- blu Lgot_result ! (and algorithm fails otherwise)
- clr %o2
-
- sethi %hi(1 << (32 - 4 - 1)), %g1
-
- cmp %o3, %g1
- blu Lnot_really_big
- clr %o4
-
- ! Here the dividend is >= 2**(31-N) or so. We must be careful here,
- ! as our usual N-at-a-shot divide step will cause overflow and havoc.
- ! The number of bits in the result here is N*ITER+SC, where SC <= N.
- ! Compute ITER in an unorthodox manner: know we need to shift V into
- ! the top decade: so do not even bother to compare to R.
- 1:
- cmp %o5, %g1
- bgeu 3f
- mov 1, %g7
-
- sll %o5, 4, %o5
-
- b 1b
- add %o4, 1, %o4
-
- ! Now compute %g7.
- 2:
- addcc %o5, %o5, %o5
- bcc Lnot_too_big
- add %g7, 1, %g7
-
- ! We get here if the %o1 overflowed while shifting.
- ! This means that %o3 has the high-order bit set.
- ! Restore %o5 and subtract from %o3.
- sll %g1, 4, %g1 ! high order bit
- srl %o5, 1, %o5 ! rest of %o5
- add %o5, %g1, %o5
-
- b Ldo_single_div
- sub %g7, 1, %g7
-
- Lnot_too_big:
- 3:
- cmp %o5, %o3
- blu 2b
- nop
-
- be Ldo_single_div
- nop
- /* NB: these are commented out in the V8-Sparc manual as well */
- /* (I do not understand this) */
- ! %o5 > %o3: went too far: back up 1 step
- ! srl %o5, 1, %o5
- ! dec %g7
- ! do single-bit divide steps
- !
- ! We have to be careful here. We know that %o3 >= %o5, so we can do the
- ! first divide step without thinking. BUT, the others are conditional,
- ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high-
- ! order bit set in the first step, just falling into the regular
- ! division loop will mess up the first time around.
- ! So we unroll slightly...
- Ldo_single_div:
- subcc %g7, 1, %g7
- bl Lend_regular_divide
- nop
-
- sub %o3, %o5, %o3
- mov 1, %o2
-
- b Lend_single_divloop
- nop
- Lsingle_divloop:
- sll %o2, 1, %o2
- bl 1f
- srl %o5, 1, %o5
- ! %o3 >= 0
- sub %o3, %o5, %o3
- b 2f
- add %o2, 1, %o2
- 1: ! %o3 < 0
- add %o3, %o5, %o3
- sub %o2, 1, %o2
- 2:
- Lend_single_divloop:
- subcc %g7, 1, %g7
- bge Lsingle_divloop
- tst %o3
-
- b,a Lend_regular_divide
-
-Lnot_really_big:
-1:
- sll %o5, 4, %o5
-
- cmp %o5, %o3
- bleu 1b
- addcc %o4, 1, %o4
-
- be Lgot_result
- sub %o4, 1, %o4
-
- tst %o3 ! set up for initial iteration
-Ldivloop:
- sll %o2, 4, %o2
- ! depth 1, accumulated bits 0
- bl L.1.16
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 2, accumulated bits 1
- bl L.2.17
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 3, accumulated bits 3
- bl L.3.19
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits 7
- bl L.4.23
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (7*2+1), %o2
-
-L.4.23:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (7*2-1), %o2
-
-L.3.19:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits 5
- bl L.4.21
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (5*2+1), %o2
-
-L.4.21:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (5*2-1), %o2
-
-L.2.17:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 3, accumulated bits 1
- bl L.3.17
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits 3
- bl L.4.19
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (3*2+1), %o2
-
-L.4.19:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (3*2-1), %o2
-
-L.3.17:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits 1
- bl L.4.17
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (1*2+1), %o2
-
-L.4.17:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (1*2-1), %o2
-
-L.1.16:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 2, accumulated bits -1
- bl L.2.15
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 3, accumulated bits -1
- bl L.3.15
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits -1
- bl L.4.15
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-1*2+1), %o2
-
-L.4.15:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-1*2-1), %o2
-
-L.3.15:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits -3
- bl L.4.13
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-3*2+1), %o2
-
-L.4.13:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-3*2-1), %o2
-
-L.2.15:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 3, accumulated bits -3
- bl L.3.13
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- ! depth 4, accumulated bits -5
- bl L.4.11
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-5*2+1), %o2
-
-L.4.11:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-5*2-1), %o2
-
-L.3.13:
- ! remainder is negative
- addcc %o3,%o5,%o3
- ! depth 4, accumulated bits -7
- bl L.4.9
- srl %o5,1,%o5
- ! remainder is positive
- subcc %o3,%o5,%o3
- b 9f
- add %o2, (-7*2+1), %o2
-
-L.4.9:
- ! remainder is negative
- addcc %o3,%o5,%o3
- b 9f
- add %o2, (-7*2-1), %o2
-
- 9:
-Lend_regular_divide:
- subcc %o4, 1, %o4
- bge Ldivloop
- tst %o3
-
- bl,a Lgot_result
- ! non-restoring fixup here (one instruction only!)
- add %o3, %o1, %o3
-
-Lgot_result:
-
- retl
- mov %o3, %o0
-
- .globl .urem_patch
-.urem_patch:
- wr %g0, 0x0, %y
- nop
- nop
- nop
- udiv %o0, %o1, %o2
- umul %o2, %o1, %o2
- retl
- sub %o0, %o2, %o0
diff --git a/arch/sparc/lib/xor.S b/arch/sparc/lib/xor.S
index f44f58f40234..2c05641c3263 100644
--- a/arch/sparc/lib/xor.S
+++ b/arch/sparc/lib/xor.S
@@ -8,6 +8,7 @@
* Copyright (C) 2006 David S. Miller <davem@davemloft.net>
*/
+#include <linux/linkage.h>
#include <asm/visasm.h>
#include <asm/asi.h>
#include <asm/dcu.h>
@@ -19,12 +20,9 @@
* !(len & 127) && len >= 256
*/
.text
- .align 32
/* VIS versions. */
- .globl xor_vis_2
- .type xor_vis_2,#function
-xor_vis_2:
+ENTRY(xor_vis_2)
rd %fprs, %o5
andcc %o5, FPRS_FEF|FPRS_DU, %g0
be,pt %icc, 0f
@@ -91,11 +89,9 @@ xor_vis_2:
wr %g1, %g0, %asi
retl
wr %g0, 0, %fprs
- .size xor_vis_2, .-xor_vis_2
+ENDPROC(xor_vis_2)
- .globl xor_vis_3
- .type xor_vis_3,#function
-xor_vis_3:
+ENTRY(xor_vis_3)
rd %fprs, %o5
andcc %o5, FPRS_FEF|FPRS_DU, %g0
be,pt %icc, 0f
@@ -159,11 +155,9 @@ xor_vis_3:
wr %g1, %g0, %asi
retl
wr %g0, 0, %fprs
- .size xor_vis_3, .-xor_vis_3
+ENDPROC(xor_vis_3)
- .globl xor_vis_4
- .type xor_vis_4,#function
-xor_vis_4:
+ENTRY(xor_vis_4)
rd %fprs, %o5
andcc %o5, FPRS_FEF|FPRS_DU, %g0
be,pt %icc, 0f
@@ -246,11 +240,9 @@ xor_vis_4:
wr %g1, %g0, %asi
retl
wr %g0, 0, %fprs
- .size xor_vis_4, .-xor_vis_4
+ENDPROC(xor_vis_4)
- .globl xor_vis_5
- .type xor_vis_5,#function
-xor_vis_5:
+ENTRY(xor_vis_5)
save %sp, -192, %sp
rd %fprs, %o5
andcc %o5, FPRS_FEF|FPRS_DU, %g0
@@ -354,12 +346,10 @@ xor_vis_5:
wr %g0, 0, %fprs
ret
restore
- .size xor_vis_5, .-xor_vis_5
+ENDPROC(xor_vis_5)
/* Niagara versions. */
- .globl xor_niagara_2
- .type xor_niagara_2,#function
-xor_niagara_2: /* %o0=bytes, %o1=dest, %o2=src */
+ENTRY(xor_niagara_2) /* %o0=bytes, %o1=dest, %o2=src */
save %sp, -192, %sp
prefetch [%i1], #n_writes
prefetch [%i2], #one_read
@@ -402,11 +392,9 @@ xor_niagara_2: /* %o0=bytes, %o1=dest, %o2=src */
wr %g7, 0x0, %asi
ret
restore
- .size xor_niagara_2, .-xor_niagara_2
+ENDPROC(xor_niagara_2)
- .globl xor_niagara_3
- .type xor_niagara_3,#function
-xor_niagara_3: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2 */
+ENTRY(xor_niagara_3) /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2 */
save %sp, -192, %sp
prefetch [%i1], #n_writes
prefetch [%i2], #one_read
@@ -465,11 +453,9 @@ xor_niagara_3: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2 */
wr %g7, 0x0, %asi
ret
restore
- .size xor_niagara_3, .-xor_niagara_3
+ENDPROC(xor_niagara_3)
- .globl xor_niagara_4
- .type xor_niagara_4,#function
-xor_niagara_4: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3 */
+ENTRY(xor_niagara_4) /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3 */
save %sp, -192, %sp
prefetch [%i1], #n_writes
prefetch [%i2], #one_read
@@ -549,11 +535,9 @@ xor_niagara_4: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3 */
wr %g7, 0x0, %asi
ret
restore
- .size xor_niagara_4, .-xor_niagara_4
+ENDPROC(xor_niagara_4)
- .globl xor_niagara_5
- .type xor_niagara_5,#function
-xor_niagara_5: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3, %o5=src4 */
+ENTRY(xor_niagara_5) /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3, %o5=src4 */
save %sp, -192, %sp
prefetch [%i1], #n_writes
prefetch [%i2], #one_read
@@ -649,4 +633,4 @@ xor_niagara_5: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3, %o5=src4 *
wr %g7, 0x0, %asi
ret
restore
- .size xor_niagara_5, .-xor_niagara_5
+ENDPROC(xor_niagara_5)
diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile
index 301421c11291..69ffd3112fed 100644
--- a/arch/sparc/mm/Makefile
+++ b/arch/sparc/mm/Makefile
@@ -7,8 +7,7 @@ ccflags-y := -Werror
obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o gup.o
obj-y += fault_$(BITS).o
obj-y += init_$(BITS).o
-obj-$(CONFIG_SPARC32) += loadmmu.o
-obj-$(CONFIG_SPARC32) += extable.o btfixup.o srmmu.o iommu.o io-unit.o
+obj-$(CONFIG_SPARC32) += extable.o srmmu.o iommu.o io-unit.o
obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o
obj-$(CONFIG_SPARC_LEON)+= leon_mm.o
@@ -17,9 +16,3 @@ obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
# Only used by sparc32
obj-$(CONFIG_HIGHMEM) += highmem.o
-
-ifdef CONFIG_SMP
-obj-$(CONFIG_SPARC32) += nosun4c.o
-else
-obj-$(CONFIG_SPARC32) += sun4c.o
-endif
diff --git a/arch/sparc/mm/btfixup.c b/arch/sparc/mm/btfixup.c
deleted file mode 100644
index 09d6af22db2d..000000000000
--- a/arch/sparc/mm/btfixup.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/* btfixup.c: Boot time code fixup and relocator, so that
- * we can get rid of most indirect calls to achieve single
- * image sun4c and srmmu kernel.
- *
- * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/btfixup.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/oplib.h>
-#include <asm/cacheflush.h>
-
-#define BTFIXUP_OPTIMIZE_NOP
-#define BTFIXUP_OPTIMIZE_OTHER
-
-extern char *srmmu_name;
-static char version[] __initdata = "Boot time fixup v1.6. 4/Mar/98 Jakub Jelinek (jj@ultra.linux.cz). Patching kernel for ";
-static char str_sun4c[] __initdata = "sun4c\n";
-static char str_srmmu[] __initdata = "srmmu[%s]/";
-static char str_iommu[] __initdata = "iommu\n";
-static char str_iounit[] __initdata = "io-unit\n";
-
-static int visited __initdata = 0;
-extern unsigned int ___btfixup_start[], ___btfixup_end[], __init_begin[], __init_end[], __init_text_end[];
-extern unsigned int _stext[], _end[], __start___ksymtab[], __stop___ksymtab[];
-static char wrong_f[] __initdata = "Trying to set f fixup %p to invalid function %08x\n";
-static char wrong_b[] __initdata = "Trying to set b fixup %p to invalid function %08x\n";
-static char wrong_s[] __initdata = "Trying to set s fixup %p to invalid value %08x\n";
-static char wrong_h[] __initdata = "Trying to set h fixup %p to invalid value %08x\n";
-static char wrong_a[] __initdata = "Trying to set a fixup %p to invalid value %08x\n";
-static char wrong[] __initdata = "Wrong address for %c fixup %p\n";
-static char insn_f[] __initdata = "Fixup f %p refers to weird instructions at %p[%08x,%08x]\n";
-static char insn_b[] __initdata = "Fixup b %p doesn't refer to a SETHI at %p[%08x]\n";
-static char insn_s[] __initdata = "Fixup s %p doesn't refer to an OR at %p[%08x]\n";
-static char insn_h[] __initdata = "Fixup h %p doesn't refer to a SETHI at %p[%08x]\n";
-static char insn_a[] __initdata = "Fixup a %p doesn't refer to a SETHI nor OR at %p[%08x]\n";
-static char insn_i[] __initdata = "Fixup i %p doesn't refer to a valid instruction at %p[%08x]\n";
-static char fca_und[] __initdata = "flush_cache_all undefined in btfixup()\n";
-static char wrong_setaddr[] __initdata = "Garbled CALL/INT patch at %p[%08x,%08x,%08x]=%08x\n";
-
-#ifdef BTFIXUP_OPTIMIZE_OTHER
-static void __init set_addr(unsigned int *addr, unsigned int q1, int fmangled, unsigned int value)
-{
- if (!fmangled)
- *addr = value;
- else {
- unsigned int *q = (unsigned int *)q1;
- if (*addr == 0x01000000) {
- /* Noped */
- *q = value;
- } else if (addr[-1] == *q) {
- /* Moved */
- addr[-1] = value;
- *q = value;
- } else {
- prom_printf(wrong_setaddr, addr-1, addr[-1], *addr, *q, value);
- prom_halt();
- }
- }
-}
-#else
-static inline void set_addr(unsigned int *addr, unsigned int q1, int fmangled, unsigned int value)
-{
- *addr = value;
-}
-#endif
-
-void __init btfixup(void)
-{
- unsigned int *p, *q;
- int type, count;
- unsigned insn;
- unsigned *addr;
- int fmangled = 0;
- void (*flush_cacheall)(void);
-
- if (!visited) {
- visited++;
- printk(version);
- if (ARCH_SUN4C)
- printk(str_sun4c);
- else {
- printk(str_srmmu, srmmu_name);
- if (sparc_cpu_model == sun4d)
- printk(str_iounit);
- else
- printk(str_iommu);
- }
- }
- for (p = ___btfixup_start; p < ___btfixup_end; ) {
- count = p[2];
- q = p + 3;
- switch (type = *(unsigned char *)p) {
- case 'f':
- count = p[3];
- q = p + 4;
- if (((p[0] & 1) || p[1])
- && ((p[1] & 3) || (unsigned *)(p[1]) < _stext || (unsigned *)(p[1]) >= _end)) {
- prom_printf(wrong_f, p, p[1]);
- prom_halt();
- }
- break;
- case 'b':
- if (p[1] < (unsigned long)__init_begin || p[1] >= (unsigned long)__init_text_end || (p[1] & 3)) {
- prom_printf(wrong_b, p, p[1]);
- prom_halt();
- }
- break;
- case 's':
- if (p[1] + 0x1000 >= 0x2000) {
- prom_printf(wrong_s, p, p[1]);
- prom_halt();
- }
- break;
- case 'h':
- if (p[1] & 0x3ff) {
- prom_printf(wrong_h, p, p[1]);
- prom_halt();
- }
- break;
- case 'a':
- if (p[1] + 0x1000 >= 0x2000 && (p[1] & 0x3ff)) {
- prom_printf(wrong_a, p, p[1]);
- prom_halt();
- }
- break;
- }
- if (p[0] & 1) {
- p[0] &= ~1;
- while (count) {
- fmangled = 0;
- addr = (unsigned *)*q;
- if (addr < _stext || addr >= _end) {
- prom_printf(wrong, type, p);
- prom_halt();
- }
- insn = *addr;
-#ifdef BTFIXUP_OPTIMIZE_OTHER
- if (type != 'f' && q[1]) {
- insn = *(unsigned int *)q[1];
- if (!insn || insn == 1)
- insn = *addr;
- else
- fmangled = 1;
- }
-#endif
- switch (type) {
- case 'f': /* CALL */
- if (addr >= __start___ksymtab && addr < __stop___ksymtab) {
- *addr = p[1];
- break;
- } else if (!q[1]) {
- if ((insn & 0xc1c00000) == 0x01000000) { /* SETHI */
- *addr = (insn & 0xffc00000) | (p[1] >> 10); break;
- } else if ((insn & 0xc1f82000) == 0x80102000) { /* OR X, %LO(i), Y */
- *addr = (insn & 0xffffe000) | (p[1] & 0x3ff); break;
- } else if ((insn & 0xc0000000) != 0x40000000) { /* !CALL */
- bad_f:
- prom_printf(insn_f, p, addr, insn, addr[1]);
- prom_halt();
- }
- } else if (q[1] != 1)
- addr[1] = q[1];
- if (p[2] == BTFIXUPCALL_NORM) {
- norm_f:
- *addr = 0x40000000 | ((p[1] - (unsigned)addr) >> 2);
- q[1] = 0;
- break;
- }
-#ifndef BTFIXUP_OPTIMIZE_NOP
- goto norm_f;
-#else
- if (!(addr[1] & 0x80000000)) {
- if ((addr[1] & 0xc1c00000) != 0x01000000) /* !SETHI */
- goto bad_f; /* CALL, Bicc, FBfcc, CBccc are weird in delay slot, aren't they? */
- } else {
- if ((addr[1] & 0x01800000) == 0x01800000) {
- if ((addr[1] & 0x01f80000) == 0x01e80000) {
- /* RESTORE */
- goto norm_f; /* It is dangerous to patch that */
- }
- goto bad_f;
- }
- if ((addr[1] & 0xffffe003) == 0x9e03e000) {
- /* ADD %O7, XX, %o7 */
- int displac = (addr[1] << 19);
-
- displac = (displac >> 21) + 2;
- *addr = (0x10800000) + (displac & 0x3fffff);
- q[1] = addr[1];
- addr[1] = p[2];
- break;
- }
- if ((addr[1] & 0x201f) == 0x200f || (addr[1] & 0x7c000) == 0x3c000)
- goto norm_f; /* Someone is playing bad tricks with us: rs1 or rs2 is o7 */
- if ((addr[1] & 0x3e000000) == 0x1e000000)
- goto norm_f; /* rd is %o7. We'd better take care. */
- }
- if (p[2] == BTFIXUPCALL_NOP) {
- *addr = 0x01000000;
- q[1] = 1;
- break;
- }
-#ifndef BTFIXUP_OPTIMIZE_OTHER
- goto norm_f;
-#else
- if (addr[1] == 0x01000000) { /* NOP in the delay slot */
- q[1] = addr[1];
- *addr = p[2];
- break;
- }
- if ((addr[1] & 0xc0000000) != 0xc0000000) {
- /* Not a memory operation */
- if ((addr[1] & 0x30000000) == 0x10000000) {
- /* Ok, non-memory op with rd %oX */
- if ((addr[1] & 0x3e000000) == 0x1c000000)
- goto bad_f; /* Aiee. Someone is playing strange %sp tricks */
- if ((addr[1] & 0x3e000000) > 0x12000000 ||
- ((addr[1] & 0x3e000000) == 0x12000000 &&
- p[2] != BTFIXUPCALL_STO1O0 && p[2] != BTFIXUPCALL_SWAPO0O1) ||
- ((p[2] & 0xffffe000) == BTFIXUPCALL_RETINT(0))) {
- /* Nobody uses the result. We can nop it out. */
- *addr = p[2];
- q[1] = addr[1];
- addr[1] = 0x01000000;
- break;
- }
- if ((addr[1] & 0xf1ffffe0) == 0x90100000) {
- /* MOV %reg, %Ox */
- if ((addr[1] & 0x3e000000) == 0x10000000 &&
- (p[2] & 0x7c000) == 0x20000) {
- /* Ok, it is call xx; mov reg, %o0 and call optimizes
- to doing something on %o0. Patch the patch. */
- *addr = (p[2] & ~0x7c000) | ((addr[1] & 0x1f) << 14);
- q[1] = addr[1];
- addr[1] = 0x01000000;
- break;
- }
- if ((addr[1] & 0x3e000000) == 0x12000000 &&
- p[2] == BTFIXUPCALL_STO1O0) {
- *addr = (p[2] & ~0x3e000000) | ((addr[1] & 0x1f) << 25);
- q[1] = addr[1];
- addr[1] = 0x01000000;
- break;
- }
- }
- }
- }
- *addr = addr[1];
- q[1] = addr[1];
- addr[1] = p[2];
- break;
-#endif /* BTFIXUP_OPTIMIZE_OTHER */
-#endif /* BTFIXUP_OPTIMIZE_NOP */
- case 'b': /* BLACKBOX */
- /* Has to be sethi i, xx */
- if ((insn & 0xc1c00000) != 0x01000000) {
- prom_printf(insn_b, p, addr, insn);
- prom_halt();
- } else {
- void (*do_fixup)(unsigned *);
-
- do_fixup = (void (*)(unsigned *))p[1];
- do_fixup(addr);
- }
- break;
- case 's': /* SIMM13 */
- /* Has to be or %g0, i, xx */
- if ((insn & 0xc1ffe000) != 0x80102000) {
- prom_printf(insn_s, p, addr, insn);
- prom_halt();
- }
- set_addr(addr, q[1], fmangled, (insn & 0xffffe000) | (p[1] & 0x1fff));
- break;
- case 'h': /* SETHI */
- /* Has to be sethi i, xx */
- if ((insn & 0xc1c00000) != 0x01000000) {
- prom_printf(insn_h, p, addr, insn);
- prom_halt();
- }
- set_addr(addr, q[1], fmangled, (insn & 0xffc00000) | (p[1] >> 10));
- break;
- case 'a': /* HALF */
- /* Has to be sethi i, xx or or %g0, i, xx */
- if ((insn & 0xc1c00000) != 0x01000000 &&
- (insn & 0xc1ffe000) != 0x80102000) {
- prom_printf(insn_a, p, addr, insn);
- prom_halt();
- }
- if (p[1] & 0x3ff)
- set_addr(addr, q[1], fmangled,
- (insn & 0x3e000000) | 0x80102000 | (p[1] & 0x1fff));
- else
- set_addr(addr, q[1], fmangled,
- (insn & 0x3e000000) | 0x01000000 | (p[1] >> 10));
- break;
- case 'i': /* INT */
- if ((insn & 0xc1c00000) == 0x01000000) /* %HI */
- set_addr(addr, q[1], fmangled, (insn & 0xffc00000) | (p[1] >> 10));
- else if ((insn & 0x80002000) == 0x80002000) /* %LO */
- set_addr(addr, q[1], fmangled, (insn & 0xffffe000) | (p[1] & 0x3ff));
- else {
- prom_printf(insn_i, p, addr, insn);
- prom_halt();
- }
- break;
- }
- count -= 2;
- q += 2;
- }
- } else
- p = q + count;
- }
-#ifdef CONFIG_SMP
- flush_cacheall = (void (*)(void))BTFIXUPVAL_CALL(local_flush_cache_all);
-#else
- flush_cacheall = (void (*)(void))BTFIXUPVAL_CALL(flush_cache_all);
-#endif
- if (!flush_cacheall) {
- prom_printf(fca_und);
- prom_halt();
- }
- (*flush_cacheall)();
-}
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index df3155a17991..f46cf6be3370 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -24,29 +24,19 @@
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <asm/memreg.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/smp.h>
#include <asm/traps.h>
#include <asm/uaccess.h>
-extern int prom_node_root;
-
int show_unhandled_signals = 1;
/* At boot time we determine these two values necessary for setting
* up the segment maps and page table entries (pte's).
*/
-int num_segmaps, num_contexts;
-int invalid_segment;
-
-/* various Virtual Address Cache parameters we find at boot time... */
-
-int vac_size, vac_linesize, vac_do_hw_vac_flushes;
-int vac_entries_per_context, vac_entries_per_segment;
-int vac_entries_per_page;
+int num_contexts;
/* Return how much physical memory we have. */
unsigned long probe_memory(void)
@@ -60,55 +50,36 @@ unsigned long probe_memory(void)
return total;
}
-extern void sun4c_complete_all_stores(void);
-
-/* Whee, a level 15 NMI interrupt memory error. Let's have fun... */
-asmlinkage void sparc_lvl15_nmi(struct pt_regs *regs, unsigned long serr,
- unsigned long svaddr, unsigned long aerr,
- unsigned long avaddr)
-{
- sun4c_complete_all_stores();
- printk("FAULT: NMI received\n");
- printk("SREGS: Synchronous Error %08lx\n", serr);
- printk(" Synchronous Vaddr %08lx\n", svaddr);
- printk(" Asynchronous Error %08lx\n", aerr);
- printk(" Asynchronous Vaddr %08lx\n", avaddr);
- if (sun4c_memerr_reg)
- printk(" Memory Parity Error %08lx\n", *sun4c_memerr_reg);
- printk("REGISTER DUMP:\n");
- show_regs(regs);
- prom_halt();
-}
-
static void unhandled_fault(unsigned long, struct task_struct *,
struct pt_regs *) __attribute__ ((noreturn));
-static void unhandled_fault(unsigned long address, struct task_struct *tsk,
- struct pt_regs *regs)
+static void __noreturn unhandled_fault(unsigned long address,
+ struct task_struct *tsk,
+ struct pt_regs *regs)
{
- if((unsigned long) address < PAGE_SIZE) {
+ if ((unsigned long) address < PAGE_SIZE) {
printk(KERN_ALERT
"Unable to handle kernel NULL pointer dereference\n");
} else {
- printk(KERN_ALERT "Unable to handle kernel paging request "
- "at virtual address %08lx\n", address);
+ printk(KERN_ALERT "Unable to handle kernel paging request at virtual address %08lx\n",
+ address);
}
printk(KERN_ALERT "tsk->{mm,active_mm}->context = %08lx\n",
(tsk->mm ? tsk->mm->context : tsk->active_mm->context));
printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %08lx\n",
(tsk->mm ? (unsigned long) tsk->mm->pgd :
- (unsigned long) tsk->active_mm->pgd));
+ (unsigned long) tsk->active_mm->pgd));
die_if_kernel("Oops", regs);
}
-asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
+asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
unsigned long address)
{
struct pt_regs regs;
unsigned long g2;
unsigned int insn;
int i;
-
+
i = search_extables_range(ret_pc, &g2);
switch (i) {
case 3:
@@ -128,14 +99,14 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
/* for _from_ macros */
insn = *((unsigned int *) pc);
if (!((insn >> 21) & 1) || ((insn>>19)&0x3f) == 15)
- return 2;
- break;
+ return 2;
+ break;
default:
break;
}
- memset(&regs, 0, sizeof (regs));
+ memset(&regs, 0, sizeof(regs));
regs.pc = pc;
regs.npc = pc + 4;
__asm__ __volatile__(
@@ -198,11 +169,10 @@ static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault)
if (text_fault)
return regs->pc;
- if (regs->psr & PSR_PS) {
+ if (regs->psr & PSR_PS)
insn = *(unsigned int *) regs->pc;
- } else {
+ else
__get_user(insn, (unsigned int *) regs->pc);
- }
return safe_compute_effective_address(regs, insn);
}
@@ -228,7 +198,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
(write ? FAULT_FLAG_WRITE : 0));
- if(text_fault)
+ if (text_fault)
address = regs->pc;
/*
@@ -241,36 +211,32 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
* nothing more.
*/
code = SEGV_MAPERR;
- if (!ARCH_SUN4C && address >= TASK_SIZE)
+ if (address >= TASK_SIZE)
goto vmalloc_fault;
/*
* If we're in an interrupt or have no user
* context, we must not take the fault..
*/
- if (in_atomic() || !mm)
- goto no_context;
+ if (in_atomic() || !mm)
+ goto no_context;
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
retry:
down_read(&mm->mmap_sem);
- /*
- * The kernel referencing a bad kernel pointer can lock up
- * a sun4c machine completely, so we must attempt recovery.
- */
- if(!from_user && address >= PAGE_OFFSET)
+ if (!from_user && address >= PAGE_OFFSET)
goto bad_area;
vma = find_vma(mm, address);
- if(!vma)
+ if (!vma)
goto bad_area;
- if(vma->vm_start <= address)
+ if (vma->vm_start <= address)
goto good_area;
- if(!(vma->vm_flags & VM_GROWSDOWN))
+ if (!(vma->vm_flags & VM_GROWSDOWN))
goto bad_area;
- if(expand_stack(vma, address))
+ if (expand_stack(vma, address))
goto bad_area;
/*
* Ok, we have a good vm_area for this memory access, so
@@ -278,12 +244,12 @@ retry:
*/
good_area:
code = SEGV_ACCERR;
- if(write) {
- if(!(vma->vm_flags & VM_WRITE))
+ if (write) {
+ if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
} else {
/* Allow reads even for write-only mappings */
- if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
goto bad_area;
}
@@ -349,14 +315,16 @@ no_context:
g2 = regs->u_regs[UREG_G2];
if (!from_user) {
fixup = search_extables_range(regs->pc, &g2);
- if (fixup > 10) { /* Values below are reserved for other things */
+ /* Values below 10 are reserved for other things */
+ if (fixup > 10) {
extern const unsigned __memset_start[];
extern const unsigned __memset_end[];
extern const unsigned __csum_partial_copy_start[];
extern const unsigned __csum_partial_copy_end[];
#ifdef DEBUG_EXCEPTIONS
- printk("Exception: PC<%08lx> faddr<%08lx>\n", regs->pc, address);
+ printk("Exception: PC<%08lx> faddr<%08lx>\n",
+ regs->pc, address);
printk("EX_TABLE: insn<%08lx> fixup<%08x> g2<%08lx>\n",
regs->pc, fixup, g2);
#endif
@@ -364,7 +332,7 @@ no_context:
regs->pc < (unsigned long)__memset_end) ||
(regs->pc >= (unsigned long)__csum_partial_copy_start &&
regs->pc < (unsigned long)__csum_partial_copy_end)) {
- regs->u_regs[UREG_I4] = address;
+ regs->u_regs[UREG_I4] = address;
regs->u_regs[UREG_I5] = regs->pc;
}
regs->u_regs[UREG_G2] = g2;
@@ -373,8 +341,8 @@ no_context:
return;
}
}
-
- unhandled_fault (address, tsk, regs);
+
+ unhandled_fault(address, tsk, regs);
do_exit(SIGKILL);
/*
@@ -420,97 +388,12 @@ vmalloc_fault:
if (pmd_present(*pmd) || !pmd_present(*pmd_k))
goto bad_area_nosemaphore;
+
*pmd = *pmd_k;
return;
}
}
-asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write,
- unsigned long address)
-{
- extern void sun4c_update_mmu_cache(struct vm_area_struct *,
- unsigned long,pte_t *);
- extern pte_t *sun4c_pte_offset_kernel(pmd_t *,unsigned long);
- struct task_struct *tsk = current;
- struct mm_struct *mm = tsk->mm;
- pgd_t *pgdp;
- pte_t *ptep;
-
- if (text_fault) {
- address = regs->pc;
- } else if (!write &&
- !(regs->psr & PSR_PS)) {
- unsigned int insn, __user *ip;
-
- ip = (unsigned int __user *)regs->pc;
- if (!get_user(insn, ip)) {
- if ((insn & 0xc1680000) == 0xc0680000)
- write = 1;
- }
- }
-
- if (!mm) {
- /* We are oopsing. */
- do_sparc_fault(regs, text_fault, write, address);
- BUG(); /* P3 Oops already, you bitch */
- }
-
- pgdp = pgd_offset(mm, address);
- ptep = sun4c_pte_offset_kernel((pmd_t *) pgdp, address);
-
- if (pgd_val(*pgdp)) {
- if (write) {
- if ((pte_val(*ptep) & (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_PRESENT))
- == (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_PRESENT)) {
- unsigned long flags;
-
- *ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_ACCESSED |
- _SUN4C_PAGE_MODIFIED |
- _SUN4C_PAGE_VALID |
- _SUN4C_PAGE_DIRTY);
-
- local_irq_save(flags);
- if (sun4c_get_segmap(address) != invalid_segment) {
- sun4c_put_pte(address, pte_val(*ptep));
- local_irq_restore(flags);
- return;
- }
- local_irq_restore(flags);
- }
- } else {
- if ((pte_val(*ptep) & (_SUN4C_PAGE_READ|_SUN4C_PAGE_PRESENT))
- == (_SUN4C_PAGE_READ|_SUN4C_PAGE_PRESENT)) {
- unsigned long flags;
-
- *ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_ACCESSED |
- _SUN4C_PAGE_VALID);
-
- local_irq_save(flags);
- if (sun4c_get_segmap(address) != invalid_segment) {
- sun4c_put_pte(address, pte_val(*ptep));
- local_irq_restore(flags);
- return;
- }
- local_irq_restore(flags);
- }
- }
- }
-
- /* This conditional is 'interesting'. */
- if (pgd_val(*pgdp) && !(write && !(pte_val(*ptep) & _SUN4C_PAGE_WRITE))
- && (pte_val(*ptep) & _SUN4C_PAGE_VALID))
- /* Note: It is safe to not grab the MMAP semaphore here because
- * we know that update_mmu_cache() will not sleep for
- * any reason (at least not in the current implementation)
- * and therefore there is no danger of another thread getting
- * on the CPU and doing a shrink_mmap() on this vma.
- */
- sun4c_update_mmu_cache (find_vma(current->mm, address), address,
- ptep);
- else
- do_sparc_fault(regs, text_fault, write, address);
-}
-
/* This always deals with user addresses. */
static void force_user_fault(unsigned long address, int write)
{
@@ -523,21 +406,21 @@ static void force_user_fault(unsigned long address, int write)
down_read(&mm->mmap_sem);
vma = find_vma(mm, address);
- if(!vma)
+ if (!vma)
goto bad_area;
- if(vma->vm_start <= address)
+ if (vma->vm_start <= address)
goto good_area;
- if(!(vma->vm_flags & VM_GROWSDOWN))
+ if (!(vma->vm_flags & VM_GROWSDOWN))
goto bad_area;
- if(expand_stack(vma, address))
+ if (expand_stack(vma, address))
goto bad_area;
good_area:
code = SEGV_ACCERR;
- if(write) {
- if(!(vma->vm_flags & VM_WRITE))
+ if (write) {
+ if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
} else {
- if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
goto bad_area;
}
switch (handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0)) {
@@ -568,7 +451,7 @@ void window_overflow_fault(void)
unsigned long sp;
sp = current_thread_info()->rwbuf_stkptrs[0];
- if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
+ if (((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
force_user_fault(sp + 0x38, 1);
force_user_fault(sp, 1);
@@ -577,7 +460,7 @@ void window_overflow_fault(void)
void window_underflow_fault(unsigned long sp)
{
- if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
+ if (((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
force_user_fault(sp + 0x38, 0);
force_user_fault(sp, 0);
@@ -589,7 +472,7 @@ void window_ret_fault(struct pt_regs *regs)
unsigned long sp;
sp = regs->u_regs[UREG_FP];
- if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
+ if (((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
force_user_fault(sp + 0x38, 0);
force_user_fault(sp, 0);
diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c
index c5f9021b1a01..ef5c779ec855 100644
--- a/arch/sparc/mm/init_32.c
+++ b/arch/sparc/mm/init_32.c
@@ -27,7 +27,6 @@
#include <linux/gfp.h>
#include <asm/sections.h>
-#include <asm/vac-ops.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/vaddrs.h>
@@ -45,9 +44,6 @@ EXPORT_SYMBOL(phys_base);
unsigned long pfn_base;
EXPORT_SYMBOL(pfn_base);
-unsigned long page_kernel;
-EXPORT_SYMBOL(page_kernel);
-
struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1];
unsigned long sparc_unmapped_base;
@@ -287,44 +283,16 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
}
/*
- * check_pgt_cache
- *
- * This is called at the end of unmapping of VMA (zap_page_range),
- * to rescan the page cache for architecture specific things,
- * presumably something like sun4/sun4c PMEGs. Most architectures
- * define check_pgt_cache empty.
- *
- * We simply copy the 2.4 implementation for now.
- */
-static int pgt_cache_water[2] = { 25, 50 };
-
-void check_pgt_cache(void)
-{
- do_check_pgt_cache(pgt_cache_water[0], pgt_cache_water[1]);
-}
-
-/*
* paging_init() sets up the page tables: We call the MMU specific
* init routine based upon the Sun model type on the Sparc.
*
*/
-extern void sun4c_paging_init(void);
extern void srmmu_paging_init(void);
extern void device_scan(void);
-pgprot_t PAGE_SHARED __read_mostly;
-EXPORT_SYMBOL(PAGE_SHARED);
-
void __init paging_init(void)
{
switch(sparc_cpu_model) {
- case sun4c:
- case sun4e:
- case sun4:
- sun4c_paging_init();
- sparc_unmapped_base = 0xe0000000;
- BTFIXUPSET_SETHI(sparc_unmapped_base, 0xe0000000);
- break;
case sparc_leon:
leon_init();
/* fall through */
@@ -332,7 +300,6 @@ void __init paging_init(void)
case sun4d:
srmmu_paging_init();
sparc_unmapped_base = 0x50000000;
- BTFIXUPSET_SETHI(sparc_unmapped_base, 0x50000000);
break;
default:
prom_printf("paging_init: Cannot init paging on this Sparc\n");
@@ -341,24 +308,6 @@ void __init paging_init(void)
prom_halt();
}
- /* Initialize the protection map with non-constant, MMU dependent values. */
- protection_map[0] = PAGE_NONE;
- protection_map[1] = PAGE_READONLY;
- protection_map[2] = PAGE_COPY;
- protection_map[3] = PAGE_COPY;
- protection_map[4] = PAGE_READONLY;
- protection_map[5] = PAGE_READONLY;
- protection_map[6] = PAGE_COPY;
- protection_map[7] = PAGE_COPY;
- protection_map[8] = PAGE_NONE;
- protection_map[9] = PAGE_READONLY;
- protection_map[10] = PAGE_SHARED;
- protection_map[11] = PAGE_SHARED;
- protection_map[12] = PAGE_READONLY;
- protection_map[13] = PAGE_READONLY;
- protection_map[14] = PAGE_SHARED;
- protection_map[15] = PAGE_SHARED;
- btfixup();
prom_build_devicetree();
of_fill_in_cpu_data();
device_scan();
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 21faaeea85de..6026fdd1b2ed 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -741,7 +741,6 @@ static void __init find_ramdisk(unsigned long phys_base)
struct node_mem_mask {
unsigned long mask;
unsigned long val;
- unsigned long bootmem_paddr;
};
static struct node_mem_mask node_masks[MAX_NUMNODES];
static int num_node_masks;
@@ -806,12 +805,6 @@ static u64 memblock_nid_range(u64 start, u64 end, int *nid)
return start;
}
-#else
-static u64 memblock_nid_range(u64 start, u64 end, int *nid)
-{
- *nid = 0;
- return end;
-}
#endif
/* This must be invoked after performing all of the necessary
@@ -820,10 +813,11 @@ static u64 memblock_nid_range(u64 start, u64 end, int *nid)
*/
static void __init allocate_node_data(int nid)
{
- unsigned long paddr, num_pages, start_pfn, end_pfn;
struct pglist_data *p;
-
+ unsigned long start_pfn, end_pfn;
#ifdef CONFIG_NEED_MULTIPLE_NODES
+ unsigned long paddr;
+
paddr = memblock_alloc_try_nid(sizeof(struct pglist_data), SMP_CACHE_BYTES, nid);
if (!paddr) {
prom_printf("Cannot allocate pglist_data for nid[%d]\n", nid);
@@ -832,7 +826,7 @@ static void __init allocate_node_data(int nid)
NODE_DATA(nid) = __va(paddr);
memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
- NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
+ NODE_DATA(nid)->node_id = nid;
#endif
p = NODE_DATA(nid);
@@ -840,18 +834,6 @@ static void __init allocate_node_data(int nid)
get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
p->node_start_pfn = start_pfn;
p->node_spanned_pages = end_pfn - start_pfn;
-
- if (p->node_spanned_pages) {
- num_pages = bootmem_bootmap_pages(p->node_spanned_pages);
-
- paddr = memblock_alloc_try_nid(num_pages << PAGE_SHIFT, PAGE_SIZE, nid);
- if (!paddr) {
- prom_printf("Cannot allocate bootmap for nid[%d]\n",
- nid);
- prom_halt();
- }
- node_masks[nid].bootmem_paddr = paddr;
- }
}
static void init_node_masks_nonnuma(void)
@@ -1292,75 +1274,9 @@ static void __init bootmem_init_nonnuma(void)
node_set_online(0);
}
-static void __init reserve_range_in_node(int nid, unsigned long start,
- unsigned long end)
-{
- numadbg(" reserve_range_in_node(nid[%d],start[%lx],end[%lx]\n",
- nid, start, end);
- while (start < end) {
- unsigned long this_end;
- int n;
-
- this_end = memblock_nid_range(start, end, &n);
- if (n == nid) {
- numadbg(" MATCH reserving range [%lx:%lx]\n",
- start, this_end);
- reserve_bootmem_node(NODE_DATA(nid), start,
- (this_end - start), BOOTMEM_DEFAULT);
- } else
- numadbg(" NO MATCH, advancing start to %lx\n",
- this_end);
-
- start = this_end;
- }
-}
-
-static void __init trim_reserved_in_node(int nid)
-{
- struct memblock_region *reg;
-
- numadbg(" trim_reserved_in_node(%d)\n", nid);
-
- for_each_memblock(reserved, reg)
- reserve_range_in_node(nid, reg->base, reg->base + reg->size);
-}
-
-static void __init bootmem_init_one_node(int nid)
-{
- struct pglist_data *p;
-
- numadbg("bootmem_init_one_node(%d)\n", nid);
-
- p = NODE_DATA(nid);
-
- if (p->node_spanned_pages) {
- unsigned long paddr = node_masks[nid].bootmem_paddr;
- unsigned long end_pfn;
-
- end_pfn = p->node_start_pfn + p->node_spanned_pages;
-
- numadbg(" init_bootmem_node(%d, %lx, %lx, %lx)\n",
- nid, paddr >> PAGE_SHIFT, p->node_start_pfn, end_pfn);
-
- init_bootmem_node(p, paddr >> PAGE_SHIFT,
- p->node_start_pfn, end_pfn);
-
- numadbg(" free_bootmem_with_active_regions(%d, %lx)\n",
- nid, end_pfn);
- free_bootmem_with_active_regions(nid, end_pfn);
-
- trim_reserved_in_node(nid);
-
- numadbg(" sparse_memory_present_with_active_regions(%d)\n",
- nid);
- sparse_memory_present_with_active_regions(nid);
- }
-}
-
static unsigned long __init bootmem_init(unsigned long phys_base)
{
unsigned long end_pfn;
- int nid;
end_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT;
max_pfn = max_low_pfn = end_pfn;
@@ -1369,11 +1285,12 @@ static unsigned long __init bootmem_init(unsigned long phys_base)
if (bootmem_init_numa() < 0)
bootmem_init_nonnuma();
- /* XXX cpu notifier XXX */
+ /* Dump memblock with node info. */
+ memblock_dump_all();
- for_each_online_node(nid)
- bootmem_init_one_node(nid);
+ /* XXX cpu notifier XXX */
+ sparse_memory_present_with_active_regions(MAX_NUMNODES);
sparse_init();
return end_pfn;
@@ -1701,6 +1618,7 @@ void __init paging_init(void)
{
unsigned long end_pfn, shift, phys_base;
unsigned long real_end, i;
+ int node;
/* These build time checkes make sure that the dcache_dirty_cpu()
* page->flags usage will work.
@@ -1826,22 +1744,24 @@ void __init paging_init(void)
#endif
}
+ /* Setup bootmem... */
+ last_valid_pfn = end_pfn = bootmem_init(phys_base);
+
/* Once the OF device tree and MDESC have been setup, we know
* the list of possible cpus. Therefore we can allocate the
* IRQ stacks.
*/
for_each_possible_cpu(i) {
- /* XXX Use node local allocations... XXX */
- softirq_stack[i] = __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
- hardirq_stack[i] = __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
- }
+ node = cpu_to_node(i);
- /* Setup bootmem... */
- last_valid_pfn = end_pfn = bootmem_init(phys_base);
+ softirq_stack[i] = __alloc_bootmem_node(NODE_DATA(node),
+ THREAD_SIZE,
+ THREAD_SIZE, 0);
+ hardirq_stack[i] = __alloc_bootmem_node(NODE_DATA(node),
+ THREAD_SIZE,
+ THREAD_SIZE, 0);
+ }
-#ifndef CONFIG_NEED_MULTIPLE_NODES
- max_mapnr = last_valid_pfn;
-#endif
kernel_physical_mapping_init();
{
@@ -1973,6 +1893,7 @@ void __init mem_init(void)
free_all_bootmem_node(NODE_DATA(i));
}
}
+ totalram_pages += free_low_memory_core_early(MAX_NUMNODES);
}
#else
totalram_pages = free_all_bootmem();
diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c
index fc58c3e917df..eb99862e9654 100644
--- a/arch/sparc/mm/io-unit.c
+++ b/arch/sparc/mm/io-unit.c
@@ -197,7 +197,7 @@ static void iounit_release_scsi_sgl(struct device *dev, struct scatterlist *sg,
}
#ifdef CONFIG_SBUS
-static int iounit_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va, __u32 addr, int len)
+static int iounit_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va, unsigned long addr, int len)
{
struct iounit_struct *iounit = dev->archdata.iommu;
unsigned long page, end;
@@ -242,29 +242,18 @@ static void iounit_unmap_dma_area(struct device *dev, unsigned long addr, int le
}
#endif
-static char *iounit_lockarea(char *vaddr, unsigned long len)
-{
-/* FIXME: Write this */
- return vaddr;
-}
-
-static void iounit_unlockarea(char *vaddr, unsigned long len)
-{
-/* FIXME: Write this */
-}
+static const struct sparc32_dma_ops iounit_dma_ops = {
+ .get_scsi_one = iounit_get_scsi_one,
+ .get_scsi_sgl = iounit_get_scsi_sgl,
+ .release_scsi_one = iounit_release_scsi_one,
+ .release_scsi_sgl = iounit_release_scsi_sgl,
+#ifdef CONFIG_SBUS
+ .map_dma_area = iounit_map_dma_area,
+ .unmap_dma_area = iounit_unmap_dma_area,
+#endif
+};
void __init ld_mmu_iounit(void)
{
- BTFIXUPSET_CALL(mmu_lockarea, iounit_lockarea, BTFIXUPCALL_RETO0);
- BTFIXUPSET_CALL(mmu_unlockarea, iounit_unlockarea, BTFIXUPCALL_NOP);
-
- BTFIXUPSET_CALL(mmu_get_scsi_one, iounit_get_scsi_one, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_get_scsi_sgl, iounit_get_scsi_sgl, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_release_scsi_one, iounit_release_scsi_one, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_release_scsi_sgl, iounit_release_scsi_sgl, BTFIXUPCALL_NORM);
-
-#ifdef CONFIG_SBUS
- BTFIXUPSET_CALL(mmu_map_dma_area, iounit_map_dma_area, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_unmap_dma_area, iounit_unmap_dma_area, BTFIXUPCALL_NORM);
-#endif
+ sparc32_dma_ops = &iounit_dma_ops;
}
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index 07fc6a65d9b6..a8a58cad9d2b 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -39,8 +39,6 @@
/* srmmu.c */
extern int viking_mxcc_present;
-BTFIXUPDEF_CALL(void, flush_page_for_dma, unsigned long)
-#define flush_page_for_dma(page) BTFIXUP_CALL(flush_page_for_dma)(page)
extern int flush_page_for_dma_global;
static int viking_flush;
/* viking.S */
@@ -143,7 +141,6 @@ static int __init iommu_init(void)
subsys_initcall(iommu_init);
-/* This begs to be btfixup-ed by srmmu. */
/* Flush the iotlb entries to ram. */
/* This could be better if we didn't have to flush whole pages. */
static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte)
@@ -216,11 +213,6 @@ static u32 iommu_get_scsi_one(struct device *dev, char *vaddr, unsigned int len)
return busa + off;
}
-static __u32 iommu_get_scsi_one_noflush(struct device *dev, char *vaddr, unsigned long len)
-{
- return iommu_get_scsi_one(dev, vaddr, len);
-}
-
static __u32 iommu_get_scsi_one_gflush(struct device *dev, char *vaddr, unsigned long len)
{
flush_page_for_dma(0);
@@ -238,19 +230,6 @@ static __u32 iommu_get_scsi_one_pflush(struct device *dev, char *vaddr, unsigned
return iommu_get_scsi_one(dev, vaddr, len);
}
-static void iommu_get_scsi_sgl_noflush(struct device *dev, struct scatterlist *sg, int sz)
-{
- int n;
-
- while (sz != 0) {
- --sz;
- n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT;
- sg->dma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset;
- sg->dma_length = sg->length;
- sg = sg_next(sg);
- }
-}
-
static void iommu_get_scsi_sgl_gflush(struct device *dev, struct scatterlist *sg, int sz)
{
int n;
@@ -426,40 +405,36 @@ static void iommu_unmap_dma_area(struct device *dev, unsigned long busa, int len
}
#endif
-static char *iommu_lockarea(char *vaddr, unsigned long len)
-{
- return vaddr;
-}
+static const struct sparc32_dma_ops iommu_dma_gflush_ops = {
+ .get_scsi_one = iommu_get_scsi_one_gflush,
+ .get_scsi_sgl = iommu_get_scsi_sgl_gflush,
+ .release_scsi_one = iommu_release_scsi_one,
+ .release_scsi_sgl = iommu_release_scsi_sgl,
+#ifdef CONFIG_SBUS
+ .map_dma_area = iommu_map_dma_area,
+ .unmap_dma_area = iommu_unmap_dma_area,
+#endif
+};
-static void iommu_unlockarea(char *vaddr, unsigned long len)
-{
-}
+static const struct sparc32_dma_ops iommu_dma_pflush_ops = {
+ .get_scsi_one = iommu_get_scsi_one_pflush,
+ .get_scsi_sgl = iommu_get_scsi_sgl_pflush,
+ .release_scsi_one = iommu_release_scsi_one,
+ .release_scsi_sgl = iommu_release_scsi_sgl,
+#ifdef CONFIG_SBUS
+ .map_dma_area = iommu_map_dma_area,
+ .unmap_dma_area = iommu_unmap_dma_area,
+#endif
+};
void __init ld_mmu_iommu(void)
{
- viking_flush = (BTFIXUPVAL_CALL(flush_page_for_dma) == (unsigned long)viking_flush_page);
- BTFIXUPSET_CALL(mmu_lockarea, iommu_lockarea, BTFIXUPCALL_RETO0);
- BTFIXUPSET_CALL(mmu_unlockarea, iommu_unlockarea, BTFIXUPCALL_NOP);
-
- if (!BTFIXUPVAL_CALL(flush_page_for_dma)) {
- /* IO coherent chip */
- BTFIXUPSET_CALL(mmu_get_scsi_one, iommu_get_scsi_one_noflush, BTFIXUPCALL_RETO0);
- BTFIXUPSET_CALL(mmu_get_scsi_sgl, iommu_get_scsi_sgl_noflush, BTFIXUPCALL_NORM);
- } else if (flush_page_for_dma_global) {
+ if (flush_page_for_dma_global) {
/* flush_page_for_dma flushes everything, no matter of what page is it */
- BTFIXUPSET_CALL(mmu_get_scsi_one, iommu_get_scsi_one_gflush, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_get_scsi_sgl, iommu_get_scsi_sgl_gflush, BTFIXUPCALL_NORM);
+ sparc32_dma_ops = &iommu_dma_gflush_ops;
} else {
- BTFIXUPSET_CALL(mmu_get_scsi_one, iommu_get_scsi_one_pflush, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_get_scsi_sgl, iommu_get_scsi_sgl_pflush, BTFIXUPCALL_NORM);
+ sparc32_dma_ops = &iommu_dma_pflush_ops;
}
- BTFIXUPSET_CALL(mmu_release_scsi_one, iommu_release_scsi_one, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_release_scsi_sgl, iommu_release_scsi_sgl, BTFIXUPCALL_NORM);
-
-#ifdef CONFIG_SBUS
- BTFIXUPSET_CALL(mmu_map_dma_area, iommu_map_dma_area, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_unmap_dma_area, iommu_unmap_dma_area, BTFIXUPCALL_NORM);
-#endif
if (viking_mxcc_present || srmmu_modtype == HyperSparc) {
dvma_prot = __pgprot(SRMMU_CACHE | SRMMU_ET_PTE | SRMMU_PRIV);
diff --git a/arch/sparc/mm/leon_mm.c b/arch/sparc/mm/leon_mm.c
index 13c2169822a8..4c67ae6e5023 100644
--- a/arch/sparc/mm/leon_mm.c
+++ b/arch/sparc/mm/leon_mm.c
@@ -15,9 +15,23 @@
#include <asm/leon.h>
#include <asm/tlbflush.h>
+#include "srmmu.h"
+
int leon_flush_during_switch = 1;
int srmmu_swprobe_trace;
+static inline unsigned long leon_get_ctable_ptr(void)
+{
+ unsigned int retval;
+
+ __asm__ __volatile__("lda [%1] %2, %0\n\t" :
+ "=r" (retval) :
+ "r" (SRMMU_CTXTBL_PTR),
+ "i" (ASI_LEON_MMUREGS));
+ return (retval & SRMMU_CTX_PMASK) << 4;
+}
+
+
unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr)
{
@@ -33,10 +47,10 @@ unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr)
if (srmmu_swprobe_trace)
printk(KERN_INFO "swprobe: trace on\n");
- ctxtbl = srmmu_get_ctable_ptr();
+ ctxtbl = leon_get_ctable_ptr();
if (!(ctxtbl)) {
if (srmmu_swprobe_trace)
- printk(KERN_INFO "swprobe: srmmu_get_ctable_ptr returned 0=>0\n");
+ printk(KERN_INFO "swprobe: leon_get_ctable_ptr returned 0=>0\n");
return 0;
}
if (!_pfn_valid(PFN(ctxtbl))) {
@@ -258,3 +272,80 @@ void leon_switch_mm(void)
if (leon_flush_during_switch)
leon_flush_cache_all();
}
+
+static void leon_flush_cache_mm(struct mm_struct *mm)
+{
+ leon_flush_cache_all();
+}
+
+static void leon_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
+{
+ leon_flush_pcache_all(vma, page);
+}
+
+static void leon_flush_cache_range(struct vm_area_struct *vma,
+ unsigned long start,
+ unsigned long end)
+{
+ leon_flush_cache_all();
+}
+
+static void leon_flush_tlb_mm(struct mm_struct *mm)
+{
+ leon_flush_tlb_all();
+}
+
+static void leon_flush_tlb_page(struct vm_area_struct *vma,
+ unsigned long page)
+{
+ leon_flush_tlb_all();
+}
+
+static void leon_flush_tlb_range(struct vm_area_struct *vma,
+ unsigned long start,
+ unsigned long end)
+{
+ leon_flush_tlb_all();
+}
+
+static void leon_flush_page_to_ram(unsigned long page)
+{
+ leon_flush_cache_all();
+}
+
+static void leon_flush_sig_insns(struct mm_struct *mm, unsigned long page)
+{
+ leon_flush_cache_all();
+}
+
+static void leon_flush_page_for_dma(unsigned long page)
+{
+ leon_flush_dcache_all();
+}
+
+void __init poke_leonsparc(void)
+{
+}
+
+static const struct sparc32_cachetlb_ops leon_ops = {
+ .cache_all = leon_flush_cache_all,
+ .cache_mm = leon_flush_cache_mm,
+ .cache_page = leon_flush_cache_page,
+ .cache_range = leon_flush_cache_range,
+ .tlb_all = leon_flush_tlb_all,
+ .tlb_mm = leon_flush_tlb_mm,
+ .tlb_page = leon_flush_tlb_page,
+ .tlb_range = leon_flush_tlb_range,
+ .page_to_ram = leon_flush_page_to_ram,
+ .sig_insns = leon_flush_sig_insns,
+ .page_for_dma = leon_flush_page_for_dma,
+};
+
+void __init init_leon(void)
+{
+ srmmu_name = "LEON";
+ sparc32_cachetlb_ops = &leon_ops;
+ poke_srmmu = poke_leonsparc;
+
+ leon_flush_during_switch = leon_flush_needed();
+}
diff --git a/arch/sparc/mm/loadmmu.c b/arch/sparc/mm/loadmmu.c
deleted file mode 100644
index c5bf2a6c3858..000000000000
--- a/arch/sparc/mm/loadmmu.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * loadmmu.c: This code loads up all the mm function pointers once the
- * machine type has been determined. It also sets the static
- * mmu values such as PAGE_NONE, etc.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/mmu_context.h>
-#include <asm/oplib.h>
-
-struct ctx_list *ctx_list_pool;
-struct ctx_list ctx_free;
-struct ctx_list ctx_used;
-
-extern void ld_mmu_sun4c(void);
-extern void ld_mmu_srmmu(void);
-
-void __init load_mmu(void)
-{
- switch(sparc_cpu_model) {
- case sun4c:
- case sun4:
- ld_mmu_sun4c();
- break;
- case sun4m:
- case sun4d:
- case sparc_leon:
- ld_mmu_srmmu();
- break;
- default:
- prom_printf("load_mmu: %d unsupported\n", (int)sparc_cpu_model);
- prom_halt();
- }
- btfixup();
-}
diff --git a/arch/sparc/mm/nosun4c.c b/arch/sparc/mm/nosun4c.c
deleted file mode 100644
index 4e62c27147c4..000000000000
--- a/arch/sparc/mm/nosun4c.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * nosun4c.c: This file is a bunch of dummies for SMP compiles,
- * so that it does not need sun4c and avoid ifdefs.
- *
- * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <asm/pgtable.h>
-
-static char shouldnothappen[] __initdata = "32bit SMP kernel only supports sun4m and sun4d\n";
-
-/* Dummies */
-struct sun4c_mmu_ring {
- unsigned long xxx1[3];
- unsigned char xxx2[2];
- int xxx3;
-};
-struct sun4c_mmu_ring sun4c_kernel_ring;
-struct sun4c_mmu_ring sun4c_kfree_ring;
-unsigned long sun4c_kernel_faults;
-unsigned long *sun4c_memerr_reg;
-
-static void __init should_not_happen(void)
-{
- prom_printf(shouldnothappen);
- prom_halt();
-}
-
-unsigned long __init sun4c_paging_init(unsigned long start_mem, unsigned long end_mem)
-{
- should_not_happen();
- return 0;
-}
-
-void __init ld_mmu_sun4c(void)
-{
- should_not_happen();
-}
-
-void sun4c_mapioaddr(unsigned long physaddr, unsigned long virt_addr, int bus_type, int rdonly)
-{
-}
-
-void sun4c_unmapioaddr(unsigned long virt_addr)
-{
-}
-
-void sun4c_complete_all_stores(void)
-{
-}
-
-pte_t *sun4c_pte_offset(pmd_t * dir, unsigned long address)
-{
- return NULL;
-}
-
-pte_t *sun4c_pte_offset_kernel(pmd_t *dir, unsigned long address)
-{
- return NULL;
-}
-
-void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
-{
-}
-
-void __init sun4c_probe_vac(void)
-{
- should_not_happen();
-}
-
-void __init sun4c_probe_memerr_reg(void)
-{
- should_not_happen();
-}
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index cbef74e793b8..8e97e0305b01 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -48,39 +48,37 @@
#include <asm/turbosparc.h>
#include <asm/leon.h>
-#include <asm/btfixup.h>
+#include "srmmu.h"
enum mbus_module srmmu_modtype;
static unsigned int hwbug_bitmask;
int vac_cache_size;
int vac_line_size;
+struct ctx_list *ctx_list_pool;
+struct ctx_list ctx_free;
+struct ctx_list ctx_used;
+
extern struct resource sparc_iomap;
extern unsigned long last_valid_pfn;
-extern unsigned long page_kernel;
-
static pgd_t *srmmu_swapper_pg_dir;
+const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops;
+
#ifdef CONFIG_SMP
+const struct sparc32_cachetlb_ops *local_ops;
+
#define FLUSH_BEGIN(mm)
#define FLUSH_END
#else
-#define FLUSH_BEGIN(mm) if((mm)->context != NO_CONTEXT) {
+#define FLUSH_BEGIN(mm) if ((mm)->context != NO_CONTEXT) {
#define FLUSH_END }
#endif
-BTFIXUPDEF_CALL(void, flush_page_for_dma, unsigned long)
-#define flush_page_for_dma(page) BTFIXUP_CALL(flush_page_for_dma)(page)
-
int flush_page_for_dma_global = 1;
-#ifdef CONFIG_SMP
-BTFIXUPDEF_CALL(void, local_flush_page_for_dma, unsigned long)
-#define local_flush_page_for_dma(page) BTFIXUP_CALL(local_flush_page_for_dma)(page)
-#endif
-
char *srmmu_name;
ctxd_t *srmmu_ctx_table_phys;
@@ -91,28 +89,6 @@ static DEFINE_SPINLOCK(srmmu_context_spinlock);
static int is_hypersparc;
-/*
- * In general all page table modifications should use the V8 atomic
- * swap instruction. This insures the mmu and the cpu are in sync
- * with respect to ref/mod bits in the page tables.
- */
-static inline unsigned long srmmu_swap(unsigned long *addr, unsigned long value)
-{
- __asm__ __volatile__("swap [%2], %0" : "=&r" (value) : "0" (value), "r" (addr));
- return value;
-}
-
-static inline void srmmu_set_pte(pte_t *ptep, pte_t pteval)
-{
- srmmu_swap((unsigned long *)ptep, pte_val(pteval));
-}
-
-/* The very generic SRMMU page table operations. */
-static inline int srmmu_device_memory(unsigned long x)
-{
- return ((x & 0xF0000000) != 0);
-}
-
static int srmmu_cache_pagetables;
/* these will be initialized in srmmu_nocache_calcsize() */
@@ -129,145 +105,39 @@ void *srmmu_nocache_pool;
void *srmmu_nocache_bitmap;
static struct bit_map srmmu_nocache_map;
-static unsigned long srmmu_pte_pfn(pte_t pte)
-{
- if (srmmu_device_memory(pte_val(pte))) {
- /* Just return something that will cause
- * pfn_valid() to return false. This makes
- * copy_one_pte() to just directly copy to
- * PTE over.
- */
- return ~0UL;
- }
- return (pte_val(pte) & SRMMU_PTE_PMASK) >> (PAGE_SHIFT-4);
-}
-
-static struct page *srmmu_pmd_page(pmd_t pmd)
-{
-
- if (srmmu_device_memory(pmd_val(pmd)))
- BUG();
- return pfn_to_page((pmd_val(pmd) & SRMMU_PTD_PMASK) >> (PAGE_SHIFT-4));
-}
-
-static inline unsigned long srmmu_pgd_page(pgd_t pgd)
-{ return srmmu_device_memory(pgd_val(pgd))?~0:(unsigned long)__nocache_va((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4); }
-
-
-static inline int srmmu_pte_none(pte_t pte)
-{ return !(pte_val(pte) & 0xFFFFFFF); }
-
-static inline int srmmu_pte_present(pte_t pte)
-{ return ((pte_val(pte) & SRMMU_ET_MASK) == SRMMU_ET_PTE); }
-
-static inline void srmmu_pte_clear(pte_t *ptep)
-{ srmmu_set_pte(ptep, __pte(0)); }
-
static inline int srmmu_pmd_none(pmd_t pmd)
{ return !(pmd_val(pmd) & 0xFFFFFFF); }
-static inline int srmmu_pmd_bad(pmd_t pmd)
-{ return (pmd_val(pmd) & SRMMU_ET_MASK) != SRMMU_ET_PTD; }
-
-static inline int srmmu_pmd_present(pmd_t pmd)
-{ return ((pmd_val(pmd) & SRMMU_ET_MASK) == SRMMU_ET_PTD); }
-
-static inline void srmmu_pmd_clear(pmd_t *pmdp) {
- int i;
- for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++)
- srmmu_set_pte((pte_t *)&pmdp->pmdv[i], __pte(0));
-}
-
-static inline int srmmu_pgd_none(pgd_t pgd)
-{ return !(pgd_val(pgd) & 0xFFFFFFF); }
-
-static inline int srmmu_pgd_bad(pgd_t pgd)
-{ return (pgd_val(pgd) & SRMMU_ET_MASK) != SRMMU_ET_PTD; }
-
-static inline int srmmu_pgd_present(pgd_t pgd)
-{ return ((pgd_val(pgd) & SRMMU_ET_MASK) == SRMMU_ET_PTD); }
-
-static inline void srmmu_pgd_clear(pgd_t * pgdp)
-{ srmmu_set_pte((pte_t *)pgdp, __pte(0)); }
-
-static inline pte_t srmmu_pte_wrprotect(pte_t pte)
-{ return __pte(pte_val(pte) & ~SRMMU_WRITE);}
-
-static inline pte_t srmmu_pte_mkclean(pte_t pte)
-{ return __pte(pte_val(pte) & ~SRMMU_DIRTY);}
-
-static inline pte_t srmmu_pte_mkold(pte_t pte)
-{ return __pte(pte_val(pte) & ~SRMMU_REF);}
-
-static inline pte_t srmmu_pte_mkwrite(pte_t pte)
-{ return __pte(pte_val(pte) | SRMMU_WRITE);}
-
-static inline pte_t srmmu_pte_mkdirty(pte_t pte)
-{ return __pte(pte_val(pte) | SRMMU_DIRTY);}
-
-static inline pte_t srmmu_pte_mkyoung(pte_t pte)
-{ return __pte(pte_val(pte) | SRMMU_REF);}
-
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-static pte_t srmmu_mk_pte(struct page *page, pgprot_t pgprot)
-{ return __pte((page_to_pfn(page) << (PAGE_SHIFT-4)) | pgprot_val(pgprot)); }
-
-static pte_t srmmu_mk_pte_phys(unsigned long page, pgprot_t pgprot)
-{ return __pte(((page) >> 4) | pgprot_val(pgprot)); }
-
-static pte_t srmmu_mk_pte_io(unsigned long page, pgprot_t pgprot, int space)
-{ return __pte(((page) >> 4) | (space << 28) | pgprot_val(pgprot)); }
-
/* XXX should we hyper_flush_whole_icache here - Anton */
static inline void srmmu_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp)
-{ srmmu_set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) pgdp) >> 4))); }
+{ set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) pgdp) >> 4))); }
-static inline void srmmu_pgd_set(pgd_t * pgdp, pmd_t * pmdp)
-{ srmmu_set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) pmdp) >> 4))); }
-
-static void srmmu_pmd_set(pmd_t *pmdp, pte_t *ptep)
+void pmd_set(pmd_t *pmdp, pte_t *ptep)
{
unsigned long ptp; /* Physical address, shifted right by 4 */
int i;
ptp = __nocache_pa((unsigned long) ptep) >> 4;
for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) {
- srmmu_set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp);
+ set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp);
ptp += (SRMMU_REAL_PTRS_PER_PTE*sizeof(pte_t) >> 4);
}
}
-static void srmmu_pmd_populate(pmd_t *pmdp, struct page *ptep)
+void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep)
{
unsigned long ptp; /* Physical address, shifted right by 4 */
int i;
ptp = page_to_pfn(ptep) << (PAGE_SHIFT-4); /* watch for overflow */
for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) {
- srmmu_set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp);
+ set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp);
ptp += (SRMMU_REAL_PTRS_PER_PTE*sizeof(pte_t) >> 4);
}
}
-static inline pte_t srmmu_pte_modify(pte_t pte, pgprot_t newprot)
-{ return __pte((pte_val(pte) & SRMMU_CHG_MASK) | pgprot_val(newprot)); }
-
-/* to find an entry in a top-level page table... */
-static inline pgd_t *srmmu_pgd_offset(struct mm_struct * mm, unsigned long address)
-{ return mm->pgd + (address >> SRMMU_PGDIR_SHIFT); }
-
-/* Find an entry in the second-level page table.. */
-static inline pmd_t *srmmu_pmd_offset(pgd_t * dir, unsigned long address)
-{
- return (pmd_t *) srmmu_pgd_page(*dir) +
- ((address >> PMD_SHIFT) & (PTRS_PER_PMD - 1));
-}
-
/* Find an entry in the third-level page table.. */
-static inline pte_t *srmmu_pte_offset(pmd_t * dir, unsigned long address)
+pte_t *pte_offset_kernel(pmd_t * dir, unsigned long address)
{
void *pte;
@@ -276,23 +146,6 @@ static inline pte_t *srmmu_pte_offset(pmd_t * dir, unsigned long address)
((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
}
-static unsigned long srmmu_swp_type(swp_entry_t entry)
-{
- return (entry.val >> SRMMU_SWP_TYPE_SHIFT) & SRMMU_SWP_TYPE_MASK;
-}
-
-static unsigned long srmmu_swp_offset(swp_entry_t entry)
-{
- return (entry.val >> SRMMU_SWP_OFF_SHIFT) & SRMMU_SWP_OFF_MASK;
-}
-
-static swp_entry_t srmmu_swp_entry(unsigned long type, unsigned long offset)
-{
- return (swp_entry_t) {
- (type & SRMMU_SWP_TYPE_MASK) << SRMMU_SWP_TYPE_SHIFT
- | (offset & SRMMU_SWP_OFF_MASK) << SRMMU_SWP_OFF_SHIFT };
-}
-
/*
* size: bytes to allocate in the nocache area.
* align: bytes, number to align at.
@@ -325,7 +178,7 @@ static unsigned long __srmmu_get_nocache(int size, int align)
return (SRMMU_NOCACHE_VADDR + (offset << SRMMU_NOCACHE_BITMAP_SHIFT));
}
-static unsigned long srmmu_get_nocache(int size, int align)
+unsigned long srmmu_get_nocache(int size, int align)
{
unsigned long tmp;
@@ -337,7 +190,7 @@ static unsigned long srmmu_get_nocache(int size, int align)
return tmp;
}
-static void srmmu_free_nocache(unsigned long vaddr, int size)
+void srmmu_free_nocache(unsigned long vaddr, int size)
{
int offset;
@@ -429,15 +282,15 @@ static void __init srmmu_nocache_init(void)
while (vaddr < srmmu_nocache_end) {
pgd = pgd_offset_k(vaddr);
- pmd = srmmu_pmd_offset(__nocache_fix(pgd), vaddr);
- pte = srmmu_pte_offset(__nocache_fix(pmd), vaddr);
+ pmd = pmd_offset(__nocache_fix(pgd), vaddr);
+ pte = pte_offset_kernel(__nocache_fix(pmd), vaddr);
pteval = ((paddr >> 4) | SRMMU_ET_PTE | SRMMU_PRIV);
if (srmmu_cache_pagetables)
pteval |= SRMMU_CACHE;
- srmmu_set_pte(__nocache_fix(pte), __pte(pteval));
+ set_pte(__nocache_fix(pte), __pte(pteval));
vaddr += PAGE_SIZE;
paddr += PAGE_SIZE;
@@ -447,7 +300,7 @@ static void __init srmmu_nocache_init(void)
flush_tlb_all();
}
-static inline pgd_t *srmmu_get_pgd_fast(void)
+pgd_t *get_pgd_fast(void)
{
pgd_t *pgd = NULL;
@@ -462,21 +315,6 @@ static inline pgd_t *srmmu_get_pgd_fast(void)
return pgd;
}
-static void srmmu_free_pgd_fast(pgd_t *pgd)
-{
- srmmu_free_nocache((unsigned long)pgd, SRMMU_PGD_TABLE_SIZE);
-}
-
-static pmd_t *srmmu_pmd_alloc_one(struct mm_struct *mm, unsigned long address)
-{
- return (pmd_t *)srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE);
-}
-
-static void srmmu_pmd_free(pmd_t * pmd)
-{
- srmmu_free_nocache((unsigned long)pmd, SRMMU_PMD_TABLE_SIZE);
-}
-
/*
* Hardware needs alignment to 256 only, but we align to whole page size
* to reduce fragmentation problems due to the buddy principle.
@@ -485,31 +323,19 @@ static void srmmu_pmd_free(pmd_t * pmd)
* Alignments up to the page size are the same for physical and virtual
* addresses of the nocache area.
*/
-static pte_t *
-srmmu_pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
-{
- return (pte_t *)srmmu_get_nocache(PTE_SIZE, PTE_SIZE);
-}
-
-static pgtable_t
-srmmu_pte_alloc_one(struct mm_struct *mm, unsigned long address)
+pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
unsigned long pte;
struct page *page;
- if ((pte = (unsigned long)srmmu_pte_alloc_one_kernel(mm, address)) == 0)
+ if ((pte = (unsigned long)pte_alloc_one_kernel(mm, address)) == 0)
return NULL;
page = pfn_to_page( __nocache_pa(pte) >> PAGE_SHIFT );
pgtable_page_ctor(page);
return page;
}
-static void srmmu_free_pte_fast(pte_t *pte)
-{
- srmmu_free_nocache((unsigned long)pte, PTE_SIZE);
-}
-
-static void srmmu_pte_free(pgtable_t pte)
+void pte_free(struct mm_struct *mm, pgtable_t pte)
{
unsigned long p;
@@ -560,8 +386,8 @@ static inline void free_context(int context)
}
-static void srmmu_switch_mm(struct mm_struct *old_mm, struct mm_struct *mm,
- struct task_struct *tsk, int cpu)
+void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm,
+ struct task_struct *tsk)
{
if(mm->context == NO_CONTEXT) {
spin_lock(&srmmu_context_spinlock);
@@ -590,8 +416,8 @@ static inline void srmmu_mapioaddr(unsigned long physaddr,
physaddr &= PAGE_MASK;
pgdp = pgd_offset_k(virt_addr);
- pmdp = srmmu_pmd_offset(pgdp, virt_addr);
- ptep = srmmu_pte_offset(pmdp, virt_addr);
+ pmdp = pmd_offset(pgdp, virt_addr);
+ ptep = pte_offset_kernel(pmdp, virt_addr);
tmp = (physaddr >> 4) | SRMMU_ET_PTE;
/*
@@ -602,11 +428,11 @@ static inline void srmmu_mapioaddr(unsigned long physaddr,
tmp |= (bus_type << 28);
tmp |= SRMMU_PRIV;
__flush_page_to_ram(virt_addr);
- srmmu_set_pte(ptep, __pte(tmp));
+ set_pte(ptep, __pte(tmp));
}
-static void srmmu_mapiorange(unsigned int bus, unsigned long xpa,
- unsigned long xva, unsigned int len)
+void srmmu_mapiorange(unsigned int bus, unsigned long xpa,
+ unsigned long xva, unsigned int len)
{
while (len != 0) {
len -= PAGE_SIZE;
@@ -624,14 +450,14 @@ static inline void srmmu_unmapioaddr(unsigned long virt_addr)
pte_t *ptep;
pgdp = pgd_offset_k(virt_addr);
- pmdp = srmmu_pmd_offset(pgdp, virt_addr);
- ptep = srmmu_pte_offset(pmdp, virt_addr);
+ pmdp = pmd_offset(pgdp, virt_addr);
+ ptep = pte_offset_kernel(pmdp, virt_addr);
/* No need to flush uncacheable page. */
- srmmu_pte_clear(ptep);
+ __pte_clear(ptep);
}
-static void srmmu_unmapiorange(unsigned long virt_addr, unsigned int len)
+void srmmu_unmapiorange(unsigned long virt_addr, unsigned int len)
{
while (len != 0) {
len -= PAGE_SIZE;
@@ -647,10 +473,9 @@ static void srmmu_unmapiorange(unsigned long virt_addr, unsigned int len)
* pool. As a side effect we are putting a little too much pressure
* on the gfp() subsystem. This setup also makes the logic of the
* iommu mapping code a lot easier as we can transparently handle
- * mappings on the kernel stack without any special code as we did
- * need on the sun4c.
+ * mappings on the kernel stack without any special code.
*/
-static struct thread_info *srmmu_alloc_thread_info_node(int node)
+struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
{
struct thread_info *ret;
@@ -664,7 +489,7 @@ static struct thread_info *srmmu_alloc_thread_info_node(int node)
return ret;
}
-static void srmmu_free_thread_info(struct thread_info *ti)
+void free_thread_info(struct thread_info *ti)
{
free_pages((unsigned long)ti, THREAD_INFO_ORDER);
}
@@ -683,38 +508,6 @@ extern void tsunami_flush_tlb_range(struct vm_area_struct *vma, unsigned long st
extern void tsunami_flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
extern void tsunami_setup_blockops(void);
-/*
- * Workaround, until we find what's going on with Swift. When low on memory,
- * it sometimes loops in fault/handle_mm_fault incl. flush_tlb_page to find
- * out it is already in page tables/ fault again on the same instruction.
- * I really don't understand it, have checked it and contexts
- * are right, flush_tlb_all is done as well, and it faults again...
- * Strange. -jj
- *
- * The following code is a deadwood that may be necessary when
- * we start to make precise page flushes again. --zaitcev
- */
-static void swift_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t *ptep)
-{
-#if 0
- static unsigned long last;
- unsigned int val;
- /* unsigned int n; */
-
- if (address == last) {
- val = srmmu_hwprobe(address);
- if (val != 0 && pte_val(*ptep) != val) {
- printk("swift_update_mmu_cache: "
- "addr %lx put %08x probed %08x from %p\n",
- address, pte_val(*ptep), val,
- __builtin_return_address(0));
- srmmu_flush_whole_tlb();
- }
- }
- last = address;
-#endif
-}
-
/* swift.S */
extern void swift_flush_cache_all(void);
extern void swift_flush_cache_mm(struct mm_struct *mm);
@@ -767,244 +560,6 @@ void swift_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
* with respect to cache coherency.
*/
-/* Cypress flushes. */
-static void cypress_flush_cache_all(void)
-{
- volatile unsigned long cypress_sucks;
- unsigned long faddr, tagval;
-
- flush_user_windows();
- for(faddr = 0; faddr < 0x10000; faddr += 0x20) {
- __asm__ __volatile__("lda [%1 + %2] %3, %0\n\t" :
- "=r" (tagval) :
- "r" (faddr), "r" (0x40000),
- "i" (ASI_M_DATAC_TAG));
-
- /* If modified and valid, kick it. */
- if((tagval & 0x60) == 0x60)
- cypress_sucks = *(unsigned long *)(0xf0020000 + faddr);
- }
-}
-
-static void cypress_flush_cache_mm(struct mm_struct *mm)
-{
- register unsigned long a, b, c, d, e, f, g;
- unsigned long flags, faddr;
- int octx;
-
- FLUSH_BEGIN(mm)
- flush_user_windows();
- local_irq_save(flags);
- octx = srmmu_get_context();
- srmmu_set_context(mm->context);
- a = 0x20; b = 0x40; c = 0x60;
- d = 0x80; e = 0xa0; f = 0xc0; g = 0xe0;
-
- faddr = (0x10000 - 0x100);
- goto inside;
- do {
- faddr -= 0x100;
- inside:
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
- "sta %%g0, [%0 + %2] %1\n\t"
- "sta %%g0, [%0 + %3] %1\n\t"
- "sta %%g0, [%0 + %4] %1\n\t"
- "sta %%g0, [%0 + %5] %1\n\t"
- "sta %%g0, [%0 + %6] %1\n\t"
- "sta %%g0, [%0 + %7] %1\n\t"
- "sta %%g0, [%0 + %8] %1\n\t" : :
- "r" (faddr), "i" (ASI_M_FLUSH_CTX),
- "r" (a), "r" (b), "r" (c), "r" (d),
- "r" (e), "r" (f), "r" (g));
- } while(faddr);
- srmmu_set_context(octx);
- local_irq_restore(flags);
- FLUSH_END
-}
-
-static void cypress_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
- register unsigned long a, b, c, d, e, f, g;
- unsigned long flags, faddr;
- int octx;
-
- FLUSH_BEGIN(mm)
- flush_user_windows();
- local_irq_save(flags);
- octx = srmmu_get_context();
- srmmu_set_context(mm->context);
- a = 0x20; b = 0x40; c = 0x60;
- d = 0x80; e = 0xa0; f = 0xc0; g = 0xe0;
-
- start &= SRMMU_REAL_PMD_MASK;
- while(start < end) {
- faddr = (start + (0x10000 - 0x100));
- goto inside;
- do {
- faddr -= 0x100;
- inside:
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
- "sta %%g0, [%0 + %2] %1\n\t"
- "sta %%g0, [%0 + %3] %1\n\t"
- "sta %%g0, [%0 + %4] %1\n\t"
- "sta %%g0, [%0 + %5] %1\n\t"
- "sta %%g0, [%0 + %6] %1\n\t"
- "sta %%g0, [%0 + %7] %1\n\t"
- "sta %%g0, [%0 + %8] %1\n\t" : :
- "r" (faddr),
- "i" (ASI_M_FLUSH_SEG),
- "r" (a), "r" (b), "r" (c), "r" (d),
- "r" (e), "r" (f), "r" (g));
- } while (faddr != start);
- start += SRMMU_REAL_PMD_SIZE;
- }
- srmmu_set_context(octx);
- local_irq_restore(flags);
- FLUSH_END
-}
-
-static void cypress_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
-{
- register unsigned long a, b, c, d, e, f, g;
- struct mm_struct *mm = vma->vm_mm;
- unsigned long flags, line;
- int octx;
-
- FLUSH_BEGIN(mm)
- flush_user_windows();
- local_irq_save(flags);
- octx = srmmu_get_context();
- srmmu_set_context(mm->context);
- a = 0x20; b = 0x40; c = 0x60;
- d = 0x80; e = 0xa0; f = 0xc0; g = 0xe0;
-
- page &= PAGE_MASK;
- line = (page + PAGE_SIZE) - 0x100;
- goto inside;
- do {
- line -= 0x100;
- inside:
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
- "sta %%g0, [%0 + %2] %1\n\t"
- "sta %%g0, [%0 + %3] %1\n\t"
- "sta %%g0, [%0 + %4] %1\n\t"
- "sta %%g0, [%0 + %5] %1\n\t"
- "sta %%g0, [%0 + %6] %1\n\t"
- "sta %%g0, [%0 + %7] %1\n\t"
- "sta %%g0, [%0 + %8] %1\n\t" : :
- "r" (line),
- "i" (ASI_M_FLUSH_PAGE),
- "r" (a), "r" (b), "r" (c), "r" (d),
- "r" (e), "r" (f), "r" (g));
- } while(line != page);
- srmmu_set_context(octx);
- local_irq_restore(flags);
- FLUSH_END
-}
-
-/* Cypress is copy-back, at least that is how we configure it. */
-static void cypress_flush_page_to_ram(unsigned long page)
-{
- register unsigned long a, b, c, d, e, f, g;
- unsigned long line;
-
- a = 0x20; b = 0x40; c = 0x60; d = 0x80; e = 0xa0; f = 0xc0; g = 0xe0;
- page &= PAGE_MASK;
- line = (page + PAGE_SIZE) - 0x100;
- goto inside;
- do {
- line -= 0x100;
- inside:
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
- "sta %%g0, [%0 + %2] %1\n\t"
- "sta %%g0, [%0 + %3] %1\n\t"
- "sta %%g0, [%0 + %4] %1\n\t"
- "sta %%g0, [%0 + %5] %1\n\t"
- "sta %%g0, [%0 + %6] %1\n\t"
- "sta %%g0, [%0 + %7] %1\n\t"
- "sta %%g0, [%0 + %8] %1\n\t" : :
- "r" (line),
- "i" (ASI_M_FLUSH_PAGE),
- "r" (a), "r" (b), "r" (c), "r" (d),
- "r" (e), "r" (f), "r" (g));
- } while(line != page);
-}
-
-/* Cypress is also IO cache coherent. */
-static void cypress_flush_page_for_dma(unsigned long page)
-{
-}
-
-/* Cypress has unified L2 VIPT, from which both instructions and data
- * are stored. It does not have an onboard icache of any sort, therefore
- * no flush is necessary.
- */
-static void cypress_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
-{
-}
-
-static void cypress_flush_tlb_all(void)
-{
- srmmu_flush_whole_tlb();
-}
-
-static void cypress_flush_tlb_mm(struct mm_struct *mm)
-{
- FLUSH_BEGIN(mm)
- __asm__ __volatile__(
- "lda [%0] %3, %%g5\n\t"
- "sta %2, [%0] %3\n\t"
- "sta %%g0, [%1] %4\n\t"
- "sta %%g5, [%0] %3\n"
- : /* no outputs */
- : "r" (SRMMU_CTX_REG), "r" (0x300), "r" (mm->context),
- "i" (ASI_M_MMUREGS), "i" (ASI_M_FLUSH_PROBE)
- : "g5");
- FLUSH_END
-}
-
-static void cypress_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
- unsigned long size;
-
- FLUSH_BEGIN(mm)
- start &= SRMMU_PGDIR_MASK;
- size = SRMMU_PGDIR_ALIGN(end) - start;
- __asm__ __volatile__(
- "lda [%0] %5, %%g5\n\t"
- "sta %1, [%0] %5\n"
- "1:\n\t"
- "subcc %3, %4, %3\n\t"
- "bne 1b\n\t"
- " sta %%g0, [%2 + %3] %6\n\t"
- "sta %%g5, [%0] %5\n"
- : /* no outputs */
- : "r" (SRMMU_CTX_REG), "r" (mm->context), "r" (start | 0x200),
- "r" (size), "r" (SRMMU_PGDIR_SIZE), "i" (ASI_M_MMUREGS),
- "i" (ASI_M_FLUSH_PROBE)
- : "g5", "cc");
- FLUSH_END
-}
-
-static void cypress_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
- struct mm_struct *mm = vma->vm_mm;
-
- FLUSH_BEGIN(mm)
- __asm__ __volatile__(
- "lda [%0] %3, %%g5\n\t"
- "sta %1, [%0] %3\n\t"
- "sta %%g0, [%2] %4\n\t"
- "sta %%g5, [%0] %3\n"
- : /* no outputs */
- : "r" (SRMMU_CTX_REG), "r" (mm->context), "r" (page & PAGE_MASK),
- "i" (ASI_M_MMUREGS), "i" (ASI_M_FLUSH_PROBE)
- : "g5");
- FLUSH_END
-}
-
/* viking.S */
extern void viking_flush_cache_all(void);
extern void viking_flush_cache_mm(struct mm_struct *mm);
@@ -1065,21 +620,21 @@ static void __init srmmu_early_allocate_ptable_skeleton(unsigned long start,
while(start < end) {
pgdp = pgd_offset_k(start);
- if(srmmu_pgd_none(*(pgd_t *)__nocache_fix(pgdp))) {
+ if (pgd_none(*(pgd_t *)__nocache_fix(pgdp))) {
pmdp = (pmd_t *) __srmmu_get_nocache(
SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE);
if (pmdp == NULL)
early_pgtable_allocfail("pmd");
memset(__nocache_fix(pmdp), 0, SRMMU_PMD_TABLE_SIZE);
- srmmu_pgd_set(__nocache_fix(pgdp), pmdp);
+ pgd_set(__nocache_fix(pgdp), pmdp);
}
- pmdp = srmmu_pmd_offset(__nocache_fix(pgdp), start);
+ pmdp = pmd_offset(__nocache_fix(pgdp), start);
if(srmmu_pmd_none(*(pmd_t *)__nocache_fix(pmdp))) {
ptep = (pte_t *)__srmmu_get_nocache(PTE_SIZE, PTE_SIZE);
if (ptep == NULL)
early_pgtable_allocfail("pte");
memset(__nocache_fix(ptep), 0, PTE_SIZE);
- srmmu_pmd_set(__nocache_fix(pmdp), ptep);
+ pmd_set(__nocache_fix(pmdp), ptep);
}
if (start > (0xffffffffUL - PMD_SIZE))
break;
@@ -1096,21 +651,21 @@ static void __init srmmu_allocate_ptable_skeleton(unsigned long start,
while(start < end) {
pgdp = pgd_offset_k(start);
- if(srmmu_pgd_none(*pgdp)) {
+ if (pgd_none(*pgdp)) {
pmdp = (pmd_t *)__srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE);
if (pmdp == NULL)
early_pgtable_allocfail("pmd");
memset(pmdp, 0, SRMMU_PMD_TABLE_SIZE);
- srmmu_pgd_set(pgdp, pmdp);
+ pgd_set(pgdp, pmdp);
}
- pmdp = srmmu_pmd_offset(pgdp, start);
+ pmdp = pmd_offset(pgdp, start);
if(srmmu_pmd_none(*pmdp)) {
ptep = (pte_t *) __srmmu_get_nocache(PTE_SIZE,
PTE_SIZE);
if (ptep == NULL)
early_pgtable_allocfail("pte");
memset(ptep, 0, PTE_SIZE);
- srmmu_pmd_set(pmdp, ptep);
+ pmd_set(pmdp, ptep);
}
if (start > (0xffffffffUL - PMD_SIZE))
break;
@@ -1162,21 +717,21 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
start += SRMMU_PGDIR_SIZE;
continue;
}
- if(srmmu_pgd_none(*(pgd_t *)__nocache_fix(pgdp))) {
+ if (pgd_none(*(pgd_t *)__nocache_fix(pgdp))) {
pmdp = (pmd_t *)__srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE);
if (pmdp == NULL)
early_pgtable_allocfail("pmd");
memset(__nocache_fix(pmdp), 0, SRMMU_PMD_TABLE_SIZE);
- srmmu_pgd_set(__nocache_fix(pgdp), pmdp);
+ pgd_set(__nocache_fix(pgdp), pmdp);
}
- pmdp = srmmu_pmd_offset(__nocache_fix(pgdp), start);
+ pmdp = pmd_offset(__nocache_fix(pgdp), start);
if(srmmu_pmd_none(*(pmd_t *)__nocache_fix(pmdp))) {
ptep = (pte_t *) __srmmu_get_nocache(PTE_SIZE,
PTE_SIZE);
if (ptep == NULL)
early_pgtable_allocfail("pte");
memset(__nocache_fix(ptep), 0, PTE_SIZE);
- srmmu_pmd_set(__nocache_fix(pmdp), ptep);
+ pmd_set(__nocache_fix(pmdp), ptep);
}
if(what == 1) {
/*
@@ -1190,7 +745,7 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
start += SRMMU_REAL_PMD_SIZE;
continue;
}
- ptep = srmmu_pte_offset(__nocache_fix(pmdp), start);
+ ptep = pte_offset_kernel(__nocache_fix(pmdp), start);
*(pte_t *)__nocache_fix(ptep) = __pte(prompte);
start += PAGE_SIZE;
}
@@ -1231,13 +786,6 @@ static unsigned long __init map_spbank(unsigned long vbase, int sp_entry)
return vstart;
}
-static inline void memprobe_error(char *msg)
-{
- prom_printf(msg);
- prom_printf("Halting now...\n");
- prom_halt();
-}
-
static inline void map_kernel(void)
{
int i;
@@ -1249,8 +797,6 @@ static inline void map_kernel(void)
for (i = 0; sp_banks[i].num_bytes != 0; i++) {
map_spbank((unsigned long)__va(sp_banks[i].base_addr), i);
}
-
- BTFIXUPSET_SIMM13(user_ptrs_per_pgd, PAGE_OFFSET / SRMMU_PGDIR_SIZE);
}
/* Paging initialization on the Sparc Reference MMU. */
@@ -1312,7 +858,7 @@ void __init srmmu_paging_init(void)
srmmu_set_ctable_ptr((unsigned long)srmmu_ctx_table_phys);
#ifdef CONFIG_SMP
/* Stop from hanging here... */
- local_flush_tlb_all();
+ local_ops->tlb_all();
#else
flush_tlb_all();
#endif
@@ -1326,8 +872,8 @@ void __init srmmu_paging_init(void)
srmmu_allocate_ptable_skeleton(PKMAP_BASE, PKMAP_END);
pgd = pgd_offset_k(PKMAP_BASE);
- pmd = srmmu_pmd_offset(pgd, PKMAP_BASE);
- pte = srmmu_pte_offset(pmd, PKMAP_BASE);
+ pmd = pmd_offset(pgd, PKMAP_BASE);
+ pte = pte_offset_kernel(pmd, PKMAP_BASE);
pkmap_page_table = pte;
flush_cache_all();
@@ -1359,7 +905,7 @@ void __init srmmu_paging_init(void)
}
}
-static void srmmu_mmu_info(struct seq_file *m)
+void mmu_info(struct seq_file *m)
{
seq_printf(m,
"MMU type\t: %s\n"
@@ -1372,11 +918,7 @@ static void srmmu_mmu_info(struct seq_file *m)
srmmu_nocache_map.used << SRMMU_NOCACHE_BITMAP_SHIFT);
}
-static void srmmu_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte)
-{
-}
-
-static void srmmu_destroy_context(struct mm_struct *mm)
+void destroy_context(struct mm_struct *mm)
{
if(mm->context != NO_CONTEXT) {
@@ -1474,6 +1016,20 @@ static void __cpuinit poke_hypersparc(void)
clear = srmmu_get_fstatus();
}
+static const struct sparc32_cachetlb_ops hypersparc_ops = {
+ .cache_all = hypersparc_flush_cache_all,
+ .cache_mm = hypersparc_flush_cache_mm,
+ .cache_page = hypersparc_flush_cache_page,
+ .cache_range = hypersparc_flush_cache_range,
+ .tlb_all = hypersparc_flush_tlb_all,
+ .tlb_mm = hypersparc_flush_tlb_mm,
+ .tlb_page = hypersparc_flush_tlb_page,
+ .tlb_range = hypersparc_flush_tlb_range,
+ .page_to_ram = hypersparc_flush_page_to_ram,
+ .sig_insns = hypersparc_flush_sig_insns,
+ .page_for_dma = hypersparc_flush_page_for_dma,
+};
+
static void __init init_hypersparc(void)
{
srmmu_name = "ROSS HyperSparc";
@@ -1482,118 +1038,13 @@ static void __init init_hypersparc(void)
init_vac_layout();
is_hypersparc = 1;
-
- BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_clear, srmmu_pmd_clear, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_clear, srmmu_pgd_clear, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_all, hypersparc_flush_cache_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_mm, hypersparc_flush_cache_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_range, hypersparc_flush_cache_range, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_page, hypersparc_flush_cache_page, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(flush_tlb_all, hypersparc_flush_tlb_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_mm, hypersparc_flush_tlb_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_range, hypersparc_flush_tlb_range, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_page, hypersparc_flush_tlb_page, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(__flush_page_to_ram, hypersparc_flush_page_to_ram, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_sig_insns, hypersparc_flush_sig_insns, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_page_for_dma, hypersparc_flush_page_for_dma, BTFIXUPCALL_NOP);
-
+ sparc32_cachetlb_ops = &hypersparc_ops;
poke_srmmu = poke_hypersparc;
hypersparc_setup_blockops();
}
-static void __cpuinit poke_cypress(void)
-{
- unsigned long mreg = srmmu_get_mmureg();
- unsigned long faddr, tagval;
- volatile unsigned long cypress_sucks;
- volatile unsigned long clear;
-
- clear = srmmu_get_faddr();
- clear = srmmu_get_fstatus();
-
- if (!(mreg & CYPRESS_CENABLE)) {
- for(faddr = 0x0; faddr < 0x10000; faddr += 20) {
- __asm__ __volatile__("sta %%g0, [%0 + %1] %2\n\t"
- "sta %%g0, [%0] %2\n\t" : :
- "r" (faddr), "r" (0x40000),
- "i" (ASI_M_DATAC_TAG));
- }
- } else {
- for(faddr = 0; faddr < 0x10000; faddr += 0x20) {
- __asm__ __volatile__("lda [%1 + %2] %3, %0\n\t" :
- "=r" (tagval) :
- "r" (faddr), "r" (0x40000),
- "i" (ASI_M_DATAC_TAG));
-
- /* If modified and valid, kick it. */
- if((tagval & 0x60) == 0x60)
- cypress_sucks = *(unsigned long *)
- (0xf0020000 + faddr);
- }
- }
-
- /* And one more, for our good neighbor, Mr. Broken Cypress. */
- clear = srmmu_get_faddr();
- clear = srmmu_get_fstatus();
-
- mreg |= (CYPRESS_CENABLE | CYPRESS_CMODE);
- srmmu_set_mmureg(mreg);
-}
-
-static void __init init_cypress_common(void)
-{
- init_vac_layout();
-
- BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_clear, srmmu_pmd_clear, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_clear, srmmu_pgd_clear, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_all, cypress_flush_cache_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_mm, cypress_flush_cache_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_range, cypress_flush_cache_range, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_page, cypress_flush_cache_page, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(flush_tlb_all, cypress_flush_tlb_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_mm, cypress_flush_tlb_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_page, cypress_flush_tlb_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_range, cypress_flush_tlb_range, BTFIXUPCALL_NORM);
-
-
- BTFIXUPSET_CALL(__flush_page_to_ram, cypress_flush_page_to_ram, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_sig_insns, cypress_flush_sig_insns, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(flush_page_for_dma, cypress_flush_page_for_dma, BTFIXUPCALL_NOP);
-
- poke_srmmu = poke_cypress;
-}
-
-static void __init init_cypress_604(void)
-{
- srmmu_name = "ROSS Cypress-604(UP)";
- srmmu_modtype = Cypress;
- init_cypress_common();
-}
-
-static void __init init_cypress_605(unsigned long mrev)
-{
- srmmu_name = "ROSS Cypress-605(MP)";
- if(mrev == 0xe) {
- srmmu_modtype = Cypress_vE;
- hwbug_bitmask |= HWBUG_COPYBACK_BROKEN;
- } else {
- if(mrev == 0xd) {
- srmmu_modtype = Cypress_vD;
- hwbug_bitmask |= HWBUG_ASIFLUSH_BROKEN;
- } else {
- srmmu_modtype = Cypress;
- }
- }
- init_cypress_common();
-}
-
static void __cpuinit poke_swift(void)
{
unsigned long mreg;
@@ -1617,6 +1068,20 @@ static void __cpuinit poke_swift(void)
srmmu_set_mmureg(mreg);
}
+static const struct sparc32_cachetlb_ops swift_ops = {
+ .cache_all = swift_flush_cache_all,
+ .cache_mm = swift_flush_cache_mm,
+ .cache_page = swift_flush_cache_page,
+ .cache_range = swift_flush_cache_range,
+ .tlb_all = swift_flush_tlb_all,
+ .tlb_mm = swift_flush_tlb_mm,
+ .tlb_page = swift_flush_tlb_page,
+ .tlb_range = swift_flush_tlb_range,
+ .page_to_ram = swift_flush_page_to_ram,
+ .sig_insns = swift_flush_sig_insns,
+ .page_for_dma = swift_flush_page_for_dma,
+};
+
#define SWIFT_MASKID_ADDR 0x10003018
static void __init init_swift(void)
{
@@ -1667,23 +1132,7 @@ static void __init init_swift(void)
break;
}
- BTFIXUPSET_CALL(flush_cache_all, swift_flush_cache_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_mm, swift_flush_cache_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_page, swift_flush_cache_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_range, swift_flush_cache_range, BTFIXUPCALL_NORM);
-
-
- BTFIXUPSET_CALL(flush_tlb_all, swift_flush_tlb_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_mm, swift_flush_tlb_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_page, swift_flush_tlb_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_range, swift_flush_tlb_range, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(__flush_page_to_ram, swift_flush_page_to_ram, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_sig_insns, swift_flush_sig_insns, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_page_for_dma, swift_flush_page_for_dma, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(update_mmu_cache, swift_update_mmu_cache, BTFIXUPCALL_NORM);
-
+ sparc32_cachetlb_ops = &swift_ops;
flush_page_for_dma_global = 0;
/*
@@ -1816,26 +1265,25 @@ static void __cpuinit poke_turbosparc(void)
srmmu_set_mmureg(mreg);
}
+static const struct sparc32_cachetlb_ops turbosparc_ops = {
+ .cache_all = turbosparc_flush_cache_all,
+ .cache_mm = turbosparc_flush_cache_mm,
+ .cache_page = turbosparc_flush_cache_page,
+ .cache_range = turbosparc_flush_cache_range,
+ .tlb_all = turbosparc_flush_tlb_all,
+ .tlb_mm = turbosparc_flush_tlb_mm,
+ .tlb_page = turbosparc_flush_tlb_page,
+ .tlb_range = turbosparc_flush_tlb_range,
+ .page_to_ram = turbosparc_flush_page_to_ram,
+ .sig_insns = turbosparc_flush_sig_insns,
+ .page_for_dma = turbosparc_flush_page_for_dma,
+};
+
static void __init init_turbosparc(void)
{
srmmu_name = "Fujitsu TurboSparc";
srmmu_modtype = TurboSparc;
-
- BTFIXUPSET_CALL(flush_cache_all, turbosparc_flush_cache_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_mm, turbosparc_flush_cache_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_page, turbosparc_flush_cache_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_range, turbosparc_flush_cache_range, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(flush_tlb_all, turbosparc_flush_tlb_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_mm, turbosparc_flush_tlb_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_page, turbosparc_flush_tlb_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_range, turbosparc_flush_tlb_range, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(__flush_page_to_ram, turbosparc_flush_page_to_ram, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(flush_sig_insns, turbosparc_flush_sig_insns, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(flush_page_for_dma, turbosparc_flush_page_for_dma, BTFIXUPCALL_NORM);
-
+ sparc32_cachetlb_ops = &turbosparc_ops;
poke_srmmu = poke_turbosparc;
}
@@ -1850,6 +1298,20 @@ static void __cpuinit poke_tsunami(void)
srmmu_set_mmureg(mreg);
}
+static const struct sparc32_cachetlb_ops tsunami_ops = {
+ .cache_all = tsunami_flush_cache_all,
+ .cache_mm = tsunami_flush_cache_mm,
+ .cache_page = tsunami_flush_cache_page,
+ .cache_range = tsunami_flush_cache_range,
+ .tlb_all = tsunami_flush_tlb_all,
+ .tlb_mm = tsunami_flush_tlb_mm,
+ .tlb_page = tsunami_flush_tlb_page,
+ .tlb_range = tsunami_flush_tlb_range,
+ .page_to_ram = tsunami_flush_page_to_ram,
+ .sig_insns = tsunami_flush_sig_insns,
+ .page_for_dma = tsunami_flush_page_for_dma,
+};
+
static void __init init_tsunami(void)
{
/*
@@ -1860,22 +1322,7 @@ static void __init init_tsunami(void)
srmmu_name = "TI Tsunami";
srmmu_modtype = Tsunami;
-
- BTFIXUPSET_CALL(flush_cache_all, tsunami_flush_cache_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_mm, tsunami_flush_cache_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_page, tsunami_flush_cache_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_range, tsunami_flush_cache_range, BTFIXUPCALL_NORM);
-
-
- BTFIXUPSET_CALL(flush_tlb_all, tsunami_flush_tlb_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_mm, tsunami_flush_tlb_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_page, tsunami_flush_tlb_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_range, tsunami_flush_tlb_range, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(__flush_page_to_ram, tsunami_flush_page_to_ram, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(flush_sig_insns, tsunami_flush_sig_insns, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_page_for_dma, tsunami_flush_page_for_dma, BTFIXUPCALL_NORM);
-
+ sparc32_cachetlb_ops = &tsunami_ops;
poke_srmmu = poke_tsunami;
tsunami_setup_blockops();
@@ -1886,7 +1333,7 @@ static void __cpuinit poke_viking(void)
unsigned long mreg = srmmu_get_mmureg();
static int smp_catch;
- if(viking_mxcc_present) {
+ if (viking_mxcc_present) {
unsigned long mxcc_control = mxcc_get_creg();
mxcc_control |= (MXCC_CTL_ECE | MXCC_CTL_PRE | MXCC_CTL_MCE);
@@ -1923,6 +1370,52 @@ static void __cpuinit poke_viking(void)
srmmu_set_mmureg(mreg);
}
+static struct sparc32_cachetlb_ops viking_ops = {
+ .cache_all = viking_flush_cache_all,
+ .cache_mm = viking_flush_cache_mm,
+ .cache_page = viking_flush_cache_page,
+ .cache_range = viking_flush_cache_range,
+ .tlb_all = viking_flush_tlb_all,
+ .tlb_mm = viking_flush_tlb_mm,
+ .tlb_page = viking_flush_tlb_page,
+ .tlb_range = viking_flush_tlb_range,
+ .page_to_ram = viking_flush_page_to_ram,
+ .sig_insns = viking_flush_sig_insns,
+ .page_for_dma = viking_flush_page_for_dma,
+};
+
+#ifdef CONFIG_SMP
+/* On sun4d the cpu broadcasts local TLB flushes, so we can just
+ * perform the local TLB flush and all the other cpus will see it.
+ * But, unfortunately, there is a bug in the sun4d XBUS backplane
+ * that requires that we add some synchronization to these flushes.
+ *
+ * The bug is that the fifo which keeps track of all the pending TLB
+ * broadcasts in the system is an entry or two too small, so if we
+ * have too many going at once we'll overflow that fifo and lose a TLB
+ * flush resulting in corruption.
+ *
+ * Our workaround is to take a global spinlock around the TLB flushes,
+ * which guarentees we won't ever have too many pending. It's a big
+ * hammer, but a semaphore like system to make sure we only have N TLB
+ * flushes going at once will require SMP locking anyways so there's
+ * no real value in trying any harder than this.
+ */
+static struct sparc32_cachetlb_ops viking_sun4d_smp_ops = {
+ .cache_all = viking_flush_cache_all,
+ .cache_mm = viking_flush_cache_mm,
+ .cache_page = viking_flush_cache_page,
+ .cache_range = viking_flush_cache_range,
+ .tlb_all = sun4dsmp_flush_tlb_all,
+ .tlb_mm = sun4dsmp_flush_tlb_mm,
+ .tlb_page = sun4dsmp_flush_tlb_page,
+ .tlb_range = sun4dsmp_flush_tlb_range,
+ .page_to_ram = viking_flush_page_to_ram,
+ .sig_insns = viking_flush_sig_insns,
+ .page_for_dma = viking_flush_page_for_dma,
+};
+#endif
+
static void __init init_viking(void)
{
unsigned long mreg = srmmu_get_mmureg();
@@ -1933,10 +1426,6 @@ static void __init init_viking(void)
viking_mxcc_present = 0;
msi_set_sync();
- BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_clear, srmmu_pmd_clear, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_clear, srmmu_pgd_clear, BTFIXUPCALL_NORM);
-
/*
* We need this to make sure old viking takes no hits
* on it's cache for dma snoops to workaround the
@@ -1944,84 +1433,28 @@ static void __init init_viking(void)
* This is only necessary because of the new way in
* which we use the IOMMU.
*/
- BTFIXUPSET_CALL(flush_page_for_dma, viking_flush_page, BTFIXUPCALL_NORM);
-
+ viking_ops.page_for_dma = viking_flush_page;
+#ifdef CONFIG_SMP
+ viking_sun4d_smp_ops.page_for_dma = viking_flush_page;
+#endif
flush_page_for_dma_global = 0;
} else {
srmmu_name = "TI Viking/MXCC";
viking_mxcc_present = 1;
-
srmmu_cache_pagetables = 1;
-
- /* MXCC vikings lack the DMA snooping bug. */
- BTFIXUPSET_CALL(flush_page_for_dma, viking_flush_page_for_dma, BTFIXUPCALL_NOP);
}
- BTFIXUPSET_CALL(flush_cache_all, viking_flush_cache_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_mm, viking_flush_cache_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_page, viking_flush_cache_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_range, viking_flush_cache_range, BTFIXUPCALL_NORM);
-
+ sparc32_cachetlb_ops = (const struct sparc32_cachetlb_ops *)
+ &viking_ops;
#ifdef CONFIG_SMP
- if (sparc_cpu_model == sun4d) {
- BTFIXUPSET_CALL(flush_tlb_all, sun4dsmp_flush_tlb_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_mm, sun4dsmp_flush_tlb_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_page, sun4dsmp_flush_tlb_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_range, sun4dsmp_flush_tlb_range, BTFIXUPCALL_NORM);
- } else
+ if (sparc_cpu_model == sun4d)
+ sparc32_cachetlb_ops = (const struct sparc32_cachetlb_ops *)
+ &viking_sun4d_smp_ops;
#endif
- {
- BTFIXUPSET_CALL(flush_tlb_all, viking_flush_tlb_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_mm, viking_flush_tlb_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_page, viking_flush_tlb_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_range, viking_flush_tlb_range, BTFIXUPCALL_NORM);
- }
-
- BTFIXUPSET_CALL(__flush_page_to_ram, viking_flush_page_to_ram, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(flush_sig_insns, viking_flush_sig_insns, BTFIXUPCALL_NOP);
poke_srmmu = poke_viking;
}
-#ifdef CONFIG_SPARC_LEON
-
-void __init poke_leonsparc(void)
-{
-}
-
-void __init init_leon(void)
-{
-
- srmmu_name = "LEON";
-
- BTFIXUPSET_CALL(flush_cache_all, leon_flush_cache_all,
- BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_mm, leon_flush_cache_all,
- BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_page, leon_flush_pcache_all,
- BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_range, leon_flush_cache_all,
- BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_page_for_dma, leon_flush_dcache_all,
- BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(flush_tlb_all, leon_flush_tlb_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_mm, leon_flush_tlb_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_page, leon_flush_tlb_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_range, leon_flush_tlb_all, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(__flush_page_to_ram, leon_flush_cache_all,
- BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(flush_sig_insns, leon_flush_cache_all, BTFIXUPCALL_NOP);
-
- poke_srmmu = poke_leonsparc;
-
- srmmu_cache_pagetables = 0;
-
- leon_flush_during_switch = leon_flush_needed();
-}
-#endif
-
/* Probe for the srmmu chip version. */
static void __init get_srmmu_type(void)
{
@@ -2052,22 +1485,15 @@ static void __init get_srmmu_type(void)
break;
case 0:
case 2:
- /* Uniprocessor Cypress */
- init_cypress_604();
- break;
case 10:
case 11:
case 12:
- /* _REALLY OLD_ Cypress MP chips... */
case 13:
case 14:
case 15:
- /* MP Cypress mmu/cache-controller */
- init_cypress_605(mod_rev);
- break;
default:
- /* Some other Cypress revision, assume a 605. */
- init_cypress_605(mod_rev);
+ prom_printf("Sparc-Linux Cypress support does not longer exit.\n");
+ prom_halt();
break;
}
return;
@@ -2123,203 +1549,193 @@ static void __init get_srmmu_type(void)
srmmu_is_bad();
}
-/* don't laugh, static pagetables */
-static void srmmu_check_pgt_cache(int low, int high)
+#ifdef CONFIG_SMP
+/* Local cross-calls. */
+static void smp_flush_page_for_dma(unsigned long page)
{
+ xc1((smpfunc_t) local_ops->page_for_dma, page);
+ local_ops->page_for_dma(page);
}
-extern unsigned long spwin_mmu_patchme, fwin_mmu_patchme,
- tsetup_mmu_patchme, rtrap_mmu_patchme;
-
-extern unsigned long spwin_srmmu_stackchk, srmmu_fwin_stackchk,
- tsetup_srmmu_stackchk, srmmu_rett_stackchk;
-
-extern unsigned long srmmu_fault;
-
-#define PATCH_BRANCH(insn, dest) do { \
- iaddr = &(insn); \
- daddr = &(dest); \
- *iaddr = SPARC_BRANCH((unsigned long) daddr, (unsigned long) iaddr); \
- } while(0)
-
-static void __init patch_window_trap_handlers(void)
+static void smp_flush_cache_all(void)
{
- unsigned long *iaddr, *daddr;
-
- PATCH_BRANCH(spwin_mmu_patchme, spwin_srmmu_stackchk);
- PATCH_BRANCH(fwin_mmu_patchme, srmmu_fwin_stackchk);
- PATCH_BRANCH(tsetup_mmu_patchme, tsetup_srmmu_stackchk);
- PATCH_BRANCH(rtrap_mmu_patchme, srmmu_rett_stackchk);
- PATCH_BRANCH(sparc_ttable[SP_TRAP_TFLT].inst_three, srmmu_fault);
- PATCH_BRANCH(sparc_ttable[SP_TRAP_DFLT].inst_three, srmmu_fault);
- PATCH_BRANCH(sparc_ttable[SP_TRAP_DACC].inst_three, srmmu_fault);
+ xc0((smpfunc_t) local_ops->cache_all);
+ local_ops->cache_all();
}
-#ifdef CONFIG_SMP
-/* Local cross-calls. */
-static void smp_flush_page_for_dma(unsigned long page)
+static void smp_flush_tlb_all(void)
{
- xc1((smpfunc_t) BTFIXUP_CALL(local_flush_page_for_dma), page);
- local_flush_page_for_dma(page);
+ xc0((smpfunc_t) local_ops->tlb_all);
+ local_ops->tlb_all();
}
-#endif
-
-static pte_t srmmu_pgoff_to_pte(unsigned long pgoff)
+static void smp_flush_cache_mm(struct mm_struct *mm)
{
- return __pte((pgoff << SRMMU_PTE_FILE_SHIFT) | SRMMU_FILE);
+ if (mm->context != NO_CONTEXT) {
+ cpumask_t cpu_mask;
+ cpumask_copy(&cpu_mask, mm_cpumask(mm));
+ cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
+ if (!cpumask_empty(&cpu_mask))
+ xc1((smpfunc_t) local_ops->cache_mm, (unsigned long) mm);
+ local_ops->cache_mm(mm);
+ }
}
-static unsigned long srmmu_pte_to_pgoff(pte_t pte)
+static void smp_flush_tlb_mm(struct mm_struct *mm)
{
- return pte_val(pte) >> SRMMU_PTE_FILE_SHIFT;
+ if (mm->context != NO_CONTEXT) {
+ cpumask_t cpu_mask;
+ cpumask_copy(&cpu_mask, mm_cpumask(mm));
+ cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
+ if (!cpumask_empty(&cpu_mask)) {
+ xc1((smpfunc_t) local_ops->tlb_mm, (unsigned long) mm);
+ if (atomic_read(&mm->mm_users) == 1 && current->active_mm == mm)
+ cpumask_copy(mm_cpumask(mm),
+ cpumask_of(smp_processor_id()));
+ }
+ local_ops->tlb_mm(mm);
+ }
}
-static pgprot_t srmmu_pgprot_noncached(pgprot_t prot)
+static void smp_flush_cache_range(struct vm_area_struct *vma,
+ unsigned long start,
+ unsigned long end)
{
- prot &= ~__pgprot(SRMMU_CACHE);
+ struct mm_struct *mm = vma->vm_mm;
- return prot;
+ if (mm->context != NO_CONTEXT) {
+ cpumask_t cpu_mask;
+ cpumask_copy(&cpu_mask, mm_cpumask(mm));
+ cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
+ if (!cpumask_empty(&cpu_mask))
+ xc3((smpfunc_t) local_ops->cache_range,
+ (unsigned long) vma, start, end);
+ local_ops->cache_range(vma, start, end);
+ }
}
-/* Load up routines and constants for sun4m and sun4d mmu */
-void __init ld_mmu_srmmu(void)
+static void smp_flush_tlb_range(struct vm_area_struct *vma,
+ unsigned long start,
+ unsigned long end)
{
- extern void ld_mmu_iommu(void);
- extern void ld_mmu_iounit(void);
- extern void ___xchg32_sun4md(void);
-
- BTFIXUPSET_SIMM13(pgdir_shift, SRMMU_PGDIR_SHIFT);
- BTFIXUPSET_SETHI(pgdir_size, SRMMU_PGDIR_SIZE);
- BTFIXUPSET_SETHI(pgdir_mask, SRMMU_PGDIR_MASK);
-
- BTFIXUPSET_SIMM13(ptrs_per_pmd, SRMMU_PTRS_PER_PMD);
- BTFIXUPSET_SIMM13(ptrs_per_pgd, SRMMU_PTRS_PER_PGD);
-
- BTFIXUPSET_INT(page_none, pgprot_val(SRMMU_PAGE_NONE));
- PAGE_SHARED = pgprot_val(SRMMU_PAGE_SHARED);
- BTFIXUPSET_INT(page_copy, pgprot_val(SRMMU_PAGE_COPY));
- BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY));
- BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL));
- page_kernel = pgprot_val(SRMMU_PAGE_KERNEL);
+ struct mm_struct *mm = vma->vm_mm;
- /* Functions */
- BTFIXUPSET_CALL(pgprot_noncached, srmmu_pgprot_noncached, BTFIXUPCALL_NORM);
-#ifndef CONFIG_SMP
- BTFIXUPSET_CALL(___xchg32, ___xchg32_sun4md, BTFIXUPCALL_SWAPG1G2);
-#endif
- BTFIXUPSET_CALL(do_check_pgt_cache, srmmu_check_pgt_cache, BTFIXUPCALL_NOP);
+ if (mm->context != NO_CONTEXT) {
+ cpumask_t cpu_mask;
+ cpumask_copy(&cpu_mask, mm_cpumask(mm));
+ cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
+ if (!cpumask_empty(&cpu_mask))
+ xc3((smpfunc_t) local_ops->tlb_range,
+ (unsigned long) vma, start, end);
+ local_ops->tlb_range(vma, start, end);
+ }
+}
- BTFIXUPSET_CALL(set_pte, srmmu_set_pte, BTFIXUPCALL_SWAPO0O1);
- BTFIXUPSET_CALL(switch_mm, srmmu_switch_mm, BTFIXUPCALL_NORM);
+static void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
+{
+ struct mm_struct *mm = vma->vm_mm;
- BTFIXUPSET_CALL(pte_pfn, srmmu_pte_pfn, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_page_vaddr, srmmu_pgd_page, BTFIXUPCALL_NORM);
+ if (mm->context != NO_CONTEXT) {
+ cpumask_t cpu_mask;
+ cpumask_copy(&cpu_mask, mm_cpumask(mm));
+ cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
+ if (!cpumask_empty(&cpu_mask))
+ xc2((smpfunc_t) local_ops->cache_page,
+ (unsigned long) vma, page);
+ local_ops->cache_page(vma, page);
+ }
+}
- BTFIXUPSET_CALL(pte_present, srmmu_pte_present, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_SWAPO0G0);
+static void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ struct mm_struct *mm = vma->vm_mm;
- BTFIXUPSET_CALL(pmd_bad, srmmu_pmd_bad, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_present, srmmu_pmd_present, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_clear, srmmu_pmd_clear, BTFIXUPCALL_SWAPO0G0);
+ if (mm->context != NO_CONTEXT) {
+ cpumask_t cpu_mask;
+ cpumask_copy(&cpu_mask, mm_cpumask(mm));
+ cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
+ if (!cpumask_empty(&cpu_mask))
+ xc2((smpfunc_t) local_ops->tlb_page,
+ (unsigned long) vma, page);
+ local_ops->tlb_page(vma, page);
+ }
+}
- BTFIXUPSET_CALL(pgd_none, srmmu_pgd_none, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_bad, srmmu_pgd_bad, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_present, srmmu_pgd_present, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_clear, srmmu_pgd_clear, BTFIXUPCALL_SWAPO0G0);
+static void smp_flush_page_to_ram(unsigned long page)
+{
+ /* Current theory is that those who call this are the one's
+ * who have just dirtied their cache with the pages contents
+ * in kernel space, therefore we only run this on local cpu.
+ *
+ * XXX This experiment failed, research further... -DaveM
+ */
+#if 1
+ xc1((smpfunc_t) local_ops->page_to_ram, page);
+#endif
+ local_ops->page_to_ram(page);
+}
+
+static void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
+{
+ cpumask_t cpu_mask;
+ cpumask_copy(&cpu_mask, mm_cpumask(mm));
+ cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
+ if (!cpumask_empty(&cpu_mask))
+ xc2((smpfunc_t) local_ops->sig_insns,
+ (unsigned long) mm, insn_addr);
+ local_ops->sig_insns(mm, insn_addr);
+}
+
+static struct sparc32_cachetlb_ops smp_cachetlb_ops = {
+ .cache_all = smp_flush_cache_all,
+ .cache_mm = smp_flush_cache_mm,
+ .cache_page = smp_flush_cache_page,
+ .cache_range = smp_flush_cache_range,
+ .tlb_all = smp_flush_tlb_all,
+ .tlb_mm = smp_flush_tlb_mm,
+ .tlb_page = smp_flush_tlb_page,
+ .tlb_range = smp_flush_tlb_range,
+ .page_to_ram = smp_flush_page_to_ram,
+ .sig_insns = smp_flush_sig_insns,
+ .page_for_dma = smp_flush_page_for_dma,
+};
+#endif
- BTFIXUPSET_CALL(mk_pte, srmmu_mk_pte, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mk_pte_phys, srmmu_mk_pte_phys, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mk_pte_io, srmmu_mk_pte_io, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_set, srmmu_pgd_set, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_set, srmmu_pmd_set, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_populate, srmmu_pmd_populate, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_INT(pte_modify_mask, SRMMU_CHG_MASK);
- BTFIXUPSET_CALL(pmd_offset, srmmu_pmd_offset, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_offset_kernel, srmmu_pte_offset, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(free_pte_fast, srmmu_free_pte_fast, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_free, srmmu_pte_free, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_alloc_one_kernel, srmmu_pte_alloc_one_kernel, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_alloc_one, srmmu_pte_alloc_one, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(free_pmd_fast, srmmu_pmd_free, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_alloc_one, srmmu_pmd_alloc_one, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(free_pgd_fast, srmmu_free_pgd_fast, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(get_pgd_fast, srmmu_get_pgd_fast, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_HALF(pte_writei, SRMMU_WRITE);
- BTFIXUPSET_HALF(pte_dirtyi, SRMMU_DIRTY);
- BTFIXUPSET_HALF(pte_youngi, SRMMU_REF);
- BTFIXUPSET_HALF(pte_filei, SRMMU_FILE);
- BTFIXUPSET_HALF(pte_wrprotecti, SRMMU_WRITE);
- BTFIXUPSET_HALF(pte_mkcleani, SRMMU_DIRTY);
- BTFIXUPSET_HALF(pte_mkoldi, SRMMU_REF);
- BTFIXUPSET_CALL(pte_mkwrite, srmmu_pte_mkwrite, BTFIXUPCALL_ORINT(SRMMU_WRITE));
- BTFIXUPSET_CALL(pte_mkdirty, srmmu_pte_mkdirty, BTFIXUPCALL_ORINT(SRMMU_DIRTY));
- BTFIXUPSET_CALL(pte_mkyoung, srmmu_pte_mkyoung, BTFIXUPCALL_ORINT(SRMMU_REF));
- BTFIXUPSET_CALL(update_mmu_cache, srmmu_update_mmu_cache, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(destroy_context, srmmu_destroy_context, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(sparc_mapiorange, srmmu_mapiorange, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(sparc_unmapiorange, srmmu_unmapiorange, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(__swp_type, srmmu_swp_type, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(__swp_offset, srmmu_swp_offset, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(__swp_entry, srmmu_swp_entry, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(mmu_info, srmmu_mmu_info, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(alloc_thread_info_node, srmmu_alloc_thread_info_node, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(free_thread_info, srmmu_free_thread_info, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(pte_to_pgoff, srmmu_pte_to_pgoff, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgoff_to_pte, srmmu_pgoff_to_pte, BTFIXUPCALL_NORM);
+/* Load up routines and constants for sun4m and sun4d mmu */
+void __init load_mmu(void)
+{
+ extern void ld_mmu_iommu(void);
+ extern void ld_mmu_iounit(void);
+ /* Functions */
get_srmmu_type();
- patch_window_trap_handlers();
#ifdef CONFIG_SMP
/* El switcheroo... */
+ local_ops = sparc32_cachetlb_ops;
- BTFIXUPCOPY_CALL(local_flush_cache_all, flush_cache_all);
- BTFIXUPCOPY_CALL(local_flush_cache_mm, flush_cache_mm);
- BTFIXUPCOPY_CALL(local_flush_cache_range, flush_cache_range);
- BTFIXUPCOPY_CALL(local_flush_cache_page, flush_cache_page);
- BTFIXUPCOPY_CALL(local_flush_tlb_all, flush_tlb_all);
- BTFIXUPCOPY_CALL(local_flush_tlb_mm, flush_tlb_mm);
- BTFIXUPCOPY_CALL(local_flush_tlb_range, flush_tlb_range);
- BTFIXUPCOPY_CALL(local_flush_tlb_page, flush_tlb_page);
- BTFIXUPCOPY_CALL(local_flush_page_to_ram, __flush_page_to_ram);
- BTFIXUPCOPY_CALL(local_flush_sig_insns, flush_sig_insns);
- BTFIXUPCOPY_CALL(local_flush_page_for_dma, flush_page_for_dma);
-
- BTFIXUPSET_CALL(flush_cache_all, smp_flush_cache_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_mm, smp_flush_cache_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_range, smp_flush_cache_range, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_page, smp_flush_cache_page, BTFIXUPCALL_NORM);
- if (sparc_cpu_model != sun4d &&
- sparc_cpu_model != sparc_leon) {
- BTFIXUPSET_CALL(flush_tlb_all, smp_flush_tlb_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_mm, smp_flush_tlb_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_range, smp_flush_tlb_range, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_page, smp_flush_tlb_page, BTFIXUPCALL_NORM);
+ if (sparc_cpu_model == sun4d || sparc_cpu_model == sparc_leon) {
+ smp_cachetlb_ops.tlb_all = local_ops->tlb_all;
+ smp_cachetlb_ops.tlb_mm = local_ops->tlb_mm;
+ smp_cachetlb_ops.tlb_range = local_ops->tlb_range;
+ smp_cachetlb_ops.tlb_page = local_ops->tlb_page;
}
- BTFIXUPSET_CALL(__flush_page_to_ram, smp_flush_page_to_ram, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_sig_insns, smp_flush_sig_insns, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_page_for_dma, smp_flush_page_for_dma, BTFIXUPCALL_NORM);
if (poke_srmmu == poke_viking) {
/* Avoid unnecessary cross calls. */
- BTFIXUPCOPY_CALL(flush_cache_all, local_flush_cache_all);
- BTFIXUPCOPY_CALL(flush_cache_mm, local_flush_cache_mm);
- BTFIXUPCOPY_CALL(flush_cache_range, local_flush_cache_range);
- BTFIXUPCOPY_CALL(flush_cache_page, local_flush_cache_page);
- BTFIXUPCOPY_CALL(__flush_page_to_ram, local_flush_page_to_ram);
- BTFIXUPCOPY_CALL(flush_sig_insns, local_flush_sig_insns);
- BTFIXUPCOPY_CALL(flush_page_for_dma, local_flush_page_for_dma);
+ smp_cachetlb_ops.cache_all = local_ops->cache_all;
+ smp_cachetlb_ops.cache_mm = local_ops->cache_mm;
+ smp_cachetlb_ops.cache_range = local_ops->cache_range;
+ smp_cachetlb_ops.cache_page = local_ops->cache_page;
+
+ smp_cachetlb_ops.page_to_ram = local_ops->page_to_ram;
+ smp_cachetlb_ops.sig_insns = local_ops->sig_insns;
+ smp_cachetlb_ops.page_for_dma = local_ops->page_for_dma;
}
+
+ /* It really is const after this point. */
+ sparc32_cachetlb_ops = (const struct sparc32_cachetlb_ops *)
+ &smp_cachetlb_ops;
#endif
if (sparc_cpu_model == sun4d)
diff --git a/arch/sparc/mm/srmmu.h b/arch/sparc/mm/srmmu.h
new file mode 100644
index 000000000000..5703274ccf89
--- /dev/null
+++ b/arch/sparc/mm/srmmu.h
@@ -0,0 +1,4 @@
+/* srmmu.c */
+extern char *srmmu_name;
+
+extern void (*poke_srmmu)(void);
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
deleted file mode 100644
index 1cf4f198709a..000000000000
--- a/arch/sparc/mm/sun4c.c
+++ /dev/null
@@ -1,2166 +0,0 @@
-/* sun4c.c: Doing in software what should be done in hardware.
- *
- * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
- * Copyright (C) 1996 Andrew Tridgell (Andrew.Tridgell@anu.edu.au)
- * Copyright (C) 1997-2000 Anton Blanchard (anton@samba.org)
- * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#define NR_TASK_BUCKETS 512
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/bootmem.h>
-#include <linux/highmem.h>
-#include <linux/fs.h>
-#include <linux/seq_file.h>
-#include <linux/scatterlist.h>
-#include <linux/bitmap.h>
-
-#include <asm/sections.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/vaddrs.h>
-#include <asm/idprom.h>
-#include <asm/machines.h>
-#include <asm/memreg.h>
-#include <asm/processor.h>
-#include <asm/auxio.h>
-#include <asm/io.h>
-#include <asm/oplib.h>
-#include <asm/openprom.h>
-#include <asm/mmu_context.h>
-#include <asm/highmem.h>
-#include <asm/btfixup.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
-/* Because of our dynamic kernel TLB miss strategy, and how
- * our DVMA mapping allocation works, you _MUST_:
- *
- * 1) Disable interrupts _and_ not touch any dynamic kernel
- * memory while messing with kernel MMU state. By
- * dynamic memory I mean any object which is not in
- * the kernel image itself or a thread_union (both of
- * which are locked into the MMU).
- * 2) Disable interrupts while messing with user MMU state.
- */
-
-extern int num_segmaps, num_contexts;
-
-extern unsigned long page_kernel;
-
-/* That's it, we prom_halt() on sun4c if the cache size is something other than 65536.
- * So let's save some cycles and just use that everywhere except for that bootup
- * sanity check.
- */
-#define SUN4C_VAC_SIZE 65536
-
-#define SUN4C_KERNEL_BUCKETS 32
-
-/* Flushing the cache. */
-struct sun4c_vac_props sun4c_vacinfo;
-unsigned long sun4c_kernel_faults;
-
-/* Invalidate every sun4c cache line tag. */
-static void __init sun4c_flush_all(void)
-{
- unsigned long begin, end;
-
- if (sun4c_vacinfo.on)
- panic("SUN4C: AIEEE, trying to invalidate vac while it is on.");
-
- /* Clear 'valid' bit in all cache line tags */
- begin = AC_CACHETAGS;
- end = (AC_CACHETAGS + SUN4C_VAC_SIZE);
- while (begin < end) {
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
- "r" (begin), "i" (ASI_CONTROL));
- begin += sun4c_vacinfo.linesize;
- }
-}
-
-static void sun4c_flush_context_hw(void)
-{
- unsigned long end = SUN4C_VAC_SIZE;
-
- __asm__ __volatile__(
- "1: addcc %0, -4096, %0\n\t"
- " bne 1b\n\t"
- " sta %%g0, [%0] %2"
- : "=&r" (end)
- : "0" (end), "i" (ASI_HWFLUSHCONTEXT)
- : "cc");
-}
-
-/* Must be called minimally with IRQs disabled. */
-static void sun4c_flush_segment_hw(unsigned long addr)
-{
- if (sun4c_get_segmap(addr) != invalid_segment) {
- unsigned long vac_size = SUN4C_VAC_SIZE;
-
- __asm__ __volatile__(
- "1: addcc %0, -4096, %0\n\t"
- " bne 1b\n\t"
- " sta %%g0, [%2 + %0] %3"
- : "=&r" (vac_size)
- : "0" (vac_size), "r" (addr), "i" (ASI_HWFLUSHSEG)
- : "cc");
- }
-}
-
-/* File local boot time fixups. */
-BTFIXUPDEF_CALL(void, sun4c_flush_page, unsigned long)
-BTFIXUPDEF_CALL(void, sun4c_flush_segment, unsigned long)
-BTFIXUPDEF_CALL(void, sun4c_flush_context, void)
-
-#define sun4c_flush_page(addr) BTFIXUP_CALL(sun4c_flush_page)(addr)
-#define sun4c_flush_segment(addr) BTFIXUP_CALL(sun4c_flush_segment)(addr)
-#define sun4c_flush_context() BTFIXUP_CALL(sun4c_flush_context)()
-
-/* Must be called minimally with interrupts disabled. */
-static void sun4c_flush_page_hw(unsigned long addr)
-{
- addr &= PAGE_MASK;
- if ((int)sun4c_get_pte(addr) < 0)
- __asm__ __volatile__("sta %%g0, [%0] %1"
- : : "r" (addr), "i" (ASI_HWFLUSHPAGE));
-}
-
-/* Don't inline the software version as it eats too many cache lines if expanded. */
-static void sun4c_flush_context_sw(void)
-{
- unsigned long nbytes = SUN4C_VAC_SIZE;
- unsigned long lsize = sun4c_vacinfo.linesize;
-
- __asm__ __volatile__(
- "add %2, %2, %%g1\n\t"
- "add %2, %%g1, %%g2\n\t"
- "add %2, %%g2, %%g3\n\t"
- "add %2, %%g3, %%g4\n\t"
- "add %2, %%g4, %%g5\n\t"
- "add %2, %%g5, %%o4\n\t"
- "add %2, %%o4, %%o5\n"
- "1:\n\t"
- "subcc %0, %%o5, %0\n\t"
- "sta %%g0, [%0] %3\n\t"
- "sta %%g0, [%0 + %2] %3\n\t"
- "sta %%g0, [%0 + %%g1] %3\n\t"
- "sta %%g0, [%0 + %%g2] %3\n\t"
- "sta %%g0, [%0 + %%g3] %3\n\t"
- "sta %%g0, [%0 + %%g4] %3\n\t"
- "sta %%g0, [%0 + %%g5] %3\n\t"
- "bg 1b\n\t"
- " sta %%g0, [%1 + %%o4] %3\n"
- : "=&r" (nbytes)
- : "0" (nbytes), "r" (lsize), "i" (ASI_FLUSHCTX)
- : "g1", "g2", "g3", "g4", "g5", "o4", "o5", "cc");
-}
-
-/* Don't inline the software version as it eats too many cache lines if expanded. */
-static void sun4c_flush_segment_sw(unsigned long addr)
-{
- if (sun4c_get_segmap(addr) != invalid_segment) {
- unsigned long nbytes = SUN4C_VAC_SIZE;
- unsigned long lsize = sun4c_vacinfo.linesize;
-
- __asm__ __volatile__(
- "add %2, %2, %%g1\n\t"
- "add %2, %%g1, %%g2\n\t"
- "add %2, %%g2, %%g3\n\t"
- "add %2, %%g3, %%g4\n\t"
- "add %2, %%g4, %%g5\n\t"
- "add %2, %%g5, %%o4\n\t"
- "add %2, %%o4, %%o5\n"
- "1:\n\t"
- "subcc %1, %%o5, %1\n\t"
- "sta %%g0, [%0] %6\n\t"
- "sta %%g0, [%0 + %2] %6\n\t"
- "sta %%g0, [%0 + %%g1] %6\n\t"
- "sta %%g0, [%0 + %%g2] %6\n\t"
- "sta %%g0, [%0 + %%g3] %6\n\t"
- "sta %%g0, [%0 + %%g4] %6\n\t"
- "sta %%g0, [%0 + %%g5] %6\n\t"
- "sta %%g0, [%0 + %%o4] %6\n\t"
- "bg 1b\n\t"
- " add %0, %%o5, %0\n"
- : "=&r" (addr), "=&r" (nbytes), "=&r" (lsize)
- : "0" (addr), "1" (nbytes), "2" (lsize),
- "i" (ASI_FLUSHSEG)
- : "g1", "g2", "g3", "g4", "g5", "o4", "o5", "cc");
- }
-}
-
-/* Don't inline the software version as it eats too many cache lines if expanded. */
-static void sun4c_flush_page_sw(unsigned long addr)
-{
- addr &= PAGE_MASK;
- if ((sun4c_get_pte(addr) & (_SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_VALID)) ==
- _SUN4C_PAGE_VALID) {
- unsigned long left = PAGE_SIZE;
- unsigned long lsize = sun4c_vacinfo.linesize;
-
- __asm__ __volatile__(
- "add %2, %2, %%g1\n\t"
- "add %2, %%g1, %%g2\n\t"
- "add %2, %%g2, %%g3\n\t"
- "add %2, %%g3, %%g4\n\t"
- "add %2, %%g4, %%g5\n\t"
- "add %2, %%g5, %%o4\n\t"
- "add %2, %%o4, %%o5\n"
- "1:\n\t"
- "subcc %1, %%o5, %1\n\t"
- "sta %%g0, [%0] %6\n\t"
- "sta %%g0, [%0 + %2] %6\n\t"
- "sta %%g0, [%0 + %%g1] %6\n\t"
- "sta %%g0, [%0 + %%g2] %6\n\t"
- "sta %%g0, [%0 + %%g3] %6\n\t"
- "sta %%g0, [%0 + %%g4] %6\n\t"
- "sta %%g0, [%0 + %%g5] %6\n\t"
- "sta %%g0, [%0 + %%o4] %6\n\t"
- "bg 1b\n\t"
- " add %0, %%o5, %0\n"
- : "=&r" (addr), "=&r" (left), "=&r" (lsize)
- : "0" (addr), "1" (left), "2" (lsize),
- "i" (ASI_FLUSHPG)
- : "g1", "g2", "g3", "g4", "g5", "o4", "o5", "cc");
- }
-}
-
-/* The sun4c's do have an on chip store buffer. And the way you
- * clear them out isn't so obvious. The only way I can think of
- * to accomplish this is to read the current context register,
- * store the same value there, then read an external hardware
- * register.
- */
-void sun4c_complete_all_stores(void)
-{
- volatile int _unused;
-
- _unused = sun4c_get_context();
- sun4c_set_context(_unused);
- _unused = get_auxio();
-}
-
-/* Bootup utility functions. */
-static inline void sun4c_init_clean_segmap(unsigned char pseg)
-{
- unsigned long vaddr;
-
- sun4c_put_segmap(0, pseg);
- for (vaddr = 0; vaddr < SUN4C_REAL_PGDIR_SIZE; vaddr += PAGE_SIZE)
- sun4c_put_pte(vaddr, 0);
- sun4c_put_segmap(0, invalid_segment);
-}
-
-static inline void sun4c_init_clean_mmu(unsigned long kernel_end)
-{
- unsigned long vaddr;
- unsigned char savectx, ctx;
-
- savectx = sun4c_get_context();
- for (ctx = 0; ctx < num_contexts; ctx++) {
- sun4c_set_context(ctx);
- for (vaddr = 0; vaddr < 0x20000000; vaddr += SUN4C_REAL_PGDIR_SIZE)
- sun4c_put_segmap(vaddr, invalid_segment);
- for (vaddr = 0xe0000000; vaddr < KERNBASE; vaddr += SUN4C_REAL_PGDIR_SIZE)
- sun4c_put_segmap(vaddr, invalid_segment);
- for (vaddr = kernel_end; vaddr < KADB_DEBUGGER_BEGVM; vaddr += SUN4C_REAL_PGDIR_SIZE)
- sun4c_put_segmap(vaddr, invalid_segment);
- for (vaddr = LINUX_OPPROM_ENDVM; vaddr; vaddr += SUN4C_REAL_PGDIR_SIZE)
- sun4c_put_segmap(vaddr, invalid_segment);
- }
- sun4c_set_context(savectx);
-}
-
-void __init sun4c_probe_vac(void)
-{
- sun4c_disable_vac();
-
- if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
- (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
- /* PROM on SS1 lacks this info, to be super safe we
- * hard code it here since this arch is cast in stone.
- */
- sun4c_vacinfo.num_bytes = 65536;
- sun4c_vacinfo.linesize = 16;
- } else {
- sun4c_vacinfo.num_bytes =
- prom_getintdefault(prom_root_node, "vac-size", 65536);
- sun4c_vacinfo.linesize =
- prom_getintdefault(prom_root_node, "vac-linesize", 16);
- }
- sun4c_vacinfo.do_hwflushes =
- prom_getintdefault(prom_root_node, "vac-hwflush", 0);
-
- if (sun4c_vacinfo.do_hwflushes == 0)
- sun4c_vacinfo.do_hwflushes =
- prom_getintdefault(prom_root_node, "vac_hwflush", 0);
-
- if (sun4c_vacinfo.num_bytes != 65536) {
- prom_printf("WEIRD Sun4C VAC cache size, "
- "tell sparclinux@vger.kernel.org");
- prom_halt();
- }
-
- switch (sun4c_vacinfo.linesize) {
- case 16:
- sun4c_vacinfo.log2lsize = 4;
- break;
- case 32:
- sun4c_vacinfo.log2lsize = 5;
- break;
- default:
- prom_printf("probe_vac: Didn't expect vac-linesize of %d, halting\n",
- sun4c_vacinfo.linesize);
- prom_halt();
- }
-
- sun4c_flush_all();
- sun4c_enable_vac();
-}
-
-/* Patch instructions for the low level kernel fault handler. */
-extern unsigned long invalid_segment_patch1, invalid_segment_patch1_ff;
-extern unsigned long invalid_segment_patch2, invalid_segment_patch2_ff;
-extern unsigned long invalid_segment_patch1_1ff, invalid_segment_patch2_1ff;
-extern unsigned long num_context_patch1, num_context_patch1_16;
-extern unsigned long num_context_patch2_16;
-extern unsigned long vac_linesize_patch, vac_linesize_patch_32;
-extern unsigned long vac_hwflush_patch1, vac_hwflush_patch1_on;
-extern unsigned long vac_hwflush_patch2, vac_hwflush_patch2_on;
-
-#define PATCH_INSN(src, dst) do { \
- daddr = &(dst); \
- iaddr = &(src); \
- *daddr = *iaddr; \
- } while (0)
-
-static void __init patch_kernel_fault_handler(void)
-{
- unsigned long *iaddr, *daddr;
-
- switch (num_segmaps) {
- case 128:
- /* Default, nothing to do. */
- break;
- case 256:
- PATCH_INSN(invalid_segment_patch1_ff,
- invalid_segment_patch1);
- PATCH_INSN(invalid_segment_patch2_ff,
- invalid_segment_patch2);
- break;
- case 512:
- PATCH_INSN(invalid_segment_patch1_1ff,
- invalid_segment_patch1);
- PATCH_INSN(invalid_segment_patch2_1ff,
- invalid_segment_patch2);
- break;
- default:
- prom_printf("Unhandled number of segmaps: %d\n",
- num_segmaps);
- prom_halt();
- }
- switch (num_contexts) {
- case 8:
- /* Default, nothing to do. */
- break;
- case 16:
- PATCH_INSN(num_context_patch1_16,
- num_context_patch1);
- break;
- default:
- prom_printf("Unhandled number of contexts: %d\n",
- num_contexts);
- prom_halt();
- }
-
- if (sun4c_vacinfo.do_hwflushes != 0) {
- PATCH_INSN(vac_hwflush_patch1_on, vac_hwflush_patch1);
- PATCH_INSN(vac_hwflush_patch2_on, vac_hwflush_patch2);
- } else {
- switch (sun4c_vacinfo.linesize) {
- case 16:
- /* Default, nothing to do. */
- break;
- case 32:
- PATCH_INSN(vac_linesize_patch_32, vac_linesize_patch);
- break;
- default:
- prom_printf("Impossible VAC linesize %d, halting...\n",
- sun4c_vacinfo.linesize);
- prom_halt();
- }
- }
-}
-
-static void __init sun4c_probe_mmu(void)
-{
- if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
- (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
- /* Hardcode these just to be safe, PROM on SS1 does
- * not have this info available in the root node.
- */
- num_segmaps = 128;
- num_contexts = 8;
- } else {
- num_segmaps =
- prom_getintdefault(prom_root_node, "mmu-npmg", 128);
- num_contexts =
- prom_getintdefault(prom_root_node, "mmu-nctx", 0x8);
- }
- patch_kernel_fault_handler();
-}
-
-volatile unsigned long __iomem *sun4c_memerr_reg = NULL;
-
-void __init sun4c_probe_memerr_reg(void)
-{
- phandle node;
- struct linux_prom_registers regs[1];
-
- node = prom_getchild(prom_root_node);
- node = prom_searchsiblings(prom_root_node, "memory-error");
- if (!node)
- return;
- if (prom_getproperty(node, "reg", (char *)regs, sizeof(regs)) <= 0)
- return;
- /* hmm I think regs[0].which_io is zero here anyways */
- sun4c_memerr_reg = ioremap(regs[0].phys_addr, regs[0].reg_size);
-}
-
-static inline void sun4c_init_ss2_cache_bug(void)
-{
- if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) ||
- (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) ||
- (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) {
- /* Whee.. */
- printk("SS2 cache bug detected, uncaching trap table page\n");
- sun4c_flush_page((unsigned int) &_start);
- sun4c_put_pte(((unsigned long) &_start),
- (sun4c_get_pte((unsigned long) &_start) | _SUN4C_PAGE_NOCACHE));
- }
-}
-
-/* Addr is always aligned on a page boundary for us already. */
-static int sun4c_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va,
- unsigned long addr, int len)
-{
- unsigned long page, end;
-
- *pba = addr;
-
- end = PAGE_ALIGN((addr + len));
- while (addr < end) {
- page = va;
- sun4c_flush_page(page);
- page -= PAGE_OFFSET;
- page >>= PAGE_SHIFT;
- page |= (_SUN4C_PAGE_VALID | _SUN4C_PAGE_DIRTY |
- _SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_PRIV);
- sun4c_put_pte(addr, page);
- addr += PAGE_SIZE;
- va += PAGE_SIZE;
- }
-
- return 0;
-}
-
-static void sun4c_unmap_dma_area(struct device *dev, unsigned long busa, int len)
-{
- /* Fortunately for us, bus_addr == uncached_virt in sun4c. */
- /* XXX Implement this */
-}
-
-/* TLB management. */
-
-/* Don't change this struct without changing entry.S. This is used
- * in the in-window kernel fault handler, and you don't want to mess
- * with that. (See sun4c_fault in entry.S).
- */
-struct sun4c_mmu_entry {
- struct sun4c_mmu_entry *next;
- struct sun4c_mmu_entry *prev;
- unsigned long vaddr;
- unsigned char pseg;
- unsigned char locked;
-
- /* For user mappings only, and completely hidden from kernel
- * TLB miss code.
- */
- unsigned char ctx;
- struct sun4c_mmu_entry *lru_next;
- struct sun4c_mmu_entry *lru_prev;
-};
-
-static struct sun4c_mmu_entry mmu_entry_pool[SUN4C_MAX_SEGMAPS];
-
-static void __init sun4c_init_mmu_entry_pool(void)
-{
- int i;
-
- for (i=0; i < SUN4C_MAX_SEGMAPS; i++) {
- mmu_entry_pool[i].pseg = i;
- mmu_entry_pool[i].next = NULL;
- mmu_entry_pool[i].prev = NULL;
- mmu_entry_pool[i].vaddr = 0;
- mmu_entry_pool[i].locked = 0;
- mmu_entry_pool[i].ctx = 0;
- mmu_entry_pool[i].lru_next = NULL;
- mmu_entry_pool[i].lru_prev = NULL;
- }
- mmu_entry_pool[invalid_segment].locked = 1;
-}
-
-static inline void fix_permissions(unsigned long vaddr, unsigned long bits_on,
- unsigned long bits_off)
-{
- unsigned long start, end;
-
- end = vaddr + SUN4C_REAL_PGDIR_SIZE;
- for (start = vaddr; start < end; start += PAGE_SIZE)
- if (sun4c_get_pte(start) & _SUN4C_PAGE_VALID)
- sun4c_put_pte(start, (sun4c_get_pte(start) | bits_on) &
- ~bits_off);
-}
-
-static inline void sun4c_init_map_kernelprom(unsigned long kernel_end)
-{
- unsigned long vaddr;
- unsigned char pseg, ctx;
-
- for (vaddr = KADB_DEBUGGER_BEGVM;
- vaddr < LINUX_OPPROM_ENDVM;
- vaddr += SUN4C_REAL_PGDIR_SIZE) {
- pseg = sun4c_get_segmap(vaddr);
- if (pseg != invalid_segment) {
- mmu_entry_pool[pseg].locked = 1;
- for (ctx = 0; ctx < num_contexts; ctx++)
- prom_putsegment(ctx, vaddr, pseg);
- fix_permissions(vaddr, _SUN4C_PAGE_PRIV, 0);
- }
- }
-
- for (vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) {
- pseg = sun4c_get_segmap(vaddr);
- mmu_entry_pool[pseg].locked = 1;
- for (ctx = 0; ctx < num_contexts; ctx++)
- prom_putsegment(ctx, vaddr, pseg);
- fix_permissions(vaddr, _SUN4C_PAGE_PRIV, _SUN4C_PAGE_NOCACHE);
- }
-}
-
-static void __init sun4c_init_lock_area(unsigned long start, unsigned long end)
-{
- int i, ctx;
-
- while (start < end) {
- for (i = 0; i < invalid_segment; i++)
- if (!mmu_entry_pool[i].locked)
- break;
- mmu_entry_pool[i].locked = 1;
- sun4c_init_clean_segmap(i);
- for (ctx = 0; ctx < num_contexts; ctx++)
- prom_putsegment(ctx, start, mmu_entry_pool[i].pseg);
- start += SUN4C_REAL_PGDIR_SIZE;
- }
-}
-
-/* Don't change this struct without changing entry.S. This is used
- * in the in-window kernel fault handler, and you don't want to mess
- * with that. (See sun4c_fault in entry.S).
- */
-struct sun4c_mmu_ring {
- struct sun4c_mmu_entry ringhd;
- int num_entries;
-};
-
-static struct sun4c_mmu_ring sun4c_context_ring[SUN4C_MAX_CONTEXTS]; /* used user entries */
-static struct sun4c_mmu_ring sun4c_ufree_ring; /* free user entries */
-static struct sun4c_mmu_ring sun4c_ulru_ring; /* LRU user entries */
-struct sun4c_mmu_ring sun4c_kernel_ring; /* used kernel entries */
-struct sun4c_mmu_ring sun4c_kfree_ring; /* free kernel entries */
-
-static inline void sun4c_init_rings(void)
-{
- int i;
-
- for (i = 0; i < SUN4C_MAX_CONTEXTS; i++) {
- sun4c_context_ring[i].ringhd.next =
- sun4c_context_ring[i].ringhd.prev =
- &sun4c_context_ring[i].ringhd;
- sun4c_context_ring[i].num_entries = 0;
- }
- sun4c_ufree_ring.ringhd.next = sun4c_ufree_ring.ringhd.prev =
- &sun4c_ufree_ring.ringhd;
- sun4c_ufree_ring.num_entries = 0;
- sun4c_ulru_ring.ringhd.lru_next = sun4c_ulru_ring.ringhd.lru_prev =
- &sun4c_ulru_ring.ringhd;
- sun4c_ulru_ring.num_entries = 0;
- sun4c_kernel_ring.ringhd.next = sun4c_kernel_ring.ringhd.prev =
- &sun4c_kernel_ring.ringhd;
- sun4c_kernel_ring.num_entries = 0;
- sun4c_kfree_ring.ringhd.next = sun4c_kfree_ring.ringhd.prev =
- &sun4c_kfree_ring.ringhd;
- sun4c_kfree_ring.num_entries = 0;
-}
-
-static void add_ring(struct sun4c_mmu_ring *ring,
- struct sun4c_mmu_entry *entry)
-{
- struct sun4c_mmu_entry *head = &ring->ringhd;
-
- entry->prev = head;
- (entry->next = head->next)->prev = entry;
- head->next = entry;
- ring->num_entries++;
-}
-
-static inline void add_lru(struct sun4c_mmu_entry *entry)
-{
- struct sun4c_mmu_ring *ring = &sun4c_ulru_ring;
- struct sun4c_mmu_entry *head = &ring->ringhd;
-
- entry->lru_next = head;
- (entry->lru_prev = head->lru_prev)->lru_next = entry;
- head->lru_prev = entry;
-}
-
-static void add_ring_ordered(struct sun4c_mmu_ring *ring,
- struct sun4c_mmu_entry *entry)
-{
- struct sun4c_mmu_entry *head = &ring->ringhd;
- unsigned long addr = entry->vaddr;
-
- while ((head->next != &ring->ringhd) && (head->next->vaddr < addr))
- head = head->next;
-
- entry->prev = head;
- (entry->next = head->next)->prev = entry;
- head->next = entry;
- ring->num_entries++;
-
- add_lru(entry);
-}
-
-static inline void remove_ring(struct sun4c_mmu_ring *ring,
- struct sun4c_mmu_entry *entry)
-{
- struct sun4c_mmu_entry *next = entry->next;
-
- (next->prev = entry->prev)->next = next;
- ring->num_entries--;
-}
-
-static void remove_lru(struct sun4c_mmu_entry *entry)
-{
- struct sun4c_mmu_entry *next = entry->lru_next;
-
- (next->lru_prev = entry->lru_prev)->lru_next = next;
-}
-
-static void free_user_entry(int ctx, struct sun4c_mmu_entry *entry)
-{
- remove_ring(sun4c_context_ring+ctx, entry);
- remove_lru(entry);
- add_ring(&sun4c_ufree_ring, entry);
-}
-
-static void free_kernel_entry(struct sun4c_mmu_entry *entry,
- struct sun4c_mmu_ring *ring)
-{
- remove_ring(ring, entry);
- add_ring(&sun4c_kfree_ring, entry);
-}
-
-static void __init sun4c_init_fill_kernel_ring(int howmany)
-{
- int i;
-
- while (howmany) {
- for (i = 0; i < invalid_segment; i++)
- if (!mmu_entry_pool[i].locked)
- break;
- mmu_entry_pool[i].locked = 1;
- sun4c_init_clean_segmap(i);
- add_ring(&sun4c_kfree_ring, &mmu_entry_pool[i]);
- howmany--;
- }
-}
-
-static void __init sun4c_init_fill_user_ring(void)
-{
- int i;
-
- for (i = 0; i < invalid_segment; i++) {
- if (mmu_entry_pool[i].locked)
- continue;
- sun4c_init_clean_segmap(i);
- add_ring(&sun4c_ufree_ring, &mmu_entry_pool[i]);
- }
-}
-
-static void sun4c_kernel_unmap(struct sun4c_mmu_entry *kentry)
-{
- int savectx, ctx;
-
- savectx = sun4c_get_context();
- for (ctx = 0; ctx < num_contexts; ctx++) {
- sun4c_set_context(ctx);
- sun4c_put_segmap(kentry->vaddr, invalid_segment);
- }
- sun4c_set_context(savectx);
-}
-
-static void sun4c_kernel_map(struct sun4c_mmu_entry *kentry)
-{
- int savectx, ctx;
-
- savectx = sun4c_get_context();
- for (ctx = 0; ctx < num_contexts; ctx++) {
- sun4c_set_context(ctx);
- sun4c_put_segmap(kentry->vaddr, kentry->pseg);
- }
- sun4c_set_context(savectx);
-}
-
-#define sun4c_user_unmap(__entry) \
- sun4c_put_segmap((__entry)->vaddr, invalid_segment)
-
-static void sun4c_demap_context(struct sun4c_mmu_ring *crp, unsigned char ctx)
-{
- struct sun4c_mmu_entry *head = &crp->ringhd;
- unsigned long flags;
-
- local_irq_save(flags);
- if (head->next != head) {
- struct sun4c_mmu_entry *entry = head->next;
- int savectx = sun4c_get_context();
-
- flush_user_windows();
- sun4c_set_context(ctx);
- sun4c_flush_context();
- do {
- struct sun4c_mmu_entry *next = entry->next;
-
- sun4c_user_unmap(entry);
- free_user_entry(ctx, entry);
-
- entry = next;
- } while (entry != head);
- sun4c_set_context(savectx);
- }
- local_irq_restore(flags);
-}
-
-static int sun4c_user_taken_entries; /* This is how much we have. */
-static int max_user_taken_entries; /* This limits us and prevents deadlock. */
-
-static struct sun4c_mmu_entry *sun4c_kernel_strategy(void)
-{
- struct sun4c_mmu_entry *this_entry;
-
- /* If some are free, return first one. */
- if (sun4c_kfree_ring.num_entries) {
- this_entry = sun4c_kfree_ring.ringhd.next;
- return this_entry;
- }
-
- /* Else free one up. */
- this_entry = sun4c_kernel_ring.ringhd.prev;
- sun4c_flush_segment(this_entry->vaddr);
- sun4c_kernel_unmap(this_entry);
- free_kernel_entry(this_entry, &sun4c_kernel_ring);
- this_entry = sun4c_kfree_ring.ringhd.next;
-
- return this_entry;
-}
-
-/* Using this method to free up mmu entries eliminates a lot of
- * potential races since we have a kernel that incurs tlb
- * replacement faults. There may be performance penalties.
- *
- * NOTE: Must be called with interrupts disabled.
- */
-static struct sun4c_mmu_entry *sun4c_user_strategy(void)
-{
- struct sun4c_mmu_entry *entry;
- unsigned char ctx;
- int savectx;
-
- /* If some are free, return first one. */
- if (sun4c_ufree_ring.num_entries) {
- entry = sun4c_ufree_ring.ringhd.next;
- goto unlink_out;
- }
-
- if (sun4c_user_taken_entries) {
- entry = sun4c_kernel_strategy();
- sun4c_user_taken_entries--;
- goto kunlink_out;
- }
-
- /* Grab from the beginning of the LRU list. */
- entry = sun4c_ulru_ring.ringhd.lru_next;
- ctx = entry->ctx;
-
- savectx = sun4c_get_context();
- flush_user_windows();
- sun4c_set_context(ctx);
- sun4c_flush_segment(entry->vaddr);
- sun4c_user_unmap(entry);
- remove_ring(sun4c_context_ring + ctx, entry);
- remove_lru(entry);
- sun4c_set_context(savectx);
-
- return entry;
-
-unlink_out:
- remove_ring(&sun4c_ufree_ring, entry);
- return entry;
-kunlink_out:
- remove_ring(&sun4c_kfree_ring, entry);
- return entry;
-}
-
-/* NOTE: Must be called with interrupts disabled. */
-void sun4c_grow_kernel_ring(void)
-{
- struct sun4c_mmu_entry *entry;
-
- /* Prevent deadlock condition. */
- if (sun4c_user_taken_entries >= max_user_taken_entries)
- return;
-
- if (sun4c_ufree_ring.num_entries) {
- entry = sun4c_ufree_ring.ringhd.next;
- remove_ring(&sun4c_ufree_ring, entry);
- add_ring(&sun4c_kfree_ring, entry);
- sun4c_user_taken_entries++;
- }
-}
-
-/* 2 page buckets for task struct and kernel stack allocation.
- *
- * TASK_STACK_BEGIN
- * bucket[0]
- * bucket[1]
- * [ ... ]
- * bucket[NR_TASK_BUCKETS-1]
- * TASK_STACK_BEGIN + (sizeof(struct task_bucket) * NR_TASK_BUCKETS)
- *
- * Each slot looks like:
- *
- * page 1 -- task struct + beginning of kernel stack
- * page 2 -- rest of kernel stack
- */
-
-union task_union *sun4c_bucket[NR_TASK_BUCKETS];
-
-static int sun4c_lowbucket_avail;
-
-#define BUCKET_EMPTY ((union task_union *) 0)
-#define BUCKET_SHIFT (PAGE_SHIFT + 1) /* log2(sizeof(struct task_bucket)) */
-#define BUCKET_SIZE (1 << BUCKET_SHIFT)
-#define BUCKET_NUM(addr) ((((addr) - SUN4C_LOCK_VADDR) >> BUCKET_SHIFT))
-#define BUCKET_ADDR(num) (((num) << BUCKET_SHIFT) + SUN4C_LOCK_VADDR)
-#define BUCKET_PTE(page) \
- ((((page) - PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(SUN4C_PAGE_KERNEL))
-#define BUCKET_PTE_PAGE(pte) \
- (PAGE_OFFSET + (((pte) & SUN4C_PFN_MASK) << PAGE_SHIFT))
-
-static void get_locked_segment(unsigned long addr)
-{
- struct sun4c_mmu_entry *stolen;
- unsigned long flags;
-
- local_irq_save(flags);
- addr &= SUN4C_REAL_PGDIR_MASK;
- stolen = sun4c_user_strategy();
- max_user_taken_entries--;
- stolen->vaddr = addr;
- flush_user_windows();
- sun4c_kernel_map(stolen);
- local_irq_restore(flags);
-}
-
-static void free_locked_segment(unsigned long addr)
-{
- struct sun4c_mmu_entry *entry;
- unsigned long flags;
- unsigned char pseg;
-
- local_irq_save(flags);
- addr &= SUN4C_REAL_PGDIR_MASK;
- pseg = sun4c_get_segmap(addr);
- entry = &mmu_entry_pool[pseg];
-
- flush_user_windows();
- sun4c_flush_segment(addr);
- sun4c_kernel_unmap(entry);
- add_ring(&sun4c_ufree_ring, entry);
- max_user_taken_entries++;
- local_irq_restore(flags);
-}
-
-static inline void garbage_collect(int entry)
-{
- int start, end;
-
- /* 32 buckets per segment... */
- entry &= ~31;
- start = entry;
- for (end = (start + 32); start < end; start++)
- if (sun4c_bucket[start] != BUCKET_EMPTY)
- return;
-
- /* Entire segment empty, release it. */
- free_locked_segment(BUCKET_ADDR(entry));
-}
-
-static struct thread_info *sun4c_alloc_thread_info_node(int node)
-{
- unsigned long addr, pages;
- int entry;
-
- pages = __get_free_pages(GFP_KERNEL, THREAD_INFO_ORDER);
- if (!pages)
- return NULL;
-
- for (entry = sun4c_lowbucket_avail; entry < NR_TASK_BUCKETS; entry++)
- if (sun4c_bucket[entry] == BUCKET_EMPTY)
- break;
- if (entry == NR_TASK_BUCKETS) {
- free_pages(pages, THREAD_INFO_ORDER);
- return NULL;
- }
- if (entry >= sun4c_lowbucket_avail)
- sun4c_lowbucket_avail = entry + 1;
-
- addr = BUCKET_ADDR(entry);
- sun4c_bucket[entry] = (union task_union *) addr;
- if(sun4c_get_segmap(addr) == invalid_segment)
- get_locked_segment(addr);
-
- /* We are changing the virtual color of the page(s)
- * so we must flush the cache to guarantee consistency.
- */
- sun4c_flush_page(pages);
- sun4c_flush_page(pages + PAGE_SIZE);
-
- sun4c_put_pte(addr, BUCKET_PTE(pages));
- sun4c_put_pte(addr + PAGE_SIZE, BUCKET_PTE(pages + PAGE_SIZE));
-
-#ifdef CONFIG_DEBUG_STACK_USAGE
- memset((void *)addr, 0, PAGE_SIZE << THREAD_INFO_ORDER);
-#endif /* DEBUG_STACK_USAGE */
-
- return (struct thread_info *) addr;
-}
-
-static void sun4c_free_thread_info(struct thread_info *ti)
-{
- unsigned long tiaddr = (unsigned long) ti;
- unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tiaddr));
- int entry = BUCKET_NUM(tiaddr);
-
- /* We are deleting a mapping, so the flush here is mandatory. */
- sun4c_flush_page(tiaddr);
- sun4c_flush_page(tiaddr + PAGE_SIZE);
-
- sun4c_put_pte(tiaddr, 0);
- sun4c_put_pte(tiaddr + PAGE_SIZE, 0);
-
- sun4c_bucket[entry] = BUCKET_EMPTY;
- if (entry < sun4c_lowbucket_avail)
- sun4c_lowbucket_avail = entry;
-
- free_pages(pages, THREAD_INFO_ORDER);
- garbage_collect(entry);
-}
-
-static void __init sun4c_init_buckets(void)
-{
- int entry;
-
- if (sizeof(union thread_union) != (PAGE_SIZE << THREAD_INFO_ORDER)) {
- extern void thread_info_size_is_bolixed_pete(void);
- thread_info_size_is_bolixed_pete();
- }
-
- for (entry = 0; entry < NR_TASK_BUCKETS; entry++)
- sun4c_bucket[entry] = BUCKET_EMPTY;
- sun4c_lowbucket_avail = 0;
-}
-
-static unsigned long sun4c_iobuffer_start;
-static unsigned long sun4c_iobuffer_end;
-static unsigned long sun4c_iobuffer_high;
-static unsigned long *sun4c_iobuffer_map;
-static int iobuffer_map_size;
-
-/*
- * Alias our pages so they do not cause a trap.
- * Also one page may be aliased into several I/O areas and we may
- * finish these I/O separately.
- */
-static char *sun4c_lockarea(char *vaddr, unsigned long size)
-{
- unsigned long base, scan;
- unsigned long npages;
- unsigned long vpage;
- unsigned long pte;
- unsigned long apage;
- unsigned long high;
- unsigned long flags;
-
- npages = (((unsigned long)vaddr & ~PAGE_MASK) +
- size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
-
- local_irq_save(flags);
- base = bitmap_find_next_zero_area(sun4c_iobuffer_map, iobuffer_map_size,
- 0, npages, 0);
- if (base >= iobuffer_map_size)
- goto abend;
-
- high = ((base + npages) << PAGE_SHIFT) + sun4c_iobuffer_start;
- high = SUN4C_REAL_PGDIR_ALIGN(high);
- while (high > sun4c_iobuffer_high) {
- get_locked_segment(sun4c_iobuffer_high);
- sun4c_iobuffer_high += SUN4C_REAL_PGDIR_SIZE;
- }
-
- vpage = ((unsigned long) vaddr) & PAGE_MASK;
- for (scan = base; scan < base+npages; scan++) {
- pte = ((vpage-PAGE_OFFSET) >> PAGE_SHIFT);
- pte |= pgprot_val(SUN4C_PAGE_KERNEL);
- pte |= _SUN4C_PAGE_NOCACHE;
- set_bit(scan, sun4c_iobuffer_map);
- apage = (scan << PAGE_SHIFT) + sun4c_iobuffer_start;
-
- /* Flush original mapping so we see the right things later. */
- sun4c_flush_page(vpage);
-
- sun4c_put_pte(apage, pte);
- vpage += PAGE_SIZE;
- }
- local_irq_restore(flags);
- return (char *) ((base << PAGE_SHIFT) + sun4c_iobuffer_start +
- (((unsigned long) vaddr) & ~PAGE_MASK));
-
-abend:
- local_irq_restore(flags);
- printk("DMA vaddr=0x%p size=%08lx\n", vaddr, size);
- panic("Out of iobuffer table");
- return NULL;
-}
-
-static void sun4c_unlockarea(char *vaddr, unsigned long size)
-{
- unsigned long vpage, npages;
- unsigned long flags;
- int scan, high;
-
- vpage = (unsigned long)vaddr & PAGE_MASK;
- npages = (((unsigned long)vaddr & ~PAGE_MASK) +
- size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
-
- local_irq_save(flags);
- while (npages != 0) {
- --npages;
-
- /* This mapping is marked non-cachable, no flush necessary. */
- sun4c_put_pte(vpage, 0);
- clear_bit((vpage - sun4c_iobuffer_start) >> PAGE_SHIFT,
- sun4c_iobuffer_map);
- vpage += PAGE_SIZE;
- }
-
- /* garbage collect */
- scan = (sun4c_iobuffer_high - sun4c_iobuffer_start) >> PAGE_SHIFT;
- while (scan >= 0 && !sun4c_iobuffer_map[scan >> 5])
- scan -= 32;
- scan += 32;
- high = sun4c_iobuffer_start + (scan << PAGE_SHIFT);
- high = SUN4C_REAL_PGDIR_ALIGN(high) + SUN4C_REAL_PGDIR_SIZE;
- while (high < sun4c_iobuffer_high) {
- sun4c_iobuffer_high -= SUN4C_REAL_PGDIR_SIZE;
- free_locked_segment(sun4c_iobuffer_high);
- }
- local_irq_restore(flags);
-}
-
-/* Note the scsi code at init time passes to here buffers
- * which sit on the kernel stack, those are already locked
- * by implication and fool the page locking code above
- * if passed to by mistake.
- */
-static __u32 sun4c_get_scsi_one(struct device *dev, char *bufptr, unsigned long len)
-{
- unsigned long page;
-
- page = ((unsigned long)bufptr) & PAGE_MASK;
- if (!virt_addr_valid(page)) {
- sun4c_flush_page(page);
- return (__u32)bufptr; /* already locked */
- }
- return (__u32)sun4c_lockarea(bufptr, len);
-}
-
-static void sun4c_get_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz)
-{
- while (sz != 0) {
- --sz;
- sg->dma_address = (__u32)sun4c_lockarea(sg_virt(sg), sg->length);
- sg->dma_length = sg->length;
- sg = sg_next(sg);
- }
-}
-
-static void sun4c_release_scsi_one(struct device *dev, __u32 bufptr, unsigned long len)
-{
- if (bufptr < sun4c_iobuffer_start)
- return; /* On kernel stack or similar, see above */
- sun4c_unlockarea((char *)bufptr, len);
-}
-
-static void sun4c_release_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz)
-{
- while (sz != 0) {
- --sz;
- sun4c_unlockarea((char *)sg->dma_address, sg->length);
- sg = sg_next(sg);
- }
-}
-
-#define TASK_ENTRY_SIZE BUCKET_SIZE /* see above */
-#define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
-
-struct vm_area_struct sun4c_kstack_vma;
-
-static void __init sun4c_init_lock_areas(void)
-{
- unsigned long sun4c_taskstack_start;
- unsigned long sun4c_taskstack_end;
- int bitmap_size;
-
- sun4c_init_buckets();
- sun4c_taskstack_start = SUN4C_LOCK_VADDR;
- sun4c_taskstack_end = (sun4c_taskstack_start +
- (TASK_ENTRY_SIZE * NR_TASK_BUCKETS));
- if (sun4c_taskstack_end >= SUN4C_LOCK_END) {
- prom_printf("Too many tasks, decrease NR_TASK_BUCKETS please.\n");
- prom_halt();
- }
-
- sun4c_iobuffer_start = sun4c_iobuffer_high =
- SUN4C_REAL_PGDIR_ALIGN(sun4c_taskstack_end);
- sun4c_iobuffer_end = SUN4C_LOCK_END;
- bitmap_size = (sun4c_iobuffer_end - sun4c_iobuffer_start) >> PAGE_SHIFT;
- bitmap_size = (bitmap_size + 7) >> 3;
- bitmap_size = LONG_ALIGN(bitmap_size);
- iobuffer_map_size = bitmap_size << 3;
- sun4c_iobuffer_map = __alloc_bootmem(bitmap_size, SMP_CACHE_BYTES, 0UL);
- memset((void *) sun4c_iobuffer_map, 0, bitmap_size);
-
- sun4c_kstack_vma.vm_mm = &init_mm;
- sun4c_kstack_vma.vm_start = sun4c_taskstack_start;
- sun4c_kstack_vma.vm_end = sun4c_taskstack_end;
- sun4c_kstack_vma.vm_page_prot = PAGE_SHARED;
- sun4c_kstack_vma.vm_flags = VM_READ | VM_WRITE | VM_EXEC;
- insert_vm_struct(&init_mm, &sun4c_kstack_vma);
-}
-
-/* Cache flushing on the sun4c. */
-static void sun4c_flush_cache_all(void)
-{
- unsigned long begin, end;
-
- flush_user_windows();
- begin = (KERNBASE + SUN4C_REAL_PGDIR_SIZE);
- end = (begin + SUN4C_VAC_SIZE);
-
- if (sun4c_vacinfo.linesize == 32) {
- while (begin < end) {
- __asm__ __volatile__(
- "ld [%0 + 0x00], %%g0\n\t"
- "ld [%0 + 0x20], %%g0\n\t"
- "ld [%0 + 0x40], %%g0\n\t"
- "ld [%0 + 0x60], %%g0\n\t"
- "ld [%0 + 0x80], %%g0\n\t"
- "ld [%0 + 0xa0], %%g0\n\t"
- "ld [%0 + 0xc0], %%g0\n\t"
- "ld [%0 + 0xe0], %%g0\n\t"
- "ld [%0 + 0x100], %%g0\n\t"
- "ld [%0 + 0x120], %%g0\n\t"
- "ld [%0 + 0x140], %%g0\n\t"
- "ld [%0 + 0x160], %%g0\n\t"
- "ld [%0 + 0x180], %%g0\n\t"
- "ld [%0 + 0x1a0], %%g0\n\t"
- "ld [%0 + 0x1c0], %%g0\n\t"
- "ld [%0 + 0x1e0], %%g0\n"
- : : "r" (begin));
- begin += 512;
- }
- } else {
- while (begin < end) {
- __asm__ __volatile__(
- "ld [%0 + 0x00], %%g0\n\t"
- "ld [%0 + 0x10], %%g0\n\t"
- "ld [%0 + 0x20], %%g0\n\t"
- "ld [%0 + 0x30], %%g0\n\t"
- "ld [%0 + 0x40], %%g0\n\t"
- "ld [%0 + 0x50], %%g0\n\t"
- "ld [%0 + 0x60], %%g0\n\t"
- "ld [%0 + 0x70], %%g0\n\t"
- "ld [%0 + 0x80], %%g0\n\t"
- "ld [%0 + 0x90], %%g0\n\t"
- "ld [%0 + 0xa0], %%g0\n\t"
- "ld [%0 + 0xb0], %%g0\n\t"
- "ld [%0 + 0xc0], %%g0\n\t"
- "ld [%0 + 0xd0], %%g0\n\t"
- "ld [%0 + 0xe0], %%g0\n\t"
- "ld [%0 + 0xf0], %%g0\n"
- : : "r" (begin));
- begin += 256;
- }
- }
-}
-
-static void sun4c_flush_cache_mm(struct mm_struct *mm)
-{
- int new_ctx = mm->context;
-
- if (new_ctx != NO_CONTEXT) {
- flush_user_windows();
-
- if (sun4c_context_ring[new_ctx].num_entries) {
- struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
- unsigned long flags;
-
- local_irq_save(flags);
- if (head->next != head) {
- struct sun4c_mmu_entry *entry = head->next;
- int savectx = sun4c_get_context();
-
- sun4c_set_context(new_ctx);
- sun4c_flush_context();
- do {
- struct sun4c_mmu_entry *next = entry->next;
-
- sun4c_user_unmap(entry);
- free_user_entry(new_ctx, entry);
-
- entry = next;
- } while (entry != head);
- sun4c_set_context(savectx);
- }
- local_irq_restore(flags);
- }
- }
-}
-
-static void sun4c_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
- int new_ctx = mm->context;
-
- if (new_ctx != NO_CONTEXT) {
- struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
- struct sun4c_mmu_entry *entry;
- unsigned long flags;
-
- flush_user_windows();
-
- local_irq_save(flags);
- /* All user segmap chains are ordered on entry->vaddr. */
- for (entry = head->next;
- (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start);
- entry = entry->next)
- ;
-
- /* Tracing various job mixtures showed that this conditional
- * only passes ~35% of the time for most worse case situations,
- * therefore we avoid all of this gross overhead ~65% of the time.
- */
- if ((entry != head) && (entry->vaddr < end)) {
- int octx = sun4c_get_context();
- sun4c_set_context(new_ctx);
-
- /* At this point, always, (start >= entry->vaddr) and
- * (entry->vaddr < end), once the latter condition
- * ceases to hold, or we hit the end of the list, we
- * exit the loop. The ordering of all user allocated
- * segmaps makes this all work out so beautifully.
- */
- do {
- struct sun4c_mmu_entry *next = entry->next;
- unsigned long realend;
-
- /* "realstart" is always >= entry->vaddr */
- realend = entry->vaddr + SUN4C_REAL_PGDIR_SIZE;
- if (end < realend)
- realend = end;
- if ((realend - entry->vaddr) <= (PAGE_SIZE << 3)) {
- unsigned long page = entry->vaddr;
- while (page < realend) {
- sun4c_flush_page(page);
- page += PAGE_SIZE;
- }
- } else {
- sun4c_flush_segment(entry->vaddr);
- sun4c_user_unmap(entry);
- free_user_entry(new_ctx, entry);
- }
- entry = next;
- } while ((entry != head) && (entry->vaddr < end));
- sun4c_set_context(octx);
- }
- local_irq_restore(flags);
- }
-}
-
-static void sun4c_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
-{
- struct mm_struct *mm = vma->vm_mm;
- int new_ctx = mm->context;
-
- /* Sun4c has no separate I/D caches so cannot optimize for non
- * text page flushes.
- */
- if (new_ctx != NO_CONTEXT) {
- int octx = sun4c_get_context();
- unsigned long flags;
-
- flush_user_windows();
- local_irq_save(flags);
- sun4c_set_context(new_ctx);
- sun4c_flush_page(page);
- sun4c_set_context(octx);
- local_irq_restore(flags);
- }
-}
-
-static void sun4c_flush_page_to_ram(unsigned long page)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- sun4c_flush_page(page);
- local_irq_restore(flags);
-}
-
-/* Sun4c cache is unified, both instructions and data live there, so
- * no need to flush the on-stack instructions for new signal handlers.
- */
-static void sun4c_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
-{
-}
-
-/* TLB flushing on the sun4c. These routines count on the cache
- * flushing code to flush the user register windows so that we need
- * not do so when we get here.
- */
-
-static void sun4c_flush_tlb_all(void)
-{
- struct sun4c_mmu_entry *this_entry, *next_entry;
- unsigned long flags;
- int savectx, ctx;
-
- local_irq_save(flags);
- this_entry = sun4c_kernel_ring.ringhd.next;
- savectx = sun4c_get_context();
- flush_user_windows();
- while (sun4c_kernel_ring.num_entries) {
- next_entry = this_entry->next;
- sun4c_flush_segment(this_entry->vaddr);
- for (ctx = 0; ctx < num_contexts; ctx++) {
- sun4c_set_context(ctx);
- sun4c_put_segmap(this_entry->vaddr, invalid_segment);
- }
- free_kernel_entry(this_entry, &sun4c_kernel_ring);
- this_entry = next_entry;
- }
- sun4c_set_context(savectx);
- local_irq_restore(flags);
-}
-
-static void sun4c_flush_tlb_mm(struct mm_struct *mm)
-{
- int new_ctx = mm->context;
-
- if (new_ctx != NO_CONTEXT) {
- struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
- unsigned long flags;
-
- local_irq_save(flags);
- if (head->next != head) {
- struct sun4c_mmu_entry *entry = head->next;
- int savectx = sun4c_get_context();
-
- sun4c_set_context(new_ctx);
- sun4c_flush_context();
- do {
- struct sun4c_mmu_entry *next = entry->next;
-
- sun4c_user_unmap(entry);
- free_user_entry(new_ctx, entry);
-
- entry = next;
- } while (entry != head);
- sun4c_set_context(savectx);
- }
- local_irq_restore(flags);
- }
-}
-
-static void sun4c_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
- int new_ctx = mm->context;
-
- if (new_ctx != NO_CONTEXT) {
- struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
- struct sun4c_mmu_entry *entry;
- unsigned long flags;
-
- local_irq_save(flags);
- /* See commentary in sun4c_flush_cache_range(). */
- for (entry = head->next;
- (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start);
- entry = entry->next)
- ;
-
- if ((entry != head) && (entry->vaddr < end)) {
- int octx = sun4c_get_context();
-
- sun4c_set_context(new_ctx);
- do {
- struct sun4c_mmu_entry *next = entry->next;
-
- sun4c_flush_segment(entry->vaddr);
- sun4c_user_unmap(entry);
- free_user_entry(new_ctx, entry);
-
- entry = next;
- } while ((entry != head) && (entry->vaddr < end));
- sun4c_set_context(octx);
- }
- local_irq_restore(flags);
- }
-}
-
-static void sun4c_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
- struct mm_struct *mm = vma->vm_mm;
- int new_ctx = mm->context;
-
- if (new_ctx != NO_CONTEXT) {
- int savectx = sun4c_get_context();
- unsigned long flags;
-
- local_irq_save(flags);
- sun4c_set_context(new_ctx);
- page &= PAGE_MASK;
- sun4c_flush_page(page);
- sun4c_put_pte(page, 0);
- sun4c_set_context(savectx);
- local_irq_restore(flags);
- }
-}
-
-static inline void sun4c_mapioaddr(unsigned long physaddr, unsigned long virt_addr)
-{
- unsigned long page_entry, pg_iobits;
-
- pg_iobits = _SUN4C_PAGE_PRESENT | _SUN4C_READABLE | _SUN4C_WRITEABLE |
- _SUN4C_PAGE_IO | _SUN4C_PAGE_NOCACHE;
-
- page_entry = ((physaddr >> PAGE_SHIFT) & SUN4C_PFN_MASK);
- page_entry |= ((pg_iobits | _SUN4C_PAGE_PRIV) & ~(_SUN4C_PAGE_PRESENT));
- sun4c_put_pte(virt_addr, page_entry);
-}
-
-static void sun4c_mapiorange(unsigned int bus, unsigned long xpa,
- unsigned long xva, unsigned int len)
-{
- while (len != 0) {
- len -= PAGE_SIZE;
- sun4c_mapioaddr(xpa, xva);
- xva += PAGE_SIZE;
- xpa += PAGE_SIZE;
- }
-}
-
-static void sun4c_unmapiorange(unsigned long virt_addr, unsigned int len)
-{
- while (len != 0) {
- len -= PAGE_SIZE;
- sun4c_put_pte(virt_addr, 0);
- virt_addr += PAGE_SIZE;
- }
-}
-
-static void sun4c_alloc_context(struct mm_struct *old_mm, struct mm_struct *mm)
-{
- struct ctx_list *ctxp;
-
- ctxp = ctx_free.next;
- if (ctxp != &ctx_free) {
- remove_from_ctx_list(ctxp);
- add_to_used_ctxlist(ctxp);
- mm->context = ctxp->ctx_number;
- ctxp->ctx_mm = mm;
- return;
- }
- ctxp = ctx_used.next;
- if (ctxp->ctx_mm == old_mm)
- ctxp = ctxp->next;
- remove_from_ctx_list(ctxp);
- add_to_used_ctxlist(ctxp);
- ctxp->ctx_mm->context = NO_CONTEXT;
- ctxp->ctx_mm = mm;
- mm->context = ctxp->ctx_number;
- sun4c_demap_context(&sun4c_context_ring[ctxp->ctx_number],
- ctxp->ctx_number);
-}
-
-/* Switch the current MM context. */
-static void sun4c_switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk, int cpu)
-{
- struct ctx_list *ctx;
- int dirty = 0;
-
- if (mm->context == NO_CONTEXT) {
- dirty = 1;
- sun4c_alloc_context(old_mm, mm);
- } else {
- /* Update the LRU ring of contexts. */
- ctx = ctx_list_pool + mm->context;
- remove_from_ctx_list(ctx);
- add_to_used_ctxlist(ctx);
- }
- if (dirty || old_mm != mm)
- sun4c_set_context(mm->context);
-}
-
-static void sun4c_destroy_context(struct mm_struct *mm)
-{
- struct ctx_list *ctx_old;
-
- if (mm->context != NO_CONTEXT) {
- sun4c_demap_context(&sun4c_context_ring[mm->context], mm->context);
- ctx_old = ctx_list_pool + mm->context;
- remove_from_ctx_list(ctx_old);
- add_to_free_ctxlist(ctx_old);
- mm->context = NO_CONTEXT;
- }
-}
-
-static void sun4c_mmu_info(struct seq_file *m)
-{
- int used_user_entries, i;
-
- used_user_entries = 0;
- for (i = 0; i < num_contexts; i++)
- used_user_entries += sun4c_context_ring[i].num_entries;
-
- seq_printf(m,
- "vacsize\t\t: %d bytes\n"
- "vachwflush\t: %s\n"
- "vaclinesize\t: %d bytes\n"
- "mmuctxs\t\t: %d\n"
- "mmupsegs\t: %d\n"
- "kernelpsegs\t: %d\n"
- "kfreepsegs\t: %d\n"
- "usedpsegs\t: %d\n"
- "ufreepsegs\t: %d\n"
- "user_taken\t: %d\n"
- "max_taken\t: %d\n",
- sun4c_vacinfo.num_bytes,
- (sun4c_vacinfo.do_hwflushes ? "yes" : "no"),
- sun4c_vacinfo.linesize,
- num_contexts,
- (invalid_segment + 1),
- sun4c_kernel_ring.num_entries,
- sun4c_kfree_ring.num_entries,
- used_user_entries,
- sun4c_ufree_ring.num_entries,
- sun4c_user_taken_entries,
- max_user_taken_entries);
-}
-
-/* Nothing below here should touch the mmu hardware nor the mmu_entry
- * data structures.
- */
-
-/* First the functions which the mid-level code uses to directly
- * manipulate the software page tables. Some defines since we are
- * emulating the i386 page directory layout.
- */
-#define PGD_PRESENT 0x001
-#define PGD_RW 0x002
-#define PGD_USER 0x004
-#define PGD_ACCESSED 0x020
-#define PGD_DIRTY 0x040
-#define PGD_TABLE (PGD_PRESENT | PGD_RW | PGD_USER | PGD_ACCESSED | PGD_DIRTY)
-
-static void sun4c_set_pte(pte_t *ptep, pte_t pte)
-{
- *ptep = pte;
-}
-
-static void sun4c_pgd_set(pgd_t * pgdp, pmd_t * pmdp)
-{
-}
-
-static void sun4c_pmd_set(pmd_t * pmdp, pte_t * ptep)
-{
- pmdp->pmdv[0] = PGD_TABLE | (unsigned long) ptep;
-}
-
-static void sun4c_pmd_populate(pmd_t * pmdp, struct page * ptep)
-{
- if (page_address(ptep) == NULL) BUG(); /* No highmem on sun4c */
- pmdp->pmdv[0] = PGD_TABLE | (unsigned long) page_address(ptep);
-}
-
-static int sun4c_pte_present(pte_t pte)
-{
- return ((pte_val(pte) & (_SUN4C_PAGE_PRESENT | _SUN4C_PAGE_PRIV)) != 0);
-}
-static void sun4c_pte_clear(pte_t *ptep) { *ptep = __pte(0); }
-
-static int sun4c_pmd_bad(pmd_t pmd)
-{
- return (((pmd_val(pmd) & ~PAGE_MASK) != PGD_TABLE) ||
- (!virt_addr_valid(pmd_val(pmd))));
-}
-
-static int sun4c_pmd_present(pmd_t pmd)
-{
- return ((pmd_val(pmd) & PGD_PRESENT) != 0);
-}
-
-#if 0 /* if PMD takes one word */
-static void sun4c_pmd_clear(pmd_t *pmdp) { *pmdp = __pmd(0); }
-#else /* if pmd_t is a longish aggregate */
-static void sun4c_pmd_clear(pmd_t *pmdp) {
- memset((void *)pmdp, 0, sizeof(pmd_t));
-}
-#endif
-
-static int sun4c_pgd_none(pgd_t pgd) { return 0; }
-static int sun4c_pgd_bad(pgd_t pgd) { return 0; }
-static int sun4c_pgd_present(pgd_t pgd) { return 1; }
-static void sun4c_pgd_clear(pgd_t * pgdp) { }
-
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
-static pte_t sun4c_pte_mkwrite(pte_t pte)
-{
- pte = __pte(pte_val(pte) | _SUN4C_PAGE_WRITE);
- if (pte_val(pte) & _SUN4C_PAGE_MODIFIED)
- pte = __pte(pte_val(pte) | _SUN4C_PAGE_SILENT_WRITE);
- return pte;
-}
-
-static pte_t sun4c_pte_mkdirty(pte_t pte)
-{
- pte = __pte(pte_val(pte) | _SUN4C_PAGE_MODIFIED);
- if (pte_val(pte) & _SUN4C_PAGE_WRITE)
- pte = __pte(pte_val(pte) | _SUN4C_PAGE_SILENT_WRITE);
- return pte;
-}
-
-static pte_t sun4c_pte_mkyoung(pte_t pte)
-{
- pte = __pte(pte_val(pte) | _SUN4C_PAGE_ACCESSED);
- if (pte_val(pte) & _SUN4C_PAGE_READ)
- pte = __pte(pte_val(pte) | _SUN4C_PAGE_SILENT_READ);
- return pte;
-}
-
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-static pte_t sun4c_mk_pte(struct page *page, pgprot_t pgprot)
-{
- return __pte(page_to_pfn(page) | pgprot_val(pgprot));
-}
-
-static pte_t sun4c_mk_pte_phys(unsigned long phys_page, pgprot_t pgprot)
-{
- return __pte((phys_page >> PAGE_SHIFT) | pgprot_val(pgprot));
-}
-
-static pte_t sun4c_mk_pte_io(unsigned long page, pgprot_t pgprot, int space)
-{
- return __pte(((page - PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(pgprot));
-}
-
-static unsigned long sun4c_pte_pfn(pte_t pte)
-{
- return pte_val(pte) & SUN4C_PFN_MASK;
-}
-
-static pte_t sun4c_pgoff_to_pte(unsigned long pgoff)
-{
- return __pte(pgoff | _SUN4C_PAGE_FILE);
-}
-
-static unsigned long sun4c_pte_to_pgoff(pte_t pte)
-{
- return pte_val(pte) & ((1UL << PTE_FILE_MAX_BITS) - 1);
-}
-
-
-static inline unsigned long sun4c_pmd_page_v(pmd_t pmd)
-{
- return (pmd_val(pmd) & PAGE_MASK);
-}
-
-static struct page *sun4c_pmd_page(pmd_t pmd)
-{
- return virt_to_page(sun4c_pmd_page_v(pmd));
-}
-
-static unsigned long sun4c_pgd_page(pgd_t pgd) { return 0; }
-
-/* to find an entry in a page-table-directory */
-static inline pgd_t *sun4c_pgd_offset(struct mm_struct * mm, unsigned long address)
-{
- return mm->pgd + (address >> SUN4C_PGDIR_SHIFT);
-}
-
-/* Find an entry in the second-level page table.. */
-static pmd_t *sun4c_pmd_offset(pgd_t * dir, unsigned long address)
-{
- return (pmd_t *) dir;
-}
-
-/* Find an entry in the third-level page table.. */
-pte_t *sun4c_pte_offset_kernel(pmd_t * dir, unsigned long address)
-{
- return (pte_t *) sun4c_pmd_page_v(*dir) +
- ((address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1));
-}
-
-static unsigned long sun4c_swp_type(swp_entry_t entry)
-{
- return (entry.val & SUN4C_SWP_TYPE_MASK);
-}
-
-static unsigned long sun4c_swp_offset(swp_entry_t entry)
-{
- return (entry.val >> SUN4C_SWP_OFF_SHIFT) & SUN4C_SWP_OFF_MASK;
-}
-
-static swp_entry_t sun4c_swp_entry(unsigned long type, unsigned long offset)
-{
- return (swp_entry_t) {
- (offset & SUN4C_SWP_OFF_MASK) << SUN4C_SWP_OFF_SHIFT
- | (type & SUN4C_SWP_TYPE_MASK) };
-}
-
-static void sun4c_free_pte_slow(pte_t *pte)
-{
- free_page((unsigned long)pte);
-}
-
-static void sun4c_free_pgd_slow(pgd_t *pgd)
-{
- free_page((unsigned long)pgd);
-}
-
-static pgd_t *sun4c_get_pgd_fast(void)
-{
- unsigned long *ret;
-
- if ((ret = pgd_quicklist) != NULL) {
- pgd_quicklist = (unsigned long *)(*ret);
- ret[0] = ret[1];
- pgtable_cache_size--;
- } else {
- pgd_t *init;
-
- ret = (unsigned long *)__get_free_page(GFP_KERNEL);
- memset (ret, 0, (KERNBASE / SUN4C_PGDIR_SIZE) * sizeof(pgd_t));
- init = sun4c_pgd_offset(&init_mm, 0);
- memcpy (((pgd_t *)ret) + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
- (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
- }
- return (pgd_t *)ret;
-}
-
-static void sun4c_free_pgd_fast(pgd_t *pgd)
-{
- *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
- pgd_quicklist = (unsigned long *) pgd;
- pgtable_cache_size++;
-}
-
-
-static inline pte_t *
-sun4c_pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
-{
- unsigned long *ret;
-
- if ((ret = (unsigned long *)pte_quicklist) != NULL) {
- pte_quicklist = (unsigned long *)(*ret);
- ret[0] = ret[1];
- pgtable_cache_size--;
- }
- return (pte_t *)ret;
-}
-
-static pte_t *sun4c_pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
-{
- pte_t *pte;
-
- if ((pte = sun4c_pte_alloc_one_fast(mm, address)) != NULL)
- return pte;
-
- pte = (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
- return pte;
-}
-
-static pgtable_t sun4c_pte_alloc_one(struct mm_struct *mm, unsigned long address)
-{
- pte_t *pte;
- struct page *page;
-
- pte = sun4c_pte_alloc_one_kernel(mm, address);
- if (pte == NULL)
- return NULL;
- page = virt_to_page(pte);
- pgtable_page_ctor(page);
- return page;
-}
-
-static inline void sun4c_free_pte_fast(pte_t *pte)
-{
- *(unsigned long *)pte = (unsigned long) pte_quicklist;
- pte_quicklist = (unsigned long *) pte;
- pgtable_cache_size++;
-}
-
-static void sun4c_pte_free(pgtable_t pte)
-{
- pgtable_page_dtor(pte);
- sun4c_free_pte_fast(page_address(pte));
-}
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-static pmd_t *sun4c_pmd_alloc_one(struct mm_struct *mm, unsigned long address)
-{
- BUG();
- return NULL;
-}
-
-static void sun4c_free_pmd_fast(pmd_t * pmd) { }
-
-static void sun4c_check_pgt_cache(int low, int high)
-{
- if (pgtable_cache_size > high) {
- do {
- if (pgd_quicklist)
- sun4c_free_pgd_slow(sun4c_get_pgd_fast());
- if (pte_quicklist)
- sun4c_free_pte_slow(sun4c_pte_alloc_one_fast(NULL, 0));
- } while (pgtable_cache_size > low);
- }
-}
-
-/* An experiment, turn off by default for now... -DaveM */
-#define SUN4C_PRELOAD_PSEG
-
-void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
-{
- unsigned long flags;
- int pseg;
-
- if (vma->vm_mm->context == NO_CONTEXT)
- return;
-
- local_irq_save(flags);
- address &= PAGE_MASK;
- if ((pseg = sun4c_get_segmap(address)) == invalid_segment) {
- struct sun4c_mmu_entry *entry = sun4c_user_strategy();
- struct mm_struct *mm = vma->vm_mm;
- unsigned long start, end;
-
- entry->vaddr = start = (address & SUN4C_REAL_PGDIR_MASK);
- entry->ctx = mm->context;
- add_ring_ordered(sun4c_context_ring + mm->context, entry);
- sun4c_put_segmap(entry->vaddr, entry->pseg);
- end = start + SUN4C_REAL_PGDIR_SIZE;
- while (start < end) {
-#ifdef SUN4C_PRELOAD_PSEG
- pgd_t *pgdp = sun4c_pgd_offset(mm, start);
- pte_t *ptep;
-
- if (!pgdp)
- goto no_mapping;
- ptep = sun4c_pte_offset_kernel((pmd_t *) pgdp, start);
- if (!ptep || !(pte_val(*ptep) & _SUN4C_PAGE_PRESENT))
- goto no_mapping;
- sun4c_put_pte(start, pte_val(*ptep));
- goto next;
-
- no_mapping:
-#endif
- sun4c_put_pte(start, 0);
-#ifdef SUN4C_PRELOAD_PSEG
- next:
-#endif
- start += PAGE_SIZE;
- }
-#ifndef SUN4C_PRELOAD_PSEG
- sun4c_put_pte(address, pte_val(*ptep));
-#endif
- local_irq_restore(flags);
- return;
- } else {
- struct sun4c_mmu_entry *entry = &mmu_entry_pool[pseg];
-
- remove_lru(entry);
- add_lru(entry);
- }
-
- sun4c_put_pte(address, pte_val(*ptep));
- local_irq_restore(flags);
-}
-
-extern void sparc_context_init(int);
-extern unsigned long bootmem_init(unsigned long *pages_avail);
-extern unsigned long last_valid_pfn;
-
-void __init sun4c_paging_init(void)
-{
- int i, cnt;
- unsigned long kernel_end, vaddr;
- extern struct resource sparc_iomap;
- unsigned long end_pfn, pages_avail;
-
- kernel_end = (unsigned long) &_end;
- kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
-
- pages_avail = 0;
- last_valid_pfn = bootmem_init(&pages_avail);
- end_pfn = last_valid_pfn;
-
- sun4c_probe_mmu();
- invalid_segment = (num_segmaps - 1);
- sun4c_init_mmu_entry_pool();
- sun4c_init_rings();
- sun4c_init_map_kernelprom(kernel_end);
- sun4c_init_clean_mmu(kernel_end);
- sun4c_init_fill_kernel_ring(SUN4C_KERNEL_BUCKETS);
- sun4c_init_lock_area(sparc_iomap.start, IOBASE_END);
- sun4c_init_lock_area(DVMA_VADDR, DVMA_END);
- sun4c_init_lock_areas();
- sun4c_init_fill_user_ring();
-
- sun4c_set_context(0);
- memset(swapper_pg_dir, 0, PAGE_SIZE);
- memset(pg0, 0, PAGE_SIZE);
- memset(pg1, 0, PAGE_SIZE);
- memset(pg2, 0, PAGE_SIZE);
- memset(pg3, 0, PAGE_SIZE);
-
- /* Save work later. */
- vaddr = VMALLOC_START;
- swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg0);
- vaddr += SUN4C_PGDIR_SIZE;
- swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg1);
- vaddr += SUN4C_PGDIR_SIZE;
- swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg2);
- vaddr += SUN4C_PGDIR_SIZE;
- swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg3);
- sun4c_init_ss2_cache_bug();
- sparc_context_init(num_contexts);
-
- {
- unsigned long zones_size[MAX_NR_ZONES];
- unsigned long zholes_size[MAX_NR_ZONES];
- unsigned long npages;
- int znum;
-
- for (znum = 0; znum < MAX_NR_ZONES; znum++)
- zones_size[znum] = zholes_size[znum] = 0;
-
- npages = max_low_pfn - pfn_base;
-
- zones_size[ZONE_DMA] = npages;
- zholes_size[ZONE_DMA] = npages - pages_avail;
-
- npages = highend_pfn - max_low_pfn;
- zones_size[ZONE_HIGHMEM] = npages;
- zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
-
- free_area_init_node(0, zones_size, pfn_base, zholes_size);
- }
-
- cnt = 0;
- for (i = 0; i < num_segmaps; i++)
- if (mmu_entry_pool[i].locked)
- cnt++;
-
- max_user_taken_entries = num_segmaps - cnt - 40 - 1;
-
- printk("SUN4C: %d mmu entries for the kernel\n", cnt);
-}
-
-static pgprot_t sun4c_pgprot_noncached(pgprot_t prot)
-{
- prot |= __pgprot(_SUN4C_PAGE_IO | _SUN4C_PAGE_NOCACHE);
-
- return prot;
-}
-
-/* Load up routines and constants for sun4c mmu */
-void __init ld_mmu_sun4c(void)
-{
- extern void ___xchg32_sun4c(void);
-
- printk("Loading sun4c MMU routines\n");
-
- /* First the constants */
- BTFIXUPSET_SIMM13(pgdir_shift, SUN4C_PGDIR_SHIFT);
- BTFIXUPSET_SETHI(pgdir_size, SUN4C_PGDIR_SIZE);
- BTFIXUPSET_SETHI(pgdir_mask, SUN4C_PGDIR_MASK);
-
- BTFIXUPSET_SIMM13(ptrs_per_pmd, SUN4C_PTRS_PER_PMD);
- BTFIXUPSET_SIMM13(ptrs_per_pgd, SUN4C_PTRS_PER_PGD);
- BTFIXUPSET_SIMM13(user_ptrs_per_pgd, KERNBASE / SUN4C_PGDIR_SIZE);
-
- BTFIXUPSET_INT(page_none, pgprot_val(SUN4C_PAGE_NONE));
- PAGE_SHARED = pgprot_val(SUN4C_PAGE_SHARED);
- BTFIXUPSET_INT(page_copy, pgprot_val(SUN4C_PAGE_COPY));
- BTFIXUPSET_INT(page_readonly, pgprot_val(SUN4C_PAGE_READONLY));
- BTFIXUPSET_INT(page_kernel, pgprot_val(SUN4C_PAGE_KERNEL));
- page_kernel = pgprot_val(SUN4C_PAGE_KERNEL);
-
- /* Functions */
- BTFIXUPSET_CALL(pgprot_noncached, sun4c_pgprot_noncached, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(___xchg32, ___xchg32_sun4c, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(do_check_pgt_cache, sun4c_check_pgt_cache, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(flush_cache_all, sun4c_flush_cache_all, BTFIXUPCALL_NORM);
-
- if (sun4c_vacinfo.do_hwflushes) {
- BTFIXUPSET_CALL(sun4c_flush_page, sun4c_flush_page_hw, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(sun4c_flush_segment, sun4c_flush_segment_hw, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(sun4c_flush_context, sun4c_flush_context_hw, BTFIXUPCALL_NORM);
- } else {
- BTFIXUPSET_CALL(sun4c_flush_page, sun4c_flush_page_sw, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(sun4c_flush_segment, sun4c_flush_segment_sw, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(sun4c_flush_context, sun4c_flush_context_sw, BTFIXUPCALL_NORM);
- }
-
- BTFIXUPSET_CALL(flush_tlb_mm, sun4c_flush_tlb_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_mm, sun4c_flush_cache_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(destroy_context, sun4c_destroy_context, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(switch_mm, sun4c_switch_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_page, sun4c_flush_cache_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_page, sun4c_flush_tlb_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_range, sun4c_flush_tlb_range, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_cache_range, sun4c_flush_cache_range, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(__flush_page_to_ram, sun4c_flush_page_to_ram, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_all, sun4c_flush_tlb_all, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(flush_sig_insns, sun4c_flush_sig_insns, BTFIXUPCALL_NOP);
-
- BTFIXUPSET_CALL(set_pte, sun4c_set_pte, BTFIXUPCALL_STO1O0);
-
- BTFIXUPSET_CALL(pte_pfn, sun4c_pte_pfn, BTFIXUPCALL_NORM);
-#if 0 /* PAGE_SHIFT <= 12 */ /* Eek. Investigate. XXX */
- BTFIXUPSET_CALL(pmd_page, sun4c_pmd_page, BTFIXUPCALL_ANDNINT(PAGE_SIZE - 1));
-#else
- BTFIXUPSET_CALL(pmd_page, sun4c_pmd_page, BTFIXUPCALL_NORM);
-#endif
- BTFIXUPSET_CALL(pmd_set, sun4c_pmd_set, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_populate, sun4c_pmd_populate, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(pte_present, sun4c_pte_present, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_clear, sun4c_pte_clear, BTFIXUPCALL_STG0O0);
-
- BTFIXUPSET_CALL(pmd_bad, sun4c_pmd_bad, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_present, sun4c_pmd_present, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_clear, sun4c_pmd_clear, BTFIXUPCALL_STG0O0);
-
- BTFIXUPSET_CALL(pgd_none, sun4c_pgd_none, BTFIXUPCALL_RETINT(0));
- BTFIXUPSET_CALL(pgd_bad, sun4c_pgd_bad, BTFIXUPCALL_RETINT(0));
- BTFIXUPSET_CALL(pgd_present, sun4c_pgd_present, BTFIXUPCALL_RETINT(1));
- BTFIXUPSET_CALL(pgd_clear, sun4c_pgd_clear, BTFIXUPCALL_NOP);
-
- BTFIXUPSET_CALL(mk_pte, sun4c_mk_pte, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mk_pte_phys, sun4c_mk_pte_phys, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mk_pte_io, sun4c_mk_pte_io, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_INT(pte_modify_mask, _SUN4C_PAGE_CHG_MASK);
- BTFIXUPSET_CALL(pmd_offset, sun4c_pmd_offset, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_offset_kernel, sun4c_pte_offset_kernel, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(free_pte_fast, sun4c_free_pte_fast, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_free, sun4c_pte_free, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_alloc_one_kernel, sun4c_pte_alloc_one_kernel, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_alloc_one, sun4c_pte_alloc_one, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(free_pmd_fast, sun4c_free_pmd_fast, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(pmd_alloc_one, sun4c_pmd_alloc_one, BTFIXUPCALL_RETO0);
- BTFIXUPSET_CALL(free_pgd_fast, sun4c_free_pgd_fast, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(get_pgd_fast, sun4c_get_pgd_fast, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_HALF(pte_writei, _SUN4C_PAGE_WRITE);
- BTFIXUPSET_HALF(pte_dirtyi, _SUN4C_PAGE_MODIFIED);
- BTFIXUPSET_HALF(pte_youngi, _SUN4C_PAGE_ACCESSED);
- BTFIXUPSET_HALF(pte_filei, _SUN4C_PAGE_FILE);
- BTFIXUPSET_HALF(pte_wrprotecti, _SUN4C_PAGE_WRITE|_SUN4C_PAGE_SILENT_WRITE);
- BTFIXUPSET_HALF(pte_mkcleani, _SUN4C_PAGE_MODIFIED|_SUN4C_PAGE_SILENT_WRITE);
- BTFIXUPSET_HALF(pte_mkoldi, _SUN4C_PAGE_ACCESSED|_SUN4C_PAGE_SILENT_READ);
- BTFIXUPSET_CALL(pte_mkwrite, sun4c_pte_mkwrite, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_mkdirty, sun4c_pte_mkdirty, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_mkyoung, sun4c_pte_mkyoung, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(update_mmu_cache, sun4c_update_mmu_cache, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(pte_to_pgoff, sun4c_pte_to_pgoff, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgoff_to_pte, sun4c_pgoff_to_pte, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(mmu_lockarea, sun4c_lockarea, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_unlockarea, sun4c_unlockarea, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(mmu_get_scsi_one, sun4c_get_scsi_one, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_get_scsi_sgl, sun4c_get_scsi_sgl, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_release_scsi_one, sun4c_release_scsi_one, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_release_scsi_sgl, sun4c_release_scsi_sgl, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(mmu_map_dma_area, sun4c_map_dma_area, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_unmap_dma_area, sun4c_unmap_dma_area, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(sparc_mapiorange, sun4c_mapiorange, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(sparc_unmapiorange, sun4c_unmapiorange, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(__swp_type, sun4c_swp_type, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(__swp_offset, sun4c_swp_offset, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(__swp_entry, sun4c_swp_entry, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(alloc_thread_info_node, sun4c_alloc_thread_info_node, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(free_thread_info, sun4c_free_thread_info, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(mmu_info, sun4c_mmu_info, BTFIXUPCALL_NORM);
-
- /* These should _never_ get called with two level tables. */
- BTFIXUPSET_CALL(pgd_set, sun4c_pgd_set, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(pgd_page_vaddr, sun4c_pgd_page, BTFIXUPCALL_RETO0);
-}
diff --git a/arch/sparc/mm/viking.S b/arch/sparc/mm/viking.S
index 6dfcc13d3100..bf8ee0613ae7 100644
--- a/arch/sparc/mm/viking.S
+++ b/arch/sparc/mm/viking.S
@@ -14,7 +14,6 @@
#include <asm/page.h>
#include <asm/pgtsrmmu.h>
#include <asm/viking.h>
-#include <asm/btfixup.h>
#ifdef CONFIG_SMP
.data
diff --git a/arch/sparc/prom/Makefile b/arch/sparc/prom/Makefile
index 8287bbe88768..020300b18c0b 100644
--- a/arch/sparc/prom/Makefile
+++ b/arch/sparc/prom/Makefile
@@ -10,7 +10,6 @@ lib-$(CONFIG_SPARC32) += memory.o
lib-y += misc_$(BITS).o
lib-$(CONFIG_SPARC32) += mp.o
lib-$(CONFIG_SPARC32) += ranges.o
-lib-$(CONFIG_SPARC32) += segment.o
lib-y += console_$(BITS).o
lib-y += printf.o
lib-y += tree_$(BITS).o
diff --git a/arch/sparc/prom/segment.c b/arch/sparc/prom/segment.c
deleted file mode 100644
index 86a663f1d3c5..000000000000
--- a/arch/sparc/prom/segment.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * segment.c: Prom routine to map segments in other contexts before
- * a standalone is completely mapped. This is for sun4 and
- * sun4c architectures only.
- *
- * 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);
-
-/* Set physical segment 'segment' at virtual address 'vaddr' in
- * context 'ctx'.
- */
-void
-prom_putsegment(int ctx, unsigned long vaddr, int segment)
-{
- unsigned long flags;
- spin_lock_irqsave(&prom_lock, flags);
- (*(romvec->pv_setctxt))(ctx, (char *) vaddr, segment);
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
-}
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 96033e2d6845..74239dd77e06 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -11,6 +11,7 @@ config TILE
select GENERIC_IRQ_PROBE
select GENERIC_PENDING_IRQ if SMP
select GENERIC_IRQ_SHOW
+ select HAVE_SYSCALL_WRAPPERS if TILEGX
select SYS_HYPERVISOR
select ARCH_HAVE_NMI_SAFE_CMPXCHG
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h
index 34c1e01ffb5e..15cd8a4a06ce 100644
--- a/arch/tile/include/asm/processor.h
+++ b/arch/tile/include/asm/processor.h
@@ -210,9 +210,6 @@ static inline void release_thread(struct task_struct *dead_task)
/* Nothing for now */
}
-/* Prepare to copy thread state - unlazy all lazy status. */
-#define prepare_to_copy(tsk) do { } while (0)
-
extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
extern int do_work_pending(struct pt_regs *regs, u32 flags);
diff --git a/arch/tile/include/asm/thread_info.h b/arch/tile/include/asm/thread_info.h
index 7594764d8a69..656c486e64fa 100644
--- a/arch/tile/include/asm/thread_info.h
+++ b/arch/tile/include/asm/thread_info.h
@@ -77,16 +77,14 @@ struct thread_info {
#ifndef __ASSEMBLY__
+void arch_release_thread_info(struct thread_info *info);
+
/* How to get the thread information struct from C. */
register unsigned long stack_pointer __asm__("sp");
#define current_thread_info() \
((struct thread_info *)(stack_pointer & -THREAD_SIZE))
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-extern struct thread_info *alloc_thread_info_node(struct task_struct *task, int node);
-extern void free_thread_info(struct thread_info *info);
-
/* Sit on a nap instruction until interrupted. */
extern void smp_nap(void);
diff --git a/arch/tile/include/asm/topology.h b/arch/tile/include/asm/topology.h
index 6fdd0c860193..7a7ce390534f 100644
--- a/arch/tile/include/asm/topology.h
+++ b/arch/tile/include/asm/topology.h
@@ -78,32 +78,6 @@ static inline const struct cpumask *cpumask_of_node(int node)
.balance_interval = 32, \
}
-/* sched_domains SD_NODE_INIT for TILE architecture */
-#define SD_NODE_INIT (struct sched_domain) { \
- .min_interval = 16, \
- .max_interval = 512, \
- .busy_factor = 32, \
- .imbalance_pct = 125, \
- .cache_nice_tries = 1, \
- .busy_idx = 3, \
- .idle_idx = 1, \
- .newidle_idx = 2, \
- .wake_idx = 1, \
- .flags = 1*SD_LOAD_BALANCE \
- | 1*SD_BALANCE_NEWIDLE \
- | 1*SD_BALANCE_EXEC \
- | 1*SD_BALANCE_FORK \
- | 0*SD_BALANCE_WAKE \
- | 0*SD_WAKE_AFFINE \
- | 0*SD_PREFER_LOCAL \
- | 0*SD_SHARE_CPUPOWER \
- | 0*SD_SHARE_PKG_RESOURCES \
- | 1*SD_SERIALIZE \
- , \
- .last_balance = jiffies, \
- .balance_interval = 128, \
-}
-
/* By definition, we create nodes based on online memory. */
#define node_has_online_mem(nid) 1
diff --git a/arch/tile/kernel/Makefile b/arch/tile/kernel/Makefile
index b4dbc057baad..0d826faf8f35 100644
--- a/arch/tile/kernel/Makefile
+++ b/arch/tile/kernel/Makefile
@@ -3,7 +3,7 @@
#
extra-y := vmlinux.lds head_$(BITS).o
-obj-y := backtrace.o entry.o init_task.o irq.o messaging.o \
+obj-y := backtrace.o entry.o irq.o messaging.o \
pci-dma.o proc.o process.o ptrace.o reboot.o \
setup.o signal.o single_step.o stack.o sys.o sysfs.o time.o traps.o \
intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o
diff --git a/arch/tile/kernel/init_task.c b/arch/tile/kernel/init_task.c
deleted file mode 100644
index 928b31870669..000000000000
--- a/arch/tile/kernel/init_task.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, version 2.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for
- * more details.
- */
-
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/init_task.h>
-#include <linux/mqueue.h>
-#include <linux/module.h>
-#include <linux/start_kernel.h>
-#include <linux/uaccess.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is THREAD_SIZE aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data = {
- INIT_THREAD_INFO(init_task)
-};
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
-
-/*
- * per-CPU stack and boot info.
- */
-DEFINE_PER_CPU(unsigned long, boot_sp) =
- (unsigned long)init_stack + THREAD_SIZE;
-
-#ifdef CONFIG_SMP
-DEFINE_PER_CPU(unsigned long, boot_pc) = (unsigned long)start_kernel;
-#else
-/*
- * The variable must be __initdata since it references __init code.
- * With CONFIG_SMP it is per-cpu data, which is exempt from validation.
- */
-unsigned long __initdata boot_pc = (unsigned long)start_kernel;
-#endif
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index 54e6c64b85cc..f572c19c4082 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -114,27 +114,10 @@ void cpu_idle(void)
}
}
-struct thread_info *alloc_thread_info_node(struct task_struct *task, int node)
-{
- struct page *page;
- gfp_t flags = GFP_KERNEL;
-
-#ifdef CONFIG_DEBUG_STACK_USAGE
- flags |= __GFP_ZERO;
-#endif
-
- page = alloc_pages_node(node, flags, THREAD_SIZE_ORDER);
- if (!page)
- return NULL;
-
- return (struct thread_info *)page_address(page);
-}
-
/*
- * Free a thread_info node, and all of its derivative
- * data structures.
+ * Release a thread_info structure
*/
-void free_thread_info(struct thread_info *info)
+void arch_release_thread_info(struct thread_info *info)
{
struct single_step_state *step_state = info->step_state;
@@ -169,8 +152,6 @@ void free_thread_info(struct thread_info *info)
*/
kfree(step_state);
}
-
- free_pages((unsigned long)info, THREAD_SIZE_ORDER);
}
static void save_arch_state(struct thread_struct *t);
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index bff23f476110..98d80eb49ddb 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -61,6 +61,22 @@ unsigned long __initdata node_free_pfn[MAX_NUMNODES];
static unsigned long __initdata node_percpu[MAX_NUMNODES];
+/*
+ * per-CPU stack and boot info.
+ */
+DEFINE_PER_CPU(unsigned long, boot_sp) =
+ (unsigned long)init_stack + THREAD_SIZE;
+
+#ifdef CONFIG_SMP
+DEFINE_PER_CPU(unsigned long, boot_pc) = (unsigned long)start_kernel;
+#else
+/*
+ * The variable must be __initdata since it references __init code.
+ * With CONFIG_SMP it is per-cpu data, which is exempt from validation.
+ */
+unsigned long __initdata boot_pc = (unsigned long)start_kernel;
+#endif
+
#ifdef CONFIG_HIGHMEM
/* Page frame index of end of lowmem on each controller. */
unsigned long __cpuinitdata node_lowmem_end_pfn[MAX_NUMNODES];
diff --git a/arch/tile/kernel/smpboot.c b/arch/tile/kernel/smpboot.c
index 172aef7d3159..84873fbe8f27 100644
--- a/arch/tile/kernel/smpboot.c
+++ b/arch/tile/kernel/smpboot.c
@@ -222,7 +222,7 @@ void __cpuinit online_secondary(void)
cpu_idle();
}
-int __cpuinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
/* Wait 5s total for all CPUs for them to come online */
static int timeout;
diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common
index 20a49ba93cb9..43ef890d292c 100644
--- a/arch/um/Kconfig.common
+++ b/arch/um/Kconfig.common
@@ -56,11 +56,6 @@ config GENERIC_CLOCKEVENTS
bool
default y
-# Used in kernel/irq/manage.c and include/linux/irq.h
-config IRQ_RELEASE_METHOD
- bool
- default y
-
config HZ
int
default 100
diff --git a/arch/um/defconfig b/arch/um/defconfig
index fdc97e2c3d73..7823ab12e6a4 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -12,7 +12,6 @@ CONFIG_LOCKDEP_SUPPORT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_IRQ_RELEASE_METHOD=y
CONFIG_HZ=100
#
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index ca4c7ebfd0aa..45e248c2f43c 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -8,6 +8,7 @@
#include <linux/tty_flip.h>
#include "chan.h"
#include "os.h"
+#include "irq_kern.h"
#ifdef CONFIG_NOCONFIG_CHAN
static void *not_configged_init(char *str, int device,
@@ -213,9 +214,9 @@ void free_irqs(void)
chan = list_entry(ele, struct chan, free_list);
if (chan->input && chan->enabled)
- free_irq(chan->line->driver->read_irq, chan);
+ um_free_irq(chan->line->driver->read_irq, chan);
if (chan->output && chan->enabled)
- free_irq(chan->line->driver->write_irq, chan);
+ um_free_irq(chan->line->driver->write_irq, chan);
chan->enabled = 0;
}
}
@@ -234,9 +235,9 @@ static void close_one_chan(struct chan *chan, int delay_free_irq)
}
else {
if (chan->input && chan->enabled)
- free_irq(chan->line->driver->read_irq, chan);
+ um_free_irq(chan->line->driver->read_irq, chan);
if (chan->output && chan->enabled)
- free_irq(chan->line->driver->write_irq, chan);
+ um_free_irq(chan->line->driver->write_irq, chan);
chan->enabled = 0;
}
if (chan->ops->close != NULL)
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 4ab0d9c0911c..acfd0e0fd0c9 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -699,7 +699,7 @@ struct winch {
static void __free_winch(struct work_struct *work)
{
struct winch *winch = container_of(work, struct winch, work);
- free_irq(WINCH_IRQ, winch);
+ um_free_irq(WINCH_IRQ, winch);
if (winch->pid != -1)
os_kill_process(winch->pid, 1);
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 43b39d61b538..88e466b159dc 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -705,6 +705,7 @@ static void stack_proc(void *arg)
struct task_struct *from = current, *to = arg;
to->thread.saved_task = from;
+ rcu_switch_from(from);
switch_to(from, to, from);
}
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 95f4416e6d9f..0d60c5685c26 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -195,7 +195,7 @@ static int uml_net_close(struct net_device *dev)
netif_stop_queue(dev);
- free_irq(dev->irq, dev);
+ um_free_irq(dev->irq, dev);
if (lp->close != NULL)
(*lp->close)(lp->fd, &lp->user);
lp->fd = -1;
@@ -835,7 +835,7 @@ static void close_devices(void)
spin_lock(&opened_lock);
list_for_each(ele, &opened) {
lp = list_entry(ele, struct uml_net_private, list);
- free_irq(lp->dev->irq, lp->dev);
+ um_free_irq(lp->dev->irq, lp->dev);
if ((lp->close != NULL) && (lp->fd >= 0))
(*lp->close)(lp->fd, &lp->user);
if (lp->remove != NULL)
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index e31680e662a4..11866ffd45a9 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -254,7 +254,7 @@ int port_wait(void *data)
* connection. Then we loop here throwing out failed
* connections until a good one is found.
*/
- free_irq(TELNETD_IRQ, conn);
+ um_free_irq(TELNETD_IRQ, conn);
if (conn->fd >= 0)
break;
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index 8bd130f0bda3..b68bbe269e01 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -65,7 +65,7 @@ int xterm_fd(int socket, int *pid_out)
* isn't set) this will hang... */
wait_for_completion(&data->ready);
- free_irq(XTERM_IRQ, data);
+ um_free_irq(XTERM_IRQ, data);
ret = data->new_fd;
*pid_out = data->pid;
diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h
index 6a3f9845743e..5888f1b83477 100644
--- a/arch/um/include/asm/pgtable.h
+++ b/arch/um/include/asm/pgtable.h
@@ -273,6 +273,12 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
}
#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+#define __HAVE_ARCH_PTE_SAME
+static inline int pte_same(pte_t pte_a, pte_t pte_b)
+{
+ return !((pte_val(pte_a) ^ pte_val(pte_b)) & ~_PAGE_NEWPAGE);
+}
+
/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
@@ -348,11 +354,11 @@ extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr);
#define update_mmu_cache(vma,address,ptep) do ; while (0)
/* Encode and de-code a swap entry */
-#define __swp_type(x) (((x).val >> 4) & 0x3f)
+#define __swp_type(x) (((x).val >> 5) & 0x1f)
#define __swp_offset(x) ((x).val >> 11)
#define __swp_entry(type, offset) \
- ((swp_entry_t) { ((type) << 4) | ((offset) << 11) })
+ ((swp_entry_t) { ((type) << 5) | ((offset) << 11) })
#define __pte_to_swp_entry(pte) \
((swp_entry_t) { pte_val(pte_mkuptodate(pte)) })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h
index 98d01bc4fa92..69f1c57a8d0d 100644
--- a/arch/um/include/asm/processor-generic.h
+++ b/arch/um/include/asm/processor-generic.h
@@ -68,19 +68,12 @@ struct thread_struct {
.request = { 0 } \
}
-extern struct task_struct *alloc_task_struct_node(int node);
-
static inline void release_thread(struct task_struct *task)
{
}
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-static inline void prepare_to_copy(struct task_struct *tsk)
-{
-}
-
-
extern unsigned long thread_saved_pc(struct task_struct *t);
static inline void mm_copy_segments(struct mm_struct *from_mm,
diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h
index 200c4ab1240c..c04e5ab68f56 100644
--- a/arch/um/include/asm/thread_info.h
+++ b/arch/um/include/asm/thread_info.h
@@ -71,6 +71,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_MEMDIE 5 /* is terminating due to OOM killer */
#define TIF_SYSCALL_AUDIT 6
#define TIF_RESTORE_SIGMASK 7
+#define TIF_NOTIFY_RESUME 8
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
@@ -78,6 +79,5 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_MEMDIE (1 << TIF_MEMDIE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
-#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#endif
diff --git a/arch/um/include/shared/irq_kern.h b/arch/um/include/shared/irq_kern.h
index b05d22f3d84e..7a5bfa6291b8 100644
--- a/arch/um/include/shared/irq_kern.h
+++ b/arch/um/include/shared/irq_kern.h
@@ -13,6 +13,6 @@ extern int um_request_irq(unsigned int irq, int fd, int type,
irq_handler_t handler,
unsigned long irqflags, const char * devname,
void *dev_id);
-
+void um_free_irq(unsigned int irq, void *dev);
#endif
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 65a1c3d690ea..babe21826e3e 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -10,7 +10,7 @@ CPPFLAGS_vmlinux.lds := -DSTART=$(LDS_START) \
extra-y := vmlinux.lds
clean-files :=
-obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
+obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \
physmem.o process.o ptrace.o reboot.o sigio.o \
signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \
um_arch.o umid.o skas/
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
deleted file mode 100644
index ddc9698b66ed..000000000000
--- a/arch/um/kernel/init_task.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,intel.linux}.com)
- * Licensed under the GPL
- */
-
-#include "linux/sched.h"
-#include "linux/init_task.h"
-#include "linux/fs.h"
-#include "linux/module.h"
-#include "linux/mqueue.h"
-#include "asm/uaccess.h"
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
-
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-union thread_union cpu0_irqstack
- __attribute__((__section__(".data..init_irqstack"))) =
- { INIT_THREAD_INFO(init_task) };
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 71b8c947e5ef..00506c3d5d6e 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -297,6 +297,13 @@ unsigned int do_IRQ(int irq, struct uml_pt_regs *regs)
return 1;
}
+void um_free_irq(unsigned int irq, void *dev)
+{
+ free_irq_by_irq_and_dev(irq, dev);
+ free_irq(irq, dev);
+}
+EXPORT_SYMBOL(um_free_irq);
+
int um_request_irq(unsigned int irq, int fd, int type,
irq_handler_t handler,
unsigned long irqflags, const char * devname,
@@ -327,7 +334,6 @@ static void dummy(struct irq_data *d)
/* This is used for everything else than the timer. */
static struct irq_chip normal_irq_type = {
.name = "SIGIO",
- .release = free_irq_by_irq_and_dev,
.irq_disable = dummy,
.irq_enable = dummy,
.irq_ack = dummy,
@@ -335,7 +341,6 @@ static struct irq_chip normal_irq_type = {
static struct irq_chip SIGVTALRM_irq_type = {
.name = "SIGVTALRM",
- .release = free_irq_by_irq_and_dev,
.irq_disable = dummy,
.irq_enable = dummy,
.irq_ack = dummy,
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 2b73dedb44ca..3a2235e0abc3 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -18,6 +18,7 @@
#include <linux/seq_file.h>
#include <linux/tick.h>
#include <linux/threads.h>
+#include <linux/tracehook.h>
#include <asm/current.h>
#include <asm/pgtable.h>
#include <asm/mmu_context.h>
@@ -114,8 +115,13 @@ void interrupt_end(void)
{
if (need_resched())
schedule();
- if (test_tsk_thread_flag(current, TIF_SIGPENDING))
+ if (test_thread_flag(TIF_SIGPENDING))
do_signal();
+ if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) {
+ tracehook_notify_resume(&current->thread.regs);
+ if (current->replacement_session_keyring)
+ key_replace_session_keyring();
+ }
}
void exit_thread(void)
@@ -190,7 +196,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
if (current->thread.forking) {
memcpy(&p->thread.regs.regs, &regs->regs,
sizeof(p->thread.regs.regs));
- REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.gp, 0);
+ UPT_SET_SYSCALL_RETURN(&p->thread.regs.regs, 0);
if (sp != 0)
REGS_SP(p->thread.regs.regs.gp) = sp;
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index fb12f4c5e649..187118fbe1bc 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -29,9 +29,6 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
unsigned long sp;
int err;
- /* Always make any pending restarted system calls return -EINTR */
- current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
/* Did we come from a system call? */
if (PT_REGS_SYSCALL_NR(regs) >= 0) {
/* If so, check system call restarting.. */
@@ -77,15 +74,14 @@ static int kern_do_signal(struct pt_regs *regs)
{
struct k_sigaction ka_copy;
siginfo_t info;
- sigset_t *oldset;
int sig, handled_sig = 0;
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
- oldset = &current->saved_sigmask;
- else
- oldset = &current->blocked;
-
while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) {
+ sigset_t *oldset;
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
+ oldset = &current->blocked;
handled_sig = 1;
/* Whee! Actually deliver the signal. */
if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) {
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c
index f5173e1ec3ac..05fbeb480e0b 100644
--- a/arch/um/kernel/skas/syscall.c
+++ b/arch/um/kernel/skas/syscall.c
@@ -34,7 +34,7 @@ void handle_syscall(struct uml_pt_regs *r)
result = -ENOSYS;
else result = EXECUTE_SYSCALL(syscall, regs);
- REGS_SET_SYSCALL_RETURN(r->gp, result);
+ UPT_SET_SYSCALL_RETURN(r, result);
syscall_trace(r, 1);
}
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index 6f588e160fb0..a02b7e9e6b94 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -140,7 +140,7 @@ void smp_prepare_boot_cpu(void)
set_cpu_online(smp_processor_id(), true);
}
-int __cpu_up(unsigned int cpu)
+int __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
cpu_set(cpu, smp_commenced_mask);
while (!cpu_online(cpu))
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 7f3d4d86431a..f819af951c19 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -75,6 +75,7 @@ static int do_ops(struct host_vm_change *hvc, int end,
default:
printk(KERN_ERR "Unknown op type %d in do_ops\n",
op->type);
+ BUG();
break;
}
}
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index ba00eae45aad..4db8770906ca 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -10,6 +10,7 @@
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/utsname.h>
+#include <linux/sched.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/setup.h>
@@ -47,6 +48,10 @@ struct cpuinfo_um boot_cpu_data = {
.ipi_pipe = { -1, -1 }
};
+union thread_union cpu0_irqstack
+ __attribute__((__section__(".data..init_irqstack"))) =
+ { INIT_THREAD_INFO(init_task) };
+
unsigned long thread_saved_pc(struct task_struct *task)
{
/* FIXME: Need to look up userspace_pid by cpu */
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index c0afff7af4bd..90b310d29179 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -48,10 +48,6 @@ __initcall(init_syscall_regs);
extern int proc_mm;
-int single_count = 0;
-int multi_count = 0;
-int multi_op_count = 0;
-
static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
{
int n, i;
@@ -64,8 +60,6 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
/* FIXME: Need to look up userspace_pid by cpu */
pid = userspace_pid[0];
- multi_count++;
-
n = ptrace_setregs(pid, syscall_regs);
if (n < 0) {
printk(UM_KERN_ERR "Registers - \n");
@@ -126,9 +120,6 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall,
{
unsigned long *stack = check_init_stack(mm_idp, *addr);
- if (done && *addr == NULL)
- single_count++;
-
*stack += sizeof(long);
stack += *stack / sizeof(long);
@@ -141,7 +132,6 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall,
*stack++ = args[5];
*stack++ = expected;
*stack = 0;
- multi_op_count++;
if (!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) <
UM_KERN_PAGE_SIZE - 10 * sizeof(long))) {
diff --git a/arch/unicore32/Makefile b/arch/unicore32/Makefile
index 6af4bc415f2b..b6f5c4c1eaf9 100644
--- a/arch/unicore32/Makefile
+++ b/arch/unicore32/Makefile
@@ -33,7 +33,6 @@ endif
CHECKFLAGS += -D__unicore32__
head-y := arch/unicore32/kernel/head.o
-head-y += arch/unicore32/kernel/init_task.o
core-y += arch/unicore32/kernel/
core-y += arch/unicore32/mm/
diff --git a/arch/unicore32/include/asm/processor.h b/arch/unicore32/include/asm/processor.h
index f0d780a51f9b..14382cb09657 100644
--- a/arch/unicore32/include/asm/processor.h
+++ b/arch/unicore32/include/asm/processor.h
@@ -68,9 +68,6 @@ struct task_struct;
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
unsigned long get_wchan(struct task_struct *p);
#define cpu_relax() barrier()
diff --git a/arch/unicore32/kernel/Makefile b/arch/unicore32/kernel/Makefile
index aeb0f181568e..324010156958 100644
--- a/arch/unicore32/kernel/Makefile
+++ b/arch/unicore32/kernel/Makefile
@@ -29,4 +29,4 @@ obj-$(CONFIG_PUV3_NB0916) += puv3-nb0916.o
head-y := head.o
obj-$(CONFIG_DEBUG_LL) += debug.o
-extra-y := $(head-y) init_task.o vmlinux.lds
+extra-y := $(head-y) vmlinux.lds
diff --git a/arch/unicore32/kernel/init_task.c b/arch/unicore32/kernel/init_task.c
deleted file mode 100644
index a35a1e50e4f4..000000000000
--- a/arch/unicore32/kernel/init_task.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * linux/arch/unicore32/kernel/init_task.c
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * 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/mm.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/mqueue.h>
-#include <linux/uaccess.h>
-
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is 8192-byte aligned due to the
- * way process stacks are handled. This is done by making sure
- * the linker maps this in the .text segment right after head.S,
- * and making head.S ensure the proper alignment.
- *
- * The things we do for performance..
- */
-union thread_union init_thread_union __init_task_data = {
- INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 9137057152c3..d6168994e115 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -12,6 +12,7 @@ config X86_32
config X86_64
def_bool 64BIT
+ select X86_DEV_DMA_OPS
### Arch settings
config X86
@@ -40,7 +41,6 @@ config X86
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_GRAPH_FP_TEST
select HAVE_FUNCTION_TRACE_MCOUNT_TEST
- select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KVM
select HAVE_ARCH_KGDB
@@ -77,11 +77,14 @@ config X86
select GENERIC_CLOCKEVENTS_MIN_ADJUST
select IRQ_FORCED_THREADING
select USE_GENERIC_SMP_HELPERS if SMP
- select HAVE_BPF_JIT if (X86_64 && NET)
+ select HAVE_BPF_JIT if X86_64
select CLKEVT_I8253
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select GENERIC_IOMAP
select DCACHE_WORD_ACCESS
+ select GENERIC_SMP_IDLE_THREAD
+ select HAVE_ARCH_SECCOMP_FILTER
+ select BUILDTIME_EXTABLE_SORT
config INSTRUCTION_DECODER
def_bool (KPROBES || PERF_EVENTS)
@@ -160,9 +163,6 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
def_bool X86_XADD
-config ARCH_HAS_CPU_IDLE_WAIT
- def_bool y
-
config GENERIC_CALIBRATE_DELAY
def_bool y
@@ -328,6 +328,7 @@ config X86_EXTENDED_PLATFORM
NUMAQ (IBM/Sequent)
RDC R-321x SoC
SGI 320/540 (Visual Workstation)
+ STA2X11-based (e.g. Northville)
Summit/EXA (IBM x440)
Unisys ES7000 IA32 series
Moorestown MID devices
@@ -374,6 +375,7 @@ config X86_VSMP
select PARAVIRT
depends on X86_64 && PCI
depends on X86_EXTENDED_PLATFORM
+ depends on SMP
---help---
Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is
supposed to run on these EM64T-based machines. Only choose this option
@@ -460,10 +462,10 @@ config X86_32_NON_STANDARD
depends on X86_32 && SMP
depends on X86_EXTENDED_PLATFORM
---help---
- This option compiles in the NUMAQ, Summit, bigsmp, ES7000, default
- subarchitectures. It is intended for a generic binary kernel.
- if you select them all, kernel will probe it one by one. and will
- fallback to default.
+ This option compiles in the NUMAQ, Summit, bigsmp, ES7000,
+ STA2X11, default subarchitectures. It is intended for a generic
+ binary kernel. If you select them all, kernel will probe it
+ one by one and will fallback to default.
# Alphabetically sorted list of Non standard 32 bit platforms
@@ -503,6 +505,22 @@ config X86_VISWS
A kernel compiled for the Visual Workstation will run on general
PCs as well. See <file:Documentation/sgi-visws.txt> for details.
+config STA2X11
+ bool "STA2X11 Companion Chip Support"
+ depends on X86_32_NON_STANDARD && PCI
+ select X86_DEV_DMA_OPS
+ select X86_DMA_REMAP
+ select SWIOTLB
+ select MFD_STA2X11
+ select ARCH_REQUIRE_GPIOLIB
+ default n
+ ---help---
+ This adds support for boards based on the STA2X11 IO-Hub,
+ a.k.a. "ConneXt". The chip is used in place of the standard
+ PC chipset, so all "standard" peripherals are missing. If this
+ option is selected the kernel will still be able to boot on
+ standard PC machines.
+
config X86_SUMMIT
bool "Summit/EXA (IBM x440)"
depends on X86_32_NON_STANDARD
@@ -1239,10 +1257,6 @@ config NODES_SHIFT
Specify the maximum number of NUMA Nodes available on the target
system. Increases memory reserved to accommodate various tables.
-config HAVE_ARCH_BOOTMEM
- def_bool y
- depends on X86_32 && NUMA
-
config HAVE_ARCH_ALLOC_REMAP
def_bool y
depends on X86_32 && NUMA
@@ -2205,6 +2219,14 @@ config HAVE_TEXT_POKE_SMP
bool
select STOP_MACHINE if SMP
+config X86_DEV_DMA_OPS
+ bool
+ depends on X86_64 || STA2X11
+
+config X86_DMA_REMAP
+ bool
+ depends on STA2X11
+
source "net/Kconfig"
source "drivers/Kconfig"
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 41a7237606a3..1f2521434554 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -115,9 +115,10 @@ cfi-sections := $(call as-instr,.cfi_sections .debug_frame,-DCONFIG_AS_CFI_SECTI
# does binutils support specific instructions?
asinstr := $(call as-instr,fxsaveq (%rax),-DCONFIG_AS_FXSAVEQ=1)
+avx_instr := $(call as-instr,vxorps %ymm0$(comma)%ymm1$(comma)%ymm2,-DCONFIG_AS_AVX=1)
-KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr)
-KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr)
+KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr)
+KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr)
LDFLAGS := -m elf_$(UTS_MACHINE)
@@ -134,6 +135,9 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,)
KBUILD_CFLAGS += $(mflags-y)
KBUILD_AFLAGS += $(mflags-y)
+archscripts:
+ $(Q)$(MAKE) $(build)=arch/x86/tools relocs
+
###
# Syscall table generation
@@ -146,7 +150,6 @@ archheaders:
head-y := arch/x86/kernel/head_$(BITS).o
head-y += arch/x86/kernel/head$(BITS).o
head-y += arch/x86/kernel/head.o
-head-y += arch/x86/kernel/init_task.o
libs-y += arch/x86/lib/
@@ -203,6 +206,7 @@ archclean:
$(Q)rm -rf $(objtree)/arch/i386
$(Q)rm -rf $(objtree)/arch/x86_64
$(Q)$(MAKE) $(clean)=$(boot)
+ $(Q)$(MAKE) $(clean)=arch/x86/tools
define archhelp
echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)'
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index fd55a2ff3ad8..e398bb5d63bb 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -40,13 +40,12 @@ OBJCOPYFLAGS_vmlinux.bin := -R .comment -S
$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy)
+targets += vmlinux.bin.all vmlinux.relocs
-targets += vmlinux.bin.all vmlinux.relocs relocs
-hostprogs-$(CONFIG_X86_NEED_RELOCS) += relocs
-
+CMD_RELOCS = arch/x86/tools/relocs
quiet_cmd_relocs = RELOCS $@
- cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $<
-$(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE
+ cmd_relocs = $(CMD_RELOCS) $< > $@;$(CMD_RELOCS) --abs-relocs $<
+$(obj)/vmlinux.relocs: vmlinux FORCE
$(call if_changed,relocs)
vmlinux.bin.all-y := $(obj)/vmlinux.bin
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 0cdfc0d2315e..2c14e76bb4c7 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -904,11 +904,19 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table)
memset(boot_params, 0x0, 0x4000);
- /* Copy first two sectors to boot_params */
- memcpy(boot_params, image->image_base, 1024);
-
hdr = &boot_params->hdr;
+ /* Copy the second sector to boot_params */
+ memcpy(&hdr->jump, image->image_base + 512, 512);
+
+ /*
+ * Fill out some of the header fields ourselves because the
+ * EFI firmware loader doesn't load the first sector.
+ */
+ hdr->root_flags = 1;
+ hdr->vid_mode = 0xffff;
+ hdr->boot_flag = 0xAA55;
+
/*
* The EFI firmware loader could have placed the kernel image
* anywhere in memory, but the kernel has various restrictions
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index f1bbeeb09148..8bbea6aa40d9 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -147,7 +147,7 @@ optional_header:
# Filled in by build.c
.long 0x0000 # AddressOfEntryPoint
- .long 0x0000 # BaseOfCode
+ .long 0x0200 # BaseOfCode
#ifdef CONFIG_X86_32
.long 0 # data
#endif
@@ -189,7 +189,7 @@ extra_header_fields:
.quad 0 # SizeOfHeapCommit
#endif
.long 0 # LoaderFlags
- .long 0x1 # NumberOfRvaAndSizes
+ .long 0x6 # NumberOfRvaAndSizes
.quad 0 # ExportTable
.quad 0 # ImportTable
@@ -217,18 +217,17 @@ section_table:
#
# The EFI application loader requires a relocation section
- # because EFI applications are relocatable and not having
- # this section seems to confuse it. But since we don't need
- # the loader to fixup any relocs for us just fill it with a
- # single dummy reloc.
+ # because EFI applications must be relocatable. But since
+ # we don't need the loader to fixup any relocs for us, we
+ # just create an empty (zero-length) .reloc section header.
#
.ascii ".reloc"
.byte 0
.byte 0
- .long reloc_end - reloc_start
- .long reloc_start
- .long reloc_end - reloc_start # SizeOfRawData
- .long reloc_start # PointerToRawData
+ .long 0
+ .long 0
+ .long 0 # SizeOfRawData
+ .long 0 # PointerToRawData
.long 0 # PointerToRelocations
.long 0 # PointerToLineNumbers
.word 0 # NumberOfRelocations
@@ -469,10 +468,3 @@ setup_corrupt:
.data
dummy: .long 0
-
- .section .reloc
-reloc_start:
- .long dummy - reloc_start
- .long 10
- .word 0
-reloc_end:
diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
index 40358c8905be..cf6083d444f4 100644
--- a/arch/x86/boot/main.c
+++ b/arch/x86/boot/main.c
@@ -57,14 +57,20 @@ static void copy_boot_params(void)
}
/*
- * Set the keyboard repeat rate to maximum. Unclear why this
+ * Query the keyboard lock status as given by the BIOS, and
+ * set the keyboard repeat rate to maximum. Unclear why the latter
* is done here; this might be possible to kill off as stale code.
*/
-static void keyboard_set_repeat(void)
+static void keyboard_init(void)
{
- struct biosregs ireg;
+ struct biosregs ireg, oreg;
initregs(&ireg);
- ireg.ax = 0x0305;
+
+ ireg.ah = 0x02; /* Get keyboard status */
+ intcall(0x16, &ireg, &oreg);
+ boot_params.kbd_status = oreg.al;
+
+ ireg.ax = 0x0305; /* Set keyboard repeat rate */
intcall(0x16, &ireg, NULL);
}
@@ -151,8 +157,8 @@ void main(void)
/* Detect memory layout */
detect_memory();
- /* Set keyboard repeat rate (why?) */
- keyboard_set_repeat();
+ /* Set keyboard repeat rate (why?) and query the lock flags */
+ keyboard_init();
/* Query MCA information */
query_mca();
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index 24443a332083..3f61f6e2b46f 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -198,12 +198,19 @@ int main(int argc, char ** argv)
pe_header = get_unaligned_le32(&buf[0x3c]);
- /* Size of code */
- put_unaligned_le32(file_sz, &buf[pe_header + 0x1c]);
-
/* Size of image */
put_unaligned_le32(file_sz, &buf[pe_header + 0x50]);
+ /*
+ * Subtract the size of the first section (512 bytes) which
+ * includes the header and .reloc section. The remaining size
+ * is that of the .text section.
+ */
+ file_sz -= 512;
+
+ /* Size of code */
+ put_unaligned_le32(file_sz, &buf[pe_header + 0x1c]);
+
#ifdef CONFIG_X86_32
/*
* Address of entry point.
@@ -216,8 +223,14 @@ int main(int argc, char ** argv)
/* .text size */
put_unaligned_le32(file_sz, &buf[pe_header + 0xb0]);
+ /* .text vma */
+ put_unaligned_le32(0x200, &buf[pe_header + 0xb4]);
+
/* .text size of initialised data */
put_unaligned_le32(file_sz, &buf[pe_header + 0xb8]);
+
+ /* .text file offset */
+ put_unaligned_le32(0x200, &buf[pe_header + 0xbc]);
#else
/*
* Address of entry point. startup_32 is at the beginning and
@@ -231,9 +244,14 @@ int main(int argc, char ** argv)
/* .text size */
put_unaligned_le32(file_sz, &buf[pe_header + 0xc0]);
+ /* .text vma */
+ put_unaligned_le32(0x200, &buf[pe_header + 0xc4]);
+
/* .text size of initialised data */
put_unaligned_le32(file_sz, &buf[pe_header + 0xc8]);
+ /* .text file offset */
+ put_unaligned_le32(0x200, &buf[pe_header + 0xcc]);
#endif /* CONFIG_X86_32 */
#endif /* CONFIG_EFI_STUB */
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index c799352e24fc..ac7f5cd019e8 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -222,27 +222,6 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
}
}
-static struct crypto_alg aesni_alg = {
- .cra_name = "aes",
- .cra_driver_name = "aes-aesni",
- .cra_priority = 300,
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct crypto_aes_ctx)+AESNI_ALIGN-1,
- .cra_alignmask = 0,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(aesni_alg.cra_list),
- .cra_u = {
- .cipher = {
- .cia_min_keysize = AES_MIN_KEY_SIZE,
- .cia_max_keysize = AES_MAX_KEY_SIZE,
- .cia_setkey = aes_set_key,
- .cia_encrypt = aes_encrypt,
- .cia_decrypt = aes_decrypt
- }
- }
-};
-
static void __aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm));
@@ -257,27 +236,6 @@ static void __aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
aesni_dec(ctx, dst, src);
}
-static struct crypto_alg __aesni_alg = {
- .cra_name = "__aes-aesni",
- .cra_driver_name = "__driver-aes-aesni",
- .cra_priority = 0,
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct crypto_aes_ctx)+AESNI_ALIGN-1,
- .cra_alignmask = 0,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(__aesni_alg.cra_list),
- .cra_u = {
- .cipher = {
- .cia_min_keysize = AES_MIN_KEY_SIZE,
- .cia_max_keysize = AES_MAX_KEY_SIZE,
- .cia_setkey = aes_set_key,
- .cia_encrypt = __aes_encrypt,
- .cia_decrypt = __aes_decrypt
- }
- }
-};
-
static int ecb_encrypt(struct blkcipher_desc *desc,
struct scatterlist *dst, struct scatterlist *src,
unsigned int nbytes)
@@ -326,28 +284,6 @@ static int ecb_decrypt(struct blkcipher_desc *desc,
return err;
}
-static struct crypto_alg blk_ecb_alg = {
- .cra_name = "__ecb-aes-aesni",
- .cra_driver_name = "__driver-ecb-aes-aesni",
- .cra_priority = 0,
- .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct crypto_aes_ctx)+AESNI_ALIGN-1,
- .cra_alignmask = 0,
- .cra_type = &crypto_blkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(blk_ecb_alg.cra_list),
- .cra_u = {
- .blkcipher = {
- .min_keysize = AES_MIN_KEY_SIZE,
- .max_keysize = AES_MAX_KEY_SIZE,
- .setkey = aes_set_key,
- .encrypt = ecb_encrypt,
- .decrypt = ecb_decrypt,
- },
- },
-};
-
static int cbc_encrypt(struct blkcipher_desc *desc,
struct scatterlist *dst, struct scatterlist *src,
unsigned int nbytes)
@@ -396,28 +332,6 @@ static int cbc_decrypt(struct blkcipher_desc *desc,
return err;
}
-static struct crypto_alg blk_cbc_alg = {
- .cra_name = "__cbc-aes-aesni",
- .cra_driver_name = "__driver-cbc-aes-aesni",
- .cra_priority = 0,
- .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct crypto_aes_ctx)+AESNI_ALIGN-1,
- .cra_alignmask = 0,
- .cra_type = &crypto_blkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(blk_cbc_alg.cra_list),
- .cra_u = {
- .blkcipher = {
- .min_keysize = AES_MIN_KEY_SIZE,
- .max_keysize = AES_MAX_KEY_SIZE,
- .setkey = aes_set_key,
- .encrypt = cbc_encrypt,
- .decrypt = cbc_decrypt,
- },
- },
-};
-
#ifdef CONFIG_X86_64
static void ctr_crypt_final(struct crypto_aes_ctx *ctx,
struct blkcipher_walk *walk)
@@ -461,29 +375,6 @@ static int ctr_crypt(struct blkcipher_desc *desc,
return err;
}
-
-static struct crypto_alg blk_ctr_alg = {
- .cra_name = "__ctr-aes-aesni",
- .cra_driver_name = "__driver-ctr-aes-aesni",
- .cra_priority = 0,
- .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
- .cra_blocksize = 1,
- .cra_ctxsize = sizeof(struct crypto_aes_ctx)+AESNI_ALIGN-1,
- .cra_alignmask = 0,
- .cra_type = &crypto_blkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(blk_ctr_alg.cra_list),
- .cra_u = {
- .blkcipher = {
- .min_keysize = AES_MIN_KEY_SIZE,
- .max_keysize = AES_MAX_KEY_SIZE,
- .ivsize = AES_BLOCK_SIZE,
- .setkey = aes_set_key,
- .encrypt = ctr_crypt,
- .decrypt = ctr_crypt,
- },
- },
-};
#endif
static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key,
@@ -551,281 +442,65 @@ static void ablk_exit(struct crypto_tfm *tfm)
cryptd_free_ablkcipher(ctx->cryptd_tfm);
}
-static void ablk_init_common(struct crypto_tfm *tfm,
- struct cryptd_ablkcipher *cryptd_tfm)
+static int ablk_init_common(struct crypto_tfm *tfm, const char *drv_name)
{
struct async_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct cryptd_ablkcipher *cryptd_tfm;
+
+ cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0);
+ if (IS_ERR(cryptd_tfm))
+ return PTR_ERR(cryptd_tfm);
ctx->cryptd_tfm = cryptd_tfm;
tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) +
crypto_ablkcipher_reqsize(&cryptd_tfm->base);
+
+ return 0;
}
static int ablk_ecb_init(struct crypto_tfm *tfm)
{
- struct cryptd_ablkcipher *cryptd_tfm;
-
- cryptd_tfm = cryptd_alloc_ablkcipher("__driver-ecb-aes-aesni", 0, 0);
- if (IS_ERR(cryptd_tfm))
- return PTR_ERR(cryptd_tfm);
- ablk_init_common(tfm, cryptd_tfm);
- return 0;
+ return ablk_init_common(tfm, "__driver-ecb-aes-aesni");
}
-static struct crypto_alg ablk_ecb_alg = {
- .cra_name = "ecb(aes)",
- .cra_driver_name = "ecb-aes-aesni",
- .cra_priority = 400,
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct async_aes_ctx),
- .cra_alignmask = 0,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(ablk_ecb_alg.cra_list),
- .cra_init = ablk_ecb_init,
- .cra_exit = ablk_exit,
- .cra_u = {
- .ablkcipher = {
- .min_keysize = AES_MIN_KEY_SIZE,
- .max_keysize = AES_MAX_KEY_SIZE,
- .setkey = ablk_set_key,
- .encrypt = ablk_encrypt,
- .decrypt = ablk_decrypt,
- },
- },
-};
-
static int ablk_cbc_init(struct crypto_tfm *tfm)
{
- struct cryptd_ablkcipher *cryptd_tfm;
-
- cryptd_tfm = cryptd_alloc_ablkcipher("__driver-cbc-aes-aesni", 0, 0);
- if (IS_ERR(cryptd_tfm))
- return PTR_ERR(cryptd_tfm);
- ablk_init_common(tfm, cryptd_tfm);
- return 0;
+ return ablk_init_common(tfm, "__driver-cbc-aes-aesni");
}
-static struct crypto_alg ablk_cbc_alg = {
- .cra_name = "cbc(aes)",
- .cra_driver_name = "cbc-aes-aesni",
- .cra_priority = 400,
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct async_aes_ctx),
- .cra_alignmask = 0,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(ablk_cbc_alg.cra_list),
- .cra_init = ablk_cbc_init,
- .cra_exit = ablk_exit,
- .cra_u = {
- .ablkcipher = {
- .min_keysize = AES_MIN_KEY_SIZE,
- .max_keysize = AES_MAX_KEY_SIZE,
- .ivsize = AES_BLOCK_SIZE,
- .setkey = ablk_set_key,
- .encrypt = ablk_encrypt,
- .decrypt = ablk_decrypt,
- },
- },
-};
-
#ifdef CONFIG_X86_64
static int ablk_ctr_init(struct crypto_tfm *tfm)
{
- struct cryptd_ablkcipher *cryptd_tfm;
-
- cryptd_tfm = cryptd_alloc_ablkcipher("__driver-ctr-aes-aesni", 0, 0);
- if (IS_ERR(cryptd_tfm))
- return PTR_ERR(cryptd_tfm);
- ablk_init_common(tfm, cryptd_tfm);
- return 0;
+ return ablk_init_common(tfm, "__driver-ctr-aes-aesni");
}
-static struct crypto_alg ablk_ctr_alg = {
- .cra_name = "ctr(aes)",
- .cra_driver_name = "ctr-aes-aesni",
- .cra_priority = 400,
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
- .cra_blocksize = 1,
- .cra_ctxsize = sizeof(struct async_aes_ctx),
- .cra_alignmask = 0,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(ablk_ctr_alg.cra_list),
- .cra_init = ablk_ctr_init,
- .cra_exit = ablk_exit,
- .cra_u = {
- .ablkcipher = {
- .min_keysize = AES_MIN_KEY_SIZE,
- .max_keysize = AES_MAX_KEY_SIZE,
- .ivsize = AES_BLOCK_SIZE,
- .setkey = ablk_set_key,
- .encrypt = ablk_encrypt,
- .decrypt = ablk_encrypt,
- .geniv = "chainiv",
- },
- },
-};
-
#ifdef HAS_CTR
static int ablk_rfc3686_ctr_init(struct crypto_tfm *tfm)
{
- struct cryptd_ablkcipher *cryptd_tfm;
-
- cryptd_tfm = cryptd_alloc_ablkcipher(
- "rfc3686(__driver-ctr-aes-aesni)", 0, 0);
- if (IS_ERR(cryptd_tfm))
- return PTR_ERR(cryptd_tfm);
- ablk_init_common(tfm, cryptd_tfm);
- return 0;
+ return ablk_init_common(tfm, "rfc3686(__driver-ctr-aes-aesni)");
}
-
-static struct crypto_alg ablk_rfc3686_ctr_alg = {
- .cra_name = "rfc3686(ctr(aes))",
- .cra_driver_name = "rfc3686-ctr-aes-aesni",
- .cra_priority = 400,
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
- .cra_blocksize = 1,
- .cra_ctxsize = sizeof(struct async_aes_ctx),
- .cra_alignmask = 0,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(ablk_rfc3686_ctr_alg.cra_list),
- .cra_init = ablk_rfc3686_ctr_init,
- .cra_exit = ablk_exit,
- .cra_u = {
- .ablkcipher = {
- .min_keysize = AES_MIN_KEY_SIZE+CTR_RFC3686_NONCE_SIZE,
- .max_keysize = AES_MAX_KEY_SIZE+CTR_RFC3686_NONCE_SIZE,
- .ivsize = CTR_RFC3686_IV_SIZE,
- .setkey = ablk_set_key,
- .encrypt = ablk_encrypt,
- .decrypt = ablk_decrypt,
- .geniv = "seqiv",
- },
- },
-};
#endif
#endif
#ifdef HAS_LRW
static int ablk_lrw_init(struct crypto_tfm *tfm)
{
- struct cryptd_ablkcipher *cryptd_tfm;
-
- cryptd_tfm = cryptd_alloc_ablkcipher("fpu(lrw(__driver-aes-aesni))",
- 0, 0);
- if (IS_ERR(cryptd_tfm))
- return PTR_ERR(cryptd_tfm);
- ablk_init_common(tfm, cryptd_tfm);
- return 0;
+ return ablk_init_common(tfm, "fpu(lrw(__driver-aes-aesni))");
}
-
-static struct crypto_alg ablk_lrw_alg = {
- .cra_name = "lrw(aes)",
- .cra_driver_name = "lrw-aes-aesni",
- .cra_priority = 400,
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct async_aes_ctx),
- .cra_alignmask = 0,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(ablk_lrw_alg.cra_list),
- .cra_init = ablk_lrw_init,
- .cra_exit = ablk_exit,
- .cra_u = {
- .ablkcipher = {
- .min_keysize = AES_MIN_KEY_SIZE + AES_BLOCK_SIZE,
- .max_keysize = AES_MAX_KEY_SIZE + AES_BLOCK_SIZE,
- .ivsize = AES_BLOCK_SIZE,
- .setkey = ablk_set_key,
- .encrypt = ablk_encrypt,
- .decrypt = ablk_decrypt,
- },
- },
-};
#endif
#ifdef HAS_PCBC
static int ablk_pcbc_init(struct crypto_tfm *tfm)
{
- struct cryptd_ablkcipher *cryptd_tfm;
-
- cryptd_tfm = cryptd_alloc_ablkcipher("fpu(pcbc(__driver-aes-aesni))",
- 0, 0);
- if (IS_ERR(cryptd_tfm))
- return PTR_ERR(cryptd_tfm);
- ablk_init_common(tfm, cryptd_tfm);
- return 0;
+ return ablk_init_common(tfm, "fpu(pcbc(__driver-aes-aesni))");
}
-
-static struct crypto_alg ablk_pcbc_alg = {
- .cra_name = "pcbc(aes)",
- .cra_driver_name = "pcbc-aes-aesni",
- .cra_priority = 400,
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct async_aes_ctx),
- .cra_alignmask = 0,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(ablk_pcbc_alg.cra_list),
- .cra_init = ablk_pcbc_init,
- .cra_exit = ablk_exit,
- .cra_u = {
- .ablkcipher = {
- .min_keysize = AES_MIN_KEY_SIZE,
- .max_keysize = AES_MAX_KEY_SIZE,
- .ivsize = AES_BLOCK_SIZE,
- .setkey = ablk_set_key,
- .encrypt = ablk_encrypt,
- .decrypt = ablk_decrypt,
- },
- },
-};
#endif
#ifdef HAS_XTS
static int ablk_xts_init(struct crypto_tfm *tfm)
{
- struct cryptd_ablkcipher *cryptd_tfm;
-
- cryptd_tfm = cryptd_alloc_ablkcipher("fpu(xts(__driver-aes-aesni))",
- 0, 0);
- if (IS_ERR(cryptd_tfm))
- return PTR_ERR(cryptd_tfm);
- ablk_init_common(tfm, cryptd_tfm);
- return 0;
+ return ablk_init_common(tfm, "fpu(xts(__driver-aes-aesni))");
}
-
-static struct crypto_alg ablk_xts_alg = {
- .cra_name = "xts(aes)",
- .cra_driver_name = "xts-aes-aesni",
- .cra_priority = 400,
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct async_aes_ctx),
- .cra_alignmask = 0,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(ablk_xts_alg.cra_list),
- .cra_init = ablk_xts_init,
- .cra_exit = ablk_exit,
- .cra_u = {
- .ablkcipher = {
- .min_keysize = 2 * AES_MIN_KEY_SIZE,
- .max_keysize = 2 * AES_MAX_KEY_SIZE,
- .ivsize = AES_BLOCK_SIZE,
- .setkey = ablk_set_key,
- .encrypt = ablk_encrypt,
- .decrypt = ablk_decrypt,
- },
- },
-};
#endif
#ifdef CONFIG_X86_64
@@ -1050,32 +725,6 @@ static int rfc4106_decrypt(struct aead_request *req)
}
}
-static struct crypto_alg rfc4106_alg = {
- .cra_name = "rfc4106(gcm(aes))",
- .cra_driver_name = "rfc4106-gcm-aesni",
- .cra_priority = 400,
- .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
- .cra_blocksize = 1,
- .cra_ctxsize = sizeof(struct aesni_rfc4106_gcm_ctx) + AESNI_ALIGN,
- .cra_alignmask = 0,
- .cra_type = &crypto_nivaead_type,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(rfc4106_alg.cra_list),
- .cra_init = rfc4106_init,
- .cra_exit = rfc4106_exit,
- .cra_u = {
- .aead = {
- .setkey = rfc4106_set_key,
- .setauthsize = rfc4106_set_authsize,
- .encrypt = rfc4106_encrypt,
- .decrypt = rfc4106_decrypt,
- .geniv = "seqiv",
- .ivsize = 8,
- .maxauthsize = 16,
- },
- },
-};
-
static int __driver_rfc4106_encrypt(struct aead_request *req)
{
u8 one_entry_in_sg = 0;
@@ -1233,26 +882,316 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
}
return retval;
}
+#endif
-static struct crypto_alg __rfc4106_alg = {
+static struct crypto_alg aesni_algs[] = { {
+ .cra_name = "aes",
+ .cra_driver_name = "aes-aesni",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx) +
+ AESNI_ALIGN - 1,
+ .cra_alignmask = 0,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = AES_MIN_KEY_SIZE,
+ .cia_max_keysize = AES_MAX_KEY_SIZE,
+ .cia_setkey = aes_set_key,
+ .cia_encrypt = aes_encrypt,
+ .cia_decrypt = aes_decrypt
+ }
+ }
+}, {
+ .cra_name = "__aes-aesni",
+ .cra_driver_name = "__driver-aes-aesni",
+ .cra_priority = 0,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx) +
+ AESNI_ALIGN - 1,
+ .cra_alignmask = 0,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = AES_MIN_KEY_SIZE,
+ .cia_max_keysize = AES_MAX_KEY_SIZE,
+ .cia_setkey = aes_set_key,
+ .cia_encrypt = __aes_encrypt,
+ .cia_decrypt = __aes_decrypt
+ }
+ }
+}, {
+ .cra_name = "__ecb-aes-aesni",
+ .cra_driver_name = "__driver-ecb-aes-aesni",
+ .cra_priority = 0,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx) +
+ AESNI_ALIGN - 1,
+ .cra_alignmask = 0,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = aes_set_key,
+ .encrypt = ecb_encrypt,
+ .decrypt = ecb_decrypt,
+ },
+ },
+}, {
+ .cra_name = "__cbc-aes-aesni",
+ .cra_driver_name = "__driver-cbc-aes-aesni",
+ .cra_priority = 0,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx) +
+ AESNI_ALIGN - 1,
+ .cra_alignmask = 0,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = aes_set_key,
+ .encrypt = cbc_encrypt,
+ .decrypt = cbc_decrypt,
+ },
+ },
+}, {
+ .cra_name = "ecb(aes)",
+ .cra_driver_name = "ecb-aes-aesni",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct async_aes_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = ablk_ecb_init,
+ .cra_exit = ablk_exit,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = ablk_set_key,
+ .encrypt = ablk_encrypt,
+ .decrypt = ablk_decrypt,
+ },
+ },
+}, {
+ .cra_name = "cbc(aes)",
+ .cra_driver_name = "cbc-aes-aesni",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct async_aes_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = ablk_cbc_init,
+ .cra_exit = ablk_exit,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = ablk_set_key,
+ .encrypt = ablk_encrypt,
+ .decrypt = ablk_decrypt,
+ },
+ },
+#ifdef CONFIG_X86_64
+}, {
+ .cra_name = "__ctr-aes-aesni",
+ .cra_driver_name = "__driver-ctr-aes-aesni",
+ .cra_priority = 0,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx) +
+ AESNI_ALIGN - 1,
+ .cra_alignmask = 0,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = aes_set_key,
+ .encrypt = ctr_crypt,
+ .decrypt = ctr_crypt,
+ },
+ },
+}, {
+ .cra_name = "ctr(aes)",
+ .cra_driver_name = "ctr-aes-aesni",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct async_aes_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = ablk_ctr_init,
+ .cra_exit = ablk_exit,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = ablk_set_key,
+ .encrypt = ablk_encrypt,
+ .decrypt = ablk_encrypt,
+ .geniv = "chainiv",
+ },
+ },
+}, {
.cra_name = "__gcm-aes-aesni",
.cra_driver_name = "__driver-gcm-aes-aesni",
.cra_priority = 0,
.cra_flags = CRYPTO_ALG_TYPE_AEAD,
.cra_blocksize = 1,
- .cra_ctxsize = sizeof(struct aesni_rfc4106_gcm_ctx) + AESNI_ALIGN,
+ .cra_ctxsize = sizeof(struct aesni_rfc4106_gcm_ctx) +
+ AESNI_ALIGN,
.cra_alignmask = 0,
.cra_type = &crypto_aead_type,
.cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(__rfc4106_alg.cra_list),
.cra_u = {
.aead = {
.encrypt = __driver_rfc4106_encrypt,
.decrypt = __driver_rfc4106_decrypt,
},
},
-};
+}, {
+ .cra_name = "rfc4106(gcm(aes))",
+ .cra_driver_name = "rfc4106-gcm-aesni",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct aesni_rfc4106_gcm_ctx) +
+ AESNI_ALIGN,
+ .cra_alignmask = 0,
+ .cra_type = &crypto_nivaead_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = rfc4106_init,
+ .cra_exit = rfc4106_exit,
+ .cra_u = {
+ .aead = {
+ .setkey = rfc4106_set_key,
+ .setauthsize = rfc4106_set_authsize,
+ .encrypt = rfc4106_encrypt,
+ .decrypt = rfc4106_decrypt,
+ .geniv = "seqiv",
+ .ivsize = 8,
+ .maxauthsize = 16,
+ },
+ },
+#ifdef HAS_CTR
+}, {
+ .cra_name = "rfc3686(ctr(aes))",
+ .cra_driver_name = "rfc3686-ctr-aes-aesni",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct async_aes_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = ablk_rfc3686_ctr_init,
+ .cra_exit = ablk_exit,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE +
+ CTR_RFC3686_NONCE_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE +
+ CTR_RFC3686_NONCE_SIZE,
+ .ivsize = CTR_RFC3686_IV_SIZE,
+ .setkey = ablk_set_key,
+ .encrypt = ablk_encrypt,
+ .decrypt = ablk_decrypt,
+ .geniv = "seqiv",
+ },
+ },
+#endif
+#endif
+#ifdef HAS_LRW
+}, {
+ .cra_name = "lrw(aes)",
+ .cra_driver_name = "lrw-aes-aesni",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct async_aes_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = ablk_lrw_init,
+ .cra_exit = ablk_exit,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE + AES_BLOCK_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE + AES_BLOCK_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = ablk_set_key,
+ .encrypt = ablk_encrypt,
+ .decrypt = ablk_decrypt,
+ },
+ },
+#endif
+#ifdef HAS_PCBC
+}, {
+ .cra_name = "pcbc(aes)",
+ .cra_driver_name = "pcbc-aes-aesni",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct async_aes_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = ablk_pcbc_init,
+ .cra_exit = ablk_exit,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = ablk_set_key,
+ .encrypt = ablk_encrypt,
+ .decrypt = ablk_decrypt,
+ },
+ },
#endif
+#ifdef HAS_XTS
+}, {
+ .cra_name = "xts(aes)",
+ .cra_driver_name = "xts-aes-aesni",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct async_aes_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = ablk_xts_init,
+ .cra_exit = ablk_exit,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = 2 * AES_MIN_KEY_SIZE,
+ .max_keysize = 2 * AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = ablk_set_key,
+ .encrypt = ablk_encrypt,
+ .decrypt = ablk_decrypt,
+ },
+ },
+#endif
+} };
static const struct x86_cpu_id aesni_cpu_id[] = {
@@ -1263,120 +1202,24 @@ MODULE_DEVICE_TABLE(x86cpu, aesni_cpu_id);
static int __init aesni_init(void)
{
- int err;
+ int err, i;
if (!x86_match_cpu(aesni_cpu_id))
return -ENODEV;
- if ((err = crypto_fpu_init()))
- goto fpu_err;
- if ((err = crypto_register_alg(&aesni_alg)))
- goto aes_err;
- if ((err = crypto_register_alg(&__aesni_alg)))
- goto __aes_err;
- if ((err = crypto_register_alg(&blk_ecb_alg)))
- goto blk_ecb_err;
- if ((err = crypto_register_alg(&blk_cbc_alg)))
- goto blk_cbc_err;
- if ((err = crypto_register_alg(&ablk_ecb_alg)))
- goto ablk_ecb_err;
- if ((err = crypto_register_alg(&ablk_cbc_alg)))
- goto ablk_cbc_err;
-#ifdef CONFIG_X86_64
- if ((err = crypto_register_alg(&blk_ctr_alg)))
- goto blk_ctr_err;
- if ((err = crypto_register_alg(&ablk_ctr_alg)))
- goto ablk_ctr_err;
- if ((err = crypto_register_alg(&__rfc4106_alg)))
- goto __aead_gcm_err;
- if ((err = crypto_register_alg(&rfc4106_alg)))
- goto aead_gcm_err;
-#ifdef HAS_CTR
- if ((err = crypto_register_alg(&ablk_rfc3686_ctr_alg)))
- goto ablk_rfc3686_ctr_err;
-#endif
-#endif
-#ifdef HAS_LRW
- if ((err = crypto_register_alg(&ablk_lrw_alg)))
- goto ablk_lrw_err;
-#endif
-#ifdef HAS_PCBC
- if ((err = crypto_register_alg(&ablk_pcbc_alg)))
- goto ablk_pcbc_err;
-#endif
-#ifdef HAS_XTS
- if ((err = crypto_register_alg(&ablk_xts_alg)))
- goto ablk_xts_err;
-#endif
- return err;
+ err = crypto_fpu_init();
+ if (err)
+ return err;
-#ifdef HAS_XTS
-ablk_xts_err:
-#endif
-#ifdef HAS_PCBC
- crypto_unregister_alg(&ablk_pcbc_alg);
-ablk_pcbc_err:
-#endif
-#ifdef HAS_LRW
- crypto_unregister_alg(&ablk_lrw_alg);
-ablk_lrw_err:
-#endif
-#ifdef CONFIG_X86_64
-#ifdef HAS_CTR
- crypto_unregister_alg(&ablk_rfc3686_ctr_alg);
-ablk_rfc3686_ctr_err:
-#endif
- crypto_unregister_alg(&rfc4106_alg);
-aead_gcm_err:
- crypto_unregister_alg(&__rfc4106_alg);
-__aead_gcm_err:
- crypto_unregister_alg(&ablk_ctr_alg);
-ablk_ctr_err:
- crypto_unregister_alg(&blk_ctr_alg);
-blk_ctr_err:
-#endif
- crypto_unregister_alg(&ablk_cbc_alg);
-ablk_cbc_err:
- crypto_unregister_alg(&ablk_ecb_alg);
-ablk_ecb_err:
- crypto_unregister_alg(&blk_cbc_alg);
-blk_cbc_err:
- crypto_unregister_alg(&blk_ecb_alg);
-blk_ecb_err:
- crypto_unregister_alg(&__aesni_alg);
-__aes_err:
- crypto_unregister_alg(&aesni_alg);
-aes_err:
-fpu_err:
- return err;
+ for (i = 0; i < ARRAY_SIZE(aesni_algs); i++)
+ INIT_LIST_HEAD(&aesni_algs[i].cra_list);
+
+ return crypto_register_algs(aesni_algs, ARRAY_SIZE(aesni_algs));
}
static void __exit aesni_exit(void)
{
-#ifdef HAS_XTS
- crypto_unregister_alg(&ablk_xts_alg);
-#endif
-#ifdef HAS_PCBC
- crypto_unregister_alg(&ablk_pcbc_alg);
-#endif
-#ifdef HAS_LRW
- crypto_unregister_alg(&ablk_lrw_alg);
-#endif
-#ifdef CONFIG_X86_64
-#ifdef HAS_CTR
- crypto_unregister_alg(&ablk_rfc3686_ctr_alg);
-#endif
- crypto_unregister_alg(&rfc4106_alg);
- crypto_unregister_alg(&__rfc4106_alg);
- crypto_unregister_alg(&ablk_ctr_alg);
- crypto_unregister_alg(&blk_ctr_alg);
-#endif
- crypto_unregister_alg(&ablk_cbc_alg);
- crypto_unregister_alg(&ablk_ecb_alg);
- crypto_unregister_alg(&blk_cbc_alg);
- crypto_unregister_alg(&blk_ecb_alg);
- crypto_unregister_alg(&__aesni_alg);
- crypto_unregister_alg(&aesni_alg);
+ crypto_unregister_algs(aesni_algs, ARRAY_SIZE(aesni_algs));
crypto_fpu_exit();
}
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index a69245ba27e3..0b3f2354f6aa 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -67,6 +67,10 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
switch (from->si_code >> 16) {
case __SI_FAULT >> 16:
break;
+ case __SI_SYS >> 16:
+ put_user_ex(from->si_syscall, &to->si_syscall);
+ put_user_ex(from->si_arch, &to->si_arch);
+ break;
case __SI_CHLD >> 16:
if (ia32) {
put_user_ex(from->si_utime, &to->si_utime);
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index e3e734005e19..20e5f7ba0e6b 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -13,6 +13,7 @@
#include <asm/thread_info.h>
#include <asm/segment.h>
#include <asm/irqflags.h>
+#include <asm/asm.h>
#include <linux/linkage.h>
#include <linux/err.h>
@@ -146,9 +147,7 @@ ENTRY(ia32_sysenter_target)
/* no need to do an access_ok check here because rbp has been
32bit zero extended */
1: movl (%rbp),%ebp
- .section __ex_table,"a"
- .quad 1b,ia32_badarg
- .previous
+ _ASM_EXTABLE(1b,ia32_badarg)
orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
CFI_REMEMBER_STATE
@@ -303,9 +302,7 @@ ENTRY(ia32_cstar_target)
32bit zero extended */
/* hardware stack frame is complete now */
1: movl (%r8),%r9d
- .section __ex_table,"a"
- .quad 1b,ia32_badarg
- .previous
+ _ASM_EXTABLE(1b,ia32_badarg)
orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
CFI_REMEMBER_STATE
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index aec2202a596c..edca9c0a79cc 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -287,11 +287,6 @@ asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 __user *act,
return ret;
}
-asmlinkage long sys32_alarm(unsigned int seconds)
-{
- return alarm_setitimer(seconds);
-}
-
asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr,
int options)
{
@@ -300,11 +295,6 @@ asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr,
/* 32-bit timeval and related flotsam. */
-asmlinkage long sys32_sysfs(int option, u32 arg1, u32 arg2)
-{
- return sys_sysfs(option, arg1, arg2);
-}
-
asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid,
struct compat_timespec __user *interval)
{
@@ -375,19 +365,6 @@ asmlinkage long sys32_pwrite(unsigned int fd, const char __user *ubuf,
}
-asmlinkage long sys32_personality(unsigned long personality)
-{
- int ret;
-
- if (personality(current->personality) == PER_LINUX32 &&
- personality == PER_LINUX)
- personality = PER_LINUX32;
- ret = sys_personality(personality);
- if (ret == PER_LINUX32)
- ret = PER_LINUX;
- return ret;
-}
-
asmlinkage long sys32_sendfile(int out_fd, int in_fd,
compat_off_t __user *offset, s32 count)
{
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index d85410171260..eaff4790ed96 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -138,6 +138,11 @@ static inline void native_apic_msr_write(u32 reg, u32 v)
wrmsr(APIC_BASE_MSR + (reg >> 4), v, 0);
}
+static inline void native_apic_msr_eoi_write(u32 reg, u32 v)
+{
+ wrmsr(APIC_BASE_MSR + (APIC_EOI >> 4), APIC_EOI_ACK, 0);
+}
+
static inline u32 native_apic_msr_read(u32 reg)
{
u64 msr;
@@ -351,6 +356,14 @@ struct apic {
/* apic ops */
u32 (*read)(u32 reg);
void (*write)(u32 reg, u32 v);
+ /*
+ * ->eoi_write() has the same signature as ->write().
+ *
+ * Drivers can support both ->eoi_write() and ->write() by passing the same
+ * callback value. Kernel can override ->eoi_write() and fall back
+ * on write for EOI.
+ */
+ void (*eoi_write)(u32 reg, u32 v);
u64 (*icr_read)(void);
void (*icr_write)(u32 low, u32 high);
void (*wait_icr_idle)(void);
@@ -426,6 +439,11 @@ static inline void apic_write(u32 reg, u32 val)
apic->write(reg, val);
}
+static inline void apic_eoi(void)
+{
+ apic->eoi_write(APIC_EOI, APIC_EOI_ACK);
+}
+
static inline u64 apic_icr_read(void)
{
return apic->icr_read();
@@ -450,6 +468,7 @@ static inline u32 safe_apic_wait_icr_idle(void)
static inline u32 apic_read(u32 reg) { return 0; }
static inline void apic_write(u32 reg, u32 val) { }
+static inline void apic_eoi(void) { }
static inline u64 apic_icr_read(void) { return 0; }
static inline void apic_icr_write(u32 low, u32 high) { }
static inline void apic_wait_icr_idle(void) { }
@@ -463,9 +482,7 @@ static inline void ack_APIC_irq(void)
* ack_APIC_irq() actually gets compiled as a single instruction
* ... yummie.
*/
-
- /* Docs say use 0 for future compatibility */
- apic_write(APIC_EOI, 0);
+ apic_eoi();
}
static inline unsigned default_get_apic_id(unsigned long x)
diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index 134bba00df09..c46bb99d5fb2 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -37,7 +37,7 @@
#define APIC_ARBPRI_MASK 0xFFu
#define APIC_PROCPRI 0xA0
#define APIC_EOI 0xB0
-#define APIC_EIO_ACK 0x0
+#define APIC_EOI_ACK 0x0 /* Docs say 0 for future compat. */
#define APIC_RRR 0xC0
#define APIC_LDR 0xD0
#define APIC_LDR_MASK (0xFFu << 24)
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 9412d6558c88..1c2d247f65ce 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -4,11 +4,9 @@
#ifdef __ASSEMBLY__
# define __ASM_FORM(x) x
# define __ASM_FORM_COMMA(x) x,
-# define __ASM_EX_SEC .section __ex_table, "a"
#else
# define __ASM_FORM(x) " " #x " "
# define __ASM_FORM_COMMA(x) " " #x ","
-# define __ASM_EX_SEC " .section __ex_table,\"a\"\n"
#endif
#ifdef CONFIG_X86_32
@@ -42,17 +40,33 @@
/* Exception table entry */
#ifdef __ASSEMBLY__
-# define _ASM_EXTABLE(from,to) \
- __ASM_EX_SEC ; \
- _ASM_ALIGN ; \
- _ASM_PTR from , to ; \
- .previous
+# define _ASM_EXTABLE(from,to) \
+ .pushsection "__ex_table","a" ; \
+ .balign 8 ; \
+ .long (from) - . ; \
+ .long (to) - . ; \
+ .popsection
+
+# define _ASM_EXTABLE_EX(from,to) \
+ .pushsection "__ex_table","a" ; \
+ .balign 8 ; \
+ .long (from) - . ; \
+ .long (to) - . + 0x7ffffff0 ; \
+ .popsection
#else
-# define _ASM_EXTABLE(from,to) \
- __ASM_EX_SEC \
- _ASM_ALIGN "\n" \
- _ASM_PTR #from "," #to "\n" \
- " .previous\n"
+# define _ASM_EXTABLE(from,to) \
+ " .pushsection \"__ex_table\",\"a\"\n" \
+ " .balign 8\n" \
+ " .long (" #from ") - .\n" \
+ " .long (" #to ") - .\n" \
+ " .popsection\n"
+
+# define _ASM_EXTABLE_EX(from,to) \
+ " .pushsection \"__ex_table\",\"a\"\n" \
+ " .balign 8\n" \
+ " .long (" #from ") - .\n" \
+ " .long (" #to ") - . + 0x7ffffff0\n" \
+ " .popsection\n"
#endif
#endif /* _ASM_X86_ASM_H */
diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h
index 198119910da5..b154de75c90c 100644
--- a/arch/x86/include/asm/atomic64_32.h
+++ b/arch/x86/include/asm/atomic64_32.h
@@ -63,7 +63,7 @@ ATOMIC64_DECL(add_unless);
/**
* atomic64_cmpxchg - cmpxchg atomic64 variable
- * @p: pointer to type atomic64_t
+ * @v: pointer to type atomic64_t
* @o: expected value
* @n: new value
*
@@ -98,7 +98,7 @@ static inline long long atomic64_xchg(atomic64_t *v, long long n)
/**
* atomic64_set - set atomic64 variable
* @v: pointer to type atomic64_t
- * @n: value to assign
+ * @i: value to assign
*
* Atomically sets the value of @v to @n.
*/
@@ -200,7 +200,7 @@ static inline long long atomic64_sub(long long i, atomic64_t *v)
* atomic64_sub_and_test - subtract value from variable and test result
* @i: integer value to subtract
* @v: pointer to type atomic64_t
- *
+ *
* Atomically subtracts @i from @v and returns
* true if the result is zero, or false for all
* other cases.
@@ -224,9 +224,9 @@ static inline void atomic64_inc(atomic64_t *v)
/**
* atomic64_dec - decrement atomic64 variable
- * @ptr: pointer to type atomic64_t
+ * @v: pointer to type atomic64_t
*
- * Atomically decrements @ptr by 1.
+ * Atomically decrements @v by 1.
*/
static inline void atomic64_dec(atomic64_t *v)
{
diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h
index 5e1a2eef3e7c..b13fe63bdc59 100644
--- a/arch/x86/include/asm/boot.h
+++ b/arch/x86/include/asm/boot.h
@@ -19,7 +19,7 @@
#ifdef CONFIG_X86_64
#define MIN_KERNEL_ALIGN_LG2 PMD_SHIFT
#else
-#define MIN_KERNEL_ALIGN_LG2 (PAGE_SHIFT + THREAD_ORDER)
+#define MIN_KERNEL_ALIGN_LG2 (PAGE_SHIFT + THREAD_SIZE_ORDER)
#endif
#define MIN_KERNEL_ALIGN (_AC(1, UL) << MIN_KERNEL_ALIGN_LG2)
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
index 2f90c51cc49d..eb45aa6b1f27 100644
--- a/arch/x86/include/asm/bootparam.h
+++ b/arch/x86/include/asm/bootparam.h
@@ -112,7 +112,8 @@ struct boot_params {
__u8 e820_entries; /* 0x1e8 */
__u8 eddbuf_entries; /* 0x1e9 */
__u8 edd_mbr_sig_buf_entries; /* 0x1ea */
- __u8 _pad6[6]; /* 0x1eb */
+ __u8 kbd_status; /* 0x1eb */
+ __u8 _pad6[5]; /* 0x1ec */
struct setup_header hdr; /* setup header */ /* 0x1f1 */
__u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)];
__u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
index d6805798d6fc..fedf32b73e65 100644
--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -229,7 +229,7 @@ static inline void __user *arch_compat_alloc_user_space(long len)
sp = task_pt_regs(current)->sp;
} else {
/* -128 for the x32 ABI redzone */
- sp = percpu_read(old_rsp) - 128;
+ sp = this_cpu_read(old_rsp) - 128;
}
return (void __user *)round_down(sp - len, 16);
diff --git a/arch/x86/include/asm/current.h b/arch/x86/include/asm/current.h
index 4d447b732d82..9476c04ee635 100644
--- a/arch/x86/include/asm/current.h
+++ b/arch/x86/include/asm/current.h
@@ -11,7 +11,7 @@ DECLARE_PER_CPU(struct task_struct *, current_task);
static __always_inline struct task_struct *get_current(void)
{
- return percpu_read_stable(current_task);
+ return this_cpu_read_stable(current_task);
}
#define current get_current()
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
index e95822d683f4..8bf1c06070d5 100644
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -6,6 +6,7 @@
#include <asm/mmu.h>
#include <linux/smp.h>
+#include <linux/percpu.h>
static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *info)
{
diff --git a/arch/x86/include/asm/device.h b/arch/x86/include/asm/device.h
index 63a2a03d7d51..93e1c55f14ab 100644
--- a/arch/x86/include/asm/device.h
+++ b/arch/x86/include/asm/device.h
@@ -5,8 +5,8 @@ struct dev_archdata {
#ifdef CONFIG_ACPI
void *acpi_handle;
#endif
-#ifdef CONFIG_X86_64
-struct dma_map_ops *dma_ops;
+#ifdef CONFIG_X86_DEV_DMA_OPS
+ struct dma_map_ops *dma_ops;
#endif
#if defined(CONFIG_INTEL_IOMMU) || defined(CONFIG_AMD_IOMMU)
void *iommu; /* hook for IOMMU specific extension */
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 4b4331d71935..61c0bd25845a 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -30,7 +30,7 @@ extern struct dma_map_ops *dma_ops;
static inline struct dma_map_ops *get_dma_ops(struct device *dev)
{
-#ifdef CONFIG_X86_32
+#ifndef CONFIG_X86_DEV_DMA_OPS
return dma_ops;
#else
if (unlikely(!dev) || !dev->archdata.dma_ops)
@@ -62,6 +62,12 @@ extern void *dma_generic_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addr, gfp_t flag,
struct dma_attrs *attrs);
+#ifdef CONFIG_X86_DMA_REMAP /* Platform code defines bridge-specific code */
+extern bool dma_capable(struct device *dev, dma_addr_t addr, size_t size);
+extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
+extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
+#else
+
static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
{
if (!dev->dma_mask)
@@ -79,6 +85,7 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
{
return daddr;
}
+#endif /* CONFIG_X86_DMA_REMAP */
static inline void
dma_cache_sync(struct device *dev, void *vaddr, size_t size,
diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h
index 4fa88154e4de..75f4c6d6a331 100644
--- a/arch/x86/include/asm/fpu-internal.h
+++ b/arch/x86/include/asm/fpu-internal.h
@@ -290,14 +290,14 @@ static inline int __thread_has_fpu(struct task_struct *tsk)
static inline void __thread_clear_has_fpu(struct task_struct *tsk)
{
tsk->thread.fpu.has_fpu = 0;
- percpu_write(fpu_owner_task, NULL);
+ this_cpu_write(fpu_owner_task, NULL);
}
/* Must be paired with a 'clts' before! */
static inline void __thread_set_has_fpu(struct task_struct *tsk)
{
tsk->thread.fpu.has_fpu = 1;
- percpu_write(fpu_owner_task, tsk);
+ this_cpu_write(fpu_owner_task, tsk);
}
/*
@@ -344,7 +344,7 @@ typedef struct { int preload; } fpu_switch_t;
*/
static inline int fpu_lazy_restore(struct task_struct *new, unsigned int cpu)
{
- return new == percpu_read_stable(fpu_owner_task) &&
+ return new == this_cpu_read_stable(fpu_owner_task) &&
cpu == new->thread.fpu.last_cpu;
}
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index 268c783ab1c0..18d9005d9e4f 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -34,6 +34,7 @@
#ifndef __ASSEMBLY__
extern void mcount(void);
+extern int modifying_ftrace_code;
static inline unsigned long ftrace_call_adjust(unsigned long addr)
{
@@ -50,6 +51,8 @@ struct dyn_arch_ftrace {
/* No extra data needed for x86 */
};
+int ftrace_int3_handler(struct pt_regs *regs);
+
#endif /* CONFIG_DYNAMIC_FTRACE */
#endif /* __ASSEMBLY__ */
#endif /* CONFIG_FUNCTION_TRACER */
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index 382f75d735f3..d3895dbf4ddb 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -35,14 +35,15 @@ DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
#define __ARCH_IRQ_STAT
-#define inc_irq_stat(member) percpu_inc(irq_stat.member)
+#define inc_irq_stat(member) this_cpu_inc(irq_stat.member)
-#define local_softirq_pending() percpu_read(irq_stat.__softirq_pending)
+#define local_softirq_pending() this_cpu_read(irq_stat.__softirq_pending)
#define __ARCH_SET_SOFTIRQ_PENDING
-#define set_softirq_pending(x) percpu_write(irq_stat.__softirq_pending, (x))
-#define or_softirq_pending(x) percpu_or(irq_stat.__softirq_pending, (x))
+#define set_softirq_pending(x) \
+ this_cpu_write(irq_stat.__softirq_pending, (x))
+#define or_softirq_pending(x) this_cpu_or(irq_stat.__softirq_pending, (x))
extern void ack_bad_irq(unsigned int irq);
diff --git a/arch/x86/include/asm/ia32.h b/arch/x86/include/asm/ia32.h
index ee52760549f0..b04cbdb138cd 100644
--- a/arch/x86/include/asm/ia32.h
+++ b/arch/x86/include/asm/ia32.h
@@ -144,6 +144,12 @@ typedef struct compat_siginfo {
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
+
+ struct {
+ unsigned int _call_addr; /* calling insn */
+ int _syscall; /* triggering system call number */
+ unsigned int _arch; /* AUDIT_ARCH_* of syscall */
+ } _sigsys;
} _sifields;
} compat_siginfo_t;
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 2c4943de5150..73d8c5398ea9 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -5,7 +5,7 @@
#include <asm/mpspec.h>
#include <asm/apicdef.h>
#include <asm/irq_vectors.h>
-
+#include <asm/x86_init.h>
/*
* Intel IO-APIC support for SMP and UP systems.
*
@@ -21,15 +21,6 @@
#define IO_APIC_REDIR_LEVEL_TRIGGER (1 << 15)
#define IO_APIC_REDIR_MASKED (1 << 16)
-struct io_apic_ops {
- void (*init) (void);
- unsigned int (*read) (unsigned int apic, unsigned int reg);
- void (*write) (unsigned int apic, unsigned int reg, unsigned int value);
- void (*modify)(unsigned int apic, unsigned int reg, unsigned int value);
-};
-
-void __init set_io_apic_ops(const struct io_apic_ops *);
-
/*
* The structure of the IO-APIC:
*/
@@ -156,7 +147,6 @@ struct io_apic_irq_attr;
extern int io_apic_set_pci_routing(struct device *dev, int irq,
struct io_apic_irq_attr *irq_attr);
void setup_IO_APIC_irq_extra(u32 gsi);
-extern void ioapic_and_gsi_init(void);
extern void ioapic_insert_resources(void);
int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr);
@@ -185,12 +175,29 @@ extern void mp_save_irq(struct mpc_intsrc *m);
extern void disable_ioapic_support(void);
+extern void __init native_io_apic_init_mappings(void);
+extern unsigned int native_io_apic_read(unsigned int apic, unsigned int reg);
+extern void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int val);
+extern void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val);
+
+static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
+{
+ return x86_io_apic_ops.read(apic, reg);
+}
+
+static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
+{
+ x86_io_apic_ops.write(apic, reg, value);
+}
+static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
+{
+ x86_io_apic_ops.modify(apic, reg, value);
+}
#else /* !CONFIG_X86_IO_APIC */
#define io_apic_assign_pci_irqs 0
#define setup_ioapic_ids_from_mpc x86_init_noop
static const int timer_through_8259 = 0;
-static inline void ioapic_and_gsi_init(void) { }
static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
@@ -212,6 +219,10 @@ static inline int restore_ioapic_entries(void)
static inline void mp_save_irq(struct mpc_intsrc *m) { };
static inline void disable_ioapic_support(void) { }
+#define native_io_apic_init_mappings NULL
+#define native_io_apic_read NULL
+#define native_io_apic_write NULL
+#define native_io_apic_modify NULL
#endif
#endif /* _ASM_X86_IO_APIC_H */
diff --git a/arch/x86/include/asm/irq_regs.h b/arch/x86/include/asm/irq_regs.h
index 77843225b7ea..d82250b1debb 100644
--- a/arch/x86/include/asm/irq_regs.h
+++ b/arch/x86/include/asm/irq_regs.h
@@ -15,7 +15,7 @@ DECLARE_PER_CPU(struct pt_regs *, irq_regs);
static inline struct pt_regs *get_irq_regs(void)
{
- return percpu_read(irq_regs);
+ return this_cpu_read(irq_regs);
}
static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
@@ -23,7 +23,7 @@ static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
struct pt_regs *old_regs;
old_regs = get_irq_regs();
- percpu_write(irq_regs, new_regs);
+ this_cpu_write(irq_regs, new_regs);
return old_regs;
}
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h
index 47d99934580f..5fb9bbbd2f14 100644
--- a/arch/x86/include/asm/irq_remapping.h
+++ b/arch/x86/include/asm/irq_remapping.h
@@ -1,45 +1,101 @@
-#ifndef _ASM_X86_IRQ_REMAPPING_H
-#define _ASM_X86_IRQ_REMAPPING_H
+/*
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * Author: Joerg Roedel <joerg.roedel@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This header file contains the interface of the interrupt remapping code to
+ * the x86 interrupt management code.
+ */
-#define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
+#ifndef __X86_IRQ_REMAPPING_H
+#define __X86_IRQ_REMAPPING_H
+
+#include <asm/io_apic.h>
#ifdef CONFIG_IRQ_REMAP
-static void irq_remap_modify_chip_defaults(struct irq_chip *chip);
-static inline void prepare_irte(struct irte *irte, int vector,
- unsigned int dest)
+
+extern int irq_remapping_enabled;
+
+extern void setup_irq_remapping_ops(void);
+extern int irq_remapping_supported(void);
+extern int irq_remapping_prepare(void);
+extern int irq_remapping_enable(void);
+extern void irq_remapping_disable(void);
+extern int irq_remapping_reenable(int);
+extern int irq_remap_enable_fault_handling(void);
+extern int setup_ioapic_remapped_entry(int irq,
+ struct IO_APIC_route_entry *entry,
+ unsigned int destination,
+ int vector,
+ struct io_apic_irq_attr *attr);
+extern int set_remapped_irq_affinity(struct irq_data *data,
+ const struct cpumask *mask,
+ bool force);
+extern void free_remapped_irq(int irq);
+extern void compose_remapped_msi_msg(struct pci_dev *pdev,
+ unsigned int irq, unsigned int dest,
+ struct msi_msg *msg, u8 hpet_id);
+extern int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec);
+extern int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
+ int index, int sub_handle);
+extern int setup_hpet_msi_remapped(unsigned int irq, unsigned int id);
+
+#else /* CONFIG_IRQ_REMAP */
+
+#define irq_remapping_enabled 0
+
+static inline void setup_irq_remapping_ops(void) { }
+static inline int irq_remapping_supported(void) { return 0; }
+static inline int irq_remapping_prepare(void) { return -ENODEV; }
+static inline int irq_remapping_enable(void) { return -ENODEV; }
+static inline void irq_remapping_disable(void) { }
+static inline int irq_remapping_reenable(int eim) { return -ENODEV; }
+static inline int irq_remap_enable_fault_handling(void) { return -ENODEV; }
+static inline int setup_ioapic_remapped_entry(int irq,
+ struct IO_APIC_route_entry *entry,
+ unsigned int destination,
+ int vector,
+ struct io_apic_irq_attr *attr)
+{
+ return -ENODEV;
+}
+static inline int set_remapped_irq_affinity(struct irq_data *data,
+ const struct cpumask *mask,
+ bool force)
{
- memset(irte, 0, sizeof(*irte));
-
- irte->present = 1;
- irte->dst_mode = apic->irq_dest_mode;
- /*
- * Trigger mode in the IRTE will always be edge, and for IO-APIC, the
- * actual level or edge trigger will be setup in the IO-APIC
- * RTE. This will help simplify level triggered irq migration.
- * For more details, see the comments (in io_apic.c) explainig IO-APIC
- * irq migration in the presence of interrupt-remapping.
- */
- irte->trigger_mode = 0;
- irte->dlvry_mode = apic->irq_delivery_mode;
- irte->vector = vector;
- irte->dest_id = IRTE_DEST(dest);
- irte->redir_hint = 1;
+ return 0;
}
-static inline bool irq_remapped(struct irq_cfg *cfg)
+static inline void free_remapped_irq(int irq) { }
+static inline void compose_remapped_msi_msg(struct pci_dev *pdev,
+ unsigned int irq, unsigned int dest,
+ struct msi_msg *msg, u8 hpet_id)
{
- return cfg->irq_2_iommu.iommu != NULL;
}
-#else
-static void prepare_irte(struct irte *irte, int vector, unsigned int dest)
+static inline int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
{
+ return -ENODEV;
}
-static inline bool irq_remapped(struct irq_cfg *cfg)
+static inline int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
+ int index, int sub_handle)
{
- return false;
+ return -ENODEV;
}
-static inline void irq_remap_modify_chip_defaults(struct irq_chip *chip)
+static inline int setup_hpet_msi_remapped(unsigned int irq, unsigned int id)
{
+ return -ENODEV;
}
-#endif
+#endif /* CONFIG_IRQ_REMAP */
-#endif /* _ASM_X86_IRQ_REMAPPING_H */
+#endif /* __X86_IRQ_REMAPPING_H */
diff --git a/arch/x86/include/asm/kbdleds.h b/arch/x86/include/asm/kbdleds.h
new file mode 100644
index 000000000000..f27ac5ff597d
--- /dev/null
+++ b/arch/x86/include/asm/kbdleds.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_X86_KBDLEDS_H
+#define _ASM_X86_KBDLEDS_H
+
+/*
+ * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
+ * This seems a good reason to start with NumLock off. That's why on X86 we
+ * ask the bios for the correct state.
+ */
+
+#include <asm/setup.h>
+
+static inline int kbd_defleds(void)
+{
+ return boot_params.kbd_status & 0x20 ? (1 << VC_NUMLOCK) : 0;
+}
+
+#endif /* _ASM_X86_KBDLEDS_H */
diff --git a/arch/x86/include/asm/kdebug.h b/arch/x86/include/asm/kdebug.h
index d73f1571bde7..2c37aadcbc35 100644
--- a/arch/x86/include/asm/kdebug.h
+++ b/arch/x86/include/asm/kdebug.h
@@ -24,7 +24,6 @@ enum die_val {
extern void printk_address(unsigned long address, int reliable);
extern void die(const char *, struct pt_regs *,long);
extern int __must_check __die(const char *, struct pt_regs *, long);
-extern void show_registers(struct pt_regs *regs);
extern void show_trace(struct task_struct *t, struct pt_regs *regs,
unsigned long *sp, unsigned long bp);
extern void __show_regs(struct pt_regs *regs, int all);
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index e216ba066e79..e5b97be12d2a 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -27,6 +27,7 @@
#include <asm/desc.h>
#include <asm/mtrr.h>
#include <asm/msr-index.h>
+#include <asm/asm.h>
#define KVM_MAX_VCPUS 254
#define KVM_SOFT_MAX_VCPUS 160
@@ -921,9 +922,7 @@ extern bool kvm_rebooting;
__ASM_SIZE(push) " $666b \n\t" \
"call kvm_spurious_fault \n\t" \
".popsection \n\t" \
- ".pushsection __ex_table, \"a\" \n\t" \
- _ASM_PTR " 666b, 667b \n\t" \
- ".popsection"
+ _ASM_EXTABLE(666b, 667b)
#define __kvm_handle_fault_on_reboot(insn) \
____kvm_handle_fault_on_reboot(insn, "")
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index 734c3767cfac..183922e13de1 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -170,6 +170,9 @@ static inline int kvm_para_available(void)
unsigned int eax, ebx, ecx, edx;
char signature[13];
+ if (boot_cpu_data.cpuid_level < 0)
+ return 0; /* So we don't blow up on old processors */
+
cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
memcpy(signature + 0, &ebx, 4);
memcpy(signature + 4, &ecx, 4);
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index 69021528b43c..cdbf36776106 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -25,8 +25,8 @@ void destroy_context(struct mm_struct *mm);
static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
#ifdef CONFIG_SMP
- if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK)
- percpu_write(cpu_tlbstate.state, TLBSTATE_LAZY);
+ if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK)
+ this_cpu_write(cpu_tlbstate.state, TLBSTATE_LAZY);
#endif
}
@@ -37,8 +37,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
if (likely(prev != next)) {
#ifdef CONFIG_SMP
- percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
- percpu_write(cpu_tlbstate.active_mm, next);
+ this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK);
+ this_cpu_write(cpu_tlbstate.active_mm, next);
#endif
cpumask_set_cpu(cpu, mm_cpumask(next));
@@ -56,8 +56,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
}
#ifdef CONFIG_SMP
else {
- percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
- BUG_ON(percpu_read(cpu_tlbstate.active_mm) != next);
+ this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK);
+ BUG_ON(this_cpu_read(cpu_tlbstate.active_mm) != next);
if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next))) {
/* We were in lazy tlb mode and leave_mm disabled
diff --git a/arch/x86/include/asm/mmzone_32.h b/arch/x86/include/asm/mmzone_32.h
index 55728e121473..eb05fb3b02fb 100644
--- a/arch/x86/include/asm/mmzone_32.h
+++ b/arch/x86/include/asm/mmzone_32.h
@@ -61,10 +61,4 @@ static inline int pfn_valid(int pfn)
#endif /* CONFIG_DISCONTIGMEM */
-#ifdef CONFIG_NEED_MULTIPLE_NODES
-/* always use node 0 for bootmem on this numa platform */
-#define bootmem_arch_preferred_node(__bdata, size, align, goal, limit) \
- (NODE_DATA(0)->bdata)
-#endif /* CONFIG_NEED_MULTIPLE_NODES */
-
#endif /* _ASM_X86_MMZONE_32_H */
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index ccb805966f68..957ec87385af 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -134,6 +134,8 @@
#define MSR_AMD64_IBSFETCHCTL 0xc0011030
#define MSR_AMD64_IBSFETCHLINAD 0xc0011031
#define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032
+#define MSR_AMD64_IBSFETCH_REG_COUNT 3
+#define MSR_AMD64_IBSFETCH_REG_MASK ((1UL<<MSR_AMD64_IBSFETCH_REG_COUNT)-1)
#define MSR_AMD64_IBSOPCTL 0xc0011033
#define MSR_AMD64_IBSOPRIP 0xc0011034
#define MSR_AMD64_IBSOPDATA 0xc0011035
@@ -141,8 +143,11 @@
#define MSR_AMD64_IBSOPDATA3 0xc0011037
#define MSR_AMD64_IBSDCLINAD 0xc0011038
#define MSR_AMD64_IBSDCPHYSAD 0xc0011039
+#define MSR_AMD64_IBSOP_REG_COUNT 7
+#define MSR_AMD64_IBSOP_REG_MASK ((1UL<<MSR_AMD64_IBSOP_REG_COUNT)-1)
#define MSR_AMD64_IBSCTL 0xc001103a
#define MSR_AMD64_IBSBRTARGET 0xc001103b
+#define MSR_AMD64_IBS_REG_COUNT_MAX 8 /* includes MSR_AMD64_IBSBRTARGET */
/* Fam 15h MSRs */
#define MSR_F15H_PERF_CTL 0xc0010200
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index 95203d40ffdd..084ef95274cd 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -169,14 +169,7 @@ static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high)
return native_write_msr_safe(msr, low, high);
}
-/*
- * rdmsr with exception handling.
- *
- * Please note that the exception handling works only after we've
- * switched to the "smart" #GP handler in trap_init() which knows about
- * exception tables - using this macro earlier than that causes machine
- * hangs on boxes which do not implement the @msr in the first argument.
- */
+/* rdmsr with exception handling */
#define rdmsr_safe(msr, p1, p2) \
({ \
int __err; \
diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h
index fd3f9f18cf3f..0e3793b821ef 100644
--- a/arch/x86/include/asm/nmi.h
+++ b/arch/x86/include/asm/nmi.h
@@ -27,6 +27,8 @@ void arch_trigger_all_cpu_backtrace(void);
enum {
NMI_LOCAL=0,
NMI_UNKNOWN,
+ NMI_SERR,
+ NMI_IO_CHECK,
NMI_MAX
};
@@ -35,8 +37,24 @@ enum {
typedef int (*nmi_handler_t)(unsigned int, struct pt_regs *);
-int register_nmi_handler(unsigned int, nmi_handler_t, unsigned long,
- const char *);
+struct nmiaction {
+ struct list_head list;
+ nmi_handler_t handler;
+ unsigned long flags;
+ const char *name;
+};
+
+#define register_nmi_handler(t, fn, fg, n) \
+({ \
+ static struct nmiaction fn##_na = { \
+ .handler = (fn), \
+ .name = (n), \
+ .flags = (fg), \
+ }; \
+ __register_nmi_handler((t), &fn##_na); \
+})
+
+int __register_nmi_handler(unsigned int, struct nmiaction *);
void unregister_nmi_handler(unsigned int, const char *);
diff --git a/arch/x86/include/asm/nops.h b/arch/x86/include/asm/nops.h
index 405b4032a60b..aff2b3356101 100644
--- a/arch/x86/include/asm/nops.h
+++ b/arch/x86/include/asm/nops.h
@@ -87,7 +87,11 @@
#define P6_NOP8 0x0f,0x1f,0x84,0x00,0,0,0,0
#define P6_NOP5_ATOMIC P6_NOP5
+#ifdef __ASSEMBLY__
+#define _ASM_MK_NOP(x) .byte x
+#else
#define _ASM_MK_NOP(x) ".byte " __stringify(x) "\n"
+#endif
#if defined(CONFIG_MK7)
#define ASM_NOP1 _ASM_MK_NOP(K7_NOP1)
diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h
index ade619ff9e2a..ef17af013475 100644
--- a/arch/x86/include/asm/page_32_types.h
+++ b/arch/x86/include/asm/page_32_types.h
@@ -15,8 +15,8 @@
*/
#define __PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL)
-#define THREAD_ORDER 1
-#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
+#define THREAD_SIZE_ORDER 1
+#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
#define STACKFAULT_STACK 0
#define DOUBLEFAULT_STACK 1
diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h
index 7639dbf5d223..320f7bb95f76 100644
--- a/arch/x86/include/asm/page_64_types.h
+++ b/arch/x86/include/asm/page_64_types.h
@@ -1,8 +1,8 @@
#ifndef _ASM_X86_PAGE_64_DEFS_H
#define _ASM_X86_PAGE_64_DEFS_H
-#define THREAD_ORDER 1
-#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
+#define THREAD_SIZE_ORDER 1
+#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
#define CURRENT_MASK (~(THREAD_SIZE - 1))
#define EXCEPTION_STACK_ORDER 0
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index aa0f91308367..6cbbabf52707 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -1023,10 +1023,8 @@ extern void default_banner(void);
call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs) \
)
-#define GET_CR2_INTO_RCX \
- call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2); \
- movq %rax, %rcx; \
- xorq %rax, %rax;
+#define GET_CR2_INTO_RAX \
+ call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2)
#define PARAVIRT_ADJUST_EXCEPTION_FRAME \
PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_adjust_exception_frame), \
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index 7a11910a63c4..d9b8e3f7f42a 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -46,7 +46,7 @@
#ifdef CONFIG_SMP
#define __percpu_prefix "%%"__stringify(__percpu_seg)":"
-#define __my_cpu_offset percpu_read(this_cpu_off)
+#define __my_cpu_offset this_cpu_read(this_cpu_off)
/*
* Compared to the generic __my_cpu_offset version, the following
@@ -351,23 +351,15 @@ do { \
})
/*
- * percpu_read() makes gcc load the percpu variable every time it is
- * accessed while percpu_read_stable() allows the value to be cached.
- * percpu_read_stable() is more efficient and can be used if its value
+ * this_cpu_read() makes gcc load the percpu variable every time it is
+ * accessed while this_cpu_read_stable() allows the value to be cached.
+ * this_cpu_read_stable() is more efficient and can be used if its value
* is guaranteed to be valid across cpus. The current users include
* get_current() and get_thread_info() both of which are actually
* per-thread variables implemented as per-cpu variables and thus
* stable for the duration of the respective task.
*/
-#define percpu_read(var) percpu_from_op("mov", var, "m" (var))
-#define percpu_read_stable(var) percpu_from_op("mov", var, "p" (&(var)))
-#define percpu_write(var, val) percpu_to_op("mov", var, val)
-#define percpu_add(var, val) percpu_add_op(var, val)
-#define percpu_sub(var, val) percpu_add_op(var, -(val))
-#define percpu_and(var, val) percpu_to_op("and", var, val)
-#define percpu_or(var, val) percpu_to_op("or", var, val)
-#define percpu_xor(var, val) percpu_to_op("xor", var, val)
-#define percpu_inc(var) percpu_unary_op("inc", var)
+#define this_cpu_read_stable(var) percpu_from_op("mov", var, "p" (&(var)))
#define __this_cpu_read_1(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
#define __this_cpu_read_2(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
@@ -512,7 +504,11 @@ static __always_inline int x86_this_cpu_constant_test_bit(unsigned int nr,
{
unsigned long __percpu *a = (unsigned long *)addr + nr / BITS_PER_LONG;
- return ((1UL << (nr % BITS_PER_LONG)) & percpu_read(*a)) != 0;
+#ifdef CONFIG_X86_64
+ return ((1UL << (nr % BITS_PER_LONG)) & __this_cpu_read_8(*a)) != 0;
+#else
+ return ((1UL << (nr % BITS_PER_LONG)) & __this_cpu_read_4(*a)) != 0;
+#endif
}
static inline int x86_this_cpu_variable_test_bit(int nr,
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 2291895b1836..588f52ea810e 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -158,6 +158,7 @@ struct x86_pmu_capability {
#define IBS_CAPS_OPCNT (1U<<4)
#define IBS_CAPS_BRNTRGT (1U<<5)
#define IBS_CAPS_OPCNTEXT (1U<<6)
+#define IBS_CAPS_RIPINVALIDCHK (1U<<7)
#define IBS_CAPS_DEFAULT (IBS_CAPS_AVAIL \
| IBS_CAPS_FETCHSAM \
@@ -170,21 +171,28 @@ struct x86_pmu_capability {
#define IBSCTL_LVT_OFFSET_VALID (1ULL<<8)
#define IBSCTL_LVT_OFFSET_MASK 0x0F
-/* IbsFetchCtl bits/masks */
+/* ibs fetch bits/masks */
#define IBS_FETCH_RAND_EN (1ULL<<57)
#define IBS_FETCH_VAL (1ULL<<49)
#define IBS_FETCH_ENABLE (1ULL<<48)
#define IBS_FETCH_CNT 0xFFFF0000ULL
#define IBS_FETCH_MAX_CNT 0x0000FFFFULL
-/* IbsOpCtl bits */
+/* ibs op bits/masks */
+/* lower 4 bits of the current count are ignored: */
+#define IBS_OP_CUR_CNT (0xFFFF0ULL<<32)
#define IBS_OP_CNT_CTL (1ULL<<19)
#define IBS_OP_VAL (1ULL<<18)
#define IBS_OP_ENABLE (1ULL<<17)
#define IBS_OP_MAX_CNT 0x0000FFFFULL
#define IBS_OP_MAX_CNT_EXT 0x007FFFFFULL /* not a register bit mask */
+#define IBS_RIP_INVALID (1ULL<<38)
+#ifdef CONFIG_X86_LOCAL_APIC
extern u32 get_ibs_caps(void);
+#else
+static inline u32 get_ibs_caps(void) { return 0; }
+#endif
#ifdef CONFIG_PERF_EVENTS
extern void perf_events_lapic_init(void);
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 4fa7dcceb6c0..7745b257f035 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -579,9 +579,6 @@ extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
-/* Prepare to copy thread state - unlazy all lazy state */
-extern void prepare_to_copy(struct task_struct *tsk);
-
unsigned long get_wchan(struct task_struct *p);
/*
@@ -974,8 +971,6 @@ extern bool cpu_has_amd_erratum(const int *);
#define cpu_has_amd_erratum(x) (false)
#endif /* CONFIG_CPU_SUP_AMD */
-void cpu_idle_wait(void);
-
extern unsigned long arch_align_stack(unsigned long sp);
extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index 165466233ab0..c48a95035a77 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -205,13 +205,15 @@
#define IDT_ENTRIES 256
#define NUM_EXCEPTION_VECTORS 32
+/* Bitmask of exception vectors which push an error code on the stack */
+#define EXCEPTION_ERRCODE_MASK 0x00027d00
#define GDT_SIZE (GDT_ENTRIES * 8)
#define GDT_ENTRY_TLS_ENTRIES 3
#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
-extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][10];
+extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5];
/*
* Load a segment. Fall back on loading the zero
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index 0434c400287c..f48394513c37 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -62,6 +62,8 @@ DECLARE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid);
/* Static state in head.S used to set up a CPU */
extern unsigned long stack_start; /* Initial stack pointer address */
+struct task_struct;
+
struct smp_ops {
void (*smp_prepare_boot_cpu)(void);
void (*smp_prepare_cpus)(unsigned max_cpus);
@@ -70,7 +72,7 @@ struct smp_ops {
void (*stop_other_cpus)(int wait);
void (*smp_send_reschedule)(int cpu);
- int (*cpu_up)(unsigned cpu);
+ int (*cpu_up)(unsigned cpu, struct task_struct *tidle);
int (*cpu_disable)(void);
void (*cpu_die)(unsigned int cpu);
void (*play_dead)(void);
@@ -113,9 +115,9 @@ static inline void smp_cpus_done(unsigned int max_cpus)
smp_ops.smp_cpus_done(max_cpus);
}
-static inline int __cpu_up(unsigned int cpu)
+static inline int __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
- return smp_ops.cpu_up(cpu);
+ return smp_ops.cpu_up(cpu, tidle);
}
static inline int __cpu_disable(void)
@@ -152,7 +154,7 @@ void cpu_disable_common(void);
void native_smp_prepare_boot_cpu(void);
void native_smp_prepare_cpus(unsigned int max_cpus);
void native_smp_cpus_done(unsigned int max_cpus);
-int native_cpu_up(unsigned int cpunum);
+int native_cpu_up(unsigned int cpunum, struct task_struct *tidle);
int native_cpu_disable(void);
void native_cpu_die(unsigned int cpu);
void native_play_dead(void);
@@ -162,6 +164,7 @@ int wbinvd_on_all_cpus(void);
void native_send_call_func_ipi(const struct cpumask *mask);
void native_send_call_func_single_ipi(int cpu);
+void x86_idle_thread_init(unsigned int cpu, struct task_struct *idle);
void smp_store_cpu_info(int id);
#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu)
@@ -188,11 +191,11 @@ extern unsigned disabled_cpus __cpuinitdata;
* from the initial startup. We map APIC_BASE very early in page_setup(),
* so this is correct in the x86 case.
*/
-#define raw_smp_processor_id() (percpu_read(cpu_number))
+#define raw_smp_processor_id() (this_cpu_read(cpu_number))
extern int safe_smp_processor_id(void);
#elif defined(CONFIG_X86_64_SMP)
-#define raw_smp_processor_id() (percpu_read(cpu_number))
+#define raw_smp_processor_id() (this_cpu_read(cpu_number))
#define stack_smp_processor_id() \
({ \
diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h
index 76bfa2cf301d..b315a33867f2 100644
--- a/arch/x86/include/asm/spinlock.h
+++ b/arch/x86/include/asm/spinlock.h
@@ -20,10 +20,8 @@
#ifdef CONFIG_X86_32
# define LOCK_PTR_REG "a"
-# define REG_PTR_MODE "k"
#else
# define LOCK_PTR_REG "D"
-# define REG_PTR_MODE "q"
#endif
#if defined(CONFIG_X86_32) && \
diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h
index b5d9533d2c38..6a998598f172 100644
--- a/arch/x86/include/asm/stackprotector.h
+++ b/arch/x86/include/asm/stackprotector.h
@@ -75,9 +75,9 @@ static __always_inline void boot_init_stack_canary(void)
current->stack_canary = canary;
#ifdef CONFIG_X86_64
- percpu_write(irq_stack_union.stack_canary, canary);
+ this_cpu_write(irq_stack_union.stack_canary, canary);
#else
- percpu_write(stack_canary.canary, canary);
+ this_cpu_write(stack_canary.canary, canary);
#endif
}
diff --git a/arch/x86/include/asm/stat.h b/arch/x86/include/asm/stat.h
index e0b1d9bbcbc6..7b3ddc348585 100644
--- a/arch/x86/include/asm/stat.h
+++ b/arch/x86/include/asm/stat.h
@@ -25,6 +25,12 @@ struct stat {
unsigned long __unused5;
};
+/* We don't need to memset the whole thing just to initialize the padding */
+#define INIT_STRUCT_STAT_PADDING(st) do { \
+ st.__unused4 = 0; \
+ st.__unused5 = 0; \
+} while (0)
+
#define STAT64_HAS_BROKEN_ST_INO 1
/* This matches struct stat64 in glibc2.1, hence the absolutely
@@ -63,6 +69,12 @@ struct stat64 {
unsigned long long st_ino;
};
+/* We don't need to memset the whole thing just to initialize the padding */
+#define INIT_STRUCT_STAT64_PADDING(st) do { \
+ memset(&st.__pad0, 0, sizeof(st.__pad0)); \
+ memset(&st.__pad3, 0, sizeof(st.__pad3)); \
+} while (0)
+
#else /* __i386__ */
struct stat {
@@ -87,6 +99,15 @@ struct stat {
unsigned long st_ctime_nsec;
long __unused[3];
};
+
+/* We don't need to memset the whole thing just to initialize the padding */
+#define INIT_STRUCT_STAT_PADDING(st) do { \
+ st.__pad0 = 0; \
+ st.__unused[0] = 0; \
+ st.__unused[1] = 0; \
+ st.__unused[2] = 0; \
+} while (0)
+
#endif
/* for 32bit emulation and 32 bit kernels */
diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h
index 386b78686c4d..1ace47b62592 100644
--- a/arch/x86/include/asm/syscall.h
+++ b/arch/x86/include/asm/syscall.h
@@ -13,9 +13,11 @@
#ifndef _ASM_X86_SYSCALL_H
#define _ASM_X86_SYSCALL_H
+#include <linux/audit.h>
#include <linux/sched.h>
#include <linux/err.h>
#include <asm/asm-offsets.h> /* For NR_syscalls */
+#include <asm/thread_info.h> /* for TS_COMPAT */
#include <asm/unistd.h>
extern const unsigned long sys_call_table[];
@@ -88,6 +90,12 @@ static inline void syscall_set_arguments(struct task_struct *task,
memcpy(&regs->bx + i, args, n * sizeof(args[0]));
}
+static inline int syscall_get_arch(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ return AUDIT_ARCH_I386;
+}
+
#else /* CONFIG_X86_64 */
static inline void syscall_get_arguments(struct task_struct *task,
@@ -212,6 +220,25 @@ static inline void syscall_set_arguments(struct task_struct *task,
}
}
+static inline int syscall_get_arch(struct task_struct *task,
+ struct pt_regs *regs)
+{
+#ifdef CONFIG_IA32_EMULATION
+ /*
+ * TS_COMPAT is set for 32-bit syscall entry and then
+ * remains set until we return to user mode.
+ *
+ * TIF_IA32 tasks should always have TS_COMPAT set at
+ * system call time.
+ *
+ * x32 tasks should be considered AUDIT_ARCH_X86_64.
+ */
+ if (task_thread_info(task)->status & TS_COMPAT)
+ return AUDIT_ARCH_I386;
+#endif
+ /* Both x32 and x86_64 are considered "64-bit". */
+ return AUDIT_ARCH_X86_64;
+}
#endif /* CONFIG_X86_32 */
#endif /* _ASM_X86_SYSCALL_H */
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index ad6df8ccd715..3c9aebc00d39 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -155,24 +155,6 @@ struct thread_info {
#define PREEMPT_ACTIVE 0x10000000
-/* thread information allocation */
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define THREAD_FLAGS (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO)
-#else
-#define THREAD_FLAGS (GFP_KERNEL | __GFP_NOTRACK)
-#endif
-
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-
-#define alloc_thread_info_node(tsk, node) \
-({ \
- struct page *page = alloc_pages_node(node, THREAD_FLAGS, \
- THREAD_ORDER); \
- struct thread_info *ret = page ? page_address(page) : NULL; \
- \
- ret; \
-})
-
#ifdef CONFIG_X86_32
#define STACK_WARN (THREAD_SIZE/8)
@@ -222,7 +204,7 @@ DECLARE_PER_CPU(unsigned long, kernel_stack);
static inline struct thread_info *current_thread_info(void)
{
struct thread_info *ti;
- ti = (void *)(percpu_read_stable(kernel_stack) +
+ ti = (void *)(this_cpu_read_stable(kernel_stack) +
KERNEL_STACK_OFFSET - THREAD_SIZE);
return ti;
}
@@ -282,8 +264,7 @@ static inline bool is_ia32_task(void)
#ifndef __ASSEMBLY__
extern void arch_task_cache_init(void);
-extern void free_thread_info(struct thread_info *ti);
extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
-#define arch_task_cache_init arch_task_cache_init
+extern void arch_release_task_struct(struct task_struct *tsk);
#endif
#endif /* _ASM_X86_THREAD_INFO_H */
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index c0e108e08079..36a1a2ab87d2 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -62,11 +62,7 @@ static inline void __flush_tlb_one(unsigned long addr)
__flush_tlb();
}
-#ifdef CONFIG_X86_32
-# define TLB_FLUSH_ALL 0xffffffff
-#else
-# define TLB_FLUSH_ALL -1ULL
-#endif
+#define TLB_FLUSH_ALL -1UL
/*
* TLB flushing:
@@ -156,8 +152,8 @@ DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);
static inline void reset_lazy_tlbstate(void)
{
- percpu_write(cpu_tlbstate.state, 0);
- percpu_write(cpu_tlbstate.active_mm, &init_mm);
+ this_cpu_write(cpu_tlbstate.state, 0);
+ this_cpu_write(cpu_tlbstate.active_mm, &init_mm);
}
#endif /* SMP */
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index b9676ae37ada..095b21507b6a 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -92,44 +92,6 @@ extern void setup_node_to_cpumask_map(void);
#define pcibus_to_node(bus) __pcibus_to_node(bus)
-#ifdef CONFIG_X86_32
-# define SD_CACHE_NICE_TRIES 1
-# define SD_IDLE_IDX 1
-#else
-# define SD_CACHE_NICE_TRIES 2
-# define SD_IDLE_IDX 2
-#endif
-
-/* sched_domains SD_NODE_INIT for NUMA machines */
-#define SD_NODE_INIT (struct sched_domain) { \
- .min_interval = 8, \
- .max_interval = 32, \
- .busy_factor = 32, \
- .imbalance_pct = 125, \
- .cache_nice_tries = SD_CACHE_NICE_TRIES, \
- .busy_idx = 3, \
- .idle_idx = SD_IDLE_IDX, \
- .newidle_idx = 0, \
- .wake_idx = 0, \
- .forkexec_idx = 0, \
- \
- .flags = 1*SD_LOAD_BALANCE \
- | 1*SD_BALANCE_NEWIDLE \
- | 1*SD_BALANCE_EXEC \
- | 1*SD_BALANCE_FORK \
- | 0*SD_BALANCE_WAKE \
- | 1*SD_WAKE_AFFINE \
- | 0*SD_PREFER_LOCAL \
- | 0*SD_SHARE_CPUPOWER \
- | 0*SD_POWERSAVINGS_BALANCE \
- | 0*SD_SHARE_PKG_RESOURCES \
- | 1*SD_SERIALIZE \
- | 0*SD_PREFER_SIBLING \
- , \
- .last_balance = jiffies, \
- .balance_interval = 1, \
-}
-
extern int __node_distance(int, int);
#define node_distance(a, b) __node_distance(a, b)
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index e0544597cfe7..851fe0dc13bc 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -79,11 +79,12 @@
#define access_ok(type, addr, size) (likely(__range_not_ok(addr, size) == 0))
/*
- * The exception table consists of pairs of addresses: the first is the
- * address of an instruction that is allowed to fault, and the second is
- * the address at which the program should continue. No registers are
- * modified, so it is entirely up to the continuation code to figure out
- * what to do.
+ * The exception table consists of pairs of addresses relative to the
+ * exception table enty itself: the first is the address of an
+ * instruction that is allowed to fault, and the second is the address
+ * at which the program should continue. No registers are modified,
+ * so it is entirely up to the continuation code to figure out what to
+ * do.
*
* All the routines below use bits of fixup code that are out of line
* with the main instruction path. This means when everything is well,
@@ -92,10 +93,14 @@
*/
struct exception_table_entry {
- unsigned long insn, fixup;
+ int insn, fixup;
};
+/* This is not the generic standard exception_table_entry format */
+#define ARCH_HAS_SORT_EXTABLE
+#define ARCH_HAS_SEARCH_EXTABLE
extern int fixup_exception(struct pt_regs *regs);
+extern int early_fixup_exception(unsigned long *ip);
/*
* These are the main single-value transfer routines. They automatically
@@ -202,8 +207,8 @@ extern int __get_user_bad(void);
asm volatile("1: movl %%eax,0(%1)\n" \
"2: movl %%edx,4(%1)\n" \
"3:\n" \
- _ASM_EXTABLE(1b, 2b - 1b) \
- _ASM_EXTABLE(2b, 3b - 2b) \
+ _ASM_EXTABLE_EX(1b, 2b) \
+ _ASM_EXTABLE_EX(2b, 3b) \
: : "A" (x), "r" (addr))
#define __put_user_x8(x, ptr, __ret_pu) \
@@ -408,7 +413,7 @@ do { \
#define __get_user_asm_ex(x, addr, itype, rtype, ltype) \
asm volatile("1: mov"itype" %1,%"rtype"0\n" \
"2:\n" \
- _ASM_EXTABLE(1b, 2b - 1b) \
+ _ASM_EXTABLE_EX(1b, 2b) \
: ltype(x) : "m" (__m(addr)))
#define __put_user_nocheck(x, ptr, size) \
@@ -450,7 +455,7 @@ struct __large_struct { unsigned long buf[100]; };
#define __put_user_asm_ex(x, addr, itype, rtype, ltype) \
asm volatile("1: mov"itype" %"rtype"0,%1\n" \
"2:\n" \
- _ASM_EXTABLE(1b, 2b - 1b) \
+ _ASM_EXTABLE_EX(1b, 2b) \
: : ltype(x), "m" (__m(addr)))
/*
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 764b66a4cf89..c090af10ac7d 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -188,11 +188,18 @@ struct x86_msi_ops {
void (*restore_msi_irqs)(struct pci_dev *dev, int irq);
};
+struct x86_io_apic_ops {
+ void (*init) (void);
+ unsigned int (*read) (unsigned int apic, unsigned int reg);
+ void (*write) (unsigned int apic, unsigned int reg, unsigned int value);
+ void (*modify)(unsigned int apic, unsigned int reg, unsigned int value);
+};
+
extern struct x86_init_ops x86_init;
extern struct x86_cpuinit_ops x86_cpuinit;
extern struct x86_platform_ops x86_platform;
extern struct x86_msi_ops x86_msi;
-
+extern struct x86_io_apic_ops x86_io_apic_ops;
extern void x86_init_noop(void);
extern void x86_init_uint_noop(unsigned int unused);
diff --git a/arch/x86/include/asm/xor_32.h b/arch/x86/include/asm/xor_32.h
index 133b40a0f495..454570891bdc 100644
--- a/arch/x86/include/asm/xor_32.h
+++ b/arch/x86/include/asm/xor_32.h
@@ -861,6 +861,9 @@ static struct xor_block_template xor_block_pIII_sse = {
.do_5 = xor_sse_5,
};
+/* Also try the AVX routines */
+#include "xor_avx.h"
+
/* Also try the generic routines. */
#include <asm-generic/xor.h>
@@ -871,6 +874,7 @@ do { \
xor_speed(&xor_block_8regs_p); \
xor_speed(&xor_block_32regs); \
xor_speed(&xor_block_32regs_p); \
+ AVX_XOR_SPEED; \
if (cpu_has_xmm) \
xor_speed(&xor_block_pIII_sse); \
if (cpu_has_mmx) { \
@@ -883,6 +887,6 @@ do { \
We may also be able to load into the L1 only depending on how the cpu
deals with a load to a line that is being prefetched. */
#define XOR_SELECT_TEMPLATE(FASTEST) \
- (cpu_has_xmm ? &xor_block_pIII_sse : FASTEST)
+ AVX_SELECT(cpu_has_xmm ? &xor_block_pIII_sse : FASTEST)
#endif /* _ASM_X86_XOR_32_H */
diff --git a/arch/x86/include/asm/xor_64.h b/arch/x86/include/asm/xor_64.h
index 1549b5e261f6..b9b2323e90fe 100644
--- a/arch/x86/include/asm/xor_64.h
+++ b/arch/x86/include/asm/xor_64.h
@@ -347,15 +347,21 @@ static struct xor_block_template xor_block_sse = {
.do_5 = xor_sse_5,
};
+
+/* Also try the AVX routines */
+#include "xor_avx.h"
+
#undef XOR_TRY_TEMPLATES
#define XOR_TRY_TEMPLATES \
do { \
+ AVX_XOR_SPEED; \
xor_speed(&xor_block_sse); \
} while (0)
/* We force the use of the SSE xor block because it can write around L2.
We may also be able to load into the L1 only depending on how the cpu
deals with a load to a line that is being prefetched. */
-#define XOR_SELECT_TEMPLATE(FASTEST) (&xor_block_sse)
+#define XOR_SELECT_TEMPLATE(FASTEST) \
+ AVX_SELECT(&xor_block_sse)
#endif /* _ASM_X86_XOR_64_H */
diff --git a/arch/x86/include/asm/xor_avx.h b/arch/x86/include/asm/xor_avx.h
new file mode 100644
index 000000000000..2510d35f480e
--- /dev/null
+++ b/arch/x86/include/asm/xor_avx.h
@@ -0,0 +1,214 @@
+#ifndef _ASM_X86_XOR_AVX_H
+#define _ASM_X86_XOR_AVX_H
+
+/*
+ * Optimized RAID-5 checksumming functions for AVX
+ *
+ * Copyright (C) 2012 Intel Corporation
+ * Author: Jim Kukunas <james.t.kukunas@linux.intel.com>
+ *
+ * Based on Ingo Molnar and Zach Brown's respective MMX and SSE routines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#ifdef CONFIG_AS_AVX
+
+#include <linux/compiler.h>
+#include <asm/i387.h>
+
+#define ALIGN32 __aligned(32)
+
+#define YMM_SAVED_REGS 4
+
+#define YMMS_SAVE \
+do { \
+ preempt_disable(); \
+ cr0 = read_cr0(); \
+ clts(); \
+ asm volatile("vmovaps %%ymm0, %0" : "=m" (ymm_save[0]) : : "memory"); \
+ asm volatile("vmovaps %%ymm1, %0" : "=m" (ymm_save[32]) : : "memory"); \
+ asm volatile("vmovaps %%ymm2, %0" : "=m" (ymm_save[64]) : : "memory"); \
+ asm volatile("vmovaps %%ymm3, %0" : "=m" (ymm_save[96]) : : "memory"); \
+} while (0);
+
+#define YMMS_RESTORE \
+do { \
+ asm volatile("sfence" : : : "memory"); \
+ asm volatile("vmovaps %0, %%ymm3" : : "m" (ymm_save[96])); \
+ asm volatile("vmovaps %0, %%ymm2" : : "m" (ymm_save[64])); \
+ asm volatile("vmovaps %0, %%ymm1" : : "m" (ymm_save[32])); \
+ asm volatile("vmovaps %0, %%ymm0" : : "m" (ymm_save[0])); \
+ write_cr0(cr0); \
+ preempt_enable(); \
+} while (0);
+
+#define BLOCK4(i) \
+ BLOCK(32 * i, 0) \
+ BLOCK(32 * (i + 1), 1) \
+ BLOCK(32 * (i + 2), 2) \
+ BLOCK(32 * (i + 3), 3)
+
+#define BLOCK16() \
+ BLOCK4(0) \
+ BLOCK4(4) \
+ BLOCK4(8) \
+ BLOCK4(12)
+
+static void xor_avx_2(unsigned long bytes, unsigned long *p0, unsigned long *p1)
+{
+ unsigned long cr0, lines = bytes >> 9;
+ char ymm_save[32 * YMM_SAVED_REGS] ALIGN32;
+
+ YMMS_SAVE
+
+ while (lines--) {
+#undef BLOCK
+#define BLOCK(i, reg) \
+do { \
+ asm volatile("vmovdqa %0, %%ymm" #reg : : "m" (p1[i / sizeof(*p1)])); \
+ asm volatile("vxorps %0, %%ymm" #reg ", %%ymm" #reg : : \
+ "m" (p0[i / sizeof(*p0)])); \
+ asm volatile("vmovdqa %%ymm" #reg ", %0" : \
+ "=m" (p0[i / sizeof(*p0)])); \
+} while (0);
+
+ BLOCK16()
+
+ p0 = (unsigned long *)((uintptr_t)p0 + 512);
+ p1 = (unsigned long *)((uintptr_t)p1 + 512);
+ }
+
+ YMMS_RESTORE
+}
+
+static void xor_avx_3(unsigned long bytes, unsigned long *p0, unsigned long *p1,
+ unsigned long *p2)
+{
+ unsigned long cr0, lines = bytes >> 9;
+ char ymm_save[32 * YMM_SAVED_REGS] ALIGN32;
+
+ YMMS_SAVE
+
+ while (lines--) {
+#undef BLOCK
+#define BLOCK(i, reg) \
+do { \
+ asm volatile("vmovdqa %0, %%ymm" #reg : : "m" (p2[i / sizeof(*p2)])); \
+ asm volatile("vxorps %0, %%ymm" #reg ", %%ymm" #reg : : \
+ "m" (p1[i / sizeof(*p1)])); \
+ asm volatile("vxorps %0, %%ymm" #reg ", %%ymm" #reg : : \
+ "m" (p0[i / sizeof(*p0)])); \
+ asm volatile("vmovdqa %%ymm" #reg ", %0" : \
+ "=m" (p0[i / sizeof(*p0)])); \
+} while (0);
+
+ BLOCK16()
+
+ p0 = (unsigned long *)((uintptr_t)p0 + 512);
+ p1 = (unsigned long *)((uintptr_t)p1 + 512);
+ p2 = (unsigned long *)((uintptr_t)p2 + 512);
+ }
+
+ YMMS_RESTORE
+}
+
+static void xor_avx_4(unsigned long bytes, unsigned long *p0, unsigned long *p1,
+ unsigned long *p2, unsigned long *p3)
+{
+ unsigned long cr0, lines = bytes >> 9;
+ char ymm_save[32 * YMM_SAVED_REGS] ALIGN32;
+
+ YMMS_SAVE
+
+ while (lines--) {
+#undef BLOCK
+#define BLOCK(i, reg) \
+do { \
+ asm volatile("vmovdqa %0, %%ymm" #reg : : "m" (p3[i / sizeof(*p3)])); \
+ asm volatile("vxorps %0, %%ymm" #reg ", %%ymm" #reg : : \
+ "m" (p2[i / sizeof(*p2)])); \
+ asm volatile("vxorps %0, %%ymm" #reg ", %%ymm" #reg : : \
+ "m" (p1[i / sizeof(*p1)])); \
+ asm volatile("vxorps %0, %%ymm" #reg ", %%ymm" #reg : : \
+ "m" (p0[i / sizeof(*p0)])); \
+ asm volatile("vmovdqa %%ymm" #reg ", %0" : \
+ "=m" (p0[i / sizeof(*p0)])); \
+} while (0);
+
+ BLOCK16();
+
+ p0 = (unsigned long *)((uintptr_t)p0 + 512);
+ p1 = (unsigned long *)((uintptr_t)p1 + 512);
+ p2 = (unsigned long *)((uintptr_t)p2 + 512);
+ p3 = (unsigned long *)((uintptr_t)p3 + 512);
+ }
+
+ YMMS_RESTORE
+}
+
+static void xor_avx_5(unsigned long bytes, unsigned long *p0, unsigned long *p1,
+ unsigned long *p2, unsigned long *p3, unsigned long *p4)
+{
+ unsigned long cr0, lines = bytes >> 9;
+ char ymm_save[32 * YMM_SAVED_REGS] ALIGN32;
+
+ YMMS_SAVE
+
+ while (lines--) {
+#undef BLOCK
+#define BLOCK(i, reg) \
+do { \
+ asm volatile("vmovdqa %0, %%ymm" #reg : : "m" (p4[i / sizeof(*p4)])); \
+ asm volatile("vxorps %0, %%ymm" #reg ", %%ymm" #reg : : \
+ "m" (p3[i / sizeof(*p3)])); \
+ asm volatile("vxorps %0, %%ymm" #reg ", %%ymm" #reg : : \
+ "m" (p2[i / sizeof(*p2)])); \
+ asm volatile("vxorps %0, %%ymm" #reg ", %%ymm" #reg : : \
+ "m" (p1[i / sizeof(*p1)])); \
+ asm volatile("vxorps %0, %%ymm" #reg ", %%ymm" #reg : : \
+ "m" (p0[i / sizeof(*p0)])); \
+ asm volatile("vmovdqa %%ymm" #reg ", %0" : \
+ "=m" (p0[i / sizeof(*p0)])); \
+} while (0);
+
+ BLOCK16()
+
+ p0 = (unsigned long *)((uintptr_t)p0 + 512);
+ p1 = (unsigned long *)((uintptr_t)p1 + 512);
+ p2 = (unsigned long *)((uintptr_t)p2 + 512);
+ p3 = (unsigned long *)((uintptr_t)p3 + 512);
+ p4 = (unsigned long *)((uintptr_t)p4 + 512);
+ }
+
+ YMMS_RESTORE
+}
+
+static struct xor_block_template xor_block_avx = {
+ .name = "avx",
+ .do_2 = xor_avx_2,
+ .do_3 = xor_avx_3,
+ .do_4 = xor_avx_4,
+ .do_5 = xor_avx_5,
+};
+
+#define AVX_XOR_SPEED \
+do { \
+ if (cpu_has_avx) \
+ xor_speed(&xor_block_avx); \
+} while (0)
+
+#define AVX_SELECT(FASTEST) \
+ (cpu_has_avx ? &xor_block_avx : FASTEST)
+
+#else
+
+#define AVX_XOR_SPEED {}
+
+#define AVX_SELECT(FASTEST) (FASTEST)
+
+#endif
+#endif
diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h
index c6ce2452f10c..8a1b6f9b594a 100644
--- a/arch/x86/include/asm/xsave.h
+++ b/arch/x86/include/asm/xsave.h
@@ -80,10 +80,7 @@ static inline int xsave_user(struct xsave_struct __user *buf)
"3: movl $-1,%[err]\n"
" jmp 2b\n"
".previous\n"
- ".section __ex_table,\"a\"\n"
- _ASM_ALIGN "\n"
- _ASM_PTR "1b,3b\n"
- ".previous"
+ _ASM_EXTABLE(1b,3b)
: [err] "=r" (err)
: "D" (buf), "a" (-1), "d" (-1), "0" (0)
: "memory");
@@ -106,10 +103,7 @@ static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask)
"3: movl $-1,%[err]\n"
" jmp 2b\n"
".previous\n"
- ".section __ex_table,\"a\"\n"
- _ASM_ALIGN "\n"
- _ASM_PTR "1b,3b\n"
- ".previous"
+ _ASM_EXTABLE(1b,3b)
: [err] "=r" (err)
: "D" (xstate), "a" (lmask), "d" (hmask), "0" (0)
: "memory"); /* memory required? */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 7d1569947204..bb8529275aab 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -2,7 +2,7 @@
# Makefile for the linux kernel.
#
-extra-y := head_$(BITS).o head$(BITS).o head.o init_task.o vmlinux.lds
+extra-y := head_$(BITS).o head$(BITS).o head.o vmlinux.lds
CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE)
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index f564b189de1a..8afb69319815 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -593,7 +593,7 @@ void __init acpi_set_irq_model_ioapic(void)
#ifdef CONFIG_ACPI_HOTPLUG_CPU
#include <acpi/processor.h>
-static void __cpuinitdata acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
+static void __cpuinit acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
{
#ifdef CONFIG_ACPI_NUMA
int nid;
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index edc24480469f..39a222e094af 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -35,6 +35,7 @@
#include <linux/smp.h>
#include <linux/mm.h>
+#include <asm/irq_remapping.h>
#include <asm/perf_event.h>
#include <asm/x86_init.h>
#include <asm/pgalloc.h>
@@ -1325,11 +1326,13 @@ void __cpuinit setup_local_APIC(void)
acked);
break;
}
- if (cpu_has_tsc) {
- rdtscll(ntsc);
- max_loops = (cpu_khz << 10) - (ntsc - tsc);
- } else
- max_loops--;
+ if (queued) {
+ if (cpu_has_tsc) {
+ rdtscll(ntsc);
+ max_loops = (cpu_khz << 10) - (ntsc - tsc);
+ } else
+ max_loops--;
+ }
} while (queued && max_loops > 0);
WARN_ON(max_loops <= 0);
@@ -1441,8 +1444,8 @@ void __init bsp_end_local_APIC_setup(void)
* Now that local APIC setup is completed for BP, configure the fault
* handling for interrupt remapping.
*/
- if (intr_remapping_enabled)
- enable_drhd_fault_handling();
+ if (irq_remapping_enabled)
+ irq_remap_enable_fault_handling();
}
@@ -1517,7 +1520,7 @@ void enable_x2apic(void)
int __init enable_IR(void)
{
#ifdef CONFIG_IRQ_REMAP
- if (!intr_remapping_supported()) {
+ if (!irq_remapping_supported()) {
pr_debug("intr-remapping not supported\n");
return -1;
}
@@ -1528,7 +1531,7 @@ int __init enable_IR(void)
return -1;
}
- return enable_intr_remapping();
+ return irq_remapping_enable();
#endif
return -1;
}
@@ -1537,10 +1540,13 @@ void __init enable_IR_x2apic(void)
{
unsigned long flags;
int ret, x2apic_enabled = 0;
- int dmar_table_init_ret;
+ int hardware_init_ret;
+
+ /* Make sure irq_remap_ops are initialized */
+ setup_irq_remapping_ops();
- dmar_table_init_ret = dmar_table_init();
- if (dmar_table_init_ret && !x2apic_supported())
+ hardware_init_ret = irq_remapping_prepare();
+ if (hardware_init_ret && !x2apic_supported())
return;
ret = save_ioapic_entries();
@@ -1556,7 +1562,7 @@ void __init enable_IR_x2apic(void)
if (x2apic_preenabled && nox2apic)
disable_x2apic();
- if (dmar_table_init_ret)
+ if (hardware_init_ret)
ret = -1;
else
ret = enable_IR();
@@ -2176,8 +2182,8 @@ static int lapic_suspend(void)
local_irq_save(flags);
disable_local_APIC();
- if (intr_remapping_enabled)
- disable_intr_remapping();
+ if (irq_remapping_enabled)
+ irq_remapping_disable();
local_irq_restore(flags);
return 0;
@@ -2193,7 +2199,7 @@ static void lapic_resume(void)
return;
local_irq_save(flags);
- if (intr_remapping_enabled) {
+ if (irq_remapping_enabled) {
/*
* IO-APIC and PIC have their own resume routines.
* We just mask them here to make sure the interrupt
@@ -2245,8 +2251,8 @@ static void lapic_resume(void)
apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);
- if (intr_remapping_enabled)
- reenable_intr_remapping(x2apic_mode);
+ if (irq_remapping_enabled)
+ irq_remapping_reenable(x2apic_mode);
local_irq_restore(flags);
}
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c
index 359b6899a36c..0e881c46e8c8 100644
--- a/arch/x86/kernel/apic/apic_flat_64.c
+++ b/arch/x86/kernel/apic/apic_flat_64.c
@@ -227,6 +227,7 @@ static struct apic apic_flat = {
.read = native_apic_mem_read,
.write = native_apic_mem_write,
+ .eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle,
@@ -386,6 +387,7 @@ static struct apic apic_physflat = {
.read = native_apic_mem_read,
.write = native_apic_mem_write,
+ .eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle,
diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c
index 634ae6cdd5c9..a6e4c6e06c08 100644
--- a/arch/x86/kernel/apic/apic_noop.c
+++ b/arch/x86/kernel/apic/apic_noop.c
@@ -181,6 +181,7 @@ struct apic apic_noop = {
.read = noop_apic_read,
.write = noop_apic_write,
+ .eoi_write = noop_apic_write,
.icr_read = noop_apic_icr_read,
.icr_write = noop_apic_icr_write,
.wait_icr_idle = noop_apic_wait_icr_idle,
diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c
index 23e75422e013..6ec6d5d297c3 100644
--- a/arch/x86/kernel/apic/apic_numachip.c
+++ b/arch/x86/kernel/apic/apic_numachip.c
@@ -295,6 +295,7 @@ static struct apic apic_numachip __refconst = {
.read = native_apic_mem_read,
.write = native_apic_mem_write,
+ .eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle,
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c
index 0cdec7065aff..31fbdbfbf960 100644
--- a/arch/x86/kernel/apic/bigsmp_32.c
+++ b/arch/x86/kernel/apic/bigsmp_32.c
@@ -248,6 +248,7 @@ static struct apic apic_bigsmp = {
.read = native_apic_mem_read,
.write = native_apic_mem_write,
+ .eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle,
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c
index e42d1d3b9134..db4ab1be3c79 100644
--- a/arch/x86/kernel/apic/es7000_32.c
+++ b/arch/x86/kernel/apic/es7000_32.c
@@ -678,6 +678,7 @@ static struct apic __refdata apic_es7000_cluster = {
.read = native_apic_mem_read,
.write = native_apic_mem_write,
+ .eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle,
@@ -742,6 +743,7 @@ static struct apic __refdata apic_es7000 = {
.read = native_apic_mem_read,
.write = native_apic_mem_write,
+ .eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle,
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 675e9045a3c5..ac96561d1a99 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -68,23 +68,21 @@
#define for_each_irq_pin(entry, head) \
for (entry = head; entry; entry = entry->next)
-static void __init __ioapic_init_mappings(void);
-
-static unsigned int __io_apic_read (unsigned int apic, unsigned int reg);
-static void __io_apic_write (unsigned int apic, unsigned int reg, unsigned int val);
-static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val);
-
-static struct io_apic_ops io_apic_ops = {
- .init = __ioapic_init_mappings,
- .read = __io_apic_read,
- .write = __io_apic_write,
- .modify = __io_apic_modify,
-};
-
-void __init set_io_apic_ops(const struct io_apic_ops *ops)
+#ifdef CONFIG_IRQ_REMAP
+static void irq_remap_modify_chip_defaults(struct irq_chip *chip);
+static inline bool irq_remapped(struct irq_cfg *cfg)
+{
+ return cfg->irq_2_iommu.iommu != NULL;
+}
+#else
+static inline bool irq_remapped(struct irq_cfg *cfg)
+{
+ return false;
+}
+static inline void irq_remap_modify_chip_defaults(struct irq_chip *chip)
{
- io_apic_ops = *ops;
}
+#endif
/*
* Is the SiS APIC rmw bug present ?
@@ -313,21 +311,6 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg)
irq_free_desc(at);
}
-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
-{
- return io_apic_ops.read(apic, reg);
-}
-
-static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
-{
- io_apic_ops.write(apic, reg, value);
-}
-
-static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
-{
- io_apic_ops.modify(apic, reg, value);
-}
-
struct io_apic {
unsigned int index;
@@ -349,14 +332,14 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
writel(vector, &io_apic->eoi);
}
-static unsigned int __io_apic_read(unsigned int apic, unsigned int reg)
+unsigned int native_io_apic_read(unsigned int apic, unsigned int reg)
{
struct io_apic __iomem *io_apic = io_apic_base(apic);
writel(reg, &io_apic->index);
return readl(&io_apic->data);
}
-static void __io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
+void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
{
struct io_apic __iomem *io_apic = io_apic_base(apic);
@@ -370,7 +353,7 @@ static void __io_apic_write(unsigned int apic, unsigned int reg, unsigned int va
*
* Older SiS APIC requires we rewrite the index register
*/
-static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
+void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
{
struct io_apic __iomem *io_apic = io_apic_base(apic);
@@ -379,29 +362,6 @@ static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int v
writel(value, &io_apic->data);
}
-static bool io_apic_level_ack_pending(struct irq_cfg *cfg)
-{
- struct irq_pin_list *entry;
- unsigned long flags;
-
- raw_spin_lock_irqsave(&ioapic_lock, flags);
- for_each_irq_pin(entry, cfg->irq_2_pin) {
- unsigned int reg;
- int pin;
-
- pin = entry->pin;
- reg = io_apic_read(entry->apic, 0x10 + pin*2);
- /* Is the remote IRR bit set? */
- if (reg & IO_APIC_REDIR_REMOTE_IRR) {
- raw_spin_unlock_irqrestore(&ioapic_lock, flags);
- return true;
- }
- }
- raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-
- return false;
-}
-
union entry_union {
struct { u32 w1, w2; };
struct IO_APIC_route_entry entry;
@@ -1350,77 +1310,13 @@ static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg,
fasteoi ? "fasteoi" : "edge");
}
-
-static int setup_ir_ioapic_entry(int irq,
- struct IR_IO_APIC_route_entry *entry,
- unsigned int destination, int vector,
- struct io_apic_irq_attr *attr)
-{
- int index;
- struct irte irte;
- int ioapic_id = mpc_ioapic_id(attr->ioapic);
- struct intel_iommu *iommu = map_ioapic_to_ir(ioapic_id);
-
- if (!iommu) {
- pr_warn("No mapping iommu for ioapic %d\n", ioapic_id);
- return -ENODEV;
- }
-
- index = alloc_irte(iommu, irq, 1);
- if (index < 0) {
- pr_warn("Failed to allocate IRTE for ioapic %d\n", ioapic_id);
- return -ENOMEM;
- }
-
- prepare_irte(&irte, vector, destination);
-
- /* Set source-id of interrupt request */
- set_ioapic_sid(&irte, ioapic_id);
-
- modify_irte(irq, &irte);
-
- apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
- "Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
- "Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X "
- "Avail:%X Vector:%02X Dest:%08X "
- "SID:%04X SQ:%X SVT:%X)\n",
- attr->ioapic, irte.present, irte.fpd, irte.dst_mode,
- irte.redir_hint, irte.trigger_mode, irte.dlvry_mode,
- irte.avail, irte.vector, irte.dest_id,
- irte.sid, irte.sq, irte.svt);
-
- memset(entry, 0, sizeof(*entry));
-
- entry->index2 = (index >> 15) & 0x1;
- entry->zero = 0;
- entry->format = 1;
- entry->index = (index & 0x7fff);
- /*
- * IO-APIC RTE will be configured with virtual vector.
- * irq handler will do the explicit EOI to the io-apic.
- */
- entry->vector = attr->ioapic_pin;
- entry->mask = 0; /* enable IRQ */
- entry->trigger = attr->trigger;
- entry->polarity = attr->polarity;
-
- /* Mask level triggered irqs.
- * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
- */
- if (attr->trigger)
- entry->mask = 1;
-
- return 0;
-}
-
static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
unsigned int destination, int vector,
struct io_apic_irq_attr *attr)
{
- if (intr_remapping_enabled)
- return setup_ir_ioapic_entry(irq,
- (struct IR_IO_APIC_route_entry *)entry,
- destination, vector, attr);
+ if (irq_remapping_enabled)
+ return setup_ioapic_remapped_entry(irq, entry, destination,
+ vector, attr);
memset(entry, 0, sizeof(*entry));
@@ -1577,7 +1473,7 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
{
struct IO_APIC_route_entry entry;
- if (intr_remapping_enabled)
+ if (irq_remapping_enabled)
return;
memset(&entry, 0, sizeof(entry));
@@ -1663,7 +1559,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx)
printk(KERN_DEBUG ".... IRQ redirection table:\n");
- if (intr_remapping_enabled) {
+ if (irq_remapping_enabled) {
printk(KERN_DEBUG " NR Indx Fmt Mask Trig IRR"
" Pol Stat Indx2 Zero Vect:\n");
} else {
@@ -1672,7 +1568,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx)
}
for (i = 0; i <= reg_01.bits.entries; i++) {
- if (intr_remapping_enabled) {
+ if (irq_remapping_enabled) {
struct IO_APIC_route_entry entry;
struct IR_IO_APIC_route_entry *ir_entry;
@@ -2039,7 +1935,7 @@ void disable_IO_APIC(void)
* IOAPIC RTE as well as interrupt-remapping table entry).
* As this gets called during crash dump, keep this simple for now.
*/
- if (ioapic_i8259.pin != -1 && !intr_remapping_enabled) {
+ if (ioapic_i8259.pin != -1 && !irq_remapping_enabled) {
struct IO_APIC_route_entry entry;
memset(&entry, 0, sizeof(entry));
@@ -2063,7 +1959,7 @@ void disable_IO_APIC(void)
* Use virtual wire A mode when interrupt remapping is enabled.
*/
if (cpu_has_apic || apic_from_smp_config())
- disconnect_bsp_APIC(!intr_remapping_enabled &&
+ disconnect_bsp_APIC(!irq_remapping_enabled &&
ioapic_i8259.pin != -1);
}
@@ -2379,71 +2275,6 @@ ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
return ret;
}
-#ifdef CONFIG_IRQ_REMAP
-
-/*
- * Migrate the IO-APIC irq in the presence of intr-remapping.
- *
- * For both level and edge triggered, irq migration is a simple atomic
- * update(of vector and cpu destination) of IRTE and flush the hardware cache.
- *
- * For level triggered, we eliminate the io-apic RTE modification (with the
- * updated vector information), by using a virtual vector (io-apic pin number).
- * Real vector that is used for interrupting cpu will be coming from
- * the interrupt-remapping table entry.
- *
- * As the migration is a simple atomic update of IRTE, the same mechanism
- * is used to migrate MSI irq's in the presence of interrupt-remapping.
- */
-static int
-ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
- bool force)
-{
- struct irq_cfg *cfg = data->chip_data;
- unsigned int dest, irq = data->irq;
- struct irte irte;
-
- if (!cpumask_intersects(mask, cpu_online_mask))
- return -EINVAL;
-
- if (get_irte(irq, &irte))
- return -EBUSY;
-
- if (assign_irq_vector(irq, cfg, mask))
- return -EBUSY;
-
- dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
-
- irte.vector = cfg->vector;
- irte.dest_id = IRTE_DEST(dest);
-
- /*
- * Atomically updates the IRTE with the new destination, vector
- * and flushes the interrupt entry cache.
- */
- modify_irte(irq, &irte);
-
- /*
- * After this point, all the interrupts will start arriving
- * at the new destination. So, time to cleanup the previous
- * vector allocation.
- */
- if (cfg->move_in_progress)
- send_cleanup_vector(cfg);
-
- cpumask_copy(data->affinity, mask);
- return 0;
-}
-
-#else
-static inline int
-ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
- bool force)
-{
- return 0;
-}
-#endif
-
asmlinkage void smp_irq_move_cleanup_interrupt(void)
{
unsigned vector, me;
@@ -2541,6 +2372,29 @@ static void ack_apic_edge(struct irq_data *data)
atomic_t irq_mis_count;
#ifdef CONFIG_GENERIC_PENDING_IRQ
+static bool io_apic_level_ack_pending(struct irq_cfg *cfg)
+{
+ struct irq_pin_list *entry;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&ioapic_lock, flags);
+ for_each_irq_pin(entry, cfg->irq_2_pin) {
+ unsigned int reg;
+ int pin;
+
+ pin = entry->pin;
+ reg = io_apic_read(entry->apic, 0x10 + pin*2);
+ /* Is the remote IRR bit set? */
+ if (reg & IO_APIC_REDIR_REMOTE_IRR) {
+ raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+ return true;
+ }
+ }
+ raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+
+ return false;
+}
+
static inline bool ioapic_irqd_mask(struct irq_data *data, struct irq_cfg *cfg)
{
/* If we are moving the irq we need to mask it */
@@ -2688,7 +2542,7 @@ static void irq_remap_modify_chip_defaults(struct irq_chip *chip)
chip->irq_eoi = ir_ack_apic_level;
#ifdef CONFIG_SMP
- chip->irq_set_affinity = ir_ioapic_set_affinity;
+ chip->irq_set_affinity = set_remapped_irq_affinity;
#endif
}
#endif /* CONFIG_IRQ_REMAP */
@@ -2901,7 +2755,7 @@ static inline void __init check_timer(void)
* 8259A.
*/
if (pin1 == -1) {
- if (intr_remapping_enabled)
+ if (irq_remapping_enabled)
panic("BIOS bug: timer not connected to IO-APIC");
pin1 = pin2;
apic1 = apic2;
@@ -2934,7 +2788,7 @@ static inline void __init check_timer(void)
clear_IO_APIC_pin(0, pin1);
goto out;
}
- if (intr_remapping_enabled)
+ if (irq_remapping_enabled)
panic("timer doesn't work through Interrupt-remapped IO-APIC");
local_irq_disable();
clear_IO_APIC_pin(apic1, pin1);
@@ -3158,7 +3012,7 @@ void destroy_irq(unsigned int irq)
irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE);
if (irq_remapped(cfg))
- free_irte(irq);
+ free_remapped_irq(irq);
raw_spin_lock_irqsave(&vector_lock, flags);
__clear_irq_vector(irq, cfg);
raw_spin_unlock_irqrestore(&vector_lock, flags);
@@ -3187,54 +3041,34 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
if (irq_remapped(cfg)) {
- struct irte irte;
- int ir_index;
- u16 sub_handle;
-
- ir_index = map_irq_to_irte_handle(irq, &sub_handle);
- BUG_ON(ir_index == -1);
-
- prepare_irte(&irte, cfg->vector, dest);
-
- /* Set source-id of interrupt request */
- if (pdev)
- set_msi_sid(&irte, pdev);
- else
- set_hpet_sid(&irte, hpet_id);
-
- modify_irte(irq, &irte);
+ compose_remapped_msi_msg(pdev, irq, dest, msg, hpet_id);
+ return err;
+ }
+ if (x2apic_enabled())
+ msg->address_hi = MSI_ADDR_BASE_HI |
+ MSI_ADDR_EXT_DEST_ID(dest);
+ else
msg->address_hi = MSI_ADDR_BASE_HI;
- msg->data = sub_handle;
- msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
- MSI_ADDR_IR_SHV |
- MSI_ADDR_IR_INDEX1(ir_index) |
- MSI_ADDR_IR_INDEX2(ir_index);
- } else {
- if (x2apic_enabled())
- msg->address_hi = MSI_ADDR_BASE_HI |
- MSI_ADDR_EXT_DEST_ID(dest);
- else
- msg->address_hi = MSI_ADDR_BASE_HI;
- msg->address_lo =
- MSI_ADDR_BASE_LO |
- ((apic->irq_dest_mode == 0) ?
- MSI_ADDR_DEST_MODE_PHYSICAL:
- MSI_ADDR_DEST_MODE_LOGICAL) |
- ((apic->irq_delivery_mode != dest_LowestPrio) ?
- MSI_ADDR_REDIRECTION_CPU:
- MSI_ADDR_REDIRECTION_LOWPRI) |
- MSI_ADDR_DEST_ID(dest);
+ msg->address_lo =
+ MSI_ADDR_BASE_LO |
+ ((apic->irq_dest_mode == 0) ?
+ MSI_ADDR_DEST_MODE_PHYSICAL:
+ MSI_ADDR_DEST_MODE_LOGICAL) |
+ ((apic->irq_delivery_mode != dest_LowestPrio) ?
+ MSI_ADDR_REDIRECTION_CPU:
+ MSI_ADDR_REDIRECTION_LOWPRI) |
+ MSI_ADDR_DEST_ID(dest);
+
+ msg->data =
+ MSI_DATA_TRIGGER_EDGE |
+ MSI_DATA_LEVEL_ASSERT |
+ ((apic->irq_delivery_mode != dest_LowestPrio) ?
+ MSI_DATA_DELIVERY_FIXED:
+ MSI_DATA_DELIVERY_LOWPRI) |
+ MSI_DATA_VECTOR(cfg->vector);
- msg->data =
- MSI_DATA_TRIGGER_EDGE |
- MSI_DATA_LEVEL_ASSERT |
- ((apic->irq_delivery_mode != dest_LowestPrio) ?
- MSI_DATA_DELIVERY_FIXED:
- MSI_DATA_DELIVERY_LOWPRI) |
- MSI_DATA_VECTOR(cfg->vector);
- }
return err;
}
@@ -3277,33 +3111,6 @@ static struct irq_chip msi_chip = {
.irq_retrigger = ioapic_retrigger_irq,
};
-/*
- * Map the PCI dev to the corresponding remapping hardware unit
- * and allocate 'nvec' consecutive interrupt-remapping table entries
- * in it.
- */
-static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
-{
- struct intel_iommu *iommu;
- int index;
-
- iommu = map_dev_to_ir(dev);
- if (!iommu) {
- printk(KERN_ERR
- "Unable to map PCI %s to iommu\n", pci_name(dev));
- return -ENOENT;
- }
-
- index = alloc_irte(iommu, irq, nvec);
- if (index < 0) {
- printk(KERN_ERR
- "Unable to allocate %d IRTE for PCI %s\n", nvec,
- pci_name(dev));
- return -ENOSPC;
- }
- return index;
-}
-
static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
{
struct irq_chip *chip = &msi_chip;
@@ -3334,7 +3141,6 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
int node, ret, sub_handle, index = 0;
unsigned int irq, irq_want;
struct msi_desc *msidesc;
- struct intel_iommu *iommu = NULL;
/* x86 doesn't support multiple MSI yet */
if (type == PCI_CAP_ID_MSI && nvec > 1)
@@ -3348,7 +3154,7 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
if (irq == 0)
return -1;
irq_want = irq + 1;
- if (!intr_remapping_enabled)
+ if (!irq_remapping_enabled)
goto no_ir;
if (!sub_handle) {
@@ -3356,23 +3162,16 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
* allocate the consecutive block of IRTE's
* for 'nvec'
*/
- index = msi_alloc_irte(dev, irq, nvec);
+ index = msi_alloc_remapped_irq(dev, irq, nvec);
if (index < 0) {
ret = index;
goto error;
}
} else {
- iommu = map_dev_to_ir(dev);
- if (!iommu) {
- ret = -ENOENT;
+ ret = msi_setup_remapped_irq(dev, irq, index,
+ sub_handle);
+ if (ret < 0)
goto error;
- }
- /*
- * setup the mapping between the irq and the IRTE
- * base index, the sub_handle pointing to the
- * appropriate interrupt remap table entry.
- */
- set_irte_irq(irq, iommu, index, sub_handle);
}
no_ir:
ret = setup_msi_irq(dev, msidesc, irq);
@@ -3490,15 +3289,8 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
struct msi_msg msg;
int ret;
- if (intr_remapping_enabled) {
- struct intel_iommu *iommu = map_hpet_to_ir(id);
- int index;
-
- if (!iommu)
- return -1;
-
- index = alloc_irte(iommu, irq, 1);
- if (index < 0)
+ if (irq_remapping_enabled) {
+ if (!setup_hpet_msi_remapped(irq, id))
return -1;
}
@@ -3877,8 +3669,8 @@ void __init setup_ioapic_dest(void)
else
mask = apic->target_cpus();
- if (intr_remapping_enabled)
- ir_ioapic_set_affinity(idata, mask, false);
+ if (irq_remapping_enabled)
+ set_remapped_irq_affinity(idata, mask, false);
else
ioapic_set_affinity(idata, mask, false);
}
@@ -3920,12 +3712,7 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics)
return res;
}
-void __init ioapic_and_gsi_init(void)
-{
- io_apic_ops.init();
-}
-
-static void __init __ioapic_init_mappings(void)
+void __init native_io_apic_init_mappings(void)
{
unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
struct resource *ioapic_res;
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c
index 00d2422ca7c9..f00a68cca37a 100644
--- a/arch/x86/kernel/apic/numaq_32.c
+++ b/arch/x86/kernel/apic/numaq_32.c
@@ -530,6 +530,7 @@ static struct apic __refdata apic_numaq = {
.read = native_apic_mem_read,
.write = native_apic_mem_write,
+ .eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle,
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c
index ff2c1b9aac4d..1b291da09e60 100644
--- a/arch/x86/kernel/apic/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -142,6 +142,7 @@ static struct apic apic_default = {
.read = native_apic_mem_read,
.write = native_apic_mem_write,
+ .eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle,
diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c
index fea000b27f07..659897c00755 100644
--- a/arch/x86/kernel/apic/summit_32.c
+++ b/arch/x86/kernel/apic/summit_32.c
@@ -546,6 +546,7 @@ static struct apic apic_summit = {
.read = native_apic_mem_read,
.write = native_apic_mem_write,
+ .eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle,
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c
index 48f3103b3c93..ff35cff0e1a7 100644
--- a/arch/x86/kernel/apic/x2apic_cluster.c
+++ b/arch/x86/kernel/apic/x2apic_cluster.c
@@ -260,6 +260,7 @@ static struct apic apic_x2apic_cluster = {
.read = native_apic_msr_read,
.write = native_apic_msr_write,
+ .eoi_write = native_apic_msr_eoi_write,
.icr_read = native_x2apic_icr_read,
.icr_write = native_x2apic_icr_write,
.wait_icr_idle = native_x2apic_wait_icr_idle,
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 991e315f4227..c17e982db275 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -172,6 +172,7 @@ static struct apic apic_x2apic_phys = {
.read = native_apic_msr_read,
.write = native_apic_msr_write,
+ .eoi_write = native_apic_msr_eoi_write,
.icr_read = native_x2apic_icr_read,
.icr_write = native_x2apic_icr_write,
.wait_icr_idle = native_x2apic_wait_icr_idle,
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 87bfa69e216e..c6d03f7a4401 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -404,6 +404,7 @@ static struct apic __refdata apic_x2apic_uv_x = {
.read = native_apic_msr_read,
.write = native_apic_msr_write,
+ .eoi_write = native_apic_msr_eoi_write,
.icr_read = native_x2apic_icr_read,
.icr_write = native_x2apic_icr_write,
.wait_icr_idle = native_x2apic_wait_icr_idle,
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 459e78cbf61e..07b0c0db466c 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -2401,7 +2401,7 @@ static void __exit apm_exit(void)
* (pm_idle), Wait for all processors to update cached/local
* copies of pm_idle before proceeding.
*/
- cpu_idle_wait();
+ kick_all_cpus_sync();
}
if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
&& (apm_info.connection_version > 0x0100)) {
diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c
index 5da1269e8ddc..e2dbcb7dabdd 100644
--- a/arch/x86/kernel/check.c
+++ b/arch/x86/kernel/check.c
@@ -27,21 +27,29 @@ static int num_scan_areas;
static __init int set_corruption_check(char *arg)
{
- char *end;
+ ssize_t ret;
+ unsigned long val;
- memory_corruption_check = simple_strtol(arg, &end, 10);
+ ret = kstrtoul(arg, 10, &val);
+ if (ret)
+ return ret;
- return (*end == 0) ? 0 : -EINVAL;
+ memory_corruption_check = val;
+ return 0;
}
early_param("memory_corruption_check", set_corruption_check);
static __init int set_corruption_check_period(char *arg)
{
- char *end;
+ ssize_t ret;
+ unsigned long val;
- corruption_check_period = simple_strtoul(arg, &end, 10);
+ ret = kstrtoul(arg, 10, &val);
+ if (ret)
+ return ret;
- return (*end == 0) ? 0 : -EINVAL;
+ corruption_check_period = val;
+ return 0;
}
early_param("memory_corruption_check_period", set_corruption_check_period);
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index cf79302198a6..82f29e70d058 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1185,7 +1185,7 @@ void __cpuinit cpu_init(void)
oist = &per_cpu(orig_ist, cpu);
#ifdef CONFIG_NUMA
- if (cpu != 0 && percpu_read(numa_node) == 0 &&
+ if (cpu != 0 && this_cpu_read(numa_node) == 0 &&
early_cpu_to_node(cpu) != NUMA_NO_NODE)
set_numa_node(early_cpu_to_node(cpu));
#endif
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index b8f3653dddbc..9a7c90d80bc4 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -615,14 +615,14 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
new_l2 = this_leaf.size/1024;
num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
index_msb = get_count_order(num_threads_sharing);
- l2_id = c->apicid >> index_msb;
+ l2_id = c->apicid & ~((1 << index_msb) - 1);
break;
case 3:
new_l3 = this_leaf.size/1024;
num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
index_msb = get_count_order(
num_threads_sharing);
- l3_id = c->apicid >> index_msb;
+ l3_id = c->apicid & ~((1 << index_msb) - 1);
break;
default:
break;
diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c
index 5502b289341b..36565373af87 100644
--- a/arch/x86/kernel/cpu/match.c
+++ b/arch/x86/kernel/cpu/match.c
@@ -23,7 +23,7 @@
* %X86_MODEL_ANY, %X86_FEATURE_ANY or 0 (except for vendor)
*
* Arrays used to match for this should also be declared using
- * MODULE_DEVICE_TABLE(x86_cpu, ...)
+ * MODULE_DEVICE_TABLE(x86cpu, ...)
*
* This always matches against the boot cpu, assuming models and features are
* consistent over all CPUs.
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index d086a09c087d..2afcbd253e1d 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -583,7 +583,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
struct mce m;
int i;
- percpu_inc(mce_poll_count);
+ this_cpu_inc(mce_poll_count);
mce_gather_info(&m, NULL);
@@ -945,9 +945,10 @@ struct mce_info {
atomic_t inuse;
struct task_struct *t;
__u64 paddr;
+ int restartable;
} mce_info[MCE_INFO_MAX];
-static void mce_save_info(__u64 addr)
+static void mce_save_info(__u64 addr, int c)
{
struct mce_info *mi;
@@ -955,6 +956,7 @@ static void mce_save_info(__u64 addr)
if (atomic_cmpxchg(&mi->inuse, 0, 1) == 0) {
mi->t = current;
mi->paddr = addr;
+ mi->restartable = c;
return;
}
}
@@ -1015,7 +1017,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
atomic_inc(&mce_entry);
- percpu_inc(mce_exception_count);
+ this_cpu_inc(mce_exception_count);
if (!banks)
goto out;
@@ -1130,7 +1132,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
mce_panic("Fatal machine check on current CPU", &m, msg);
if (worst == MCE_AR_SEVERITY) {
/* schedule action before return to userland */
- mce_save_info(m.addr);
+ mce_save_info(m.addr, m.mcgstatus & MCG_STATUS_RIPV);
set_thread_flag(TIF_MCE_NOTIFY);
} else if (kill_it) {
force_sig(SIGBUS, current);
@@ -1179,7 +1181,13 @@ void mce_notify_process(void)
pr_err("Uncorrected hardware memory error in user-access at %llx",
mi->paddr);
- if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0) {
+ /*
+ * We must call memory_failure() here even if the current process is
+ * doomed. We still need to mark the page as poisoned and alert any
+ * other users of the page.
+ */
+ if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0 ||
+ mi->restartable == 0) {
pr_err("Memory error not recovered");
force_sig(SIGBUS, current);
}
@@ -1423,6 +1431,43 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
*/
if (c->x86 == 6 && banks > 0)
mce_banks[0].ctl = 0;
+
+ /*
+ * Turn off MC4_MISC thresholding banks on those models since
+ * they're not supported there.
+ */
+ if (c->x86 == 0x15 &&
+ (c->x86_model >= 0x10 && c->x86_model <= 0x1f)) {
+ int i;
+ u64 val, hwcr;
+ bool need_toggle;
+ u32 msrs[] = {
+ 0x00000413, /* MC4_MISC0 */
+ 0xc0000408, /* MC4_MISC1 */
+ };
+
+ rdmsrl(MSR_K7_HWCR, hwcr);
+
+ /* McStatusWrEn has to be set */
+ need_toggle = !(hwcr & BIT(18));
+
+ if (need_toggle)
+ wrmsrl(MSR_K7_HWCR, hwcr | BIT(18));
+
+ for (i = 0; i < ARRAY_SIZE(msrs); i++) {
+ rdmsrl(msrs[i], val);
+
+ /* CntP bit set? */
+ if (val & BIT(62)) {
+ val &= ~BIT(62);
+ wrmsrl(msrs[i], val);
+ }
+ }
+
+ /* restore old settings */
+ if (need_toggle)
+ wrmsrl(MSR_K7_HWCR, hwcr);
+ }
}
if (c->x86_vendor == X86_VENDOR_INTEL) {
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 99b57179f912..f4873a64f46d 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -51,6 +51,7 @@ struct threshold_block {
unsigned int cpu;
u32 address;
u16 interrupt_enable;
+ bool interrupt_capable;
u16 threshold_limit;
struct kobject kobj;
struct list_head miscj;
@@ -83,6 +84,21 @@ struct thresh_restart {
u16 old_limit;
};
+static bool lvt_interrupt_supported(unsigned int bank, u32 msr_high_bits)
+{
+ /*
+ * bank 4 supports APIC LVT interrupts implicitly since forever.
+ */
+ if (bank == 4)
+ return true;
+
+ /*
+ * IntP: interrupt present; if this bit is set, the thresholding
+ * bank can generate APIC LVT interrupts
+ */
+ return msr_high_bits & BIT(28);
+}
+
static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi)
{
int msr = (hi & MASK_LVTOFF_HI) >> 20;
@@ -104,8 +120,10 @@ static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi)
return 1;
};
-/* must be called with correct cpu affinity */
-/* Called via smp_call_function_single() */
+/*
+ * Called via smp_call_function_single(), must be called with correct
+ * cpu affinity.
+ */
static void threshold_restart_bank(void *_tr)
{
struct thresh_restart *tr = _tr;
@@ -128,6 +146,12 @@ static void threshold_restart_bank(void *_tr)
(new_count & THRESHOLD_MAX);
}
+ /* clear IntType */
+ hi &= ~MASK_INT_TYPE_HI;
+
+ if (!tr->b->interrupt_capable)
+ goto done;
+
if (tr->set_lvt_off) {
if (lvt_off_valid(tr->b, tr->lvt_off, lo, hi)) {
/* set new lvt offset */
@@ -136,9 +160,10 @@ static void threshold_restart_bank(void *_tr)
}
}
- tr->b->interrupt_enable ?
- (hi = (hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) :
- (hi &= ~MASK_INT_TYPE_HI);
+ if (tr->b->interrupt_enable)
+ hi |= INT_TYPE_APIC;
+
+ done:
hi |= MASK_COUNT_EN_HI;
wrmsr(tr->b->address, lo, hi);
@@ -202,14 +227,17 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
if (shared_bank[bank] && c->cpu_core_id)
break;
- offset = setup_APIC_mce(offset,
- (high & MASK_LVTOFF_HI) >> 20);
-
memset(&b, 0, sizeof(b));
- b.cpu = cpu;
- b.bank = bank;
- b.block = block;
- b.address = address;
+ b.cpu = cpu;
+ b.bank = bank;
+ b.block = block;
+ b.address = address;
+ b.interrupt_capable = lvt_interrupt_supported(bank, high);
+
+ if (b.interrupt_capable) {
+ int new = (high & MASK_LVTOFF_HI) >> 20;
+ offset = setup_APIC_mce(offset, new);
+ }
mce_threshold_block_init(&b, offset);
mce_threshold_vector = amd_threshold_interrupt;
@@ -309,6 +337,9 @@ store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size)
struct thresh_restart tr;
unsigned long new;
+ if (!b->interrupt_capable)
+ return -EINVAL;
+
if (strict_strtoul(buf, 0, &new) < 0)
return -EINVAL;
@@ -390,10 +421,10 @@ RW_ATTR(threshold_limit);
RW_ATTR(error_count);
static struct attribute *default_attrs[] = {
- &interrupt_enable.attr,
&threshold_limit.attr,
&error_count.attr,
- NULL
+ NULL, /* possibly interrupt_enable if supported, see below */
+ NULL,
};
#define to_block(k) container_of(k, struct threshold_block, kobj)
@@ -467,8 +498,14 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
b->cpu = cpu;
b->address = address;
b->interrupt_enable = 0;
+ b->interrupt_capable = lvt_interrupt_supported(bank, high);
b->threshold_limit = THRESHOLD_MAX;
+ if (b->interrupt_capable)
+ threshold_ktype.default_attrs[2] = &interrupt_enable.attr;
+ else
+ threshold_ktype.default_attrs[2] = NULL;
+
INIT_LIST_HEAD(&b->miscj);
if (per_cpu(threshold_banks, cpu)[bank]->blocks) {
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index bb8e03407e18..e049d6da0183 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -484,9 +484,6 @@ static int __x86_pmu_event_init(struct perf_event *event)
/* mark unused */
event->hw.extra_reg.idx = EXTRA_REG_NONE;
-
- /* mark not used */
- event->hw.extra_reg.idx = EXTRA_REG_NONE;
event->hw.branch_reg.idx = EXTRA_REG_NONE;
return x86_pmu.hw_config(event);
@@ -1186,8 +1183,6 @@ int x86_pmu_handle_irq(struct pt_regs *regs)
int idx, handled = 0;
u64 val;
- perf_sample_data_init(&data, 0);
-
cpuc = &__get_cpu_var(cpu_hw_events);
/*
@@ -1222,7 +1217,7 @@ int x86_pmu_handle_irq(struct pt_regs *regs)
* event overflow
*/
handled++;
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, 0, event->hw.last_period);
if (!x86_perf_event_set_period(event))
continue;
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index 95e7fe1c5f0b..11a4eb9131d5 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -134,8 +134,13 @@ static u64 amd_pmu_event_map(int hw_event)
static int amd_pmu_hw_config(struct perf_event *event)
{
- int ret = x86_pmu_hw_config(event);
+ int ret;
+ /* pass precise event sampling to ibs: */
+ if (event->attr.precise_ip && get_ibs_caps())
+ return -ENOENT;
+
+ ret = x86_pmu_hw_config(event);
if (ret)
return ret;
@@ -205,10 +210,8 @@ static void amd_put_event_constraints(struct cpu_hw_events *cpuc,
* when we come here
*/
for (i = 0; i < x86_pmu.num_counters; i++) {
- if (nb->owners[i] == event) {
- cmpxchg(nb->owners+i, event, NULL);
+ if (cmpxchg(nb->owners + i, event, NULL) == event)
break;
- }
}
}
@@ -493,6 +496,7 @@ static __initconst const struct x86_pmu amd_pmu = {
* 0x023 DE PERF_CTL[2:0]
* 0x02D LS PERF_CTL[3]
* 0x02E LS PERF_CTL[3,0]
+ * 0x031 LS PERF_CTL[2:0] (**)
* 0x043 CU PERF_CTL[2:0]
* 0x045 CU PERF_CTL[2:0]
* 0x046 CU PERF_CTL[2:0]
@@ -506,10 +510,12 @@ static __initconst const struct x86_pmu amd_pmu = {
* 0x0DD LS PERF_CTL[5:0]
* 0x0DE LS PERF_CTL[5:0]
* 0x0DF LS PERF_CTL[5:0]
+ * 0x1C0 EX PERF_CTL[5:3]
* 0x1D6 EX PERF_CTL[5:0]
* 0x1D8 EX PERF_CTL[5:0]
*
- * (*) depending on the umask all FPU counters may be used
+ * (*) depending on the umask all FPU counters may be used
+ * (**) only one unitmask enabled at a time
*/
static struct event_constraint amd_f15_PMC0 = EVENT_CONSTRAINT(0, 0x01, 0);
@@ -559,6 +565,12 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *ev
return &amd_f15_PMC3;
case 0x02E:
return &amd_f15_PMC30;
+ case 0x031:
+ if (hweight_long(hwc->config & ARCH_PERFMON_EVENTSEL_UMASK) <= 1)
+ return &amd_f15_PMC20;
+ return &emptyconstraint;
+ case 0x1C0:
+ return &amd_f15_PMC53;
default:
return &amd_f15_PMC50;
}
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
index 3b8a2d30d14e..da9bcdcd9856 100644
--- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c
+++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
@@ -9,6 +9,7 @@
#include <linux/perf_event.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/ptrace.h>
#include <asm/apic.h>
@@ -16,36 +17,591 @@ static u32 ibs_caps;
#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD)
-static struct pmu perf_ibs;
+#include <linux/kprobes.h>
+#include <linux/hardirq.h>
+
+#include <asm/nmi.h>
+
+#define IBS_FETCH_CONFIG_MASK (IBS_FETCH_RAND_EN | IBS_FETCH_MAX_CNT)
+#define IBS_OP_CONFIG_MASK IBS_OP_MAX_CNT
+
+enum ibs_states {
+ IBS_ENABLED = 0,
+ IBS_STARTED = 1,
+ IBS_STOPPING = 2,
+
+ IBS_MAX_STATES,
+};
+
+struct cpu_perf_ibs {
+ struct perf_event *event;
+ unsigned long state[BITS_TO_LONGS(IBS_MAX_STATES)];
+};
+
+struct perf_ibs {
+ struct pmu pmu;
+ unsigned int msr;
+ u64 config_mask;
+ u64 cnt_mask;
+ u64 enable_mask;
+ u64 valid_mask;
+ u64 max_period;
+ unsigned long offset_mask[1];
+ int offset_max;
+ struct cpu_perf_ibs __percpu *pcpu;
+ u64 (*get_count)(u64 config);
+};
+
+struct perf_ibs_data {
+ u32 size;
+ union {
+ u32 data[0]; /* data buffer starts here */
+ u32 caps;
+ };
+ u64 regs[MSR_AMD64_IBS_REG_COUNT_MAX];
+};
+
+static int
+perf_event_set_period(struct hw_perf_event *hwc, u64 min, u64 max, u64 *hw_period)
+{
+ s64 left = local64_read(&hwc->period_left);
+ s64 period = hwc->sample_period;
+ int overflow = 0;
+
+ /*
+ * If we are way outside a reasonable range then just skip forward:
+ */
+ if (unlikely(left <= -period)) {
+ left = period;
+ local64_set(&hwc->period_left, left);
+ hwc->last_period = period;
+ overflow = 1;
+ }
+
+ if (unlikely(left < (s64)min)) {
+ left += period;
+ local64_set(&hwc->period_left, left);
+ hwc->last_period = period;
+ overflow = 1;
+ }
+
+ /*
+ * If the hw period that triggers the sw overflow is too short
+ * we might hit the irq handler. This biases the results.
+ * Thus we shorten the next-to-last period and set the last
+ * period to the max period.
+ */
+ if (left > max) {
+ left -= max;
+ if (left > max)
+ left = max;
+ else if (left < min)
+ left = min;
+ }
+
+ *hw_period = (u64)left;
+
+ return overflow;
+}
+
+static int
+perf_event_try_update(struct perf_event *event, u64 new_raw_count, int width)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int shift = 64 - width;
+ u64 prev_raw_count;
+ u64 delta;
+
+ /*
+ * Careful: an NMI might modify the previous event value.
+ *
+ * Our tactic to handle this is to first atomically read and
+ * exchange a new raw count - then add that new-prev delta
+ * count to the generic event atomically:
+ */
+ prev_raw_count = local64_read(&hwc->prev_count);
+ if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+ new_raw_count) != prev_raw_count)
+ return 0;
+
+ /*
+ * Now we have the new raw value and have updated the prev
+ * timestamp already. We can now calculate the elapsed delta
+ * (event-)time and add that to the generic event.
+ *
+ * Careful, not all hw sign-extends above the physical width
+ * of the count.
+ */
+ delta = (new_raw_count << shift) - (prev_raw_count << shift);
+ delta >>= shift;
+
+ local64_add(delta, &event->count);
+ local64_sub(delta, &hwc->period_left);
+
+ return 1;
+}
+
+static struct perf_ibs perf_ibs_fetch;
+static struct perf_ibs perf_ibs_op;
+
+static struct perf_ibs *get_ibs_pmu(int type)
+{
+ if (perf_ibs_fetch.pmu.type == type)
+ return &perf_ibs_fetch;
+ if (perf_ibs_op.pmu.type == type)
+ return &perf_ibs_op;
+ return NULL;
+}
+
+/*
+ * Use IBS for precise event sampling:
+ *
+ * perf record -a -e cpu-cycles:p ... # use ibs op counting cycle count
+ * perf record -a -e r076:p ... # same as -e cpu-cycles:p
+ * perf record -a -e r0C1:p ... # use ibs op counting micro-ops
+ *
+ * IbsOpCntCtl (bit 19) of IBS Execution Control Register (IbsOpCtl,
+ * MSRC001_1033) is used to select either cycle or micro-ops counting
+ * mode.
+ *
+ * The rip of IBS samples has skid 0. Thus, IBS supports precise
+ * levels 1 and 2 and the PERF_EFLAGS_EXACT is set. In rare cases the
+ * rip is invalid when IBS was not able to record the rip correctly.
+ * We clear PERF_EFLAGS_EXACT and take the rip from pt_regs then.
+ *
+ */
+static int perf_ibs_precise_event(struct perf_event *event, u64 *config)
+{
+ switch (event->attr.precise_ip) {
+ case 0:
+ return -ENOENT;
+ case 1:
+ case 2:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ switch (event->attr.type) {
+ case PERF_TYPE_HARDWARE:
+ switch (event->attr.config) {
+ case PERF_COUNT_HW_CPU_CYCLES:
+ *config = 0;
+ return 0;
+ }
+ break;
+ case PERF_TYPE_RAW:
+ switch (event->attr.config) {
+ case 0x0076:
+ *config = 0;
+ return 0;
+ case 0x00C1:
+ *config = IBS_OP_CNT_CTL;
+ return 0;
+ }
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return -EOPNOTSUPP;
+}
static int perf_ibs_init(struct perf_event *event)
{
- if (perf_ibs.type != event->attr.type)
+ struct hw_perf_event *hwc = &event->hw;
+ struct perf_ibs *perf_ibs;
+ u64 max_cnt, config;
+ int ret;
+
+ perf_ibs = get_ibs_pmu(event->attr.type);
+ if (perf_ibs) {
+ config = event->attr.config;
+ } else {
+ perf_ibs = &perf_ibs_op;
+ ret = perf_ibs_precise_event(event, &config);
+ if (ret)
+ return ret;
+ }
+
+ if (event->pmu != &perf_ibs->pmu)
return -ENOENT;
+
+ if (config & ~perf_ibs->config_mask)
+ return -EINVAL;
+
+ if (hwc->sample_period) {
+ if (config & perf_ibs->cnt_mask)
+ /* raw max_cnt may not be set */
+ return -EINVAL;
+ if (!event->attr.sample_freq && hwc->sample_period & 0x0f)
+ /*
+ * lower 4 bits can not be set in ibs max cnt,
+ * but allowing it in case we adjust the
+ * sample period to set a frequency.
+ */
+ return -EINVAL;
+ hwc->sample_period &= ~0x0FULL;
+ if (!hwc->sample_period)
+ hwc->sample_period = 0x10;
+ } else {
+ max_cnt = config & perf_ibs->cnt_mask;
+ config &= ~perf_ibs->cnt_mask;
+ event->attr.sample_period = max_cnt << 4;
+ hwc->sample_period = event->attr.sample_period;
+ }
+
+ if (!hwc->sample_period)
+ return -EINVAL;
+
+ /*
+ * If we modify hwc->sample_period, we also need to update
+ * hwc->last_period and hwc->period_left.
+ */
+ hwc->last_period = hwc->sample_period;
+ local64_set(&hwc->period_left, hwc->sample_period);
+
+ hwc->config_base = perf_ibs->msr;
+ hwc->config = config;
+
return 0;
}
+static int perf_ibs_set_period(struct perf_ibs *perf_ibs,
+ struct hw_perf_event *hwc, u64 *period)
+{
+ int overflow;
+
+ /* ignore lower 4 bits in min count: */
+ overflow = perf_event_set_period(hwc, 1<<4, perf_ibs->max_period, period);
+ local64_set(&hwc->prev_count, 0);
+
+ return overflow;
+}
+
+static u64 get_ibs_fetch_count(u64 config)
+{
+ return (config & IBS_FETCH_CNT) >> 12;
+}
+
+static u64 get_ibs_op_count(u64 config)
+{
+ u64 count = 0;
+
+ if (config & IBS_OP_VAL)
+ count += (config & IBS_OP_MAX_CNT) << 4; /* cnt rolled over */
+
+ if (ibs_caps & IBS_CAPS_RDWROPCNT)
+ count += (config & IBS_OP_CUR_CNT) >> 32;
+
+ return count;
+}
+
+static void
+perf_ibs_event_update(struct perf_ibs *perf_ibs, struct perf_event *event,
+ u64 *config)
+{
+ u64 count = perf_ibs->get_count(*config);
+
+ /*
+ * Set width to 64 since we do not overflow on max width but
+ * instead on max count. In perf_ibs_set_period() we clear
+ * prev count manually on overflow.
+ */
+ while (!perf_event_try_update(event, count, 64)) {
+ rdmsrl(event->hw.config_base, *config);
+ count = perf_ibs->get_count(*config);
+ }
+}
+
+static inline void perf_ibs_enable_event(struct perf_ibs *perf_ibs,
+ struct hw_perf_event *hwc, u64 config)
+{
+ wrmsrl(hwc->config_base, hwc->config | config | perf_ibs->enable_mask);
+}
+
+/*
+ * Erratum #420 Instruction-Based Sampling Engine May Generate
+ * Interrupt that Cannot Be Cleared:
+ *
+ * Must clear counter mask first, then clear the enable bit. See
+ * Revision Guide for AMD Family 10h Processors, Publication #41322.
+ */
+static inline void perf_ibs_disable_event(struct perf_ibs *perf_ibs,
+ struct hw_perf_event *hwc, u64 config)
+{
+ config &= ~perf_ibs->cnt_mask;
+ wrmsrl(hwc->config_base, config);
+ config &= ~perf_ibs->enable_mask;
+ wrmsrl(hwc->config_base, config);
+}
+
+/*
+ * We cannot restore the ibs pmu state, so we always needs to update
+ * the event while stopping it and then reset the state when starting
+ * again. Thus, ignoring PERF_EF_RELOAD and PERF_EF_UPDATE flags in
+ * perf_ibs_start()/perf_ibs_stop() and instead always do it.
+ */
+static void perf_ibs_start(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
+ struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+ u64 period;
+
+ if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
+ return;
+
+ WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+ hwc->state = 0;
+
+ perf_ibs_set_period(perf_ibs, hwc, &period);
+ set_bit(IBS_STARTED, pcpu->state);
+ perf_ibs_enable_event(perf_ibs, hwc, period >> 4);
+
+ perf_event_update_userpage(event);
+}
+
+static void perf_ibs_stop(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
+ struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+ u64 config;
+ int stopping;
+
+ stopping = test_and_clear_bit(IBS_STARTED, pcpu->state);
+
+ if (!stopping && (hwc->state & PERF_HES_UPTODATE))
+ return;
+
+ rdmsrl(hwc->config_base, config);
+
+ if (stopping) {
+ set_bit(IBS_STOPPING, pcpu->state);
+ perf_ibs_disable_event(perf_ibs, hwc, config);
+ WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+ hwc->state |= PERF_HES_STOPPED;
+ }
+
+ if (hwc->state & PERF_HES_UPTODATE)
+ return;
+
+ /*
+ * Clear valid bit to not count rollovers on update, rollovers
+ * are only updated in the irq handler.
+ */
+ config &= ~perf_ibs->valid_mask;
+
+ perf_ibs_event_update(perf_ibs, event, &config);
+ hwc->state |= PERF_HES_UPTODATE;
+}
+
static int perf_ibs_add(struct perf_event *event, int flags)
{
+ struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
+ struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+
+ if (test_and_set_bit(IBS_ENABLED, pcpu->state))
+ return -ENOSPC;
+
+ event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+ pcpu->event = event;
+
+ if (flags & PERF_EF_START)
+ perf_ibs_start(event, PERF_EF_RELOAD);
+
return 0;
}
static void perf_ibs_del(struct perf_event *event, int flags)
{
+ struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
+ struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+
+ if (!test_and_clear_bit(IBS_ENABLED, pcpu->state))
+ return;
+
+ perf_ibs_stop(event, PERF_EF_UPDATE);
+
+ pcpu->event = NULL;
+
+ perf_event_update_userpage(event);
}
-static struct pmu perf_ibs = {
- .event_init= perf_ibs_init,
- .add= perf_ibs_add,
- .del= perf_ibs_del,
+static void perf_ibs_read(struct perf_event *event) { }
+
+static struct perf_ibs perf_ibs_fetch = {
+ .pmu = {
+ .task_ctx_nr = perf_invalid_context,
+
+ .event_init = perf_ibs_init,
+ .add = perf_ibs_add,
+ .del = perf_ibs_del,
+ .start = perf_ibs_start,
+ .stop = perf_ibs_stop,
+ .read = perf_ibs_read,
+ },
+ .msr = MSR_AMD64_IBSFETCHCTL,
+ .config_mask = IBS_FETCH_CONFIG_MASK,
+ .cnt_mask = IBS_FETCH_MAX_CNT,
+ .enable_mask = IBS_FETCH_ENABLE,
+ .valid_mask = IBS_FETCH_VAL,
+ .max_period = IBS_FETCH_MAX_CNT << 4,
+ .offset_mask = { MSR_AMD64_IBSFETCH_REG_MASK },
+ .offset_max = MSR_AMD64_IBSFETCH_REG_COUNT,
+
+ .get_count = get_ibs_fetch_count,
};
+static struct perf_ibs perf_ibs_op = {
+ .pmu = {
+ .task_ctx_nr = perf_invalid_context,
+
+ .event_init = perf_ibs_init,
+ .add = perf_ibs_add,
+ .del = perf_ibs_del,
+ .start = perf_ibs_start,
+ .stop = perf_ibs_stop,
+ .read = perf_ibs_read,
+ },
+ .msr = MSR_AMD64_IBSOPCTL,
+ .config_mask = IBS_OP_CONFIG_MASK,
+ .cnt_mask = IBS_OP_MAX_CNT,
+ .enable_mask = IBS_OP_ENABLE,
+ .valid_mask = IBS_OP_VAL,
+ .max_period = IBS_OP_MAX_CNT << 4,
+ .offset_mask = { MSR_AMD64_IBSOP_REG_MASK },
+ .offset_max = MSR_AMD64_IBSOP_REG_COUNT,
+
+ .get_count = get_ibs_op_count,
+};
+
+static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
+{
+ struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+ struct perf_event *event = pcpu->event;
+ struct hw_perf_event *hwc = &event->hw;
+ struct perf_sample_data data;
+ struct perf_raw_record raw;
+ struct pt_regs regs;
+ struct perf_ibs_data ibs_data;
+ int offset, size, check_rip, offset_max, throttle = 0;
+ unsigned int msr;
+ u64 *buf, *config, period;
+
+ if (!test_bit(IBS_STARTED, pcpu->state)) {
+ /*
+ * Catch spurious interrupts after stopping IBS: After
+ * disabling IBS there could be still incomming NMIs
+ * with samples that even have the valid bit cleared.
+ * Mark all this NMIs as handled.
+ */
+ return test_and_clear_bit(IBS_STOPPING, pcpu->state) ? 1 : 0;
+ }
+
+ msr = hwc->config_base;
+ buf = ibs_data.regs;
+ rdmsrl(msr, *buf);
+ if (!(*buf++ & perf_ibs->valid_mask))
+ return 0;
+
+ config = &ibs_data.regs[0];
+ perf_ibs_event_update(perf_ibs, event, config);
+ perf_sample_data_init(&data, 0, hwc->last_period);
+ if (!perf_ibs_set_period(perf_ibs, hwc, &period))
+ goto out; /* no sw counter overflow */
+
+ ibs_data.caps = ibs_caps;
+ size = 1;
+ offset = 1;
+ check_rip = (perf_ibs == &perf_ibs_op && (ibs_caps & IBS_CAPS_RIPINVALIDCHK));
+ if (event->attr.sample_type & PERF_SAMPLE_RAW)
+ offset_max = perf_ibs->offset_max;
+ else if (check_rip)
+ offset_max = 2;
+ else
+ offset_max = 1;
+ do {
+ rdmsrl(msr + offset, *buf++);
+ size++;
+ offset = find_next_bit(perf_ibs->offset_mask,
+ perf_ibs->offset_max,
+ offset + 1);
+ } while (offset < offset_max);
+ ibs_data.size = sizeof(u64) * size;
+
+ regs = *iregs;
+ if (check_rip && (ibs_data.regs[2] & IBS_RIP_INVALID)) {
+ regs.flags &= ~PERF_EFLAGS_EXACT;
+ } else {
+ instruction_pointer_set(&regs, ibs_data.regs[1]);
+ regs.flags |= PERF_EFLAGS_EXACT;
+ }
+
+ if (event->attr.sample_type & PERF_SAMPLE_RAW) {
+ raw.size = sizeof(u32) + ibs_data.size;
+ raw.data = ibs_data.data;
+ data.raw = &raw;
+ }
+
+ throttle = perf_event_overflow(event, &data, &regs);
+out:
+ if (throttle)
+ perf_ibs_disable_event(perf_ibs, hwc, *config);
+ else
+ perf_ibs_enable_event(perf_ibs, hwc, period >> 4);
+
+ perf_event_update_userpage(event);
+
+ return 1;
+}
+
+static int __kprobes
+perf_ibs_nmi_handler(unsigned int cmd, struct pt_regs *regs)
+{
+ int handled = 0;
+
+ handled += perf_ibs_handle_irq(&perf_ibs_fetch, regs);
+ handled += perf_ibs_handle_irq(&perf_ibs_op, regs);
+
+ if (handled)
+ inc_irq_stat(apic_perf_irqs);
+
+ return handled;
+}
+
+static __init int perf_ibs_pmu_init(struct perf_ibs *perf_ibs, char *name)
+{
+ struct cpu_perf_ibs __percpu *pcpu;
+ int ret;
+
+ pcpu = alloc_percpu(struct cpu_perf_ibs);
+ if (!pcpu)
+ return -ENOMEM;
+
+ perf_ibs->pcpu = pcpu;
+
+ ret = perf_pmu_register(&perf_ibs->pmu, name, -1);
+ if (ret) {
+ perf_ibs->pcpu = NULL;
+ free_percpu(pcpu);
+ }
+
+ return ret;
+}
+
static __init int perf_event_ibs_init(void)
{
if (!ibs_caps)
return -ENODEV; /* ibs not supported by the cpu */
- perf_pmu_register(&perf_ibs, "ibs", -1);
+ perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch");
+ if (ibs_caps & IBS_CAPS_OPCNT)
+ perf_ibs_op.config_mask |= IBS_OP_CNT_CTL;
+ perf_ibs_pmu_init(&perf_ibs_op, "ibs_op");
+ register_nmi_handler(NMI_LOCAL, perf_ibs_nmi_handler, 0, "perf_ibs");
printk(KERN_INFO "perf: AMD IBS detected (0x%08x)\n", ibs_caps);
return 0;
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 26b3e2fef104..166546ec6aef 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1027,8 +1027,6 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
u64 status;
int handled;
- perf_sample_data_init(&data, 0);
-
cpuc = &__get_cpu_var(cpu_hw_events);
/*
@@ -1082,7 +1080,7 @@ again:
if (!intel_pmu_save_and_restart(event))
continue;
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, 0, event->hw.last_period);
if (has_branch_stack(event))
data.br_stack = &cpuc->lbr_stack;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index 7f64df19e7dd..5a3edc27f6e5 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -316,8 +316,7 @@ int intel_pmu_drain_bts_buffer(void)
ds->bts_index = ds->bts_buffer_base;
- perf_sample_data_init(&data, 0);
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, 0, event->hw.last_period);
regs.ip = 0;
/*
@@ -564,8 +563,7 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
if (!intel_pmu_save_and_restart(event))
return;
- perf_sample_data_init(&data, 0);
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, 0, event->hw.last_period);
/*
* We use the interrupt regs as a base because the PEBS record
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
index a2dfacfd7103..47124a73dd73 100644
--- a/arch/x86/kernel/cpu/perf_event_p4.c
+++ b/arch/x86/kernel/cpu/perf_event_p4.c
@@ -1005,8 +1005,6 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
int idx, handled = 0;
u64 val;
- perf_sample_data_init(&data, 0);
-
cpuc = &__get_cpu_var(cpu_hw_events);
for (idx = 0; idx < x86_pmu.num_counters; idx++) {
@@ -1034,10 +1032,12 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
handled += overflow;
/* event overflow for sure */
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, 0, hwc->last_period);
if (!x86_perf_event_set_period(event))
continue;
+
+
if (perf_event_overflow(event, &data, regs))
x86_pmu_stop(event, 0);
}
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index 1b81839b6c88..571246d81edf 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -271,7 +271,7 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
current->thread.trap_nr, SIGSEGV) == NOTIFY_STOP)
return 1;
- show_registers(regs);
+ show_regs(regs);
#ifdef CONFIG_X86_32
if (user_mode_vm(regs)) {
sp = regs->sp;
@@ -311,16 +311,33 @@ void die(const char *str, struct pt_regs *regs, long err)
static int __init kstack_setup(char *s)
{
+ ssize_t ret;
+ unsigned long val;
+
if (!s)
return -EINVAL;
- kstack_depth_to_print = simple_strtoul(s, NULL, 0);
+
+ ret = kstrtoul(s, 0, &val);
+ if (ret)
+ return ret;
+ kstack_depth_to_print = val;
return 0;
}
early_param("kstack", kstack_setup);
static int __init code_bytes_setup(char *s)
{
- code_bytes = simple_strtoul(s, NULL, 0);
+ ssize_t ret;
+ unsigned long val;
+
+ if (!s)
+ return -EINVAL;
+
+ ret = kstrtoul(s, 0, &val);
+ if (ret)
+ return ret;
+
+ code_bytes = val;
if (code_bytes > 8192)
code_bytes = 8192;
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
index 88ec9129271d..e0b1d783daab 100644
--- a/arch/x86/kernel/dumpstack_32.c
+++ b/arch/x86/kernel/dumpstack_32.c
@@ -82,7 +82,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
}
-void show_registers(struct pt_regs *regs)
+void show_regs(struct pt_regs *regs)
{
int i;
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index 17107bd6e1f0..791b76122aa8 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -245,7 +245,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
show_trace_log_lvl(task, regs, sp, bp, log_lvl);
}
-void show_registers(struct pt_regs *regs)
+void show_regs(struct pt_regs *regs)
{
int i;
unsigned long sp;
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 7b784f4ef1e4..01ccf9b71473 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -56,6 +56,7 @@
#include <asm/irq_vectors.h>
#include <asm/cpufeature.h>
#include <asm/alternative-asm.h>
+#include <asm/asm.h>
/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
#include <linux/elf-em.h>
@@ -151,10 +152,8 @@
.pushsection .fixup, "ax"
99: movl $0, (%esp)
jmp 98b
-.section __ex_table, "a"
- .align 4
- .long 98b, 99b
.popsection
+ _ASM_EXTABLE(98b,99b)
.endm
.macro PTGS_TO_GS
@@ -164,10 +163,8 @@
.pushsection .fixup, "ax"
99: movl $0, PT_GS(%esp)
jmp 98b
-.section __ex_table, "a"
- .align 4
- .long 98b, 99b
.popsection
+ _ASM_EXTABLE(98b,99b)
.endm
.macro GS_TO_REG reg
@@ -249,12 +246,10 @@
jmp 2b
6: movl $0, (%esp)
jmp 3b
-.section __ex_table, "a"
- .align 4
- .long 1b, 4b
- .long 2b, 5b
- .long 3b, 6b
.popsection
+ _ASM_EXTABLE(1b,4b)
+ _ASM_EXTABLE(2b,5b)
+ _ASM_EXTABLE(3b,6b)
POP_GS_EX
.endm
@@ -415,10 +410,7 @@ sysenter_past_esp:
jae syscall_fault
1: movl (%ebp),%ebp
movl %ebp,PT_EBP(%esp)
-.section __ex_table,"a"
- .align 4
- .long 1b,syscall_fault
-.previous
+ _ASM_EXTABLE(1b,syscall_fault)
GET_THREAD_INFO(%ebp)
@@ -485,10 +477,8 @@ sysexit_audit:
.pushsection .fixup,"ax"
2: movl $0,PT_FS(%esp)
jmp 1b
-.section __ex_table,"a"
- .align 4
- .long 1b,2b
.popsection
+ _ASM_EXTABLE(1b,2b)
PTGS_TO_GS_EX
ENDPROC(ia32_sysenter_target)
@@ -543,10 +533,7 @@ ENTRY(iret_exc)
pushl $do_iret_error
jmp error_code
.previous
-.section __ex_table,"a"
- .align 4
- .long irq_return,iret_exc
-.previous
+ _ASM_EXTABLE(irq_return,iret_exc)
CFI_RESTORE_STATE
ldt_ss:
@@ -901,10 +888,7 @@ END(device_not_available)
#ifdef CONFIG_PARAVIRT
ENTRY(native_iret)
iret
-.section __ex_table,"a"
- .align 4
- .long native_iret, iret_exc
-.previous
+ _ASM_EXTABLE(native_iret, iret_exc)
END(native_iret)
ENTRY(native_irq_enable_sysexit)
@@ -1093,13 +1077,10 @@ ENTRY(xen_failsafe_callback)
movl %eax,16(%esp)
jmp 4b
.previous
-.section __ex_table,"a"
- .align 4
- .long 1b,6b
- .long 2b,7b
- .long 3b,8b
- .long 4b,9b
-.previous
+ _ASM_EXTABLE(1b,6b)
+ _ASM_EXTABLE(2b,7b)
+ _ASM_EXTABLE(3b,8b)
+ _ASM_EXTABLE(4b,9b)
ENDPROC(xen_failsafe_callback)
BUILD_INTERRUPT3(xen_hvm_callback_vector, XEN_HVM_EVTCHN_CALLBACK,
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index cdc79b5cfcd9..320852d02026 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -55,6 +55,7 @@
#include <asm/paravirt.h>
#include <asm/ftrace.h>
#include <asm/percpu.h>
+#include <asm/asm.h>
#include <linux/err.h>
/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
@@ -900,18 +901,12 @@ restore_args:
irq_return:
INTERRUPT_RETURN
-
- .section __ex_table, "a"
- .quad irq_return, bad_iret
- .previous
+ _ASM_EXTABLE(irq_return, bad_iret)
#ifdef CONFIG_PARAVIRT
ENTRY(native_iret)
iretq
-
- .section __ex_table,"a"
- .quad native_iret, bad_iret
- .previous
+ _ASM_EXTABLE(native_iret, bad_iret)
#endif
.section .fixup,"ax"
@@ -1181,10 +1176,7 @@ gs_change:
CFI_ENDPROC
END(native_load_gs_index)
- .section __ex_table,"a"
- .align 8
- .quad gs_change,bad_gs
- .previous
+ _ASM_EXTABLE(gs_change,bad_gs)
.section .fixup,"ax"
/* running with kernelgs */
bad_gs:
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index c9a281f272fd..32ff36596ab1 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -24,40 +24,21 @@
#include <trace/syscall.h>
#include <asm/cacheflush.h>
+#include <asm/kprobes.h>
#include <asm/ftrace.h>
#include <asm/nops.h>
-#include <asm/nmi.h>
-
#ifdef CONFIG_DYNAMIC_FTRACE
-/*
- * modifying_code is set to notify NMIs that they need to use
- * memory barriers when entering or exiting. But we don't want
- * to burden NMIs with unnecessary memory barriers when code
- * modification is not being done (which is most of the time).
- *
- * A mutex is already held when ftrace_arch_code_modify_prepare
- * and post_process are called. No locks need to be taken here.
- *
- * Stop machine will make sure currently running NMIs are done
- * and new NMIs will see the updated variable before we need
- * to worry about NMIs doing memory barriers.
- */
-static int modifying_code __read_mostly;
-static DEFINE_PER_CPU(int, save_modifying_code);
-
int ftrace_arch_code_modify_prepare(void)
{
set_kernel_text_rw();
set_all_modules_text_rw();
- modifying_code = 1;
return 0;
}
int ftrace_arch_code_modify_post_process(void)
{
- modifying_code = 0;
set_all_modules_text_ro();
set_kernel_text_ro();
return 0;
@@ -90,134 +71,6 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
return calc.code;
}
-/*
- * Modifying code must take extra care. On an SMP machine, if
- * the code being modified is also being executed on another CPU
- * that CPU will have undefined results and possibly take a GPF.
- * We use kstop_machine to stop other CPUS from exectuing code.
- * But this does not stop NMIs from happening. We still need
- * to protect against that. We separate out the modification of
- * the code to take care of this.
- *
- * Two buffers are added: An IP buffer and a "code" buffer.
- *
- * 1) Put the instruction pointer into the IP buffer
- * and the new code into the "code" buffer.
- * 2) Wait for any running NMIs to finish and set a flag that says
- * we are modifying code, it is done in an atomic operation.
- * 3) Write the code
- * 4) clear the flag.
- * 5) Wait for any running NMIs to finish.
- *
- * If an NMI is executed, the first thing it does is to call
- * "ftrace_nmi_enter". This will check if the flag is set to write
- * and if it is, it will write what is in the IP and "code" buffers.
- *
- * The trick is, it does not matter if everyone is writing the same
- * content to the code location. Also, if a CPU is executing code
- * it is OK to write to that code location if the contents being written
- * are the same as what exists.
- */
-
-#define MOD_CODE_WRITE_FLAG (1 << 31) /* set when NMI should do the write */
-static atomic_t nmi_running = ATOMIC_INIT(0);
-static int mod_code_status; /* holds return value of text write */
-static void *mod_code_ip; /* holds the IP to write to */
-static const void *mod_code_newcode; /* holds the text to write to the IP */
-
-static unsigned nmi_wait_count;
-static atomic_t nmi_update_count = ATOMIC_INIT(0);
-
-int ftrace_arch_read_dyn_info(char *buf, int size)
-{
- int r;
-
- r = snprintf(buf, size, "%u %u",
- nmi_wait_count,
- atomic_read(&nmi_update_count));
- return r;
-}
-
-static void clear_mod_flag(void)
-{
- int old = atomic_read(&nmi_running);
-
- for (;;) {
- int new = old & ~MOD_CODE_WRITE_FLAG;
-
- if (old == new)
- break;
-
- old = atomic_cmpxchg(&nmi_running, old, new);
- }
-}
-
-static void ftrace_mod_code(void)
-{
- /*
- * Yes, more than one CPU process can be writing to mod_code_status.
- * (and the code itself)
- * But if one were to fail, then they all should, and if one were
- * to succeed, then they all should.
- */
- mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode,
- MCOUNT_INSN_SIZE);
-
- /* if we fail, then kill any new writers */
- if (mod_code_status)
- clear_mod_flag();
-}
-
-void ftrace_nmi_enter(void)
-{
- __this_cpu_write(save_modifying_code, modifying_code);
-
- if (!__this_cpu_read(save_modifying_code))
- return;
-
- if (atomic_inc_return(&nmi_running) & MOD_CODE_WRITE_FLAG) {
- smp_rmb();
- ftrace_mod_code();
- atomic_inc(&nmi_update_count);
- }
- /* Must have previous changes seen before executions */
- smp_mb();
-}
-
-void ftrace_nmi_exit(void)
-{
- if (!__this_cpu_read(save_modifying_code))
- return;
-
- /* Finish all executions before clearing nmi_running */
- smp_mb();
- atomic_dec(&nmi_running);
-}
-
-static void wait_for_nmi_and_set_mod_flag(void)
-{
- if (!atomic_cmpxchg(&nmi_running, 0, MOD_CODE_WRITE_FLAG))
- return;
-
- do {
- cpu_relax();
- } while (atomic_cmpxchg(&nmi_running, 0, MOD_CODE_WRITE_FLAG));
-
- nmi_wait_count++;
-}
-
-static void wait_for_nmi(void)
-{
- if (!atomic_read(&nmi_running))
- return;
-
- do {
- cpu_relax();
- } while (atomic_read(&nmi_running));
-
- nmi_wait_count++;
-}
-
static inline int
within(unsigned long addr, unsigned long start, unsigned long end)
{
@@ -238,26 +91,7 @@ do_ftrace_mod_code(unsigned long ip, const void *new_code)
if (within(ip, (unsigned long)_text, (unsigned long)_etext))
ip = (unsigned long)__va(__pa(ip));
- mod_code_ip = (void *)ip;
- mod_code_newcode = new_code;
-
- /* The buffers need to be visible before we let NMIs write them */
- smp_mb();
-
- wait_for_nmi_and_set_mod_flag();
-
- /* Make sure all running NMIs have finished before we write the code */
- smp_mb();
-
- ftrace_mod_code();
-
- /* Make sure the write happens before clearing the bit */
- smp_mb();
-
- clear_mod_flag();
- wait_for_nmi();
-
- return mod_code_status;
+ return probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE);
}
static const unsigned char *ftrace_nop_replace(void)
@@ -334,6 +168,336 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
return ret;
}
+int modifying_ftrace_code __read_mostly;
+
+/*
+ * A breakpoint was added to the code address we are about to
+ * modify, and this is the handle that will just skip over it.
+ * We are either changing a nop into a trace call, or a trace
+ * call to a nop. While the change is taking place, we treat
+ * it just like it was a nop.
+ */
+int ftrace_int3_handler(struct pt_regs *regs)
+{
+ if (WARN_ON_ONCE(!regs))
+ return 0;
+
+ if (!ftrace_location(regs->ip - 1))
+ return 0;
+
+ regs->ip += MCOUNT_INSN_SIZE - 1;
+
+ return 1;
+}
+
+static int ftrace_write(unsigned long ip, const char *val, int size)
+{
+ /*
+ * On x86_64, kernel text mappings are mapped read-only with
+ * CONFIG_DEBUG_RODATA. So we use the kernel identity mapping instead
+ * of the kernel text mapping to modify the kernel text.
+ *
+ * For 32bit kernels, these mappings are same and we can use
+ * kernel identity mapping to modify code.
+ */
+ if (within(ip, (unsigned long)_text, (unsigned long)_etext))
+ ip = (unsigned long)__va(__pa(ip));
+
+ return probe_kernel_write((void *)ip, val, size);
+}
+
+static int add_break(unsigned long ip, const char *old)
+{
+ unsigned char replaced[MCOUNT_INSN_SIZE];
+ unsigned char brk = BREAKPOINT_INSTRUCTION;
+
+ if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
+ return -EFAULT;
+
+ /* Make sure it is what we expect it to be */
+ if (memcmp(replaced, old, MCOUNT_INSN_SIZE) != 0)
+ return -EINVAL;
+
+ if (ftrace_write(ip, &brk, 1))
+ return -EPERM;
+
+ return 0;
+}
+
+static int add_brk_on_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+ unsigned const char *old;
+ unsigned long ip = rec->ip;
+
+ old = ftrace_call_replace(ip, addr);
+
+ return add_break(rec->ip, old);
+}
+
+
+static int add_brk_on_nop(struct dyn_ftrace *rec)
+{
+ unsigned const char *old;
+
+ old = ftrace_nop_replace();
+
+ return add_break(rec->ip, old);
+}
+
+static int add_breakpoints(struct dyn_ftrace *rec, int enable)
+{
+ unsigned long ftrace_addr;
+ int ret;
+
+ ret = ftrace_test_record(rec, enable);
+
+ ftrace_addr = (unsigned long)FTRACE_ADDR;
+
+ switch (ret) {
+ case FTRACE_UPDATE_IGNORE:
+ return 0;
+
+ case FTRACE_UPDATE_MAKE_CALL:
+ /* converting nop to call */
+ return add_brk_on_nop(rec);
+
+ case FTRACE_UPDATE_MAKE_NOP:
+ /* converting a call to a nop */
+ return add_brk_on_call(rec, ftrace_addr);
+ }
+ return 0;
+}
+
+/*
+ * On error, we need to remove breakpoints. This needs to
+ * be done caefully. If the address does not currently have a
+ * breakpoint, we know we are done. Otherwise, we look at the
+ * remaining 4 bytes of the instruction. If it matches a nop
+ * we replace the breakpoint with the nop. Otherwise we replace
+ * it with the call instruction.
+ */
+static int remove_breakpoint(struct dyn_ftrace *rec)
+{
+ unsigned char ins[MCOUNT_INSN_SIZE];
+ unsigned char brk = BREAKPOINT_INSTRUCTION;
+ const unsigned char *nop;
+ unsigned long ftrace_addr;
+ unsigned long ip = rec->ip;
+
+ /* If we fail the read, just give up */
+ if (probe_kernel_read(ins, (void *)ip, MCOUNT_INSN_SIZE))
+ return -EFAULT;
+
+ /* If this does not have a breakpoint, we are done */
+ if (ins[0] != brk)
+ return -1;
+
+ nop = ftrace_nop_replace();
+
+ /*
+ * If the last 4 bytes of the instruction do not match
+ * a nop, then we assume that this is a call to ftrace_addr.
+ */
+ if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) != 0) {
+ /*
+ * For extra paranoidism, we check if the breakpoint is on
+ * a call that would actually jump to the ftrace_addr.
+ * If not, don't touch the breakpoint, we make just create
+ * a disaster.
+ */
+ ftrace_addr = (unsigned long)FTRACE_ADDR;
+ nop = ftrace_call_replace(ip, ftrace_addr);
+
+ if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) != 0)
+ return -EINVAL;
+ }
+
+ return probe_kernel_write((void *)ip, &nop[0], 1);
+}
+
+static int add_update_code(unsigned long ip, unsigned const char *new)
+{
+ /* skip breakpoint */
+ ip++;
+ new++;
+ if (ftrace_write(ip, new, MCOUNT_INSN_SIZE - 1))
+ return -EPERM;
+ return 0;
+}
+
+static int add_update_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+ unsigned long ip = rec->ip;
+ unsigned const char *new;
+
+ new = ftrace_call_replace(ip, addr);
+ return add_update_code(ip, new);
+}
+
+static int add_update_nop(struct dyn_ftrace *rec)
+{
+ unsigned long ip = rec->ip;
+ unsigned const char *new;
+
+ new = ftrace_nop_replace();
+ return add_update_code(ip, new);
+}
+
+static int add_update(struct dyn_ftrace *rec, int enable)
+{
+ unsigned long ftrace_addr;
+ int ret;
+
+ ret = ftrace_test_record(rec, enable);
+
+ ftrace_addr = (unsigned long)FTRACE_ADDR;
+
+ switch (ret) {
+ case FTRACE_UPDATE_IGNORE:
+ return 0;
+
+ case FTRACE_UPDATE_MAKE_CALL:
+ /* converting nop to call */
+ return add_update_call(rec, ftrace_addr);
+
+ case FTRACE_UPDATE_MAKE_NOP:
+ /* converting a call to a nop */
+ return add_update_nop(rec);
+ }
+
+ return 0;
+}
+
+static int finish_update_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+ unsigned long ip = rec->ip;
+ unsigned const char *new;
+
+ new = ftrace_call_replace(ip, addr);
+
+ if (ftrace_write(ip, new, 1))
+ return -EPERM;
+
+ return 0;
+}
+
+static int finish_update_nop(struct dyn_ftrace *rec)
+{
+ unsigned long ip = rec->ip;
+ unsigned const char *new;
+
+ new = ftrace_nop_replace();
+
+ if (ftrace_write(ip, new, 1))
+ return -EPERM;
+ return 0;
+}
+
+static int finish_update(struct dyn_ftrace *rec, int enable)
+{
+ unsigned long ftrace_addr;
+ int ret;
+
+ ret = ftrace_update_record(rec, enable);
+
+ ftrace_addr = (unsigned long)FTRACE_ADDR;
+
+ switch (ret) {
+ case FTRACE_UPDATE_IGNORE:
+ return 0;
+
+ case FTRACE_UPDATE_MAKE_CALL:
+ /* converting nop to call */
+ return finish_update_call(rec, ftrace_addr);
+
+ case FTRACE_UPDATE_MAKE_NOP:
+ /* converting a call to a nop */
+ return finish_update_nop(rec);
+ }
+
+ return 0;
+}
+
+static void do_sync_core(void *data)
+{
+ sync_core();
+}
+
+static void run_sync(void)
+{
+ int enable_irqs = irqs_disabled();
+
+ /* We may be called with interrupts disbled (on bootup). */
+ if (enable_irqs)
+ local_irq_enable();
+ on_each_cpu(do_sync_core, NULL, 1);
+ if (enable_irqs)
+ local_irq_disable();
+}
+
+void ftrace_replace_code(int enable)
+{
+ struct ftrace_rec_iter *iter;
+ struct dyn_ftrace *rec;
+ const char *report = "adding breakpoints";
+ int count = 0;
+ int ret;
+
+ for_ftrace_rec_iter(iter) {
+ rec = ftrace_rec_iter_record(iter);
+
+ ret = add_breakpoints(rec, enable);
+ if (ret)
+ goto remove_breakpoints;
+ count++;
+ }
+
+ run_sync();
+
+ report = "updating code";
+
+ for_ftrace_rec_iter(iter) {
+ rec = ftrace_rec_iter_record(iter);
+
+ ret = add_update(rec, enable);
+ if (ret)
+ goto remove_breakpoints;
+ }
+
+ run_sync();
+
+ report = "removing breakpoints";
+
+ for_ftrace_rec_iter(iter) {
+ rec = ftrace_rec_iter_record(iter);
+
+ ret = finish_update(rec, enable);
+ if (ret)
+ goto remove_breakpoints;
+ }
+
+ run_sync();
+
+ return;
+
+ remove_breakpoints:
+ ftrace_bug(ret, rec ? rec->ip : 0);
+ printk(KERN_WARNING "Failed on %s (%d):\n", report, count);
+ for_ftrace_rec_iter(iter) {
+ rec = ftrace_rec_iter_record(iter);
+ remove_breakpoint(rec);
+ }
+}
+
+void arch_ftrace_update_code(int command)
+{
+ modifying_ftrace_code++;
+
+ ftrace_modify_all_code(command);
+
+ modifying_ftrace_code--;
+}
+
int __init ftrace_dyn_arch_init(void *data)
{
/* The return code is retured via data */
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index ce0be7cd085e..463c9797ca6a 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -21,6 +21,7 @@
#include <asm/msr-index.h>
#include <asm/cpufeature.h>
#include <asm/percpu.h>
+#include <asm/nops.h>
/* Physical address */
#define pa(X) ((X) - __PAGE_OFFSET)
@@ -363,28 +364,23 @@ default_entry:
pushl $0
popfl
-#ifdef CONFIG_SMP
- cmpb $0, ready
- jnz checkCPUtype
-#endif /* CONFIG_SMP */
-
/*
* start system 32-bit setup. We need to re-do some of the things done
* in 16-bit mode for the "real" operations.
*/
- call setup_idt
-
-checkCPUtype:
-
- movl $-1,X86_CPUID # -1 for no CPUID initially
-
+ movl setup_once_ref,%eax
+ andl %eax,%eax
+ jz 1f # Did we do this already?
+ call *%eax
+1:
+
/* check if it is 486 or 386. */
/*
* XXX - this does a lot of unnecessary setup. Alignment checks don't
* apply at our cpl of 0 and the stack ought to be aligned already, and
* we don't need to preserve eflags.
*/
-
+ movl $-1,X86_CPUID # -1 for no CPUID initially
movb $3,X86 # at least 386
pushfl # push EFLAGS
popl %eax # get EFLAGS
@@ -450,21 +446,6 @@ is386: movl $2,%ecx # set MP
movl $(__KERNEL_PERCPU), %eax
movl %eax,%fs # set this cpu's percpu
-#ifdef CONFIG_CC_STACKPROTECTOR
- /*
- * The linker can't handle this by relocation. Manually set
- * base address in stack canary segment descriptor.
- */
- cmpb $0,ready
- jne 1f
- movl $gdt_page,%eax
- movl $stack_canary,%ecx
- movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax)
- shrl $16, %ecx
- movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax)
- movb %ch, 8 * GDT_ENTRY_STACK_CANARY + 7(%eax)
-1:
-#endif
movl $(__KERNEL_STACK_CANARY),%eax
movl %eax,%gs
@@ -473,7 +454,6 @@ is386: movl $2,%ecx # set MP
cld # gcc2 wants the direction flag cleared at all times
pushl $0 # fake return address for unwinder
- movb $1, ready
jmp *(initial_code)
/*
@@ -495,81 +475,122 @@ check_x87:
.byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */
ret
+
+#include "verify_cpu.S"
+
/*
- * setup_idt
+ * setup_once
*
- * sets up a idt with 256 entries pointing to
- * ignore_int, interrupt gates. It doesn't actually load
- * idt - that can be done only after paging has been enabled
- * and the kernel moved to PAGE_OFFSET. Interrupts
- * are enabled elsewhere, when we can be relatively
- * sure everything is ok.
+ * The setup work we only want to run on the BSP.
*
* Warning: %esi is live across this function.
*/
-setup_idt:
- lea ignore_int,%edx
- movl $(__KERNEL_CS << 16),%eax
- movw %dx,%ax /* selector = 0x0010 = cs */
- movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
+__INIT
+setup_once:
+ /*
+ * Set up a idt with 256 entries pointing to ignore_int,
+ * interrupt gates. It doesn't actually load idt - that needs
+ * to be done on each CPU. Interrupts are enabled elsewhere,
+ * when we can be relatively sure everything is ok.
+ */
- lea idt_table,%edi
- mov $256,%ecx
-rp_sidt:
+ movl $idt_table,%edi
+ movl $early_idt_handlers,%eax
+ movl $NUM_EXCEPTION_VECTORS,%ecx
+1:
movl %eax,(%edi)
- movl %edx,4(%edi)
+ movl %eax,4(%edi)
+ /* interrupt gate, dpl=0, present */
+ movl $(0x8E000000 + __KERNEL_CS),2(%edi)
+ addl $9,%eax
addl $8,%edi
- dec %ecx
- jne rp_sidt
+ loop 1b
-.macro set_early_handler handler,trapno
- lea \handler,%edx
+ movl $256 - NUM_EXCEPTION_VECTORS,%ecx
+ movl $ignore_int,%edx
movl $(__KERNEL_CS << 16),%eax
- movw %dx,%ax
+ movw %dx,%ax /* selector = 0x0010 = cs */
movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
- lea idt_table,%edi
- movl %eax,8*\trapno(%edi)
- movl %edx,8*\trapno+4(%edi)
-.endm
+2:
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+ loop 2b
- set_early_handler handler=early_divide_err,trapno=0
- set_early_handler handler=early_illegal_opcode,trapno=6
- set_early_handler handler=early_protection_fault,trapno=13
- set_early_handler handler=early_page_fault,trapno=14
+#ifdef CONFIG_CC_STACKPROTECTOR
+ /*
+ * Configure the stack canary. The linker can't handle this by
+ * relocation. Manually set base address in stack canary
+ * segment descriptor.
+ */
+ movl $gdt_page,%eax
+ movl $stack_canary,%ecx
+ movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax)
+ shrl $16, %ecx
+ movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax)
+ movb %ch, 8 * GDT_ENTRY_STACK_CANARY + 7(%eax)
+#endif
+ andl $0,setup_once_ref /* Once is enough, thanks */
ret
-early_divide_err:
- xor %edx,%edx
- pushl $0 /* fake errcode */
- jmp early_fault
+ENTRY(early_idt_handlers)
+ # 36(%esp) %eflags
+ # 32(%esp) %cs
+ # 28(%esp) %eip
+ # 24(%rsp) error code
+ i = 0
+ .rept NUM_EXCEPTION_VECTORS
+ .if (EXCEPTION_ERRCODE_MASK >> i) & 1
+ ASM_NOP2
+ .else
+ pushl $0 # Dummy error code, to make stack frame uniform
+ .endif
+ pushl $i # 20(%esp) Vector number
+ jmp early_idt_handler
+ i = i + 1
+ .endr
+ENDPROC(early_idt_handlers)
+
+ /* This is global to keep gas from relaxing the jumps */
+ENTRY(early_idt_handler)
+ cld
+ cmpl $2,%ss:early_recursion_flag
+ je hlt_loop
+ incl %ss:early_recursion_flag
-early_illegal_opcode:
- movl $6,%edx
- pushl $0 /* fake errcode */
- jmp early_fault
+ push %eax # 16(%esp)
+ push %ecx # 12(%esp)
+ push %edx # 8(%esp)
+ push %ds # 4(%esp)
+ push %es # 0(%esp)
+ movl $(__KERNEL_DS),%eax
+ movl %eax,%ds
+ movl %eax,%es
-early_protection_fault:
- movl $13,%edx
- jmp early_fault
+ cmpl $(__KERNEL_CS),32(%esp)
+ jne 10f
-early_page_fault:
- movl $14,%edx
- jmp early_fault
+ leal 28(%esp),%eax # Pointer to %eip
+ call early_fixup_exception
+ andl %eax,%eax
+ jnz ex_entry /* found an exception entry */
-early_fault:
- cld
+10:
#ifdef CONFIG_PRINTK
- pusha
- movl $(__KERNEL_DS),%eax
- movl %eax,%ds
- movl %eax,%es
- cmpl $2,early_recursion_flag
- je hlt_loop
- incl early_recursion_flag
+ xorl %eax,%eax
+ movw %ax,2(%esp) /* clean up the segment values on some cpus */
+ movw %ax,6(%esp)
+ movw %ax,34(%esp)
+ leal 40(%esp),%eax
+ pushl %eax /* %esp before the exception */
+ pushl %ebx
+ pushl %ebp
+ pushl %esi
+ pushl %edi
movl %cr2,%eax
pushl %eax
- pushl %edx /* trapno */
+ pushl (20+6*4)(%esp) /* trapno */
pushl $fault_msg
call printk
#endif
@@ -578,6 +599,17 @@ hlt_loop:
hlt
jmp hlt_loop
+ex_entry:
+ pop %es
+ pop %ds
+ pop %edx
+ pop %ecx
+ pop %eax
+ addl $8,%esp /* drop vector number and error code */
+ decl %ss:early_recursion_flag
+ iret
+ENDPROC(early_idt_handler)
+
/* This is the default interrupt "handler" :-) */
ALIGN
ignore_int:
@@ -611,13 +643,18 @@ ignore_int:
popl %eax
#endif
iret
+ENDPROC(ignore_int)
+__INITDATA
+ .align 4
+early_recursion_flag:
+ .long 0
-#include "verify_cpu.S"
-
- __REFDATA
-.align 4
+__REFDATA
+ .align 4
ENTRY(initial_code)
.long i386_start_kernel
+ENTRY(setup_once_ref)
+ .long setup_once
/*
* BSS section
@@ -670,22 +707,19 @@ ENTRY(initial_page_table)
ENTRY(stack_start)
.long init_thread_union+THREAD_SIZE
-early_recursion_flag:
- .long 0
-
-ready: .byte 0
-
+__INITRODATA
int_msg:
.asciz "Unknown interrupt or fault at: %p %p %p\n"
fault_msg:
/* fault info: */
.ascii "BUG: Int %d: CR2 %p\n"
-/* pusha regs: */
- .ascii " EDI %p ESI %p EBP %p ESP %p\n"
- .ascii " EBX %p EDX %p ECX %p EAX %p\n"
+/* regs pushed in early_idt_handler: */
+ .ascii " EDI %p ESI %p EBP %p EBX %p\n"
+ .ascii " ESP %p ES %p DS %p\n"
+ .ascii " EDX %p ECX %p EAX %p\n"
/* fault frame: */
- .ascii " err %p EIP %p CS %p flg %p\n"
+ .ascii " vec %p err %p EIP %p CS %p flg %p\n"
.ascii "Stack: %p %p %p %p %p %p %p %p\n"
.ascii " %p %p %p %p %p %p %p %p\n"
.asciz " %p %p %p %p %p %p %p %p\n"
@@ -699,6 +733,7 @@ fault_msg:
* segment size, and 32-bit linear address value:
*/
+ .data
.globl boot_gdt_descr
.globl idt_descr
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 40f4eb3766d1..7a40f2447321 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -19,12 +19,15 @@
#include <asm/cache.h>
#include <asm/processor-flags.h>
#include <asm/percpu.h>
+#include <asm/nops.h>
#ifdef CONFIG_PARAVIRT
#include <asm/asm-offsets.h>
#include <asm/paravirt.h>
+#define GET_CR2_INTO(reg) GET_CR2_INTO_RAX ; movq %rax, reg
#else
-#define GET_CR2_INTO_RCX movq %cr2, %rcx
+#define GET_CR2_INTO(reg) movq %cr2, reg
+#define INTERRUPT_RETURN iretq
#endif
/* we are not able to switch in one step to the final KERNEL ADDRESS SPACE
@@ -270,36 +273,56 @@ bad_address:
jmp bad_address
.section ".init.text","ax"
-#ifdef CONFIG_EARLY_PRINTK
.globl early_idt_handlers
early_idt_handlers:
+ # 104(%rsp) %rflags
+ # 96(%rsp) %cs
+ # 88(%rsp) %rip
+ # 80(%rsp) error code
i = 0
.rept NUM_EXCEPTION_VECTORS
- movl $i, %esi
+ .if (EXCEPTION_ERRCODE_MASK >> i) & 1
+ ASM_NOP2
+ .else
+ pushq $0 # Dummy error code, to make stack frame uniform
+ .endif
+ pushq $i # 72(%rsp) Vector number
jmp early_idt_handler
i = i + 1
.endr
-#endif
ENTRY(early_idt_handler)
-#ifdef CONFIG_EARLY_PRINTK
+ cld
+
cmpl $2,early_recursion_flag(%rip)
jz 1f
incl early_recursion_flag(%rip)
- GET_CR2_INTO_RCX
- movq %rcx,%r9
- xorl %r8d,%r8d # zero for error code
- movl %esi,%ecx # get vector number
- # Test %ecx against mask of vectors that push error code.
- cmpl $31,%ecx
- ja 0f
- movl $1,%eax
- salq %cl,%rax
- testl $0x27d00,%eax
- je 0f
- popq %r8 # get error code
-0: movq 0(%rsp),%rcx # get ip
- movq 8(%rsp),%rdx # get cs
+
+ pushq %rax # 64(%rsp)
+ pushq %rcx # 56(%rsp)
+ pushq %rdx # 48(%rsp)
+ pushq %rsi # 40(%rsp)
+ pushq %rdi # 32(%rsp)
+ pushq %r8 # 24(%rsp)
+ pushq %r9 # 16(%rsp)
+ pushq %r10 # 8(%rsp)
+ pushq %r11 # 0(%rsp)
+
+ cmpl $__KERNEL_CS,96(%rsp)
+ jne 10f
+
+ leaq 88(%rsp),%rdi # Pointer to %rip
+ call early_fixup_exception
+ andl %eax,%eax
+ jnz 20f # Found an exception entry
+
+10:
+#ifdef CONFIG_EARLY_PRINTK
+ GET_CR2_INTO(%r9) # can clobber any volatile register if pv
+ movl 80(%rsp),%r8d # error code
+ movl 72(%rsp),%esi # vector number
+ movl 96(%rsp),%edx # %cs
+ movq 88(%rsp),%rcx # %rip
xorl %eax,%eax
leaq early_idt_msg(%rip),%rdi
call early_printk
@@ -308,17 +331,32 @@ ENTRY(early_idt_handler)
call dump_stack
#ifdef CONFIG_KALLSYMS
leaq early_idt_ripmsg(%rip),%rdi
- movq 0(%rsp),%rsi # get rip again
+ movq 40(%rsp),%rsi # %rip again
call __print_symbol
#endif
#endif /* EARLY_PRINTK */
1: hlt
jmp 1b
-#ifdef CONFIG_EARLY_PRINTK
+20: # Exception table entry found
+ popq %r11
+ popq %r10
+ popq %r9
+ popq %r8
+ popq %rdi
+ popq %rsi
+ popq %rdx
+ popq %rcx
+ popq %rax
+ addq $16,%rsp # drop vector number and error code
+ decl early_recursion_flag(%rip)
+ INTERRUPT_RETURN
+
+ .balign 4
early_recursion_flag:
.long 0
+#ifdef CONFIG_EARLY_PRINTK
early_idt_msg:
.asciz "PANIC: early exception %02lx rip %lx:%lx error %lx cr2 %lx\n"
early_idt_ripmsg:
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 2d6e6498c176..f250431fb505 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -88,7 +88,7 @@ void kernel_fpu_begin(void)
__thread_clear_has_fpu(me);
/* We do 'stts()' in kernel_fpu_end() */
} else {
- percpu_write(fpu_owner_task, NULL);
+ this_cpu_write(fpu_owner_task, NULL);
clts();
}
}
diff --git a/arch/x86/kernel/init_task.c b/arch/x86/kernel/init_task.c
deleted file mode 100644
index 43e9ccf44947..000000000000
--- a/arch/x86/kernel/init_task.c
+++ /dev/null
@@ -1,42 +0,0 @@
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/desc.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is THREAD_SIZE aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
-
-/*
- * per-CPU TSS segments. Threads are completely 'soft' on Linux,
- * no more per-task TSS's. The TSS size is kept cacheline-aligned
- * so they are allowed to end up in the .data..cacheline_aligned
- * section. Since TSS's are completely CPU-local, we want them
- * on exact cacheline boundaries, to eliminate cacheline ping-pong.
- */
-DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS;
-
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 58b7f27cb3e9..344faf8d0d62 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -127,8 +127,8 @@ void __cpuinit irq_ctx_init(int cpu)
return;
irqctx = page_address(alloc_pages_node(cpu_to_node(cpu),
- THREAD_FLAGS,
- THREAD_ORDER));
+ THREADINFO_GFP,
+ THREAD_SIZE_ORDER));
memset(&irqctx->tinfo, 0, sizeof(struct thread_info));
irqctx->tinfo.cpu = cpu;
irqctx->tinfo.preempt_count = HARDIRQ_OFFSET;
@@ -137,8 +137,8 @@ void __cpuinit irq_ctx_init(int cpu)
per_cpu(hardirq_ctx, cpu) = irqctx;
irqctx = page_address(alloc_pages_node(cpu_to_node(cpu),
- THREAD_FLAGS,
- THREAD_ORDER));
+ THREADINFO_GFP,
+ THREAD_SIZE_ORDER));
memset(&irqctx->tinfo, 0, sizeof(struct thread_info));
irqctx->tinfo.cpu = cpu;
irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index e213fc8408d2..e2f751efb7b1 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -1037,9 +1037,9 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
"current sp %p does not match saved sp %p\n",
stack_addr(regs), kcb->jprobe_saved_sp);
printk(KERN_ERR "Saved registers for jprobe %p\n", jp);
- show_registers(saved_regs);
+ show_regs(saved_regs);
printk(KERN_ERR "Current registers\n");
- show_registers(regs);
+ show_regs(regs);
BUG();
}
*regs = kcb->jprobe_saved_regs;
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index c9bda6d6035c..fbdfc6917180 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -299,12 +299,11 @@ static ssize_t reload_store(struct device *dev,
{
unsigned long val;
int cpu = dev->id;
- int ret = 0;
- char *end;
+ ssize_t ret = 0;
- val = simple_strtoul(buf, &end, 0);
- if (end == buf)
- return -EINVAL;
+ ret = kstrtoul(buf, 0, &val);
+ if (ret)
+ return ret;
if (val == 1) {
get_online_cpus();
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
index 3ca42d0e43a2..0327e2b3c408 100644
--- a/arch/x86/kernel/microcode_intel.c
+++ b/arch/x86/kernel/microcode_intel.c
@@ -147,12 +147,6 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
memset(csig, 0, sizeof(*csig));
- if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
- cpu_has(c, X86_FEATURE_IA64)) {
- pr_err("CPU%d not a capable Intel processor\n", cpu_num);
- return -1;
- }
-
csig->sig = cpuid_eax(0x00000001);
if ((c->x86_model >= 5) || (c->x86 > 6)) {
@@ -463,6 +457,14 @@ static struct microcode_ops microcode_intel_ops = {
struct microcode_ops * __init init_intel_microcode(void)
{
+ struct cpuinfo_x86 *c = &cpu_data(0);
+
+ if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
+ cpu_has(c, X86_FEATURE_IA64)) {
+ pr_err("Intel CPU family 0x%x not supported\n", c->x86);
+ return NULL;
+ }
+
return &microcode_intel_ops;
}
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
index 7b3fdfdabf94..90875279ef3d 100644
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -29,14 +29,6 @@
#include <asm/nmi.h>
#include <asm/x86_init.h>
-#define NMI_MAX_NAMELEN 16
-struct nmiaction {
- struct list_head list;
- nmi_handler_t handler;
- unsigned int flags;
- char *name;
-};
-
struct nmi_desc {
spinlock_t lock;
struct list_head head;
@@ -52,6 +44,14 @@ static struct nmi_desc nmi_desc[NMI_MAX] =
.lock = __SPIN_LOCK_UNLOCKED(&nmi_desc[1].lock),
.head = LIST_HEAD_INIT(nmi_desc[1].head),
},
+ {
+ .lock = __SPIN_LOCK_UNLOCKED(&nmi_desc[2].lock),
+ .head = LIST_HEAD_INIT(nmi_desc[2].head),
+ },
+ {
+ .lock = __SPIN_LOCK_UNLOCKED(&nmi_desc[3].lock),
+ .head = LIST_HEAD_INIT(nmi_desc[3].head),
+ },
};
@@ -82,7 +82,7 @@ __setup("unknown_nmi_panic", setup_unknown_nmi_panic);
#define nmi_to_desc(type) (&nmi_desc[type])
-static int notrace __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2b)
+static int __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2b)
{
struct nmi_desc *desc = nmi_to_desc(type);
struct nmiaction *a;
@@ -105,11 +105,14 @@ static int notrace __kprobes nmi_handle(unsigned int type, struct pt_regs *regs,
return handled;
}
-static int __setup_nmi(unsigned int type, struct nmiaction *action)
+int __register_nmi_handler(unsigned int type, struct nmiaction *action)
{
struct nmi_desc *desc = nmi_to_desc(type);
unsigned long flags;
+ if (!action->handler)
+ return -EINVAL;
+
spin_lock_irqsave(&desc->lock, flags);
/*
@@ -118,6 +121,8 @@ static int __setup_nmi(unsigned int type, struct nmiaction *action)
* to manage expectations
*/
WARN_ON_ONCE(type == NMI_UNKNOWN && !list_empty(&desc->head));
+ WARN_ON_ONCE(type == NMI_SERR && !list_empty(&desc->head));
+ WARN_ON_ONCE(type == NMI_IO_CHECK && !list_empty(&desc->head));
/*
* some handlers need to be executed first otherwise a fake
@@ -131,8 +136,9 @@ static int __setup_nmi(unsigned int type, struct nmiaction *action)
spin_unlock_irqrestore(&desc->lock, flags);
return 0;
}
+EXPORT_SYMBOL(__register_nmi_handler);
-static struct nmiaction *__free_nmi(unsigned int type, const char *name)
+void unregister_nmi_handler(unsigned int type, const char *name)
{
struct nmi_desc *desc = nmi_to_desc(type);
struct nmiaction *n;
@@ -155,61 +161,16 @@ static struct nmiaction *__free_nmi(unsigned int type, const char *name)
spin_unlock_irqrestore(&desc->lock, flags);
synchronize_rcu();
- return (n);
}
-
-int register_nmi_handler(unsigned int type, nmi_handler_t handler,
- unsigned long nmiflags, const char *devname)
-{
- struct nmiaction *action;
- int retval = -ENOMEM;
-
- if (!handler)
- return -EINVAL;
-
- action = kzalloc(sizeof(struct nmiaction), GFP_KERNEL);
- if (!action)
- goto fail_action;
-
- action->handler = handler;
- action->flags = nmiflags;
- action->name = kstrndup(devname, NMI_MAX_NAMELEN, GFP_KERNEL);
- if (!action->name)
- goto fail_action_name;
-
- retval = __setup_nmi(type, action);
-
- if (retval)
- goto fail_setup_nmi;
-
- return retval;
-
-fail_setup_nmi:
- kfree(action->name);
-fail_action_name:
- kfree(action);
-fail_action:
-
- return retval;
-}
-EXPORT_SYMBOL_GPL(register_nmi_handler);
-
-void unregister_nmi_handler(unsigned int type, const char *name)
-{
- struct nmiaction *a;
-
- a = __free_nmi(type, name);
- if (a) {
- kfree(a->name);
- kfree(a);
- }
-}
-
EXPORT_SYMBOL_GPL(unregister_nmi_handler);
-static notrace __kprobes void
+static __kprobes void
pci_serr_error(unsigned char reason, struct pt_regs *regs)
{
+ /* check to see if anyone registered against these types of errors */
+ if (nmi_handle(NMI_SERR, regs, false))
+ return;
+
pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n",
reason, smp_processor_id());
@@ -234,15 +195,19 @@ pci_serr_error(unsigned char reason, struct pt_regs *regs)
outb(reason, NMI_REASON_PORT);
}
-static notrace __kprobes void
+static __kprobes void
io_check_error(unsigned char reason, struct pt_regs *regs)
{
unsigned long i;
+ /* check to see if anyone registered against these types of errors */
+ if (nmi_handle(NMI_IO_CHECK, regs, false))
+ return;
+
pr_emerg(
"NMI: IOCK error (debug interrupt?) for reason %02x on CPU %d.\n",
reason, smp_processor_id());
- show_registers(regs);
+ show_regs(regs);
if (panic_on_io_nmi)
panic("NMI IOCK error: Not continuing");
@@ -261,7 +226,7 @@ io_check_error(unsigned char reason, struct pt_regs *regs)
outb(reason, NMI_REASON_PORT);
}
-static notrace __kprobes void
+static __kprobes void
unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
{
int handled;
@@ -293,7 +258,7 @@ unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
static DEFINE_PER_CPU(bool, swallow_nmi);
static DEFINE_PER_CPU(unsigned long, last_nmi_rip);
-static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+static __kprobes void default_do_nmi(struct pt_regs *regs)
{
unsigned char reason = 0;
int handled;
diff --git a/arch/x86/kernel/nmi_selftest.c b/arch/x86/kernel/nmi_selftest.c
index 2c39dcd510fa..e31bf8d5c4d2 100644
--- a/arch/x86/kernel/nmi_selftest.c
+++ b/arch/x86/kernel/nmi_selftest.c
@@ -13,6 +13,7 @@
#include <linux/cpumask.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/percpu.h>
#include <asm/apic.h>
#include <asm/nmi.h>
@@ -117,15 +118,15 @@ static void __init dotest(void (*testcase_fn)(void), int expected)
unexpected_testcase_failures++;
if (nmi_fail == FAILURE)
- printk("FAILED |");
+ printk(KERN_CONT "FAILED |");
else if (nmi_fail == TIMEOUT)
- printk("TIMEOUT|");
+ printk(KERN_CONT "TIMEOUT|");
else
- printk("ERROR |");
+ printk(KERN_CONT "ERROR |");
dump_stack();
} else {
testcase_successes++;
- printk(" ok |");
+ printk(KERN_CONT " ok |");
}
testcase_total++;
@@ -150,10 +151,10 @@ void __init nmi_selftest(void)
print_testname("remote IPI");
dotest(remote_ipi, SUCCESS);
- printk("\n");
+ printk(KERN_CONT "\n");
print_testname("local IPI");
dotest(local_ipi, SUCCESS);
- printk("\n");
+ printk(KERN_CONT "\n");
cleanup_nmi_testsuite();
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index ab137605e694..9ce885996fd7 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -241,16 +241,16 @@ static DEFINE_PER_CPU(enum paravirt_lazy_mode, paravirt_lazy_mode) = PARAVIRT_LA
static inline void enter_lazy(enum paravirt_lazy_mode mode)
{
- BUG_ON(percpu_read(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
+ BUG_ON(this_cpu_read(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
- percpu_write(paravirt_lazy_mode, mode);
+ this_cpu_write(paravirt_lazy_mode, mode);
}
static void leave_lazy(enum paravirt_lazy_mode mode)
{
- BUG_ON(percpu_read(paravirt_lazy_mode) != mode);
+ BUG_ON(this_cpu_read(paravirt_lazy_mode) != mode);
- percpu_write(paravirt_lazy_mode, PARAVIRT_LAZY_NONE);
+ this_cpu_write(paravirt_lazy_mode, PARAVIRT_LAZY_NONE);
}
void paravirt_enter_lazy_mmu(void)
@@ -267,7 +267,7 @@ void paravirt_start_context_switch(struct task_struct *prev)
{
BUG_ON(preemptible());
- if (percpu_read(paravirt_lazy_mode) == PARAVIRT_LAZY_MMU) {
+ if (this_cpu_read(paravirt_lazy_mode) == PARAVIRT_LAZY_MMU) {
arch_leave_lazy_mmu_mode();
set_ti_thread_flag(task_thread_info(prev), TIF_LAZY_MMU_UPDATES);
}
@@ -289,7 +289,7 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
if (in_interrupt())
return PARAVIRT_LAZY_NONE;
- return percpu_read(paravirt_lazy_mode);
+ return this_cpu_read(paravirt_lazy_mode);
}
void arch_flush_lazy_mmu_mode(void)
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index d0b2fb9ccbb1..b72838bae64a 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -1480,8 +1480,9 @@ cleanup:
static int __init calgary_parse_options(char *p)
{
unsigned int bridge;
+ unsigned long val;
size_t len;
- char* endp;
+ ssize_t ret;
while (*p) {
if (!strncmp(p, "64k", 3))
@@ -1512,10 +1513,11 @@ static int __init calgary_parse_options(char *p)
++p;
if (*p == '\0')
break;
- bridge = simple_strtoul(p, &endp, 0);
- if (p == endp)
+ ret = kstrtoul(p, 0, &val);
+ if (ret)
break;
+ bridge = val;
if (bridge < MAX_PHB_BUS_NUM) {
printk(KERN_INFO "Calgary: disabling "
"translation for PHB %#x\n", bridge);
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 1d92a5ab6e8b..735279e54e59 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -27,6 +27,15 @@
#include <asm/debugreg.h>
#include <asm/nmi.h>
+/*
+ * per-CPU TSS segments. Threads are completely 'soft' on Linux,
+ * no more per-task TSS's. The TSS size is kept cacheline-aligned
+ * so they are allowed to end up in the .data..cacheline_aligned
+ * section. Since TSS's are completely CPU-local, we want them
+ * on exact cacheline boundaries, to eliminate cacheline ping-pong.
+ */
+DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS;
+
#ifdef CONFIG_X86_64
static DEFINE_PER_CPU(unsigned char, is_idle);
static ATOMIC_NOTIFIER_HEAD(idle_notifier);
@@ -47,10 +56,16 @@ EXPORT_SYMBOL_GPL(idle_notifier_unregister);
struct kmem_cache *task_xstate_cachep;
EXPORT_SYMBOL_GPL(task_xstate_cachep);
+/*
+ * this gets called so that we can store lazy state into memory and copy the
+ * current task into the new thread.
+ */
int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
int ret;
+ unlazy_fpu(src);
+
*dst = *src;
if (fpu_allocated(&src->thread.fpu)) {
memset(&dst->thread.fpu, 0, sizeof(dst->thread.fpu));
@@ -67,10 +82,9 @@ void free_thread_xstate(struct task_struct *tsk)
fpu_free(&tsk->thread.fpu);
}
-void free_thread_info(struct thread_info *ti)
+void arch_release_task_struct(struct task_struct *tsk)
{
- free_thread_xstate(ti->task);
- free_pages((unsigned long)ti, THREAD_ORDER);
+ free_thread_xstate(tsk);
}
void arch_task_cache_init(void)
@@ -81,6 +95,16 @@ void arch_task_cache_init(void)
SLAB_PANIC | SLAB_NOTRACK, NULL);
}
+static inline void drop_fpu(struct task_struct *tsk)
+{
+ /*
+ * Forget coprocessor state..
+ */
+ tsk->fpu_counter = 0;
+ clear_fpu(tsk);
+ clear_used_math();
+}
+
/*
* Free current thread data structures etc..
*/
@@ -103,12 +127,8 @@ void exit_thread(void)
put_cpu();
kfree(bp);
}
-}
-void show_regs(struct pt_regs *regs)
-{
- show_registers(regs);
- show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs), 0);
+ drop_fpu(me);
}
void show_regs_common(void)
@@ -143,12 +163,7 @@ void flush_thread(void)
flush_ptrace_hw_breakpoint(tsk);
memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
- /*
- * Forget coprocessor state..
- */
- tsk->fpu_counter = 0;
- clear_fpu(tsk);
- clear_used_math();
+ drop_fpu(tsk);
}
static void hard_disable_TSC(void)
@@ -377,7 +392,7 @@ static inline void play_dead(void)
#ifdef CONFIG_X86_64
void enter_idle(void)
{
- percpu_write(is_idle, 1);
+ this_cpu_write(is_idle, 1);
atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
}
@@ -516,26 +531,6 @@ void stop_this_cpu(void *dummy)
}
}
-static void do_nothing(void *unused)
-{
-}
-
-/*
- * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
- * pm_idle and update to new pm_idle value. Required while changing pm_idle
- * handler on SMP systems.
- *
- * Caller must have changed pm_idle to the new value before the call. Old
- * pm_idle value will not be used by any CPU after the return of this function.
- */
-void cpu_idle_wait(void)
-{
- smp_mb();
- /* kick all the CPUs so that they exit out of pm_idle */
- smp_call_function(do_nothing, NULL, 1);
-}
-EXPORT_SYMBOL_GPL(cpu_idle_wait);
-
/* Default MONITOR/MWAIT with no hints, used for default C1 state */
static void mwait_idle(void)
{
@@ -594,9 +589,17 @@ int mwait_usable(const struct cpuinfo_x86 *c)
{
u32 eax, ebx, ecx, edx;
+ /* Use mwait if idle=mwait boot option is given */
if (boot_option_idle_override == IDLE_FORCE_MWAIT)
return 1;
+ /*
+ * Any idle= boot option other than idle=mwait means that we must not
+ * use mwait. Eg: idle=halt or idle=poll or idle=nomwait
+ */
+ if (boot_option_idle_override != IDLE_NO_OVERRIDE)
+ return 0;
+
if (c->cpuid_level < MWAIT_INFO)
return 0;
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index ae6847303e26..516fa186121b 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -126,15 +126,6 @@ void release_thread(struct task_struct *dead_task)
release_vm86_irqs(dead_task);
}
-/*
- * This gets called before we allocate a new thread and copy
- * the current task into it.
- */
-void prepare_to_copy(struct task_struct *tsk)
-{
- unlazy_fpu(tsk);
-}
-
int copy_thread(unsigned long clone_flags, unsigned long sp,
unsigned long unused,
struct task_struct *p, struct pt_regs *regs)
@@ -302,7 +293,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
switch_fpu_finish(next_p, fpu);
- percpu_write(current_task, next_p);
+ this_cpu_write(current_task, next_p);
return prev_p;
}
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 43d8b48b23e6..61cdf7fdf099 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -145,15 +145,6 @@ static inline u32 read_32bit_tls(struct task_struct *t, int tls)
return get_desc_base(&t->thread.tls_array[tls]);
}
-/*
- * This gets called before we allocate a new thread and copy
- * the current task into it.
- */
-void prepare_to_copy(struct task_struct *tsk)
-{
- unlazy_fpu(tsk);
-}
-
int copy_thread(unsigned long clone_flags, unsigned long sp,
unsigned long unused,
struct task_struct *p, struct pt_regs *regs)
@@ -237,7 +228,7 @@ start_thread_common(struct pt_regs *regs, unsigned long new_ip,
current->thread.usersp = new_sp;
regs->ip = new_ip;
regs->sp = new_sp;
- percpu_write(old_rsp, new_sp);
+ this_cpu_write(old_rsp, new_sp);
regs->cs = _cs;
regs->ss = _ss;
regs->flags = X86_EFLAGS_IF;
@@ -359,11 +350,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
/*
* Switch the PDA and FPU contexts.
*/
- prev->usersp = percpu_read(old_rsp);
- percpu_write(old_rsp, next->usersp);
- percpu_write(current_task, next_p);
+ prev->usersp = this_cpu_read(old_rsp);
+ this_cpu_write(old_rsp, next->usersp);
+ this_cpu_write(current_task, next_p);
- percpu_write(kernel_stack,
+ this_cpu_write(kernel_stack,
(unsigned long)task_stack_page(next_p) +
THREAD_SIZE - KERNEL_STACK_OFFSET);
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 685845cf16e0..13b1990c7c58 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -1480,7 +1480,11 @@ long syscall_trace_enter(struct pt_regs *regs)
regs->flags |= X86_EFLAGS_TF;
/* do the secure computing check first */
- secure_computing(regs->orig_ax);
+ if (secure_computing(regs->orig_ax)) {
+ /* seccomp failures shouldn't expose any additional code. */
+ ret = -1L;
+ goto out;
+ }
if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
ret = -1L;
@@ -1505,6 +1509,7 @@ long syscall_trace_enter(struct pt_regs *regs)
regs->dx, regs->r10);
#endif
+out:
return ret ?: regs->orig_ax;
}
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index d840e69a853c..77215c23fba1 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -39,7 +39,8 @@ static int reboot_mode;
enum reboot_type reboot_type = BOOT_ACPI;
int reboot_force;
-/* This variable is used privately to keep track of whether or not
+/*
+ * This variable is used privately to keep track of whether or not
* reboot_type is still set to its default value (i.e., reboot= hasn't
* been set on the command line). This is needed so that we can
* suppress DMI scanning for reboot quirks. Without it, it's
@@ -51,7 +52,8 @@ static int reboot_default = 1;
static int reboot_cpu = -1;
#endif
-/* This is set if we need to go through the 'emergency' path.
+/*
+ * This is set if we need to go through the 'emergency' path.
* When machine_emergency_restart() is called, we may be on
* an inconsistent state and won't be able to do a clean cleanup
*/
@@ -60,22 +62,24 @@ static int reboot_emergency;
/* This is set by the PCI code if either type 1 or type 2 PCI is detected */
bool port_cf9_safe = false;
-/* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci]
- warm Don't set the cold reboot flag
- cold Set the cold reboot flag
- bios Reboot by jumping through the BIOS (only for X86_32)
- smp Reboot by executing reset on BSP or other CPU (only for X86_32)
- triple Force a triple fault (init)
- kbd Use the keyboard controller. cold reset (default)
- acpi Use the RESET_REG in the FADT
- efi Use efi reset_system runtime service
- pci Use the so-called "PCI reset register", CF9
- force Avoid anything that could hang.
+/*
+ * reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci]
+ * warm Don't set the cold reboot flag
+ * cold Set the cold reboot flag
+ * bios Reboot by jumping through the BIOS (only for X86_32)
+ * smp Reboot by executing reset on BSP or other CPU (only for X86_32)
+ * triple Force a triple fault (init)
+ * kbd Use the keyboard controller. cold reset (default)
+ * acpi Use the RESET_REG in the FADT
+ * efi Use efi reset_system runtime service
+ * pci Use the so-called "PCI reset register", CF9
+ * force Avoid anything that could hang.
*/
static int __init reboot_setup(char *str)
{
for (;;) {
- /* Having anything passed on the command line via
+ /*
+ * Having anything passed on the command line via
* reboot= will cause us to disable DMI checking
* below.
*/
@@ -98,9 +102,11 @@ static int __init reboot_setup(char *str)
if (isdigit(*(str+2)))
reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0');
}
- /* we will leave sorting out the final value
- when we are ready to reboot, since we might not
- have detected BSP APIC ID or smp_num_cpu */
+ /*
+ * We will leave sorting out the final value
+ * when we are ready to reboot, since we might not
+ * have detected BSP APIC ID or smp_num_cpu
+ */
break;
#endif /* CONFIG_SMP */
@@ -150,6 +156,82 @@ static int __init set_bios_reboot(const struct dmi_system_id *d)
return 0;
}
+extern const unsigned char machine_real_restart_asm[];
+extern const u64 machine_real_restart_gdt[3];
+
+void machine_real_restart(unsigned int type)
+{
+ void *restart_va;
+ unsigned long restart_pa;
+ void (*restart_lowmem)(unsigned int);
+ u64 *lowmem_gdt;
+
+ local_irq_disable();
+
+ /*
+ * Write zero to CMOS register number 0x0f, which the BIOS POST
+ * routine will recognize as telling it to do a proper reboot. (Well
+ * that's what this book in front of me says -- it may only apply to
+ * the Phoenix BIOS though, it's not clear). At the same time,
+ * disable NMIs by setting the top bit in the CMOS address register,
+ * as we're about to do peculiar things to the CPU. I'm not sure if
+ * `outb_p' is needed instead of just `outb'. Use it to be on the
+ * safe side. (Yes, CMOS_WRITE does outb_p's. - Paul G.)
+ */
+ spin_lock(&rtc_lock);
+ CMOS_WRITE(0x00, 0x8f);
+ spin_unlock(&rtc_lock);
+
+ /*
+ * Switch back to the initial page table.
+ */
+ load_cr3(initial_page_table);
+
+ /*
+ * Write 0x1234 to absolute memory location 0x472. The BIOS reads
+ * this on booting to tell it to "Bypass memory test (also warm
+ * boot)". This seems like a fairly standard thing that gets set by
+ * REBOOT.COM programs, and the previous reset routine did this
+ * too. */
+ *((unsigned short *)0x472) = reboot_mode;
+
+ /* Patch the GDT in the low memory trampoline */
+ lowmem_gdt = TRAMPOLINE_SYM(machine_real_restart_gdt);
+
+ restart_va = TRAMPOLINE_SYM(machine_real_restart_asm);
+ restart_pa = virt_to_phys(restart_va);
+ restart_lowmem = (void (*)(unsigned int))restart_pa;
+
+ /* GDT[0]: GDT self-pointer */
+ lowmem_gdt[0] =
+ (u64)(sizeof(machine_real_restart_gdt) - 1) +
+ ((u64)virt_to_phys(lowmem_gdt) << 16);
+ /* GDT[1]: 64K real mode code segment */
+ lowmem_gdt[1] =
+ GDT_ENTRY(0x009b, restart_pa, 0xffff);
+
+ /* Jump to the identity-mapped low memory code */
+ restart_lowmem(type);
+}
+#ifdef CONFIG_APM_MODULE
+EXPORT_SYMBOL(machine_real_restart);
+#endif
+
+#endif /* CONFIG_X86_32 */
+
+/*
+ * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
+ */
+static int __init set_pci_reboot(const struct dmi_system_id *d)
+{
+ if (reboot_type != BOOT_CF9) {
+ reboot_type = BOOT_CF9;
+ printk(KERN_INFO "%s series board detected. "
+ "Selecting PCI-method for reboots.\n", d->ident);
+ }
+ return 0;
+}
+
static int __init set_kbd_reboot(const struct dmi_system_id *d)
{
if (reboot_type != BOOT_KBD) {
@@ -159,7 +241,12 @@ static int __init set_kbd_reboot(const struct dmi_system_id *d)
return 0;
}
+/*
+ * This is a single dmi_table handling all reboot quirks. Note that
+ * REBOOT_BIOS is only available for 32bit
+ */
static struct dmi_system_id __initdata reboot_dmi_table[] = {
+#ifdef CONFIG_X86_32
{ /* Handle problems with rebooting on Dell E520's */
.callback = set_bios_reboot,
.ident = "Dell E520",
@@ -184,7 +271,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
},
},
- { /* Handle problems with rebooting on Dell Optiplex 745's SFF*/
+ { /* Handle problems with rebooting on Dell Optiplex 745's SFF */
.callback = set_bios_reboot,
.ident = "Dell OptiPlex 745",
.matches = {
@@ -192,7 +279,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
},
},
- { /* Handle problems with rebooting on Dell Optiplex 745's DFF*/
+ { /* Handle problems with rebooting on Dell Optiplex 745's DFF */
.callback = set_bios_reboot,
.ident = "Dell OptiPlex 745",
.matches = {
@@ -201,7 +288,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "0MM599"),
},
},
- { /* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */
+ { /* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */
.callback = set_bios_reboot,
.ident = "Dell OptiPlex 745",
.matches = {
@@ -210,7 +297,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "0KW626"),
},
},
- { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */
+ { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */
.callback = set_bios_reboot,
.ident = "Dell OptiPlex 330",
.matches = {
@@ -219,7 +306,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "0KP561"),
},
},
- { /* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */
+ { /* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */
.callback = set_bios_reboot,
.ident = "Dell OptiPlex 360",
.matches = {
@@ -228,7 +315,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "0T656F"),
},
},
- { /* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G*/
+ { /* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G */
.callback = set_bios_reboot,
.ident = "Dell OptiPlex 760",
.matches = {
@@ -301,7 +388,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "SBC-FITPC2"),
},
},
- { /* Handle problems with rebooting on ASUS P4S800 */
+ { /* Handle problems with rebooting on ASUS P4S800 */
.callback = set_bios_reboot,
.ident = "ASUS P4S800",
.matches = {
@@ -309,7 +396,9 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
},
},
- { /* Handle reboot issue on Acer Aspire one */
+#endif /* CONFIG_X86_32 */
+
+ { /* Handle reboot issue on Acer Aspire one */
.callback = set_kbd_reboot,
.ident = "Acer Aspire One A110",
.matches = {
@@ -317,96 +406,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),
},
},
- { }
-};
-
-static int __init reboot_init(void)
-{
- /* Only do the DMI check if reboot_type hasn't been overridden
- * on the command line
- */
- if (reboot_default) {
- dmi_check_system(reboot_dmi_table);
- }
- return 0;
-}
-core_initcall(reboot_init);
-
-extern const unsigned char machine_real_restart_asm[];
-extern const u64 machine_real_restart_gdt[3];
-
-void machine_real_restart(unsigned int type)
-{
- void *restart_va;
- unsigned long restart_pa;
- void (*restart_lowmem)(unsigned int);
- u64 *lowmem_gdt;
-
- local_irq_disable();
-
- /* Write zero to CMOS register number 0x0f, which the BIOS POST
- routine will recognize as telling it to do a proper reboot. (Well
- that's what this book in front of me says -- it may only apply to
- the Phoenix BIOS though, it's not clear). At the same time,
- disable NMIs by setting the top bit in the CMOS address register,
- as we're about to do peculiar things to the CPU. I'm not sure if
- `outb_p' is needed instead of just `outb'. Use it to be on the
- safe side. (Yes, CMOS_WRITE does outb_p's. - Paul G.)
- */
- spin_lock(&rtc_lock);
- CMOS_WRITE(0x00, 0x8f);
- spin_unlock(&rtc_lock);
-
- /*
- * Switch back to the initial page table.
- */
- load_cr3(initial_page_table);
-
- /* Write 0x1234 to absolute memory location 0x472. The BIOS reads
- this on booting to tell it to "Bypass memory test (also warm
- boot)". This seems like a fairly standard thing that gets set by
- REBOOT.COM programs, and the previous reset routine did this
- too. */
- *((unsigned short *)0x472) = reboot_mode;
-
- /* Patch the GDT in the low memory trampoline */
- lowmem_gdt = TRAMPOLINE_SYM(machine_real_restart_gdt);
-
- restart_va = TRAMPOLINE_SYM(machine_real_restart_asm);
- restart_pa = virt_to_phys(restart_va);
- restart_lowmem = (void (*)(unsigned int))restart_pa;
-
- /* GDT[0]: GDT self-pointer */
- lowmem_gdt[0] =
- (u64)(sizeof(machine_real_restart_gdt) - 1) +
- ((u64)virt_to_phys(lowmem_gdt) << 16);
- /* GDT[1]: 64K real mode code segment */
- lowmem_gdt[1] =
- GDT_ENTRY(0x009b, restart_pa, 0xffff);
-
- /* Jump to the identity-mapped low memory code */
- restart_lowmem(type);
-}
-#ifdef CONFIG_APM_MODULE
-EXPORT_SYMBOL(machine_real_restart);
-#endif
-
-#endif /* CONFIG_X86_32 */
-
-/*
- * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
- */
-static int __init set_pci_reboot(const struct dmi_system_id *d)
-{
- if (reboot_type != BOOT_CF9) {
- reboot_type = BOOT_CF9;
- printk(KERN_INFO "%s series board detected. "
- "Selecting PCI-method for reboots.\n", d->ident);
- }
- return 0;
-}
-
-static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
{ /* Handle problems with rebooting on Apple MacBook5 */
.callback = set_pci_reboot,
.ident = "Apple MacBook5",
@@ -474,17 +473,17 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
{ }
};
-static int __init pci_reboot_init(void)
+static int __init reboot_init(void)
{
- /* Only do the DMI check if reboot_type hasn't been overridden
+ /*
+ * Only do the DMI check if reboot_type hasn't been overridden
* on the command line
*/
- if (reboot_default) {
- dmi_check_system(pci_reboot_dmi_table);
- }
+ if (reboot_default)
+ dmi_check_system(reboot_dmi_table);
return 0;
}
-core_initcall(pci_reboot_init);
+core_initcall(reboot_init);
static inline void kb_wait(void)
{
@@ -502,14 +501,14 @@ static void vmxoff_nmi(int cpu, struct pt_regs *regs)
cpu_emergency_vmxoff();
}
-/* Use NMIs as IPIs to tell all CPUs to disable virtualization
- */
+/* Use NMIs as IPIs to tell all CPUs to disable virtualization */
static void emergency_vmx_disable_all(void)
{
/* Just make sure we won't change CPUs while doing this */
local_irq_disable();
- /* We need to disable VMX on all CPUs before rebooting, otherwise
+ /*
+ * We need to disable VMX on all CPUs before rebooting, otherwise
* we risk hanging up the machine, because the CPU ignore INIT
* signals when VMX is enabled.
*
@@ -528,8 +527,7 @@ static void emergency_vmx_disable_all(void)
* is still enabling VMX.
*/
if (cpu_has_vmx() && cpu_vmx_enabled()) {
- /* Disable VMX on this CPU.
- */
+ /* Disable VMX on this CPU. */
cpu_vmxoff();
/* Halt and disable VMX on the other CPUs */
@@ -574,12 +572,12 @@ static void native_machine_emergency_restart(void)
/* Could also try the reset bit in the Hammer NB */
switch (reboot_type) {
case BOOT_KBD:
- mach_reboot_fixups(); /* for board specific fixups */
+ mach_reboot_fixups(); /* For board specific fixups */
for (i = 0; i < 10; i++) {
kb_wait();
udelay(50);
- outb(0xfe, 0x64); /* pulse reset low */
+ outb(0xfe, 0x64); /* Pulse reset low */
udelay(50);
}
if (attempt == 0 && orig_reboot_type == BOOT_ACPI) {
@@ -621,7 +619,7 @@ static void native_machine_emergency_restart(void)
case BOOT_CF9:
port_cf9_safe = true;
- /* fall through */
+ /* Fall through */
case BOOT_CF9_COND:
if (port_cf9_safe) {
@@ -659,7 +657,8 @@ void native_machine_shutdown(void)
/* Make certain I only run on the appropriate processor */
set_cpus_allowed_ptr(current, cpumask_of(reboot_cpu_id));
- /* O.K Now that I'm on the appropriate processor,
+ /*
+ * O.K Now that I'm on the appropriate processor,
* stop all of the others.
*/
stop_other_cpus();
@@ -697,12 +696,11 @@ static void native_machine_restart(char *__unused)
static void native_machine_halt(void)
{
- /* stop other cpus and apics */
+ /* Stop other cpus and apics */
machine_shutdown();
tboot_shutdown(TB_SHUTDOWN_HALT);
- /* stop this cpu */
stop_this_cpu(NULL);
}
@@ -713,7 +711,7 @@ static void native_machine_power_off(void)
machine_shutdown();
pm_power_off();
}
- /* a fallback in case there is no PM info available */
+ /* A fallback in case there is no PM info available */
tboot_shutdown(TB_SHUTDOWN_HALT);
}
@@ -775,7 +773,8 @@ static int crash_nmi_callback(unsigned int val, struct pt_regs *regs)
cpu = raw_smp_processor_id();
- /* Don't do anything if this handler is invoked on crashing cpu.
+ /*
+ * Don't do anything if this handler is invoked on crashing cpu.
* Otherwise, system will completely hang. Crashing cpu can get
* an NMI if system was initially booted with nmi_watchdog parameter.
*/
@@ -799,7 +798,8 @@ static void smp_send_nmi_allbutself(void)
apic->send_IPI_allbutself(NMI_VECTOR);
}
-/* Halt all other CPUs, calling the specified function on each of them
+/*
+ * Halt all other CPUs, calling the specified function on each of them
*
* This function can be used to halt all other CPUs on crash
* or emergency reboot time. The function passed as parameter
@@ -810,7 +810,7 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback)
unsigned long msecs;
local_irq_disable();
- /* Make a note of crashing cpu. Will be used in NMI callback.*/
+ /* Make a note of crashing cpu. Will be used in NMI callback. */
crashing_cpu = safe_smp_processor_id();
shootdown_callback = callback;
@@ -819,8 +819,9 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback)
/* Would it be better to replace the trap vector here? */
if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback,
NMI_FLAG_FIRST, "crash"))
- return; /* return what? */
- /* Ensure the new callback function is set before sending
+ return; /* Return what? */
+ /*
+ * Ensure the new callback function is set before sending
* out the NMI
*/
wmb();
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 879166402bf9..366c688d619e 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -386,10 +386,9 @@ static void __init reserve_initrd(void)
initrd_start = 0;
if (ramdisk_size >= (end_of_lowmem>>1)) {
- memblock_free(ramdisk_image, ramdisk_end - ramdisk_image);
- printk(KERN_ERR "initrd too large to handle, "
- "disabling initrd\n");
- return;
+ panic("initrd too large to handle, "
+ "disabling initrd (%lld needed, %lld available)\n",
+ ramdisk_size, end_of_lowmem>>1);
}
printk(KERN_INFO "RAMDISK: %08llx - %08llx\n", ramdisk_image,
@@ -1004,7 +1003,8 @@ void __init setup_arch(char **cmdline_p)
init_cpu_to_node();
init_apic_mappings();
- ioapic_and_gsi_init();
+ if (x86_io_apic_ops.init)
+ x86_io_apic_ops.init();
kvm_guest_init();
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index 66c74f481cab..48d2b7ded422 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -109,6 +109,9 @@
* about nothing of note with C stepping upwards.
*/
+static atomic_t stopping_cpu = ATOMIC_INIT(-1);
+static bool smp_no_nmi_ipi = false;
+
/*
* this function sends a 'reschedule' IPI to another CPU.
* it goes straight through and wastes no time serializing
@@ -149,8 +152,6 @@ void native_send_call_func_ipi(const struct cpumask *mask)
free_cpumask_var(allbutself);
}
-static atomic_t stopping_cpu = ATOMIC_INIT(-1);
-
static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs)
{
/* We are registered on stopping cpu too, avoid spurious NMI */
@@ -162,7 +163,19 @@ static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs)
return NMI_HANDLED;
}
-static void native_nmi_stop_other_cpus(int wait)
+/*
+ * this function calls the 'stop' function on all other CPUs in the system.
+ */
+
+asmlinkage void smp_reboot_interrupt(void)
+{
+ ack_APIC_irq();
+ irq_enter();
+ stop_this_cpu(NULL);
+ irq_exit();
+}
+
+static void native_stop_other_cpus(int wait)
{
unsigned long flags;
unsigned long timeout;
@@ -174,20 +187,25 @@ static void native_nmi_stop_other_cpus(int wait)
* Use an own vector here because smp_call_function
* does lots of things not suitable in a panic situation.
*/
+
+ /*
+ * We start by using the REBOOT_VECTOR irq.
+ * The irq is treated as a sync point to allow critical
+ * regions of code on other cpus to release their spin locks
+ * and re-enable irqs. Jumping straight to an NMI might
+ * accidentally cause deadlocks with further shutdown/panic
+ * code. By syncing, we give the cpus up to one second to
+ * finish their work before we force them off with the NMI.
+ */
if (num_online_cpus() > 1) {
/* did someone beat us here? */
if (atomic_cmpxchg(&stopping_cpu, -1, safe_smp_processor_id()) != -1)
return;
- if (register_nmi_handler(NMI_LOCAL, smp_stop_nmi_callback,
- NMI_FLAG_FIRST, "smp_stop"))
- /* Note: we ignore failures here */
- return;
-
- /* sync above data before sending NMI */
+ /* sync above data before sending IRQ */
wmb();
- apic->send_IPI_allbutself(NMI_VECTOR);
+ apic->send_IPI_allbutself(REBOOT_VECTOR);
/*
* Don't wait longer than a second if the caller
@@ -197,63 +215,37 @@ static void native_nmi_stop_other_cpus(int wait)
while (num_online_cpus() > 1 && (wait || timeout--))
udelay(1);
}
+
+ /* if the REBOOT_VECTOR didn't work, try with the NMI */
+ if ((num_online_cpus() > 1) && (!smp_no_nmi_ipi)) {
+ if (register_nmi_handler(NMI_LOCAL, smp_stop_nmi_callback,
+ NMI_FLAG_FIRST, "smp_stop"))
+ /* Note: we ignore failures here */
+ /* Hope the REBOOT_IRQ is good enough */
+ goto finish;
- local_irq_save(flags);
- disable_local_APIC();
- local_irq_restore(flags);
-}
-
-/*
- * this function calls the 'stop' function on all other CPUs in the system.
- */
-
-asmlinkage void smp_reboot_interrupt(void)
-{
- ack_APIC_irq();
- irq_enter();
- stop_this_cpu(NULL);
- irq_exit();
-}
-
-static void native_irq_stop_other_cpus(int wait)
-{
- unsigned long flags;
- unsigned long timeout;
+ /* sync above data before sending IRQ */
+ wmb();
- if (reboot_force)
- return;
+ pr_emerg("Shutting down cpus with NMI\n");
- /*
- * Use an own vector here because smp_call_function
- * does lots of things not suitable in a panic situation.
- * On most systems we could also use an NMI here,
- * but there are a few systems around where NMI
- * is problematic so stay with an non NMI for now
- * (this implies we cannot stop CPUs spinning with irq off
- * currently)
- */
- if (num_online_cpus() > 1) {
- apic->send_IPI_allbutself(REBOOT_VECTOR);
+ apic->send_IPI_allbutself(NMI_VECTOR);
/*
- * Don't wait longer than a second if the caller
+ * Don't wait longer than a 10 ms if the caller
* didn't ask us to wait.
*/
- timeout = USEC_PER_SEC;
+ timeout = USEC_PER_MSEC * 10;
while (num_online_cpus() > 1 && (wait || timeout--))
udelay(1);
}
+finish:
local_irq_save(flags);
disable_local_APIC();
local_irq_restore(flags);
}
-static void native_smp_disable_nmi_ipi(void)
-{
- smp_ops.stop_other_cpus = native_irq_stop_other_cpus;
-}
-
/*
* Reschedule call back.
*/
@@ -287,8 +279,8 @@ void smp_call_function_single_interrupt(struct pt_regs *regs)
static int __init nonmi_ipi_setup(char *str)
{
- native_smp_disable_nmi_ipi();
- return 1;
+ smp_no_nmi_ipi = true;
+ return 1;
}
__setup("nonmi_ipi", nonmi_ipi_setup);
@@ -298,7 +290,7 @@ struct smp_ops smp_ops = {
.smp_prepare_cpus = native_smp_prepare_cpus,
.smp_cpus_done = native_smp_cpus_done,
- .stop_other_cpus = native_nmi_stop_other_cpus,
+ .stop_other_cpus = native_stop_other_cpus,
.smp_send_reschedule = native_smp_send_reschedule,
.cpu_up = native_cpu_up,
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 6e1e406038c2..433529e29be4 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -76,20 +76,8 @@
/* State of each CPU */
DEFINE_PER_CPU(int, cpu_state) = { 0 };
-/* Store all idle threads, this can be reused instead of creating
-* a new thread. Also avoids complicated thread destroy functionality
-* for idle threads.
-*/
#ifdef CONFIG_HOTPLUG_CPU
/*
- * Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is
- * removed after init for !CONFIG_HOTPLUG_CPU.
- */
-static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
-#define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x))
-#define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p))
-
-/*
* We need this for trampoline_base protection from concurrent accesses when
* off- and onlining cores wildly.
*/
@@ -97,20 +85,16 @@ static DEFINE_MUTEX(x86_cpu_hotplug_driver_mutex);
void cpu_hotplug_driver_lock(void)
{
- mutex_lock(&x86_cpu_hotplug_driver_mutex);
+ mutex_lock(&x86_cpu_hotplug_driver_mutex);
}
void cpu_hotplug_driver_unlock(void)
{
- mutex_unlock(&x86_cpu_hotplug_driver_mutex);
+ mutex_unlock(&x86_cpu_hotplug_driver_mutex);
}
ssize_t arch_cpu_probe(const char *buf, size_t count) { return -1; }
ssize_t arch_cpu_release(const char *buf, size_t count) { return -1; }
-#else
-static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
-#define get_idle_for_cpu(x) (idle_thread_array[(x)])
-#define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p))
#endif
/* Number of siblings per CPU package */
@@ -315,59 +299,90 @@ void __cpuinit smp_store_cpu_info(int id)
identify_secondary_cpu(c);
}
-static void __cpuinit link_thread_siblings(int cpu1, int cpu2)
+static bool __cpuinit
+topology_sane(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o, const char *name)
{
- cpumask_set_cpu(cpu1, cpu_sibling_mask(cpu2));
- cpumask_set_cpu(cpu2, cpu_sibling_mask(cpu1));
- cpumask_set_cpu(cpu1, cpu_core_mask(cpu2));
- cpumask_set_cpu(cpu2, cpu_core_mask(cpu1));
- cpumask_set_cpu(cpu1, cpu_llc_shared_mask(cpu2));
- cpumask_set_cpu(cpu2, cpu_llc_shared_mask(cpu1));
+ int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
+
+ return !WARN_ONCE(cpu_to_node(cpu1) != cpu_to_node(cpu2),
+ "sched: CPU #%d's %s-sibling CPU #%d is not on the same node! "
+ "[node: %d != %d]. Ignoring dependency.\n",
+ cpu1, name, cpu2, cpu_to_node(cpu1), cpu_to_node(cpu2));
}
+#define link_mask(_m, c1, c2) \
+do { \
+ cpumask_set_cpu((c1), cpu_##_m##_mask(c2)); \
+ cpumask_set_cpu((c2), cpu_##_m##_mask(c1)); \
+} while (0)
+
+static bool __cpuinit match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
+{
+ if (cpu_has(c, X86_FEATURE_TOPOEXT)) {
+ int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
+
+ if (c->phys_proc_id == o->phys_proc_id &&
+ per_cpu(cpu_llc_id, cpu1) == per_cpu(cpu_llc_id, cpu2) &&
+ c->compute_unit_id == o->compute_unit_id)
+ return topology_sane(c, o, "smt");
+
+ } else if (c->phys_proc_id == o->phys_proc_id &&
+ c->cpu_core_id == o->cpu_core_id) {
+ return topology_sane(c, o, "smt");
+ }
+
+ return false;
+}
+
+static bool __cpuinit match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
+{
+ int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
+
+ if (per_cpu(cpu_llc_id, cpu1) != BAD_APICID &&
+ per_cpu(cpu_llc_id, cpu1) == per_cpu(cpu_llc_id, cpu2))
+ return topology_sane(c, o, "llc");
+
+ return false;
+}
+
+static bool __cpuinit match_mc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
+{
+ if (c->phys_proc_id == o->phys_proc_id)
+ return topology_sane(c, o, "mc");
+
+ return false;
+}
void __cpuinit set_cpu_sibling_map(int cpu)
{
- int i;
+ bool has_mc = boot_cpu_data.x86_max_cores > 1;
+ bool has_smt = smp_num_siblings > 1;
struct cpuinfo_x86 *c = &cpu_data(cpu);
+ struct cpuinfo_x86 *o;
+ int i;
cpumask_set_cpu(cpu, cpu_sibling_setup_mask);
- if (smp_num_siblings > 1) {
- for_each_cpu(i, cpu_sibling_setup_mask) {
- struct cpuinfo_x86 *o = &cpu_data(i);
-
- if (cpu_has(c, X86_FEATURE_TOPOEXT)) {
- if (c->phys_proc_id == o->phys_proc_id &&
- per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i) &&
- c->compute_unit_id == o->compute_unit_id)
- link_thread_siblings(cpu, i);
- } else if (c->phys_proc_id == o->phys_proc_id &&
- c->cpu_core_id == o->cpu_core_id) {
- link_thread_siblings(cpu, i);
- }
- }
- } else {
+ if (!has_smt && !has_mc) {
cpumask_set_cpu(cpu, cpu_sibling_mask(cpu));
- }
-
- cpumask_set_cpu(cpu, cpu_llc_shared_mask(cpu));
-
- if (__this_cpu_read(cpu_info.x86_max_cores) == 1) {
- cpumask_copy(cpu_core_mask(cpu), cpu_sibling_mask(cpu));
+ cpumask_set_cpu(cpu, cpu_llc_shared_mask(cpu));
+ cpumask_set_cpu(cpu, cpu_core_mask(cpu));
c->booted_cores = 1;
return;
}
for_each_cpu(i, cpu_sibling_setup_mask) {
- if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
- per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
- cpumask_set_cpu(i, cpu_llc_shared_mask(cpu));
- cpumask_set_cpu(cpu, cpu_llc_shared_mask(i));
- }
- if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
- cpumask_set_cpu(i, cpu_core_mask(cpu));
- cpumask_set_cpu(cpu, cpu_core_mask(i));
+ o = &cpu_data(i);
+
+ if ((i == cpu) || (has_smt && match_smt(c, o)))
+ link_mask(sibling, cpu, i);
+
+ if ((i == cpu) || (has_mc && match_llc(c, o)))
+ link_mask(llc_shared, cpu, i);
+
+ if ((i == cpu) || (has_mc && match_mc(c, o))) {
+ link_mask(core, cpu, i);
+
/*
* Does this new cpu bringup a new core?
*/
@@ -398,8 +413,7 @@ const struct cpumask *cpu_coregroup_mask(int cpu)
* For perf, we return last level cache shared map.
* And for power savings, we return cpu_core_map
*/
- if ((sched_mc_power_savings || sched_smt_power_savings) &&
- !(cpu_has(c, X86_FEATURE_AMD_DCM)))
+ if (!(cpu_has(c, X86_FEATURE_AMD_DCM)))
return cpu_core_mask(cpu);
else
return cpu_llc_shared_mask(cpu);
@@ -618,22 +632,6 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
return (send_status | accept_status);
}
-struct create_idle {
- struct work_struct work;
- struct task_struct *idle;
- struct completion done;
- int cpu;
-};
-
-static void __cpuinit do_fork_idle(struct work_struct *work)
-{
- struct create_idle *c_idle =
- container_of(work, struct create_idle, work);
-
- c_idle->idle = fork_idle(c_idle->cpu);
- complete(&c_idle->done);
-}
-
/* reduce the number of lines printed when booting a large cpu count system */
static void __cpuinit announce_cpu(int cpu, int apicid)
{
@@ -660,58 +658,31 @@ static void __cpuinit announce_cpu(int cpu, int apicid)
* Returns zero if CPU booted OK, else error code from
* ->wakeup_secondary_cpu.
*/
-static int __cpuinit do_boot_cpu(int apicid, int cpu)
+static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
{
unsigned long boot_error = 0;
unsigned long start_ip;
int timeout;
- struct create_idle c_idle = {
- .cpu = cpu,
- .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
- };
-
- INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle);
alternatives_smp_switch(1);
- c_idle.idle = get_idle_for_cpu(cpu);
-
- /*
- * We can't use kernel_thread since we must avoid to
- * reschedule the child.
- */
- if (c_idle.idle) {
- c_idle.idle->thread.sp = (unsigned long) (((struct pt_regs *)
- (THREAD_SIZE + task_stack_page(c_idle.idle))) - 1);
- init_idle(c_idle.idle, cpu);
- goto do_rest;
- }
-
- schedule_work(&c_idle.work);
- wait_for_completion(&c_idle.done);
+ idle->thread.sp = (unsigned long) (((struct pt_regs *)
+ (THREAD_SIZE + task_stack_page(idle))) - 1);
+ per_cpu(current_task, cpu) = idle;
- if (IS_ERR(c_idle.idle)) {
- printk("failed fork for CPU %d\n", cpu);
- destroy_work_on_stack(&c_idle.work);
- return PTR_ERR(c_idle.idle);
- }
-
- set_idle_for_cpu(cpu, c_idle.idle);
-do_rest:
- per_cpu(current_task, cpu) = c_idle.idle;
#ifdef CONFIG_X86_32
/* Stack for startup_32 can be just as for start_secondary onwards */
irq_ctx_init(cpu);
#else
- clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
+ clear_tsk_thread_flag(idle, TIF_FORK);
initial_gs = per_cpu_offset(cpu);
per_cpu(kernel_stack, cpu) =
- (unsigned long)task_stack_page(c_idle.idle) -
+ (unsigned long)task_stack_page(idle) -
KERNEL_STACK_OFFSET + THREAD_SIZE;
#endif
early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
initial_code = (unsigned long)start_secondary;
- stack_start = c_idle.idle->thread.sp;
+ stack_start = idle->thread.sp;
/* start_ip had better be page-aligned! */
start_ip = trampoline_address();
@@ -813,12 +784,10 @@ do_rest:
*/
smpboot_restore_warm_reset_vector();
}
-
- destroy_work_on_stack(&c_idle.work);
return boot_error;
}
-int __cpuinit native_cpu_up(unsigned int cpu)
+int __cpuinit native_cpu_up(unsigned int cpu, struct task_struct *tidle)
{
int apicid = apic->cpu_present_to_apicid(cpu);
unsigned long flags;
@@ -851,7 +820,7 @@ int __cpuinit native_cpu_up(unsigned int cpu)
per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
- err = do_boot_cpu(apicid, cpu);
+ err = do_boot_cpu(apicid, cpu, tidle);
if (err) {
pr_debug("do_boot_cpu failed %d\n", err);
return -EIO;
diff --git a/arch/x86/kernel/test_rodata.c b/arch/x86/kernel/test_rodata.c
index c29e235792af..b79133abda48 100644
--- a/arch/x86/kernel/test_rodata.c
+++ b/arch/x86/kernel/test_rodata.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <asm/cacheflush.h>
#include <asm/sections.h>
+#include <asm/asm.h>
int rodata_test(void)
{
@@ -42,14 +43,7 @@ int rodata_test(void)
".section .fixup,\"ax\"\n"
"2: jmp 1b\n"
".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 16\n"
-#ifdef CONFIG_X86_32
- " .long 0b,2b\n"
-#else
- " .quad 0b,2b\n"
-#endif
- ".previous"
+ _ASM_EXTABLE(0b,2b)
: [rslt] "=r" (result)
: [rodata_test] "r" (&rodata_test_data), [zero] "r" (0UL)
);
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 4754f510b360..ff08457a025d 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -46,6 +46,7 @@
#include <asm/processor.h>
#include <asm/debugreg.h>
#include <linux/atomic.h>
+#include <asm/ftrace.h>
#include <asm/traps.h>
#include <asm/desc.h>
#include <asm/i387.h>
@@ -299,8 +300,13 @@ gp_in_kernel:
}
/* May run on IST stack. */
-dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
+dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_code)
{
+#ifdef CONFIG_DYNAMIC_FTRACE
+ /* ftrace must be first, everything else may cause a recursive crash */
+ if (unlikely(modifying_ftrace_code) && ftrace_int3_handler(regs))
+ return;
+#endif
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
SIGTRAP) == NOTIFY_STOP)
diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c
index a1d804bcd483..8eeb55a551b4 100644
--- a/arch/x86/kernel/vsmp_64.c
+++ b/arch/x86/kernel/vsmp_64.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/pci_ids.h>
#include <linux/pci_regs.h>
+#include <linux/smp.h>
#include <asm/apic.h>
#include <asm/pci-direct.h>
@@ -22,6 +23,8 @@
#include <asm/paravirt.h>
#include <asm/setup.h>
+#define TOPOLOGY_REGISTER_OFFSET 0x10
+
#if defined CONFIG_PCI && defined CONFIG_PARAVIRT
/*
* Interrupt control on vSMPowered systems:
@@ -149,12 +152,49 @@ int is_vsmp_box(void)
return 0;
}
#endif
+
+static void __init vsmp_cap_cpus(void)
+{
+#if !defined(CONFIG_X86_VSMP) && defined(CONFIG_SMP)
+ void __iomem *address;
+ unsigned int cfg, topology, node_shift, maxcpus;
+
+ /*
+ * CONFIG_X86_VSMP is not configured, so limit the number CPUs to the
+ * ones present in the first board, unless explicitly overridden by
+ * setup_max_cpus
+ */
+ if (setup_max_cpus != NR_CPUS)
+ return;
+
+ /* Read the vSMP Foundation topology register */
+ cfg = read_pci_config(0, 0x1f, 0, PCI_BASE_ADDRESS_0);
+ address = early_ioremap(cfg + TOPOLOGY_REGISTER_OFFSET, 4);
+ if (WARN_ON(!address))
+ return;
+
+ topology = readl(address);
+ node_shift = (topology >> 16) & 0x7;
+ if (!node_shift)
+ /* The value 0 should be decoded as 8 */
+ node_shift = 8;
+ maxcpus = (topology & ((1 << node_shift) - 1)) + 1;
+
+ pr_info("vSMP CTL: Capping CPUs to %d (CONFIG_X86_VSMP is unset)\n",
+ maxcpus);
+ setup_max_cpus = maxcpus;
+ early_iounmap(address, 4);
+#endif
+}
+
void __init vsmp_init(void)
{
detect_vsmp_box();
if (!is_vsmp_box())
return;
+ vsmp_cap_cpus();
+
set_vsmp_pv_ops();
return;
}
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index 9cf71d0b2d37..35c5e543f550 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -18,6 +18,7 @@
#include <asm/e820.h>
#include <asm/time.h>
#include <asm/irq.h>
+#include <asm/io_apic.h>
#include <asm/pat.h>
#include <asm/tsc.h>
#include <asm/iommu.h>
@@ -119,3 +120,10 @@ struct x86_msi_ops x86_msi = {
.teardown_msi_irqs = default_teardown_msi_irqs,
.restore_msi_irqs = default_restore_msi_irqs,
};
+
+struct x86_io_apic_ops x86_io_apic_ops = {
+ .init = native_io_apic_init_mappings,
+ .read = native_io_apic_read,
+ .write = native_io_apic_write,
+ .modify = native_io_apic_modify,
+};
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index e62728e30b01..bd18149b2b0f 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -48,8 +48,6 @@ void __sanitize_i387_state(struct task_struct *tsk)
if (!fx)
return;
- BUG_ON(__thread_has_fpu(tsk));
-
xstate_bv = tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv;
/*
diff --git a/arch/x86/lib/checksum_32.S b/arch/x86/lib/checksum_32.S
index 78d16a554db0..2af5df3ade7c 100644
--- a/arch/x86/lib/checksum_32.S
+++ b/arch/x86/lib/checksum_32.S
@@ -28,6 +28,7 @@
#include <linux/linkage.h>
#include <asm/dwarf2.h>
#include <asm/errno.h>
+#include <asm/asm.h>
/*
* computes a partial checksum, e.g. for TCP/UDP fragments
@@ -282,15 +283,11 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst,
#define SRC(y...) \
9999: y; \
- .section __ex_table, "a"; \
- .long 9999b, 6001f ; \
- .previous
+ _ASM_EXTABLE(9999b, 6001f)
#define DST(y...) \
9999: y; \
- .section __ex_table, "a"; \
- .long 9999b, 6002f ; \
- .previous
+ _ASM_EXTABLE(9999b, 6002f)
#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
index 024840266ba0..5b2995f4557a 100644
--- a/arch/x86/lib/copy_user_64.S
+++ b/arch/x86/lib/copy_user_64.S
@@ -16,6 +16,7 @@
#include <asm/thread_info.h>
#include <asm/cpufeature.h>
#include <asm/alternative-asm.h>
+#include <asm/asm.h>
/*
* By placing feature2 after feature1 in altinstructions section, we logically
@@ -63,11 +64,8 @@
jmp copy_user_handle_tail
.previous
- .section __ex_table,"a"
- .align 8
- .quad 100b,103b
- .quad 101b,103b
- .previous
+ _ASM_EXTABLE(100b,103b)
+ _ASM_EXTABLE(101b,103b)
#endif
.endm
@@ -191,29 +189,26 @@ ENTRY(copy_user_generic_unrolled)
60: jmp copy_user_handle_tail /* ecx is zerorest also */
.previous
- .section __ex_table,"a"
- .align 8
- .quad 1b,30b
- .quad 2b,30b
- .quad 3b,30b
- .quad 4b,30b
- .quad 5b,30b
- .quad 6b,30b
- .quad 7b,30b
- .quad 8b,30b
- .quad 9b,30b
- .quad 10b,30b
- .quad 11b,30b
- .quad 12b,30b
- .quad 13b,30b
- .quad 14b,30b
- .quad 15b,30b
- .quad 16b,30b
- .quad 18b,40b
- .quad 19b,40b
- .quad 21b,50b
- .quad 22b,50b
- .previous
+ _ASM_EXTABLE(1b,30b)
+ _ASM_EXTABLE(2b,30b)
+ _ASM_EXTABLE(3b,30b)
+ _ASM_EXTABLE(4b,30b)
+ _ASM_EXTABLE(5b,30b)
+ _ASM_EXTABLE(6b,30b)
+ _ASM_EXTABLE(7b,30b)
+ _ASM_EXTABLE(8b,30b)
+ _ASM_EXTABLE(9b,30b)
+ _ASM_EXTABLE(10b,30b)
+ _ASM_EXTABLE(11b,30b)
+ _ASM_EXTABLE(12b,30b)
+ _ASM_EXTABLE(13b,30b)
+ _ASM_EXTABLE(14b,30b)
+ _ASM_EXTABLE(15b,30b)
+ _ASM_EXTABLE(16b,30b)
+ _ASM_EXTABLE(18b,40b)
+ _ASM_EXTABLE(19b,40b)
+ _ASM_EXTABLE(21b,50b)
+ _ASM_EXTABLE(22b,50b)
CFI_ENDPROC
ENDPROC(copy_user_generic_unrolled)
@@ -259,11 +254,8 @@ ENTRY(copy_user_generic_string)
jmp copy_user_handle_tail
.previous
- .section __ex_table,"a"
- .align 8
- .quad 1b,11b
- .quad 3b,12b
- .previous
+ _ASM_EXTABLE(1b,11b)
+ _ASM_EXTABLE(3b,12b)
CFI_ENDPROC
ENDPROC(copy_user_generic_string)
@@ -294,9 +286,6 @@ ENTRY(copy_user_enhanced_fast_string)
jmp copy_user_handle_tail
.previous
- .section __ex_table,"a"
- .align 8
- .quad 1b,12b
- .previous
+ _ASM_EXTABLE(1b,12b)
CFI_ENDPROC
ENDPROC(copy_user_enhanced_fast_string)
diff --git a/arch/x86/lib/copy_user_nocache_64.S b/arch/x86/lib/copy_user_nocache_64.S
index cb0c112386fb..cacddc7163eb 100644
--- a/arch/x86/lib/copy_user_nocache_64.S
+++ b/arch/x86/lib/copy_user_nocache_64.S
@@ -14,6 +14,7 @@
#include <asm/current.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
+#include <asm/asm.h>
.macro ALIGN_DESTINATION
#ifdef FIX_ALIGNMENT
@@ -36,11 +37,8 @@
jmp copy_user_handle_tail
.previous
- .section __ex_table,"a"
- .align 8
- .quad 100b,103b
- .quad 101b,103b
- .previous
+ _ASM_EXTABLE(100b,103b)
+ _ASM_EXTABLE(101b,103b)
#endif
.endm
@@ -111,27 +109,25 @@ ENTRY(__copy_user_nocache)
jmp copy_user_handle_tail
.previous
- .section __ex_table,"a"
- .quad 1b,30b
- .quad 2b,30b
- .quad 3b,30b
- .quad 4b,30b
- .quad 5b,30b
- .quad 6b,30b
- .quad 7b,30b
- .quad 8b,30b
- .quad 9b,30b
- .quad 10b,30b
- .quad 11b,30b
- .quad 12b,30b
- .quad 13b,30b
- .quad 14b,30b
- .quad 15b,30b
- .quad 16b,30b
- .quad 18b,40b
- .quad 19b,40b
- .quad 21b,50b
- .quad 22b,50b
- .previous
+ _ASM_EXTABLE(1b,30b)
+ _ASM_EXTABLE(2b,30b)
+ _ASM_EXTABLE(3b,30b)
+ _ASM_EXTABLE(4b,30b)
+ _ASM_EXTABLE(5b,30b)
+ _ASM_EXTABLE(6b,30b)
+ _ASM_EXTABLE(7b,30b)
+ _ASM_EXTABLE(8b,30b)
+ _ASM_EXTABLE(9b,30b)
+ _ASM_EXTABLE(10b,30b)
+ _ASM_EXTABLE(11b,30b)
+ _ASM_EXTABLE(12b,30b)
+ _ASM_EXTABLE(13b,30b)
+ _ASM_EXTABLE(14b,30b)
+ _ASM_EXTABLE(15b,30b)
+ _ASM_EXTABLE(16b,30b)
+ _ASM_EXTABLE(18b,40b)
+ _ASM_EXTABLE(19b,40b)
+ _ASM_EXTABLE(21b,50b)
+ _ASM_EXTABLE(22b,50b)
CFI_ENDPROC
ENDPROC(__copy_user_nocache)
diff --git a/arch/x86/lib/csum-copy_64.S b/arch/x86/lib/csum-copy_64.S
index fb903b758da8..2419d5fefae3 100644
--- a/arch/x86/lib/csum-copy_64.S
+++ b/arch/x86/lib/csum-copy_64.S
@@ -8,6 +8,7 @@
#include <linux/linkage.h>
#include <asm/dwarf2.h>
#include <asm/errno.h>
+#include <asm/asm.h>
/*
* Checksum copy with exception handling.
@@ -31,26 +32,17 @@
.macro source
10:
- .section __ex_table, "a"
- .align 8
- .quad 10b, .Lbad_source
- .previous
+ _ASM_EXTABLE(10b, .Lbad_source)
.endm
.macro dest
20:
- .section __ex_table, "a"
- .align 8
- .quad 20b, .Lbad_dest
- .previous
+ _ASM_EXTABLE(20b, .Lbad_dest)
.endm
.macro ignore L=.Lignore
30:
- .section __ex_table, "a"
- .align 8
- .quad 30b, \L
- .previous
+ _ASM_EXTABLE(30b, \L)
.endm
diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
index 51f1504cddd9..b33b1fb1e6d4 100644
--- a/arch/x86/lib/getuser.S
+++ b/arch/x86/lib/getuser.S
@@ -95,10 +95,9 @@ bad_get_user:
CFI_ENDPROC
END(bad_get_user)
-.section __ex_table,"a"
- _ASM_PTR 1b,bad_get_user
- _ASM_PTR 2b,bad_get_user
- _ASM_PTR 3b,bad_get_user
+ _ASM_EXTABLE(1b,bad_get_user)
+ _ASM_EXTABLE(2b,bad_get_user)
+ _ASM_EXTABLE(3b,bad_get_user)
#ifdef CONFIG_X86_64
- _ASM_PTR 4b,bad_get_user
+ _ASM_EXTABLE(4b,bad_get_user)
#endif
diff --git a/arch/x86/lib/putuser.S b/arch/x86/lib/putuser.S
index 36b0d15ae6e9..7f951c8f76c4 100644
--- a/arch/x86/lib/putuser.S
+++ b/arch/x86/lib/putuser.S
@@ -86,12 +86,10 @@ bad_put_user:
EXIT
END(bad_put_user)
-.section __ex_table,"a"
- _ASM_PTR 1b,bad_put_user
- _ASM_PTR 2b,bad_put_user
- _ASM_PTR 3b,bad_put_user
- _ASM_PTR 4b,bad_put_user
+ _ASM_EXTABLE(1b,bad_put_user)
+ _ASM_EXTABLE(2b,bad_put_user)
+ _ASM_EXTABLE(3b,bad_put_user)
+ _ASM_EXTABLE(4b,bad_put_user)
#ifdef CONFIG_X86_32
- _ASM_PTR 5b,bad_put_user
+ _ASM_EXTABLE(5b,bad_put_user)
#endif
-.previous
diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c
index d6ae30bbd7bb..2e4e4b02c37a 100644
--- a/arch/x86/lib/usercopy.c
+++ b/arch/x86/lib/usercopy.c
@@ -44,13 +44,6 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
}
EXPORT_SYMBOL_GPL(copy_from_user_nmi);
-static inline unsigned long count_bytes(unsigned long mask)
-{
- mask = (mask - 1) & ~mask;
- mask >>= 7;
- return count_masked_bytes(mask);
-}
-
/*
* Do a strncpy, return length of string without final '\0'.
* 'count' is the user-supplied count (return 'count' if we
@@ -69,16 +62,19 @@ static inline long do_strncpy_from_user(char *dst, const char __user *src, long
max = count;
while (max >= sizeof(unsigned long)) {
- unsigned long c;
+ unsigned long c, mask;
/* Fall back to byte-at-a-time if we get a page fault */
if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
break;
- /* This can write a few bytes past the NUL character, but that's ok */
+ mask = has_zero(c);
+ if (mask) {
+ mask = (mask - 1) & ~mask;
+ mask >>= 7;
+ *(unsigned long *)(dst+res) = c & mask;
+ return res + count_masked_bytes(mask);
+ }
*(unsigned long *)(dst+res) = c;
- c = has_zero(c);
- if (c)
- return res + count_bytes(c);
res += sizeof(unsigned long);
max -= sizeof(unsigned long);
}
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index ef2a6a5d78e3..883b216c60b2 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -13,6 +13,7 @@
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/mmx.h>
+#include <asm/asm.h>
#ifdef CONFIG_X86_INTEL_USERCOPY
/*
@@ -127,10 +128,7 @@ long strnlen_user(const char __user *s, long n)
"3: movb $1,%%al\n"
" jmp 1b\n"
".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,2b\n"
- ".previous"
+ _ASM_EXTABLE(0b,2b)
:"=&r" (n), "=&D" (s), "=&a" (res), "=&c" (tmp)
:"0" (n), "1" (s), "2" (0), "3" (mask)
:"cc");
@@ -199,47 +197,44 @@ __copy_user_intel(void __user *to, const void *from, unsigned long size)
"101: lea 0(%%eax,%0,4),%0\n"
" jmp 100b\n"
".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 1b,100b\n"
- " .long 2b,100b\n"
- " .long 3b,100b\n"
- " .long 4b,100b\n"
- " .long 5b,100b\n"
- " .long 6b,100b\n"
- " .long 7b,100b\n"
- " .long 8b,100b\n"
- " .long 9b,100b\n"
- " .long 10b,100b\n"
- " .long 11b,100b\n"
- " .long 12b,100b\n"
- " .long 13b,100b\n"
- " .long 14b,100b\n"
- " .long 15b,100b\n"
- " .long 16b,100b\n"
- " .long 17b,100b\n"
- " .long 18b,100b\n"
- " .long 19b,100b\n"
- " .long 20b,100b\n"
- " .long 21b,100b\n"
- " .long 22b,100b\n"
- " .long 23b,100b\n"
- " .long 24b,100b\n"
- " .long 25b,100b\n"
- " .long 26b,100b\n"
- " .long 27b,100b\n"
- " .long 28b,100b\n"
- " .long 29b,100b\n"
- " .long 30b,100b\n"
- " .long 31b,100b\n"
- " .long 32b,100b\n"
- " .long 33b,100b\n"
- " .long 34b,100b\n"
- " .long 35b,100b\n"
- " .long 36b,100b\n"
- " .long 37b,100b\n"
- " .long 99b,101b\n"
- ".previous"
+ _ASM_EXTABLE(1b,100b)
+ _ASM_EXTABLE(2b,100b)
+ _ASM_EXTABLE(3b,100b)
+ _ASM_EXTABLE(4b,100b)
+ _ASM_EXTABLE(5b,100b)
+ _ASM_EXTABLE(6b,100b)
+ _ASM_EXTABLE(7b,100b)
+ _ASM_EXTABLE(8b,100b)
+ _ASM_EXTABLE(9b,100b)
+ _ASM_EXTABLE(10b,100b)
+ _ASM_EXTABLE(11b,100b)
+ _ASM_EXTABLE(12b,100b)
+ _ASM_EXTABLE(13b,100b)
+ _ASM_EXTABLE(14b,100b)
+ _ASM_EXTABLE(15b,100b)
+ _ASM_EXTABLE(16b,100b)
+ _ASM_EXTABLE(17b,100b)
+ _ASM_EXTABLE(18b,100b)
+ _ASM_EXTABLE(19b,100b)
+ _ASM_EXTABLE(20b,100b)
+ _ASM_EXTABLE(21b,100b)
+ _ASM_EXTABLE(22b,100b)
+ _ASM_EXTABLE(23b,100b)
+ _ASM_EXTABLE(24b,100b)
+ _ASM_EXTABLE(25b,100b)
+ _ASM_EXTABLE(26b,100b)
+ _ASM_EXTABLE(27b,100b)
+ _ASM_EXTABLE(28b,100b)
+ _ASM_EXTABLE(29b,100b)
+ _ASM_EXTABLE(30b,100b)
+ _ASM_EXTABLE(31b,100b)
+ _ASM_EXTABLE(32b,100b)
+ _ASM_EXTABLE(33b,100b)
+ _ASM_EXTABLE(34b,100b)
+ _ASM_EXTABLE(35b,100b)
+ _ASM_EXTABLE(36b,100b)
+ _ASM_EXTABLE(37b,100b)
+ _ASM_EXTABLE(99b,101b)
: "=&c"(size), "=&D" (d0), "=&S" (d1)
: "1"(to), "2"(from), "0"(size)
: "eax", "edx", "memory");
@@ -312,29 +307,26 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size)
" popl %0\n"
" jmp 8b\n"
".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,16b\n"
- " .long 1b,16b\n"
- " .long 2b,16b\n"
- " .long 21b,16b\n"
- " .long 3b,16b\n"
- " .long 31b,16b\n"
- " .long 4b,16b\n"
- " .long 41b,16b\n"
- " .long 10b,16b\n"
- " .long 51b,16b\n"
- " .long 11b,16b\n"
- " .long 61b,16b\n"
- " .long 12b,16b\n"
- " .long 71b,16b\n"
- " .long 13b,16b\n"
- " .long 81b,16b\n"
- " .long 14b,16b\n"
- " .long 91b,16b\n"
- " .long 6b,9b\n"
- " .long 7b,16b\n"
- ".previous"
+ _ASM_EXTABLE(0b,16b)
+ _ASM_EXTABLE(1b,16b)
+ _ASM_EXTABLE(2b,16b)
+ _ASM_EXTABLE(21b,16b)
+ _ASM_EXTABLE(3b,16b)
+ _ASM_EXTABLE(31b,16b)
+ _ASM_EXTABLE(4b,16b)
+ _ASM_EXTABLE(41b,16b)
+ _ASM_EXTABLE(10b,16b)
+ _ASM_EXTABLE(51b,16b)
+ _ASM_EXTABLE(11b,16b)
+ _ASM_EXTABLE(61b,16b)
+ _ASM_EXTABLE(12b,16b)
+ _ASM_EXTABLE(71b,16b)
+ _ASM_EXTABLE(13b,16b)
+ _ASM_EXTABLE(81b,16b)
+ _ASM_EXTABLE(14b,16b)
+ _ASM_EXTABLE(91b,16b)
+ _ASM_EXTABLE(6b,9b)
+ _ASM_EXTABLE(7b,16b)
: "=&c"(size), "=&D" (d0), "=&S" (d1)
: "1"(to), "2"(from), "0"(size)
: "eax", "edx", "memory");
@@ -414,29 +406,26 @@ static unsigned long __copy_user_zeroing_intel_nocache(void *to,
" popl %0\n"
" jmp 8b\n"
".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,16b\n"
- " .long 1b,16b\n"
- " .long 2b,16b\n"
- " .long 21b,16b\n"
- " .long 3b,16b\n"
- " .long 31b,16b\n"
- " .long 4b,16b\n"
- " .long 41b,16b\n"
- " .long 10b,16b\n"
- " .long 51b,16b\n"
- " .long 11b,16b\n"
- " .long 61b,16b\n"
- " .long 12b,16b\n"
- " .long 71b,16b\n"
- " .long 13b,16b\n"
- " .long 81b,16b\n"
- " .long 14b,16b\n"
- " .long 91b,16b\n"
- " .long 6b,9b\n"
- " .long 7b,16b\n"
- ".previous"
+ _ASM_EXTABLE(0b,16b)
+ _ASM_EXTABLE(1b,16b)
+ _ASM_EXTABLE(2b,16b)
+ _ASM_EXTABLE(21b,16b)
+ _ASM_EXTABLE(3b,16b)
+ _ASM_EXTABLE(31b,16b)
+ _ASM_EXTABLE(4b,16b)
+ _ASM_EXTABLE(41b,16b)
+ _ASM_EXTABLE(10b,16b)
+ _ASM_EXTABLE(51b,16b)
+ _ASM_EXTABLE(11b,16b)
+ _ASM_EXTABLE(61b,16b)
+ _ASM_EXTABLE(12b,16b)
+ _ASM_EXTABLE(71b,16b)
+ _ASM_EXTABLE(13b,16b)
+ _ASM_EXTABLE(81b,16b)
+ _ASM_EXTABLE(14b,16b)
+ _ASM_EXTABLE(91b,16b)
+ _ASM_EXTABLE(6b,9b)
+ _ASM_EXTABLE(7b,16b)
: "=&c"(size), "=&D" (d0), "=&S" (d1)
: "1"(to), "2"(from), "0"(size)
: "eax", "edx", "memory");
@@ -505,29 +494,26 @@ static unsigned long __copy_user_intel_nocache(void *to,
"9: lea 0(%%eax,%0,4),%0\n"
"16: jmp 8b\n"
".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,16b\n"
- " .long 1b,16b\n"
- " .long 2b,16b\n"
- " .long 21b,16b\n"
- " .long 3b,16b\n"
- " .long 31b,16b\n"
- " .long 4b,16b\n"
- " .long 41b,16b\n"
- " .long 10b,16b\n"
- " .long 51b,16b\n"
- " .long 11b,16b\n"
- " .long 61b,16b\n"
- " .long 12b,16b\n"
- " .long 71b,16b\n"
- " .long 13b,16b\n"
- " .long 81b,16b\n"
- " .long 14b,16b\n"
- " .long 91b,16b\n"
- " .long 6b,9b\n"
- " .long 7b,16b\n"
- ".previous"
+ _ASM_EXTABLE(0b,16b)
+ _ASM_EXTABLE(1b,16b)
+ _ASM_EXTABLE(2b,16b)
+ _ASM_EXTABLE(21b,16b)
+ _ASM_EXTABLE(3b,16b)
+ _ASM_EXTABLE(31b,16b)
+ _ASM_EXTABLE(4b,16b)
+ _ASM_EXTABLE(41b,16b)
+ _ASM_EXTABLE(10b,16b)
+ _ASM_EXTABLE(51b,16b)
+ _ASM_EXTABLE(11b,16b)
+ _ASM_EXTABLE(61b,16b)
+ _ASM_EXTABLE(12b,16b)
+ _ASM_EXTABLE(71b,16b)
+ _ASM_EXTABLE(13b,16b)
+ _ASM_EXTABLE(81b,16b)
+ _ASM_EXTABLE(14b,16b)
+ _ASM_EXTABLE(91b,16b)
+ _ASM_EXTABLE(6b,9b)
+ _ASM_EXTABLE(7b,16b)
: "=&c"(size), "=&D" (d0), "=&S" (d1)
: "1"(to), "2"(from), "0"(size)
: "eax", "edx", "memory");
@@ -574,12 +560,9 @@ do { \
"3: lea 0(%3,%0,4),%0\n" \
" jmp 2b\n" \
".previous\n" \
- ".section __ex_table,\"a\"\n" \
- " .align 4\n" \
- " .long 4b,5b\n" \
- " .long 0b,3b\n" \
- " .long 1b,2b\n" \
- ".previous" \
+ _ASM_EXTABLE(4b,5b) \
+ _ASM_EXTABLE(0b,3b) \
+ _ASM_EXTABLE(1b,2b) \
: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \
: "3"(size), "0"(size), "1"(to), "2"(from) \
: "memory"); \
@@ -616,12 +599,9 @@ do { \
" popl %0\n" \
" jmp 2b\n" \
".previous\n" \
- ".section __ex_table,\"a\"\n" \
- " .align 4\n" \
- " .long 4b,5b\n" \
- " .long 0b,3b\n" \
- " .long 1b,6b\n" \
- ".previous" \
+ _ASM_EXTABLE(4b,5b) \
+ _ASM_EXTABLE(0b,3b) \
+ _ASM_EXTABLE(1b,6b) \
: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \
: "3"(size), "0"(size), "1"(to), "2"(from) \
: "memory"); \
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 1fb85dbe390a..903ec1e9c326 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -1,11 +1,23 @@
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/sort.h>
#include <asm/uaccess.h>
+static inline unsigned long
+ex_insn_addr(const struct exception_table_entry *x)
+{
+ return (unsigned long)&x->insn + x->insn;
+}
+static inline unsigned long
+ex_fixup_addr(const struct exception_table_entry *x)
+{
+ return (unsigned long)&x->fixup + x->fixup;
+}
int fixup_exception(struct pt_regs *regs)
{
const struct exception_table_entry *fixup;
+ unsigned long new_ip;
#ifdef CONFIG_PNPBIOS
if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) {
@@ -23,15 +35,135 @@ int fixup_exception(struct pt_regs *regs)
fixup = search_exception_tables(regs->ip);
if (fixup) {
- /* If fixup is less than 16, it means uaccess error */
- if (fixup->fixup < 16) {
+ new_ip = ex_fixup_addr(fixup);
+
+ if (fixup->fixup - fixup->insn >= 0x7ffffff0 - 4) {
+ /* Special hack for uaccess_err */
current_thread_info()->uaccess_err = 1;
- regs->ip += fixup->fixup;
- return 1;
+ new_ip -= 0x7ffffff0;
}
- regs->ip = fixup->fixup;
+ regs->ip = new_ip;
return 1;
}
return 0;
}
+
+/* Restricted version used during very early boot */
+int __init early_fixup_exception(unsigned long *ip)
+{
+ const struct exception_table_entry *fixup;
+ unsigned long new_ip;
+
+ fixup = search_exception_tables(*ip);
+ if (fixup) {
+ new_ip = ex_fixup_addr(fixup);
+
+ if (fixup->fixup - fixup->insn >= 0x7ffffff0 - 4) {
+ /* uaccess handling not supported during early boot */
+ return 0;
+ }
+
+ *ip = new_ip;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Search one exception table for an entry corresponding to the
+ * given instruction address, and return the address of the entry,
+ * or NULL if none is found.
+ * We use a binary search, and thus we assume that the table is
+ * already sorted.
+ */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+ const struct exception_table_entry *last,
+ unsigned long value)
+{
+ while (first <= last) {
+ const struct exception_table_entry *mid;
+ unsigned long addr;
+
+ mid = ((last - first) >> 1) + first;
+ addr = ex_insn_addr(mid);
+ if (addr < value)
+ first = mid + 1;
+ else if (addr > value)
+ last = mid - 1;
+ else
+ return mid;
+ }
+ return NULL;
+}
+
+/*
+ * The exception table needs to be sorted so that the binary
+ * search that we use to find entries in it works properly.
+ * This is used both for the kernel exception table and for
+ * the exception tables of modules that get loaded.
+ *
+ */
+static int cmp_ex(const void *a, const void *b)
+{
+ const struct exception_table_entry *x = a, *y = b;
+
+ /*
+ * This value will always end up fittin in an int, because on
+ * both i386 and x86-64 the kernel symbol-reachable address
+ * space is < 2 GiB.
+ *
+ * This compare is only valid after normalization.
+ */
+ return x->insn - y->insn;
+}
+
+void sort_extable(struct exception_table_entry *start,
+ struct exception_table_entry *finish)
+{
+ struct exception_table_entry *p;
+ int i;
+
+ /* Convert all entries to being relative to the start of the section */
+ i = 0;
+ for (p = start; p < finish; p++) {
+ p->insn += i;
+ i += 4;
+ p->fixup += i;
+ i += 4;
+ }
+
+ sort(start, finish - start, sizeof(struct exception_table_entry),
+ cmp_ex, NULL);
+
+ /* Denormalize all entries */
+ i = 0;
+ for (p = start; p < finish; p++) {
+ p->insn -= i;
+ i += 4;
+ p->fixup -= i;
+ i += 4;
+ }
+}
+
+#ifdef CONFIG_MODULES
+/*
+ * If the exception table is sorted, any referring to the module init
+ * will be at the beginning or the end.
+ */
+void trim_init_extable(struct module *m)
+{
+ /*trim the beginning*/
+ while (m->num_exentries &&
+ within_module_init(ex_insn_addr(&m->extable[0]), m)) {
+ m->extable++;
+ m->num_exentries--;
+ }
+ /*trim the end*/
+ while (m->num_exentries &&
+ within_module_init(ex_insn_addr(&m->extable[m->num_exentries-1]), m))
+ m->num_exentries--;
+}
+#endif /* CONFIG_MODULES */
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 4f0cec7e4ffb..319b6f2fb8b9 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -29,8 +29,14 @@ int direct_gbpages
#endif
;
-static void __init find_early_table_space(unsigned long end, int use_pse,
- int use_gbpages)
+struct map_range {
+ unsigned long start;
+ unsigned long end;
+ unsigned page_size_mask;
+};
+
+static void __init find_early_table_space(struct map_range *mr, unsigned long end,
+ int use_pse, int use_gbpages)
{
unsigned long puds, pmds, ptes, tables, start = 0, good_end = end;
phys_addr_t base;
@@ -55,6 +61,9 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
#ifdef CONFIG_X86_32
extra += PMD_SIZE;
#endif
+ /* The first 2/4M doesn't use large pages. */
+ extra += mr->end - mr->start;
+
ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
} else
ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -84,12 +93,6 @@ void __init native_pagetable_reserve(u64 start, u64 end)
memblock_reserve(start, end - start);
}
-struct map_range {
- unsigned long start;
- unsigned long end;
- unsigned page_size_mask;
-};
-
#ifdef CONFIG_X86_32
#define NR_RANGE_MR 3
#else /* CONFIG_X86_64 */
@@ -261,7 +264,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
* nodes are discovered.
*/
if (!after_bootmem)
- find_early_table_space(end, use_pse, use_gbpages);
+ find_early_table_space(&mr[0], end, use_pse, use_gbpages);
for (i = 0; i < nr_range; i++)
ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index fc18be0f6f29..2b6b4a3c8beb 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -407,12 +407,12 @@ static unsigned long __meminit
phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
unsigned long page_size_mask, pgprot_t prot)
{
- unsigned long pages = 0;
+ unsigned long pages = 0, next;
unsigned long last_map_addr = end;
int i = pmd_index(address);
- for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) {
+ for (; i < PTRS_PER_PMD; i++, address = next) {
unsigned long pte_phys;
pmd_t *pmd = pmd_page + pmd_index(address);
pte_t *pte;
@@ -426,6 +426,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
break;
}
+ next = (address & PMD_MASK) + PMD_SIZE;
+
if (pmd_val(*pmd)) {
if (!pmd_large(*pmd)) {
spin_lock(&init_mm.page_table_lock);
@@ -449,7 +451,7 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
* attributes.
*/
if (page_size_mask & (1 << PG_LEVEL_2M)) {
- pages++;
+ last_map_addr = next;
continue;
}
new_prot = pte_pgprot(pte_clrhuge(*(pte_t *)pmd));
@@ -462,7 +464,7 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
pfn_pte(address >> PAGE_SHIFT,
__pgprot(pgprot_val(prot) | _PAGE_PSE)));
spin_unlock(&init_mm.page_table_lock);
- last_map_addr = (address & PMD_MASK) + PMD_SIZE;
+ last_map_addr = next;
continue;
}
@@ -482,11 +484,11 @@ static unsigned long __meminit
phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
unsigned long page_size_mask)
{
- unsigned long pages = 0;
+ unsigned long pages = 0, next;
unsigned long last_map_addr = end;
int i = pud_index(addr);
- for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE) {
+ for (; i < PTRS_PER_PUD; i++, addr = next) {
unsigned long pmd_phys;
pud_t *pud = pud_page + pud_index(addr);
pmd_t *pmd;
@@ -495,8 +497,9 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
if (addr >= end)
break;
- if (!after_bootmem &&
- !e820_any_mapped(addr, addr+PUD_SIZE, 0)) {
+ next = (addr & PUD_MASK) + PUD_SIZE;
+
+ if (!after_bootmem && !e820_any_mapped(addr, next, 0)) {
set_pud(pud, __pud(0));
continue;
}
@@ -523,7 +526,7 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
* attributes.
*/
if (page_size_mask & (1 << PG_LEVEL_1G)) {
- pages++;
+ last_map_addr = next;
continue;
}
prot = pte_pgprot(pte_clrhuge(*(pte_t *)pud));
@@ -535,7 +538,7 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
set_pte((pte_t *)pud,
pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
spin_unlock(&init_mm.page_table_lock);
- last_map_addr = (addr & PUD_MASK) + PUD_SIZE;
+ last_map_addr = next;
continue;
}
diff --git a/arch/x86/mm/numa_emulation.c b/arch/x86/mm/numa_emulation.c
index 53489ff6bf82..871dd8868170 100644
--- a/arch/x86/mm/numa_emulation.c
+++ b/arch/x86/mm/numa_emulation.c
@@ -339,9 +339,11 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
} else {
unsigned long n;
- n = simple_strtoul(emu_cmdline, NULL, 0);
+ n = simple_strtoul(emu_cmdline, &emu_cmdline, 0);
ret = split_nodes_interleave(&ei, &pi, 0, max_addr, n);
}
+ if (*emu_cmdline == ':')
+ emu_cmdline++;
if (ret < 0)
goto no_emu;
@@ -418,7 +420,9 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
int physj = emu_nid_to_phys[j];
int dist;
- if (physi >= numa_dist_cnt || physj >= numa_dist_cnt)
+ if (get_option(&emu_cmdline, &dist) == 2)
+ ;
+ else if (physi >= numa_dist_cnt || physj >= numa_dist_cnt)
dist = physi == physj ?
LOCAL_DISTANCE : REMOTE_DISTANCE;
else
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index d6c0418c3e47..5e57e113b72c 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -61,11 +61,13 @@ static DEFINE_PER_CPU_READ_MOSTLY(int, tlb_vector_offset);
*/
void leave_mm(int cpu)
{
- if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK)
+ struct mm_struct *active_mm = this_cpu_read(cpu_tlbstate.active_mm);
+ if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK)
BUG();
- cpumask_clear_cpu(cpu,
- mm_cpumask(percpu_read(cpu_tlbstate.active_mm)));
- load_cr3(swapper_pg_dir);
+ if (cpumask_test_cpu(cpu, mm_cpumask(active_mm))) {
+ cpumask_clear_cpu(cpu, mm_cpumask(active_mm));
+ load_cr3(swapper_pg_dir);
+ }
}
EXPORT_SYMBOL_GPL(leave_mm);
@@ -152,8 +154,8 @@ void smp_invalidate_interrupt(struct pt_regs *regs)
* BUG();
*/
- if (f->flush_mm == percpu_read(cpu_tlbstate.active_mm)) {
- if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
+ if (f->flush_mm == this_cpu_read(cpu_tlbstate.active_mm)) {
+ if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
if (f->flush_va == TLB_FLUSH_ALL)
local_flush_tlb();
else
@@ -322,7 +324,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
static void do_flush_tlb_all(void *info)
{
__flush_tlb_all();
- if (percpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY)
+ if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY)
leave_mm(smp_processor_id());
}
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
index e76e18c94a3c..3af5a1e79c9c 100644
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -11,6 +11,8 @@ obj-$(CONFIG_X86_INTEL_CE) += ce4100.o
obj-$(CONFIG_ACPI) += acpi.o
obj-y += legacy.o irq.o
+obj-$(CONFIG_STA2X11) += sta2x11-fixup.o
+
obj-$(CONFIG_X86_VISWS) += visws.o
obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index ed2835e148b5..fc09c2754e08 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -9,11 +9,11 @@
struct pci_root_info {
struct acpi_device *bridge;
- char *name;
+ char name[16];
unsigned int res_num;
struct resource *res;
- struct list_head *resources;
int busnum;
+ struct pci_sysdata sd;
};
static bool pci_use_crs = true;
@@ -245,13 +245,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
return AE_OK;
}
-static bool resource_contains(struct resource *res, resource_size_t point)
-{
- if (res->start <= point && point <= res->end)
- return true;
- return false;
-}
-
static void coalesce_windows(struct pci_root_info *info, unsigned long type)
{
int i, j;
@@ -272,10 +265,7 @@ static void coalesce_windows(struct pci_root_info *info, unsigned long type)
* our resources no longer match the ACPI _CRS, but
* the kernel resource tree doesn't allow overlaps.
*/
- if (resource_contains(res1, res2->start) ||
- resource_contains(res1, res2->end) ||
- resource_contains(res2, res1->start) ||
- resource_contains(res2, res1->end)) {
+ if (resource_overlaps(res1, res2)) {
res1->start = min(res1->start, res2->start);
res1->end = max(res1->end, res2->end);
dev_info(&info->bridge->dev,
@@ -287,7 +277,8 @@ static void coalesce_windows(struct pci_root_info *info, unsigned long type)
}
}
-static void add_resources(struct pci_root_info *info)
+static void add_resources(struct pci_root_info *info,
+ struct list_head *resources)
{
int i;
struct resource *res, *root, *conflict;
@@ -311,53 +302,74 @@ static void add_resources(struct pci_root_info *info)
"ignoring host bridge window %pR (conflicts with %s %pR)\n",
res, conflict->name, conflict);
else
- pci_add_resource(info->resources, res);
+ pci_add_resource(resources, res);
}
}
+static void free_pci_root_info_res(struct pci_root_info *info)
+{
+ kfree(info->res);
+ info->res = NULL;
+ info->res_num = 0;
+}
+
+static void __release_pci_root_info(struct pci_root_info *info)
+{
+ int i;
+ struct resource *res;
+
+ for (i = 0; i < info->res_num; i++) {
+ res = &info->res[i];
+
+ if (!res->parent)
+ continue;
+
+ if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
+ continue;
+
+ release_resource(res);
+ }
+
+ free_pci_root_info_res(info);
+
+ kfree(info);
+}
+static void release_pci_root_info(struct pci_host_bridge *bridge)
+{
+ struct pci_root_info *info = bridge->release_data;
+
+ __release_pci_root_info(info);
+}
+
static void
-get_current_resources(struct acpi_device *device, int busnum,
- int domain, struct list_head *resources)
+probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
+ int busnum, int domain)
{
- struct pci_root_info info;
size_t size;
- info.bridge = device;
- info.res_num = 0;
- info.resources = resources;
+ info->bridge = device;
+ info->res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
- &info);
- if (!info.res_num)
+ info);
+ if (!info->res_num)
return;
- size = sizeof(*info.res) * info.res_num;
- info.res = kmalloc(size, GFP_KERNEL);
- if (!info.res)
+ size = sizeof(*info->res) * info->res_num;
+ info->res_num = 0;
+ info->res = kmalloc(size, GFP_KERNEL);
+ if (!info->res)
return;
- info.name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum);
- if (!info.name)
- goto name_alloc_fail;
+ sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
- info.res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
- &info);
-
- if (pci_use_crs) {
- add_resources(&info);
-
- return;
- }
-
- kfree(info.name);
-
-name_alloc_fail:
- kfree(info.res);
+ info);
}
struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
{
struct acpi_device *device = root->device;
+ struct pci_root_info *info = NULL;
int domain = root->segment;
int busnum = root->secondary.start;
LIST_HEAD(resources);
@@ -389,17 +401,14 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
if (node != -1 && !node_online(node))
node = -1;
- /* Allocate per-root-bus (not per bus) arch-specific data.
- * TODO: leak; this memory is never freed.
- * It's arguable whether it's worth the trouble to care.
- */
- sd = kzalloc(sizeof(*sd), GFP_KERNEL);
- if (!sd) {
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
printk(KERN_WARNING "pci_bus %04x:%02x: "
"ignored (out of memory)\n", domain, busnum);
return NULL;
}
+ sd = &info->sd;
sd->domain = domain;
sd->node = node;
/*
@@ -413,22 +422,32 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
* be replaced by sd.
*/
memcpy(bus->sysdata, sd, sizeof(*sd));
- kfree(sd);
+ kfree(info);
} else {
- get_current_resources(device, busnum, domain, &resources);
+ probe_pci_root_info(info, device, busnum, domain);
/*
* _CRS with no apertures is normal, so only fall back to
* defaults or native bridge info if we're ignoring _CRS.
*/
- if (!pci_use_crs)
+ if (pci_use_crs)
+ add_resources(info, &resources);
+ else {
+ free_pci_root_info_res(info);
x86_pci_root_bus_resources(busnum, &resources);
+ }
+
bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
&resources);
- if (bus)
+ if (bus) {
bus->subordinate = pci_scan_child_bus(bus);
- else
+ pci_set_host_bridge_release(
+ to_pci_host_bridge(bus->bridge),
+ release_pci_root_info, info);
+ } else {
pci_free_resource_list(&resources);
+ __release_pci_root_info(info);
+ }
}
/* After the PCI-E bus has been walked and all devices discovered,
@@ -445,9 +464,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
}
}
- if (!bus)
- kfree(sd);
-
if (bus && node != -1) {
#ifdef CONFIG_ACPI_NUMA
if (pxm >= 0)
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 0567df3890e1..5aed49bff058 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -32,6 +32,27 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = {
#define RANGE_NUM 16
+static struct pci_root_info __init *find_pci_root_info(int node, int link)
+{
+ struct pci_root_info *info;
+
+ /* find the position */
+ list_for_each_entry(info, &pci_root_infos, list)
+ if (info->node == node && info->link == link)
+ return info;
+
+ return NULL;
+}
+
+static void __init set_mp_bus_range_to_node(int min_bus, int max_bus, int node)
+{
+#ifdef CONFIG_NUMA
+ int j;
+
+ for (j = min_bus; j <= max_bus; j++)
+ set_mp_bus_to_node(j, node);
+#endif
+}
/**
* early_fill_mp_bus_to_node()
* called before pcibios_scan_root and pci_scan_bus
@@ -41,7 +62,6 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = {
static int __init early_fill_mp_bus_info(void)
{
int i;
- int j;
unsigned bus;
unsigned slot;
int node;
@@ -50,7 +70,6 @@ static int __init early_fill_mp_bus_info(void)
int def_link;
struct pci_root_info *info;
u32 reg;
- struct resource *res;
u64 start;
u64 end;
struct range range[RANGE_NUM];
@@ -86,7 +105,6 @@ static int __init early_fill_mp_bus_info(void)
if (!found)
return 0;
- pci_root_num = 0;
for (i = 0; i < 4; i++) {
int min_bus;
int max_bus;
@@ -99,19 +117,11 @@ static int __init early_fill_mp_bus_info(void)
min_bus = (reg >> 16) & 0xff;
max_bus = (reg >> 24) & 0xff;
node = (reg >> 4) & 0x07;
-#ifdef CONFIG_NUMA
- for (j = min_bus; j <= max_bus; j++)
- set_mp_bus_to_node(j, node);
-#endif
+ set_mp_bus_range_to_node(min_bus, max_bus, node);
link = (reg >> 8) & 0x03;
- info = &pci_root_info[pci_root_num];
- info->bus_min = min_bus;
- info->bus_max = max_bus;
- info->node = node;
- info->link = link;
+ info = alloc_pci_root_info(min_bus, max_bus, node, link);
sprintf(info->name, "PCI Bus #%02x", min_bus);
- pci_root_num++;
}
/* get the default node and link for left over res */
@@ -134,16 +144,10 @@ static int __init early_fill_mp_bus_info(void)
link = (reg >> 4) & 0x03;
end = (reg & 0xfff000) | 0xfff;
- /* find the position */
- for (j = 0; j < pci_root_num; j++) {
- info = &pci_root_info[j];
- if (info->node == node && info->link == link)
- break;
- }
- if (j == pci_root_num)
+ info = find_pci_root_info(node, link);
+ if (!info)
continue; /* not found */
- info = &pci_root_info[j];
printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n",
node, link, start, end);
@@ -155,13 +159,8 @@ static int __init early_fill_mp_bus_info(void)
}
/* add left over io port range to def node/link, [0, 0xffff] */
/* find the position */
- for (j = 0; j < pci_root_num; j++) {
- info = &pci_root_info[j];
- if (info->node == def_node && info->link == def_link)
- break;
- }
- if (j < pci_root_num) {
- info = &pci_root_info[j];
+ info = find_pci_root_info(def_node, def_link);
+ if (info) {
for (i = 0; i < RANGE_NUM; i++) {
if (!range[i].end)
continue;
@@ -214,16 +213,10 @@ static int __init early_fill_mp_bus_info(void)
end <<= 8;
end |= 0xffff;
- /* find the position */
- for (j = 0; j < pci_root_num; j++) {
- info = &pci_root_info[j];
- if (info->node == node && info->link == link)
- break;
- }
- if (j == pci_root_num)
- continue; /* not found */
+ info = find_pci_root_info(node, link);
- info = &pci_root_info[j];
+ if (!info)
+ continue;
printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]",
node, link, start, end);
@@ -291,14 +284,8 @@ static int __init early_fill_mp_bus_info(void)
* add left over mmio range to def node/link ?
* that is tricky, just record range in from start_min to 4G
*/
- for (j = 0; j < pci_root_num; j++) {
- info = &pci_root_info[j];
- if (info->node == def_node && info->link == def_link)
- break;
- }
- if (j < pci_root_num) {
- info = &pci_root_info[j];
-
+ info = find_pci_root_info(def_node, def_link);
+ if (info) {
for (i = 0; i < RANGE_NUM; i++) {
if (!range[i].end)
continue;
@@ -309,20 +296,16 @@ static int __init early_fill_mp_bus_info(void)
}
}
- for (i = 0; i < pci_root_num; i++) {
- int res_num;
+ list_for_each_entry(info, &pci_root_infos, list) {
int busnum;
+ struct pci_root_res *root_res;
- info = &pci_root_info[i];
- res_num = info->res_num;
busnum = info->bus_min;
printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n",
info->bus_min, info->bus_max, info->node, info->link);
- for (j = 0; j < res_num; j++) {
- res = &info->res[j];
- printk(KERN_DEBUG "bus: %02x index %x %pR\n",
- busnum, j, res);
- }
+ list_for_each_entry(root_res, &info->resources, list)
+ printk(KERN_DEBUG "bus: %02x %pR\n",
+ busnum, &root_res->res);
}
return 0;
diff --git a/arch/x86/pci/broadcom_bus.c b/arch/x86/pci/broadcom_bus.c
index f3a7c569a403..614392ced7d6 100644
--- a/arch/x86/pci/broadcom_bus.c
+++ b/arch/x86/pci/broadcom_bus.c
@@ -22,19 +22,15 @@
static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
{
struct pci_root_info *info;
+ struct pci_root_res *root_res;
struct resource res;
u16 word1, word2;
u8 fbus, lbus;
- int i;
-
- info = &pci_root_info[pci_root_num];
- pci_root_num++;
/* read the PCI bus numbers */
fbus = read_pci_config_byte(bus, slot, func, 0x44);
lbus = read_pci_config_byte(bus, slot, func, 0x45);
- info->bus_min = fbus;
- info->bus_max = lbus;
+ info = alloc_pci_root_info(fbus, lbus, 0, 0);
/*
* Add the legacy IDE ports on bus 0
@@ -86,8 +82,8 @@ static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
res.flags = IORESOURCE_BUS;
printk(KERN_INFO "CNB20LE PCI Host Bridge (domain 0000 %pR)\n", &res);
- for (i = 0; i < info->res_num; i++)
- printk(KERN_INFO "host bridge window %pR\n", &info->res[i]);
+ list_for_each_entry(root_res, &info->resources, list)
+ printk(KERN_INFO "host bridge window %pR\n", &root_res->res);
}
static int __init broadcom_postcore_init(void)
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index fd3f65510e9d..306579f7d0fd 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -4,35 +4,38 @@
#include "bus_numa.h"
-int pci_root_num;
-struct pci_root_info pci_root_info[PCI_ROOT_NR];
+LIST_HEAD(pci_root_infos);
-void x86_pci_root_bus_resources(int bus, struct list_head *resources)
+static struct pci_root_info *x86_find_pci_root_info(int bus)
{
- int i;
- int j;
struct pci_root_info *info;
- if (!pci_root_num)
- goto default_resources;
+ if (list_empty(&pci_root_infos))
+ return NULL;
- for (i = 0; i < pci_root_num; i++) {
- if (pci_root_info[i].bus_min == bus)
- break;
- }
+ list_for_each_entry(info, &pci_root_infos, list)
+ if (info->bus_min == bus)
+ return info;
+
+ return NULL;
+}
- if (i == pci_root_num)
+void x86_pci_root_bus_resources(int bus, struct list_head *resources)
+{
+ struct pci_root_info *info = x86_find_pci_root_info(bus);
+ struct pci_root_res *root_res;
+
+ if (!info)
goto default_resources;
printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
bus);
- info = &pci_root_info[i];
- for (j = 0; j < info->res_num; j++) {
+ list_for_each_entry(root_res, &info->resources, list) {
struct resource *res;
struct resource *root;
- res = &info->res[j];
+ res = &root_res->res;
pci_add_resource(resources, res);
if (res->flags & IORESOURCE_IO)
root = &ioport_resource;
@@ -53,11 +56,32 @@ default_resources:
pci_add_resource(resources, &iomem_resource);
}
+struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
+ int node, int link)
+{
+ struct pci_root_info *info;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+
+ if (!info)
+ return info;
+
+ INIT_LIST_HEAD(&info->resources);
+ info->bus_min = bus_min;
+ info->bus_max = bus_max;
+ info->node = node;
+ info->link = link;
+
+ list_add_tail(&info->list, &pci_root_infos);
+
+ return info;
+}
+
void __devinit update_res(struct pci_root_info *info, resource_size_t start,
resource_size_t end, unsigned long flags, int merge)
{
- int i;
struct resource *res;
+ struct pci_root_res *root_res;
if (start > end)
return;
@@ -69,11 +93,11 @@ void __devinit update_res(struct pci_root_info *info, resource_size_t start,
goto addit;
/* try to merge it with old one */
- for (i = 0; i < info->res_num; i++) {
+ list_for_each_entry(root_res, &info->resources, list) {
resource_size_t final_start, final_end;
resource_size_t common_start, common_end;
- res = &info->res[i];
+ res = &root_res->res;
if (res->flags != flags)
continue;
@@ -93,14 +117,15 @@ void __devinit update_res(struct pci_root_info *info, resource_size_t start,
addit:
/* need to add that */
- if (info->res_num >= RES_NUM)
+ root_res = kzalloc(sizeof(*root_res), GFP_KERNEL);
+ if (!root_res)
return;
- res = &info->res[info->res_num];
+ res = &root_res->res;
res->name = info->name;
res->flags = flags;
res->start = start;
res->end = end;
- res->child = NULL;
- info->res_num++;
+
+ list_add_tail(&root_res->list, &info->resources);
}
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h
index 804a4b40c31a..226a466b2b2b 100644
--- a/arch/x86/pci/bus_numa.h
+++ b/arch/x86/pci/bus_numa.h
@@ -4,22 +4,24 @@
* sub bus (transparent) will use entres from 3 to store extra from
* root, so need to make sure we have enough slot there.
*/
-#define RES_NUM 16
+struct pci_root_res {
+ struct list_head list;
+ struct resource res;
+};
+
struct pci_root_info {
+ struct list_head list;
char name[12];
- unsigned int res_num;
- struct resource res[RES_NUM];
+ struct list_head resources;
int bus_min;
int bus_max;
int node;
int link;
};
-/* 4 at this time, it may become to 32 */
-#define PCI_ROOT_NR 4
-extern int pci_root_num;
-extern struct pci_root_info pci_root_info[PCI_ROOT_NR];
-
+extern struct list_head pci_root_infos;
+struct pci_root_info *alloc_pci_root_info(int bus_min, int bus_max,
+ int node, int link);
extern void update_res(struct pci_root_info *info, resource_size_t start,
resource_size_t end, unsigned long flags, int merge);
#endif
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 323481e06ef8..0ad990a20d4a 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -11,6 +11,7 @@
#include <linux/dmi.h>
#include <linux/slab.h>
+#include <asm-generic/pci-bridge.h>
#include <asm/acpi.h>
#include <asm/segment.h>
#include <asm/io.h>
@@ -229,6 +230,14 @@ static int __devinit assign_all_busses(const struct dmi_system_id *d)
}
#endif
+static int __devinit set_scan_all(const struct dmi_system_id *d)
+{
+ printk(KERN_INFO "PCI: %s detected, enabling pci=pcie_scan_all\n",
+ d->ident);
+ pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS);
+ return 0;
+}
+
static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = {
#ifdef __i386__
/*
@@ -420,6 +429,13 @@ static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"),
},
},
+ {
+ .callback = set_scan_all,
+ .ident = "Stratus/NEC ftServer",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ftServer"),
+ },
+ },
{}
};
@@ -430,9 +446,7 @@ void __init dmi_check_pciprobe(void)
struct pci_bus * __devinit pcibios_scan_root(int busnum)
{
- LIST_HEAD(resources);
struct pci_bus *bus = NULL;
- struct pci_sysdata *sd;
while ((bus = pci_find_next_bus(bus)) != NULL) {
if (bus->number == busnum) {
@@ -441,28 +455,10 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
}
}
- /* Allocate per-root-bus (not per bus) arch-specific data.
- * TODO: leak; this memory is never freed.
- * It's arguable whether it's worth the trouble to care.
- */
- sd = kzalloc(sizeof(*sd), GFP_KERNEL);
- if (!sd) {
- printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum);
- return NULL;
- }
-
- sd->node = get_mp_bus_to_node(busnum);
-
- printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
- x86_pci_root_bus_resources(busnum, &resources);
- bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
- if (!bus) {
- pci_free_resource_list(&resources);
- kfree(sd);
- }
-
- return bus;
+ return pci_scan_bus_on_node(busnum, &pci_root_ops,
+ get_mp_bus_to_node(busnum));
}
+
void __init pcibios_set_cache_line_size(void)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
@@ -656,6 +652,7 @@ struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops,
}
sd->node = node;
x86_pci_root_bus_resources(busno, &resources);
+ printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busno);
bus = pci_scan_root_bus(NULL, busno, ops, sd, &resources);
if (!bus) {
pci_free_resource_list(&resources);
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index d0e6e403b4f6..5dd467bd6121 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -519,3 +519,20 @@ static void sb600_disable_hpet_bar(struct pci_dev *dev)
}
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4385, sb600_disable_hpet_bar);
+
+/*
+ * Twinhead H12Y needs us to block out a region otherwise we map devices
+ * there and any access kills the box.
+ *
+ * See: https://bugzilla.kernel.org/show_bug.cgi?id=10231
+ *
+ * Match off the LPC and svid/sdid (older kernels lose the bridge subvendor)
+ */
+static void __devinit twinhead_reserve_killing_zone(struct pci_dev *dev)
+{
+ if (dev->subsystem_vendor == 0x14FF && dev->subsystem_device == 0xA003) {
+ pr_info("Reserving memory on Twinhead H12Y\n");
+ request_mem_region(0xFFB00000, 0x100000, "twinhead");
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone);
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 831971e731f7..dd8ca6f7223b 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -57,7 +57,7 @@ static struct pcibios_fwaddrmap *pcibios_fwaddrmap_lookup(struct pci_dev *dev)
{
struct pcibios_fwaddrmap *map;
- WARN_ON(!spin_is_locked(&pcibios_fwaddrmap_lock));
+ WARN_ON_SMP(!spin_is_locked(&pcibios_fwaddrmap_lock));
list_for_each_entry(map, &pcibios_fwaddrmappings, list)
if (map->dev == dev)
diff --git a/arch/x86/pci/sta2x11-fixup.c b/arch/x86/pci/sta2x11-fixup.c
new file mode 100644
index 000000000000..9d8a509c9730
--- /dev/null
+++ b/arch/x86/pci/sta2x11-fixup.c
@@ -0,0 +1,366 @@
+/*
+ * arch/x86/pci/sta2x11-fixup.c
+ * glue code for lib/swiotlb.c and DMA translation between STA2x11
+ * AMBA memory mapping and the X86 memory mapping
+ *
+ * ST Microelectronics ConneXt (STA2X11/STA2X10)
+ *
+ * Copyright (c) 2010-2011 Wind River Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/export.h>
+#include <linux/list.h>
+
+#define STA2X11_SWIOTLB_SIZE (4*1024*1024)
+extern int swiotlb_late_init_with_default_size(size_t default_size);
+
+/*
+ * We build a list of bus numbers that are under the ConneXt. The
+ * main bridge hosts 4 busses, which are the 4 endpoints, in order.
+ */
+#define STA2X11_NR_EP 4 /* 0..3 included */
+#define STA2X11_NR_FUNCS 8 /* 0..7 included */
+#define STA2X11_AMBA_SIZE (512 << 20)
+
+struct sta2x11_ahb_regs { /* saved during suspend */
+ u32 base, pexlbase, pexhbase, crw;
+};
+
+struct sta2x11_mapping {
+ u32 amba_base;
+ int is_suspended;
+ struct sta2x11_ahb_regs regs[STA2X11_NR_FUNCS];
+};
+
+struct sta2x11_instance {
+ struct list_head list;
+ int bus0;
+ struct sta2x11_mapping map[STA2X11_NR_EP];
+};
+
+static LIST_HEAD(sta2x11_instance_list);
+
+/* At probe time, record new instances of this bridge (likely one only) */
+static void sta2x11_new_instance(struct pci_dev *pdev)
+{
+ struct sta2x11_instance *instance;
+
+ instance = kzalloc(sizeof(*instance), GFP_ATOMIC);
+ if (!instance)
+ return;
+ /* This has a subordinate bridge, with 4 more-subordinate ones */
+ instance->bus0 = pdev->subordinate->number + 1;
+
+ if (list_empty(&sta2x11_instance_list)) {
+ int size = STA2X11_SWIOTLB_SIZE;
+ /* First instance: register your own swiotlb area */
+ dev_info(&pdev->dev, "Using SWIOTLB (size %i)\n", size);
+ if (swiotlb_late_init_with_default_size(size))
+ dev_emerg(&pdev->dev, "init swiotlb failed\n");
+ }
+ list_add(&instance->list, &sta2x11_instance_list);
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_STMICRO, 0xcc17, sta2x11_new_instance);
+
+/*
+ * Utility functions used in this file from below
+ */
+static struct sta2x11_instance *sta2x11_pdev_to_instance(struct pci_dev *pdev)
+{
+ struct sta2x11_instance *instance;
+ int ep;
+
+ list_for_each_entry(instance, &sta2x11_instance_list, list) {
+ ep = pdev->bus->number - instance->bus0;
+ if (ep >= 0 && ep < STA2X11_NR_EP)
+ return instance;
+ }
+ return NULL;
+}
+
+static int sta2x11_pdev_to_ep(struct pci_dev *pdev)
+{
+ struct sta2x11_instance *instance;
+
+ instance = sta2x11_pdev_to_instance(pdev);
+ if (!instance)
+ return -1;
+
+ return pdev->bus->number - instance->bus0;
+}
+
+static struct sta2x11_mapping *sta2x11_pdev_to_mapping(struct pci_dev *pdev)
+{
+ struct sta2x11_instance *instance;
+ int ep;
+
+ instance = sta2x11_pdev_to_instance(pdev);
+ if (!instance)
+ return NULL;
+ ep = sta2x11_pdev_to_ep(pdev);
+ return instance->map + ep;
+}
+
+/* This is exported, as some devices need to access the MFD registers */
+struct sta2x11_instance *sta2x11_get_instance(struct pci_dev *pdev)
+{
+ return sta2x11_pdev_to_instance(pdev);
+}
+EXPORT_SYMBOL(sta2x11_get_instance);
+
+
+/**
+ * p2a - Translate physical address to STA2x11 AMBA address,
+ * used for DMA transfers to STA2x11
+ * @p: Physical address
+ * @pdev: PCI device (must be hosted within the connext)
+ */
+static dma_addr_t p2a(dma_addr_t p, struct pci_dev *pdev)
+{
+ struct sta2x11_mapping *map;
+ dma_addr_t a;
+
+ map = sta2x11_pdev_to_mapping(pdev);
+ a = p + map->amba_base;
+ return a;
+}
+
+/**
+ * a2p - Translate STA2x11 AMBA address to physical address
+ * used for DMA transfers from STA2x11
+ * @a: STA2x11 AMBA address
+ * @pdev: PCI device (must be hosted within the connext)
+ */
+static dma_addr_t a2p(dma_addr_t a, struct pci_dev *pdev)
+{
+ struct sta2x11_mapping *map;
+ dma_addr_t p;
+
+ map = sta2x11_pdev_to_mapping(pdev);
+ p = a - map->amba_base;
+ return p;
+}
+
+/**
+ * sta2x11_swiotlb_alloc_coherent - Allocate swiotlb bounce buffers
+ * returns virtual address. This is the only "special" function here.
+ * @dev: PCI device
+ * @size: Size of the buffer
+ * @dma_handle: DMA address
+ * @flags: memory flags
+ */
+static void *sta2x11_swiotlb_alloc_coherent(struct device *dev,
+ size_t size,
+ dma_addr_t *dma_handle,
+ gfp_t flags,
+ struct dma_attrs *attrs)
+{
+ void *vaddr;
+
+ vaddr = dma_generic_alloc_coherent(dev, size, dma_handle, flags, attrs);
+ if (!vaddr)
+ vaddr = swiotlb_alloc_coherent(dev, size, dma_handle, flags);
+ *dma_handle = p2a(*dma_handle, to_pci_dev(dev));
+ return vaddr;
+}
+
+/* We have our own dma_ops: the same as swiotlb but from alloc (above) */
+static struct dma_map_ops sta2x11_dma_ops = {
+ .alloc = sta2x11_swiotlb_alloc_coherent,
+ .free = swiotlb_free_coherent,
+ .map_page = swiotlb_map_page,
+ .unmap_page = swiotlb_unmap_page,
+ .map_sg = swiotlb_map_sg_attrs,
+ .unmap_sg = swiotlb_unmap_sg_attrs,
+ .sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+ .sync_single_for_device = swiotlb_sync_single_for_device,
+ .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+ .sync_sg_for_device = swiotlb_sync_sg_for_device,
+ .mapping_error = swiotlb_dma_mapping_error,
+ .dma_supported = NULL, /* FIXME: we should use this instead! */
+};
+
+/* At setup time, we use our own ops if the device is a ConneXt one */
+static void sta2x11_setup_pdev(struct pci_dev *pdev)
+{
+ struct sta2x11_instance *instance = sta2x11_pdev_to_instance(pdev);
+
+ if (!instance) /* either a sta2x11 bridge or another ST device */
+ return;
+ pci_set_consistent_dma_mask(pdev, STA2X11_AMBA_SIZE - 1);
+ pci_set_dma_mask(pdev, STA2X11_AMBA_SIZE - 1);
+ pdev->dev.archdata.dma_ops = &sta2x11_dma_ops;
+
+ /* We must enable all devices as master, for audio DMA to work */
+ pci_set_master(pdev);
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_STMICRO, PCI_ANY_ID, sta2x11_setup_pdev);
+
+/*
+ * The following three functions are exported (used in swiotlb: FIXME)
+ */
+/**
+ * dma_capable - Check if device can manage DMA transfers (FIXME: kill it)
+ * @dev: device for a PCI device
+ * @addr: DMA address
+ * @size: DMA size
+ */
+bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+ struct sta2x11_mapping *map;
+
+ if (dev->archdata.dma_ops != &sta2x11_dma_ops) {
+ if (!dev->dma_mask)
+ return false;
+ return addr + size - 1 <= *dev->dma_mask;
+ }
+
+ map = sta2x11_pdev_to_mapping(to_pci_dev(dev));
+
+ if (!map || (addr < map->amba_base))
+ return false;
+ if (addr + size >= map->amba_base + STA2X11_AMBA_SIZE) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * phys_to_dma - Return the DMA AMBA address used for this STA2x11 device
+ * @dev: device for a PCI device
+ * @paddr: Physical address
+ */
+dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+ if (dev->archdata.dma_ops != &sta2x11_dma_ops)
+ return paddr;
+ return p2a(paddr, to_pci_dev(dev));
+}
+
+/**
+ * dma_to_phys - Return the physical address used for this STA2x11 DMA address
+ * @dev: device for a PCI device
+ * @daddr: STA2x11 AMBA DMA address
+ */
+phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+ if (dev->archdata.dma_ops != &sta2x11_dma_ops)
+ return daddr;
+ return a2p(daddr, to_pci_dev(dev));
+}
+
+
+/*
+ * At boot we must set up the mappings for the pcie-to-amba bridge.
+ * It involves device access, and the same happens at suspend/resume time
+ */
+
+#define AHB_MAPB 0xCA4
+#define AHB_CRW(i) (AHB_MAPB + 0 + (i) * 0x10)
+#define AHB_CRW_SZMASK 0xfffffc00UL
+#define AHB_CRW_ENABLE (1 << 0)
+#define AHB_CRW_WTYPE_MEM (2 << 1)
+#define AHB_CRW_ROE (1UL << 3) /* Relax Order Ena */
+#define AHB_CRW_NSE (1UL << 4) /* No Snoop Enable */
+#define AHB_BASE(i) (AHB_MAPB + 4 + (i) * 0x10)
+#define AHB_PEXLBASE(i) (AHB_MAPB + 8 + (i) * 0x10)
+#define AHB_PEXHBASE(i) (AHB_MAPB + 12 + (i) * 0x10)
+
+/* At probe time, enable mapping for each endpoint, using the pdev */
+static void sta2x11_map_ep(struct pci_dev *pdev)
+{
+ struct sta2x11_mapping *map = sta2x11_pdev_to_mapping(pdev);
+ int i;
+
+ if (!map)
+ return;
+ pci_read_config_dword(pdev, AHB_BASE(0), &map->amba_base);
+
+ /* Configure AHB mapping */
+ pci_write_config_dword(pdev, AHB_PEXLBASE(0), 0);
+ pci_write_config_dword(pdev, AHB_PEXHBASE(0), 0);
+ pci_write_config_dword(pdev, AHB_CRW(0), STA2X11_AMBA_SIZE |
+ AHB_CRW_WTYPE_MEM | AHB_CRW_ENABLE);
+
+ /* Disable all the other windows */
+ for (i = 1; i < STA2X11_NR_FUNCS; i++)
+ pci_write_config_dword(pdev, AHB_CRW(i), 0);
+
+ dev_info(&pdev->dev,
+ "sta2x11: Map EP %i: AMBA address %#8x-%#8x\n",
+ sta2x11_pdev_to_ep(pdev), map->amba_base,
+ map->amba_base + STA2X11_AMBA_SIZE - 1);
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_STMICRO, PCI_ANY_ID, sta2x11_map_ep);
+
+#ifdef CONFIG_PM /* Some register values must be saved and restored */
+
+static void suspend_mapping(struct pci_dev *pdev)
+{
+ struct sta2x11_mapping *map = sta2x11_pdev_to_mapping(pdev);
+ int i;
+
+ if (!map)
+ return;
+
+ if (map->is_suspended)
+ return;
+ map->is_suspended = 1;
+
+ /* Save all window configs */
+ for (i = 0; i < STA2X11_NR_FUNCS; i++) {
+ struct sta2x11_ahb_regs *regs = map->regs + i;
+
+ pci_read_config_dword(pdev, AHB_BASE(i), &regs->base);
+ pci_read_config_dword(pdev, AHB_PEXLBASE(i), &regs->pexlbase);
+ pci_read_config_dword(pdev, AHB_PEXHBASE(i), &regs->pexhbase);
+ pci_read_config_dword(pdev, AHB_CRW(i), &regs->crw);
+ }
+}
+DECLARE_PCI_FIXUP_SUSPEND(PCI_VENDOR_ID_STMICRO, PCI_ANY_ID, suspend_mapping);
+
+static void resume_mapping(struct pci_dev *pdev)
+{
+ struct sta2x11_mapping *map = sta2x11_pdev_to_mapping(pdev);
+ int i;
+
+ if (!map)
+ return;
+
+
+ if (!map->is_suspended)
+ goto out;
+ map->is_suspended = 0;
+
+ /* Restore all window configs */
+ for (i = 0; i < STA2X11_NR_FUNCS; i++) {
+ struct sta2x11_ahb_regs *regs = map->regs + i;
+
+ pci_write_config_dword(pdev, AHB_BASE(i), regs->base);
+ pci_write_config_dword(pdev, AHB_PEXLBASE(i), regs->pexlbase);
+ pci_write_config_dword(pdev, AHB_PEXHBASE(i), regs->pexhbase);
+ pci_write_config_dword(pdev, AHB_CRW(i), regs->crw);
+ }
+out:
+ pci_set_master(pdev); /* Like at boot, enable master on all devices */
+}
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_STMICRO, PCI_ANY_ID, resume_mapping);
+
+#endif /* CONFIG_PM */
diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c
index 1d4c783d7325..04b8c73659c5 100644
--- a/arch/x86/platform/olpc/olpc-xo1-sci.c
+++ b/arch/x86/platform/olpc/olpc-xo1-sci.c
@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
+#include <linux/pm_wakeup.h>
#include <linux/mfd/core.h>
#include <linux/power_supply.h>
#include <linux/suspend.h>
@@ -83,8 +84,12 @@ static void send_ebook_state(void)
return;
}
+ if (!!test_bit(SW_TABLET_MODE, ebook_switch_idev->sw) == state)
+ return; /* Nothing new to report. */
+
input_report_switch(ebook_switch_idev, SW_TABLET_MODE, state);
input_sync(ebook_switch_idev);
+ pm_wakeup_event(&ebook_switch_idev->dev, 0);
}
static void flip_lid_inverter(void)
@@ -123,8 +128,12 @@ static void detect_lid_state(void)
/* Report current lid switch state through input layer */
static void send_lid_state(void)
{
+ if (!!test_bit(SW_LID, lid_switch_idev->sw) == !lid_open)
+ return; /* Nothing new to report. */
+
input_report_switch(lid_switch_idev, SW_LID, !lid_open);
input_sync(lid_switch_idev);
+ pm_wakeup_event(&lid_switch_idev->dev, 0);
}
static ssize_t lid_wake_mode_show(struct device *dev,
@@ -213,11 +222,30 @@ static irqreturn_t xo1_sci_intr(int irq, void *dev_id)
dev_dbg(&pdev->dev, "sts %x gpe %x\n", sts, gpe);
- if (sts & CS5536_PWRBTN_FLAG && !(sts & CS5536_WAK_FLAG)) {
- input_report_key(power_button_idev, KEY_POWER, 1);
- input_sync(power_button_idev);
- input_report_key(power_button_idev, KEY_POWER, 0);
- input_sync(power_button_idev);
+ if (sts & CS5536_PWRBTN_FLAG) {
+ if (!(sts & CS5536_WAK_FLAG)) {
+ /* Only report power button input when it was pressed
+ * during regular operation (as opposed to when it
+ * was used to wake the system). */
+ input_report_key(power_button_idev, KEY_POWER, 1);
+ input_sync(power_button_idev);
+ input_report_key(power_button_idev, KEY_POWER, 0);
+ input_sync(power_button_idev);
+ }
+ /* Report the wakeup event in all cases. */
+ pm_wakeup_event(&power_button_idev->dev, 0);
+ }
+
+ if ((sts & (CS5536_RTC_FLAG | CS5536_WAK_FLAG)) ==
+ (CS5536_RTC_FLAG | CS5536_WAK_FLAG)) {
+ /* When the system is woken by the RTC alarm, report the
+ * event on the rtc device. */
+ struct device *rtc = bus_find_device_by_name(
+ &platform_bus_type, NULL, "rtc_cmos");
+ if (rtc) {
+ pm_wakeup_event(rtc, 0);
+ put_device(rtc);
+ }
}
if (gpe & CS5536_GPIOM7_PME_FLAG) { /* EC GPIO */
@@ -310,9 +338,10 @@ static int __devinit setup_sci_interrupt(struct platform_device *pdev)
outb(lo, CS5536_PIC_INT_SEL2);
}
- /* Enable SCI from power button, and clear pending interrupts */
+ /* Enable interesting SCI events, and clear pending interrupts */
sts = inl(acpi_base + CS5536_PM1_STS);
- outl((CS5536_PM_PWRBTN << 16) | 0xffff, acpi_base + CS5536_PM1_STS);
+ outl(((CS5536_PM_PWRBTN | CS5536_PM_RTC) << 16) | 0xffff,
+ acpi_base + CS5536_PM1_STS);
r = request_irq(sci_irq, xo1_sci_intr, 0, DRV_NAME, pdev);
if (r)
diff --git a/arch/x86/platform/visws/visws_quirks.c b/arch/x86/platform/visws/visws_quirks.c
index c7abf13a213f..94d8a39332ec 100644
--- a/arch/x86/platform/visws/visws_quirks.c
+++ b/arch/x86/platform/visws/visws_quirks.c
@@ -445,7 +445,7 @@ static void ack_cobalt_irq(struct irq_data *data)
spin_lock_irqsave(&cobalt_lock, flags);
disable_cobalt_irq(data);
- apic_write(APIC_EOI, APIC_EIO_ACK);
+ apic_write(APIC_EOI, APIC_EOI_ACK);
spin_unlock_irqrestore(&cobalt_lock, flags);
}
diff --git a/arch/x86/tools/.gitignore b/arch/x86/tools/.gitignore
new file mode 100644
index 000000000000..be0ed065249b
--- /dev/null
+++ b/arch/x86/tools/.gitignore
@@ -0,0 +1 @@
+relocs
diff --git a/arch/x86/tools/Makefile b/arch/x86/tools/Makefile
index d511aa97533a..733057b435b0 100644
--- a/arch/x86/tools/Makefile
+++ b/arch/x86/tools/Makefile
@@ -36,3 +36,7 @@ HOSTCFLAGS_insn_sanity.o := -Wall -I$(objtree)/arch/x86/lib/ -I$(srctree)/arch/x
$(obj)/test_get_len.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c
$(obj)/insn_sanity.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c
+
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include
+hostprogs-y += relocs
+relocs: $(obj)/relocs
diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/tools/relocs.c
index fb7117a4ade1..b43cfcd9bf40 100644
--- a/arch/x86/boot/compressed/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -18,6 +18,8 @@ static void die(char *fmt, ...);
static Elf32_Ehdr ehdr;
static unsigned long reloc_count, reloc_idx;
static unsigned long *relocs;
+static unsigned long reloc16_count, reloc16_idx;
+static unsigned long *relocs16;
struct section {
Elf32_Shdr shdr;
@@ -28,52 +30,86 @@ struct section {
};
static struct section *secs;
+enum symtype {
+ S_ABS,
+ S_REL,
+ S_SEG,
+ S_LIN,
+ S_NSYMTYPES
+};
+
+static const char * const sym_regex_kernel[S_NSYMTYPES] = {
/*
* Following symbols have been audited. There values are constant and do
* not change if bzImage is loaded at a different physical address than
* the address for which it has been compiled. Don't warn user about
* absolute relocations present w.r.t these symbols.
*/
-static const char abs_sym_regex[] =
+ [S_ABS] =
"^(xen_irq_disable_direct_reloc$|"
"xen_save_fl_direct_reloc$|"
"VDSO|"
- "__crc_)";
-static regex_t abs_sym_regex_c;
-static int is_abs_reloc(const char *sym_name)
-{
- return !regexec(&abs_sym_regex_c, sym_name, 0, NULL, 0);
-}
+ "__crc_)",
/*
* These symbols are known to be relative, even if the linker marks them
* as absolute (typically defined outside any section in the linker script.)
*/
-static const char rel_sym_regex[] =
- "^_end$";
-static regex_t rel_sym_regex_c;
-static int is_rel_reloc(const char *sym_name)
+ [S_REL] =
+ "^(__init_(begin|end)|"
+ "__x86_cpu_dev_(start|end)|"
+ "(__parainstructions|__alt_instructions)(|_end)|"
+ "(__iommu_table|__apicdrivers|__smp_locks)(|_end)|"
+ "_end)$"
+};
+
+
+static const char * const sym_regex_realmode[S_NSYMTYPES] = {
+/*
+ * These are 16-bit segment symbols when compiling 16-bit code.
+ */
+ [S_SEG] =
+ "^real_mode_seg$",
+
+/*
+ * These are offsets belonging to segments, as opposed to linear addresses,
+ * when compiling 16-bit code.
+ */
+ [S_LIN] =
+ "^pa_",
+};
+
+static const char * const *sym_regex;
+
+static regex_t sym_regex_c[S_NSYMTYPES];
+static int is_reloc(enum symtype type, const char *sym_name)
{
- return !regexec(&rel_sym_regex_c, sym_name, 0, NULL, 0);
+ return sym_regex[type] &&
+ !regexec(&sym_regex_c[type], sym_name, 0, NULL, 0);
}
-static void regex_init(void)
+static void regex_init(int use_real_mode)
{
char errbuf[128];
int err;
-
- err = regcomp(&abs_sym_regex_c, abs_sym_regex,
- REG_EXTENDED|REG_NOSUB);
- if (err) {
- regerror(err, &abs_sym_regex_c, errbuf, sizeof errbuf);
- die("%s", errbuf);
- }
+ int i;
+
+ if (use_real_mode)
+ sym_regex = sym_regex_realmode;
+ else
+ sym_regex = sym_regex_kernel;
- err = regcomp(&rel_sym_regex_c, rel_sym_regex,
- REG_EXTENDED|REG_NOSUB);
- if (err) {
- regerror(err, &rel_sym_regex_c, errbuf, sizeof errbuf);
- die("%s", errbuf);
+ for (i = 0; i < S_NSYMTYPES; i++) {
+ if (!sym_regex[i])
+ continue;
+
+ err = regcomp(&sym_regex_c[i], sym_regex[i],
+ REG_EXTENDED|REG_NOSUB);
+
+ if (err) {
+ regerror(err, &sym_regex_c[i], errbuf, sizeof errbuf);
+ die("%s", errbuf);
+ }
}
}
@@ -154,6 +190,10 @@ static const char *rel_type(unsigned type)
REL_TYPE(R_386_RELATIVE),
REL_TYPE(R_386_GOTOFF),
REL_TYPE(R_386_GOTPC),
+ REL_TYPE(R_386_8),
+ REL_TYPE(R_386_PC8),
+ REL_TYPE(R_386_16),
+ REL_TYPE(R_386_PC16),
#undef REL_TYPE
};
const char *name = "unknown type rel type name";
@@ -189,7 +229,7 @@ static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym)
name = sym_strtab + sym->st_name;
}
else {
- name = sec_name(secs[sym->st_shndx].shdr.sh_name);
+ name = sec_name(sym->st_shndx);
}
return name;
}
@@ -472,7 +512,7 @@ static void print_absolute_relocs(void)
* Before warning check if this absolute symbol
* relocation is harmless.
*/
- if (is_abs_reloc(name) || is_rel_reloc(name))
+ if (is_reloc(S_ABS, name) || is_reloc(S_REL, name))
continue;
if (!printed) {
@@ -496,7 +536,8 @@ static void print_absolute_relocs(void)
printf("\n");
}
-static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
+static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym),
+ int use_real_mode)
{
int i;
/* Walk through the relocations */
@@ -521,30 +562,67 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
Elf32_Rel *rel;
Elf32_Sym *sym;
unsigned r_type;
+ const char *symname;
+ int shn_abs;
+
rel = &sec->reltab[j];
sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
r_type = ELF32_R_TYPE(rel->r_info);
- /* Don't visit relocations to absolute symbols */
- if (sym->st_shndx == SHN_ABS &&
- !is_rel_reloc(sym_name(sym_strtab, sym))) {
- continue;
- }
+
+ shn_abs = sym->st_shndx == SHN_ABS;
+
switch (r_type) {
case R_386_NONE:
case R_386_PC32:
+ case R_386_PC16:
+ case R_386_PC8:
/*
* NONE can be ignored and and PC relative
* relocations don't need to be adjusted.
*/
break;
+
+ case R_386_16:
+ symname = sym_name(sym_strtab, sym);
+ if (!use_real_mode)
+ goto bad;
+ if (shn_abs) {
+ if (is_reloc(S_ABS, symname))
+ break;
+ else if (!is_reloc(S_SEG, symname))
+ goto bad;
+ } else {
+ if (is_reloc(S_LIN, symname))
+ goto bad;
+ else
+ break;
+ }
+ visit(rel, sym);
+ break;
+
case R_386_32:
- /* Visit relocations that need to be adjusted */
+ symname = sym_name(sym_strtab, sym);
+ if (shn_abs) {
+ if (is_reloc(S_ABS, symname))
+ break;
+ else if (!is_reloc(S_REL, symname))
+ goto bad;
+ } else {
+ if (use_real_mode &&
+ !is_reloc(S_LIN, symname))
+ break;
+ }
visit(rel, sym);
break;
default:
die("Unsupported relocation type: %s (%d)\n",
rel_type(r_type), r_type);
break;
+ bad:
+ symname = sym_name(sym_strtab, sym);
+ die("Invalid %s %s relocation: %s\n",
+ shn_abs ? "absolute" : "relative",
+ rel_type(r_type), symname);
}
}
}
@@ -552,13 +630,19 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
{
- reloc_count += 1;
+ if (ELF32_R_TYPE(rel->r_info) == R_386_16)
+ reloc16_count++;
+ else
+ reloc_count++;
}
static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
{
/* Remember the address that needs to be adjusted. */
- relocs[reloc_idx++] = rel->r_offset;
+ if (ELF32_R_TYPE(rel->r_info) == R_386_16)
+ relocs16[reloc16_idx++] = rel->r_offset;
+ else
+ relocs[reloc_idx++] = rel->r_offset;
}
static int cmp_relocs(const void *va, const void *vb)
@@ -568,23 +652,41 @@ static int cmp_relocs(const void *va, const void *vb)
return (*a == *b)? 0 : (*a > *b)? 1 : -1;
}
-static void emit_relocs(int as_text)
+static int write32(unsigned int v, FILE *f)
+{
+ unsigned char buf[4];
+
+ put_unaligned_le32(v, buf);
+ return fwrite(buf, 1, 4, f) == 4 ? 0 : -1;
+}
+
+static void emit_relocs(int as_text, int use_real_mode)
{
int i;
/* Count how many relocations I have and allocate space for them. */
reloc_count = 0;
- walk_relocs(count_reloc);
+ walk_relocs(count_reloc, use_real_mode);
relocs = malloc(reloc_count * sizeof(relocs[0]));
if (!relocs) {
die("malloc of %d entries for relocs failed\n",
reloc_count);
}
+
+ relocs16 = malloc(reloc16_count * sizeof(relocs[0]));
+ if (!relocs16) {
+ die("malloc of %d entries for relocs16 failed\n",
+ reloc16_count);
+ }
/* Collect up the relocations */
reloc_idx = 0;
- walk_relocs(collect_reloc);
+ walk_relocs(collect_reloc, use_real_mode);
+
+ if (reloc16_count && !use_real_mode)
+ die("Segment relocations found but --realmode not specified\n");
/* Order the relocations for more efficient processing */
qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs);
+ qsort(relocs16, reloc16_count, sizeof(relocs16[0]), cmp_relocs);
/* Print the relocations */
if (as_text) {
@@ -593,58 +695,83 @@ static void emit_relocs(int as_text)
*/
printf(".section \".data.reloc\",\"a\"\n");
printf(".balign 4\n");
- for (i = 0; i < reloc_count; i++) {
- printf("\t .long 0x%08lx\n", relocs[i]);
+ if (use_real_mode) {
+ printf("\t.long %lu\n", reloc16_count);
+ for (i = 0; i < reloc16_count; i++)
+ printf("\t.long 0x%08lx\n", relocs16[i]);
+ printf("\t.long %lu\n", reloc_count);
+ for (i = 0; i < reloc_count; i++) {
+ printf("\t.long 0x%08lx\n", relocs[i]);
+ }
+ } else {
+ /* Print a stop */
+ printf("\t.long 0x%08lx\n", (unsigned long)0);
+ for (i = 0; i < reloc_count; i++) {
+ printf("\t.long 0x%08lx\n", relocs[i]);
+ }
}
+
printf("\n");
}
else {
- unsigned char buf[4];
- /* Print a stop */
- fwrite("\0\0\0\0", 4, 1, stdout);
- /* Now print each relocation */
- for (i = 0; i < reloc_count; i++) {
- put_unaligned_le32(relocs[i], buf);
- fwrite(buf, 4, 1, stdout);
+ if (use_real_mode) {
+ write32(reloc16_count, stdout);
+ for (i = 0; i < reloc16_count; i++)
+ write32(relocs16[i], stdout);
+ write32(reloc_count, stdout);
+
+ /* Now print each relocation */
+ for (i = 0; i < reloc_count; i++)
+ write32(relocs[i], stdout);
+ } else {
+ /* Print a stop */
+ write32(0, stdout);
+
+ /* Now print each relocation */
+ for (i = 0; i < reloc_count; i++) {
+ write32(relocs[i], stdout);
+ }
}
}
}
static void usage(void)
{
- die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n");
+ die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n");
}
int main(int argc, char **argv)
{
int show_absolute_syms, show_absolute_relocs;
- int as_text;
+ int as_text, use_real_mode;
const char *fname;
FILE *fp;
int i;
- regex_init();
-
show_absolute_syms = 0;
show_absolute_relocs = 0;
as_text = 0;
+ use_real_mode = 0;
fname = NULL;
for (i = 1; i < argc; i++) {
char *arg = argv[i];
if (*arg == '-') {
- if (strcmp(argv[1], "--abs-syms") == 0) {
+ if (strcmp(arg, "--abs-syms") == 0) {
show_absolute_syms = 1;
continue;
}
-
- if (strcmp(argv[1], "--abs-relocs") == 0) {
+ if (strcmp(arg, "--abs-relocs") == 0) {
show_absolute_relocs = 1;
continue;
}
- else if (strcmp(argv[1], "--text") == 0) {
+ if (strcmp(arg, "--text") == 0) {
as_text = 1;
continue;
}
+ if (strcmp(arg, "--realmode") == 0) {
+ use_real_mode = 1;
+ continue;
+ }
}
else if (!fname) {
fname = arg;
@@ -655,6 +782,7 @@ int main(int argc, char **argv)
if (!fname) {
usage();
}
+ regex_init(use_real_mode);
fp = fopen(fname, "r");
if (!fp) {
die("Cannot open %s: %s\n",
@@ -673,6 +801,6 @@ int main(int argc, char **argv)
print_absolute_relocs();
return 0;
}
- emit_relocs(as_text);
+ emit_relocs(as_text, use_real_mode);
return 0;
}
diff --git a/arch/x86/um/asm/elf.h b/arch/x86/um/asm/elf.h
index f3b0633b69a1..0e07adc8cbe4 100644
--- a/arch/x86/um/asm/elf.h
+++ b/arch/x86/um/asm/elf.h
@@ -34,25 +34,25 @@
#define ELF_ARCH EM_386
#define ELF_PLAT_INIT(regs, load_addr) do { \
- PT_REGS_EBX(regs) = 0; \
- PT_REGS_ECX(regs) = 0; \
- PT_REGS_EDX(regs) = 0; \
- PT_REGS_ESI(regs) = 0; \
- PT_REGS_EDI(regs) = 0; \
- PT_REGS_EBP(regs) = 0; \
- PT_REGS_EAX(regs) = 0; \
+ PT_REGS_BX(regs) = 0; \
+ PT_REGS_CX(regs) = 0; \
+ PT_REGS_DX(regs) = 0; \
+ PT_REGS_SI(regs) = 0; \
+ PT_REGS_DI(regs) = 0; \
+ PT_REGS_BP(regs) = 0; \
+ PT_REGS_AX(regs) = 0; \
} while (0)
/* Shamelessly stolen from include/asm-i386/elf.h */
#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \
- pr_reg[0] = PT_REGS_EBX(regs); \
- pr_reg[1] = PT_REGS_ECX(regs); \
- pr_reg[2] = PT_REGS_EDX(regs); \
- pr_reg[3] = PT_REGS_ESI(regs); \
- pr_reg[4] = PT_REGS_EDI(regs); \
- pr_reg[5] = PT_REGS_EBP(regs); \
- pr_reg[6] = PT_REGS_EAX(regs); \
+ pr_reg[0] = PT_REGS_BX(regs); \
+ pr_reg[1] = PT_REGS_CX(regs); \
+ pr_reg[2] = PT_REGS_DX(regs); \
+ pr_reg[3] = PT_REGS_SI(regs); \
+ pr_reg[4] = PT_REGS_DI(regs); \
+ pr_reg[5] = PT_REGS_BP(regs); \
+ pr_reg[6] = PT_REGS_AX(regs); \
pr_reg[7] = PT_REGS_DS(regs); \
pr_reg[8] = PT_REGS_ES(regs); \
/* fake once used fs and gs selectors? */ \
@@ -130,13 +130,13 @@ do { \
#define ELF_ARCH EM_X86_64
#define ELF_PLAT_INIT(regs, load_addr) do { \
- PT_REGS_RBX(regs) = 0; \
- PT_REGS_RCX(regs) = 0; \
- PT_REGS_RDX(regs) = 0; \
- PT_REGS_RSI(regs) = 0; \
- PT_REGS_RDI(regs) = 0; \
- PT_REGS_RBP(regs) = 0; \
- PT_REGS_RAX(regs) = 0; \
+ PT_REGS_BX(regs) = 0; \
+ PT_REGS_CX(regs) = 0; \
+ PT_REGS_DX(regs) = 0; \
+ PT_REGS_SI(regs) = 0; \
+ PT_REGS_DI(regs) = 0; \
+ PT_REGS_BP(regs) = 0; \
+ PT_REGS_AX(regs) = 0; \
PT_REGS_R8(regs) = 0; \
PT_REGS_R9(regs) = 0; \
PT_REGS_R10(regs) = 0; \
diff --git a/arch/x86/um/asm/ptrace.h b/arch/x86/um/asm/ptrace.h
index c8aca8c501b0..950dfb7b8417 100644
--- a/arch/x86/um/asm/ptrace.h
+++ b/arch/x86/um/asm/ptrace.h
@@ -1,5 +1,39 @@
+#ifndef __UM_X86_PTRACE_H
+#define __UM_X86_PTRACE_H
+
#ifdef CONFIG_X86_32
# include "ptrace_32.h"
#else
# include "ptrace_64.h"
#endif
+
+#define PT_REGS_AX(r) UPT_AX(&(r)->regs)
+#define PT_REGS_BX(r) UPT_BX(&(r)->regs)
+#define PT_REGS_CX(r) UPT_CX(&(r)->regs)
+#define PT_REGS_DX(r) UPT_DX(&(r)->regs)
+
+#define PT_REGS_SI(r) UPT_SI(&(r)->regs)
+#define PT_REGS_DI(r) UPT_DI(&(r)->regs)
+#define PT_REGS_BP(r) UPT_BP(&(r)->regs)
+#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
+
+#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
+#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
+#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
+#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
+
+#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_AX(r)
+#define PT_REGS_SYSCALL_RET(r) PT_REGS_AX(r)
+
+#define PT_FIX_EXEC_STACK(sp) do ; while(0)
+
+#define profile_pc(regs) PT_REGS_IP(regs)
+
+#define UPT_RESTART_SYSCALL(r) (UPT_IP(r) -= 2)
+#define UPT_SET_SYSCALL_RETURN(r, res) (UPT_AX(r) = (res))
+
+static inline long regs_return_value(struct uml_pt_regs *regs)
+{
+ return UPT_AX(regs);
+}
+#endif /* __UM_X86_PTRACE_H */
diff --git a/arch/x86/um/asm/ptrace_32.h b/arch/x86/um/asm/ptrace_32.h
index 5d2a59112537..2cf225351b65 100644
--- a/arch/x86/um/asm/ptrace_32.h
+++ b/arch/x86/um/asm/ptrace_32.h
@@ -11,29 +11,6 @@
#include "linux/compiler.h"
#include "asm/ptrace-generic.h"
-#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
-#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs)
-#define PT_REGS_ECX(r) UPT_ECX(&(r)->regs)
-#define PT_REGS_EDX(r) UPT_EDX(&(r)->regs)
-#define PT_REGS_ESI(r) UPT_ESI(&(r)->regs)
-#define PT_REGS_EDI(r) UPT_EDI(&(r)->regs)
-#define PT_REGS_EBP(r) UPT_EBP(&(r)->regs)
-
-#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
-#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
-#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
-#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
-#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
-#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
-
-#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
-
-#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_EAX(r)
-#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r)
-#define PT_FIX_EXEC_STACK(sp) do ; while(0)
-
-#define profile_pc(regs) PT_REGS_IP(regs)
-
#define user_mode(r) UPT_IS_USER(&(r)->regs)
/*
diff --git a/arch/x86/um/asm/ptrace_64.h b/arch/x86/um/asm/ptrace_64.h
index 706a0d80545c..ea7bff394320 100644
--- a/arch/x86/um/asm/ptrace_64.h
+++ b/arch/x86/um/asm/ptrace_64.h
@@ -15,13 +15,6 @@
#define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
-#define PT_REGS_RBX(r) UPT_RBX(&(r)->regs)
-#define PT_REGS_RCX(r) UPT_RCX(&(r)->regs)
-#define PT_REGS_RDX(r) UPT_RDX(&(r)->regs)
-#define PT_REGS_RSI(r) UPT_RSI(&(r)->regs)
-#define PT_REGS_RDI(r) UPT_RDI(&(r)->regs)
-#define PT_REGS_RBP(r) UPT_RBP(&(r)->regs)
-#define PT_REGS_RAX(r) UPT_RAX(&(r)->regs)
#define PT_REGS_R8(r) UPT_R8(&(r)->regs)
#define PT_REGS_R9(r) UPT_R9(&(r)->regs)
#define PT_REGS_R10(r) UPT_R10(&(r)->regs)
@@ -31,27 +24,8 @@
#define PT_REGS_R14(r) UPT_R14(&(r)->regs)
#define PT_REGS_R15(r) UPT_R15(&(r)->regs)
-#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
-#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
-#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
-#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
-#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
-#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
-
-#define PT_REGS_ORIG_RAX(r) UPT_ORIG_RAX(&(r)->regs)
-#define PT_REGS_RIP(r) UPT_IP(&(r)->regs)
-#define PT_REGS_SP(r) UPT_SP(&(r)->regs)
-
-#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
-
/* XXX */
#define user_mode(r) UPT_IS_USER(&(r)->regs)
-#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_RAX(r)
-#define PT_REGS_SYSCALL_RET(r) PT_REGS_RAX(r)
-
-#define PT_FIX_EXEC_STACK(sp) do ; while(0)
-
-#define profile_pc(regs) PT_REGS_IP(regs)
struct user_desc;
diff --git a/arch/x86/um/checksum_32.S b/arch/x86/um/checksum_32.S
index f058d2f82e18..8d0c420465cc 100644
--- a/arch/x86/um/checksum_32.S
+++ b/arch/x86/um/checksum_32.S
@@ -26,6 +26,7 @@
*/
#include <asm/errno.h>
+#include <asm/asm.h>
/*
* computes a partial checksum, e.g. for TCP/UDP fragments
@@ -232,15 +233,11 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst,
#define SRC(y...) \
9999: y; \
- .section __ex_table, "a"; \
- .long 9999b, 6001f ; \
- .previous
+ _ASM_EXTABLE(9999b, 6001f)
#define DST(y...) \
9999: y; \
- .section __ex_table, "a"; \
- .long 9999b, 6002f ; \
- .previous
+ _ASM_EXTABLE(9999b, 6002f)
.align 4
diff --git a/arch/x86/um/shared/sysdep/ptrace.h b/arch/x86/um/shared/sysdep/ptrace.h
index 2bbe1ec2d96a..6ce2d76eb908 100644
--- a/arch/x86/um/shared/sysdep/ptrace.h
+++ b/arch/x86/um/shared/sysdep/ptrace.h
@@ -1,15 +1,74 @@
#ifndef __SYSDEP_X86_PTRACE_H
#define __SYSDEP_X86_PTRACE_H
+#include <generated/user_constants.h>
+#include "sysdep/faultinfo.h"
+
+#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
+
+#define REGS_IP(r) ((r)[HOST_IP])
+#define REGS_SP(r) ((r)[HOST_SP])
+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
+#define REGS_AX(r) ((r)[HOST_AX])
+#define REGS_BX(r) ((r)[HOST_BX])
+#define REGS_CX(r) ((r)[HOST_CX])
+#define REGS_DX(r) ((r)[HOST_DX])
+#define REGS_SI(r) ((r)[HOST_SI])
+#define REGS_DI(r) ((r)[HOST_DI])
+#define REGS_BP(r) ((r)[HOST_BP])
+#define REGS_CS(r) ((r)[HOST_CS])
+#define REGS_SS(r) ((r)[HOST_SS])
+#define REGS_DS(r) ((r)[HOST_DS])
+#define REGS_ES(r) ((r)[HOST_ES])
+
+#define UPT_IP(r) REGS_IP((r)->gp)
+#define UPT_SP(r) REGS_SP((r)->gp)
+#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
+#define UPT_AX(r) REGS_AX((r)->gp)
+#define UPT_BX(r) REGS_BX((r)->gp)
+#define UPT_CX(r) REGS_CX((r)->gp)
+#define UPT_DX(r) REGS_DX((r)->gp)
+#define UPT_SI(r) REGS_SI((r)->gp)
+#define UPT_DI(r) REGS_DI((r)->gp)
+#define UPT_BP(r) REGS_BP((r)->gp)
+#define UPT_CS(r) REGS_CS((r)->gp)
+#define UPT_SS(r) REGS_SS((r)->gp)
+#define UPT_DS(r) REGS_DS((r)->gp)
+#define UPT_ES(r) REGS_ES((r)->gp)
+
#ifdef __i386__
#include "ptrace_32.h"
#else
#include "ptrace_64.h"
#endif
-static inline long regs_return_value(struct uml_pt_regs *regs)
-{
- return UPT_SYSCALL_RET(regs);
-}
+struct syscall_args {
+ unsigned long args[6];
+};
+
+#define SYSCALL_ARGS(r) ((struct syscall_args) \
+ { .args = { UPT_SYSCALL_ARG1(r), \
+ UPT_SYSCALL_ARG2(r), \
+ UPT_SYSCALL_ARG3(r), \
+ UPT_SYSCALL_ARG4(r), \
+ UPT_SYSCALL_ARG5(r), \
+ UPT_SYSCALL_ARG6(r) } } )
+
+struct uml_pt_regs {
+ unsigned long gp[MAX_REG_NR];
+ unsigned long fp[MAX_FP_NR];
+ struct faultinfo faultinfo;
+ long syscall;
+ int is_user;
+};
+
+#define EMPTY_UML_PT_REGS { }
+
+#define UPT_SYSCALL_NR(r) ((r)->syscall)
+#define UPT_FAULTINFO(r) (&(r)->faultinfo)
+#define UPT_IS_USER(r) ((r)->is_user)
+
+extern int user_context(unsigned long sp);
#endif /* __SYSDEP_X86_PTRACE_H */
diff --git a/arch/x86/um/shared/sysdep/ptrace_32.h b/arch/x86/um/shared/sysdep/ptrace_32.h
index befd1df32ed0..b94a108de1dc 100644
--- a/arch/x86/um/shared/sysdep/ptrace_32.h
+++ b/arch/x86/um/shared/sysdep/ptrace_32.h
@@ -6,11 +6,7 @@
#ifndef __SYSDEP_I386_PTRACE_H
#define __SYSDEP_I386_PTRACE_H
-#include <generated/user_constants.h>
-#include "sysdep/faultinfo.h"
-
-#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
-#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+#define MAX_FP_NR HOST_FPX_SIZE
static inline void update_debugregs(int seq) {}
@@ -24,90 +20,16 @@ void set_using_sysemu(int value);
int get_using_sysemu(void);
extern int sysemu_supported;
-#define REGS_IP(r) ((r)[HOST_IP])
-#define REGS_SP(r) ((r)[HOST_SP])
-#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
-#define REGS_EAX(r) ((r)[HOST_AX])
-#define REGS_EBX(r) ((r)[HOST_BX])
-#define REGS_ECX(r) ((r)[HOST_CX])
-#define REGS_EDX(r) ((r)[HOST_DX])
-#define REGS_ESI(r) ((r)[HOST_SI])
-#define REGS_EDI(r) ((r)[HOST_DI])
-#define REGS_EBP(r) ((r)[HOST_BP])
-#define REGS_CS(r) ((r)[HOST_CS])
-#define REGS_SS(r) ((r)[HOST_SS])
-#define REGS_DS(r) ((r)[HOST_DS])
-#define REGS_ES(r) ((r)[HOST_ES])
-#define REGS_FS(r) ((r)[HOST_FS])
-#define REGS_GS(r) ((r)[HOST_GS])
-
-#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res)
-
-#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
-
#ifndef PTRACE_SYSEMU_SINGLESTEP
#define PTRACE_SYSEMU_SINGLESTEP 32
#endif
-struct uml_pt_regs {
- unsigned long gp[MAX_REG_NR];
- unsigned long fp[HOST_FPX_SIZE];
- struct faultinfo faultinfo;
- long syscall;
- int is_user;
-};
-
-#define EMPTY_UML_PT_REGS { }
-
-#define UPT_IP(r) REGS_IP((r)->gp)
-#define UPT_SP(r) REGS_SP((r)->gp)
-#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
-#define UPT_EAX(r) REGS_EAX((r)->gp)
-#define UPT_EBX(r) REGS_EBX((r)->gp)
-#define UPT_ECX(r) REGS_ECX((r)->gp)
-#define UPT_EDX(r) REGS_EDX((r)->gp)
-#define UPT_ESI(r) REGS_ESI((r)->gp)
-#define UPT_EDI(r) REGS_EDI((r)->gp)
-#define UPT_EBP(r) REGS_EBP((r)->gp)
-#define UPT_ORIG_EAX(r) ((r)->syscall)
-#define UPT_CS(r) REGS_CS((r)->gp)
-#define UPT_SS(r) REGS_SS((r)->gp)
-#define UPT_DS(r) REGS_DS((r)->gp)
-#define UPT_ES(r) REGS_ES((r)->gp)
-#define UPT_FS(r) REGS_FS((r)->gp)
-#define UPT_GS(r) REGS_GS((r)->gp)
-
-#define UPT_SYSCALL_ARG1(r) UPT_EBX(r)
-#define UPT_SYSCALL_ARG2(r) UPT_ECX(r)
-#define UPT_SYSCALL_ARG3(r) UPT_EDX(r)
-#define UPT_SYSCALL_ARG4(r) UPT_ESI(r)
-#define UPT_SYSCALL_ARG5(r) UPT_EDI(r)
-#define UPT_SYSCALL_ARG6(r) UPT_EBP(r)
-
-extern int user_context(unsigned long sp);
-
-#define UPT_IS_USER(r) ((r)->is_user)
-
-struct syscall_args {
- unsigned long args[6];
-};
-
-#define SYSCALL_ARGS(r) ((struct syscall_args) \
- { .args = { UPT_SYSCALL_ARG1(r), \
- UPT_SYSCALL_ARG2(r), \
- UPT_SYSCALL_ARG3(r), \
- UPT_SYSCALL_ARG4(r), \
- UPT_SYSCALL_ARG5(r), \
- UPT_SYSCALL_ARG6(r) } } )
-
-#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
-
-#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
-#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
-#define UPT_SYSCALL_RET(r) UPT_EAX(r)
-
-#define UPT_FAULTINFO(r) (&(r)->faultinfo)
+#define UPT_SYSCALL_ARG1(r) UPT_BX(r)
+#define UPT_SYSCALL_ARG2(r) UPT_CX(r)
+#define UPT_SYSCALL_ARG3(r) UPT_DX(r)
+#define UPT_SYSCALL_ARG4(r) UPT_SI(r)
+#define UPT_SYSCALL_ARG5(r) UPT_DI(r)
+#define UPT_SYSCALL_ARG6(r) UPT_BP(r)
extern void arch_init_registers(int pid);
diff --git a/arch/x86/um/shared/sysdep/ptrace_64.h b/arch/x86/um/shared/sysdep/ptrace_64.h
index 031edc53ac57..919789f1071e 100644
--- a/arch/x86/um/shared/sysdep/ptrace_64.h
+++ b/arch/x86/um/shared/sysdep/ptrace_64.h
@@ -8,22 +8,8 @@
#ifndef __SYSDEP_X86_64_PTRACE_H
#define __SYSDEP_X86_64_PTRACE_H
-#include <generated/user_constants.h>
-#include "sysdep/faultinfo.h"
+#define MAX_FP_NR HOST_FP_SIZE
-#define MAX_REG_OFFSET (UM_FRAME_SIZE)
-#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
-
-#define REGS_IP(r) ((r)[HOST_IP])
-#define REGS_SP(r) ((r)[HOST_SP])
-
-#define REGS_RBX(r) ((r)[HOST_BX])
-#define REGS_RCX(r) ((r)[HOST_CX])
-#define REGS_RDX(r) ((r)[HOST_DX])
-#define REGS_RSI(r) ((r)[HOST_SI])
-#define REGS_RDI(r) ((r)[HOST_DI])
-#define REGS_RBP(r) ((r)[HOST_BP])
-#define REGS_RAX(r) ((r)[HOST_AX])
#define REGS_R8(r) ((r)[HOST_R8])
#define REGS_R9(r) ((r)[HOST_R9])
#define REGS_R10(r) ((r)[HOST_R10])
@@ -32,9 +18,6 @@
#define REGS_R13(r) ((r)[HOST_R13])
#define REGS_R14(r) ((r)[HOST_R14])
#define REGS_R15(r) ((r)[HOST_R15])
-#define REGS_CS(r) ((r)[HOST_CS])
-#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
-#define REGS_SS(r) ((r)[HOST_SS])
#define HOST_FS_BASE 21
#define HOST_GS_BASE 22
@@ -58,45 +41,6 @@
#define GS (HOST_GS * sizeof(long))
#endif
-#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE])
-#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE])
-#define REGS_DS(r) ((r)[HOST_DS])
-#define REGS_ES(r) ((r)[HOST_ES])
-#define REGS_FS(r) ((r)[HOST_FS])
-#define REGS_GS(r) ((r)[HOST_GS])
-
-#define REGS_ORIG_RAX(r) ((r)[HOST_ORIG_AX])
-
-#define REGS_SET_SYSCALL_RETURN(r, res) REGS_RAX(r) = (res)
-
-#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
-
-#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
-
-#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
-
-#define REGS_TRAP(r) ((r)->trap_type)
-
-#define REGS_ERR(r) ((r)->fault_type)
-
-struct uml_pt_regs {
- unsigned long gp[MAX_REG_NR];
- unsigned long fp[HOST_FP_SIZE];
- struct faultinfo faultinfo;
- long syscall;
- int is_user;
-};
-
-#define EMPTY_UML_PT_REGS { }
-
-#define UPT_RBX(r) REGS_RBX((r)->gp)
-#define UPT_RCX(r) REGS_RCX((r)->gp)
-#define UPT_RDX(r) REGS_RDX((r)->gp)
-#define UPT_RSI(r) REGS_RSI((r)->gp)
-#define UPT_RDI(r) REGS_RDI((r)->gp)
-#define UPT_RBP(r) REGS_RBP((r)->gp)
-#define UPT_RAX(r) REGS_RAX((r)->gp)
#define UPT_R8(r) REGS_R8((r)->gp)
#define UPT_R9(r) REGS_R9((r)->gp)
#define UPT_R10(r) REGS_R10((r)->gp)
@@ -105,51 +49,14 @@ struct uml_pt_regs {
#define UPT_R13(r) REGS_R13((r)->gp)
#define UPT_R14(r) REGS_R14((r)->gp)
#define UPT_R15(r) REGS_R15((r)->gp)
-#define UPT_CS(r) REGS_CS((r)->gp)
-#define UPT_FS_BASE(r) REGS_FS_BASE((r)->gp)
-#define UPT_FS(r) REGS_FS((r)->gp)
-#define UPT_GS_BASE(r) REGS_GS_BASE((r)->gp)
-#define UPT_GS(r) REGS_GS((r)->gp)
-#define UPT_DS(r) REGS_DS((r)->gp)
-#define UPT_ES(r) REGS_ES((r)->gp)
-#define UPT_CS(r) REGS_CS((r)->gp)
-#define UPT_SS(r) REGS_SS((r)->gp)
-#define UPT_ORIG_RAX(r) REGS_ORIG_RAX((r)->gp)
-
-#define UPT_IP(r) REGS_IP((r)->gp)
-#define UPT_SP(r) REGS_SP((r)->gp)
-
-#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
-#define UPT_SYSCALL_NR(r) ((r)->syscall)
-#define UPT_SYSCALL_RET(r) UPT_RAX(r)
-
-extern int user_context(unsigned long sp);
-#define UPT_IS_USER(r) ((r)->is_user)
-
-#define UPT_SYSCALL_ARG1(r) UPT_RDI(r)
-#define UPT_SYSCALL_ARG2(r) UPT_RSI(r)
-#define UPT_SYSCALL_ARG3(r) UPT_RDX(r)
+#define UPT_SYSCALL_ARG1(r) UPT_DI(r)
+#define UPT_SYSCALL_ARG2(r) UPT_SI(r)
+#define UPT_SYSCALL_ARG3(r) UPT_DX(r)
#define UPT_SYSCALL_ARG4(r) UPT_R10(r)
#define UPT_SYSCALL_ARG5(r) UPT_R8(r)
#define UPT_SYSCALL_ARG6(r) UPT_R9(r)
-struct syscall_args {
- unsigned long args[6];
-};
-
-#define SYSCALL_ARGS(r) ((struct syscall_args) \
- { .args = { UPT_SYSCALL_ARG1(r), \
- UPT_SYSCALL_ARG2(r), \
- UPT_SYSCALL_ARG3(r), \
- UPT_SYSCALL_ARG4(r), \
- UPT_SYSCALL_ARG5(r), \
- UPT_SYSCALL_ARG6(r) } } )
-
-#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
-
-#define UPT_FAULTINFO(r) (&(r)->faultinfo)
-
static inline void arch_init_registers(int pid)
{
}
diff --git a/arch/x86/um/signal.c b/arch/x86/um/signal.c
index 4883b9546016..bb0fb03b9f85 100644
--- a/arch/x86/um/signal.c
+++ b/arch/x86/um/signal.c
@@ -156,6 +156,9 @@ static int copy_sc_from_user(struct pt_regs *regs,
struct sigcontext sc;
int err, pid;
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
err = copy_from_user(&sc, from, sizeof(sc));
if (err)
return err;
@@ -410,9 +413,9 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
PT_REGS_SP(regs) = (unsigned long) frame;
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
- PT_REGS_EAX(regs) = (unsigned long) sig;
- PT_REGS_EDX(regs) = (unsigned long) 0;
- PT_REGS_ECX(regs) = (unsigned long) 0;
+ PT_REGS_AX(regs) = (unsigned long) sig;
+ PT_REGS_DX(regs) = (unsigned long) 0;
+ PT_REGS_CX(regs) = (unsigned long) 0;
if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
ptrace_notify(SIGTRAP);
@@ -460,9 +463,9 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
PT_REGS_SP(regs) = (unsigned long) frame;
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
- PT_REGS_EAX(regs) = (unsigned long) sig;
- PT_REGS_EDX(regs) = (unsigned long) &frame->info;
- PT_REGS_ECX(regs) = (unsigned long) &frame->uc;
+ PT_REGS_AX(regs) = (unsigned long) sig;
+ PT_REGS_DX(regs) = (unsigned long) &frame->info;
+ PT_REGS_CX(regs) = (unsigned long) &frame->uc;
if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
ptrace_notify(SIGTRAP);
@@ -541,8 +544,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
set->sig[0]);
err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
if (sizeof(*set) == 16) {
- __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
- __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
+ err |= __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
+ err |= __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
}
else
err |= __copy_to_user(&frame->uc.uc_sigmask, set,
@@ -570,17 +573,17 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
}
PT_REGS_SP(regs) = (unsigned long) frame;
- PT_REGS_RDI(regs) = sig;
+ PT_REGS_DI(regs) = sig;
/* In case the signal handler was declared without prototypes */
- PT_REGS_RAX(regs) = 0;
+ PT_REGS_AX(regs) = 0;
/*
* This also works for non SA_SIGINFO handlers because they expect the
* next argument after the signal number on the stack.
*/
- PT_REGS_RSI(regs) = (unsigned long) &frame->info;
- PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
- PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
+ PT_REGS_SI(regs) = (unsigned long) &frame->info;
+ PT_REGS_DX(regs) = (unsigned long) &frame->uc;
+ PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
out:
return err;
}
diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c
index 9924776f4265..170bd926a69c 100644
--- a/arch/x86/um/sys_call_table_64.c
+++ b/arch/x86/um/sys_call_table_64.c
@@ -31,7 +31,6 @@
#define stub_fork sys_fork
#define stub_vfork sys_vfork
#define stub_execve sys_execve
-#define stub_rt_sigsuspend sys_rt_sigsuspend
#define stub_sigaltstack sys_sigaltstack
#define stub_rt_sigreturn sys_rt_sigreturn
diff --git a/arch/x86/um/syscalls_32.c b/arch/x86/um/syscalls_32.c
index 70ca357393b8..b853e8600b9d 100644
--- a/arch/x86/um/syscalls_32.c
+++ b/arch/x86/um/syscalls_32.c
@@ -44,10 +44,10 @@ long sys_sigaction(int sig, const struct old_sigaction __user *act,
old_sigset_t mask;
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
+ __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+ __get_user(mask, &act->sa_mask))
return -EFAULT;
- __get_user(new_ka.sa.sa_flags, &act->sa_flags);
- __get_user(mask, &act->sa_mask);
siginitset(&new_ka.sa.sa_mask, mask);
}
@@ -56,10 +56,10 @@ long sys_sigaction(int sig, const struct old_sigaction __user *act,
if (!ret && oact) {
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
return -EFAULT;
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
}
return ret;
diff --git a/arch/x86/um/sysrq_32.c b/arch/x86/um/sysrq_32.c
index 171b3e9dc867..2d5cc51e9bef 100644
--- a/arch/x86/um/sysrq_32.c
+++ b/arch/x86/um/sysrq_32.c
@@ -23,12 +23,10 @@ void show_regs(struct pt_regs *regs)
printk(" EFLAGS: %08lx\n %s\n", PT_REGS_EFLAGS(regs),
print_tainted());
printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
- PT_REGS_EAX(regs), PT_REGS_EBX(regs),
- PT_REGS_ECX(regs),
- PT_REGS_EDX(regs));
+ PT_REGS_AX(regs), PT_REGS_BX(regs),
+ PT_REGS_CX(regs), PT_REGS_DX(regs));
printk("ESI: %08lx EDI: %08lx EBP: %08lx",
- PT_REGS_ESI(regs), PT_REGS_EDI(regs),
- PT_REGS_EBP(regs));
+ PT_REGS_SI(regs), PT_REGS_DI(regs), PT_REGS_BP(regs));
printk(" DS: %04lx ES: %04lx\n",
0xffff & PT_REGS_DS(regs),
0xffff & PT_REGS_ES(regs));
diff --git a/arch/x86/um/sysrq_64.c b/arch/x86/um/sysrq_64.c
index e8913436d7dc..08258f179969 100644
--- a/arch/x86/um/sysrq_64.c
+++ b/arch/x86/um/sysrq_64.c
@@ -19,15 +19,15 @@ void __show_regs(struct pt_regs *regs)
printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
current->comm, print_tainted(), init_utsname()->release);
printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
- PT_REGS_RIP(regs));
+ PT_REGS_IP(regs));
printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_SP(regs),
PT_REGS_EFLAGS(regs));
printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
- PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
+ PT_REGS_AX(regs), PT_REGS_BX(regs), PT_REGS_CX(regs));
printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
- PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs));
+ PT_REGS_DX(regs), PT_REGS_SI(regs), PT_REGS_DI(regs));
printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
- PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
+ PT_REGS_BP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
diff --git a/arch/x86/um/tls_32.c b/arch/x86/um/tls_32.c
index c6c7131e563b..baba84f8ecb8 100644
--- a/arch/x86/um/tls_32.c
+++ b/arch/x86/um/tls_32.c
@@ -219,7 +219,7 @@ int arch_copy_tls(struct task_struct *new)
int idx, ret = -EFAULT;
if (copy_from_user(&info,
- (void __user *) UPT_ESI(&new->thread.regs.regs),
+ (void __user *) UPT_SI(&new->thread.regs.regs),
sizeof(info)))
goto out;
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index add2c2d729ce..96ab2c09cb68 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -20,5 +20,5 @@ obj-$(CONFIG_EVENT_TRACING) += trace.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o
-obj-$(CONFIG_XEN_DOM0) += vga.o
+obj-$(CONFIG_XEN_DOM0) += apic.o vga.o
obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o
diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c
new file mode 100644
index 000000000000..ec57bd3818a4
--- /dev/null
+++ b/arch/x86/xen/apic.c
@@ -0,0 +1,33 @@
+#include <linux/init.h>
+
+#include <asm/x86_init.h>
+#include <asm/apic.h>
+#include <asm/xen/hypercall.h>
+
+#include <xen/xen.h>
+#include <xen/interface/physdev.h>
+
+unsigned int xen_io_apic_read(unsigned apic, unsigned reg)
+{
+ struct physdev_apic apic_op;
+ int ret;
+
+ apic_op.apic_physbase = mpc_ioapic_addr(apic);
+ apic_op.reg = reg;
+ ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
+ if (!ret)
+ return apic_op.value;
+
+ /* fallback to return an emulated IO_APIC values */
+ if (reg == 0x1)
+ return 0x00170020;
+ else if (reg == 0x0)
+ return apic << 24;
+
+ return 0xfd;
+}
+
+void __init xen_init_apic(void)
+{
+ x86_io_apic_ops.read = xen_io_apic_read;
+}
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 95dccce8e979..c0f5facdb10c 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1396,6 +1396,8 @@ asmlinkage void __init xen_start_kernel(void)
xen_start_info->console.domU.mfn = 0;
xen_start_info->console.domU.evtchn = 0;
+ xen_init_apic();
+
/* Make sure ACS will be enabled */
pci_request_acs();
}
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 69f5857660ac..3506cd4f9a43 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -1864,7 +1864,6 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
#endif /* CONFIG_X86_64 */
static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss;
-static unsigned char fake_ioapic_mapping[PAGE_SIZE] __page_aligned_bss;
static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
{
@@ -1905,7 +1904,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
* We just don't map the IO APIC - all access is via
* hypercalls. Keep the address in the pte for reference.
*/
- pte = pfn_pte(PFN_DOWN(__pa(fake_ioapic_mapping)), PAGE_KERNEL);
+ pte = pfn_pte(PFN_DOWN(__pa(dummy_mapping)), PAGE_KERNEL);
break;
#endif
@@ -2070,7 +2069,6 @@ void __init xen_init_mmu_ops(void)
pv_mmu_ops = xen_mmu_ops;
memset(dummy_mapping, 0xff, PAGE_SIZE);
- memset(fake_ioapic_mapping, 0xfd, PAGE_SIZE);
}
/* Protected by xen_reservation_lock. */
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 0503c0c493a9..3700945ed0d5 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -265,18 +265,8 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
set_cpu_possible(cpu, false);
}
- for_each_possible_cpu (cpu) {
- struct task_struct *idle;
-
- if (cpu == 0)
- continue;
-
- idle = fork_idle(cpu);
- if (IS_ERR(idle))
- panic("failed fork for CPU %d", cpu);
-
+ for_each_possible_cpu(cpu)
set_cpu_present(cpu, true);
- }
}
static int __cpuinit
@@ -346,9 +336,8 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
return 0;
}
-static int __cpuinit xen_cpu_up(unsigned int cpu)
+static int __cpuinit xen_cpu_up(unsigned int cpu, struct task_struct *idle)
{
- struct task_struct *idle = idle_task(cpu);
int rc;
per_cpu(current_task, cpu) = idle;
@@ -562,10 +551,10 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
xen_init_lock_cpu(0);
}
-static int __cpuinit xen_hvm_cpu_up(unsigned int cpu)
+static int __cpuinit xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
{
int rc;
- rc = native_cpu_up(cpu);
+ rc = native_cpu_up(cpu, tidle);
WARN_ON (xen_smp_intr_init(cpu));
return rc;
}
diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S
index b040b0e518ca..f9643fc50de5 100644
--- a/arch/x86/xen/xen-asm_32.S
+++ b/arch/x86/xen/xen-asm_32.S
@@ -14,6 +14,7 @@
#include <asm/thread_info.h>
#include <asm/processor-flags.h>
#include <asm/segment.h>
+#include <asm/asm.h>
#include <xen/interface/xen.h>
@@ -137,10 +138,7 @@ iret_restore_end:
1: iret
xen_iret_end_crit:
-.section __ex_table, "a"
- .align 4
- .long 1b, iret_exc
-.previous
+ _ASM_EXTABLE(1b, iret_exc)
hyper_iret:
/* put this out of line since its very rarely used */
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index b095739ccd4c..45c0c0667bd9 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -92,11 +92,15 @@ struct dom0_vga_console_info;
#ifdef CONFIG_XEN_DOM0
void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
+void __init xen_init_apic(void);
#else
static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
size_t size)
{
}
+static inline void __init xen_init_apic(void)
+{
+}
#endif
/* Declare an asm function, along with symbols needed to make it
diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h
index 3acb26e8dead..5c371d8d4528 100644
--- a/arch/xtensa/include/asm/processor.h
+++ b/arch/xtensa/include/asm/processor.h
@@ -168,9 +168,6 @@ struct mm_struct;
/* Free all resources held by a thread. */
#define release_thread(thread) do { } while(0)
-/* Prepare to copy thread state - unlazy all lazy status */
-extern void prepare_to_copy(struct task_struct*);
-
/* Create a kernel thread without removing it from tasklists */
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 2d2728b3e862..59fc3fe15572 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -6,7 +6,7 @@ extra-y := head.o vmlinux.lds
obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o \
setup.o signal.o syscall.o time.o traps.o vectors.o platform.o \
- pci-dma.o init_task.o io.o
+ pci-dma.o io.o
obj-$(CONFIG_KGDB) += xtensa-stub.o
obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/xtensa/kernel/init_task.c b/arch/xtensa/kernel/init_task.c
deleted file mode 100644
index cd122fb7e48a..000000000000
--- a/arch/xtensa/kernel/init_task.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * arch/xtensa/kernel/init_task.c
- *
- * Xtensa Processor version.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2007 Tensilica Inc.
- *
- * Chris Zankel <chris@zankel.net>
- */
-
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/module.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index 6a2d6edf8f72..9b306e550e3f 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -140,13 +140,16 @@ void flush_thread(void)
}
/*
- * This is called before the thread is copied.
+ * this gets called so that we can store coprocessor state into memory and
+ * copy the current task into the new thread.
*/
-void prepare_to_copy(struct task_struct *tsk)
+int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
#if XTENSA_HAVE_COPROCESSORS
- coprocessor_flush_all(task_thread_info(tsk));
+ coprocessor_flush_all(task_thread_info(src));
#endif
+ *dst = *src;
+ return 0;
}
/*
diff --git a/arch/xtensa/variants/s6000/dmac.c b/arch/xtensa/variants/s6000/dmac.c
index dc7f7c573518..340f5bb0b5ef 100644
--- a/arch/xtensa/variants/s6000/dmac.c
+++ b/arch/xtensa/variants/s6000/dmac.c
@@ -1,5 +1,5 @@
/*
- * Authors: Oskar Schirmer <os@emlix.com>
+ * Authors: Oskar Schirmer <oskar@scara.com>
* Daniel Gloeckner <dg@emlix.com>
* (c) 2008 emlix GmbH http://www.emlix.com
*
diff --git a/arch/xtensa/variants/s6000/gpio.c b/arch/xtensa/variants/s6000/gpio.c
index 7af0757e001b..b89541ba39ab 100644
--- a/arch/xtensa/variants/s6000/gpio.c
+++ b/arch/xtensa/variants/s6000/gpio.c
@@ -2,8 +2,8 @@
* s6000 gpio driver
*
* Copyright (c) 2009 emlix GmbH
- * Authors: Oskar Schirmer <os@emlix.com>
- * Johannes Weiner <jw@emlix.com>
+ * Authors: Oskar Schirmer <oskar@scara.com>
+ * Johannes Weiner <hannes@cmpxchg.org>
* Daniel Gloeckner <dg@emlix.com>
*/
#include <linux/bitops.h>
diff --git a/arch/xtensa/variants/s6000/include/variant/dmac.h b/arch/xtensa/variants/s6000/include/variant/dmac.h
index e81735b2a206..3f88d9fc6897 100644
--- a/arch/xtensa/variants/s6000/include/variant/dmac.h
+++ b/arch/xtensa/variants/s6000/include/variant/dmac.h
@@ -8,7 +8,7 @@
* Copyright (C) 2006 Tensilica Inc.
* Copyright (C) 2008 Emlix GmbH <info@emlix.com>
* Authors: Fabian Godehardt <fg@emlix.com>
- * Oskar Schirmer <os@emlix.com>
+ * Oskar Schirmer <oskar@scara.com>
* Daniel Gloeckner <dg@emlix.com>
*/
diff --git a/arch/xtensa/variants/s6000/irq.c b/arch/xtensa/variants/s6000/irq.c
index 6651e3285fcf..81a241e79075 100644
--- a/arch/xtensa/variants/s6000/irq.c
+++ b/arch/xtensa/variants/s6000/irq.c
@@ -2,8 +2,8 @@
* s6000 irq crossbar
*
* Copyright (c) 2009 emlix GmbH
- * Authors: Johannes Weiner <jw@emlix.com>
- * Oskar Schirmer <os@emlix.com>
+ * Authors: Johannes Weiner <hannes@cmpxchg.org>
+ * Oskar Schirmer <oskar@scara.com>
*/
#include <linux/io.h>
#include <asm/irq.h>
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index ea84a23d5e68..126c341955de 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -28,34 +28,12 @@ static LIST_HEAD(blkio_list);
struct blkio_cgroup blkio_root_cgroup = { .weight = 2*BLKIO_WEIGHT_DEFAULT };
EXPORT_SYMBOL_GPL(blkio_root_cgroup);
-static struct cgroup_subsys_state *blkiocg_create(struct cgroup *);
-static int blkiocg_can_attach(struct cgroup *, struct cgroup_taskset *);
-static void blkiocg_attach(struct cgroup *, struct cgroup_taskset *);
-static void blkiocg_destroy(struct cgroup *);
-static int blkiocg_populate(struct cgroup_subsys *, struct cgroup *);
-
/* for encoding cft->private value on file */
#define BLKIOFILE_PRIVATE(x, val) (((x) << 16) | (val))
/* What policy owns the file, proportional or throttle */
#define BLKIOFILE_POLICY(val) (((val) >> 16) & 0xffff)
#define BLKIOFILE_ATTR(val) ((val) & 0xffff)
-struct cgroup_subsys blkio_subsys = {
- .name = "blkio",
- .create = blkiocg_create,
- .can_attach = blkiocg_can_attach,
- .attach = blkiocg_attach,
- .destroy = blkiocg_destroy,
- .populate = blkiocg_populate,
-#ifdef CONFIG_BLK_CGROUP
- /* note: blkio_subsys_id is otherwise defined in blk-cgroup.h */
- .subsys_id = blkio_subsys_id,
-#endif
- .use_id = 1,
- .module = THIS_MODULE,
-};
-EXPORT_SYMBOL_GPL(blkio_subsys);
-
static inline void blkio_policy_insert_node(struct blkio_cgroup *blkcg,
struct blkio_policy_node *pn)
{
@@ -1537,14 +1515,9 @@ struct cftype blkio_files[] = {
.read_map = blkiocg_file_read_map,
},
#endif
+ { } /* terminate */
};
-static int blkiocg_populate(struct cgroup_subsys *subsys, struct cgroup *cgroup)
-{
- return cgroup_add_files(cgroup, subsys, blkio_files,
- ARRAY_SIZE(blkio_files));
-}
-
static void blkiocg_destroy(struct cgroup *cgroup)
{
struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
@@ -1658,6 +1631,22 @@ static void blkiocg_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
}
}
+struct cgroup_subsys blkio_subsys = {
+ .name = "blkio",
+ .create = blkiocg_create,
+ .can_attach = blkiocg_can_attach,
+ .attach = blkiocg_attach,
+ .destroy = blkiocg_destroy,
+#ifdef CONFIG_BLK_CGROUP
+ /* note: blkio_subsys_id is otherwise defined in blk-cgroup.h */
+ .subsys_id = blkio_subsys_id,
+#endif
+ .base_cftypes = blkio_files,
+ .use_id = 1,
+ .module = THIS_MODULE,
+};
+EXPORT_SYMBOL_GPL(blkio_subsys);
+
void blkio_policy_register(struct blkio_policy_type *blkiop)
{
spin_lock(&blkio_list_lock);
diff --git a/block/genhd.c b/block/genhd.c
index df9816ede75b..9cf5583c90ff 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -743,7 +743,7 @@ void __init printk_all_partitions(void)
struct hd_struct *part;
char name_buf[BDEVNAME_SIZE];
char devt_buf[BDEVT_SIZE];
- u8 uuid[PARTITION_META_INFO_UUIDLTH * 2 + 1];
+ char uuid_buf[PARTITION_META_INFO_UUIDLTH * 2 + 5];
/*
* Don't show empty devices or things that have been
@@ -762,14 +762,16 @@ void __init printk_all_partitions(void)
while ((part = disk_part_iter_next(&piter))) {
bool is_part0 = part == &disk->part0;
- uuid[0] = 0;
+ uuid_buf[0] = '\0';
if (part->info)
- part_unpack_uuid(part->info->uuid, uuid);
+ snprintf(uuid_buf, sizeof(uuid_buf), "%pU",
+ part->info->uuid);
printk("%s%s %10llu %s %s", is_part0 ? "" : " ",
bdevt_str(part_devt(part), devt_buf),
(unsigned long long)part->nr_sects >> 1,
- disk_name(disk, part->partno, name_buf), uuid);
+ disk_name(disk, part->partno, name_buf),
+ uuid_buf);
if (is_part0) {
if (disk->driverfs_dev != NULL &&
disk->driverfs_dev->driver != NULL)
diff --git a/block/partitions/ibm.c b/block/partitions/ibm.c
index d513a07f44bb..1104acac780b 100644
--- a/block/partitions/ibm.c
+++ b/block/partitions/ibm.c
@@ -253,7 +253,7 @@ int ibm_partition(struct parsed_partitions *state)
/* Are we not supposed to report this ? */
goto out_readerr;
} else
- printk(KERN_WARNING "Warning, expected Label VOL1 not "
+ printk(KERN_INFO "Expected Label VOL1 not "
"found, treating as CDL formated Disk");
}
diff --git a/crypto/xor.c b/crypto/xor.c
index b75182d8ab14..65c7b416b4a3 100644
--- a/crypto/xor.c
+++ b/crypto/xor.c
@@ -21,6 +21,7 @@
#include <linux/gfp.h>
#include <linux/raid/xor.h>
#include <linux/jiffies.h>
+#include <linux/preempt.h>
#include <asm/xor.h>
/* The xor routines to use. */
@@ -63,12 +64,14 @@ static void
do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
{
int speed;
- unsigned long now;
+ unsigned long now, j;
int i, count, max;
tmpl->next = template_list;
template_list = tmpl;
+ preempt_disable();
+
/*
* Count the number of XORs done during a whole jiffy, and use
* this to calculate the speed of checksumming. We use a 2-page
@@ -76,9 +79,11 @@ do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
*/
max = 0;
for (i = 0; i < 5; i++) {
- now = jiffies;
+ j = jiffies;
count = 0;
- while (jiffies == now) {
+ while ((now = jiffies) == j)
+ cpu_relax();
+ while (time_before(jiffies, now + 1)) {
mb(); /* prevent loop optimzation */
tmpl->do_2(BENCH_SIZE, b1, b2);
mb();
@@ -89,6 +94,8 @@ do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
max = count;
}
+ preempt_enable();
+
speed = max * (HZ * BENCH_SIZE / 1024);
tmpl->speed = speed;
@@ -129,9 +136,9 @@ calibrate_xor_blocks(void)
if (fastest) {
printk(KERN_INFO "xor: automatically using best "
- "checksumming function: %s\n",
- fastest->name);
+ "checksumming function:\n");
xor_speed(fastest);
+ goto out;
} else {
printk(KERN_INFO "xor: measuring software checksum speed\n");
XOR_TRY_TEMPLATES;
@@ -146,6 +153,7 @@ calibrate_xor_blocks(void)
#undef xor_speed
+ out:
free_pages((unsigned long)b1, 2);
active_template = fastest;
diff --git a/drivers/Kconfig b/drivers/Kconfig
index d236aef7e59f..bfc918633fd9 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -140,4 +140,12 @@ source "drivers/virt/Kconfig"
source "drivers/devfreq/Kconfig"
+source "drivers/extcon/Kconfig"
+
+source "drivers/memory/Kconfig"
+
+source "drivers/iio/Kconfig"
+
+source "drivers/vme/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index f9b82f2c7c47..0ee98d50f975 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -133,3 +133,7 @@ obj-$(CONFIG_VIRT_DRIVERS) += virt/
obj-$(CONFIG_HYPERV) += hv/
obj-$(CONFIG_PM_DEVFREQ) += devfreq/
+obj-$(CONFIG_EXTCON) += extcon/
+obj-$(CONFIG_MEMORY) += memory/
+obj-$(CONFIG_IIO) += iio/
+obj-$(CONFIG_VME_BUS) += vme/
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 3263b68cdfa3..3188da3df8da 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -250,6 +250,10 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state)
return -ENODEV;
}
+ /* For D3cold we should execute _PS3, not _PS4. */
+ if (state == ACPI_STATE_D3_COLD)
+ object_name[3] = '3';
+
/*
* Transition Power
* ----------------
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 29a4a5c8ee00..1564e0927c21 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -69,6 +69,7 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
up_read(&bus_type_sem);
return ret;
}
+EXPORT_SYMBOL_GPL(register_acpi_bus_type);
static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle)
{
@@ -85,6 +86,7 @@ static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle)
up_read(&bus_type_sem);
return ret;
}
+EXPORT_SYMBOL_GPL(unregister_acpi_bus_type);
/* Get device's handler per its address under its parent */
struct acpi_find_child {
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 4a29763b8eb4..a12808259dfb 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -720,21 +720,21 @@ static int acpi_pci_link_add(struct acpi_device *device)
acpi_device_bid(device));
for (i = 0; i < link->irq.possible_count; i++) {
if (link->irq.active == link->irq.possible[i]) {
- printk(" *%d", link->irq.possible[i]);
+ printk(KERN_CONT " *%d", link->irq.possible[i]);
found = 1;
} else
- printk(" %d", link->irq.possible[i]);
+ printk(KERN_CONT " %d", link->irq.possible[i]);
}
- printk(")");
+ printk(KERN_CONT ")");
if (!found)
- printk(" *%d", link->irq.active);
+ printk(KERN_CONT " *%d", link->irq.active);
if (!link->device->status.enabled)
- printk(", disabled.");
+ printk(KERN_CONT ", disabled.");
- printk("\n");
+ printk(KERN_CONT "\n");
list_add_tail(&link->list, &acpi_link_list);
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 330bb4d75852..0500f719f63e 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -660,7 +660,7 @@ int acpi_power_on_resources(struct acpi_device *device, int state)
int acpi_power_transition(struct acpi_device *device, int state)
{
- int result;
+ int result = 0;
if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
return -EINVAL;
@@ -679,8 +679,11 @@ int acpi_power_transition(struct acpi_device *device, int state)
* (e.g. so the device doesn't lose power while transitioning). Then,
* we dereference all power resources used in the current list.
*/
- result = acpi_power_on_list(&device->power.states[state].resources);
- if (!result)
+ if (state < ACPI_STATE_D3_COLD)
+ result = acpi_power_on_list(
+ &device->power.states[state].resources);
+
+ if (!result && device->power.state < ACPI_STATE_D3_COLD)
acpi_power_off_list(
&device->power.states[device->power.state].resources);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 7417267e88fa..85cbfdccc97c 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -908,6 +908,10 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
device->power.states[ACPI_STATE_D3].flags.valid = 1;
device->power.states[ACPI_STATE_D3].power = 0;
+ /* Set D3cold's explicit_set flag if _PS3 exists. */
+ if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set)
+ device->power.states[ACPI_STATE_D3_COLD].flags.explicit_set = 1;
+
acpi_bus_init_power(device);
return 0;
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index eb6fd233764b..06527c526618 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -887,7 +887,7 @@ int __init acpi_sleep_init(void)
status = acpi_get_sleep_type_data(i, &type_a, &type_b);
if (ACPI_SUCCESS(status)) {
sleep_states[i] = 1;
- printk(" S%d", i);
+ printk(KERN_CONT " S%d", i);
}
}
@@ -901,7 +901,7 @@ int __init acpi_sleep_init(void)
hibernation_set_ops(old_suspend_ordering ?
&acpi_hibernation_ops_old : &acpi_hibernation_ops);
sleep_states[ACPI_STATE_S4] = 1;
- printk(" S4");
+ printk(KERN_CONT " S4");
if (!nosigcheck) {
acpi_get_table(ACPI_SIG_FACS, 1,
(struct acpi_table_header **)&facs);
@@ -914,11 +914,11 @@ int __init acpi_sleep_init(void)
status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
if (ACPI_SUCCESS(status)) {
sleep_states[ACPI_STATE_S5] = 1;
- printk(" S5");
+ printk(KERN_CONT " S5");
pm_power_off_prepare = acpi_power_off_prepare;
pm_power_off = acpi_power_off;
}
- printk(")\n");
+ printk(KERN_CONT ")\n");
/*
* Register the tts_notifier to reboot notifier list so that the _TTS
* object can also be evaluated when the system enters S5.
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index b002a471c5d4..adbbc1c80a26 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -382,3 +382,33 @@ acpi_evaluate_reference(acpi_handle handle,
}
EXPORT_SYMBOL(acpi_evaluate_reference);
+
+acpi_status
+acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld *pld)
+{
+ acpi_status status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *output;
+
+ status = acpi_evaluate_object(handle, "_PLD", NULL, &buffer);
+
+ if (ACPI_FAILURE(status))
+ return status;
+
+ output = buffer.pointer;
+
+ if (!output || output->type != ACPI_TYPE_PACKAGE
+ || !output->package.count
+ || output->package.elements[0].type != ACPI_TYPE_BUFFER
+ || output->package.elements[0].buffer.length > sizeof(*pld)) {
+ status = AE_TYPE;
+ goto out;
+ }
+
+ memcpy(pld, output->package.elements[0].buffer.pointer,
+ output->package.elements[0].buffer.length);
+out:
+ kfree(buffer.pointer);
+ return status;
+}
+EXPORT_SYMBOL(acpi_get_physical_device_location);
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index cc273226dbd0..b7e728517284 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -527,9 +527,9 @@ int amba_device_add(struct amba_device *dev, struct resource *parent)
if (ret)
goto err_release;
- if (dev->irq[0] && dev->irq[0] != NO_IRQ)
+ if (dev->irq[0])
ret = device_create_file(&dev->dev, &dev_attr_irq0);
- if (ret == 0 && dev->irq[1] && dev->irq[1] != NO_IRQ)
+ if (ret == 0 && dev->irq[1])
ret = device_create_file(&dev->dev, &dev_attr_irq1);
if (ret == 0)
return ret;
@@ -543,6 +543,55 @@ int amba_device_add(struct amba_device *dev, struct resource *parent)
}
EXPORT_SYMBOL_GPL(amba_device_add);
+static struct amba_device *
+amba_aphb_device_add(struct device *parent, const char *name,
+ resource_size_t base, size_t size, int irq1, int irq2,
+ void *pdata, unsigned int periphid, u64 dma_mask)
+{
+ struct amba_device *dev;
+ int ret;
+
+ dev = amba_device_alloc(name, base, size);
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
+ dev->dma_mask = dma_mask;
+ dev->dev.coherent_dma_mask = dma_mask;
+ dev->irq[0] = irq1;
+ dev->irq[1] = irq2;
+ dev->periphid = periphid;
+ dev->dev.platform_data = pdata;
+ dev->dev.parent = parent;
+
+ ret = amba_device_add(dev, &iomem_resource);
+ if (ret) {
+ amba_device_put(dev);
+ return ERR_PTR(ret);
+ }
+
+ return dev;
+}
+
+struct amba_device *
+amba_apb_device_add(struct device *parent, const char *name,
+ resource_size_t base, size_t size, int irq1, int irq2,
+ void *pdata, unsigned int periphid)
+{
+ return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata,
+ periphid, 0);
+}
+EXPORT_SYMBOL_GPL(amba_apb_device_add);
+
+struct amba_device *
+amba_ahb_device_add(struct device *parent, const char *name,
+ resource_size_t base, size_t size, int irq1, int irq2,
+ void *pdata, unsigned int periphid)
+{
+ return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata,
+ periphid, ~0ULL);
+}
+EXPORT_SYMBOL_GPL(amba_ahb_device_add);
+
static void amba_device_initialize(struct amba_device *dev, const char *name)
{
device_initialize(&dev->dev);
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 6bdedd7cca2c..2be8ef1d3093 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -416,6 +416,15 @@ config PATA_EFAR
If unsure, say N.
+config PATA_EP93XX
+ tristate "Cirrus Logic EP93xx PATA support"
+ depends on ARCH_EP93XX
+ help
+ This option enables support for the PATA controller in
+ the Cirrus Logic EP9312 and EP9315 ARM CPU.
+
+ If unsure, say N.
+
config PATA_HPT366
tristate "HPT 366/368 PATA support"
depends on PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 6ece5b7231a3..a454a139b1d2 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_PATA_CS5535) += pata_cs5535.o
obj-$(CONFIG_PATA_CS5536) += pata_cs5536.o
obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o
obj-$(CONFIG_PATA_EFAR) += pata_efar.o
+obj-$(CONFIG_PATA_EP93XX) += pata_ep93xx.o
obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o
obj-$(CONFIG_PATA_HPT37X) += pata_hpt37x.o
obj-$(CONFIG_PATA_HPT3X2N) += pata_hpt3x2n.o
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 7df56ec31819..aae115600b74 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -177,7 +177,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
if ((id->driver_data & ATA_GEN_CLASS_MATCH) && all_generic_ide == 0)
return -ENODEV;
- if (id->driver_data & ATA_GEN_INTEL_IDER)
+ if ((id->driver_data & ATA_GEN_INTEL_IDER) && !all_generic_ide)
if (!is_intel_ider(dev))
return -ENODEV;
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 7857e8fd0a3e..3c809bfbccf5 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -1554,6 +1554,39 @@ static bool piix_broken_system_poweroff(struct pci_dev *pdev)
return false;
}
+static int prefer_ms_hyperv = 1;
+module_param(prefer_ms_hyperv, int, 0);
+
+static void piix_ignore_devices_quirk(struct ata_host *host)
+{
+#if IS_ENABLED(CONFIG_HYPERV_STORAGE)
+ static const struct dmi_system_id ignore_hyperv[] = {
+ {
+ /* On Hyper-V hypervisors the disks are exposed on
+ * both the emulated SATA controller and on the
+ * paravirtualised drivers. The CD/DVD devices
+ * are only exposed on the emulated controller.
+ * Request we ignore ATA devices on this host.
+ */
+ .ident = "Hyper-V Virtual Machine",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "Microsoft Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+ },
+ },
+ { } /* terminate list */
+ };
+ const struct dmi_system_id *dmi = dmi_first_match(ignore_hyperv);
+
+ if (dmi && prefer_ms_hyperv) {
+ host->flags |= ATA_HOST_IGNORE_ATA;
+ dev_info(host->dev, "%s detected, ATA device ignore set\n",
+ dmi->ident);
+ }
+#endif
+}
+
/**
* piix_init_one - Register PIIX ATA PCI device with kernel services
* @pdev: PCI device to register
@@ -1669,6 +1702,9 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
}
host->flags |= ATA_HOST_PARALLEL_SCAN;
+ /* Allow hosts to specify device types to ignore when scanning. */
+ piix_ignore_devices_quirk(host);
+
pci_set_master(pdev);
return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 23763a1ec570..cece3a4d11ea 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1973,6 +1973,12 @@ retry:
if (class == ATA_DEV_ATA) {
if (!ata_id_is_ata(id) && !ata_id_is_cfa(id))
goto err_out;
+ if (ap->host->flags & ATA_HOST_IGNORE_ATA &&
+ ata_id_is_ata(id)) {
+ ata_dev_dbg(dev,
+ "host indicates ignore ATA devices, ignored\n");
+ return -ENOENT;
+ }
} else {
if (ata_id_is_ata(id))
goto err_out;
@@ -4051,6 +4057,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA },
{ "SAMSUNG CD-ROM SN-124", "N001", ATA_HORKAGE_NODMA },
{ "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA },
+ { "2GB ATA Flash Disk", "ADMA428M", ATA_HORKAGE_NODMA },
/* Odd clown on sil3726/4726 PMPs */
{ "Config Disk", NULL, ATA_HORKAGE_DISABLE },
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index d1fbd59ead16..6d53cf9b3b6e 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2047,6 +2047,26 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
}
/**
+ * ata_eh_worth_retry - analyze error and decide whether to retry
+ * @qc: qc to possibly retry
+ *
+ * Look at the cause of the error and decide if a retry
+ * might be useful or not. We don't want to retry media errors
+ * because the drive itself has probably already taken 10-30 seconds
+ * doing its own internal retries before reporting the failure.
+ */
+static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc)
+{
+ if (qc->flags & AC_ERR_MEDIA)
+ return 0; /* don't retry media errors */
+ if (qc->flags & ATA_QCFLAG_IO)
+ return 1; /* otherwise retry anything from fs stack */
+ if (qc->err_mask & AC_ERR_INVALID)
+ return 0; /* don't retry these */
+ return qc->err_mask != AC_ERR_DEV; /* retry if not dev error */
+}
+
+/**
* ata_eh_link_autopsy - analyze error and determine recovery action
* @link: host link to perform autopsy on
*
@@ -2120,9 +2140,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
/* determine whether the command is worth retrying */
- if (qc->flags & ATA_QCFLAG_IO ||
- (!(qc->err_mask & AC_ERR_INVALID) &&
- qc->err_mask != AC_ERR_DEV))
+ if (ata_eh_worth_retry(qc))
qc->flags |= ATA_QCFLAG_RETRY;
/* accumulate error info */
diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c
new file mode 100644
index 000000000000..6ef2e3741f76
--- /dev/null
+++ b/drivers/ata/pata_ep93xx.c
@@ -0,0 +1,1044 @@
+/*
+ * EP93XX PATA controller driver.
+ *
+ * Copyright (c) 2012, Metasoft s.c.
+ * Rafal Prylowski <prylowski@metasoft.pl>
+ *
+ * Based on pata_scc.c, pata_icside.c and on earlier version of EP93XX
+ * PATA driver by Lennert Buytenhek and Alessandro Zummo.
+ * Read/Write timings, resource management and other improvements
+ * from driver by Joao Ramos and Bartlomiej Zolnierkiewicz.
+ * DMA engine support based on spi-ep93xx.c by Mika Westerberg.
+ *
+ * Original copyrights:
+ *
+ * Support for Cirrus Logic's EP93xx (EP9312, EP9315) CPUs
+ * PATA host controller driver.
+ *
+ * Copyright (c) 2009, Bartlomiej Zolnierkiewicz
+ *
+ * Heavily based on the ep93xx-ide.c driver:
+ *
+ * Copyright (c) 2009, Joao Ramos <joao.ramos@inov.pt>
+ * INESC Inovacao (INOV)
+ *
+ * EP93XX PATA controller driver.
+ * Copyright (C) 2007 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * An ATA driver for the Cirrus Logic EP93xx PATA controller.
+ *
+ * Based on an earlier version by Alessandro Zummo, which is:
+ * Copyright (C) 2006 Tower Technologies
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <scsi/scsi_host.h>
+#include <linux/ata.h>
+#include <linux/libata.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/ktime.h>
+
+#include <mach/dma.h>
+#include <mach/platform.h>
+
+#define DRV_NAME "ep93xx-ide"
+#define DRV_VERSION "1.0"
+
+enum {
+ /* IDE Control Register */
+ IDECTRL = 0x00,
+ IDECTRL_CS0N = (1 << 0),
+ IDECTRL_CS1N = (1 << 1),
+ IDECTRL_DIORN = (1 << 5),
+ IDECTRL_DIOWN = (1 << 6),
+ IDECTRL_INTRQ = (1 << 9),
+ IDECTRL_IORDY = (1 << 10),
+ /*
+ * the device IDE register to be accessed is selected through
+ * IDECTRL register's specific bitfields 'DA', 'CS1N' and 'CS0N':
+ * b4 b3 b2 b1 b0
+ * A2 A1 A0 CS1N CS0N
+ * the values filled in this structure allows the value to be directly
+ * ORed to the IDECTRL register, hence giving directly the A[2:0] and
+ * CS1N/CS0N values for each IDE register.
+ * The values correspond to the transformation:
+ * ((real IDE address) << 2) | CS1N value << 1 | CS0N value
+ */
+ IDECTRL_ADDR_CMD = 0 + 2, /* CS1 */
+ IDECTRL_ADDR_DATA = (ATA_REG_DATA << 2) + 2,
+ IDECTRL_ADDR_ERROR = (ATA_REG_ERR << 2) + 2,
+ IDECTRL_ADDR_FEATURE = (ATA_REG_FEATURE << 2) + 2,
+ IDECTRL_ADDR_NSECT = (ATA_REG_NSECT << 2) + 2,
+ IDECTRL_ADDR_LBAL = (ATA_REG_LBAL << 2) + 2,
+ IDECTRL_ADDR_LBAM = (ATA_REG_LBAM << 2) + 2,
+ IDECTRL_ADDR_LBAH = (ATA_REG_LBAH << 2) + 2,
+ IDECTRL_ADDR_DEVICE = (ATA_REG_DEVICE << 2) + 2,
+ IDECTRL_ADDR_STATUS = (ATA_REG_STATUS << 2) + 2,
+ IDECTRL_ADDR_COMMAND = (ATA_REG_CMD << 2) + 2,
+ IDECTRL_ADDR_ALTSTATUS = (0x06 << 2) + 1, /* CS0 */
+ IDECTRL_ADDR_CTL = (0x06 << 2) + 1, /* CS0 */
+
+ /* IDE Configuration Register */
+ IDECFG = 0x04,
+ IDECFG_IDEEN = (1 << 0),
+ IDECFG_PIO = (1 << 1),
+ IDECFG_MDMA = (1 << 2),
+ IDECFG_UDMA = (1 << 3),
+ IDECFG_MODE_SHIFT = 4,
+ IDECFG_MODE_MASK = (0xf << 4),
+ IDECFG_WST_SHIFT = 8,
+ IDECFG_WST_MASK = (0x3 << 8),
+
+ /* MDMA Operation Register */
+ IDEMDMAOP = 0x08,
+
+ /* UDMA Operation Register */
+ IDEUDMAOP = 0x0c,
+ IDEUDMAOP_UEN = (1 << 0),
+ IDEUDMAOP_RWOP = (1 << 1),
+
+ /* PIO/MDMA/UDMA Data Registers */
+ IDEDATAOUT = 0x10,
+ IDEDATAIN = 0x14,
+ IDEMDMADATAOUT = 0x18,
+ IDEMDMADATAIN = 0x1c,
+ IDEUDMADATAOUT = 0x20,
+ IDEUDMADATAIN = 0x24,
+
+ /* UDMA Status Register */
+ IDEUDMASTS = 0x28,
+ IDEUDMASTS_DMAIDE = (1 << 16),
+ IDEUDMASTS_INTIDE = (1 << 17),
+ IDEUDMASTS_SBUSY = (1 << 18),
+ IDEUDMASTS_NDO = (1 << 24),
+ IDEUDMASTS_NDI = (1 << 25),
+ IDEUDMASTS_N4X = (1 << 26),
+
+ /* UDMA Debug Status Register */
+ IDEUDMADEBUG = 0x2c,
+};
+
+struct ep93xx_pata_data {
+ const struct platform_device *pdev;
+ void __iomem *ide_base;
+ struct ata_timing t;
+ bool iordy;
+
+ unsigned long udma_in_phys;
+ unsigned long udma_out_phys;
+
+ struct dma_chan *dma_rx_channel;
+ struct ep93xx_dma_data dma_rx_data;
+ struct dma_chan *dma_tx_channel;
+ struct ep93xx_dma_data dma_tx_data;
+};
+
+static void ep93xx_pata_clear_regs(void __iomem *base)
+{
+ writel(IDECTRL_CS0N | IDECTRL_CS1N | IDECTRL_DIORN |
+ IDECTRL_DIOWN, base + IDECTRL);
+
+ writel(0, base + IDECFG);
+ writel(0, base + IDEMDMAOP);
+ writel(0, base + IDEUDMAOP);
+ writel(0, base + IDEDATAOUT);
+ writel(0, base + IDEDATAIN);
+ writel(0, base + IDEMDMADATAOUT);
+ writel(0, base + IDEMDMADATAIN);
+ writel(0, base + IDEUDMADATAOUT);
+ writel(0, base + IDEUDMADATAIN);
+ writel(0, base + IDEUDMADEBUG);
+}
+
+static bool ep93xx_pata_check_iordy(void __iomem *base)
+{
+ return !!(readl(base + IDECTRL) & IDECTRL_IORDY);
+}
+
+/*
+ * According to EP93xx User's Guide, WST field of IDECFG specifies number
+ * of HCLK cycles to hold the data bus after a PIO write operation.
+ * It should be programmed to guarantee following delays:
+ *
+ * PIO Mode [ns]
+ * 0 30
+ * 1 20
+ * 2 15
+ * 3 10
+ * 4 5
+ *
+ * Maximum possible value for HCLK is 100MHz.
+ */
+static int ep93xx_pata_get_wst(int pio_mode)
+{
+ int val;
+
+ if (pio_mode == 0)
+ val = 3;
+ else if (pio_mode < 3)
+ val = 2;
+ else
+ val = 1;
+
+ return val << IDECFG_WST_SHIFT;
+}
+
+static void ep93xx_pata_enable_pio(void __iomem *base, int pio_mode)
+{
+ writel(IDECFG_IDEEN | IDECFG_PIO |
+ ep93xx_pata_get_wst(pio_mode) |
+ (pio_mode << IDECFG_MODE_SHIFT), base + IDECFG);
+}
+
+/*
+ * Based on delay loop found in mach-pxa/mp900.c.
+ *
+ * Single iteration should take 5 cpu cycles. This is 25ns assuming the
+ * fastest ep93xx cpu speed (200MHz) and is better optimized for PIO4 timings
+ * than eg. 20ns.
+ */
+static void ep93xx_pata_delay(unsigned long count)
+{
+ __asm__ volatile (
+ "0:\n"
+ "mov r0, r0\n"
+ "subs %0, %1, #1\n"
+ "bge 0b\n"
+ : "=r" (count)
+ : "0" (count)
+ );
+}
+
+static unsigned long ep93xx_pata_wait_for_iordy(void __iomem *base,
+ unsigned long t2)
+{
+ /*
+ * According to ATA specification, IORDY pin can be first sampled
+ * tA = 35ns after activation of DIOR-/DIOW-. Maximum IORDY pulse
+ * width is tB = 1250ns.
+ *
+ * We are already t2 delay loop iterations after activation of
+ * DIOR-/DIOW-, so we set timeout to (1250 + 35) / 25 - t2 additional
+ * delay loop iterations.
+ */
+ unsigned long start = (1250 + 35) / 25 - t2;
+ unsigned long counter = start;
+
+ while (!ep93xx_pata_check_iordy(base) && counter--)
+ ep93xx_pata_delay(1);
+ return start - counter;
+}
+
+/* common part at start of ep93xx_pata_read/write() */
+static void ep93xx_pata_rw_begin(void __iomem *base, unsigned long addr,
+ unsigned long t1)
+{
+ writel(IDECTRL_DIOWN | IDECTRL_DIORN | addr, base + IDECTRL);
+ ep93xx_pata_delay(t1);
+}
+
+/* common part at end of ep93xx_pata_read/write() */
+static void ep93xx_pata_rw_end(void __iomem *base, unsigned long addr,
+ bool iordy, unsigned long t0, unsigned long t2,
+ unsigned long t2i)
+{
+ ep93xx_pata_delay(t2);
+ /* lengthen t2 if needed */
+ if (iordy)
+ t2 += ep93xx_pata_wait_for_iordy(base, t2);
+ writel(IDECTRL_DIOWN | IDECTRL_DIORN | addr, base + IDECTRL);
+ if (t0 > t2 && t0 - t2 > t2i)
+ ep93xx_pata_delay(t0 - t2);
+ else
+ ep93xx_pata_delay(t2i);
+}
+
+static u16 ep93xx_pata_read(struct ep93xx_pata_data *drv_data,
+ unsigned long addr,
+ bool reg)
+{
+ void __iomem *base = drv_data->ide_base;
+ const struct ata_timing *t = &drv_data->t;
+ unsigned long t0 = reg ? t->cyc8b : t->cycle;
+ unsigned long t2 = reg ? t->act8b : t->active;
+ unsigned long t2i = reg ? t->rec8b : t->recover;
+
+ ep93xx_pata_rw_begin(base, addr, t->setup);
+ writel(IDECTRL_DIOWN | addr, base + IDECTRL);
+ /*
+ * The IDEDATAIN register is loaded from the DD pins at the positive
+ * edge of the DIORN signal. (EP93xx UG p27-14)
+ */
+ ep93xx_pata_rw_end(base, addr, drv_data->iordy, t0, t2, t2i);
+ return readl(base + IDEDATAIN);
+}
+
+/* IDE register read */
+static u16 ep93xx_pata_read_reg(struct ep93xx_pata_data *drv_data,
+ unsigned long addr)
+{
+ return ep93xx_pata_read(drv_data, addr, true);
+}
+
+/* PIO data read */
+static u16 ep93xx_pata_read_data(struct ep93xx_pata_data *drv_data,
+ unsigned long addr)
+{
+ return ep93xx_pata_read(drv_data, addr, false);
+}
+
+static void ep93xx_pata_write(struct ep93xx_pata_data *drv_data,
+ u16 value, unsigned long addr,
+ bool reg)
+{
+ void __iomem *base = drv_data->ide_base;
+ const struct ata_timing *t = &drv_data->t;
+ unsigned long t0 = reg ? t->cyc8b : t->cycle;
+ unsigned long t2 = reg ? t->act8b : t->active;
+ unsigned long t2i = reg ? t->rec8b : t->recover;
+
+ ep93xx_pata_rw_begin(base, addr, t->setup);
+ /*
+ * Value from IDEDATAOUT register is driven onto the DD pins when
+ * DIOWN is low. (EP93xx UG p27-13)
+ */
+ writel(value, base + IDEDATAOUT);
+ writel(IDECTRL_DIORN | addr, base + IDECTRL);
+ ep93xx_pata_rw_end(base, addr, drv_data->iordy, t0, t2, t2i);
+}
+
+/* IDE register write */
+static void ep93xx_pata_write_reg(struct ep93xx_pata_data *drv_data,
+ u16 value, unsigned long addr)
+{
+ ep93xx_pata_write(drv_data, value, addr, true);
+}
+
+/* PIO data write */
+static void ep93xx_pata_write_data(struct ep93xx_pata_data *drv_data,
+ u16 value, unsigned long addr)
+{
+ ep93xx_pata_write(drv_data, value, addr, false);
+}
+
+static void ep93xx_pata_set_piomode(struct ata_port *ap,
+ struct ata_device *adev)
+{
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+ struct ata_device *pair = ata_dev_pair(adev);
+ /*
+ * Calculate timings for the delay loop, assuming ep93xx cpu speed
+ * is 200MHz (maximum possible for ep93xx). If actual cpu speed is
+ * slower, we will wait a bit longer in each delay.
+ * Additional division of cpu speed by 5, because single iteration
+ * of our delay loop takes 5 cpu cycles (25ns).
+ */
+ unsigned long T = 1000000 / (200 / 5);
+
+ ata_timing_compute(adev, adev->pio_mode, &drv_data->t, T, 0);
+ if (pair && pair->pio_mode) {
+ struct ata_timing t;
+ ata_timing_compute(pair, pair->pio_mode, &t, T, 0);
+ ata_timing_merge(&t, &drv_data->t, &drv_data->t,
+ ATA_TIMING_SETUP | ATA_TIMING_8BIT);
+ }
+ drv_data->iordy = ata_pio_need_iordy(adev);
+
+ ep93xx_pata_enable_pio(drv_data->ide_base,
+ adev->pio_mode - XFER_PIO_0);
+}
+
+/* Note: original code is ata_sff_check_status */
+static u8 ep93xx_pata_check_status(struct ata_port *ap)
+{
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+
+ return ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_STATUS);
+}
+
+static u8 ep93xx_pata_check_altstatus(struct ata_port *ap)
+{
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+
+ return ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_ALTSTATUS);
+}
+
+/* Note: original code is ata_sff_tf_load */
+static void ep93xx_pata_tf_load(struct ata_port *ap,
+ const struct ata_taskfile *tf)
+{
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+ unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+ if (tf->ctl != ap->last_ctl) {
+ ep93xx_pata_write_reg(drv_data, tf->ctl, IDECTRL_ADDR_CTL);
+ ap->last_ctl = tf->ctl;
+ ata_wait_idle(ap);
+ }
+
+ if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+ ep93xx_pata_write_reg(drv_data, tf->hob_feature,
+ IDECTRL_ADDR_FEATURE);
+ ep93xx_pata_write_reg(drv_data, tf->hob_nsect,
+ IDECTRL_ADDR_NSECT);
+ ep93xx_pata_write_reg(drv_data, tf->hob_lbal,
+ IDECTRL_ADDR_LBAL);
+ ep93xx_pata_write_reg(drv_data, tf->hob_lbam,
+ IDECTRL_ADDR_LBAM);
+ ep93xx_pata_write_reg(drv_data, tf->hob_lbah,
+ IDECTRL_ADDR_LBAH);
+ }
+
+ if (is_addr) {
+ ep93xx_pata_write_reg(drv_data, tf->feature,
+ IDECTRL_ADDR_FEATURE);
+ ep93xx_pata_write_reg(drv_data, tf->nsect, IDECTRL_ADDR_NSECT);
+ ep93xx_pata_write_reg(drv_data, tf->lbal, IDECTRL_ADDR_LBAL);
+ ep93xx_pata_write_reg(drv_data, tf->lbam, IDECTRL_ADDR_LBAM);
+ ep93xx_pata_write_reg(drv_data, tf->lbah, IDECTRL_ADDR_LBAH);
+ }
+
+ if (tf->flags & ATA_TFLAG_DEVICE)
+ ep93xx_pata_write_reg(drv_data, tf->device,
+ IDECTRL_ADDR_DEVICE);
+
+ ata_wait_idle(ap);
+}
+
+/* Note: original code is ata_sff_tf_read */
+static void ep93xx_pata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+
+ tf->command = ep93xx_pata_check_status(ap);
+ tf->feature = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_FEATURE);
+ tf->nsect = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_NSECT);
+ tf->lbal = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_LBAL);
+ tf->lbam = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_LBAM);
+ tf->lbah = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_LBAH);
+ tf->device = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_DEVICE);
+
+ if (tf->flags & ATA_TFLAG_LBA48) {
+ ep93xx_pata_write_reg(drv_data, tf->ctl | ATA_HOB,
+ IDECTRL_ADDR_CTL);
+ tf->hob_feature = ep93xx_pata_read_reg(drv_data,
+ IDECTRL_ADDR_FEATURE);
+ tf->hob_nsect = ep93xx_pata_read_reg(drv_data,
+ IDECTRL_ADDR_NSECT);
+ tf->hob_lbal = ep93xx_pata_read_reg(drv_data,
+ IDECTRL_ADDR_LBAL);
+ tf->hob_lbam = ep93xx_pata_read_reg(drv_data,
+ IDECTRL_ADDR_LBAM);
+ tf->hob_lbah = ep93xx_pata_read_reg(drv_data,
+ IDECTRL_ADDR_LBAH);
+ ep93xx_pata_write_reg(drv_data, tf->ctl, IDECTRL_ADDR_CTL);
+ ap->last_ctl = tf->ctl;
+ }
+}
+
+/* Note: original code is ata_sff_exec_command */
+static void ep93xx_pata_exec_command(struct ata_port *ap,
+ const struct ata_taskfile *tf)
+{
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+
+ ep93xx_pata_write_reg(drv_data, tf->command,
+ IDECTRL_ADDR_COMMAND);
+ ata_sff_pause(ap);
+}
+
+/* Note: original code is ata_sff_dev_select */
+static void ep93xx_pata_dev_select(struct ata_port *ap, unsigned int device)
+{
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+ u8 tmp = ATA_DEVICE_OBS;
+
+ if (device != 0)
+ tmp |= ATA_DEV1;
+
+ ep93xx_pata_write_reg(drv_data, tmp, IDECTRL_ADDR_DEVICE);
+ ata_sff_pause(ap); /* needed; also flushes, for mmio */
+}
+
+/* Note: original code is ata_sff_set_devctl */
+static void ep93xx_pata_set_devctl(struct ata_port *ap, u8 ctl)
+{
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+
+ ep93xx_pata_write_reg(drv_data, ctl, IDECTRL_ADDR_CTL);
+}
+
+/* Note: original code is ata_sff_data_xfer */
+static unsigned int ep93xx_pata_data_xfer(struct ata_device *adev,
+ unsigned char *buf,
+ unsigned int buflen, int rw)
+{
+ struct ata_port *ap = adev->link->ap;
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+ u16 *data = (u16 *)buf;
+ unsigned int words = buflen >> 1;
+
+ /* Transfer multiple of 2 bytes */
+ while (words--)
+ if (rw == READ)
+ *data++ = cpu_to_le16(
+ ep93xx_pata_read_data(
+ drv_data, IDECTRL_ADDR_DATA));
+ else
+ ep93xx_pata_write_data(drv_data, le16_to_cpu(*data++),
+ IDECTRL_ADDR_DATA);
+
+ /* Transfer trailing 1 byte, if any. */
+ if (unlikely(buflen & 0x01)) {
+ unsigned char pad[2] = { };
+
+ buf += buflen - 1;
+
+ if (rw == READ) {
+ *pad = cpu_to_le16(
+ ep93xx_pata_read_data(
+ drv_data, IDECTRL_ADDR_DATA));
+ *buf = pad[0];
+ } else {
+ pad[0] = *buf;
+ ep93xx_pata_write_data(drv_data, le16_to_cpu(*pad),
+ IDECTRL_ADDR_DATA);
+ }
+ words++;
+ }
+
+ return words << 1;
+}
+
+/* Note: original code is ata_devchk */
+static bool ep93xx_pata_device_is_present(struct ata_port *ap,
+ unsigned int device)
+{
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+ u8 nsect, lbal;
+
+ ap->ops->sff_dev_select(ap, device);
+
+ ep93xx_pata_write_reg(drv_data, 0x55, IDECTRL_ADDR_NSECT);
+ ep93xx_pata_write_reg(drv_data, 0xaa, IDECTRL_ADDR_LBAL);
+
+ ep93xx_pata_write_reg(drv_data, 0xaa, IDECTRL_ADDR_NSECT);
+ ep93xx_pata_write_reg(drv_data, 0x55, IDECTRL_ADDR_LBAL);
+
+ ep93xx_pata_write_reg(drv_data, 0x55, IDECTRL_ADDR_NSECT);
+ ep93xx_pata_write_reg(drv_data, 0xaa, IDECTRL_ADDR_LBAL);
+
+ nsect = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_NSECT);
+ lbal = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_LBAL);
+
+ if ((nsect == 0x55) && (lbal == 0xaa))
+ return true;
+
+ return false;
+}
+
+/* Note: original code is ata_sff_wait_after_reset */
+static int ep93xx_pata_wait_after_reset(struct ata_link *link,
+ unsigned int devmask,
+ unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+ unsigned int dev0 = devmask & (1 << 0);
+ unsigned int dev1 = devmask & (1 << 1);
+ int rc, ret = 0;
+
+ ata_msleep(ap, ATA_WAIT_AFTER_RESET);
+
+ /* always check readiness of the master device */
+ rc = ata_sff_wait_ready(link, deadline);
+ /*
+ * -ENODEV means the odd clown forgot the D7 pulldown resistor
+ * and TF status is 0xff, bail out on it too.
+ */
+ if (rc)
+ return rc;
+
+ /*
+ * if device 1 was found in ata_devchk, wait for register
+ * access briefly, then wait for BSY to clear.
+ */
+ if (dev1) {
+ int i;
+
+ ap->ops->sff_dev_select(ap, 1);
+
+ /*
+ * Wait for register access. Some ATAPI devices fail
+ * to set nsect/lbal after reset, so don't waste too
+ * much time on it. We're gonna wait for !BSY anyway.
+ */
+ for (i = 0; i < 2; i++) {
+ u8 nsect, lbal;
+
+ nsect = ep93xx_pata_read_reg(drv_data,
+ IDECTRL_ADDR_NSECT);
+ lbal = ep93xx_pata_read_reg(drv_data,
+ IDECTRL_ADDR_LBAL);
+ if (nsect == 1 && lbal == 1)
+ break;
+ msleep(50); /* give drive a breather */
+ }
+
+ rc = ata_sff_wait_ready(link, deadline);
+ if (rc) {
+ if (rc != -ENODEV)
+ return rc;
+ ret = rc;
+ }
+ }
+ /* is all this really necessary? */
+ ap->ops->sff_dev_select(ap, 0);
+ if (dev1)
+ ap->ops->sff_dev_select(ap, 1);
+ if (dev0)
+ ap->ops->sff_dev_select(ap, 0);
+
+ return ret;
+}
+
+/* Note: original code is ata_bus_softreset */
+static int ep93xx_pata_bus_softreset(struct ata_port *ap, unsigned int devmask,
+ unsigned long deadline)
+{
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+
+ ep93xx_pata_write_reg(drv_data, ap->ctl, IDECTRL_ADDR_CTL);
+ udelay(20); /* FIXME: flush */
+ ep93xx_pata_write_reg(drv_data, ap->ctl | ATA_SRST, IDECTRL_ADDR_CTL);
+ udelay(20); /* FIXME: flush */
+ ep93xx_pata_write_reg(drv_data, ap->ctl, IDECTRL_ADDR_CTL);
+ ap->last_ctl = ap->ctl;
+
+ return ep93xx_pata_wait_after_reset(&ap->link, devmask, deadline);
+}
+
+static void ep93xx_pata_release_dma(struct ep93xx_pata_data *drv_data)
+{
+ if (drv_data->dma_rx_channel) {
+ dma_release_channel(drv_data->dma_rx_channel);
+ drv_data->dma_rx_channel = NULL;
+ }
+ if (drv_data->dma_tx_channel) {
+ dma_release_channel(drv_data->dma_tx_channel);
+ drv_data->dma_tx_channel = NULL;
+ }
+}
+
+static bool ep93xx_pata_dma_filter(struct dma_chan *chan, void *filter_param)
+{
+ if (ep93xx_dma_chan_is_m2p(chan))
+ return false;
+
+ chan->private = filter_param;
+ return true;
+}
+
+static void ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
+{
+ const struct platform_device *pdev = drv_data->pdev;
+ dma_cap_mask_t mask;
+ struct dma_slave_config conf;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ /*
+ * Request two channels for IDE. Another possibility would be
+ * to request only one channel, and reprogram it's direction at
+ * start of new transfer.
+ */
+ drv_data->dma_rx_data.port = EP93XX_DMA_IDE;
+ drv_data->dma_rx_data.direction = DMA_FROM_DEVICE;
+ drv_data->dma_rx_data.name = "ep93xx-pata-rx";
+ drv_data->dma_rx_channel = dma_request_channel(mask,
+ ep93xx_pata_dma_filter, &drv_data->dma_rx_data);
+ if (!drv_data->dma_rx_channel)
+ return;
+
+ drv_data->dma_tx_data.port = EP93XX_DMA_IDE;
+ drv_data->dma_tx_data.direction = DMA_TO_DEVICE;
+ drv_data->dma_tx_data.name = "ep93xx-pata-tx";
+ drv_data->dma_tx_channel = dma_request_channel(mask,
+ ep93xx_pata_dma_filter, &drv_data->dma_tx_data);
+ if (!drv_data->dma_tx_channel) {
+ dma_release_channel(drv_data->dma_rx_channel);
+ return;
+ }
+
+ /* Configure receive channel direction and source address */
+ memset(&conf, 0, sizeof(conf));
+ conf.direction = DMA_FROM_DEVICE;
+ conf.src_addr = drv_data->udma_in_phys;
+ conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ if (dmaengine_slave_config(drv_data->dma_rx_channel, &conf)) {
+ dev_err(&pdev->dev, "failed to configure rx dma channel\n");
+ ep93xx_pata_release_dma(drv_data);
+ return;
+ }
+
+ /* Configure transmit channel direction and destination address */
+ memset(&conf, 0, sizeof(conf));
+ conf.direction = DMA_TO_DEVICE;
+ conf.dst_addr = drv_data->udma_out_phys;
+ conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ if (dmaengine_slave_config(drv_data->dma_tx_channel, &conf)) {
+ dev_err(&pdev->dev, "failed to configure tx dma channel\n");
+ ep93xx_pata_release_dma(drv_data);
+ }
+}
+
+static void ep93xx_pata_dma_start(struct ata_queued_cmd *qc)
+{
+ struct dma_async_tx_descriptor *txd;
+ struct ep93xx_pata_data *drv_data = qc->ap->host->private_data;
+ void __iomem *base = drv_data->ide_base;
+ struct ata_device *adev = qc->dev;
+ u32 v = qc->dma_dir == DMA_TO_DEVICE ? IDEUDMAOP_RWOP : 0;
+ struct dma_chan *channel = qc->dma_dir == DMA_TO_DEVICE
+ ? drv_data->dma_tx_channel : drv_data->dma_rx_channel;
+
+ txd = channel->device->device_prep_slave_sg(channel, qc->sg,
+ qc->n_elem, qc->dma_dir, DMA_CTRL_ACK, NULL);
+ if (!txd) {
+ dev_err(qc->ap->dev, "failed to prepare slave for sg dma\n");
+ return;
+ }
+ txd->callback = NULL;
+ txd->callback_param = NULL;
+
+ if (dmaengine_submit(txd) < 0) {
+ dev_err(qc->ap->dev, "failed to submit dma transfer\n");
+ return;
+ }
+ dma_async_issue_pending(channel);
+
+ /*
+ * When enabling UDMA operation, IDEUDMAOP register needs to be
+ * programmed in three step sequence:
+ * 1) set or clear the RWOP bit,
+ * 2) perform dummy read of the register,
+ * 3) set the UEN bit.
+ */
+ writel(v, base + IDEUDMAOP);
+ readl(base + IDEUDMAOP);
+ writel(v | IDEUDMAOP_UEN, base + IDEUDMAOP);
+
+ writel(IDECFG_IDEEN | IDECFG_UDMA |
+ ((adev->xfer_mode - XFER_UDMA_0) << IDECFG_MODE_SHIFT),
+ base + IDECFG);
+}
+
+static void ep93xx_pata_dma_stop(struct ata_queued_cmd *qc)
+{
+ struct ep93xx_pata_data *drv_data = qc->ap->host->private_data;
+ void __iomem *base = drv_data->ide_base;
+
+ /* terminate all dma transfers, if not yet finished */
+ dmaengine_terminate_all(drv_data->dma_rx_channel);
+ dmaengine_terminate_all(drv_data->dma_tx_channel);
+
+ /*
+ * To properly stop IDE-DMA, IDEUDMAOP register must to be cleared
+ * and IDECTRL register must be set to default value.
+ */
+ writel(0, base + IDEUDMAOP);
+ writel(readl(base + IDECTRL) | IDECTRL_DIOWN | IDECTRL_DIORN |
+ IDECTRL_CS0N | IDECTRL_CS1N, base + IDECTRL);
+
+ ep93xx_pata_enable_pio(drv_data->ide_base,
+ qc->dev->pio_mode - XFER_PIO_0);
+
+ ata_sff_dma_pause(qc->ap);
+}
+
+static void ep93xx_pata_dma_setup(struct ata_queued_cmd *qc)
+{
+ qc->ap->ops->sff_exec_command(qc->ap, &qc->tf);
+}
+
+static u8 ep93xx_pata_dma_status(struct ata_port *ap)
+{
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+ u32 val = readl(drv_data->ide_base + IDEUDMASTS);
+
+ /*
+ * UDMA Status Register bits:
+ *
+ * DMAIDE - DMA request signal from UDMA state machine,
+ * INTIDE - INT line generated by UDMA because of errors in the
+ * state machine,
+ * SBUSY - UDMA state machine busy, not in idle state,
+ * NDO - error for data-out not completed,
+ * NDI - error for data-in not completed,
+ * N4X - error for data transferred not multiplies of four
+ * 32-bit words.
+ * (EP93xx UG p27-17)
+ */
+ if (val & IDEUDMASTS_NDO || val & IDEUDMASTS_NDI ||
+ val & IDEUDMASTS_N4X || val & IDEUDMASTS_INTIDE)
+ return ATA_DMA_ERR;
+
+ /* read INTRQ (INT[3]) pin input state */
+ if (readl(drv_data->ide_base + IDECTRL) & IDECTRL_INTRQ)
+ return ATA_DMA_INTR;
+
+ if (val & IDEUDMASTS_SBUSY || val & IDEUDMASTS_DMAIDE)
+ return ATA_DMA_ACTIVE;
+
+ return 0;
+}
+
+/* Note: original code is ata_sff_softreset */
+static int ep93xx_pata_softreset(struct ata_link *al, unsigned int *classes,
+ unsigned long deadline)
+{
+ struct ata_port *ap = al->ap;
+ unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+ unsigned int devmask = 0;
+ int rc;
+ u8 err;
+
+ /* determine if device 0/1 are present */
+ if (ep93xx_pata_device_is_present(ap, 0))
+ devmask |= (1 << 0);
+ if (slave_possible && ep93xx_pata_device_is_present(ap, 1))
+ devmask |= (1 << 1);
+
+ /* select device 0 again */
+ ap->ops->sff_dev_select(al->ap, 0);
+
+ /* issue bus reset */
+ rc = ep93xx_pata_bus_softreset(ap, devmask, deadline);
+ /* if link is ocuppied, -ENODEV too is an error */
+ if (rc && (rc != -ENODEV || sata_scr_valid(al))) {
+ ata_link_printk(al, KERN_ERR, "SRST failed (errno=%d)\n",
+ rc);
+ return rc;
+ }
+
+ /* determine by signature whether we have ATA or ATAPI devices */
+ classes[0] = ata_sff_dev_classify(&al->device[0], devmask & (1 << 0),
+ &err);
+ if (slave_possible && err != 0x81)
+ classes[1] = ata_sff_dev_classify(&al->device[1],
+ devmask & (1 << 1), &err);
+
+ return 0;
+}
+
+/* Note: original code is ata_sff_drain_fifo */
+static void ep93xx_pata_drain_fifo(struct ata_queued_cmd *qc)
+{
+ int count;
+ struct ata_port *ap;
+ struct ep93xx_pata_data *drv_data;
+
+ /* We only need to flush incoming data when a command was running */
+ if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE)
+ return;
+
+ ap = qc->ap;
+ drv_data = ap->host->private_data;
+ /* Drain up to 64K of data before we give up this recovery method */
+ for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ)
+ && count < 65536; count += 2)
+ ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_DATA);
+
+ /* Can become DEBUG later */
+ if (count)
+ ata_port_printk(ap, KERN_DEBUG,
+ "drained %d bytes to clear DRQ.\n", count);
+
+}
+
+static int ep93xx_pata_port_start(struct ata_port *ap)
+{
+ struct ep93xx_pata_data *drv_data = ap->host->private_data;
+
+ /*
+ * Set timings to safe values at startup (= number of ns from ATA
+ * specification), we'll switch to properly calculated values later.
+ */
+ drv_data->t = *ata_timing_find_mode(XFER_PIO_0);
+ return 0;
+}
+
+static struct scsi_host_template ep93xx_pata_sht = {
+ ATA_BASE_SHT(DRV_NAME),
+ /* ep93xx dma implementation limit */
+ .sg_tablesize = 32,
+ /* ep93xx dma can't transfer 65536 bytes at once */
+ .dma_boundary = 0x7fff,
+};
+
+static struct ata_port_operations ep93xx_pata_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .qc_prep = ata_noop_qc_prep,
+
+ .softreset = ep93xx_pata_softreset,
+ .hardreset = ATA_OP_NULL,
+
+ .sff_dev_select = ep93xx_pata_dev_select,
+ .sff_set_devctl = ep93xx_pata_set_devctl,
+ .sff_check_status = ep93xx_pata_check_status,
+ .sff_check_altstatus = ep93xx_pata_check_altstatus,
+ .sff_tf_load = ep93xx_pata_tf_load,
+ .sff_tf_read = ep93xx_pata_tf_read,
+ .sff_exec_command = ep93xx_pata_exec_command,
+ .sff_data_xfer = ep93xx_pata_data_xfer,
+ .sff_drain_fifo = ep93xx_pata_drain_fifo,
+ .sff_irq_clear = ATA_OP_NULL,
+
+ .set_piomode = ep93xx_pata_set_piomode,
+
+ .bmdma_setup = ep93xx_pata_dma_setup,
+ .bmdma_start = ep93xx_pata_dma_start,
+ .bmdma_stop = ep93xx_pata_dma_stop,
+ .bmdma_status = ep93xx_pata_dma_status,
+
+ .cable_detect = ata_cable_unknown,
+ .port_start = ep93xx_pata_port_start,
+};
+
+static int __devinit ep93xx_pata_probe(struct platform_device *pdev)
+{
+ struct ep93xx_pata_data *drv_data;
+ struct ata_host *host;
+ struct ata_port *ap;
+ unsigned int irq;
+ struct resource *mem_res;
+ void __iomem *ide_base;
+ int err;
+
+ err = ep93xx_ide_acquire_gpio(pdev);
+ if (err)
+ return err;
+
+ /* INT[3] (IRQ_EP93XX_EXT3) line connected as pull down */
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ err = -ENXIO;
+ goto err_rel_gpio;
+ }
+
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem_res) {
+ err = -ENXIO;
+ goto err_rel_gpio;
+ }
+
+ ide_base = devm_request_and_ioremap(&pdev->dev, mem_res);
+ if (!ide_base) {
+ err = -ENXIO;
+ goto err_rel_gpio;
+ }
+
+ drv_data = devm_kzalloc(&pdev->dev, sizeof(*drv_data), GFP_KERNEL);
+ if (!drv_data) {
+ err = -ENXIO;
+ goto err_rel_gpio;
+ }
+
+ platform_set_drvdata(pdev, drv_data);
+ drv_data->pdev = pdev;
+ drv_data->ide_base = ide_base;
+ drv_data->udma_in_phys = mem_res->start + IDEUDMADATAIN;
+ drv_data->udma_out_phys = mem_res->start + IDEUDMADATAOUT;
+ ep93xx_pata_dma_init(drv_data);
+
+ /* allocate host */
+ host = ata_host_alloc(&pdev->dev, 1);
+ if (!host) {
+ err = -ENXIO;
+ goto err_rel_dma;
+ }
+
+ ep93xx_pata_clear_regs(ide_base);
+
+ host->private_data = drv_data;
+
+ ap = host->ports[0];
+ ap->dev = &pdev->dev;
+ ap->ops = &ep93xx_pata_port_ops;
+ ap->flags |= ATA_FLAG_SLAVE_POSS;
+ ap->pio_mask = ATA_PIO4;
+
+ /*
+ * Maximum UDMA modes:
+ * EP931x rev.E0 - UDMA2
+ * EP931x rev.E1 - UDMA3
+ * EP931x rev.E2 - UDMA4
+ *
+ * MWDMA support was removed from EP931x rev.E2,
+ * so this driver supports only UDMA modes.
+ */
+ if (drv_data->dma_rx_channel && drv_data->dma_tx_channel) {
+ int chip_rev = ep93xx_chip_revision();
+
+ if (chip_rev == EP93XX_CHIP_REV_E1)
+ ap->udma_mask = ATA_UDMA3;
+ else if (chip_rev == EP93XX_CHIP_REV_E2)
+ ap->udma_mask = ATA_UDMA4;
+ else
+ ap->udma_mask = ATA_UDMA2;
+ }
+
+ /* defaults, pio 0 */
+ ep93xx_pata_enable_pio(ide_base, 0);
+
+ dev_info(&pdev->dev, "version " DRV_VERSION "\n");
+
+ /* activate host */
+ err = ata_host_activate(host, irq, ata_bmdma_interrupt, 0,
+ &ep93xx_pata_sht);
+ if (err == 0)
+ return 0;
+
+err_rel_dma:
+ ep93xx_pata_release_dma(drv_data);
+err_rel_gpio:
+ ep93xx_ide_release_gpio(pdev);
+ return err;
+}
+
+static int __devexit ep93xx_pata_remove(struct platform_device *pdev)
+{
+ struct ata_host *host = platform_get_drvdata(pdev);
+ struct ep93xx_pata_data *drv_data = host->private_data;
+
+ ata_host_detach(host);
+ ep93xx_pata_release_dma(drv_data);
+ ep93xx_pata_clear_regs(drv_data->ide_base);
+ ep93xx_ide_release_gpio(pdev);
+ return 0;
+}
+
+static struct platform_driver ep93xx_pata_platform_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = ep93xx_pata_probe,
+ .remove = __devexit_p(ep93xx_pata_remove),
+};
+
+module_platform_driver(ep93xx_pata_platform_driver);
+
+MODULE_AUTHOR("Alessandro Zummo, Lennert Buytenhek, Joao Ramos, "
+ "Bartlomiej Zolnierkiewicz, Rafal Prylowski");
+MODULE_DESCRIPTION("low-level driver for cirrus ep93xx IDE controller");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("platform:pata_ep93xx");
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 26a06b801b5b..2bcef657a60c 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -21,8 +21,7 @@
#include "power/power.h"
/* /sys/devices/system */
-/* FIXME: make static after drivers/base/sys.c is deleted */
-struct kset *system_kset;
+static struct kset *system_kset;
#define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index e28ce9898af4..346be8b78b24 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -25,6 +25,7 @@
#include <linux/mutex.h>
#include <linux/async.h>
#include <linux/pm_runtime.h>
+#include <linux/netdevice.h>
#include "base.h"
#include "power/power.h"
@@ -65,7 +66,7 @@ static inline int device_is_not_partition(struct device *dev)
* @dev: struct device to get the name of
*
* Will return the device's driver's name if it is bound to a device. If
- * the device is not bound to a device, it will return the name of the bus
+ * the device is not bound to a driver, it will return the name of the bus
* it is attached to. If it is not attached to a bus either, an empty
* string will be returned.
*/
@@ -878,8 +879,8 @@ EXPORT_SYMBOL_GPL(dev_set_name);
* to NULL prevents an entry from being created. class->dev_kobj must
* be set (or cleared) before any devices are registered to the class
* otherwise device_create_sys_dev_entry() and
- * device_remove_sys_dev_entry() will disagree about the the presence
- * of the link.
+ * device_remove_sys_dev_entry() will disagree about the presence of
+ * the link.
*/
static struct kobject *device_to_dev_kobj(struct device *dev)
{
@@ -1843,15 +1844,60 @@ void device_shutdown(void)
*/
#ifdef CONFIG_PRINTK
-
int __dev_printk(const char *level, const struct device *dev,
struct va_format *vaf)
{
+ char dict[128];
+ size_t dictlen = 0;
+ const char *subsys;
+
if (!dev)
return printk("%s(NULL device *): %pV", level, vaf);
- return printk("%s%s %s: %pV",
- level, dev_driver_string(dev), dev_name(dev), vaf);
+ if (dev->class)
+ subsys = dev->class->name;
+ else if (dev->bus)
+ subsys = dev->bus->name;
+ else
+ goto skip;
+
+ dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen,
+ "SUBSYSTEM=%s", subsys);
+
+ /*
+ * Add device identifier DEVICE=:
+ * b12:8 block dev_t
+ * c127:3 char dev_t
+ * n8 netdev ifindex
+ * +sound:card0 subsystem:devname
+ */
+ if (MAJOR(dev->devt)) {
+ char c;
+
+ if (strcmp(subsys, "block") == 0)
+ c = 'b';
+ else
+ c = 'c';
+ dictlen++;
+ dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen,
+ "DEVICE=%c%u:%u",
+ c, MAJOR(dev->devt), MINOR(dev->devt));
+ } else if (strcmp(subsys, "net") == 0) {
+ struct net_device *net = to_net_dev(dev);
+
+ dictlen++;
+ dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen,
+ "DEVICE=n%u", net->ifindex);
+ } else {
+ dictlen++;
+ dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen,
+ "DEVICE=+%s:%s", subsys, dev_name(dev));
+ }
+skip:
+ return printk_emit(0, level[1] - '0',
+ dictlen ? dict : NULL, dictlen,
+ "%s %s: %pV",
+ dev_driver_string(dev), dev_name(dev), vaf);
}
EXPORT_SYMBOL(__dev_printk);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index adf937bf4091..63452943abd1 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -330,8 +330,4 @@ void __init cpu_dev_init(void)
panic("Failed to register CPU subsystem");
cpu_dev_register_generic();
-
-#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
- sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root);
-#endif
}
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 524bf96c289f..2360adb7a58f 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -309,6 +309,10 @@ EXPORT_SYMBOL_GPL(devres_remove);
* which @match returns 1. If @match is NULL, it's considered to
* match all. If found, the resource is removed atomically and freed.
*
+ * Note that the release function for the resource will not be called,
+ * only the devres-allocated data will be freed. The caller becomes
+ * responsible for freeing any other data.
+ *
* RETURNS:
* 0 if devres is found and freed, -ENOENT if not found.
*/
@@ -326,6 +330,37 @@ int devres_destroy(struct device *dev, dr_release_t release,
}
EXPORT_SYMBOL_GPL(devres_destroy);
+
+/**
+ * devres_release - Find a device resource and destroy it, calling release
+ * @dev: Device to find resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev associated with @release and for
+ * which @match returns 1. If @match is NULL, it's considered to
+ * match all. If found, the resource is removed atomically, the
+ * release function called and the resource freed.
+ *
+ * RETURNS:
+ * 0 if devres is found and freed, -ENOENT if not found.
+ */
+int devres_release(struct device *dev, dr_release_t release,
+ dr_match_t match, void *match_data)
+{
+ void *res;
+
+ res = devres_remove(dev, release, match, match_data);
+ if (unlikely(!res))
+ return -ENOENT;
+
+ (*release)(dev, res);
+ devres_free(res);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(devres_release);
+
static int remove_nodes(struct device *dev,
struct list_head *first, struct list_head *end,
struct list_head *todo)
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index 8493536ea55b..765c3a28077a 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -7,9 +7,9 @@
* devtmpfs, a tmpfs-based filesystem is created. Every driver-core
* device which requests a device node, will add a node in this
* filesystem.
- * By default, all devices are named after the the name of the
- * device, owned by root and have a default mode of 0600. Subsystems
- * can overwrite the default setting if needed.
+ * By default, all devices are named after the name of the device,
+ * owned by root and have a default mode of 0600. Subsystems can
+ * overwrite the default setting if needed.
*/
#include <linux/kernel.h>
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
index 07cbbc6fddb4..05c64c11bad2 100644
--- a/drivers/base/dma-buf.c
+++ b/drivers/base/dma-buf.c
@@ -293,7 +293,7 @@ EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
* cpu in the kernel context. Calls begin_cpu_access to allow exporter-specific
* preparations. Coherency is only guaranteed in the specified range for the
* specified access direction.
- * @dma_buf: [in] buffer to prepare cpu access for.
+ * @dmabuf: [in] buffer to prepare cpu access for.
* @start: [in] start of range for cpu access.
* @len: [in] length of range for cpu access.
* @direction: [in] length of range for cpu access.
@@ -320,7 +320,7 @@ EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access);
* cpu in the kernel context. Calls end_cpu_access to allow exporter-specific
* actions. Coherency is only guaranteed in the specified range for the
* specified access direction.
- * @dma_buf: [in] buffer to complete cpu access for.
+ * @dmabuf: [in] buffer to complete cpu access for.
* @start: [in] start of range for cpu access.
* @len: [in] length of range for cpu access.
* @direction: [in] length of range for cpu access.
@@ -340,7 +340,7 @@ EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access);
/**
* dma_buf_kmap_atomic - Map a page of the buffer object into kernel address
* space. The same restrictions as for kmap_atomic and friends apply.
- * @dma_buf: [in] buffer to map page from.
+ * @dmabuf: [in] buffer to map page from.
* @page_num: [in] page in PAGE_SIZE units to map.
*
* This call must always succeed, any necessary preparations that might fail
@@ -356,7 +356,7 @@ EXPORT_SYMBOL_GPL(dma_buf_kmap_atomic);
/**
* dma_buf_kunmap_atomic - Unmap a page obtained by dma_buf_kmap_atomic.
- * @dma_buf: [in] buffer to unmap page from.
+ * @dmabuf: [in] buffer to unmap page from.
* @page_num: [in] page in PAGE_SIZE units to unmap.
* @vaddr: [in] kernel space pointer obtained from dma_buf_kmap_atomic.
*
@@ -375,7 +375,7 @@ EXPORT_SYMBOL_GPL(dma_buf_kunmap_atomic);
/**
* dma_buf_kmap - Map a page of the buffer object into kernel address space. The
* same restrictions as for kmap and friends apply.
- * @dma_buf: [in] buffer to map page from.
+ * @dmabuf: [in] buffer to map page from.
* @page_num: [in] page in PAGE_SIZE units to map.
*
* This call must always succeed, any necessary preparations that might fail
@@ -391,7 +391,7 @@ EXPORT_SYMBOL_GPL(dma_buf_kmap);
/**
* dma_buf_kunmap - Unmap a page obtained by dma_buf_kmap.
- * @dma_buf: [in] buffer to unmap page from.
+ * @dmabuf: [in] buffer to unmap page from.
* @page_num: [in] page in PAGE_SIZE units to unmap.
* @vaddr: [in] kernel space pointer obtained from dma_buf_kmap.
*
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 3ec3896c83a6..207c27ddf828 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -80,7 +80,7 @@ struct device *driver_find_device(struct device_driver *drv,
struct klist_iter i;
struct device *dev;
- if (!drv)
+ if (!drv || !drv->p)
return NULL;
klist_iter_init_node(&drv->p->klist_devices, &i,
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 73ce9fbe9839..83aa694a8efe 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -11,6 +11,7 @@
#include <linux/io.h>
#include <linux/pm_runtime.h>
#include <linux/pm_domain.h>
+#include <linux/pm_qos.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/sched.h>
@@ -38,11 +39,13 @@
ktime_t __start = ktime_get(); \
type __retval = GENPD_DEV_CALLBACK(genpd, type, callback, dev); \
s64 __elapsed = ktime_to_ns(ktime_sub(ktime_get(), __start)); \
- struct generic_pm_domain_data *__gpd_data = dev_gpd_data(dev); \
- if (__elapsed > __gpd_data->td.field) { \
- __gpd_data->td.field = __elapsed; \
+ struct gpd_timing_data *__td = &dev_gpd_data(dev)->td; \
+ if (!__retval && __elapsed > __td->field) { \
+ __td->field = __elapsed; \
dev_warn(dev, name " latency exceeded, new value %lld ns\n", \
__elapsed); \
+ genpd->max_off_time_changed = true; \
+ __td->constraint_changed = true; \
} \
__retval; \
})
@@ -211,6 +214,7 @@ int __pm_genpd_poweron(struct generic_pm_domain *genpd)
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
if (elapsed_ns > genpd->power_on_latency_ns) {
genpd->power_on_latency_ns = elapsed_ns;
+ genpd->max_off_time_changed = true;
if (genpd->name)
pr_warning("%s: Power-on latency exceeded, "
"new value %lld ns\n", genpd->name,
@@ -247,6 +251,53 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd)
#ifdef CONFIG_PM_RUNTIME
+static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
+ unsigned long val, void *ptr)
+{
+ struct generic_pm_domain_data *gpd_data;
+ struct device *dev;
+
+ gpd_data = container_of(nb, struct generic_pm_domain_data, nb);
+
+ mutex_lock(&gpd_data->lock);
+ dev = gpd_data->base.dev;
+ if (!dev) {
+ mutex_unlock(&gpd_data->lock);
+ return NOTIFY_DONE;
+ }
+ mutex_unlock(&gpd_data->lock);
+
+ for (;;) {
+ struct generic_pm_domain *genpd;
+ struct pm_domain_data *pdd;
+
+ spin_lock_irq(&dev->power.lock);
+
+ pdd = dev->power.subsys_data ?
+ dev->power.subsys_data->domain_data : NULL;
+ if (pdd) {
+ to_gpd_data(pdd)->td.constraint_changed = true;
+ genpd = dev_to_genpd(dev);
+ } else {
+ genpd = ERR_PTR(-ENODATA);
+ }
+
+ spin_unlock_irq(&dev->power.lock);
+
+ if (!IS_ERR(genpd)) {
+ mutex_lock(&genpd->lock);
+ genpd->max_off_time_changed = true;
+ mutex_unlock(&genpd->lock);
+ }
+
+ dev = dev->parent;
+ if (!dev || dev->power.ignore_children)
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
/**
* __pm_genpd_save_device - Save the pre-suspend state of a device.
* @pdd: Domain data of the device to save the state of.
@@ -435,6 +486,7 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
if (elapsed_ns > genpd->power_off_latency_ns) {
genpd->power_off_latency_ns = elapsed_ns;
+ genpd->max_off_time_changed = true;
if (genpd->name)
pr_warning("%s: Power-off latency exceeded, "
"new value %lld ns\n", genpd->name,
@@ -443,17 +495,6 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
}
genpd->status = GPD_STATE_POWER_OFF;
- genpd->power_off_time = ktime_get();
-
- /* Update PM QoS information for devices in the domain. */
- list_for_each_entry_reverse(pdd, &genpd->dev_list, list_node) {
- struct gpd_timing_data *td = &to_gpd_data(pdd)->td;
-
- pm_runtime_update_max_time_suspended(pdd->dev,
- td->start_latency_ns +
- td->restore_state_latency_ns +
- genpd->power_on_latency_ns);
- }
list_for_each_entry(link, &genpd->slave_links, slave_node) {
genpd_sd_counter_dec(link->master);
@@ -514,9 +555,6 @@ static int pm_genpd_runtime_suspend(struct device *dev)
if (ret)
return ret;
- pm_runtime_update_max_time_suspended(dev,
- dev_gpd_data(dev)->td.start_latency_ns);
-
/*
* If power.irq_safe is set, this routine will be run with interrupts
* off, so it can't use mutexes.
@@ -613,6 +651,12 @@ void pm_genpd_poweroff_unused(void)
#else
+static inline int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
+ unsigned long val, void *ptr)
+{
+ return NOTIFY_DONE;
+}
+
static inline void genpd_power_off_work_fn(struct work_struct *work) {}
#define pm_genpd_runtime_suspend NULL
@@ -1209,12 +1253,15 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
return -EINVAL;
- genpd_acquire_lock(genpd);
+ gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
+ if (!gpd_data)
+ return -ENOMEM;
- if (genpd->status == GPD_STATE_POWER_OFF) {
- ret = -EINVAL;
- goto out;
- }
+ mutex_init(&gpd_data->lock);
+ gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier;
+ dev_pm_qos_add_notifier(dev, &gpd_data->nb);
+
+ genpd_acquire_lock(genpd);
if (genpd->prepared_count > 0) {
ret = -EAGAIN;
@@ -1227,26 +1274,35 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
goto out;
}
- gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
- if (!gpd_data) {
- ret = -ENOMEM;
- goto out;
- }
-
genpd->device_count++;
+ genpd->max_off_time_changed = true;
- dev->pm_domain = &genpd->domain;
dev_pm_get_subsys_data(dev);
+
+ mutex_lock(&gpd_data->lock);
+ spin_lock_irq(&dev->power.lock);
+ dev->pm_domain = &genpd->domain;
dev->power.subsys_data->domain_data = &gpd_data->base;
gpd_data->base.dev = dev;
- gpd_data->need_restore = false;
list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
+ gpd_data->need_restore = genpd->status == GPD_STATE_POWER_OFF;
if (td)
gpd_data->td = *td;
+ gpd_data->td.constraint_changed = true;
+ gpd_data->td.effective_constraint_ns = -1;
+ spin_unlock_irq(&dev->power.lock);
+ mutex_unlock(&gpd_data->lock);
+
+ genpd_release_lock(genpd);
+
+ return 0;
+
out:
genpd_release_lock(genpd);
+ dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
+ kfree(gpd_data);
return ret;
}
@@ -1290,12 +1346,15 @@ int __pm_genpd_of_add_device(struct device_node *genpd_node, struct device *dev,
int pm_genpd_remove_device(struct generic_pm_domain *genpd,
struct device *dev)
{
+ struct generic_pm_domain_data *gpd_data;
struct pm_domain_data *pdd;
- int ret = -EINVAL;
+ int ret = 0;
dev_dbg(dev, "%s()\n", __func__);
- if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
+ if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev)
+ || IS_ERR_OR_NULL(dev->pm_domain)
+ || pd_to_genpd(dev->pm_domain) != genpd)
return -EINVAL;
genpd_acquire_lock(genpd);
@@ -1305,21 +1364,27 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
goto out;
}
- list_for_each_entry(pdd, &genpd->dev_list, list_node) {
- if (pdd->dev != dev)
- continue;
+ genpd->device_count--;
+ genpd->max_off_time_changed = true;
- list_del_init(&pdd->list_node);
- pdd->dev = NULL;
- dev_pm_put_subsys_data(dev);
- dev->pm_domain = NULL;
- kfree(to_gpd_data(pdd));
+ spin_lock_irq(&dev->power.lock);
+ dev->pm_domain = NULL;
+ pdd = dev->power.subsys_data->domain_data;
+ list_del_init(&pdd->list_node);
+ dev->power.subsys_data->domain_data = NULL;
+ spin_unlock_irq(&dev->power.lock);
- genpd->device_count--;
+ gpd_data = to_gpd_data(pdd);
+ mutex_lock(&gpd_data->lock);
+ pdd->dev = NULL;
+ mutex_unlock(&gpd_data->lock);
- ret = 0;
- break;
- }
+ genpd_release_lock(genpd);
+
+ dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
+ kfree(gpd_data);
+ dev_pm_put_subsys_data(dev);
+ return 0;
out:
genpd_release_lock(genpd);
@@ -1348,6 +1413,26 @@ void pm_genpd_dev_always_on(struct device *dev, bool val)
EXPORT_SYMBOL_GPL(pm_genpd_dev_always_on);
/**
+ * pm_genpd_dev_need_restore - Set/unset the device's "need restore" flag.
+ * @dev: Device to set/unset the flag for.
+ * @val: The new value of the device's "need restore" flag.
+ */
+void pm_genpd_dev_need_restore(struct device *dev, bool val)
+{
+ struct pm_subsys_data *psd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->power.lock, flags);
+
+ psd = dev_to_psd(dev);
+ if (psd && psd->domain_data)
+ to_gpd_data(psd->domain_data)->need_restore = val;
+
+ spin_unlock_irqrestore(&dev->power.lock, flags);
+}
+EXPORT_SYMBOL_GPL(pm_genpd_dev_need_restore);
+
+/**
* pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
* @genpd: Master PM domain to add the subdomain to.
* @subdomain: Subdomain to be added.
@@ -1378,7 +1463,7 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
goto out;
}
- list_for_each_entry(link, &genpd->slave_links, slave_node) {
+ list_for_each_entry(link, &genpd->master_links, master_node) {
if (link->slave == subdomain && link->master == genpd) {
ret = -EINVAL;
goto out;
@@ -1690,6 +1775,7 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
genpd->resume_count = 0;
genpd->device_count = 0;
genpd->max_off_time_ns = -1;
+ genpd->max_off_time_changed = true;
genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
genpd->domain.ops.runtime_idle = pm_generic_runtime_idle;
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c
index 66a265bf5867..28dee3053f1f 100644
--- a/drivers/base/power/domain_governor.c
+++ b/drivers/base/power/domain_governor.c
@@ -14,6 +14,31 @@
#ifdef CONFIG_PM_RUNTIME
+static int dev_update_qos_constraint(struct device *dev, void *data)
+{
+ s64 *constraint_ns_p = data;
+ s32 constraint_ns = -1;
+
+ if (dev->power.subsys_data && dev->power.subsys_data->domain_data)
+ constraint_ns = dev_gpd_data(dev)->td.effective_constraint_ns;
+
+ if (constraint_ns < 0) {
+ constraint_ns = dev_pm_qos_read_value(dev);
+ constraint_ns *= NSEC_PER_USEC;
+ }
+ if (constraint_ns == 0)
+ return 0;
+
+ /*
+ * constraint_ns cannot be negative here, because the device has been
+ * suspended.
+ */
+ if (constraint_ns < *constraint_ns_p || *constraint_ns_p == 0)
+ *constraint_ns_p = constraint_ns;
+
+ return 0;
+}
+
/**
* default_stop_ok - Default PM domain governor routine for stopping devices.
* @dev: Device to check.
@@ -21,14 +46,52 @@
bool default_stop_ok(struct device *dev)
{
struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
+ unsigned long flags;
+ s64 constraint_ns;
dev_dbg(dev, "%s()\n", __func__);
- if (dev->power.max_time_suspended_ns < 0 || td->break_even_ns == 0)
- return true;
+ spin_lock_irqsave(&dev->power.lock, flags);
+
+ if (!td->constraint_changed) {
+ bool ret = td->cached_stop_ok;
- return td->stop_latency_ns + td->start_latency_ns < td->break_even_ns
- && td->break_even_ns < dev->power.max_time_suspended_ns;
+ spin_unlock_irqrestore(&dev->power.lock, flags);
+ return ret;
+ }
+ td->constraint_changed = false;
+ td->cached_stop_ok = false;
+ td->effective_constraint_ns = -1;
+ constraint_ns = __dev_pm_qos_read_value(dev);
+
+ spin_unlock_irqrestore(&dev->power.lock, flags);
+
+ if (constraint_ns < 0)
+ return false;
+
+ constraint_ns *= NSEC_PER_USEC;
+ /*
+ * We can walk the children without any additional locking, because
+ * they all have been suspended at this point and their
+ * effective_constraint_ns fields won't be modified in parallel with us.
+ */
+ if (!dev->power.ignore_children)
+ device_for_each_child(dev, &constraint_ns,
+ dev_update_qos_constraint);
+
+ if (constraint_ns > 0) {
+ constraint_ns -= td->start_latency_ns;
+ if (constraint_ns == 0)
+ return false;
+ }
+ td->effective_constraint_ns = constraint_ns;
+ td->cached_stop_ok = constraint_ns > td->stop_latency_ns ||
+ constraint_ns == 0;
+ /*
+ * The children have been suspended already, so we don't need to take
+ * their stop latencies into account here.
+ */
+ return td->cached_stop_ok;
}
/**
@@ -42,9 +105,27 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
struct generic_pm_domain *genpd = pd_to_genpd(pd);
struct gpd_link *link;
struct pm_domain_data *pdd;
- s64 min_dev_off_time_ns;
+ s64 min_off_time_ns;
s64 off_on_time_ns;
- ktime_t time_now = ktime_get();
+
+ if (genpd->max_off_time_changed) {
+ struct gpd_link *link;
+
+ /*
+ * We have to invalidate the cached results for the masters, so
+ * use the observation that default_power_down_ok() is not
+ * going to be called for any master until this instance
+ * returns.
+ */
+ list_for_each_entry(link, &genpd->slave_links, slave_node)
+ link->master->max_off_time_changed = true;
+
+ genpd->max_off_time_changed = false;
+ genpd->cached_power_down_ok = false;
+ genpd->max_off_time_ns = -1;
+ } else {
+ return genpd->cached_power_down_ok;
+ }
off_on_time_ns = genpd->power_off_latency_ns +
genpd->power_on_latency_ns;
@@ -61,6 +142,7 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
to_gpd_data(pdd)->td.save_state_latency_ns;
}
+ min_off_time_ns = -1;
/*
* Check if subdomains can be off for enough time.
*
@@ -73,8 +155,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
if (sd_max_off_ns < 0)
continue;
- sd_max_off_ns -= ktime_to_ns(ktime_sub(time_now,
- sd->power_off_time));
/*
* Check if the subdomain is allowed to be off long enough for
* the current domain to turn off and on (that's how much time
@@ -82,60 +162,64 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
*/
if (sd_max_off_ns <= off_on_time_ns)
return false;
+
+ if (min_off_time_ns > sd_max_off_ns || min_off_time_ns < 0)
+ min_off_time_ns = sd_max_off_ns;
}
/*
* Check if the devices in the domain can be off enough time.
*/
- min_dev_off_time_ns = -1;
list_for_each_entry(pdd, &genpd->dev_list, list_node) {
struct gpd_timing_data *td;
- struct device *dev = pdd->dev;
- s64 dev_off_time_ns;
+ s64 constraint_ns;
- if (!dev->driver || dev->power.max_time_suspended_ns < 0)
+ if (!pdd->dev->driver)
continue;
+ /*
+ * Check if the device is allowed to be off long enough for the
+ * domain to turn off and on (that's how much time it will
+ * have to wait worst case).
+ */
td = &to_gpd_data(pdd)->td;
- dev_off_time_ns = dev->power.max_time_suspended_ns -
- (td->start_latency_ns + td->restore_state_latency_ns +
- ktime_to_ns(ktime_sub(time_now,
- dev->power.suspend_time)));
- if (dev_off_time_ns <= off_on_time_ns)
- return false;
-
- if (min_dev_off_time_ns > dev_off_time_ns
- || min_dev_off_time_ns < 0)
- min_dev_off_time_ns = dev_off_time_ns;
- }
+ constraint_ns = td->effective_constraint_ns;
+ /* default_stop_ok() need not be called before us. */
+ if (constraint_ns < 0) {
+ constraint_ns = dev_pm_qos_read_value(pdd->dev);
+ constraint_ns *= NSEC_PER_USEC;
+ }
+ if (constraint_ns == 0)
+ continue;
- if (min_dev_off_time_ns < 0) {
/*
- * There are no latency constraints, so the domain can spend
- * arbitrary time in the "off" state.
+ * constraint_ns cannot be negative here, because the device has
+ * been suspended.
*/
- genpd->max_off_time_ns = -1;
- return true;
+ constraint_ns -= td->restore_state_latency_ns;
+ if (constraint_ns <= off_on_time_ns)
+ return false;
+
+ if (min_off_time_ns > constraint_ns || min_off_time_ns < 0)
+ min_off_time_ns = constraint_ns;
}
+ genpd->cached_power_down_ok = true;
+
/*
- * The difference between the computed minimum delta and the time needed
- * to turn the domain on is the maximum theoretical time this domain can
- * spend in the "off" state.
+ * If the computed minimum device off time is negative, there are no
+ * latency constraints, so the domain can spend arbitrary time in the
+ * "off" state.
*/
- min_dev_off_time_ns -= genpd->power_on_latency_ns;
+ if (min_off_time_ns < 0)
+ return true;
/*
- * If the difference between the computed minimum delta and the time
- * needed to turn the domain off and back on on is smaller than the
- * domain's power break even time, removing power from the domain is not
- * worth it.
+ * The difference between the computed minimum subdomain or device off
+ * time and the time needed to turn the domain on is the maximum
+ * theoretical time this domain can spend in the "off" state.
*/
- if (genpd->break_even_ns >
- min_dev_off_time_ns - genpd->power_off_latency_ns)
- return false;
-
- genpd->max_off_time_ns = min_dev_off_time_ns;
+ genpd->max_off_time_ns = min_off_time_ns - genpd->power_on_latency_ns;
return true;
}
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index b462c0e341cb..e0fb5b0435a3 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -889,6 +889,11 @@ static int dpm_suspend_noirq(pm_message_t state)
if (!list_empty(&dev->power.entry))
list_move(&dev->power.entry, &dpm_noirq_list);
put_device(dev);
+
+ if (pm_wakeup_pending()) {
+ error = -EBUSY;
+ break;
+ }
}
mutex_unlock(&dpm_list_mtx);
if (error)
@@ -962,6 +967,11 @@ static int dpm_suspend_late(pm_message_t state)
if (!list_empty(&dev->power.entry))
list_move(&dev->power.entry, &dpm_late_early_list);
put_device(dev);
+
+ if (pm_wakeup_pending()) {
+ error = -EBUSY;
+ break;
+ }
}
mutex_unlock(&dpm_list_mtx);
if (error)
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index 71855570922d..fd849a2c4fa8 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -352,21 +352,26 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);
*
* Will register the notifier into a notification chain that gets called
* upon changes to the target value for the device.
+ *
+ * If the device's constraints object doesn't exist when this routine is called,
+ * it will be created (or error code will be returned if that fails).
*/
int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
{
- int retval = 0;
+ int ret = 0;
mutex_lock(&dev_pm_qos_mtx);
- /* Silently return if the constraints object is not present. */
- if (dev->power.constraints)
- retval = blocking_notifier_chain_register(
- dev->power.constraints->notifiers,
- notifier);
+ if (!dev->power.constraints)
+ ret = dev->power.power_state.event != PM_EVENT_INVALID ?
+ dev_pm_qos_constraints_allocate(dev) : -ENODEV;
+
+ if (!ret)
+ ret = blocking_notifier_chain_register(
+ dev->power.constraints->notifiers, notifier);
mutex_unlock(&dev_pm_qos_mtx);
- return retval;
+ return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index bd0f3949bcf9..59894873a3b3 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -282,47 +282,6 @@ static int rpm_callback(int (*cb)(struct device *), struct device *dev)
return retval != -EACCES ? retval : -EIO;
}
-struct rpm_qos_data {
- ktime_t time_now;
- s64 constraint_ns;
-};
-
-/**
- * rpm_update_qos_constraint - Update a given PM QoS constraint data.
- * @dev: Device whose timing data to use.
- * @data: PM QoS constraint data to update.
- *
- * Use the suspend timing data of @dev to update PM QoS constraint data pointed
- * to by @data.
- */
-static int rpm_update_qos_constraint(struct device *dev, void *data)
-{
- struct rpm_qos_data *qos = data;
- unsigned long flags;
- s64 delta_ns;
- int ret = 0;
-
- spin_lock_irqsave(&dev->power.lock, flags);
-
- if (dev->power.max_time_suspended_ns < 0)
- goto out;
-
- delta_ns = dev->power.max_time_suspended_ns -
- ktime_to_ns(ktime_sub(qos->time_now, dev->power.suspend_time));
- if (delta_ns <= 0) {
- ret = -EBUSY;
- goto out;
- }
-
- if (qos->constraint_ns > delta_ns || qos->constraint_ns == 0)
- qos->constraint_ns = delta_ns;
-
- out:
- spin_unlock_irqrestore(&dev->power.lock, flags);
-
- return ret;
-}
-
/**
* rpm_suspend - Carry out runtime suspend of given device.
* @dev: Device to suspend.
@@ -349,7 +308,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)
{
int (*callback)(struct device *);
struct device *parent = NULL;
- struct rpm_qos_data qos;
int retval;
trace_rpm_suspend(dev, rpmflags);
@@ -445,38 +403,14 @@ static int rpm_suspend(struct device *dev, int rpmflags)
goto out;
}
- qos.constraint_ns = __dev_pm_qos_read_value(dev);
- if (qos.constraint_ns < 0) {
- /* Negative constraint means "never suspend". */
+ if (__dev_pm_qos_read_value(dev) < 0) {
+ /* Negative PM QoS constraint means "never suspend". */
retval = -EPERM;
goto out;
}
- qos.constraint_ns *= NSEC_PER_USEC;
- qos.time_now = ktime_get();
__update_runtime_status(dev, RPM_SUSPENDING);
- if (!dev->power.ignore_children) {
- if (dev->power.irq_safe)
- spin_unlock(&dev->power.lock);
- else
- spin_unlock_irq(&dev->power.lock);
-
- retval = device_for_each_child(dev, &qos,
- rpm_update_qos_constraint);
-
- if (dev->power.irq_safe)
- spin_lock(&dev->power.lock);
- else
- spin_lock_irq(&dev->power.lock);
-
- if (retval)
- goto fail;
- }
-
- dev->power.suspend_time = qos.time_now;
- dev->power.max_time_suspended_ns = qos.constraint_ns ? : -1;
-
if (dev->pm_domain)
callback = dev->pm_domain->ops.runtime_suspend;
else if (dev->type && dev->type->pm)
@@ -529,8 +463,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)
fail:
__update_runtime_status(dev, RPM_ACTIVE);
- dev->power.suspend_time = ktime_set(0, 0);
- dev->power.max_time_suspended_ns = -1;
dev->power.deferred_resume = false;
wake_up_all(&dev->power.wait_queue);
@@ -704,9 +636,6 @@ static int rpm_resume(struct device *dev, int rpmflags)
if (dev->power.no_callbacks)
goto no_callback; /* Assume success. */
- dev->power.suspend_time = ktime_set(0, 0);
- dev->power.max_time_suspended_ns = -1;
-
__update_runtime_status(dev, RPM_RESUMING);
if (dev->pm_domain)
@@ -1369,9 +1298,6 @@ void pm_runtime_init(struct device *dev)
setup_timer(&dev->power.suspend_timer, pm_suspend_timer_fn,
(unsigned long)dev);
- dev->power.suspend_time = ktime_set(0, 0);
- dev->power.max_time_suspended_ns = -1;
-
init_waitqueue_head(&dev->power.wait_queue);
}
@@ -1389,28 +1315,3 @@ void pm_runtime_remove(struct device *dev)
if (dev->power.irq_safe && dev->parent)
pm_runtime_put_sync(dev->parent);
}
-
-/**
- * pm_runtime_update_max_time_suspended - Update device's suspend time data.
- * @dev: Device to handle.
- * @delta_ns: Value to subtract from the device's max_time_suspended_ns field.
- *
- * Update the device's power.max_time_suspended_ns field by subtracting
- * @delta_ns from it. The resulting value of power.max_time_suspended_ns is
- * never negative.
- */
-void pm_runtime_update_max_time_suspended(struct device *dev, s64 delta_ns)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&dev->power.lock, flags);
-
- if (delta_ns > 0 && dev->power.max_time_suspended_ns > 0) {
- if (dev->power.max_time_suspended_ns > delta_ns)
- dev->power.max_time_suspended_ns -= delta_ns;
- else
- dev->power.max_time_suspended_ns = 0;
- }
-
- spin_unlock_irqrestore(&dev->power.lock, flags);
-}
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 95c12f6cb5b9..48be2ad4dd2c 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -314,22 +314,41 @@ static ssize_t wakeup_active_count_show(struct device *dev,
static DEVICE_ATTR(wakeup_active_count, 0444, wakeup_active_count_show, NULL);
-static ssize_t wakeup_hit_count_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t wakeup_abort_count_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long count = 0;
+ bool enabled = false;
+
+ spin_lock_irq(&dev->power.lock);
+ if (dev->power.wakeup) {
+ count = dev->power.wakeup->wakeup_count;
+ enabled = true;
+ }
+ spin_unlock_irq(&dev->power.lock);
+ return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_abort_count, 0444, wakeup_abort_count_show, NULL);
+
+static ssize_t wakeup_expire_count_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
unsigned long count = 0;
bool enabled = false;
spin_lock_irq(&dev->power.lock);
if (dev->power.wakeup) {
- count = dev->power.wakeup->hit_count;
+ count = dev->power.wakeup->expire_count;
enabled = true;
}
spin_unlock_irq(&dev->power.lock);
return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
}
-static DEVICE_ATTR(wakeup_hit_count, 0444, wakeup_hit_count_show, NULL);
+static DEVICE_ATTR(wakeup_expire_count, 0444, wakeup_expire_count_show, NULL);
static ssize_t wakeup_active_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -398,6 +417,27 @@ static ssize_t wakeup_last_time_show(struct device *dev,
}
static DEVICE_ATTR(wakeup_last_time_ms, 0444, wakeup_last_time_show, NULL);
+
+#ifdef CONFIG_PM_AUTOSLEEP
+static ssize_t wakeup_prevent_sleep_time_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ s64 msec = 0;
+ bool enabled = false;
+
+ spin_lock_irq(&dev->power.lock);
+ if (dev->power.wakeup) {
+ msec = ktime_to_ms(dev->power.wakeup->prevent_sleep_time);
+ enabled = true;
+ }
+ spin_unlock_irq(&dev->power.lock);
+ return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_prevent_sleep_time_ms, 0444,
+ wakeup_prevent_sleep_time_show, NULL);
+#endif /* CONFIG_PM_AUTOSLEEP */
#endif /* CONFIG_PM_SLEEP */
#ifdef CONFIG_PM_ADVANCED_DEBUG
@@ -486,11 +526,15 @@ static struct attribute *wakeup_attrs[] = {
&dev_attr_wakeup.attr,
&dev_attr_wakeup_count.attr,
&dev_attr_wakeup_active_count.attr,
- &dev_attr_wakeup_hit_count.attr,
+ &dev_attr_wakeup_abort_count.attr,
+ &dev_attr_wakeup_expire_count.attr,
&dev_attr_wakeup_active.attr,
&dev_attr_wakeup_total_time_ms.attr,
&dev_attr_wakeup_max_time_ms.attr,
&dev_attr_wakeup_last_time_ms.attr,
+#ifdef CONFIG_PM_AUTOSLEEP
+ &dev_attr_wakeup_prevent_sleep_time_ms.attr,
+#endif
#endif
NULL,
};
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 2a3e581b8dcd..cbb463b3a750 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -14,16 +14,15 @@
#include <linux/suspend.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>
+#include <trace/events/power.h>
#include "power.h"
-#define TIMEOUT 100
-
/*
* If set, the suspend/hibernate code will abort transitions to a sleep state
* if wakeup events are registered during or immediately before the transition.
*/
-bool events_check_enabled;
+bool events_check_enabled __read_mostly;
/*
* Combined counters of registered wakeup events and wakeup events in progress.
@@ -52,6 +51,8 @@ static void pm_wakeup_timer_fn(unsigned long data);
static LIST_HEAD(wakeup_sources);
+static DECLARE_WAIT_QUEUE_HEAD(wakeup_count_wait_queue);
+
/**
* wakeup_source_prepare - Prepare a new wakeup source for initialization.
* @ws: Wakeup source to prepare.
@@ -132,6 +133,7 @@ void wakeup_source_add(struct wakeup_source *ws)
spin_lock_init(&ws->lock);
setup_timer(&ws->timer, pm_wakeup_timer_fn, (unsigned long)ws);
ws->active = false;
+ ws->last_time = ktime_get();
spin_lock_irq(&events_lock);
list_add_rcu(&ws->entry, &wakeup_sources);
@@ -374,12 +376,33 @@ EXPORT_SYMBOL_GPL(device_set_wakeup_enable);
*/
static void wakeup_source_activate(struct wakeup_source *ws)
{
+ unsigned int cec;
+
ws->active = true;
ws->active_count++;
ws->last_time = ktime_get();
+ if (ws->autosleep_enabled)
+ ws->start_prevent_time = ws->last_time;
/* Increment the counter of events in progress. */
- atomic_inc(&combined_event_count);
+ cec = atomic_inc_return(&combined_event_count);
+
+ trace_wakeup_source_activate(ws->name, cec);
+}
+
+/**
+ * wakeup_source_report_event - Report wakeup event using the given source.
+ * @ws: Wakeup source to report the event for.
+ */
+static void wakeup_source_report_event(struct wakeup_source *ws)
+{
+ ws->event_count++;
+ /* This is racy, but the counter is approximate anyway. */
+ if (events_check_enabled)
+ ws->wakeup_count++;
+
+ if (!ws->active)
+ wakeup_source_activate(ws);
}
/**
@@ -397,10 +420,7 @@ void __pm_stay_awake(struct wakeup_source *ws)
spin_lock_irqsave(&ws->lock, flags);
- ws->event_count++;
- if (!ws->active)
- wakeup_source_activate(ws);
-
+ wakeup_source_report_event(ws);
del_timer(&ws->timer);
ws->timer_expires = 0;
@@ -432,6 +452,17 @@ void pm_stay_awake(struct device *dev)
}
EXPORT_SYMBOL_GPL(pm_stay_awake);
+#ifdef CONFIG_PM_AUTOSLEEP
+static void update_prevent_sleep_time(struct wakeup_source *ws, ktime_t now)
+{
+ ktime_t delta = ktime_sub(now, ws->start_prevent_time);
+ ws->prevent_sleep_time = ktime_add(ws->prevent_sleep_time, delta);
+}
+#else
+static inline void update_prevent_sleep_time(struct wakeup_source *ws,
+ ktime_t now) {}
+#endif
+
/**
* wakup_source_deactivate - Mark given wakeup source as inactive.
* @ws: Wakeup source to handle.
@@ -442,6 +473,7 @@ EXPORT_SYMBOL_GPL(pm_stay_awake);
*/
static void wakeup_source_deactivate(struct wakeup_source *ws)
{
+ unsigned int cnt, inpr, cec;
ktime_t duration;
ktime_t now;
@@ -468,14 +500,23 @@ static void wakeup_source_deactivate(struct wakeup_source *ws)
if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time))
ws->max_time = duration;
+ ws->last_time = now;
del_timer(&ws->timer);
ws->timer_expires = 0;
+ if (ws->autosleep_enabled)
+ update_prevent_sleep_time(ws, now);
+
/*
* Increment the counter of registered wakeup events and decrement the
* couter of wakeup events in progress simultaneously.
*/
- atomic_add(MAX_IN_PROGRESS, &combined_event_count);
+ cec = atomic_add_return(MAX_IN_PROGRESS, &combined_event_count);
+ trace_wakeup_source_deactivate(ws->name, cec);
+
+ split_counters(&cnt, &inpr);
+ if (!inpr && waitqueue_active(&wakeup_count_wait_queue))
+ wake_up(&wakeup_count_wait_queue);
}
/**
@@ -536,8 +577,10 @@ static void pm_wakeup_timer_fn(unsigned long data)
spin_lock_irqsave(&ws->lock, flags);
if (ws->active && ws->timer_expires
- && time_after_eq(jiffies, ws->timer_expires))
+ && time_after_eq(jiffies, ws->timer_expires)) {
wakeup_source_deactivate(ws);
+ ws->expire_count++;
+ }
spin_unlock_irqrestore(&ws->lock, flags);
}
@@ -564,9 +607,7 @@ void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
spin_lock_irqsave(&ws->lock, flags);
- ws->event_count++;
- if (!ws->active)
- wakeup_source_activate(ws);
+ wakeup_source_report_event(ws);
if (!msec) {
wakeup_source_deactivate(ws);
@@ -609,24 +650,6 @@ void pm_wakeup_event(struct device *dev, unsigned int msec)
EXPORT_SYMBOL_GPL(pm_wakeup_event);
/**
- * pm_wakeup_update_hit_counts - Update hit counts of all active wakeup sources.
- */
-static void pm_wakeup_update_hit_counts(void)
-{
- unsigned long flags;
- struct wakeup_source *ws;
-
- rcu_read_lock();
- list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
- spin_lock_irqsave(&ws->lock, flags);
- if (ws->active)
- ws->hit_count++;
- spin_unlock_irqrestore(&ws->lock, flags);
- }
- rcu_read_unlock();
-}
-
-/**
* pm_wakeup_pending - Check if power transition in progress should be aborted.
*
* Compare the current number of registered wakeup events with its preserved
@@ -648,32 +671,38 @@ bool pm_wakeup_pending(void)
events_check_enabled = !ret;
}
spin_unlock_irqrestore(&events_lock, flags);
- if (ret)
- pm_wakeup_update_hit_counts();
return ret;
}
/**
* pm_get_wakeup_count - Read the number of registered wakeup events.
* @count: Address to store the value at.
+ * @block: Whether or not to block.
*
- * Store the number of registered wakeup events at the address in @count. Block
- * if the current number of wakeup events being processed is nonzero.
+ * Store the number of registered wakeup events at the address in @count. If
+ * @block is set, block until the current number of wakeup events being
+ * processed is zero.
*
- * Return 'false' if the wait for the number of wakeup events being processed to
- * drop down to zero has been interrupted by a signal (and the current number
- * of wakeup events being processed is still nonzero). Otherwise return 'true'.
+ * Return 'false' if the current number of wakeup events being processed is
+ * nonzero. Otherwise return 'true'.
*/
-bool pm_get_wakeup_count(unsigned int *count)
+bool pm_get_wakeup_count(unsigned int *count, bool block)
{
unsigned int cnt, inpr;
- for (;;) {
- split_counters(&cnt, &inpr);
- if (inpr == 0 || signal_pending(current))
- break;
- pm_wakeup_update_hit_counts();
- schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
+ if (block) {
+ DEFINE_WAIT(wait);
+
+ for (;;) {
+ prepare_to_wait(&wakeup_count_wait_queue, &wait,
+ TASK_INTERRUPTIBLE);
+ split_counters(&cnt, &inpr);
+ if (inpr == 0 || signal_pending(current))
+ break;
+
+ schedule();
+ }
+ finish_wait(&wakeup_count_wait_queue, &wait);
}
split_counters(&cnt, &inpr);
@@ -703,11 +732,37 @@ bool pm_save_wakeup_count(unsigned int count)
events_check_enabled = true;
}
spin_unlock_irq(&events_lock);
- if (!events_check_enabled)
- pm_wakeup_update_hit_counts();
return events_check_enabled;
}
+#ifdef CONFIG_PM_AUTOSLEEP
+/**
+ * pm_wakep_autosleep_enabled - Modify autosleep_enabled for all wakeup sources.
+ * @enabled: Whether to set or to clear the autosleep_enabled flags.
+ */
+void pm_wakep_autosleep_enabled(bool set)
+{
+ struct wakeup_source *ws;
+ ktime_t now = ktime_get();
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
+ spin_lock_irq(&ws->lock);
+ if (ws->autosleep_enabled != set) {
+ ws->autosleep_enabled = set;
+ if (ws->active) {
+ if (set)
+ ws->start_prevent_time = now;
+ else
+ update_prevent_sleep_time(ws, now);
+ }
+ }
+ spin_unlock_irq(&ws->lock);
+ }
+ rcu_read_unlock();
+}
+#endif /* CONFIG_PM_AUTOSLEEP */
+
static struct dentry *wakeup_sources_stats_dentry;
/**
@@ -723,27 +778,37 @@ static int print_wakeup_source_stats(struct seq_file *m,
ktime_t max_time;
unsigned long active_count;
ktime_t active_time;
+ ktime_t prevent_sleep_time;
int ret;
spin_lock_irqsave(&ws->lock, flags);
total_time = ws->total_time;
max_time = ws->max_time;
+ prevent_sleep_time = ws->prevent_sleep_time;
active_count = ws->active_count;
if (ws->active) {
- active_time = ktime_sub(ktime_get(), ws->last_time);
+ ktime_t now = ktime_get();
+
+ active_time = ktime_sub(now, ws->last_time);
total_time = ktime_add(total_time, active_time);
if (active_time.tv64 > max_time.tv64)
max_time = active_time;
+
+ if (ws->autosleep_enabled)
+ prevent_sleep_time = ktime_add(prevent_sleep_time,
+ ktime_sub(now, ws->start_prevent_time));
} else {
active_time = ktime_set(0, 0);
}
- ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t"
- "%lld\t\t%lld\t\t%lld\t\t%lld\n",
- ws->name, active_count, ws->event_count, ws->hit_count,
+ ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t"
+ "%lld\t\t%lld\t\t%lld\t\t%lld\t\t%lld\n",
+ ws->name, active_count, ws->event_count,
+ ws->wakeup_count, ws->expire_count,
ktime_to_ms(active_time), ktime_to_ms(total_time),
- ktime_to_ms(max_time), ktime_to_ms(ws->last_time));
+ ktime_to_ms(max_time), ktime_to_ms(ws->last_time),
+ ktime_to_ms(prevent_sleep_time));
spin_unlock_irqrestore(&ws->lock, flags);
@@ -758,8 +823,9 @@ static int wakeup_sources_stats_show(struct seq_file *m, void *unused)
{
struct wakeup_source *ws;
- seq_puts(m, "name\t\tactive_count\tevent_count\thit_count\t"
- "active_since\ttotal_time\tmax_time\tlast_change\n");
+ seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t"
+ "expire_count\tactive_since\ttotal_time\tmax_time\t"
+ "last_change\tprevent_suspend_time\n");
rcu_read_lock();
list_for_each_entry_rcu(ws, &wakeup_sources, entry)
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index 0f6c7fb418e8..6be390bd8bd1 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -6,6 +6,7 @@ config REGMAP
default y if (REGMAP_I2C || REGMAP_SPI)
select LZO_COMPRESS
select LZO_DECOMPRESS
+ select IRQ_DOMAIN if REGMAP_IRQ
bool
config REGMAP_I2C
@@ -14,5 +15,8 @@ config REGMAP_I2C
config REGMAP_SPI
tristate
+config REGMAP_MMIO
+ tristate
+
config REGMAP_IRQ
bool
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
index defd57963c84..5e75d1b683e2 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -3,4 +3,5 @@ obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o
obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
+obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o
obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index fcafc5b2e651..b986b8660b0c 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -26,21 +26,30 @@ struct regmap_format {
size_t val_bytes;
void (*format_write)(struct regmap *map,
unsigned int reg, unsigned int val);
- void (*format_reg)(void *buf, unsigned int reg);
- void (*format_val)(void *buf, unsigned int val);
+ void (*format_reg)(void *buf, unsigned int reg, unsigned int shift);
+ void (*format_val)(void *buf, unsigned int val, unsigned int shift);
unsigned int (*parse_val)(void *buf);
};
+typedef void (*regmap_lock)(struct regmap *map);
+typedef void (*regmap_unlock)(struct regmap *map);
+
struct regmap {
- struct mutex lock;
+ struct mutex mutex;
+ spinlock_t spinlock;
+ regmap_lock lock;
+ regmap_unlock unlock;
struct device *dev; /* Device we do I/O on */
void *work_buf; /* Scratch buffer used to format I/O */
struct regmap_format format; /* Buffer format */
const struct regmap_bus *bus;
+ void *bus_context;
+ const char *name;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs;
+ const char *debugfs_name;
#endif
unsigned int max_register;
@@ -52,6 +61,10 @@ struct regmap {
u8 read_flag_mask;
u8 write_flag_mask;
+ /* number of bits to (left) shift the reg value when formatting*/
+ int reg_shift;
+ int reg_stride;
+
/* regcache specific members */
const struct regcache_ops *cache_ops;
enum regcache_type cache_type;
@@ -79,6 +92,9 @@ struct regmap {
struct reg_default *patch;
int patch_regs;
+
+ /* if set, converts bulk rw to single rw */
+ bool use_single_rw;
};
struct regcache_ops {
@@ -101,11 +117,11 @@ int _regmap_write(struct regmap *map, unsigned int reg,
#ifdef CONFIG_DEBUG_FS
extern void regmap_debugfs_initcall(void);
-extern void regmap_debugfs_init(struct regmap *map);
+extern void regmap_debugfs_init(struct regmap *map, const char *name);
extern void regmap_debugfs_exit(struct regmap *map);
#else
static inline void regmap_debugfs_initcall(void) { }
-static inline void regmap_debugfs_init(struct regmap *map) { }
+static inline void regmap_debugfs_init(struct regmap *map, const char *name) { }
static inline void regmap_debugfs_exit(struct regmap *map) { }
#endif
diff --git a/drivers/base/regmap/regcache-lzo.c b/drivers/base/regmap/regcache-lzo.c
index 483b06d4a380..afd6aa91a0df 100644
--- a/drivers/base/regmap/regcache-lzo.c
+++ b/drivers/base/regmap/regcache-lzo.c
@@ -108,7 +108,7 @@ static int regcache_lzo_decompress_cache_block(struct regmap *map,
static inline int regcache_lzo_get_blkindex(struct regmap *map,
unsigned int reg)
{
- return (reg * map->cache_word_size) /
+ return ((reg / map->reg_stride) * map->cache_word_size) /
DIV_ROUND_UP(map->cache_size_raw,
regcache_lzo_block_count(map));
}
@@ -116,9 +116,10 @@ static inline int regcache_lzo_get_blkindex(struct regmap *map,
static inline int regcache_lzo_get_blkpos(struct regmap *map,
unsigned int reg)
{
- return reg % (DIV_ROUND_UP(map->cache_size_raw,
- regcache_lzo_block_count(map)) /
- map->cache_word_size);
+ return (reg / map->reg_stride) %
+ (DIV_ROUND_UP(map->cache_size_raw,
+ regcache_lzo_block_count(map)) /
+ map->cache_word_size);
}
static inline int regcache_lzo_get_blksize(struct regmap *map)
@@ -322,7 +323,7 @@ static int regcache_lzo_write(struct regmap *map,
}
/* set the bit so we know we have to sync this register */
- set_bit(reg, lzo_block->sync_bmp);
+ set_bit(reg / map->reg_stride, lzo_block->sync_bmp);
kfree(tmp_dst);
kfree(lzo_block->src);
return 0;
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index 92b779ee002b..e6732cf7c06e 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -39,11 +39,12 @@ struct regcache_rbtree_ctx {
};
static inline void regcache_rbtree_get_base_top_reg(
+ struct regmap *map,
struct regcache_rbtree_node *rbnode,
unsigned int *base, unsigned int *top)
{
*base = rbnode->base_reg;
- *top = rbnode->base_reg + rbnode->blklen - 1;
+ *top = rbnode->base_reg + ((rbnode->blklen - 1) * map->reg_stride);
}
static unsigned int regcache_rbtree_get_register(
@@ -70,7 +71,8 @@ static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
rbnode = rbtree_ctx->cached_rbnode;
if (rbnode) {
- regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
+ regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
+ &top_reg);
if (reg >= base_reg && reg <= top_reg)
return rbnode;
}
@@ -78,7 +80,8 @@ static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
node = rbtree_ctx->root.rb_node;
while (node) {
rbnode = container_of(node, struct regcache_rbtree_node, node);
- regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
+ regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
+ &top_reg);
if (reg >= base_reg && reg <= top_reg) {
rbtree_ctx->cached_rbnode = rbnode;
return rbnode;
@@ -92,7 +95,7 @@ static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
return NULL;
}
-static int regcache_rbtree_insert(struct rb_root *root,
+static int regcache_rbtree_insert(struct regmap *map, struct rb_root *root,
struct regcache_rbtree_node *rbnode)
{
struct rb_node **new, *parent;
@@ -106,7 +109,7 @@ static int regcache_rbtree_insert(struct rb_root *root,
rbnode_tmp = container_of(*new, struct regcache_rbtree_node,
node);
/* base and top registers of the current rbnode */
- regcache_rbtree_get_base_top_reg(rbnode_tmp, &base_reg_tmp,
+ regcache_rbtree_get_base_top_reg(map, rbnode_tmp, &base_reg_tmp,
&top_reg_tmp);
/* base register of the rbnode to be added */
base_reg = rbnode->base_reg;
@@ -138,19 +141,20 @@ static int rbtree_show(struct seq_file *s, void *ignored)
unsigned int base, top;
int nodes = 0;
int registers = 0;
- int average;
+ int this_registers, average;
- mutex_lock(&map->lock);
+ map->lock(map);
for (node = rb_first(&rbtree_ctx->root); node != NULL;
node = rb_next(node)) {
n = container_of(node, struct regcache_rbtree_node, node);
- regcache_rbtree_get_base_top_reg(n, &base, &top);
- seq_printf(s, "%x-%x (%d)\n", base, top, top - base + 1);
+ regcache_rbtree_get_base_top_reg(map, n, &base, &top);
+ this_registers = ((top - base) / map->reg_stride) + 1;
+ seq_printf(s, "%x-%x (%d)\n", base, top, this_registers);
nodes++;
- registers += top - base + 1;
+ registers += this_registers;
}
if (nodes)
@@ -161,7 +165,7 @@ static int rbtree_show(struct seq_file *s, void *ignored)
seq_printf(s, "%d nodes, %d registers, average %d registers\n",
nodes, registers, average);
- mutex_unlock(&map->lock);
+ map->unlock(map);
return 0;
}
@@ -255,7 +259,7 @@ static int regcache_rbtree_read(struct regmap *map,
rbnode = regcache_rbtree_lookup(map, reg);
if (rbnode) {
- reg_tmp = reg - rbnode->base_reg;
+ reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
*value = regcache_rbtree_get_register(rbnode, reg_tmp,
map->cache_word_size);
} else {
@@ -310,7 +314,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
*/
rbnode = regcache_rbtree_lookup(map, reg);
if (rbnode) {
- reg_tmp = reg - rbnode->base_reg;
+ reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
val = regcache_rbtree_get_register(rbnode, reg_tmp,
map->cache_word_size);
if (val == value)
@@ -321,13 +325,15 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
/* look for an adjacent register to the one we are about to add */
for (node = rb_first(&rbtree_ctx->root); node;
node = rb_next(node)) {
- rbnode_tmp = rb_entry(node, struct regcache_rbtree_node, node);
+ rbnode_tmp = rb_entry(node, struct regcache_rbtree_node,
+ node);
for (i = 0; i < rbnode_tmp->blklen; i++) {
- reg_tmp = rbnode_tmp->base_reg + i;
- if (abs(reg_tmp - reg) != 1)
+ reg_tmp = rbnode_tmp->base_reg +
+ (i * map->reg_stride);
+ if (abs(reg_tmp - reg) != map->reg_stride)
continue;
/* decide where in the block to place our register */
- if (reg_tmp + 1 == reg)
+ if (reg_tmp + map->reg_stride == reg)
pos = i + 1;
else
pos = i;
@@ -357,7 +363,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
return -ENOMEM;
}
regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size);
- regcache_rbtree_insert(&rbtree_ctx->root, rbnode);
+ regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode);
rbtree_ctx->cached_rbnode = rbnode;
}
@@ -397,7 +403,7 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
end = rbnode->blklen;
for (i = base; i < end; i++) {
- regtmp = rbnode->base_reg + i;
+ regtmp = rbnode->base_reg + (i * map->reg_stride);
val = regcache_rbtree_get_register(rbnode, i,
map->cache_word_size);
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 74b69095def6..835883bda977 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -59,7 +59,7 @@ static int regcache_hw_init(struct regmap *map)
for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
val = regcache_get_val(map->reg_defaults_raw,
i, map->cache_word_size);
- if (regmap_volatile(map, i))
+ if (regmap_volatile(map, i * map->reg_stride))
continue;
count++;
}
@@ -76,9 +76,9 @@ static int regcache_hw_init(struct regmap *map)
for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
val = regcache_get_val(map->reg_defaults_raw,
i, map->cache_word_size);
- if (regmap_volatile(map, i))
+ if (regmap_volatile(map, i * map->reg_stride))
continue;
- map->reg_defaults[j].reg = i;
+ map->reg_defaults[j].reg = i * map->reg_stride;
map->reg_defaults[j].def = val;
j++;
}
@@ -98,6 +98,10 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
int i;
void *tmp_buf;
+ for (i = 0; i < config->num_reg_defaults; i++)
+ if (config->reg_defaults[i].reg % map->reg_stride)
+ return -EINVAL;
+
if (map->cache_type == REGCACHE_NONE) {
map->cache_bypass = true;
return 0;
@@ -264,7 +268,7 @@ int regcache_sync(struct regmap *map)
BUG_ON(!map->cache_ops || !map->cache_ops->sync);
- mutex_lock(&map->lock);
+ map->lock(map);
/* Remember the initial bypass state */
bypass = map->cache_bypass;
dev_dbg(map->dev, "Syncing %s cache\n",
@@ -278,6 +282,10 @@ int regcache_sync(struct regmap *map)
/* Apply any patch first */
map->cache_bypass = 1;
for (i = 0; i < map->patch_regs; i++) {
+ if (map->patch[i].reg % map->reg_stride) {
+ ret = -EINVAL;
+ goto out;
+ }
ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
if (ret != 0) {
dev_err(map->dev, "Failed to write %x = %x: %d\n",
@@ -296,7 +304,7 @@ out:
trace_regcache_sync(map->dev, name, "stop");
/* Restore the bypass state */
map->cache_bypass = bypass;
- mutex_unlock(&map->lock);
+ map->unlock(map);
return ret;
}
@@ -323,7 +331,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
BUG_ON(!map->cache_ops || !map->cache_ops->sync);
- mutex_lock(&map->lock);
+ map->lock(map);
/* Remember the initial bypass state */
bypass = map->cache_bypass;
@@ -342,7 +350,7 @@ out:
trace_regcache_sync(map->dev, name, "stop region");
/* Restore the bypass state */
map->cache_bypass = bypass;
- mutex_unlock(&map->lock);
+ map->unlock(map);
return ret;
}
@@ -362,11 +370,11 @@ EXPORT_SYMBOL_GPL(regcache_sync_region);
*/
void regcache_cache_only(struct regmap *map, bool enable)
{
- mutex_lock(&map->lock);
+ map->lock(map);
WARN_ON(map->cache_bypass && enable);
map->cache_only = enable;
trace_regmap_cache_only(map->dev, enable);
- mutex_unlock(&map->lock);
+ map->unlock(map);
}
EXPORT_SYMBOL_GPL(regcache_cache_only);
@@ -381,9 +389,9 @@ EXPORT_SYMBOL_GPL(regcache_cache_only);
*/
void regcache_mark_dirty(struct regmap *map)
{
- mutex_lock(&map->lock);
+ map->lock(map);
map->cache_dirty = true;
- mutex_unlock(&map->lock);
+ map->unlock(map);
}
EXPORT_SYMBOL_GPL(regcache_mark_dirty);
@@ -400,11 +408,11 @@ EXPORT_SYMBOL_GPL(regcache_mark_dirty);
*/
void regcache_cache_bypass(struct regmap *map, bool enable)
{
- mutex_lock(&map->lock);
+ map->lock(map);
WARN_ON(map->cache_only && enable);
map->cache_bypass = enable;
trace_regmap_cache_bypass(map->dev, enable);
- mutex_unlock(&map->lock);
+ map->unlock(map);
}
EXPORT_SYMBOL_GPL(regcache_cache_bypass);
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index 251eb70f83e7..bb1ff175b962 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -80,7 +80,7 @@ static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
val_len = 2 * map->format.val_bytes;
tot_len = reg_len + val_len + 3; /* : \n */
- for (i = 0; i < map->max_register + 1; i++) {
+ for (i = 0; i <= map->max_register; i += map->reg_stride) {
if (!regmap_readable(map, i))
continue;
@@ -197,7 +197,7 @@ static ssize_t regmap_access_read_file(struct file *file,
reg_len = regmap_calc_reg_len(map->max_register, buf, count);
tot_len = reg_len + 10; /* ': R W V P\n' */
- for (i = 0; i < map->max_register + 1; i++) {
+ for (i = 0; i <= map->max_register; i += map->reg_stride) {
/* Ignore registers which are neither readable nor writable */
if (!regmap_readable(map, i) && !regmap_writeable(map, i))
continue;
@@ -242,10 +242,17 @@ static const struct file_operations regmap_access_fops = {
.llseek = default_llseek,
};
-void regmap_debugfs_init(struct regmap *map)
+void regmap_debugfs_init(struct regmap *map, const char *name)
{
- map->debugfs = debugfs_create_dir(dev_name(map->dev),
- regmap_debugfs_root);
+ if (name) {
+ map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s",
+ dev_name(map->dev), name);
+ name = map->debugfs_name;
+ } else {
+ name = dev_name(map->dev);
+ }
+
+ map->debugfs = debugfs_create_dir(name, regmap_debugfs_root);
if (!map->debugfs) {
dev_warn(map->dev, "Failed to create debugfs directory\n");
return;
@@ -274,6 +281,7 @@ void regmap_debugfs_init(struct regmap *map)
void regmap_debugfs_exit(struct regmap *map)
{
debugfs_remove_recursive(map->debugfs);
+ kfree(map->debugfs_name);
}
void regmap_debugfs_initcall(void)
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index 9a3a8c564389..5f6b2478bf17 100644
--- a/drivers/base/regmap/regmap-i2c.c
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -15,8 +15,9 @@
#include <linux/module.h>
#include <linux/init.h>
-static int regmap_i2c_write(struct device *dev, const void *data, size_t count)
+static int regmap_i2c_write(void *context, const void *data, size_t count)
{
+ struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev);
int ret;
@@ -29,10 +30,11 @@ static int regmap_i2c_write(struct device *dev, const void *data, size_t count)
return -EIO;
}
-static int regmap_i2c_gather_write(struct device *dev,
+static int regmap_i2c_gather_write(void *context,
const void *reg, size_t reg_size,
const void *val, size_t val_size)
{
+ struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev);
struct i2c_msg xfer[2];
int ret;
@@ -62,10 +64,11 @@ static int regmap_i2c_gather_write(struct device *dev,
return -EIO;
}
-static int regmap_i2c_read(struct device *dev,
+static int regmap_i2c_read(void *context,
const void *reg, size_t reg_size,
void *val, size_t val_size)
{
+ struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev);
struct i2c_msg xfer[2];
int ret;
@@ -107,7 +110,7 @@ static struct regmap_bus regmap_i2c = {
struct regmap *regmap_init_i2c(struct i2c_client *i2c,
const struct regmap_config *config)
{
- return regmap_init(&i2c->dev, &regmap_i2c, config);
+ return regmap_init(&i2c->dev, &regmap_i2c, &i2c->dev, config);
}
EXPORT_SYMBOL_GPL(regmap_init_i2c);
@@ -124,7 +127,7 @@ EXPORT_SYMBOL_GPL(regmap_init_i2c);
struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c,
const struct regmap_config *config)
{
- return devm_regmap_init(&i2c->dev, &regmap_i2c, config);
+ return devm_regmap_init(&i2c->dev, &regmap_i2c, &i2c->dev, config);
}
EXPORT_SYMBOL_GPL(devm_regmap_init_i2c);
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 1befaa7a31cb..4fac4b9be88f 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -15,6 +15,7 @@
#include <linux/regmap.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
#include <linux/slab.h>
#include "internal.h"
@@ -26,18 +27,20 @@ struct regmap_irq_chip_data {
struct regmap_irq_chip *chip;
int irq_base;
+ struct irq_domain *domain;
- void *status_reg_buf;
unsigned int *status_buf;
unsigned int *mask_buf;
unsigned int *mask_buf_def;
+
+ unsigned int irq_reg_stride;
};
static inline const
struct regmap_irq *irq_to_regmap_irq(struct regmap_irq_chip_data *data,
int irq)
{
- return &data->chip->irqs[irq - data->irq_base];
+ return &data->chip->irqs[irq];
}
static void regmap_irq_lock(struct irq_data *data)
@@ -50,6 +53,7 @@ static void regmap_irq_lock(struct irq_data *data)
static void regmap_irq_sync_unlock(struct irq_data *data)
{
struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
+ struct regmap *map = d->map;
int i, ret;
/*
@@ -58,11 +62,13 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
* suppress pointless writes.
*/
for (i = 0; i < d->chip->num_regs; i++) {
- ret = regmap_update_bits(d->map, d->chip->mask_base + i,
+ ret = regmap_update_bits(d->map, d->chip->mask_base +
+ (i * map->reg_stride *
+ d->irq_reg_stride),
d->mask_buf_def[i], d->mask_buf[i]);
if (ret != 0)
dev_err(d->map->dev, "Failed to sync masks in %x\n",
- d->chip->mask_base + i);
+ d->chip->mask_base + (i * map->reg_stride));
}
mutex_unlock(&d->lock);
@@ -71,17 +77,19 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
static void regmap_irq_enable(struct irq_data *data)
{
struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
- const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->irq);
+ struct regmap *map = d->map;
+ const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq);
- d->mask_buf[irq_data->reg_offset] &= ~irq_data->mask;
+ d->mask_buf[irq_data->reg_offset / map->reg_stride] &= ~irq_data->mask;
}
static void regmap_irq_disable(struct irq_data *data)
{
struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
- const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->irq);
+ struct regmap *map = d->map;
+ const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq);
- d->mask_buf[irq_data->reg_offset] |= irq_data->mask;
+ d->mask_buf[irq_data->reg_offset / map->reg_stride] |= irq_data->mask;
}
static struct irq_chip regmap_irq_chip = {
@@ -98,18 +106,8 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
struct regmap_irq_chip *chip = data->chip;
struct regmap *map = data->map;
int ret, i;
- u8 *buf8 = data->status_reg_buf;
- u16 *buf16 = data->status_reg_buf;
- u32 *buf32 = data->status_reg_buf;
bool handled = false;
- ret = regmap_bulk_read(map, chip->status_base, data->status_reg_buf,
- chip->num_regs);
- if (ret != 0) {
- dev_err(map->dev, "Failed to read IRQ status: %d\n", ret);
- return IRQ_NONE;
- }
-
/*
* Ignore masked IRQs and ack if we need to; we ack early so
* there is no race between handling and acknowleding the
@@ -118,36 +116,34 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
* doing a write per register.
*/
for (i = 0; i < data->chip->num_regs; i++) {
- switch (map->format.val_bytes) {
- case 1:
- data->status_buf[i] = buf8[i];
- break;
- case 2:
- data->status_buf[i] = buf16[i];
- break;
- case 4:
- data->status_buf[i] = buf32[i];
- break;
- default:
- BUG();
+ ret = regmap_read(map, chip->status_base + (i * map->reg_stride
+ * data->irq_reg_stride),
+ &data->status_buf[i]);
+
+ if (ret != 0) {
+ dev_err(map->dev, "Failed to read IRQ status: %d\n",
+ ret);
return IRQ_NONE;
}
data->status_buf[i] &= ~data->mask_buf[i];
if (data->status_buf[i] && chip->ack_base) {
- ret = regmap_write(map, chip->ack_base + i,
+ ret = regmap_write(map, chip->ack_base +
+ (i * map->reg_stride *
+ data->irq_reg_stride),
data->status_buf[i]);
if (ret != 0)
dev_err(map->dev, "Failed to ack 0x%x: %d\n",
- chip->ack_base + i, ret);
+ chip->ack_base + (i * map->reg_stride),
+ ret);
}
}
for (i = 0; i < chip->num_irqs; i++) {
- if (data->status_buf[chip->irqs[i].reg_offset] &
- chip->irqs[i].mask) {
- handle_nested_irq(data->irq_base + i);
+ if (data->status_buf[chip->irqs[i].reg_offset /
+ map->reg_stride] & chip->irqs[i].mask) {
+ handle_nested_irq(irq_find_mapping(data->domain, i));
handled = true;
}
}
@@ -158,6 +154,31 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
return IRQ_NONE;
}
+static int regmap_irq_map(struct irq_domain *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct regmap_irq_chip_data *data = h->host_data;
+
+ irq_set_chip_data(virq, data);
+ irq_set_chip_and_handler(virq, &regmap_irq_chip, handle_edge_irq);
+ irq_set_nested_thread(virq, 1);
+
+ /* ARM needs us to explicitly flag the IRQ as valid
+ * and will set them noprobe when we do so. */
+#ifdef CONFIG_ARM
+ set_irq_flags(virq, IRQF_VALID);
+#else
+ irq_set_noprobe(virq);
+#endif
+
+ return 0;
+}
+
+static struct irq_domain_ops regmap_domain_ops = {
+ .map = regmap_irq_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
/**
* regmap_add_irq_chip(): Use standard regmap IRQ controller handling
*
@@ -178,30 +199,37 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
struct regmap_irq_chip_data **data)
{
struct regmap_irq_chip_data *d;
- int cur_irq, i;
+ int i;
int ret = -ENOMEM;
- irq_base = irq_alloc_descs(irq_base, 0, chip->num_irqs, 0);
- if (irq_base < 0) {
- dev_warn(map->dev, "Failed to allocate IRQs: %d\n",
- irq_base);
- return irq_base;
+ for (i = 0; i < chip->num_irqs; i++) {
+ if (chip->irqs[i].reg_offset % map->reg_stride)
+ return -EINVAL;
+ if (chip->irqs[i].reg_offset / map->reg_stride >=
+ chip->num_regs)
+ return -EINVAL;
+ }
+
+ if (irq_base) {
+ irq_base = irq_alloc_descs(irq_base, 0, chip->num_irqs, 0);
+ if (irq_base < 0) {
+ dev_warn(map->dev, "Failed to allocate IRQs: %d\n",
+ irq_base);
+ return irq_base;
+ }
}
d = kzalloc(sizeof(*d), GFP_KERNEL);
if (!d)
return -ENOMEM;
+ *data = d;
+
d->status_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
GFP_KERNEL);
if (!d->status_buf)
goto err_alloc;
- d->status_reg_buf = kzalloc(map->format.val_bytes * chip->num_regs,
- GFP_KERNEL);
- if (!d->status_reg_buf)
- goto err_alloc;
-
d->mask_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
GFP_KERNEL);
if (!d->mask_buf)
@@ -215,54 +243,59 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
d->map = map;
d->chip = chip;
d->irq_base = irq_base;
+
+ if (chip->irq_reg_stride)
+ d->irq_reg_stride = chip->irq_reg_stride;
+ else
+ d->irq_reg_stride = 1;
+
mutex_init(&d->lock);
for (i = 0; i < chip->num_irqs; i++)
- d->mask_buf_def[chip->irqs[i].reg_offset]
+ d->mask_buf_def[chip->irqs[i].reg_offset / map->reg_stride]
|= chip->irqs[i].mask;
/* Mask all the interrupts by default */
for (i = 0; i < chip->num_regs; i++) {
d->mask_buf[i] = d->mask_buf_def[i];
- ret = regmap_write(map, chip->mask_base + i, d->mask_buf[i]);
+ ret = regmap_write(map, chip->mask_base + (i * map->reg_stride
+ * d->irq_reg_stride),
+ d->mask_buf[i]);
if (ret != 0) {
dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
- chip->mask_base + i, ret);
+ chip->mask_base + (i * map->reg_stride), ret);
goto err_alloc;
}
}
- /* Register them with genirq */
- for (cur_irq = irq_base;
- cur_irq < chip->num_irqs + irq_base;
- cur_irq++) {
- irq_set_chip_data(cur_irq, d);
- irq_set_chip_and_handler(cur_irq, &regmap_irq_chip,
- handle_edge_irq);
- irq_set_nested_thread(cur_irq, 1);
-
- /* ARM needs us to explicitly flag the IRQ as valid
- * and will set them noprobe when we do so. */
-#ifdef CONFIG_ARM
- set_irq_flags(cur_irq, IRQF_VALID);
-#else
- irq_set_noprobe(cur_irq);
-#endif
+ if (irq_base)
+ d->domain = irq_domain_add_legacy(map->dev->of_node,
+ chip->num_irqs, irq_base, 0,
+ &regmap_domain_ops, d);
+ else
+ d->domain = irq_domain_add_linear(map->dev->of_node,
+ chip->num_irqs,
+ &regmap_domain_ops, d);
+ if (!d->domain) {
+ dev_err(map->dev, "Failed to create IRQ domain\n");
+ ret = -ENOMEM;
+ goto err_alloc;
}
ret = request_threaded_irq(irq, NULL, regmap_irq_thread, irq_flags,
chip->name, d);
if (ret != 0) {
dev_err(map->dev, "Failed to request IRQ %d: %d\n", irq, ret);
- goto err_alloc;
+ goto err_domain;
}
return 0;
+err_domain:
+ /* Should really dispose of the domain but... */
err_alloc:
kfree(d->mask_buf_def);
kfree(d->mask_buf);
- kfree(d->status_reg_buf);
kfree(d->status_buf);
kfree(d);
return ret;
@@ -281,9 +314,9 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
return;
free_irq(irq, d);
+ /* We should unmap the domain but... */
kfree(d->mask_buf_def);
kfree(d->mask_buf);
- kfree(d->status_reg_buf);
kfree(d->status_buf);
kfree(d);
}
@@ -298,6 +331,21 @@ EXPORT_SYMBOL_GPL(regmap_del_irq_chip);
*/
int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data)
{
+ WARN_ON(!data->irq_base);
return data->irq_base;
}
EXPORT_SYMBOL_GPL(regmap_irq_chip_get_base);
+
+/**
+ * regmap_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
+ *
+ * Useful for drivers to request their own IRQs.
+ *
+ * @data: regmap_irq controller to operate on.
+ * @irq: index of the interrupt requested in the chip IRQs
+ */
+int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq)
+{
+ return irq_create_mapping(data->domain, irq);
+}
+EXPORT_SYMBOL_GPL(regmap_irq_get_virq);
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
new file mode 100644
index 000000000000..febd6de6c8ac
--- /dev/null
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -0,0 +1,224 @@
+/*
+ * Register map access API - MMIO support
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+struct regmap_mmio_context {
+ void __iomem *regs;
+ unsigned val_bytes;
+};
+
+static int regmap_mmio_gather_write(void *context,
+ const void *reg, size_t reg_size,
+ const void *val, size_t val_size)
+{
+ struct regmap_mmio_context *ctx = context;
+ u32 offset;
+
+ BUG_ON(reg_size != 4);
+
+ offset = be32_to_cpup(reg);
+
+ while (val_size) {
+ switch (ctx->val_bytes) {
+ case 1:
+ writeb(*(u8 *)val, ctx->regs + offset);
+ break;
+ case 2:
+ writew(be16_to_cpup(val), ctx->regs + offset);
+ break;
+ case 4:
+ writel(be32_to_cpup(val), ctx->regs + offset);
+ break;
+#ifdef CONFIG_64BIT
+ case 8:
+ writeq(be64_to_cpup(val), ctx->regs + offset);
+ break;
+#endif
+ default:
+ /* Should be caught by regmap_mmio_check_config */
+ BUG();
+ }
+ val_size -= ctx->val_bytes;
+ val += ctx->val_bytes;
+ offset += ctx->val_bytes;
+ }
+
+ return 0;
+}
+
+static int regmap_mmio_write(void *context, const void *data, size_t count)
+{
+ BUG_ON(count < 4);
+
+ return regmap_mmio_gather_write(context, data, 4, data + 4, count - 4);
+}
+
+static int regmap_mmio_read(void *context,
+ const void *reg, size_t reg_size,
+ void *val, size_t val_size)
+{
+ struct regmap_mmio_context *ctx = context;
+ u32 offset;
+
+ BUG_ON(reg_size != 4);
+
+ offset = be32_to_cpup(reg);
+
+ while (val_size) {
+ switch (ctx->val_bytes) {
+ case 1:
+ *(u8 *)val = readb(ctx->regs + offset);
+ break;
+ case 2:
+ *(u16 *)val = cpu_to_be16(readw(ctx->regs + offset));
+ break;
+ case 4:
+ *(u32 *)val = cpu_to_be32(readl(ctx->regs + offset));
+ break;
+#ifdef CONFIG_64BIT
+ case 8:
+ *(u64 *)val = cpu_to_be32(readq(ctx->regs + offset));
+ break;
+#endif
+ default:
+ /* Should be caught by regmap_mmio_check_config */
+ BUG();
+ }
+ val_size -= ctx->val_bytes;
+ val += ctx->val_bytes;
+ offset += ctx->val_bytes;
+ }
+
+ return 0;
+}
+
+static void regmap_mmio_free_context(void *context)
+{
+ kfree(context);
+}
+
+static struct regmap_bus regmap_mmio = {
+ .fast_io = true,
+ .write = regmap_mmio_write,
+ .gather_write = regmap_mmio_gather_write,
+ .read = regmap_mmio_read,
+ .free_context = regmap_mmio_free_context,
+};
+
+struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
+ const struct regmap_config *config)
+{
+ struct regmap_mmio_context *ctx;
+ int min_stride;
+
+ if (config->reg_bits != 32)
+ return ERR_PTR(-EINVAL);
+
+ if (config->pad_bits)
+ return ERR_PTR(-EINVAL);
+
+ switch (config->val_bits) {
+ case 8:
+ /* The core treats 0 as 1 */
+ min_stride = 0;
+ break;
+ case 16:
+ min_stride = 2;
+ break;
+ case 32:
+ min_stride = 4;
+ break;
+#ifdef CONFIG_64BIT
+ case 64:
+ min_stride = 8;
+ break;
+#endif
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (config->reg_stride < min_stride)
+ return ERR_PTR(-EINVAL);
+
+ ctx = kzalloc(GFP_KERNEL, sizeof(*ctx));
+ if (!ctx)
+ return ERR_PTR(-ENOMEM);
+
+ ctx->regs = regs;
+ ctx->val_bytes = config->val_bits / 8;
+
+ return ctx;
+}
+
+/**
+ * regmap_init_mmio(): Initialise register map
+ *
+ * @dev: Device that will be interacted with
+ * @regs: Pointer to memory-mapped IO region
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.
+ */
+struct regmap *regmap_init_mmio(struct device *dev,
+ void __iomem *regs,
+ const struct regmap_config *config)
+{
+ struct regmap_mmio_context *ctx;
+
+ ctx = regmap_mmio_gen_context(regs, config);
+ if (IS_ERR(ctx))
+ return ERR_CAST(ctx);
+
+ return regmap_init(dev, &regmap_mmio, ctx, config);
+}
+EXPORT_SYMBOL_GPL(regmap_init_mmio);
+
+/**
+ * devm_regmap_init_mmio(): Initialise managed register map
+ *
+ * @dev: Device that will be interacted with
+ * @regs: Pointer to memory-mapped IO region
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct regmap. The regmap will be automatically freed by the
+ * device management code.
+ */
+struct regmap *devm_regmap_init_mmio(struct device *dev,
+ void __iomem *regs,
+ const struct regmap_config *config)
+{
+ struct regmap_mmio_context *ctx;
+
+ ctx = regmap_mmio_gen_context(regs, config);
+ if (IS_ERR(ctx))
+ return ERR_CAST(ctx);
+
+ return devm_regmap_init(dev, &regmap_mmio, ctx, config);
+}
+EXPORT_SYMBOL_GPL(devm_regmap_init_mmio);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c
index 7c0c35a39c33..ffa46a92ad33 100644
--- a/drivers/base/regmap/regmap-spi.c
+++ b/drivers/base/regmap/regmap-spi.c
@@ -15,17 +15,19 @@
#include <linux/init.h>
#include <linux/module.h>
-static int regmap_spi_write(struct device *dev, const void *data, size_t count)
+static int regmap_spi_write(void *context, const void *data, size_t count)
{
+ struct device *dev = context;
struct spi_device *spi = to_spi_device(dev);
return spi_write(spi, data, count);
}
-static int regmap_spi_gather_write(struct device *dev,
+static int regmap_spi_gather_write(void *context,
const void *reg, size_t reg_len,
const void *val, size_t val_len)
{
+ struct device *dev = context;
struct spi_device *spi = to_spi_device(dev);
struct spi_message m;
struct spi_transfer t[2] = { { .tx_buf = reg, .len = reg_len, },
@@ -38,10 +40,11 @@ static int regmap_spi_gather_write(struct device *dev,
return spi_sync(spi, &m);
}
-static int regmap_spi_read(struct device *dev,
+static int regmap_spi_read(void *context,
const void *reg, size_t reg_size,
void *val, size_t val_size)
{
+ struct device *dev = context;
struct spi_device *spi = to_spi_device(dev);
return spi_write_then_read(spi, reg, reg_size, val, val_size);
@@ -66,7 +69,7 @@ static struct regmap_bus regmap_spi = {
struct regmap *regmap_init_spi(struct spi_device *spi,
const struct regmap_config *config)
{
- return regmap_init(&spi->dev, &regmap_spi, config);
+ return regmap_init(&spi->dev, &regmap_spi, &spi->dev, config);
}
EXPORT_SYMBOL_GPL(regmap_init_spi);
@@ -83,7 +86,7 @@ EXPORT_SYMBOL_GPL(regmap_init_spi);
struct regmap *devm_regmap_init_spi(struct spi_device *spi,
const struct regmap_config *config)
{
- return devm_regmap_init(&spi->dev, &regmap_spi, config);
+ return devm_regmap_init(&spi->dev, &regmap_spi, &spi->dev, config);
}
EXPORT_SYMBOL_GPL(devm_regmap_init_spi);
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index bb80853ff27a..0bcda488f11c 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -112,25 +112,36 @@ static void regmap_format_10_14_write(struct regmap *map,
out[0] = reg >> 2;
}
-static void regmap_format_8(void *buf, unsigned int val)
+static void regmap_format_8(void *buf, unsigned int val, unsigned int shift)
{
u8 *b = buf;
- b[0] = val;
+ b[0] = val << shift;
}
-static void regmap_format_16(void *buf, unsigned int val)
+static void regmap_format_16(void *buf, unsigned int val, unsigned int shift)
{
__be16 *b = buf;
- b[0] = cpu_to_be16(val);
+ b[0] = cpu_to_be16(val << shift);
}
-static void regmap_format_32(void *buf, unsigned int val)
+static void regmap_format_24(void *buf, unsigned int val, unsigned int shift)
+{
+ u8 *b = buf;
+
+ val <<= shift;
+
+ b[0] = val >> 16;
+ b[1] = val >> 8;
+ b[2] = val;
+}
+
+static void regmap_format_32(void *buf, unsigned int val, unsigned int shift)
{
__be32 *b = buf;
- b[0] = cpu_to_be32(val);
+ b[0] = cpu_to_be32(val << shift);
}
static unsigned int regmap_parse_8(void *buf)
@@ -149,6 +160,16 @@ static unsigned int regmap_parse_16(void *buf)
return b[0];
}
+static unsigned int regmap_parse_24(void *buf)
+{
+ u8 *b = buf;
+ unsigned int ret = b[2];
+ ret |= ((unsigned int)b[1]) << 8;
+ ret |= ((unsigned int)b[0]) << 16;
+
+ return ret;
+}
+
static unsigned int regmap_parse_32(void *buf)
{
__be32 *b = buf;
@@ -158,11 +179,41 @@ static unsigned int regmap_parse_32(void *buf)
return b[0];
}
+static void regmap_lock_mutex(struct regmap *map)
+{
+ mutex_lock(&map->mutex);
+}
+
+static void regmap_unlock_mutex(struct regmap *map)
+{
+ mutex_unlock(&map->mutex);
+}
+
+static void regmap_lock_spinlock(struct regmap *map)
+{
+ spin_lock(&map->spinlock);
+}
+
+static void regmap_unlock_spinlock(struct regmap *map)
+{
+ spin_unlock(&map->spinlock);
+}
+
+static void dev_get_regmap_release(struct device *dev, void *res)
+{
+ /*
+ * We don't actually have anything to do here; the goal here
+ * is not to manage the regmap but to provide a simple way to
+ * get the regmap back given a struct device.
+ */
+}
+
/**
* regmap_init(): Initialise register map
*
* @dev: Device that will be interacted with
* @bus: Bus-specific callbacks to use with device
+ * @bus_context: Data passed to bus-specific callbacks
* @config: Configuration for register map
*
* The return value will be an ERR_PTR() on error or a valid pointer to
@@ -171,9 +222,10 @@ static unsigned int regmap_parse_32(void *buf)
*/
struct regmap *regmap_init(struct device *dev,
const struct regmap_bus *bus,
+ void *bus_context,
const struct regmap_config *config)
{
- struct regmap *map;
+ struct regmap *map, **m;
int ret = -EINVAL;
if (!bus || !config)
@@ -185,20 +237,36 @@ struct regmap *regmap_init(struct device *dev,
goto err;
}
- mutex_init(&map->lock);
+ if (bus->fast_io) {
+ spin_lock_init(&map->spinlock);
+ map->lock = regmap_lock_spinlock;
+ map->unlock = regmap_unlock_spinlock;
+ } else {
+ mutex_init(&map->mutex);
+ map->lock = regmap_lock_mutex;
+ map->unlock = regmap_unlock_mutex;
+ }
map->format.buf_size = (config->reg_bits + config->val_bits) / 8;
map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
map->format.pad_bytes = config->pad_bits / 8;
map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);
map->format.buf_size += map->format.pad_bytes;
+ map->reg_shift = config->pad_bits % 8;
+ if (config->reg_stride)
+ map->reg_stride = config->reg_stride;
+ else
+ map->reg_stride = 1;
+ map->use_single_rw = config->use_single_rw;
map->dev = dev;
map->bus = bus;
+ map->bus_context = bus_context;
map->max_register = config->max_register;
map->writeable_reg = config->writeable_reg;
map->readable_reg = config->readable_reg;
map->volatile_reg = config->volatile_reg;
map->precious_reg = config->precious_reg;
map->cache_type = config->cache_type;
+ map->name = config->name;
if (config->read_flag_mask || config->write_flag_mask) {
map->read_flag_mask = config->read_flag_mask;
@@ -207,7 +275,7 @@ struct regmap *regmap_init(struct device *dev,
map->read_flag_mask = bus->read_flag_mask;
}
- switch (config->reg_bits) {
+ switch (config->reg_bits + map->reg_shift) {
case 2:
switch (config->val_bits) {
case 6:
@@ -273,12 +341,19 @@ struct regmap *regmap_init(struct device *dev,
map->format.format_val = regmap_format_16;
map->format.parse_val = regmap_parse_16;
break;
+ case 24:
+ map->format.format_val = regmap_format_24;
+ map->format.parse_val = regmap_parse_24;
+ break;
case 32:
map->format.format_val = regmap_format_32;
map->format.parse_val = regmap_parse_32;
break;
}
+ if (map->format.format_write)
+ map->use_single_rw = true;
+
if (!map->format.format_write &&
!(map->format.format_reg && map->format.format_val))
goto err_map;
@@ -289,14 +364,25 @@ struct regmap *regmap_init(struct device *dev,
goto err_map;
}
- regmap_debugfs_init(map);
+ regmap_debugfs_init(map, config->name);
ret = regcache_init(map, config);
if (ret < 0)
goto err_free_workbuf;
+ /* Add a devres resource for dev_get_regmap() */
+ m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL);
+ if (!m) {
+ ret = -ENOMEM;
+ goto err_cache;
+ }
+ *m = map;
+ devres_add(dev, m);
+
return map;
+err_cache:
+ regcache_exit(map);
err_free_workbuf:
kfree(map->work_buf);
err_map:
@@ -316,6 +402,7 @@ static void devm_regmap_release(struct device *dev, void *res)
*
* @dev: Device that will be interacted with
* @bus: Bus-specific callbacks to use with device
+ * @bus_context: Data passed to bus-specific callbacks
* @config: Configuration for register map
*
* The return value will be an ERR_PTR() on error or a valid pointer
@@ -325,6 +412,7 @@ static void devm_regmap_release(struct device *dev, void *res)
*/
struct regmap *devm_regmap_init(struct device *dev,
const struct regmap_bus *bus,
+ void *bus_context,
const struct regmap_config *config)
{
struct regmap **ptr, *regmap;
@@ -333,7 +421,7 @@ struct regmap *devm_regmap_init(struct device *dev,
if (!ptr)
return ERR_PTR(-ENOMEM);
- regmap = regmap_init(dev, bus, config);
+ regmap = regmap_init(dev, bus, bus_context, config);
if (!IS_ERR(regmap)) {
*ptr = regmap;
devres_add(dev, ptr);
@@ -360,7 +448,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
{
int ret;
- mutex_lock(&map->lock);
+ map->lock(map);
regcache_exit(map);
regmap_debugfs_exit(map);
@@ -372,14 +460,14 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
map->precious_reg = config->precious_reg;
map->cache_type = config->cache_type;
- regmap_debugfs_init(map);
+ regmap_debugfs_init(map, config->name);
map->cache_bypass = false;
map->cache_only = false;
ret = regcache_init(map, config);
- mutex_unlock(&map->lock);
+ map->unlock(map);
return ret;
}
@@ -391,11 +479,51 @@ void regmap_exit(struct regmap *map)
{
regcache_exit(map);
regmap_debugfs_exit(map);
+ if (map->bus->free_context)
+ map->bus->free_context(map->bus_context);
kfree(map->work_buf);
kfree(map);
}
EXPORT_SYMBOL_GPL(regmap_exit);
+static int dev_get_regmap_match(struct device *dev, void *res, void *data)
+{
+ struct regmap **r = res;
+ if (!r || !*r) {
+ WARN_ON(!r || !*r);
+ return 0;
+ }
+
+ /* If the user didn't specify a name match any */
+ if (data)
+ return (*r)->name == data;
+ else
+ return 1;
+}
+
+/**
+ * dev_get_regmap(): Obtain the regmap (if any) for a device
+ *
+ * @dev: Device to retrieve the map for
+ * @name: Optional name for the register map, usually NULL.
+ *
+ * Returns the regmap for the device if one is present, or NULL. If
+ * name is specified then it must match the name specified when
+ * registering the device, if it is NULL then the first regmap found
+ * will be used. Devices with multiple register maps are very rare,
+ * generic code should normally not need to specify a name.
+ */
+struct regmap *dev_get_regmap(struct device *dev, const char *name)
+{
+ struct regmap **r = devres_find(dev, dev_get_regmap_release,
+ dev_get_regmap_match, (void *)name);
+
+ if (!r)
+ return NULL;
+ return *r;
+}
+EXPORT_SYMBOL_GPL(dev_get_regmap);
+
static int _regmap_raw_write(struct regmap *map, unsigned int reg,
const void *val, size_t val_len)
{
@@ -408,7 +536,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
/* Check for unwritable registers before we start */
if (map->writeable_reg)
for (i = 0; i < val_len / map->format.val_bytes; i++)
- if (!map->writeable_reg(map->dev, reg + i))
+ if (!map->writeable_reg(map->dev,
+ reg + (i * map->reg_stride)))
return -EINVAL;
if (!map->cache_bypass && map->format.parse_val) {
@@ -417,7 +546,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
for (i = 0; i < val_len / val_bytes; i++) {
memcpy(map->work_buf, val + (i * val_bytes), val_bytes);
ival = map->format.parse_val(map->work_buf);
- ret = regcache_write(map, reg + i, ival);
+ ret = regcache_write(map, reg + (i * map->reg_stride),
+ ival);
if (ret) {
dev_err(map->dev,
"Error in caching of register: %u ret: %d\n",
@@ -431,7 +561,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
}
}
- map->format.format_reg(map->work_buf, reg);
+ map->format.format_reg(map->work_buf, reg, map->reg_shift);
u8[0] |= map->write_flag_mask;
@@ -444,12 +574,12 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
*/
if (val == (map->work_buf + map->format.pad_bytes +
map->format.reg_bytes))
- ret = map->bus->write(map->dev, map->work_buf,
+ ret = map->bus->write(map->bus_context, map->work_buf,
map->format.reg_bytes +
map->format.pad_bytes +
val_len);
else if (map->bus->gather_write)
- ret = map->bus->gather_write(map->dev, map->work_buf,
+ ret = map->bus->gather_write(map->bus_context, map->work_buf,
map->format.reg_bytes +
map->format.pad_bytes,
val, val_len);
@@ -464,7 +594,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
memcpy(buf, map->work_buf, map->format.reg_bytes);
memcpy(buf + map->format.reg_bytes + map->format.pad_bytes,
val, val_len);
- ret = map->bus->write(map->dev, buf, len);
+ ret = map->bus->write(map->bus_context, buf, len);
kfree(buf);
}
@@ -498,7 +628,7 @@ int _regmap_write(struct regmap *map, unsigned int reg,
trace_regmap_hw_write_start(map->dev, reg, 1);
- ret = map->bus->write(map->dev, map->work_buf,
+ ret = map->bus->write(map->bus_context, map->work_buf,
map->format.buf_size);
trace_regmap_hw_write_done(map->dev, reg, 1);
@@ -506,7 +636,7 @@ int _regmap_write(struct regmap *map, unsigned int reg,
return ret;
} else {
map->format.format_val(map->work_buf + map->format.reg_bytes
- + map->format.pad_bytes, val);
+ + map->format.pad_bytes, val, 0);
return _regmap_raw_write(map, reg,
map->work_buf +
map->format.reg_bytes +
@@ -529,11 +659,14 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
{
int ret;
- mutex_lock(&map->lock);
+ if (reg % map->reg_stride)
+ return -EINVAL;
+
+ map->lock(map);
ret = _regmap_write(map, reg, val);
- mutex_unlock(&map->lock);
+ map->unlock(map);
return ret;
}
@@ -560,11 +693,16 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
{
int ret;
- mutex_lock(&map->lock);
+ if (val_len % map->format.val_bytes)
+ return -EINVAL;
+ if (reg % map->reg_stride)
+ return -EINVAL;
+
+ map->lock(map);
ret = _regmap_raw_write(map, reg, val, val_len);
- mutex_unlock(&map->lock);
+ map->unlock(map);
return ret;
}
@@ -593,8 +731,10 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
if (!map->format.parse_val)
return -EINVAL;
+ if (reg % map->reg_stride)
+ return -EINVAL;
- mutex_lock(&map->lock);
+ map->lock(map);
/* No formatting is require if val_byte is 1 */
if (val_bytes == 1) {
@@ -609,13 +749,28 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
for (i = 0; i < val_count * val_bytes; i += val_bytes)
map->format.parse_val(wval + i);
}
- ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count);
+ /*
+ * Some devices does not support bulk write, for
+ * them we have a series of single write operations.
+ */
+ if (map->use_single_rw) {
+ for (i = 0; i < val_count; i++) {
+ ret = regmap_raw_write(map,
+ reg + (i * map->reg_stride),
+ val + (i * val_bytes),
+ val_bytes);
+ if (ret != 0)
+ return ret;
+ }
+ } else {
+ ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count);
+ }
if (val_bytes != 1)
kfree(wval);
out:
- mutex_unlock(&map->lock);
+ map->unlock(map);
return ret;
}
EXPORT_SYMBOL_GPL(regmap_bulk_write);
@@ -626,7 +781,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
u8 *u8 = map->work_buf;
int ret;
- map->format.format_reg(map->work_buf, reg);
+ map->format.format_reg(map->work_buf, reg, map->reg_shift);
/*
* Some buses or devices flag reads by setting the high bits in the
@@ -639,7 +794,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
trace_regmap_hw_read_start(map->dev, reg,
val_len / map->format.val_bytes);
- ret = map->bus->read(map->dev, map->work_buf,
+ ret = map->bus->read(map->bus_context, map->work_buf,
map->format.reg_bytes + map->format.pad_bytes,
val, val_len);
@@ -672,6 +827,9 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
trace_regmap_reg_read(map->dev, reg, *val);
}
+ if (ret == 0 && !map->cache_bypass)
+ regcache_write(map, reg, *val);
+
return ret;
}
@@ -689,11 +847,14 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
{
int ret;
- mutex_lock(&map->lock);
+ if (reg % map->reg_stride)
+ return -EINVAL;
+
+ map->lock(map);
ret = _regmap_read(map, reg, val);
- mutex_unlock(&map->lock);
+ map->unlock(map);
return ret;
}
@@ -718,7 +879,12 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
unsigned int v;
int ret, i;
- mutex_lock(&map->lock);
+ if (val_len % map->format.val_bytes)
+ return -EINVAL;
+ if (reg % map->reg_stride)
+ return -EINVAL;
+
+ map->lock(map);
if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
map->cache_type == REGCACHE_NONE) {
@@ -730,16 +896,17 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
* cost as we expect to hit the cache.
*/
for (i = 0; i < val_count; i++) {
- ret = _regmap_read(map, reg + i, &v);
+ ret = _regmap_read(map, reg + (i * map->reg_stride),
+ &v);
if (ret != 0)
goto out;
- map->format.format_val(val + (i * val_bytes), v);
+ map->format.format_val(val + (i * val_bytes), v, 0);
}
}
out:
- mutex_unlock(&map->lock);
+ map->unlock(map);
return ret;
}
@@ -765,18 +932,37 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
if (!map->format.parse_val)
return -EINVAL;
+ if (reg % map->reg_stride)
+ return -EINVAL;
if (vol || map->cache_type == REGCACHE_NONE) {
- ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
- if (ret != 0)
- return ret;
+ /*
+ * Some devices does not support bulk read, for
+ * them we have a series of single read operations.
+ */
+ if (map->use_single_rw) {
+ for (i = 0; i < val_count; i++) {
+ ret = regmap_raw_read(map,
+ reg + (i * map->reg_stride),
+ val + (i * val_bytes),
+ val_bytes);
+ if (ret != 0)
+ return ret;
+ }
+ } else {
+ ret = regmap_raw_read(map, reg, val,
+ val_bytes * val_count);
+ if (ret != 0)
+ return ret;
+ }
for (i = 0; i < val_count * val_bytes; i += val_bytes)
map->format.parse_val(val + i);
} else {
for (i = 0; i < val_count; i++) {
unsigned int ival;
- ret = regmap_read(map, reg + i, &ival);
+ ret = regmap_read(map, reg + (i * map->reg_stride),
+ &ival);
if (ret != 0)
return ret;
memcpy(val + (i * val_bytes), &ival, val_bytes);
@@ -794,7 +980,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
int ret;
unsigned int tmp, orig;
- mutex_lock(&map->lock);
+ map->lock(map);
ret = _regmap_read(map, reg, &orig);
if (ret != 0)
@@ -811,7 +997,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
}
out:
- mutex_unlock(&map->lock);
+ map->unlock(map);
return ret;
}
@@ -878,7 +1064,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
if (map->patch)
return -EBUSY;
- mutex_lock(&map->lock);
+ map->lock(map);
bypass = map->cache_bypass;
@@ -906,7 +1092,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
out:
map->cache_bypass = bypass;
- mutex_unlock(&map->lock);
+ map->unlock(map);
return ret;
}
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index f94cccccfa56..3bea7fe25b20 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -297,6 +297,23 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
return -EILSEQ;
}
+ /* First Slave Address Descriptor should be port 0:
+ * the main register space for the core
+ */
+ tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0);
+ if (tmp <= 0) {
+ /* Try again to see if it is a bridge */
+ tmp = bcma_erom_get_addr_desc(bus, eromptr,
+ SCAN_ADDR_TYPE_BRIDGE, 0);
+ if (tmp <= 0) {
+ return -EILSEQ;
+ } else {
+ pr_info("Bridge found\n");
+ return -ENXIO;
+ }
+ }
+ core->addr = tmp;
+
/* get & parse slave ports */
for (i = 0; i < ports[1]; i++) {
for (j = 0; ; j++) {
@@ -309,7 +326,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
break;
} else {
if (i == 0 && j == 0)
- core->addr = tmp;
+ core->addr1 = tmp;
}
}
}
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 8db9089127c5..9a13e889837e 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -6580,24 +6580,21 @@ static const struct file_operations dac960_user_command_proc_fops = {
static void DAC960_CreateProcEntries(DAC960_Controller_T *Controller)
{
- struct proc_dir_entry *StatusProcEntry;
struct proc_dir_entry *ControllerProcEntry;
- struct proc_dir_entry *UserCommandProcEntry;
if (DAC960_ProcDirectoryEntry == NULL) {
- DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL);
- StatusProcEntry = proc_create("status", 0,
- DAC960_ProcDirectoryEntry,
- &dac960_proc_fops);
+ DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL);
+ proc_create("status", 0, DAC960_ProcDirectoryEntry,
+ &dac960_proc_fops);
}
- sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber);
- ControllerProcEntry = proc_mkdir(Controller->ControllerName,
- DAC960_ProcDirectoryEntry);
- proc_create_data("initial_status", 0, ControllerProcEntry, &dac960_initial_status_proc_fops, Controller);
- proc_create_data("current_status", 0, ControllerProcEntry, &dac960_current_status_proc_fops, Controller);
- UserCommandProcEntry = proc_create_data("user_command", S_IWUSR | S_IRUSR, ControllerProcEntry, &dac960_user_command_proc_fops, Controller);
- Controller->ControllerProcEntry = ControllerProcEntry;
+ sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber);
+ ControllerProcEntry = proc_mkdir(Controller->ControllerName,
+ DAC960_ProcDirectoryEntry);
+ proc_create_data("initial_status", 0, ControllerProcEntry, &dac960_initial_status_proc_fops, Controller);
+ proc_create_data("current_status", 0, ControllerProcEntry, &dac960_current_status_proc_fops, Controller);
+ proc_create_data("user_command", S_IWUSR | S_IRUSR, ControllerProcEntry, &dac960_user_command_proc_fops, Controller);
+ Controller->ControllerProcEntry = ControllerProcEntry;
}
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 00f9fc992090..304000c3d433 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -2510,8 +2510,10 @@ static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd,
up(&dd->port->cmd_slot);
return NULL;
}
- if (unlikely(*tag < 0))
+ if (unlikely(*tag < 0)) {
+ up(&dd->port->cmd_slot);
return NULL;
+ }
return dd->port->commands[*tag].sg;
}
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 0d39f2f4294a..693187df7601 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -29,9 +29,6 @@ struct virtio_blk
/* The disk structure for the kernel. */
struct gendisk *disk;
- /* Request tracking. */
- struct list_head reqs;
-
mempool_t *pool;
/* Process context for config space updates */
@@ -55,7 +52,6 @@ struct virtio_blk
struct virtblk_req
{
- struct list_head list;
struct request *req;
struct virtio_blk_outhdr out_hdr;
struct virtio_scsi_inhdr in_hdr;
@@ -99,7 +95,6 @@ static void blk_done(struct virtqueue *vq)
}
__blk_end_request_all(vbr->req, error);
- list_del(&vbr->list);
mempool_free(vbr, vblk->pool);
}
/* In case queue is stopped waiting for more buffers. */
@@ -184,7 +179,6 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
return false;
}
- list_add_tail(&vbr->list, &vblk->reqs);
return true;
}
@@ -437,7 +431,6 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
goto out_free_index;
}
- INIT_LIST_HEAD(&vblk->reqs);
spin_lock_init(&vblk->lock);
vblk->vdev = vdev;
vblk->sg_elems = sg_elems;
@@ -583,21 +576,29 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
{
struct virtio_blk *vblk = vdev->priv;
int index = vblk->index;
+ struct virtblk_req *vbr;
+ unsigned long flags;
/* Prevent config work handler from accessing the device. */
mutex_lock(&vblk->config_lock);
vblk->config_enable = false;
mutex_unlock(&vblk->config_lock);
- /* Nothing should be pending. */
- BUG_ON(!list_empty(&vblk->reqs));
-
/* Stop all the virtqueues. */
vdev->config->reset(vdev);
flush_work(&vblk->config_work);
del_gendisk(vblk->disk);
+
+ /* Abort requests dispatched to driver. */
+ spin_lock_irqsave(&vblk->lock, flags);
+ while ((vbr = virtqueue_detach_unused_buf(vblk->vq))) {
+ __blk_end_request_all(vbr->req, -EIO);
+ mempool_free(vbr, vblk->pool);
+ }
+ spin_unlock_irqrestore(&vblk->lock, flags);
+
blk_cleanup_queue(vblk->disk->queue);
put_disk(vblk->disk);
mempool_destroy(vblk->pool);
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 57fd867553d7..2812b152d6e9 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -439,6 +439,7 @@ static struct usb_driver ath3k_driver = {
.probe = ath3k_probe,
.disconnect = ath3k_disconnect,
.id_table = ath3k_table,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(ath3k_driver);
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
index 1e742a50e2cd..37ae175162f3 100644
--- a/drivers/bluetooth/bcm203x.c
+++ b/drivers/bluetooth/bcm203x.c
@@ -279,6 +279,7 @@ static struct usb_driver bcm203x_driver = {
.probe = bcm203x_probe,
.disconnect = bcm203x_disconnect,
.id_table = bcm203x_table,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(bcm203x_driver);
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index b8ac1c549a1c..32e825144fe9 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -749,6 +749,7 @@ static struct usb_driver bfusb_driver = {
.probe = bfusb_probe,
.disconnect = bfusb_disconnect,
.id_table = bfusb_table,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(bfusb_driver);
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index d894340a7601..609861a53c28 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -508,6 +508,7 @@ static struct usb_driver bpa10x_driver = {
.probe = bpa10x_probe,
.disconnect = bpa10x_disconnect,
.id_table = bpa10x_table,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(bpa10x_driver);
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 9217121362e1..461c68bc4dd7 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1218,6 +1218,7 @@ static struct usb_driver btusb_driver = {
#endif
.id_table = btusb_table,
.supports_autosuspend = 1,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(btusb_driver);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index ee946865d6cb..ea6f6325f9ba 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -585,14 +585,6 @@ config DEVPORT
source "drivers/s390/char/Kconfig"
-config RAMOOPS
- tristate "Log panic/oops to a RAM buffer"
- depends on HAS_IOMEM
- default n
- help
- This enables panic and oops messages to be logged to a circular
- buffer in RAM where it can be read back at some later point.
-
config MSM_SMD_PKT
bool "Enable device interface for some SMD packet ports"
default n
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 0dc5d7ce4864..d0b27a39f1d4 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -58,7 +58,6 @@ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
obj-$(CONFIG_TCG_TPM) += tpm/
obj-$(CONFIG_PS3_FLASH) += ps3flash.o
-obj-$(CONFIG_RAMOOPS) += ramoops.o
obj-$(CONFIG_JS_RTC) += js-rtc.o
js-rtc-y = rtc.o
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 0689bf6b0183..f45dad39a18b 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -62,8 +62,8 @@ config HW_RANDOM_AMD
config HW_RANDOM_ATMEL
tristate "Atmel Random Number Generator support"
- depends on HW_RANDOM && ARCH_AT91SAM9G45
- default HW_RANDOM
+ depends on HW_RANDOM && HAVE_CLK
+ default (HW_RANDOM && ARCH_AT91)
---help---
This driver provides kernel-side support for the Random Number
Generator hardware found on Atmel AT91 devices.
@@ -250,3 +250,16 @@ config UML_RANDOM
(check your distro, or download from
http://sourceforge.net/projects/gkernel/). rngd periodically reads
/dev/hwrng and injects the entropy into /dev/random.
+
+config HW_RANDOM_PSERIES
+ tristate "pSeries HW Random Number Generator support"
+ depends on HW_RANDOM && PPC64 && IBMVIO
+ default HW_RANDOM
+ ---help---
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on POWER7+ machines and above
+
+ To compile this driver as a module, choose M here: the
+ module will be called pseries-rng.
+
+ If unsure, say Y.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index b2ff5265a996..d901dfa30321 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
+obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index a07a5caa599c..1412565c01af 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -115,22 +115,12 @@ static int __devinit omap_rng_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -ENOENT;
- goto err_region;
- }
-
- if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
- ret = -EBUSY;
- goto err_region;
- }
-
- dev_set_drvdata(&pdev->dev, res);
- rng_base = ioremap(res->start, resource_size(res));
+ rng_base = devm_request_and_ioremap(&pdev->dev, res);
if (!rng_base) {
ret = -ENOMEM;
goto err_ioremap;
}
+ dev_set_drvdata(&pdev->dev, res);
ret = hwrng_register(&omap_rng_ops);
if (ret)
@@ -145,11 +135,8 @@ static int __devinit omap_rng_probe(struct platform_device *pdev)
return 0;
err_register:
- iounmap(rng_base);
rng_base = NULL;
err_ioremap:
- release_mem_region(res->start, resource_size(res));
-err_region:
if (cpu_is_omap24xx()) {
clk_disable(rng_ick);
clk_put(rng_ick);
@@ -159,20 +146,15 @@ err_region:
static int __exit omap_rng_remove(struct platform_device *pdev)
{
- struct resource *res = dev_get_drvdata(&pdev->dev);
-
hwrng_unregister(&omap_rng_ops);
omap_rng_write_reg(RNG_MASK_REG, 0x0);
- iounmap(rng_base);
-
if (cpu_is_omap24xx()) {
clk_disable(rng_ick);
clk_put(rng_ick);
}
- release_mem_region(res->start, resource_size(res));
rng_base = NULL;
return 0;
diff --git a/drivers/char/hw_random/pseries-rng.c b/drivers/char/hw_random/pseries-rng.c
new file mode 100644
index 000000000000..5f1197929f0c
--- /dev/null
+++ b/drivers/char/hw_random/pseries-rng.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2010 Michael Neuling IBM Corporation
+ *
+ * Driver for the pseries hardware RNG for POWER7+ and above
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/hw_random.h>
+#include <asm/vio.h>
+
+#define MODULE_NAME "pseries-rng"
+
+static int pseries_rng_data_read(struct hwrng *rng, u32 *data)
+{
+ if (plpar_hcall(H_RANDOM, (unsigned long *)data) != H_SUCCESS) {
+ printk(KERN_ERR "pseries rng hcall error\n");
+ return 0;
+ }
+ return 8;
+}
+
+/**
+ * pseries_rng_get_desired_dma - Return desired DMA allocate for CMO operations
+ *
+ * This is a required function for a driver to operate in a CMO environment
+ * but this device does not make use of DMA allocations, return 0.
+ *
+ * Return value:
+ * Number of bytes of IO data the driver will need to perform well -> 0
+ */
+static unsigned long pseries_rng_get_desired_dma(struct vio_dev *vdev)
+{
+ return 0;
+};
+
+static struct hwrng pseries_rng = {
+ .name = MODULE_NAME,
+ .data_read = pseries_rng_data_read,
+};
+
+static int __init pseries_rng_probe(struct vio_dev *dev,
+ const struct vio_device_id *id)
+{
+ return hwrng_register(&pseries_rng);
+}
+
+static int __exit pseries_rng_remove(struct vio_dev *dev)
+{
+ hwrng_unregister(&pseries_rng);
+ return 0;
+}
+
+static struct vio_device_id pseries_rng_driver_ids[] = {
+ { "ibm,random-v1", "ibm,random"},
+ { "", "" }
+};
+MODULE_DEVICE_TABLE(vio, pseries_rng_driver_ids);
+
+static struct vio_driver pseries_rng_driver = {
+ .name = MODULE_NAME,
+ .probe = pseries_rng_probe,
+ .remove = pseries_rng_remove,
+ .get_desired_dma = pseries_rng_get_desired_dma,
+ .id_table = pseries_rng_driver_ids
+};
+
+static int __init rng_init(void)
+{
+ printk(KERN_INFO "Registering IBM pSeries RNG driver\n");
+ return vio_register_driver(&pseries_rng_driver);
+}
+
+module_init(rng_init);
+
+static void __exit rng_exit(void)
+{
+ vio_unregister_driver(&pseries_rng_driver);
+}
+module_exit(rng_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Neuling <mikey@neuling.org>");
+MODULE_DESCRIPTION("H/W RNG driver for IBM pSeries processors");
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index d6e9d081c8b1..67c3371723cc 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -807,44 +807,6 @@ static const struct file_operations oldmem_fops = {
};
#endif
-static ssize_t kmsg_writev(struct kiocb *iocb, const struct iovec *iv,
- unsigned long count, loff_t pos)
-{
- char *line, *p;
- int i;
- ssize_t ret = -EFAULT;
- size_t len = iov_length(iv, count);
-
- line = kmalloc(len + 1, GFP_KERNEL);
- if (line == NULL)
- return -ENOMEM;
-
- /*
- * copy all vectors into a single string, to ensure we do
- * not interleave our log line with other printk calls
- */
- p = line;
- for (i = 0; i < count; i++) {
- if (copy_from_user(p, iv[i].iov_base, iv[i].iov_len))
- goto out;
- p += iv[i].iov_len;
- }
- p[0] = '\0';
-
- ret = printk("%s", line);
- /* printk can add a prefix */
- if (ret > len)
- ret = len;
-out:
- kfree(line);
- return ret;
-}
-
-static const struct file_operations kmsg_fops = {
- .aio_write = kmsg_writev,
- .llseek = noop_llseek,
-};
-
static const struct memdev {
const char *name;
umode_t mode;
@@ -863,7 +825,9 @@ static const struct memdev {
[7] = { "full", 0666, &full_fops, NULL },
[8] = { "random", 0666, &random_fops, NULL },
[9] = { "urandom", 0666, &urandom_fops, NULL },
- [11] = { "kmsg", 0, &kmsg_fops, NULL },
+#ifdef CONFIG_PRINTK
+ [11] = { "kmsg", 0644, &kmsg_fops, NULL },
+#endif
#ifdef CONFIG_CRASH_DUMP
[12] = { "oldmem", 0, &oldmem_fops, NULL },
#endif
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c
deleted file mode 100644
index 2a5e45d2a9f8..000000000000
--- a/drivers/char/ramoops.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * RAM Oops/Panic logger
- *
- * Copyright (C) 2010 Marco Stornelli <marco.stornelli@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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/kmsg_dump.h>
-#include <linux/time.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/ramoops.h>
-
-#define RAMOOPS_KERNMSG_HDR "===="
-#define MIN_MEM_SIZE 4096UL
-
-static ulong record_size = MIN_MEM_SIZE;
-module_param(record_size, ulong, 0400);
-MODULE_PARM_DESC(record_size,
- "size of each dump done on oops/panic");
-
-static ulong mem_address;
-module_param(mem_address, ulong, 0400);
-MODULE_PARM_DESC(mem_address,
- "start of reserved RAM used to store oops/panic logs");
-
-static ulong mem_size;
-module_param(mem_size, ulong, 0400);
-MODULE_PARM_DESC(mem_size,
- "size of reserved RAM used to store oops/panic logs");
-
-static int dump_oops = 1;
-module_param(dump_oops, int, 0600);
-MODULE_PARM_DESC(dump_oops,
- "set to 1 to dump oopses, 0 to only dump panics (default 1)");
-
-static struct ramoops_context {
- struct kmsg_dumper dump;
- void *virt_addr;
- phys_addr_t phys_addr;
- unsigned long size;
- unsigned long record_size;
- int dump_oops;
- int count;
- int max_count;
-} oops_cxt;
-
-static struct platform_device *dummy;
-static struct ramoops_platform_data *dummy_data;
-
-static void ramoops_do_dump(struct kmsg_dumper *dumper,
- enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
- const char *s2, unsigned long l2)
-{
- struct ramoops_context *cxt = container_of(dumper,
- struct ramoops_context, dump);
- unsigned long s1_start, s2_start;
- unsigned long l1_cpy, l2_cpy;
- int res, hdr_size;
- char *buf, *buf_orig;
- struct timeval timestamp;
-
- if (reason != KMSG_DUMP_OOPS &&
- reason != KMSG_DUMP_PANIC)
- return;
-
- /* Only dump oopses if dump_oops is set */
- if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops)
- return;
-
- buf = cxt->virt_addr + (cxt->count * cxt->record_size);
- buf_orig = buf;
-
- memset(buf, '\0', cxt->record_size);
- res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
- buf += res;
- do_gettimeofday(&timestamp);
- res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec);
- buf += res;
-
- hdr_size = buf - buf_orig;
- l2_cpy = min(l2, cxt->record_size - hdr_size);
- l1_cpy = min(l1, cxt->record_size - hdr_size - l2_cpy);
-
- s2_start = l2 - l2_cpy;
- s1_start = l1 - l1_cpy;
-
- memcpy(buf, s1 + s1_start, l1_cpy);
- memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
-
- cxt->count = (cxt->count + 1) % cxt->max_count;
-}
-
-static int __init ramoops_probe(struct platform_device *pdev)
-{
- struct ramoops_platform_data *pdata = pdev->dev.platform_data;
- struct ramoops_context *cxt = &oops_cxt;
- int err = -EINVAL;
-
- if (!pdata->mem_size || !pdata->record_size) {
- pr_err("The memory size and the record size must be "
- "non-zero\n");
- goto fail3;
- }
-
- pdata->mem_size = rounddown_pow_of_two(pdata->mem_size);
- pdata->record_size = rounddown_pow_of_two(pdata->record_size);
-
- /* Check for the minimum memory size */
- if (pdata->mem_size < MIN_MEM_SIZE &&
- pdata->record_size < MIN_MEM_SIZE) {
- pr_err("memory size too small, minium is %lu\n", MIN_MEM_SIZE);
- goto fail3;
- }
-
- if (pdata->mem_size < pdata->record_size) {
- pr_err("The memory size must be larger than the "
- "records size\n");
- goto fail3;
- }
-
- cxt->max_count = pdata->mem_size / pdata->record_size;
- cxt->count = 0;
- cxt->size = pdata->mem_size;
- cxt->phys_addr = pdata->mem_address;
- cxt->record_size = pdata->record_size;
- cxt->dump_oops = pdata->dump_oops;
-
- if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) {
- pr_err("request mem region failed\n");
- err = -EINVAL;
- goto fail3;
- }
-
- cxt->virt_addr = ioremap(cxt->phys_addr, cxt->size);
- if (!cxt->virt_addr) {
- pr_err("ioremap failed\n");
- goto fail2;
- }
-
- cxt->dump.dump = ramoops_do_dump;
- err = kmsg_dump_register(&cxt->dump);
- if (err) {
- pr_err("registering kmsg dumper failed\n");
- goto fail1;
- }
-
- /*
- * Update the module parameter variables as well so they are visible
- * through /sys/module/ramoops/parameters/
- */
- mem_size = pdata->mem_size;
- mem_address = pdata->mem_address;
- record_size = pdata->record_size;
- dump_oops = pdata->dump_oops;
-
- return 0;
-
-fail1:
- iounmap(cxt->virt_addr);
-fail2:
- release_mem_region(cxt->phys_addr, cxt->size);
-fail3:
- return err;
-}
-
-static int __exit ramoops_remove(struct platform_device *pdev)
-{
- struct ramoops_context *cxt = &oops_cxt;
-
- if (kmsg_dump_unregister(&cxt->dump) < 0)
- pr_warn("could not unregister kmsg_dumper\n");
-
- iounmap(cxt->virt_addr);
- release_mem_region(cxt->phys_addr, cxt->size);
- return 0;
-}
-
-static struct platform_driver ramoops_driver = {
- .remove = __exit_p(ramoops_remove),
- .driver = {
- .name = "ramoops",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init ramoops_init(void)
-{
- int ret;
- ret = platform_driver_probe(&ramoops_driver, ramoops_probe);
- if (ret == -ENODEV) {
- /*
- * If we didn't find a platform device, we use module parameters
- * building platform data on the fly.
- */
- pr_info("platform device not found, using module parameters\n");
- dummy_data = kzalloc(sizeof(struct ramoops_platform_data),
- GFP_KERNEL);
- if (!dummy_data)
- return -ENOMEM;
- dummy_data->mem_size = mem_size;
- dummy_data->mem_address = mem_address;
- dummy_data->record_size = record_size;
- dummy_data->dump_oops = dump_oops;
- dummy = platform_create_bundle(&ramoops_driver, ramoops_probe,
- NULL, 0, dummy_data,
- sizeof(struct ramoops_platform_data));
-
- if (IS_ERR(dummy))
- ret = PTR_ERR(dummy);
- else
- ret = 0;
- }
-
- return ret;
-}
-
-static void __exit ramoops_exit(void)
-{
- platform_driver_unregister(&ramoops_driver);
- kfree(dummy_data);
-}
-
-module_init(ramoops_init);
-module_exit(ramoops_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marco Stornelli <marco.stornelli@gmail.com>");
-MODULE_DESCRIPTION("RAM Oops/Panic logger/driver");
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index ddf86b6500b7..cdf2f5451c76 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1895,6 +1895,13 @@ static int virtcons_restore(struct virtio_device *vdev)
/* Get port open/close status on the host */
send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
+
+ /*
+ * If a port was open at the time of suspending, we
+ * have to let the host know that it's still open.
+ */
+ if (port->guest_connected)
+ send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 1);
}
return 0;
}
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 31ba11ca75e1..2c5d15beea35 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -167,6 +167,7 @@ static const struct config_registers v4_config_registers = {
.BOOTSTS = UNIMPLEMENTED,
.CTL_1 = UNIMPLEMENTED,
};
+
static const struct config_registers v5_config_registers = {
.CRC = 0,
.FAR = 1,
@@ -192,6 +193,31 @@ static const struct config_registers v5_config_registers = {
.CTL_1 = 19,
};
+static const struct config_registers v6_config_registers = {
+ .CRC = 0,
+ .FAR = 1,
+ .FDRI = 2,
+ .FDRO = 3,
+ .CMD = 4,
+ .CTL = 5,
+ .MASK = 6,
+ .STAT = 7,
+ .LOUT = 8,
+ .COR = 9,
+ .MFWR = 10,
+ .FLR = UNIMPLEMENTED,
+ .KEY = UNIMPLEMENTED,
+ .CBC = 11,
+ .IDCODE = 12,
+ .AXSS = 13,
+ .C0R_1 = 14,
+ .CSOB = 15,
+ .WBSTAR = 16,
+ .TIMER = 17,
+ .BOOTSTS = 22,
+ .CTL_1 = 24,
+};
+
/**
* hwicap_command_desync - Send a DESYNC command to the ICAP port.
* @drvdata: a pointer to the drvdata.
@@ -744,6 +770,8 @@ static int __devinit hwicap_of_probe(struct platform_device *op,
regs = &v4_config_registers;
} else if (!strcmp(family, "virtex5")) {
regs = &v5_config_registers;
+ } else if (!strcmp(family, "virtex6")) {
+ regs = &v6_config_registers;
}
}
return hwicap_setup(&op->dev, id ? *id : -1, &res, config,
@@ -785,6 +813,8 @@ static int __devinit hwicap_drv_probe(struct platform_device *pdev)
regs = &v4_config_registers;
} else if (!strcmp(family, "virtex5")) {
regs = &v5_config_registers;
+ } else if (!strcmp(family, "virtex6")) {
+ regs = &v6_config_registers;
}
}
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
index 8cca11981c5f..d31ee23c9f13 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
@@ -86,7 +86,7 @@ struct hwicap_driver_config {
};
/* Number of times to poll the done regsiter */
-#define XHI_MAX_RETRIES 10
+#define XHI_MAX_RETRIES 5000
/************ Constant Definitions *************/
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 6db161f64ae0..c535cf8c5770 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -35,7 +35,12 @@ static DEFINE_MUTEX(clocks_mutex);
static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
{
struct clk_lookup *p, *cl = NULL;
- int match, best = 0;
+ int match, best_found = 0, best_possible = 0;
+
+ if (dev_id)
+ best_possible += 2;
+ if (con_id)
+ best_possible += 1;
list_for_each_entry(p, &clocks, node) {
match = 0;
@@ -50,10 +55,10 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
match += 1;
}
- if (match > best) {
+ if (match > best_found) {
cl = p;
- if (match != 3)
- best = match;
+ if (match != best_possible)
+ best_found = match;
else
break;
}
@@ -89,6 +94,51 @@ void clk_put(struct clk *clk)
}
EXPORT_SYMBOL(clk_put);
+static void devm_clk_release(struct device *dev, void *res)
+{
+ clk_put(*(struct clk **)res);
+}
+
+struct clk *devm_clk_get(struct device *dev, const char *id)
+{
+ struct clk **ptr, *clk;
+
+ ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ clk = clk_get(dev, id);
+ if (!IS_ERR(clk)) {
+ *ptr = clk;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return clk;
+}
+EXPORT_SYMBOL(devm_clk_get);
+
+static int devm_clk_match(struct device *dev, void *res, void *data)
+{
+ struct clk **c = res;
+ if (!c || !*c) {
+ WARN_ON(!c || !*c);
+ return 0;
+ }
+ return *c == data;
+}
+
+void devm_clk_put(struct device *dev, struct clk *clk)
+{
+ int ret;
+
+ ret = devres_destroy(dev, devm_clk_release, devm_clk_match, clk);
+
+ WARN_ON(ret);
+}
+EXPORT_SYMBOL(devm_clk_put);
+
void clkdev_add(struct clk_lookup *cl)
{
mutex_lock(&clocks_mutex);
@@ -116,8 +166,9 @@ struct clk_lookup_alloc {
char con_id[MAX_CON_ID];
};
-struct clk_lookup * __init_refok
-clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
+static struct clk_lookup * __init_refok
+vclkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt,
+ va_list ap)
{
struct clk_lookup_alloc *cla;
@@ -132,16 +183,25 @@ clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
}
if (dev_fmt) {
- va_list ap;
-
- va_start(ap, dev_fmt);
vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
cla->cl.dev_id = cla->dev_id;
- va_end(ap);
}
return &cla->cl;
}
+
+struct clk_lookup * __init_refok
+clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
+{
+ struct clk_lookup *cl;
+ va_list ap;
+
+ va_start(ap, dev_fmt);
+ cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
+ va_end(ap);
+
+ return cl;
+}
EXPORT_SYMBOL(clkdev_alloc);
int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
@@ -173,3 +233,65 @@ void clkdev_drop(struct clk_lookup *cl)
kfree(cl);
}
EXPORT_SYMBOL(clkdev_drop);
+
+/**
+ * clk_register_clkdev - register one clock lookup for a struct clk
+ * @clk: struct clk to associate with all clk_lookups
+ * @con_id: connection ID string on device
+ * @dev_id: format string describing device name
+ *
+ * con_id or dev_id may be NULL as a wildcard, just as in the rest of
+ * clkdev.
+ *
+ * To make things easier for mass registration, we detect error clks
+ * from a previous clk_register() call, and return the error code for
+ * those. This is to permit this function to be called immediately
+ * after clk_register().
+ */
+int clk_register_clkdev(struct clk *clk, const char *con_id,
+ const char *dev_fmt, ...)
+{
+ struct clk_lookup *cl;
+ va_list ap;
+
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ va_start(ap, dev_fmt);
+ cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
+ va_end(ap);
+
+ if (!cl)
+ return -ENOMEM;
+
+ clkdev_add(cl);
+
+ return 0;
+}
+
+/**
+ * clk_register_clkdevs - register a set of clk_lookup for a struct clk
+ * @clk: struct clk to associate with all clk_lookups
+ * @cl: array of clk_lookup structures with con_id and dev_id pre-initialized
+ * @num: number of clk_lookup structures to register
+ *
+ * To make things easier for mass registration, we detect error clks
+ * from a previous clk_register() call, and return the error code for
+ * those. This is to permit this function to be called immediately
+ * after clk_register().
+ */
+int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num)
+{
+ unsigned i;
+
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ for (i = 0; i < num; i++, cl++) {
+ cl->clk = clk;
+ clkdev_add(cl);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_register_clkdevs);
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 5138927a416c..99c6b203e6cd 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -18,7 +18,7 @@ config DW_APB_TIMER
config CLKSRC_DBX500_PRCMU
bool "Clocksource PRCMU Timer"
- depends on UX500_SOC_DB5500 || UX500_SOC_DB8500
+ depends on UX500_SOC_DB8500
default y
help
Use the always on PRCMU Timer as clocksource
diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c
index 0bf1b8910eeb..74b830b635a6 100644
--- a/drivers/cpufreq/db8500-cpufreq.c
+++ b/drivers/cpufreq/db8500-cpufreq.c
@@ -161,7 +161,7 @@ static struct cpufreq_driver db8500_cpufreq_driver = {
static int __init db8500_cpufreq_register(void)
{
- if (!cpu_is_u8500v20_or_later())
+ if (!cpu_is_u8500_family())
return -ENODEV;
pr_info("cpufreq for DB8500 started\n");
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 2f0083a51a9a..d90519cec880 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -40,17 +40,6 @@ void disable_cpuidle(void)
off = 1;
}
-#if defined(CONFIG_ARCH_HAS_CPU_IDLE_WAIT)
-static void cpuidle_kick_cpus(void)
-{
- cpu_idle_wait();
-}
-#elif defined(CONFIG_SMP)
-# error "Arch needs cpu_idle_wait() equivalent here"
-#else /* !CONFIG_ARCH_HAS_CPU_IDLE_WAIT && !CONFIG_SMP */
-static void cpuidle_kick_cpus(void) {}
-#endif
-
static int __cpuidle_register_device(struct cpuidle_device *dev);
static inline int cpuidle_enter(struct cpuidle_device *dev,
@@ -186,7 +175,7 @@ void cpuidle_uninstall_idle_handler(void)
{
if (enabled_devices) {
initialized = 0;
- cpuidle_kick_cpus();
+ kick_all_cpus_sync();
}
}
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index ab9abb46d01a..1092a770482e 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -111,6 +111,7 @@ config CRYPTO_DES_S390
depends on S390
select CRYPTO_ALGAPI
select CRYPTO_BLKCIPHER
+ select CRYPTO_DES
help
This is the s390 hardware accelerated implementation of the
DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
@@ -164,6 +165,7 @@ config CRYPTO_DEV_MV_CESA
select CRYPTO_ALGAPI
select CRYPTO_AES
select CRYPTO_BLKCIPHER2
+ select CRYPTO_HASH
help
This driver allows you to utilize the Cryptographic Engines and
Security Accelerator (CESA) which can be found on the Marvell Orion
@@ -295,4 +297,32 @@ config CRYPTO_DEV_TEGRA_AES
To compile this driver as a module, choose M here: the module
will be called tegra-aes.
+config CRYPTO_DEV_NX
+ tristate "Support for Power7+ in-Nest cryptographic accleration"
+ depends on PPC64 && IBMVIO
+ select CRYPTO_AES
+ select CRYPTO_CBC
+ select CRYPTO_ECB
+ select CRYPTO_CCM
+ select CRYPTO_GCM
+ select CRYPTO_AUTHENC
+ select CRYPTO_XCBC
+ select CRYPTO_SHA256
+ select CRYPTO_SHA512
+ help
+ Support for Power7+ in-Nest cryptographic acceleration. This
+ module supports acceleration for AES and SHA2 algorithms. If you
+ choose 'M' here, this module will be called nx_crypto.
+
+config CRYPTO_DEV_UX500
+ tristate "Driver for ST-Ericsson UX500 crypto hardware acceleration"
+ depends on ARCH_U8500
+ select CRYPTO_ALGAPI
+ help
+ Driver for ST-Ericsson UX500 crypto engine.
+
+if CRYPTO_DEV_UX500
+ source "drivers/crypto/ux500/Kconfig"
+endif # if CRYPTO_DEV_UX500
+
endif # CRYPTO_HW
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index f3e64eadd7af..01390325d72d 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o
obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o
obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o
+obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/ \ No newline at end of file
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 13f8e1a14988..802e85102c32 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -1244,9 +1244,9 @@ err_start_dev:
iounmap(core_dev->dev->ce_base);
err_iomap:
free_irq(core_dev->irq, dev);
+err_request_irq:
irq_dispose_mapping(core_dev->irq);
tasklet_kill(&core_dev->tasklet);
-err_request_irq:
crypto4xx_destroy_sdr(core_dev->dev);
err_build_sdr:
crypto4xx_destroy_gdr(core_dev->dev);
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 534a36469d57..4eec389184d3 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -2267,8 +2267,11 @@ static void __exit caam_algapi_exit(void)
int i, err;
dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
- if (!dev_node)
- return;
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return;
+ }
pdev = of_find_device_by_node(dev_node);
if (!pdev)
@@ -2350,8 +2353,11 @@ static int __init caam_algapi_init(void)
int i = 0, err = 0;
dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
- if (!dev_node)
- return -ENODEV;
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return -ENODEV;
+ }
pdev = of_find_device_by_node(dev_node);
if (!pdev)
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index c5f61c55d923..77557ebcd337 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -98,6 +98,12 @@ static int caam_probe(struct platform_device *pdev)
rspec = 0;
for_each_compatible_node(np, NULL, "fsl,sec-v4.0-job-ring")
rspec++;
+ if (!rspec) {
+ /* for backward compatible with device trees */
+ for_each_compatible_node(np, NULL, "fsl,sec4.0-job-ring")
+ rspec++;
+ }
+
ctrlpriv->jrdev = kzalloc(sizeof(struct device *) * rspec, GFP_KERNEL);
if (ctrlpriv->jrdev == NULL) {
iounmap(&topregs->ctrl);
@@ -111,6 +117,13 @@ static int caam_probe(struct platform_device *pdev)
ctrlpriv->total_jobrs++;
ring++;
}
+ if (!ring) {
+ for_each_compatible_node(np, NULL, "fsl,sec4.0-job-ring") {
+ caam_jr_probe(pdev, np, ring);
+ ctrlpriv->total_jobrs++;
+ ring++;
+ }
+ }
/* Check to see if QI present. If so, enable */
ctrlpriv->qi_present = !!(rd_reg64(&topregs->ctrl.perfmon.comp_parms) &
@@ -226,6 +239,9 @@ static struct of_device_id caam_match[] = {
{
.compatible = "fsl,sec-v4.0",
},
+ {
+ .compatible = "fsl,sec4.0",
+ },
{},
};
MODULE_DEVICE_TABLE(of, caam_match);
diff --git a/drivers/crypto/nx/Makefile b/drivers/crypto/nx/Makefile
new file mode 100644
index 000000000000..411ce59c80d1
--- /dev/null
+++ b/drivers/crypto/nx/Makefile
@@ -0,0 +1,11 @@
+obj-$(CONFIG_CRYPTO_DEV_NX) += nx-crypto.o
+nx-crypto-objs := nx.o \
+ nx_debugfs.o \
+ nx-aes-cbc.o \
+ nx-aes-ecb.o \
+ nx-aes-gcm.o \
+ nx-aes-ccm.o \
+ nx-aes-ctr.o \
+ nx-aes-xcbc.o \
+ nx-sha256.o \
+ nx-sha512.o
diff --git a/drivers/crypto/nx/nx-aes-cbc.c b/drivers/crypto/nx/nx-aes-cbc.c
new file mode 100644
index 000000000000..69ed796ee327
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-cbc.c
@@ -0,0 +1,141 @@
+/**
+ * AES CBC routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2011-2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * 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.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+static int cbc_aes_nx_set_key(struct crypto_tfm *tfm,
+ const u8 *in_key,
+ unsigned int key_len)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+
+ nx_ctx_init(nx_ctx, HCOP_FC_AES);
+
+ switch (key_len) {
+ case AES_KEYSIZE_128:
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
+ break;
+ case AES_KEYSIZE_192:
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192];
+ break;
+ case AES_KEYSIZE_256:
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ csbcpb->cpb.hdr.mode = NX_MODE_AES_CBC;
+ memcpy(csbcpb->cpb.aes_cbc.key, in_key, key_len);
+
+ return 0;
+}
+
+static int cbc_aes_nx_crypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes,
+ int enc)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+ int rc;
+
+ if (nbytes > nx_ctx->ap->databytelen)
+ return -EINVAL;
+
+ if (enc)
+ NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
+ else
+ NX_CPB_FDM(csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
+
+ rc = nx_build_sg_lists(nx_ctx, desc, dst, src, nbytes,
+ csbcpb->cpb.aes_cbc.iv);
+ if (rc)
+ goto out;
+
+ if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
+ desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto out;
+
+ atomic_inc(&(nx_ctx->stats->aes_ops));
+ atomic64_add(csbcpb->csb.processed_byte_count,
+ &(nx_ctx->stats->aes_bytes));
+out:
+ return rc;
+}
+
+static int cbc_aes_nx_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return cbc_aes_nx_crypt(desc, dst, src, nbytes, 1);
+}
+
+static int cbc_aes_nx_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return cbc_aes_nx_crypt(desc, dst, src, nbytes, 0);
+}
+
+struct crypto_alg nx_cbc_aes_alg = {
+ .cra_name = "cbc(aes)",
+ .cra_driver_name = "cbc-aes-nx",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct nx_crypto_ctx),
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(nx_cbc_aes_alg.cra_list),
+ .cra_init = nx_crypto_ctx_aes_cbc_init,
+ .cra_exit = nx_crypto_ctx_exit,
+ .cra_blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = cbc_aes_nx_set_key,
+ .encrypt = cbc_aes_nx_encrypt,
+ .decrypt = cbc_aes_nx_decrypt,
+ }
+};
diff --git a/drivers/crypto/nx/nx-aes-ccm.c b/drivers/crypto/nx/nx-aes-ccm.c
new file mode 100644
index 000000000000..7aeac678b9c0
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-ccm.c
@@ -0,0 +1,468 @@
+/**
+ * AES CCM routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * 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.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/internal/aead.h>
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/scatterwalk.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+static int ccm_aes_nx_set_key(struct crypto_aead *tfm,
+ const u8 *in_key,
+ unsigned int key_len)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+ struct nx_csbcpb *csbcpb_aead = nx_ctx->csbcpb_aead;
+
+ nx_ctx_init(nx_ctx, HCOP_FC_AES);
+
+ switch (key_len) {
+ case AES_KEYSIZE_128:
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
+ NX_CPB_SET_KEY_SIZE(csbcpb_aead, NX_KS_AES_128);
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ csbcpb->cpb.hdr.mode = NX_MODE_AES_CCM;
+ memcpy(csbcpb->cpb.aes_ccm.key, in_key, key_len);
+
+ csbcpb_aead->cpb.hdr.mode = NX_MODE_AES_CCA;
+ memcpy(csbcpb_aead->cpb.aes_cca.key, in_key, key_len);
+
+ return 0;
+
+}
+
+static int ccm4309_aes_nx_set_key(struct crypto_aead *tfm,
+ const u8 *in_key,
+ unsigned int key_len)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
+
+ if (key_len < 3)
+ return -EINVAL;
+
+ key_len -= 3;
+
+ memcpy(nx_ctx->priv.ccm.nonce, in_key + key_len, 3);
+
+ return ccm_aes_nx_set_key(tfm, in_key, key_len);
+}
+
+static int ccm_aes_nx_setauthsize(struct crypto_aead *tfm,
+ unsigned int authsize)
+{
+ switch (authsize) {
+ case 4:
+ case 6:
+ case 8:
+ case 10:
+ case 12:
+ case 14:
+ case 16:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ crypto_aead_crt(tfm)->authsize = authsize;
+
+ return 0;
+}
+
+static int ccm4309_aes_nx_setauthsize(struct crypto_aead *tfm,
+ unsigned int authsize)
+{
+ switch (authsize) {
+ case 8:
+ case 12:
+ case 16:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ crypto_aead_crt(tfm)->authsize = authsize;
+
+ return 0;
+}
+
+/* taken from crypto/ccm.c */
+static int set_msg_len(u8 *block, unsigned int msglen, int csize)
+{
+ __be32 data;
+
+ memset(block, 0, csize);
+ block += csize;
+
+ if (csize >= 4)
+ csize = 4;
+ else if (msglen > (unsigned int)(1 << (8 * csize)))
+ return -EOVERFLOW;
+
+ data = cpu_to_be32(msglen);
+ memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
+
+ return 0;
+}
+
+/* taken from crypto/ccm.c */
+static inline int crypto_ccm_check_iv(const u8 *iv)
+{
+ /* 2 <= L <= 8, so 1 <= L' <= 7. */
+ if (1 > iv[0] || iv[0] > 7)
+ return -EINVAL;
+
+ return 0;
+}
+
+/* based on code from crypto/ccm.c */
+static int generate_b0(u8 *iv, unsigned int assoclen, unsigned int authsize,
+ unsigned int cryptlen, u8 *b0)
+{
+ unsigned int l, lp, m = authsize;
+ int rc;
+
+ memcpy(b0, iv, 16);
+
+ lp = b0[0];
+ l = lp + 1;
+
+ /* set m, bits 3-5 */
+ *b0 |= (8 * ((m - 2) / 2));
+
+ /* set adata, bit 6, if associated data is used */
+ if (assoclen)
+ *b0 |= 64;
+
+ rc = set_msg_len(b0 + 16 - l, cryptlen, l);
+
+ return rc;
+}
+
+static int generate_pat(u8 *iv,
+ struct aead_request *req,
+ struct nx_crypto_ctx *nx_ctx,
+ unsigned int authsize,
+ unsigned int nbytes,
+ u8 *out)
+{
+ struct nx_sg *nx_insg = nx_ctx->in_sg;
+ struct nx_sg *nx_outsg = nx_ctx->out_sg;
+ unsigned int iauth_len = 0;
+ struct vio_pfo_op *op = NULL;
+ u8 tmp[16], *b1 = NULL, *b0 = NULL, *result = NULL;
+ int rc;
+
+ /* zero the ctr value */
+ memset(iv + 15 - iv[0], 0, iv[0] + 1);
+
+ if (!req->assoclen) {
+ b0 = nx_ctx->csbcpb->cpb.aes_ccm.in_pat_or_b0;
+ } else if (req->assoclen <= 14) {
+ /* if associated data is 14 bytes or less, we do 1 GCM
+ * operation on 2 AES blocks, B0 (stored in the csbcpb) and B1,
+ * which is fed in through the source buffers here */
+ b0 = nx_ctx->csbcpb->cpb.aes_ccm.in_pat_or_b0;
+ b1 = nx_ctx->priv.ccm.iauth_tag;
+ iauth_len = req->assoclen;
+
+ nx_insg = nx_build_sg_list(nx_insg, b1, 16, nx_ctx->ap->sglen);
+ nx_outsg = nx_build_sg_list(nx_outsg, tmp, 16,
+ nx_ctx->ap->sglen);
+
+ /* inlen should be negative, indicating to phyp that its a
+ * pointer to an sg list */
+ nx_ctx->op.inlen = (nx_ctx->in_sg - nx_insg) *
+ sizeof(struct nx_sg);
+ nx_ctx->op.outlen = (nx_ctx->out_sg - nx_outsg) *
+ sizeof(struct nx_sg);
+
+ NX_CPB_FDM(nx_ctx->csbcpb) |= NX_FDM_ENDE_ENCRYPT;
+ NX_CPB_FDM(nx_ctx->csbcpb) |= NX_FDM_INTERMEDIATE;
+
+ op = &nx_ctx->op;
+ result = nx_ctx->csbcpb->cpb.aes_ccm.out_pat_or_mac;
+ } else if (req->assoclen <= 65280) {
+ /* if associated data is less than (2^16 - 2^8), we construct
+ * B1 differently and feed in the associated data to a CCA
+ * operation */
+ b0 = nx_ctx->csbcpb_aead->cpb.aes_cca.b0;
+ b1 = nx_ctx->csbcpb_aead->cpb.aes_cca.b1;
+ iauth_len = 14;
+
+ /* remaining assoc data must have scatterlist built for it */
+ nx_insg = nx_walk_and_build(nx_insg, nx_ctx->ap->sglen,
+ req->assoc, iauth_len,
+ req->assoclen - iauth_len);
+ nx_ctx->op_aead.inlen = (nx_ctx->in_sg - nx_insg) *
+ sizeof(struct nx_sg);
+
+ op = &nx_ctx->op_aead;
+ result = nx_ctx->csbcpb_aead->cpb.aes_cca.out_pat_or_b0;
+ } else {
+ /* if associated data is less than (2^32), we construct B1
+ * differently yet again and feed in the associated data to a
+ * CCA operation */
+ pr_err("associated data len is %u bytes (returning -EINVAL)\n",
+ req->assoclen);
+ rc = -EINVAL;
+ }
+
+ rc = generate_b0(iv, req->assoclen, authsize, nbytes, b0);
+ if (rc)
+ goto done;
+
+ if (b1) {
+ memset(b1, 0, 16);
+ *(u16 *)b1 = (u16)req->assoclen;
+
+ scatterwalk_map_and_copy(b1 + 2, req->assoc, 0,
+ iauth_len, SCATTERWALK_FROM_SG);
+
+ rc = nx_hcall_sync(nx_ctx, op,
+ req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto done;
+
+ atomic_inc(&(nx_ctx->stats->aes_ops));
+ atomic64_add(req->assoclen, &(nx_ctx->stats->aes_bytes));
+
+ memcpy(out, result, AES_BLOCK_SIZE);
+ }
+done:
+ return rc;
+}
+
+static int ccm_nx_decrypt(struct aead_request *req,
+ struct blkcipher_desc *desc)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+ unsigned int nbytes = req->cryptlen;
+ unsigned int authsize = crypto_aead_authsize(crypto_aead_reqtfm(req));
+ struct nx_ccm_priv *priv = &nx_ctx->priv.ccm;
+ int rc = -1;
+
+ if (nbytes > nx_ctx->ap->databytelen)
+ return -EINVAL;
+
+ nbytes -= authsize;
+
+ /* copy out the auth tag to compare with later */
+ scatterwalk_map_and_copy(priv->oauth_tag,
+ req->src, nbytes, authsize,
+ SCATTERWALK_FROM_SG);
+
+ rc = generate_pat(desc->info, req, nx_ctx, authsize, nbytes,
+ csbcpb->cpb.aes_ccm.in_pat_or_b0);
+ if (rc)
+ goto out;
+
+ rc = nx_build_sg_lists(nx_ctx, desc, req->dst, req->src, nbytes,
+ csbcpb->cpb.aes_ccm.iv_or_ctr);
+ if (rc)
+ goto out;
+
+ NX_CPB_FDM(nx_ctx->csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
+ NX_CPB_FDM(nx_ctx->csbcpb) &= ~NX_FDM_INTERMEDIATE;
+
+ rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
+ req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto out;
+
+ atomic_inc(&(nx_ctx->stats->aes_ops));
+ atomic64_add(csbcpb->csb.processed_byte_count,
+ &(nx_ctx->stats->aes_bytes));
+
+ rc = memcmp(csbcpb->cpb.aes_ccm.out_pat_or_mac, priv->oauth_tag,
+ authsize) ? -EBADMSG : 0;
+out:
+ return rc;
+}
+
+static int ccm_nx_encrypt(struct aead_request *req,
+ struct blkcipher_desc *desc)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+ unsigned int nbytes = req->cryptlen;
+ unsigned int authsize = crypto_aead_authsize(crypto_aead_reqtfm(req));
+ int rc = -1;
+
+ if (nbytes > nx_ctx->ap->databytelen)
+ return -EINVAL;
+
+ rc = generate_pat(desc->info, req, nx_ctx, authsize, nbytes,
+ csbcpb->cpb.aes_ccm.in_pat_or_b0);
+ if (rc)
+ goto out;
+
+ rc = nx_build_sg_lists(nx_ctx, desc, req->dst, req->src, nbytes,
+ csbcpb->cpb.aes_ccm.iv_or_ctr);
+ if (rc)
+ goto out;
+
+ NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
+ NX_CPB_FDM(csbcpb) &= ~NX_FDM_INTERMEDIATE;
+
+ rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
+ req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto out;
+
+ atomic_inc(&(nx_ctx->stats->aes_ops));
+ atomic64_add(csbcpb->csb.processed_byte_count,
+ &(nx_ctx->stats->aes_bytes));
+
+ /* copy out the auth tag */
+ scatterwalk_map_and_copy(csbcpb->cpb.aes_ccm.out_pat_or_mac,
+ req->dst, nbytes, authsize,
+ SCATTERWALK_TO_SG);
+out:
+ return rc;
+}
+
+static int ccm4309_aes_nx_encrypt(struct aead_request *req)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+ struct blkcipher_desc desc;
+ u8 *iv = nx_ctx->priv.ccm.iv;
+
+ iv[0] = 3;
+ memcpy(iv + 1, nx_ctx->priv.ccm.nonce, 3);
+ memcpy(iv + 4, req->iv, 8);
+
+ desc.info = iv;
+ desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
+
+ return ccm_nx_encrypt(req, &desc);
+}
+
+static int ccm_aes_nx_encrypt(struct aead_request *req)
+{
+ struct blkcipher_desc desc;
+ int rc;
+
+ desc.info = req->iv;
+ desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
+
+ rc = crypto_ccm_check_iv(desc.info);
+ if (rc)
+ return rc;
+
+ return ccm_nx_encrypt(req, &desc);
+}
+
+static int ccm4309_aes_nx_decrypt(struct aead_request *req)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+ struct blkcipher_desc desc;
+ u8 *iv = nx_ctx->priv.ccm.iv;
+
+ iv[0] = 3;
+ memcpy(iv + 1, nx_ctx->priv.ccm.nonce, 3);
+ memcpy(iv + 4, req->iv, 8);
+
+ desc.info = iv;
+ desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
+
+ return ccm_nx_decrypt(req, &desc);
+}
+
+static int ccm_aes_nx_decrypt(struct aead_request *req)
+{
+ struct blkcipher_desc desc;
+ int rc;
+
+ desc.info = req->iv;
+ desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
+
+ rc = crypto_ccm_check_iv(desc.info);
+ if (rc)
+ return rc;
+
+ return ccm_nx_decrypt(req, &desc);
+}
+
+/* tell the block cipher walk routines that this is a stream cipher by
+ * setting cra_blocksize to 1. Even using blkcipher_walk_virt_block
+ * during encrypt/decrypt doesn't solve this problem, because it calls
+ * blkcipher_walk_done under the covers, which doesn't use walk->blocksize,
+ * but instead uses this tfm->blocksize. */
+struct crypto_alg nx_ccm_aes_alg = {
+ .cra_name = "ccm(aes)",
+ .cra_driver_name = "ccm-aes-nx",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct nx_crypto_ctx),
+ .cra_type = &crypto_aead_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(nx_ccm_aes_alg.cra_list),
+ .cra_init = nx_crypto_ctx_aes_ccm_init,
+ .cra_exit = nx_crypto_ctx_exit,
+ .cra_aead = {
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = AES_BLOCK_SIZE,
+ .setkey = ccm_aes_nx_set_key,
+ .setauthsize = ccm_aes_nx_setauthsize,
+ .encrypt = ccm_aes_nx_encrypt,
+ .decrypt = ccm_aes_nx_decrypt,
+ }
+};
+
+struct crypto_alg nx_ccm4309_aes_alg = {
+ .cra_name = "rfc4309(ccm(aes))",
+ .cra_driver_name = "rfc4309-ccm-aes-nx",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct nx_crypto_ctx),
+ .cra_type = &crypto_nivaead_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(nx_ccm4309_aes_alg.cra_list),
+ .cra_init = nx_crypto_ctx_aes_ccm_init,
+ .cra_exit = nx_crypto_ctx_exit,
+ .cra_aead = {
+ .ivsize = 8,
+ .maxauthsize = AES_BLOCK_SIZE,
+ .setkey = ccm4309_aes_nx_set_key,
+ .setauthsize = ccm4309_aes_nx_setauthsize,
+ .encrypt = ccm4309_aes_nx_encrypt,
+ .decrypt = ccm4309_aes_nx_decrypt,
+ .geniv = "seqiv",
+ }
+};
diff --git a/drivers/crypto/nx/nx-aes-ctr.c b/drivers/crypto/nx/nx-aes-ctr.c
new file mode 100644
index 000000000000..52d4eb05e8f7
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-ctr.c
@@ -0,0 +1,178 @@
+/**
+ * AES CTR routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2011-2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * 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.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/aes.h>
+#include <crypto/ctr.h>
+#include <crypto/algapi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+static int ctr_aes_nx_set_key(struct crypto_tfm *tfm,
+ const u8 *in_key,
+ unsigned int key_len)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+
+ nx_ctx_init(nx_ctx, HCOP_FC_AES);
+
+ switch (key_len) {
+ case AES_KEYSIZE_128:
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
+ break;
+ case AES_KEYSIZE_192:
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192];
+ break;
+ case AES_KEYSIZE_256:
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ csbcpb->cpb.hdr.mode = NX_MODE_AES_CTR;
+ memcpy(csbcpb->cpb.aes_ctr.key, in_key, key_len);
+
+ return 0;
+}
+
+static int ctr3686_aes_nx_set_key(struct crypto_tfm *tfm,
+ const u8 *in_key,
+ unsigned int key_len)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
+
+ if (key_len < CTR_RFC3686_NONCE_SIZE)
+ return -EINVAL;
+
+ memcpy(nx_ctx->priv.ctr.iv,
+ in_key + key_len - CTR_RFC3686_NONCE_SIZE,
+ CTR_RFC3686_NONCE_SIZE);
+
+ key_len -= CTR_RFC3686_NONCE_SIZE;
+
+ return ctr_aes_nx_set_key(tfm, in_key, key_len);
+}
+
+static int ctr_aes_nx_crypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+ int rc;
+
+ if (nbytes > nx_ctx->ap->databytelen)
+ return -EINVAL;
+
+ rc = nx_build_sg_lists(nx_ctx, desc, dst, src, nbytes,
+ csbcpb->cpb.aes_ctr.iv);
+ if (rc)
+ goto out;
+
+ if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
+ desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto out;
+
+ atomic_inc(&(nx_ctx->stats->aes_ops));
+ atomic64_add(csbcpb->csb.processed_byte_count,
+ &(nx_ctx->stats->aes_bytes));
+out:
+ return rc;
+}
+
+static int ctr3686_aes_nx_crypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
+ u8 *iv = nx_ctx->priv.ctr.iv;
+
+ memcpy(iv + CTR_RFC3686_NONCE_SIZE,
+ desc->info, CTR_RFC3686_IV_SIZE);
+ iv[15] = 1;
+
+ desc->info = nx_ctx->priv.ctr.iv;
+
+ return ctr_aes_nx_crypt(desc, dst, src, nbytes);
+}
+
+struct crypto_alg nx_ctr_aes_alg = {
+ .cra_name = "ctr(aes)",
+ .cra_driver_name = "ctr-aes-nx",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct nx_crypto_ctx),
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(nx_ctr_aes_alg.cra_list),
+ .cra_init = nx_crypto_ctx_aes_ctr_init,
+ .cra_exit = nx_crypto_ctx_exit,
+ .cra_blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = ctr_aes_nx_set_key,
+ .encrypt = ctr_aes_nx_crypt,
+ .decrypt = ctr_aes_nx_crypt,
+ }
+};
+
+struct crypto_alg nx_ctr3686_aes_alg = {
+ .cra_name = "rfc3686(ctr(aes))",
+ .cra_driver_name = "rfc3686-ctr-aes-nx",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct nx_crypto_ctx),
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(nx_ctr3686_aes_alg.cra_list),
+ .cra_init = nx_crypto_ctx_aes_ctr_init,
+ .cra_exit = nx_crypto_ctx_exit,
+ .cra_blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
+ .ivsize = CTR_RFC3686_IV_SIZE,
+ .geniv = "seqiv",
+ .setkey = ctr3686_aes_nx_set_key,
+ .encrypt = ctr3686_aes_nx_crypt,
+ .decrypt = ctr3686_aes_nx_crypt,
+ }
+};
diff --git a/drivers/crypto/nx/nx-aes-ecb.c b/drivers/crypto/nx/nx-aes-ecb.c
new file mode 100644
index 000000000000..7b77bc2d1df4
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-ecb.c
@@ -0,0 +1,139 @@
+/**
+ * AES ECB routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2011-2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * 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.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+static int ecb_aes_nx_set_key(struct crypto_tfm *tfm,
+ const u8 *in_key,
+ unsigned int key_len)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
+ struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
+
+ nx_ctx_init(nx_ctx, HCOP_FC_AES);
+
+ switch (key_len) {
+ case AES_KEYSIZE_128:
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
+ break;
+ case AES_KEYSIZE_192:
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192];
+ break;
+ case AES_KEYSIZE_256:
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ csbcpb->cpb.hdr.mode = NX_MODE_AES_ECB;
+ memcpy(csbcpb->cpb.aes_ecb.key, in_key, key_len);
+
+ return 0;
+}
+
+static int ecb_aes_nx_crypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes,
+ int enc)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+ int rc;
+
+ if (nbytes > nx_ctx->ap->databytelen)
+ return -EINVAL;
+
+ if (enc)
+ NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
+ else
+ NX_CPB_FDM(csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
+
+ rc = nx_build_sg_lists(nx_ctx, desc, dst, src, nbytes, NULL);
+ if (rc)
+ goto out;
+
+ if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
+ desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto out;
+
+ atomic_inc(&(nx_ctx->stats->aes_ops));
+ atomic64_add(csbcpb->csb.processed_byte_count,
+ &(nx_ctx->stats->aes_bytes));
+out:
+ return rc;
+}
+
+static int ecb_aes_nx_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return ecb_aes_nx_crypt(desc, dst, src, nbytes, 1);
+}
+
+static int ecb_aes_nx_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return ecb_aes_nx_crypt(desc, dst, src, nbytes, 0);
+}
+
+struct crypto_alg nx_ecb_aes_alg = {
+ .cra_name = "ecb(aes)",
+ .cra_driver_name = "ecb-aes-nx",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct nx_crypto_ctx),
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(nx_ecb_aes_alg.cra_list),
+ .cra_init = nx_crypto_ctx_aes_ecb_init,
+ .cra_exit = nx_crypto_ctx_exit,
+ .cra_blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = ecb_aes_nx_set_key,
+ .encrypt = ecb_aes_nx_encrypt,
+ .decrypt = ecb_aes_nx_decrypt,
+ }
+};
diff --git a/drivers/crypto/nx/nx-aes-gcm.c b/drivers/crypto/nx/nx-aes-gcm.c
new file mode 100644
index 000000000000..9ab1c7341dac
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-gcm.c
@@ -0,0 +1,353 @@
+/**
+ * AES GCM routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * 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.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/internal/aead.h>
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/scatterwalk.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+static int gcm_aes_nx_set_key(struct crypto_aead *tfm,
+ const u8 *in_key,
+ unsigned int key_len)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+ struct nx_csbcpb *csbcpb_aead = nx_ctx->csbcpb_aead;
+
+ nx_ctx_init(nx_ctx, HCOP_FC_AES);
+
+ switch (key_len) {
+ case AES_KEYSIZE_128:
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
+ NX_CPB_SET_KEY_SIZE(csbcpb_aead, NX_KS_AES_128);
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
+ break;
+ case AES_KEYSIZE_192:
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
+ NX_CPB_SET_KEY_SIZE(csbcpb_aead, NX_KS_AES_192);
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192];
+ break;
+ case AES_KEYSIZE_256:
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
+ NX_CPB_SET_KEY_SIZE(csbcpb_aead, NX_KS_AES_256);
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ csbcpb->cpb.hdr.mode = NX_MODE_AES_GCM;
+ memcpy(csbcpb->cpb.aes_gcm.key, in_key, key_len);
+
+ csbcpb_aead->cpb.hdr.mode = NX_MODE_AES_GCA;
+ memcpy(csbcpb_aead->cpb.aes_gca.key, in_key, key_len);
+
+ return 0;
+}
+
+static int gcm4106_aes_nx_set_key(struct crypto_aead *tfm,
+ const u8 *in_key,
+ unsigned int key_len)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
+ char *nonce = nx_ctx->priv.gcm.nonce;
+ int rc;
+
+ if (key_len < 4)
+ return -EINVAL;
+
+ key_len -= 4;
+
+ rc = gcm_aes_nx_set_key(tfm, in_key, key_len);
+ if (rc)
+ goto out;
+
+ memcpy(nonce, in_key + key_len, 4);
+out:
+ return rc;
+}
+
+static int gcm_aes_nx_setauthsize(struct crypto_aead *tfm,
+ unsigned int authsize)
+{
+ if (authsize > crypto_aead_alg(tfm)->maxauthsize)
+ return -EINVAL;
+
+ crypto_aead_crt(tfm)->authsize = authsize;
+
+ return 0;
+}
+
+static int gcm4106_aes_nx_setauthsize(struct crypto_aead *tfm,
+ unsigned int authsize)
+{
+ switch (authsize) {
+ case 8:
+ case 12:
+ case 16:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ crypto_aead_crt(tfm)->authsize = authsize;
+
+ return 0;
+}
+
+static int nx_gca(struct nx_crypto_ctx *nx_ctx,
+ struct aead_request *req,
+ u8 *out)
+{
+ struct nx_csbcpb *csbcpb_aead = nx_ctx->csbcpb_aead;
+ int rc = -EINVAL;
+ struct scatter_walk walk;
+ struct nx_sg *nx_sg = nx_ctx->in_sg;
+
+ if (req->assoclen > nx_ctx->ap->databytelen)
+ goto out;
+
+ if (req->assoclen <= AES_BLOCK_SIZE) {
+ scatterwalk_start(&walk, req->assoc);
+ scatterwalk_copychunks(out, &walk, req->assoclen,
+ SCATTERWALK_FROM_SG);
+ scatterwalk_done(&walk, SCATTERWALK_FROM_SG, 0);
+
+ rc = 0;
+ goto out;
+ }
+
+ nx_sg = nx_walk_and_build(nx_sg, nx_ctx->ap->sglen, req->assoc, 0,
+ req->assoclen);
+ nx_ctx->op_aead.inlen = (nx_ctx->in_sg - nx_sg) * sizeof(struct nx_sg);
+
+ rc = nx_hcall_sync(nx_ctx, &nx_ctx->op_aead,
+ req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto out;
+
+ atomic_inc(&(nx_ctx->stats->aes_ops));
+ atomic64_add(req->assoclen, &(nx_ctx->stats->aes_bytes));
+
+ memcpy(out, csbcpb_aead->cpb.aes_gca.out_pat, AES_BLOCK_SIZE);
+out:
+ return rc;
+}
+
+static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+ struct blkcipher_desc desc;
+ unsigned int nbytes = req->cryptlen;
+ int rc = -EINVAL;
+
+ if (nbytes > nx_ctx->ap->databytelen)
+ goto out;
+
+ desc.info = nx_ctx->priv.gcm.iv;
+ /* initialize the counter */
+ *(u32 *)(desc.info + NX_GCM_CTR_OFFSET) = 1;
+
+ /* For scenarios where the input message is zero length, AES CTR mode
+ * may be used. Set the source data to be a single block (16B) of all
+ * zeros, and set the input IV value to be the same as the GMAC IV
+ * value. - nx_wb 4.8.1.3 */
+ if (nbytes == 0) {
+ char src[AES_BLOCK_SIZE] = {};
+ struct scatterlist sg;
+
+ desc.tfm = crypto_alloc_blkcipher("ctr(aes)", 0, 0);
+ if (IS_ERR(desc.tfm)) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ crypto_blkcipher_setkey(desc.tfm, csbcpb->cpb.aes_gcm.key,
+ NX_CPB_KEY_SIZE(csbcpb) == NX_KS_AES_128 ? 16 :
+ NX_CPB_KEY_SIZE(csbcpb) == NX_KS_AES_192 ? 24 : 32);
+
+ sg_init_one(&sg, src, AES_BLOCK_SIZE);
+ if (enc)
+ crypto_blkcipher_encrypt_iv(&desc, req->dst, &sg,
+ AES_BLOCK_SIZE);
+ else
+ crypto_blkcipher_decrypt_iv(&desc, req->dst, &sg,
+ AES_BLOCK_SIZE);
+ crypto_free_blkcipher(desc.tfm);
+
+ rc = 0;
+ goto out;
+ }
+
+ desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
+
+ csbcpb->cpb.aes_gcm.bit_length_aad = req->assoclen * 8;
+
+ if (req->assoclen) {
+ rc = nx_gca(nx_ctx, req, csbcpb->cpb.aes_gcm.in_pat_or_aad);
+ if (rc)
+ goto out;
+ }
+
+ if (enc)
+ NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
+ else
+ nbytes -= AES_BLOCK_SIZE;
+
+ csbcpb->cpb.aes_gcm.bit_length_data = nbytes * 8;
+
+ rc = nx_build_sg_lists(nx_ctx, &desc, req->dst, req->src, nbytes,
+ csbcpb->cpb.aes_gcm.iv_or_cnt);
+ if (rc)
+ goto out;
+
+ rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
+ req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto out;
+
+ atomic_inc(&(nx_ctx->stats->aes_ops));
+ atomic64_add(csbcpb->csb.processed_byte_count,
+ &(nx_ctx->stats->aes_bytes));
+
+ if (enc) {
+ /* copy out the auth tag */
+ scatterwalk_map_and_copy(csbcpb->cpb.aes_gcm.out_pat_or_mac,
+ req->dst, nbytes,
+ crypto_aead_authsize(crypto_aead_reqtfm(req)),
+ SCATTERWALK_TO_SG);
+ } else if (req->assoclen) {
+ u8 *itag = nx_ctx->priv.gcm.iauth_tag;
+ u8 *otag = csbcpb->cpb.aes_gcm.out_pat_or_mac;
+
+ scatterwalk_map_and_copy(itag, req->dst, nbytes,
+ crypto_aead_authsize(crypto_aead_reqtfm(req)),
+ SCATTERWALK_FROM_SG);
+ rc = memcmp(itag, otag,
+ crypto_aead_authsize(crypto_aead_reqtfm(req))) ?
+ -EBADMSG : 0;
+ }
+out:
+ return rc;
+}
+
+static int gcm_aes_nx_encrypt(struct aead_request *req)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+ char *iv = nx_ctx->priv.gcm.iv;
+
+ memcpy(iv, req->iv, 12);
+
+ return gcm_aes_nx_crypt(req, 1);
+}
+
+static int gcm_aes_nx_decrypt(struct aead_request *req)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+ char *iv = nx_ctx->priv.gcm.iv;
+
+ memcpy(iv, req->iv, 12);
+
+ return gcm_aes_nx_crypt(req, 0);
+}
+
+static int gcm4106_aes_nx_encrypt(struct aead_request *req)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+ char *iv = nx_ctx->priv.gcm.iv;
+ char *nonce = nx_ctx->priv.gcm.nonce;
+
+ memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);
+ memcpy(iv + NX_GCM4106_NONCE_LEN, req->iv, 8);
+
+ return gcm_aes_nx_crypt(req, 1);
+}
+
+static int gcm4106_aes_nx_decrypt(struct aead_request *req)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+ char *iv = nx_ctx->priv.gcm.iv;
+ char *nonce = nx_ctx->priv.gcm.nonce;
+
+ memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);
+ memcpy(iv + NX_GCM4106_NONCE_LEN, req->iv, 8);
+
+ return gcm_aes_nx_crypt(req, 0);
+}
+
+/* tell the block cipher walk routines that this is a stream cipher by
+ * setting cra_blocksize to 1. Even using blkcipher_walk_virt_block
+ * during encrypt/decrypt doesn't solve this problem, because it calls
+ * blkcipher_walk_done under the covers, which doesn't use walk->blocksize,
+ * but instead uses this tfm->blocksize. */
+struct crypto_alg nx_gcm_aes_alg = {
+ .cra_name = "gcm(aes)",
+ .cra_driver_name = "gcm-aes-nx",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct nx_crypto_ctx),
+ .cra_type = &crypto_aead_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(nx_gcm_aes_alg.cra_list),
+ .cra_init = nx_crypto_ctx_aes_gcm_init,
+ .cra_exit = nx_crypto_ctx_exit,
+ .cra_aead = {
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = AES_BLOCK_SIZE,
+ .setkey = gcm_aes_nx_set_key,
+ .setauthsize = gcm_aes_nx_setauthsize,
+ .encrypt = gcm_aes_nx_encrypt,
+ .decrypt = gcm_aes_nx_decrypt,
+ }
+};
+
+struct crypto_alg nx_gcm4106_aes_alg = {
+ .cra_name = "rfc4106(gcm(aes))",
+ .cra_driver_name = "rfc4106-gcm-aes-nx",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct nx_crypto_ctx),
+ .cra_type = &crypto_nivaead_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(nx_gcm4106_aes_alg.cra_list),
+ .cra_init = nx_crypto_ctx_aes_gcm_init,
+ .cra_exit = nx_crypto_ctx_exit,
+ .cra_aead = {
+ .ivsize = 8,
+ .maxauthsize = AES_BLOCK_SIZE,
+ .geniv = "seqiv",
+ .setkey = gcm4106_aes_nx_set_key,
+ .setauthsize = gcm4106_aes_nx_setauthsize,
+ .encrypt = gcm4106_aes_nx_encrypt,
+ .decrypt = gcm4106_aes_nx_decrypt,
+ }
+};
diff --git a/drivers/crypto/nx/nx-aes-xcbc.c b/drivers/crypto/nx/nx-aes-xcbc.c
new file mode 100644
index 000000000000..93923e4628c0
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-xcbc.c
@@ -0,0 +1,236 @@
+/**
+ * AES XCBC routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2011-2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * 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.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/internal/hash.h>
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+struct xcbc_state {
+ u8 state[AES_BLOCK_SIZE];
+ unsigned int count;
+ u8 buffer[AES_BLOCK_SIZE];
+};
+
+static int nx_xcbc_set_key(struct crypto_shash *desc,
+ const u8 *in_key,
+ unsigned int key_len)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_shash_ctx(desc);
+
+ switch (key_len) {
+ case AES_KEYSIZE_128:
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ memcpy(nx_ctx->priv.xcbc.key, in_key, key_len);
+
+ return 0;
+}
+
+static int nx_xcbc_init(struct shash_desc *desc)
+{
+ struct xcbc_state *sctx = shash_desc_ctx(desc);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+ struct nx_sg *out_sg;
+
+ nx_ctx_init(nx_ctx, HCOP_FC_AES);
+
+ memset(sctx, 0, sizeof *sctx);
+
+ NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
+ csbcpb->cpb.hdr.mode = NX_MODE_AES_XCBC_MAC;
+
+ memcpy(csbcpb->cpb.aes_xcbc.key, nx_ctx->priv.xcbc.key, AES_BLOCK_SIZE);
+ memset(nx_ctx->priv.xcbc.key, 0, sizeof *nx_ctx->priv.xcbc.key);
+
+ out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
+ AES_BLOCK_SIZE, nx_ctx->ap->sglen);
+ nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
+
+ return 0;
+}
+
+static int nx_xcbc_update(struct shash_desc *desc,
+ const u8 *data,
+ unsigned int len)
+{
+ struct xcbc_state *sctx = shash_desc_ctx(desc);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+ struct nx_sg *in_sg;
+ u32 to_process, leftover;
+ int rc = 0;
+
+ if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
+ /* we've hit the nx chip previously and we're updating again,
+ * so copy over the partial digest */
+ memcpy(csbcpb->cpb.aes_xcbc.cv,
+ csbcpb->cpb.aes_xcbc.out_cv_mac, AES_BLOCK_SIZE);
+ }
+
+ /* 2 cases for total data len:
+ * 1: <= AES_BLOCK_SIZE: copy into state, return 0
+ * 2: > AES_BLOCK_SIZE: process X blocks, copy in leftover
+ */
+ if (len + sctx->count <= AES_BLOCK_SIZE) {
+ memcpy(sctx->buffer + sctx->count, data, len);
+ sctx->count += len;
+ goto out;
+ }
+
+ /* to_process: the AES_BLOCK_SIZE data chunk to process in this
+ * update */
+ to_process = (sctx->count + len) & ~(AES_BLOCK_SIZE - 1);
+ leftover = (sctx->count + len) & (AES_BLOCK_SIZE - 1);
+
+ /* the hardware will not accept a 0 byte operation for this algorithm
+ * and the operation MUST be finalized to be correct. So if we happen
+ * to get an update that falls on a block sized boundary, we must
+ * save off the last block to finalize with later. */
+ if (!leftover) {
+ to_process -= AES_BLOCK_SIZE;
+ leftover = AES_BLOCK_SIZE;
+ }
+
+ if (sctx->count) {
+ in_sg = nx_build_sg_list(nx_ctx->in_sg, sctx->buffer,
+ sctx->count, nx_ctx->ap->sglen);
+ in_sg = nx_build_sg_list(in_sg, (u8 *)data,
+ to_process - sctx->count,
+ nx_ctx->ap->sglen);
+ nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
+ sizeof(struct nx_sg);
+ } else {
+ in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)data, to_process,
+ nx_ctx->ap->sglen);
+ nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
+ sizeof(struct nx_sg);
+ }
+
+ NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
+
+ if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
+ desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto out;
+
+ atomic_inc(&(nx_ctx->stats->aes_ops));
+
+ /* copy the leftover back into the state struct */
+ memcpy(sctx->buffer, data + len - leftover, leftover);
+ sctx->count = leftover;
+
+ /* everything after the first update is continuation */
+ NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
+out:
+ return rc;
+}
+
+static int nx_xcbc_final(struct shash_desc *desc, u8 *out)
+{
+ struct xcbc_state *sctx = shash_desc_ctx(desc);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+ struct nx_sg *in_sg, *out_sg;
+ int rc = 0;
+
+ if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
+ /* we've hit the nx chip previously, now we're finalizing,
+ * so copy over the partial digest */
+ memcpy(csbcpb->cpb.aes_xcbc.cv,
+ csbcpb->cpb.aes_xcbc.out_cv_mac, AES_BLOCK_SIZE);
+ } else if (sctx->count == 0) {
+ /* we've never seen an update, so this is a 0 byte op. The
+ * hardware cannot handle a 0 byte op, so just copy out the
+ * known 0 byte result. This is cheaper than allocating a
+ * software context to do a 0 byte op */
+ u8 data[] = { 0x75, 0xf0, 0x25, 0x1d, 0x52, 0x8a, 0xc0, 0x1c,
+ 0x45, 0x73, 0xdf, 0xd5, 0x84, 0xd7, 0x9f, 0x29 };
+ memcpy(out, data, sizeof(data));
+ goto out;
+ }
+
+ /* final is represented by continuing the operation and indicating that
+ * this is not an intermediate operation */
+ NX_CPB_FDM(csbcpb) &= ~NX_FDM_INTERMEDIATE;
+
+ in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)sctx->buffer,
+ sctx->count, nx_ctx->ap->sglen);
+ out_sg = nx_build_sg_list(nx_ctx->out_sg, out, AES_BLOCK_SIZE,
+ nx_ctx->ap->sglen);
+
+ nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
+ nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
+
+ if (!nx_ctx->op.outlen) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
+ desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto out;
+
+ atomic_inc(&(nx_ctx->stats->aes_ops));
+
+ memcpy(out, csbcpb->cpb.aes_xcbc.out_cv_mac, AES_BLOCK_SIZE);
+out:
+ return rc;
+}
+
+struct shash_alg nx_shash_aes_xcbc_alg = {
+ .digestsize = AES_BLOCK_SIZE,
+ .init = nx_xcbc_init,
+ .update = nx_xcbc_update,
+ .final = nx_xcbc_final,
+ .setkey = nx_xcbc_set_key,
+ .descsize = sizeof(struct xcbc_state),
+ .statesize = sizeof(struct xcbc_state),
+ .base = {
+ .cra_name = "xcbc(aes)",
+ .cra_driver_name = "xcbc-aes-nx",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ .cra_ctxsize = sizeof(struct nx_crypto_ctx),
+ .cra_init = nx_crypto_ctx_aes_xcbc_init,
+ .cra_exit = nx_crypto_ctx_exit,
+ }
+};
diff --git a/drivers/crypto/nx/nx-sha256.c b/drivers/crypto/nx/nx-sha256.c
new file mode 100644
index 000000000000..9767315f8c0b
--- /dev/null
+++ b/drivers/crypto/nx/nx-sha256.c
@@ -0,0 +1,246 @@
+/**
+ * SHA-256 routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2011-2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * 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.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/internal/hash.h>
+#include <crypto/sha.h>
+#include <linux/module.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+static int nx_sha256_init(struct shash_desc *desc)
+{
+ struct sha256_state *sctx = shash_desc_ctx(desc);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_sg *out_sg;
+
+ nx_ctx_init(nx_ctx, HCOP_FC_SHA);
+
+ memset(sctx, 0, sizeof *sctx);
+
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_SHA256];
+
+ NX_CPB_SET_DIGEST_SIZE(nx_ctx->csbcpb, NX_DS_SHA256);
+ out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
+ SHA256_DIGEST_SIZE, nx_ctx->ap->sglen);
+ nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
+
+ return 0;
+}
+
+static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ struct sha256_state *sctx = shash_desc_ctx(desc);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
+ struct nx_sg *in_sg;
+ u64 to_process, leftover;
+ int rc = 0;
+
+ if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
+ /* we've hit the nx chip previously and we're updating again,
+ * so copy over the partial digest */
+ memcpy(csbcpb->cpb.sha256.input_partial_digest,
+ csbcpb->cpb.sha256.message_digest, SHA256_DIGEST_SIZE);
+ }
+
+ /* 2 cases for total data len:
+ * 1: <= SHA256_BLOCK_SIZE: copy into state, return 0
+ * 2: > SHA256_BLOCK_SIZE: process X blocks, copy in leftover
+ */
+ if (len + sctx->count <= SHA256_BLOCK_SIZE) {
+ memcpy(sctx->buf + sctx->count, data, len);
+ sctx->count += len;
+ goto out;
+ }
+
+ /* to_process: the SHA256_BLOCK_SIZE data chunk to process in this
+ * update */
+ to_process = (sctx->count + len) & ~(SHA256_BLOCK_SIZE - 1);
+ leftover = (sctx->count + len) & (SHA256_BLOCK_SIZE - 1);
+
+ if (sctx->count) {
+ in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)sctx->buf,
+ sctx->count, nx_ctx->ap->sglen);
+ in_sg = nx_build_sg_list(in_sg, (u8 *)data,
+ to_process - sctx->count,
+ nx_ctx->ap->sglen);
+ nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
+ sizeof(struct nx_sg);
+ } else {
+ in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)data,
+ to_process, nx_ctx->ap->sglen);
+ nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
+ sizeof(struct nx_sg);
+ }
+
+ NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
+
+ if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
+ desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto out;
+
+ atomic_inc(&(nx_ctx->stats->sha256_ops));
+
+ /* copy the leftover back into the state struct */
+ memcpy(sctx->buf, data + len - leftover, leftover);
+ sctx->count = leftover;
+
+ csbcpb->cpb.sha256.message_bit_length += (u64)
+ (csbcpb->cpb.sha256.spbc * 8);
+
+ /* everything after the first update is continuation */
+ NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
+out:
+ return rc;
+}
+
+static int nx_sha256_final(struct shash_desc *desc, u8 *out)
+{
+ struct sha256_state *sctx = shash_desc_ctx(desc);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
+ struct nx_sg *in_sg, *out_sg;
+ int rc;
+
+ if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
+ /* we've hit the nx chip previously, now we're finalizing,
+ * so copy over the partial digest */
+ memcpy(csbcpb->cpb.sha256.input_partial_digest,
+ csbcpb->cpb.sha256.message_digest, SHA256_DIGEST_SIZE);
+ }
+
+ /* final is represented by continuing the operation and indicating that
+ * this is not an intermediate operation */
+ NX_CPB_FDM(csbcpb) &= ~NX_FDM_INTERMEDIATE;
+
+ csbcpb->cpb.sha256.message_bit_length += (u64)(sctx->count * 8);
+
+ in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)sctx->buf,
+ sctx->count, nx_ctx->ap->sglen);
+ out_sg = nx_build_sg_list(nx_ctx->out_sg, out, SHA256_DIGEST_SIZE,
+ nx_ctx->ap->sglen);
+ nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
+ nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
+
+ if (!nx_ctx->op.outlen) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
+ desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto out;
+
+ atomic_inc(&(nx_ctx->stats->sha256_ops));
+
+ atomic64_add(csbcpb->cpb.sha256.message_bit_length,
+ &(nx_ctx->stats->sha256_bytes));
+ memcpy(out, csbcpb->cpb.sha256.message_digest, SHA256_DIGEST_SIZE);
+out:
+ return rc;
+}
+
+static int nx_sha256_export(struct shash_desc *desc, void *out)
+{
+ struct sha256_state *sctx = shash_desc_ctx(desc);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
+ struct sha256_state *octx = out;
+
+ octx->count = sctx->count +
+ (csbcpb->cpb.sha256.message_bit_length / 8);
+ memcpy(octx->buf, sctx->buf, sizeof(octx->buf));
+
+ /* if no data has been processed yet, we need to export SHA256's
+ * initial data, in case this context gets imported into a software
+ * context */
+ if (csbcpb->cpb.sha256.message_bit_length)
+ memcpy(octx->state, csbcpb->cpb.sha256.message_digest,
+ SHA256_DIGEST_SIZE);
+ else {
+ octx->state[0] = SHA256_H0;
+ octx->state[1] = SHA256_H1;
+ octx->state[2] = SHA256_H2;
+ octx->state[3] = SHA256_H3;
+ octx->state[4] = SHA256_H4;
+ octx->state[5] = SHA256_H5;
+ octx->state[6] = SHA256_H6;
+ octx->state[7] = SHA256_H7;
+ }
+
+ return 0;
+}
+
+static int nx_sha256_import(struct shash_desc *desc, const void *in)
+{
+ struct sha256_state *sctx = shash_desc_ctx(desc);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
+ const struct sha256_state *ictx = in;
+
+ memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf));
+
+ sctx->count = ictx->count & 0x3f;
+ csbcpb->cpb.sha256.message_bit_length = (ictx->count & ~0x3f) * 8;
+
+ if (csbcpb->cpb.sha256.message_bit_length) {
+ memcpy(csbcpb->cpb.sha256.message_digest, ictx->state,
+ SHA256_DIGEST_SIZE);
+
+ NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
+ NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
+ }
+
+ return 0;
+}
+
+struct shash_alg nx_shash_sha256_alg = {
+ .digestsize = SHA256_DIGEST_SIZE,
+ .init = nx_sha256_init,
+ .update = nx_sha256_update,
+ .final = nx_sha256_final,
+ .export = nx_sha256_export,
+ .import = nx_sha256_import,
+ .descsize = sizeof(struct sha256_state),
+ .statesize = sizeof(struct sha256_state),
+ .base = {
+ .cra_name = "sha256",
+ .cra_driver_name = "sha256-nx",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ .cra_ctxsize = sizeof(struct nx_crypto_ctx),
+ .cra_init = nx_crypto_ctx_sha_init,
+ .cra_exit = nx_crypto_ctx_exit,
+ }
+};
diff --git a/drivers/crypto/nx/nx-sha512.c b/drivers/crypto/nx/nx-sha512.c
new file mode 100644
index 000000000000..3177b8c3d5f1
--- /dev/null
+++ b/drivers/crypto/nx/nx-sha512.c
@@ -0,0 +1,265 @@
+/**
+ * SHA-512 routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2011-2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * 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.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/internal/hash.h>
+#include <crypto/sha.h>
+#include <linux/module.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+static int nx_sha512_init(struct shash_desc *desc)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_sg *out_sg;
+
+ nx_ctx_init(nx_ctx, HCOP_FC_SHA);
+
+ memset(sctx, 0, sizeof *sctx);
+
+ nx_ctx->ap = &nx_ctx->props[NX_PROPS_SHA512];
+
+ NX_CPB_SET_DIGEST_SIZE(nx_ctx->csbcpb, NX_DS_SHA512);
+ out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
+ SHA512_DIGEST_SIZE, nx_ctx->ap->sglen);
+ nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
+
+ return 0;
+}
+
+static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
+ struct nx_sg *in_sg;
+ u64 to_process, leftover, spbc_bits;
+ int rc = 0;
+
+ if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
+ /* we've hit the nx chip previously and we're updating again,
+ * so copy over the partial digest */
+ memcpy(csbcpb->cpb.sha512.input_partial_digest,
+ csbcpb->cpb.sha512.message_digest, SHA512_DIGEST_SIZE);
+ }
+
+ /* 2 cases for total data len:
+ * 1: <= SHA512_BLOCK_SIZE: copy into state, return 0
+ * 2: > SHA512_BLOCK_SIZE: process X blocks, copy in leftover
+ */
+ if ((u64)len + sctx->count[0] <= SHA512_BLOCK_SIZE) {
+ memcpy(sctx->buf + sctx->count[0], data, len);
+ sctx->count[0] += len;
+ goto out;
+ }
+
+ /* to_process: the SHA512_BLOCK_SIZE data chunk to process in this
+ * update */
+ to_process = (sctx->count[0] + len) & ~(SHA512_BLOCK_SIZE - 1);
+ leftover = (sctx->count[0] + len) & (SHA512_BLOCK_SIZE - 1);
+
+ if (sctx->count[0]) {
+ in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)sctx->buf,
+ sctx->count[0], nx_ctx->ap->sglen);
+ in_sg = nx_build_sg_list(in_sg, (u8 *)data,
+ to_process - sctx->count[0],
+ nx_ctx->ap->sglen);
+ nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
+ sizeof(struct nx_sg);
+ } else {
+ in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)data,
+ to_process, nx_ctx->ap->sglen);
+ nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
+ sizeof(struct nx_sg);
+ }
+
+ NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
+
+ if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
+ desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto out;
+
+ atomic_inc(&(nx_ctx->stats->sha512_ops));
+
+ /* copy the leftover back into the state struct */
+ memcpy(sctx->buf, data + len - leftover, leftover);
+ sctx->count[0] = leftover;
+
+ spbc_bits = csbcpb->cpb.sha512.spbc * 8;
+ csbcpb->cpb.sha512.message_bit_length_lo += spbc_bits;
+ if (csbcpb->cpb.sha512.message_bit_length_lo < spbc_bits)
+ csbcpb->cpb.sha512.message_bit_length_hi++;
+
+ /* everything after the first update is continuation */
+ NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
+out:
+ return rc;
+}
+
+static int nx_sha512_final(struct shash_desc *desc, u8 *out)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
+ struct nx_sg *in_sg, *out_sg;
+ u64 count0;
+ int rc;
+
+ if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
+ /* we've hit the nx chip previously, now we're finalizing,
+ * so copy over the partial digest */
+ memcpy(csbcpb->cpb.sha512.input_partial_digest,
+ csbcpb->cpb.sha512.message_digest, SHA512_DIGEST_SIZE);
+ }
+
+ /* final is represented by continuing the operation and indicating that
+ * this is not an intermediate operation */
+ NX_CPB_FDM(csbcpb) &= ~NX_FDM_INTERMEDIATE;
+
+ count0 = sctx->count[0] * 8;
+
+ csbcpb->cpb.sha512.message_bit_length_lo += count0;
+ if (csbcpb->cpb.sha512.message_bit_length_lo < count0)
+ csbcpb->cpb.sha512.message_bit_length_hi++;
+
+ in_sg = nx_build_sg_list(nx_ctx->in_sg, sctx->buf, sctx->count[0],
+ nx_ctx->ap->sglen);
+ out_sg = nx_build_sg_list(nx_ctx->out_sg, out, SHA512_DIGEST_SIZE,
+ nx_ctx->ap->sglen);
+ nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
+ nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
+
+ if (!nx_ctx->op.outlen) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
+ desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (rc)
+ goto out;
+
+ atomic_inc(&(nx_ctx->stats->sha512_ops));
+ atomic64_add(csbcpb->cpb.sha512.message_bit_length_lo,
+ &(nx_ctx->stats->sha512_bytes));
+
+ memcpy(out, csbcpb->cpb.sha512.message_digest, SHA512_DIGEST_SIZE);
+out:
+ return rc;
+}
+
+static int nx_sha512_export(struct shash_desc *desc, void *out)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
+ struct sha512_state *octx = out;
+
+ /* move message_bit_length (128 bits) into count and convert its value
+ * to bytes */
+ octx->count[0] = csbcpb->cpb.sha512.message_bit_length_lo >> 3 |
+ ((csbcpb->cpb.sha512.message_bit_length_hi & 7) << 61);
+ octx->count[1] = csbcpb->cpb.sha512.message_bit_length_hi >> 3;
+
+ octx->count[0] += sctx->count[0];
+ if (octx->count[0] < sctx->count[0])
+ octx->count[1]++;
+
+ memcpy(octx->buf, sctx->buf, sizeof(octx->buf));
+
+ /* if no data has been processed yet, we need to export SHA512's
+ * initial data, in case this context gets imported into a software
+ * context */
+ if (csbcpb->cpb.sha512.message_bit_length_hi ||
+ csbcpb->cpb.sha512.message_bit_length_lo)
+ memcpy(octx->state, csbcpb->cpb.sha512.message_digest,
+ SHA512_DIGEST_SIZE);
+ else {
+ octx->state[0] = SHA512_H0;
+ octx->state[1] = SHA512_H1;
+ octx->state[2] = SHA512_H2;
+ octx->state[3] = SHA512_H3;
+ octx->state[4] = SHA512_H4;
+ octx->state[5] = SHA512_H5;
+ octx->state[6] = SHA512_H6;
+ octx->state[7] = SHA512_H7;
+ }
+
+ return 0;
+}
+
+static int nx_sha512_import(struct shash_desc *desc, const void *in)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
+ struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
+ const struct sha512_state *ictx = in;
+
+ memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf));
+ sctx->count[0] = ictx->count[0] & 0x3f;
+ csbcpb->cpb.sha512.message_bit_length_lo = (ictx->count[0] & ~0x3f)
+ << 3;
+ csbcpb->cpb.sha512.message_bit_length_hi = ictx->count[1] << 3 |
+ ictx->count[0] >> 61;
+
+ if (csbcpb->cpb.sha512.message_bit_length_hi ||
+ csbcpb->cpb.sha512.message_bit_length_lo) {
+ memcpy(csbcpb->cpb.sha512.message_digest, ictx->state,
+ SHA512_DIGEST_SIZE);
+
+ NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
+ NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
+ }
+
+ return 0;
+}
+
+struct shash_alg nx_shash_sha512_alg = {
+ .digestsize = SHA512_DIGEST_SIZE,
+ .init = nx_sha512_init,
+ .update = nx_sha512_update,
+ .final = nx_sha512_final,
+ .export = nx_sha512_export,
+ .import = nx_sha512_import,
+ .descsize = sizeof(struct sha512_state),
+ .statesize = sizeof(struct sha512_state),
+ .base = {
+ .cra_name = "sha512",
+ .cra_driver_name = "sha512-nx",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA512_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ .cra_ctxsize = sizeof(struct nx_crypto_ctx),
+ .cra_init = nx_crypto_ctx_sha_init,
+ .cra_exit = nx_crypto_ctx_exit,
+ }
+};
diff --git a/drivers/crypto/nx/nx.c b/drivers/crypto/nx/nx.c
new file mode 100644
index 000000000000..d7f179cc2e98
--- /dev/null
+++ b/drivers/crypto/nx/nx.c
@@ -0,0 +1,716 @@
+/**
+ * Routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2011-2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * 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.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/internal/hash.h>
+#include <crypto/hash.h>
+#include <crypto/aes.h>
+#include <crypto/sha.h>
+#include <crypto/algapi.h>
+#include <crypto/scatterwalk.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <asm/pSeries_reconfig.h>
+#include <asm/abs_addr.h>
+#include <asm/hvcall.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+/**
+ * nx_hcall_sync - make an H_COP_OP hcall for the passed in op structure
+ *
+ * @nx_ctx: the crypto context handle
+ * @op: PFO operation struct to pass in
+ * @may_sleep: flag indicating the request can sleep
+ *
+ * Make the hcall, retrying while the hardware is busy. If we cannot yield
+ * the thread, limit the number of retries to 10 here.
+ */
+int nx_hcall_sync(struct nx_crypto_ctx *nx_ctx,
+ struct vio_pfo_op *op,
+ u32 may_sleep)
+{
+ int rc, retries = 10;
+ struct vio_dev *viodev = nx_driver.viodev;
+
+ atomic_inc(&(nx_ctx->stats->sync_ops));
+
+ do {
+ rc = vio_h_cop_sync(viodev, op);
+ } while ((rc == -EBUSY && !may_sleep && retries--) ||
+ (rc == -EBUSY && may_sleep && cond_resched()));
+
+ if (rc) {
+ dev_dbg(&viodev->dev, "vio_h_cop_sync failed: rc: %d "
+ "hcall rc: %ld\n", rc, op->hcall_err);
+ atomic_inc(&(nx_ctx->stats->errors));
+ atomic_set(&(nx_ctx->stats->last_error), op->hcall_err);
+ atomic_set(&(nx_ctx->stats->last_error_pid), current->pid);
+ }
+
+ return rc;
+}
+
+/**
+ * nx_build_sg_list - build an NX scatter list describing a single buffer
+ *
+ * @sg_head: pointer to the first scatter list element to build
+ * @start_addr: pointer to the linear buffer
+ * @len: length of the data at @start_addr
+ * @sgmax: the largest number of scatter list elements we're allowed to create
+ *
+ * This function will start writing nx_sg elements at @sg_head and keep
+ * writing them until all of the data from @start_addr is described or
+ * until sgmax elements have been written. Scatter list elements will be
+ * created such that none of the elements describes a buffer that crosses a 4K
+ * boundary.
+ */
+struct nx_sg *nx_build_sg_list(struct nx_sg *sg_head,
+ u8 *start_addr,
+ unsigned int len,
+ u32 sgmax)
+{
+ unsigned int sg_len = 0;
+ struct nx_sg *sg;
+ u64 sg_addr = (u64)start_addr;
+ u64 end_addr;
+
+ /* determine the start and end for this address range - slightly
+ * different if this is in VMALLOC_REGION */
+ if (is_vmalloc_addr(start_addr))
+ sg_addr = phys_to_abs(page_to_phys(vmalloc_to_page(start_addr)))
+ + offset_in_page(sg_addr);
+ else
+ sg_addr = virt_to_abs(sg_addr);
+
+ end_addr = sg_addr + len;
+
+ /* each iteration will write one struct nx_sg element and add the
+ * length of data described by that element to sg_len. Once @len bytes
+ * have been described (or @sgmax elements have been written), the
+ * loop ends. min_t is used to ensure @end_addr falls on the same page
+ * as sg_addr, if not, we need to create another nx_sg element for the
+ * data on the next page */
+ for (sg = sg_head; sg_len < len; sg++) {
+ sg->addr = sg_addr;
+ sg_addr = min_t(u64, NX_PAGE_NUM(sg_addr + NX_PAGE_SIZE), end_addr);
+ sg->len = sg_addr - sg->addr;
+ sg_len += sg->len;
+
+ if ((sg - sg_head) == sgmax) {
+ pr_err("nx: scatter/gather list overflow, pid: %d\n",
+ current->pid);
+ return NULL;
+ }
+ }
+
+ /* return the moved sg_head pointer */
+ return sg;
+}
+
+/**
+ * nx_walk_and_build - walk a linux scatterlist and build an nx scatterlist
+ *
+ * @nx_dst: pointer to the first nx_sg element to write
+ * @sglen: max number of nx_sg entries we're allowed to write
+ * @sg_src: pointer to the source linux scatterlist to walk
+ * @start: number of bytes to fast-forward past at the beginning of @sg_src
+ * @src_len: number of bytes to walk in @sg_src
+ */
+struct nx_sg *nx_walk_and_build(struct nx_sg *nx_dst,
+ unsigned int sglen,
+ struct scatterlist *sg_src,
+ unsigned int start,
+ unsigned int src_len)
+{
+ struct scatter_walk walk;
+ struct nx_sg *nx_sg = nx_dst;
+ unsigned int n, offset = 0, len = src_len;
+ char *dst;
+
+ /* we need to fast forward through @start bytes first */
+ for (;;) {
+ scatterwalk_start(&walk, sg_src);
+
+ if (start < offset + sg_src->length)
+ break;
+
+ offset += sg_src->length;
+ sg_src = scatterwalk_sg_next(sg_src);
+ }
+
+ /* start - offset is the number of bytes to advance in the scatterlist
+ * element we're currently looking at */
+ scatterwalk_advance(&walk, start - offset);
+
+ while (len && nx_sg) {
+ n = scatterwalk_clamp(&walk, len);
+ if (!n) {
+ scatterwalk_start(&walk, sg_next(walk.sg));
+ n = scatterwalk_clamp(&walk, len);
+ }
+ dst = scatterwalk_map(&walk);
+
+ nx_sg = nx_build_sg_list(nx_sg, dst, n, sglen);
+ len -= n;
+
+ scatterwalk_unmap(dst);
+ scatterwalk_advance(&walk, n);
+ scatterwalk_done(&walk, SCATTERWALK_FROM_SG, len);
+ }
+
+ /* return the moved destination pointer */
+ return nx_sg;
+}
+
+/**
+ * nx_build_sg_lists - walk the input scatterlists and build arrays of NX
+ * scatterlists based on them.
+ *
+ * @nx_ctx: NX crypto context for the lists we're building
+ * @desc: the block cipher descriptor for the operation
+ * @dst: destination scatterlist
+ * @src: source scatterlist
+ * @nbytes: length of data described in the scatterlists
+ * @iv: destination for the iv data, if the algorithm requires it
+ *
+ * This is common code shared by all the AES algorithms. It uses the block
+ * cipher walk routines to traverse input and output scatterlists, building
+ * corresponding NX scatterlists
+ */
+int nx_build_sg_lists(struct nx_crypto_ctx *nx_ctx,
+ struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes,
+ u8 *iv)
+{
+ struct nx_sg *nx_insg = nx_ctx->in_sg;
+ struct nx_sg *nx_outsg = nx_ctx->out_sg;
+ struct blkcipher_walk walk;
+ int rc;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ rc = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);
+ if (rc)
+ goto out;
+
+ if (iv)
+ memcpy(iv, walk.iv, AES_BLOCK_SIZE);
+
+ while (walk.nbytes) {
+ nx_insg = nx_build_sg_list(nx_insg, walk.src.virt.addr,
+ walk.nbytes, nx_ctx->ap->sglen);
+ nx_outsg = nx_build_sg_list(nx_outsg, walk.dst.virt.addr,
+ walk.nbytes, nx_ctx->ap->sglen);
+
+ rc = blkcipher_walk_done(desc, &walk, 0);
+ if (rc)
+ break;
+ }
+
+ if (walk.nbytes) {
+ nx_insg = nx_build_sg_list(nx_insg, walk.src.virt.addr,
+ walk.nbytes, nx_ctx->ap->sglen);
+ nx_outsg = nx_build_sg_list(nx_outsg, walk.dst.virt.addr,
+ walk.nbytes, nx_ctx->ap->sglen);
+
+ rc = 0;
+ }
+
+ /* these lengths should be negative, which will indicate to phyp that
+ * the input and output parameters are scatterlists, not linear
+ * buffers */
+ nx_ctx->op.inlen = (nx_ctx->in_sg - nx_insg) * sizeof(struct nx_sg);
+ nx_ctx->op.outlen = (nx_ctx->out_sg - nx_outsg) * sizeof(struct nx_sg);
+out:
+ return rc;
+}
+
+/**
+ * nx_ctx_init - initialize an nx_ctx's vio_pfo_op struct
+ *
+ * @nx_ctx: the nx context to initialize
+ * @function: the function code for the op
+ */
+void nx_ctx_init(struct nx_crypto_ctx *nx_ctx, unsigned int function)
+{
+ memset(nx_ctx->kmem, 0, nx_ctx->kmem_len);
+ nx_ctx->csbcpb->csb.valid |= NX_CSB_VALID_BIT;
+
+ nx_ctx->op.flags = function;
+ nx_ctx->op.csbcpb = virt_to_abs(nx_ctx->csbcpb);
+ nx_ctx->op.in = virt_to_abs(nx_ctx->in_sg);
+ nx_ctx->op.out = virt_to_abs(nx_ctx->out_sg);
+
+ if (nx_ctx->csbcpb_aead) {
+ nx_ctx->csbcpb_aead->csb.valid |= NX_CSB_VALID_BIT;
+
+ nx_ctx->op_aead.flags = function;
+ nx_ctx->op_aead.csbcpb = virt_to_abs(nx_ctx->csbcpb_aead);
+ nx_ctx->op_aead.in = virt_to_abs(nx_ctx->in_sg);
+ nx_ctx->op_aead.out = virt_to_abs(nx_ctx->out_sg);
+ }
+}
+
+static void nx_of_update_status(struct device *dev,
+ struct property *p,
+ struct nx_of *props)
+{
+ if (!strncmp(p->value, "okay", p->length)) {
+ props->status = NX_WAITING;
+ props->flags |= NX_OF_FLAG_STATUS_SET;
+ } else {
+ dev_info(dev, "%s: status '%s' is not 'okay'\n", __func__,
+ (char *)p->value);
+ }
+}
+
+static void nx_of_update_sglen(struct device *dev,
+ struct property *p,
+ struct nx_of *props)
+{
+ if (p->length != sizeof(props->max_sg_len)) {
+ dev_err(dev, "%s: unexpected format for "
+ "ibm,max-sg-len property\n", __func__);
+ dev_dbg(dev, "%s: ibm,max-sg-len is %d bytes "
+ "long, expected %zd bytes\n", __func__,
+ p->length, sizeof(props->max_sg_len));
+ return;
+ }
+
+ props->max_sg_len = *(u32 *)p->value;
+ props->flags |= NX_OF_FLAG_MAXSGLEN_SET;
+}
+
+static void nx_of_update_msc(struct device *dev,
+ struct property *p,
+ struct nx_of *props)
+{
+ struct msc_triplet *trip;
+ struct max_sync_cop *msc;
+ unsigned int bytes_so_far, i, lenp;
+
+ msc = (struct max_sync_cop *)p->value;
+ lenp = p->length;
+
+ /* You can't tell if the data read in for this property is sane by its
+ * size alone. This is because there are sizes embedded in the data
+ * structure. The best we can do is check lengths as we parse and bail
+ * as soon as a length error is detected. */
+ bytes_so_far = 0;
+
+ while ((bytes_so_far + sizeof(struct max_sync_cop)) <= lenp) {
+ bytes_so_far += sizeof(struct max_sync_cop);
+
+ trip = msc->trip;
+
+ for (i = 0;
+ ((bytes_so_far + sizeof(struct msc_triplet)) <= lenp) &&
+ i < msc->triplets;
+ i++) {
+ if (msc->fc > NX_MAX_FC || msc->mode > NX_MAX_MODE) {
+ dev_err(dev, "unknown function code/mode "
+ "combo: %d/%d (ignored)\n", msc->fc,
+ msc->mode);
+ goto next_loop;
+ }
+
+ switch (trip->keybitlen) {
+ case 128:
+ case 160:
+ props->ap[msc->fc][msc->mode][0].databytelen =
+ trip->databytelen;
+ props->ap[msc->fc][msc->mode][0].sglen =
+ trip->sglen;
+ break;
+ case 192:
+ props->ap[msc->fc][msc->mode][1].databytelen =
+ trip->databytelen;
+ props->ap[msc->fc][msc->mode][1].sglen =
+ trip->sglen;
+ break;
+ case 256:
+ if (msc->fc == NX_FC_AES) {
+ props->ap[msc->fc][msc->mode][2].
+ databytelen = trip->databytelen;
+ props->ap[msc->fc][msc->mode][2].sglen =
+ trip->sglen;
+ } else if (msc->fc == NX_FC_AES_HMAC ||
+ msc->fc == NX_FC_SHA) {
+ props->ap[msc->fc][msc->mode][1].
+ databytelen = trip->databytelen;
+ props->ap[msc->fc][msc->mode][1].sglen =
+ trip->sglen;
+ } else {
+ dev_warn(dev, "unknown function "
+ "code/key bit len combo"
+ ": (%u/256)\n", msc->fc);
+ }
+ break;
+ case 512:
+ props->ap[msc->fc][msc->mode][2].databytelen =
+ trip->databytelen;
+ props->ap[msc->fc][msc->mode][2].sglen =
+ trip->sglen;
+ break;
+ default:
+ dev_warn(dev, "unknown function code/key bit "
+ "len combo: (%u/%u)\n", msc->fc,
+ trip->keybitlen);
+ break;
+ }
+next_loop:
+ bytes_so_far += sizeof(struct msc_triplet);
+ trip++;
+ }
+
+ msc = (struct max_sync_cop *)trip;
+ }
+
+ props->flags |= NX_OF_FLAG_MAXSYNCCOP_SET;
+}
+
+/**
+ * nx_of_init - read openFirmware values from the device tree
+ *
+ * @dev: device handle
+ * @props: pointer to struct to hold the properties values
+ *
+ * Called once at driver probe time, this function will read out the
+ * openFirmware properties we use at runtime. If all the OF properties are
+ * acceptable, when we exit this function props->flags will indicate that
+ * we're ready to register our crypto algorithms.
+ */
+static void nx_of_init(struct device *dev, struct nx_of *props)
+{
+ struct device_node *base_node = dev->of_node;
+ struct property *p;
+
+ p = of_find_property(base_node, "status", NULL);
+ if (!p)
+ dev_info(dev, "%s: property 'status' not found\n", __func__);
+ else
+ nx_of_update_status(dev, p, props);
+
+ p = of_find_property(base_node, "ibm,max-sg-len", NULL);
+ if (!p)
+ dev_info(dev, "%s: property 'ibm,max-sg-len' not found\n",
+ __func__);
+ else
+ nx_of_update_sglen(dev, p, props);
+
+ p = of_find_property(base_node, "ibm,max-sync-cop", NULL);
+ if (!p)
+ dev_info(dev, "%s: property 'ibm,max-sync-cop' not found\n",
+ __func__);
+ else
+ nx_of_update_msc(dev, p, props);
+}
+
+/**
+ * nx_register_algs - register algorithms with the crypto API
+ *
+ * Called from nx_probe()
+ *
+ * If all OF properties are in an acceptable state, the driver flags will
+ * indicate that we're ready and we'll create our debugfs files and register
+ * out crypto algorithms.
+ */
+static int nx_register_algs(void)
+{
+ int rc = -1;
+
+ if (nx_driver.of.flags != NX_OF_FLAG_MASK_READY)
+ goto out;
+
+ memset(&nx_driver.stats, 0, sizeof(struct nx_stats));
+
+ rc = NX_DEBUGFS_INIT(&nx_driver);
+ if (rc)
+ goto out;
+
+ rc = crypto_register_alg(&nx_ecb_aes_alg);
+ if (rc)
+ goto out;
+
+ rc = crypto_register_alg(&nx_cbc_aes_alg);
+ if (rc)
+ goto out_unreg_ecb;
+
+ rc = crypto_register_alg(&nx_ctr_aes_alg);
+ if (rc)
+ goto out_unreg_cbc;
+
+ rc = crypto_register_alg(&nx_ctr3686_aes_alg);
+ if (rc)
+ goto out_unreg_ctr;
+
+ rc = crypto_register_alg(&nx_gcm_aes_alg);
+ if (rc)
+ goto out_unreg_ctr3686;
+
+ rc = crypto_register_alg(&nx_gcm4106_aes_alg);
+ if (rc)
+ goto out_unreg_gcm;
+
+ rc = crypto_register_alg(&nx_ccm_aes_alg);
+ if (rc)
+ goto out_unreg_gcm4106;
+
+ rc = crypto_register_alg(&nx_ccm4309_aes_alg);
+ if (rc)
+ goto out_unreg_ccm;
+
+ rc = crypto_register_shash(&nx_shash_sha256_alg);
+ if (rc)
+ goto out_unreg_ccm4309;
+
+ rc = crypto_register_shash(&nx_shash_sha512_alg);
+ if (rc)
+ goto out_unreg_s256;
+
+ rc = crypto_register_shash(&nx_shash_aes_xcbc_alg);
+ if (rc)
+ goto out_unreg_s512;
+
+ nx_driver.of.status = NX_OKAY;
+
+ goto out;
+
+out_unreg_s512:
+ crypto_unregister_shash(&nx_shash_sha512_alg);
+out_unreg_s256:
+ crypto_unregister_shash(&nx_shash_sha256_alg);
+out_unreg_ccm4309:
+ crypto_unregister_alg(&nx_ccm4309_aes_alg);
+out_unreg_ccm:
+ crypto_unregister_alg(&nx_ccm_aes_alg);
+out_unreg_gcm4106:
+ crypto_unregister_alg(&nx_gcm4106_aes_alg);
+out_unreg_gcm:
+ crypto_unregister_alg(&nx_gcm_aes_alg);
+out_unreg_ctr3686:
+ crypto_unregister_alg(&nx_ctr3686_aes_alg);
+out_unreg_ctr:
+ crypto_unregister_alg(&nx_ctr_aes_alg);
+out_unreg_cbc:
+ crypto_unregister_alg(&nx_cbc_aes_alg);
+out_unreg_ecb:
+ crypto_unregister_alg(&nx_ecb_aes_alg);
+out:
+ return rc;
+}
+
+/**
+ * nx_crypto_ctx_init - create and initialize a crypto api context
+ *
+ * @nx_ctx: the crypto api context
+ * @fc: function code for the context
+ * @mode: the function code specific mode for this context
+ */
+static int nx_crypto_ctx_init(struct nx_crypto_ctx *nx_ctx, u32 fc, u32 mode)
+{
+ if (nx_driver.of.status != NX_OKAY) {
+ pr_err("Attempt to initialize NX crypto context while device "
+ "is not available!\n");
+ return -ENODEV;
+ }
+
+ /* we need an extra page for csbcpb_aead for these modes */
+ if (mode == NX_MODE_AES_GCM || mode == NX_MODE_AES_CCM)
+ nx_ctx->kmem_len = (4 * NX_PAGE_SIZE) +
+ sizeof(struct nx_csbcpb);
+ else
+ nx_ctx->kmem_len = (3 * NX_PAGE_SIZE) +
+ sizeof(struct nx_csbcpb);
+
+ nx_ctx->kmem = kmalloc(nx_ctx->kmem_len, GFP_KERNEL);
+ if (!nx_ctx->kmem)
+ return -ENOMEM;
+
+ /* the csbcpb and scatterlists must be 4K aligned pages */
+ nx_ctx->csbcpb = (struct nx_csbcpb *)(round_up((u64)nx_ctx->kmem,
+ (u64)NX_PAGE_SIZE));
+ nx_ctx->in_sg = (struct nx_sg *)((u8 *)nx_ctx->csbcpb + NX_PAGE_SIZE);
+ nx_ctx->out_sg = (struct nx_sg *)((u8 *)nx_ctx->in_sg + NX_PAGE_SIZE);
+
+ if (mode == NX_MODE_AES_GCM || mode == NX_MODE_AES_CCM)
+ nx_ctx->csbcpb_aead =
+ (struct nx_csbcpb *)((u8 *)nx_ctx->out_sg +
+ NX_PAGE_SIZE);
+
+ /* give each context a pointer to global stats and their OF
+ * properties */
+ nx_ctx->stats = &nx_driver.stats;
+ memcpy(nx_ctx->props, nx_driver.of.ap[fc][mode],
+ sizeof(struct alg_props) * 3);
+
+ return 0;
+}
+
+/* entry points from the crypto tfm initializers */
+int nx_crypto_ctx_aes_ccm_init(struct crypto_tfm *tfm)
+{
+ return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
+ NX_MODE_AES_CCM);
+}
+
+int nx_crypto_ctx_aes_gcm_init(struct crypto_tfm *tfm)
+{
+ return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
+ NX_MODE_AES_GCM);
+}
+
+int nx_crypto_ctx_aes_ctr_init(struct crypto_tfm *tfm)
+{
+ return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
+ NX_MODE_AES_CTR);
+}
+
+int nx_crypto_ctx_aes_cbc_init(struct crypto_tfm *tfm)
+{
+ return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
+ NX_MODE_AES_CBC);
+}
+
+int nx_crypto_ctx_aes_ecb_init(struct crypto_tfm *tfm)
+{
+ return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
+ NX_MODE_AES_ECB);
+}
+
+int nx_crypto_ctx_sha_init(struct crypto_tfm *tfm)
+{
+ return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_SHA, NX_MODE_SHA);
+}
+
+int nx_crypto_ctx_aes_xcbc_init(struct crypto_tfm *tfm)
+{
+ return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
+ NX_MODE_AES_XCBC_MAC);
+}
+
+/**
+ * nx_crypto_ctx_exit - destroy a crypto api context
+ *
+ * @tfm: the crypto transform pointer for the context
+ *
+ * As crypto API contexts are destroyed, this exit hook is called to free the
+ * memory associated with it.
+ */
+void nx_crypto_ctx_exit(struct crypto_tfm *tfm)
+{
+ struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
+
+ kzfree(nx_ctx->kmem);
+ nx_ctx->csbcpb = NULL;
+ nx_ctx->csbcpb_aead = NULL;
+ nx_ctx->in_sg = NULL;
+ nx_ctx->out_sg = NULL;
+}
+
+static int __devinit nx_probe(struct vio_dev *viodev,
+ const struct vio_device_id *id)
+{
+ dev_dbg(&viodev->dev, "driver probed: %s resource id: 0x%x\n",
+ viodev->name, viodev->resource_id);
+
+ if (nx_driver.viodev) {
+ dev_err(&viodev->dev, "%s: Attempt to register more than one "
+ "instance of the hardware\n", __func__);
+ return -EINVAL;
+ }
+
+ nx_driver.viodev = viodev;
+
+ nx_of_init(&viodev->dev, &nx_driver.of);
+
+ return nx_register_algs();
+}
+
+static int __devexit nx_remove(struct vio_dev *viodev)
+{
+ dev_dbg(&viodev->dev, "entering nx_remove for UA 0x%x\n",
+ viodev->unit_address);
+
+ if (nx_driver.of.status == NX_OKAY) {
+ NX_DEBUGFS_FINI(&nx_driver);
+
+ crypto_unregister_alg(&nx_ccm_aes_alg);
+ crypto_unregister_alg(&nx_ccm4309_aes_alg);
+ crypto_unregister_alg(&nx_gcm_aes_alg);
+ crypto_unregister_alg(&nx_gcm4106_aes_alg);
+ crypto_unregister_alg(&nx_ctr_aes_alg);
+ crypto_unregister_alg(&nx_ctr3686_aes_alg);
+ crypto_unregister_alg(&nx_cbc_aes_alg);
+ crypto_unregister_alg(&nx_ecb_aes_alg);
+ crypto_unregister_shash(&nx_shash_sha256_alg);
+ crypto_unregister_shash(&nx_shash_sha512_alg);
+ crypto_unregister_shash(&nx_shash_aes_xcbc_alg);
+ }
+
+ return 0;
+}
+
+
+/* module wide initialization/cleanup */
+static int __init nx_init(void)
+{
+ return vio_register_driver(&nx_driver.viodriver);
+}
+
+static void __exit nx_fini(void)
+{
+ vio_unregister_driver(&nx_driver.viodriver);
+}
+
+static struct vio_device_id nx_crypto_driver_ids[] __devinitdata = {
+ { "ibm,sym-encryption-v1", "ibm,sym-encryption" },
+ { "", "" }
+};
+MODULE_DEVICE_TABLE(vio, nx_crypto_driver_ids);
+
+/* driver state structure */
+struct nx_crypto_driver nx_driver = {
+ .viodriver = {
+ .id_table = nx_crypto_driver_ids,
+ .probe = nx_probe,
+ .remove = nx_remove,
+ .name = NX_NAME,
+ },
+};
+
+module_init(nx_init);
+module_exit(nx_fini);
+
+MODULE_AUTHOR("Kent Yoder <yoder1@us.ibm.com>");
+MODULE_DESCRIPTION(NX_STRING);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(NX_VERSION);
diff --git a/drivers/crypto/nx/nx.h b/drivers/crypto/nx/nx.h
new file mode 100644
index 000000000000..3232b182dd28
--- /dev/null
+++ b/drivers/crypto/nx/nx.h
@@ -0,0 +1,193 @@
+
+#ifndef __NX_H__
+#define __NX_H__
+
+#define NX_NAME "nx-crypto"
+#define NX_STRING "IBM Power7+ Nest Accelerator Crypto Driver"
+#define NX_VERSION "1.0"
+
+static const char nx_driver_string[] = NX_STRING;
+static const char nx_driver_version[] = NX_VERSION;
+
+/* a scatterlist in the format PHYP is expecting */
+struct nx_sg {
+ u64 addr;
+ u32 rsvd;
+ u32 len;
+} __attribute((packed));
+
+#define NX_PAGE_SIZE (4096)
+#define NX_MAX_SG_ENTRIES (NX_PAGE_SIZE/(sizeof(struct nx_sg)))
+
+enum nx_status {
+ NX_DISABLED,
+ NX_WAITING,
+ NX_OKAY
+};
+
+/* msc_triplet and max_sync_cop are used only to assist in parsing the
+ * openFirmware property */
+struct msc_triplet {
+ u32 keybitlen;
+ u32 databytelen;
+ u32 sglen;
+} __packed;
+
+struct max_sync_cop {
+ u32 fc;
+ u32 mode;
+ u32 triplets;
+ struct msc_triplet trip[0];
+} __packed;
+
+struct alg_props {
+ u32 databytelen;
+ u32 sglen;
+};
+
+#define NX_OF_FLAG_MAXSGLEN_SET (1)
+#define NX_OF_FLAG_STATUS_SET (2)
+#define NX_OF_FLAG_MAXSYNCCOP_SET (4)
+#define NX_OF_FLAG_MASK_READY (NX_OF_FLAG_MAXSGLEN_SET | \
+ NX_OF_FLAG_STATUS_SET | \
+ NX_OF_FLAG_MAXSYNCCOP_SET)
+struct nx_of {
+ u32 flags;
+ u32 max_sg_len;
+ enum nx_status status;
+ struct alg_props ap[NX_MAX_FC][NX_MAX_MODE][3];
+};
+
+struct nx_stats {
+ atomic_t aes_ops;
+ atomic64_t aes_bytes;
+ atomic_t sha256_ops;
+ atomic64_t sha256_bytes;
+ atomic_t sha512_ops;
+ atomic64_t sha512_bytes;
+
+ atomic_t sync_ops;
+
+ atomic_t errors;
+ atomic_t last_error;
+ atomic_t last_error_pid;
+};
+
+struct nx_debugfs {
+ struct dentry *dfs_root;
+ struct dentry *dfs_aes_ops, *dfs_aes_bytes;
+ struct dentry *dfs_sha256_ops, *dfs_sha256_bytes;
+ struct dentry *dfs_sha512_ops, *dfs_sha512_bytes;
+ struct dentry *dfs_errors, *dfs_last_error, *dfs_last_error_pid;
+};
+
+struct nx_crypto_driver {
+ struct nx_stats stats;
+ struct nx_of of;
+ struct vio_dev *viodev;
+ struct vio_driver viodriver;
+ struct nx_debugfs dfs;
+};
+
+#define NX_GCM4106_NONCE_LEN (4)
+#define NX_GCM_CTR_OFFSET (12)
+struct nx_gcm_priv {
+ u8 iv[16];
+ u8 iauth_tag[16];
+ u8 nonce[NX_GCM4106_NONCE_LEN];
+};
+
+#define NX_CCM_AES_KEY_LEN (16)
+#define NX_CCM4309_AES_KEY_LEN (19)
+#define NX_CCM4309_NONCE_LEN (3)
+struct nx_ccm_priv {
+ u8 iv[16];
+ u8 b0[16];
+ u8 iauth_tag[16];
+ u8 oauth_tag[16];
+ u8 nonce[NX_CCM4309_NONCE_LEN];
+};
+
+struct nx_xcbc_priv {
+ u8 key[16];
+};
+
+struct nx_ctr_priv {
+ u8 iv[16];
+};
+
+struct nx_crypto_ctx {
+ void *kmem; /* unaligned, kmalloc'd buffer */
+ size_t kmem_len; /* length of kmem */
+ struct nx_csbcpb *csbcpb; /* aligned page given to phyp @ hcall time */
+ struct vio_pfo_op op; /* operation struct with hcall parameters */
+ struct nx_csbcpb *csbcpb_aead; /* secondary csbcpb used by AEAD algs */
+ struct vio_pfo_op op_aead;/* operation struct for csbcpb_aead */
+
+ struct nx_sg *in_sg; /* aligned pointer into kmem to an sg list */
+ struct nx_sg *out_sg; /* aligned pointer into kmem to an sg list */
+
+ struct alg_props *ap; /* pointer into props based on our key size */
+ struct alg_props props[3];/* openFirmware properties for requests */
+ struct nx_stats *stats; /* pointer into an nx_crypto_driver for stats
+ reporting */
+
+ union {
+ struct nx_gcm_priv gcm;
+ struct nx_ccm_priv ccm;
+ struct nx_xcbc_priv xcbc;
+ struct nx_ctr_priv ctr;
+ } priv;
+};
+
+/* prototypes */
+int nx_crypto_ctx_aes_ccm_init(struct crypto_tfm *tfm);
+int nx_crypto_ctx_aes_gcm_init(struct crypto_tfm *tfm);
+int nx_crypto_ctx_aes_xcbc_init(struct crypto_tfm *tfm);
+int nx_crypto_ctx_aes_ctr_init(struct crypto_tfm *tfm);
+int nx_crypto_ctx_aes_cbc_init(struct crypto_tfm *tfm);
+int nx_crypto_ctx_aes_ecb_init(struct crypto_tfm *tfm);
+int nx_crypto_ctx_sha_init(struct crypto_tfm *tfm);
+void nx_crypto_ctx_exit(struct crypto_tfm *tfm);
+void nx_ctx_init(struct nx_crypto_ctx *nx_ctx, unsigned int function);
+int nx_hcall_sync(struct nx_crypto_ctx *ctx, struct vio_pfo_op *op,
+ u32 may_sleep);
+struct nx_sg *nx_build_sg_list(struct nx_sg *, u8 *, unsigned int, u32);
+int nx_build_sg_lists(struct nx_crypto_ctx *, struct blkcipher_desc *,
+ struct scatterlist *, struct scatterlist *, unsigned int,
+ u8 *);
+struct nx_sg *nx_walk_and_build(struct nx_sg *, unsigned int,
+ struct scatterlist *, unsigned int,
+ unsigned int);
+
+#ifdef CONFIG_DEBUG_FS
+#define NX_DEBUGFS_INIT(drv) nx_debugfs_init(drv)
+#define NX_DEBUGFS_FINI(drv) nx_debugfs_fini(drv)
+
+int nx_debugfs_init(struct nx_crypto_driver *);
+void nx_debugfs_fini(struct nx_crypto_driver *);
+#else
+#define NX_DEBUGFS_INIT(drv) (0)
+#define NX_DEBUGFS_FINI(drv) (0)
+#endif
+
+#define NX_PAGE_NUM(x) ((u64)(x) & 0xfffffffffffff000ULL)
+
+extern struct crypto_alg nx_cbc_aes_alg;
+extern struct crypto_alg nx_ecb_aes_alg;
+extern struct crypto_alg nx_gcm_aes_alg;
+extern struct crypto_alg nx_gcm4106_aes_alg;
+extern struct crypto_alg nx_ctr_aes_alg;
+extern struct crypto_alg nx_ctr3686_aes_alg;
+extern struct crypto_alg nx_ccm_aes_alg;
+extern struct crypto_alg nx_ccm4309_aes_alg;
+extern struct shash_alg nx_shash_aes_xcbc_alg;
+extern struct shash_alg nx_shash_sha512_alg;
+extern struct shash_alg nx_shash_sha256_alg;
+
+extern struct nx_crypto_driver nx_driver;
+
+#define SCATTERWALK_TO_SG 1
+#define SCATTERWALK_FROM_SG 0
+
+#endif
diff --git a/drivers/crypto/nx/nx_csbcpb.h b/drivers/crypto/nx/nx_csbcpb.h
new file mode 100644
index 000000000000..a304f956d6f8
--- /dev/null
+++ b/drivers/crypto/nx/nx_csbcpb.h
@@ -0,0 +1,205 @@
+
+#ifndef __NX_CSBCPB_H__
+#define __NX_CSBCPB_H__
+
+struct cop_symcpb_aes_ecb {
+ u8 key[32];
+ u8 __rsvd[80];
+} __packed;
+
+struct cop_symcpb_aes_cbc {
+ u8 iv[16];
+ u8 key[32];
+ u8 cv[16];
+ u32 spbc;
+ u8 __rsvd[44];
+} __packed;
+
+struct cop_symcpb_aes_gca {
+ u8 in_pat[16];
+ u8 key[32];
+ u8 out_pat[16];
+ u32 spbc;
+ u8 __rsvd[44];
+} __packed;
+
+struct cop_symcpb_aes_gcm {
+ u8 in_pat_or_aad[16];
+ u8 iv_or_cnt[16];
+ u64 bit_length_aad;
+ u64 bit_length_data;
+ u8 in_s0[16];
+ u8 key[32];
+ u8 __rsvd1[16];
+ u8 out_pat_or_mac[16];
+ u8 out_s0[16];
+ u8 out_cnt[16];
+ u32 spbc;
+ u8 __rsvd2[12];
+} __packed;
+
+struct cop_symcpb_aes_ctr {
+ u8 iv[16];
+ u8 key[32];
+ u8 cv[16];
+ u32 spbc;
+ u8 __rsvd2[44];
+} __packed;
+
+struct cop_symcpb_aes_cca {
+ u8 b0[16];
+ u8 b1[16];
+ u8 key[16];
+ u8 out_pat_or_b0[16];
+ u32 spbc;
+ u8 __rsvd[44];
+} __packed;
+
+struct cop_symcpb_aes_ccm {
+ u8 in_pat_or_b0[16];
+ u8 iv_or_ctr[16];
+ u8 in_s0[16];
+ u8 key[16];
+ u8 __rsvd1[48];
+ u8 out_pat_or_mac[16];
+ u8 out_s0[16];
+ u8 out_ctr[16];
+ u32 spbc;
+ u8 __rsvd2[12];
+} __packed;
+
+struct cop_symcpb_aes_xcbc {
+ u8 cv[16];
+ u8 key[16];
+ u8 __rsvd1[16];
+ u8 out_cv_mac[16];
+ u32 spbc;
+ u8 __rsvd2[44];
+} __packed;
+
+struct cop_symcpb_sha256 {
+ u64 message_bit_length;
+ u64 __rsvd1;
+ u8 input_partial_digest[32];
+ u8 message_digest[32];
+ u32 spbc;
+ u8 __rsvd2[44];
+} __packed;
+
+struct cop_symcpb_sha512 {
+ u64 message_bit_length_hi;
+ u64 message_bit_length_lo;
+ u8 input_partial_digest[64];
+ u8 __rsvd1[32];
+ u8 message_digest[64];
+ u32 spbc;
+ u8 __rsvd2[76];
+} __packed;
+
+#define NX_FDM_INTERMEDIATE 0x01
+#define NX_FDM_CONTINUATION 0x02
+#define NX_FDM_ENDE_ENCRYPT 0x80
+
+#define NX_CPB_FDM(c) ((c)->cpb.hdr.fdm)
+#define NX_CPB_KS_DS(c) ((c)->cpb.hdr.ks_ds)
+
+#define NX_CPB_KEY_SIZE(c) (NX_CPB_KS_DS(c) >> 4)
+#define NX_CPB_SET_KEY_SIZE(c, x) NX_CPB_KS_DS(c) |= ((x) << 4)
+#define NX_CPB_SET_DIGEST_SIZE(c, x) NX_CPB_KS_DS(c) |= (x)
+
+struct cop_symcpb_header {
+ u8 mode;
+ u8 fdm;
+ u8 ks_ds;
+ u8 pad_byte;
+ u8 __rsvd[12];
+} __packed;
+
+struct cop_parameter_block {
+ struct cop_symcpb_header hdr;
+ union {
+ struct cop_symcpb_aes_ecb aes_ecb;
+ struct cop_symcpb_aes_cbc aes_cbc;
+ struct cop_symcpb_aes_gca aes_gca;
+ struct cop_symcpb_aes_gcm aes_gcm;
+ struct cop_symcpb_aes_cca aes_cca;
+ struct cop_symcpb_aes_ccm aes_ccm;
+ struct cop_symcpb_aes_ctr aes_ctr;
+ struct cop_symcpb_aes_xcbc aes_xcbc;
+ struct cop_symcpb_sha256 sha256;
+ struct cop_symcpb_sha512 sha512;
+ };
+} __packed;
+
+#define NX_CSB_VALID_BIT 0x80
+
+/* co-processor status block */
+struct cop_status_block {
+ u8 valid;
+ u8 crb_seq_number;
+ u8 completion_code;
+ u8 completion_extension;
+ u32 processed_byte_count;
+ u64 address;
+} __packed;
+
+/* Nest accelerator workbook section 4.4 */
+struct nx_csbcpb {
+ unsigned char __rsvd[112];
+ struct cop_status_block csb;
+ struct cop_parameter_block cpb;
+} __packed;
+
+/* nx_csbcpb related definitions */
+#define NX_MODE_AES_ECB 0
+#define NX_MODE_AES_CBC 1
+#define NX_MODE_AES_GMAC 2
+#define NX_MODE_AES_GCA 3
+#define NX_MODE_AES_GCM 4
+#define NX_MODE_AES_CCA 5
+#define NX_MODE_AES_CCM 6
+#define NX_MODE_AES_CTR 7
+#define NX_MODE_AES_XCBC_MAC 20
+#define NX_MODE_SHA 0
+#define NX_MODE_SHA_HMAC 1
+#define NX_MODE_AES_CBC_HMAC_ETA 8
+#define NX_MODE_AES_CBC_HMAC_ATE 9
+#define NX_MODE_AES_CBC_HMAC_EAA 10
+#define NX_MODE_AES_CTR_HMAC_ETA 12
+#define NX_MODE_AES_CTR_HMAC_ATE 13
+#define NX_MODE_AES_CTR_HMAC_EAA 14
+
+#define NX_FDM_CI_FULL 0
+#define NX_FDM_CI_FIRST 1
+#define NX_FDM_CI_LAST 2
+#define NX_FDM_CI_MIDDLE 3
+
+#define NX_FDM_PR_NONE 0
+#define NX_FDM_PR_PAD 1
+
+#define NX_KS_AES_128 1
+#define NX_KS_AES_192 2
+#define NX_KS_AES_256 3
+
+#define NX_DS_SHA256 2
+#define NX_DS_SHA512 3
+
+#define NX_FC_AES 0
+#define NX_FC_SHA 2
+#define NX_FC_AES_HMAC 6
+
+#define NX_MAX_FC (NX_FC_AES_HMAC + 1)
+#define NX_MAX_MODE (NX_MODE_AES_XCBC_MAC + 1)
+
+#define HCOP_FC_AES NX_FC_AES
+#define HCOP_FC_SHA NX_FC_SHA
+#define HCOP_FC_AES_HMAC NX_FC_AES_HMAC
+
+/* indices into the array of algorithm properties */
+#define NX_PROPS_AES_128 0
+#define NX_PROPS_AES_192 1
+#define NX_PROPS_AES_256 2
+#define NX_PROPS_SHA256 1
+#define NX_PROPS_SHA512 2
+
+#endif
diff --git a/drivers/crypto/nx/nx_debugfs.c b/drivers/crypto/nx/nx_debugfs.c
new file mode 100644
index 000000000000..7ab2e8dcd9b4
--- /dev/null
+++ b/drivers/crypto/nx/nx_debugfs.c
@@ -0,0 +1,103 @@
+/**
+ * debugfs routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2011-2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * 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.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <linux/device.h>
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/crypto.h>
+#include <crypto/hash.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+#ifdef CONFIG_DEBUG_FS
+
+/*
+ * debugfs
+ *
+ * For documentation on these attributes, please see:
+ *
+ * Documentation/ABI/testing/debugfs-pfo-nx-crypto
+ */
+
+int nx_debugfs_init(struct nx_crypto_driver *drv)
+{
+ struct nx_debugfs *dfs = &drv->dfs;
+
+ dfs->dfs_root = debugfs_create_dir(NX_NAME, NULL);
+
+ dfs->dfs_aes_ops =
+ debugfs_create_u32("aes_ops",
+ S_IRUSR | S_IRGRP | S_IROTH,
+ dfs->dfs_root, (u32 *)&drv->stats.aes_ops);
+ dfs->dfs_sha256_ops =
+ debugfs_create_u32("sha256_ops",
+ S_IRUSR | S_IRGRP | S_IROTH,
+ dfs->dfs_root,
+ (u32 *)&drv->stats.sha256_ops);
+ dfs->dfs_sha512_ops =
+ debugfs_create_u32("sha512_ops",
+ S_IRUSR | S_IRGRP | S_IROTH,
+ dfs->dfs_root,
+ (u32 *)&drv->stats.sha512_ops);
+ dfs->dfs_aes_bytes =
+ debugfs_create_u64("aes_bytes",
+ S_IRUSR | S_IRGRP | S_IROTH,
+ dfs->dfs_root,
+ (u64 *)&drv->stats.aes_bytes);
+ dfs->dfs_sha256_bytes =
+ debugfs_create_u64("sha256_bytes",
+ S_IRUSR | S_IRGRP | S_IROTH,
+ dfs->dfs_root,
+ (u64 *)&drv->stats.sha256_bytes);
+ dfs->dfs_sha512_bytes =
+ debugfs_create_u64("sha512_bytes",
+ S_IRUSR | S_IRGRP | S_IROTH,
+ dfs->dfs_root,
+ (u64 *)&drv->stats.sha512_bytes);
+ dfs->dfs_errors =
+ debugfs_create_u32("errors",
+ S_IRUSR | S_IRGRP | S_IROTH,
+ dfs->dfs_root, (u32 *)&drv->stats.errors);
+ dfs->dfs_last_error =
+ debugfs_create_u32("last_error",
+ S_IRUSR | S_IRGRP | S_IROTH,
+ dfs->dfs_root,
+ (u32 *)&drv->stats.last_error);
+ dfs->dfs_last_error_pid =
+ debugfs_create_u32("last_error_pid",
+ S_IRUSR | S_IRGRP | S_IROTH,
+ dfs->dfs_root,
+ (u32 *)&drv->stats.last_error_pid);
+ return 0;
+}
+
+void
+nx_debugfs_fini(struct nx_crypto_driver *drv)
+{
+ debugfs_remove_recursive(drv->dfs.dfs_root);
+}
+
+#endif
diff --git a/drivers/crypto/ux500/Kconfig b/drivers/crypto/ux500/Kconfig
new file mode 100644
index 000000000000..b35e5c4b025a
--- /dev/null
+++ b/drivers/crypto/ux500/Kconfig
@@ -0,0 +1,30 @@
+#
+# Copyright (C) ST-Ericsson SA 2010
+# Author: Shujuan Chen (shujuan.chen@stericsson.com)
+# License terms: GNU General Public License (GPL) version 2
+#
+
+config CRYPTO_DEV_UX500_CRYP
+ tristate "UX500 crypto driver for CRYP block"
+ depends on CRYPTO_DEV_UX500
+ select CRYPTO_DES
+ help
+ This selects the crypto driver for the UX500_CRYP hardware. It supports
+ AES-ECB, CBC and CTR with keys sizes of 128, 192 and 256 bit sizes.
+
+config CRYPTO_DEV_UX500_HASH
+ tristate "UX500 crypto driver for HASH block"
+ depends on CRYPTO_DEV_UX500
+ select CRYPTO_HASH
+ select CRYPTO_HMAC
+ help
+ This selects the hash driver for the UX500_HASH hardware.
+ Depends on UX500/STM DMA if running in DMA mode.
+
+config CRYPTO_DEV_UX500_DEBUG
+ bool "Activate ux500 platform debug-mode for crypto and hash block"
+ depends on CRYPTO_DEV_UX500_CRYP || CRYPTO_DEV_UX500_HASH
+ default n
+ help
+ Say Y if you want to add debug prints to ux500_hash and
+ ux500_cryp devices.
diff --git a/drivers/crypto/ux500/Makefile b/drivers/crypto/ux500/Makefile
new file mode 100644
index 000000000000..b9a365bade86
--- /dev/null
+++ b/drivers/crypto/ux500/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (C) ST-Ericsson SA 2010
+# Author: Shujuan Chen (shujuan.chen@stericsson.com)
+# License terms: GNU General Public License (GPL) version 2
+#
+
+obj-$(CONFIG_CRYPTO_DEV_UX500_HASH) += hash/
+obj-$(CONFIG_CRYPTO_DEV_UX500_CRYP) += cryp/
diff --git a/drivers/crypto/ux500/cryp/Makefile b/drivers/crypto/ux500/cryp/Makefile
new file mode 100644
index 000000000000..e5d362a6f680
--- /dev/null
+++ b/drivers/crypto/ux500/cryp/Makefile
@@ -0,0 +1,13 @@
+#/*
+# * Copyright (C) ST-Ericsson SA 2010
+# * Author: shujuan.chen@stericsson.com for ST-Ericsson.
+# * License terms: GNU General Public License (GPL) version 2 */
+
+ifdef CONFIG_CRYPTO_DEV_UX500_DEBUG
+CFLAGS_cryp_core.o := -DDEBUG -O0
+CFLAGS_cryp.o := -DDEBUG -O0
+CFLAGS_cryp_irq.o := -DDEBUG -O0
+endif
+
+obj-$(CONFIG_CRYPTO_DEV_UX500_CRYP) += ux500_cryp.o
+ux500_cryp-objs := cryp.o cryp_irq.o cryp_core.o
diff --git a/drivers/crypto/ux500/cryp/cryp.c b/drivers/crypto/ux500/cryp/cryp.c
new file mode 100644
index 000000000000..e208ceaf81c9
--- /dev/null
+++ b/drivers/crypto/ux500/cryp/cryp.c
@@ -0,0 +1,389 @@
+/**
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Shujuan Chen <shujuan.chen@stericsson.com> for ST-Ericsson.
+ * Author: Jonas Linde <jonas.linde@stericsson.com> for ST-Ericsson.
+ * Author: Niklas Hernaeus <niklas.hernaeus@stericsson.com> for ST-Ericsson.
+ * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson.
+ * Author: Berne Hebark <berne.herbark@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <mach/hardware.h>
+
+#include "cryp_p.h"
+#include "cryp.h"
+
+/**
+ * cryp_wait_until_done - wait until the device logic is not busy
+ */
+void cryp_wait_until_done(struct cryp_device_data *device_data)
+{
+ while (cryp_is_logic_busy(device_data))
+ cpu_relax();
+}
+
+/**
+ * cryp_check - This routine checks Peripheral and PCell Id
+ * @device_data: Pointer to the device data struct for base address.
+ */
+int cryp_check(struct cryp_device_data *device_data)
+{
+ int peripheralid2 = 0;
+
+ if (NULL == device_data)
+ return -EINVAL;
+
+ peripheralid2 = readl_relaxed(&device_data->base->periphId2);
+
+ if (peripheralid2 != CRYP_PERIPHERAL_ID2_DB8500)
+ return -EPERM;
+
+ /* Check Peripheral and Pcell Id Register for CRYP */
+ if ((CRYP_PERIPHERAL_ID0 ==
+ readl_relaxed(&device_data->base->periphId0))
+ && (CRYP_PERIPHERAL_ID1 ==
+ readl_relaxed(&device_data->base->periphId1))
+ && (CRYP_PERIPHERAL_ID3 ==
+ readl_relaxed(&device_data->base->periphId3))
+ && (CRYP_PCELL_ID0 ==
+ readl_relaxed(&device_data->base->pcellId0))
+ && (CRYP_PCELL_ID1 ==
+ readl_relaxed(&device_data->base->pcellId1))
+ && (CRYP_PCELL_ID2 ==
+ readl_relaxed(&device_data->base->pcellId2))
+ && (CRYP_PCELL_ID3 ==
+ readl_relaxed(&device_data->base->pcellId3))) {
+ return 0;
+ }
+
+ return -EPERM;
+}
+
+/**
+ * cryp_activity - This routine enables/disable the cryptography function.
+ * @device_data: Pointer to the device data struct for base address.
+ * @cryp_crypen: Enable/Disable functionality
+ */
+void cryp_activity(struct cryp_device_data *device_data,
+ enum cryp_crypen cryp_crypen)
+{
+ CRYP_PUT_BITS(&device_data->base->cr,
+ cryp_crypen,
+ CRYP_CR_CRYPEN_POS,
+ CRYP_CR_CRYPEN_MASK);
+}
+
+/**
+ * cryp_flush_inoutfifo - Resets both the input and the output FIFOs
+ * @device_data: Pointer to the device data struct for base address.
+ */
+void cryp_flush_inoutfifo(struct cryp_device_data *device_data)
+{
+ /*
+ * We always need to disble the hardware before trying to flush the
+ * FIFO. This is something that isn't written in the design
+ * specification, but we have been informed by the hardware designers
+ * that this must be done.
+ */
+ cryp_activity(device_data, CRYP_CRYPEN_DISABLE);
+ cryp_wait_until_done(device_data);
+
+ CRYP_SET_BITS(&device_data->base->cr, CRYP_CR_FFLUSH_MASK);
+ /*
+ * CRYP_SR_INFIFO_READY_MASK is the expected value on the status
+ * register when starting a new calculation, which means Input FIFO is
+ * not full and input FIFO is empty.
+ */
+ while (readl_relaxed(&device_data->base->sr) !=
+ CRYP_SR_INFIFO_READY_MASK)
+ cpu_relax();
+}
+
+/**
+ * cryp_set_configuration - This routine set the cr CRYP IP
+ * @device_data: Pointer to the device data struct for base address.
+ * @cryp_config: Pointer to the configuration parameter
+ * @control_register: The control register to be written later on.
+ */
+int cryp_set_configuration(struct cryp_device_data *device_data,
+ struct cryp_config *cryp_config,
+ u32 *control_register)
+{
+ u32 cr_for_kse;
+
+ if (NULL == device_data || NULL == cryp_config)
+ return -EINVAL;
+
+ *control_register |= (cryp_config->keysize << CRYP_CR_KEYSIZE_POS);
+
+ /* Prepare key for decryption in AES_ECB and AES_CBC mode. */
+ if ((CRYP_ALGORITHM_DECRYPT == cryp_config->algodir) &&
+ ((CRYP_ALGO_AES_ECB == cryp_config->algomode) ||
+ (CRYP_ALGO_AES_CBC == cryp_config->algomode))) {
+ cr_for_kse = *control_register;
+ /*
+ * This seems a bit odd, but it is indeed needed to set this to
+ * encrypt even though it is a decryption that we are doing. It
+ * also mentioned in the design spec that you need to do this.
+ * After the keyprepartion for decrypting is done you should set
+ * algodir back to decryption, which is done outside this if
+ * statement.
+ *
+ * According to design specification we should set mode ECB
+ * during key preparation even though we might be running CBC
+ * when enter this function.
+ *
+ * Writing to KSE_ENABLED will drop CRYPEN when key preparation
+ * is done. Therefore we need to set CRYPEN again outside this
+ * if statement when running decryption.
+ */
+ cr_for_kse |= ((CRYP_ALGORITHM_ENCRYPT << CRYP_CR_ALGODIR_POS) |
+ (CRYP_ALGO_AES_ECB << CRYP_CR_ALGOMODE_POS) |
+ (CRYP_CRYPEN_ENABLE << CRYP_CR_CRYPEN_POS) |
+ (KSE_ENABLED << CRYP_CR_KSE_POS));
+
+ writel_relaxed(cr_for_kse, &device_data->base->cr);
+ cryp_wait_until_done(device_data);
+ }
+
+ *control_register |=
+ ((cryp_config->algomode << CRYP_CR_ALGOMODE_POS) |
+ (cryp_config->algodir << CRYP_CR_ALGODIR_POS));
+
+ return 0;
+}
+
+/**
+ * cryp_configure_protection - set the protection bits in the CRYP logic.
+ * @device_data: Pointer to the device data struct for base address.
+ * @p_protect_config: Pointer to the protection mode and
+ * secure mode configuration
+ */
+int cryp_configure_protection(struct cryp_device_data *device_data,
+ struct cryp_protection_config *p_protect_config)
+{
+ if (NULL == p_protect_config)
+ return -EINVAL;
+
+ CRYP_WRITE_BIT(&device_data->base->cr,
+ (u32) p_protect_config->secure_access,
+ CRYP_CR_SECURE_MASK);
+ CRYP_PUT_BITS(&device_data->base->cr,
+ p_protect_config->privilege_access,
+ CRYP_CR_PRLG_POS,
+ CRYP_CR_PRLG_MASK);
+
+ return 0;
+}
+
+/**
+ * cryp_is_logic_busy - returns the busy status of the CRYP logic
+ * @device_data: Pointer to the device data struct for base address.
+ */
+int cryp_is_logic_busy(struct cryp_device_data *device_data)
+{
+ return CRYP_TEST_BITS(&device_data->base->sr,
+ CRYP_SR_BUSY_MASK);
+}
+
+/**
+ * cryp_configure_for_dma - configures the CRYP IP for DMA operation
+ * @device_data: Pointer to the device data struct for base address.
+ * @dma_req: Specifies the DMA request type value.
+ */
+void cryp_configure_for_dma(struct cryp_device_data *device_data,
+ enum cryp_dma_req_type dma_req)
+{
+ CRYP_SET_BITS(&device_data->base->dmacr,
+ (u32) dma_req);
+}
+
+/**
+ * cryp_configure_key_values - configures the key values for CRYP operations
+ * @device_data: Pointer to the device data struct for base address.
+ * @key_reg_index: Key value index register
+ * @key_value: The key value struct
+ */
+int cryp_configure_key_values(struct cryp_device_data *device_data,
+ enum cryp_key_reg_index key_reg_index,
+ struct cryp_key_value key_value)
+{
+ while (cryp_is_logic_busy(device_data))
+ cpu_relax();
+
+ switch (key_reg_index) {
+ case CRYP_KEY_REG_1:
+ writel_relaxed(key_value.key_value_left,
+ &device_data->base->key_1_l);
+ writel_relaxed(key_value.key_value_right,
+ &device_data->base->key_1_r);
+ break;
+ case CRYP_KEY_REG_2:
+ writel_relaxed(key_value.key_value_left,
+ &device_data->base->key_2_l);
+ writel_relaxed(key_value.key_value_right,
+ &device_data->base->key_2_r);
+ break;
+ case CRYP_KEY_REG_3:
+ writel_relaxed(key_value.key_value_left,
+ &device_data->base->key_3_l);
+ writel_relaxed(key_value.key_value_right,
+ &device_data->base->key_3_r);
+ break;
+ case CRYP_KEY_REG_4:
+ writel_relaxed(key_value.key_value_left,
+ &device_data->base->key_4_l);
+ writel_relaxed(key_value.key_value_right,
+ &device_data->base->key_4_r);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * cryp_configure_init_vector - configures the initialization vector register
+ * @device_data: Pointer to the device data struct for base address.
+ * @init_vector_index: Specifies the index of the init vector.
+ * @init_vector_value: Specifies the value for the init vector.
+ */
+int cryp_configure_init_vector(struct cryp_device_data *device_data,
+ enum cryp_init_vector_index
+ init_vector_index,
+ struct cryp_init_vector_value
+ init_vector_value)
+{
+ while (cryp_is_logic_busy(device_data))
+ cpu_relax();
+
+ switch (init_vector_index) {
+ case CRYP_INIT_VECTOR_INDEX_0:
+ writel_relaxed(init_vector_value.init_value_left,
+ &device_data->base->init_vect_0_l);
+ writel_relaxed(init_vector_value.init_value_right,
+ &device_data->base->init_vect_0_r);
+ break;
+ case CRYP_INIT_VECTOR_INDEX_1:
+ writel_relaxed(init_vector_value.init_value_left,
+ &device_data->base->init_vect_1_l);
+ writel_relaxed(init_vector_value.init_value_right,
+ &device_data->base->init_vect_1_r);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * cryp_save_device_context - Store hardware registers and
+ * other device context parameter
+ * @device_data: Pointer to the device data struct for base address.
+ * @ctx: Crypto device context
+ */
+void cryp_save_device_context(struct cryp_device_data *device_data,
+ struct cryp_device_context *ctx,
+ int cryp_mode)
+{
+ enum cryp_algo_mode algomode;
+ struct cryp_register *src_reg = device_data->base;
+ struct cryp_config *config =
+ (struct cryp_config *)device_data->current_ctx;
+
+ /*
+ * Always start by disable the hardware and wait for it to finish the
+ * ongoing calculations before trying to reprogram it.
+ */
+ cryp_activity(device_data, CRYP_CRYPEN_DISABLE);
+ cryp_wait_until_done(device_data);
+
+ if (cryp_mode == CRYP_MODE_DMA)
+ cryp_configure_for_dma(device_data, CRYP_DMA_DISABLE_BOTH);
+
+ if (CRYP_TEST_BITS(&src_reg->sr, CRYP_SR_IFEM_MASK) == 0)
+ ctx->din = readl_relaxed(&src_reg->din);
+
+ ctx->cr = readl_relaxed(&src_reg->cr) & CRYP_CR_CONTEXT_SAVE_MASK;
+
+ switch (config->keysize) {
+ case CRYP_KEY_SIZE_256:
+ ctx->key_4_l = readl_relaxed(&src_reg->key_4_l);
+ ctx->key_4_r = readl_relaxed(&src_reg->key_4_r);
+
+ case CRYP_KEY_SIZE_192:
+ ctx->key_3_l = readl_relaxed(&src_reg->key_3_l);
+ ctx->key_3_r = readl_relaxed(&src_reg->key_3_r);
+
+ case CRYP_KEY_SIZE_128:
+ ctx->key_2_l = readl_relaxed(&src_reg->key_2_l);
+ ctx->key_2_r = readl_relaxed(&src_reg->key_2_r);
+
+ default:
+ ctx->key_1_l = readl_relaxed(&src_reg->key_1_l);
+ ctx->key_1_r = readl_relaxed(&src_reg->key_1_r);
+ }
+
+ /* Save IV for CBC mode for both AES and DES. */
+ algomode = ((ctx->cr & CRYP_CR_ALGOMODE_MASK) >> CRYP_CR_ALGOMODE_POS);
+ if (algomode == CRYP_ALGO_TDES_CBC ||
+ algomode == CRYP_ALGO_DES_CBC ||
+ algomode == CRYP_ALGO_AES_CBC) {
+ ctx->init_vect_0_l = readl_relaxed(&src_reg->init_vect_0_l);
+ ctx->init_vect_0_r = readl_relaxed(&src_reg->init_vect_0_r);
+ ctx->init_vect_1_l = readl_relaxed(&src_reg->init_vect_1_l);
+ ctx->init_vect_1_r = readl_relaxed(&src_reg->init_vect_1_r);
+ }
+}
+
+/**
+ * cryp_restore_device_context - Restore hardware registers and
+ * other device context parameter
+ * @device_data: Pointer to the device data struct for base address.
+ * @ctx: Crypto device context
+ */
+void cryp_restore_device_context(struct cryp_device_data *device_data,
+ struct cryp_device_context *ctx)
+{
+ struct cryp_register *reg = device_data->base;
+ struct cryp_config *config =
+ (struct cryp_config *)device_data->current_ctx;
+
+ /*
+ * Fall through for all items in switch statement. DES is captured in
+ * the default.
+ */
+ switch (config->keysize) {
+ case CRYP_KEY_SIZE_256:
+ writel_relaxed(ctx->key_4_l, &reg->key_4_l);
+ writel_relaxed(ctx->key_4_r, &reg->key_4_r);
+
+ case CRYP_KEY_SIZE_192:
+ writel_relaxed(ctx->key_3_l, &reg->key_3_l);
+ writel_relaxed(ctx->key_3_r, &reg->key_3_r);
+
+ case CRYP_KEY_SIZE_128:
+ writel_relaxed(ctx->key_2_l, &reg->key_2_l);
+ writel_relaxed(ctx->key_2_r, &reg->key_2_r);
+
+ default:
+ writel_relaxed(ctx->key_1_l, &reg->key_1_l);
+ writel_relaxed(ctx->key_1_r, &reg->key_1_r);
+ }
+
+ /* Restore IV for CBC mode for AES and DES. */
+ if (config->algomode == CRYP_ALGO_TDES_CBC ||
+ config->algomode == CRYP_ALGO_DES_CBC ||
+ config->algomode == CRYP_ALGO_AES_CBC) {
+ writel_relaxed(ctx->init_vect_0_l, &reg->init_vect_0_l);
+ writel_relaxed(ctx->init_vect_0_r, &reg->init_vect_0_r);
+ writel_relaxed(ctx->init_vect_1_l, &reg->init_vect_1_l);
+ writel_relaxed(ctx->init_vect_1_r, &reg->init_vect_1_r);
+ }
+}
diff --git a/drivers/crypto/ux500/cryp/cryp.h b/drivers/crypto/ux500/cryp/cryp.h
new file mode 100644
index 000000000000..14cfd05b777a
--- /dev/null
+++ b/drivers/crypto/ux500/cryp/cryp.h
@@ -0,0 +1,308 @@
+/**
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Shujuan Chen <shujuan.chen@stericsson.com> for ST-Ericsson.
+ * Author: Jonas Linde <jonas.linde@stericsson.com> for ST-Ericsson.
+ * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson.
+ * Author: Berne Hebark <berne.herbark@stericsson.com> for ST-Ericsson.
+ * Author: Niklas Hernaeus <niklas.hernaeus@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef _CRYP_H_
+#define _CRYP_H_
+
+#include <linux/completion.h>
+#include <linux/dmaengine.h>
+#include <linux/klist.h>
+#include <linux/mutex.h>
+
+#define DEV_DBG_NAME "crypX crypX:"
+
+/* CRYP enable/disable */
+enum cryp_crypen {
+ CRYP_CRYPEN_DISABLE = 0,
+ CRYP_CRYPEN_ENABLE = 1
+};
+
+/* CRYP Start Computation enable/disable */
+enum cryp_start {
+ CRYP_START_DISABLE = 0,
+ CRYP_START_ENABLE = 1
+};
+
+/* CRYP Init Signal enable/disable */
+enum cryp_init {
+ CRYP_INIT_DISABLE = 0,
+ CRYP_INIT_ENABLE = 1
+};
+
+/* Cryp State enable/disable */
+enum cryp_state {
+ CRYP_STATE_DISABLE = 0,
+ CRYP_STATE_ENABLE = 1
+};
+
+/* Key preparation bit enable */
+enum cryp_key_prep {
+ KSE_DISABLED = 0,
+ KSE_ENABLED = 1
+};
+
+/* Key size for AES */
+#define CRYP_KEY_SIZE_128 (0)
+#define CRYP_KEY_SIZE_192 (1)
+#define CRYP_KEY_SIZE_256 (2)
+
+/* AES modes */
+enum cryp_algo_mode {
+ CRYP_ALGO_TDES_ECB,
+ CRYP_ALGO_TDES_CBC,
+ CRYP_ALGO_DES_ECB,
+ CRYP_ALGO_DES_CBC,
+ CRYP_ALGO_AES_ECB,
+ CRYP_ALGO_AES_CBC,
+ CRYP_ALGO_AES_CTR,
+ CRYP_ALGO_AES_XTS
+};
+
+/* Cryp Encryption or Decryption */
+enum cryp_algorithm_dir {
+ CRYP_ALGORITHM_ENCRYPT,
+ CRYP_ALGORITHM_DECRYPT
+};
+
+/* Hardware access method */
+enum cryp_mode {
+ CRYP_MODE_POLLING,
+ CRYP_MODE_INTERRUPT,
+ CRYP_MODE_DMA
+};
+
+/**
+ * struct cryp_config -
+ * @keysize: Key size for AES
+ * @algomode: AES modes
+ * @algodir: Cryp Encryption or Decryption
+ *
+ * CRYP configuration structure to be passed to set configuration
+ */
+struct cryp_config {
+ int keysize;
+ enum cryp_algo_mode algomode;
+ enum cryp_algorithm_dir algodir;
+};
+
+/**
+ * struct cryp_protection_config -
+ * @privilege_access: Privileged cryp state enable/disable
+ * @secure_access: Secure cryp state enable/disable
+ *
+ * Protection configuration structure for setting privilage access
+ */
+struct cryp_protection_config {
+ enum cryp_state privilege_access;
+ enum cryp_state secure_access;
+};
+
+/* Cryp status */
+enum cryp_status_id {
+ CRYP_STATUS_BUSY = 0x10,
+ CRYP_STATUS_OUTPUT_FIFO_FULL = 0x08,
+ CRYP_STATUS_OUTPUT_FIFO_NOT_EMPTY = 0x04,
+ CRYP_STATUS_INPUT_FIFO_NOT_FULL = 0x02,
+ CRYP_STATUS_INPUT_FIFO_EMPTY = 0x01
+};
+
+/* Cryp DMA interface */
+enum cryp_dma_req_type {
+ CRYP_DMA_DISABLE_BOTH,
+ CRYP_DMA_ENABLE_IN_DATA,
+ CRYP_DMA_ENABLE_OUT_DATA,
+ CRYP_DMA_ENABLE_BOTH_DIRECTIONS
+};
+
+enum cryp_dma_channel {
+ CRYP_DMA_RX = 0,
+ CRYP_DMA_TX
+};
+
+/* Key registers */
+enum cryp_key_reg_index {
+ CRYP_KEY_REG_1,
+ CRYP_KEY_REG_2,
+ CRYP_KEY_REG_3,
+ CRYP_KEY_REG_4
+};
+
+/* Key register left and right */
+struct cryp_key_value {
+ u32 key_value_left;
+ u32 key_value_right;
+};
+
+/* Cryp Initialization structure */
+enum cryp_init_vector_index {
+ CRYP_INIT_VECTOR_INDEX_0,
+ CRYP_INIT_VECTOR_INDEX_1
+};
+
+/* struct cryp_init_vector_value -
+ * @init_value_left
+ * @init_value_right
+ * */
+struct cryp_init_vector_value {
+ u32 init_value_left;
+ u32 init_value_right;
+};
+
+/**
+ * struct cryp_device_context - structure for a cryp context.
+ * @cr: control register
+ * @dmacr: DMA control register
+ * @imsc: Interrupt mask set/clear register
+ * @key_1_l: Key 1l register
+ * @key_1_r: Key 1r register
+ * @key_2_l: Key 2l register
+ * @key_2_r: Key 2r register
+ * @key_3_l: Key 3l register
+ * @key_3_r: Key 3r register
+ * @key_4_l: Key 4l register
+ * @key_4_r: Key 4r register
+ * @init_vect_0_l: Initialization vector 0l register
+ * @init_vect_0_r: Initialization vector 0r register
+ * @init_vect_1_l: Initialization vector 1l register
+ * @init_vect_1_r: Initialization vector 0r register
+ * @din: Data in register
+ * @dout: Data out register
+ *
+ * CRYP power management specifc structure.
+ */
+struct cryp_device_context {
+ u32 cr;
+ u32 dmacr;
+ u32 imsc;
+
+ u32 key_1_l;
+ u32 key_1_r;
+ u32 key_2_l;
+ u32 key_2_r;
+ u32 key_3_l;
+ u32 key_3_r;
+ u32 key_4_l;
+ u32 key_4_r;
+
+ u32 init_vect_0_l;
+ u32 init_vect_0_r;
+ u32 init_vect_1_l;
+ u32 init_vect_1_r;
+
+ u32 din;
+ u32 dout;
+};
+
+struct cryp_dma {
+ dma_cap_mask_t mask;
+ struct completion cryp_dma_complete;
+ struct dma_chan *chan_cryp2mem;
+ struct dma_chan *chan_mem2cryp;
+ struct stedma40_chan_cfg *cfg_cryp2mem;
+ struct stedma40_chan_cfg *cfg_mem2cryp;
+ int sg_src_len;
+ int sg_dst_len;
+ struct scatterlist *sg_src;
+ struct scatterlist *sg_dst;
+ int nents_src;
+ int nents_dst;
+};
+
+/**
+ * struct cryp_device_data - structure for a cryp device.
+ * @base: Pointer to the hardware base address.
+ * @dev: Pointer to the devices dev structure.
+ * @clk: Pointer to the device's clock control.
+ * @pwr_regulator: Pointer to the device's power control.
+ * @power_status: Current status of the power.
+ * @ctx_lock: Lock for current_ctx.
+ * @current_ctx: Pointer to the currently allocated context.
+ * @list_node: For inclusion into a klist.
+ * @dma: The dma structure holding channel configuration.
+ * @power_state: TRUE = power state on, FALSE = power state off.
+ * @power_state_spinlock: Spinlock for power_state.
+ * @restore_dev_ctx: TRUE = saved ctx, FALSE = no saved ctx.
+ */
+struct cryp_device_data {
+ struct cryp_register __iomem *base;
+ struct device *dev;
+ struct clk *clk;
+ struct regulator *pwr_regulator;
+ int power_status;
+ struct spinlock ctx_lock;
+ struct cryp_ctx *current_ctx;
+ struct klist_node list_node;
+ struct cryp_dma dma;
+ bool power_state;
+ struct spinlock power_state_spinlock;
+ bool restore_dev_ctx;
+};
+
+void cryp_wait_until_done(struct cryp_device_data *device_data);
+
+/* Initialization functions */
+
+int cryp_check(struct cryp_device_data *device_data);
+
+void cryp_activity(struct cryp_device_data *device_data,
+ enum cryp_crypen cryp_crypen);
+
+void cryp_flush_inoutfifo(struct cryp_device_data *device_data);
+
+int cryp_set_configuration(struct cryp_device_data *device_data,
+ struct cryp_config *cryp_config,
+ u32 *control_register);
+
+void cryp_configure_for_dma(struct cryp_device_data *device_data,
+ enum cryp_dma_req_type dma_req);
+
+int cryp_configure_key_values(struct cryp_device_data *device_data,
+ enum cryp_key_reg_index key_reg_index,
+ struct cryp_key_value key_value);
+
+int cryp_configure_init_vector(struct cryp_device_data *device_data,
+ enum cryp_init_vector_index
+ init_vector_index,
+ struct cryp_init_vector_value
+ init_vector_value);
+
+int cryp_configure_protection(struct cryp_device_data *device_data,
+ struct cryp_protection_config *p_protect_config);
+
+/* Power management funtions */
+void cryp_save_device_context(struct cryp_device_data *device_data,
+ struct cryp_device_context *ctx,
+ int cryp_mode);
+
+void cryp_restore_device_context(struct cryp_device_data *device_data,
+ struct cryp_device_context *ctx);
+
+/* Data transfer and status bits. */
+int cryp_is_logic_busy(struct cryp_device_data *device_data);
+
+int cryp_get_status(struct cryp_device_data *device_data);
+
+/**
+ * cryp_write_indata - This routine writes 32 bit data into the data input
+ * register of the cryptography IP.
+ * @device_data: Pointer to the device data struct for base address.
+ * @write_data: Data to write.
+ */
+int cryp_write_indata(struct cryp_device_data *device_data, u32 write_data);
+
+/**
+ * cryp_read_outdata - This routine reads the data from the data output
+ * register of the CRYP logic
+ * @device_data: Pointer to the device data struct for base address.
+ * @read_data: Read the data from the output FIFO.
+ */
+int cryp_read_outdata(struct cryp_device_data *device_data, u32 *read_data);
+
+#endif /* _CRYP_H_ */
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c
new file mode 100644
index 000000000000..7cac12793a4b
--- /dev/null
+++ b/drivers/crypto/ux500/cryp/cryp_core.c
@@ -0,0 +1,1784 @@
+/**
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Shujuan Chen <shujuan.chen@stericsson.com> for ST-Ericsson.
+ * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson.
+ * Author: Berne Hebark <berne.herbark@stericsson.com> for ST-Ericsson.
+ * Author: Niklas Hernaeus <niklas.hernaeus@stericsson.com> for ST-Ericsson.
+ * Author: Jonas Linde <jonas.linde@stericsson.com> for ST-Ericsson.
+ * Author: Andreas Westin <andreas.westin@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/crypto.h>
+#include <linux/dmaengine.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irqreturn.h>
+#include <linux/klist.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/semaphore.h>
+
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/ctr.h>
+#include <crypto/des.h>
+#include <crypto/scatterwalk.h>
+
+#include <plat/ste_dma40.h>
+
+#include <mach/crypto-ux500.h>
+#include <mach/hardware.h>
+
+#include "cryp_p.h"
+#include "cryp.h"
+
+#define CRYP_MAX_KEY_SIZE 32
+#define BYTES_PER_WORD 4
+
+static int cryp_mode;
+static atomic_t session_id;
+
+static struct stedma40_chan_cfg *mem_to_engine;
+static struct stedma40_chan_cfg *engine_to_mem;
+
+/**
+ * struct cryp_driver_data - data specific to the driver.
+ *
+ * @device_list: A list of registered devices to choose from.
+ * @device_allocation: A semaphore initialized with number of devices.
+ */
+struct cryp_driver_data {
+ struct klist device_list;
+ struct semaphore device_allocation;
+};
+
+/**
+ * struct cryp_ctx - Crypto context
+ * @config: Crypto mode.
+ * @key[CRYP_MAX_KEY_SIZE]: Key.
+ * @keylen: Length of key.
+ * @iv: Pointer to initialization vector.
+ * @indata: Pointer to indata.
+ * @outdata: Pointer to outdata.
+ * @datalen: Length of indata.
+ * @outlen: Length of outdata.
+ * @blocksize: Size of blocks.
+ * @updated: Updated flag.
+ * @dev_ctx: Device dependent context.
+ * @device: Pointer to the device.
+ */
+struct cryp_ctx {
+ struct cryp_config config;
+ u8 key[CRYP_MAX_KEY_SIZE];
+ u32 keylen;
+ u8 *iv;
+ const u8 *indata;
+ u8 *outdata;
+ u32 datalen;
+ u32 outlen;
+ u32 blocksize;
+ u8 updated;
+ struct cryp_device_context dev_ctx;
+ struct cryp_device_data *device;
+ u32 session_id;
+};
+
+static struct cryp_driver_data driver_data;
+
+/**
+ * uint8p_to_uint32_be - 4*uint8 to uint32 big endian
+ * @in: Data to convert.
+ */
+static inline u32 uint8p_to_uint32_be(u8 *in)
+{
+ u32 *data = (u32 *)in;
+
+ return cpu_to_be32p(data);
+}
+
+/**
+ * swap_bits_in_byte - mirror the bits in a byte
+ * @b: the byte to be mirrored
+ *
+ * The bits are swapped the following way:
+ * Byte b include bits 0-7, nibble 1 (n1) include bits 0-3 and
+ * nibble 2 (n2) bits 4-7.
+ *
+ * Nibble 1 (n1):
+ * (The "old" (moved) bit is replaced with a zero)
+ * 1. Move bit 6 and 7, 4 positions to the left.
+ * 2. Move bit 3 and 5, 2 positions to the left.
+ * 3. Move bit 1-4, 1 position to the left.
+ *
+ * Nibble 2 (n2):
+ * 1. Move bit 0 and 1, 4 positions to the right.
+ * 2. Move bit 2 and 4, 2 positions to the right.
+ * 3. Move bit 3-6, 1 position to the right.
+ *
+ * Combine the two nibbles to a complete and swapped byte.
+ */
+
+static inline u8 swap_bits_in_byte(u8 b)
+{
+#define R_SHIFT_4_MASK 0xc0 /* Bits 6 and 7, right shift 4 */
+#define R_SHIFT_2_MASK 0x28 /* (After right shift 4) Bits 3 and 5,
+ right shift 2 */
+#define R_SHIFT_1_MASK 0x1e /* (After right shift 2) Bits 1-4,
+ right shift 1 */
+#define L_SHIFT_4_MASK 0x03 /* Bits 0 and 1, left shift 4 */
+#define L_SHIFT_2_MASK 0x14 /* (After left shift 4) Bits 2 and 4,
+ left shift 2 */
+#define L_SHIFT_1_MASK 0x78 /* (After left shift 1) Bits 3-6,
+ left shift 1 */
+
+ u8 n1;
+ u8 n2;
+
+ /* Swap most significant nibble */
+ /* Right shift 4, bits 6 and 7 */
+ n1 = ((b & R_SHIFT_4_MASK) >> 4) | (b & ~(R_SHIFT_4_MASK >> 4));
+ /* Right shift 2, bits 3 and 5 */
+ n1 = ((n1 & R_SHIFT_2_MASK) >> 2) | (n1 & ~(R_SHIFT_2_MASK >> 2));
+ /* Right shift 1, bits 1-4 */
+ n1 = (n1 & R_SHIFT_1_MASK) >> 1;
+
+ /* Swap least significant nibble */
+ /* Left shift 4, bits 0 and 1 */
+ n2 = ((b & L_SHIFT_4_MASK) << 4) | (b & ~(L_SHIFT_4_MASK << 4));
+ /* Left shift 2, bits 2 and 4 */
+ n2 = ((n2 & L_SHIFT_2_MASK) << 2) | (n2 & ~(L_SHIFT_2_MASK << 2));
+ /* Left shift 1, bits 3-6 */
+ n2 = (n2 & L_SHIFT_1_MASK) << 1;
+
+ return n1 | n2;
+}
+
+static inline void swap_words_in_key_and_bits_in_byte(const u8 *in,
+ u8 *out, u32 len)
+{
+ unsigned int i = 0;
+ int j;
+ int index = 0;
+
+ j = len - BYTES_PER_WORD;
+ while (j >= 0) {
+ for (i = 0; i < BYTES_PER_WORD; i++) {
+ index = len - j - BYTES_PER_WORD + i;
+ out[j + i] =
+ swap_bits_in_byte(in[index]);
+ }
+ j -= BYTES_PER_WORD;
+ }
+}
+
+static void add_session_id(struct cryp_ctx *ctx)
+{
+ /*
+ * We never want 0 to be a valid value, since this is the default value
+ * for the software context.
+ */
+ if (unlikely(atomic_inc_and_test(&session_id)))
+ atomic_inc(&session_id);
+
+ ctx->session_id = atomic_read(&session_id);
+}
+
+static irqreturn_t cryp_interrupt_handler(int irq, void *param)
+{
+ struct cryp_ctx *ctx;
+ int i;
+ struct cryp_device_data *device_data;
+
+ if (param == NULL) {
+ BUG_ON(!param);
+ return IRQ_HANDLED;
+ }
+
+ /* The device is coming from the one found in hw_crypt_noxts. */
+ device_data = (struct cryp_device_data *)param;
+
+ ctx = device_data->current_ctx;
+
+ if (ctx == NULL) {
+ BUG_ON(!ctx);
+ return IRQ_HANDLED;
+ }
+
+ dev_dbg(ctx->device->dev, "[%s] (len: %d) %s, ", __func__, ctx->outlen,
+ cryp_pending_irq_src(device_data, CRYP_IRQ_SRC_OUTPUT_FIFO) ?
+ "out" : "in");
+
+ if (cryp_pending_irq_src(device_data,
+ CRYP_IRQ_SRC_OUTPUT_FIFO)) {
+ if (ctx->outlen / ctx->blocksize > 0) {
+ for (i = 0; i < ctx->blocksize / 4; i++) {
+ *(ctx->outdata) = readl_relaxed(
+ &device_data->base->dout);
+ ctx->outdata += 4;
+ ctx->outlen -= 4;
+ }
+
+ if (ctx->outlen == 0) {
+ cryp_disable_irq_src(device_data,
+ CRYP_IRQ_SRC_OUTPUT_FIFO);
+ }
+ }
+ } else if (cryp_pending_irq_src(device_data,
+ CRYP_IRQ_SRC_INPUT_FIFO)) {
+ if (ctx->datalen / ctx->blocksize > 0) {
+ for (i = 0 ; i < ctx->blocksize / 4; i++) {
+ writel_relaxed(ctx->indata,
+ &device_data->base->din);
+ ctx->indata += 4;
+ ctx->datalen -= 4;
+ }
+
+ if (ctx->datalen == 0)
+ cryp_disable_irq_src(device_data,
+ CRYP_IRQ_SRC_INPUT_FIFO);
+
+ if (ctx->config.algomode == CRYP_ALGO_AES_XTS) {
+ CRYP_PUT_BITS(&device_data->base->cr,
+ CRYP_START_ENABLE,
+ CRYP_CR_START_POS,
+ CRYP_CR_START_MASK);
+
+ cryp_wait_until_done(device_data);
+ }
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int mode_is_aes(enum cryp_algo_mode mode)
+{
+ return CRYP_ALGO_AES_ECB == mode ||
+ CRYP_ALGO_AES_CBC == mode ||
+ CRYP_ALGO_AES_CTR == mode ||
+ CRYP_ALGO_AES_XTS == mode;
+}
+
+static int cfg_iv(struct cryp_device_data *device_data, u32 left, u32 right,
+ enum cryp_init_vector_index index)
+{
+ struct cryp_init_vector_value vector_value;
+
+ dev_dbg(device_data->dev, "[%s]", __func__);
+
+ vector_value.init_value_left = left;
+ vector_value.init_value_right = right;
+
+ return cryp_configure_init_vector(device_data,
+ index,
+ vector_value);
+}
+
+static int cfg_ivs(struct cryp_device_data *device_data, struct cryp_ctx *ctx)
+{
+ int i;
+ int status = 0;
+ int num_of_regs = ctx->blocksize / 8;
+ u32 iv[AES_BLOCK_SIZE / 4];
+
+ dev_dbg(device_data->dev, "[%s]", __func__);
+
+ /*
+ * Since we loop on num_of_regs we need to have a check in case
+ * someone provides an incorrect blocksize which would force calling
+ * cfg_iv with i greater than 2 which is an error.
+ */
+ if (num_of_regs > 2) {
+ dev_err(device_data->dev, "[%s] Incorrect blocksize %d",
+ __func__, ctx->blocksize);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ctx->blocksize / 4; i++)
+ iv[i] = uint8p_to_uint32_be(ctx->iv + i*4);
+
+ for (i = 0; i < num_of_regs; i++) {
+ status = cfg_iv(device_data, iv[i*2], iv[i*2+1],
+ (enum cryp_init_vector_index) i);
+ if (status != 0)
+ return status;
+ }
+ return status;
+}
+
+static int set_key(struct cryp_device_data *device_data,
+ u32 left_key,
+ u32 right_key,
+ enum cryp_key_reg_index index)
+{
+ struct cryp_key_value key_value;
+ int cryp_error;
+
+ dev_dbg(device_data->dev, "[%s]", __func__);
+
+ key_value.key_value_left = left_key;
+ key_value.key_value_right = right_key;
+
+ cryp_error = cryp_configure_key_values(device_data,
+ index,
+ key_value);
+ if (cryp_error != 0)
+ dev_err(device_data->dev, "[%s]: "
+ "cryp_configure_key_values() failed!", __func__);
+
+ return cryp_error;
+}
+
+static int cfg_keys(struct cryp_ctx *ctx)
+{
+ int i;
+ int num_of_regs = ctx->keylen / 8;
+ u32 swapped_key[CRYP_MAX_KEY_SIZE / 4];
+ int cryp_error = 0;
+
+ dev_dbg(ctx->device->dev, "[%s]", __func__);
+
+ if (mode_is_aes(ctx->config.algomode)) {
+ swap_words_in_key_and_bits_in_byte((u8 *)ctx->key,
+ (u8 *)swapped_key,
+ ctx->keylen);
+ } else {
+ for (i = 0; i < ctx->keylen / 4; i++)
+ swapped_key[i] = uint8p_to_uint32_be(ctx->key + i*4);
+ }
+
+ for (i = 0; i < num_of_regs; i++) {
+ cryp_error = set_key(ctx->device,
+ *(((u32 *)swapped_key)+i*2),
+ *(((u32 *)swapped_key)+i*2+1),
+ (enum cryp_key_reg_index) i);
+
+ if (cryp_error != 0) {
+ dev_err(ctx->device->dev, "[%s]: set_key() failed!",
+ __func__);
+ return cryp_error;
+ }
+ }
+ return cryp_error;
+}
+
+static int cryp_setup_context(struct cryp_ctx *ctx,
+ struct cryp_device_data *device_data)
+{
+ u32 control_register = CRYP_CR_DEFAULT;
+
+ switch (cryp_mode) {
+ case CRYP_MODE_INTERRUPT:
+ writel_relaxed(CRYP_IMSC_DEFAULT, &device_data->base->imsc);
+ break;
+
+ case CRYP_MODE_DMA:
+ writel_relaxed(CRYP_DMACR_DEFAULT, &device_data->base->dmacr);
+ break;
+
+ default:
+ break;
+ }
+
+ if (ctx->updated == 0) {
+ cryp_flush_inoutfifo(device_data);
+ if (cfg_keys(ctx) != 0) {
+ dev_err(ctx->device->dev, "[%s]: cfg_keys failed!",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (ctx->iv &&
+ CRYP_ALGO_AES_ECB != ctx->config.algomode &&
+ CRYP_ALGO_DES_ECB != ctx->config.algomode &&
+ CRYP_ALGO_TDES_ECB != ctx->config.algomode) {
+ if (cfg_ivs(device_data, ctx) != 0)
+ return -EPERM;
+ }
+
+ cryp_set_configuration(device_data, &ctx->config,
+ &control_register);
+ add_session_id(ctx);
+ } else if (ctx->updated == 1 &&
+ ctx->session_id != atomic_read(&session_id)) {
+ cryp_flush_inoutfifo(device_data);
+ cryp_restore_device_context(device_data, &ctx->dev_ctx);
+
+ add_session_id(ctx);
+ control_register = ctx->dev_ctx.cr;
+ } else
+ control_register = ctx->dev_ctx.cr;
+
+ writel(control_register |
+ (CRYP_CRYPEN_ENABLE << CRYP_CR_CRYPEN_POS),
+ &device_data->base->cr);
+
+ return 0;
+}
+
+static int cryp_get_device_data(struct cryp_ctx *ctx,
+ struct cryp_device_data **device_data)
+{
+ int ret;
+ struct klist_iter device_iterator;
+ struct klist_node *device_node;
+ struct cryp_device_data *local_device_data = NULL;
+ pr_debug(DEV_DBG_NAME " [%s]", __func__);
+
+ /* Wait until a device is available */
+ ret = down_interruptible(&driver_data.device_allocation);
+ if (ret)
+ return ret; /* Interrupted */
+
+ /* Select a device */
+ klist_iter_init(&driver_data.device_list, &device_iterator);
+
+ device_node = klist_next(&device_iterator);
+ while (device_node) {
+ local_device_data = container_of(device_node,
+ struct cryp_device_data, list_node);
+ spin_lock(&local_device_data->ctx_lock);
+ /* current_ctx allocates a device, NULL = unallocated */
+ if (local_device_data->current_ctx) {
+ device_node = klist_next(&device_iterator);
+ } else {
+ local_device_data->current_ctx = ctx;
+ ctx->device = local_device_data;
+ spin_unlock(&local_device_data->ctx_lock);
+ break;
+ }
+ spin_unlock(&local_device_data->ctx_lock);
+ }
+ klist_iter_exit(&device_iterator);
+
+ if (!device_node) {
+ /**
+ * No free device found.
+ * Since we allocated a device with down_interruptible, this
+ * should not be able to happen.
+ * Number of available devices, which are contained in
+ * device_allocation, is therefore decremented by not doing
+ * an up(device_allocation).
+ */
+ return -EBUSY;
+ }
+
+ *device_data = local_device_data;
+
+ return 0;
+}
+
+static void cryp_dma_setup_channel(struct cryp_device_data *device_data,
+ struct device *dev)
+{
+ dma_cap_zero(device_data->dma.mask);
+ dma_cap_set(DMA_SLAVE, device_data->dma.mask);
+
+ device_data->dma.cfg_mem2cryp = mem_to_engine;
+ device_data->dma.chan_mem2cryp =
+ dma_request_channel(device_data->dma.mask,
+ stedma40_filter,
+ device_data->dma.cfg_mem2cryp);
+
+ device_data->dma.cfg_cryp2mem = engine_to_mem;
+ device_data->dma.chan_cryp2mem =
+ dma_request_channel(device_data->dma.mask,
+ stedma40_filter,
+ device_data->dma.cfg_cryp2mem);
+
+ init_completion(&device_data->dma.cryp_dma_complete);
+}
+
+static void cryp_dma_out_callback(void *data)
+{
+ struct cryp_ctx *ctx = (struct cryp_ctx *) data;
+ dev_dbg(ctx->device->dev, "[%s]: ", __func__);
+
+ complete(&ctx->device->dma.cryp_dma_complete);
+}
+
+static int cryp_set_dma_transfer(struct cryp_ctx *ctx,
+ struct scatterlist *sg,
+ int len,
+ enum dma_data_direction direction)
+{
+ struct dma_async_tx_descriptor *desc;
+ struct dma_chan *channel = NULL;
+ dma_cookie_t cookie;
+
+ dev_dbg(ctx->device->dev, "[%s]: ", __func__);
+
+ if (unlikely(!IS_ALIGNED((u32)sg, 4))) {
+ dev_err(ctx->device->dev, "[%s]: Data in sg list isn't "
+ "aligned! Addr: 0x%08x", __func__, (u32)sg);
+ return -EFAULT;
+ }
+
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ channel = ctx->device->dma.chan_mem2cryp;
+ ctx->device->dma.sg_src = sg;
+ ctx->device->dma.sg_src_len = dma_map_sg(channel->device->dev,
+ ctx->device->dma.sg_src,
+ ctx->device->dma.nents_src,
+ direction);
+
+ if (!ctx->device->dma.sg_src_len) {
+ dev_dbg(ctx->device->dev,
+ "[%s]: Could not map the sg list (TO_DEVICE)",
+ __func__);
+ return -EFAULT;
+ }
+
+ dev_dbg(ctx->device->dev, "[%s]: Setting up DMA for buffer "
+ "(TO_DEVICE)", __func__);
+
+ desc = channel->device->device_prep_slave_sg(channel,
+ ctx->device->dma.sg_src,
+ ctx->device->dma.sg_src_len,
+ direction, DMA_CTRL_ACK, NULL);
+ break;
+
+ case DMA_FROM_DEVICE:
+ channel = ctx->device->dma.chan_cryp2mem;
+ ctx->device->dma.sg_dst = sg;
+ ctx->device->dma.sg_dst_len = dma_map_sg(channel->device->dev,
+ ctx->device->dma.sg_dst,
+ ctx->device->dma.nents_dst,
+ direction);
+
+ if (!ctx->device->dma.sg_dst_len) {
+ dev_dbg(ctx->device->dev,
+ "[%s]: Could not map the sg list (FROM_DEVICE)",
+ __func__);
+ return -EFAULT;
+ }
+
+ dev_dbg(ctx->device->dev, "[%s]: Setting up DMA for buffer "
+ "(FROM_DEVICE)", __func__);
+
+ desc = channel->device->device_prep_slave_sg(channel,
+ ctx->device->dma.sg_dst,
+ ctx->device->dma.sg_dst_len,
+ direction,
+ DMA_CTRL_ACK |
+ DMA_PREP_INTERRUPT, NULL);
+
+ desc->callback = cryp_dma_out_callback;
+ desc->callback_param = ctx;
+ break;
+
+ default:
+ dev_dbg(ctx->device->dev, "[%s]: Invalid DMA direction",
+ __func__);
+ return -EFAULT;
+ }
+
+ cookie = desc->tx_submit(desc);
+ dma_async_issue_pending(channel);
+
+ return 0;
+}
+
+static void cryp_dma_done(struct cryp_ctx *ctx)
+{
+ struct dma_chan *chan;
+
+ dev_dbg(ctx->device->dev, "[%s]: ", __func__);
+
+ chan = ctx->device->dma.chan_mem2cryp;
+ chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
+ dma_unmap_sg(chan->device->dev, ctx->device->dma.sg_src,
+ ctx->device->dma.sg_src_len, DMA_TO_DEVICE);
+
+ chan = ctx->device->dma.chan_cryp2mem;
+ chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
+ dma_unmap_sg(chan->device->dev, ctx->device->dma.sg_dst,
+ ctx->device->dma.sg_dst_len, DMA_FROM_DEVICE);
+}
+
+static int cryp_dma_write(struct cryp_ctx *ctx, struct scatterlist *sg,
+ int len)
+{
+ int error = cryp_set_dma_transfer(ctx, sg, len, DMA_TO_DEVICE);
+ dev_dbg(ctx->device->dev, "[%s]: ", __func__);
+
+ if (error) {
+ dev_dbg(ctx->device->dev, "[%s]: cryp_set_dma_transfer() "
+ "failed", __func__);
+ return error;
+ }
+
+ return len;
+}
+
+static int cryp_dma_read(struct cryp_ctx *ctx, struct scatterlist *sg, int len)
+{
+ int error = cryp_set_dma_transfer(ctx, sg, len, DMA_FROM_DEVICE);
+ if (error) {
+ dev_dbg(ctx->device->dev, "[%s]: cryp_set_dma_transfer() "
+ "failed", __func__);
+ return error;
+ }
+
+ return len;
+}
+
+static void cryp_polling_mode(struct cryp_ctx *ctx,
+ struct cryp_device_data *device_data)
+{
+ int len = ctx->blocksize / BYTES_PER_WORD;
+ int remaining_length = ctx->datalen;
+ u32 *indata = (u32 *)ctx->indata;
+ u32 *outdata = (u32 *)ctx->outdata;
+
+ while (remaining_length > 0) {
+ writesl(&device_data->base->din, indata, len);
+ indata += len;
+ remaining_length -= (len * BYTES_PER_WORD);
+ cryp_wait_until_done(device_data);
+
+ readsl(&device_data->base->dout, outdata, len);
+ outdata += len;
+ cryp_wait_until_done(device_data);
+ }
+}
+
+static int cryp_disable_power(struct device *dev,
+ struct cryp_device_data *device_data,
+ bool save_device_context)
+{
+ int ret = 0;
+
+ dev_dbg(dev, "[%s]", __func__);
+
+ spin_lock(&device_data->power_state_spinlock);
+ if (!device_data->power_state)
+ goto out;
+
+ spin_lock(&device_data->ctx_lock);
+ if (save_device_context && device_data->current_ctx) {
+ cryp_save_device_context(device_data,
+ &device_data->current_ctx->dev_ctx,
+ cryp_mode);
+ device_data->restore_dev_ctx = true;
+ }
+ spin_unlock(&device_data->ctx_lock);
+
+ clk_disable(device_data->clk);
+ ret = regulator_disable(device_data->pwr_regulator);
+ if (ret)
+ dev_err(dev, "[%s]: "
+ "regulator_disable() failed!",
+ __func__);
+
+ device_data->power_state = false;
+
+out:
+ spin_unlock(&device_data->power_state_spinlock);
+
+ return ret;
+}
+
+static int cryp_enable_power(
+ struct device *dev,
+ struct cryp_device_data *device_data,
+ bool restore_device_context)
+{
+ int ret = 0;
+
+ dev_dbg(dev, "[%s]", __func__);
+
+ spin_lock(&device_data->power_state_spinlock);
+ if (!device_data->power_state) {
+ ret = regulator_enable(device_data->pwr_regulator);
+ if (ret) {
+ dev_err(dev, "[%s]: regulator_enable() failed!",
+ __func__);
+ goto out;
+ }
+
+ ret = clk_enable(device_data->clk);
+ if (ret) {
+ dev_err(dev, "[%s]: clk_enable() failed!",
+ __func__);
+ regulator_disable(device_data->pwr_regulator);
+ goto out;
+ }
+ device_data->power_state = true;
+ }
+
+ if (device_data->restore_dev_ctx) {
+ spin_lock(&device_data->ctx_lock);
+ if (restore_device_context && device_data->current_ctx) {
+ device_data->restore_dev_ctx = false;
+ cryp_restore_device_context(device_data,
+ &device_data->current_ctx->dev_ctx);
+ }
+ spin_unlock(&device_data->ctx_lock);
+ }
+out:
+ spin_unlock(&device_data->power_state_spinlock);
+
+ return ret;
+}
+
+static int hw_crypt_noxts(struct cryp_ctx *ctx,
+ struct cryp_device_data *device_data)
+{
+ int ret = 0;
+
+ const u8 *indata = ctx->indata;
+ u8 *outdata = ctx->outdata;
+ u32 datalen = ctx->datalen;
+ u32 outlen = datalen;
+
+ pr_debug(DEV_DBG_NAME " [%s]", __func__);
+
+ ctx->outlen = ctx->datalen;
+
+ if (unlikely(!IS_ALIGNED((u32)indata, 4))) {
+ pr_debug(DEV_DBG_NAME " [%s]: Data isn't aligned! Addr: "
+ "0x%08x", __func__, (u32)indata);
+ return -EINVAL;
+ }
+
+ ret = cryp_setup_context(ctx, device_data);
+
+ if (ret)
+ goto out;
+
+ if (cryp_mode == CRYP_MODE_INTERRUPT) {
+ cryp_enable_irq_src(device_data, CRYP_IRQ_SRC_INPUT_FIFO |
+ CRYP_IRQ_SRC_OUTPUT_FIFO);
+
+ /*
+ * ctx->outlen is decremented in the cryp_interrupt_handler
+ * function. We had to add cpu_relax() (barrier) to make sure
+ * that gcc didn't optimze away this variable.
+ */
+ while (ctx->outlen > 0)
+ cpu_relax();
+ } else if (cryp_mode == CRYP_MODE_POLLING ||
+ cryp_mode == CRYP_MODE_DMA) {
+ /*
+ * The reason for having DMA in this if case is that if we are
+ * running cryp_mode = 2, then we separate DMA routines for
+ * handling cipher/plaintext > blocksize, except when
+ * running the normal CRYPTO_ALG_TYPE_CIPHER, then we still use
+ * the polling mode. Overhead of doing DMA setup eats up the
+ * benefits using it.
+ */
+ cryp_polling_mode(ctx, device_data);
+ } else {
+ dev_err(ctx->device->dev, "[%s]: Invalid operation mode!",
+ __func__);
+ ret = -EPERM;
+ goto out;
+ }
+
+ cryp_save_device_context(device_data, &ctx->dev_ctx, cryp_mode);
+ ctx->updated = 1;
+
+out:
+ ctx->indata = indata;
+ ctx->outdata = outdata;
+ ctx->datalen = datalen;
+ ctx->outlen = outlen;
+
+ return ret;
+}
+
+static int get_nents(struct scatterlist *sg, int nbytes)
+{
+ int nents = 0;
+
+ while (nbytes > 0) {
+ nbytes -= sg->length;
+ sg = scatterwalk_sg_next(sg);
+ nents++;
+ }
+
+ return nents;
+}
+
+static int ablk_dma_crypt(struct ablkcipher_request *areq)
+{
+ struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
+ struct cryp_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+ struct cryp_device_data *device_data;
+
+ int bytes_written = 0;
+ int bytes_read = 0;
+ int ret;
+
+ pr_debug(DEV_DBG_NAME " [%s]", __func__);
+
+ ctx->datalen = areq->nbytes;
+ ctx->outlen = areq->nbytes;
+
+ ret = cryp_get_device_data(ctx, &device_data);
+ if (ret)
+ return ret;
+
+ ret = cryp_setup_context(ctx, device_data);
+ if (ret)
+ goto out;
+
+ /* We have the device now, so store the nents in the dma struct. */
+ ctx->device->dma.nents_src = get_nents(areq->src, ctx->datalen);
+ ctx->device->dma.nents_dst = get_nents(areq->dst, ctx->outlen);
+
+ /* Enable DMA in- and output. */
+ cryp_configure_for_dma(device_data, CRYP_DMA_ENABLE_BOTH_DIRECTIONS);
+
+ bytes_written = cryp_dma_write(ctx, areq->src, ctx->datalen);
+ bytes_read = cryp_dma_read(ctx, areq->dst, bytes_written);
+
+ wait_for_completion(&ctx->device->dma.cryp_dma_complete);
+ cryp_dma_done(ctx);
+
+ cryp_save_device_context(device_data, &ctx->dev_ctx, cryp_mode);
+ ctx->updated = 1;
+
+out:
+ spin_lock(&device_data->ctx_lock);
+ device_data->current_ctx = NULL;
+ ctx->device = NULL;
+ spin_unlock(&device_data->ctx_lock);
+
+ /*
+ * The down_interruptible part for this semaphore is called in
+ * cryp_get_device_data.
+ */
+ up(&driver_data.device_allocation);
+
+ if (unlikely(bytes_written != bytes_read))
+ return -EPERM;
+
+ return 0;
+}
+
+static int ablk_crypt(struct ablkcipher_request *areq)
+{
+ struct ablkcipher_walk walk;
+ struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
+ struct cryp_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+ struct cryp_device_data *device_data;
+ unsigned long src_paddr;
+ unsigned long dst_paddr;
+ int ret;
+ int nbytes;
+
+ pr_debug(DEV_DBG_NAME " [%s]", __func__);
+
+ ret = cryp_get_device_data(ctx, &device_data);
+ if (ret)
+ goto out;
+
+ ablkcipher_walk_init(&walk, areq->dst, areq->src, areq->nbytes);
+ ret = ablkcipher_walk_phys(areq, &walk);
+
+ if (ret) {
+ pr_err(DEV_DBG_NAME "[%s]: ablkcipher_walk_phys() failed!",
+ __func__);
+ goto out;
+ }
+
+ while ((nbytes = walk.nbytes) > 0) {
+ ctx->iv = walk.iv;
+ src_paddr = (page_to_phys(walk.src.page) + walk.src.offset);
+ ctx->indata = phys_to_virt(src_paddr);
+
+ dst_paddr = (page_to_phys(walk.dst.page) + walk.dst.offset);
+ ctx->outdata = phys_to_virt(dst_paddr);
+
+ ctx->datalen = nbytes - (nbytes % ctx->blocksize);
+
+ ret = hw_crypt_noxts(ctx, device_data);
+ if (ret)
+ goto out;
+
+ nbytes -= ctx->datalen;
+ ret = ablkcipher_walk_done(areq, &walk, nbytes);
+ if (ret)
+ goto out;
+ }
+ ablkcipher_walk_complete(&walk);
+
+out:
+ /* Release the device */
+ spin_lock(&device_data->ctx_lock);
+ device_data->current_ctx = NULL;
+ ctx->device = NULL;
+ spin_unlock(&device_data->ctx_lock);
+
+ /*
+ * The down_interruptible part for this semaphore is called in
+ * cryp_get_device_data.
+ */
+ up(&driver_data.device_allocation);
+
+ return ret;
+}
+
+static int aes_ablkcipher_setkey(struct crypto_ablkcipher *cipher,
+ const u8 *key, unsigned int keylen)
+{
+ struct cryp_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+ u32 *flags = &cipher->base.crt_flags;
+
+ pr_debug(DEV_DBG_NAME " [%s]", __func__);
+
+ switch (keylen) {
+ case AES_KEYSIZE_128:
+ ctx->config.keysize = CRYP_KEY_SIZE_128;
+ break;
+
+ case AES_KEYSIZE_192:
+ ctx->config.keysize = CRYP_KEY_SIZE_192;
+ break;
+
+ case AES_KEYSIZE_256:
+ ctx->config.keysize = CRYP_KEY_SIZE_256;
+ break;
+
+ default:
+ pr_err(DEV_DBG_NAME "[%s]: Unknown keylen!", __func__);
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+
+ memcpy(ctx->key, key, keylen);
+ ctx->keylen = keylen;
+
+ ctx->updated = 0;
+
+ return 0;
+}
+
+static int des_ablkcipher_setkey(struct crypto_ablkcipher *cipher,
+ const u8 *key, unsigned int keylen)
+{
+ struct cryp_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+ u32 *flags = &cipher->base.crt_flags;
+ u32 tmp[DES_EXPKEY_WORDS];
+ int ret;
+
+ pr_debug(DEV_DBG_NAME " [%s]", __func__);
+ if (keylen != DES_KEY_SIZE) {
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ pr_debug(DEV_DBG_NAME " [%s]: CRYPTO_TFM_RES_BAD_KEY_LEN",
+ __func__);
+ return -EINVAL;
+ }
+
+ ret = des_ekey(tmp, key);
+ if (unlikely(ret == 0) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ *flags |= CRYPTO_TFM_RES_WEAK_KEY;
+ pr_debug(DEV_DBG_NAME " [%s]: CRYPTO_TFM_REQ_WEAK_KEY",
+ __func__);
+ return -EINVAL;
+ }
+
+ memcpy(ctx->key, key, keylen);
+ ctx->keylen = keylen;
+
+ ctx->updated = 0;
+ return 0;
+}
+
+static int des3_ablkcipher_setkey(struct crypto_ablkcipher *cipher,
+ const u8 *key, unsigned int keylen)
+{
+ struct cryp_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+ u32 *flags = &cipher->base.crt_flags;
+ const u32 *K = (const u32 *)key;
+ u32 tmp[DES3_EDE_EXPKEY_WORDS];
+ int i, ret;
+
+ pr_debug(DEV_DBG_NAME " [%s]", __func__);
+ if (keylen != DES3_EDE_KEY_SIZE) {
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ pr_debug(DEV_DBG_NAME " [%s]: CRYPTO_TFM_RES_BAD_KEY_LEN",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* Checking key interdependency for weak key detection. */
+ if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
+ !((K[2] ^ K[4]) | (K[3] ^ K[5]))) &&
+ (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ *flags |= CRYPTO_TFM_RES_WEAK_KEY;
+ pr_debug(DEV_DBG_NAME " [%s]: CRYPTO_TFM_REQ_WEAK_KEY",
+ __func__);
+ return -EINVAL;
+ }
+ for (i = 0; i < 3; i++) {
+ ret = des_ekey(tmp, key + i*DES_KEY_SIZE);
+ if (unlikely(ret == 0) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ *flags |= CRYPTO_TFM_RES_WEAK_KEY;
+ pr_debug(DEV_DBG_NAME " [%s]: "
+ "CRYPTO_TFM_REQ_WEAK_KEY", __func__);
+ return -EINVAL;
+ }
+ }
+
+ memcpy(ctx->key, key, keylen);
+ ctx->keylen = keylen;
+
+ ctx->updated = 0;
+ return 0;
+}
+
+static int cryp_blk_encrypt(struct ablkcipher_request *areq)
+{
+ struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
+ struct cryp_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+
+ pr_debug(DEV_DBG_NAME " [%s]", __func__);
+
+ ctx->config.algodir = CRYP_ALGORITHM_ENCRYPT;
+
+ /*
+ * DMA does not work for DES due to a hw bug */
+ if (cryp_mode == CRYP_MODE_DMA && mode_is_aes(ctx->config.algomode))
+ return ablk_dma_crypt(areq);
+
+ /* For everything except DMA, we run the non DMA version. */
+ return ablk_crypt(areq);
+}
+
+static int cryp_blk_decrypt(struct ablkcipher_request *areq)
+{
+ struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
+ struct cryp_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+
+ pr_debug(DEV_DBG_NAME " [%s]", __func__);
+
+ ctx->config.algodir = CRYP_ALGORITHM_DECRYPT;
+
+ /* DMA does not work for DES due to a hw bug */
+ if (cryp_mode == CRYP_MODE_DMA && mode_is_aes(ctx->config.algomode))
+ return ablk_dma_crypt(areq);
+
+ /* For everything except DMA, we run the non DMA version. */
+ return ablk_crypt(areq);
+}
+
+struct cryp_algo_template {
+ enum cryp_algo_mode algomode;
+ struct crypto_alg crypto;
+};
+
+static int cryp_cra_init(struct crypto_tfm *tfm)
+{
+ struct cryp_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_alg *alg = tfm->__crt_alg;
+ struct cryp_algo_template *cryp_alg = container_of(alg,
+ struct cryp_algo_template,
+ crypto);
+
+ ctx->config.algomode = cryp_alg->algomode;
+ ctx->blocksize = crypto_tfm_alg_blocksize(tfm);
+
+ return 0;
+}
+
+static struct cryp_algo_template cryp_algs[] = {
+ {
+ .algomode = CRYP_ALGO_AES_ECB,
+ .crypto = {
+ .cra_name = "aes",
+ .cra_driver_name = "aes-ux500",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_init = cryp_cra_init,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = aes_ablkcipher_setkey,
+ .encrypt = cryp_blk_encrypt,
+ .decrypt = cryp_blk_decrypt
+ }
+ }
+ }
+ },
+ {
+ .algomode = CRYP_ALGO_AES_ECB,
+ .crypto = {
+ .cra_name = "ecb(aes)",
+ .cra_driver_name = "ecb-aes-ux500",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_init = cryp_cra_init,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = aes_ablkcipher_setkey,
+ .encrypt = cryp_blk_encrypt,
+ .decrypt = cryp_blk_decrypt,
+ }
+ }
+ }
+ },
+ {
+ .algomode = CRYP_ALGO_AES_CBC,
+ .crypto = {
+ .cra_name = "cbc(aes)",
+ .cra_driver_name = "cbc-aes-ux500",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_init = cryp_cra_init,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = aes_ablkcipher_setkey,
+ .encrypt = cryp_blk_encrypt,
+ .decrypt = cryp_blk_decrypt,
+ .ivsize = AES_BLOCK_SIZE,
+ }
+ }
+ }
+ },
+ {
+ .algomode = CRYP_ALGO_AES_CTR,
+ .crypto = {
+ .cra_name = "ctr(aes)",
+ .cra_driver_name = "ctr-aes-ux500",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_init = cryp_cra_init,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = aes_ablkcipher_setkey,
+ .encrypt = cryp_blk_encrypt,
+ .decrypt = cryp_blk_decrypt,
+ .ivsize = AES_BLOCK_SIZE,
+ }
+ }
+ }
+ },
+ {
+ .algomode = CRYP_ALGO_DES_ECB,
+ .crypto = {
+ .cra_name = "des",
+ .cra_driver_name = "des-ux500",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_init = cryp_cra_init,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .setkey = des_ablkcipher_setkey,
+ .encrypt = cryp_blk_encrypt,
+ .decrypt = cryp_blk_decrypt
+ }
+ }
+ }
+
+ },
+ {
+ .algomode = CRYP_ALGO_TDES_ECB,
+ .crypto = {
+ .cra_name = "des3_ede",
+ .cra_driver_name = "des3_ede-ux500",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_init = cryp_cra_init,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .setkey = des_ablkcipher_setkey,
+ .encrypt = cryp_blk_encrypt,
+ .decrypt = cryp_blk_decrypt
+ }
+ }
+ }
+ },
+ {
+ .algomode = CRYP_ALGO_DES_ECB,
+ .crypto = {
+ .cra_name = "ecb(des)",
+ .cra_driver_name = "ecb-des-ux500",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_init = cryp_cra_init,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .setkey = des_ablkcipher_setkey,
+ .encrypt = cryp_blk_encrypt,
+ .decrypt = cryp_blk_decrypt,
+ }
+ }
+ }
+ },
+ {
+ .algomode = CRYP_ALGO_TDES_ECB,
+ .crypto = {
+ .cra_name = "ecb(des3_ede)",
+ .cra_driver_name = "ecb-des3_ede-ux500",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_init = cryp_cra_init,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .setkey = des3_ablkcipher_setkey,
+ .encrypt = cryp_blk_encrypt,
+ .decrypt = cryp_blk_decrypt,
+ }
+ }
+ }
+ },
+ {
+ .algomode = CRYP_ALGO_DES_CBC,
+ .crypto = {
+ .cra_name = "cbc(des)",
+ .cra_driver_name = "cbc-des-ux500",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_init = cryp_cra_init,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .setkey = des_ablkcipher_setkey,
+ .encrypt = cryp_blk_encrypt,
+ .decrypt = cryp_blk_decrypt,
+ }
+ }
+ }
+ },
+ {
+ .algomode = CRYP_ALGO_TDES_CBC,
+ .crypto = {
+ .cra_name = "cbc(des3_ede)",
+ .cra_driver_name = "cbc-des3_ede-ux500",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_init = cryp_cra_init,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .setkey = des3_ablkcipher_setkey,
+ .encrypt = cryp_blk_encrypt,
+ .decrypt = cryp_blk_decrypt,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ }
+ }
+ }
+ }
+};
+
+/**
+ * cryp_algs_register_all -
+ */
+static int cryp_algs_register_all(void)
+{
+ int ret;
+ int i;
+ int count;
+
+ pr_debug("[%s]", __func__);
+
+ for (i = 0; i < ARRAY_SIZE(cryp_algs); i++) {
+ ret = crypto_register_alg(&cryp_algs[i].crypto);
+ if (ret) {
+ count = i;
+ pr_err("[%s] alg registration failed",
+ cryp_algs[i].crypto.cra_driver_name);
+ goto unreg;
+ }
+ }
+ return 0;
+unreg:
+ for (i = 0; i < count; i++)
+ crypto_unregister_alg(&cryp_algs[i].crypto);
+ return ret;
+}
+
+/**
+ * cryp_algs_unregister_all -
+ */
+static void cryp_algs_unregister_all(void)
+{
+ int i;
+
+ pr_debug(DEV_DBG_NAME " [%s]", __func__);
+
+ for (i = 0; i < ARRAY_SIZE(cryp_algs); i++)
+ crypto_unregister_alg(&cryp_algs[i].crypto);
+}
+
+static int ux500_cryp_probe(struct platform_device *pdev)
+{
+ int ret;
+ int cryp_error = 0;
+ struct resource *res = NULL;
+ struct resource *res_irq = NULL;
+ struct cryp_device_data *device_data;
+ struct cryp_protection_config prot = {
+ .privilege_access = CRYP_STATE_ENABLE
+ };
+ struct device *dev = &pdev->dev;
+
+ dev_dbg(dev, "[%s]", __func__);
+ device_data = kzalloc(sizeof(struct cryp_device_data), GFP_ATOMIC);
+ if (!device_data) {
+ dev_err(dev, "[%s]: kzalloc() failed!", __func__);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ device_data->dev = dev;
+ device_data->current_ctx = NULL;
+
+ /* Grab the DMA configuration from platform data. */
+ mem_to_engine = &((struct cryp_platform_data *)
+ dev->platform_data)->mem_to_engine;
+ engine_to_mem = &((struct cryp_platform_data *)
+ dev->platform_data)->engine_to_mem;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "[%s]: platform_get_resource() failed",
+ __func__);
+ ret = -ENODEV;
+ goto out_kfree;
+ }
+
+ res = request_mem_region(res->start, resource_size(res), pdev->name);
+ if (res == NULL) {
+ dev_err(dev, "[%s]: request_mem_region() failed",
+ __func__);
+ ret = -EBUSY;
+ goto out_kfree;
+ }
+
+ device_data->base = ioremap(res->start, resource_size(res));
+ if (!device_data->base) {
+ dev_err(dev, "[%s]: ioremap failed!", __func__);
+ ret = -ENOMEM;
+ goto out_free_mem;
+ }
+
+ spin_lock_init(&device_data->ctx_lock);
+ spin_lock_init(&device_data->power_state_spinlock);
+
+ /* Enable power for CRYP hardware block */
+ device_data->pwr_regulator = regulator_get(&pdev->dev, "v-ape");
+ if (IS_ERR(device_data->pwr_regulator)) {
+ dev_err(dev, "[%s]: could not get cryp regulator", __func__);
+ ret = PTR_ERR(device_data->pwr_regulator);
+ device_data->pwr_regulator = NULL;
+ goto out_unmap;
+ }
+
+ /* Enable the clk for CRYP hardware block */
+ device_data->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(device_data->clk)) {
+ dev_err(dev, "[%s]: clk_get() failed!", __func__);
+ ret = PTR_ERR(device_data->clk);
+ goto out_regulator;
+ }
+
+ /* Enable device power (and clock) */
+ ret = cryp_enable_power(device_data->dev, device_data, false);
+ if (ret) {
+ dev_err(dev, "[%s]: cryp_enable_power() failed!", __func__);
+ goto out_clk;
+ }
+
+ cryp_error = cryp_check(device_data);
+ if (cryp_error != 0) {
+ dev_err(dev, "[%s]: cryp_init() failed!", __func__);
+ ret = -EINVAL;
+ goto out_power;
+ }
+
+ cryp_error = cryp_configure_protection(device_data, &prot);
+ if (cryp_error != 0) {
+ dev_err(dev, "[%s]: cryp_configure_protection() failed!",
+ __func__);
+ ret = -EINVAL;
+ goto out_power;
+ }
+
+ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res_irq) {
+ dev_err(dev, "[%s]: IORESOURCE_IRQ unavailable",
+ __func__);
+ goto out_power;
+ }
+
+ ret = request_irq(res_irq->start,
+ cryp_interrupt_handler,
+ 0,
+ "cryp1",
+ device_data);
+ if (ret) {
+ dev_err(dev, "[%s]: Unable to request IRQ", __func__);
+ goto out_power;
+ }
+
+ if (cryp_mode == CRYP_MODE_DMA)
+ cryp_dma_setup_channel(device_data, dev);
+
+ platform_set_drvdata(pdev, device_data);
+
+ /* Put the new device into the device list... */
+ klist_add_tail(&device_data->list_node, &driver_data.device_list);
+
+ /* ... and signal that a new device is available. */
+ up(&driver_data.device_allocation);
+
+ atomic_set(&session_id, 1);
+
+ ret = cryp_algs_register_all();
+ if (ret) {
+ dev_err(dev, "[%s]: cryp_algs_register_all() failed!",
+ __func__);
+ goto out_power;
+ }
+
+ return 0;
+
+out_power:
+ cryp_disable_power(device_data->dev, device_data, false);
+
+out_clk:
+ clk_put(device_data->clk);
+
+out_regulator:
+ regulator_put(device_data->pwr_regulator);
+
+out_unmap:
+ iounmap(device_data->base);
+
+out_free_mem:
+ release_mem_region(res->start, resource_size(res));
+
+out_kfree:
+ kfree(device_data);
+out:
+ return ret;
+}
+
+static int ux500_cryp_remove(struct platform_device *pdev)
+{
+ struct resource *res = NULL;
+ struct resource *res_irq = NULL;
+ struct cryp_device_data *device_data;
+
+ dev_dbg(&pdev->dev, "[%s]", __func__);
+ device_data = platform_get_drvdata(pdev);
+ if (!device_data) {
+ dev_err(&pdev->dev, "[%s]: platform_get_drvdata() failed!",
+ __func__);
+ return -ENOMEM;
+ }
+
+ /* Try to decrease the number of available devices. */
+ if (down_trylock(&driver_data.device_allocation))
+ return -EBUSY;
+
+ /* Check that the device is free */
+ spin_lock(&device_data->ctx_lock);
+ /* current_ctx allocates a device, NULL = unallocated */
+ if (device_data->current_ctx) {
+ /* The device is busy */
+ spin_unlock(&device_data->ctx_lock);
+ /* Return the device to the pool. */
+ up(&driver_data.device_allocation);
+ return -EBUSY;
+ }
+
+ spin_unlock(&device_data->ctx_lock);
+
+ /* Remove the device from the list */
+ if (klist_node_attached(&device_data->list_node))
+ klist_remove(&device_data->list_node);
+
+ /* If this was the last device, remove the services */
+ if (list_empty(&driver_data.device_list.k_list))
+ cryp_algs_unregister_all();
+
+ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res_irq)
+ dev_err(&pdev->dev, "[%s]: IORESOURCE_IRQ, unavailable",
+ __func__);
+ else {
+ disable_irq(res_irq->start);
+ free_irq(res_irq->start, device_data);
+ }
+
+ if (cryp_disable_power(&pdev->dev, device_data, false))
+ dev_err(&pdev->dev, "[%s]: cryp_disable_power() failed",
+ __func__);
+
+ clk_put(device_data->clk);
+ regulator_put(device_data->pwr_regulator);
+
+ iounmap(device_data->base);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res)
+ release_mem_region(res->start, res->end - res->start + 1);
+
+ kfree(device_data);
+
+ return 0;
+}
+
+static void ux500_cryp_shutdown(struct platform_device *pdev)
+{
+ struct resource *res_irq = NULL;
+ struct cryp_device_data *device_data;
+
+ dev_dbg(&pdev->dev, "[%s]", __func__);
+
+ device_data = platform_get_drvdata(pdev);
+ if (!device_data) {
+ dev_err(&pdev->dev, "[%s]: platform_get_drvdata() failed!",
+ __func__);
+ return;
+ }
+
+ /* Check that the device is free */
+ spin_lock(&device_data->ctx_lock);
+ /* current_ctx allocates a device, NULL = unallocated */
+ if (!device_data->current_ctx) {
+ if (down_trylock(&driver_data.device_allocation))
+ dev_dbg(&pdev->dev, "[%s]: Cryp still in use!"
+ "Shutting down anyway...", __func__);
+ /**
+ * (Allocate the device)
+ * Need to set this to non-null (dummy) value,
+ * to avoid usage if context switching.
+ */
+ device_data->current_ctx++;
+ }
+ spin_unlock(&device_data->ctx_lock);
+
+ /* Remove the device from the list */
+ if (klist_node_attached(&device_data->list_node))
+ klist_remove(&device_data->list_node);
+
+ /* If this was the last device, remove the services */
+ if (list_empty(&driver_data.device_list.k_list))
+ cryp_algs_unregister_all();
+
+ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res_irq)
+ dev_err(&pdev->dev, "[%s]: IORESOURCE_IRQ, unavailable",
+ __func__);
+ else {
+ disable_irq(res_irq->start);
+ free_irq(res_irq->start, device_data);
+ }
+
+ if (cryp_disable_power(&pdev->dev, device_data, false))
+ dev_err(&pdev->dev, "[%s]: cryp_disable_power() failed",
+ __func__);
+
+}
+
+static int ux500_cryp_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ int ret;
+ struct cryp_device_data *device_data;
+ struct resource *res_irq;
+ struct cryp_ctx *temp_ctx = NULL;
+
+ dev_dbg(&pdev->dev, "[%s]", __func__);
+
+ /* Handle state? */
+ device_data = platform_get_drvdata(pdev);
+ if (!device_data) {
+ dev_err(&pdev->dev, "[%s]: platform_get_drvdata() failed!",
+ __func__);
+ return -ENOMEM;
+ }
+
+ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res_irq)
+ dev_err(&pdev->dev, "[%s]: IORESOURCE_IRQ, unavailable",
+ __func__);
+ else
+ disable_irq(res_irq->start);
+
+ spin_lock(&device_data->ctx_lock);
+ if (!device_data->current_ctx)
+ device_data->current_ctx++;
+ spin_unlock(&device_data->ctx_lock);
+
+ if (device_data->current_ctx == ++temp_ctx) {
+ if (down_interruptible(&driver_data.device_allocation))
+ dev_dbg(&pdev->dev, "[%s]: down_interruptible() "
+ "failed", __func__);
+ ret = cryp_disable_power(&pdev->dev, device_data, false);
+
+ } else
+ ret = cryp_disable_power(&pdev->dev, device_data, true);
+
+ if (ret)
+ dev_err(&pdev->dev, "[%s]: cryp_disable_power()", __func__);
+
+ return ret;
+}
+
+static int ux500_cryp_resume(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct cryp_device_data *device_data;
+ struct resource *res_irq;
+ struct cryp_ctx *temp_ctx = NULL;
+
+ dev_dbg(&pdev->dev, "[%s]", __func__);
+
+ device_data = platform_get_drvdata(pdev);
+ if (!device_data) {
+ dev_err(&pdev->dev, "[%s]: platform_get_drvdata() failed!",
+ __func__);
+ return -ENOMEM;
+ }
+
+ spin_lock(&device_data->ctx_lock);
+ if (device_data->current_ctx == ++temp_ctx)
+ device_data->current_ctx = NULL;
+ spin_unlock(&device_data->ctx_lock);
+
+
+ if (!device_data->current_ctx)
+ up(&driver_data.device_allocation);
+ else
+ ret = cryp_enable_power(&pdev->dev, device_data, true);
+
+ if (ret)
+ dev_err(&pdev->dev, "[%s]: cryp_enable_power() failed!",
+ __func__);
+ else {
+ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (res_irq)
+ enable_irq(res_irq->start);
+ }
+
+ return ret;
+}
+
+static struct platform_driver cryp_driver = {
+ .probe = ux500_cryp_probe,
+ .remove = ux500_cryp_remove,
+ .shutdown = ux500_cryp_shutdown,
+ .suspend = ux500_cryp_suspend,
+ .resume = ux500_cryp_resume,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "cryp1"
+ }
+};
+
+static int __init ux500_cryp_mod_init(void)
+{
+ pr_debug("[%s] is called!", __func__);
+ klist_init(&driver_data.device_list, NULL, NULL);
+ /* Initialize the semaphore to 0 devices (locked state) */
+ sema_init(&driver_data.device_allocation, 0);
+ return platform_driver_register(&cryp_driver);
+}
+
+static void __exit ux500_cryp_mod_fini(void)
+{
+ pr_debug("[%s] is called!", __func__);
+ platform_driver_unregister(&cryp_driver);
+ return;
+}
+
+module_init(ux500_cryp_mod_init);
+module_exit(ux500_cryp_mod_fini);
+
+module_param(cryp_mode, int, 0);
+
+MODULE_DESCRIPTION("Driver for ST-Ericsson UX500 CRYP crypto engine.");
+MODULE_ALIAS("aes-all");
+MODULE_ALIAS("des-all");
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/crypto/ux500/cryp/cryp_irq.c b/drivers/crypto/ux500/cryp/cryp_irq.c
new file mode 100644
index 000000000000..08d291cdbe6d
--- /dev/null
+++ b/drivers/crypto/ux500/cryp/cryp_irq.c
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Shujuan Chen <shujuan.chen@stericsson.com> for ST-Ericsson.
+ * Author: Jonas Linde <jonas.linde@stericsson.com> for ST-Ericsson.
+ * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson.
+ * Author: Berne Hebark <berne.herbark@stericsson.com> for ST-Ericsson.
+ * Author: Niklas Hernaeus <niklas.hernaeus@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitmap.h>
+#include <linux/device.h>
+
+#include "cryp.h"
+#include "cryp_p.h"
+#include "cryp_irq.h"
+#include "cryp_irqp.h"
+
+void cryp_enable_irq_src(struct cryp_device_data *device_data, u32 irq_src)
+{
+ u32 i;
+
+ dev_dbg(device_data->dev, "[%s]", __func__);
+
+ i = readl_relaxed(&device_data->base->imsc);
+ i = i | irq_src;
+ writel_relaxed(i, &device_data->base->imsc);
+}
+
+void cryp_disable_irq_src(struct cryp_device_data *device_data, u32 irq_src)
+{
+ u32 i;
+
+ dev_dbg(device_data->dev, "[%s]", __func__);
+
+ i = readl_relaxed(&device_data->base->imsc);
+ i = i & ~irq_src;
+ writel_relaxed(i, &device_data->base->imsc);
+}
+
+bool cryp_pending_irq_src(struct cryp_device_data *device_data, u32 irq_src)
+{
+ return (readl_relaxed(&device_data->base->mis) & irq_src) > 0;
+}
diff --git a/drivers/crypto/ux500/cryp/cryp_irq.h b/drivers/crypto/ux500/cryp/cryp_irq.h
new file mode 100644
index 000000000000..5a7837f1b8f9
--- /dev/null
+++ b/drivers/crypto/ux500/cryp/cryp_irq.h
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Shujuan Chen <shujuan.chen@stericsson.com> for ST-Ericsson.
+ * Author: Jonas Linde <jonas.linde@stericsson.com> for ST-Ericsson.
+ * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson.
+ * Author: Berne Hebark <berne.herbark@stericsson.com> for ST-Ericsson.
+ * Author: Niklas Hernaeus <niklas.hernaeus@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef _CRYP_IRQ_H_
+#define _CRYP_IRQ_H_
+
+#include "cryp.h"
+
+enum cryp_irq_src_id {
+ CRYP_IRQ_SRC_INPUT_FIFO = 0x1,
+ CRYP_IRQ_SRC_OUTPUT_FIFO = 0x2,
+ CRYP_IRQ_SRC_ALL = 0x3
+};
+
+/**
+ * M0 Funtions
+ */
+void cryp_enable_irq_src(struct cryp_device_data *device_data, u32 irq_src);
+
+void cryp_disable_irq_src(struct cryp_device_data *device_data, u32 irq_src);
+
+bool cryp_pending_irq_src(struct cryp_device_data *device_data, u32 irq_src);
+
+#endif /* _CRYP_IRQ_H_ */
diff --git a/drivers/crypto/ux500/cryp/cryp_irqp.h b/drivers/crypto/ux500/cryp/cryp_irqp.h
new file mode 100644
index 000000000000..8b339cc34bf8
--- /dev/null
+++ b/drivers/crypto/ux500/cryp/cryp_irqp.h
@@ -0,0 +1,125 @@
+/**
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Shujuan Chen <shujuan.chen@stericsson.com> for ST-Ericsson.
+ * Author: Jonas Linde <jonas.linde@stericsson.com> for ST-Ericsson.
+ * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson.
+ * Author: Berne Hebark <berne.herbark@stericsson.com> for ST-Ericsson.
+ * Author: Niklas Hernaeus <niklas.hernaeus@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __CRYP_IRQP_H_
+#define __CRYP_IRQP_H_
+
+#include "cryp_irq.h"
+
+/**
+ *
+ * CRYP Registers - Offset mapping
+ * +-----------------+
+ * 00h | CRYP_CR | Configuration register
+ * +-----------------+
+ * 04h | CRYP_SR | Status register
+ * +-----------------+
+ * 08h | CRYP_DIN | Data In register
+ * +-----------------+
+ * 0ch | CRYP_DOUT | Data out register
+ * +-----------------+
+ * 10h | CRYP_DMACR | DMA control register
+ * +-----------------+
+ * 14h | CRYP_IMSC | IMSC
+ * +-----------------+
+ * 18h | CRYP_RIS | Raw interrupt status
+ * +-----------------+
+ * 1ch | CRYP_MIS | Masked interrupt status.
+ * +-----------------+
+ * Key registers
+ * IVR registers
+ * Peripheral
+ * Cell IDs
+ *
+ * Refer data structure for other register map
+ */
+
+/**
+ * struct cryp_register
+ * @cr - Configuration register
+ * @status - Status register
+ * @din - Data input register
+ * @din_size - Data input size register
+ * @dout - Data output register
+ * @dout_size - Data output size register
+ * @dmacr - Dma control register
+ * @imsc - Interrupt mask set/clear register
+ * @ris - Raw interrupt status
+ * @mis - Masked interrupt statu register
+ * @key_1_l - Key register 1 L
+ * @key_1_r - Key register 1 R
+ * @key_2_l - Key register 2 L
+ * @key_2_r - Key register 2 R
+ * @key_3_l - Key register 3 L
+ * @key_3_r - Key register 3 R
+ * @key_4_l - Key register 4 L
+ * @key_4_r - Key register 4 R
+ * @init_vect_0_l - init vector 0 L
+ * @init_vect_0_r - init vector 0 R
+ * @init_vect_1_l - init vector 1 L
+ * @init_vect_1_r - init vector 1 R
+ * @cryp_unused1 - unused registers
+ * @itcr - Integration test control register
+ * @itip - Integration test input register
+ * @itop - Integration test output register
+ * @cryp_unused2 - unused registers
+ * @periphId0 - FE0 CRYP Peripheral Identication Register
+ * @periphId1 - FE4
+ * @periphId2 - FE8
+ * @periphId3 - FEC
+ * @pcellId0 - FF0 CRYP PCell Identication Register
+ * @pcellId1 - FF4
+ * @pcellId2 - FF8
+ * @pcellId3 - FFC
+ */
+struct cryp_register {
+ u32 cr; /* Configuration register */
+ u32 sr; /* Status register */
+ u32 din; /* Data input register */
+ u32 din_size; /* Data input size register */
+ u32 dout; /* Data output register */
+ u32 dout_size; /* Data output size register */
+ u32 dmacr; /* Dma control register */
+ u32 imsc; /* Interrupt mask set/clear register */
+ u32 ris; /* Raw interrupt status */
+ u32 mis; /* Masked interrupt statu register */
+
+ u32 key_1_l; /*Key register 1 L */
+ u32 key_1_r; /*Key register 1 R */
+ u32 key_2_l; /*Key register 2 L */
+ u32 key_2_r; /*Key register 2 R */
+ u32 key_3_l; /*Key register 3 L */
+ u32 key_3_r; /*Key register 3 R */
+ u32 key_4_l; /*Key register 4 L */
+ u32 key_4_r; /*Key register 4 R */
+
+ u32 init_vect_0_l; /*init vector 0 L */
+ u32 init_vect_0_r; /*init vector 0 R */
+ u32 init_vect_1_l; /*init vector 1 L */
+ u32 init_vect_1_r; /*init vector 1 R */
+
+ u32 cryp_unused1[(0x80 - 0x58) / sizeof(u32)]; /* unused registers */
+ u32 itcr; /*Integration test control register */
+ u32 itip; /*Integration test input register */
+ u32 itop; /*Integration test output register */
+ u32 cryp_unused2[(0xFE0 - 0x8C) / sizeof(u32)]; /* unused registers */
+
+ u32 periphId0; /* FE0 CRYP Peripheral Identication Register */
+ u32 periphId1; /* FE4 */
+ u32 periphId2; /* FE8 */
+ u32 periphId3; /* FEC */
+
+ u32 pcellId0; /* FF0 CRYP PCell Identication Register */
+ u32 pcellId1; /* FF4 */
+ u32 pcellId2; /* FF8 */
+ u32 pcellId3; /* FFC */
+};
+
+#endif
diff --git a/drivers/crypto/ux500/cryp/cryp_p.h b/drivers/crypto/ux500/cryp/cryp_p.h
new file mode 100644
index 000000000000..6dcffe15c2bc
--- /dev/null
+++ b/drivers/crypto/ux500/cryp/cryp_p.h
@@ -0,0 +1,123 @@
+/**
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Shujuan Chen <shujuan.chen@stericsson.com> for ST-Ericsson.
+ * Author: Jonas Linde <jonas.linde@stericsson.com> for ST-Ericsson.
+ * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson.
+ * Author: Berne Hebark <berne.herbark@stericsson.com> for ST-Ericsson.
+ * Author: Niklas Hernaeus <niklas.hernaeus@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef _CRYP_P_H_
+#define _CRYP_P_H_
+
+#include <linux/io.h>
+#include <linux/bitops.h>
+
+#include "cryp.h"
+#include "cryp_irqp.h"
+
+/**
+ * Generic Macros
+ */
+#define CRYP_SET_BITS(reg_name, mask) \
+ writel_relaxed((readl_relaxed(reg_name) | mask), reg_name)
+
+#define CRYP_WRITE_BIT(reg_name, val, mask) \
+ writel_relaxed(((readl_relaxed(reg_name) & ~(mask)) |\
+ ((val) & (mask))), reg_name)
+
+#define CRYP_TEST_BITS(reg_name, val) \
+ (readl_relaxed(reg_name) & (val))
+
+#define CRYP_PUT_BITS(reg, val, shift, mask) \
+ writel_relaxed(((readl_relaxed(reg) & ~(mask)) | \
+ (((u32)val << shift) & (mask))), reg)
+
+/**
+ * CRYP specific Macros
+ */
+#define CRYP_PERIPHERAL_ID0 0xE3
+#define CRYP_PERIPHERAL_ID1 0x05
+
+#define CRYP_PERIPHERAL_ID2_DB8500 0x28
+#define CRYP_PERIPHERAL_ID3 0x00
+
+#define CRYP_PCELL_ID0 0x0D
+#define CRYP_PCELL_ID1 0xF0
+#define CRYP_PCELL_ID2 0x05
+#define CRYP_PCELL_ID3 0xB1
+
+/**
+ * CRYP register default values
+ */
+#define MAX_DEVICE_SUPPORT 2
+
+/* Priv set, keyrden set and datatype 8bits swapped set as default. */
+#define CRYP_CR_DEFAULT 0x0482
+#define CRYP_DMACR_DEFAULT 0x0
+#define CRYP_IMSC_DEFAULT 0x0
+#define CRYP_DIN_DEFAULT 0x0
+#define CRYP_DOUT_DEFAULT 0x0
+#define CRYP_KEY_DEFAULT 0x0
+#define CRYP_INIT_VECT_DEFAULT 0x0
+
+/**
+ * CRYP Control register specific mask
+ */
+#define CRYP_CR_SECURE_MASK BIT(0)
+#define CRYP_CR_PRLG_MASK BIT(1)
+#define CRYP_CR_ALGODIR_MASK BIT(2)
+#define CRYP_CR_ALGOMODE_MASK (BIT(5) | BIT(4) | BIT(3))
+#define CRYP_CR_DATATYPE_MASK (BIT(7) | BIT(6))
+#define CRYP_CR_KEYSIZE_MASK (BIT(9) | BIT(8))
+#define CRYP_CR_KEYRDEN_MASK BIT(10)
+#define CRYP_CR_KSE_MASK BIT(11)
+#define CRYP_CR_START_MASK BIT(12)
+#define CRYP_CR_INIT_MASK BIT(13)
+#define CRYP_CR_FFLUSH_MASK BIT(14)
+#define CRYP_CR_CRYPEN_MASK BIT(15)
+#define CRYP_CR_CONTEXT_SAVE_MASK (CRYP_CR_SECURE_MASK |\
+ CRYP_CR_PRLG_MASK |\
+ CRYP_CR_ALGODIR_MASK |\
+ CRYP_CR_ALGOMODE_MASK |\
+ CRYP_CR_DATATYPE_MASK |\
+ CRYP_CR_KEYSIZE_MASK |\
+ CRYP_CR_KEYRDEN_MASK |\
+ CRYP_CR_DATATYPE_MASK)
+
+
+#define CRYP_SR_INFIFO_READY_MASK (BIT(0) | BIT(1))
+#define CRYP_SR_IFEM_MASK BIT(0)
+#define CRYP_SR_BUSY_MASK BIT(4)
+
+/**
+ * Bit position used while setting bits in register
+ */
+#define CRYP_CR_PRLG_POS 1
+#define CRYP_CR_ALGODIR_POS 2
+#define CRYP_CR_ALGOMODE_POS 3
+#define CRYP_CR_DATATYPE_POS 6
+#define CRYP_CR_KEYSIZE_POS 8
+#define CRYP_CR_KEYRDEN_POS 10
+#define CRYP_CR_KSE_POS 11
+#define CRYP_CR_START_POS 12
+#define CRYP_CR_INIT_POS 13
+#define CRYP_CR_CRYPEN_POS 15
+
+#define CRYP_SR_BUSY_POS 4
+
+/**
+ * CRYP PCRs------PC_NAND control register
+ * BIT_MASK
+ */
+#define CRYP_DMA_REQ_MASK (BIT(1) | BIT(0))
+#define CRYP_DMA_REQ_MASK_POS 0
+
+
+struct cryp_system_context {
+ /* CRYP Register structure */
+ struct cryp_register *p_cryp_reg[MAX_DEVICE_SUPPORT];
+};
+
+#endif
diff --git a/drivers/crypto/ux500/hash/Makefile b/drivers/crypto/ux500/hash/Makefile
new file mode 100644
index 000000000000..b2f90d9bac72
--- /dev/null
+++ b/drivers/crypto/ux500/hash/Makefile
@@ -0,0 +1,11 @@
+#
+# Copyright (C) ST-Ericsson SA 2010
+# Author: Shujuan Chen (shujuan.chen@stericsson.com)
+# License terms: GNU General Public License (GPL) version 2
+#
+ifdef CONFIG_CRYPTO_DEV_UX500_DEBUG
+CFLAGS_hash_core.o := -DDEBUG -O0
+endif
+
+obj-$(CONFIG_CRYPTO_DEV_UX500_HASH) += ux500_hash.o
+ux500_hash-objs := hash_core.o
diff --git a/drivers/crypto/ux500/hash/hash_alg.h b/drivers/crypto/ux500/hash/hash_alg.h
new file mode 100644
index 000000000000..cd9351cb24df
--- /dev/null
+++ b/drivers/crypto/ux500/hash/hash_alg.h
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Shujuan Chen (shujuan.chen@stericsson.com)
+ * Author: Joakim Bech (joakim.xx.bech@stericsson.com)
+ * Author: Berne Hebark (berne.hebark@stericsson.com))
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef _HASH_ALG_H
+#define _HASH_ALG_H
+
+#include <linux/bitops.h>
+
+#define HASH_BLOCK_SIZE 64
+#define HASH_DMA_ALIGN_SIZE 4
+#define HASH_DMA_PERFORMANCE_MIN_SIZE 1024
+#define HASH_BYTES_PER_WORD 4
+
+/* Maximum value of the length's high word */
+#define HASH_HIGH_WORD_MAX_VAL 0xFFFFFFFFUL
+
+/* Power on Reset values HASH registers */
+#define HASH_RESET_CR_VALUE 0x0
+#define HASH_RESET_STR_VALUE 0x0
+
+/* Number of context swap registers */
+#define HASH_CSR_COUNT 52
+
+#define HASH_RESET_CSRX_REG_VALUE 0x0
+#define HASH_RESET_CSFULL_REG_VALUE 0x0
+#define HASH_RESET_CSDATAIN_REG_VALUE 0x0
+
+#define HASH_RESET_INDEX_VAL 0x0
+#define HASH_RESET_BIT_INDEX_VAL 0x0
+#define HASH_RESET_BUFFER_VAL 0x0
+#define HASH_RESET_LEN_HIGH_VAL 0x0
+#define HASH_RESET_LEN_LOW_VAL 0x0
+
+/* Control register bitfields */
+#define HASH_CR_RESUME_MASK 0x11FCF
+
+#define HASH_CR_SWITCHON_POS 31
+#define HASH_CR_SWITCHON_MASK BIT(31)
+
+#define HASH_CR_EMPTYMSG_POS 20
+#define HASH_CR_EMPTYMSG_MASK BIT(20)
+
+#define HASH_CR_DINF_POS 12
+#define HASH_CR_DINF_MASK BIT(12)
+
+#define HASH_CR_NBW_POS 8
+#define HASH_CR_NBW_MASK 0x00000F00UL
+
+#define HASH_CR_LKEY_POS 16
+#define HASH_CR_LKEY_MASK BIT(16)
+
+#define HASH_CR_ALGO_POS 7
+#define HASH_CR_ALGO_MASK BIT(7)
+
+#define HASH_CR_MODE_POS 6
+#define HASH_CR_MODE_MASK BIT(6)
+
+#define HASH_CR_DATAFORM_POS 4
+#define HASH_CR_DATAFORM_MASK (BIT(4) | BIT(5))
+
+#define HASH_CR_DMAE_POS 3
+#define HASH_CR_DMAE_MASK BIT(3)
+
+#define HASH_CR_INIT_POS 2
+#define HASH_CR_INIT_MASK BIT(2)
+
+#define HASH_CR_PRIVN_POS 1
+#define HASH_CR_PRIVN_MASK BIT(1)
+
+#define HASH_CR_SECN_POS 0
+#define HASH_CR_SECN_MASK BIT(0)
+
+/* Start register bitfields */
+#define HASH_STR_DCAL_POS 8
+#define HASH_STR_DCAL_MASK BIT(8)
+#define HASH_STR_DEFAULT 0x0
+
+#define HASH_STR_NBLW_POS 0
+#define HASH_STR_NBLW_MASK 0x0000001FUL
+
+#define HASH_NBLW_MAX_VAL 0x1F
+
+/* PrimeCell IDs */
+#define HASH_P_ID0 0xE0
+#define HASH_P_ID1 0x05
+#define HASH_P_ID2 0x38
+#define HASH_P_ID3 0x00
+#define HASH_CELL_ID0 0x0D
+#define HASH_CELL_ID1 0xF0
+#define HASH_CELL_ID2 0x05
+#define HASH_CELL_ID3 0xB1
+
+#define HASH_SET_BITS(reg_name, mask) \
+ writel_relaxed((readl_relaxed(reg_name) | mask), reg_name)
+
+#define HASH_CLEAR_BITS(reg_name, mask) \
+ writel_relaxed((readl_relaxed(reg_name) & ~mask), reg_name)
+
+#define HASH_PUT_BITS(reg, val, shift, mask) \
+ writel_relaxed(((readl(reg) & ~(mask)) | \
+ (((u32)val << shift) & (mask))), reg)
+
+#define HASH_SET_DIN(val, len) writesl(&device_data->base->din, (val), (len))
+
+#define HASH_INITIALIZE \
+ HASH_PUT_BITS( \
+ &device_data->base->cr, \
+ 0x01, HASH_CR_INIT_POS, \
+ HASH_CR_INIT_MASK)
+
+#define HASH_SET_DATA_FORMAT(data_format) \
+ HASH_PUT_BITS( \
+ &device_data->base->cr, \
+ (u32) (data_format), HASH_CR_DATAFORM_POS, \
+ HASH_CR_DATAFORM_MASK)
+#define HASH_SET_NBLW(val) \
+ HASH_PUT_BITS( \
+ &device_data->base->str, \
+ (u32) (val), HASH_STR_NBLW_POS, \
+ HASH_STR_NBLW_MASK)
+#define HASH_SET_DCAL \
+ HASH_PUT_BITS( \
+ &device_data->base->str, \
+ 0x01, HASH_STR_DCAL_POS, \
+ HASH_STR_DCAL_MASK)
+
+/* Hardware access method */
+enum hash_mode {
+ HASH_MODE_CPU,
+ HASH_MODE_DMA
+};
+
+/**
+ * struct uint64 - Structure to handle 64 bits integers.
+ * @high_word: Most significant bits.
+ * @low_word: Least significant bits.
+ *
+ * Used to handle 64 bits integers.
+ */
+struct uint64 {
+ u32 high_word;
+ u32 low_word;
+};
+
+/**
+ * struct hash_register - Contains all registers in ux500 hash hardware.
+ * @cr: HASH control register (0x000).
+ * @din: HASH data input register (0x004).
+ * @str: HASH start register (0x008).
+ * @hx: HASH digest register 0..7 (0x00c-0x01C).
+ * @padding0: Reserved (0x02C).
+ * @itcr: Integration test control register (0x080).
+ * @itip: Integration test input register (0x084).
+ * @itop: Integration test output register (0x088).
+ * @padding1: Reserved (0x08C).
+ * @csfull: HASH context full register (0x0F8).
+ * @csdatain: HASH context swap data input register (0x0FC).
+ * @csrx: HASH context swap register 0..51 (0x100-0x1CC).
+ * @padding2: Reserved (0x1D0).
+ * @periphid0: HASH peripheral identification register 0 (0xFE0).
+ * @periphid1: HASH peripheral identification register 1 (0xFE4).
+ * @periphid2: HASH peripheral identification register 2 (0xFE8).
+ * @periphid3: HASH peripheral identification register 3 (0xFEC).
+ * @cellid0: HASH PCell identification register 0 (0xFF0).
+ * @cellid1: HASH PCell identification register 1 (0xFF4).
+ * @cellid2: HASH PCell identification register 2 (0xFF8).
+ * @cellid3: HASH PCell identification register 3 (0xFFC).
+ *
+ * The device communicates to the HASH via 32-bit-wide control registers
+ * accessible via the 32-bit width AMBA rev. 2.0 AHB Bus. Below is a structure
+ * with the registers used.
+ */
+struct hash_register {
+ u32 cr;
+ u32 din;
+ u32 str;
+ u32 hx[8];
+
+ u32 padding0[(0x080 - 0x02C) / sizeof(u32)];
+
+ u32 itcr;
+ u32 itip;
+ u32 itop;
+
+ u32 padding1[(0x0F8 - 0x08C) / sizeof(u32)];
+
+ u32 csfull;
+ u32 csdatain;
+ u32 csrx[HASH_CSR_COUNT];
+
+ u32 padding2[(0xFE0 - 0x1D0) / sizeof(u32)];
+
+ u32 periphid0;
+ u32 periphid1;
+ u32 periphid2;
+ u32 periphid3;
+
+ u32 cellid0;
+ u32 cellid1;
+ u32 cellid2;
+ u32 cellid3;
+};
+
+/**
+ * struct hash_state - Hash context state.
+ * @temp_cr: Temporary HASH Control Register.
+ * @str_reg: HASH Start Register.
+ * @din_reg: HASH Data Input Register.
+ * @csr[52]: HASH Context Swap Registers 0-39.
+ * @csfull: HASH Context Swap Registers 40 ie Status flags.
+ * @csdatain: HASH Context Swap Registers 41 ie Input data.
+ * @buffer: Working buffer for messages going to the hardware.
+ * @length: Length of the part of message hashed so far (floor(N/64) * 64).
+ * @index: Valid number of bytes in buffer (N % 64).
+ * @bit_index: Valid number of bits in buffer (N % 8).
+ *
+ * This structure is used between context switches, i.e. when ongoing jobs are
+ * interupted with new jobs. When this happens we need to store intermediate
+ * results in software.
+ *
+ * WARNING: "index" is the member of the structure, to be sure that "buffer"
+ * is aligned on a 4-bytes boundary. This is highly implementation dependent
+ * and MUST be checked whenever this code is ported on new platforms.
+ */
+struct hash_state {
+ u32 temp_cr;
+ u32 str_reg;
+ u32 din_reg;
+ u32 csr[52];
+ u32 csfull;
+ u32 csdatain;
+ u32 buffer[HASH_BLOCK_SIZE / sizeof(u32)];
+ struct uint64 length;
+ u8 index;
+ u8 bit_index;
+};
+
+/**
+ * enum hash_device_id - HASH device ID.
+ * @HASH_DEVICE_ID_0: Hash hardware with ID 0
+ * @HASH_DEVICE_ID_1: Hash hardware with ID 1
+ */
+enum hash_device_id {
+ HASH_DEVICE_ID_0 = 0,
+ HASH_DEVICE_ID_1 = 1
+};
+
+/**
+ * enum hash_data_format - HASH data format.
+ * @HASH_DATA_32_BITS: 32 bits data format
+ * @HASH_DATA_16_BITS: 16 bits data format
+ * @HASH_DATA_8_BITS: 8 bits data format.
+ * @HASH_DATA_1_BITS: 1 bit data format.
+ */
+enum hash_data_format {
+ HASH_DATA_32_BITS = 0x0,
+ HASH_DATA_16_BITS = 0x1,
+ HASH_DATA_8_BITS = 0x2,
+ HASH_DATA_1_BIT = 0x3
+};
+
+/**
+ * enum hash_algo - Enumeration for selecting between SHA1 or SHA2 algorithm.
+ * @HASH_ALGO_SHA1: Indicates that SHA1 is used.
+ * @HASH_ALGO_SHA2: Indicates that SHA2 (SHA256) is used.
+ */
+enum hash_algo {
+ HASH_ALGO_SHA1 = 0x0,
+ HASH_ALGO_SHA256 = 0x1
+};
+
+/**
+ * enum hash_op - Enumeration for selecting between HASH or HMAC mode.
+ * @HASH_OPER_MODE_HASH: Indicates usage of normal HASH mode.
+ * @HASH_OPER_MODE_HMAC: Indicates usage of HMAC.
+ */
+enum hash_op {
+ HASH_OPER_MODE_HASH = 0x0,
+ HASH_OPER_MODE_HMAC = 0x1
+};
+
+/**
+ * struct hash_config - Configuration data for the hardware.
+ * @data_format: Format of data entered into the hash data in register.
+ * @algorithm: Algorithm selection bit.
+ * @oper_mode: Operating mode selection bit.
+ */
+struct hash_config {
+ int data_format;
+ int algorithm;
+ int oper_mode;
+};
+
+/**
+ * struct hash_dma - Structure used for dma.
+ * @mask: DMA capabilities bitmap mask.
+ * @complete: Used to maintain state for a "completion".
+ * @chan_mem2hash: DMA channel.
+ * @cfg_mem2hash: DMA channel configuration.
+ * @sg_len: Scatterlist length.
+ * @sg: Scatterlist.
+ * @nents: Number of sg entries.
+ */
+struct hash_dma {
+ dma_cap_mask_t mask;
+ struct completion complete;
+ struct dma_chan *chan_mem2hash;
+ void *cfg_mem2hash;
+ int sg_len;
+ struct scatterlist *sg;
+ int nents;
+};
+
+/**
+ * struct hash_ctx - The context used for hash calculations.
+ * @key: The key used in the operation.
+ * @keylen: The length of the key.
+ * @state: The state of the current calculations.
+ * @config: The current configuration.
+ * @digestsize: The size of current digest.
+ * @device: Pointer to the device structure.
+ */
+struct hash_ctx {
+ u8 *key;
+ u32 keylen;
+ struct hash_config config;
+ int digestsize;
+ struct hash_device_data *device;
+};
+
+/**
+ * struct hash_ctx - The request context used for hash calculations.
+ * @state: The state of the current calculations.
+ * @dma_mode: Used in special cases (workaround), e.g. need to change to
+ * cpu mode, if not supported/working in dma mode.
+ * @updated: Indicates if hardware is initialized for new operations.
+ */
+struct hash_req_ctx {
+ struct hash_state state;
+ bool dma_mode;
+ u8 updated;
+};
+
+/**
+ * struct hash_device_data - structure for a hash device.
+ * @base: Pointer to the hardware base address.
+ * @list_node: For inclusion in klist.
+ * @dev: Pointer to the device dev structure.
+ * @ctx_lock: Spinlock for current_ctx.
+ * @current_ctx: Pointer to the currently allocated context.
+ * @power_state: TRUE = power state on, FALSE = power state off.
+ * @power_state_lock: Spinlock for power_state.
+ * @regulator: Pointer to the device's power control.
+ * @clk: Pointer to the device's clock control.
+ * @restore_dev_state: TRUE = saved state, FALSE = no saved state.
+ * @dma: Structure used for dma.
+ */
+struct hash_device_data {
+ struct hash_register __iomem *base;
+ struct klist_node list_node;
+ struct device *dev;
+ struct spinlock ctx_lock;
+ struct hash_ctx *current_ctx;
+ bool power_state;
+ struct spinlock power_state_lock;
+ struct regulator *regulator;
+ struct clk *clk;
+ bool restore_dev_state;
+ struct hash_state state; /* Used for saving and resuming state */
+ struct hash_dma dma;
+};
+
+int hash_check_hw(struct hash_device_data *device_data);
+
+int hash_setconfiguration(struct hash_device_data *device_data,
+ struct hash_config *config);
+
+void hash_begin(struct hash_device_data *device_data, struct hash_ctx *ctx);
+
+void hash_get_digest(struct hash_device_data *device_data,
+ u8 *digest, int algorithm);
+
+int hash_hw_update(struct ahash_request *req);
+
+int hash_save_state(struct hash_device_data *device_data,
+ struct hash_state *state);
+
+int hash_resume_state(struct hash_device_data *device_data,
+ const struct hash_state *state);
+
+#endif
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
new file mode 100644
index 000000000000..6dbb9ec709a3
--- /dev/null
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -0,0 +1,2009 @@
+/*
+ * Cryptographic API.
+ * Support for Nomadik hardware crypto engine.
+
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Shujuan Chen <shujuan.chen@stericsson.com> for ST-Ericsson
+ * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson
+ * Author: Berne Hebark <berne.herbark@stericsson.com> for ST-Ericsson.
+ * Author: Niklas Hernaeus <niklas.hernaeus@stericsson.com> for ST-Ericsson.
+ * Author: Andreas Westin <andreas.westin@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/klist.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/crypto.h>
+
+#include <linux/regulator/consumer.h>
+#include <linux/dmaengine.h>
+#include <linux/bitops.h>
+
+#include <crypto/internal/hash.h>
+#include <crypto/sha.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/algapi.h>
+
+#include <mach/crypto-ux500.h>
+#include <mach/hardware.h>
+
+#include "hash_alg.h"
+
+#define DEV_DBG_NAME "hashX hashX:"
+
+static int hash_mode;
+module_param(hash_mode, int, 0);
+MODULE_PARM_DESC(hash_mode, "CPU or DMA mode. CPU = 0 (default), DMA = 1");
+
+/**
+ * Pre-calculated empty message digests.
+ */
+static u8 zero_message_hash_sha1[SHA1_DIGEST_SIZE] = {
+ 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
+ 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
+ 0xaf, 0xd8, 0x07, 0x09
+};
+
+static u8 zero_message_hash_sha256[SHA256_DIGEST_SIZE] = {
+ 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
+ 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
+ 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
+ 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
+};
+
+/* HMAC-SHA1, no key */
+static u8 zero_message_hmac_sha1[SHA1_DIGEST_SIZE] = {
+ 0xfb, 0xdb, 0x1d, 0x1b, 0x18, 0xaa, 0x6c, 0x08,
+ 0x32, 0x4b, 0x7d, 0x64, 0xb7, 0x1f, 0xb7, 0x63,
+ 0x70, 0x69, 0x0e, 0x1d
+};
+
+/* HMAC-SHA256, no key */
+static u8 zero_message_hmac_sha256[SHA256_DIGEST_SIZE] = {
+ 0xb6, 0x13, 0x67, 0x9a, 0x08, 0x14, 0xd9, 0xec,
+ 0x77, 0x2f, 0x95, 0xd7, 0x78, 0xc3, 0x5f, 0xc5,
+ 0xff, 0x16, 0x97, 0xc4, 0x93, 0x71, 0x56, 0x53,
+ 0xc6, 0xc7, 0x12, 0x14, 0x42, 0x92, 0xc5, 0xad
+};
+
+/**
+ * struct hash_driver_data - data specific to the driver.
+ *
+ * @device_list: A list of registered devices to choose from.
+ * @device_allocation: A semaphore initialized with number of devices.
+ */
+struct hash_driver_data {
+ struct klist device_list;
+ struct semaphore device_allocation;
+};
+
+static struct hash_driver_data driver_data;
+
+/* Declaration of functions */
+/**
+ * hash_messagepad - Pads a message and write the nblw bits.
+ * @device_data: Structure for the hash device.
+ * @message: Last word of a message
+ * @index_bytes: The number of bytes in the last message
+ *
+ * This function manages the final part of the digest calculation, when less
+ * than 512 bits (64 bytes) remain in message. This means index_bytes < 64.
+ *
+ */
+static void hash_messagepad(struct hash_device_data *device_data,
+ const u32 *message, u8 index_bytes);
+
+/**
+ * release_hash_device - Releases a previously allocated hash device.
+ * @device_data: Structure for the hash device.
+ *
+ */
+static void release_hash_device(struct hash_device_data *device_data)
+{
+ spin_lock(&device_data->ctx_lock);
+ device_data->current_ctx->device = NULL;
+ device_data->current_ctx = NULL;
+ spin_unlock(&device_data->ctx_lock);
+
+ /*
+ * The down_interruptible part for this semaphore is called in
+ * cryp_get_device_data.
+ */
+ up(&driver_data.device_allocation);
+}
+
+static void hash_dma_setup_channel(struct hash_device_data *device_data,
+ struct device *dev)
+{
+ struct hash_platform_data *platform_data = dev->platform_data;
+ dma_cap_zero(device_data->dma.mask);
+ dma_cap_set(DMA_SLAVE, device_data->dma.mask);
+
+ device_data->dma.cfg_mem2hash = platform_data->mem_to_engine;
+ device_data->dma.chan_mem2hash =
+ dma_request_channel(device_data->dma.mask,
+ platform_data->dma_filter,
+ device_data->dma.cfg_mem2hash);
+
+ init_completion(&device_data->dma.complete);
+}
+
+static void hash_dma_callback(void *data)
+{
+ struct hash_ctx *ctx = (struct hash_ctx *) data;
+
+ complete(&ctx->device->dma.complete);
+}
+
+static int hash_set_dma_transfer(struct hash_ctx *ctx, struct scatterlist *sg,
+ int len, enum dma_data_direction direction)
+{
+ struct dma_async_tx_descriptor *desc = NULL;
+ struct dma_chan *channel = NULL;
+ dma_cookie_t cookie;
+
+ if (direction != DMA_TO_DEVICE) {
+ dev_err(ctx->device->dev, "[%s] Invalid DMA direction",
+ __func__);
+ return -EFAULT;
+ }
+
+ sg->length = ALIGN(sg->length, HASH_DMA_ALIGN_SIZE);
+
+ channel = ctx->device->dma.chan_mem2hash;
+ ctx->device->dma.sg = sg;
+ ctx->device->dma.sg_len = dma_map_sg(channel->device->dev,
+ ctx->device->dma.sg, ctx->device->dma.nents,
+ direction);
+
+ if (!ctx->device->dma.sg_len) {
+ dev_err(ctx->device->dev,
+ "[%s]: Could not map the sg list (TO_DEVICE)",
+ __func__);
+ return -EFAULT;
+ }
+
+ dev_dbg(ctx->device->dev, "[%s]: Setting up DMA for buffer "
+ "(TO_DEVICE)", __func__);
+ desc = channel->device->device_prep_slave_sg(channel,
+ ctx->device->dma.sg, ctx->device->dma.sg_len,
+ direction, DMA_CTRL_ACK | DMA_PREP_INTERRUPT, NULL);
+ if (!desc) {
+ dev_err(ctx->device->dev,
+ "[%s]: device_prep_slave_sg() failed!", __func__);
+ return -EFAULT;
+ }
+
+ desc->callback = hash_dma_callback;
+ desc->callback_param = ctx;
+
+ cookie = desc->tx_submit(desc);
+ dma_async_issue_pending(channel);
+
+ return 0;
+}
+
+static void hash_dma_done(struct hash_ctx *ctx)
+{
+ struct dma_chan *chan;
+
+ chan = ctx->device->dma.chan_mem2hash;
+ chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
+ dma_unmap_sg(chan->device->dev, ctx->device->dma.sg,
+ ctx->device->dma.sg_len, DMA_TO_DEVICE);
+
+}
+
+static int hash_dma_write(struct hash_ctx *ctx,
+ struct scatterlist *sg, int len)
+{
+ int error = hash_set_dma_transfer(ctx, sg, len, DMA_TO_DEVICE);
+ if (error) {
+ dev_dbg(ctx->device->dev, "[%s]: hash_set_dma_transfer() "
+ "failed", __func__);
+ return error;
+ }
+
+ return len;
+}
+
+/**
+ * get_empty_message_digest - Returns a pre-calculated digest for
+ * the empty message.
+ * @device_data: Structure for the hash device.
+ * @zero_hash: Buffer to return the empty message digest.
+ * @zero_hash_size: Hash size of the empty message digest.
+ * @zero_digest: True if zero_digest returned.
+ */
+static int get_empty_message_digest(
+ struct hash_device_data *device_data,
+ u8 *zero_hash, u32 *zero_hash_size, bool *zero_digest)
+{
+ int ret = 0;
+ struct hash_ctx *ctx = device_data->current_ctx;
+ *zero_digest = false;
+
+ /**
+ * Caller responsible for ctx != NULL.
+ */
+
+ if (HASH_OPER_MODE_HASH == ctx->config.oper_mode) {
+ if (HASH_ALGO_SHA1 == ctx->config.algorithm) {
+ memcpy(zero_hash, &zero_message_hash_sha1[0],
+ SHA1_DIGEST_SIZE);
+ *zero_hash_size = SHA1_DIGEST_SIZE;
+ *zero_digest = true;
+ } else if (HASH_ALGO_SHA256 ==
+ ctx->config.algorithm) {
+ memcpy(zero_hash, &zero_message_hash_sha256[0],
+ SHA256_DIGEST_SIZE);
+ *zero_hash_size = SHA256_DIGEST_SIZE;
+ *zero_digest = true;
+ } else {
+ dev_err(device_data->dev, "[%s] "
+ "Incorrect algorithm!"
+ , __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+ } else if (HASH_OPER_MODE_HMAC == ctx->config.oper_mode) {
+ if (!ctx->keylen) {
+ if (HASH_ALGO_SHA1 == ctx->config.algorithm) {
+ memcpy(zero_hash, &zero_message_hmac_sha1[0],
+ SHA1_DIGEST_SIZE);
+ *zero_hash_size = SHA1_DIGEST_SIZE;
+ *zero_digest = true;
+ } else if (HASH_ALGO_SHA256 == ctx->config.algorithm) {
+ memcpy(zero_hash, &zero_message_hmac_sha256[0],
+ SHA256_DIGEST_SIZE);
+ *zero_hash_size = SHA256_DIGEST_SIZE;
+ *zero_digest = true;
+ } else {
+ dev_err(device_data->dev, "[%s] "
+ "Incorrect algorithm!"
+ , __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+ } else {
+ dev_dbg(device_data->dev, "[%s] Continue hash "
+ "calculation, since hmac key avalable",
+ __func__);
+ }
+ }
+out:
+
+ return ret;
+}
+
+/**
+ * hash_disable_power - Request to disable power and clock.
+ * @device_data: Structure for the hash device.
+ * @save_device_state: If true, saves the current hw state.
+ *
+ * This function request for disabling power (regulator) and clock,
+ * and could also save current hw state.
+ */
+static int hash_disable_power(
+ struct hash_device_data *device_data,
+ bool save_device_state)
+{
+ int ret = 0;
+ struct device *dev = device_data->dev;
+
+ spin_lock(&device_data->power_state_lock);
+ if (!device_data->power_state)
+ goto out;
+
+ if (save_device_state) {
+ hash_save_state(device_data,
+ &device_data->state);
+ device_data->restore_dev_state = true;
+ }
+
+ clk_disable(device_data->clk);
+ ret = regulator_disable(device_data->regulator);
+ if (ret)
+ dev_err(dev, "[%s] regulator_disable() failed!", __func__);
+
+ device_data->power_state = false;
+
+out:
+ spin_unlock(&device_data->power_state_lock);
+
+ return ret;
+}
+
+/**
+ * hash_enable_power - Request to enable power and clock.
+ * @device_data: Structure for the hash device.
+ * @restore_device_state: If true, restores a previous saved hw state.
+ *
+ * This function request for enabling power (regulator) and clock,
+ * and could also restore a previously saved hw state.
+ */
+static int hash_enable_power(
+ struct hash_device_data *device_data,
+ bool restore_device_state)
+{
+ int ret = 0;
+ struct device *dev = device_data->dev;
+
+ spin_lock(&device_data->power_state_lock);
+ if (!device_data->power_state) {
+ ret = regulator_enable(device_data->regulator);
+ if (ret) {
+ dev_err(dev, "[%s]: regulator_enable() failed!",
+ __func__);
+ goto out;
+ }
+ ret = clk_enable(device_data->clk);
+ if (ret) {
+ dev_err(dev, "[%s]: clk_enable() failed!",
+ __func__);
+ ret = regulator_disable(
+ device_data->regulator);
+ goto out;
+ }
+ device_data->power_state = true;
+ }
+
+ if (device_data->restore_dev_state) {
+ if (restore_device_state) {
+ device_data->restore_dev_state = false;
+ hash_resume_state(device_data,
+ &device_data->state);
+ }
+ }
+out:
+ spin_unlock(&device_data->power_state_lock);
+
+ return ret;
+}
+
+/**
+ * hash_get_device_data - Checks for an available hash device and return it.
+ * @hash_ctx: Structure for the hash context.
+ * @device_data: Structure for the hash device.
+ *
+ * This function check for an available hash device and return it to
+ * the caller.
+ * Note! Caller need to release the device, calling up().
+ */
+static int hash_get_device_data(struct hash_ctx *ctx,
+ struct hash_device_data **device_data)
+{
+ int ret;
+ struct klist_iter device_iterator;
+ struct klist_node *device_node;
+ struct hash_device_data *local_device_data = NULL;
+
+ /* Wait until a device is available */
+ ret = down_interruptible(&driver_data.device_allocation);
+ if (ret)
+ return ret; /* Interrupted */
+
+ /* Select a device */
+ klist_iter_init(&driver_data.device_list, &device_iterator);
+ device_node = klist_next(&device_iterator);
+ while (device_node) {
+ local_device_data = container_of(device_node,
+ struct hash_device_data, list_node);
+ spin_lock(&local_device_data->ctx_lock);
+ /* current_ctx allocates a device, NULL = unallocated */
+ if (local_device_data->current_ctx) {
+ device_node = klist_next(&device_iterator);
+ } else {
+ local_device_data->current_ctx = ctx;
+ ctx->device = local_device_data;
+ spin_unlock(&local_device_data->ctx_lock);
+ break;
+ }
+ spin_unlock(&local_device_data->ctx_lock);
+ }
+ klist_iter_exit(&device_iterator);
+
+ if (!device_node) {
+ /**
+ * No free device found.
+ * Since we allocated a device with down_interruptible, this
+ * should not be able to happen.
+ * Number of available devices, which are contained in
+ * device_allocation, is therefore decremented by not doing
+ * an up(device_allocation).
+ */
+ return -EBUSY;
+ }
+
+ *device_data = local_device_data;
+
+ return 0;
+}
+
+/**
+ * hash_hw_write_key - Writes the key to the hardware registries.
+ *
+ * @device_data: Structure for the hash device.
+ * @key: Key to be written.
+ * @keylen: The lengt of the key.
+ *
+ * Note! This function DOES NOT write to the NBLW registry, even though
+ * specified in the the hw design spec. Either due to incorrect info in the
+ * spec or due to a bug in the hw.
+ */
+static void hash_hw_write_key(struct hash_device_data *device_data,
+ const u8 *key, unsigned int keylen)
+{
+ u32 word = 0;
+ int nwords = 1;
+
+ HASH_CLEAR_BITS(&device_data->base->str, HASH_STR_NBLW_MASK);
+
+ while (keylen >= 4) {
+ u32 *key_word = (u32 *)key;
+
+ HASH_SET_DIN(key_word, nwords);
+ keylen -= 4;
+ key += 4;
+ }
+
+ /* Take care of the remaining bytes in the last word */
+ if (keylen) {
+ word = 0;
+ while (keylen) {
+ word |= (key[keylen - 1] << (8 * (keylen - 1)));
+ keylen--;
+ }
+
+ HASH_SET_DIN(&word, nwords);
+ }
+
+ while (device_data->base->str & HASH_STR_DCAL_MASK)
+ cpu_relax();
+
+ HASH_SET_DCAL;
+
+ while (device_data->base->str & HASH_STR_DCAL_MASK)
+ cpu_relax();
+}
+
+/**
+ * init_hash_hw - Initialise the hash hardware for a new calculation.
+ * @device_data: Structure for the hash device.
+ * @ctx: The hash context.
+ *
+ * This function will enable the bits needed to clear and start a new
+ * calculation.
+ */
+static int init_hash_hw(struct hash_device_data *device_data,
+ struct hash_ctx *ctx)
+{
+ int ret = 0;
+
+ ret = hash_setconfiguration(device_data, &ctx->config);
+ if (ret) {
+ dev_err(device_data->dev, "[%s] hash_setconfiguration() "
+ "failed!", __func__);
+ return ret;
+ }
+
+ hash_begin(device_data, ctx);
+
+ if (ctx->config.oper_mode == HASH_OPER_MODE_HMAC)
+ hash_hw_write_key(device_data, ctx->key, ctx->keylen);
+
+ return ret;
+}
+
+/**
+ * hash_get_nents - Return number of entries (nents) in scatterlist (sg).
+ *
+ * @sg: Scatterlist.
+ * @size: Size in bytes.
+ * @aligned: True if sg data aligned to work in DMA mode.
+ *
+ */
+static int hash_get_nents(struct scatterlist *sg, int size, bool *aligned)
+{
+ int nents = 0;
+ bool aligned_data = true;
+
+ while (size > 0 && sg) {
+ nents++;
+ size -= sg->length;
+
+ /* hash_set_dma_transfer will align last nent */
+ if ((aligned && !IS_ALIGNED(sg->offset, HASH_DMA_ALIGN_SIZE))
+ || (!IS_ALIGNED(sg->length, HASH_DMA_ALIGN_SIZE) &&
+ size > 0))
+ aligned_data = false;
+
+ sg = sg_next(sg);
+ }
+
+ if (aligned)
+ *aligned = aligned_data;
+
+ if (size != 0)
+ return -EFAULT;
+
+ return nents;
+}
+
+/**
+ * hash_dma_valid_data - checks for dma valid sg data.
+ * @sg: Scatterlist.
+ * @datasize: Datasize in bytes.
+ *
+ * NOTE! This function checks for dma valid sg data, since dma
+ * only accept datasizes of even wordsize.
+ */
+static bool hash_dma_valid_data(struct scatterlist *sg, int datasize)
+{
+ bool aligned;
+
+ /* Need to include at least one nent, else error */
+ if (hash_get_nents(sg, datasize, &aligned) < 1)
+ return false;
+
+ return aligned;
+}
+
+/**
+ * hash_init - Common hash init function for SHA1/SHA2 (SHA256).
+ * @req: The hash request for the job.
+ *
+ * Initialize structures.
+ */
+static int hash_init(struct ahash_request *req)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct hash_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct hash_req_ctx *req_ctx = ahash_request_ctx(req);
+
+ if (!ctx->key)
+ ctx->keylen = 0;
+
+ memset(&req_ctx->state, 0, sizeof(struct hash_state));
+ req_ctx->updated = 0;
+ if (hash_mode == HASH_MODE_DMA) {
+ if (req->nbytes < HASH_DMA_ALIGN_SIZE) {
+ req_ctx->dma_mode = false; /* Don't use DMA */
+
+ pr_debug(DEV_DBG_NAME " [%s] DMA mode, but direct "
+ "to CPU mode for data size < %d",
+ __func__, HASH_DMA_ALIGN_SIZE);
+ } else {
+ if (req->nbytes >= HASH_DMA_PERFORMANCE_MIN_SIZE &&
+ hash_dma_valid_data(req->src,
+ req->nbytes)) {
+ req_ctx->dma_mode = true;
+ } else {
+ req_ctx->dma_mode = false;
+ pr_debug(DEV_DBG_NAME " [%s] DMA mode, but use"
+ " CPU mode for datalength < %d"
+ " or non-aligned data, except "
+ "in last nent", __func__,
+ HASH_DMA_PERFORMANCE_MIN_SIZE);
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * hash_processblock - This function processes a single block of 512 bits (64
+ * bytes), word aligned, starting at message.
+ * @device_data: Structure for the hash device.
+ * @message: Block (512 bits) of message to be written to
+ * the HASH hardware.
+ *
+ */
+static void hash_processblock(
+ struct hash_device_data *device_data,
+ const u32 *message, int length)
+{
+ int len = length / HASH_BYTES_PER_WORD;
+ /*
+ * NBLW bits. Reset the number of bits in last word (NBLW).
+ */
+ HASH_CLEAR_BITS(&device_data->base->str, HASH_STR_NBLW_MASK);
+
+ /*
+ * Write message data to the HASH_DIN register.
+ */
+ HASH_SET_DIN(message, len);
+}
+
+/**
+ * hash_messagepad - Pads a message and write the nblw bits.
+ * @device_data: Structure for the hash device.
+ * @message: Last word of a message.
+ * @index_bytes: The number of bytes in the last message.
+ *
+ * This function manages the final part of the digest calculation, when less
+ * than 512 bits (64 bytes) remain in message. This means index_bytes < 64.
+ *
+ */
+static void hash_messagepad(struct hash_device_data *device_data,
+ const u32 *message, u8 index_bytes)
+{
+ int nwords = 1;
+
+ /*
+ * Clear hash str register, only clear NBLW
+ * since DCAL will be reset by hardware.
+ */
+ HASH_CLEAR_BITS(&device_data->base->str, HASH_STR_NBLW_MASK);
+
+ /* Main loop */
+ while (index_bytes >= 4) {
+ HASH_SET_DIN(message, nwords);
+ index_bytes -= 4;
+ message++;
+ }
+
+ if (index_bytes)
+ HASH_SET_DIN(message, nwords);
+
+ while (device_data->base->str & HASH_STR_DCAL_MASK)
+ cpu_relax();
+
+ /* num_of_bytes == 0 => NBLW <- 0 (32 bits valid in DATAIN) */
+ HASH_SET_NBLW(index_bytes * 8);
+ dev_dbg(device_data->dev, "[%s] DIN=0x%08x NBLW=%d", __func__,
+ readl_relaxed(&device_data->base->din),
+ (int)(readl_relaxed(&device_data->base->str) &
+ HASH_STR_NBLW_MASK));
+ HASH_SET_DCAL;
+ dev_dbg(device_data->dev, "[%s] after dcal -> DIN=0x%08x NBLW=%d",
+ __func__, readl_relaxed(&device_data->base->din),
+ (int)(readl_relaxed(&device_data->base->str) &
+ HASH_STR_NBLW_MASK));
+
+ while (device_data->base->str & HASH_STR_DCAL_MASK)
+ cpu_relax();
+}
+
+/**
+ * hash_incrementlength - Increments the length of the current message.
+ * @ctx: Hash context
+ * @incr: Length of message processed already
+ *
+ * Overflow cannot occur, because conditions for overflow are checked in
+ * hash_hw_update.
+ */
+static void hash_incrementlength(struct hash_req_ctx *ctx, u32 incr)
+{
+ ctx->state.length.low_word += incr;
+
+ /* Check for wrap-around */
+ if (ctx->state.length.low_word < incr)
+ ctx->state.length.high_word++;
+}
+
+/**
+ * hash_setconfiguration - Sets the required configuration for the hash
+ * hardware.
+ * @device_data: Structure for the hash device.
+ * @config: Pointer to a configuration structure.
+ */
+int hash_setconfiguration(struct hash_device_data *device_data,
+ struct hash_config *config)
+{
+ int ret = 0;
+
+ if (config->algorithm != HASH_ALGO_SHA1 &&
+ config->algorithm != HASH_ALGO_SHA256)
+ return -EPERM;
+
+ /*
+ * DATAFORM bits. Set the DATAFORM bits to 0b11, which means the data
+ * to be written to HASH_DIN is considered as 32 bits.
+ */
+ HASH_SET_DATA_FORMAT(config->data_format);
+
+ /*
+ * ALGO bit. Set to 0b1 for SHA-1 and 0b0 for SHA-256
+ */
+ switch (config->algorithm) {
+ case HASH_ALGO_SHA1:
+ HASH_SET_BITS(&device_data->base->cr, HASH_CR_ALGO_MASK);
+ break;
+
+ case HASH_ALGO_SHA256:
+ HASH_CLEAR_BITS(&device_data->base->cr, HASH_CR_ALGO_MASK);
+ break;
+
+ default:
+ dev_err(device_data->dev, "[%s] Incorrect algorithm.",
+ __func__);
+ return -EPERM;
+ }
+
+ /*
+ * MODE bit. This bit selects between HASH or HMAC mode for the
+ * selected algorithm. 0b0 = HASH and 0b1 = HMAC.
+ */
+ if (HASH_OPER_MODE_HASH == config->oper_mode)
+ HASH_CLEAR_BITS(&device_data->base->cr,
+ HASH_CR_MODE_MASK);
+ else if (HASH_OPER_MODE_HMAC == config->oper_mode) {
+ HASH_SET_BITS(&device_data->base->cr,
+ HASH_CR_MODE_MASK);
+ if (device_data->current_ctx->keylen > HASH_BLOCK_SIZE) {
+ /* Truncate key to blocksize */
+ dev_dbg(device_data->dev, "[%s] LKEY set", __func__);
+ HASH_SET_BITS(&device_data->base->cr,
+ HASH_CR_LKEY_MASK);
+ } else {
+ dev_dbg(device_data->dev, "[%s] LKEY cleared",
+ __func__);
+ HASH_CLEAR_BITS(&device_data->base->cr,
+ HASH_CR_LKEY_MASK);
+ }
+ } else { /* Wrong hash mode */
+ ret = -EPERM;
+ dev_err(device_data->dev, "[%s] HASH_INVALID_PARAMETER!",
+ __func__);
+ }
+ return ret;
+}
+
+/**
+ * hash_begin - This routine resets some globals and initializes the hash
+ * hardware.
+ * @device_data: Structure for the hash device.
+ * @ctx: Hash context.
+ */
+void hash_begin(struct hash_device_data *device_data, struct hash_ctx *ctx)
+{
+ /* HW and SW initializations */
+ /* Note: there is no need to initialize buffer and digest members */
+
+ while (device_data->base->str & HASH_STR_DCAL_MASK)
+ cpu_relax();
+
+ /*
+ * INIT bit. Set this bit to 0b1 to reset the HASH processor core and
+ * prepare the initialize the HASH accelerator to compute the message
+ * digest of a new message.
+ */
+ HASH_INITIALIZE;
+
+ /*
+ * NBLW bits. Reset the number of bits in last word (NBLW).
+ */
+ HASH_CLEAR_BITS(&device_data->base->str, HASH_STR_NBLW_MASK);
+}
+
+int hash_process_data(
+ struct hash_device_data *device_data,
+ struct hash_ctx *ctx, struct hash_req_ctx *req_ctx,
+ int msg_length, u8 *data_buffer, u8 *buffer, u8 *index)
+{
+ int ret = 0;
+ u32 count;
+
+ do {
+ if ((*index + msg_length) < HASH_BLOCK_SIZE) {
+ for (count = 0; count < msg_length; count++) {
+ buffer[*index + count] =
+ *(data_buffer + count);
+ }
+ *index += msg_length;
+ msg_length = 0;
+ } else {
+ if (req_ctx->updated) {
+
+ ret = hash_resume_state(device_data,
+ &device_data->state);
+ memmove(req_ctx->state.buffer,
+ device_data->state.buffer,
+ HASH_BLOCK_SIZE / sizeof(u32));
+ if (ret) {
+ dev_err(device_data->dev, "[%s] "
+ "hash_resume_state()"
+ " failed!", __func__);
+ goto out;
+ }
+ } else {
+ ret = init_hash_hw(device_data, ctx);
+ if (ret) {
+ dev_err(device_data->dev, "[%s] "
+ "init_hash_hw()"
+ " failed!", __func__);
+ goto out;
+ }
+ req_ctx->updated = 1;
+ }
+ /*
+ * If 'data_buffer' is four byte aligned and
+ * local buffer does not have any data, we can
+ * write data directly from 'data_buffer' to
+ * HW peripheral, otherwise we first copy data
+ * to a local buffer
+ */
+ if ((0 == (((u32)data_buffer) % 4))
+ && (0 == *index))
+ hash_processblock(device_data,
+ (const u32 *)
+ data_buffer, HASH_BLOCK_SIZE);
+ else {
+ for (count = 0; count <
+ (u32)(HASH_BLOCK_SIZE -
+ *index);
+ count++) {
+ buffer[*index + count] =
+ *(data_buffer + count);
+ }
+ hash_processblock(device_data,
+ (const u32 *)buffer,
+ HASH_BLOCK_SIZE);
+ }
+ hash_incrementlength(req_ctx, HASH_BLOCK_SIZE);
+ data_buffer += (HASH_BLOCK_SIZE - *index);
+
+ msg_length -= (HASH_BLOCK_SIZE - *index);
+ *index = 0;
+
+ ret = hash_save_state(device_data,
+ &device_data->state);
+
+ memmove(device_data->state.buffer,
+ req_ctx->state.buffer,
+ HASH_BLOCK_SIZE / sizeof(u32));
+ if (ret) {
+ dev_err(device_data->dev, "[%s] "
+ "hash_save_state()"
+ " failed!", __func__);
+ goto out;
+ }
+ }
+ } while (msg_length != 0);
+out:
+
+ return ret;
+}
+
+/**
+ * hash_dma_final - The hash dma final function for SHA1/SHA256.
+ * @req: The hash request for the job.
+ */
+static int hash_dma_final(struct ahash_request *req)
+{
+ int ret = 0;
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct hash_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct hash_req_ctx *req_ctx = ahash_request_ctx(req);
+ struct hash_device_data *device_data;
+ u8 digest[SHA256_DIGEST_SIZE];
+ int bytes_written = 0;
+
+ ret = hash_get_device_data(ctx, &device_data);
+ if (ret)
+ return ret;
+
+ dev_dbg(device_data->dev, "[%s] (ctx=0x%x)!", __func__, (u32) ctx);
+
+ if (req_ctx->updated) {
+ ret = hash_resume_state(device_data, &device_data->state);
+
+ if (ret) {
+ dev_err(device_data->dev, "[%s] hash_resume_state() "
+ "failed!", __func__);
+ goto out;
+ }
+
+ }
+
+ if (!req_ctx->updated) {
+ ret = hash_setconfiguration(device_data, &ctx->config);
+ if (ret) {
+ dev_err(device_data->dev, "[%s] "
+ "hash_setconfiguration() failed!",
+ __func__);
+ goto out;
+ }
+
+ /* Enable DMA input */
+ if (hash_mode != HASH_MODE_DMA || !req_ctx->dma_mode) {
+ HASH_CLEAR_BITS(&device_data->base->cr,
+ HASH_CR_DMAE_MASK);
+ } else {
+ HASH_SET_BITS(&device_data->base->cr,
+ HASH_CR_DMAE_MASK);
+ HASH_SET_BITS(&device_data->base->cr,
+ HASH_CR_PRIVN_MASK);
+ }
+
+ HASH_INITIALIZE;
+
+ if (ctx->config.oper_mode == HASH_OPER_MODE_HMAC)
+ hash_hw_write_key(device_data, ctx->key, ctx->keylen);
+
+ /* Number of bits in last word = (nbytes * 8) % 32 */
+ HASH_SET_NBLW((req->nbytes * 8) % 32);
+ req_ctx->updated = 1;
+ }
+
+ /* Store the nents in the dma struct. */
+ ctx->device->dma.nents = hash_get_nents(req->src, req->nbytes, NULL);
+ if (!ctx->device->dma.nents) {
+ dev_err(device_data->dev, "[%s] "
+ "ctx->device->dma.nents = 0", __func__);
+ goto out;
+ }
+
+ bytes_written = hash_dma_write(ctx, req->src, req->nbytes);
+ if (bytes_written != req->nbytes) {
+ dev_err(device_data->dev, "[%s] "
+ "hash_dma_write() failed!", __func__);
+ goto out;
+ }
+
+ wait_for_completion(&ctx->device->dma.complete);
+ hash_dma_done(ctx);
+
+ while (device_data->base->str & HASH_STR_DCAL_MASK)
+ cpu_relax();
+
+ if (ctx->config.oper_mode == HASH_OPER_MODE_HMAC && ctx->key) {
+ unsigned int keylen = ctx->keylen;
+ u8 *key = ctx->key;
+
+ dev_dbg(device_data->dev, "[%s] keylen: %d", __func__,
+ ctx->keylen);
+ hash_hw_write_key(device_data, key, keylen);
+ }
+
+ hash_get_digest(device_data, digest, ctx->config.algorithm);
+ memcpy(req->result, digest, ctx->digestsize);
+
+out:
+ release_hash_device(device_data);
+
+ /**
+ * Allocated in setkey, and only used in HMAC.
+ */
+ kfree(ctx->key);
+
+ return ret;
+}
+
+/**
+ * hash_hw_final - The final hash calculation function
+ * @req: The hash request for the job.
+ */
+int hash_hw_final(struct ahash_request *req)
+{
+ int ret = 0;
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct hash_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct hash_req_ctx *req_ctx = ahash_request_ctx(req);
+ struct hash_device_data *device_data;
+ u8 digest[SHA256_DIGEST_SIZE];
+
+ ret = hash_get_device_data(ctx, &device_data);
+ if (ret)
+ return ret;
+
+ dev_dbg(device_data->dev, "[%s] (ctx=0x%x)!", __func__, (u32) ctx);
+
+ if (req_ctx->updated) {
+ ret = hash_resume_state(device_data, &device_data->state);
+
+ if (ret) {
+ dev_err(device_data->dev, "[%s] hash_resume_state() "
+ "failed!", __func__);
+ goto out;
+ }
+ } else if (req->nbytes == 0 && ctx->keylen == 0) {
+ u8 zero_hash[SHA256_DIGEST_SIZE];
+ u32 zero_hash_size = 0;
+ bool zero_digest = false;
+ /**
+ * Use a pre-calculated empty message digest
+ * (workaround since hw return zeroes, hw bug!?)
+ */
+ ret = get_empty_message_digest(device_data, &zero_hash[0],
+ &zero_hash_size, &zero_digest);
+ if (!ret && likely(zero_hash_size == ctx->digestsize) &&
+ zero_digest) {
+ memcpy(req->result, &zero_hash[0], ctx->digestsize);
+ goto out;
+ } else if (!ret && !zero_digest) {
+ dev_dbg(device_data->dev, "[%s] HMAC zero msg with "
+ "key, continue...", __func__);
+ } else {
+ dev_err(device_data->dev, "[%s] ret=%d, or wrong "
+ "digest size? %s", __func__, ret,
+ (zero_hash_size == ctx->digestsize) ?
+ "true" : "false");
+ /* Return error */
+ goto out;
+ }
+ } else if (req->nbytes == 0 && ctx->keylen > 0) {
+ dev_err(device_data->dev, "[%s] Empty message with "
+ "keylength > 0, NOT supported.", __func__);
+ goto out;
+ }
+
+ if (!req_ctx->updated) {
+ ret = init_hash_hw(device_data, ctx);
+ if (ret) {
+ dev_err(device_data->dev, "[%s] init_hash_hw() "
+ "failed!", __func__);
+ goto out;
+ }
+ }
+
+ if (req_ctx->state.index) {
+ hash_messagepad(device_data, req_ctx->state.buffer,
+ req_ctx->state.index);
+ } else {
+ HASH_SET_DCAL;
+ while (device_data->base->str & HASH_STR_DCAL_MASK)
+ cpu_relax();
+ }
+
+ if (ctx->config.oper_mode == HASH_OPER_MODE_HMAC && ctx->key) {
+ unsigned int keylen = ctx->keylen;
+ u8 *key = ctx->key;
+
+ dev_dbg(device_data->dev, "[%s] keylen: %d", __func__,
+ ctx->keylen);
+ hash_hw_write_key(device_data, key, keylen);
+ }
+
+ hash_get_digest(device_data, digest, ctx->config.algorithm);
+ memcpy(req->result, digest, ctx->digestsize);
+
+out:
+ release_hash_device(device_data);
+
+ /**
+ * Allocated in setkey, and only used in HMAC.
+ */
+ kfree(ctx->key);
+
+ return ret;
+}
+
+/**
+ * hash_hw_update - Updates current HASH computation hashing another part of
+ * the message.
+ * @req: Byte array containing the message to be hashed (caller
+ * allocated).
+ */
+int hash_hw_update(struct ahash_request *req)
+{
+ int ret = 0;
+ u8 index = 0;
+ u8 *buffer;
+ struct hash_device_data *device_data;
+ u8 *data_buffer;
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct hash_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct hash_req_ctx *req_ctx = ahash_request_ctx(req);
+ struct crypto_hash_walk walk;
+ int msg_length = crypto_hash_walk_first(req, &walk);
+
+ /* Empty message ("") is correct indata */
+ if (msg_length == 0)
+ return ret;
+
+ index = req_ctx->state.index;
+ buffer = (u8 *)req_ctx->state.buffer;
+
+ /* Check if ctx->state.length + msg_length
+ overflows */
+ if (msg_length > (req_ctx->state.length.low_word + msg_length) &&
+ HASH_HIGH_WORD_MAX_VAL ==
+ req_ctx->state.length.high_word) {
+ pr_err(DEV_DBG_NAME " [%s] HASH_MSG_LENGTH_OVERFLOW!",
+ __func__);
+ return -EPERM;
+ }
+
+ ret = hash_get_device_data(ctx, &device_data);
+ if (ret)
+ return ret;
+
+ /* Main loop */
+ while (0 != msg_length) {
+ data_buffer = walk.data;
+ ret = hash_process_data(device_data, ctx, req_ctx, msg_length,
+ data_buffer, buffer, &index);
+
+ if (ret) {
+ dev_err(device_data->dev, "[%s] hash_internal_hw_"
+ "update() failed!", __func__);
+ goto out;
+ }
+
+ msg_length = crypto_hash_walk_done(&walk, 0);
+ }
+
+ req_ctx->state.index = index;
+ dev_dbg(device_data->dev, "[%s] indata length=%d, bin=%d))",
+ __func__, req_ctx->state.index,
+ req_ctx->state.bit_index);
+
+out:
+ release_hash_device(device_data);
+
+ return ret;
+}
+
+/**
+ * hash_resume_state - Function that resumes the state of an calculation.
+ * @device_data: Pointer to the device structure.
+ * @device_state: The state to be restored in the hash hardware
+ */
+int hash_resume_state(struct hash_device_data *device_data,
+ const struct hash_state *device_state)
+{
+ u32 temp_cr;
+ s32 count;
+ int hash_mode = HASH_OPER_MODE_HASH;
+
+ if (NULL == device_state) {
+ dev_err(device_data->dev, "[%s] HASH_INVALID_PARAMETER!",
+ __func__);
+ return -EPERM;
+ }
+
+ /* Check correctness of index and length members */
+ if (device_state->index > HASH_BLOCK_SIZE
+ || (device_state->length.low_word % HASH_BLOCK_SIZE) != 0) {
+ dev_err(device_data->dev, "[%s] HASH_INVALID_PARAMETER!",
+ __func__);
+ return -EPERM;
+ }
+
+ /*
+ * INIT bit. Set this bit to 0b1 to reset the HASH processor core and
+ * prepare the initialize the HASH accelerator to compute the message
+ * digest of a new message.
+ */
+ HASH_INITIALIZE;
+
+ temp_cr = device_state->temp_cr;
+ writel_relaxed(temp_cr & HASH_CR_RESUME_MASK, &device_data->base->cr);
+
+ if (device_data->base->cr & HASH_CR_MODE_MASK)
+ hash_mode = HASH_OPER_MODE_HMAC;
+ else
+ hash_mode = HASH_OPER_MODE_HASH;
+
+ for (count = 0; count < HASH_CSR_COUNT; count++) {
+ if ((count >= 36) && (hash_mode == HASH_OPER_MODE_HASH))
+ break;
+
+ writel_relaxed(device_state->csr[count],
+ &device_data->base->csrx[count]);
+ }
+
+ writel_relaxed(device_state->csfull, &device_data->base->csfull);
+ writel_relaxed(device_state->csdatain, &device_data->base->csdatain);
+
+ writel_relaxed(device_state->str_reg, &device_data->base->str);
+ writel_relaxed(temp_cr, &device_data->base->cr);
+
+ return 0;
+}
+
+/**
+ * hash_save_state - Function that saves the state of hardware.
+ * @device_data: Pointer to the device structure.
+ * @device_state: The strucure where the hardware state should be saved.
+ */
+int hash_save_state(struct hash_device_data *device_data,
+ struct hash_state *device_state)
+{
+ u32 temp_cr;
+ u32 count;
+ int hash_mode = HASH_OPER_MODE_HASH;
+
+ if (NULL == device_state) {
+ dev_err(device_data->dev, "[%s] HASH_INVALID_PARAMETER!",
+ __func__);
+ return -ENOTSUPP;
+ }
+
+ /* Write dummy value to force digest intermediate calculation. This
+ * actually makes sure that there isn't any ongoing calculation in the
+ * hardware.
+ */
+ while (device_data->base->str & HASH_STR_DCAL_MASK)
+ cpu_relax();
+
+ temp_cr = readl_relaxed(&device_data->base->cr);
+
+ device_state->str_reg = readl_relaxed(&device_data->base->str);
+
+ device_state->din_reg = readl_relaxed(&device_data->base->din);
+
+ if (device_data->base->cr & HASH_CR_MODE_MASK)
+ hash_mode = HASH_OPER_MODE_HMAC;
+ else
+ hash_mode = HASH_OPER_MODE_HASH;
+
+ for (count = 0; count < HASH_CSR_COUNT; count++) {
+ if ((count >= 36) && (hash_mode == HASH_OPER_MODE_HASH))
+ break;
+
+ device_state->csr[count] =
+ readl_relaxed(&device_data->base->csrx[count]);
+ }
+
+ device_state->csfull = readl_relaxed(&device_data->base->csfull);
+ device_state->csdatain = readl_relaxed(&device_data->base->csdatain);
+
+ device_state->temp_cr = temp_cr;
+
+ return 0;
+}
+
+/**
+ * hash_check_hw - This routine checks for peripheral Ids and PCell Ids.
+ * @device_data:
+ *
+ */
+int hash_check_hw(struct hash_device_data *device_data)
+{
+ /* Checking Peripheral Ids */
+ if (HASH_P_ID0 == readl_relaxed(&device_data->base->periphid0)
+ && HASH_P_ID1 == readl_relaxed(&device_data->base->periphid1)
+ && HASH_P_ID2 == readl_relaxed(&device_data->base->periphid2)
+ && HASH_P_ID3 == readl_relaxed(&device_data->base->periphid3)
+ && HASH_CELL_ID0 == readl_relaxed(&device_data->base->cellid0)
+ && HASH_CELL_ID1 == readl_relaxed(&device_data->base->cellid1)
+ && HASH_CELL_ID2 == readl_relaxed(&device_data->base->cellid2)
+ && HASH_CELL_ID3 == readl_relaxed(&device_data->base->cellid3)
+ ) {
+ return 0;
+ }
+
+ dev_err(device_data->dev, "[%s] HASH_UNSUPPORTED_HW!",
+ __func__);
+ return -ENOTSUPP;
+}
+
+/**
+ * hash_get_digest - Gets the digest.
+ * @device_data: Pointer to the device structure.
+ * @digest: User allocated byte array for the calculated digest.
+ * @algorithm: The algorithm in use.
+ */
+void hash_get_digest(struct hash_device_data *device_data,
+ u8 *digest, int algorithm)
+{
+ u32 temp_hx_val, count;
+ int loop_ctr;
+
+ if (algorithm != HASH_ALGO_SHA1 && algorithm != HASH_ALGO_SHA256) {
+ dev_err(device_data->dev, "[%s] Incorrect algorithm %d",
+ __func__, algorithm);
+ return;
+ }
+
+ if (algorithm == HASH_ALGO_SHA1)
+ loop_ctr = SHA1_DIGEST_SIZE / sizeof(u32);
+ else
+ loop_ctr = SHA256_DIGEST_SIZE / sizeof(u32);
+
+ dev_dbg(device_data->dev, "[%s] digest array:(0x%x)",
+ __func__, (u32) digest);
+
+ /* Copy result into digest array */
+ for (count = 0; count < loop_ctr; count++) {
+ temp_hx_val = readl_relaxed(&device_data->base->hx[count]);
+ digest[count * 4] = (u8) ((temp_hx_val >> 24) & 0xFF);
+ digest[count * 4 + 1] = (u8) ((temp_hx_val >> 16) & 0xFF);
+ digest[count * 4 + 2] = (u8) ((temp_hx_val >> 8) & 0xFF);
+ digest[count * 4 + 3] = (u8) ((temp_hx_val >> 0) & 0xFF);
+ }
+}
+
+/**
+ * hash_update - The hash update function for SHA1/SHA2 (SHA256).
+ * @req: The hash request for the job.
+ */
+static int ahash_update(struct ahash_request *req)
+{
+ int ret = 0;
+ struct hash_req_ctx *req_ctx = ahash_request_ctx(req);
+
+ if (hash_mode != HASH_MODE_DMA || !req_ctx->dma_mode)
+ ret = hash_hw_update(req);
+ /* Skip update for DMA, all data will be passed to DMA in final */
+
+ if (ret) {
+ pr_err(DEV_DBG_NAME " [%s] hash_hw_update() failed!",
+ __func__);
+ }
+
+ return ret;
+}
+
+/**
+ * hash_final - The hash final function for SHA1/SHA2 (SHA256).
+ * @req: The hash request for the job.
+ */
+static int ahash_final(struct ahash_request *req)
+{
+ int ret = 0;
+ struct hash_req_ctx *req_ctx = ahash_request_ctx(req);
+
+ pr_debug(DEV_DBG_NAME " [%s] data size: %d", __func__, req->nbytes);
+
+ if ((hash_mode == HASH_MODE_DMA) && req_ctx->dma_mode)
+ ret = hash_dma_final(req);
+ else
+ ret = hash_hw_final(req);
+
+ if (ret) {
+ pr_err(DEV_DBG_NAME " [%s] hash_hw/dma_final() failed",
+ __func__);
+ }
+
+ return ret;
+}
+
+static int hash_setkey(struct crypto_ahash *tfm,
+ const u8 *key, unsigned int keylen, int alg)
+{
+ int ret = 0;
+ struct hash_ctx *ctx = crypto_ahash_ctx(tfm);
+
+ /**
+ * Freed in final.
+ */
+ ctx->key = kmalloc(keylen, GFP_KERNEL);
+ if (!ctx->key) {
+ pr_err(DEV_DBG_NAME " [%s] Failed to allocate ctx->key "
+ "for %d\n", __func__, alg);
+ return -ENOMEM;
+ }
+
+ memcpy(ctx->key, key, keylen);
+ ctx->keylen = keylen;
+
+ return ret;
+}
+
+static int ahash_sha1_init(struct ahash_request *req)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct hash_ctx *ctx = crypto_ahash_ctx(tfm);
+
+ ctx->config.data_format = HASH_DATA_8_BITS;
+ ctx->config.algorithm = HASH_ALGO_SHA1;
+ ctx->config.oper_mode = HASH_OPER_MODE_HASH;
+ ctx->digestsize = SHA1_DIGEST_SIZE;
+
+ return hash_init(req);
+}
+
+static int ahash_sha256_init(struct ahash_request *req)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct hash_ctx *ctx = crypto_ahash_ctx(tfm);
+
+ ctx->config.data_format = HASH_DATA_8_BITS;
+ ctx->config.algorithm = HASH_ALGO_SHA256;
+ ctx->config.oper_mode = HASH_OPER_MODE_HASH;
+ ctx->digestsize = SHA256_DIGEST_SIZE;
+
+ return hash_init(req);
+}
+
+static int ahash_sha1_digest(struct ahash_request *req)
+{
+ int ret2, ret1;
+
+ ret1 = ahash_sha1_init(req);
+ if (ret1)
+ goto out;
+
+ ret1 = ahash_update(req);
+ ret2 = ahash_final(req);
+
+out:
+ return ret1 ? ret1 : ret2;
+}
+
+static int ahash_sha256_digest(struct ahash_request *req)
+{
+ int ret2, ret1;
+
+ ret1 = ahash_sha256_init(req);
+ if (ret1)
+ goto out;
+
+ ret1 = ahash_update(req);
+ ret2 = ahash_final(req);
+
+out:
+ return ret1 ? ret1 : ret2;
+}
+
+static int hmac_sha1_init(struct ahash_request *req)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct hash_ctx *ctx = crypto_ahash_ctx(tfm);
+
+ ctx->config.data_format = HASH_DATA_8_BITS;
+ ctx->config.algorithm = HASH_ALGO_SHA1;
+ ctx->config.oper_mode = HASH_OPER_MODE_HMAC;
+ ctx->digestsize = SHA1_DIGEST_SIZE;
+
+ return hash_init(req);
+}
+
+static int hmac_sha256_init(struct ahash_request *req)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct hash_ctx *ctx = crypto_ahash_ctx(tfm);
+
+ ctx->config.data_format = HASH_DATA_8_BITS;
+ ctx->config.algorithm = HASH_ALGO_SHA256;
+ ctx->config.oper_mode = HASH_OPER_MODE_HMAC;
+ ctx->digestsize = SHA256_DIGEST_SIZE;
+
+ return hash_init(req);
+}
+
+static int hmac_sha1_digest(struct ahash_request *req)
+{
+ int ret2, ret1;
+
+ ret1 = hmac_sha1_init(req);
+ if (ret1)
+ goto out;
+
+ ret1 = ahash_update(req);
+ ret2 = ahash_final(req);
+
+out:
+ return ret1 ? ret1 : ret2;
+}
+
+static int hmac_sha256_digest(struct ahash_request *req)
+{
+ int ret2, ret1;
+
+ ret1 = hmac_sha256_init(req);
+ if (ret1)
+ goto out;
+
+ ret1 = ahash_update(req);
+ ret2 = ahash_final(req);
+
+out:
+ return ret1 ? ret1 : ret2;
+}
+
+static int hmac_sha1_setkey(struct crypto_ahash *tfm,
+ const u8 *key, unsigned int keylen)
+{
+ return hash_setkey(tfm, key, keylen, HASH_ALGO_SHA1);
+}
+
+static int hmac_sha256_setkey(struct crypto_ahash *tfm,
+ const u8 *key, unsigned int keylen)
+{
+ return hash_setkey(tfm, key, keylen, HASH_ALGO_SHA256);
+}
+
+struct hash_algo_template {
+ struct hash_config conf;
+ struct ahash_alg hash;
+};
+
+static int hash_cra_init(struct crypto_tfm *tfm)
+{
+ struct hash_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_alg *alg = tfm->__crt_alg;
+ struct hash_algo_template *hash_alg;
+
+ hash_alg = container_of(__crypto_ahash_alg(alg),
+ struct hash_algo_template,
+ hash);
+
+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+ sizeof(struct hash_req_ctx));
+
+ ctx->config.data_format = HASH_DATA_8_BITS;
+ ctx->config.algorithm = hash_alg->conf.algorithm;
+ ctx->config.oper_mode = hash_alg->conf.oper_mode;
+
+ ctx->digestsize = hash_alg->hash.halg.digestsize;
+
+ return 0;
+}
+
+static struct hash_algo_template hash_algs[] = {
+ {
+ .conf.algorithm = HASH_ALGO_SHA1,
+ .conf.oper_mode = HASH_OPER_MODE_HASH,
+ .hash = {
+ .init = hash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .digest = ahash_sha1_digest,
+ .halg.digestsize = SHA1_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct hash_ctx),
+ .halg.base = {
+ .cra_name = "sha1",
+ .cra_driver_name = "sha1-ux500",
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct hash_ctx),
+ .cra_init = hash_cra_init,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ },
+ {
+ .conf.algorithm = HASH_ALGO_SHA256,
+ .conf.oper_mode = HASH_OPER_MODE_HASH,
+ .hash = {
+ .init = hash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .digest = ahash_sha256_digest,
+ .halg.digestsize = SHA256_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct hash_ctx),
+ .halg.base = {
+ .cra_name = "sha256",
+ .cra_driver_name = "sha256-ux500",
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct hash_ctx),
+ .cra_type = &crypto_ahash_type,
+ .cra_init = hash_cra_init,
+ .cra_module = THIS_MODULE,
+ }
+ }
+
+ },
+ {
+ .conf.algorithm = HASH_ALGO_SHA1,
+ .conf.oper_mode = HASH_OPER_MODE_HMAC,
+ .hash = {
+ .init = hash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .digest = hmac_sha1_digest,
+ .setkey = hmac_sha1_setkey,
+ .halg.digestsize = SHA1_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct hash_ctx),
+ .halg.base = {
+ .cra_name = "hmac(sha1)",
+ .cra_driver_name = "hmac-sha1-ux500",
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct hash_ctx),
+ .cra_type = &crypto_ahash_type,
+ .cra_init = hash_cra_init,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ },
+ {
+ .conf.algorithm = HASH_ALGO_SHA256,
+ .conf.oper_mode = HASH_OPER_MODE_HMAC,
+ .hash = {
+ .init = hash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .digest = hmac_sha256_digest,
+ .setkey = hmac_sha256_setkey,
+ .halg.digestsize = SHA256_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct hash_ctx),
+ .halg.base = {
+ .cra_name = "hmac(sha256)",
+ .cra_driver_name = "hmac-sha256-ux500",
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct hash_ctx),
+ .cra_type = &crypto_ahash_type,
+ .cra_init = hash_cra_init,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ }
+};
+
+/**
+ * hash_algs_register_all -
+ */
+static int ahash_algs_register_all(struct hash_device_data *device_data)
+{
+ int ret;
+ int i;
+ int count;
+
+ for (i = 0; i < ARRAY_SIZE(hash_algs); i++) {
+ ret = crypto_register_ahash(&hash_algs[i].hash);
+ if (ret) {
+ count = i;
+ dev_err(device_data->dev, "[%s] alg registration failed",
+ hash_algs[i].hash.halg.base.cra_driver_name);
+ goto unreg;
+ }
+ }
+ return 0;
+unreg:
+ for (i = 0; i < count; i++)
+ crypto_unregister_ahash(&hash_algs[i].hash);
+ return ret;
+}
+
+/**
+ * hash_algs_unregister_all -
+ */
+static void ahash_algs_unregister_all(struct hash_device_data *device_data)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hash_algs); i++)
+ crypto_unregister_ahash(&hash_algs[i].hash);
+}
+
+/**
+ * ux500_hash_probe - Function that probes the hash hardware.
+ * @pdev: The platform device.
+ */
+static int ux500_hash_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct resource *res = NULL;
+ struct hash_device_data *device_data;
+ struct device *dev = &pdev->dev;
+
+ device_data = kzalloc(sizeof(struct hash_device_data), GFP_ATOMIC);
+ if (!device_data) {
+ dev_dbg(dev, "[%s] kzalloc() failed!", __func__);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ device_data->dev = dev;
+ device_data->current_ctx = NULL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_dbg(dev, "[%s] platform_get_resource() failed!", __func__);
+ ret = -ENODEV;
+ goto out_kfree;
+ }
+
+ res = request_mem_region(res->start, resource_size(res), pdev->name);
+ if (res == NULL) {
+ dev_dbg(dev, "[%s] request_mem_region() failed!", __func__);
+ ret = -EBUSY;
+ goto out_kfree;
+ }
+
+ device_data->base = ioremap(res->start, resource_size(res));
+ if (!device_data->base) {
+ dev_err(dev, "[%s] ioremap() failed!",
+ __func__);
+ ret = -ENOMEM;
+ goto out_free_mem;
+ }
+ spin_lock_init(&device_data->ctx_lock);
+ spin_lock_init(&device_data->power_state_lock);
+
+ /* Enable power for HASH1 hardware block */
+ device_data->regulator = regulator_get(dev, "v-ape");
+ if (IS_ERR(device_data->regulator)) {
+ dev_err(dev, "[%s] regulator_get() failed!", __func__);
+ ret = PTR_ERR(device_data->regulator);
+ device_data->regulator = NULL;
+ goto out_unmap;
+ }
+
+ /* Enable the clock for HASH1 hardware block */
+ device_data->clk = clk_get(dev, NULL);
+ if (IS_ERR(device_data->clk)) {
+ dev_err(dev, "[%s] clk_get() failed!", __func__);
+ ret = PTR_ERR(device_data->clk);
+ goto out_regulator;
+ }
+
+ /* Enable device power (and clock) */
+ ret = hash_enable_power(device_data, false);
+ if (ret) {
+ dev_err(dev, "[%s]: hash_enable_power() failed!", __func__);
+ goto out_clk;
+ }
+
+ ret = hash_check_hw(device_data);
+ if (ret) {
+ dev_err(dev, "[%s] hash_check_hw() failed!", __func__);
+ goto out_power;
+ }
+
+ if (hash_mode == HASH_MODE_DMA)
+ hash_dma_setup_channel(device_data, dev);
+
+ platform_set_drvdata(pdev, device_data);
+
+ /* Put the new device into the device list... */
+ klist_add_tail(&device_data->list_node, &driver_data.device_list);
+ /* ... and signal that a new device is available. */
+ up(&driver_data.device_allocation);
+
+ ret = ahash_algs_register_all(device_data);
+ if (ret) {
+ dev_err(dev, "[%s] ahash_algs_register_all() "
+ "failed!", __func__);
+ goto out_power;
+ }
+
+ dev_info(dev, "[%s] successfully probed\n", __func__);
+ return 0;
+
+out_power:
+ hash_disable_power(device_data, false);
+
+out_clk:
+ clk_put(device_data->clk);
+
+out_regulator:
+ regulator_put(device_data->regulator);
+
+out_unmap:
+ iounmap(device_data->base);
+
+out_free_mem:
+ release_mem_region(res->start, resource_size(res));
+
+out_kfree:
+ kfree(device_data);
+out:
+ return ret;
+}
+
+/**
+ * ux500_hash_remove - Function that removes the hash device from the platform.
+ * @pdev: The platform device.
+ */
+static int ux500_hash_remove(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct hash_device_data *device_data;
+ struct device *dev = &pdev->dev;
+
+ device_data = platform_get_drvdata(pdev);
+ if (!device_data) {
+ dev_err(dev, "[%s]: platform_get_drvdata() failed!",
+ __func__);
+ return -ENOMEM;
+ }
+
+ /* Try to decrease the number of available devices. */
+ if (down_trylock(&driver_data.device_allocation))
+ return -EBUSY;
+
+ /* Check that the device is free */
+ spin_lock(&device_data->ctx_lock);
+ /* current_ctx allocates a device, NULL = unallocated */
+ if (device_data->current_ctx) {
+ /* The device is busy */
+ spin_unlock(&device_data->ctx_lock);
+ /* Return the device to the pool. */
+ up(&driver_data.device_allocation);
+ return -EBUSY;
+ }
+
+ spin_unlock(&device_data->ctx_lock);
+
+ /* Remove the device from the list */
+ if (klist_node_attached(&device_data->list_node))
+ klist_remove(&device_data->list_node);
+
+ /* If this was the last device, remove the services */
+ if (list_empty(&driver_data.device_list.k_list))
+ ahash_algs_unregister_all(device_data);
+
+ if (hash_disable_power(device_data, false))
+ dev_err(dev, "[%s]: hash_disable_power() failed",
+ __func__);
+
+ clk_put(device_data->clk);
+ regulator_put(device_data->regulator);
+
+ iounmap(device_data->base);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res)
+ release_mem_region(res->start, resource_size(res));
+
+ kfree(device_data);
+
+ return 0;
+}
+
+/**
+ * ux500_hash_shutdown - Function that shutdown the hash device.
+ * @pdev: The platform device
+ */
+static void ux500_hash_shutdown(struct platform_device *pdev)
+{
+ struct resource *res = NULL;
+ struct hash_device_data *device_data;
+
+ device_data = platform_get_drvdata(pdev);
+ if (!device_data) {
+ dev_err(&pdev->dev, "[%s] platform_get_drvdata() failed!",
+ __func__);
+ return;
+ }
+
+ /* Check that the device is free */
+ spin_lock(&device_data->ctx_lock);
+ /* current_ctx allocates a device, NULL = unallocated */
+ if (!device_data->current_ctx) {
+ if (down_trylock(&driver_data.device_allocation))
+ dev_dbg(&pdev->dev, "[%s]: Cryp still in use!"
+ "Shutting down anyway...", __func__);
+ /**
+ * (Allocate the device)
+ * Need to set this to non-null (dummy) value,
+ * to avoid usage if context switching.
+ */
+ device_data->current_ctx++;
+ }
+ spin_unlock(&device_data->ctx_lock);
+
+ /* Remove the device from the list */
+ if (klist_node_attached(&device_data->list_node))
+ klist_remove(&device_data->list_node);
+
+ /* If this was the last device, remove the services */
+ if (list_empty(&driver_data.device_list.k_list))
+ ahash_algs_unregister_all(device_data);
+
+ iounmap(device_data->base);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res)
+ release_mem_region(res->start, resource_size(res));
+
+ if (hash_disable_power(device_data, false))
+ dev_err(&pdev->dev, "[%s] hash_disable_power() failed",
+ __func__);
+}
+
+/**
+ * ux500_hash_suspend - Function that suspends the hash device.
+ * @pdev: The platform device.
+ * @state: -
+ */
+static int ux500_hash_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ int ret;
+ struct hash_device_data *device_data;
+ struct hash_ctx *temp_ctx = NULL;
+
+ device_data = platform_get_drvdata(pdev);
+ if (!device_data) {
+ dev_err(&pdev->dev, "[%s] platform_get_drvdata() failed!",
+ __func__);
+ return -ENOMEM;
+ }
+
+ spin_lock(&device_data->ctx_lock);
+ if (!device_data->current_ctx)
+ device_data->current_ctx++;
+ spin_unlock(&device_data->ctx_lock);
+
+ if (device_data->current_ctx == ++temp_ctx) {
+ if (down_interruptible(&driver_data.device_allocation))
+ dev_dbg(&pdev->dev, "[%s]: down_interruptible() "
+ "failed", __func__);
+ ret = hash_disable_power(device_data, false);
+
+ } else
+ ret = hash_disable_power(device_data, true);
+
+ if (ret)
+ dev_err(&pdev->dev, "[%s]: hash_disable_power()", __func__);
+
+ return ret;
+}
+
+/**
+ * ux500_hash_resume - Function that resume the hash device.
+ * @pdev: The platform device.
+ */
+static int ux500_hash_resume(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct hash_device_data *device_data;
+ struct hash_ctx *temp_ctx = NULL;
+
+ device_data = platform_get_drvdata(pdev);
+ if (!device_data) {
+ dev_err(&pdev->dev, "[%s] platform_get_drvdata() failed!",
+ __func__);
+ return -ENOMEM;
+ }
+
+ spin_lock(&device_data->ctx_lock);
+ if (device_data->current_ctx == ++temp_ctx)
+ device_data->current_ctx = NULL;
+ spin_unlock(&device_data->ctx_lock);
+
+ if (!device_data->current_ctx)
+ up(&driver_data.device_allocation);
+ else
+ ret = hash_enable_power(device_data, true);
+
+ if (ret)
+ dev_err(&pdev->dev, "[%s]: hash_enable_power() failed!",
+ __func__);
+
+ return ret;
+}
+
+static struct platform_driver hash_driver = {
+ .probe = ux500_hash_probe,
+ .remove = ux500_hash_remove,
+ .shutdown = ux500_hash_shutdown,
+ .suspend = ux500_hash_suspend,
+ .resume = ux500_hash_resume,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "hash1",
+ }
+};
+
+/**
+ * ux500_hash_mod_init - The kernel module init function.
+ */
+static int __init ux500_hash_mod_init(void)
+{
+ klist_init(&driver_data.device_list, NULL, NULL);
+ /* Initialize the semaphore to 0 devices (locked state) */
+ sema_init(&driver_data.device_allocation, 0);
+
+ return platform_driver_register(&hash_driver);
+}
+
+/**
+ * ux500_hash_mod_fini - The kernel module exit function.
+ */
+static void __exit ux500_hash_mod_fini(void)
+{
+ platform_driver_unregister(&hash_driver);
+ return;
+}
+
+module_init(ux500_hash_mod_init);
+module_exit(ux500_hash_mod_fini);
+
+MODULE_DESCRIPTION("Driver for ST-Ericsson UX500 HASH engine.");
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("sha1-all");
+MODULE_ALIAS("sha256-all");
+MODULE_ALIAS("hmac-sha1-all");
+MODULE_ALIAS("hmac-sha256-all");
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 464fa2147dfb..f6b0a6e2ea50 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -16,7 +16,7 @@ menuconfig PM_DEVFREQ
is attached to a single device and returns a "representative"
clock frequency of the device, which is also attached
to a device by 1-to-1. The device registering devfreq takes the
- responsiblity to "interpret" the representative frequency and
+ responsibility to "interpret" the representative frequency and
to set its every clock accordingly with the "target" callback
given to devfreq.
diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c
index 574a06b1b1de..af75ddd4f158 100644
--- a/drivers/devfreq/governor_performance.c
+++ b/drivers/devfreq/governor_performance.c
@@ -10,6 +10,7 @@
*/
#include <linux/devfreq.h>
+#include "governor.h"
static int devfreq_performance_func(struct devfreq *df,
unsigned long *freq)
@@ -25,8 +26,14 @@ static int devfreq_performance_func(struct devfreq *df,
return 0;
}
+static int performance_init(struct devfreq *devfreq)
+{
+ return update_devfreq(devfreq);
+}
+
const struct devfreq_governor devfreq_performance = {
.name = "performance",
+ .init = performance_init,
.get_target_freq = devfreq_performance_func,
.no_central_polling = true,
};
diff --git a/drivers/devfreq/governor_powersave.c b/drivers/devfreq/governor_powersave.c
index d742d4a82d6a..fec0cdbd2477 100644
--- a/drivers/devfreq/governor_powersave.c
+++ b/drivers/devfreq/governor_powersave.c
@@ -10,6 +10,7 @@
*/
#include <linux/devfreq.h>
+#include "governor.h"
static int devfreq_powersave_func(struct devfreq *df,
unsigned long *freq)
@@ -22,8 +23,14 @@ static int devfreq_powersave_func(struct devfreq *df,
return 0;
}
+static int powersave_init(struct devfreq *devfreq)
+{
+ return update_devfreq(devfreq);
+}
+
const struct devfreq_governor devfreq_powersave = {
.name = "powersave",
+ .init = powersave_init,
.get_target_freq = devfreq_powersave_func,
.no_central_polling = true,
};
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 445fdf811695..bf0d7e4e345b 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -245,7 +245,9 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
dev_vdbg(chan2dev(&atchan->chan_common),
"descriptor %u complete\n", txd->cookie);
- dma_cookie_complete(txd);
+ /* mark the descriptor as complete for non cyclic cases only */
+ if (!atc_chan_is_cyclic(atchan))
+ dma_cookie_complete(txd);
/* move children to free_list */
list_splice_init(&desc->tx_list, &atchan->free_list);
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index e6f133b78dc2..f6e9b572b998 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -703,7 +703,9 @@ static void ep93xx_dma_tasklet(unsigned long data)
desc = ep93xx_dma_get_active(edmac);
if (desc) {
if (desc->complete) {
- dma_cookie_complete(&desc->txd);
+ /* mark descriptor complete for non cyclic case only */
+ if (!test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags))
+ dma_cookie_complete(&desc->txd);
list_splice_init(&edmac->active, &list);
}
callback = desc->txd.callback;
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 2ee6e23930ad..fa3fb21e60be 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2322,7 +2322,8 @@ static void pl330_tasklet(unsigned long data)
/* Pick up ripe tomatoes */
list_for_each_entry_safe(desc, _dt, &pch->work_list, node)
if (desc->status == DONE) {
- dma_cookie_complete(&desc->txd);
+ if (pch->cyclic)
+ dma_cookie_complete(&desc->txd);
list_move_tail(&desc->node, &list);
}
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index e48ab3108ad8..5b739411d62f 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -107,13 +107,13 @@ extern int edac_debug_level;
*
* CPU caches (L1 and L2)
* DMA engines
- * Core CPU swithces
+ * Core CPU switches
* Fabric switch units
* PCIe interface controllers
* other EDAC/ECC type devices that can be monitored for
* errors, etc.
*
- * It allows for a 2 level set of hiearchry. For example:
+ * It allows for a 2 level set of hierarchy. For example:
*
* cache could be composed of L1, L2 and L3 levels of cache.
* Each CPU core would have its own L1 cache, while sharing
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c
index 4b154593343a..45b8f4bdd773 100644
--- a/drivers/edac/edac_device.c
+++ b/drivers/edac/edac_device.c
@@ -56,7 +56,7 @@ static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev)
*
* The control structure is allocated in complete chunk
* from the OS. It is in turn sub allocated to the
- * various objects that compose the struture
+ * various objects that compose the structure
*
* The structure has a 'nr_instance' array within itself.
* Each instance represents a major component
@@ -118,7 +118,7 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
/* Calc the 'end' offset past the attributes array */
pvt = edac_align_ptr(&dev_attrib[count], sz_private);
} else {
- /* no attribute array specificed */
+ /* no attribute array specified */
pvt = edac_align_ptr(dev_attrib, sz_private);
}
@@ -394,7 +394,7 @@ static void edac_device_workq_function(struct work_struct *work_req)
/* Reschedule the workq for the next time period to start again
* if the number of msec is for 1 sec, then adjust to the next
- * whole one second to save timers fireing all over the period
+ * whole one second to save timers firing all over the period
* between integral seconds
*/
if (edac_dev->poll_msec == 1000)
@@ -563,7 +563,7 @@ EXPORT_SYMBOL_GPL(edac_device_add_device);
* Remove sysfs entries for specified edac_device structure and
* then remove edac_device structure from global list
*
- * @pdev:
+ * @dev:
* Pointer to 'struct device' representing edac_device
* structure to remove.
*
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 85226ccf5290..7f1dfcc4e597 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -90,7 +90,7 @@ MODULE_PARM_DESC(use_pci_fixup, "Enable PCI fixup to seek for hidden devices");
#define MC_MAX_DOD 0x64
/*
- * OFFSETS for Device 3 Function 4, as inicated on Xeon 5500 datasheet:
+ * OFFSETS for Device 3 Function 4, as indicated on Xeon 5500 datasheet:
* http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
*/
@@ -101,7 +101,7 @@ MODULE_PARM_DESC(use_pci_fixup, "Enable PCI fixup to seek for hidden devices");
#define DIMM1_COR_ERR(r) (((r) >> 16) & 0x7fff)
#define DIMM0_COR_ERR(r) ((r) & 0x7fff)
-/* OFFSETS for Device 3 Function 2, as inicated on Xeon 5500 datasheet */
+/* OFFSETS for Device 3 Function 2, as indicated on Xeon 5500 datasheet */
#define MC_SSRCONTROL 0x48
#define SSR_MODE_DISABLE 0x00
#define SSR_MODE_ENABLE 0x01
@@ -398,7 +398,7 @@ static DEFINE_PCI_DEVICE_TABLE(i7core_pci_tbl) = {
};
/****************************************************************************
- Anciliary status routines
+ Ancillary status routines
****************************************************************************/
/* MC_CONTROL bits */
@@ -1361,7 +1361,7 @@ static int i7core_get_onedevice(struct pci_dev **prev,
dev_descr->dev_id, *prev);
/*
- * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
+ * On Xeon 55xx, the Intel QuickPath Arch Generic Non-core regs
* is at addr 8086:2c40, instead of 8086:2c41. So, we need
* to probe for the alternate address in case of failure
*/
@@ -2132,7 +2132,7 @@ static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 new_bw)
/*
* get_sdram_scrub_rate This routine convert current scrub rate value
- * into byte/sec bandwidth accourding to
+ * into byte/sec bandwidth according to
* SCRUBINTERVAL formula found in datasheet.
*/
static int get_sdram_scrub_rate(struct mem_ctl_info *mci)
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index a203536d90dd..123204f8e23b 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -58,7 +58,7 @@ static int probed;
/*
* FIXME: For now, let's order by device function, as it makes
- * easier for driver's development proccess. This table should be
+ * easier for driver's development process. This table should be
* moved to pci_id.h when submitted upstream
*/
#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0 0x3cf4 /* 12.6 */
@@ -375,7 +375,7 @@ static DEFINE_PCI_DEVICE_TABLE(sbridge_pci_tbl) = {
/****************************************************************************
- Anciliary status routines
+ Ancillary status routines
****************************************************************************/
static inline int numrank(u32 mtr)
@@ -1430,7 +1430,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
type = "FATAL";
/*
- * According with Table 15-9 of the Intel Archictecture spec vol 3A,
+ * According with Table 15-9 of the Intel Architecture spec vol 3A,
* memory errors should fit in this mask:
* 000f 0000 1mmm cccc (binary)
* where:
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
new file mode 100644
index 000000000000..29c5cf852efc
--- /dev/null
+++ b/drivers/extcon/Kconfig
@@ -0,0 +1,32 @@
+menuconfig EXTCON
+ tristate "External Connector Class (extcon) support"
+ help
+ Say Y here to enable external connector class (extcon) support.
+ This allows monitoring external connectors by userspace
+ via sysfs and uevent and supports external connectors with
+ multiple states; i.e., an extcon that may have multiple
+ cables attached. For example, an external connector of a device
+ may be used to connect an HDMI cable and a AC adaptor, and to
+ host USB ports. Many of 30-pin connectors including PDMI are
+ also good examples.
+
+if EXTCON
+
+comment "Extcon Device Drivers"
+
+config EXTCON_GPIO
+ tristate "GPIO extcon support"
+ depends on GENERIC_GPIO
+ help
+ Say Y here to enable GPIO based extcon support. Note that GPIO
+ extcon supports single state per extcon instance.
+
+config EXTCON_MAX8997
+ tristate "MAX8997 EXTCON Support"
+ depends on MFD_MAX8997
+ help
+ If you say yes here you get support for the MUIC device of
+ Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory
+ detector and switch.
+
+endif # MULTISTATE_SWITCH
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
new file mode 100644
index 000000000000..86020bdb6da0
--- /dev/null
+++ b/drivers/extcon/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for external connector class (extcon) devices
+#
+
+obj-$(CONFIG_EXTCON) += extcon_class.o
+obj-$(CONFIG_EXTCON_GPIO) += extcon_gpio.o
+obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o
diff --git a/drivers/misc/max8997-muic.c b/drivers/extcon/extcon-max8997.c
index 19591eaa492a..23416e443765 100644
--- a/drivers/misc/max8997-muic.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -1,7 +1,7 @@
/*
- * max8997-muic.c - MAX8997 muic driver for the Maxim 8997
+ * extcon-max8997.c - MAX8997 extcon driver to support MAX8997 MUIC
*
- * Copyright (C) 2011 Samsung Electrnoics
+ * Copyright (C) 2012 Samsung Electrnoics
* Donggeun Kim <dg77.kim@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -13,11 +13,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
#include <linux/kernel.h>
@@ -30,6 +25,9 @@
#include <linux/kobject.h>
#include <linux/mfd/max8997.h>
#include <linux/mfd/max8997-private.h>
+#include <linux/extcon.h>
+
+#define DEV_NAME "max8997-muic"
/* MAX8997-MUIC STATUS1 register */
#define STATUS1_ADC_SHIFT 0
@@ -95,7 +93,6 @@ static struct max8997_muic_irq muic_irqs[] = {
struct max8997_muic_info {
struct device *dev;
- struct max8997_dev *iodev;
struct i2c_client *muic;
struct max8997_muic_platform_data *muic_pdata;
@@ -106,12 +103,28 @@ struct max8997_muic_info {
int pre_adc;
struct mutex mutex;
+
+ struct extcon_dev *edev;
+};
+
+const char *max8997_extcon_cable[] = {
+ [0] = "USB",
+ [1] = "USB-Host",
+ [2] = "TA",
+ [3] = "Fast-charger",
+ [4] = "Slow-charger",
+ [5] = "Charge-downstream",
+ [6] = "MHL",
+ [7] = "Dock-desk",
+ [7] = "Dock-card",
+ [8] = "JIG",
+
+ NULL,
};
static int max8997_muic_handle_usb(struct max8997_muic_info *info,
enum max8997_muic_usb_type usb_type, bool attached)
{
- struct max8997_muic_platform_data *mdata = info->muic_pdata;
int ret = 0;
if (usb_type == MAX8997_USB_HOST) {
@@ -125,25 +138,25 @@ static int max8997_muic_handle_usb(struct max8997_muic_info *info,
}
}
- if (mdata->usb_callback)
- mdata->usb_callback(usb_type, attached);
+ switch (usb_type) {
+ case MAX8997_USB_HOST:
+ extcon_set_cable_state(info->edev, "USB-Host", attached);
+ break;
+ case MAX8997_USB_DEVICE:
+ extcon_set_cable_state(info->edev, "USB", attached);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
out:
return ret;
}
-static void max8997_muic_handle_mhl(struct max8997_muic_info *info,
- bool attached)
-{
- struct max8997_muic_platform_data *mdata = info->muic_pdata;
-
- if (mdata->mhl_callback)
- mdata->mhl_callback(attached);
-}
-
static int max8997_muic_handle_dock(struct max8997_muic_info *info,
int adc, bool attached)
{
- struct max8997_muic_platform_data *mdata = info->muic_pdata;
int ret = 0;
/* switch to AUDIO */
@@ -157,14 +170,13 @@ static int max8997_muic_handle_dock(struct max8997_muic_info *info,
switch (adc) {
case MAX8997_ADC_DESKDOCK:
- if (mdata->deskdock_callback)
- mdata->deskdock_callback(attached);
+ extcon_set_cable_state(info->edev, "Dock-desk", attached);
break;
case MAX8997_ADC_CARDOCK:
- if (mdata->cardock_callback)
- mdata->cardock_callback(attached);
+ extcon_set_cable_state(info->edev, "Dock-card", attached);
break;
default:
+ ret = -EINVAL;
break;
}
out:
@@ -174,7 +186,6 @@ out:
static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info,
bool attached)
{
- struct max8997_muic_platform_data *mdata = info->muic_pdata;
int ret = 0;
/* switch to UART */
@@ -186,8 +197,7 @@ static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info,
goto out;
}
- if (mdata->uart_callback)
- mdata->uart_callback(attached);
+ extcon_set_cable_state(info->edev, "JIG", attached);
out:
return ret;
}
@@ -201,7 +211,7 @@ static int max8997_muic_handle_adc_detach(struct max8997_muic_info *info)
ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, false);
break;
case MAX8997_ADC_MHL:
- max8997_muic_handle_mhl(info, false);
+ extcon_set_cable_state(info->edev, "MHL", false);
break;
case MAX8997_ADC_JIG_USB_1:
case MAX8997_ADC_JIG_USB_2:
@@ -230,7 +240,7 @@ static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc)
ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, true);
break;
case MAX8997_ADC_MHL:
- max8997_muic_handle_mhl(info, true);
+ extcon_set_cable_state(info->edev, "MHL", true);
break;
case MAX8997_ADC_JIG_USB_1:
case MAX8997_ADC_JIG_USB_2:
@@ -247,10 +257,40 @@ static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc)
ret = max8997_muic_handle_adc_detach(info);
break;
default:
- break;
+ ret = -EINVAL;
+ goto out;
}
info->pre_adc = adc;
+out:
+ return ret;
+}
+
+static int max8997_muic_handle_charger_type_detach(
+ struct max8997_muic_info *info)
+{
+ int ret = 0;
+
+ switch (info->pre_charger_type) {
+ case MAX8997_CHARGER_TYPE_USB:
+ extcon_set_cable_state(info->edev, "USB", false);
+ break;
+ case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
+ extcon_set_cable_state(info->edev, "Charge-downstream", false);
+ break;
+ case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
+ extcon_set_cable_state(info->edev, "TA", false);
+ break;
+ case MAX8997_CHARGER_TYPE_500MA:
+ extcon_set_cable_state(info->edev, "Slow-charger", false);
+ break;
+ case MAX8997_CHARGER_TYPE_1A:
+ extcon_set_cable_state(info->edev, "Fast-charger", false);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
return ret;
}
@@ -258,7 +298,6 @@ static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc)
static int max8997_muic_handle_charger_type(struct max8997_muic_info *info,
enum max8997_muic_charger_type charger_type)
{
- struct max8997_muic_platform_data *mdata = info->muic_pdata;
u8 adc;
int ret;
@@ -270,30 +309,29 @@ static int max8997_muic_handle_charger_type(struct max8997_muic_info *info,
switch (charger_type) {
case MAX8997_CHARGER_TYPE_NONE:
- if (mdata->charger_callback)
- mdata->charger_callback(false, charger_type);
- if (info->pre_charger_type == MAX8997_CHARGER_TYPE_USB) {
- max8997_muic_handle_usb(info,
- MAX8997_USB_DEVICE, false);
- }
+ ret = max8997_muic_handle_charger_type_detach(info);
break;
case MAX8997_CHARGER_TYPE_USB:
if ((adc & STATUS1_ADC_MASK) == MAX8997_ADC_OPEN) {
max8997_muic_handle_usb(info,
MAX8997_USB_DEVICE, true);
}
- if (mdata->charger_callback)
- mdata->charger_callback(true, charger_type);
break;
case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
+ extcon_set_cable_state(info->edev, "Charge-downstream", true);
+ break;
case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
+ extcon_set_cable_state(info->edev, "TA", true);
+ break;
case MAX8997_CHARGER_TYPE_500MA:
+ extcon_set_cable_state(info->edev, "Slow-charger", true);
+ break;
case MAX8997_CHARGER_TYPE_1A:
- if (mdata->charger_callback)
- mdata->charger_callback(true, charger_type);
+ extcon_set_cable_state(info->edev, "Fast-charger", true);
break;
default:
- break;
+ ret = -EINVAL;
+ goto out;
}
info->pre_charger_type = charger_type;
@@ -305,18 +343,17 @@ static void max8997_muic_irq_work(struct work_struct *work)
{
struct max8997_muic_info *info = container_of(work,
struct max8997_muic_info, irq_work);
- struct max8997_platform_data *pdata =
- dev_get_platdata(info->iodev->dev);
- u8 status[3];
+ struct max8997_dev *max8997 = i2c_get_clientdata(info->muic);
+ u8 status[2];
u8 adc, chg_type;
- int irq_type = info->irq - pdata->irq_base;
+ int irq_type = info->irq - max8997->irq_base;
int ret;
mutex_lock(&info->mutex);
ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
- 3, status);
+ 2, status);
if (ret) {
dev_err(info->dev, "failed to read muic register\n");
mutex_unlock(&info->mutex);
@@ -340,8 +377,8 @@ static void max8997_muic_irq_work(struct work_struct *work)
max8997_muic_handle_charger_type(info, chg_type);
break;
default:
- dev_info(info->dev, "misc interrupt: %s occurred\n",
- muic_irqs[irq_type].name);
+ dev_info(info->dev, "misc interrupt: irq %d occurred\n",
+ irq_type);
break;
}
@@ -387,21 +424,10 @@ static void max8997_muic_detect_dev(struct max8997_muic_info *info)
max8997_muic_handle_charger_type(info, chg_type);
}
-static void max8997_initialize_device(struct max8997_muic_info *info)
-{
- struct max8997_muic_platform_data *mdata = info->muic_pdata;
- int i;
-
- for (i = 0; i < mdata->num_init_data; i++) {
- max8997_write_reg(info->muic, mdata->init_data[i].addr,
- mdata->init_data[i].data);
- }
-}
-
static int __devinit max8997_muic_probe(struct platform_device *pdev)
{
- struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
- struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+ struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent);
+ struct max8997_platform_data *pdata = dev_get_platdata(max8997->dev);
struct max8997_muic_info *info;
int ret, i;
@@ -412,16 +438,8 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev)
goto err_kfree;
}
- if (!pdata->muic_pdata) {
- dev_err(&pdev->dev, "failed to get platform_data\n");
- ret = -EINVAL;
- goto err_pdata;
- }
- info->muic_pdata = pdata->muic_pdata;
-
info->dev = &pdev->dev;
- info->iodev = iodev;
- info->muic = iodev->muic;
+ info->muic = max8997->muic;
platform_set_drvdata(pdev, info);
mutex_init(&info->mutex);
@@ -440,24 +458,45 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev)
"failed: irq request (IRQ: %d,"
" error :%d)\n",
muic_irq->irq, ret);
-
- for (i = i - 1; i >= 0; i--)
- free_irq(muic_irq->irq, info);
-
goto err_irq;
}
}
+ /* External connector */
+ info->edev = kzalloc(sizeof(struct extcon_dev), GFP_KERNEL);
+ if (!info->edev) {
+ dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
+ ret = -ENOMEM;
+ goto err_irq;
+ }
+ info->edev->name = DEV_NAME;
+ info->edev->supported_cable = max8997_extcon_cable;
+ ret = extcon_dev_register(info->edev, NULL);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register extcon device\n");
+ goto err_extcon;
+ }
+
/* Initialize registers according to platform data */
- max8997_initialize_device(info);
+ if (pdata->muic_pdata) {
+ struct max8997_muic_platform_data *mdata = info->muic_pdata;
+
+ for (i = 0; i < mdata->num_init_data; i++) {
+ max8997_write_reg(info->muic, mdata->init_data[i].addr,
+ mdata->init_data[i].data);
+ }
+ }
/* Initial device detection */
max8997_muic_detect_dev(info);
return ret;
+err_extcon:
+ kfree(info->edev);
err_irq:
-err_pdata:
+ while (--i >= 0)
+ free_irq(pdata->irq_base + muic_irqs[i].irq, info);
kfree(info);
err_kfree:
return ret;
@@ -466,14 +505,15 @@ err_kfree:
static int __devexit max8997_muic_remove(struct platform_device *pdev)
{
struct max8997_muic_info *info = platform_get_drvdata(pdev);
- struct max8997_platform_data *pdata =
- dev_get_platdata(info->iodev->dev);
+ struct max8997_dev *max8997 = i2c_get_clientdata(info->muic);
int i;
for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
- free_irq(pdata->irq_base + muic_irqs[i].irq, info);
+ free_irq(max8997->irq_base + muic_irqs[i].irq, info);
cancel_work_sync(&info->irq_work);
+ extcon_dev_unregister(info->edev);
+
kfree(info);
return 0;
@@ -481,7 +521,7 @@ static int __devexit max8997_muic_remove(struct platform_device *pdev)
static struct platform_driver max8997_muic_driver = {
.driver = {
- .name = "max8997-muic",
+ .name = DEV_NAME,
.owner = THIS_MODULE,
},
.probe = max8997_muic_probe,
@@ -490,6 +530,6 @@ static struct platform_driver max8997_muic_driver = {
module_platform_driver(max8997_muic_driver);
-MODULE_DESCRIPTION("Maxim MAX8997 MUIC driver");
+MODULE_DESCRIPTION("Maxim MAX8997 Extcon driver");
MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/extcon/extcon_class.c b/drivers/extcon/extcon_class.c
new file mode 100644
index 000000000000..f598a700ec15
--- /dev/null
+++ b/drivers/extcon/extcon_class.c
@@ -0,0 +1,832 @@
+/*
+ * drivers/extcon/extcon_class.c
+ *
+ * External connector (extcon) class driver
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Author: Donggeun Kim <dg77.kim@samsung.com>
+ * Author: MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * based on android/drivers/switch/switch_class.c
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/err.h>
+#include <linux/extcon.h>
+#include <linux/slab.h>
+
+/*
+ * extcon_cable_name suggests the standard cable names for commonly used
+ * cable types.
+ *
+ * However, please do not use extcon_cable_name directly for extcon_dev
+ * struct's supported_cable pointer unless your device really supports
+ * every single port-type of the following cable names. Please choose cable
+ * names that are actually used in your extcon device.
+ */
+const char *extcon_cable_name[] = {
+ [EXTCON_USB] = "USB",
+ [EXTCON_USB_HOST] = "USB-Host",
+ [EXTCON_TA] = "TA",
+ [EXTCON_FAST_CHARGER] = "Fast-charger",
+ [EXTCON_SLOW_CHARGER] = "Slow-charger",
+ [EXTCON_CHARGE_DOWNSTREAM] = "Charge-downstream",
+ [EXTCON_HDMI] = "HDMI",
+ [EXTCON_MHL] = "MHL",
+ [EXTCON_DVI] = "DVI",
+ [EXTCON_VGA] = "VGA",
+ [EXTCON_DOCK] = "Dock",
+ [EXTCON_LINE_IN] = "Line-in",
+ [EXTCON_LINE_OUT] = "Line-out",
+ [EXTCON_MIC_IN] = "Microphone",
+ [EXTCON_HEADPHONE_OUT] = "Headphone",
+ [EXTCON_SPDIF_IN] = "SPDIF-in",
+ [EXTCON_SPDIF_OUT] = "SPDIF-out",
+ [EXTCON_VIDEO_IN] = "Video-in",
+ [EXTCON_VIDEO_OUT] = "Video-out",
+ [EXTCON_MECHANICAL] = "Mechanical",
+
+ NULL,
+};
+
+struct class *extcon_class;
+#if defined(CONFIG_ANDROID)
+static struct class_compat *switch_class;
+#endif /* CONFIG_ANDROID */
+
+static LIST_HEAD(extcon_dev_list);
+static DEFINE_MUTEX(extcon_dev_list_lock);
+
+/**
+ * check_mutually_exclusive - Check if new_state violates mutually_exclusive
+ * condition.
+ * @edev: the extcon device
+ * @new_state: new cable attach status for @edev
+ *
+ * Returns 0 if nothing violates. Returns the index + 1 for the first
+ * violated condition.
+ */
+static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
+{
+ int i = 0;
+
+ if (!edev->mutually_exclusive)
+ return 0;
+
+ for (i = 0; edev->mutually_exclusive[i]; i++) {
+ int count = 0, j;
+ u32 correspondants = new_state & edev->mutually_exclusive[i];
+ u32 exp = 1;
+
+ for (j = 0; j < 32; j++) {
+ if (exp & correspondants)
+ count++;
+ if (count > 1)
+ return i + 1;
+ exp <<= 1;
+ }
+ }
+
+ return 0;
+}
+
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int i, count = 0;
+ struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
+
+ if (edev->print_state) {
+ int ret = edev->print_state(edev, buf);
+
+ if (ret >= 0)
+ return ret;
+ /* Use default if failed */
+ }
+
+ if (edev->max_supported == 0)
+ return sprintf(buf, "%u\n", edev->state);
+
+ for (i = 0; i < SUPPORTED_CABLE_MAX; i++) {
+ if (!edev->supported_cable[i])
+ break;
+ count += sprintf(buf + count, "%s=%d\n",
+ edev->supported_cable[i],
+ !!(edev->state & (1 << i)));
+ }
+
+ return count;
+}
+
+int extcon_set_state(struct extcon_dev *edev, u32 state);
+static ssize_t state_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 state;
+ ssize_t ret = 0;
+ struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
+
+ ret = sscanf(buf, "0x%x", &state);
+ if (ret == 0)
+ ret = -EINVAL;
+ else
+ ret = extcon_set_state(edev, state);
+
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static ssize_t name_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
+
+ /* Optional callback given by the user */
+ if (edev->print_name) {
+ int ret = edev->print_name(edev, buf);
+ if (ret >= 0)
+ return ret;
+ }
+
+ return sprintf(buf, "%s\n", dev_name(edev->dev));
+}
+
+static ssize_t cable_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct extcon_cable *cable = container_of(attr, struct extcon_cable,
+ attr_name);
+
+ return sprintf(buf, "%s\n",
+ cable->edev->supported_cable[cable->cable_index]);
+}
+
+static ssize_t cable_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct extcon_cable *cable = container_of(attr, struct extcon_cable,
+ attr_state);
+
+ return sprintf(buf, "%d\n",
+ extcon_get_cable_state_(cable->edev,
+ cable->cable_index));
+}
+
+static ssize_t cable_state_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct extcon_cable *cable = container_of(attr, struct extcon_cable,
+ attr_state);
+ int ret, state;
+
+ ret = sscanf(buf, "%d", &state);
+ if (ret == 0)
+ ret = -EINVAL;
+ else
+ ret = extcon_set_cable_state_(cable->edev, cable->cable_index,
+ state);
+
+ if (ret < 0)
+ return ret;
+ return count;
+}
+
+/**
+ * extcon_update_state() - Update the cable attach states of the extcon device
+ * only for the masked bits.
+ * @edev: the extcon device
+ * @mask: the bit mask to designate updated bits.
+ * @state: new cable attach status for @edev
+ *
+ * Changing the state sends uevent with environment variable containing
+ * the name of extcon device (envp[0]) and the state output (envp[1]).
+ * Tizen uses this format for extcon device to get events from ports.
+ * Android uses this format as well.
+ *
+ * Note that the notifier provides which bits are changed in the state
+ * variable with the val parameter (second) to the callback.
+ */
+int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
+{
+ char name_buf[120];
+ char state_buf[120];
+ char *prop_buf;
+ char *envp[3];
+ int env_offset = 0;
+ int length;
+ unsigned long flags;
+
+ spin_lock_irqsave(&edev->lock, flags);
+
+ if (edev->state != ((edev->state & ~mask) | (state & mask))) {
+ u32 old_state = edev->state;
+
+ if (check_mutually_exclusive(edev, (edev->state & ~mask) |
+ (state & mask))) {
+ spin_unlock_irqrestore(&edev->lock, flags);
+ return -EPERM;
+ }
+
+ edev->state &= ~mask;
+ edev->state |= state & mask;
+
+ raw_notifier_call_chain(&edev->nh, old_state, edev);
+
+ /* This could be in interrupt handler */
+ prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
+ if (prop_buf) {
+ length = name_show(edev->dev, NULL, prop_buf);
+ if (length > 0) {
+ if (prop_buf[length - 1] == '\n')
+ prop_buf[length - 1] = 0;
+ snprintf(name_buf, sizeof(name_buf),
+ "NAME=%s", prop_buf);
+ envp[env_offset++] = name_buf;
+ }
+ length = state_show(edev->dev, NULL, prop_buf);
+ if (length > 0) {
+ if (prop_buf[length - 1] == '\n')
+ prop_buf[length - 1] = 0;
+ snprintf(state_buf, sizeof(state_buf),
+ "STATE=%s", prop_buf);
+ envp[env_offset++] = state_buf;
+ }
+ envp[env_offset] = NULL;
+ /* Unlock early before uevent */
+ spin_unlock_irqrestore(&edev->lock, flags);
+
+ kobject_uevent_env(&edev->dev->kobj, KOBJ_CHANGE, envp);
+ free_page((unsigned long)prop_buf);
+ } else {
+ /* Unlock early before uevent */
+ spin_unlock_irqrestore(&edev->lock, flags);
+
+ dev_err(edev->dev, "out of memory in extcon_set_state\n");
+ kobject_uevent(&edev->dev->kobj, KOBJ_CHANGE);
+ }
+ } else {
+ /* No changes */
+ spin_unlock_irqrestore(&edev->lock, flags);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(extcon_update_state);
+
+/**
+ * extcon_set_state() - Set the cable attach states of the extcon device.
+ * @edev: the extcon device
+ * @state: new cable attach status for @edev
+ *
+ * Note that notifier provides which bits are changed in the state
+ * variable with the val parameter (second) to the callback.
+ */
+int extcon_set_state(struct extcon_dev *edev, u32 state)
+{
+ return extcon_update_state(edev, 0xffffffff, state);
+}
+EXPORT_SYMBOL_GPL(extcon_set_state);
+
+/**
+ * extcon_find_cable_index() - Get the cable index based on the cable name.
+ * @edev: the extcon device that has the cable.
+ * @cable_name: cable name to be searched.
+ *
+ * Note that accessing a cable state based on cable_index is faster than
+ * cable_name because using cable_name induces a loop with strncmp().
+ * Thus, when get/set_cable_state is repeatedly used, using cable_index
+ * is recommended.
+ */
+int extcon_find_cable_index(struct extcon_dev *edev, const char *cable_name)
+{
+ int i;
+
+ if (edev->supported_cable) {
+ for (i = 0; edev->supported_cable[i]; i++) {
+ if (!strncmp(edev->supported_cable[i],
+ cable_name, CABLE_NAME_MAX))
+ return i;
+ }
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(extcon_find_cable_index);
+
+/**
+ * extcon_get_cable_state_() - Get the status of a specific cable.
+ * @edev: the extcon device that has the cable.
+ * @index: cable index that can be retrieved by extcon_find_cable_index().
+ */
+int extcon_get_cable_state_(struct extcon_dev *edev, int index)
+{
+ if (index < 0 || (edev->max_supported && edev->max_supported <= index))
+ return -EINVAL;
+
+ return !!(edev->state & (1 << index));
+}
+EXPORT_SYMBOL_GPL(extcon_get_cable_state_);
+
+/**
+ * extcon_get_cable_state() - Get the status of a specific cable.
+ * @edev: the extcon device that has the cable.
+ * @cable_name: cable name.
+ *
+ * Note that this is slower than extcon_get_cable_state_.
+ */
+int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
+{
+ return extcon_get_cable_state_(edev, extcon_find_cable_index
+ (edev, cable_name));
+}
+EXPORT_SYMBOL_GPL(extcon_get_cable_state);
+
+/**
+ * extcon_get_cable_state_() - Set the status of a specific cable.
+ * @edev: the extcon device that has the cable.
+ * @index: cable index that can be retrieved by extcon_find_cable_index().
+ * @cable_state: the new cable status. The default semantics is
+ * true: attached / false: detached.
+ */
+int extcon_set_cable_state_(struct extcon_dev *edev,
+ int index, bool cable_state)
+{
+ u32 state;
+
+ if (index < 0 || (edev->max_supported && edev->max_supported <= index))
+ return -EINVAL;
+
+ state = cable_state ? (1 << index) : 0;
+ return extcon_update_state(edev, 1 << index, state);
+}
+EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
+
+/**
+ * extcon_get_cable_state() - Set the status of a specific cable.
+ * @edev: the extcon device that has the cable.
+ * @cable_name: cable name.
+ * @cable_state: the new cable status. The default semantics is
+ * true: attached / false: detached.
+ *
+ * Note that this is slower than extcon_set_cable_state_.
+ */
+int extcon_set_cable_state(struct extcon_dev *edev,
+ const char *cable_name, bool cable_state)
+{
+ return extcon_set_cable_state_(edev, extcon_find_cable_index
+ (edev, cable_name), cable_state);
+}
+EXPORT_SYMBOL_GPL(extcon_set_cable_state);
+
+/**
+ * extcon_get_extcon_dev() - Get the extcon device instance from the name
+ * @extcon_name: The extcon name provided with extcon_dev_register()
+ */
+struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
+{
+ struct extcon_dev *sd;
+
+ mutex_lock(&extcon_dev_list_lock);
+ list_for_each_entry(sd, &extcon_dev_list, entry) {
+ if (!strcmp(sd->name, extcon_name))
+ goto out;
+ }
+ sd = NULL;
+out:
+ mutex_unlock(&extcon_dev_list_lock);
+ return sd;
+}
+EXPORT_SYMBOL_GPL(extcon_get_extcon_dev);
+
+static int _call_per_cable(struct notifier_block *nb, unsigned long val,
+ void *ptr)
+{
+ struct extcon_specific_cable_nb *obj = container_of(nb,
+ struct extcon_specific_cable_nb, internal_nb);
+ struct extcon_dev *edev = ptr;
+
+ if ((val & (1 << obj->cable_index)) !=
+ (edev->state & (1 << obj->cable_index))) {
+ bool cable_state = true;
+
+ obj->previous_value = val;
+
+ if (val & (1 << obj->cable_index))
+ cable_state = false;
+
+ return obj->user_nb->notifier_call(obj->user_nb,
+ cable_state, ptr);
+ }
+
+ return NOTIFY_OK;
+}
+
+/**
+ * extcon_register_interest() - Register a notifier for a state change of a
+ * specific cable, not a entier set of cables of a
+ * extcon device.
+ * @obj: an empty extcon_specific_cable_nb object to be returned.
+ * @extcon_name: the name of extcon device.
+ * @cable_name: the target cable name.
+ * @nb: the notifier block to get notified.
+ *
+ * Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets
+ * the struct for you.
+ *
+ * extcon_register_interest is a helper function for those who want to get
+ * notification for a single specific cable's status change. If a user wants
+ * to get notification for any changes of all cables of a extcon device,
+ * he/she should use the general extcon_register_notifier().
+ *
+ * Note that the second parameter given to the callback of nb (val) is
+ * "old_state", not the current state. The current state can be retrieved
+ * by looking at the third pameter (edev pointer)'s state value.
+ */
+int extcon_register_interest(struct extcon_specific_cable_nb *obj,
+ const char *extcon_name, const char *cable_name,
+ struct notifier_block *nb)
+{
+ if (!obj || !extcon_name || !cable_name || !nb)
+ return -EINVAL;
+
+ obj->edev = extcon_get_extcon_dev(extcon_name);
+ if (!obj->edev)
+ return -ENODEV;
+
+ obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
+ if (obj->cable_index < 0)
+ return -ENODEV;
+
+ obj->user_nb = nb;
+
+ obj->internal_nb.notifier_call = _call_per_cable;
+
+ return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+}
+
+/**
+ * extcon_unregister_interest() - Unregister the notifier registered by
+ * extcon_register_interest().
+ * @obj: the extcon_specific_cable_nb object returned by
+ * extcon_register_interest().
+ */
+int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
+{
+ if (!obj)
+ return -EINVAL;
+
+ return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb);
+}
+
+/**
+ * extcon_register_notifier() - Register a notifee to get notified by
+ * any attach status changes from the extcon.
+ * @edev: the extcon device.
+ * @nb: a notifier block to be registered.
+ *
+ * Note that the second parameter given to the callback of nb (val) is
+ * "old_state", not the current state. The current state can be retrieved
+ * by looking at the third pameter (edev pointer)'s state value.
+ */
+int extcon_register_notifier(struct extcon_dev *edev,
+ struct notifier_block *nb)
+{
+ return raw_notifier_chain_register(&edev->nh, nb);
+}
+EXPORT_SYMBOL_GPL(extcon_register_notifier);
+
+/**
+ * extcon_unregister_notifier() - Unregister a notifee from the extcon device.
+ * @edev: the extcon device.
+ * @nb: a registered notifier block to be unregistered.
+ */
+int extcon_unregister_notifier(struct extcon_dev *edev,
+ struct notifier_block *nb)
+{
+ return raw_notifier_chain_unregister(&edev->nh, nb);
+}
+EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
+
+static struct device_attribute extcon_attrs[] = {
+ __ATTR(state, S_IRUGO | S_IWUSR, state_show, state_store),
+ __ATTR_RO(name),
+ __ATTR_NULL,
+};
+
+static int create_extcon_class(void)
+{
+ if (!extcon_class) {
+ extcon_class = class_create(THIS_MODULE, "extcon");
+ if (IS_ERR(extcon_class))
+ return PTR_ERR(extcon_class);
+ extcon_class->dev_attrs = extcon_attrs;
+
+#if defined(CONFIG_ANDROID)
+ switch_class = class_compat_register("switch");
+ if (WARN(!switch_class, "cannot allocate"))
+ return -ENOMEM;
+#endif /* CONFIG_ANDROID */
+ }
+
+ return 0;
+}
+
+static void extcon_cleanup(struct extcon_dev *edev, bool skip)
+{
+ mutex_lock(&extcon_dev_list_lock);
+ list_del(&edev->entry);
+ mutex_unlock(&extcon_dev_list_lock);
+
+ if (!skip && get_device(edev->dev)) {
+ int index;
+
+ if (edev->mutually_exclusive && edev->max_supported) {
+ for (index = 0; edev->mutually_exclusive[index];
+ index++)
+ kfree(edev->d_attrs_muex[index].attr.name);
+ kfree(edev->d_attrs_muex);
+ kfree(edev->attrs_muex);
+ }
+
+ for (index = 0; index < edev->max_supported; index++)
+ kfree(edev->cables[index].attr_g.name);
+
+ if (edev->max_supported) {
+ kfree(edev->extcon_dev_type.groups);
+ kfree(edev->cables);
+ }
+
+ device_unregister(edev->dev);
+ put_device(edev->dev);
+ }
+
+ kfree(edev->dev);
+}
+
+static void extcon_dev_release(struct device *dev)
+{
+ struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
+
+ extcon_cleanup(edev, true);
+}
+
+static const char *muex_name = "mutually_exclusive";
+static void dummy_sysfs_dev_release(struct device *dev)
+{
+}
+
+/**
+ * extcon_dev_register() - Register a new extcon device
+ * @edev : the new extcon device (should be allocated before calling)
+ * @dev : the parent device for this extcon device.
+ *
+ * Among the members of edev struct, please set the "user initializing data"
+ * in any case and set the "optional callbacks" if required. However, please
+ * do not set the values of "internal data", which are initialized by
+ * this function.
+ */
+int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
+{
+ int ret, index = 0;
+
+ if (!extcon_class) {
+ ret = create_extcon_class();
+ if (ret < 0)
+ return ret;
+ }
+
+ if (edev->supported_cable) {
+ /* Get size of array */
+ for (index = 0; edev->supported_cable[index]; index++)
+ ;
+ edev->max_supported = index;
+ } else {
+ edev->max_supported = 0;
+ }
+
+ if (index > SUPPORTED_CABLE_MAX) {
+ dev_err(edev->dev, "extcon: maximum number of supported cables exceeded.\n");
+ return -EINVAL;
+ }
+
+ edev->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+ if (!edev->dev)
+ return -ENOMEM;
+ edev->dev->parent = dev;
+ edev->dev->class = extcon_class;
+ edev->dev->release = extcon_dev_release;
+
+ dev_set_name(edev->dev, edev->name ? edev->name : dev_name(dev));
+
+ if (edev->max_supported) {
+ char buf[10];
+ char *str;
+ struct extcon_cable *cable;
+
+ edev->cables = kzalloc(sizeof(struct extcon_cable) *
+ edev->max_supported, GFP_KERNEL);
+ if (!edev->cables) {
+ ret = -ENOMEM;
+ goto err_sysfs_alloc;
+ }
+ for (index = 0; index < edev->max_supported; index++) {
+ cable = &edev->cables[index];
+
+ snprintf(buf, 10, "cable.%d", index);
+ str = kzalloc(sizeof(char) * (strlen(buf) + 1),
+ GFP_KERNEL);
+ if (!str) {
+ for (index--; index >= 0; index--) {
+ cable = &edev->cables[index];
+ kfree(cable->attr_g.name);
+ }
+ ret = -ENOMEM;
+
+ goto err_alloc_cables;
+ }
+ strcpy(str, buf);
+
+ cable->edev = edev;
+ cable->cable_index = index;
+ cable->attrs[0] = &cable->attr_name.attr;
+ cable->attrs[1] = &cable->attr_state.attr;
+ cable->attrs[2] = NULL;
+ cable->attr_g.name = str;
+ cable->attr_g.attrs = cable->attrs;
+
+ cable->attr_name.attr.name = "name";
+ cable->attr_name.attr.mode = 0444;
+ cable->attr_name.show = cable_name_show;
+
+ cable->attr_state.attr.name = "state";
+ cable->attr_state.attr.mode = 0644;
+ cable->attr_state.show = cable_state_show;
+ cable->attr_state.store = cable_state_store;
+ }
+ }
+
+ if (edev->max_supported && edev->mutually_exclusive) {
+ char buf[80];
+ char *name;
+
+ /* Count the size of mutually_exclusive array */
+ for (index = 0; edev->mutually_exclusive[index]; index++)
+ ;
+
+ edev->attrs_muex = kzalloc(sizeof(struct attribute *) *
+ (index + 1), GFP_KERNEL);
+ if (!edev->attrs_muex) {
+ ret = -ENOMEM;
+ goto err_muex;
+ }
+
+ edev->d_attrs_muex = kzalloc(sizeof(struct device_attribute) *
+ index, GFP_KERNEL);
+ if (!edev->d_attrs_muex) {
+ ret = -ENOMEM;
+ kfree(edev->attrs_muex);
+ goto err_muex;
+ }
+
+ for (index = 0; edev->mutually_exclusive[index]; index++) {
+ sprintf(buf, "0x%x", edev->mutually_exclusive[index]);
+ name = kzalloc(sizeof(char) * (strlen(buf) + 1),
+ GFP_KERNEL);
+ if (!name) {
+ for (index--; index >= 0; index--) {
+ kfree(edev->d_attrs_muex[index].attr.
+ name);
+ }
+ kfree(edev->d_attrs_muex);
+ kfree(edev->attrs_muex);
+ ret = -ENOMEM;
+ goto err_muex;
+ }
+ strcpy(name, buf);
+ edev->d_attrs_muex[index].attr.name = name;
+ edev->d_attrs_muex[index].attr.mode = 0000;
+ edev->attrs_muex[index] = &edev->d_attrs_muex[index]
+ .attr;
+ }
+ edev->attr_g_muex.name = muex_name;
+ edev->attr_g_muex.attrs = edev->attrs_muex;
+
+ }
+
+ if (edev->max_supported) {
+ edev->extcon_dev_type.groups =
+ kzalloc(sizeof(struct attribute_group *) *
+ (edev->max_supported + 2), GFP_KERNEL);
+ if (!edev->extcon_dev_type.groups) {
+ ret = -ENOMEM;
+ goto err_alloc_groups;
+ }
+
+ edev->extcon_dev_type.name = dev_name(edev->dev);
+ edev->extcon_dev_type.release = dummy_sysfs_dev_release;
+
+ for (index = 0; index < edev->max_supported; index++)
+ edev->extcon_dev_type.groups[index] =
+ &edev->cables[index].attr_g;
+ if (edev->mutually_exclusive)
+ edev->extcon_dev_type.groups[index] =
+ &edev->attr_g_muex;
+
+ edev->dev->type = &edev->extcon_dev_type;
+ }
+
+ ret = device_register(edev->dev);
+ if (ret) {
+ put_device(edev->dev);
+ goto err_dev;
+ }
+#if defined(CONFIG_ANDROID)
+ if (switch_class)
+ ret = class_compat_create_link(switch_class, edev->dev,
+ dev);
+#endif /* CONFIG_ANDROID */
+
+ spin_lock_init(&edev->lock);
+
+ RAW_INIT_NOTIFIER_HEAD(&edev->nh);
+
+ dev_set_drvdata(edev->dev, edev);
+ edev->state = 0;
+
+ mutex_lock(&extcon_dev_list_lock);
+ list_add(&edev->entry, &extcon_dev_list);
+ mutex_unlock(&extcon_dev_list_lock);
+
+ return 0;
+
+err_dev:
+ if (edev->max_supported)
+ kfree(edev->extcon_dev_type.groups);
+err_alloc_groups:
+ if (edev->max_supported && edev->mutually_exclusive) {
+ for (index = 0; edev->mutually_exclusive[index]; index++)
+ kfree(edev->d_attrs_muex[index].attr.name);
+ kfree(edev->d_attrs_muex);
+ kfree(edev->attrs_muex);
+ }
+err_muex:
+ for (index = 0; index < edev->max_supported; index++)
+ kfree(edev->cables[index].attr_g.name);
+err_alloc_cables:
+ if (edev->max_supported)
+ kfree(edev->cables);
+err_sysfs_alloc:
+ kfree(edev->dev);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(extcon_dev_register);
+
+/**
+ * extcon_dev_unregister() - Unregister the extcon device.
+ * @edev: the extcon device instance to be unregitered.
+ *
+ * Note that this does not call kfree(edev) because edev was not allocated
+ * by this class.
+ */
+void extcon_dev_unregister(struct extcon_dev *edev)
+{
+ extcon_cleanup(edev, false);
+}
+EXPORT_SYMBOL_GPL(extcon_dev_unregister);
+
+static int __init extcon_class_init(void)
+{
+ return create_extcon_class();
+}
+module_init(extcon_class_init);
+
+static void __exit extcon_class_exit(void)
+{
+ class_destroy(extcon_class);
+}
+module_exit(extcon_class_exit);
+
+MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
+MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("External connector (extcon) class driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/extcon/extcon_gpio.c b/drivers/extcon/extcon_gpio.c
new file mode 100644
index 000000000000..fe7a07b47336
--- /dev/null
+++ b/drivers/extcon/extcon_gpio.c
@@ -0,0 +1,169 @@
+/*
+ * drivers/extcon/extcon_gpio.c
+ *
+ * Single-state GPIO extcon driver based on extcon class
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.com>
+ *
+ * Modified by MyungJoo Ham <myungjoo.ham@samsung.com> to support extcon
+ * (originally switch class is supported)
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/extcon.h>
+#include <linux/workqueue.h>
+#include <linux/gpio.h>
+#include <linux/extcon.h>
+#include <linux/extcon/extcon_gpio.h>
+
+struct gpio_extcon_data {
+ struct extcon_dev edev;
+ unsigned gpio;
+ const char *state_on;
+ const char *state_off;
+ int irq;
+ struct delayed_work work;
+ unsigned long debounce_jiffies;
+};
+
+static void gpio_extcon_work(struct work_struct *work)
+{
+ int state;
+ struct gpio_extcon_data *data =
+ container_of(to_delayed_work(work), struct gpio_extcon_data,
+ work);
+
+ state = gpio_get_value(data->gpio);
+ extcon_set_state(&data->edev, state);
+}
+
+static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+{
+ struct gpio_extcon_data *extcon_data = dev_id;
+
+ schedule_delayed_work(&extcon_data->work,
+ extcon_data->debounce_jiffies);
+ return IRQ_HANDLED;
+}
+
+static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
+{
+ struct gpio_extcon_data *extcon_data =
+ container_of(edev, struct gpio_extcon_data, edev);
+ const char *state;
+ if (extcon_get_state(edev))
+ state = extcon_data->state_on;
+ else
+ state = extcon_data->state_off;
+
+ if (state)
+ return sprintf(buf, "%s\n", state);
+ return -EINVAL;
+}
+
+static int __devinit gpio_extcon_probe(struct platform_device *pdev)
+{
+ struct gpio_extcon_platform_data *pdata = pdev->dev.platform_data;
+ struct gpio_extcon_data *extcon_data;
+ int ret = 0;
+
+ if (!pdata)
+ return -EBUSY;
+ if (!pdata->irq_flags) {
+ dev_err(&pdev->dev, "IRQ flag is not specified.\n");
+ return -EINVAL;
+ }
+
+ extcon_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_extcon_data),
+ GFP_KERNEL);
+ if (!extcon_data)
+ return -ENOMEM;
+
+ extcon_data->edev.name = pdata->name;
+ extcon_data->gpio = pdata->gpio;
+ extcon_data->state_on = pdata->state_on;
+ extcon_data->state_off = pdata->state_off;
+ if (pdata->state_on && pdata->state_off)
+ extcon_data->edev.print_state = extcon_gpio_print_state;
+ extcon_data->debounce_jiffies = msecs_to_jiffies(pdata->debounce);
+
+ ret = extcon_dev_register(&extcon_data->edev, &pdev->dev);
+ if (ret < 0)
+ goto err_extcon_dev_register;
+
+ ret = gpio_request_one(extcon_data->gpio, GPIOF_DIR_IN, pdev->name);
+ if (ret < 0)
+ goto err_request_gpio;
+
+ INIT_DELAYED_WORK(&extcon_data->work, gpio_extcon_work);
+
+ extcon_data->irq = gpio_to_irq(extcon_data->gpio);
+ if (extcon_data->irq < 0) {
+ ret = extcon_data->irq;
+ goto err_detect_irq_num_failed;
+ }
+
+ ret = request_any_context_irq(extcon_data->irq, gpio_irq_handler,
+ pdata->irq_flags, pdev->name,
+ extcon_data);
+ if (ret < 0)
+ goto err_request_irq;
+
+ /* Perform initial detection */
+ gpio_extcon_work(&extcon_data->work.work);
+
+ return 0;
+
+err_request_irq:
+err_detect_irq_num_failed:
+ gpio_free(extcon_data->gpio);
+err_request_gpio:
+ extcon_dev_unregister(&extcon_data->edev);
+err_extcon_dev_register:
+ devm_kfree(&pdev->dev, extcon_data);
+
+ return ret;
+}
+
+static int __devexit gpio_extcon_remove(struct platform_device *pdev)
+{
+ struct gpio_extcon_data *extcon_data = platform_get_drvdata(pdev);
+
+ cancel_delayed_work_sync(&extcon_data->work);
+ gpio_free(extcon_data->gpio);
+ extcon_dev_unregister(&extcon_data->edev);
+ devm_kfree(&pdev->dev, extcon_data);
+
+ return 0;
+}
+
+static struct platform_driver gpio_extcon_driver = {
+ .probe = gpio_extcon_probe,
+ .remove = __devexit_p(gpio_extcon_remove),
+ .driver = {
+ .name = "extcon-gpio",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver(gpio_extcon_driver);
+
+MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
+MODULE_DESCRIPTION("GPIO extcon driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index cc595eba7ba9..f5552b362efc 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -676,6 +676,7 @@ void fw_card_release(struct kref *kref)
complete(&card->done);
}
+EXPORT_SYMBOL_GPL(fw_card_release);
void fw_core_remove_card(struct fw_card *card)
{
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index dea2dcc9310d..db8a965cf712 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -820,6 +820,15 @@ void fw_send_response(struct fw_card *card,
}
EXPORT_SYMBOL(fw_send_response);
+/**
+ * fw_get_request_speed() - returns speed at which the @request was received
+ */
+int fw_get_request_speed(struct fw_request *request)
+{
+ return request->response.speed;
+}
+EXPORT_SYMBOL(fw_get_request_speed);
+
static void handle_exclusive_region_request(struct fw_card *card,
struct fw_packet *p,
struct fw_request *request,
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index 9047f5547d98..b5a2f6197053 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -120,21 +120,6 @@ int fw_compute_block_crc(__be32 *block);
void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset);
void fw_schedule_bm_work(struct fw_card *card, unsigned long delay);
-static inline struct fw_card *fw_card_get(struct fw_card *card)
-{
- kref_get(&card->kref);
-
- return card;
-}
-
-void fw_card_release(struct kref *kref);
-
-static inline void fw_card_put(struct fw_card *card)
-{
- kref_put(&card->kref, fw_card_release);
-}
-
-
/* -cdev */
extern const struct file_operations fw_device_ops;
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index e03653d69357..eb80ba300452 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -91,6 +91,12 @@ config GPIO_IT8761E
help
Say yes here to support GPIO functionality of IT8761E super I/O chip.
+config GPIO_EM
+ tristate "Emma Mobile GPIO"
+ depends on ARM
+ help
+ Say yes here to support GPIO on Renesas Emma Mobile SoCs.
+
config GPIO_EP93XX
def_bool y
depends on ARCH_EP93XX
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 007f54bd0081..708ffb2165ea 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o
+obj-$(CONFIG_GPIO_EM) += gpio-em.o
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
@@ -36,7 +37,6 @@ obj-$(CONFIG_GPIO_MSM_V1) += gpio-msm-v1.o
obj-$(CONFIG_GPIO_MSM_V2) += gpio-msm-v2.o
obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
-obj-$(CONFIG_PLAT_NOMADIK) += gpio-nomadik.o
obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o
obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c
index 3dd29399cef5..8950f6261bbb 100644
--- a/drivers/gpio/devres.c
+++ b/drivers/gpio/devres.c
@@ -83,8 +83,7 @@ EXPORT_SYMBOL(devm_gpio_request);
void devm_gpio_free(struct device *dev, unsigned int gpio)
{
- WARN_ON(devres_destroy(dev, devm_gpio_release, devm_gpio_match,
+ WARN_ON(devres_release(dev, devm_gpio_release, devm_gpio_match,
&gpio));
- gpio_free(gpio);
}
EXPORT_SYMBOL(devm_gpio_free);
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
new file mode 100644
index 000000000000..150d9768811d
--- /dev/null
+++ b/drivers/gpio/gpio-em.c
@@ -0,0 +1,418 @@
+/*
+ * Emma Mobile GPIO Support - GIO
+ *
+ * Copyright (C) 2012 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_data/gpio-em.h>
+
+struct em_gio_priv {
+ void __iomem *base0;
+ void __iomem *base1;
+ unsigned int irq_base;
+ spinlock_t sense_lock;
+ struct platform_device *pdev;
+ struct gpio_chip gpio_chip;
+ struct irq_chip irq_chip;
+ struct irq_domain *irq_domain;
+};
+
+#define GIO_E1 0x00
+#define GIO_E0 0x04
+#define GIO_EM 0x04
+#define GIO_OL 0x08
+#define GIO_OH 0x0c
+#define GIO_I 0x10
+#define GIO_IIA 0x14
+#define GIO_IEN 0x18
+#define GIO_IDS 0x1c
+#define GIO_IIM 0x1c
+#define GIO_RAW 0x20
+#define GIO_MST 0x24
+#define GIO_IIR 0x28
+
+#define GIO_IDT0 0x40
+#define GIO_IDT1 0x44
+#define GIO_IDT2 0x48
+#define GIO_IDT3 0x4c
+#define GIO_RAWBL 0x50
+#define GIO_RAWBH 0x54
+#define GIO_IRBL 0x58
+#define GIO_IRBH 0x5c
+
+#define GIO_IDT(n) (GIO_IDT0 + ((n) * 4))
+
+static inline unsigned long em_gio_read(struct em_gio_priv *p, int offs)
+{
+ if (offs < GIO_IDT0)
+ return ioread32(p->base0 + offs);
+ else
+ return ioread32(p->base1 + (offs - GIO_IDT0));
+}
+
+static inline void em_gio_write(struct em_gio_priv *p, int offs,
+ unsigned long value)
+{
+ if (offs < GIO_IDT0)
+ iowrite32(value, p->base0 + offs);
+ else
+ iowrite32(value, p->base1 + (offs - GIO_IDT0));
+}
+
+static inline struct em_gio_priv *irq_to_priv(struct irq_data *d)
+{
+ struct irq_chip *chip = irq_data_get_irq_chip(d);
+ return container_of(chip, struct em_gio_priv, irq_chip);
+}
+
+static void em_gio_irq_disable(struct irq_data *d)
+{
+ struct em_gio_priv *p = irq_to_priv(d);
+
+ em_gio_write(p, GIO_IDS, BIT(irqd_to_hwirq(d)));
+}
+
+static void em_gio_irq_enable(struct irq_data *d)
+{
+ struct em_gio_priv *p = irq_to_priv(d);
+
+ em_gio_write(p, GIO_IEN, BIT(irqd_to_hwirq(d)));
+}
+
+#define GIO_ASYNC(x) (x + 8)
+
+static unsigned char em_gio_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
+ [IRQ_TYPE_EDGE_RISING] = GIO_ASYNC(0x00),
+ [IRQ_TYPE_EDGE_FALLING] = GIO_ASYNC(0x01),
+ [IRQ_TYPE_LEVEL_HIGH] = GIO_ASYNC(0x02),
+ [IRQ_TYPE_LEVEL_LOW] = GIO_ASYNC(0x03),
+ [IRQ_TYPE_EDGE_BOTH] = GIO_ASYNC(0x04),
+};
+
+static int em_gio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+ unsigned char value = em_gio_sense_table[type & IRQ_TYPE_SENSE_MASK];
+ struct em_gio_priv *p = irq_to_priv(d);
+ unsigned int reg, offset, shift;
+ unsigned long flags;
+ unsigned long tmp;
+
+ if (!value)
+ return -EINVAL;
+
+ offset = irqd_to_hwirq(d);
+
+ pr_debug("gio: sense irq = %d, mode = %d\n", offset, value);
+
+ /* 8 x 4 bit fields in 4 IDT registers */
+ reg = GIO_IDT(offset >> 3);
+ shift = (offset & 0x07) << 4;
+
+ spin_lock_irqsave(&p->sense_lock, flags);
+
+ /* disable the interrupt in IIA */
+ tmp = em_gio_read(p, GIO_IIA);
+ tmp &= ~BIT(offset);
+ em_gio_write(p, GIO_IIA, tmp);
+
+ /* change the sense setting in IDT */
+ tmp = em_gio_read(p, reg);
+ tmp &= ~(0xf << shift);
+ tmp |= value << shift;
+ em_gio_write(p, reg, tmp);
+
+ /* clear pending interrupts */
+ em_gio_write(p, GIO_IIR, BIT(offset));
+
+ /* enable the interrupt in IIA */
+ tmp = em_gio_read(p, GIO_IIA);
+ tmp |= BIT(offset);
+ em_gio_write(p, GIO_IIA, tmp);
+
+ spin_unlock_irqrestore(&p->sense_lock, flags);
+
+ return 0;
+}
+
+static irqreturn_t em_gio_irq_handler(int irq, void *dev_id)
+{
+ struct em_gio_priv *p = dev_id;
+ unsigned long pending;
+ unsigned int offset, irqs_handled = 0;
+
+ while ((pending = em_gio_read(p, GIO_MST))) {
+ offset = __ffs(pending);
+ em_gio_write(p, GIO_IIR, BIT(offset));
+ generic_handle_irq(irq_find_mapping(p->irq_domain, offset));
+ irqs_handled++;
+ }
+
+ return irqs_handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static inline struct em_gio_priv *gpio_to_priv(struct gpio_chip *chip)
+{
+ return container_of(chip, struct em_gio_priv, gpio_chip);
+}
+
+static int em_gio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ em_gio_write(gpio_to_priv(chip), GIO_E0, BIT(offset));
+ return 0;
+}
+
+static int em_gio_get(struct gpio_chip *chip, unsigned offset)
+{
+ return (int)(em_gio_read(gpio_to_priv(chip), GIO_I) & BIT(offset));
+}
+
+static void __em_gio_set(struct gpio_chip *chip, unsigned int reg,
+ unsigned shift, int value)
+{
+ /* upper 16 bits contains mask and lower 16 actual value */
+ em_gio_write(gpio_to_priv(chip), reg,
+ (1 << (shift + 16)) | (value << shift));
+}
+
+static void em_gio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ /* output is split into two registers */
+ if (offset < 16)
+ __em_gio_set(chip, GIO_OL, offset, value);
+ else
+ __em_gio_set(chip, GIO_OH, offset - 16, value);
+}
+
+static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ /* write GPIO value to output before selecting output mode of pin */
+ em_gio_set(chip, offset, value);
+ em_gio_write(gpio_to_priv(chip), GIO_E1, BIT(offset));
+ return 0;
+}
+
+static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ return irq_find_mapping(gpio_to_priv(chip)->irq_domain, offset);
+}
+
+static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct em_gio_priv *p = h->host_data;
+
+ pr_debug("gio: map hw irq = %d, virq = %d\n", (int)hw, virq);
+
+ irq_set_chip_data(virq, h->host_data);
+ irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
+ set_irq_flags(virq, IRQF_VALID); /* kill me now */
+ return 0;
+}
+
+static struct irq_domain_ops em_gio_irq_domain_ops = {
+ .map = em_gio_irq_domain_map,
+};
+
+static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p)
+{
+ struct platform_device *pdev = p->pdev;
+ struct gpio_em_config *pdata = pdev->dev.platform_data;
+
+ p->irq_base = irq_alloc_descs(pdata->irq_base, 0,
+ pdata->number_of_pins, numa_node_id());
+ if (IS_ERR_VALUE(p->irq_base)) {
+ dev_err(&pdev->dev, "cannot get irq_desc\n");
+ return -ENXIO;
+ }
+ pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n",
+ pdata->gpio_base, pdata->number_of_pins, p->irq_base);
+
+ p->irq_domain = irq_domain_add_legacy(pdev->dev.of_node,
+ pdata->number_of_pins,
+ p->irq_base, 0,
+ &em_gio_irq_domain_ops, p);
+ if (!p->irq_domain) {
+ irq_free_descs(p->irq_base, pdata->number_of_pins);
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static void __devexit em_gio_irq_domain_cleanup(struct em_gio_priv *p)
+{
+ struct gpio_em_config *pdata = p->pdev->dev.platform_data;
+
+ irq_free_descs(p->irq_base, pdata->number_of_pins);
+ /* FIXME: irq domain wants to be freed! */
+}
+
+static int __devinit em_gio_probe(struct platform_device *pdev)
+{
+ struct gpio_em_config *pdata = pdev->dev.platform_data;
+ struct em_gio_priv *p;
+ struct resource *io[2], *irq[2];
+ struct gpio_chip *gpio_chip;
+ struct irq_chip *irq_chip;
+ const char *name = dev_name(&pdev->dev);
+ int ret;
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p) {
+ dev_err(&pdev->dev, "failed to allocate driver data\n");
+ ret = -ENOMEM;
+ goto err0;
+ }
+
+ p->pdev = pdev;
+ platform_set_drvdata(pdev, p);
+ spin_lock_init(&p->sense_lock);
+
+ io[0] = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ io[1] = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+
+ if (!io[0] || !io[1] || !irq[0] || !irq[1] || !pdata) {
+ dev_err(&pdev->dev, "missing IRQ, IOMEM or configuration\n");
+ ret = -EINVAL;
+ goto err1;
+ }
+
+ p->base0 = ioremap_nocache(io[0]->start, resource_size(io[0]));
+ if (!p->base0) {
+ dev_err(&pdev->dev, "failed to remap low I/O memory\n");
+ ret = -ENXIO;
+ goto err1;
+ }
+
+ p->base1 = ioremap_nocache(io[1]->start, resource_size(io[1]));
+ if (!p->base1) {
+ dev_err(&pdev->dev, "failed to remap high I/O memory\n");
+ ret = -ENXIO;
+ goto err2;
+ }
+
+ gpio_chip = &p->gpio_chip;
+ gpio_chip->direction_input = em_gio_direction_input;
+ gpio_chip->get = em_gio_get;
+ gpio_chip->direction_output = em_gio_direction_output;
+ gpio_chip->set = em_gio_set;
+ gpio_chip->to_irq = em_gio_to_irq;
+ gpio_chip->label = name;
+ gpio_chip->owner = THIS_MODULE;
+ gpio_chip->base = pdata->gpio_base;
+ gpio_chip->ngpio = pdata->number_of_pins;
+
+ irq_chip = &p->irq_chip;
+ irq_chip->name = name;
+ irq_chip->irq_mask = em_gio_irq_disable;
+ irq_chip->irq_unmask = em_gio_irq_enable;
+ irq_chip->irq_enable = em_gio_irq_enable;
+ irq_chip->irq_disable = em_gio_irq_disable;
+ irq_chip->irq_set_type = em_gio_irq_set_type;
+ irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
+
+ ret = em_gio_irq_domain_init(p);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot initialize irq domain\n");
+ goto err3;
+ }
+
+ if (request_irq(irq[0]->start, em_gio_irq_handler, 0, name, p)) {
+ dev_err(&pdev->dev, "failed to request low IRQ\n");
+ ret = -ENOENT;
+ goto err4;
+ }
+
+ if (request_irq(irq[1]->start, em_gio_irq_handler, 0, name, p)) {
+ dev_err(&pdev->dev, "failed to request high IRQ\n");
+ ret = -ENOENT;
+ goto err5;
+ }
+
+ ret = gpiochip_add(gpio_chip);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add GPIO controller\n");
+ goto err6;
+ }
+ return 0;
+
+err6:
+ free_irq(irq[1]->start, pdev);
+err5:
+ free_irq(irq[0]->start, pdev);
+err4:
+ em_gio_irq_domain_cleanup(p);
+err3:
+ iounmap(p->base1);
+err2:
+ iounmap(p->base0);
+err1:
+ kfree(p);
+err0:
+ return ret;
+}
+
+static int __devexit em_gio_remove(struct platform_device *pdev)
+{
+ struct em_gio_priv *p = platform_get_drvdata(pdev);
+ struct resource *irq[2];
+ int ret;
+
+ ret = gpiochip_remove(&p->gpio_chip);
+ if (ret)
+ return ret;
+
+ irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+
+ free_irq(irq[1]->start, pdev);
+ free_irq(irq[0]->start, pdev);
+ em_gio_irq_domain_cleanup(p);
+ iounmap(p->base1);
+ iounmap(p->base0);
+ kfree(p);
+ return 0;
+}
+
+static struct platform_driver em_gio_device_driver = {
+ .probe = em_gio_probe,
+ .remove = __devexit_p(em_gio_remove),
+ .driver = {
+ .name = "em_gio",
+ }
+};
+
+module_platform_driver(em_gio_device_driver);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("Renesas Emma Mobile GIO Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index fc3ace3fd4cb..58a6a63a6ece 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -11,13 +11,17 @@
* 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/clk.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio-pxa.h>
#include <linux/init.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/syscore_ops.h>
#include <linux/slab.h>
@@ -56,6 +60,10 @@
int pxa_last_gpio;
+#ifdef CONFIG_OF
+static struct irq_domain *domain;
+#endif
+
struct pxa_gpio_chip {
struct gpio_chip chip;
void __iomem *regbase;
@@ -81,7 +89,6 @@ enum {
PXA3XX_GPIO,
PXA93X_GPIO,
MMP_GPIO = 0x10,
- MMP2_GPIO,
};
static DEFINE_SPINLOCK(gpio_lock);
@@ -475,22 +482,92 @@ static int pxa_gpio_nums(void)
gpio_type = MMP_GPIO;
} else if (cpu_is_mmp2()) {
count = 191;
- gpio_type = MMP2_GPIO;
+ gpio_type = MMP_GPIO;
}
#endif /* CONFIG_ARCH_MMP */
return count;
}
+static struct of_device_id pxa_gpio_dt_ids[] = {
+ { .compatible = "mrvl,pxa-gpio" },
+ { .compatible = "mrvl,mmp-gpio", .data = (void *)MMP_GPIO },
+ {}
+};
+
+static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+ handle_edge_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ return 0;
+}
+
+const struct irq_domain_ops pxa_irq_domain_ops = {
+ .map = pxa_irq_domain_map,
+};
+
+#ifdef CONFIG_OF
+static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev)
+{
+ int ret, nr_banks, nr_gpios, irq_base;
+ struct device_node *prev, *next, *np = pdev->dev.of_node;
+ const struct of_device_id *of_id =
+ of_match_device(pxa_gpio_dt_ids, &pdev->dev);
+
+ if (!of_id) {
+ dev_err(&pdev->dev, "Failed to find gpio controller\n");
+ return -EFAULT;
+ }
+ gpio_type = (int)of_id->data;
+
+ next = of_get_next_child(np, NULL);
+ prev = next;
+ if (!next) {
+ dev_err(&pdev->dev, "Failed to find child gpio node\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ for (nr_banks = 1; ; nr_banks++) {
+ next = of_get_next_child(np, prev);
+ if (!next)
+ break;
+ prev = next;
+ }
+ of_node_put(prev);
+ nr_gpios = nr_banks << 5;
+ pxa_last_gpio = nr_gpios - 1;
+
+ irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0);
+ if (irq_base < 0) {
+ dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
+ goto err;
+ }
+ domain = irq_domain_add_legacy(np, nr_gpios, irq_base, 0,
+ &pxa_irq_domain_ops, NULL);
+ return 0;
+err:
+ iounmap(gpio_reg_base);
+ return ret;
+}
+#else
+#define pxa_gpio_probe_dt(pdev) (-1)
+#endif
+
static int __devinit pxa_gpio_probe(struct platform_device *pdev)
{
struct pxa_gpio_chip *c;
struct resource *res;
struct clk *clk;
struct pxa_gpio_platform_data *info;
- int gpio, irq, ret;
+ int gpio, irq, ret, use_of = 0;
int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
- pxa_last_gpio = pxa_gpio_nums();
+ ret = pxa_gpio_probe_dt(pdev);
+ if (ret < 0)
+ pxa_last_gpio = pxa_gpio_nums();
+ else
+ use_of = 1;
if (!pxa_last_gpio)
return -EINVAL;
@@ -545,25 +622,27 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev)
writel_relaxed(~0, c->regbase + ED_MASK_OFFSET);
}
+ if (!use_of) {
#ifdef CONFIG_ARCH_PXA
- irq = gpio_to_irq(0);
- irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
- handle_edge_irq);
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
- irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler);
-
- irq = gpio_to_irq(1);
- irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
- handle_edge_irq);
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
- irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler);
-#endif
+ irq = gpio_to_irq(0);
+ irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+ handle_edge_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler);
- for (irq = gpio_to_irq(gpio_offset);
- irq <= gpio_to_irq(pxa_last_gpio); irq++) {
+ irq = gpio_to_irq(1);
irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler);
+#endif
+
+ for (irq = gpio_to_irq(gpio_offset);
+ irq <= gpio_to_irq(pxa_last_gpio); irq++) {
+ irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+ handle_edge_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
}
irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler);
@@ -574,6 +653,7 @@ static struct platform_driver pxa_gpio_driver = {
.probe = pxa_gpio_probe,
.driver = {
.name = "pxa-gpio",
+ .of_match_table = pxa_gpio_dt_ids,
},
};
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 12f349b3830d..dc5184d57892 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -26,10 +26,10 @@
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/irqdomain.h>
+#include <linux/pinctrl/consumer.h>
#include <asm/mach/irq.h>
-#include <mach/gpio-tegra.h>
#include <mach/iomap.h>
#include <mach/suspend.h>
@@ -108,18 +108,29 @@ static void tegra_gpio_mask_write(u32 reg, int gpio, int value)
tegra_gpio_writel(val, reg);
}
-void tegra_gpio_enable(int gpio)
+static void tegra_gpio_enable(int gpio)
{
tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
}
EXPORT_SYMBOL_GPL(tegra_gpio_enable);
-void tegra_gpio_disable(int gpio)
+static void tegra_gpio_disable(int gpio)
{
tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
}
EXPORT_SYMBOL_GPL(tegra_gpio_disable);
+int tegra_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ return pinctrl_request_gpio(offset);
+}
+
+void tegra_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ pinctrl_free_gpio(offset);
+ tegra_gpio_disable(offset);
+}
+
static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
tegra_gpio_mask_write(GPIO_MSK_OUT(offset), offset, value);
@@ -133,6 +144,7 @@ static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 0);
+ tegra_gpio_enable(offset);
return 0;
}
@@ -141,6 +153,7 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
{
tegra_gpio_set(chip, offset, value);
tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 1);
+ tegra_gpio_enable(offset);
return 0;
}
@@ -151,13 +164,14 @@ static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
static struct gpio_chip tegra_gpio_chip = {
.label = "tegra-gpio",
+ .request = tegra_gpio_request,
+ .free = tegra_gpio_free,
.direction_input = tegra_gpio_direction_input,
.get = tegra_gpio_get,
.direction_output = tegra_gpio_direction_output,
.set = tegra_gpio_set,
.to_irq = tegra_gpio_to_irq,
.base = 0,
- .ngpio = TEGRA_NR_GPIOS,
};
static void tegra_gpio_irq_ack(struct irq_data *d)
@@ -224,6 +238,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
+ tegra_gpio_mask_write(GPIO_MSK_OE(gpio), gpio, 0);
+ tegra_gpio_enable(gpio);
+
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
__irq_set_handler_locked(d->irq, handle_level_irq);
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
@@ -490,20 +507,6 @@ static int __init tegra_gpio_init(void)
}
postcore_initcall(tegra_gpio_init);
-void tegra_gpio_config(struct tegra_gpio_table *table, int num)
-{
- int i;
-
- for (i = 0; i < num; i++) {
- int gpio = table[i].gpio;
-
- if (table[i].enable)
- tegra_gpio_enable(gpio);
- else
- tegra_gpio_disable(gpio);
- }
-}
-
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index 0ebb7d4796fa..ef67e181377b 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -1827,14 +1827,10 @@ void radeon_do_release(struct drm_device * dev)
r600_do_cleanup_cp(dev);
else
radeon_do_cleanup_cp(dev);
- if (dev_priv->me_fw) {
- release_firmware(dev_priv->me_fw);
- dev_priv->me_fw = NULL;
- }
- if (dev_priv->pfp_fw) {
- release_firmware(dev_priv->pfp_fw);
- dev_priv->pfp_fw = NULL;
- }
+ release_firmware(dev_priv->me_fw);
+ dev_priv->me_fw = NULL;
+ release_firmware(dev_priv->pfp_fw);
+ dev_priv->pfp_fw = NULL;
}
}
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
index c58a036233fb..456a77cf4b7f 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -551,7 +551,7 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
/* nothing to do if vm isn't bound */
if (vm->id == -1)
- return 0;;
+ return 0;
bo_va = radeon_bo_va(bo, vm);
if (bo_va == NULL) {
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index c7008b5210f7..0519b05968b5 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -91,7 +91,7 @@ int radeon_gem_set_domain(struct drm_gem_object *gobj,
}
if (!domain) {
/* Do nothings */
- printk(KERN_WARNING "Set domain withou domain !\n");
+ printk(KERN_WARNING "Set domain without domain !\n");
return 0;
}
if (domain == RADEON_GEM_DOMAIN_CPU) {
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index ffddcba32af6..034c80a10f1f 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -32,9 +32,13 @@ config HID
If unsure, say Y.
config HID_BATTERY_STRENGTH
- bool
+ bool "Battery level reporting for HID devices"
depends on HID && POWER_SUPPLY && HID = POWER_SUPPLY
default n
+ ---help---
+ This option adds support of reporting battery strength (for HID devices
+ that support this feature) through power_supply class so that userspace
+ tools, such as upower, can display it.
config HIDRAW
bool "/dev/hidraw raw HID device support"
@@ -60,6 +64,18 @@ source "drivers/hid/usbhid/Kconfig"
menu "Special HID drivers"
depends on HID
+config HID_GENERIC
+ tristate "Generic HID driver"
+ depends on HID
+ default y
+ ---help---
+ Support for generic HID devices.
+
+ To compile this driver as a module, choose M here: the module
+ will be called hid-generic.
+
+ If unsure, say Y.
+
config HID_A4TECH
tristate "A4 tech mice" if EXPERT
depends on USB_HID
@@ -92,6 +108,12 @@ config HID_APPLE
Say Y here if you want support for keyboards of Apple iBooks, PowerBooks,
MacBooks, MacBook Pros and Apple Aluminum.
+config HID_AUREAL
+ tristate "Aureal"
+ depends on USB_HID
+ ---help---
+ Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes.
+
config HID_BELKIN
tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT
depends on USB_HID
@@ -448,7 +470,7 @@ config HID_PICOLCD_FB
select FB_SYS_FOPS
---help---
Provide access to PicoLCD's 256x64 monochrome display via a
- frambuffer device.
+ framebuffer device.
config HID_PICOLCD_BACKLIGHT
bool "Backlight control" if EXPERT
@@ -595,16 +617,10 @@ config THRUSTMASTER_FF
config HID_WACOM
tristate "Wacom Bluetooth devices support"
depends on BT_HIDP
- ---help---
- Support for Wacom Graphire Bluetooth tablet.
-
-config HID_WACOM_POWER_SUPPLY
- bool "Wacom Bluetooth devices power supply status support"
- depends on HID_WACOM
+ depends on LEDS_CLASS
select POWER_SUPPLY
---help---
- Say Y here if you want to enable power supply status monitoring for
- Wacom Bluetooth devices.
+ Support for Wacom Graphire Bluetooth and Intuos4 WL tablets.
config HID_WIIMOTE
tristate "Nintendo Wii Remote support"
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 22f1d16cd79c..ca6cc9f0485c 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -9,6 +9,8 @@ endif
obj-$(CONFIG_HID) += hid.o
+obj-$(CONFIG_HID_GENERIC) += hid-generic.o
+
hid-$(CONFIG_HIDRAW) += hidraw.o
hid-logitech-y := hid-lg.o
@@ -36,6 +38,7 @@ endif
obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
obj-$(CONFIG_HID_ACRUX) += hid-axff.o
obj-$(CONFIG_HID_APPLE) += hid-apple.o
+obj-$(CONFIG_HID_AUREAL) += hid-aureal.o
obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index 299d23871122..fa10f847f7db 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -234,7 +234,7 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
}
}
- if (iso_layout) {
+ if (iso_layout) {
if (asc->quirks & APPLE_ISO_KEYBOARD) {
trans = apple_find_translation(apple_iso_keyboard, usage->code);
if (trans) {
@@ -458,6 +458,9 @@ static const struct hid_device_id apple_devices[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
APPLE_ISO_KEYBOARD },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
diff --git a/drivers/hid/hid-aureal.c b/drivers/hid/hid-aureal.c
new file mode 100644
index 000000000000..ba64b041b8bf
--- /dev/null
+++ b/drivers/hid/hid-aureal.c
@@ -0,0 +1,54 @@
+/*
+ * HID driver for Aureal Cy se W-01RN USB_V3.1 devices
+ *
+ * Copyright (c) 2010 Franco Catrin <fcatrin@gmail.com>
+ * Copyright (c) 2010 Ben Cropley <bcropley@internode.on.net>
+ *
+ * Based on HID sunplus driver by
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static __u8 *aureal_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int *rsize)
+{
+ if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) {
+ dev_info(&hdev->dev, "fixing Aureal Cy se W-01RN USB_V3.1 report descriptor.\n");
+ rdesc[53] = 0x65;
+ } return rdesc;
+}
+
+static const struct hid_device_id aureal_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, aureal_devices);
+
+static struct hid_driver aureal_driver = {
+ .name = "aureal",
+ .id_table = aureal_devices,
+ .report_fixup = aureal_report_fixup,
+};
+
+static int __init aureal_init(void)
+{
+ return hid_register_driver(&aureal_driver);
+}
+
+static void __exit aureal_exit(void)
+{
+ hid_unregister_driver(&aureal_driver);
+}
+
+module_init(aureal_init);
+module_exit(aureal_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 4da66b4b977c..8e3a6b261477 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -230,9 +230,16 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
return -1;
}
- if (parser->global.logical_maximum < parser->global.logical_minimum) {
- hid_err(parser->device, "logical range invalid %d %d\n",
- parser->global.logical_minimum, parser->global.logical_maximum);
+ /* Handle both signed and unsigned cases properly */
+ if ((parser->global.logical_minimum < 0 &&
+ parser->global.logical_maximum <
+ parser->global.logical_minimum) ||
+ (parser->global.logical_minimum >= 0 &&
+ (__u32)parser->global.logical_maximum <
+ (__u32)parser->global.logical_minimum)) {
+ dbg_hid("logical range invalid 0x%x 0x%x\n",
+ parser->global.logical_minimum,
+ parser->global.logical_maximum);
return -1;
}
@@ -546,12 +553,11 @@ static void hid_free_report(struct hid_report *report)
}
/*
- * Free a device structure, all reports, and all fields.
+ * Close report. This function returns the device
+ * state to the point prior to hid_open_report().
*/
-
-static void hid_device_release(struct device *dev)
+static void hid_close_report(struct hid_device *device)
{
- struct hid_device *device = container_of(dev, struct hid_device, dev);
unsigned i, j;
for (i = 0; i < HID_REPORT_TYPES; i++) {
@@ -562,11 +568,34 @@ static void hid_device_release(struct device *dev)
if (report)
hid_free_report(report);
}
+ memset(report_enum, 0, sizeof(*report_enum));
+ INIT_LIST_HEAD(&report_enum->report_list);
}
kfree(device->rdesc);
+ device->rdesc = NULL;
+ device->rsize = 0;
+
kfree(device->collection);
- kfree(device);
+ device->collection = NULL;
+ device->collection_size = 0;
+ device->maxcollection = 0;
+ device->maxapplication = 0;
+
+ device->status &= ~HID_STAT_PARSED;
+}
+
+/*
+ * Free a device structure, all reports, and all fields.
+ */
+
+static void hid_device_release(struct device *dev)
+{
+ struct hid_device *hid = container_of(dev, struct hid_device, dev);
+
+ hid_close_report(hid);
+ kfree(hid->dev_rdesc);
+ kfree(hid);
}
/*
@@ -636,6 +665,60 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
return NULL;
}
+static void hid_scan_usage(struct hid_device *hid, u32 usage)
+{
+ if (usage == HID_DG_CONTACTID)
+ hid->group = HID_GROUP_MULTITOUCH;
+}
+
+/*
+ * Scan a report descriptor before the device is added to the bus.
+ * Sets device groups and other properties that determine what driver
+ * to load.
+ */
+static int hid_scan_report(struct hid_device *hid)
+{
+ unsigned int page = 0, delim = 0;
+ __u8 *start = hid->dev_rdesc;
+ __u8 *end = start + hid->dev_rsize;
+ unsigned int u, u_min = 0, u_max = 0;
+ struct hid_item item;
+
+ hid->group = HID_GROUP_GENERIC;
+ while ((start = fetch_item(start, end, &item)) != NULL) {
+ if (item.format != HID_ITEM_FORMAT_SHORT)
+ return -EINVAL;
+ if (item.type == HID_ITEM_TYPE_GLOBAL) {
+ if (item.tag == HID_GLOBAL_ITEM_TAG_USAGE_PAGE)
+ page = item_udata(&item) << 16;
+ } else if (item.type == HID_ITEM_TYPE_LOCAL) {
+ if (delim > 1)
+ break;
+ u = item_udata(&item);
+ if (item.size <= 2)
+ u += page;
+ switch (item.tag) {
+ case HID_LOCAL_ITEM_TAG_DELIMITER:
+ delim += !!u;
+ break;
+ case HID_LOCAL_ITEM_TAG_USAGE:
+ hid_scan_usage(hid, u);
+ break;
+ case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
+ u_min = u;
+ break;
+ case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
+ u_max = u;
+ for (u = u_min; u <= u_max; u++)
+ hid_scan_usage(hid, u);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
/**
* hid_parse_report - parse device report
*
@@ -643,15 +726,37 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
* @start: report start
* @size: report size
*
+ * Allocate the device report as read by the bus driver. This function should
+ * only be called from parse() in ll drivers.
+ */
+int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size)
+{
+ hid->dev_rdesc = kmemdup(start, size, GFP_KERNEL);
+ if (!hid->dev_rdesc)
+ return -ENOMEM;
+ hid->dev_rsize = size;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hid_parse_report);
+
+/**
+ * hid_open_report - open a driver-specific device report
+ *
+ * @device: hid device
+ *
* Parse a report description into a hid_device structure. Reports are
* enumerated, fields are attached to these reports.
* 0 returned on success, otherwise nonzero error value.
+ *
+ * This function (or the equivalent hid_parse() macro) should only be
+ * called from probe() in drivers, before starting the device.
*/
-int hid_parse_report(struct hid_device *device, __u8 *start,
- unsigned size)
+int hid_open_report(struct hid_device *device)
{
struct hid_parser *parser;
struct hid_item item;
+ unsigned int size;
+ __u8 *start;
__u8 *end;
int ret;
static int (*dispatch_type[])(struct hid_parser *parser,
@@ -662,6 +767,14 @@ int hid_parse_report(struct hid_device *device, __u8 *start,
hid_parser_reserved
};
+ if (WARN_ON(device->status & HID_STAT_PARSED))
+ return -EBUSY;
+
+ start = device->dev_rdesc;
+ if (WARN_ON(!start))
+ return -ENODEV;
+ size = device->dev_rsize;
+
if (device->driver->report_fixup)
start = device->driver->report_fixup(device, start, &size);
@@ -679,6 +792,15 @@ int hid_parse_report(struct hid_device *device, __u8 *start,
parser->device = device;
end = start + size;
+
+ device->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS,
+ sizeof(struct hid_collection), GFP_KERNEL);
+ if (!device->collection) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
+
ret = -EINVAL;
while ((start = fetch_item(start, end, &item)) != NULL) {
@@ -704,6 +826,7 @@ int hid_parse_report(struct hid_device *device, __u8 *start,
goto err;
}
vfree(parser);
+ device->status |= HID_STAT_PARSED;
return 0;
}
}
@@ -711,9 +834,10 @@ int hid_parse_report(struct hid_device *device, __u8 *start,
hid_err(device, "item fetching failed at offset %d\n", (int)(end - start));
err:
vfree(parser);
+ hid_close_report(device);
return ret;
}
-EXPORT_SYMBOL_GPL(hid_parse_report);
+EXPORT_SYMBOL_GPL(hid_open_report);
/*
* Convert a signed n-bit integer to signed 32-bit integer. Common
@@ -1032,7 +1156,7 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum,
return report;
}
-void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
+int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
int interrupt)
{
struct hid_report_enum *report_enum = hid->report_enum + type;
@@ -1040,10 +1164,11 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
unsigned int a;
int rsize, csize = size;
u8 *cdata = data;
+ int ret = 0;
report = hid_get_report(report_enum, data);
if (!report)
- return;
+ goto out;
if (report_enum->numbered) {
cdata++;
@@ -1063,14 +1188,19 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
hid->hiddev_report_event(hid, report);
- if (hid->claimed & HID_CLAIMED_HIDRAW)
- hidraw_report_event(hid, data, size);
+ if (hid->claimed & HID_CLAIMED_HIDRAW) {
+ ret = hidraw_report_event(hid, data, size);
+ if (ret)
+ goto out;
+ }
for (a = 0; a < report->maxfield; a++)
hid_input_field(hid, report->field[a], cdata, interrupt);
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_report_event(hid, report);
+out:
+ return ret;
}
EXPORT_SYMBOL_GPL(hid_report_raw_event);
@@ -1147,7 +1277,7 @@ nomem:
}
}
- hid_report_raw_event(hid, type, data, size, interrupt);
+ ret = hid_report_raw_event(hid, type, data, size, interrupt);
unlock:
up(&hid->driver_lock);
@@ -1158,7 +1288,8 @@ EXPORT_SYMBOL_GPL(hid_input_report);
static bool hid_match_one_id(struct hid_device *hdev,
const struct hid_device_id *id)
{
- return id->bus == hdev->bus &&
+ return (id->bus == HID_BUS_ANY || id->bus == hdev->bus) &&
+ (id->group == HID_GROUP_ANY || id->group == hdev->group) &&
(id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) &&
(id->product == HID_ANY_ID || id->product == hdev->product);
}
@@ -1234,10 +1365,6 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev,
connect_mask & HID_CONNECT_HIDINPUT_FORCE))
hdev->claimed |= HID_CLAIMED_INPUT;
- if (hdev->quirks & HID_QUIRK_MULTITOUCH) {
- /* this device should be handled by hid-multitouch, skip it */
- return -ENODEV;
- }
if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect &&
!hdev->hiddev_connect(hdev,
@@ -1314,13 +1441,10 @@ EXPORT_SYMBOL_GPL(hid_disconnect);
/* a list of devices for which there is a specialized driver on HID bus */
static const struct hid_device_id hid_have_special_driver[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) },
- { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, USB_DEVICE_ID_ACTIONSTAR_1011) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
@@ -1385,60 +1509,33 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
- { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
- { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
- { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
- { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
- { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
- { HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
- { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) },
{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_FRUCTEL, USB_DEVICE_ID_GAMETEL_MT_MODE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, USB_DEVICE_ID_GOODTOUCH_000f) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
- { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
- { HID_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT, USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
- { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) },
- { HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
@@ -1447,7 +1544,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MULTITOUCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
@@ -1480,8 +1576,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH_DUAL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
@@ -1513,15 +1607,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
- { HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC, USB_DEVICE_ID_PANABOARD_UBT780) },
- { HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC, USB_DEVICE_ID_PANABOARD_UBT880) },
- { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) },
- { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) },
- { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
- { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
@@ -1538,9 +1625,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
- { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) },
- { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
@@ -1554,16 +1638,13 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) },
- { HID_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL, USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
- { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
- { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
@@ -1578,16 +1659,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_PID_0038) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
- { HID_USB_DEVICE(USB_VENDOR_ID_XAT, USB_DEVICE_ID_XAT_CSR) },
- { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX) },
- { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX) },
- { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR) },
- { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX1) },
- { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX1) },
- { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR1) },
- { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX2) },
- { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX2) },
- { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) },
{ HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
@@ -1631,6 +1703,7 @@ static ssize_t store_new_id(struct device_driver *drv, const char *buf,
return -ENOMEM;
dynid->id.bus = bus;
+ dynid->id.group = HID_GROUP_ANY;
dynid->id.vendor = vendor;
dynid->id.product = product;
dynid->id.driver_data = driver_data;
@@ -1679,18 +1752,7 @@ static int hid_bus_match(struct device *dev, struct device_driver *drv)
struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- if ((hdev->quirks & HID_QUIRK_MULTITOUCH) &&
- !strncmp(hdrv->name, "hid-multitouch", 14))
- return 1;
-
- if (!hid_match_device(hdev, hdrv))
- return 0;
-
- /* generic wants all that don't have specialized driver */
- if (!strncmp(hdrv->name, "generic-", 8) && !hid_ignore_special_drivers)
- return !hid_match_id(hdev, hid_have_special_driver);
-
- return 1;
+ return hid_match_device(hdev, hdrv) != NULL;
}
static int hid_device_probe(struct device *dev)
@@ -1707,23 +1769,22 @@ static int hid_device_probe(struct device *dev)
if (!hdev->driver) {
id = hid_match_device(hdev, hdrv);
if (id == NULL) {
- if (!((hdev->quirks & HID_QUIRK_MULTITOUCH) &&
- !strncmp(hdrv->name, "hid-multitouch", 14))) {
- ret = -ENODEV;
- goto unlock;
- }
+ ret = -ENODEV;
+ goto unlock;
}
hdev->driver = hdrv;
if (hdrv->probe) {
ret = hdrv->probe(hdev, id);
} else { /* default probe */
- ret = hid_parse(hdev);
+ ret = hid_open_report(hdev);
if (!ret)
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
}
- if (ret)
+ if (ret) {
+ hid_close_report(hdev);
hdev->driver = NULL;
+ }
}
unlock:
up(&hdev->driver_lock);
@@ -1744,6 +1805,7 @@ static int hid_device_remove(struct device *dev)
hdrv->remove(hdev);
else /* default remove */
hid_hw_stop(hdev);
+ hid_close_report(hdev);
hdev->driver = NULL;
}
@@ -1751,6 +1813,23 @@ static int hid_device_remove(struct device *dev)
return 0;
}
+static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
+ char *buf)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ int len;
+
+ len = snprintf(buf, PAGE_SIZE, "hid:b%04Xg%04Xv%08Xp%08X\n",
+ hdev->bus, hdev->group, hdev->vendor, hdev->product);
+
+ return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+
+static struct device_attribute hid_dev_attrs[] = {
+ __ATTR_RO(modalias),
+ __ATTR_NULL,
+};
+
static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
@@ -1768,8 +1847,8 @@ static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
if (add_uevent_var(env, "HID_UNIQ=%s", hdev->uniq))
return -ENOMEM;
- if (add_uevent_var(env, "MODALIAS=hid:b%04Xv%08Xp%08X",
- hdev->bus, hdev->vendor, hdev->product))
+ if (add_uevent_var(env, "MODALIAS=hid:b%04Xg%04Xv%08Xp%08X",
+ hdev->bus, hdev->group, hdev->vendor, hdev->product))
return -ENOMEM;
return 0;
@@ -1777,6 +1856,7 @@ static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
static struct bus_type hid_bus_type = {
.name = "hid",
+ .dev_attrs = hid_dev_attrs,
.match = hid_bus_match,
.probe = hid_device_probe,
.remove = hid_device_remove,
@@ -2075,6 +2155,26 @@ int hid_add_device(struct hid_device *hdev)
&& (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE)))
return -ENODEV;
+ /*
+ * Read the device report descriptor once and use as template
+ * for the driver-specific modifications.
+ */
+ ret = hdev->ll_driver->parse(hdev);
+ if (ret)
+ return ret;
+ if (!hdev->dev_rdesc)
+ return -ENODEV;
+
+ /*
+ * Scan generic devices for group information
+ */
+ if (hid_ignore_special_drivers ||
+ !hid_match_id(hdev, hid_have_special_driver)) {
+ ret = hid_scan_report(hdev);
+ if (ret)
+ hid_warn(hdev, "bad device descriptor (%d)\n", ret);
+ }
+
/* XXX hack, any other cleaner solution after the driver core
* is converted to allow more than 20 bytes as the device name? */
dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
@@ -2103,7 +2203,6 @@ EXPORT_SYMBOL_GPL(hid_add_device);
struct hid_device *hid_allocate_device(void)
{
struct hid_device *hdev;
- unsigned int i;
int ret = -ENOMEM;
hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
@@ -2114,23 +2213,13 @@ struct hid_device *hid_allocate_device(void)
hdev->dev.release = hid_device_release;
hdev->dev.bus = &hid_bus_type;
- hdev->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS,
- sizeof(struct hid_collection), GFP_KERNEL);
- if (hdev->collection == NULL)
- goto err;
- hdev->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
-
- for (i = 0; i < HID_REPORT_TYPES; i++)
- INIT_LIST_HEAD(&hdev->report_enum[i].report_list);
+ hid_close_report(hdev);
init_waitqueue_head(&hdev->debug_wait);
INIT_LIST_HEAD(&hdev->debug_list);
sema_init(&hdev->driver_lock, 1);
return hdev;
-err:
- put_device(&hdev->dev);
- return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(hid_allocate_device);
@@ -2141,6 +2230,9 @@ static void hid_remove_device(struct hid_device *hdev)
hid_debug_unregister(hdev);
hdev->status &= ~HID_STAT_ADDED;
}
+ kfree(hdev->dev_rdesc);
+ hdev->dev_rdesc = NULL;
+ hdev->dev_rsize = 0;
}
/**
diff --git a/drivers/hid/hid-generic.c b/drivers/hid/hid-generic.c
new file mode 100644
index 000000000000..a8b3148e03a2
--- /dev/null
+++ b/drivers/hid/hid-generic.c
@@ -0,0 +1,53 @@
+/*
+ * HID support for Linux
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2007-2008 Oliver Neukum
+ * Copyright (c) 2006-2012 Jiri Kosina
+ * Copyright (c) 2012 Henrik Rydberg
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+
+#include <linux/hid.h>
+
+static const struct hid_device_id hid_table[] = {
+ { HID_DEVICE(HID_BUS_ANY, HID_GROUP_GENERIC, HID_ANY_ID, HID_ANY_ID) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, hid_table);
+
+static struct hid_driver hid_generic = {
+ .name = "hid-generic",
+ .id_table = hid_table,
+};
+
+static int __init hid_init(void)
+{
+ return hid_register_driver(&hid_generic);
+}
+
+static void __exit hid_exit(void)
+{
+ hid_unregister_driver(&hid_generic);
+}
+
+module_init(hid_init);
+module_exit(hid_exit);
+
+MODULE_AUTHOR("Henrik Rydberg");
+MODULE_DESCRIPTION("HID generic driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
index 406632472c1b..3d62781b8993 100644
--- a/drivers/hid/hid-hyperv.c
+++ b/drivers/hid/hid-hyperv.c
@@ -430,6 +430,15 @@ cleanup:
return ret;
}
+static int mousevsc_hid_parse(struct hid_device *hid)
+{
+ struct hv_device *dev = hid_get_drvdata(hid);
+ struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
+
+ return hid_parse_report(hid, input_dev->report_desc,
+ input_dev->report_desc_size);
+}
+
static int mousevsc_hid_open(struct hid_device *hid)
{
return 0;
@@ -449,6 +458,7 @@ static void mousevsc_hid_stop(struct hid_device *hid)
}
static struct hid_ll_driver mousevsc_ll_driver = {
+ .parse = mousevsc_hid_parse,
.open = mousevsc_hid_open,
.close = mousevsc_hid_close,
.start = mousevsc_hid_start,
@@ -506,13 +516,14 @@ static int mousevsc_probe(struct hv_device *device,
sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse");
+ hid_set_drvdata(hid_dev, device);
+
ret = hid_add_device(hid_dev);
if (ret)
goto probe_err1;
- ret = hid_parse_report(hid_dev, input_dev->report_desc,
- input_dev->report_desc_size);
+ ret = hid_parse(hid_dev);
if (ret) {
hid_err(hid_dev, "parse failed\n");
goto probe_err2;
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index e39aecb1f9f2..9373f535dfe9 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -154,9 +154,15 @@
#define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c
#define USB_DEVICE_ID_ATMEL_MXT_DIGITIZER 0x2118
+#define USB_VENDOR_ID_AUREAL 0x0755
+#define USB_DEVICE_ID_AUREAL_W01RN 0x2626
+
#define USB_VENDOR_ID_AVERMEDIA 0x07ca
#define USB_DEVICE_ID_AVER_FM_MR800 0xb800
+#define USB_VENDOR_ID_BAANTO 0x2453
+#define USB_DEVICE_ID_BAANTO_MT_190W2 0x0100
+
#define USB_VENDOR_ID_BELKIN 0x050d
#define USB_DEVICE_ID_FLIP_KVM 0x3201
@@ -726,6 +732,7 @@
#define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004
#define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005
#define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064
+#define USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850 0x0522
#define USB_VENDOR_ID_UNITEC 0x227d
#define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709
@@ -749,6 +756,7 @@
#define USB_DEVICE_ID_WALTOP_PID_0038 0x0038
#define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH 0x0501
#define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH 0x0500
+#define USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET 0x0502
#define USB_VENDOR_ID_WISEGROUP 0x0925
#define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 002781c5a616..132b0019365e 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -225,7 +225,10 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
* Verify and convert units.
* See HID specification v1.11 6.2.2.7 Global Items for unit decoding
*/
- if (code == ABS_X || code == ABS_Y || code == ABS_Z) {
+ switch (code) {
+ case ABS_X:
+ case ABS_Y:
+ case ABS_Z:
if (field->unit == 0x11) { /* If centimeters */
/* Convert to millimeters */
unit_exponent += 1;
@@ -239,7 +242,13 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
} else {
return 0;
}
- } else if (code == ABS_RX || code == ABS_RY || code == ABS_RZ) {
+ break;
+
+ case ABS_RX:
+ case ABS_RY:
+ case ABS_RZ:
+ case ABS_TILT_X:
+ case ABS_TILT_Y:
if (field->unit == 0x14) { /* If degrees */
/* Convert to radians */
prev = logical_extents;
@@ -250,7 +259,9 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
} else if (field->unit != 0x12) { /* If not radians */
return 0;
}
- } else {
+ break;
+
+ default:
return 0;
}
@@ -623,6 +634,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
map_key_clear(BTN_TOOL_RUBBER);
break;
+ case 0x3d: /* X Tilt */
+ map_abs_clear(ABS_TILT_X);
+ break;
+
+ case 0x3e: /* Y Tilt */
+ map_abs_clear(ABS_TILT_Y);
+ break;
+
case 0x33: /* Touch */
case 0x42: /* TipSwitch */
case 0x43: /* TipSwitch2 */
@@ -638,10 +657,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
map_key_clear(BTN_STYLUS2);
break;
- case 0x51: /* ContactID */
- device->quirks |= HID_QUIRK_MULTITOUCH;
- goto unknown;
-
default: goto unknown;
}
break;
@@ -1208,13 +1223,6 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
}
}
- if (hid->quirks & HID_QUIRK_MULTITOUCH) {
- /* generic hid does not know how to handle multitouch devices */
- if (hidinput)
- goto out_cleanup;
- goto out_unwind;
- }
-
if (hidinput && input_register_device(hidinput->input))
goto out_cleanup;
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index e7a7bd1eb34a..fc37ed6b108c 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -109,23 +109,23 @@ static __u8 dfp_rdesc_fixed[] = {
static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
- unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+ struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
- if ((quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
+ if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
rdesc[84] == 0x8c && rdesc[85] == 0x02) {
hid_info(hdev,
"fixing up Logitech keyboard report descriptor\n");
rdesc[84] = rdesc[89] = 0x4d;
rdesc[85] = rdesc[90] = 0x10;
}
- if ((quirks & LG_RDESC_REL_ABS) && *rsize >= 50 &&
+ if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 50 &&
rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
rdesc[49] == 0x81 && rdesc[50] == 0x06) {
hid_info(hdev,
"fixing up rel/abs in Logitech report descriptor\n");
rdesc[33] = rdesc[50] = 0x02;
}
- if ((quirks & LG_FF4) && *rsize >= 101 &&
+ if ((drv_data->quirks & LG_FF4) && *rsize >= 101 &&
rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
rdesc[47] == 0x05 && rdesc[48] == 0x09) {
hid_info(hdev, "fixing up Logitech Speed Force Wireless button descriptor\n");
@@ -278,7 +278,7 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
0, 0, 0, 0, 0,183,184,185,186,187,
188,189,190,191,192,193,194, 0, 0, 0
};
- unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+ struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
unsigned int hid = usage->hid;
if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER &&
@@ -289,7 +289,7 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
lg_dinovo_mapping(hi, usage, bit, max))
return 1;
- if ((quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
+ if ((drv_data->quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
return 1;
if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
@@ -299,11 +299,11 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
/* Special handling for Logitech Cordless Desktop */
if (field->application == HID_GD_MOUSE) {
- if ((quirks & LG_IGNORE_DOUBLED_WHEEL) &&
+ if ((drv_data->quirks & LG_IGNORE_DOUBLED_WHEEL) &&
(hid == 7 || hid == 8))
return -1;
} else {
- if ((quirks & LG_EXPANDED_KEYMAP) &&
+ if ((drv_data->quirks & LG_EXPANDED_KEYMAP) &&
hid < ARRAY_SIZE(e_keymap) &&
e_keymap[hid] != 0) {
hid_map_usage(hi, usage, bit, max, EV_KEY,
@@ -319,13 +319,13 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
- unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+ struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
- if ((quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
+ if ((drv_data->quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
(field->flags & HID_MAIN_ITEM_RELATIVE))
field->flags &= ~HID_MAIN_ITEM_RELATIVE;
- if ((quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY ||
+ if ((drv_data->quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY ||
usage->type == EV_REL || usage->type == EV_ABS))
clear_bit(usage->code, *bit);
@@ -335,9 +335,9 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
static int lg_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
- unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+ struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
- if ((quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
+ if ((drv_data->quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
input_event(field->hidinput->input, usage->type, usage->code,
-value);
return 1;
@@ -348,13 +348,20 @@ static int lg_event(struct hid_device *hdev, struct hid_field *field,
static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
- unsigned long quirks = id->driver_data;
unsigned int connect_mask = HID_CONNECT_DEFAULT;
+ struct lg_drv_data *drv_data;
int ret;
- hid_set_drvdata(hdev, (void *)quirks);
+ drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
+ if (!drv_data) {
+ hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
+ return -ENOMEM;
+ }
+ drv_data->quirks = id->driver_data;
+
+ hid_set_drvdata(hdev, (void *)drv_data);
- if (quirks & LG_NOGET)
+ if (drv_data->quirks & LG_NOGET)
hdev->quirks |= HID_QUIRK_NOGET;
ret = hid_parse(hdev);
@@ -363,7 +370,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto err_free;
}
- if (quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
+ if (drv_data->quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
connect_mask &= ~HID_CONNECT_FF;
ret = hid_hw_start(hdev, connect_mask);
@@ -392,27 +399,29 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
}
}
- if (quirks & LG_FF)
+ if (drv_data->quirks & LG_FF)
lgff_init(hdev);
- if (quirks & LG_FF2)
+ if (drv_data->quirks & LG_FF2)
lg2ff_init(hdev);
- if (quirks & LG_FF3)
+ if (drv_data->quirks & LG_FF3)
lg3ff_init(hdev);
- if (quirks & LG_FF4)
+ if (drv_data->quirks & LG_FF4)
lg4ff_init(hdev);
return 0;
err_free:
+ kfree(drv_data);
return ret;
}
static void lg_remove(struct hid_device *hdev)
{
- unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
- if(quirks & LG_FF4)
+ struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
+ if (drv_data->quirks & LG_FF4)
lg4ff_deinit(hdev);
hid_hw_stop(hdev);
+ kfree(drv_data);
}
static const struct hid_device_id lg_devices[] = {
diff --git a/drivers/hid/hid-lg.h b/drivers/hid/hid-lg.h
index 4b097286dc78..d64cf8d2751e 100644
--- a/drivers/hid/hid-lg.h
+++ b/drivers/hid/hid-lg.h
@@ -1,6 +1,11 @@
#ifndef __HID_LG_H
#define __HID_LG_H
+struct lg_drv_data {
+ unsigned long quirks;
+ void *device_props; /* Device specific properties */
+};
+
#ifdef CONFIG_LOGITECH_FF
int lgff_init(struct hid_device *hdev);
#else
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 6ecc9e220440..f3390ee6105c 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -1,7 +1,8 @@
/*
- * Force feedback support for Logitech Speed Force Wireless
+ * Force feedback support for Logitech Gaming Wheels
*
- * http://wiibrew.org/wiki/Logitech_USB_steering_wheel
+ * Including G27, G25, DFP, DFGT, FFEX, Momo, Momo2 &
+ * Speed Force Wireless (WiiWheel)
*
* Copyright (c) 2010 Simon Wood <simon@mungewell.org>
*/
@@ -51,20 +52,18 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
static DEVICE_ATTR(range, S_IRWXU | S_IRWXG | S_IRWXO, lg4ff_range_show, lg4ff_range_store);
-static bool list_inited;
-
struct lg4ff_device_entry {
- char *device_id; /* Use name in respective kobject structure's address as the ID */
__u16 range;
__u16 min_range;
__u16 max_range;
- __u8 leds;
+#ifdef CONFIG_LEDS_CLASS
+ __u8 led_state;
+ struct led_classdev *led[5];
+#endif
struct list_head list;
void (*set_range)(struct hid_device *hid, u16 range);
};
-static struct lg4ff_device_entry device_list;
-
static const signed short lg4ff_wheel_effects[] = {
FF_CONSTANT,
FF_AUTOCENTER,
@@ -285,18 +284,20 @@ static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_n
/* Read current range and display it in terminal */
static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct lg4ff_device_entry *uninitialized_var(entry);
- struct list_head *h;
struct hid_device *hid = to_hid_device(dev);
+ struct lg4ff_device_entry *entry;
+ struct lg_drv_data *drv_data;
size_t count;
- list_for_each(h, &device_list.list) {
- entry = list_entry(h, struct lg4ff_device_entry, list);
- if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0)
- break;
+ drv_data = hid_get_drvdata(hid);
+ if (!drv_data) {
+ hid_err(hid, "Private driver data not found!\n");
+ return 0;
}
- if (h == &device_list.list) {
- dbg_hid("Device not found!");
+
+ entry = drv_data->device_props;
+ if (!entry) {
+ hid_err(hid, "Device properties not found!\n");
return 0;
}
@@ -308,19 +309,21 @@ static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *att
* according to the type of the wheel */
static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- struct lg4ff_device_entry *uninitialized_var(entry);
- struct list_head *h;
struct hid_device *hid = to_hid_device(dev);
+ struct lg4ff_device_entry *entry;
+ struct lg_drv_data *drv_data;
__u16 range = simple_strtoul(buf, NULL, 10);
- list_for_each(h, &device_list.list) {
- entry = list_entry(h, struct lg4ff_device_entry, list);
- if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0)
- break;
+ drv_data = hid_get_drvdata(hid);
+ if (!drv_data) {
+ hid_err(hid, "Private driver data not found!\n");
+ return 0;
}
- if (h == &device_list.list) {
- dbg_hid("Device not found!");
- return count;
+
+ entry = drv_data->device_props;
+ if (!entry) {
+ hid_err(hid, "Device properties not found!\n");
+ return 0;
}
if (range == 0)
@@ -336,6 +339,88 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
return count;
}
+#ifdef CONFIG_LEDS_CLASS
+static void lg4ff_set_leds(struct hid_device *hid, __u8 leds)
+{
+ struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+
+ report->field[0]->value[0] = 0xf8;
+ report->field[0]->value[1] = 0x12;
+ report->field[0]->value[2] = leds;
+ report->field[0]->value[3] = 0x00;
+ report->field[0]->value[4] = 0x00;
+ report->field[0]->value[5] = 0x00;
+ report->field[0]->value[6] = 0x00;
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+static void lg4ff_led_set_brightness(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct device *dev = led_cdev->dev->parent;
+ struct hid_device *hid = container_of(dev, struct hid_device, dev);
+ struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
+ struct lg4ff_device_entry *entry;
+ int i, state = 0;
+
+ if (!drv_data) {
+ hid_err(hid, "Device data not found.");
+ return;
+ }
+
+ entry = (struct lg4ff_device_entry *)drv_data->device_props;
+
+ if (!entry) {
+ hid_err(hid, "Device properties not found.");
+ return;
+ }
+
+ for (i = 0; i < 5; i++) {
+ if (led_cdev != entry->led[i])
+ continue;
+ state = (entry->led_state >> i) & 1;
+ if (value == LED_OFF && state) {
+ entry->led_state &= ~(1 << i);
+ lg4ff_set_leds(hid, entry->led_state);
+ } else if (value != LED_OFF && !state) {
+ entry->led_state |= 1 << i;
+ lg4ff_set_leds(hid, entry->led_state);
+ }
+ break;
+ }
+}
+
+static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cdev)
+{
+ struct device *dev = led_cdev->dev->parent;
+ struct hid_device *hid = container_of(dev, struct hid_device, dev);
+ struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
+ struct lg4ff_device_entry *entry;
+ int i, value = 0;
+
+ if (!drv_data) {
+ hid_err(hid, "Device data not found.");
+ return LED_OFF;
+ }
+
+ entry = (struct lg4ff_device_entry *)drv_data->device_props;
+
+ if (!entry) {
+ hid_err(hid, "Device properties not found.");
+ return LED_OFF;
+ }
+
+ for (i = 0; i < 5; i++)
+ if (led_cdev == entry->led[i]) {
+ value = (entry->led_state >> i) & 1;
+ break;
+ }
+
+ return value ? LED_FULL : LED_OFF;
+}
+#endif
+
int lg4ff_init(struct hid_device *hid)
{
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
@@ -344,6 +429,7 @@ int lg4ff_init(struct hid_device *hid)
struct hid_report *report;
struct hid_field *field;
struct lg4ff_device_entry *entry;
+ struct lg_drv_data *drv_data;
struct usb_device_descriptor *udesc;
int error, i, j;
__u16 bcdDevice, rev_maj, rev_min;
@@ -423,28 +509,24 @@ int lg4ff_init(struct hid_device *hid)
dev->ff->set_autocenter(dev, 0);
}
- /* Initialize device_list if this is the first device to handle by lg4ff */
- if (!list_inited) {
- INIT_LIST_HEAD(&device_list.list);
- list_inited = 1;
+ /* Get private driver data */
+ drv_data = hid_get_drvdata(hid);
+ if (!drv_data) {
+ hid_err(hid, "Cannot add device, private driver data not allocated\n");
+ return -1;
}
- /* Add the device to device_list */
+ /* Initialize device properties */
entry = kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL);
if (!entry) {
- hid_err(hid, "Cannot add device, insufficient memory.\n");
- return -ENOMEM;
- }
- entry->device_id = kstrdup((&hid->dev)->kobj.name, GFP_KERNEL);
- if (!entry->device_id) {
- hid_err(hid, "Cannot set device_id, insufficient memory.\n");
- kfree(entry);
+ hid_err(hid, "Cannot add device, insufficient memory to allocate device properties.\n");
return -ENOMEM;
}
+ drv_data->device_props = entry;
+
entry->min_range = lg4ff_devices[i].min_range;
entry->max_range = lg4ff_devices[i].max_range;
entry->set_range = lg4ff_devices[i].set_range;
- list_add(&entry->list, &device_list.list);
/* Create sysfs interface */
error = device_create_file(&hid->dev, &dev_attr_range);
@@ -457,32 +539,100 @@ int lg4ff_init(struct hid_device *hid)
if (entry->set_range != NULL)
entry->set_range(hid, entry->range);
- hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n");
+#ifdef CONFIG_LEDS_CLASS
+ /* register led subsystem - G27 only */
+ entry->led_state = 0;
+ for (j = 0; j < 5; j++)
+ entry->led[j] = NULL;
+
+ if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL) {
+ struct led_classdev *led;
+ size_t name_sz;
+ char *name;
+
+ lg4ff_set_leds(hid, 0);
+
+ name_sz = strlen(dev_name(&hid->dev)) + 8;
+
+ for (j = 0; j < 5; j++) {
+ led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL);
+ if (!led) {
+ hid_err(hid, "can't allocate memory for LED %d\n", j);
+ goto err;
+ }
+
+ name = (void *)(&led[1]);
+ snprintf(name, name_sz, "%s::RPM%d", dev_name(&hid->dev), j+1);
+ led->name = name;
+ led->brightness = 0;
+ led->max_brightness = 1;
+ led->brightness_get = lg4ff_led_get_brightness;
+ led->brightness_set = lg4ff_led_set_brightness;
+
+ entry->led[j] = led;
+ error = led_classdev_register(&hid->dev, led);
+
+ if (error) {
+ hid_err(hid, "failed to register LED %d. Aborting.\n", j);
+err:
+ /* Deregister LEDs (if any) */
+ for (j = 0; j < 5; j++) {
+ led = entry->led[j];
+ entry->led[j] = NULL;
+ if (!led)
+ continue;
+ led_classdev_unregister(led);
+ kfree(led);
+ }
+ goto out; /* Let the driver continue without LEDs */
+ }
+ }
+ }
+out:
+#endif
+ hid_info(hid, "Force feedback support for Logitech Gaming Wheels\n");
return 0;
}
int lg4ff_deinit(struct hid_device *hid)
{
- bool found = 0;
struct lg4ff_device_entry *entry;
- struct list_head *h, *g;
- list_for_each_safe(h, g, &device_list.list) {
- entry = list_entry(h, struct lg4ff_device_entry, list);
- if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0) {
- list_del(h);
- kfree(entry->device_id);
- kfree(entry);
- found = 1;
- break;
- }
- }
+ struct lg_drv_data *drv_data;
+
+ device_remove_file(&hid->dev, &dev_attr_range);
- if (!found) {
- dbg_hid("Device entry not found!\n");
+ drv_data = hid_get_drvdata(hid);
+ if (!drv_data) {
+ hid_err(hid, "Error while deinitializing device, no private driver data.\n");
+ return -1;
+ }
+ entry = drv_data->device_props;
+ if (!entry) {
+ hid_err(hid, "Error while deinitializing device, no device properties data.\n");
return -1;
}
- device_remove_file(&hid->dev, &dev_attr_range);
+#ifdef CONFIG_LEDS_CLASS
+ {
+ int j;
+ struct led_classdev *led;
+
+ /* Deregister LEDs (if any) */
+ for (j = 0; j < 5; j++) {
+
+ led = entry->led[j];
+ entry->led[j] = NULL;
+ if (!led)
+ continue;
+ led_classdev_unregister(led);
+ kfree(led);
+ }
+ }
+#endif
+
+ /* Deallocate memory */
+ kfree(entry);
+
dbg_hid("Device successfully unregistered\n");
return 0;
}
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 2b56efcbdf61..5e8a7ed42344 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -26,6 +26,7 @@
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/usb.h>
+#include <asm/unaligned.h>
#include "usbhid/usbhid.h"
#include "hid-ids.h"
#include "hid-logitech-dj.h"
@@ -155,6 +156,14 @@ static const char media_descriptor[] = {
/* Maximum size of all defined hid reports in bytes (including report id) */
#define MAX_REPORT_SIZE 8
+/* Make sure all descriptors are present here */
+#define MAX_RDESC_SIZE \
+ (sizeof(kbd_descriptor) + \
+ sizeof(mse_descriptor) + \
+ sizeof(consumer_descriptor) + \
+ sizeof(syscontrol_descriptor) + \
+ sizeof(media_descriptor))
+
/* Number of possible hid report types that can be created by this driver.
*
* Right now, RF report types have the same report types (or report id's)
@@ -265,8 +274,8 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
goto dj_device_allocate_fail;
}
- dj_dev->reports_supported = le32_to_cpu(
- dj_report->report_params[DEVICE_PAIRED_RF_REPORT_TYPE]);
+ dj_dev->reports_supported = get_unaligned_le32(
+ dj_report->report_params + DEVICE_PAIRED_RF_REPORT_TYPE);
dj_dev->hdev = dj_hiddev;
dj_dev->dj_receiver_dev = djrcv_dev;
dj_dev->device_index = dj_report->device_index;
@@ -473,9 +482,17 @@ static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
return 0;
}
+static void rdcat(char **rdesc, unsigned int *rsize, const char *data, unsigned int size)
+{
+ memcpy(*rdesc + *rsize, data, size);
+ *rsize += size;
+}
+
static int logi_dj_ll_parse(struct hid_device *hid)
{
struct dj_device *djdev = hid->driver_data;
+ unsigned int rsize = 0;
+ char *rdesc;
int retval;
dbg_hid("%s\n", __func__);
@@ -483,70 +500,38 @@ static int logi_dj_ll_parse(struct hid_device *hid)
djdev->hdev->version = 0x0111;
djdev->hdev->country = 0x00;
+ rdesc = kmalloc(MAX_RDESC_SIZE, GFP_KERNEL);
+ if (!rdesc)
+ return -ENOMEM;
+
if (djdev->reports_supported & STD_KEYBOARD) {
dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n",
__func__, djdev->reports_supported);
- retval = hid_parse_report(hid,
- (u8 *) kbd_descriptor,
- sizeof(kbd_descriptor));
- if (retval) {
- dbg_hid("%s: sending a kbd descriptor, hid_parse failed"
- " error: %d\n", __func__, retval);
- return retval;
- }
+ rdcat(&rdesc, &rsize, kbd_descriptor, sizeof(kbd_descriptor));
}
if (djdev->reports_supported & STD_MOUSE) {
dbg_hid("%s: sending a mouse descriptor, reports_supported: "
"%x\n", __func__, djdev->reports_supported);
- retval = hid_parse_report(hid,
- (u8 *) mse_descriptor,
- sizeof(mse_descriptor));
- if (retval) {
- dbg_hid("%s: sending a mouse descriptor, hid_parse "
- "failed error: %d\n", __func__, retval);
- return retval;
- }
+ rdcat(&rdesc, &rsize, mse_descriptor, sizeof(mse_descriptor));
}
if (djdev->reports_supported & MULTIMEDIA) {
dbg_hid("%s: sending a multimedia report descriptor: %x\n",
__func__, djdev->reports_supported);
- retval = hid_parse_report(hid,
- (u8 *) consumer_descriptor,
- sizeof(consumer_descriptor));
- if (retval) {
- dbg_hid("%s: sending a consumer_descriptor, hid_parse "
- "failed error: %d\n", __func__, retval);
- return retval;
- }
+ rdcat(&rdesc, &rsize, consumer_descriptor, sizeof(consumer_descriptor));
}
if (djdev->reports_supported & POWER_KEYS) {
dbg_hid("%s: sending a power keys report descriptor: %x\n",
__func__, djdev->reports_supported);
- retval = hid_parse_report(hid,
- (u8 *) syscontrol_descriptor,
- sizeof(syscontrol_descriptor));
- if (retval) {
- dbg_hid("%s: sending a syscontrol_descriptor, "
- "hid_parse failed error: %d\n",
- __func__, retval);
- return retval;
- }
+ rdcat(&rdesc, &rsize, syscontrol_descriptor, sizeof(syscontrol_descriptor));
}
if (djdev->reports_supported & MEDIA_CENTER) {
dbg_hid("%s: sending a media center report descriptor: %x\n",
__func__, djdev->reports_supported);
- retval = hid_parse_report(hid,
- (u8 *) media_descriptor,
- sizeof(media_descriptor));
- if (retval) {
- dbg_hid("%s: sending a media_descriptor, hid_parse "
- "failed error: %d\n", __func__, retval);
- return retval;
- }
+ rdcat(&rdesc, &rsize, media_descriptor, sizeof(media_descriptor));
}
if (djdev->reports_supported & KBD_LEDS) {
@@ -554,7 +539,10 @@ static int logi_dj_ll_parse(struct hid_device *hid)
__func__, djdev->reports_supported);
}
- return 0;
+ retval = hid_parse_report(hid, rdesc, rsize);
+ kfree(rdesc);
+
+ return retval;
}
static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 1d5b94167b52..6e3332a99976 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -70,9 +70,16 @@ struct mt_class {
bool is_indirect; /* true for touchpads */
};
+struct mt_fields {
+ unsigned usages[HID_MAX_FIELDS];
+ unsigned int length;
+};
+
struct mt_device {
struct mt_slot curdata; /* placeholder of incoming data */
struct mt_class mtclass; /* our mt device class */
+ struct mt_fields *fields; /* temporary placeholder for storing the
+ multitouch fields */
unsigned last_field_index; /* last field index of the report */
unsigned last_slot_field; /* the last field of a slot */
__s8 inputmode; /* InputMode HID feature, -1 if non-existent */
@@ -110,6 +117,9 @@ struct mt_device {
#define MT_DEFAULT_MAXCONTACT 10
+#define MT_USB_DEVICE(v, p) HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p)
+#define MT_BT_DEVICE(v, p) HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p)
+
/*
* these device-dependent functions determine what slot corresponds
* to a valid contact that was just read.
@@ -275,11 +285,15 @@ static void set_abs(struct input_dev *input, unsigned int code,
input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
}
-static void set_last_slot_field(struct hid_usage *usage, struct mt_device *td,
+static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
struct hid_input *hi)
{
- if (!test_bit(usage->hid, hi->input->absbit))
- td->last_slot_field = usage->hid;
+ struct mt_fields *f = td->fields;
+
+ if (f->length >= HID_MAX_FIELDS)
+ return;
+
+ f->usages[f->length++] = usage->hid;
}
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -330,7 +344,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
cls->sn_move);
/* touchscreen emulation */
set_abs(hi->input, ABS_X, field, cls->sn_move);
- set_last_slot_field(usage, td, hi);
+ mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
case HID_GD_Y:
@@ -340,7 +354,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
cls->sn_move);
/* touchscreen emulation */
set_abs(hi->input, ABS_Y, field, cls->sn_move);
- set_last_slot_field(usage, td, hi);
+ mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
}
@@ -349,24 +363,24 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case HID_UP_DIGITIZER:
switch (usage->hid) {
case HID_DG_INRANGE:
- set_last_slot_field(usage, td, hi);
+ mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
case HID_DG_CONFIDENCE:
- set_last_slot_field(usage, td, hi);
+ mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
case HID_DG_TIPSWITCH:
hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
- set_last_slot_field(usage, td, hi);
+ mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
case HID_DG_CONTACTID:
if (!td->maxcontacts)
td->maxcontacts = MT_DEFAULT_MAXCONTACT;
input_mt_init_slots(hi->input, td->maxcontacts);
- td->last_slot_field = usage->hid;
+ mt_store_field(usage, td, hi);
td->last_field_index = field->index;
td->touches_by_report++;
return 1;
@@ -375,7 +389,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
EV_ABS, ABS_MT_TOUCH_MAJOR);
set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
cls->sn_width);
- set_last_slot_field(usage, td, hi);
+ mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
case HID_DG_HEIGHT:
@@ -385,7 +399,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
cls->sn_height);
input_set_abs_params(hi->input,
ABS_MT_ORIENTATION, 0, 1, 0, 0);
- set_last_slot_field(usage, td, hi);
+ mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
case HID_DG_TIPPRESSURE:
@@ -396,7 +410,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
/* touchscreen emulation */
set_abs(hi->input, ABS_PRESSURE, field,
cls->sn_pressure);
- set_last_slot_field(usage, td, hi);
+ mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
case HID_DG_CONTACTCOUNT:
@@ -635,6 +649,31 @@ static void mt_set_maxcontacts(struct hid_device *hdev)
}
}
+static void mt_post_parse_default_settings(struct mt_device *td)
+{
+ __s32 quirks = td->mtclass.quirks;
+
+ /* unknown serial device needs special quirks */
+ if (td->touches_by_report == 1) {
+ quirks |= MT_QUIRK_ALWAYS_VALID;
+ quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
+ quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
+ quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE;
+ }
+
+ td->mtclass.quirks = quirks;
+}
+
+static void mt_post_parse(struct mt_device *td)
+{
+ struct mt_fields *f = td->fields;
+
+ if (td->touches_by_report > 0) {
+ int field_count_per_touch = f->length / td->touches_by_report;
+ td->last_slot_field = f->usages[field_count_per_touch - 1];
+ }
+}
+
static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret, i;
@@ -654,7 +693,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
* that emit events over several HID messages.
*/
hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
- hdev->quirks &= ~HID_QUIRK_MULTITOUCH;
td = kzalloc(sizeof(struct mt_device), GFP_KERNEL);
if (!td) {
@@ -666,6 +704,13 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
td->maxcontact_report_id = -1;
hid_set_drvdata(hdev, td);
+ td->fields = kzalloc(sizeof(struct mt_fields), GFP_KERNEL);
+ if (!td->fields) {
+ dev_err(&hdev->dev, "cannot allocate multitouch fields data\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
ret = hid_parse(hdev);
if (ret != 0)
goto fail;
@@ -674,14 +719,10 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (ret)
goto fail;
- if (!id && td->touches_by_report == 1) {
- /* the device has been sent by hid-generic */
- mtclass = &td->mtclass;
- mtclass->quirks |= MT_QUIRK_ALWAYS_VALID;
- mtclass->quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
- mtclass->quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
- mtclass->quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE;
- }
+ mt_post_parse(td);
+
+ if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
+ mt_post_parse_default_settings(td);
td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),
GFP_KERNEL);
@@ -697,9 +738,13 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
mt_set_maxcontacts(hdev);
mt_set_input_mode(hdev);
+ kfree(td->fields);
+ td->fields = NULL;
+
return 0;
fail:
+ kfree(td->fields);
kfree(td);
return ret;
}
@@ -727,50 +772,54 @@ static const struct hid_device_id mt_devices[] = {
/* 3M panels */
{ .driver_data = MT_CLS_3M,
- HID_USB_DEVICE(USB_VENDOR_ID_3M,
+ MT_USB_DEVICE(USB_VENDOR_ID_3M,
USB_DEVICE_ID_3M1968) },
{ .driver_data = MT_CLS_3M,
- HID_USB_DEVICE(USB_VENDOR_ID_3M,
+ MT_USB_DEVICE(USB_VENDOR_ID_3M,
USB_DEVICE_ID_3M2256) },
{ .driver_data = MT_CLS_3M,
- HID_USB_DEVICE(USB_VENDOR_ID_3M,
+ MT_USB_DEVICE(USB_VENDOR_ID_3M,
USB_DEVICE_ID_3M3266) },
/* ActionStar panels */
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR,
+ MT_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR,
USB_DEVICE_ID_ACTIONSTAR_1011) },
/* Atmel panels */
{ .driver_data = MT_CLS_SERIAL,
- HID_USB_DEVICE(USB_VENDOR_ID_ATMEL,
+ MT_USB_DEVICE(USB_VENDOR_ID_ATMEL,
USB_DEVICE_ID_ATMEL_MULTITOUCH) },
{ .driver_data = MT_CLS_SERIAL,
- HID_USB_DEVICE(USB_VENDOR_ID_ATMEL,
+ MT_USB_DEVICE(USB_VENDOR_ID_ATMEL,
USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) },
+ /* Baanto multitouch devices */
+ { .driver_data = MT_CLS_DEFAULT,
+ MT_USB_DEVICE(USB_VENDOR_ID_BAANTO,
+ USB_DEVICE_ID_BAANTO_MT_190W2) },
/* Cando panels */
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
- HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+ MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
- HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+ MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
- HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+ MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
- HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+ MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
/* Chunghwa Telecom touch panels */
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
+ MT_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
/* CVTouch panels */
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
+ MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
USB_DEVICE_ID_CVTOUCH_SCREEN) },
/* Cypress panel */
@@ -780,225 +829,227 @@ static const struct hid_device_id mt_devices[] = {
/* eGalax devices (resistive) */
{ .driver_data = MT_CLS_EGALAX,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) },
{ .driver_data = MT_CLS_EGALAX,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) },
/* eGalax devices (capacitive) */
{ .driver_data = MT_CLS_EGALAX,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) },
{ .driver_data = MT_CLS_EGALAX_SERIAL,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207) },
{ .driver_data = MT_CLS_EGALAX_SERIAL,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) },
{ .driver_data = MT_CLS_EGALAX_SERIAL,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) },
{ .driver_data = MT_CLS_EGALAX_SERIAL,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_722A) },
{ .driver_data = MT_CLS_EGALAX,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) },
{ .driver_data = MT_CLS_EGALAX_SERIAL,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7262) },
{ .driver_data = MT_CLS_EGALAX,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) },
{ .driver_data = MT_CLS_EGALAX_SERIAL,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA) },
{ .driver_data = MT_CLS_EGALAX,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA) },
{ .driver_data = MT_CLS_EGALAX,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) },
{ .driver_data = MT_CLS_EGALAX_SERIAL,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349) },
{ .driver_data = MT_CLS_EGALAX_SERIAL,
- HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
/* Elo TouchSystems IntelliTouch Plus panel */
{ .driver_data = MT_CLS_DUAL_NSMU_CONTACTID,
- HID_USB_DEVICE(USB_VENDOR_ID_ELO,
+ MT_USB_DEVICE(USB_VENDOR_ID_ELO,
USB_DEVICE_ID_ELO_TS2515) },
/* GeneralTouch panel */
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
- HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
+ MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
/* Gametel game controller */
{ .driver_data = MT_CLS_DEFAULT,
- HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_FRUCTEL,
+ MT_BT_DEVICE(USB_VENDOR_ID_FRUCTEL,
USB_DEVICE_ID_GAMETEL_MT_MODE) },
/* GoodTouch panels */
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
+ MT_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
USB_DEVICE_ID_GOODTOUCH_000f) },
/* Hanvon panels */
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
- HID_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,
+ MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,
USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
/* Ideacom panel */
{ .driver_data = MT_CLS_SERIAL,
- HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM,
+ MT_USB_DEVICE(USB_VENDOR_ID_IDEACOM,
USB_DEVICE_ID_IDEACOM_IDC6650) },
{ .driver_data = MT_CLS_SERIAL,
- HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM,
+ MT_USB_DEVICE(USB_VENDOR_ID_IDEACOM,
USB_DEVICE_ID_IDEACOM_IDC6651) },
/* Ilitek dual touch panel */
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_ILITEK,
+ MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
USB_DEVICE_ID_ILITEK_MULTITOUCH) },
/* IRTOUCH panels */
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
- HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
+ MT_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
/* LG Display panels */
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_LG,
+ MT_USB_DEVICE(USB_VENDOR_ID_LG,
USB_DEVICE_ID_LG_MULTITOUCH) },
/* Lumio panels */
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
- HID_USB_DEVICE(USB_VENDOR_ID_LUMIO,
+ MT_USB_DEVICE(USB_VENDOR_ID_LUMIO,
USB_DEVICE_ID_CRYSTALTOUCH) },
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
- HID_USB_DEVICE(USB_VENDOR_ID_LUMIO,
+ MT_USB_DEVICE(USB_VENDOR_ID_LUMIO,
USB_DEVICE_ID_CRYSTALTOUCH_DUAL) },
/* MosArt panels */
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
- HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
+ MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
USB_DEVICE_ID_ASUS_T91MT)},
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
- HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
+ MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
- HID_USB_DEVICE(USB_VENDOR_ID_TURBOX,
+ MT_USB_DEVICE(USB_VENDOR_ID_TURBOX,
USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
/* Panasonic panels */
{ .driver_data = MT_CLS_PANASONIC,
- HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
+ MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
USB_DEVICE_ID_PANABOARD_UBT780) },
{ .driver_data = MT_CLS_PANASONIC,
- HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
+ MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
USB_DEVICE_ID_PANABOARD_UBT880) },
/* PenMount panels */
{ .driver_data = MT_CLS_CONFIDENCE,
- HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT,
+ MT_USB_DEVICE(USB_VENDOR_ID_PENMOUNT,
USB_DEVICE_ID_PENMOUNT_PCI) },
/* PixArt optical touch screen */
{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
- HID_USB_DEVICE(USB_VENDOR_ID_PIXART,
+ MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) },
{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
- HID_USB_DEVICE(USB_VENDOR_ID_PIXART,
+ MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) },
{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
- HID_USB_DEVICE(USB_VENDOR_ID_PIXART,
+ MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) },
/* PixCir-based panels */
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
- HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
+ MT_USB_DEVICE(USB_VENDOR_ID_HANVON,
USB_DEVICE_ID_HANVON_MULTITOUCH) },
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
- HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+ MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
/* Quanta-based panels */
{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
- HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
+ MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
- HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
+ MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) },
{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
- HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
+ MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) },
/* Stantum panels */
{ .driver_data = MT_CLS_CONFIDENCE,
- HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
+ MT_USB_DEVICE(USB_VENDOR_ID_STANTUM,
USB_DEVICE_ID_MTP)},
{ .driver_data = MT_CLS_CONFIDENCE,
- HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
+ MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
USB_DEVICE_ID_MTP_STM)},
{ .driver_data = MT_CLS_CONFIDENCE,
- HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX,
+ MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX,
USB_DEVICE_ID_MTP_SITRONIX)},
/* TopSeed panels */
{ .driver_data = MT_CLS_TOPSEED,
- HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2,
+ MT_USB_DEVICE(USB_VENDOR_ID_TOPSEED2,
USB_DEVICE_ID_TOPSEED2_PERIPAD_701) },
/* Touch International panels */
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL,
+ MT_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL,
USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) },
/* Unitec panels */
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_UNITEC,
+ MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_UNITEC,
+ MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
/* XAT */
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_XAT,
+ MT_USB_DEVICE(USB_VENDOR_ID_XAT,
USB_DEVICE_ID_XAT_CSR) },
/* Xiroku */
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
+ MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
USB_DEVICE_ID_XIROKU_SPX) },
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
+ MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
USB_DEVICE_ID_XIROKU_MPX) },
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
+ MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
USB_DEVICE_ID_XIROKU_CSR) },
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
+ MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
USB_DEVICE_ID_XIROKU_SPX1) },
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
+ MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
USB_DEVICE_ID_XIROKU_MPX1) },
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
+ MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
USB_DEVICE_ID_XIROKU_CSR1) },
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
+ MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
USB_DEVICE_ID_XIROKU_SPX2) },
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
+ MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
USB_DEVICE_ID_XIROKU_MPX2) },
{ .driver_data = MT_CLS_DEFAULT,
- HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
+ MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
USB_DEVICE_ID_XIROKU_CSR2) },
+ /* Generic MT device */
+ { HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },
{ }
};
MODULE_DEVICE_TABLE(hid, mt_devices);
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
index 1f1128910337..3aba02be1f26 100644
--- a/drivers/hid/hid-uclogic.c
+++ b/drivers/hid/hid-uclogic.c
@@ -14,6 +14,7 @@
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
+#include <linux/usb.h>
#include "hid-ids.h"
@@ -352,9 +353,125 @@ static __u8 pf1209_rdesc_fixed[] = {
0xC0 /* End Collection */
};
+/*
+ * See TWHL850 description, device and HID report descriptors at
+ * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Wireless_Tablet_TWHL850
+ */
+
+/* Size of the original descriptors of TWHL850 tablet */
+#define TWHL850_RDESC_ORIG_SIZE0 182
+#define TWHL850_RDESC_ORIG_SIZE1 161
+#define TWHL850_RDESC_ORIG_SIZE2 92
+
+/* Fixed PID 0522 tablet report descriptor, interface 0 (stylus) */
+static __u8 twhl850_rdesc_fixed0[] = {
+ 0x05, 0x0D, /* Usage Page (Digitizer), */
+ 0x09, 0x02, /* Usage (Pen), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x85, 0x09, /* Report ID (9), */
+ 0x09, 0x20, /* Usage (Stylus), */
+ 0xA0, /* Collection (Physical), */
+ 0x14, /* Logical Minimum (0), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x09, 0x42, /* Usage (Tip Switch), */
+ 0x09, 0x44, /* Usage (Barrel Switch), */
+ 0x09, 0x46, /* Usage (Tablet Pick), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x09, 0x32, /* Usage (In Range), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x75, 0x10, /* Report Size (16), */
+ 0xA4, /* Push, */
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x65, 0x13, /* Unit (Inch), */
+ 0x55, 0xFD, /* Unit Exponent (-3), */
+ 0x34, /* Physical Minimum (0), */
+ 0x09, 0x30, /* Usage (X), */
+ 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */
+ 0x26, 0x00, 0x7D, /* Logical Maximum (32000), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x09, 0x31, /* Usage (Y), */
+ 0x46, 0x88, 0x13, /* Physical Maximum (5000), */
+ 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xB4, /* Pop, */
+ 0x09, 0x30, /* Usage (Tip Pressure), */
+ 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xC0, /* End Collection, */
+ 0xC0 /* End Collection */
+};
+
+/* Fixed PID 0522 tablet report descriptor, interface 1 (mouse) */
+static __u8 twhl850_rdesc_fixed1[] = {
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x09, 0x02, /* Usage (Mouse), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x85, 0x01, /* Report ID (1), */
+ 0x09, 0x01, /* Usage (Pointer), */
+ 0xA0, /* Collection (Physical), */
+ 0x05, 0x09, /* Usage Page (Button), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x19, 0x01, /* Usage Minimum (01h), */
+ 0x29, 0x03, /* Usage Maximum (03h), */
+ 0x14, /* Logical Minimum (0), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x95, 0x05, /* Report Count (5), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x09, 0x30, /* Usage (X), */
+ 0x09, 0x31, /* Usage (Y), */
+ 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */
+ 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */
+ 0x75, 0x10, /* Report Size (16), */
+ 0x95, 0x02, /* Report Count (2), */
+ 0x81, 0x06, /* Input (Variable, Relative), */
+ 0x09, 0x38, /* Usage (Wheel), */
+ 0x15, 0xFF, /* Logical Minimum (-1), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x81, 0x06, /* Input (Variable, Relative), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0xC0, /* End Collection, */
+ 0xC0 /* End Collection */
+};
+
+/* Fixed PID 0522 tablet report descriptor, interface 2 (frame buttons) */
+static __u8 twhl850_rdesc_fixed2[] = {
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x09, 0x06, /* Usage (Keyboard), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x85, 0x03, /* Report ID (3), */
+ 0x05, 0x07, /* Usage Page (Keyboard), */
+ 0x14, /* Logical Minimum (0), */
+ 0x19, 0xE0, /* Usage Minimum (KB Leftcontrol), */
+ 0x29, 0xE7, /* Usage Maximum (KB Right GUI), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x95, 0x08, /* Report Count (8), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x18, /* Usage Minimum (None), */
+ 0x29, 0xFF, /* Usage Maximum (FFh), */
+ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x06, /* Report Count (6), */
+ 0x80, /* Input, */
+ 0xC0 /* End Collection */
+};
+
static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
+ struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
+ __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
+
switch (hdev->product) {
case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209:
if (*rsize == PF1209_RDESC_ORIG_SIZE) {
@@ -386,6 +503,28 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*rsize = sizeof(wp1062_rdesc_fixed);
}
break;
+ case USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850:
+ switch (iface_num) {
+ case 0:
+ if (*rsize == TWHL850_RDESC_ORIG_SIZE0) {
+ rdesc = twhl850_rdesc_fixed0;
+ *rsize = sizeof(twhl850_rdesc_fixed0);
+ }
+ break;
+ case 1:
+ if (*rsize == TWHL850_RDESC_ORIG_SIZE1) {
+ rdesc = twhl850_rdesc_fixed1;
+ *rsize = sizeof(twhl850_rdesc_fixed1);
+ }
+ break;
+ case 2:
+ if (*rsize == TWHL850_RDESC_ORIG_SIZE2) {
+ rdesc = twhl850_rdesc_fixed2;
+ *rsize = sizeof(twhl850_rdesc_fixed2);
+ }
+ break;
+ }
+ break;
}
return rdesc;
@@ -402,6 +541,8 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
+ USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
{ }
};
MODULE_DEVICE_TABLE(hid, uclogic_devices);
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
index 067e2963314c..fe23a1eb586b 100644
--- a/drivers/hid/hid-wacom.c
+++ b/drivers/hid/hid-wacom.c
@@ -24,15 +24,16 @@
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
+#include <linux/leds.h>
#include <linux/slab.h>
-#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
#include <linux/power_supply.h>
-#endif
#include "hid-ids.h"
#define PAD_DEVICE_ID 0x0F
+#define WAC_CMD_LED_CONTROL 0x20
+
struct wacom_data {
__u16 tool;
__u16 butstate;
@@ -41,16 +42,20 @@ struct wacom_data {
__u32 id;
__u32 serial;
unsigned char high_speed;
-#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
- int battery_capacity;
+ __u8 battery_capacity;
+ __u8 power_raw;
+ __u8 ps_connected;
struct power_supply battery;
struct power_supply ac;
-#endif
+ __u8 led_selector;
+ struct led_classdev *leds[4];
};
-#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
-/*percent of battery capacity, 0 means AC online*/
-static unsigned short batcap[8] = { 1, 15, 25, 35, 50, 70, 100, 0 };
+/*percent of battery capacity for Graphire
+ 8th value means AC online and show 100% capacity */
+static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 };
+/*percent of battery capacity for Intuos4 WL, AC has a separate bit*/
+static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 };
static enum power_supply_property wacom_battery_props[] = {
POWER_SUPPLY_PROP_PRESENT,
@@ -64,13 +69,123 @@ static enum power_supply_property wacom_ac_props[] = {
POWER_SUPPLY_PROP_SCOPE,
};
+static void wacom_leds_set_brightness(struct led_classdev *led_dev,
+ enum led_brightness value)
+{
+ struct device *dev = led_dev->dev->parent;
+ struct hid_device *hdev;
+ struct wacom_data *wdata;
+ unsigned char *buf;
+ __u8 led = 0;
+ int i;
+
+ hdev = container_of(dev, struct hid_device, dev);
+ wdata = hid_get_drvdata(hdev);
+ for (i = 0; i < 4; ++i) {
+ if (wdata->leds[i] == led_dev)
+ wdata->led_selector = i;
+ }
+
+ led = wdata->led_selector | 0x04;
+ buf = kzalloc(9, GFP_KERNEL);
+ if (buf) {
+ buf[0] = WAC_CMD_LED_CONTROL;
+ buf[1] = led;
+ buf[2] = value;
+ hdev->hid_output_raw_report(hdev, buf, 9, HID_FEATURE_REPORT);
+ kfree(buf);
+ }
+
+ return;
+}
+
+static enum led_brightness wacom_leds_get_brightness(struct led_classdev *led_dev)
+{
+ struct wacom_data *wdata;
+ struct device *dev = led_dev->dev->parent;
+ int value = 0;
+ int i;
+
+ wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev));
+
+ for (i = 0; i < 4; ++i) {
+ if (wdata->leds[i] == led_dev) {
+ value = wdata->leds[i]->brightness;
+ break;
+ }
+ }
+
+ return value;
+}
+
+
+static int wacom_initialize_leds(struct hid_device *hdev)
+{
+ struct wacom_data *wdata = hid_get_drvdata(hdev);
+ struct led_classdev *led;
+ struct device *dev = &hdev->dev;
+ size_t namesz = strlen(dev_name(dev)) + 12;
+ char *name;
+ int i, ret;
+
+ wdata->led_selector = 0;
+
+ for (i = 0; i < 4; i++) {
+ led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL);
+ if (!led) {
+ hid_warn(hdev,
+ "can't allocate memory for LED selector\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ name = (void *)&led[1];
+ snprintf(name, namesz, "%s:selector:%d", dev_name(dev), i);
+ led->name = name;
+ led->brightness = 0;
+ led->max_brightness = 127;
+ led->brightness_get = wacom_leds_get_brightness;
+ led->brightness_set = wacom_leds_set_brightness;
+
+ wdata->leds[i] = led;
+
+ ret = led_classdev_register(dev, wdata->leds[i]);
+
+ if (ret) {
+ wdata->leds[i] = NULL;
+ kfree(led);
+ hid_warn(hdev, "can't register LED\n");
+ goto err;
+ }
+ }
+
+err:
+ return ret;
+}
+
+static void wacom_destroy_leds(struct hid_device *hdev)
+{
+ struct wacom_data *wdata = hid_get_drvdata(hdev);
+ struct led_classdev *led;
+ int i;
+
+ for (i = 0; i < 4; ++i) {
+ if (wdata->leds[i]) {
+ led = wdata->leds[i];
+ wdata->leds[i] = NULL;
+ led_classdev_unregister(led);
+ kfree(led);
+ }
+ }
+
+}
+
static int wacom_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
struct wacom_data *wdata = container_of(psy,
struct wacom_data, battery);
- int power_state = batcap[wdata->battery_capacity];
int ret = 0;
switch (psp) {
@@ -81,11 +196,7 @@ static int wacom_battery_get_property(struct power_supply *psy,
val->intval = POWER_SUPPLY_SCOPE_DEVICE;
break;
case POWER_SUPPLY_PROP_CAPACITY:
- /* show 100% battery capacity when charging */
- if (power_state == 0)
- val->intval = 100;
- else
- val->intval = power_state;
+ val->intval = wdata->battery_capacity;
break;
default:
ret = -EINVAL;
@@ -99,17 +210,13 @@ static int wacom_ac_get_property(struct power_supply *psy,
union power_supply_propval *val)
{
struct wacom_data *wdata = container_of(psy, struct wacom_data, ac);
- int power_state = batcap[wdata->battery_capacity];
int ret = 0;
switch (psp) {
case POWER_SUPPLY_PROP_PRESENT:
/* fall through */
case POWER_SUPPLY_PROP_ONLINE:
- if (power_state == 0)
- val->intval = 1;
- else
- val->intval = 0;
+ val->intval = wdata->ps_connected;
break;
case POWER_SUPPLY_PROP_SCOPE:
val->intval = POWER_SUPPLY_SCOPE_DEVICE;
@@ -120,41 +227,16 @@ static int wacom_ac_get_property(struct power_supply *psy,
}
return ret;
}
-#endif
-
-static void wacom_set_features(struct hid_device *hdev)
-{
- int ret;
- __u8 rep_data[2];
-
- /*set high speed, tablet mode*/
- rep_data[0] = 0x03;
- rep_data[1] = 0x20;
- ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
- HID_FEATURE_REPORT);
- return;
-}
-static void wacom_poke(struct hid_device *hdev, u8 speed)
+static void wacom_set_features(struct hid_device *hdev, u8 speed)
{
struct wacom_data *wdata = hid_get_drvdata(hdev);
int limit, ret;
- char rep_data[2];
-
- rep_data[0] = 0x03 ; rep_data[1] = 0x00;
- limit = 3;
- do {
- ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
- HID_FEATURE_REPORT);
- } while (ret < 0 && limit-- > 0);
-
- if (ret >= 0) {
- if (speed == 0)
- rep_data[0] = 0x05;
- else
- rep_data[0] = 0x06;
+ __u8 rep_data[2];
- rep_data[1] = 0x00;
+ switch (hdev->product) {
+ case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
+ rep_data[0] = 0x03 ; rep_data[1] = 0x00;
limit = 3;
do {
ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
@@ -162,17 +244,47 @@ static void wacom_poke(struct hid_device *hdev, u8 speed)
} while (ret < 0 && limit-- > 0);
if (ret >= 0) {
- wdata->high_speed = speed;
- return;
+ if (speed == 0)
+ rep_data[0] = 0x05;
+ else
+ rep_data[0] = 0x06;
+
+ rep_data[1] = 0x00;
+ limit = 3;
+ do {
+ ret = hdev->hid_output_raw_report(hdev,
+ rep_data, 2, HID_FEATURE_REPORT);
+ } while (ret < 0 && limit-- > 0);
+
+ if (ret >= 0) {
+ wdata->high_speed = speed;
+ return;
+ }
}
+
+ /*
+ * Note that if the raw queries fail, it's not a hard failure
+ * and it is safe to continue
+ */
+ hid_warn(hdev, "failed to poke device, command %d, err %d\n",
+ rep_data[0], ret);
+ break;
+ case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
+ if (speed == 1)
+ wdata->features &= ~0x20;
+ else
+ wdata->features |= 0x20;
+
+ rep_data[0] = 0x03;
+ rep_data[1] = wdata->features;
+
+ ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
+ HID_FEATURE_REPORT);
+ if (ret >= 0)
+ wdata->high_speed = speed;
+ break;
}
- /*
- * Note that if the raw queries fail, it's not a hard failure and it
- * is safe to continue
- */
- hid_warn(hdev, "failed to poke device, command %d, err %d\n",
- rep_data[0], ret);
return;
}
@@ -196,7 +308,7 @@ static ssize_t wacom_store_speed(struct device *dev,
return -EINVAL;
if (new_speed == 0 || new_speed == 1) {
- wacom_poke(hdev, new_speed);
+ wacom_set_features(hdev, new_speed);
return strnlen(buf, PAGE_SIZE);
} else
return -EINVAL;
@@ -310,12 +422,16 @@ static int wacom_gr_parse_report(struct hid_device *hdev,
input_sync(input);
}
-#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
- /* Store current battery capacity */
+ /* Store current battery capacity and power supply state*/
rw = (data[7] >> 2 & 0x07);
- if (rw != wdata->battery_capacity)
- wdata->battery_capacity = rw;
-#endif
+ if (rw != wdata->power_raw) {
+ wdata->power_raw = rw;
+ wdata->battery_capacity = batcap_gr[rw];
+ if (rw == 7)
+ wdata->ps_connected = 1;
+ else
+ wdata->ps_connected = 0;
+ }
return 1;
}
@@ -369,6 +485,7 @@ static void wacom_i4_parse_pen_report(struct wacom_data *wdata,
{
__u16 x, y, pressure;
__u8 distance;
+ __u8 tilt_x, tilt_y;
switch (data[1]) {
case 0x80: /* Out of proximity report */
@@ -405,6 +522,8 @@ static void wacom_i4_parse_pen_report(struct wacom_data *wdata,
pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5)
| (data[1] & 0x01);
distance = (data[9] >> 2) & 0x3f;
+ tilt_x = ((data[7] << 1) & 0x7e) | (data[8] >> 7);
+ tilt_y = data[8] & 0x7f;
input_report_key(input, BTN_TOUCH, pressure > 1);
@@ -415,6 +534,8 @@ static void wacom_i4_parse_pen_report(struct wacom_data *wdata,
input_report_abs(input, ABS_Y, y);
input_report_abs(input, ABS_PRESSURE, pressure);
input_report_abs(input, ABS_DISTANCE, distance);
+ input_report_abs(input, ABS_TILT_X, tilt_x);
+ input_report_abs(input, ABS_TILT_Y, tilt_y);
input_report_abs(input, ABS_MISC, wdata->id);
input_event(input, EV_MSC, MSC_SERIAL, wdata->serial);
input_report_key(input, wdata->tool, 1);
@@ -455,6 +576,7 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
struct input_dev *input;
unsigned char *data = (unsigned char *) raw_data;
int i;
+ __u8 power_raw;
if (!(hdev->claimed & HID_CLAIMED_INPUT))
return 0;
@@ -462,13 +584,15 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
input = hidinput->input;
- /* Check if this is a tablet report */
- if (data[0] != 0x03)
- return 0;
-
switch (hdev->product) {
case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
- return wacom_gr_parse_report(hdev, wdata, input, data);
+ if (data[0] == 0x03) {
+ return wacom_gr_parse_report(hdev, wdata, input, data);
+ } else {
+ hid_err(hdev, "Unknown report: %d,%d size:%d\n",
+ data[0], data[1], size);
+ return 0;
+ }
break;
case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
i = 1;
@@ -482,6 +606,13 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
wacom_i4_parse_report(hdev, wdata, input, data + i);
i += 10;
wacom_i4_parse_report(hdev, wdata, input, data + i);
+ power_raw = data[i+10];
+ if (power_raw != wdata->power_raw) {
+ wdata->power_raw = power_raw;
+ wdata->battery_capacity = batcap_i4[power_raw & 0x07];
+ wdata->ps_connected = power_raw & 0x08;
+ }
+
break;
default:
hid_err(hdev, "Unknown report: %d,%d size:%d\n",
@@ -546,6 +677,8 @@ static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi,
input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0);
input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0);
input_set_abs_params(input, ABS_DISTANCE, 0, 63, 0, 0);
+ input_set_abs_params(input, ABS_TILT_X, 0, 127, 0, 0);
+ input_set_abs_params(input, ABS_TILT_Y, 0, 127, 0, 0);
break;
}
@@ -584,19 +717,19 @@ static int wacom_probe(struct hid_device *hdev,
hid_warn(hdev,
"can't create sysfs speed attribute err: %d\n", ret);
- switch (hdev->product) {
- case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
- /* Set Wacom mode 2 with high reporting speed */
- wacom_poke(hdev, 1);
- break;
- case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
+ wdata->features = 0;
+ wacom_set_features(hdev, 1);
+
+ if (hdev->product == USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) {
sprintf(hdev->name, "%s", "Wacom Intuos4 WL");
- wdata->features = 0;
- wacom_set_features(hdev);
- break;
+ ret = wacom_initialize_leds(hdev);
+ if (ret) {
+ hid_warn(hdev,
+ "can't create led attribute, err: %d\n", ret);
+ goto destroy_leds;
+ }
}
-#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
wdata->battery.properties = wacom_battery_props;
wdata->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
wdata->battery.get_property = wacom_battery_get_property;
@@ -629,16 +762,15 @@ static int wacom_probe(struct hid_device *hdev,
}
power_supply_powers(&wdata->ac, &hdev->dev);
-#endif
return 0;
-#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
err_ac:
power_supply_unregister(&wdata->battery);
err_battery:
device_remove_file(&hdev->dev, &dev_attr_speed);
hid_hw_stop(hdev);
-#endif
+destroy_leds:
+ wacom_destroy_leds(hdev);
err_free:
kfree(wdata);
return ret;
@@ -646,16 +778,14 @@ err_free:
static void wacom_remove(struct hid_device *hdev)
{
-#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
struct wacom_data *wdata = hid_get_drvdata(hdev);
-#endif
+
+ wacom_destroy_leds(hdev);
device_remove_file(&hdev->dev, &dev_attr_speed);
hid_hw_stop(hdev);
-#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
power_supply_unregister(&wdata->battery);
power_supply_unregister(&wdata->ac);
-#endif
kfree(hid_get_drvdata(hdev));
}
@@ -693,5 +823,5 @@ static void __exit wacom_exit(void)
module_init(wacom_init);
module_exit(wacom_exit);
+MODULE_DESCRIPTION("Driver for Wacom Graphire Bluetooth and Wacom Intuos4 WL");
MODULE_LICENSE("GPL");
-
diff --git a/drivers/hid/hid-waltop.c b/drivers/hid/hid-waltop.c
index 2cfd95c4467b..745e4e9a8cf2 100644
--- a/drivers/hid/hid-waltop.c
+++ b/drivers/hid/hid-waltop.c
@@ -502,28 +502,146 @@ static __u8 media_tablet_14_1_inch_rdesc_fixed[] = {
0xC0 /* End Collection */
};
-struct waltop_state {
- u8 pressure0;
- u8 pressure1;
+/*
+ * See Sirius Battery Free Tablet description, device and HID report descriptors
+ * at
+ * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Sirius_Battery_Free_Tablet
+ */
+
+/* Size of the original report descriptor of Sirius Battery Free Tablet */
+#define SIRIUS_BATTERY_FREE_TABLET_RDESC_ORIG_SIZE 335
+
+/* Fixed Sirius Battery Free Tablet descriptor */
+static __u8 sirius_battery_free_tablet_rdesc_fixed[] = {
+ 0x05, 0x0D, /* Usage Page (Digitizer), */
+ 0x09, 0x02, /* Usage (Pen), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x85, 0x10, /* Report ID (16), */
+ 0x09, 0x20, /* Usage (Stylus), */
+ 0xA0, /* Collection (Physical), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x15, 0x01, /* Logical Minimum (1), */
+ 0x25, 0x03, /* Logical Maximum (3), */
+ 0x75, 0x02, /* Report Size (2), */
+ 0x09, 0x42, /* Usage (Tip Switch), */
+ 0x09, 0x44, /* Usage (Barrel Switch), */
+ 0x09, 0x46, /* Usage (Tablet Pick), */
+ 0x80, /* Input, */
+ 0x14, /* Logical Minimum (0), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x09, 0x3C, /* Usage (Invert), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x09, 0x32, /* Usage (In Range), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0xA4, /* Push, */
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x55, 0xFD, /* Unit Exponent (-3), */
+ 0x65, 0x13, /* Unit (Inch), */
+ 0x34, /* Physical Minimum (0), */
+ 0x14, /* Logical Minimum (0), */
+ 0x75, 0x10, /* Report Size (16), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x46, 0x10, 0x27, /* Physical Maximum (10000), */
+ 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */
+ 0x09, 0x30, /* Usage (X), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x46, 0x70, 0x17, /* Physical Maximum (6000), */
+ 0x26, 0xE0, 0x2E, /* Logical Maximum (12000), */
+ 0x09, 0x31, /* Usage (Y), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xB4, /* Pop, */
+ 0x75, 0x10, /* Report Size (16), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x14, /* Logical Minimum (0), */
+ 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
+ 0x09, 0x30, /* Usage (Tip Pressure), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xA4, /* Push, */
+ 0x55, 0xFE, /* Unit Exponent (-2), */
+ 0x65, 0x12, /* Unit (Radians), */
+ 0x35, 0x97, /* Physical Minimum (-105), */
+ 0x45, 0x69, /* Physical Maximum (105), */
+ 0x15, 0x97, /* Logical Minimum (-105), */
+ 0x25, 0x69, /* Logical Maximum (105), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x02, /* Report Count (2), */
+ 0x09, 0x3D, /* Usage (X Tilt), */
+ 0x09, 0x3E, /* Usage (Y Tilt), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xB4, /* Pop, */
+ 0xC0, /* End Collection, */
+ 0xC0, /* End Collection, */
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x09, 0x02, /* Usage (Mouse), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x85, 0x01, /* Report ID (1), */
+ 0x09, 0x01, /* Usage (Pointer), */
+ 0xA0, /* Collection (Physical), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x09, 0x38, /* Usage (Wheel), */
+ 0x15, 0xFF, /* Logical Minimum (-1), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x81, 0x06, /* Input (Variable, Relative), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0xC0, /* End Collection, */
+ 0xC0, /* End Collection, */
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x09, 0x06, /* Usage (Keyboard), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x85, 0x0D, /* Report ID (13), */
+ 0x05, 0x07, /* Usage Page (Keyboard), */
+ 0x19, 0xE0, /* Usage Minimum (KB Leftcontrol), */
+ 0x29, 0xE7, /* Usage Maximum (KB Right GUI), */
+ 0x14, /* Logical Minimum (0), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x95, 0x08, /* Report Count (8), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x81, 0x01, /* Input (Constant), */
+ 0x18, /* Usage Minimum (None), */
+ 0x29, 0x65, /* Usage Maximum (KB Application), */
+ 0x14, /* Logical Minimum (0), */
+ 0x25, 0x65, /* Logical Maximum (101), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x05, /* Report Count (5), */
+ 0x80, /* Input, */
+ 0xC0, /* End Collection, */
+ 0x05, 0x0C, /* Usage Page (Consumer), */
+ 0x09, 0x01, /* Usage (Consumer Control), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x85, 0x0C, /* Report ID (12), */
+ 0x09, 0xE9, /* Usage (Volume Inc), */
+ 0x09, 0xEA, /* Usage (Volume Dec), */
+ 0x14, /* Logical Minimum (0), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x95, 0x02, /* Report Count (2), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x75, 0x06, /* Report Size (6), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x75, 0x10, /* Report Size (16), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0xC0 /* End Collection */
};
static int waltop_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
int ret;
- struct waltop_state *s;
-
- s = kzalloc(sizeof(*s), GFP_KERNEL);
- if (s == NULL) {
- hid_err(hdev, "can't allocate device state\n");
- ret = -ENOMEM;
- goto err;
- }
-
- s->pressure0 = 0;
- s->pressure1 = 0;
-
- hid_set_drvdata(hdev, s);
ret = hid_parse(hdev);
if (ret) {
@@ -539,7 +657,6 @@ static int waltop_probe(struct hid_device *hdev,
return 0;
err:
- kfree(s);
return ret;
}
@@ -583,6 +700,12 @@ static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*rsize = sizeof(media_tablet_14_1_inch_rdesc_fixed);
}
break;
+ case USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET:
+ if (*rsize == SIRIUS_BATTERY_FREE_TABLET_RDESC_ORIG_SIZE) {
+ rdesc = sirius_battery_free_tablet_rdesc_fixed;
+ *rsize = sizeof(sirius_battery_free_tablet_rdesc_fixed);
+ }
+ break;
}
return rdesc;
}
@@ -590,39 +713,72 @@ static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc,
static int waltop_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *data, int size)
{
- /* If this is a pen input report of a tablet with PID 0038 */
- if (hdev->product == USB_DEVICE_ID_WALTOP_PID_0038 &&
- report->type == HID_INPUT_REPORT &&
- report->id == 16 &&
- size == 8) {
- struct waltop_state *s = hid_get_drvdata(hdev);
-
+ /* If this is a pen input report */
+ if (report->type == HID_INPUT_REPORT && report->id == 16 && size >= 8) {
/*
- * Ignore maximum pressure reported when a barrel button is
- * pressed.
+ * Ignore reported pressure when a barrel button is pressed,
+ * because it is rarely correct.
*/
/* If a barrel button is pressed */
if ((data[1] & 0xF) > 1) {
- /* Use the last known pressure */
- data[6] = s->pressure0;
- data[7] = s->pressure1;
- } else {
- /* Remember reported pressure */
- s->pressure0 = data[6];
- s->pressure1 = data[7];
+ /* Report zero pressure */
+ data[6] = 0;
+ data[7] = 0;
}
}
+ /* If this is a pen input report of Sirius Battery Free Tablet */
+ if (hdev->product == USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET &&
+ report->type == HID_INPUT_REPORT &&
+ report->id == 16 &&
+ size == 10) {
+ /*
+ * The tablet reports tilt as roughly sin(a)*21 (18 means 60
+ * degrees).
+ *
+ * This array stores angles as radians * 100, corresponding to
+ * reported values up to 60 degrees, as expected by userspace.
+ */
+ static const s8 tilt_to_radians[] = {
+ 0, 5, 10, 14, 19, 24, 29, 34, 40, 45,
+ 50, 56, 62, 68, 74, 81, 88, 96, 105
+ };
+
+ s8 tilt_x = (s8)data[8];
+ s8 tilt_y = (s8)data[9];
+ s8 sign_x = tilt_x >= 0 ? 1 : -1;
+ s8 sign_y = tilt_y >= 0 ? 1 : -1;
+
+ tilt_x *= sign_x;
+ tilt_y *= sign_y;
+
+ /*
+ * Reverse the Y Tilt direction to match the HID standard and
+ * userspace expectations. See HID Usage Tables v1.12 16.3.2
+ * Tilt Orientation.
+ */
+ sign_y *= -1;
+
+ /*
+ * This effectively clamps reported tilt to 60 degrees - the
+ * range expected by userspace
+ */
+ if (tilt_x > ARRAY_SIZE(tilt_to_radians) - 1)
+ tilt_x = ARRAY_SIZE(tilt_to_radians) - 1;
+ if (tilt_y > ARRAY_SIZE(tilt_to_radians) - 1)
+ tilt_y = ARRAY_SIZE(tilt_to_radians) - 1;
+
+ data[8] = tilt_to_radians[tilt_x] * sign_x;
+ data[9] = tilt_to_radians[tilt_y] * sign_y;
+ }
+
return 0;
}
static void waltop_remove(struct hid_device *hdev)
{
- struct waltop_state *s = hid_get_drvdata(hdev);
-
hid_hw_stop(hdev);
- kfree(s);
}
static const struct hid_device_id waltop_devices[] = {
@@ -638,6 +794,8 @@ static const struct hid_device_id waltop_devices[] = {
USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
+ USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) },
{ }
};
MODULE_DEVICE_TABLE(hid, waltop_devices);
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index cac3589b1ed5..84e2fbec5fbb 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -769,7 +769,7 @@ static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir,
/*
* Basic IR data is encoded into 3 bytes. The first two bytes are the
- * upper 8 bit of the X/Y data, the 3rd byte contains the lower 2 bits
+ * lower 8 bit of the X/Y data, the 3rd byte contains the upper 2 bits
* of both.
* If data is packed, then the 3rd byte is put first and slightly
* reordered. This allows to interleave packed and non-packed data to
@@ -778,17 +778,11 @@ static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir,
*/
if (packed) {
- x = ir[1] << 2;
- y = ir[2] << 2;
-
- x |= ir[0] & 0x3;
- y |= (ir[0] >> 2) & 0x3;
+ x = ir[1] | ((ir[0] & 0x03) << 8);
+ y = ir[2] | ((ir[0] & 0x0c) << 6);
} else {
- x = ir[0] << 2;
- y = ir[1] << 2;
-
- x |= (ir[2] >> 4) & 0x3;
- y |= (ir[2] >> 6) & 0x3;
+ x = ir[0] | ((ir[2] & 0x30) << 4);
+ y = ir[1] | ((ir[2] & 0xc0) << 2);
}
input_report_abs(wdata->ir, xid, x);
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index cf7d6d58e79f..36fa77b40ffb 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -87,11 +87,13 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
len = list->buffer[list->tail].len > count ?
count : list->buffer[list->tail].len;
- if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
- ret = -EFAULT;
- goto out;
+ if (list->buffer[list->tail].value) {
+ if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ ret = len;
}
- ret = len;
kfree(list->buffer[list->tail].value);
list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
@@ -437,19 +439,24 @@ static const struct file_operations hidraw_ops = {
.llseek = noop_llseek,
};
-void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
+int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
{
struct hidraw *dev = hid->hidraw;
struct hidraw_list *list;
+ int ret = 0;
list_for_each_entry(list, &dev->list, node) {
- list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC);
+ if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) {
+ ret = -ENOMEM;
+ break;
+ }
list->buffer[list->head].len = len;
list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
kill_fasync(&list->fasync, SIGIO, POLL_IN);
}
wake_up_interruptible(&dev->wait);
+ return ret;
}
EXPORT_SYMBOL_GPL(hidraw_report_event);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 5bf91dbad59d..482f936fc29b 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -28,6 +28,7 @@
#include <linux/input.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
+#include <linux/string.h>
#include <linux/usb.h>
@@ -86,8 +87,13 @@ static int hid_start_in(struct hid_device *hid)
!test_bit(HID_REPORTED_IDLE, &usbhid->iofl) &&
!test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
- if (rc != 0)
+ if (rc != 0) {
clear_bit(HID_IN_RUNNING, &usbhid->iofl);
+ if (rc == -ENOSPC)
+ set_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
+ } else {
+ clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
+ }
}
spin_unlock_irqrestore(&usbhid->lock, flags);
return rc;
@@ -173,8 +179,10 @@ static void hid_io_error(struct hid_device *hid)
if (time_after(jiffies, usbhid->stop_retry)) {
- /* Retries failed, so do a port reset */
- if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {
+ /* Retries failed, so do a port reset unless we lack bandwidth*/
+ if (test_bit(HID_NO_BANDWIDTH, &usbhid->iofl)
+ && !test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {
+
schedule_work(&usbhid->reset_work);
goto done;
}
@@ -203,7 +211,7 @@ static int usbhid_restart_out_queue(struct usbhid_device *usbhid)
return 0;
if ((kicked = (usbhid->outhead != usbhid->outtail))) {
- dbg("Kicking head %d tail %d", usbhid->outhead, usbhid->outtail);
+ hid_dbg(hid, "Kicking head %d tail %d", usbhid->outhead, usbhid->outtail);
r = usb_autopm_get_interface_async(usbhid->intf);
if (r < 0)
@@ -230,7 +238,7 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid)
return 0;
if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) {
- dbg("Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail);
+ hid_dbg(hid, "Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail);
r = usb_autopm_get_interface_async(usbhid->intf);
if (r < 0)
@@ -399,6 +407,16 @@ static int hid_submit_ctrl(struct hid_device *hid)
* Output interrupt completion handler.
*/
+static int irq_out_pump_restart(struct hid_device *hid)
+{
+ struct usbhid_device *usbhid = hid->driver_data;
+
+ if (usbhid->outhead != usbhid->outtail)
+ return hid_submit_out(hid);
+ else
+ return -1;
+}
+
static void hid_irq_out(struct urb *urb)
{
struct hid_device *hid = urb->context;
@@ -428,7 +446,7 @@ static void hid_irq_out(struct urb *urb)
else
usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
- if (usbhid->outhead != usbhid->outtail && !hid_submit_out(hid)) {
+ if (!irq_out_pump_restart(hid)) {
/* Successfully submitted next urb in queue */
spin_unlock_irqrestore(&usbhid->lock, flags);
return;
@@ -443,6 +461,15 @@ static void hid_irq_out(struct urb *urb)
/*
* Control pipe completion handler.
*/
+static int ctrl_pump_restart(struct hid_device *hid)
+{
+ struct usbhid_device *usbhid = hid->driver_data;
+
+ if (usbhid->ctrlhead != usbhid->ctrltail)
+ return hid_submit_ctrl(hid);
+ else
+ return -1;
+}
static void hid_ctrl(struct urb *urb)
{
@@ -476,7 +503,7 @@ static void hid_ctrl(struct urb *urb)
else
usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
- if (usbhid->ctrlhead != usbhid->ctrltail && !hid_submit_ctrl(hid)) {
+ if (!ctrl_pump_restart(hid)) {
/* Successfully submitted next urb in queue */
spin_unlock(&usbhid->lock);
return;
@@ -535,11 +562,27 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
* the queue is known to run
* but an earlier request may be stuck
* we may need to time out
- * no race because this is called under
+ * no race because the URB is blocked under
* spinlock
*/
- if (time_after(jiffies, usbhid->last_out + HZ * 5))
+ if (time_after(jiffies, usbhid->last_out + HZ * 5)) {
+ usb_block_urb(usbhid->urbout);
+ /* drop lock to not deadlock if the callback is called */
+ spin_unlock(&usbhid->lock);
usb_unlink_urb(usbhid->urbout);
+ spin_lock(&usbhid->lock);
+ usb_unblock_urb(usbhid->urbout);
+ /*
+ * if the unlinking has already completed
+ * the pump will have been stopped
+ * it must be restarted now
+ */
+ if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl))
+ if (!irq_out_pump_restart(hid))
+ set_bit(HID_OUT_RUNNING, &usbhid->iofl);
+
+
+ }
}
return;
}
@@ -583,11 +626,25 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
* the queue is known to run
* but an earlier request may be stuck
* we may need to time out
- * no race because this is called under
+ * no race because the URB is blocked under
* spinlock
*/
- if (time_after(jiffies, usbhid->last_ctrl + HZ * 5))
+ if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) {
+ usb_block_urb(usbhid->urbctrl);
+ /* drop lock to not deadlock if the callback is called */
+ spin_unlock(&usbhid->lock);
usb_unlink_urb(usbhid->urbctrl);
+ spin_lock(&usbhid->lock);
+ usb_unblock_urb(usbhid->urbctrl);
+ /*
+ * if the unlinking has already completed
+ * the pump will have been stopped
+ * it must be restarted now
+ */
+ if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
+ if (!ctrl_pump_restart(hid))
+ set_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+ }
}
}
@@ -700,7 +757,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
int usbhid_open(struct hid_device *hid)
{
struct usbhid_device *usbhid = hid->driver_data;
- int res;
+ int res = 0;
mutex_lock(&hid_open_mut);
if (!hid->open++) {
@@ -708,17 +765,27 @@ int usbhid_open(struct hid_device *hid)
/* the device must be awake to reliably request remote wakeup */
if (res < 0) {
hid->open--;
- mutex_unlock(&hid_open_mut);
- return -EIO;
+ res = -EIO;
+ goto done;
}
usbhid->intf->needs_remote_wakeup = 1;
- if (hid_start_in(hid))
- hid_io_error(hid);
-
+ res = hid_start_in(hid);
+ if (res) {
+ if (res != -ENOSPC) {
+ hid_io_error(hid);
+ res = 0;
+ } else {
+ /* no use opening if resources are insufficient */
+ hid->open--;
+ res = -EBUSY;
+ usbhid->intf->needs_remote_wakeup = 0;
+ }
+ }
usb_autopm_put_interface(usbhid->intf);
}
+done:
mutex_unlock(&hid_open_mut);
- return 0;
+ return res;
}
void usbhid_close(struct hid_device *hid)
@@ -1347,7 +1414,34 @@ static int hid_post_reset(struct usb_interface *intf)
struct usb_device *dev = interface_to_usbdev (intf);
struct hid_device *hid = usb_get_intfdata(intf);
struct usbhid_device *usbhid = hid->driver_data;
+ struct usb_host_interface *interface = intf->cur_altsetting;
int status;
+ char *rdesc;
+
+ /* Fetch and examine the HID report descriptor. If this
+ * has changed, then rebind. Since usbcore's check of the
+ * configuration descriptors passed, we already know that
+ * the size of the HID report descriptor has not changed.
+ */
+ rdesc = kmalloc(hid->rsize, GFP_KERNEL);
+ if (!rdesc) {
+ dbg_hid("couldn't allocate rdesc memory (post_reset)\n");
+ return 1;
+ }
+ status = hid_get_class_descriptor(dev,
+ interface->desc.bInterfaceNumber,
+ HID_DT_REPORT, rdesc, hid->rsize);
+ if (status < 0) {
+ dbg_hid("reading report descriptor failed (post_reset)\n");
+ kfree(rdesc);
+ return 1;
+ }
+ status = memcmp(rdesc, hid->rdesc, hid->rsize);
+ kfree(rdesc);
+ if (status != 0) {
+ dbg_hid("report descriptor changed\n");
+ return 1;
+ }
spin_lock_irq(&usbhid->lock);
clear_bit(HID_RESET_PENDING, &usbhid->iofl);
@@ -1504,28 +1598,15 @@ static struct usb_driver hid_driver = {
.supports_autosuspend = 1,
};
-static const struct hid_device_id hid_usb_table[] = {
- { HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) },
- { }
-};
-
struct usb_interface *usbhid_find_interface(int minor)
{
return usb_find_interface(&hid_driver, minor);
}
-static struct hid_driver hid_usb_driver = {
- .name = "generic-usb",
- .id_table = hid_usb_table,
-};
-
static int __init hid_init(void)
{
int retval = -ENOMEM;
- retval = hid_register_driver(&hid_usb_driver);
- if (retval)
- goto hid_register_fail;
retval = usbhid_quirks_init(quirks_param);
if (retval)
goto usbhid_quirks_init_fail;
@@ -1538,8 +1619,6 @@ static int __init hid_init(void)
usb_register_fail:
usbhid_quirks_exit();
usbhid_quirks_init_fail:
- hid_unregister_driver(&hid_usb_driver);
-hid_register_fail:
return retval;
}
@@ -1547,7 +1626,6 @@ static void __exit hid_exit(void)
{
usb_deregister(&hid_driver);
usbhid_quirks_exit();
- hid_unregister_driver(&hid_usb_driver);
}
module_init(hid_init);
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 782c63955f29..0597ee604f6e 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -88,6 +88,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT },
+ { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index b1ec0e2aeb57..14599e256791 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -34,6 +34,7 @@
#include <linux/hid.h>
#include <linux/hiddev.h>
#include <linux/compat.h>
+#include <linux/vmalloc.h>
#include "usbhid.h"
#ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -250,13 +251,13 @@ static int hiddev_release(struct inode * inode, struct file * file)
} else {
mutex_unlock(&list->hiddev->existancelock);
kfree(list->hiddev);
- kfree(list);
+ vfree(list);
return 0;
}
}
mutex_unlock(&list->hiddev->existancelock);
- kfree(list);
+ vfree(list);
return 0;
}
@@ -278,7 +279,7 @@ static int hiddev_open(struct inode *inode, struct file *file)
hid = usb_get_intfdata(intf);
hiddev = hid->hiddev;
- if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
+ if (!(list = vzalloc(sizeof(struct hiddev_list))))
return -ENOMEM;
mutex_init(&list->thread_lock);
list->hiddev = hiddev;
@@ -322,7 +323,7 @@ bail_unlock:
mutex_unlock(&hiddev->existancelock);
bail:
file->private_data = NULL;
- kfree(list);
+ vfree(list);
return res;
}
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index cb8f703efde5..1883d7b94870 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -55,6 +55,7 @@ struct usb_interface *usbhid_find_interface(int minor);
#define HID_STARTED 8
#define HID_REPORTED_IDLE 9
#define HID_KEYS_PRESSED 10
+#define HID_NO_BANDWIDTH 11
/*
* USB-specific HID struct, to be pointed to
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c
index 0f6be45d43d5..bf16d72dc370 100644
--- a/drivers/hid/usbhid/usbmouse.c
+++ b/drivers/hid/usbhid/usbmouse.c
@@ -92,9 +92,10 @@ static void usb_mouse_irq(struct urb *urb)
resubmit:
status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
- err ("can't resubmit intr, %s-%s/input0, status %d",
- mouse->usbdev->bus->bus_name,
- mouse->usbdev->devpath, status);
+ dev_err(&mouse->usbdev->dev,
+ "can't resubmit intr, %s-%s/input0, status %d\n",
+ mouse->usbdev->bus->bus_name,
+ mouse->usbdev->devpath, status);
}
static int usb_mouse_open(struct input_dev *dev)
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 9ffbfc575a0c..2b8b8d4558d2 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -46,40 +46,61 @@ struct vmbus_channel_message_table_entry {
*
* @icmsghdrp is of type &struct icmsg_hdr.
* @negop is of type &struct icmsg_negotiate.
- * Set up and fill in default negotiate response message. This response can
- * come from both the vmbus driver and the hv_utils driver. The current api
- * will respond properly to both Windows 2008 and Windows 2008-R2 operating
- * systems.
+ * Set up and fill in default negotiate response message.
+ *
+ * The max_fw_version specifies the maximum framework version that
+ * we can support and max _srv_version specifies the maximum service
+ * version we can support. A special value MAX_SRV_VER can be
+ * specified to indicate that we can handle the maximum version
+ * exposed by the host.
*
* Mainly used by Hyper-V drivers.
*/
void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
- struct icmsg_negotiate *negop, u8 *buf)
+ struct icmsg_negotiate *negop, u8 *buf,
+ int max_fw_version, int max_srv_version)
{
- if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- icmsghdrp->icmsgsize = 0x10;
-
- negop = (struct icmsg_negotiate *)&buf[
- sizeof(struct vmbuspipe_hdr) +
- sizeof(struct icmsg_hdr)];
-
- if (negop->icframe_vercnt == 2 &&
- negop->icversion_data[1].major == 3) {
- negop->icversion_data[0].major = 3;
- negop->icversion_data[0].minor = 0;
- negop->icversion_data[1].major = 3;
- negop->icversion_data[1].minor = 0;
- } else {
- negop->icversion_data[0].major = 1;
- negop->icversion_data[0].minor = 0;
- negop->icversion_data[1].major = 1;
- negop->icversion_data[1].minor = 0;
- }
+ int icframe_vercnt;
+ int icmsg_vercnt;
+ int i;
+
+ icmsghdrp->icmsgsize = 0x10;
+
+ negop = (struct icmsg_negotiate *)&buf[
+ sizeof(struct vmbuspipe_hdr) +
+ sizeof(struct icmsg_hdr)];
+
+ icframe_vercnt = negop->icframe_vercnt;
+ icmsg_vercnt = negop->icmsg_vercnt;
+
+ /*
+ * Select the framework version number we will
+ * support.
+ */
+
+ for (i = 0; i < negop->icframe_vercnt; i++) {
+ if (negop->icversion_data[i].major <= max_fw_version)
+ icframe_vercnt = negop->icversion_data[i].major;
+ }
- negop->icframe_vercnt = 1;
- negop->icmsg_vercnt = 1;
+ for (i = negop->icframe_vercnt;
+ (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) {
+ if (negop->icversion_data[i].major <= max_srv_version)
+ icmsg_vercnt = negop->icversion_data[i].major;
}
+
+ /*
+ * Respond with the maximum framework and service
+ * version numbers we can support.
+ */
+ negop->icframe_vercnt = 1;
+ negop->icmsg_vercnt = 1;
+ negop->icversion_data[0].major = icframe_vercnt;
+ negop->icversion_data[0].minor = 0;
+ negop->icversion_data[1].major = icmsg_vercnt;
+ negop->icversion_data[1].minor = 0;
}
+
EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp);
/*
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 15956bd48b48..86f8885aeb45 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -252,7 +252,7 @@ void hv_cleanup(void)
*
* This involves a hypercall.
*/
-u16 hv_post_message(union hv_connection_id connection_id,
+int hv_post_message(union hv_connection_id connection_id,
enum hv_message_type message_type,
void *payload, size_t payload_size)
{
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 6186025209ce..0012eed6d872 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -394,7 +394,8 @@ void hv_kvp_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer);
+ vmbus_prep_negotiate_resp(icmsghdrp, negop,
+ recv_buffer, MAX_SRV_VER, MAX_SRV_VER);
} else {
kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
sizeof(struct vmbuspipe_hdr) +
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index dbb8b8eec210..d3ac6a40118b 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -70,7 +70,8 @@ static void shutdown_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- vmbus_prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
+ vmbus_prep_negotiate_resp(icmsghdrp, negop,
+ shut_txf_buf, MAX_SRV_VER, MAX_SRV_VER);
} else {
shutdown_msg =
(struct shutdown_msg_data *)&shut_txf_buf[
@@ -195,7 +196,8 @@ static void timesync_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
+ vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf,
+ MAX_SRV_VER, MAX_SRV_VER);
} else {
timedatap = (struct ictimesync_data *)&time_txf_buf[
sizeof(struct vmbuspipe_hdr) +
@@ -234,7 +236,8 @@ static void heartbeat_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- vmbus_prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
+ vmbus_prep_negotiate_resp(icmsghdrp, NULL,
+ hbeat_txf_buf, MAX_SRV_VER, MAX_SRV_VER);
} else {
heartbeat_msg =
(struct heartbeat_msg_data *)&hbeat_txf_buf[
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 699f0d8e59ed..b9426a6592ee 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -495,7 +495,7 @@ extern int hv_init(void);
extern void hv_cleanup(void);
-extern u16 hv_post_message(union hv_connection_id connection_id,
+extern int hv_post_message(union hv_connection_id connection_id,
enum hv_message_type message_type,
void *payload, size_t payload_size);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 8deedc1b9840..7cd9bf42108b 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -318,7 +318,7 @@ config SENSORS_EXYNOS4_TMU
tristate "Temperature sensor on Samsung EXYNOS4"
depends on ARCH_EXYNOS4
help
- If you say yes here you get support for TMU (Thermal Managment
+ If you say yes here you get support for TMU (Thermal Management
Unit) on SAMSUNG EXYNOS4 series of SoC.
This driver can also be built as a module. If so, the module
@@ -1102,6 +1102,19 @@ config SENSORS_AMC6821
This driver can also be build as a module. If so, the module
will be called amc6821.
+config SENSORS_INA2XX
+ tristate "Texas Instruments INA219, INA226"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for INA219 and INA226 power
+ monitor chips.
+
+ The INA2xx driver is configured for the default configuration of
+ the part as described in the datasheet.
+ Default value for Rshunt is 10 mOhms.
+ This driver can also be built as a module. If so, the module
+ will be called ina2xx.
+
config SENSORS_THMC50
tristate "Texas Instruments THMC50 / Analog Devices ADM1022"
depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 6d3f11f71815..e1eeac13b851 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
+obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_JC42) += jc42.o
obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o
diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c
index 9140236a0182..34ad5a27a7e9 100644
--- a/drivers/hwmon/acpi_power_meter.c
+++ b/drivers/hwmon/acpi_power_meter.c
@@ -107,15 +107,7 @@ struct acpi_power_meter_resource {
struct kobject *holders_dir;
};
-struct ro_sensor_template {
- char *label;
- ssize_t (*show)(struct device *dev,
- struct device_attribute *devattr,
- char *buf);
- int index;
-};
-
-struct rw_sensor_template {
+struct sensor_template {
char *label;
ssize_t (*show)(struct device *dev,
struct device_attribute *devattr,
@@ -469,52 +461,67 @@ static ssize_t show_name(struct device *dev,
return sprintf(buf, "%s\n", ACPI_POWER_METER_NAME);
}
+#define RO_SENSOR_TEMPLATE(_label, _show, _index) \
+ { \
+ .label = _label, \
+ .show = _show, \
+ .index = _index, \
+ }
+
+#define RW_SENSOR_TEMPLATE(_label, _show, _set, _index) \
+ { \
+ .label = _label, \
+ .show = _show, \
+ .set = _set, \
+ .index = _index, \
+ }
+
/* Sensor descriptions. If you add a sensor, update NUM_SENSORS above! */
-static struct ro_sensor_template meter_ro_attrs[] = {
-{POWER_AVERAGE_NAME, show_power, 0},
-{"power1_accuracy", show_accuracy, 0},
-{"power1_average_interval_min", show_val, 0},
-{"power1_average_interval_max", show_val, 1},
-{"power1_is_battery", show_val, 5},
-{NULL, NULL, 0},
+static struct sensor_template meter_attrs[] = {
+ RO_SENSOR_TEMPLATE(POWER_AVERAGE_NAME, show_power, 0),
+ RO_SENSOR_TEMPLATE("power1_accuracy", show_accuracy, 0),
+ RO_SENSOR_TEMPLATE("power1_average_interval_min", show_val, 0),
+ RO_SENSOR_TEMPLATE("power1_average_interval_max", show_val, 1),
+ RO_SENSOR_TEMPLATE("power1_is_battery", show_val, 5),
+ RW_SENSOR_TEMPLATE(POWER_AVG_INTERVAL_NAME, show_avg_interval,
+ set_avg_interval, 0),
+ {},
};
-static struct rw_sensor_template meter_rw_attrs[] = {
-{POWER_AVG_INTERVAL_NAME, show_avg_interval, set_avg_interval, 0},
-{NULL, NULL, NULL, 0},
+static struct sensor_template misc_cap_attrs[] = {
+ RO_SENSOR_TEMPLATE("power1_cap_min", show_val, 2),
+ RO_SENSOR_TEMPLATE("power1_cap_max", show_val, 3),
+ RO_SENSOR_TEMPLATE("power1_cap_hyst", show_val, 4),
+ RO_SENSOR_TEMPLATE(POWER_ALARM_NAME, show_val, 6),
+ {},
};
-static struct ro_sensor_template misc_cap_attrs[] = {
-{"power1_cap_min", show_val, 2},
-{"power1_cap_max", show_val, 3},
-{"power1_cap_hyst", show_val, 4},
-{POWER_ALARM_NAME, show_val, 6},
-{NULL, NULL, 0},
+static struct sensor_template ro_cap_attrs[] = {
+ RO_SENSOR_TEMPLATE(POWER_CAP_NAME, show_cap, 0),
+ {},
};
-static struct ro_sensor_template ro_cap_attrs[] = {
-{POWER_CAP_NAME, show_cap, 0},
-{NULL, NULL, 0},
+static struct sensor_template rw_cap_attrs[] = {
+ RW_SENSOR_TEMPLATE(POWER_CAP_NAME, show_cap, set_cap, 0),
+ {},
};
-static struct rw_sensor_template rw_cap_attrs[] = {
-{POWER_CAP_NAME, show_cap, set_cap, 0},
-{NULL, NULL, NULL, 0},
+static struct sensor_template trip_attrs[] = {
+ RW_SENSOR_TEMPLATE("power1_average_min", show_val, set_trip, 7),
+ RW_SENSOR_TEMPLATE("power1_average_max", show_val, set_trip, 8),
+ {},
};
-static struct rw_sensor_template trip_attrs[] = {
-{"power1_average_min", show_val, set_trip, 7},
-{"power1_average_max", show_val, set_trip, 8},
-{NULL, NULL, NULL, 0},
+static struct sensor_template misc_attrs[] = {
+ RO_SENSOR_TEMPLATE("name", show_name, 0),
+ RO_SENSOR_TEMPLATE("power1_model_number", show_str, 0),
+ RO_SENSOR_TEMPLATE("power1_oem_info", show_str, 2),
+ RO_SENSOR_TEMPLATE("power1_serial_number", show_str, 1),
+ {},
};
-static struct ro_sensor_template misc_attrs[] = {
-{"name", show_name, 0},
-{"power1_model_number", show_str, 0},
-{"power1_oem_info", show_str, 2},
-{"power1_serial_number", show_str, 1},
-{NULL, NULL, 0},
-};
+#undef RO_SENSOR_TEMPLATE
+#undef RW_SENSOR_TEMPLATE
/* Read power domain data */
static void remove_domain_devices(struct acpi_power_meter_resource *resource)
@@ -619,49 +626,24 @@ end:
}
/* Registration and deregistration */
-static int register_ro_attrs(struct acpi_power_meter_resource *resource,
- struct ro_sensor_template *ro)
+static int register_attrs(struct acpi_power_meter_resource *resource,
+ struct sensor_template *attrs)
{
struct device *dev = &resource->acpi_dev->dev;
struct sensor_device_attribute *sensors =
&resource->sensors[resource->num_sensors];
int res = 0;
- while (ro->label) {
- sensors->dev_attr.attr.name = ro->label;
+ while (attrs->label) {
+ sensors->dev_attr.attr.name = attrs->label;
sensors->dev_attr.attr.mode = S_IRUGO;
- sensors->dev_attr.show = ro->show;
- sensors->index = ro->index;
+ sensors->dev_attr.show = attrs->show;
+ sensors->index = attrs->index;
- sysfs_attr_init(&sensors->dev_attr.attr);
- res = device_create_file(dev, &sensors->dev_attr);
- if (res) {
- sensors->dev_attr.attr.name = NULL;
- goto error;
+ if (attrs->set) {
+ sensors->dev_attr.attr.mode |= S_IWUSR;
+ sensors->dev_attr.store = attrs->set;
}
- sensors++;
- resource->num_sensors++;
- ro++;
- }
-
-error:
- return res;
-}
-
-static int register_rw_attrs(struct acpi_power_meter_resource *resource,
- struct rw_sensor_template *rw)
-{
- struct device *dev = &resource->acpi_dev->dev;
- struct sensor_device_attribute *sensors =
- &resource->sensors[resource->num_sensors];
- int res = 0;
-
- while (rw->label) {
- sensors->dev_attr.attr.name = rw->label;
- sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR;
- sensors->dev_attr.show = rw->show;
- sensors->dev_attr.store = rw->set;
- sensors->index = rw->index;
sysfs_attr_init(&sensors->dev_attr.attr);
res = device_create_file(dev, &sensors->dev_attr);
@@ -671,7 +653,7 @@ static int register_rw_attrs(struct acpi_power_meter_resource *resource,
}
sensors++;
resource->num_sensors++;
- rw++;
+ attrs++;
}
error:
@@ -703,10 +685,7 @@ static int setup_attrs(struct acpi_power_meter_resource *resource)
return res;
if (resource->caps.flags & POWER_METER_CAN_MEASURE) {
- res = register_ro_attrs(resource, meter_ro_attrs);
- if (res)
- goto error;
- res = register_rw_attrs(resource, meter_rw_attrs);
+ res = register_attrs(resource, meter_attrs);
if (res)
goto error;
}
@@ -718,28 +697,27 @@ static int setup_attrs(struct acpi_power_meter_resource *resource)
goto skip_unsafe_cap;
}
- if (resource->caps.configurable_cap) {
- res = register_rw_attrs(resource, rw_cap_attrs);
- if (res)
- goto error;
- } else {
- res = register_ro_attrs(resource, ro_cap_attrs);
- if (res)
- goto error;
- }
- res = register_ro_attrs(resource, misc_cap_attrs);
+ if (resource->caps.configurable_cap)
+ res = register_attrs(resource, rw_cap_attrs);
+ else
+ res = register_attrs(resource, ro_cap_attrs);
+
+ if (res)
+ goto error;
+
+ res = register_attrs(resource, misc_cap_attrs);
if (res)
goto error;
}
-skip_unsafe_cap:
+skip_unsafe_cap:
if (resource->caps.flags & POWER_METER_CAN_TRIP) {
- res = register_rw_attrs(resource, trip_attrs);
+ res = register_attrs(resource, trip_attrs);
if (res)
goto error;
}
- res = register_ro_attrs(resource, misc_attrs);
+ res = register_attrs(resource, misc_attrs);
if (res)
goto error;
diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c
index f85ce70d9677..cfec802cf9ca 100644
--- a/drivers/hwmon/ad7314.c
+++ b/drivers/hwmon/ad7314.c
@@ -18,21 +18,14 @@
#include <linux/hwmon-sysfs.h>
/*
- * AD7314 power mode
- */
-#define AD7314_PD 0x2000
-
-/*
* AD7314 temperature masks
*/
-#define AD7314_TEMP_SIGN 0x200
#define AD7314_TEMP_MASK 0x7FE0
-#define AD7314_TEMP_OFFSET 5
+#define AD7314_TEMP_SHIFT 5
/*
* ADT7301 and ADT7302 temperature masks
*/
-#define ADT7301_TEMP_SIGN 0x2000
#define ADT7301_TEMP_MASK 0x3FFF
enum ad7314_variant {
@@ -73,7 +66,7 @@ static ssize_t ad7314_show_temperature(struct device *dev,
return ret;
switch (spi_get_device_id(chip->spi_dev)->driver_data) {
case ad7314:
- data = (ret & AD7314_TEMP_MASK) >> AD7314_TEMP_OFFSET;
+ data = (ret & AD7314_TEMP_MASK) >> AD7314_TEMP_SHIFT;
data = (data << 6) >> 6;
return sprintf(buf, "%d\n", 250 * data);
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index e8e18cab1fb8..6b13f1a4dc27 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -257,15 +257,4 @@ static struct pci_driver fam15h_power_driver = {
.remove = __devexit_p(fam15h_power_remove),
};
-static int __init fam15h_power_init(void)
-{
- return pci_register_driver(&fam15h_power_driver);
-}
-
-static void __exit fam15h_power_exit(void)
-{
- pci_unregister_driver(&fam15h_power_driver);
-}
-
-module_init(fam15h_power_init)
-module_exit(fam15h_power_exit)
+module_pci_driver(fam15h_power_driver);
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
new file mode 100644
index 000000000000..7f3f4a385729
--- /dev/null
+++ b/drivers/hwmon/ina2xx.c
@@ -0,0 +1,368 @@
+/*
+ * Driver for Texas Instruments INA219, INA226 power monitor chips
+ *
+ * INA219:
+ * Zero Drift Bi-Directional Current/Power Monitor with I2C Interface
+ * Datasheet: http://www.ti.com/product/ina219
+ *
+ * INA226:
+ * Bi-Directional Current/Power Monitor with I2C Interface
+ * Datasheet: http://www.ti.com/product/ina226
+ *
+ * Copyright (C) 2012 Lothar Felten <l-felten@ti.com>
+ * Thanks to Jan Volkering
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+#include <linux/platform_data/ina2xx.h>
+
+/* common register definitions */
+#define INA2XX_CONFIG 0x00
+#define INA2XX_SHUNT_VOLTAGE 0x01 /* readonly */
+#define INA2XX_BUS_VOLTAGE 0x02 /* readonly */
+#define INA2XX_POWER 0x03 /* readonly */
+#define INA2XX_CURRENT 0x04 /* readonly */
+#define INA2XX_CALIBRATION 0x05
+
+/* INA226 register definitions */
+#define INA226_MASK_ENABLE 0x06
+#define INA226_ALERT_LIMIT 0x07
+#define INA226_DIE_ID 0xFF
+
+
+/* register count */
+#define INA219_REGISTERS 6
+#define INA226_REGISTERS 8
+
+#define INA2XX_MAX_REGISTERS 8
+
+/* settings - depend on use case */
+#define INA219_CONFIG_DEFAULT 0x399F /* PGA=8 */
+#define INA226_CONFIG_DEFAULT 0x4527 /* averages=16 */
+
+/* worst case is 68.10 ms (~14.6Hz, ina219) */
+#define INA2XX_CONVERSION_RATE 15
+
+enum ina2xx_ids { ina219, ina226 };
+
+struct ina2xx_data {
+ struct device *hwmon_dev;
+
+ struct mutex update_lock;
+ bool valid;
+ unsigned long last_updated;
+
+ int kind;
+ int registers;
+ u16 regs[INA2XX_MAX_REGISTERS];
+};
+
+int ina2xx_read_word(struct i2c_client *client, int reg)
+{
+ int val = i2c_smbus_read_word_data(client, reg);
+ if (unlikely(val < 0)) {
+ dev_dbg(&client->dev,
+ "Failed to read register: %d\n", reg);
+ return val;
+ }
+ return be16_to_cpu(val);
+}
+
+void ina2xx_write_word(struct i2c_client *client, int reg, int data)
+{
+ i2c_smbus_write_word_data(client, reg, cpu_to_be16(data));
+}
+
+static struct ina2xx_data *ina2xx_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ina2xx_data *data = i2c_get_clientdata(client);
+ struct ina2xx_data *ret = data;
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated +
+ HZ / INA2XX_CONVERSION_RATE) || !data->valid) {
+
+ int i;
+
+ dev_dbg(&client->dev, "Starting ina2xx update\n");
+
+ /* Read all registers */
+ for (i = 0; i < data->registers; i++) {
+ int rv = ina2xx_read_word(client, i);
+ if (rv < 0) {
+ ret = ERR_PTR(rv);
+ goto abort;
+ }
+ data->regs[i] = rv;
+ }
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+abort:
+ mutex_unlock(&data->update_lock);
+ return ret;
+}
+
+static int ina219_get_value(struct ina2xx_data *data, u8 reg)
+{
+ /*
+ * calculate exact value for the given register
+ * we assume default power-on reset settings:
+ * bus voltage range 32V
+ * gain = /8
+ * adc 1 & 2 -> conversion time 532uS
+ * mode is continuous shunt and bus
+ * calibration value is INA219_CALIBRATION_VALUE
+ */
+ int val = data->regs[reg];
+
+ switch (reg) {
+ case INA2XX_SHUNT_VOLTAGE:
+ /* LSB=10uV. Convert to mV. */
+ val = DIV_ROUND_CLOSEST(val, 100);
+ break;
+ case INA2XX_BUS_VOLTAGE:
+ /* LSB=4mV. Register is not right aligned, convert to mV. */
+ val = (val >> 3) * 4;
+ break;
+ case INA2XX_POWER:
+ /* LSB=20mW. Convert to uW */
+ val = val * 20 * 1000;
+ break;
+ case INA2XX_CURRENT:
+ /* LSB=1mA (selected). Is in mA */
+ break;
+ default:
+ /* programmer goofed */
+ WARN_ON_ONCE(1);
+ val = 0;
+ break;
+ }
+
+ return val;
+}
+
+static int ina226_get_value(struct ina2xx_data *data, u8 reg)
+{
+ /*
+ * calculate exact value for the given register
+ * we assume default power-on reset settings:
+ * bus voltage range 32V
+ * gain = /8
+ * adc 1 & 2 -> conversion time 532uS
+ * mode is continuous shunt and bus
+ * calibration value is INA226_CALIBRATION_VALUE
+ */
+ int val = data->regs[reg];
+
+ switch (reg) {
+ case INA2XX_SHUNT_VOLTAGE:
+ /* LSB=2.5uV. Convert to mV. */
+ val = DIV_ROUND_CLOSEST(val, 400);
+ break;
+ case INA2XX_BUS_VOLTAGE:
+ /* LSB=1.25mV. Convert to mV. */
+ val = val + DIV_ROUND_CLOSEST(val, 4);
+ break;
+ case INA2XX_POWER:
+ /* LSB=25mW. Convert to uW */
+ val = val * 25 * 1000;
+ break;
+ case INA2XX_CURRENT:
+ /* LSB=1mA (selected). Is in mA */
+ break;
+ default:
+ /* programmer goofed */
+ WARN_ON_ONCE(1);
+ val = 0;
+ break;
+ }
+
+ return val;
+}
+
+static ssize_t ina2xx_show_value(struct device *dev,
+ struct device_attribute *da, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct ina2xx_data *data = ina2xx_update_device(dev);
+ int value = 0;
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ switch (data->kind) {
+ case ina219:
+ value = ina219_get_value(data, attr->index);
+ break;
+ case ina226:
+ value = ina226_get_value(data, attr->index);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+ return snprintf(buf, PAGE_SIZE, "%d\n", value);
+}
+
+/* shunt voltage */
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, \
+ ina2xx_show_value, NULL, INA2XX_SHUNT_VOLTAGE);
+
+/* bus voltage */
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, \
+ ina2xx_show_value, NULL, INA2XX_BUS_VOLTAGE);
+
+/* calculated current */
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, \
+ ina2xx_show_value, NULL, INA2XX_CURRENT);
+
+/* calculated power */
+static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, \
+ ina2xx_show_value, NULL, INA2XX_POWER);
+
+/* pointers to created device attributes */
+static struct attribute *ina2xx_attributes[] = {
+ &sensor_dev_attr_in0_input.dev_attr.attr,
+ &sensor_dev_attr_in1_input.dev_attr.attr,
+ &sensor_dev_attr_curr1_input.dev_attr.attr,
+ &sensor_dev_attr_power1_input.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group ina2xx_group = {
+ .attrs = ina2xx_attributes,
+};
+
+static int ina2xx_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ struct ina2xx_data *data;
+ struct ina2xx_platform_data *pdata;
+ int ret = 0;
+ long shunt = 10000; /* default shunt value 10mOhms */
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
+ return -ENODEV;
+
+ data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ if (client->dev.platform_data) {
+ pdata =
+ (struct ina2xx_platform_data *)client->dev.platform_data;
+ shunt = pdata->shunt_uohms;
+ }
+
+ if (shunt <= 0)
+ return -ENODEV;
+
+ /* set the device type */
+ data->kind = id->driver_data;
+
+ switch (data->kind) {
+ case ina219:
+ /* device configuration */
+ ina2xx_write_word(client, INA2XX_CONFIG, INA219_CONFIG_DEFAULT);
+
+ /* set current LSB to 1mA, shunt is in uOhms */
+ /* (equation 13 in datasheet) */
+ ina2xx_write_word(client, INA2XX_CALIBRATION, 40960000 / shunt);
+ dev_info(&client->dev,
+ "power monitor INA219 (Rshunt = %li uOhm)\n", shunt);
+ data->registers = INA219_REGISTERS;
+ break;
+ case ina226:
+ /* device configuration */
+ ina2xx_write_word(client, INA2XX_CONFIG, INA226_CONFIG_DEFAULT);
+
+ /* set current LSB to 1mA, shunt is in uOhms */
+ /* (equation 1 in datasheet)*/
+ ina2xx_write_word(client, INA2XX_CALIBRATION, 5120000 / shunt);
+ dev_info(&client->dev,
+ "power monitor INA226 (Rshunt = %li uOhm)\n", shunt);
+ data->registers = INA226_REGISTERS;
+ break;
+ default:
+ /* unknown device id */
+ return -ENODEV;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+
+ ret = sysfs_create_group(&client->dev.kobj, &ina2xx_group);
+ if (ret)
+ return ret;
+
+ data->hwmon_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ ret = PTR_ERR(data->hwmon_dev);
+ goto out_err_hwmon;
+ }
+
+ return 0;
+
+out_err_hwmon:
+ sysfs_remove_group(&client->dev.kobj, &ina2xx_group);
+ return ret;
+}
+
+static int ina2xx_remove(struct i2c_client *client)
+{
+ struct ina2xx_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &ina2xx_group);
+
+ return 0;
+}
+
+static const struct i2c_device_id ina2xx_id[] = {
+ { "ina219", ina219 },
+ { "ina226", ina226 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ina2xx_id);
+
+static struct i2c_driver ina2xx_driver = {
+ .driver = {
+ .name = "ina2xx",
+ },
+ .probe = ina2xx_probe,
+ .remove = ina2xx_remove,
+ .id_table = ina2xx_id,
+};
+
+static int __init ina2xx_init(void)
+{
+ return i2c_add_driver(&ina2xx_driver);
+}
+
+static void __exit ina2xx_exit(void)
+{
+ i2c_del_driver(&ina2xx_driver);
+}
+
+MODULE_AUTHOR("Lothar Felten <l-felten@ti.com>");
+MODULE_DESCRIPTION("ina2xx driver");
+MODULE_LICENSE("GPL");
+
+module_init(ina2xx_init);
+module_exit(ina2xx_exit);
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 0b204e4cf51c..e7701d99f8e8 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -19,6 +19,8 @@
* IT8726F Super I/O chip w/LPC interface
* IT8728F Super I/O chip w/LPC interface
* IT8758E Super I/O chip w/LPC interface
+ * IT8782F Super I/O chip w/LPC interface
+ * IT8783E/F Super I/O chip w/LPC interface
* Sis950 A clone of the IT8705F
*
* Copyright (C) 2001 Chris Gauthron
@@ -59,7 +61,8 @@
#define DRVNAME "it87"
-enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728 };
+enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8782,
+ it8783 };
static unsigned short force_id;
module_param(force_id, ushort, 0);
@@ -137,13 +140,18 @@ static inline void superio_exit(void)
#define IT8721F_DEVID 0x8721
#define IT8726F_DEVID 0x8726
#define IT8728F_DEVID 0x8728
+#define IT8782F_DEVID 0x8782
+#define IT8783E_DEVID 0x8783
#define IT87_ACT_REG 0x30
#define IT87_BASE_REG 0x60
/* Logical device 7 registers (IT8712F and later) */
+#define IT87_SIO_GPIO1_REG 0x25
#define IT87_SIO_GPIO3_REG 0x27
#define IT87_SIO_GPIO5_REG 0x29
+#define IT87_SIO_PINX1_REG 0x2a /* Pin selection */
#define IT87_SIO_PINX2_REG 0x2c /* Pin selection */
+#define IT87_SIO_SPI_REG 0xef /* SPI function pin select */
#define IT87_SIO_VID_REG 0xfc /* VID value */
#define IT87_SIO_BEEP_PIN_REG 0xf6 /* Beep pin mapping */
@@ -210,6 +218,7 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
#define IT87_REG_VIN_ENABLE 0x50
#define IT87_REG_TEMP_ENABLE 0x51
+#define IT87_REG_TEMP_EXTRA 0x55
#define IT87_REG_BEEP_ENABLE 0x5c
#define IT87_REG_CHIPID 0x58
@@ -226,9 +235,11 @@ struct it87_sio_data {
u8 beep_pin;
u8 internal; /* Internal sensors can be labeled */
/* Features skipped based on config or DMI */
+ u16 skip_in;
u8 skip_vid;
u8 skip_fan;
u8 skip_pwm;
+ u8 skip_temp;
};
/*
@@ -253,6 +264,7 @@ struct it87_data {
u8 has_fan; /* Bitfield, fans enabled */
u16 fan[5]; /* Register values, possibly combined */
u16 fan_min[5]; /* Register values, possibly combined */
+ u8 has_temp; /* Bitfield, temp sensors enabled */
s8 temp[3]; /* Register value */
s8 temp_high[3]; /* Register value */
s8 temp_low[3]; /* Register value */
@@ -304,31 +316,23 @@ static inline int has_newer_autopwm(const struct it87_data *data)
|| data->type == it8728;
}
-static u8 in_to_reg(const struct it87_data *data, int nr, long val)
+static int adc_lsb(const struct it87_data *data, int nr)
{
- long lsb;
-
- if (has_12mv_adc(data)) {
- if (data->in_scaled & (1 << nr))
- lsb = 24;
- else
- lsb = 12;
- } else
- lsb = 16;
+ int lsb = has_12mv_adc(data) ? 12 : 16;
+ if (data->in_scaled & (1 << nr))
+ lsb <<= 1;
+ return lsb;
+}
- val = DIV_ROUND_CLOSEST(val, lsb);
+static u8 in_to_reg(const struct it87_data *data, int nr, long val)
+{
+ val = DIV_ROUND_CLOSEST(val, adc_lsb(data, nr));
return SENSORS_LIMIT(val, 0, 255);
}
static int in_from_reg(const struct it87_data *data, int nr, int val)
{
- if (has_12mv_adc(data)) {
- if (data->in_scaled & (1 << nr))
- return val * 24;
- else
- return val * 12;
- } else
- return val * 16;
+ return val * adc_lsb(data, nr);
}
static inline u8 FAN_TO_REG(long rpm, int div)
@@ -407,7 +411,9 @@ static inline int has_16bit_fans(const struct it87_data *data)
|| data->type == it8718
|| data->type == it8720
|| data->type == it8721
- || data->type == it8728;
+ || data->type == it8728
+ || data->type == it8782
+ || data->type == it8783;
}
static inline int has_old_autopwm(const struct it87_data *data)
@@ -1369,57 +1375,103 @@ static ssize_t show_name(struct device *dev, struct device_attribute
}
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-static struct attribute *it87_attributes[] = {
+static struct attribute *it87_attributes_in[9][5] = {
+{
&sensor_dev_attr_in0_input.dev_attr.attr,
- &sensor_dev_attr_in1_input.dev_attr.attr,
- &sensor_dev_attr_in2_input.dev_attr.attr,
- &sensor_dev_attr_in3_input.dev_attr.attr,
- &sensor_dev_attr_in4_input.dev_attr.attr,
- &sensor_dev_attr_in5_input.dev_attr.attr,
- &sensor_dev_attr_in6_input.dev_attr.attr,
- &sensor_dev_attr_in7_input.dev_attr.attr,
- &sensor_dev_attr_in8_input.dev_attr.attr,
&sensor_dev_attr_in0_min.dev_attr.attr,
- &sensor_dev_attr_in1_min.dev_attr.attr,
- &sensor_dev_attr_in2_min.dev_attr.attr,
- &sensor_dev_attr_in3_min.dev_attr.attr,
- &sensor_dev_attr_in4_min.dev_attr.attr,
- &sensor_dev_attr_in5_min.dev_attr.attr,
- &sensor_dev_attr_in6_min.dev_attr.attr,
- &sensor_dev_attr_in7_min.dev_attr.attr,
&sensor_dev_attr_in0_max.dev_attr.attr,
- &sensor_dev_attr_in1_max.dev_attr.attr,
- &sensor_dev_attr_in2_max.dev_attr.attr,
- &sensor_dev_attr_in3_max.dev_attr.attr,
- &sensor_dev_attr_in4_max.dev_attr.attr,
- &sensor_dev_attr_in5_max.dev_attr.attr,
- &sensor_dev_attr_in6_max.dev_attr.attr,
- &sensor_dev_attr_in7_max.dev_attr.attr,
&sensor_dev_attr_in0_alarm.dev_attr.attr,
+ NULL
+}, {
+ &sensor_dev_attr_in1_input.dev_attr.attr,
+ &sensor_dev_attr_in1_min.dev_attr.attr,
+ &sensor_dev_attr_in1_max.dev_attr.attr,
&sensor_dev_attr_in1_alarm.dev_attr.attr,
+ NULL
+}, {
+ &sensor_dev_attr_in2_input.dev_attr.attr,
+ &sensor_dev_attr_in2_min.dev_attr.attr,
+ &sensor_dev_attr_in2_max.dev_attr.attr,
&sensor_dev_attr_in2_alarm.dev_attr.attr,
+ NULL
+}, {
+ &sensor_dev_attr_in3_input.dev_attr.attr,
+ &sensor_dev_attr_in3_min.dev_attr.attr,
+ &sensor_dev_attr_in3_max.dev_attr.attr,
&sensor_dev_attr_in3_alarm.dev_attr.attr,
+ NULL
+}, {
+ &sensor_dev_attr_in4_input.dev_attr.attr,
+ &sensor_dev_attr_in4_min.dev_attr.attr,
+ &sensor_dev_attr_in4_max.dev_attr.attr,
&sensor_dev_attr_in4_alarm.dev_attr.attr,
+ NULL
+}, {
+ &sensor_dev_attr_in5_input.dev_attr.attr,
+ &sensor_dev_attr_in5_min.dev_attr.attr,
+ &sensor_dev_attr_in5_max.dev_attr.attr,
&sensor_dev_attr_in5_alarm.dev_attr.attr,
+ NULL
+}, {
+ &sensor_dev_attr_in6_input.dev_attr.attr,
+ &sensor_dev_attr_in6_min.dev_attr.attr,
+ &sensor_dev_attr_in6_max.dev_attr.attr,
&sensor_dev_attr_in6_alarm.dev_attr.attr,
+ NULL
+}, {
+ &sensor_dev_attr_in7_input.dev_attr.attr,
+ &sensor_dev_attr_in7_min.dev_attr.attr,
+ &sensor_dev_attr_in7_max.dev_attr.attr,
&sensor_dev_attr_in7_alarm.dev_attr.attr,
+ NULL
+}, {
+ &sensor_dev_attr_in8_input.dev_attr.attr,
+ NULL
+} };
+static const struct attribute_group it87_group_in[9] = {
+ { .attrs = it87_attributes_in[0] },
+ { .attrs = it87_attributes_in[1] },
+ { .attrs = it87_attributes_in[2] },
+ { .attrs = it87_attributes_in[3] },
+ { .attrs = it87_attributes_in[4] },
+ { .attrs = it87_attributes_in[5] },
+ { .attrs = it87_attributes_in[6] },
+ { .attrs = it87_attributes_in[7] },
+ { .attrs = it87_attributes_in[8] },
+};
+
+static struct attribute *it87_attributes_temp[3][6] = {
+{
&sensor_dev_attr_temp1_input.dev_attr.attr,
- &sensor_dev_attr_temp2_input.dev_attr.attr,
- &sensor_dev_attr_temp3_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
- &sensor_dev_attr_temp2_max.dev_attr.attr,
- &sensor_dev_attr_temp3_max.dev_attr.attr,
&sensor_dev_attr_temp1_min.dev_attr.attr,
- &sensor_dev_attr_temp2_min.dev_attr.attr,
- &sensor_dev_attr_temp3_min.dev_attr.attr,
&sensor_dev_attr_temp1_type.dev_attr.attr,
- &sensor_dev_attr_temp2_type.dev_attr.attr,
- &sensor_dev_attr_temp3_type.dev_attr.attr,
&sensor_dev_attr_temp1_alarm.dev_attr.attr,
+ NULL
+} , {
+ &sensor_dev_attr_temp2_input.dev_attr.attr,
+ &sensor_dev_attr_temp2_max.dev_attr.attr,
+ &sensor_dev_attr_temp2_min.dev_attr.attr,
+ &sensor_dev_attr_temp2_type.dev_attr.attr,
&sensor_dev_attr_temp2_alarm.dev_attr.attr,
+ NULL
+} , {
+ &sensor_dev_attr_temp3_input.dev_attr.attr,
+ &sensor_dev_attr_temp3_max.dev_attr.attr,
+ &sensor_dev_attr_temp3_min.dev_attr.attr,
+ &sensor_dev_attr_temp3_type.dev_attr.attr,
&sensor_dev_attr_temp3_alarm.dev_attr.attr,
+ NULL
+} };
+
+static const struct attribute_group it87_group_temp[3] = {
+ { .attrs = it87_attributes_temp[0] },
+ { .attrs = it87_attributes_temp[1] },
+ { .attrs = it87_attributes_temp[2] },
+};
+static struct attribute *it87_attributes[] = {
&dev_attr_alarms.attr,
&sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
&dev_attr_name.attr,
@@ -1430,7 +1482,7 @@ static const struct attribute_group it87_group = {
.attrs = it87_attributes,
};
-static struct attribute *it87_attributes_beep[] = {
+static struct attribute *it87_attributes_in_beep[] = {
&sensor_dev_attr_in0_beep.dev_attr.attr,
&sensor_dev_attr_in1_beep.dev_attr.attr,
&sensor_dev_attr_in2_beep.dev_attr.attr,
@@ -1439,15 +1491,13 @@ static struct attribute *it87_attributes_beep[] = {
&sensor_dev_attr_in5_beep.dev_attr.attr,
&sensor_dev_attr_in6_beep.dev_attr.attr,
&sensor_dev_attr_in7_beep.dev_attr.attr,
+ NULL
+};
+static struct attribute *it87_attributes_temp_beep[] = {
&sensor_dev_attr_temp1_beep.dev_attr.attr,
&sensor_dev_attr_temp2_beep.dev_attr.attr,
&sensor_dev_attr_temp3_beep.dev_attr.attr,
- NULL
-};
-
-static const struct attribute_group it87_group_beep = {
- .attrs = it87_attributes_beep,
};
static struct attribute *it87_attributes_fan16[5][3+1] = { {
@@ -1651,6 +1701,12 @@ static int __init it87_find(unsigned short *address,
case IT8728F_DEVID:
sio_data->type = it8728;
break;
+ case IT8782F_DEVID:
+ sio_data->type = it8782;
+ break;
+ case IT8783E_DEVID:
+ sio_data->type = it8783;
+ break;
case 0xffff: /* No device at all */
goto exit;
default:
@@ -1686,16 +1742,86 @@ static int __init it87_find(unsigned short *address,
/* The IT8705F has a different LD number for GPIO */
superio_select(5);
sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
+ } else if (sio_data->type == it8783) {
+ int reg25, reg27, reg2A, reg2C, regEF;
+
+ sio_data->skip_vid = 1; /* No VID */
+
+ superio_select(GPIO);
+
+ reg25 = superio_inb(IT87_SIO_GPIO1_REG);
+ reg27 = superio_inb(IT87_SIO_GPIO3_REG);
+ reg2A = superio_inb(IT87_SIO_PINX1_REG);
+ reg2C = superio_inb(IT87_SIO_PINX2_REG);
+ regEF = superio_inb(IT87_SIO_SPI_REG);
+
+ /* Check if fan3 is there or not */
+ if ((reg27 & (1 << 0)) || !(reg2C & (1 << 2)))
+ sio_data->skip_fan |= (1 << 2);
+ if ((reg25 & (1 << 4))
+ || (!(reg2A & (1 << 1)) && (regEF & (1 << 0))))
+ sio_data->skip_pwm |= (1 << 2);
+
+ /* Check if fan2 is there or not */
+ if (reg27 & (1 << 7))
+ sio_data->skip_fan |= (1 << 1);
+ if (reg27 & (1 << 3))
+ sio_data->skip_pwm |= (1 << 1);
+
+ /* VIN5 */
+ if ((reg27 & (1 << 0)) || (reg2C & (1 << 2)))
+ sio_data->skip_in |= (1 << 5); /* No VIN5 */
+
+ /* VIN6 */
+ if (reg27 & (1 << 1))
+ sio_data->skip_in |= (1 << 6); /* No VIN6 */
+
+ /*
+ * VIN7
+ * Does not depend on bit 2 of Reg2C, contrary to datasheet.
+ */
+ if (reg27 & (1 << 2)) {
+ /*
+ * The data sheet is a bit unclear regarding the
+ * internal voltage divider for VCCH5V. It says
+ * "This bit enables and switches VIN7 (pin 91) to the
+ * internal voltage divider for VCCH5V".
+ * This is different to other chips, where the internal
+ * voltage divider would connect VIN7 to an internal
+ * voltage source. Maybe that is the case here as well.
+ *
+ * Since we don't know for sure, re-route it if that is
+ * not the case, and ask the user to report if the
+ * resulting voltage is sane.
+ */
+ if (!(reg2C & (1 << 1))) {
+ reg2C |= (1 << 1);
+ superio_outb(IT87_SIO_PINX2_REG, reg2C);
+ pr_notice("Routing internal VCCH5V to in7.\n");
+ }
+ pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n");
+ pr_notice("Please report if it displays a reasonable voltage.\n");
+ }
+
+ if (reg2C & (1 << 0))
+ sio_data->internal |= (1 << 0);
+ if (reg2C & (1 << 1))
+ sio_data->internal |= (1 << 1);
+
+ sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
+
} else {
int reg;
+ bool uart6;
superio_select(GPIO);
reg = superio_inb(IT87_SIO_GPIO3_REG);
- if (sio_data->type == it8721 || sio_data->type == it8728) {
+ if (sio_data->type == it8721 || sio_data->type == it8728 ||
+ sio_data->type == it8782) {
/*
- * The IT8721F/IT8758E doesn't have VID pins at all,
- * not sure about the IT8728F.
+ * IT8721F/IT8758E, and IT8782F don't have VID pins
+ * at all, not sure about the IT8728F.
*/
sio_data->skip_vid = 1;
} else {
@@ -1724,6 +1850,9 @@ static int __init it87_find(unsigned short *address,
sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
reg = superio_inb(IT87_SIO_PINX2_REG);
+
+ uart6 = sio_data->type == it8782 && (reg & (1 << 2));
+
/*
* The IT8720F has no VIN7 pin, so VCCH should always be
* routed internally to VIN7 with an internal divider.
@@ -1733,8 +1862,12 @@ static int __init it87_find(unsigned short *address,
* configured, even though the IT8720F datasheet claims
* that the internal routing of VCCH to VIN7 is the default
* setting. So we force the internal routing in this case.
+ *
+ * On IT8782F, VIN7 is multiplexed with one of the UART6 pins.
+ * If UART6 is enabled, re-route VIN7 to the internal divider
+ * if that is not already the case.
*/
- if (sio_data->type == it8720 && !(reg & (1 << 1))) {
+ if ((sio_data->type == it8720 || uart6) && !(reg & (1 << 1))) {
reg |= (1 << 1);
superio_outb(IT87_SIO_PINX2_REG, reg);
pr_notice("Routing internal VCCH to in7\n");
@@ -1745,6 +1878,20 @@ static int __init it87_find(unsigned short *address,
sio_data->type == it8728)
sio_data->internal |= (1 << 1);
+ /*
+ * On IT8782F, UART6 pins overlap with VIN5, VIN6, and VIN7.
+ * While VIN7 can be routed to the internal voltage divider,
+ * VIN5 and VIN6 are not available if UART6 is enabled.
+ *
+ * Also, temp3 is not available if UART6 is enabled and TEMPIN3
+ * is the temperature source. Since we can not read the
+ * temperature source here, skip_temp is preliminary.
+ */
+ if (uart6) {
+ sio_data->skip_in |= (1 << 5) | (1 << 6);
+ sio_data->skip_temp |= (1 << 2);
+ }
+
sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
}
if (sio_data->beep_pin)
@@ -1782,8 +1929,22 @@ static void it87_remove_files(struct device *dev)
int i;
sysfs_remove_group(&dev->kobj, &it87_group);
- if (sio_data->beep_pin)
- sysfs_remove_group(&dev->kobj, &it87_group_beep);
+ for (i = 0; i < 9; i++) {
+ if (sio_data->skip_in & (1 << i))
+ continue;
+ sysfs_remove_group(&dev->kobj, &it87_group_in[i]);
+ if (it87_attributes_in_beep[i])
+ sysfs_remove_file(&dev->kobj,
+ it87_attributes_in_beep[i]);
+ }
+ for (i = 0; i < 3; i++) {
+ if (!(data->has_temp & (1 << i)))
+ continue;
+ sysfs_remove_group(&dev->kobj, &it87_group_temp[i]);
+ if (sio_data->beep_pin)
+ sysfs_remove_file(&dev->kobj,
+ it87_attributes_temp_beep[i]);
+ }
for (i = 0; i < 5; i++) {
if (!(data->has_fan & (1 << i)))
continue;
@@ -1823,22 +1984,22 @@ static int __devinit it87_probe(struct platform_device *pdev)
"it8720",
"it8721",
"it8728",
+ "it8782",
+ "it8783",
};
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (!request_region(res->start, IT87_EC_EXTENT, DRVNAME)) {
+ if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT,
+ DRVNAME)) {
dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
(unsigned long)res->start,
(unsigned long)(res->start + IT87_EC_EXTENT - 1));
- err = -EBUSY;
- goto ERROR0;
+ return -EBUSY;
}
- data = kzalloc(sizeof(struct it87_data), GFP_KERNEL);
- if (!data) {
- err = -ENOMEM;
- goto ERROR1;
- }
+ data = devm_kzalloc(&pdev->dev, sizeof(struct it87_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
data->addr = res->start;
data->type = sio_data->type;
@@ -1847,10 +2008,8 @@ static int __devinit it87_probe(struct platform_device *pdev)
/* Now, we do the remaining detection. */
if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80)
- || it87_read_value(data, IT87_REG_CHIPID) != 0x90) {
- err = -ENODEV;
- goto ERROR2;
- }
+ || it87_read_value(data, IT87_REG_CHIPID) != 0x90)
+ return -ENODEV;
platform_set_drvdata(pdev, data);
@@ -1867,6 +2026,18 @@ static int __devinit it87_probe(struct platform_device *pdev)
data->in_scaled |= (1 << 7); /* in7 is VSB */
if (sio_data->internal & (1 << 2))
data->in_scaled |= (1 << 8); /* in8 is Vbat */
+ } else if (sio_data->type == it8782 || sio_data->type == it8783) {
+ if (sio_data->internal & (1 << 0))
+ data->in_scaled |= (1 << 3); /* in3 is VCC5V */
+ if (sio_data->internal & (1 << 1))
+ data->in_scaled |= (1 << 7); /* in7 is VCCH5V */
+ }
+
+ data->has_temp = 0x07;
+ if (sio_data->skip_temp & (1 << 2)) {
+ if (sio_data->type == it8782
+ && !(it87_read_value(data, IT87_REG_TEMP_EXTRA) & 0x80))
+ data->has_temp &= ~(1 << 2);
}
/* Initialize the IT87 chip */
@@ -1875,12 +2046,34 @@ static int __devinit it87_probe(struct platform_device *pdev)
/* Register sysfs hooks */
err = sysfs_create_group(&dev->kobj, &it87_group);
if (err)
- goto ERROR2;
+ return err;
- if (sio_data->beep_pin) {
- err = sysfs_create_group(&dev->kobj, &it87_group_beep);
+ for (i = 0; i < 9; i++) {
+ if (sio_data->skip_in & (1 << i))
+ continue;
+ err = sysfs_create_group(&dev->kobj, &it87_group_in[i]);
if (err)
- goto ERROR4;
+ goto error;
+ if (sio_data->beep_pin && it87_attributes_in_beep[i]) {
+ err = sysfs_create_file(&dev->kobj,
+ it87_attributes_in_beep[i]);
+ if (err)
+ goto error;
+ }
+ }
+
+ for (i = 0; i < 3; i++) {
+ if (!(data->has_temp & (1 << i)))
+ continue;
+ err = sysfs_create_group(&dev->kobj, &it87_group_temp[i]);
+ if (err)
+ goto error;
+ if (sio_data->beep_pin) {
+ err = sysfs_create_file(&dev->kobj,
+ it87_attributes_temp_beep[i]);
+ if (err)
+ goto error;
+ }
}
/* Do not create fan files for disabled fans */
@@ -1891,13 +2084,13 @@ static int __devinit it87_probe(struct platform_device *pdev)
continue;
err = sysfs_create_group(&dev->kobj, &fan_group[i]);
if (err)
- goto ERROR4;
+ goto error;
if (sio_data->beep_pin) {
err = sysfs_create_file(&dev->kobj,
it87_attributes_fan_beep[i]);
if (err)
- goto ERROR4;
+ goto error;
if (!fan_beep_need_rw)
continue;
@@ -1922,14 +2115,14 @@ static int __devinit it87_probe(struct platform_device *pdev)
err = sysfs_create_group(&dev->kobj,
&it87_group_pwm[i]);
if (err)
- goto ERROR4;
+ goto error;
if (!has_old_autopwm(data))
continue;
err = sysfs_create_group(&dev->kobj,
&it87_group_autopwm[i]);
if (err)
- goto ERROR4;
+ goto error;
}
}
@@ -1939,7 +2132,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
data->vid = sio_data->vid_value;
err = sysfs_create_group(&dev->kobj, &it87_group_vid);
if (err)
- goto ERROR4;
+ goto error;
}
/* Export labels for internal sensors */
@@ -1949,25 +2142,19 @@ static int __devinit it87_probe(struct platform_device *pdev)
err = sysfs_create_file(&dev->kobj,
it87_attributes_label[i]);
if (err)
- goto ERROR4;
+ goto error;
}
data->hwmon_dev = hwmon_device_register(dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
- goto ERROR4;
+ goto error;
}
return 0;
-ERROR4:
+error:
it87_remove_files(dev);
-ERROR2:
- platform_set_drvdata(pdev, NULL);
- kfree(data);
-ERROR1:
- release_region(res->start, IT87_EC_EXTENT);
-ERROR0:
return err;
}
@@ -1978,10 +2165,6 @@ static int __devexit it87_remove(struct platform_device *pdev)
hwmon_device_unregister(data->hwmon_dev);
it87_remove_files(&pdev->dev);
- release_region(data->addr, IT87_EC_EXTENT);
- platform_set_drvdata(pdev, NULL);
- kfree(data);
-
return 0;
}
@@ -2143,8 +2326,9 @@ static void __devinit it87_init_device(struct platform_device *pdev)
it87_write_value(data, IT87_REG_FAN_16BIT,
tmp | 0x07);
}
- /* IT8705F only supports three fans. */
- if (data->type != it87) {
+ /* IT8705F, IT8782F, and IT8783E/F only support three fans. */
+ if (data->type != it87 && data->type != it8782 &&
+ data->type != it8783) {
if (tmp & (1 << 4))
data->has_fan |= (1 << 3); /* fan4 enabled */
if (tmp & (1 << 5))
@@ -2233,6 +2417,8 @@ static struct it87_data *it87_update_device(struct device *dev)
}
}
for (i = 0; i < 3; i++) {
+ if (!(data->has_temp & (1 << i)))
+ continue;
data->temp[i] =
it87_read_value(data, IT87_REG_TEMP(i));
data->temp_high[i] =
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index 307bb325dde9..7356b5ec8f67 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -225,15 +225,4 @@ static struct pci_driver k10temp_driver = {
.remove = __devexit_p(k10temp_remove),
};
-static int __init k10temp_init(void)
-{
- return pci_register_driver(&k10temp_driver);
-}
-
-static void __exit k10temp_exit(void)
-{
- pci_unregister_driver(&k10temp_driver);
-}
-
-module_init(k10temp_init)
-module_exit(k10temp_exit)
+module_pci_driver(k10temp_driver);
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index 575101988751..35aac82ee8eb 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -339,19 +339,8 @@ static struct pci_driver k8temp_driver = {
.remove = __devexit_p(k8temp_remove),
};
-static int __init k8temp_init(void)
-{
- return pci_register_driver(&k8temp_driver);
-}
-
-static void __exit k8temp_exit(void)
-{
- pci_unregister_driver(&k8temp_driver);
-}
+module_pci_driver(k8temp_driver);
MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
MODULE_DESCRIPTION("AMD K8 core temperature monitor");
MODULE_LICENSE("GPL");
-
-module_init(k8temp_init)
-module_exit(k8temp_exit)
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index 9b382ec2c3bd..6da9696e1827 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -134,8 +134,7 @@ static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
return div64_u64(dividend, divisor);
}
-static unsigned int get_ohm_of_thermistor(struct ntc_data *data,
- unsigned int uV)
+static int get_ohm_of_thermistor(struct ntc_data *data, unsigned int uV)
{
struct ntc_thermistor_platform_data *pdata = data->pdata;
u64 mV = uV / 1000;
@@ -146,12 +145,12 @@ static unsigned int get_ohm_of_thermistor(struct ntc_data *data,
if (mV == 0) {
if (pdata->connect == NTC_CONNECTED_POSITIVE)
- return UINT_MAX;
+ return INT_MAX;
return 0;
}
if (mV >= pmV)
return (pdata->connect == NTC_CONNECTED_POSITIVE) ?
- 0 : UINT_MAX;
+ 0 : INT_MAX;
if (pdata->connect == NTC_CONNECTED_POSITIVE && puO == 0)
N = div64_u64_safe(pdO * (pmV - mV), mV);
@@ -163,113 +162,109 @@ static unsigned int get_ohm_of_thermistor(struct ntc_data *data,
else
N = div64_u64_safe(pdO * puO * mV, pdO * (pmV - mV) - puO * mV);
- return (unsigned int) N;
+ if (N > INT_MAX)
+ N = INT_MAX;
+ return N;
}
-static int lookup_comp(struct ntc_data *data,
- unsigned int ohm, int *i_low, int *i_high)
+static void lookup_comp(struct ntc_data *data, unsigned int ohm,
+ int *i_low, int *i_high)
{
- int start, end, mid = -1;
+ int start, end, mid;
+
+ /*
+ * Handle special cases: Resistance is higher than or equal to
+ * resistance in first table entry, or resistance is lower or equal
+ * to resistance in last table entry.
+ * In these cases, return i_low == i_high, either pointing to the
+ * beginning or to the end of the table depending on the condition.
+ */
+ if (ohm >= data->comp[0].ohm) {
+ *i_low = 0;
+ *i_high = 0;
+ return;
+ }
+ if (ohm <= data->comp[data->n_comp - 1].ohm) {
+ *i_low = data->n_comp - 1;
+ *i_high = data->n_comp - 1;
+ return;
+ }
/* Do a binary search on compensation table */
start = 0;
end = data->n_comp;
-
- while (end > start) {
+ while (start < end) {
mid = start + (end - start) / 2;
- if (data->comp[mid].ohm < ohm)
+ /*
+ * start <= mid < end
+ * data->comp[start].ohm > ohm >= data->comp[end].ohm
+ *
+ * We could check for "ohm == data->comp[mid].ohm" here, but
+ * that is a quite unlikely condition, and we would have to
+ * check again after updating start. Check it at the end instead
+ * for simplicity.
+ */
+ if (ohm >= data->comp[mid].ohm) {
end = mid;
- else if (data->comp[mid].ohm > ohm)
- start = mid + 1;
- else
- break;
- }
-
- if (mid == 0) {
- if (data->comp[mid].ohm > ohm) {
- *i_high = mid;
- *i_low = mid + 1;
- return 0;
- } else {
- *i_low = mid;
- *i_high = -1;
- return -EINVAL;
- }
- }
- if (mid == (data->n_comp - 1)) {
- if (data->comp[mid].ohm <= ohm) {
- *i_low = mid;
- *i_high = mid - 1;
- return 0;
} else {
- *i_low = -1;
- *i_high = mid;
- return -EINVAL;
+ start = mid + 1;
+ /*
+ * ohm >= data->comp[start].ohm might be true here,
+ * since we set start to mid + 1. In that case, we are
+ * done. We could keep going, but the condition is quite
+ * likely to occur, so it is worth checking for it.
+ */
+ if (ohm >= data->comp[start].ohm)
+ end = start;
}
+ /*
+ * start <= end
+ * data->comp[start].ohm >= ohm >= data->comp[end].ohm
+ */
}
-
- if (data->comp[mid].ohm <= ohm) {
- *i_low = mid;
- *i_high = mid - 1;
- } else {
- *i_low = mid + 1;
- *i_high = mid;
- }
-
- return 0;
+ /*
+ * start == end
+ * ohm >= data->comp[end].ohm
+ */
+ *i_low = end;
+ if (ohm == data->comp[end].ohm)
+ *i_high = end;
+ else
+ *i_high = end - 1;
}
-static int get_temp_mC(struct ntc_data *data, unsigned int ohm, int *temp)
+static int get_temp_mC(struct ntc_data *data, unsigned int ohm)
{
int low, high;
- int ret;
+ int temp;
- ret = lookup_comp(data, ohm, &low, &high);
- if (ret) {
+ lookup_comp(data, ohm, &low, &high);
+ if (low == high) {
/* Unable to use linear approximation */
- if (low != -1)
- *temp = data->comp[low].temp_C * 1000;
- else if (high != -1)
- *temp = data->comp[high].temp_C * 1000;
- else
- return ret;
+ temp = data->comp[low].temp_C * 1000;
} else {
- *temp = data->comp[low].temp_C * 1000 +
+ temp = data->comp[low].temp_C * 1000 +
((data->comp[high].temp_C - data->comp[low].temp_C) *
1000 * ((int)ohm - (int)data->comp[low].ohm)) /
((int)data->comp[high].ohm - (int)data->comp[low].ohm);
}
-
- return 0;
+ return temp;
}
-static int ntc_thermistor_read(struct ntc_data *data, int *temp)
+static int ntc_thermistor_get_ohm(struct ntc_data *data)
{
- int ret;
- int read_ohm, read_uV;
- unsigned int ohm = 0;
-
- if (data->pdata->read_ohm) {
- read_ohm = data->pdata->read_ohm();
- if (read_ohm < 0)
- return read_ohm;
- ohm = (unsigned int)read_ohm;
- }
+ int read_uV;
+
+ if (data->pdata->read_ohm)
+ return data->pdata->read_ohm();
if (data->pdata->read_uV) {
read_uV = data->pdata->read_uV();
if (read_uV < 0)
return read_uV;
- ohm = get_ohm_of_thermistor(data, (unsigned int)read_uV);
- }
-
- ret = get_temp_mC(data, ohm, temp);
- if (ret) {
- dev_dbg(data->dev, "Sensor reading function not available.\n");
- return ret;
+ return get_ohm_of_thermistor(data, read_uV);
}
-
- return 0;
+ return -EINVAL;
}
static ssize_t ntc_show_name(struct device *dev,
@@ -290,12 +285,13 @@ static ssize_t ntc_show_temp(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ntc_data *data = dev_get_drvdata(dev);
- int temp, ret;
+ int ohm;
- ret = ntc_thermistor_read(data, &temp);
- if (ret)
- return ret;
- return sprintf(buf, "%d\n", temp);
+ ohm = ntc_thermistor_get_ohm(data);
+ if (ohm < 0)
+ return ohm;
+
+ return sprintf(buf, "%d\n", get_temp_mC(data, ohm));
}
static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, ntc_show_type, NULL, 0);
@@ -326,14 +322,14 @@ static int __devinit ntc_thermistor_probe(struct platform_device *pdev)
/* Either one of the two is required. */
if (!pdata->read_uV && !pdata->read_ohm) {
- dev_err(&pdev->dev, "Both read_uV and read_ohm missing."
- "Need either one of the two.\n");
+ dev_err(&pdev->dev,
+ "Both read_uV and read_ohm missing. Need either one of the two.\n");
return -EINVAL;
}
if (pdata->read_uV && pdata->read_ohm) {
- dev_warn(&pdev->dev, "Only one of read_uV and read_ohm "
- "is needed; ignoring read_uV.\n");
+ dev_warn(&pdev->dev,
+ "Only one of read_uV and read_ohm is needed; ignoring read_uV.\n");
pdata->read_uV = NULL;
}
@@ -344,12 +340,12 @@ static int __devinit ntc_thermistor_probe(struct platform_device *pdev)
NTC_CONNECTED_POSITIVE) ||
(pdata->connect != NTC_CONNECTED_POSITIVE &&
pdata->connect != NTC_CONNECTED_GROUND))) {
- dev_err(&pdev->dev, "Required data to use read_uV not "
- "supplied.\n");
+ dev_err(&pdev->dev,
+ "Required data to use read_uV not supplied.\n");
return -EINVAL;
}
- data = kzalloc(sizeof(struct ntc_data), GFP_KERNEL);
+ data = devm_kzalloc(&pdev->dev, sizeof(struct ntc_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -370,8 +366,7 @@ static int __devinit ntc_thermistor_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n",
pdev->id_entry->driver_data,
pdev->id_entry->name);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
platform_set_drvdata(pdev, data);
@@ -379,13 +374,13 @@ static int __devinit ntc_thermistor_probe(struct platform_device *pdev)
ret = sysfs_create_group(&data->dev->kobj, &ntc_attr_group);
if (ret) {
dev_err(data->dev, "unable to create sysfs files\n");
- goto err;
+ return ret;
}
data->hwmon_dev = hwmon_device_register(data->dev);
- if (IS_ERR_OR_NULL(data->hwmon_dev)) {
+ if (IS_ERR(data->hwmon_dev)) {
dev_err(data->dev, "unable to register as hwmon device.\n");
- ret = -EINVAL;
+ ret = PTR_ERR(data->hwmon_dev);
goto err_after_sysfs;
}
@@ -395,8 +390,6 @@ static int __devinit ntc_thermistor_probe(struct platform_device *pdev)
return 0;
err_after_sysfs:
sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
-err:
- kfree(data);
return ret;
}
@@ -408,8 +401,6 @@ static int __devexit ntc_thermistor_remove(struct platform_device *pdev)
sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
platform_set_drvdata(pdev, NULL);
- kfree(data);
-
return 0;
}
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d2c5095deeac..94468a64ce3a 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -351,7 +351,7 @@ config I2C_DAVINCI
For details please see http://www.ti.com/davinci
config I2C_DESIGNWARE_PLATFORM
- tristate "Synopsys DesignWare Platfrom"
+ tristate "Synopsys DesignWare Platform"
depends on HAVE_CLK
help
If you say yes to this option, support will be included for the
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index dfb84b7ee550..56bce9a8bcbb 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -51,6 +51,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_i2c.h>
+#include <linux/pinctrl/consumer.h>
#include <mach/irqs.h>
#include <mach/hardware.h>
@@ -470,6 +471,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
struct imx_i2c_struct *i2c_imx;
struct resource *res;
struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
+ struct pinctrl *pinctrl;
void __iomem *base;
resource_size_t res_size;
int irq, bitrate;
@@ -520,6 +522,12 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
i2c_imx->base = base;
i2c_imx->res = res;
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ goto fail3;
+ }
+
/* Get I2C clock */
i2c_imx->clk = clk_get(&pdev->dev, "i2c_clk");
if (IS_ERR(i2c_imx->clk)) {
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 76b8af44f634..7fa73eed84a7 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -26,6 +26,7 @@
#include <linux/platform_device.h>
#include <linux/jiffies.h>
#include <linux/io.h>
+#include <linux/pinctrl/consumer.h>
#include <mach/common.h>
@@ -325,10 +326,15 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct mxs_i2c_dev *i2c;
struct i2c_adapter *adap;
+ struct pinctrl *pinctrl;
struct resource *res;
resource_size_t res_size;
int err, irq;
+ pinctrl = devm_pinctrl_get_select_default(dev);
+ if (IS_ERR(pinctrl))
+ return PTR_ERR(pinctrl);
+
i2c = devm_kzalloc(dev, sizeof(struct mxs_i2c_dev), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index eb8ad538c79f..99389d2eae51 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -23,16 +23,61 @@
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/slab.h>
+#include <linux/of_i2c.h>
+
+#define I2C_PNX_TIMEOUT_DEFAULT 10 /* msec */
+#define I2C_PNX_SPEED_KHZ_DEFAULT 100
+#define I2C_PNX_REGION_SIZE 0x100
+
+enum {
+ mstatus_tdi = 0x00000001,
+ mstatus_afi = 0x00000002,
+ mstatus_nai = 0x00000004,
+ mstatus_drmi = 0x00000008,
+ mstatus_active = 0x00000020,
+ mstatus_scl = 0x00000040,
+ mstatus_sda = 0x00000080,
+ mstatus_rff = 0x00000100,
+ mstatus_rfe = 0x00000200,
+ mstatus_tff = 0x00000400,
+ mstatus_tfe = 0x00000800,
+};
-#include <mach/hardware.h>
-#include <mach/i2c.h>
+enum {
+ mcntrl_tdie = 0x00000001,
+ mcntrl_afie = 0x00000002,
+ mcntrl_naie = 0x00000004,
+ mcntrl_drmie = 0x00000008,
+ mcntrl_daie = 0x00000020,
+ mcntrl_rffie = 0x00000040,
+ mcntrl_tffie = 0x00000080,
+ mcntrl_reset = 0x00000100,
+ mcntrl_cdbmode = 0x00000400,
+};
-#define I2C_PNX_TIMEOUT 10 /* msec */
-#define I2C_PNX_SPEED_KHZ 100
-#define I2C_PNX_REGION_SIZE 0x100
+enum {
+ rw_bit = 1 << 0,
+ start_bit = 1 << 8,
+ stop_bit = 1 << 9,
+};
-static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
+#define I2C_REG_RX(a) ((a)->ioaddr) /* Rx FIFO reg (RO) */
+#define I2C_REG_TX(a) ((a)->ioaddr) /* Tx FIFO reg (WO) */
+#define I2C_REG_STS(a) ((a)->ioaddr + 0x04) /* Status reg (RO) */
+#define I2C_REG_CTL(a) ((a)->ioaddr + 0x08) /* Ctl reg */
+#define I2C_REG_CKL(a) ((a)->ioaddr + 0x0c) /* Clock divider low */
+#define I2C_REG_CKH(a) ((a)->ioaddr + 0x10) /* Clock divider high */
+#define I2C_REG_ADR(a) ((a)->ioaddr + 0x14) /* I2C address */
+#define I2C_REG_RFL(a) ((a)->ioaddr + 0x18) /* Rx FIFO level (RO) */
+#define I2C_REG_TFL(a) ((a)->ioaddr + 0x1c) /* Tx FIFO level (RO) */
+#define I2C_REG_RXB(a) ((a)->ioaddr + 0x20) /* Num of bytes Rx-ed (RO) */
+#define I2C_REG_TXB(a) ((a)->ioaddr + 0x24) /* Num of bytes Tx-ed (RO) */
+#define I2C_REG_TXS(a) ((a)->ioaddr + 0x28) /* Tx slave FIFO (RO) */
+#define I2C_REG_STFL(a) ((a)->ioaddr + 0x2c) /* Tx slave FIFO level (RO) */
+
+static inline int wait_timeout(struct i2c_pnx_algo_data *data)
{
+ long timeout = data->timeout;
while (timeout > 0 &&
(ioread32(I2C_REG_STS(data)) & mstatus_active)) {
mdelay(1);
@@ -41,8 +86,9 @@ static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
return (timeout <= 0);
}
-static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
+static inline int wait_reset(struct i2c_pnx_algo_data *data)
{
+ long timeout = data->timeout;
while (timeout > 0 &&
(ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
mdelay(1);
@@ -54,7 +100,7 @@ static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
{
struct timer_list *timer = &alg_data->mif.timer;
- unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT);
+ unsigned long expires = msecs_to_jiffies(alg_data->timeout);
if (expires <= 1)
expires = 2;
@@ -92,7 +138,7 @@ static int i2c_pnx_start(unsigned char slave_addr,
}
/* First, make sure bus is idle */
- if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
+ if (wait_timeout(alg_data)) {
/* Somebody else is monopolizing the bus */
dev_err(&alg_data->adapter.dev,
"%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n",
@@ -185,7 +231,7 @@ static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
if (alg_data->mif.len == 0) {
if (alg_data->last) {
/* Wait until the STOP is seen. */
- if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
+ if (wait_timeout(alg_data))
dev_err(&alg_data->adapter.dev,
"The bus is still active after timeout\n");
}
@@ -283,7 +329,7 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
if (alg_data->mif.len == 0) {
if (alg_data->last)
/* Wait until the STOP is seen. */
- if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
+ if (wait_timeout(alg_data))
dev_err(&alg_data->adapter.dev,
"The bus is still active after timeout\n");
@@ -399,7 +445,7 @@ static void i2c_pnx_timeout(unsigned long data)
ctl |= mcntrl_reset;
iowrite32(ctl, I2C_REG_CTL(alg_data));
- wait_reset(I2C_PNX_TIMEOUT, alg_data);
+ wait_reset(alg_data);
alg_data->mif.ret = -EIO;
complete(&alg_data->mif.complete);
}
@@ -414,18 +460,18 @@ static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data)
alg_data->adapter.name);
iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
I2C_REG_CTL(alg_data));
- wait_reset(I2C_PNX_TIMEOUT, alg_data);
+ wait_reset(alg_data);
} else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) {
/* If there is data in the fifo's after transfer,
* flush fifo's by reset.
*/
iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
I2C_REG_CTL(alg_data));
- wait_reset(I2C_PNX_TIMEOUT, alg_data);
+ wait_reset(alg_data);
} else if (stat & mstatus_nai) {
iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
I2C_REG_CTL(alg_data));
- wait_reset(I2C_PNX_TIMEOUT, alg_data);
+ wait_reset(alg_data);
}
}
@@ -568,14 +614,8 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)
int ret = 0;
struct i2c_pnx_algo_data *alg_data;
unsigned long freq;
- struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data;
-
- if (!i2c_pnx || !i2c_pnx->name) {
- dev_err(&pdev->dev, "%s: no platform data supplied\n",
- __func__);
- ret = -EINVAL;
- goto out;
- }
+ struct resource *res;
+ u32 speed = I2C_PNX_SPEED_KHZ_DEFAULT * 1000;
alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL);
if (!alg_data) {
@@ -585,14 +625,27 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, alg_data);
- strlcpy(alg_data->adapter.name, i2c_pnx->name,
- sizeof(alg_data->adapter.name));
alg_data->adapter.dev.parent = &pdev->dev;
alg_data->adapter.algo = &pnx_algorithm;
alg_data->adapter.algo_data = alg_data;
alg_data->adapter.nr = pdev->id;
- alg_data->i2c_pnx = i2c_pnx;
+ alg_data->timeout = I2C_PNX_TIMEOUT_DEFAULT;
+#ifdef CONFIG_OF
+ alg_data->adapter.dev.of_node = of_node_get(pdev->dev.of_node);
+ if (pdev->dev.of_node) {
+ of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+ &speed);
+ /*
+ * At this point, it is planned to add an OF timeout property.
+ * As soon as there is a consensus about how to call and handle
+ * this, sth. like the following can be put here:
+ *
+ * of_property_read_u32(pdev->dev.of_node, "timeout",
+ * &alg_data->timeout);
+ */
+ }
+#endif
alg_data->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(alg_data->clk)) {
ret = PTR_ERR(alg_data->clk);
@@ -603,17 +656,27 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)
alg_data->mif.timer.function = i2c_pnx_timeout;
alg_data->mif.timer.data = (unsigned long)alg_data;
+ snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name),
+ "%s", pdev->name);
+
/* Register I/O resource */
- if (!request_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE,
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Unable to get mem resource.\n");
+ ret = -EBUSY;
+ goto out_clkget;
+ }
+ if (!request_mem_region(res->start, I2C_PNX_REGION_SIZE,
pdev->name)) {
dev_err(&pdev->dev,
"I/O region 0x%08x for I2C already in use.\n",
- i2c_pnx->base);
- ret = -ENODEV;
+ res->start);
+ ret = -ENOMEM;
goto out_clkget;
}
- alg_data->ioaddr = ioremap(i2c_pnx->base, I2C_PNX_REGION_SIZE);
+ alg_data->base = res->start;
+ alg_data->ioaddr = ioremap(res->start, I2C_PNX_REGION_SIZE);
if (!alg_data->ioaddr) {
dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n");
ret = -ENOMEM;
@@ -637,20 +700,25 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)
* the deglitching filter length.
*/
- tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;
+ tmp = (freq / speed) / 2 - 2;
if (tmp > 0x3FF)
tmp = 0x3FF;
iowrite32(tmp, I2C_REG_CKH(alg_data));
iowrite32(tmp, I2C_REG_CKL(alg_data));
iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));
- if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) {
+ if (wait_reset(alg_data)) {
ret = -ENODEV;
goto out_clock;
}
init_completion(&alg_data->mif.complete);
- ret = request_irq(i2c_pnx->irq, i2c_pnx_interrupt,
+ alg_data->irq = platform_get_irq(pdev, 0);
+ if (alg_data->irq < 0) {
+ dev_err(&pdev->dev, "Failed to get IRQ from platform resource\n");
+ goto out_irq;
+ }
+ ret = request_irq(alg_data->irq, i2c_pnx_interrupt,
0, pdev->name, alg_data);
if (ret)
goto out_clock;
@@ -662,39 +730,39 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)
goto out_irq;
}
+ of_i2c_register_devices(&alg_data->adapter);
+
dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
- alg_data->adapter.name, i2c_pnx->base, i2c_pnx->irq);
+ alg_data->adapter.name, res->start, alg_data->irq);
return 0;
out_irq:
- free_irq(i2c_pnx->irq, alg_data);
+ free_irq(alg_data->irq, alg_data);
out_clock:
clk_disable(alg_data->clk);
out_unmap:
iounmap(alg_data->ioaddr);
out_release:
- release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE);
+ release_mem_region(res->start, I2C_PNX_REGION_SIZE);
out_clkget:
clk_put(alg_data->clk);
out_drvdata:
kfree(alg_data);
err_kzalloc:
platform_set_drvdata(pdev, NULL);
-out:
return ret;
}
static int __devexit i2c_pnx_remove(struct platform_device *pdev)
{
struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
- struct i2c_pnx_data *i2c_pnx = alg_data->i2c_pnx;
- free_irq(i2c_pnx->irq, alg_data);
+ free_irq(alg_data->irq, alg_data);
i2c_del_adapter(&alg_data->adapter);
clk_disable(alg_data->clk);
iounmap(alg_data->ioaddr);
- release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE);
+ release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE);
clk_put(alg_data->clk);
kfree(alg_data);
platform_set_drvdata(pdev, NULL);
@@ -702,10 +770,19 @@ static int __devexit i2c_pnx_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id i2c_pnx_of_match[] = {
+ { .compatible = "nxp,pnx-i2c" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, i2c_pnx_of_match);
+#endif
+
static struct platform_driver i2c_pnx_driver = {
.driver = {
.name = "pnx-i2c",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(i2c_pnx_of_match),
},
.probe = i2c_pnx_probe,
.remove = __devexit_p(i2c_pnx_remove),
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 7b397c6f607e..31c47e18d83c 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -227,6 +227,72 @@ static int __devexit i2c_powermac_remove(struct platform_device *dev)
return 0;
}
+static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap,
+ struct pmac_i2c_bus *bus)
+{
+ struct i2c_client *newdev;
+ struct device_node *node;
+
+ for_each_child_of_node(adap->dev.of_node, node) {
+ struct i2c_board_info info = {};
+ struct dev_archdata dev_ad = {};
+ const __be32 *reg;
+ char tmp[16];
+ u32 addr;
+ int len;
+
+ /* Get address & channel */
+ reg = of_get_property(node, "reg", &len);
+ if (!reg || (len < sizeof(int))) {
+ dev_err(&adap->dev, "i2c-powermac: invalid reg on %s\n",
+ node->full_name);
+ continue;
+ }
+ addr = be32_to_cpup(reg);
+
+ /* Multibus setup, check channel */
+ if (!pmac_i2c_match_adapter(node, adap))
+ continue;
+
+ dev_dbg(&adap->dev, "i2c-powermac: register %s\n",
+ node->full_name);
+
+ /* Make up a modalias. Note: we to _NOT_ want the standard
+ * i2c drivers to match with any of our powermac stuff
+ * unless they have been specifically modified to handle
+ * it on a case by case basis. For example, for thermal
+ * control, things like lm75 etc... shall match with their
+ * corresponding windfarm drivers, _NOT_ the generic ones,
+ * so we force a prefix of AAPL, onto the modalias to
+ * make that happen
+ */
+ if (of_modalias_node(node, tmp, sizeof(tmp)) < 0) {
+ dev_err(&adap->dev, "i2c-powermac: modalias failure"
+ " on %s\n", node->full_name);
+ continue;
+ }
+ snprintf(info.type, sizeof(info.type), "MAC,%s", tmp);
+
+ /* Fill out the rest of the info structure */
+ info.addr = (addr & 0xff) >> 1;
+ info.irq = irq_of_parse_and_map(node, 0);
+ info.of_node = of_node_get(node);
+ info.archdata = &dev_ad;
+
+ newdev = i2c_new_device(adap, &info);
+ if (!newdev) {
+ dev_err(&adap->dev, "i2c-powermac: Failure to register"
+ " %s\n", node->full_name);
+ of_node_put(node);
+ /* We do not dispose of the interrupt mapping on
+ * purpose. It's not necessary (interrupt cannot be
+ * re-used) and somebody else might have grabbed it
+ * via direct DT lookup so let's not bother
+ */
+ continue;
+ }
+ }
+}
static int __devinit i2c_powermac_probe(struct platform_device *dev)
{
@@ -272,6 +338,7 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
adapter->algo = &i2c_powermac_algorithm;
i2c_set_adapdata(adapter, bus);
adapter->dev.parent = &dev->dev;
+ adapter->dev.of_node = dev->dev.of_node;
rc = i2c_add_adapter(adapter);
if (rc) {
printk(KERN_ERR "i2c-powermac: Adapter %s registration "
@@ -281,33 +348,10 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name);
- if (!strncmp(basename, "uni-n", 5)) {
- struct device_node *np;
- const u32 *prop;
- struct i2c_board_info info;
-
- /* Instantiate I2C motion sensor if present */
- np = of_find_node_by_name(NULL, "accelerometer");
- if (np && of_device_is_compatible(np, "AAPL,accelerometer_1") &&
- (prop = of_get_property(np, "reg", NULL))) {
- int i2c_bus;
- const char *tmp_bus;
-
- /* look for bus either using "reg" or by path */
- tmp_bus = strstr(np->full_name, "/i2c-bus@");
- if (tmp_bus)
- i2c_bus = *(tmp_bus + 9) - '0';
- else
- i2c_bus = ((*prop) >> 8) & 0x0f;
-
- if (pmac_i2c_get_channel(bus) == i2c_bus) {
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = ((*prop) & 0xff) >> 1;
- strlcpy(info.type, "ams", I2C_NAME_SIZE);
- i2c_new_device(adapter, &info);
- }
- }
- }
+ /* Cannot use of_i2c_register_devices() due to Apple device-tree
+ * funkyness
+ */
+ i2c_powermac_register_devices(adapter, bus);
return rc;
}
diff --git a/drivers/i2c/busses/i2c-s6000.c b/drivers/i2c/busses/i2c-s6000.c
index c64ba736f480..b76a29d1f8e4 100644
--- a/drivers/i2c/busses/i2c-s6000.c
+++ b/drivers/i2c/busses/i2c-s6000.c
@@ -3,7 +3,7 @@
*
* Description: Driver for S6000 Family I2C Interface
* Copyright (c) 2008 emlix GmbH
- * Author: Oskar Schirmer <os@emlix.com>
+ * Author: Oskar Schirmer <oskar@scara.com>
*
* Partially based on i2c-bfin-twi.c driver by <sonic.zhang@analog.com>
* Copyright (c) 2005-2007 Analog Devices, Inc.
diff --git a/drivers/i2c/busses/i2c-s6000.h b/drivers/i2c/busses/i2c-s6000.h
index ff23b81ded44..4936f9f2256f 100644
--- a/drivers/i2c/busses/i2c-s6000.h
+++ b/drivers/i2c/busses/i2c-s6000.h
@@ -6,7 +6,7 @@
* for more details.
*
* Copyright (C) 2008 Emlix GmbH <info@emlix.com>
- * Author: Oskar Schirmer <os@emlix.com>
+ * Author: Oskar Schirmer <oskar@scara.com>
*/
#ifndef __DRIVERS_I2C_BUSSES_I2C_S6000_H
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
new file mode 100644
index 000000000000..56eecefcec75
--- /dev/null
+++ b/drivers/iio/Kconfig
@@ -0,0 +1,54 @@
+#
+# Industrial I/O subsytem configuration
+#
+
+menuconfig IIO
+ tristate "Industrial I/O support"
+ depends on GENERIC_HARDIRQS
+ help
+ The industrial I/O subsystem provides a unified framework for
+ drivers for many different types of embedded sensors using a
+ number of different physical interfaces (i2c, spi, etc). See
+ Documentation/iio for more information.
+
+if IIO
+
+config IIO_BUFFER
+ bool "Enable buffer support within IIO"
+ help
+ Provide core support for various buffer based data
+ acquisition methods.
+
+if IIO_BUFFER
+
+config IIO_KFIFO_BUF
+ select IIO_TRIGGER
+ tristate "Industrial I/O buffering based on kfifo"
+ help
+ A simple fifo based on kfifo. Use this if you want a fifo
+ rather than a ring buffer. Note that this currently provides
+ no buffer events so it is up to userspace to work out how
+ often to read from the buffer.
+
+endif # IIO_BUFFER
+
+config IIO_TRIGGER
+ boolean "Enable triggered sampling support"
+ help
+ Provides IIO core support for triggers. Currently these
+ are used to initialize capture of samples to push into
+ ring buffers. The triggers are effectively a 'capture
+ data now' interrupt.
+
+config IIO_CONSUMERS_PER_TRIGGER
+ int "Maximum number of consumers per trigger"
+ depends on IIO_TRIGGER
+ default "2"
+ help
+ This value controls the maximum number of consumers that a
+ given trigger may handle. Default is 2.
+
+source "drivers/iio/adc/Kconfig"
+source "drivers/iio/amplifiers/Kconfig"
+
+endif # IIO
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
new file mode 100644
index 000000000000..e425afd1480c
--- /dev/null
+++ b/drivers/iio/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the industrial I/O core.
+#
+
+obj-$(CONFIG_IIO) += industrialio.o
+industrialio-y := industrialio-core.o industrialio-event.o inkern.o
+industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o
+industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
+
+obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
+
+obj-y += adc/
+obj-y += amplifiers/
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
new file mode 100644
index 000000000000..9a0df8123cc4
--- /dev/null
+++ b/drivers/iio/adc/Kconfig
@@ -0,0 +1,16 @@
+#
+# ADC drivers
+#
+menu "Analog to digital converters"
+
+config AT91_ADC
+ tristate "Atmel AT91 ADC"
+ depends on ARCH_AT91
+ select IIO_BUFFER
+ select IIO_KFIFO_BUF
+ select IIO_TRIGGER
+ select SYSFS
+ help
+ Say yes here to build support for Atmel AT91 ADC.
+
+endmenu
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
new file mode 100644
index 000000000000..175c8d41ea99
--- /dev/null
+++ b/drivers/iio/adc/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for IIO ADC drivers
+#
+
+obj-$(CONFIG_AT91_ADC) += at91_adc.o
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
new file mode 100644
index 000000000000..f18a95d80255
--- /dev/null
+++ b/drivers/iio/adc/at91_adc.c
@@ -0,0 +1,802 @@
+/*
+ * Driver for the ADC present in the Atmel AT91 evaluation boards.
+ *
+ * Copyright 2011 Free Electrons
+ *
+ * Licensed under the GPLv2 or later.
+ */
+
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+
+#include <linux/platform_data/at91_adc.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+
+#include <mach/at91_adc.h>
+
+#define AT91_ADC_CHAN(st, ch) \
+ (st->registers->channel_base + (ch * 4))
+#define at91_adc_readl(st, reg) \
+ (readl_relaxed(st->reg_base + reg))
+#define at91_adc_writel(st, reg, val) \
+ (writel_relaxed(val, st->reg_base + reg))
+
+struct at91_adc_state {
+ struct clk *adc_clk;
+ u16 *buffer;
+ unsigned long channels_mask;
+ struct clk *clk;
+ bool done;
+ int irq;
+ bool irq_enabled;
+ u16 last_value;
+ struct mutex lock;
+ u8 num_channels;
+ void __iomem *reg_base;
+ struct at91_adc_reg_desc *registers;
+ u8 startup_time;
+ struct iio_trigger **trig;
+ struct at91_adc_trigger *trigger_list;
+ u32 trigger_number;
+ bool use_external;
+ u32 vref_mv;
+ wait_queue_head_t wq_data_avail;
+};
+
+static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *idev = pf->indio_dev;
+ struct at91_adc_state *st = iio_priv(idev);
+ struct iio_buffer *buffer = idev->buffer;
+ int i, j = 0;
+
+ for (i = 0; i < idev->masklength; i++) {
+ if (!test_bit(i, idev->active_scan_mask))
+ continue;
+ st->buffer[j] = at91_adc_readl(st, AT91_ADC_CHAN(st, i));
+ j++;
+ }
+
+ if (idev->scan_timestamp) {
+ s64 *timestamp = (s64 *)((u8 *)st->buffer +
+ ALIGN(j, sizeof(s64)));
+ *timestamp = pf->timestamp;
+ }
+
+ buffer->access->store_to(buffer, (u8 *)st->buffer, pf->timestamp);
+
+ iio_trigger_notify_done(idev->trig);
+ st->irq_enabled = true;
+
+ /* Needed to ACK the DRDY interruption */
+ at91_adc_readl(st, AT91_ADC_LCDR);
+
+ enable_irq(st->irq);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t at91_adc_eoc_trigger(int irq, void *private)
+{
+ struct iio_dev *idev = private;
+ struct at91_adc_state *st = iio_priv(idev);
+ u32 status = at91_adc_readl(st, st->registers->status_register);
+
+ if (!(status & st->registers->drdy_mask))
+ return IRQ_HANDLED;
+
+ if (iio_buffer_enabled(idev)) {
+ disable_irq_nosync(irq);
+ st->irq_enabled = false;
+ iio_trigger_poll(idev->trig, iio_get_time_ns());
+ } else {
+ st->last_value = at91_adc_readl(st, AT91_ADC_LCDR);
+ st->done = true;
+ wake_up_interruptible(&st->wq_data_avail);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int at91_adc_channel_init(struct iio_dev *idev)
+{
+ struct at91_adc_state *st = iio_priv(idev);
+ struct iio_chan_spec *chan_array, *timestamp;
+ int bit, idx = 0;
+
+ idev->num_channels = bitmap_weight(&st->channels_mask,
+ st->num_channels) + 1;
+
+ chan_array = devm_kzalloc(&idev->dev,
+ ((idev->num_channels + 1) *
+ sizeof(struct iio_chan_spec)),
+ GFP_KERNEL);
+
+ if (!chan_array)
+ return -ENOMEM;
+
+ for_each_set_bit(bit, &st->channels_mask, st->num_channels) {
+ struct iio_chan_spec *chan = chan_array + idx;
+
+ chan->type = IIO_VOLTAGE;
+ chan->indexed = 1;
+ chan->channel = bit;
+ chan->scan_index = idx;
+ chan->scan_type.sign = 'u';
+ chan->scan_type.realbits = 10;
+ chan->scan_type.storagebits = 16;
+ chan->info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_RAW_SEPARATE_BIT;
+ idx++;
+ }
+ timestamp = chan_array + idx;
+
+ timestamp->type = IIO_TIMESTAMP;
+ timestamp->channel = -1;
+ timestamp->scan_index = idx;
+ timestamp->scan_type.sign = 's';
+ timestamp->scan_type.realbits = 64;
+ timestamp->scan_type.storagebits = 64;
+
+ idev->channels = chan_array;
+ return idev->num_channels;
+}
+
+static u8 at91_adc_get_trigger_value_by_name(struct iio_dev *idev,
+ struct at91_adc_trigger *triggers,
+ const char *trigger_name)
+{
+ struct at91_adc_state *st = iio_priv(idev);
+ u8 value = 0;
+ int i;
+
+ for (i = 0; i < st->trigger_number; i++) {
+ char *name = kasprintf(GFP_KERNEL,
+ "%s-dev%d-%s",
+ idev->name,
+ idev->id,
+ triggers[i].name);
+ if (!name)
+ return -ENOMEM;
+
+ if (strcmp(trigger_name, name) == 0) {
+ value = triggers[i].value;
+ kfree(name);
+ break;
+ }
+
+ kfree(name);
+ }
+
+ return value;
+}
+
+static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *idev = trig->private_data;
+ struct at91_adc_state *st = iio_priv(idev);
+ struct iio_buffer *buffer = idev->buffer;
+ struct at91_adc_reg_desc *reg = st->registers;
+ u32 status = at91_adc_readl(st, reg->trigger_register);
+ u8 value;
+ u8 bit;
+
+ value = at91_adc_get_trigger_value_by_name(idev,
+ st->trigger_list,
+ idev->trig->name);
+ if (value == 0)
+ return -EINVAL;
+
+ if (state) {
+ st->buffer = kmalloc(idev->scan_bytes, GFP_KERNEL);
+ if (st->buffer == NULL)
+ return -ENOMEM;
+
+ at91_adc_writel(st, reg->trigger_register,
+ status | value);
+
+ for_each_set_bit(bit, buffer->scan_mask,
+ st->num_channels) {
+ struct iio_chan_spec const *chan = idev->channels + bit;
+ at91_adc_writel(st, AT91_ADC_CHER,
+ AT91_ADC_CH(chan->channel));
+ }
+
+ at91_adc_writel(st, AT91_ADC_IER, reg->drdy_mask);
+
+ } else {
+ at91_adc_writel(st, AT91_ADC_IDR, reg->drdy_mask);
+
+ at91_adc_writel(st, reg->trigger_register,
+ status & ~value);
+
+ for_each_set_bit(bit, buffer->scan_mask,
+ st->num_channels) {
+ struct iio_chan_spec const *chan = idev->channels + bit;
+ at91_adc_writel(st, AT91_ADC_CHDR,
+ AT91_ADC_CH(chan->channel));
+ }
+ kfree(st->buffer);
+ }
+
+ return 0;
+}
+
+static const struct iio_trigger_ops at91_adc_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &at91_adc_configure_trigger,
+};
+
+static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *idev,
+ struct at91_adc_trigger *trigger)
+{
+ struct iio_trigger *trig;
+ int ret;
+
+ trig = iio_trigger_alloc("%s-dev%d-%s", idev->name,
+ idev->id, trigger->name);
+ if (trig == NULL)
+ return NULL;
+
+ trig->dev.parent = idev->dev.parent;
+ trig->private_data = idev;
+ trig->ops = &at91_adc_trigger_ops;
+
+ ret = iio_trigger_register(trig);
+ if (ret)
+ return NULL;
+
+ return trig;
+}
+
+static int at91_adc_trigger_init(struct iio_dev *idev)
+{
+ struct at91_adc_state *st = iio_priv(idev);
+ int i, ret;
+
+ st->trig = devm_kzalloc(&idev->dev,
+ st->trigger_number * sizeof(st->trig),
+ GFP_KERNEL);
+
+ if (st->trig == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+
+ for (i = 0; i < st->trigger_number; i++) {
+ if (st->trigger_list[i].is_external && !(st->use_external))
+ continue;
+
+ st->trig[i] = at91_adc_allocate_trigger(idev,
+ st->trigger_list + i);
+ if (st->trig[i] == NULL) {
+ dev_err(&idev->dev,
+ "Could not allocate trigger %d\n", i);
+ ret = -ENOMEM;
+ goto error_trigger;
+ }
+ }
+
+ return 0;
+
+error_trigger:
+ for (i--; i >= 0; i--) {
+ iio_trigger_unregister(st->trig[i]);
+ iio_trigger_free(st->trig[i]);
+ }
+error_ret:
+ return ret;
+}
+
+static void at91_adc_trigger_remove(struct iio_dev *idev)
+{
+ struct at91_adc_state *st = iio_priv(idev);
+ int i;
+
+ for (i = 0; i < st->trigger_number; i++) {
+ iio_trigger_unregister(st->trig[i]);
+ iio_trigger_free(st->trig[i]);
+ }
+}
+
+static const struct iio_buffer_setup_ops at91_adc_buffer_ops = {
+ .preenable = &iio_sw_buffer_preenable,
+ .postenable = &iio_triggered_buffer_postenable,
+ .predisable = &iio_triggered_buffer_predisable,
+};
+
+static int at91_adc_buffer_init(struct iio_dev *idev)
+{
+ int ret;
+
+ idev->buffer = iio_kfifo_allocate(idev);
+ if (!idev->buffer) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+
+ idev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+ &at91_adc_trigger_handler,
+ IRQF_ONESHOT,
+ idev,
+ "%s-consumer%d",
+ idev->name,
+ idev->id);
+ if (idev->pollfunc == NULL) {
+ ret = -ENOMEM;
+ goto error_pollfunc;
+ }
+
+ idev->setup_ops = &at91_adc_buffer_ops;
+ idev->modes |= INDIO_BUFFER_TRIGGERED;
+
+ ret = iio_buffer_register(idev,
+ idev->channels,
+ idev->num_channels);
+ if (ret)
+ goto error_register;
+
+ return 0;
+
+error_register:
+ iio_dealloc_pollfunc(idev->pollfunc);
+error_pollfunc:
+ iio_kfifo_free(idev->buffer);
+error_ret:
+ return ret;
+}
+
+static void at91_adc_buffer_remove(struct iio_dev *idev)
+{
+ iio_buffer_unregister(idev);
+ iio_dealloc_pollfunc(idev->pollfunc);
+ iio_kfifo_free(idev->buffer);
+}
+
+static int at91_adc_read_raw(struct iio_dev *idev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct at91_adc_state *st = iio_priv(idev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&st->lock);
+
+ at91_adc_writel(st, AT91_ADC_CHER,
+ AT91_ADC_CH(chan->channel));
+ at91_adc_writel(st, AT91_ADC_IER, st->registers->drdy_mask);
+ at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_START);
+
+ ret = wait_event_interruptible_timeout(st->wq_data_avail,
+ st->done,
+ msecs_to_jiffies(1000));
+ if (ret == 0)
+ return -ETIMEDOUT;
+ else if (ret < 0)
+ return ret;
+
+ *val = st->last_value;
+
+ at91_adc_writel(st, AT91_ADC_CHDR,
+ AT91_ADC_CH(chan->channel));
+ at91_adc_writel(st, AT91_ADC_IDR, st->registers->drdy_mask);
+
+ st->last_value = 0;
+ st->done = false;
+ mutex_unlock(&st->lock);
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ *val = (st->vref_mv * 1000) >> chan->scan_type.realbits;
+ *val2 = 0;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ break;
+ }
+ return -EINVAL;
+}
+
+static int at91_adc_probe_dt(struct at91_adc_state *st,
+ struct platform_device *pdev)
+{
+ struct iio_dev *idev = iio_priv_to_dev(st);
+ struct device_node *node = pdev->dev.of_node;
+ struct device_node *trig_node;
+ int i = 0, ret;
+ u32 prop;
+
+ if (!node)
+ return -EINVAL;
+
+ st->use_external = of_property_read_bool(node, "atmel,adc-use-external-triggers");
+
+ if (of_property_read_u32(node, "atmel,adc-channels-used", &prop)) {
+ dev_err(&idev->dev, "Missing adc-channels-used property in the DT.\n");
+ ret = -EINVAL;
+ goto error_ret;
+ }
+ st->channels_mask = prop;
+
+ if (of_property_read_u32(node, "atmel,adc-num-channels", &prop)) {
+ dev_err(&idev->dev, "Missing adc-num-channels property in the DT.\n");
+ ret = -EINVAL;
+ goto error_ret;
+ }
+ st->num_channels = prop;
+
+ if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) {
+ dev_err(&idev->dev, "Missing adc-startup-time property in the DT.\n");
+ ret = -EINVAL;
+ goto error_ret;
+ }
+ st->startup_time = prop;
+
+
+ if (of_property_read_u32(node, "atmel,adc-vref", &prop)) {
+ dev_err(&idev->dev, "Missing adc-vref property in the DT.\n");
+ ret = -EINVAL;
+ goto error_ret;
+ }
+ st->vref_mv = prop;
+
+ st->registers = devm_kzalloc(&idev->dev,
+ sizeof(struct at91_adc_reg_desc),
+ GFP_KERNEL);
+ if (!st->registers) {
+ dev_err(&idev->dev, "Could not allocate register memory.\n");
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+
+ if (of_property_read_u32(node, "atmel,adc-channel-base", &prop)) {
+ dev_err(&idev->dev, "Missing adc-channel-base property in the DT.\n");
+ ret = -EINVAL;
+ goto error_ret;
+ }
+ st->registers->channel_base = prop;
+
+ if (of_property_read_u32(node, "atmel,adc-drdy-mask", &prop)) {
+ dev_err(&idev->dev, "Missing adc-drdy-mask property in the DT.\n");
+ ret = -EINVAL;
+ goto error_ret;
+ }
+ st->registers->drdy_mask = prop;
+
+ if (of_property_read_u32(node, "atmel,adc-status-register", &prop)) {
+ dev_err(&idev->dev, "Missing adc-status-register property in the DT.\n");
+ ret = -EINVAL;
+ goto error_ret;
+ }
+ st->registers->status_register = prop;
+
+ if (of_property_read_u32(node, "atmel,adc-trigger-register", &prop)) {
+ dev_err(&idev->dev, "Missing adc-trigger-register property in the DT.\n");
+ ret = -EINVAL;
+ goto error_ret;
+ }
+ st->registers->trigger_register = prop;
+
+ st->trigger_number = of_get_child_count(node);
+ st->trigger_list = devm_kzalloc(&idev->dev, st->trigger_number *
+ sizeof(struct at91_adc_trigger),
+ GFP_KERNEL);
+ if (!st->trigger_list) {
+ dev_err(&idev->dev, "Could not allocate trigger list memory.\n");
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+
+ for_each_child_of_node(node, trig_node) {
+ struct at91_adc_trigger *trig = st->trigger_list + i;
+ const char *name;
+
+ if (of_property_read_string(trig_node, "trigger-name", &name)) {
+ dev_err(&idev->dev, "Missing trigger-name property in the DT.\n");
+ ret = -EINVAL;
+ goto error_ret;
+ }
+ trig->name = name;
+
+ if (of_property_read_u32(trig_node, "trigger-value", &prop)) {
+ dev_err(&idev->dev, "Missing trigger-value property in the DT.\n");
+ ret = -EINVAL;
+ goto error_ret;
+ }
+ trig->value = prop;
+ trig->is_external = of_property_read_bool(trig_node, "trigger-external");
+ i++;
+ }
+
+ return 0;
+
+error_ret:
+ return ret;
+}
+
+static int at91_adc_probe_pdata(struct at91_adc_state *st,
+ struct platform_device *pdev)
+{
+ struct at91_adc_data *pdata = pdev->dev.platform_data;
+
+ if (!pdata)
+ return -EINVAL;
+
+ st->use_external = pdata->use_external_triggers;
+ st->vref_mv = pdata->vref;
+ st->channels_mask = pdata->channels_used;
+ st->num_channels = pdata->num_channels;
+ st->startup_time = pdata->startup_time;
+ st->trigger_number = pdata->trigger_number;
+ st->trigger_list = pdata->trigger_list;
+ st->registers = pdata->registers;
+
+ return 0;
+}
+
+static const struct iio_info at91_adc_info = {
+ .driver_module = THIS_MODULE,
+ .read_raw = &at91_adc_read_raw,
+};
+
+static int __devinit at91_adc_probe(struct platform_device *pdev)
+{
+ unsigned int prsc, mstrclk, ticks, adc_clk;
+ int ret;
+ struct iio_dev *idev;
+ struct at91_adc_state *st;
+ struct resource *res;
+
+ idev = iio_device_alloc(sizeof(struct at91_adc_state));
+ if (idev == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+
+ st = iio_priv(idev);
+
+ if (pdev->dev.of_node)
+ ret = at91_adc_probe_dt(st, pdev);
+ else
+ ret = at91_adc_probe_pdata(st, pdev);
+
+ if (ret) {
+ dev_err(&pdev->dev, "No platform data available.\n");
+ ret = -EINVAL;
+ goto error_free_device;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "No resource defined\n");
+ ret = -ENXIO;
+ goto error_ret;
+ }
+
+ platform_set_drvdata(pdev, idev);
+
+ idev->dev.parent = &pdev->dev;
+ idev->name = dev_name(&pdev->dev);
+ idev->modes = INDIO_DIRECT_MODE;
+ idev->info = &at91_adc_info;
+
+ st->irq = platform_get_irq(pdev, 0);
+ if (st->irq < 0) {
+ dev_err(&pdev->dev, "No IRQ ID is designated\n");
+ ret = -ENODEV;
+ goto error_free_device;
+ }
+
+ if (!request_mem_region(res->start, resource_size(res),
+ "AT91 adc registers")) {
+ dev_err(&pdev->dev, "Resources are unavailable.\n");
+ ret = -EBUSY;
+ goto error_free_device;
+ }
+
+ st->reg_base = ioremap(res->start, resource_size(res));
+ if (!st->reg_base) {
+ dev_err(&pdev->dev, "Failed to map registers.\n");
+ ret = -ENOMEM;
+ goto error_release_mem;
+ }
+
+ /*
+ * Disable all IRQs before setting up the handler
+ */
+ at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_SWRST);
+ at91_adc_writel(st, AT91_ADC_IDR, 0xFFFFFFFF);
+ ret = request_irq(st->irq,
+ at91_adc_eoc_trigger,
+ 0,
+ pdev->dev.driver->name,
+ idev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to allocate IRQ.\n");
+ goto error_unmap_reg;
+ }
+
+ st->clk = clk_get(&pdev->dev, "adc_clk");
+ if (IS_ERR(st->clk)) {
+ dev_err(&pdev->dev, "Failed to get the clock.\n");
+ ret = PTR_ERR(st->clk);
+ goto error_free_irq;
+ }
+
+ ret = clk_prepare(st->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not prepare the clock.\n");
+ goto error_free_clk;
+ }
+
+ ret = clk_enable(st->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not enable the clock.\n");
+ goto error_unprepare_clk;
+ }
+
+ st->adc_clk = clk_get(&pdev->dev, "adc_op_clk");
+ if (IS_ERR(st->adc_clk)) {
+ dev_err(&pdev->dev, "Failed to get the ADC clock.\n");
+ ret = PTR_ERR(st->clk);
+ goto error_disable_clk;
+ }
+
+ ret = clk_prepare(st->adc_clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not prepare the ADC clock.\n");
+ goto error_free_adc_clk;
+ }
+
+ ret = clk_enable(st->adc_clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not enable the ADC clock.\n");
+ goto error_unprepare_adc_clk;
+ }
+
+ /*
+ * Prescaler rate computation using the formula from the Atmel's
+ * datasheet : ADC Clock = MCK / ((Prescaler + 1) * 2), ADC Clock being
+ * specified by the electrical characteristics of the board.
+ */
+ mstrclk = clk_get_rate(st->clk);
+ adc_clk = clk_get_rate(st->adc_clk);
+ prsc = (mstrclk / (2 * adc_clk)) - 1;
+
+ if (!st->startup_time) {
+ dev_err(&pdev->dev, "No startup time available.\n");
+ ret = -EINVAL;
+ goto error_disable_adc_clk;
+ }
+
+ /*
+ * Number of ticks needed to cover the startup time of the ADC as
+ * defined in the electrical characteristics of the board, divided by 8.
+ * The formula thus is : Startup Time = (ticks + 1) * 8 / ADC Clock
+ */
+ ticks = round_up((st->startup_time * adc_clk /
+ 1000000) - 1, 8) / 8;
+ at91_adc_writel(st, AT91_ADC_MR,
+ (AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
+ (AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
+
+ /* Setup the ADC channels available on the board */
+ ret = at91_adc_channel_init(idev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Couldn't initialize the channels.\n");
+ goto error_disable_adc_clk;
+ }
+
+ init_waitqueue_head(&st->wq_data_avail);
+ mutex_init(&st->lock);
+
+ ret = at91_adc_buffer_init(idev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Couldn't initialize the buffer.\n");
+ goto error_disable_adc_clk;
+ }
+
+ ret = at91_adc_trigger_init(idev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Couldn't setup the triggers.\n");
+ goto error_unregister_buffer;
+ }
+
+ ret = iio_device_register(idev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Couldn't register the device.\n");
+ goto error_remove_triggers;
+ }
+
+ return 0;
+
+error_remove_triggers:
+ at91_adc_trigger_remove(idev);
+error_unregister_buffer:
+ at91_adc_buffer_remove(idev);
+error_disable_adc_clk:
+ clk_disable(st->adc_clk);
+error_unprepare_adc_clk:
+ clk_unprepare(st->adc_clk);
+error_free_adc_clk:
+ clk_put(st->adc_clk);
+error_disable_clk:
+ clk_disable(st->clk);
+error_unprepare_clk:
+ clk_unprepare(st->clk);
+error_free_clk:
+ clk_put(st->clk);
+error_free_irq:
+ free_irq(st->irq, idev);
+error_unmap_reg:
+ iounmap(st->reg_base);
+error_release_mem:
+ release_mem_region(res->start, resource_size(res));
+error_free_device:
+ iio_device_free(idev);
+error_ret:
+ return ret;
+}
+
+static int __devexit at91_adc_remove(struct platform_device *pdev)
+{
+ struct iio_dev *idev = platform_get_drvdata(pdev);
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct at91_adc_state *st = iio_priv(idev);
+
+ iio_device_unregister(idev);
+ at91_adc_trigger_remove(idev);
+ at91_adc_buffer_remove(idev);
+ clk_disable_unprepare(st->adc_clk);
+ clk_put(st->adc_clk);
+ clk_disable(st->clk);
+ clk_unprepare(st->clk);
+ clk_put(st->clk);
+ free_irq(st->irq, idev);
+ iounmap(st->reg_base);
+ release_mem_region(res->start, resource_size(res));
+ iio_device_free(idev);
+
+ return 0;
+}
+
+static const struct of_device_id at91_adc_dt_ids[] = {
+ { .compatible = "atmel,at91sam9260-adc" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
+
+static struct platform_driver at91_adc_driver = {
+ .probe = at91_adc_probe,
+ .remove = __devexit_p(at91_adc_remove),
+ .driver = {
+ .name = "at91_adc",
+ .of_match_table = of_match_ptr(at91_adc_dt_ids),
+ },
+};
+
+module_platform_driver(at91_adc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Atmel AT91 ADC Driver");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
diff --git a/drivers/iio/amplifiers/Kconfig b/drivers/iio/amplifiers/Kconfig
new file mode 100644
index 000000000000..05d707ed7d4f
--- /dev/null
+++ b/drivers/iio/amplifiers/Kconfig
@@ -0,0 +1,17 @@
+#
+# Gain Amplifiers, etc.
+#
+menu "Amplifiers"
+
+config AD8366
+ tristate "Analog Devices AD8366 VGA"
+ depends on SPI
+ select BITREVERSE
+ help
+ Say yes here to build support for Analog Devices AD8366
+ SPI Dual-Digital Variable Gain Amplifier (VGA).
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad8366.
+
+endmenu
diff --git a/drivers/iio/amplifiers/Makefile b/drivers/iio/amplifiers/Makefile
new file mode 100644
index 000000000000..a6ca366908e0
--- /dev/null
+++ b/drivers/iio/amplifiers/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile iio/amplifiers
+#
+
+obj-$(CONFIG_AD8366) += ad8366.o
diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c
new file mode 100644
index 000000000000..d8281cdbfc4a
--- /dev/null
+++ b/drivers/iio/amplifiers/ad8366.c
@@ -0,0 +1,222 @@
+/*
+ * AD8366 SPI Dual-Digital Variable Gain Amplifier (VGA)
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/bitrev.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+struct ad8366_state {
+ struct spi_device *spi;
+ struct regulator *reg;
+ unsigned char ch[2];
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ unsigned char data[2] ____cacheline_aligned;
+};
+
+static int ad8366_write(struct iio_dev *indio_dev,
+ unsigned char ch_a, char unsigned ch_b)
+{
+ struct ad8366_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ch_a = bitrev8(ch_a & 0x3F);
+ ch_b = bitrev8(ch_b & 0x3F);
+
+ st->data[0] = ch_b >> 4;
+ st->data[1] = (ch_b << 4) | (ch_a >> 2);
+
+ ret = spi_write(st->spi, st->data, ARRAY_SIZE(st->data));
+ if (ret < 0)
+ dev_err(&indio_dev->dev, "write failed (%d)", ret);
+
+ return ret;
+}
+
+static int ad8366_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long m)
+{
+ struct ad8366_state *st = iio_priv(indio_dev);
+ int ret;
+ unsigned code;
+
+ mutex_lock(&indio_dev->mlock);
+ switch (m) {
+ case IIO_CHAN_INFO_HARDWAREGAIN:
+ code = st->ch[chan->channel];
+
+ /* Values in dB */
+ code = code * 253 + 4500;
+ *val = code / 1000;
+ *val2 = (code % 1000) * 1000;
+
+ ret = IIO_VAL_INT_PLUS_MICRO_DB;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
+};
+
+static int ad8366_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ struct ad8366_state *st = iio_priv(indio_dev);
+ unsigned code;
+ int ret;
+
+ if (val < 0 || val2 < 0)
+ return -EINVAL;
+
+ /* Values in dB */
+ code = (((u8)val * 1000) + ((u32)val2 / 1000));
+
+ if (code > 20500 || code < 4500)
+ return -EINVAL;
+
+ code = (code - 4500) / 253;
+
+ mutex_lock(&indio_dev->mlock);
+ switch (mask) {
+ case IIO_CHAN_INFO_HARDWAREGAIN:
+ st->ch[chan->channel] = code;
+ ret = ad8366_write(indio_dev, st->ch[0], st->ch[1]);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
+}
+
+static const struct iio_info ad8366_info = {
+ .read_raw = &ad8366_read_raw,
+ .write_raw = &ad8366_write_raw,
+ .driver_module = THIS_MODULE,
+};
+
+#define AD8366_CHAN(_channel) { \
+ .type = IIO_VOLTAGE, \
+ .output = 1, \
+ .indexed = 1, \
+ .channel = _channel, \
+ .info_mask = IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT,\
+}
+
+static const struct iio_chan_spec ad8366_channels[] = {
+ AD8366_CHAN(0),
+ AD8366_CHAN(1),
+};
+
+static int __devinit ad8366_probe(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev;
+ struct ad8366_state *st;
+ int ret;
+
+ indio_dev = iio_device_alloc(sizeof(*st));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ st->reg = regulator_get(&spi->dev, "vcc");
+ if (!IS_ERR(st->reg)) {
+ ret = regulator_enable(st->reg);
+ if (ret)
+ goto error_put_reg;
+ }
+
+ spi_set_drvdata(spi, indio_dev);
+ st->spi = spi;
+
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->info = &ad8366_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = ad8366_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad8366_channels);
+
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_disable_reg;
+
+ ad8366_write(indio_dev, 0 , 0);
+
+ return 0;
+
+error_disable_reg:
+ if (!IS_ERR(st->reg))
+ regulator_disable(st->reg);
+error_put_reg:
+ if (!IS_ERR(st->reg))
+ regulator_put(st->reg);
+
+ iio_device_free(indio_dev);
+
+ return ret;
+}
+
+static int __devexit ad8366_remove(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad8366_state *st = iio_priv(indio_dev);
+ struct regulator *reg = st->reg;
+
+ iio_device_unregister(indio_dev);
+
+ if (!IS_ERR(reg)) {
+ regulator_disable(reg);
+ regulator_put(reg);
+ }
+
+ iio_device_free(indio_dev);
+
+ return 0;
+}
+
+static const struct spi_device_id ad8366_id[] = {
+ {"ad8366", 0},
+ {}
+};
+
+static struct spi_driver ad8366_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = ad8366_probe,
+ .remove = __devexit_p(ad8366_remove),
+ .id_table = ad8366_id,
+};
+
+module_spi_driver(ad8366_driver);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD8366 VGA");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/iio_core.h b/drivers/iio/iio_core.h
index c9dfcba0bac8..f652e6ae5a35 100644
--- a/drivers/staging/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -12,6 +12,12 @@
#ifndef _IIO_CORE_H_
#define _IIO_CORE_H_
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+struct iio_chan_spec;
+struct iio_dev;
+
int __iio_add_chan_devattr(const char *postfix,
struct iio_chan_spec const *chan,
diff --git a/drivers/staging/iio/iio_core_trigger.h b/drivers/iio/iio_core_trigger.h
index 6f7c56fcbe78..6f7c56fcbe78 100644
--- a/drivers/staging/iio/iio_core_trigger.h
+++ b/drivers/iio/iio_core_trigger.h
diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 386ba760f3f1..ac185b8694bd 100644
--- a/drivers/staging/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -21,10 +21,10 @@
#include <linux/slab.h>
#include <linux/poll.h>
-#include "iio.h"
+#include <linux/iio/iio.h>
#include "iio_core.h"
-#include "sysfs.h"
-#include "buffer.h"
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
static const char * const iio_endian_prefix[] = {
[IIO_BE] = "be",
@@ -105,7 +105,7 @@ static ssize_t iio_scan_el_show(struct device *dev,
char *buf)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
ret = test_bit(to_iio_dev_attr(attr)->address,
indio_dev->buffer->scan_mask);
@@ -124,13 +124,15 @@ static ssize_t iio_scan_el_store(struct device *dev,
const char *buf,
size_t len)
{
- int ret = 0;
+ int ret;
bool state;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_buffer *buffer = indio_dev->buffer;
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- state = !(buf[0] == '0');
+ ret = strtobool(buf, &state);
+ if (ret < 0)
+ return ret;
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) {
ret = -EBUSY;
@@ -160,7 +162,7 @@ static ssize_t iio_scan_el_ts_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
return sprintf(buf, "%d\n", indio_dev->buffer->scan_timestamp);
}
@@ -169,17 +171,21 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
const char *buf,
size_t len)
{
- int ret = 0;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ int ret;
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
bool state;
- state = !(buf[0] == '0');
+ ret = strtobool(buf, &state);
+ if (ret < 0)
+ return ret;
+
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) {
ret = -EBUSY;
goto error_ret;
}
indio_dev->buffer->scan_timestamp = state;
+ indio_dev->scan_timestamp = state;
error_ret:
mutex_unlock(&indio_dev->mlock);
@@ -291,7 +297,7 @@ int iio_buffer_register(struct iio_dev *indio_dev,
goto error_cleanup_dynamic;
attrcount += ret;
if (channels[i].type == IIO_TIMESTAMP)
- buffer->scan_index_timestamp =
+ indio_dev->scan_index_timestamp =
channels[i].scan_index;
}
if (indio_dev->masklength && buffer->scan_mask == NULL) {
@@ -346,7 +352,7 @@ ssize_t iio_buffer_read_length(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_buffer *buffer = indio_dev->buffer;
if (buffer->access->get_length)
@@ -364,7 +370,7 @@ ssize_t iio_buffer_write_length(struct device *dev,
{
int ret;
ulong val;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_buffer *buffer = indio_dev->buffer;
ret = strict_strtoul(buf, 10, &val);
@@ -397,7 +403,7 @@ ssize_t iio_buffer_store_enable(struct device *dev,
int ret;
bool requested_state, current_state;
int previous_mode;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_buffer *buffer = indio_dev->buffer;
mutex_lock(&indio_dev->mlock);
@@ -483,7 +489,7 @@ ssize_t iio_buffer_show_enable(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
return sprintf(buf, "%d\n", iio_buffer_enabled(indio_dev));
}
EXPORT_SYMBOL(iio_buffer_show_enable);
@@ -503,30 +509,41 @@ static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
return NULL;
}
-int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
+static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask,
+ bool timestamp)
{
- struct iio_buffer *buffer = indio_dev->buffer;
const struct iio_chan_spec *ch;
unsigned bytes = 0;
int length, i;
- dev_dbg(&indio_dev->dev, "%s\n", __func__);
/* How much space will the demuxed element take? */
- for_each_set_bit(i, buffer->scan_mask,
+ for_each_set_bit(i, mask,
indio_dev->masklength) {
ch = iio_find_channel_from_si(indio_dev, i);
- length = ch->scan_type.storagebits/8;
+ length = ch->scan_type.storagebits / 8;
bytes = ALIGN(bytes, length);
bytes += length;
}
- if (buffer->scan_timestamp) {
+ if (timestamp) {
ch = iio_find_channel_from_si(indio_dev,
- buffer->scan_index_timestamp);
- length = ch->scan_type.storagebits/8;
+ indio_dev->scan_index_timestamp);
+ length = ch->scan_type.storagebits / 8;
bytes = ALIGN(bytes, length);
bytes += length;
}
- buffer->access->set_bytes_per_datum(buffer, bytes);
+ return bytes;
+}
+
+int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct iio_buffer *buffer = indio_dev->buffer;
+ dev_dbg(&indio_dev->dev, "%s\n", __func__);
+
+ /* How much space will the demuxed element take? */
+ indio_dev->scan_bytes =
+ iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
+ buffer->scan_timestamp);
+ buffer->access->set_bytes_per_datum(buffer, indio_dev->scan_bytes);
/* What scan mask do we actually have ?*/
if (indio_dev->available_scan_masks)
@@ -638,19 +655,25 @@ int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
}
EXPORT_SYMBOL_GPL(iio_push_to_buffer);
+static void iio_buffer_demux_free(struct iio_buffer *buffer)
+{
+ struct iio_demux_table *p, *q;
+ list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
+ list_del(&p->l);
+ kfree(p);
+ }
+}
+
int iio_update_demux(struct iio_dev *indio_dev)
{
const struct iio_chan_spec *ch;
struct iio_buffer *buffer = indio_dev->buffer;
int ret, in_ind = -1, out_ind, length;
unsigned in_loc = 0, out_loc = 0;
- struct iio_demux_table *p, *q;
+ struct iio_demux_table *p;
/* Clear out any old demux */
- list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
- list_del(&p->l);
- kfree(p);
- }
+ iio_buffer_demux_free(buffer);
kfree(buffer->demux_bounce);
buffer->demux_bounce = NULL;
@@ -704,7 +727,7 @@ int iio_update_demux(struct iio_dev *indio_dev)
goto error_clear_mux_table;
}
ch = iio_find_channel_from_si(indio_dev,
- buffer->scan_index_timestamp);
+ indio_dev->scan_index_timestamp);
length = ch->scan_type.storagebits/8;
if (out_loc % length)
out_loc += length - out_loc % length;
@@ -725,10 +748,8 @@ int iio_update_demux(struct iio_dev *indio_dev)
return 0;
error_clear_mux_table:
- list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
- list_del(&p->l);
- kfree(p);
- }
+ iio_buffer_demux_free(buffer);
+
return ret;
}
EXPORT_SYMBOL_GPL(iio_update_demux);
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index d303bfbff27f..1ddd8861c71b 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -23,11 +23,11 @@
#include <linux/slab.h>
#include <linux/anon_inodes.h>
#include <linux/debugfs.h>
-#include "iio.h"
+#include <linux/iio/iio.h>
#include "iio_core.h"
#include "iio_core_trigger.h"
-#include "sysfs.h"
-#include "events.h"
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
/* IDA to assign each registered device a unique id*/
static DEFINE_IDA(iio_ida);
@@ -42,11 +42,6 @@ EXPORT_SYMBOL(iio_bus_type);
static struct dentry *iio_debugfs_dentry;
-static const char * const iio_data_type_name[] = {
- [IIO_RAW] = "raw",
- [IIO_PROCESSED] = "input",
-};
-
static const char * const iio_direction[] = {
[0] = "in",
[1] = "out",
@@ -68,6 +63,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_ANGL] = "angl",
[IIO_TIMESTAMP] = "timestamp",
[IIO_CAPACITANCE] = "capacitance",
+ [IIO_ALTVOLTAGE] = "altvoltage",
};
static const char * const iio_modifier_names[] = {
@@ -80,6 +76,8 @@ static const char * const iio_modifier_names[] = {
/* relies on pairs of these shared then separate */
static const char * const iio_chan_info_postfix[] = {
+ [IIO_CHAN_INFO_RAW] = "raw",
+ [IIO_CHAN_INFO_PROCESSED] = "input",
[IIO_CHAN_INFO_SCALE] = "scale",
[IIO_CHAN_INFO_OFFSET] = "offset",
[IIO_CHAN_INFO_CALIBSCALE] = "calibscale",
@@ -90,6 +88,10 @@ static const char * const iio_chan_info_postfix[] = {
[IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw",
[IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY]
= "filter_low_pass_3db_frequency",
+ [IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency",
+ [IIO_CHAN_INFO_FREQUENCY] = "frequency",
+ [IIO_CHAN_INFO_PHASE] = "phase",
+ [IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain",
};
const struct iio_chan_spec
@@ -151,14 +153,6 @@ static void __exit iio_exit(void)
}
#if defined(CONFIG_DEBUG_FS)
-static int iio_debugfs_open(struct inode *inode, struct file *file)
-{
- if (inode->i_private)
- file->private_data = inode->i_private;
-
- return 0;
-}
-
static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
@@ -217,7 +211,7 @@ static ssize_t iio_debugfs_write_reg(struct file *file,
}
static const struct file_operations iio_debugfs_reg_fops = {
- .open = iio_debugfs_open,
+ .open = simple_open,
.read = iio_debugfs_read_reg,
.write = iio_debugfs_write_reg,
};
@@ -234,15 +228,12 @@ static int iio_device_register_debugfs(struct iio_dev *indio_dev)
if (indio_dev->info->debugfs_reg_access == NULL)
return 0;
- if (IS_ERR(iio_debugfs_dentry))
+ if (!iio_debugfs_dentry)
return 0;
indio_dev->debugfs_dentry =
debugfs_create_dir(dev_name(&indio_dev->dev),
iio_debugfs_dentry);
- if (IS_ERR(indio_dev->debugfs_dentry))
- return PTR_ERR(indio_dev->debugfs_dentry);
-
if (indio_dev->debugfs_dentry == NULL) {
dev_warn(indio_dev->dev.parent,
"Failed to create debugfs directory\n");
@@ -274,13 +265,13 @@ static ssize_t iio_read_channel_ext_info(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
const struct iio_chan_spec_ext_info *ext_info;
ext_info = &this_attr->c->ext_info[this_attr->address];
- return ext_info->read(indio_dev, this_attr->c, buf);
+ return ext_info->read(indio_dev, ext_info->private, this_attr->c, buf);
}
static ssize_t iio_write_channel_ext_info(struct device *dev,
@@ -288,42 +279,50 @@ static ssize_t iio_write_channel_ext_info(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
const struct iio_chan_spec_ext_info *ext_info;
ext_info = &this_attr->c->ext_info[this_attr->address];
- return ext_info->write(indio_dev, this_attr->c, buf, len);
+ return ext_info->write(indio_dev, ext_info->private,
+ this_attr->c, buf, len);
}
static ssize_t iio_read_channel_info(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int val, val2;
+ bool scale_db = false;
int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
&val, &val2, this_attr->address);
if (ret < 0)
return ret;
- if (ret == IIO_VAL_INT)
+ switch (ret) {
+ case IIO_VAL_INT:
return sprintf(buf, "%d\n", val);
- else if (ret == IIO_VAL_INT_PLUS_MICRO) {
+ case IIO_VAL_INT_PLUS_MICRO_DB:
+ scale_db = true;
+ case IIO_VAL_INT_PLUS_MICRO:
if (val2 < 0)
- return sprintf(buf, "-%d.%06u\n", val, -val2);
+ return sprintf(buf, "-%d.%06u%s\n", val, -val2,
+ scale_db ? " dB" : "");
else
- return sprintf(buf, "%d.%06u\n", val, val2);
- } else if (ret == IIO_VAL_INT_PLUS_NANO) {
+ return sprintf(buf, "%d.%06u%s\n", val, val2,
+ scale_db ? " dB" : "");
+ case IIO_VAL_INT_PLUS_NANO:
if (val2 < 0)
return sprintf(buf, "-%d.%09u\n", val, -val2);
else
return sprintf(buf, "%d.%09u\n", val, val2);
- } else
+ default:
return 0;
+ }
}
static ssize_t iio_write_channel_info(struct device *dev,
@@ -331,7 +330,7 @@ static ssize_t iio_write_channel_info(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret, integer = 0, fract = 0, fract_mult = 100000;
bool integer_part = true, negative = false;
@@ -575,25 +574,12 @@ error_ret:
static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan)
{
- int ret, i, attrcount = 0;
+ int ret, attrcount = 0;
+ int i;
const struct iio_chan_spec_ext_info *ext_info;
if (chan->channel < 0)
return 0;
-
- ret = __iio_add_chan_devattr(iio_data_type_name[chan->processed_val],
- chan,
- &iio_read_channel_info,
- (chan->output ?
- &iio_write_channel_info : NULL),
- 0,
- 0,
- &indio_dev->dev,
- &indio_dev->channel_attr_list);
- if (ret)
- goto error_ret;
- attrcount++;
-
for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) {
ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2],
chan,
@@ -652,7 +638,7 @@ static ssize_t iio_show_dev_name(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
return sprintf(buf, "%s\n", indio_dev->name);
}
@@ -738,7 +724,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
static void iio_dev_release(struct device *device)
{
- struct iio_dev *indio_dev = container_of(device, struct iio_dev, dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(device);
cdev_del(&indio_dev->chrdev);
if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
iio_device_unregister_trigger_consumer(indio_dev);
@@ -752,7 +738,7 @@ static struct device_type iio_dev_type = {
.release = iio_dev_release,
};
-struct iio_dev *iio_allocate_device(int sizeof_priv)
+struct iio_dev *iio_device_alloc(int sizeof_priv)
{
struct iio_dev *dev;
size_t alloc_size;
@@ -788,16 +774,16 @@ struct iio_dev *iio_allocate_device(int sizeof_priv)
return dev;
}
-EXPORT_SYMBOL(iio_allocate_device);
+EXPORT_SYMBOL(iio_device_alloc);
-void iio_free_device(struct iio_dev *dev)
+void iio_device_free(struct iio_dev *dev)
{
if (dev) {
ida_simple_remove(&iio_ida, dev->id);
kfree(dev);
}
}
-EXPORT_SYMBOL(iio_free_device);
+EXPORT_SYMBOL(iio_device_free);
/**
* iio_chrdev_open() - chrdev file open for buffer access and ioctls
diff --git a/drivers/staging/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index 5fdf739e38f9..b49059de5d02 100644
--- a/drivers/staging/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -20,10 +20,10 @@
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
-#include "iio.h"
+#include <linux/iio/iio.h>
#include "iio_core.h"
-#include "sysfs.h"
-#include "events.h"
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
/**
* struct iio_event_interface - chrdev interface for an event line
@@ -186,7 +186,7 @@ static ssize_t iio_ev_state_store(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
bool val;
@@ -205,7 +205,7 @@ static ssize_t iio_ev_state_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int val = indio_dev->info->read_event_config(indio_dev,
this_attr->address);
@@ -220,7 +220,7 @@ static ssize_t iio_ev_value_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int val, ret;
@@ -237,7 +237,7 @@ static ssize_t iio_ev_value_store(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
unsigned long val;
int ret;
diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index 47ecadd4818d..0f582df75a19 100644
--- a/drivers/staging/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -15,11 +15,11 @@
#include <linux/list.h>
#include <linux/slab.h>
-#include "iio.h"
-#include "trigger.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
#include "iio_core.h"
#include "iio_core_trigger.h"
-#include "trigger_consumer.h"
+#include <linux/iio/trigger_consumer.h>
/* RFC - Question of approach
* Make the common case (single sensor single trigger)
@@ -310,7 +310,7 @@ static ssize_t iio_trigger_read_current(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
if (indio_dev->trig)
return sprintf(buf, "%s\n", indio_dev->trig->name);
@@ -329,7 +329,7 @@ static ssize_t iio_trigger_write_current(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_trigger *oldtrig = indio_dev->trig;
struct iio_trigger *trig;
int ret;
@@ -360,9 +360,9 @@ static ssize_t iio_trigger_write_current(struct device *dev,
indio_dev->trig = trig;
if (oldtrig && indio_dev->trig != oldtrig)
- iio_put_trigger(oldtrig);
+ iio_trigger_put(oldtrig);
if (indio_dev->trig)
- iio_get_trigger(indio_dev->trig);
+ iio_trigger_get(indio_dev->trig);
return len;
}
@@ -426,7 +426,7 @@ static void iio_trig_subirqunmask(struct irq_data *d)
trig->subirqs[d->irq - trig->subirq_base].enabled = true;
}
-struct iio_trigger *iio_allocate_trigger(const char *fmt, ...)
+struct iio_trigger *iio_trigger_alloc(const char *fmt, ...)
{
va_list vargs;
struct iio_trigger *trig;
@@ -472,14 +472,14 @@ struct iio_trigger *iio_allocate_trigger(const char *fmt, ...)
}
return trig;
}
-EXPORT_SYMBOL(iio_allocate_trigger);
+EXPORT_SYMBOL(iio_trigger_alloc);
-void iio_free_trigger(struct iio_trigger *trig)
+void iio_trigger_free(struct iio_trigger *trig)
{
if (trig)
put_device(&trig->dev);
}
-EXPORT_SYMBOL(iio_free_trigger);
+EXPORT_SYMBOL(iio_trigger_free);
void iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
{
@@ -491,7 +491,7 @@ void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev)
{
/* Clean up and associated but not attached triggers references */
if (indio_dev->trig)
- iio_put_trigger(indio_dev->trig);
+ iio_trigger_put(indio_dev->trig);
}
int iio_triggered_buffer_postenable(struct iio_dev *indio_dev)
diff --git a/drivers/staging/iio/inkern.c b/drivers/iio/inkern.c
index ef07a02bf542..922645893dc8 100644
--- a/drivers/staging/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -11,11 +11,11 @@
#include <linux/slab.h>
#include <linux/mutex.h>
-#include "iio.h"
+#include <linux/iio/iio.h>
#include "iio_core.h"
-#include "machine.h"
-#include "driver.h"
-#include "consumer.h"
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+#include <linux/iio/consumer.h>
struct iio_map_internal {
struct iio_dev *indio_dev;
diff --git a/drivers/staging/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c
index 9f3bd59c0e72..6bf9d05f4841 100644
--- a/drivers/staging/iio/kfifo_buf.c
+++ b/drivers/iio/kfifo_buf.c
@@ -5,8 +5,7 @@
#include <linux/workqueue.h>
#include <linux/kfifo.h>
#include <linux/mutex.h>
-
-#include "kfifo_buf.h"
+#include <linux/iio/kfifo_buf.h>
struct iio_kfifo {
struct iio_buffer buffer;
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index eb0add311dc8..a0f29c1d03bc 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -51,6 +51,7 @@ source "drivers/infiniband/hw/cxgb3/Kconfig"
source "drivers/infiniband/hw/cxgb4/Kconfig"
source "drivers/infiniband/hw/mlx4/Kconfig"
source "drivers/infiniband/hw/nes/Kconfig"
+source "drivers/infiniband/hw/ocrdma/Kconfig"
source "drivers/infiniband/ulp/ipoib/Kconfig"
diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile
index a3b2d8eac86e..bf846a14b9d3 100644
--- a/drivers/infiniband/Makefile
+++ b/drivers/infiniband/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_INFINIBAND_CXGB3) += hw/cxgb3/
obj-$(CONFIG_INFINIBAND_CXGB4) += hw/cxgb4/
obj-$(CONFIG_MLX4_INFINIBAND) += hw/mlx4/
obj-$(CONFIG_INFINIBAND_NES) += hw/nes/
+obj-$(CONFIG_INFINIBAND_OCRDMA) += hw/ocrdma/
obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/
obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/
obj-$(CONFIG_INFINIBAND_SRPT) += ulp/srpt/
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 59fbd704a1ec..55d5642eb10a 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -1219,13 +1219,13 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
}
if (!conn_id) {
ret = -ENOMEM;
- goto out;
+ goto err1;
}
mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING);
ret = cma_acquire_dev(conn_id);
if (ret)
- goto release_conn_id;
+ goto err2;
conn_id->cm_id.ib = cm_id;
cm_id->context = conn_id;
@@ -1237,31 +1237,33 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
*/
atomic_inc(&conn_id->refcount);
ret = conn_id->id.event_handler(&conn_id->id, &event);
- if (!ret) {
- /*
- * Acquire mutex to prevent user executing rdma_destroy_id()
- * while we're accessing the cm_id.
- */
- mutex_lock(&lock);
- if (cma_comp(conn_id, RDMA_CM_CONNECT) && (conn_id->id.qp_type != IB_QPT_UD))
- ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
- mutex_unlock(&lock);
- mutex_unlock(&conn_id->handler_mutex);
- cma_deref_id(conn_id);
- goto out;
- }
+ if (ret)
+ goto err3;
+
+ /*
+ * Acquire mutex to prevent user executing rdma_destroy_id()
+ * while we're accessing the cm_id.
+ */
+ mutex_lock(&lock);
+ if (cma_comp(conn_id, RDMA_CM_CONNECT) && (conn_id->id.qp_type != IB_QPT_UD))
+ ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
+ mutex_unlock(&lock);
+ mutex_unlock(&conn_id->handler_mutex);
+ mutex_unlock(&listen_id->handler_mutex);
cma_deref_id(conn_id);
+ return 0;
+err3:
+ cma_deref_id(conn_id);
/* Destroy the CM ID by returning a non-zero value. */
conn_id->cm_id.ib = NULL;
-
-release_conn_id:
+err2:
cma_exch(conn_id, RDMA_CM_DESTROYING);
mutex_unlock(&conn_id->handler_mutex);
- rdma_destroy_id(&conn_id->id);
-
-out:
+err1:
mutex_unlock(&listen_id->handler_mutex);
+ if (conn_id)
+ rdma_destroy_id(&conn_id->id);
return ret;
}
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 71f0c0f7df94..a84112322071 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -269,7 +269,7 @@ void ib_umem_release(struct ib_umem *umem)
} else
down_write(&mm->mmap_sem);
- current->mm->locked_vm -= diff;
+ current->mm->pinned_vm -= diff;
up_write(&mm->mmap_sem);
mmput(mm);
kfree(umem);
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 4d27e4c3fe34..f9d0d7c413a2 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -41,13 +41,18 @@
#include "uverbs.h"
-static struct lock_class_key pd_lock_key;
-static struct lock_class_key mr_lock_key;
-static struct lock_class_key cq_lock_key;
-static struct lock_class_key qp_lock_key;
-static struct lock_class_key ah_lock_key;
-static struct lock_class_key srq_lock_key;
-static struct lock_class_key xrcd_lock_key;
+struct uverbs_lock_class {
+ struct lock_class_key key;
+ char name[16];
+};
+
+static struct uverbs_lock_class pd_lock_class = { .name = "PD-uobj" };
+static struct uverbs_lock_class mr_lock_class = { .name = "MR-uobj" };
+static struct uverbs_lock_class cq_lock_class = { .name = "CQ-uobj" };
+static struct uverbs_lock_class qp_lock_class = { .name = "QP-uobj" };
+static struct uverbs_lock_class ah_lock_class = { .name = "AH-uobj" };
+static struct uverbs_lock_class srq_lock_class = { .name = "SRQ-uobj" };
+static struct uverbs_lock_class xrcd_lock_class = { .name = "XRCD-uobj" };
#define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \
do { \
@@ -83,13 +88,13 @@ static struct lock_class_key xrcd_lock_key;
*/
static void init_uobj(struct ib_uobject *uobj, u64 user_handle,
- struct ib_ucontext *context, struct lock_class_key *key)
+ struct ib_ucontext *context, struct uverbs_lock_class *c)
{
uobj->user_handle = user_handle;
uobj->context = context;
kref_init(&uobj->ref);
init_rwsem(&uobj->mutex);
- lockdep_set_class(&uobj->mutex, key);
+ lockdep_set_class_and_name(&uobj->mutex, &c->key, c->name);
uobj->live = 0;
}
@@ -522,7 +527,7 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
if (!uobj)
return -ENOMEM;
- init_uobj(uobj, 0, file->ucontext, &pd_lock_key);
+ init_uobj(uobj, 0, file->ucontext, &pd_lock_class);
down_write(&uobj->mutex);
pd = file->device->ib_dev->alloc_pd(file->device->ib_dev,
@@ -750,7 +755,7 @@ ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
goto err_tree_mutex_unlock;
}
- init_uobj(&obj->uobject, 0, file->ucontext, &xrcd_lock_key);
+ init_uobj(&obj->uobject, 0, file->ucontext, &xrcd_lock_class);
down_write(&obj->uobject.mutex);
@@ -947,7 +952,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
if (!uobj)
return -ENOMEM;
- init_uobj(uobj, 0, file->ucontext, &mr_lock_key);
+ init_uobj(uobj, 0, file->ucontext, &mr_lock_class);
down_write(&uobj->mutex);
pd = idr_read_pd(cmd.pd_handle, file->ucontext);
@@ -1115,7 +1120,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
if (!obj)
return -ENOMEM;
- init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &cq_lock_key);
+ init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &cq_lock_class);
down_write(&obj->uobject.mutex);
if (cmd.comp_channel >= 0) {
@@ -1399,6 +1404,9 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
+ if (cmd.qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW))
+ return -EPERM;
+
INIT_UDATA(&udata, buf + sizeof cmd,
(unsigned long) cmd.response + sizeof resp,
in_len - sizeof cmd, out_len - sizeof resp);
@@ -1407,7 +1415,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
if (!obj)
return -ENOMEM;
- init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
+ init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_class);
down_write(&obj->uevent.uobject.mutex);
if (cmd.qp_type == IB_QPT_XRC_TGT) {
@@ -1418,13 +1426,6 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
}
device = xrcd->device;
} else {
- pd = idr_read_pd(cmd.pd_handle, file->ucontext);
- scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
- if (!pd || !scq) {
- ret = -EINVAL;
- goto err_put;
- }
-
if (cmd.qp_type == IB_QPT_XRC_INI) {
cmd.max_recv_wr = cmd.max_recv_sge = 0;
} else {
@@ -1435,13 +1436,24 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
goto err_put;
}
}
- rcq = (cmd.recv_cq_handle == cmd.send_cq_handle) ?
- scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
- if (!rcq) {
- ret = -EINVAL;
- goto err_put;
+
+ if (cmd.recv_cq_handle != cmd.send_cq_handle) {
+ rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext, 0);
+ if (!rcq) {
+ ret = -EINVAL;
+ goto err_put;
+ }
}
}
+
+ scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, !!rcq);
+ rcq = rcq ?: scq;
+ pd = idr_read_pd(cmd.pd_handle, file->ucontext);
+ if (!pd || !scq) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+
device = pd->device;
}
@@ -1585,7 +1597,7 @@ ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
if (!obj)
return -ENOMEM;
- init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
+ init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_class);
down_write(&obj->uevent.uobject.mutex);
xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
@@ -2272,7 +2284,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
if (!uobj)
return -ENOMEM;
- init_uobj(uobj, cmd.user_handle, file->ucontext, &ah_lock_key);
+ init_uobj(uobj, cmd.user_handle, file->ucontext, &ah_lock_class);
down_write(&uobj->mutex);
pd = idr_read_pd(cmd.pd_handle, file->ucontext);
@@ -2476,30 +2488,30 @@ static int __uverbs_create_xsrq(struct ib_uverbs_file *file,
if (!obj)
return -ENOMEM;
- init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, &srq_lock_key);
+ init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, &srq_lock_class);
down_write(&obj->uevent.uobject.mutex);
- pd = idr_read_pd(cmd->pd_handle, file->ucontext);
- if (!pd) {
- ret = -EINVAL;
- goto err;
- }
-
if (cmd->srq_type == IB_SRQT_XRC) {
- attr.ext.xrc.cq = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
- if (!attr.ext.xrc.cq) {
- ret = -EINVAL;
- goto err_put_pd;
- }
-
attr.ext.xrc.xrcd = idr_read_xrcd(cmd->xrcd_handle, file->ucontext, &xrcd_uobj);
if (!attr.ext.xrc.xrcd) {
ret = -EINVAL;
- goto err_put_cq;
+ goto err;
}
obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
atomic_inc(&obj->uxrcd->refcnt);
+
+ attr.ext.xrc.cq = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
+ if (!attr.ext.xrc.cq) {
+ ret = -EINVAL;
+ goto err_put_xrcd;
+ }
+ }
+
+ pd = idr_read_pd(cmd->pd_handle, file->ucontext);
+ if (!pd) {
+ ret = -EINVAL;
+ goto err_put_cq;
}
attr.event_handler = ib_uverbs_srq_event_handler;
@@ -2576,17 +2588,17 @@ err_destroy:
ib_destroy_srq(srq);
err_put:
- if (cmd->srq_type == IB_SRQT_XRC) {
- atomic_dec(&obj->uxrcd->refcnt);
- put_uobj_read(xrcd_uobj);
- }
+ put_pd_read(pd);
err_put_cq:
if (cmd->srq_type == IB_SRQT_XRC)
put_cq_read(attr.ext.xrc.cq);
-err_put_pd:
- put_pd_read(pd);
+err_put_xrcd:
+ if (cmd->srq_type == IB_SRQT_XRC) {
+ atomic_dec(&obj->uxrcd->refcnt);
+ put_uobj_read(xrcd_uobj);
+ }
err:
put_uobj_write(&obj->uevent.uobject);
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 575b78045aaf..30f199e8579f 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -479,6 +479,7 @@ static const struct {
[IB_QPT_UD] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_QKEY),
+ [IB_QPT_RAW_PACKET] = IB_QP_PORT,
[IB_QPT_UC] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
@@ -1183,23 +1184,33 @@ EXPORT_SYMBOL(ib_dealloc_fmr);
int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
{
+ int ret;
+
if (!qp->device->attach_mcast)
return -ENOSYS;
if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD)
return -EINVAL;
- return qp->device->attach_mcast(qp, gid, lid);
+ ret = qp->device->attach_mcast(qp, gid, lid);
+ if (!ret)
+ atomic_inc(&qp->usecnt);
+ return ret;
}
EXPORT_SYMBOL(ib_attach_mcast);
int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
{
+ int ret;
+
if (!qp->device->detach_mcast)
return -ENOSYS;
if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD)
return -EINVAL;
- return qp->device->detach_mcast(qp, gid, lid);
+ ret = qp->device->detach_mcast(qp, gid, lid);
+ if (!ret)
+ atomic_dec(&qp->usecnt);
+ return ret;
}
EXPORT_SYMBOL(ib_detach_mcast);
diff --git a/drivers/infiniband/hw/cxgb4/Makefile b/drivers/infiniband/hw/cxgb4/Makefile
index 46b878ca2c3b..e11cf7299945 100644
--- a/drivers/infiniband/hw/cxgb4/Makefile
+++ b/drivers/infiniband/hw/cxgb4/Makefile
@@ -2,4 +2,4 @@ ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o
-iw_cxgb4-y := device.o cm.o provider.o mem.o cq.o qp.o resource.o ev.o
+iw_cxgb4-y := device.o cm.o provider.o mem.o cq.o qp.o resource.o ev.o id_table.o
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 92b4c2b0308b..55ab284e22f2 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -1362,7 +1362,10 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
ep = lookup_tid(t, tid);
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
- BUG_ON(!ep);
+ if (!ep) {
+ printk(KERN_WARNING MOD "Abort rpl to freed endpoint\n");
+ return 0;
+ }
mutex_lock(&ep->com.mutex);
switch (ep->com.state) {
case ABORTING:
@@ -1410,6 +1413,24 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
return 0;
}
+ /*
+ * Log interesting failures.
+ */
+ switch (status) {
+ case CPL_ERR_CONN_RESET:
+ case CPL_ERR_CONN_TIMEDOUT:
+ break;
+ default:
+ printk(KERN_INFO MOD "Active open failure - "
+ "atid %u status %u errno %d %pI4:%u->%pI4:%u\n",
+ atid, status, status2errno(status),
+ &ep->com.local_addr.sin_addr.s_addr,
+ ntohs(ep->com.local_addr.sin_port),
+ &ep->com.remote_addr.sin_addr.s_addr,
+ ntohs(ep->com.remote_addr.sin_port));
+ break;
+ }
+
connect_reply_upcall(ep, status2errno(status));
state_set(&ep->com, DEAD);
@@ -1593,7 +1614,7 @@ static int import_ep(struct c4iw_ep *ep, __be32 peer_ip, struct dst_entry *dst,
n, n->dev, 0);
if (!ep->l2t)
goto out;
- ep->mtu = dst_mtu(ep->dst);
+ ep->mtu = dst_mtu(dst);
ep->tx_chan = cxgb4_port_chan(n->dev);
ep->smac_idx = (cxgb4_port_viid(n->dev) & 0x7F) << 1;
step = cdev->rdev.lldi.ntxq /
@@ -2656,6 +2677,12 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
unsigned int tid = GET_TID(req);
ep = lookup_tid(t, tid);
+ if (!ep) {
+ printk(KERN_WARNING MOD
+ "Abort on non-existent endpoint, tid %d\n", tid);
+ kfree_skb(skb);
+ return 0;
+ }
if (is_neg_adv_abort(req->status)) {
PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
ep->hwtid);
@@ -2667,11 +2694,8 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
/*
* Wake up any threads in rdma_init() or rdma_fini().
- * However, this is not needed if com state is just
- * MPA_REQ_SENT
*/
- if (ep->com.state != MPA_REQ_SENT)
- c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
+ c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
sched(dev, skb);
return 0;
}
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 6d0df6ec161b..cb4ecd783700 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/debugfs.h>
+#include <linux/vmalloc.h>
#include <rdma/ib_verbs.h>
@@ -44,6 +45,12 @@ MODULE_DESCRIPTION("Chelsio T4 RDMA Driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(DRV_VERSION);
+struct uld_ctx {
+ struct list_head entry;
+ struct cxgb4_lld_info lldi;
+ struct c4iw_dev *dev;
+};
+
static LIST_HEAD(uld_ctx_list);
static DEFINE_MUTEX(dev_mutex);
@@ -115,7 +122,7 @@ static int qp_release(struct inode *inode, struct file *file)
printk(KERN_INFO "%s null qpd?\n", __func__);
return 0;
}
- kfree(qpd->buf);
+ vfree(qpd->buf);
kfree(qpd);
return 0;
}
@@ -139,7 +146,7 @@ static int qp_open(struct inode *inode, struct file *file)
spin_unlock_irq(&qpd->devp->lock);
qpd->bufsize = count * 128;
- qpd->buf = kmalloc(qpd->bufsize, GFP_KERNEL);
+ qpd->buf = vmalloc(qpd->bufsize);
if (!qpd->buf) {
ret = -ENOMEM;
goto err1;
@@ -240,6 +247,81 @@ static const struct file_operations stag_debugfs_fops = {
.llseek = default_llseek,
};
+static char *db_state_str[] = {"NORMAL", "FLOW_CONTROL", "RECOVERY"};
+
+static int stats_show(struct seq_file *seq, void *v)
+{
+ struct c4iw_dev *dev = seq->private;
+
+ seq_printf(seq, " Object: %10s %10s %10s %10s\n", "Total", "Current",
+ "Max", "Fail");
+ seq_printf(seq, " PDID: %10llu %10llu %10llu %10llu\n",
+ dev->rdev.stats.pd.total, dev->rdev.stats.pd.cur,
+ dev->rdev.stats.pd.max, dev->rdev.stats.pd.fail);
+ seq_printf(seq, " QID: %10llu %10llu %10llu %10llu\n",
+ dev->rdev.stats.qid.total, dev->rdev.stats.qid.cur,
+ dev->rdev.stats.qid.max, dev->rdev.stats.qid.fail);
+ seq_printf(seq, " TPTMEM: %10llu %10llu %10llu %10llu\n",
+ dev->rdev.stats.stag.total, dev->rdev.stats.stag.cur,
+ dev->rdev.stats.stag.max, dev->rdev.stats.stag.fail);
+ seq_printf(seq, " PBLMEM: %10llu %10llu %10llu %10llu\n",
+ dev->rdev.stats.pbl.total, dev->rdev.stats.pbl.cur,
+ dev->rdev.stats.pbl.max, dev->rdev.stats.pbl.fail);
+ seq_printf(seq, " RQTMEM: %10llu %10llu %10llu %10llu\n",
+ dev->rdev.stats.rqt.total, dev->rdev.stats.rqt.cur,
+ dev->rdev.stats.rqt.max, dev->rdev.stats.rqt.fail);
+ seq_printf(seq, " OCQPMEM: %10llu %10llu %10llu %10llu\n",
+ dev->rdev.stats.ocqp.total, dev->rdev.stats.ocqp.cur,
+ dev->rdev.stats.ocqp.max, dev->rdev.stats.ocqp.fail);
+ seq_printf(seq, " DB FULL: %10llu\n", dev->rdev.stats.db_full);
+ seq_printf(seq, " DB EMPTY: %10llu\n", dev->rdev.stats.db_empty);
+ seq_printf(seq, " DB DROP: %10llu\n", dev->rdev.stats.db_drop);
+ seq_printf(seq, " DB State: %s Transitions %llu\n",
+ db_state_str[dev->db_state],
+ dev->rdev.stats.db_state_transitions);
+ return 0;
+}
+
+static int stats_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, stats_show, inode->i_private);
+}
+
+static ssize_t stats_clear(struct file *file, const char __user *buf,
+ size_t count, loff_t *pos)
+{
+ struct c4iw_dev *dev = ((struct seq_file *)file->private_data)->private;
+
+ mutex_lock(&dev->rdev.stats.lock);
+ dev->rdev.stats.pd.max = 0;
+ dev->rdev.stats.pd.fail = 0;
+ dev->rdev.stats.qid.max = 0;
+ dev->rdev.stats.qid.fail = 0;
+ dev->rdev.stats.stag.max = 0;
+ dev->rdev.stats.stag.fail = 0;
+ dev->rdev.stats.pbl.max = 0;
+ dev->rdev.stats.pbl.fail = 0;
+ dev->rdev.stats.rqt.max = 0;
+ dev->rdev.stats.rqt.fail = 0;
+ dev->rdev.stats.ocqp.max = 0;
+ dev->rdev.stats.ocqp.fail = 0;
+ dev->rdev.stats.db_full = 0;
+ dev->rdev.stats.db_empty = 0;
+ dev->rdev.stats.db_drop = 0;
+ dev->rdev.stats.db_state_transitions = 0;
+ mutex_unlock(&dev->rdev.stats.lock);
+ return count;
+}
+
+static const struct file_operations stats_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .open = stats_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .write = stats_clear,
+};
+
static int setup_debugfs(struct c4iw_dev *devp)
{
struct dentry *de;
@@ -256,6 +338,12 @@ static int setup_debugfs(struct c4iw_dev *devp)
(void *)devp, &stag_debugfs_fops);
if (de && de->d_inode)
de->d_inode->i_size = 4096;
+
+ de = debugfs_create_file("stats", S_IWUSR, devp->debugfs_root,
+ (void *)devp, &stats_debugfs_fops);
+ if (de && de->d_inode)
+ de->d_inode->i_size = 4096;
+
return 0;
}
@@ -269,9 +357,13 @@ void c4iw_release_dev_ucontext(struct c4iw_rdev *rdev,
list_for_each_safe(pos, nxt, &uctx->qpids) {
entry = list_entry(pos, struct c4iw_qid_list, entry);
list_del_init(&entry->entry);
- if (!(entry->qid & rdev->qpmask))
- c4iw_put_resource(&rdev->resource.qid_fifo, entry->qid,
- &rdev->resource.qid_fifo_lock);
+ if (!(entry->qid & rdev->qpmask)) {
+ c4iw_put_resource(&rdev->resource.qid_table,
+ entry->qid);
+ mutex_lock(&rdev->stats.lock);
+ rdev->stats.qid.cur -= rdev->qpmask + 1;
+ mutex_unlock(&rdev->stats.lock);
+ }
kfree(entry);
}
@@ -332,6 +424,13 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
goto err1;
}
+ rdev->stats.pd.total = T4_MAX_NUM_PD;
+ rdev->stats.stag.total = rdev->lldi.vr->stag.size;
+ rdev->stats.pbl.total = rdev->lldi.vr->pbl.size;
+ rdev->stats.rqt.total = rdev->lldi.vr->rq.size;
+ rdev->stats.ocqp.total = rdev->lldi.vr->ocq.size;
+ rdev->stats.qid.total = rdev->lldi.vr->qp.size;
+
err = c4iw_init_resource(rdev, c4iw_num_stags(rdev), T4_MAX_NUM_PD);
if (err) {
printk(KERN_ERR MOD "error %d initializing resources\n", err);
@@ -370,12 +469,6 @@ static void c4iw_rdev_close(struct c4iw_rdev *rdev)
c4iw_destroy_resource(&rdev->resource);
}
-struct uld_ctx {
- struct list_head entry;
- struct cxgb4_lld_info lldi;
- struct c4iw_dev *dev;
-};
-
static void c4iw_dealloc(struct uld_ctx *ctx)
{
c4iw_rdev_close(&ctx->dev->rdev);
@@ -440,6 +533,8 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
idr_init(&devp->qpidr);
idr_init(&devp->mmidr);
spin_lock_init(&devp->lock);
+ mutex_init(&devp->rdev.stats.lock);
+ mutex_init(&devp->db_mutex);
if (c4iw_debugfs_root) {
devp->debugfs_root = debugfs_create_dir(
@@ -585,11 +680,234 @@ static int c4iw_uld_state_change(void *handle, enum cxgb4_state new_state)
return 0;
}
+static int disable_qp_db(int id, void *p, void *data)
+{
+ struct c4iw_qp *qp = p;
+
+ t4_disable_wq_db(&qp->wq);
+ return 0;
+}
+
+static void stop_queues(struct uld_ctx *ctx)
+{
+ spin_lock_irq(&ctx->dev->lock);
+ if (ctx->dev->db_state == NORMAL) {
+ ctx->dev->rdev.stats.db_state_transitions++;
+ ctx->dev->db_state = FLOW_CONTROL;
+ idr_for_each(&ctx->dev->qpidr, disable_qp_db, NULL);
+ }
+ spin_unlock_irq(&ctx->dev->lock);
+}
+
+static int enable_qp_db(int id, void *p, void *data)
+{
+ struct c4iw_qp *qp = p;
+
+ t4_enable_wq_db(&qp->wq);
+ return 0;
+}
+
+static void resume_queues(struct uld_ctx *ctx)
+{
+ spin_lock_irq(&ctx->dev->lock);
+ if (ctx->dev->qpcnt <= db_fc_threshold &&
+ ctx->dev->db_state == FLOW_CONTROL) {
+ ctx->dev->db_state = NORMAL;
+ ctx->dev->rdev.stats.db_state_transitions++;
+ idr_for_each(&ctx->dev->qpidr, enable_qp_db, NULL);
+ }
+ spin_unlock_irq(&ctx->dev->lock);
+}
+
+struct qp_list {
+ unsigned idx;
+ struct c4iw_qp **qps;
+};
+
+static int add_and_ref_qp(int id, void *p, void *data)
+{
+ struct qp_list *qp_listp = data;
+ struct c4iw_qp *qp = p;
+
+ c4iw_qp_add_ref(&qp->ibqp);
+ qp_listp->qps[qp_listp->idx++] = qp;
+ return 0;
+}
+
+static int count_qps(int id, void *p, void *data)
+{
+ unsigned *countp = data;
+ (*countp)++;
+ return 0;
+}
+
+static void deref_qps(struct qp_list qp_list)
+{
+ int idx;
+
+ for (idx = 0; idx < qp_list.idx; idx++)
+ c4iw_qp_rem_ref(&qp_list.qps[idx]->ibqp);
+}
+
+static void recover_lost_dbs(struct uld_ctx *ctx, struct qp_list *qp_list)
+{
+ int idx;
+ int ret;
+
+ for (idx = 0; idx < qp_list->idx; idx++) {
+ struct c4iw_qp *qp = qp_list->qps[idx];
+
+ ret = cxgb4_sync_txq_pidx(qp->rhp->rdev.lldi.ports[0],
+ qp->wq.sq.qid,
+ t4_sq_host_wq_pidx(&qp->wq),
+ t4_sq_wq_size(&qp->wq));
+ if (ret) {
+ printk(KERN_ERR MOD "%s: Fatal error - "
+ "DB overflow recovery failed - "
+ "error syncing SQ qid %u\n",
+ pci_name(ctx->lldi.pdev), qp->wq.sq.qid);
+ return;
+ }
+
+ ret = cxgb4_sync_txq_pidx(qp->rhp->rdev.lldi.ports[0],
+ qp->wq.rq.qid,
+ t4_rq_host_wq_pidx(&qp->wq),
+ t4_rq_wq_size(&qp->wq));
+
+ if (ret) {
+ printk(KERN_ERR MOD "%s: Fatal error - "
+ "DB overflow recovery failed - "
+ "error syncing RQ qid %u\n",
+ pci_name(ctx->lldi.pdev), qp->wq.rq.qid);
+ return;
+ }
+
+ /* Wait for the dbfifo to drain */
+ while (cxgb4_dbfifo_count(qp->rhp->rdev.lldi.ports[0], 1) > 0) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(usecs_to_jiffies(10));
+ }
+ }
+}
+
+static void recover_queues(struct uld_ctx *ctx)
+{
+ int count = 0;
+ struct qp_list qp_list;
+ int ret;
+
+ /* lock out kernel db ringers */
+ mutex_lock(&ctx->dev->db_mutex);
+
+ /* put all queues in to recovery mode */
+ spin_lock_irq(&ctx->dev->lock);
+ ctx->dev->db_state = RECOVERY;
+ ctx->dev->rdev.stats.db_state_transitions++;
+ idr_for_each(&ctx->dev->qpidr, disable_qp_db, NULL);
+ spin_unlock_irq(&ctx->dev->lock);
+
+ /* slow everybody down */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(usecs_to_jiffies(1000));
+
+ /* Wait for the dbfifo to completely drain. */
+ while (cxgb4_dbfifo_count(ctx->dev->rdev.lldi.ports[0], 1) > 0) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(usecs_to_jiffies(10));
+ }
+
+ /* flush the SGE contexts */
+ ret = cxgb4_flush_eq_cache(ctx->dev->rdev.lldi.ports[0]);
+ if (ret) {
+ printk(KERN_ERR MOD "%s: Fatal error - DB overflow recovery failed\n",
+ pci_name(ctx->lldi.pdev));
+ goto out;
+ }
+
+ /* Count active queues so we can build a list of queues to recover */
+ spin_lock_irq(&ctx->dev->lock);
+ idr_for_each(&ctx->dev->qpidr, count_qps, &count);
+
+ qp_list.qps = kzalloc(count * sizeof *qp_list.qps, GFP_ATOMIC);
+ if (!qp_list.qps) {
+ printk(KERN_ERR MOD "%s: Fatal error - DB overflow recovery failed\n",
+ pci_name(ctx->lldi.pdev));
+ spin_unlock_irq(&ctx->dev->lock);
+ goto out;
+ }
+ qp_list.idx = 0;
+
+ /* add and ref each qp so it doesn't get freed */
+ idr_for_each(&ctx->dev->qpidr, add_and_ref_qp, &qp_list);
+
+ spin_unlock_irq(&ctx->dev->lock);
+
+ /* now traverse the list in a safe context to recover the db state*/
+ recover_lost_dbs(ctx, &qp_list);
+
+ /* we're almost done! deref the qps and clean up */
+ deref_qps(qp_list);
+ kfree(qp_list.qps);
+
+ /* Wait for the dbfifo to completely drain again */
+ while (cxgb4_dbfifo_count(ctx->dev->rdev.lldi.ports[0], 1) > 0) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(usecs_to_jiffies(10));
+ }
+
+ /* resume the queues */
+ spin_lock_irq(&ctx->dev->lock);
+ if (ctx->dev->qpcnt > db_fc_threshold)
+ ctx->dev->db_state = FLOW_CONTROL;
+ else {
+ ctx->dev->db_state = NORMAL;
+ idr_for_each(&ctx->dev->qpidr, enable_qp_db, NULL);
+ }
+ ctx->dev->rdev.stats.db_state_transitions++;
+ spin_unlock_irq(&ctx->dev->lock);
+
+out:
+ /* start up kernel db ringers again */
+ mutex_unlock(&ctx->dev->db_mutex);
+}
+
+static int c4iw_uld_control(void *handle, enum cxgb4_control control, ...)
+{
+ struct uld_ctx *ctx = handle;
+
+ switch (control) {
+ case CXGB4_CONTROL_DB_FULL:
+ stop_queues(ctx);
+ mutex_lock(&ctx->dev->rdev.stats.lock);
+ ctx->dev->rdev.stats.db_full++;
+ mutex_unlock(&ctx->dev->rdev.stats.lock);
+ break;
+ case CXGB4_CONTROL_DB_EMPTY:
+ resume_queues(ctx);
+ mutex_lock(&ctx->dev->rdev.stats.lock);
+ ctx->dev->rdev.stats.db_empty++;
+ mutex_unlock(&ctx->dev->rdev.stats.lock);
+ break;
+ case CXGB4_CONTROL_DB_DROP:
+ recover_queues(ctx);
+ mutex_lock(&ctx->dev->rdev.stats.lock);
+ ctx->dev->rdev.stats.db_drop++;
+ mutex_unlock(&ctx->dev->rdev.stats.lock);
+ break;
+ default:
+ printk(KERN_WARNING MOD "%s: unknown control cmd %u\n",
+ pci_name(ctx->lldi.pdev), control);
+ break;
+ }
+ return 0;
+}
+
static struct cxgb4_uld_info c4iw_uld_info = {
.name = DRV_NAME,
.add = c4iw_uld_add,
.rx_handler = c4iw_uld_rx_handler,
.state_change = c4iw_uld_state_change,
+ .control = c4iw_uld_control,
};
static int __init c4iw_init_module(void)
diff --git a/drivers/infiniband/hw/cxgb4/ev.c b/drivers/infiniband/hw/cxgb4/ev.c
index 397cb36cf103..cf2f6b47617a 100644
--- a/drivers/infiniband/hw/cxgb4/ev.c
+++ b/drivers/infiniband/hw/cxgb4/ev.c
@@ -84,7 +84,7 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
struct c4iw_qp *qhp;
u32 cqid;
- spin_lock(&dev->lock);
+ spin_lock_irq(&dev->lock);
qhp = get_qhp(dev, CQE_QPID(err_cqe));
if (!qhp) {
printk(KERN_ERR MOD "BAD AE qpid 0x%x opcode %d "
@@ -93,7 +93,7 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
CQE_OPCODE(err_cqe), CQE_STATUS(err_cqe),
CQE_TYPE(err_cqe), CQE_WRID_HI(err_cqe),
CQE_WRID_LOW(err_cqe));
- spin_unlock(&dev->lock);
+ spin_unlock_irq(&dev->lock);
goto out;
}
@@ -109,13 +109,13 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
CQE_OPCODE(err_cqe), CQE_STATUS(err_cqe),
CQE_TYPE(err_cqe), CQE_WRID_HI(err_cqe),
CQE_WRID_LOW(err_cqe));
- spin_unlock(&dev->lock);
+ spin_unlock_irq(&dev->lock);
goto out;
}
c4iw_qp_add_ref(&qhp->ibqp);
atomic_inc(&chp->refcnt);
- spin_unlock(&dev->lock);
+ spin_unlock_irq(&dev->lock);
/* Bad incoming write */
if (RQ_TYPE(err_cqe) &&
diff --git a/drivers/infiniband/hw/cxgb4/id_table.c b/drivers/infiniband/hw/cxgb4/id_table.c
new file mode 100644
index 000000000000..f95e5df30db2
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb4/id_table.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2011 Chelsio Communications. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include <linux/kernel.h>
+#include <linux/random.h>
+#include "iw_cxgb4.h"
+
+#define RANDOM_SKIP 16
+
+/*
+ * Trivial bitmap-based allocator. If the random flag is set, the
+ * allocator is designed to:
+ * - pseudo-randomize the id returned such that it is not trivially predictable.
+ * - avoid reuse of recently used id (at the expense of predictability)
+ */
+u32 c4iw_id_alloc(struct c4iw_id_table *alloc)
+{
+ unsigned long flags;
+ u32 obj;
+
+ spin_lock_irqsave(&alloc->lock, flags);
+
+ obj = find_next_zero_bit(alloc->table, alloc->max, alloc->last);
+ if (obj >= alloc->max)
+ obj = find_first_zero_bit(alloc->table, alloc->max);
+
+ if (obj < alloc->max) {
+ if (alloc->flags & C4IW_ID_TABLE_F_RANDOM)
+ alloc->last += random32() % RANDOM_SKIP;
+ else
+ alloc->last = obj + 1;
+ if (alloc->last >= alloc->max)
+ alloc->last = 0;
+ set_bit(obj, alloc->table);
+ obj += alloc->start;
+ } else
+ obj = -1;
+
+ spin_unlock_irqrestore(&alloc->lock, flags);
+ return obj;
+}
+
+void c4iw_id_free(struct c4iw_id_table *alloc, u32 obj)
+{
+ unsigned long flags;
+
+ obj -= alloc->start;
+ BUG_ON((int)obj < 0);
+
+ spin_lock_irqsave(&alloc->lock, flags);
+ clear_bit(obj, alloc->table);
+ spin_unlock_irqrestore(&alloc->lock, flags);
+}
+
+int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num,
+ u32 reserved, u32 flags)
+{
+ int i;
+
+ alloc->start = start;
+ alloc->flags = flags;
+ if (flags & C4IW_ID_TABLE_F_RANDOM)
+ alloc->last = random32() % RANDOM_SKIP;
+ else
+ alloc->last = 0;
+ alloc->max = num;
+ spin_lock_init(&alloc->lock);
+ alloc->table = kmalloc(BITS_TO_LONGS(num) * sizeof(long),
+ GFP_KERNEL);
+ if (!alloc->table)
+ return -ENOMEM;
+
+ bitmap_zero(alloc->table, num);
+ if (!(alloc->flags & C4IW_ID_TABLE_F_EMPTY))
+ for (i = 0; i < reserved; ++i)
+ set_bit(i, alloc->table);
+
+ return 0;
+}
+
+void c4iw_id_table_free(struct c4iw_id_table *alloc)
+{
+ kfree(alloc->table);
+}
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 1357c5bf209b..9beb3a9f0336 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -45,7 +45,6 @@
#include <linux/kref.h>
#include <linux/timer.h>
#include <linux/io.h>
-#include <linux/kfifo.h>
#include <asm/byteorder.h>
@@ -79,13 +78,22 @@ static inline void *cplhdr(struct sk_buff *skb)
return skb->data;
}
+#define C4IW_ID_TABLE_F_RANDOM 1 /* Pseudo-randomize the id's returned */
+#define C4IW_ID_TABLE_F_EMPTY 2 /* Table is initially empty */
+
+struct c4iw_id_table {
+ u32 flags;
+ u32 start; /* logical minimal id */
+ u32 last; /* hint for find */
+ u32 max;
+ spinlock_t lock;
+ unsigned long *table;
+};
+
struct c4iw_resource {
- struct kfifo tpt_fifo;
- spinlock_t tpt_fifo_lock;
- struct kfifo qid_fifo;
- spinlock_t qid_fifo_lock;
- struct kfifo pdid_fifo;
- spinlock_t pdid_fifo_lock;
+ struct c4iw_id_table tpt_table;
+ struct c4iw_id_table qid_table;
+ struct c4iw_id_table pdid_table;
};
struct c4iw_qid_list {
@@ -103,6 +111,27 @@ enum c4iw_rdev_flags {
T4_FATAL_ERROR = (1<<0),
};
+struct c4iw_stat {
+ u64 total;
+ u64 cur;
+ u64 max;
+ u64 fail;
+};
+
+struct c4iw_stats {
+ struct mutex lock;
+ struct c4iw_stat qid;
+ struct c4iw_stat pd;
+ struct c4iw_stat stag;
+ struct c4iw_stat pbl;
+ struct c4iw_stat rqt;
+ struct c4iw_stat ocqp;
+ u64 db_full;
+ u64 db_empty;
+ u64 db_drop;
+ u64 db_state_transitions;
+};
+
struct c4iw_rdev {
struct c4iw_resource resource;
unsigned long qpshift;
@@ -117,6 +146,7 @@ struct c4iw_rdev {
struct cxgb4_lld_info lldi;
unsigned long oc_mw_pa;
void __iomem *oc_mw_kva;
+ struct c4iw_stats stats;
};
static inline int c4iw_fatal_error(struct c4iw_rdev *rdev)
@@ -175,6 +205,12 @@ static inline int c4iw_wait_for_reply(struct c4iw_rdev *rdev,
return wr_waitp->ret;
}
+enum db_state {
+ NORMAL = 0,
+ FLOW_CONTROL = 1,
+ RECOVERY = 2
+};
+
struct c4iw_dev {
struct ib_device ibdev;
struct c4iw_rdev rdev;
@@ -183,7 +219,10 @@ struct c4iw_dev {
struct idr qpidr;
struct idr mmidr;
spinlock_t lock;
+ struct mutex db_mutex;
struct dentry *debugfs_root;
+ enum db_state db_state;
+ int qpcnt;
};
static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev)
@@ -211,29 +250,57 @@ static inline struct c4iw_mr *get_mhp(struct c4iw_dev *rhp, u32 mmid)
return idr_find(&rhp->mmidr, mmid);
}
-static inline int insert_handle(struct c4iw_dev *rhp, struct idr *idr,
- void *handle, u32 id)
+static inline int _insert_handle(struct c4iw_dev *rhp, struct idr *idr,
+ void *handle, u32 id, int lock)
{
int ret;
int newid;
do {
- if (!idr_pre_get(idr, GFP_KERNEL))
+ if (!idr_pre_get(idr, lock ? GFP_KERNEL : GFP_ATOMIC))
return -ENOMEM;
- spin_lock_irq(&rhp->lock);
+ if (lock)
+ spin_lock_irq(&rhp->lock);
ret = idr_get_new_above(idr, handle, id, &newid);
- BUG_ON(newid != id);
- spin_unlock_irq(&rhp->lock);
+ BUG_ON(!ret && newid != id);
+ if (lock)
+ spin_unlock_irq(&rhp->lock);
} while (ret == -EAGAIN);
return ret;
}
-static inline void remove_handle(struct c4iw_dev *rhp, struct idr *idr, u32 id)
+static inline int insert_handle(struct c4iw_dev *rhp, struct idr *idr,
+ void *handle, u32 id)
+{
+ return _insert_handle(rhp, idr, handle, id, 1);
+}
+
+static inline int insert_handle_nolock(struct c4iw_dev *rhp, struct idr *idr,
+ void *handle, u32 id)
+{
+ return _insert_handle(rhp, idr, handle, id, 0);
+}
+
+static inline void _remove_handle(struct c4iw_dev *rhp, struct idr *idr,
+ u32 id, int lock)
{
- spin_lock_irq(&rhp->lock);
+ if (lock)
+ spin_lock_irq(&rhp->lock);
idr_remove(idr, id);
- spin_unlock_irq(&rhp->lock);
+ if (lock)
+ spin_unlock_irq(&rhp->lock);
+}
+
+static inline void remove_handle(struct c4iw_dev *rhp, struct idr *idr, u32 id)
+{
+ _remove_handle(rhp, idr, id, 1);
+}
+
+static inline void remove_handle_nolock(struct c4iw_dev *rhp,
+ struct idr *idr, u32 id)
+{
+ _remove_handle(rhp, idr, id, 0);
}
struct c4iw_pd {
@@ -353,6 +420,8 @@ struct c4iw_qp_attributes {
struct c4iw_ep *llp_stream_handle;
u8 layer_etype;
u8 ecode;
+ u16 sq_db_inc;
+ u16 rq_db_inc;
};
struct c4iw_qp {
@@ -427,6 +496,8 @@ static inline void insert_mmap(struct c4iw_ucontext *ucontext,
enum c4iw_qp_attr_mask {
C4IW_QP_ATTR_NEXT_STATE = 1 << 0,
+ C4IW_QP_ATTR_SQ_DB = 1<<1,
+ C4IW_QP_ATTR_RQ_DB = 1<<2,
C4IW_QP_ATTR_ENABLE_RDMA_READ = 1 << 7,
C4IW_QP_ATTR_ENABLE_RDMA_WRITE = 1 << 8,
C4IW_QP_ATTR_ENABLE_RDMA_BIND = 1 << 9,
@@ -480,6 +551,23 @@ static inline int c4iw_convert_state(enum ib_qp_state ib_state)
}
}
+static inline int to_ib_qp_state(int c4iw_qp_state)
+{
+ switch (c4iw_qp_state) {
+ case C4IW_QP_STATE_IDLE:
+ return IB_QPS_INIT;
+ case C4IW_QP_STATE_RTS:
+ return IB_QPS_RTS;
+ case C4IW_QP_STATE_CLOSING:
+ return IB_QPS_SQD;
+ case C4IW_QP_STATE_TERMINATE:
+ return IB_QPS_SQE;
+ case C4IW_QP_STATE_ERROR:
+ return IB_QPS_ERR;
+ }
+ return IB_QPS_ERR;
+}
+
static inline u32 c4iw_ib_to_tpt_access(int a)
{
return (a & IB_ACCESS_REMOTE_WRITE ? FW_RI_MEM_ACCESS_REM_WRITE : 0) |
@@ -693,14 +781,20 @@ static inline int compute_wscale(int win)
return wscale;
}
+u32 c4iw_id_alloc(struct c4iw_id_table *alloc);
+void c4iw_id_free(struct c4iw_id_table *alloc, u32 obj);
+int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num,
+ u32 reserved, u32 flags);
+void c4iw_id_table_free(struct c4iw_id_table *alloc);
+
typedef int (*c4iw_handler_func)(struct c4iw_dev *dev, struct sk_buff *skb);
int c4iw_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new,
struct l2t_entry *l2t);
void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qpid,
struct c4iw_dev_ucontext *uctx);
-u32 c4iw_get_resource(struct kfifo *fifo, spinlock_t *lock);
-void c4iw_put_resource(struct kfifo *fifo, u32 entry, spinlock_t *lock);
+u32 c4iw_get_resource(struct c4iw_id_table *id_table);
+void c4iw_put_resource(struct c4iw_id_table *id_table, u32 entry);
int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid);
int c4iw_init_ctrl_qp(struct c4iw_rdev *rdev);
int c4iw_pblpool_create(struct c4iw_rdev *rdev);
@@ -769,6 +863,8 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd,
struct ib_udata *udata);
int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int attr_mask, struct ib_udata *udata);
+int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask, struct ib_qp_init_attr *init_attr);
struct ib_qp *c4iw_get_qp(struct ib_device *dev, int qpn);
u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size);
void c4iw_rqtpool_free(struct c4iw_rdev *rdev, u32 addr, int size);
@@ -797,5 +893,7 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe);
extern struct cxgb4_client t4c_client;
extern c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS];
extern int c4iw_max_read_depth;
+extern int db_fc_threshold;
+
#endif
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index 40c835309e49..57e07c61ace2 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -131,10 +131,14 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
stag_idx = (*stag) >> 8;
if ((!reset_tpt_entry) && (*stag == T4_STAG_UNSET)) {
- stag_idx = c4iw_get_resource(&rdev->resource.tpt_fifo,
- &rdev->resource.tpt_fifo_lock);
+ stag_idx = c4iw_get_resource(&rdev->resource.tpt_table);
if (!stag_idx)
return -ENOMEM;
+ mutex_lock(&rdev->stats.lock);
+ rdev->stats.stag.cur += 32;
+ if (rdev->stats.stag.cur > rdev->stats.stag.max)
+ rdev->stats.stag.max = rdev->stats.stag.cur;
+ mutex_unlock(&rdev->stats.lock);
*stag = (stag_idx << 8) | (atomic_inc_return(&key) & 0xff);
}
PDBG("%s stag_state 0x%0x type 0x%0x pdid 0x%0x, stag_idx 0x%x\n",
@@ -165,9 +169,12 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
(rdev->lldi.vr->stag.start >> 5),
sizeof(tpt), &tpt);
- if (reset_tpt_entry)
- c4iw_put_resource(&rdev->resource.tpt_fifo, stag_idx,
- &rdev->resource.tpt_fifo_lock);
+ if (reset_tpt_entry) {
+ c4iw_put_resource(&rdev->resource.tpt_table, stag_idx);
+ mutex_lock(&rdev->stats.lock);
+ rdev->stats.stag.cur -= 32;
+ mutex_unlock(&rdev->stats.lock);
+ }
return err;
}
@@ -686,8 +693,8 @@ int c4iw_dealloc_mw(struct ib_mw *mw)
mhp = to_c4iw_mw(mw);
rhp = mhp->rhp;
mmid = (mw->rkey) >> 8;
- deallocate_window(&rhp->rdev, mhp->attr.stag);
remove_handle(rhp, &rhp->mmidr, mmid);
+ deallocate_window(&rhp->rdev, mhp->attr.stag);
kfree(mhp);
PDBG("%s ib_mw %p mmid 0x%x ptr %p\n", __func__, mw, mmid, mhp);
return 0;
@@ -789,12 +796,12 @@ int c4iw_dereg_mr(struct ib_mr *ib_mr)
mhp = to_c4iw_mr(ib_mr);
rhp = mhp->rhp;
mmid = mhp->attr.stag >> 8;
+ remove_handle(rhp, &rhp->mmidr, mmid);
dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
mhp->attr.pbl_addr);
if (mhp->attr.pbl_size)
c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
mhp->attr.pbl_size << 3);
- remove_handle(rhp, &rhp->mmidr, mmid);
if (mhp->kva)
kfree((void *) (unsigned long) mhp->kva);
if (mhp->umem)
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index be1c18f44400..e084fdc6da7f 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -188,8 +188,10 @@ static int c4iw_deallocate_pd(struct ib_pd *pd)
php = to_c4iw_pd(pd);
rhp = php->rhp;
PDBG("%s ibpd %p pdid 0x%x\n", __func__, pd, php->pdid);
- c4iw_put_resource(&rhp->rdev.resource.pdid_fifo, php->pdid,
- &rhp->rdev.resource.pdid_fifo_lock);
+ c4iw_put_resource(&rhp->rdev.resource.pdid_table, php->pdid);
+ mutex_lock(&rhp->rdev.stats.lock);
+ rhp->rdev.stats.pd.cur--;
+ mutex_unlock(&rhp->rdev.stats.lock);
kfree(php);
return 0;
}
@@ -204,14 +206,12 @@ static struct ib_pd *c4iw_allocate_pd(struct ib_device *ibdev,
PDBG("%s ibdev %p\n", __func__, ibdev);
rhp = (struct c4iw_dev *) ibdev;
- pdid = c4iw_get_resource(&rhp->rdev.resource.pdid_fifo,
- &rhp->rdev.resource.pdid_fifo_lock);
+ pdid = c4iw_get_resource(&rhp->rdev.resource.pdid_table);
if (!pdid)
return ERR_PTR(-EINVAL);
php = kzalloc(sizeof(*php), GFP_KERNEL);
if (!php) {
- c4iw_put_resource(&rhp->rdev.resource.pdid_fifo, pdid,
- &rhp->rdev.resource.pdid_fifo_lock);
+ c4iw_put_resource(&rhp->rdev.resource.pdid_table, pdid);
return ERR_PTR(-ENOMEM);
}
php->pdid = pdid;
@@ -222,6 +222,11 @@ static struct ib_pd *c4iw_allocate_pd(struct ib_device *ibdev,
return ERR_PTR(-EFAULT);
}
}
+ mutex_lock(&rhp->rdev.stats.lock);
+ rhp->rdev.stats.pd.cur++;
+ if (rhp->rdev.stats.pd.cur > rhp->rdev.stats.pd.max)
+ rhp->rdev.stats.pd.max = rhp->rdev.stats.pd.cur;
+ mutex_unlock(&rhp->rdev.stats.lock);
PDBG("%s pdid 0x%0x ptr 0x%p\n", __func__, pdid, php);
return &php->ibpd;
}
@@ -438,6 +443,7 @@ int c4iw_register_device(struct c4iw_dev *dev)
(1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) |
(1ull << IB_USER_VERBS_CMD_CREATE_QP) |
(1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_QP) |
(1ull << IB_USER_VERBS_CMD_POLL_CQ) |
(1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
(1ull << IB_USER_VERBS_CMD_POST_SEND) |
@@ -460,6 +466,7 @@ int c4iw_register_device(struct c4iw_dev *dev)
dev->ibdev.destroy_ah = c4iw_ah_destroy;
dev->ibdev.create_qp = c4iw_create_qp;
dev->ibdev.modify_qp = c4iw_ib_modify_qp;
+ dev->ibdev.query_qp = c4iw_ib_query_qp;
dev->ibdev.destroy_qp = c4iw_destroy_qp;
dev->ibdev.create_cq = c4iw_create_cq;
dev->ibdev.destroy_cq = c4iw_destroy_cq;
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index 5f940aeaab1e..45aedf1d9338 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -34,10 +34,19 @@
#include "iw_cxgb4.h"
+static int db_delay_usecs = 1;
+module_param(db_delay_usecs, int, 0644);
+MODULE_PARM_DESC(db_delay_usecs, "Usecs to delay awaiting db fifo to drain");
+
static int ocqp_support = 1;
module_param(ocqp_support, int, 0644);
MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=1)");
+int db_fc_threshold = 2000;
+module_param(db_fc_threshold, int, 0644);
+MODULE_PARM_DESC(db_fc_threshold, "QP count/threshold that triggers automatic "
+ "db flow control mode (default = 2000)");
+
static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state)
{
unsigned long flag;
@@ -1128,6 +1137,35 @@ out:
return ret;
}
+/*
+ * Called by the library when the qp has user dbs disabled due to
+ * a DB_FULL condition. This function will single-thread all user
+ * DB rings to avoid overflowing the hw db-fifo.
+ */
+static int ring_kernel_db(struct c4iw_qp *qhp, u32 qid, u16 inc)
+{
+ int delay = db_delay_usecs;
+
+ mutex_lock(&qhp->rhp->db_mutex);
+ do {
+
+ /*
+ * The interrupt threshold is dbfifo_int_thresh << 6. So
+ * make sure we don't cross that and generate an interrupt.
+ */
+ if (cxgb4_dbfifo_count(qhp->rhp->rdev.lldi.ports[0], 1) <
+ (qhp->rhp->rdev.lldi.dbfifo_int_thresh << 5)) {
+ writel(V_QID(qid) | V_PIDX(inc), qhp->wq.db);
+ break;
+ }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(usecs_to_jiffies(delay));
+ delay = min(delay << 1, 2000);
+ } while (1);
+ mutex_unlock(&qhp->rhp->db_mutex);
+ return 0;
+}
+
int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
enum c4iw_qp_attr_mask mask,
struct c4iw_qp_attributes *attrs,
@@ -1176,6 +1214,15 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
qhp->attr = newattr;
}
+ if (mask & C4IW_QP_ATTR_SQ_DB) {
+ ret = ring_kernel_db(qhp, qhp->wq.sq.qid, attrs->sq_db_inc);
+ goto out;
+ }
+ if (mask & C4IW_QP_ATTR_RQ_DB) {
+ ret = ring_kernel_db(qhp, qhp->wq.rq.qid, attrs->rq_db_inc);
+ goto out;
+ }
+
if (!(mask & C4IW_QP_ATTR_NEXT_STATE))
goto out;
if (qhp->attr.state == attrs->next_state)
@@ -1352,6 +1399,14 @@ out:
return ret;
}
+static int enable_qp_db(int id, void *p, void *data)
+{
+ struct c4iw_qp *qp = p;
+
+ t4_enable_wq_db(&qp->wq);
+ return 0;
+}
+
int c4iw_destroy_qp(struct ib_qp *ib_qp)
{
struct c4iw_dev *rhp;
@@ -1369,7 +1424,16 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
wait_event(qhp->wait, !qhp->ep);
- remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid);
+ spin_lock_irq(&rhp->lock);
+ remove_handle_nolock(rhp, &rhp->qpidr, qhp->wq.sq.qid);
+ rhp->qpcnt--;
+ BUG_ON(rhp->qpcnt < 0);
+ if (rhp->qpcnt <= db_fc_threshold && rhp->db_state == FLOW_CONTROL) {
+ rhp->rdev.stats.db_state_transitions++;
+ rhp->db_state = NORMAL;
+ idr_for_each(&rhp->qpidr, enable_qp_db, NULL);
+ }
+ spin_unlock_irq(&rhp->lock);
atomic_dec(&qhp->refcnt);
wait_event(qhp->wait, !atomic_read(&qhp->refcnt));
@@ -1383,6 +1447,14 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
return 0;
}
+static int disable_qp_db(int id, void *p, void *data)
+{
+ struct c4iw_qp *qp = p;
+
+ t4_disable_wq_db(&qp->wq);
+ return 0;
+}
+
struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
struct ib_udata *udata)
{
@@ -1469,7 +1541,16 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
init_waitqueue_head(&qhp->wait);
atomic_set(&qhp->refcnt, 1);
- ret = insert_handle(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid);
+ spin_lock_irq(&rhp->lock);
+ if (rhp->db_state != NORMAL)
+ t4_disable_wq_db(&qhp->wq);
+ if (++rhp->qpcnt > db_fc_threshold && rhp->db_state == NORMAL) {
+ rhp->rdev.stats.db_state_transitions++;
+ rhp->db_state = FLOW_CONTROL;
+ idr_for_each(&rhp->qpidr, disable_qp_db, NULL);
+ }
+ ret = insert_handle_nolock(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid);
+ spin_unlock_irq(&rhp->lock);
if (ret)
goto err2;
@@ -1613,6 +1694,15 @@ int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
C4IW_QP_ATTR_ENABLE_RDMA_WRITE |
C4IW_QP_ATTR_ENABLE_RDMA_BIND) : 0;
+ /*
+ * Use SQ_PSN and RQ_PSN to pass in IDX_INC values for
+ * ringing the queue db when we're in DB_FULL mode.
+ */
+ attrs.sq_db_inc = attr->sq_psn;
+ attrs.rq_db_inc = attr->rq_psn;
+ mask |= (attr_mask & IB_QP_SQ_PSN) ? C4IW_QP_ATTR_SQ_DB : 0;
+ mask |= (attr_mask & IB_QP_RQ_PSN) ? C4IW_QP_ATTR_RQ_DB : 0;
+
return c4iw_modify_qp(rhp, qhp, mask, &attrs, 0);
}
@@ -1621,3 +1711,14 @@ struct ib_qp *c4iw_get_qp(struct ib_device *dev, int qpn)
PDBG("%s ib_dev %p qpn 0x%x\n", __func__, dev, qpn);
return (struct ib_qp *)get_qhp(to_c4iw_dev(dev), qpn);
}
+
+int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask, struct ib_qp_init_attr *init_attr)
+{
+ struct c4iw_qp *qhp = to_c4iw_qp(ibqp);
+
+ memset(attr, 0, sizeof *attr);
+ memset(init_attr, 0, sizeof *init_attr);
+ attr->qp_state = to_ib_qp_state(qhp->attr.state);
+ return 0;
+}
diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c
index 407ff3924150..cdef4d7fb6d8 100644
--- a/drivers/infiniband/hw/cxgb4/resource.c
+++ b/drivers/infiniband/hw/cxgb4/resource.c
@@ -30,96 +30,25 @@
* SOFTWARE.
*/
/* Crude resource management */
-#include <linux/kernel.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-#include <linux/kfifo.h>
#include <linux/spinlock.h>
-#include <linux/errno.h>
#include <linux/genalloc.h>
#include <linux/ratelimit.h>
#include "iw_cxgb4.h"
-#define RANDOM_SIZE 16
-
-static int __c4iw_init_resource_fifo(struct kfifo *fifo,
- spinlock_t *fifo_lock,
- u32 nr, u32 skip_low,
- u32 skip_high,
- int random)
-{
- u32 i, j, entry = 0, idx;
- u32 random_bytes;
- u32 rarray[16];
- spin_lock_init(fifo_lock);
-
- if (kfifo_alloc(fifo, nr * sizeof(u32), GFP_KERNEL))
- return -ENOMEM;
-
- for (i = 0; i < skip_low + skip_high; i++)
- kfifo_in(fifo, (unsigned char *) &entry, sizeof(u32));
- if (random) {
- j = 0;
- random_bytes = random32();
- for (i = 0; i < RANDOM_SIZE; i++)
- rarray[i] = i + skip_low;
- for (i = skip_low + RANDOM_SIZE; i < nr - skip_high; i++) {
- if (j >= RANDOM_SIZE) {
- j = 0;
- random_bytes = random32();
- }
- idx = (random_bytes >> (j * 2)) & 0xF;
- kfifo_in(fifo,
- (unsigned char *) &rarray[idx],
- sizeof(u32));
- rarray[idx] = i;
- j++;
- }
- for (i = 0; i < RANDOM_SIZE; i++)
- kfifo_in(fifo,
- (unsigned char *) &rarray[i],
- sizeof(u32));
- } else
- for (i = skip_low; i < nr - skip_high; i++)
- kfifo_in(fifo, (unsigned char *) &i, sizeof(u32));
-
- for (i = 0; i < skip_low + skip_high; i++)
- if (kfifo_out_locked(fifo, (unsigned char *) &entry,
- sizeof(u32), fifo_lock))
- break;
- return 0;
-}
-
-static int c4iw_init_resource_fifo(struct kfifo *fifo, spinlock_t * fifo_lock,
- u32 nr, u32 skip_low, u32 skip_high)
-{
- return __c4iw_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
- skip_high, 0);
-}
-
-static int c4iw_init_resource_fifo_random(struct kfifo *fifo,
- spinlock_t *fifo_lock,
- u32 nr, u32 skip_low, u32 skip_high)
-{
- return __c4iw_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
- skip_high, 1);
-}
-
-static int c4iw_init_qid_fifo(struct c4iw_rdev *rdev)
+static int c4iw_init_qid_table(struct c4iw_rdev *rdev)
{
u32 i;
- spin_lock_init(&rdev->resource.qid_fifo_lock);
-
- if (kfifo_alloc(&rdev->resource.qid_fifo, rdev->lldi.vr->qp.size *
- sizeof(u32), GFP_KERNEL))
+ if (c4iw_id_table_alloc(&rdev->resource.qid_table,
+ rdev->lldi.vr->qp.start,
+ rdev->lldi.vr->qp.size,
+ rdev->lldi.vr->qp.size, 0))
return -ENOMEM;
for (i = rdev->lldi.vr->qp.start;
- i < rdev->lldi.vr->qp.start + rdev->lldi.vr->qp.size; i++)
+ i < rdev->lldi.vr->qp.start + rdev->lldi.vr->qp.size; i++)
if (!(i & rdev->qpmask))
- kfifo_in(&rdev->resource.qid_fifo,
- (unsigned char *) &i, sizeof(u32));
+ c4iw_id_free(&rdev->resource.qid_table, i);
return 0;
}
@@ -127,44 +56,42 @@ static int c4iw_init_qid_fifo(struct c4iw_rdev *rdev)
int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid)
{
int err = 0;
- err = c4iw_init_resource_fifo_random(&rdev->resource.tpt_fifo,
- &rdev->resource.tpt_fifo_lock,
- nr_tpt, 1, 0);
+ err = c4iw_id_table_alloc(&rdev->resource.tpt_table, 0, nr_tpt, 1,
+ C4IW_ID_TABLE_F_RANDOM);
if (err)
goto tpt_err;
- err = c4iw_init_qid_fifo(rdev);
+ err = c4iw_init_qid_table(rdev);
if (err)
goto qid_err;
- err = c4iw_init_resource_fifo(&rdev->resource.pdid_fifo,
- &rdev->resource.pdid_fifo_lock,
- nr_pdid, 1, 0);
+ err = c4iw_id_table_alloc(&rdev->resource.pdid_table, 0,
+ nr_pdid, 1, 0);
if (err)
goto pdid_err;
return 0;
-pdid_err:
- kfifo_free(&rdev->resource.qid_fifo);
-qid_err:
- kfifo_free(&rdev->resource.tpt_fifo);
-tpt_err:
+ pdid_err:
+ c4iw_id_table_free(&rdev->resource.qid_table);
+ qid_err:
+ c4iw_id_table_free(&rdev->resource.tpt_table);
+ tpt_err:
return -ENOMEM;
}
/*
* returns 0 if no resource available
*/
-u32 c4iw_get_resource(struct kfifo *fifo, spinlock_t *lock)
+u32 c4iw_get_resource(struct c4iw_id_table *id_table)
{
u32 entry;
- if (kfifo_out_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock))
- return entry;
- else
+ entry = c4iw_id_alloc(id_table);
+ if (entry == (u32)(-1))
return 0;
+ return entry;
}
-void c4iw_put_resource(struct kfifo *fifo, u32 entry, spinlock_t *lock)
+void c4iw_put_resource(struct c4iw_id_table *id_table, u32 entry)
{
PDBG("%s entry 0x%x\n", __func__, entry);
- kfifo_in_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock);
+ c4iw_id_free(id_table, entry);
}
u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
@@ -181,10 +108,12 @@ u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
qid = entry->qid;
kfree(entry);
} else {
- qid = c4iw_get_resource(&rdev->resource.qid_fifo,
- &rdev->resource.qid_fifo_lock);
+ qid = c4iw_get_resource(&rdev->resource.qid_table);
if (!qid)
goto out;
+ mutex_lock(&rdev->stats.lock);
+ rdev->stats.qid.cur += rdev->qpmask + 1;
+ mutex_unlock(&rdev->stats.lock);
for (i = qid+1; i & rdev->qpmask; i++) {
entry = kmalloc(sizeof *entry, GFP_KERNEL);
if (!entry)
@@ -213,6 +142,10 @@ u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
out:
mutex_unlock(&uctx->lock);
PDBG("%s qid 0x%x\n", __func__, qid);
+ mutex_lock(&rdev->stats.lock);
+ if (rdev->stats.qid.cur > rdev->stats.qid.max)
+ rdev->stats.qid.max = rdev->stats.qid.cur;
+ mutex_unlock(&rdev->stats.lock);
return qid;
}
@@ -245,10 +178,12 @@ u32 c4iw_get_qpid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
qid = entry->qid;
kfree(entry);
} else {
- qid = c4iw_get_resource(&rdev->resource.qid_fifo,
- &rdev->resource.qid_fifo_lock);
+ qid = c4iw_get_resource(&rdev->resource.qid_table);
if (!qid)
goto out;
+ mutex_lock(&rdev->stats.lock);
+ rdev->stats.qid.cur += rdev->qpmask + 1;
+ mutex_unlock(&rdev->stats.lock);
for (i = qid+1; i & rdev->qpmask; i++) {
entry = kmalloc(sizeof *entry, GFP_KERNEL);
if (!entry)
@@ -277,6 +212,10 @@ u32 c4iw_get_qpid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
out:
mutex_unlock(&uctx->lock);
PDBG("%s qid 0x%x\n", __func__, qid);
+ mutex_lock(&rdev->stats.lock);
+ if (rdev->stats.qid.cur > rdev->stats.qid.max)
+ rdev->stats.qid.max = rdev->stats.qid.cur;
+ mutex_unlock(&rdev->stats.lock);
return qid;
}
@@ -297,9 +236,9 @@ void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qid,
void c4iw_destroy_resource(struct c4iw_resource *rscp)
{
- kfifo_free(&rscp->tpt_fifo);
- kfifo_free(&rscp->qid_fifo);
- kfifo_free(&rscp->pdid_fifo);
+ c4iw_id_table_free(&rscp->tpt_table);
+ c4iw_id_table_free(&rscp->qid_table);
+ c4iw_id_table_free(&rscp->pdid_table);
}
/*
@@ -312,15 +251,23 @@ u32 c4iw_pblpool_alloc(struct c4iw_rdev *rdev, int size)
{
unsigned long addr = gen_pool_alloc(rdev->pbl_pool, size);
PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
- if (!addr)
- printk_ratelimited(KERN_WARNING MOD "%s: Out of PBL memory\n",
- pci_name(rdev->lldi.pdev));
+ mutex_lock(&rdev->stats.lock);
+ if (addr) {
+ rdev->stats.pbl.cur += roundup(size, 1 << MIN_PBL_SHIFT);
+ if (rdev->stats.pbl.cur > rdev->stats.pbl.max)
+ rdev->stats.pbl.max = rdev->stats.pbl.cur;
+ } else
+ rdev->stats.pbl.fail++;
+ mutex_unlock(&rdev->stats.lock);
return (u32)addr;
}
void c4iw_pblpool_free(struct c4iw_rdev *rdev, u32 addr, int size)
{
PDBG("%s addr 0x%x size %d\n", __func__, addr, size);
+ mutex_lock(&rdev->stats.lock);
+ rdev->stats.pbl.cur -= roundup(size, 1 << MIN_PBL_SHIFT);
+ mutex_unlock(&rdev->stats.lock);
gen_pool_free(rdev->pbl_pool, (unsigned long)addr, size);
}
@@ -377,12 +324,23 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size)
if (!addr)
printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n",
pci_name(rdev->lldi.pdev));
+ mutex_lock(&rdev->stats.lock);
+ if (addr) {
+ rdev->stats.rqt.cur += roundup(size << 6, 1 << MIN_RQT_SHIFT);
+ if (rdev->stats.rqt.cur > rdev->stats.rqt.max)
+ rdev->stats.rqt.max = rdev->stats.rqt.cur;
+ } else
+ rdev->stats.rqt.fail++;
+ mutex_unlock(&rdev->stats.lock);
return (u32)addr;
}
void c4iw_rqtpool_free(struct c4iw_rdev *rdev, u32 addr, int size)
{
PDBG("%s addr 0x%x size %d\n", __func__, addr, size << 6);
+ mutex_lock(&rdev->stats.lock);
+ rdev->stats.rqt.cur -= roundup(size << 6, 1 << MIN_RQT_SHIFT);
+ mutex_unlock(&rdev->stats.lock);
gen_pool_free(rdev->rqt_pool, (unsigned long)addr, size << 6);
}
@@ -433,12 +391,22 @@ u32 c4iw_ocqp_pool_alloc(struct c4iw_rdev *rdev, int size)
{
unsigned long addr = gen_pool_alloc(rdev->ocqp_pool, size);
PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
+ if (addr) {
+ mutex_lock(&rdev->stats.lock);
+ rdev->stats.ocqp.cur += roundup(size, 1 << MIN_OCQP_SHIFT);
+ if (rdev->stats.ocqp.cur > rdev->stats.ocqp.max)
+ rdev->stats.ocqp.max = rdev->stats.ocqp.cur;
+ mutex_unlock(&rdev->stats.lock);
+ }
return (u32)addr;
}
void c4iw_ocqp_pool_free(struct c4iw_rdev *rdev, u32 addr, int size)
{
PDBG("%s addr 0x%x size %d\n", __func__, addr, size);
+ mutex_lock(&rdev->stats.lock);
+ rdev->stats.ocqp.cur -= roundup(size, 1 << MIN_OCQP_SHIFT);
+ mutex_unlock(&rdev->stats.lock);
gen_pool_free(rdev->ocqp_pool, (unsigned long)addr, size);
}
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h
index c0221eec8817..16f26ab29302 100644
--- a/drivers/infiniband/hw/cxgb4/t4.h
+++ b/drivers/infiniband/hw/cxgb4/t4.h
@@ -62,6 +62,10 @@ struct t4_status_page {
__be16 pidx;
u8 qp_err; /* flit 1 - sw owns */
u8 db_off;
+ u8 pad;
+ u16 host_wq_pidx;
+ u16 host_cidx;
+ u16 host_pidx;
};
#define T4_EQ_ENTRY_SIZE 64
@@ -375,6 +379,16 @@ static inline void t4_rq_consume(struct t4_wq *wq)
wq->rq.cidx = 0;
}
+static inline u16 t4_rq_host_wq_pidx(struct t4_wq *wq)
+{
+ return wq->rq.queue[wq->rq.size].status.host_wq_pidx;
+}
+
+static inline u16 t4_rq_wq_size(struct t4_wq *wq)
+{
+ return wq->rq.size * T4_RQ_NUM_SLOTS;
+}
+
static inline int t4_sq_onchip(struct t4_sq *sq)
{
return sq->flags & T4_SQ_ONCHIP;
@@ -412,6 +426,16 @@ static inline void t4_sq_consume(struct t4_wq *wq)
wq->sq.cidx = 0;
}
+static inline u16 t4_sq_host_wq_pidx(struct t4_wq *wq)
+{
+ return wq->sq.queue[wq->sq.size].status.host_wq_pidx;
+}
+
+static inline u16 t4_sq_wq_size(struct t4_wq *wq)
+{
+ return wq->sq.size * T4_SQ_NUM_SLOTS;
+}
+
static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc)
{
wmb();
diff --git a/drivers/infiniband/hw/cxgb4/user.h b/drivers/infiniband/hw/cxgb4/user.h
index e6669d54770e..32b754c35ab7 100644
--- a/drivers/infiniband/hw/cxgb4/user.h
+++ b/drivers/infiniband/hw/cxgb4/user.h
@@ -32,7 +32,7 @@
#ifndef __C4IW_USER_H__
#define __C4IW_USER_H__
-#define C4IW_UVERBS_ABI_VERSION 1
+#define C4IW_UVERBS_ABI_VERSION 2
/*
* Make sure that all structs defined in this file remain laid out so
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c
index 1d7aea132a09..7cc305488a3d 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6110.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c
@@ -596,8 +596,7 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
ipath_format_hwerrors(hwerrs,
ipath_6110_hwerror_msgs,
- sizeof(ipath_6110_hwerror_msgs) /
- sizeof(ipath_6110_hwerror_msgs[0]),
+ ARRAY_SIZE(ipath_6110_hwerror_msgs),
msg, msgl);
if (hwerrs & (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS))
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index c0a03ac03ee7..26dfbc8ee0f1 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -209,8 +209,7 @@ void ipath_format_hwerrors(u64 hwerrs,
{
int i;
const int glen =
- sizeof(ipath_generic_hwerror_msgs) /
- sizeof(ipath_generic_hwerror_msgs[0]);
+ ARRAY_SIZE(ipath_generic_hwerror_msgs);
for (i=0; i<glen; i++) {
if (hwerrs & ipath_generic_hwerror_msgs[i].mask) {
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index 77c8cb4c5073..6d4ef71cbcdf 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -50,7 +50,7 @@ static void mlx4_ib_cq_event(struct mlx4_cq *cq, enum mlx4_event type)
struct ib_cq *ibcq;
if (type != MLX4_EVENT_TYPE_CQ_ERROR) {
- printk(KERN_WARNING "mlx4_ib: Unexpected event type %d "
+ pr_warn("Unexpected event type %d "
"on CQ %06x\n", type, cq->cqn);
return;
}
@@ -222,6 +222,9 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
uar = &dev->priv_uar;
}
+ if (dev->eq_table)
+ vector = dev->eq_table[vector % ibdev->num_comp_vectors];
+
err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar,
cq->db.dma, &cq->mcq, vector, 0);
if (err)
@@ -463,7 +466,7 @@ static void dump_cqe(void *cqe)
{
__be32 *buf = cqe;
- printk(KERN_DEBUG "CQE contents %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ pr_debug("CQE contents %08x %08x %08x %08x %08x %08x %08x %08x\n",
be32_to_cpu(buf[0]), be32_to_cpu(buf[1]), be32_to_cpu(buf[2]),
be32_to_cpu(buf[3]), be32_to_cpu(buf[4]), be32_to_cpu(buf[5]),
be32_to_cpu(buf[6]), be32_to_cpu(buf[7]));
@@ -473,7 +476,7 @@ static void mlx4_ib_handle_error_cqe(struct mlx4_err_cqe *cqe,
struct ib_wc *wc)
{
if (cqe->syndrome == MLX4_CQE_SYNDROME_LOCAL_QP_OP_ERR) {
- printk(KERN_DEBUG "local QP operation err "
+ pr_debug("local QP operation err "
"(QPN %06x, WQE index %x, vendor syndrome %02x, "
"opcode = %02x)\n",
be32_to_cpu(cqe->my_qpn), be16_to_cpu(cqe->wqe_index),
@@ -576,7 +579,7 @@ repoll:
if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) == MLX4_OPCODE_NOP &&
is_send)) {
- printk(KERN_WARNING "Completion for NOP opcode detected!\n");
+ pr_warn("Completion for NOP opcode detected!\n");
return -EINVAL;
}
@@ -606,7 +609,7 @@ repoll:
mqp = __mlx4_qp_lookup(to_mdev(cq->ibcq.device)->dev,
be32_to_cpu(cqe->vlan_my_qpn));
if (unlikely(!mqp)) {
- printk(KERN_WARNING "CQ %06x with entry for unknown QPN %06x\n",
+ pr_warn("CQ %06x with entry for unknown QPN %06x\n",
cq->mcq.cqn, be32_to_cpu(cqe->vlan_my_qpn) & MLX4_CQE_QPN_MASK);
return -EINVAL;
}
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index b948b6dd5d55..ee1c577238f7 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -789,7 +789,7 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
list_del(&ge->list);
kfree(ge);
} else
- printk(KERN_WARNING "could not find mgid entry\n");
+ pr_warn("could not find mgid entry\n");
mutex_unlock(&mqp->mutex);
@@ -902,7 +902,7 @@ static void update_gids_task(struct work_struct *work)
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox)) {
- printk(KERN_WARNING "update gid table failed %ld\n", PTR_ERR(mailbox));
+ pr_warn("update gid table failed %ld\n", PTR_ERR(mailbox));
return;
}
@@ -913,7 +913,7 @@ static void update_gids_task(struct work_struct *work)
1, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
MLX4_CMD_NATIVE);
if (err)
- printk(KERN_WARNING "set port command failed\n");
+ pr_warn("set port command failed\n");
else {
memcpy(gw->dev->iboe.gid_table[gw->port - 1], gw->gids, sizeof gw->gids);
event.device = &gw->dev->ib_dev;
@@ -1076,18 +1076,98 @@ static int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event
return NOTIFY_DONE;
}
+static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
+{
+ char name[32];
+ int eq_per_port = 0;
+ int added_eqs = 0;
+ int total_eqs = 0;
+ int i, j, eq;
+
+ /* Init eq table */
+ ibdev->eq_table = NULL;
+ ibdev->eq_added = 0;
+
+ /* Legacy mode? */
+ if (dev->caps.comp_pool == 0)
+ return;
+
+ eq_per_port = rounddown_pow_of_two(dev->caps.comp_pool/
+ dev->caps.num_ports);
+
+ /* Init eq table */
+ added_eqs = 0;
+ mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
+ added_eqs += eq_per_port;
+
+ total_eqs = dev->caps.num_comp_vectors + added_eqs;
+
+ ibdev->eq_table = kzalloc(total_eqs * sizeof(int), GFP_KERNEL);
+ if (!ibdev->eq_table)
+ return;
+
+ ibdev->eq_added = added_eqs;
+
+ eq = 0;
+ mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) {
+ for (j = 0; j < eq_per_port; j++) {
+ sprintf(name, "mlx4-ib-%d-%d@%s",
+ i, j, dev->pdev->bus->name);
+ /* Set IRQ for specific name (per ring) */
+ if (mlx4_assign_eq(dev, name, &ibdev->eq_table[eq])) {
+ /* Use legacy (same as mlx4_en driver) */
+ pr_warn("Can't allocate EQ %d; reverting to legacy\n", eq);
+ ibdev->eq_table[eq] =
+ (eq % dev->caps.num_comp_vectors);
+ }
+ eq++;
+ }
+ }
+
+ /* Fill the reset of the vector with legacy EQ */
+ for (i = 0, eq = added_eqs; i < dev->caps.num_comp_vectors; i++)
+ ibdev->eq_table[eq++] = i;
+
+ /* Advertise the new number of EQs to clients */
+ ibdev->ib_dev.num_comp_vectors = total_eqs;
+}
+
+static void mlx4_ib_free_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
+{
+ int i;
+ int total_eqs;
+
+ /* Reset the advertised EQ number */
+ ibdev->ib_dev.num_comp_vectors = dev->caps.num_comp_vectors;
+
+ /* Free only the added eqs */
+ for (i = 0; i < ibdev->eq_added; i++) {
+ /* Don't free legacy eqs if used */
+ if (ibdev->eq_table[i] <= dev->caps.num_comp_vectors)
+ continue;
+ mlx4_release_eq(dev, ibdev->eq_table[i]);
+ }
+
+ total_eqs = dev->caps.num_comp_vectors + ibdev->eq_added;
+ memset(ibdev->eq_table, 0, total_eqs * sizeof(int));
+ kfree(ibdev->eq_table);
+
+ ibdev->eq_table = NULL;
+ ibdev->eq_added = 0;
+}
+
static void *mlx4_ib_add(struct mlx4_dev *dev)
{
struct mlx4_ib_dev *ibdev;
int num_ports = 0;
- int i;
+ int i, j;
int err;
struct mlx4_ib_iboe *iboe;
- printk_once(KERN_INFO "%s", mlx4_ib_version);
+ pr_info_once("%s", mlx4_ib_version);
if (mlx4_is_mfunc(dev)) {
- printk(KERN_WARNING "IB not yet supported in SRIOV\n");
+ pr_warn("IB not yet supported in SRIOV\n");
return NULL;
}
@@ -1210,6 +1290,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
(1ull << IB_USER_VERBS_CMD_CLOSE_XRCD);
}
+ mlx4_ib_alloc_eqs(dev, ibdev);
+
spin_lock_init(&iboe->lock);
if (init_node_data(ibdev))
@@ -1241,9 +1323,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
goto err_reg;
}
- for (i = 0; i < ARRAY_SIZE(mlx4_class_attributes); ++i) {
+ for (j = 0; j < ARRAY_SIZE(mlx4_class_attributes); ++j) {
if (device_create_file(&ibdev->ib_dev.dev,
- mlx4_class_attributes[i]))
+ mlx4_class_attributes[j]))
goto err_notif;
}
@@ -1253,7 +1335,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
err_notif:
if (unregister_netdevice_notifier(&ibdev->iboe.nb))
- printk(KERN_WARNING "failure unregistering notifier\n");
+ pr_warn("failure unregistering notifier\n");
flush_workqueue(wq);
err_reg:
@@ -1288,7 +1370,7 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
ib_unregister_device(&ibdev->ib_dev);
if (ibdev->iboe.nb.notifier_call) {
if (unregister_netdevice_notifier(&ibdev->iboe.nb))
- printk(KERN_WARNING "failure unregistering notifier\n");
+ pr_warn("failure unregistering notifier\n");
ibdev->iboe.nb.notifier_call = NULL;
}
iounmap(ibdev->uar_map);
@@ -1298,6 +1380,8 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
mlx4_CLOSE_PORT(dev, p);
+ mlx4_ib_free_eqs(dev, ibdev);
+
mlx4_uar_free(dev, &ibdev->priv_uar);
mlx4_pd_free(dev, ibdev->priv_pdn);
ib_dealloc_device(&ibdev->ib_dev);
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index ed80345c99ae..e62297cc77cc 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -202,6 +202,8 @@ struct mlx4_ib_dev {
bool ib_active;
struct mlx4_ib_iboe iboe;
int counters[MLX4_MAX_PORTS];
+ int *eq_table;
+ int eq_added;
};
static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev)
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c
index dca55b19a6f1..bbaf6176f207 100644
--- a/drivers/infiniband/hw/mlx4/mr.c
+++ b/drivers/infiniband/hw/mlx4/mr.c
@@ -338,7 +338,7 @@ int mlx4_ib_unmap_fmr(struct list_head *fmr_list)
err = mlx4_SYNC_TPT(mdev);
if (err)
- printk(KERN_WARNING "mlx4_ib: SYNC_TPT error %d when "
+ pr_warn("SYNC_TPT error %d when "
"unmapping FMRs\n", err);
return 0;
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 3a7848966627..ceb33327091a 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -84,6 +84,11 @@ enum {
MLX4_IB_CACHE_LINE_SIZE = 64,
};
+enum {
+ MLX4_RAW_QP_MTU = 7,
+ MLX4_RAW_QP_MSGMAX = 31,
+};
+
static const __be32 mlx4_ib_opcode[] = {
[IB_WR_SEND] = cpu_to_be32(MLX4_OPCODE_SEND),
[IB_WR_LSO] = cpu_to_be32(MLX4_OPCODE_LSO),
@@ -256,7 +261,7 @@ static void mlx4_ib_qp_event(struct mlx4_qp *qp, enum mlx4_event type)
event.event = IB_EVENT_QP_ACCESS_ERR;
break;
default:
- printk(KERN_WARNING "mlx4_ib: Unexpected event type %d "
+ pr_warn("Unexpected event type %d "
"on QP %06x\n", type, qp->qpn);
return;
}
@@ -573,7 +578,12 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (sqpn) {
qpn = sqpn;
} else {
- err = mlx4_qp_reserve_range(dev->dev, 1, 1, &qpn);
+ /* Raw packet QPNs must be aligned to 8 bits. If not, the WQE
+ * BlueFlame setup flow wrongly causes VLAN insertion. */
+ if (init_attr->qp_type == IB_QPT_RAW_PACKET)
+ err = mlx4_qp_reserve_range(dev->dev, 1, 1 << 8, &qpn);
+ else
+ err = mlx4_qp_reserve_range(dev->dev, 1, 1, &qpn);
if (err)
goto err_wrid;
}
@@ -715,7 +725,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
if (qp->state != IB_QPS_RESET)
if (mlx4_qp_modify(dev->dev, NULL, to_mlx4_state(qp->state),
MLX4_QP_STATE_RST, NULL, 0, 0, &qp->mqp))
- printk(KERN_WARNING "mlx4_ib: modify QP %06x to RESET failed.\n",
+ pr_warn("modify QP %06x to RESET failed.\n",
qp->mqp.qpn);
get_cqs(qp, &send_cq, &recv_cq);
@@ -791,6 +801,7 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
case IB_QPT_RC:
case IB_QPT_UC:
case IB_QPT_UD:
+ case IB_QPT_RAW_PACKET:
{
qp = kzalloc(sizeof *qp, GFP_KERNEL);
if (!qp)
@@ -872,7 +883,8 @@ static int to_mlx4_st(enum ib_qp_type type)
case IB_QPT_XRC_INI:
case IB_QPT_XRC_TGT: return MLX4_QP_ST_XRC;
case IB_QPT_SMI:
- case IB_QPT_GSI: return MLX4_QP_ST_MLX;
+ case IB_QPT_GSI:
+ case IB_QPT_RAW_PACKET: return MLX4_QP_ST_MLX;
default: return -1;
}
}
@@ -946,7 +958,7 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
if (ah->ah_flags & IB_AH_GRH) {
if (ah->grh.sgid_index >= dev->dev->caps.gid_table_len[port]) {
- printk(KERN_ERR "sgid_index (%u) too large. max is %d\n",
+ pr_err("sgid_index (%u) too large. max is %d\n",
ah->grh.sgid_index, dev->dev->caps.gid_table_len[port] - 1);
return -1;
}
@@ -1042,6 +1054,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI)
context->mtu_msgmax = (IB_MTU_4096 << 5) | 11;
+ else if (ibqp->qp_type == IB_QPT_RAW_PACKET)
+ context->mtu_msgmax = (MLX4_RAW_QP_MTU << 5) | MLX4_RAW_QP_MSGMAX;
else if (ibqp->qp_type == IB_QPT_UD) {
if (qp->flags & MLX4_IB_QP_LSO)
context->mtu_msgmax = (IB_MTU_4096 << 5) |
@@ -1050,7 +1064,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
context->mtu_msgmax = (IB_MTU_4096 << 5) | 12;
} else if (attr_mask & IB_QP_PATH_MTU) {
if (attr->path_mtu < IB_MTU_256 || attr->path_mtu > IB_MTU_4096) {
- printk(KERN_ERR "path MTU (%u) is invalid\n",
+ pr_err("path MTU (%u) is invalid\n",
attr->path_mtu);
goto out;
}
@@ -1200,7 +1214,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (cur_state == IB_QPS_INIT &&
new_state == IB_QPS_RTR &&
(ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI ||
- ibqp->qp_type == IB_QPT_UD)) {
+ ibqp->qp_type == IB_QPT_UD ||
+ ibqp->qp_type == IB_QPT_RAW_PACKET)) {
context->pri_path.sched_queue = (qp->port - 1) << 6;
if (is_qp0(dev, qp))
context->pri_path.sched_queue |= MLX4_IB_DEFAULT_QP0_SCHED_QUEUE;
@@ -1266,7 +1281,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (is_qp0(dev, qp)) {
if (cur_state != IB_QPS_RTR && new_state == IB_QPS_RTR)
if (mlx4_INIT_PORT(dev->dev, qp->port))
- printk(KERN_WARNING "INIT_PORT failed for port %d\n",
+ pr_warn("INIT_PORT failed for port %d\n",
qp->port);
if (cur_state != IB_QPS_RESET && cur_state != IB_QPS_ERR &&
@@ -1319,6 +1334,11 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
goto out;
}
+ if ((attr_mask & IB_QP_PORT) && (ibqp->qp_type == IB_QPT_RAW_PACKET) &&
+ (rdma_port_get_link_layer(&dev->ib_dev, attr->port_num) !=
+ IB_LINK_LAYER_ETHERNET))
+ goto out;
+
if (attr_mask & IB_QP_PKEY_INDEX) {
int p = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
if (attr->pkey_index >= dev->dev->caps.pkey_table_len[p])
@@ -1424,6 +1444,9 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
if (is_eth) {
u8 *smac;
+ u16 pcp = (be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 29) << 13;
+
+ mlx->sched_prio = cpu_to_be16(pcp);
memcpy(sqp->ud_header.eth.dmac_h, ah->av.eth.mac, 6);
/* FIXME: cache smac value? */
@@ -1434,10 +1457,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
if (!is_vlan) {
sqp->ud_header.eth.type = cpu_to_be16(MLX4_IB_IBOE_ETHERTYPE);
} else {
- u16 pcp;
-
sqp->ud_header.vlan.type = cpu_to_be16(MLX4_IB_IBOE_ETHERTYPE);
- pcp = (be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 29) << 13;
sqp->ud_header.vlan.tag = cpu_to_be16(vlan | pcp);
}
} else {
@@ -1460,16 +1480,16 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
header_size = ib_ud_header_pack(&sqp->ud_header, sqp->header_buf);
if (0) {
- printk(KERN_ERR "built UD header of size %d:\n", header_size);
+ pr_err("built UD header of size %d:\n", header_size);
for (i = 0; i < header_size / 4; ++i) {
if (i % 8 == 0)
- printk(" [%02x] ", i * 4);
- printk(" %08x",
- be32_to_cpu(((__be32 *) sqp->header_buf)[i]));
+ pr_err(" [%02x] ", i * 4);
+ pr_cont(" %08x",
+ be32_to_cpu(((__be32 *) sqp->header_buf)[i]));
if ((i + 1) % 8 == 0)
- printk("\n");
+ pr_cont("\n");
}
- printk("\n");
+ pr_err("\n");
}
/*
diff --git a/drivers/infiniband/hw/mlx4/srq.c b/drivers/infiniband/hw/mlx4/srq.c
index 39542f3703b8..60c5fb025fc7 100644
--- a/drivers/infiniband/hw/mlx4/srq.c
+++ b/drivers/infiniband/hw/mlx4/srq.c
@@ -59,7 +59,7 @@ static void mlx4_ib_srq_event(struct mlx4_srq *srq, enum mlx4_event type)
event.event = IB_EVENT_SRQ_ERR;
break;
default:
- printk(KERN_WARNING "mlx4_ib: Unexpected event type %d "
+ pr_warn("Unexpected event type %d "
"on SRQ %06x\n", type, srq->srqn);
return;
}
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 71edfbbcce1c..020e95c4c4b9 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -2884,7 +2884,8 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
ibevent.device = nesqp->ibqp.device;
ibevent.event = nesqp->terminate_eventtype;
ibevent.element.qp = &nesqp->ibqp;
- nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
+ if (nesqp->ibqp.event_handler)
+ nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
}
}
@@ -3320,6 +3321,10 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
nesqp->private_data_len = conn_param->private_data_len;
nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord);
+ /* space for rdma0 read msg */
+ if (conn_param->ord == 0)
+ nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(1);
+
nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord);
nes_debug(NES_DBG_CM, "mpa private data len =%u\n",
conn_param->private_data_len);
diff --git a/drivers/infiniband/hw/ocrdma/Kconfig b/drivers/infiniband/hw/ocrdma/Kconfig
new file mode 100644
index 000000000000..b5b6056c8518
--- /dev/null
+++ b/drivers/infiniband/hw/ocrdma/Kconfig
@@ -0,0 +1,8 @@
+config INFINIBAND_OCRDMA
+ tristate "Emulex One Connect HCA support"
+ depends on ETHERNET && NETDEVICES && PCI && (IPV6 || IPV6=n)
+ select NET_VENDOR_EMULEX
+ select BE2NET
+ ---help---
+ This driver provides low-level InfiniBand over Ethernet
+ support for Emulex One Connect host channel adapters (HCAs).
diff --git a/drivers/infiniband/hw/ocrdma/Makefile b/drivers/infiniband/hw/ocrdma/Makefile
new file mode 100644
index 000000000000..06a5bed12e43
--- /dev/null
+++ b/drivers/infiniband/hw/ocrdma/Makefile
@@ -0,0 +1,5 @@
+ccflags-y := -Idrivers/net/ethernet/emulex/benet
+
+obj-$(CONFIG_INFINIBAND_OCRDMA) += ocrdma.o
+
+ocrdma-y := ocrdma_main.o ocrdma_verbs.o ocrdma_hw.o ocrdma_ah.o
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h
new file mode 100644
index 000000000000..85a69c958559
--- /dev/null
+++ b/drivers/infiniband/hw/ocrdma/ocrdma.h
@@ -0,0 +1,393 @@
+/*******************************************************************
+ * This file is part of the Emulex RoCE Device Driver for *
+ * RoCE (RDMA over Converged Ethernet) adapters. *
+ * Copyright (C) 2008-2012 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.emulex.com *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of version 2 of the GNU General *
+ * Public License as published by the Free Software Foundation. *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID. See the GNU General Public License for *
+ * more details, a copy of which can be found in the file COPYING *
+ * included with this package. *
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ *******************************************************************/
+
+#ifndef __OCRDMA_H__
+#define __OCRDMA_H__
+
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_user_verbs.h>
+
+#include <be_roce.h>
+#include "ocrdma_sli.h"
+
+#define OCRDMA_ROCE_DEV_VERSION "1.0.0"
+#define OCRDMA_NODE_DESC "Emulex OneConnect RoCE HCA"
+
+#define ocrdma_err(format, arg...) printk(KERN_ERR format, ##arg)
+
+#define OCRDMA_MAX_AH 512
+
+#define OCRDMA_UVERBS(CMD_NAME) (1ull << IB_USER_VERBS_CMD_##CMD_NAME)
+
+struct ocrdma_dev_attr {
+ u8 fw_ver[32];
+ u32 vendor_id;
+ u32 device_id;
+ u16 max_pd;
+ u16 max_cq;
+ u16 max_cqe;
+ u16 max_qp;
+ u16 max_wqe;
+ u16 max_rqe;
+ u32 max_inline_data;
+ int max_send_sge;
+ int max_recv_sge;
+ int max_mr;
+ u64 max_mr_size;
+ u32 max_num_mr_pbl;
+ int max_fmr;
+ int max_map_per_fmr;
+ int max_pages_per_frmr;
+ u16 max_ord_per_qp;
+ u16 max_ird_per_qp;
+
+ int device_cap_flags;
+ u8 cq_overflow_detect;
+ u8 srq_supported;
+
+ u32 wqe_size;
+ u32 rqe_size;
+ u32 ird_page_size;
+ u8 local_ca_ack_delay;
+ u8 ird;
+ u8 num_ird_pages;
+};
+
+struct ocrdma_pbl {
+ void *va;
+ dma_addr_t pa;
+};
+
+struct ocrdma_queue_info {
+ void *va;
+ dma_addr_t dma;
+ u32 size;
+ u16 len;
+ u16 entry_size; /* Size of an element in the queue */
+ u16 id; /* qid, where to ring the doorbell. */
+ u16 head, tail;
+ bool created;
+ atomic_t used; /* Number of valid elements in the queue */
+};
+
+struct ocrdma_eq {
+ struct ocrdma_queue_info q;
+ u32 vector;
+ int cq_cnt;
+ struct ocrdma_dev *dev;
+ char irq_name[32];
+};
+
+struct ocrdma_mq {
+ struct ocrdma_queue_info sq;
+ struct ocrdma_queue_info cq;
+ bool rearm_cq;
+};
+
+struct mqe_ctx {
+ struct mutex lock; /* for serializing mailbox commands on MQ */
+ wait_queue_head_t cmd_wait;
+ u32 tag;
+ u16 cqe_status;
+ u16 ext_status;
+ bool cmd_done;
+};
+
+struct ocrdma_dev {
+ struct ib_device ibdev;
+ struct ocrdma_dev_attr attr;
+
+ struct mutex dev_lock; /* provides syncronise access to device data */
+ spinlock_t flush_q_lock ____cacheline_aligned;
+
+ struct ocrdma_cq **cq_tbl;
+ struct ocrdma_qp **qp_tbl;
+
+ struct ocrdma_eq meq;
+ struct ocrdma_eq *qp_eq_tbl;
+ int eq_cnt;
+ u16 base_eqid;
+ u16 max_eq;
+
+ union ib_gid *sgid_tbl;
+ /* provided synchronization to sgid table for
+ * updating gid entries triggered by notifier.
+ */
+ spinlock_t sgid_lock;
+
+ int gsi_qp_created;
+ struct ocrdma_cq *gsi_sqcq;
+ struct ocrdma_cq *gsi_rqcq;
+
+ struct {
+ struct ocrdma_av *va;
+ dma_addr_t pa;
+ u32 size;
+ u32 num_ah;
+ /* provide synchronization for av
+ * entry allocations.
+ */
+ spinlock_t lock;
+ u32 ahid;
+ struct ocrdma_pbl pbl;
+ } av_tbl;
+
+ void *mbx_cmd;
+ struct ocrdma_mq mq;
+ struct mqe_ctx mqe_ctx;
+
+ struct be_dev_info nic_info;
+
+ struct list_head entry;
+ struct rcu_head rcu;
+ int id;
+};
+
+struct ocrdma_cq {
+ struct ib_cq ibcq;
+ struct ocrdma_dev *dev;
+ struct ocrdma_cqe *va;
+ u32 phase;
+ u32 getp; /* pointer to pending wrs to
+ * return to stack, wrap arounds
+ * at max_hw_cqe
+ */
+ u32 max_hw_cqe;
+ bool phase_change;
+ bool armed, solicited;
+ bool arm_needed;
+
+ spinlock_t cq_lock ____cacheline_aligned; /* provide synchronization
+ * to cq polling
+ */
+ /* syncronizes cq completion handler invoked from multiple context */
+ spinlock_t comp_handler_lock ____cacheline_aligned;
+ u16 id;
+ u16 eqn;
+
+ struct ocrdma_ucontext *ucontext;
+ dma_addr_t pa;
+ u32 len;
+ atomic_t use_cnt;
+
+ /* head of all qp's sq and rq for which cqes need to be flushed
+ * by the software.
+ */
+ struct list_head sq_head, rq_head;
+};
+
+struct ocrdma_pd {
+ struct ib_pd ibpd;
+ struct ocrdma_dev *dev;
+ struct ocrdma_ucontext *uctx;
+ atomic_t use_cnt;
+ u32 id;
+ int num_dpp_qp;
+ u32 dpp_page;
+ bool dpp_enabled;
+};
+
+struct ocrdma_ah {
+ struct ib_ah ibah;
+ struct ocrdma_dev *dev;
+ struct ocrdma_av *av;
+ u16 sgid_index;
+ u32 id;
+};
+
+struct ocrdma_qp_hwq_info {
+ u8 *va; /* virtual address */
+ u32 max_sges;
+ u32 head, tail;
+ u32 entry_size;
+ u32 max_cnt;
+ u32 max_wqe_idx;
+ u32 free_delta;
+ u16 dbid; /* qid, where to ring the doorbell. */
+ u32 len;
+ dma_addr_t pa;
+};
+
+struct ocrdma_srq {
+ struct ib_srq ibsrq;
+ struct ocrdma_dev *dev;
+ u8 __iomem *db;
+ /* provide synchronization to multiple context(s) posting rqe */
+ spinlock_t q_lock ____cacheline_aligned;
+
+ struct ocrdma_qp_hwq_info rq;
+ struct ocrdma_pd *pd;
+ atomic_t use_cnt;
+ u32 id;
+ u64 *rqe_wr_id_tbl;
+ u32 *idx_bit_fields;
+ u32 bit_fields_len;
+};
+
+struct ocrdma_qp {
+ struct ib_qp ibqp;
+ struct ocrdma_dev *dev;
+
+ u8 __iomem *sq_db;
+ /* provide synchronization to multiple context(s) posting wqe, rqe */
+ spinlock_t q_lock ____cacheline_aligned;
+ struct ocrdma_qp_hwq_info sq;
+ struct {
+ uint64_t wrid;
+ uint16_t dpp_wqe_idx;
+ uint16_t dpp_wqe;
+ uint8_t signaled;
+ uint8_t rsvd[3];
+ } *wqe_wr_id_tbl;
+ u32 max_inline_data;
+ struct ocrdma_cq *sq_cq;
+ /* list maintained per CQ to flush SQ errors */
+ struct list_head sq_entry;
+
+ u8 __iomem *rq_db;
+ struct ocrdma_qp_hwq_info rq;
+ u64 *rqe_wr_id_tbl;
+ struct ocrdma_cq *rq_cq;
+ struct ocrdma_srq *srq;
+ /* list maintained per CQ to flush RQ errors */
+ struct list_head rq_entry;
+
+ enum ocrdma_qp_state state; /* QP state */
+ int cap_flags;
+ u32 max_ord, max_ird;
+
+ u32 id;
+ struct ocrdma_pd *pd;
+
+ enum ib_qp_type qp_type;
+
+ int sgid_idx;
+ u32 qkey;
+ bool dpp_enabled;
+ u8 *ird_q_va;
+};
+
+#define OCRDMA_GET_NUM_POSTED_SHIFT_VAL(qp) \
+ (((qp->dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) && \
+ (qp->id < 64)) ? 24 : 16)
+
+struct ocrdma_hw_mr {
+ struct ocrdma_dev *dev;
+ u32 lkey;
+ u8 fr_mr;
+ u8 remote_atomic;
+ u8 remote_rd;
+ u8 remote_wr;
+ u8 local_rd;
+ u8 local_wr;
+ u8 mw_bind;
+ u8 rsvd;
+ u64 len;
+ struct ocrdma_pbl *pbl_table;
+ u32 num_pbls;
+ u32 num_pbes;
+ u32 pbl_size;
+ u32 pbe_size;
+ u64 fbo;
+ u64 va;
+};
+
+struct ocrdma_mr {
+ struct ib_mr ibmr;
+ struct ib_umem *umem;
+ struct ocrdma_hw_mr hwmr;
+ struct ocrdma_pd *pd;
+};
+
+struct ocrdma_ucontext {
+ struct ib_ucontext ibucontext;
+ struct ocrdma_dev *dev;
+
+ struct list_head mm_head;
+ struct mutex mm_list_lock; /* protects list entries of mm type */
+ struct {
+ u32 *va;
+ dma_addr_t pa;
+ u32 len;
+ } ah_tbl;
+};
+
+struct ocrdma_mm {
+ struct {
+ u64 phy_addr;
+ unsigned long len;
+ } key;
+ struct list_head entry;
+};
+
+static inline struct ocrdma_dev *get_ocrdma_dev(struct ib_device *ibdev)
+{
+ return container_of(ibdev, struct ocrdma_dev, ibdev);
+}
+
+static inline struct ocrdma_ucontext *get_ocrdma_ucontext(struct ib_ucontext
+ *ibucontext)
+{
+ return container_of(ibucontext, struct ocrdma_ucontext, ibucontext);
+}
+
+static inline struct ocrdma_pd *get_ocrdma_pd(struct ib_pd *ibpd)
+{
+ return container_of(ibpd, struct ocrdma_pd, ibpd);
+}
+
+static inline struct ocrdma_cq *get_ocrdma_cq(struct ib_cq *ibcq)
+{
+ return container_of(ibcq, struct ocrdma_cq, ibcq);
+}
+
+static inline struct ocrdma_qp *get_ocrdma_qp(struct ib_qp *ibqp)
+{
+ return container_of(ibqp, struct ocrdma_qp, ibqp);
+}
+
+static inline struct ocrdma_mr *get_ocrdma_mr(struct ib_mr *ibmr)
+{
+ return container_of(ibmr, struct ocrdma_mr, ibmr);
+}
+
+static inline struct ocrdma_ah *get_ocrdma_ah(struct ib_ah *ibah)
+{
+ return container_of(ibah, struct ocrdma_ah, ibah);
+}
+
+static inline struct ocrdma_srq *get_ocrdma_srq(struct ib_srq *ibsrq)
+{
+ return container_of(ibsrq, struct ocrdma_srq, ibsrq);
+}
+
+#endif
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_abi.h b/drivers/infiniband/hw/ocrdma/ocrdma_abi.h
new file mode 100644
index 000000000000..a411a4e3193d
--- /dev/null
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_abi.h
@@ -0,0 +1,134 @@
+/*******************************************************************
+ * This file is part of the Emulex RoCE Device Driver for *
+ * RoCE (RDMA over Converged Ethernet) adapters. *
+ * Copyright (C) 2008-2012 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.emulex.com *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of version 2 of the GNU General *
+ * Public License as published by the Free Software Foundation. *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID. See the GNU General Public License for *
+ * more details, a copy of which can be found in the file COPYING *
+ * included with this package. *
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ *******************************************************************/
+
+#ifndef __OCRDMA_ABI_H__
+#define __OCRDMA_ABI_H__
+
+struct ocrdma_alloc_ucontext_resp {
+ u32 dev_id;
+ u32 wqe_size;
+ u32 max_inline_data;
+ u32 dpp_wqe_size;
+ u64 ah_tbl_page;
+ u32 ah_tbl_len;
+ u32 rsvd;
+ u8 fw_ver[32];
+ u32 rqe_size;
+ u64 rsvd1;
+} __packed;
+
+/* user kernel communication data structures. */
+struct ocrdma_alloc_pd_ureq {
+ u64 rsvd1;
+} __packed;
+
+struct ocrdma_alloc_pd_uresp {
+ u32 id;
+ u32 dpp_enabled;
+ u32 dpp_page_addr_hi;
+ u32 dpp_page_addr_lo;
+ u64 rsvd1;
+} __packed;
+
+struct ocrdma_create_cq_ureq {
+ u32 dpp_cq;
+ u32 rsvd;
+} __packed;
+
+#define MAX_CQ_PAGES 8
+struct ocrdma_create_cq_uresp {
+ u32 cq_id;
+ u32 page_size;
+ u32 num_pages;
+ u32 max_hw_cqe;
+ u64 page_addr[MAX_CQ_PAGES];
+ u64 db_page_addr;
+ u32 db_page_size;
+ u32 phase_change;
+ u64 rsvd1;
+ u64 rsvd2;
+} __packed;
+
+#define MAX_QP_PAGES 8
+#define MAX_UD_AV_PAGES 8
+
+struct ocrdma_create_qp_ureq {
+ u8 enable_dpp_cq;
+ u8 rsvd;
+ u16 dpp_cq_id;
+ u32 rsvd1;
+};
+
+struct ocrdma_create_qp_uresp {
+ u16 qp_id;
+ u16 sq_dbid;
+ u16 rq_dbid;
+ u16 resv0;
+ u32 sq_page_size;
+ u32 rq_page_size;
+ u32 num_sq_pages;
+ u32 num_rq_pages;
+ u64 sq_page_addr[MAX_QP_PAGES];
+ u64 rq_page_addr[MAX_QP_PAGES];
+ u64 db_page_addr;
+ u32 db_page_size;
+ u32 dpp_credit;
+ u32 dpp_offset;
+ u32 rsvd1;
+ u32 num_wqe_allocated;
+ u32 num_rqe_allocated;
+ u32 free_wqe_delta;
+ u32 free_rqe_delta;
+ u32 db_sq_offset;
+ u32 db_rq_offset;
+ u32 db_shift;
+ u64 rsvd2;
+ u64 rsvd3;
+} __packed;
+
+struct ocrdma_create_srq_uresp {
+ u16 rq_dbid;
+ u16 resv0;
+ u32 resv1;
+
+ u32 rq_page_size;
+ u32 num_rq_pages;
+
+ u64 rq_page_addr[MAX_QP_PAGES];
+ u64 db_page_addr;
+
+ u32 db_page_size;
+ u32 num_rqe_allocated;
+ u32 db_rq_offset;
+ u32 db_shift;
+
+ u32 free_rqe_delta;
+ u32 rsvd2;
+ u64 rsvd3;
+} __packed;
+
+#endif /* __OCRDMA_ABI_H__ */
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
new file mode 100644
index 000000000000..a877a8ed7907
--- /dev/null
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
@@ -0,0 +1,172 @@
+/*******************************************************************
+ * This file is part of the Emulex RoCE Device Driver for *
+ * RoCE (RDMA over Converged Ethernet) adapters. *
+ * Copyright (C) 2008-2012 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.emulex.com *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of version 2 of the GNU General *
+ * Public License as published by the Free Software Foundation. *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID. See the GNU General Public License for *
+ * more details, a copy of which can be found in the file COPYING *
+ * included with this package. *
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ *******************************************************************/
+
+#include <net/neighbour.h>
+#include <net/netevent.h>
+
+#include <rdma/ib_addr.h>
+#include <rdma/ib_cache.h>
+
+#include "ocrdma.h"
+#include "ocrdma_verbs.h"
+#include "ocrdma_ah.h"
+#include "ocrdma_hw.h"
+
+static inline int set_av_attr(struct ocrdma_ah *ah,
+ struct ib_ah_attr *attr, int pdid)
+{
+ int status = 0;
+ u16 vlan_tag; bool vlan_enabled = false;
+ struct ocrdma_dev *dev = ah->dev;
+ struct ocrdma_eth_vlan eth;
+ struct ocrdma_grh grh;
+ int eth_sz;
+
+ memset(&eth, 0, sizeof(eth));
+ memset(&grh, 0, sizeof(grh));
+
+ ah->sgid_index = attr->grh.sgid_index;
+
+ vlan_tag = rdma_get_vlan_id(&attr->grh.dgid);
+ if (vlan_tag && (vlan_tag < 0x1000)) {
+ eth.eth_type = cpu_to_be16(0x8100);
+ eth.roce_eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE);
+ vlan_tag |= (attr->sl & 7) << 13;
+ eth.vlan_tag = cpu_to_be16(vlan_tag);
+ eth_sz = sizeof(struct ocrdma_eth_vlan);
+ vlan_enabled = true;
+ } else {
+ eth.eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE);
+ eth_sz = sizeof(struct ocrdma_eth_basic);
+ }
+ memcpy(&eth.smac[0], &dev->nic_info.mac_addr[0], ETH_ALEN);
+ status = ocrdma_resolve_dgid(dev, &attr->grh.dgid, &eth.dmac[0]);
+ if (status)
+ return status;
+ status = ocrdma_query_gid(&dev->ibdev, 1, attr->grh.sgid_index,
+ (union ib_gid *)&grh.sgid[0]);
+ if (status)
+ return status;
+
+ grh.tclass_flow = cpu_to_be32((6 << 28) |
+ (attr->grh.traffic_class << 24) |
+ attr->grh.flow_label);
+ /* 0x1b is next header value in GRH */
+ grh.pdid_hoplimit = cpu_to_be32((pdid << 16) |
+ (0x1b << 8) | attr->grh.hop_limit);
+
+ memcpy(&grh.dgid[0], attr->grh.dgid.raw, sizeof(attr->grh.dgid.raw));
+ memcpy(&ah->av->eth_hdr, &eth, eth_sz);
+ memcpy((u8 *)ah->av + eth_sz, &grh, sizeof(struct ocrdma_grh));
+ if (vlan_enabled)
+ ah->av->valid |= OCRDMA_AV_VLAN_VALID;
+ return status;
+}
+
+struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
+{
+ u32 *ahid_addr;
+ int status;
+ struct ocrdma_ah *ah;
+ struct ocrdma_pd *pd = get_ocrdma_pd(ibpd);
+ struct ocrdma_dev *dev = pd->dev;
+
+ if (!(attr->ah_flags & IB_AH_GRH))
+ return ERR_PTR(-EINVAL);
+
+ ah = kzalloc(sizeof *ah, GFP_ATOMIC);
+ if (!ah)
+ return ERR_PTR(-ENOMEM);
+ ah->dev = pd->dev;
+
+ status = ocrdma_alloc_av(dev, ah);
+ if (status)
+ goto av_err;
+ status = set_av_attr(ah, attr, pd->id);
+ if (status)
+ goto av_conf_err;
+
+ /* if pd is for the user process, pass the ah_id to user space */
+ if ((pd->uctx) && (pd->uctx->ah_tbl.va)) {
+ ahid_addr = pd->uctx->ah_tbl.va + attr->dlid;
+ *ahid_addr = ah->id;
+ }
+ return &ah->ibah;
+
+av_conf_err:
+ ocrdma_free_av(dev, ah);
+av_err:
+ kfree(ah);
+ return ERR_PTR(status);
+}
+
+int ocrdma_destroy_ah(struct ib_ah *ibah)
+{
+ struct ocrdma_ah *ah = get_ocrdma_ah(ibah);
+ ocrdma_free_av(ah->dev, ah);
+ kfree(ah);
+ return 0;
+}
+
+int ocrdma_query_ah(struct ib_ah *ibah, struct ib_ah_attr *attr)
+{
+ struct ocrdma_ah *ah = get_ocrdma_ah(ibah);
+ struct ocrdma_av *av = ah->av;
+ struct ocrdma_grh *grh;
+ attr->ah_flags |= IB_AH_GRH;
+ if (ah->av->valid & Bit(1)) {
+ grh = (struct ocrdma_grh *)((u8 *)ah->av +
+ sizeof(struct ocrdma_eth_vlan));
+ attr->sl = be16_to_cpu(av->eth_hdr.vlan_tag) >> 13;
+ } else {
+ grh = (struct ocrdma_grh *)((u8 *)ah->av +
+ sizeof(struct ocrdma_eth_basic));
+ attr->sl = 0;
+ }
+ memcpy(&attr->grh.dgid.raw[0], &grh->dgid[0], sizeof(grh->dgid));
+ attr->grh.sgid_index = ah->sgid_index;
+ attr->grh.hop_limit = be32_to_cpu(grh->pdid_hoplimit) & 0xff;
+ attr->grh.traffic_class = be32_to_cpu(grh->tclass_flow) >> 24;
+ attr->grh.flow_label = be32_to_cpu(grh->tclass_flow) & 0x00ffffffff;
+ return 0;
+}
+
+int ocrdma_modify_ah(struct ib_ah *ibah, struct ib_ah_attr *attr)
+{
+ /* modify_ah is unsupported */
+ return -ENOSYS;
+}
+
+int ocrdma_process_mad(struct ib_device *ibdev,
+ int process_mad_flags,
+ u8 port_num,
+ struct ib_wc *in_wc,
+ struct ib_grh *in_grh,
+ struct ib_mad *in_mad, struct ib_mad *out_mad)
+{
+ return IB_MAD_RESULT_SUCCESS;
+}
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.h b/drivers/infiniband/hw/ocrdma/ocrdma_ah.h
new file mode 100644
index 000000000000..8ac49e7f96d1
--- /dev/null
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.h
@@ -0,0 +1,42 @@
+/*******************************************************************
+ * This file is part of the Emulex RoCE Device Driver for *
+ * RoCE (RDMA over Converged Ethernet) adapters. *
+ * Copyright (C) 2008-2012 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.emulex.com *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of version 2 of the GNU General *
+ * Public License as published by the Free Software Foundation. *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID. See the GNU General Public License for *
+ * more details, a copy of which can be found in the file COPYING *
+ * included with this package. *
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ *******************************************************************/
+
+#ifndef __OCRDMA_AH_H__
+#define __OCRDMA_AH_H__
+
+struct ib_ah *ocrdma_create_ah(struct ib_pd *, struct ib_ah_attr *);
+int ocrdma_destroy_ah(struct ib_ah *);
+int ocrdma_query_ah(struct ib_ah *, struct ib_ah_attr *);
+int ocrdma_modify_ah(struct ib_ah *, struct ib_ah_attr *);
+
+int ocrdma_process_mad(struct ib_device *,
+ int process_mad_flags,
+ u8 port_num,
+ struct ib_wc *in_wc,
+ struct ib_grh *in_grh,
+ struct ib_mad *in_mad, struct ib_mad *out_mad);
+#endif /* __OCRDMA_AH_H__ */
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
new file mode 100644
index 000000000000..9b204b1ba336
--- /dev/null
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
@@ -0,0 +1,2640 @@
+/*******************************************************************
+ * This file is part of the Emulex RoCE Device Driver for *
+ * RoCE (RDMA over Converged Ethernet) CNA Adapters. *
+ * Copyright (C) 2008-2012 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.emulex.com *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of version 2 of the GNU General *
+ * Public License as published by the Free Software Foundation. *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID. See the GNU General Public License for *
+ * more details, a copy of which can be found in the file COPYING *
+ * included with this package. *
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ *******************************************************************/
+
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/log2.h>
+#include <linux/dma-mapping.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_addr.h>
+
+#include "ocrdma.h"
+#include "ocrdma_hw.h"
+#include "ocrdma_verbs.h"
+#include "ocrdma_ah.h"
+
+enum mbx_status {
+ OCRDMA_MBX_STATUS_FAILED = 1,
+ OCRDMA_MBX_STATUS_ILLEGAL_FIELD = 3,
+ OCRDMA_MBX_STATUS_OOR = 100,
+ OCRDMA_MBX_STATUS_INVALID_PD = 101,
+ OCRDMA_MBX_STATUS_PD_INUSE = 102,
+ OCRDMA_MBX_STATUS_INVALID_CQ = 103,
+ OCRDMA_MBX_STATUS_INVALID_QP = 104,
+ OCRDMA_MBX_STATUS_INVALID_LKEY = 105,
+ OCRDMA_MBX_STATUS_ORD_EXCEEDS = 106,
+ OCRDMA_MBX_STATUS_IRD_EXCEEDS = 107,
+ OCRDMA_MBX_STATUS_SENDQ_WQE_EXCEEDS = 108,
+ OCRDMA_MBX_STATUS_RECVQ_RQE_EXCEEDS = 109,
+ OCRDMA_MBX_STATUS_SGE_SEND_EXCEEDS = 110,
+ OCRDMA_MBX_STATUS_SGE_WRITE_EXCEEDS = 111,
+ OCRDMA_MBX_STATUS_SGE_RECV_EXCEEDS = 112,
+ OCRDMA_MBX_STATUS_INVALID_STATE_CHANGE = 113,
+ OCRDMA_MBX_STATUS_MW_BOUND = 114,
+ OCRDMA_MBX_STATUS_INVALID_VA = 115,
+ OCRDMA_MBX_STATUS_INVALID_LENGTH = 116,
+ OCRDMA_MBX_STATUS_INVALID_FBO = 117,
+ OCRDMA_MBX_STATUS_INVALID_ACC_RIGHTS = 118,
+ OCRDMA_MBX_STATUS_INVALID_PBE_SIZE = 119,
+ OCRDMA_MBX_STATUS_INVALID_PBL_ENTRY = 120,
+ OCRDMA_MBX_STATUS_INVALID_PBL_SHIFT = 121,
+ OCRDMA_MBX_STATUS_INVALID_SRQ_ID = 129,
+ OCRDMA_MBX_STATUS_SRQ_ERROR = 133,
+ OCRDMA_MBX_STATUS_RQE_EXCEEDS = 134,
+ OCRDMA_MBX_STATUS_MTU_EXCEEDS = 135,
+ OCRDMA_MBX_STATUS_MAX_QP_EXCEEDS = 136,
+ OCRDMA_MBX_STATUS_SRQ_LIMIT_EXCEEDS = 137,
+ OCRDMA_MBX_STATUS_SRQ_SIZE_UNDERUNS = 138,
+ OCRDMA_MBX_STATUS_QP_BOUND = 130,
+ OCRDMA_MBX_STATUS_INVALID_CHANGE = 139,
+ OCRDMA_MBX_STATUS_ATOMIC_OPS_UNSUP = 140,
+ OCRDMA_MBX_STATUS_INVALID_RNR_NAK_TIMER = 141,
+ OCRDMA_MBX_STATUS_MW_STILL_BOUND = 142,
+ OCRDMA_MBX_STATUS_PKEY_INDEX_INVALID = 143,
+ OCRDMA_MBX_STATUS_PKEY_INDEX_EXCEEDS = 144
+};
+
+enum additional_status {
+ OCRDMA_MBX_ADDI_STATUS_INSUFFICIENT_RESOURCES = 22
+};
+
+enum cqe_status {
+ OCRDMA_MBX_CQE_STATUS_INSUFFICIENT_PRIVILEDGES = 1,
+ OCRDMA_MBX_CQE_STATUS_INVALID_PARAMETER = 2,
+ OCRDMA_MBX_CQE_STATUS_INSUFFICIENT_RESOURCES = 3,
+ OCRDMA_MBX_CQE_STATUS_QUEUE_FLUSHING = 4,
+ OCRDMA_MBX_CQE_STATUS_DMA_FAILED = 5
+};
+
+static inline void *ocrdma_get_eqe(struct ocrdma_eq *eq)
+{
+ return (u8 *)eq->q.va + (eq->q.tail * sizeof(struct ocrdma_eqe));
+}
+
+static inline void ocrdma_eq_inc_tail(struct ocrdma_eq *eq)
+{
+ eq->q.tail = (eq->q.tail + 1) & (OCRDMA_EQ_LEN - 1);
+}
+
+static inline void *ocrdma_get_mcqe(struct ocrdma_dev *dev)
+{
+ struct ocrdma_mcqe *cqe = (struct ocrdma_mcqe *)
+ ((u8 *) dev->mq.cq.va +
+ (dev->mq.cq.tail * sizeof(struct ocrdma_mcqe)));
+
+ if (!(le32_to_cpu(cqe->valid_ae_cmpl_cons) & OCRDMA_MCQE_VALID_MASK))
+ return NULL;
+ return cqe;
+}
+
+static inline void ocrdma_mcq_inc_tail(struct ocrdma_dev *dev)
+{
+ dev->mq.cq.tail = (dev->mq.cq.tail + 1) & (OCRDMA_MQ_CQ_LEN - 1);
+}
+
+static inline struct ocrdma_mqe *ocrdma_get_mqe(struct ocrdma_dev *dev)
+{
+ return (struct ocrdma_mqe *)((u8 *) dev->mq.sq.va +
+ (dev->mq.sq.head *
+ sizeof(struct ocrdma_mqe)));
+}
+
+static inline void ocrdma_mq_inc_head(struct ocrdma_dev *dev)
+{
+ dev->mq.sq.head = (dev->mq.sq.head + 1) & (OCRDMA_MQ_LEN - 1);
+ atomic_inc(&dev->mq.sq.used);
+}
+
+static inline void *ocrdma_get_mqe_rsp(struct ocrdma_dev *dev)
+{
+ return (void *)((u8 *) dev->mq.sq.va +
+ (dev->mqe_ctx.tag * sizeof(struct ocrdma_mqe)));
+}
+
+enum ib_qp_state get_ibqp_state(enum ocrdma_qp_state qps)
+{
+ switch (qps) {
+ case OCRDMA_QPS_RST:
+ return IB_QPS_RESET;
+ case OCRDMA_QPS_INIT:
+ return IB_QPS_INIT;
+ case OCRDMA_QPS_RTR:
+ return IB_QPS_RTR;
+ case OCRDMA_QPS_RTS:
+ return IB_QPS_RTS;
+ case OCRDMA_QPS_SQD:
+ case OCRDMA_QPS_SQ_DRAINING:
+ return IB_QPS_SQD;
+ case OCRDMA_QPS_SQE:
+ return IB_QPS_SQE;
+ case OCRDMA_QPS_ERR:
+ return IB_QPS_ERR;
+ };
+ return IB_QPS_ERR;
+}
+
+static enum ocrdma_qp_state get_ocrdma_qp_state(enum ib_qp_state qps)
+{
+ switch (qps) {
+ case IB_QPS_RESET:
+ return OCRDMA_QPS_RST;
+ case IB_QPS_INIT:
+ return OCRDMA_QPS_INIT;
+ case IB_QPS_RTR:
+ return OCRDMA_QPS_RTR;
+ case IB_QPS_RTS:
+ return OCRDMA_QPS_RTS;
+ case IB_QPS_SQD:
+ return OCRDMA_QPS_SQD;
+ case IB_QPS_SQE:
+ return OCRDMA_QPS_SQE;
+ case IB_QPS_ERR:
+ return OCRDMA_QPS_ERR;
+ };
+ return OCRDMA_QPS_ERR;
+}
+
+static int ocrdma_get_mbx_errno(u32 status)
+{
+ int err_num = -EFAULT;
+ u8 mbox_status = (status & OCRDMA_MBX_RSP_STATUS_MASK) >>
+ OCRDMA_MBX_RSP_STATUS_SHIFT;
+ u8 add_status = (status & OCRDMA_MBX_RSP_ASTATUS_MASK) >>
+ OCRDMA_MBX_RSP_ASTATUS_SHIFT;
+
+ switch (mbox_status) {
+ case OCRDMA_MBX_STATUS_OOR:
+ case OCRDMA_MBX_STATUS_MAX_QP_EXCEEDS:
+ err_num = -EAGAIN;
+ break;
+
+ case OCRDMA_MBX_STATUS_INVALID_PD:
+ case OCRDMA_MBX_STATUS_INVALID_CQ:
+ case OCRDMA_MBX_STATUS_INVALID_SRQ_ID:
+ case OCRDMA_MBX_STATUS_INVALID_QP:
+ case OCRDMA_MBX_STATUS_INVALID_CHANGE:
+ case OCRDMA_MBX_STATUS_MTU_EXCEEDS:
+ case OCRDMA_MBX_STATUS_INVALID_RNR_NAK_TIMER:
+ case OCRDMA_MBX_STATUS_PKEY_INDEX_INVALID:
+ case OCRDMA_MBX_STATUS_PKEY_INDEX_EXCEEDS:
+ case OCRDMA_MBX_STATUS_ILLEGAL_FIELD:
+ case OCRDMA_MBX_STATUS_INVALID_PBL_ENTRY:
+ case OCRDMA_MBX_STATUS_INVALID_LKEY:
+ case OCRDMA_MBX_STATUS_INVALID_VA:
+ case OCRDMA_MBX_STATUS_INVALID_LENGTH:
+ case OCRDMA_MBX_STATUS_INVALID_FBO:
+ case OCRDMA_MBX_STATUS_INVALID_ACC_RIGHTS:
+ case OCRDMA_MBX_STATUS_INVALID_PBE_SIZE:
+ case OCRDMA_MBX_STATUS_ATOMIC_OPS_UNSUP:
+ case OCRDMA_MBX_STATUS_SRQ_ERROR:
+ case OCRDMA_MBX_STATUS_SRQ_SIZE_UNDERUNS:
+ err_num = -EINVAL;
+ break;
+
+ case OCRDMA_MBX_STATUS_PD_INUSE:
+ case OCRDMA_MBX_STATUS_QP_BOUND:
+ case OCRDMA_MBX_STATUS_MW_STILL_BOUND:
+ case OCRDMA_MBX_STATUS_MW_BOUND:
+ err_num = -EBUSY;
+ break;
+
+ case OCRDMA_MBX_STATUS_RECVQ_RQE_EXCEEDS:
+ case OCRDMA_MBX_STATUS_SGE_RECV_EXCEEDS:
+ case OCRDMA_MBX_STATUS_RQE_EXCEEDS:
+ case OCRDMA_MBX_STATUS_SRQ_LIMIT_EXCEEDS:
+ case OCRDMA_MBX_STATUS_ORD_EXCEEDS:
+ case OCRDMA_MBX_STATUS_IRD_EXCEEDS:
+ case OCRDMA_MBX_STATUS_SENDQ_WQE_EXCEEDS:
+ case OCRDMA_MBX_STATUS_SGE_SEND_EXCEEDS:
+ case OCRDMA_MBX_STATUS_SGE_WRITE_EXCEEDS:
+ err_num = -ENOBUFS;
+ break;
+
+ case OCRDMA_MBX_STATUS_FAILED:
+ switch (add_status) {
+ case OCRDMA_MBX_ADDI_STATUS_INSUFFICIENT_RESOURCES:
+ err_num = -EAGAIN;
+ break;
+ }
+ default:
+ err_num = -EFAULT;
+ }
+ return err_num;
+}
+
+static int ocrdma_get_mbx_cqe_errno(u16 cqe_status)
+{
+ int err_num = -EINVAL;
+
+ switch (cqe_status) {
+ case OCRDMA_MBX_CQE_STATUS_INSUFFICIENT_PRIVILEDGES:
+ err_num = -EPERM;
+ break;
+ case OCRDMA_MBX_CQE_STATUS_INVALID_PARAMETER:
+ err_num = -EINVAL;
+ break;
+ case OCRDMA_MBX_CQE_STATUS_INSUFFICIENT_RESOURCES:
+ case OCRDMA_MBX_CQE_STATUS_QUEUE_FLUSHING:
+ err_num = -EAGAIN;
+ break;
+ case OCRDMA_MBX_CQE_STATUS_DMA_FAILED:
+ err_num = -EIO;
+ break;
+ }
+ return err_num;
+}
+
+void ocrdma_ring_cq_db(struct ocrdma_dev *dev, u16 cq_id, bool armed,
+ bool solicited, u16 cqe_popped)
+{
+ u32 val = cq_id & OCRDMA_DB_CQ_RING_ID_MASK;
+
+ val |= ((cq_id & OCRDMA_DB_CQ_RING_ID_EXT_MASK) <<
+ OCRDMA_DB_CQ_RING_ID_EXT_MASK_SHIFT);
+
+ if (armed)
+ val |= (1 << OCRDMA_DB_CQ_REARM_SHIFT);
+ if (solicited)
+ val |= (1 << OCRDMA_DB_CQ_SOLICIT_SHIFT);
+ val |= (cqe_popped << OCRDMA_DB_CQ_NUM_POPPED_SHIFT);
+ iowrite32(val, dev->nic_info.db + OCRDMA_DB_CQ_OFFSET);
+}
+
+static void ocrdma_ring_mq_db(struct ocrdma_dev *dev)
+{
+ u32 val = 0;
+
+ val |= dev->mq.sq.id & OCRDMA_MQ_ID_MASK;
+ val |= 1 << OCRDMA_MQ_NUM_MQE_SHIFT;
+ iowrite32(val, dev->nic_info.db + OCRDMA_DB_MQ_OFFSET);
+}
+
+static void ocrdma_ring_eq_db(struct ocrdma_dev *dev, u16 eq_id,
+ bool arm, bool clear_int, u16 num_eqe)
+{
+ u32 val = 0;
+
+ val |= eq_id & OCRDMA_EQ_ID_MASK;
+ val |= ((eq_id & OCRDMA_EQ_ID_EXT_MASK) << OCRDMA_EQ_ID_EXT_MASK_SHIFT);
+ if (arm)
+ val |= (1 << OCRDMA_REARM_SHIFT);
+ if (clear_int)
+ val |= (1 << OCRDMA_EQ_CLR_SHIFT);
+ val |= (1 << OCRDMA_EQ_TYPE_SHIFT);
+ val |= (num_eqe << OCRDMA_NUM_EQE_SHIFT);
+ iowrite32(val, dev->nic_info.db + OCRDMA_DB_EQ_OFFSET);
+}
+
+static void ocrdma_init_mch(struct ocrdma_mbx_hdr *cmd_hdr,
+ u8 opcode, u8 subsys, u32 cmd_len)
+{
+ cmd_hdr->subsys_op = (opcode | (subsys << OCRDMA_MCH_SUBSYS_SHIFT));
+ cmd_hdr->timeout = 20; /* seconds */
+ cmd_hdr->cmd_len = cmd_len - sizeof(struct ocrdma_mbx_hdr);
+}
+
+static void *ocrdma_init_emb_mqe(u8 opcode, u32 cmd_len)
+{
+ struct ocrdma_mqe *mqe;
+
+ mqe = kzalloc(sizeof(struct ocrdma_mqe), GFP_KERNEL);
+ if (!mqe)
+ return NULL;
+ mqe->hdr.spcl_sge_cnt_emb |=
+ (OCRDMA_MQE_EMBEDDED << OCRDMA_MQE_HDR_EMB_SHIFT) &
+ OCRDMA_MQE_HDR_EMB_MASK;
+ mqe->hdr.pyld_len = cmd_len - sizeof(struct ocrdma_mqe_hdr);
+
+ ocrdma_init_mch(&mqe->u.emb_req.mch, opcode, OCRDMA_SUBSYS_ROCE,
+ mqe->hdr.pyld_len);
+ return mqe;
+}
+
+static void ocrdma_free_q(struct ocrdma_dev *dev, struct ocrdma_queue_info *q)
+{
+ dma_free_coherent(&dev->nic_info.pdev->dev, q->size, q->va, q->dma);
+}
+
+static int ocrdma_alloc_q(struct ocrdma_dev *dev,
+ struct ocrdma_queue_info *q, u16 len, u16 entry_size)
+{
+ memset(q, 0, sizeof(*q));
+ q->len = len;
+ q->entry_size = entry_size;
+ q->size = len * entry_size;
+ q->va = dma_alloc_coherent(&dev->nic_info.pdev->dev, q->size,
+ &q->dma, GFP_KERNEL);
+ if (!q->va)
+ return -ENOMEM;
+ memset(q->va, 0, q->size);
+ return 0;
+}
+
+static void ocrdma_build_q_pages(struct ocrdma_pa *q_pa, int cnt,
+ dma_addr_t host_pa, int hw_page_size)
+{
+ int i;
+
+ for (i = 0; i < cnt; i++) {
+ q_pa[i].lo = (u32) (host_pa & 0xffffffff);
+ q_pa[i].hi = (u32) upper_32_bits(host_pa);
+ host_pa += hw_page_size;
+ }
+}
+
+static void ocrdma_assign_eq_vect_gen2(struct ocrdma_dev *dev,
+ struct ocrdma_eq *eq)
+{
+ /* assign vector and update vector id for next EQ */
+ eq->vector = dev->nic_info.msix.start_vector;
+ dev->nic_info.msix.start_vector += 1;
+}
+
+static void ocrdma_free_eq_vect_gen2(struct ocrdma_dev *dev)
+{
+ /* this assumes that EQs are freed in exactly reverse order
+ * as its allocation.
+ */
+ dev->nic_info.msix.start_vector -= 1;
+}
+
+static int ocrdma_mbx_delete_q(struct ocrdma_dev *dev, struct ocrdma_queue_info *q,
+ int queue_type)
+{
+ u8 opcode = 0;
+ int status;
+ struct ocrdma_delete_q_req *cmd = dev->mbx_cmd;
+
+ switch (queue_type) {
+ case QTYPE_MCCQ:
+ opcode = OCRDMA_CMD_DELETE_MQ;
+ break;
+ case QTYPE_CQ:
+ opcode = OCRDMA_CMD_DELETE_CQ;
+ break;
+ case QTYPE_EQ:
+ opcode = OCRDMA_CMD_DELETE_EQ;
+ break;
+ default:
+ BUG();
+ }
+ memset(cmd, 0, sizeof(*cmd));
+ ocrdma_init_mch(&cmd->req, opcode, OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
+ cmd->id = q->id;
+
+ status = be_roce_mcc_cmd(dev->nic_info.netdev,
+ cmd, sizeof(*cmd), NULL, NULL);
+ if (!status)
+ q->created = false;
+ return status;
+}
+
+static int ocrdma_mbx_create_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
+{
+ int status;
+ struct ocrdma_create_eq_req *cmd = dev->mbx_cmd;
+ struct ocrdma_create_eq_rsp *rsp = dev->mbx_cmd;
+
+ memset(cmd, 0, sizeof(*cmd));
+ ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_EQ, OCRDMA_SUBSYS_COMMON,
+ sizeof(*cmd));
+ if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY)
+ cmd->req.rsvd_version = 0;
+ else
+ cmd->req.rsvd_version = 2;
+
+ cmd->num_pages = 4;
+ cmd->valid = OCRDMA_CREATE_EQ_VALID;
+ cmd->cnt = 4 << OCRDMA_CREATE_EQ_CNT_SHIFT;
+
+ ocrdma_build_q_pages(&cmd->pa[0], cmd->num_pages, eq->q.dma,
+ PAGE_SIZE_4K);
+ status = be_roce_mcc_cmd(dev->nic_info.netdev, cmd, sizeof(*cmd), NULL,
+ NULL);
+ if (!status) {
+ eq->q.id = rsp->vector_eqid & 0xffff;
+ if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY)
+ ocrdma_assign_eq_vect_gen2(dev, eq);
+ else {
+ eq->vector = (rsp->vector_eqid >> 16) & 0xffff;
+ dev->nic_info.msix.start_vector += 1;
+ }
+ eq->q.created = true;
+ }
+ return status;
+}
+
+static int ocrdma_create_eq(struct ocrdma_dev *dev,
+ struct ocrdma_eq *eq, u16 q_len)
+{
+ int status;
+
+ status = ocrdma_alloc_q(dev, &eq->q, OCRDMA_EQ_LEN,
+ sizeof(struct ocrdma_eqe));
+ if (status)
+ return status;
+
+ status = ocrdma_mbx_create_eq(dev, eq);
+ if (status)
+ goto mbx_err;
+ eq->dev = dev;
+ ocrdma_ring_eq_db(dev, eq->q.id, true, true, 0);
+
+ return 0;
+mbx_err:
+ ocrdma_free_q(dev, &eq->q);
+ return status;
+}
+
+static int ocrdma_get_irq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
+{
+ int irq;
+
+ if (dev->nic_info.intr_mode == BE_INTERRUPT_MODE_INTX)
+ irq = dev->nic_info.pdev->irq;
+ else
+ irq = dev->nic_info.msix.vector_list[eq->vector];
+ return irq;
+}
+
+static void _ocrdma_destroy_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
+{
+ if (eq->q.created) {
+ ocrdma_mbx_delete_q(dev, &eq->q, QTYPE_EQ);
+ if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY)
+ ocrdma_free_eq_vect_gen2(dev);
+ ocrdma_free_q(dev, &eq->q);
+ }
+}
+
+static void ocrdma_destroy_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
+{
+ int irq;
+
+ /* disarm EQ so that interrupts are not generated
+ * during freeing and EQ delete is in progress.
+ */
+ ocrdma_ring_eq_db(dev, eq->q.id, false, false, 0);
+
+ irq = ocrdma_get_irq(dev, eq);
+ free_irq(irq, eq);
+ _ocrdma_destroy_eq(dev, eq);
+}
+
+static void ocrdma_destroy_qp_eqs(struct ocrdma_dev *dev)
+{
+ int i;
+
+ /* deallocate the data path eqs */
+ for (i = 0; i < dev->eq_cnt; i++)
+ ocrdma_destroy_eq(dev, &dev->qp_eq_tbl[i]);
+}
+
+static int ocrdma_mbx_mq_cq_create(struct ocrdma_dev *dev,
+ struct ocrdma_queue_info *cq,
+ struct ocrdma_queue_info *eq)
+{
+ struct ocrdma_create_cq_cmd *cmd = dev->mbx_cmd;
+ struct ocrdma_create_cq_cmd_rsp *rsp = dev->mbx_cmd;
+ int status;
+
+ memset(cmd, 0, sizeof(*cmd));
+ ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_CQ,
+ OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
+
+ cmd->pgsz_pgcnt = PAGES_4K_SPANNED(cq->va, cq->size);
+ cmd->ev_cnt_flags = OCRDMA_CREATE_CQ_DEF_FLAGS;
+ cmd->eqn = (eq->id << OCRDMA_CREATE_CQ_EQID_SHIFT);
+
+ ocrdma_build_q_pages(&cmd->pa[0], cmd->pgsz_pgcnt,
+ cq->dma, PAGE_SIZE_4K);
+ status = be_roce_mcc_cmd(dev->nic_info.netdev,
+ cmd, sizeof(*cmd), NULL, NULL);
+ if (!status) {
+ cq->id = (rsp->cq_id & OCRDMA_CREATE_CQ_RSP_CQ_ID_MASK);
+ cq->created = true;
+ }
+ return status;
+}
+
+static u32 ocrdma_encoded_q_len(int q_len)
+{
+ u32 len_encoded = fls(q_len); /* log2(len) + 1 */
+
+ if (len_encoded == 16)
+ len_encoded = 0;
+ return len_encoded;
+}
+
+static int ocrdma_mbx_create_mq(struct ocrdma_dev *dev,
+ struct ocrdma_queue_info *mq,
+ struct ocrdma_queue_info *cq)
+{
+ int num_pages, status;
+ struct ocrdma_create_mq_req *cmd = dev->mbx_cmd;
+ struct ocrdma_create_mq_rsp *rsp = dev->mbx_cmd;
+ struct ocrdma_pa *pa;
+
+ memset(cmd, 0, sizeof(*cmd));
+ num_pages = PAGES_4K_SPANNED(mq->va, mq->size);
+
+ if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) {
+ ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_MQ,
+ OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
+ cmd->v0.pages = num_pages;
+ cmd->v0.async_cqid_valid = OCRDMA_CREATE_MQ_ASYNC_CQ_VALID;
+ cmd->v0.async_cqid_valid = (cq->id << 1);
+ cmd->v0.cqid_ringsize |= (ocrdma_encoded_q_len(mq->len) <<
+ OCRDMA_CREATE_MQ_RING_SIZE_SHIFT);
+ cmd->v0.cqid_ringsize |=
+ (cq->id << OCRDMA_CREATE_MQ_V0_CQ_ID_SHIFT);
+ cmd->v0.valid = OCRDMA_CREATE_MQ_VALID;
+ pa = &cmd->v0.pa[0];
+ } else {
+ ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_MQ_EXT,
+ OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
+ cmd->req.rsvd_version = 1;
+ cmd->v1.cqid_pages = num_pages;
+ cmd->v1.cqid_pages |= (cq->id << OCRDMA_CREATE_MQ_CQ_ID_SHIFT);
+ cmd->v1.async_cqid_valid = OCRDMA_CREATE_MQ_ASYNC_CQ_VALID;
+ cmd->v1.async_event_bitmap = Bit(20);
+ cmd->v1.async_cqid_ringsize = cq->id;
+ cmd->v1.async_cqid_ringsize |= (ocrdma_encoded_q_len(mq->len) <<
+ OCRDMA_CREATE_MQ_RING_SIZE_SHIFT);
+ cmd->v1.valid = OCRDMA_CREATE_MQ_VALID;
+ pa = &cmd->v1.pa[0];
+ }
+ ocrdma_build_q_pages(pa, num_pages, mq->dma, PAGE_SIZE_4K);
+ status = be_roce_mcc_cmd(dev->nic_info.netdev,
+ cmd, sizeof(*cmd), NULL, NULL);
+ if (!status) {
+ mq->id = rsp->id;
+ mq->created = true;
+ }
+ return status;
+}
+
+static int ocrdma_create_mq(struct ocrdma_dev *dev)
+{
+ int status;
+
+ /* Alloc completion queue for Mailbox queue */
+ status = ocrdma_alloc_q(dev, &dev->mq.cq, OCRDMA_MQ_CQ_LEN,
+ sizeof(struct ocrdma_mcqe));
+ if (status)
+ goto alloc_err;
+
+ status = ocrdma_mbx_mq_cq_create(dev, &dev->mq.cq, &dev->meq.q);
+ if (status)
+ goto mbx_cq_free;
+
+ memset(&dev->mqe_ctx, 0, sizeof(dev->mqe_ctx));
+ init_waitqueue_head(&dev->mqe_ctx.cmd_wait);
+ mutex_init(&dev->mqe_ctx.lock);
+
+ /* Alloc Mailbox queue */
+ status = ocrdma_alloc_q(dev, &dev->mq.sq, OCRDMA_MQ_LEN,
+ sizeof(struct ocrdma_mqe));
+ if (status)
+ goto mbx_cq_destroy;
+ status = ocrdma_mbx_create_mq(dev, &dev->mq.sq, &dev->mq.cq);
+ if (status)
+ goto mbx_q_free;
+ ocrdma_ring_cq_db(dev, dev->mq.cq.id, true, false, 0);
+ return 0;
+
+mbx_q_free:
+ ocrdma_free_q(dev, &dev->mq.sq);
+mbx_cq_destroy:
+ ocrdma_mbx_delete_q(dev, &dev->mq.cq, QTYPE_CQ);
+mbx_cq_free:
+ ocrdma_free_q(dev, &dev->mq.cq);
+alloc_err:
+ return status;
+}
+
+static void ocrdma_destroy_mq(struct ocrdma_dev *dev)
+{
+ struct ocrdma_queue_info *mbxq, *cq;
+
+ /* mqe_ctx lock synchronizes with any other pending cmds. */
+ mutex_lock(&dev->mqe_ctx.lock);
+ mbxq = &dev->mq.sq;
+ if (mbxq->created) {
+ ocrdma_mbx_delete_q(dev, mbxq, QTYPE_MCCQ);
+ ocrdma_free_q(dev, mbxq);
+ }
+ mutex_unlock(&dev->mqe_ctx.lock);
+
+ cq = &dev->mq.cq;
+ if (cq->created) {
+ ocrdma_mbx_delete_q(dev, cq, QTYPE_CQ);
+ ocrdma_free_q(dev, cq);
+ }
+}
+
+static void ocrdma_process_qpcat_error(struct ocrdma_dev *dev,
+ struct ocrdma_qp *qp)
+{
+ enum ib_qp_state new_ib_qps = IB_QPS_ERR;
+ enum ib_qp_state old_ib_qps;
+
+ if (qp == NULL)
+ BUG();
+ ocrdma_qp_state_machine(qp, new_ib_qps, &old_ib_qps);
+}
+
+static void ocrdma_dispatch_ibevent(struct ocrdma_dev *dev,
+ struct ocrdma_ae_mcqe *cqe)
+{
+ struct ocrdma_qp *qp = NULL;
+ struct ocrdma_cq *cq = NULL;
+ struct ib_event ib_evt;
+ int cq_event = 0;
+ int qp_event = 1;
+ int srq_event = 0;
+ int dev_event = 0;
+ int type = (cqe->valid_ae_event & OCRDMA_AE_MCQE_EVENT_TYPE_MASK) >>
+ OCRDMA_AE_MCQE_EVENT_TYPE_SHIFT;
+
+ if (cqe->qpvalid_qpid & OCRDMA_AE_MCQE_QPVALID)
+ qp = dev->qp_tbl[cqe->qpvalid_qpid & OCRDMA_AE_MCQE_QPID_MASK];
+ if (cqe->cqvalid_cqid & OCRDMA_AE_MCQE_CQVALID)
+ cq = dev->cq_tbl[cqe->cqvalid_cqid & OCRDMA_AE_MCQE_CQID_MASK];
+
+ ib_evt.device = &dev->ibdev;
+
+ switch (type) {
+ case OCRDMA_CQ_ERROR:
+ ib_evt.element.cq = &cq->ibcq;
+ ib_evt.event = IB_EVENT_CQ_ERR;
+ cq_event = 1;
+ qp_event = 0;
+ break;
+ case OCRDMA_CQ_OVERRUN_ERROR:
+ ib_evt.element.cq = &cq->ibcq;
+ ib_evt.event = IB_EVENT_CQ_ERR;
+ break;
+ case OCRDMA_CQ_QPCAT_ERROR:
+ ib_evt.element.qp = &qp->ibqp;
+ ib_evt.event = IB_EVENT_QP_FATAL;
+ ocrdma_process_qpcat_error(dev, qp);
+ break;
+ case OCRDMA_QP_ACCESS_ERROR:
+ ib_evt.element.qp = &qp->ibqp;
+ ib_evt.event = IB_EVENT_QP_ACCESS_ERR;
+ break;
+ case OCRDMA_QP_COMM_EST_EVENT:
+ ib_evt.element.qp = &qp->ibqp;
+ ib_evt.event = IB_EVENT_COMM_EST;
+ break;
+ case OCRDMA_SQ_DRAINED_EVENT:
+ ib_evt.element.qp = &qp->ibqp;
+ ib_evt.event = IB_EVENT_SQ_DRAINED;
+ break;
+ case OCRDMA_DEVICE_FATAL_EVENT:
+ ib_evt.element.port_num = 1;
+ ib_evt.event = IB_EVENT_DEVICE_FATAL;
+ qp_event = 0;
+ dev_event = 1;
+ break;
+ case OCRDMA_SRQCAT_ERROR:
+ ib_evt.element.srq = &qp->srq->ibsrq;
+ ib_evt.event = IB_EVENT_SRQ_ERR;
+ srq_event = 1;
+ qp_event = 0;
+ break;
+ case OCRDMA_SRQ_LIMIT_EVENT:
+ ib_evt.element.srq = &qp->srq->ibsrq;
+ ib_evt.event = IB_EVENT_QP_LAST_WQE_REACHED;
+ srq_event = 1;
+ qp_event = 0;
+ break;
+ case OCRDMA_QP_LAST_WQE_EVENT:
+ ib_evt.element.qp = &qp->ibqp;
+ ib_evt.event = IB_EVENT_QP_LAST_WQE_REACHED;
+ break;
+ default:
+ cq_event = 0;
+ qp_event = 0;
+ srq_event = 0;
+ dev_event = 0;
+ ocrdma_err("%s() unknown type=0x%x\n", __func__, type);
+ break;
+ }
+
+ if (qp_event) {
+ if (qp->ibqp.event_handler)
+ qp->ibqp.event_handler(&ib_evt, qp->ibqp.qp_context);
+ } else if (cq_event) {
+ if (cq->ibcq.event_handler)
+ cq->ibcq.event_handler(&ib_evt, cq->ibcq.cq_context);
+ } else if (srq_event) {
+ if (qp->srq->ibsrq.event_handler)
+ qp->srq->ibsrq.event_handler(&ib_evt,
+ qp->srq->ibsrq.
+ srq_context);
+ } else if (dev_event)
+ ib_dispatch_event(&ib_evt);
+
+}
+
+static void ocrdma_process_acqe(struct ocrdma_dev *dev, void *ae_cqe)
+{
+ /* async CQE processing */
+ struct ocrdma_ae_mcqe *cqe = ae_cqe;
+ u32 evt_code = (cqe->valid_ae_event & OCRDMA_AE_MCQE_EVENT_CODE_MASK) >>
+ OCRDMA_AE_MCQE_EVENT_CODE_SHIFT;
+
+ if (evt_code == OCRDMA_ASYNC_EVE_CODE)
+ ocrdma_dispatch_ibevent(dev, cqe);
+ else
+ ocrdma_err("%s(%d) invalid evt code=0x%x\n",
+ __func__, dev->id, evt_code);
+}
+
+static void ocrdma_process_mcqe(struct ocrdma_dev *dev, struct ocrdma_mcqe *cqe)
+{
+ if (dev->mqe_ctx.tag == cqe->tag_lo && dev->mqe_ctx.cmd_done == false) {
+ dev->mqe_ctx.cqe_status = (cqe->status &
+ OCRDMA_MCQE_STATUS_MASK) >> OCRDMA_MCQE_STATUS_SHIFT;
+ dev->mqe_ctx.ext_status =
+ (cqe->status & OCRDMA_MCQE_ESTATUS_MASK)
+ >> OCRDMA_MCQE_ESTATUS_SHIFT;
+ dev->mqe_ctx.cmd_done = true;
+ wake_up(&dev->mqe_ctx.cmd_wait);
+ } else
+ ocrdma_err("%s() cqe for invalid tag0x%x.expected=0x%x\n",
+ __func__, cqe->tag_lo, dev->mqe_ctx.tag);
+}
+
+static int ocrdma_mq_cq_handler(struct ocrdma_dev *dev, u16 cq_id)
+{
+ u16 cqe_popped = 0;
+ struct ocrdma_mcqe *cqe;
+
+ while (1) {
+ cqe = ocrdma_get_mcqe(dev);
+ if (cqe == NULL)
+ break;
+ ocrdma_le32_to_cpu(cqe, sizeof(*cqe));
+ cqe_popped += 1;
+ if (cqe->valid_ae_cmpl_cons & OCRDMA_MCQE_AE_MASK)
+ ocrdma_process_acqe(dev, cqe);
+ else if (cqe->valid_ae_cmpl_cons & OCRDMA_MCQE_CMPL_MASK)
+ ocrdma_process_mcqe(dev, cqe);
+ else
+ ocrdma_err("%s() cqe->compl is not set.\n", __func__);
+ memset(cqe, 0, sizeof(struct ocrdma_mcqe));
+ ocrdma_mcq_inc_tail(dev);
+ }
+ ocrdma_ring_cq_db(dev, dev->mq.cq.id, true, false, cqe_popped);
+ return 0;
+}
+
+static void ocrdma_qp_buddy_cq_handler(struct ocrdma_dev *dev,
+ struct ocrdma_cq *cq)
+{
+ unsigned long flags;
+ struct ocrdma_qp *qp;
+ bool buddy_cq_found = false;
+ /* Go through list of QPs in error state which are using this CQ
+ * and invoke its callback handler to trigger CQE processing for
+ * error/flushed CQE. It is rare to find more than few entries in
+ * this list as most consumers stops after getting error CQE.
+ * List is traversed only once when a matching buddy cq found for a QP.
+ */
+ spin_lock_irqsave(&dev->flush_q_lock, flags);
+ list_for_each_entry(qp, &cq->sq_head, sq_entry) {
+ if (qp->srq)
+ continue;
+ /* if wq and rq share the same cq, than comp_handler
+ * is already invoked.
+ */
+ if (qp->sq_cq == qp->rq_cq)
+ continue;
+ /* if completion came on sq, rq's cq is buddy cq.
+ * if completion came on rq, sq's cq is buddy cq.
+ */
+ if (qp->sq_cq == cq)
+ cq = qp->rq_cq;
+ else
+ cq = qp->sq_cq;
+ buddy_cq_found = true;
+ break;
+ }
+ spin_unlock_irqrestore(&dev->flush_q_lock, flags);
+ if (buddy_cq_found == false)
+ return;
+ if (cq->ibcq.comp_handler) {
+ spin_lock_irqsave(&cq->comp_handler_lock, flags);
+ (*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context);
+ spin_unlock_irqrestore(&cq->comp_handler_lock, flags);
+ }
+}
+
+static void ocrdma_qp_cq_handler(struct ocrdma_dev *dev, u16 cq_idx)
+{
+ unsigned long flags;
+ struct ocrdma_cq *cq;
+
+ if (cq_idx >= OCRDMA_MAX_CQ)
+ BUG();
+
+ cq = dev->cq_tbl[cq_idx];
+ if (cq == NULL) {
+ ocrdma_err("%s%d invalid id=0x%x\n", __func__, dev->id, cq_idx);
+ return;
+ }
+ spin_lock_irqsave(&cq->cq_lock, flags);
+ cq->armed = false;
+ cq->solicited = false;
+ spin_unlock_irqrestore(&cq->cq_lock, flags);
+
+ ocrdma_ring_cq_db(dev, cq->id, false, false, 0);
+
+ if (cq->ibcq.comp_handler) {
+ spin_lock_irqsave(&cq->comp_handler_lock, flags);
+ (*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context);
+ spin_unlock_irqrestore(&cq->comp_handler_lock, flags);
+ }
+ ocrdma_qp_buddy_cq_handler(dev, cq);
+}
+
+static void ocrdma_cq_handler(struct ocrdma_dev *dev, u16 cq_id)
+{
+ /* process the MQ-CQE. */
+ if (cq_id == dev->mq.cq.id)
+ ocrdma_mq_cq_handler(dev, cq_id);
+ else
+ ocrdma_qp_cq_handler(dev, cq_id);
+}
+
+static irqreturn_t ocrdma_irq_handler(int irq, void *handle)
+{
+ struct ocrdma_eq *eq = handle;
+ struct ocrdma_dev *dev = eq->dev;
+ struct ocrdma_eqe eqe;
+ struct ocrdma_eqe *ptr;
+ u16 eqe_popped = 0;
+ u16 cq_id;
+ while (1) {
+ ptr = ocrdma_get_eqe(eq);
+ eqe = *ptr;
+ ocrdma_le32_to_cpu(&eqe, sizeof(eqe));
+ if ((eqe.id_valid & OCRDMA_EQE_VALID_MASK) == 0)
+ break;
+ eqe_popped += 1;
+ ptr->id_valid = 0;
+ /* check whether its CQE or not. */
+ if ((eqe.id_valid & OCRDMA_EQE_FOR_CQE_MASK) == 0) {
+ cq_id = eqe.id_valid >> OCRDMA_EQE_RESOURCE_ID_SHIFT;
+ ocrdma_cq_handler(dev, cq_id);
+ }
+ ocrdma_eq_inc_tail(eq);
+ }
+ ocrdma_ring_eq_db(dev, eq->q.id, true, true, eqe_popped);
+ /* Ring EQ doorbell with num_popped to 0 to enable interrupts again. */
+ if (dev->nic_info.intr_mode == BE_INTERRUPT_MODE_INTX)
+ ocrdma_ring_eq_db(dev, eq->q.id, true, true, 0);
+ return IRQ_HANDLED;
+}
+
+static void ocrdma_post_mqe(struct ocrdma_dev *dev, struct ocrdma_mqe *cmd)
+{
+ struct ocrdma_mqe *mqe;
+
+ dev->mqe_ctx.tag = dev->mq.sq.head;
+ dev->mqe_ctx.cmd_done = false;
+ mqe = ocrdma_get_mqe(dev);
+ cmd->hdr.tag_lo = dev->mq.sq.head;
+ ocrdma_copy_cpu_to_le32(mqe, cmd, sizeof(*mqe));
+ /* make sure descriptor is written before ringing doorbell */
+ wmb();
+ ocrdma_mq_inc_head(dev);
+ ocrdma_ring_mq_db(dev);
+}
+
+static int ocrdma_wait_mqe_cmpl(struct ocrdma_dev *dev)
+{
+ long status;
+ /* 30 sec timeout */
+ status = wait_event_timeout(dev->mqe_ctx.cmd_wait,
+ (dev->mqe_ctx.cmd_done != false),
+ msecs_to_jiffies(30000));
+ if (status)
+ return 0;
+ else
+ return -1;
+}
+
+/* issue a mailbox command on the MQ */
+static int ocrdma_mbx_cmd(struct ocrdma_dev *dev, struct ocrdma_mqe *mqe)
+{
+ int status = 0;
+ u16 cqe_status, ext_status;
+ struct ocrdma_mqe *rsp;
+
+ mutex_lock(&dev->mqe_ctx.lock);
+ ocrdma_post_mqe(dev, mqe);
+ status = ocrdma_wait_mqe_cmpl(dev);
+ if (status)
+ goto mbx_err;
+ cqe_status = dev->mqe_ctx.cqe_status;
+ ext_status = dev->mqe_ctx.ext_status;
+ rsp = ocrdma_get_mqe_rsp(dev);
+ ocrdma_copy_le32_to_cpu(mqe, rsp, (sizeof(*mqe)));
+ if (cqe_status || ext_status) {
+ ocrdma_err
+ ("%s() opcode=0x%x, cqe_status=0x%x, ext_status=0x%x\n",
+ __func__,
+ (rsp->u.rsp.subsys_op & OCRDMA_MBX_RSP_OPCODE_MASK) >>
+ OCRDMA_MBX_RSP_OPCODE_SHIFT, cqe_status, ext_status);
+ status = ocrdma_get_mbx_cqe_errno(cqe_status);
+ goto mbx_err;
+ }
+ if (mqe->u.rsp.status & OCRDMA_MBX_RSP_STATUS_MASK)
+ status = ocrdma_get_mbx_errno(mqe->u.rsp.status);
+mbx_err:
+ mutex_unlock(&dev->mqe_ctx.lock);
+ return status;
+}
+
+static void ocrdma_get_attr(struct ocrdma_dev *dev,
+ struct ocrdma_dev_attr *attr,
+ struct ocrdma_mbx_query_config *rsp)
+{
+ int max_q_mem;
+
+ attr->max_pd =
+ (rsp->max_pd_ca_ack_delay & OCRDMA_MBX_QUERY_CFG_MAX_PD_MASK) >>
+ OCRDMA_MBX_QUERY_CFG_MAX_PD_SHIFT;
+ attr->max_qp =
+ (rsp->qp_srq_cq_ird_ord & OCRDMA_MBX_QUERY_CFG_MAX_QP_MASK) >>
+ OCRDMA_MBX_QUERY_CFG_MAX_QP_SHIFT;
+ attr->max_send_sge = ((rsp->max_write_send_sge &
+ OCRDMA_MBX_QUERY_CFG_MAX_SEND_SGE_MASK) >>
+ OCRDMA_MBX_QUERY_CFG_MAX_SEND_SGE_SHIFT);
+ attr->max_recv_sge = (rsp->max_write_send_sge &
+ OCRDMA_MBX_QUERY_CFG_MAX_SEND_SGE_MASK) >>
+ OCRDMA_MBX_QUERY_CFG_MAX_SEND_SGE_SHIFT;
+ attr->max_ord_per_qp = (rsp->max_ird_ord_per_qp &
+ OCRDMA_MBX_QUERY_CFG_MAX_ORD_PER_QP_MASK) >>
+ OCRDMA_MBX_QUERY_CFG_MAX_ORD_PER_QP_SHIFT;
+ attr->max_ird_per_qp = (rsp->max_ird_ord_per_qp &
+ OCRDMA_MBX_QUERY_CFG_MAX_IRD_PER_QP_MASK) >>
+ OCRDMA_MBX_QUERY_CFG_MAX_IRD_PER_QP_SHIFT;
+ attr->cq_overflow_detect = (rsp->qp_srq_cq_ird_ord &
+ OCRDMA_MBX_QUERY_CFG_CQ_OVERFLOW_MASK) >>
+ OCRDMA_MBX_QUERY_CFG_CQ_OVERFLOW_SHIFT;
+ attr->srq_supported = (rsp->qp_srq_cq_ird_ord &
+ OCRDMA_MBX_QUERY_CFG_SRQ_SUPPORTED_MASK) >>
+ OCRDMA_MBX_QUERY_CFG_SRQ_SUPPORTED_SHIFT;
+ attr->local_ca_ack_delay = (rsp->max_pd_ca_ack_delay &
+ OCRDMA_MBX_QUERY_CFG_CA_ACK_DELAY_MASK) >>
+ OCRDMA_MBX_QUERY_CFG_CA_ACK_DELAY_SHIFT;
+ attr->max_mr = rsp->max_mr;
+ attr->max_mr_size = ~0ull;
+ attr->max_fmr = 0;
+ attr->max_pages_per_frmr = rsp->max_pages_per_frmr;
+ attr->max_num_mr_pbl = rsp->max_num_mr_pbl;
+ attr->max_cqe = rsp->max_cq_cqes_per_cq &
+ OCRDMA_MBX_QUERY_CFG_MAX_CQES_PER_CQ_MASK;
+ attr->wqe_size = ((rsp->wqe_rqe_stride_max_dpp_cqs &
+ OCRDMA_MBX_QUERY_CFG_MAX_WQE_SIZE_MASK) >>
+ OCRDMA_MBX_QUERY_CFG_MAX_WQE_SIZE_OFFSET) *
+ OCRDMA_WQE_STRIDE;
+ attr->rqe_size = ((rsp->wqe_rqe_stride_max_dpp_cqs &
+ OCRDMA_MBX_QUERY_CFG_MAX_RQE_SIZE_MASK) >>
+ OCRDMA_MBX_QUERY_CFG_MAX_RQE_SIZE_OFFSET) *
+ OCRDMA_WQE_STRIDE;
+ attr->max_inline_data =
+ attr->wqe_size - (sizeof(struct ocrdma_hdr_wqe) +
+ sizeof(struct ocrdma_sge));
+ max_q_mem = OCRDMA_Q_PAGE_BASE_SIZE << (OCRDMA_MAX_Q_PAGE_SIZE_CNT - 1);
+ /* hw can queue one less then the configured size,
+ * so publish less by one to stack.
+ */
+ if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) {
+ dev->attr.max_wqe = max_q_mem / dev->attr.wqe_size;
+ attr->ird = 1;
+ attr->ird_page_size = OCRDMA_MIN_Q_PAGE_SIZE;
+ attr->num_ird_pages = MAX_OCRDMA_IRD_PAGES;
+ } else
+ dev->attr.max_wqe = (max_q_mem / dev->attr.wqe_size) - 1;
+ dev->attr.max_rqe = (max_q_mem / dev->attr.rqe_size) - 1;
+}
+
+static int ocrdma_check_fw_config(struct ocrdma_dev *dev,
+ struct ocrdma_fw_conf_rsp *conf)
+{
+ u32 fn_mode;
+
+ fn_mode = conf->fn_mode & OCRDMA_FN_MODE_RDMA;
+ if (fn_mode != OCRDMA_FN_MODE_RDMA)
+ return -EINVAL;
+ dev->base_eqid = conf->base_eqid;
+ dev->max_eq = conf->max_eq;
+ dev->attr.max_cq = OCRDMA_MAX_CQ - 1;
+ return 0;
+}
+
+/* can be issued only during init time. */
+static int ocrdma_mbx_query_fw_ver(struct ocrdma_dev *dev)
+{
+ int status = -ENOMEM;
+ struct ocrdma_mqe *cmd;
+ struct ocrdma_fw_ver_rsp *rsp;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_GET_FW_VER, sizeof(*cmd));
+ if (!cmd)
+ return -ENOMEM;
+ ocrdma_init_mch((struct ocrdma_mbx_hdr *)&cmd->u.cmd[0],
+ OCRDMA_CMD_GET_FW_VER,
+ OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
+
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+ rsp = (struct ocrdma_fw_ver_rsp *)cmd;
+ memset(&dev->attr.fw_ver[0], 0, sizeof(dev->attr.fw_ver));
+ memcpy(&dev->attr.fw_ver[0], &rsp->running_ver[0],
+ sizeof(rsp->running_ver));
+ ocrdma_le32_to_cpu(dev->attr.fw_ver, sizeof(rsp->running_ver));
+mbx_err:
+ kfree(cmd);
+ return status;
+}
+
+/* can be issued only during init time. */
+static int ocrdma_mbx_query_fw_config(struct ocrdma_dev *dev)
+{
+ int status = -ENOMEM;
+ struct ocrdma_mqe *cmd;
+ struct ocrdma_fw_conf_rsp *rsp;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_GET_FW_CONFIG, sizeof(*cmd));
+ if (!cmd)
+ return -ENOMEM;
+ ocrdma_init_mch((struct ocrdma_mbx_hdr *)&cmd->u.cmd[0],
+ OCRDMA_CMD_GET_FW_CONFIG,
+ OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+ rsp = (struct ocrdma_fw_conf_rsp *)cmd;
+ status = ocrdma_check_fw_config(dev, rsp);
+mbx_err:
+ kfree(cmd);
+ return status;
+}
+
+static int ocrdma_mbx_query_dev(struct ocrdma_dev *dev)
+{
+ int status = -ENOMEM;
+ struct ocrdma_mbx_query_config *rsp;
+ struct ocrdma_mqe *cmd;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_QUERY_CONFIG, sizeof(*cmd));
+ if (!cmd)
+ return status;
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+ rsp = (struct ocrdma_mbx_query_config *)cmd;
+ ocrdma_get_attr(dev, &dev->attr, rsp);
+mbx_err:
+ kfree(cmd);
+ return status;
+}
+
+int ocrdma_mbx_alloc_pd(struct ocrdma_dev *dev, struct ocrdma_pd *pd)
+{
+ int status = -ENOMEM;
+ struct ocrdma_alloc_pd *cmd;
+ struct ocrdma_alloc_pd_rsp *rsp;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_ALLOC_PD, sizeof(*cmd));
+ if (!cmd)
+ return status;
+ if (pd->dpp_enabled)
+ cmd->enable_dpp_rsvd |= OCRDMA_ALLOC_PD_ENABLE_DPP;
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+ rsp = (struct ocrdma_alloc_pd_rsp *)cmd;
+ pd->id = rsp->dpp_page_pdid & OCRDMA_ALLOC_PD_RSP_PDID_MASK;
+ if (rsp->dpp_page_pdid & OCRDMA_ALLOC_PD_RSP_DPP) {
+ pd->dpp_enabled = true;
+ pd->dpp_page = rsp->dpp_page_pdid >>
+ OCRDMA_ALLOC_PD_RSP_DPP_PAGE_SHIFT;
+ } else {
+ pd->dpp_enabled = false;
+ pd->num_dpp_qp = 0;
+ }
+mbx_err:
+ kfree(cmd);
+ return status;
+}
+
+int ocrdma_mbx_dealloc_pd(struct ocrdma_dev *dev, struct ocrdma_pd *pd)
+{
+ int status = -ENOMEM;
+ struct ocrdma_dealloc_pd *cmd;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DEALLOC_PD, sizeof(*cmd));
+ if (!cmd)
+ return status;
+ cmd->id = pd->id;
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ kfree(cmd);
+ return status;
+}
+
+static int ocrdma_build_q_conf(u32 *num_entries, int entry_size,
+ int *num_pages, int *page_size)
+{
+ int i;
+ int mem_size;
+
+ *num_entries = roundup_pow_of_two(*num_entries);
+ mem_size = *num_entries * entry_size;
+ /* find the possible lowest possible multiplier */
+ for (i = 0; i < OCRDMA_MAX_Q_PAGE_SIZE_CNT; i++) {
+ if (mem_size <= (OCRDMA_Q_PAGE_BASE_SIZE << i))
+ break;
+ }
+ if (i >= OCRDMA_MAX_Q_PAGE_SIZE_CNT)
+ return -EINVAL;
+ mem_size = roundup(mem_size,
+ ((OCRDMA_Q_PAGE_BASE_SIZE << i) / OCRDMA_MAX_Q_PAGES));
+ *num_pages =
+ mem_size / ((OCRDMA_Q_PAGE_BASE_SIZE << i) / OCRDMA_MAX_Q_PAGES);
+ *page_size = ((OCRDMA_Q_PAGE_BASE_SIZE << i) / OCRDMA_MAX_Q_PAGES);
+ *num_entries = mem_size / entry_size;
+ return 0;
+}
+
+static int ocrdma_mbx_create_ah_tbl(struct ocrdma_dev *dev)
+{
+ int i ;
+ int status = 0;
+ int max_ah;
+ struct ocrdma_create_ah_tbl *cmd;
+ struct ocrdma_create_ah_tbl_rsp *rsp;
+ struct pci_dev *pdev = dev->nic_info.pdev;
+ dma_addr_t pa;
+ struct ocrdma_pbe *pbes;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_CREATE_AH_TBL, sizeof(*cmd));
+ if (!cmd)
+ return status;
+
+ max_ah = OCRDMA_MAX_AH;
+ dev->av_tbl.size = sizeof(struct ocrdma_av) * max_ah;
+
+ /* number of PBEs in PBL */
+ cmd->ah_conf = (OCRDMA_AH_TBL_PAGES <<
+ OCRDMA_CREATE_AH_NUM_PAGES_SHIFT) &
+ OCRDMA_CREATE_AH_NUM_PAGES_MASK;
+
+ /* page size */
+ for (i = 0; i < OCRDMA_MAX_Q_PAGE_SIZE_CNT; i++) {
+ if (PAGE_SIZE == (OCRDMA_MIN_Q_PAGE_SIZE << i))
+ break;
+ }
+ cmd->ah_conf |= (i << OCRDMA_CREATE_AH_PAGE_SIZE_SHIFT) &
+ OCRDMA_CREATE_AH_PAGE_SIZE_MASK;
+
+ /* ah_entry size */
+ cmd->ah_conf |= (sizeof(struct ocrdma_av) <<
+ OCRDMA_CREATE_AH_ENTRY_SIZE_SHIFT) &
+ OCRDMA_CREATE_AH_ENTRY_SIZE_MASK;
+
+ dev->av_tbl.pbl.va = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
+ &dev->av_tbl.pbl.pa,
+ GFP_KERNEL);
+ if (dev->av_tbl.pbl.va == NULL)
+ goto mem_err;
+
+ dev->av_tbl.va = dma_alloc_coherent(&pdev->dev, dev->av_tbl.size,
+ &pa, GFP_KERNEL);
+ if (dev->av_tbl.va == NULL)
+ goto mem_err_ah;
+ dev->av_tbl.pa = pa;
+ dev->av_tbl.num_ah = max_ah;
+ memset(dev->av_tbl.va, 0, dev->av_tbl.size);
+
+ pbes = (struct ocrdma_pbe *)dev->av_tbl.pbl.va;
+ for (i = 0; i < dev->av_tbl.size / OCRDMA_MIN_Q_PAGE_SIZE; i++) {
+ pbes[i].pa_lo = (u32) (pa & 0xffffffff);
+ pbes[i].pa_hi = (u32) upper_32_bits(pa);
+ pa += PAGE_SIZE;
+ }
+ cmd->tbl_addr[0].lo = (u32)(dev->av_tbl.pbl.pa & 0xFFFFFFFF);
+ cmd->tbl_addr[0].hi = (u32)upper_32_bits(dev->av_tbl.pbl.pa);
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+ rsp = (struct ocrdma_create_ah_tbl_rsp *)cmd;
+ dev->av_tbl.ahid = rsp->ahid & 0xFFFF;
+ kfree(cmd);
+ return 0;
+
+mbx_err:
+ dma_free_coherent(&pdev->dev, dev->av_tbl.size, dev->av_tbl.va,
+ dev->av_tbl.pa);
+ dev->av_tbl.va = NULL;
+mem_err_ah:
+ dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->av_tbl.pbl.va,
+ dev->av_tbl.pbl.pa);
+ dev->av_tbl.pbl.va = NULL;
+ dev->av_tbl.size = 0;
+mem_err:
+ kfree(cmd);
+ return status;
+}
+
+static void ocrdma_mbx_delete_ah_tbl(struct ocrdma_dev *dev)
+{
+ struct ocrdma_delete_ah_tbl *cmd;
+ struct pci_dev *pdev = dev->nic_info.pdev;
+
+ if (dev->av_tbl.va == NULL)
+ return;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DELETE_AH_TBL, sizeof(*cmd));
+ if (!cmd)
+ return;
+ cmd->ahid = dev->av_tbl.ahid;
+
+ ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ dma_free_coherent(&pdev->dev, dev->av_tbl.size, dev->av_tbl.va,
+ dev->av_tbl.pa);
+ dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->av_tbl.pbl.va,
+ dev->av_tbl.pbl.pa);
+ kfree(cmd);
+}
+
+/* Multiple CQs uses the EQ. This routine returns least used
+ * EQ to associate with CQ. This will distributes the interrupt
+ * processing and CPU load to associated EQ, vector and so to that CPU.
+ */
+static u16 ocrdma_bind_eq(struct ocrdma_dev *dev)
+{
+ int i, selected_eq = 0, cq_cnt = 0;
+ u16 eq_id;
+
+ mutex_lock(&dev->dev_lock);
+ cq_cnt = dev->qp_eq_tbl[0].cq_cnt;
+ eq_id = dev->qp_eq_tbl[0].q.id;
+ /* find the EQ which is has the least number of
+ * CQs associated with it.
+ */
+ for (i = 0; i < dev->eq_cnt; i++) {
+ if (dev->qp_eq_tbl[i].cq_cnt < cq_cnt) {
+ cq_cnt = dev->qp_eq_tbl[i].cq_cnt;
+ eq_id = dev->qp_eq_tbl[i].q.id;
+ selected_eq = i;
+ }
+ }
+ dev->qp_eq_tbl[selected_eq].cq_cnt += 1;
+ mutex_unlock(&dev->dev_lock);
+ return eq_id;
+}
+
+static void ocrdma_unbind_eq(struct ocrdma_dev *dev, u16 eq_id)
+{
+ int i;
+
+ mutex_lock(&dev->dev_lock);
+ for (i = 0; i < dev->eq_cnt; i++) {
+ if (dev->qp_eq_tbl[i].q.id != eq_id)
+ continue;
+ dev->qp_eq_tbl[i].cq_cnt -= 1;
+ break;
+ }
+ mutex_unlock(&dev->dev_lock);
+}
+
+int ocrdma_mbx_create_cq(struct ocrdma_dev *dev, struct ocrdma_cq *cq,
+ int entries, int dpp_cq)
+{
+ int status = -ENOMEM; int max_hw_cqe;
+ struct pci_dev *pdev = dev->nic_info.pdev;
+ struct ocrdma_create_cq *cmd;
+ struct ocrdma_create_cq_rsp *rsp;
+ u32 hw_pages, cqe_size, page_size, cqe_count;
+
+ if (dpp_cq)
+ return -EINVAL;
+ if (entries > dev->attr.max_cqe) {
+ ocrdma_err("%s(%d) max_cqe=0x%x, requester_cqe=0x%x\n",
+ __func__, dev->id, dev->attr.max_cqe, entries);
+ return -EINVAL;
+ }
+ if (dpp_cq && (dev->nic_info.dev_family != OCRDMA_GEN2_FAMILY))
+ return -EINVAL;
+
+ if (dpp_cq) {
+ cq->max_hw_cqe = 1;
+ max_hw_cqe = 1;
+ cqe_size = OCRDMA_DPP_CQE_SIZE;
+ hw_pages = 1;
+ } else {
+ cq->max_hw_cqe = dev->attr.max_cqe;
+ max_hw_cqe = dev->attr.max_cqe;
+ cqe_size = sizeof(struct ocrdma_cqe);
+ hw_pages = OCRDMA_CREATE_CQ_MAX_PAGES;
+ }
+
+ cq->len = roundup(max_hw_cqe * cqe_size, OCRDMA_MIN_Q_PAGE_SIZE);
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_CREATE_CQ, sizeof(*cmd));
+ if (!cmd)
+ return -ENOMEM;
+ ocrdma_init_mch(&cmd->cmd.req, OCRDMA_CMD_CREATE_CQ,
+ OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
+ cq->va = dma_alloc_coherent(&pdev->dev, cq->len, &cq->pa, GFP_KERNEL);
+ if (!cq->va) {
+ status = -ENOMEM;
+ goto mem_err;
+ }
+ memset(cq->va, 0, cq->len);
+ page_size = cq->len / hw_pages;
+ cmd->cmd.pgsz_pgcnt = (page_size / OCRDMA_MIN_Q_PAGE_SIZE) <<
+ OCRDMA_CREATE_CQ_PAGE_SIZE_SHIFT;
+ cmd->cmd.pgsz_pgcnt |= hw_pages;
+ cmd->cmd.ev_cnt_flags = OCRDMA_CREATE_CQ_DEF_FLAGS;
+
+ if (dev->eq_cnt < 0)
+ goto eq_err;
+ cq->eqn = ocrdma_bind_eq(dev);
+ cmd->cmd.req.rsvd_version = OCRDMA_CREATE_CQ_VER2;
+ cqe_count = cq->len / cqe_size;
+ if (cqe_count > 1024)
+ /* Set cnt to 3 to indicate more than 1024 cq entries */
+ cmd->cmd.ev_cnt_flags |= (0x3 << OCRDMA_CREATE_CQ_CNT_SHIFT);
+ else {
+ u8 count = 0;
+ switch (cqe_count) {
+ case 256:
+ count = 0;
+ break;
+ case 512:
+ count = 1;
+ break;
+ case 1024:
+ count = 2;
+ break;
+ default:
+ goto mbx_err;
+ }
+ cmd->cmd.ev_cnt_flags |= (count << OCRDMA_CREATE_CQ_CNT_SHIFT);
+ }
+ /* shared eq between all the consumer cqs. */
+ cmd->cmd.eqn = cq->eqn;
+ if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) {
+ if (dpp_cq)
+ cmd->cmd.pgsz_pgcnt |= OCRDMA_CREATE_CQ_DPP <<
+ OCRDMA_CREATE_CQ_TYPE_SHIFT;
+ cq->phase_change = false;
+ cmd->cmd.cqe_count = (cq->len / cqe_size);
+ } else {
+ cmd->cmd.cqe_count = (cq->len / cqe_size) - 1;
+ cmd->cmd.ev_cnt_flags |= OCRDMA_CREATE_CQ_FLAGS_AUTO_VALID;
+ cq->phase_change = true;
+ }
+
+ ocrdma_build_q_pages(&cmd->cmd.pa[0], hw_pages, cq->pa, page_size);
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+
+ rsp = (struct ocrdma_create_cq_rsp *)cmd;
+ cq->id = (u16) (rsp->rsp.cq_id & OCRDMA_CREATE_CQ_RSP_CQ_ID_MASK);
+ kfree(cmd);
+ return 0;
+mbx_err:
+ ocrdma_unbind_eq(dev, cq->eqn);
+eq_err:
+ dma_free_coherent(&pdev->dev, cq->len, cq->va, cq->pa);
+mem_err:
+ kfree(cmd);
+ return status;
+}
+
+int ocrdma_mbx_destroy_cq(struct ocrdma_dev *dev, struct ocrdma_cq *cq)
+{
+ int status = -ENOMEM;
+ struct ocrdma_destroy_cq *cmd;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DELETE_CQ, sizeof(*cmd));
+ if (!cmd)
+ return status;
+ ocrdma_init_mch(&cmd->req, OCRDMA_CMD_DELETE_CQ,
+ OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
+
+ cmd->bypass_flush_qid |=
+ (cq->id << OCRDMA_DESTROY_CQ_QID_SHIFT) &
+ OCRDMA_DESTROY_CQ_QID_MASK;
+
+ ocrdma_unbind_eq(dev, cq->eqn);
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+ dma_free_coherent(&dev->nic_info.pdev->dev, cq->len, cq->va, cq->pa);
+mbx_err:
+ kfree(cmd);
+ return status;
+}
+
+int ocrdma_mbx_alloc_lkey(struct ocrdma_dev *dev, struct ocrdma_hw_mr *hwmr,
+ u32 pdid, int addr_check)
+{
+ int status = -ENOMEM;
+ struct ocrdma_alloc_lkey *cmd;
+ struct ocrdma_alloc_lkey_rsp *rsp;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_ALLOC_LKEY, sizeof(*cmd));
+ if (!cmd)
+ return status;
+ cmd->pdid = pdid;
+ cmd->pbl_sz_flags |= addr_check;
+ cmd->pbl_sz_flags |= (hwmr->fr_mr << OCRDMA_ALLOC_LKEY_FMR_SHIFT);
+ cmd->pbl_sz_flags |=
+ (hwmr->remote_wr << OCRDMA_ALLOC_LKEY_REMOTE_WR_SHIFT);
+ cmd->pbl_sz_flags |=
+ (hwmr->remote_rd << OCRDMA_ALLOC_LKEY_REMOTE_RD_SHIFT);
+ cmd->pbl_sz_flags |=
+ (hwmr->local_wr << OCRDMA_ALLOC_LKEY_LOCAL_WR_SHIFT);
+ cmd->pbl_sz_flags |=
+ (hwmr->remote_atomic << OCRDMA_ALLOC_LKEY_REMOTE_ATOMIC_SHIFT);
+ cmd->pbl_sz_flags |=
+ (hwmr->num_pbls << OCRDMA_ALLOC_LKEY_PBL_SIZE_SHIFT);
+
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+ rsp = (struct ocrdma_alloc_lkey_rsp *)cmd;
+ hwmr->lkey = rsp->lrkey;
+mbx_err:
+ kfree(cmd);
+ return status;
+}
+
+int ocrdma_mbx_dealloc_lkey(struct ocrdma_dev *dev, int fr_mr, u32 lkey)
+{
+ int status = -ENOMEM;
+ struct ocrdma_dealloc_lkey *cmd;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DEALLOC_LKEY, sizeof(*cmd));
+ if (!cmd)
+ return -ENOMEM;
+ cmd->lkey = lkey;
+ cmd->rsvd_frmr = fr_mr ? 1 : 0;
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+mbx_err:
+ kfree(cmd);
+ return status;
+}
+
+static int ocrdma_mbx_reg_mr(struct ocrdma_dev *dev, struct ocrdma_hw_mr *hwmr,
+ u32 pdid, u32 pbl_cnt, u32 pbe_size, u32 last)
+{
+ int status = -ENOMEM;
+ int i;
+ struct ocrdma_reg_nsmr *cmd;
+ struct ocrdma_reg_nsmr_rsp *rsp;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_REGISTER_NSMR, sizeof(*cmd));
+ if (!cmd)
+ return -ENOMEM;
+ cmd->num_pbl_pdid =
+ pdid | (hwmr->num_pbls << OCRDMA_REG_NSMR_NUM_PBL_SHIFT);
+
+ cmd->flags_hpage_pbe_sz |= (hwmr->remote_wr <<
+ OCRDMA_REG_NSMR_REMOTE_WR_SHIFT);
+ cmd->flags_hpage_pbe_sz |= (hwmr->remote_rd <<
+ OCRDMA_REG_NSMR_REMOTE_RD_SHIFT);
+ cmd->flags_hpage_pbe_sz |= (hwmr->local_wr <<
+ OCRDMA_REG_NSMR_LOCAL_WR_SHIFT);
+ cmd->flags_hpage_pbe_sz |= (hwmr->remote_atomic <<
+ OCRDMA_REG_NSMR_REMOTE_ATOMIC_SHIFT);
+ cmd->flags_hpage_pbe_sz |= (hwmr->mw_bind <<
+ OCRDMA_REG_NSMR_BIND_MEMWIN_SHIFT);
+ cmd->flags_hpage_pbe_sz |= (last << OCRDMA_REG_NSMR_LAST_SHIFT);
+
+ cmd->flags_hpage_pbe_sz |= (hwmr->pbe_size / OCRDMA_MIN_HPAGE_SIZE);
+ cmd->flags_hpage_pbe_sz |= (hwmr->pbl_size / OCRDMA_MIN_HPAGE_SIZE) <<
+ OCRDMA_REG_NSMR_HPAGE_SIZE_SHIFT;
+ cmd->totlen_low = hwmr->len;
+ cmd->totlen_high = upper_32_bits(hwmr->len);
+ cmd->fbo_low = (u32) (hwmr->fbo & 0xffffffff);
+ cmd->fbo_high = (u32) upper_32_bits(hwmr->fbo);
+ cmd->va_loaddr = (u32) hwmr->va;
+ cmd->va_hiaddr = (u32) upper_32_bits(hwmr->va);
+
+ for (i = 0; i < pbl_cnt; i++) {
+ cmd->pbl[i].lo = (u32) (hwmr->pbl_table[i].pa & 0xffffffff);
+ cmd->pbl[i].hi = upper_32_bits(hwmr->pbl_table[i].pa);
+ }
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+ rsp = (struct ocrdma_reg_nsmr_rsp *)cmd;
+ hwmr->lkey = rsp->lrkey;
+mbx_err:
+ kfree(cmd);
+ return status;
+}
+
+static int ocrdma_mbx_reg_mr_cont(struct ocrdma_dev *dev,
+ struct ocrdma_hw_mr *hwmr, u32 pbl_cnt,
+ u32 pbl_offset, u32 last)
+{
+ int status = -ENOMEM;
+ int i;
+ struct ocrdma_reg_nsmr_cont *cmd;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_REGISTER_NSMR_CONT, sizeof(*cmd));
+ if (!cmd)
+ return -ENOMEM;
+ cmd->lrkey = hwmr->lkey;
+ cmd->num_pbl_offset = (pbl_cnt << OCRDMA_REG_NSMR_CONT_NUM_PBL_SHIFT) |
+ (pbl_offset & OCRDMA_REG_NSMR_CONT_PBL_SHIFT_MASK);
+ cmd->last = last << OCRDMA_REG_NSMR_CONT_LAST_SHIFT;
+
+ for (i = 0; i < pbl_cnt; i++) {
+ cmd->pbl[i].lo =
+ (u32) (hwmr->pbl_table[i + pbl_offset].pa & 0xffffffff);
+ cmd->pbl[i].hi =
+ upper_32_bits(hwmr->pbl_table[i + pbl_offset].pa);
+ }
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+mbx_err:
+ kfree(cmd);
+ return status;
+}
+
+int ocrdma_reg_mr(struct ocrdma_dev *dev,
+ struct ocrdma_hw_mr *hwmr, u32 pdid, int acc)
+{
+ int status;
+ u32 last = 0;
+ u32 cur_pbl_cnt, pbl_offset;
+ u32 pending_pbl_cnt = hwmr->num_pbls;
+
+ pbl_offset = 0;
+ cur_pbl_cnt = min(pending_pbl_cnt, MAX_OCRDMA_NSMR_PBL);
+ if (cur_pbl_cnt == pending_pbl_cnt)
+ last = 1;
+
+ status = ocrdma_mbx_reg_mr(dev, hwmr, pdid,
+ cur_pbl_cnt, hwmr->pbe_size, last);
+ if (status) {
+ ocrdma_err("%s() status=%d\n", __func__, status);
+ return status;
+ }
+ /* if there is no more pbls to register then exit. */
+ if (last)
+ return 0;
+
+ while (!last) {
+ pbl_offset += cur_pbl_cnt;
+ pending_pbl_cnt -= cur_pbl_cnt;
+ cur_pbl_cnt = min(pending_pbl_cnt, MAX_OCRDMA_NSMR_PBL);
+ /* if we reach the end of the pbls, then need to set the last
+ * bit, indicating no more pbls to register for this memory key.
+ */
+ if (cur_pbl_cnt == pending_pbl_cnt)
+ last = 1;
+
+ status = ocrdma_mbx_reg_mr_cont(dev, hwmr, cur_pbl_cnt,
+ pbl_offset, last);
+ if (status)
+ break;
+ }
+ if (status)
+ ocrdma_err("%s() err. status=%d\n", __func__, status);
+
+ return status;
+}
+
+bool ocrdma_is_qp_in_sq_flushlist(struct ocrdma_cq *cq, struct ocrdma_qp *qp)
+{
+ struct ocrdma_qp *tmp;
+ bool found = false;
+ list_for_each_entry(tmp, &cq->sq_head, sq_entry) {
+ if (qp == tmp) {
+ found = true;
+ break;
+ }
+ }
+ return found;
+}
+
+bool ocrdma_is_qp_in_rq_flushlist(struct ocrdma_cq *cq, struct ocrdma_qp *qp)
+{
+ struct ocrdma_qp *tmp;
+ bool found = false;
+ list_for_each_entry(tmp, &cq->rq_head, rq_entry) {
+ if (qp == tmp) {
+ found = true;
+ break;
+ }
+ }
+ return found;
+}
+
+void ocrdma_flush_qp(struct ocrdma_qp *qp)
+{
+ bool found;
+ unsigned long flags;
+
+ spin_lock_irqsave(&qp->dev->flush_q_lock, flags);
+ found = ocrdma_is_qp_in_sq_flushlist(qp->sq_cq, qp);
+ if (!found)
+ list_add_tail(&qp->sq_entry, &qp->sq_cq->sq_head);
+ if (!qp->srq) {
+ found = ocrdma_is_qp_in_rq_flushlist(qp->rq_cq, qp);
+ if (!found)
+ list_add_tail(&qp->rq_entry, &qp->rq_cq->rq_head);
+ }
+ spin_unlock_irqrestore(&qp->dev->flush_q_lock, flags);
+}
+
+int ocrdma_qp_state_machine(struct ocrdma_qp *qp, enum ib_qp_state new_ib_state,
+ enum ib_qp_state *old_ib_state)
+{
+ unsigned long flags;
+ int status = 0;
+ enum ocrdma_qp_state new_state;
+ new_state = get_ocrdma_qp_state(new_ib_state);
+
+ /* sync with wqe and rqe posting */
+ spin_lock_irqsave(&qp->q_lock, flags);
+
+ if (old_ib_state)
+ *old_ib_state = get_ibqp_state(qp->state);
+ if (new_state == qp->state) {
+ spin_unlock_irqrestore(&qp->q_lock, flags);
+ return 1;
+ }
+
+ switch (qp->state) {
+ case OCRDMA_QPS_RST:
+ switch (new_state) {
+ case OCRDMA_QPS_RST:
+ case OCRDMA_QPS_INIT:
+ break;
+ default:
+ status = -EINVAL;
+ break;
+ };
+ break;
+ case OCRDMA_QPS_INIT:
+ /* qps: INIT->XXX */
+ switch (new_state) {
+ case OCRDMA_QPS_INIT:
+ case OCRDMA_QPS_RTR:
+ break;
+ case OCRDMA_QPS_ERR:
+ ocrdma_flush_qp(qp);
+ break;
+ default:
+ status = -EINVAL;
+ break;
+ };
+ break;
+ case OCRDMA_QPS_RTR:
+ /* qps: RTS->XXX */
+ switch (new_state) {
+ case OCRDMA_QPS_RTS:
+ break;
+ case OCRDMA_QPS_ERR:
+ ocrdma_flush_qp(qp);
+ break;
+ default:
+ status = -EINVAL;
+ break;
+ };
+ break;
+ case OCRDMA_QPS_RTS:
+ /* qps: RTS->XXX */
+ switch (new_state) {
+ case OCRDMA_QPS_SQD:
+ case OCRDMA_QPS_SQE:
+ break;
+ case OCRDMA_QPS_ERR:
+ ocrdma_flush_qp(qp);
+ break;
+ default:
+ status = -EINVAL;
+ break;
+ };
+ break;
+ case OCRDMA_QPS_SQD:
+ /* qps: SQD->XXX */
+ switch (new_state) {
+ case OCRDMA_QPS_RTS:
+ case OCRDMA_QPS_SQE:
+ case OCRDMA_QPS_ERR:
+ break;
+ default:
+ status = -EINVAL;
+ break;
+ };
+ break;
+ case OCRDMA_QPS_SQE:
+ switch (new_state) {
+ case OCRDMA_QPS_RTS:
+ case OCRDMA_QPS_ERR:
+ break;
+ default:
+ status = -EINVAL;
+ break;
+ };
+ break;
+ case OCRDMA_QPS_ERR:
+ /* qps: ERR->XXX */
+ switch (new_state) {
+ case OCRDMA_QPS_RST:
+ break;
+ default:
+ status = -EINVAL;
+ break;
+ };
+ break;
+ default:
+ status = -EINVAL;
+ break;
+ };
+ if (!status)
+ qp->state = new_state;
+
+ spin_unlock_irqrestore(&qp->q_lock, flags);
+ return status;
+}
+
+static u32 ocrdma_set_create_qp_mbx_access_flags(struct ocrdma_qp *qp)
+{
+ u32 flags = 0;
+ if (qp->cap_flags & OCRDMA_QP_INB_RD)
+ flags |= OCRDMA_CREATE_QP_REQ_INB_RDEN_MASK;
+ if (qp->cap_flags & OCRDMA_QP_INB_WR)
+ flags |= OCRDMA_CREATE_QP_REQ_INB_WREN_MASK;
+ if (qp->cap_flags & OCRDMA_QP_MW_BIND)
+ flags |= OCRDMA_CREATE_QP_REQ_BIND_MEMWIN_MASK;
+ if (qp->cap_flags & OCRDMA_QP_LKEY0)
+ flags |= OCRDMA_CREATE_QP_REQ_ZERO_LKEYEN_MASK;
+ if (qp->cap_flags & OCRDMA_QP_FAST_REG)
+ flags |= OCRDMA_CREATE_QP_REQ_FMR_EN_MASK;
+ return flags;
+}
+
+static int ocrdma_set_create_qp_sq_cmd(struct ocrdma_create_qp_req *cmd,
+ struct ib_qp_init_attr *attrs,
+ struct ocrdma_qp *qp)
+{
+ int status;
+ u32 len, hw_pages, hw_page_size;
+ dma_addr_t pa;
+ struct ocrdma_dev *dev = qp->dev;
+ struct pci_dev *pdev = dev->nic_info.pdev;
+ u32 max_wqe_allocated;
+ u32 max_sges = attrs->cap.max_send_sge;
+
+ max_wqe_allocated = attrs->cap.max_send_wr;
+ /* need to allocate one extra to for GEN1 family */
+ if (dev->nic_info.dev_family != OCRDMA_GEN2_FAMILY)
+ max_wqe_allocated += 1;
+
+ status = ocrdma_build_q_conf(&max_wqe_allocated,
+ dev->attr.wqe_size, &hw_pages, &hw_page_size);
+ if (status) {
+ ocrdma_err("%s() req. max_send_wr=0x%x\n", __func__,
+ max_wqe_allocated);
+ return -EINVAL;
+ }
+ qp->sq.max_cnt = max_wqe_allocated;
+ len = (hw_pages * hw_page_size);
+
+ qp->sq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
+ if (!qp->sq.va)
+ return -EINVAL;
+ memset(qp->sq.va, 0, len);
+ qp->sq.len = len;
+ qp->sq.pa = pa;
+ qp->sq.entry_size = dev->attr.wqe_size;
+ ocrdma_build_q_pages(&cmd->wq_addr[0], hw_pages, pa, hw_page_size);
+
+ cmd->type_pgsz_pdn |= (ilog2(hw_page_size / OCRDMA_MIN_Q_PAGE_SIZE)
+ << OCRDMA_CREATE_QP_REQ_SQ_PAGE_SIZE_SHIFT);
+ cmd->num_wq_rq_pages |= (hw_pages <<
+ OCRDMA_CREATE_QP_REQ_NUM_WQ_PAGES_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_NUM_WQ_PAGES_MASK;
+ cmd->max_sge_send_write |= (max_sges <<
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_SEND_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_SEND_MASK;
+ cmd->max_sge_send_write |= (max_sges <<
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_WRITE_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_WRITE_MASK;
+ cmd->max_wqe_rqe |= (ilog2(qp->sq.max_cnt) <<
+ OCRDMA_CREATE_QP_REQ_MAX_WQE_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_MAX_WQE_MASK;
+ cmd->wqe_rqe_size |= (dev->attr.wqe_size <<
+ OCRDMA_CREATE_QP_REQ_WQE_SIZE_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_WQE_SIZE_MASK;
+ return 0;
+}
+
+static int ocrdma_set_create_qp_rq_cmd(struct ocrdma_create_qp_req *cmd,
+ struct ib_qp_init_attr *attrs,
+ struct ocrdma_qp *qp)
+{
+ int status;
+ u32 len, hw_pages, hw_page_size;
+ dma_addr_t pa = 0;
+ struct ocrdma_dev *dev = qp->dev;
+ struct pci_dev *pdev = dev->nic_info.pdev;
+ u32 max_rqe_allocated = attrs->cap.max_recv_wr + 1;
+
+ status = ocrdma_build_q_conf(&max_rqe_allocated, dev->attr.rqe_size,
+ &hw_pages, &hw_page_size);
+ if (status) {
+ ocrdma_err("%s() req. max_recv_wr=0x%x\n", __func__,
+ attrs->cap.max_recv_wr + 1);
+ return status;
+ }
+ qp->rq.max_cnt = max_rqe_allocated;
+ len = (hw_pages * hw_page_size);
+
+ qp->rq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
+ if (!qp->rq.va)
+ return status;
+ memset(qp->rq.va, 0, len);
+ qp->rq.pa = pa;
+ qp->rq.len = len;
+ qp->rq.entry_size = dev->attr.rqe_size;
+
+ ocrdma_build_q_pages(&cmd->rq_addr[0], hw_pages, pa, hw_page_size);
+ cmd->type_pgsz_pdn |= (ilog2(hw_page_size / OCRDMA_MIN_Q_PAGE_SIZE) <<
+ OCRDMA_CREATE_QP_REQ_RQ_PAGE_SIZE_SHIFT);
+ cmd->num_wq_rq_pages |=
+ (hw_pages << OCRDMA_CREATE_QP_REQ_NUM_RQ_PAGES_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_NUM_RQ_PAGES_MASK;
+ cmd->max_sge_recv_flags |= (attrs->cap.max_recv_sge <<
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_RECV_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_RECV_MASK;
+ cmd->max_wqe_rqe |= (ilog2(qp->rq.max_cnt) <<
+ OCRDMA_CREATE_QP_REQ_MAX_RQE_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_MAX_RQE_MASK;
+ cmd->wqe_rqe_size |= (dev->attr.rqe_size <<
+ OCRDMA_CREATE_QP_REQ_RQE_SIZE_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_RQE_SIZE_MASK;
+ return 0;
+}
+
+static void ocrdma_set_create_qp_dpp_cmd(struct ocrdma_create_qp_req *cmd,
+ struct ocrdma_pd *pd,
+ struct ocrdma_qp *qp,
+ u8 enable_dpp_cq, u16 dpp_cq_id)
+{
+ pd->num_dpp_qp--;
+ qp->dpp_enabled = true;
+ cmd->max_sge_recv_flags |= OCRDMA_CREATE_QP_REQ_ENABLE_DPP_MASK;
+ if (!enable_dpp_cq)
+ return;
+ cmd->max_sge_recv_flags |= OCRDMA_CREATE_QP_REQ_ENABLE_DPP_MASK;
+ cmd->dpp_credits_cqid = dpp_cq_id;
+ cmd->dpp_credits_cqid |= OCRDMA_CREATE_QP_REQ_DPP_CREDIT_LIMIT <<
+ OCRDMA_CREATE_QP_REQ_DPP_CREDIT_SHIFT;
+}
+
+static int ocrdma_set_create_qp_ird_cmd(struct ocrdma_create_qp_req *cmd,
+ struct ocrdma_qp *qp)
+{
+ struct ocrdma_dev *dev = qp->dev;
+ struct pci_dev *pdev = dev->nic_info.pdev;
+ dma_addr_t pa = 0;
+ int ird_page_size = dev->attr.ird_page_size;
+ int ird_q_len = dev->attr.num_ird_pages * ird_page_size;
+
+ if (dev->attr.ird == 0)
+ return 0;
+
+ qp->ird_q_va = dma_alloc_coherent(&pdev->dev, ird_q_len,
+ &pa, GFP_KERNEL);
+ if (!qp->ird_q_va)
+ return -ENOMEM;
+ memset(qp->ird_q_va, 0, ird_q_len);
+ ocrdma_build_q_pages(&cmd->ird_addr[0], dev->attr.num_ird_pages,
+ pa, ird_page_size);
+ return 0;
+}
+
+static void ocrdma_get_create_qp_rsp(struct ocrdma_create_qp_rsp *rsp,
+ struct ocrdma_qp *qp,
+ struct ib_qp_init_attr *attrs,
+ u16 *dpp_offset, u16 *dpp_credit_lmt)
+{
+ u32 max_wqe_allocated, max_rqe_allocated;
+ qp->id = rsp->qp_id & OCRDMA_CREATE_QP_RSP_QP_ID_MASK;
+ qp->rq.dbid = rsp->sq_rq_id & OCRDMA_CREATE_QP_RSP_RQ_ID_MASK;
+ qp->sq.dbid = rsp->sq_rq_id >> OCRDMA_CREATE_QP_RSP_SQ_ID_SHIFT;
+ qp->max_ird = rsp->max_ord_ird & OCRDMA_CREATE_QP_RSP_MAX_IRD_MASK;
+ qp->max_ord = (rsp->max_ord_ird >> OCRDMA_CREATE_QP_RSP_MAX_ORD_SHIFT);
+ qp->dpp_enabled = false;
+ if (rsp->dpp_response & OCRDMA_CREATE_QP_RSP_DPP_ENABLED_MASK) {
+ qp->dpp_enabled = true;
+ *dpp_credit_lmt = (rsp->dpp_response &
+ OCRDMA_CREATE_QP_RSP_DPP_CREDITS_MASK) >>
+ OCRDMA_CREATE_QP_RSP_DPP_CREDITS_SHIFT;
+ *dpp_offset = (rsp->dpp_response &
+ OCRDMA_CREATE_QP_RSP_DPP_PAGE_OFFSET_MASK) >>
+ OCRDMA_CREATE_QP_RSP_DPP_PAGE_OFFSET_SHIFT;
+ }
+ max_wqe_allocated =
+ rsp->max_wqe_rqe >> OCRDMA_CREATE_QP_RSP_MAX_WQE_SHIFT;
+ max_wqe_allocated = 1 << max_wqe_allocated;
+ max_rqe_allocated = 1 << ((u16)rsp->max_wqe_rqe);
+
+ if (qp->dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) {
+ qp->sq.free_delta = 0;
+ qp->rq.free_delta = 1;
+ } else
+ qp->sq.free_delta = 1;
+
+ qp->sq.max_cnt = max_wqe_allocated;
+ qp->sq.max_wqe_idx = max_wqe_allocated - 1;
+
+ if (!attrs->srq) {
+ qp->rq.max_cnt = max_rqe_allocated;
+ qp->rq.max_wqe_idx = max_rqe_allocated - 1;
+ qp->rq.free_delta = 1;
+ }
+}
+
+int ocrdma_mbx_create_qp(struct ocrdma_qp *qp, struct ib_qp_init_attr *attrs,
+ u8 enable_dpp_cq, u16 dpp_cq_id, u16 *dpp_offset,
+ u16 *dpp_credit_lmt)
+{
+ int status = -ENOMEM;
+ u32 flags = 0;
+ struct ocrdma_dev *dev = qp->dev;
+ struct ocrdma_pd *pd = qp->pd;
+ struct pci_dev *pdev = dev->nic_info.pdev;
+ struct ocrdma_cq *cq;
+ struct ocrdma_create_qp_req *cmd;
+ struct ocrdma_create_qp_rsp *rsp;
+ int qptype;
+
+ switch (attrs->qp_type) {
+ case IB_QPT_GSI:
+ qptype = OCRDMA_QPT_GSI;
+ break;
+ case IB_QPT_RC:
+ qptype = OCRDMA_QPT_RC;
+ break;
+ case IB_QPT_UD:
+ qptype = OCRDMA_QPT_UD;
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_CREATE_QP, sizeof(*cmd));
+ if (!cmd)
+ return status;
+ cmd->type_pgsz_pdn |= (qptype << OCRDMA_CREATE_QP_REQ_QPT_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_QPT_MASK;
+ status = ocrdma_set_create_qp_sq_cmd(cmd, attrs, qp);
+ if (status)
+ goto sq_err;
+
+ if (attrs->srq) {
+ struct ocrdma_srq *srq = get_ocrdma_srq(attrs->srq);
+ cmd->max_sge_recv_flags |= OCRDMA_CREATE_QP_REQ_USE_SRQ_MASK;
+ cmd->rq_addr[0].lo = srq->id;
+ qp->srq = srq;
+ } else {
+ status = ocrdma_set_create_qp_rq_cmd(cmd, attrs, qp);
+ if (status)
+ goto rq_err;
+ }
+
+ status = ocrdma_set_create_qp_ird_cmd(cmd, qp);
+ if (status)
+ goto mbx_err;
+
+ cmd->type_pgsz_pdn |= (pd->id << OCRDMA_CREATE_QP_REQ_PD_ID_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_PD_ID_MASK;
+
+ flags = ocrdma_set_create_qp_mbx_access_flags(qp);
+
+ cmd->max_sge_recv_flags |= flags;
+ cmd->max_ord_ird |= (dev->attr.max_ord_per_qp <<
+ OCRDMA_CREATE_QP_REQ_MAX_ORD_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_MAX_ORD_MASK;
+ cmd->max_ord_ird |= (dev->attr.max_ird_per_qp <<
+ OCRDMA_CREATE_QP_REQ_MAX_IRD_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_MAX_IRD_MASK;
+ cq = get_ocrdma_cq(attrs->send_cq);
+ cmd->wq_rq_cqid |= (cq->id << OCRDMA_CREATE_QP_REQ_WQ_CQID_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_WQ_CQID_MASK;
+ qp->sq_cq = cq;
+ cq = get_ocrdma_cq(attrs->recv_cq);
+ cmd->wq_rq_cqid |= (cq->id << OCRDMA_CREATE_QP_REQ_RQ_CQID_SHIFT) &
+ OCRDMA_CREATE_QP_REQ_RQ_CQID_MASK;
+ qp->rq_cq = cq;
+
+ if (pd->dpp_enabled && attrs->cap.max_inline_data && pd->num_dpp_qp &&
+ (attrs->cap.max_inline_data <= dev->attr.max_inline_data))
+ ocrdma_set_create_qp_dpp_cmd(cmd, pd, qp, enable_dpp_cq,
+ dpp_cq_id);
+
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+ rsp = (struct ocrdma_create_qp_rsp *)cmd;
+ ocrdma_get_create_qp_rsp(rsp, qp, attrs, dpp_offset, dpp_credit_lmt);
+ qp->state = OCRDMA_QPS_RST;
+ kfree(cmd);
+ return 0;
+mbx_err:
+ if (qp->rq.va)
+ dma_free_coherent(&pdev->dev, qp->rq.len, qp->rq.va, qp->rq.pa);
+rq_err:
+ ocrdma_err("%s(%d) rq_err\n", __func__, dev->id);
+ dma_free_coherent(&pdev->dev, qp->sq.len, qp->sq.va, qp->sq.pa);
+sq_err:
+ ocrdma_err("%s(%d) sq_err\n", __func__, dev->id);
+ kfree(cmd);
+ return status;
+}
+
+int ocrdma_mbx_query_qp(struct ocrdma_dev *dev, struct ocrdma_qp *qp,
+ struct ocrdma_qp_params *param)
+{
+ int status = -ENOMEM;
+ struct ocrdma_query_qp *cmd;
+ struct ocrdma_query_qp_rsp *rsp;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_QUERY_QP, sizeof(*cmd));
+ if (!cmd)
+ return status;
+ cmd->qp_id = qp->id;
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+ rsp = (struct ocrdma_query_qp_rsp *)cmd;
+ memcpy(param, &rsp->params, sizeof(struct ocrdma_qp_params));
+mbx_err:
+ kfree(cmd);
+ return status;
+}
+
+int ocrdma_resolve_dgid(struct ocrdma_dev *dev, union ib_gid *dgid,
+ u8 *mac_addr)
+{
+ struct in6_addr in6;
+
+ memcpy(&in6, dgid, sizeof in6);
+ if (rdma_is_multicast_addr(&in6))
+ rdma_get_mcast_mac(&in6, mac_addr);
+ else if (rdma_link_local_addr(&in6))
+ rdma_get_ll_mac(&in6, mac_addr);
+ else {
+ ocrdma_err("%s() fail to resolve mac_addr.\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void ocrdma_set_av_params(struct ocrdma_qp *qp,
+ struct ocrdma_modify_qp *cmd,
+ struct ib_qp_attr *attrs)
+{
+ struct ib_ah_attr *ah_attr = &attrs->ah_attr;
+ union ib_gid sgid;
+ u32 vlan_id;
+ u8 mac_addr[6];
+ if ((ah_attr->ah_flags & IB_AH_GRH) == 0)
+ return;
+ cmd->params.tclass_sq_psn |=
+ (ah_attr->grh.traffic_class << OCRDMA_QP_PARAMS_TCLASS_SHIFT);
+ cmd->params.rnt_rc_sl_fl |=
+ (ah_attr->grh.flow_label & OCRDMA_QP_PARAMS_FLOW_LABEL_MASK);
+ cmd->params.hop_lmt_rq_psn |=
+ (ah_attr->grh.hop_limit << OCRDMA_QP_PARAMS_HOP_LMT_SHIFT);
+ cmd->flags |= OCRDMA_QP_PARA_FLOW_LBL_VALID;
+ memcpy(&cmd->params.dgid[0], &ah_attr->grh.dgid.raw[0],
+ sizeof(cmd->params.dgid));
+ ocrdma_query_gid(&qp->dev->ibdev, 1,
+ ah_attr->grh.sgid_index, &sgid);
+ qp->sgid_idx = ah_attr->grh.sgid_index;
+ memcpy(&cmd->params.sgid[0], &sgid.raw[0], sizeof(cmd->params.sgid));
+ ocrdma_resolve_dgid(qp->dev, &ah_attr->grh.dgid, &mac_addr[0]);
+ cmd->params.dmac_b0_to_b3 = mac_addr[0] | (mac_addr[1] << 8) |
+ (mac_addr[2] << 16) | (mac_addr[3] << 24);
+ /* convert them to LE format. */
+ ocrdma_cpu_to_le32(&cmd->params.dgid[0], sizeof(cmd->params.dgid));
+ ocrdma_cpu_to_le32(&cmd->params.sgid[0], sizeof(cmd->params.sgid));
+ cmd->params.vlan_dmac_b4_to_b5 = mac_addr[4] | (mac_addr[5] << 8);
+ vlan_id = rdma_get_vlan_id(&sgid);
+ if (vlan_id && (vlan_id < 0x1000)) {
+ cmd->params.vlan_dmac_b4_to_b5 |=
+ vlan_id << OCRDMA_QP_PARAMS_VLAN_SHIFT;
+ cmd->flags |= OCRDMA_QP_PARA_VLAN_EN_VALID;
+ }
+}
+
+static int ocrdma_set_qp_params(struct ocrdma_qp *qp,
+ struct ocrdma_modify_qp *cmd,
+ struct ib_qp_attr *attrs, int attr_mask,
+ enum ib_qp_state old_qps)
+{
+ int status = 0;
+ struct net_device *netdev = qp->dev->nic_info.netdev;
+ int eth_mtu = iboe_get_mtu(netdev->mtu);
+
+ if (attr_mask & IB_QP_PKEY_INDEX) {
+ cmd->params.path_mtu_pkey_indx |= (attrs->pkey_index &
+ OCRDMA_QP_PARAMS_PKEY_INDEX_MASK);
+ cmd->flags |= OCRDMA_QP_PARA_PKEY_VALID;
+ }
+ if (attr_mask & IB_QP_QKEY) {
+ qp->qkey = attrs->qkey;
+ cmd->params.qkey = attrs->qkey;
+ cmd->flags |= OCRDMA_QP_PARA_QKEY_VALID;
+ }
+ if (attr_mask & IB_QP_AV)
+ ocrdma_set_av_params(qp, cmd, attrs);
+ else if (qp->qp_type == IB_QPT_GSI || qp->qp_type == IB_QPT_UD) {
+ /* set the default mac address for UD, GSI QPs */
+ cmd->params.dmac_b0_to_b3 = qp->dev->nic_info.mac_addr[0] |
+ (qp->dev->nic_info.mac_addr[1] << 8) |
+ (qp->dev->nic_info.mac_addr[2] << 16) |
+ (qp->dev->nic_info.mac_addr[3] << 24);
+ cmd->params.vlan_dmac_b4_to_b5 = qp->dev->nic_info.mac_addr[4] |
+ (qp->dev->nic_info.mac_addr[5] << 8);
+ }
+ if ((attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY) &&
+ attrs->en_sqd_async_notify) {
+ cmd->params.max_sge_recv_flags |=
+ OCRDMA_QP_PARAMS_FLAGS_SQD_ASYNC;
+ cmd->flags |= OCRDMA_QP_PARA_DST_QPN_VALID;
+ }
+ if (attr_mask & IB_QP_DEST_QPN) {
+ cmd->params.ack_to_rnr_rtc_dest_qpn |= (attrs->dest_qp_num &
+ OCRDMA_QP_PARAMS_DEST_QPN_MASK);
+ cmd->flags |= OCRDMA_QP_PARA_DST_QPN_VALID;
+ }
+ if (attr_mask & IB_QP_PATH_MTU) {
+ if (ib_mtu_enum_to_int(eth_mtu) <
+ ib_mtu_enum_to_int(attrs->path_mtu)) {
+ status = -EINVAL;
+ goto pmtu_err;
+ }
+ cmd->params.path_mtu_pkey_indx |=
+ (ib_mtu_enum_to_int(attrs->path_mtu) <<
+ OCRDMA_QP_PARAMS_PATH_MTU_SHIFT) &
+ OCRDMA_QP_PARAMS_PATH_MTU_MASK;
+ cmd->flags |= OCRDMA_QP_PARA_PMTU_VALID;
+ }
+ if (attr_mask & IB_QP_TIMEOUT) {
+ cmd->params.ack_to_rnr_rtc_dest_qpn |= attrs->timeout <<
+ OCRDMA_QP_PARAMS_ACK_TIMEOUT_SHIFT;
+ cmd->flags |= OCRDMA_QP_PARA_ACK_TO_VALID;
+ }
+ if (attr_mask & IB_QP_RETRY_CNT) {
+ cmd->params.rnt_rc_sl_fl |= (attrs->retry_cnt <<
+ OCRDMA_QP_PARAMS_RETRY_CNT_SHIFT) &
+ OCRDMA_QP_PARAMS_RETRY_CNT_MASK;
+ cmd->flags |= OCRDMA_QP_PARA_RETRY_CNT_VALID;
+ }
+ if (attr_mask & IB_QP_MIN_RNR_TIMER) {
+ cmd->params.rnt_rc_sl_fl |= (attrs->min_rnr_timer <<
+ OCRDMA_QP_PARAMS_RNR_NAK_TIMER_SHIFT) &
+ OCRDMA_QP_PARAMS_RNR_NAK_TIMER_MASK;
+ cmd->flags |= OCRDMA_QP_PARA_RNT_VALID;
+ }
+ if (attr_mask & IB_QP_RNR_RETRY) {
+ cmd->params.ack_to_rnr_rtc_dest_qpn |= (attrs->rnr_retry <<
+ OCRDMA_QP_PARAMS_RNR_RETRY_CNT_SHIFT)
+ & OCRDMA_QP_PARAMS_RNR_RETRY_CNT_MASK;
+ cmd->flags |= OCRDMA_QP_PARA_RRC_VALID;
+ }
+ if (attr_mask & IB_QP_SQ_PSN) {
+ cmd->params.tclass_sq_psn |= (attrs->sq_psn & 0x00ffffff);
+ cmd->flags |= OCRDMA_QP_PARA_SQPSN_VALID;
+ }
+ if (attr_mask & IB_QP_RQ_PSN) {
+ cmd->params.hop_lmt_rq_psn |= (attrs->rq_psn & 0x00ffffff);
+ cmd->flags |= OCRDMA_QP_PARA_RQPSN_VALID;
+ }
+ if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
+ if (attrs->max_rd_atomic > qp->dev->attr.max_ord_per_qp) {
+ status = -EINVAL;
+ goto pmtu_err;
+ }
+ qp->max_ord = attrs->max_rd_atomic;
+ cmd->flags |= OCRDMA_QP_PARA_MAX_ORD_VALID;
+ }
+ if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
+ if (attrs->max_dest_rd_atomic > qp->dev->attr.max_ird_per_qp) {
+ status = -EINVAL;
+ goto pmtu_err;
+ }
+ qp->max_ird = attrs->max_dest_rd_atomic;
+ cmd->flags |= OCRDMA_QP_PARA_MAX_IRD_VALID;
+ }
+ cmd->params.max_ord_ird = (qp->max_ord <<
+ OCRDMA_QP_PARAMS_MAX_ORD_SHIFT) |
+ (qp->max_ird & OCRDMA_QP_PARAMS_MAX_IRD_MASK);
+pmtu_err:
+ return status;
+}
+
+int ocrdma_mbx_modify_qp(struct ocrdma_dev *dev, struct ocrdma_qp *qp,
+ struct ib_qp_attr *attrs, int attr_mask,
+ enum ib_qp_state old_qps)
+{
+ int status = -ENOMEM;
+ struct ocrdma_modify_qp *cmd;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_MODIFY_QP, sizeof(*cmd));
+ if (!cmd)
+ return status;
+
+ cmd->params.id = qp->id;
+ cmd->flags = 0;
+ if (attr_mask & IB_QP_STATE) {
+ cmd->params.max_sge_recv_flags |=
+ (get_ocrdma_qp_state(attrs->qp_state) <<
+ OCRDMA_QP_PARAMS_STATE_SHIFT) &
+ OCRDMA_QP_PARAMS_STATE_MASK;
+ cmd->flags |= OCRDMA_QP_PARA_QPS_VALID;
+ } else
+ cmd->params.max_sge_recv_flags |=
+ (qp->state << OCRDMA_QP_PARAMS_STATE_SHIFT) &
+ OCRDMA_QP_PARAMS_STATE_MASK;
+ status = ocrdma_set_qp_params(qp, cmd, attrs, attr_mask, old_qps);
+ if (status)
+ goto mbx_err;
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+
+mbx_err:
+ kfree(cmd);
+ return status;
+}
+
+int ocrdma_mbx_destroy_qp(struct ocrdma_dev *dev, struct ocrdma_qp *qp)
+{
+ int status = -ENOMEM;
+ struct ocrdma_destroy_qp *cmd;
+ struct pci_dev *pdev = dev->nic_info.pdev;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DELETE_QP, sizeof(*cmd));
+ if (!cmd)
+ return status;
+ cmd->qp_id = qp->id;
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+
+mbx_err:
+ kfree(cmd);
+ if (qp->sq.va)
+ dma_free_coherent(&pdev->dev, qp->sq.len, qp->sq.va, qp->sq.pa);
+ if (!qp->srq && qp->rq.va)
+ dma_free_coherent(&pdev->dev, qp->rq.len, qp->rq.va, qp->rq.pa);
+ if (qp->dpp_enabled)
+ qp->pd->num_dpp_qp++;
+ return status;
+}
+
+int ocrdma_mbx_create_srq(struct ocrdma_srq *srq,
+ struct ib_srq_init_attr *srq_attr,
+ struct ocrdma_pd *pd)
+{
+ int status = -ENOMEM;
+ int hw_pages, hw_page_size;
+ int len;
+ struct ocrdma_create_srq_rsp *rsp;
+ struct ocrdma_create_srq *cmd;
+ dma_addr_t pa;
+ struct ocrdma_dev *dev = srq->dev;
+ struct pci_dev *pdev = dev->nic_info.pdev;
+ u32 max_rqe_allocated;
+
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_CREATE_SRQ, sizeof(*cmd));
+ if (!cmd)
+ return status;
+
+ cmd->pgsz_pdid = pd->id & OCRDMA_CREATE_SRQ_PD_ID_MASK;
+ max_rqe_allocated = srq_attr->attr.max_wr + 1;
+ status = ocrdma_build_q_conf(&max_rqe_allocated,
+ dev->attr.rqe_size,
+ &hw_pages, &hw_page_size);
+ if (status) {
+ ocrdma_err("%s() req. max_wr=0x%x\n", __func__,
+ srq_attr->attr.max_wr);
+ status = -EINVAL;
+ goto ret;
+ }
+ len = hw_pages * hw_page_size;
+ srq->rq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
+ if (!srq->rq.va) {
+ status = -ENOMEM;
+ goto ret;
+ }
+ ocrdma_build_q_pages(&cmd->rq_addr[0], hw_pages, pa, hw_page_size);
+
+ srq->rq.entry_size = dev->attr.rqe_size;
+ srq->rq.pa = pa;
+ srq->rq.len = len;
+ srq->rq.max_cnt = max_rqe_allocated;
+
+ cmd->max_sge_rqe = ilog2(max_rqe_allocated);
+ cmd->max_sge_rqe |= srq_attr->attr.max_sge <<
+ OCRDMA_CREATE_SRQ_MAX_SGE_RECV_SHIFT;
+
+ cmd->pgsz_pdid |= (ilog2(hw_page_size / OCRDMA_MIN_Q_PAGE_SIZE)
+ << OCRDMA_CREATE_SRQ_PG_SZ_SHIFT);
+ cmd->pages_rqe_sz |= (dev->attr.rqe_size
+ << OCRDMA_CREATE_SRQ_RQE_SIZE_SHIFT)
+ & OCRDMA_CREATE_SRQ_RQE_SIZE_MASK;
+ cmd->pages_rqe_sz |= hw_pages << OCRDMA_CREATE_SRQ_NUM_RQ_PAGES_SHIFT;
+
+ status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
+ if (status)
+ goto mbx_err;
+ rsp = (struct ocrdma_create_srq_rsp *)cmd;
+ srq->id = rsp->id;
+ srq->rq.dbid = rsp->id;
+ max_rqe_allocated = ((rsp->max_sge_rqe_allocated &
+ OCRDMA_CREATE_SRQ_RSP_MAX_RQE_ALLOCATED_MASK) >>
+ OCRDMA_CREATE_SRQ_RSP_MAX_RQE_ALLOCATED_SHIFT);
+ max_rqe_allocated = (1 << max_rqe_allocated);
+ srq->rq.max_cnt = max_rqe_allocated;
+ srq->rq.max_wqe_idx = max_rqe_allocated - 1;
+ srq->rq.max_sges = (rsp->max_sge_rqe_allocated &
+ OCRDMA_CREATE_SRQ_RSP_MAX_SGE_RECV_ALLOCATED_MASK) >>
+ OCRDMA_CREATE_SRQ_RSP_MAX_SGE_RECV_ALLOCATED_SHIFT;
+ goto ret;
+mbx_err:
+ dma_free_coherent(&pdev->dev, srq->rq.len, srq->rq.va, pa);
+ret:
+ kfree(cmd);
+ return status;
+}
+
+int ocrdma_mbx_modify_srq(struct ocrdma_srq *srq, struct ib_srq_attr *srq_attr)
+{
+ int status = -ENOMEM;
+ struct ocrdma_modify_srq *cmd;
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_CREATE_SRQ, sizeof(*cmd));
+ if (!cmd)
+ return status;
+ cmd->id = srq->id;
+ cmd->limit_max_rqe |= srq_attr->srq_limit <<
+ OCRDMA_MODIFY_SRQ_LIMIT_SHIFT;
+ status = ocrdma_mbx_cmd(srq->dev, (struct ocrdma_mqe *)cmd);
+ kfree(cmd);
+ return status;
+}
+
+int ocrdma_mbx_query_srq(struct ocrdma_srq *srq, struct ib_srq_attr *srq_attr)
+{
+ int status = -ENOMEM;
+ struct ocrdma_query_srq *cmd;
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_CREATE_SRQ, sizeof(*cmd));
+ if (!cmd)
+ return status;
+ cmd->id = srq->rq.dbid;
+ status = ocrdma_mbx_cmd(srq->dev, (struct ocrdma_mqe *)cmd);
+ if (status == 0) {
+ struct ocrdma_query_srq_rsp *rsp =
+ (struct ocrdma_query_srq_rsp *)cmd;
+ srq_attr->max_sge =
+ rsp->srq_lmt_max_sge &
+ OCRDMA_QUERY_SRQ_RSP_MAX_SGE_RECV_MASK;
+ srq_attr->max_wr =
+ rsp->max_rqe_pdid >> OCRDMA_QUERY_SRQ_RSP_MAX_RQE_SHIFT;
+ srq_attr->srq_limit = rsp->srq_lmt_max_sge >>
+ OCRDMA_QUERY_SRQ_RSP_SRQ_LIMIT_SHIFT;
+ }
+ kfree(cmd);
+ return status;
+}
+
+int ocrdma_mbx_destroy_srq(struct ocrdma_dev *dev, struct ocrdma_srq *srq)
+{
+ int status = -ENOMEM;
+ struct ocrdma_destroy_srq *cmd;
+ struct pci_dev *pdev = dev->nic_info.pdev;
+ cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DELETE_SRQ, sizeof(*cmd));
+ if (!cmd)
+ return status;
+ cmd->id = srq->id;
+ status = ocrdma_mbx_cmd(srq->dev, (struct ocrdma_mqe *)cmd);
+ if (srq->rq.va)
+ dma_free_coherent(&pdev->dev, srq->rq.len,
+ srq->rq.va, srq->rq.pa);
+ kfree(cmd);
+ return status;
+}
+
+int ocrdma_alloc_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah)
+{
+ int i;
+ int status = -EINVAL;
+ struct ocrdma_av *av;
+ unsigned long flags;
+
+ av = dev->av_tbl.va;
+ spin_lock_irqsave(&dev->av_tbl.lock, flags);
+ for (i = 0; i < dev->av_tbl.num_ah; i++) {
+ if (av->valid == 0) {
+ av->valid = OCRDMA_AV_VALID;
+ ah->av = av;
+ ah->id = i;
+ status = 0;
+ break;
+ }
+ av++;
+ }
+ if (i == dev->av_tbl.num_ah)
+ status = -EAGAIN;
+ spin_unlock_irqrestore(&dev->av_tbl.lock, flags);
+ return status;
+}
+
+int ocrdma_free_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&dev->av_tbl.lock, flags);
+ ah->av->valid = 0;
+ spin_unlock_irqrestore(&dev->av_tbl.lock, flags);
+ return 0;
+}
+
+static int ocrdma_create_mq_eq(struct ocrdma_dev *dev)
+{
+ int status;
+ int irq;
+ unsigned long flags = 0;
+ int num_eq = 0;
+
+ if (dev->nic_info.intr_mode == BE_INTERRUPT_MODE_INTX)
+ flags = IRQF_SHARED;
+ else {
+ num_eq = dev->nic_info.msix.num_vectors -
+ dev->nic_info.msix.start_vector;
+ /* minimum two vectors/eq are required for rdma to work.
+ * one for control path and one for data path.
+ */
+ if (num_eq < 2)
+ return -EBUSY;
+ }
+
+ status = ocrdma_create_eq(dev, &dev->meq, OCRDMA_EQ_LEN);
+ if (status)
+ return status;
+ sprintf(dev->meq.irq_name, "ocrdma_mq%d", dev->id);
+ irq = ocrdma_get_irq(dev, &dev->meq);
+ status = request_irq(irq, ocrdma_irq_handler, flags, dev->meq.irq_name,
+ &dev->meq);
+ if (status)
+ _ocrdma_destroy_eq(dev, &dev->meq);
+ return status;
+}
+
+static int ocrdma_create_qp_eqs(struct ocrdma_dev *dev)
+{
+ int num_eq, i, status = 0;
+ int irq;
+ unsigned long flags = 0;
+
+ num_eq = dev->nic_info.msix.num_vectors -
+ dev->nic_info.msix.start_vector;
+ if (dev->nic_info.intr_mode == BE_INTERRUPT_MODE_INTX) {
+ num_eq = 1;
+ flags = IRQF_SHARED;
+ } else
+ num_eq = min_t(u32, num_eq, num_online_cpus());
+ dev->qp_eq_tbl = kzalloc(sizeof(struct ocrdma_eq) * num_eq, GFP_KERNEL);
+ if (!dev->qp_eq_tbl)
+ return -ENOMEM;
+
+ for (i = 0; i < num_eq; i++) {
+ status = ocrdma_create_eq(dev, &dev->qp_eq_tbl[i],
+ OCRDMA_EQ_LEN);
+ if (status) {
+ status = -EINVAL;
+ break;
+ }
+ sprintf(dev->qp_eq_tbl[i].irq_name, "ocrdma_qp%d-%d",
+ dev->id, i);
+ irq = ocrdma_get_irq(dev, &dev->qp_eq_tbl[i]);
+ status = request_irq(irq, ocrdma_irq_handler, flags,
+ dev->qp_eq_tbl[i].irq_name,
+ &dev->qp_eq_tbl[i]);
+ if (status) {
+ _ocrdma_destroy_eq(dev, &dev->qp_eq_tbl[i]);
+ status = -EINVAL;
+ break;
+ }
+ dev->eq_cnt += 1;
+ }
+ /* one eq is sufficient for data path to work */
+ if (dev->eq_cnt >= 1)
+ return 0;
+ if (status)
+ ocrdma_destroy_qp_eqs(dev);
+ return status;
+}
+
+int ocrdma_init_hw(struct ocrdma_dev *dev)
+{
+ int status;
+ /* set up control path eq */
+ status = ocrdma_create_mq_eq(dev);
+ if (status)
+ return status;
+ /* set up data path eq */
+ status = ocrdma_create_qp_eqs(dev);
+ if (status)
+ goto qpeq_err;
+ status = ocrdma_create_mq(dev);
+ if (status)
+ goto mq_err;
+ status = ocrdma_mbx_query_fw_config(dev);
+ if (status)
+ goto conf_err;
+ status = ocrdma_mbx_query_dev(dev);
+ if (status)
+ goto conf_err;
+ status = ocrdma_mbx_query_fw_ver(dev);
+ if (status)
+ goto conf_err;
+ status = ocrdma_mbx_create_ah_tbl(dev);
+ if (status)
+ goto conf_err;
+ return 0;
+
+conf_err:
+ ocrdma_destroy_mq(dev);
+mq_err:
+ ocrdma_destroy_qp_eqs(dev);
+qpeq_err:
+ ocrdma_destroy_eq(dev, &dev->meq);
+ ocrdma_err("%s() status=%d\n", __func__, status);
+ return status;
+}
+
+void ocrdma_cleanup_hw(struct ocrdma_dev *dev)
+{
+ ocrdma_mbx_delete_ah_tbl(dev);
+
+ /* cleanup the data path eqs */
+ ocrdma_destroy_qp_eqs(dev);
+
+ /* cleanup the control path */
+ ocrdma_destroy_mq(dev);
+ ocrdma_destroy_eq(dev, &dev->meq);
+}
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.h b/drivers/infiniband/hw/ocrdma/ocrdma_hw.h
new file mode 100644
index 000000000000..be5db77404db
--- /dev/null
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.h
@@ -0,0 +1,132 @@
+/*******************************************************************
+ * This file is part of the Emulex RoCE Device Driver for *
+ * RoCE (RDMA over Converged Ethernet) CNA Adapters. *
+ * Copyright (C) 2008-2012 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.emulex.com *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of version 2 of the GNU General *
+ * Public License as published by the Free Software Foundation. *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID. See the GNU General Public License for *
+ * more details, a copy of which can be found in the file COPYING *
+ * included with this package. *
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ *******************************************************************/
+
+#ifndef __OCRDMA_HW_H__
+#define __OCRDMA_HW_H__
+
+#include "ocrdma_sli.h"
+
+static inline void ocrdma_cpu_to_le32(void *dst, u32 len)
+{
+#ifdef __BIG_ENDIAN
+ int i = 0;
+ u32 *src_ptr = dst;
+ u32 *dst_ptr = dst;
+ for (; i < (len / 4); i++)
+ *(dst_ptr + i) = cpu_to_le32p(src_ptr + i);
+#endif
+}
+
+static inline void ocrdma_le32_to_cpu(void *dst, u32 len)
+{
+#ifdef __BIG_ENDIAN
+ int i = 0;
+ u32 *src_ptr = dst;
+ u32 *dst_ptr = dst;
+ for (; i < (len / sizeof(u32)); i++)
+ *(dst_ptr + i) = le32_to_cpu(*(src_ptr + i));
+#endif
+}
+
+static inline void ocrdma_copy_cpu_to_le32(void *dst, void *src, u32 len)
+{
+#ifdef __BIG_ENDIAN
+ int i = 0;
+ u32 *src_ptr = src;
+ u32 *dst_ptr = dst;
+ for (; i < (len / sizeof(u32)); i++)
+ *(dst_ptr + i) = cpu_to_le32p(src_ptr + i);
+#else
+ memcpy(dst, src, len);
+#endif
+}
+
+static inline void ocrdma_copy_le32_to_cpu(void *dst, void *src, u32 len)
+{
+#ifdef __BIG_ENDIAN
+ int i = 0;
+ u32 *src_ptr = src;
+ u32 *dst_ptr = dst;
+ for (; i < len / sizeof(u32); i++)
+ *(dst_ptr + i) = le32_to_cpu(*(src_ptr + i));
+#else
+ memcpy(dst, src, len);
+#endif
+}
+
+int ocrdma_init_hw(struct ocrdma_dev *);
+void ocrdma_cleanup_hw(struct ocrdma_dev *);
+
+enum ib_qp_state get_ibqp_state(enum ocrdma_qp_state qps);
+void ocrdma_ring_cq_db(struct ocrdma_dev *, u16 cq_id, bool armed,
+ bool solicited, u16 cqe_popped);
+
+/* verbs specific mailbox commands */
+int ocrdma_query_config(struct ocrdma_dev *,
+ struct ocrdma_mbx_query_config *config);
+int ocrdma_resolve_dgid(struct ocrdma_dev *, union ib_gid *dgid, u8 *mac_addr);
+
+int ocrdma_mbx_alloc_pd(struct ocrdma_dev *, struct ocrdma_pd *);
+int ocrdma_mbx_dealloc_pd(struct ocrdma_dev *, struct ocrdma_pd *);
+
+int ocrdma_mbx_alloc_lkey(struct ocrdma_dev *, struct ocrdma_hw_mr *hwmr,
+ u32 pd_id, int addr_check);
+int ocrdma_mbx_dealloc_lkey(struct ocrdma_dev *, int fmr, u32 lkey);
+
+int ocrdma_reg_mr(struct ocrdma_dev *, struct ocrdma_hw_mr *hwmr,
+ u32 pd_id, int acc);
+int ocrdma_mbx_create_cq(struct ocrdma_dev *, struct ocrdma_cq *,
+ int entries, int dpp_cq);
+int ocrdma_mbx_destroy_cq(struct ocrdma_dev *, struct ocrdma_cq *);
+
+int ocrdma_mbx_create_qp(struct ocrdma_qp *, struct ib_qp_init_attr *attrs,
+ u8 enable_dpp_cq, u16 dpp_cq_id, u16 *dpp_offset,
+ u16 *dpp_credit_lmt);
+int ocrdma_mbx_modify_qp(struct ocrdma_dev *, struct ocrdma_qp *,
+ struct ib_qp_attr *attrs, int attr_mask,
+ enum ib_qp_state old_qps);
+int ocrdma_mbx_query_qp(struct ocrdma_dev *, struct ocrdma_qp *,
+ struct ocrdma_qp_params *param);
+int ocrdma_mbx_destroy_qp(struct ocrdma_dev *, struct ocrdma_qp *);
+
+int ocrdma_mbx_create_srq(struct ocrdma_srq *,
+ struct ib_srq_init_attr *,
+ struct ocrdma_pd *);
+int ocrdma_mbx_modify_srq(struct ocrdma_srq *, struct ib_srq_attr *);
+int ocrdma_mbx_query_srq(struct ocrdma_srq *, struct ib_srq_attr *);
+int ocrdma_mbx_destroy_srq(struct ocrdma_dev *, struct ocrdma_srq *);
+
+int ocrdma_alloc_av(struct ocrdma_dev *, struct ocrdma_ah *);
+int ocrdma_free_av(struct ocrdma_dev *, struct ocrdma_ah *);
+
+int ocrdma_qp_state_machine(struct ocrdma_qp *, enum ib_qp_state new_state,
+ enum ib_qp_state *old_ib_state);
+bool ocrdma_is_qp_in_sq_flushlist(struct ocrdma_cq *, struct ocrdma_qp *);
+bool ocrdma_is_qp_in_rq_flushlist(struct ocrdma_cq *, struct ocrdma_qp *);
+void ocrdma_flush_qp(struct ocrdma_qp *);
+
+#endif /* __OCRDMA_HW_H__ */
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
new file mode 100644
index 000000000000..a20d16eaae71
--- /dev/null
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
@@ -0,0 +1,577 @@
+/*******************************************************************
+ * This file is part of the Emulex RoCE Device Driver for *
+ * RoCE (RDMA over Converged Ethernet) adapters. *
+ * Copyright (C) 2008-2012 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.emulex.com *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of version 2 of the GNU General *
+ * Public License as published by the Free Software Foundation. *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID. See the GNU General Public License for *
+ * more details, a copy of which can be found in the file COPYING *
+ * included with this package. *
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ *******************************************************************/
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/idr.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_addr.h>
+
+#include <linux/netdevice.h>
+#include <net/addrconf.h>
+
+#include "ocrdma.h"
+#include "ocrdma_verbs.h"
+#include "ocrdma_ah.h"
+#include "be_roce.h"
+#include "ocrdma_hw.h"
+
+MODULE_VERSION(OCRDMA_ROCE_DEV_VERSION);
+MODULE_DESCRIPTION("Emulex RoCE HCA Driver");
+MODULE_AUTHOR("Emulex Corporation");
+MODULE_LICENSE("GPL");
+
+static LIST_HEAD(ocrdma_dev_list);
+static DEFINE_SPINLOCK(ocrdma_devlist_lock);
+static DEFINE_IDR(ocrdma_dev_id);
+
+static union ib_gid ocrdma_zero_sgid;
+
+static int ocrdma_get_instance(void)
+{
+ int instance = 0;
+
+ /* Assign an unused number */
+ if (!idr_pre_get(&ocrdma_dev_id, GFP_KERNEL))
+ return -1;
+ if (idr_get_new(&ocrdma_dev_id, NULL, &instance))
+ return -1;
+ return instance;
+}
+
+void ocrdma_get_guid(struct ocrdma_dev *dev, u8 *guid)
+{
+ u8 mac_addr[6];
+
+ memcpy(&mac_addr[0], &dev->nic_info.mac_addr[0], ETH_ALEN);
+ guid[0] = mac_addr[0] ^ 2;
+ guid[1] = mac_addr[1];
+ guid[2] = mac_addr[2];
+ guid[3] = 0xff;
+ guid[4] = 0xfe;
+ guid[5] = mac_addr[3];
+ guid[6] = mac_addr[4];
+ guid[7] = mac_addr[5];
+}
+
+static void ocrdma_build_sgid_mac(union ib_gid *sgid, unsigned char *mac_addr,
+ bool is_vlan, u16 vlan_id)
+{
+ sgid->global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
+ sgid->raw[8] = mac_addr[0] ^ 2;
+ sgid->raw[9] = mac_addr[1];
+ sgid->raw[10] = mac_addr[2];
+ if (is_vlan) {
+ sgid->raw[11] = vlan_id >> 8;
+ sgid->raw[12] = vlan_id & 0xff;
+ } else {
+ sgid->raw[11] = 0xff;
+ sgid->raw[12] = 0xfe;
+ }
+ sgid->raw[13] = mac_addr[3];
+ sgid->raw[14] = mac_addr[4];
+ sgid->raw[15] = mac_addr[5];
+}
+
+static void ocrdma_add_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr,
+ bool is_vlan, u16 vlan_id)
+{
+ int i;
+ bool found = false;
+ union ib_gid new_sgid;
+ int free_idx = OCRDMA_MAX_SGID;
+ unsigned long flags;
+
+ memset(&ocrdma_zero_sgid, 0, sizeof(union ib_gid));
+
+ ocrdma_build_sgid_mac(&new_sgid, mac_addr, is_vlan, vlan_id);
+
+ spin_lock_irqsave(&dev->sgid_lock, flags);
+ for (i = 0; i < OCRDMA_MAX_SGID; i++) {
+ if (!memcmp(&dev->sgid_tbl[i], &ocrdma_zero_sgid,
+ sizeof(union ib_gid))) {
+ /* found free entry */
+ if (!found) {
+ free_idx = i;
+ found = true;
+ break;
+ }
+ } else if (!memcmp(&dev->sgid_tbl[i], &new_sgid,
+ sizeof(union ib_gid))) {
+ /* entry already present, no addition is required. */
+ spin_unlock_irqrestore(&dev->sgid_lock, flags);
+ return;
+ }
+ }
+ /* if entry doesn't exist and if table has some space, add entry */
+ if (found)
+ memcpy(&dev->sgid_tbl[free_idx], &new_sgid,
+ sizeof(union ib_gid));
+ spin_unlock_irqrestore(&dev->sgid_lock, flags);
+}
+
+static bool ocrdma_del_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr,
+ bool is_vlan, u16 vlan_id)
+{
+ int found = false;
+ int i;
+ union ib_gid sgid;
+ unsigned long flags;
+
+ ocrdma_build_sgid_mac(&sgid, mac_addr, is_vlan, vlan_id);
+
+ spin_lock_irqsave(&dev->sgid_lock, flags);
+ /* first is default sgid, which cannot be deleted. */
+ for (i = 1; i < OCRDMA_MAX_SGID; i++) {
+ if (!memcmp(&dev->sgid_tbl[i], &sgid, sizeof(union ib_gid))) {
+ /* found matching entry */
+ memset(&dev->sgid_tbl[i], 0, sizeof(union ib_gid));
+ found = true;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&dev->sgid_lock, flags);
+ return found;
+}
+
+static void ocrdma_add_default_sgid(struct ocrdma_dev *dev)
+{
+ /* GID Index 0 - Invariant manufacturer-assigned EUI-64 */
+ union ib_gid *sgid = &dev->sgid_tbl[0];
+
+ sgid->global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
+ ocrdma_get_guid(dev, &sgid->raw[8]);
+}
+
+static int ocrdma_build_sgid_tbl(struct ocrdma_dev *dev)
+{
+ struct net_device *netdev, *tmp;
+ u16 vlan_id;
+ bool is_vlan;
+
+ netdev = dev->nic_info.netdev;
+
+ ocrdma_add_default_sgid(dev);
+
+ rcu_read_lock();
+ for_each_netdev_rcu(&init_net, tmp) {
+ if (netdev == tmp || vlan_dev_real_dev(tmp) == netdev) {
+ if (!netif_running(tmp) || !netif_oper_up(tmp))
+ continue;
+ if (netdev != tmp) {
+ vlan_id = vlan_dev_vlan_id(tmp);
+ is_vlan = true;
+ } else {
+ is_vlan = false;
+ vlan_id = 0;
+ tmp = netdev;
+ }
+ ocrdma_add_sgid(dev, tmp->dev_addr, is_vlan, vlan_id);
+ }
+ }
+ rcu_read_unlock();
+ return 0;
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+
+static int ocrdma_inet6addr_event(struct notifier_block *notifier,
+ unsigned long event, void *ptr)
+{
+ struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
+ struct net_device *event_netdev = ifa->idev->dev;
+ struct net_device *netdev = NULL;
+ struct ib_event gid_event;
+ struct ocrdma_dev *dev;
+ bool found = false;
+ bool is_vlan = false;
+ u16 vid = 0;
+
+ netdev = vlan_dev_real_dev(event_netdev);
+ if (netdev != event_netdev) {
+ is_vlan = true;
+ vid = vlan_dev_vlan_id(event_netdev);
+ }
+ rcu_read_lock();
+ list_for_each_entry_rcu(dev, &ocrdma_dev_list, entry) {
+ if (dev->nic_info.netdev == netdev) {
+ found = true;
+ break;
+ }
+ }
+ rcu_read_unlock();
+
+ if (!found)
+ return NOTIFY_DONE;
+ if (!rdma_link_local_addr((struct in6_addr *)&ifa->addr))
+ return NOTIFY_DONE;
+
+ mutex_lock(&dev->dev_lock);
+ switch (event) {
+ case NETDEV_UP:
+ ocrdma_add_sgid(dev, netdev->dev_addr, is_vlan, vid);
+ break;
+ case NETDEV_DOWN:
+ found = ocrdma_del_sgid(dev, netdev->dev_addr, is_vlan, vid);
+ if (found) {
+ /* found the matching entry, notify
+ * the consumers about it
+ */
+ gid_event.device = &dev->ibdev;
+ gid_event.element.port_num = 1;
+ gid_event.event = IB_EVENT_GID_CHANGE;
+ ib_dispatch_event(&gid_event);
+ }
+ break;
+ default:
+ break;
+ }
+ mutex_unlock(&dev->dev_lock);
+ return NOTIFY_OK;
+}
+
+static struct notifier_block ocrdma_inet6addr_notifier = {
+ .notifier_call = ocrdma_inet6addr_event
+};
+
+#endif /* IPV6 */
+
+static enum rdma_link_layer ocrdma_link_layer(struct ib_device *device,
+ u8 port_num)
+{
+ return IB_LINK_LAYER_ETHERNET;
+}
+
+static int ocrdma_register_device(struct ocrdma_dev *dev)
+{
+ strlcpy(dev->ibdev.name, "ocrdma%d", IB_DEVICE_NAME_MAX);
+ ocrdma_get_guid(dev, (u8 *)&dev->ibdev.node_guid);
+ memcpy(dev->ibdev.node_desc, OCRDMA_NODE_DESC,
+ sizeof(OCRDMA_NODE_DESC));
+ dev->ibdev.owner = THIS_MODULE;
+ dev->ibdev.uverbs_cmd_mask =
+ OCRDMA_UVERBS(GET_CONTEXT) |
+ OCRDMA_UVERBS(QUERY_DEVICE) |
+ OCRDMA_UVERBS(QUERY_PORT) |
+ OCRDMA_UVERBS(ALLOC_PD) |
+ OCRDMA_UVERBS(DEALLOC_PD) |
+ OCRDMA_UVERBS(REG_MR) |
+ OCRDMA_UVERBS(DEREG_MR) |
+ OCRDMA_UVERBS(CREATE_COMP_CHANNEL) |
+ OCRDMA_UVERBS(CREATE_CQ) |
+ OCRDMA_UVERBS(RESIZE_CQ) |
+ OCRDMA_UVERBS(DESTROY_CQ) |
+ OCRDMA_UVERBS(REQ_NOTIFY_CQ) |
+ OCRDMA_UVERBS(CREATE_QP) |
+ OCRDMA_UVERBS(MODIFY_QP) |
+ OCRDMA_UVERBS(QUERY_QP) |
+ OCRDMA_UVERBS(DESTROY_QP) |
+ OCRDMA_UVERBS(POLL_CQ) |
+ OCRDMA_UVERBS(POST_SEND) |
+ OCRDMA_UVERBS(POST_RECV);
+
+ dev->ibdev.uverbs_cmd_mask |=
+ OCRDMA_UVERBS(CREATE_AH) |
+ OCRDMA_UVERBS(MODIFY_AH) |
+ OCRDMA_UVERBS(QUERY_AH) |
+ OCRDMA_UVERBS(DESTROY_AH);
+
+ dev->ibdev.node_type = RDMA_NODE_IB_CA;
+ dev->ibdev.phys_port_cnt = 1;
+ dev->ibdev.num_comp_vectors = 1;
+
+ /* mandatory verbs. */
+ dev->ibdev.query_device = ocrdma_query_device;
+ dev->ibdev.query_port = ocrdma_query_port;
+ dev->ibdev.modify_port = ocrdma_modify_port;
+ dev->ibdev.query_gid = ocrdma_query_gid;
+ dev->ibdev.get_link_layer = ocrdma_link_layer;
+ dev->ibdev.alloc_pd = ocrdma_alloc_pd;
+ dev->ibdev.dealloc_pd = ocrdma_dealloc_pd;
+
+ dev->ibdev.create_cq = ocrdma_create_cq;
+ dev->ibdev.destroy_cq = ocrdma_destroy_cq;
+ dev->ibdev.resize_cq = ocrdma_resize_cq;
+
+ dev->ibdev.create_qp = ocrdma_create_qp;
+ dev->ibdev.modify_qp = ocrdma_modify_qp;
+ dev->ibdev.query_qp = ocrdma_query_qp;
+ dev->ibdev.destroy_qp = ocrdma_destroy_qp;
+
+ dev->ibdev.query_pkey = ocrdma_query_pkey;
+ dev->ibdev.create_ah = ocrdma_create_ah;
+ dev->ibdev.destroy_ah = ocrdma_destroy_ah;
+ dev->ibdev.query_ah = ocrdma_query_ah;
+ dev->ibdev.modify_ah = ocrdma_modify_ah;
+
+ dev->ibdev.poll_cq = ocrdma_poll_cq;
+ dev->ibdev.post_send = ocrdma_post_send;
+ dev->ibdev.post_recv = ocrdma_post_recv;
+ dev->ibdev.req_notify_cq = ocrdma_arm_cq;
+
+ dev->ibdev.get_dma_mr = ocrdma_get_dma_mr;
+ dev->ibdev.dereg_mr = ocrdma_dereg_mr;
+ dev->ibdev.reg_user_mr = ocrdma_reg_user_mr;
+
+ /* mandatory to support user space verbs consumer. */
+ dev->ibdev.alloc_ucontext = ocrdma_alloc_ucontext;
+ dev->ibdev.dealloc_ucontext = ocrdma_dealloc_ucontext;
+ dev->ibdev.mmap = ocrdma_mmap;
+ dev->ibdev.dma_device = &dev->nic_info.pdev->dev;
+
+ dev->ibdev.process_mad = ocrdma_process_mad;
+
+ if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) {
+ dev->ibdev.uverbs_cmd_mask |=
+ OCRDMA_UVERBS(CREATE_SRQ) |
+ OCRDMA_UVERBS(MODIFY_SRQ) |
+ OCRDMA_UVERBS(QUERY_SRQ) |
+ OCRDMA_UVERBS(DESTROY_SRQ) |
+ OCRDMA_UVERBS(POST_SRQ_RECV);
+
+ dev->ibdev.create_srq = ocrdma_create_srq;
+ dev->ibdev.modify_srq = ocrdma_modify_srq;
+ dev->ibdev.query_srq = ocrdma_query_srq;
+ dev->ibdev.destroy_srq = ocrdma_destroy_srq;
+ dev->ibdev.post_srq_recv = ocrdma_post_srq_recv;
+ }
+ return ib_register_device(&dev->ibdev, NULL);
+}
+
+static int ocrdma_alloc_resources(struct ocrdma_dev *dev)
+{
+ mutex_init(&dev->dev_lock);
+ dev->sgid_tbl = kzalloc(sizeof(union ib_gid) *
+ OCRDMA_MAX_SGID, GFP_KERNEL);
+ if (!dev->sgid_tbl)
+ goto alloc_err;
+ spin_lock_init(&dev->sgid_lock);
+
+ dev->cq_tbl = kzalloc(sizeof(struct ocrdma_cq *) *
+ OCRDMA_MAX_CQ, GFP_KERNEL);
+ if (!dev->cq_tbl)
+ goto alloc_err;
+
+ if (dev->attr.max_qp) {
+ dev->qp_tbl = kzalloc(sizeof(struct ocrdma_qp *) *
+ OCRDMA_MAX_QP, GFP_KERNEL);
+ if (!dev->qp_tbl)
+ goto alloc_err;
+ }
+ spin_lock_init(&dev->av_tbl.lock);
+ spin_lock_init(&dev->flush_q_lock);
+ return 0;
+alloc_err:
+ ocrdma_err("%s(%d) error.\n", __func__, dev->id);
+ return -ENOMEM;
+}
+
+static void ocrdma_free_resources(struct ocrdma_dev *dev)
+{
+ kfree(dev->qp_tbl);
+ kfree(dev->cq_tbl);
+ kfree(dev->sgid_tbl);
+}
+
+static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info)
+{
+ int status = 0;
+ struct ocrdma_dev *dev;
+
+ dev = (struct ocrdma_dev *)ib_alloc_device(sizeof(struct ocrdma_dev));
+ if (!dev) {
+ ocrdma_err("Unable to allocate ib device\n");
+ return NULL;
+ }
+ dev->mbx_cmd = kzalloc(sizeof(struct ocrdma_mqe_emb_cmd), GFP_KERNEL);
+ if (!dev->mbx_cmd)
+ goto idr_err;
+
+ memcpy(&dev->nic_info, dev_info, sizeof(*dev_info));
+ dev->id = ocrdma_get_instance();
+ if (dev->id < 0)
+ goto idr_err;
+
+ status = ocrdma_init_hw(dev);
+ if (status)
+ goto init_err;
+
+ status = ocrdma_alloc_resources(dev);
+ if (status)
+ goto alloc_err;
+
+ status = ocrdma_build_sgid_tbl(dev);
+ if (status)
+ goto alloc_err;
+
+ status = ocrdma_register_device(dev);
+ if (status)
+ goto alloc_err;
+
+ spin_lock(&ocrdma_devlist_lock);
+ list_add_tail_rcu(&dev->entry, &ocrdma_dev_list);
+ spin_unlock(&ocrdma_devlist_lock);
+ return dev;
+
+alloc_err:
+ ocrdma_free_resources(dev);
+ ocrdma_cleanup_hw(dev);
+init_err:
+ idr_remove(&ocrdma_dev_id, dev->id);
+idr_err:
+ kfree(dev->mbx_cmd);
+ ib_dealloc_device(&dev->ibdev);
+ ocrdma_err("%s() leaving. ret=%d\n", __func__, status);
+ return NULL;
+}
+
+static void ocrdma_remove_free(struct rcu_head *rcu)
+{
+ struct ocrdma_dev *dev = container_of(rcu, struct ocrdma_dev, rcu);
+
+ ocrdma_free_resources(dev);
+ ocrdma_cleanup_hw(dev);
+
+ idr_remove(&ocrdma_dev_id, dev->id);
+ kfree(dev->mbx_cmd);
+ ib_dealloc_device(&dev->ibdev);
+}
+
+static void ocrdma_remove(struct ocrdma_dev *dev)
+{
+ /* first unregister with stack to stop all the active traffic
+ * of the registered clients.
+ */
+ ib_unregister_device(&dev->ibdev);
+
+ spin_lock(&ocrdma_devlist_lock);
+ list_del_rcu(&dev->entry);
+ spin_unlock(&ocrdma_devlist_lock);
+ call_rcu(&dev->rcu, ocrdma_remove_free);
+}
+
+static int ocrdma_open(struct ocrdma_dev *dev)
+{
+ struct ib_event port_event;
+
+ port_event.event = IB_EVENT_PORT_ACTIVE;
+ port_event.element.port_num = 1;
+ port_event.device = &dev->ibdev;
+ ib_dispatch_event(&port_event);
+ return 0;
+}
+
+static int ocrdma_close(struct ocrdma_dev *dev)
+{
+ int i;
+ struct ocrdma_qp *qp, **cur_qp;
+ struct ib_event err_event;
+ struct ib_qp_attr attrs;
+ int attr_mask = IB_QP_STATE;
+
+ attrs.qp_state = IB_QPS_ERR;
+ mutex_lock(&dev->dev_lock);
+ if (dev->qp_tbl) {
+ cur_qp = dev->qp_tbl;
+ for (i = 0; i < OCRDMA_MAX_QP; i++) {
+ qp = cur_qp[i];
+ if (qp) {
+ /* change the QP state to ERROR */
+ _ocrdma_modify_qp(&qp->ibqp, &attrs, attr_mask);
+
+ err_event.event = IB_EVENT_QP_FATAL;
+ err_event.element.qp = &qp->ibqp;
+ err_event.device = &dev->ibdev;
+ ib_dispatch_event(&err_event);
+ }
+ }
+ }
+ mutex_unlock(&dev->dev_lock);
+
+ err_event.event = IB_EVENT_PORT_ERR;
+ err_event.element.port_num = 1;
+ err_event.device = &dev->ibdev;
+ ib_dispatch_event(&err_event);
+ return 0;
+}
+
+/* event handling via NIC driver ensures that all the NIC specific
+ * initialization done before RoCE driver notifies
+ * event to stack.
+ */
+static void ocrdma_event_handler(struct ocrdma_dev *dev, u32 event)
+{
+ switch (event) {
+ case BE_DEV_UP:
+ ocrdma_open(dev);
+ break;
+ case BE_DEV_DOWN:
+ ocrdma_close(dev);
+ break;
+ };
+}
+
+static struct ocrdma_driver ocrdma_drv = {
+ .name = "ocrdma_driver",
+ .add = ocrdma_add,
+ .remove = ocrdma_remove,
+ .state_change_handler = ocrdma_event_handler,
+};
+
+static void ocrdma_unregister_inet6addr_notifier(void)
+{
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ unregister_inet6addr_notifier(&ocrdma_inet6addr_notifier);
+#endif
+}
+
+static int __init ocrdma_init_module(void)
+{
+ int status;
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ status = register_inet6addr_notifier(&ocrdma_inet6addr_notifier);
+ if (status)
+ return status;
+#endif
+
+ status = be_roce_register_driver(&ocrdma_drv);
+ if (status)
+ ocrdma_unregister_inet6addr_notifier();
+
+ return status;
+}
+
+static void __exit ocrdma_exit_module(void)
+{
+ be_roce_unregister_driver(&ocrdma_drv);
+ ocrdma_unregister_inet6addr_notifier();
+}
+
+module_init(ocrdma_init_module);
+module_exit(ocrdma_exit_module);
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
new file mode 100644
index 000000000000..7fd80cc0f037
--- /dev/null
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
@@ -0,0 +1,1672 @@
+/*******************************************************************
+ * This file is part of the Emulex RoCE Device Driver for *
+ * RoCE (RDMA over Converged Ethernet) adapters. *
+ * Copyright (C) 2008-2012 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.emulex.com *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of version 2 of the GNU General *
+ * Public License as published by the Free Software Foundation. *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID. See the GNU General Public License for *
+ * more details, a copy of which can be found in the file COPYING *
+ * included with this package. *
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ *******************************************************************/
+
+#ifndef __OCRDMA_SLI_H__
+#define __OCRDMA_SLI_H__
+
+#define Bit(_b) (1 << (_b))
+
+#define OCRDMA_GEN1_FAMILY 0xB
+#define OCRDMA_GEN2_FAMILY 0x2
+
+#define OCRDMA_SUBSYS_ROCE 10
+enum {
+ OCRDMA_CMD_QUERY_CONFIG = 1,
+ OCRDMA_CMD_ALLOC_PD,
+ OCRDMA_CMD_DEALLOC_PD,
+
+ OCRDMA_CMD_CREATE_AH_TBL,
+ OCRDMA_CMD_DELETE_AH_TBL,
+
+ OCRDMA_CMD_CREATE_QP,
+ OCRDMA_CMD_QUERY_QP,
+ OCRDMA_CMD_MODIFY_QP,
+ OCRDMA_CMD_DELETE_QP,
+
+ OCRDMA_CMD_RSVD1,
+ OCRDMA_CMD_ALLOC_LKEY,
+ OCRDMA_CMD_DEALLOC_LKEY,
+ OCRDMA_CMD_REGISTER_NSMR,
+ OCRDMA_CMD_REREGISTER_NSMR,
+ OCRDMA_CMD_REGISTER_NSMR_CONT,
+ OCRDMA_CMD_QUERY_NSMR,
+ OCRDMA_CMD_ALLOC_MW,
+ OCRDMA_CMD_QUERY_MW,
+
+ OCRDMA_CMD_CREATE_SRQ,
+ OCRDMA_CMD_QUERY_SRQ,
+ OCRDMA_CMD_MODIFY_SRQ,
+ OCRDMA_CMD_DELETE_SRQ,
+
+ OCRDMA_CMD_ATTACH_MCAST,
+ OCRDMA_CMD_DETACH_MCAST,
+
+ OCRDMA_CMD_MAX
+};
+
+#define OCRDMA_SUBSYS_COMMON 1
+enum {
+ OCRDMA_CMD_CREATE_CQ = 12,
+ OCRDMA_CMD_CREATE_EQ = 13,
+ OCRDMA_CMD_CREATE_MQ = 21,
+ OCRDMA_CMD_GET_FW_VER = 35,
+ OCRDMA_CMD_DELETE_MQ = 53,
+ OCRDMA_CMD_DELETE_CQ = 54,
+ OCRDMA_CMD_DELETE_EQ = 55,
+ OCRDMA_CMD_GET_FW_CONFIG = 58,
+ OCRDMA_CMD_CREATE_MQ_EXT = 90
+};
+
+enum {
+ QTYPE_EQ = 1,
+ QTYPE_CQ = 2,
+ QTYPE_MCCQ = 3
+};
+
+#define OCRDMA_MAX_SGID (8)
+
+#define OCRDMA_MAX_QP 2048
+#define OCRDMA_MAX_CQ 2048
+
+enum {
+ OCRDMA_DB_RQ_OFFSET = 0xE0,
+ OCRDMA_DB_GEN2_RQ1_OFFSET = 0x100,
+ OCRDMA_DB_GEN2_RQ2_OFFSET = 0xC0,
+ OCRDMA_DB_SQ_OFFSET = 0x60,
+ OCRDMA_DB_GEN2_SQ_OFFSET = 0x1C0,
+ OCRDMA_DB_SRQ_OFFSET = OCRDMA_DB_RQ_OFFSET,
+ OCRDMA_DB_GEN2_SRQ_OFFSET = OCRDMA_DB_GEN2_RQ1_OFFSET,
+ OCRDMA_DB_CQ_OFFSET = 0x120,
+ OCRDMA_DB_EQ_OFFSET = OCRDMA_DB_CQ_OFFSET,
+ OCRDMA_DB_MQ_OFFSET = 0x140
+};
+
+#define OCRDMA_DB_CQ_RING_ID_MASK 0x3FF /* bits 0 - 9 */
+#define OCRDMA_DB_CQ_RING_ID_EXT_MASK 0x0C00 /* bits 10-11 of qid at 12-11 */
+/* qid #2 msbits at 12-11 */
+#define OCRDMA_DB_CQ_RING_ID_EXT_MASK_SHIFT 0x1
+#define OCRDMA_DB_CQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */
+/* Rearm bit */
+#define OCRDMA_DB_CQ_REARM_SHIFT (29) /* bit 29 */
+/* solicited bit */
+#define OCRDMA_DB_CQ_SOLICIT_SHIFT (31) /* bit 31 */
+
+#define OCRDMA_EQ_ID_MASK 0x1FF /* bits 0 - 8 */
+#define OCRDMA_EQ_ID_EXT_MASK 0x3e00 /* bits 9-13 */
+#define OCRDMA_EQ_ID_EXT_MASK_SHIFT (2) /* qid bits 9-13 at 11-15 */
+
+/* Clear the interrupt for this eq */
+#define OCRDMA_EQ_CLR_SHIFT (9) /* bit 9 */
+/* Must be 1 */
+#define OCRDMA_EQ_TYPE_SHIFT (10) /* bit 10 */
+/* Number of event entries processed */
+#define OCRDMA_NUM_EQE_SHIFT (16) /* bits 16 - 28 */
+/* Rearm bit */
+#define OCRDMA_REARM_SHIFT (29) /* bit 29 */
+
+#define OCRDMA_MQ_ID_MASK 0x7FF /* bits 0 - 10 */
+/* Number of entries posted */
+#define OCRDMA_MQ_NUM_MQE_SHIFT (16) /* bits 16 - 29 */
+
+#define OCRDMA_MIN_HPAGE_SIZE (4096)
+
+#define OCRDMA_MIN_Q_PAGE_SIZE (4096)
+#define OCRDMA_MAX_Q_PAGES (8)
+
+/*
+# 0: 4K Bytes
+# 1: 8K Bytes
+# 2: 16K Bytes
+# 3: 32K Bytes
+# 4: 64K Bytes
+*/
+#define OCRDMA_MAX_Q_PAGE_SIZE_CNT (5)
+#define OCRDMA_Q_PAGE_BASE_SIZE (OCRDMA_MIN_Q_PAGE_SIZE * OCRDMA_MAX_Q_PAGES)
+
+#define MAX_OCRDMA_QP_PAGES (8)
+#define OCRDMA_MAX_WQE_MEM_SIZE (MAX_OCRDMA_QP_PAGES * OCRDMA_MIN_HQ_PAGE_SIZE)
+
+#define OCRDMA_CREATE_CQ_MAX_PAGES (4)
+#define OCRDMA_DPP_CQE_SIZE (4)
+
+#define OCRDMA_GEN2_MAX_CQE 1024
+#define OCRDMA_GEN2_CQ_PAGE_SIZE 4096
+#define OCRDMA_GEN2_WQE_SIZE 256
+#define OCRDMA_MAX_CQE 4095
+#define OCRDMA_CQ_PAGE_SIZE 16384
+#define OCRDMA_WQE_SIZE 128
+#define OCRDMA_WQE_STRIDE 8
+#define OCRDMA_WQE_ALIGN_BYTES 16
+
+#define MAX_OCRDMA_SRQ_PAGES MAX_OCRDMA_QP_PAGES
+
+enum {
+ OCRDMA_MCH_OPCODE_SHIFT = 0,
+ OCRDMA_MCH_OPCODE_MASK = 0xFF,
+ OCRDMA_MCH_SUBSYS_SHIFT = 8,
+ OCRDMA_MCH_SUBSYS_MASK = 0xFF00
+};
+
+/* mailbox cmd header */
+struct ocrdma_mbx_hdr {
+ u32 subsys_op;
+ u32 timeout; /* in seconds */
+ u32 cmd_len;
+ u32 rsvd_version;
+} __packed;
+
+enum {
+ OCRDMA_MBX_RSP_OPCODE_SHIFT = 0,
+ OCRDMA_MBX_RSP_OPCODE_MASK = 0xFF,
+ OCRDMA_MBX_RSP_SUBSYS_SHIFT = 8,
+ OCRDMA_MBX_RSP_SUBSYS_MASK = 0xFF << OCRDMA_MBX_RSP_SUBSYS_SHIFT,
+
+ OCRDMA_MBX_RSP_STATUS_SHIFT = 0,
+ OCRDMA_MBX_RSP_STATUS_MASK = 0xFF,
+ OCRDMA_MBX_RSP_ASTATUS_SHIFT = 8,
+ OCRDMA_MBX_RSP_ASTATUS_MASK = 0xFF << OCRDMA_MBX_RSP_ASTATUS_SHIFT
+};
+
+/* mailbox cmd response */
+struct ocrdma_mbx_rsp {
+ u32 subsys_op;
+ u32 status;
+ u32 rsp_len;
+ u32 add_rsp_len;
+} __packed;
+
+enum {
+ OCRDMA_MQE_EMBEDDED = 1,
+ OCRDMA_MQE_NONEMBEDDED = 0
+};
+
+struct ocrdma_mqe_sge {
+ u32 pa_lo;
+ u32 pa_hi;
+ u32 len;
+} __packed;
+
+enum {
+ OCRDMA_MQE_HDR_EMB_SHIFT = 0,
+ OCRDMA_MQE_HDR_EMB_MASK = Bit(0),
+ OCRDMA_MQE_HDR_SGE_CNT_SHIFT = 3,
+ OCRDMA_MQE_HDR_SGE_CNT_MASK = 0x1F << OCRDMA_MQE_HDR_SGE_CNT_SHIFT,
+ OCRDMA_MQE_HDR_SPECIAL_SHIFT = 24,
+ OCRDMA_MQE_HDR_SPECIAL_MASK = 0xFF << OCRDMA_MQE_HDR_SPECIAL_SHIFT
+};
+
+struct ocrdma_mqe_hdr {
+ u32 spcl_sge_cnt_emb;
+ u32 pyld_len;
+ u32 tag_lo;
+ u32 tag_hi;
+ u32 rsvd3;
+} __packed;
+
+struct ocrdma_mqe_emb_cmd {
+ struct ocrdma_mbx_hdr mch;
+ u8 pyld[220];
+} __packed;
+
+struct ocrdma_mqe {
+ struct ocrdma_mqe_hdr hdr;
+ union {
+ struct ocrdma_mqe_emb_cmd emb_req;
+ struct {
+ struct ocrdma_mqe_sge sge[19];
+ } nonemb_req;
+ u8 cmd[236];
+ struct ocrdma_mbx_rsp rsp;
+ } u;
+} __packed;
+
+#define OCRDMA_EQ_LEN 4096
+#define OCRDMA_MQ_CQ_LEN 256
+#define OCRDMA_MQ_LEN 128
+
+#define PAGE_SHIFT_4K 12
+#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
+
+/* Returns number of pages spanned by the data starting at the given addr */
+#define PAGES_4K_SPANNED(_address, size) \
+ ((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \
+ (size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K))
+
+struct ocrdma_delete_q_req {
+ struct ocrdma_mbx_hdr req;
+ u32 id;
+} __packed;
+
+struct ocrdma_pa {
+ u32 lo;
+ u32 hi;
+} __packed;
+
+#define MAX_OCRDMA_EQ_PAGES (8)
+struct ocrdma_create_eq_req {
+ struct ocrdma_mbx_hdr req;
+ u32 num_pages;
+ u32 valid;
+ u32 cnt;
+ u32 delay;
+ u32 rsvd;
+ struct ocrdma_pa pa[MAX_OCRDMA_EQ_PAGES];
+} __packed;
+
+enum {
+ OCRDMA_CREATE_EQ_VALID = Bit(29),
+ OCRDMA_CREATE_EQ_CNT_SHIFT = 26,
+ OCRDMA_CREATE_CQ_DELAY_SHIFT = 13,
+};
+
+struct ocrdma_create_eq_rsp {
+ struct ocrdma_mbx_rsp rsp;
+ u32 vector_eqid;
+};
+
+#define OCRDMA_EQ_MINOR_OTHER (0x1)
+
+enum {
+ OCRDMA_MCQE_STATUS_SHIFT = 0,
+ OCRDMA_MCQE_STATUS_MASK = 0xFFFF,
+ OCRDMA_MCQE_ESTATUS_SHIFT = 16,
+ OCRDMA_MCQE_ESTATUS_MASK = 0xFFFF << OCRDMA_MCQE_ESTATUS_SHIFT,
+ OCRDMA_MCQE_CONS_SHIFT = 27,
+ OCRDMA_MCQE_CONS_MASK = Bit(27),
+ OCRDMA_MCQE_CMPL_SHIFT = 28,
+ OCRDMA_MCQE_CMPL_MASK = Bit(28),
+ OCRDMA_MCQE_AE_SHIFT = 30,
+ OCRDMA_MCQE_AE_MASK = Bit(30),
+ OCRDMA_MCQE_VALID_SHIFT = 31,
+ OCRDMA_MCQE_VALID_MASK = Bit(31)
+};
+
+struct ocrdma_mcqe {
+ u32 status;
+ u32 tag_lo;
+ u32 tag_hi;
+ u32 valid_ae_cmpl_cons;
+} __packed;
+
+enum {
+ OCRDMA_AE_MCQE_QPVALID = Bit(31),
+ OCRDMA_AE_MCQE_QPID_MASK = 0xFFFF,
+
+ OCRDMA_AE_MCQE_CQVALID = Bit(31),
+ OCRDMA_AE_MCQE_CQID_MASK = 0xFFFF,
+ OCRDMA_AE_MCQE_VALID = Bit(31),
+ OCRDMA_AE_MCQE_AE = Bit(30),
+ OCRDMA_AE_MCQE_EVENT_TYPE_SHIFT = 16,
+ OCRDMA_AE_MCQE_EVENT_TYPE_MASK =
+ 0xFF << OCRDMA_AE_MCQE_EVENT_TYPE_SHIFT,
+ OCRDMA_AE_MCQE_EVENT_CODE_SHIFT = 8,
+ OCRDMA_AE_MCQE_EVENT_CODE_MASK =
+ 0xFF << OCRDMA_AE_MCQE_EVENT_CODE_SHIFT
+};
+struct ocrdma_ae_mcqe {
+ u32 qpvalid_qpid;
+ u32 cqvalid_cqid;
+ u32 evt_tag;
+ u32 valid_ae_event;
+} __packed;
+
+enum {
+ OCRDMA_AE_MPA_MCQE_REQ_ID_SHIFT = 16,
+ OCRDMA_AE_MPA_MCQE_REQ_ID_MASK = 0xFFFF <<
+ OCRDMA_AE_MPA_MCQE_REQ_ID_SHIFT,
+
+ OCRDMA_AE_MPA_MCQE_EVENT_CODE_SHIFT = 8,
+ OCRDMA_AE_MPA_MCQE_EVENT_CODE_MASK = 0xFF <<
+ OCRDMA_AE_MPA_MCQE_EVENT_CODE_SHIFT,
+ OCRDMA_AE_MPA_MCQE_EVENT_TYPE_SHIFT = 16,
+ OCRDMA_AE_MPA_MCQE_EVENT_TYPE_MASK = 0xFF <<
+ OCRDMA_AE_MPA_MCQE_EVENT_TYPE_SHIFT,
+ OCRDMA_AE_MPA_MCQE_EVENT_AE_SHIFT = 30,
+ OCRDMA_AE_MPA_MCQE_EVENT_AE_MASK = Bit(30),
+ OCRDMA_AE_MPA_MCQE_EVENT_VALID_SHIFT = 31,
+ OCRDMA_AE_MPA_MCQE_EVENT_VALID_MASK = Bit(31)
+};
+
+struct ocrdma_ae_mpa_mcqe {
+ u32 req_id;
+ u32 w1;
+ u32 w2;
+ u32 valid_ae_event;
+} __packed;
+
+enum {
+ OCRDMA_AE_QP_MCQE_NEW_QP_STATE_SHIFT = 0,
+ OCRDMA_AE_QP_MCQE_NEW_QP_STATE_MASK = 0xFFFF,
+ OCRDMA_AE_QP_MCQE_QP_ID_SHIFT = 16,
+ OCRDMA_AE_QP_MCQE_QP_ID_MASK = 0xFFFF <<
+ OCRDMA_AE_QP_MCQE_QP_ID_SHIFT,
+
+ OCRDMA_AE_QP_MCQE_EVENT_CODE_SHIFT = 8,
+ OCRDMA_AE_QP_MCQE_EVENT_CODE_MASK = 0xFF <<
+ OCRDMA_AE_QP_MCQE_EVENT_CODE_SHIFT,
+ OCRDMA_AE_QP_MCQE_EVENT_TYPE_SHIFT = 16,
+ OCRDMA_AE_QP_MCQE_EVENT_TYPE_MASK = 0xFF <<
+ OCRDMA_AE_QP_MCQE_EVENT_TYPE_SHIFT,
+ OCRDMA_AE_QP_MCQE_EVENT_AE_SHIFT = 30,
+ OCRDMA_AE_QP_MCQE_EVENT_AE_MASK = Bit(30),
+ OCRDMA_AE_QP_MCQE_EVENT_VALID_SHIFT = 31,
+ OCRDMA_AE_QP_MCQE_EVENT_VALID_MASK = Bit(31)
+};
+
+struct ocrdma_ae_qp_mcqe {
+ u32 qp_id_state;
+ u32 w1;
+ u32 w2;
+ u32 valid_ae_event;
+} __packed;
+
+#define OCRDMA_ASYNC_EVE_CODE 0x14
+
+enum OCRDMA_ASYNC_EVENT_TYPE {
+ OCRDMA_CQ_ERROR = 0x00,
+ OCRDMA_CQ_OVERRUN_ERROR = 0x01,
+ OCRDMA_CQ_QPCAT_ERROR = 0x02,
+ OCRDMA_QP_ACCESS_ERROR = 0x03,
+ OCRDMA_QP_COMM_EST_EVENT = 0x04,
+ OCRDMA_SQ_DRAINED_EVENT = 0x05,
+ OCRDMA_DEVICE_FATAL_EVENT = 0x08,
+ OCRDMA_SRQCAT_ERROR = 0x0E,
+ OCRDMA_SRQ_LIMIT_EVENT = 0x0F,
+ OCRDMA_QP_LAST_WQE_EVENT = 0x10
+};
+
+/* mailbox command request and responses */
+enum {
+ OCRDMA_MBX_QUERY_CFG_CQ_OVERFLOW_SHIFT = 2,
+ OCRDMA_MBX_QUERY_CFG_CQ_OVERFLOW_MASK = Bit(2),
+ OCRDMA_MBX_QUERY_CFG_SRQ_SUPPORTED_SHIFT = 3,
+ OCRDMA_MBX_QUERY_CFG_SRQ_SUPPORTED_MASK = Bit(3),
+ OCRDMA_MBX_QUERY_CFG_MAX_QP_SHIFT = 8,
+ OCRDMA_MBX_QUERY_CFG_MAX_QP_MASK = 0xFFFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_QP_SHIFT,
+
+ OCRDMA_MBX_QUERY_CFG_MAX_PD_SHIFT = 16,
+ OCRDMA_MBX_QUERY_CFG_MAX_PD_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_PD_SHIFT,
+ OCRDMA_MBX_QUERY_CFG_CA_ACK_DELAY_SHIFT = 8,
+ OCRDMA_MBX_QUERY_CFG_CA_ACK_DELAY_MASK = 0xFF <<
+ OCRDMA_MBX_QUERY_CFG_CA_ACK_DELAY_SHIFT,
+
+ OCRDMA_MBX_QUERY_CFG_MAX_SEND_SGE_SHIFT = 0,
+ OCRDMA_MBX_QUERY_CFG_MAX_SEND_SGE_MASK = 0xFFFF,
+
+ OCRDMA_MBX_QUERY_CFG_MAX_ORD_PER_QP_SHIFT = 0,
+ OCRDMA_MBX_QUERY_CFG_MAX_ORD_PER_QP_MASK = 0xFFFF,
+ OCRDMA_MBX_QUERY_CFG_MAX_IRD_PER_QP_SHIFT = 16,
+ OCRDMA_MBX_QUERY_CFG_MAX_IRD_PER_QP_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_IRD_PER_QP_SHIFT,
+
+ OCRDMA_MBX_QUERY_CFG_MAX_WQE_SIZE_OFFSET = 24,
+ OCRDMA_MBX_QUERY_CFG_MAX_WQE_SIZE_MASK = 0xFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_WQE_SIZE_OFFSET,
+ OCRDMA_MBX_QUERY_CFG_MAX_RQE_SIZE_OFFSET = 16,
+ OCRDMA_MBX_QUERY_CFG_MAX_RQE_SIZE_MASK = 0xFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_RQE_SIZE_OFFSET,
+ OCRDMA_MBX_QUERY_CFG_MAX_DPP_CQES_OFFSET = 0,
+ OCRDMA_MBX_QUERY_CFG_MAX_DPP_CQES_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_DPP_CQES_OFFSET,
+
+ OCRDMA_MBX_QUERY_CFG_MAX_SRQ_OFFSET = 16,
+ OCRDMA_MBX_QUERY_CFG_MAX_SRQ_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_SRQ_OFFSET,
+ OCRDMA_MBX_QUERY_CFG_MAX_RPIR_QPS_OFFSET = 0,
+ OCRDMA_MBX_QUERY_CFG_MAX_RPIR_QPS_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_RPIR_QPS_OFFSET,
+
+ OCRDMA_MBX_QUERY_CFG_MAX_DPP_PDS_OFFSET = 16,
+ OCRDMA_MBX_QUERY_CFG_MAX_DPP_PDS_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_DPP_PDS_OFFSET,
+ OCRDMA_MBX_QUERY_CFG_MAX_DPP_CREDITS_OFFSET = 0,
+ OCRDMA_MBX_QUERY_CFG_MAX_DPP_CREDITS_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_DPP_CREDITS_OFFSET,
+
+ OCRDMA_MBX_QUERY_CFG_MAX_DPP_QPS_OFFSET = 0,
+ OCRDMA_MBX_QUERY_CFG_MAX_DPP_QPS_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_DPP_QPS_OFFSET,
+
+ OCRDMA_MBX_QUERY_CFG_MAX_WQES_PER_WQ_OFFSET = 16,
+ OCRDMA_MBX_QUERY_CFG_MAX_WQES_PER_WQ_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_WQES_PER_WQ_OFFSET,
+ OCRDMA_MBX_QUERY_CFG_MAX_RQES_PER_RQ_OFFSET = 0,
+ OCRDMA_MBX_QUERY_CFG_MAX_RQES_PER_RQ_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_WQES_PER_WQ_OFFSET,
+
+ OCRDMA_MBX_QUERY_CFG_MAX_CQ_OFFSET = 16,
+ OCRDMA_MBX_QUERY_CFG_MAX_CQ_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_CQ_OFFSET,
+ OCRDMA_MBX_QUERY_CFG_MAX_CQES_PER_CQ_OFFSET = 0,
+ OCRDMA_MBX_QUERY_CFG_MAX_CQES_PER_CQ_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_CQES_PER_CQ_OFFSET,
+
+ OCRDMA_MBX_QUERY_CFG_MAX_SRQ_RQE_OFFSET = 16,
+ OCRDMA_MBX_QUERY_CFG_MAX_SRQ_RQE_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_SRQ_RQE_OFFSET,
+ OCRDMA_MBX_QUERY_CFG_MAX_SRQ_SGE_OFFSET = 0,
+ OCRDMA_MBX_QUERY_CFG_MAX_SRQ_SGE_MASK = 0xFFFF <<
+ OCRDMA_MBX_QUERY_CFG_MAX_SRQ_SGE_OFFSET,
+};
+
+struct ocrdma_mbx_query_config {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+ u32 qp_srq_cq_ird_ord;
+ u32 max_pd_ca_ack_delay;
+ u32 max_write_send_sge;
+ u32 max_ird_ord_per_qp;
+ u32 max_shared_ird_ord;
+ u32 max_mr;
+ u64 max_mr_size;
+ u32 max_num_mr_pbl;
+ u32 max_mw;
+ u32 max_fmr;
+ u32 max_pages_per_frmr;
+ u32 max_mcast_group;
+ u32 max_mcast_qp_attach;
+ u32 max_total_mcast_qp_attach;
+ u32 wqe_rqe_stride_max_dpp_cqs;
+ u32 max_srq_rpir_qps;
+ u32 max_dpp_pds_credits;
+ u32 max_dpp_credits_pds_per_pd;
+ u32 max_wqes_rqes_per_q;
+ u32 max_cq_cqes_per_cq;
+ u32 max_srq_rqe_sge;
+} __packed;
+
+struct ocrdma_fw_ver_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+
+ u8 running_ver[32];
+} __packed;
+
+struct ocrdma_fw_conf_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+
+ u32 config_num;
+ u32 asic_revision;
+ u32 phy_port;
+ u32 fn_mode;
+ struct {
+ u32 mode;
+ u32 nic_wqid_base;
+ u32 nic_wq_tot;
+ u32 prot_wqid_base;
+ u32 prot_wq_tot;
+ u32 prot_rqid_base;
+ u32 prot_rqid_tot;
+ u32 rsvd[6];
+ } ulp[2];
+ u32 fn_capabilities;
+ u32 rsvd1;
+ u32 rsvd2;
+ u32 base_eqid;
+ u32 max_eq;
+
+} __packed;
+
+enum {
+ OCRDMA_FN_MODE_RDMA = 0x4
+};
+
+enum {
+ OCRDMA_CREATE_CQ_VER2 = 2,
+
+ OCRDMA_CREATE_CQ_PAGE_CNT_MASK = 0xFFFF,
+ OCRDMA_CREATE_CQ_PAGE_SIZE_SHIFT = 16,
+ OCRDMA_CREATE_CQ_PAGE_SIZE_MASK = 0xFF,
+
+ OCRDMA_CREATE_CQ_COALESCWM_SHIFT = 12,
+ OCRDMA_CREATE_CQ_COALESCWM_MASK = Bit(13) | Bit(12),
+ OCRDMA_CREATE_CQ_FLAGS_NODELAY = Bit(14),
+ OCRDMA_CREATE_CQ_FLAGS_AUTO_VALID = Bit(15),
+
+ OCRDMA_CREATE_CQ_EQ_ID_MASK = 0xFFFF,
+ OCRDMA_CREATE_CQ_CQE_COUNT_MASK = 0xFFFF
+};
+
+enum {
+ OCRDMA_CREATE_CQ_VER0 = 0,
+ OCRDMA_CREATE_CQ_DPP = 1,
+ OCRDMA_CREATE_CQ_TYPE_SHIFT = 24,
+ OCRDMA_CREATE_CQ_EQID_SHIFT = 22,
+
+ OCRDMA_CREATE_CQ_CNT_SHIFT = 27,
+ OCRDMA_CREATE_CQ_FLAGS_VALID = Bit(29),
+ OCRDMA_CREATE_CQ_FLAGS_EVENTABLE = Bit(31),
+ OCRDMA_CREATE_CQ_DEF_FLAGS = OCRDMA_CREATE_CQ_FLAGS_VALID |
+ OCRDMA_CREATE_CQ_FLAGS_EVENTABLE |
+ OCRDMA_CREATE_CQ_FLAGS_NODELAY
+};
+
+struct ocrdma_create_cq_cmd {
+ struct ocrdma_mbx_hdr req;
+ u32 pgsz_pgcnt;
+ u32 ev_cnt_flags;
+ u32 eqn;
+ u32 cqe_count;
+ u32 rsvd6;
+ struct ocrdma_pa pa[OCRDMA_CREATE_CQ_MAX_PAGES];
+};
+
+struct ocrdma_create_cq {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_create_cq_cmd cmd;
+} __packed;
+
+enum {
+ OCRDMA_CREATE_CQ_RSP_CQ_ID_MASK = 0xFFFF
+};
+
+struct ocrdma_create_cq_cmd_rsp {
+ struct ocrdma_mbx_rsp rsp;
+ u32 cq_id;
+} __packed;
+
+struct ocrdma_create_cq_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_create_cq_cmd_rsp rsp;
+} __packed;
+
+enum {
+ OCRDMA_CREATE_MQ_V0_CQ_ID_SHIFT = 22,
+ OCRDMA_CREATE_MQ_CQ_ID_SHIFT = 16,
+ OCRDMA_CREATE_MQ_RING_SIZE_SHIFT = 16,
+ OCRDMA_CREATE_MQ_VALID = Bit(31),
+ OCRDMA_CREATE_MQ_ASYNC_CQ_VALID = Bit(0)
+};
+
+struct ocrdma_create_mq_v0 {
+ u32 pages;
+ u32 cqid_ringsize;
+ u32 valid;
+ u32 async_cqid_valid;
+ u32 rsvd;
+ struct ocrdma_pa pa[8];
+} __packed;
+
+struct ocrdma_create_mq_v1 {
+ u32 cqid_pages;
+ u32 async_event_bitmap;
+ u32 async_cqid_ringsize;
+ u32 valid;
+ u32 async_cqid_valid;
+ u32 rsvd;
+ struct ocrdma_pa pa[8];
+} __packed;
+
+struct ocrdma_create_mq_req {
+ struct ocrdma_mbx_hdr req;
+ union {
+ struct ocrdma_create_mq_v0 v0;
+ struct ocrdma_create_mq_v1 v1;
+ };
+} __packed;
+
+struct ocrdma_create_mq_rsp {
+ struct ocrdma_mbx_rsp rsp;
+ u32 id;
+} __packed;
+
+enum {
+ OCRDMA_DESTROY_CQ_QID_SHIFT = 0,
+ OCRDMA_DESTROY_CQ_QID_MASK = 0xFFFF,
+ OCRDMA_DESTROY_CQ_QID_BYPASS_FLUSH_SHIFT = 16,
+ OCRDMA_DESTROY_CQ_QID_BYPASS_FLUSH_MASK = 0xFFFF <<
+ OCRDMA_DESTROY_CQ_QID_BYPASS_FLUSH_SHIFT
+};
+
+struct ocrdma_destroy_cq {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+
+ u32 bypass_flush_qid;
+} __packed;
+
+struct ocrdma_destroy_cq_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+} __packed;
+
+enum {
+ OCRDMA_QPT_GSI = 1,
+ OCRDMA_QPT_RC = 2,
+ OCRDMA_QPT_UD = 4,
+};
+
+enum {
+ OCRDMA_CREATE_QP_REQ_PD_ID_SHIFT = 0,
+ OCRDMA_CREATE_QP_REQ_PD_ID_MASK = 0xFFFF,
+ OCRDMA_CREATE_QP_REQ_SQ_PAGE_SIZE_SHIFT = 16,
+ OCRDMA_CREATE_QP_REQ_RQ_PAGE_SIZE_SHIFT = 19,
+ OCRDMA_CREATE_QP_REQ_QPT_SHIFT = 29,
+ OCRDMA_CREATE_QP_REQ_QPT_MASK = Bit(31) | Bit(30) | Bit(29),
+
+ OCRDMA_CREATE_QP_REQ_MAX_RQE_SHIFT = 0,
+ OCRDMA_CREATE_QP_REQ_MAX_RQE_MASK = 0xFFFF,
+ OCRDMA_CREATE_QP_REQ_MAX_WQE_SHIFT = 16,
+ OCRDMA_CREATE_QP_REQ_MAX_WQE_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_REQ_MAX_WQE_SHIFT,
+
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_WRITE_SHIFT = 0,
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_WRITE_MASK = 0xFFFF,
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_SEND_SHIFT = 16,
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_SEND_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_SEND_SHIFT,
+
+ OCRDMA_CREATE_QP_REQ_FMR_EN_SHIFT = 0,
+ OCRDMA_CREATE_QP_REQ_FMR_EN_MASK = Bit(0),
+ OCRDMA_CREATE_QP_REQ_ZERO_LKEYEN_SHIFT = 1,
+ OCRDMA_CREATE_QP_REQ_ZERO_LKEYEN_MASK = Bit(1),
+ OCRDMA_CREATE_QP_REQ_BIND_MEMWIN_SHIFT = 2,
+ OCRDMA_CREATE_QP_REQ_BIND_MEMWIN_MASK = Bit(2),
+ OCRDMA_CREATE_QP_REQ_INB_WREN_SHIFT = 3,
+ OCRDMA_CREATE_QP_REQ_INB_WREN_MASK = Bit(3),
+ OCRDMA_CREATE_QP_REQ_INB_RDEN_SHIFT = 4,
+ OCRDMA_CREATE_QP_REQ_INB_RDEN_MASK = Bit(4),
+ OCRDMA_CREATE_QP_REQ_USE_SRQ_SHIFT = 5,
+ OCRDMA_CREATE_QP_REQ_USE_SRQ_MASK = Bit(5),
+ OCRDMA_CREATE_QP_REQ_ENABLE_RPIR_SHIFT = 6,
+ OCRDMA_CREATE_QP_REQ_ENABLE_RPIR_MASK = Bit(6),
+ OCRDMA_CREATE_QP_REQ_ENABLE_DPP_SHIFT = 7,
+ OCRDMA_CREATE_QP_REQ_ENABLE_DPP_MASK = Bit(7),
+ OCRDMA_CREATE_QP_REQ_ENABLE_DPP_CQ_SHIFT = 8,
+ OCRDMA_CREATE_QP_REQ_ENABLE_DPP_CQ_MASK = Bit(8),
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_RECV_SHIFT = 16,
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_RECV_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_REQ_MAX_SGE_RECV_SHIFT,
+
+ OCRDMA_CREATE_QP_REQ_MAX_IRD_SHIFT = 0,
+ OCRDMA_CREATE_QP_REQ_MAX_IRD_MASK = 0xFFFF,
+ OCRDMA_CREATE_QP_REQ_MAX_ORD_SHIFT = 16,
+ OCRDMA_CREATE_QP_REQ_MAX_ORD_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_REQ_MAX_ORD_SHIFT,
+
+ OCRDMA_CREATE_QP_REQ_NUM_RQ_PAGES_SHIFT = 0,
+ OCRDMA_CREATE_QP_REQ_NUM_RQ_PAGES_MASK = 0xFFFF,
+ OCRDMA_CREATE_QP_REQ_NUM_WQ_PAGES_SHIFT = 16,
+ OCRDMA_CREATE_QP_REQ_NUM_WQ_PAGES_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_REQ_NUM_WQ_PAGES_SHIFT,
+
+ OCRDMA_CREATE_QP_REQ_RQE_SIZE_SHIFT = 0,
+ OCRDMA_CREATE_QP_REQ_RQE_SIZE_MASK = 0xFFFF,
+ OCRDMA_CREATE_QP_REQ_WQE_SIZE_SHIFT = 16,
+ OCRDMA_CREATE_QP_REQ_WQE_SIZE_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_REQ_WQE_SIZE_SHIFT,
+
+ OCRDMA_CREATE_QP_REQ_RQ_CQID_SHIFT = 0,
+ OCRDMA_CREATE_QP_REQ_RQ_CQID_MASK = 0xFFFF,
+ OCRDMA_CREATE_QP_REQ_WQ_CQID_SHIFT = 16,
+ OCRDMA_CREATE_QP_REQ_WQ_CQID_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_REQ_WQ_CQID_SHIFT,
+
+ OCRDMA_CREATE_QP_REQ_DPP_CQPID_SHIFT = 0,
+ OCRDMA_CREATE_QP_REQ_DPP_CQPID_MASK = 0xFFFF,
+ OCRDMA_CREATE_QP_REQ_DPP_CREDIT_SHIFT = 16,
+ OCRDMA_CREATE_QP_REQ_DPP_CREDIT_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_REQ_DPP_CREDIT_SHIFT
+};
+
+enum {
+ OCRDMA_CREATE_QP_REQ_DPP_CREDIT_LIMIT = 16,
+ OCRDMA_CREATE_QP_RSP_DPP_PAGE_SHIFT = 1
+};
+
+#define MAX_OCRDMA_IRD_PAGES 4
+
+enum ocrdma_qp_flags {
+ OCRDMA_QP_MW_BIND = 1,
+ OCRDMA_QP_LKEY0 = (1 << 1),
+ OCRDMA_QP_FAST_REG = (1 << 2),
+ OCRDMA_QP_INB_RD = (1 << 6),
+ OCRDMA_QP_INB_WR = (1 << 7),
+};
+
+enum ocrdma_qp_state {
+ OCRDMA_QPS_RST = 0,
+ OCRDMA_QPS_INIT = 1,
+ OCRDMA_QPS_RTR = 2,
+ OCRDMA_QPS_RTS = 3,
+ OCRDMA_QPS_SQE = 4,
+ OCRDMA_QPS_SQ_DRAINING = 5,
+ OCRDMA_QPS_ERR = 6,
+ OCRDMA_QPS_SQD = 7
+};
+
+struct ocrdma_create_qp_req {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+
+ u32 type_pgsz_pdn;
+ u32 max_wqe_rqe;
+ u32 max_sge_send_write;
+ u32 max_sge_recv_flags;
+ u32 max_ord_ird;
+ u32 num_wq_rq_pages;
+ u32 wqe_rqe_size;
+ u32 wq_rq_cqid;
+ struct ocrdma_pa wq_addr[MAX_OCRDMA_QP_PAGES];
+ struct ocrdma_pa rq_addr[MAX_OCRDMA_QP_PAGES];
+ u32 dpp_credits_cqid;
+ u32 rpir_lkey;
+ struct ocrdma_pa ird_addr[MAX_OCRDMA_IRD_PAGES];
+} __packed;
+
+enum {
+ OCRDMA_CREATE_QP_RSP_QP_ID_SHIFT = 0,
+ OCRDMA_CREATE_QP_RSP_QP_ID_MASK = 0xFFFF,
+
+ OCRDMA_CREATE_QP_RSP_MAX_RQE_SHIFT = 0,
+ OCRDMA_CREATE_QP_RSP_MAX_RQE_MASK = 0xFFFF,
+ OCRDMA_CREATE_QP_RSP_MAX_WQE_SHIFT = 16,
+ OCRDMA_CREATE_QP_RSP_MAX_WQE_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_RSP_MAX_WQE_SHIFT,
+
+ OCRDMA_CREATE_QP_RSP_MAX_SGE_WRITE_SHIFT = 0,
+ OCRDMA_CREATE_QP_RSP_MAX_SGE_WRITE_MASK = 0xFFFF,
+ OCRDMA_CREATE_QP_RSP_MAX_SGE_SEND_SHIFT = 16,
+ OCRDMA_CREATE_QP_RSP_MAX_SGE_SEND_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_RSP_MAX_SGE_SEND_SHIFT,
+
+ OCRDMA_CREATE_QP_RSP_MAX_SGE_RECV_SHIFT = 16,
+ OCRDMA_CREATE_QP_RSP_MAX_SGE_RECV_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_RSP_MAX_SGE_RECV_SHIFT,
+
+ OCRDMA_CREATE_QP_RSP_MAX_IRD_SHIFT = 0,
+ OCRDMA_CREATE_QP_RSP_MAX_IRD_MASK = 0xFFFF,
+ OCRDMA_CREATE_QP_RSP_MAX_ORD_SHIFT = 16,
+ OCRDMA_CREATE_QP_RSP_MAX_ORD_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_RSP_MAX_ORD_SHIFT,
+
+ OCRDMA_CREATE_QP_RSP_RQ_ID_SHIFT = 0,
+ OCRDMA_CREATE_QP_RSP_RQ_ID_MASK = 0xFFFF,
+ OCRDMA_CREATE_QP_RSP_SQ_ID_SHIFT = 16,
+ OCRDMA_CREATE_QP_RSP_SQ_ID_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_RSP_SQ_ID_SHIFT,
+
+ OCRDMA_CREATE_QP_RSP_DPP_ENABLED_MASK = Bit(0),
+ OCRDMA_CREATE_QP_RSP_DPP_PAGE_OFFSET_SHIFT = 1,
+ OCRDMA_CREATE_QP_RSP_DPP_PAGE_OFFSET_MASK = 0x7FFF <<
+ OCRDMA_CREATE_QP_RSP_DPP_PAGE_OFFSET_SHIFT,
+ OCRDMA_CREATE_QP_RSP_DPP_CREDITS_SHIFT = 16,
+ OCRDMA_CREATE_QP_RSP_DPP_CREDITS_MASK = 0xFFFF <<
+ OCRDMA_CREATE_QP_RSP_DPP_CREDITS_SHIFT,
+};
+
+struct ocrdma_create_qp_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+
+ u32 qp_id;
+ u32 max_wqe_rqe;
+ u32 max_sge_send_write;
+ u32 max_sge_recv;
+ u32 max_ord_ird;
+ u32 sq_rq_id;
+ u32 dpp_response;
+} __packed;
+
+struct ocrdma_destroy_qp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+ u32 qp_id;
+} __packed;
+
+struct ocrdma_destroy_qp_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+} __packed;
+
+enum {
+ OCRDMA_MODIFY_QP_ID_SHIFT = 0,
+ OCRDMA_MODIFY_QP_ID_MASK = 0xFFFF,
+
+ OCRDMA_QP_PARA_QPS_VALID = Bit(0),
+ OCRDMA_QP_PARA_SQD_ASYNC_VALID = Bit(1),
+ OCRDMA_QP_PARA_PKEY_VALID = Bit(2),
+ OCRDMA_QP_PARA_QKEY_VALID = Bit(3),
+ OCRDMA_QP_PARA_PMTU_VALID = Bit(4),
+ OCRDMA_QP_PARA_ACK_TO_VALID = Bit(5),
+ OCRDMA_QP_PARA_RETRY_CNT_VALID = Bit(6),
+ OCRDMA_QP_PARA_RRC_VALID = Bit(7),
+ OCRDMA_QP_PARA_RQPSN_VALID = Bit(8),
+ OCRDMA_QP_PARA_MAX_IRD_VALID = Bit(9),
+ OCRDMA_QP_PARA_MAX_ORD_VALID = Bit(10),
+ OCRDMA_QP_PARA_RNT_VALID = Bit(11),
+ OCRDMA_QP_PARA_SQPSN_VALID = Bit(12),
+ OCRDMA_QP_PARA_DST_QPN_VALID = Bit(13),
+ OCRDMA_QP_PARA_MAX_WQE_VALID = Bit(14),
+ OCRDMA_QP_PARA_MAX_RQE_VALID = Bit(15),
+ OCRDMA_QP_PARA_SGE_SEND_VALID = Bit(16),
+ OCRDMA_QP_PARA_SGE_RECV_VALID = Bit(17),
+ OCRDMA_QP_PARA_SGE_WR_VALID = Bit(18),
+ OCRDMA_QP_PARA_INB_RDEN_VALID = Bit(19),
+ OCRDMA_QP_PARA_INB_WREN_VALID = Bit(20),
+ OCRDMA_QP_PARA_FLOW_LBL_VALID = Bit(21),
+ OCRDMA_QP_PARA_BIND_EN_VALID = Bit(22),
+ OCRDMA_QP_PARA_ZLKEY_EN_VALID = Bit(23),
+ OCRDMA_QP_PARA_FMR_EN_VALID = Bit(24),
+ OCRDMA_QP_PARA_INBAT_EN_VALID = Bit(25),
+ OCRDMA_QP_PARA_VLAN_EN_VALID = Bit(26),
+
+ OCRDMA_MODIFY_QP_FLAGS_RD = Bit(0),
+ OCRDMA_MODIFY_QP_FLAGS_WR = Bit(1),
+ OCRDMA_MODIFY_QP_FLAGS_SEND = Bit(2),
+ OCRDMA_MODIFY_QP_FLAGS_ATOMIC = Bit(3)
+};
+
+enum {
+ OCRDMA_QP_PARAMS_SRQ_ID_SHIFT = 0,
+ OCRDMA_QP_PARAMS_SRQ_ID_MASK = 0xFFFF,
+
+ OCRDMA_QP_PARAMS_MAX_RQE_SHIFT = 0,
+ OCRDMA_QP_PARAMS_MAX_RQE_MASK = 0xFFFF,
+ OCRDMA_QP_PARAMS_MAX_WQE_SHIFT = 16,
+ OCRDMA_QP_PARAMS_MAX_WQE_MASK = 0xFFFF <<
+ OCRDMA_QP_PARAMS_MAX_WQE_SHIFT,
+
+ OCRDMA_QP_PARAMS_MAX_SGE_WRITE_SHIFT = 0,
+ OCRDMA_QP_PARAMS_MAX_SGE_WRITE_MASK = 0xFFFF,
+ OCRDMA_QP_PARAMS_MAX_SGE_SEND_SHIFT = 16,
+ OCRDMA_QP_PARAMS_MAX_SGE_SEND_MASK = 0xFFFF <<
+ OCRDMA_QP_PARAMS_MAX_SGE_SEND_SHIFT,
+
+ OCRDMA_QP_PARAMS_FLAGS_FMR_EN = Bit(0),
+ OCRDMA_QP_PARAMS_FLAGS_LKEY_0_EN = Bit(1),
+ OCRDMA_QP_PARAMS_FLAGS_BIND_MW_EN = Bit(2),
+ OCRDMA_QP_PARAMS_FLAGS_INBWR_EN = Bit(3),
+ OCRDMA_QP_PARAMS_FLAGS_INBRD_EN = Bit(4),
+ OCRDMA_QP_PARAMS_STATE_SHIFT = 5,
+ OCRDMA_QP_PARAMS_STATE_MASK = Bit(5) | Bit(6) | Bit(7),
+ OCRDMA_QP_PARAMS_FLAGS_SQD_ASYNC = Bit(8),
+ OCRDMA_QP_PARAMS_FLAGS_INB_ATEN = Bit(9),
+ OCRDMA_QP_PARAMS_MAX_SGE_RECV_SHIFT = 16,
+ OCRDMA_QP_PARAMS_MAX_SGE_RECV_MASK = 0xFFFF <<
+ OCRDMA_QP_PARAMS_MAX_SGE_RECV_SHIFT,
+
+ OCRDMA_QP_PARAMS_MAX_IRD_SHIFT = 0,
+ OCRDMA_QP_PARAMS_MAX_IRD_MASK = 0xFFFF,
+ OCRDMA_QP_PARAMS_MAX_ORD_SHIFT = 16,
+ OCRDMA_QP_PARAMS_MAX_ORD_MASK = 0xFFFF <<
+ OCRDMA_QP_PARAMS_MAX_ORD_SHIFT,
+
+ OCRDMA_QP_PARAMS_RQ_CQID_SHIFT = 0,
+ OCRDMA_QP_PARAMS_RQ_CQID_MASK = 0xFFFF,
+ OCRDMA_QP_PARAMS_WQ_CQID_SHIFT = 16,
+ OCRDMA_QP_PARAMS_WQ_CQID_MASK = 0xFFFF <<
+ OCRDMA_QP_PARAMS_WQ_CQID_SHIFT,
+
+ OCRDMA_QP_PARAMS_RQ_PSN_SHIFT = 0,
+ OCRDMA_QP_PARAMS_RQ_PSN_MASK = 0xFFFFFF,
+ OCRDMA_QP_PARAMS_HOP_LMT_SHIFT = 24,
+ OCRDMA_QP_PARAMS_HOP_LMT_MASK = 0xFF <<
+ OCRDMA_QP_PARAMS_HOP_LMT_SHIFT,
+
+ OCRDMA_QP_PARAMS_SQ_PSN_SHIFT = 0,
+ OCRDMA_QP_PARAMS_SQ_PSN_MASK = 0xFFFFFF,
+ OCRDMA_QP_PARAMS_TCLASS_SHIFT = 24,
+ OCRDMA_QP_PARAMS_TCLASS_MASK = 0xFF <<
+ OCRDMA_QP_PARAMS_TCLASS_SHIFT,
+
+ OCRDMA_QP_PARAMS_DEST_QPN_SHIFT = 0,
+ OCRDMA_QP_PARAMS_DEST_QPN_MASK = 0xFFFFFF,
+ OCRDMA_QP_PARAMS_RNR_RETRY_CNT_SHIFT = 24,
+ OCRDMA_QP_PARAMS_RNR_RETRY_CNT_MASK = 0x7 <<
+ OCRDMA_QP_PARAMS_RNR_RETRY_CNT_SHIFT,
+ OCRDMA_QP_PARAMS_ACK_TIMEOUT_SHIFT = 27,
+ OCRDMA_QP_PARAMS_ACK_TIMEOUT_MASK = 0x1F <<
+ OCRDMA_QP_PARAMS_ACK_TIMEOUT_SHIFT,
+
+ OCRDMA_QP_PARAMS_PKEY_IDNEX_SHIFT = 0,
+ OCRDMA_QP_PARAMS_PKEY_INDEX_MASK = 0xFFFF,
+ OCRDMA_QP_PARAMS_PATH_MTU_SHIFT = 18,
+ OCRDMA_QP_PARAMS_PATH_MTU_MASK = 0x3FFF <<
+ OCRDMA_QP_PARAMS_PATH_MTU_SHIFT,
+
+ OCRDMA_QP_PARAMS_FLOW_LABEL_SHIFT = 0,
+ OCRDMA_QP_PARAMS_FLOW_LABEL_MASK = 0xFFFFF,
+ OCRDMA_QP_PARAMS_SL_SHIFT = 20,
+ OCRDMA_QP_PARAMS_SL_MASK = 0xF <<
+ OCRDMA_QP_PARAMS_SL_SHIFT,
+ OCRDMA_QP_PARAMS_RETRY_CNT_SHIFT = 24,
+ OCRDMA_QP_PARAMS_RETRY_CNT_MASK = 0x7 <<
+ OCRDMA_QP_PARAMS_RETRY_CNT_SHIFT,
+ OCRDMA_QP_PARAMS_RNR_NAK_TIMER_SHIFT = 27,
+ OCRDMA_QP_PARAMS_RNR_NAK_TIMER_MASK = 0x1F <<
+ OCRDMA_QP_PARAMS_RNR_NAK_TIMER_SHIFT,
+
+ OCRDMA_QP_PARAMS_DMAC_B4_TO_B5_SHIFT = 0,
+ OCRDMA_QP_PARAMS_DMAC_B4_TO_B5_MASK = 0xFFFF,
+ OCRDMA_QP_PARAMS_VLAN_SHIFT = 16,
+ OCRDMA_QP_PARAMS_VLAN_MASK = 0xFFFF <<
+ OCRDMA_QP_PARAMS_VLAN_SHIFT
+};
+
+struct ocrdma_qp_params {
+ u32 id;
+ u32 max_wqe_rqe;
+ u32 max_sge_send_write;
+ u32 max_sge_recv_flags;
+ u32 max_ord_ird;
+ u32 wq_rq_cqid;
+ u32 hop_lmt_rq_psn;
+ u32 tclass_sq_psn;
+ u32 ack_to_rnr_rtc_dest_qpn;
+ u32 path_mtu_pkey_indx;
+ u32 rnt_rc_sl_fl;
+ u8 sgid[16];
+ u8 dgid[16];
+ u32 dmac_b0_to_b3;
+ u32 vlan_dmac_b4_to_b5;
+ u32 qkey;
+} __packed;
+
+
+struct ocrdma_modify_qp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+
+ struct ocrdma_qp_params params;
+ u32 flags;
+ u32 rdma_flags;
+ u32 num_outstanding_atomic_rd;
+} __packed;
+
+enum {
+ OCRDMA_MODIFY_QP_RSP_MAX_RQE_SHIFT = 0,
+ OCRDMA_MODIFY_QP_RSP_MAX_RQE_MASK = 0xFFFF,
+ OCRDMA_MODIFY_QP_RSP_MAX_WQE_SHIFT = 16,
+ OCRDMA_MODIFY_QP_RSP_MAX_WQE_MASK = 0xFFFF <<
+ OCRDMA_MODIFY_QP_RSP_MAX_WQE_SHIFT,
+
+ OCRDMA_MODIFY_QP_RSP_MAX_IRD_SHIFT = 0,
+ OCRDMA_MODIFY_QP_RSP_MAX_IRD_MASK = 0xFFFF,
+ OCRDMA_MODIFY_QP_RSP_MAX_ORD_SHIFT = 16,
+ OCRDMA_MODIFY_QP_RSP_MAX_ORD_MASK = 0xFFFF <<
+ OCRDMA_MODIFY_QP_RSP_MAX_ORD_SHIFT
+};
+struct ocrdma_modify_qp_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+
+ u32 max_wqe_rqe;
+ u32 max_ord_ird;
+} __packed;
+
+struct ocrdma_query_qp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+
+#define OCRDMA_QUERY_UP_QP_ID_SHIFT 0
+#define OCRDMA_QUERY_UP_QP_ID_MASK 0xFFFFFF
+ u32 qp_id;
+} __packed;
+
+struct ocrdma_query_qp_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+ struct ocrdma_qp_params params;
+} __packed;
+
+enum {
+ OCRDMA_CREATE_SRQ_PD_ID_SHIFT = 0,
+ OCRDMA_CREATE_SRQ_PD_ID_MASK = 0xFFFF,
+ OCRDMA_CREATE_SRQ_PG_SZ_SHIFT = 16,
+ OCRDMA_CREATE_SRQ_PG_SZ_MASK = 0x3 <<
+ OCRDMA_CREATE_SRQ_PG_SZ_SHIFT,
+
+ OCRDMA_CREATE_SRQ_MAX_RQE_SHIFT = 0,
+ OCRDMA_CREATE_SRQ_MAX_SGE_RECV_SHIFT = 16,
+ OCRDMA_CREATE_SRQ_MAX_SGE_RECV_MASK = 0xFFFF <<
+ OCRDMA_CREATE_SRQ_MAX_SGE_RECV_SHIFT,
+
+ OCRDMA_CREATE_SRQ_RQE_SIZE_SHIFT = 0,
+ OCRDMA_CREATE_SRQ_RQE_SIZE_MASK = 0xFFFF,
+ OCRDMA_CREATE_SRQ_NUM_RQ_PAGES_SHIFT = 16,
+ OCRDMA_CREATE_SRQ_NUM_RQ_PAGES_MASK = 0xFFFF <<
+ OCRDMA_CREATE_SRQ_NUM_RQ_PAGES_SHIFT
+};
+
+struct ocrdma_create_srq {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+
+ u32 pgsz_pdid;
+ u32 max_sge_rqe;
+ u32 pages_rqe_sz;
+ struct ocrdma_pa rq_addr[MAX_OCRDMA_SRQ_PAGES];
+} __packed;
+
+enum {
+ OCRDMA_CREATE_SRQ_RSP_SRQ_ID_SHIFT = 0,
+ OCRDMA_CREATE_SRQ_RSP_SRQ_ID_MASK = 0xFFFFFF,
+
+ OCRDMA_CREATE_SRQ_RSP_MAX_RQE_ALLOCATED_SHIFT = 0,
+ OCRDMA_CREATE_SRQ_RSP_MAX_RQE_ALLOCATED_MASK = 0xFFFF,
+ OCRDMA_CREATE_SRQ_RSP_MAX_SGE_RECV_ALLOCATED_SHIFT = 16,
+ OCRDMA_CREATE_SRQ_RSP_MAX_SGE_RECV_ALLOCATED_MASK = 0xFFFF <<
+ OCRDMA_CREATE_SRQ_RSP_MAX_SGE_RECV_ALLOCATED_SHIFT
+};
+
+struct ocrdma_create_srq_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+
+ u32 id;
+ u32 max_sge_rqe_allocated;
+} __packed;
+
+enum {
+ OCRDMA_MODIFY_SRQ_ID_SHIFT = 0,
+ OCRDMA_MODIFY_SRQ_ID_MASK = 0xFFFFFF,
+
+ OCRDMA_MODIFY_SRQ_MAX_RQE_SHIFT = 0,
+ OCRDMA_MODIFY_SRQ_MAX_RQE_MASK = 0xFFFF,
+ OCRDMA_MODIFY_SRQ_LIMIT_SHIFT = 16,
+ OCRDMA_MODIFY_SRQ__LIMIT_MASK = 0xFFFF <<
+ OCRDMA_MODIFY_SRQ_LIMIT_SHIFT
+};
+
+struct ocrdma_modify_srq {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rep;
+
+ u32 id;
+ u32 limit_max_rqe;
+} __packed;
+
+enum {
+ OCRDMA_QUERY_SRQ_ID_SHIFT = 0,
+ OCRDMA_QUERY_SRQ_ID_MASK = 0xFFFFFF
+};
+
+struct ocrdma_query_srq {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp req;
+
+ u32 id;
+} __packed;
+
+enum {
+ OCRDMA_QUERY_SRQ_RSP_PD_ID_SHIFT = 0,
+ OCRDMA_QUERY_SRQ_RSP_PD_ID_MASK = 0xFFFF,
+ OCRDMA_QUERY_SRQ_RSP_MAX_RQE_SHIFT = 16,
+ OCRDMA_QUERY_SRQ_RSP_MAX_RQE_MASK = 0xFFFF <<
+ OCRDMA_QUERY_SRQ_RSP_MAX_RQE_SHIFT,
+
+ OCRDMA_QUERY_SRQ_RSP_MAX_SGE_RECV_SHIFT = 0,
+ OCRDMA_QUERY_SRQ_RSP_MAX_SGE_RECV_MASK = 0xFFFF,
+ OCRDMA_QUERY_SRQ_RSP_SRQ_LIMIT_SHIFT = 16,
+ OCRDMA_QUERY_SRQ_RSP_SRQ_LIMIT_MASK = 0xFFFF <<
+ OCRDMA_QUERY_SRQ_RSP_SRQ_LIMIT_SHIFT
+};
+
+struct ocrdma_query_srq_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp req;
+
+ u32 max_rqe_pdid;
+ u32 srq_lmt_max_sge;
+} __packed;
+
+enum {
+ OCRDMA_DESTROY_SRQ_ID_SHIFT = 0,
+ OCRDMA_DESTROY_SRQ_ID_MASK = 0xFFFFFF
+};
+
+struct ocrdma_destroy_srq {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp req;
+
+ u32 id;
+} __packed;
+
+enum {
+ OCRDMA_ALLOC_PD_ENABLE_DPP = BIT(16),
+ OCRDMA_PD_MAX_DPP_ENABLED_QP = 8,
+ OCRDMA_DPP_PAGE_SIZE = 4096
+};
+
+struct ocrdma_alloc_pd {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+ u32 enable_dpp_rsvd;
+} __packed;
+
+enum {
+ OCRDMA_ALLOC_PD_RSP_DPP = Bit(16),
+ OCRDMA_ALLOC_PD_RSP_DPP_PAGE_SHIFT = 20,
+ OCRDMA_ALLOC_PD_RSP_PDID_MASK = 0xFFFF,
+};
+
+struct ocrdma_alloc_pd_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+ u32 dpp_page_pdid;
+} __packed;
+
+struct ocrdma_dealloc_pd {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+ u32 id;
+} __packed;
+
+struct ocrdma_dealloc_pd_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+} __packed;
+
+enum {
+ OCRDMA_ADDR_CHECK_ENABLE = 1,
+ OCRDMA_ADDR_CHECK_DISABLE = 0
+};
+
+enum {
+ OCRDMA_ALLOC_LKEY_PD_ID_SHIFT = 0,
+ OCRDMA_ALLOC_LKEY_PD_ID_MASK = 0xFFFF,
+
+ OCRDMA_ALLOC_LKEY_ADDR_CHECK_SHIFT = 0,
+ OCRDMA_ALLOC_LKEY_ADDR_CHECK_MASK = Bit(0),
+ OCRDMA_ALLOC_LKEY_FMR_SHIFT = 1,
+ OCRDMA_ALLOC_LKEY_FMR_MASK = Bit(1),
+ OCRDMA_ALLOC_LKEY_REMOTE_INV_SHIFT = 2,
+ OCRDMA_ALLOC_LKEY_REMOTE_INV_MASK = Bit(2),
+ OCRDMA_ALLOC_LKEY_REMOTE_WR_SHIFT = 3,
+ OCRDMA_ALLOC_LKEY_REMOTE_WR_MASK = Bit(3),
+ OCRDMA_ALLOC_LKEY_REMOTE_RD_SHIFT = 4,
+ OCRDMA_ALLOC_LKEY_REMOTE_RD_MASK = Bit(4),
+ OCRDMA_ALLOC_LKEY_LOCAL_WR_SHIFT = 5,
+ OCRDMA_ALLOC_LKEY_LOCAL_WR_MASK = Bit(5),
+ OCRDMA_ALLOC_LKEY_REMOTE_ATOMIC_MASK = Bit(6),
+ OCRDMA_ALLOC_LKEY_REMOTE_ATOMIC_SHIFT = 6,
+ OCRDMA_ALLOC_LKEY_PBL_SIZE_SHIFT = 16,
+ OCRDMA_ALLOC_LKEY_PBL_SIZE_MASK = 0xFFFF <<
+ OCRDMA_ALLOC_LKEY_PBL_SIZE_SHIFT
+};
+
+struct ocrdma_alloc_lkey {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+
+ u32 pdid;
+ u32 pbl_sz_flags;
+} __packed;
+
+struct ocrdma_alloc_lkey_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+
+ u32 lrkey;
+ u32 num_pbl_rsvd;
+} __packed;
+
+struct ocrdma_dealloc_lkey {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+
+ u32 lkey;
+ u32 rsvd_frmr;
+} __packed;
+
+struct ocrdma_dealloc_lkey_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+} __packed;
+
+#define MAX_OCRDMA_NSMR_PBL (u32)22
+#define MAX_OCRDMA_PBL_SIZE 65536
+#define MAX_OCRDMA_PBL_PER_LKEY 32767
+
+enum {
+ OCRDMA_REG_NSMR_LRKEY_INDEX_SHIFT = 0,
+ OCRDMA_REG_NSMR_LRKEY_INDEX_MASK = 0xFFFFFF,
+ OCRDMA_REG_NSMR_LRKEY_SHIFT = 24,
+ OCRDMA_REG_NSMR_LRKEY_MASK = 0xFF <<
+ OCRDMA_REG_NSMR_LRKEY_SHIFT,
+
+ OCRDMA_REG_NSMR_PD_ID_SHIFT = 0,
+ OCRDMA_REG_NSMR_PD_ID_MASK = 0xFFFF,
+ OCRDMA_REG_NSMR_NUM_PBL_SHIFT = 16,
+ OCRDMA_REG_NSMR_NUM_PBL_MASK = 0xFFFF <<
+ OCRDMA_REG_NSMR_NUM_PBL_SHIFT,
+
+ OCRDMA_REG_NSMR_PBE_SIZE_SHIFT = 0,
+ OCRDMA_REG_NSMR_PBE_SIZE_MASK = 0xFFFF,
+ OCRDMA_REG_NSMR_HPAGE_SIZE_SHIFT = 16,
+ OCRDMA_REG_NSMR_HPAGE_SIZE_MASK = 0xFF <<
+ OCRDMA_REG_NSMR_HPAGE_SIZE_SHIFT,
+ OCRDMA_REG_NSMR_BIND_MEMWIN_SHIFT = 24,
+ OCRDMA_REG_NSMR_BIND_MEMWIN_MASK = Bit(24),
+ OCRDMA_REG_NSMR_ZB_SHIFT = 25,
+ OCRDMA_REG_NSMR_ZB_SHIFT_MASK = Bit(25),
+ OCRDMA_REG_NSMR_REMOTE_INV_SHIFT = 26,
+ OCRDMA_REG_NSMR_REMOTE_INV_MASK = Bit(26),
+ OCRDMA_REG_NSMR_REMOTE_WR_SHIFT = 27,
+ OCRDMA_REG_NSMR_REMOTE_WR_MASK = Bit(27),
+ OCRDMA_REG_NSMR_REMOTE_RD_SHIFT = 28,
+ OCRDMA_REG_NSMR_REMOTE_RD_MASK = Bit(28),
+ OCRDMA_REG_NSMR_LOCAL_WR_SHIFT = 29,
+ OCRDMA_REG_NSMR_LOCAL_WR_MASK = Bit(29),
+ OCRDMA_REG_NSMR_REMOTE_ATOMIC_SHIFT = 30,
+ OCRDMA_REG_NSMR_REMOTE_ATOMIC_MASK = Bit(30),
+ OCRDMA_REG_NSMR_LAST_SHIFT = 31,
+ OCRDMA_REG_NSMR_LAST_MASK = Bit(31)
+};
+
+struct ocrdma_reg_nsmr {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr cmd;
+
+ u32 lrkey_key_index;
+ u32 num_pbl_pdid;
+ u32 flags_hpage_pbe_sz;
+ u32 totlen_low;
+ u32 totlen_high;
+ u32 fbo_low;
+ u32 fbo_high;
+ u32 va_loaddr;
+ u32 va_hiaddr;
+ struct ocrdma_pa pbl[MAX_OCRDMA_NSMR_PBL];
+} __packed;
+
+enum {
+ OCRDMA_REG_NSMR_CONT_PBL_SHIFT = 0,
+ OCRDMA_REG_NSMR_CONT_PBL_SHIFT_MASK = 0xFFFF,
+ OCRDMA_REG_NSMR_CONT_NUM_PBL_SHIFT = 16,
+ OCRDMA_REG_NSMR_CONT_NUM_PBL_MASK = 0xFFFF <<
+ OCRDMA_REG_NSMR_CONT_NUM_PBL_SHIFT,
+
+ OCRDMA_REG_NSMR_CONT_LAST_SHIFT = 31,
+ OCRDMA_REG_NSMR_CONT_LAST_MASK = Bit(31)
+};
+
+struct ocrdma_reg_nsmr_cont {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr cmd;
+
+ u32 lrkey;
+ u32 num_pbl_offset;
+ u32 last;
+
+ struct ocrdma_pa pbl[MAX_OCRDMA_NSMR_PBL];
+} __packed;
+
+struct ocrdma_pbe {
+ u32 pa_hi;
+ u32 pa_lo;
+} __packed;
+
+enum {
+ OCRDMA_REG_NSMR_RSP_NUM_PBL_SHIFT = 16,
+ OCRDMA_REG_NSMR_RSP_NUM_PBL_MASK = 0xFFFF0000
+};
+struct ocrdma_reg_nsmr_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+
+ u32 lrkey;
+ u32 num_pbl;
+} __packed;
+
+enum {
+ OCRDMA_REG_NSMR_CONT_RSP_LRKEY_INDEX_SHIFT = 0,
+ OCRDMA_REG_NSMR_CONT_RSP_LRKEY_INDEX_MASK = 0xFFFFFF,
+ OCRDMA_REG_NSMR_CONT_RSP_LRKEY_SHIFT = 24,
+ OCRDMA_REG_NSMR_CONT_RSP_LRKEY_MASK = 0xFF <<
+ OCRDMA_REG_NSMR_CONT_RSP_LRKEY_SHIFT,
+
+ OCRDMA_REG_NSMR_CONT_RSP_NUM_PBL_SHIFT = 16,
+ OCRDMA_REG_NSMR_CONT_RSP_NUM_PBL_MASK = 0xFFFF <<
+ OCRDMA_REG_NSMR_CONT_RSP_NUM_PBL_SHIFT
+};
+
+struct ocrdma_reg_nsmr_cont_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+
+ u32 lrkey_key_index;
+ u32 num_pbl;
+} __packed;
+
+enum {
+ OCRDMA_ALLOC_MW_PD_ID_SHIFT = 0,
+ OCRDMA_ALLOC_MW_PD_ID_MASK = 0xFFFF
+};
+
+struct ocrdma_alloc_mw {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+
+ u32 pdid;
+} __packed;
+
+enum {
+ OCRDMA_ALLOC_MW_RSP_LRKEY_INDEX_SHIFT = 0,
+ OCRDMA_ALLOC_MW_RSP_LRKEY_INDEX_MASK = 0xFFFFFF
+};
+
+struct ocrdma_alloc_mw_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+
+ u32 lrkey_index;
+} __packed;
+
+struct ocrdma_attach_mcast {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+ u32 qp_id;
+ u8 mgid[16];
+ u32 mac_b0_to_b3;
+ u32 vlan_mac_b4_to_b5;
+} __packed;
+
+struct ocrdma_attach_mcast_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+} __packed;
+
+struct ocrdma_detach_mcast {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+ u32 qp_id;
+ u8 mgid[16];
+ u32 mac_b0_to_b3;
+ u32 vlan_mac_b4_to_b5;
+} __packed;
+
+struct ocrdma_detach_mcast_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+} __packed;
+
+enum {
+ OCRDMA_CREATE_AH_NUM_PAGES_SHIFT = 19,
+ OCRDMA_CREATE_AH_NUM_PAGES_MASK = 0xF <<
+ OCRDMA_CREATE_AH_NUM_PAGES_SHIFT,
+
+ OCRDMA_CREATE_AH_PAGE_SIZE_SHIFT = 16,
+ OCRDMA_CREATE_AH_PAGE_SIZE_MASK = 0x7 <<
+ OCRDMA_CREATE_AH_PAGE_SIZE_SHIFT,
+
+ OCRDMA_CREATE_AH_ENTRY_SIZE_SHIFT = 23,
+ OCRDMA_CREATE_AH_ENTRY_SIZE_MASK = 0x1FF <<
+ OCRDMA_CREATE_AH_ENTRY_SIZE_SHIFT,
+};
+
+#define OCRDMA_AH_TBL_PAGES 8
+
+struct ocrdma_create_ah_tbl {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+
+ u32 ah_conf;
+ struct ocrdma_pa tbl_addr[8];
+} __packed;
+
+struct ocrdma_create_ah_tbl_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+ u32 ahid;
+} __packed;
+
+struct ocrdma_delete_ah_tbl {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_hdr req;
+ u32 ahid;
+} __packed;
+
+struct ocrdma_delete_ah_tbl_rsp {
+ struct ocrdma_mqe_hdr hdr;
+ struct ocrdma_mbx_rsp rsp;
+} __packed;
+
+enum {
+ OCRDMA_EQE_VALID_SHIFT = 0,
+ OCRDMA_EQE_VALID_MASK = Bit(0),
+ OCRDMA_EQE_FOR_CQE_MASK = 0xFFFE,
+ OCRDMA_EQE_RESOURCE_ID_SHIFT = 16,
+ OCRDMA_EQE_RESOURCE_ID_MASK = 0xFFFF <<
+ OCRDMA_EQE_RESOURCE_ID_SHIFT,
+};
+
+struct ocrdma_eqe {
+ u32 id_valid;
+} __packed;
+
+enum OCRDMA_CQE_STATUS {
+ OCRDMA_CQE_SUCCESS = 0,
+ OCRDMA_CQE_LOC_LEN_ERR,
+ OCRDMA_CQE_LOC_QP_OP_ERR,
+ OCRDMA_CQE_LOC_EEC_OP_ERR,
+ OCRDMA_CQE_LOC_PROT_ERR,
+ OCRDMA_CQE_WR_FLUSH_ERR,
+ OCRDMA_CQE_MW_BIND_ERR,
+ OCRDMA_CQE_BAD_RESP_ERR,
+ OCRDMA_CQE_LOC_ACCESS_ERR,
+ OCRDMA_CQE_REM_INV_REQ_ERR,
+ OCRDMA_CQE_REM_ACCESS_ERR,
+ OCRDMA_CQE_REM_OP_ERR,
+ OCRDMA_CQE_RETRY_EXC_ERR,
+ OCRDMA_CQE_RNR_RETRY_EXC_ERR,
+ OCRDMA_CQE_LOC_RDD_VIOL_ERR,
+ OCRDMA_CQE_REM_INV_RD_REQ_ERR,
+ OCRDMA_CQE_REM_ABORT_ERR,
+ OCRDMA_CQE_INV_EECN_ERR,
+ OCRDMA_CQE_INV_EEC_STATE_ERR,
+ OCRDMA_CQE_FATAL_ERR,
+ OCRDMA_CQE_RESP_TIMEOUT_ERR,
+ OCRDMA_CQE_GENERAL_ERR
+};
+
+enum {
+ /* w0 */
+ OCRDMA_CQE_WQEIDX_SHIFT = 0,
+ OCRDMA_CQE_WQEIDX_MASK = 0xFFFF,
+
+ /* w1 */
+ OCRDMA_CQE_UD_XFER_LEN_SHIFT = 16,
+ OCRDMA_CQE_PKEY_SHIFT = 0,
+ OCRDMA_CQE_PKEY_MASK = 0xFFFF,
+
+ /* w2 */
+ OCRDMA_CQE_QPN_SHIFT = 0,
+ OCRDMA_CQE_QPN_MASK = 0x0000FFFF,
+
+ OCRDMA_CQE_BUFTAG_SHIFT = 16,
+ OCRDMA_CQE_BUFTAG_MASK = 0xFFFF << OCRDMA_CQE_BUFTAG_SHIFT,
+
+ /* w3 */
+ OCRDMA_CQE_UD_STATUS_SHIFT = 24,
+ OCRDMA_CQE_UD_STATUS_MASK = 0x7 << OCRDMA_CQE_UD_STATUS_SHIFT,
+ OCRDMA_CQE_STATUS_SHIFT = 16,
+ OCRDMA_CQE_STATUS_MASK = 0xFF << OCRDMA_CQE_STATUS_SHIFT,
+ OCRDMA_CQE_VALID = Bit(31),
+ OCRDMA_CQE_INVALIDATE = Bit(30),
+ OCRDMA_CQE_QTYPE = Bit(29),
+ OCRDMA_CQE_IMM = Bit(28),
+ OCRDMA_CQE_WRITE_IMM = Bit(27),
+ OCRDMA_CQE_QTYPE_SQ = 0,
+ OCRDMA_CQE_QTYPE_RQ = 1,
+ OCRDMA_CQE_SRCQP_MASK = 0xFFFFFF
+};
+
+struct ocrdma_cqe {
+ union {
+ /* w0 to w2 */
+ struct {
+ u32 wqeidx;
+ u32 bytes_xfered;
+ u32 qpn;
+ } wq;
+ struct {
+ u32 lkey_immdt;
+ u32 rxlen;
+ u32 buftag_qpn;
+ } rq;
+ struct {
+ u32 lkey_immdt;
+ u32 rxlen_pkey;
+ u32 buftag_qpn;
+ } ud;
+ struct {
+ u32 word_0;
+ u32 word_1;
+ u32 qpn;
+ } cmn;
+ };
+ u32 flags_status_srcqpn; /* w3 */
+} __packed;
+
+#define is_cqe_valid(cq, cqe) \
+ (((le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_VALID)\
+ == cq->phase) ? 1 : 0)
+#define is_cqe_for_sq(cqe) \
+ ((le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_QTYPE) ? 0 : 1)
+#define is_cqe_for_rq(cqe) \
+ ((le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_QTYPE) ? 1 : 0)
+#define is_cqe_invalidated(cqe) \
+ ((le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_INVALIDATE) ? \
+ 1 : 0)
+#define is_cqe_imm(cqe) \
+ ((le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_IMM) ? 1 : 0)
+#define is_cqe_wr_imm(cqe) \
+ ((le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_WRITE_IMM) ? 1 : 0)
+
+struct ocrdma_sge {
+ u32 addr_hi;
+ u32 addr_lo;
+ u32 lrkey;
+ u32 len;
+} __packed;
+
+enum {
+ OCRDMA_FLAG_SIG = 0x1,
+ OCRDMA_FLAG_INV = 0x2,
+ OCRDMA_FLAG_FENCE_L = 0x4,
+ OCRDMA_FLAG_FENCE_R = 0x8,
+ OCRDMA_FLAG_SOLICIT = 0x10,
+ OCRDMA_FLAG_IMM = 0x20,
+
+ /* Stag flags */
+ OCRDMA_LKEY_FLAG_LOCAL_WR = 0x1,
+ OCRDMA_LKEY_FLAG_REMOTE_RD = 0x2,
+ OCRDMA_LKEY_FLAG_REMOTE_WR = 0x4,
+ OCRDMA_LKEY_FLAG_VATO = 0x8,
+};
+
+enum OCRDMA_WQE_OPCODE {
+ OCRDMA_WRITE = 0x06,
+ OCRDMA_READ = 0x0C,
+ OCRDMA_RESV0 = 0x02,
+ OCRDMA_SEND = 0x00,
+ OCRDMA_CMP_SWP = 0x14,
+ OCRDMA_BIND_MW = 0x10,
+ OCRDMA_RESV1 = 0x0A,
+ OCRDMA_LKEY_INV = 0x15,
+ OCRDMA_FETCH_ADD = 0x13,
+ OCRDMA_POST_RQ = 0x12
+};
+
+enum {
+ OCRDMA_TYPE_INLINE = 0x0,
+ OCRDMA_TYPE_LKEY = 0x1,
+};
+
+enum {
+ OCRDMA_WQE_OPCODE_SHIFT = 0,
+ OCRDMA_WQE_OPCODE_MASK = 0x0000001F,
+ OCRDMA_WQE_FLAGS_SHIFT = 5,
+ OCRDMA_WQE_TYPE_SHIFT = 16,
+ OCRDMA_WQE_TYPE_MASK = 0x00030000,
+ OCRDMA_WQE_SIZE_SHIFT = 18,
+ OCRDMA_WQE_SIZE_MASK = 0xFF,
+ OCRDMA_WQE_NXT_WQE_SIZE_SHIFT = 25,
+
+ OCRDMA_WQE_LKEY_FLAGS_SHIFT = 0,
+ OCRDMA_WQE_LKEY_FLAGS_MASK = 0xF
+};
+
+/* header WQE for all the SQ and RQ operations */
+struct ocrdma_hdr_wqe {
+ u32 cw;
+ union {
+ u32 rsvd_tag;
+ u32 rsvd_lkey_flags;
+ };
+ union {
+ u32 immdt;
+ u32 lkey;
+ };
+ u32 total_len;
+} __packed;
+
+struct ocrdma_ewqe_ud_hdr {
+ u32 rsvd_dest_qpn;
+ u32 qkey;
+ u32 rsvd_ahid;
+ u32 rsvd;
+} __packed;
+
+struct ocrdma_eth_basic {
+ u8 dmac[6];
+ u8 smac[6];
+ __be16 eth_type;
+} __packed;
+
+struct ocrdma_eth_vlan {
+ u8 dmac[6];
+ u8 smac[6];
+ __be16 eth_type;
+ __be16 vlan_tag;
+#define OCRDMA_ROCE_ETH_TYPE 0x8915
+ __be16 roce_eth_type;
+} __packed;
+
+struct ocrdma_grh {
+ __be32 tclass_flow;
+ __be32 pdid_hoplimit;
+ u8 sgid[16];
+ u8 dgid[16];
+ u16 rsvd;
+} __packed;
+
+#define OCRDMA_AV_VALID Bit(0)
+#define OCRDMA_AV_VLAN_VALID Bit(1)
+
+struct ocrdma_av {
+ struct ocrdma_eth_vlan eth_hdr;
+ struct ocrdma_grh grh;
+ u32 valid;
+} __packed;
+
+#endif /* __OCRDMA_SLI_H__ */
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
new file mode 100644
index 000000000000..e9f74d1b48f6
--- /dev/null
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -0,0 +1,2537 @@
+/*******************************************************************
+ * This file is part of the Emulex RoCE Device Driver for *
+ * RoCE (RDMA over Converged Ethernet) adapters. *
+ * Copyright (C) 2008-2012 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.emulex.com *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of version 2 of the GNU General *
+ * Public License as published by the Free Software Foundation. *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID. See the GNU General Public License for *
+ * more details, a copy of which can be found in the file COPYING *
+ * included with this package. *
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ *******************************************************************/
+
+#include <linux/dma-mapping.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_user_verbs.h>
+#include <rdma/iw_cm.h>
+#include <rdma/ib_umem.h>
+#include <rdma/ib_addr.h>
+
+#include "ocrdma.h"
+#include "ocrdma_hw.h"
+#include "ocrdma_verbs.h"
+#include "ocrdma_abi.h"
+
+int ocrdma_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
+{
+ if (index > 1)
+ return -EINVAL;
+
+ *pkey = 0xffff;
+ return 0;
+}
+
+int ocrdma_query_gid(struct ib_device *ibdev, u8 port,
+ int index, union ib_gid *sgid)
+{
+ struct ocrdma_dev *dev;
+
+ dev = get_ocrdma_dev(ibdev);
+ memset(sgid, 0, sizeof(*sgid));
+ if (index > OCRDMA_MAX_SGID)
+ return -EINVAL;
+
+ memcpy(sgid, &dev->sgid_tbl[index], sizeof(*sgid));
+
+ return 0;
+}
+
+int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr)
+{
+ struct ocrdma_dev *dev = get_ocrdma_dev(ibdev);
+
+ memset(attr, 0, sizeof *attr);
+ memcpy(&attr->fw_ver, &dev->attr.fw_ver[0],
+ min(sizeof(dev->attr.fw_ver), sizeof(attr->fw_ver)));
+ ocrdma_get_guid(dev, (u8 *)&attr->sys_image_guid);
+ attr->max_mr_size = ~0ull;
+ attr->page_size_cap = 0xffff000;
+ attr->vendor_id = dev->nic_info.pdev->vendor;
+ attr->vendor_part_id = dev->nic_info.pdev->device;
+ attr->hw_ver = 0;
+ attr->max_qp = dev->attr.max_qp;
+ attr->max_ah = dev->attr.max_qp;
+ attr->max_qp_wr = dev->attr.max_wqe;
+
+ attr->device_cap_flags = IB_DEVICE_CURR_QP_STATE_MOD |
+ IB_DEVICE_RC_RNR_NAK_GEN |
+ IB_DEVICE_SHUTDOWN_PORT |
+ IB_DEVICE_SYS_IMAGE_GUID |
+ IB_DEVICE_LOCAL_DMA_LKEY;
+ attr->max_sge = dev->attr.max_send_sge;
+ attr->max_sge_rd = dev->attr.max_send_sge;
+ attr->max_cq = dev->attr.max_cq;
+ attr->max_cqe = dev->attr.max_cqe;
+ attr->max_mr = dev->attr.max_mr;
+ attr->max_mw = 0;
+ attr->max_pd = dev->attr.max_pd;
+ attr->atomic_cap = 0;
+ attr->max_fmr = 0;
+ attr->max_map_per_fmr = 0;
+ attr->max_qp_rd_atom =
+ min(dev->attr.max_ord_per_qp, dev->attr.max_ird_per_qp);
+ attr->max_qp_init_rd_atom = dev->attr.max_ord_per_qp;
+ attr->max_srq = (dev->attr.max_qp - 1);
+ attr->max_srq_sge = attr->max_sge;
+ attr->max_srq_wr = dev->attr.max_rqe;
+ attr->local_ca_ack_delay = dev->attr.local_ca_ack_delay;
+ attr->max_fast_reg_page_list_len = 0;
+ attr->max_pkeys = 1;
+ return 0;
+}
+
+int ocrdma_query_port(struct ib_device *ibdev,
+ u8 port, struct ib_port_attr *props)
+{
+ enum ib_port_state port_state;
+ struct ocrdma_dev *dev;
+ struct net_device *netdev;
+
+ dev = get_ocrdma_dev(ibdev);
+ if (port > 1) {
+ ocrdma_err("%s(%d) invalid_port=0x%x\n", __func__,
+ dev->id, port);
+ return -EINVAL;
+ }
+ netdev = dev->nic_info.netdev;
+ if (netif_running(netdev) && netif_oper_up(netdev)) {
+ port_state = IB_PORT_ACTIVE;
+ props->phys_state = 5;
+ } else {
+ port_state = IB_PORT_DOWN;
+ props->phys_state = 3;
+ }
+ props->max_mtu = IB_MTU_4096;
+ props->active_mtu = iboe_get_mtu(netdev->mtu);
+ props->lid = 0;
+ props->lmc = 0;
+ props->sm_lid = 0;
+ props->sm_sl = 0;
+ props->state = port_state;
+ props->port_cap_flags =
+ IB_PORT_CM_SUP |
+ IB_PORT_REINIT_SUP |
+ IB_PORT_DEVICE_MGMT_SUP | IB_PORT_VENDOR_CLASS_SUP;
+ props->gid_tbl_len = OCRDMA_MAX_SGID;
+ props->pkey_tbl_len = 1;
+ props->bad_pkey_cntr = 0;
+ props->qkey_viol_cntr = 0;
+ props->active_width = IB_WIDTH_1X;
+ props->active_speed = 4;
+ props->max_msg_sz = 0x80000000;
+ props->max_vl_num = 4;
+ return 0;
+}
+
+int ocrdma_modify_port(struct ib_device *ibdev, u8 port, int mask,
+ struct ib_port_modify *props)
+{
+ struct ocrdma_dev *dev;
+
+ dev = get_ocrdma_dev(ibdev);
+ if (port > 1) {
+ ocrdma_err("%s(%d) invalid_port=0x%x\n", __func__,
+ dev->id, port);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int ocrdma_add_mmap(struct ocrdma_ucontext *uctx, u64 phy_addr,
+ unsigned long len)
+{
+ struct ocrdma_mm *mm;
+
+ mm = kzalloc(sizeof(*mm), GFP_KERNEL);
+ if (mm == NULL)
+ return -ENOMEM;
+ mm->key.phy_addr = phy_addr;
+ mm->key.len = len;
+ INIT_LIST_HEAD(&mm->entry);
+
+ mutex_lock(&uctx->mm_list_lock);
+ list_add_tail(&mm->entry, &uctx->mm_head);
+ mutex_unlock(&uctx->mm_list_lock);
+ return 0;
+}
+
+static void ocrdma_del_mmap(struct ocrdma_ucontext *uctx, u64 phy_addr,
+ unsigned long len)
+{
+ struct ocrdma_mm *mm, *tmp;
+
+ mutex_lock(&uctx->mm_list_lock);
+ list_for_each_entry_safe(mm, tmp, &uctx->mm_head, entry) {
+ if (len != mm->key.len || phy_addr != mm->key.phy_addr)
+ continue;
+
+ list_del(&mm->entry);
+ kfree(mm);
+ break;
+ }
+ mutex_unlock(&uctx->mm_list_lock);
+}
+
+static bool ocrdma_search_mmap(struct ocrdma_ucontext *uctx, u64 phy_addr,
+ unsigned long len)
+{
+ bool found = false;
+ struct ocrdma_mm *mm;
+
+ mutex_lock(&uctx->mm_list_lock);
+ list_for_each_entry(mm, &uctx->mm_head, entry) {
+ if (len != mm->key.len || phy_addr != mm->key.phy_addr)
+ continue;
+
+ found = true;
+ break;
+ }
+ mutex_unlock(&uctx->mm_list_lock);
+ return found;
+}
+
+struct ib_ucontext *ocrdma_alloc_ucontext(struct ib_device *ibdev,
+ struct ib_udata *udata)
+{
+ int status;
+ struct ocrdma_ucontext *ctx;
+ struct ocrdma_alloc_ucontext_resp resp;
+ struct ocrdma_dev *dev = get_ocrdma_dev(ibdev);
+ struct pci_dev *pdev = dev->nic_info.pdev;
+ u32 map_len = roundup(sizeof(u32) * 2048, PAGE_SIZE);
+
+ if (!udata)
+ return ERR_PTR(-EFAULT);
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return ERR_PTR(-ENOMEM);
+ ctx->dev = dev;
+ INIT_LIST_HEAD(&ctx->mm_head);
+ mutex_init(&ctx->mm_list_lock);
+
+ ctx->ah_tbl.va = dma_alloc_coherent(&pdev->dev, map_len,
+ &ctx->ah_tbl.pa, GFP_KERNEL);
+ if (!ctx->ah_tbl.va) {
+ kfree(ctx);
+ return ERR_PTR(-ENOMEM);
+ }
+ memset(ctx->ah_tbl.va, 0, map_len);
+ ctx->ah_tbl.len = map_len;
+
+ resp.ah_tbl_len = ctx->ah_tbl.len;
+ resp.ah_tbl_page = ctx->ah_tbl.pa;
+
+ status = ocrdma_add_mmap(ctx, resp.ah_tbl_page, resp.ah_tbl_len);
+ if (status)
+ goto map_err;
+ resp.dev_id = dev->id;
+ resp.max_inline_data = dev->attr.max_inline_data;
+ resp.wqe_size = dev->attr.wqe_size;
+ resp.rqe_size = dev->attr.rqe_size;
+ resp.dpp_wqe_size = dev->attr.wqe_size;
+ resp.rsvd = 0;
+
+ memcpy(resp.fw_ver, dev->attr.fw_ver, sizeof(resp.fw_ver));
+ status = ib_copy_to_udata(udata, &resp, sizeof(resp));
+ if (status)
+ goto cpy_err;
+ return &ctx->ibucontext;
+
+cpy_err:
+ ocrdma_del_mmap(ctx, ctx->ah_tbl.pa, ctx->ah_tbl.len);
+map_err:
+ dma_free_coherent(&pdev->dev, ctx->ah_tbl.len, ctx->ah_tbl.va,
+ ctx->ah_tbl.pa);
+ kfree(ctx);
+ return ERR_PTR(status);
+}
+
+int ocrdma_dealloc_ucontext(struct ib_ucontext *ibctx)
+{
+ struct ocrdma_mm *mm, *tmp;
+ struct ocrdma_ucontext *uctx = get_ocrdma_ucontext(ibctx);
+ struct pci_dev *pdev = uctx->dev->nic_info.pdev;
+
+ ocrdma_del_mmap(uctx, uctx->ah_tbl.pa, uctx->ah_tbl.len);
+ dma_free_coherent(&pdev->dev, uctx->ah_tbl.len, uctx->ah_tbl.va,
+ uctx->ah_tbl.pa);
+
+ list_for_each_entry_safe(mm, tmp, &uctx->mm_head, entry) {
+ list_del(&mm->entry);
+ kfree(mm);
+ }
+ kfree(uctx);
+ return 0;
+}
+
+int ocrdma_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+{
+ struct ocrdma_ucontext *ucontext = get_ocrdma_ucontext(context);
+ struct ocrdma_dev *dev = ucontext->dev;
+ unsigned long vm_page = vma->vm_pgoff << PAGE_SHIFT;
+ u64 unmapped_db = (u64) dev->nic_info.unmapped_db;
+ unsigned long len = (vma->vm_end - vma->vm_start);
+ int status = 0;
+ bool found;
+
+ if (vma->vm_start & (PAGE_SIZE - 1))
+ return -EINVAL;
+ found = ocrdma_search_mmap(ucontext, vma->vm_pgoff << PAGE_SHIFT, len);
+ if (!found)
+ return -EINVAL;
+
+ if ((vm_page >= unmapped_db) && (vm_page <= (unmapped_db +
+ dev->nic_info.db_total_size)) &&
+ (len <= dev->nic_info.db_page_size)) {
+ /* doorbell mapping */
+ status = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ len, vma->vm_page_prot);
+ } else if (dev->nic_info.dpp_unmapped_len &&
+ (vm_page >= (u64) dev->nic_info.dpp_unmapped_addr) &&
+ (vm_page <= (u64) (dev->nic_info.dpp_unmapped_addr +
+ dev->nic_info.dpp_unmapped_len)) &&
+ (len <= dev->nic_info.dpp_unmapped_len)) {
+ /* dpp area mapping */
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ status = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ len, vma->vm_page_prot);
+ } else {
+ /* queue memory mapping */
+ status = remap_pfn_range(vma, vma->vm_start,
+ vma->vm_pgoff, len, vma->vm_page_prot);
+ }
+ return status;
+}
+
+static int ocrdma_copy_pd_uresp(struct ocrdma_pd *pd,
+ struct ib_ucontext *ib_ctx,
+ struct ib_udata *udata)
+{
+ int status;
+ u64 db_page_addr;
+ u64 dpp_page_addr = 0;
+ u32 db_page_size;
+ struct ocrdma_alloc_pd_uresp rsp;
+ struct ocrdma_ucontext *uctx = get_ocrdma_ucontext(ib_ctx);
+
+ rsp.id = pd->id;
+ rsp.dpp_enabled = pd->dpp_enabled;
+ db_page_addr = pd->dev->nic_info.unmapped_db +
+ (pd->id * pd->dev->nic_info.db_page_size);
+ db_page_size = pd->dev->nic_info.db_page_size;
+
+ status = ocrdma_add_mmap(uctx, db_page_addr, db_page_size);
+ if (status)
+ return status;
+
+ if (pd->dpp_enabled) {
+ dpp_page_addr = pd->dev->nic_info.dpp_unmapped_addr +
+ (pd->id * OCRDMA_DPP_PAGE_SIZE);
+ status = ocrdma_add_mmap(uctx, dpp_page_addr,
+ OCRDMA_DPP_PAGE_SIZE);
+ if (status)
+ goto dpp_map_err;
+ rsp.dpp_page_addr_hi = upper_32_bits(dpp_page_addr);
+ rsp.dpp_page_addr_lo = dpp_page_addr;
+ }
+
+ status = ib_copy_to_udata(udata, &rsp, sizeof(rsp));
+ if (status)
+ goto ucopy_err;
+
+ pd->uctx = uctx;
+ return 0;
+
+ucopy_err:
+ if (pd->dpp_enabled)
+ ocrdma_del_mmap(pd->uctx, dpp_page_addr, OCRDMA_DPP_PAGE_SIZE);
+dpp_map_err:
+ ocrdma_del_mmap(pd->uctx, db_page_addr, db_page_size);
+ return status;
+}
+
+struct ib_pd *ocrdma_alloc_pd(struct ib_device *ibdev,
+ struct ib_ucontext *context,
+ struct ib_udata *udata)
+{
+ struct ocrdma_dev *dev = get_ocrdma_dev(ibdev);
+ struct ocrdma_pd *pd;
+ int status;
+
+ pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return ERR_PTR(-ENOMEM);
+ pd->dev = dev;
+ if (udata && context) {
+ pd->dpp_enabled = (dev->nic_info.dev_family ==
+ OCRDMA_GEN2_FAMILY) ? true : false;
+ pd->num_dpp_qp =
+ pd->dpp_enabled ? OCRDMA_PD_MAX_DPP_ENABLED_QP : 0;
+ }
+ status = ocrdma_mbx_alloc_pd(dev, pd);
+ if (status) {
+ kfree(pd);
+ return ERR_PTR(status);
+ }
+ atomic_set(&pd->use_cnt, 0);
+
+ if (udata && context) {
+ status = ocrdma_copy_pd_uresp(pd, context, udata);
+ if (status)
+ goto err;
+ }
+ return &pd->ibpd;
+
+err:
+ ocrdma_dealloc_pd(&pd->ibpd);
+ return ERR_PTR(status);
+}
+
+int ocrdma_dealloc_pd(struct ib_pd *ibpd)
+{
+ struct ocrdma_pd *pd = get_ocrdma_pd(ibpd);
+ struct ocrdma_dev *dev = pd->dev;
+ int status;
+ u64 usr_db;
+
+ if (atomic_read(&pd->use_cnt)) {
+ ocrdma_err("%s(%d) pd=0x%x is in use.\n",
+ __func__, dev->id, pd->id);
+ status = -EFAULT;
+ goto dealloc_err;
+ }
+ status = ocrdma_mbx_dealloc_pd(dev, pd);
+ if (pd->uctx) {
+ u64 dpp_db = dev->nic_info.dpp_unmapped_addr +
+ (pd->id * OCRDMA_DPP_PAGE_SIZE);
+ if (pd->dpp_enabled)
+ ocrdma_del_mmap(pd->uctx, dpp_db, OCRDMA_DPP_PAGE_SIZE);
+ usr_db = dev->nic_info.unmapped_db +
+ (pd->id * dev->nic_info.db_page_size);
+ ocrdma_del_mmap(pd->uctx, usr_db, dev->nic_info.db_page_size);
+ }
+ kfree(pd);
+dealloc_err:
+ return status;
+}
+
+static struct ocrdma_mr *ocrdma_alloc_lkey(struct ib_pd *ibpd,
+ int acc, u32 num_pbls,
+ u32 addr_check)
+{
+ int status;
+ struct ocrdma_mr *mr;
+ struct ocrdma_pd *pd = get_ocrdma_pd(ibpd);
+ struct ocrdma_dev *dev = pd->dev;
+
+ if (acc & IB_ACCESS_REMOTE_WRITE && !(acc & IB_ACCESS_LOCAL_WRITE)) {
+ ocrdma_err("%s(%d) leaving err, invalid access rights\n",
+ __func__, dev->id);
+ return ERR_PTR(-EINVAL);
+ }
+
+ mr = kzalloc(sizeof(*mr), GFP_KERNEL);
+ if (!mr)
+ return ERR_PTR(-ENOMEM);
+ mr->hwmr.dev = dev;
+ mr->hwmr.fr_mr = 0;
+ mr->hwmr.local_rd = 1;
+ mr->hwmr.remote_rd = (acc & IB_ACCESS_REMOTE_READ) ? 1 : 0;
+ mr->hwmr.remote_wr = (acc & IB_ACCESS_REMOTE_WRITE) ? 1 : 0;
+ mr->hwmr.local_wr = (acc & IB_ACCESS_LOCAL_WRITE) ? 1 : 0;
+ mr->hwmr.mw_bind = (acc & IB_ACCESS_MW_BIND) ? 1 : 0;
+ mr->hwmr.remote_atomic = (acc & IB_ACCESS_REMOTE_ATOMIC) ? 1 : 0;
+ mr->hwmr.num_pbls = num_pbls;
+
+ status = ocrdma_mbx_alloc_lkey(dev, &mr->hwmr, pd->id, addr_check);
+ if (status) {
+ kfree(mr);
+ return ERR_PTR(-ENOMEM);
+ }
+ mr->pd = pd;
+ atomic_inc(&pd->use_cnt);
+ mr->ibmr.lkey = mr->hwmr.lkey;
+ if (mr->hwmr.remote_wr || mr->hwmr.remote_rd)
+ mr->ibmr.rkey = mr->hwmr.lkey;
+ return mr;
+}
+
+struct ib_mr *ocrdma_get_dma_mr(struct ib_pd *ibpd, int acc)
+{
+ struct ocrdma_mr *mr;
+
+ mr = ocrdma_alloc_lkey(ibpd, acc, 0, OCRDMA_ADDR_CHECK_DISABLE);
+ if (IS_ERR(mr))
+ return ERR_CAST(mr);
+
+ return &mr->ibmr;
+}
+
+static void ocrdma_free_mr_pbl_tbl(struct ocrdma_dev *dev,
+ struct ocrdma_hw_mr *mr)
+{
+ struct pci_dev *pdev = dev->nic_info.pdev;
+ int i = 0;
+
+ if (mr->pbl_table) {
+ for (i = 0; i < mr->num_pbls; i++) {
+ if (!mr->pbl_table[i].va)
+ continue;
+ dma_free_coherent(&pdev->dev, mr->pbl_size,
+ mr->pbl_table[i].va,
+ mr->pbl_table[i].pa);
+ }
+ kfree(mr->pbl_table);
+ mr->pbl_table = NULL;
+ }
+}
+
+static int ocrdma_get_pbl_info(struct ocrdma_mr *mr, u32 num_pbes)
+{
+ u32 num_pbls = 0;
+ u32 idx = 0;
+ int status = 0;
+ u32 pbl_size;
+
+ do {
+ pbl_size = OCRDMA_MIN_HPAGE_SIZE * (1 << idx);
+ if (pbl_size > MAX_OCRDMA_PBL_SIZE) {
+ status = -EFAULT;
+ break;
+ }
+ num_pbls = roundup(num_pbes, (pbl_size / sizeof(u64)));
+ num_pbls = num_pbls / (pbl_size / sizeof(u64));
+ idx++;
+ } while (num_pbls >= mr->hwmr.dev->attr.max_num_mr_pbl);
+
+ mr->hwmr.num_pbes = num_pbes;
+ mr->hwmr.num_pbls = num_pbls;
+ mr->hwmr.pbl_size = pbl_size;
+ return status;
+}
+
+static int ocrdma_build_pbl_tbl(struct ocrdma_dev *dev, struct ocrdma_hw_mr *mr)
+{
+ int status = 0;
+ int i;
+ u32 dma_len = mr->pbl_size;
+ struct pci_dev *pdev = dev->nic_info.pdev;
+ void *va;
+ dma_addr_t pa;
+
+ mr->pbl_table = kzalloc(sizeof(struct ocrdma_pbl) *
+ mr->num_pbls, GFP_KERNEL);
+
+ if (!mr->pbl_table)
+ return -ENOMEM;
+
+ for (i = 0; i < mr->num_pbls; i++) {
+ va = dma_alloc_coherent(&pdev->dev, dma_len, &pa, GFP_KERNEL);
+ if (!va) {
+ ocrdma_free_mr_pbl_tbl(dev, mr);
+ status = -ENOMEM;
+ break;
+ }
+ memset(va, 0, dma_len);
+ mr->pbl_table[i].va = va;
+ mr->pbl_table[i].pa = pa;
+ }
+ return status;
+}
+
+static void build_user_pbes(struct ocrdma_dev *dev, struct ocrdma_mr *mr,
+ u32 num_pbes)
+{
+ struct ocrdma_pbe *pbe;
+ struct ib_umem_chunk *chunk;
+ struct ocrdma_pbl *pbl_tbl = mr->hwmr.pbl_table;
+ struct ib_umem *umem = mr->umem;
+ int i, shift, pg_cnt, pages, pbe_cnt, total_num_pbes = 0;
+
+ if (!mr->hwmr.num_pbes)
+ return;
+
+ pbe = (struct ocrdma_pbe *)pbl_tbl->va;
+ pbe_cnt = 0;
+
+ shift = ilog2(umem->page_size);
+
+ list_for_each_entry(chunk, &umem->chunk_list, list) {
+ /* get all the dma regions from the chunk. */
+ for (i = 0; i < chunk->nmap; i++) {
+ pages = sg_dma_len(&chunk->page_list[i]) >> shift;
+ for (pg_cnt = 0; pg_cnt < pages; pg_cnt++) {
+ /* store the page address in pbe */
+ pbe->pa_lo =
+ cpu_to_le32(sg_dma_address
+ (&chunk->page_list[i]) +
+ (umem->page_size * pg_cnt));
+ pbe->pa_hi =
+ cpu_to_le32(upper_32_bits
+ ((sg_dma_address
+ (&chunk->page_list[i]) +
+ umem->page_size * pg_cnt)));
+ pbe_cnt += 1;
+ total_num_pbes += 1;
+ pbe++;
+
+ /* if done building pbes, issue the mbx cmd. */
+ if (total_num_pbes == num_pbes)
+ return;
+
+ /* if the given pbl is full storing the pbes,
+ * move to next pbl.
+ */
+ if (pbe_cnt ==
+ (mr->hwmr.pbl_size / sizeof(u64))) {
+ pbl_tbl++;
+ pbe = (struct ocrdma_pbe *)pbl_tbl->va;
+ pbe_cnt = 0;
+ }
+ }
+ }
+ }
+}
+
+struct ib_mr *ocrdma_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 len,
+ u64 usr_addr, int acc, struct ib_udata *udata)
+{
+ int status = -ENOMEM;
+ struct ocrdma_dev *dev;
+ struct ocrdma_mr *mr;
+ struct ocrdma_pd *pd;
+ u32 num_pbes;
+
+ pd = get_ocrdma_pd(ibpd);
+ dev = pd->dev;
+
+ if (acc & IB_ACCESS_REMOTE_WRITE && !(acc & IB_ACCESS_LOCAL_WRITE))
+ return ERR_PTR(-EINVAL);
+
+ mr = kzalloc(sizeof(*mr), GFP_KERNEL);
+ if (!mr)
+ return ERR_PTR(status);
+ mr->hwmr.dev = dev;
+ mr->umem = ib_umem_get(ibpd->uobject->context, start, len, acc, 0);
+ if (IS_ERR(mr->umem)) {
+ status = -EFAULT;
+ goto umem_err;
+ }
+ num_pbes = ib_umem_page_count(mr->umem);
+ status = ocrdma_get_pbl_info(mr, num_pbes);
+ if (status)
+ goto umem_err;
+
+ mr->hwmr.pbe_size = mr->umem->page_size;
+ mr->hwmr.fbo = mr->umem->offset;
+ mr->hwmr.va = usr_addr;
+ mr->hwmr.len = len;
+ mr->hwmr.remote_wr = (acc & IB_ACCESS_REMOTE_WRITE) ? 1 : 0;
+ mr->hwmr.remote_rd = (acc & IB_ACCESS_REMOTE_READ) ? 1 : 0;
+ mr->hwmr.local_wr = (acc & IB_ACCESS_LOCAL_WRITE) ? 1 : 0;
+ mr->hwmr.local_rd = 1;
+ mr->hwmr.remote_atomic = (acc & IB_ACCESS_REMOTE_ATOMIC) ? 1 : 0;
+ status = ocrdma_build_pbl_tbl(dev, &mr->hwmr);
+ if (status)
+ goto umem_err;
+ build_user_pbes(dev, mr, num_pbes);
+ status = ocrdma_reg_mr(dev, &mr->hwmr, pd->id, acc);
+ if (status)
+ goto mbx_err;
+ mr->pd = pd;
+ atomic_inc(&pd->use_cnt);
+ mr->ibmr.lkey = mr->hwmr.lkey;
+ if (mr->hwmr.remote_wr || mr->hwmr.remote_rd)
+ mr->ibmr.rkey = mr->hwmr.lkey;
+
+ return &mr->ibmr;
+
+mbx_err:
+ ocrdma_free_mr_pbl_tbl(dev, &mr->hwmr);
+umem_err:
+ kfree(mr);
+ return ERR_PTR(status);
+}
+
+int ocrdma_dereg_mr(struct ib_mr *ib_mr)
+{
+ struct ocrdma_mr *mr = get_ocrdma_mr(ib_mr);
+ struct ocrdma_dev *dev = mr->hwmr.dev;
+ int status;
+
+ status = ocrdma_mbx_dealloc_lkey(dev, mr->hwmr.fr_mr, mr->hwmr.lkey);
+
+ if (mr->hwmr.fr_mr == 0)
+ ocrdma_free_mr_pbl_tbl(dev, &mr->hwmr);
+
+ atomic_dec(&mr->pd->use_cnt);
+ /* it could be user registered memory. */
+ if (mr->umem)
+ ib_umem_release(mr->umem);
+ kfree(mr);
+ return status;
+}
+
+static int ocrdma_copy_cq_uresp(struct ocrdma_cq *cq, struct ib_udata *udata,
+ struct ib_ucontext *ib_ctx)
+{
+ int status;
+ struct ocrdma_ucontext *uctx;
+ struct ocrdma_create_cq_uresp uresp;
+
+ uresp.cq_id = cq->id;
+ uresp.page_size = cq->len;
+ uresp.num_pages = 1;
+ uresp.max_hw_cqe = cq->max_hw_cqe;
+ uresp.page_addr[0] = cq->pa;
+ uresp.db_page_addr = cq->dev->nic_info.unmapped_db;
+ uresp.db_page_size = cq->dev->nic_info.db_page_size;
+ uresp.phase_change = cq->phase_change ? 1 : 0;
+ status = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
+ if (status) {
+ ocrdma_err("%s(%d) copy error cqid=0x%x.\n",
+ __func__, cq->dev->id, cq->id);
+ goto err;
+ }
+ uctx = get_ocrdma_ucontext(ib_ctx);
+ status = ocrdma_add_mmap(uctx, uresp.db_page_addr, uresp.db_page_size);
+ if (status)
+ goto err;
+ status = ocrdma_add_mmap(uctx, uresp.page_addr[0], uresp.page_size);
+ if (status) {
+ ocrdma_del_mmap(uctx, uresp.db_page_addr, uresp.db_page_size);
+ goto err;
+ }
+ cq->ucontext = uctx;
+err:
+ return status;
+}
+
+struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev, int entries, int vector,
+ struct ib_ucontext *ib_ctx,
+ struct ib_udata *udata)
+{
+ struct ocrdma_cq *cq;
+ struct ocrdma_dev *dev = get_ocrdma_dev(ibdev);
+ int status;
+ struct ocrdma_create_cq_ureq ureq;
+
+ if (udata) {
+ if (ib_copy_from_udata(&ureq, udata, sizeof(ureq)))
+ return ERR_PTR(-EFAULT);
+ } else
+ ureq.dpp_cq = 0;
+ cq = kzalloc(sizeof(*cq), GFP_KERNEL);
+ if (!cq)
+ return ERR_PTR(-ENOMEM);
+
+ spin_lock_init(&cq->cq_lock);
+ spin_lock_init(&cq->comp_handler_lock);
+ atomic_set(&cq->use_cnt, 0);
+ INIT_LIST_HEAD(&cq->sq_head);
+ INIT_LIST_HEAD(&cq->rq_head);
+ cq->dev = dev;
+
+ status = ocrdma_mbx_create_cq(dev, cq, entries, ureq.dpp_cq);
+ if (status) {
+ kfree(cq);
+ return ERR_PTR(status);
+ }
+ if (ib_ctx) {
+ status = ocrdma_copy_cq_uresp(cq, udata, ib_ctx);
+ if (status)
+ goto ctx_err;
+ }
+ cq->phase = OCRDMA_CQE_VALID;
+ cq->arm_needed = true;
+ dev->cq_tbl[cq->id] = cq;
+
+ return &cq->ibcq;
+
+ctx_err:
+ ocrdma_mbx_destroy_cq(dev, cq);
+ kfree(cq);
+ return ERR_PTR(status);
+}
+
+int ocrdma_resize_cq(struct ib_cq *ibcq, int new_cnt,
+ struct ib_udata *udata)
+{
+ int status = 0;
+ struct ocrdma_cq *cq = get_ocrdma_cq(ibcq);
+
+ if (new_cnt < 1 || new_cnt > cq->max_hw_cqe) {
+ status = -EINVAL;
+ return status;
+ }
+ ibcq->cqe = new_cnt;
+ return status;
+}
+
+int ocrdma_destroy_cq(struct ib_cq *ibcq)
+{
+ int status;
+ struct ocrdma_cq *cq = get_ocrdma_cq(ibcq);
+ struct ocrdma_dev *dev = cq->dev;
+
+ if (atomic_read(&cq->use_cnt))
+ return -EINVAL;
+
+ status = ocrdma_mbx_destroy_cq(dev, cq);
+
+ if (cq->ucontext) {
+ ocrdma_del_mmap(cq->ucontext, (u64) cq->pa, cq->len);
+ ocrdma_del_mmap(cq->ucontext, dev->nic_info.unmapped_db,
+ dev->nic_info.db_page_size);
+ }
+ dev->cq_tbl[cq->id] = NULL;
+
+ kfree(cq);
+ return status;
+}
+
+static int ocrdma_add_qpn_map(struct ocrdma_dev *dev, struct ocrdma_qp *qp)
+{
+ int status = -EINVAL;
+
+ if (qp->id < OCRDMA_MAX_QP && dev->qp_tbl[qp->id] == NULL) {
+ dev->qp_tbl[qp->id] = qp;
+ status = 0;
+ }
+ return status;
+}
+
+static void ocrdma_del_qpn_map(struct ocrdma_dev *dev, struct ocrdma_qp *qp)
+{
+ dev->qp_tbl[qp->id] = NULL;
+}
+
+static int ocrdma_check_qp_params(struct ib_pd *ibpd, struct ocrdma_dev *dev,
+ struct ib_qp_init_attr *attrs)
+{
+ if (attrs->qp_type != IB_QPT_GSI &&
+ attrs->qp_type != IB_QPT_RC &&
+ attrs->qp_type != IB_QPT_UD) {
+ ocrdma_err("%s(%d) unsupported qp type=0x%x requested\n",
+ __func__, dev->id, attrs->qp_type);
+ return -EINVAL;
+ }
+ if (attrs->cap.max_send_wr > dev->attr.max_wqe) {
+ ocrdma_err("%s(%d) unsupported send_wr=0x%x requested\n",
+ __func__, dev->id, attrs->cap.max_send_wr);
+ ocrdma_err("%s(%d) supported send_wr=0x%x\n",
+ __func__, dev->id, dev->attr.max_wqe);
+ return -EINVAL;
+ }
+ if (!attrs->srq && (attrs->cap.max_recv_wr > dev->attr.max_rqe)) {
+ ocrdma_err("%s(%d) unsupported recv_wr=0x%x requested\n",
+ __func__, dev->id, attrs->cap.max_recv_wr);
+ ocrdma_err("%s(%d) supported recv_wr=0x%x\n",
+ __func__, dev->id, dev->attr.max_rqe);
+ return -EINVAL;
+ }
+ if (attrs->cap.max_inline_data > dev->attr.max_inline_data) {
+ ocrdma_err("%s(%d) unsupported inline data size=0x%x"
+ " requested\n", __func__, dev->id,
+ attrs->cap.max_inline_data);
+ ocrdma_err("%s(%d) supported inline data size=0x%x\n",
+ __func__, dev->id, dev->attr.max_inline_data);
+ return -EINVAL;
+ }
+ if (attrs->cap.max_send_sge > dev->attr.max_send_sge) {
+ ocrdma_err("%s(%d) unsupported send_sge=0x%x requested\n",
+ __func__, dev->id, attrs->cap.max_send_sge);
+ ocrdma_err("%s(%d) supported send_sge=0x%x\n",
+ __func__, dev->id, dev->attr.max_send_sge);
+ return -EINVAL;
+ }
+ if (attrs->cap.max_recv_sge > dev->attr.max_recv_sge) {
+ ocrdma_err("%s(%d) unsupported recv_sge=0x%x requested\n",
+ __func__, dev->id, attrs->cap.max_recv_sge);
+ ocrdma_err("%s(%d) supported recv_sge=0x%x\n",
+ __func__, dev->id, dev->attr.max_recv_sge);
+ return -EINVAL;
+ }
+ /* unprivileged user space cannot create special QP */
+ if (ibpd->uobject && attrs->qp_type == IB_QPT_GSI) {
+ ocrdma_err
+ ("%s(%d) Userspace can't create special QPs of type=0x%x\n",
+ __func__, dev->id, attrs->qp_type);
+ return -EINVAL;
+ }
+ /* allow creating only one GSI type of QP */
+ if (attrs->qp_type == IB_QPT_GSI && dev->gsi_qp_created) {
+ ocrdma_err("%s(%d) GSI special QPs already created.\n",
+ __func__, dev->id);
+ return -EINVAL;
+ }
+ /* verify consumer QPs are not trying to use GSI QP's CQ */
+ if ((attrs->qp_type != IB_QPT_GSI) && (dev->gsi_qp_created)) {
+ if ((dev->gsi_sqcq == get_ocrdma_cq(attrs->send_cq)) ||
+ (dev->gsi_sqcq == get_ocrdma_cq(attrs->send_cq))) {
+ ocrdma_err("%s(%d) Consumer QP cannot use GSI CQs.\n",
+ __func__, dev->id);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static int ocrdma_copy_qp_uresp(struct ocrdma_qp *qp,
+ struct ib_udata *udata, int dpp_offset,
+ int dpp_credit_lmt, int srq)
+{
+ int status = 0;
+ u64 usr_db;
+ struct ocrdma_create_qp_uresp uresp;
+ struct ocrdma_dev *dev = qp->dev;
+ struct ocrdma_pd *pd = qp->pd;
+
+ memset(&uresp, 0, sizeof(uresp));
+ usr_db = dev->nic_info.unmapped_db +
+ (pd->id * dev->nic_info.db_page_size);
+ uresp.qp_id = qp->id;
+ uresp.sq_dbid = qp->sq.dbid;
+ uresp.num_sq_pages = 1;
+ uresp.sq_page_size = qp->sq.len;
+ uresp.sq_page_addr[0] = qp->sq.pa;
+ uresp.num_wqe_allocated = qp->sq.max_cnt;
+ if (!srq) {
+ uresp.rq_dbid = qp->rq.dbid;
+ uresp.num_rq_pages = 1;
+ uresp.rq_page_size = qp->rq.len;
+ uresp.rq_page_addr[0] = qp->rq.pa;
+ uresp.num_rqe_allocated = qp->rq.max_cnt;
+ }
+ uresp.db_page_addr = usr_db;
+ uresp.db_page_size = dev->nic_info.db_page_size;
+ if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) {
+ uresp.db_sq_offset = OCRDMA_DB_GEN2_SQ_OFFSET;
+ uresp.db_rq_offset = ((qp->id & 0xFFFF) < 128) ?
+ OCRDMA_DB_GEN2_RQ1_OFFSET : OCRDMA_DB_GEN2_RQ2_OFFSET;
+ uresp.db_shift = (qp->id < 128) ? 24 : 16;
+ } else {
+ uresp.db_sq_offset = OCRDMA_DB_SQ_OFFSET;
+ uresp.db_rq_offset = OCRDMA_DB_RQ_OFFSET;
+ uresp.db_shift = 16;
+ }
+ uresp.free_wqe_delta = qp->sq.free_delta;
+ uresp.free_rqe_delta = qp->rq.free_delta;
+
+ if (qp->dpp_enabled) {
+ uresp.dpp_credit = dpp_credit_lmt;
+ uresp.dpp_offset = dpp_offset;
+ }
+ status = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
+ if (status) {
+ ocrdma_err("%s(%d) user copy error.\n", __func__, dev->id);
+ goto err;
+ }
+ status = ocrdma_add_mmap(pd->uctx, uresp.sq_page_addr[0],
+ uresp.sq_page_size);
+ if (status)
+ goto err;
+
+ if (!srq) {
+ status = ocrdma_add_mmap(pd->uctx, uresp.rq_page_addr[0],
+ uresp.rq_page_size);
+ if (status)
+ goto rq_map_err;
+ }
+ return status;
+rq_map_err:
+ ocrdma_del_mmap(pd->uctx, uresp.sq_page_addr[0], uresp.sq_page_size);
+err:
+ return status;
+}
+
+static void ocrdma_set_qp_db(struct ocrdma_dev *dev, struct ocrdma_qp *qp,
+ struct ocrdma_pd *pd)
+{
+ if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) {
+ qp->sq_db = dev->nic_info.db +
+ (pd->id * dev->nic_info.db_page_size) +
+ OCRDMA_DB_GEN2_SQ_OFFSET;
+ qp->rq_db = dev->nic_info.db +
+ (pd->id * dev->nic_info.db_page_size) +
+ ((qp->id < 128) ?
+ OCRDMA_DB_GEN2_RQ1_OFFSET : OCRDMA_DB_GEN2_RQ2_OFFSET);
+ } else {
+ qp->sq_db = dev->nic_info.db +
+ (pd->id * dev->nic_info.db_page_size) +
+ OCRDMA_DB_SQ_OFFSET;
+ qp->rq_db = dev->nic_info.db +
+ (pd->id * dev->nic_info.db_page_size) +
+ OCRDMA_DB_RQ_OFFSET;
+ }
+}
+
+static int ocrdma_alloc_wr_id_tbl(struct ocrdma_qp *qp)
+{
+ qp->wqe_wr_id_tbl =
+ kzalloc(sizeof(*(qp->wqe_wr_id_tbl)) * qp->sq.max_cnt,
+ GFP_KERNEL);
+ if (qp->wqe_wr_id_tbl == NULL)
+ return -ENOMEM;
+ qp->rqe_wr_id_tbl =
+ kzalloc(sizeof(u64) * qp->rq.max_cnt, GFP_KERNEL);
+ if (qp->rqe_wr_id_tbl == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void ocrdma_set_qp_init_params(struct ocrdma_qp *qp,
+ struct ocrdma_pd *pd,
+ struct ib_qp_init_attr *attrs)
+{
+ qp->pd = pd;
+ spin_lock_init(&qp->q_lock);
+ INIT_LIST_HEAD(&qp->sq_entry);
+ INIT_LIST_HEAD(&qp->rq_entry);
+
+ qp->qp_type = attrs->qp_type;
+ qp->cap_flags = OCRDMA_QP_INB_RD | OCRDMA_QP_INB_WR;
+ qp->max_inline_data = attrs->cap.max_inline_data;
+ qp->sq.max_sges = attrs->cap.max_send_sge;
+ qp->rq.max_sges = attrs->cap.max_recv_sge;
+ qp->state = OCRDMA_QPS_RST;
+}
+
+static void ocrdma_set_qp_use_cnt(struct ocrdma_qp *qp, struct ocrdma_pd *pd)
+{
+ atomic_inc(&pd->use_cnt);
+ atomic_inc(&qp->sq_cq->use_cnt);
+ atomic_inc(&qp->rq_cq->use_cnt);
+ if (qp->srq)
+ atomic_inc(&qp->srq->use_cnt);
+ qp->ibqp.qp_num = qp->id;
+}
+
+static void ocrdma_store_gsi_qp_cq(struct ocrdma_dev *dev,
+ struct ib_qp_init_attr *attrs)
+{
+ if (attrs->qp_type == IB_QPT_GSI) {
+ dev->gsi_qp_created = 1;
+ dev->gsi_sqcq = get_ocrdma_cq(attrs->send_cq);
+ dev->gsi_rqcq = get_ocrdma_cq(attrs->recv_cq);
+ }
+}
+
+struct ib_qp *ocrdma_create_qp(struct ib_pd *ibpd,
+ struct ib_qp_init_attr *attrs,
+ struct ib_udata *udata)
+{
+ int status;
+ struct ocrdma_pd *pd = get_ocrdma_pd(ibpd);
+ struct ocrdma_qp *qp;
+ struct ocrdma_dev *dev = pd->dev;
+ struct ocrdma_create_qp_ureq ureq;
+ u16 dpp_credit_lmt, dpp_offset;
+
+ status = ocrdma_check_qp_params(ibpd, dev, attrs);
+ if (status)
+ goto gen_err;
+
+ memset(&ureq, 0, sizeof(ureq));
+ if (udata) {
+ if (ib_copy_from_udata(&ureq, udata, sizeof(ureq)))
+ return ERR_PTR(-EFAULT);
+ }
+ qp = kzalloc(sizeof(*qp), GFP_KERNEL);
+ if (!qp) {
+ status = -ENOMEM;
+ goto gen_err;
+ }
+ qp->dev = dev;
+ ocrdma_set_qp_init_params(qp, pd, attrs);
+
+ mutex_lock(&dev->dev_lock);
+ status = ocrdma_mbx_create_qp(qp, attrs, ureq.enable_dpp_cq,
+ ureq.dpp_cq_id,
+ &dpp_offset, &dpp_credit_lmt);
+ if (status)
+ goto mbx_err;
+
+ /* user space QP's wr_id table are managed in library */
+ if (udata == NULL) {
+ qp->cap_flags |= (OCRDMA_QP_MW_BIND | OCRDMA_QP_LKEY0 |
+ OCRDMA_QP_FAST_REG);
+ status = ocrdma_alloc_wr_id_tbl(qp);
+ if (status)
+ goto map_err;
+ }
+
+ status = ocrdma_add_qpn_map(dev, qp);
+ if (status)
+ goto map_err;
+ ocrdma_set_qp_db(dev, qp, pd);
+ if (udata) {
+ status = ocrdma_copy_qp_uresp(qp, udata, dpp_offset,
+ dpp_credit_lmt,
+ (attrs->srq != NULL));
+ if (status)
+ goto cpy_err;
+ }
+ ocrdma_store_gsi_qp_cq(dev, attrs);
+ ocrdma_set_qp_use_cnt(qp, pd);
+ mutex_unlock(&dev->dev_lock);
+ return &qp->ibqp;
+
+cpy_err:
+ ocrdma_del_qpn_map(dev, qp);
+map_err:
+ ocrdma_mbx_destroy_qp(dev, qp);
+mbx_err:
+ mutex_unlock(&dev->dev_lock);
+ kfree(qp->wqe_wr_id_tbl);
+ kfree(qp->rqe_wr_id_tbl);
+ kfree(qp);
+ ocrdma_err("%s(%d) error=%d\n", __func__, dev->id, status);
+gen_err:
+ return ERR_PTR(status);
+}
+
+int _ocrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask)
+{
+ int status = 0;
+ struct ocrdma_qp *qp;
+ struct ocrdma_dev *dev;
+ enum ib_qp_state old_qps;
+
+ qp = get_ocrdma_qp(ibqp);
+ dev = qp->dev;
+ if (attr_mask & IB_QP_STATE)
+ status = ocrdma_qp_state_machine(qp, attr->qp_state, &old_qps);
+ /* if new and previous states are same hw doesn't need to
+ * know about it.
+ */
+ if (status < 0)
+ return status;
+ status = ocrdma_mbx_modify_qp(dev, qp, attr, attr_mask, old_qps);
+ return status;
+}
+
+int ocrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask, struct ib_udata *udata)
+{
+ unsigned long flags;
+ int status = -EINVAL;
+ struct ocrdma_qp *qp;
+ struct ocrdma_dev *dev;
+ enum ib_qp_state old_qps, new_qps;
+
+ qp = get_ocrdma_qp(ibqp);
+ dev = qp->dev;
+
+ /* syncronize with multiple context trying to change, retrive qps */
+ mutex_lock(&dev->dev_lock);
+ /* syncronize with wqe, rqe posting and cqe processing contexts */
+ spin_lock_irqsave(&qp->q_lock, flags);
+ old_qps = get_ibqp_state(qp->state);
+ if (attr_mask & IB_QP_STATE)
+ new_qps = attr->qp_state;
+ else
+ new_qps = old_qps;
+ spin_unlock_irqrestore(&qp->q_lock, flags);
+
+ if (!ib_modify_qp_is_ok(old_qps, new_qps, ibqp->qp_type, attr_mask)) {
+ ocrdma_err("%s(%d) invalid attribute mask=0x%x specified for "
+ "qpn=0x%x of type=0x%x old_qps=0x%x, new_qps=0x%x\n",
+ __func__, dev->id, attr_mask, qp->id, ibqp->qp_type,
+ old_qps, new_qps);
+ goto param_err;
+ }
+
+ status = _ocrdma_modify_qp(ibqp, attr, attr_mask);
+ if (status > 0)
+ status = 0;
+param_err:
+ mutex_unlock(&dev->dev_lock);
+ return status;
+}
+
+static enum ib_mtu ocrdma_mtu_int_to_enum(u16 mtu)
+{
+ switch (mtu) {
+ case 256:
+ return IB_MTU_256;
+ case 512:
+ return IB_MTU_512;
+ case 1024:
+ return IB_MTU_1024;
+ case 2048:
+ return IB_MTU_2048;
+ case 4096:
+ return IB_MTU_4096;
+ default:
+ return IB_MTU_1024;
+ }
+}
+
+static int ocrdma_to_ib_qp_acc_flags(int qp_cap_flags)
+{
+ int ib_qp_acc_flags = 0;
+
+ if (qp_cap_flags & OCRDMA_QP_INB_WR)
+ ib_qp_acc_flags |= IB_ACCESS_REMOTE_WRITE;
+ if (qp_cap_flags & OCRDMA_QP_INB_RD)
+ ib_qp_acc_flags |= IB_ACCESS_LOCAL_WRITE;
+ return ib_qp_acc_flags;
+}
+
+int ocrdma_query_qp(struct ib_qp *ibqp,
+ struct ib_qp_attr *qp_attr,
+ int attr_mask, struct ib_qp_init_attr *qp_init_attr)
+{
+ int status;
+ u32 qp_state;
+ struct ocrdma_qp_params params;
+ struct ocrdma_qp *qp = get_ocrdma_qp(ibqp);
+ struct ocrdma_dev *dev = qp->dev;
+
+ memset(&params, 0, sizeof(params));
+ mutex_lock(&dev->dev_lock);
+ status = ocrdma_mbx_query_qp(dev, qp, &params);
+ mutex_unlock(&dev->dev_lock);
+ if (status)
+ goto mbx_err;
+ qp_attr->qp_state = get_ibqp_state(IB_QPS_INIT);
+ qp_attr->cur_qp_state = get_ibqp_state(IB_QPS_INIT);
+ qp_attr->path_mtu =
+ ocrdma_mtu_int_to_enum(params.path_mtu_pkey_indx &
+ OCRDMA_QP_PARAMS_PATH_MTU_MASK) >>
+ OCRDMA_QP_PARAMS_PATH_MTU_SHIFT;
+ qp_attr->path_mig_state = IB_MIG_MIGRATED;
+ qp_attr->rq_psn = params.hop_lmt_rq_psn & OCRDMA_QP_PARAMS_RQ_PSN_MASK;
+ qp_attr->sq_psn = params.tclass_sq_psn & OCRDMA_QP_PARAMS_SQ_PSN_MASK;
+ qp_attr->dest_qp_num =
+ params.ack_to_rnr_rtc_dest_qpn & OCRDMA_QP_PARAMS_DEST_QPN_MASK;
+
+ qp_attr->qp_access_flags = ocrdma_to_ib_qp_acc_flags(qp->cap_flags);
+ qp_attr->cap.max_send_wr = qp->sq.max_cnt - 1;
+ qp_attr->cap.max_recv_wr = qp->rq.max_cnt - 1;
+ qp_attr->cap.max_send_sge = qp->sq.max_sges;
+ qp_attr->cap.max_recv_sge = qp->rq.max_sges;
+ qp_attr->cap.max_inline_data = dev->attr.max_inline_data;
+ qp_init_attr->cap = qp_attr->cap;
+ memcpy(&qp_attr->ah_attr.grh.dgid, &params.dgid[0],
+ sizeof(params.dgid));
+ qp_attr->ah_attr.grh.flow_label = params.rnt_rc_sl_fl &
+ OCRDMA_QP_PARAMS_FLOW_LABEL_MASK;
+ qp_attr->ah_attr.grh.sgid_index = qp->sgid_idx;
+ qp_attr->ah_attr.grh.hop_limit = (params.hop_lmt_rq_psn &
+ OCRDMA_QP_PARAMS_HOP_LMT_MASK) >>
+ OCRDMA_QP_PARAMS_HOP_LMT_SHIFT;
+ qp_attr->ah_attr.grh.traffic_class = (params.tclass_sq_psn &
+ OCRDMA_QP_PARAMS_SQ_PSN_MASK) >>
+ OCRDMA_QP_PARAMS_TCLASS_SHIFT;
+
+ qp_attr->ah_attr.ah_flags = IB_AH_GRH;
+ qp_attr->ah_attr.port_num = 1;
+ qp_attr->ah_attr.sl = (params.rnt_rc_sl_fl &
+ OCRDMA_QP_PARAMS_SL_MASK) >>
+ OCRDMA_QP_PARAMS_SL_SHIFT;
+ qp_attr->timeout = (params.ack_to_rnr_rtc_dest_qpn &
+ OCRDMA_QP_PARAMS_ACK_TIMEOUT_MASK) >>
+ OCRDMA_QP_PARAMS_ACK_TIMEOUT_SHIFT;
+ qp_attr->rnr_retry = (params.ack_to_rnr_rtc_dest_qpn &
+ OCRDMA_QP_PARAMS_RNR_RETRY_CNT_MASK) >>
+ OCRDMA_QP_PARAMS_RNR_RETRY_CNT_SHIFT;
+ qp_attr->retry_cnt =
+ (params.rnt_rc_sl_fl & OCRDMA_QP_PARAMS_RETRY_CNT_MASK) >>
+ OCRDMA_QP_PARAMS_RETRY_CNT_SHIFT;
+ qp_attr->min_rnr_timer = 0;
+ qp_attr->pkey_index = 0;
+ qp_attr->port_num = 1;
+ qp_attr->ah_attr.src_path_bits = 0;
+ qp_attr->ah_attr.static_rate = 0;
+ qp_attr->alt_pkey_index = 0;
+ qp_attr->alt_port_num = 0;
+ qp_attr->alt_timeout = 0;
+ memset(&qp_attr->alt_ah_attr, 0, sizeof(qp_attr->alt_ah_attr));
+ qp_state = (params.max_sge_recv_flags & OCRDMA_QP_PARAMS_STATE_MASK) >>
+ OCRDMA_QP_PARAMS_STATE_SHIFT;
+ qp_attr->sq_draining = (qp_state == OCRDMA_QPS_SQ_DRAINING) ? 1 : 0;
+ qp_attr->max_dest_rd_atomic =
+ params.max_ord_ird >> OCRDMA_QP_PARAMS_MAX_ORD_SHIFT;
+ qp_attr->max_rd_atomic =
+ params.max_ord_ird & OCRDMA_QP_PARAMS_MAX_IRD_MASK;
+ qp_attr->en_sqd_async_notify = (params.max_sge_recv_flags &
+ OCRDMA_QP_PARAMS_FLAGS_SQD_ASYNC) ? 1 : 0;
+mbx_err:
+ return status;
+}
+
+static void ocrdma_srq_toggle_bit(struct ocrdma_srq *srq, int idx)
+{
+ int i = idx / 32;
+ unsigned int mask = (1 << (idx % 32));
+
+ if (srq->idx_bit_fields[i] & mask)
+ srq->idx_bit_fields[i] &= ~mask;
+ else
+ srq->idx_bit_fields[i] |= mask;
+}
+
+static int ocrdma_hwq_free_cnt(struct ocrdma_qp_hwq_info *q)
+{
+ int free_cnt;
+ if (q->head >= q->tail)
+ free_cnt = (q->max_cnt - q->head) + q->tail;
+ else
+ free_cnt = q->tail - q->head;
+ if (q->free_delta)
+ free_cnt -= q->free_delta;
+ return free_cnt;
+}
+
+static int is_hw_sq_empty(struct ocrdma_qp *qp)
+{
+ return (qp->sq.tail == qp->sq.head &&
+ ocrdma_hwq_free_cnt(&qp->sq) ? 1 : 0);
+}
+
+static int is_hw_rq_empty(struct ocrdma_qp *qp)
+{
+ return (qp->rq.tail == qp->rq.head) ? 1 : 0;
+}
+
+static void *ocrdma_hwq_head(struct ocrdma_qp_hwq_info *q)
+{
+ return q->va + (q->head * q->entry_size);
+}
+
+static void *ocrdma_hwq_head_from_idx(struct ocrdma_qp_hwq_info *q,
+ u32 idx)
+{
+ return q->va + (idx * q->entry_size);
+}
+
+static void ocrdma_hwq_inc_head(struct ocrdma_qp_hwq_info *q)
+{
+ q->head = (q->head + 1) & q->max_wqe_idx;
+}
+
+static void ocrdma_hwq_inc_tail(struct ocrdma_qp_hwq_info *q)
+{
+ q->tail = (q->tail + 1) & q->max_wqe_idx;
+}
+
+/* discard the cqe for a given QP */
+static void ocrdma_discard_cqes(struct ocrdma_qp *qp, struct ocrdma_cq *cq)
+{
+ unsigned long cq_flags;
+ unsigned long flags;
+ int discard_cnt = 0;
+ u32 cur_getp, stop_getp;
+ struct ocrdma_cqe *cqe;
+ u32 qpn = 0;
+
+ spin_lock_irqsave(&cq->cq_lock, cq_flags);
+
+ /* traverse through the CQEs in the hw CQ,
+ * find the matching CQE for a given qp,
+ * mark the matching one discarded by clearing qpn.
+ * ring the doorbell in the poll_cq() as
+ * we don't complete out of order cqe.
+ */
+
+ cur_getp = cq->getp;
+ /* find upto when do we reap the cq. */
+ stop_getp = cur_getp;
+ do {
+ if (is_hw_sq_empty(qp) && (!qp->srq && is_hw_rq_empty(qp)))
+ break;
+
+ cqe = cq->va + cur_getp;
+ /* if (a) done reaping whole hw cq, or
+ * (b) qp_xq becomes empty.
+ * then exit
+ */
+ qpn = cqe->cmn.qpn & OCRDMA_CQE_QPN_MASK;
+ /* if previously discarded cqe found, skip that too. */
+ /* check for matching qp */
+ if (qpn == 0 || qpn != qp->id)
+ goto skip_cqe;
+
+ /* mark cqe discarded so that it is not picked up later
+ * in the poll_cq().
+ */
+ discard_cnt += 1;
+ cqe->cmn.qpn = 0;
+ if (is_cqe_for_sq(cqe))
+ ocrdma_hwq_inc_tail(&qp->sq);
+ else {
+ if (qp->srq) {
+ spin_lock_irqsave(&qp->srq->q_lock, flags);
+ ocrdma_hwq_inc_tail(&qp->srq->rq);
+ ocrdma_srq_toggle_bit(qp->srq, cur_getp);
+ spin_unlock_irqrestore(&qp->srq->q_lock, flags);
+
+ } else
+ ocrdma_hwq_inc_tail(&qp->rq);
+ }
+skip_cqe:
+ cur_getp = (cur_getp + 1) % cq->max_hw_cqe;
+ } while (cur_getp != stop_getp);
+ spin_unlock_irqrestore(&cq->cq_lock, cq_flags);
+}
+
+static void ocrdma_del_flush_qp(struct ocrdma_qp *qp)
+{
+ int found = false;
+ unsigned long flags;
+ struct ocrdma_dev *dev = qp->dev;
+ /* sync with any active CQ poll */
+
+ spin_lock_irqsave(&dev->flush_q_lock, flags);
+ found = ocrdma_is_qp_in_sq_flushlist(qp->sq_cq, qp);
+ if (found)
+ list_del(&qp->sq_entry);
+ if (!qp->srq) {
+ found = ocrdma_is_qp_in_rq_flushlist(qp->rq_cq, qp);
+ if (found)
+ list_del(&qp->rq_entry);
+ }
+ spin_unlock_irqrestore(&dev->flush_q_lock, flags);
+}
+
+int ocrdma_destroy_qp(struct ib_qp *ibqp)
+{
+ int status;
+ struct ocrdma_pd *pd;
+ struct ocrdma_qp *qp;
+ struct ocrdma_dev *dev;
+ struct ib_qp_attr attrs;
+ int attr_mask = IB_QP_STATE;
+ unsigned long flags;
+
+ qp = get_ocrdma_qp(ibqp);
+ dev = qp->dev;
+
+ attrs.qp_state = IB_QPS_ERR;
+ pd = qp->pd;
+
+ /* change the QP state to ERROR */
+ _ocrdma_modify_qp(ibqp, &attrs, attr_mask);
+
+ /* ensure that CQEs for newly created QP (whose id may be same with
+ * one which just getting destroyed are same), dont get
+ * discarded until the old CQEs are discarded.
+ */
+ mutex_lock(&dev->dev_lock);
+ status = ocrdma_mbx_destroy_qp(dev, qp);
+
+ /*
+ * acquire CQ lock while destroy is in progress, in order to
+ * protect against proessing in-flight CQEs for this QP.
+ */
+ spin_lock_irqsave(&qp->sq_cq->cq_lock, flags);
+ if (qp->rq_cq && (qp->rq_cq != qp->sq_cq))
+ spin_lock(&qp->rq_cq->cq_lock);
+
+ ocrdma_del_qpn_map(dev, qp);
+
+ if (qp->rq_cq && (qp->rq_cq != qp->sq_cq))
+ spin_unlock(&qp->rq_cq->cq_lock);
+ spin_unlock_irqrestore(&qp->sq_cq->cq_lock, flags);
+
+ if (!pd->uctx) {
+ ocrdma_discard_cqes(qp, qp->sq_cq);
+ ocrdma_discard_cqes(qp, qp->rq_cq);
+ }
+ mutex_unlock(&dev->dev_lock);
+
+ if (pd->uctx) {
+ ocrdma_del_mmap(pd->uctx, (u64) qp->sq.pa, qp->sq.len);
+ if (!qp->srq)
+ ocrdma_del_mmap(pd->uctx, (u64) qp->rq.pa, qp->rq.len);
+ }
+
+ ocrdma_del_flush_qp(qp);
+
+ atomic_dec(&qp->pd->use_cnt);
+ atomic_dec(&qp->sq_cq->use_cnt);
+ atomic_dec(&qp->rq_cq->use_cnt);
+ if (qp->srq)
+ atomic_dec(&qp->srq->use_cnt);
+ kfree(qp->wqe_wr_id_tbl);
+ kfree(qp->rqe_wr_id_tbl);
+ kfree(qp);
+ return status;
+}
+
+static int ocrdma_copy_srq_uresp(struct ocrdma_srq *srq, struct ib_udata *udata)
+{
+ int status;
+ struct ocrdma_create_srq_uresp uresp;
+
+ uresp.rq_dbid = srq->rq.dbid;
+ uresp.num_rq_pages = 1;
+ uresp.rq_page_addr[0] = srq->rq.pa;
+ uresp.rq_page_size = srq->rq.len;
+ uresp.db_page_addr = srq->dev->nic_info.unmapped_db +
+ (srq->pd->id * srq->dev->nic_info.db_page_size);
+ uresp.db_page_size = srq->dev->nic_info.db_page_size;
+ uresp.num_rqe_allocated = srq->rq.max_cnt;
+ uresp.free_rqe_delta = 1;
+ if (srq->dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) {
+ uresp.db_rq_offset = OCRDMA_DB_GEN2_RQ1_OFFSET;
+ uresp.db_shift = 24;
+ } else {
+ uresp.db_rq_offset = OCRDMA_DB_RQ_OFFSET;
+ uresp.db_shift = 16;
+ }
+
+ status = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
+ if (status)
+ return status;
+ status = ocrdma_add_mmap(srq->pd->uctx, uresp.rq_page_addr[0],
+ uresp.rq_page_size);
+ if (status)
+ return status;
+ return status;
+}
+
+struct ib_srq *ocrdma_create_srq(struct ib_pd *ibpd,
+ struct ib_srq_init_attr *init_attr,
+ struct ib_udata *udata)
+{
+ int status = -ENOMEM;
+ struct ocrdma_pd *pd = get_ocrdma_pd(ibpd);
+ struct ocrdma_dev *dev = pd->dev;
+ struct ocrdma_srq *srq;
+
+ if (init_attr->attr.max_sge > dev->attr.max_recv_sge)
+ return ERR_PTR(-EINVAL);
+ if (init_attr->attr.max_wr > dev->attr.max_rqe)
+ return ERR_PTR(-EINVAL);
+
+ srq = kzalloc(sizeof(*srq), GFP_KERNEL);
+ if (!srq)
+ return ERR_PTR(status);
+
+ spin_lock_init(&srq->q_lock);
+ srq->dev = dev;
+ srq->pd = pd;
+ srq->db = dev->nic_info.db + (pd->id * dev->nic_info.db_page_size);
+ status = ocrdma_mbx_create_srq(srq, init_attr, pd);
+ if (status)
+ goto err;
+
+ if (udata == NULL) {
+ srq->rqe_wr_id_tbl = kzalloc(sizeof(u64) * srq->rq.max_cnt,
+ GFP_KERNEL);
+ if (srq->rqe_wr_id_tbl == NULL)
+ goto arm_err;
+
+ srq->bit_fields_len = (srq->rq.max_cnt / 32) +
+ (srq->rq.max_cnt % 32 ? 1 : 0);
+ srq->idx_bit_fields =
+ kmalloc(srq->bit_fields_len * sizeof(u32), GFP_KERNEL);
+ if (srq->idx_bit_fields == NULL)
+ goto arm_err;
+ memset(srq->idx_bit_fields, 0xff,
+ srq->bit_fields_len * sizeof(u32));
+ }
+
+ if (init_attr->attr.srq_limit) {
+ status = ocrdma_mbx_modify_srq(srq, &init_attr->attr);
+ if (status)
+ goto arm_err;
+ }
+
+ atomic_set(&srq->use_cnt, 0);
+ if (udata) {
+ status = ocrdma_copy_srq_uresp(srq, udata);
+ if (status)
+ goto arm_err;
+ }
+
+ atomic_inc(&pd->use_cnt);
+ return &srq->ibsrq;
+
+arm_err:
+ ocrdma_mbx_destroy_srq(dev, srq);
+err:
+ kfree(srq->rqe_wr_id_tbl);
+ kfree(srq->idx_bit_fields);
+ kfree(srq);
+ return ERR_PTR(status);
+}
+
+int ocrdma_modify_srq(struct ib_srq *ibsrq,
+ struct ib_srq_attr *srq_attr,
+ enum ib_srq_attr_mask srq_attr_mask,
+ struct ib_udata *udata)
+{
+ int status = 0;
+ struct ocrdma_srq *srq;
+
+ srq = get_ocrdma_srq(ibsrq);
+ if (srq_attr_mask & IB_SRQ_MAX_WR)
+ status = -EINVAL;
+ else
+ status = ocrdma_mbx_modify_srq(srq, srq_attr);
+ return status;
+}
+
+int ocrdma_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
+{
+ int status;
+ struct ocrdma_srq *srq;
+
+ srq = get_ocrdma_srq(ibsrq);
+ status = ocrdma_mbx_query_srq(srq, srq_attr);
+ return status;
+}
+
+int ocrdma_destroy_srq(struct ib_srq *ibsrq)
+{
+ int status;
+ struct ocrdma_srq *srq;
+ struct ocrdma_dev *dev;
+
+ srq = get_ocrdma_srq(ibsrq);
+ dev = srq->dev;
+ if (atomic_read(&srq->use_cnt)) {
+ ocrdma_err("%s(%d) err, srq=0x%x in use\n",
+ __func__, dev->id, srq->id);
+ return -EAGAIN;
+ }
+
+ status = ocrdma_mbx_destroy_srq(dev, srq);
+
+ if (srq->pd->uctx)
+ ocrdma_del_mmap(srq->pd->uctx, (u64) srq->rq.pa, srq->rq.len);
+
+ atomic_dec(&srq->pd->use_cnt);
+ kfree(srq->idx_bit_fields);
+ kfree(srq->rqe_wr_id_tbl);
+ kfree(srq);
+ return status;
+}
+
+/* unprivileged verbs and their support functions. */
+static void ocrdma_build_ud_hdr(struct ocrdma_qp *qp,
+ struct ocrdma_hdr_wqe *hdr,
+ struct ib_send_wr *wr)
+{
+ struct ocrdma_ewqe_ud_hdr *ud_hdr =
+ (struct ocrdma_ewqe_ud_hdr *)(hdr + 1);
+ struct ocrdma_ah *ah = get_ocrdma_ah(wr->wr.ud.ah);
+
+ ud_hdr->rsvd_dest_qpn = wr->wr.ud.remote_qpn;
+ if (qp->qp_type == IB_QPT_GSI)
+ ud_hdr->qkey = qp->qkey;
+ else
+ ud_hdr->qkey = wr->wr.ud.remote_qkey;
+ ud_hdr->rsvd_ahid = ah->id;
+}
+
+static void ocrdma_build_sges(struct ocrdma_hdr_wqe *hdr,
+ struct ocrdma_sge *sge, int num_sge,
+ struct ib_sge *sg_list)
+{
+ int i;
+
+ for (i = 0; i < num_sge; i++) {
+ sge[i].lrkey = sg_list[i].lkey;
+ sge[i].addr_lo = sg_list[i].addr;
+ sge[i].addr_hi = upper_32_bits(sg_list[i].addr);
+ sge[i].len = sg_list[i].length;
+ hdr->total_len += sg_list[i].length;
+ }
+ if (num_sge == 0)
+ memset(sge, 0, sizeof(*sge));
+}
+
+static int ocrdma_build_inline_sges(struct ocrdma_qp *qp,
+ struct ocrdma_hdr_wqe *hdr,
+ struct ocrdma_sge *sge,
+ struct ib_send_wr *wr, u32 wqe_size)
+{
+ if (wr->send_flags & IB_SEND_INLINE) {
+ if (wr->sg_list[0].length > qp->max_inline_data) {
+ ocrdma_err("%s() supported_len=0x%x,"
+ " unspported len req=0x%x\n", __func__,
+ qp->max_inline_data, wr->sg_list[0].length);
+ return -EINVAL;
+ }
+ memcpy(sge,
+ (void *)(unsigned long)wr->sg_list[0].addr,
+ wr->sg_list[0].length);
+ hdr->total_len = wr->sg_list[0].length;
+ wqe_size += roundup(hdr->total_len, OCRDMA_WQE_ALIGN_BYTES);
+ hdr->cw |= (OCRDMA_TYPE_INLINE << OCRDMA_WQE_TYPE_SHIFT);
+ } else {
+ ocrdma_build_sges(hdr, sge, wr->num_sge, wr->sg_list);
+ if (wr->num_sge)
+ wqe_size += (wr->num_sge * sizeof(struct ocrdma_sge));
+ else
+ wqe_size += sizeof(struct ocrdma_sge);
+ hdr->cw |= (OCRDMA_TYPE_LKEY << OCRDMA_WQE_TYPE_SHIFT);
+ }
+ hdr->cw |= ((wqe_size / OCRDMA_WQE_STRIDE) << OCRDMA_WQE_SIZE_SHIFT);
+ return 0;
+}
+
+static int ocrdma_build_send(struct ocrdma_qp *qp, struct ocrdma_hdr_wqe *hdr,
+ struct ib_send_wr *wr)
+{
+ int status;
+ struct ocrdma_sge *sge;
+ u32 wqe_size = sizeof(*hdr);
+
+ if (qp->qp_type == IB_QPT_UD || qp->qp_type == IB_QPT_GSI) {
+ ocrdma_build_ud_hdr(qp, hdr, wr);
+ sge = (struct ocrdma_sge *)(hdr + 2);
+ wqe_size += sizeof(struct ocrdma_ewqe_ud_hdr);
+ } else
+ sge = (struct ocrdma_sge *)(hdr + 1);
+
+ status = ocrdma_build_inline_sges(qp, hdr, sge, wr, wqe_size);
+ return status;
+}
+
+static int ocrdma_build_write(struct ocrdma_qp *qp, struct ocrdma_hdr_wqe *hdr,
+ struct ib_send_wr *wr)
+{
+ int status;
+ struct ocrdma_sge *ext_rw = (struct ocrdma_sge *)(hdr + 1);
+ struct ocrdma_sge *sge = ext_rw + 1;
+ u32 wqe_size = sizeof(*hdr) + sizeof(*ext_rw);
+
+ status = ocrdma_build_inline_sges(qp, hdr, sge, wr, wqe_size);
+ if (status)
+ return status;
+ ext_rw->addr_lo = wr->wr.rdma.remote_addr;
+ ext_rw->addr_hi = upper_32_bits(wr->wr.rdma.remote_addr);
+ ext_rw->lrkey = wr->wr.rdma.rkey;
+ ext_rw->len = hdr->total_len;
+ return 0;
+}
+
+static void ocrdma_build_read(struct ocrdma_qp *qp, struct ocrdma_hdr_wqe *hdr,
+ struct ib_send_wr *wr)
+{
+ struct ocrdma_sge *ext_rw = (struct ocrdma_sge *)(hdr + 1);
+ struct ocrdma_sge *sge = ext_rw + 1;
+ u32 wqe_size = ((wr->num_sge + 1) * sizeof(struct ocrdma_sge)) +
+ sizeof(struct ocrdma_hdr_wqe);
+
+ ocrdma_build_sges(hdr, sge, wr->num_sge, wr->sg_list);
+ hdr->cw |= ((wqe_size / OCRDMA_WQE_STRIDE) << OCRDMA_WQE_SIZE_SHIFT);
+ hdr->cw |= (OCRDMA_READ << OCRDMA_WQE_OPCODE_SHIFT);
+ hdr->cw |= (OCRDMA_TYPE_LKEY << OCRDMA_WQE_TYPE_SHIFT);
+
+ ext_rw->addr_lo = wr->wr.rdma.remote_addr;
+ ext_rw->addr_hi = upper_32_bits(wr->wr.rdma.remote_addr);
+ ext_rw->lrkey = wr->wr.rdma.rkey;
+ ext_rw->len = hdr->total_len;
+}
+
+static void ocrdma_ring_sq_db(struct ocrdma_qp *qp)
+{
+ u32 val = qp->sq.dbid | (1 << 16);
+
+ iowrite32(val, qp->sq_db);
+}
+
+int ocrdma_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ struct ib_send_wr **bad_wr)
+{
+ int status = 0;
+ struct ocrdma_qp *qp = get_ocrdma_qp(ibqp);
+ struct ocrdma_hdr_wqe *hdr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&qp->q_lock, flags);
+ if (qp->state != OCRDMA_QPS_RTS && qp->state != OCRDMA_QPS_SQD) {
+ spin_unlock_irqrestore(&qp->q_lock, flags);
+ return -EINVAL;
+ }
+
+ while (wr) {
+ if (ocrdma_hwq_free_cnt(&qp->sq) == 0 ||
+ wr->num_sge > qp->sq.max_sges) {
+ status = -ENOMEM;
+ break;
+ }
+ hdr = ocrdma_hwq_head(&qp->sq);
+ hdr->cw = 0;
+ if (wr->send_flags & IB_SEND_SIGNALED)
+ hdr->cw |= (OCRDMA_FLAG_SIG << OCRDMA_WQE_FLAGS_SHIFT);
+ if (wr->send_flags & IB_SEND_FENCE)
+ hdr->cw |=
+ (OCRDMA_FLAG_FENCE_L << OCRDMA_WQE_FLAGS_SHIFT);
+ if (wr->send_flags & IB_SEND_SOLICITED)
+ hdr->cw |=
+ (OCRDMA_FLAG_SOLICIT << OCRDMA_WQE_FLAGS_SHIFT);
+ hdr->total_len = 0;
+ switch (wr->opcode) {
+ case IB_WR_SEND_WITH_IMM:
+ hdr->cw |= (OCRDMA_FLAG_IMM << OCRDMA_WQE_FLAGS_SHIFT);
+ hdr->immdt = ntohl(wr->ex.imm_data);
+ case IB_WR_SEND:
+ hdr->cw |= (OCRDMA_SEND << OCRDMA_WQE_OPCODE_SHIFT);
+ ocrdma_build_send(qp, hdr, wr);
+ break;
+ case IB_WR_SEND_WITH_INV:
+ hdr->cw |= (OCRDMA_FLAG_INV << OCRDMA_WQE_FLAGS_SHIFT);
+ hdr->cw |= (OCRDMA_SEND << OCRDMA_WQE_OPCODE_SHIFT);
+ hdr->lkey = wr->ex.invalidate_rkey;
+ status = ocrdma_build_send(qp, hdr, wr);
+ break;
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ hdr->cw |= (OCRDMA_FLAG_IMM << OCRDMA_WQE_FLAGS_SHIFT);
+ hdr->immdt = ntohl(wr->ex.imm_data);
+ case IB_WR_RDMA_WRITE:
+ hdr->cw |= (OCRDMA_WRITE << OCRDMA_WQE_OPCODE_SHIFT);
+ status = ocrdma_build_write(qp, hdr, wr);
+ break;
+ case IB_WR_RDMA_READ_WITH_INV:
+ hdr->cw |= (OCRDMA_FLAG_INV << OCRDMA_WQE_FLAGS_SHIFT);
+ case IB_WR_RDMA_READ:
+ ocrdma_build_read(qp, hdr, wr);
+ break;
+ case IB_WR_LOCAL_INV:
+ hdr->cw |=
+ (OCRDMA_LKEY_INV << OCRDMA_WQE_OPCODE_SHIFT);
+ hdr->cw |= (sizeof(struct ocrdma_hdr_wqe) /
+ OCRDMA_WQE_STRIDE) << OCRDMA_WQE_SIZE_SHIFT;
+ hdr->lkey = wr->ex.invalidate_rkey;
+ break;
+ default:
+ status = -EINVAL;
+ break;
+ }
+ if (status) {
+ *bad_wr = wr;
+ break;
+ }
+ if (wr->send_flags & IB_SEND_SIGNALED)
+ qp->wqe_wr_id_tbl[qp->sq.head].signaled = 1;
+ else
+ qp->wqe_wr_id_tbl[qp->sq.head].signaled = 0;
+ qp->wqe_wr_id_tbl[qp->sq.head].wrid = wr->wr_id;
+ ocrdma_cpu_to_le32(hdr, ((hdr->cw >> OCRDMA_WQE_SIZE_SHIFT) &
+ OCRDMA_WQE_SIZE_MASK) * OCRDMA_WQE_STRIDE);
+ /* make sure wqe is written before adapter can access it */
+ wmb();
+ /* inform hw to start processing it */
+ ocrdma_ring_sq_db(qp);
+
+ /* update pointer, counter for next wr */
+ ocrdma_hwq_inc_head(&qp->sq);
+ wr = wr->next;
+ }
+ spin_unlock_irqrestore(&qp->q_lock, flags);
+ return status;
+}
+
+static void ocrdma_ring_rq_db(struct ocrdma_qp *qp)
+{
+ u32 val = qp->rq.dbid | (1 << OCRDMA_GET_NUM_POSTED_SHIFT_VAL(qp));
+
+ iowrite32(val, qp->rq_db);
+}
+
+static void ocrdma_build_rqe(struct ocrdma_hdr_wqe *rqe, struct ib_recv_wr *wr,
+ u16 tag)
+{
+ u32 wqe_size = 0;
+ struct ocrdma_sge *sge;
+ if (wr->num_sge)
+ wqe_size = (wr->num_sge * sizeof(*sge)) + sizeof(*rqe);
+ else
+ wqe_size = sizeof(*sge) + sizeof(*rqe);
+
+ rqe->cw = ((wqe_size / OCRDMA_WQE_STRIDE) <<
+ OCRDMA_WQE_SIZE_SHIFT);
+ rqe->cw |= (OCRDMA_FLAG_SIG << OCRDMA_WQE_FLAGS_SHIFT);
+ rqe->cw |= (OCRDMA_TYPE_LKEY << OCRDMA_WQE_TYPE_SHIFT);
+ rqe->total_len = 0;
+ rqe->rsvd_tag = tag;
+ sge = (struct ocrdma_sge *)(rqe + 1);
+ ocrdma_build_sges(rqe, sge, wr->num_sge, wr->sg_list);
+ ocrdma_cpu_to_le32(rqe, wqe_size);
+}
+
+int ocrdma_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
+{
+ int status = 0;
+ unsigned long flags;
+ struct ocrdma_qp *qp = get_ocrdma_qp(ibqp);
+ struct ocrdma_hdr_wqe *rqe;
+
+ spin_lock_irqsave(&qp->q_lock, flags);
+ if (qp->state == OCRDMA_QPS_RST || qp->state == OCRDMA_QPS_ERR) {
+ spin_unlock_irqrestore(&qp->q_lock, flags);
+ *bad_wr = wr;
+ return -EINVAL;
+ }
+ while (wr) {
+ if (ocrdma_hwq_free_cnt(&qp->rq) == 0 ||
+ wr->num_sge > qp->rq.max_sges) {
+ *bad_wr = wr;
+ status = -ENOMEM;
+ break;
+ }
+ rqe = ocrdma_hwq_head(&qp->rq);
+ ocrdma_build_rqe(rqe, wr, 0);
+
+ qp->rqe_wr_id_tbl[qp->rq.head] = wr->wr_id;
+ /* make sure rqe is written before adapter can access it */
+ wmb();
+
+ /* inform hw to start processing it */
+ ocrdma_ring_rq_db(qp);
+
+ /* update pointer, counter for next wr */
+ ocrdma_hwq_inc_head(&qp->rq);
+ wr = wr->next;
+ }
+ spin_unlock_irqrestore(&qp->q_lock, flags);
+ return status;
+}
+
+/* cqe for srq's rqe can potentially arrive out of order.
+ * index gives the entry in the shadow table where to store
+ * the wr_id. tag/index is returned in cqe to reference back
+ * for a given rqe.
+ */
+static int ocrdma_srq_get_idx(struct ocrdma_srq *srq)
+{
+ int row = 0;
+ int indx = 0;
+
+ for (row = 0; row < srq->bit_fields_len; row++) {
+ if (srq->idx_bit_fields[row]) {
+ indx = ffs(srq->idx_bit_fields[row]);
+ indx = (row * 32) + (indx - 1);
+ if (indx >= srq->rq.max_cnt)
+ BUG();
+ ocrdma_srq_toggle_bit(srq, indx);
+ break;
+ }
+ }
+
+ if (row == srq->bit_fields_len)
+ BUG();
+ return indx;
+}
+
+static void ocrdma_ring_srq_db(struct ocrdma_srq *srq)
+{
+ u32 val = srq->rq.dbid | (1 << 16);
+
+ iowrite32(val, srq->db + OCRDMA_DB_GEN2_SRQ_OFFSET);
+}
+
+int ocrdma_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
+{
+ int status = 0;
+ unsigned long flags;
+ struct ocrdma_srq *srq;
+ struct ocrdma_hdr_wqe *rqe;
+ u16 tag;
+
+ srq = get_ocrdma_srq(ibsrq);
+
+ spin_lock_irqsave(&srq->q_lock, flags);
+ while (wr) {
+ if (ocrdma_hwq_free_cnt(&srq->rq) == 0 ||
+ wr->num_sge > srq->rq.max_sges) {
+ status = -ENOMEM;
+ *bad_wr = wr;
+ break;
+ }
+ tag = ocrdma_srq_get_idx(srq);
+ rqe = ocrdma_hwq_head(&srq->rq);
+ ocrdma_build_rqe(rqe, wr, tag);
+
+ srq->rqe_wr_id_tbl[tag] = wr->wr_id;
+ /* make sure rqe is written before adapter can perform DMA */
+ wmb();
+ /* inform hw to start processing it */
+ ocrdma_ring_srq_db(srq);
+ /* update pointer, counter for next wr */
+ ocrdma_hwq_inc_head(&srq->rq);
+ wr = wr->next;
+ }
+ spin_unlock_irqrestore(&srq->q_lock, flags);
+ return status;
+}
+
+static enum ib_wc_status ocrdma_to_ibwc_err(u16 status)
+{
+ enum ib_wc_status ibwc_status = IB_WC_GENERAL_ERR;
+
+ switch (status) {
+ case OCRDMA_CQE_GENERAL_ERR:
+ ibwc_status = IB_WC_GENERAL_ERR;
+ break;
+ case OCRDMA_CQE_LOC_LEN_ERR:
+ ibwc_status = IB_WC_LOC_LEN_ERR;
+ break;
+ case OCRDMA_CQE_LOC_QP_OP_ERR:
+ ibwc_status = IB_WC_LOC_QP_OP_ERR;
+ break;
+ case OCRDMA_CQE_LOC_EEC_OP_ERR:
+ ibwc_status = IB_WC_LOC_EEC_OP_ERR;
+ break;
+ case OCRDMA_CQE_LOC_PROT_ERR:
+ ibwc_status = IB_WC_LOC_PROT_ERR;
+ break;
+ case OCRDMA_CQE_WR_FLUSH_ERR:
+ ibwc_status = IB_WC_WR_FLUSH_ERR;
+ break;
+ case OCRDMA_CQE_MW_BIND_ERR:
+ ibwc_status = IB_WC_MW_BIND_ERR;
+ break;
+ case OCRDMA_CQE_BAD_RESP_ERR:
+ ibwc_status = IB_WC_BAD_RESP_ERR;
+ break;
+ case OCRDMA_CQE_LOC_ACCESS_ERR:
+ ibwc_status = IB_WC_LOC_ACCESS_ERR;
+ break;
+ case OCRDMA_CQE_REM_INV_REQ_ERR:
+ ibwc_status = IB_WC_REM_INV_REQ_ERR;
+ break;
+ case OCRDMA_CQE_REM_ACCESS_ERR:
+ ibwc_status = IB_WC_REM_ACCESS_ERR;
+ break;
+ case OCRDMA_CQE_REM_OP_ERR:
+ ibwc_status = IB_WC_REM_OP_ERR;
+ break;
+ case OCRDMA_CQE_RETRY_EXC_ERR:
+ ibwc_status = IB_WC_RETRY_EXC_ERR;
+ break;
+ case OCRDMA_CQE_RNR_RETRY_EXC_ERR:
+ ibwc_status = IB_WC_RNR_RETRY_EXC_ERR;
+ break;
+ case OCRDMA_CQE_LOC_RDD_VIOL_ERR:
+ ibwc_status = IB_WC_LOC_RDD_VIOL_ERR;
+ break;
+ case OCRDMA_CQE_REM_INV_RD_REQ_ERR:
+ ibwc_status = IB_WC_REM_INV_RD_REQ_ERR;
+ break;
+ case OCRDMA_CQE_REM_ABORT_ERR:
+ ibwc_status = IB_WC_REM_ABORT_ERR;
+ break;
+ case OCRDMA_CQE_INV_EECN_ERR:
+ ibwc_status = IB_WC_INV_EECN_ERR;
+ break;
+ case OCRDMA_CQE_INV_EEC_STATE_ERR:
+ ibwc_status = IB_WC_INV_EEC_STATE_ERR;
+ break;
+ case OCRDMA_CQE_FATAL_ERR:
+ ibwc_status = IB_WC_FATAL_ERR;
+ break;
+ case OCRDMA_CQE_RESP_TIMEOUT_ERR:
+ ibwc_status = IB_WC_RESP_TIMEOUT_ERR;
+ break;
+ default:
+ ibwc_status = IB_WC_GENERAL_ERR;
+ break;
+ };
+ return ibwc_status;
+}
+
+static void ocrdma_update_wc(struct ocrdma_qp *qp, struct ib_wc *ibwc,
+ u32 wqe_idx)
+{
+ struct ocrdma_hdr_wqe *hdr;
+ struct ocrdma_sge *rw;
+ int opcode;
+
+ hdr = ocrdma_hwq_head_from_idx(&qp->sq, wqe_idx);
+
+ ibwc->wr_id = qp->wqe_wr_id_tbl[wqe_idx].wrid;
+ /* Undo the hdr->cw swap */
+ opcode = le32_to_cpu(hdr->cw) & OCRDMA_WQE_OPCODE_MASK;
+ switch (opcode) {
+ case OCRDMA_WRITE:
+ ibwc->opcode = IB_WC_RDMA_WRITE;
+ break;
+ case OCRDMA_READ:
+ rw = (struct ocrdma_sge *)(hdr + 1);
+ ibwc->opcode = IB_WC_RDMA_READ;
+ ibwc->byte_len = rw->len;
+ break;
+ case OCRDMA_SEND:
+ ibwc->opcode = IB_WC_SEND;
+ break;
+ case OCRDMA_LKEY_INV:
+ ibwc->opcode = IB_WC_LOCAL_INV;
+ break;
+ default:
+ ibwc->status = IB_WC_GENERAL_ERR;
+ ocrdma_err("%s() invalid opcode received = 0x%x\n",
+ __func__, hdr->cw & OCRDMA_WQE_OPCODE_MASK);
+ break;
+ };
+}
+
+static void ocrdma_set_cqe_status_flushed(struct ocrdma_qp *qp,
+ struct ocrdma_cqe *cqe)
+{
+ if (is_cqe_for_sq(cqe)) {
+ cqe->flags_status_srcqpn = cpu_to_le32(le32_to_cpu(
+ cqe->flags_status_srcqpn) &
+ ~OCRDMA_CQE_STATUS_MASK);
+ cqe->flags_status_srcqpn = cpu_to_le32(le32_to_cpu(
+ cqe->flags_status_srcqpn) |
+ (OCRDMA_CQE_WR_FLUSH_ERR <<
+ OCRDMA_CQE_STATUS_SHIFT));
+ } else {
+ if (qp->qp_type == IB_QPT_UD || qp->qp_type == IB_QPT_GSI) {
+ cqe->flags_status_srcqpn = cpu_to_le32(le32_to_cpu(
+ cqe->flags_status_srcqpn) &
+ ~OCRDMA_CQE_UD_STATUS_MASK);
+ cqe->flags_status_srcqpn = cpu_to_le32(le32_to_cpu(
+ cqe->flags_status_srcqpn) |
+ (OCRDMA_CQE_WR_FLUSH_ERR <<
+ OCRDMA_CQE_UD_STATUS_SHIFT));
+ } else {
+ cqe->flags_status_srcqpn = cpu_to_le32(le32_to_cpu(
+ cqe->flags_status_srcqpn) &
+ ~OCRDMA_CQE_STATUS_MASK);
+ cqe->flags_status_srcqpn = cpu_to_le32(le32_to_cpu(
+ cqe->flags_status_srcqpn) |
+ (OCRDMA_CQE_WR_FLUSH_ERR <<
+ OCRDMA_CQE_STATUS_SHIFT));
+ }
+ }
+}
+
+static bool ocrdma_update_err_cqe(struct ib_wc *ibwc, struct ocrdma_cqe *cqe,
+ struct ocrdma_qp *qp, int status)
+{
+ bool expand = false;
+
+ ibwc->byte_len = 0;
+ ibwc->qp = &qp->ibqp;
+ ibwc->status = ocrdma_to_ibwc_err(status);
+
+ ocrdma_flush_qp(qp);
+ ocrdma_qp_state_machine(qp, IB_QPS_ERR, NULL);
+
+ /* if wqe/rqe pending for which cqe needs to be returned,
+ * trigger inflating it.
+ */
+ if (!is_hw_rq_empty(qp) || !is_hw_sq_empty(qp)) {
+ expand = true;
+ ocrdma_set_cqe_status_flushed(qp, cqe);
+ }
+ return expand;
+}
+
+static int ocrdma_update_err_rcqe(struct ib_wc *ibwc, struct ocrdma_cqe *cqe,
+ struct ocrdma_qp *qp, int status)
+{
+ ibwc->opcode = IB_WC_RECV;
+ ibwc->wr_id = qp->rqe_wr_id_tbl[qp->rq.tail];
+ ocrdma_hwq_inc_tail(&qp->rq);
+
+ return ocrdma_update_err_cqe(ibwc, cqe, qp, status);
+}
+
+static int ocrdma_update_err_scqe(struct ib_wc *ibwc, struct ocrdma_cqe *cqe,
+ struct ocrdma_qp *qp, int status)
+{
+ ocrdma_update_wc(qp, ibwc, qp->sq.tail);
+ ocrdma_hwq_inc_tail(&qp->sq);
+
+ return ocrdma_update_err_cqe(ibwc, cqe, qp, status);
+}
+
+
+static bool ocrdma_poll_err_scqe(struct ocrdma_qp *qp,
+ struct ocrdma_cqe *cqe, struct ib_wc *ibwc,
+ bool *polled, bool *stop)
+{
+ bool expand;
+ int status = (le32_to_cpu(cqe->flags_status_srcqpn) &
+ OCRDMA_CQE_STATUS_MASK) >> OCRDMA_CQE_STATUS_SHIFT;
+
+ /* when hw sq is empty, but rq is not empty, so we continue
+ * to keep the cqe in order to get the cq event again.
+ */
+ if (is_hw_sq_empty(qp) && !is_hw_rq_empty(qp)) {
+ /* when cq for rq and sq is same, it is safe to return
+ * flush cqe for RQEs.
+ */
+ if (!qp->srq && (qp->sq_cq == qp->rq_cq)) {
+ *polled = true;
+ status = OCRDMA_CQE_WR_FLUSH_ERR;
+ expand = ocrdma_update_err_rcqe(ibwc, cqe, qp, status);
+ } else {
+ /* stop processing further cqe as this cqe is used for
+ * triggering cq event on buddy cq of RQ.
+ * When QP is destroyed, this cqe will be removed
+ * from the cq's hardware q.
+ */
+ *polled = false;
+ *stop = true;
+ expand = false;
+ }
+ } else {
+ *polled = true;
+ expand = ocrdma_update_err_scqe(ibwc, cqe, qp, status);
+ }
+ return expand;
+}
+
+static bool ocrdma_poll_success_scqe(struct ocrdma_qp *qp,
+ struct ocrdma_cqe *cqe,
+ struct ib_wc *ibwc, bool *polled)
+{
+ bool expand = false;
+ int tail = qp->sq.tail;
+ u32 wqe_idx;
+
+ if (!qp->wqe_wr_id_tbl[tail].signaled) {
+ expand = true; /* CQE cannot be consumed yet */
+ *polled = false; /* WC cannot be consumed yet */
+ } else {
+ ibwc->status = IB_WC_SUCCESS;
+ ibwc->wc_flags = 0;
+ ibwc->qp = &qp->ibqp;
+ ocrdma_update_wc(qp, ibwc, tail);
+ *polled = true;
+ wqe_idx = le32_to_cpu(cqe->wq.wqeidx) & OCRDMA_CQE_WQEIDX_MASK;
+ if (tail != wqe_idx)
+ expand = true; /* Coalesced CQE can't be consumed yet */
+ }
+ ocrdma_hwq_inc_tail(&qp->sq);
+ return expand;
+}
+
+static bool ocrdma_poll_scqe(struct ocrdma_qp *qp, struct ocrdma_cqe *cqe,
+ struct ib_wc *ibwc, bool *polled, bool *stop)
+{
+ int status;
+ bool expand;
+
+ status = (le32_to_cpu(cqe->flags_status_srcqpn) &
+ OCRDMA_CQE_STATUS_MASK) >> OCRDMA_CQE_STATUS_SHIFT;
+
+ if (status == OCRDMA_CQE_SUCCESS)
+ expand = ocrdma_poll_success_scqe(qp, cqe, ibwc, polled);
+ else
+ expand = ocrdma_poll_err_scqe(qp, cqe, ibwc, polled, stop);
+ return expand;
+}
+
+static int ocrdma_update_ud_rcqe(struct ib_wc *ibwc, struct ocrdma_cqe *cqe)
+{
+ int status;
+
+ status = (le32_to_cpu(cqe->flags_status_srcqpn) &
+ OCRDMA_CQE_UD_STATUS_MASK) >> OCRDMA_CQE_UD_STATUS_SHIFT;
+ ibwc->src_qp = le32_to_cpu(cqe->flags_status_srcqpn) &
+ OCRDMA_CQE_SRCQP_MASK;
+ ibwc->pkey_index = le32_to_cpu(cqe->ud.rxlen_pkey) &
+ OCRDMA_CQE_PKEY_MASK;
+ ibwc->wc_flags = IB_WC_GRH;
+ ibwc->byte_len = (le32_to_cpu(cqe->ud.rxlen_pkey) >>
+ OCRDMA_CQE_UD_XFER_LEN_SHIFT);
+ return status;
+}
+
+static void ocrdma_update_free_srq_cqe(struct ib_wc *ibwc,
+ struct ocrdma_cqe *cqe,
+ struct ocrdma_qp *qp)
+{
+ unsigned long flags;
+ struct ocrdma_srq *srq;
+ u32 wqe_idx;
+
+ srq = get_ocrdma_srq(qp->ibqp.srq);
+ wqe_idx = le32_to_cpu(cqe->rq.buftag_qpn) >> OCRDMA_CQE_BUFTAG_SHIFT;
+ ibwc->wr_id = srq->rqe_wr_id_tbl[wqe_idx];
+ spin_lock_irqsave(&srq->q_lock, flags);
+ ocrdma_srq_toggle_bit(srq, wqe_idx);
+ spin_unlock_irqrestore(&srq->q_lock, flags);
+ ocrdma_hwq_inc_tail(&srq->rq);
+}
+
+static bool ocrdma_poll_err_rcqe(struct ocrdma_qp *qp, struct ocrdma_cqe *cqe,
+ struct ib_wc *ibwc, bool *polled, bool *stop,
+ int status)
+{
+ bool expand;
+
+ /* when hw_rq is empty, but wq is not empty, so continue
+ * to keep the cqe to get the cq event again.
+ */
+ if (is_hw_rq_empty(qp) && !is_hw_sq_empty(qp)) {
+ if (!qp->srq && (qp->sq_cq == qp->rq_cq)) {
+ *polled = true;
+ status = OCRDMA_CQE_WR_FLUSH_ERR;
+ expand = ocrdma_update_err_scqe(ibwc, cqe, qp, status);
+ } else {
+ *polled = false;
+ *stop = true;
+ expand = false;
+ }
+ } else
+ expand = ocrdma_update_err_rcqe(ibwc, cqe, qp, status);
+ return expand;
+}
+
+static void ocrdma_poll_success_rcqe(struct ocrdma_qp *qp,
+ struct ocrdma_cqe *cqe, struct ib_wc *ibwc)
+{
+ ibwc->opcode = IB_WC_RECV;
+ ibwc->qp = &qp->ibqp;
+ ibwc->status = IB_WC_SUCCESS;
+
+ if (qp->qp_type == IB_QPT_UD || qp->qp_type == IB_QPT_GSI)
+ ocrdma_update_ud_rcqe(ibwc, cqe);
+ else
+ ibwc->byte_len = le32_to_cpu(cqe->rq.rxlen);
+
+ if (is_cqe_imm(cqe)) {
+ ibwc->ex.imm_data = htonl(le32_to_cpu(cqe->rq.lkey_immdt));
+ ibwc->wc_flags |= IB_WC_WITH_IMM;
+ } else if (is_cqe_wr_imm(cqe)) {
+ ibwc->opcode = IB_WC_RECV_RDMA_WITH_IMM;
+ ibwc->ex.imm_data = htonl(le32_to_cpu(cqe->rq.lkey_immdt));
+ ibwc->wc_flags |= IB_WC_WITH_IMM;
+ } else if (is_cqe_invalidated(cqe)) {
+ ibwc->ex.invalidate_rkey = le32_to_cpu(cqe->rq.lkey_immdt);
+ ibwc->wc_flags |= IB_WC_WITH_INVALIDATE;
+ }
+ if (qp->ibqp.srq)
+ ocrdma_update_free_srq_cqe(ibwc, cqe, qp);
+ else {
+ ibwc->wr_id = qp->rqe_wr_id_tbl[qp->rq.tail];
+ ocrdma_hwq_inc_tail(&qp->rq);
+ }
+}
+
+static bool ocrdma_poll_rcqe(struct ocrdma_qp *qp, struct ocrdma_cqe *cqe,
+ struct ib_wc *ibwc, bool *polled, bool *stop)
+{
+ int status;
+ bool expand = false;
+
+ ibwc->wc_flags = 0;
+ if (qp->qp_type == IB_QPT_UD || qp->qp_type == IB_QPT_GSI)
+ status = (le32_to_cpu(cqe->flags_status_srcqpn) &
+ OCRDMA_CQE_UD_STATUS_MASK) >>
+ OCRDMA_CQE_UD_STATUS_SHIFT;
+ else
+ status = (le32_to_cpu(cqe->flags_status_srcqpn) &
+ OCRDMA_CQE_STATUS_MASK) >> OCRDMA_CQE_STATUS_SHIFT;
+
+ if (status == OCRDMA_CQE_SUCCESS) {
+ *polled = true;
+ ocrdma_poll_success_rcqe(qp, cqe, ibwc);
+ } else {
+ expand = ocrdma_poll_err_rcqe(qp, cqe, ibwc, polled, stop,
+ status);
+ }
+ return expand;
+}
+
+static void ocrdma_change_cq_phase(struct ocrdma_cq *cq, struct ocrdma_cqe *cqe,
+ u16 cur_getp)
+{
+ if (cq->phase_change) {
+ if (cur_getp == 0)
+ cq->phase = (~cq->phase & OCRDMA_CQE_VALID);
+ } else
+ /* clear valid bit */
+ cqe->flags_status_srcqpn = 0;
+}
+
+static int ocrdma_poll_hwcq(struct ocrdma_cq *cq, int num_entries,
+ struct ib_wc *ibwc)
+{
+ u16 qpn = 0;
+ int i = 0;
+ bool expand = false;
+ int polled_hw_cqes = 0;
+ struct ocrdma_qp *qp = NULL;
+ struct ocrdma_dev *dev = cq->dev;
+ struct ocrdma_cqe *cqe;
+ u16 cur_getp; bool polled = false; bool stop = false;
+
+ cur_getp = cq->getp;
+ while (num_entries) {
+ cqe = cq->va + cur_getp;
+ /* check whether valid cqe or not */
+ if (!is_cqe_valid(cq, cqe))
+ break;
+ qpn = (le32_to_cpu(cqe->cmn.qpn) & OCRDMA_CQE_QPN_MASK);
+ /* ignore discarded cqe */
+ if (qpn == 0)
+ goto skip_cqe;
+ qp = dev->qp_tbl[qpn];
+ BUG_ON(qp == NULL);
+
+ if (is_cqe_for_sq(cqe)) {
+ expand = ocrdma_poll_scqe(qp, cqe, ibwc, &polled,
+ &stop);
+ } else {
+ expand = ocrdma_poll_rcqe(qp, cqe, ibwc, &polled,
+ &stop);
+ }
+ if (expand)
+ goto expand_cqe;
+ if (stop)
+ goto stop_cqe;
+ /* clear qpn to avoid duplicate processing by discard_cqe() */
+ cqe->cmn.qpn = 0;
+skip_cqe:
+ polled_hw_cqes += 1;
+ cur_getp = (cur_getp + 1) % cq->max_hw_cqe;
+ ocrdma_change_cq_phase(cq, cqe, cur_getp);
+expand_cqe:
+ if (polled) {
+ num_entries -= 1;
+ i += 1;
+ ibwc = ibwc + 1;
+ polled = false;
+ }
+ }
+stop_cqe:
+ cq->getp = cur_getp;
+ if (polled_hw_cqes || expand || stop) {
+ ocrdma_ring_cq_db(dev, cq->id, cq->armed, cq->solicited,
+ polled_hw_cqes);
+ }
+ return i;
+}
+
+/* insert error cqe if the QP's SQ or RQ's CQ matches the CQ under poll. */
+static int ocrdma_add_err_cqe(struct ocrdma_cq *cq, int num_entries,
+ struct ocrdma_qp *qp, struct ib_wc *ibwc)
+{
+ int err_cqes = 0;
+
+ while (num_entries) {
+ if (is_hw_sq_empty(qp) && is_hw_rq_empty(qp))
+ break;
+ if (!is_hw_sq_empty(qp) && qp->sq_cq == cq) {
+ ocrdma_update_wc(qp, ibwc, qp->sq.tail);
+ ocrdma_hwq_inc_tail(&qp->sq);
+ } else if (!is_hw_rq_empty(qp) && qp->rq_cq == cq) {
+ ibwc->wr_id = qp->rqe_wr_id_tbl[qp->rq.tail];
+ ocrdma_hwq_inc_tail(&qp->rq);
+ } else
+ return err_cqes;
+ ibwc->byte_len = 0;
+ ibwc->status = IB_WC_WR_FLUSH_ERR;
+ ibwc = ibwc + 1;
+ err_cqes += 1;
+ num_entries -= 1;
+ }
+ return err_cqes;
+}
+
+int ocrdma_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
+{
+ int cqes_to_poll = num_entries;
+ struct ocrdma_cq *cq = NULL;
+ unsigned long flags;
+ struct ocrdma_dev *dev;
+ int num_os_cqe = 0, err_cqes = 0;
+ struct ocrdma_qp *qp;
+
+ cq = get_ocrdma_cq(ibcq);
+ dev = cq->dev;
+
+ /* poll cqes from adapter CQ */
+ spin_lock_irqsave(&cq->cq_lock, flags);
+ num_os_cqe = ocrdma_poll_hwcq(cq, cqes_to_poll, wc);
+ spin_unlock_irqrestore(&cq->cq_lock, flags);
+ cqes_to_poll -= num_os_cqe;
+
+ if (cqes_to_poll) {
+ wc = wc + num_os_cqe;
+ /* adapter returns single error cqe when qp moves to
+ * error state. So insert error cqes with wc_status as
+ * FLUSHED for pending WQEs and RQEs of QP's SQ and RQ
+ * respectively which uses this CQ.
+ */
+ spin_lock_irqsave(&dev->flush_q_lock, flags);
+ list_for_each_entry(qp, &cq->sq_head, sq_entry) {
+ if (cqes_to_poll == 0)
+ break;
+ err_cqes = ocrdma_add_err_cqe(cq, cqes_to_poll, qp, wc);
+ cqes_to_poll -= err_cqes;
+ num_os_cqe += err_cqes;
+ wc = wc + err_cqes;
+ }
+ spin_unlock_irqrestore(&dev->flush_q_lock, flags);
+ }
+ return num_os_cqe;
+}
+
+int ocrdma_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags cq_flags)
+{
+ struct ocrdma_cq *cq;
+ unsigned long flags;
+ struct ocrdma_dev *dev;
+ u16 cq_id;
+ u16 cur_getp;
+ struct ocrdma_cqe *cqe;
+
+ cq = get_ocrdma_cq(ibcq);
+ cq_id = cq->id;
+ dev = cq->dev;
+
+ spin_lock_irqsave(&cq->cq_lock, flags);
+ if (cq_flags & IB_CQ_NEXT_COMP || cq_flags & IB_CQ_SOLICITED)
+ cq->armed = true;
+ if (cq_flags & IB_CQ_SOLICITED)
+ cq->solicited = true;
+
+ cur_getp = cq->getp;
+ cqe = cq->va + cur_getp;
+
+ /* check whether any valid cqe exist or not, if not then safe to
+ * arm. If cqe is not yet consumed, then let it get consumed and then
+ * we arm it to avoid false interrupts.
+ */
+ if (!is_cqe_valid(cq, cqe) || cq->arm_needed) {
+ cq->arm_needed = false;
+ ocrdma_ring_cq_db(dev, cq_id, cq->armed, cq->solicited, 0);
+ }
+ spin_unlock_irqrestore(&cq->cq_lock, flags);
+ return 0;
+}
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
new file mode 100644
index 000000000000..e6483439f25f
--- /dev/null
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
@@ -0,0 +1,94 @@
+/*******************************************************************
+ * This file is part of the Emulex RoCE Device Driver for *
+ * RoCE (RDMA over Converged Ethernet) adapters. *
+ * Copyright (C) 2008-2012 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.emulex.com *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of version 2 of the GNU General *
+ * Public License as published by the Free Software Foundation. *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID. See the GNU General Public License for *
+ * more details, a copy of which can be found in the file COPYING *
+ * included with this package. *
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ *******************************************************************/
+
+#ifndef __OCRDMA_VERBS_H__
+#define __OCRDMA_VERBS_H__
+
+#include <linux/version.h>
+int ocrdma_post_send(struct ib_qp *, struct ib_send_wr *,
+ struct ib_send_wr **bad_wr);
+int ocrdma_post_recv(struct ib_qp *, struct ib_recv_wr *,
+ struct ib_recv_wr **bad_wr);
+
+int ocrdma_poll_cq(struct ib_cq *, int num_entries, struct ib_wc *wc);
+int ocrdma_arm_cq(struct ib_cq *, enum ib_cq_notify_flags flags);
+
+int ocrdma_query_device(struct ib_device *, struct ib_device_attr *props);
+int ocrdma_query_port(struct ib_device *, u8 port, struct ib_port_attr *props);
+int ocrdma_modify_port(struct ib_device *, u8 port, int mask,
+ struct ib_port_modify *props);
+
+void ocrdma_get_guid(struct ocrdma_dev *, u8 *guid);
+int ocrdma_query_gid(struct ib_device *, u8 port,
+ int index, union ib_gid *gid);
+int ocrdma_query_pkey(struct ib_device *, u8 port, u16 index, u16 *pkey);
+
+struct ib_ucontext *ocrdma_alloc_ucontext(struct ib_device *,
+ struct ib_udata *);
+int ocrdma_dealloc_ucontext(struct ib_ucontext *);
+
+int ocrdma_mmap(struct ib_ucontext *, struct vm_area_struct *vma);
+
+struct ib_pd *ocrdma_alloc_pd(struct ib_device *,
+ struct ib_ucontext *, struct ib_udata *);
+int ocrdma_dealloc_pd(struct ib_pd *pd);
+
+struct ib_cq *ocrdma_create_cq(struct ib_device *, int entries, int vector,
+ struct ib_ucontext *, struct ib_udata *);
+int ocrdma_resize_cq(struct ib_cq *, int cqe, struct ib_udata *);
+int ocrdma_destroy_cq(struct ib_cq *);
+
+struct ib_qp *ocrdma_create_qp(struct ib_pd *,
+ struct ib_qp_init_attr *attrs,
+ struct ib_udata *);
+int _ocrdma_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
+ int attr_mask);
+int ocrdma_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
+ int attr_mask, struct ib_udata *udata);
+int ocrdma_query_qp(struct ib_qp *,
+ struct ib_qp_attr *qp_attr,
+ int qp_attr_mask, struct ib_qp_init_attr *);
+int ocrdma_destroy_qp(struct ib_qp *);
+
+struct ib_srq *ocrdma_create_srq(struct ib_pd *, struct ib_srq_init_attr *,
+ struct ib_udata *);
+int ocrdma_modify_srq(struct ib_srq *, struct ib_srq_attr *,
+ enum ib_srq_attr_mask, struct ib_udata *);
+int ocrdma_query_srq(struct ib_srq *, struct ib_srq_attr *);
+int ocrdma_destroy_srq(struct ib_srq *);
+int ocrdma_post_srq_recv(struct ib_srq *, struct ib_recv_wr *,
+ struct ib_recv_wr **bad_recv_wr);
+
+int ocrdma_dereg_mr(struct ib_mr *);
+struct ib_mr *ocrdma_get_dma_mr(struct ib_pd *, int acc);
+struct ib_mr *ocrdma_reg_kernel_mr(struct ib_pd *,
+ struct ib_phys_buf *buffer_list,
+ int num_phys_buf, int acc, u64 *iova_start);
+struct ib_mr *ocrdma_reg_user_mr(struct ib_pd *, u64 start, u64 length,
+ u64 virt, int acc, struct ib_udata *);
+
+#endif /* __OCRDMA_VERBS_H__ */
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
index 6b811e3e8bd1..7e62f4137148 100644
--- a/drivers/infiniband/hw/qib/qib.h
+++ b/drivers/infiniband/hw/qib/qib.h
@@ -530,8 +530,6 @@ struct qib_pportdata {
/* qib_lflags driver is waiting for */
u32 state_wanted;
spinlock_t lflags_lock;
- /* number of (port-specific) interrupts for this port -- saturates... */
- u32 int_counter;
/* ref count for each pkey */
atomic_t pkeyrefs[4];
@@ -543,24 +541,26 @@ struct qib_pportdata {
u64 *statusp;
/* SendDMA related entries */
- spinlock_t sdma_lock;
- struct qib_sdma_state sdma_state;
- unsigned long sdma_buf_jiffies;
+
+ /* read mostly */
struct qib_sdma_desc *sdma_descq;
+ struct qib_sdma_state sdma_state;
+ dma_addr_t sdma_descq_phys;
+ volatile __le64 *sdma_head_dma; /* DMA'ed by chip */
+ dma_addr_t sdma_head_phys;
+ u16 sdma_descq_cnt;
+
+ /* read/write using lock */
+ spinlock_t sdma_lock ____cacheline_aligned_in_smp;
+ struct list_head sdma_activelist;
u64 sdma_descq_added;
u64 sdma_descq_removed;
- u16 sdma_descq_cnt;
u16 sdma_descq_tail;
u16 sdma_descq_head;
- u16 sdma_next_intr;
- u16 sdma_reset_wait;
u8 sdma_generation;
- struct tasklet_struct sdma_sw_clean_up_task;
- struct list_head sdma_activelist;
- dma_addr_t sdma_descq_phys;
- volatile __le64 *sdma_head_dma; /* DMA'ed by chip */
- dma_addr_t sdma_head_phys;
+ struct tasklet_struct sdma_sw_clean_up_task
+ ____cacheline_aligned_in_smp;
wait_queue_head_t state_wait; /* for state_wanted */
@@ -873,7 +873,14 @@ struct qib_devdata {
* pio_writing.
*/
spinlock_t pioavail_lock;
-
+ /*
+ * index of last buffer to optimize search for next
+ */
+ u32 last_pio;
+ /*
+ * min kernel pio buffer to optimize search
+ */
+ u32 min_kernel_pio;
/*
* Shadow copies of registers; size indicates read access size.
* Most of them are readonly, but some are write-only register,
diff --git a/drivers/infiniband/hw/qib/qib_driver.c b/drivers/infiniband/hw/qib/qib_driver.c
index 6fc9365ba8a6..8895cfec5019 100644
--- a/drivers/infiniband/hw/qib/qib_driver.c
+++ b/drivers/infiniband/hw/qib/qib_driver.c
@@ -38,6 +38,7 @@
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
+#include <linux/prefetch.h>
#include "qib.h"
@@ -481,8 +482,10 @@ u32 qib_kreceive(struct qib_ctxtdata *rcd, u32 *llic, u32 *npkts)
etail = qib_hdrget_index(rhf_addr);
updegr = 1;
if (tlen > sizeof(*hdr) ||
- etype >= RCVHQ_RCV_TYPE_NON_KD)
+ etype >= RCVHQ_RCV_TYPE_NON_KD) {
ebuf = qib_get_egrbuf(rcd, etail);
+ prefetch_range(ebuf, tlen - sizeof(*hdr));
+ }
}
if (!eflags) {
u16 lrh_len = be16_to_cpu(hdr->lrh[2]) << 2;
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index d0c64d514813..4d352b90750a 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -3132,6 +3132,7 @@ static void get_6120_chip_params(struct qib_devdata *dd)
val = qib_read_kreg64(dd, kr_sendpiobufcnt);
dd->piobcnt2k = val & ~0U;
dd->piobcnt4k = val >> 32;
+ dd->last_pio = dd->piobcnt4k + dd->piobcnt2k - 1;
/* these may be adjusted in init_chip_wc_pat() */
dd->pio2kbase = (u32 __iomem *)
(((char __iomem *)dd->kregbase) + dd->pio2k_bufbase);
diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c
index 3c722f79d6f6..86a0ba7ca0c2 100644
--- a/drivers/infiniband/hw/qib/qib_iba7220.c
+++ b/drivers/infiniband/hw/qib/qib_iba7220.c
@@ -4157,6 +4157,7 @@ static int qib_init_7220_variables(struct qib_devdata *dd)
dd->cspec->sdmabufcnt;
dd->lastctxt_piobuf = dd->cspec->lastbuf_for_pio - sbufs;
dd->cspec->lastbuf_for_pio--; /* range is <= , not < */
+ dd->last_pio = dd->cspec->lastbuf_for_pio;
dd->pbufsctxt = dd->lastctxt_piobuf /
(dd->cfgctxts - dd->first_user_ctxt);
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index 060b96064469..c881e744c091 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -6379,6 +6379,7 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
dd->cspec->sdmabufcnt;
dd->lastctxt_piobuf = dd->cspec->lastbuf_for_pio - sbufs;
dd->cspec->lastbuf_for_pio--; /* range is <= , not < */
+ dd->last_pio = dd->cspec->lastbuf_for_pio;
dd->pbufsctxt = (dd->cfgctxts > dd->first_user_ctxt) ?
dd->lastctxt_piobuf / (dd->cfgctxts - dd->first_user_ctxt) : 0;
@@ -7708,7 +7709,7 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd)
ibsd_wr_allchans(ppd, 5, 0, BMASK(0, 0));
msleep(20);
/* Set Frequency Loop Bandwidth */
- ibsd_wr_allchans(ppd, 2, (7 << 5), BMASK(8, 5));
+ ibsd_wr_allchans(ppd, 2, (15 << 5), BMASK(8, 5));
/* Enable Frequency Loop */
ibsd_wr_allchans(ppd, 2, (1 << 4), BMASK(4, 4));
/* Set Timing Loop Bandwidth */
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index cf0cd30adc8d..dc14e100a7f1 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -102,6 +102,8 @@ void qib_set_ctxtcnt(struct qib_devdata *dd)
dd->cfgctxts = qib_cfgctxts;
else
dd->cfgctxts = dd->ctxtcnt;
+ dd->freectxts = (dd->first_user_ctxt > dd->cfgctxts) ? 0 :
+ dd->cfgctxts - dd->first_user_ctxt;
}
/*
@@ -402,7 +404,6 @@ static void enable_chip(struct qib_devdata *dd)
if (rcd)
dd->f_rcvctrl(rcd->ppd, rcvmask, i);
}
- dd->freectxts = dd->cfgctxts - dd->first_user_ctxt;
}
static void verify_interrupt(unsigned long opaque)
diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c
index c4ff788823b5..43390217a026 100644
--- a/drivers/infiniband/hw/qib/qib_mad.c
+++ b/drivers/infiniband/hw/qib/qib_mad.c
@@ -396,6 +396,7 @@ static int get_linkdowndefaultstate(struct qib_pportdata *ppd)
static int check_mkey(struct qib_ibport *ibp, struct ib_smp *smp, int mad_flags)
{
+ int valid_mkey = 0;
int ret = 0;
/* Is the mkey in the process of expiring? */
@@ -406,23 +407,36 @@ static int check_mkey(struct qib_ibport *ibp, struct ib_smp *smp, int mad_flags)
ibp->mkeyprot = 0;
}
- /* M_Key checking depends on Portinfo:M_Key_protect_bits */
- if ((mad_flags & IB_MAD_IGNORE_MKEY) == 0 && ibp->mkey != 0 &&
- ibp->mkey != smp->mkey &&
- (smp->method == IB_MGMT_METHOD_SET ||
- smp->method == IB_MGMT_METHOD_TRAP_REPRESS ||
- (smp->method == IB_MGMT_METHOD_GET && ibp->mkeyprot >= 2))) {
- if (ibp->mkey_violations != 0xFFFF)
- ++ibp->mkey_violations;
- if (!ibp->mkey_lease_timeout && ibp->mkey_lease_period)
- ibp->mkey_lease_timeout = jiffies +
- ibp->mkey_lease_period * HZ;
- /* Generate a trap notice. */
- qib_bad_mkey(ibp, smp);
- ret = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
- } else if (ibp->mkey_lease_timeout)
+ if ((mad_flags & IB_MAD_IGNORE_MKEY) || ibp->mkey == 0 ||
+ ibp->mkey == smp->mkey)
+ valid_mkey = 1;
+
+ /* Unset lease timeout on any valid Get/Set/TrapRepress */
+ if (valid_mkey && ibp->mkey_lease_timeout &&
+ (smp->method == IB_MGMT_METHOD_GET ||
+ smp->method == IB_MGMT_METHOD_SET ||
+ smp->method == IB_MGMT_METHOD_TRAP_REPRESS))
ibp->mkey_lease_timeout = 0;
+ if (!valid_mkey) {
+ switch (smp->method) {
+ case IB_MGMT_METHOD_GET:
+ /* Bad mkey not a violation below level 2 */
+ if (ibp->mkeyprot < 2)
+ break;
+ case IB_MGMT_METHOD_SET:
+ case IB_MGMT_METHOD_TRAP_REPRESS:
+ if (ibp->mkey_violations != 0xFFFF)
+ ++ibp->mkey_violations;
+ if (!ibp->mkey_lease_timeout && ibp->mkey_lease_period)
+ ibp->mkey_lease_timeout = jiffies +
+ ibp->mkey_lease_period * HZ;
+ /* Generate a trap notice. */
+ qib_bad_mkey(ibp, smp);
+ ret = 1;
+ }
+ }
+
return ret;
}
@@ -450,6 +464,7 @@ static int subn_get_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
ibp = to_iport(ibdev, port_num);
ret = check_mkey(ibp, smp, 0);
if (ret)
+ ret = IB_MAD_RESULT_FAILURE;
goto bail;
}
}
@@ -631,7 +646,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
struct qib_devdata *dd;
struct qib_pportdata *ppd;
struct qib_ibport *ibp;
- char clientrereg = 0;
+ u8 clientrereg = (pip->clientrereg_resv_subnetto & 0x80);
unsigned long flags;
u16 lid, smlid;
u8 lwe;
@@ -781,12 +796,6 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
ibp->subnet_timeout = pip->clientrereg_resv_subnetto & 0x1F;
- if (pip->clientrereg_resv_subnetto & 0x80) {
- clientrereg = 1;
- event.event = IB_EVENT_CLIENT_REREGISTER;
- ib_dispatch_event(&event);
- }
-
/*
* Do the port state change now that the other link parameters
* have been set.
@@ -844,10 +853,15 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
smp->status |= IB_SMP_INVALID_FIELD;
}
+ if (clientrereg) {
+ event.event = IB_EVENT_CLIENT_REREGISTER;
+ ib_dispatch_event(&event);
+ }
+
ret = subn_get_portinfo(smp, ibdev, port);
- if (clientrereg)
- pip->clientrereg_resv_subnetto |= 0x80;
+ /* restore re-reg bit per o14-12.2.1 */
+ pip->clientrereg_resv_subnetto |= clientrereg;
goto get_only;
@@ -1835,6 +1849,7 @@ static int process_subn(struct ib_device *ibdev, int mad_flags,
port_num && port_num <= ibdev->phys_port_cnt &&
port != port_num)
(void) check_mkey(to_iport(ibdev, port_num), smp, 0);
+ ret = IB_MAD_RESULT_FAILURE;
goto bail;
}
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c
index 7e7e16fbee99..1ce56b51ab1a 100644
--- a/drivers/infiniband/hw/qib/qib_qp.c
+++ b/drivers/infiniband/hw/qib/qib_qp.c
@@ -1038,6 +1038,11 @@ struct ib_qp *qib_create_qp(struct ib_pd *ibpd,
goto bail_swq;
}
RCU_INIT_POINTER(qp->next, NULL);
+ qp->s_hdr = kzalloc(sizeof(*qp->s_hdr), GFP_KERNEL);
+ if (!qp->s_hdr) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail_qp;
+ }
qp->timeout_jiffies =
usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
1000UL);
@@ -1159,6 +1164,7 @@ bail_ip:
vfree(qp->r_rq.wq);
free_qpn(&dev->qpn_table, qp->ibqp.qp_num);
bail_qp:
+ kfree(qp->s_hdr);
kfree(qp);
bail_swq:
vfree(swq);
@@ -1214,6 +1220,7 @@ int qib_destroy_qp(struct ib_qp *ibqp)
else
vfree(qp->r_rq.wq);
vfree(qp->s_wq);
+ kfree(qp->s_hdr);
kfree(qp);
return 0;
}
diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c
index 765b4cbaa020..b641416148eb 100644
--- a/drivers/infiniband/hw/qib/qib_rc.c
+++ b/drivers/infiniband/hw/qib/qib_rc.c
@@ -244,9 +244,9 @@ int qib_make_rc_req(struct qib_qp *qp)
int ret = 0;
int delta;
- ohdr = &qp->s_hdr.u.oth;
+ ohdr = &qp->s_hdr->u.oth;
if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
- ohdr = &qp->s_hdr.u.l.oth;
+ ohdr = &qp->s_hdr->u.l.oth;
/*
* The lock is needed to synchronize between the sending tasklet,
diff --git a/drivers/infiniband/hw/qib/qib_ruc.c b/drivers/infiniband/hw/qib/qib_ruc.c
index b4b37e47321a..c0ee7e095d81 100644
--- a/drivers/infiniband/hw/qib/qib_ruc.c
+++ b/drivers/infiniband/hw/qib/qib_ruc.c
@@ -688,17 +688,17 @@ void qib_make_ruc_header(struct qib_qp *qp, struct qib_other_headers *ohdr,
nwords = (qp->s_cur_size + extra_bytes) >> 2;
lrh0 = QIB_LRH_BTH;
if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) {
- qp->s_hdrwords += qib_make_grh(ibp, &qp->s_hdr.u.l.grh,
+ qp->s_hdrwords += qib_make_grh(ibp, &qp->s_hdr->u.l.grh,
&qp->remote_ah_attr.grh,
qp->s_hdrwords, nwords);
lrh0 = QIB_LRH_GRH;
}
lrh0 |= ibp->sl_to_vl[qp->remote_ah_attr.sl] << 12 |
qp->remote_ah_attr.sl << 4;
- qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
- qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
- qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords + SIZE_OF_CRC);
- qp->s_hdr.lrh[3] = cpu_to_be16(ppd_from_ibp(ibp)->lid |
+ qp->s_hdr->lrh[0] = cpu_to_be16(lrh0);
+ qp->s_hdr->lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
+ qp->s_hdr->lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords + SIZE_OF_CRC);
+ qp->s_hdr->lrh[3] = cpu_to_be16(ppd_from_ibp(ibp)->lid |
qp->remote_ah_attr.src_path_bits);
bth0 |= qib_get_pkey(ibp, qp->s_pkey_index);
bth0 |= extra_bytes << 20;
@@ -758,7 +758,7 @@ void qib_do_send(struct work_struct *work)
* If the packet cannot be sent now, return and
* the send tasklet will be woken up later.
*/
- if (qib_verbs_send(qp, &qp->s_hdr, qp->s_hdrwords,
+ if (qib_verbs_send(qp, qp->s_hdr, qp->s_hdrwords,
qp->s_cur_sge, qp->s_cur_size))
break;
/* Record that s_hdr is empty. */
diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c
index dae51604cfcd..dd9cd49d0979 100644
--- a/drivers/infiniband/hw/qib/qib_sysfs.c
+++ b/drivers/infiniband/hw/qib/qib_sysfs.c
@@ -503,8 +503,11 @@ static ssize_t show_nctxts(struct device *device,
struct qib_devdata *dd = dd_from_dev(dev);
/* Return the number of user ports (contexts) available. */
- return scnprintf(buf, PAGE_SIZE, "%u\n", dd->cfgctxts -
- dd->first_user_ctxt);
+ /* The calculation below deals with a special case where
+ * cfgctxts is set to 1 on a single-port board. */
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ (dd->first_user_ctxt > dd->cfgctxts) ? 0 :
+ (dd->cfgctxts - dd->first_user_ctxt));
}
static ssize_t show_nfreectxts(struct device *device,
diff --git a/drivers/infiniband/hw/qib/qib_tx.c b/drivers/infiniband/hw/qib/qib_tx.c
index 1bf626c40172..31d3561400a4 100644
--- a/drivers/infiniband/hw/qib/qib_tx.c
+++ b/drivers/infiniband/hw/qib/qib_tx.c
@@ -295,6 +295,7 @@ u32 __iomem *qib_getsendbuf_range(struct qib_devdata *dd, u32 *pbufnum,
nbufs = last - first + 1; /* number in range to check */
if (dd->upd_pio_shadow) {
+update_shadow:
/*
* Minor optimization. If we had no buffers on last call,
* start out by doing the update; continue and do scan even
@@ -304,37 +305,39 @@ u32 __iomem *qib_getsendbuf_range(struct qib_devdata *dd, u32 *pbufnum,
updated++;
}
i = first;
-rescan:
/*
* While test_and_set_bit() is atomic, we do that and then the
* change_bit(), and the pair is not. See if this is the cause
* of the remaining armlaunch errors.
*/
spin_lock_irqsave(&dd->pioavail_lock, flags);
+ if (dd->last_pio >= first && dd->last_pio <= last)
+ i = dd->last_pio + 1;
+ if (!first)
+ /* adjust to min possible */
+ nbufs = last - dd->min_kernel_pio + 1;
for (j = 0; j < nbufs; j++, i++) {
if (i > last)
- i = first;
+ i = !first ? dd->min_kernel_pio : first;
if (__test_and_set_bit((2 * i) + 1, shadow))
continue;
/* flip generation bit */
__change_bit(2 * i, shadow);
/* remember that the buffer can be written to now */
__set_bit(i, dd->pio_writing);
+ if (!first && first != last) /* first == last on VL15, avoid */
+ dd->last_pio = i;
break;
}
spin_unlock_irqrestore(&dd->pioavail_lock, flags);
if (j == nbufs) {
- if (!updated) {
+ if (!updated)
/*
* First time through; shadow exhausted, but may be
* buffers available, try an update and then rescan.
*/
- update_send_bufs(dd);
- updated++;
- i = first;
- goto rescan;
- }
+ goto update_shadow;
no_send_bufs(dd);
buf = NULL;
} else {
@@ -422,14 +425,20 @@ void qib_chg_pioavailkernel(struct qib_devdata *dd, unsigned start,
__clear_bit(QLOGIC_IB_SENDPIOAVAIL_CHECK_SHIFT
+ start, dd->pioavailshadow);
__set_bit(start, dd->pioavailkernel);
+ if ((start >> 1) < dd->min_kernel_pio)
+ dd->min_kernel_pio = start >> 1;
} else {
__set_bit(start + QLOGIC_IB_SENDPIOAVAIL_BUSY_SHIFT,
dd->pioavailshadow);
__clear_bit(start, dd->pioavailkernel);
+ if ((start >> 1) > dd->min_kernel_pio)
+ dd->min_kernel_pio = start >> 1;
}
start += 2;
}
+ if (dd->min_kernel_pio > 0 && dd->last_pio < dd->min_kernel_pio - 1)
+ dd->last_pio = dd->min_kernel_pio - 1;
spin_unlock_irqrestore(&dd->pioavail_lock, flags);
dd->f_txchk_change(dd, ostart, len, avail, rcd);
diff --git a/drivers/infiniband/hw/qib/qib_uc.c b/drivers/infiniband/hw/qib/qib_uc.c
index 7ce2ac2ed219..ce7387ff5d91 100644
--- a/drivers/infiniband/hw/qib/qib_uc.c
+++ b/drivers/infiniband/hw/qib/qib_uc.c
@@ -72,9 +72,9 @@ int qib_make_uc_req(struct qib_qp *qp)
goto done;
}
- ohdr = &qp->s_hdr.u.oth;
+ ohdr = &qp->s_hdr->u.oth;
if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
- ohdr = &qp->s_hdr.u.l.oth;
+ ohdr = &qp->s_hdr->u.l.oth;
/* header size in 32-bit words LRH+BTH = (8+12)/4. */
hwords = 5;
diff --git a/drivers/infiniband/hw/qib/qib_ud.c b/drivers/infiniband/hw/qib/qib_ud.c
index 828609fa4d28..a468bf2d4465 100644
--- a/drivers/infiniband/hw/qib/qib_ud.c
+++ b/drivers/infiniband/hw/qib/qib_ud.c
@@ -321,11 +321,11 @@ int qib_make_ud_req(struct qib_qp *qp)
if (ah_attr->ah_flags & IB_AH_GRH) {
/* Header size in 32-bit words. */
- qp->s_hdrwords += qib_make_grh(ibp, &qp->s_hdr.u.l.grh,
+ qp->s_hdrwords += qib_make_grh(ibp, &qp->s_hdr->u.l.grh,
&ah_attr->grh,
qp->s_hdrwords, nwords);
lrh0 = QIB_LRH_GRH;
- ohdr = &qp->s_hdr.u.l.oth;
+ ohdr = &qp->s_hdr->u.l.oth;
/*
* Don't worry about sending to locally attached multicast
* QPs. It is unspecified by the spec. what happens.
@@ -333,7 +333,7 @@ int qib_make_ud_req(struct qib_qp *qp)
} else {
/* Header size in 32-bit words. */
lrh0 = QIB_LRH_BTH;
- ohdr = &qp->s_hdr.u.oth;
+ ohdr = &qp->s_hdr->u.oth;
}
if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
qp->s_hdrwords++;
@@ -346,15 +346,15 @@ int qib_make_ud_req(struct qib_qp *qp)
lrh0 |= 0xF000; /* Set VL (see ch. 13.5.3.1) */
else
lrh0 |= ibp->sl_to_vl[ah_attr->sl] << 12;
- qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
- qp->s_hdr.lrh[1] = cpu_to_be16(ah_attr->dlid); /* DEST LID */
- qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords + SIZE_OF_CRC);
+ qp->s_hdr->lrh[0] = cpu_to_be16(lrh0);
+ qp->s_hdr->lrh[1] = cpu_to_be16(ah_attr->dlid); /* DEST LID */
+ qp->s_hdr->lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords + SIZE_OF_CRC);
lid = ppd->lid;
if (lid) {
lid |= ah_attr->src_path_bits & ((1 << ppd->lmc) - 1);
- qp->s_hdr.lrh[3] = cpu_to_be16(lid);
+ qp->s_hdr->lrh[3] = cpu_to_be16(lid);
} else
- qp->s_hdr.lrh[3] = IB_LID_PERMISSIVE;
+ qp->s_hdr->lrh[3] = IB_LID_PERMISSIVE;
if (wqe->wr.send_flags & IB_SEND_SOLICITED)
bth0 |= IB_BTH_SOLICITED;
bth0 |= extra_bytes << 20;
diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h
index 0c19ef0c4123..487606024659 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.h
+++ b/drivers/infiniband/hw/qib/qib_verbs.h
@@ -367,9 +367,10 @@ struct qib_rwq {
struct qib_rq {
struct qib_rwq *wq;
- spinlock_t lock; /* protect changes in this struct */
u32 size; /* size of RWQE array */
u8 max_sge;
+ spinlock_t lock /* protect changes in this struct */
+ ____cacheline_aligned_in_smp;
};
struct qib_srq {
@@ -412,31 +413,75 @@ struct qib_ack_entry {
*/
struct qib_qp {
struct ib_qp ibqp;
- struct qib_qp *next; /* link list for QPN hash table */
- struct qib_qp *timer_next; /* link list for qib_ib_timer() */
- struct list_head iowait; /* link for wait PIO buf */
- struct list_head rspwait; /* link for waititing to respond */
+ /* read mostly fields above and below */
struct ib_ah_attr remote_ah_attr;
struct ib_ah_attr alt_ah_attr;
- struct qib_ib_header s_hdr; /* next packet header to send */
- atomic_t refcount;
- wait_queue_head_t wait;
- wait_queue_head_t wait_dma;
- struct timer_list s_timer;
- struct work_struct s_work;
+ struct qib_qp *next; /* link list for QPN hash table */
+ struct qib_swqe *s_wq; /* send work queue */
struct qib_mmap_info *ip;
+ struct qib_ib_header *s_hdr; /* next packet header to send */
+ unsigned long timeout_jiffies; /* computed from timeout */
+
+ enum ib_mtu path_mtu;
+ u32 remote_qpn;
+ u32 pmtu; /* decoded from path_mtu */
+ u32 qkey; /* QKEY for this QP (for UD or RD) */
+ u32 s_size; /* send work queue size */
+ u32 s_rnr_timeout; /* number of milliseconds for RNR timeout */
+
+ u8 state; /* QP state */
+ u8 qp_access_flags;
+ u8 alt_timeout; /* Alternate path timeout for this QP */
+ u8 timeout; /* Timeout for this QP */
+ u8 s_srate;
+ u8 s_mig_state;
+ u8 port_num;
+ u8 s_pkey_index; /* PKEY index to use */
+ u8 s_alt_pkey_index; /* Alternate path PKEY index to use */
+ u8 r_max_rd_atomic; /* max number of RDMA read/atomic to receive */
+ u8 s_max_rd_atomic; /* max number of RDMA read/atomic to send */
+ u8 s_retry_cnt; /* number of times to retry */
+ u8 s_rnr_retry_cnt;
+ u8 r_min_rnr_timer; /* retry timeout value for RNR NAKs */
+ u8 s_max_sge; /* size of s_wq->sg_list */
+ u8 s_draining;
+
+ /* start of read/write fields */
+
+ atomic_t refcount ____cacheline_aligned_in_smp;
+ wait_queue_head_t wait;
+
+
+ struct qib_ack_entry s_ack_queue[QIB_MAX_RDMA_ATOMIC + 1]
+ ____cacheline_aligned_in_smp;
+ struct qib_sge_state s_rdma_read_sge;
+
+ spinlock_t r_lock ____cacheline_aligned_in_smp; /* used for APM */
+ unsigned long r_aflags;
+ u64 r_wr_id; /* ID for current receive WQE */
+ u32 r_ack_psn; /* PSN for next ACK or atomic ACK */
+ u32 r_len; /* total length of r_sge */
+ u32 r_rcv_len; /* receive data len processed */
+ u32 r_psn; /* expected rcv packet sequence number */
+ u32 r_msn; /* message sequence number */
+
+ u8 r_state; /* opcode of last packet received */
+ u8 r_flags;
+ u8 r_head_ack_queue; /* index into s_ack_queue[] */
+
+ struct list_head rspwait; /* link for waititing to respond */
+
+ struct qib_sge_state r_sge; /* current receive data */
+ struct qib_rq r_rq; /* receive work queue */
+
+ spinlock_t s_lock ____cacheline_aligned_in_smp;
struct qib_sge_state *s_cur_sge;
+ u32 s_flags;
struct qib_verbs_txreq *s_tx;
- struct qib_mregion *s_rdma_mr;
+ struct qib_swqe *s_wqe;
struct qib_sge_state s_sge; /* current send request data */
- struct qib_ack_entry s_ack_queue[QIB_MAX_RDMA_ATOMIC + 1];
- struct qib_sge_state s_ack_rdma_sge;
- struct qib_sge_state s_rdma_read_sge;
- struct qib_sge_state r_sge; /* current receive data */
- spinlock_t r_lock; /* used for APM */
- spinlock_t s_lock;
+ struct qib_mregion *s_rdma_mr;
atomic_t s_dma_busy;
- u32 s_flags;
u32 s_cur_size; /* size of send packet in bytes */
u32 s_len; /* total length of s_sge */
u32 s_rdma_read_len; /* total length of s_rdma_read_sge */
@@ -447,60 +492,34 @@ struct qib_qp {
u32 s_psn; /* current packet sequence number */
u32 s_ack_rdma_psn; /* PSN for sending RDMA read responses */
u32 s_ack_psn; /* PSN for acking sends and RDMA writes */
- u32 s_rnr_timeout; /* number of milliseconds for RNR timeout */
- u32 r_ack_psn; /* PSN for next ACK or atomic ACK */
- u64 r_wr_id; /* ID for current receive WQE */
- unsigned long r_aflags;
- u32 r_len; /* total length of r_sge */
- u32 r_rcv_len; /* receive data len processed */
- u32 r_psn; /* expected rcv packet sequence number */
- u32 r_msn; /* message sequence number */
+ u32 s_head; /* new entries added here */
+ u32 s_tail; /* next entry to process */
+ u32 s_cur; /* current work queue entry */
+ u32 s_acked; /* last un-ACK'ed entry */
+ u32 s_last; /* last completed entry */
+ u32 s_ssn; /* SSN of tail entry */
+ u32 s_lsn; /* limit sequence number (credit) */
u16 s_hdrwords; /* size of s_hdr in 32 bit words */
u16 s_rdma_ack_cnt;
- u8 state; /* QP state */
u8 s_state; /* opcode of last packet sent */
u8 s_ack_state; /* opcode of packet to ACK */
u8 s_nak_state; /* non-zero if NAK is pending */
- u8 r_state; /* opcode of last packet received */
u8 r_nak_state; /* non-zero if NAK is pending */
- u8 r_min_rnr_timer; /* retry timeout value for RNR NAKs */
- u8 r_flags;
- u8 r_max_rd_atomic; /* max number of RDMA read/atomic to receive */
- u8 r_head_ack_queue; /* index into s_ack_queue[] */
- u8 qp_access_flags;
- u8 s_max_sge; /* size of s_wq->sg_list */
- u8 s_retry_cnt; /* number of times to retry */
- u8 s_rnr_retry_cnt;
u8 s_retry; /* requester retry counter */
u8 s_rnr_retry; /* requester RNR retry counter */
- u8 s_pkey_index; /* PKEY index to use */
- u8 s_alt_pkey_index; /* Alternate path PKEY index to use */
- u8 s_max_rd_atomic; /* max number of RDMA read/atomic to send */
u8 s_num_rd_atomic; /* number of RDMA read/atomic pending */
u8 s_tail_ack_queue; /* index into s_ack_queue[] */
- u8 s_srate;
- u8 s_draining;
- u8 s_mig_state;
- u8 timeout; /* Timeout for this QP */
- u8 alt_timeout; /* Alternate path timeout for this QP */
- u8 port_num;
- enum ib_mtu path_mtu;
- u32 pmtu; /* decoded from path_mtu */
- u32 remote_qpn;
- u32 qkey; /* QKEY for this QP (for UD or RD) */
- u32 s_size; /* send work queue size */
- u32 s_head; /* new entries added here */
- u32 s_tail; /* next entry to process */
- u32 s_cur; /* current work queue entry */
- u32 s_acked; /* last un-ACK'ed entry */
- u32 s_last; /* last completed entry */
- u32 s_ssn; /* SSN of tail entry */
- u32 s_lsn; /* limit sequence number (credit) */
- unsigned long timeout_jiffies; /* computed from timeout */
- struct qib_swqe *s_wq; /* send work queue */
- struct qib_swqe *s_wqe;
- struct qib_rq r_rq; /* receive work queue */
- struct qib_sge r_sg_list[0]; /* verified SGEs */
+
+ struct qib_sge_state s_ack_rdma_sge;
+ struct timer_list s_timer;
+ struct list_head iowait; /* link for wait PIO buf */
+
+ struct work_struct s_work;
+
+ wait_queue_head_t wait_dma;
+
+ struct qib_sge r_sg_list[0] /* verified SGEs */
+ ____cacheline_aligned_in_smp;
};
/*
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index db43b3117168..0ab8c9cc3a78 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -573,10 +573,9 @@ iscsi_iser_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
err = iser_connect(ib_conn, NULL, (struct sockaddr_in *)dst_addr,
non_blocking);
- if (err) {
- iscsi_destroy_endpoint(ep);
+ if (err)
return ERR_PTR(err);
- }
+
return ep;
}
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 14224ba44fd8..2dddabd8fcf9 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -613,8 +613,9 @@ id_failure:
ib_conn->cma_id = NULL;
addr_failure:
ib_conn->state = ISER_CONN_DOWN;
+ iser_conn_put(ib_conn, 1); /* deref ib conn's cma id */
connect_failure:
- iser_conn_release(ib_conn, 1);
+ iser_conn_put(ib_conn, 1); /* deref ib conn deallocate */
return err;
}
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index daf21b899999..5f6b7f63cdef 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -1099,9 +1099,8 @@ static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch,
dir = cmd->data_direction;
BUG_ON(dir == DMA_NONE);
- transport_do_task_sg_chain(cmd);
- ioctx->sg = sg = sg_orig = cmd->t_tasks_sg_chained;
- ioctx->sg_cnt = sg_cnt = cmd->t_tasks_sg_chained_no;
+ ioctx->sg = sg = sg_orig = cmd->t_data_sg;
+ ioctx->sg_cnt = sg_cnt = cmd->t_data_nents;
count = ib_dma_map_sg(ch->sport->sdev->device, sg, sg_cnt,
opposite_dma_dir(dir));
@@ -1769,7 +1768,7 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
goto send_sense;
}
- ret = transport_generic_allocate_tasks(cmd, srp_cmd->cdb);
+ ret = target_setup_cmd_from_cdb(cmd, srp_cmd->cdb);
if (ret < 0) {
kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) {
@@ -4004,9 +4003,6 @@ static int __init srpt_init_module(void)
srpt_target->tf_ops = srpt_template;
- /* Enable SG chaining */
- srpt_target->tf_ops.task_sg_chaining = true;
-
/*
* Set up default attribute lists.
*/
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 405febd94f24..daeeb4c7e3b0 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -317,7 +317,8 @@ int iforce_init_device(struct iforce *iforce)
break;
if (i == 20) { /* 5 seconds */
- err("Timeout waiting for response from device.");
+ dev_err(&input_dev->dev,
+ "Timeout waiting for response from device.\n");
error = -ENODEV;
goto fail;
}
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index a17b50016009..08f98f2eaf88 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -257,7 +257,8 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
status = usb_submit_urb(iforce->ctrl, GFP_ATOMIC);
if (status) {
- err("usb_submit_urb failed %d", status);
+ dev_err(&iforce->intf->dev,
+ "usb_submit_urb failed %d\n", status);
return -1;
}
@@ -265,12 +266,14 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
iforce->ctrl->status != -EINPROGRESS, HZ);
if (iforce->ctrl->status) {
- dbg("iforce->ctrl->status = %d", iforce->ctrl->status);
+ dev_dbg(&iforce->intf->dev,
+ "iforce->ctrl->status = %d\n",
+ iforce->ctrl->status);
usb_unlink_urb(iforce->ctrl);
return -1;
}
#else
- dbg("iforce_get_id_packet: iforce->bus = USB!");
+ printk(KERN_DEBUG "iforce_get_id_packet: iforce->bus = USB!\n");
#endif
}
break;
@@ -289,12 +292,15 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
return -1;
}
#else
- err("iforce_get_id_packet: iforce->bus = SERIO!");
+ dev_err(&iforce->dev->dev,
+ "iforce_get_id_packet: iforce->bus = SERIO!\n");
#endif
break;
default:
- err("iforce_get_id_packet: iforce->bus = %d", iforce->bus);
+ dev_err(&iforce->dev->dev,
+ "iforce_get_id_packet: iforce->bus = %d\n",
+ iforce->bus);
break;
}
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 6c96631ae5d9..d96aa27dfcdc 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -64,7 +64,7 @@ void iforce_usb_xmit(struct iforce *iforce)
if ( (n=usb_submit_urb(iforce->out, GFP_ATOMIC)) ) {
clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
- dev_warn(&iforce->dev->dev, "usb_submit_urb failed %d\n", n);
+ dev_warn(&iforce->intf->dev, "usb_submit_urb failed %d\n", n);
}
/* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
@@ -76,6 +76,7 @@ void iforce_usb_xmit(struct iforce *iforce)
static void iforce_usb_irq(struct urb *urb)
{
struct iforce *iforce = urb->context;
+ struct device *dev = &iforce->intf->dev;
int status;
switch (urb->status) {
@@ -86,11 +87,12 @@ static void iforce_usb_irq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, urb->status);
+ dev_dbg(dev, "%s - urb shutting down with status: %d\n",
+ __func__, urb->status);
return;
default:
- dbg("%s - urb has status of: %d", __func__, urb->status);
+ dev_dbg(dev, "%s - urb has status of: %d\n",
+ __func__, urb->status);
goto exit;
}
@@ -100,8 +102,8 @@ static void iforce_usb_irq(struct urb *urb)
exit:
status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
- err ("%s - usb_submit_urb failed with result %d",
- __func__, status);
+ dev_err(dev, "%s - usb_submit_urb failed with result %d\n",
+ __func__, status);
}
static void iforce_usb_out(struct urb *urb)
@@ -110,7 +112,8 @@ static void iforce_usb_out(struct urb *urb)
if (urb->status) {
clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
- dbg("urb->status %d, exiting", urb->status);
+ dev_dbg(&iforce->intf->dev, "urb->status %d, exiting\n",
+ urb->status);
return;
}
@@ -155,6 +158,7 @@ static int iforce_usb_probe(struct usb_interface *intf,
iforce->bus = IFORCE_USB;
iforce->usbdev = dev;
+ iforce->intf = intf;
iforce->cr.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE;
iforce->cr.wIndex = 0;
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index 9f494b75848a..b1d7d9b0eb86 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -115,6 +115,7 @@ struct iforce {
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_USB
struct usb_device *usbdev; /* USB transfer */
+ struct usb_interface *intf;
struct urb *irq, *out, *ctrl;
struct usb_ctrlrequest cr;
#endif
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index fd7a0d5bc94d..ee16fb67b7ae 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -252,6 +252,7 @@ MODULE_DEVICE_TABLE (usb, xpad_table);
struct usb_xpad {
struct input_dev *dev; /* input device interface */
struct usb_device *udev; /* usb device */
+ struct usb_interface *intf; /* usb interface */
int pad_present;
@@ -457,6 +458,7 @@ static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned cha
static void xpad_irq_in(struct urb *urb)
{
struct usb_xpad *xpad = urb->context;
+ struct device *dev = &xpad->intf->dev;
int retval, status;
status = urb->status;
@@ -469,11 +471,11 @@ static void xpad_irq_in(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
+ dev_dbg(dev, "%s - urb shutting down with status: %d\n",
__func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
+ dev_dbg(dev, "%s - nonzero urb status received: %d\n",
__func__, status);
goto exit;
}
@@ -492,12 +494,15 @@ static void xpad_irq_in(struct urb *urb)
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err ("%s - usb_submit_urb failed with result %d",
- __func__, retval);
+ dev_err(dev, "%s - usb_submit_urb failed with result %d\n",
+ __func__, retval);
}
static void xpad_bulk_out(struct urb *urb)
{
+ struct usb_xpad *xpad = urb->context;
+ struct device *dev = &xpad->intf->dev;
+
switch (urb->status) {
case 0:
/* success */
@@ -506,16 +511,20 @@ static void xpad_bulk_out(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__, urb->status);
+ dev_dbg(dev, "%s - urb shutting down with status: %d\n",
+ __func__, urb->status);
break;
default:
- dbg("%s - nonzero urb status received: %d", __func__, urb->status);
+ dev_dbg(dev, "%s - nonzero urb status received: %d\n",
+ __func__, urb->status);
}
}
#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
static void xpad_irq_out(struct urb *urb)
{
+ struct usb_xpad *xpad = urb->context;
+ struct device *dev = &xpad->intf->dev;
int retval, status;
status = urb->status;
@@ -529,19 +538,21 @@ static void xpad_irq_out(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__, status);
+ dev_dbg(dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__, status);
+ dev_dbg(dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err("%s - usb_submit_urb failed with result %d",
- __func__, retval);
+ dev_err(dev, "%s - usb_submit_urb failed with result %d\n",
+ __func__, retval);
}
static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
@@ -654,7 +665,8 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
default:
- dbg("%s - rumble command sent to unsupported xpad type: %d",
+ dev_dbg(&xpad->dev->dev,
+ "%s - rumble command sent to unsupported xpad type: %d\n",
__func__, xpad->xtype);
return -1;
}
@@ -844,6 +856,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
}
xpad->udev = udev;
+ xpad->intf = intf;
xpad->mapping = xpad_device[i].mapping;
xpad->xtype = xpad_device[i].xtype;
diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c
index ab860511f016..082684e7f390 100644
--- a/drivers/input/misc/cm109.c
+++ b/drivers/input/misc/cm109.c
@@ -327,7 +327,9 @@ static void cm109_submit_buzz_toggle(struct cm109_dev *dev)
error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC);
if (error)
- err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error);
+ dev_err(&dev->intf->dev,
+ "%s: usb_submit_urb (urb_ctl) failed %d\n",
+ __func__, error);
}
/*
@@ -339,7 +341,7 @@ static void cm109_urb_irq_callback(struct urb *urb)
const int status = urb->status;
int error;
- dev_dbg(&urb->dev->dev, "### URB IRQ: [0x%02x 0x%02x 0x%02x 0x%02x] keybit=0x%02x\n",
+ dev_dbg(&dev->intf->dev, "### URB IRQ: [0x%02x 0x%02x 0x%02x 0x%02x] keybit=0x%02x\n",
dev->irq_data->byte[0],
dev->irq_data->byte[1],
dev->irq_data->byte[2],
@@ -349,7 +351,7 @@ static void cm109_urb_irq_callback(struct urb *urb)
if (status) {
if (status == -ESHUTDOWN)
return;
- err("%s: urb status %d", __func__, status);
+ dev_err(&dev->intf->dev, "%s: urb status %d\n", __func__, status);
}
/* Special keys */
@@ -396,7 +398,8 @@ static void cm109_urb_irq_callback(struct urb *urb)
error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC);
if (error)
- err("%s: usb_submit_urb (urb_ctl) failed %d",
+ dev_err(&dev->intf->dev,
+ "%s: usb_submit_urb (urb_ctl) failed %d\n",
__func__, error);
}
@@ -409,14 +412,14 @@ static void cm109_urb_ctl_callback(struct urb *urb)
const int status = urb->status;
int error;
- dev_dbg(&urb->dev->dev, "### URB CTL: [0x%02x 0x%02x 0x%02x 0x%02x]\n",
+ dev_dbg(&dev->intf->dev, "### URB CTL: [0x%02x 0x%02x 0x%02x 0x%02x]\n",
dev->ctl_data->byte[0],
dev->ctl_data->byte[1],
dev->ctl_data->byte[2],
dev->ctl_data->byte[3]);
if (status)
- err("%s: urb status %d", __func__, status);
+ dev_err(&dev->intf->dev, "%s: urb status %d\n", __func__, status);
spin_lock(&dev->ctl_submit_lock);
@@ -433,7 +436,8 @@ static void cm109_urb_ctl_callback(struct urb *urb)
dev->irq_urb_pending = 1;
error = usb_submit_urb(dev->urb_irq, GFP_ATOMIC);
if (error)
- err("%s: usb_submit_urb (urb_irq) failed %d",
+ dev_err(&dev->intf->dev,
+ "%s: usb_submit_urb (urb_irq) failed %d\n",
__func__, error);
}
}
@@ -476,7 +480,8 @@ static void cm109_toggle_buzzer_sync(struct cm109_dev *dev, int on)
dev->ctl_data,
USB_PKT_LEN, USB_CTRL_SET_TIMEOUT);
if (error < 0 && error != -EINTR)
- err("%s: usb_control_msg() failed %d", __func__, error);
+ dev_err(&dev->intf->dev, "%s: usb_control_msg() failed %d\n",
+ __func__, error);
}
static void cm109_stop_traffic(struct cm109_dev *dev)
@@ -518,8 +523,8 @@ static int cm109_input_open(struct input_dev *idev)
error = usb_autopm_get_interface(dev->intf);
if (error < 0) {
- err("%s - cannot autoresume, result %d",
- __func__, error);
+ dev_err(&idev->dev, "%s - cannot autoresume, result %d\n",
+ __func__, error);
return error;
}
@@ -537,7 +542,8 @@ static int cm109_input_open(struct input_dev *idev)
error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL);
if (error)
- err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error);
+ dev_err(&dev->intf->dev, "%s: usb_submit_urb (urb_ctl) failed %d\n",
+ __func__, error);
else
dev->open = 1;
@@ -573,7 +579,7 @@ static int cm109_input_ev(struct input_dev *idev, unsigned int type,
{
struct cm109_dev *dev = input_get_drvdata(idev);
- dev_dbg(&dev->udev->dev,
+ dev_dbg(&dev->intf->dev,
"input_ev: type=%u code=%u value=%d\n", type, code, value);
if (type != EV_SND)
@@ -710,7 +716,8 @@ static int cm109_usb_probe(struct usb_interface *intf,
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
if (ret != USB_PKT_LEN)
- err("invalid payload size %d, expected %d", ret, USB_PKT_LEN);
+ dev_err(&intf->dev, "invalid payload size %d, expected %d\n",
+ ret, USB_PKT_LEN);
/* initialise irq urb */
usb_fill_int_urb(dev->urb_irq, udev, pipe, dev->irq_data,
diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c
index d99151a8bf10..290fa5f97ded 100644
--- a/drivers/input/misc/keyspan_remote.c
+++ b/drivers/input/misc/keyspan_remote.c
@@ -157,7 +157,7 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed)
* though so it's not too big a deal
*/
if (dev->data.pos >= dev->data.len) {
- dev_dbg(&dev->udev->dev,
+ dev_dbg(&dev->interface->dev,
"%s - Error ran out of data. pos: %d, len: %d\n",
__func__, dev->data.pos, dev->data.len);
return -1;
@@ -267,7 +267,9 @@ static void keyspan_check_data(struct usb_keyspan *remote)
remote->data.tester = remote->data.tester >> 6;
remote->data.bits_left -= 6;
} else {
- err("%s - Unknown sequence found in system data.\n", __func__);
+ dev_err(&remote->interface->dev,
+ "%s - Unknown sequence found in system data.\n",
+ __func__);
remote->stage = 0;
return;
}
@@ -286,7 +288,9 @@ static void keyspan_check_data(struct usb_keyspan *remote)
remote->data.tester = remote->data.tester >> 6;
remote->data.bits_left -= 6;
} else {
- err("%s - Unknown sequence found in button data.\n", __func__);
+ dev_err(&remote->interface->dev,
+ "%s - Unknown sequence found in button data.\n",
+ __func__);
remote->stage = 0;
return;
}
@@ -302,7 +306,9 @@ static void keyspan_check_data(struct usb_keyspan *remote)
remote->data.tester = remote->data.tester >> 6;
remote->data.bits_left -= 6;
} else {
- err("%s - Error in message, invalid toggle.\n", __func__);
+ dev_err(&remote->interface->dev,
+ "%s - Error in message, invalid toggle.\n",
+ __func__);
remote->stage = 0;
return;
}
@@ -312,10 +318,11 @@ static void keyspan_check_data(struct usb_keyspan *remote)
remote->data.tester = remote->data.tester >> 5;
remote->data.bits_left -= 5;
} else {
- err("Bad message received, no stop bit found.\n");
+ dev_err(&remote->interface->dev,
+ "Bad message received, no stop bit found.\n");
}
- dev_dbg(&remote->udev->dev,
+ dev_dbg(&remote->interface->dev,
"%s found valid message: system: %d, button: %d, toggle: %d\n",
__func__, message.system, message.button, message.toggle);
@@ -397,7 +404,9 @@ static void keyspan_irq_recv(struct urb *urb)
resubmit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err ("%s - usb_submit_urb failed with result: %d", __func__, retval);
+ dev_err(&dev->interface->dev,
+ "%s - usb_submit_urb failed with result: %d\n",
+ __func__, retval);
}
static int keyspan_open(struct input_dev *dev)
diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c
index 538f7049ec64..49c0c3ebd321 100644
--- a/drivers/input/misc/powermate.c
+++ b/drivers/input/misc/powermate.c
@@ -65,6 +65,7 @@ struct powermate_device {
struct urb *irq, *config;
struct usb_ctrlrequest *configcr;
struct usb_device *udev;
+ struct usb_interface *intf;
struct input_dev *input;
spinlock_t lock;
int static_brightness;
@@ -85,6 +86,7 @@ static void powermate_config_complete(struct urb *urb);
static void powermate_irq(struct urb *urb)
{
struct powermate_device *pm = urb->context;
+ struct device *dev = &pm->intf->dev;
int retval;
switch (urb->status) {
@@ -95,10 +97,12 @@ static void powermate_irq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__, urb->status);
+ dev_dbg(dev, "%s - urb shutting down with status: %d\n",
+ __func__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__, urb->status);
+ dev_dbg(dev, "%s - nonzero urb status received: %d\n",
+ __func__, urb->status);
goto exit;
}
@@ -110,8 +114,8 @@ static void powermate_irq(struct urb *urb)
exit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
if (retval)
- err ("%s - usb_submit_urb failed with result %d",
- __func__, retval);
+ dev_err(dev, "%s - usb_submit_urb failed with result: %d\n",
+ __func__, retval);
}
/* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */
@@ -330,6 +334,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
goto fail3;
pm->udev = udev;
+ pm->intf = intf;
pm->input = input_dev;
usb_make_path(udev, pm->phys, sizeof(pm->phys));
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c
index f4776e7f8c15..285a5bd6cbc9 100644
--- a/drivers/input/misc/yealink.c
+++ b/drivers/input/misc/yealink.c
@@ -101,6 +101,7 @@ static const struct lcd_segment_map {
struct yealink_dev {
struct input_dev *idev; /* input device */
struct usb_device *udev; /* usb device */
+ struct usb_interface *intf; /* usb interface */
/* irq input channel */
struct yld_ctl_packet *irq_data;
@@ -428,7 +429,8 @@ static void urb_irq_callback(struct urb *urb)
int ret, status = urb->status;
if (status)
- err("%s - urb status %d", __func__, status);
+ dev_err(&yld->intf->dev, "%s - urb status %d\n",
+ __func__, status);
switch (yld->irq_data->cmd) {
case CMD_KEYPRESS:
@@ -437,13 +439,15 @@ static void urb_irq_callback(struct urb *urb)
break;
case CMD_SCANCODE:
- dbg("get scancode %x", yld->irq_data->data[0]);
+ dev_dbg(&yld->intf->dev, "get scancode %x\n",
+ yld->irq_data->data[0]);
report_key(yld, map_p1k_to_key(yld->irq_data->data[0]));
break;
default:
- err("unexpected response %x", yld->irq_data->cmd);
+ dev_err(&yld->intf->dev, "unexpected response %x\n",
+ yld->irq_data->cmd);
}
yealink_do_idle_tasks(yld);
@@ -451,7 +455,9 @@ static void urb_irq_callback(struct urb *urb)
if (!yld->shutdown) {
ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
if (ret && ret != -EPERM)
- err("%s - usb_submit_urb failed %d", __func__, ret);
+ dev_err(&yld->intf->dev,
+ "%s - usb_submit_urb failed %d\n",
+ __func__, ret);
}
}
@@ -461,7 +467,8 @@ static void urb_ctl_callback(struct urb *urb)
int ret = 0, status = urb->status;
if (status)
- err("%s - urb status %d", __func__, status);
+ dev_err(&yld->intf->dev, "%s - urb status %d\n",
+ __func__, status);
switch (yld->ctl_data->cmd) {
case CMD_KEYPRESS:
@@ -479,7 +486,8 @@ static void urb_ctl_callback(struct urb *urb)
}
if (ret && ret != -EPERM)
- err("%s - usb_submit_urb failed %d", __func__, ret);
+ dev_err(&yld->intf->dev, "%s - usb_submit_urb failed %d\n",
+ __func__, ret);
}
/*******************************************************************************
@@ -511,7 +519,7 @@ static int input_open(struct input_dev *dev)
struct yealink_dev *yld = input_get_drvdata(dev);
int i, ret;
- dbg("%s", __func__);
+ dev_dbg(&yld->intf->dev, "%s\n", __func__);
/* force updates to device */
for (i = 0; i<sizeof(yld->master); i++)
@@ -526,8 +534,9 @@ static int input_open(struct input_dev *dev)
yld->ctl_data->size = 10;
yld->ctl_data->sum = 0x100-CMD_INIT-10;
if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) {
- dbg("%s - usb_submit_urb failed with result %d",
- __func__, ret);
+ dev_dbg(&yld->intf->dev,
+ "%s - usb_submit_urb failed with result %d\n",
+ __func__, ret);
return ret;
}
return 0;
@@ -876,6 +885,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
return -ENOMEM;
yld->udev = udev;
+ yld->intf = intf;
yld->idev = input_dev = input_allocate_device();
if (!input_dev)
@@ -909,7 +919,8 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
if (ret != USB_PKT_LEN)
- err("invalid payload size %d, expected %zd", ret, USB_PKT_LEN);
+ dev_err(&intf->dev, "invalid payload size %d, expected %zd\n",
+ ret, USB_PKT_LEN);
/* initialise irq urb */
usb_fill_int_urb(yld->urb_irq, udev, pipe, yld->irq_data,
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index 0acbc7d50d05..e42f1fa8cdc0 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -195,6 +195,7 @@ enum atp_status_bits {
struct atp {
char phys[64];
struct usb_device *udev; /* usb device */
+ struct usb_interface *intf; /* usb interface */
struct urb *urb; /* usb request block */
u8 *data; /* transferred data */
struct input_dev *input; /* input dev */
@@ -253,8 +254,9 @@ MODULE_PARM_DESC(debug, "Activate debugging output");
* packets (Report ID 2). This code changes device mode, so it
* sends raw sensor reports (Report ID 5).
*/
-static int atp_geyser_init(struct usb_device *udev)
+static int atp_geyser_init(struct atp *dev)
{
+ struct usb_device *udev = dev->udev;
char *data;
int size;
int i;
@@ -262,7 +264,7 @@ static int atp_geyser_init(struct usb_device *udev)
data = kmalloc(8, GFP_KERNEL);
if (!data) {
- err("Out of memory");
+ dev_err(&dev->intf->dev, "Out of memory\n");
return -ENOMEM;
}
@@ -277,7 +279,7 @@ static int atp_geyser_init(struct usb_device *udev)
for (i = 0; i < 8; i++)
dprintk("appletouch[%d]: %d\n", i, data[i]);
- err("Failed to read mode from device.");
+ dev_err(&dev->intf->dev, "Failed to read mode from device.\n");
ret = -EIO;
goto out_free;
}
@@ -296,7 +298,7 @@ static int atp_geyser_init(struct usb_device *udev)
for (i = 0; i < 8; i++)
dprintk("appletouch[%d]: %d\n", i, data[i]);
- err("Failed to request geyser raw mode");
+ dev_err(&dev->intf->dev, "Failed to request geyser raw mode\n");
ret = -EIO;
goto out_free;
}
@@ -313,16 +315,16 @@ out_free:
static void atp_reinit(struct work_struct *work)
{
struct atp *dev = container_of(work, struct atp, work);
- struct usb_device *udev = dev->udev;
int retval;
dprintk("appletouch: putting appletouch to sleep (reinit)\n");
- atp_geyser_init(udev);
+ atp_geyser_init(dev);
retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
if (retval)
- err("atp_reinit: usb_submit_urb failed with error %d",
- retval);
+ dev_err(&dev->intf->dev,
+ "atp_reinit: usb_submit_urb failed with error %d\n",
+ retval);
}
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
@@ -400,6 +402,7 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers)
static int atp_status_check(struct urb *urb)
{
struct atp *dev = urb->context;
+ struct usb_interface *intf = dev->intf;
switch (urb->status) {
case 0:
@@ -407,8 +410,8 @@ static int atp_status_check(struct urb *urb)
break;
case -EOVERFLOW:
if (!dev->overflow_warned) {
- printk(KERN_WARNING "appletouch: OVERFLOW with data "
- "length %d, actual length is %d\n",
+ dev_warn(&intf->dev,
+ "appletouch: OVERFLOW with data length %d, actual length is %d\n",
dev->info->datalen, dev->urb->actual_length);
dev->overflow_warned = true;
}
@@ -416,13 +419,15 @@ static int atp_status_check(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* This urb is terminated, clean up */
- dbg("atp_complete: urb shutting down with status: %d",
- urb->status);
+ dev_dbg(&intf->dev,
+ "atp_complete: urb shutting down with status: %d\n",
+ urb->status);
return ATP_URB_STATUS_ERROR_FATAL;
default:
- dbg("atp_complete: nonzero urb status received: %d",
- urb->status);
+ dev_dbg(&intf->dev,
+ "atp_complete: nonzero urb status received: %d\n",
+ urb->status);
return ATP_URB_STATUS_ERROR;
}
@@ -445,7 +450,8 @@ static void atp_detect_size(struct atp *dev)
for (i = dev->info->xsensors; i < ATP_XSENSORS; i++) {
if (dev->xy_cur[i]) {
- printk(KERN_INFO "appletouch: 17\" model detected.\n");
+ dev_info(&dev->intf->dev,
+ "appletouch: 17\" model detected.\n");
input_set_abs_params(dev->input, ABS_X, 0,
(dev->info->xsensors_17 - 1) *
@@ -588,8 +594,9 @@ static void atp_complete_geyser_1_2(struct urb *urb)
exit:
retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
if (retval)
- err("atp_complete: usb_submit_urb failed with result %d",
- retval);
+ dev_err(&dev->intf->dev,
+ "atp_complete: usb_submit_urb failed with result %d\n",
+ retval);
}
/* Interrupt function for older touchpads: GEYSER3/GEYSER4 */
@@ -722,8 +729,9 @@ static void atp_complete_geyser_3_4(struct urb *urb)
exit:
retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
if (retval)
- err("atp_complete: usb_submit_urb failed with result %d",
- retval);
+ dev_err(&dev->intf->dev,
+ "atp_complete: usb_submit_urb failed with result %d\n",
+ retval);
}
static int atp_open(struct input_dev *input)
@@ -748,14 +756,12 @@ static void atp_close(struct input_dev *input)
static int atp_handle_geyser(struct atp *dev)
{
- struct usb_device *udev = dev->udev;
-
if (dev->info != &fountain_info) {
/* switch to raw sensor mode */
- if (atp_geyser_init(udev))
+ if (atp_geyser_init(dev))
return -EIO;
- printk(KERN_INFO "appletouch: Geyser mode initialized.\n");
+ dev_info(&dev->intf->dev, "Geyser mode initialized.\n");
}
return 0;
@@ -785,7 +791,7 @@ static int atp_probe(struct usb_interface *iface,
}
}
if (!int_in_endpointAddr) {
- err("Could not find int-in endpoint");
+ dev_err(&iface->dev, "Could not find int-in endpoint\n");
return -EIO;
}
@@ -793,11 +799,12 @@ static int atp_probe(struct usb_interface *iface,
dev = kzalloc(sizeof(struct atp), GFP_KERNEL);
input_dev = input_allocate_device();
if (!dev || !input_dev) {
- err("Out of memory");
+ dev_err(&iface->dev, "Out of memory\n");
goto err_free_devs;
}
dev->udev = udev;
+ dev->intf = iface;
dev->input = input_dev;
dev->info = info;
dev->overflow_warned = false;
@@ -886,7 +893,7 @@ static void atp_disconnect(struct usb_interface *iface)
usb_free_urb(dev->urb);
kfree(dev);
}
- printk(KERN_INFO "input: appletouch disconnected\n");
+ dev_info(&iface->dev, "input: appletouch disconnected\n");
}
static int atp_recover(struct atp *dev)
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index f9e2758b9f46..2cf681d98c0d 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -584,7 +584,7 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
int retval = 0, size;
if (!data) {
- err("bcm5974: out of memory");
+ dev_err(&dev->intf->dev, "out of memory\n");
retval = -ENOMEM;
goto out;
}
@@ -597,7 +597,7 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
if (size != 8) {
- err("bcm5974: could not read from device");
+ dev_err(&dev->intf->dev, "could not read from device\n");
retval = -EIO;
goto out;
}
@@ -615,7 +615,7 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
if (size != 8) {
- err("bcm5974: could not write to device");
+ dev_err(&dev->intf->dev, "could not write to device\n");
retval = -EIO;
goto out;
}
@@ -631,6 +631,7 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
static void bcm5974_irq_button(struct urb *urb)
{
struct bcm5974 *dev = urb->context;
+ struct usb_interface *intf = dev->intf;
int error;
switch (urb->status) {
@@ -640,10 +641,11 @@ static void bcm5974_irq_button(struct urb *urb)
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
- dbg("bcm5974: button urb shutting down: %d", urb->status);
+ dev_dbg(&intf->dev, "button urb shutting down: %d\n",
+ urb->status);
return;
default:
- dbg("bcm5974: button urb status: %d", urb->status);
+ dev_dbg(&intf->dev, "button urb status: %d\n", urb->status);
goto exit;
}
@@ -654,12 +656,13 @@ static void bcm5974_irq_button(struct urb *urb)
exit:
error = usb_submit_urb(dev->bt_urb, GFP_ATOMIC);
if (error)
- err("bcm5974: button urb failed: %d", error);
+ dev_err(&intf->dev, "button urb failed: %d\n", error);
}
static void bcm5974_irq_trackpad(struct urb *urb)
{
struct bcm5974 *dev = urb->context;
+ struct usb_interface *intf = dev->intf;
int error;
switch (urb->status) {
@@ -669,10 +672,11 @@ static void bcm5974_irq_trackpad(struct urb *urb)
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
- dbg("bcm5974: trackpad urb shutting down: %d", urb->status);
+ dev_dbg(&intf->dev, "trackpad urb shutting down: %d\n",
+ urb->status);
return;
default:
- dbg("bcm5974: trackpad urb status: %d", urb->status);
+ dev_dbg(&intf->dev, "trackpad urb status: %d\n", urb->status);
goto exit;
}
@@ -687,7 +691,7 @@ static void bcm5974_irq_trackpad(struct urb *urb)
exit:
error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC);
if (error)
- err("bcm5974: trackpad urb failed: %d", error);
+ dev_err(&intf->dev, "trackpad urb failed: %d\n", error);
}
/*
@@ -833,7 +837,7 @@ static int bcm5974_probe(struct usb_interface *iface,
dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL);
input_dev = input_allocate_device();
if (!dev || !input_dev) {
- err("bcm5974: out of memory");
+ dev_err(&iface->dev, "out of memory\n");
goto err_free_devs;
}
diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c
index f8b0b1df9138..e062ec899ca1 100644
--- a/drivers/input/tablet/acecad.c
+++ b/drivers/input/tablet/acecad.c
@@ -51,6 +51,7 @@ struct usb_acecad {
char name[128];
char phys[64];
struct usb_device *usbdev;
+ struct usb_interface *intf;
struct input_dev *input;
struct urb *irq;
@@ -63,6 +64,7 @@ static void usb_acecad_irq(struct urb *urb)
struct usb_acecad *acecad = urb->context;
unsigned char *data = acecad->data;
struct input_dev *dev = acecad->input;
+ struct usb_interface *intf = acecad->intf;
int prox, status;
switch (urb->status) {
@@ -73,10 +75,12 @@ static void usb_acecad_irq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__, urb->status);
+ dev_dbg(&intf->dev, "%s - urb shutting down with status: %d\n",
+ __func__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__, urb->status);
+ dev_dbg(&intf->dev, "%s - nonzero urb status received: %d\n",
+ __func__, urb->status);
goto resubmit;
}
@@ -105,8 +109,10 @@ static void usb_acecad_irq(struct urb *urb)
resubmit:
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status)
- err("can't resubmit intr, %s-%s/input0, status %d",
- acecad->usbdev->bus->bus_name, acecad->usbdev->devpath, status);
+ dev_err(&intf->dev,
+ "can't resubmit intr, %s-%s/input0, status %d\n",
+ acecad->usbdev->bus->bus_name,
+ acecad->usbdev->devpath, status);
}
static int usb_acecad_open(struct input_dev *dev)
@@ -168,6 +174,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
}
acecad->usbdev = dev;
+ acecad->intf = intf;
acecad->input = input_dev;
if (dev->manufacturer)
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index 205d16aab441..755a39e4c9e9 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -309,6 +309,7 @@ struct aiptek_settings {
struct aiptek {
struct input_dev *inputdev; /* input device struct */
struct usb_device *usbdev; /* usb device struct */
+ struct usb_interface *intf; /* usb interface struct */
struct urb *urb; /* urb for incoming reports */
dma_addr_t data_dma; /* our dma stuffage */
struct aiptek_features features; /* tablet's array of features */
@@ -435,6 +436,7 @@ static void aiptek_irq(struct urb *urb)
struct aiptek *aiptek = urb->context;
unsigned char *data = aiptek->data;
struct input_dev *inputdev = aiptek->inputdev;
+ struct usb_interface *intf = aiptek->intf;
int jitterable = 0;
int retval, macro, x, y, z, left, right, middle, p, dv, tip, bs, pck;
@@ -447,13 +449,13 @@ static void aiptek_irq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* This urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, urb->status);
+ dev_dbg(&intf->dev, "%s - urb shutting down with status: %d\n",
+ __func__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, urb->status);
+ dev_dbg(&intf->dev, "%s - nonzero urb status received: %d\n",
+ __func__, urb->status);
goto exit;
}
@@ -785,7 +787,7 @@ static void aiptek_irq(struct urb *urb)
1 | AIPTEK_REPORT_TOOL_UNKNOWN);
input_sync(inputdev);
} else {
- dbg("Unknown report %d", data[0]);
+ dev_dbg(&intf->dev, "Unknown report %d\n", data[0]);
}
/* Jitter may occur when the user presses a button on the stlyus
@@ -811,8 +813,9 @@ static void aiptek_irq(struct urb *urb)
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval != 0) {
- err("%s - usb_submit_urb failed with result %d",
- __func__, retval);
+ dev_err(&intf->dev,
+ "%s - usb_submit_urb failed with result %d\n",
+ __func__, retval);
}
}
@@ -912,8 +915,9 @@ aiptek_command(struct aiptek *aiptek, unsigned char command, unsigned char data)
if ((ret =
aiptek_set_report(aiptek, 3, 2, buf, sizeof_buf)) != sizeof_buf) {
- dbg("aiptek_program: failed, tried to send: 0x%02x 0x%02x",
- command, data);
+ dev_dbg(&aiptek->intf->dev,
+ "aiptek_program: failed, tried to send: 0x%02x 0x%02x\n",
+ command, data);
}
kfree(buf);
return ret < 0 ? ret : 0;
@@ -947,8 +951,9 @@ aiptek_query(struct aiptek *aiptek, unsigned char command, unsigned char data)
if ((ret =
aiptek_get_report(aiptek, 3, 2, buf, sizeof_buf)) != sizeof_buf) {
- dbg("aiptek_query failed: returned 0x%02x 0x%02x 0x%02x",
- buf[0], buf[1], buf[2]);
+ dev_dbg(&aiptek->intf->dev,
+ "aiptek_query failed: returned 0x%02x 0x%02x 0x%02x\n",
+ buf[0], buf[1], buf[2]);
ret = -EIO;
} else {
ret = get_unaligned_le16(buf + 1);
@@ -1726,6 +1731,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
aiptek->inputdev = inputdev;
aiptek->usbdev = usbdev;
+ aiptek->intf = intf;
aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber;
aiptek->inDelay = 0;
aiptek->endDelay = 0;
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c
index 89a297801dce..29e01ab6859f 100644
--- a/drivers/input/tablet/gtco.c
+++ b/drivers/input/tablet/gtco.c
@@ -2,8 +2,6 @@
GTCO digitizer USB driver
-Use the err() and dbg() macros from usb.h for system logging
-
TO CHECK: Is pressure done right on report 5?
Copyright (C) 2006 GTCO CalComp
@@ -108,6 +106,7 @@ struct gtco {
struct input_dev *inputdevice; /* input device struct pointer */
struct usb_device *usbdev; /* the usb device for this device */
+ struct usb_interface *intf; /* the usb interface for this device */
struct urb *urbinfo; /* urb for incoming reports */
dma_addr_t buf_dma; /* dma addr of the data buffer*/
unsigned char * buffer; /* databuffer for reports */
@@ -202,6 +201,7 @@ struct hid_descriptor
static void parse_hid_report_descriptor(struct gtco *device, char * report,
int length)
{
+ struct device *ddev = &device->intf->dev;
int x, i = 0;
/* Tag primitive vars */
@@ -228,7 +228,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
char indentstr[10] = "";
- dbg("======>>>>>>PARSE<<<<<<======");
+ dev_dbg(ddev, "======>>>>>>PARSE<<<<<<======\n");
/* Walk this report and pull out the info we need */
while (i < length) {
@@ -277,11 +277,11 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
else if (data == 3)
strcpy(globtype, "Var|Const");
- dbg("::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits",
- globalval[TAG_GLOB_REPORT_ID], inputnum,
- globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX],
- globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN],
- globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]);
+ dev_dbg(ddev, "::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits\n",
+ globalval[TAG_GLOB_REPORT_ID], inputnum,
+ globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX],
+ globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN],
+ globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]);
/*
@@ -292,7 +292,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
*/
switch (inputnum) {
case 0: /* X coord */
- dbg("GER: X Usage: 0x%x", usage);
+ dev_dbg(ddev, "GER: X Usage: 0x%x\n", usage);
if (device->max_X == 0) {
device->max_X = globalval[TAG_GLOB_LOG_MAX];
device->min_X = globalval[TAG_GLOB_LOG_MIN];
@@ -300,7 +300,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
break;
case 1: /* Y coord */
- dbg("GER: Y Usage: 0x%x", usage);
+ dev_dbg(ddev, "GER: Y Usage: 0x%x\n", usage);
if (device->max_Y == 0) {
device->max_Y = globalval[TAG_GLOB_LOG_MAX];
device->min_Y = globalval[TAG_GLOB_LOG_MIN];
@@ -350,10 +350,10 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
maintype = 'S';
if (data == 0) {
- dbg("======>>>>>> Physical");
+ dev_dbg(ddev, "======>>>>>> Physical\n");
strcpy(globtype, "Physical");
} else
- dbg("======>>>>>>");
+ dev_dbg(ddev, "======>>>>>>\n");
/* Indent the debug output */
indent++;
@@ -368,7 +368,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
break;
case TAG_MAIN_COL_END:
- dbg("<<<<<<======");
+ dev_dbg(ddev, "<<<<<<======\n");
maintype = 'E';
indent--;
for (x = 0; x < indent; x++)
@@ -384,18 +384,18 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
switch (size) {
case 1:
- dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
- indentstr, tag, maintype, size, globtype, data);
+ dev_dbg(ddev, "%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x\n",
+ indentstr, tag, maintype, size, globtype, data);
break;
case 2:
- dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
- indentstr, tag, maintype, size, globtype, data16);
+ dev_dbg(ddev, "%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x\n",
+ indentstr, tag, maintype, size, globtype, data16);
break;
case 4:
- dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
- indentstr, tag, maintype, size, globtype, data32);
+ dev_dbg(ddev, "%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x\n",
+ indentstr, tag, maintype, size, globtype, data32);
break;
}
break;
@@ -465,26 +465,26 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
if (tag < TAG_GLOB_MAX) {
switch (size) {
case 1:
- dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
- indentstr, globtype, tag, size, data);
+ dev_dbg(ddev, "%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x\n",
+ indentstr, globtype, tag, size, data);
globalval[tag] = data;
break;
case 2:
- dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
- indentstr, globtype, tag, size, data16);
+ dev_dbg(ddev, "%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x\n",
+ indentstr, globtype, tag, size, data16);
globalval[tag] = data16;
break;
case 4:
- dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
- indentstr, globtype, tag, size, data32);
+ dev_dbg(ddev, "%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x\n",
+ indentstr, globtype, tag, size, data32);
globalval[tag] = data32;
break;
}
} else {
- dbg("%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d ",
- indentstr, tag, size);
+ dev_dbg(ddev, "%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d\n",
+ indentstr, tag, size);
}
break;
@@ -511,18 +511,18 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
switch (size) {
case 1:
- dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
- indentstr, tag, globtype, size, data);
+ dev_dbg(ddev, "%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x\n",
+ indentstr, tag, globtype, size, data);
break;
case 2:
- dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
- indentstr, tag, globtype, size, data16);
+ dev_dbg(ddev, "%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x\n",
+ indentstr, tag, globtype, size, data16);
break;
case 4:
- dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
- indentstr, tag, globtype, size, data32);
+ dev_dbg(ddev, "%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x\n",
+ indentstr, tag, globtype, size, data32);
break;
}
@@ -714,8 +714,9 @@ static void gtco_urb_callback(struct urb *urbinfo)
* the rest as 0
*/
val = device->buffer[5] & MASK_BUTTON;
- dbg("======>>>>>>REPORT 1: val 0x%X(%d)",
- val, val);
+ dev_dbg(&device->intf->dev,
+ "======>>>>>>REPORT 1: val 0x%X(%d)\n",
+ val, val);
/*
* We don't apply any meaning to the button
@@ -808,7 +809,8 @@ static void gtco_urb_callback(struct urb *urbinfo)
resubmit:
rc = usb_submit_urb(urbinfo, GFP_ATOMIC);
if (rc != 0)
- err("usb_submit_urb failed rc=0x%x", rc);
+ dev_err(&device->intf->dev,
+ "usb_submit_urb failed rc=0x%x\n", rc);
}
/*
@@ -838,7 +840,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
gtco = kzalloc(sizeof(struct gtco), GFP_KERNEL);
input_dev = input_allocate_device();
if (!gtco || !input_dev) {
- err("No more memory");
+ dev_err(&usbinterface->dev, "No more memory\n");
error = -ENOMEM;
goto err_free_devs;
}
@@ -848,12 +850,13 @@ static int gtco_probe(struct usb_interface *usbinterface,
/* Save interface information */
gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface));
+ gtco->intf = usbinterface;
/* Allocate some data for incoming reports */
gtco->buffer = usb_alloc_coherent(gtco->usbdev, REPORT_MAX_SIZE,
GFP_KERNEL, &gtco->buf_dma);
if (!gtco->buffer) {
- err("No more memory for us buffers");
+ dev_err(&usbinterface->dev, "No more memory for us buffers\n");
error = -ENOMEM;
goto err_free_devs;
}
@@ -861,7 +864,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
/* Allocate URB for reports */
gtco->urbinfo = usb_alloc_urb(0, GFP_KERNEL);
if (!gtco->urbinfo) {
- err("Failed to allocate URB");
+ dev_err(&usbinterface->dev, "Failed to allocate URB\n");
error = -ENOMEM;
goto err_free_buf;
}
@@ -873,14 +876,14 @@ static int gtco_probe(struct usb_interface *usbinterface,
endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
/* Some debug */
- dbg("gtco # interfaces: %d", usbinterface->num_altsetting);
- dbg("num endpoints: %d", usbinterface->cur_altsetting->desc.bNumEndpoints);
- dbg("interface class: %d", usbinterface->cur_altsetting->desc.bInterfaceClass);
- dbg("endpoint: attribute:0x%x type:0x%x", endpoint->bmAttributes, endpoint->bDescriptorType);
+ dev_dbg(&usbinterface->dev, "gtco # interfaces: %d\n", usbinterface->num_altsetting);
+ dev_dbg(&usbinterface->dev, "num endpoints: %d\n", usbinterface->cur_altsetting->desc.bNumEndpoints);
+ dev_dbg(&usbinterface->dev, "interface class: %d\n", usbinterface->cur_altsetting->desc.bInterfaceClass);
+ dev_dbg(&usbinterface->dev, "endpoint: attribute:0x%x type:0x%x\n", endpoint->bmAttributes, endpoint->bDescriptorType);
if (usb_endpoint_xfer_int(endpoint))
- dbg("endpoint: we have interrupt endpoint\n");
+ dev_dbg(&usbinterface->dev, "endpoint: we have interrupt endpoint\n");
- dbg("endpoint extra len:%d ", usbinterface->altsetting[0].extralen);
+ dev_dbg(&usbinterface->dev, "endpoint extra len:%d\n", usbinterface->altsetting[0].extralen);
/*
* Find the HID descriptor so we can find out the size of the
@@ -888,17 +891,19 @@ static int gtco_probe(struct usb_interface *usbinterface,
*/
if (usb_get_extra_descriptor(usbinterface->cur_altsetting,
HID_DEVICE_TYPE, &hid_desc) != 0){
- err("Can't retrieve exta USB descriptor to get hid report descriptor length");
+ dev_err(&usbinterface->dev,
+ "Can't retrieve exta USB descriptor to get hid report descriptor length\n");
error = -EIO;
goto err_free_urb;
}
- dbg("Extra descriptor success: type:%d len:%d",
- hid_desc->bDescriptorType, hid_desc->wDescriptorLength);
+ dev_dbg(&usbinterface->dev,
+ "Extra descriptor success: type:%d len:%d\n",
+ hid_desc->bDescriptorType, hid_desc->wDescriptorLength);
report = kzalloc(le16_to_cpu(hid_desc->wDescriptorLength), GFP_KERNEL);
if (!report) {
- err("No more memory for report");
+ dev_err(&usbinterface->dev, "No more memory for report\n");
error = -ENOMEM;
goto err_free_urb;
}
@@ -915,7 +920,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
le16_to_cpu(hid_desc->wDescriptorLength),
5000); /* 5 secs */
- dbg("usb_control_msg result: %d", result);
+ dev_dbg(&usbinterface->dev, "usb_control_msg result: %d\n", result);
if (result == le16_to_cpu(hid_desc->wDescriptorLength)) {
parse_hid_report_descriptor(gtco, report, result);
break;
@@ -926,8 +931,9 @@ static int gtco_probe(struct usb_interface *usbinterface,
/* If we didn't get the report, fail */
if (result != le16_to_cpu(hid_desc->wDescriptorLength)) {
- err("Failed to get HID Report Descriptor of size: %d",
- hid_desc->wDescriptorLength);
+ dev_err(&usbinterface->dev,
+ "Failed to get HID Report Descriptor of size: %d\n",
+ hid_desc->wDescriptorLength);
error = -EIO;
goto err_free_urb;
}
diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c
index 85a5b40333ac..3fba74b9b602 100644
--- a/drivers/input/tablet/kbtab.c
+++ b/drivers/input/tablet/kbtab.c
@@ -33,6 +33,7 @@ struct kbtab {
dma_addr_t data_dma;
struct input_dev *dev;
struct usb_device *usbdev;
+ struct usb_interface *intf;
struct urb *irq;
char phys[32];
};
@@ -53,10 +54,14 @@ static void kbtab_irq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__, urb->status);
+ dev_dbg(&kbtab->intf->dev,
+ "%s - urb shutting down with status: %d\n",
+ __func__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__, urb->status);
+ dev_dbg(&kbtab->intf->dev,
+ "%s - nonzero urb status received: %d\n",
+ __func__, urb->status);
goto exit;
}
@@ -80,8 +85,9 @@ static void kbtab_irq(struct urb *urb)
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err("%s - usb_submit_urb failed with result %d",
- __func__, retval);
+ dev_err(&kbtab->intf->dev,
+ "%s - usb_submit_urb failed with result %d\n",
+ __func__, retval);
}
static struct usb_device_id kbtab_ids[] = {
@@ -131,6 +137,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
goto fail2;
kbtab->usbdev = dev;
+ kbtab->intf = intf;
kbtab->dev = input_dev;
usb_make_path(dev, kbtab->phys, sizeof(kbtab->phys));
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 0d269212931e..79a0509882d4 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -99,6 +99,7 @@ static int wacom_set_report(struct usb_interface *intf, u8 type, u8 id,
static void wacom_sys_irq(struct urb *urb)
{
struct wacom *wacom = urb->context;
+ struct device *dev = &wacom->intf->dev;
int retval;
switch (urb->status) {
@@ -109,10 +110,12 @@ static void wacom_sys_irq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__, urb->status);
+ dev_dbg(dev, "%s - urb shutting down with status: %d\n",
+ __func__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__, urb->status);
+ dev_dbg(dev, "%s - nonzero urb status received: %d\n",
+ __func__, urb->status);
goto exit;
}
@@ -122,8 +125,8 @@ static void wacom_sys_irq(struct urb *urb)
usb_mark_last_busy(wacom->usbdev);
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err ("%s - usb_submit_urb failed with result %d",
- __func__, retval);
+ dev_err(dev, "%s - usb_submit_urb failed with result %d\n",
+ __func__, retval);
}
static int wacom_open(struct input_dev *dev)
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index cecd35c8f0b3..b327790e9a0c 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -76,7 +76,8 @@ static int wacom_pl_irq(struct wacom_wac *wacom)
int prox, pressure;
if (data[0] != WACOM_REPORT_PENABLED) {
- dbg("wacom_pl_irq: received unknown report #%d", data[0]);
+ dev_dbg(&input->dev,
+ "wacom_pl_irq: received unknown report #%d\n", data[0]);
return 0;
}
@@ -175,7 +176,7 @@ static int wacom_dtu_irq(struct wacom_wac *wacom)
struct input_dev *input = wacom->input;
int prox = data[1] & 0x20, pressure;
- dbg("wacom_dtu_irq: received report #%d", data[0]);
+ dev_dbg(&input->dev, "wacom_dtu_irq: received report #%d\n", data[0]);
if (prox) {
/* Going into proximity select tool */
@@ -211,7 +212,9 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
int retval = 0;
if (data[0] != WACOM_REPORT_PENABLED) {
- dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
+ dev_dbg(&input->dev,
+ "wacom_graphire_irq: received unknown report #%d\n",
+ data[0]);
goto exit;
}
@@ -484,7 +487,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_INTUOSREAD
&& data[0] != WACOM_REPORT_INTUOSWRITE && data[0] != WACOM_REPORT_INTUOSPAD) {
- dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
+ dev_dbg(&input->dev,
+ "wacom_intuos_irq: received unknown report #%d\n",
+ data[0]);
return 0;
}
@@ -830,7 +835,8 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
{
char *data = wacom->data;
- dbg("wacom_tpc_irq: received report #%d", data[0]);
+ dev_dbg(&wacom->input->dev, "wacom_tpc_irq: received report #%d\n",
+ data[0]);
switch (len) {
case WACOM_PKGLEN_TPC1FG:
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 2a2141915aa0..75838d7710ce 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -489,10 +489,10 @@ config TOUCHSCREEN_TI_TSCADC
config TOUCHSCREEN_ATMEL_TSADCC
tristate "Atmel Touchscreen Interface"
- depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
+ depends on ARCH_AT91
help
Say Y here if you have a 4-wire touchscreen connected to the
- ADC Controller on your Atmel SoC (such as the AT91SAM9RL).
+ ADC Controller on your Atmel SoC.
If unsure, say N.
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index 22cd96f58c99..e32709e0dd65 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -269,8 +269,9 @@ static int e2i_init(struct usbtouch_usb *usbtouch)
0x01, 0x02, 0x0000, 0x0081,
NULL, 0, USB_CTRL_SET_TIMEOUT);
- dbg("%s - usb_control_msg - E2I_RESET - bytes|err: %d",
- __func__, ret);
+ dev_dbg(&usbtouch->interface->dev,
+ "%s - usb_control_msg - E2I_RESET - bytes|err: %d\n",
+ __func__, ret);
return ret;
}
@@ -425,8 +426,9 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
MTOUCHUSB_RESET,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
- dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d",
- __func__, ret);
+ dev_dbg(&usbtouch->interface->dev,
+ "%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d\n",
+ __func__, ret);
if (ret < 0)
return ret;
msleep(150);
@@ -436,8 +438,9 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
MTOUCHUSB_ASYNC_REPORT,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
- dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
- __func__, ret);
+ dev_dbg(&usbtouch->interface->dev,
+ "%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d\n",
+ __func__, ret);
if (ret >= 0)
break;
if (ret != -EPIPE)
@@ -737,27 +740,29 @@ static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
#ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC
static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
+ struct usb_interface *intf = dev->interface;
+
switch (pkt[0]) {
case 0x3A: /* command response */
- dbg("%s: Command response %d", __func__, pkt[1]);
+ dev_dbg(&intf->dev, "%s: Command response %d\n", __func__, pkt[1]);
break;
case 0xC0: /* down */
dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7);
dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7);
dev->touch = 1;
- dbg("%s: down %d,%d", __func__, dev->x, dev->y);
+ dev_dbg(&intf->dev, "%s: down %d,%d\n", __func__, dev->x, dev->y);
return 1;
case 0x80: /* up */
dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7);
dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7);
dev->touch = 0;
- dbg("%s: up %d,%d", __func__, dev->x, dev->y);
+ dev_dbg(&intf->dev, "%s: up %d,%d\n", __func__, dev->x, dev->y);
return 1;
default:
- dbg("%s: Unknown return %d", __func__, pkt[0]);
+ dev_dbg(&intf->dev, "%s: Unknown return %d\n", __func__, pkt[0]);
break;
}
@@ -812,7 +817,8 @@ static int nexio_alloc(struct usbtouch_usb *usbtouch)
priv->ack = usb_alloc_urb(0, GFP_KERNEL);
if (!priv->ack) {
- dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__);
+ dev_dbg(&usbtouch->interface->dev,
+ "%s - usb_alloc_urb failed: usbtouch->ack\n", __func__);
goto err_ack_buf;
}
@@ -1349,6 +1355,7 @@ out_flush_buf:
static void usbtouch_irq(struct urb *urb)
{
struct usbtouch_usb *usbtouch = urb->context;
+ struct device *dev = &usbtouch->interface->dev;
int retval;
switch (urb->status) {
@@ -1357,20 +1364,21 @@ static void usbtouch_irq(struct urb *urb)
break;
case -ETIME:
/* this urb is timing out */
- dbg("%s - urb timed out - was the device unplugged?",
- __func__);
+ dev_dbg(dev,
+ "%s - urb timed out - was the device unplugged?\n",
+ __func__);
return;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
case -EPIPE:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, urb->status);
+ dev_dbg(dev, "%s - urb shutting down with status: %d\n",
+ __func__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, urb->status);
+ dev_dbg(dev, "%s - nonzero urb status received: %d\n",
+ __func__, urb->status);
goto exit;
}
@@ -1380,8 +1388,8 @@ exit:
usb_mark_last_busy(interface_to_usbdev(usbtouch->interface));
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err("%s - usb_submit_urb failed with result: %d",
- __func__, retval);
+ dev_err(dev, "%s - usb_submit_urb failed with result: %d\n",
+ __func__, retval);
}
static int usbtouch_open(struct input_dev *input)
@@ -1456,8 +1464,9 @@ static int usbtouch_reset_resume(struct usb_interface *intf)
if (usbtouch->type->init) {
err = usbtouch->type->init(usbtouch);
if (err) {
- dbg("%s - type->init() failed, err: %d",
- __func__, err);
+ dev_dbg(&intf->dev,
+ "%s - type->init() failed, err: %d\n",
+ __func__, err);
return err;
}
}
@@ -1532,7 +1541,8 @@ static int usbtouch_probe(struct usb_interface *intf,
usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!usbtouch->irq) {
- dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__);
+ dev_dbg(&intf->dev,
+ "%s - usb_alloc_urb failed: usbtouch->irq\n", __func__);
goto out_free_buffers;
}
@@ -1594,7 +1604,9 @@ static int usbtouch_probe(struct usb_interface *intf,
if (type->alloc) {
err = type->alloc(usbtouch);
if (err) {
- dbg("%s - type->alloc() failed, err: %d", __func__, err);
+ dev_dbg(&intf->dev,
+ "%s - type->alloc() failed, err: %d\n",
+ __func__, err);
goto out_free_urb;
}
}
@@ -1603,14 +1615,18 @@ static int usbtouch_probe(struct usb_interface *intf,
if (type->init) {
err = type->init(usbtouch);
if (err) {
- dbg("%s - type->init() failed, err: %d", __func__, err);
+ dev_dbg(&intf->dev,
+ "%s - type->init() failed, err: %d\n",
+ __func__, err);
goto out_do_exit;
}
}
err = input_register_device(usbtouch->input);
if (err) {
- dbg("%s - input_register_device failed, err: %d", __func__, err);
+ dev_dbg(&intf->dev,
+ "%s - input_register_device failed, err: %d\n",
+ __func__, err);
goto out_do_exit;
}
@@ -1622,8 +1638,9 @@ static int usbtouch_probe(struct usb_interface *intf,
err = usb_submit_urb(usbtouch->irq, GFP_KERNEL);
if (err) {
usb_autopm_put_interface(intf);
- err("%s - usb_submit_urb failed with result: %d",
- __func__, err);
+ dev_err(&intf->dev,
+ "%s - usb_submit_urb failed with result: %d\n",
+ __func__, err);
goto out_unregister_input;
}
}
@@ -1650,12 +1667,12 @@ static void usbtouch_disconnect(struct usb_interface *intf)
{
struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
- dbg("%s - called", __func__);
-
if (!usbtouch)
return;
- dbg("%s - usbtouch is initialized, cleaning up", __func__);
+ dev_dbg(&intf->dev,
+ "%s - usbtouch is initialized, cleaning up\n", __func__);
+
usb_set_intfdata(intf, NULL);
/* this will stop IO via close */
input_unregister_device(usbtouch->input);
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 3bd9fff5c589..c69843742bb0 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -43,7 +43,7 @@ config AMD_IOMMU
With this option you can enable support for AMD IOMMU hardware in
your system. An IOMMU is a hardware component which provides
remapping of DMA memory accesses from devices. With an AMD IOMMU you
- can isolate the the DMA memory of different devices and protect the
+ can isolate the DMA memory of different devices and protect the
system from misbehaving device drivers or hardware.
You can find out if your system has an AMD IOMMU if you look into
@@ -67,7 +67,7 @@ config AMD_IOMMU_V2
---help---
This option enables support for the AMD IOMMUv2 features of the IOMMU
hardware. Select this option if you want to use devices that support
- the the PCI PRI and PASID interface.
+ the PCI PRI and PASID interface.
# Intel IOMMU support
config DMAR_TABLE
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 7ad7a3bc1242..3e5e82ae9f0d 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
obj-$(CONFIG_DMAR_TABLE) += dmar.o
obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o
-obj-$(CONFIG_IRQ_REMAP) += intr_remapping.o
+obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 35c1e17fce1d..3a74e4410fc0 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -36,6 +36,7 @@
#include <linux/tboot.h>
#include <linux/dmi.h>
#include <linux/slab.h>
+#include <asm/irq_remapping.h>
#include <asm/iommu_table.h>
#define PREFIX "DMAR: "
@@ -555,7 +556,7 @@ int __init detect_intel_iommu(void)
dmar = (struct acpi_table_dmar *) dmar_tbl;
- if (ret && intr_remapping_enabled && cpu_has_x2apic &&
+ if (ret && irq_remapping_enabled && cpu_has_x2apic &&
dmar->flags & 0x1)
printk(KERN_INFO
"Queued invalidation will be enabled to support x2apic and Intr-remapping.\n");
@@ -1041,7 +1042,7 @@ static const char *dma_remap_fault_reasons[] =
"non-zero reserved fields in PTE",
};
-static const char *intr_remap_fault_reasons[] =
+static const char *irq_remap_fault_reasons[] =
{
"Detected reserved fields in the decoded interrupt-remapped request",
"Interrupt index exceeded the interrupt-remapping table size",
@@ -1056,10 +1057,10 @@ static const char *intr_remap_fault_reasons[] =
const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
{
- if (fault_reason >= 0x20 && (fault_reason <= 0x20 +
- ARRAY_SIZE(intr_remap_fault_reasons))) {
+ if (fault_reason >= 0x20 && (fault_reason - 0x20 <
+ ARRAY_SIZE(irq_remap_fault_reasons))) {
*fault_type = INTR_REMAP;
- return intr_remap_fault_reasons[fault_reason - 0x20];
+ return irq_remap_fault_reasons[fault_reason - 0x20];
} else if (fault_reason < ARRAY_SIZE(dma_remap_fault_reasons)) {
*fault_type = DMA_REMAP;
return dma_remap_fault_reasons[fault_reason];
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index f93d5ac8f81c..bf2fbaad5e22 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -42,6 +42,7 @@
#include <linux/dmi.h>
#include <linux/pci-ats.h>
#include <linux/memblock.h>
+#include <asm/irq_remapping.h>
#include <asm/cacheflush.h>
#include <asm/iommu.h>
@@ -4082,7 +4083,7 @@ static int intel_iommu_domain_has_cap(struct iommu_domain *domain,
if (cap == IOMMU_CAP_CACHE_COHERENCY)
return dmar_domain->iommu_snooping;
if (cap == IOMMU_CAP_INTR_REMAP)
- return intr_remapping_enabled;
+ return irq_remapping_enabled;
return 0;
}
diff --git a/drivers/iommu/intr_remapping.c b/drivers/iommu/intel_irq_remapping.c
index 6777ca049471..6d347064b8b0 100644
--- a/drivers/iommu/intr_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -10,49 +10,33 @@
#include <asm/smp.h>
#include <asm/cpu.h>
#include <linux/intel-iommu.h>
-#include "intr_remapping.h"
#include <acpi/acpi.h>
+#include <asm/irq_remapping.h>
#include <asm/pci-direct.h>
+#include <asm/msidef.h>
-static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
-static struct hpet_scope ir_hpet[MAX_HPET_TBS];
-static int ir_ioapic_num, ir_hpet_num;
-int intr_remapping_enabled;
-
-static int disable_intremap;
-static int disable_sourceid_checking;
-static int no_x2apic_optout;
+#include "irq_remapping.h"
-static __init int setup_nointremap(char *str)
-{
- disable_intremap = 1;
- return 0;
-}
-early_param("nointremap", setup_nointremap);
+struct ioapic_scope {
+ struct intel_iommu *iommu;
+ unsigned int id;
+ unsigned int bus; /* PCI bus number */
+ unsigned int devfn; /* PCI devfn number */
+};
-static __init int setup_intremap(char *str)
-{
- if (!str)
- return -EINVAL;
+struct hpet_scope {
+ struct intel_iommu *iommu;
+ u8 id;
+ unsigned int bus;
+ unsigned int devfn;
+};
- while (*str) {
- if (!strncmp(str, "on", 2))
- disable_intremap = 0;
- else if (!strncmp(str, "off", 3))
- disable_intremap = 1;
- else if (!strncmp(str, "nosid", 5))
- disable_sourceid_checking = 1;
- else if (!strncmp(str, "no_x2apic_optout", 16))
- no_x2apic_optout = 1;
-
- str += strcspn(str, ",");
- while (*str == ',')
- str++;
- }
+#define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
+#define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
- return 0;
-}
-early_param("intremap", setup_intremap);
+static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
+static struct hpet_scope ir_hpet[MAX_HPET_TBS];
+static int ir_ioapic_num, ir_hpet_num;
static DEFINE_RAW_SPINLOCK(irq_2_ir_lock);
@@ -80,7 +64,7 @@ int get_irte(int irq, struct irte *entry)
return 0;
}
-int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
+static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
{
struct ir_table *table = iommu->ir_table;
struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
@@ -152,7 +136,7 @@ static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
return qi_submit_sync(&desc, iommu);
}
-int map_irq_to_irte_handle(int irq, u16 *sub_handle)
+static int map_irq_to_irte_handle(int irq, u16 *sub_handle)
{
struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
unsigned long flags;
@@ -168,7 +152,7 @@ int map_irq_to_irte_handle(int irq, u16 *sub_handle)
return index;
}
-int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
+static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
{
struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
unsigned long flags;
@@ -188,7 +172,7 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
return 0;
}
-int modify_irte(int irq, struct irte *irte_modified)
+static int modify_irte(int irq, struct irte *irte_modified)
{
struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
struct intel_iommu *iommu;
@@ -216,7 +200,7 @@ int modify_irte(int irq, struct irte *irte_modified)
return rc;
}
-struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
+static struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
{
int i;
@@ -226,7 +210,7 @@ struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
return NULL;
}
-struct intel_iommu *map_ioapic_to_ir(int apic)
+static struct intel_iommu *map_ioapic_to_ir(int apic)
{
int i;
@@ -236,7 +220,7 @@ struct intel_iommu *map_ioapic_to_ir(int apic)
return NULL;
}
-struct intel_iommu *map_dev_to_ir(struct pci_dev *dev)
+static struct intel_iommu *map_dev_to_ir(struct pci_dev *dev)
{
struct dmar_drhd_unit *drhd;
@@ -270,7 +254,7 @@ static int clear_entries(struct irq_2_iommu *irq_iommu)
return qi_flush_iec(iommu, index, irq_iommu->irte_mask);
}
-int free_irte(int irq)
+static int free_irte(int irq)
{
struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
unsigned long flags;
@@ -328,7 +312,7 @@ static void set_irte_sid(struct irte *irte, unsigned int svt,
irte->sid = sid;
}
-int set_ioapic_sid(struct irte *irte, int apic)
+static int set_ioapic_sid(struct irte *irte, int apic)
{
int i;
u16 sid = 0;
@@ -353,7 +337,7 @@ int set_ioapic_sid(struct irte *irte, int apic)
return 0;
}
-int set_hpet_sid(struct irte *irte, u8 id)
+static int set_hpet_sid(struct irte *irte, u8 id)
{
int i;
u16 sid = 0;
@@ -383,7 +367,7 @@ int set_hpet_sid(struct irte *irte, u8 id)
return 0;
}
-int set_msi_sid(struct irte *irte, struct pci_dev *dev)
+static int set_msi_sid(struct irte *irte, struct pci_dev *dev)
{
struct pci_dev *bridge;
@@ -410,7 +394,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev)
return 0;
}
-static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
+static void iommu_set_irq_remapping(struct intel_iommu *iommu, int mode)
{
u64 addr;
u32 sts;
@@ -450,7 +434,7 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
}
-static int setup_intr_remapping(struct intel_iommu *iommu, int mode)
+static int intel_setup_irq_remapping(struct intel_iommu *iommu, int mode)
{
struct ir_table *ir_table;
struct page *pages;
@@ -473,14 +457,14 @@ static int setup_intr_remapping(struct intel_iommu *iommu, int mode)
ir_table->base = page_address(pages);
- iommu_set_intr_remapping(iommu, mode);
+ iommu_set_irq_remapping(iommu, mode);
return 0;
}
/*
* Disable Interrupt Remapping.
*/
-static void iommu_disable_intr_remapping(struct intel_iommu *iommu)
+static void iommu_disable_irq_remapping(struct intel_iommu *iommu)
{
unsigned long flags;
u32 sts;
@@ -519,11 +503,11 @@ static int __init dmar_x2apic_optout(void)
return dmar->flags & DMAR_X2APIC_OPT_OUT;
}
-int __init intr_remapping_supported(void)
+static int __init intel_irq_remapping_supported(void)
{
struct dmar_drhd_unit *drhd;
- if (disable_intremap)
+ if (disable_irq_remap)
return 0;
if (!dmar_ir_support())
@@ -539,7 +523,7 @@ int __init intr_remapping_supported(void)
return 1;
}
-int __init enable_intr_remapping(void)
+static int __init intel_enable_irq_remapping(void)
{
struct dmar_drhd_unit *drhd;
int setup = 0;
@@ -577,7 +561,7 @@ int __init enable_intr_remapping(void)
* Disable intr remapping and queued invalidation, if already
* enabled prior to OS handover.
*/
- iommu_disable_intr_remapping(iommu);
+ iommu_disable_irq_remapping(iommu);
dmar_disable_qi(iommu);
}
@@ -623,7 +607,7 @@ int __init enable_intr_remapping(void)
if (!ecap_ir_support(iommu->ecap))
continue;
- if (setup_intr_remapping(iommu, eim))
+ if (intel_setup_irq_remapping(iommu, eim))
goto error;
setup = 1;
@@ -632,7 +616,7 @@ int __init enable_intr_remapping(void)
if (!setup)
goto error;
- intr_remapping_enabled = 1;
+ irq_remapping_enabled = 1;
pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic");
return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;
@@ -775,14 +759,14 @@ int __init parse_ioapics_under_ir(void)
int __init ir_dev_scope_init(void)
{
- if (!intr_remapping_enabled)
+ if (!irq_remapping_enabled)
return 0;
return dmar_dev_scope_init();
}
rootfs_initcall(ir_dev_scope_init);
-void disable_intr_remapping(void)
+static void disable_irq_remapping(void)
{
struct dmar_drhd_unit *drhd;
struct intel_iommu *iommu = NULL;
@@ -794,11 +778,11 @@ void disable_intr_remapping(void)
if (!ecap_ir_support(iommu->ecap))
continue;
- iommu_disable_intr_remapping(iommu);
+ iommu_disable_irq_remapping(iommu);
}
}
-int reenable_intr_remapping(int eim)
+static int reenable_irq_remapping(int eim)
{
struct dmar_drhd_unit *drhd;
int setup = 0;
@@ -816,7 +800,7 @@ int reenable_intr_remapping(int eim)
continue;
/* Set up interrupt remapping for iommu.*/
- iommu_set_intr_remapping(iommu, eim);
+ iommu_set_irq_remapping(iommu, eim);
setup = 1;
}
@@ -832,3 +816,254 @@ error:
return -1;
}
+static void prepare_irte(struct irte *irte, int vector,
+ unsigned int dest)
+{
+ memset(irte, 0, sizeof(*irte));
+
+ irte->present = 1;
+ irte->dst_mode = apic->irq_dest_mode;
+ /*
+ * Trigger mode in the IRTE will always be edge, and for IO-APIC, the
+ * actual level or edge trigger will be setup in the IO-APIC
+ * RTE. This will help simplify level triggered irq migration.
+ * For more details, see the comments (in io_apic.c) explainig IO-APIC
+ * irq migration in the presence of interrupt-remapping.
+ */
+ irte->trigger_mode = 0;
+ irte->dlvry_mode = apic->irq_delivery_mode;
+ irte->vector = vector;
+ irte->dest_id = IRTE_DEST(dest);
+ irte->redir_hint = 1;
+}
+
+static int intel_setup_ioapic_entry(int irq,
+ struct IO_APIC_route_entry *route_entry,
+ unsigned int destination, int vector,
+ struct io_apic_irq_attr *attr)
+{
+ int ioapic_id = mpc_ioapic_id(attr->ioapic);
+ struct intel_iommu *iommu = map_ioapic_to_ir(ioapic_id);
+ struct IR_IO_APIC_route_entry *entry;
+ struct irte irte;
+ int index;
+
+ if (!iommu) {
+ pr_warn("No mapping iommu for ioapic %d\n", ioapic_id);
+ return -ENODEV;
+ }
+
+ entry = (struct IR_IO_APIC_route_entry *)route_entry;
+
+ index = alloc_irte(iommu, irq, 1);
+ if (index < 0) {
+ pr_warn("Failed to allocate IRTE for ioapic %d\n", ioapic_id);
+ return -ENOMEM;
+ }
+
+ prepare_irte(&irte, vector, destination);
+
+ /* Set source-id of interrupt request */
+ set_ioapic_sid(&irte, ioapic_id);
+
+ modify_irte(irq, &irte);
+
+ apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
+ "Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
+ "Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X "
+ "Avail:%X Vector:%02X Dest:%08X "
+ "SID:%04X SQ:%X SVT:%X)\n",
+ attr->ioapic, irte.present, irte.fpd, irte.dst_mode,
+ irte.redir_hint, irte.trigger_mode, irte.dlvry_mode,
+ irte.avail, irte.vector, irte.dest_id,
+ irte.sid, irte.sq, irte.svt);
+
+ memset(entry, 0, sizeof(*entry));
+
+ entry->index2 = (index >> 15) & 0x1;
+ entry->zero = 0;
+ entry->format = 1;
+ entry->index = (index & 0x7fff);
+ /*
+ * IO-APIC RTE will be configured with virtual vector.
+ * irq handler will do the explicit EOI to the io-apic.
+ */
+ entry->vector = attr->ioapic_pin;
+ entry->mask = 0; /* enable IRQ */
+ entry->trigger = attr->trigger;
+ entry->polarity = attr->polarity;
+
+ /* Mask level triggered irqs.
+ * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
+ */
+ if (attr->trigger)
+ entry->mask = 1;
+
+ return 0;
+}
+
+#ifdef CONFIG_SMP
+/*
+ * Migrate the IO-APIC irq in the presence of intr-remapping.
+ *
+ * For both level and edge triggered, irq migration is a simple atomic
+ * update(of vector and cpu destination) of IRTE and flush the hardware cache.
+ *
+ * For level triggered, we eliminate the io-apic RTE modification (with the
+ * updated vector information), by using a virtual vector (io-apic pin number).
+ * Real vector that is used for interrupting cpu will be coming from
+ * the interrupt-remapping table entry.
+ *
+ * As the migration is a simple atomic update of IRTE, the same mechanism
+ * is used to migrate MSI irq's in the presence of interrupt-remapping.
+ */
+static int
+intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+ bool force)
+{
+ struct irq_cfg *cfg = data->chip_data;
+ unsigned int dest, irq = data->irq;
+ struct irte irte;
+
+ if (!cpumask_intersects(mask, cpu_online_mask))
+ return -EINVAL;
+
+ if (get_irte(irq, &irte))
+ return -EBUSY;
+
+ if (assign_irq_vector(irq, cfg, mask))
+ return -EBUSY;
+
+ dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
+
+ irte.vector = cfg->vector;
+ irte.dest_id = IRTE_DEST(dest);
+
+ /*
+ * Atomically updates the IRTE with the new destination, vector
+ * and flushes the interrupt entry cache.
+ */
+ modify_irte(irq, &irte);
+
+ /*
+ * After this point, all the interrupts will start arriving
+ * at the new destination. So, time to cleanup the previous
+ * vector allocation.
+ */
+ if (cfg->move_in_progress)
+ send_cleanup_vector(cfg);
+
+ cpumask_copy(data->affinity, mask);
+ return 0;
+}
+#endif
+
+static void intel_compose_msi_msg(struct pci_dev *pdev,
+ unsigned int irq, unsigned int dest,
+ struct msi_msg *msg, u8 hpet_id)
+{
+ struct irq_cfg *cfg;
+ struct irte irte;
+ u16 sub_handle = 0;
+ int ir_index;
+
+ cfg = irq_get_chip_data(irq);
+
+ ir_index = map_irq_to_irte_handle(irq, &sub_handle);
+ BUG_ON(ir_index == -1);
+
+ prepare_irte(&irte, cfg->vector, dest);
+
+ /* Set source-id of interrupt request */
+ if (pdev)
+ set_msi_sid(&irte, pdev);
+ else
+ set_hpet_sid(&irte, hpet_id);
+
+ modify_irte(irq, &irte);
+
+ msg->address_hi = MSI_ADDR_BASE_HI;
+ msg->data = sub_handle;
+ msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
+ MSI_ADDR_IR_SHV |
+ MSI_ADDR_IR_INDEX1(ir_index) |
+ MSI_ADDR_IR_INDEX2(ir_index);
+}
+
+/*
+ * Map the PCI dev to the corresponding remapping hardware unit
+ * and allocate 'nvec' consecutive interrupt-remapping table entries
+ * in it.
+ */
+static int intel_msi_alloc_irq(struct pci_dev *dev, int irq, int nvec)
+{
+ struct intel_iommu *iommu;
+ int index;
+
+ iommu = map_dev_to_ir(dev);
+ if (!iommu) {
+ printk(KERN_ERR
+ "Unable to map PCI %s to iommu\n", pci_name(dev));
+ return -ENOENT;
+ }
+
+ index = alloc_irte(iommu, irq, nvec);
+ if (index < 0) {
+ printk(KERN_ERR
+ "Unable to allocate %d IRTE for PCI %s\n", nvec,
+ pci_name(dev));
+ return -ENOSPC;
+ }
+ return index;
+}
+
+static int intel_msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
+ int index, int sub_handle)
+{
+ struct intel_iommu *iommu;
+
+ iommu = map_dev_to_ir(pdev);
+ if (!iommu)
+ return -ENOENT;
+ /*
+ * setup the mapping between the irq and the IRTE
+ * base index, the sub_handle pointing to the
+ * appropriate interrupt remap table entry.
+ */
+ set_irte_irq(irq, iommu, index, sub_handle);
+
+ return 0;
+}
+
+static int intel_setup_hpet_msi(unsigned int irq, unsigned int id)
+{
+ struct intel_iommu *iommu = map_hpet_to_ir(id);
+ int index;
+
+ if (!iommu)
+ return -1;
+
+ index = alloc_irte(iommu, irq, 1);
+ if (index < 0)
+ return -1;
+
+ return 0;
+}
+
+struct irq_remap_ops intel_irq_remap_ops = {
+ .supported = intel_irq_remapping_supported,
+ .prepare = dmar_table_init,
+ .enable = intel_enable_irq_remapping,
+ .disable = disable_irq_remapping,
+ .reenable = reenable_irq_remapping,
+ .enable_faulting = enable_drhd_fault_handling,
+ .setup_ioapic_entry = intel_setup_ioapic_entry,
+#ifdef CONFIG_SMP
+ .set_affinity = intel_ioapic_set_affinity,
+#endif
+ .free_irq = free_irte,
+ .compose_msi_msg = intel_compose_msi_msg,
+ .msi_alloc_irq = intel_msi_alloc_irq,
+ .msi_setup_irq = intel_msi_setup_irq,
+ .setup_hpet_msi = intel_setup_hpet_msi,
+};
diff --git a/drivers/iommu/intr_remapping.h b/drivers/iommu/intr_remapping.h
deleted file mode 100644
index 5662fecfee60..000000000000
--- a/drivers/iommu/intr_remapping.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <linux/intel-iommu.h>
-
-struct ioapic_scope {
- struct intel_iommu *iommu;
- unsigned int id;
- unsigned int bus; /* PCI bus number */
- unsigned int devfn; /* PCI devfn number */
-};
-
-struct hpet_scope {
- struct intel_iommu *iommu;
- u8 id;
- unsigned int bus;
- unsigned int devfn;
-};
-
-#define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c
new file mode 100644
index 000000000000..40cda8e98d87
--- /dev/null
+++ b/drivers/iommu/irq_remapping.c
@@ -0,0 +1,166 @@
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+
+#include "irq_remapping.h"
+
+int irq_remapping_enabled;
+
+int disable_irq_remap;
+int disable_sourceid_checking;
+int no_x2apic_optout;
+
+static struct irq_remap_ops *remap_ops;
+
+static __init int setup_nointremap(char *str)
+{
+ disable_irq_remap = 1;
+ return 0;
+}
+early_param("nointremap", setup_nointremap);
+
+static __init int setup_irqremap(char *str)
+{
+ if (!str)
+ return -EINVAL;
+
+ while (*str) {
+ if (!strncmp(str, "on", 2))
+ disable_irq_remap = 0;
+ else if (!strncmp(str, "off", 3))
+ disable_irq_remap = 1;
+ else if (!strncmp(str, "nosid", 5))
+ disable_sourceid_checking = 1;
+ else if (!strncmp(str, "no_x2apic_optout", 16))
+ no_x2apic_optout = 1;
+
+ str += strcspn(str, ",");
+ while (*str == ',')
+ str++;
+ }
+
+ return 0;
+}
+early_param("intremap", setup_irqremap);
+
+void __init setup_irq_remapping_ops(void)
+{
+ remap_ops = &intel_irq_remap_ops;
+}
+
+int irq_remapping_supported(void)
+{
+ if (disable_irq_remap)
+ return 0;
+
+ if (!remap_ops || !remap_ops->supported)
+ return 0;
+
+ return remap_ops->supported();
+}
+
+int __init irq_remapping_prepare(void)
+{
+ if (!remap_ops || !remap_ops->prepare)
+ return -ENODEV;
+
+ return remap_ops->prepare();
+}
+
+int __init irq_remapping_enable(void)
+{
+ if (!remap_ops || !remap_ops->enable)
+ return -ENODEV;
+
+ return remap_ops->enable();
+}
+
+void irq_remapping_disable(void)
+{
+ if (!remap_ops || !remap_ops->disable)
+ return;
+
+ remap_ops->disable();
+}
+
+int irq_remapping_reenable(int mode)
+{
+ if (!remap_ops || !remap_ops->reenable)
+ return 0;
+
+ return remap_ops->reenable(mode);
+}
+
+int __init irq_remap_enable_fault_handling(void)
+{
+ if (!remap_ops || !remap_ops->enable_faulting)
+ return -ENODEV;
+
+ return remap_ops->enable_faulting();
+}
+
+int setup_ioapic_remapped_entry(int irq,
+ struct IO_APIC_route_entry *entry,
+ unsigned int destination, int vector,
+ struct io_apic_irq_attr *attr)
+{
+ if (!remap_ops || !remap_ops->setup_ioapic_entry)
+ return -ENODEV;
+
+ return remap_ops->setup_ioapic_entry(irq, entry, destination,
+ vector, attr);
+}
+
+#ifdef CONFIG_SMP
+int set_remapped_irq_affinity(struct irq_data *data, const struct cpumask *mask,
+ bool force)
+{
+ if (!remap_ops || !remap_ops->set_affinity)
+ return 0;
+
+ return remap_ops->set_affinity(data, mask, force);
+}
+#endif
+
+void free_remapped_irq(int irq)
+{
+ if (!remap_ops || !remap_ops->free_irq)
+ return;
+
+ remap_ops->free_irq(irq);
+}
+
+void compose_remapped_msi_msg(struct pci_dev *pdev,
+ unsigned int irq, unsigned int dest,
+ struct msi_msg *msg, u8 hpet_id)
+{
+ if (!remap_ops || !remap_ops->compose_msi_msg)
+ return;
+
+ remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id);
+}
+
+int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
+{
+ if (!remap_ops || !remap_ops->msi_alloc_irq)
+ return -ENODEV;
+
+ return remap_ops->msi_alloc_irq(pdev, irq, nvec);
+}
+
+int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
+ int index, int sub_handle)
+{
+ if (!remap_ops || !remap_ops->msi_setup_irq)
+ return -ENODEV;
+
+ return remap_ops->msi_setup_irq(pdev, irq, index, sub_handle);
+}
+
+int setup_hpet_msi_remapped(unsigned int irq, unsigned int id)
+{
+ if (!remap_ops || !remap_ops->setup_hpet_msi)
+ return -ENODEV;
+
+ return remap_ops->setup_hpet_msi(irq, id);
+}
diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h
new file mode 100644
index 000000000000..be9d72950c51
--- /dev/null
+++ b/drivers/iommu/irq_remapping.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * Author: Joerg Roedel <joerg.roedel@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This header file contains stuff that is shared between different interrupt
+ * remapping drivers but with no need to be visible outside of the IOMMU layer.
+ */
+
+#ifndef __IRQ_REMAPPING_H
+#define __IRQ_REMAPPING_H
+
+#ifdef CONFIG_IRQ_REMAP
+
+struct IO_APIC_route_entry;
+struct io_apic_irq_attr;
+struct irq_data;
+struct cpumask;
+struct pci_dev;
+struct msi_msg;
+
+extern int disable_irq_remap;
+extern int disable_sourceid_checking;
+extern int no_x2apic_optout;
+
+struct irq_remap_ops {
+ /* Check whether Interrupt Remapping is supported */
+ int (*supported)(void);
+
+ /* Initializes hardware and makes it ready for remapping interrupts */
+ int (*prepare)(void);
+
+ /* Enables the remapping hardware */
+ int (*enable)(void);
+
+ /* Disables the remapping hardware */
+ void (*disable)(void);
+
+ /* Reenables the remapping hardware */
+ int (*reenable)(int);
+
+ /* Enable fault handling */
+ int (*enable_faulting)(void);
+
+ /* IO-APIC setup routine */
+ int (*setup_ioapic_entry)(int irq, struct IO_APIC_route_entry *,
+ unsigned int, int,
+ struct io_apic_irq_attr *);
+
+#ifdef CONFIG_SMP
+ /* Set the CPU affinity of a remapped interrupt */
+ int (*set_affinity)(struct irq_data *data, const struct cpumask *mask,
+ bool force);
+#endif
+
+ /* Free an IRQ */
+ int (*free_irq)(int);
+
+ /* Create MSI msg to use for interrupt remapping */
+ void (*compose_msi_msg)(struct pci_dev *,
+ unsigned int, unsigned int,
+ struct msi_msg *, u8);
+
+ /* Allocate remapping resources for MSI */
+ int (*msi_alloc_irq)(struct pci_dev *, int, int);
+
+ /* Setup the remapped MSI irq */
+ int (*msi_setup_irq)(struct pci_dev *, unsigned int, int, int);
+
+ /* Setup interrupt remapping for an HPET MSI */
+ int (*setup_hpet_msi)(unsigned int, unsigned int);
+};
+
+extern struct irq_remap_ops intel_irq_remap_ops;
+
+#endif /* CONFIG_IRQ_REMAP */
+
+#endif /* __IRQ_REMAPPING_H */
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 3b9278b333ba..527588708948 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -148,6 +148,7 @@ static struct usb_driver gigaset_usb_driver = {
.reset_resume = gigaset_post_reset,
.pre_reset = gigaset_pre_reset,
.post_reset = gigaset_post_reset,
+ .disable_hub_initiated_lpm = 1,
};
/* get message text for usb_submit_urb return code
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index bb12d8051732..d0a41cb0cf62 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -124,6 +124,7 @@ static struct usb_driver gigaset_usb_driver = {
.reset_resume = gigaset_resume,
.pre_reset = gigaset_pre_reset,
.post_reset = gigaset_resume,
+ .disable_hub_initiated_lpm = 1,
};
struct usb_cardstate {
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
index 83206e453d4e..c65c3440cd70 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -2126,6 +2126,7 @@ static struct usb_driver hfcsusb_drv = {
.id_table = hfcsusb_idtab,
.probe = hfcsusb_probe,
.disconnect = hfcsusb_disconnect,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(hfcsusb_drv);
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index 62c65bdefd8a..84f9c8103078 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -1568,6 +1568,7 @@ static struct usb_driver hfc_drv = {
.id_table = hfcusb_idtab,
.probe = hfc_usb_probe,
.disconnect = hfc_usb_disconnect,
+ .disable_hub_initiated_lpm = 1,
};
static void __exit
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
index 100296e20dc0..54ef9e4f8cbc 100644
--- a/drivers/isdn/hisax/st5481_init.c
+++ b/drivers/isdn/hisax/st5481_init.c
@@ -182,6 +182,7 @@ static struct usb_driver st5481_usb_driver = {
.probe = probe_st5481,
.disconnect = disconnect_st5481,
.id_table = st5481_ids,
+ .disable_hub_initiated_lpm = 1,
};
static int __init st5481_usb_init(void)
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index d9f5524593fb..8c610fa6782b 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -46,7 +46,6 @@ static DEFINE_MUTEX(isdn_mutex);
static char *isdn_revision = "$Revision: 1.1.2.3 $";
extern char *isdn_net_revision;
-extern char *isdn_tty_revision;
#ifdef CONFIG_ISDN_PPP
extern char *isdn_ppp_revision;
#else
@@ -2327,8 +2326,6 @@ static int __init isdn_init(void)
dev->chanmap[i] = -1;
dev->m_idx[i] = -1;
strcpy(dev->num[i], "???");
- init_waitqueue_head(&dev->mdm.info[i].open_wait);
- init_waitqueue_head(&dev->mdm.info[i].close_wait);
}
if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
printk(KERN_WARNING "isdn: Could not register control devices\n");
@@ -2353,8 +2350,6 @@ static int __init isdn_init(void)
strcpy(tmprev, isdn_revision);
printk(KERN_NOTICE "ISDN subsystem Rev: %s/", isdn_getrev(tmprev));
- strcpy(tmprev, isdn_tty_revision);
- printk("%s/", isdn_getrev(tmprev));
strcpy(tmprev, isdn_net_revision);
printk("%s/", isdn_getrev(tmprev));
strcpy(tmprev, isdn_ppp_revision);
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 3831abdbc66f..7bc50670d7d9 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1,5 +1,4 @@
-/* $Id: isdn_tty.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $
- *
+/*
* Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
*
* Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
@@ -12,6 +11,7 @@
#undef ISDN_TTY_STAT_DEBUG
#include <linux/isdn.h>
+#include <linux/serial.h> /* ASYNC_* flags */
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/mutex.h>
@@ -48,9 +48,6 @@ static int bit2si[8] =
static int si2bit[8] =
{4, 1, 4, 4, 4, 4, 4, 4};
-char *isdn_tty_revision = "$Revision: 1.1.2.3 $";
-
-
/* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
* to stuff incoming data directly into a tty's flip-buffer. This
* is done to speed up tty-receiving if the receive-queue is empty.
@@ -68,49 +65,54 @@ isdn_tty_try_read(modem_info *info, struct sk_buff *skb)
struct tty_struct *tty;
char last;
- if (info->online) {
- if ((tty = info->tty)) {
- if (info->mcr & UART_MCR_RTS) {
- len = skb->len
+ if (!info->online)
+ return 0;
+
+ tty = info->port.tty;
+ if (!tty)
+ return 0;
+
+ if (!(info->mcr & UART_MCR_RTS))
+ return 0;
+
+ len = skb->len
#ifdef CONFIG_ISDN_AUDIO
- + ISDN_AUDIO_SKB_DLECOUNT(skb)
+ + ISDN_AUDIO_SKB_DLECOUNT(skb)
#endif
- ;
+ ;
+
+ c = tty_buffer_request_room(tty, len);
+ if (c < len)
+ return 0;
- c = tty_buffer_request_room(tty, len);
- if (c >= len) {
-#ifdef CONFIG_ISDN_AUDIO
- if (ISDN_AUDIO_SKB_DLECOUNT(skb)) {
- int l = skb->len;
- unsigned char *dp = skb->data;
- while (--l) {
- if (*dp == DLE)
- tty_insert_flip_char(tty, DLE, 0);
- tty_insert_flip_char(tty, *dp++, 0);
- }
- if (*dp == DLE)
- tty_insert_flip_char(tty, DLE, 0);
- last = *dp;
- } else {
-#endif
- if (len > 1)
- tty_insert_flip_string(tty, skb->data, len - 1);
- last = skb->data[len - 1];
#ifdef CONFIG_ISDN_AUDIO
- }
+ if (ISDN_AUDIO_SKB_DLECOUNT(skb)) {
+ int l = skb->len;
+ unsigned char *dp = skb->data;
+ while (--l) {
+ if (*dp == DLE)
+ tty_insert_flip_char(tty, DLE, 0);
+ tty_insert_flip_char(tty, *dp++, 0);
+ }
+ if (*dp == DLE)
+ tty_insert_flip_char(tty, DLE, 0);
+ last = *dp;
+ } else {
#endif
- if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP)
- tty_insert_flip_char(tty, last, 0xFF);
- else
- tty_insert_flip_char(tty, last, TTY_NORMAL);
- tty_flip_buffer_push(tty);
- kfree_skb(skb);
- return 1;
- }
- }
- }
+ if (len > 1)
+ tty_insert_flip_string(tty, skb->data, len - 1);
+ last = skb->data[len - 1];
+#ifdef CONFIG_ISDN_AUDIO
}
- return 0;
+#endif
+ if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP)
+ tty_insert_flip_char(tty, last, 0xFF);
+ else
+ tty_insert_flip_char(tty, last, TTY_NORMAL);
+ tty_flip_buffer_push(tty);
+ kfree_skb(skb);
+
+ return 1;
}
/* isdn_tty_readmodem() is called periodically from within timer-interrupt.
@@ -128,35 +130,39 @@ isdn_tty_readmodem(void)
modem_info *info;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- if ((midx = dev->m_idx[i]) >= 0) {
- info = &dev->mdm.info[midx];
- if (info->online) {
- r = 0;
+ midx = dev->m_idx[i];
+ if (midx < 0)
+ continue;
+
+ info = &dev->mdm.info[midx];
+ if (!info->online)
+ continue;
+
+ r = 0;
#ifdef CONFIG_ISDN_AUDIO
- isdn_audio_eval_dtmf(info);
- if ((info->vonline & 1) && (info->emu.vpar[1]))
- isdn_audio_eval_silence(info);
-#endif
- if ((tty = info->tty)) {
- if (info->mcr & UART_MCR_RTS) {
- /* CISCO AsyncPPP Hack */
- if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
- r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 0);
- else
- r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 1);
- if (r)
- tty_flip_buffer_push(tty);
- } else
- r = 1;
- } else
- r = 1;
- if (r) {
- info->rcvsched = 0;
- resched = 1;
- } else
- info->rcvsched = 1;
- }
- }
+ isdn_audio_eval_dtmf(info);
+ if ((info->vonline & 1) && (info->emu.vpar[1]))
+ isdn_audio_eval_silence(info);
+#endif
+ tty = info->port.tty;
+ if (tty) {
+ if (info->mcr & UART_MCR_RTS) {
+ /* CISCO AsyncPPP Hack */
+ if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
+ r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 0);
+ else
+ r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 1);
+ if (r)
+ tty_flip_buffer_push(tty);
+ } else
+ r = 1;
+ } else
+ r = 1;
+ if (r) {
+ info->rcvsched = 0;
+ resched = 1;
+ } else
+ info->rcvsched = 1;
}
if (!resched)
isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 0);
@@ -294,7 +300,7 @@ isdn_tty_tint(modem_info *info)
len = skb->len;
if ((slen = isdn_writebuf_skb_stub(info->isdn_driver,
info->isdn_channel, 1, skb)) == len) {
- struct tty_struct *tty = info->tty;
+ struct tty_struct *tty = info->port.tty;
info->send_outstanding++;
info->msr &= ~UART_MSR_CTS;
info->lsr &= ~UART_LSR_TEMT;
@@ -327,7 +333,7 @@ isdn_tty_countDLE(unsigned char *buf, int len)
static int
isdn_tty_handleDLEdown(modem_info *info, atemu *m, int len)
{
- unsigned char *p = &info->xmit_buf[info->xmit_count];
+ unsigned char *p = &info->port.xmit_buf[info->xmit_count];
int count = 0;
while (len > 0) {
@@ -471,7 +477,7 @@ isdn_tty_senddown(modem_info *info)
return;
}
skb_reserve(skb, skb_res);
- memcpy(skb_put(skb, buflen), info->xmit_buf, buflen);
+ memcpy(skb_put(skb, buflen), info->port.xmit_buf, buflen);
info->xmit_count = 0;
#ifdef CONFIG_ISDN_AUDIO
if (info->vonline & 2) {
@@ -699,7 +705,7 @@ isdn_tty_modem_hup(modem_info *info, int local)
printk(KERN_DEBUG "Mhup ttyI%d\n", info->line);
#endif
info->rcvsched = 0;
- isdn_tty_flush_buffer(info->tty);
+ isdn_tty_flush_buffer(info->port.tty);
if (info->online) {
info->last_lhup = local;
info->online = 0;
@@ -997,20 +1003,21 @@ isdn_tty_paranoia_check(modem_info *info, char *name, const char *routine)
static void
isdn_tty_change_speed(modem_info *info)
{
+ struct tty_port *port = &info->port;
uint cflag,
cval,
quot;
int i;
- if (!info->tty || !info->tty->termios)
+ if (!port->tty || !port->tty->termios)
return;
- cflag = info->tty->termios->c_cflag;
+ cflag = port->tty->termios->c_cflag;
quot = i = cflag & CBAUD;
if (i & CBAUDEX) {
i &= ~CBAUDEX;
if (i < 1 || i > 2)
- info->tty->termios->c_cflag &= ~CBAUDEX;
+ port->tty->termios->c_cflag &= ~CBAUDEX;
else
i += 15;
}
@@ -1040,20 +1047,20 @@ isdn_tty_change_speed(modem_info *info)
/* CTS flow control flag and modem status interrupts */
if (cflag & CRTSCTS) {
- info->flags |= ISDN_ASYNC_CTS_FLOW;
+ port->flags |= ASYNC_CTS_FLOW;
} else
- info->flags &= ~ISDN_ASYNC_CTS_FLOW;
+ port->flags &= ~ASYNC_CTS_FLOW;
if (cflag & CLOCAL)
- info->flags &= ~ISDN_ASYNC_CHECK_CD;
+ port->flags &= ~ASYNC_CHECK_CD;
else {
- info->flags |= ISDN_ASYNC_CHECK_CD;
+ port->flags |= ASYNC_CHECK_CD;
}
}
static int
isdn_tty_startup(modem_info *info)
{
- if (info->flags & ISDN_ASYNC_INITIALIZED)
+ if (info->port.flags & ASYNC_INITIALIZED)
return 0;
isdn_lock_drivers();
#ifdef ISDN_DEBUG_MODEM_OPEN
@@ -1063,14 +1070,14 @@ isdn_tty_startup(modem_info *info)
* Now, initialize the UART
*/
info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
- if (info->tty)
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ if (info->port.tty)
+ clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
/*
* and set the speed of the serial port
*/
isdn_tty_change_speed(info);
- info->flags |= ISDN_ASYNC_INITIALIZED;
+ info->port.flags |= ASYNC_INITIALIZED;
info->msr |= (UART_MSR_DSR | UART_MSR_CTS);
info->send_outstanding = 0;
return 0;
@@ -1083,14 +1090,14 @@ isdn_tty_startup(modem_info *info)
static void
isdn_tty_shutdown(modem_info *info)
{
- if (!(info->flags & ISDN_ASYNC_INITIALIZED))
+ if (!(info->port.flags & ASYNC_INITIALIZED))
return;
#ifdef ISDN_DEBUG_MODEM_OPEN
printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line);
#endif
isdn_unlock_drivers();
info->msr &= ~UART_MSR_RI;
- if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
+ if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) {
info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
isdn_tty_modem_reset_regs(info, 0);
@@ -1100,10 +1107,10 @@ isdn_tty_shutdown(modem_info *info)
isdn_tty_modem_hup(info, 1);
}
}
- if (info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
+ if (info->port.tty)
+ set_bit(TTY_IO_ERROR, &info->port.tty->flags);
- info->flags &= ~ISDN_ASYNC_INITIALIZED;
+ info->port.flags &= ~ASYNC_INITIALIZED;
}
/* isdn_tty_write() is the main send-routine. It is called from the upper
@@ -1146,7 +1153,7 @@ isdn_tty_write(struct tty_struct *tty, const u_char *buf, int count)
isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c,
&(m->pluscount),
&(m->lastplus));
- memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
+ memcpy(&info->port.xmit_buf[info->xmit_count], buf, c);
#ifdef CONFIG_ISDN_AUDIO
if (info->vonline) {
int cc = isdn_tty_handleDLEdown(info, m, c);
@@ -1478,107 +1485,6 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
* isdn_tty_open() and friends
* ------------------------------------------------------------
*/
-static int
-isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info *info)
-{
- DECLARE_WAITQUEUE(wait, NULL);
- int do_clocal = 0;
- int retval;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (tty_hung_up_p(filp) ||
- (info->flags & ISDN_ASYNC_CLOSING)) {
- if (info->flags & ISDN_ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
-#ifdef MODEM_DO_RESTART
- if (info->flags & ISDN_ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
-#else
- return -EAGAIN;
-#endif
- }
- /*
- * If non-blocking mode is set, then make the check up front
- * and then exit.
- */
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR))) {
- if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
- return -EBUSY;
- info->flags |= ISDN_ASYNC_NORMAL_ACTIVE;
- return 0;
- }
- if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) {
- if (info->normal_termios.c_cflag & CLOCAL)
- do_clocal = 1;
- } else {
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
- }
- /*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, info->count is dropped by one, so that
- * isdn_tty_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
- retval = 0;
- add_wait_queue(&info->open_wait, &wait);
-#ifdef ISDN_DEBUG_MODEM_OPEN
- printk(KERN_DEBUG "isdn_tty_block_til_ready before block: ttyi%d, count = %d\n",
- info->line, info->count);
-#endif
- if (!(tty_hung_up_p(filp)))
- info->count--;
- info->blocked_open++;
- while (1) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) ||
- !(info->flags & ISDN_ASYNC_INITIALIZED)) {
-#ifdef MODEM_DO_RESTART
- if (info->flags & ISDN_ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
-#else
- retval = -EAGAIN;
-#endif
- break;
- }
- if (!(info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
- !(info->flags & ISDN_ASYNC_CLOSING) &&
- (do_clocal || (info->msr & UART_MSR_DCD))) {
- break;
- }
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
-#ifdef ISDN_DEBUG_MODEM_OPEN
- printk(KERN_DEBUG "isdn_tty_block_til_ready blocking: ttyi%d, count = %d\n",
- info->line, info->count);
-#endif
- schedule();
- }
- current->state = TASK_RUNNING;
- remove_wait_queue(&info->open_wait, &wait);
- if (!tty_hung_up_p(filp))
- info->count++;
- info->blocked_open--;
-#ifdef ISDN_DEBUG_MODEM_OPEN
- printk(KERN_DEBUG "isdn_tty_block_til_ready after blocking: ttyi%d, count = %d\n",
- info->line, info->count);
-#endif
- if (retval)
- return retval;
- info->flags |= ISDN_ASYNC_NORMAL_ACTIVE;
- return 0;
-}
/*
* This routine is called whenever a serial port is opened. It
@@ -1589,23 +1495,22 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info *
static int
isdn_tty_open(struct tty_struct *tty, struct file *filp)
{
+ struct tty_port *port;
modem_info *info;
int retval;
info = &dev->mdm.info[tty->index];
if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open"))
return -ENODEV;
- if (!try_module_get(info->owner)) {
- printk(KERN_WARNING "%s: cannot reserve module\n", __func__);
- return -ENODEV;
- }
+ port = &info->port;
#ifdef ISDN_DEBUG_MODEM_OPEN
printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name,
- info->count);
+ port->count);
#endif
- info->count++;
+ port->count++;
tty->driver_data = info;
- info->tty = tty;
+ port->tty = tty;
+ tty->port = port;
/*
* Start up serial port
*/
@@ -1614,15 +1519,13 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp)
#ifdef ISDN_DEBUG_MODEM_OPEN
printk(KERN_DEBUG "isdn_tty_open return after startup\n");
#endif
- module_put(info->owner);
return retval;
}
- retval = isdn_tty_block_til_ready(tty, filp, info);
+ retval = tty_port_block_til_ready(port, tty, filp);
if (retval) {
#ifdef ISDN_DEBUG_MODEM_OPEN
printk(KERN_DEBUG "isdn_tty_open return after isdn_tty_block_til_ready \n");
#endif
- module_put(info->owner);
return retval;
}
#ifdef ISDN_DEBUG_MODEM_OPEN
@@ -1639,6 +1542,7 @@ static void
isdn_tty_close(struct tty_struct *tty, struct file *filp)
{
modem_info *info = (modem_info *) tty->driver_data;
+ struct tty_port *port = &info->port;
ulong timeout;
if (!info || isdn_tty_paranoia_check(info, tty->name, "isdn_tty_close"))
@@ -1649,7 +1553,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
#endif
return;
}
- if ((tty->count == 1) && (info->count != 1)) {
+ if ((tty->count == 1) && (port->count != 1)) {
/*
* Uh, oh. tty->count is 1, which means that the tty
* structure will be freed. Info->count should always
@@ -1658,30 +1562,21 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
* serial port won't be shutdown.
*/
printk(KERN_ERR "isdn_tty_close: bad port count; tty->count is 1, "
- "info->count is %d\n", info->count);
- info->count = 1;
+ "info->count is %d\n", port->count);
+ port->count = 1;
}
- if (--info->count < 0) {
+ if (--port->count < 0) {
printk(KERN_ERR "isdn_tty_close: bad port count for ttyi%d: %d\n",
- info->line, info->count);
- info->count = 0;
+ info->line, port->count);
+ port->count = 0;
}
- if (info->count) {
+ if (port->count) {
#ifdef ISDN_DEBUG_MODEM_OPEN
printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n");
#endif
- module_put(info->owner);
return;
}
- info->flags |= ISDN_ASYNC_CLOSING;
- /*
- * Save the termios structure, since this port may have
- * separate termios for callout and dialin.
- */
- if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE)
- info->normal_termios = *tty->termios;
- if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
- info->callout_termios = *tty->termios;
+ port->flags |= ASYNC_CLOSING;
tty->closing = 1;
/*
@@ -1690,7 +1585,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
* interrupt driver to stop checking the data ready bit in the
* line status register.
*/
- if (info->flags & ISDN_ASYNC_INITIALIZED) {
+ if (port->flags & ASYNC_INITIALIZED) {
tty_wait_until_sent_from_close(tty, 3000); /* 30 seconds timeout */
/*
* Before we drop DTR, make sure the UART transmitter
@@ -1708,16 +1603,10 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
isdn_tty_shutdown(info);
isdn_tty_flush_buffer(tty);
tty_ldisc_flush(tty);
- info->tty = NULL;
+ port->tty = NULL;
info->ncarrier = 0;
- tty->closing = 0;
- module_put(info->owner);
- if (info->blocked_open) {
- msleep_interruptible(500);
- wake_up_interruptible(&info->open_wait);
- }
- info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CLOSING);
- wake_up_interruptible(&info->close_wait);
+
+ tty_port_close_end(port, tty);
#ifdef ISDN_DEBUG_MODEM_OPEN
printk(KERN_DEBUG "isdn_tty_close normal exit\n");
#endif
@@ -1730,14 +1619,15 @@ static void
isdn_tty_hangup(struct tty_struct *tty)
{
modem_info *info = (modem_info *) tty->driver_data;
+ struct tty_port *port = &info->port;
if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_hangup"))
return;
isdn_tty_shutdown(info);
- info->count = 0;
- info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE);
- info->tty = NULL;
- wake_up_interruptible(&info->open_wait);
+ port->count = 0;
+ port->flags &= ~ASYNC_NORMAL_ACTIVE;
+ port->tty = NULL;
+ wake_up_interruptible(&port->open_wait);
}
/* This routine initializes all emulator-data.
@@ -1864,6 +1754,16 @@ static const struct tty_operations modem_ops = {
.tiocmset = isdn_tty_tiocmset,
};
+static int isdn_tty_carrier_raised(struct tty_port *port)
+{
+ modem_info *info = container_of(port, modem_info, port);
+ return info->msr & UART_MSR_DCD;
+}
+
+static const struct tty_port_operations isdn_tty_port_ops = {
+ .carrier_raised = isdn_tty_carrier_raised,
+};
+
int
isdn_tty_modem_init(void)
{
@@ -1899,9 +1799,8 @@ isdn_tty_modem_init(void)
goto err_unregister;
}
#endif
-#ifdef MODULE
- info->owner = THIS_MODULE;
-#endif
+ tty_port_init(&info->port);
+ info->port.ops = &isdn_tty_port_ops;
spin_lock_init(&info->readlock);
sprintf(info->last_cause, "0000");
sprintf(info->last_num, "none");
@@ -1913,12 +1812,7 @@ isdn_tty_modem_init(void)
isdn_tty_modem_reset_regs(info, 1);
info->magic = ISDN_ASYNC_MAGIC;
info->line = i;
- info->tty = NULL;
info->x_char = 0;
- info->count = 0;
- info->blocked_open = 0;
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
info->isdn_driver = -1;
info->isdn_channel = -1;
info->drv_index = -1;
@@ -1930,13 +1824,15 @@ isdn_tty_modem_init(void)
#ifdef CONFIG_ISDN_AUDIO
skb_queue_head_init(&info->dtmf_queue);
#endif
- if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL))) {
+ info->port.xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5,
+ GFP_KERNEL);
+ if (!info->port.xmit_buf) {
printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
retval = -ENOMEM;
goto err_unregister;
}
/* Make room for T.70 header */
- info->xmit_buf += 4;
+ info->port.xmit_buf += 4;
}
return 0;
err_unregister:
@@ -1945,7 +1841,7 @@ err_unregister:
#ifdef CONFIG_ISDN_TTY_FAX
kfree(info->fax);
#endif
- kfree(info->xmit_buf - 4);
+ kfree(info->port.xmit_buf - 4);
}
tty_unregister_driver(m->tty_modem);
err:
@@ -1966,7 +1862,7 @@ isdn_tty_exit(void)
#ifdef CONFIG_ISDN_TTY_FAX
kfree(info->fax);
#endif
- kfree(info->xmit_buf - 4);
+ kfree(info->port.xmit_buf - 4);
}
tty_unregister_driver(dev->mdm.tty_modem);
put_tty_driver(dev->mdm.tty_modem);
@@ -2068,7 +1964,7 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup)
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
modem_info *info = &dev->mdm.info[i];
- if (info->count == 0)
+ if (info->port.count == 0)
continue;
if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */
(info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */
@@ -2076,12 +1972,12 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup)
#ifdef ISDN_DEBUG_MODEM_ICALL
printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret);
printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx,
- info->flags, info->isdn_driver, info->isdn_channel,
- dev->usage[idx]);
+ info->port.flags, info->isdn_driver,
+ info->isdn_channel, dev->usage[idx]);
#endif
if (
#ifndef FIX_FILE_TRANSFER
- (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) &&
+ (info->port.flags & ASYNC_NORMAL_ACTIVE) &&
#endif
(info->isdn_driver == -1) &&
(info->isdn_channel == -1) &&
@@ -2120,8 +2016,7 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup)
return (wret == 2) ? 3 : 0;
}
-#define TTY_IS_ACTIVE(info) \
- (info->flags & (ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE))
+#define TTY_IS_ACTIVE(info) (info->port.flags & ASYNC_NORMAL_ACTIVE)
int
isdn_tty_stat_callback(int i, isdn_ctrl *c)
@@ -2212,9 +2107,9 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
* for incoming call of this device when
* DCD follow the state of incoming carrier
*/
- if (info->blocked_open &&
+ if (info->port.blocked_open &&
(info->emu.mdmreg[REG_DCD] & BIT_DCD)) {
- wake_up_interruptible(&info->open_wait);
+ wake_up_interruptible(&info->port.open_wait);
}
/* Schedule CONNECT-Message to any tty
@@ -2222,7 +2117,8 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
* set DCD-bit of its modem-status.
*/
if (TTY_IS_ACTIVE(info) ||
- (info->blocked_open && (info->emu.mdmreg[REG_DCD] & BIT_DCD))) {
+ (info->port.blocked_open &&
+ (info->emu.mdmreg[REG_DCD] & BIT_DCD))) {
info->msr |= UART_MSR_DCD;
info->emu.charge = 0;
if (info->dialing & 0xf)
@@ -2339,8 +2235,8 @@ isdn_tty_at_cout(char *msg, modem_info *info)
l = strlen(msg);
spin_lock_irqsave(&info->readlock, flags);
- tty = info->tty;
- if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {
+ tty = info->port.tty;
+ if ((info->port.flags & ASYNC_CLOSING) || (!tty)) {
spin_unlock_irqrestore(&info->readlock, flags);
return;
}
@@ -2490,15 +2386,15 @@ isdn_tty_modem_result(int code, modem_info *info)
case RESULT_NO_CARRIER:
#ifdef ISDN_DEBUG_MODEM_HUP
printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n",
- (info->flags & ISDN_ASYNC_CLOSING),
- (!info->tty));
+ (info->port.flags & ASYNC_CLOSING),
+ (!info->port.tty));
#endif
m->mdmreg[REG_RINGCNT] = 0;
del_timer(&info->nc_timer);
info->ncarrier = 0;
- if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
+ if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty))
return;
- }
+
#ifdef CONFIG_ISDN_AUDIO
if (info->vonline & 1) {
#ifdef ISDN_DEBUG_MODEM_VOICE
@@ -2629,14 +2525,11 @@ isdn_tty_modem_result(int code, modem_info *info)
}
}
if (code == RESULT_NO_CARRIER) {
- if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
+ if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty))
return;
- }
- if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
- (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
- (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
- tty_hangup(info->tty);
- }
+
+ if (info->port.flags & ASYNC_CHECK_CD)
+ tty_hangup(info->port.tty);
}
}
@@ -3803,19 +3696,19 @@ isdn_tty_modem_escape(void)
int midx;
for (i = 0; i < ISDN_MAX_CHANNELS; i++)
- if (USG_MODEM(dev->usage[i]))
- if ((midx = dev->m_idx[i]) >= 0) {
- modem_info *info = &dev->mdm.info[midx];
- if (info->online) {
- ton = 1;
- if ((info->emu.pluscount == 3) &&
- time_after(jiffies , info->emu.lastplus + PLUSWAIT2)) {
- info->emu.pluscount = 0;
- info->online = 0;
- isdn_tty_modem_result(RESULT_OK, info);
- }
+ if (USG_MODEM(dev->usage[i]) && (midx = dev->m_idx[i]) >= 0) {
+ modem_info *info = &dev->mdm.info[midx];
+ if (info->online) {
+ ton = 1;
+ if ((info->emu.pluscount == 3) &&
+ time_after(jiffies,
+ info->emu.lastplus + PLUSWAIT2)) {
+ info->emu.pluscount = 0;
+ info->online = 0;
+ isdn_tty_modem_result(RESULT_OK, info);
}
}
+ }
isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, ton);
}
@@ -3873,15 +3766,14 @@ isdn_tty_carrier_timeout(void)
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
modem_info *info = &dev->mdm.info[i];
- if (info->dialing) {
- if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) {
- info->dialing = 0;
- isdn_tty_modem_result(RESULT_NO_CARRIER, info);
- isdn_tty_modem_hup(info, 1);
- }
- else
- ton = 1;
- }
+ if (!info->dialing)
+ continue;
+ if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) {
+ info->dialing = 0;
+ isdn_tty_modem_result(RESULT_NO_CARRIER, info);
+ isdn_tty_modem_hup(info, 1);
+ } else
+ ton = 1;
}
isdn_timer_ctrl(ISDN_TIMER_CARRIER, ton);
}
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index fa51af11c6f1..a555da64224e 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -204,11 +204,14 @@ config THERM_ADT746X
better fan behaviour by default, and some manual control.
config THERM_PM72
- tristate "Support for thermal management on PowerMac G5"
+ tristate "Support for thermal management on PowerMac G5 (AGP)"
depends on I2C && I2C_POWERMAC && PPC_PMAC64
+ default n
help
This driver provides thermostat and fan control for the desktop
- G5 machines.
+ G5 machines.
+
+ This is deprecated, use windfarm instead.
config WINDFARM
tristate "New PowerMac thermal control infrastructure"
@@ -221,6 +224,22 @@ config WINDFARM_PM81
help
This driver provides thermal control for the iMacG5
+config WINDFARM_PM72
+ tristate "Support for thermal management on PowerMac G5 (AGP)"
+ depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && ADB_PMU
+ select I2C_POWERMAC
+ help
+ This driver provides thermal control for the PowerMac G5
+ "AGP" variants (PowerMac 7,2 and 7,3)
+
+config WINDFARM_RM31
+ tristate "Support for thermal management on Xserve G5"
+ depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && ADB_PMU
+ select I2C_POWERMAC
+ help
+ This driver provides thermal control for the Xserve G5
+ (RackMac3,1)
+
config WINDFARM_PM91
tristate "Support for thermal management on PowerMac9,1"
depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index 6652a6ebb6fa..6753b65f8ede 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -29,6 +29,20 @@ obj-$(CONFIG_THERM_PM72) += therm_pm72.o
obj-$(CONFIG_THERM_WINDTUNNEL) += therm_windtunnel.o
obj-$(CONFIG_THERM_ADT746X) += therm_adt746x.o
obj-$(CONFIG_WINDFARM) += windfarm_core.o
+obj-$(CONFIG_WINDFARM_PM72) += windfarm_fcu_controls.o \
+ windfarm_ad7417_sensor.o \
+ windfarm_lm75_sensor.o \
+ windfarm_max6690_sensor.o \
+ windfarm_pid.o \
+ windfarm_cpufreq_clamp.o \
+ windfarm_pm72.o
+obj-$(CONFIG_WINDFARM_RM31) += windfarm_fcu_controls.o \
+ windfarm_ad7417_sensor.o \
+ windfarm_lm75_sensor.o \
+ windfarm_lm87_sensor.o \
+ windfarm_pid.o \
+ windfarm_cpufreq_clamp.o \
+ windfarm_rm31.o
obj-$(CONFIG_WINDFARM_PM81) += windfarm_smu_controls.o \
windfarm_smu_sensors.o \
windfarm_lm75_sensor.o windfarm_pid.o \
diff --git a/drivers/macintosh/ams/ams-i2c.c b/drivers/macintosh/ams/ams-i2c.c
index abeecd27b484..978eda8d6678 100644
--- a/drivers/macintosh/ams/ams-i2c.c
+++ b/drivers/macintosh/ams/ams-i2c.c
@@ -65,7 +65,7 @@ static int ams_i2c_probe(struct i2c_client *client,
static int ams_i2c_remove(struct i2c_client *client);
static const struct i2c_device_id ams_id[] = {
- { "ams", 0 },
+ { "MAC,accelerometer_1", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ams_id);
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index fc71723cbc48..f433521a6f9d 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -47,7 +47,7 @@ static u8 FAN_SPD_SET[2] = {0x30, 0x31};
static u8 default_limits_local[3] = {70, 50, 70}; /* local, sensor1, sensor2 */
static u8 default_limits_chip[3] = {80, 65, 80}; /* local, sensor1, sensor2 */
-static const char *sensor_location[3];
+static const char *sensor_location[3] = { "?", "?", "?" };
static int limit_adjust;
static int fan_speed = -1;
@@ -79,18 +79,16 @@ struct thermostat {
int last_speed[2];
int last_var[2];
int pwm_inv[2];
+ struct task_struct *thread;
+ struct platform_device *pdev;
+ enum {
+ ADT7460,
+ ADT7467
+ } type;
};
-static enum {ADT7460, ADT7467} therm_type;
-static int therm_bus, therm_address;
-static struct platform_device * of_dev;
-static struct thermostat* thermostat;
-static struct task_struct *thread_therm = NULL;
-
static void write_both_fan_speed(struct thermostat *th, int speed);
static void write_fan_speed(struct thermostat *th, int speed, int fan);
-static void thermostat_create_files(void);
-static void thermostat_remove_files(void);
static int
write_reg(struct thermostat* th, int reg, u8 data)
@@ -126,66 +124,6 @@ read_reg(struct thermostat* th, int reg)
return data;
}
-static struct i2c_driver thermostat_driver;
-
-static int
-attach_thermostat(struct i2c_adapter *adapter)
-{
- unsigned long bus_no;
- struct i2c_board_info info;
- struct i2c_client *client;
-
- if (strncmp(adapter->name, "uni-n", 5))
- return -ENODEV;
- bus_no = simple_strtoul(adapter->name + 6, NULL, 10);
- if (bus_no != therm_bus)
- return -ENODEV;
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "therm_adt746x", I2C_NAME_SIZE);
- info.addr = therm_address;
- client = i2c_new_device(adapter, &info);
- if (!client)
- return -ENODEV;
-
- /*
- * Let i2c-core delete that device on driver removal.
- * This is safe because i2c-core holds the core_lock mutex for us.
- */
- list_add_tail(&client->detected, &thermostat_driver.clients);
- return 0;
-}
-
-static int
-remove_thermostat(struct i2c_client *client)
-{
- struct thermostat *th = i2c_get_clientdata(client);
- int i;
-
- thermostat_remove_files();
-
- if (thread_therm != NULL) {
- kthread_stop(thread_therm);
- }
-
- printk(KERN_INFO "adt746x: Putting max temperatures back from "
- "%d, %d, %d to %d, %d, %d\n",
- th->limits[0], th->limits[1], th->limits[2],
- th->initial_limits[0], th->initial_limits[1],
- th->initial_limits[2]);
-
- for (i = 0; i < 3; i++)
- write_reg(th, LIMIT_REG[i], th->initial_limits[i]);
-
- write_both_fan_speed(th, -1);
-
- thermostat = NULL;
-
- kfree(th);
-
- return 0;
-}
-
static int read_fan_speed(struct thermostat *th, u8 addr)
{
u8 tmp[2];
@@ -203,7 +141,7 @@ static int read_fan_speed(struct thermostat *th, u8 addr)
static void write_both_fan_speed(struct thermostat *th, int speed)
{
write_fan_speed(th, speed, 0);
- if (therm_type == ADT7460)
+ if (th->type == ADT7460)
write_fan_speed(th, speed, 1);
}
@@ -216,7 +154,7 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan)
else if (speed < -1)
speed = 0;
- if (therm_type == ADT7467 && fan == 1)
+ if (th->type == ADT7467 && fan == 1)
return;
if (th->last_speed[fan] != speed) {
@@ -239,7 +177,7 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan)
write_reg(th, FAN_SPD_SET[fan], speed);
} else {
/* back to automatic */
- if(therm_type == ADT7460) {
+ if(th->type == ADT7460) {
manual = read_reg(th,
MANUAL_MODE[fan]) & (~MANUAL_MASK);
manual &= ~INVERT_MASK;
@@ -293,7 +231,7 @@ static void update_fans_speed (struct thermostat *th)
/* we don't care about local sensor, so we start at sensor 1 */
for (i = 1; i < 3; i++) {
int started = 0;
- int fan_number = (therm_type == ADT7460 && i == 2);
+ int fan_number = (th->type == ADT7460 && i == 2);
int var = th->temps[i] - th->limits[i];
if (var > -1) {
@@ -370,116 +308,22 @@ static int monitor_task(void *arg)
static void set_limit(struct thermostat *th, int i)
{
- /* Set sensor1 limit higher to avoid powerdowns */
- th->limits[i] = default_limits_chip[i] + limit_adjust;
- write_reg(th, LIMIT_REG[i], th->limits[i]);
+ /* Set sensor1 limit higher to avoid powerdowns */
+ th->limits[i] = default_limits_chip[i] + limit_adjust;
+ write_reg(th, LIMIT_REG[i], th->limits[i]);
- /* set our limits to normal */
- th->limits[i] = default_limits_local[i] + limit_adjust;
+ /* set our limits to normal */
+ th->limits[i] = default_limits_local[i] + limit_adjust;
}
-static int probe_thermostat(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct thermostat* th;
- int rc;
- int i;
-
- if (thermostat)
- return 0;
-
- th = kzalloc(sizeof(struct thermostat), GFP_KERNEL);
- if (!th)
- return -ENOMEM;
-
- i2c_set_clientdata(client, th);
- th->clt = client;
-
- rc = read_reg(th, CONFIG_REG);
- if (rc < 0) {
- dev_err(&client->dev, "Thermostat failed to read config!\n");
- kfree(th);
- return -ENODEV;
- }
-
- /* force manual control to start the fan quieter */
- if (fan_speed == -1)
- fan_speed = 64;
-
- if(therm_type == ADT7460) {
- printk(KERN_INFO "adt746x: ADT7460 initializing\n");
- /* The 7460 needs to be started explicitly */
- write_reg(th, CONFIG_REG, 1);
- } else
- printk(KERN_INFO "adt746x: ADT7467 initializing\n");
-
- for (i = 0; i < 3; i++) {
- th->initial_limits[i] = read_reg(th, LIMIT_REG[i]);
- set_limit(th, i);
- }
-
- printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d"
- " to %d, %d, %d\n",
- th->initial_limits[0], th->initial_limits[1],
- th->initial_limits[2], th->limits[0], th->limits[1],
- th->limits[2]);
-
- thermostat = th;
-
- /* record invert bit status because fw can corrupt it after suspend */
- th->pwm_inv[0] = read_reg(th, MANUAL_MODE[0]) & INVERT_MASK;
- th->pwm_inv[1] = read_reg(th, MANUAL_MODE[1]) & INVERT_MASK;
-
- /* be sure to really write fan speed the first time */
- th->last_speed[0] = -2;
- th->last_speed[1] = -2;
- th->last_var[0] = -80;
- th->last_var[1] = -80;
-
- if (fan_speed != -1) {
- /* manual mode, stop fans */
- write_both_fan_speed(th, 0);
- } else {
- /* automatic mode */
- write_both_fan_speed(th, -1);
- }
-
- thread_therm = kthread_run(monitor_task, th, "kfand");
-
- if (thread_therm == ERR_PTR(-ENOMEM)) {
- printk(KERN_INFO "adt746x: Kthread creation failed\n");
- thread_therm = NULL;
- return -ENOMEM;
- }
-
- thermostat_create_files();
-
- return 0;
+#define BUILD_SHOW_FUNC_INT(name, data) \
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct thermostat *th = dev_get_drvdata(dev); \
+ return sprintf(buf, "%d\n", data); \
}
-static const struct i2c_device_id therm_adt746x_id[] = {
- { "therm_adt746x", 0 },
- { }
-};
-
-static struct i2c_driver thermostat_driver = {
- .driver = {
- .name = "therm_adt746x",
- },
- .attach_adapter = attach_thermostat,
- .probe = probe_thermostat,
- .remove = remove_thermostat,
- .id_table = therm_adt746x_id,
-};
-
-/*
- * Now, unfortunately, sysfs doesn't give us a nice void * we could
- * pass around to the attribute functions, so we don't really have
- * choice but implement a bunch of them...
- *
- * FIXME, it does now...
- */
-#define BUILD_SHOW_FUNC_INT(name, data) \
+#define BUILD_SHOW_FUNC_INT_LITE(name, data) \
static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return sprintf(buf, "%d\n", data); \
@@ -494,22 +338,24 @@ static ssize_t show_##name(struct device *dev, struct device_attribute *attr, ch
#define BUILD_SHOW_FUNC_FAN(name, data) \
static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
+ struct thermostat *th = dev_get_drvdata(dev); \
return sprintf(buf, "%d (%d rpm)\n", \
- thermostat->last_speed[data], \
- read_fan_speed(thermostat, FAN_SPEED[data]) \
+ th->last_speed[data], \
+ read_fan_speed(th, FAN_SPEED[data]) \
); \
}
#define BUILD_STORE_FUNC_DEG(name, data) \
static ssize_t store_##name(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) \
{ \
+ struct thermostat *th = dev_get_drvdata(dev); \
int val; \
int i; \
val = simple_strtol(buf, NULL, 10); \
printk(KERN_INFO "Adjusting limits by %d degrees\n", val); \
limit_adjust = val; \
for (i=0; i < 3; i++) \
- set_limit(thermostat, i); \
+ set_limit(th, i); \
return n; \
}
@@ -525,20 +371,21 @@ static ssize_t store_##name(struct device *dev, struct device_attribute *attr, c
return n; \
}
-BUILD_SHOW_FUNC_INT(sensor1_temperature, (read_reg(thermostat, TEMP_REG[1])))
-BUILD_SHOW_FUNC_INT(sensor2_temperature, (read_reg(thermostat, TEMP_REG[2])))
-BUILD_SHOW_FUNC_INT(sensor1_limit, thermostat->limits[1])
-BUILD_SHOW_FUNC_INT(sensor2_limit, thermostat->limits[2])
+BUILD_SHOW_FUNC_INT(sensor1_temperature, (read_reg(th, TEMP_REG[1])))
+BUILD_SHOW_FUNC_INT(sensor2_temperature, (read_reg(th, TEMP_REG[2])))
+BUILD_SHOW_FUNC_INT(sensor1_limit, th->limits[1])
+BUILD_SHOW_FUNC_INT(sensor2_limit, th->limits[2])
BUILD_SHOW_FUNC_STR(sensor1_location, sensor_location[1])
BUILD_SHOW_FUNC_STR(sensor2_location, sensor_location[2])
-BUILD_SHOW_FUNC_INT(specified_fan_speed, fan_speed)
+BUILD_SHOW_FUNC_INT_LITE(specified_fan_speed, fan_speed)
+BUILD_STORE_FUNC_INT(specified_fan_speed,fan_speed)
+
BUILD_SHOW_FUNC_FAN(sensor1_fan_speed, 0)
BUILD_SHOW_FUNC_FAN(sensor2_fan_speed, 1)
-BUILD_STORE_FUNC_INT(specified_fan_speed,fan_speed)
-BUILD_SHOW_FUNC_INT(limit_adjust, limit_adjust)
-BUILD_STORE_FUNC_DEG(limit_adjust, thermostat)
+BUILD_SHOW_FUNC_INT_LITE(limit_adjust, limit_adjust)
+BUILD_STORE_FUNC_DEG(limit_adjust, th)
static DEVICE_ATTR(sensor1_temperature, S_IRUGO,
show_sensor1_temperature,NULL);
@@ -564,53 +411,77 @@ static DEVICE_ATTR(sensor2_fan_speed, S_IRUGO,
static DEVICE_ATTR(limit_adjust, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
show_limit_adjust, store_limit_adjust);
-
-static int __init
-thermostat_init(void)
+static void thermostat_create_files(struct thermostat *th)
{
- struct device_node* np;
- const u32 *prop;
- int i = 0, offset = 0;
+ struct device_node *np = th->clt->dev.of_node;
+ struct device *dev;
+ int err;
- np = of_find_node_by_name(NULL, "fan");
- if (!np)
- return -ENODEV;
- if (of_device_is_compatible(np, "adt7460"))
- therm_type = ADT7460;
- else if (of_device_is_compatible(np, "adt7467"))
- therm_type = ADT7467;
- else {
- of_node_put(np);
- return -ENODEV;
- }
+ /* To maintain ABI compatibility with userspace, create
+ * the old style platform driver and attach the attributes
+ * to it here
+ */
+ th->pdev = of_platform_device_create(np, "temperatures", NULL);
+ if (!th->pdev)
+ return;
+ dev = &th->pdev->dev;
+ dev_set_drvdata(dev, th);
+ err = device_create_file(dev, &dev_attr_sensor1_temperature);
+ err |= device_create_file(dev, &dev_attr_sensor2_temperature);
+ err |= device_create_file(dev, &dev_attr_sensor1_limit);
+ err |= device_create_file(dev, &dev_attr_sensor2_limit);
+ err |= device_create_file(dev, &dev_attr_sensor1_location);
+ err |= device_create_file(dev, &dev_attr_sensor2_location);
+ err |= device_create_file(dev, &dev_attr_limit_adjust);
+ err |= device_create_file(dev, &dev_attr_specified_fan_speed);
+ err |= device_create_file(dev, &dev_attr_sensor1_fan_speed);
+ if(th->type == ADT7460)
+ err |= device_create_file(dev, &dev_attr_sensor2_fan_speed);
+ if (err)
+ printk(KERN_WARNING
+ "Failed to create temperature attribute file(s).\n");
+}
- prop = of_get_property(np, "hwsensor-params-version", NULL);
- printk(KERN_INFO "adt746x: version %d (%ssupported)\n", *prop,
- (*prop == 1)?"":"un");
- if (*prop != 1) {
- of_node_put(np);
- return -ENODEV;
- }
+static void thermostat_remove_files(struct thermostat *th)
+{
+ struct device *dev;
- prop = of_get_property(np, "reg", NULL);
- if (!prop) {
- of_node_put(np);
- return -ENODEV;
- }
+ if (!th->pdev)
+ return;
+ dev = &th->pdev->dev;
+ device_remove_file(dev, &dev_attr_sensor1_temperature);
+ device_remove_file(dev, &dev_attr_sensor2_temperature);
+ device_remove_file(dev, &dev_attr_sensor1_limit);
+ device_remove_file(dev, &dev_attr_sensor2_limit);
+ device_remove_file(dev, &dev_attr_sensor1_location);
+ device_remove_file(dev, &dev_attr_sensor2_location);
+ device_remove_file(dev, &dev_attr_limit_adjust);
+ device_remove_file(dev, &dev_attr_specified_fan_speed);
+ device_remove_file(dev, &dev_attr_sensor1_fan_speed);
+ if (th->type == ADT7460)
+ device_remove_file(dev, &dev_attr_sensor2_fan_speed);
+ of_device_unregister(th->pdev);
- /* look for bus either by path or using "reg" */
- if (strstr(np->full_name, "/i2c-bus@") != NULL) {
- const char *tmp_bus = (strstr(np->full_name, "/i2c-bus@") + 9);
- therm_bus = tmp_bus[0]-'0';
- } else {
- therm_bus = ((*prop) >> 8) & 0x0f;
- }
+}
- therm_address = ((*prop) & 0xff) >> 1;
+static int probe_thermostat(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device_node *np = client->dev.of_node;
+ struct thermostat* th;
+ const __be32 *prop;
+ int i, rc, vers, offset = 0;
- printk(KERN_INFO "adt746x: Thermostat bus: %d, address: 0x%02x, "
- "limit_adjust: %d, fan_speed: %d\n",
- therm_bus, therm_address, limit_adjust, fan_speed);
+ if (!np)
+ return -ENXIO;
+ prop = of_get_property(np, "hwsensor-params-version", NULL);
+ if (!prop)
+ return -ENXIO;
+ vers = be32_to_cpup(prop);
+ printk(KERN_INFO "adt746x: version %d (%ssupported)\n",
+ vers, vers == 1 ? "" : "un");
+ if (vers != 1)
+ return -ENXIO;
if (of_get_property(np, "hwsensor-location", NULL)) {
for (i = 0; i < 3; i++) {
@@ -623,72 +494,129 @@ thermostat_init(void)
printk(KERN_INFO "sensor %d: %s\n", i, sensor_location[i]);
offset += strlen(sensor_location[i]) + 1;
}
- } else {
- sensor_location[0] = "?";
- sensor_location[1] = "?";
- sensor_location[2] = "?";
}
- of_dev = of_platform_device_create(np, "temperatures", NULL);
- of_node_put(np);
+ th = kzalloc(sizeof(struct thermostat), GFP_KERNEL);
+ if (!th)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, th);
+ th->clt = client;
+ th->type = id->driver_data;
- if (of_dev == NULL) {
- printk(KERN_ERR "Can't register temperatures device !\n");
+ rc = read_reg(th, CONFIG_REG);
+ if (rc < 0) {
+ dev_err(&client->dev, "Thermostat failed to read config!\n");
+ kfree(th);
return -ENODEV;
}
-#ifndef CONFIG_I2C_POWERMAC
- request_module("i2c-powermac");
-#endif
+ /* force manual control to start the fan quieter */
+ if (fan_speed == -1)
+ fan_speed = 64;
+
+ if (th->type == ADT7460) {
+ printk(KERN_INFO "adt746x: ADT7460 initializing\n");
+ /* The 7460 needs to be started explicitly */
+ write_reg(th, CONFIG_REG, 1);
+ } else
+ printk(KERN_INFO "adt746x: ADT7467 initializing\n");
- return i2c_add_driver(&thermostat_driver);
+ for (i = 0; i < 3; i++) {
+ th->initial_limits[i] = read_reg(th, LIMIT_REG[i]);
+ set_limit(th, i);
+ }
+
+ printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d"
+ " to %d, %d, %d\n",
+ th->initial_limits[0], th->initial_limits[1],
+ th->initial_limits[2], th->limits[0], th->limits[1],
+ th->limits[2]);
+
+ /* record invert bit status because fw can corrupt it after suspend */
+ th->pwm_inv[0] = read_reg(th, MANUAL_MODE[0]) & INVERT_MASK;
+ th->pwm_inv[1] = read_reg(th, MANUAL_MODE[1]) & INVERT_MASK;
+
+ /* be sure to really write fan speed the first time */
+ th->last_speed[0] = -2;
+ th->last_speed[1] = -2;
+ th->last_var[0] = -80;
+ th->last_var[1] = -80;
+
+ if (fan_speed != -1) {
+ /* manual mode, stop fans */
+ write_both_fan_speed(th, 0);
+ } else {
+ /* automatic mode */
+ write_both_fan_speed(th, -1);
+ }
+
+ th->thread = kthread_run(monitor_task, th, "kfand");
+ if (th->thread == ERR_PTR(-ENOMEM)) {
+ printk(KERN_INFO "adt746x: Kthread creation failed\n");
+ th->thread = NULL;
+ return -ENOMEM;
+ }
+
+ thermostat_create_files(th);
+
+ return 0;
}
-static void thermostat_create_files(void)
+static int remove_thermostat(struct i2c_client *client)
{
- int err;
+ struct thermostat *th = i2c_get_clientdata(client);
+ int i;
+
+ thermostat_remove_files(th);
- err = device_create_file(&of_dev->dev, &dev_attr_sensor1_temperature);
- err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_temperature);
- err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_limit);
- err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_limit);
- err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_location);
- err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_location);
- err |= device_create_file(&of_dev->dev, &dev_attr_limit_adjust);
- err |= device_create_file(&of_dev->dev, &dev_attr_specified_fan_speed);
- err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_fan_speed);
- if(therm_type == ADT7460)
- err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed);
- if (err)
- printk(KERN_WARNING
- "Failed to create temperature attribute file(s).\n");
+ if (th->thread != NULL)
+ kthread_stop(th->thread);
+
+ printk(KERN_INFO "adt746x: Putting max temperatures back from "
+ "%d, %d, %d to %d, %d, %d\n",
+ th->limits[0], th->limits[1], th->limits[2],
+ th->initial_limits[0], th->initial_limits[1],
+ th->initial_limits[2]);
+
+ for (i = 0; i < 3; i++)
+ write_reg(th, LIMIT_REG[i], th->initial_limits[i]);
+
+ write_both_fan_speed(th, -1);
+
+ kfree(th);
+
+ return 0;
}
-static void thermostat_remove_files(void)
+static const struct i2c_device_id therm_adt746x_id[] = {
+ { "MAC,adt7460", ADT7460 },
+ { "MAC,adt7467", ADT7467 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, therm_adt746x_id);
+
+static struct i2c_driver thermostat_driver = {
+ .driver = {
+ .name = "therm_adt746x",
+ },
+ .probe = probe_thermostat,
+ .remove = remove_thermostat,
+ .id_table = therm_adt746x_id,
+};
+
+static int __init thermostat_init(void)
{
- if (of_dev) {
- device_remove_file(&of_dev->dev, &dev_attr_sensor1_temperature);
- device_remove_file(&of_dev->dev, &dev_attr_sensor2_temperature);
- device_remove_file(&of_dev->dev, &dev_attr_sensor1_limit);
- device_remove_file(&of_dev->dev, &dev_attr_sensor2_limit);
- device_remove_file(&of_dev->dev, &dev_attr_sensor1_location);
- device_remove_file(&of_dev->dev, &dev_attr_sensor2_location);
- device_remove_file(&of_dev->dev, &dev_attr_limit_adjust);
- device_remove_file(&of_dev->dev, &dev_attr_specified_fan_speed);
- device_remove_file(&of_dev->dev, &dev_attr_sensor1_fan_speed);
-
- if(therm_type == ADT7460)
- device_remove_file(&of_dev->dev,
- &dev_attr_sensor2_fan_speed);
+#ifndef CONFIG_I2C_POWERMAC
+ request_module("i2c-powermac");
+#endif
- }
+ return i2c_add_driver(&thermostat_driver);
}
-static void __exit
-thermostat_exit(void)
+static void __exit thermostat_exit(void)
{
i2c_del_driver(&thermostat_driver);
- of_device_unregister(of_dev);
}
module_init(thermostat_init);
diff --git a/drivers/macintosh/windfarm.h b/drivers/macintosh/windfarm.h
index 7a2482cc26a7..028cdac2d33d 100644
--- a/drivers/macintosh/windfarm.h
+++ b/drivers/macintosh/windfarm.h
@@ -17,7 +17,7 @@
#include <linux/device.h>
/* Display a 16.16 fixed point value */
-#define FIX32TOPRINT(f) ((f) >> 16),((((f) & 0xffff) * 1000) >> 16)
+#define FIX32TOPRINT(f) (((s32)(f)) >> 16),(((((s32)(f)) & 0xffff) * 1000) >> 16)
/*
* Control objects
@@ -35,12 +35,13 @@ struct wf_control_ops {
};
struct wf_control {
- struct list_head link;
- struct wf_control_ops *ops;
- char *name;
- int type;
- struct kref ref;
- struct device_attribute attr;
+ struct list_head link;
+ const struct wf_control_ops *ops;
+ const char *name;
+ int type;
+ struct kref ref;
+ struct device_attribute attr;
+ void *priv;
};
#define WF_CONTROL_TYPE_GENERIC 0
@@ -72,6 +73,26 @@ static inline int wf_control_set_min(struct wf_control *ct)
return ct->ops->set_value(ct, vmin);
}
+static inline int wf_control_set(struct wf_control *ct, s32 val)
+{
+ return ct->ops->set_value(ct, val);
+}
+
+static inline int wf_control_get(struct wf_control *ct, s32 *val)
+{
+ return ct->ops->get_value(ct, val);
+}
+
+static inline s32 wf_control_get_min(struct wf_control *ct)
+{
+ return ct->ops->get_min(ct);
+}
+
+static inline s32 wf_control_get_max(struct wf_control *ct)
+{
+ return ct->ops->get_max(ct);
+}
+
/*
* Sensor objects
*/
@@ -85,11 +106,12 @@ struct wf_sensor_ops {
};
struct wf_sensor {
- struct list_head link;
- struct wf_sensor_ops *ops;
- char *name;
- struct kref ref;
- struct device_attribute attr;
+ struct list_head link;
+ const struct wf_sensor_ops *ops;
+ const char *name;
+ struct kref ref;
+ struct device_attribute attr;
+ void *priv;
};
/* Same lifetime rules as controls */
@@ -99,6 +121,11 @@ extern struct wf_sensor * wf_find_sensor(const char *name);
extern int wf_get_sensor(struct wf_sensor *sr);
extern void wf_put_sensor(struct wf_sensor *sr);
+static inline int wf_sensor_get(struct wf_sensor *sr, s32 *val)
+{
+ return sr->ops->get_value(sr, val);
+}
+
/* For use by clients. Note that we are a bit racy here since
* notifier_block doesn't have a module owner field. I may fix
* it one day ...
diff --git a/drivers/macintosh/windfarm_ad7417_sensor.c b/drivers/macintosh/windfarm_ad7417_sensor.c
new file mode 100644
index 000000000000..ac3f243b9c5a
--- /dev/null
+++ b/drivers/macintosh/windfarm_ad7417_sensor.c
@@ -0,0 +1,347 @@
+/*
+ * Windfarm PowerMac thermal control. AD7417 sensors
+ *
+ * Copyright 2012 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * Released under the term of the GNU GPL v2.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/i2c.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+
+#include "windfarm.h"
+#include "windfarm_mpu.h"
+
+#define VERSION "1.0"
+
+struct wf_ad7417_priv {
+ struct kref ref;
+ struct i2c_client *i2c;
+ u8 config;
+ u8 cpu;
+ const struct mpu_data *mpu;
+ struct wf_sensor sensors[5];
+ struct mutex lock;
+};
+
+static int wf_ad7417_temp_get(struct wf_sensor *sr, s32 *value)
+{
+ struct wf_ad7417_priv *pv = sr->priv;
+ u8 buf[2];
+ s16 raw;
+ int rc;
+
+ *value = 0;
+ mutex_lock(&pv->lock);
+
+ /* Read temp register */
+ buf[0] = 0;
+ rc = i2c_master_send(pv->i2c, buf, 1);
+ if (rc < 0)
+ goto error;
+ rc = i2c_master_recv(pv->i2c, buf, 2);
+ if (rc < 0)
+ goto error;
+
+ /* Read a a 16-bit signed value */
+ raw = be16_to_cpup((__le16 *)buf);
+
+ /* Convert 8.8-bit to 16.16 fixed point */
+ *value = ((s32)raw) << 8;
+
+ mutex_unlock(&pv->lock);
+ return 0;
+
+error:
+ mutex_unlock(&pv->lock);
+ return -1;
+}
+
+/*
+ * Scaling factors for the AD7417 ADC converters (except
+ * for the CPU diode which is obtained from the EEPROM).
+ * Those values are obtained from the property list of
+ * the darwin driver
+ */
+#define ADC_12V_CURRENT_SCALE 0x0320 /* _AD2 */
+#define ADC_CPU_VOLTAGE_SCALE 0x00a0 /* _AD3 */
+#define ADC_CPU_CURRENT_SCALE 0x1f40 /* _AD4 */
+
+static void wf_ad7417_adc_convert(struct wf_ad7417_priv *pv,
+ int chan, s32 raw, s32 *value)
+{
+ switch(chan) {
+ case 1: /* Diode */
+ *value = (raw * (s32)pv->mpu->mdiode +
+ ((s32)pv->mpu->bdiode << 12)) >> 2;
+ break;
+ case 2: /* 12v current */
+ *value = raw * ADC_12V_CURRENT_SCALE;
+ break;
+ case 3: /* core voltage */
+ *value = raw * ADC_CPU_VOLTAGE_SCALE;
+ break;
+ case 4: /* core current */
+ *value = raw * ADC_CPU_CURRENT_SCALE;
+ break;
+ }
+}
+
+static int wf_ad7417_adc_get(struct wf_sensor *sr, s32 *value)
+{
+ struct wf_ad7417_priv *pv = sr->priv;
+ int chan = sr - pv->sensors;
+ int i, rc;
+ u8 buf[2];
+ u16 raw;
+
+ *value = 0;
+ mutex_lock(&pv->lock);
+ for (i = 0; i < 10; i++) {
+ /* Set channel */
+ buf[0] = 1;
+ buf[1] = (pv->config & 0x1f) | (chan << 5);
+ rc = i2c_master_send(pv->i2c, buf, 2);
+ if (rc < 0)
+ goto error;
+
+ /* Wait for conversion */
+ msleep(1);
+
+ /* Switch to data register */
+ buf[0] = 4;
+ rc = i2c_master_send(pv->i2c, buf, 1);
+ if (rc < 0)
+ goto error;
+
+ /* Read result */
+ rc = i2c_master_recv(pv->i2c, buf, 2);
+ if (rc < 0)
+ goto error;
+
+ /* Read a a 16-bit signed value */
+ raw = be16_to_cpup((__le16 *)buf) >> 6;
+ wf_ad7417_adc_convert(pv, chan, raw, value);
+
+ dev_vdbg(&pv->i2c->dev, "ADC chan %d [%s]"
+ " raw value: 0x%x, conv to: 0x%08x\n",
+ chan, sr->name, raw, *value);
+
+ mutex_unlock(&pv->lock);
+ return 0;
+
+ error:
+ dev_dbg(&pv->i2c->dev,
+ "Error reading ADC, try %d...\n", i);
+ if (i < 9)
+ msleep(10);
+ }
+ mutex_unlock(&pv->lock);
+ return -1;
+}
+
+static void wf_ad7417_release(struct kref *ref)
+{
+ struct wf_ad7417_priv *pv = container_of(ref,
+ struct wf_ad7417_priv, ref);
+ kfree(pv);
+}
+
+static void wf_ad7417_sensor_release(struct wf_sensor *sr)
+{
+ struct wf_ad7417_priv *pv = sr->priv;
+
+ kfree(sr->name);
+ kref_put(&pv->ref, wf_ad7417_release);
+}
+
+static const struct wf_sensor_ops wf_ad7417_temp_ops = {
+ .get_value = wf_ad7417_temp_get,
+ .release = wf_ad7417_sensor_release,
+ .owner = THIS_MODULE,
+};
+
+static const struct wf_sensor_ops wf_ad7417_adc_ops = {
+ .get_value = wf_ad7417_adc_get,
+ .release = wf_ad7417_sensor_release,
+ .owner = THIS_MODULE,
+};
+
+static void __devinit wf_ad7417_add_sensor(struct wf_ad7417_priv *pv,
+ int index, const char *name,
+ const struct wf_sensor_ops *ops)
+{
+ pv->sensors[index].name = kasprintf(GFP_KERNEL, "%s-%d", name, pv->cpu);
+ pv->sensors[index].priv = pv;
+ pv->sensors[index].ops = ops;
+ if (!wf_register_sensor(&pv->sensors[index]))
+ kref_get(&pv->ref);
+}
+
+static void __devinit wf_ad7417_init_chip(struct wf_ad7417_priv *pv)
+{
+ int rc;
+ u8 buf[2];
+ u8 config = 0;
+
+ /*
+ * Read ADC the configuration register and cache it. We
+ * also make sure Config2 contains proper values, I've seen
+ * cases where we got stale grabage in there, thus preventing
+ * proper reading of conv. values
+ */
+
+ /* Clear Config2 */
+ buf[0] = 5;
+ buf[1] = 0;
+ i2c_master_send(pv->i2c, buf, 2);
+
+ /* Read & cache Config1 */
+ buf[0] = 1;
+ rc = i2c_master_send(pv->i2c, buf, 1);
+ if (rc > 0) {
+ rc = i2c_master_recv(pv->i2c, buf, 1);
+ if (rc > 0) {
+ config = buf[0];
+
+ dev_dbg(&pv->i2c->dev, "ADC config reg: %02x\n",
+ config);
+
+ /* Disable shutdown mode */
+ config &= 0xfe;
+ buf[0] = 1;
+ buf[1] = config;
+ rc = i2c_master_send(pv->i2c, buf, 2);
+ }
+ }
+ if (rc <= 0)
+ dev_err(&pv->i2c->dev, "Error reading ADC config\n");
+
+ pv->config = config;
+}
+
+static int __devinit wf_ad7417_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct wf_ad7417_priv *pv;
+ const struct mpu_data *mpu;
+ const char *loc;
+ int cpu_nr;
+
+ loc = of_get_property(client->dev.of_node, "hwsensor-location", NULL);
+ if (!loc) {
+ dev_warn(&client->dev, "Missing hwsensor-location property!\n");
+ return -ENXIO;
+ }
+
+ /*
+ * Identify which CPU we belong to by looking at the first entry
+ * in the hwsensor-location list
+ */
+ if (!strncmp(loc, "CPU A", 5))
+ cpu_nr = 0;
+ else if (!strncmp(loc, "CPU B", 5))
+ cpu_nr = 1;
+ else {
+ pr_err("wf_ad7417: Can't identify location %s\n", loc);
+ return -ENXIO;
+ }
+ mpu = wf_get_mpu(cpu_nr);
+ if (!mpu) {
+ dev_err(&client->dev, "Failed to retrieve MPU data\n");
+ return -ENXIO;
+ }
+
+ pv = kzalloc(sizeof(struct wf_ad7417_priv), GFP_KERNEL);
+ if (pv == NULL)
+ return -ENODEV;
+
+ kref_init(&pv->ref);
+ mutex_init(&pv->lock);
+ pv->i2c = client;
+ pv->cpu = cpu_nr;
+ pv->mpu = mpu;
+ dev_set_drvdata(&client->dev, pv);
+
+ /* Initialize the chip */
+ wf_ad7417_init_chip(pv);
+
+ /*
+ * We cannot rely on Apple device-tree giving us child
+ * node with the names of the individual sensors so we
+ * just hard code what we know about them
+ */
+ wf_ad7417_add_sensor(pv, 0, "cpu-amb-temp", &wf_ad7417_temp_ops);
+ wf_ad7417_add_sensor(pv, 1, "cpu-diode-temp", &wf_ad7417_adc_ops);
+ wf_ad7417_add_sensor(pv, 2, "cpu-12v-current", &wf_ad7417_adc_ops);
+ wf_ad7417_add_sensor(pv, 3, "cpu-voltage", &wf_ad7417_adc_ops);
+ wf_ad7417_add_sensor(pv, 4, "cpu-current", &wf_ad7417_adc_ops);
+
+ return 0;
+}
+
+static int __devexit wf_ad7417_remove(struct i2c_client *client)
+{
+ struct wf_ad7417_priv *pv = dev_get_drvdata(&client->dev);
+ int i;
+
+ /* Mark client detached */
+ pv->i2c = NULL;
+
+ /* Release sensor */
+ for (i = 0; i < 5; i++)
+ wf_unregister_sensor(&pv->sensors[i]);
+
+ kref_put(&pv->ref, wf_ad7417_release);
+
+ return 0;
+}
+
+static const struct i2c_device_id wf_ad7417_id[] = {
+ { "MAC,ad7417", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wf_ad7417_id);
+
+static struct i2c_driver wf_ad7417_driver = {
+ .driver = {
+ .name = "wf_ad7417",
+ },
+ .probe = wf_ad7417_probe,
+ .remove = wf_ad7417_remove,
+ .id_table = wf_ad7417_id,
+};
+
+static int __devinit wf_ad7417_init(void)
+{
+ /* This is only supported on these machines */
+ if (!of_machine_is_compatible("PowerMac7,2") &&
+ !of_machine_is_compatible("PowerMac7,3") &&
+ !of_machine_is_compatible("RackMac3,1"))
+ return -ENODEV;
+
+ return i2c_add_driver(&wf_ad7417_driver);
+}
+
+static void __devexit wf_ad7417_exit(void)
+{
+ i2c_del_driver(&wf_ad7417_driver);
+}
+
+module_init(wf_ad7417_init);
+module_exit(wf_ad7417_exit);
+
+MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
+MODULE_DESCRIPTION("ad7417 sensor driver for PowerMacs");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index ce8897933a84..3ee198b65843 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -164,13 +164,27 @@ static ssize_t wf_show_control(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
+ const char *typestr;
s32 val = 0;
int err;
err = ctrl->ops->get_value(ctrl, &val);
- if (err < 0)
+ if (err < 0) {
+ if (err == -EFAULT)
+ return sprintf(buf, "<HW FAULT>\n");
return err;
- return sprintf(buf, "%d\n", val);
+ }
+ switch(ctrl->type) {
+ case WF_CONTROL_RPM_FAN:
+ typestr = " RPM";
+ break;
+ case WF_CONTROL_PWM_FAN:
+ typestr = " %";
+ break;
+ default:
+ typestr = "";
+ }
+ return sprintf(buf, "%d%s\n", val, typestr);
}
/* This is really only for debugging... */
@@ -470,11 +484,6 @@ static int __init windfarm_core_init(void)
{
DBG("wf: core loaded\n");
- /* Don't register on old machines that use therm_pm72 for now */
- if (of_machine_is_compatible("PowerMac7,2") ||
- of_machine_is_compatible("PowerMac7,3") ||
- of_machine_is_compatible("RackMac3,1"))
- return -ENODEV;
platform_device_register(&wf_platform_device);
return 0;
}
diff --git a/drivers/macintosh/windfarm_cpufreq_clamp.c b/drivers/macintosh/windfarm_cpufreq_clamp.c
index 1a77a7c97d0e..72d1fdfe02a5 100644
--- a/drivers/macintosh/windfarm_cpufreq_clamp.c
+++ b/drivers/macintosh/windfarm_cpufreq_clamp.c
@@ -75,12 +75,6 @@ static int __init wf_cpufreq_clamp_init(void)
{
struct wf_control *clamp;
- /* Don't register on old machines that use therm_pm72 for now */
- if (of_machine_is_compatible("PowerMac7,2") ||
- of_machine_is_compatible("PowerMac7,3") ||
- of_machine_is_compatible("RackMac3,1"))
- return -ENODEV;
-
clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL);
if (clamp == NULL)
return -ENOMEM;
diff --git a/drivers/macintosh/windfarm_fcu_controls.c b/drivers/macintosh/windfarm_fcu_controls.c
new file mode 100644
index 000000000000..b3411edb324b
--- /dev/null
+++ b/drivers/macintosh/windfarm_fcu_controls.c
@@ -0,0 +1,613 @@
+/*
+ * Windfarm PowerMac thermal control. FCU fan control
+ *
+ * Copyright 2012 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * Released under the term of the GNU GPL v2.
+ */
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/i2c.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+
+#include "windfarm.h"
+#include "windfarm_mpu.h"
+
+#define VERSION "1.0"
+
+#ifdef DEBUG
+#define DBG(args...) printk(args)
+#else
+#define DBG(args...) do { } while(0)
+#endif
+
+/*
+ * This option is "weird" :) Basically, if you define this to 1
+ * the control loop for the RPMs fans (not PWMs) will apply the
+ * correction factor obtained from the PID to the actual RPM
+ * speed read from the FCU.
+ *
+ * If you define the below constant to 0, then it will be
+ * applied to the setpoint RPM speed, that is basically the
+ * speed we proviously "asked" for.
+ *
+ * I'm using 0 for now which is what therm_pm72 used to do and
+ * what Darwin -apparently- does based on observed behaviour.
+ */
+#define RPM_PID_USE_ACTUAL_SPEED 0
+
+/* Default min/max for pumps */
+#define CPU_PUMP_OUTPUT_MAX 3200
+#define CPU_PUMP_OUTPUT_MIN 1250
+
+#define FCU_FAN_RPM 0
+#define FCU_FAN_PWM 1
+
+struct wf_fcu_priv {
+ struct kref ref;
+ struct i2c_client *i2c;
+ struct mutex lock;
+ struct list_head fan_list;
+ int rpm_shift;
+};
+
+struct wf_fcu_fan {
+ struct list_head link;
+ int id;
+ s32 min, max, target;
+ struct wf_fcu_priv *fcu_priv;
+ struct wf_control ctrl;
+};
+
+static void wf_fcu_release(struct kref *ref)
+{
+ struct wf_fcu_priv *pv = container_of(ref, struct wf_fcu_priv, ref);
+
+ kfree(pv);
+}
+
+static void wf_fcu_fan_release(struct wf_control *ct)
+{
+ struct wf_fcu_fan *fan = ct->priv;
+
+ kref_put(&fan->fcu_priv->ref, wf_fcu_release);
+ kfree(fan);
+}
+
+static int wf_fcu_read_reg(struct wf_fcu_priv *pv, int reg,
+ unsigned char *buf, int nb)
+{
+ int tries, nr, nw;
+
+ mutex_lock(&pv->lock);
+
+ buf[0] = reg;
+ tries = 0;
+ for (;;) {
+ nw = i2c_master_send(pv->i2c, buf, 1);
+ if (nw > 0 || (nw < 0 && nw != -EIO) || tries >= 100)
+ break;
+ msleep(10);
+ ++tries;
+ }
+ if (nw <= 0) {
+ pr_err("Failure writing address to FCU: %d", nw);
+ nr = nw;
+ goto bail;
+ }
+ tries = 0;
+ for (;;) {
+ nr = i2c_master_recv(pv->i2c, buf, nb);
+ if (nr > 0 || (nr < 0 && nr != -ENODEV) || tries >= 100)
+ break;
+ msleep(10);
+ ++tries;
+ }
+ if (nr <= 0)
+ pr_err("wf_fcu: Failure reading data from FCU: %d", nw);
+ bail:
+ mutex_unlock(&pv->lock);
+ return nr;
+}
+
+static int wf_fcu_write_reg(struct wf_fcu_priv *pv, int reg,
+ const unsigned char *ptr, int nb)
+{
+ int tries, nw;
+ unsigned char buf[16];
+
+ buf[0] = reg;
+ memcpy(buf+1, ptr, nb);
+ ++nb;
+ tries = 0;
+ for (;;) {
+ nw = i2c_master_send(pv->i2c, buf, nb);
+ if (nw > 0 || (nw < 0 && nw != -EIO) || tries >= 100)
+ break;
+ msleep(10);
+ ++tries;
+ }
+ if (nw < 0)
+ pr_err("wf_fcu: Failure writing to FCU: %d", nw);
+ return nw;
+}
+
+static int wf_fcu_fan_set_rpm(struct wf_control *ct, s32 value)
+{
+ struct wf_fcu_fan *fan = ct->priv;
+ struct wf_fcu_priv *pv = fan->fcu_priv;
+ int rc, shift = pv->rpm_shift;
+ unsigned char buf[2];
+
+ if (value < fan->min)
+ value = fan->min;
+ if (value > fan->max)
+ value = fan->max;
+
+ fan->target = value;
+
+ buf[0] = value >> (8 - shift);
+ buf[1] = value << shift;
+ rc = wf_fcu_write_reg(pv, 0x10 + (fan->id * 2), buf, 2);
+ if (rc < 0)
+ return -EIO;
+ return 0;
+}
+
+static int wf_fcu_fan_get_rpm(struct wf_control *ct, s32 *value)
+{
+ struct wf_fcu_fan *fan = ct->priv;
+ struct wf_fcu_priv *pv = fan->fcu_priv;
+ int rc, reg_base, shift = pv->rpm_shift;
+ unsigned char failure;
+ unsigned char active;
+ unsigned char buf[2];
+
+ rc = wf_fcu_read_reg(pv, 0xb, &failure, 1);
+ if (rc != 1)
+ return -EIO;
+ if ((failure & (1 << fan->id)) != 0)
+ return -EFAULT;
+ rc = wf_fcu_read_reg(pv, 0xd, &active, 1);
+ if (rc != 1)
+ return -EIO;
+ if ((active & (1 << fan->id)) == 0)
+ return -ENXIO;
+
+ /* Programmed value or real current speed */
+#if RPM_PID_USE_ACTUAL_SPEED
+ reg_base = 0x11;
+#else
+ reg_base = 0x10;
+#endif
+ rc = wf_fcu_read_reg(pv, reg_base + (fan->id * 2), buf, 2);
+ if (rc != 2)
+ return -EIO;
+
+ *value = (buf[0] << (8 - shift)) | buf[1] >> shift;
+
+ return 0;
+}
+
+static int wf_fcu_fan_set_pwm(struct wf_control *ct, s32 value)
+{
+ struct wf_fcu_fan *fan = ct->priv;
+ struct wf_fcu_priv *pv = fan->fcu_priv;
+ unsigned char buf[2];
+ int rc;
+
+ if (value < fan->min)
+ value = fan->min;
+ if (value > fan->max)
+ value = fan->max;
+
+ fan->target = value;
+
+ value = (value * 2559) / 1000;
+ buf[0] = value;
+ rc = wf_fcu_write_reg(pv, 0x30 + (fan->id * 2), buf, 1);
+ if (rc < 0)
+ return -EIO;
+ return 0;
+}
+
+static int wf_fcu_fan_get_pwm(struct wf_control *ct, s32 *value)
+{
+ struct wf_fcu_fan *fan = ct->priv;
+ struct wf_fcu_priv *pv = fan->fcu_priv;
+ unsigned char failure;
+ unsigned char active;
+ unsigned char buf[2];
+ int rc;
+
+ rc = wf_fcu_read_reg(pv, 0x2b, &failure, 1);
+ if (rc != 1)
+ return -EIO;
+ if ((failure & (1 << fan->id)) != 0)
+ return -EFAULT;
+ rc = wf_fcu_read_reg(pv, 0x2d, &active, 1);
+ if (rc != 1)
+ return -EIO;
+ if ((active & (1 << fan->id)) == 0)
+ return -ENXIO;
+
+ rc = wf_fcu_read_reg(pv, 0x30 + (fan->id * 2), buf, 1);
+ if (rc != 1)
+ return -EIO;
+
+ *value = (((s32)buf[0]) * 1000) / 2559;
+
+ return 0;
+}
+
+static s32 wf_fcu_fan_min(struct wf_control *ct)
+{
+ struct wf_fcu_fan *fan = ct->priv;
+
+ return fan->min;
+}
+
+static s32 wf_fcu_fan_max(struct wf_control *ct)
+{
+ struct wf_fcu_fan *fan = ct->priv;
+
+ return fan->max;
+}
+
+static const struct wf_control_ops wf_fcu_fan_rpm_ops = {
+ .set_value = wf_fcu_fan_set_rpm,
+ .get_value = wf_fcu_fan_get_rpm,
+ .get_min = wf_fcu_fan_min,
+ .get_max = wf_fcu_fan_max,
+ .release = wf_fcu_fan_release,
+ .owner = THIS_MODULE,
+};
+
+static const struct wf_control_ops wf_fcu_fan_pwm_ops = {
+ .set_value = wf_fcu_fan_set_pwm,
+ .get_value = wf_fcu_fan_get_pwm,
+ .get_min = wf_fcu_fan_min,
+ .get_max = wf_fcu_fan_max,
+ .release = wf_fcu_fan_release,
+ .owner = THIS_MODULE,
+};
+
+static void __devinit wf_fcu_get_pump_minmax(struct wf_fcu_fan *fan)
+{
+ const struct mpu_data *mpu = wf_get_mpu(0);
+ u16 pump_min = 0, pump_max = 0xffff;
+ u16 tmp[4];
+
+ /* Try to fetch pumps min/max infos from eeprom */
+ if (mpu) {
+ memcpy(&tmp, mpu->processor_part_num, 8);
+ if (tmp[0] != 0xffff && tmp[1] != 0xffff) {
+ pump_min = max(pump_min, tmp[0]);
+ pump_max = min(pump_max, tmp[1]);
+ }
+ if (tmp[2] != 0xffff && tmp[3] != 0xffff) {
+ pump_min = max(pump_min, tmp[2]);
+ pump_max = min(pump_max, tmp[3]);
+ }
+ }
+
+ /* Double check the values, this _IS_ needed as the EEPROM on
+ * some dual 2.5Ghz G5s seem, at least, to have both min & max
+ * same to the same value ... (grrrr)
+ */
+ if (pump_min == pump_max || pump_min == 0 || pump_max == 0xffff) {
+ pump_min = CPU_PUMP_OUTPUT_MIN;
+ pump_max = CPU_PUMP_OUTPUT_MAX;
+ }
+
+ fan->min = pump_min;
+ fan->max = pump_max;
+
+ DBG("wf_fcu: pump min/max for %s set to: [%d..%d] RPM\n",
+ fan->ctrl.name, pump_min, pump_max);
+}
+
+static void __devinit wf_fcu_get_rpmfan_minmax(struct wf_fcu_fan *fan)
+{
+ struct wf_fcu_priv *pv = fan->fcu_priv;
+ const struct mpu_data *mpu0 = wf_get_mpu(0);
+ const struct mpu_data *mpu1 = wf_get_mpu(1);
+
+ /* Default */
+ fan->min = 2400 >> pv->rpm_shift;
+ fan->max = 56000 >> pv->rpm_shift;
+
+ /* CPU fans have min/max in MPU */
+ if (mpu0 && !strcmp(fan->ctrl.name, "cpu-front-fan-0")) {
+ fan->min = max(fan->min, (s32)mpu0->rminn_intake_fan);
+ fan->max = min(fan->max, (s32)mpu0->rmaxn_intake_fan);
+ goto bail;
+ }
+ if (mpu1 && !strcmp(fan->ctrl.name, "cpu-front-fan-1")) {
+ fan->min = max(fan->min, (s32)mpu1->rminn_intake_fan);
+ fan->max = min(fan->max, (s32)mpu1->rmaxn_intake_fan);
+ goto bail;
+ }
+ if (mpu0 && !strcmp(fan->ctrl.name, "cpu-rear-fan-0")) {
+ fan->min = max(fan->min, (s32)mpu0->rminn_exhaust_fan);
+ fan->max = min(fan->max, (s32)mpu0->rmaxn_exhaust_fan);
+ goto bail;
+ }
+ if (mpu1 && !strcmp(fan->ctrl.name, "cpu-rear-fan-1")) {
+ fan->min = max(fan->min, (s32)mpu1->rminn_exhaust_fan);
+ fan->max = min(fan->max, (s32)mpu1->rmaxn_exhaust_fan);
+ goto bail;
+ }
+ /* Rackmac variants, we just use mpu0 intake */
+ if (!strncmp(fan->ctrl.name, "cpu-fan", 7)) {
+ fan->min = max(fan->min, (s32)mpu0->rminn_intake_fan);
+ fan->max = min(fan->max, (s32)mpu0->rmaxn_intake_fan);
+ goto bail;
+ }
+ bail:
+ DBG("wf_fcu: fan min/max for %s set to: [%d..%d] RPM\n",
+ fan->ctrl.name, fan->min, fan->max);
+}
+
+static void __devinit wf_fcu_add_fan(struct wf_fcu_priv *pv,
+ const char *name,
+ int type, int id)
+{
+ struct wf_fcu_fan *fan;
+
+ fan = kzalloc(sizeof(*fan), GFP_KERNEL);
+ if (!fan)
+ return;
+ fan->fcu_priv = pv;
+ fan->id = id;
+ fan->ctrl.name = name;
+ fan->ctrl.priv = fan;
+
+ /* min/max is oddball but the code comes from
+ * therm_pm72 which seems to work so ...
+ */
+ if (type == FCU_FAN_RPM) {
+ if (!strncmp(name, "cpu-pump", strlen("cpu-pump")))
+ wf_fcu_get_pump_minmax(fan);
+ else
+ wf_fcu_get_rpmfan_minmax(fan);
+ fan->ctrl.type = WF_CONTROL_RPM_FAN;
+ fan->ctrl.ops = &wf_fcu_fan_rpm_ops;
+ } else {
+ fan->min = 10;
+ fan->max = 100;
+ fan->ctrl.type = WF_CONTROL_PWM_FAN;
+ fan->ctrl.ops = &wf_fcu_fan_pwm_ops;
+ }
+
+ if (wf_register_control(&fan->ctrl)) {
+ pr_err("wf_fcu: Failed to register fan %s\n", name);
+ kfree(fan);
+ return;
+ }
+ list_add(&fan->link, &pv->fan_list);
+ kref_get(&pv->ref);
+}
+
+static void __devinit wf_fcu_lookup_fans(struct wf_fcu_priv *pv)
+{
+ /* Translation of device-tree location properties to
+ * windfarm fan names
+ */
+ static const struct {
+ const char *dt_name; /* Device-tree name */
+ const char *ct_name; /* Control name */
+ } loc_trans[] = {
+ { "BACKSIDE", "backside-fan", },
+ { "SYS CTRLR FAN", "backside-fan", },
+ { "DRIVE BAY", "drive-bay-fan", },
+ { "SLOT", "slots-fan", },
+ { "PCI FAN", "slots-fan", },
+ { "CPU A INTAKE", "cpu-front-fan-0", },
+ { "CPU A EXHAUST", "cpu-rear-fan-0", },
+ { "CPU B INTAKE", "cpu-front-fan-1", },
+ { "CPU B EXHAUST", "cpu-rear-fan-1", },
+ { "CPU A PUMP", "cpu-pump-0", },
+ { "CPU B PUMP", "cpu-pump-1", },
+ { "CPU A 1", "cpu-fan-a-0", },
+ { "CPU A 2", "cpu-fan-b-0", },
+ { "CPU A 3", "cpu-fan-c-0", },
+ { "CPU B 1", "cpu-fan-a-1", },
+ { "CPU B 2", "cpu-fan-b-1", },
+ { "CPU B 3", "cpu-fan-c-1", },
+ };
+ struct device_node *np = NULL, *fcu = pv->i2c->dev.of_node;
+ int i;
+
+ DBG("Looking up FCU controls in device-tree...\n");
+
+ while ((np = of_get_next_child(fcu, np)) != NULL) {
+ int id, type = -1;
+ const char *loc;
+ const char *name;
+ const u32 *reg;
+
+ DBG(" control: %s, type: %s\n", np->name, np->type);
+
+ /* Detect control type */
+ if (!strcmp(np->type, "fan-rpm-control") ||
+ !strcmp(np->type, "fan-rpm"))
+ type = FCU_FAN_RPM;
+ if (!strcmp(np->type, "fan-pwm-control") ||
+ !strcmp(np->type, "fan-pwm"))
+ type = FCU_FAN_PWM;
+ /* Only care about fans for now */
+ if (type == -1)
+ continue;
+
+ /* Lookup for a matching location */
+ loc = of_get_property(np, "location", NULL);
+ reg = of_get_property(np, "reg", NULL);
+ if (loc == NULL || reg == NULL)
+ continue;
+ DBG(" matching location: %s, reg: 0x%08x\n", loc, *reg);
+
+ for (i = 0; i < ARRAY_SIZE(loc_trans); i++) {
+ if (strncmp(loc, loc_trans[i].dt_name,
+ strlen(loc_trans[i].dt_name)))
+ continue;
+ name = loc_trans[i].ct_name;
+
+ DBG(" location match, name: %s\n", name);
+
+ if (type == FCU_FAN_RPM)
+ id = ((*reg) - 0x10) / 2;
+ else
+ id = ((*reg) - 0x30) / 2;
+ if (id > 7) {
+ pr_warning("wf_fcu: Can't parse "
+ "fan ID in device-tree for %s\n",
+ np->full_name);
+ break;
+ }
+ wf_fcu_add_fan(pv, name, type, id);
+ break;
+ }
+ }
+}
+
+static void __devinit wf_fcu_default_fans(struct wf_fcu_priv *pv)
+{
+ /* We only support the default fans for PowerMac7,2 */
+ if (!of_machine_is_compatible("PowerMac7,2"))
+ return;
+
+ wf_fcu_add_fan(pv, "backside-fan", FCU_FAN_PWM, 1);
+ wf_fcu_add_fan(pv, "drive-bay-fan", FCU_FAN_RPM, 2);
+ wf_fcu_add_fan(pv, "slots-fan", FCU_FAN_PWM, 2);
+ wf_fcu_add_fan(pv, "cpu-front-fan-0", FCU_FAN_RPM, 3);
+ wf_fcu_add_fan(pv, "cpu-rear-fan-0", FCU_FAN_RPM, 4);
+ wf_fcu_add_fan(pv, "cpu-front-fan-1", FCU_FAN_RPM, 5);
+ wf_fcu_add_fan(pv, "cpu-rear-fan-1", FCU_FAN_RPM, 6);
+}
+
+static int __devinit wf_fcu_init_chip(struct wf_fcu_priv *pv)
+{
+ unsigned char buf = 0xff;
+ int rc;
+
+ rc = wf_fcu_write_reg(pv, 0xe, &buf, 1);
+ if (rc < 0)
+ return -EIO;
+ rc = wf_fcu_write_reg(pv, 0x2e, &buf, 1);
+ if (rc < 0)
+ return -EIO;
+ rc = wf_fcu_read_reg(pv, 0, &buf, 1);
+ if (rc < 0)
+ return -EIO;
+ pv->rpm_shift = (buf == 1) ? 2 : 3;
+
+ pr_debug("wf_fcu: FCU Initialized, RPM fan shift is %d\n",
+ pv->rpm_shift);
+
+ return 0;
+}
+
+static int __devinit wf_fcu_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct wf_fcu_priv *pv;
+
+ pv = kzalloc(sizeof(*pv), GFP_KERNEL);
+ if (!pv)
+ return -ENOMEM;
+
+ kref_init(&pv->ref);
+ mutex_init(&pv->lock);
+ INIT_LIST_HEAD(&pv->fan_list);
+ pv->i2c = client;
+
+ /*
+ * First we must start the FCU which will query the
+ * shift value to apply to RPMs
+ */
+ if (wf_fcu_init_chip(pv)) {
+ pr_err("wf_fcu: Initialization failed !\n");
+ kfree(pv);
+ return -ENXIO;
+ }
+
+ /* First lookup fans in the device-tree */
+ wf_fcu_lookup_fans(pv);
+
+ /*
+ * Older machines don't have the device-tree entries
+ * we are looking for, just hard code the list
+ */
+ if (list_empty(&pv->fan_list))
+ wf_fcu_default_fans(pv);
+
+ /* Still no fans ? FAIL */
+ if (list_empty(&pv->fan_list)) {
+ pr_err("wf_fcu: Failed to find fans for your machine\n");
+ kfree(pv);
+ return -ENODEV;
+ }
+
+ dev_set_drvdata(&client->dev, pv);
+
+ return 0;
+}
+
+static int __devexit wf_fcu_remove(struct i2c_client *client)
+{
+ struct wf_fcu_priv *pv = dev_get_drvdata(&client->dev);
+ struct wf_fcu_fan *fan;
+
+ while (!list_empty(&pv->fan_list)) {
+ fan = list_first_entry(&pv->fan_list, struct wf_fcu_fan, link);
+ list_del(&fan->link);
+ wf_unregister_control(&fan->ctrl);
+ }
+ kref_put(&pv->ref, wf_fcu_release);
+ return 0;
+}
+
+static const struct i2c_device_id wf_fcu_id[] = {
+ { "MAC,fcu", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wf_fcu_id);
+
+static struct i2c_driver wf_fcu_driver = {
+ .driver = {
+ .name = "wf_fcu",
+ },
+ .probe = wf_fcu_probe,
+ .remove = wf_fcu_remove,
+ .id_table = wf_fcu_id,
+};
+
+static int __init wf_fcu_init(void)
+{
+ return i2c_add_driver(&wf_fcu_driver);
+}
+
+static void __exit wf_fcu_exit(void)
+{
+ i2c_del_driver(&wf_fcu_driver);
+}
+
+
+module_init(wf_fcu_init);
+module_exit(wf_fcu_exit);
+
+MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
+MODULE_DESCRIPTION("FCU control objects for PowerMacs thermal control");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index 4d6a90a1372b..b0c2d3695b34 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -23,7 +23,7 @@
#include "windfarm.h"
-#define VERSION "0.2"
+#define VERSION "1.0"
#undef DEBUG
@@ -36,8 +36,8 @@
struct wf_lm75_sensor {
int ds1775 : 1;
int inited : 1;
- struct i2c_client *i2c;
- struct wf_sensor sens;
+ struct i2c_client *i2c;
+ struct wf_sensor sens;
};
#define wf_to_lm75(c) container_of(c, struct wf_lm75_sensor, sens)
@@ -90,40 +90,19 @@ static struct wf_sensor_ops wf_lm75_ops = {
static int wf_lm75_probe(struct i2c_client *client,
const struct i2c_device_id *id)
-{
+{
struct wf_lm75_sensor *lm;
- int rc;
-
- lm = kzalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL);
- if (lm == NULL)
- return -ENODEV;
-
- lm->inited = 0;
- lm->ds1775 = id->driver_data;
- lm->i2c = client;
- lm->sens.name = client->dev.platform_data;
- lm->sens.ops = &wf_lm75_ops;
- i2c_set_clientdata(client, lm);
-
- rc = wf_register_sensor(&lm->sens);
- if (rc)
- kfree(lm);
-
- return rc;
-}
-
-static struct i2c_driver wf_lm75_driver;
-
-static struct i2c_client *wf_lm75_create(struct i2c_adapter *adapter,
- u8 addr, int ds1775,
- const char *loc)
-{
- struct i2c_board_info info;
- struct i2c_client *client;
- char *name;
+ int rc, ds1775 = id->driver_data;
+ const char *name, *loc;
DBG("wf_lm75: creating %s device at address 0x%02x\n",
- ds1775 ? "ds1775" : "lm75", addr);
+ ds1775 ? "ds1775" : "lm75", client->addr);
+
+ loc = of_get_property(client->dev.of_node, "hwsensor-location", NULL);
+ if (!loc) {
+ dev_warn(&client->dev, "Missing hwsensor-location property!\n");
+ return -ENXIO;
+ }
/* Usual rant about sensor names not beeing very consistent in
* the device-tree, oh well ...
@@ -137,68 +116,31 @@ static struct i2c_client *wf_lm75_create(struct i2c_adapter *adapter,
name = "optical-drive-temp";
else if (!strcmp(loc, "HD Temp"))
name = "hard-drive-temp";
+ else if (!strcmp(loc, "PCI SLOTS"))
+ name = "slots-temp";
+ else if (!strcmp(loc, "CPU A INLET"))
+ name = "cpu-inlet-temp-0";
+ else if (!strcmp(loc, "CPU B INLET"))
+ name = "cpu-inlet-temp-1";
else
- goto fail;
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = (addr >> 1) & 0x7f;
- info.platform_data = name;
- strlcpy(info.type, ds1775 ? "wf_ds1775" : "wf_lm75", I2C_NAME_SIZE);
-
- client = i2c_new_device(adapter, &info);
- if (client == NULL) {
- printk(KERN_ERR "windfarm: failed to attach %s %s to i2c\n",
- ds1775 ? "ds1775" : "lm75", name);
- goto fail;
- }
-
- /*
- * Let i2c-core delete that device on driver removal.
- * This is safe because i2c-core holds the core_lock mutex for us.
- */
- list_add_tail(&client->detected, &wf_lm75_driver.clients);
- return client;
- fail:
- return NULL;
-}
-
-static int wf_lm75_attach(struct i2c_adapter *adapter)
-{
- struct device_node *busnode, *dev;
- struct pmac_i2c_bus *bus;
+ return -ENXIO;
+
- DBG("wf_lm75: adapter %s detected\n", adapter->name);
-
- bus = pmac_i2c_adapter_to_bus(adapter);
- if (bus == NULL)
+ lm = kzalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL);
+ if (lm == NULL)
return -ENODEV;
- busnode = pmac_i2c_get_bus_node(bus);
- DBG("wf_lm75: bus found, looking for device...\n");
-
- /* Now look for lm75(s) in there */
- for (dev = NULL;
- (dev = of_get_next_child(busnode, dev)) != NULL;) {
- const char *loc =
- of_get_property(dev, "hwsensor-location", NULL);
- u8 addr;
+ lm->inited = 0;
+ lm->ds1775 = ds1775;
+ lm->i2c = client;
+ lm->sens.name = (char *)name; /* XXX fix constness in structure */
+ lm->sens.ops = &wf_lm75_ops;
+ i2c_set_clientdata(client, lm);
- /* We must re-match the adapter in order to properly check
- * the channel on multibus setups
- */
- if (!pmac_i2c_match_adapter(dev, adapter))
- continue;
- addr = pmac_i2c_get_dev_addr(dev);
- if (loc == NULL || addr == 0)
- continue;
- /* real lm75 */
- if (of_device_is_compatible(dev, "lm75"))
- wf_lm75_create(adapter, addr, 0, loc);
- /* ds1775 (compatible, better resolution */
- else if (of_device_is_compatible(dev, "ds1775"))
- wf_lm75_create(adapter, addr, 1, loc);
- }
- return 0;
+ rc = wf_register_sensor(&lm->sens);
+ if (rc)
+ kfree(lm);
+ return rc;
}
static int wf_lm75_remove(struct i2c_client *client)
@@ -217,16 +159,16 @@ static int wf_lm75_remove(struct i2c_client *client)
}
static const struct i2c_device_id wf_lm75_id[] = {
- { "wf_lm75", 0 },
- { "wf_ds1775", 1 },
+ { "MAC,lm75", 0 },
+ { "MAC,ds1775", 1 },
{ }
};
+MODULE_DEVICE_TABLE(i2c, wf_lm75_id);
static struct i2c_driver wf_lm75_driver = {
.driver = {
.name = "wf_lm75",
},
- .attach_adapter = wf_lm75_attach,
.probe = wf_lm75_probe,
.remove = wf_lm75_remove,
.id_table = wf_lm75_id,
@@ -234,11 +176,6 @@ static struct i2c_driver wf_lm75_driver = {
static int __init wf_lm75_sensor_init(void)
{
- /* Don't register on old machines that use therm_pm72 for now */
- if (of_machine_is_compatible("PowerMac7,2") ||
- of_machine_is_compatible("PowerMac7,3") ||
- of_machine_is_compatible("RackMac3,1"))
- return -ENODEV;
return i2c_add_driver(&wf_lm75_driver);
}
diff --git a/drivers/macintosh/windfarm_lm87_sensor.c b/drivers/macintosh/windfarm_lm87_sensor.c
new file mode 100644
index 000000000000..c071aab79dd1
--- /dev/null
+++ b/drivers/macintosh/windfarm_lm87_sensor.c
@@ -0,0 +1,201 @@
+/*
+ * Windfarm PowerMac thermal control. LM87 sensor
+ *
+ * Copyright 2012 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * Released under the term of the GNU GPL v2.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/i2c.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+#include <asm/pmac_low_i2c.h>
+
+#include "windfarm.h"
+
+#define VERSION "1.0"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(args...) printk(args)
+#else
+#define DBG(args...) do { } while(0)
+#endif
+
+struct wf_lm87_sensor {
+ struct i2c_client *i2c;
+ struct wf_sensor sens;
+};
+#define wf_to_lm87(c) container_of(c, struct wf_lm87_sensor, sens)
+
+
+static int wf_lm87_read_reg(struct i2c_client *chip, int reg)
+{
+ int rc, tries = 0;
+ u8 buf;
+
+ for (;;) {
+ /* Set address */
+ buf = (u8)reg;
+ rc = i2c_master_send(chip, &buf, 1);
+ if (rc <= 0)
+ goto error;
+ rc = i2c_master_recv(chip, &buf, 1);
+ if (rc <= 0)
+ goto error;
+ return (int)buf;
+ error:
+ DBG("wf_lm87: Error reading LM87, retrying...\n");
+ if (++tries > 10) {
+ printk(KERN_ERR "wf_lm87: Error reading LM87 !\n");
+ return -EIO;
+ }
+ msleep(10);
+ }
+}
+
+static int wf_lm87_get(struct wf_sensor *sr, s32 *value)
+{
+ struct wf_lm87_sensor *lm = sr->priv;
+ s32 temp;
+
+ if (lm->i2c == NULL)
+ return -ENODEV;
+
+#define LM87_INT_TEMP 0x27
+
+ /* Read temperature register */
+ temp = wf_lm87_read_reg(lm->i2c, LM87_INT_TEMP);
+ if (temp < 0)
+ return temp;
+ *value = temp << 16;
+
+ return 0;
+}
+
+static void wf_lm87_release(struct wf_sensor *sr)
+{
+ struct wf_lm87_sensor *lm = wf_to_lm87(sr);
+
+ kfree(lm);
+}
+
+static struct wf_sensor_ops wf_lm87_ops = {
+ .get_value = wf_lm87_get,
+ .release = wf_lm87_release,
+ .owner = THIS_MODULE,
+};
+
+static int wf_lm87_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct wf_lm87_sensor *lm;
+ const char *name = NULL, *loc;
+ struct device_node *np = NULL;
+ int rc;
+
+ /*
+ * The lm87 contains a whole pile of sensors, additionally,
+ * the Xserve G5 has several lm87's. However, for now we only
+ * care about the internal temperature sensor
+ */
+ while ((np = of_get_next_child(client->dev.of_node, np)) != NULL) {
+ if (strcmp(np->name, "int-temp"))
+ continue;
+ loc = of_get_property(np, "location", NULL);
+ if (!loc)
+ continue;
+ if (strstr(loc, "DIMM"))
+ name = "dimms-temp";
+ else if (strstr(loc, "Processors"))
+ name = "between-cpus-temp";
+ if (name) {
+ of_node_put(np);
+ break;
+ }
+ }
+ if (!name) {
+ pr_warning("wf_lm87: Unsupported sensor %s\n",
+ client->dev.of_node->full_name);
+ return -ENODEV;
+ }
+
+ lm = kzalloc(sizeof(struct wf_lm87_sensor), GFP_KERNEL);
+ if (lm == NULL)
+ return -ENODEV;
+
+ lm->i2c = client;
+ lm->sens.name = name;
+ lm->sens.ops = &wf_lm87_ops;
+ lm->sens.priv = lm;
+ i2c_set_clientdata(client, lm);
+
+ rc = wf_register_sensor(&lm->sens);
+ if (rc)
+ kfree(lm);
+ return rc;
+}
+
+static int wf_lm87_remove(struct i2c_client *client)
+{
+ struct wf_lm87_sensor *lm = i2c_get_clientdata(client);
+
+ DBG("wf_lm87: i2c detatch called for %s\n", lm->sens.name);
+
+ /* Mark client detached */
+ lm->i2c = NULL;
+
+ /* release sensor */
+ wf_unregister_sensor(&lm->sens);
+
+ return 0;
+}
+
+static const struct i2c_device_id wf_lm87_id[] = {
+ { "MAC,lm87cimt", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wf_lm87_id);
+
+static struct i2c_driver wf_lm87_driver = {
+ .driver = {
+ .name = "wf_lm87",
+ },
+ .probe = wf_lm87_probe,
+ .remove = wf_lm87_remove,
+ .id_table = wf_lm87_id,
+};
+
+static int __init wf_lm87_sensor_init(void)
+{
+ /* We only support this on the Xserve */
+ if (!of_machine_is_compatible("RackMac3,1"))
+ return -ENODEV;
+
+ return i2c_add_driver(&wf_lm87_driver);
+}
+
+static void __exit wf_lm87_sensor_exit(void)
+{
+ i2c_del_driver(&wf_lm87_driver);
+}
+
+
+module_init(wf_lm87_sensor_init);
+module_exit(wf_lm87_sensor_exit);
+
+MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
+MODULE_DESCRIPTION("LM87 sensor objects for PowerMacs thermal control");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
index 8204113268f4..371b058d2f7d 100644
--- a/drivers/macintosh/windfarm_max6690_sensor.c
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -16,7 +16,7 @@
#include "windfarm.h"
-#define VERSION "0.2"
+#define VERSION "1.0"
/* This currently only exports the external temperature sensor,
since that's all the control loops need. */
@@ -64,9 +64,29 @@ static struct wf_sensor_ops wf_max6690_ops = {
static int wf_max6690_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ const char *name, *loc;
struct wf_6690_sensor *max;
int rc;
+ loc = of_get_property(client->dev.of_node, "hwsensor-location", NULL);
+ if (!loc) {
+ dev_warn(&client->dev, "Missing hwsensor-location property!\n");
+ return -ENXIO;
+ }
+
+ /*
+ * We only expose the external temperature register for
+ * now as this is all we need for our control loops
+ */
+ if (!strcmp(loc, "BACKSIDE") || !strcmp(loc, "SYS CTRLR AMBIENT"))
+ name = "backside-temp";
+ else if (!strcmp(loc, "NB Ambient"))
+ name = "north-bridge-temp";
+ else if (!strcmp(loc, "GPU Ambient"))
+ name = "gpu-temp";
+ else
+ return -ENXIO;
+
max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
if (max == NULL) {
printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor: "
@@ -75,90 +95,16 @@ static int wf_max6690_probe(struct i2c_client *client,
}
max->i2c = client;
- max->sens.name = client->dev.platform_data;
+ max->sens.name = (char *)name; /* XXX fix constness in structure */
max->sens.ops = &wf_max6690_ops;
i2c_set_clientdata(client, max);
rc = wf_register_sensor(&max->sens);
- if (rc) {
+ if (rc)
kfree(max);
- }
-
return rc;
}
-static struct i2c_driver wf_max6690_driver;
-
-static struct i2c_client *wf_max6690_create(struct i2c_adapter *adapter,
- u8 addr, const char *loc)
-{
- struct i2c_board_info info;
- struct i2c_client *client;
- char *name;
-
- if (!strcmp(loc, "BACKSIDE"))
- name = "backside-temp";
- else if (!strcmp(loc, "NB Ambient"))
- name = "north-bridge-temp";
- else if (!strcmp(loc, "GPU Ambient"))
- name = "gpu-temp";
- else
- goto fail;
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = addr >> 1;
- info.platform_data = name;
- strlcpy(info.type, "wf_max6690", I2C_NAME_SIZE);
-
- client = i2c_new_device(adapter, &info);
- if (client == NULL) {
- printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n");
- goto fail;
- }
-
- /*
- * Let i2c-core delete that device on driver removal.
- * This is safe because i2c-core holds the core_lock mutex for us.
- */
- list_add_tail(&client->detected, &wf_max6690_driver.clients);
- return client;
-
- fail:
- return NULL;
-}
-
-static int wf_max6690_attach(struct i2c_adapter *adapter)
-{
- struct device_node *busnode, *dev = NULL;
- struct pmac_i2c_bus *bus;
- const char *loc;
-
- bus = pmac_i2c_adapter_to_bus(adapter);
- if (bus == NULL)
- return -ENODEV;
- busnode = pmac_i2c_get_bus_node(bus);
-
- while ((dev = of_get_next_child(busnode, dev)) != NULL) {
- u8 addr;
-
- /* We must re-match the adapter in order to properly check
- * the channel on multibus setups
- */
- if (!pmac_i2c_match_adapter(dev, adapter))
- continue;
- if (!of_device_is_compatible(dev, "max6690"))
- continue;
- addr = pmac_i2c_get_dev_addr(dev);
- loc = of_get_property(dev, "hwsensor-location", NULL);
- if (loc == NULL || addr == 0)
- continue;
- printk("found max6690, loc=%s addr=0x%02x\n", loc, addr);
- wf_max6690_create(adapter, addr, loc);
- }
-
- return 0;
-}
-
static int wf_max6690_remove(struct i2c_client *client)
{
struct wf_6690_sensor *max = i2c_get_clientdata(client);
@@ -170,15 +116,15 @@ static int wf_max6690_remove(struct i2c_client *client)
}
static const struct i2c_device_id wf_max6690_id[] = {
- { "wf_max6690", 0 },
+ { "MAC,max6690", 0 },
{ }
};
+MODULE_DEVICE_TABLE(i2c, wf_max6690_id);
static struct i2c_driver wf_max6690_driver = {
.driver = {
.name = "wf_max6690",
},
- .attach_adapter = wf_max6690_attach,
.probe = wf_max6690_probe,
.remove = wf_max6690_remove,
.id_table = wf_max6690_id,
@@ -186,11 +132,6 @@ static struct i2c_driver wf_max6690_driver = {
static int __init wf_max6690_sensor_init(void)
{
- /* Don't register on old machines that use therm_pm72 for now */
- if (of_machine_is_compatible("PowerMac7,2") ||
- of_machine_is_compatible("PowerMac7,3") ||
- of_machine_is_compatible("RackMac3,1"))
- return -ENODEV;
return i2c_add_driver(&wf_max6690_driver);
}
diff --git a/drivers/macintosh/windfarm_mpu.h b/drivers/macintosh/windfarm_mpu.h
new file mode 100644
index 000000000000..046edc8c2ec5
--- /dev/null
+++ b/drivers/macintosh/windfarm_mpu.h
@@ -0,0 +1,105 @@
+/*
+ * Windfarm PowerMac thermal control
+ *
+ * Copyright 2012 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * Released under the term of the GNU GPL v2.
+ */
+
+#ifndef __WINDFARM_MPU_H
+#define __WINDFARM_MPU_H
+
+typedef unsigned short fu16;
+typedef int fs32;
+typedef short fs16;
+
+/* Definition of the MPU data structure which contains per CPU
+ * calibration information (among others) for the G5 machines
+ */
+struct mpu_data
+{
+ u8 signature; /* 0x00 - EEPROM sig. */
+ u8 bytes_used; /* 0x01 - Bytes used in eeprom (160 ?) */
+ u8 size; /* 0x02 - EEPROM size (256 ?) */
+ u8 version; /* 0x03 - EEPROM version */
+ u32 data_revision; /* 0x04 - Dataset revision */
+ u8 processor_bin_code[3]; /* 0x08 - Processor BIN code */
+ u8 bin_code_expansion; /* 0x0b - ??? (padding ?) */
+ u8 processor_num; /* 0x0c - Number of CPUs on this MPU */
+ u8 input_mul_bus_div; /* 0x0d - Clock input multiplier/bus divider */
+ u8 reserved1[2]; /* 0x0e - */
+ u32 input_clk_freq_high; /* 0x10 - Input clock frequency high */
+ u8 cpu_nb_target_cycles; /* 0x14 - ??? */
+ u8 cpu_statlat; /* 0x15 - ??? */
+ u8 cpu_snooplat; /* 0x16 - ??? */
+ u8 cpu_snoopacc; /* 0x17 - ??? */
+ u8 nb_paamwin; /* 0x18 - ??? */
+ u8 nb_statlat; /* 0x19 - ??? */
+ u8 nb_snooplat; /* 0x1a - ??? */
+ u8 nb_snoopwin; /* 0x1b - ??? */
+ u8 api_bus_mode; /* 0x1c - ??? */
+ u8 reserved2[3]; /* 0x1d - */
+ u32 input_clk_freq_low; /* 0x20 - Input clock frequency low */
+ u8 processor_card_slot; /* 0x24 - Processor card slot number */
+ u8 reserved3[2]; /* 0x25 - */
+ u8 padjmax; /* 0x27 - Max power adjustment (Not in OF!) */
+ u8 ttarget; /* 0x28 - Target temperature */
+ u8 tmax; /* 0x29 - Max temperature */
+ u8 pmaxh; /* 0x2a - Max power */
+ u8 tguardband; /* 0x2b - Guardband temp ??? Hist. len in OSX */
+ fs32 pid_gp; /* 0x2c - PID proportional gain */
+ fs32 pid_gr; /* 0x30 - PID reset gain */
+ fs32 pid_gd; /* 0x34 - PID derivative gain */
+ fu16 voph; /* 0x38 - Vop High */
+ fu16 vopl; /* 0x3a - Vop Low */
+ fs16 nactual_die; /* 0x3c - nActual Die */
+ fs16 nactual_heatsink; /* 0x3e - nActual Heatsink */
+ fs16 nactual_system; /* 0x40 - nActual System */
+ u16 calibration_flags; /* 0x42 - Calibration flags */
+ fu16 mdiode; /* 0x44 - Diode M value (scaling factor) */
+ fs16 bdiode; /* 0x46 - Diode B value (offset) */
+ fs32 theta_heat_sink; /* 0x48 - Theta heat sink */
+ u16 rminn_intake_fan; /* 0x4c - Intake fan min RPM */
+ u16 rmaxn_intake_fan; /* 0x4e - Intake fan max RPM */
+ u16 rminn_exhaust_fan; /* 0x50 - Exhaust fan min RPM */
+ u16 rmaxn_exhaust_fan; /* 0x52 - Exhaust fan max RPM */
+ u8 processor_part_num[8]; /* 0x54 - Processor part number XX pumps min/max */
+ u32 processor_lot_num; /* 0x5c - Processor lot number */
+ u8 orig_card_sernum[0x10]; /* 0x60 - Card original serial number */
+ u8 curr_card_sernum[0x10]; /* 0x70 - Card current serial number */
+ u8 mlb_sernum[0x18]; /* 0x80 - MLB serial number */
+ u32 checksum1; /* 0x98 - */
+ u32 checksum2; /* 0x9c - */
+}; /* Total size = 0xa0 */
+
+static inline const struct mpu_data *wf_get_mpu(int cpu)
+{
+ struct device_node *np;
+ char nodename[64];
+ const void *data;
+ int len;
+
+ /*
+ * prom.c routine for finding a node by path is a bit brain dead
+ * and requires exact @xxx unit numbers. This is a bit ugly but
+ * will work for these machines
+ */
+ sprintf(nodename, "/u3@0,f8000000/i2c@f8001000/cpuid@a%d", cpu ? 2 : 0);
+ np = of_find_node_by_path(nodename);
+ if (!np)
+ return NULL;
+ data = of_get_property(np, "cpuid", &len);
+ of_node_put(np);
+ if (!data)
+ return NULL;
+
+ /*
+ * We are naughty, we have dropped the reference to the device
+ * node and still return a pointer to the content. We know we
+ * can do that though as this is only ever called on PowerMac
+ * which cannot remove those nodes
+ */
+ return data;
+}
+
+#endif /* __WINDFARM_MPU_H */
diff --git a/drivers/macintosh/windfarm_pm72.c b/drivers/macintosh/windfarm_pm72.c
new file mode 100644
index 000000000000..84ac913d7e3a
--- /dev/null
+++ b/drivers/macintosh/windfarm_pm72.c
@@ -0,0 +1,847 @@
+/*
+ * Windfarm PowerMac thermal control.
+ * Control loops for PowerMac7,2 and 7,3
+ *
+ * Copyright (C) 2012 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * Use and redistribute under the terms of the GNU GPL v2.
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <asm/prom.h>
+#include <asm/smu.h>
+
+#include "windfarm.h"
+#include "windfarm_pid.h"
+#include "windfarm_mpu.h"
+
+#define VERSION "1.0"
+
+#undef DEBUG
+#undef LOTSA_DEBUG
+
+#ifdef DEBUG
+#define DBG(args...) printk(args)
+#else
+#define DBG(args...) do { } while(0)
+#endif
+
+#ifdef LOTSA_DEBUG
+#define DBG_LOTS(args...) printk(args)
+#else
+#define DBG_LOTS(args...) do { } while(0)
+#endif
+
+/* define this to force CPU overtemp to 60 degree, useful for testing
+ * the overtemp code
+ */
+#undef HACKED_OVERTEMP
+
+/* We currently only handle 2 chips */
+#define NR_CHIPS 2
+#define NR_CPU_FANS 3 * NR_CHIPS
+
+/* Controls and sensors */
+static struct wf_sensor *sens_cpu_temp[NR_CHIPS];
+static struct wf_sensor *sens_cpu_volts[NR_CHIPS];
+static struct wf_sensor *sens_cpu_amps[NR_CHIPS];
+static struct wf_sensor *backside_temp;
+static struct wf_sensor *drives_temp;
+
+static struct wf_control *cpu_front_fans[NR_CHIPS];
+static struct wf_control *cpu_rear_fans[NR_CHIPS];
+static struct wf_control *cpu_pumps[NR_CHIPS];
+static struct wf_control *backside_fan;
+static struct wf_control *drives_fan;
+static struct wf_control *slots_fan;
+static struct wf_control *cpufreq_clamp;
+
+/* We keep a temperature history for average calculation of 180s */
+#define CPU_TEMP_HIST_SIZE 180
+
+/* Fixed speed for slot fan */
+#define SLOTS_FAN_DEFAULT_PWM 40
+
+/* Scale value for CPU intake fans */
+#define CPU_INTAKE_SCALE 0x0000f852
+
+/* PID loop state */
+static const struct mpu_data *cpu_mpu_data[NR_CHIPS];
+static struct wf_cpu_pid_state cpu_pid[NR_CHIPS];
+static bool cpu_pid_combined;
+static u32 cpu_thist[CPU_TEMP_HIST_SIZE];
+static int cpu_thist_pt;
+static s64 cpu_thist_total;
+static s32 cpu_all_tmax = 100 << 16;
+static struct wf_pid_state backside_pid;
+static int backside_tick;
+static struct wf_pid_state drives_pid;
+static int drives_tick;
+
+static int nr_chips;
+static bool have_all_controls;
+static bool have_all_sensors;
+static bool started;
+
+static int failure_state;
+#define FAILURE_SENSOR 1
+#define FAILURE_FAN 2
+#define FAILURE_PERM 4
+#define FAILURE_LOW_OVERTEMP 8
+#define FAILURE_HIGH_OVERTEMP 16
+
+/* Overtemp values */
+#define LOW_OVER_AVERAGE 0
+#define LOW_OVER_IMMEDIATE (10 << 16)
+#define LOW_OVER_CLEAR ((-10) << 16)
+#define HIGH_OVER_IMMEDIATE (14 << 16)
+#define HIGH_OVER_AVERAGE (10 << 16)
+#define HIGH_OVER_IMMEDIATE (14 << 16)
+
+
+static void cpu_max_all_fans(void)
+{
+ int i;
+
+ /* We max all CPU fans in case of a sensor error. We also do the
+ * cpufreq clamping now, even if it's supposedly done later by the
+ * generic code anyway, we do it earlier here to react faster
+ */
+ if (cpufreq_clamp)
+ wf_control_set_max(cpufreq_clamp);
+ for (i = 0; i < nr_chips; i++) {
+ if (cpu_front_fans[i])
+ wf_control_set_max(cpu_front_fans[i]);
+ if (cpu_rear_fans[i])
+ wf_control_set_max(cpu_rear_fans[i]);
+ if (cpu_pumps[i])
+ wf_control_set_max(cpu_pumps[i]);
+ }
+}
+
+static int cpu_check_overtemp(s32 temp)
+{
+ int new_state = 0;
+ s32 t_avg, t_old;
+ static bool first = true;
+
+ /* First check for immediate overtemps */
+ if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) {
+ new_state |= FAILURE_LOW_OVERTEMP;
+ if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Overtemp due to immediate CPU"
+ " temperature !\n");
+ }
+ if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) {
+ new_state |= FAILURE_HIGH_OVERTEMP;
+ if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Critical overtemp due to"
+ " immediate CPU temperature !\n");
+ }
+
+ /*
+ * The first time around, initialize the array with the first
+ * temperature reading
+ */
+ if (first) {
+ int i;
+
+ cpu_thist_total = 0;
+ for (i = 0; i < CPU_TEMP_HIST_SIZE; i++) {
+ cpu_thist[i] = temp;
+ cpu_thist_total += temp;
+ }
+ first = false;
+ }
+
+ /*
+ * We calculate a history of max temperatures and use that for the
+ * overtemp management
+ */
+ t_old = cpu_thist[cpu_thist_pt];
+ cpu_thist[cpu_thist_pt] = temp;
+ cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE;
+ cpu_thist_total -= t_old;
+ cpu_thist_total += temp;
+ t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE;
+
+ DBG_LOTS(" t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
+ FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp));
+
+ /* Now check for average overtemps */
+ if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) {
+ new_state |= FAILURE_LOW_OVERTEMP;
+ if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Overtemp due to average CPU"
+ " temperature !\n");
+ }
+ if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) {
+ new_state |= FAILURE_HIGH_OVERTEMP;
+ if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Critical overtemp due to"
+ " average CPU temperature !\n");
+ }
+
+ /* Now handle overtemp conditions. We don't currently use the windfarm
+ * overtemp handling core as it's not fully suited to the needs of those
+ * new machine. This will be fixed later.
+ */
+ if (new_state) {
+ /* High overtemp -> immediate shutdown */
+ if (new_state & FAILURE_HIGH_OVERTEMP)
+ machine_power_off();
+ if ((failure_state & new_state) != new_state)
+ cpu_max_all_fans();
+ failure_state |= new_state;
+ } else if ((failure_state & FAILURE_LOW_OVERTEMP) &&
+ (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) {
+ printk(KERN_ERR "windfarm: Overtemp condition cleared !\n");
+ failure_state &= ~FAILURE_LOW_OVERTEMP;
+ }
+
+ return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP);
+}
+
+static int read_one_cpu_vals(int cpu, s32 *temp, s32 *power)
+{
+ s32 dtemp, volts, amps;
+ int rc;
+
+ /* Get diode temperature */
+ rc = wf_sensor_get(sens_cpu_temp[cpu], &dtemp);
+ if (rc) {
+ DBG(" CPU%d: temp reading error !\n", cpu);
+ return -EIO;
+ }
+ DBG_LOTS(" CPU%d: temp = %d.%03d\n", cpu, FIX32TOPRINT((dtemp)));
+ *temp = dtemp;
+
+ /* Get voltage */
+ rc = wf_sensor_get(sens_cpu_volts[cpu], &volts);
+ if (rc) {
+ DBG(" CPU%d, volts reading error !\n", cpu);
+ return -EIO;
+ }
+ DBG_LOTS(" CPU%d: volts = %d.%03d\n", cpu, FIX32TOPRINT((volts)));
+
+ /* Get current */
+ rc = wf_sensor_get(sens_cpu_amps[cpu], &amps);
+ if (rc) {
+ DBG(" CPU%d, current reading error !\n", cpu);
+ return -EIO;
+ }
+ DBG_LOTS(" CPU%d: amps = %d.%03d\n", cpu, FIX32TOPRINT((amps)));
+
+ /* Calculate power */
+
+ /* Scale voltage and current raw sensor values according to fixed scales
+ * obtained in Darwin and calculate power from I and V
+ */
+ *power = (((u64)volts) * ((u64)amps)) >> 16;
+
+ DBG_LOTS(" CPU%d: power = %d.%03d\n", cpu, FIX32TOPRINT((*power)));
+
+ return 0;
+
+}
+
+static void cpu_fans_tick_split(void)
+{
+ int err, cpu;
+ s32 intake, temp, power, t_max = 0;
+
+ DBG_LOTS("* cpu fans_tick_split()\n");
+
+ for (cpu = 0; cpu < nr_chips; ++cpu) {
+ struct wf_cpu_pid_state *sp = &cpu_pid[cpu];
+
+ /* Read current speed */
+ wf_control_get(cpu_rear_fans[cpu], &sp->target);
+
+ DBG_LOTS(" CPU%d: cur_target = %d RPM\n", cpu, sp->target);
+
+ err = read_one_cpu_vals(cpu, &temp, &power);
+ if (err) {
+ failure_state |= FAILURE_SENSOR;
+ cpu_max_all_fans();
+ return;
+ }
+
+ /* Keep track of highest temp */
+ t_max = max(t_max, temp);
+
+ /* Handle possible overtemps */
+ if (cpu_check_overtemp(t_max))
+ return;
+
+ /* Run PID */
+ wf_cpu_pid_run(sp, power, temp);
+
+ DBG_LOTS(" CPU%d: target = %d RPM\n", cpu, sp->target);
+
+ /* Apply result directly to exhaust fan */
+ err = wf_control_set(cpu_rear_fans[cpu], sp->target);
+ if (err) {
+ pr_warning("wf_pm72: Fan %s reports error %d\n",
+ cpu_rear_fans[cpu]->name, err);
+ failure_state |= FAILURE_FAN;
+ break;
+ }
+
+ /* Scale result for intake fan */
+ intake = (sp->target * CPU_INTAKE_SCALE) >> 16;
+ DBG_LOTS(" CPU%d: intake = %d RPM\n", cpu, intake);
+ err = wf_control_set(cpu_front_fans[cpu], intake);
+ if (err) {
+ pr_warning("wf_pm72: Fan %s reports error %d\n",
+ cpu_front_fans[cpu]->name, err);
+ failure_state |= FAILURE_FAN;
+ break;
+ }
+ }
+}
+
+static void cpu_fans_tick_combined(void)
+{
+ s32 temp0, power0, temp1, power1, t_max = 0;
+ s32 temp, power, intake, pump;
+ struct wf_control *pump0, *pump1;
+ struct wf_cpu_pid_state *sp = &cpu_pid[0];
+ int err, cpu;
+
+ DBG_LOTS("* cpu fans_tick_combined()\n");
+
+ /* Read current speed from cpu 0 */
+ wf_control_get(cpu_rear_fans[0], &sp->target);
+
+ DBG_LOTS(" CPUs: cur_target = %d RPM\n", sp->target);
+
+ /* Read values for both CPUs */
+ err = read_one_cpu_vals(0, &temp0, &power0);
+ if (err) {
+ failure_state |= FAILURE_SENSOR;
+ cpu_max_all_fans();
+ return;
+ }
+ err = read_one_cpu_vals(1, &temp1, &power1);
+ if (err) {
+ failure_state |= FAILURE_SENSOR;
+ cpu_max_all_fans();
+ return;
+ }
+
+ /* Keep track of highest temp */
+ t_max = max(t_max, max(temp0, temp1));
+
+ /* Handle possible overtemps */
+ if (cpu_check_overtemp(t_max))
+ return;
+
+ /* Use the max temp & power of both */
+ temp = max(temp0, temp1);
+ power = max(power0, power1);
+
+ /* Run PID */
+ wf_cpu_pid_run(sp, power, temp);
+
+ /* Scale result for intake fan */
+ intake = (sp->target * CPU_INTAKE_SCALE) >> 16;
+
+ /* Same deal with pump speed */
+ pump0 = cpu_pumps[0];
+ pump1 = cpu_pumps[1];
+ if (!pump0) {
+ pump0 = pump1;
+ pump1 = NULL;
+ }
+ pump = (sp->target * wf_control_get_max(pump0)) /
+ cpu_mpu_data[0]->rmaxn_exhaust_fan;
+
+ DBG_LOTS(" CPUs: target = %d RPM\n", sp->target);
+ DBG_LOTS(" CPUs: intake = %d RPM\n", intake);
+ DBG_LOTS(" CPUs: pump = %d RPM\n", pump);
+
+ for (cpu = 0; cpu < nr_chips; cpu++) {
+ err = wf_control_set(cpu_rear_fans[cpu], sp->target);
+ if (err) {
+ pr_warning("wf_pm72: Fan %s reports error %d\n",
+ cpu_rear_fans[cpu]->name, err);
+ failure_state |= FAILURE_FAN;
+ }
+ err = wf_control_set(cpu_front_fans[cpu], intake);
+ if (err) {
+ pr_warning("wf_pm72: Fan %s reports error %d\n",
+ cpu_front_fans[cpu]->name, err);
+ failure_state |= FAILURE_FAN;
+ }
+ err = 0;
+ if (cpu_pumps[cpu])
+ err = wf_control_set(cpu_pumps[cpu], pump);
+ if (err) {
+ pr_warning("wf_pm72: Pump %s reports error %d\n",
+ cpu_pumps[cpu]->name, err);
+ failure_state |= FAILURE_FAN;
+ }
+ }
+}
+
+/* Implementation... */
+static int cpu_setup_pid(int cpu)
+{
+ struct wf_cpu_pid_param pid;
+ const struct mpu_data *mpu = cpu_mpu_data[cpu];
+ s32 tmax, ttarget, ptarget;
+ int fmin, fmax, hsize;
+
+ /* Get PID params from the appropriate MPU EEPROM */
+ tmax = mpu->tmax << 16;
+ ttarget = mpu->ttarget << 16;
+ ptarget = ((s32)(mpu->pmaxh - mpu->padjmax)) << 16;
+
+ DBG("wf_72: CPU%d ttarget = %d.%03d, tmax = %d.%03d\n",
+ cpu, FIX32TOPRINT(ttarget), FIX32TOPRINT(tmax));
+
+ /* We keep a global tmax for overtemp calculations */
+ if (tmax < cpu_all_tmax)
+ cpu_all_tmax = tmax;
+
+ /* Set PID min/max by using the rear fan min/max */
+ fmin = wf_control_get_min(cpu_rear_fans[cpu]);
+ fmax = wf_control_get_max(cpu_rear_fans[cpu]);
+ DBG("wf_72: CPU%d max RPM range = [%d..%d]\n", cpu, fmin, fmax);
+
+ /* History size */
+ hsize = min_t(int, mpu->tguardband, WF_PID_MAX_HISTORY);
+ DBG("wf_72: CPU%d history size = %d\n", cpu, hsize);
+
+ /* Initialize PID loop */
+ pid.interval = 1; /* seconds */
+ pid.history_len = hsize;
+ pid.gd = mpu->pid_gd;
+ pid.gp = mpu->pid_gp;
+ pid.gr = mpu->pid_gr;
+ pid.tmax = tmax;
+ pid.ttarget = ttarget;
+ pid.pmaxadj = ptarget;
+ pid.min = fmin;
+ pid.max = fmax;
+
+ wf_cpu_pid_init(&cpu_pid[cpu], &pid);
+ cpu_pid[cpu].target = 1000;
+
+ return 0;
+}
+
+/* Backside/U3 fan */
+static struct wf_pid_param backside_u3_param = {
+ .interval = 5,
+ .history_len = 2,
+ .gd = 40 << 20,
+ .gp = 5 << 20,
+ .gr = 0,
+ .itarget = 65 << 16,
+ .additive = 1,
+ .min = 20,
+ .max = 100,
+};
+
+static struct wf_pid_param backside_u3h_param = {
+ .interval = 5,
+ .history_len = 2,
+ .gd = 20 << 20,
+ .gp = 5 << 20,
+ .gr = 0,
+ .itarget = 75 << 16,
+ .additive = 1,
+ .min = 20,
+ .max = 100,
+};
+
+static void backside_fan_tick(void)
+{
+ s32 temp;
+ int speed;
+ int err;
+
+ if (!backside_fan || !backside_temp || !backside_tick)
+ return;
+ if (--backside_tick > 0)
+ return;
+ backside_tick = backside_pid.param.interval;
+
+ DBG_LOTS("* backside fans tick\n");
+
+ /* Update fan speed from actual fans */
+ err = wf_control_get(backside_fan, &speed);
+ if (!err)
+ backside_pid.target = speed;
+
+ err = wf_sensor_get(backside_temp, &temp);
+ if (err) {
+ printk(KERN_WARNING "windfarm: U4 temp sensor error %d\n",
+ err);
+ failure_state |= FAILURE_SENSOR;
+ wf_control_set_max(backside_fan);
+ return;
+ }
+ speed = wf_pid_run(&backside_pid, temp);
+
+ DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n",
+ FIX32TOPRINT(temp), speed);
+
+ err = wf_control_set(backside_fan, speed);
+ if (err) {
+ printk(KERN_WARNING "windfarm: backside fan error %d\n", err);
+ failure_state |= FAILURE_FAN;
+ }
+}
+
+static void backside_setup_pid(void)
+{
+ /* first time initialize things */
+ s32 fmin = wf_control_get_min(backside_fan);
+ s32 fmax = wf_control_get_max(backside_fan);
+ struct wf_pid_param param;
+ struct device_node *u3;
+ int u3h = 1; /* conservative by default */
+
+ u3 = of_find_node_by_path("/u3@0,f8000000");
+ if (u3 != NULL) {
+ const u32 *vers = of_get_property(u3, "device-rev", NULL);
+ if (vers)
+ if (((*vers) & 0x3f) < 0x34)
+ u3h = 0;
+ of_node_put(u3);
+ }
+
+ param = u3h ? backside_u3h_param : backside_u3_param;
+
+ param.min = max(param.min, fmin);
+ param.max = min(param.max, fmax);
+ wf_pid_init(&backside_pid, &param);
+ backside_tick = 1;
+
+ pr_info("wf_pm72: Backside control loop started.\n");
+}
+
+/* Drive bay fan */
+static const struct wf_pid_param drives_param = {
+ .interval = 5,
+ .history_len = 2,
+ .gd = 30 << 20,
+ .gp = 5 << 20,
+ .gr = 0,
+ .itarget = 40 << 16,
+ .additive = 1,
+ .min = 300,
+ .max = 4000,
+};
+
+static void drives_fan_tick(void)
+{
+ s32 temp;
+ int speed;
+ int err;
+
+ if (!drives_fan || !drives_temp || !drives_tick)
+ return;
+ if (--drives_tick > 0)
+ return;
+ drives_tick = drives_pid.param.interval;
+
+ DBG_LOTS("* drives fans tick\n");
+
+ /* Update fan speed from actual fans */
+ err = wf_control_get(drives_fan, &speed);
+ if (!err)
+ drives_pid.target = speed;
+
+ err = wf_sensor_get(drives_temp, &temp);
+ if (err) {
+ pr_warning("wf_pm72: drive bay temp sensor error %d\n", err);
+ failure_state |= FAILURE_SENSOR;
+ wf_control_set_max(drives_fan);
+ return;
+ }
+ speed = wf_pid_run(&drives_pid, temp);
+
+ DBG_LOTS("drives PID temp=%d.%.3d speed=%d\n",
+ FIX32TOPRINT(temp), speed);
+
+ err = wf_control_set(drives_fan, speed);
+ if (err) {
+ printk(KERN_WARNING "windfarm: drive bay fan error %d\n", err);
+ failure_state |= FAILURE_FAN;
+ }
+}
+
+static void drives_setup_pid(void)
+{
+ /* first time initialize things */
+ s32 fmin = wf_control_get_min(drives_fan);
+ s32 fmax = wf_control_get_max(drives_fan);
+ struct wf_pid_param param = drives_param;
+
+ param.min = max(param.min, fmin);
+ param.max = min(param.max, fmax);
+ wf_pid_init(&drives_pid, &param);
+ drives_tick = 1;
+
+ pr_info("wf_pm72: Drive bay control loop started.\n");
+}
+
+static void set_fail_state(void)
+{
+ cpu_max_all_fans();
+
+ if (backside_fan)
+ wf_control_set_max(backside_fan);
+ if (slots_fan)
+ wf_control_set_max(slots_fan);
+ if (drives_fan)
+ wf_control_set_max(drives_fan);
+}
+
+static void pm72_tick(void)
+{
+ int i, last_failure;
+
+ if (!started) {
+ started = 1;
+ printk(KERN_INFO "windfarm: CPUs control loops started.\n");
+ for (i = 0; i < nr_chips; ++i) {
+ if (cpu_setup_pid(i) < 0) {
+ failure_state = FAILURE_PERM;
+ set_fail_state();
+ break;
+ }
+ }
+ DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax));
+
+ backside_setup_pid();
+ drives_setup_pid();
+
+ /*
+ * We don't have the right stuff to drive the PCI fan
+ * so we fix it to a default value
+ */
+ wf_control_set(slots_fan, SLOTS_FAN_DEFAULT_PWM);
+
+#ifdef HACKED_OVERTEMP
+ cpu_all_tmax = 60 << 16;
+#endif
+ }
+
+ /* Permanent failure, bail out */
+ if (failure_state & FAILURE_PERM)
+ return;
+
+ /*
+ * Clear all failure bits except low overtemp which will be eventually
+ * cleared by the control loop itself
+ */
+ last_failure = failure_state;
+ failure_state &= FAILURE_LOW_OVERTEMP;
+ if (cpu_pid_combined)
+ cpu_fans_tick_combined();
+ else
+ cpu_fans_tick_split();
+ backside_fan_tick();
+ drives_fan_tick();
+
+ DBG_LOTS(" last_failure: 0x%x, failure_state: %x\n",
+ last_failure, failure_state);
+
+ /* Check for failures. Any failure causes cpufreq clamping */
+ if (failure_state && last_failure == 0 && cpufreq_clamp)
+ wf_control_set_max(cpufreq_clamp);
+ if (failure_state == 0 && last_failure && cpufreq_clamp)
+ wf_control_set_min(cpufreq_clamp);
+
+ /* That's it for now, we might want to deal with other failures
+ * differently in the future though
+ */
+}
+
+static void pm72_new_control(struct wf_control *ct)
+{
+ bool all_controls;
+ bool had_pump = cpu_pumps[0] || cpu_pumps[1];
+
+ if (!strcmp(ct->name, "cpu-front-fan-0"))
+ cpu_front_fans[0] = ct;
+ else if (!strcmp(ct->name, "cpu-front-fan-1"))
+ cpu_front_fans[1] = ct;
+ else if (!strcmp(ct->name, "cpu-rear-fan-0"))
+ cpu_rear_fans[0] = ct;
+ else if (!strcmp(ct->name, "cpu-rear-fan-1"))
+ cpu_rear_fans[1] = ct;
+ else if (!strcmp(ct->name, "cpu-pump-0"))
+ cpu_pumps[0] = ct;
+ else if (!strcmp(ct->name, "cpu-pump-1"))
+ cpu_pumps[1] = ct;
+ else if (!strcmp(ct->name, "backside-fan"))
+ backside_fan = ct;
+ else if (!strcmp(ct->name, "slots-fan"))
+ slots_fan = ct;
+ else if (!strcmp(ct->name, "drive-bay-fan"))
+ drives_fan = ct;
+ else if (!strcmp(ct->name, "cpufreq-clamp"))
+ cpufreq_clamp = ct;
+
+ all_controls =
+ cpu_front_fans[0] &&
+ cpu_rear_fans[0] &&
+ backside_fan &&
+ slots_fan &&
+ drives_fan;
+ if (nr_chips > 1)
+ all_controls &=
+ cpu_front_fans[1] &&
+ cpu_rear_fans[1];
+ have_all_controls = all_controls;
+
+ if ((cpu_pumps[0] || cpu_pumps[1]) && !had_pump) {
+ pr_info("wf_pm72: Liquid cooling pump(s) detected,"
+ " using new algorithm !\n");
+ cpu_pid_combined = true;
+ }
+}
+
+
+static void pm72_new_sensor(struct wf_sensor *sr)
+{
+ bool all_sensors;
+
+ if (!strcmp(sr->name, "cpu-diode-temp-0"))
+ sens_cpu_temp[0] = sr;
+ else if (!strcmp(sr->name, "cpu-diode-temp-1"))
+ sens_cpu_temp[1] = sr;
+ else if (!strcmp(sr->name, "cpu-voltage-0"))
+ sens_cpu_volts[0] = sr;
+ else if (!strcmp(sr->name, "cpu-voltage-1"))
+ sens_cpu_volts[1] = sr;
+ else if (!strcmp(sr->name, "cpu-current-0"))
+ sens_cpu_amps[0] = sr;
+ else if (!strcmp(sr->name, "cpu-current-1"))
+ sens_cpu_amps[1] = sr;
+ else if (!strcmp(sr->name, "backside-temp"))
+ backside_temp = sr;
+ else if (!strcmp(sr->name, "hd-temp"))
+ drives_temp = sr;
+
+ all_sensors =
+ sens_cpu_temp[0] &&
+ sens_cpu_volts[0] &&
+ sens_cpu_amps[0] &&
+ backside_temp &&
+ drives_temp;
+ if (nr_chips > 1)
+ all_sensors &=
+ sens_cpu_temp[1] &&
+ sens_cpu_volts[1] &&
+ sens_cpu_amps[1];
+
+ have_all_sensors = all_sensors;
+}
+
+static int pm72_wf_notify(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ switch (event) {
+ case WF_EVENT_NEW_SENSOR:
+ pm72_new_sensor(data);
+ break;
+ case WF_EVENT_NEW_CONTROL:
+ pm72_new_control(data);
+ break;
+ case WF_EVENT_TICK:
+ if (have_all_controls && have_all_sensors)
+ pm72_tick();
+ }
+ return 0;
+}
+
+static struct notifier_block pm72_events = {
+ .notifier_call = pm72_wf_notify,
+};
+
+static int wf_pm72_probe(struct platform_device *dev)
+{
+ wf_register_client(&pm72_events);
+ return 0;
+}
+
+static int __devexit wf_pm72_remove(struct platform_device *dev)
+{
+ wf_unregister_client(&pm72_events);
+
+ /* should release all sensors and controls */
+ return 0;
+}
+
+static struct platform_driver wf_pm72_driver = {
+ .probe = wf_pm72_probe,
+ .remove = wf_pm72_remove,
+ .driver = {
+ .name = "windfarm",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init wf_pm72_init(void)
+{
+ struct device_node *cpu;
+ int i;
+
+ if (!of_machine_is_compatible("PowerMac7,2") &&
+ !of_machine_is_compatible("PowerMac7,3"))
+ return -ENODEV;
+
+ /* Count the number of CPU cores */
+ nr_chips = 0;
+ for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; )
+ ++nr_chips;
+ if (nr_chips > NR_CHIPS)
+ nr_chips = NR_CHIPS;
+
+ pr_info("windfarm: Initializing for desktop G5 with %d chips\n",
+ nr_chips);
+
+ /* Get MPU data for each CPU */
+ for (i = 0; i < nr_chips; i++) {
+ cpu_mpu_data[i] = wf_get_mpu(i);
+ if (!cpu_mpu_data[i]) {
+ pr_err("wf_pm72: Failed to find MPU data for CPU %d\n", i);
+ return -ENXIO;
+ }
+ }
+
+#ifdef MODULE
+ request_module("windfarm_fcu_controls");
+ request_module("windfarm_lm75_sensor");
+ request_module("windfarm_ad7417_sensor");
+ request_module("windfarm_max6690_sensor");
+ request_module("windfarm_cpufreq_clamp");
+#endif /* MODULE */
+
+ platform_driver_register(&wf_pm72_driver);
+ return 0;
+}
+
+static void __exit wf_pm72_exit(void)
+{
+ platform_driver_unregister(&wf_pm72_driver);
+}
+
+module_init(wf_pm72_init);
+module_exit(wf_pm72_exit);
+
+MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
+MODULE_DESCRIPTION("Thermal control for AGP PowerMac G5s");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:windfarm");
diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
index fc13d0f2663b..990c87606be9 100644
--- a/drivers/macintosh/windfarm_pm81.c
+++ b/drivers/macintosh/windfarm_pm81.c
@@ -302,13 +302,13 @@ static void wf_smu_create_sys_fans(void)
pid_param.interval = WF_SMU_SYS_FANS_INTERVAL;
pid_param.history_len = WF_SMU_SYS_FANS_HISTORY_SIZE;
pid_param.itarget = param->itarget;
- pid_param.min = fan_system->ops->get_min(fan_system);
- pid_param.max = fan_system->ops->get_max(fan_system);
+ pid_param.min = wf_control_get_min(fan_system);
+ pid_param.max = wf_control_get_max(fan_system);
if (fan_hd) {
pid_param.min =
- max(pid_param.min,fan_hd->ops->get_min(fan_hd));
+ max(pid_param.min, wf_control_get_min(fan_hd));
pid_param.max =
- min(pid_param.max,fan_hd->ops->get_max(fan_hd));
+ min(pid_param.max, wf_control_get_max(fan_hd));
}
wf_pid_init(&wf_smu_sys_fans->pid, &pid_param);
@@ -337,7 +337,7 @@ static void wf_smu_sys_fans_tick(struct wf_smu_sys_fans_state *st)
}
st->ticks = WF_SMU_SYS_FANS_INTERVAL;
- rc = sensor_hd_temp->ops->get_value(sensor_hd_temp, &temp);
+ rc = wf_sensor_get(sensor_hd_temp, &temp);
if (rc) {
printk(KERN_WARNING "windfarm: HD temp sensor error %d\n",
rc);
@@ -373,7 +373,7 @@ static void wf_smu_sys_fans_tick(struct wf_smu_sys_fans_state *st)
st->hd_setpoint = new_setpoint;
readjust:
if (fan_system && wf_smu_failure_state == 0) {
- rc = fan_system->ops->set_value(fan_system, st->sys_setpoint);
+ rc = wf_control_set(fan_system, st->sys_setpoint);
if (rc) {
printk(KERN_WARNING "windfarm: Sys fan error %d\n",
rc);
@@ -381,7 +381,7 @@ static void wf_smu_sys_fans_tick(struct wf_smu_sys_fans_state *st)
}
}
if (fan_hd && wf_smu_failure_state == 0) {
- rc = fan_hd->ops->set_value(fan_hd, st->hd_setpoint);
+ rc = wf_control_set(fan_hd, st->hd_setpoint);
if (rc) {
printk(KERN_WARNING "windfarm: HD fan error %d\n",
rc);
@@ -447,8 +447,8 @@ static void wf_smu_create_cpu_fans(void)
pid_param.ttarget = tmax - tdelta;
pid_param.pmaxadj = maxpow - powadj;
- pid_param.min = fan_cpu_main->ops->get_min(fan_cpu_main);
- pid_param.max = fan_cpu_main->ops->get_max(fan_cpu_main);
+ pid_param.min = wf_control_get_min(fan_cpu_main);
+ pid_param.max = wf_control_get_max(fan_cpu_main);
wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param);
@@ -481,7 +481,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
}
st->ticks = WF_SMU_CPU_FANS_INTERVAL;
- rc = sensor_cpu_temp->ops->get_value(sensor_cpu_temp, &temp);
+ rc = wf_sensor_get(sensor_cpu_temp, &temp);
if (rc) {
printk(KERN_WARNING "windfarm: CPU temp sensor error %d\n",
rc);
@@ -489,7 +489,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
return;
}
- rc = sensor_cpu_power->ops->get_value(sensor_cpu_power, &power);
+ rc = wf_sensor_get(sensor_cpu_power, &power);
if (rc) {
printk(KERN_WARNING "windfarm: CPU power sensor error %d\n",
rc);
@@ -525,8 +525,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
st->cpu_setpoint = new_setpoint;
readjust:
if (fan_cpu_main && wf_smu_failure_state == 0) {
- rc = fan_cpu_main->ops->set_value(fan_cpu_main,
- st->cpu_setpoint);
+ rc = wf_control_set(fan_cpu_main, st->cpu_setpoint);
if (rc) {
printk(KERN_WARNING "windfarm: CPU main fan"
" error %d\n", rc);
diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c
index a9430ed4f36c..7653603cb00e 100644
--- a/drivers/macintosh/windfarm_pm91.c
+++ b/drivers/macintosh/windfarm_pm91.c
@@ -192,8 +192,8 @@ static void wf_smu_create_cpu_fans(void)
pid_param.ttarget = tmax - tdelta;
pid_param.pmaxadj = maxpow - powadj;
- pid_param.min = fan_cpu_main->ops->get_min(fan_cpu_main);
- pid_param.max = fan_cpu_main->ops->get_max(fan_cpu_main);
+ pid_param.min = wf_control_get_min(fan_cpu_main);
+ pid_param.max = wf_control_get_max(fan_cpu_main);
wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param);
@@ -226,7 +226,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
}
st->ticks = WF_SMU_CPU_FANS_INTERVAL;
- rc = sensor_cpu_temp->ops->get_value(sensor_cpu_temp, &temp);
+ rc = wf_sensor_get(sensor_cpu_temp, &temp);
if (rc) {
printk(KERN_WARNING "windfarm: CPU temp sensor error %d\n",
rc);
@@ -234,7 +234,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
return;
}
- rc = sensor_cpu_power->ops->get_value(sensor_cpu_power, &power);
+ rc = wf_sensor_get(sensor_cpu_power, &power);
if (rc) {
printk(KERN_WARNING "windfarm: CPU power sensor error %d\n",
rc);
@@ -261,8 +261,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
st->cpu_setpoint = new_setpoint;
readjust:
if (fan_cpu_main && wf_smu_failure_state == 0) {
- rc = fan_cpu_main->ops->set_value(fan_cpu_main,
- st->cpu_setpoint);
+ rc = wf_control_set(fan_cpu_main, st->cpu_setpoint);
if (rc) {
printk(KERN_WARNING "windfarm: CPU main fan"
" error %d\n", rc);
@@ -270,8 +269,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
}
}
if (fan_cpu_second && wf_smu_failure_state == 0) {
- rc = fan_cpu_second->ops->set_value(fan_cpu_second,
- st->cpu_setpoint);
+ rc = wf_control_set(fan_cpu_second, st->cpu_setpoint);
if (rc) {
printk(KERN_WARNING "windfarm: CPU second fan"
" error %d\n", rc);
@@ -279,8 +277,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
}
}
if (fan_cpu_third && wf_smu_failure_state == 0) {
- rc = fan_cpu_main->ops->set_value(fan_cpu_third,
- st->cpu_setpoint);
+ rc = wf_control_set(fan_cpu_third, st->cpu_setpoint);
if (rc) {
printk(KERN_WARNING "windfarm: CPU third fan"
" error %d\n", rc);
@@ -312,8 +309,8 @@ static void wf_smu_create_drive_fans(void)
/* Fill PID params */
param.additive = (fan_hd->type == WF_CONTROL_RPM_FAN);
- param.min = fan_hd->ops->get_min(fan_hd);
- param.max = fan_hd->ops->get_max(fan_hd);
+ param.min = wf_control_get_min(fan_hd);
+ param.max = wf_control_get_max(fan_hd);
wf_pid_init(&wf_smu_drive_fans->pid, &param);
DBG("wf: Drive Fan control initialized.\n");
@@ -338,7 +335,7 @@ static void wf_smu_drive_fans_tick(struct wf_smu_drive_fans_state *st)
}
st->ticks = st->pid.param.interval;
- rc = sensor_hd_temp->ops->get_value(sensor_hd_temp, &temp);
+ rc = wf_sensor_get(sensor_hd_temp, &temp);
if (rc) {
printk(KERN_WARNING "windfarm: HD temp sensor error %d\n",
rc);
@@ -361,7 +358,7 @@ static void wf_smu_drive_fans_tick(struct wf_smu_drive_fans_state *st)
st->setpoint = new_setpoint;
readjust:
if (fan_hd && wf_smu_failure_state == 0) {
- rc = fan_hd->ops->set_value(fan_hd, st->setpoint);
+ rc = wf_control_set(fan_hd, st->setpoint);
if (rc) {
printk(KERN_WARNING "windfarm: HD fan error %d\n",
rc);
@@ -393,8 +390,8 @@ static void wf_smu_create_slots_fans(void)
/* Fill PID params */
param.additive = (fan_slots->type == WF_CONTROL_RPM_FAN);
- param.min = fan_slots->ops->get_min(fan_slots);
- param.max = fan_slots->ops->get_max(fan_slots);
+ param.min = wf_control_get_min(fan_slots);
+ param.max = wf_control_get_max(fan_slots);
wf_pid_init(&wf_smu_slots_fans->pid, &param);
DBG("wf: Slots Fan control initialized.\n");
@@ -419,7 +416,7 @@ static void wf_smu_slots_fans_tick(struct wf_smu_slots_fans_state *st)
}
st->ticks = st->pid.param.interval;
- rc = sensor_slots_power->ops->get_value(sensor_slots_power, &power);
+ rc = wf_sensor_get(sensor_slots_power, &power);
if (rc) {
printk(KERN_WARNING "windfarm: Slots power sensor error %d\n",
rc);
@@ -444,7 +441,7 @@ static void wf_smu_slots_fans_tick(struct wf_smu_slots_fans_state *st)
st->setpoint = new_setpoint;
readjust:
if (fan_slots && wf_smu_failure_state == 0) {
- rc = fan_slots->ops->set_value(fan_slots, st->setpoint);
+ rc = wf_control_set(fan_slots, st->setpoint);
if (rc) {
printk(KERN_WARNING "windfarm: Slots fan error %d\n",
rc);
diff --git a/drivers/macintosh/windfarm_rm31.c b/drivers/macintosh/windfarm_rm31.c
new file mode 100644
index 000000000000..3eca6d4b52fc
--- /dev/null
+++ b/drivers/macintosh/windfarm_rm31.c
@@ -0,0 +1,740 @@
+/*
+ * Windfarm PowerMac thermal control.
+ * Control loops for RackMack3,1 (Xserve G5)
+ *
+ * Copyright (C) 2012 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * Use and redistribute under the terms of the GNU GPL v2.
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <asm/prom.h>
+#include <asm/smu.h>
+
+#include "windfarm.h"
+#include "windfarm_pid.h"
+#include "windfarm_mpu.h"
+
+#define VERSION "1.0"
+
+#undef DEBUG
+#undef LOTSA_DEBUG
+
+#ifdef DEBUG
+#define DBG(args...) printk(args)
+#else
+#define DBG(args...) do { } while(0)
+#endif
+
+#ifdef LOTSA_DEBUG
+#define DBG_LOTS(args...) printk(args)
+#else
+#define DBG_LOTS(args...) do { } while(0)
+#endif
+
+/* define this to force CPU overtemp to 60 degree, useful for testing
+ * the overtemp code
+ */
+#undef HACKED_OVERTEMP
+
+/* We currently only handle 2 chips */
+#define NR_CHIPS 2
+#define NR_CPU_FANS 3 * NR_CHIPS
+
+/* Controls and sensors */
+static struct wf_sensor *sens_cpu_temp[NR_CHIPS];
+static struct wf_sensor *sens_cpu_volts[NR_CHIPS];
+static struct wf_sensor *sens_cpu_amps[NR_CHIPS];
+static struct wf_sensor *backside_temp;
+static struct wf_sensor *slots_temp;
+static struct wf_sensor *dimms_temp;
+
+static struct wf_control *cpu_fans[NR_CHIPS][3];
+static struct wf_control *backside_fan;
+static struct wf_control *slots_fan;
+static struct wf_control *cpufreq_clamp;
+
+/* We keep a temperature history for average calculation of 180s */
+#define CPU_TEMP_HIST_SIZE 180
+
+/* PID loop state */
+static const struct mpu_data *cpu_mpu_data[NR_CHIPS];
+static struct wf_cpu_pid_state cpu_pid[NR_CHIPS];
+static u32 cpu_thist[CPU_TEMP_HIST_SIZE];
+static int cpu_thist_pt;
+static s64 cpu_thist_total;
+static s32 cpu_all_tmax = 100 << 16;
+static struct wf_pid_state backside_pid;
+static int backside_tick;
+static struct wf_pid_state slots_pid;
+static int slots_tick;
+static int slots_speed;
+static struct wf_pid_state dimms_pid;
+static int dimms_output_clamp;
+
+static int nr_chips;
+static bool have_all_controls;
+static bool have_all_sensors;
+static bool started;
+
+static int failure_state;
+#define FAILURE_SENSOR 1
+#define FAILURE_FAN 2
+#define FAILURE_PERM 4
+#define FAILURE_LOW_OVERTEMP 8
+#define FAILURE_HIGH_OVERTEMP 16
+
+/* Overtemp values */
+#define LOW_OVER_AVERAGE 0
+#define LOW_OVER_IMMEDIATE (10 << 16)
+#define LOW_OVER_CLEAR ((-10) << 16)
+#define HIGH_OVER_IMMEDIATE (14 << 16)
+#define HIGH_OVER_AVERAGE (10 << 16)
+#define HIGH_OVER_IMMEDIATE (14 << 16)
+
+
+static void cpu_max_all_fans(void)
+{
+ int i;
+
+ /* We max all CPU fans in case of a sensor error. We also do the
+ * cpufreq clamping now, even if it's supposedly done later by the
+ * generic code anyway, we do it earlier here to react faster
+ */
+ if (cpufreq_clamp)
+ wf_control_set_max(cpufreq_clamp);
+ for (i = 0; i < nr_chips; i++) {
+ if (cpu_fans[i][0])
+ wf_control_set_max(cpu_fans[i][0]);
+ if (cpu_fans[i][1])
+ wf_control_set_max(cpu_fans[i][1]);
+ if (cpu_fans[i][2])
+ wf_control_set_max(cpu_fans[i][2]);
+ }
+}
+
+static int cpu_check_overtemp(s32 temp)
+{
+ int new_state = 0;
+ s32 t_avg, t_old;
+ static bool first = true;
+
+ /* First check for immediate overtemps */
+ if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) {
+ new_state |= FAILURE_LOW_OVERTEMP;
+ if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Overtemp due to immediate CPU"
+ " temperature !\n");
+ }
+ if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) {
+ new_state |= FAILURE_HIGH_OVERTEMP;
+ if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Critical overtemp due to"
+ " immediate CPU temperature !\n");
+ }
+
+ /*
+ * The first time around, initialize the array with the first
+ * temperature reading
+ */
+ if (first) {
+ int i;
+
+ cpu_thist_total = 0;
+ for (i = 0; i < CPU_TEMP_HIST_SIZE; i++) {
+ cpu_thist[i] = temp;
+ cpu_thist_total += temp;
+ }
+ first = false;
+ }
+
+ /*
+ * We calculate a history of max temperatures and use that for the
+ * overtemp management
+ */
+ t_old = cpu_thist[cpu_thist_pt];
+ cpu_thist[cpu_thist_pt] = temp;
+ cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE;
+ cpu_thist_total -= t_old;
+ cpu_thist_total += temp;
+ t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE;
+
+ DBG_LOTS(" t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
+ FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp));
+
+ /* Now check for average overtemps */
+ if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) {
+ new_state |= FAILURE_LOW_OVERTEMP;
+ if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Overtemp due to average CPU"
+ " temperature !\n");
+ }
+ if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) {
+ new_state |= FAILURE_HIGH_OVERTEMP;
+ if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Critical overtemp due to"
+ " average CPU temperature !\n");
+ }
+
+ /* Now handle overtemp conditions. We don't currently use the windfarm
+ * overtemp handling core as it's not fully suited to the needs of those
+ * new machine. This will be fixed later.
+ */
+ if (new_state) {
+ /* High overtemp -> immediate shutdown */
+ if (new_state & FAILURE_HIGH_OVERTEMP)
+ machine_power_off();
+ if ((failure_state & new_state) != new_state)
+ cpu_max_all_fans();
+ failure_state |= new_state;
+ } else if ((failure_state & FAILURE_LOW_OVERTEMP) &&
+ (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) {
+ printk(KERN_ERR "windfarm: Overtemp condition cleared !\n");
+ failure_state &= ~FAILURE_LOW_OVERTEMP;
+ }
+
+ return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP);
+}
+
+static int read_one_cpu_vals(int cpu, s32 *temp, s32 *power)
+{
+ s32 dtemp, volts, amps;
+ int rc;
+
+ /* Get diode temperature */
+ rc = wf_sensor_get(sens_cpu_temp[cpu], &dtemp);
+ if (rc) {
+ DBG(" CPU%d: temp reading error !\n", cpu);
+ return -EIO;
+ }
+ DBG_LOTS(" CPU%d: temp = %d.%03d\n", cpu, FIX32TOPRINT((dtemp)));
+ *temp = dtemp;
+
+ /* Get voltage */
+ rc = wf_sensor_get(sens_cpu_volts[cpu], &volts);
+ if (rc) {
+ DBG(" CPU%d, volts reading error !\n", cpu);
+ return -EIO;
+ }
+ DBG_LOTS(" CPU%d: volts = %d.%03d\n", cpu, FIX32TOPRINT((volts)));
+
+ /* Get current */
+ rc = wf_sensor_get(sens_cpu_amps[cpu], &amps);
+ if (rc) {
+ DBG(" CPU%d, current reading error !\n", cpu);
+ return -EIO;
+ }
+ DBG_LOTS(" CPU%d: amps = %d.%03d\n", cpu, FIX32TOPRINT((amps)));
+
+ /* Calculate power */
+
+ /* Scale voltage and current raw sensor values according to fixed scales
+ * obtained in Darwin and calculate power from I and V
+ */
+ *power = (((u64)volts) * ((u64)amps)) >> 16;
+
+ DBG_LOTS(" CPU%d: power = %d.%03d\n", cpu, FIX32TOPRINT((*power)));
+
+ return 0;
+
+}
+
+static void cpu_fans_tick(void)
+{
+ int err, cpu, i;
+ s32 speed, temp, power, t_max = 0;
+
+ DBG_LOTS("* cpu fans_tick_split()\n");
+
+ for (cpu = 0; cpu < nr_chips; ++cpu) {
+ struct wf_cpu_pid_state *sp = &cpu_pid[cpu];
+
+ /* Read current speed */
+ wf_control_get(cpu_fans[cpu][0], &sp->target);
+
+ err = read_one_cpu_vals(cpu, &temp, &power);
+ if (err) {
+ failure_state |= FAILURE_SENSOR;
+ cpu_max_all_fans();
+ return;
+ }
+
+ /* Keep track of highest temp */
+ t_max = max(t_max, temp);
+
+ /* Handle possible overtemps */
+ if (cpu_check_overtemp(t_max))
+ return;
+
+ /* Run PID */
+ wf_cpu_pid_run(sp, power, temp);
+
+ DBG_LOTS(" CPU%d: target = %d RPM\n", cpu, sp->target);
+
+ /* Apply DIMMs clamp */
+ speed = max(sp->target, dimms_output_clamp);
+
+ /* Apply result to all cpu fans */
+ for (i = 0; i < 3; i++) {
+ err = wf_control_set(cpu_fans[cpu][i], speed);
+ if (err) {
+ pr_warning("wf_rm31: Fan %s reports error %d\n",
+ cpu_fans[cpu][i]->name, err);
+ failure_state |= FAILURE_FAN;
+ }
+ }
+ }
+}
+
+/* Implementation... */
+static int cpu_setup_pid(int cpu)
+{
+ struct wf_cpu_pid_param pid;
+ const struct mpu_data *mpu = cpu_mpu_data[cpu];
+ s32 tmax, ttarget, ptarget;
+ int fmin, fmax, hsize;
+
+ /* Get PID params from the appropriate MPU EEPROM */
+ tmax = mpu->tmax << 16;
+ ttarget = mpu->ttarget << 16;
+ ptarget = ((s32)(mpu->pmaxh - mpu->padjmax)) << 16;
+
+ DBG("wf_72: CPU%d ttarget = %d.%03d, tmax = %d.%03d\n",
+ cpu, FIX32TOPRINT(ttarget), FIX32TOPRINT(tmax));
+
+ /* We keep a global tmax for overtemp calculations */
+ if (tmax < cpu_all_tmax)
+ cpu_all_tmax = tmax;
+
+ /* Set PID min/max by using the rear fan min/max */
+ fmin = wf_control_get_min(cpu_fans[cpu][0]);
+ fmax = wf_control_get_max(cpu_fans[cpu][0]);
+ DBG("wf_72: CPU%d max RPM range = [%d..%d]\n", cpu, fmin, fmax);
+
+ /* History size */
+ hsize = min_t(int, mpu->tguardband, WF_PID_MAX_HISTORY);
+ DBG("wf_72: CPU%d history size = %d\n", cpu, hsize);
+
+ /* Initialize PID loop */
+ pid.interval = 1; /* seconds */
+ pid.history_len = hsize;
+ pid.gd = mpu->pid_gd;
+ pid.gp = mpu->pid_gp;
+ pid.gr = mpu->pid_gr;
+ pid.tmax = tmax;
+ pid.ttarget = ttarget;
+ pid.pmaxadj = ptarget;
+ pid.min = fmin;
+ pid.max = fmax;
+
+ wf_cpu_pid_init(&cpu_pid[cpu], &pid);
+ cpu_pid[cpu].target = 4000;
+
+ return 0;
+}
+
+/* Backside/U3 fan */
+static struct wf_pid_param backside_param = {
+ .interval = 1,
+ .history_len = 2,
+ .gd = 0x00500000,
+ .gp = 0x0004cccc,
+ .gr = 0,
+ .itarget = 70 << 16,
+ .additive = 0,
+ .min = 20,
+ .max = 100,
+};
+
+/* DIMMs temperature (clamp the backside fan) */
+static struct wf_pid_param dimms_param = {
+ .interval = 1,
+ .history_len = 20,
+ .gd = 0,
+ .gp = 0,
+ .gr = 0x06553600,
+ .itarget = 50 << 16,
+ .additive = 0,
+ .min = 4000,
+ .max = 14000,
+};
+
+static void backside_fan_tick(void)
+{
+ s32 temp, dtemp;
+ int speed, dspeed, fan_min;
+ int err;
+
+ if (!backside_fan || !backside_temp || !dimms_temp || !backside_tick)
+ return;
+ if (--backside_tick > 0)
+ return;
+ backside_tick = backside_pid.param.interval;
+
+ DBG_LOTS("* backside fans tick\n");
+
+ /* Update fan speed from actual fans */
+ err = wf_control_get(backside_fan, &speed);
+ if (!err)
+ backside_pid.target = speed;
+
+ err = wf_sensor_get(backside_temp, &temp);
+ if (err) {
+ printk(KERN_WARNING "windfarm: U3 temp sensor error %d\n",
+ err);
+ failure_state |= FAILURE_SENSOR;
+ wf_control_set_max(backside_fan);
+ return;
+ }
+ speed = wf_pid_run(&backside_pid, temp);
+
+ DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n",
+ FIX32TOPRINT(temp), speed);
+
+ err = wf_sensor_get(dimms_temp, &dtemp);
+ if (err) {
+ printk(KERN_WARNING "windfarm: DIMMs temp sensor error %d\n",
+ err);
+ failure_state |= FAILURE_SENSOR;
+ wf_control_set_max(backside_fan);
+ return;
+ }
+ dspeed = wf_pid_run(&dimms_pid, dtemp);
+ dimms_output_clamp = dspeed;
+
+ fan_min = (dspeed * 100) / 14000;
+ fan_min = max(fan_min, backside_param.min);
+ speed = max(speed, fan_min);
+
+ err = wf_control_set(backside_fan, speed);
+ if (err) {
+ printk(KERN_WARNING "windfarm: backside fan error %d\n", err);
+ failure_state |= FAILURE_FAN;
+ }
+}
+
+static void backside_setup_pid(void)
+{
+ /* first time initialize things */
+ s32 fmin = wf_control_get_min(backside_fan);
+ s32 fmax = wf_control_get_max(backside_fan);
+ struct wf_pid_param param;
+
+ param = backside_param;
+ param.min = max(param.min, fmin);
+ param.max = min(param.max, fmax);
+ wf_pid_init(&backside_pid, &param);
+
+ param = dimms_param;
+ wf_pid_init(&dimms_pid, &param);
+
+ backside_tick = 1;
+
+ pr_info("wf_rm31: Backside control loop started.\n");
+}
+
+/* Slots fan */
+static const struct wf_pid_param slots_param = {
+ .interval = 5,
+ .history_len = 2,
+ .gd = 30 << 20,
+ .gp = 5 << 20,
+ .gr = 0,
+ .itarget = 40 << 16,
+ .additive = 1,
+ .min = 300,
+ .max = 4000,
+};
+
+static void slots_fan_tick(void)
+{
+ s32 temp;
+ int speed;
+ int err;
+
+ if (!slots_fan || !slots_temp || !slots_tick)
+ return;
+ if (--slots_tick > 0)
+ return;
+ slots_tick = slots_pid.param.interval;
+
+ DBG_LOTS("* slots fans tick\n");
+
+ err = wf_sensor_get(slots_temp, &temp);
+ if (err) {
+ pr_warning("wf_rm31: slots temp sensor error %d\n", err);
+ failure_state |= FAILURE_SENSOR;
+ wf_control_set_max(slots_fan);
+ return;
+ }
+ speed = wf_pid_run(&slots_pid, temp);
+
+ DBG_LOTS("slots PID temp=%d.%.3d speed=%d\n",
+ FIX32TOPRINT(temp), speed);
+
+ slots_speed = speed;
+ err = wf_control_set(slots_fan, speed);
+ if (err) {
+ printk(KERN_WARNING "windfarm: slots bay fan error %d\n", err);
+ failure_state |= FAILURE_FAN;
+ }
+}
+
+static void slots_setup_pid(void)
+{
+ /* first time initialize things */
+ s32 fmin = wf_control_get_min(slots_fan);
+ s32 fmax = wf_control_get_max(slots_fan);
+ struct wf_pid_param param = slots_param;
+
+ param.min = max(param.min, fmin);
+ param.max = min(param.max, fmax);
+ wf_pid_init(&slots_pid, &param);
+ slots_tick = 1;
+
+ pr_info("wf_rm31: Slots control loop started.\n");
+}
+
+static void set_fail_state(void)
+{
+ cpu_max_all_fans();
+
+ if (backside_fan)
+ wf_control_set_max(backside_fan);
+ if (slots_fan)
+ wf_control_set_max(slots_fan);
+}
+
+static void rm31_tick(void)
+{
+ int i, last_failure;
+
+ if (!started) {
+ started = 1;
+ printk(KERN_INFO "windfarm: CPUs control loops started.\n");
+ for (i = 0; i < nr_chips; ++i) {
+ if (cpu_setup_pid(i) < 0) {
+ failure_state = FAILURE_PERM;
+ set_fail_state();
+ break;
+ }
+ }
+ DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax));
+
+ backside_setup_pid();
+ slots_setup_pid();
+
+#ifdef HACKED_OVERTEMP
+ cpu_all_tmax = 60 << 16;
+#endif
+ }
+
+ /* Permanent failure, bail out */
+ if (failure_state & FAILURE_PERM)
+ return;
+
+ /*
+ * Clear all failure bits except low overtemp which will be eventually
+ * cleared by the control loop itself
+ */
+ last_failure = failure_state;
+ failure_state &= FAILURE_LOW_OVERTEMP;
+ backside_fan_tick();
+ slots_fan_tick();
+
+ /* We do CPUs last because they can be clamped high by
+ * DIMM temperature
+ */
+ cpu_fans_tick();
+
+ DBG_LOTS(" last_failure: 0x%x, failure_state: %x\n",
+ last_failure, failure_state);
+
+ /* Check for failures. Any failure causes cpufreq clamping */
+ if (failure_state && last_failure == 0 && cpufreq_clamp)
+ wf_control_set_max(cpufreq_clamp);
+ if (failure_state == 0 && last_failure && cpufreq_clamp)
+ wf_control_set_min(cpufreq_clamp);
+
+ /* That's it for now, we might want to deal with other failures
+ * differently in the future though
+ */
+}
+
+static void rm31_new_control(struct wf_control *ct)
+{
+ bool all_controls;
+
+ if (!strcmp(ct->name, "cpu-fan-a-0"))
+ cpu_fans[0][0] = ct;
+ else if (!strcmp(ct->name, "cpu-fan-b-0"))
+ cpu_fans[0][1] = ct;
+ else if (!strcmp(ct->name, "cpu-fan-c-0"))
+ cpu_fans[0][2] = ct;
+ else if (!strcmp(ct->name, "cpu-fan-a-1"))
+ cpu_fans[1][0] = ct;
+ else if (!strcmp(ct->name, "cpu-fan-b-1"))
+ cpu_fans[1][1] = ct;
+ else if (!strcmp(ct->name, "cpu-fan-c-1"))
+ cpu_fans[1][2] = ct;
+ else if (!strcmp(ct->name, "backside-fan"))
+ backside_fan = ct;
+ else if (!strcmp(ct->name, "slots-fan"))
+ slots_fan = ct;
+ else if (!strcmp(ct->name, "cpufreq-clamp"))
+ cpufreq_clamp = ct;
+
+ all_controls =
+ cpu_fans[0][0] &&
+ cpu_fans[0][1] &&
+ cpu_fans[0][2] &&
+ backside_fan &&
+ slots_fan;
+ if (nr_chips > 1)
+ all_controls &=
+ cpu_fans[1][0] &&
+ cpu_fans[1][1] &&
+ cpu_fans[1][2];
+ have_all_controls = all_controls;
+}
+
+
+static void rm31_new_sensor(struct wf_sensor *sr)
+{
+ bool all_sensors;
+
+ if (!strcmp(sr->name, "cpu-diode-temp-0"))
+ sens_cpu_temp[0] = sr;
+ else if (!strcmp(sr->name, "cpu-diode-temp-1"))
+ sens_cpu_temp[1] = sr;
+ else if (!strcmp(sr->name, "cpu-voltage-0"))
+ sens_cpu_volts[0] = sr;
+ else if (!strcmp(sr->name, "cpu-voltage-1"))
+ sens_cpu_volts[1] = sr;
+ else if (!strcmp(sr->name, "cpu-current-0"))
+ sens_cpu_amps[0] = sr;
+ else if (!strcmp(sr->name, "cpu-current-1"))
+ sens_cpu_amps[1] = sr;
+ else if (!strcmp(sr->name, "backside-temp"))
+ backside_temp = sr;
+ else if (!strcmp(sr->name, "slots-temp"))
+ slots_temp = sr;
+ else if (!strcmp(sr->name, "dimms-temp"))
+ dimms_temp = sr;
+
+ all_sensors =
+ sens_cpu_temp[0] &&
+ sens_cpu_volts[0] &&
+ sens_cpu_amps[0] &&
+ backside_temp &&
+ slots_temp &&
+ dimms_temp;
+ if (nr_chips > 1)
+ all_sensors &=
+ sens_cpu_temp[1] &&
+ sens_cpu_volts[1] &&
+ sens_cpu_amps[1];
+
+ have_all_sensors = all_sensors;
+}
+
+static int rm31_wf_notify(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ switch (event) {
+ case WF_EVENT_NEW_SENSOR:
+ rm31_new_sensor(data);
+ break;
+ case WF_EVENT_NEW_CONTROL:
+ rm31_new_control(data);
+ break;
+ case WF_EVENT_TICK:
+ if (have_all_controls && have_all_sensors)
+ rm31_tick();
+ }
+ return 0;
+}
+
+static struct notifier_block rm31_events = {
+ .notifier_call = rm31_wf_notify,
+};
+
+static int wf_rm31_probe(struct platform_device *dev)
+{
+ wf_register_client(&rm31_events);
+ return 0;
+}
+
+static int __devexit wf_rm31_remove(struct platform_device *dev)
+{
+ wf_unregister_client(&rm31_events);
+
+ /* should release all sensors and controls */
+ return 0;
+}
+
+static struct platform_driver wf_rm31_driver = {
+ .probe = wf_rm31_probe,
+ .remove = wf_rm31_remove,
+ .driver = {
+ .name = "windfarm",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init wf_rm31_init(void)
+{
+ struct device_node *cpu;
+ int i;
+
+ if (!of_machine_is_compatible("RackMac3,1"))
+ return -ENODEV;
+
+ /* Count the number of CPU cores */
+ nr_chips = 0;
+ for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; )
+ ++nr_chips;
+ if (nr_chips > NR_CHIPS)
+ nr_chips = NR_CHIPS;
+
+ pr_info("windfarm: Initializing for desktop G5 with %d chips\n",
+ nr_chips);
+
+ /* Get MPU data for each CPU */
+ for (i = 0; i < nr_chips; i++) {
+ cpu_mpu_data[i] = wf_get_mpu(i);
+ if (!cpu_mpu_data[i]) {
+ pr_err("wf_rm31: Failed to find MPU data for CPU %d\n", i);
+ return -ENXIO;
+ }
+ }
+
+#ifdef MODULE
+ request_module("windfarm_fcu_controls");
+ request_module("windfarm_lm75_sensor");
+ request_module("windfarm_lm87_sensor");
+ request_module("windfarm_ad7417_sensor");
+ request_module("windfarm_max6690_sensor");
+ request_module("windfarm_cpufreq_clamp");
+#endif /* MODULE */
+
+ platform_driver_register(&wf_rm31_driver);
+ return 0;
+}
+
+static void __exit wf_rm31_exit(void)
+{
+ platform_driver_unregister(&wf_rm31_driver);
+}
+
+module_init(wf_rm31_init);
+module_exit(wf_rm31_exit);
+
+MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
+MODULE_DESCRIPTION("Thermal control for Xserve G5");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:windfarm");
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c
index 3c2be5193fd5..c155a54e8638 100644
--- a/drivers/macintosh/windfarm_smu_controls.c
+++ b/drivers/macintosh/windfarm_smu_controls.c
@@ -172,7 +172,6 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node,
fct->fan_type = pwm_fan;
fct->ctrl.type = pwm_fan ? WF_CONTROL_PWM_FAN : WF_CONTROL_RPM_FAN;
- sysfs_attr_init(&fct->ctrl.attr.attr);
/* We use the name & location here the same way we do for SMU sensors,
* see the comment in windfarm_smu_sensors.c. The locations are a bit
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
index 65a8ff3e1f8e..426e810233d7 100644
--- a/drivers/macintosh/windfarm_smu_sat.c
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -20,7 +20,7 @@
#include "windfarm.h"
-#define VERSION "0.2"
+#define VERSION "1.0"
#define DEBUG
@@ -34,11 +34,12 @@
#define MAX_AGE msecs_to_jiffies(800)
struct wf_sat {
+ struct kref ref;
int nr;
- atomic_t refcnt;
struct mutex mutex;
unsigned long last_read; /* jiffies when cache last updated */
u8 cache[16];
+ struct list_head sensors;
struct i2c_client *i2c;
struct device_node *node;
};
@@ -46,11 +47,12 @@ struct wf_sat {
static struct wf_sat *sats[2];
struct wf_sat_sensor {
- int index;
- int index2; /* used for power sensors */
- int shift;
- struct wf_sat *sat;
- struct wf_sensor sens;
+ struct list_head link;
+ int index;
+ int index2; /* used for power sensors */
+ int shift;
+ struct wf_sat *sat;
+ struct wf_sensor sens;
};
#define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens)
@@ -142,7 +144,7 @@ static int wf_sat_read_cache(struct wf_sat *sat)
return 0;
}
-static int wf_sat_get(struct wf_sensor *sr, s32 *value)
+static int wf_sat_sensor_get(struct wf_sensor *sr, s32 *value)
{
struct wf_sat_sensor *sens = wf_to_sat(sr);
struct wf_sat *sat = sens->sat;
@@ -175,62 +177,34 @@ static int wf_sat_get(struct wf_sensor *sr, s32 *value)
return err;
}
-static void wf_sat_release(struct wf_sensor *sr)
+static void wf_sat_release(struct kref *ref)
+{
+ struct wf_sat *sat = container_of(ref, struct wf_sat, ref);
+
+ if (sat->nr >= 0)
+ sats[sat->nr] = NULL;
+ kfree(sat);
+}
+
+static void wf_sat_sensor_release(struct wf_sensor *sr)
{
struct wf_sat_sensor *sens = wf_to_sat(sr);
struct wf_sat *sat = sens->sat;
- if (atomic_dec_and_test(&sat->refcnt)) {
- if (sat->nr >= 0)
- sats[sat->nr] = NULL;
- kfree(sat);
- }
kfree(sens);
+ kref_put(&sat->ref, wf_sat_release);
}
static struct wf_sensor_ops wf_sat_ops = {
- .get_value = wf_sat_get,
- .release = wf_sat_release,
+ .get_value = wf_sat_sensor_get,
+ .release = wf_sat_sensor_release,
.owner = THIS_MODULE,
};
-static struct i2c_driver wf_sat_driver;
-
-static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
-{
- struct i2c_board_info info;
- struct i2c_client *client;
- const u32 *reg;
- u8 addr;
-
- reg = of_get_property(dev, "reg", NULL);
- if (reg == NULL)
- return;
- addr = *reg;
- DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr);
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = (addr >> 1) & 0x7f;
- info.platform_data = dev;
- strlcpy(info.type, "wf_sat", I2C_NAME_SIZE);
-
- client = i2c_new_device(adapter, &info);
- if (client == NULL) {
- printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n");
- return;
- }
-
- /*
- * Let i2c-core delete that device on driver removal.
- * This is safe because i2c-core holds the core_lock mutex for us.
- */
- list_add_tail(&client->detected, &wf_sat_driver.clients);
-}
-
static int wf_sat_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct device_node *dev = client->dev.platform_data;
+ struct device_node *dev = client->dev.of_node;
struct wf_sat *sat;
struct wf_sat_sensor *sens;
const u32 *reg;
@@ -246,9 +220,10 @@ static int wf_sat_probe(struct i2c_client *client,
return -ENOMEM;
sat->nr = -1;
sat->node = of_node_get(dev);
- atomic_set(&sat->refcnt, 0);
+ kref_init(&sat->ref);
mutex_init(&sat->mutex);
sat->i2c = client;
+ INIT_LIST_HEAD(&sat->sensors);
i2c_set_clientdata(client, sat);
vsens[0] = vsens[1] = -1;
@@ -310,14 +285,15 @@ static int wf_sat_probe(struct i2c_client *client,
sens->index2 = -1;
sens->shift = shift;
sens->sat = sat;
- atomic_inc(&sat->refcnt);
sens->sens.ops = &wf_sat_ops;
sens->sens.name = (char *) (sens + 1);
- snprintf(sens->sens.name, 16, "%s-%d", name, cpu);
+ snprintf((char *)sens->sens.name, 16, "%s-%d", name, cpu);
- if (wf_register_sensor(&sens->sens)) {
- atomic_dec(&sat->refcnt);
+ if (wf_register_sensor(&sens->sens))
kfree(sens);
+ else {
+ list_add(&sens->link, &sat->sensors);
+ kref_get(&sat->ref);
}
}
@@ -336,14 +312,15 @@ static int wf_sat_probe(struct i2c_client *client,
sens->index2 = isens[core];
sens->shift = 0;
sens->sat = sat;
- atomic_inc(&sat->refcnt);
sens->sens.ops = &wf_sat_ops;
sens->sens.name = (char *) (sens + 1);
- snprintf(sens->sens.name, 16, "cpu-power-%d", cpu);
+ snprintf((char *)sens->sens.name, 16, "cpu-power-%d", cpu);
- if (wf_register_sensor(&sens->sens)) {
- atomic_dec(&sat->refcnt);
+ if (wf_register_sensor(&sens->sens))
kfree(sens);
+ else {
+ list_add(&sens->link, &sat->sensors);
+ kref_get(&sat->ref);
}
}
@@ -353,42 +330,35 @@ static int wf_sat_probe(struct i2c_client *client,
return 0;
}
-static int wf_sat_attach(struct i2c_adapter *adapter)
-{
- struct device_node *busnode, *dev = NULL;
- struct pmac_i2c_bus *bus;
-
- bus = pmac_i2c_adapter_to_bus(adapter);
- if (bus == NULL)
- return -ENODEV;
- busnode = pmac_i2c_get_bus_node(bus);
-
- while ((dev = of_get_next_child(busnode, dev)) != NULL)
- if (of_device_is_compatible(dev, "smu-sat"))
- wf_sat_create(adapter, dev);
- return 0;
-}
-
static int wf_sat_remove(struct i2c_client *client)
{
struct wf_sat *sat = i2c_get_clientdata(client);
+ struct wf_sat_sensor *sens;
- /* XXX TODO */
-
+ /* release sensors */
+ while(!list_empty(&sat->sensors)) {
+ sens = list_first_entry(&sat->sensors,
+ struct wf_sat_sensor, link);
+ list_del(&sens->link);
+ wf_unregister_sensor(&sens->sens);
+ }
sat->i2c = NULL;
+ i2c_set_clientdata(client, NULL);
+ kref_put(&sat->ref, wf_sat_release);
+
return 0;
}
static const struct i2c_device_id wf_sat_id[] = {
- { "wf_sat", 0 },
+ { "MAC,smu-sat", 0 },
{ }
};
+MODULE_DEVICE_TABLE(i2c, wf_sat_id);
static struct i2c_driver wf_sat_driver = {
.driver = {
.name = "wf_smu_sat",
},
- .attach_adapter = wf_sat_attach,
.probe = wf_sat_probe,
.remove = wf_sat_remove,
.id_table = wf_sat_id,
@@ -399,15 +369,13 @@ static int __init sat_sensors_init(void)
return i2c_add_driver(&wf_sat_driver);
}
-#if 0 /* uncomment when module_exit() below is uncommented */
static void __exit sat_sensors_exit(void)
{
i2c_del_driver(&wf_sat_driver);
}
-#endif
module_init(sat_sensors_init);
-/*module_exit(sat_sensors_exit); Uncomment when cleanup is implemented */
+module_exit(sat_sensors_exit);
MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
MODULE_DESCRIPTION("SMU satellite sensors for PowerMac thermal control");
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 17e2b472e16d..15dbe03117e4 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -45,7 +45,7 @@ static inline char *bmname(struct bitmap *bitmap)
* if we find our page, we increment the page's refcount so that it stays
* allocated while we're using it
*/
-static int bitmap_checkpage(struct bitmap *bitmap,
+static int bitmap_checkpage(struct bitmap_counts *bitmap,
unsigned long page, int create)
__releases(bitmap->lock)
__acquires(bitmap->lock)
@@ -76,8 +76,7 @@ __acquires(bitmap->lock)
spin_lock_irq(&bitmap->lock);
if (mappage == NULL) {
- pr_debug("%s: bitmap map page allocation failed, hijacking\n",
- bmname(bitmap));
+ pr_debug("md/bitmap: map page allocation failed, hijacking\n");
/* failed - set the hijacked flag so that we can use the
* pointer as a counter */
if (!bitmap->bp[page].map)
@@ -100,7 +99,7 @@ __acquires(bitmap->lock)
/* if page is completely empty, put it back on the free list, or dealloc it */
/* if page was hijacked, unmark the flag so it might get alloced next time */
/* Note: lock should be held when calling this */
-static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
+static void bitmap_checkfree(struct bitmap_counts *bitmap, unsigned long page)
{
char *ptr;
@@ -130,22 +129,14 @@ static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
*/
/* IO operations when bitmap is stored near all superblocks */
-static struct page *read_sb_page(struct mddev *mddev, loff_t offset,
- struct page *page,
- unsigned long index, int size)
+static int read_sb_page(struct mddev *mddev, loff_t offset,
+ struct page *page,
+ unsigned long index, int size)
{
/* choose a good rdev and read the page from there */
struct md_rdev *rdev;
sector_t target;
- int did_alloc = 0;
-
- if (!page) {
- page = alloc_page(GFP_KERNEL);
- if (!page)
- return ERR_PTR(-ENOMEM);
- did_alloc = 1;
- }
rdev_for_each(rdev, mddev) {
if (! test_bit(In_sync, &rdev->flags)
@@ -158,15 +149,10 @@ static struct page *read_sb_page(struct mddev *mddev, loff_t offset,
roundup(size, bdev_logical_block_size(rdev->bdev)),
page, READ, true)) {
page->index = index;
- attach_page_buffers(page, NULL); /* so that free_buffer will
- * quietly no-op */
- return page;
+ return 0;
}
}
- if (did_alloc)
- put_page(page);
- return ERR_PTR(-EIO);
-
+ return -EIO;
}
static struct md_rdev *next_active_rdev(struct md_rdev *rdev, struct mddev *mddev)
@@ -208,6 +194,7 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
struct md_rdev *rdev = NULL;
struct block_device *bdev;
struct mddev *mddev = bitmap->mddev;
+ struct bitmap_storage *store = &bitmap->storage;
while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {
int size = PAGE_SIZE;
@@ -215,9 +202,13 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
bdev = (rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev;
- if (page->index == bitmap->file_pages-1)
- size = roundup(bitmap->last_page_size,
+ if (page->index == store->file_pages-1) {
+ int last_page_size = store->bytes & (PAGE_SIZE-1);
+ if (last_page_size == 0)
+ last_page_size = PAGE_SIZE;
+ size = roundup(last_page_size,
bdev_logical_block_size(bdev));
+ }
/* Just make sure we aren't corrupting data or
* metadata
*/
@@ -276,10 +267,10 @@ static void write_page(struct bitmap *bitmap, struct page *page, int wait)
{
struct buffer_head *bh;
- if (bitmap->file == NULL) {
+ if (bitmap->storage.file == NULL) {
switch (write_sb_page(bitmap, page, wait)) {
case -EINVAL:
- bitmap->flags |= BITMAP_WRITE_ERROR;
+ set_bit(BITMAP_WRITE_ERROR, &bitmap->flags);
}
} else {
@@ -297,20 +288,16 @@ static void write_page(struct bitmap *bitmap, struct page *page, int wait)
wait_event(bitmap->write_wait,
atomic_read(&bitmap->pending_writes)==0);
}
- if (bitmap->flags & BITMAP_WRITE_ERROR)
+ if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags))
bitmap_file_kick(bitmap);
}
static void end_bitmap_write(struct buffer_head *bh, int uptodate)
{
struct bitmap *bitmap = bh->b_private;
- unsigned long flags;
- if (!uptodate) {
- spin_lock_irqsave(&bitmap->lock, flags);
- bitmap->flags |= BITMAP_WRITE_ERROR;
- spin_unlock_irqrestore(&bitmap->lock, flags);
- }
+ if (!uptodate)
+ set_bit(BITMAP_WRITE_ERROR, &bitmap->flags);
if (atomic_dec_and_test(&bitmap->pending_writes))
wake_up(&bitmap->write_wait);
}
@@ -325,8 +312,12 @@ __clear_page_buffers(struct page *page)
}
static void free_buffers(struct page *page)
{
- struct buffer_head *bh = page_buffers(page);
+ struct buffer_head *bh;
+ if (!PagePrivate(page))
+ return;
+
+ bh = page_buffers(page);
while (bh) {
struct buffer_head *next = bh->b_this_page;
free_buffer_head(bh);
@@ -343,11 +334,12 @@ static void free_buffers(struct page *page)
* This usage is similar to how swap files are handled, and allows us
* to write to a file with no concerns of memory allocation failing.
*/
-static struct page *read_page(struct file *file, unsigned long index,
- struct bitmap *bitmap,
- unsigned long count)
+static int read_page(struct file *file, unsigned long index,
+ struct bitmap *bitmap,
+ unsigned long count,
+ struct page *page)
{
- struct page *page = NULL;
+ int ret = 0;
struct inode *inode = file->f_path.dentry->d_inode;
struct buffer_head *bh;
sector_t block;
@@ -355,16 +347,9 @@ static struct page *read_page(struct file *file, unsigned long index,
pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE,
(unsigned long long)index << PAGE_SHIFT);
- page = alloc_page(GFP_KERNEL);
- if (!page)
- page = ERR_PTR(-ENOMEM);
- if (IS_ERR(page))
- goto out;
-
bh = alloc_page_buffers(page, 1<<inode->i_blkbits, 0);
if (!bh) {
- put_page(page);
- page = ERR_PTR(-ENOMEM);
+ ret = -ENOMEM;
goto out;
}
attach_page_buffers(page, bh);
@@ -376,8 +361,7 @@ static struct page *read_page(struct file *file, unsigned long index,
bh->b_blocknr = bmap(inode, block);
if (bh->b_blocknr == 0) {
/* Cannot use this file! */
- free_buffers(page);
- page = ERR_PTR(-EINVAL);
+ ret = -EINVAL;
goto out;
}
bh->b_bdev = inode->i_sb->s_bdev;
@@ -400,17 +384,15 @@ static struct page *read_page(struct file *file, unsigned long index,
wait_event(bitmap->write_wait,
atomic_read(&bitmap->pending_writes)==0);
- if (bitmap->flags & BITMAP_WRITE_ERROR) {
- free_buffers(page);
- page = ERR_PTR(-EIO);
- }
+ if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags))
+ ret = -EIO;
out:
- if (IS_ERR(page))
- printk(KERN_ALERT "md: bitmap read error: (%dB @ %llu): %ld\n",
+ if (ret)
+ printk(KERN_ALERT "md: bitmap read error: (%dB @ %llu): %d\n",
(int)PAGE_SIZE,
(unsigned long long)index << PAGE_SHIFT,
- PTR_ERR(page));
- return page;
+ ret);
+ return ret;
}
/*
@@ -426,9 +408,9 @@ void bitmap_update_sb(struct bitmap *bitmap)
return;
if (bitmap->mddev->bitmap_info.external)
return;
- if (!bitmap->sb_page) /* no superblock */
+ if (!bitmap->storage.sb_page) /* no superblock */
return;
- sb = kmap_atomic(bitmap->sb_page);
+ sb = kmap_atomic(bitmap->storage.sb_page);
sb->events = cpu_to_le64(bitmap->mddev->events);
if (bitmap->mddev->events < bitmap->events_cleared)
/* rocking back to read-only */
@@ -438,8 +420,13 @@ void bitmap_update_sb(struct bitmap *bitmap)
/* Just in case these have been changed via sysfs: */
sb->daemon_sleep = cpu_to_le32(bitmap->mddev->bitmap_info.daemon_sleep/HZ);
sb->write_behind = cpu_to_le32(bitmap->mddev->bitmap_info.max_write_behind);
+ /* This might have been changed by a reshape */
+ sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors);
+ sb->chunksize = cpu_to_le32(bitmap->mddev->bitmap_info.chunksize);
+ sb->sectors_reserved = cpu_to_le32(bitmap->mddev->
+ bitmap_info.space);
kunmap_atomic(sb);
- write_page(bitmap, bitmap->sb_page, 1);
+ write_page(bitmap, bitmap->storage.sb_page, 1);
}
/* print out the bitmap file superblock */
@@ -447,9 +434,9 @@ void bitmap_print_sb(struct bitmap *bitmap)
{
bitmap_super_t *sb;
- if (!bitmap || !bitmap->sb_page)
+ if (!bitmap || !bitmap->storage.sb_page)
return;
- sb = kmap_atomic(bitmap->sb_page);
+ sb = kmap_atomic(bitmap->storage.sb_page);
printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
printk(KERN_DEBUG " magic: %08x\n", le32_to_cpu(sb->magic));
printk(KERN_DEBUG " version: %d\n", le32_to_cpu(sb->version));
@@ -488,15 +475,15 @@ static int bitmap_new_disk_sb(struct bitmap *bitmap)
unsigned long chunksize, daemon_sleep, write_behind;
int err = -EINVAL;
- bitmap->sb_page = alloc_page(GFP_KERNEL);
- if (IS_ERR(bitmap->sb_page)) {
- err = PTR_ERR(bitmap->sb_page);
- bitmap->sb_page = NULL;
+ bitmap->storage.sb_page = alloc_page(GFP_KERNEL);
+ if (IS_ERR(bitmap->storage.sb_page)) {
+ err = PTR_ERR(bitmap->storage.sb_page);
+ bitmap->storage.sb_page = NULL;
return err;
}
- bitmap->sb_page->index = 0;
+ bitmap->storage.sb_page->index = 0;
- sb = kmap_atomic(bitmap->sb_page);
+ sb = kmap_atomic(bitmap->storage.sb_page);
sb->magic = cpu_to_le32(BITMAP_MAGIC);
sb->version = cpu_to_le32(BITMAP_MAJOR_HI);
@@ -534,8 +521,8 @@ static int bitmap_new_disk_sb(struct bitmap *bitmap)
memcpy(sb->uuid, bitmap->mddev->uuid, 16);
- bitmap->flags |= BITMAP_STALE;
- sb->state |= cpu_to_le32(BITMAP_STALE);
+ set_bit(BITMAP_STALE, &bitmap->flags);
+ sb->state = cpu_to_le32(bitmap->flags);
bitmap->events_cleared = bitmap->mddev->events;
sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
@@ -551,31 +538,45 @@ static int bitmap_read_sb(struct bitmap *bitmap)
bitmap_super_t *sb;
unsigned long chunksize, daemon_sleep, write_behind;
unsigned long long events;
+ unsigned long sectors_reserved = 0;
int err = -EINVAL;
+ struct page *sb_page;
+ if (!bitmap->storage.file && !bitmap->mddev->bitmap_info.offset) {
+ chunksize = 128 * 1024 * 1024;
+ daemon_sleep = 5 * HZ;
+ write_behind = 0;
+ set_bit(BITMAP_STALE, &bitmap->flags);
+ err = 0;
+ goto out_no_sb;
+ }
/* page 0 is the superblock, read it... */
- if (bitmap->file) {
- loff_t isize = i_size_read(bitmap->file->f_mapping->host);
+ sb_page = alloc_page(GFP_KERNEL);
+ if (!sb_page)
+ return -ENOMEM;
+ bitmap->storage.sb_page = sb_page;
+
+ if (bitmap->storage.file) {
+ loff_t isize = i_size_read(bitmap->storage.file->f_mapping->host);
int bytes = isize > PAGE_SIZE ? PAGE_SIZE : isize;
- bitmap->sb_page = read_page(bitmap->file, 0, bitmap, bytes);
+ err = read_page(bitmap->storage.file, 0,
+ bitmap, bytes, sb_page);
} else {
- bitmap->sb_page = read_sb_page(bitmap->mddev,
- bitmap->mddev->bitmap_info.offset,
- NULL,
- 0, sizeof(bitmap_super_t));
+ err = read_sb_page(bitmap->mddev,
+ bitmap->mddev->bitmap_info.offset,
+ sb_page,
+ 0, sizeof(bitmap_super_t));
}
- if (IS_ERR(bitmap->sb_page)) {
- err = PTR_ERR(bitmap->sb_page);
- bitmap->sb_page = NULL;
+ if (err)
return err;
- }
- sb = kmap_atomic(bitmap->sb_page);
+ sb = kmap_atomic(sb_page);
chunksize = le32_to_cpu(sb->chunksize);
daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ;
write_behind = le32_to_cpu(sb->write_behind);
+ sectors_reserved = le32_to_cpu(sb->sectors_reserved);
/* verify that the bitmap-specific fields are valid */
if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
@@ -618,60 +619,32 @@ static int bitmap_read_sb(struct bitmap *bitmap)
"-- forcing full recovery\n",
bmname(bitmap), events,
(unsigned long long) bitmap->mddev->events);
- sb->state |= cpu_to_le32(BITMAP_STALE);
+ set_bit(BITMAP_STALE, &bitmap->flags);
}
}
/* assign fields using values from superblock */
- bitmap->mddev->bitmap_info.chunksize = chunksize;
- bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep;
- bitmap->mddev->bitmap_info.max_write_behind = write_behind;
bitmap->flags |= le32_to_cpu(sb->state);
if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN)
- bitmap->flags |= BITMAP_HOSTENDIAN;
+ set_bit(BITMAP_HOSTENDIAN, &bitmap->flags);
bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
- if (bitmap->flags & BITMAP_STALE)
- bitmap->events_cleared = bitmap->mddev->events;
err = 0;
out:
kunmap_atomic(sb);
+out_no_sb:
+ if (test_bit(BITMAP_STALE, &bitmap->flags))
+ bitmap->events_cleared = bitmap->mddev->events;
+ bitmap->mddev->bitmap_info.chunksize = chunksize;
+ bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep;
+ bitmap->mddev->bitmap_info.max_write_behind = write_behind;
+ if (bitmap->mddev->bitmap_info.space == 0 ||
+ bitmap->mddev->bitmap_info.space > sectors_reserved)
+ bitmap->mddev->bitmap_info.space = sectors_reserved;
if (err)
bitmap_print_sb(bitmap);
return err;
}
-enum bitmap_mask_op {
- MASK_SET,
- MASK_UNSET
-};
-
-/* record the state of the bitmap in the superblock. Return the old value */
-static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
- enum bitmap_mask_op op)
-{
- bitmap_super_t *sb;
- int old;
-
- if (!bitmap->sb_page) /* can't set the state */
- return 0;
- sb = kmap_atomic(bitmap->sb_page);
- old = le32_to_cpu(sb->state) & bits;
- switch (op) {
- case MASK_SET:
- sb->state |= cpu_to_le32(bits);
- bitmap->flags |= bits;
- break;
- case MASK_UNSET:
- sb->state &= cpu_to_le32(~bits);
- bitmap->flags &= ~bits;
- break;
- default:
- BUG();
- }
- kunmap_atomic(sb);
- return old;
-}
-
/*
* general bitmap file operations
*/
@@ -683,17 +656,19 @@ static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
* file a page at a time. There's a superblock at the start of the file.
*/
/* calculate the index of the page that contains this bit */
-static inline unsigned long file_page_index(struct bitmap *bitmap, unsigned long chunk)
+static inline unsigned long file_page_index(struct bitmap_storage *store,
+ unsigned long chunk)
{
- if (!bitmap->mddev->bitmap_info.external)
+ if (store->sb_page)
chunk += sizeof(bitmap_super_t) << 3;
return chunk >> PAGE_BIT_SHIFT;
}
/* calculate the (bit) offset of this bit within a page */
-static inline unsigned long file_page_offset(struct bitmap *bitmap, unsigned long chunk)
+static inline unsigned long file_page_offset(struct bitmap_storage *store,
+ unsigned long chunk)
{
- if (!bitmap->mddev->bitmap_info.external)
+ if (store->sb_page)
chunk += sizeof(bitmap_super_t) << 3;
return chunk & (PAGE_BITS - 1);
}
@@ -705,57 +680,86 @@ static inline unsigned long file_page_offset(struct bitmap *bitmap, unsigned lon
* 1 page (e.g., x86) or less than 1 page -- so the bitmap might start on page
* 0 or page 1
*/
-static inline struct page *filemap_get_page(struct bitmap *bitmap,
+static inline struct page *filemap_get_page(struct bitmap_storage *store,
unsigned long chunk)
{
- if (file_page_index(bitmap, chunk) >= bitmap->file_pages)
+ if (file_page_index(store, chunk) >= store->file_pages)
return NULL;
- return bitmap->filemap[file_page_index(bitmap, chunk)
- - file_page_index(bitmap, 0)];
+ return store->filemap[file_page_index(store, chunk)
+ - file_page_index(store, 0)];
}
-static void bitmap_file_unmap(struct bitmap *bitmap)
+static int bitmap_storage_alloc(struct bitmap_storage *store,
+ unsigned long chunks, int with_super)
+{
+ int pnum;
+ unsigned long num_pages;
+ unsigned long bytes;
+
+ bytes = DIV_ROUND_UP(chunks, 8);
+ if (with_super)
+ bytes += sizeof(bitmap_super_t);
+
+ num_pages = DIV_ROUND_UP(bytes, PAGE_SIZE);
+
+ store->filemap = kmalloc(sizeof(struct page *)
+ * num_pages, GFP_KERNEL);
+ if (!store->filemap)
+ return -ENOMEM;
+
+ if (with_super && !store->sb_page) {
+ store->sb_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
+ if (store->sb_page == NULL)
+ return -ENOMEM;
+ store->sb_page->index = 0;
+ }
+ pnum = 0;
+ if (store->sb_page) {
+ store->filemap[0] = store->sb_page;
+ pnum = 1;
+ }
+ for ( ; pnum < num_pages; pnum++) {
+ store->filemap[pnum] = alloc_page(GFP_KERNEL|__GFP_ZERO);
+ if (!store->filemap[pnum]) {
+ store->file_pages = pnum;
+ return -ENOMEM;
+ }
+ store->filemap[pnum]->index = pnum;
+ }
+ store->file_pages = pnum;
+
+ /* We need 4 bits per page, rounded up to a multiple
+ * of sizeof(unsigned long) */
+ store->filemap_attr = kzalloc(
+ roundup(DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)),
+ GFP_KERNEL);
+ if (!store->filemap_attr)
+ return -ENOMEM;
+
+ store->bytes = bytes;
+
+ return 0;
+}
+
+static void bitmap_file_unmap(struct bitmap_storage *store)
{
struct page **map, *sb_page;
- unsigned long *attr;
int pages;
- unsigned long flags;
+ struct file *file;
- spin_lock_irqsave(&bitmap->lock, flags);
- map = bitmap->filemap;
- bitmap->filemap = NULL;
- attr = bitmap->filemap_attr;
- bitmap->filemap_attr = NULL;
- pages = bitmap->file_pages;
- bitmap->file_pages = 0;
- sb_page = bitmap->sb_page;
- bitmap->sb_page = NULL;
- spin_unlock_irqrestore(&bitmap->lock, flags);
+ file = store->file;
+ map = store->filemap;
+ pages = store->file_pages;
+ sb_page = store->sb_page;
while (pages--)
if (map[pages] != sb_page) /* 0 is sb_page, release it below */
free_buffers(map[pages]);
kfree(map);
- kfree(attr);
+ kfree(store->filemap_attr);
if (sb_page)
free_buffers(sb_page);
-}
-
-static void bitmap_file_put(struct bitmap *bitmap)
-{
- struct file *file;
- unsigned long flags;
-
- spin_lock_irqsave(&bitmap->lock, flags);
- file = bitmap->file;
- bitmap->file = NULL;
- spin_unlock_irqrestore(&bitmap->lock, flags);
-
- if (file)
- wait_event(bitmap->write_wait,
- atomic_read(&bitmap->pending_writes)==0);
- bitmap_file_unmap(bitmap);
if (file) {
struct inode *inode = file->f_path.dentry->d_inode;
@@ -773,14 +777,14 @@ static void bitmap_file_kick(struct bitmap *bitmap)
{
char *path, *ptr = NULL;
- if (bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET) == 0) {
+ if (!test_and_set_bit(BITMAP_STALE, &bitmap->flags)) {
bitmap_update_sb(bitmap);
- if (bitmap->file) {
+ if (bitmap->storage.file) {
path = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (path)
- ptr = d_path(&bitmap->file->f_path, path,
- PAGE_SIZE);
+ ptr = d_path(&bitmap->storage.file->f_path,
+ path, PAGE_SIZE);
printk(KERN_ALERT
"%s: kicking failed bitmap file %s from array!\n",
@@ -792,10 +796,6 @@ static void bitmap_file_kick(struct bitmap *bitmap)
"%s: disabling internal bitmap due to errors\n",
bmname(bitmap));
}
-
- bitmap_file_put(bitmap);
-
- return;
}
enum bitmap_page_attr {
@@ -805,24 +805,30 @@ enum bitmap_page_attr {
BITMAP_PAGE_NEEDWRITE = 2, /* there are cleared bits that need to be synced */
};
-static inline void set_page_attr(struct bitmap *bitmap, struct page *page,
- enum bitmap_page_attr attr)
+static inline void set_page_attr(struct bitmap *bitmap, int pnum,
+ enum bitmap_page_attr attr)
{
- __set_bit((page->index<<2) + attr, bitmap->filemap_attr);
+ set_bit((pnum<<2) + attr, bitmap->storage.filemap_attr);
}
-static inline void clear_page_attr(struct bitmap *bitmap, struct page *page,
- enum bitmap_page_attr attr)
+static inline void clear_page_attr(struct bitmap *bitmap, int pnum,
+ enum bitmap_page_attr attr)
{
- __clear_bit((page->index<<2) + attr, bitmap->filemap_attr);
+ clear_bit((pnum<<2) + attr, bitmap->storage.filemap_attr);
}
-static inline unsigned long test_page_attr(struct bitmap *bitmap, struct page *page,
- enum bitmap_page_attr attr)
+static inline int test_page_attr(struct bitmap *bitmap, int pnum,
+ enum bitmap_page_attr attr)
{
- return test_bit((page->index<<2) + attr, bitmap->filemap_attr);
+ return test_bit((pnum<<2) + attr, bitmap->storage.filemap_attr);
}
+static inline int test_and_clear_page_attr(struct bitmap *bitmap, int pnum,
+ enum bitmap_page_attr attr)
+{
+ return test_and_clear_bit((pnum<<2) + attr,
+ bitmap->storage.filemap_attr);
+}
/*
* bitmap_file_set_bit -- called before performing a write to the md device
* to set (and eventually sync) a particular bit in the bitmap file
@@ -835,26 +841,46 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
unsigned long bit;
struct page *page;
void *kaddr;
- unsigned long chunk = block >> bitmap->chunkshift;
+ unsigned long chunk = block >> bitmap->counts.chunkshift;
- if (!bitmap->filemap)
- return;
-
- page = filemap_get_page(bitmap, chunk);
+ page = filemap_get_page(&bitmap->storage, chunk);
if (!page)
return;
- bit = file_page_offset(bitmap, chunk);
+ bit = file_page_offset(&bitmap->storage, chunk);
/* set the bit */
kaddr = kmap_atomic(page);
- if (bitmap->flags & BITMAP_HOSTENDIAN)
+ if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags))
set_bit(bit, kaddr);
else
- __set_bit_le(bit, kaddr);
+ test_and_set_bit_le(bit, kaddr);
kunmap_atomic(kaddr);
pr_debug("set file bit %lu page %lu\n", bit, page->index);
/* record page number so it gets flushed to disk when unplug occurs */
- set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
+ set_page_attr(bitmap, page->index, BITMAP_PAGE_DIRTY);
+}
+
+static void bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block)
+{
+ unsigned long bit;
+ struct page *page;
+ void *paddr;
+ unsigned long chunk = block >> bitmap->counts.chunkshift;
+
+ page = filemap_get_page(&bitmap->storage, chunk);
+ if (!page)
+ return;
+ bit = file_page_offset(&bitmap->storage, chunk);
+ paddr = kmap_atomic(page);
+ if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags))
+ clear_bit(bit, paddr);
+ else
+ test_and_clear_bit_le(bit, paddr);
+ kunmap_atomic(paddr);
+ if (!test_page_attr(bitmap, page->index, BITMAP_PAGE_NEEDWRITE)) {
+ set_page_attr(bitmap, page->index, BITMAP_PAGE_PENDING);
+ bitmap->allclean = 0;
+ }
}
/* this gets called when the md device is ready to unplug its underlying
@@ -862,42 +888,37 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
* sync the dirty pages of the bitmap file to disk */
void bitmap_unplug(struct bitmap *bitmap)
{
- unsigned long i, flags;
+ unsigned long i;
int dirty, need_write;
- struct page *page;
int wait = 0;
- if (!bitmap)
+ if (!bitmap || !bitmap->storage.filemap ||
+ test_bit(BITMAP_STALE, &bitmap->flags))
return;
/* look at each page to see if there are any set bits that need to be
* flushed out to disk */
- for (i = 0; i < bitmap->file_pages; i++) {
- spin_lock_irqsave(&bitmap->lock, flags);
- if (!bitmap->filemap) {
- spin_unlock_irqrestore(&bitmap->lock, flags);
+ for (i = 0; i < bitmap->storage.file_pages; i++) {
+ if (!bitmap->storage.filemap)
return;
+ dirty = test_and_clear_page_attr(bitmap, i, BITMAP_PAGE_DIRTY);
+ need_write = test_and_clear_page_attr(bitmap, i,
+ BITMAP_PAGE_NEEDWRITE);
+ if (dirty || need_write) {
+ clear_page_attr(bitmap, i, BITMAP_PAGE_PENDING);
+ write_page(bitmap, bitmap->storage.filemap[i], 0);
}
- page = bitmap->filemap[i];
- dirty = test_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
- need_write = test_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
- clear_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
- clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
if (dirty)
wait = 1;
- spin_unlock_irqrestore(&bitmap->lock, flags);
-
- if (dirty || need_write)
- write_page(bitmap, page, 0);
}
if (wait) { /* if any writes were performed, we need to wait on them */
- if (bitmap->file)
+ if (bitmap->storage.file)
wait_event(bitmap->write_wait,
atomic_read(&bitmap->pending_writes)==0);
else
md_super_wait(bitmap->mddev);
}
- if (bitmap->flags & BITMAP_WRITE_ERROR)
+ if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags))
bitmap_file_kick(bitmap);
}
EXPORT_SYMBOL(bitmap_unplug);
@@ -917,98 +938,77 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
{
unsigned long i, chunks, index, oldindex, bit;
- struct page *page = NULL, *oldpage = NULL;
- unsigned long num_pages, bit_cnt = 0;
+ struct page *page = NULL;
+ unsigned long bit_cnt = 0;
struct file *file;
- unsigned long bytes, offset;
+ unsigned long offset;
int outofdate;
int ret = -ENOSPC;
void *paddr;
+ struct bitmap_storage *store = &bitmap->storage;
- chunks = bitmap->chunks;
- file = bitmap->file;
+ chunks = bitmap->counts.chunks;
+ file = store->file;
- BUG_ON(!file && !bitmap->mddev->bitmap_info.offset);
+ if (!file && !bitmap->mddev->bitmap_info.offset) {
+ /* No permanent bitmap - fill with '1s'. */
+ store->filemap = NULL;
+ store->file_pages = 0;
+ for (i = 0; i < chunks ; i++) {
+ /* if the disk bit is set, set the memory bit */
+ int needed = ((sector_t)(i+1) << (bitmap->counts.chunkshift)
+ >= start);
+ bitmap_set_memory_bits(bitmap,
+ (sector_t)i << bitmap->counts.chunkshift,
+ needed);
+ }
+ return 0;
+ }
- outofdate = bitmap->flags & BITMAP_STALE;
+ outofdate = test_bit(BITMAP_STALE, &bitmap->flags);
if (outofdate)
printk(KERN_INFO "%s: bitmap file is out of date, doing full "
"recovery\n", bmname(bitmap));
- bytes = DIV_ROUND_UP(bitmap->chunks, 8);
- if (!bitmap->mddev->bitmap_info.external)
- bytes += sizeof(bitmap_super_t);
-
- num_pages = DIV_ROUND_UP(bytes, PAGE_SIZE);
-
- if (file && i_size_read(file->f_mapping->host) < bytes) {
+ if (file && i_size_read(file->f_mapping->host) < store->bytes) {
printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
- bmname(bitmap),
- (unsigned long) i_size_read(file->f_mapping->host),
- bytes);
+ bmname(bitmap),
+ (unsigned long) i_size_read(file->f_mapping->host),
+ store->bytes);
goto err;
}
- ret = -ENOMEM;
-
- bitmap->filemap = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL);
- if (!bitmap->filemap)
- goto err;
-
- /* We need 4 bits per page, rounded up to a multiple of sizeof(unsigned long) */
- bitmap->filemap_attr = kzalloc(
- roundup(DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)),
- GFP_KERNEL);
- if (!bitmap->filemap_attr)
- goto err;
-
oldindex = ~0L;
+ offset = 0;
+ if (!bitmap->mddev->bitmap_info.external)
+ offset = sizeof(bitmap_super_t);
for (i = 0; i < chunks; i++) {
int b;
- index = file_page_index(bitmap, i);
- bit = file_page_offset(bitmap, i);
+ index = file_page_index(&bitmap->storage, i);
+ bit = file_page_offset(&bitmap->storage, i);
if (index != oldindex) { /* this is a new page, read it in */
int count;
/* unmap the old page, we're done with it */
- if (index == num_pages-1)
- count = bytes - index * PAGE_SIZE;
+ if (index == store->file_pages-1)
+ count = store->bytes - index * PAGE_SIZE;
else
count = PAGE_SIZE;
- if (index == 0 && bitmap->sb_page) {
- /*
- * if we're here then the superblock page
- * contains some bits (PAGE_SIZE != sizeof sb)
- * we've already read it in, so just use it
- */
- page = bitmap->sb_page;
- offset = sizeof(bitmap_super_t);
- if (!file)
- page = read_sb_page(
- bitmap->mddev,
- bitmap->mddev->bitmap_info.offset,
- page,
- index, count);
- } else if (file) {
- page = read_page(file, index, bitmap, count);
- offset = 0;
- } else {
- page = read_sb_page(bitmap->mddev,
- bitmap->mddev->bitmap_info.offset,
- NULL,
- index, count);
- offset = 0;
- }
- if (IS_ERR(page)) { /* read error */
- ret = PTR_ERR(page);
+ page = store->filemap[index];
+ if (file)
+ ret = read_page(file, index, bitmap,
+ count, page);
+ else
+ ret = read_sb_page(
+ bitmap->mddev,
+ bitmap->mddev->bitmap_info.offset,
+ page,
+ index, count);
+
+ if (ret)
goto err;
- }
oldindex = index;
- oldpage = page;
-
- bitmap->filemap[bitmap->file_pages++] = page;
- bitmap->last_page_size = count;
if (outofdate) {
/*
@@ -1022,39 +1022,33 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
write_page(bitmap, page, 1);
ret = -EIO;
- if (bitmap->flags & BITMAP_WRITE_ERROR)
+ if (test_bit(BITMAP_WRITE_ERROR,
+ &bitmap->flags))
goto err;
}
}
paddr = kmap_atomic(page);
- if (bitmap->flags & BITMAP_HOSTENDIAN)
+ if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags))
b = test_bit(bit, paddr);
else
b = test_bit_le(bit, paddr);
kunmap_atomic(paddr);
if (b) {
/* if the disk bit is set, set the memory bit */
- int needed = ((sector_t)(i+1) << bitmap->chunkshift
+ int needed = ((sector_t)(i+1) << bitmap->counts.chunkshift
>= start);
bitmap_set_memory_bits(bitmap,
- (sector_t)i << bitmap->chunkshift,
+ (sector_t)i << bitmap->counts.chunkshift,
needed);
bit_cnt++;
}
- }
-
- /* everything went OK */
- ret = 0;
- bitmap_mask_state(bitmap, BITMAP_STALE, MASK_UNSET);
-
- if (bit_cnt) { /* Kick recovery if any bits were set */
- set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery);
- md_wakeup_thread(bitmap->mddev->thread);
+ offset = 0;
}
printk(KERN_INFO "%s: bitmap initialized from disk: "
- "read %lu/%lu pages, set %lu of %lu bits\n",
- bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt, chunks);
+ "read %lu pages, set %lu of %lu bits\n",
+ bmname(bitmap), store->file_pages,
+ bit_cnt, chunks);
return 0;
@@ -1071,22 +1065,38 @@ void bitmap_write_all(struct bitmap *bitmap)
*/
int i;
- spin_lock_irq(&bitmap->lock);
- for (i = 0; i < bitmap->file_pages; i++)
- set_page_attr(bitmap, bitmap->filemap[i],
+ if (!bitmap || !bitmap->storage.filemap)
+ return;
+ if (bitmap->storage.file)
+ /* Only one copy, so nothing needed */
+ return;
+
+ for (i = 0; i < bitmap->storage.file_pages; i++)
+ set_page_attr(bitmap, i,
BITMAP_PAGE_NEEDWRITE);
bitmap->allclean = 0;
- spin_unlock_irq(&bitmap->lock);
}
-static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
+static void bitmap_count_page(struct bitmap_counts *bitmap,
+ sector_t offset, int inc)
{
sector_t chunk = offset >> bitmap->chunkshift;
unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
bitmap->bp[page].count += inc;
bitmap_checkfree(bitmap, page);
}
-static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
+
+static void bitmap_set_pending(struct bitmap_counts *bitmap, sector_t offset)
+{
+ sector_t chunk = offset >> bitmap->chunkshift;
+ unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
+ struct bitmap_page *bp = &bitmap->bp[page];
+
+ if (!bp->pending)
+ bp->pending = 1;
+}
+
+static bitmap_counter_t *bitmap_get_counter(struct bitmap_counts *bitmap,
sector_t offset, sector_t *blocks,
int create);
@@ -1099,10 +1109,9 @@ void bitmap_daemon_work(struct mddev *mddev)
{
struct bitmap *bitmap;
unsigned long j;
- unsigned long flags;
- struct page *page = NULL, *lastpage = NULL;
+ unsigned long nextpage;
sector_t blocks;
- void *paddr;
+ struct bitmap_counts *counts;
/* Use a mutex to guard daemon_work against
* bitmap_destroy.
@@ -1124,112 +1133,90 @@ void bitmap_daemon_work(struct mddev *mddev)
}
bitmap->allclean = 1;
- spin_lock_irqsave(&bitmap->lock, flags);
- for (j = 0; j < bitmap->chunks; j++) {
+ /* Any file-page which is PENDING now needs to be written.
+ * So set NEEDWRITE now, then after we make any last-minute changes
+ * we will write it.
+ */
+ for (j = 0; j < bitmap->storage.file_pages; j++)
+ if (test_and_clear_page_attr(bitmap, j,
+ BITMAP_PAGE_PENDING))
+ set_page_attr(bitmap, j,
+ BITMAP_PAGE_NEEDWRITE);
+
+ if (bitmap->need_sync &&
+ mddev->bitmap_info.external == 0) {
+ /* Arrange for superblock update as well as
+ * other changes */
+ bitmap_super_t *sb;
+ bitmap->need_sync = 0;
+ if (bitmap->storage.filemap) {
+ sb = kmap_atomic(bitmap->storage.sb_page);
+ sb->events_cleared =
+ cpu_to_le64(bitmap->events_cleared);
+ kunmap_atomic(sb);
+ set_page_attr(bitmap, 0,
+ BITMAP_PAGE_NEEDWRITE);
+ }
+ }
+ /* Now look at the bitmap counters and if any are '2' or '1',
+ * decrement and handle accordingly.
+ */
+ counts = &bitmap->counts;
+ spin_lock_irq(&counts->lock);
+ nextpage = 0;
+ for (j = 0; j < counts->chunks; j++) {
bitmap_counter_t *bmc;
- if (!bitmap->filemap)
- /* error or shutdown */
- break;
+ sector_t block = (sector_t)j << counts->chunkshift;
- page = filemap_get_page(bitmap, j);
-
- if (page != lastpage) {
- /* skip this page unless it's marked as needing cleaning */
- if (!test_page_attr(bitmap, page, BITMAP_PAGE_PENDING)) {
- int need_write = test_page_attr(bitmap, page,
- BITMAP_PAGE_NEEDWRITE);
- if (need_write)
- clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
-
- spin_unlock_irqrestore(&bitmap->lock, flags);
- if (need_write)
- write_page(bitmap, page, 0);
- spin_lock_irqsave(&bitmap->lock, flags);
- j |= (PAGE_BITS - 1);
+ if (j == nextpage) {
+ nextpage += PAGE_COUNTER_RATIO;
+ if (!counts->bp[j >> PAGE_COUNTER_SHIFT].pending) {
+ j |= PAGE_COUNTER_MASK;
continue;
}
-
- /* grab the new page, sync and release the old */
- if (lastpage != NULL) {
- if (test_page_attr(bitmap, lastpage,
- BITMAP_PAGE_NEEDWRITE)) {
- clear_page_attr(bitmap, lastpage,
- BITMAP_PAGE_NEEDWRITE);
- spin_unlock_irqrestore(&bitmap->lock, flags);
- write_page(bitmap, lastpage, 0);
- } else {
- set_page_attr(bitmap, lastpage,
- BITMAP_PAGE_NEEDWRITE);
- bitmap->allclean = 0;
- spin_unlock_irqrestore(&bitmap->lock, flags);
- }
- } else
- spin_unlock_irqrestore(&bitmap->lock, flags);
- lastpage = page;
-
- /* We are possibly going to clear some bits, so make
- * sure that events_cleared is up-to-date.
- */
- if (bitmap->need_sync &&
- mddev->bitmap_info.external == 0) {
- bitmap_super_t *sb;
- bitmap->need_sync = 0;
- sb = kmap_atomic(bitmap->sb_page);
- sb->events_cleared =
- cpu_to_le64(bitmap->events_cleared);
- kunmap_atomic(sb);
- write_page(bitmap, bitmap->sb_page, 1);
- }
- spin_lock_irqsave(&bitmap->lock, flags);
- if (!bitmap->need_sync)
- clear_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
- else
- bitmap->allclean = 0;
+ counts->bp[j >> PAGE_COUNTER_SHIFT].pending = 0;
}
- bmc = bitmap_get_counter(bitmap,
- (sector_t)j << bitmap->chunkshift,
+ bmc = bitmap_get_counter(counts,
+ block,
&blocks, 0);
- if (!bmc)
+
+ if (!bmc) {
j |= PAGE_COUNTER_MASK;
- else if (*bmc) {
- if (*bmc == 1 && !bitmap->need_sync) {
- /* we can clear the bit */
- *bmc = 0;
- bitmap_count_page(bitmap,
- (sector_t)j << bitmap->chunkshift,
- -1);
-
- /* clear the bit */
- paddr = kmap_atomic(page);
- if (bitmap->flags & BITMAP_HOSTENDIAN)
- clear_bit(file_page_offset(bitmap, j),
- paddr);
- else
- __clear_bit_le(
- file_page_offset(bitmap,
- j),
- paddr);
- kunmap_atomic(paddr);
- } else if (*bmc <= 2) {
- *bmc = 1; /* maybe clear the bit next time */
- set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
- bitmap->allclean = 0;
- }
+ continue;
}
- }
- spin_unlock_irqrestore(&bitmap->lock, flags);
-
- /* now sync the final page */
- if (lastpage != NULL) {
- spin_lock_irqsave(&bitmap->lock, flags);
- if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
- clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
- spin_unlock_irqrestore(&bitmap->lock, flags);
- write_page(bitmap, lastpage, 0);
- } else {
- set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ if (*bmc == 1 && !bitmap->need_sync) {
+ /* We can clear the bit */
+ *bmc = 0;
+ bitmap_count_page(counts, block, -1);
+ bitmap_file_clear_bit(bitmap, block);
+ } else if (*bmc && *bmc <= 2) {
+ *bmc = 1;
+ bitmap_set_pending(counts, block);
bitmap->allclean = 0;
- spin_unlock_irqrestore(&bitmap->lock, flags);
+ }
+ }
+ spin_unlock_irq(&counts->lock);
+
+ /* Now start writeout on any page in NEEDWRITE that isn't DIRTY.
+ * DIRTY pages need to be written by bitmap_unplug so it can wait
+ * for them.
+ * If we find any DIRTY page we stop there and let bitmap_unplug
+ * handle all the rest. This is important in the case where
+ * the first blocking holds the superblock and it has been updated.
+ * We mustn't write any other blocks before the superblock.
+ */
+ for (j = 0;
+ j < bitmap->storage.file_pages
+ && !test_bit(BITMAP_STALE, &bitmap->flags);
+ j++) {
+
+ if (test_page_attr(bitmap, j,
+ BITMAP_PAGE_DIRTY))
+ /* bitmap_unplug will handle the rest */
+ break;
+ if (test_and_clear_page_attr(bitmap, j,
+ BITMAP_PAGE_NEEDWRITE)) {
+ write_page(bitmap, bitmap->storage.filemap[j], 0);
}
}
@@ -1240,7 +1227,7 @@ void bitmap_daemon_work(struct mddev *mddev)
mutex_unlock(&mddev->bitmap_info.mutex);
}
-static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
+static bitmap_counter_t *bitmap_get_counter(struct bitmap_counts *bitmap,
sector_t offset, sector_t *blocks,
int create)
__releases(bitmap->lock)
@@ -1302,10 +1289,10 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
sector_t blocks;
bitmap_counter_t *bmc;
- spin_lock_irq(&bitmap->lock);
- bmc = bitmap_get_counter(bitmap, offset, &blocks, 1);
+ spin_lock_irq(&bitmap->counts.lock);
+ bmc = bitmap_get_counter(&bitmap->counts, offset, &blocks, 1);
if (!bmc) {
- spin_unlock_irq(&bitmap->lock);
+ spin_unlock_irq(&bitmap->counts.lock);
return 0;
}
@@ -1317,7 +1304,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
*/
prepare_to_wait(&bitmap->overflow_wait, &__wait,
TASK_UNINTERRUPTIBLE);
- spin_unlock_irq(&bitmap->lock);
+ spin_unlock_irq(&bitmap->counts.lock);
io_schedule();
finish_wait(&bitmap->overflow_wait, &__wait);
continue;
@@ -1326,7 +1313,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
switch (*bmc) {
case 0:
bitmap_file_set_bit(bitmap, offset);
- bitmap_count_page(bitmap, offset, 1);
+ bitmap_count_page(&bitmap->counts, offset, 1);
/* fall through */
case 1:
*bmc = 2;
@@ -1334,7 +1321,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
(*bmc)++;
- spin_unlock_irq(&bitmap->lock);
+ spin_unlock_irq(&bitmap->counts.lock);
offset += blocks;
if (sectors > blocks)
@@ -1364,10 +1351,10 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
unsigned long flags;
bitmap_counter_t *bmc;
- spin_lock_irqsave(&bitmap->lock, flags);
- bmc = bitmap_get_counter(bitmap, offset, &blocks, 0);
+ spin_lock_irqsave(&bitmap->counts.lock, flags);
+ bmc = bitmap_get_counter(&bitmap->counts, offset, &blocks, 0);
if (!bmc) {
- spin_unlock_irqrestore(&bitmap->lock, flags);
+ spin_unlock_irqrestore(&bitmap->counts.lock, flags);
return;
}
@@ -1386,14 +1373,10 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
(*bmc)--;
if (*bmc <= 2) {
- set_page_attr(bitmap,
- filemap_get_page(
- bitmap,
- offset >> bitmap->chunkshift),
- BITMAP_PAGE_PENDING);
+ bitmap_set_pending(&bitmap->counts, offset);
bitmap->allclean = 0;
}
- spin_unlock_irqrestore(&bitmap->lock, flags);
+ spin_unlock_irqrestore(&bitmap->counts.lock, flags);
offset += blocks;
if (sectors > blocks)
sectors -= blocks;
@@ -1412,8 +1395,8 @@ static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t
*blocks = 1024;
return 1; /* always resync if no bitmap */
}
- spin_lock_irq(&bitmap->lock);
- bmc = bitmap_get_counter(bitmap, offset, blocks, 0);
+ spin_lock_irq(&bitmap->counts.lock);
+ bmc = bitmap_get_counter(&bitmap->counts, offset, blocks, 0);
rv = 0;
if (bmc) {
/* locked */
@@ -1427,7 +1410,7 @@ static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t
}
}
}
- spin_unlock_irq(&bitmap->lock);
+ spin_unlock_irq(&bitmap->counts.lock);
return rv;
}
@@ -1464,8 +1447,8 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i
*blocks = 1024;
return;
}
- spin_lock_irqsave(&bitmap->lock, flags);
- bmc = bitmap_get_counter(bitmap, offset, blocks, 0);
+ spin_lock_irqsave(&bitmap->counts.lock, flags);
+ bmc = bitmap_get_counter(&bitmap->counts, offset, blocks, 0);
if (bmc == NULL)
goto unlock;
/* locked */
@@ -1476,15 +1459,13 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i
*bmc |= NEEDED_MASK;
else {
if (*bmc <= 2) {
- set_page_attr(bitmap,
- filemap_get_page(bitmap, offset >> bitmap->chunkshift),
- BITMAP_PAGE_PENDING);
+ bitmap_set_pending(&bitmap->counts, offset);
bitmap->allclean = 0;
}
}
}
unlock:
- spin_unlock_irqrestore(&bitmap->lock, flags);
+ spin_unlock_irqrestore(&bitmap->counts.lock, flags);
}
EXPORT_SYMBOL(bitmap_end_sync);
@@ -1524,7 +1505,7 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector)
bitmap->mddev->curr_resync_completed = sector;
set_bit(MD_CHANGE_CLEAN, &bitmap->mddev->flags);
- sector &= ~((1ULL << bitmap->chunkshift) - 1);
+ sector &= ~((1ULL << bitmap->counts.chunkshift) - 1);
s = 0;
while (s < sector && s < bitmap->mddev->resync_max_sectors) {
bitmap_end_sync(bitmap, s, &blocks, 0);
@@ -1538,27 +1519,25 @@ EXPORT_SYMBOL(bitmap_cond_end_sync);
static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed)
{
/* For each chunk covered by any of these sectors, set the
- * counter to 1 and set resync_needed. They should all
+ * counter to 2 and possibly set resync_needed. They should all
* be 0 at this point
*/
sector_t secs;
bitmap_counter_t *bmc;
- spin_lock_irq(&bitmap->lock);
- bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
+ spin_lock_irq(&bitmap->counts.lock);
+ bmc = bitmap_get_counter(&bitmap->counts, offset, &secs, 1);
if (!bmc) {
- spin_unlock_irq(&bitmap->lock);
+ spin_unlock_irq(&bitmap->counts.lock);
return;
}
if (!*bmc) {
- struct page *page;
*bmc = 2 | (needed ? NEEDED_MASK : 0);
- bitmap_count_page(bitmap, offset, 1);
- page = filemap_get_page(bitmap, offset >> bitmap->chunkshift);
- set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
+ bitmap_count_page(&bitmap->counts, offset, 1);
+ bitmap_set_pending(&bitmap->counts, offset);
bitmap->allclean = 0;
}
- spin_unlock_irq(&bitmap->lock);
+ spin_unlock_irq(&bitmap->counts.lock);
}
/* dirty the memory and file bits for bitmap chunks "s" to "e" */
@@ -1567,11 +1546,9 @@ void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e)
unsigned long chunk;
for (chunk = s; chunk <= e; chunk++) {
- sector_t sec = (sector_t)chunk << bitmap->chunkshift;
+ sector_t sec = (sector_t)chunk << bitmap->counts.chunkshift;
bitmap_set_memory_bits(bitmap, sec, 1);
- spin_lock_irq(&bitmap->lock);
bitmap_file_set_bit(bitmap, sec);
- spin_unlock_irq(&bitmap->lock);
if (sec < bitmap->mddev->recovery_cp)
/* We are asserting that the array is dirty,
* so move the recovery_cp address back so
@@ -1616,11 +1593,15 @@ static void bitmap_free(struct bitmap *bitmap)
if (!bitmap) /* there was no bitmap */
return;
- /* release the bitmap file and kill the daemon */
- bitmap_file_put(bitmap);
+ /* Shouldn't be needed - but just in case.... */
+ wait_event(bitmap->write_wait,
+ atomic_read(&bitmap->pending_writes) == 0);
+
+ /* release the bitmap file */
+ bitmap_file_unmap(&bitmap->storage);
- bp = bitmap->bp;
- pages = bitmap->pages;
+ bp = bitmap->counts.bp;
+ pages = bitmap->counts.pages;
/* free all allocated memory */
@@ -1659,25 +1640,19 @@ int bitmap_create(struct mddev *mddev)
{
struct bitmap *bitmap;
sector_t blocks = mddev->resync_max_sectors;
- unsigned long chunks;
- unsigned long pages;
struct file *file = mddev->bitmap_info.file;
int err;
struct sysfs_dirent *bm = NULL;
BUILD_BUG_ON(sizeof(bitmap_super_t) != 256);
- if (!file
- && !mddev->bitmap_info.offset) /* bitmap disabled, nothing to do */
- return 0;
-
BUG_ON(file && mddev->bitmap_info.offset);
bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL);
if (!bitmap)
return -ENOMEM;
- spin_lock_init(&bitmap->lock);
+ spin_lock_init(&bitmap->counts.lock);
atomic_set(&bitmap->pending_writes, 0);
init_waitqueue_head(&bitmap->write_wait);
init_waitqueue_head(&bitmap->overflow_wait);
@@ -1693,7 +1668,7 @@ int bitmap_create(struct mddev *mddev)
} else
bitmap->sysfs_can_clear = NULL;
- bitmap->file = file;
+ bitmap->storage.file = file;
if (file) {
get_file(file);
/* As future accesses to this file will use bmap,
@@ -1724,32 +1699,15 @@ int bitmap_create(struct mddev *mddev)
goto error;
bitmap->daemon_lastrun = jiffies;
- bitmap->chunkshift = (ffz(~mddev->bitmap_info.chunksize)
- - BITMAP_BLOCK_SHIFT);
-
- chunks = (blocks + (1 << bitmap->chunkshift) - 1) >>
- bitmap->chunkshift;
- pages = (chunks + PAGE_COUNTER_RATIO - 1) / PAGE_COUNTER_RATIO;
-
- BUG_ON(!pages);
-
- bitmap->chunks = chunks;
- bitmap->pages = pages;
- bitmap->missing_pages = pages;
-
- bitmap->bp = kzalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
-
- err = -ENOMEM;
- if (!bitmap->bp)
+ err = bitmap_resize(bitmap, blocks, mddev->bitmap_info.chunksize, 1);
+ if (err)
goto error;
printk(KERN_INFO "created bitmap (%lu pages) for device %s\n",
- pages, bmname(bitmap));
+ bitmap->counts.pages, bmname(bitmap));
mddev->bitmap = bitmap;
-
-
- return (bitmap->flags & BITMAP_WRITE_ERROR) ? -EIO : 0;
+ return test_bit(BITMAP_WRITE_ERROR, &bitmap->flags) ? -EIO : 0;
error:
bitmap_free(bitmap);
@@ -1790,13 +1748,17 @@ int bitmap_load(struct mddev *mddev)
if (err)
goto out;
+ clear_bit(BITMAP_STALE, &bitmap->flags);
+
+ /* Kick recovery in case any bits were set */
+ set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery);
mddev->thread->timeout = mddev->bitmap_info.daemon_sleep;
md_wakeup_thread(mddev->thread);
bitmap_update_sb(bitmap);
- if (bitmap->flags & BITMAP_WRITE_ERROR)
+ if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags))
err = -EIO;
out:
return err;
@@ -1806,30 +1768,194 @@ EXPORT_SYMBOL_GPL(bitmap_load);
void bitmap_status(struct seq_file *seq, struct bitmap *bitmap)
{
unsigned long chunk_kb;
- unsigned long flags;
+ struct bitmap_counts *counts;
if (!bitmap)
return;
- spin_lock_irqsave(&bitmap->lock, flags);
+ counts = &bitmap->counts;
+
chunk_kb = bitmap->mddev->bitmap_info.chunksize >> 10;
seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], "
"%lu%s chunk",
- bitmap->pages - bitmap->missing_pages,
- bitmap->pages,
- (bitmap->pages - bitmap->missing_pages)
+ counts->pages - counts->missing_pages,
+ counts->pages,
+ (counts->pages - counts->missing_pages)
<< (PAGE_SHIFT - 10),
chunk_kb ? chunk_kb : bitmap->mddev->bitmap_info.chunksize,
chunk_kb ? "KB" : "B");
- if (bitmap->file) {
+ if (bitmap->storage.file) {
seq_printf(seq, ", file: ");
- seq_path(seq, &bitmap->file->f_path, " \t\n");
+ seq_path(seq, &bitmap->storage.file->f_path, " \t\n");
}
seq_printf(seq, "\n");
- spin_unlock_irqrestore(&bitmap->lock, flags);
}
+int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
+ int chunksize, int init)
+{
+ /* If chunk_size is 0, choose an appropriate chunk size.
+ * Then possibly allocate new storage space.
+ * Then quiesce, copy bits, replace bitmap, and re-start
+ *
+ * This function is called both to set up the initial bitmap
+ * and to resize the bitmap while the array is active.
+ * If this happens as a result of the array being resized,
+ * chunksize will be zero, and we need to choose a suitable
+ * chunksize, otherwise we use what we are given.
+ */
+ struct bitmap_storage store;
+ struct bitmap_counts old_counts;
+ unsigned long chunks;
+ sector_t block;
+ sector_t old_blocks, new_blocks;
+ int chunkshift;
+ int ret = 0;
+ long pages;
+ struct bitmap_page *new_bp;
+
+ if (chunksize == 0) {
+ /* If there is enough space, leave the chunk size unchanged,
+ * else increase by factor of two until there is enough space.
+ */
+ long bytes;
+ long space = bitmap->mddev->bitmap_info.space;
+
+ if (space == 0) {
+ /* We don't know how much space there is, so limit
+ * to current size - in sectors.
+ */
+ bytes = DIV_ROUND_UP(bitmap->counts.chunks, 8);
+ if (!bitmap->mddev->bitmap_info.external)
+ bytes += sizeof(bitmap_super_t);
+ space = DIV_ROUND_UP(bytes, 512);
+ bitmap->mddev->bitmap_info.space = space;
+ }
+ chunkshift = bitmap->counts.chunkshift;
+ chunkshift--;
+ do {
+ /* 'chunkshift' is shift from block size to chunk size */
+ chunkshift++;
+ chunks = DIV_ROUND_UP_SECTOR_T(blocks, 1 << chunkshift);
+ bytes = DIV_ROUND_UP(chunks, 8);
+ if (!bitmap->mddev->bitmap_info.external)
+ bytes += sizeof(bitmap_super_t);
+ } while (bytes > (space << 9));
+ } else
+ chunkshift = ffz(~chunksize) - BITMAP_BLOCK_SHIFT;
+
+ chunks = DIV_ROUND_UP_SECTOR_T(blocks, 1 << chunkshift);
+ memset(&store, 0, sizeof(store));
+ if (bitmap->mddev->bitmap_info.offset || bitmap->mddev->bitmap_info.file)
+ ret = bitmap_storage_alloc(&store, chunks,
+ !bitmap->mddev->bitmap_info.external);
+ if (ret)
+ goto err;
+
+ pages = DIV_ROUND_UP(chunks, PAGE_COUNTER_RATIO);
+
+ new_bp = kzalloc(pages * sizeof(*new_bp), GFP_KERNEL);
+ ret = -ENOMEM;
+ if (!new_bp) {
+ bitmap_file_unmap(&store);
+ goto err;
+ }
+
+ if (!init)
+ bitmap->mddev->pers->quiesce(bitmap->mddev, 1);
+
+ store.file = bitmap->storage.file;
+ bitmap->storage.file = NULL;
+
+ if (store.sb_page && bitmap->storage.sb_page)
+ memcpy(page_address(store.sb_page),
+ page_address(bitmap->storage.sb_page),
+ sizeof(bitmap_super_t));
+ bitmap_file_unmap(&bitmap->storage);
+ bitmap->storage = store;
+
+ old_counts = bitmap->counts;
+ bitmap->counts.bp = new_bp;
+ bitmap->counts.pages = pages;
+ bitmap->counts.missing_pages = pages;
+ bitmap->counts.chunkshift = chunkshift;
+ bitmap->counts.chunks = chunks;
+ bitmap->mddev->bitmap_info.chunksize = 1 << (chunkshift +
+ BITMAP_BLOCK_SHIFT);
+
+ blocks = min(old_counts.chunks << old_counts.chunkshift,
+ chunks << chunkshift);
+
+ spin_lock_irq(&bitmap->counts.lock);
+ for (block = 0; block < blocks; ) {
+ bitmap_counter_t *bmc_old, *bmc_new;
+ int set;
+
+ bmc_old = bitmap_get_counter(&old_counts, block,
+ &old_blocks, 0);
+ set = bmc_old && NEEDED(*bmc_old);
+
+ if (set) {
+ bmc_new = bitmap_get_counter(&bitmap->counts, block,
+ &new_blocks, 1);
+ if (*bmc_new == 0) {
+ /* need to set on-disk bits too. */
+ sector_t end = block + new_blocks;
+ sector_t start = block >> chunkshift;
+ start <<= chunkshift;
+ while (start < end) {
+ bitmap_file_set_bit(bitmap, block);
+ start += 1 << chunkshift;
+ }
+ *bmc_new = 2;
+ bitmap_count_page(&bitmap->counts,
+ block, 1);
+ bitmap_set_pending(&bitmap->counts,
+ block);
+ }
+ *bmc_new |= NEEDED_MASK;
+ if (new_blocks < old_blocks)
+ old_blocks = new_blocks;
+ }
+ block += old_blocks;
+ }
+
+ if (!init) {
+ int i;
+ while (block < (chunks << chunkshift)) {
+ bitmap_counter_t *bmc;
+ bmc = bitmap_get_counter(&bitmap->counts, block,
+ &new_blocks, 1);
+ if (bmc) {
+ /* new space. It needs to be resynced, so
+ * we set NEEDED_MASK.
+ */
+ if (*bmc == 0) {
+ *bmc = NEEDED_MASK | 2;
+ bitmap_count_page(&bitmap->counts,
+ block, 1);
+ bitmap_set_pending(&bitmap->counts,
+ block);
+ }
+ }
+ block += new_blocks;
+ }
+ for (i = 0; i < bitmap->storage.file_pages; i++)
+ set_page_attr(bitmap, i, BITMAP_PAGE_DIRTY);
+ }
+ spin_unlock_irq(&bitmap->counts.lock);
+
+ if (!init) {
+ bitmap_unplug(bitmap);
+ bitmap->mddev->pers->quiesce(bitmap->mddev, 0);
+ }
+ ret = 0;
+err:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(bitmap_resize);
+
static ssize_t
location_show(struct mddev *mddev, char *page)
{
@@ -1923,6 +2049,43 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
static struct md_sysfs_entry bitmap_location =
__ATTR(location, S_IRUGO|S_IWUSR, location_show, location_store);
+/* 'bitmap/space' is the space available at 'location' for the
+ * bitmap. This allows the kernel to know when it is safe to
+ * resize the bitmap to match a resized array.
+ */
+static ssize_t
+space_show(struct mddev *mddev, char *page)
+{
+ return sprintf(page, "%lu\n", mddev->bitmap_info.space);
+}
+
+static ssize_t
+space_store(struct mddev *mddev, const char *buf, size_t len)
+{
+ unsigned long sectors;
+ int rv;
+
+ rv = kstrtoul(buf, 10, &sectors);
+ if (rv)
+ return rv;
+
+ if (sectors == 0)
+ return -EINVAL;
+
+ if (mddev->bitmap &&
+ sectors < (mddev->bitmap->storage.bytes + 511) >> 9)
+ return -EFBIG; /* Bitmap is too big for this small space */
+
+ /* could make sure it isn't too big, but that isn't really
+ * needed - user-space should be careful.
+ */
+ mddev->bitmap_info.space = sectors;
+ return len;
+}
+
+static struct md_sysfs_entry bitmap_space =
+__ATTR(space, S_IRUGO|S_IWUSR, space_show, space_store);
+
static ssize_t
timeout_show(struct mddev *mddev, char *page)
{
@@ -2098,6 +2261,7 @@ __ATTR(max_backlog_used, S_IRUGO | S_IWUSR,
static struct attribute *md_bitmap_attrs[] = {
&bitmap_location.attr,
+ &bitmap_space.attr,
&bitmap_timeout.attr,
&bitmap_backlog.attr,
&bitmap_chunksize.attr,
diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h
index b44b0aba2d47..df4aeb6ac6f0 100644
--- a/drivers/md/bitmap.h
+++ b/drivers/md/bitmap.h
@@ -111,9 +111,9 @@ typedef __u16 bitmap_counter_t;
/* use these for bitmap->flags and bitmap->sb->state bit-fields */
enum bitmap_state {
- BITMAP_STALE = 0x002, /* the bitmap file is out of date or had -EIO */
- BITMAP_WRITE_ERROR = 0x004, /* A write error has occurred */
- BITMAP_HOSTENDIAN = 0x8000,
+ BITMAP_STALE = 1, /* the bitmap file is out of date or had -EIO */
+ BITMAP_WRITE_ERROR = 2, /* A write error has occurred */
+ BITMAP_HOSTENDIAN =15,
};
/* the superblock at the front of the bitmap file -- little endian */
@@ -128,8 +128,10 @@ typedef struct bitmap_super_s {
__le32 chunksize; /* 52 the bitmap chunk size in bytes */
__le32 daemon_sleep; /* 56 seconds between disk flushes */
__le32 write_behind; /* 60 number of outstanding write-behind writes */
+ __le32 sectors_reserved; /* 64 number of 512-byte sectors that are
+ * reserved for the bitmap. */
- __u8 pad[256 - 64]; /* set to zero */
+ __u8 pad[256 - 68]; /* set to zero */
} bitmap_super_t;
/* notes:
@@ -160,35 +162,48 @@ struct bitmap_page {
*/
unsigned int hijacked:1;
/*
+ * If any counter in this page is '1' or '2' - and so could be
+ * cleared then that page is marked as 'pending'
+ */
+ unsigned int pending:1;
+ /*
* count of dirty bits on the page
*/
- unsigned int count:31;
+ unsigned int count:30;
};
/* the main bitmap structure - one per mddev */
struct bitmap {
- struct bitmap_page *bp;
- unsigned long pages; /* total number of pages in the bitmap */
- unsigned long missing_pages; /* number of pages not yet allocated */
- struct mddev *mddev; /* the md device that the bitmap is for */
+ struct bitmap_counts {
+ spinlock_t lock;
+ struct bitmap_page *bp;
+ unsigned long pages; /* total number of pages
+ * in the bitmap */
+ unsigned long missing_pages; /* number of pages
+ * not yet allocated */
+ unsigned long chunkshift; /* chunksize = 2^chunkshift
+ * (for bitops) */
+ unsigned long chunks; /* Total number of data
+ * chunks for the array */
+ } counts;
- /* bitmap chunksize -- how much data does each bit represent? */
- unsigned long chunkshift; /* chunksize = 2^(chunkshift+9) (for bitops) */
- unsigned long chunks; /* total number of data chunks for the array */
+ struct mddev *mddev; /* the md device that the bitmap is for */
__u64 events_cleared;
int need_sync;
- /* bitmap spinlock */
- spinlock_t lock;
-
- struct file *file; /* backing disk file */
- struct page *sb_page; /* cached copy of the bitmap file superblock */
- struct page **filemap; /* list of cache pages for the file */
- unsigned long *filemap_attr; /* attributes associated w/ filemap pages */
- unsigned long file_pages; /* number of pages in the file */
- int last_page_size; /* bytes in the last page */
+ struct bitmap_storage {
+ struct file *file; /* backing disk file */
+ struct page *sb_page; /* cached copy of the bitmap
+ * file superblock */
+ struct page **filemap; /* list of cache pages for
+ * the file */
+ unsigned long *filemap_attr; /* attributes associated
+ * w/ filemap pages */
+ unsigned long file_pages; /* number of pages in the file*/
+ unsigned long bytes; /* total bytes in the bitmap */
+ } storage;
unsigned long flags;
@@ -242,6 +257,9 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector);
void bitmap_unplug(struct bitmap *bitmap);
void bitmap_daemon_work(struct mddev *mddev);
+
+int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
+ int chunksize, int init);
#endif
#endif
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 68965e663248..017c34d78d61 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -155,10 +155,7 @@ static void context_free(struct raid_set *rs)
for (i = 0; i < rs->md.raid_disks; i++) {
if (rs->dev[i].meta_dev)
dm_put_device(rs->ti, rs->dev[i].meta_dev);
- if (rs->dev[i].rdev.sb_page)
- put_page(rs->dev[i].rdev.sb_page);
- rs->dev[i].rdev.sb_page = NULL;
- rs->dev[i].rdev.sb_loaded = 0;
+ md_rdev_clear(&rs->dev[i].rdev);
if (rs->dev[i].data_dev)
dm_put_device(rs->ti, rs->dev[i].data_dev);
}
@@ -606,7 +603,7 @@ static int read_disk_sb(struct md_rdev *rdev, int size)
if (!sync_page_io(rdev, 0, size, rdev->sb_page, READ, 1)) {
DMERR("Failed to read superblock of device at position %d",
rdev->raid_disk);
- set_bit(Faulty, &rdev->flags);
+ md_error(rdev->mddev, rdev);
return -EINVAL;
}
@@ -617,16 +614,18 @@ static int read_disk_sb(struct md_rdev *rdev, int size)
static void super_sync(struct mddev *mddev, struct md_rdev *rdev)
{
- struct md_rdev *r;
+ int i;
uint64_t failed_devices;
struct dm_raid_superblock *sb;
+ struct raid_set *rs = container_of(mddev, struct raid_set, md);
sb = page_address(rdev->sb_page);
failed_devices = le64_to_cpu(sb->failed_devices);
- rdev_for_each(r, mddev)
- if ((r->raid_disk >= 0) && test_bit(Faulty, &r->flags))
- failed_devices |= (1ULL << r->raid_disk);
+ for (i = 0; i < mddev->raid_disks; i++)
+ if (!rs->dev[i].data_dev ||
+ test_bit(Faulty, &(rs->dev[i].rdev.flags)))
+ failed_devices |= (1ULL << i);
memset(sb, 0, sizeof(*sb));
@@ -1252,12 +1251,13 @@ static void raid_resume(struct dm_target *ti)
{
struct raid_set *rs = ti->private;
+ set_bit(MD_CHANGE_DEVS, &rs->md.flags);
if (!rs->bitmap_loaded) {
bitmap_load(&rs->md);
rs->bitmap_loaded = 1;
- } else
- md_wakeup_thread(rs->md.thread);
+ }
+ clear_bit(MD_RECOVERY_FROZEN, &rs->md.recovery);
mddev_resume(&rs->md);
}
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 2fd87b544a93..eb3d138ff55a 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -1632,6 +1632,21 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti)
pool->low_water_blocks = pt->low_water_blocks;
pool->pf = pt->pf;
+ /*
+ * If discard_passdown was enabled verify that the data device
+ * supports discards. Disable discard_passdown if not; otherwise
+ * -EOPNOTSUPP will be returned.
+ */
+ if (pt->pf.discard_passdown) {
+ struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
+ if (!q || !blk_queue_discard(q)) {
+ char buf[BDEVNAME_SIZE];
+ DMWARN("Discard unsupported by data device (%s): Disabling discard passdown.",
+ bdevname(pt->data_dev->bdev, buf));
+ pool->pf.discard_passdown = 0;
+ }
+ }
+
return 0;
}
@@ -1988,19 +2003,6 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
goto out_flags_changed;
}
- /*
- * If discard_passdown was enabled verify that the data device
- * supports discards. Disable discard_passdown if not; otherwise
- * -EOPNOTSUPP will be returned.
- */
- if (pf.discard_passdown) {
- struct request_queue *q = bdev_get_queue(data_dev->bdev);
- if (!q || !blk_queue_discard(q)) {
- DMWARN("Discard unsupported by data device: Disabling discard passdown.");
- pf.discard_passdown = 0;
- }
- }
-
pt->pool = pool;
pt->ti = ti;
pt->metadata_dev = metadata_dev;
@@ -2385,7 +2387,7 @@ static int pool_status(struct dm_target *ti, status_type_t type,
(unsigned long long)pt->low_water_blocks);
count = !pool->pf.zero_new_blocks + !pool->pf.discard_enabled +
- !pool->pf.discard_passdown;
+ !pt->pf.discard_passdown;
DMEMIT("%u ", count);
if (!pool->pf.zero_new_blocks)
@@ -2394,7 +2396,7 @@ static int pool_status(struct dm_target *ti, status_type_t type,
if (!pool->pf.discard_enabled)
DMEMIT("ignore_discard ");
- if (!pool->pf.discard_passdown)
+ if (!pt->pf.discard_passdown)
DMEMIT("no_discard_passdown ");
break;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 477eb2e180c0..1c2f9048e1ae 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -391,6 +391,8 @@ void mddev_suspend(struct mddev *mddev)
synchronize_rcu();
wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0);
mddev->pers->quiesce(mddev, 1);
+
+ del_timer_sync(&mddev->safemode_timer);
}
EXPORT_SYMBOL_GPL(mddev_suspend);
@@ -400,6 +402,7 @@ void mddev_resume(struct mddev *mddev)
wake_up(&mddev->sb_wait);
mddev->pers->quiesce(mddev, 0);
+ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
}
@@ -450,7 +453,7 @@ static void submit_flushes(struct work_struct *ws)
atomic_inc(&rdev->nr_pending);
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
- bi = bio_alloc_mddev(GFP_KERNEL, 0, mddev);
+ bi = bio_alloc_mddev(GFP_NOIO, 0, mddev);
bi->bi_end_io = md_end_flush;
bi->bi_private = rdev;
bi->bi_bdev = rdev->bdev;
@@ -605,6 +608,7 @@ void mddev_init(struct mddev *mddev)
init_waitqueue_head(&mddev->sb_wait);
init_waitqueue_head(&mddev->recovery_wait);
mddev->reshape_position = MaxSector;
+ mddev->reshape_backwards = 0;
mddev->resync_min = 0;
mddev->resync_max = MaxSector;
mddev->level = LEVEL_NONE;
@@ -800,7 +804,7 @@ static int alloc_disk_sb(struct md_rdev * rdev)
return 0;
}
-static void free_disk_sb(struct md_rdev * rdev)
+void md_rdev_clear(struct md_rdev *rdev)
{
if (rdev->sb_page) {
put_page(rdev->sb_page);
@@ -813,8 +817,10 @@ static void free_disk_sb(struct md_rdev * rdev)
put_page(rdev->bb_page);
rdev->bb_page = NULL;
}
+ kfree(rdev->badblocks.page);
+ rdev->badblocks.page = NULL;
}
-
+EXPORT_SYMBOL_GPL(md_rdev_clear);
static void super_written(struct bio *bio, int error)
{
@@ -885,6 +891,10 @@ int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
rdev->meta_bdev : rdev->bdev;
if (metadata_op)
bio->bi_sector = sector + rdev->sb_start;
+ else if (rdev->mddev->reshape_position != MaxSector &&
+ (rdev->mddev->reshape_backwards ==
+ (sector >= rdev->mddev->reshape_position)))
+ bio->bi_sector = sector + rdev->new_data_offset;
else
bio->bi_sector = sector + rdev->data_offset;
bio_add_page(bio, page, size, 0);
@@ -1032,12 +1042,17 @@ static unsigned int calc_sb_csum(mdp_super_t * sb)
struct super_type {
char *name;
struct module *owner;
- int (*load_super)(struct md_rdev *rdev, struct md_rdev *refdev,
+ int (*load_super)(struct md_rdev *rdev,
+ struct md_rdev *refdev,
int minor_version);
- int (*validate_super)(struct mddev *mddev, struct md_rdev *rdev);
- void (*sync_super)(struct mddev *mddev, struct md_rdev *rdev);
+ int (*validate_super)(struct mddev *mddev,
+ struct md_rdev *rdev);
+ void (*sync_super)(struct mddev *mddev,
+ struct md_rdev *rdev);
unsigned long long (*rdev_size_change)(struct md_rdev *rdev,
sector_t num_sectors);
+ int (*allow_new_offset)(struct md_rdev *rdev,
+ unsigned long long new_offset);
};
/*
@@ -1109,6 +1124,7 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
rdev->preferred_minor = sb->md_minor;
rdev->data_offset = 0;
+ rdev->new_data_offset = 0;
rdev->sb_size = MD_SB_BYTES;
rdev->badblocks.shift = -1;
@@ -1182,7 +1198,11 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
mddev->dev_sectors = ((sector_t)sb->size) * 2;
mddev->events = ev1;
mddev->bitmap_info.offset = 0;
+ mddev->bitmap_info.space = 0;
+ /* bitmap can use 60 K after the 4K superblocks */
mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9;
+ mddev->bitmap_info.default_space = 64*2 - (MD_SB_BYTES >> 9);
+ mddev->reshape_backwards = 0;
if (mddev->minor_version >= 91) {
mddev->reshape_position = sb->reshape_position;
@@ -1190,6 +1210,8 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
mddev->new_level = sb->new_level;
mddev->new_layout = sb->new_layout;
mddev->new_chunk_sectors = sb->new_chunk >> 9;
+ if (mddev->delta_disks < 0)
+ mddev->reshape_backwards = 1;
} else {
mddev->reshape_position = MaxSector;
mddev->delta_disks = 0;
@@ -1216,9 +1238,12 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
mddev->max_disks = MD_SB_DISKS;
if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
- mddev->bitmap_info.file == NULL)
+ mddev->bitmap_info.file == NULL) {
mddev->bitmap_info.offset =
mddev->bitmap_info.default_offset;
+ mddev->bitmap_info.space =
+ mddev->bitmap_info.space;
+ }
} else if (mddev->pers == NULL) {
/* Insist on good event counter while assembling, except
@@ -1432,6 +1457,12 @@ super_90_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
return num_sectors;
}
+static int
+super_90_allow_new_offset(struct md_rdev *rdev, unsigned long long new_offset)
+{
+ /* non-zero offset changes not possible with v0.90 */
+ return new_offset == 0;
+}
/*
* version 1 superblock
@@ -1467,6 +1498,7 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
struct mdp_superblock_1 *sb;
int ret;
sector_t sb_start;
+ sector_t sectors;
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
int bmask;
@@ -1521,9 +1553,18 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
bdevname(rdev->bdev,b));
return -EINVAL;
}
+ if (sb->pad0 ||
+ sb->pad3[0] ||
+ memcmp(sb->pad3, sb->pad3+1, sizeof(sb->pad3) - sizeof(sb->pad3[1])))
+ /* Some padding is non-zero, might be a new feature */
+ return -EINVAL;
rdev->preferred_minor = 0xffff;
rdev->data_offset = le64_to_cpu(sb->data_offset);
+ rdev->new_data_offset = rdev->data_offset;
+ if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE) &&
+ (le32_to_cpu(sb->feature_map) & MD_FEATURE_NEW_OFFSET))
+ rdev->new_data_offset += (s32)le32_to_cpu(sb->new_offset);
atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read));
rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256;
@@ -1534,6 +1575,9 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
if (minor_version
&& rdev->data_offset < sb_start + (rdev->sb_size/512))
return -EINVAL;
+ if (minor_version
+ && rdev->new_data_offset < sb_start + (rdev->sb_size/512))
+ return -EINVAL;
if (sb->level == cpu_to_le32(LEVEL_MULTIPATH))
rdev->desc_nr = -1;
@@ -1605,16 +1649,14 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
else
ret = 0;
}
- if (minor_version)
- rdev->sectors = (i_size_read(rdev->bdev->bd_inode) >> 9) -
- le64_to_cpu(sb->data_offset);
- else
- rdev->sectors = rdev->sb_start;
- if (rdev->sectors < le64_to_cpu(sb->data_size))
+ if (minor_version) {
+ sectors = (i_size_read(rdev->bdev->bd_inode) >> 9);
+ sectors -= rdev->data_offset;
+ } else
+ sectors = rdev->sb_start;
+ if (sectors < le64_to_cpu(sb->data_size))
return -EINVAL;
rdev->sectors = le64_to_cpu(sb->data_size);
- if (le64_to_cpu(sb->size) > rdev->sectors)
- return -EINVAL;
return ret;
}
@@ -1642,17 +1684,37 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
mddev->dev_sectors = le64_to_cpu(sb->size);
mddev->events = ev1;
mddev->bitmap_info.offset = 0;
+ mddev->bitmap_info.space = 0;
+ /* Default location for bitmap is 1K after superblock
+ * using 3K - total of 4K
+ */
mddev->bitmap_info.default_offset = 1024 >> 9;
-
+ mddev->bitmap_info.default_space = (4096-1024) >> 9;
+ mddev->reshape_backwards = 0;
+
mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
memcpy(mddev->uuid, sb->set_uuid, 16);
mddev->max_disks = (4096-256)/2;
if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) &&
- mddev->bitmap_info.file == NULL )
+ mddev->bitmap_info.file == NULL) {
mddev->bitmap_info.offset =
(__s32)le32_to_cpu(sb->bitmap_offset);
+ /* Metadata doesn't record how much space is available.
+ * For 1.0, we assume we can use up to the superblock
+ * if before, else to 4K beyond superblock.
+ * For others, assume no change is possible.
+ */
+ if (mddev->minor_version > 0)
+ mddev->bitmap_info.space = 0;
+ else if (mddev->bitmap_info.offset > 0)
+ mddev->bitmap_info.space =
+ 8 - mddev->bitmap_info.offset;
+ else
+ mddev->bitmap_info.space =
+ -mddev->bitmap_info.offset;
+ }
if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) {
mddev->reshape_position = le64_to_cpu(sb->reshape_position);
@@ -1660,6 +1722,11 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
mddev->new_level = le32_to_cpu(sb->new_level);
mddev->new_layout = le32_to_cpu(sb->new_layout);
mddev->new_chunk_sectors = le32_to_cpu(sb->new_chunk);
+ if (mddev->delta_disks < 0 ||
+ (mddev->delta_disks == 0 &&
+ (le32_to_cpu(sb->feature_map)
+ & MD_FEATURE_RESHAPE_BACKWARDS)))
+ mddev->reshape_backwards = 1;
} else {
mddev->reshape_position = MaxSector;
mddev->delta_disks = 0;
@@ -1733,7 +1800,6 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
sb->feature_map = 0;
sb->pad0 = 0;
sb->recovery_offset = cpu_to_le64(0);
- memset(sb->pad1, 0, sizeof(sb->pad1));
memset(sb->pad3, 0, sizeof(sb->pad3));
sb->utime = cpu_to_le64((__u64)mddev->utime);
@@ -1755,6 +1821,8 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
sb->devflags |= WriteMostly1;
else
sb->devflags &= ~WriteMostly1;
+ sb->data_offset = cpu_to_le64(rdev->data_offset);
+ sb->data_size = cpu_to_le64(rdev->sectors);
if (mddev->bitmap && mddev->bitmap_info.file == NULL) {
sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_info.offset);
@@ -1779,6 +1847,16 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
sb->delta_disks = cpu_to_le32(mddev->delta_disks);
sb->new_level = cpu_to_le32(mddev->new_level);
sb->new_chunk = cpu_to_le32(mddev->new_chunk_sectors);
+ if (mddev->delta_disks == 0 &&
+ mddev->reshape_backwards)
+ sb->feature_map
+ |= cpu_to_le32(MD_FEATURE_RESHAPE_BACKWARDS);
+ if (rdev->new_data_offset != rdev->data_offset) {
+ sb->feature_map
+ |= cpu_to_le32(MD_FEATURE_NEW_OFFSET);
+ sb->new_offset = cpu_to_le32((__u32)(rdev->new_data_offset
+ - rdev->data_offset));
+ }
}
if (rdev->badblocks.count == 0)
@@ -1855,6 +1933,8 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
sector_t max_sectors;
if (num_sectors && num_sectors < rdev->mddev->dev_sectors)
return 0; /* component must fit device */
+ if (rdev->data_offset != rdev->new_data_offset)
+ return 0; /* too confusing */
if (rdev->sb_start < rdev->data_offset) {
/* minor versions 1 and 2; superblock before data */
max_sectors = i_size_read(rdev->bdev->bd_inode) >> 9;
@@ -1882,6 +1962,40 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
rdev->sb_page);
md_super_wait(rdev->mddev);
return num_sectors;
+
+}
+
+static int
+super_1_allow_new_offset(struct md_rdev *rdev,
+ unsigned long long new_offset)
+{
+ /* All necessary checks on new >= old have been done */
+ struct bitmap *bitmap;
+ if (new_offset >= rdev->data_offset)
+ return 1;
+
+ /* with 1.0 metadata, there is no metadata to tread on
+ * so we can always move back */
+ if (rdev->mddev->minor_version == 0)
+ return 1;
+
+ /* otherwise we must be sure not to step on
+ * any metadata, so stay:
+ * 36K beyond start of superblock
+ * beyond end of badblocks
+ * beyond write-intent bitmap
+ */
+ if (rdev->sb_start + (32+4)*2 > new_offset)
+ return 0;
+ bitmap = rdev->mddev->bitmap;
+ if (bitmap && !rdev->mddev->bitmap_info.file &&
+ rdev->sb_start + rdev->mddev->bitmap_info.offset +
+ bitmap->storage.file_pages * (PAGE_SIZE>>9) > new_offset)
+ return 0;
+ if (rdev->badblocks.sector + rdev->badblocks.size > new_offset)
+ return 0;
+
+ return 1;
}
static struct super_type super_types[] = {
@@ -1892,6 +2006,7 @@ static struct super_type super_types[] = {
.validate_super = super_90_validate,
.sync_super = super_90_sync,
.rdev_size_change = super_90_rdev_size_change,
+ .allow_new_offset = super_90_allow_new_offset,
},
[1] = {
.name = "md-1",
@@ -1900,6 +2015,7 @@ static struct super_type super_types[] = {
.validate_super = super_1_validate,
.sync_super = super_1_sync,
.rdev_size_change = super_1_rdev_size_change,
+ .allow_new_offset = super_1_allow_new_offset,
},
};
@@ -2103,9 +2219,7 @@ static void unbind_rdev_from_array(struct md_rdev * rdev)
sysfs_remove_link(&rdev->kobj, "block");
sysfs_put(rdev->sysfs_state);
rdev->sysfs_state = NULL;
- kfree(rdev->badblocks.page);
rdev->badblocks.count = 0;
- rdev->badblocks.page = NULL;
/* We need to delay this, otherwise we can deadlock when
* writing to 'remove' to "dev/state". We also need
* to delay it due to rcu usage.
@@ -2156,7 +2270,7 @@ static void export_rdev(struct md_rdev * rdev)
bdevname(rdev->bdev,b));
if (rdev->mddev)
MD_BUG();
- free_disk_sb(rdev);
+ md_rdev_clear(rdev);
#ifndef MODULE
if (test_bit(AutoDetected, &rdev->flags))
md_autodetect_dev(rdev->bdev->bd_dev);
@@ -2807,9 +2921,8 @@ offset_show(struct md_rdev *rdev, char *page)
static ssize_t
offset_store(struct md_rdev *rdev, const char *buf, size_t len)
{
- char *e;
- unsigned long long offset = simple_strtoull(buf, &e, 10);
- if (e==buf || (*e && *e != '\n'))
+ unsigned long long offset;
+ if (strict_strtoull(buf, 10, &offset) < 0)
return -EINVAL;
if (rdev->mddev->pers && rdev->raid_disk >= 0)
return -EBUSY;
@@ -2824,6 +2937,63 @@ offset_store(struct md_rdev *rdev, const char *buf, size_t len)
static struct rdev_sysfs_entry rdev_offset =
__ATTR(offset, S_IRUGO|S_IWUSR, offset_show, offset_store);
+static ssize_t new_offset_show(struct md_rdev *rdev, char *page)
+{
+ return sprintf(page, "%llu\n",
+ (unsigned long long)rdev->new_data_offset);
+}
+
+static ssize_t new_offset_store(struct md_rdev *rdev,
+ const char *buf, size_t len)
+{
+ unsigned long long new_offset;
+ struct mddev *mddev = rdev->mddev;
+
+ if (strict_strtoull(buf, 10, &new_offset) < 0)
+ return -EINVAL;
+
+ if (mddev->sync_thread)
+ return -EBUSY;
+ if (new_offset == rdev->data_offset)
+ /* reset is always permitted */
+ ;
+ else if (new_offset > rdev->data_offset) {
+ /* must not push array size beyond rdev_sectors */
+ if (new_offset - rdev->data_offset
+ + mddev->dev_sectors > rdev->sectors)
+ return -E2BIG;
+ }
+ /* Metadata worries about other space details. */
+
+ /* decreasing the offset is inconsistent with a backwards
+ * reshape.
+ */
+ if (new_offset < rdev->data_offset &&
+ mddev->reshape_backwards)
+ return -EINVAL;
+ /* Increasing offset is inconsistent with forwards
+ * reshape. reshape_direction should be set to
+ * 'backwards' first.
+ */
+ if (new_offset > rdev->data_offset &&
+ !mddev->reshape_backwards)
+ return -EINVAL;
+
+ if (mddev->pers && mddev->persistent &&
+ !super_types[mddev->major_version]
+ .allow_new_offset(rdev, new_offset))
+ return -E2BIG;
+ rdev->new_data_offset = new_offset;
+ if (new_offset > rdev->data_offset)
+ mddev->reshape_backwards = 1;
+ else if (new_offset < rdev->data_offset)
+ mddev->reshape_backwards = 0;
+
+ return len;
+}
+static struct rdev_sysfs_entry rdev_new_offset =
+__ATTR(new_offset, S_IRUGO|S_IWUSR, new_offset_show, new_offset_store);
+
static ssize_t
rdev_size_show(struct md_rdev *rdev, char *page)
{
@@ -2868,6 +3038,8 @@ rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len)
if (strict_blocks_to_sectors(buf, &sectors) < 0)
return -EINVAL;
+ if (rdev->data_offset != rdev->new_data_offset)
+ return -EINVAL; /* too confusing */
if (my_mddev->pers && rdev->raid_disk >= 0) {
if (my_mddev->persistent) {
sectors = super_types[my_mddev->major_version].
@@ -3004,6 +3176,7 @@ static struct attribute *rdev_default_attrs[] = {
&rdev_errors.attr,
&rdev_slot.attr,
&rdev_offset.attr,
+ &rdev_new_offset.attr,
&rdev_size.attr,
&rdev_recovery_start.attr,
&rdev_bad_blocks.attr,
@@ -3078,6 +3251,7 @@ int md_rdev_init(struct md_rdev *rdev)
rdev->raid_disk = -1;
rdev->flags = 0;
rdev->data_offset = 0;
+ rdev->new_data_offset = 0;
rdev->sb_events = 0;
rdev->last_read_error.tv_sec = 0;
rdev->last_read_error.tv_nsec = 0;
@@ -3176,8 +3350,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
abort_free:
if (rdev->bdev)
unlock_rdev(rdev);
- free_disk_sb(rdev);
- kfree(rdev->badblocks.page);
+ md_rdev_clear(rdev);
kfree(rdev);
return ERR_PTR(err);
}
@@ -3417,6 +3590,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->raid_disks -= mddev->delta_disks;
mddev->delta_disks = 0;
+ mddev->reshape_backwards = 0;
module_put(pers->owner);
printk(KERN_WARNING "md: %s: %s would not accept array\n",
mdname(mddev), clevel);
@@ -3490,6 +3664,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
mddev->layout = mddev->new_layout;
mddev->chunk_sectors = mddev->new_chunk_sectors;
mddev->delta_disks = 0;
+ mddev->reshape_backwards = 0;
mddev->degraded = 0;
if (mddev->pers->sync_request == NULL) {
/* this is now an array without redundancy, so
@@ -3499,10 +3674,8 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
del_timer_sync(&mddev->safemode_timer);
}
pers->run(mddev);
- mddev_resume(mddev);
set_bit(MD_CHANGE_DEVS, &mddev->flags);
- set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
- md_wakeup_thread(mddev->thread);
+ mddev_resume(mddev);
sysfs_notify(&mddev->kobj, NULL, "level");
md_new_event(mddev);
return rv;
@@ -3580,9 +3753,20 @@ raid_disks_store(struct mddev *mddev, const char *buf, size_t len)
if (mddev->pers)
rv = update_raid_disks(mddev, n);
else if (mddev->reshape_position != MaxSector) {
+ struct md_rdev *rdev;
int olddisks = mddev->raid_disks - mddev->delta_disks;
+
+ rdev_for_each(rdev, mddev) {
+ if (olddisks < n &&
+ rdev->data_offset < rdev->new_data_offset)
+ return -EINVAL;
+ if (olddisks > n &&
+ rdev->data_offset > rdev->new_data_offset)
+ return -EINVAL;
+ }
mddev->delta_disks = n - olddisks;
mddev->raid_disks = n;
+ mddev->reshape_backwards = (mddev->delta_disks < 0);
} else
mddev->raid_disks = n;
return rv ? rv : len;
@@ -4264,7 +4448,8 @@ sync_completed_show(struct mddev *mddev, char *page)
if (!test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
return sprintf(page, "none\n");
- if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+ if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ||
+ test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
max_sectors = mddev->resync_max_sectors;
else
max_sectors = mddev->dev_sectors;
@@ -4426,6 +4611,7 @@ reshape_position_show(struct mddev *mddev, char *page)
static ssize_t
reshape_position_store(struct mddev *mddev, const char *buf, size_t len)
{
+ struct md_rdev *rdev;
char *e;
unsigned long long new = simple_strtoull(buf, &e, 10);
if (mddev->pers)
@@ -4434,9 +4620,12 @@ reshape_position_store(struct mddev *mddev, const char *buf, size_t len)
return -EINVAL;
mddev->reshape_position = new;
mddev->delta_disks = 0;
+ mddev->reshape_backwards = 0;
mddev->new_level = mddev->level;
mddev->new_layout = mddev->layout;
mddev->new_chunk_sectors = mddev->chunk_sectors;
+ rdev_for_each(rdev, mddev)
+ rdev->new_data_offset = rdev->data_offset;
return len;
}
@@ -4445,6 +4634,42 @@ __ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show,
reshape_position_store);
static ssize_t
+reshape_direction_show(struct mddev *mddev, char *page)
+{
+ return sprintf(page, "%s\n",
+ mddev->reshape_backwards ? "backwards" : "forwards");
+}
+
+static ssize_t
+reshape_direction_store(struct mddev *mddev, const char *buf, size_t len)
+{
+ int backwards = 0;
+ if (cmd_match(buf, "forwards"))
+ backwards = 0;
+ else if (cmd_match(buf, "backwards"))
+ backwards = 1;
+ else
+ return -EINVAL;
+ if (mddev->reshape_backwards == backwards)
+ return len;
+
+ /* check if we are allowed to change */
+ if (mddev->delta_disks)
+ return -EBUSY;
+
+ if (mddev->persistent &&
+ mddev->major_version == 0)
+ return -EINVAL;
+
+ mddev->reshape_backwards = backwards;
+ return len;
+}
+
+static struct md_sysfs_entry md_reshape_direction =
+__ATTR(reshape_direction, S_IRUGO|S_IWUSR, reshape_direction_show,
+ reshape_direction_store);
+
+static ssize_t
array_size_show(struct mddev *mddev, char *page)
{
if (mddev->external_size)
@@ -4499,6 +4724,7 @@ static struct attribute *md_default_attrs[] = {
&md_safe_delay.attr,
&md_array_state.attr,
&md_reshape_position.attr,
+ &md_reshape_direction.attr,
&md_array_size.attr,
&max_corr_read_errors.attr,
NULL,
@@ -4912,7 +5138,8 @@ int md_run(struct mddev *mddev)
err = -EINVAL;
mddev->pers->stop(mddev);
}
- if (err == 0 && mddev->pers->sync_request) {
+ if (err == 0 && mddev->pers->sync_request &&
+ (mddev->bitmap_info.file || mddev->bitmap_info.offset)) {
err = bitmap_create(mddev);
if (err) {
printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
@@ -5062,6 +5289,7 @@ static void md_clean(struct mddev *mddev)
mddev->events = 0;
mddev->can_decrease_events = 0;
mddev->delta_disks = 0;
+ mddev->reshape_backwards = 0;
mddev->new_level = LEVEL_NONE;
mddev->new_layout = 0;
mddev->new_chunk_sectors = 0;
@@ -5077,6 +5305,7 @@ static void md_clean(struct mddev *mddev)
mddev->merge_check_needed = 0;
mddev->bitmap_info.offset = 0;
mddev->bitmap_info.default_offset = 0;
+ mddev->bitmap_info.default_space = 0;
mddev->bitmap_info.chunksize = 0;
mddev->bitmap_info.daemon_sleep = 0;
mddev->bitmap_info.max_write_behind = 0;
@@ -5419,7 +5648,7 @@ static int get_bitmap_file(struct mddev * mddev, void __user * arg)
goto out;
/* bitmap disabled, zero the first byte and copy out */
- if (!mddev->bitmap || !mddev->bitmap->file) {
+ if (!mddev->bitmap || !mddev->bitmap->storage.file) {
file->pathname[0] = '\0';
goto copy_out;
}
@@ -5428,7 +5657,8 @@ static int get_bitmap_file(struct mddev * mddev, void __user * arg)
if (!buf)
goto out;
- ptr = d_path(&mddev->bitmap->file->f_path, buf, sizeof(file->pathname));
+ ptr = d_path(&mddev->bitmap->storage.file->f_path,
+ buf, sizeof(file->pathname));
if (IS_ERR(ptr))
goto out;
@@ -5873,6 +6103,7 @@ static int set_array_info(struct mddev * mddev, mdu_array_info_t *info)
set_bit(MD_CHANGE_DEVS, &mddev->flags);
mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9;
+ mddev->bitmap_info.default_space = 64*2 - (MD_SB_BYTES >> 9);
mddev->bitmap_info.offset = 0;
mddev->reshape_position = MaxSector;
@@ -5886,6 +6117,7 @@ static int set_array_info(struct mddev * mddev, mdu_array_info_t *info)
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->new_layout = mddev->layout;
mddev->delta_disks = 0;
+ mddev->reshape_backwards = 0;
return 0;
}
@@ -5920,11 +6152,7 @@ static int update_size(struct mddev *mddev, sector_t num_sectors)
*/
if (mddev->sync_thread)
return -EBUSY;
- if (mddev->bitmap)
- /* Sorry, cannot grow a bitmap yet, just remove it,
- * grow, and re-add.
- */
- return -EBUSY;
+
rdev_for_each(rdev, mddev) {
sector_t avail = rdev->sectors;
@@ -5942,6 +6170,7 @@ static int update_size(struct mddev *mddev, sector_t num_sectors)
static int update_raid_disks(struct mddev *mddev, int raid_disks)
{
int rv;
+ struct md_rdev *rdev;
/* change the number of raid disks */
if (mddev->pers->check_reshape == NULL)
return -EINVAL;
@@ -5950,11 +6179,27 @@ static int update_raid_disks(struct mddev *mddev, int raid_disks)
return -EINVAL;
if (mddev->sync_thread || mddev->reshape_position != MaxSector)
return -EBUSY;
+
+ rdev_for_each(rdev, mddev) {
+ if (mddev->raid_disks < raid_disks &&
+ rdev->data_offset < rdev->new_data_offset)
+ return -EINVAL;
+ if (mddev->raid_disks > raid_disks &&
+ rdev->data_offset > rdev->new_data_offset)
+ return -EINVAL;
+ }
+
mddev->delta_disks = raid_disks - mddev->raid_disks;
+ if (mddev->delta_disks < 0)
+ mddev->reshape_backwards = 1;
+ else if (mddev->delta_disks > 0)
+ mddev->reshape_backwards = 0;
rv = mddev->pers->check_reshape(mddev);
- if (rv < 0)
+ if (rv < 0) {
mddev->delta_disks = 0;
+ mddev->reshape_backwards = 0;
+ }
return rv;
}
@@ -6037,6 +6282,8 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
return -EINVAL;
mddev->bitmap_info.offset =
mddev->bitmap_info.default_offset;
+ mddev->bitmap_info.space =
+ mddev->bitmap_info.default_space;
mddev->pers->quiesce(mddev, 1);
rv = bitmap_create(mddev);
if (!rv)
@@ -6048,7 +6295,7 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
/* remove the bitmap */
if (!mddev->bitmap)
return -ENOENT;
- if (mddev->bitmap->file)
+ if (mddev->bitmap->storage.file)
return -EINVAL;
mddev->pers->quiesce(mddev, 1);
bitmap_destroy(mddev);
@@ -6371,6 +6618,9 @@ static int md_open(struct block_device *bdev, fmode_t mode)
struct mddev *mddev = mddev_find(bdev->bd_dev);
int err;
+ if (!mddev)
+ return -ENODEV;
+
if (mddev->gendisk != bdev->bd_disk) {
/* we are racing with mddev_put which is discarding this
* bd_disk.
@@ -6582,7 +6832,8 @@ static void status_resync(struct seq_file *seq, struct mddev * mddev)
resync = mddev->curr_resync - atomic_read(&mddev->recovery_active);
- if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+ if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ||
+ test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
max_sectors = mddev->resync_max_sectors;
else
max_sectors = mddev->dev_sectors;
@@ -7145,7 +7396,7 @@ void md_do_sync(struct mddev *mddev)
j = mddev->recovery_cp;
} else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
- max_sectors = mddev->dev_sectors;
+ max_sectors = mddev->resync_max_sectors;
else {
/* recovery follows the physical size of devices */
max_sectors = mddev->dev_sectors;
@@ -7596,7 +7847,7 @@ void md_check_recovery(struct mddev *mddev)
goto unlock;
if (mddev->pers->sync_request) {
- if (spares && mddev->bitmap && ! mddev->bitmap->file) {
+ if (spares) {
/* We are adding a device or devices to an array
* which has the bitmap stored on all devices.
* So make sure all bitmap pages get written
@@ -7644,6 +7895,20 @@ void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev)
}
EXPORT_SYMBOL(md_wait_for_blocked_rdev);
+void md_finish_reshape(struct mddev *mddev)
+{
+ /* called be personality module when reshape completes. */
+ struct md_rdev *rdev;
+
+ rdev_for_each(rdev, mddev) {
+ if (rdev->data_offset > rdev->new_data_offset)
+ rdev->sectors += rdev->data_offset - rdev->new_data_offset;
+ else
+ rdev->sectors -= rdev->new_data_offset - rdev->data_offset;
+ rdev->data_offset = rdev->new_data_offset;
+ }
+}
+EXPORT_SYMBOL(md_finish_reshape);
/* Bad block management.
* We can record which blocks on each device are 'bad' and so just
@@ -7892,10 +8157,15 @@ static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
}
int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
- int acknowledged)
+ int is_new)
{
- int rv = md_set_badblocks(&rdev->badblocks,
- s + rdev->data_offset, sectors, acknowledged);
+ int rv;
+ if (is_new)
+ s += rdev->new_data_offset;
+ else
+ s += rdev->data_offset;
+ rv = md_set_badblocks(&rdev->badblocks,
+ s, sectors, 0);
if (rv) {
/* Make sure they get written out promptly */
sysfs_notify_dirent_safe(rdev->sysfs_state);
@@ -8001,11 +8271,15 @@ out:
return rv;
}
-int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors)
+int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
+ int is_new)
{
+ if (is_new)
+ s += rdev->new_data_offset;
+ else
+ s += rdev->data_offset;
return md_clear_badblocks(&rdev->badblocks,
- s + rdev->data_offset,
- sectors);
+ s, sectors);
}
EXPORT_SYMBOL_GPL(rdev_clear_badblocks);
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 1c2063ccf48e..7b4a3c318cae 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -55,6 +55,7 @@ struct md_rdev {
int sb_loaded;
__u64 sb_events;
sector_t data_offset; /* start of data in array */
+ sector_t new_data_offset;/* only relevant while reshaping */
sector_t sb_start; /* offset of the super block (in 512byte sectors) */
int sb_size; /* bytes in the superblock */
int preferred_minor; /* autorun support */
@@ -193,8 +194,9 @@ static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors,
return 0;
}
extern int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
- int acknowledged);
-extern int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors);
+ int is_new);
+extern int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
+ int is_new);
extern void md_ack_all_badblocks(struct badblocks *bb);
struct mddev {
@@ -262,6 +264,7 @@ struct mddev {
sector_t reshape_position;
int delta_disks, new_level, new_layout;
int new_chunk_sectors;
+ int reshape_backwards;
atomic_t plug_cnt; /* If device is expecting
* more bios soon.
@@ -390,10 +393,13 @@ struct mddev {
* For external metadata, offset
* from start of device.
*/
+ unsigned long space; /* space available at this offset */
loff_t default_offset; /* this is the offset to use when
* hot-adding a bitmap. It should
* eventually be settable by sysfs.
*/
+ unsigned long default_space; /* space available at
+ * default offset */
struct mutex mutex;
unsigned long chunksize;
unsigned long daemon_sleep; /* how many jiffies between updates? */
@@ -591,6 +597,7 @@ extern void md_write_start(struct mddev *mddev, struct bio *bi);
extern void md_write_end(struct mddev *mddev);
extern void md_done_sync(struct mddev *mddev, int blocks, int ok);
extern void md_error(struct mddev *mddev, struct md_rdev *rdev);
+extern void md_finish_reshape(struct mddev *mddev);
extern int mddev_congested(struct mddev *mddev, int bits);
extern void md_flush_request(struct mddev *mddev, struct bio *bio);
@@ -615,6 +622,7 @@ extern int md_run(struct mddev *mddev);
extern void md_stop(struct mddev *mddev);
extern void md_stop_writes(struct mddev *mddev);
extern int md_rdev_init(struct md_rdev *rdev);
+extern void md_rdev_clear(struct md_rdev *rdev);
extern void mddev_suspend(struct mddev *mddev);
extern void mddev_resume(struct mddev *mddev);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 15dd59b84e94..835de7168cd3 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1859,7 +1859,9 @@ static void fix_read_error(struct r1conf *conf, int read_disk,
rdev = conf->mirrors[d].rdev;
if (rdev &&
- test_bit(In_sync, &rdev->flags) &&
+ (test_bit(In_sync, &rdev->flags) ||
+ (!test_bit(Faulty, &rdev->flags) &&
+ rdev->recovery_offset >= sect + s)) &&
is_badblock(rdev, sect, s,
&first_bad, &bad_sectors) == 0 &&
sync_page_io(rdev, sect, s<<9,
@@ -2024,7 +2026,7 @@ static void handle_sync_write_finished(struct r1conf *conf, struct r1bio *r1_bio
continue;
if (test_bit(BIO_UPTODATE, &bio->bi_flags) &&
test_bit(R1BIO_MadeGood, &r1_bio->state)) {
- rdev_clear_badblocks(rdev, r1_bio->sector, s);
+ rdev_clear_badblocks(rdev, r1_bio->sector, s, 0);
}
if (!test_bit(BIO_UPTODATE, &bio->bi_flags) &&
test_bit(R1BIO_WriteError, &r1_bio->state)) {
@@ -2044,7 +2046,7 @@ static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
struct md_rdev *rdev = conf->mirrors[m].rdev;
rdev_clear_badblocks(rdev,
r1_bio->sector,
- r1_bio->sectors);
+ r1_bio->sectors, 0);
rdev_dec_pending(rdev, conf->mddev);
} else if (r1_bio->bios[m] != NULL) {
/* This drive got a write error. We need to
@@ -2598,7 +2600,8 @@ static struct r1conf *setup_conf(struct mddev *mddev)
if (!disk->rdev ||
!test_bit(In_sync, &disk->rdev->flags)) {
disk->head_position = 0;
- if (disk->rdev)
+ if (disk->rdev &&
+ (disk->rdev->saved_raid_disk < 0))
conf->fullsync = 1;
} else if (conf->last_used < 0)
/*
@@ -2750,9 +2753,16 @@ static int raid1_resize(struct mddev *mddev, sector_t sectors)
* any io in the removed space completes, but it hardly seems
* worth it.
*/
- md_set_array_sectors(mddev, raid1_size(mddev, sectors, 0));
- if (mddev->array_sectors > raid1_size(mddev, sectors, 0))
+ sector_t newsize = raid1_size(mddev, sectors, 0);
+ if (mddev->external_size &&
+ mddev->array_sectors > newsize)
return -EINVAL;
+ if (mddev->bitmap) {
+ int ret = bitmap_resize(mddev->bitmap, newsize, 0, 0);
+ if (ret)
+ return ret;
+ }
+ md_set_array_sectors(mddev, newsize);
set_capacity(mddev->gendisk, mddev->array_sectors);
revalidate_disk(mddev->gendisk);
if (sectors > mddev->dev_sectors &&
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index c8dbb84d5357..987db37cb875 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/ratelimit.h>
+#include <linux/kthread.h>
#include "md.h"
#include "raid10.h"
#include "raid0.h"
@@ -68,6 +69,11 @@ static int max_queued_requests = 1024;
static void allow_barrier(struct r10conf *conf);
static void lower_barrier(struct r10conf *conf);
static int enough(struct r10conf *conf, int ignore);
+static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr,
+ int *skipped);
+static void reshape_request_write(struct mddev *mddev, struct r10bio *r10_bio);
+static void end_reshape_write(struct bio *bio, int error);
+static void end_reshape(struct r10conf *conf);
static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
{
@@ -112,7 +118,8 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
if (!r10_bio)
return NULL;
- if (test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery))
+ if (test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery) ||
+ test_bit(MD_RECOVERY_RESHAPE, &conf->mddev->recovery))
nalloc = conf->copies; /* resync */
else
nalloc = 2; /* recovery */
@@ -140,9 +147,10 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
struct bio *rbio = r10_bio->devs[j].repl_bio;
bio = r10_bio->devs[j].bio;
for (i = 0; i < RESYNC_PAGES; i++) {
- if (j == 1 && !test_bit(MD_RECOVERY_SYNC,
- &conf->mddev->recovery)) {
- /* we can share bv_page's during recovery */
+ if (j > 0 && !test_bit(MD_RECOVERY_SYNC,
+ &conf->mddev->recovery)) {
+ /* we can share bv_page's during recovery
+ * and reshape */
struct bio *rbio = r10_bio->devs[0].bio;
page = rbio->bi_io_vec[i].bv_page;
get_page(page);
@@ -165,10 +173,11 @@ out_free_pages:
while (j--)
for (i = 0; i < RESYNC_PAGES ; i++)
safe_put_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page);
- j = -1;
+ j = 0;
out_free_bio:
- while (++j < nalloc) {
- bio_put(r10_bio->devs[j].bio);
+ for ( ; j < nalloc; j++) {
+ if (r10_bio->devs[j].bio)
+ bio_put(r10_bio->devs[j].bio);
if (r10_bio->devs[j].repl_bio)
bio_put(r10_bio->devs[j].repl_bio);
}
@@ -504,79 +513,96 @@ static void raid10_end_write_request(struct bio *bio, int error)
* sector offset to a virtual address
*/
-static void raid10_find_phys(struct r10conf *conf, struct r10bio *r10bio)
+static void __raid10_find_phys(struct geom *geo, struct r10bio *r10bio)
{
int n,f;
sector_t sector;
sector_t chunk;
sector_t stripe;
int dev;
-
int slot = 0;
/* now calculate first sector/dev */
- chunk = r10bio->sector >> conf->chunk_shift;
- sector = r10bio->sector & conf->chunk_mask;
+ chunk = r10bio->sector >> geo->chunk_shift;
+ sector = r10bio->sector & geo->chunk_mask;
- chunk *= conf->near_copies;
+ chunk *= geo->near_copies;
stripe = chunk;
- dev = sector_div(stripe, conf->raid_disks);
- if (conf->far_offset)
- stripe *= conf->far_copies;
+ dev = sector_div(stripe, geo->raid_disks);
+ if (geo->far_offset)
+ stripe *= geo->far_copies;
- sector += stripe << conf->chunk_shift;
+ sector += stripe << geo->chunk_shift;
/* and calculate all the others */
- for (n=0; n < conf->near_copies; n++) {
+ for (n = 0; n < geo->near_copies; n++) {
int d = dev;
sector_t s = sector;
r10bio->devs[slot].addr = sector;
r10bio->devs[slot].devnum = d;
slot++;
- for (f = 1; f < conf->far_copies; f++) {
- d += conf->near_copies;
- if (d >= conf->raid_disks)
- d -= conf->raid_disks;
- s += conf->stride;
+ for (f = 1; f < geo->far_copies; f++) {
+ d += geo->near_copies;
+ if (d >= geo->raid_disks)
+ d -= geo->raid_disks;
+ s += geo->stride;
r10bio->devs[slot].devnum = d;
r10bio->devs[slot].addr = s;
slot++;
}
dev++;
- if (dev >= conf->raid_disks) {
+ if (dev >= geo->raid_disks) {
dev = 0;
- sector += (conf->chunk_mask + 1);
+ sector += (geo->chunk_mask + 1);
}
}
- BUG_ON(slot != conf->copies);
+}
+
+static void raid10_find_phys(struct r10conf *conf, struct r10bio *r10bio)
+{
+ struct geom *geo = &conf->geo;
+
+ if (conf->reshape_progress != MaxSector &&
+ ((r10bio->sector >= conf->reshape_progress) !=
+ conf->mddev->reshape_backwards)) {
+ set_bit(R10BIO_Previous, &r10bio->state);
+ geo = &conf->prev;
+ } else
+ clear_bit(R10BIO_Previous, &r10bio->state);
+
+ __raid10_find_phys(geo, r10bio);
}
static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev)
{
sector_t offset, chunk, vchunk;
+ /* Never use conf->prev as this is only called during resync
+ * or recovery, so reshape isn't happening
+ */
+ struct geom *geo = &conf->geo;
- offset = sector & conf->chunk_mask;
- if (conf->far_offset) {
+ offset = sector & geo->chunk_mask;
+ if (geo->far_offset) {
int fc;
- chunk = sector >> conf->chunk_shift;
- fc = sector_div(chunk, conf->far_copies);
- dev -= fc * conf->near_copies;
+ chunk = sector >> geo->chunk_shift;
+ fc = sector_div(chunk, geo->far_copies);
+ dev -= fc * geo->near_copies;
if (dev < 0)
- dev += conf->raid_disks;
+ dev += geo->raid_disks;
} else {
- while (sector >= conf->stride) {
- sector -= conf->stride;
- if (dev < conf->near_copies)
- dev += conf->raid_disks - conf->near_copies;
+ while (sector >= geo->stride) {
+ sector -= geo->stride;
+ if (dev < geo->near_copies)
+ dev += geo->raid_disks - geo->near_copies;
else
- dev -= conf->near_copies;
+ dev -= geo->near_copies;
}
- chunk = sector >> conf->chunk_shift;
+ chunk = sector >> geo->chunk_shift;
}
- vchunk = chunk * conf->raid_disks + dev;
- sector_div(vchunk, conf->near_copies);
- return (vchunk << conf->chunk_shift) + offset;
+ vchunk = chunk * geo->raid_disks + dev;
+ sector_div(vchunk, geo->near_copies);
+ return (vchunk << geo->chunk_shift) + offset;
}
/**
@@ -597,10 +623,17 @@ static int raid10_mergeable_bvec(struct request_queue *q,
struct r10conf *conf = mddev->private;
sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
int max;
- unsigned int chunk_sectors = mddev->chunk_sectors;
+ unsigned int chunk_sectors;
unsigned int bio_sectors = bvm->bi_size >> 9;
+ struct geom *geo = &conf->geo;
+
+ chunk_sectors = (conf->geo.chunk_mask & conf->prev.chunk_mask) + 1;
+ if (conf->reshape_progress != MaxSector &&
+ ((sector >= conf->reshape_progress) !=
+ conf->mddev->reshape_backwards))
+ geo = &conf->prev;
- if (conf->near_copies < conf->raid_disks) {
+ if (geo->near_copies < geo->raid_disks) {
max = (chunk_sectors - ((sector & (chunk_sectors - 1))
+ bio_sectors)) << 9;
if (max < 0)
@@ -614,6 +647,12 @@ static int raid10_mergeable_bvec(struct request_queue *q,
if (mddev->merge_check_needed) {
struct r10bio r10_bio;
int s;
+ if (conf->reshape_progress != MaxSector) {
+ /* Cannot give any guidance during reshape */
+ if (max <= biovec->bv_len && bio_sectors == 0)
+ return biovec->bv_len;
+ return 0;
+ }
r10_bio.sector = sector;
raid10_find_phys(conf, &r10_bio);
rcu_read_lock();
@@ -681,6 +720,7 @@ static struct md_rdev *read_balance(struct r10conf *conf,
struct md_rdev *rdev, *best_rdev;
int do_balance;
int best_slot;
+ struct geom *geo = &conf->geo;
raid10_find_phys(conf, r10_bio);
rcu_read_lock();
@@ -761,11 +801,11 @@ retry:
* sequential read speed for 'far copies' arrays. So only
* keep it for 'near' arrays, and review those later.
*/
- if (conf->near_copies > 1 && !atomic_read(&rdev->nr_pending))
+ if (geo->near_copies > 1 && !atomic_read(&rdev->nr_pending))
break;
/* for far > 1 always use the lowest address */
- if (conf->far_copies > 1)
+ if (geo->far_copies > 1)
new_distance = r10_bio->devs[slot].addr;
else
new_distance = abs(r10_bio->devs[slot].addr -
@@ -812,7 +852,10 @@ static int raid10_congested(void *data, int bits)
if (mddev_congested(mddev, bits))
return 1;
rcu_read_lock();
- for (i = 0; i < conf->raid_disks && ret == 0; i++) {
+ for (i = 0;
+ (i < conf->geo.raid_disks || i < conf->prev.raid_disks)
+ && ret == 0;
+ i++) {
struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
if (rdev && !test_bit(Faulty, &rdev->flags)) {
struct request_queue *q = bdev_get_queue(rdev->bdev);
@@ -973,13 +1016,24 @@ static void unfreeze_array(struct r10conf *conf)
spin_unlock_irq(&conf->resync_lock);
}
+static sector_t choose_data_offset(struct r10bio *r10_bio,
+ struct md_rdev *rdev)
+{
+ if (!test_bit(MD_RECOVERY_RESHAPE, &rdev->mddev->recovery) ||
+ test_bit(R10BIO_Previous, &r10_bio->state))
+ return rdev->data_offset;
+ else
+ return rdev->new_data_offset;
+}
+
static void make_request(struct mddev *mddev, struct bio * bio)
{
struct r10conf *conf = mddev->private;
struct r10bio *r10_bio;
struct bio *read_bio;
int i;
- int chunk_sects = conf->chunk_mask + 1;
+ sector_t chunk_mask = (conf->geo.chunk_mask & conf->prev.chunk_mask);
+ int chunk_sects = chunk_mask + 1;
const int rw = bio_data_dir(bio);
const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
@@ -988,6 +1042,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
int plugged;
int sectors_handled;
int max_sectors;
+ int sectors;
if (unlikely(bio->bi_rw & REQ_FLUSH)) {
md_flush_request(mddev, bio);
@@ -997,9 +1052,10 @@ static void make_request(struct mddev *mddev, struct bio * bio)
/* If this request crosses a chunk boundary, we need to
* split it. This will only happen for 1 PAGE (or less) requests.
*/
- if (unlikely( (bio->bi_sector & conf->chunk_mask) + (bio->bi_size >> 9)
- > chunk_sects &&
- conf->near_copies < conf->raid_disks)) {
+ if (unlikely((bio->bi_sector & chunk_mask) + (bio->bi_size >> 9)
+ > chunk_sects
+ && (conf->geo.near_copies < conf->geo.raid_disks
+ || conf->prev.near_copies < conf->prev.raid_disks))) {
struct bio_pair *bp;
/* Sanity check -- queue functions should prevent this happening */
if (bio->bi_vcnt != 1 ||
@@ -1051,10 +1107,41 @@ static void make_request(struct mddev *mddev, struct bio * bio)
*/
wait_barrier(conf);
+ sectors = bio->bi_size >> 9;
+ while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
+ bio->bi_sector < conf->reshape_progress &&
+ bio->bi_sector + sectors > conf->reshape_progress) {
+ /* IO spans the reshape position. Need to wait for
+ * reshape to pass
+ */
+ allow_barrier(conf);
+ wait_event(conf->wait_barrier,
+ conf->reshape_progress <= bio->bi_sector ||
+ conf->reshape_progress >= bio->bi_sector + sectors);
+ wait_barrier(conf);
+ }
+ if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
+ bio_data_dir(bio) == WRITE &&
+ (mddev->reshape_backwards
+ ? (bio->bi_sector < conf->reshape_safe &&
+ bio->bi_sector + sectors > conf->reshape_progress)
+ : (bio->bi_sector + sectors > conf->reshape_safe &&
+ bio->bi_sector < conf->reshape_progress))) {
+ /* Need to update reshape_position in metadata */
+ mddev->reshape_position = conf->reshape_progress;
+ set_bit(MD_CHANGE_DEVS, &mddev->flags);
+ set_bit(MD_CHANGE_PENDING, &mddev->flags);
+ md_wakeup_thread(mddev->thread);
+ wait_event(mddev->sb_wait,
+ !test_bit(MD_CHANGE_PENDING, &mddev->flags));
+
+ conf->reshape_safe = mddev->reshape_position;
+ }
+
r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
r10_bio->master_bio = bio;
- r10_bio->sectors = bio->bi_size >> 9;
+ r10_bio->sectors = sectors;
r10_bio->mddev = mddev;
r10_bio->sector = bio->bi_sector;
@@ -1093,7 +1180,7 @@ read_again:
r10_bio->devs[slot].rdev = rdev;
read_bio->bi_sector = r10_bio->devs[slot].addr +
- rdev->data_offset;
+ choose_data_offset(r10_bio, rdev);
read_bio->bi_bdev = rdev->bdev;
read_bio->bi_end_io = raid10_end_read_request;
read_bio->bi_rw = READ | do_sync;
@@ -1297,7 +1384,8 @@ retry_write:
r10_bio->devs[i].bio = mbio;
mbio->bi_sector = (r10_bio->devs[i].addr+
- conf->mirrors[d].rdev->data_offset);
+ choose_data_offset(r10_bio,
+ conf->mirrors[d].rdev));
mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
mbio->bi_end_io = raid10_end_write_request;
mbio->bi_rw = WRITE | do_sync | do_fua;
@@ -1321,8 +1409,10 @@ retry_write:
* so it cannot disappear, so the replacement cannot
* become NULL here
*/
- mbio->bi_sector = (r10_bio->devs[i].addr+
- conf->mirrors[d].replacement->data_offset);
+ mbio->bi_sector = (r10_bio->devs[i].addr +
+ choose_data_offset(
+ r10_bio,
+ conf->mirrors[d].replacement));
mbio->bi_bdev = conf->mirrors[d].replacement->bdev;
mbio->bi_end_io = raid10_end_write_request;
mbio->bi_rw = WRITE | do_sync | do_fua;
@@ -1368,19 +1458,19 @@ static void status(struct seq_file *seq, struct mddev *mddev)
struct r10conf *conf = mddev->private;
int i;
- if (conf->near_copies < conf->raid_disks)
+ if (conf->geo.near_copies < conf->geo.raid_disks)
seq_printf(seq, " %dK chunks", mddev->chunk_sectors / 2);
- if (conf->near_copies > 1)
- seq_printf(seq, " %d near-copies", conf->near_copies);
- if (conf->far_copies > 1) {
- if (conf->far_offset)
- seq_printf(seq, " %d offset-copies", conf->far_copies);
+ if (conf->geo.near_copies > 1)
+ seq_printf(seq, " %d near-copies", conf->geo.near_copies);
+ if (conf->geo.far_copies > 1) {
+ if (conf->geo.far_offset)
+ seq_printf(seq, " %d offset-copies", conf->geo.far_copies);
else
- seq_printf(seq, " %d far-copies", conf->far_copies);
+ seq_printf(seq, " %d far-copies", conf->geo.far_copies);
}
- seq_printf(seq, " [%d/%d] [", conf->raid_disks,
- conf->raid_disks - mddev->degraded);
- for (i = 0; i < conf->raid_disks; i++)
+ seq_printf(seq, " [%d/%d] [", conf->geo.raid_disks,
+ conf->geo.raid_disks - mddev->degraded);
+ for (i = 0; i < conf->geo.raid_disks; i++)
seq_printf(seq, "%s",
conf->mirrors[i].rdev &&
test_bit(In_sync, &conf->mirrors[i].rdev->flags) ? "U" : "_");
@@ -1392,7 +1482,7 @@ static void status(struct seq_file *seq, struct mddev *mddev)
* Don't consider the device numbered 'ignore'
* as we might be about to remove it.
*/
-static int enough(struct r10conf *conf, int ignore)
+static int _enough(struct r10conf *conf, struct geom *geo, int ignore)
{
int first = 0;
@@ -1403,7 +1493,7 @@ static int enough(struct r10conf *conf, int ignore)
if (conf->mirrors[first].rdev &&
first != ignore)
cnt++;
- first = (first+1) % conf->raid_disks;
+ first = (first+1) % geo->raid_disks;
}
if (cnt == 0)
return 0;
@@ -1411,6 +1501,12 @@ static int enough(struct r10conf *conf, int ignore)
return 1;
}
+static int enough(struct r10conf *conf, int ignore)
+{
+ return _enough(conf, &conf->geo, ignore) &&
+ _enough(conf, &conf->prev, ignore);
+}
+
static void error(struct mddev *mddev, struct md_rdev *rdev)
{
char b[BDEVNAME_SIZE];
@@ -1445,7 +1541,7 @@ static void error(struct mddev *mddev, struct md_rdev *rdev)
"md/raid10:%s: Disk failure on %s, disabling device.\n"
"md/raid10:%s: Operation continuing on %d devices.\n",
mdname(mddev), bdevname(rdev->bdev, b),
- mdname(mddev), conf->raid_disks - mddev->degraded);
+ mdname(mddev), conf->geo.raid_disks - mddev->degraded);
}
static void print_conf(struct r10conf *conf)
@@ -1458,10 +1554,10 @@ static void print_conf(struct r10conf *conf)
printk(KERN_DEBUG "(!conf)\n");
return;
}
- printk(KERN_DEBUG " --- wd:%d rd:%d\n", conf->raid_disks - conf->mddev->degraded,
- conf->raid_disks);
+ printk(KERN_DEBUG " --- wd:%d rd:%d\n", conf->geo.raid_disks - conf->mddev->degraded,
+ conf->geo.raid_disks);
- for (i = 0; i < conf->raid_disks; i++) {
+ for (i = 0; i < conf->geo.raid_disks; i++) {
char b[BDEVNAME_SIZE];
tmp = conf->mirrors + i;
if (tmp->rdev)
@@ -1493,7 +1589,7 @@ static int raid10_spare_active(struct mddev *mddev)
* Find all non-in_sync disks within the RAID10 configuration
* and mark them in_sync
*/
- for (i = 0; i < conf->raid_disks; i++) {
+ for (i = 0; i < conf->geo.raid_disks; i++) {
tmp = conf->mirrors + i;
if (tmp->replacement
&& tmp->replacement->recovery_offset == MaxSector
@@ -1535,7 +1631,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
int err = -EEXIST;
int mirror;
int first = 0;
- int last = conf->raid_disks - 1;
+ int last = conf->geo.raid_disks - 1;
struct request_queue *q = bdev_get_queue(rdev->bdev);
if (mddev->recovery_cp < MaxSector)
@@ -1543,7 +1639,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
* very different from resync
*/
return -EBUSY;
- if (rdev->saved_raid_disk < 0 && !enough(conf, -1))
+ if (rdev->saved_raid_disk < 0 && !_enough(conf, &conf->prev, -1))
return -EINVAL;
if (rdev->raid_disk >= 0)
@@ -1635,6 +1731,7 @@ static int raid10_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
if (!test_bit(Faulty, &rdev->flags) &&
mddev->recovery_disabled != p->recovery_disabled &&
(!p->replacement || p->replacement == rdev) &&
+ number < conf->geo.raid_disks &&
enough(conf, -1)) {
err = -EBUSY;
goto abort;
@@ -1676,7 +1773,11 @@ static void end_sync_read(struct bio *bio, int error)
struct r10conf *conf = r10_bio->mddev->private;
int d;
- d = find_bio_disk(conf, r10_bio, bio, NULL, NULL);
+ if (bio == r10_bio->master_bio) {
+ /* this is a reshape read */
+ d = r10_bio->read_slot; /* really the read dev */
+ } else
+ d = find_bio_disk(conf, r10_bio, bio, NULL, NULL);
if (test_bit(BIO_UPTODATE, &bio->bi_flags))
set_bit(R10BIO_Uptodate, &r10_bio->state);
@@ -2218,7 +2319,9 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
" (%d sectors at %llu on %s)\n",
mdname(mddev), s,
(unsigned long long)(
- sect + rdev->data_offset),
+ sect +
+ choose_data_offset(r10_bio,
+ rdev)),
bdevname(rdev->bdev, b));
printk(KERN_NOTICE "md/raid10:%s: %s: failing "
"drive\n",
@@ -2256,7 +2359,8 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
" (%d sectors at %llu on %s)\n",
mdname(mddev), s,
(unsigned long long)(
- sect + rdev->data_offset),
+ sect +
+ choose_data_offset(r10_bio, rdev)),
bdevname(rdev->bdev, b));
printk(KERN_NOTICE "md/raid10:%s: %s: failing "
"drive\n",
@@ -2269,7 +2373,8 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
" (%d sectors at %llu on %s)\n",
mdname(mddev), s,
(unsigned long long)(
- sect + rdev->data_offset),
+ sect +
+ choose_data_offset(r10_bio, rdev)),
bdevname(rdev->bdev, b));
atomic_add(s, &rdev->corrected_errors);
}
@@ -2343,7 +2448,7 @@ static int narrow_write_error(struct r10bio *r10_bio, int i)
wbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
md_trim_bio(wbio, sector - bio->bi_sector, sectors);
wbio->bi_sector = (r10_bio->devs[i].addr+
- rdev->data_offset+
+ choose_data_offset(r10_bio, rdev) +
(sector - r10_bio->sector));
wbio->bi_bdev = rdev->bdev;
if (submit_bio_wait(WRITE, wbio) == 0)
@@ -2420,7 +2525,7 @@ read_more:
r10_bio->devs[slot].bio = bio;
r10_bio->devs[slot].rdev = rdev;
bio->bi_sector = r10_bio->devs[slot].addr
- + rdev->data_offset;
+ + choose_data_offset(r10_bio, rdev);
bio->bi_bdev = rdev->bdev;
bio->bi_rw = READ | do_sync;
bio->bi_private = r10_bio;
@@ -2480,7 +2585,7 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
rdev_clear_badblocks(
rdev,
r10_bio->devs[m].addr,
- r10_bio->sectors);
+ r10_bio->sectors, 0);
} else {
if (!rdev_set_badblocks(
rdev,
@@ -2496,7 +2601,7 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
rdev_clear_badblocks(
rdev,
r10_bio->devs[m].addr,
- r10_bio->sectors);
+ r10_bio->sectors, 0);
} else {
if (!rdev_set_badblocks(
rdev,
@@ -2515,7 +2620,7 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
rdev_clear_badblocks(
rdev,
r10_bio->devs[m].addr,
- r10_bio->sectors);
+ r10_bio->sectors, 0);
rdev_dec_pending(rdev, conf->mddev);
} else if (bio != NULL &&
!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
@@ -2532,7 +2637,7 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
rdev_clear_badblocks(
rdev,
r10_bio->devs[m].addr,
- r10_bio->sectors);
+ r10_bio->sectors, 0);
rdev_dec_pending(rdev, conf->mddev);
}
}
@@ -2573,6 +2678,8 @@ static void raid10d(struct mddev *mddev)
if (test_bit(R10BIO_MadeGood, &r10_bio->state) ||
test_bit(R10BIO_WriteError, &r10_bio->state))
handle_write_completed(conf, r10_bio);
+ else if (test_bit(R10BIO_IsReshape, &r10_bio->state))
+ reshape_request_write(mddev, r10_bio);
else if (test_bit(R10BIO_IsSync, &r10_bio->state))
sync_request_write(mddev, r10_bio);
else if (test_bit(R10BIO_IsRecover, &r10_bio->state))
@@ -2603,7 +2710,7 @@ static int init_resync(struct r10conf *conf)
buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
BUG_ON(conf->r10buf_pool);
conf->have_replacement = 0;
- for (i = 0; i < conf->raid_disks; i++)
+ for (i = 0; i < conf->geo.raid_disks; i++)
if (conf->mirrors[i].replacement)
conf->have_replacement = 1;
conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc, r10buf_pool_free, conf);
@@ -2657,6 +2764,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
sector_t sync_blocks;
sector_t sectors_skipped = 0;
int chunks_skipped = 0;
+ sector_t chunk_mask = conf->geo.chunk_mask;
if (!conf->r10buf_pool)
if (init_resync(conf))
@@ -2664,7 +2772,8 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
skipped:
max_sector = mddev->dev_sectors;
- if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+ if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ||
+ test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
max_sector = mddev->resync_max_sectors;
if (sector_nr >= max_sector) {
/* If we aborted, we need to abort the
@@ -2676,11 +2785,16 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
* we need to convert that to several
* virtual addresses.
*/
+ if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) {
+ end_reshape(conf);
+ return 0;
+ }
+
if (mddev->curr_resync < max_sector) { /* aborted */
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
&sync_blocks, 1);
- else for (i=0; i<conf->raid_disks; i++) {
+ else for (i = 0; i < conf->geo.raid_disks; i++) {
sector_t sect =
raid10_find_virt(conf, mddev->curr_resync, i);
bitmap_end_sync(mddev->bitmap, sect,
@@ -2694,7 +2808,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
/* Completed a full sync so the replacements
* are now fully recovered.
*/
- for (i = 0; i < conf->raid_disks; i++)
+ for (i = 0; i < conf->geo.raid_disks; i++)
if (conf->mirrors[i].replacement)
conf->mirrors[i].replacement
->recovery_offset
@@ -2707,7 +2821,11 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
*skipped = 1;
return sectors_skipped;
}
- if (chunks_skipped >= conf->raid_disks) {
+
+ if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
+ return reshape_request(mddev, sector_nr, skipped);
+
+ if (chunks_skipped >= conf->geo.raid_disks) {
/* if there has been nothing to do on any drive,
* then there is nothing to do at all..
*/
@@ -2721,9 +2839,9 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
/* make sure whole request will fit in a chunk - if chunks
* are meaningful
*/
- if (conf->near_copies < conf->raid_disks &&
- max_sector > (sector_nr | conf->chunk_mask))
- max_sector = (sector_nr | conf->chunk_mask) + 1;
+ if (conf->geo.near_copies < conf->geo.raid_disks &&
+ max_sector > (sector_nr | chunk_mask))
+ max_sector = (sector_nr | chunk_mask) + 1;
/*
* If there is non-resync activity waiting for us then
* put in a delay to throttle resync.
@@ -2752,7 +2870,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
int j;
r10_bio = NULL;
- for (i=0 ; i<conf->raid_disks; i++) {
+ for (i = 0 ; i < conf->geo.raid_disks; i++) {
int still_degraded;
struct r10bio *rb2;
sector_t sect;
@@ -2806,7 +2924,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
/* Need to check if the array will still be
* degraded
*/
- for (j=0; j<conf->raid_disks; j++)
+ for (j = 0; j < conf->geo.raid_disks; j++)
if (conf->mirrors[j].rdev == NULL ||
test_bit(Faulty, &conf->mirrors[j].rdev->flags)) {
still_degraded = 1;
@@ -2984,9 +3102,9 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
r10_bio->sector = sector_nr;
set_bit(R10BIO_IsSync, &r10_bio->state);
raid10_find_phys(conf, r10_bio);
- r10_bio->sectors = (sector_nr | conf->chunk_mask) - sector_nr +1;
+ r10_bio->sectors = (sector_nr | chunk_mask) - sector_nr + 1;
- for (i=0; i<conf->copies; i++) {
+ for (i = 0; i < conf->copies; i++) {
int d = r10_bio->devs[i].devnum;
sector_t first_bad, sector;
int bad_sectors;
@@ -3152,40 +3270,107 @@ raid10_size(struct mddev *mddev, sector_t sectors, int raid_disks)
struct r10conf *conf = mddev->private;
if (!raid_disks)
- raid_disks = conf->raid_disks;
+ raid_disks = min(conf->geo.raid_disks,
+ conf->prev.raid_disks);
if (!sectors)
sectors = conf->dev_sectors;
- size = sectors >> conf->chunk_shift;
- sector_div(size, conf->far_copies);
+ size = sectors >> conf->geo.chunk_shift;
+ sector_div(size, conf->geo.far_copies);
size = size * raid_disks;
- sector_div(size, conf->near_copies);
+ sector_div(size, conf->geo.near_copies);
+
+ return size << conf->geo.chunk_shift;
+}
+
+static void calc_sectors(struct r10conf *conf, sector_t size)
+{
+ /* Calculate the number of sectors-per-device that will
+ * actually be used, and set conf->dev_sectors and
+ * conf->stride
+ */
- return size << conf->chunk_shift;
+ size = size >> conf->geo.chunk_shift;
+ sector_div(size, conf->geo.far_copies);
+ size = size * conf->geo.raid_disks;
+ sector_div(size, conf->geo.near_copies);
+ /* 'size' is now the number of chunks in the array */
+ /* calculate "used chunks per device" */
+ size = size * conf->copies;
+
+ /* We need to round up when dividing by raid_disks to
+ * get the stride size.
+ */
+ size = DIV_ROUND_UP_SECTOR_T(size, conf->geo.raid_disks);
+
+ conf->dev_sectors = size << conf->geo.chunk_shift;
+
+ if (conf->geo.far_offset)
+ conf->geo.stride = 1 << conf->geo.chunk_shift;
+ else {
+ sector_div(size, conf->geo.far_copies);
+ conf->geo.stride = size << conf->geo.chunk_shift;
+ }
}
+enum geo_type {geo_new, geo_old, geo_start};
+static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new)
+{
+ int nc, fc, fo;
+ int layout, chunk, disks;
+ switch (new) {
+ case geo_old:
+ layout = mddev->layout;
+ chunk = mddev->chunk_sectors;
+ disks = mddev->raid_disks - mddev->delta_disks;
+ break;
+ case geo_new:
+ layout = mddev->new_layout;
+ chunk = mddev->new_chunk_sectors;
+ disks = mddev->raid_disks;
+ break;
+ default: /* avoid 'may be unused' warnings */
+ case geo_start: /* new when starting reshape - raid_disks not
+ * updated yet. */
+ layout = mddev->new_layout;
+ chunk = mddev->new_chunk_sectors;
+ disks = mddev->raid_disks + mddev->delta_disks;
+ break;
+ }
+ if (layout >> 17)
+ return -1;
+ if (chunk < (PAGE_SIZE >> 9) ||
+ !is_power_of_2(chunk))
+ return -2;
+ nc = layout & 255;
+ fc = (layout >> 8) & 255;
+ fo = layout & (1<<16);
+ geo->raid_disks = disks;
+ geo->near_copies = nc;
+ geo->far_copies = fc;
+ geo->far_offset = fo;
+ geo->chunk_mask = chunk - 1;
+ geo->chunk_shift = ffz(~chunk);
+ return nc*fc;
+}
static struct r10conf *setup_conf(struct mddev *mddev)
{
struct r10conf *conf = NULL;
- int nc, fc, fo;
- sector_t stride, size;
int err = -EINVAL;
+ struct geom geo;
+ int copies;
- if (mddev->new_chunk_sectors < (PAGE_SIZE >> 9) ||
- !is_power_of_2(mddev->new_chunk_sectors)) {
+ copies = setup_geo(&geo, mddev, geo_new);
+
+ if (copies == -2) {
printk(KERN_ERR "md/raid10:%s: chunk size must be "
"at least PAGE_SIZE(%ld) and be a power of 2.\n",
mdname(mddev), PAGE_SIZE);
goto out;
}
- nc = mddev->new_layout & 255;
- fc = (mddev->new_layout >> 8) & 255;
- fo = mddev->new_layout & (1<<16);
-
- if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
- (mddev->new_layout >> 17)) {
+ if (copies < 2 || copies > mddev->raid_disks) {
printk(KERN_ERR "md/raid10:%s: unsupported raid10 layout: 0x%8x\n",
mdname(mddev), mddev->new_layout);
goto out;
@@ -3196,7 +3381,9 @@ static struct r10conf *setup_conf(struct mddev *mddev)
if (!conf)
goto out;
- conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks,
+ /* FIXME calc properly */
+ conf->mirrors = kzalloc(sizeof(struct mirror_info)*(mddev->raid_disks +
+ max(0,mddev->delta_disks)),
GFP_KERNEL);
if (!conf->mirrors)
goto out;
@@ -3205,43 +3392,29 @@ static struct r10conf *setup_conf(struct mddev *mddev)
if (!conf->tmppage)
goto out;
-
- conf->raid_disks = mddev->raid_disks;
- conf->near_copies = nc;
- conf->far_copies = fc;
- conf->copies = nc*fc;
- conf->far_offset = fo;
- conf->chunk_mask = mddev->new_chunk_sectors - 1;
- conf->chunk_shift = ffz(~mddev->new_chunk_sectors);
-
+ conf->geo = geo;
+ conf->copies = copies;
conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc,
r10bio_pool_free, conf);
if (!conf->r10bio_pool)
goto out;
- size = mddev->dev_sectors >> conf->chunk_shift;
- sector_div(size, fc);
- size = size * conf->raid_disks;
- sector_div(size, nc);
- /* 'size' is now the number of chunks in the array */
- /* calculate "used chunks per device" in 'stride' */
- stride = size * conf->copies;
-
- /* We need to round up when dividing by raid_disks to
- * get the stride size.
- */
- stride += conf->raid_disks - 1;
- sector_div(stride, conf->raid_disks);
-
- conf->dev_sectors = stride << conf->chunk_shift;
-
- if (fo)
- stride = 1;
- else
- sector_div(stride, fc);
- conf->stride = stride << conf->chunk_shift;
-
-
+ calc_sectors(conf, mddev->dev_sectors);
+ if (mddev->reshape_position == MaxSector) {
+ conf->prev = conf->geo;
+ conf->reshape_progress = MaxSector;
+ } else {
+ if (setup_geo(&conf->prev, mddev, geo_old) != conf->copies) {
+ err = -EINVAL;
+ goto out;
+ }
+ conf->reshape_progress = mddev->reshape_position;
+ if (conf->prev.far_offset)
+ conf->prev.stride = 1 << conf->prev.chunk_shift;
+ else
+ /* far_copies must be 1 */
+ conf->prev.stride = conf->dev_sectors;
+ }
spin_lock_init(&conf->device_lock);
INIT_LIST_HEAD(&conf->retry_list);
@@ -3256,8 +3429,9 @@ static struct r10conf *setup_conf(struct mddev *mddev)
return conf;
out:
- printk(KERN_ERR "md/raid10:%s: couldn't allocate memory.\n",
- mdname(mddev));
+ if (err == -ENOMEM)
+ printk(KERN_ERR "md/raid10:%s: couldn't allocate memory.\n",
+ mdname(mddev));
if (conf) {
if (conf->r10bio_pool)
mempool_destroy(conf->r10bio_pool);
@@ -3275,12 +3449,8 @@ static int run(struct mddev *mddev)
struct mirror_info *disk;
struct md_rdev *rdev;
sector_t size;
-
- /*
- * copy the already verified devices into our private RAID10
- * bookkeeping area. [whatever we allocate in run(),
- * should be freed in stop()]
- */
+ sector_t min_offset_diff = 0;
+ int first = 1;
if (mddev->private == NULL) {
conf = setup_conf(mddev);
@@ -3297,17 +3467,20 @@ static int run(struct mddev *mddev)
chunk_size = mddev->chunk_sectors << 9;
blk_queue_io_min(mddev->queue, chunk_size);
- if (conf->raid_disks % conf->near_copies)
- blk_queue_io_opt(mddev->queue, chunk_size * conf->raid_disks);
+ if (conf->geo.raid_disks % conf->geo.near_copies)
+ blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks);
else
blk_queue_io_opt(mddev->queue, chunk_size *
- (conf->raid_disks / conf->near_copies));
+ (conf->geo.raid_disks / conf->geo.near_copies));
rdev_for_each(rdev, mddev) {
+ long long diff;
disk_idx = rdev->raid_disk;
- if (disk_idx >= conf->raid_disks
- || disk_idx < 0)
+ if (disk_idx < 0)
+ continue;
+ if (disk_idx >= conf->geo.raid_disks &&
+ disk_idx >= conf->prev.raid_disks)
continue;
disk = conf->mirrors + disk_idx;
@@ -3320,12 +3493,20 @@ static int run(struct mddev *mddev)
goto out_free_conf;
disk->rdev = rdev;
}
+ diff = (rdev->new_data_offset - rdev->data_offset);
+ if (!mddev->reshape_backwards)
+ diff = -diff;
+ if (diff < 0)
+ diff = 0;
+ if (first || diff < min_offset_diff)
+ min_offset_diff = diff;
disk_stack_limits(mddev->gendisk, rdev->bdev,
rdev->data_offset << 9);
disk->head_position = 0;
}
+
/* need to check that every block has at least one working mirror */
if (!enough(conf, -1)) {
printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n",
@@ -3333,8 +3514,21 @@ static int run(struct mddev *mddev)
goto out_free_conf;
}
+ if (conf->reshape_progress != MaxSector) {
+ /* must ensure that shape change is supported */
+ if (conf->geo.far_copies != 1 &&
+ conf->geo.far_offset == 0)
+ goto out_free_conf;
+ if (conf->prev.far_copies != 1 &&
+ conf->geo.far_offset == 0)
+ goto out_free_conf;
+ }
+
mddev->degraded = 0;
- for (i = 0; i < conf->raid_disks; i++) {
+ for (i = 0;
+ i < conf->geo.raid_disks
+ || i < conf->prev.raid_disks;
+ i++) {
disk = conf->mirrors + i;
@@ -3361,8 +3555,8 @@ static int run(struct mddev *mddev)
mdname(mddev));
printk(KERN_INFO
"md/raid10:%s: active with %d out of %d devices\n",
- mdname(mddev), conf->raid_disks - mddev->degraded,
- conf->raid_disks);
+ mdname(mddev), conf->geo.raid_disks - mddev->degraded,
+ conf->geo.raid_disks);
/*
* Ok, everything is just fine now
*/
@@ -3379,11 +3573,11 @@ static int run(struct mddev *mddev)
* maybe...
*/
{
- int stripe = conf->raid_disks *
+ int stripe = conf->geo.raid_disks *
((mddev->chunk_sectors << 9) / PAGE_SIZE);
- stripe /= conf->near_copies;
- if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
- mddev->queue->backing_dev_info.ra_pages = 2* stripe;
+ stripe /= conf->geo.near_copies;
+ if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
+ mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
}
blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec);
@@ -3391,6 +3585,30 @@ static int run(struct mddev *mddev)
if (md_integrity_register(mddev))
goto out_free_conf;
+ if (conf->reshape_progress != MaxSector) {
+ unsigned long before_length, after_length;
+
+ before_length = ((1 << conf->prev.chunk_shift) *
+ conf->prev.far_copies);
+ after_length = ((1 << conf->geo.chunk_shift) *
+ conf->geo.far_copies);
+
+ if (max(before_length, after_length) > min_offset_diff) {
+ /* This cannot work */
+ printk("md/raid10: offset difference not enough to continue reshape\n");
+ goto out_free_conf;
+ }
+ conf->offset_diff = min_offset_diff;
+
+ conf->reshape_safe = conf->reshape_progress;
+ clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+ clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+ set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
+ set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+ mddev->sync_thread = md_register_thread(md_do_sync, mddev,
+ "reshape");
+ }
+
return 0;
out_free_conf:
@@ -3453,14 +3671,23 @@ static int raid10_resize(struct mddev *mddev, sector_t sectors)
struct r10conf *conf = mddev->private;
sector_t oldsize, size;
- if (conf->far_copies > 1 && !conf->far_offset)
+ if (mddev->reshape_position != MaxSector)
+ return -EBUSY;
+
+ if (conf->geo.far_copies > 1 && !conf->geo.far_offset)
return -EINVAL;
oldsize = raid10_size(mddev, 0, 0);
size = raid10_size(mddev, sectors, 0);
- md_set_array_sectors(mddev, size);
- if (mddev->array_sectors > size)
+ if (mddev->external_size &&
+ mddev->array_sectors > size)
return -EINVAL;
+ if (mddev->bitmap) {
+ int ret = bitmap_resize(mddev->bitmap, size, 0, 0);
+ if (ret)
+ return ret;
+ }
+ md_set_array_sectors(mddev, size);
set_capacity(mddev->gendisk, mddev->array_sectors);
revalidate_disk(mddev->gendisk);
if (sectors > mddev->dev_sectors &&
@@ -3468,7 +3695,8 @@ static int raid10_resize(struct mddev *mddev, sector_t sectors)
mddev->recovery_cp = oldsize;
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
}
- mddev->dev_sectors = sectors;
+ calc_sectors(conf, sectors);
+ mddev->dev_sectors = conf->dev_sectors;
mddev->resync_max_sectors = size;
return 0;
}
@@ -3526,6 +3754,758 @@ static void *raid10_takeover(struct mddev *mddev)
return ERR_PTR(-EINVAL);
}
+static int raid10_check_reshape(struct mddev *mddev)
+{
+ /* Called when there is a request to change
+ * - layout (to ->new_layout)
+ * - chunk size (to ->new_chunk_sectors)
+ * - raid_disks (by delta_disks)
+ * or when trying to restart a reshape that was ongoing.
+ *
+ * We need to validate the request and possibly allocate
+ * space if that might be an issue later.
+ *
+ * Currently we reject any reshape of a 'far' mode array,
+ * allow chunk size to change if new is generally acceptable,
+ * allow raid_disks to increase, and allow
+ * a switch between 'near' mode and 'offset' mode.
+ */
+ struct r10conf *conf = mddev->private;
+ struct geom geo;
+
+ if (conf->geo.far_copies != 1 && !conf->geo.far_offset)
+ return -EINVAL;
+
+ if (setup_geo(&geo, mddev, geo_start) != conf->copies)
+ /* mustn't change number of copies */
+ return -EINVAL;
+ if (geo.far_copies > 1 && !geo.far_offset)
+ /* Cannot switch to 'far' mode */
+ return -EINVAL;
+
+ if (mddev->array_sectors & geo.chunk_mask)
+ /* not factor of array size */
+ return -EINVAL;
+
+ if (!enough(conf, -1))
+ return -EINVAL;
+
+ kfree(conf->mirrors_new);
+ conf->mirrors_new = NULL;
+ if (mddev->delta_disks > 0) {
+ /* allocate new 'mirrors' list */
+ conf->mirrors_new = kzalloc(
+ sizeof(struct mirror_info)
+ *(mddev->raid_disks +
+ mddev->delta_disks),
+ GFP_KERNEL);
+ if (!conf->mirrors_new)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/*
+ * Need to check if array has failed when deciding whether to:
+ * - start an array
+ * - remove non-faulty devices
+ * - add a spare
+ * - allow a reshape
+ * This determination is simple when no reshape is happening.
+ * However if there is a reshape, we need to carefully check
+ * both the before and after sections.
+ * This is because some failed devices may only affect one
+ * of the two sections, and some non-in_sync devices may
+ * be insync in the section most affected by failed devices.
+ */
+static int calc_degraded(struct r10conf *conf)
+{
+ int degraded, degraded2;
+ int i;
+
+ rcu_read_lock();
+ degraded = 0;
+ /* 'prev' section first */
+ for (i = 0; i < conf->prev.raid_disks; i++) {
+ struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
+ if (!rdev || test_bit(Faulty, &rdev->flags))
+ degraded++;
+ else if (!test_bit(In_sync, &rdev->flags))
+ /* When we can reduce the number of devices in
+ * an array, this might not contribute to
+ * 'degraded'. It does now.
+ */
+ degraded++;
+ }
+ rcu_read_unlock();
+ if (conf->geo.raid_disks == conf->prev.raid_disks)
+ return degraded;
+ rcu_read_lock();
+ degraded2 = 0;
+ for (i = 0; i < conf->geo.raid_disks; i++) {
+ struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
+ if (!rdev || test_bit(Faulty, &rdev->flags))
+ degraded2++;
+ else if (!test_bit(In_sync, &rdev->flags)) {
+ /* If reshape is increasing the number of devices,
+ * this section has already been recovered, so
+ * it doesn't contribute to degraded.
+ * else it does.
+ */
+ if (conf->geo.raid_disks <= conf->prev.raid_disks)
+ degraded2++;
+ }
+ }
+ rcu_read_unlock();
+ if (degraded2 > degraded)
+ return degraded2;
+ return degraded;
+}
+
+static int raid10_start_reshape(struct mddev *mddev)
+{
+ /* A 'reshape' has been requested. This commits
+ * the various 'new' fields and sets MD_RECOVER_RESHAPE
+ * This also checks if there are enough spares and adds them
+ * to the array.
+ * We currently require enough spares to make the final
+ * array non-degraded. We also require that the difference
+ * between old and new data_offset - on each device - is
+ * enough that we never risk over-writing.
+ */
+
+ unsigned long before_length, after_length;
+ sector_t min_offset_diff = 0;
+ int first = 1;
+ struct geom new;
+ struct r10conf *conf = mddev->private;
+ struct md_rdev *rdev;
+ int spares = 0;
+ int ret;
+
+ if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+ return -EBUSY;
+
+ if (setup_geo(&new, mddev, geo_start) != conf->copies)
+ return -EINVAL;
+
+ before_length = ((1 << conf->prev.chunk_shift) *
+ conf->prev.far_copies);
+ after_length = ((1 << conf->geo.chunk_shift) *
+ conf->geo.far_copies);
+
+ rdev_for_each(rdev, mddev) {
+ if (!test_bit(In_sync, &rdev->flags)
+ && !test_bit(Faulty, &rdev->flags))
+ spares++;
+ if (rdev->raid_disk >= 0) {
+ long long diff = (rdev->new_data_offset
+ - rdev->data_offset);
+ if (!mddev->reshape_backwards)
+ diff = -diff;
+ if (diff < 0)
+ diff = 0;
+ if (first || diff < min_offset_diff)
+ min_offset_diff = diff;
+ }
+ }
+
+ if (max(before_length, after_length) > min_offset_diff)
+ return -EINVAL;
+
+ if (spares < mddev->delta_disks)
+ return -EINVAL;
+
+ conf->offset_diff = min_offset_diff;
+ spin_lock_irq(&conf->device_lock);
+ if (conf->mirrors_new) {
+ memcpy(conf->mirrors_new, conf->mirrors,
+ sizeof(struct mirror_info)*conf->prev.raid_disks);
+ smp_mb();
+ kfree(conf->mirrors_old); /* FIXME and elsewhere */
+ conf->mirrors_old = conf->mirrors;
+ conf->mirrors = conf->mirrors_new;
+ conf->mirrors_new = NULL;
+ }
+ setup_geo(&conf->geo, mddev, geo_start);
+ smp_mb();
+ if (mddev->reshape_backwards) {
+ sector_t size = raid10_size(mddev, 0, 0);
+ if (size < mddev->array_sectors) {
+ spin_unlock_irq(&conf->device_lock);
+ printk(KERN_ERR "md/raid10:%s: array size must be reduce before number of disks\n",
+ mdname(mddev));
+ return -EINVAL;
+ }
+ mddev->resync_max_sectors = size;
+ conf->reshape_progress = size;
+ } else
+ conf->reshape_progress = 0;
+ spin_unlock_irq(&conf->device_lock);
+
+ if (mddev->delta_disks && mddev->bitmap) {
+ ret = bitmap_resize(mddev->bitmap,
+ raid10_size(mddev, 0,
+ conf->geo.raid_disks),
+ 0, 0);
+ if (ret)
+ goto abort;
+ }
+ if (mddev->delta_disks > 0) {
+ rdev_for_each(rdev, mddev)
+ if (rdev->raid_disk < 0 &&
+ !test_bit(Faulty, &rdev->flags)) {
+ if (raid10_add_disk(mddev, rdev) == 0) {
+ if (rdev->raid_disk >=
+ conf->prev.raid_disks)
+ set_bit(In_sync, &rdev->flags);
+ else
+ rdev->recovery_offset = 0;
+
+ if (sysfs_link_rdev(mddev, rdev))
+ /* Failure here is OK */;
+ }
+ } else if (rdev->raid_disk >= conf->prev.raid_disks
+ && !test_bit(Faulty, &rdev->flags)) {
+ /* This is a spare that was manually added */
+ set_bit(In_sync, &rdev->flags);
+ }
+ }
+ /* When a reshape changes the number of devices,
+ * ->degraded is measured against the larger of the
+ * pre and post numbers.
+ */
+ spin_lock_irq(&conf->device_lock);
+ mddev->degraded = calc_degraded(conf);
+ spin_unlock_irq(&conf->device_lock);
+ mddev->raid_disks = conf->geo.raid_disks;
+ mddev->reshape_position = conf->reshape_progress;
+ set_bit(MD_CHANGE_DEVS, &mddev->flags);
+
+ clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+ clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+ set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
+ set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+
+ mddev->sync_thread = md_register_thread(md_do_sync, mddev,
+ "reshape");
+ if (!mddev->sync_thread) {
+ ret = -EAGAIN;
+ goto abort;
+ }
+ conf->reshape_checkpoint = jiffies;
+ md_wakeup_thread(mddev->sync_thread);
+ md_new_event(mddev);
+ return 0;
+
+abort:
+ mddev->recovery = 0;
+ spin_lock_irq(&conf->device_lock);
+ conf->geo = conf->prev;
+ mddev->raid_disks = conf->geo.raid_disks;
+ rdev_for_each(rdev, mddev)
+ rdev->new_data_offset = rdev->data_offset;
+ smp_wmb();
+ conf->reshape_progress = MaxSector;
+ mddev->reshape_position = MaxSector;
+ spin_unlock_irq(&conf->device_lock);
+ return ret;
+}
+
+/* Calculate the last device-address that could contain
+ * any block from the chunk that includes the array-address 's'
+ * and report the next address.
+ * i.e. the address returned will be chunk-aligned and after
+ * any data that is in the chunk containing 's'.
+ */
+static sector_t last_dev_address(sector_t s, struct geom *geo)
+{
+ s = (s | geo->chunk_mask) + 1;
+ s >>= geo->chunk_shift;
+ s *= geo->near_copies;
+ s = DIV_ROUND_UP_SECTOR_T(s, geo->raid_disks);
+ s *= geo->far_copies;
+ s <<= geo->chunk_shift;
+ return s;
+}
+
+/* Calculate the first device-address that could contain
+ * any block from the chunk that includes the array-address 's'.
+ * This too will be the start of a chunk
+ */
+static sector_t first_dev_address(sector_t s, struct geom *geo)
+{
+ s >>= geo->chunk_shift;
+ s *= geo->near_copies;
+ sector_div(s, geo->raid_disks);
+ s *= geo->far_copies;
+ s <<= geo->chunk_shift;
+ return s;
+}
+
+static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr,
+ int *skipped)
+{
+ /* We simply copy at most one chunk (smallest of old and new)
+ * at a time, possibly less if that exceeds RESYNC_PAGES,
+ * or we hit a bad block or something.
+ * This might mean we pause for normal IO in the middle of
+ * a chunk, but that is not a problem was mddev->reshape_position
+ * can record any location.
+ *
+ * If we will want to write to a location that isn't
+ * yet recorded as 'safe' (i.e. in metadata on disk) then
+ * we need to flush all reshape requests and update the metadata.
+ *
+ * When reshaping forwards (e.g. to more devices), we interpret
+ * 'safe' as the earliest block which might not have been copied
+ * down yet. We divide this by previous stripe size and multiply
+ * by previous stripe length to get lowest device offset that we
+ * cannot write to yet.
+ * We interpret 'sector_nr' as an address that we want to write to.
+ * From this we use last_device_address() to find where we might
+ * write to, and first_device_address on the 'safe' position.
+ * If this 'next' write position is after the 'safe' position,
+ * we must update the metadata to increase the 'safe' position.
+ *
+ * When reshaping backwards, we round in the opposite direction
+ * and perform the reverse test: next write position must not be
+ * less than current safe position.
+ *
+ * In all this the minimum difference in data offsets
+ * (conf->offset_diff - always positive) allows a bit of slack,
+ * so next can be after 'safe', but not by more than offset_disk
+ *
+ * We need to prepare all the bios here before we start any IO
+ * to ensure the size we choose is acceptable to all devices.
+ * The means one for each copy for write-out and an extra one for
+ * read-in.
+ * We store the read-in bio in ->master_bio and the others in
+ * ->devs[x].bio and ->devs[x].repl_bio.
+ */
+ struct r10conf *conf = mddev->private;
+ struct r10bio *r10_bio;
+ sector_t next, safe, last;
+ int max_sectors;
+ int nr_sectors;
+ int s;
+ struct md_rdev *rdev;
+ int need_flush = 0;
+ struct bio *blist;
+ struct bio *bio, *read_bio;
+ int sectors_done = 0;
+
+ if (sector_nr == 0) {
+ /* If restarting in the middle, skip the initial sectors */
+ if (mddev->reshape_backwards &&
+ conf->reshape_progress < raid10_size(mddev, 0, 0)) {
+ sector_nr = (raid10_size(mddev, 0, 0)
+ - conf->reshape_progress);
+ } else if (!mddev->reshape_backwards &&
+ conf->reshape_progress > 0)
+ sector_nr = conf->reshape_progress;
+ if (sector_nr) {
+ mddev->curr_resync_completed = sector_nr;
+ sysfs_notify(&mddev->kobj, NULL, "sync_completed");
+ *skipped = 1;
+ return sector_nr;
+ }
+ }
+
+ /* We don't use sector_nr to track where we are up to
+ * as that doesn't work well for ->reshape_backwards.
+ * So just use ->reshape_progress.
+ */
+ if (mddev->reshape_backwards) {
+ /* 'next' is the earliest device address that we might
+ * write to for this chunk in the new layout
+ */
+ next = first_dev_address(conf->reshape_progress - 1,
+ &conf->geo);
+
+ /* 'safe' is the last device address that we might read from
+ * in the old layout after a restart
+ */
+ safe = last_dev_address(conf->reshape_safe - 1,
+ &conf->prev);
+
+ if (next + conf->offset_diff < safe)
+ need_flush = 1;
+
+ last = conf->reshape_progress - 1;
+ sector_nr = last & ~(sector_t)(conf->geo.chunk_mask
+ & conf->prev.chunk_mask);
+ if (sector_nr + RESYNC_BLOCK_SIZE/512 < last)
+ sector_nr = last + 1 - RESYNC_BLOCK_SIZE/512;
+ } else {
+ /* 'next' is after the last device address that we
+ * might write to for this chunk in the new layout
+ */
+ next = last_dev_address(conf->reshape_progress, &conf->geo);
+
+ /* 'safe' is the earliest device address that we might
+ * read from in the old layout after a restart
+ */
+ safe = first_dev_address(conf->reshape_safe, &conf->prev);
+
+ /* Need to update metadata if 'next' might be beyond 'safe'
+ * as that would possibly corrupt data
+ */
+ if (next > safe + conf->offset_diff)
+ need_flush = 1;
+
+ sector_nr = conf->reshape_progress;
+ last = sector_nr | (conf->geo.chunk_mask
+ & conf->prev.chunk_mask);
+
+ if (sector_nr + RESYNC_BLOCK_SIZE/512 <= last)
+ last = sector_nr + RESYNC_BLOCK_SIZE/512 - 1;
+ }
+
+ if (need_flush ||
+ time_after(jiffies, conf->reshape_checkpoint + 10*HZ)) {
+ /* Need to update reshape_position in metadata */
+ wait_barrier(conf);
+ mddev->reshape_position = conf->reshape_progress;
+ if (mddev->reshape_backwards)
+ mddev->curr_resync_completed = raid10_size(mddev, 0, 0)
+ - conf->reshape_progress;
+ else
+ mddev->curr_resync_completed = conf->reshape_progress;
+ conf->reshape_checkpoint = jiffies;
+ set_bit(MD_CHANGE_DEVS, &mddev->flags);
+ md_wakeup_thread(mddev->thread);
+ wait_event(mddev->sb_wait, mddev->flags == 0 ||
+ kthread_should_stop());
+ conf->reshape_safe = mddev->reshape_position;
+ allow_barrier(conf);
+ }
+
+read_more:
+ /* Now schedule reads for blocks from sector_nr to last */
+ r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
+ raise_barrier(conf, sectors_done != 0);
+ atomic_set(&r10_bio->remaining, 0);
+ r10_bio->mddev = mddev;
+ r10_bio->sector = sector_nr;
+ set_bit(R10BIO_IsReshape, &r10_bio->state);
+ r10_bio->sectors = last - sector_nr + 1;
+ rdev = read_balance(conf, r10_bio, &max_sectors);
+ BUG_ON(!test_bit(R10BIO_Previous, &r10_bio->state));
+
+ if (!rdev) {
+ /* Cannot read from here, so need to record bad blocks
+ * on all the target devices.
+ */
+ // FIXME
+ set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+ return sectors_done;
+ }
+
+ read_bio = bio_alloc_mddev(GFP_KERNEL, RESYNC_PAGES, mddev);
+
+ read_bio->bi_bdev = rdev->bdev;
+ read_bio->bi_sector = (r10_bio->devs[r10_bio->read_slot].addr
+ + rdev->data_offset);
+ read_bio->bi_private = r10_bio;
+ read_bio->bi_end_io = end_sync_read;
+ read_bio->bi_rw = READ;
+ read_bio->bi_flags &= ~(BIO_POOL_MASK - 1);
+ read_bio->bi_flags |= 1 << BIO_UPTODATE;
+ read_bio->bi_vcnt = 0;
+ read_bio->bi_idx = 0;
+ read_bio->bi_size = 0;
+ r10_bio->master_bio = read_bio;
+ r10_bio->read_slot = r10_bio->devs[r10_bio->read_slot].devnum;
+
+ /* Now find the locations in the new layout */
+ __raid10_find_phys(&conf->geo, r10_bio);
+
+ blist = read_bio;
+ read_bio->bi_next = NULL;
+
+ for (s = 0; s < conf->copies*2; s++) {
+ struct bio *b;
+ int d = r10_bio->devs[s/2].devnum;
+ struct md_rdev *rdev2;
+ if (s&1) {
+ rdev2 = conf->mirrors[d].replacement;
+ b = r10_bio->devs[s/2].repl_bio;
+ } else {
+ rdev2 = conf->mirrors[d].rdev;
+ b = r10_bio->devs[s/2].bio;
+ }
+ if (!rdev2 || test_bit(Faulty, &rdev2->flags))
+ continue;
+ b->bi_bdev = rdev2->bdev;
+ b->bi_sector = r10_bio->devs[s/2].addr + rdev2->new_data_offset;
+ b->bi_private = r10_bio;
+ b->bi_end_io = end_reshape_write;
+ b->bi_rw = WRITE;
+ b->bi_flags &= ~(BIO_POOL_MASK - 1);
+ b->bi_flags |= 1 << BIO_UPTODATE;
+ b->bi_next = blist;
+ b->bi_vcnt = 0;
+ b->bi_idx = 0;
+ b->bi_size = 0;
+ blist = b;
+ }
+
+ /* Now add as many pages as possible to all of these bios. */
+
+ nr_sectors = 0;
+ for (s = 0 ; s < max_sectors; s += PAGE_SIZE >> 9) {
+ struct page *page = r10_bio->devs[0].bio->bi_io_vec[s/(PAGE_SIZE>>9)].bv_page;
+ int len = (max_sectors - s) << 9;
+ if (len > PAGE_SIZE)
+ len = PAGE_SIZE;
+ for (bio = blist; bio ; bio = bio->bi_next) {
+ struct bio *bio2;
+ if (bio_add_page(bio, page, len, 0))
+ continue;
+
+ /* Didn't fit, must stop */
+ for (bio2 = blist;
+ bio2 && bio2 != bio;
+ bio2 = bio2->bi_next) {
+ /* Remove last page from this bio */
+ bio2->bi_vcnt--;
+ bio2->bi_size -= len;
+ bio2->bi_flags &= ~(1<<BIO_SEG_VALID);
+ }
+ goto bio_full;
+ }
+ sector_nr += len >> 9;
+ nr_sectors += len >> 9;
+ }
+bio_full:
+ r10_bio->sectors = nr_sectors;
+
+ /* Now submit the read */
+ md_sync_acct(read_bio->bi_bdev, r10_bio->sectors);
+ atomic_inc(&r10_bio->remaining);
+ read_bio->bi_next = NULL;
+ generic_make_request(read_bio);
+ sector_nr += nr_sectors;
+ sectors_done += nr_sectors;
+ if (sector_nr <= last)
+ goto read_more;
+
+ /* Now that we have done the whole section we can
+ * update reshape_progress
+ */
+ if (mddev->reshape_backwards)
+ conf->reshape_progress -= sectors_done;
+ else
+ conf->reshape_progress += sectors_done;
+
+ return sectors_done;
+}
+
+static void end_reshape_request(struct r10bio *r10_bio);
+static int handle_reshape_read_error(struct mddev *mddev,
+ struct r10bio *r10_bio);
+static void reshape_request_write(struct mddev *mddev, struct r10bio *r10_bio)
+{
+ /* Reshape read completed. Hopefully we have a block
+ * to write out.
+ * If we got a read error then we do sync 1-page reads from
+ * elsewhere until we find the data - or give up.
+ */
+ struct r10conf *conf = mddev->private;
+ int s;
+
+ if (!test_bit(R10BIO_Uptodate, &r10_bio->state))
+ if (handle_reshape_read_error(mddev, r10_bio) < 0) {
+ /* Reshape has been aborted */
+ md_done_sync(mddev, r10_bio->sectors, 0);
+ return;
+ }
+
+ /* We definitely have the data in the pages, schedule the
+ * writes.
+ */
+ atomic_set(&r10_bio->remaining, 1);
+ for (s = 0; s < conf->copies*2; s++) {
+ struct bio *b;
+ int d = r10_bio->devs[s/2].devnum;
+ struct md_rdev *rdev;
+ if (s&1) {
+ rdev = conf->mirrors[d].replacement;
+ b = r10_bio->devs[s/2].repl_bio;
+ } else {
+ rdev = conf->mirrors[d].rdev;
+ b = r10_bio->devs[s/2].bio;
+ }
+ if (!rdev || test_bit(Faulty, &rdev->flags))
+ continue;
+ atomic_inc(&rdev->nr_pending);
+ md_sync_acct(b->bi_bdev, r10_bio->sectors);
+ atomic_inc(&r10_bio->remaining);
+ b->bi_next = NULL;
+ generic_make_request(b);
+ }
+ end_reshape_request(r10_bio);
+}
+
+static void end_reshape(struct r10conf *conf)
+{
+ if (test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery))
+ return;
+
+ spin_lock_irq(&conf->device_lock);
+ conf->prev = conf->geo;
+ md_finish_reshape(conf->mddev);
+ smp_wmb();
+ conf->reshape_progress = MaxSector;
+ spin_unlock_irq(&conf->device_lock);
+
+ /* read-ahead size must cover two whole stripes, which is
+ * 2 * (datadisks) * chunksize where 'n' is the number of raid devices
+ */
+ if (conf->mddev->queue) {
+ int stripe = conf->geo.raid_disks *
+ ((conf->mddev->chunk_sectors << 9) / PAGE_SIZE);
+ stripe /= conf->geo.near_copies;
+ if (conf->mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
+ conf->mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
+ }
+ conf->fullsync = 0;
+}
+
+
+static int handle_reshape_read_error(struct mddev *mddev,
+ struct r10bio *r10_bio)
+{
+ /* Use sync reads to get the blocks from somewhere else */
+ int sectors = r10_bio->sectors;
+ struct r10bio r10b;
+ struct r10conf *conf = mddev->private;
+ int slot = 0;
+ int idx = 0;
+ struct bio_vec *bvec = r10_bio->master_bio->bi_io_vec;
+
+ r10b.sector = r10_bio->sector;
+ __raid10_find_phys(&conf->prev, &r10b);
+
+ while (sectors) {
+ int s = sectors;
+ int success = 0;
+ int first_slot = slot;
+
+ if (s > (PAGE_SIZE >> 9))
+ s = PAGE_SIZE >> 9;
+
+ while (!success) {
+ int d = r10b.devs[slot].devnum;
+ struct md_rdev *rdev = conf->mirrors[d].rdev;
+ sector_t addr;
+ if (rdev == NULL ||
+ test_bit(Faulty, &rdev->flags) ||
+ !test_bit(In_sync, &rdev->flags))
+ goto failed;
+
+ addr = r10b.devs[slot].addr + idx * PAGE_SIZE;
+ success = sync_page_io(rdev,
+ addr,
+ s << 9,
+ bvec[idx].bv_page,
+ READ, false);
+ if (success)
+ break;
+ failed:
+ slot++;
+ if (slot >= conf->copies)
+ slot = 0;
+ if (slot == first_slot)
+ break;
+ }
+ if (!success) {
+ /* couldn't read this block, must give up */
+ set_bit(MD_RECOVERY_INTR,
+ &mddev->recovery);
+ return -EIO;
+ }
+ sectors -= s;
+ idx++;
+ }
+ return 0;
+}
+
+static void end_reshape_write(struct bio *bio, int error)
+{
+ int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+ struct r10bio *r10_bio = bio->bi_private;
+ struct mddev *mddev = r10_bio->mddev;
+ struct r10conf *conf = mddev->private;
+ int d;
+ int slot;
+ int repl;
+ struct md_rdev *rdev = NULL;
+
+ d = find_bio_disk(conf, r10_bio, bio, &slot, &repl);
+ if (repl)
+ rdev = conf->mirrors[d].replacement;
+ if (!rdev) {
+ smp_mb();
+ rdev = conf->mirrors[d].rdev;
+ }
+
+ if (!uptodate) {
+ /* FIXME should record badblock */
+ md_error(mddev, rdev);
+ }
+
+ rdev_dec_pending(rdev, mddev);
+ end_reshape_request(r10_bio);
+}
+
+static void end_reshape_request(struct r10bio *r10_bio)
+{
+ if (!atomic_dec_and_test(&r10_bio->remaining))
+ return;
+ md_done_sync(r10_bio->mddev, r10_bio->sectors, 1);
+ bio_put(r10_bio->master_bio);
+ put_buf(r10_bio);
+}
+
+static void raid10_finish_reshape(struct mddev *mddev)
+{
+ struct r10conf *conf = mddev->private;
+
+ if (test_bit(MD_RECOVERY_INTR, &mddev->recovery))
+ return;
+
+ if (mddev->delta_disks > 0) {
+ sector_t size = raid10_size(mddev, 0, 0);
+ md_set_array_sectors(mddev, size);
+ if (mddev->recovery_cp > mddev->resync_max_sectors) {
+ mddev->recovery_cp = mddev->resync_max_sectors;
+ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ }
+ mddev->resync_max_sectors = size;
+ set_capacity(mddev->gendisk, mddev->array_sectors);
+ revalidate_disk(mddev->gendisk);
+ } else {
+ int d;
+ for (d = conf->geo.raid_disks ;
+ d < conf->geo.raid_disks - mddev->delta_disks;
+ d++) {
+ struct md_rdev *rdev = conf->mirrors[d].rdev;
+ if (rdev)
+ clear_bit(In_sync, &rdev->flags);
+ rdev = conf->mirrors[d].replacement;
+ if (rdev)
+ clear_bit(In_sync, &rdev->flags);
+ }
+ }
+ mddev->layout = mddev->new_layout;
+ mddev->chunk_sectors = 1 << conf->geo.chunk_shift;
+ mddev->reshape_position = MaxSector;
+ mddev->delta_disks = 0;
+ mddev->reshape_backwards = 0;
+}
+
static struct md_personality raid10_personality =
{
.name = "raid10",
@@ -3544,6 +4524,9 @@ static struct md_personality raid10_personality =
.size = raid10_size,
.resize = raid10_resize,
.takeover = raid10_takeover,
+ .check_reshape = raid10_check_reshape,
+ .start_reshape = raid10_start_reshape,
+ .finish_reshape = raid10_finish_reshape,
};
static int __init raid_init(void)
diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h
index 7c615613c381..135b1b0a1554 100644
--- a/drivers/md/raid10.h
+++ b/drivers/md/raid10.h
@@ -14,32 +14,38 @@ struct mirror_info {
struct r10conf {
struct mddev *mddev;
struct mirror_info *mirrors;
- int raid_disks;
+ struct mirror_info *mirrors_new, *mirrors_old;
spinlock_t device_lock;
/* geometry */
- int near_copies; /* number of copies laid out
+ struct geom {
+ int raid_disks;
+ int near_copies; /* number of copies laid out
* raid0 style */
- int far_copies; /* number of copies laid out
+ int far_copies; /* number of copies laid out
* at large strides across drives
*/
- int far_offset; /* far_copies are offset by 1
+ int far_offset; /* far_copies are offset by 1
* stripe instead of many
*/
- int copies; /* near_copies * far_copies.
- * must be <= raid_disks
- */
- sector_t stride; /* distance between far copies.
+ sector_t stride; /* distance between far copies.
* This is size / far_copies unless
* far_offset, in which case it is
* 1 stripe.
*/
+ int chunk_shift; /* shift from chunks to sectors */
+ sector_t chunk_mask;
+ } prev, geo;
+ int copies; /* near_copies * far_copies.
+ * must be <= raid_disks
+ */
sector_t dev_sectors; /* temp copy of
* mddev->dev_sectors */
-
- int chunk_shift; /* shift from chunks to sectors */
- sector_t chunk_mask;
+ sector_t reshape_progress;
+ sector_t reshape_safe;
+ unsigned long reshape_checkpoint;
+ sector_t offset_diff;
struct list_head retry_list;
/* queue pending writes and submit them on unplug */
@@ -136,6 +142,7 @@ enum r10bio_state {
R10BIO_Uptodate,
R10BIO_IsSync,
R10BIO_IsRecover,
+ R10BIO_IsReshape,
R10BIO_Degraded,
/* Set ReadError on bios that experience a read error
* so that raid10d knows what to do with them.
@@ -146,5 +153,10 @@ enum r10bio_state {
*/
R10BIO_MadeGood,
R10BIO_WriteError,
+/* During a reshape we might be performing IO on the
+ * 'previous' part of the array, in which case this
+ * flag is set
+ */
+ R10BIO_Previous,
};
#endif
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index f351422938e0..d26767246d26 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -488,6 +488,27 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
return sh;
}
+/* Determine if 'data_offset' or 'new_data_offset' should be used
+ * in this stripe_head.
+ */
+static int use_new_offset(struct r5conf *conf, struct stripe_head *sh)
+{
+ sector_t progress = conf->reshape_progress;
+ /* Need a memory barrier to make sure we see the value
+ * of conf->generation, or ->data_offset that was set before
+ * reshape_progress was updated.
+ */
+ smp_rmb();
+ if (progress == MaxSector)
+ return 0;
+ if (sh->generation == conf->generation - 1)
+ return 0;
+ /* We are in a reshape, and this is a new-generation stripe,
+ * so use new_data_offset.
+ */
+ return 1;
+}
+
static void
raid5_end_read_request(struct bio *bi, int error);
static void
@@ -518,6 +539,8 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
replace_only = 1;
} else
continue;
+ if (test_and_clear_bit(R5_SyncIO, &sh->dev[i].flags))
+ rw |= REQ_SYNC;
bi = &sh->dev[i].req;
rbi = &sh->dev[i].rreq; /* For writing to replacement */
@@ -603,7 +626,12 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
__func__, (unsigned long long)sh->sector,
bi->bi_rw, i);
atomic_inc(&sh->count);
- bi->bi_sector = sh->sector + rdev->data_offset;
+ if (use_new_offset(conf, sh))
+ bi->bi_sector = (sh->sector
+ + rdev->new_data_offset);
+ else
+ bi->bi_sector = (sh->sector
+ + rdev->data_offset);
bi->bi_flags = 1 << BIO_UPTODATE;
bi->bi_idx = 0;
bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
@@ -627,7 +655,12 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
__func__, (unsigned long long)sh->sector,
rbi->bi_rw, i);
atomic_inc(&sh->count);
- rbi->bi_sector = sh->sector + rrdev->data_offset;
+ if (use_new_offset(conf, sh))
+ rbi->bi_sector = (sh->sector
+ + rrdev->new_data_offset);
+ else
+ rbi->bi_sector = (sh->sector
+ + rrdev->data_offset);
rbi->bi_flags = 1 << BIO_UPTODATE;
rbi->bi_idx = 0;
rbi->bi_io_vec[0].bv_len = STRIPE_SIZE;
@@ -1114,6 +1147,8 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
dev->sector + STRIPE_SECTORS) {
if (wbi->bi_rw & REQ_FUA)
set_bit(R5_WantFUA, &dev->flags);
+ if (wbi->bi_rw & REQ_SYNC)
+ set_bit(R5_SyncIO, &dev->flags);
tx = async_copy_data(1, wbi, dev->page,
dev->sector, tx);
wbi = r5_next_bio(wbi, dev->sector);
@@ -1131,13 +1166,15 @@ static void ops_complete_reconstruct(void *stripe_head_ref)
int pd_idx = sh->pd_idx;
int qd_idx = sh->qd_idx;
int i;
- bool fua = false;
+ bool fua = false, sync = false;
pr_debug("%s: stripe %llu\n", __func__,
(unsigned long long)sh->sector);
- for (i = disks; i--; )
+ for (i = disks; i--; ) {
fua |= test_bit(R5_WantFUA, &sh->dev[i].flags);
+ sync |= test_bit(R5_SyncIO, &sh->dev[i].flags);
+ }
for (i = disks; i--; ) {
struct r5dev *dev = &sh->dev[i];
@@ -1146,6 +1183,8 @@ static void ops_complete_reconstruct(void *stripe_head_ref)
set_bit(R5_UPTODATE, &dev->flags);
if (fua)
set_bit(R5_WantFUA, &dev->flags);
+ if (sync)
+ set_bit(R5_SyncIO, &dev->flags);
}
}
@@ -1648,7 +1687,7 @@ static void raid5_end_read_request(struct bio * bi, int error)
int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
char b[BDEVNAME_SIZE];
struct md_rdev *rdev = NULL;
-
+ sector_t s;
for (i=0 ; i<disks; i++)
if (bi == &sh->dev[i].req)
@@ -1671,6 +1710,10 @@ static void raid5_end_read_request(struct bio * bi, int error)
if (!rdev)
rdev = conf->disks[i].rdev;
+ if (use_new_offset(conf, sh))
+ s = sh->sector + rdev->new_data_offset;
+ else
+ s = sh->sector + rdev->data_offset;
if (uptodate) {
set_bit(R5_UPTODATE, &sh->dev[i].flags);
if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
@@ -1683,8 +1726,7 @@ static void raid5_end_read_request(struct bio * bi, int error)
"md/raid:%s: read error corrected"
" (%lu sectors at %llu on %s)\n",
mdname(conf->mddev), STRIPE_SECTORS,
- (unsigned long long)(sh->sector
- + rdev->data_offset),
+ (unsigned long long)s,
bdevname(rdev->bdev, b));
atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
clear_bit(R5_ReadError, &sh->dev[i].flags);
@@ -1704,8 +1746,7 @@ static void raid5_end_read_request(struct bio * bi, int error)
"md/raid:%s: read error on replacement device "
"(sector %llu on %s).\n",
mdname(conf->mddev),
- (unsigned long long)(sh->sector
- + rdev->data_offset),
+ (unsigned long long)s,
bdn);
else if (conf->mddev->degraded >= conf->max_degraded)
printk_ratelimited(
@@ -1713,8 +1754,7 @@ static void raid5_end_read_request(struct bio * bi, int error)
"md/raid:%s: read error not correctable "
"(sector %llu on %s).\n",
mdname(conf->mddev),
- (unsigned long long)(sh->sector
- + rdev->data_offset),
+ (unsigned long long)s,
bdn);
else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
/* Oh, no!!! */
@@ -1723,8 +1763,7 @@ static void raid5_end_read_request(struct bio * bi, int error)
"md/raid:%s: read error NOT corrected!! "
"(sector %llu on %s).\n",
mdname(conf->mddev),
- (unsigned long long)(sh->sector
- + rdev->data_offset),
+ (unsigned long long)s,
bdn);
else if (atomic_read(&rdev->read_errors)
> conf->max_nr_stripes)
@@ -3561,7 +3600,7 @@ finish:
if (test_and_clear_bit(R5_MadeGood, &dev->flags)) {
rdev = conf->disks[i].rdev;
rdev_clear_badblocks(rdev, sh->sector,
- STRIPE_SECTORS);
+ STRIPE_SECTORS, 0);
rdev_dec_pending(rdev, conf->mddev);
}
if (test_and_clear_bit(R5_MadeGoodRepl, &dev->flags)) {
@@ -3570,7 +3609,7 @@ finish:
/* rdev have been moved down */
rdev = conf->disks[i].rdev;
rdev_clear_badblocks(rdev, sh->sector,
- STRIPE_SECTORS);
+ STRIPE_SECTORS, 0);
rdev_dec_pending(rdev, conf->mddev);
}
}
@@ -3842,6 +3881,7 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
raid_bio->bi_next = (void*)rdev;
align_bi->bi_bdev = rdev->bdev;
align_bi->bi_flags &= ~(1 << BIO_SEG_VALID);
+ /* No reshape active, so we can trust rdev->data_offset */
align_bi->bi_sector += rdev->data_offset;
if (!bio_fits_rdev(align_bi) ||
@@ -3953,12 +3993,10 @@ static void make_request(struct mddev *mddev, struct bio * bi)
plugged = mddev_check_plugged(mddev);
for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
DEFINE_WAIT(w);
- int disks, data_disks;
int previous;
retry:
previous = 0;
- disks = conf->raid_disks;
prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE);
if (unlikely(conf->reshape_progress != MaxSector)) {
/* spinlock is needed as reshape_progress may be
@@ -3970,13 +4008,12 @@ static void make_request(struct mddev *mddev, struct bio * bi)
* to check again.
*/
spin_lock_irq(&conf->device_lock);
- if (mddev->delta_disks < 0
+ if (mddev->reshape_backwards
? logical_sector < conf->reshape_progress
: logical_sector >= conf->reshape_progress) {
- disks = conf->previous_raid_disks;
previous = 1;
} else {
- if (mddev->delta_disks < 0
+ if (mddev->reshape_backwards
? logical_sector < conf->reshape_safe
: logical_sector >= conf->reshape_safe) {
spin_unlock_irq(&conf->device_lock);
@@ -3986,7 +4023,6 @@ static void make_request(struct mddev *mddev, struct bio * bi)
}
spin_unlock_irq(&conf->device_lock);
}
- data_disks = disks - conf->max_degraded;
new_sector = raid5_compute_sector(conf, logical_sector,
previous,
@@ -4009,7 +4045,7 @@ static void make_request(struct mddev *mddev, struct bio * bi)
*/
int must_retry = 0;
spin_lock_irq(&conf->device_lock);
- if (mddev->delta_disks < 0
+ if (mddev->reshape_backwards
? logical_sector >= conf->reshape_progress
: logical_sector < conf->reshape_progress)
/* mismatch, need to try again */
@@ -4108,11 +4144,11 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
if (sector_nr == 0) {
/* If restarting in the middle, skip the initial sectors */
- if (mddev->delta_disks < 0 &&
+ if (mddev->reshape_backwards &&
conf->reshape_progress < raid5_size(mddev, 0, 0)) {
sector_nr = raid5_size(mddev, 0, 0)
- conf->reshape_progress;
- } else if (mddev->delta_disks >= 0 &&
+ } else if (!mddev->reshape_backwards &&
conf->reshape_progress > 0)
sector_nr = conf->reshape_progress;
sector_div(sector_nr, new_data_disks);
@@ -4133,13 +4169,11 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
else
reshape_sectors = mddev->chunk_sectors;
- /* we update the metadata when there is more than 3Meg
- * in the block range (that is rather arbitrary, should
- * probably be time based) or when the data about to be
- * copied would over-write the source of the data at
- * the front of the range.
- * i.e. one new_stripe along from reshape_progress new_maps
- * to after where reshape_safe old_maps to
+ /* We update the metadata at least every 10 seconds, or when
+ * the data about to be copied would over-write the source of
+ * the data at the front of the range. i.e. one new_stripe
+ * along from reshape_progress new_maps to after where
+ * reshape_safe old_maps to
*/
writepos = conf->reshape_progress;
sector_div(writepos, new_data_disks);
@@ -4147,7 +4181,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
sector_div(readpos, data_disks);
safepos = conf->reshape_safe;
sector_div(safepos, data_disks);
- if (mddev->delta_disks < 0) {
+ if (mddev->reshape_backwards) {
writepos -= min_t(sector_t, reshape_sectors, writepos);
readpos += reshape_sectors;
safepos += reshape_sectors;
@@ -4157,11 +4191,29 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
safepos -= min_t(sector_t, reshape_sectors, safepos);
}
+ /* Having calculated the 'writepos' possibly use it
+ * to set 'stripe_addr' which is where we will write to.
+ */
+ if (mddev->reshape_backwards) {
+ BUG_ON(conf->reshape_progress == 0);
+ stripe_addr = writepos;
+ BUG_ON((mddev->dev_sectors &
+ ~((sector_t)reshape_sectors - 1))
+ - reshape_sectors - stripe_addr
+ != sector_nr);
+ } else {
+ BUG_ON(writepos != sector_nr + reshape_sectors);
+ stripe_addr = sector_nr;
+ }
+
/* 'writepos' is the most advanced device address we might write.
* 'readpos' is the least advanced device address we might read.
* 'safepos' is the least address recorded in the metadata as having
* been reshaped.
- * If 'readpos' is behind 'writepos', then there is no way that we can
+ * If there is a min_offset_diff, these are adjusted either by
+ * increasing the safepos/readpos if diff is negative, or
+ * increasing writepos if diff is positive.
+ * If 'readpos' is then behind 'writepos', there is no way that we can
* ensure safety in the face of a crash - that must be done by userspace
* making a backup of the data. So in that case there is no particular
* rush to update metadata.
@@ -4174,7 +4226,13 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
* Maybe that number should be configurable, but I'm not sure it is
* worth it.... maybe it could be a multiple of safemode_delay???
*/
- if ((mddev->delta_disks < 0
+ if (conf->min_offset_diff < 0) {
+ safepos += -conf->min_offset_diff;
+ readpos += -conf->min_offset_diff;
+ } else
+ writepos += conf->min_offset_diff;
+
+ if ((mddev->reshape_backwards
? (safepos > writepos && readpos < writepos)
: (safepos < writepos && readpos > writepos)) ||
time_after(jiffies, conf->reshape_checkpoint + 10*HZ)) {
@@ -4195,17 +4253,6 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
}
- if (mddev->delta_disks < 0) {
- BUG_ON(conf->reshape_progress == 0);
- stripe_addr = writepos;
- BUG_ON((mddev->dev_sectors &
- ~((sector_t)reshape_sectors - 1))
- - reshape_sectors - stripe_addr
- != sector_nr);
- } else {
- BUG_ON(writepos != sector_nr + reshape_sectors);
- stripe_addr = sector_nr;
- }
INIT_LIST_HEAD(&stripes);
for (i = 0; i < reshape_sectors; i += STRIPE_SECTORS) {
int j;
@@ -4239,7 +4286,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
list_add(&sh->lru, &stripes);
}
spin_lock_irq(&conf->device_lock);
- if (mddev->delta_disks < 0)
+ if (mddev->reshape_backwards)
conf->reshape_progress -= reshape_sectors * new_data_disks;
else
conf->reshape_progress += reshape_sectors * new_data_disks;
@@ -4952,16 +4999,42 @@ static int run(struct mddev *mddev)
struct md_rdev *rdev;
sector_t reshape_offset = 0;
int i;
+ long long min_offset_diff = 0;
+ int first = 1;
if (mddev->recovery_cp != MaxSector)
printk(KERN_NOTICE "md/raid:%s: not clean"
" -- starting background reconstruction\n",
mdname(mddev));
+
+ rdev_for_each(rdev, mddev) {
+ long long diff;
+ if (rdev->raid_disk < 0)
+ continue;
+ diff = (rdev->new_data_offset - rdev->data_offset);
+ if (first) {
+ min_offset_diff = diff;
+ first = 0;
+ } else if (mddev->reshape_backwards &&
+ diff < min_offset_diff)
+ min_offset_diff = diff;
+ else if (!mddev->reshape_backwards &&
+ diff > min_offset_diff)
+ min_offset_diff = diff;
+ }
+
if (mddev->reshape_position != MaxSector) {
/* Check that we can continue the reshape.
- * Currently only disks can change, it must
- * increase, and we must be past the point where
- * a stripe over-writes itself
+ * Difficulties arise if the stripe we would write to
+ * next is at or after the stripe we would read from next.
+ * For a reshape that changes the number of devices, this
+ * is only possible for a very short time, and mdadm makes
+ * sure that time appears to have past before assembling
+ * the array. So we fail if that time hasn't passed.
+ * For a reshape that keeps the number of devices the same
+ * mdadm must be monitoring the reshape can keeping the
+ * critical areas read-only and backed up. It will start
+ * the array in read-only mode, so we check for that.
*/
sector_t here_new, here_old;
int old_disks;
@@ -4993,26 +5066,34 @@ static int run(struct mddev *mddev)
/* here_old is the first stripe that we might need to read
* from */
if (mddev->delta_disks == 0) {
+ if ((here_new * mddev->new_chunk_sectors !=
+ here_old * mddev->chunk_sectors)) {
+ printk(KERN_ERR "md/raid:%s: reshape position is"
+ " confused - aborting\n", mdname(mddev));
+ return -EINVAL;
+ }
/* We cannot be sure it is safe to start an in-place
- * reshape. It is only safe if user-space if monitoring
+ * reshape. It is only safe if user-space is monitoring
* and taking constant backups.
* mdadm always starts a situation like this in
* readonly mode so it can take control before
* allowing any writes. So just check for that.
*/
- if ((here_new * mddev->new_chunk_sectors !=
- here_old * mddev->chunk_sectors) ||
- mddev->ro == 0) {
- printk(KERN_ERR "md/raid:%s: in-place reshape must be started"
- " in read-only mode - aborting\n",
+ if (abs(min_offset_diff) >= mddev->chunk_sectors &&
+ abs(min_offset_diff) >= mddev->new_chunk_sectors)
+ /* not really in-place - so OK */;
+ else if (mddev->ro == 0) {
+ printk(KERN_ERR "md/raid:%s: in-place reshape "
+ "must be started in read-only mode "
+ "- aborting\n",
mdname(mddev));
return -EINVAL;
}
- } else if (mddev->delta_disks < 0
- ? (here_new * mddev->new_chunk_sectors <=
+ } else if (mddev->reshape_backwards
+ ? (here_new * mddev->new_chunk_sectors + min_offset_diff <=
here_old * mddev->chunk_sectors)
: (here_new * mddev->new_chunk_sectors >=
- here_old * mddev->chunk_sectors)) {
+ here_old * mddev->chunk_sectors + (-min_offset_diff))) {
/* Reading from the same stripe as writing to - bad */
printk(KERN_ERR "md/raid:%s: reshape_position too early for "
"auto-recovery - aborting.\n",
@@ -5037,6 +5118,7 @@ static int run(struct mddev *mddev)
if (IS_ERR(conf))
return PTR_ERR(conf);
+ conf->min_offset_diff = min_offset_diff;
mddev->thread = conf->thread;
conf->thread = NULL;
mddev->private = conf;
@@ -5182,9 +5264,12 @@ static int run(struct mddev *mddev)
blk_queue_io_opt(mddev->queue, chunk_size *
(conf->raid_disks - conf->max_degraded));
- rdev_for_each(rdev, mddev)
+ rdev_for_each(rdev, mddev) {
disk_stack_limits(mddev->gendisk, rdev->bdev,
rdev->data_offset << 9);
+ disk_stack_limits(mddev->gendisk, rdev->bdev,
+ rdev->new_data_offset << 9);
+ }
}
return 0;
@@ -5418,12 +5503,18 @@ static int raid5_resize(struct mddev *mddev, sector_t sectors)
* any io in the removed space completes, but it hardly seems
* worth it.
*/
+ sector_t newsize;
sectors &= ~((sector_t)mddev->chunk_sectors - 1);
- md_set_array_sectors(mddev, raid5_size(mddev, sectors,
- mddev->raid_disks));
- if (mddev->array_sectors >
- raid5_size(mddev, sectors, mddev->raid_disks))
+ newsize = raid5_size(mddev, sectors, mddev->raid_disks);
+ if (mddev->external_size &&
+ mddev->array_sectors > newsize)
return -EINVAL;
+ if (mddev->bitmap) {
+ int ret = bitmap_resize(mddev->bitmap, sectors, 0, 0);
+ if (ret)
+ return ret;
+ }
+ md_set_array_sectors(mddev, newsize);
set_capacity(mddev->gendisk, mddev->array_sectors);
revalidate_disk(mddev->gendisk);
if (sectors > mddev->dev_sectors &&
@@ -5468,9 +5559,6 @@ static int check_reshape(struct mddev *mddev)
mddev->new_layout == mddev->layout &&
mddev->new_chunk_sectors == mddev->chunk_sectors)
return 0; /* nothing to do */
- if (mddev->bitmap)
- /* Cannot grow a bitmap yet */
- return -EBUSY;
if (has_failed(conf))
return -EINVAL;
if (mddev->delta_disks < 0) {
@@ -5505,10 +5593,14 @@ static int raid5_start_reshape(struct mddev *mddev)
if (!check_stripe_cache(mddev))
return -ENOSPC;
- rdev_for_each(rdev, mddev)
+ if (has_failed(conf))
+ return -EINVAL;
+
+ rdev_for_each(rdev, mddev) {
if (!test_bit(In_sync, &rdev->flags)
&& !test_bit(Faulty, &rdev->flags))
spares++;
+ }
if (spares - mddev->degraded < mddev->delta_disks - conf->max_degraded)
/* Not enough devices even to make a degraded array
@@ -5535,12 +5627,16 @@ static int raid5_start_reshape(struct mddev *mddev)
conf->chunk_sectors = mddev->new_chunk_sectors;
conf->prev_algo = conf->algorithm;
conf->algorithm = mddev->new_layout;
- if (mddev->delta_disks < 0)
+ conf->generation++;
+ /* Code that selects data_offset needs to see the generation update
+ * if reshape_progress has been set - so a memory barrier needed.
+ */
+ smp_mb();
+ if (mddev->reshape_backwards)
conf->reshape_progress = raid5_size(mddev, 0, 0);
else
conf->reshape_progress = 0;
conf->reshape_safe = conf->reshape_progress;
- conf->generation++;
spin_unlock_irq(&conf->device_lock);
/* Add some new drives, as many as will fit.
@@ -5592,6 +5688,9 @@ static int raid5_start_reshape(struct mddev *mddev)
mddev->recovery = 0;
spin_lock_irq(&conf->device_lock);
mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks;
+ rdev_for_each(rdev, mddev)
+ rdev->new_data_offset = rdev->data_offset;
+ smp_wmb();
conf->reshape_progress = MaxSector;
mddev->reshape_position = MaxSector;
spin_unlock_irq(&conf->device_lock);
@@ -5610,9 +5709,13 @@ static void end_reshape(struct r5conf *conf)
{
if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
+ struct md_rdev *rdev;
spin_lock_irq(&conf->device_lock);
conf->previous_raid_disks = conf->raid_disks;
+ rdev_for_each(rdev, conf->mddev)
+ rdev->data_offset = rdev->new_data_offset;
+ smp_wmb();
conf->reshape_progress = MaxSector;
spin_unlock_irq(&conf->device_lock);
wake_up(&conf->wait_for_overlap);
@@ -5652,17 +5755,18 @@ static void raid5_finish_reshape(struct mddev *mddev)
d < conf->raid_disks - mddev->delta_disks;
d++) {
struct md_rdev *rdev = conf->disks[d].rdev;
- if (rdev &&
- raid5_remove_disk(mddev, rdev) == 0) {
- sysfs_unlink_rdev(mddev, rdev);
- rdev->raid_disk = -1;
- }
+ if (rdev)
+ clear_bit(In_sync, &rdev->flags);
+ rdev = conf->disks[d].replacement;
+ if (rdev)
+ clear_bit(In_sync, &rdev->flags);
}
}
mddev->layout = conf->algorithm;
mddev->chunk_sectors = conf->chunk_sectors;
mddev->reshape_position = MaxSector;
mddev->delta_disks = 0;
+ mddev->reshape_backwards = 0;
}
}
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 8d8e13934a48..2164021f3b5f 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -285,6 +285,7 @@ enum r5dev_flags {
*/
R5_Wantdrain, /* dev->towrite needs to be drained */
R5_WantFUA, /* Write should be FUA */
+ R5_SyncIO, /* The IO is sync */
R5_WriteError, /* got a write error - need to record it */
R5_MadeGood, /* A bad block has been fixed by writing to it */
R5_ReadRepl, /* Will/did read from replacement rather than orig */
@@ -385,6 +386,12 @@ struct r5conf {
short generation; /* increments with every reshape */
unsigned long reshape_checkpoint; /* Time we last updated
* metadata */
+ long long min_offset_diff; /* minimum difference between
+ * data_offset and
+ * new_data_offset across all
+ * devices. May be negative,
+ * but is closest to zero.
+ */
struct list_head handle_list; /* stripes needing handling */
struct list_head hold_list; /* preread ready stripes */
diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c
index e6601b886032..b5797308a39b 100644
--- a/drivers/media/video/gspca/ov534_9.c
+++ b/drivers/media/video/gspca/ov534_9.c
@@ -1376,7 +1376,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
ARRAY_SIZE(ov562x_init_2));
reg_w(gspca_dev, 0xe0, 0x00);
} else {
- err("Unknown sensor %04x", sensor_id);
+ pr_err("Unknown sensor %04x", sensor_id);
return -EINVAL;
}
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c
index 6510110f53d0..304f43ef59eb 100644
--- a/drivers/media/video/hdpvr/hdpvr-core.c
+++ b/drivers/media/video/hdpvr/hdpvr-core.c
@@ -303,7 +303,7 @@ static int hdpvr_probe(struct usb_interface *interface,
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
- err("Out of memory");
+ dev_err(&interface->dev, "Out of memory\n");
goto error;
}
@@ -311,7 +311,7 @@ static int hdpvr_probe(struct usb_interface *interface,
/* register v4l2_device early so it can be used for printks */
if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) {
- err("v4l2_device_register failed");
+ dev_err(&interface->dev, "v4l2_device_register failed\n");
goto error;
}
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
new file mode 100644
index 000000000000..067f31174a0e
--- /dev/null
+++ b/drivers/memory/Kconfig
@@ -0,0 +1,43 @@
+#
+# Memory devices
+#
+
+menuconfig MEMORY
+ bool "Memory Controller drivers"
+
+if MEMORY
+
+config TI_EMIF
+ tristate "Texas Instruments EMIF driver"
+ depends on ARCH_OMAP2PLUS
+ select DDR
+ help
+ This driver is for the EMIF module available in Texas Instruments
+ SoCs. EMIF is an SDRAM controller that, based on its revision,
+ supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols.
+ This driver takes care of only LPDDR2 memories presently. The
+ functions of the driver includes re-configuring AC timing
+ parameters and other settings during frequency, voltage and
+ temperature changes
+
+config TEGRA20_MC
+ bool "Tegra20 Memory Controller(MC) driver"
+ default y
+ depends on ARCH_TEGRA_2x_SOC
+ help
+ This driver is for the Memory Controller(MC) module available
+ in Tegra20 SoCs, mainly for a address translation fault
+ analysis, especially for IOMMU/GART(Graphics Address
+ Relocation Table) module.
+
+config TEGRA30_MC
+ bool "Tegra30 Memory Controller(MC) driver"
+ default y
+ depends on ARCH_TEGRA_3x_SOC
+ help
+ This driver is for the Memory Controller(MC) module available
+ in Tegra30 SoCs, mainly for a address translation fault
+ analysis, especially for IOMMU/SMMU(System Memory Management
+ Unit) module.
+
+endif
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
new file mode 100644
index 000000000000..42b3ce9d80fc
--- /dev/null
+++ b/drivers/memory/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for memory devices
+#
+
+obj-$(CONFIG_TI_EMIF) += emif.o
+obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
+obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o
diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
new file mode 100644
index 000000000000..33a4396b24cb
--- /dev/null
+++ b/drivers/memory/emif.c
@@ -0,0 +1,1670 @@
+/*
+ * EMIF driver
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@ti.com>
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/platform_data/emif_plat.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <memory/jedec_ddr.h>
+#include "emif.h"
+
+/**
+ * struct emif_data - Per device static data for driver's use
+ * @duplicate: Whether the DDR devices attached to this EMIF
+ * instance are exactly same as that on EMIF1. In
+ * this case we can save some memory and processing
+ * @temperature_level: Maximum temperature of LPDDR2 devices attached
+ * to this EMIF - read from MR4 register. If there
+ * are two devices attached to this EMIF, this
+ * value is the maximum of the two temperature
+ * levels.
+ * @node: node in the device list
+ * @base: base address of memory-mapped IO registers.
+ * @dev: device pointer.
+ * @addressing table with addressing information from the spec
+ * @regs_cache: An array of 'struct emif_regs' that stores
+ * calculated register values for different
+ * frequencies, to avoid re-calculating them on
+ * each DVFS transition.
+ * @curr_regs: The set of register values used in the last
+ * frequency change (i.e. corresponding to the
+ * frequency in effect at the moment)
+ * @plat_data: Pointer to saved platform data.
+ * @debugfs_root: dentry to the root folder for EMIF in debugfs
+ */
+struct emif_data {
+ u8 duplicate;
+ u8 temperature_level;
+ u8 lpmode;
+ struct list_head node;
+ unsigned long irq_state;
+ void __iomem *base;
+ struct device *dev;
+ const struct lpddr2_addressing *addressing;
+ struct emif_regs *regs_cache[EMIF_MAX_NUM_FREQUENCIES];
+ struct emif_regs *curr_regs;
+ struct emif_platform_data *plat_data;
+ struct dentry *debugfs_root;
+};
+
+static struct emif_data *emif1;
+static spinlock_t emif_lock;
+static unsigned long irq_state;
+static u32 t_ck; /* DDR clock period in ps */
+static LIST_HEAD(device_list);
+
+static void do_emif_regdump_show(struct seq_file *s, struct emif_data *emif,
+ struct emif_regs *regs)
+{
+ u32 type = emif->plat_data->device_info->type;
+ u32 ip_rev = emif->plat_data->ip_rev;
+
+ seq_printf(s, "EMIF register cache dump for %dMHz\n",
+ regs->freq/1000000);
+
+ seq_printf(s, "ref_ctrl_shdw\t: 0x%08x\n", regs->ref_ctrl_shdw);
+ seq_printf(s, "sdram_tim1_shdw\t: 0x%08x\n", regs->sdram_tim1_shdw);
+ seq_printf(s, "sdram_tim2_shdw\t: 0x%08x\n", regs->sdram_tim2_shdw);
+ seq_printf(s, "sdram_tim3_shdw\t: 0x%08x\n", regs->sdram_tim3_shdw);
+
+ if (ip_rev == EMIF_4D) {
+ seq_printf(s, "read_idle_ctrl_shdw_normal\t: 0x%08x\n",
+ regs->read_idle_ctrl_shdw_normal);
+ seq_printf(s, "read_idle_ctrl_shdw_volt_ramp\t: 0x%08x\n",
+ regs->read_idle_ctrl_shdw_volt_ramp);
+ } else if (ip_rev == EMIF_4D5) {
+ seq_printf(s, "dll_calib_ctrl_shdw_normal\t: 0x%08x\n",
+ regs->dll_calib_ctrl_shdw_normal);
+ seq_printf(s, "dll_calib_ctrl_shdw_volt_ramp\t: 0x%08x\n",
+ regs->dll_calib_ctrl_shdw_volt_ramp);
+ }
+
+ if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) {
+ seq_printf(s, "ref_ctrl_shdw_derated\t: 0x%08x\n",
+ regs->ref_ctrl_shdw_derated);
+ seq_printf(s, "sdram_tim1_shdw_derated\t: 0x%08x\n",
+ regs->sdram_tim1_shdw_derated);
+ seq_printf(s, "sdram_tim3_shdw_derated\t: 0x%08x\n",
+ regs->sdram_tim3_shdw_derated);
+ }
+}
+
+static int emif_regdump_show(struct seq_file *s, void *unused)
+{
+ struct emif_data *emif = s->private;
+ struct emif_regs **regs_cache;
+ int i;
+
+ if (emif->duplicate)
+ regs_cache = emif1->regs_cache;
+ else
+ regs_cache = emif->regs_cache;
+
+ for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) {
+ do_emif_regdump_show(s, emif, regs_cache[i]);
+ seq_printf(s, "\n");
+ }
+
+ return 0;
+}
+
+static int emif_regdump_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, emif_regdump_show, inode->i_private);
+}
+
+static const struct file_operations emif_regdump_fops = {
+ .open = emif_regdump_open,
+ .read = seq_read,
+ .release = single_release,
+};
+
+static int emif_mr4_show(struct seq_file *s, void *unused)
+{
+ struct emif_data *emif = s->private;
+
+ seq_printf(s, "MR4=%d\n", emif->temperature_level);
+ return 0;
+}
+
+static int emif_mr4_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, emif_mr4_show, inode->i_private);
+}
+
+static const struct file_operations emif_mr4_fops = {
+ .open = emif_mr4_open,
+ .read = seq_read,
+ .release = single_release,
+};
+
+static int __init_or_module emif_debugfs_init(struct emif_data *emif)
+{
+ struct dentry *dentry;
+ int ret;
+
+ dentry = debugfs_create_dir(dev_name(emif->dev), NULL);
+ if (IS_ERR(dentry)) {
+ ret = PTR_ERR(dentry);
+ goto err0;
+ }
+ emif->debugfs_root = dentry;
+
+ dentry = debugfs_create_file("regcache_dump", S_IRUGO,
+ emif->debugfs_root, emif, &emif_regdump_fops);
+ if (IS_ERR(dentry)) {
+ ret = PTR_ERR(dentry);
+ goto err1;
+ }
+
+ dentry = debugfs_create_file("mr4", S_IRUGO,
+ emif->debugfs_root, emif, &emif_mr4_fops);
+ if (IS_ERR(dentry)) {
+ ret = PTR_ERR(dentry);
+ goto err1;
+ }
+
+ return 0;
+err1:
+ debugfs_remove_recursive(emif->debugfs_root);
+err0:
+ return ret;
+}
+
+static void __exit emif_debugfs_exit(struct emif_data *emif)
+{
+ debugfs_remove_recursive(emif->debugfs_root);
+ emif->debugfs_root = NULL;
+}
+
+/*
+ * Calculate the period of DDR clock from frequency value
+ */
+static void set_ddr_clk_period(u32 freq)
+{
+ /* Divide 10^12 by frequency to get period in ps */
+ t_ck = (u32)DIV_ROUND_UP_ULL(1000000000000ull, freq);
+}
+
+/*
+ * Get bus width used by EMIF. Note that this may be different from the
+ * bus width of the DDR devices used. For instance two 16-bit DDR devices
+ * may be connected to a given CS of EMIF. In this case bus width as far
+ * as EMIF is concerned is 32, where as the DDR bus width is 16 bits.
+ */
+static u32 get_emif_bus_width(struct emif_data *emif)
+{
+ u32 width;
+ void __iomem *base = emif->base;
+
+ width = (readl(base + EMIF_SDRAM_CONFIG) & NARROW_MODE_MASK)
+ >> NARROW_MODE_SHIFT;
+ width = width == 0 ? 32 : 16;
+
+ return width;
+}
+
+/*
+ * Get the CL from SDRAM_CONFIG register
+ */
+static u32 get_cl(struct emif_data *emif)
+{
+ u32 cl;
+ void __iomem *base = emif->base;
+
+ cl = (readl(base + EMIF_SDRAM_CONFIG) & CL_MASK) >> CL_SHIFT;
+
+ return cl;
+}
+
+static void set_lpmode(struct emif_data *emif, u8 lpmode)
+{
+ u32 temp;
+ void __iomem *base = emif->base;
+
+ temp = readl(base + EMIF_POWER_MANAGEMENT_CONTROL);
+ temp &= ~LP_MODE_MASK;
+ temp |= (lpmode << LP_MODE_SHIFT);
+ writel(temp, base + EMIF_POWER_MANAGEMENT_CONTROL);
+}
+
+static void do_freq_update(void)
+{
+ struct emif_data *emif;
+
+ /*
+ * Workaround for errata i728: Disable LPMODE during FREQ_UPDATE
+ *
+ * i728 DESCRIPTION:
+ * The EMIF automatically puts the SDRAM into self-refresh mode
+ * after the EMIF has not performed accesses during
+ * EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM number of DDR clock cycles
+ * and the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field is set
+ * to 0x2. If during a small window the following three events
+ * occur:
+ * - The SR_TIMING counter expires
+ * - And frequency change is requested
+ * - And OCP access is requested
+ * Then it causes instable clock on the DDR interface.
+ *
+ * WORKAROUND
+ * To avoid the occurrence of the three events, the workaround
+ * is to disable the self-refresh when requesting a frequency
+ * change. Before requesting a frequency change the software must
+ * program EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x0. When the
+ * frequency change has been done, the software can reprogram
+ * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x2
+ */
+ list_for_each_entry(emif, &device_list, node) {
+ if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH)
+ set_lpmode(emif, EMIF_LP_MODE_DISABLE);
+ }
+
+ /*
+ * TODO: Do FREQ_UPDATE here when an API
+ * is available for this as part of the new
+ * clock framework
+ */
+
+ list_for_each_entry(emif, &device_list, node) {
+ if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH)
+ set_lpmode(emif, EMIF_LP_MODE_SELF_REFRESH);
+ }
+}
+
+/* Find addressing table entry based on the device's type and density */
+static const struct lpddr2_addressing *get_addressing_table(
+ const struct ddr_device_info *device_info)
+{
+ u32 index, type, density;
+
+ type = device_info->type;
+ density = device_info->density;
+
+ switch (type) {
+ case DDR_TYPE_LPDDR2_S4:
+ index = density - 1;
+ break;
+ case DDR_TYPE_LPDDR2_S2:
+ switch (density) {
+ case DDR_DENSITY_1Gb:
+ case DDR_DENSITY_2Gb:
+ index = density + 3;
+ break;
+ default:
+ index = density - 1;
+ }
+ break;
+ default:
+ return NULL;
+ }
+
+ return &lpddr2_jedec_addressing_table[index];
+}
+
+/*
+ * Find the the right timing table from the array of timing
+ * tables of the device using DDR clock frequency
+ */
+static const struct lpddr2_timings *get_timings_table(struct emif_data *emif,
+ u32 freq)
+{
+ u32 i, min, max, freq_nearest;
+ const struct lpddr2_timings *timings = NULL;
+ const struct lpddr2_timings *timings_arr = emif->plat_data->timings;
+ struct device *dev = emif->dev;
+
+ /* Start with a very high frequency - 1GHz */
+ freq_nearest = 1000000000;
+
+ /*
+ * Find the timings table such that:
+ * 1. the frequency range covers the required frequency(safe) AND
+ * 2. the max_freq is closest to the required frequency(optimal)
+ */
+ for (i = 0; i < emif->plat_data->timings_arr_size; i++) {
+ max = timings_arr[i].max_freq;
+ min = timings_arr[i].min_freq;
+ if ((freq >= min) && (freq <= max) && (max < freq_nearest)) {
+ freq_nearest = max;
+ timings = &timings_arr[i];
+ }
+ }
+
+ if (!timings)
+ dev_err(dev, "%s: couldn't find timings for - %dHz\n",
+ __func__, freq);
+
+ dev_dbg(dev, "%s: timings table: freq %d, speed bin freq %d\n",
+ __func__, freq, freq_nearest);
+
+ return timings;
+}
+
+static u32 get_sdram_ref_ctrl_shdw(u32 freq,
+ const struct lpddr2_addressing *addressing)
+{
+ u32 ref_ctrl_shdw = 0, val = 0, freq_khz, t_refi;
+
+ /* Scale down frequency and t_refi to avoid overflow */
+ freq_khz = freq / 1000;
+ t_refi = addressing->tREFI_ns / 100;
+
+ /*
+ * refresh rate to be set is 'tREFI(in us) * freq in MHz
+ * division by 10000 to account for change in units
+ */
+ val = t_refi * freq_khz / 10000;
+ ref_ctrl_shdw |= val << REFRESH_RATE_SHIFT;
+
+ return ref_ctrl_shdw;
+}
+
+static u32 get_sdram_tim_1_shdw(const struct lpddr2_timings *timings,
+ const struct lpddr2_min_tck *min_tck,
+ const struct lpddr2_addressing *addressing)
+{
+ u32 tim1 = 0, val = 0;
+
+ val = max(min_tck->tWTR, DIV_ROUND_UP(timings->tWTR, t_ck)) - 1;
+ tim1 |= val << T_WTR_SHIFT;
+
+ if (addressing->num_banks == B8)
+ val = DIV_ROUND_UP(timings->tFAW, t_ck*4);
+ else
+ val = max(min_tck->tRRD, DIV_ROUND_UP(timings->tRRD, t_ck));
+ tim1 |= (val - 1) << T_RRD_SHIFT;
+
+ val = DIV_ROUND_UP(timings->tRAS_min + timings->tRPab, t_ck) - 1;
+ tim1 |= val << T_RC_SHIFT;
+
+ val = max(min_tck->tRASmin, DIV_ROUND_UP(timings->tRAS_min, t_ck));
+ tim1 |= (val - 1) << T_RAS_SHIFT;
+
+ val = max(min_tck->tWR, DIV_ROUND_UP(timings->tWR, t_ck)) - 1;
+ tim1 |= val << T_WR_SHIFT;
+
+ val = max(min_tck->tRCD, DIV_ROUND_UP(timings->tRCD, t_ck)) - 1;
+ tim1 |= val << T_RCD_SHIFT;
+
+ val = max(min_tck->tRPab, DIV_ROUND_UP(timings->tRPab, t_ck)) - 1;
+ tim1 |= val << T_RP_SHIFT;
+
+ return tim1;
+}
+
+static u32 get_sdram_tim_1_shdw_derated(const struct lpddr2_timings *timings,
+ const struct lpddr2_min_tck *min_tck,
+ const struct lpddr2_addressing *addressing)
+{
+ u32 tim1 = 0, val = 0;
+
+ val = max(min_tck->tWTR, DIV_ROUND_UP(timings->tWTR, t_ck)) - 1;
+ tim1 = val << T_WTR_SHIFT;
+
+ /*
+ * tFAW is approximately 4 times tRRD. So add 1875*4 = 7500ps
+ * to tFAW for de-rating
+ */
+ if (addressing->num_banks == B8) {
+ val = DIV_ROUND_UP(timings->tFAW + 7500, 4 * t_ck) - 1;
+ } else {
+ val = DIV_ROUND_UP(timings->tRRD + 1875, t_ck);
+ val = max(min_tck->tRRD, val) - 1;
+ }
+ tim1 |= val << T_RRD_SHIFT;
+
+ val = DIV_ROUND_UP(timings->tRAS_min + timings->tRPab + 1875, t_ck);
+ tim1 |= (val - 1) << T_RC_SHIFT;
+
+ val = DIV_ROUND_UP(timings->tRAS_min + 1875, t_ck);
+ val = max(min_tck->tRASmin, val) - 1;
+ tim1 |= val << T_RAS_SHIFT;
+
+ val = max(min_tck->tWR, DIV_ROUND_UP(timings->tWR, t_ck)) - 1;
+ tim1 |= val << T_WR_SHIFT;
+
+ val = max(min_tck->tRCD, DIV_ROUND_UP(timings->tRCD + 1875, t_ck));
+ tim1 |= (val - 1) << T_RCD_SHIFT;
+
+ val = max(min_tck->tRPab, DIV_ROUND_UP(timings->tRPab + 1875, t_ck));
+ tim1 |= (val - 1) << T_RP_SHIFT;
+
+ return tim1;
+}
+
+static u32 get_sdram_tim_2_shdw(const struct lpddr2_timings *timings,
+ const struct lpddr2_min_tck *min_tck,
+ const struct lpddr2_addressing *addressing,
+ u32 type)
+{
+ u32 tim2 = 0, val = 0;
+
+ val = min_tck->tCKE - 1;
+ tim2 |= val << T_CKE_SHIFT;
+
+ val = max(min_tck->tRTP, DIV_ROUND_UP(timings->tRTP, t_ck)) - 1;
+ tim2 |= val << T_RTP_SHIFT;
+
+ /* tXSNR = tRFCab_ps + 10 ns(tRFCab_ps for LPDDR2). */
+ val = DIV_ROUND_UP(addressing->tRFCab_ps + 10000, t_ck) - 1;
+ tim2 |= val << T_XSNR_SHIFT;
+
+ /* XSRD same as XSNR for LPDDR2 */
+ tim2 |= val << T_XSRD_SHIFT;
+
+ val = max(min_tck->tXP, DIV_ROUND_UP(timings->tXP, t_ck)) - 1;
+ tim2 |= val << T_XP_SHIFT;
+
+ return tim2;
+}
+
+static u32 get_sdram_tim_3_shdw(const struct lpddr2_timings *timings,
+ const struct lpddr2_min_tck *min_tck,
+ const struct lpddr2_addressing *addressing,
+ u32 type, u32 ip_rev, u32 derated)
+{
+ u32 tim3 = 0, val = 0, t_dqsck;
+
+ val = timings->tRAS_max_ns / addressing->tREFI_ns - 1;
+ val = val > 0xF ? 0xF : val;
+ tim3 |= val << T_RAS_MAX_SHIFT;
+
+ val = DIV_ROUND_UP(addressing->tRFCab_ps, t_ck) - 1;
+ tim3 |= val << T_RFC_SHIFT;
+
+ t_dqsck = (derated == EMIF_DERATED_TIMINGS) ?
+ timings->tDQSCK_max_derated : timings->tDQSCK_max;
+ if (ip_rev == EMIF_4D5)
+ val = DIV_ROUND_UP(t_dqsck + 1000, t_ck) - 1;
+ else
+ val = DIV_ROUND_UP(t_dqsck, t_ck) - 1;
+
+ tim3 |= val << T_TDQSCKMAX_SHIFT;
+
+ val = DIV_ROUND_UP(timings->tZQCS, t_ck) - 1;
+ tim3 |= val << ZQ_ZQCS_SHIFT;
+
+ val = DIV_ROUND_UP(timings->tCKESR, t_ck);
+ val = max(min_tck->tCKESR, val) - 1;
+ tim3 |= val << T_CKESR_SHIFT;
+
+ if (ip_rev == EMIF_4D5) {
+ tim3 |= (EMIF_T_CSTA - 1) << T_CSTA_SHIFT;
+
+ val = DIV_ROUND_UP(EMIF_T_PDLL_UL, 128) - 1;
+ tim3 |= val << T_PDLL_UL_SHIFT;
+ }
+
+ return tim3;
+}
+
+static u32 get_zq_config_reg(const struct lpddr2_addressing *addressing,
+ bool cs1_used, bool cal_resistors_per_cs)
+{
+ u32 zq = 0, val = 0;
+
+ val = EMIF_ZQCS_INTERVAL_US * 1000 / addressing->tREFI_ns;
+ zq |= val << ZQ_REFINTERVAL_SHIFT;
+
+ val = DIV_ROUND_UP(T_ZQCL_DEFAULT_NS, T_ZQCS_DEFAULT_NS) - 1;
+ zq |= val << ZQ_ZQCL_MULT_SHIFT;
+
+ val = DIV_ROUND_UP(T_ZQINIT_DEFAULT_NS, T_ZQCL_DEFAULT_NS) - 1;
+ zq |= val << ZQ_ZQINIT_MULT_SHIFT;
+
+ zq |= ZQ_SFEXITEN_ENABLE << ZQ_SFEXITEN_SHIFT;
+
+ if (cal_resistors_per_cs)
+ zq |= ZQ_DUALCALEN_ENABLE << ZQ_DUALCALEN_SHIFT;
+ else
+ zq |= ZQ_DUALCALEN_DISABLE << ZQ_DUALCALEN_SHIFT;
+
+ zq |= ZQ_CS0EN_MASK; /* CS0 is used for sure */
+
+ val = cs1_used ? 1 : 0;
+ zq |= val << ZQ_CS1EN_SHIFT;
+
+ return zq;
+}
+
+static u32 get_temp_alert_config(const struct lpddr2_addressing *addressing,
+ const struct emif_custom_configs *custom_configs, bool cs1_used,
+ u32 sdram_io_width, u32 emif_bus_width)
+{
+ u32 alert = 0, interval, devcnt;
+
+ if (custom_configs && (custom_configs->mask &
+ EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL))
+ interval = custom_configs->temp_alert_poll_interval_ms;
+ else
+ interval = TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS;
+
+ interval *= 1000000; /* Convert to ns */
+ interval /= addressing->tREFI_ns; /* Convert to refresh cycles */
+ alert |= (interval << TA_REFINTERVAL_SHIFT);
+
+ /*
+ * sdram_io_width is in 'log2(x) - 1' form. Convert emif_bus_width
+ * also to this form and subtract to get TA_DEVCNT, which is
+ * in log2(x) form.
+ */
+ emif_bus_width = __fls(emif_bus_width) - 1;
+ devcnt = emif_bus_width - sdram_io_width;
+ alert |= devcnt << TA_DEVCNT_SHIFT;
+
+ /* DEVWDT is in 'log2(x) - 3' form */
+ alert |= (sdram_io_width - 2) << TA_DEVWDT_SHIFT;
+
+ alert |= 1 << TA_SFEXITEN_SHIFT;
+ alert |= 1 << TA_CS0EN_SHIFT;
+ alert |= (cs1_used ? 1 : 0) << TA_CS1EN_SHIFT;
+
+ return alert;
+}
+
+static u32 get_read_idle_ctrl_shdw(u8 volt_ramp)
+{
+ u32 idle = 0, val = 0;
+
+ /*
+ * Maximum value in normal conditions and increased frequency
+ * when voltage is ramping
+ */
+ if (volt_ramp)
+ val = READ_IDLE_INTERVAL_DVFS / t_ck / 64 - 1;
+ else
+ val = 0x1FF;
+
+ /*
+ * READ_IDLE_CTRL register in EMIF4D has same offset and fields
+ * as DLL_CALIB_CTRL in EMIF4D5, so use the same shifts
+ */
+ idle |= val << DLL_CALIB_INTERVAL_SHIFT;
+ idle |= EMIF_READ_IDLE_LEN_VAL << ACK_WAIT_SHIFT;
+
+ return idle;
+}
+
+static u32 get_dll_calib_ctrl_shdw(u8 volt_ramp)
+{
+ u32 calib = 0, val = 0;
+
+ if (volt_ramp == DDR_VOLTAGE_RAMPING)
+ val = DLL_CALIB_INTERVAL_DVFS / t_ck / 16 - 1;
+ else
+ val = 0; /* Disabled when voltage is stable */
+
+ calib |= val << DLL_CALIB_INTERVAL_SHIFT;
+ calib |= DLL_CALIB_ACK_WAIT_VAL << ACK_WAIT_SHIFT;
+
+ return calib;
+}
+
+static u32 get_ddr_phy_ctrl_1_attilaphy_4d(const struct lpddr2_timings *timings,
+ u32 freq, u8 RL)
+{
+ u32 phy = EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY, val = 0;
+
+ val = RL + DIV_ROUND_UP(timings->tDQSCK_max, t_ck) - 1;
+ phy |= val << READ_LATENCY_SHIFT_4D;
+
+ if (freq <= 100000000)
+ val = EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY;
+ else if (freq <= 200000000)
+ val = EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY;
+ else
+ val = EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY;
+
+ phy |= val << DLL_SLAVE_DLY_CTRL_SHIFT_4D;
+
+ return phy;
+}
+
+static u32 get_phy_ctrl_1_intelliphy_4d5(u32 freq, u8 cl)
+{
+ u32 phy = EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY, half_delay;
+
+ /*
+ * DLL operates at 266 MHz. If DDR frequency is near 266 MHz,
+ * half-delay is not needed else set half-delay
+ */
+ if (freq >= 265000000 && freq < 267000000)
+ half_delay = 0;
+ else
+ half_delay = 1;
+
+ phy |= half_delay << DLL_HALF_DELAY_SHIFT_4D5;
+ phy |= ((cl + DIV_ROUND_UP(EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS,
+ t_ck) - 1) << READ_LATENCY_SHIFT_4D5);
+
+ return phy;
+}
+
+static u32 get_ext_phy_ctrl_2_intelliphy_4d5(void)
+{
+ u32 fifo_we_slave_ratio;
+
+ fifo_we_slave_ratio = DIV_ROUND_CLOSEST(
+ EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck);
+
+ return fifo_we_slave_ratio | fifo_we_slave_ratio << 11 |
+ fifo_we_slave_ratio << 22;
+}
+
+static u32 get_ext_phy_ctrl_3_intelliphy_4d5(void)
+{
+ u32 fifo_we_slave_ratio;
+
+ fifo_we_slave_ratio = DIV_ROUND_CLOSEST(
+ EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck);
+
+ return fifo_we_slave_ratio >> 10 | fifo_we_slave_ratio << 1 |
+ fifo_we_slave_ratio << 12 | fifo_we_slave_ratio << 23;
+}
+
+static u32 get_ext_phy_ctrl_4_intelliphy_4d5(void)
+{
+ u32 fifo_we_slave_ratio;
+
+ fifo_we_slave_ratio = DIV_ROUND_CLOSEST(
+ EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck);
+
+ return fifo_we_slave_ratio >> 9 | fifo_we_slave_ratio << 2 |
+ fifo_we_slave_ratio << 13;
+}
+
+static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev)
+{
+ u32 pwr_mgmt_ctrl = 0, timeout;
+ u32 lpmode = EMIF_LP_MODE_SELF_REFRESH;
+ u32 timeout_perf = EMIF_LP_MODE_TIMEOUT_PERFORMANCE;
+ u32 timeout_pwr = EMIF_LP_MODE_TIMEOUT_POWER;
+ u32 freq_threshold = EMIF_LP_MODE_FREQ_THRESHOLD;
+
+ struct emif_custom_configs *cust_cfgs = emif->plat_data->custom_configs;
+
+ if (cust_cfgs && (cust_cfgs->mask & EMIF_CUSTOM_CONFIG_LPMODE)) {
+ lpmode = cust_cfgs->lpmode;
+ timeout_perf = cust_cfgs->lpmode_timeout_performance;
+ timeout_pwr = cust_cfgs->lpmode_timeout_power;
+ freq_threshold = cust_cfgs->lpmode_freq_threshold;
+ }
+
+ /* Timeout based on DDR frequency */
+ timeout = freq >= freq_threshold ? timeout_perf : timeout_pwr;
+
+ /* The value to be set in register is "log2(timeout) - 3" */
+ if (timeout < 16) {
+ timeout = 0;
+ } else {
+ timeout = __fls(timeout) - 3;
+ if (timeout & (timeout - 1))
+ timeout++;
+ }
+
+ switch (lpmode) {
+ case EMIF_LP_MODE_CLOCK_STOP:
+ pwr_mgmt_ctrl = (timeout << CS_TIM_SHIFT) |
+ SR_TIM_MASK | PD_TIM_MASK;
+ break;
+ case EMIF_LP_MODE_SELF_REFRESH:
+ /* Workaround for errata i735 */
+ if (timeout < 6)
+ timeout = 6;
+
+ pwr_mgmt_ctrl = (timeout << SR_TIM_SHIFT) |
+ CS_TIM_MASK | PD_TIM_MASK;
+ break;
+ case EMIF_LP_MODE_PWR_DN:
+ pwr_mgmt_ctrl = (timeout << PD_TIM_SHIFT) |
+ CS_TIM_MASK | SR_TIM_MASK;
+ break;
+ case EMIF_LP_MODE_DISABLE:
+ default:
+ pwr_mgmt_ctrl = CS_TIM_MASK |
+ PD_TIM_MASK | SR_TIM_MASK;
+ }
+
+ /* No CS_TIM in EMIF_4D5 */
+ if (ip_rev == EMIF_4D5)
+ pwr_mgmt_ctrl &= ~CS_TIM_MASK;
+
+ pwr_mgmt_ctrl |= lpmode << LP_MODE_SHIFT;
+
+ return pwr_mgmt_ctrl;
+}
+
+/*
+ * Get the temperature level of the EMIF instance:
+ * Reads the MR4 register of attached SDRAM parts to find out the temperature
+ * level. If there are two parts attached(one on each CS), then the temperature
+ * level for the EMIF instance is the higher of the two temperatures.
+ */
+static void get_temperature_level(struct emif_data *emif)
+{
+ u32 temp, temperature_level;
+ void __iomem *base;
+
+ base = emif->base;
+
+ /* Read mode register 4 */
+ writel(DDR_MR4, base + EMIF_LPDDR2_MODE_REG_CONFIG);
+ temperature_level = readl(base + EMIF_LPDDR2_MODE_REG_DATA);
+ temperature_level = (temperature_level & MR4_SDRAM_REF_RATE_MASK) >>
+ MR4_SDRAM_REF_RATE_SHIFT;
+
+ if (emif->plat_data->device_info->cs1_used) {
+ writel(DDR_MR4 | CS_MASK, base + EMIF_LPDDR2_MODE_REG_CONFIG);
+ temp = readl(base + EMIF_LPDDR2_MODE_REG_DATA);
+ temp = (temp & MR4_SDRAM_REF_RATE_MASK)
+ >> MR4_SDRAM_REF_RATE_SHIFT;
+ temperature_level = max(temp, temperature_level);
+ }
+
+ /* treat everything less than nominal(3) in MR4 as nominal */
+ if (unlikely(temperature_level < SDRAM_TEMP_NOMINAL))
+ temperature_level = SDRAM_TEMP_NOMINAL;
+
+ /* if we get reserved value in MR4 persist with the existing value */
+ if (likely(temperature_level != SDRAM_TEMP_RESERVED_4))
+ emif->temperature_level = temperature_level;
+}
+
+/*
+ * Program EMIF shadow registers that are not dependent on temperature
+ * or voltage
+ */
+static void setup_registers(struct emif_data *emif, struct emif_regs *regs)
+{
+ void __iomem *base = emif->base;
+
+ writel(regs->sdram_tim2_shdw, base + EMIF_SDRAM_TIMING_2_SHDW);
+ writel(regs->phy_ctrl_1_shdw, base + EMIF_DDR_PHY_CTRL_1_SHDW);
+
+ /* Settings specific for EMIF4D5 */
+ if (emif->plat_data->ip_rev != EMIF_4D5)
+ return;
+ writel(regs->ext_phy_ctrl_2_shdw, base + EMIF_EXT_PHY_CTRL_2_SHDW);
+ writel(regs->ext_phy_ctrl_3_shdw, base + EMIF_EXT_PHY_CTRL_3_SHDW);
+ writel(regs->ext_phy_ctrl_4_shdw, base + EMIF_EXT_PHY_CTRL_4_SHDW);
+}
+
+/*
+ * When voltage ramps dll calibration and forced read idle should
+ * happen more often
+ */
+static void setup_volt_sensitive_regs(struct emif_data *emif,
+ struct emif_regs *regs, u32 volt_state)
+{
+ u32 calib_ctrl;
+ void __iomem *base = emif->base;
+
+ /*
+ * EMIF_READ_IDLE_CTRL in EMIF4D refers to the same register as
+ * EMIF_DLL_CALIB_CTRL in EMIF4D5 and dll_calib_ctrl_shadow_*
+ * is an alias of the respective read_idle_ctrl_shdw_* (members of
+ * a union). So, the below code takes care of both cases
+ */
+ if (volt_state == DDR_VOLTAGE_RAMPING)
+ calib_ctrl = regs->dll_calib_ctrl_shdw_volt_ramp;
+ else
+ calib_ctrl = regs->dll_calib_ctrl_shdw_normal;
+
+ writel(calib_ctrl, base + EMIF_DLL_CALIB_CTRL_SHDW);
+}
+
+/*
+ * setup_temperature_sensitive_regs() - set the timings for temperature
+ * sensitive registers. This happens once at initialisation time based
+ * on the temperature at boot time and subsequently based on the temperature
+ * alert interrupt. Temperature alert can happen when the temperature
+ * increases or drops. So this function can have the effect of either
+ * derating the timings or going back to nominal values.
+ */
+static void setup_temperature_sensitive_regs(struct emif_data *emif,
+ struct emif_regs *regs)
+{
+ u32 tim1, tim3, ref_ctrl, type;
+ void __iomem *base = emif->base;
+ u32 temperature;
+
+ type = emif->plat_data->device_info->type;
+
+ tim1 = regs->sdram_tim1_shdw;
+ tim3 = regs->sdram_tim3_shdw;
+ ref_ctrl = regs->ref_ctrl_shdw;
+
+ /* No de-rating for non-lpddr2 devices */
+ if (type != DDR_TYPE_LPDDR2_S2 && type != DDR_TYPE_LPDDR2_S4)
+ goto out;
+
+ temperature = emif->temperature_level;
+ if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH) {
+ ref_ctrl = regs->ref_ctrl_shdw_derated;
+ } else if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS) {
+ tim1 = regs->sdram_tim1_shdw_derated;
+ tim3 = regs->sdram_tim3_shdw_derated;
+ ref_ctrl = regs->ref_ctrl_shdw_derated;
+ }
+
+out:
+ writel(tim1, base + EMIF_SDRAM_TIMING_1_SHDW);
+ writel(tim3, base + EMIF_SDRAM_TIMING_3_SHDW);
+ writel(ref_ctrl, base + EMIF_SDRAM_REFRESH_CTRL_SHDW);
+}
+
+static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif)
+{
+ u32 old_temp_level;
+ irqreturn_t ret = IRQ_HANDLED;
+
+ spin_lock_irqsave(&emif_lock, irq_state);
+ old_temp_level = emif->temperature_level;
+ get_temperature_level(emif);
+
+ if (unlikely(emif->temperature_level == old_temp_level)) {
+ goto out;
+ } else if (!emif->curr_regs) {
+ dev_err(emif->dev, "temperature alert before registers are calculated, not de-rating timings\n");
+ goto out;
+ }
+
+ if (emif->temperature_level < old_temp_level ||
+ emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) {
+ /*
+ * Temperature coming down - defer handling to thread OR
+ * Temperature far too high - do kernel_power_off() from
+ * thread context
+ */
+ ret = IRQ_WAKE_THREAD;
+ } else {
+ /* Temperature is going up - handle immediately */
+ setup_temperature_sensitive_regs(emif, emif->curr_regs);
+ do_freq_update();
+ }
+
+out:
+ spin_unlock_irqrestore(&emif_lock, irq_state);
+ return ret;
+}
+
+static irqreturn_t emif_interrupt_handler(int irq, void *dev_id)
+{
+ u32 interrupts;
+ struct emif_data *emif = dev_id;
+ void __iomem *base = emif->base;
+ struct device *dev = emif->dev;
+ irqreturn_t ret = IRQ_HANDLED;
+
+ /* Save the status and clear it */
+ interrupts = readl(base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS);
+ writel(interrupts, base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS);
+
+ /*
+ * Handle temperature alert
+ * Temperature alert should be same for all ports
+ * So, it's enough to process it only for one of the ports
+ */
+ if (interrupts & TA_SYS_MASK)
+ ret = handle_temp_alert(base, emif);
+
+ if (interrupts & ERR_SYS_MASK)
+ dev_err(dev, "Access error from SYS port - %x\n", interrupts);
+
+ if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) {
+ /* Save the status and clear it */
+ interrupts = readl(base + EMIF_LL_OCP_INTERRUPT_STATUS);
+ writel(interrupts, base + EMIF_LL_OCP_INTERRUPT_STATUS);
+
+ if (interrupts & ERR_LL_MASK)
+ dev_err(dev, "Access error from LL port - %x\n",
+ interrupts);
+ }
+
+ return ret;
+}
+
+static irqreturn_t emif_threaded_isr(int irq, void *dev_id)
+{
+ struct emif_data *emif = dev_id;
+
+ if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) {
+ dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n");
+ kernel_power_off();
+ return IRQ_HANDLED;
+ }
+
+ spin_lock_irqsave(&emif_lock, irq_state);
+
+ if (emif->curr_regs) {
+ setup_temperature_sensitive_regs(emif, emif->curr_regs);
+ do_freq_update();
+ } else {
+ dev_err(emif->dev, "temperature alert before registers are calculated, not de-rating timings\n");
+ }
+
+ spin_unlock_irqrestore(&emif_lock, irq_state);
+
+ return IRQ_HANDLED;
+}
+
+static void clear_all_interrupts(struct emif_data *emif)
+{
+ void __iomem *base = emif->base;
+
+ writel(readl(base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS),
+ base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS);
+ if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE)
+ writel(readl(base + EMIF_LL_OCP_INTERRUPT_STATUS),
+ base + EMIF_LL_OCP_INTERRUPT_STATUS);
+}
+
+static void disable_and_clear_all_interrupts(struct emif_data *emif)
+{
+ void __iomem *base = emif->base;
+
+ /* Disable all interrupts */
+ writel(readl(base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET),
+ base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR);
+ if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE)
+ writel(readl(base + EMIF_LL_OCP_INTERRUPT_ENABLE_SET),
+ base + EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR);
+
+ /* Clear all interrupts */
+ clear_all_interrupts(emif);
+}
+
+static int __init_or_module setup_interrupts(struct emif_data *emif, u32 irq)
+{
+ u32 interrupts, type;
+ void __iomem *base = emif->base;
+
+ type = emif->plat_data->device_info->type;
+
+ clear_all_interrupts(emif);
+
+ /* Enable interrupts for SYS interface */
+ interrupts = EN_ERR_SYS_MASK;
+ if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4)
+ interrupts |= EN_TA_SYS_MASK;
+ writel(interrupts, base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET);
+
+ /* Enable interrupts for LL interface */
+ if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) {
+ /* TA need not be enabled for LL */
+ interrupts = EN_ERR_LL_MASK;
+ writel(interrupts, base + EMIF_LL_OCP_INTERRUPT_ENABLE_SET);
+ }
+
+ /* setup IRQ handlers */
+ return devm_request_threaded_irq(emif->dev, irq,
+ emif_interrupt_handler,
+ emif_threaded_isr,
+ 0, dev_name(emif->dev),
+ emif);
+
+}
+
+static void __init_or_module emif_onetime_settings(struct emif_data *emif)
+{
+ u32 pwr_mgmt_ctrl, zq, temp_alert_cfg;
+ void __iomem *base = emif->base;
+ const struct lpddr2_addressing *addressing;
+ const struct ddr_device_info *device_info;
+
+ device_info = emif->plat_data->device_info;
+ addressing = get_addressing_table(device_info);
+
+ /*
+ * Init power management settings
+ * We don't know the frequency yet. Use a high frequency
+ * value for a conservative timeout setting
+ */
+ pwr_mgmt_ctrl = get_pwr_mgmt_ctrl(1000000000, emif,
+ emif->plat_data->ip_rev);
+ emif->lpmode = (pwr_mgmt_ctrl & LP_MODE_MASK) >> LP_MODE_SHIFT;
+ writel(pwr_mgmt_ctrl, base + EMIF_POWER_MANAGEMENT_CONTROL);
+
+ /* Init ZQ calibration settings */
+ zq = get_zq_config_reg(addressing, device_info->cs1_used,
+ device_info->cal_resistors_per_cs);
+ writel(zq, base + EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG);
+
+ /* Check temperature level temperature level*/
+ get_temperature_level(emif);
+ if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN)
+ dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n");
+
+ /* Init temperature polling */
+ temp_alert_cfg = get_temp_alert_config(addressing,
+ emif->plat_data->custom_configs, device_info->cs1_used,
+ device_info->io_width, get_emif_bus_width(emif));
+ writel(temp_alert_cfg, base + EMIF_TEMPERATURE_ALERT_CONFIG);
+
+ /*
+ * Program external PHY control registers that are not frequency
+ * dependent
+ */
+ if (emif->plat_data->phy_type != EMIF_PHY_TYPE_INTELLIPHY)
+ return;
+ writel(EMIF_EXT_PHY_CTRL_1_VAL, base + EMIF_EXT_PHY_CTRL_1_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_5_VAL, base + EMIF_EXT_PHY_CTRL_5_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_6_VAL, base + EMIF_EXT_PHY_CTRL_6_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_7_VAL, base + EMIF_EXT_PHY_CTRL_7_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_8_VAL, base + EMIF_EXT_PHY_CTRL_8_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_9_VAL, base + EMIF_EXT_PHY_CTRL_9_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_10_VAL, base + EMIF_EXT_PHY_CTRL_10_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_11_VAL, base + EMIF_EXT_PHY_CTRL_11_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_12_VAL, base + EMIF_EXT_PHY_CTRL_12_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_13_VAL, base + EMIF_EXT_PHY_CTRL_13_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_14_VAL, base + EMIF_EXT_PHY_CTRL_14_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_15_VAL, base + EMIF_EXT_PHY_CTRL_15_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_16_VAL, base + EMIF_EXT_PHY_CTRL_16_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_17_VAL, base + EMIF_EXT_PHY_CTRL_17_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_18_VAL, base + EMIF_EXT_PHY_CTRL_18_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_19_VAL, base + EMIF_EXT_PHY_CTRL_19_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_20_VAL, base + EMIF_EXT_PHY_CTRL_20_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_21_VAL, base + EMIF_EXT_PHY_CTRL_21_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_22_VAL, base + EMIF_EXT_PHY_CTRL_22_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_23_VAL, base + EMIF_EXT_PHY_CTRL_23_SHDW);
+ writel(EMIF_EXT_PHY_CTRL_24_VAL, base + EMIF_EXT_PHY_CTRL_24_SHDW);
+}
+
+static void get_default_timings(struct emif_data *emif)
+{
+ struct emif_platform_data *pd = emif->plat_data;
+
+ pd->timings = lpddr2_jedec_timings;
+ pd->timings_arr_size = ARRAY_SIZE(lpddr2_jedec_timings);
+
+ dev_warn(emif->dev, "%s: using default timings\n", __func__);
+}
+
+static int is_dev_data_valid(u32 type, u32 density, u32 io_width, u32 phy_type,
+ u32 ip_rev, struct device *dev)
+{
+ int valid;
+
+ valid = (type == DDR_TYPE_LPDDR2_S4 ||
+ type == DDR_TYPE_LPDDR2_S2)
+ && (density >= DDR_DENSITY_64Mb
+ && density <= DDR_DENSITY_8Gb)
+ && (io_width >= DDR_IO_WIDTH_8
+ && io_width <= DDR_IO_WIDTH_32);
+
+ /* Combinations of EMIF and PHY revisions that we support today */
+ switch (ip_rev) {
+ case EMIF_4D:
+ valid = valid && (phy_type == EMIF_PHY_TYPE_ATTILAPHY);
+ break;
+ case EMIF_4D5:
+ valid = valid && (phy_type == EMIF_PHY_TYPE_INTELLIPHY);
+ break;
+ default:
+ valid = 0;
+ }
+
+ if (!valid)
+ dev_err(dev, "%s: invalid DDR details\n", __func__);
+ return valid;
+}
+
+static int is_custom_config_valid(struct emif_custom_configs *cust_cfgs,
+ struct device *dev)
+{
+ int valid = 1;
+
+ if ((cust_cfgs->mask & EMIF_CUSTOM_CONFIG_LPMODE) &&
+ (cust_cfgs->lpmode != EMIF_LP_MODE_DISABLE))
+ valid = cust_cfgs->lpmode_freq_threshold &&
+ cust_cfgs->lpmode_timeout_performance &&
+ cust_cfgs->lpmode_timeout_power;
+
+ if (cust_cfgs->mask & EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL)
+ valid = valid && cust_cfgs->temp_alert_poll_interval_ms;
+
+ if (!valid)
+ dev_warn(dev, "%s: invalid custom configs\n", __func__);
+
+ return valid;
+}
+
+static struct emif_data *__init_or_module get_device_details(
+ struct platform_device *pdev)
+{
+ u32 size;
+ struct emif_data *emif = NULL;
+ struct ddr_device_info *dev_info;
+ struct emif_custom_configs *cust_cfgs;
+ struct emif_platform_data *pd;
+ struct device *dev;
+ void *temp;
+
+ pd = pdev->dev.platform_data;
+ dev = &pdev->dev;
+
+ if (!(pd && pd->device_info && is_dev_data_valid(pd->device_info->type,
+ pd->device_info->density, pd->device_info->io_width,
+ pd->phy_type, pd->ip_rev, dev))) {
+ dev_err(dev, "%s: invalid device data\n", __func__);
+ goto error;
+ }
+
+ emif = devm_kzalloc(dev, sizeof(*emif), GFP_KERNEL);
+ temp = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+ dev_info = devm_kzalloc(dev, sizeof(*dev_info), GFP_KERNEL);
+
+ if (!emif || !pd || !dev_info) {
+ dev_err(dev, "%s:%d: allocation error\n", __func__, __LINE__);
+ goto error;
+ }
+
+ memcpy(temp, pd, sizeof(*pd));
+ pd = temp;
+ memcpy(dev_info, pd->device_info, sizeof(*dev_info));
+
+ pd->device_info = dev_info;
+ emif->plat_data = pd;
+ emif->dev = dev;
+ emif->temperature_level = SDRAM_TEMP_NOMINAL;
+
+ /*
+ * For EMIF instances other than EMIF1 see if the devices connected
+ * are exactly same as on EMIF1(which is typically the case). If so,
+ * mark it as a duplicate of EMIF1 and skip copying timings data.
+ * This will save some memory and some computation later.
+ */
+ emif->duplicate = emif1 && (memcmp(dev_info,
+ emif1->plat_data->device_info,
+ sizeof(struct ddr_device_info)) == 0);
+
+ if (emif->duplicate) {
+ pd->timings = NULL;
+ pd->min_tck = NULL;
+ goto out;
+ } else if (emif1) {
+ dev_warn(emif->dev, "%s: Non-symmetric DDR geometry\n",
+ __func__);
+ }
+
+ /*
+ * Copy custom configs - ignore allocation error, if any, as
+ * custom_configs is not very critical
+ */
+ cust_cfgs = pd->custom_configs;
+ if (cust_cfgs && is_custom_config_valid(cust_cfgs, dev)) {
+ temp = devm_kzalloc(dev, sizeof(*cust_cfgs), GFP_KERNEL);
+ if (temp)
+ memcpy(temp, cust_cfgs, sizeof(*cust_cfgs));
+ else
+ dev_warn(dev, "%s:%d: allocation error\n", __func__,
+ __LINE__);
+ pd->custom_configs = temp;
+ }
+
+ /*
+ * Copy timings and min-tck values from platform data. If it is not
+ * available or if memory allocation fails, use JEDEC defaults
+ */
+ size = sizeof(struct lpddr2_timings) * pd->timings_arr_size;
+ if (pd->timings) {
+ temp = devm_kzalloc(dev, size, GFP_KERNEL);
+ if (temp) {
+ memcpy(temp, pd->timings, sizeof(*pd->timings));
+ pd->timings = temp;
+ } else {
+ dev_warn(dev, "%s:%d: allocation error\n", __func__,
+ __LINE__);
+ get_default_timings(emif);
+ }
+ } else {
+ get_default_timings(emif);
+ }
+
+ if (pd->min_tck) {
+ temp = devm_kzalloc(dev, sizeof(*pd->min_tck), GFP_KERNEL);
+ if (temp) {
+ memcpy(temp, pd->min_tck, sizeof(*pd->min_tck));
+ pd->min_tck = temp;
+ } else {
+ dev_warn(dev, "%s:%d: allocation error\n", __func__,
+ __LINE__);
+ pd->min_tck = &lpddr2_jedec_min_tck;
+ }
+ } else {
+ pd->min_tck = &lpddr2_jedec_min_tck;
+ }
+
+out:
+ return emif;
+
+error:
+ return NULL;
+}
+
+static int __init_or_module emif_probe(struct platform_device *pdev)
+{
+ struct emif_data *emif;
+ struct resource *res;
+ int irq;
+
+ emif = get_device_details(pdev);
+ if (!emif) {
+ pr_err("%s: error getting device data\n", __func__);
+ goto error;
+ }
+
+ list_add(&emif->node, &device_list);
+ emif->addressing = get_addressing_table(emif->plat_data->device_info);
+
+ /* Save pointers to each other in emif and device structures */
+ emif->dev = &pdev->dev;
+ platform_set_drvdata(pdev, emif);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(emif->dev, "%s: error getting memory resource\n",
+ __func__);
+ goto error;
+ }
+
+ emif->base = devm_request_and_ioremap(emif->dev, res);
+ if (!emif->base) {
+ dev_err(emif->dev, "%s: devm_request_and_ioremap() failed\n",
+ __func__);
+ goto error;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(emif->dev, "%s: error getting IRQ resource - %d\n",
+ __func__, irq);
+ goto error;
+ }
+
+ emif_onetime_settings(emif);
+ emif_debugfs_init(emif);
+ disable_and_clear_all_interrupts(emif);
+ setup_interrupts(emif, irq);
+
+ /* One-time actions taken on probing the first device */
+ if (!emif1) {
+ emif1 = emif;
+ spin_lock_init(&emif_lock);
+
+ /*
+ * TODO: register notifiers for frequency and voltage
+ * change here once the respective frameworks are
+ * available
+ */
+ }
+
+ dev_info(&pdev->dev, "%s: device configured with addr = %p and IRQ%d\n",
+ __func__, emif->base, irq);
+
+ return 0;
+error:
+ return -ENODEV;
+}
+
+static int __exit emif_remove(struct platform_device *pdev)
+{
+ struct emif_data *emif = platform_get_drvdata(pdev);
+
+ emif_debugfs_exit(emif);
+
+ return 0;
+}
+
+static void emif_shutdown(struct platform_device *pdev)
+{
+ struct emif_data *emif = platform_get_drvdata(pdev);
+
+ disable_and_clear_all_interrupts(emif);
+}
+
+static int get_emif_reg_values(struct emif_data *emif, u32 freq,
+ struct emif_regs *regs)
+{
+ u32 cs1_used, ip_rev, phy_type;
+ u32 cl, type;
+ const struct lpddr2_timings *timings;
+ const struct lpddr2_min_tck *min_tck;
+ const struct ddr_device_info *device_info;
+ const struct lpddr2_addressing *addressing;
+ struct emif_data *emif_for_calc;
+ struct device *dev;
+ const struct emif_custom_configs *custom_configs;
+
+ dev = emif->dev;
+ /*
+ * If the devices on this EMIF instance is duplicate of EMIF1,
+ * use EMIF1 details for the calculation
+ */
+ emif_for_calc = emif->duplicate ? emif1 : emif;
+ timings = get_timings_table(emif_for_calc, freq);
+ addressing = emif_for_calc->addressing;
+ if (!timings || !addressing) {
+ dev_err(dev, "%s: not enough data available for %dHz",
+ __func__, freq);
+ return -1;
+ }
+
+ device_info = emif_for_calc->plat_data->device_info;
+ type = device_info->type;
+ cs1_used = device_info->cs1_used;
+ ip_rev = emif_for_calc->plat_data->ip_rev;
+ phy_type = emif_for_calc->plat_data->phy_type;
+
+ min_tck = emif_for_calc->plat_data->min_tck;
+ custom_configs = emif_for_calc->plat_data->custom_configs;
+
+ set_ddr_clk_period(freq);
+
+ regs->ref_ctrl_shdw = get_sdram_ref_ctrl_shdw(freq, addressing);
+ regs->sdram_tim1_shdw = get_sdram_tim_1_shdw(timings, min_tck,
+ addressing);
+ regs->sdram_tim2_shdw = get_sdram_tim_2_shdw(timings, min_tck,
+ addressing, type);
+ regs->sdram_tim3_shdw = get_sdram_tim_3_shdw(timings, min_tck,
+ addressing, type, ip_rev, EMIF_NORMAL_TIMINGS);
+
+ cl = get_cl(emif);
+
+ if (phy_type == EMIF_PHY_TYPE_ATTILAPHY && ip_rev == EMIF_4D) {
+ regs->phy_ctrl_1_shdw = get_ddr_phy_ctrl_1_attilaphy_4d(
+ timings, freq, cl);
+ } else if (phy_type == EMIF_PHY_TYPE_INTELLIPHY && ip_rev == EMIF_4D5) {
+ regs->phy_ctrl_1_shdw = get_phy_ctrl_1_intelliphy_4d5(freq, cl);
+ regs->ext_phy_ctrl_2_shdw = get_ext_phy_ctrl_2_intelliphy_4d5();
+ regs->ext_phy_ctrl_3_shdw = get_ext_phy_ctrl_3_intelliphy_4d5();
+ regs->ext_phy_ctrl_4_shdw = get_ext_phy_ctrl_4_intelliphy_4d5();
+ } else {
+ return -1;
+ }
+
+ /* Only timeout values in pwr_mgmt_ctrl_shdw register */
+ regs->pwr_mgmt_ctrl_shdw =
+ get_pwr_mgmt_ctrl(freq, emif_for_calc, ip_rev) &
+ (CS_TIM_MASK | SR_TIM_MASK | PD_TIM_MASK);
+
+ if (ip_rev & EMIF_4D) {
+ regs->read_idle_ctrl_shdw_normal =
+ get_read_idle_ctrl_shdw(DDR_VOLTAGE_STABLE);
+
+ regs->read_idle_ctrl_shdw_volt_ramp =
+ get_read_idle_ctrl_shdw(DDR_VOLTAGE_RAMPING);
+ } else if (ip_rev & EMIF_4D5) {
+ regs->dll_calib_ctrl_shdw_normal =
+ get_dll_calib_ctrl_shdw(DDR_VOLTAGE_STABLE);
+
+ regs->dll_calib_ctrl_shdw_volt_ramp =
+ get_dll_calib_ctrl_shdw(DDR_VOLTAGE_RAMPING);
+ }
+
+ if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) {
+ regs->ref_ctrl_shdw_derated = get_sdram_ref_ctrl_shdw(freq / 4,
+ addressing);
+
+ regs->sdram_tim1_shdw_derated =
+ get_sdram_tim_1_shdw_derated(timings, min_tck,
+ addressing);
+
+ regs->sdram_tim3_shdw_derated = get_sdram_tim_3_shdw(timings,
+ min_tck, addressing, type, ip_rev,
+ EMIF_DERATED_TIMINGS);
+ }
+
+ regs->freq = freq;
+
+ return 0;
+}
+
+/*
+ * get_regs() - gets the cached emif_regs structure for a given EMIF instance
+ * given frequency(freq):
+ *
+ * As an optimisation, every EMIF instance other than EMIF1 shares the
+ * register cache with EMIF1 if the devices connected on this instance
+ * are same as that on EMIF1(indicated by the duplicate flag)
+ *
+ * If we do not have an entry corresponding to the frequency given, we
+ * allocate a new entry and calculate the values
+ *
+ * Upon finding the right reg dump, save it in curr_regs. It can be
+ * directly used for thermal de-rating and voltage ramping changes.
+ */
+static struct emif_regs *get_regs(struct emif_data *emif, u32 freq)
+{
+ int i;
+ struct emif_regs **regs_cache;
+ struct emif_regs *regs = NULL;
+ struct device *dev;
+
+ dev = emif->dev;
+ if (emif->curr_regs && emif->curr_regs->freq == freq) {
+ dev_dbg(dev, "%s: using curr_regs - %u Hz", __func__, freq);
+ return emif->curr_regs;
+ }
+
+ if (emif->duplicate)
+ regs_cache = emif1->regs_cache;
+ else
+ regs_cache = emif->regs_cache;
+
+ for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) {
+ if (regs_cache[i]->freq == freq) {
+ regs = regs_cache[i];
+ dev_dbg(dev,
+ "%s: reg dump found in reg cache for %u Hz\n",
+ __func__, freq);
+ break;
+ }
+ }
+
+ /*
+ * If we don't have an entry for this frequency in the cache create one
+ * and calculate the values
+ */
+ if (!regs) {
+ regs = devm_kzalloc(emif->dev, sizeof(*regs), GFP_ATOMIC);
+ if (!regs)
+ return NULL;
+
+ if (get_emif_reg_values(emif, freq, regs)) {
+ devm_kfree(emif->dev, regs);
+ return NULL;
+ }
+
+ /*
+ * Now look for an un-used entry in the cache and save the
+ * newly created struct. If there are no free entries
+ * over-write the last entry
+ */
+ for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++)
+ ;
+
+ if (i >= EMIF_MAX_NUM_FREQUENCIES) {
+ dev_warn(dev, "%s: regs_cache full - reusing a slot!!\n",
+ __func__);
+ i = EMIF_MAX_NUM_FREQUENCIES - 1;
+ devm_kfree(emif->dev, regs_cache[i]);
+ }
+ regs_cache[i] = regs;
+ }
+
+ return regs;
+}
+
+static void do_volt_notify_handling(struct emif_data *emif, u32 volt_state)
+{
+ dev_dbg(emif->dev, "%s: voltage notification : %d", __func__,
+ volt_state);
+
+ if (!emif->curr_regs) {
+ dev_err(emif->dev,
+ "%s: volt-notify before registers are ready: %d\n",
+ __func__, volt_state);
+ return;
+ }
+
+ setup_volt_sensitive_regs(emif, emif->curr_regs, volt_state);
+}
+
+/*
+ * TODO: voltage notify handling should be hooked up to
+ * regulator framework as soon as the necessary support
+ * is available in mainline kernel. This function is un-used
+ * right now.
+ */
+static void __attribute__((unused)) volt_notify_handling(u32 volt_state)
+{
+ struct emif_data *emif;
+
+ spin_lock_irqsave(&emif_lock, irq_state);
+
+ list_for_each_entry(emif, &device_list, node)
+ do_volt_notify_handling(emif, volt_state);
+ do_freq_update();
+
+ spin_unlock_irqrestore(&emif_lock, irq_state);
+}
+
+static void do_freq_pre_notify_handling(struct emif_data *emif, u32 new_freq)
+{
+ struct emif_regs *regs;
+
+ regs = get_regs(emif, new_freq);
+ if (!regs)
+ return;
+
+ emif->curr_regs = regs;
+
+ /*
+ * Update the shadow registers:
+ * Temperature and voltage-ramp sensitive settings are also configured
+ * in terms of DDR cycles. So, we need to update them too when there
+ * is a freq change
+ */
+ dev_dbg(emif->dev, "%s: setting up shadow registers for %uHz",
+ __func__, new_freq);
+ setup_registers(emif, regs);
+ setup_temperature_sensitive_regs(emif, regs);
+ setup_volt_sensitive_regs(emif, regs, DDR_VOLTAGE_STABLE);
+
+ /*
+ * Part of workaround for errata i728. See do_freq_update()
+ * for more details
+ */
+ if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH)
+ set_lpmode(emif, EMIF_LP_MODE_DISABLE);
+}
+
+/*
+ * TODO: frequency notify handling should be hooked up to
+ * clock framework as soon as the necessary support is
+ * available in mainline kernel. This function is un-used
+ * right now.
+ */
+static void __attribute__((unused)) freq_pre_notify_handling(u32 new_freq)
+{
+ struct emif_data *emif;
+
+ /*
+ * NOTE: we are taking the spin-lock here and releases it
+ * only in post-notifier. This doesn't look good and
+ * Sparse complains about it, but this seems to be
+ * un-avoidable. We need to lock a sequence of events
+ * that is split between EMIF and clock framework.
+ *
+ * 1. EMIF driver updates EMIF timings in shadow registers in the
+ * frequency pre-notify callback from clock framework
+ * 2. clock framework sets up the registers for the new frequency
+ * 3. clock framework initiates a hw-sequence that updates
+ * the frequency EMIF timings synchronously.
+ *
+ * All these 3 steps should be performed as an atomic operation
+ * vis-a-vis similar sequence in the EMIF interrupt handler
+ * for temperature events. Otherwise, there could be race
+ * conditions that could result in incorrect EMIF timings for
+ * a given frequency
+ */
+ spin_lock_irqsave(&emif_lock, irq_state);
+
+ list_for_each_entry(emif, &device_list, node)
+ do_freq_pre_notify_handling(emif, new_freq);
+}
+
+static void do_freq_post_notify_handling(struct emif_data *emif)
+{
+ /*
+ * Part of workaround for errata i728. See do_freq_update()
+ * for more details
+ */
+ if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH)
+ set_lpmode(emif, EMIF_LP_MODE_SELF_REFRESH);
+}
+
+/*
+ * TODO: frequency notify handling should be hooked up to
+ * clock framework as soon as the necessary support is
+ * available in mainline kernel. This function is un-used
+ * right now.
+ */
+static void __attribute__((unused)) freq_post_notify_handling(void)
+{
+ struct emif_data *emif;
+
+ list_for_each_entry(emif, &device_list, node)
+ do_freq_post_notify_handling(emif);
+
+ /*
+ * Lock is done in pre-notify handler. See freq_pre_notify_handling()
+ * for more details
+ */
+ spin_unlock_irqrestore(&emif_lock, irq_state);
+}
+
+static struct platform_driver emif_driver = {
+ .remove = __exit_p(emif_remove),
+ .shutdown = emif_shutdown,
+ .driver = {
+ .name = "emif",
+ },
+};
+
+static int __init_or_module emif_register(void)
+{
+ return platform_driver_probe(&emif_driver, emif_probe);
+}
+
+static void __exit emif_unregister(void)
+{
+ platform_driver_unregister(&emif_driver);
+}
+
+module_init(emif_register);
+module_exit(emif_unregister);
+MODULE_DESCRIPTION("TI EMIF SDRAM Controller Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:emif");
+MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h
new file mode 100644
index 000000000000..bfe08bae961a
--- /dev/null
+++ b/drivers/memory/emif.h
@@ -0,0 +1,589 @@
+/*
+ * Defines for the EMIF driver
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __EMIF_H
+#define __EMIF_H
+
+/*
+ * Maximum number of different frequencies supported by EMIF driver
+ * Determines the number of entries in the pointer array for register
+ * cache
+ */
+#define EMIF_MAX_NUM_FREQUENCIES 6
+
+/* State of the core voltage */
+#define DDR_VOLTAGE_STABLE 0
+#define DDR_VOLTAGE_RAMPING 1
+
+/* Defines for timing De-rating */
+#define EMIF_NORMAL_TIMINGS 0
+#define EMIF_DERATED_TIMINGS 1
+
+/* Length of the forced read idle period in terms of cycles */
+#define EMIF_READ_IDLE_LEN_VAL 5
+
+/*
+ * forced read idle interval to be used when voltage
+ * is changed as part of DVFS/DPS - 1ms
+ */
+#define READ_IDLE_INTERVAL_DVFS (1*1000000)
+
+/*
+ * Forced read idle interval to be used when voltage is stable
+ * 50us - or maximum value will do
+ */
+#define READ_IDLE_INTERVAL_NORMAL (50*1000000)
+
+/* DLL calibration interval when voltage is NOT stable - 1us */
+#define DLL_CALIB_INTERVAL_DVFS (1*1000000)
+
+#define DLL_CALIB_ACK_WAIT_VAL 5
+
+/* Interval between ZQCS commands - hw team recommended value */
+#define EMIF_ZQCS_INTERVAL_US (50*1000)
+/* Enable ZQ Calibration on exiting Self-refresh */
+#define ZQ_SFEXITEN_ENABLE 1
+/*
+ * ZQ Calibration simultaneously on both chip-selects:
+ * Needs one calibration resistor per CS
+ */
+#define ZQ_DUALCALEN_DISABLE 0
+#define ZQ_DUALCALEN_ENABLE 1
+
+#define T_ZQCS_DEFAULT_NS 90
+#define T_ZQCL_DEFAULT_NS 360
+#define T_ZQINIT_DEFAULT_NS 1000
+
+/* DPD_EN */
+#define DPD_DISABLE 0
+#define DPD_ENABLE 1
+
+/*
+ * Default values for the low-power entry to be used if not provided by user.
+ * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512
+ * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz
+ */
+#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE 2048
+#define EMIF_LP_MODE_TIMEOUT_POWER 512
+#define EMIF_LP_MODE_FREQ_THRESHOLD 400000000
+
+/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */
+#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY 0x049FF000
+#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY 0x41
+#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY 0x80
+#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
+
+/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
+#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY 0x0E084200
+#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS 10000
+
+/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
+#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS 360
+
+#define EMIF_T_CSTA 3
+#define EMIF_T_PDLL_UL 128
+
+/* External PHY control registers magic values */
+#define EMIF_EXT_PHY_CTRL_1_VAL 0x04020080
+#define EMIF_EXT_PHY_CTRL_5_VAL 0x04010040
+#define EMIF_EXT_PHY_CTRL_6_VAL 0x01004010
+#define EMIF_EXT_PHY_CTRL_7_VAL 0x00001004
+#define EMIF_EXT_PHY_CTRL_8_VAL 0x04010040
+#define EMIF_EXT_PHY_CTRL_9_VAL 0x01004010
+#define EMIF_EXT_PHY_CTRL_10_VAL 0x00001004
+#define EMIF_EXT_PHY_CTRL_11_VAL 0x00000000
+#define EMIF_EXT_PHY_CTRL_12_VAL 0x00000000
+#define EMIF_EXT_PHY_CTRL_13_VAL 0x00000000
+#define EMIF_EXT_PHY_CTRL_14_VAL 0x80080080
+#define EMIF_EXT_PHY_CTRL_15_VAL 0x00800800
+#define EMIF_EXT_PHY_CTRL_16_VAL 0x08102040
+#define EMIF_EXT_PHY_CTRL_17_VAL 0x00000001
+#define EMIF_EXT_PHY_CTRL_18_VAL 0x540A8150
+#define EMIF_EXT_PHY_CTRL_19_VAL 0xA81502A0
+#define EMIF_EXT_PHY_CTRL_20_VAL 0x002A0540
+#define EMIF_EXT_PHY_CTRL_21_VAL 0x00000000
+#define EMIF_EXT_PHY_CTRL_22_VAL 0x00000000
+#define EMIF_EXT_PHY_CTRL_23_VAL 0x00000000
+#define EMIF_EXT_PHY_CTRL_24_VAL 0x00000077
+
+#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS 1200
+
+/* Registers offset */
+#define EMIF_MODULE_ID_AND_REVISION 0x0000
+#define EMIF_STATUS 0x0004
+#define EMIF_SDRAM_CONFIG 0x0008
+#define EMIF_SDRAM_CONFIG_2 0x000c
+#define EMIF_SDRAM_REFRESH_CONTROL 0x0010
+#define EMIF_SDRAM_REFRESH_CTRL_SHDW 0x0014
+#define EMIF_SDRAM_TIMING_1 0x0018
+#define EMIF_SDRAM_TIMING_1_SHDW 0x001c
+#define EMIF_SDRAM_TIMING_2 0x0020
+#define EMIF_SDRAM_TIMING_2_SHDW 0x0024
+#define EMIF_SDRAM_TIMING_3 0x0028
+#define EMIF_SDRAM_TIMING_3_SHDW 0x002c
+#define EMIF_LPDDR2_NVM_TIMING 0x0030
+#define EMIF_LPDDR2_NVM_TIMING_SHDW 0x0034
+#define EMIF_POWER_MANAGEMENT_CONTROL 0x0038
+#define EMIF_POWER_MANAGEMENT_CTRL_SHDW 0x003c
+#define EMIF_LPDDR2_MODE_REG_DATA 0x0040
+#define EMIF_LPDDR2_MODE_REG_CONFIG 0x0050
+#define EMIF_OCP_CONFIG 0x0054
+#define EMIF_OCP_CONFIG_VALUE_1 0x0058
+#define EMIF_OCP_CONFIG_VALUE_2 0x005c
+#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL 0x0060
+#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT 0x0064
+#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT 0x0068
+#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1 0x006c
+#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2 0x0070
+#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3 0x0074
+#define EMIF_PERFORMANCE_COUNTER_1 0x0080
+#define EMIF_PERFORMANCE_COUNTER_2 0x0084
+#define EMIF_PERFORMANCE_COUNTER_CONFIG 0x0088
+#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT 0x008c
+#define EMIF_PERFORMANCE_COUNTER_TIME 0x0090
+#define EMIF_MISC_REG 0x0094
+#define EMIF_DLL_CALIB_CTRL 0x0098
+#define EMIF_DLL_CALIB_CTRL_SHDW 0x009c
+#define EMIF_END_OF_INTERRUPT 0x00a0
+#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS 0x00a4
+#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS 0x00a8
+#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS 0x00ac
+#define EMIF_LL_OCP_INTERRUPT_STATUS 0x00b0
+#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET 0x00b4
+#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET 0x00b8
+#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR 0x00bc
+#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR 0x00c0
+#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG 0x00c8
+#define EMIF_TEMPERATURE_ALERT_CONFIG 0x00cc
+#define EMIF_OCP_ERROR_LOG 0x00d0
+#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW 0x00d4
+#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL 0x00d8
+#define EMIF_READ_WRITE_LEVELING_CONTROL 0x00dc
+#define EMIF_DDR_PHY_CTRL_1 0x00e4
+#define EMIF_DDR_PHY_CTRL_1_SHDW 0x00e8
+#define EMIF_DDR_PHY_CTRL_2 0x00ec
+#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING 0x0100
+#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104
+#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108
+#define EMIF_READ_WRITE_EXECUTION_THRESHOLD 0x0120
+#define EMIF_COS_CONFIG 0x0124
+#define EMIF_PHY_STATUS_1 0x0140
+#define EMIF_PHY_STATUS_2 0x0144
+#define EMIF_PHY_STATUS_3 0x0148
+#define EMIF_PHY_STATUS_4 0x014c
+#define EMIF_PHY_STATUS_5 0x0150
+#define EMIF_PHY_STATUS_6 0x0154
+#define EMIF_PHY_STATUS_7 0x0158
+#define EMIF_PHY_STATUS_8 0x015c
+#define EMIF_PHY_STATUS_9 0x0160
+#define EMIF_PHY_STATUS_10 0x0164
+#define EMIF_PHY_STATUS_11 0x0168
+#define EMIF_PHY_STATUS_12 0x016c
+#define EMIF_PHY_STATUS_13 0x0170
+#define EMIF_PHY_STATUS_14 0x0174
+#define EMIF_PHY_STATUS_15 0x0178
+#define EMIF_PHY_STATUS_16 0x017c
+#define EMIF_PHY_STATUS_17 0x0180
+#define EMIF_PHY_STATUS_18 0x0184
+#define EMIF_PHY_STATUS_19 0x0188
+#define EMIF_PHY_STATUS_20 0x018c
+#define EMIF_PHY_STATUS_21 0x0190
+#define EMIF_EXT_PHY_CTRL_1 0x0200
+#define EMIF_EXT_PHY_CTRL_1_SHDW 0x0204
+#define EMIF_EXT_PHY_CTRL_2 0x0208
+#define EMIF_EXT_PHY_CTRL_2_SHDW 0x020c
+#define EMIF_EXT_PHY_CTRL_3 0x0210
+#define EMIF_EXT_PHY_CTRL_3_SHDW 0x0214
+#define EMIF_EXT_PHY_CTRL_4 0x0218
+#define EMIF_EXT_PHY_CTRL_4_SHDW 0x021c
+#define EMIF_EXT_PHY_CTRL_5 0x0220
+#define EMIF_EXT_PHY_CTRL_5_SHDW 0x0224
+#define EMIF_EXT_PHY_CTRL_6 0x0228
+#define EMIF_EXT_PHY_CTRL_6_SHDW 0x022c
+#define EMIF_EXT_PHY_CTRL_7 0x0230
+#define EMIF_EXT_PHY_CTRL_7_SHDW 0x0234
+#define EMIF_EXT_PHY_CTRL_8 0x0238
+#define EMIF_EXT_PHY_CTRL_8_SHDW 0x023c
+#define EMIF_EXT_PHY_CTRL_9 0x0240
+#define EMIF_EXT_PHY_CTRL_9_SHDW 0x0244
+#define EMIF_EXT_PHY_CTRL_10 0x0248
+#define EMIF_EXT_PHY_CTRL_10_SHDW 0x024c
+#define EMIF_EXT_PHY_CTRL_11 0x0250
+#define EMIF_EXT_PHY_CTRL_11_SHDW 0x0254
+#define EMIF_EXT_PHY_CTRL_12 0x0258
+#define EMIF_EXT_PHY_CTRL_12_SHDW 0x025c
+#define EMIF_EXT_PHY_CTRL_13 0x0260
+#define EMIF_EXT_PHY_CTRL_13_SHDW 0x0264
+#define EMIF_EXT_PHY_CTRL_14 0x0268
+#define EMIF_EXT_PHY_CTRL_14_SHDW 0x026c
+#define EMIF_EXT_PHY_CTRL_15 0x0270
+#define EMIF_EXT_PHY_CTRL_15_SHDW 0x0274
+#define EMIF_EXT_PHY_CTRL_16 0x0278
+#define EMIF_EXT_PHY_CTRL_16_SHDW 0x027c
+#define EMIF_EXT_PHY_CTRL_17 0x0280
+#define EMIF_EXT_PHY_CTRL_17_SHDW 0x0284
+#define EMIF_EXT_PHY_CTRL_18 0x0288
+#define EMIF_EXT_PHY_CTRL_18_SHDW 0x028c
+#define EMIF_EXT_PHY_CTRL_19 0x0290
+#define EMIF_EXT_PHY_CTRL_19_SHDW 0x0294
+#define EMIF_EXT_PHY_CTRL_20 0x0298
+#define EMIF_EXT_PHY_CTRL_20_SHDW 0x029c
+#define EMIF_EXT_PHY_CTRL_21 0x02a0
+#define EMIF_EXT_PHY_CTRL_21_SHDW 0x02a4
+#define EMIF_EXT_PHY_CTRL_22 0x02a8
+#define EMIF_EXT_PHY_CTRL_22_SHDW 0x02ac
+#define EMIF_EXT_PHY_CTRL_23 0x02b0
+#define EMIF_EXT_PHY_CTRL_23_SHDW 0x02b4
+#define EMIF_EXT_PHY_CTRL_24 0x02b8
+#define EMIF_EXT_PHY_CTRL_24_SHDW 0x02bc
+#define EMIF_EXT_PHY_CTRL_25 0x02c0
+#define EMIF_EXT_PHY_CTRL_25_SHDW 0x02c4
+#define EMIF_EXT_PHY_CTRL_26 0x02c8
+#define EMIF_EXT_PHY_CTRL_26_SHDW 0x02cc
+#define EMIF_EXT_PHY_CTRL_27 0x02d0
+#define EMIF_EXT_PHY_CTRL_27_SHDW 0x02d4
+#define EMIF_EXT_PHY_CTRL_28 0x02d8
+#define EMIF_EXT_PHY_CTRL_28_SHDW 0x02dc
+#define EMIF_EXT_PHY_CTRL_29 0x02e0
+#define EMIF_EXT_PHY_CTRL_29_SHDW 0x02e4
+#define EMIF_EXT_PHY_CTRL_30 0x02e8
+#define EMIF_EXT_PHY_CTRL_30_SHDW 0x02ec
+
+/* Registers shifts and masks */
+
+/* EMIF_MODULE_ID_AND_REVISION */
+#define SCHEME_SHIFT 30
+#define SCHEME_MASK (0x3 << 30)
+#define MODULE_ID_SHIFT 16
+#define MODULE_ID_MASK (0xfff << 16)
+#define RTL_VERSION_SHIFT 11
+#define RTL_VERSION_MASK (0x1f << 11)
+#define MAJOR_REVISION_SHIFT 8
+#define MAJOR_REVISION_MASK (0x7 << 8)
+#define MINOR_REVISION_SHIFT 0
+#define MINOR_REVISION_MASK (0x3f << 0)
+
+/* STATUS */
+#define BE_SHIFT 31
+#define BE_MASK (1 << 31)
+#define DUAL_CLK_MODE_SHIFT 30
+#define DUAL_CLK_MODE_MASK (1 << 30)
+#define FAST_INIT_SHIFT 29
+#define FAST_INIT_MASK (1 << 29)
+#define RDLVLGATETO_SHIFT 6
+#define RDLVLGATETO_MASK (1 << 6)
+#define RDLVLTO_SHIFT 5
+#define RDLVLTO_MASK (1 << 5)
+#define WRLVLTO_SHIFT 4
+#define WRLVLTO_MASK (1 << 4)
+#define PHY_DLL_READY_SHIFT 2
+#define PHY_DLL_READY_MASK (1 << 2)
+
+/* SDRAM_CONFIG */
+#define SDRAM_TYPE_SHIFT 29
+#define SDRAM_TYPE_MASK (0x7 << 29)
+#define IBANK_POS_SHIFT 27
+#define IBANK_POS_MASK (0x3 << 27)
+#define DDR_TERM_SHIFT 24
+#define DDR_TERM_MASK (0x7 << 24)
+#define DDR2_DDQS_SHIFT 23
+#define DDR2_DDQS_MASK (1 << 23)
+#define DYN_ODT_SHIFT 21
+#define DYN_ODT_MASK (0x3 << 21)
+#define DDR_DISABLE_DLL_SHIFT 20
+#define DDR_DISABLE_DLL_MASK (1 << 20)
+#define SDRAM_DRIVE_SHIFT 18
+#define SDRAM_DRIVE_MASK (0x3 << 18)
+#define CWL_SHIFT 16
+#define CWL_MASK (0x3 << 16)
+#define NARROW_MODE_SHIFT 14
+#define NARROW_MODE_MASK (0x3 << 14)
+#define CL_SHIFT 10
+#define CL_MASK (0xf << 10)
+#define ROWSIZE_SHIFT 7
+#define ROWSIZE_MASK (0x7 << 7)
+#define IBANK_SHIFT 4
+#define IBANK_MASK (0x7 << 4)
+#define EBANK_SHIFT 3
+#define EBANK_MASK (1 << 3)
+#define PAGESIZE_SHIFT 0
+#define PAGESIZE_MASK (0x7 << 0)
+
+/* SDRAM_CONFIG_2 */
+#define CS1NVMEN_SHIFT 30
+#define CS1NVMEN_MASK (1 << 30)
+#define EBANK_POS_SHIFT 27
+#define EBANK_POS_MASK (1 << 27)
+#define RDBNUM_SHIFT 4
+#define RDBNUM_MASK (0x3 << 4)
+#define RDBSIZE_SHIFT 0
+#define RDBSIZE_MASK (0x7 << 0)
+
+/* SDRAM_REFRESH_CONTROL */
+#define INITREF_DIS_SHIFT 31
+#define INITREF_DIS_MASK (1 << 31)
+#define SRT_SHIFT 29
+#define SRT_MASK (1 << 29)
+#define ASR_SHIFT 28
+#define ASR_MASK (1 << 28)
+#define PASR_SHIFT 24
+#define PASR_MASK (0x7 << 24)
+#define REFRESH_RATE_SHIFT 0
+#define REFRESH_RATE_MASK (0xffff << 0)
+
+/* SDRAM_TIMING_1 */
+#define T_RTW_SHIFT 29
+#define T_RTW_MASK (0x7 << 29)
+#define T_RP_SHIFT 25
+#define T_RP_MASK (0xf << 25)
+#define T_RCD_SHIFT 21
+#define T_RCD_MASK (0xf << 21)
+#define T_WR_SHIFT 17
+#define T_WR_MASK (0xf << 17)
+#define T_RAS_SHIFT 12
+#define T_RAS_MASK (0x1f << 12)
+#define T_RC_SHIFT 6
+#define T_RC_MASK (0x3f << 6)
+#define T_RRD_SHIFT 3
+#define T_RRD_MASK (0x7 << 3)
+#define T_WTR_SHIFT 0
+#define T_WTR_MASK (0x7 << 0)
+
+/* SDRAM_TIMING_2 */
+#define T_XP_SHIFT 28
+#define T_XP_MASK (0x7 << 28)
+#define T_ODT_SHIFT 25
+#define T_ODT_MASK (0x7 << 25)
+#define T_XSNR_SHIFT 16
+#define T_XSNR_MASK (0x1ff << 16)
+#define T_XSRD_SHIFT 6
+#define T_XSRD_MASK (0x3ff << 6)
+#define T_RTP_SHIFT 3
+#define T_RTP_MASK (0x7 << 3)
+#define T_CKE_SHIFT 0
+#define T_CKE_MASK (0x7 << 0)
+
+/* SDRAM_TIMING_3 */
+#define T_PDLL_UL_SHIFT 28
+#define T_PDLL_UL_MASK (0xf << 28)
+#define T_CSTA_SHIFT 24
+#define T_CSTA_MASK (0xf << 24)
+#define T_CKESR_SHIFT 21
+#define T_CKESR_MASK (0x7 << 21)
+#define ZQ_ZQCS_SHIFT 15
+#define ZQ_ZQCS_MASK (0x3f << 15)
+#define T_TDQSCKMAX_SHIFT 13
+#define T_TDQSCKMAX_MASK (0x3 << 13)
+#define T_RFC_SHIFT 4
+#define T_RFC_MASK (0x1ff << 4)
+#define T_RAS_MAX_SHIFT 0
+#define T_RAS_MAX_MASK (0xf << 0)
+
+/* POWER_MANAGEMENT_CONTROL */
+#define PD_TIM_SHIFT 12
+#define PD_TIM_MASK (0xf << 12)
+#define DPD_EN_SHIFT 11
+#define DPD_EN_MASK (1 << 11)
+#define LP_MODE_SHIFT 8
+#define LP_MODE_MASK (0x7 << 8)
+#define SR_TIM_SHIFT 4
+#define SR_TIM_MASK (0xf << 4)
+#define CS_TIM_SHIFT 0
+#define CS_TIM_MASK (0xf << 0)
+
+/* LPDDR2_MODE_REG_DATA */
+#define VALUE_0_SHIFT 0
+#define VALUE_0_MASK (0x7f << 0)
+
+/* LPDDR2_MODE_REG_CONFIG */
+#define CS_SHIFT 31
+#define CS_MASK (1 << 31)
+#define REFRESH_EN_SHIFT 30
+#define REFRESH_EN_MASK (1 << 30)
+#define ADDRESS_SHIFT 0
+#define ADDRESS_MASK (0xff << 0)
+
+/* OCP_CONFIG */
+#define SYS_THRESH_MAX_SHIFT 24
+#define SYS_THRESH_MAX_MASK (0xf << 24)
+#define MPU_THRESH_MAX_SHIFT 20
+#define MPU_THRESH_MAX_MASK (0xf << 20)
+#define LL_THRESH_MAX_SHIFT 16
+#define LL_THRESH_MAX_MASK (0xf << 16)
+
+/* PERFORMANCE_COUNTER_1 */
+#define COUNTER1_SHIFT 0
+#define COUNTER1_MASK (0xffffffff << 0)
+
+/* PERFORMANCE_COUNTER_2 */
+#define COUNTER2_SHIFT 0
+#define COUNTER2_MASK (0xffffffff << 0)
+
+/* PERFORMANCE_COUNTER_CONFIG */
+#define CNTR2_MCONNID_EN_SHIFT 31
+#define CNTR2_MCONNID_EN_MASK (1 << 31)
+#define CNTR2_REGION_EN_SHIFT 30
+#define CNTR2_REGION_EN_MASK (1 << 30)
+#define CNTR2_CFG_SHIFT 16
+#define CNTR2_CFG_MASK (0xf << 16)
+#define CNTR1_MCONNID_EN_SHIFT 15
+#define CNTR1_MCONNID_EN_MASK (1 << 15)
+#define CNTR1_REGION_EN_SHIFT 14
+#define CNTR1_REGION_EN_MASK (1 << 14)
+#define CNTR1_CFG_SHIFT 0
+#define CNTR1_CFG_MASK (0xf << 0)
+
+/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */
+#define MCONNID2_SHIFT 24
+#define MCONNID2_MASK (0xff << 24)
+#define REGION_SEL2_SHIFT 16
+#define REGION_SEL2_MASK (0x3 << 16)
+#define MCONNID1_SHIFT 8
+#define MCONNID1_MASK (0xff << 8)
+#define REGION_SEL1_SHIFT 0
+#define REGION_SEL1_MASK (0x3 << 0)
+
+/* PERFORMANCE_COUNTER_TIME */
+#define TOTAL_TIME_SHIFT 0
+#define TOTAL_TIME_MASK (0xffffffff << 0)
+
+/* DLL_CALIB_CTRL */
+#define ACK_WAIT_SHIFT 16
+#define ACK_WAIT_MASK (0xf << 16)
+#define DLL_CALIB_INTERVAL_SHIFT 0
+#define DLL_CALIB_INTERVAL_MASK (0x1ff << 0)
+
+/* END_OF_INTERRUPT */
+#define EOI_SHIFT 0
+#define EOI_MASK (1 << 0)
+
+/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */
+#define DNV_SYS_SHIFT 2
+#define DNV_SYS_MASK (1 << 2)
+#define TA_SYS_SHIFT 1
+#define TA_SYS_MASK (1 << 1)
+#define ERR_SYS_SHIFT 0
+#define ERR_SYS_MASK (1 << 0)
+
+/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */
+#define DNV_LL_SHIFT 2
+#define DNV_LL_MASK (1 << 2)
+#define TA_LL_SHIFT 1
+#define TA_LL_MASK (1 << 1)
+#define ERR_LL_SHIFT 0
+#define ERR_LL_MASK (1 << 0)
+
+/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */
+#define EN_DNV_SYS_SHIFT 2
+#define EN_DNV_SYS_MASK (1 << 2)
+#define EN_TA_SYS_SHIFT 1
+#define EN_TA_SYS_MASK (1 << 1)
+#define EN_ERR_SYS_SHIFT 0
+#define EN_ERR_SYS_MASK (1 << 0)
+
+/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */
+#define EN_DNV_LL_SHIFT 2
+#define EN_DNV_LL_MASK (1 << 2)
+#define EN_TA_LL_SHIFT 1
+#define EN_TA_LL_MASK (1 << 1)
+#define EN_ERR_LL_SHIFT 0
+#define EN_ERR_LL_MASK (1 << 0)
+
+/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */
+#define ZQ_CS1EN_SHIFT 31
+#define ZQ_CS1EN_MASK (1 << 31)
+#define ZQ_CS0EN_SHIFT 30
+#define ZQ_CS0EN_MASK (1 << 30)
+#define ZQ_DUALCALEN_SHIFT 29
+#define ZQ_DUALCALEN_MASK (1 << 29)
+#define ZQ_SFEXITEN_SHIFT 28
+#define ZQ_SFEXITEN_MASK (1 << 28)
+#define ZQ_ZQINIT_MULT_SHIFT 18
+#define ZQ_ZQINIT_MULT_MASK (0x3 << 18)
+#define ZQ_ZQCL_MULT_SHIFT 16
+#define ZQ_ZQCL_MULT_MASK (0x3 << 16)
+#define ZQ_REFINTERVAL_SHIFT 0
+#define ZQ_REFINTERVAL_MASK (0xffff << 0)
+
+/* TEMPERATURE_ALERT_CONFIG */
+#define TA_CS1EN_SHIFT 31
+#define TA_CS1EN_MASK (1 << 31)
+#define TA_CS0EN_SHIFT 30
+#define TA_CS0EN_MASK (1 << 30)
+#define TA_SFEXITEN_SHIFT 28
+#define TA_SFEXITEN_MASK (1 << 28)
+#define TA_DEVWDT_SHIFT 26
+#define TA_DEVWDT_MASK (0x3 << 26)
+#define TA_DEVCNT_SHIFT 24
+#define TA_DEVCNT_MASK (0x3 << 24)
+#define TA_REFINTERVAL_SHIFT 0
+#define TA_REFINTERVAL_MASK (0x3fffff << 0)
+
+/* OCP_ERROR_LOG */
+#define MADDRSPACE_SHIFT 14
+#define MADDRSPACE_MASK (0x3 << 14)
+#define MBURSTSEQ_SHIFT 11
+#define MBURSTSEQ_MASK (0x7 << 11)
+#define MCMD_SHIFT 8
+#define MCMD_MASK (0x7 << 8)
+#define MCONNID_SHIFT 0
+#define MCONNID_MASK (0xff << 0)
+
+/* DDR_PHY_CTRL_1 - EMIF4D */
+#define DLL_SLAVE_DLY_CTRL_SHIFT_4D 4
+#define DLL_SLAVE_DLY_CTRL_MASK_4D (0xFF << 4)
+#define READ_LATENCY_SHIFT_4D 0
+#define READ_LATENCY_MASK_4D (0xf << 0)
+
+/* DDR_PHY_CTRL_1 - EMIF4D5 */
+#define DLL_HALF_DELAY_SHIFT_4D5 21
+#define DLL_HALF_DELAY_MASK_4D5 (1 << 21)
+#define READ_LATENCY_SHIFT_4D5 0
+#define READ_LATENCY_MASK_4D5 (0x1f << 0)
+
+/* DDR_PHY_CTRL_1_SHDW */
+#define DDR_PHY_CTRL_1_SHDW_SHIFT 5
+#define DDR_PHY_CTRL_1_SHDW_MASK (0x7ffffff << 5)
+#define READ_LATENCY_SHDW_SHIFT 0
+#define READ_LATENCY_SHDW_MASK (0x1f << 0)
+
+#ifndef __ASSEMBLY__
+/*
+ * Structure containing shadow of important registers in EMIF
+ * The calculation function fills in this structure to be later used for
+ * initialisation and DVFS
+ */
+struct emif_regs {
+ u32 freq;
+ u32 ref_ctrl_shdw;
+ u32 ref_ctrl_shdw_derated;
+ u32 sdram_tim1_shdw;
+ u32 sdram_tim1_shdw_derated;
+ u32 sdram_tim2_shdw;
+ u32 sdram_tim3_shdw;
+ u32 sdram_tim3_shdw_derated;
+ u32 pwr_mgmt_ctrl_shdw;
+ union {
+ u32 read_idle_ctrl_shdw_normal;
+ u32 dll_calib_ctrl_shdw_normal;
+ };
+ union {
+ u32 read_idle_ctrl_shdw_volt_ramp;
+ u32 dll_calib_ctrl_shdw_volt_ramp;
+ };
+
+ u32 phy_ctrl_1_shdw;
+ u32 ext_phy_ctrl_2_shdw;
+ u32 ext_phy_ctrl_3_shdw;
+ u32 ext_phy_ctrl_4_shdw;
+};
+#endif /* __ASSEMBLY__ */
+#endif /* __EMIF_H */
diff --git a/drivers/memory/tegra20-mc.c b/drivers/memory/tegra20-mc.c
new file mode 100644
index 000000000000..3ed49c1c2b91
--- /dev/null
+++ b/drivers/memory/tegra20-mc.c
@@ -0,0 +1,257 @@
+/*
+ * Tegra20 Memory Controller
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ratelimit.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#define DRV_NAME "tegra20-mc"
+
+#define MC_INTSTATUS 0x0
+#define MC_INTMASK 0x4
+
+#define MC_INT_ERR_SHIFT 6
+#define MC_INT_ERR_MASK (0x1f << MC_INT_ERR_SHIFT)
+#define MC_INT_DECERR_EMEM BIT(MC_INT_ERR_SHIFT)
+#define MC_INT_INVALID_GART_PAGE BIT(MC_INT_ERR_SHIFT + 1)
+#define MC_INT_SECURITY_VIOLATION BIT(MC_INT_ERR_SHIFT + 2)
+#define MC_INT_ARBITRATION_EMEM BIT(MC_INT_ERR_SHIFT + 3)
+
+#define MC_GART_ERROR_REQ 0x30
+#define MC_DECERR_EMEM_OTHERS_STATUS 0x58
+#define MC_SECURITY_VIOLATION_STATUS 0x74
+
+#define SECURITY_VIOLATION_TYPE BIT(30) /* 0=TRUSTZONE, 1=CARVEOUT */
+
+#define MC_CLIENT_ID_MASK 0x3f
+
+#define NUM_MC_REG_BANKS 2
+
+struct tegra20_mc {
+ void __iomem *regs[NUM_MC_REG_BANKS];
+ struct device *dev;
+};
+
+static inline u32 mc_readl(struct tegra20_mc *mc, u32 offs)
+{
+ u32 val = 0;
+
+ if (offs < 0x24)
+ val = readl(mc->regs[0] + offs);
+ if (offs < 0x400)
+ val = readl(mc->regs[1] + offs - 0x3c);
+
+ return val;
+}
+
+static inline void mc_writel(struct tegra20_mc *mc, u32 val, u32 offs)
+{
+ if (offs < 0x24) {
+ writel(val, mc->regs[0] + offs);
+ return;
+ }
+ if (offs < 0x400) {
+ writel(val, mc->regs[1] + offs - 0x3c);
+ return;
+ }
+}
+
+static const char * const tegra20_mc_client[] = {
+ "cbr_display0a",
+ "cbr_display0ab",
+ "cbr_display0b",
+ "cbr_display0bb",
+ "cbr_display0c",
+ "cbr_display0cb",
+ "cbr_display1b",
+ "cbr_display1bb",
+ "cbr_eppup",
+ "cbr_g2pr",
+ "cbr_g2sr",
+ "cbr_mpeunifbr",
+ "cbr_viruv",
+ "csr_avpcarm7r",
+ "csr_displayhc",
+ "csr_displayhcb",
+ "csr_fdcdrd",
+ "csr_g2dr",
+ "csr_host1xdmar",
+ "csr_host1xr",
+ "csr_idxsrd",
+ "csr_mpcorer",
+ "csr_mpe_ipred",
+ "csr_mpeamemrd",
+ "csr_mpecsrd",
+ "csr_ppcsahbdmar",
+ "csr_ppcsahbslvr",
+ "csr_texsrd",
+ "csr_vdebsevr",
+ "csr_vdember",
+ "csr_vdemcer",
+ "csr_vdetper",
+ "cbw_eppu",
+ "cbw_eppv",
+ "cbw_eppy",
+ "cbw_mpeunifbw",
+ "cbw_viwsb",
+ "cbw_viwu",
+ "cbw_viwv",
+ "cbw_viwy",
+ "ccw_g2dw",
+ "csw_avpcarm7w",
+ "csw_fdcdwr",
+ "csw_host1xw",
+ "csw_ispw",
+ "csw_mpcorew",
+ "csw_mpecswr",
+ "csw_ppcsahbdmaw",
+ "csw_ppcsahbslvw",
+ "csw_vdebsevw",
+ "csw_vdembew",
+ "csw_vdetpmw",
+};
+
+static void tegra20_mc_decode(struct tegra20_mc *mc, int n)
+{
+ u32 addr, req;
+ const char *client = "Unknown";
+ int idx, cid;
+ const struct reg_info {
+ u32 offset;
+ u32 write_bit; /* 0=READ, 1=WRITE */
+ int cid_shift;
+ char *message;
+ } reg[] = {
+ {
+ .offset = MC_DECERR_EMEM_OTHERS_STATUS,
+ .write_bit = 31,
+ .message = "MC_DECERR",
+ },
+ {
+ .offset = MC_GART_ERROR_REQ,
+ .cid_shift = 1,
+ .message = "MC_GART_ERR",
+
+ },
+ {
+ .offset = MC_SECURITY_VIOLATION_STATUS,
+ .write_bit = 31,
+ .message = "MC_SECURITY_ERR",
+ },
+ };
+
+ idx = n - MC_INT_ERR_SHIFT;
+ if ((idx < 0) || (idx >= ARRAY_SIZE(reg))) {
+ dev_err_ratelimited(mc->dev, "Unknown interrupt status %08lx\n",
+ BIT(n));
+ return;
+ }
+
+ req = mc_readl(mc, reg[idx].offset);
+ cid = (req >> reg[idx].cid_shift) & MC_CLIENT_ID_MASK;
+ if (cid < ARRAY_SIZE(tegra20_mc_client))
+ client = tegra20_mc_client[cid];
+
+ addr = mc_readl(mc, reg[idx].offset + sizeof(u32));
+
+ dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s)\n",
+ reg[idx].message, req, addr, client,
+ (req & BIT(reg[idx].write_bit)) ? "write" : "read",
+ (reg[idx].offset == MC_SECURITY_VIOLATION_STATUS) ?
+ ((req & SECURITY_VIOLATION_TYPE) ?
+ "carveout" : "trustzone") : "");
+}
+
+static const struct of_device_id tegra20_mc_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra20-mc", },
+ {},
+};
+
+static irqreturn_t tegra20_mc_isr(int irq, void *data)
+{
+ u32 stat, mask, bit;
+ struct tegra20_mc *mc = data;
+
+ stat = mc_readl(mc, MC_INTSTATUS);
+ mask = mc_readl(mc, MC_INTMASK);
+ mask &= stat;
+ if (!mask)
+ return IRQ_NONE;
+ while ((bit = ffs(mask)) != 0)
+ tegra20_mc_decode(mc, bit - 1);
+ mc_writel(mc, stat, MC_INTSTATUS);
+ return IRQ_HANDLED;
+}
+
+static int __devinit tegra20_mc_probe(struct platform_device *pdev)
+{
+ struct resource *irq;
+ struct tegra20_mc *mc;
+ int i, err;
+ u32 intmask;
+
+ mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
+ if (!mc)
+ return -ENOMEM;
+ mc->dev = &pdev->dev;
+
+ for (i = 0; i < ARRAY_SIZE(mc->regs); i++) {
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ if (!res)
+ return -ENODEV;
+ mc->regs[i] = devm_request_and_ioremap(&pdev->dev, res);
+ if (!mc->regs[i])
+ return -EBUSY;
+ }
+
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq)
+ return -ENODEV;
+ err = devm_request_irq(&pdev->dev, irq->start, tegra20_mc_isr,
+ IRQF_SHARED, dev_name(&pdev->dev), mc);
+ if (err)
+ return -ENODEV;
+
+ platform_set_drvdata(pdev, mc);
+
+ intmask = MC_INT_INVALID_GART_PAGE |
+ MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION;
+ mc_writel(mc, intmask, MC_INTMASK);
+ return 0;
+}
+
+static struct platform_driver tegra20_mc_driver = {
+ .probe = tegra20_mc_probe,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = tegra20_mc_of_match,
+ },
+};
+module_platform_driver(tegra20_mc_driver);
+
+MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>");
+MODULE_DESCRIPTION("Tegra20 MC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c
new file mode 100644
index 000000000000..e56ff04eb5cc
--- /dev/null
+++ b/drivers/memory/tegra30-mc.c
@@ -0,0 +1,382 @@
+/*
+ * Tegra30 Memory Controller
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ratelimit.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#define DRV_NAME "tegra30-mc"
+
+#define MC_INTSTATUS 0x0
+#define MC_INTMASK 0x4
+
+#define MC_INT_ERR_SHIFT 6
+#define MC_INT_ERR_MASK (0x1f << MC_INT_ERR_SHIFT)
+#define MC_INT_DECERR_EMEM BIT(MC_INT_ERR_SHIFT)
+#define MC_INT_SECURITY_VIOLATION BIT(MC_INT_ERR_SHIFT + 2)
+#define MC_INT_ARBITRATION_EMEM BIT(MC_INT_ERR_SHIFT + 3)
+#define MC_INT_INVALID_SMMU_PAGE BIT(MC_INT_ERR_SHIFT + 4)
+
+#define MC_ERR_STATUS 0x8
+#define MC_ERR_ADR 0xc
+
+#define MC_ERR_TYPE_SHIFT 28
+#define MC_ERR_TYPE_MASK (7 << MC_ERR_TYPE_SHIFT)
+#define MC_ERR_TYPE_DECERR_EMEM 2
+#define MC_ERR_TYPE_SECURITY_TRUSTZONE 3
+#define MC_ERR_TYPE_SECURITY_CARVEOUT 4
+#define MC_ERR_TYPE_INVALID_SMMU_PAGE 6
+
+#define MC_ERR_INVALID_SMMU_PAGE_SHIFT 25
+#define MC_ERR_INVALID_SMMU_PAGE_MASK (7 << MC_ERR_INVALID_SMMU_PAGE_SHIFT)
+#define MC_ERR_RW_SHIFT 16
+#define MC_ERR_RW BIT(MC_ERR_RW_SHIFT)
+#define MC_ERR_SECURITY BIT(MC_ERR_RW_SHIFT + 1)
+
+#define SECURITY_VIOLATION_TYPE BIT(30) /* 0=TRUSTZONE, 1=CARVEOUT */
+
+#define MC_EMEM_ARB_CFG 0x90
+#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94
+#define MC_EMEM_ARB_TIMING_RCD 0x98
+#define MC_EMEM_ARB_TIMING_RP 0x9c
+#define MC_EMEM_ARB_TIMING_RC 0xa0
+#define MC_EMEM_ARB_TIMING_RAS 0xa4
+#define MC_EMEM_ARB_TIMING_FAW 0xa8
+#define MC_EMEM_ARB_TIMING_RRD 0xac
+#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0
+#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4
+#define MC_EMEM_ARB_TIMING_R2R 0xb8
+#define MC_EMEM_ARB_TIMING_W2W 0xbc
+#define MC_EMEM_ARB_TIMING_R2W 0xc0
+#define MC_EMEM_ARB_TIMING_W2R 0xc4
+
+#define MC_EMEM_ARB_DA_TURNS 0xd0
+#define MC_EMEM_ARB_DA_COVERS 0xd4
+#define MC_EMEM_ARB_MISC0 0xd8
+#define MC_EMEM_ARB_MISC1 0xdc
+
+#define MC_EMEM_ARB_RING3_THROTTLE 0xe4
+#define MC_EMEM_ARB_OVERRIDE 0xe8
+
+#define MC_TIMING_CONTROL 0xfc
+
+#define MC_CLIENT_ID_MASK 0x7f
+
+#define NUM_MC_REG_BANKS 4
+
+struct tegra30_mc {
+ void __iomem *regs[NUM_MC_REG_BANKS];
+ struct device *dev;
+ u32 ctx[0];
+};
+
+static inline u32 mc_readl(struct tegra30_mc *mc, u32 offs)
+{
+ u32 val = 0;
+
+ if (offs < 0x10)
+ val = readl(mc->regs[0] + offs);
+ if (offs < 0x1f0)
+ val = readl(mc->regs[1] + offs - 0x3c);
+ if (offs < 0x228)
+ val = readl(mc->regs[2] + offs - 0x200);
+ if (offs < 0x400)
+ val = readl(mc->regs[3] + offs - 0x284);
+
+ return val;
+}
+
+static inline void mc_writel(struct tegra30_mc *mc, u32 val, u32 offs)
+{
+ if (offs < 0x10) {
+ writel(val, mc->regs[0] + offs);
+ return;
+ }
+ if (offs < 0x1f0) {
+ writel(val, mc->regs[1] + offs - 0x3c);
+ return;
+ }
+ if (offs < 0x228) {
+ writel(val, mc->regs[2] + offs - 0x200);
+ return;
+ }
+ if (offs < 0x400) {
+ writel(val, mc->regs[3] + offs - 0x284);
+ return;
+ }
+}
+
+static const char * const tegra30_mc_client[] = {
+ "csr_ptcr",
+ "cbr_display0a",
+ "cbr_display0ab",
+ "cbr_display0b",
+ "cbr_display0bb",
+ "cbr_display0c",
+ "cbr_display0cb",
+ "cbr_display1b",
+ "cbr_display1bb",
+ "cbr_eppup",
+ "cbr_g2pr",
+ "cbr_g2sr",
+ "cbr_mpeunifbr",
+ "cbr_viruv",
+ "csr_afir",
+ "csr_avpcarm7r",
+ "csr_displayhc",
+ "csr_displayhcb",
+ "csr_fdcdrd",
+ "csr_fdcdrd2",
+ "csr_g2dr",
+ "csr_hdar",
+ "csr_host1xdmar",
+ "csr_host1xr",
+ "csr_idxsrd",
+ "csr_idxsrd2",
+ "csr_mpe_ipred",
+ "csr_mpeamemrd",
+ "csr_mpecsrd",
+ "csr_ppcsahbdmar",
+ "csr_ppcsahbslvr",
+ "csr_satar",
+ "csr_texsrd",
+ "csr_texsrd2",
+ "csr_vdebsevr",
+ "csr_vdember",
+ "csr_vdemcer",
+ "csr_vdetper",
+ "csr_mpcorelpr",
+ "csr_mpcorer",
+ "cbw_eppu",
+ "cbw_eppv",
+ "cbw_eppy",
+ "cbw_mpeunifbw",
+ "cbw_viwsb",
+ "cbw_viwu",
+ "cbw_viwv",
+ "cbw_viwy",
+ "ccw_g2dw",
+ "csw_afiw",
+ "csw_avpcarm7w",
+ "csw_fdcdwr",
+ "csw_fdcdwr2",
+ "csw_hdaw",
+ "csw_host1xw",
+ "csw_ispw",
+ "csw_mpcorelpw",
+ "csw_mpcorew",
+ "csw_mpecswr",
+ "csw_ppcsahbdmaw",
+ "csw_ppcsahbslvw",
+ "csw_sataw",
+ "csw_vdebsevw",
+ "csw_vdedbgw",
+ "csw_vdembew",
+ "csw_vdetpmw",
+};
+
+static void tegra30_mc_decode(struct tegra30_mc *mc, int n)
+{
+ u32 err, addr;
+ const char * const mc_int_err[] = {
+ "MC_DECERR",
+ "Unknown",
+ "MC_SECURITY_ERR",
+ "MC_ARBITRATION_EMEM",
+ "MC_SMMU_ERR",
+ };
+ const char * const err_type[] = {
+ "Unknown",
+ "Unknown",
+ "DECERR_EMEM",
+ "SECURITY_TRUSTZONE",
+ "SECURITY_CARVEOUT",
+ "Unknown",
+ "INVALID_SMMU_PAGE",
+ "Unknown",
+ };
+ char attr[6];
+ int cid, perm, type, idx;
+ const char *client = "Unknown";
+
+ idx = n - MC_INT_ERR_SHIFT;
+ if ((idx < 0) || (idx >= ARRAY_SIZE(mc_int_err)) || (idx == 1)) {
+ dev_err_ratelimited(mc->dev, "Unknown interrupt status %08lx\n",
+ BIT(n));
+ return;
+ }
+
+ err = readl(mc + MC_ERR_STATUS);
+
+ type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT;
+ perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >>
+ MC_ERR_INVALID_SMMU_PAGE_SHIFT;
+ if (type == MC_ERR_TYPE_INVALID_SMMU_PAGE)
+ sprintf(attr, "%c-%c-%c",
+ (perm & BIT(2)) ? 'R' : '-',
+ (perm & BIT(1)) ? 'W' : '-',
+ (perm & BIT(0)) ? 'S' : '-');
+ else
+ attr[0] = '\0';
+
+ cid = err & MC_CLIENT_ID_MASK;
+ if (cid < ARRAY_SIZE(tegra30_mc_client))
+ client = tegra30_mc_client[cid];
+
+ addr = readl(mc + MC_ERR_ADR);
+
+ dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n",
+ mc_int_err[idx], err, addr, client,
+ (err & MC_ERR_SECURITY) ? "secure" : "non-secure",
+ (err & MC_ERR_RW) ? "write" : "read",
+ err_type[type], attr);
+}
+
+static const u32 tegra30_mc_ctx[] = {
+ MC_EMEM_ARB_CFG,
+ MC_EMEM_ARB_OUTSTANDING_REQ,
+ MC_EMEM_ARB_TIMING_RCD,
+ MC_EMEM_ARB_TIMING_RP,
+ MC_EMEM_ARB_TIMING_RC,
+ MC_EMEM_ARB_TIMING_RAS,
+ MC_EMEM_ARB_TIMING_FAW,
+ MC_EMEM_ARB_TIMING_RRD,
+ MC_EMEM_ARB_TIMING_RAP2PRE,
+ MC_EMEM_ARB_TIMING_WAP2PRE,
+ MC_EMEM_ARB_TIMING_R2R,
+ MC_EMEM_ARB_TIMING_W2W,
+ MC_EMEM_ARB_TIMING_R2W,
+ MC_EMEM_ARB_TIMING_W2R,
+ MC_EMEM_ARB_DA_TURNS,
+ MC_EMEM_ARB_DA_COVERS,
+ MC_EMEM_ARB_MISC0,
+ MC_EMEM_ARB_MISC1,
+ MC_EMEM_ARB_RING3_THROTTLE,
+ MC_EMEM_ARB_OVERRIDE,
+ MC_INTMASK,
+};
+
+static int tegra30_mc_suspend(struct device *dev)
+{
+ int i;
+ struct tegra30_mc *mc = dev_get_drvdata(dev);
+
+ for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++)
+ mc->ctx[i] = mc_readl(mc, tegra30_mc_ctx[i]);
+ return 0;
+}
+
+static int tegra30_mc_resume(struct device *dev)
+{
+ int i;
+ struct tegra30_mc *mc = dev_get_drvdata(dev);
+
+ for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++)
+ mc_writel(mc, mc->ctx[i], tegra30_mc_ctx[i]);
+
+ mc_writel(mc, 1, MC_TIMING_CONTROL);
+ /* Read-back to ensure that write reached */
+ mc_readl(mc, MC_TIMING_CONTROL);
+ return 0;
+}
+
+static UNIVERSAL_DEV_PM_OPS(tegra30_mc_pm,
+ tegra30_mc_suspend,
+ tegra30_mc_resume, NULL);
+
+static const struct of_device_id tegra30_mc_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra30-mc", },
+ {},
+};
+
+static irqreturn_t tegra30_mc_isr(int irq, void *data)
+{
+ u32 stat, mask, bit;
+ struct tegra30_mc *mc = data;
+
+ stat = mc_readl(mc, MC_INTSTATUS);
+ mask = mc_readl(mc, MC_INTMASK);
+ mask &= stat;
+ if (!mask)
+ return IRQ_NONE;
+ while ((bit = ffs(mask)) != 0)
+ tegra30_mc_decode(mc, bit - 1);
+ mc_writel(mc, stat, MC_INTSTATUS);
+ return IRQ_HANDLED;
+}
+
+static int __devinit tegra30_mc_probe(struct platform_device *pdev)
+{
+ struct resource *irq;
+ struct tegra30_mc *mc;
+ size_t bytes;
+ int err, i;
+ u32 intmask;
+
+ bytes = sizeof(*mc) + sizeof(u32) * ARRAY_SIZE(tegra30_mc_ctx);
+ mc = devm_kzalloc(&pdev->dev, bytes, GFP_KERNEL);
+ if (!mc)
+ return -ENOMEM;
+ mc->dev = &pdev->dev;
+
+ for (i = 0; i < ARRAY_SIZE(mc->regs); i++) {
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ if (!res)
+ return -ENODEV;
+ mc->regs[i] = devm_request_and_ioremap(&pdev->dev, res);
+ if (!mc->regs[i])
+ return -EBUSY;
+ }
+
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq)
+ return -ENODEV;
+ err = devm_request_irq(&pdev->dev, irq->start, tegra30_mc_isr,
+ IRQF_SHARED, dev_name(&pdev->dev), mc);
+ if (err)
+ return -ENODEV;
+
+ platform_set_drvdata(pdev, mc);
+
+ intmask = MC_INT_INVALID_SMMU_PAGE |
+ MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION;
+ mc_writel(mc, intmask, MC_INTMASK);
+ return 0;
+}
+
+static struct platform_driver tegra30_mc_driver = {
+ .probe = tegra30_mc_probe,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = tegra30_mc_of_match,
+ .pm = &tegra30_mc_pm,
+ },
+};
+module_platform_driver(tegra30_mc_driver);
+
+MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>");
+MODULE_DESCRIPTION("Tegra30 MC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 11e44386fa9b..f4b4dad77391 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -162,6 +162,7 @@ config MFD_TPS6586X
bool "TPS6586x Power Management chips"
depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS
select MFD_CORE
+ depends on REGULATOR
help
If you say yes here you get support for the TPS6586X series of
Power Management chips.
@@ -414,7 +415,7 @@ config MFD_MAX8925
select MFD_CORE
help
Say yes here to support for Maxim Semiconductor MAX8925. This is
- a Power Management IC. This driver provies common support for
+ a Power Management IC. This driver provides common support for
accessing the device, additional drivers must be enabled in order
to use the functionality of the device.
@@ -437,7 +438,7 @@ config MFD_MAX8998
help
Say yes here to support for Maxim Semiconductor MAX8998 and
National Semiconductor LP3974. This is a Power Management IC.
- This driver provies common support for accessing the device,
+ This driver provides common support for accessing the device,
additional drivers must be enabled in order to use the functionality
of the device.
@@ -448,7 +449,7 @@ config MFD_S5M_CORE
select REGMAP_I2C
help
Support for the Samsung Electronics S5M MFD series.
- This driver provies common support for accessing the device,
+ This driver provides common support for accessing the device,
additional drivers must be enabled in order to use the functionality
of the device
@@ -648,23 +649,6 @@ config EZX_PCAP
This enables the PCAP ASIC present on EZX Phones. This is
needed for MMC, TouchScreen, Sound, USB, etc..
-config AB5500_CORE
- bool "ST-Ericsson AB5500 Mixed Signal Power Management chip"
- depends on ABX500_CORE && MFD_DB5500_PRCMU
- select MFD_CORE
- help
- Select this option to enable access to AB5500 power management
- chip. This connects to the db5500 chip via the I2C bus via PRCMU.
- This chip embeds various other multimedia funtionalities as well.
-
-config AB5500_DEBUG
- bool "Enable debug info via debugfs"
- depends on AB5500_CORE && DEBUG_FS
- default y if DEBUG_FS
- help
- Select this option if you want debug information from the AB5500
- using the debug filesystem, debugfs.
-
config AB8500_CORE
bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
depends on GENERIC_HARDIRQS && ABX500_CORE
@@ -711,16 +695,6 @@ config MFD_DB8500_PRCMU
system controller running an XP70 microprocessor, which is accessed
through a register map.
-config MFD_DB5500_PRCMU
- bool "ST-Ericsson DB5500 Power Reset Control Management Unit"
- depends on UX500_SOC_DB5500
- select MFD_CORE
- help
- Select this option to enable support for the DB5500 Power Reset
- and Control Management Unit. This is basically an autonomous
- system controller running an XP70 microprocessor, which is accessed
- through a register map.
-
config MFD_CS5535
tristate "Support for CS5535 and CS5536 southbridge core functions"
select MFD_CORE
@@ -888,6 +862,16 @@ config MFD_ANATOP
MFD controller. This controller embeds regulator and
thermal devices for Freescale i.MX platforms.
+config MFD_PALMAS
+ bool "Support for the TI Palmas series chips"
+ select MFD_CORE
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ depends on I2C=y
+ help
+ If you say yes here you get support for the Palmas
+ series of PMIC chips from Texas Instruments.
+
endmenu
endif
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 05fa538c5efe..43672b87805a 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -87,15 +87,12 @@ obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o
obj-$(CONFIG_ABX500_CORE) += abx500-core.o
obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o
-obj-$(CONFIG_AB5500_CORE) += ab5500-core.o
-obj-$(CONFIG_AB5500_DEBUG) += ab5500-debugfs.o
obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o
obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
# ab8500-i2c need to come after db8500-prcmu (which provides the channel)
obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o
-obj-$(CONFIG_MFD_DB5500_PRCMU) += db5500-prcmu.o
obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
obj-$(CONFIG_LPC_SCH) += lpc_sch.o
@@ -113,6 +110,8 @@ obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
obj-$(CONFIG_MFD_TPS65090) += tps65090.o
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
+obj-$(CONFIG_MFD_PALMAS) += palmas.o
obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
obj-$(CONFIG_MFD_S5M_CORE) += s5m-core.o s5m-irq.o
obj-$(CONFIG_MFD_ANATOP) += anatop-mfd.o
+obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o
diff --git a/drivers/mfd/ab5500-core.c b/drivers/mfd/ab5500-core.c
deleted file mode 100644
index 54d0fe40845f..000000000000
--- a/drivers/mfd/ab5500-core.c
+++ /dev/null
@@ -1,1439 +0,0 @@
-/*
- * Copyright (C) 2007-2011 ST-Ericsson
- * License terms: GNU General Public License (GPL) version 2
- * Low-level core for exclusive access to the AB5500 IC on the I2C bus
- * and some basic chip-configuration.
- * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
- * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
- * Author: Mattias Wallin <mattias.wallin@stericsson.com>
- * Author: Rickard Andersson <rickard.andersson@stericsson.com>
- * Author: Karl Komierowski <karl.komierowski@stericsson.com>
- * Author: Bibek Basu <bibek.basu@stericsson.com>
- *
- * TODO: Event handling with irq_chip. Waiting for PRCMU fw support.
- */
-
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/random.h>
-#include <linux/mfd/abx500.h>
-#include <linux/mfd/abx500/ab5500.h>
-#include <linux/list.h>
-#include <linux/bitops.h>
-#include <linux/spinlock.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/db5500-prcmu.h>
-
-#include "ab5500-core.h"
-#include "ab5500-debugfs.h"
-
-#define AB5500_NUM_EVENT_REG 23
-#define AB5500_IT_LATCH0_REG 0x40
-#define AB5500_IT_MASK0_REG 0x60
-
-/*
- * Permissible register ranges for reading and writing per device and bank.
- *
- * The ranges must be listed in increasing address order, and no overlaps are
- * allowed. It is assumed that write permission implies read permission
- * (i.e. only RO and RW permissions should be used). Ranges with write
- * permission must not be split up.
- */
-
-#define NO_RANGE {.count = 0, .range = NULL,}
-static struct ab5500_i2c_banks ab5500_bank_ranges[AB5500_NUM_DEVICES] = {
- [AB5500_DEVID_USB] = {
- .nbanks = 1,
- .bank = (struct ab5500_i2c_ranges []) {
- {
- .bankid = AB5500_BANK_USB,
- .nranges = 12,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x01,
- .last = 0x01,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x80,
- .last = 0x83,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x87,
- .last = 0x8A,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x8B,
- .last = 0x8B,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x91,
- .last = 0x92,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x93,
- .last = 0x93,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x94,
- .last = 0x94,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0xA8,
- .last = 0xB0,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0xB2,
- .last = 0xB2,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0xB4,
- .last = 0xBC,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0xBF,
- .last = 0xBF,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0xC1,
- .last = 0xC5,
- .perm = AB5500_PERM_RO,
- },
- },
- },
- },
- },
- [AB5500_DEVID_ADC] = {
- .nbanks = 1,
- .bank = (struct ab5500_i2c_ranges []) {
- {
- .bankid = AB5500_BANK_ADC,
- .nranges = 6,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x1F,
- .last = 0x22,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x23,
- .last = 0x24,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x26,
- .last = 0x2D,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x2F,
- .last = 0x34,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x37,
- .last = 0x57,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x58,
- .last = 0x58,
- .perm = AB5500_PERM_RO,
- },
- },
- },
- },
- },
- [AB5500_DEVID_LEDS] = {
- .nbanks = 1,
- .bank = (struct ab5500_i2c_ranges []) {
- {
- .bankid = AB5500_BANK_LED,
- .nranges = 1,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x0C,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- },
- },
- [AB5500_DEVID_VIDEO] = {
- .nbanks = 1,
- .bank = (struct ab5500_i2c_ranges []) {
- {
- .bankid = AB5500_BANK_VDENC,
- .nranges = 12,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x08,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x09,
- .last = 0x09,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x0A,
- .last = 0x12,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x15,
- .last = 0x19,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x1B,
- .last = 0x21,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x27,
- .last = 0x2C,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x41,
- .last = 0x41,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x45,
- .last = 0x5B,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x5D,
- .last = 0x5D,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x69,
- .last = 0x69,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x6C,
- .last = 0x6D,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x80,
- .last = 0x81,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- },
- },
- [AB5500_DEVID_REGULATORS] = {
- .nbanks = 2,
- .bank = (struct ab5500_i2c_ranges []) {
- {
- .bankid = AB5500_BANK_STARTUP,
- .nranges = 12,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x01,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x1F,
- .last = 0x1F,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x2E,
- .last = 0x2E,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x2F,
- .last = 0x30,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x50,
- .last = 0x51,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x60,
- .last = 0x61,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x66,
- .last = 0x8A,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x8C,
- .last = 0x96,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0xAA,
- .last = 0xB4,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0xB7,
- .last = 0xBF,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0xC1,
- .last = 0xCA,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0xD3,
- .last = 0xE0,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- {
- .bankid = AB5500_BANK_SIM_USBSIM,
- .nranges = 1,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x13,
- .last = 0x19,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- },
- },
- [AB5500_DEVID_SIM] = {
- .nbanks = 1,
- .bank = (struct ab5500_i2c_ranges []) {
- {
- .bankid = AB5500_BANK_SIM_USBSIM,
- .nranges = 1,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x13,
- .last = 0x19,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- },
- },
- [AB5500_DEVID_RTC] = {
- .nbanks = 1,
- .bank = (struct ab5500_i2c_ranges []) {
- {
- .bankid = AB5500_BANK_RTC,
- .nranges = 2,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x04,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x06,
- .last = 0x0C,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- },
- },
- [AB5500_DEVID_CHARGER] = {
- .nbanks = 1,
- .bank = (struct ab5500_i2c_ranges []) {
- {
- .bankid = AB5500_BANK_CHG,
- .nranges = 2,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x11,
- .last = 0x11,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x12,
- .last = 0x1B,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- },
- },
- [AB5500_DEVID_FUELGAUGE] = {
- .nbanks = 1,
- .bank = (struct ab5500_i2c_ranges []) {
- {
- .bankid = AB5500_BANK_FG_BATTCOM_ACC,
- .nranges = 2,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x0B,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x0C,
- .last = 0x10,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- },
- },
- [AB5500_DEVID_VIBRATOR] = {
- .nbanks = 1,
- .bank = (struct ab5500_i2c_ranges []) {
- {
- .bankid = AB5500_BANK_VIBRA,
- .nranges = 2,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x10,
- .last = 0x13,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0xFE,
- .last = 0xFE,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- },
- },
- [AB5500_DEVID_CODEC] = {
- .nbanks = 1,
- .bank = (struct ab5500_i2c_ranges []) {
- {
- .bankid = AB5500_BANK_AUDIO_HEADSETUSB,
- .nranges = 2,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x48,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0xEB,
- .last = 0xFB,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- },
- },
- [AB5500_DEVID_POWER] = {
- .nbanks = 2,
- .bank = (struct ab5500_i2c_ranges []) {
- {
- .bankid = AB5500_BANK_STARTUP,
- .nranges = 1,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x30,
- .last = 0x30,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- {
- .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
- .nranges = 1,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x01,
- .last = 0x01,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- },
- },
-};
-
-#define AB5500_IRQ(bank, bit) ((bank) * 8 + (bit))
-
-/* I appologize for the resource names beeing a mix of upper case
- * and lower case but I want them to be exact as the documentation */
-static struct mfd_cell ab5500_devs[AB5500_NUM_DEVICES] = {
- [AB5500_DEVID_LEDS] = {
- .name = "ab5500-leds",
- .id = AB5500_DEVID_LEDS,
- },
- [AB5500_DEVID_POWER] = {
- .name = "ab5500-power",
- .id = AB5500_DEVID_POWER,
- },
- [AB5500_DEVID_REGULATORS] = {
- .name = "ab5500-regulator",
- .id = AB5500_DEVID_REGULATORS,
- },
- [AB5500_DEVID_SIM] = {
- .name = "ab5500-sim",
- .id = AB5500_DEVID_SIM,
- .num_resources = 1,
- .resources = (struct resource[]) {
- {
- .name = "SIMOFF",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(2, 0), /*rising*/
- .end = AB5500_IRQ(2, 1), /*falling*/
- },
- },
- },
- [AB5500_DEVID_RTC] = {
- .name = "ab5500-rtc",
- .id = AB5500_DEVID_RTC,
- .num_resources = 1,
- .resources = (struct resource[]) {
- {
- .name = "RTC_Alarm",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(1, 7),
- .end = AB5500_IRQ(1, 7),
- }
- },
- },
- [AB5500_DEVID_CHARGER] = {
- .name = "ab5500-charger",
- .id = AB5500_DEVID_CHARGER,
- },
- [AB5500_DEVID_ADC] = {
- .name = "ab5500-adc",
- .id = AB5500_DEVID_ADC,
- .num_resources = 10,
- .resources = (struct resource[]) {
- {
- .name = "TRIGGER-0",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(0, 0),
- .end = AB5500_IRQ(0, 0),
- },
- {
- .name = "TRIGGER-1",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(0, 1),
- .end = AB5500_IRQ(0, 1),
- },
- {
- .name = "TRIGGER-2",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(0, 2),
- .end = AB5500_IRQ(0, 2),
- },
- {
- .name = "TRIGGER-3",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(0, 3),
- .end = AB5500_IRQ(0, 3),
- },
- {
- .name = "TRIGGER-4",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(0, 4),
- .end = AB5500_IRQ(0, 4),
- },
- {
- .name = "TRIGGER-5",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(0, 5),
- .end = AB5500_IRQ(0, 5),
- },
- {
- .name = "TRIGGER-6",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(0, 6),
- .end = AB5500_IRQ(0, 6),
- },
- {
- .name = "TRIGGER-7",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(0, 7),
- .end = AB5500_IRQ(0, 7),
- },
- {
- .name = "TRIGGER-VBAT",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(0, 8),
- .end = AB5500_IRQ(0, 8),
- },
- {
- .name = "TRIGGER-VBAT-TXON",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(0, 9),
- .end = AB5500_IRQ(0, 9),
- },
- },
- },
- [AB5500_DEVID_FUELGAUGE] = {
- .name = "ab5500-fuelgauge",
- .id = AB5500_DEVID_FUELGAUGE,
- .num_resources = 6,
- .resources = (struct resource[]) {
- {
- .name = "Batt_attach",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(7, 5),
- .end = AB5500_IRQ(7, 5),
- },
- {
- .name = "Batt_removal",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(7, 6),
- .end = AB5500_IRQ(7, 6),
- },
- {
- .name = "UART_framing",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(7, 7),
- .end = AB5500_IRQ(7, 7),
- },
- {
- .name = "UART_overrun",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(8, 0),
- .end = AB5500_IRQ(8, 0),
- },
- {
- .name = "UART_Rdy_RX",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(8, 1),
- .end = AB5500_IRQ(8, 1),
- },
- {
- .name = "UART_Rdy_TX",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(8, 2),
- .end = AB5500_IRQ(8, 2),
- },
- },
- },
- [AB5500_DEVID_VIBRATOR] = {
- .name = "ab5500-vibrator",
- .id = AB5500_DEVID_VIBRATOR,
- },
- [AB5500_DEVID_CODEC] = {
- .name = "ab5500-codec",
- .id = AB5500_DEVID_CODEC,
- .num_resources = 3,
- .resources = (struct resource[]) {
- {
- .name = "audio_spkr1_ovc",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(9, 5),
- .end = AB5500_IRQ(9, 5),
- },
- {
- .name = "audio_plllocked",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(9, 6),
- .end = AB5500_IRQ(9, 6),
- },
- {
- .name = "audio_spkr2_ovc",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(17, 4),
- .end = AB5500_IRQ(17, 4),
- },
- },
- },
- [AB5500_DEVID_USB] = {
- .name = "ab5500-usb",
- .id = AB5500_DEVID_USB,
- .num_resources = 36,
- .resources = (struct resource[]) {
- {
- .name = "Link_Update",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(22, 1),
- .end = AB5500_IRQ(22, 1),
- },
- {
- .name = "DCIO",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(8, 3),
- .end = AB5500_IRQ(8, 4),
- },
- {
- .name = "VBUS_R",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(8, 5),
- .end = AB5500_IRQ(8, 5),
- },
- {
- .name = "VBUS_F",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(8, 6),
- .end = AB5500_IRQ(8, 6),
- },
- {
- .name = "CHGstate_10_PCVBUSchg",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(8, 7),
- .end = AB5500_IRQ(8, 7),
- },
- {
- .name = "DCIOreverse_ovc",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(9, 0),
- .end = AB5500_IRQ(9, 0),
- },
- {
- .name = "USBCharDetDone",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(9, 1),
- .end = AB5500_IRQ(9, 1),
- },
- {
- .name = "DCIO_no_limit",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(9, 2),
- .end = AB5500_IRQ(9, 2),
- },
- {
- .name = "USB_suspend",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(9, 3),
- .end = AB5500_IRQ(9, 3),
- },
- {
- .name = "DCIOreverse_fwdcurrent",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(9, 4),
- .end = AB5500_IRQ(9, 4),
- },
- {
- .name = "Vbus_Imeasmax_change",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(9, 5),
- .end = AB5500_IRQ(9, 6),
- },
- {
- .name = "OVV",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(14, 5),
- .end = AB5500_IRQ(14, 5),
- },
- {
- .name = "USBcharging_NOTok",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(15, 3),
- .end = AB5500_IRQ(15, 3),
- },
- {
- .name = "usb_adp_sensoroff",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(15, 6),
- .end = AB5500_IRQ(15, 6),
- },
- {
- .name = "usb_adp_probeplug",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(15, 7),
- .end = AB5500_IRQ(15, 7),
- },
- {
- .name = "usb_adp_sinkerror",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(16, 0),
- .end = AB5500_IRQ(16, 6),
- },
- {
- .name = "usb_adp_sourceerror",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(16, 1),
- .end = AB5500_IRQ(16, 1),
- },
- {
- .name = "usb_idgnd_r",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(16, 2),
- .end = AB5500_IRQ(16, 2),
- },
- {
- .name = "usb_idgnd_f",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(16, 3),
- .end = AB5500_IRQ(16, 3),
- },
- {
- .name = "usb_iddetR1",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(16, 4),
- .end = AB5500_IRQ(16, 5),
- },
- {
- .name = "usb_iddetR2",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(16, 6),
- .end = AB5500_IRQ(16, 7),
- },
- {
- .name = "usb_iddetR3",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(17, 0),
- .end = AB5500_IRQ(17, 1),
- },
- {
- .name = "usb_iddetR4",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(17, 2),
- .end = AB5500_IRQ(17, 3),
- },
- {
- .name = "CharTempWindowOk",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(17, 7),
- .end = AB5500_IRQ(18, 0),
- },
- {
- .name = "USB_SprDetect",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(18, 1),
- .end = AB5500_IRQ(18, 1),
- },
- {
- .name = "usb_adp_probe_unplug",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(18, 2),
- .end = AB5500_IRQ(18, 2),
- },
- {
- .name = "VBUSChDrop",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(18, 3),
- .end = AB5500_IRQ(18, 4),
- },
- {
- .name = "dcio_char_rec_done",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(18, 5),
- .end = AB5500_IRQ(18, 5),
- },
- {
- .name = "Charging_stopped_by_temp",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(18, 6),
- .end = AB5500_IRQ(18, 6),
- },
- {
- .name = "CHGstate_11_SafeModeVBUS",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(21, 1),
- .end = AB5500_IRQ(21, 2),
- },
- {
- .name = "CHGstate_12_comletedVBUS",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(21, 2),
- .end = AB5500_IRQ(21, 2),
- },
- {
- .name = "CHGstate_13_completedVBUS",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(21, 3),
- .end = AB5500_IRQ(21, 3),
- },
- {
- .name = "CHGstate_14_FullChgDCIO",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(21, 4),
- .end = AB5500_IRQ(21, 4),
- },
- {
- .name = "CHGstate_15_SafeModeDCIO",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(21, 5),
- .end = AB5500_IRQ(21, 5),
- },
- {
- .name = "CHGstate_16_OFFsuspendDCIO",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(21, 6),
- .end = AB5500_IRQ(21, 6),
- },
- {
- .name = "CHGstate_17_completedDCIO",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(21, 7),
- .end = AB5500_IRQ(21, 7),
- },
- },
- },
- [AB5500_DEVID_OTP] = {
- .name = "ab5500-otp",
- .id = AB5500_DEVID_OTP,
- },
- [AB5500_DEVID_VIDEO] = {
- .name = "ab5500-video",
- .id = AB5500_DEVID_VIDEO,
- .num_resources = 1,
- .resources = (struct resource[]) {
- {
- .name = "plugTVdet",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(22, 2),
- .end = AB5500_IRQ(22, 2),
- },
- },
- },
- [AB5500_DEVID_DBIECI] = {
- .name = "ab5500-dbieci",
- .id = AB5500_DEVID_DBIECI,
- .num_resources = 10,
- .resources = (struct resource[]) {
- {
- .name = "COLL",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(14, 0),
- .end = AB5500_IRQ(14, 0),
- },
- {
- .name = "RESERR",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(14, 1),
- .end = AB5500_IRQ(14, 1),
- },
- {
- .name = "FRAERR",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(14, 2),
- .end = AB5500_IRQ(14, 2),
- },
- {
- .name = "COMERR",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(14, 3),
- .end = AB5500_IRQ(14, 3),
- },
- {
- .name = "BSI_indicator",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(14, 4),
- .end = AB5500_IRQ(14, 4),
- },
- {
- .name = "SPDSET",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(14, 6),
- .end = AB5500_IRQ(14, 6),
- },
- {
- .name = "DSENT",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(14, 7),
- .end = AB5500_IRQ(14, 7),
- },
- {
- .name = "DREC",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(15, 0),
- .end = AB5500_IRQ(15, 0),
- },
- {
- .name = "ACCINT",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(15, 1),
- .end = AB5500_IRQ(15, 1),
- },
- {
- .name = "NOPINT",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(15, 2),
- .end = AB5500_IRQ(15, 2),
- },
- },
- },
- [AB5500_DEVID_ONSWA] = {
- .name = "ab5500-onswa",
- .id = AB5500_DEVID_ONSWA,
- .num_resources = 2,
- .resources = (struct resource[]) {
- {
- .name = "ONSWAn_rising",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(1, 3),
- .end = AB5500_IRQ(1, 3),
- },
- {
- .name = "ONSWAn_falling",
- .flags = IORESOURCE_IRQ,
- .start = AB5500_IRQ(1, 4),
- .end = AB5500_IRQ(1, 4),
- },
- },
- },
-};
-
-/*
- * Functionality for getting/setting register values.
- */
-int ab5500_get_register_interruptible_raw(struct ab5500 *ab,
- u8 bank, u8 reg,
- u8 *value)
-{
- int err;
-
- if (bank >= AB5500_NUM_BANKS)
- return -EINVAL;
-
- err = mutex_lock_interruptible(&ab->access_mutex);
- if (err)
- return err;
- err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr, reg, value, 1);
-
- mutex_unlock(&ab->access_mutex);
- return err;
-}
-
-static int get_register_page_interruptible(struct ab5500 *ab, u8 bank,
- u8 first_reg, u8 *regvals, u8 numregs)
-{
- int err;
-
- if (bank >= AB5500_NUM_BANKS)
- return -EINVAL;
-
- err = mutex_lock_interruptible(&ab->access_mutex);
- if (err)
- return err;
-
- while (numregs) {
- /* The hardware limit for get page is 4 */
- u8 curnum = min_t(u8, numregs, 4u);
-
- err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr,
- first_reg, regvals, curnum);
- if (err)
- goto out;
-
- numregs -= curnum;
- first_reg += curnum;
- regvals += curnum;
- }
-
-out:
- mutex_unlock(&ab->access_mutex);
- return err;
-}
-
-int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank,
- u8 reg, u8 bitmask, u8 bitvalues)
-{
- int err = 0;
-
- if (bank >= AB5500_NUM_BANKS)
- return -EINVAL;
-
- if (bitmask) {
- u8 buf;
-
- err = mutex_lock_interruptible(&ab->access_mutex);
- if (err)
- return err;
-
- if (bitmask == 0xFF) /* No need to read in this case. */
- buf = bitvalues;
- else { /* Read and modify the register value. */
- err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr,
- reg, &buf, 1);
- if (err)
- return err;
-
- buf = ((~bitmask & buf) | (bitmask & bitvalues));
- }
- /* Write the new value. */
- err = db5500_prcmu_abb_write(bankinfo[bank].slave_addr, reg,
- &buf, 1);
-
- mutex_unlock(&ab->access_mutex);
- }
- return err;
-}
-
-static int
-set_register_interruptible(struct ab5500 *ab, u8 bank, u8 reg, u8 value)
-{
- return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg,
- 0xff, value);
-}
-
-/*
- * Read/write permission checking functions.
- */
-static const struct ab5500_i2c_ranges *get_bankref(u8 devid, u8 bank)
-{
- u8 i;
-
- if (devid < AB5500_NUM_DEVICES) {
- for (i = 0; i < ab5500_bank_ranges[devid].nbanks; i++) {
- if (ab5500_bank_ranges[devid].bank[i].bankid == bank)
- return &ab5500_bank_ranges[devid].bank[i];
- }
- }
- return NULL;
-}
-
-static bool page_write_allowed(u8 devid, u8 bank, u8 first_reg, u8 last_reg)
-{
- u8 i; /* range loop index */
- const struct ab5500_i2c_ranges *bankref;
-
- bankref = get_bankref(devid, bank);
- if (bankref == NULL || last_reg < first_reg)
- return false;
-
- for (i = 0; i < bankref->nranges; i++) {
- if (first_reg < bankref->range[i].first)
- break;
- if ((last_reg <= bankref->range[i].last) &&
- (bankref->range[i].perm & AB5500_PERM_WR))
- return true;
- }
- return false;
-}
-
-static bool reg_write_allowed(u8 devid, u8 bank, u8 reg)
-{
- return page_write_allowed(devid, bank, reg, reg);
-}
-
-static bool page_read_allowed(u8 devid, u8 bank, u8 first_reg, u8 last_reg)
-{
- u8 i;
- const struct ab5500_i2c_ranges *bankref;
-
- bankref = get_bankref(devid, bank);
- if (bankref == NULL || last_reg < first_reg)
- return false;
-
-
- /* Find the range (if it exists in the list) that includes first_reg. */
- for (i = 0; i < bankref->nranges; i++) {
- if (first_reg < bankref->range[i].first)
- return false;
- if (first_reg <= bankref->range[i].last)
- break;
- }
- /* Make sure that the entire range up to and including last_reg is
- * readable. This may span several of the ranges in the list.
- */
- while ((i < bankref->nranges) &&
- (bankref->range[i].perm & AB5500_PERM_RD)) {
- if (last_reg <= bankref->range[i].last)
- return true;
- if ((++i >= bankref->nranges) ||
- (bankref->range[i].first !=
- (bankref->range[i - 1].last + 1))) {
- break;
- }
- }
- return false;
-}
-
-static bool reg_read_allowed(u8 devid, u8 bank, u8 reg)
-{
- return page_read_allowed(devid, bank, reg, reg);
-}
-
-
-/*
- * The exported register access functionality.
- */
-static int ab5500_get_chip_id(struct device *dev)
-{
- struct ab5500 *ab = dev_get_drvdata(dev->parent);
-
- return (int)ab->chip_id;
-}
-
-static int ab5500_mask_and_set_register_interruptible(struct device *dev,
- u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
-{
- struct ab5500 *ab;
- struct platform_device *pdev = to_platform_device(dev);
-
- if ((AB5500_NUM_BANKS <= bank) ||
- !reg_write_allowed(pdev->id, bank, reg))
- return -EINVAL;
-
- ab = dev_get_drvdata(dev->parent);
- return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg,
- bitmask, bitvalues);
-}
-
-static int ab5500_set_register_interruptible(struct device *dev, u8 bank,
- u8 reg, u8 value)
-{
- return ab5500_mask_and_set_register_interruptible(dev, bank, reg, 0xFF,
- value);
-}
-
-static int ab5500_get_register_interruptible(struct device *dev, u8 bank,
- u8 reg, u8 *value)
-{
- struct ab5500 *ab;
- struct platform_device *pdev = to_platform_device(dev);
-
- if ((AB5500_NUM_BANKS <= bank) ||
- !reg_read_allowed(pdev->id, bank, reg))
- return -EINVAL;
-
- ab = dev_get_drvdata(dev->parent);
- return ab5500_get_register_interruptible_raw(ab, bank, reg, value);
-}
-
-static int ab5500_get_register_page_interruptible(struct device *dev, u8 bank,
- u8 first_reg, u8 *regvals, u8 numregs)
-{
- struct ab5500 *ab;
- struct platform_device *pdev = to_platform_device(dev);
-
- if ((AB5500_NUM_BANKS <= bank) ||
- !page_read_allowed(pdev->id, bank,
- first_reg, (first_reg + numregs - 1)))
- return -EINVAL;
-
- ab = dev_get_drvdata(dev->parent);
- return get_register_page_interruptible(ab, bank, first_reg, regvals,
- numregs);
-}
-
-static int
-ab5500_event_registers_startup_state_get(struct device *dev, u8 *event)
-{
- struct ab5500 *ab;
-
- ab = dev_get_drvdata(dev->parent);
- if (!ab->startup_events_read)
- return -EAGAIN; /* Try again later */
-
- memcpy(event, ab->startup_events, AB5500_NUM_EVENT_REG);
- return 0;
-}
-
-static struct abx500_ops ab5500_ops = {
- .get_chip_id = ab5500_get_chip_id,
- .get_register = ab5500_get_register_interruptible,
- .set_register = ab5500_set_register_interruptible,
- .get_register_page = ab5500_get_register_page_interruptible,
- .set_register_page = NULL,
- .mask_and_set_register = ab5500_mask_and_set_register_interruptible,
- .event_registers_startup_state_get =
- ab5500_event_registers_startup_state_get,
- .startup_irq_enabled = NULL,
-};
-
-/*
- * ab5500_setup : Basic set-up, datastructure creation/destruction
- * and I2C interface.This sets up a default config
- * in the AB5500 chip so that it will work as expected.
- * @ab : Pointer to ab5500 structure
- * @settings : Pointer to struct abx500_init_settings
- * @size : Size of init data
- */
-static int __init ab5500_setup(struct ab5500 *ab,
- struct abx500_init_settings *settings, unsigned int size)
-{
- int err = 0;
- int i;
-
- for (i = 0; i < size; i++) {
- err = ab5500_mask_and_set_register_interruptible_raw(ab,
- settings[i].bank,
- settings[i].reg,
- 0xFF, settings[i].setting);
- if (err)
- goto exit_no_setup;
-
- /* If event mask register update the event mask in ab5500 */
- if ((settings[i].bank == AB5500_BANK_IT) &&
- (AB5500_MASK_BASE <= settings[i].reg) &&
- (settings[i].reg <= AB5500_MASK_END)) {
- ab->mask[settings[i].reg - AB5500_MASK_BASE] =
- settings[i].setting;
- }
- }
-exit_no_setup:
- return err;
-}
-
-struct ab_family_id {
- u8 id;
- char *name;
-};
-
-static const struct ab_family_id ids[] __initdata = {
- /* AB5500 */
- {
- .id = AB5500_1_0,
- .name = "1.0"
- },
- {
- .id = AB5500_1_1,
- .name = "1.1"
- },
- /* Terminator */
- {
- .id = 0x00,
- }
-};
-
-static int __init ab5500_probe(struct platform_device *pdev)
-{
- struct ab5500 *ab;
- struct ab5500_platform_data *ab5500_plf_data =
- pdev->dev.platform_data;
- int err;
- int i;
-
- ab = kzalloc(sizeof(struct ab5500), GFP_KERNEL);
- if (!ab) {
- dev_err(&pdev->dev,
- "could not allocate ab5500 device\n");
- return -ENOMEM;
- }
-
- /* Initialize data structure */
- mutex_init(&ab->access_mutex);
- mutex_init(&ab->irq_lock);
- ab->dev = &pdev->dev;
-
- platform_set_drvdata(pdev, ab);
-
- /* Read chip ID register */
- err = ab5500_get_register_interruptible_raw(ab,
- AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
- AB5500_CHIP_ID, &ab->chip_id);
- if (err) {
- dev_err(&pdev->dev, "could not communicate with the analog "
- "baseband chip\n");
- goto exit_no_detect;
- }
-
- for (i = 0; ids[i].id != 0x0; i++) {
- if (ids[i].id == ab->chip_id) {
- snprintf(&ab->chip_name[0], sizeof(ab->chip_name) - 1,
- "AB5500 %s", ids[i].name);
- break;
- }
- }
- if (ids[i].id == 0x0) {
- dev_err(&pdev->dev, "unknown analog baseband chip id: 0x%x\n",
- ab->chip_id);
- dev_err(&pdev->dev, "driver not started!\n");
- goto exit_no_detect;
- }
-
- /* Clear and mask all interrupts */
- for (i = 0; i < AB5500_NUM_IRQ_REGS; i++) {
- u8 latchreg = AB5500_IT_LATCH0_REG + i;
- u8 maskreg = AB5500_IT_MASK0_REG + i;
- u8 val;
-
- ab5500_get_register_interruptible_raw(ab, AB5500_BANK_IT,
- latchreg, &val);
- set_register_interruptible(ab, AB5500_BANK_IT, maskreg, 0xff);
- ab->mask[i] = ab->oldmask[i] = 0xff;
- }
-
- err = abx500_register_ops(&pdev->dev, &ab5500_ops);
- if (err) {
- dev_err(&pdev->dev, "ab5500_register ops error\n");
- goto exit_no_detect;
- }
-
- /* Set up and register the platform devices. */
- for (i = 0; i < AB5500_NUM_DEVICES; i++) {
- ab5500_devs[i].platform_data = ab5500_plf_data->dev_data[i];
- ab5500_devs[i].pdata_size =
- sizeof(ab5500_plf_data->dev_data[i]);
- }
-
- err = mfd_add_devices(&pdev->dev, 0, ab5500_devs,
- ARRAY_SIZE(ab5500_devs), NULL,
- ab5500_plf_data->irq.base);
- if (err) {
- dev_err(&pdev->dev, "ab5500_mfd_add_device error\n");
- goto exit_no_detect;
- }
-
- err = ab5500_setup(ab, ab5500_plf_data->init_settings,
- ab5500_plf_data->init_settings_sz);
- if (err) {
- dev_err(&pdev->dev, "ab5500_setup error\n");
- goto exit_no_detect;
- }
-
- ab5500_setup_debugfs(ab);
-
- dev_info(&pdev->dev, "detected AB chip: %s\n", &ab->chip_name[0]);
- return 0;
-
-exit_no_detect:
- kfree(ab);
- return err;
-}
-
-static int __exit ab5500_remove(struct platform_device *pdev)
-{
- struct ab5500 *ab = platform_get_drvdata(pdev);
-
- ab5500_remove_debugfs();
- mfd_remove_devices(&pdev->dev);
- kfree(ab);
- return 0;
-}
-
-static struct platform_driver ab5500_driver = {
- .driver = {
- .name = "ab5500-core",
- .owner = THIS_MODULE,
- },
- .remove = __exit_p(ab5500_remove),
-};
-
-static int __init ab5500_core_init(void)
-{
- return platform_driver_probe(&ab5500_driver, ab5500_probe);
-}
-
-static void __exit ab5500_core_exit(void)
-{
- platform_driver_unregister(&ab5500_driver);
-}
-
-subsys_initcall(ab5500_core_init);
-module_exit(ab5500_core_exit);
-
-MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
-MODULE_DESCRIPTION("AB5500 core driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ab5500-debugfs.c b/drivers/mfd/ab5500-debugfs.c
deleted file mode 100644
index 72006940937a..000000000000
--- a/drivers/mfd/ab5500-debugfs.c
+++ /dev/null
@@ -1,807 +0,0 @@
-/*
- * Copyright (C) 2011 ST-Ericsson
- * License terms: GNU General Public License (GPL) version 2
- * Debugfs support for the AB5500 MFD driver
- */
-
-#include <linux/module.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/mfd/abx500.h>
-#include <linux/mfd/abx500/ab5500.h>
-#include <linux/uaccess.h>
-
-#include "ab5500-core.h"
-#include "ab5500-debugfs.h"
-
-static struct ab5500_i2c_ranges ab5500_reg_ranges[AB5500_NUM_BANKS] = {
- [AB5500_BANK_LED] = {
- .bankid = AB5500_BANK_LED,
- .nranges = 1,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x0C,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- [AB5500_BANK_ADC] = {
- .bankid = AB5500_BANK_ADC,
- .nranges = 6,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x1F,
- .last = 0x22,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x23,
- .last = 0x24,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x26,
- .last = 0x2D,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x2F,
- .last = 0x34,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x37,
- .last = 0x57,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x58,
- .last = 0x58,
- .perm = AB5500_PERM_RO,
- },
- },
- },
- [AB5500_BANK_RTC] = {
- .bankid = AB5500_BANK_RTC,
- .nranges = 2,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x04,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x06,
- .last = 0x0C,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- [AB5500_BANK_STARTUP] = {
- .bankid = AB5500_BANK_STARTUP,
- .nranges = 12,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x01,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x1F,
- .last = 0x1F,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x2E,
- .last = 0x2E,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x2F,
- .last = 0x30,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x50,
- .last = 0x51,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x60,
- .last = 0x61,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x66,
- .last = 0x8A,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x8C,
- .last = 0x96,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0xAA,
- .last = 0xB4,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0xB7,
- .last = 0xBF,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0xC1,
- .last = 0xCA,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0xD3,
- .last = 0xE0,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- [AB5500_BANK_DBI_ECI] = {
- .bankid = AB5500_BANK_DBI_ECI,
- .nranges = 3,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x07,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x10,
- .last = 0x10,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x13,
- .last = 0x13,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- [AB5500_BANK_CHG] = {
- .bankid = AB5500_BANK_CHG,
- .nranges = 2,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x11,
- .last = 0x11,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x12,
- .last = 0x1B,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- [AB5500_BANK_FG_BATTCOM_ACC] = {
- .bankid = AB5500_BANK_FG_BATTCOM_ACC,
- .nranges = 2,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x0B,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x0C,
- .last = 0x10,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- [AB5500_BANK_USB] = {
- .bankid = AB5500_BANK_USB,
- .nranges = 12,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x01,
- .last = 0x01,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x80,
- .last = 0x83,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x87,
- .last = 0x8A,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x8B,
- .last = 0x8B,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x91,
- .last = 0x92,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x93,
- .last = 0x93,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x94,
- .last = 0x94,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0xA8,
- .last = 0xB0,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0xB2,
- .last = 0xB2,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0xB4,
- .last = 0xBC,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0xBF,
- .last = 0xBF,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0xC1,
- .last = 0xC5,
- .perm = AB5500_PERM_RO,
- },
- },
- },
- [AB5500_BANK_IT] = {
- .bankid = AB5500_BANK_IT,
- .nranges = 4,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x02,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x20,
- .last = 0x36,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x40,
- .last = 0x56,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x60,
- .last = 0x76,
- .perm = AB5500_PERM_RO,
- },
- },
- },
- [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = {
- .bankid = AB5500_BANK_VDDDIG_IO_I2C_CLK_TST,
- .nranges = 7,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x02,
- .last = 0x02,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x12,
- .last = 0x12,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x30,
- .last = 0x34,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x40,
- .last = 0x44,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x50,
- .last = 0x54,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x60,
- .last = 0x64,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x70,
- .last = 0x74,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = {
- .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
- .nranges = 13,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x01,
- .last = 0x01,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x02,
- .last = 0x02,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x0D,
- .last = 0x0F,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x1C,
- .last = 0x1C,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x1E,
- .last = 0x1E,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x20,
- .last = 0x21,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x25,
- .last = 0x25,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x28,
- .last = 0x2A,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x30,
- .last = 0x33,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x40,
- .last = 0x43,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x50,
- .last = 0x53,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x60,
- .last = 0x63,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x70,
- .last = 0x73,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- [AB5500_BANK_VIBRA] = {
- .bankid = AB5500_BANK_VIBRA,
- .nranges = 2,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x10,
- .last = 0x13,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0xFE,
- .last = 0xFE,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- [AB5500_BANK_AUDIO_HEADSETUSB] = {
- .bankid = AB5500_BANK_AUDIO_HEADSETUSB,
- .nranges = 2,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x48,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0xEB,
- .last = 0xFB,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- [AB5500_BANK_SIM_USBSIM] = {
- .bankid = AB5500_BANK_SIM_USBSIM,
- .nranges = 1,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x13,
- .last = 0x19,
- .perm = AB5500_PERM_RW,
- },
- },
- },
- [AB5500_BANK_VDENC] = {
- .bankid = AB5500_BANK_VDENC,
- .nranges = 12,
- .range = (struct ab5500_reg_range[]) {
- {
- .first = 0x00,
- .last = 0x08,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x09,
- .last = 0x09,
- .perm = AB5500_PERM_RO,
- },
- {
- .first = 0x0A,
- .last = 0x12,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x15,
- .last = 0x19,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x1B,
- .last = 0x21,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x27,
- .last = 0x2C,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x41,
- .last = 0x41,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x45,
- .last = 0x5B,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x5D,
- .last = 0x5D,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x69,
- .last = 0x69,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x6C,
- .last = 0x6D,
- .perm = AB5500_PERM_RW,
- },
- {
- .first = 0x80,
- .last = 0x81,
- .perm = AB5500_PERM_RW,
- },
- },
- },
-};
-
-static int ab5500_registers_print(struct seq_file *s, void *p)
-{
- struct ab5500 *ab = s->private;
- unsigned int i;
- u8 bank = (u8)ab->debug_bank;
-
- seq_printf(s, "ab5500 register values:\n");
- for (bank = 0; bank < AB5500_NUM_BANKS; bank++) {
- seq_printf(s, " bank %u, %s (0x%x):\n", bank,
- bankinfo[bank].name,
- bankinfo[bank].slave_addr);
- for (i = 0; i < ab5500_reg_ranges[bank].nranges; i++) {
- u8 reg;
- int err;
-
- for (reg = ab5500_reg_ranges[bank].range[i].first;
- reg <= ab5500_reg_ranges[bank].range[i].last;
- reg++) {
- u8 value;
-
- err = ab5500_get_register_interruptible_raw(ab,
- bank, reg,
- &value);
- if (err < 0) {
- dev_err(ab->dev, "get_reg failed %d"
- "bank 0x%x reg 0x%x\n",
- err, bank, reg);
- return err;
- }
-
- err = seq_printf(s, "[%d/0x%02X]: 0x%02X\n",
- bank, reg, value);
- if (err < 0) {
- dev_err(ab->dev,
- "seq_printf overflow\n");
- /*
- * Error is not returned here since
- * the output is wanted in any case
- */
- return 0;
- }
- }
- }
- }
- return 0;
-}
-
-static int ab5500_registers_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab5500_registers_print, inode->i_private);
-}
-
-static const struct file_operations ab5500_registers_fops = {
- .open = ab5500_registers_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int ab5500_bank_print(struct seq_file *s, void *p)
-{
- struct ab5500 *ab = s->private;
-
- seq_printf(s, "%d\n", ab->debug_bank);
- return 0;
-}
-
-static int ab5500_bank_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab5500_bank_print, inode->i_private);
-}
-
-static ssize_t ab5500_bank_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
- char buf[32];
- int buf_size;
- unsigned long user_bank;
- int err;
-
- /* Get userspace string and assure termination */
- buf_size = min(count, (sizeof(buf) - 1));
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- buf[buf_size] = 0;
-
- err = strict_strtoul(buf, 0, &user_bank);
- if (err)
- return -EINVAL;
-
- if (user_bank >= AB5500_NUM_BANKS) {
- dev_err(ab->dev,
- "debugfs error input > number of banks\n");
- return -EINVAL;
- }
-
- ab->debug_bank = user_bank;
-
- return buf_size;
-}
-
-static int ab5500_address_print(struct seq_file *s, void *p)
-{
- struct ab5500 *ab = s->private;
-
- seq_printf(s, "0x%02X\n", ab->debug_address);
- return 0;
-}
-
-static int ab5500_address_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab5500_address_print, inode->i_private);
-}
-
-static ssize_t ab5500_address_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
- char buf[32];
- int buf_size;
- unsigned long user_address;
- int err;
-
- /* Get userspace string and assure termination */
- buf_size = min(count, (sizeof(buf) - 1));
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- buf[buf_size] = 0;
-
- err = strict_strtoul(buf, 0, &user_address);
- if (err)
- return -EINVAL;
- if (user_address > 0xff) {
- dev_err(ab->dev,
- "debugfs error input > 0xff\n");
- return -EINVAL;
- }
- ab->debug_address = user_address;
- return buf_size;
-}
-
-static int ab5500_val_print(struct seq_file *s, void *p)
-{
- struct ab5500 *ab = s->private;
- int err;
- u8 regvalue;
-
- err = ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank,
- (u8)ab->debug_address, &regvalue);
- if (err) {
- dev_err(ab->dev, "get_reg failed %d, bank 0x%x"
- ", reg 0x%x\n", err, ab->debug_bank,
- ab->debug_address);
- return -EINVAL;
- }
- seq_printf(s, "0x%02X\n", regvalue);
-
- return 0;
-}
-
-static int ab5500_val_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab5500_val_print, inode->i_private);
-}
-
-static ssize_t ab5500_val_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
- char buf[32];
- int buf_size;
- unsigned long user_val;
- int err;
- u8 regvalue;
-
- /* Get userspace string and assure termination */
- buf_size = min(count, (sizeof(buf)-1));
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- buf[buf_size] = 0;
-
- err = strict_strtoul(buf, 0, &user_val);
- if (err)
- return -EINVAL;
- if (user_val > 0xff) {
- dev_err(ab->dev,
- "debugfs error input > 0xff\n");
- return -EINVAL;
- }
- err = ab5500_mask_and_set_register_interruptible_raw(
- ab, (u8)ab->debug_bank,
- (u8)ab->debug_address, 0xFF, (u8)user_val);
- if (err)
- return -EINVAL;
-
- ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank,
- (u8)ab->debug_address, &regvalue);
- if (err)
- return -EINVAL;
-
- return buf_size;
-}
-
-static const struct file_operations ab5500_bank_fops = {
- .open = ab5500_bank_open,
- .write = ab5500_bank_write,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static const struct file_operations ab5500_address_fops = {
- .open = ab5500_address_open,
- .write = ab5500_address_write,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static const struct file_operations ab5500_val_fops = {
- .open = ab5500_val_open,
- .write = ab5500_val_write,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static struct dentry *ab5500_dir;
-static struct dentry *ab5500_reg_file;
-static struct dentry *ab5500_bank_file;
-static struct dentry *ab5500_address_file;
-static struct dentry *ab5500_val_file;
-
-void __init ab5500_setup_debugfs(struct ab5500 *ab)
-{
- ab->debug_bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP;
- ab->debug_address = AB5500_CHIP_ID;
-
- ab5500_dir = debugfs_create_dir("ab5500", NULL);
- if (!ab5500_dir)
- goto exit_no_debugfs;
-
- ab5500_reg_file = debugfs_create_file("all-bank-registers",
- S_IRUGO, ab5500_dir, ab, &ab5500_registers_fops);
- if (!ab5500_reg_file)
- goto exit_destroy_dir;
-
- ab5500_bank_file = debugfs_create_file("register-bank",
- (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_bank_fops);
- if (!ab5500_bank_file)
- goto exit_destroy_reg;
-
- ab5500_address_file = debugfs_create_file("register-address",
- (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_address_fops);
- if (!ab5500_address_file)
- goto exit_destroy_bank;
-
- ab5500_val_file = debugfs_create_file("register-value",
- (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_val_fops);
- if (!ab5500_val_file)
- goto exit_destroy_address;
-
- return;
-
-exit_destroy_address:
- debugfs_remove(ab5500_address_file);
-exit_destroy_bank:
- debugfs_remove(ab5500_bank_file);
-exit_destroy_reg:
- debugfs_remove(ab5500_reg_file);
-exit_destroy_dir:
- debugfs_remove(ab5500_dir);
-exit_no_debugfs:
- dev_err(ab->dev, "failed to create debugfs entries.\n");
- return;
-}
-
-void __exit ab5500_remove_debugfs(void)
-{
- debugfs_remove(ab5500_val_file);
- debugfs_remove(ab5500_address_file);
- debugfs_remove(ab5500_bank_file);
- debugfs_remove(ab5500_reg_file);
- debugfs_remove(ab5500_dir);
-}
diff --git a/drivers/mfd/ab5500-debugfs.h b/drivers/mfd/ab5500-debugfs.h
deleted file mode 100644
index 7330a9b6afa6..000000000000
--- a/drivers/mfd/ab5500-debugfs.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2011 ST-Ericsson
- * License terms: GNU General Public License (GPL) version 2
- * Debugfs interface to the AB5500 core driver
- */
-
-#ifdef CONFIG_DEBUG_FS
-
-void ab5500_setup_debugfs(struct ab5500 *ab);
-void ab5500_remove_debugfs(void);
-
-#else /* !CONFIG_DEBUG_FS */
-
-static inline void ab5500_setup_debugfs(struct ab5500 *ab)
-{
-}
-
-static inline void ab5500_remove_debugfs(void)
-{
-}
-
-#endif
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c
index 7ff313fe9fb1..7776aff46269 100644
--- a/drivers/mfd/da9052-core.c
+++ b/drivers/mfd/da9052-core.c
@@ -659,12 +659,11 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
ret = regmap_add_irq_chip(da9052->regmap, da9052->chip_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
da9052->irq_base, &da9052_regmap_irq_chip,
- NULL);
+ &da9052->irq_data);
if (ret < 0)
goto regmap_err;
- desc = irq_to_desc(da9052->chip_irq);
- da9052->irq_base = regmap_irq_chip_get_base(desc->action->dev_id);
+ da9052->irq_base = regmap_irq_chip_get_base(da9052->irq_data);
ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info,
ARRAY_SIZE(da9052_subdev_info), NULL, 0);
@@ -681,8 +680,7 @@ regmap_err:
void da9052_device_exit(struct da9052 *da9052)
{
- regmap_del_irq_chip(da9052->chip_irq,
- irq_get_irq_data(da9052->irq_base)->chip_data);
+ regmap_del_irq_chip(da9052->chip_irq, da9052->irq_data);
mfd_remove_devices(da9052->dev);
}
diff --git a/drivers/mfd/db5500-prcmu.c b/drivers/mfd/db5500-prcmu.c
deleted file mode 100644
index bb115b2f04e9..000000000000
--- a/drivers/mfd/db5500-prcmu.c
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License v2
- * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
- *
- * U5500 PRCM Unit interface driver
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/completion.h>
-#include <linux/irq.h>
-#include <linux/jiffies.h>
-#include <linux/bitops.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/dbx500-prcmu.h>
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include <mach/db5500-regs.h>
-#include "dbx500-prcmu-regs.h"
-
-#define _PRCM_MB_HEADER (tcdm_base + 0xFE8)
-#define PRCM_REQ_MB0_HEADER (_PRCM_MB_HEADER + 0x0)
-#define PRCM_REQ_MB1_HEADER (_PRCM_MB_HEADER + 0x1)
-#define PRCM_REQ_MB2_HEADER (_PRCM_MB_HEADER + 0x2)
-#define PRCM_REQ_MB3_HEADER (_PRCM_MB_HEADER + 0x3)
-#define PRCM_REQ_MB4_HEADER (_PRCM_MB_HEADER + 0x4)
-#define PRCM_REQ_MB5_HEADER (_PRCM_MB_HEADER + 0x5)
-#define PRCM_REQ_MB6_HEADER (_PRCM_MB_HEADER + 0x6)
-#define PRCM_REQ_MB7_HEADER (_PRCM_MB_HEADER + 0x7)
-#define PRCM_ACK_MB0_HEADER (_PRCM_MB_HEADER + 0x8)
-#define PRCM_ACK_MB1_HEADER (_PRCM_MB_HEADER + 0x9)
-#define PRCM_ACK_MB2_HEADER (_PRCM_MB_HEADER + 0xa)
-#define PRCM_ACK_MB3_HEADER (_PRCM_MB_HEADER + 0xb)
-#define PRCM_ACK_MB4_HEADER (_PRCM_MB_HEADER + 0xc)
-#define PRCM_ACK_MB5_HEADER (_PRCM_MB_HEADER + 0xd)
-#define PRCM_ACK_MB6_HEADER (_PRCM_MB_HEADER + 0xe)
-#define PRCM_ACK_MB7_HEADER (_PRCM_MB_HEADER + 0xf)
-
-/* Req Mailboxes */
-#define PRCM_REQ_MB0 (tcdm_base + 0xFD8)
-#define PRCM_REQ_MB1 (tcdm_base + 0xFCC)
-#define PRCM_REQ_MB2 (tcdm_base + 0xFC4)
-#define PRCM_REQ_MB3 (tcdm_base + 0xFC0)
-#define PRCM_REQ_MB4 (tcdm_base + 0xF98)
-#define PRCM_REQ_MB5 (tcdm_base + 0xF90)
-#define PRCM_REQ_MB6 (tcdm_base + 0xF8C)
-#define PRCM_REQ_MB7 (tcdm_base + 0xF84)
-
-/* Ack Mailboxes */
-#define PRCM_ACK_MB0 (tcdm_base + 0xF38)
-#define PRCM_ACK_MB1 (tcdm_base + 0xF30)
-#define PRCM_ACK_MB2 (tcdm_base + 0xF24)
-#define PRCM_ACK_MB3 (tcdm_base + 0xF20)
-#define PRCM_ACK_MB4 (tcdm_base + 0xF1C)
-#define PRCM_ACK_MB5 (tcdm_base + 0xF14)
-#define PRCM_ACK_MB6 (tcdm_base + 0xF0C)
-#define PRCM_ACK_MB7 (tcdm_base + 0xF08)
-
-enum mb_return_code {
- RC_SUCCESS,
- RC_FAIL,
-};
-
-/* Mailbox 0 headers. */
-enum mb0_header {
- /* request */
- RMB0H_PWR_STATE_TRANS = 1,
- RMB0H_WAKE_UP_CFG,
- RMB0H_RD_WAKE_UP_ACK,
- /* acknowledge */
- AMB0H_WAKE_UP = 1,
-};
-
-/* Mailbox 5 headers. */
-enum mb5_header {
- MB5H_I2C_WRITE = 1,
- MB5H_I2C_READ,
-};
-
-/* Request mailbox 5 fields. */
-#define PRCM_REQ_MB5_I2C_SLAVE (PRCM_REQ_MB5 + 0)
-#define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 1)
-#define PRCM_REQ_MB5_I2C_SIZE (PRCM_REQ_MB5 + 2)
-#define PRCM_REQ_MB5_I2C_DATA (PRCM_REQ_MB5 + 4)
-
-/* Acknowledge mailbox 5 fields. */
-#define PRCM_ACK_MB5_RETURN_CODE (PRCM_ACK_MB5 + 0)
-#define PRCM_ACK_MB5_I2C_DATA (PRCM_ACK_MB5 + 4)
-
-#define NUM_MB 8
-#define MBOX_BIT BIT
-#define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1)
-
-/*
-* Used by MCDE to setup all necessary PRCMU registers
-*/
-#define PRCMU_RESET_DSIPLL 0x00004000
-#define PRCMU_UNCLAMP_DSIPLL 0x00400800
-
-/* HDMI CLK MGT PLLSW=001 (PLLSOC0), PLLDIV=0x8, = 50 Mhz*/
-#define PRCMU_DSI_CLOCK_SETTING 0x00000128
-/* TVCLK_MGT PLLSW=001 (PLLSOC0) PLLDIV=0x13, = 19.05 MHZ */
-#define PRCMU_DSI_LP_CLOCK_SETTING 0x00000135
-#define PRCMU_PLLDSI_FREQ_SETTING 0x00020121
-#define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000002
-#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x03000201
-#define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00000101
-
-#define PRCMU_ENABLE_PLLDSI 0x00000001
-#define PRCMU_DISABLE_PLLDSI 0x00000000
-
-#define PRCMU_DSI_RESET_SW 0x00000003
-#define PRCMU_RESOUTN0_PIN 0x00000001
-#define PRCMU_RESOUTN1_PIN 0x00000002
-#define PRCMU_RESOUTN2_PIN 0x00000004
-
-#define PRCMU_PLLDSI_LOCKP_LOCKED 0x3
-
-/*
- * mb0_transfer - state needed for mailbox 0 communication.
- * @lock: The transaction lock.
- */
-static struct {
- spinlock_t lock;
-} mb0_transfer;
-
-/*
- * mb5_transfer - state needed for mailbox 5 communication.
- * @lock: The transaction lock.
- * @work: The transaction completion structure.
- * @ack: Reply ("acknowledge") data.
- */
-static struct {
- struct mutex lock;
- struct completion work;
- struct {
- u8 header;
- u8 status;
- u8 value[4];
- } ack;
-} mb5_transfer;
-
-/* PRCMU TCDM base IO address. */
-static __iomem void *tcdm_base;
-
-/**
- * db5500_prcmu_abb_read() - Read register value(s) from the ABB.
- * @slave: The I2C slave address.
- * @reg: The (start) register address.
- * @value: The read out value(s).
- * @size: The number of registers to read.
- *
- * Reads register value(s) from the ABB.
- * @size has to be <= 4.
- */
-int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
-{
- int r;
-
- if ((size < 1) || (4 < size))
- return -EINVAL;
-
- mutex_lock(&mb5_transfer.lock);
-
- while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
- cpu_relax();
- writeb(slave, PRCM_REQ_MB5_I2C_SLAVE);
- writeb(reg, PRCM_REQ_MB5_I2C_REG);
- writeb(size, PRCM_REQ_MB5_I2C_SIZE);
- writeb(MB5H_I2C_READ, PRCM_REQ_MB5_HEADER);
-
- writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
- wait_for_completion(&mb5_transfer.work);
-
- r = 0;
- if ((mb5_transfer.ack.header == MB5H_I2C_READ) &&
- (mb5_transfer.ack.status == RC_SUCCESS))
- memcpy(value, mb5_transfer.ack.value, (size_t)size);
- else
- r = -EIO;
-
- mutex_unlock(&mb5_transfer.lock);
-
- return r;
-}
-
-/**
- * db5500_prcmu_abb_write() - Write register value(s) to the ABB.
- * @slave: The I2C slave address.
- * @reg: The (start) register address.
- * @value: The value(s) to write.
- * @size: The number of registers to write.
- *
- * Writes register value(s) to the ABB.
- * @size has to be <= 4.
- */
-int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
-{
- int r;
-
- if ((size < 1) || (4 < size))
- return -EINVAL;
-
- mutex_lock(&mb5_transfer.lock);
-
- while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
- cpu_relax();
- writeb(slave, PRCM_REQ_MB5_I2C_SLAVE);
- writeb(reg, PRCM_REQ_MB5_I2C_REG);
- writeb(size, PRCM_REQ_MB5_I2C_SIZE);
- memcpy_toio(PRCM_REQ_MB5_I2C_DATA, value, size);
- writeb(MB5H_I2C_WRITE, PRCM_REQ_MB5_HEADER);
-
- writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
- wait_for_completion(&mb5_transfer.work);
-
- if ((mb5_transfer.ack.header == MB5H_I2C_WRITE) &&
- (mb5_transfer.ack.status == RC_SUCCESS))
- r = 0;
- else
- r = -EIO;
-
- mutex_unlock(&mb5_transfer.lock);
-
- return r;
-}
-
-int db5500_prcmu_enable_dsipll(void)
-{
- int i;
-
- /* Enable DSIPLL_RESETN resets */
- writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR);
- /* Unclamp DSIPLL in/out */
- writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR);
- /* Set DSI PLL FREQ */
- writel(PRCMU_PLLDSI_FREQ_SETTING, PRCM_PLLDSI_FREQ);
- writel(PRCMU_DSI_PLLOUT_SEL_SETTING,
- PRCM_DSI_PLLOUT_SEL);
- /* Enable Escape clocks */
- writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
-
- /* Start DSI PLL */
- writel(PRCMU_ENABLE_PLLDSI, PRCM_PLLDSI_ENABLE);
- /* Reset DSI PLL */
- writel(PRCMU_DSI_RESET_SW, PRCM_DSI_SW_RESET);
- for (i = 0; i < 10; i++) {
- if ((readl(PRCM_PLLDSI_LOCKP) &
- PRCMU_PLLDSI_LOCKP_LOCKED) == PRCMU_PLLDSI_LOCKP_LOCKED)
- break;
- udelay(100);
- }
- /* Release DSIPLL_RESETN */
- writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_SET);
- return 0;
-}
-
-int db5500_prcmu_disable_dsipll(void)
-{
- /* Disable dsi pll */
- writel(PRCMU_DISABLE_PLLDSI, PRCM_PLLDSI_ENABLE);
- /* Disable escapeclock */
- writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
- return 0;
-}
-
-int db5500_prcmu_set_display_clocks(void)
-{
- /* HDMI and TVCLK Should be handled somewhere else */
- /* PLLDIV=8, PLLSW=2, CLKEN=1 */
- writel(PRCMU_DSI_CLOCK_SETTING, PRCM_HDMICLK_MGT);
- /* PLLDIV=14, PLLSW=2, CLKEN=1 */
- writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT);
- return 0;
-}
-
-static void ack_dbb_wakeup(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&mb0_transfer.lock, flags);
-
- while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
- cpu_relax();
-
- writeb(RMB0H_RD_WAKE_UP_ACK, PRCM_REQ_MB0_HEADER);
- writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
-
- spin_unlock_irqrestore(&mb0_transfer.lock, flags);
-}
-
-static inline void print_unknown_header_warning(u8 n, u8 header)
-{
- pr_warning("prcmu: Unknown message header (%d) in mailbox %d.\n",
- header, n);
-}
-
-static bool read_mailbox_0(void)
-{
- bool r;
- u8 header;
-
- header = readb(PRCM_ACK_MB0_HEADER);
- switch (header) {
- case AMB0H_WAKE_UP:
- r = true;
- break;
- default:
- print_unknown_header_warning(0, header);
- r = false;
- break;
- }
- writel(MBOX_BIT(0), PRCM_ARM_IT1_CLR);
- return r;
-}
-
-static bool read_mailbox_1(void)
-{
- writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR);
- return false;
-}
-
-static bool read_mailbox_2(void)
-{
- writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR);
- return false;
-}
-
-static bool read_mailbox_3(void)
-{
- writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR);
- return false;
-}
-
-static bool read_mailbox_4(void)
-{
- writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR);
- return false;
-}
-
-static bool read_mailbox_5(void)
-{
- u8 header;
-
- header = readb(PRCM_ACK_MB5_HEADER);
- switch (header) {
- case MB5H_I2C_READ:
- memcpy_fromio(mb5_transfer.ack.value, PRCM_ACK_MB5_I2C_DATA, 4);
- case MB5H_I2C_WRITE:
- mb5_transfer.ack.header = header;
- mb5_transfer.ack.status = readb(PRCM_ACK_MB5_RETURN_CODE);
- complete(&mb5_transfer.work);
- break;
- default:
- print_unknown_header_warning(5, header);
- break;
- }
- writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR);
- return false;
-}
-
-static bool read_mailbox_6(void)
-{
- writel(MBOX_BIT(6), PRCM_ARM_IT1_CLR);
- return false;
-}
-
-static bool read_mailbox_7(void)
-{
- writel(MBOX_BIT(7), PRCM_ARM_IT1_CLR);
- return false;
-}
-
-static bool (* const read_mailbox[NUM_MB])(void) = {
- read_mailbox_0,
- read_mailbox_1,
- read_mailbox_2,
- read_mailbox_3,
- read_mailbox_4,
- read_mailbox_5,
- read_mailbox_6,
- read_mailbox_7
-};
-
-static irqreturn_t prcmu_irq_handler(int irq, void *data)
-{
- u32 bits;
- u8 n;
- irqreturn_t r;
-
- bits = (readl(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS);
- if (unlikely(!bits))
- return IRQ_NONE;
-
- r = IRQ_HANDLED;
- for (n = 0; bits; n++) {
- if (bits & MBOX_BIT(n)) {
- bits -= MBOX_BIT(n);
- if (read_mailbox[n]())
- r = IRQ_WAKE_THREAD;
- }
- }
- return r;
-}
-
-static irqreturn_t prcmu_irq_thread_fn(int irq, void *data)
-{
- ack_dbb_wakeup();
- return IRQ_HANDLED;
-}
-
-void __init db5500_prcmu_early_init(void)
-{
- tcdm_base = __io_address(U5500_PRCMU_TCDM_BASE);
- spin_lock_init(&mb0_transfer.lock);
- mutex_init(&mb5_transfer.lock);
- init_completion(&mb5_transfer.work);
-}
-
-/**
- * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
- *
- */
-int __init db5500_prcmu_init(void)
-{
- int r = 0;
-
- if (ux500_is_svp() || !cpu_is_u5500())
- return -ENODEV;
-
- /* Clean up the mailbox interrupts after pre-kernel code. */
- writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
-
- r = request_threaded_irq(IRQ_DB5500_PRCMU1, prcmu_irq_handler,
- prcmu_irq_thread_fn, 0, "prcmu", NULL);
- if (r < 0) {
- pr_err("prcmu: Failed to allocate IRQ_DB5500_PRCMU1.\n");
- return -EBUSY;
- }
- return 0;
-}
-
-arch_initcall(db5500_prcmu_init);
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index 9fd4f63c45cc..738722cdecaa 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -813,7 +813,8 @@ err_revision:
mc13xxx_add_subdevice(mc13xxx, "%s-adc");
if (mc13xxx->flags & MC13XXX_USE_CODEC)
- mc13xxx_add_subdevice(mc13xxx, "%s-codec");
+ mc13xxx_add_subdevice_pdata(mc13xxx, "%s-codec",
+ pdata->codec, sizeof(*pdata->codec));
if (mc13xxx->flags & MC13XXX_USE_RTC)
mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
new file mode 100644
index 000000000000..00c0aba7eba0
--- /dev/null
+++ b/drivers/mfd/palmas.c
@@ -0,0 +1,509 @@
+/*
+ * TI Palmas MFD Driver
+ *
+ * Copyright 2011-2012 Texas Instruments Inc.
+ *
+ * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/palmas.h>
+
+static const struct resource gpadc_resource[] = {
+ {
+ .name = "EOC_SW",
+ .start = PALMAS_GPADC_EOC_SW_IRQ,
+ .end = PALMAS_GPADC_EOC_SW_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static const struct resource usb_resource[] = {
+ {
+ .name = "ID",
+ .start = PALMAS_ID_OTG_IRQ,
+ .end = PALMAS_ID_OTG_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "ID_WAKEUP",
+ .start = PALMAS_ID_IRQ,
+ .end = PALMAS_ID_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "VBUS",
+ .start = PALMAS_VBUS_OTG_IRQ,
+ .end = PALMAS_VBUS_OTG_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "VBUS_WAKEUP",
+ .start = PALMAS_VBUS_IRQ,
+ .end = PALMAS_VBUS_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const struct resource rtc_resource[] = {
+ {
+ .name = "RTC_ALARM",
+ .start = PALMAS_RTC_ALARM_IRQ,
+ .end = PALMAS_RTC_ALARM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const struct resource pwron_resource[] = {
+ {
+ .name = "PWRON_BUTTON",
+ .start = PALMAS_PWRON_IRQ,
+ .end = PALMAS_PWRON_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+enum palmas_ids {
+ PALMAS_PMIC_ID,
+ PALMAS_GPIO_ID,
+ PALMAS_LEDS_ID,
+ PALMAS_WDT_ID,
+ PALMAS_RTC_ID,
+ PALMAS_PWRBUTTON_ID,
+ PALMAS_GPADC_ID,
+ PALMAS_RESOURCE_ID,
+ PALMAS_CLK_ID,
+ PALMAS_PWM_ID,
+ PALMAS_USB_ID,
+};
+
+static const struct mfd_cell palmas_children[] = {
+ {
+ .name = "palmas-pmic",
+ .id = PALMAS_PMIC_ID,
+ },
+ {
+ .name = "palmas-gpio",
+ .id = PALMAS_GPIO_ID,
+ },
+ {
+ .name = "palmas-leds",
+ .id = PALMAS_LEDS_ID,
+ },
+ {
+ .name = "palmas-wdt",
+ .id = PALMAS_WDT_ID,
+ },
+ {
+ .name = "palmas-rtc",
+ .num_resources = ARRAY_SIZE(rtc_resource),
+ .resources = rtc_resource,
+ .id = PALMAS_RTC_ID,
+ },
+ {
+ .name = "palmas-pwrbutton",
+ .num_resources = ARRAY_SIZE(pwron_resource),
+ .resources = pwron_resource,
+ .id = PALMAS_PWRBUTTON_ID,
+ },
+ {
+ .name = "palmas-gpadc",
+ .num_resources = ARRAY_SIZE(gpadc_resource),
+ .resources = gpadc_resource,
+ .id = PALMAS_GPADC_ID,
+ },
+ {
+ .name = "palmas-resource",
+ .id = PALMAS_RESOURCE_ID,
+ },
+ {
+ .name = "palmas-clk",
+ .id = PALMAS_CLK_ID,
+ },
+ {
+ .name = "palmas-pwm",
+ .id = PALMAS_PWM_ID,
+ },
+ {
+ .name = "palmas-usb",
+ .num_resources = ARRAY_SIZE(usb_resource),
+ .resources = usb_resource,
+ .id = PALMAS_USB_ID,
+ }
+};
+
+static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = {
+ {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE,
+ PALMAS_PRIMARY_SECONDARY_PAD3),
+ },
+ {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = PALMAS_BASE_TO_REG(PALMAS_GPADC_BASE,
+ PALMAS_GPADC_SMPS_VSEL_MONITORING),
+ },
+ {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = PALMAS_BASE_TO_REG(PALMAS_TRIM_GPADC_BASE,
+ PALMAS_GPADC_TRIM16),
+ },
+};
+
+static const struct regmap_irq palmas_irqs[] = {
+ /* INT1 IRQs */
+ [PALMAS_CHARG_DET_N_VBUS_OVV_IRQ] = {
+ .mask = PALMAS_INT1_STATUS_CHARG_DET_N_VBUS_OVV,
+ },
+ [PALMAS_PWRON_IRQ] = {
+ .mask = PALMAS_INT1_STATUS_PWRON,
+ },
+ [PALMAS_LONG_PRESS_KEY_IRQ] = {
+ .mask = PALMAS_INT1_STATUS_LONG_PRESS_KEY,
+ },
+ [PALMAS_RPWRON_IRQ] = {
+ .mask = PALMAS_INT1_STATUS_RPWRON,
+ },
+ [PALMAS_PWRDOWN_IRQ] = {
+ .mask = PALMAS_INT1_STATUS_PWRDOWN,
+ },
+ [PALMAS_HOTDIE_IRQ] = {
+ .mask = PALMAS_INT1_STATUS_HOTDIE,
+ },
+ [PALMAS_VSYS_MON_IRQ] = {
+ .mask = PALMAS_INT1_STATUS_VSYS_MON,
+ },
+ [PALMAS_VBAT_MON_IRQ] = {
+ .mask = PALMAS_INT1_STATUS_VBAT_MON,
+ },
+ /* INT2 IRQs*/
+ [PALMAS_RTC_ALARM_IRQ] = {
+ .mask = PALMAS_INT2_STATUS_RTC_ALARM,
+ .reg_offset = 1,
+ },
+ [PALMAS_RTC_TIMER_IRQ] = {
+ .mask = PALMAS_INT2_STATUS_RTC_TIMER,
+ .reg_offset = 1,
+ },
+ [PALMAS_WDT_IRQ] = {
+ .mask = PALMAS_INT2_STATUS_WDT,
+ .reg_offset = 1,
+ },
+ [PALMAS_BATREMOVAL_IRQ] = {
+ .mask = PALMAS_INT2_STATUS_BATREMOVAL,
+ .reg_offset = 1,
+ },
+ [PALMAS_RESET_IN_IRQ] = {
+ .mask = PALMAS_INT2_STATUS_RESET_IN,
+ .reg_offset = 1,
+ },
+ [PALMAS_FBI_BB_IRQ] = {
+ .mask = PALMAS_INT2_STATUS_FBI_BB,
+ .reg_offset = 1,
+ },
+ [PALMAS_SHORT_IRQ] = {
+ .mask = PALMAS_INT2_STATUS_SHORT,
+ .reg_offset = 1,
+ },
+ [PALMAS_VAC_ACOK_IRQ] = {
+ .mask = PALMAS_INT2_STATUS_VAC_ACOK,
+ .reg_offset = 1,
+ },
+ /* INT3 IRQs */
+ [PALMAS_GPADC_AUTO_0_IRQ] = {
+ .mask = PALMAS_INT3_STATUS_GPADC_AUTO_0,
+ .reg_offset = 2,
+ },
+ [PALMAS_GPADC_AUTO_1_IRQ] = {
+ .mask = PALMAS_INT3_STATUS_GPADC_AUTO_1,
+ .reg_offset = 2,
+ },
+ [PALMAS_GPADC_EOC_SW_IRQ] = {
+ .mask = PALMAS_INT3_STATUS_GPADC_EOC_SW,
+ .reg_offset = 2,
+ },
+ [PALMAS_GPADC_EOC_RT_IRQ] = {
+ .mask = PALMAS_INT3_STATUS_GPADC_EOC_RT,
+ .reg_offset = 2,
+ },
+ [PALMAS_ID_OTG_IRQ] = {
+ .mask = PALMAS_INT3_STATUS_ID_OTG,
+ .reg_offset = 2,
+ },
+ [PALMAS_ID_IRQ] = {
+ .mask = PALMAS_INT3_STATUS_ID,
+ .reg_offset = 2,
+ },
+ [PALMAS_VBUS_OTG_IRQ] = {
+ .mask = PALMAS_INT3_STATUS_VBUS_OTG,
+ .reg_offset = 2,
+ },
+ [PALMAS_VBUS_IRQ] = {
+ .mask = PALMAS_INT3_STATUS_VBUS,
+ .reg_offset = 2,
+ },
+ /* INT4 IRQs */
+ [PALMAS_GPIO_0_IRQ] = {
+ .mask = PALMAS_INT4_STATUS_GPIO_0,
+ .reg_offset = 3,
+ },
+ [PALMAS_GPIO_1_IRQ] = {
+ .mask = PALMAS_INT4_STATUS_GPIO_1,
+ .reg_offset = 3,
+ },
+ [PALMAS_GPIO_2_IRQ] = {
+ .mask = PALMAS_INT4_STATUS_GPIO_2,
+ .reg_offset = 3,
+ },
+ [PALMAS_GPIO_3_IRQ] = {
+ .mask = PALMAS_INT4_STATUS_GPIO_3,
+ .reg_offset = 3,
+ },
+ [PALMAS_GPIO_4_IRQ] = {
+ .mask = PALMAS_INT4_STATUS_GPIO_4,
+ .reg_offset = 3,
+ },
+ [PALMAS_GPIO_5_IRQ] = {
+ .mask = PALMAS_INT4_STATUS_GPIO_5,
+ .reg_offset = 3,
+ },
+ [PALMAS_GPIO_6_IRQ] = {
+ .mask = PALMAS_INT4_STATUS_GPIO_6,
+ .reg_offset = 3,
+ },
+ [PALMAS_GPIO_7_IRQ] = {
+ .mask = PALMAS_INT4_STATUS_GPIO_7,
+ .reg_offset = 3,
+ },
+};
+
+static struct regmap_irq_chip palmas_irq_chip = {
+ .name = "palmas",
+ .irqs = palmas_irqs,
+ .num_irqs = ARRAY_SIZE(palmas_irqs),
+
+ .num_regs = 4,
+ .irq_reg_stride = 5,
+ .status_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE,
+ PALMAS_INT1_STATUS),
+ .mask_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE,
+ PALMAS_INT1_MASK),
+};
+
+static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct palmas *palmas;
+ struct palmas_platform_data *pdata;
+ int ret = 0, i;
+ unsigned int reg, addr;
+ int slave;
+ struct mfd_cell *children;
+
+ pdata = dev_get_platdata(&i2c->dev);
+ if (!pdata)
+ return -EINVAL;
+
+ palmas = devm_kzalloc(&i2c->dev, sizeof(struct palmas), GFP_KERNEL);
+ if (palmas == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, palmas);
+ palmas->dev = &i2c->dev;
+ palmas->id = id->driver_data;
+ palmas->irq = i2c->irq;
+
+ for (i = 0; i < PALMAS_NUM_CLIENTS; i++) {
+ if (i == 0)
+ palmas->i2c_clients[i] = i2c;
+ else {
+ palmas->i2c_clients[i] =
+ i2c_new_dummy(i2c->adapter,
+ i2c->addr + i);
+ if (!palmas->i2c_clients[i]) {
+ dev_err(palmas->dev,
+ "can't attach client %d\n", i);
+ ret = -ENOMEM;
+ goto err;
+ }
+ }
+ palmas->regmap[i] = devm_regmap_init_i2c(palmas->i2c_clients[i],
+ &palmas_regmap_config[i]);
+ if (IS_ERR(palmas->regmap[i])) {
+ ret = PTR_ERR(palmas->regmap[i]);
+ dev_err(palmas->dev,
+ "Failed to allocate regmap %d, err: %d\n",
+ i, ret);
+ goto err;
+ }
+ }
+
+ ret = regmap_add_irq_chip(palmas->regmap[1], palmas->irq,
+ IRQF_ONESHOT | IRQF_TRIGGER_LOW, -1, &palmas_irq_chip,
+ &palmas->irq_data);
+ if (ret < 0)
+ goto err;
+
+ slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE);
+ addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE,
+ PALMAS_PRIMARY_SECONDARY_PAD1);
+
+ if (pdata->mux_from_pdata) {
+ reg = pdata->pad1;
+ ret = regmap_write(palmas->regmap[slave], addr, reg);
+ if (ret)
+ goto err;
+ } else {
+ ret = regmap_read(palmas->regmap[slave], addr, &reg);
+ if (ret)
+ goto err;
+ }
+
+ if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_0))
+ palmas->gpio_muxed |= PALMAS_GPIO_0_MUXED;
+ if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK))
+ palmas->gpio_muxed |= PALMAS_GPIO_1_MUXED;
+ else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK) ==
+ (2 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT))
+ palmas->led_muxed |= PALMAS_LED1_MUXED;
+ else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK) ==
+ (3 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT))
+ palmas->pwm_muxed |= PALMAS_PWM1_MUXED;
+ if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK))
+ palmas->gpio_muxed |= PALMAS_GPIO_2_MUXED;
+ else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK) ==
+ (2 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_SHIFT))
+ palmas->led_muxed |= PALMAS_LED2_MUXED;
+ else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK) ==
+ (3 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_SHIFT))
+ palmas->pwm_muxed |= PALMAS_PWM2_MUXED;
+ if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_3))
+ palmas->gpio_muxed |= PALMAS_GPIO_3_MUXED;
+
+ addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE,
+ PALMAS_PRIMARY_SECONDARY_PAD2);
+
+ if (pdata->mux_from_pdata) {
+ reg = pdata->pad2;
+ ret = regmap_write(palmas->regmap[slave], addr, reg);
+ if (ret)
+ goto err;
+ } else {
+ ret = regmap_read(palmas->regmap[slave], addr, &reg);
+ if (ret)
+ goto err;
+ }
+
+ if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_4))
+ palmas->gpio_muxed |= PALMAS_GPIO_4_MUXED;
+ if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_5_MASK))
+ palmas->gpio_muxed |= PALMAS_GPIO_5_MUXED;
+ if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_6))
+ palmas->gpio_muxed |= PALMAS_GPIO_6_MUXED;
+ if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_MASK))
+ palmas->gpio_muxed |= PALMAS_GPIO_7_MUXED;
+
+ dev_info(palmas->dev, "Muxing GPIO %x, PWM %x, LED %x\n",
+ palmas->gpio_muxed, palmas->pwm_muxed,
+ palmas->led_muxed);
+
+ reg = pdata->power_ctrl;
+
+ slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE);
+ addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_POWER_CTRL);
+
+ ret = regmap_write(palmas->regmap[slave], addr, reg);
+ if (ret)
+ goto err;
+
+ children = kmemdup(palmas_children, sizeof(palmas_children),
+ GFP_KERNEL);
+ if (!children) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ret = mfd_add_devices(palmas->dev, -1,
+ children, ARRAY_SIZE(palmas_children),
+ NULL, regmap_irq_chip_get_base(palmas->irq_data));
+ kfree(children);
+
+ if (ret < 0)
+ goto err;
+
+ return ret;
+
+err:
+ mfd_remove_devices(palmas->dev);
+ kfree(palmas);
+ return ret;
+}
+
+static int palmas_i2c_remove(struct i2c_client *i2c)
+{
+ struct palmas *palmas = i2c_get_clientdata(i2c);
+
+ mfd_remove_devices(palmas->dev);
+ regmap_del_irq_chip(palmas->irq, palmas->irq_data);
+
+ return 0;
+}
+
+static const struct i2c_device_id palmas_i2c_id[] = {
+ { "palmas", },
+ { "twl6035", },
+ { "twl6037", },
+ { "tps65913", },
+};
+MODULE_DEVICE_TABLE(i2c, palmas_i2c_id);
+
+static struct of_device_id __devinitdata of_palmas_match_tbl[] = {
+ { .compatible = "ti,palmas", },
+ { /* end */ }
+};
+
+static struct i2c_driver palmas_i2c_driver = {
+ .driver = {
+ .name = "palmas",
+ .of_match_table = of_palmas_match_tbl,
+ .owner = THIS_MODULE,
+ },
+ .probe = palmas_i2c_probe,
+ .remove = palmas_i2c_remove,
+ .id_table = palmas_i2c_id,
+};
+
+static int __init palmas_i2c_init(void)
+{
+ return i2c_add_driver(&palmas_i2c_driver);
+}
+/* init early so consumer devices can complete system boot */
+subsys_initcall(palmas_i2c_init);
+
+static void __exit palmas_i2c_exit(void)
+{
+ i2c_del_driver(&palmas_i2c_driver);
+}
+module_exit(palmas_i2c_exit);
+
+MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
+MODULE_DESCRIPTION("Palmas chip family multi-function driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
index a66d4df51293..47f802bf1848 100644
--- a/drivers/mfd/tps65090.c
+++ b/drivers/mfd/tps65090.c
@@ -78,17 +78,6 @@ static struct mfd_cell tps65090s[] = {
},
};
-struct tps65090 {
- struct mutex lock;
- struct device *dev;
- struct i2c_client *client;
- struct regmap *rmap;
- struct irq_chip irq_chip;
- struct mutex irq_lock;
- int irq_base;
- unsigned int id;
-};
-
int tps65090_write(struct device *dev, int reg, uint8_t val)
{
struct tps65090 *tps = dev_get_drvdata(dev);
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index a5ddf31b60ca..c84b5506d5fb 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
+#include <linux/regulator/of_regulator.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps6586x.h>
@@ -460,6 +461,7 @@ static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x,
pdev->dev.parent = tps6586x->dev;
pdev->dev.platform_data = subdev->platform_data;
+ pdev->dev.of_node = subdev->of_node;
ret = platform_device_add(pdev);
if (ret) {
@@ -474,6 +476,86 @@ failed:
return ret;
}
+#ifdef CONFIG_OF
+static struct of_regulator_match tps6586x_matches[] = {
+ { .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 },
+ { .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 },
+ { .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 },
+ { .name = "ldo0", .driver_data = (void *)TPS6586X_ID_LDO_0 },
+ { .name = "ldo1", .driver_data = (void *)TPS6586X_ID_LDO_1 },
+ { .name = "ldo2", .driver_data = (void *)TPS6586X_ID_LDO_2 },
+ { .name = "ldo3", .driver_data = (void *)TPS6586X_ID_LDO_3 },
+ { .name = "ldo4", .driver_data = (void *)TPS6586X_ID_LDO_4 },
+ { .name = "ldo5", .driver_data = (void *)TPS6586X_ID_LDO_5 },
+ { .name = "ldo6", .driver_data = (void *)TPS6586X_ID_LDO_6 },
+ { .name = "ldo7", .driver_data = (void *)TPS6586X_ID_LDO_7 },
+ { .name = "ldo8", .driver_data = (void *)TPS6586X_ID_LDO_8 },
+ { .name = "ldo9", .driver_data = (void *)TPS6586X_ID_LDO_9 },
+ { .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
+};
+
+static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client)
+{
+ const unsigned int num = ARRAY_SIZE(tps6586x_matches);
+ struct device_node *np = client->dev.of_node;
+ struct tps6586x_platform_data *pdata;
+ struct tps6586x_subdev_info *devs;
+ struct device_node *regs;
+ unsigned int count;
+ unsigned int i, j;
+ int err;
+
+ regs = of_find_node_by_name(np, "regulators");
+ if (!regs)
+ return NULL;
+
+ err = of_regulator_match(&client->dev, regs, tps6586x_matches, num);
+ if (err < 0) {
+ of_node_put(regs);
+ return NULL;
+ }
+
+ of_node_put(regs);
+ count = err;
+
+ devs = devm_kzalloc(&client->dev, count * sizeof(*devs), GFP_KERNEL);
+ if (!devs)
+ return NULL;
+
+ for (i = 0, j = 0; i < num && j < count; i++) {
+ if (!tps6586x_matches[i].init_data)
+ continue;
+
+ devs[j].name = "tps6586x-regulator";
+ devs[j].platform_data = tps6586x_matches[i].init_data;
+ devs[j].id = (int)tps6586x_matches[i].driver_data;
+ devs[j].of_node = tps6586x_matches[i].of_node;
+ j++;
+ }
+
+ pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return NULL;
+
+ pdata->num_subdevs = count;
+ pdata->subdevs = devs;
+ pdata->gpio_base = -1;
+ pdata->irq_base = -1;
+
+ return pdata;
+}
+
+static struct of_device_id tps6586x_of_match[] = {
+ { .compatible = "ti,tps6586x", },
+ { },
+};
+#else
+static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client)
+{
+ return NULL;
+}
+#endif
+
static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -481,6 +563,9 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
struct tps6586x *tps6586x;
int ret;
+ if (!pdata && client->dev.of_node)
+ pdata = tps6586x_parse_dt(client);
+
if (!pdata) {
dev_err(&client->dev, "tps6586x requires platform data\n");
return -ENOTSUPP;
@@ -573,6 +658,7 @@ static struct i2c_driver tps6586x_driver = {
.driver = {
.name = "tps6586x",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tps6586x_of_match),
},
.probe = tps6586x_i2c_probe,
.remove = __devexit_p(tps6586x_i2c_remove),
diff --git a/drivers/mfd/tps65911-comparator.c b/drivers/mfd/tps65911-comparator.c
index e7ff783aa31e..5a62e6bf89ae 100644
--- a/drivers/mfd/tps65911-comparator.c
+++ b/drivers/mfd/tps65911-comparator.c
@@ -26,7 +26,7 @@
#define COMP1 1
#define COMP2 2
-/* Comparator 1 voltage selection table in milivolts */
+/* Comparator 1 voltage selection table in millivolts */
static const u16 COMP_VSEL_TABLE[] = {
0, 2500, 2500, 2500, 2500, 2550, 2600, 2650,
2700, 2750, 2800, 2850, 2900, 2950, 3000, 3050,
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 7c2267e71f8b..6fc90befa79e 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -224,13 +224,6 @@
#define HIGH_PERF_SQ (1 << 3)
#define CK32K_LOWPWR_EN (1 << 7)
-
-/* chip-specific feature flags, for i2c_device_id.driver_data */
-#define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */
-#define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */
-#define TWL5031 BIT(2) /* twl5031 has different registers */
-#define TWL6030_CLASS BIT(3) /* TWL6030 class */
-
/*----------------------------------------------------------------------*/
/* is driver active, bound to a chip? */
diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c
index 46b20c445ecf..f1837f669755 100644
--- a/drivers/mfd/wm8994-irq.c
+++ b/drivers/mfd/wm8994-irq.c
@@ -147,12 +147,6 @@ int wm8994_irq_init(struct wm8994 *wm8994)
return 0;
}
- if (!wm8994->irq_base) {
- dev_err(wm8994->dev,
- "No interrupt base specified, no interrupts\n");
- return 0;
- }
-
ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
wm8994->irq_base, &wm8994_irq_chip,
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index c7795096d43b..2661f6e366f9 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -452,14 +452,32 @@ config ARM_CHARLCD
still useful.
config BMP085
- tristate "BMP085 digital pressure sensor"
+ bool
+ depends on SYSFS
+
+config BMP085_I2C
+ tristate "BMP085 digital pressure sensor on I2C"
+ select BMP085
+ select REGMAP_I2C
depends on I2C && SYSFS
help
- If you say yes here you get support for the Bosch Sensortec
- BMP085 digital pressure sensor.
+ Say Y here if you want to support Bosch Sensortec's digital pressure
+ sensor hooked to an I2C bus.
To compile this driver as a module, choose M here: the
- module will be called bmp085.
+ module will be called bmp085-i2c.
+
+config BMP085_SPI
+ tristate "BMP085 digital pressure sensor on SPI"
+ select BMP085
+ select REGMAP_SPI
+ depends on SPI_MASTER && SYSFS
+ help
+ Say Y here if you want to support Bosch Sensortec's digital pressure
+ sensor hooked to an SPI bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bmp085-spi.
config PCH_PHUB
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB"
@@ -490,14 +508,6 @@ config USB_SWITCH_FSA9480
stereo and mono audio, video, microphone and UART data to use
a common connector port.
-config MAX8997_MUIC
- tristate "MAX8997 MUIC Support"
- depends on MFD_MAX8997
- help
- If you say yes here you get support for the MUIC device of
- Maxim MAX8997 PMIC.
- The MAX8997 MUIC is a USB port accessory detector and switch.
-
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
@@ -506,4 +516,5 @@ source "drivers/misc/ti-st/Kconfig"
source "drivers/misc/lis3lv02d/Kconfig"
source "drivers/misc/carma/Kconfig"
source "drivers/misc/altera-stapl/Kconfig"
+source "drivers/misc/mei/Kconfig"
endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 3e1d80106f04..456972faaeb3 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -11,6 +11,8 @@ obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
obj-$(CONFIG_BMP085) += bmp085.o
+obj-$(CONFIG_BMP085_I2C) += bmp085-i2c.o
+obj-$(CONFIG_BMP085_SPI) += bmp085-spi.o
obj-$(CONFIG_ICS932S401) += ics932s401.o
obj-$(CONFIG_LKDTM) += lkdtm.o
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
@@ -48,4 +50,4 @@ obj-y += lis3lv02d/
obj-y += carma/
obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
-obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o
+obj-$(CONFIG_INTEL_MEI) += mei/
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
index 1d1d42615915..6938f1be664d 100644
--- a/drivers/misc/ad525x_dpot.c
+++ b/drivers/misc/ad525x_dpot.c
@@ -749,7 +749,7 @@ exit:
}
EXPORT_SYMBOL(ad_dpot_probe);
-__devexit int ad_dpot_remove(struct device *dev)
+int ad_dpot_remove(struct device *dev)
{
struct dpot_data *data = dev_get_drvdata(dev);
int i;
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
index 54f6f39f990a..f1f9877f3fdf 100644
--- a/drivers/misc/bh1780gli.c
+++ b/drivers/misc/bh1780gli.c
@@ -248,7 +248,7 @@ static const struct i2c_device_id bh1780_id[] = {
static struct i2c_driver bh1780_driver = {
.probe = bh1780_probe,
- .remove = bh1780_remove,
+ .remove = __devexit_p(bh1780_remove),
.id_table = bh1780_id,
.driver = {
.name = "bh1780",
diff --git a/drivers/misc/bmp085-i2c.c b/drivers/misc/bmp085-i2c.c
new file mode 100644
index 000000000000..9943971c13e3
--- /dev/null
+++ b/drivers/misc/bmp085-i2c.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012 Bosch Sensortec GmbH
+ * Copyright (c) 2012 Unixphere AB
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include "bmp085.h"
+
+#define BMP085_I2C_ADDRESS 0x77
+
+static const unsigned short normal_i2c[] = { BMP085_I2C_ADDRESS,
+ I2C_CLIENT_END };
+
+static int bmp085_i2c_detect(struct i2c_client *client,
+ struct i2c_board_info *info)
+{
+ if (client->addr != BMP085_I2C_ADDRESS)
+ return -ENODEV;
+
+ return bmp085_detect(&client->dev);
+}
+
+static int __devinit bmp085_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err;
+ struct regmap *regmap = devm_regmap_init_i2c(client,
+ &bmp085_regmap_config);
+
+ if (IS_ERR(regmap)) {
+ err = PTR_ERR(regmap);
+ dev_err(&client->dev, "Failed to init regmap: %d\n", err);
+ return err;
+ }
+
+ return bmp085_probe(&client->dev, regmap);
+}
+
+static int bmp085_i2c_remove(struct i2c_client *client)
+{
+ return bmp085_remove(&client->dev);
+}
+
+static const struct of_device_id bmp085_of_match[] = {
+ { .compatible = "bosch,bmp085", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, bmp085_of_match);
+
+static const struct i2c_device_id bmp085_id[] = {
+ { BMP085_NAME, 0 },
+ { "bmp180", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, bmp085_id);
+
+static struct i2c_driver bmp085_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = BMP085_NAME,
+ .of_match_table = bmp085_of_match
+ },
+ .id_table = bmp085_id,
+ .probe = bmp085_i2c_probe,
+ .remove = __devexit_p(bmp085_i2c_remove),
+
+ .detect = bmp085_i2c_detect,
+ .address_list = normal_i2c
+};
+
+module_i2c_driver(bmp085_i2c_driver);
+
+MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
+MODULE_DESCRIPTION("BMP085 I2C bus driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/bmp085-spi.c b/drivers/misc/bmp085-spi.c
new file mode 100644
index 000000000000..78aaff9b5231
--- /dev/null
+++ b/drivers/misc/bmp085-spi.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012 Bosch Sensortec GmbH
+ * Copyright (c) 2012 Unixphere AB
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+#include "bmp085.h"
+
+static int __devinit bmp085_spi_probe(struct spi_device *client)
+{
+ int err;
+ struct regmap *regmap;
+
+ client->bits_per_word = 8;
+ err = spi_setup(client);
+ if (err < 0) {
+ dev_err(&client->dev, "spi_setup failed!\n");
+ return err;
+ }
+
+ regmap = devm_regmap_init_spi(client, &bmp085_regmap_config);
+ if (IS_ERR(regmap)) {
+ err = PTR_ERR(regmap);
+ dev_err(&client->dev, "Failed to init regmap: %d\n", err);
+ return err;
+ }
+
+ return bmp085_probe(&client->dev, regmap);
+}
+
+static int bmp085_spi_remove(struct spi_device *client)
+{
+ return bmp085_remove(&client->dev);
+}
+
+static const struct of_device_id bmp085_of_match[] = {
+ { .compatible = "bosch,bmp085", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, bmp085_of_match);
+
+static const struct spi_device_id bmp085_id[] = {
+ { "bmp180", 0 },
+ { "bmp181", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, bmp085_id);
+
+static struct spi_driver bmp085_spi_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = BMP085_NAME,
+ .of_match_table = bmp085_of_match
+ },
+ .id_table = bmp085_id,
+ .probe = bmp085_spi_probe,
+ .remove = __devexit_p(bmp085_spi_remove)
+};
+
+static int __init bmp085_spi_init(void)
+{
+ return spi_register_driver(&bmp085_spi_driver);
+}
+
+static void __exit bmp085_spi_exit(void)
+{
+ spi_unregister_driver(&bmp085_spi_driver);
+}
+
+MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
+MODULE_DESCRIPTION("BMP085 SPI bus driver");
+MODULE_LICENSE("GPL");
+
+module_init(bmp085_spi_init);
+module_exit(bmp085_spi_exit);
diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c
index 76c3064629f1..62e418293b7e 100644
--- a/drivers/misc/bmp085.c
+++ b/drivers/misc/bmp085.c
@@ -1,62 +1,62 @@
/* Copyright (c) 2010 Christoph Mair <christoph.mair@gmail.com>
-
- This driver supports the bmp085 digital barometric pressure
- and temperature sensor from Bosch Sensortec. The datasheet
- is available from their website:
- http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP085-DS000-05.pdf
-
- A pressure measurement is issued by reading from pressure0_input.
- The return value ranges from 30000 to 110000 pascal with a resulution
- of 1 pascal (0.01 millibar) which enables measurements from 9000m above
- to 500m below sea level.
-
- The temperature can be read from temp0_input. Values range from
- -400 to 850 representing the ambient temperature in degree celsius
- multiplied by 10.The resolution is 0.1 celsius.
-
- Because ambient pressure is temperature dependent, a temperature
- measurement will be executed automatically even if the user is reading
- from pressure0_input. This happens if the last temperature measurement
- has been executed more then one second ago.
-
- To decrease RMS noise from pressure measurements, the bmp085 can
- autonomously calculate the average of up to eight samples. This is
- set up by writing to the oversampling sysfs file. Accepted values
- are 0, 1, 2 and 3. 2^x when x is the value written to this file
- specifies the number of samples used to calculate the ambient pressure.
- RMS noise is specified with six pascal (without averaging) and decreases
- down to 3 pascal when using an oversampling setting of 3.
-
- 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.
-*/
-
+ * Copyright (c) 2012 Bosch Sensortec GmbH
+ * Copyright (c) 2012 Unixphere AB
+ *
+ * This driver supports the bmp085 and bmp18x digital barometric pressure
+ * and temperature sensors from Bosch Sensortec. The datasheets
+ * are available from their website:
+ * http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP085-DS000-05.pdf
+ * http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP180-DS000-07.pdf
+ *
+ * A pressure measurement is issued by reading from pressure0_input.
+ * The return value ranges from 30000 to 110000 pascal with a resulution
+ * of 1 pascal (0.01 millibar) which enables measurements from 9000m above
+ * to 500m below sea level.
+ *
+ * The temperature can be read from temp0_input. Values range from
+ * -400 to 850 representing the ambient temperature in degree celsius
+ * multiplied by 10.The resolution is 0.1 celsius.
+ *
+ * Because ambient pressure is temperature dependent, a temperature
+ * measurement will be executed automatically even if the user is reading
+ * from pressure0_input. This happens if the last temperature measurement
+ * has been executed more then one second ago.
+ *
+ * To decrease RMS noise from pressure measurements, the bmp085 can
+ * autonomously calculate the average of up to eight samples. This is
+ * set up by writing to the oversampling sysfs file. Accepted values
+ * are 0, 1, 2 and 3. 2^x when x is the value written to this file
+ * specifies the number of samples used to calculate the ambient pressure.
+ * RMS noise is specified with six pascal (without averaging) and decreases
+ * down to 3 pascal when using an oversampling setting of 3.
+ *
+ * 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.
+ */
#include <linux/module.h>
+#include <linux/device.h>
#include <linux/init.h>
-#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/of.h>
+#include "bmp085.h"
-
-#define BMP085_I2C_ADDRESS 0x77
#define BMP085_CHIP_ID 0x55
-
#define BMP085_CALIBRATION_DATA_START 0xAA
#define BMP085_CALIBRATION_DATA_LENGTH 11 /* 16 bit values */
#define BMP085_CHIP_ID_REG 0xD0
-#define BMP085_VERSION_REG 0xD1
#define BMP085_CTRL_REG 0xF4
#define BMP085_TEMP_MEASUREMENT 0x2E
#define BMP085_PRESSURE_MEASUREMENT 0x34
@@ -65,12 +65,6 @@
#define BMP085_CONVERSION_REGISTER_XLSB 0xF8
#define BMP085_TEMP_CONVERSION_TIME 5
-#define BMP085_CLIENT_NAME "bmp085"
-
-
-static const unsigned short normal_i2c[] = { BMP085_I2C_ADDRESS,
- I2C_CLIENT_END };
-
struct bmp085_calibration_data {
s16 AC1, AC2, AC3;
u16 AC4, AC5, AC6;
@@ -78,35 +72,30 @@ struct bmp085_calibration_data {
s16 MB, MC, MD;
};
-
-/* Each client has this additional data */
struct bmp085_data {
- struct i2c_client *client;
- struct mutex lock;
- struct bmp085_calibration_data calibration;
- u32 raw_temperature;
- u32 raw_pressure;
- unsigned char oversampling_setting;
+ struct device *dev;
+ struct regmap *regmap;
+ struct mutex lock;
+ struct bmp085_calibration_data calibration;
+ u8 oversampling_setting;
+ u32 raw_temperature;
+ u32 raw_pressure;
+ u32 temp_measurement_period;
unsigned long last_temp_measurement;
- s32 b6; /* calculated temperature correction coefficient */
+ u8 chip_id;
+ s32 b6; /* calculated temperature correction coefficient */
};
-
-static s32 bmp085_read_calibration_data(struct i2c_client *client)
+static s32 bmp085_read_calibration_data(struct bmp085_data *data)
{
u16 tmp[BMP085_CALIBRATION_DATA_LENGTH];
- struct bmp085_data *data = i2c_get_clientdata(client);
struct bmp085_calibration_data *cali = &(data->calibration);
- s32 status = i2c_smbus_read_i2c_block_data(client,
- BMP085_CALIBRATION_DATA_START,
- BMP085_CALIBRATION_DATA_LENGTH*sizeof(u16),
- (u8 *)tmp);
+ s32 status = regmap_bulk_read(data->regmap,
+ BMP085_CALIBRATION_DATA_START, (u8 *)tmp,
+ (BMP085_CALIBRATION_DATA_LENGTH << 1));
if (status < 0)
return status;
- if (status != BMP085_CALIBRATION_DATA_LENGTH*sizeof(u16))
- return -EIO;
-
cali->AC1 = be16_to_cpu(tmp[0]);
cali->AC2 = be16_to_cpu(tmp[1]);
cali->AC3 = be16_to_cpu(tmp[2]);
@@ -121,30 +110,26 @@ static s32 bmp085_read_calibration_data(struct i2c_client *client)
return 0;
}
-
static s32 bmp085_update_raw_temperature(struct bmp085_data *data)
{
u16 tmp;
s32 status;
mutex_lock(&data->lock);
- status = i2c_smbus_write_byte_data(data->client, BMP085_CTRL_REG,
- BMP085_TEMP_MEASUREMENT);
- if (status != 0) {
- dev_err(&data->client->dev,
+ status = regmap_write(data->regmap, BMP085_CTRL_REG,
+ BMP085_TEMP_MEASUREMENT);
+ if (status < 0) {
+ dev_err(data->dev,
"Error while requesting temperature measurement.\n");
goto exit;
}
msleep(BMP085_TEMP_CONVERSION_TIME);
- status = i2c_smbus_read_i2c_block_data(data->client,
- BMP085_CONVERSION_REGISTER_MSB, sizeof(tmp), (u8 *)&tmp);
- if (status < 0)
- goto exit;
- if (status != sizeof(tmp)) {
- dev_err(&data->client->dev,
+ status = regmap_bulk_read(data->regmap, BMP085_CONVERSION_REGISTER_MSB,
+ &tmp, sizeof(tmp));
+ if (status < 0) {
+ dev_err(data->dev,
"Error while reading temperature measurement result\n");
- status = -EIO;
goto exit;
}
data->raw_temperature = be16_to_cpu(tmp);
@@ -162,10 +147,11 @@ static s32 bmp085_update_raw_pressure(struct bmp085_data *data)
s32 status;
mutex_lock(&data->lock);
- status = i2c_smbus_write_byte_data(data->client, BMP085_CTRL_REG,
- BMP085_PRESSURE_MEASUREMENT + (data->oversampling_setting<<6));
- if (status != 0) {
- dev_err(&data->client->dev,
+ status = regmap_write(data->regmap, BMP085_CTRL_REG,
+ BMP085_PRESSURE_MEASUREMENT +
+ (data->oversampling_setting << 6));
+ if (status < 0) {
+ dev_err(data->dev,
"Error while requesting pressure measurement.\n");
goto exit;
}
@@ -174,14 +160,11 @@ static s32 bmp085_update_raw_pressure(struct bmp085_data *data)
msleep(2+(3 << data->oversampling_setting));
/* copy data into a u32 (4 bytes), but skip the first byte. */
- status = i2c_smbus_read_i2c_block_data(data->client,
- BMP085_CONVERSION_REGISTER_MSB, 3, ((u8 *)&tmp)+1);
- if (status < 0)
- goto exit;
- if (status != 3) {
- dev_err(&data->client->dev,
+ status = regmap_bulk_read(data->regmap, BMP085_CONVERSION_REGISTER_MSB,
+ ((u8 *)&tmp)+1, 3);
+ if (status < 0) {
+ dev_err(data->dev,
"Error while reading pressure measurement results\n");
- status = -EIO;
goto exit;
}
data->raw_pressure = be32_to_cpu((tmp));
@@ -193,7 +176,6 @@ exit:
return status;
}
-
/*
* This function starts the temperature measurement and returns the value
* in tenth of a degree celsius.
@@ -205,7 +187,7 @@ static s32 bmp085_get_temperature(struct bmp085_data *data, int *temperature)
int status;
status = bmp085_update_raw_temperature(data);
- if (status != 0)
+ if (status < 0)
goto exit;
x1 = ((data->raw_temperature - cali->AC6) * cali->AC5) >> 15;
@@ -222,8 +204,10 @@ exit:
/*
* This function starts the pressure measurement and returns the value
* in millibar. Since the pressure depends on the ambient temperature,
- * a temperature measurement is executed if the last known value is older
- * than one second.
+ * a temperature measurement is executed according to the given temperature
+ * measurement period (default is 1 sec boundary). This period could vary
+ * and needs to be adjusted according to the sensor environment, i.e. if big
+ * temperature variations then the temperature needs to be read out often.
*/
static s32 bmp085_get_pressure(struct bmp085_data *data, int *pressure)
{
@@ -234,16 +218,16 @@ static s32 bmp085_get_pressure(struct bmp085_data *data, int *pressure)
int status;
/* alt least every second force an update of the ambient temperature */
- if (data->last_temp_measurement == 0 ||
- time_is_before_jiffies(data->last_temp_measurement + 1*HZ)) {
+ if ((data->last_temp_measurement == 0) ||
+ time_is_before_jiffies(data->last_temp_measurement + 1*HZ)) {
status = bmp085_get_temperature(data, NULL);
- if (status != 0)
- goto exit;
+ if (status < 0)
+ return status;
}
status = bmp085_update_raw_pressure(data);
- if (status != 0)
- goto exit;
+ if (status < 0)
+ return status;
x1 = (data->b6 * data->b6) >> 12;
x1 *= cali->B2;
@@ -274,15 +258,14 @@ static s32 bmp085_get_pressure(struct bmp085_data *data, int *pressure)
*pressure = p;
-exit:
- return status;
+ return 0;
}
/*
* This function sets the chip-internal oversampling. Valid values are 0..3.
* The chip will use 2^oversampling samples for internal averaging.
* This influences the measurement time and the accuracy; larger values
- * increase both. The datasheet gives on overview on how measurement time,
+ * increase both. The datasheet gives an overview on how measurement time,
* accuracy and noise correlate.
*/
static void bmp085_set_oversampling(struct bmp085_data *data,
@@ -306,22 +289,25 @@ static ssize_t set_oversampling(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct bmp085_data *data = i2c_get_clientdata(client);
+ struct bmp085_data *data = dev_get_drvdata(dev);
unsigned long oversampling;
- int success = strict_strtoul(buf, 10, &oversampling);
- if (success == 0) {
+ int err = kstrtoul(buf, 10, &oversampling);
+
+ if (err == 0) {
+ mutex_lock(&data->lock);
bmp085_set_oversampling(data, oversampling);
+ mutex_unlock(&data->lock);
return count;
}
- return success;
+
+ return err;
}
static ssize_t show_oversampling(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct bmp085_data *data = i2c_get_clientdata(client);
+ struct bmp085_data *data = dev_get_drvdata(dev);
+
return sprintf(buf, "%u\n", bmp085_get_oversampling(data));
}
static DEVICE_ATTR(oversampling, S_IWUSR | S_IRUGO,
@@ -333,11 +319,10 @@ static ssize_t show_temperature(struct device *dev,
{
int temperature;
int status;
- struct i2c_client *client = to_i2c_client(dev);
- struct bmp085_data *data = i2c_get_clientdata(client);
+ struct bmp085_data *data = dev_get_drvdata(dev);
status = bmp085_get_temperature(data, &temperature);
- if (status != 0)
+ if (status < 0)
return status;
else
return sprintf(buf, "%d\n", temperature);
@@ -350,11 +335,10 @@ static ssize_t show_pressure(struct device *dev,
{
int pressure;
int status;
- struct i2c_client *client = to_i2c_client(dev);
- struct bmp085_data *data = i2c_get_clientdata(client);
+ struct bmp085_data *data = dev_get_drvdata(dev);
status = bmp085_get_pressure(data, &pressure);
- if (status != 0)
+ if (status < 0)
return status;
else
return sprintf(buf, "%d\n", pressure);
@@ -373,38 +357,70 @@ static const struct attribute_group bmp085_attr_group = {
.attrs = bmp085_attributes,
};
-static int bmp085_detect(struct i2c_client *client, struct i2c_board_info *info)
+int bmp085_detect(struct device *dev)
{
- if (client->addr != BMP085_I2C_ADDRESS)
- return -ENODEV;
+ struct bmp085_data *data = dev_get_drvdata(dev);
+ unsigned int id;
+ int ret;
- if (i2c_smbus_read_byte_data(client, BMP085_CHIP_ID_REG) != BMP085_CHIP_ID)
+ ret = regmap_read(data->regmap, BMP085_CHIP_ID_REG, &id);
+ if (ret < 0)
+ return ret;
+
+ if (id != data->chip_id)
return -ENODEV;
return 0;
}
+EXPORT_SYMBOL_GPL(bmp085_detect);
-static int bmp085_init_client(struct i2c_client *client)
+static void __init bmp085_get_of_properties(struct bmp085_data *data)
{
- unsigned char version;
- int status;
- struct bmp085_data *data = i2c_get_clientdata(client);
- data->client = client;
- status = bmp085_read_calibration_data(client);
- if (status != 0)
- goto exit;
- version = i2c_smbus_read_byte_data(client, BMP085_VERSION_REG);
+#ifdef CONFIG_OF
+ struct device_node *np = data->dev->of_node;
+ u32 prop;
+
+ if (!np)
+ return;
+
+ if (!of_property_read_u32(np, "chip-id", &prop))
+ data->chip_id = prop & 0xff;
+
+ if (!of_property_read_u32(np, "temp-measurement-period", &prop))
+ data->temp_measurement_period = (prop/100)*HZ;
+
+ if (!of_property_read_u32(np, "default-oversampling", &prop))
+ data->oversampling_setting = prop & 0xff;
+#endif
+}
+
+static int bmp085_init_client(struct bmp085_data *data)
+{
+ int status = bmp085_read_calibration_data(data);
+
+ if (status < 0)
+ return status;
+
+ /* default settings */
+ data->chip_id = BMP085_CHIP_ID;
data->last_temp_measurement = 0;
+ data->temp_measurement_period = 1*HZ;
data->oversampling_setting = 3;
+
+ bmp085_get_of_properties(data);
+
mutex_init(&data->lock);
- dev_info(&data->client->dev, "BMP085 ver. %d.%d found.\n",
- (version & 0x0F), (version & 0xF0) >> 4);
-exit:
- return status;
+
+ return 0;
}
-static int __devinit bmp085_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+struct regmap_config bmp085_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8
+};
+EXPORT_SYMBOL_GPL(bmp085_regmap_config);
+
+__devinit int bmp085_probe(struct device *dev, struct regmap *regmap)
{
struct bmp085_data *data;
int err = 0;
@@ -415,58 +431,48 @@ static int __devinit bmp085_probe(struct i2c_client *client,
goto exit;
}
- /* default settings after POR */
- data->oversampling_setting = 0x00;
-
- i2c_set_clientdata(client, data);
+ dev_set_drvdata(dev, data);
+ data->dev = dev;
+ data->regmap = regmap;
/* Initialize the BMP085 chip */
- err = bmp085_init_client(client);
- if (err != 0)
+ err = bmp085_init_client(data);
+ if (err < 0)
goto exit_free;
+ err = bmp085_detect(dev);
+ if (err < 0) {
+ dev_err(dev, "%s: chip_id failed!\n", BMP085_NAME);
+ goto exit_free;
+ }
+
/* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &bmp085_attr_group);
+ err = sysfs_create_group(&dev->kobj, &bmp085_attr_group);
if (err)
goto exit_free;
- dev_info(&data->client->dev, "Successfully initialized bmp085!\n");
- goto exit;
+ dev_info(dev, "Successfully initialized %s!\n", BMP085_NAME);
+
+ return 0;
exit_free:
kfree(data);
exit:
return err;
}
+EXPORT_SYMBOL_GPL(bmp085_probe);
-static int __devexit bmp085_remove(struct i2c_client *client)
+int bmp085_remove(struct device *dev)
{
- sysfs_remove_group(&client->dev.kobj, &bmp085_attr_group);
- kfree(i2c_get_clientdata(client));
- return 0;
-}
+ struct bmp085_data *data = dev_get_drvdata(dev);
-static const struct i2c_device_id bmp085_id[] = {
- { "bmp085", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, bmp085_id);
-
-static struct i2c_driver bmp085_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "bmp085"
- },
- .id_table = bmp085_id,
- .probe = bmp085_probe,
- .remove = __devexit_p(bmp085_remove),
-
- .detect = bmp085_detect,
- .address_list = normal_i2c
-};
+ sysfs_remove_group(&data->dev->kobj, &bmp085_attr_group);
+ kfree(data);
-module_i2c_driver(bmp085_driver);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bmp085_remove);
-MODULE_AUTHOR("Christoph Mair <christoph.mair@gmail.com");
+MODULE_AUTHOR("Christoph Mair <christoph.mair@gmail.com>");
MODULE_DESCRIPTION("BMP085 driver");
MODULE_LICENSE("GPL");
diff --git a/arch/arm/include/asm/hardware/ep7211.h b/drivers/misc/bmp085.h
index 654d5f625c49..2b8f615bca92 100644
--- a/arch/arm/include/asm/hardware/ep7211.h
+++ b/drivers/misc/bmp085.h
@@ -1,10 +1,6 @@
/*
- * arch/arm/include/asm/hardware/ep7211.h
- *
- * This file contains the hardware definitions of the EP7211 internal
- * registers.
- *
- * Copyright (C) 2001 Blue Mug, Inc. All Rights Reserved.
+ * Copyright (c) 2012 Bosch Sensortec GmbH
+ * Copyright (c) 2012 Unixphere AB
*
* 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
@@ -18,23 +14,20 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#ifndef __ASM_HARDWARE_EP7211_H
-#define __ASM_HARDWARE_EP7211_H
-#include <asm/hardware/clps7111.h>
+#ifndef _BMP085_H
+#define _BMP085_H
-/*
- * define EP7211_BASE to be the base address of the region
- * you want to access.
- */
+#include <linux/regmap.h>
-#define EP7211_PHYS_BASE (0x80000000)
+#define BMP085_NAME "bmp085"
-/*
- * XXX miket@bluemug.com: need to introduce EP7211 registers (those not
- * present in 7212) here.
- */
+extern struct regmap_config bmp085_regmap_config;
+
+int bmp085_probe(struct device *dev, struct regmap *regmap);
+int bmp085_remove(struct device *dev);
+int bmp085_detect(struct device *dev);
-#endif /* __ASM_HARDWARE_EP7211_H */
+#endif
diff --git a/drivers/misc/c2port/Kconfig b/drivers/misc/c2port/Kconfig
index e46af9a5810d..33ee834e1b83 100644
--- a/drivers/misc/c2port/Kconfig
+++ b/drivers/misc/c2port/Kconfig
@@ -5,7 +5,7 @@
menuconfig C2PORT
tristate "Silicon Labs C2 port support (EXPERIMENTAL)"
depends on EXPERIMENTAL
- default no
+ default n
help
This option enables support for Silicon Labs C2 port used to
program Silicon micro controller chips (and other 8051 compatible).
@@ -23,8 +23,8 @@ if C2PORT
config C2PORT_DURAMAR_2150
tristate "C2 port support for Eurotech's Duramar 2150 (EXPERIMENTAL)"
- depends on X86 && C2PORT
- default no
+ depends on X86
+ default n
help
This option enables C2 support for the Eurotech's Duramar 2150
on board micro controller.
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 01ab3c9b4cf7..0842c2994ee2 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -50,6 +50,7 @@ struct at25_data {
#define AT25_SR_BP1 0x08
#define AT25_SR_WPEN 0x80 /* writeprotect enable */
+#define AT25_INSTR_BIT3 0x08 /* Additional address bit in instr */
#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */
@@ -75,6 +76,7 @@ at25_ee_read(
ssize_t status;
struct spi_transfer t[2];
struct spi_message m;
+ u8 instr;
if (unlikely(offset >= at25->bin.size))
return 0;
@@ -84,7 +86,12 @@ at25_ee_read(
return count;
cp = command;
- *cp++ = AT25_READ;
+
+ instr = AT25_READ;
+ if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
+ if (offset >= (1U << (at25->addrlen * 8)))
+ instr |= AT25_INSTR_BIT3;
+ *cp++ = instr;
/* 8/16/24-bit address is written MSB first */
switch (at25->addrlen) {
@@ -167,14 +174,14 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
/* For write, rollover is within the page ... so we write at
* most one page, then manually roll over to the next page.
*/
- bounce[0] = AT25_WRITE;
mutex_lock(&at25->lock);
do {
unsigned long timeout, retries;
unsigned segment;
unsigned offset = (unsigned) off;
- u8 *cp = bounce + 1;
+ u8 *cp = bounce;
int sr;
+ u8 instr;
*cp = AT25_WREN;
status = spi_write(at25->spi, cp, 1);
@@ -184,6 +191,12 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
break;
}
+ instr = AT25_WRITE;
+ if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
+ if (offset >= (1U << (at25->addrlen * 8)))
+ instr |= AT25_INSTR_BIT3;
+ *cp++ = instr;
+
/* 8/16/24-bit address is written MSB first */
switch (at25->addrlen) {
default: /* case 3 */
diff --git a/drivers/staging/mei/Kconfig b/drivers/misc/mei/Kconfig
index 47d78a72db2e..47d78a72db2e 100644
--- a/drivers/staging/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
diff --git a/drivers/staging/mei/Makefile b/drivers/misc/mei/Makefile
index 57168db6c7e5..57168db6c7e5 100644
--- a/drivers/staging/mei/Makefile
+++ b/drivers/misc/mei/Makefile
diff --git a/drivers/staging/mei/hw.h b/drivers/misc/mei/hw.h
index 24c4c962819e..24c4c962819e 100644
--- a/drivers/staging/mei/hw.h
+++ b/drivers/misc/mei/hw.h
diff --git a/drivers/staging/mei/init.c b/drivers/misc/mei/init.c
index eab711fb5fc4..a7d0bb0880ec 100644
--- a/drivers/staging/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -22,7 +22,7 @@
#include "mei_dev.h"
#include "hw.h"
#include "interface.h"
-#include "mei.h"
+#include <linux/mei.h>
const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
0xa8, 0x46, 0xe0, 0xff, 0x65,
@@ -200,7 +200,7 @@ int mei_hw_init(struct mei_device *dev)
if (!(dev->me_hw_state & ME_RDY_HRA))
dev_dbg(&dev->pdev->dev, "ME turn off ME_RDY.\n");
- printk(KERN_ERR "mei: link layer initialization failed.\n");
+ dev_err(&dev->pdev->dev, "link layer initialization failed.\n");
ret = -ENODEV;
goto out;
}
diff --git a/drivers/staging/mei/interface.c b/drivers/misc/mei/interface.c
index 9a2cfafc52a6..428d21e36416 100644
--- a/drivers/staging/mei/interface.c
+++ b/drivers/misc/mei/interface.c
@@ -16,7 +16,7 @@
#include <linux/pci.h>
#include "mei_dev.h"
-#include "mei.h"
+#include <linux/mei.h>
#include "interface.h"
diff --git a/drivers/staging/mei/interface.h b/drivers/misc/mei/interface.h
index fb90c6f8a759..ddff5d16616f 100644
--- a/drivers/staging/mei/interface.h
+++ b/drivers/misc/mei/interface.h
@@ -19,7 +19,7 @@
#ifndef _MEI_INTERFACE_H_
#define _MEI_INTERFACE_H_
-#include "mei.h"
+#include <linux/mei.h>
#include "mei_dev.h"
@@ -51,8 +51,7 @@ int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl);
int mei_wd_send(struct mei_device *dev);
int mei_wd_stop(struct mei_device *dev, bool preserve);
-bool mei_wd_host_init(struct mei_device *dev);
-void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout);
+int mei_wd_host_init(struct mei_device *dev);
/*
* mei_watchdog_register - Registering watchdog interface
* once we got connection to the WD Client
diff --git a/drivers/staging/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 2007d2447b1c..93936f1b75eb 100644
--- a/drivers/staging/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -22,7 +22,7 @@
#include <linux/jiffies.h>
#include "mei_dev.h"
-#include "mei.h"
+#include <linux/mei.h>
#include "hw.h"
#include "interface.h"
diff --git a/drivers/staging/mei/iorw.c b/drivers/misc/mei/iorw.c
index 0a80dc4e62f3..f9cced69b65e 100644
--- a/drivers/staging/mei/iorw.c
+++ b/drivers/misc/mei/iorw.c
@@ -35,7 +35,7 @@
#include "mei_dev.h"
#include "hw.h"
-#include "mei.h"
+#include <linux/mei.h>
#include "interface.h"
diff --git a/drivers/staging/mei/main.c b/drivers/misc/mei/main.c
index 7c9321fa7bb1..c70333228337 100644
--- a/drivers/staging/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -14,6 +14,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -36,19 +38,10 @@
#include <linux/miscdevice.h>
#include "mei_dev.h"
-#include "mei.h"
+#include <linux/mei.h>
#include "interface.h"
-
-#define MEI_READ_TIMEOUT 45
-#define MEI_DRIVER_NAME "mei"
-#define MEI_DEV_NAME "mei"
-
-/*
- * mei driver strings
- */
-static char mei_driver_name[] = MEI_DRIVER_NAME;
-static const char mei_driver_string[] = "Intel(R) Management Engine Interface";
+static const char mei_driver_name[] = "mei";
/* The device pointer */
/* Currently this driver works as long as there is only a single AMT device. */
@@ -931,7 +924,7 @@ static const struct file_operations mei_fops = {
* Misc Device Struct
*/
static struct miscdevice mei_misc_device = {
- .name = MEI_DRIVER_NAME,
+ .name = "mei",
.fops = &mei_fops,
.minor = MISC_DYNAMIC_MINOR,
};
@@ -958,7 +951,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
/* enable pci dev */
err = pci_enable_device(pdev);
if (err) {
- printk(KERN_ERR "mei: Failed to enable pci device.\n");
+ dev_err(&pdev->dev, "failed to enable pci device.\n");
goto end;
}
/* set PCI host mastering */
@@ -966,7 +959,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
/* pci request regions for mei driver */
err = pci_request_regions(pdev, mei_driver_name);
if (err) {
- printk(KERN_ERR "mei: Failed to get pci regions.\n");
+ dev_err(&pdev->dev, "failed to get pci regions.\n");
goto disable_device;
}
/* allocates and initializes the mei dev structure */
@@ -978,7 +971,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
/* mapping IO device memory */
dev->mem_addr = pci_iomap(pdev, 0, 0);
if (!dev->mem_addr) {
- printk(KERN_ERR "mei: mapping I/O device memory failure.\n");
+ dev_err(&pdev->dev, "mapping I/O device memory failure.\n");
err = -ENOMEM;
goto free_device;
}
@@ -997,13 +990,13 @@ static int __devinit mei_probe(struct pci_dev *pdev,
IRQF_SHARED, mei_driver_name, dev);
if (err) {
- printk(KERN_ERR "mei: request_threaded_irq failure. irq = %d\n",
+ dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
pdev->irq);
goto unmap_memory;
}
INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
if (mei_hw_init(dev)) {
- printk(KERN_ERR "mei: Init hw failure.\n");
+ dev_err(&pdev->dev, "init hw failure.\n");
err = -ENODEV;
goto release_irq;
}
@@ -1020,7 +1013,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
mutex_unlock(&mei_mutex);
- pr_debug("mei: Driver initialization successful.\n");
+ pr_debug("initialization successful.\n");
return 0;
@@ -1041,7 +1034,7 @@ disable_device:
pci_disable_device(pdev);
end:
mutex_unlock(&mei_mutex);
- printk(KERN_ERR "mei: Driver initialization failed.\n");
+ dev_err(&pdev->dev, "initialization failed.\n");
return err;
}
@@ -1160,8 +1153,8 @@ static int mei_pci_resume(struct device *device)
IRQF_SHARED, mei_driver_name, dev);
if (err) {
- printk(KERN_ERR "mei: Request_irq failure. irq = %d\n",
- pdev->irq);
+ dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
+ pdev->irq);
return err;
}
@@ -1204,11 +1197,11 @@ static int __init mei_init_module(void)
{
int ret;
- pr_debug("mei: %s\n", mei_driver_string);
+ pr_debug("loading.\n");
/* init pci module */
ret = pci_register_driver(&mei_driver);
if (ret < 0)
- printk(KERN_ERR "mei: Error registering driver.\n");
+ pr_err("error registering driver.\n");
return ret;
}
@@ -1226,7 +1219,7 @@ static void __exit mei_exit_module(void)
misc_deregister(&mei_misc_device);
pci_unregister_driver(&mei_driver);
- pr_debug("mei: Driver unloaded successfully.\n");
+ pr_debug("unloaded successfully.\n");
}
module_exit(mei_exit_module);
diff --git a/drivers/staging/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 10b1b4e2f8ac..63d7ee97c5fb 100644
--- a/drivers/staging/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -19,7 +19,7 @@
#include <linux/types.h>
#include <linux/watchdog.h>
-#include "mei.h"
+#include <linux/mei.h>
#include "hw.h"
/*
diff --git a/drivers/staging/mei/wd.c b/drivers/misc/mei/wd.c
index cf4c29d10e7f..6be5605707b4 100644
--- a/drivers/staging/mei/wd.c
+++ b/drivers/misc/mei/wd.c
@@ -24,7 +24,7 @@
#include "mei_dev.h"
#include "hw.h"
#include "interface.h"
-#include "mei.h"
+#include <linux/mei.h>
static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 };
@@ -45,23 +45,22 @@ const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89,
0x9D, 0xA9, 0x15, 0x14, 0xCB,
0x32, 0xAB);
-void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
+static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
{
- dev_dbg(&dev->pdev->dev, "timeout=%d.\n", timeout);
+ dev_dbg(&dev->pdev->dev, "wd: set timeout=%d.\n", timeout);
memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE);
- memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE,
- &timeout, sizeof(u16));
+ memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE, &timeout, sizeof(u16));
}
/**
* host_init_wd - mei initialization wd.
*
* @dev: the device structure
+ * returns -ENENT if wd client cannot be found
+ * -EIO if write has failed
*/
-bool mei_wd_host_init(struct mei_device *dev)
+int mei_wd_host_init(struct mei_device *dev)
{
- bool ret = false;
-
mei_cl_init(&dev->wd_cl, dev);
/* look for WD client and connect to it */
@@ -72,25 +71,21 @@ bool mei_wd_host_init(struct mei_device *dev)
mei_find_me_client_update_filext(dev, &dev->wd_cl,
&mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
- dev_dbg(&dev->pdev->dev, "check wd_cl\n");
- if (MEI_FILE_CONNECTING == dev->wd_cl.state) {
- if (mei_connect(dev, &dev->wd_cl)) {
- dev_dbg(&dev->pdev->dev, "Failed to connect to WD client\n");
- dev->wd_cl.state = MEI_FILE_DISCONNECTED;
- dev->wd_cl.host_client_id = 0;
- ret = false;
- goto end;
- } else {
- dev->wd_cl.timer_count = CONNECT_TIMEOUT;
- }
- } else {
- dev_dbg(&dev->pdev->dev, "Failed to find WD client\n");
- ret = false;
- goto end;
+ dev_dbg(&dev->pdev->dev, "wd: check client\n");
+ if (MEI_FILE_CONNECTING != dev->wd_cl.state) {
+ dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
+ return -ENOENT;
}
-end:
- return ret;
+ if (mei_connect(dev, &dev->wd_cl)) {
+ dev_err(&dev->pdev->dev, "wd: failed to connect to the client\n");
+ dev->wd_cl.state = MEI_FILE_DISCONNECTED;
+ dev->wd_cl.host_client_id = 0;
+ return -EIO;
+ }
+ dev->wd_cl.timer_count = CONNECT_TIMEOUT;
+
+ return 0;
}
/**
@@ -159,7 +154,7 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
if (ret)
goto out;
} else {
- dev_dbg(&dev->pdev->dev, "send stop WD failed\n");
+ dev_err(&dev->pdev->dev, "wd: send stop failed\n");
}
dev->wd_pending = false;
@@ -173,13 +168,13 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
dev->wd_stopped, 10 * HZ);
mutex_lock(&dev->device_lock);
if (dev->wd_stopped) {
- dev_dbg(&dev->pdev->dev, "stop wd complete ret=%d.\n", ret);
+ dev_dbg(&dev->pdev->dev, "wd: stop completed ret=%d.\n", ret);
ret = 0;
} else {
if (!ret)
ret = -ETIMEDOUT;
dev_warn(&dev->pdev->dev,
- "stop wd failed to complete ret=%d.\n", ret);
+ "wd: stop failed to complete ret=%d.\n", ret);
}
if (preserve)
@@ -208,13 +203,15 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev)
mutex_lock(&dev->device_lock);
if (dev->mei_state != MEI_ENABLED) {
- dev_dbg(&dev->pdev->dev, "mei_state != MEI_ENABLED mei_state= %d\n",
- dev->mei_state);
+ dev_dbg(&dev->pdev->dev,
+ "wd: mei_state != MEI_ENABLED mei_state = %d\n",
+ dev->mei_state);
goto end_unlock;
}
if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
- dev_dbg(&dev->pdev->dev, "MEI Driver is not connected to Watchdog Client\n");
+ dev_dbg(&dev->pdev->dev,
+ "MEI Driver is not connected to Watchdog Client\n");
goto end_unlock;
}
@@ -267,7 +264,7 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
mutex_lock(&dev->device_lock);
if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
- dev_dbg(&dev->pdev->dev, "wd is not connected.\n");
+ dev_err(&dev->pdev->dev, "wd: not connected.\n");
ret = -ENODEV;
goto end;
}
@@ -277,16 +274,17 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
dev->mei_host_buffer_is_empty = false;
- dev_dbg(&dev->pdev->dev, "sending watchdog ping\n");
+ dev_dbg(&dev->pdev->dev, "wd: sending ping\n");
if (mei_wd_send(dev)) {
- dev_dbg(&dev->pdev->dev, "wd send failed.\n");
+ dev_err(&dev->pdev->dev, "wd: send failed.\n");
ret = -EIO;
goto end;
}
if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) {
- dev_dbg(&dev->pdev->dev, "mei_flow_ctrl_reduce() failed.\n");
+ dev_err(&dev->pdev->dev,
+ "wd: mei_flow_ctrl_reduce() failed.\n");
ret = -EIO;
goto end;
}
@@ -346,7 +344,7 @@ static const struct watchdog_info wd_info = {
.options = WDIOF_KEEPALIVEPING,
};
-struct watchdog_device amt_wd_dev = {
+static struct watchdog_device amt_wd_dev = {
.info = &wd_info,
.ops = &wd_ops,
.timeout = AMT_WD_DEFAULT_TIMEOUT,
@@ -362,10 +360,12 @@ void mei_watchdog_register(struct mei_device *dev)
dev->wd_due_counter = !!dev->wd_timeout;
if (watchdog_register_device(&amt_wd_dev)) {
- dev_err(&dev->pdev->dev, "unable to register watchdog device.\n");
+ dev_err(&dev->pdev->dev,
+ "wd: unable to register watchdog device.\n");
dev->wd_interface_reg = false;
} else {
- dev_dbg(&dev->pdev->dev, "successfully register watchdog interface.\n");
+ dev_dbg(&dev->pdev->dev,
+ "wd: successfully register watchdog interface.\n");
dev->wd_interface_reg = true;
}
}
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
index 10fc4785dba7..9fbcacd703d5 100644
--- a/drivers/misc/pch_phub.c
+++ b/drivers/misc/pch_phub.c
@@ -65,10 +65,6 @@
#define PCI_VENDOR_ID_ROHM 0x10db
#define PCI_DEVICE_ID_ROHM_ML7213_PHUB 0x801A
-/* Macros for ML7213 */
-#define PCI_VENDOR_ID_ROHM 0x10db
-#define PCI_DEVICE_ID_ROHM_ML7213_PHUB 0x801A
-
/* Macros for ML7223 */
#define PCI_DEVICE_ID_ROHM_ML7223_mPHUB 0x8012 /* for Bus-m */
#define PCI_DEVICE_ID_ROHM_ML7223_nPHUB 0x8002 /* for Bus-n */
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
index 383133b201a1..b7eb545394b1 100644
--- a/drivers/misc/pti.c
+++ b/drivers/misc/pti.c
@@ -888,7 +888,7 @@ static struct pci_driver pti_pci_driver = {
.name = PCINAME,
.id_table = pci_ids,
.probe = pti_pci_probe,
- .remove = pti_pci_remove,
+ .remove = __devexit_p(pti_pci_remove),
};
/**
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 032b84791a16..b6f38421d541 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -94,6 +94,17 @@ static struct variant_data variant_u300 = {
.signal_direction = true,
};
+static struct variant_data variant_nomadik = {
+ .fifosize = 16 * 4,
+ .fifohalfsize = 8 * 4,
+ .clkreg = MCI_CLK_ENABLE,
+ .datalength_bits = 24,
+ .sdio = true,
+ .st_clkdiv = true,
+ .pwrreg_powerup = MCI_PWR_ON,
+ .signal_direction = true,
+};
+
static struct variant_data variant_ux500 = {
.fifosize = 30 * 4,
.fifohalfsize = 8 * 4,
@@ -1397,7 +1408,7 @@ static int __devinit mmci_probe(struct amba_device *dev,
if (ret)
goto unmap;
- if (dev->irq[1] == NO_IRQ || !dev->irq[1])
+ if (!dev->irq[1])
host->singleirq = true;
else {
ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED,
@@ -1569,6 +1580,11 @@ static struct amba_id mmci_ids[] = {
.data = &variant_u300,
},
{
+ .id = 0x10180180,
+ .mask = 0xf0ffffff,
+ .data = &variant_nomadik,
+ },
+ {
.id = 0x00280180,
.mask = 0x00ffffff,
.data = &variant_u300,
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index e3f5af96ab87..bb03ddda481d 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -39,6 +39,7 @@
#include <linux/regulator/consumer.h>
#include <linux/module.h>
#include <linux/fsl/mxs-dma.h>
+#include <linux/pinctrl/consumer.h>
#include <mach/mxs.h>
#include <mach/common.h>
@@ -682,6 +683,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
struct mmc_host *mmc;
struct resource *iores, *dmares, *r;
struct mxs_mmc_platform_data *pdata;
+ struct pinctrl *pinctrl;
int ret = 0, irq_err, irq_dma;
dma_cap_mask_t mask;
@@ -719,6 +721,12 @@ static int mxs_mmc_probe(struct platform_device *pdev)
host->irq = irq_err;
host->sdio_irq_en = 0;
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ goto out_iounmap;
+ }
+
host->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(host->clk)) {
ret = PTR_ERR(host->clk);
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 8abdaf6697a8..d190d04636a7 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -24,6 +24,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
#include <mach/esdhc.h>
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
@@ -68,6 +69,7 @@ struct pltfm_imx_data {
int flags;
u32 scratchpad;
enum imx_esdhc_type devtype;
+ struct pinctrl *pinctrl;
struct esdhc_platform_data boarddata;
};
@@ -467,6 +469,12 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
clk_prepare_enable(clk);
pltfm_host->clk = clk;
+ imx_data->pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(imx_data->pinctrl)) {
+ err = PTR_ERR(imx_data->pinctrl);
+ goto pin_err;
+ }
+
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data))
@@ -558,6 +566,7 @@ no_card_detect_irq:
gpio_free(boarddata->wp_gpio);
no_card_detect_pin:
no_board_data:
+pin_err:
clk_disable_unprepare(pltfm_host->clk);
clk_put(pltfm_host->clk);
err_clk_get:
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 53b26502f6e2..ff5a16991939 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -269,7 +269,6 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
"failed to allocate power gpio\n");
goto err_power_req;
}
- tegra_gpio_enable(plat->power_gpio);
gpio_direction_output(plat->power_gpio, 1);
}
@@ -280,7 +279,6 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
"failed to allocate cd gpio\n");
goto err_cd_req;
}
- tegra_gpio_enable(plat->cd_gpio);
gpio_direction_input(plat->cd_gpio);
rc = request_irq(gpio_to_irq(plat->cd_gpio), carddetect_irq,
@@ -301,7 +299,6 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
"failed to allocate wp gpio\n");
goto err_wp_req;
}
- tegra_gpio_enable(plat->wp_gpio);
gpio_direction_input(plat->wp_gpio);
}
@@ -329,23 +326,17 @@ err_add_host:
clk_disable(pltfm_host->clk);
clk_put(pltfm_host->clk);
err_clk_get:
- if (gpio_is_valid(plat->wp_gpio)) {
- tegra_gpio_disable(plat->wp_gpio);
+ if (gpio_is_valid(plat->wp_gpio))
gpio_free(plat->wp_gpio);
- }
err_wp_req:
if (gpio_is_valid(plat->cd_gpio))
free_irq(gpio_to_irq(plat->cd_gpio), host);
err_cd_irq_req:
- if (gpio_is_valid(plat->cd_gpio)) {
- tegra_gpio_disable(plat->cd_gpio);
+ if (gpio_is_valid(plat->cd_gpio))
gpio_free(plat->cd_gpio);
- }
err_cd_req:
- if (gpio_is_valid(plat->power_gpio)) {
- tegra_gpio_disable(plat->power_gpio);
+ if (gpio_is_valid(plat->power_gpio))
gpio_free(plat->power_gpio);
- }
err_power_req:
err_no_plat:
sdhci_pltfm_free(pdev);
@@ -362,21 +353,16 @@ static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
sdhci_remove_host(host, dead);
- if (gpio_is_valid(plat->wp_gpio)) {
- tegra_gpio_disable(plat->wp_gpio);
+ if (gpio_is_valid(plat->wp_gpio))
gpio_free(plat->wp_gpio);
- }
if (gpio_is_valid(plat->cd_gpio)) {
free_irq(gpio_to_irq(plat->cd_gpio), host);
- tegra_gpio_disable(plat->cd_gpio);
gpio_free(plat->cd_gpio);
}
- if (gpio_is_valid(plat->power_gpio)) {
- tegra_gpio_disable(plat->power_gpio);
+ if (gpio_is_valid(plat->power_gpio))
gpio_free(plat->power_gpio);
- }
clk_disable(pltfm_host->clk);
clk_put(pltfm_host->clk);
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
index 8272c02668d6..50aa90aa7a7f 100644
--- a/drivers/mtd/devices/docg3.c
+++ b/drivers/mtd/devices/docg3.c
@@ -383,7 +383,7 @@ static void doc_set_device_id(struct docg3 *docg3, int id)
* leveling counters are stored. To access this last area of 4 bytes, a special
* mode must be input to the flash ASIC.
*
- * Returns 0 if no error occured, -EIO else.
+ * Returns 0 if no error occurred, -EIO else.
*/
static int doc_set_extra_page_mode(struct docg3 *docg3)
{
@@ -681,7 +681,7 @@ out:
* - one read of 512 bytes at offset 0
* - one read of 512 bytes at offset 512 + 16
*
- * Returns 0 if successful, -EIO if a read error occured.
+ * Returns 0 if successful, -EIO if a read error occurred.
*/
static int doc_read_page_prepare(struct docg3 *docg3, int block0, int block1,
int page, int offset)
@@ -839,7 +839,7 @@ static void calc_block_sector(loff_t from, int *block0, int *block1, int *page,
*
* Reads flash memory OOB area of pages.
*
- * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured
+ * Returns 0 if read successful, of -EIO, -EINVAL if an error occurred
*/
static int doc_read_oob(struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops)
@@ -971,7 +971,7 @@ err_in_read:
* Reads flash memory pages. This function does not read the OOB chunk, but only
* the page data.
*
- * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured
+ * Returns 0 if read successful, of -EIO, -EINVAL if an error occurred
*/
static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf)
@@ -1109,7 +1109,7 @@ static int doc_get_op_status(struct docg3 *docg3)
* Wait for the chip to be ready again after erase or write operation, and check
* erase/write status.
*
- * Returns 0 if erase successfull, -EIO if erase/write issue, -ETIMEOUT if
+ * Returns 0 if erase successful, -EIO if erase/write issue, -ETIMEOUT if
* timeout
*/
static int doc_write_erase_wait_status(struct docg3 *docg3)
@@ -1186,7 +1186,7 @@ static int doc_erase_block(struct docg3 *docg3, int block0, int block1)
* Erase a bunch of contiguous blocks, by pairs, as a "mtd" page of 1024 is
* split into 2 pages of 512 bytes on 2 contiguous blocks.
*
- * Returns 0 if erase successful, -EINVAL if adressing error, -EIO if erase
+ * Returns 0 if erase successful, -EINVAL if addressing error, -EIO if erase
* issue
*/
static int doc_erase(struct mtd_info *mtd, struct erase_info *info)
@@ -1397,7 +1397,7 @@ static int doc_backup_oob(struct docg3 *docg3, loff_t to,
* Or provide data without OOB, and then a all zeroed OOB will be used (ECC will
* still be filled in if asked for).
*
- * Returns 0 is successfull, EINVAL if length is not 14 bytes
+ * Returns 0 is successful, EINVAL if length is not 14 bytes
*/
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
struct mtd_oob_ops *ops)
@@ -1945,7 +1945,7 @@ static void doc_release_device(struct mtd_info *mtd)
* docg3_resume - Awakens docg3 floor
* @pdev: platfrom device
*
- * Returns 0 (always successfull)
+ * Returns 0 (always successful)
*/
static int docg3_resume(struct platform_device *pdev)
{
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
index 2e42ec2e8ff4..04769a49a7cb 100644
--- a/drivers/mtd/nand/autcpu12.c
+++ b/drivers/mtd/nand/autcpu12.c
@@ -102,10 +102,10 @@ static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd,
void __iomem *addr;
unsigned char bits;
- addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
- bits = (ctrl & NAND_CLE) << 4;
+ bits = clps_readb(AUTCPU12_SMC_PORT_OFFSET) & ~0x30;
+ bits |= (ctrl & NAND_CLE) << 4;
bits |= (ctrl & NAND_ALE) << 2;
- writeb((readb(addr) & ~0x30) | bits, addr);
+ clps_writeb(bits, AUTCPU12_SMC_PORT_OFFSET);
addr = autcpu12_fio_base + AUTCPU12_SMC_SELECT_OFFSET;
writeb((readb(addr) & ~0x1) | (ctrl & NAND_NCE), addr);
@@ -120,9 +120,7 @@ static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd,
*/
int autcpu12_device_ready(struct mtd_info *mtd)
{
- void __iomem *addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
-
- return readb(addr) & AUTCPU12_SMC_RDY;
+ return clps_readb(AUTCPU12_SMC_PORT_OFFSET) & AUTCPU12_SMC_RDY;
}
/*
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 9ec51cec2e14..b68e04310bd8 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/mtd/gpmi-nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/pinctrl/consumer.h>
#include "gpmi-nand.h"
/* add our owner bbt descriptor */
@@ -476,6 +477,7 @@ acquire_err:
static int __devinit acquire_resources(struct gpmi_nand_data *this)
{
struct resources *res = &this->resources;
+ struct pinctrl *pinctrl;
int ret;
ret = acquire_register_block(this, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME);
@@ -494,6 +496,12 @@ static int __devinit acquire_resources(struct gpmi_nand_data *this)
if (ret)
goto exit_dma_channels;
+ pinctrl = devm_pinctrl_get_select_default(&this->pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ goto exit_pin;
+ }
+
res->clock = clk_get(&this->pdev->dev, NULL);
if (IS_ERR(res->clock)) {
pr_err("can not get the clock\n");
@@ -503,6 +511,7 @@ static int __devinit acquire_resources(struct gpmi_nand_data *this)
return 0;
exit_clock:
+exit_pin:
release_dma_channels(this);
exit_dma_channels:
release_bch_irq(this);
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c
index 11e487813428..9bf5ce5fa22d 100644
--- a/drivers/mtd/nand/h1910.c
+++ b/drivers/mtd/nand/h1910.c
@@ -24,7 +24,7 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
-#include <mach/hardware.h> /* for CLPS7111_VIRT_BASE */
+#include <mach/hardware.h>
#include <asm/sizes.h>
#include <mach/h1900-gpio.h>
#include <mach/ipaq.h>
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index 1d3bfb26080c..0f50ef38b87b 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/of.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
@@ -74,11 +75,13 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static int __init orion_nand_probe(struct platform_device *pdev)
{
struct mtd_info *mtd;
+ struct mtd_part_parser_data ppdata = {};
struct nand_chip *nc;
struct orion_nand_data *board;
struct resource *res;
void __iomem *io_base;
int ret = 0;
+ u32 val = 0;
nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL);
if (!nc) {
@@ -101,7 +104,32 @@ static int __init orion_nand_probe(struct platform_device *pdev)
goto no_res;
}
- board = pdev->dev.platform_data;
+ if (pdev->dev.of_node) {
+ board = devm_kzalloc(&pdev->dev, sizeof(struct orion_nand_data),
+ GFP_KERNEL);
+ if (!board) {
+ printk(KERN_ERR "orion_nand: failed to allocate board structure.\n");
+ ret = -ENOMEM;
+ goto no_res;
+ }
+ if (!of_property_read_u32(pdev->dev.of_node, "cle", &val))
+ board->cle = (u8)val;
+ else
+ board->cle = 0;
+ if (!of_property_read_u32(pdev->dev.of_node, "ale", &val))
+ board->ale = (u8)val;
+ else
+ board->ale = 1;
+ if (!of_property_read_u32(pdev->dev.of_node,
+ "bank-width", &val))
+ board->width = (u8)val * 8;
+ else
+ board->width = 8;
+ if (!of_property_read_u32(pdev->dev.of_node,
+ "chip-delay", &val))
+ board->chip_delay = (u8)val;
+ } else
+ board = pdev->dev.platform_data;
mtd->priv = nc;
mtd->owner = THIS_MODULE;
@@ -115,6 +143,10 @@ static int __init orion_nand_probe(struct platform_device *pdev)
if (board->chip_delay)
nc->chip_delay = board->chip_delay;
+ WARN(board->width > 16,
+ "%d bit bus width out of range",
+ board->width);
+
if (board->width == 16)
nc->options |= NAND_BUSWIDTH_16;
@@ -129,8 +161,9 @@ static int __init orion_nand_probe(struct platform_device *pdev)
}
mtd->name = "orion_nand";
- ret = mtd_device_parse_register(mtd, NULL, NULL, board->parts,
- board->nr_parts);
+ ppdata.of_node = pdev->dev.of_node;
+ ret = mtd_device_parse_register(mtd, NULL, &ppdata,
+ board->parts, board->nr_parts);
if (ret) {
nand_release(mtd);
goto no_dev;
@@ -161,11 +194,19 @@ static int __devexit orion_nand_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static struct of_device_id orion_nand_of_match_table[] = {
+ { .compatible = "mrvl,orion-nand", },
+ {},
+};
+#endif
+
static struct platform_driver orion_nand_driver = {
.remove = __devexit_p(orion_nand_remove),
.driver = {
.name = "orion_nand",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(orion_nand_of_match_table),
},
};
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index 4dcc752a0c0b..738ee8dc16cd 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -52,12 +52,4 @@ config MTD_UBI_GLUEBI
work on top of UBI. Do not enable this unless you use legacy
software.
-config MTD_UBI_DEBUG
- bool "UBI debugging"
- depends on SYSFS
- select DEBUG_FS
- select KALLSYMS
- help
- This option enables UBI debugging.
-
endif # MTD_UBI
diff --git a/drivers/mtd/ubi/Makefile b/drivers/mtd/ubi/Makefile
index c9302a5452b0..a0803ac74712 100644
--- a/drivers/mtd/ubi/Makefile
+++ b/drivers/mtd/ubi/Makefile
@@ -1,7 +1,6 @@
obj-$(CONFIG_MTD_UBI) += ubi.o
-ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o scan.o
-ubi-y += misc.o
+ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o
+ubi-y += misc.o debug.o
-ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o
obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/attach.c
index 12c43b44f815..bd27cbbb4066 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/attach.c
@@ -19,21 +19,21 @@
*/
/*
- * UBI scanning sub-system.
+ * UBI attaching sub-system.
*
- * This sub-system is responsible for scanning the flash media, checking UBI
- * headers and providing complete information about the UBI flash image.
+ * This sub-system is responsible for attaching MTD devices and it also
+ * implements flash media scanning.
*
- * The scanning information is represented by a &struct ubi_scan_info' object.
- * Information about found volumes is represented by &struct ubi_scan_volume
+ * The attaching information is represented by a &struct ubi_attach_info'
+ * object. Information about volumes is represented by &struct ubi_ainf_volume
* objects which are kept in volume RB-tree with root at the @volumes field.
* The RB-tree is indexed by the volume ID.
*
- * Scanned logical eraseblocks are represented by &struct ubi_scan_leb objects.
- * These objects are kept in per-volume RB-trees with the root at the
- * corresponding &struct ubi_scan_volume object. To put it differently, we keep
- * an RB-tree of per-volume objects and each of these objects is the root of
- * RB-tree of per-eraseblock objects.
+ * Logical eraseblocks are represented by &struct ubi_ainf_peb objects. These
+ * objects are kept in per-volume RB-trees with the root at the corresponding
+ * &struct ubi_ainf_volume object. To put it differently, we keep an RB-tree of
+ * per-volume objects and each of these objects is the root of RB-tree of
+ * per-LEB objects.
*
* Corrupted physical eraseblocks are put to the @corr list, free physical
* eraseblocks are put to the @free list and the physical eraseblock to be
@@ -51,28 +51,29 @@
*
* 1. Corruptions caused by power cuts. These are expected corruptions and UBI
* tries to handle them gracefully, without printing too many warnings and
- * error messages. The idea is that we do not lose important data in these case
- * - we may lose only the data which was being written to the media just before
- * the power cut happened, and the upper layers (e.g., UBIFS) are supposed to
- * handle such data losses (e.g., by using the FS journal).
+ * error messages. The idea is that we do not lose important data in these
+ * cases - we may lose only the data which were being written to the media just
+ * before the power cut happened, and the upper layers (e.g., UBIFS) are
+ * supposed to handle such data losses (e.g., by using the FS journal).
*
* When UBI detects a corruption (CRC-32 mismatch) in a PEB, and it looks like
* the reason is a power cut, UBI puts this PEB to the @erase list, and all
* PEBs in the @erase list are scheduled for erasure later.
*
* 2. Unexpected corruptions which are not caused by power cuts. During
- * scanning, such PEBs are put to the @corr list and UBI preserves them.
+ * attaching, such PEBs are put to the @corr list and UBI preserves them.
* Obviously, this lessens the amount of available PEBs, and if at some point
* UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly informs
* about such PEBs every time the MTD device is attached.
*
* However, it is difficult to reliably distinguish between these types of
- * corruptions and UBI's strategy is as follows. UBI assumes corruption type 2
- * if the VID header is corrupted and the data area does not contain all 0xFFs,
- * and there were no bit-flips or integrity errors while reading the data area.
- * Otherwise UBI assumes corruption type 1. So the decision criteria are as
- * follows.
- * o If the data area contains only 0xFFs, there is no data, and it is safe
+ * corruptions and UBI's strategy is as follows (in case of attaching by
+ * scanning). UBI assumes corruption type 2 if the VID header is corrupted and
+ * the data area does not contain all 0xFFs, and there were no bit-flips or
+ * integrity errors (e.g., ECC errors in case of NAND) while reading the data
+ * area. Otherwise UBI assumes corruption type 1. So the decision criteria
+ * are as follows.
+ * o If the data area contains only 0xFFs, there are no data, and it is safe
* to just erase this PEB - this is corruption type 1.
* o If the data area has bit-flips or data integrity errors (ECC errors on
* NAND), it is probably a PEB which was being erased when power cut
@@ -88,11 +89,7 @@
#include <linux/random.h>
#include "ubi.h"
-#ifdef CONFIG_MTD_UBI_DEBUG
-static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si);
-#else
-#define paranoid_check_si(ubi, si) 0
-#endif
+static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai);
/* Temporary variables used during scanning */
static struct ubi_ec_hdr *ech;
@@ -100,13 +97,18 @@ static struct ubi_vid_hdr *vidh;
/**
* add_to_list - add physical eraseblock to a list.
- * @si: scanning information
+ * @ai: attaching information
* @pnum: physical eraseblock number to add
+ * @vol_id: the last used volume id for the PEB
+ * @lnum: the last used LEB number for the PEB
* @ec: erase counter of the physical eraseblock
* @to_head: if not zero, add to the head of the list
* @list: the list to add to
*
- * This function adds physical eraseblock @pnum to free, erase, or alien lists.
+ * This function allocates a 'struct ubi_ainf_peb' object for physical
+ * eraseblock @pnum and adds it to the "free", "erase", or "alien" lists.
+ * It stores the @lnum and @vol_id alongside, which can both be
+ * %UBI_UNKNOWN if they are not available, not readable, or not assigned.
* If @to_head is not zero, PEB will be added to the head of the list, which
* basically means it will be processed first later. E.g., we add corrupted
* PEBs (corrupted due to power cuts) to the head of the erase list to make
@@ -114,65 +116,68 @@ static struct ubi_vid_hdr *vidh;
* returns zero in case of success and a negative error code in case of
* failure.
*/
-static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head,
- struct list_head *list)
+static int add_to_list(struct ubi_attach_info *ai, int pnum, int vol_id,
+ int lnum, int ec, int to_head, struct list_head *list)
{
- struct ubi_scan_leb *seb;
+ struct ubi_ainf_peb *aeb;
- if (list == &si->free) {
+ if (list == &ai->free) {
dbg_bld("add to free: PEB %d, EC %d", pnum, ec);
- } else if (list == &si->erase) {
+ } else if (list == &ai->erase) {
dbg_bld("add to erase: PEB %d, EC %d", pnum, ec);
- } else if (list == &si->alien) {
+ } else if (list == &ai->alien) {
dbg_bld("add to alien: PEB %d, EC %d", pnum, ec);
- si->alien_peb_count += 1;
+ ai->alien_peb_count += 1;
} else
BUG();
- seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
- if (!seb)
+ aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL);
+ if (!aeb)
return -ENOMEM;
- seb->pnum = pnum;
- seb->ec = ec;
+ aeb->pnum = pnum;
+ aeb->vol_id = vol_id;
+ aeb->lnum = lnum;
+ aeb->ec = ec;
if (to_head)
- list_add(&seb->u.list, list);
+ list_add(&aeb->u.list, list);
else
- list_add_tail(&seb->u.list, list);
+ list_add_tail(&aeb->u.list, list);
return 0;
}
/**
* add_corrupted - add a corrupted physical eraseblock.
- * @si: scanning information
+ * @ai: attaching information
* @pnum: physical eraseblock number to add
* @ec: erase counter of the physical eraseblock
*
- * This function adds corrupted physical eraseblock @pnum to the 'corr' list.
- * The corruption was presumably not caused by a power cut. Returns zero in
- * case of success and a negative error code in case of failure.
+ * This function allocates a 'struct ubi_ainf_peb' object for a corrupted
+ * physical eraseblock @pnum and adds it to the 'corr' list. The corruption
+ * was presumably not caused by a power cut. Returns zero in case of success
+ * and a negative error code in case of failure.
*/
-static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec)
+static int add_corrupted(struct ubi_attach_info *ai, int pnum, int ec)
{
- struct ubi_scan_leb *seb;
+ struct ubi_ainf_peb *aeb;
dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
- seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
- if (!seb)
+ aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL);
+ if (!aeb)
return -ENOMEM;
- si->corr_peb_count += 1;
- seb->pnum = pnum;
- seb->ec = ec;
- list_add(&seb->u.list, &si->corr);
+ ai->corr_peb_count += 1;
+ aeb->pnum = pnum;
+ aeb->ec = ec;
+ list_add(&aeb->u.list, &ai->corr);
return 0;
}
/**
* validate_vid_hdr - check volume identifier header.
* @vid_hdr: the volume identifier header to check
- * @sv: information about the volume this logical eraseblock belongs to
+ * @av: information about the volume this logical eraseblock belongs to
* @pnum: physical eraseblock number the VID header came from
*
* This function checks that data stored in @vid_hdr is consistent. Returns
@@ -184,15 +189,15 @@ static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec)
* headers of the same volume.
*/
static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr,
- const struct ubi_scan_volume *sv, int pnum)
+ const struct ubi_ainf_volume *av, int pnum)
{
int vol_type = vid_hdr->vol_type;
int vol_id = be32_to_cpu(vid_hdr->vol_id);
int used_ebs = be32_to_cpu(vid_hdr->used_ebs);
int data_pad = be32_to_cpu(vid_hdr->data_pad);
- if (sv->leb_count != 0) {
- int sv_vol_type;
+ if (av->leb_count != 0) {
+ int av_vol_type;
/*
* This is not the first logical eraseblock belonging to this
@@ -200,28 +205,28 @@ static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr,
* to the data in previous logical eraseblock headers.
*/
- if (vol_id != sv->vol_id) {
- dbg_err("inconsistent vol_id");
+ if (vol_id != av->vol_id) {
+ ubi_err("inconsistent vol_id");
goto bad;
}
- if (sv->vol_type == UBI_STATIC_VOLUME)
- sv_vol_type = UBI_VID_STATIC;
+ if (av->vol_type == UBI_STATIC_VOLUME)
+ av_vol_type = UBI_VID_STATIC;
else
- sv_vol_type = UBI_VID_DYNAMIC;
+ av_vol_type = UBI_VID_DYNAMIC;
- if (vol_type != sv_vol_type) {
- dbg_err("inconsistent vol_type");
+ if (vol_type != av_vol_type) {
+ ubi_err("inconsistent vol_type");
goto bad;
}
- if (used_ebs != sv->used_ebs) {
- dbg_err("inconsistent used_ebs");
+ if (used_ebs != av->used_ebs) {
+ ubi_err("inconsistent used_ebs");
goto bad;
}
- if (data_pad != sv->data_pad) {
- dbg_err("inconsistent data_pad");
+ if (data_pad != av->data_pad) {
+ ubi_err("inconsistent data_pad");
goto bad;
}
}
@@ -230,74 +235,74 @@ static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr,
bad:
ubi_err("inconsistent VID header at PEB %d", pnum);
- ubi_dbg_dump_vid_hdr(vid_hdr);
- ubi_dbg_dump_sv(sv);
+ ubi_dump_vid_hdr(vid_hdr);
+ ubi_dump_av(av);
return -EINVAL;
}
/**
- * add_volume - add volume to the scanning information.
- * @si: scanning information
+ * add_volume - add volume to the attaching information.
+ * @ai: attaching information
* @vol_id: ID of the volume to add
* @pnum: physical eraseblock number
* @vid_hdr: volume identifier header
*
* If the volume corresponding to the @vid_hdr logical eraseblock is already
- * present in the scanning information, this function does nothing. Otherwise
- * it adds corresponding volume to the scanning information. Returns a pointer
- * to the scanning volume object in case of success and a negative error code
- * in case of failure.
+ * present in the attaching information, this function does nothing. Otherwise
+ * it adds corresponding volume to the attaching information. Returns a pointer
+ * to the allocated "av" object in case of success and a negative error code in
+ * case of failure.
*/
-static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id,
- int pnum,
+static struct ubi_ainf_volume *add_volume(struct ubi_attach_info *ai,
+ int vol_id, int pnum,
const struct ubi_vid_hdr *vid_hdr)
{
- struct ubi_scan_volume *sv;
- struct rb_node **p = &si->volumes.rb_node, *parent = NULL;
+ struct ubi_ainf_volume *av;
+ struct rb_node **p = &ai->volumes.rb_node, *parent = NULL;
ubi_assert(vol_id == be32_to_cpu(vid_hdr->vol_id));
/* Walk the volume RB-tree to look if this volume is already present */
while (*p) {
parent = *p;
- sv = rb_entry(parent, struct ubi_scan_volume, rb);
+ av = rb_entry(parent, struct ubi_ainf_volume, rb);
- if (vol_id == sv->vol_id)
- return sv;
+ if (vol_id == av->vol_id)
+ return av;
- if (vol_id > sv->vol_id)
+ if (vol_id > av->vol_id)
p = &(*p)->rb_left;
else
p = &(*p)->rb_right;
}
/* The volume is absent - add it */
- sv = kmalloc(sizeof(struct ubi_scan_volume), GFP_KERNEL);
- if (!sv)
+ av = kmalloc(sizeof(struct ubi_ainf_volume), GFP_KERNEL);
+ if (!av)
return ERR_PTR(-ENOMEM);
- sv->highest_lnum = sv->leb_count = 0;
- sv->vol_id = vol_id;
- sv->root = RB_ROOT;
- sv->used_ebs = be32_to_cpu(vid_hdr->used_ebs);
- sv->data_pad = be32_to_cpu(vid_hdr->data_pad);
- sv->compat = vid_hdr->compat;
- sv->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME
+ av->highest_lnum = av->leb_count = 0;
+ av->vol_id = vol_id;
+ av->root = RB_ROOT;
+ av->used_ebs = be32_to_cpu(vid_hdr->used_ebs);
+ av->data_pad = be32_to_cpu(vid_hdr->data_pad);
+ av->compat = vid_hdr->compat;
+ av->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME
: UBI_STATIC_VOLUME;
- if (vol_id > si->highest_vol_id)
- si->highest_vol_id = vol_id;
+ if (vol_id > ai->highest_vol_id)
+ ai->highest_vol_id = vol_id;
- rb_link_node(&sv->rb, parent, p);
- rb_insert_color(&sv->rb, &si->volumes);
- si->vols_found += 1;
+ rb_link_node(&av->rb, parent, p);
+ rb_insert_color(&av->rb, &ai->volumes);
+ ai->vols_found += 1;
dbg_bld("added volume %d", vol_id);
- return sv;
+ return av;
}
/**
* compare_lebs - find out which logical eraseblock is newer.
* @ubi: UBI device description object
- * @seb: first logical eraseblock to compare
+ * @aeb: first logical eraseblock to compare
* @pnum: physical eraseblock number of the second logical eraseblock to
* compare
* @vid_hdr: volume identifier header of the second logical eraseblock
@@ -306,7 +311,7 @@ static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id,
* case of success this function returns a positive value, in case of failure, a
* negative error code is returned. The success return codes use the following
* bits:
- * o bit 0 is cleared: the first PEB (described by @seb) is newer than the
+ * o bit 0 is cleared: the first PEB (described by @aeb) is newer than the
* second PEB (described by @pnum and @vid_hdr);
* o bit 0 is set: the second PEB is newer;
* o bit 1 is cleared: no bit-flips were detected in the newer LEB;
@@ -314,7 +319,7 @@ static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id,
* o bit 2 is cleared: the older LEB is not corrupted;
* o bit 2 is set: the older LEB is corrupted.
*/
-static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
+static int compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
int pnum, const struct ubi_vid_hdr *vid_hdr)
{
void *buf;
@@ -323,7 +328,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
struct ubi_vid_hdr *vh = NULL;
unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum);
- if (sqnum2 == seb->sqnum) {
+ if (sqnum2 == aeb->sqnum) {
/*
* This must be a really ancient UBI image which has been
* created before sequence numbers support has been added. At
@@ -337,7 +342,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
}
/* Obviously the LEB with lower sequence counter is older */
- second_is_newer = !!(sqnum2 > seb->sqnum);
+ second_is_newer = (sqnum2 > aeb->sqnum);
/*
* Now we know which copy is newer. If the copy flag of the PEB with
@@ -356,7 +361,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
return 1;
}
} else {
- if (!seb->copy_flag) {
+ if (!aeb->copy_flag) {
/* It is not a copy, so it is newer */
dbg_bld("first PEB %d is newer, copy_flag is unset",
pnum);
@@ -367,13 +372,13 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
if (!vh)
return -ENOMEM;
- pnum = seb->pnum;
+ pnum = aeb->pnum;
err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
if (err) {
if (err == UBI_IO_BITFLIPS)
bitflips = 1;
else {
- dbg_err("VID of PEB %d header is bad, but it "
+ ubi_err("VID of PEB %d header is bad, but it "
"was OK earlier, err %d", pnum, err);
if (err > 0)
err = -EIO;
@@ -429,9 +434,9 @@ out_free_vidh:
}
/**
- * ubi_scan_add_used - add physical eraseblock to the scanning information.
+ * ubi_add_to_av - add used physical eraseblock to the attaching information.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
* @pnum: the physical eraseblock number
* @ec: erase counter
* @vid_hdr: the volume identifier header
@@ -444,14 +449,13 @@ out_free_vidh:
* to be picked, while the older one has to be dropped. This function returns
* zero in case of success and a negative error code in case of failure.
*/
-int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
- int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
- int bitflips)
+int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
+ int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips)
{
int err, vol_id, lnum;
unsigned long long sqnum;
- struct ubi_scan_volume *sv;
- struct ubi_scan_leb *seb;
+ struct ubi_ainf_volume *av;
+ struct ubi_ainf_peb *aeb;
struct rb_node **p, *parent = NULL;
vol_id = be32_to_cpu(vid_hdr->vol_id);
@@ -461,25 +465,25 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, bitflips %d",
pnum, vol_id, lnum, ec, sqnum, bitflips);
- sv = add_volume(si, vol_id, pnum, vid_hdr);
- if (IS_ERR(sv))
- return PTR_ERR(sv);
+ av = add_volume(ai, vol_id, pnum, vid_hdr);
+ if (IS_ERR(av))
+ return PTR_ERR(av);
- if (si->max_sqnum < sqnum)
- si->max_sqnum = sqnum;
+ if (ai->max_sqnum < sqnum)
+ ai->max_sqnum = sqnum;
/*
* Walk the RB-tree of logical eraseblocks of volume @vol_id to look
* if this is the first instance of this logical eraseblock or not.
*/
- p = &sv->root.rb_node;
+ p = &av->root.rb_node;
while (*p) {
int cmp_res;
parent = *p;
- seb = rb_entry(parent, struct ubi_scan_leb, u.rb);
- if (lnum != seb->lnum) {
- if (lnum < seb->lnum)
+ aeb = rb_entry(parent, struct ubi_ainf_peb, u.rb);
+ if (lnum != aeb->lnum) {
+ if (lnum < aeb->lnum)
p = &(*p)->rb_left;
else
p = &(*p)->rb_right;
@@ -491,8 +495,8 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
* logical eraseblock present.
*/
- dbg_bld("this LEB already exists: PEB %d, sqnum %llu, "
- "EC %d", seb->pnum, seb->sqnum, seb->ec);
+ dbg_bld("this LEB already exists: PEB %d, sqnum %llu, EC %d",
+ aeb->pnum, aeb->sqnum, aeb->ec);
/*
* Make sure that the logical eraseblocks have different
@@ -507,11 +511,11 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
* images, but refuse attaching old images with duplicated
* logical eraseblocks because there was an unclean reboot.
*/
- if (seb->sqnum == sqnum && sqnum != 0) {
+ if (aeb->sqnum == sqnum && sqnum != 0) {
ubi_err("two LEBs with same sequence number %llu",
sqnum);
- ubi_dbg_dump_seb(seb, 0);
- ubi_dbg_dump_vid_hdr(vid_hdr);
+ ubi_dump_aeb(aeb, 0);
+ ubi_dump_vid_hdr(vid_hdr);
return -EINVAL;
}
@@ -519,7 +523,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
* Now we have to drop the older one and preserve the newer
* one.
*/
- cmp_res = compare_lebs(ubi, seb, pnum, vid_hdr);
+ cmp_res = compare_lebs(ubi, aeb, pnum, vid_hdr);
if (cmp_res < 0)
return cmp_res;
@@ -528,23 +532,26 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
* This logical eraseblock is newer than the one
* found earlier.
*/
- err = validate_vid_hdr(vid_hdr, sv, pnum);
+ err = validate_vid_hdr(vid_hdr, av, pnum);
if (err)
return err;
- err = add_to_list(si, seb->pnum, seb->ec, cmp_res & 4,
- &si->erase);
+ err = add_to_list(ai, aeb->pnum, aeb->vol_id,
+ aeb->lnum, aeb->ec, cmp_res & 4,
+ &ai->erase);
if (err)
return err;
- seb->ec = ec;
- seb->pnum = pnum;
- seb->scrub = ((cmp_res & 2) || bitflips);
- seb->copy_flag = vid_hdr->copy_flag;
- seb->sqnum = sqnum;
+ aeb->ec = ec;
+ aeb->pnum = pnum;
+ aeb->vol_id = vol_id;
+ aeb->lnum = lnum;
+ aeb->scrub = ((cmp_res & 2) || bitflips);
+ aeb->copy_flag = vid_hdr->copy_flag;
+ aeb->sqnum = sqnum;
- if (sv->highest_lnum == lnum)
- sv->last_data_size =
+ if (av->highest_lnum == lnum)
+ av->last_data_size =
be32_to_cpu(vid_hdr->data_size);
return 0;
@@ -553,92 +560,64 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
* This logical eraseblock is older than the one found
* previously.
*/
- return add_to_list(si, pnum, ec, cmp_res & 4,
- &si->erase);
+ return add_to_list(ai, pnum, vol_id, lnum, ec,
+ cmp_res & 4, &ai->erase);
}
}
/*
* We've met this logical eraseblock for the first time, add it to the
- * scanning information.
+ * attaching information.
*/
- err = validate_vid_hdr(vid_hdr, sv, pnum);
+ err = validate_vid_hdr(vid_hdr, av, pnum);
if (err)
return err;
- seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
- if (!seb)
+ aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL);
+ if (!aeb)
return -ENOMEM;
- seb->ec = ec;
- seb->pnum = pnum;
- seb->lnum = lnum;
- seb->scrub = bitflips;
- seb->copy_flag = vid_hdr->copy_flag;
- seb->sqnum = sqnum;
-
- if (sv->highest_lnum <= lnum) {
- sv->highest_lnum = lnum;
- sv->last_data_size = be32_to_cpu(vid_hdr->data_size);
+ aeb->ec = ec;
+ aeb->pnum = pnum;
+ aeb->vol_id = vol_id;
+ aeb->lnum = lnum;
+ aeb->scrub = bitflips;
+ aeb->copy_flag = vid_hdr->copy_flag;
+ aeb->sqnum = sqnum;
+
+ if (av->highest_lnum <= lnum) {
+ av->highest_lnum = lnum;
+ av->last_data_size = be32_to_cpu(vid_hdr->data_size);
}
- sv->leb_count += 1;
- rb_link_node(&seb->u.rb, parent, p);
- rb_insert_color(&seb->u.rb, &sv->root);
+ av->leb_count += 1;
+ rb_link_node(&aeb->u.rb, parent, p);
+ rb_insert_color(&aeb->u.rb, &av->root);
return 0;
}
/**
- * ubi_scan_find_sv - find volume in the scanning information.
- * @si: scanning information
+ * ubi_find_av - find volume in the attaching information.
+ * @ai: attaching information
* @vol_id: the requested volume ID
*
* This function returns a pointer to the volume description or %NULL if there
- * are no data about this volume in the scanning information.
- */
-struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si,
- int vol_id)
-{
- struct ubi_scan_volume *sv;
- struct rb_node *p = si->volumes.rb_node;
-
- while (p) {
- sv = rb_entry(p, struct ubi_scan_volume, rb);
-
- if (vol_id == sv->vol_id)
- return sv;
-
- if (vol_id > sv->vol_id)
- p = p->rb_left;
- else
- p = p->rb_right;
- }
-
- return NULL;
-}
-
-/**
- * ubi_scan_find_seb - find LEB in the volume scanning information.
- * @sv: a pointer to the volume scanning information
- * @lnum: the requested logical eraseblock
- *
- * This function returns a pointer to the scanning logical eraseblock or %NULL
- * if there are no data about it in the scanning volume information.
+ * are no data about this volume in the attaching information.
*/
-struct ubi_scan_leb *ubi_scan_find_seb(const struct ubi_scan_volume *sv,
- int lnum)
+struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai,
+ int vol_id)
{
- struct ubi_scan_leb *seb;
- struct rb_node *p = sv->root.rb_node;
+ struct ubi_ainf_volume *av;
+ struct rb_node *p = ai->volumes.rb_node;
while (p) {
- seb = rb_entry(p, struct ubi_scan_leb, u.rb);
+ av = rb_entry(p, struct ubi_ainf_volume, rb);
- if (lnum == seb->lnum)
- return seb;
+ if (vol_id == av->vol_id)
+ return av;
- if (lnum > seb->lnum)
+ if (vol_id > av->vol_id)
p = p->rb_left;
else
p = p->rb_right;
@@ -648,34 +627,34 @@ struct ubi_scan_leb *ubi_scan_find_seb(const struct ubi_scan_volume *sv,
}
/**
- * ubi_scan_rm_volume - delete scanning information about a volume.
- * @si: scanning information
- * @sv: the volume scanning information to delete
+ * ubi_remove_av - delete attaching information about a volume.
+ * @ai: attaching information
+ * @av: the volume attaching information to delete
*/
-void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
+void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av)
{
struct rb_node *rb;
- struct ubi_scan_leb *seb;
+ struct ubi_ainf_peb *aeb;
- dbg_bld("remove scanning information about volume %d", sv->vol_id);
+ dbg_bld("remove attaching information about volume %d", av->vol_id);
- while ((rb = rb_first(&sv->root))) {
- seb = rb_entry(rb, struct ubi_scan_leb, u.rb);
- rb_erase(&seb->u.rb, &sv->root);
- list_add_tail(&seb->u.list, &si->erase);
+ while ((rb = rb_first(&av->root))) {
+ aeb = rb_entry(rb, struct ubi_ainf_peb, u.rb);
+ rb_erase(&aeb->u.rb, &av->root);
+ list_add_tail(&aeb->u.list, &ai->erase);
}
- rb_erase(&sv->rb, &si->volumes);
- kfree(sv);
- si->vols_found -= 1;
+ rb_erase(&av->rb, &ai->volumes);
+ kfree(av);
+ ai->vols_found -= 1;
}
/**
- * ubi_scan_erase_peb - erase a physical eraseblock.
+ * early_erase_peb - erase a physical eraseblock.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
* @pnum: physical eraseblock number to erase;
- * @ec: erase counter value to write (%UBI_SCAN_UNKNOWN_EC if it is unknown)
+ * @ec: erase counter value to write (%UBI_UNKNOWN if it is unknown)
*
* This function erases physical eraseblock 'pnum', and writes the erase
* counter header to it. This function should only be used on UBI device
@@ -683,8 +662,8 @@ void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
* This function returns zero in case of success and a negative error code in
* case of failure.
*/
-int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
- int pnum, int ec)
+static int early_erase_peb(struct ubi_device *ubi,
+ const struct ubi_attach_info *ai, int pnum, int ec)
{
int err;
struct ubi_ec_hdr *ec_hdr;
@@ -716,9 +695,9 @@ out_free:
}
/**
- * ubi_scan_get_free_peb - get a free physical eraseblock.
+ * ubi_early_get_peb - get a free physical eraseblock.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
*
* This function returns a free physical eraseblock. It is supposed to be
* called on the UBI initialization stages when the wear-leveling sub-system is
@@ -726,20 +705,20 @@ out_free:
* the lists, writes the EC header if it is needed, and removes it from the
* list.
*
- * This function returns scanning physical eraseblock information in case of
- * success and an error code in case of failure.
+ * This function returns a pointer to the "aeb" of the found free PEB in case
+ * of success and an error code in case of failure.
*/
-struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
- struct ubi_scan_info *si)
+struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
+ struct ubi_attach_info *ai)
{
int err = 0;
- struct ubi_scan_leb *seb, *tmp_seb;
+ struct ubi_ainf_peb *aeb, *tmp_aeb;
- if (!list_empty(&si->free)) {
- seb = list_entry(si->free.next, struct ubi_scan_leb, u.list);
- list_del(&seb->u.list);
- dbg_bld("return free PEB %d, EC %d", seb->pnum, seb->ec);
- return seb;
+ if (!list_empty(&ai->free)) {
+ aeb = list_entry(ai->free.next, struct ubi_ainf_peb, u.list);
+ list_del(&aeb->u.list);
+ dbg_bld("return free PEB %d, EC %d", aeb->pnum, aeb->ec);
+ return aeb;
}
/*
@@ -748,18 +727,18 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
* so forth. We don't want to take care about bad eraseblocks here -
* they'll be handled later.
*/
- list_for_each_entry_safe(seb, tmp_seb, &si->erase, u.list) {
- if (seb->ec == UBI_SCAN_UNKNOWN_EC)
- seb->ec = si->mean_ec;
+ list_for_each_entry_safe(aeb, tmp_aeb, &ai->erase, u.list) {
+ if (aeb->ec == UBI_UNKNOWN)
+ aeb->ec = ai->mean_ec;
- err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1);
+ err = early_erase_peb(ubi, ai, aeb->pnum, aeb->ec+1);
if (err)
continue;
- seb->ec += 1;
- list_del(&seb->u.list);
- dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec);
- return seb;
+ aeb->ec += 1;
+ list_del(&aeb->u.list);
+ dbg_bld("return PEB %d, EC %d", aeb->pnum, aeb->ec);
+ return aeb;
}
ubi_err("no free eraseblocks");
@@ -814,7 +793,7 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
ubi_err("PEB %d contains corrupted VID header, and the data does not "
"contain all 0xFF, this may be a non-UBI PEB or a severe VID "
"header corruption which requires manual inspection", pnum);
- ubi_dbg_dump_vid_hdr(vid_hdr);
+ ubi_dump_vid_hdr(vid_hdr);
dbg_msg("hexdump of PEB %d offset %d, length %d",
pnum, ubi->leb_start, ubi->leb_size);
ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
@@ -827,16 +806,18 @@ out_unlock:
}
/**
- * process_eb - read, check UBI headers, and add them to scanning information.
+ * scan_peb - scan and process UBI headers of a PEB.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
* @pnum: the physical eraseblock number
*
- * This function returns a zero if the physical eraseblock was successfully
- * handled and a negative error code in case of failure.
+ * This function reads UBI headers of PEB @pnum, checks them, and adds
+ * information about this PEB to the corresponding list or RB-tree in the
+ * "attaching info" structure. Returns zero if the physical eraseblock was
+ * successfully handled and a negative error code in case of failure.
*/
-static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
- int pnum)
+static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
+ int pnum)
{
long long uninitialized_var(ec);
int err, bitflips = 0, vol_id, ec_err = 0;
@@ -848,12 +829,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
if (err < 0)
return err;
else if (err) {
- /*
- * FIXME: this is actually duty of the I/O sub-system to
- * initialize this, but MTD does not provide enough
- * information.
- */
- si->bad_peb_count += 1;
+ ai->bad_peb_count += 1;
return 0;
}
@@ -867,13 +843,13 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
bitflips = 1;
break;
case UBI_IO_FF:
- si->empty_peb_count += 1;
- return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 0,
- &si->erase);
+ ai->empty_peb_count += 1;
+ return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
+ UBI_UNKNOWN, 0, &ai->erase);
case UBI_IO_FF_BITFLIPS:
- si->empty_peb_count += 1;
- return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 1,
- &si->erase);
+ ai->empty_peb_count += 1;
+ return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
+ UBI_UNKNOWN, 1, &ai->erase);
case UBI_IO_BAD_HDR_EBADMSG:
case UBI_IO_BAD_HDR:
/*
@@ -882,7 +858,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
* moved and EC be re-created.
*/
ec_err = err;
- ec = UBI_SCAN_UNKNOWN_EC;
+ ec = UBI_UNKNOWN;
bitflips = 1;
break;
default:
@@ -911,7 +887,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
*/
ubi_err("erase counter overflow, max is %d",
UBI_MAX_ERASECOUNTER);
- ubi_dbg_dump_ec_hdr(ech);
+ ubi_dump_ec_hdr(ech);
return -EINVAL;
}
@@ -933,7 +909,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
ubi->image_seq != image_seq) {
ubi_err("bad image sequence number %d in PEB %d, "
"expected %d", image_seq, pnum, ubi->image_seq);
- ubi_dbg_dump_ec_hdr(ech);
+ ubi_dump_ec_hdr(ech);
return -EINVAL;
}
}
@@ -957,7 +933,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
* PEB, bit it is not marked as bad yet. This may also
* be a result of power cut during erasure.
*/
- si->maybe_bad_peb_count += 1;
+ ai->maybe_bad_peb_count += 1;
case UBI_IO_BAD_HDR:
if (ec_err)
/*
@@ -984,23 +960,27 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
return err;
else if (!err)
/* This corruption is caused by a power cut */
- err = add_to_list(si, pnum, ec, 1, &si->erase);
+ err = add_to_list(ai, pnum, UBI_UNKNOWN,
+ UBI_UNKNOWN, ec, 1, &ai->erase);
else
/* This is an unexpected corruption */
- err = add_corrupted(si, pnum, ec);
+ err = add_corrupted(ai, pnum, ec);
if (err)
return err;
goto adjust_mean_ec;
case UBI_IO_FF_BITFLIPS:
- err = add_to_list(si, pnum, ec, 1, &si->erase);
+ err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
+ ec, 1, &ai->erase);
if (err)
return err;
goto adjust_mean_ec;
case UBI_IO_FF:
if (ec_err)
- err = add_to_list(si, pnum, ec, 1, &si->erase);
+ err = add_to_list(ai, pnum, UBI_UNKNOWN,
+ UBI_UNKNOWN, ec, 1, &ai->erase);
else
- err = add_to_list(si, pnum, ec, 0, &si->free);
+ err = add_to_list(ai, pnum, UBI_UNKNOWN,
+ UBI_UNKNOWN, ec, 0, &ai->free);
if (err)
return err;
goto adjust_mean_ec;
@@ -1019,7 +999,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
case UBI_COMPAT_DELETE:
ubi_msg("\"delete\" compatible internal volume %d:%d"
" found, will remove it", vol_id, lnum);
- err = add_to_list(si, pnum, ec, 1, &si->erase);
+ err = add_to_list(ai, pnum, vol_id, lnum,
+ ec, 1, &ai->erase);
if (err)
return err;
return 0;
@@ -1034,7 +1015,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
case UBI_COMPAT_PRESERVE:
ubi_msg("\"preserve\" compatible internal volume %d:%d"
" found", vol_id, lnum);
- err = add_to_list(si, pnum, ec, 0, &si->alien);
+ err = add_to_list(ai, pnum, vol_id, lnum,
+ ec, 0, &ai->alien);
if (err)
return err;
return 0;
@@ -1049,40 +1031,40 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
if (ec_err)
ubi_warn("valid VID header but corrupted EC header at PEB %d",
pnum);
- err = ubi_scan_add_used(ubi, si, pnum, ec, vidh, bitflips);
+ err = ubi_add_to_av(ubi, ai, pnum, ec, vidh, bitflips);
if (err)
return err;
adjust_mean_ec:
if (!ec_err) {
- si->ec_sum += ec;
- si->ec_count += 1;
- if (ec > si->max_ec)
- si->max_ec = ec;
- if (ec < si->min_ec)
- si->min_ec = ec;
+ ai->ec_sum += ec;
+ ai->ec_count += 1;
+ if (ec > ai->max_ec)
+ ai->max_ec = ec;
+ if (ec < ai->min_ec)
+ ai->min_ec = ec;
}
return 0;
}
/**
- * check_what_we_have - check what PEB were found by scanning.
+ * late_analysis - analyze the overall situation with PEB.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
*
- * This is a helper function which takes a look what PEBs were found by
- * scanning, and decides whether the flash is empty and should be formatted and
- * whether there are too many corrupted PEBs and we should not attach this
- * MTD device. Returns zero if we should proceed with attaching the MTD device,
- * and %-EINVAL if we should not.
+ * This is a helper function which takes a look what PEBs we have after we
+ * gather information about all of them ("ai" is compete). It decides whether
+ * the flash is empty and should be formatted of whether there are too many
+ * corrupted PEBs and we should not attach this MTD device. Returns zero if we
+ * should proceed with attaching the MTD device, and %-EINVAL if we should not.
*/
-static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
+static int late_analysis(struct ubi_device *ubi, struct ubi_attach_info *ai)
{
- struct ubi_scan_leb *seb;
+ struct ubi_ainf_peb *aeb;
int max_corr, peb_count;
- peb_count = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
+ peb_count = ubi->peb_count - ai->bad_peb_count - ai->alien_peb_count;
max_corr = peb_count / 20 ?: 8;
/*
@@ -1090,25 +1072,25 @@ static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
* unclean reboots. However, many of them may indicate some problems
* with the flash HW or driver.
*/
- if (si->corr_peb_count) {
+ if (ai->corr_peb_count) {
ubi_err("%d PEBs are corrupted and preserved",
- si->corr_peb_count);
+ ai->corr_peb_count);
printk(KERN_ERR "Corrupted PEBs are:");
- list_for_each_entry(seb, &si->corr, u.list)
- printk(KERN_CONT " %d", seb->pnum);
+ list_for_each_entry(aeb, &ai->corr, u.list)
+ printk(KERN_CONT " %d", aeb->pnum);
printk(KERN_CONT "\n");
/*
* If too many PEBs are corrupted, we refuse attaching,
* otherwise, only print a warning.
*/
- if (si->corr_peb_count >= max_corr) {
+ if (ai->corr_peb_count >= max_corr) {
ubi_err("too many corrupted PEBs, refusing");
return -EINVAL;
}
}
- if (si->empty_peb_count + si->maybe_bad_peb_count == peb_count) {
+ if (ai->empty_peb_count + ai->maybe_bad_peb_count == peb_count) {
/*
* All PEBs are empty, or almost all - a couple PEBs look like
* they may be bad PEBs which were not marked as bad yet.
@@ -1124,8 +1106,8 @@ static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
* 2. Flash contains non-UBI data and we do not want to format
* it and destroy possibly important information.
*/
- if (si->maybe_bad_peb_count <= 2) {
- si->is_empty = 1;
+ if (ai->maybe_bad_peb_count <= 2) {
+ ai->is_empty = 1;
ubi_msg("empty MTD device detected");
get_random_bytes(&ubi->image_seq,
sizeof(ubi->image_seq));
@@ -1141,40 +1123,41 @@ static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
}
/**
- * ubi_scan - scan an MTD device.
+ * scan_all - scan entire MTD device.
* @ubi: UBI device description object
*
* This function does full scanning of an MTD device and returns complete
- * information about it. In case of failure, an error code is returned.
+ * information about it in form of a "struct ubi_attach_info" object. In case
+ * of failure, an error code is returned.
*/
-struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
+static struct ubi_attach_info *scan_all(struct ubi_device *ubi)
{
int err, pnum;
struct rb_node *rb1, *rb2;
- struct ubi_scan_volume *sv;
- struct ubi_scan_leb *seb;
- struct ubi_scan_info *si;
+ struct ubi_ainf_volume *av;
+ struct ubi_ainf_peb *aeb;
+ struct ubi_attach_info *ai;
- si = kzalloc(sizeof(struct ubi_scan_info), GFP_KERNEL);
- if (!si)
+ ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
+ if (!ai)
return ERR_PTR(-ENOMEM);
- INIT_LIST_HEAD(&si->corr);
- INIT_LIST_HEAD(&si->free);
- INIT_LIST_HEAD(&si->erase);
- INIT_LIST_HEAD(&si->alien);
- si->volumes = RB_ROOT;
+ INIT_LIST_HEAD(&ai->corr);
+ INIT_LIST_HEAD(&ai->free);
+ INIT_LIST_HEAD(&ai->erase);
+ INIT_LIST_HEAD(&ai->alien);
+ ai->volumes = RB_ROOT;
err = -ENOMEM;
- si->scan_leb_slab = kmem_cache_create("ubi_scan_leb_slab",
- sizeof(struct ubi_scan_leb),
- 0, 0, NULL);
- if (!si->scan_leb_slab)
- goto out_si;
+ ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
+ sizeof(struct ubi_ainf_peb),
+ 0, 0, NULL);
+ if (!ai->aeb_slab_cache)
+ goto out_ai;
ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
if (!ech)
- goto out_si;
+ goto out_ai;
vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
if (!vidh)
@@ -1184,7 +1167,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
cond_resched();
dbg_gen("process PEB %d", pnum);
- err = process_eb(ubi, si, pnum);
+ err = scan_peb(ubi, ai, pnum);
if (err < 0)
goto out_vidh;
}
@@ -1192,10 +1175,10 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
dbg_msg("scanning is finished");
/* Calculate mean erase counter */
- if (si->ec_count)
- si->mean_ec = div_u64(si->ec_sum, si->ec_count);
+ if (ai->ec_count)
+ ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count);
- err = check_what_we_have(ubi, si);
+ err = late_analysis(ubi, ai);
if (err)
goto out_vidh;
@@ -1203,55 +1186,102 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
* In case of unknown erase counter we use the mean erase counter
* value.
*/
- ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
- ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb)
- if (seb->ec == UBI_SCAN_UNKNOWN_EC)
- seb->ec = si->mean_ec;
+ ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
+ ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb)
+ if (aeb->ec == UBI_UNKNOWN)
+ aeb->ec = ai->mean_ec;
}
- list_for_each_entry(seb, &si->free, u.list) {
- if (seb->ec == UBI_SCAN_UNKNOWN_EC)
- seb->ec = si->mean_ec;
+ list_for_each_entry(aeb, &ai->free, u.list) {
+ if (aeb->ec == UBI_UNKNOWN)
+ aeb->ec = ai->mean_ec;
}
- list_for_each_entry(seb, &si->corr, u.list)
- if (seb->ec == UBI_SCAN_UNKNOWN_EC)
- seb->ec = si->mean_ec;
+ list_for_each_entry(aeb, &ai->corr, u.list)
+ if (aeb->ec == UBI_UNKNOWN)
+ aeb->ec = ai->mean_ec;
- list_for_each_entry(seb, &si->erase, u.list)
- if (seb->ec == UBI_SCAN_UNKNOWN_EC)
- seb->ec = si->mean_ec;
+ list_for_each_entry(aeb, &ai->erase, u.list)
+ if (aeb->ec == UBI_UNKNOWN)
+ aeb->ec = ai->mean_ec;
- err = paranoid_check_si(ubi, si);
+ err = self_check_ai(ubi, ai);
if (err)
goto out_vidh;
ubi_free_vid_hdr(ubi, vidh);
kfree(ech);
- return si;
+ return ai;
out_vidh:
ubi_free_vid_hdr(ubi, vidh);
out_ech:
kfree(ech);
-out_si:
- ubi_scan_destroy_si(si);
+out_ai:
+ ubi_destroy_ai(ai);
return ERR_PTR(err);
}
/**
- * destroy_sv - free the scanning volume information
- * @sv: scanning volume information
- * @si: scanning information
+ * ubi_attach - attach an MTD device.
+ * @ubi: UBI device descriptor
*
- * This function destroys the volume RB-tree (@sv->root) and the scanning
- * volume information.
+ * This function returns zero in case of success and a negative error code in
+ * case of failure.
*/
-static void destroy_sv(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
+int ubi_attach(struct ubi_device *ubi)
{
- struct ubi_scan_leb *seb;
- struct rb_node *this = sv->root.rb_node;
+ int err;
+ struct ubi_attach_info *ai;
+
+ ai = scan_all(ubi);
+ if (IS_ERR(ai))
+ return PTR_ERR(ai);
+
+ ubi->bad_peb_count = ai->bad_peb_count;
+ ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
+ ubi->corr_peb_count = ai->corr_peb_count;
+ ubi->max_ec = ai->max_ec;
+ ubi->mean_ec = ai->mean_ec;
+ ubi_msg("max. sequence number: %llu", ai->max_sqnum);
+
+ err = ubi_read_volume_table(ubi, ai);
+ if (err)
+ goto out_ai;
+
+ err = ubi_wl_init(ubi, ai);
+ if (err)
+ goto out_vtbl;
+
+ err = ubi_eba_init(ubi, ai);
+ if (err)
+ goto out_wl;
+
+ ubi_destroy_ai(ai);
+ return 0;
+
+out_wl:
+ ubi_wl_close(ubi);
+out_vtbl:
+ ubi_free_internal_volumes(ubi);
+ vfree(ubi->vtbl);
+out_ai:
+ ubi_destroy_ai(ai);
+ return err;
+}
+
+/**
+ * destroy_av - free volume attaching information.
+ * @av: volume attaching information
+ * @ai: attaching information
+ *
+ * This function destroys the volume attaching information.
+ */
+static void destroy_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av)
+{
+ struct ubi_ainf_peb *aeb;
+ struct rb_node *this = av->root.rb_node;
while (this) {
if (this->rb_left)
@@ -1259,224 +1289,222 @@ static void destroy_sv(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
else if (this->rb_right)
this = this->rb_right;
else {
- seb = rb_entry(this, struct ubi_scan_leb, u.rb);
+ aeb = rb_entry(this, struct ubi_ainf_peb, u.rb);
this = rb_parent(this);
if (this) {
- if (this->rb_left == &seb->u.rb)
+ if (this->rb_left == &aeb->u.rb)
this->rb_left = NULL;
else
this->rb_right = NULL;
}
- kmem_cache_free(si->scan_leb_slab, seb);
+ kmem_cache_free(ai->aeb_slab_cache, aeb);
}
}
- kfree(sv);
+ kfree(av);
}
/**
- * ubi_scan_destroy_si - destroy scanning information.
- * @si: scanning information
+ * ubi_destroy_ai - destroy attaching information.
+ * @ai: attaching information
*/
-void ubi_scan_destroy_si(struct ubi_scan_info *si)
+void ubi_destroy_ai(struct ubi_attach_info *ai)
{
- struct ubi_scan_leb *seb, *seb_tmp;
- struct ubi_scan_volume *sv;
+ struct ubi_ainf_peb *aeb, *aeb_tmp;
+ struct ubi_ainf_volume *av;
struct rb_node *rb;
- list_for_each_entry_safe(seb, seb_tmp, &si->alien, u.list) {
- list_del(&seb->u.list);
- kmem_cache_free(si->scan_leb_slab, seb);
+ list_for_each_entry_safe(aeb, aeb_tmp, &ai->alien, u.list) {
+ list_del(&aeb->u.list);
+ kmem_cache_free(ai->aeb_slab_cache, aeb);
}
- list_for_each_entry_safe(seb, seb_tmp, &si->erase, u.list) {
- list_del(&seb->u.list);
- kmem_cache_free(si->scan_leb_slab, seb);
+ list_for_each_entry_safe(aeb, aeb_tmp, &ai->erase, u.list) {
+ list_del(&aeb->u.list);
+ kmem_cache_free(ai->aeb_slab_cache, aeb);
}
- list_for_each_entry_safe(seb, seb_tmp, &si->corr, u.list) {
- list_del(&seb->u.list);
- kmem_cache_free(si->scan_leb_slab, seb);
+ list_for_each_entry_safe(aeb, aeb_tmp, &ai->corr, u.list) {
+ list_del(&aeb->u.list);
+ kmem_cache_free(ai->aeb_slab_cache, aeb);
}
- list_for_each_entry_safe(seb, seb_tmp, &si->free, u.list) {
- list_del(&seb->u.list);
- kmem_cache_free(si->scan_leb_slab, seb);
+ list_for_each_entry_safe(aeb, aeb_tmp, &ai->free, u.list) {
+ list_del(&aeb->u.list);
+ kmem_cache_free(ai->aeb_slab_cache, aeb);
}
/* Destroy the volume RB-tree */
- rb = si->volumes.rb_node;
+ rb = ai->volumes.rb_node;
while (rb) {
if (rb->rb_left)
rb = rb->rb_left;
else if (rb->rb_right)
rb = rb->rb_right;
else {
- sv = rb_entry(rb, struct ubi_scan_volume, rb);
+ av = rb_entry(rb, struct ubi_ainf_volume, rb);
rb = rb_parent(rb);
if (rb) {
- if (rb->rb_left == &sv->rb)
+ if (rb->rb_left == &av->rb)
rb->rb_left = NULL;
else
rb->rb_right = NULL;
}
- destroy_sv(si, sv);
+ destroy_av(ai, av);
}
}
- if (si->scan_leb_slab)
- kmem_cache_destroy(si->scan_leb_slab);
+ if (ai->aeb_slab_cache)
+ kmem_cache_destroy(ai->aeb_slab_cache);
- kfree(si);
+ kfree(ai);
}
-#ifdef CONFIG_MTD_UBI_DEBUG
-
/**
- * paranoid_check_si - check the scanning information.
+ * self_check_ai - check the attaching information.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
*
- * This function returns zero if the scanning information is all right, and a
+ * This function returns zero if the attaching information is all right, and a
* negative error code if not or if an error occurred.
*/
-static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
+static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
{
int pnum, err, vols_found = 0;
struct rb_node *rb1, *rb2;
- struct ubi_scan_volume *sv;
- struct ubi_scan_leb *seb, *last_seb;
+ struct ubi_ainf_volume *av;
+ struct ubi_ainf_peb *aeb, *last_aeb;
uint8_t *buf;
if (!ubi->dbg->chk_gen)
return 0;
/*
- * At first, check that scanning information is OK.
+ * At first, check that attaching information is OK.
*/
- ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
+ ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
int leb_count = 0;
cond_resched();
vols_found += 1;
- if (si->is_empty) {
+ if (ai->is_empty) {
ubi_err("bad is_empty flag");
- goto bad_sv;
+ goto bad_av;
}
- if (sv->vol_id < 0 || sv->highest_lnum < 0 ||
- sv->leb_count < 0 || sv->vol_type < 0 || sv->used_ebs < 0 ||
- sv->data_pad < 0 || sv->last_data_size < 0) {
+ if (av->vol_id < 0 || av->highest_lnum < 0 ||
+ av->leb_count < 0 || av->vol_type < 0 || av->used_ebs < 0 ||
+ av->data_pad < 0 || av->last_data_size < 0) {
ubi_err("negative values");
- goto bad_sv;
+ goto bad_av;
}
- if (sv->vol_id >= UBI_MAX_VOLUMES &&
- sv->vol_id < UBI_INTERNAL_VOL_START) {
+ if (av->vol_id >= UBI_MAX_VOLUMES &&
+ av->vol_id < UBI_INTERNAL_VOL_START) {
ubi_err("bad vol_id");
- goto bad_sv;
+ goto bad_av;
}
- if (sv->vol_id > si->highest_vol_id) {
+ if (av->vol_id > ai->highest_vol_id) {
ubi_err("highest_vol_id is %d, but vol_id %d is there",
- si->highest_vol_id, sv->vol_id);
+ ai->highest_vol_id, av->vol_id);
goto out;
}
- if (sv->vol_type != UBI_DYNAMIC_VOLUME &&
- sv->vol_type != UBI_STATIC_VOLUME) {
+ if (av->vol_type != UBI_DYNAMIC_VOLUME &&
+ av->vol_type != UBI_STATIC_VOLUME) {
ubi_err("bad vol_type");
- goto bad_sv;
+ goto bad_av;
}
- if (sv->data_pad > ubi->leb_size / 2) {
+ if (av->data_pad > ubi->leb_size / 2) {
ubi_err("bad data_pad");
- goto bad_sv;
+ goto bad_av;
}
- last_seb = NULL;
- ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
+ last_aeb = NULL;
+ ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) {
cond_resched();
- last_seb = seb;
+ last_aeb = aeb;
leb_count += 1;
- if (seb->pnum < 0 || seb->ec < 0) {
+ if (aeb->pnum < 0 || aeb->ec < 0) {
ubi_err("negative values");
- goto bad_seb;
+ goto bad_aeb;
}
- if (seb->ec < si->min_ec) {
- ubi_err("bad si->min_ec (%d), %d found",
- si->min_ec, seb->ec);
- goto bad_seb;
+ if (aeb->ec < ai->min_ec) {
+ ubi_err("bad ai->min_ec (%d), %d found",
+ ai->min_ec, aeb->ec);
+ goto bad_aeb;
}
- if (seb->ec > si->max_ec) {
- ubi_err("bad si->max_ec (%d), %d found",
- si->max_ec, seb->ec);
- goto bad_seb;
+ if (aeb->ec > ai->max_ec) {
+ ubi_err("bad ai->max_ec (%d), %d found",
+ ai->max_ec, aeb->ec);
+ goto bad_aeb;
}
- if (seb->pnum >= ubi->peb_count) {
+ if (aeb->pnum >= ubi->peb_count) {
ubi_err("too high PEB number %d, total PEBs %d",
- seb->pnum, ubi->peb_count);
- goto bad_seb;
+ aeb->pnum, ubi->peb_count);
+ goto bad_aeb;
}
- if (sv->vol_type == UBI_STATIC_VOLUME) {
- if (seb->lnum >= sv->used_ebs) {
+ if (av->vol_type == UBI_STATIC_VOLUME) {
+ if (aeb->lnum >= av->used_ebs) {
ubi_err("bad lnum or used_ebs");
- goto bad_seb;
+ goto bad_aeb;
}
} else {
- if (sv->used_ebs != 0) {
+ if (av->used_ebs != 0) {
ubi_err("non-zero used_ebs");
- goto bad_seb;
+ goto bad_aeb;
}
}
- if (seb->lnum > sv->highest_lnum) {
+ if (aeb->lnum > av->highest_lnum) {
ubi_err("incorrect highest_lnum or lnum");
- goto bad_seb;
+ goto bad_aeb;
}
}
- if (sv->leb_count != leb_count) {
+ if (av->leb_count != leb_count) {
ubi_err("bad leb_count, %d objects in the tree",
leb_count);
- goto bad_sv;
+ goto bad_av;
}
- if (!last_seb)
+ if (!last_aeb)
continue;
- seb = last_seb;
+ aeb = last_aeb;
- if (seb->lnum != sv->highest_lnum) {
+ if (aeb->lnum != av->highest_lnum) {
ubi_err("bad highest_lnum");
- goto bad_seb;
+ goto bad_aeb;
}
}
- if (vols_found != si->vols_found) {
- ubi_err("bad si->vols_found %d, should be %d",
- si->vols_found, vols_found);
+ if (vols_found != ai->vols_found) {
+ ubi_err("bad ai->vols_found %d, should be %d",
+ ai->vols_found, vols_found);
goto out;
}
- /* Check that scanning information is correct */
- ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
- last_seb = NULL;
- ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
+ /* Check that attaching information is correct */
+ ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
+ last_aeb = NULL;
+ ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) {
int vol_type;
cond_resched();
- last_seb = seb;
+ last_aeb = aeb;
- err = ubi_io_read_vid_hdr(ubi, seb->pnum, vidh, 1);
+ err = ubi_io_read_vid_hdr(ubi, aeb->pnum, vidh, 1);
if (err && err != UBI_IO_BITFLIPS) {
ubi_err("VID header is not OK (%d)", err);
if (err > 0)
@@ -1486,52 +1514,52 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
vol_type = vidh->vol_type == UBI_VID_DYNAMIC ?
UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME;
- if (sv->vol_type != vol_type) {
+ if (av->vol_type != vol_type) {
ubi_err("bad vol_type");
goto bad_vid_hdr;
}
- if (seb->sqnum != be64_to_cpu(vidh->sqnum)) {
- ubi_err("bad sqnum %llu", seb->sqnum);
+ if (aeb->sqnum != be64_to_cpu(vidh->sqnum)) {
+ ubi_err("bad sqnum %llu", aeb->sqnum);
goto bad_vid_hdr;
}
- if (sv->vol_id != be32_to_cpu(vidh->vol_id)) {
- ubi_err("bad vol_id %d", sv->vol_id);
+ if (av->vol_id != be32_to_cpu(vidh->vol_id)) {
+ ubi_err("bad vol_id %d", av->vol_id);
goto bad_vid_hdr;
}
- if (sv->compat != vidh->compat) {
+ if (av->compat != vidh->compat) {
ubi_err("bad compat %d", vidh->compat);
goto bad_vid_hdr;
}
- if (seb->lnum != be32_to_cpu(vidh->lnum)) {
- ubi_err("bad lnum %d", seb->lnum);
+ if (aeb->lnum != be32_to_cpu(vidh->lnum)) {
+ ubi_err("bad lnum %d", aeb->lnum);
goto bad_vid_hdr;
}
- if (sv->used_ebs != be32_to_cpu(vidh->used_ebs)) {
- ubi_err("bad used_ebs %d", sv->used_ebs);
+ if (av->used_ebs != be32_to_cpu(vidh->used_ebs)) {
+ ubi_err("bad used_ebs %d", av->used_ebs);
goto bad_vid_hdr;
}
- if (sv->data_pad != be32_to_cpu(vidh->data_pad)) {
- ubi_err("bad data_pad %d", sv->data_pad);
+ if (av->data_pad != be32_to_cpu(vidh->data_pad)) {
+ ubi_err("bad data_pad %d", av->data_pad);
goto bad_vid_hdr;
}
}
- if (!last_seb)
+ if (!last_aeb)
continue;
- if (sv->highest_lnum != be32_to_cpu(vidh->lnum)) {
- ubi_err("bad highest_lnum %d", sv->highest_lnum);
+ if (av->highest_lnum != be32_to_cpu(vidh->lnum)) {
+ ubi_err("bad highest_lnum %d", av->highest_lnum);
goto bad_vid_hdr;
}
- if (sv->last_data_size != be32_to_cpu(vidh->data_size)) {
- ubi_err("bad last_data_size %d", sv->last_data_size);
+ if (av->last_data_size != be32_to_cpu(vidh->data_size)) {
+ ubi_err("bad last_data_size %d", av->last_data_size);
goto bad_vid_hdr;
}
}
@@ -1553,21 +1581,21 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
buf[pnum] = 1;
}
- ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb)
- ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb)
- buf[seb->pnum] = 1;
+ ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb)
+ ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb)
+ buf[aeb->pnum] = 1;
- list_for_each_entry(seb, &si->free, u.list)
- buf[seb->pnum] = 1;
+ list_for_each_entry(aeb, &ai->free, u.list)
+ buf[aeb->pnum] = 1;
- list_for_each_entry(seb, &si->corr, u.list)
- buf[seb->pnum] = 1;
+ list_for_each_entry(aeb, &ai->corr, u.list)
+ buf[aeb->pnum] = 1;
- list_for_each_entry(seb, &si->erase, u.list)
- buf[seb->pnum] = 1;
+ list_for_each_entry(aeb, &ai->erase, u.list)
+ buf[aeb->pnum] = 1;
- list_for_each_entry(seb, &si->alien, u.list)
- buf[seb->pnum] = 1;
+ list_for_each_entry(aeb, &ai->alien, u.list)
+ buf[aeb->pnum] = 1;
err = 0;
for (pnum = 0; pnum < ubi->peb_count; pnum++)
@@ -1581,25 +1609,23 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
goto out;
return 0;
-bad_seb:
- ubi_err("bad scanning information about LEB %d", seb->lnum);
- ubi_dbg_dump_seb(seb, 0);
- ubi_dbg_dump_sv(sv);
+bad_aeb:
+ ubi_err("bad attaching information about LEB %d", aeb->lnum);
+ ubi_dump_aeb(aeb, 0);
+ ubi_dump_av(av);
goto out;
-bad_sv:
- ubi_err("bad scanning information about volume %d", sv->vol_id);
- ubi_dbg_dump_sv(sv);
+bad_av:
+ ubi_err("bad attaching information about volume %d", av->vol_id);
+ ubi_dump_av(av);
goto out;
bad_vid_hdr:
- ubi_err("bad scanning information about volume %d", sv->vol_id);
- ubi_dbg_dump_sv(sv);
- ubi_dbg_dump_vid_hdr(vidh);
+ ubi_err("bad attaching information about volume %d", av->vol_id);
+ ubi_dump_av(av);
+ ubi_dump_vid_hdr(vidh);
out:
- ubi_dbg_dump_stack();
+ dump_stack();
return -EINVAL;
}
-
-#endif /* CONFIG_MTD_UBI_DEBUG */
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 0fde9fc7d2e5..2c5ed5ca9c33 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -27,10 +27,6 @@
* module load parameters or the kernel boot parameters. If MTD devices were
* specified, UBI does not attach any MTD device, but it is possible to do
* later using the "UBI control device".
- *
- * At the moment we only attach UBI devices by scanning, which will become a
- * bottleneck when flashes reach certain large size. Then one may improve UBI
- * and add other methods, although it does not seem to be easy to do.
*/
#include <linux/err.h>
@@ -554,10 +550,10 @@ static void uif_close(struct ubi_device *ubi)
}
/**
- * free_internal_volumes - free internal volumes.
+ * ubi_free_internal_volumes - free internal volumes.
* @ubi: UBI device description object
*/
-static void free_internal_volumes(struct ubi_device *ubi)
+void ubi_free_internal_volumes(struct ubi_device *ubi)
{
int i;
@@ -569,59 +565,6 @@ static void free_internal_volumes(struct ubi_device *ubi)
}
/**
- * attach_by_scanning - attach an MTD device using scanning method.
- * @ubi: UBI device descriptor
- *
- * This function returns zero in case of success and a negative error code in
- * case of failure.
- *
- * Note, currently this is the only method to attach UBI devices. Hopefully in
- * the future we'll have more scalable attaching methods and avoid full media
- * scanning. But even in this case scanning will be needed as a fall-back
- * attaching method if there are some on-flash table corruptions.
- */
-static int attach_by_scanning(struct ubi_device *ubi)
-{
- int err;
- struct ubi_scan_info *si;
-
- si = ubi_scan(ubi);
- if (IS_ERR(si))
- return PTR_ERR(si);
-
- ubi->bad_peb_count = si->bad_peb_count;
- ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
- ubi->corr_peb_count = si->corr_peb_count;
- ubi->max_ec = si->max_ec;
- ubi->mean_ec = si->mean_ec;
- ubi_msg("max. sequence number: %llu", si->max_sqnum);
-
- err = ubi_read_volume_table(ubi, si);
- if (err)
- goto out_si;
-
- err = ubi_wl_init_scan(ubi, si);
- if (err)
- goto out_vtbl;
-
- err = ubi_eba_init_scan(ubi, si);
- if (err)
- goto out_wl;
-
- ubi_scan_destroy_si(si);
- return 0;
-
-out_wl:
- ubi_wl_close(ubi);
-out_vtbl:
- free_internal_volumes(ubi);
- vfree(ubi->vtbl);
-out_si:
- ubi_scan_destroy_si(si);
- return err;
-}
-
-/**
* io_init - initialize I/O sub-system for a given UBI device.
* @ubi: UBI device description object
*
@@ -790,11 +733,11 @@ static int io_init(struct ubi_device *ubi)
ubi_msg("data offset: %d", ubi->leb_start);
/*
- * Note, ideally, we have to initialize ubi->bad_peb_count here. But
+ * Note, ideally, we have to initialize @ubi->bad_peb_count here. But
* unfortunately, MTD does not provide this information. We should loop
* over all physical eraseblocks and invoke mtd->block_is_bad() for
- * each physical eraseblock. So, we skip ubi->bad_peb_count
- * uninitialized and initialize it after scanning.
+ * each physical eraseblock. So, we leave @ubi->bad_peb_count
+ * uninitialized so far.
*/
return 0;
@@ -805,7 +748,7 @@ static int io_init(struct ubi_device *ubi)
* @ubi: UBI device description object
* @vol_id: ID of the volume to re-size
*
- * This function re-sizes the volume marked by the @UBI_VTBL_AUTORESIZE_FLG in
+ * This function re-sizes the volume marked by the %UBI_VTBL_AUTORESIZE_FLG in
* the volume table to the largest possible size. See comments in ubi-header.h
* for more description of the flag. Returns zero in case of success and a
* negative error code in case of failure.
@@ -881,7 +824,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
for (i = 0; i < UBI_MAX_DEVICES; i++) {
ubi = ubi_devices[i];
if (ubi && mtd->index == ubi->mtd->index) {
- dbg_err("mtd%d is already attached to ubi%d",
+ ubi_err("mtd%d is already attached to ubi%d",
mtd->index, i);
return -EEXIST;
}
@@ -907,7 +850,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
if (!ubi_devices[ubi_num])
break;
if (ubi_num == UBI_MAX_DEVICES) {
- dbg_err("only %d UBI devices may be created",
+ ubi_err("only %d UBI devices may be created",
UBI_MAX_DEVICES);
return -ENFILE;
}
@@ -917,7 +860,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
/* Make sure ubi_num is not busy */
if (ubi_devices[ubi_num]) {
- dbg_err("ubi%d already exists", ubi_num);
+ ubi_err("ubi%d already exists", ubi_num);
return -EEXIST;
}
}
@@ -937,7 +880,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
spin_lock_init(&ubi->volumes_lock);
ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
- dbg_msg("sizeof(struct ubi_scan_leb) %zu", sizeof(struct ubi_scan_leb));
+ dbg_msg("sizeof(struct ubi_ainf_peb) %zu", sizeof(struct ubi_ainf_peb));
dbg_msg("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));
err = io_init(ubi);
@@ -953,9 +896,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
if (err)
goto out_free;
- err = attach_by_scanning(ubi);
+ err = ubi_attach(ubi);
if (err) {
- dbg_err("failed to attach by scanning, error %d", err);
+ ubi_err("failed to attach mtd%d, error %d", mtd->index, err);
goto out_debugging;
}
@@ -1020,7 +963,7 @@ out_uif:
uif_close(ubi);
out_detach:
ubi_wl_close(ubi);
- free_internal_volumes(ubi);
+ ubi_free_internal_volumes(ubi);
vfree(ubi->vtbl);
out_debugging:
ubi_debugging_exit_dev(ubi);
@@ -1092,7 +1035,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
ubi_debugfs_exit_dev(ubi);
uif_close(ubi);
ubi_wl_close(ubi);
- free_internal_volumes(ubi);
+ ubi_free_internal_volumes(ubi);
vfree(ubi->vtbl);
put_mtd_device(ubi->mtd);
ubi_debugging_exit_dev(ubi);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index ad76592fb2f4..acec85deb6af 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -63,7 +63,7 @@ static int get_exclusive(struct ubi_volume_desc *desc)
users = vol->readers + vol->writers + vol->exclusive;
ubi_assert(users > 0);
if (users > 1) {
- dbg_err("%d users for volume %d", users, vol->vol_id);
+ ubi_err("%d users for volume %d", users, vol->vol_id);
err = -EBUSY;
} else {
vol->readers = vol->writers = 0;
@@ -159,7 +159,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
if (vol->updating) {
/* Update is in progress, seeking is prohibited */
- dbg_err("updating");
+ ubi_err("updating");
return -EBUSY;
}
@@ -178,7 +178,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
}
if (new_offset < 0 || new_offset > vol->used_bytes) {
- dbg_err("bad seek %lld", new_offset);
+ ubi_err("bad seek %lld", new_offset);
return -EINVAL;
}
@@ -216,11 +216,11 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
count, *offp, vol->vol_id);
if (vol->updating) {
- dbg_err("updating");
+ ubi_err("updating");
return -EBUSY;
}
if (vol->upd_marker) {
- dbg_err("damaged volume, update marker is set");
+ ubi_err("damaged volume, update marker is set");
return -EBADF;
}
if (*offp == vol->used_bytes || count == 0)
@@ -300,7 +300,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
lnum = div_u64_rem(*offp, vol->usable_leb_size, &off);
if (off & (ubi->min_io_size - 1)) {
- dbg_err("unaligned position");
+ ubi_err("unaligned position");
return -EINVAL;
}
@@ -309,7 +309,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
/* We can write only in fractions of the minimum I/O unit */
if (count & (ubi->min_io_size - 1)) {
- dbg_err("unaligned write length");
+ ubi_err("unaligned write length");
return -EINVAL;
}
@@ -334,8 +334,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
break;
}
- err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len,
- UBI_UNKNOWN);
+ err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len);
if (err)
break;
@@ -477,9 +476,6 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
req.bytes < 0 || req.lnum >= vol->usable_leb_size)
break;
- if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM &&
- req.dtype != UBI_UNKNOWN)
- break;
err = get_exclusive(desc);
if (err < 0)
@@ -518,7 +514,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
if (err)
break;
- err = ubi_wl_flush(ubi);
+ err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
break;
}
@@ -532,7 +528,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
err = -EFAULT;
break;
}
- err = ubi_leb_map(desc, req.lnum, req.dtype);
+ err = ubi_leb_map(desc, req.lnum);
break;
}
@@ -647,8 +643,8 @@ static int verify_mkvol_req(const struct ubi_device *ubi,
return 0;
bad:
- dbg_err("bad volume creation request");
- ubi_dbg_dump_mkvol_req(req);
+ ubi_err("bad volume creation request");
+ ubi_dump_mkvol_req(req);
return err;
}
@@ -713,12 +709,12 @@ static int rename_volumes(struct ubi_device *ubi,
for (i = 0; i < req->count - 1; i++) {
for (n = i + 1; n < req->count; n++) {
if (req->ents[i].vol_id == req->ents[n].vol_id) {
- dbg_err("duplicated volume id %d",
+ ubi_err("duplicated volume id %d",
req->ents[i].vol_id);
return -EINVAL;
}
if (!strcmp(req->ents[i].name, req->ents[n].name)) {
- dbg_err("duplicated volume name \"%s\"",
+ ubi_err("duplicated volume name \"%s\"",
req->ents[i].name);
return -EINVAL;
}
@@ -741,7 +737,7 @@ static int rename_volumes(struct ubi_device *ubi,
re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE);
if (IS_ERR(re->desc)) {
err = PTR_ERR(re->desc);
- dbg_err("cannot open volume %d, error %d", vol_id, err);
+ ubi_err("cannot open volume %d, error %d", vol_id, err);
kfree(re);
goto out_free;
}
@@ -800,7 +796,7 @@ static int rename_volumes(struct ubi_device *ubi,
continue;
/* The volume exists but busy, or an error occurred */
- dbg_err("cannot open volume \"%s\", error %d",
+ ubi_err("cannot open volume \"%s\", error %d",
re->new_name, err);
goto out_free;
}
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 61af9bb560ab..9f957c2d48e9 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -18,24 +18,49 @@
* Author: Artem Bityutskiy (Битюцкий Артём)
*/
-/*
- * Here we keep all the UBI debugging stuff which should normally be disabled
- * and compiled-out, but it is extremely helpful when hunting bugs or doing big
- * changes.
- */
-
-#ifdef CONFIG_MTD_UBI_DEBUG
-
#include "ubi.h"
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/module.h>
+
+/**
+ * ubi_dump_flash - dump a region of flash.
+ * @ubi: UBI device description object
+ * @pnum: the physical eraseblock number to dump
+ * @offset: the starting offset within the physical eraseblock to dump
+ * @len: the length of the region to dump
+ */
+void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len)
+{
+ int err;
+ size_t read;
+ void *buf;
+ loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
+
+ buf = vmalloc(len);
+ if (!buf)
+ return;
+ err = mtd_read(ubi->mtd, addr, len, &read, buf);
+ if (err && err != -EUCLEAN) {
+ ubi_err("error %d while reading %d bytes from PEB %d:%d, "
+ "read %zd bytes", err, len, pnum, offset, read);
+ goto out;
+ }
+
+ ubi_msg("dumping %d bytes of data from PEB %d, offset %d",
+ len, pnum, offset);
+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
+out:
+ vfree(buf);
+ return;
+}
+
/**
- * ubi_dbg_dump_ec_hdr - dump an erase counter header.
+ * ubi_dump_ec_hdr - dump an erase counter header.
* @ec_hdr: the erase counter header to dump
*/
-void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
+void ubi_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
{
printk(KERN_DEBUG "Erase counter header dump:\n");
printk(KERN_DEBUG "\tmagic %#08x\n",
@@ -57,10 +82,10 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
}
/**
- * ubi_dbg_dump_vid_hdr - dump a volume identifier header.
+ * ubi_dump_vid_hdr - dump a volume identifier header.
* @vid_hdr: the volume identifier header to dump
*/
-void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
+void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
{
printk(KERN_DEBUG "Volume identifier header dump:\n");
printk(KERN_DEBUG "\tmagic %08x\n", be32_to_cpu(vid_hdr->magic));
@@ -82,10 +107,10 @@ void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
}
/**
- * ubi_dbg_dump_vol_info- dump volume information.
+ * ubi_dump_vol_info - dump volume information.
* @vol: UBI volume description object
*/
-void ubi_dbg_dump_vol_info(const struct ubi_volume *vol)
+void ubi_dump_vol_info(const struct ubi_volume *vol)
{
printk(KERN_DEBUG "Volume information dump:\n");
printk(KERN_DEBUG "\tvol_id %d\n", vol->vol_id);
@@ -112,11 +137,11 @@ void ubi_dbg_dump_vol_info(const struct ubi_volume *vol)
}
/**
- * ubi_dbg_dump_vtbl_record - dump a &struct ubi_vtbl_record object.
+ * ubi_dump_vtbl_record - dump a &struct ubi_vtbl_record object.
* @r: the object to dump
* @idx: volume table index
*/
-void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
+void ubi_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
{
int name_len = be16_to_cpu(r->name_len);
@@ -146,44 +171,44 @@ void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
}
/**
- * ubi_dbg_dump_sv - dump a &struct ubi_scan_volume object.
- * @sv: the object to dump
+ * ubi_dump_av - dump a &struct ubi_ainf_volume object.
+ * @av: the object to dump
*/
-void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv)
+void ubi_dump_av(const struct ubi_ainf_volume *av)
{
- printk(KERN_DEBUG "Volume scanning information dump:\n");
- printk(KERN_DEBUG "\tvol_id %d\n", sv->vol_id);
- printk(KERN_DEBUG "\thighest_lnum %d\n", sv->highest_lnum);
- printk(KERN_DEBUG "\tleb_count %d\n", sv->leb_count);
- printk(KERN_DEBUG "\tcompat %d\n", sv->compat);
- printk(KERN_DEBUG "\tvol_type %d\n", sv->vol_type);
- printk(KERN_DEBUG "\tused_ebs %d\n", sv->used_ebs);
- printk(KERN_DEBUG "\tlast_data_size %d\n", sv->last_data_size);
- printk(KERN_DEBUG "\tdata_pad %d\n", sv->data_pad);
+ printk(KERN_DEBUG "Volume attaching information dump:\n");
+ printk(KERN_DEBUG "\tvol_id %d\n", av->vol_id);
+ printk(KERN_DEBUG "\thighest_lnum %d\n", av->highest_lnum);
+ printk(KERN_DEBUG "\tleb_count %d\n", av->leb_count);
+ printk(KERN_DEBUG "\tcompat %d\n", av->compat);
+ printk(KERN_DEBUG "\tvol_type %d\n", av->vol_type);
+ printk(KERN_DEBUG "\tused_ebs %d\n", av->used_ebs);
+ printk(KERN_DEBUG "\tlast_data_size %d\n", av->last_data_size);
+ printk(KERN_DEBUG "\tdata_pad %d\n", av->data_pad);
}
/**
- * ubi_dbg_dump_seb - dump a &struct ubi_scan_leb object.
- * @seb: the object to dump
+ * ubi_dump_aeb - dump a &struct ubi_ainf_peb object.
+ * @aeb: the object to dump
* @type: object type: 0 - not corrupted, 1 - corrupted
*/
-void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type)
+void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type)
{
- printk(KERN_DEBUG "eraseblock scanning information dump:\n");
- printk(KERN_DEBUG "\tec %d\n", seb->ec);
- printk(KERN_DEBUG "\tpnum %d\n", seb->pnum);
+ printk(KERN_DEBUG "eraseblock attaching information dump:\n");
+ printk(KERN_DEBUG "\tec %d\n", aeb->ec);
+ printk(KERN_DEBUG "\tpnum %d\n", aeb->pnum);
if (type == 0) {
- printk(KERN_DEBUG "\tlnum %d\n", seb->lnum);
- printk(KERN_DEBUG "\tscrub %d\n", seb->scrub);
- printk(KERN_DEBUG "\tsqnum %llu\n", seb->sqnum);
+ printk(KERN_DEBUG "\tlnum %d\n", aeb->lnum);
+ printk(KERN_DEBUG "\tscrub %d\n", aeb->scrub);
+ printk(KERN_DEBUG "\tsqnum %llu\n", aeb->sqnum);
}
}
/**
- * ubi_dbg_dump_mkvol_req - dump a &struct ubi_mkvol_req object.
+ * ubi_dump_mkvol_req - dump a &struct ubi_mkvol_req object.
* @req: the object to dump
*/
-void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req)
+void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req)
{
char nm[17];
@@ -200,38 +225,6 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req)
}
/**
- * ubi_dbg_dump_flash - dump a region of flash.
- * @ubi: UBI device description object
- * @pnum: the physical eraseblock number to dump
- * @offset: the starting offset within the physical eraseblock to dump
- * @len: the length of the region to dump
- */
-void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len)
-{
- int err;
- size_t read;
- void *buf;
- loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
-
- buf = vmalloc(len);
- if (!buf)
- return;
- err = mtd_read(ubi->mtd, addr, len, &read, buf);
- if (err && err != -EUCLEAN) {
- ubi_err("error %d while reading %d bytes from PEB %d:%d, "
- "read %zd bytes", err, len, pnum, offset, read);
- goto out;
- }
-
- dbg_msg("dumping %d bytes of data from PEB %d, offset %d",
- len, pnum, offset);
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
-out:
- vfree(buf);
- return;
-}
-
-/**
* ubi_debugging_init_dev - initialize debugging for an UBI device.
* @ubi: UBI device description object
*
@@ -479,5 +472,3 @@ void ubi_debugfs_exit_dev(struct ubi_device *ubi)
{
debugfs_remove_recursive(ubi->dbg->dfs_dir);
}
-
-#endif /* CONFIG_MTD_UBI_DEBUG */
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index ead2cd16ba75..d5d2645b51a7 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -21,21 +21,20 @@
#ifndef __UBI_DEBUG_H__
#define __UBI_DEBUG_H__
-#ifdef CONFIG_MTD_UBI_DEBUG
+void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
+void ubi_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr);
+void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr);
+
#include <linux/random.h>
#define ubi_assert(expr) do { \
if (unlikely(!(expr))) { \
printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
__func__, __LINE__, current->pid); \
- ubi_dbg_dump_stack(); \
+ dump_stack(); \
} \
} while (0)
-#define dbg_err(fmt, ...) ubi_err(fmt, ##__VA_ARGS__)
-
-#define ubi_dbg_dump_stack() dump_stack()
-
#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a) \
print_hex_dump(l, ps, pt, r, g, b, len, a)
@@ -58,17 +57,13 @@
/* Initialization and build messages */
#define dbg_bld(fmt, ...) ubi_dbg_msg("bld", fmt, ##__VA_ARGS__)
-void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr);
-void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr);
-void ubi_dbg_dump_vol_info(const struct ubi_volume *vol);
-void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx);
-void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv);
-void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type);
-void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
-void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
-int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
-int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
- int offset, int len);
+void ubi_dump_vol_info(const struct ubi_volume *vol);
+void ubi_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx);
+void ubi_dump_av(const struct ubi_ainf_volume *av);
+void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type);
+void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req);
+int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
+ int len);
int ubi_debugging_init_dev(struct ubi_device *ubi);
void ubi_debugging_exit_dev(struct ubi_device *ubi);
int ubi_debugfs_init(void);
@@ -167,73 +162,4 @@ static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
return 0;
}
-#else
-
-/* Use "if (0)" to make compiler check arguments even if debugging is off */
-#define ubi_assert(expr) do { \
- if (0) { \
- printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
- __func__, __LINE__, current->pid); \
- } \
-} while (0)
-
-#define dbg_err(fmt, ...) do { \
- if (0) \
- ubi_err(fmt, ##__VA_ARGS__); \
-} while (0)
-
-#define ubi_dbg_msg(fmt, ...) do { \
- if (0) \
- printk(KERN_DEBUG fmt "\n", ##__VA_ARGS__); \
-} while (0)
-
-#define dbg_msg(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_gen(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_eba(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_wl(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_io(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_bld(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
-
-static inline void ubi_dbg_dump_stack(void) { return; }
-static inline void
-ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) { return; }
-static inline void
-ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) { return; }
-static inline void
-ubi_dbg_dump_vol_info(const struct ubi_volume *vol) { return; }
-static inline void
-ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx) { return; }
-static inline void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv) { return; }
-static inline void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb,
- int type) { return; }
-static inline void
-ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req) { return; }
-static inline void ubi_dbg_dump_flash(struct ubi_device *ubi,
- int pnum, int offset, int len) { return; }
-static inline void
-ubi_dbg_print_hex_dump(const char *l, const char *ps, int pt, int r,
- int g, const void *b, size_t len, bool a) { return; }
-static inline int ubi_dbg_check_all_ff(struct ubi_device *ubi,
- int pnum, int offset,
- int len) { return 0; }
-static inline int ubi_dbg_check_write(struct ubi_device *ubi,
- const void *buf, int pnum,
- int offset, int len) { return 0; }
-
-static inline int ubi_debugging_init_dev(struct ubi_device *ubi) { return 0; }
-static inline void ubi_debugging_exit_dev(struct ubi_device *ubi) { return; }
-static inline int ubi_debugfs_init(void) { return 0; }
-static inline void ubi_debugfs_exit(void) { return; }
-static inline int ubi_debugfs_init_dev(struct ubi_device *ubi) { return 0; }
-static inline void ubi_debugfs_exit_dev(struct ubi_device *ubi) { return; }
-
-static inline int
-ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi) { return 0; }
-static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi) { return 0; }
-static inline int
-ubi_dbg_is_write_failure(const struct ubi_device *ubi) { return 0; }
-static inline int
-ubi_dbg_is_erase_failure(const struct ubi_device *ubi) { return 0; }
-
-#endif /* !CONFIG_MTD_UBI_DEBUG */
#endif /* !__UBI_DEBUG_H__ */
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 2455d620d96b..b703ac7729cf 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -341,7 +341,7 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum);
vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED;
- err = ubi_wl_put_peb(ubi, pnum, 0);
+ err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 0);
out_unlock:
leb_write_unlock(ubi, vol_id, lnum);
@@ -507,7 +507,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
return -ENOMEM;
retry:
- new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN);
+ new_pnum = ubi_wl_get_peb(ubi);
if (new_pnum < 0) {
ubi_free_vid_hdr(ubi, vid_hdr);
return new_pnum;
@@ -550,7 +550,7 @@ retry:
ubi_free_vid_hdr(ubi, vid_hdr);
vol->eba_tbl[lnum] = new_pnum;
- ubi_wl_put_peb(ubi, pnum, 1);
+ ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
ubi_msg("data was successfully recovered");
return 0;
@@ -558,7 +558,7 @@ retry:
out_unlock:
mutex_unlock(&ubi->buf_mutex);
out_put:
- ubi_wl_put_peb(ubi, new_pnum, 1);
+ ubi_wl_put_peb(ubi, vol_id, lnum, new_pnum, 1);
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
@@ -568,7 +568,7 @@ write_error:
* get another one.
*/
ubi_warn("failed to write to PEB %d", new_pnum);
- ubi_wl_put_peb(ubi, new_pnum, 1);
+ ubi_wl_put_peb(ubi, vol_id, lnum, new_pnum, 1);
if (++tries > UBI_IO_RETRIES) {
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
@@ -585,7 +585,6 @@ write_error:
* @buf: the data to write
* @offset: offset within the logical eraseblock where to write
* @len: how many bytes to write
- * @dtype: data type
*
* This function writes data to logical eraseblock @lnum of a dynamic volume
* @vol. Returns zero in case of success and a negative error code in case
@@ -593,7 +592,7 @@ write_error:
* written to the flash media, but may be some garbage.
*/
int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
- const void *buf, int offset, int len, int dtype)
+ const void *buf, int offset, int len)
{
int err, pnum, tries = 0, vol_id = vol->vol_id;
struct ubi_vid_hdr *vid_hdr;
@@ -641,7 +640,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
vid_hdr->data_pad = cpu_to_be32(vol->data_pad);
retry:
- pnum = ubi_wl_get_peb(ubi, dtype);
+ pnum = ubi_wl_get_peb(ubi);
if (pnum < 0) {
ubi_free_vid_hdr(ubi, vid_hdr);
leb_write_unlock(ubi, vol_id, lnum);
@@ -687,7 +686,7 @@ write_error:
* eraseblock, so just put it and request a new one. We assume that if
* this physical eraseblock went bad, the erase code will handle that.
*/
- err = ubi_wl_put_peb(ubi, pnum, 1);
+ err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
if (err || ++tries > UBI_IO_RETRIES) {
ubi_ro_mode(ubi);
leb_write_unlock(ubi, vol_id, lnum);
@@ -707,7 +706,6 @@ write_error:
* @lnum: logical eraseblock number
* @buf: data to write
* @len: how many bytes to write
- * @dtype: data type
* @used_ebs: how many logical eraseblocks will this volume contain
*
* This function writes data to logical eraseblock @lnum of static volume
@@ -724,8 +722,7 @@ write_error:
* code in case of failure.
*/
int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
- int lnum, const void *buf, int len, int dtype,
- int used_ebs)
+ int lnum, const void *buf, int len, int used_ebs)
{
int err, pnum, tries = 0, data_size = len, vol_id = vol->vol_id;
struct ubi_vid_hdr *vid_hdr;
@@ -763,7 +760,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
vid_hdr->data_crc = cpu_to_be32(crc);
retry:
- pnum = ubi_wl_get_peb(ubi, dtype);
+ pnum = ubi_wl_get_peb(ubi);
if (pnum < 0) {
ubi_free_vid_hdr(ubi, vid_hdr);
leb_write_unlock(ubi, vol_id, lnum);
@@ -807,7 +804,7 @@ write_error:
return err;
}
- err = ubi_wl_put_peb(ubi, pnum, 1);
+ err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
if (err || ++tries > UBI_IO_RETRIES) {
ubi_ro_mode(ubi);
leb_write_unlock(ubi, vol_id, lnum);
@@ -827,7 +824,6 @@ write_error:
* @lnum: logical eraseblock number
* @buf: data to write
* @len: how many bytes to write
- * @dtype: data type
*
* This function changes the contents of a logical eraseblock atomically. @buf
* has to contain new logical eraseblock data, and @len - the length of the
@@ -839,7 +835,7 @@ write_error:
* LEB change may be done at a time. This is ensured by @ubi->alc_mutex.
*/
int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
- int lnum, const void *buf, int len, int dtype)
+ int lnum, const void *buf, int len)
{
int err, pnum, tries = 0, vol_id = vol->vol_id;
struct ubi_vid_hdr *vid_hdr;
@@ -856,7 +852,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
err = ubi_eba_unmap_leb(ubi, vol, lnum);
if (err)
return err;
- return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype);
+ return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0);
}
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
@@ -881,7 +877,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
vid_hdr->data_crc = cpu_to_be32(crc);
retry:
- pnum = ubi_wl_get_peb(ubi, dtype);
+ pnum = ubi_wl_get_peb(ubi);
if (pnum < 0) {
err = pnum;
goto out_leb_unlock;
@@ -905,7 +901,7 @@ retry:
}
if (vol->eba_tbl[lnum] >= 0) {
- err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0);
+ err = ubi_wl_put_peb(ubi, vol_id, lnum, vol->eba_tbl[lnum], 0);
if (err)
goto out_leb_unlock;
}
@@ -930,7 +926,7 @@ write_error:
goto out_leb_unlock;
}
- err = ubi_wl_put_peb(ubi, pnum, 1);
+ err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
if (err || ++tries > UBI_IO_RETRIES) {
ubi_ro_mode(ubi);
goto out_leb_unlock;
@@ -1171,7 +1167,7 @@ out_unlock_leb:
* print_rsvd_warning - warn about not having enough reserved PEBs.
* @ubi: UBI device description object
*
- * This is a helper function for 'ubi_eba_init_scan()' which is called when UBI
+ * This is a helper function for 'ubi_eba_init()' which is called when UBI
* cannot reserve enough PEBs for bad block handling. This function makes a
* decision whether we have to print a warning or not. The algorithm is as
* follows:
@@ -1186,13 +1182,13 @@ out_unlock_leb:
* reported by real users.
*/
static void print_rsvd_warning(struct ubi_device *ubi,
- struct ubi_scan_info *si)
+ struct ubi_attach_info *ai)
{
/*
* The 1 << 18 (256KiB) number is picked randomly, just a reasonably
* large number to distinguish between newly flashed and used images.
*/
- if (si->max_sqnum > (1 << 18)) {
+ if (ai->max_sqnum > (1 << 18)) {
int min = ubi->beb_rsvd_level / 10;
if (!min)
@@ -1209,19 +1205,19 @@ static void print_rsvd_warning(struct ubi_device *ubi,
}
/**
- * ubi_eba_init_scan - initialize the EBA sub-system using scanning information.
+ * ubi_eba_init - initialize the EBA sub-system using attaching information.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
*
* This function returns zero in case of success and a negative error code in
* case of failure.
*/
-int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
+int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
{
int i, j, err, num_volumes;
- struct ubi_scan_volume *sv;
+ struct ubi_ainf_volume *av;
struct ubi_volume *vol;
- struct ubi_scan_leb *seb;
+ struct ubi_ainf_peb *aeb;
struct rb_node *rb;
dbg_eba("initialize EBA sub-system");
@@ -1230,7 +1226,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
mutex_init(&ubi->alc_mutex);
ubi->ltree = RB_ROOT;
- ubi->global_sqnum = si->max_sqnum + 1;
+ ubi->global_sqnum = ai->max_sqnum + 1;
num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT;
for (i = 0; i < num_volumes; i++) {
@@ -1250,18 +1246,18 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
for (j = 0; j < vol->reserved_pebs; j++)
vol->eba_tbl[j] = UBI_LEB_UNMAPPED;
- sv = ubi_scan_find_sv(si, idx2vol_id(ubi, i));
- if (!sv)
+ av = ubi_find_av(ai, idx2vol_id(ubi, i));
+ if (!av)
continue;
- ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) {
- if (seb->lnum >= vol->reserved_pebs)
+ ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) {
+ if (aeb->lnum >= vol->reserved_pebs)
/*
* This may happen in case of an unclean reboot
* during re-size.
*/
- ubi_scan_move_to_list(sv, seb, &si->erase);
- vol->eba_tbl[seb->lnum] = seb->pnum;
+ ubi_move_aeb_to_list(av, aeb, &ai->erase);
+ vol->eba_tbl[aeb->lnum] = aeb->pnum;
}
}
@@ -1283,7 +1279,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
if (ubi->avail_pebs < ubi->beb_rsvd_level) {
/* No enough free physical eraseblocks */
ubi->beb_rsvd_pebs = ubi->avail_pebs;
- print_rsvd_warning(ubi, si);
+ print_rsvd_warning(ubi, ai);
} else
ubi->beb_rsvd_pebs = ubi->beb_rsvd_level;
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c
index 90b98822d9a4..4e44bee4c564 100644
--- a/drivers/mtd/ubi/gluebi.c
+++ b/drivers/mtd/ubi/gluebi.c
@@ -227,7 +227,7 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len,
if (to_write > total_written)
to_write = total_written;
- err = ubi_write(gluebi->desc, lnum, buf, offs, to_write);
+ err = ubi_leb_write(gluebi->desc, lnum, buf, offs, to_write);
if (err)
break;
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 43f1a0011a55..a8d523794b52 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -91,21 +91,15 @@
#include <linux/slab.h>
#include "ubi.h"
-#ifdef CONFIG_MTD_UBI_DEBUG
-static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum);
-static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum);
-static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
- const struct ubi_ec_hdr *ec_hdr);
-static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum);
-static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
- const struct ubi_vid_hdr *vid_hdr);
-#else
-#define paranoid_check_not_bad(ubi, pnum) 0
-#define paranoid_check_peb_ec_hdr(ubi, pnum) 0
-#define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0
-#define paranoid_check_peb_vid_hdr(ubi, pnum) 0
-#define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0
-#endif
+static int self_check_not_bad(const struct ubi_device *ubi, int pnum);
+static int self_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum);
+static int self_check_ec_hdr(const struct ubi_device *ubi, int pnum,
+ const struct ubi_ec_hdr *ec_hdr);
+static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum);
+static int self_check_vid_hdr(const struct ubi_device *ubi, int pnum,
+ const struct ubi_vid_hdr *vid_hdr);
+static int self_check_write(struct ubi_device *ubi, const void *buf, int pnum,
+ int offset, int len);
/**
* ubi_io_read - read data from a physical eraseblock.
@@ -142,7 +136,7 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
ubi_assert(offset >= 0 && offset + len <= ubi->peb_size);
ubi_assert(len > 0);
- err = paranoid_check_not_bad(ubi, pnum);
+ err = self_check_not_bad(ubi, pnum);
if (err)
return err;
@@ -189,16 +183,16 @@ retry:
}
if (retries++ < UBI_IO_RETRIES) {
- dbg_io("error %d%s while reading %d bytes from PEB "
- "%d:%d, read only %zd bytes, retry",
- err, errstr, len, pnum, offset, read);
+ ubi_warn("error %d%s while reading %d bytes from PEB "
+ "%d:%d, read only %zd bytes, retry",
+ err, errstr, len, pnum, offset, read);
yield();
goto retry;
}
ubi_err("error %d%s while reading %d bytes from PEB %d:%d, "
"read %zd bytes", err, errstr, len, pnum, offset, read);
- ubi_dbg_dump_stack();
+ dump_stack();
/*
* The driver should never return -EBADMSG if it failed to read
@@ -257,14 +251,12 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
return -EROFS;
}
- /* The below has to be compiled out if paranoid checks are disabled */
-
- err = paranoid_check_not_bad(ubi, pnum);
+ err = self_check_not_bad(ubi, pnum);
if (err)
return err;
/* The area we are writing to has to contain all 0xFF bytes */
- err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
+ err = ubi_self_check_all_ff(ubi, pnum, offset, len);
if (err)
return err;
@@ -273,18 +265,18 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
* We write to the data area of the physical eraseblock. Make
* sure it has valid EC and VID headers.
*/
- err = paranoid_check_peb_ec_hdr(ubi, pnum);
+ err = self_check_peb_ec_hdr(ubi, pnum);
if (err)
return err;
- err = paranoid_check_peb_vid_hdr(ubi, pnum);
+ err = self_check_peb_vid_hdr(ubi, pnum);
if (err)
return err;
}
if (ubi_dbg_is_write_failure(ubi)) {
- dbg_err("cannot write %d bytes to PEB %d:%d "
+ ubi_err("cannot write %d bytes to PEB %d:%d "
"(emulated)", len, pnum, offset);
- ubi_dbg_dump_stack();
+ dump_stack();
return -EIO;
}
@@ -293,13 +285,13 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
if (err) {
ubi_err("error %d while writing %d bytes to PEB %d:%d, written "
"%zd bytes", err, len, pnum, offset, written);
- ubi_dbg_dump_stack();
- ubi_dbg_dump_flash(ubi, pnum, offset, len);
+ dump_stack();
+ ubi_dump_flash(ubi, pnum, offset, len);
} else
ubi_assert(written == len);
if (!err) {
- err = ubi_dbg_check_write(ubi, buf, pnum, offset, len);
+ err = self_check_write(ubi, buf, pnum, offset, len);
if (err)
return err;
@@ -310,7 +302,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
offset += len;
len = ubi->peb_size - offset;
if (len)
- err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
+ err = ubi_self_check_all_ff(ubi, pnum, offset, len);
}
return err;
@@ -364,13 +356,13 @@ retry:
err = mtd_erase(ubi->mtd, &ei);
if (err) {
if (retries++ < UBI_IO_RETRIES) {
- dbg_io("error %d while erasing PEB %d, retry",
- err, pnum);
+ ubi_warn("error %d while erasing PEB %d, retry",
+ err, pnum);
yield();
goto retry;
}
ubi_err("cannot erase PEB %d, error %d", pnum, err);
- ubi_dbg_dump_stack();
+ dump_stack();
return err;
}
@@ -383,21 +375,21 @@ retry:
if (ei.state == MTD_ERASE_FAILED) {
if (retries++ < UBI_IO_RETRIES) {
- dbg_io("error while erasing PEB %d, retry", pnum);
+ ubi_warn("error while erasing PEB %d, retry", pnum);
yield();
goto retry;
}
ubi_err("cannot erase PEB %d", pnum);
- ubi_dbg_dump_stack();
+ dump_stack();
return -EIO;
}
- err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size);
+ err = ubi_self_check_all_ff(ubi, pnum, 0, ubi->peb_size);
if (err)
return err;
if (ubi_dbg_is_erase_failure(ubi)) {
- dbg_err("cannot erase PEB %d (emulated)", pnum);
+ ubi_err("cannot erase PEB %d (emulated)", pnum);
return -EIO;
}
@@ -521,8 +513,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
* It is important to first invalidate the EC header, and then the VID
* header. Otherwise a power cut may lead to valid EC header and
* invalid VID header, in which case UBI will treat this PEB as
- * corrupted and will try to preserve it, and print scary warnings (see
- * the header comment in scan.c for more information).
+ * corrupted and will try to preserve it, and print scary warnings.
*/
addr = (loff_t)pnum * ubi->peb_size;
err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data);
@@ -563,7 +554,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
*/
ubi_err("cannot invalidate PEB %d, write returned %d read returned %d",
pnum, err, err1);
- ubi_dbg_dump_flash(ubi, pnum, 0, ubi->peb_size);
+ ubi_dump_flash(ubi, pnum, 0, ubi->peb_size);
return -EIO;
}
@@ -589,7 +580,7 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture)
ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
- err = paranoid_check_not_bad(ubi, pnum);
+ err = self_check_not_bad(ubi, pnum);
if (err != 0)
return err;
@@ -721,8 +712,8 @@ static int validate_ec_hdr(const struct ubi_device *ubi,
bad:
ubi_err("bad EC header");
- ubi_dbg_dump_ec_hdr(ec_hdr);
- ubi_dbg_dump_stack();
+ ubi_dump_ec_hdr(ec_hdr);
+ dump_stack();
return 1;
}
@@ -803,7 +794,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
if (verbose) {
ubi_warn("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
- ubi_dbg_dump_ec_hdr(ec_hdr);
+ ubi_dump_ec_hdr(ec_hdr);
}
dbg_bld("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
@@ -817,7 +808,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
if (verbose) {
ubi_warn("bad EC header CRC at PEB %d, calculated "
"%#08x, read %#08x", pnum, crc, hdr_crc);
- ubi_dbg_dump_ec_hdr(ec_hdr);
+ ubi_dump_ec_hdr(ec_hdr);
}
dbg_bld("bad EC header CRC at PEB %d, calculated "
"%#08x, read %#08x", pnum, crc, hdr_crc);
@@ -874,7 +865,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
ec_hdr->hdr_crc = cpu_to_be32(crc);
- err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr);
+ err = self_check_ec_hdr(ubi, pnum, ec_hdr);
if (err)
return err;
@@ -905,40 +896,40 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
int usable_leb_size = ubi->leb_size - data_pad;
if (copy_flag != 0 && copy_flag != 1) {
- dbg_err("bad copy_flag");
+ ubi_err("bad copy_flag");
goto bad;
}
if (vol_id < 0 || lnum < 0 || data_size < 0 || used_ebs < 0 ||
data_pad < 0) {
- dbg_err("negative values");
+ ubi_err("negative values");
goto bad;
}
if (vol_id >= UBI_MAX_VOLUMES && vol_id < UBI_INTERNAL_VOL_START) {
- dbg_err("bad vol_id");
+ ubi_err("bad vol_id");
goto bad;
}
if (vol_id < UBI_INTERNAL_VOL_START && compat != 0) {
- dbg_err("bad compat");
+ ubi_err("bad compat");
goto bad;
}
if (vol_id >= UBI_INTERNAL_VOL_START && compat != UBI_COMPAT_DELETE &&
compat != UBI_COMPAT_RO && compat != UBI_COMPAT_PRESERVE &&
compat != UBI_COMPAT_REJECT) {
- dbg_err("bad compat");
+ ubi_err("bad compat");
goto bad;
}
if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) {
- dbg_err("bad vol_type");
+ ubi_err("bad vol_type");
goto bad;
}
if (data_pad >= ubi->leb_size / 2) {
- dbg_err("bad data_pad");
+ ubi_err("bad data_pad");
goto bad;
}
@@ -950,45 +941,45 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
* mapped logical eraseblocks.
*/
if (used_ebs == 0) {
- dbg_err("zero used_ebs");
+ ubi_err("zero used_ebs");
goto bad;
}
if (data_size == 0) {
- dbg_err("zero data_size");
+ ubi_err("zero data_size");
goto bad;
}
if (lnum < used_ebs - 1) {
if (data_size != usable_leb_size) {
- dbg_err("bad data_size");
+ ubi_err("bad data_size");
goto bad;
}
} else if (lnum == used_ebs - 1) {
if (data_size == 0) {
- dbg_err("bad data_size at last LEB");
+ ubi_err("bad data_size at last LEB");
goto bad;
}
} else {
- dbg_err("too high lnum");
+ ubi_err("too high lnum");
goto bad;
}
} else {
if (copy_flag == 0) {
if (data_crc != 0) {
- dbg_err("non-zero data CRC");
+ ubi_err("non-zero data CRC");
goto bad;
}
if (data_size != 0) {
- dbg_err("non-zero data_size");
+ ubi_err("non-zero data_size");
goto bad;
}
} else {
if (data_size == 0) {
- dbg_err("zero data_size of copy");
+ ubi_err("zero data_size of copy");
goto bad;
}
}
if (used_ebs != 0) {
- dbg_err("bad used_ebs");
+ ubi_err("bad used_ebs");
goto bad;
}
}
@@ -997,8 +988,8 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
bad:
ubi_err("bad VID header");
- ubi_dbg_dump_vid_hdr(vid_hdr);
- ubi_dbg_dump_stack();
+ ubi_dump_vid_hdr(vid_hdr);
+ dump_stack();
return 1;
}
@@ -1054,7 +1045,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
if (verbose) {
ubi_warn("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
- ubi_dbg_dump_vid_hdr(vid_hdr);
+ ubi_dump_vid_hdr(vid_hdr);
}
dbg_bld("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
@@ -1068,7 +1059,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
if (verbose) {
ubi_warn("bad CRC at PEB %d, calculated %#08x, "
"read %#08x", pnum, crc, hdr_crc);
- ubi_dbg_dump_vid_hdr(vid_hdr);
+ ubi_dump_vid_hdr(vid_hdr);
}
dbg_bld("bad CRC at PEB %d, calculated %#08x, "
"read %#08x", pnum, crc, hdr_crc);
@@ -1112,7 +1103,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
dbg_io("write VID header to PEB %d", pnum);
ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
- err = paranoid_check_peb_ec_hdr(ubi, pnum);
+ err = self_check_peb_ec_hdr(ubi, pnum);
if (err)
return err;
@@ -1121,7 +1112,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC);
vid_hdr->hdr_crc = cpu_to_be32(crc);
- err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr);
+ err = self_check_vid_hdr(ubi, pnum, vid_hdr);
if (err)
return err;
@@ -1131,17 +1122,15 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
return err;
}
-#ifdef CONFIG_MTD_UBI_DEBUG
-
/**
- * paranoid_check_not_bad - ensure that a physical eraseblock is not bad.
+ * self_check_not_bad - ensure that a physical eraseblock is not bad.
* @ubi: UBI device description object
* @pnum: physical eraseblock number to check
*
* This function returns zero if the physical eraseblock is good, %-EINVAL if
* it is bad and a negative error code if an error occurred.
*/
-static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
+static int self_check_not_bad(const struct ubi_device *ubi, int pnum)
{
int err;
@@ -1152,13 +1141,13 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
if (!err)
return err;
- ubi_err("paranoid check failed for PEB %d", pnum);
- ubi_dbg_dump_stack();
+ ubi_err("self-check failed for PEB %d", pnum);
+ dump_stack();
return err > 0 ? -EINVAL : err;
}
/**
- * paranoid_check_ec_hdr - check if an erase counter header is all right.
+ * self_check_ec_hdr - check if an erase counter header is all right.
* @ubi: UBI device description object
* @pnum: physical eraseblock number the erase counter header belongs to
* @ec_hdr: the erase counter header to check
@@ -1166,8 +1155,8 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
* This function returns zero if the erase counter header contains valid
* values, and %-EINVAL if not.
*/
-static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
- const struct ubi_ec_hdr *ec_hdr)
+static int self_check_ec_hdr(const struct ubi_device *ubi, int pnum,
+ const struct ubi_ec_hdr *ec_hdr)
{
int err;
uint32_t magic;
@@ -1184,27 +1173,27 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
err = validate_ec_hdr(ubi, ec_hdr);
if (err) {
- ubi_err("paranoid check failed for PEB %d", pnum);
+ ubi_err("self-check failed for PEB %d", pnum);
goto fail;
}
return 0;
fail:
- ubi_dbg_dump_ec_hdr(ec_hdr);
- ubi_dbg_dump_stack();
+ ubi_dump_ec_hdr(ec_hdr);
+ dump_stack();
return -EINVAL;
}
/**
- * paranoid_check_peb_ec_hdr - check erase counter header.
+ * self_check_peb_ec_hdr - check erase counter header.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
*
* This function returns zero if the erase counter header is all right and and
* a negative error code if not or if an error occurred.
*/
-static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
+static int self_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
{
int err;
uint32_t crc, hdr_crc;
@@ -1225,14 +1214,14 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
hdr_crc = be32_to_cpu(ec_hdr->hdr_crc);
if (hdr_crc != crc) {
ubi_err("bad CRC, calculated %#08x, read %#08x", crc, hdr_crc);
- ubi_err("paranoid check failed for PEB %d", pnum);
- ubi_dbg_dump_ec_hdr(ec_hdr);
- ubi_dbg_dump_stack();
+ ubi_err("self-check failed for PEB %d", pnum);
+ ubi_dump_ec_hdr(ec_hdr);
+ dump_stack();
err = -EINVAL;
goto exit;
}
- err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr);
+ err = self_check_ec_hdr(ubi, pnum, ec_hdr);
exit:
kfree(ec_hdr);
@@ -1240,7 +1229,7 @@ exit:
}
/**
- * paranoid_check_vid_hdr - check that a volume identifier header is all right.
+ * self_check_vid_hdr - check that a volume identifier header is all right.
* @ubi: UBI device description object
* @pnum: physical eraseblock number the volume identifier header belongs to
* @vid_hdr: the volume identifier header to check
@@ -1248,8 +1237,8 @@ exit:
* This function returns zero if the volume identifier header is all right, and
* %-EINVAL if not.
*/
-static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
- const struct ubi_vid_hdr *vid_hdr)
+static int self_check_vid_hdr(const struct ubi_device *ubi, int pnum,
+ const struct ubi_vid_hdr *vid_hdr)
{
int err;
uint32_t magic;
@@ -1266,29 +1255,29 @@ static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
err = validate_vid_hdr(ubi, vid_hdr);
if (err) {
- ubi_err("paranoid check failed for PEB %d", pnum);
+ ubi_err("self-check failed for PEB %d", pnum);
goto fail;
}
return err;
fail:
- ubi_err("paranoid check failed for PEB %d", pnum);
- ubi_dbg_dump_vid_hdr(vid_hdr);
- ubi_dbg_dump_stack();
+ ubi_err("self-check failed for PEB %d", pnum);
+ ubi_dump_vid_hdr(vid_hdr);
+ dump_stack();
return -EINVAL;
}
/**
- * paranoid_check_peb_vid_hdr - check volume identifier header.
+ * self_check_peb_vid_hdr - check volume identifier header.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
*
* This function returns zero if the volume identifier header is all right,
* and a negative error code if not or if an error occurred.
*/
-static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
+static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
{
int err;
uint32_t crc, hdr_crc;
@@ -1313,14 +1302,14 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
if (hdr_crc != crc) {
ubi_err("bad VID header CRC at PEB %d, calculated %#08x, "
"read %#08x", pnum, crc, hdr_crc);
- ubi_err("paranoid check failed for PEB %d", pnum);
- ubi_dbg_dump_vid_hdr(vid_hdr);
- ubi_dbg_dump_stack();
+ ubi_err("self-check failed for PEB %d", pnum);
+ ubi_dump_vid_hdr(vid_hdr);
+ dump_stack();
err = -EINVAL;
goto exit;
}
- err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr);
+ err = self_check_vid_hdr(ubi, pnum, vid_hdr);
exit:
ubi_free_vid_hdr(ubi, vid_hdr);
@@ -1328,7 +1317,7 @@ exit:
}
/**
- * ubi_dbg_check_write - make sure write succeeded.
+ * self_check_write - make sure write succeeded.
* @ubi: UBI device description object
* @buf: buffer with data which were written
* @pnum: physical eraseblock number the data were written to
@@ -1339,8 +1328,8 @@ exit:
* the original data buffer - the data have to match. Returns zero if the data
* match and a negative error code if not or in case of failure.
*/
-int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
- int offset, int len)
+static int self_check_write(struct ubi_device *ubi, const void *buf, int pnum,
+ int offset, int len)
{
int err, i;
size_t read;
@@ -1368,7 +1357,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
if (c == c1)
continue;
- ubi_err("paranoid check failed for PEB %d:%d, len %d",
+ ubi_err("self-check failed for PEB %d:%d, len %d",
pnum, offset, len);
ubi_msg("data differ at position %d", i);
dump_len = max_t(int, 128, len - i);
@@ -1380,7 +1369,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
i, i + dump_len);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
buf1 + i, dump_len, 1);
- ubi_dbg_dump_stack();
+ dump_stack();
err = -EINVAL;
goto out_free;
}
@@ -1394,7 +1383,7 @@ out_free:
}
/**
- * ubi_dbg_check_all_ff - check that a region of flash is empty.
+ * ubi_self_check_all_ff - check that a region of flash is empty.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
* @offset: the starting offset within the physical eraseblock to check
@@ -1404,7 +1393,7 @@ out_free:
* @offset of the physical eraseblock @pnum, and a negative error code if not
* or if an error occurred.
*/
-int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
+int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
{
size_t read;
int err;
@@ -1438,14 +1427,12 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
return 0;
fail:
- ubi_err("paranoid check failed for PEB %d", pnum);
+ ubi_err("self-check failed for PEB %d", pnum);
ubi_msg("hex dump of the %d-%d region", offset, offset + len);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
err = -EINVAL;
error:
- ubi_dbg_dump_stack();
+ dump_stack();
vfree(buf);
return err;
}
-
-#endif /* CONFIG_MTD_UBI_DEBUG */
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index 9fdb35367fe0..3aac1acceeb4 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -221,7 +221,7 @@ out_free:
kfree(desc);
out_put_ubi:
ubi_put_device(ubi);
- dbg_err("cannot open device %d, volume %d, error %d",
+ ubi_err("cannot open device %d, volume %d, error %d",
ubi_num, vol_id, err);
return ERR_PTR(err);
}
@@ -426,11 +426,9 @@ EXPORT_SYMBOL_GPL(ubi_leb_read);
* @buf: data to write
* @offset: offset within the logical eraseblock where to write
* @len: how many bytes to write
- * @dtype: expected data type
*
* This function writes @len bytes of data from @buf to offset @offset of
- * logical eraseblock @lnum. The @dtype argument describes expected lifetime of
- * the data.
+ * logical eraseblock @lnum.
*
* This function takes care of physical eraseblock write failures. If write to
* the physical eraseblock write operation fails, the logical eraseblock is
@@ -447,7 +445,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_read);
* returns immediately with %-EBADF code.
*/
int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int offset, int len, int dtype)
+ int offset, int len)
{
struct ubi_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi;
@@ -466,17 +464,13 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1))
return -EINVAL;
- if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
- dtype != UBI_UNKNOWN)
- return -EINVAL;
-
if (vol->upd_marker)
return -EBADF;
if (len == 0)
return 0;
- return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len, dtype);
+ return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len);
}
EXPORT_SYMBOL_GPL(ubi_leb_write);
@@ -486,7 +480,6 @@ EXPORT_SYMBOL_GPL(ubi_leb_write);
* @lnum: logical eraseblock number to change
* @buf: data to write
* @len: how many bytes to write
- * @dtype: expected data type
*
* This function changes the contents of a logical eraseblock atomically. @buf
* has to contain new logical eraseblock data, and @len - the length of the
@@ -497,7 +490,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_write);
* code in case of failure.
*/
int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int len, int dtype)
+ int len)
{
struct ubi_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi;
@@ -515,17 +508,13 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
len > vol->usable_leb_size || len & (ubi->min_io_size - 1))
return -EINVAL;
- if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
- dtype != UBI_UNKNOWN)
- return -EINVAL;
-
if (vol->upd_marker)
return -EBADF;
if (len == 0)
return 0;
- return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len, dtype);
+ return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len);
}
EXPORT_SYMBOL_GPL(ubi_leb_change);
@@ -562,7 +551,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum)
if (err)
return err;
- return ubi_wl_flush(ubi);
+ return ubi_wl_flush(ubi, vol->vol_id, lnum);
}
EXPORT_SYMBOL_GPL(ubi_leb_erase);
@@ -626,7 +615,6 @@ EXPORT_SYMBOL_GPL(ubi_leb_unmap);
* ubi_leb_map - map logical eraseblock to a physical eraseblock.
* @desc: volume descriptor
* @lnum: logical eraseblock number
- * @dtype: expected data type
*
* This function maps an un-mapped logical eraseblock @lnum to a physical
* eraseblock. This means, that after a successful invocation of this
@@ -639,7 +627,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_unmap);
* eraseblock is already mapped, and other negative error codes in case of
* other failures.
*/
-int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
+int ubi_leb_map(struct ubi_volume_desc *desc, int lnum)
{
struct ubi_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi;
@@ -652,17 +640,13 @@ int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
if (lnum < 0 || lnum >= vol->reserved_pebs)
return -EINVAL;
- if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
- dtype != UBI_UNKNOWN)
- return -EINVAL;
-
if (vol->upd_marker)
return -EBADF;
if (vol->eba_tbl[lnum] >= 0)
return -EBADMSG;
- return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype);
+ return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0);
}
EXPORT_SYMBOL_GPL(ubi_leb_map);
@@ -720,6 +704,33 @@ int ubi_sync(int ubi_num)
}
EXPORT_SYMBOL_GPL(ubi_sync);
+/**
+ * ubi_flush - flush UBI work queue.
+ * @ubi_num: UBI device to flush work queue
+ * @vol_id: volume id to flush for
+ * @lnum: logical eraseblock number to flush for
+ *
+ * This function executes all pending works for a particular volume id / logical
+ * eraseblock number pair. If either value is set to %UBI_ALL, then it acts as
+ * a wildcard for all of the corresponding volume numbers or logical
+ * eraseblock numbers. It returns zero in case of success and a negative error
+ * code in case of failure.
+ */
+int ubi_flush(int ubi_num, int vol_id, int lnum)
+{
+ struct ubi_device *ubi;
+ int err = 0;
+
+ ubi = ubi_get_device(ubi_num);
+ if (!ubi)
+ return -ENODEV;
+
+ err = ubi_wl_flush(ubi, vol_id, lnum);
+ ubi_put_device(ubi);
+ return err;
+}
+EXPORT_SYMBOL_GPL(ubi_flush);
+
BLOCKING_NOTIFIER_HEAD(ubi_notifiers);
/**
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
deleted file mode 100644
index d48aef15ab5d..000000000000
--- a/drivers/mtd/ubi/scan.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Author: Artem Bityutskiy (Битюцкий Артём)
- */
-
-#ifndef __UBI_SCAN_H__
-#define __UBI_SCAN_H__
-
-/* The erase counter value for this physical eraseblock is unknown */
-#define UBI_SCAN_UNKNOWN_EC (-1)
-
-/**
- * struct ubi_scan_leb - scanning information about a physical eraseblock.
- * @ec: erase counter (%UBI_SCAN_UNKNOWN_EC if it is unknown)
- * @pnum: physical eraseblock number
- * @lnum: logical eraseblock number
- * @scrub: if this physical eraseblock needs scrubbing
- * @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB)
- * @sqnum: sequence number
- * @u: unions RB-tree or @list links
- * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects
- * @u.list: link in one of the eraseblock lists
- *
- * One object of this type is allocated for each physical eraseblock during
- * scanning.
- */
-struct ubi_scan_leb {
- int ec;
- int pnum;
- int lnum;
- unsigned int scrub:1;
- unsigned int copy_flag:1;
- unsigned long long sqnum;
- union {
- struct rb_node rb;
- struct list_head list;
- } u;
-};
-
-/**
- * struct ubi_scan_volume - scanning information about a volume.
- * @vol_id: volume ID
- * @highest_lnum: highest logical eraseblock number in this volume
- * @leb_count: number of logical eraseblocks in this volume
- * @vol_type: volume type
- * @used_ebs: number of used logical eraseblocks in this volume (only for
- * static volumes)
- * @last_data_size: amount of data in the last logical eraseblock of this
- * volume (always equivalent to the usable logical eraseblock
- * size in case of dynamic volumes)
- * @data_pad: how many bytes at the end of logical eraseblocks of this volume
- * are not used (due to volume alignment)
- * @compat: compatibility flags of this volume
- * @rb: link in the volume RB-tree
- * @root: root of the RB-tree containing all the eraseblock belonging to this
- * volume (&struct ubi_scan_leb objects)
- *
- * One object of this type is allocated for each volume during scanning.
- */
-struct ubi_scan_volume {
- int vol_id;
- int highest_lnum;
- int leb_count;
- int vol_type;
- int used_ebs;
- int last_data_size;
- int data_pad;
- int compat;
- struct rb_node rb;
- struct rb_root root;
-};
-
-/**
- * struct ubi_scan_info - UBI scanning information.
- * @volumes: root of the volume RB-tree
- * @corr: list of corrupted physical eraseblocks
- * @free: list of free physical eraseblocks
- * @erase: list of physical eraseblocks which have to be erased
- * @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
- * those belonging to "preserve"-compatible internal volumes)
- * @corr_peb_count: count of PEBs in the @corr list
- * @empty_peb_count: count of PEBs which are presumably empty (contain only
- * 0xFF bytes)
- * @alien_peb_count: count of PEBs in the @alien list
- * @bad_peb_count: count of bad physical eraseblocks
- * @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked
- * as bad yet, but which look like bad
- * @vols_found: number of volumes found during scanning
- * @highest_vol_id: highest volume ID
- * @is_empty: flag indicating whether the MTD device is empty or not
- * @min_ec: lowest erase counter value
- * @max_ec: highest erase counter value
- * @max_sqnum: highest sequence number value
- * @mean_ec: mean erase counter value
- * @ec_sum: a temporary variable used when calculating @mean_ec
- * @ec_count: a temporary variable used when calculating @mean_ec
- * @scan_leb_slab: slab cache for &struct ubi_scan_leb objects
- *
- * This data structure contains the result of scanning and may be used by other
- * UBI sub-systems to build final UBI data structures, further error-recovery
- * and so on.
- */
-struct ubi_scan_info {
- struct rb_root volumes;
- struct list_head corr;
- struct list_head free;
- struct list_head erase;
- struct list_head alien;
- int corr_peb_count;
- int empty_peb_count;
- int alien_peb_count;
- int bad_peb_count;
- int maybe_bad_peb_count;
- int vols_found;
- int highest_vol_id;
- int is_empty;
- int min_ec;
- int max_ec;
- unsigned long long max_sqnum;
- int mean_ec;
- uint64_t ec_sum;
- int ec_count;
- struct kmem_cache *scan_leb_slab;
-};
-
-struct ubi_device;
-struct ubi_vid_hdr;
-
-/*
- * ubi_scan_move_to_list - move a PEB from the volume tree to a list.
- *
- * @sv: volume scanning information
- * @seb: scanning eraseblock information
- * @list: the list to move to
- */
-static inline void ubi_scan_move_to_list(struct ubi_scan_volume *sv,
- struct ubi_scan_leb *seb,
- struct list_head *list)
-{
- rb_erase(&seb->u.rb, &sv->root);
- list_add_tail(&seb->u.list, list);
-}
-
-int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
- int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
- int bitflips);
-struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si,
- int vol_id);
-struct ubi_scan_leb *ubi_scan_find_seb(const struct ubi_scan_volume *sv,
- int lnum);
-void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv);
-struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
- struct ubi_scan_info *si);
-int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
- int pnum, int ec);
-struct ubi_scan_info *ubi_scan(struct ubi_device *ubi);
-void ubi_scan_destroy_si(struct ubi_scan_info *si);
-
-#endif /* !__UBI_SCAN_H__ */
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
index 6fb8ec2174a5..468ffbc0eabd 100644
--- a/drivers/mtd/ubi/ubi-media.h
+++ b/drivers/mtd/ubi/ubi-media.h
@@ -149,10 +149,10 @@ enum {
* The @image_seq field is used to validate a UBI image that has been prepared
* for a UBI device. The @image_seq value can be any value, but it must be the
* same on all eraseblocks. UBI will ensure that all new erase counter headers
- * also contain this value, and will check the value when scanning at start-up.
+ * also contain this value, and will check the value when attaching the flash.
* One way to make use of @image_seq is to increase its value by one every time
* an image is flashed over an existing image, then, if the flashing does not
- * complete, UBI will detect the error when scanning.
+ * complete, UBI will detect the error when attaching the media.
*/
struct ubi_ec_hdr {
__be32 magic;
@@ -298,8 +298,8 @@ struct ubi_vid_hdr {
#define UBI_INT_VOL_COUNT 1
/*
- * Starting ID of internal volumes. There is reserved room for 4096 internal
- * volumes.
+ * Starting ID of internal volumes: 0x7fffefff.
+ * There is reserved room for 4096 internal volumes.
*/
#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index b162790790a9..a1a81c9ea8ce 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -43,7 +43,6 @@
#include <asm/pgtable.h>
#include "ubi-media.h"
-#include "scan.h"
/* Maximum number of supported UBI devices */
#define UBI_MAX_DEVICES 32
@@ -66,7 +65,10 @@
/* Background thread name pattern */
#define UBI_BGT_NAME_PATTERN "ubi_bgt%dd"
-/* This marker in the EBA table means that the LEB is um-mapped */
+/*
+ * This marker in the EBA table means that the LEB is um-mapped.
+ * NOTE! It has to have the same value as %UBI_ALL.
+ */
#define UBI_LEB_UNMAPPED -1
/*
@@ -82,6 +84,9 @@
*/
#define UBI_PROT_QUEUE_LEN 10
+/* The volume ID/LEB number/erase counter is unknown */
+#define UBI_UNKNOWN -1
+
/*
* Error codes returned by the I/O sub-system.
*
@@ -222,8 +227,6 @@ struct ubi_volume_desc;
* @upd_ebs: how many eraseblocks are expected to be updated
* @ch_lnum: LEB number which is being changing by the atomic LEB change
* operation
- * @ch_dtype: data persistency type which is being changing by the atomic LEB
- * change operation
* @upd_bytes: how many bytes are expected to be received for volume update or
* atomic LEB change
* @upd_received: how many bytes were already received for volume update or
@@ -270,7 +273,6 @@ struct ubi_volume {
int upd_ebs;
int ch_lnum;
- int ch_dtype;
long long upd_bytes;
long long upd_received;
void *upd_buf;
@@ -477,6 +479,124 @@ struct ubi_device {
struct ubi_debug_info *dbg;
};
+/**
+ * struct ubi_ainf_peb - attach information about a physical eraseblock.
+ * @ec: erase counter (%UBI_UNKNOWN if it is unknown)
+ * @pnum: physical eraseblock number
+ * @vol_id: ID of the volume this LEB belongs to
+ * @lnum: logical eraseblock number
+ * @scrub: if this physical eraseblock needs scrubbing
+ * @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB)
+ * @sqnum: sequence number
+ * @u: unions RB-tree or @list links
+ * @u.rb: link in the per-volume RB-tree of &struct ubi_ainf_peb objects
+ * @u.list: link in one of the eraseblock lists
+ *
+ * One object of this type is allocated for each physical eraseblock when
+ * attaching an MTD device. Note, if this PEB does not belong to any LEB /
+ * volume, the @vol_id and @lnum fields are initialized to %UBI_UNKNOWN.
+ */
+struct ubi_ainf_peb {
+ int ec;
+ int pnum;
+ int vol_id;
+ int lnum;
+ unsigned int scrub:1;
+ unsigned int copy_flag:1;
+ unsigned long long sqnum;
+ union {
+ struct rb_node rb;
+ struct list_head list;
+ } u;
+};
+
+/**
+ * struct ubi_ainf_volume - attaching information about a volume.
+ * @vol_id: volume ID
+ * @highest_lnum: highest logical eraseblock number in this volume
+ * @leb_count: number of logical eraseblocks in this volume
+ * @vol_type: volume type
+ * @used_ebs: number of used logical eraseblocks in this volume (only for
+ * static volumes)
+ * @last_data_size: amount of data in the last logical eraseblock of this
+ * volume (always equivalent to the usable logical eraseblock
+ * size in case of dynamic volumes)
+ * @data_pad: how many bytes at the end of logical eraseblocks of this volume
+ * are not used (due to volume alignment)
+ * @compat: compatibility flags of this volume
+ * @rb: link in the volume RB-tree
+ * @root: root of the RB-tree containing all the eraseblock belonging to this
+ * volume (&struct ubi_ainf_peb objects)
+ *
+ * One object of this type is allocated for each volume when attaching an MTD
+ * device.
+ */
+struct ubi_ainf_volume {
+ int vol_id;
+ int highest_lnum;
+ int leb_count;
+ int vol_type;
+ int used_ebs;
+ int last_data_size;
+ int data_pad;
+ int compat;
+ struct rb_node rb;
+ struct rb_root root;
+};
+
+/**
+ * struct ubi_attach_info - MTD device attaching information.
+ * @volumes: root of the volume RB-tree
+ * @corr: list of corrupted physical eraseblocks
+ * @free: list of free physical eraseblocks
+ * @erase: list of physical eraseblocks which have to be erased
+ * @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
+ * those belonging to "preserve"-compatible internal volumes)
+ * @corr_peb_count: count of PEBs in the @corr list
+ * @empty_peb_count: count of PEBs which are presumably empty (contain only
+ * 0xFF bytes)
+ * @alien_peb_count: count of PEBs in the @alien list
+ * @bad_peb_count: count of bad physical eraseblocks
+ * @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked
+ * as bad yet, but which look like bad
+ * @vols_found: number of volumes found
+ * @highest_vol_id: highest volume ID
+ * @is_empty: flag indicating whether the MTD device is empty or not
+ * @min_ec: lowest erase counter value
+ * @max_ec: highest erase counter value
+ * @max_sqnum: highest sequence number value
+ * @mean_ec: mean erase counter value
+ * @ec_sum: a temporary variable used when calculating @mean_ec
+ * @ec_count: a temporary variable used when calculating @mean_ec
+ * @aeb_slab_cache: slab cache for &struct ubi_ainf_peb objects
+ *
+ * This data structure contains the result of attaching an MTD device and may
+ * be used by other UBI sub-systems to build final UBI data structures, further
+ * error-recovery and so on.
+ */
+struct ubi_attach_info {
+ struct rb_root volumes;
+ struct list_head corr;
+ struct list_head free;
+ struct list_head erase;
+ struct list_head alien;
+ int corr_peb_count;
+ int empty_peb_count;
+ int alien_peb_count;
+ int bad_peb_count;
+ int maybe_bad_peb_count;
+ int vols_found;
+ int highest_vol_id;
+ int is_empty;
+ int min_ec;
+ int max_ec;
+ unsigned long long max_sqnum;
+ int mean_ec;
+ uint64_t ec_sum;
+ int ec_count;
+ struct kmem_cache *aeb_slab_cache;
+};
+
#include "debug.h"
extern struct kmem_cache *ubi_wl_entry_slab;
@@ -487,12 +607,23 @@ extern struct class *ubi_class;
extern struct mutex ubi_devices_mutex;
extern struct blocking_notifier_head ubi_notifiers;
+/* scan.c */
+int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
+ int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips);
+struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai,
+ int vol_id);
+void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av);
+struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
+ struct ubi_attach_info *ai);
+int ubi_attach(struct ubi_device *ubi);
+void ubi_destroy_ai(struct ubi_attach_info *ai);
+
/* vtbl.c */
int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
struct ubi_vtbl_record *vtbl_rec);
int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
struct list_head *rename_list);
-int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si);
+int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai);
/* vmt.c */
int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req);
@@ -525,22 +656,22 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
void *buf, int offset, int len, int check);
int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
- const void *buf, int offset, int len, int dtype);
+ const void *buf, int offset, int len);
int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
- int lnum, const void *buf, int len, int dtype,
- int used_ebs);
+ int lnum, const void *buf, int len, int used_ebs);
int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
- int lnum, const void *buf, int len, int dtype);
+ int lnum, const void *buf, int len);
int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
struct ubi_vid_hdr *vid_hdr);
-int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
+int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai);
/* wl.c */
-int ubi_wl_get_peb(struct ubi_device *ubi, int dtype);
-int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture);
-int ubi_wl_flush(struct ubi_device *ubi);
+int ubi_wl_get_peb(struct ubi_device *ubi);
+int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum,
+ int pnum, int torture);
+int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum);
int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum);
-int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
+int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai);
void ubi_wl_close(struct ubi_device *ubi);
int ubi_thread(void *u);
@@ -573,6 +704,7 @@ int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol,
int ubi_notify_all(struct ubi_device *ubi, int ntype,
struct notifier_block *nb);
int ubi_enumerate_volumes(struct notifier_block *nb);
+void ubi_free_internal_volumes(struct ubi_device *ubi);
/* kapi.c */
void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di);
@@ -593,6 +725,21 @@ void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol,
rb = rb_next(rb), \
pos = (rb ? container_of(rb, typeof(*pos), member) : NULL))
+/*
+ * ubi_move_aeb_to_list - move a PEB from the volume tree to a list.
+ *
+ * @av: volume attaching information
+ * @aeb: attaching eraseblock information
+ * @list: the list to move to
+ */
+static inline void ubi_move_aeb_to_list(struct ubi_ainf_volume *av,
+ struct ubi_ainf_peb *aeb,
+ struct list_head *list)
+{
+ rb_erase(&aeb->u.rb, &av->root);
+ list_add_tail(&aeb->u.list, list);
+}
+
/**
* ubi_zalloc_vid_hdr - allocate a volume identifier header object.
* @ubi: UBI device description object
@@ -667,7 +814,7 @@ static inline void ubi_ro_mode(struct ubi_device *ubi)
if (!ubi->ro_mode) {
ubi->ro_mode = 1;
ubi_warn("switch to read-only mode");
- ubi_dbg_dump_stack();
+ dump_stack();
}
}
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
index 425bf5a3edd4..9f2ebd8750e7 100644
--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -147,7 +147,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
}
if (bytes == 0) {
- err = ubi_wl_flush(ubi);
+ err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
if (err)
return err;
@@ -186,14 +186,12 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
dbg_gen("start changing LEB %d:%d, %u bytes",
vol->vol_id, req->lnum, req->bytes);
if (req->bytes == 0)
- return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0,
- req->dtype);
+ return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0);
vol->upd_bytes = req->bytes;
vol->upd_received = 0;
vol->changing_leb = 1;
vol->ch_lnum = req->lnum;
- vol->ch_dtype = req->dtype;
vol->upd_buf = vmalloc(req->bytes);
if (!vol->upd_buf)
@@ -246,8 +244,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
return 0;
}
- err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len,
- UBI_UNKNOWN);
+ err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len);
} else {
/*
* When writing static volume, and this is the last logical
@@ -259,8 +256,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
* contain zeros, not random trash.
*/
memset(buf + len, 0, vol->usable_leb_size - len);
- err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len,
- UBI_UNKNOWN, used_ebs);
+ err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, used_ebs);
}
return err;
@@ -365,7 +361,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
ubi_assert(vol->upd_received <= vol->upd_bytes);
if (vol->upd_received == vol->upd_bytes) {
- err = ubi_wl_flush(ubi);
+ err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
if (err)
return err;
/* The update is finished, clear the update marker */
@@ -421,7 +417,7 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
len - vol->upd_bytes);
len = ubi_calc_data_len(ubi, vol->upd_buf, len);
err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,
- vol->upd_buf, len, UBI_UNKNOWN);
+ vol->upd_buf, len);
if (err)
return err;
}
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 863835f4aefe..0669cff8ac3c 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -29,11 +29,7 @@
#include <linux/export.h>
#include "ubi.h"
-#ifdef CONFIG_MTD_UBI_DEBUG
-static int paranoid_check_volumes(struct ubi_device *ubi);
-#else
-#define paranoid_check_volumes(ubi) 0
-#endif
+static int self_check_volumes(struct ubi_device *ubi);
static ssize_t vol_attribute_show(struct device *dev,
struct device_attribute *attr, char *buf);
@@ -227,7 +223,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
}
if (vol_id == UBI_VOL_NUM_AUTO) {
- dbg_err("out of volume IDs");
+ ubi_err("out of volume IDs");
err = -ENFILE;
goto out_unlock;
}
@@ -241,7 +237,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
/* Ensure that this volume does not exist */
err = -EEXIST;
if (ubi->volumes[vol_id]) {
- dbg_err("volume %d already exists", vol_id);
+ ubi_err("volume %d already exists", vol_id);
goto out_unlock;
}
@@ -250,7 +246,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
if (ubi->volumes[i] &&
ubi->volumes[i]->name_len == req->name_len &&
!strcmp(ubi->volumes[i]->name, req->name)) {
- dbg_err("volume \"%s\" exists (ID %d)", req->name, i);
+ ubi_err("volume \"%s\" exists (ID %d)", req->name, i);
goto out_unlock;
}
@@ -261,9 +257,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
/* Reserve physical eraseblocks */
if (vol->reserved_pebs > ubi->avail_pebs) {
- dbg_err("not enough PEBs, only %d available", ubi->avail_pebs);
+ ubi_err("not enough PEBs, only %d available", ubi->avail_pebs);
if (ubi->corr_peb_count)
- dbg_err("%d PEBs are corrupted and not used",
+ ubi_err("%d PEBs are corrupted and not used",
ubi->corr_peb_count);
err = -ENOSPC;
goto out_unlock;
@@ -284,7 +280,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
* Finish all pending erases because there may be some LEBs belonging
* to the same volume ID.
*/
- err = ubi_wl_flush(ubi);
+ err = ubi_wl_flush(ubi, vol_id, UBI_ALL);
if (err)
goto out_acc;
@@ -360,8 +356,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
spin_unlock(&ubi->volumes_lock);
ubi_volume_notify(ubi, vol, UBI_VOLUME_ADDED);
- if (paranoid_check_volumes(ubi))
- dbg_err("check failed while creating volume %d", vol_id);
+ self_check_volumes(ubi);
return err;
out_sysfs:
@@ -461,8 +456,8 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
spin_unlock(&ubi->volumes_lock);
ubi_volume_notify(ubi, vol, UBI_VOLUME_REMOVED);
- if (!no_vtbl && paranoid_check_volumes(ubi))
- dbg_err("check failed while removing volume %d", vol_id);
+ if (!no_vtbl)
+ self_check_volumes(ubi);
return err;
@@ -500,7 +495,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
if (vol->vol_type == UBI_STATIC_VOLUME &&
reserved_pebs < vol->used_ebs) {
- dbg_err("too small size %d, %d LEBs contain data",
+ ubi_err("too small size %d, %d LEBs contain data",
reserved_pebs, vol->used_ebs);
return -EINVAL;
}
@@ -529,10 +524,10 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
if (pebs > 0) {
spin_lock(&ubi->volumes_lock);
if (pebs > ubi->avail_pebs) {
- dbg_err("not enough PEBs: requested %d, available %d",
+ ubi_err("not enough PEBs: requested %d, available %d",
pebs, ubi->avail_pebs);
if (ubi->corr_peb_count)
- dbg_err("%d PEBs are corrupted and not used",
+ ubi_err("%d PEBs are corrupted and not used",
ubi->corr_peb_count);
spin_unlock(&ubi->volumes_lock);
err = -ENOSPC;
@@ -588,8 +583,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
}
ubi_volume_notify(ubi, vol, UBI_VOLUME_RESIZED);
- if (paranoid_check_volumes(ubi))
- dbg_err("check failed while re-sizing volume %d", vol_id);
+ self_check_volumes(ubi);
return err;
out_acc:
@@ -638,8 +632,8 @@ int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list)
}
}
- if (!err && paranoid_check_volumes(ubi))
- ;
+ if (!err)
+ self_check_volumes(ubi);
return err;
}
@@ -686,8 +680,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
return err;
}
- if (paranoid_check_volumes(ubi))
- dbg_err("check failed while adding volume %d", vol_id);
+ self_check_volumes(ubi);
return err;
out_cdev:
@@ -712,16 +705,14 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol)
volume_sysfs_close(vol);
}
-#ifdef CONFIG_MTD_UBI_DEBUG
-
/**
- * paranoid_check_volume - check volume information.
+ * self_check_volume - check volume information.
* @ubi: UBI device description object
* @vol_id: volume ID
*
* Returns zero if volume is all right and a a negative error code if not.
*/
-static int paranoid_check_volume(struct ubi_device *ubi, int vol_id)
+static int self_check_volume(struct ubi_device *ubi, int vol_id)
{
int idx = vol_id2idx(ubi, vol_id);
int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker;
@@ -771,7 +762,7 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id)
}
if (vol->upd_marker && vol->corrupted) {
- dbg_err("update marker and corrupted simultaneously");
+ ubi_err("update marker and corrupted simultaneously");
goto fail;
}
@@ -853,22 +844,22 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id)
return 0;
fail:
- ubi_err("paranoid check failed for volume %d", vol_id);
+ ubi_err("self-check failed for volume %d", vol_id);
if (vol)
- ubi_dbg_dump_vol_info(vol);
- ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);
+ ubi_dump_vol_info(vol);
+ ubi_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);
dump_stack();
spin_unlock(&ubi->volumes_lock);
return -EINVAL;
}
/**
- * paranoid_check_volumes - check information about all volumes.
+ * self_check_volumes - check information about all volumes.
* @ubi: UBI device description object
*
* Returns zero if volumes are all right and a a negative error code if not.
*/
-static int paranoid_check_volumes(struct ubi_device *ubi)
+static int self_check_volumes(struct ubi_device *ubi)
{
int i, err = 0;
@@ -876,11 +867,10 @@ static int paranoid_check_volumes(struct ubi_device *ubi)
return 0;
for (i = 0; i < ubi->vtbl_slots; i++) {
- err = paranoid_check_volume(ubi, i);
+ err = self_check_volume(ubi, i);
if (err)
break;
}
return err;
}
-#endif
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 17cec0c01544..437bc193e170 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -37,16 +37,15 @@
* LEB 1. This scheme guarantees recoverability from unclean reboots.
*
* In this UBI implementation the on-flash volume table does not contain any
- * information about how many data static volumes contain. This information may
- * be found from the scanning data.
+ * information about how much data static volumes contain.
*
* But it would still be beneficial to store this information in the volume
* table. For example, suppose we have a static volume X, and all its physical
* eraseblocks became bad for some reasons. Suppose we are attaching the
- * corresponding MTD device, the scanning has found no logical eraseblocks
+ * corresponding MTD device, for some reason we find no logical eraseblocks
* corresponding to the volume X. According to the volume table volume X does
* exist. So we don't know whether it is just empty or all its physical
- * eraseblocks went bad. So we cannot alarm the user about this corruption.
+ * eraseblocks went bad. So we cannot alarm the user properly.
*
* The volume table also stores so-called "update marker", which is used for
* volume updates. Before updating the volume, the update marker is set, and
@@ -62,11 +61,7 @@
#include <asm/div64.h>
#include "ubi.h"
-#ifdef CONFIG_MTD_UBI_DEBUG
-static void paranoid_vtbl_check(const struct ubi_device *ubi);
-#else
-#define paranoid_vtbl_check(ubi)
-#endif
+static void self_vtbl_check(const struct ubi_device *ubi);
/* Empty volume table record */
static struct ubi_vtbl_record empty_vtbl_record;
@@ -106,12 +101,12 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
return err;
err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
- ubi->vtbl_size, UBI_LONGTERM);
+ ubi->vtbl_size);
if (err)
return err;
}
- paranoid_vtbl_check(ubi);
+ self_vtbl_check(ubi);
return 0;
}
@@ -158,7 +153,7 @@ int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
return err;
err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
- ubi->vtbl_size, UBI_LONGTERM);
+ ubi->vtbl_size);
if (err)
return err;
}
@@ -197,7 +192,7 @@ static int vtbl_check(const struct ubi_device *ubi,
if (be32_to_cpu(vtbl[i].crc) != crc) {
ubi_err("bad CRC at record %u: %#08x, not %#08x",
i, crc, be32_to_cpu(vtbl[i].crc));
- ubi_dbg_dump_vtbl_record(&vtbl[i], i);
+ ubi_dump_vtbl_record(&vtbl[i], i);
return 1;
}
@@ -229,7 +224,7 @@ static int vtbl_check(const struct ubi_device *ubi,
n = ubi->leb_size % alignment;
if (data_pad != n) {
- dbg_err("bad data_pad, has to be %d", n);
+ ubi_err("bad data_pad, has to be %d", n);
err = 6;
goto bad;
}
@@ -245,7 +240,7 @@ static int vtbl_check(const struct ubi_device *ubi,
}
if (reserved_pebs > ubi->good_peb_count) {
- dbg_err("too large reserved_pebs %d, good PEBs %d",
+ ubi_err("too large reserved_pebs %d, good PEBs %d",
reserved_pebs, ubi->good_peb_count);
err = 9;
goto bad;
@@ -277,8 +272,8 @@ static int vtbl_check(const struct ubi_device *ubi,
!strncmp(vtbl[i].name, vtbl[n].name, len1)) {
ubi_err("volumes %d and %d have the same name"
" \"%s\"", i, n, vtbl[i].name);
- ubi_dbg_dump_vtbl_record(&vtbl[i], i);
- ubi_dbg_dump_vtbl_record(&vtbl[n], n);
+ ubi_dump_vtbl_record(&vtbl[i], i);
+ ubi_dump_vtbl_record(&vtbl[n], n);
return -EINVAL;
}
}
@@ -288,26 +283,26 @@ static int vtbl_check(const struct ubi_device *ubi,
bad:
ubi_err("volume table check failed: record %d, error %d", i, err);
- ubi_dbg_dump_vtbl_record(&vtbl[i], i);
+ ubi_dump_vtbl_record(&vtbl[i], i);
return -EINVAL;
}
/**
* create_vtbl - create a copy of volume table.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
* @copy: number of the volume table copy
* @vtbl: contents of the volume table
*
* This function returns zero in case of success and a negative error code in
* case of failure.
*/
-static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
+static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai,
int copy, void *vtbl)
{
int err, tries = 0;
struct ubi_vid_hdr *vid_hdr;
- struct ubi_scan_leb *new_seb;
+ struct ubi_ainf_peb *new_aeb;
ubi_msg("create volume table (copy #%d)", copy + 1);
@@ -316,9 +311,9 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
return -ENOMEM;
retry:
- new_seb = ubi_scan_get_free_peb(ubi, si);
- if (IS_ERR(new_seb)) {
- err = PTR_ERR(new_seb);
+ new_aeb = ubi_early_get_peb(ubi, ai);
+ if (IS_ERR(new_aeb)) {
+ err = PTR_ERR(new_aeb);
goto out_free;
}
@@ -328,25 +323,24 @@ retry:
vid_hdr->data_size = vid_hdr->used_ebs =
vid_hdr->data_pad = cpu_to_be32(0);
vid_hdr->lnum = cpu_to_be32(copy);
- vid_hdr->sqnum = cpu_to_be64(++si->max_sqnum);
+ vid_hdr->sqnum = cpu_to_be64(++ai->max_sqnum);
/* The EC header is already there, write the VID header */
- err = ubi_io_write_vid_hdr(ubi, new_seb->pnum, vid_hdr);
+ err = ubi_io_write_vid_hdr(ubi, new_aeb->pnum, vid_hdr);
if (err)
goto write_error;
/* Write the layout volume contents */
- err = ubi_io_write_data(ubi, vtbl, new_seb->pnum, 0, ubi->vtbl_size);
+ err = ubi_io_write_data(ubi, vtbl, new_aeb->pnum, 0, ubi->vtbl_size);
if (err)
goto write_error;
/*
- * And add it to the scanning information. Don't delete the old version
- * of this LEB as it will be deleted and freed in 'ubi_scan_add_used()'.
+ * And add it to the attaching information. Don't delete the old version
+ * of this LEB as it will be deleted and freed in 'ubi_add_to_av()'.
*/
- err = ubi_scan_add_used(ubi, si, new_seb->pnum, new_seb->ec,
- vid_hdr, 0);
- kfree(new_seb);
+ err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0);
+ kfree(new_aeb);
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
@@ -356,10 +350,10 @@ write_error:
* Probably this physical eraseblock went bad, try to pick
* another one.
*/
- list_add(&new_seb->u.list, &si->erase);
+ list_add(&new_aeb->u.list, &ai->erase);
goto retry;
}
- kfree(new_seb);
+ kfree(new_aeb);
out_free:
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
@@ -369,20 +363,20 @@ out_free:
/**
* process_lvol - process the layout volume.
* @ubi: UBI device description object
- * @si: scanning information
- * @sv: layout volume scanning information
+ * @ai: attaching information
+ * @av: layout volume attaching information
*
* This function is responsible for reading the layout volume, ensuring it is
* not corrupted, and recovering from corruptions if needed. Returns volume
* table in case of success and a negative error code in case of failure.
*/
static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
- struct ubi_scan_info *si,
- struct ubi_scan_volume *sv)
+ struct ubi_attach_info *ai,
+ struct ubi_ainf_volume *av)
{
int err;
struct rb_node *rb;
- struct ubi_scan_leb *seb;
+ struct ubi_ainf_peb *aeb;
struct ubi_vtbl_record *leb[UBI_LAYOUT_VOLUME_EBS] = { NULL, NULL };
int leb_corrupted[UBI_LAYOUT_VOLUME_EBS] = {1, 1};
@@ -414,14 +408,14 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
dbg_gen("check layout volume");
/* Read both LEB 0 and LEB 1 into memory */
- ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) {
- leb[seb->lnum] = vzalloc(ubi->vtbl_size);
- if (!leb[seb->lnum]) {
+ ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) {
+ leb[aeb->lnum] = vzalloc(ubi->vtbl_size);
+ if (!leb[aeb->lnum]) {
err = -ENOMEM;
goto out_free;
}
- err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
+ err = ubi_io_read_data(ubi, leb[aeb->lnum], aeb->pnum, 0,
ubi->vtbl_size);
if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err))
/*
@@ -429,12 +423,12 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
* uncorrectable ECC error, but we have our own CRC and
* the data will be checked later. If the data is OK,
* the PEB will be scrubbed (because we set
- * seb->scrub). If the data is not OK, the contents of
+ * aeb->scrub). If the data is not OK, the contents of
* the PEB will be recovered from the second copy, and
- * seb->scrub will be cleared in
- * 'ubi_scan_add_used()'.
+ * aeb->scrub will be cleared in
+ * 'ubi_add_to_av()'.
*/
- seb->scrub = 1;
+ aeb->scrub = 1;
else if (err)
goto out_free;
}
@@ -453,7 +447,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
ubi->vtbl_size);
if (leb_corrupted[1]) {
ubi_warn("volume table copy #2 is corrupted");
- err = create_vtbl(ubi, si, 1, leb[0]);
+ err = create_vtbl(ubi, ai, 1, leb[0]);
if (err)
goto out_free;
ubi_msg("volume table was restored");
@@ -476,7 +470,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
}
ubi_warn("volume table copy #1 is corrupted");
- err = create_vtbl(ubi, si, 0, leb[1]);
+ err = create_vtbl(ubi, ai, 0, leb[1]);
if (err)
goto out_free;
ubi_msg("volume table was restored");
@@ -494,13 +488,13 @@ out_free:
/**
* create_empty_lvol - create empty layout volume.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
*
* This function returns volume table contents in case of success and a
* negative error code in case of failure.
*/
static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,
- struct ubi_scan_info *si)
+ struct ubi_attach_info *ai)
{
int i;
struct ubi_vtbl_record *vtbl;
@@ -515,7 +509,7 @@ static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,
for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
int err;
- err = create_vtbl(ubi, si, i, vtbl);
+ err = create_vtbl(ubi, ai, i, vtbl);
if (err) {
vfree(vtbl);
return ERR_PTR(err);
@@ -528,18 +522,19 @@ static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,
/**
* init_volumes - initialize volume information for existing volumes.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: scanning information
* @vtbl: volume table
*
* This function allocates volume description objects for existing volumes.
* Returns zero in case of success and a negative error code in case of
* failure.
*/
-static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
+static int init_volumes(struct ubi_device *ubi,
+ const struct ubi_attach_info *ai,
const struct ubi_vtbl_record *vtbl)
{
int i, reserved_pebs = 0;
- struct ubi_scan_volume *sv;
+ struct ubi_ainf_volume *av;
struct ubi_volume *vol;
for (i = 0; i < ubi->vtbl_slots; i++) {
@@ -595,8 +590,8 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
}
/* Static volumes only */
- sv = ubi_scan_find_sv(si, i);
- if (!sv) {
+ av = ubi_find_av(ai, i);
+ if (!av) {
/*
* No eraseblocks belonging to this volume found. We
* don't actually know whether this static volume is
@@ -608,22 +603,22 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
continue;
}
- if (sv->leb_count != sv->used_ebs) {
+ if (av->leb_count != av->used_ebs) {
/*
* We found a static volume which misses several
* eraseblocks. Treat it as corrupted.
*/
ubi_warn("static volume %d misses %d LEBs - corrupted",
- sv->vol_id, sv->used_ebs - sv->leb_count);
+ av->vol_id, av->used_ebs - av->leb_count);
vol->corrupted = 1;
continue;
}
- vol->used_ebs = sv->used_ebs;
+ vol->used_ebs = av->used_ebs;
vol->used_bytes =
(long long)(vol->used_ebs - 1) * vol->usable_leb_size;
- vol->used_bytes += sv->last_data_size;
- vol->last_eb_bytes = sv->last_data_size;
+ vol->used_bytes += av->last_data_size;
+ vol->last_eb_bytes = av->last_data_size;
}
/* And add the layout volume */
@@ -664,105 +659,104 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
}
/**
- * check_sv - check volume scanning information.
+ * check_av - check volume attaching information.
* @vol: UBI volume description object
- * @sv: volume scanning information
+ * @av: volume attaching information
*
- * This function returns zero if the volume scanning information is consistent
+ * This function returns zero if the volume attaching information is consistent
* to the data read from the volume tabla, and %-EINVAL if not.
*/
-static int check_sv(const struct ubi_volume *vol,
- const struct ubi_scan_volume *sv)
+static int check_av(const struct ubi_volume *vol,
+ const struct ubi_ainf_volume *av)
{
int err;
- if (sv->highest_lnum >= vol->reserved_pebs) {
+ if (av->highest_lnum >= vol->reserved_pebs) {
err = 1;
goto bad;
}
- if (sv->leb_count > vol->reserved_pebs) {
+ if (av->leb_count > vol->reserved_pebs) {
err = 2;
goto bad;
}
- if (sv->vol_type != vol->vol_type) {
+ if (av->vol_type != vol->vol_type) {
err = 3;
goto bad;
}
- if (sv->used_ebs > vol->reserved_pebs) {
+ if (av->used_ebs > vol->reserved_pebs) {
err = 4;
goto bad;
}
- if (sv->data_pad != vol->data_pad) {
+ if (av->data_pad != vol->data_pad) {
err = 5;
goto bad;
}
return 0;
bad:
- ubi_err("bad scanning information, error %d", err);
- ubi_dbg_dump_sv(sv);
- ubi_dbg_dump_vol_info(vol);
+ ubi_err("bad attaching information, error %d", err);
+ ubi_dump_av(av);
+ ubi_dump_vol_info(vol);
return -EINVAL;
}
/**
- * check_scanning_info - check that scanning information.
+ * check_attaching_info - check that attaching information.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
*
* Even though we protect on-flash data by CRC checksums, we still don't trust
- * the media. This function ensures that scanning information is consistent to
- * the information read from the volume table. Returns zero if the scanning
+ * the media. This function ensures that attaching information is consistent to
+ * the information read from the volume table. Returns zero if the attaching
* information is OK and %-EINVAL if it is not.
*/
-static int check_scanning_info(const struct ubi_device *ubi,
- struct ubi_scan_info *si)
+static int check_attaching_info(const struct ubi_device *ubi,
+ struct ubi_attach_info *ai)
{
int err, i;
- struct ubi_scan_volume *sv;
+ struct ubi_ainf_volume *av;
struct ubi_volume *vol;
- if (si->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) {
- ubi_err("scanning found %d volumes, maximum is %d + %d",
- si->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots);
+ if (ai->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) {
+ ubi_err("found %d volumes while attaching, maximum is %d + %d",
+ ai->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots);
return -EINVAL;
}
- if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&
- si->highest_vol_id < UBI_INTERNAL_VOL_START) {
- ubi_err("too large volume ID %d found by scanning",
- si->highest_vol_id);
+ if (ai->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&
+ ai->highest_vol_id < UBI_INTERNAL_VOL_START) {
+ ubi_err("too large volume ID %d found", ai->highest_vol_id);
return -EINVAL;
}
for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
cond_resched();
- sv = ubi_scan_find_sv(si, i);
+ av = ubi_find_av(ai, i);
vol = ubi->volumes[i];
if (!vol) {
- if (sv)
- ubi_scan_rm_volume(si, sv);
+ if (av)
+ ubi_remove_av(ai, av);
continue;
}
if (vol->reserved_pebs == 0) {
ubi_assert(i < ubi->vtbl_slots);
- if (!sv)
+ if (!av)
continue;
/*
- * During scanning we found a volume which does not
+ * During attaching we found a volume which does not
* exist according to the information in the volume
* table. This must have happened due to an unclean
* reboot while the volume was being removed. Discard
* these eraseblocks.
*/
- ubi_msg("finish volume %d removal", sv->vol_id);
- ubi_scan_rm_volume(si, sv);
- } else if (sv) {
- err = check_sv(vol, sv);
+ ubi_msg("finish volume %d removal", av->vol_id);
+ ubi_remove_av(ai, av);
+ } else if (av) {
+ err = check_av(vol, av);
if (err)
return err;
}
@@ -774,16 +768,16 @@ static int check_scanning_info(const struct ubi_device *ubi,
/**
* ubi_read_volume_table - read the volume table.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
*
* This function reads volume table, checks it, recover from errors if needed,
* or creates it if needed. Returns zero in case of success and a negative
* error code in case of failure.
*/
-int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
+int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai)
{
int i, err;
- struct ubi_scan_volume *sv;
+ struct ubi_ainf_volume *av;
empty_vtbl_record.crc = cpu_to_be32(0xf116c36b);
@@ -798,8 +792,8 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
ubi->vtbl_size = ubi->vtbl_slots * UBI_VTBL_RECORD_SIZE;
ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size);
- sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID);
- if (!sv) {
+ av = ubi_find_av(ai, UBI_LAYOUT_VOLUME_ID);
+ if (!av) {
/*
* No logical eraseblocks belonging to the layout volume were
* found. This could mean that the flash is just empty. In
@@ -808,8 +802,8 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
* But if flash is not empty this must be a corruption or the
* MTD device just contains garbage.
*/
- if (si->is_empty) {
- ubi->vtbl = create_empty_lvol(ubi, si);
+ if (ai->is_empty) {
+ ubi->vtbl = create_empty_lvol(ubi, ai);
if (IS_ERR(ubi->vtbl))
return PTR_ERR(ubi->vtbl);
} else {
@@ -817,14 +811,14 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
return -EINVAL;
}
} else {
- if (sv->leb_count > UBI_LAYOUT_VOLUME_EBS) {
+ if (av->leb_count > UBI_LAYOUT_VOLUME_EBS) {
/* This must not happen with proper UBI images */
- dbg_err("too many LEBs (%d) in layout volume",
- sv->leb_count);
+ ubi_err("too many LEBs (%d) in layout volume",
+ av->leb_count);
return -EINVAL;
}
- ubi->vtbl = process_lvol(ubi, si, sv);
+ ubi->vtbl = process_lvol(ubi, ai, av);
if (IS_ERR(ubi->vtbl))
return PTR_ERR(ubi->vtbl);
}
@@ -835,15 +829,15 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
* The layout volume is OK, initialize the corresponding in-RAM data
* structures.
*/
- err = init_volumes(ubi, si, ubi->vtbl);
+ err = init_volumes(ubi, ai, ubi->vtbl);
if (err)
goto out_free;
/*
- * Make sure that the scanning information is consistent to the
+ * Make sure that the attaching information is consistent to the
* information stored in the volume table.
*/
- err = check_scanning_info(ubi, si);
+ err = check_attaching_info(ubi, ai);
if (err)
goto out_free;
@@ -858,21 +852,17 @@ out_free:
return err;
}
-#ifdef CONFIG_MTD_UBI_DEBUG
-
/**
- * paranoid_vtbl_check - check volume table.
+ * self_vtbl_check - check volume table.
* @ubi: UBI device description object
*/
-static void paranoid_vtbl_check(const struct ubi_device *ubi)
+static void self_vtbl_check(const struct ubi_device *ubi)
{
if (!ubi->dbg->chk_gen)
return;
if (vtbl_check(ubi, ubi->vtbl)) {
- ubi_err("paranoid check failed");
+ ubi_err("self-check failed");
BUG();
}
}
-
-#endif /* CONFIG_MTD_UBI_DEBUG */
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 7c1a9bf8ac86..9df100a4ec38 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -41,12 +41,6 @@
* physical eraseblocks with low erase counter to free physical eraseblocks
* with high erase counter.
*
- * The 'ubi_wl_get_peb()' function accepts data type hints which help to pick
- * an "optimal" physical eraseblock. For example, when it is known that the
- * physical eraseblock will be "put" soon because it contains short-term data,
- * the WL sub-system may pick a free physical eraseblock with low erase
- * counter, and so forth.
- *
* If the WL sub-system fails to erase a physical eraseblock, it marks it as
* bad.
*
@@ -70,8 +64,7 @@
* to the user; instead, we first want to let users fill them up with data;
*
* o there is a chance that the user will put the physical eraseblock very
- * soon, so it makes sense not to move it for some time, but wait; this is
- * especially important in case of "short term" physical eraseblocks.
+ * soon, so it makes sense not to move it for some time, but wait.
*
* Physical eraseblocks stay protected only for limited time. But the "time" is
* measured in erase cycles in this case. This is implemented with help of the
@@ -147,6 +140,8 @@
* @list: a link in the list of pending works
* @func: worker function
* @e: physical eraseblock to erase
+ * @vol_id: the volume ID on which this erasure is being performed
+ * @lnum: the logical eraseblock number
* @torture: if the physical eraseblock has to be tortured
*
* The @func pointer points to the worker function. If the @cancel argument is
@@ -159,21 +154,16 @@ struct ubi_work {
int (*func)(struct ubi_device *ubi, struct ubi_work *wrk, int cancel);
/* The below fields are only relevant to erasure works */
struct ubi_wl_entry *e;
+ int vol_id;
+ int lnum;
int torture;
};
-#ifdef CONFIG_MTD_UBI_DEBUG
-static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec);
-static int paranoid_check_in_wl_tree(const struct ubi_device *ubi,
- struct ubi_wl_entry *e,
- struct rb_root *root);
-static int paranoid_check_in_pq(const struct ubi_device *ubi,
- struct ubi_wl_entry *e);
-#else
-#define paranoid_check_ec(ubi, pnum, ec) 0
-#define paranoid_check_in_wl_tree(ubi, e, root)
-#define paranoid_check_in_pq(ubi, e) 0
-#endif
+static int self_check_ec(struct ubi_device *ubi, int pnum, int ec);
+static int self_check_in_wl_tree(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e, struct rb_root *root);
+static int self_check_in_pq(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e);
/**
* wl_tree_add - add a wear-leveling entry to a WL RB-tree.
@@ -383,19 +373,15 @@ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int diff)
/**
* ubi_wl_get_peb - get a physical eraseblock.
* @ubi: UBI device description object
- * @dtype: type of data which will be stored in this physical eraseblock
*
* This function returns a physical eraseblock in case of success and a
* negative error code in case of failure. Might sleep.
*/
-int ubi_wl_get_peb(struct ubi_device *ubi, int dtype)
+int ubi_wl_get_peb(struct ubi_device *ubi)
{
int err;
struct ubi_wl_entry *e, *first, *last;
- ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM ||
- dtype == UBI_UNKNOWN);
-
retry:
spin_lock(&ubi->wl_lock);
if (!ubi->free.rb_node) {
@@ -413,45 +399,15 @@ retry:
goto retry;
}
- switch (dtype) {
- case UBI_LONGTERM:
- /*
- * For long term data we pick a physical eraseblock with high
- * erase counter. But the highest erase counter we can pick is
- * bounded by the the lowest erase counter plus
- * %WL_FREE_MAX_DIFF.
- */
- e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
- break;
- case UBI_UNKNOWN:
- /*
- * For unknown data we pick a physical eraseblock with medium
- * erase counter. But we by no means can pick a physical
- * eraseblock with erase counter greater or equivalent than the
- * lowest erase counter plus %WL_FREE_MAX_DIFF/2.
- */
- first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry,
- u.rb);
- last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, u.rb);
-
- if (last->ec - first->ec < WL_FREE_MAX_DIFF)
- e = rb_entry(ubi->free.rb_node,
- struct ubi_wl_entry, u.rb);
- else
- e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF/2);
- break;
- case UBI_SHORTTERM:
- /*
- * For short term data we pick a physical eraseblock with the
- * lowest erase counter as we expect it will be erased soon.
- */
- e = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, u.rb);
- break;
- default:
- BUG();
- }
+ first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, u.rb);
+ last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, u.rb);
+
+ if (last->ec - first->ec < WL_FREE_MAX_DIFF)
+ e = rb_entry(ubi->free.rb_node, struct ubi_wl_entry, u.rb);
+ else
+ e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF/2);
- paranoid_check_in_wl_tree(ubi, e, &ubi->free);
+ self_check_in_wl_tree(ubi, e, &ubi->free);
/*
* Move the physical eraseblock to the protection queue where it will
@@ -462,8 +418,8 @@ retry:
prot_queue_add(ubi, e);
spin_unlock(&ubi->wl_lock);
- err = ubi_dbg_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
- ubi->peb_size - ubi->vid_hdr_aloffset);
+ err = ubi_self_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
+ ubi->peb_size - ubi->vid_hdr_aloffset);
if (err) {
ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum);
return err;
@@ -488,7 +444,7 @@ static int prot_queue_del(struct ubi_device *ubi, int pnum)
if (!e)
return -ENODEV;
- if (paranoid_check_in_pq(ubi, e))
+ if (self_check_in_pq(ubi, e))
return -ENODEV;
list_del(&e->u.list);
@@ -514,7 +470,7 @@ static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
dbg_wl("erase PEB %d, old EC %llu", e->pnum, ec);
- err = paranoid_check_ec(ubi, e->pnum, e->ec);
+ err = self_check_ec(ubi, e->pnum, e->ec);
if (err)
return -EINVAL;
@@ -627,13 +583,15 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
* schedule_erase - schedule an erase work.
* @ubi: UBI device description object
* @e: the WL entry of the physical eraseblock to erase
+ * @vol_id: the volume ID that last used this PEB
+ * @lnum: the last used logical eraseblock number for the PEB
* @torture: if the physical eraseblock has to be tortured
*
* This function returns zero in case of success and a %-ENOMEM in case of
* failure.
*/
static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
- int torture)
+ int vol_id, int lnum, int torture)
{
struct ubi_work *wl_wrk;
@@ -646,6 +604,8 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
wl_wrk->func = &erase_worker;
wl_wrk->e = e;
+ wl_wrk->vol_id = vol_id;
+ wl_wrk->lnum = lnum;
wl_wrk->torture = torture;
schedule_ubi_work(ubi, wl_wrk);
@@ -714,7 +674,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
e1->ec, e2->ec);
goto out_cancel;
}
- paranoid_check_in_wl_tree(ubi, e1, &ubi->used);
+ self_check_in_wl_tree(ubi, e1, &ubi->used);
rb_erase(&e1->u.rb, &ubi->used);
dbg_wl("move PEB %d EC %d to PEB %d EC %d",
e1->pnum, e1->ec, e2->pnum, e2->ec);
@@ -723,12 +683,12 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
scrubbing = 1;
e1 = rb_entry(rb_first(&ubi->scrub), struct ubi_wl_entry, u.rb);
e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
- paranoid_check_in_wl_tree(ubi, e1, &ubi->scrub);
+ self_check_in_wl_tree(ubi, e1, &ubi->scrub);
rb_erase(&e1->u.rb, &ubi->scrub);
dbg_wl("scrub PEB %d to PEB %d", e1->pnum, e2->pnum);
}
- paranoid_check_in_wl_tree(ubi, e2, &ubi->free);
+ self_check_in_wl_tree(ubi, e2, &ubi->free);
rb_erase(&e2->u.rb, &ubi->free);
ubi->move_from = e1;
ubi->move_to = e2;
@@ -846,7 +806,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
ubi->move_to_put = ubi->wl_scheduled = 0;
spin_unlock(&ubi->wl_lock);
- err = schedule_erase(ubi, e1, 0);
+ err = schedule_erase(ubi, e1, vol_id, lnum, 0);
if (err) {
kmem_cache_free(ubi_wl_entry_slab, e1);
if (e2)
@@ -861,7 +821,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
*/
dbg_wl("PEB %d (LEB %d:%d) was put meanwhile, erase",
e2->pnum, vol_id, lnum);
- err = schedule_erase(ubi, e2, 0);
+ err = schedule_erase(ubi, e2, vol_id, lnum, 0);
if (err) {
kmem_cache_free(ubi_wl_entry_slab, e2);
goto out_ro;
@@ -900,7 +860,7 @@ out_not_moved:
spin_unlock(&ubi->wl_lock);
ubi_free_vid_hdr(ubi, vid_hdr);
- err = schedule_erase(ubi, e2, torture);
+ err = schedule_erase(ubi, e2, vol_id, lnum, torture);
if (err) {
kmem_cache_free(ubi_wl_entry_slab, e2);
goto out_ro;
@@ -1019,6 +979,8 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
{
struct ubi_wl_entry *e = wl_wrk->e;
int pnum = e->pnum, err, need;
+ int vol_id = wl_wrk->vol_id;
+ int lnum = wl_wrk->lnum;
if (cancel) {
dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec);
@@ -1027,7 +989,8 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
return 0;
}
- dbg_wl("erase PEB %d EC %d", pnum, e->ec);
+ dbg_wl("erase PEB %d EC %d LEB %d:%d",
+ pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum);
err = sync_erase(ubi, e, wl_wrk->torture);
if (!err) {
@@ -1057,7 +1020,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
int err1;
/* Re-schedule the LEB for erasure */
- err1 = schedule_erase(ubi, e, 0);
+ err1 = schedule_erase(ubi, e, vol_id, lnum, 0);
if (err1) {
err = err1;
goto out_ro;
@@ -1125,6 +1088,8 @@ out_ro:
/**
* ubi_wl_put_peb - return a PEB to the wear-leveling sub-system.
* @ubi: UBI device description object
+ * @vol_id: the volume ID that last used this PEB
+ * @lnum: the last used logical eraseblock number for the PEB
* @pnum: physical eraseblock to return
* @torture: if this physical eraseblock has to be tortured
*
@@ -1133,7 +1098,8 @@ out_ro:
* occurred to this @pnum and it has to be tested. This function returns zero
* in case of success, and a negative error code in case of failure.
*/
-int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture)
+int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum,
+ int pnum, int torture)
{
int err;
struct ubi_wl_entry *e;
@@ -1175,13 +1141,13 @@ retry:
return 0;
} else {
if (in_wl_tree(e, &ubi->used)) {
- paranoid_check_in_wl_tree(ubi, e, &ubi->used);
+ self_check_in_wl_tree(ubi, e, &ubi->used);
rb_erase(&e->u.rb, &ubi->used);
} else if (in_wl_tree(e, &ubi->scrub)) {
- paranoid_check_in_wl_tree(ubi, e, &ubi->scrub);
+ self_check_in_wl_tree(ubi, e, &ubi->scrub);
rb_erase(&e->u.rb, &ubi->scrub);
} else if (in_wl_tree(e, &ubi->erroneous)) {
- paranoid_check_in_wl_tree(ubi, e, &ubi->erroneous);
+ self_check_in_wl_tree(ubi, e, &ubi->erroneous);
rb_erase(&e->u.rb, &ubi->erroneous);
ubi->erroneous_peb_count -= 1;
ubi_assert(ubi->erroneous_peb_count >= 0);
@@ -1199,7 +1165,7 @@ retry:
}
spin_unlock(&ubi->wl_lock);
- err = schedule_erase(ubi, e, torture);
+ err = schedule_erase(ubi, e, vol_id, lnum, torture);
if (err) {
spin_lock(&ubi->wl_lock);
wl_tree_add(e, &ubi->used);
@@ -1248,7 +1214,7 @@ retry:
}
if (in_wl_tree(e, &ubi->used)) {
- paranoid_check_in_wl_tree(ubi, e, &ubi->used);
+ self_check_in_wl_tree(ubi, e, &ubi->used);
rb_erase(&e->u.rb, &ubi->used);
} else {
int err;
@@ -1275,44 +1241,55 @@ retry:
/**
* ubi_wl_flush - flush all pending works.
* @ubi: UBI device description object
+ * @vol_id: the volume id to flush for
+ * @lnum: the logical eraseblock number to flush for
*
- * This function returns zero in case of success and a negative error code in
- * case of failure.
+ * This function executes all pending works for a particular volume id /
+ * logical eraseblock number pair. If either value is set to %UBI_ALL, then it
+ * acts as a wildcard for all of the corresponding volume numbers or logical
+ * eraseblock numbers. It returns zero in case of success and a negative error
+ * code in case of failure.
*/
-int ubi_wl_flush(struct ubi_device *ubi)
+int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum)
{
- int err;
+ int err = 0;
+ int found = 1;
/*
* Erase while the pending works queue is not empty, but not more than
* the number of currently pending works.
*/
- dbg_wl("flush (%d pending works)", ubi->works_count);
- while (ubi->works_count) {
- err = do_work(ubi);
- if (err)
- return err;
- }
+ dbg_wl("flush pending work for LEB %d:%d (%d pending works)",
+ vol_id, lnum, ubi->works_count);
- /*
- * Make sure all the works which have been done in parallel are
- * finished.
- */
down_write(&ubi->work_sem);
- up_write(&ubi->work_sem);
+ while (found) {
+ struct ubi_work *wrk;
+ found = 0;
- /*
- * And in case last was the WL worker and it canceled the LEB
- * movement, flush again.
- */
- while (ubi->works_count) {
- dbg_wl("flush more (%d pending works)", ubi->works_count);
- err = do_work(ubi);
- if (err)
- return err;
+ spin_lock(&ubi->wl_lock);
+ list_for_each_entry(wrk, &ubi->works, list) {
+ if ((vol_id == UBI_ALL || wrk->vol_id == vol_id) &&
+ (lnum == UBI_ALL || wrk->lnum == lnum)) {
+ list_del(&wrk->list);
+ ubi->works_count -= 1;
+ ubi_assert(ubi->works_count >= 0);
+ spin_unlock(&ubi->wl_lock);
+
+ err = wrk->func(ubi, wrk, 0);
+ if (err)
+ goto out;
+ spin_lock(&ubi->wl_lock);
+ found = 1;
+ break;
+ }
+ }
+ spin_unlock(&ubi->wl_lock);
}
- return 0;
+out:
+ up_write(&ubi->work_sem);
+ return err;
}
/**
@@ -1421,26 +1398,26 @@ static void cancel_pending(struct ubi_device *ubi)
}
/**
- * ubi_wl_init_scan - initialize the WL sub-system using scanning information.
+ * ubi_wl_init - initialize the WL sub-system using attaching information.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
*
* This function returns zero in case of success, and a negative error code in
* case of failure.
*/
-int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
+int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
{
int err, i;
struct rb_node *rb1, *rb2;
- struct ubi_scan_volume *sv;
- struct ubi_scan_leb *seb, *tmp;
+ struct ubi_ainf_volume *av;
+ struct ubi_ainf_peb *aeb, *tmp;
struct ubi_wl_entry *e;
ubi->used = ubi->erroneous = ubi->free = ubi->scrub = RB_ROOT;
spin_lock_init(&ubi->wl_lock);
mutex_init(&ubi->move_mutex);
init_rwsem(&ubi->work_sem);
- ubi->max_ec = si->max_ec;
+ ubi->max_ec = ai->max_ec;
INIT_LIST_HEAD(&ubi->works);
sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num);
@@ -1454,48 +1431,48 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
INIT_LIST_HEAD(&ubi->pq[i]);
ubi->pq_head = 0;
- list_for_each_entry_safe(seb, tmp, &si->erase, u.list) {
+ list_for_each_entry_safe(aeb, tmp, &ai->erase, u.list) {
cond_resched();
e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
if (!e)
goto out_free;
- e->pnum = seb->pnum;
- e->ec = seb->ec;
+ e->pnum = aeb->pnum;
+ e->ec = aeb->ec;
ubi->lookuptbl[e->pnum] = e;
- if (schedule_erase(ubi, e, 0)) {
+ if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0)) {
kmem_cache_free(ubi_wl_entry_slab, e);
goto out_free;
}
}
- list_for_each_entry(seb, &si->free, u.list) {
+ list_for_each_entry(aeb, &ai->free, u.list) {
cond_resched();
e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
if (!e)
goto out_free;
- e->pnum = seb->pnum;
- e->ec = seb->ec;
+ e->pnum = aeb->pnum;
+ e->ec = aeb->ec;
ubi_assert(e->ec >= 0);
wl_tree_add(e, &ubi->free);
ubi->lookuptbl[e->pnum] = e;
}
- ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
- ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
+ ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
+ ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) {
cond_resched();
e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
if (!e)
goto out_free;
- e->pnum = seb->pnum;
- e->ec = seb->ec;
+ e->pnum = aeb->pnum;
+ e->ec = aeb->ec;
ubi->lookuptbl[e->pnum] = e;
- if (!seb->scrub) {
+ if (!aeb->scrub) {
dbg_wl("add PEB %d EC %d to the used tree",
e->pnum, e->ec);
wl_tree_add(e, &ubi->used);
@@ -1567,10 +1544,8 @@ void ubi_wl_close(struct ubi_device *ubi)
kfree(ubi->lookuptbl);
}
-#ifdef CONFIG_MTD_UBI_DEBUG
-
/**
- * paranoid_check_ec - make sure that the erase counter of a PEB is correct.
+ * self_check_ec - make sure that the erase counter of a PEB is correct.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
* @ec: the erase counter to check
@@ -1579,7 +1554,7 @@ void ubi_wl_close(struct ubi_device *ubi)
* is equivalent to @ec, and a negative error code if not or if an error
* occurred.
*/
-static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
+static int self_check_ec(struct ubi_device *ubi, int pnum, int ec)
{
int err;
long long read_ec;
@@ -1601,9 +1576,9 @@ static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
read_ec = be64_to_cpu(ec_hdr->ec);
if (ec != read_ec) {
- ubi_err("paranoid check failed for PEB %d", pnum);
+ ubi_err("self-check failed for PEB %d", pnum);
ubi_err("read EC is %lld, should be %d", read_ec, ec);
- ubi_dbg_dump_stack();
+ dump_stack();
err = 1;
} else
err = 0;
@@ -1614,7 +1589,7 @@ out_free:
}
/**
- * paranoid_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree.
+ * self_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree.
* @ubi: UBI device description object
* @e: the wear-leveling entry to check
* @root: the root of the tree
@@ -1622,9 +1597,8 @@ out_free:
* This function returns zero if @e is in the @root RB-tree and %-EINVAL if it
* is not.
*/
-static int paranoid_check_in_wl_tree(const struct ubi_device *ubi,
- struct ubi_wl_entry *e,
- struct rb_root *root)
+static int self_check_in_wl_tree(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e, struct rb_root *root)
{
if (!ubi->dbg->chk_gen)
return 0;
@@ -1632,22 +1606,22 @@ static int paranoid_check_in_wl_tree(const struct ubi_device *ubi,
if (in_wl_tree(e, root))
return 0;
- ubi_err("paranoid check failed for PEB %d, EC %d, RB-tree %p ",
+ ubi_err("self-check failed for PEB %d, EC %d, RB-tree %p ",
e->pnum, e->ec, root);
- ubi_dbg_dump_stack();
+ dump_stack();
return -EINVAL;
}
/**
- * paranoid_check_in_pq - check if wear-leveling entry is in the protection
+ * self_check_in_pq - check if wear-leveling entry is in the protection
* queue.
* @ubi: UBI device description object
* @e: the wear-leveling entry to check
*
* This function returns zero if @e is in @ubi->pq and %-EINVAL if it is not.
*/
-static int paranoid_check_in_pq(const struct ubi_device *ubi,
- struct ubi_wl_entry *e)
+static int self_check_in_pq(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e)
{
struct ubi_wl_entry *p;
int i;
@@ -1660,10 +1634,8 @@ static int paranoid_check_in_pq(const struct ubi_device *ubi,
if (p == e)
return 0;
- ubi_err("paranoid check failed for PEB %d, EC %d, Protect queue",
+ ubi_err("self-check failed for PEB %d, EC %d, Protect queue",
e->pnum, e->ec);
- ubi_dbg_dump_stack();
+ dump_stack();
return -EINVAL;
}
-
-#endif /* CONFIG_MTD_UBI_DEBUG */
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 1efb08386c61..38c0690df5c8 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -35,6 +35,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
#define DRV_NAME "flexcan"
@@ -927,11 +928,16 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
struct flexcan_priv *priv;
struct resource *mem;
struct clk *clk = NULL;
+ struct pinctrl *pinctrl;
void __iomem *base;
resource_size_t mem_size;
int err, irq;
u32 clock_freq = 0;
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl))
+ return PTR_ERR(pinctrl);
+
if (pdev->dev.of_node) {
const u32 *clock_freq_p;
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
index b60d6c5f29a0..03df9a8f2bbf 100644
--- a/drivers/net/can/sja1000/Kconfig
+++ b/drivers/net/can/sja1000/Kconfig
@@ -75,7 +75,7 @@ config CAN_KVASER_PCI
tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
depends on PCI
---help---
- This driver is for the the PCIcanx and PCIcan cards (1, 2 or
+ This driver is for the PCIcanx and PCIcan cards (1, 2 or
4 channel) from Kvaser (http://www.kvaser.com).
config CAN_PLX_PCI
diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index 1234a14b2b73..b15366635147 100644
--- a/drivers/net/ethernet/3com/typhoon.c
+++ b/drivers/net/ethernet/3com/typhoon.c
@@ -2549,8 +2549,7 @@ typhoon_init(void)
static void __exit
typhoon_cleanup(void)
{
- if (typhoon_fw)
- release_firmware(typhoon_fw);
+ release_firmware(typhoon_fw);
pci_unregister_driver(&typhoon_driver);
}
diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c
index f4c228e4d76c..f2958df9a1e4 100644
--- a/drivers/net/ethernet/amd/ariadne.c
+++ b/drivers/net/ethernet/amd/ariadne.c
@@ -213,10 +213,10 @@ static int ariadne_rx(struct net_device *dev)
(const void *)priv->rx_buff[entry],
pkt_len);
skb->protocol = eth_type_trans(skb, dev);
- netdev_dbg(dev, "RX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
+ netdev_dbg(dev, "RX pkt type 0x%04x from %pM to %pM data %p len %u\n",
((u_short *)skb->data)[6],
skb->data + 6, skb->data,
- (int)skb->data, (int)skb->len);
+ skb->data, skb->len);
netif_rx(skb);
dev->stats.rx_packets++;
@@ -566,10 +566,10 @@ static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
/* Fill in a Tx ring entry */
- netdev_dbg(dev, "TX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
+ netdev_dbg(dev, "TX pkt type 0x%04x from %pM to %pM data %p len %u\n",
((u_short *)skb->data)[6],
skb->data + 6, skb->data,
- (int)skb->data, (int)skb->len);
+ skb->data, skb->len);
local_irq_save(flags);
diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c
index 70ed79c46245..84219df72f51 100644
--- a/drivers/net/ethernet/amd/atarilance.c
+++ b/drivers/net/ethernet/amd/atarilance.c
@@ -558,21 +558,18 @@ static unsigned long __init lance_probe1( struct net_device *dev,
printk( "Lance: request for irq %d failed\n", IRQ_AUTO_5 );
return 0;
}
- dev->irq = (unsigned short)IRQ_AUTO_5;
+ dev->irq = IRQ_AUTO_5;
}
else {
- /* For VME-RieblCards, request a free VME int;
- * (This must be unsigned long, since dev->irq is short and the
- * IRQ_MACHSPEC bit would be cut off...)
- */
- unsigned long irq = atari_register_vme_int();
+ /* For VME-RieblCards, request a free VME int */
+ unsigned int irq = atari_register_vme_int();
if (!irq) {
printk( "Lance: request for VME interrupt failed\n" );
return 0;
}
if (request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO,
"Riebl-VME Ethernet", dev)) {
- printk( "Lance: request for irq %ld failed\n", irq );
+ printk( "Lance: request for irq %u failed\n", irq );
return 0;
}
dev->irq = irq;
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 39b92f5ed7dd..edeeb516807a 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -195,15 +195,6 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
#define TG3_RX_OFFSET(tp) (NET_SKB_PAD)
#endif
-/* This driver uses the new build_skb() API providing a frag as skb->head
- * This strategy permits better GRO aggregation, better TCP coalescing, and
- * better splice() implementation (avoids a copy from head to a page), at
- * minimal memory cost.
- * In this 2048 bytes block, we have enough room to store the MTU=1500 frame
- * and the struct skb_shared_info.
- */
-#define TG3_FRAGSIZE 2048
-
/* minimum number of free TX descriptors required to wake up TX process */
#define TG3_TX_WAKEUP_THRESH(tnapi) ((tnapi)->tx_pending / 4)
#define TG3_TX_BD_DMA_MAX_2K 2048
@@ -5631,25 +5622,6 @@ static void tg3_tx(struct tg3_napi *tnapi)
}
}
-static void *tg3_frag_alloc(struct tg3_rx_prodring_set *tpr)
-{
- void *data;
-
- if (tpr->rx_page_size < TG3_FRAGSIZE) {
- struct page *page = alloc_page(GFP_ATOMIC);
-
- if (!page)
- return NULL;
- atomic_add((PAGE_SIZE / TG3_FRAGSIZE) - 1, &page->_count);
- tpr->rx_page_addr = page_address(page);
- tpr->rx_page_size = PAGE_SIZE;
- }
- data = tpr->rx_page_addr;
- tpr->rx_page_addr += TG3_FRAGSIZE;
- tpr->rx_page_size -= TG3_FRAGSIZE;
- return data;
-}
-
static void tg3_frag_free(bool is_frag, void *data)
{
if (is_frag)
@@ -5668,7 +5640,7 @@ static void tg3_rx_data_free(struct tg3 *tp, struct ring_info *ri, u32 map_sz)
pci_unmap_single(tp->pdev, dma_unmap_addr(ri, mapping),
map_sz, PCI_DMA_FROMDEVICE);
- tg3_frag_free(skb_size <= TG3_FRAGSIZE, ri->data);
+ tg3_frag_free(skb_size <= PAGE_SIZE, ri->data);
ri->data = NULL;
}
@@ -5721,9 +5693,9 @@ static int tg3_alloc_rx_data(struct tg3 *tp, struct tg3_rx_prodring_set *tpr,
*/
skb_size = SKB_DATA_ALIGN(data_size + TG3_RX_OFFSET(tp)) +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
- if (skb_size <= TG3_FRAGSIZE) {
- data = tg3_frag_alloc(tpr);
- *frag_size = TG3_FRAGSIZE;
+ if (skb_size <= PAGE_SIZE) {
+ data = netdev_alloc_frag(skb_size);
+ *frag_size = skb_size;
} else {
data = kmalloc(skb_size, GFP_ATOMIC);
*frag_size = 0;
@@ -5736,7 +5708,7 @@ static int tg3_alloc_rx_data(struct tg3 *tp, struct tg3_rx_prodring_set *tpr,
data_size,
PCI_DMA_FROMDEVICE);
if (unlikely(pci_dma_mapping_error(tp->pdev, mapping))) {
- tg3_frag_free(skb_size <= TG3_FRAGSIZE, data);
+ tg3_frag_free(skb_size <= PAGE_SIZE, data);
return -EIO;
}
@@ -15911,8 +15883,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
if (dev) {
struct tg3 *tp = netdev_priv(dev);
- if (tp->fw)
- release_firmware(tp->fw);
+ release_firmware(tp->fw);
tg3_reset_task_cancel(tp);
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index 7c855455d937..93865f899a4f 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -2815,8 +2815,6 @@ struct tg3_rx_prodring_set {
struct ring_info *rx_jmb_buffers;
dma_addr_t rx_std_mapping;
dma_addr_t rx_jmb_mapping;
- void *rx_page_addr;
- unsigned int rx_page_size;
};
#define TG3_IRQ_MAX_VECS_RSS 5
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 25c4e7f2a099..67cd2ed0306a 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -3520,9 +3520,7 @@ static void __exit
bnad_module_exit(void)
{
pci_unregister_driver(&bnad_pci_driver);
-
- if (bfi_fw)
- release_firmware(bfi_fw);
+ release_firmware(bfi_fw);
}
module_init(bnad_module_init);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 0fe18850c838..ec2dafe8ae5b 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -51,6 +51,8 @@
#define FW_VERSION_MINOR 1
#define FW_VERSION_MICRO 0
+#define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
+
enum {
MAX_NPORTS = 4, /* max # of ports */
SERNUM_LEN = 24, /* Serial # length */
@@ -64,6 +66,15 @@ enum {
MEM_MC
};
+enum {
+ MEMWIN0_APERTURE = 65536,
+ MEMWIN0_BASE = 0x30000,
+ MEMWIN1_APERTURE = 32768,
+ MEMWIN1_BASE = 0x28000,
+ MEMWIN2_APERTURE = 2048,
+ MEMWIN2_BASE = 0x1b800,
+};
+
enum dev_master {
MASTER_CANT,
MASTER_MAY,
@@ -403,6 +414,9 @@ struct sge_txq {
struct tx_sw_desc *sdesc; /* address of SW Tx descriptor ring */
struct sge_qstat *stat; /* queue status entry */
dma_addr_t phys_addr; /* physical address of the ring */
+ spinlock_t db_lock;
+ int db_disabled;
+ unsigned short db_pidx;
};
struct sge_eth_txq { /* state for an SGE Ethernet Tx queue */
@@ -475,6 +489,7 @@ struct adapter {
void __iomem *regs;
struct pci_dev *pdev;
struct device *pdev_dev;
+ unsigned int mbox;
unsigned int fn;
unsigned int flags;
@@ -504,6 +519,8 @@ struct adapter {
void **tid_release_head;
spinlock_t tid_release_lock;
struct work_struct tid_release_task;
+ struct work_struct db_full_task;
+ struct work_struct db_drop_task;
bool tid_release_task_busy;
struct dentry *debugfs_root;
@@ -605,6 +622,7 @@ irqreturn_t t4_sge_intr_msix(int irq, void *cookie);
void t4_sge_init(struct adapter *adap);
void t4_sge_start(struct adapter *adap);
void t4_sge_stop(struct adapter *adap);
+extern int dbfifo_int_thresh;
#define for_each_port(adapter, iter) \
for (iter = 0; iter < (adapter)->params.nports; ++iter)
@@ -719,4 +737,9 @@ int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
unsigned int vf, unsigned int eqid);
int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
+void t4_db_full(struct adapter *adapter);
+void t4_db_dropped(struct adapter *adapter);
+int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len);
+int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
+ u32 addr, u32 val);
#endif /* __CXGB4_H__ */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index b126b98065a9..e1f96fbb48c1 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -149,15 +149,6 @@ static unsigned int pfvfres_pmask(struct adapter *adapter,
#endif
enum {
- MEMWIN0_APERTURE = 65536,
- MEMWIN0_BASE = 0x30000,
- MEMWIN1_APERTURE = 32768,
- MEMWIN1_BASE = 0x28000,
- MEMWIN2_APERTURE = 2048,
- MEMWIN2_BASE = 0x1b800,
-};
-
-enum {
MAX_TXQ_ENTRIES = 16384,
MAX_CTRL_TXQ_ENTRIES = 1024,
MAX_RSPQ_ENTRIES = 16384,
@@ -371,6 +362,15 @@ static int set_addr_filters(const struct net_device *dev, bool sleep)
uhash | mhash, sleep);
}
+int dbfifo_int_thresh = 10; /* 10 == 640 entry threshold */
+module_param(dbfifo_int_thresh, int, 0644);
+MODULE_PARM_DESC(dbfifo_int_thresh, "doorbell fifo interrupt threshold");
+
+int dbfifo_drain_delay = 1000; /* usecs to sleep while draining the dbfifo */
+module_param(dbfifo_drain_delay, int, 0644);
+MODULE_PARM_DESC(dbfifo_drain_delay,
+ "usecs to sleep while draining the dbfifo");
+
/*
* Set Rx properties of a port, such as promiscruity, address filters, and MTU.
* If @mtu is -1 it is left unchanged.
@@ -389,6 +389,8 @@ static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok)
return ret;
}
+static struct workqueue_struct *workq;
+
/**
* link_start - enable a port
* @dev: the port to enable
@@ -2196,7 +2198,7 @@ static void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan,
adap->tid_release_head = (void **)((uintptr_t)p | chan);
if (!adap->tid_release_task_busy) {
adap->tid_release_task_busy = true;
- schedule_work(&adap->tid_release_task);
+ queue_work(workq, &adap->tid_release_task);
}
spin_unlock_bh(&adap->tid_release_lock);
}
@@ -2366,6 +2368,16 @@ unsigned int cxgb4_port_chan(const struct net_device *dev)
}
EXPORT_SYMBOL(cxgb4_port_chan);
+unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo)
+{
+ struct adapter *adap = netdev2adap(dev);
+ u32 v;
+
+ v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
+ return lpfifo ? G_LP_COUNT(v) : G_HP_COUNT(v);
+}
+EXPORT_SYMBOL(cxgb4_dbfifo_count);
+
/**
* cxgb4_port_viid - get the VI id of a port
* @dev: the net device for the port
@@ -2413,6 +2425,59 @@ void cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask,
}
EXPORT_SYMBOL(cxgb4_iscsi_init);
+int cxgb4_flush_eq_cache(struct net_device *dev)
+{
+ struct adapter *adap = netdev2adap(dev);
+ int ret;
+
+ ret = t4_fwaddrspace_write(adap, adap->mbox,
+ 0xe1000000 + A_SGE_CTXT_CMD, 0x20000000);
+ return ret;
+}
+EXPORT_SYMBOL(cxgb4_flush_eq_cache);
+
+static int read_eq_indices(struct adapter *adap, u16 qid, u16 *pidx, u16 *cidx)
+{
+ u32 addr = t4_read_reg(adap, A_SGE_DBQ_CTXT_BADDR) + 24 * qid + 8;
+ __be64 indices;
+ int ret;
+
+ ret = t4_mem_win_read_len(adap, addr, (__be32 *)&indices, 8);
+ if (!ret) {
+ indices = be64_to_cpu(indices);
+ *cidx = (indices >> 25) & 0xffff;
+ *pidx = (indices >> 9) & 0xffff;
+ }
+ return ret;
+}
+
+int cxgb4_sync_txq_pidx(struct net_device *dev, u16 qid, u16 pidx,
+ u16 size)
+{
+ struct adapter *adap = netdev2adap(dev);
+ u16 hw_pidx, hw_cidx;
+ int ret;
+
+ ret = read_eq_indices(adap, qid, &hw_pidx, &hw_cidx);
+ if (ret)
+ goto out;
+
+ if (pidx != hw_pidx) {
+ u16 delta;
+
+ if (pidx >= hw_pidx)
+ delta = pidx - hw_pidx;
+ else
+ delta = size - hw_pidx + pidx;
+ wmb();
+ t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL),
+ V_QID(qid) | V_PIDX(delta));
+ }
+out:
+ return ret;
+}
+EXPORT_SYMBOL(cxgb4_sync_txq_pidx);
+
static struct pci_driver cxgb4_driver;
static void check_neigh_update(struct neighbour *neigh)
@@ -2446,6 +2511,144 @@ static struct notifier_block cxgb4_netevent_nb = {
.notifier_call = netevent_cb
};
+static void drain_db_fifo(struct adapter *adap, int usecs)
+{
+ u32 v;
+
+ do {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(usecs_to_jiffies(usecs));
+ v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
+ if (G_LP_COUNT(v) == 0 && G_HP_COUNT(v) == 0)
+ break;
+ } while (1);
+}
+
+static void disable_txq_db(struct sge_txq *q)
+{
+ spin_lock_irq(&q->db_lock);
+ q->db_disabled = 1;
+ spin_unlock_irq(&q->db_lock);
+}
+
+static void enable_txq_db(struct sge_txq *q)
+{
+ spin_lock_irq(&q->db_lock);
+ q->db_disabled = 0;
+ spin_unlock_irq(&q->db_lock);
+}
+
+static void disable_dbs(struct adapter *adap)
+{
+ int i;
+
+ for_each_ethrxq(&adap->sge, i)
+ disable_txq_db(&adap->sge.ethtxq[i].q);
+ for_each_ofldrxq(&adap->sge, i)
+ disable_txq_db(&adap->sge.ofldtxq[i].q);
+ for_each_port(adap, i)
+ disable_txq_db(&adap->sge.ctrlq[i].q);
+}
+
+static void enable_dbs(struct adapter *adap)
+{
+ int i;
+
+ for_each_ethrxq(&adap->sge, i)
+ enable_txq_db(&adap->sge.ethtxq[i].q);
+ for_each_ofldrxq(&adap->sge, i)
+ enable_txq_db(&adap->sge.ofldtxq[i].q);
+ for_each_port(adap, i)
+ enable_txq_db(&adap->sge.ctrlq[i].q);
+}
+
+static void sync_txq_pidx(struct adapter *adap, struct sge_txq *q)
+{
+ u16 hw_pidx, hw_cidx;
+ int ret;
+
+ spin_lock_bh(&q->db_lock);
+ ret = read_eq_indices(adap, (u16)q->cntxt_id, &hw_pidx, &hw_cidx);
+ if (ret)
+ goto out;
+ if (q->db_pidx != hw_pidx) {
+ u16 delta;
+
+ if (q->db_pidx >= hw_pidx)
+ delta = q->db_pidx - hw_pidx;
+ else
+ delta = q->size - hw_pidx + q->db_pidx;
+ wmb();
+ t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL),
+ V_QID(q->cntxt_id) | V_PIDX(delta));
+ }
+out:
+ q->db_disabled = 0;
+ spin_unlock_bh(&q->db_lock);
+ if (ret)
+ CH_WARN(adap, "DB drop recovery failed.\n");
+}
+static void recover_all_queues(struct adapter *adap)
+{
+ int i;
+
+ for_each_ethrxq(&adap->sge, i)
+ sync_txq_pidx(adap, &adap->sge.ethtxq[i].q);
+ for_each_ofldrxq(&adap->sge, i)
+ sync_txq_pidx(adap, &adap->sge.ofldtxq[i].q);
+ for_each_port(adap, i)
+ sync_txq_pidx(adap, &adap->sge.ctrlq[i].q);
+}
+
+static void notify_rdma_uld(struct adapter *adap, enum cxgb4_control cmd)
+{
+ mutex_lock(&uld_mutex);
+ if (adap->uld_handle[CXGB4_ULD_RDMA])
+ ulds[CXGB4_ULD_RDMA].control(adap->uld_handle[CXGB4_ULD_RDMA],
+ cmd);
+ mutex_unlock(&uld_mutex);
+}
+
+static void process_db_full(struct work_struct *work)
+{
+ struct adapter *adap;
+
+ adap = container_of(work, struct adapter, db_full_task);
+
+ notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL);
+ drain_db_fifo(adap, dbfifo_drain_delay);
+ t4_set_reg_field(adap, A_SGE_INT_ENABLE3,
+ F_DBFIFO_HP_INT | F_DBFIFO_LP_INT,
+ F_DBFIFO_HP_INT | F_DBFIFO_LP_INT);
+ notify_rdma_uld(adap, CXGB4_CONTROL_DB_EMPTY);
+}
+
+static void process_db_drop(struct work_struct *work)
+{
+ struct adapter *adap;
+
+ adap = container_of(work, struct adapter, db_drop_task);
+
+ t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_DROPPED_DB, 0);
+ disable_dbs(adap);
+ notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP);
+ drain_db_fifo(adap, 1);
+ recover_all_queues(adap);
+ enable_dbs(adap);
+}
+
+void t4_db_full(struct adapter *adap)
+{
+ t4_set_reg_field(adap, A_SGE_INT_ENABLE3,
+ F_DBFIFO_HP_INT | F_DBFIFO_LP_INT, 0);
+ queue_work(workq, &adap->db_full_task);
+}
+
+void t4_db_dropped(struct adapter *adap)
+{
+ queue_work(workq, &adap->db_drop_task);
+}
+
static void uld_attach(struct adapter *adap, unsigned int uld)
{
void *handle;
@@ -2479,6 +2682,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS);
lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL);
lli.fw_vers = adap->params.fw_vers;
+ lli.dbfifo_int_thresh = dbfifo_int_thresh;
handle = ulds[uld].add(&lli);
if (IS_ERR(handle)) {
@@ -2649,6 +2853,8 @@ static void cxgb_down(struct adapter *adapter)
{
t4_intr_disable(adapter);
cancel_work_sync(&adapter->tid_release_task);
+ cancel_work_sync(&adapter->db_full_task);
+ cancel_work_sync(&adapter->db_drop_task);
adapter->tid_release_task_busy = false;
adapter->tid_release_head = NULL;
@@ -3593,6 +3799,7 @@ static int __devinit init_one(struct pci_dev *pdev,
adapter->pdev = pdev;
adapter->pdev_dev = &pdev->dev;
+ adapter->mbox = func;
adapter->fn = func;
adapter->msg_enable = dflt_msg_enable;
memset(adapter->chan_map, 0xff, sizeof(adapter->chan_map));
@@ -3601,6 +3808,8 @@ static int __devinit init_one(struct pci_dev *pdev,
spin_lock_init(&adapter->tid_release_lock);
INIT_WORK(&adapter->tid_release_task, process_tid_release_list);
+ INIT_WORK(&adapter->db_full_task, process_db_full);
+ INIT_WORK(&adapter->db_drop_task, process_db_drop);
err = t4_prep_adapter(adapter);
if (err)
@@ -3788,6 +3997,10 @@ static int __init cxgb4_init_module(void)
{
int ret;
+ workq = create_singlethread_workqueue("cxgb4");
+ if (!workq)
+ return -ENOMEM;
+
/* Debugfs support is optional, just warn if this fails */
cxgb4_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
if (!cxgb4_debugfs_root)
@@ -3803,6 +4016,8 @@ static void __exit cxgb4_cleanup_module(void)
{
pci_unregister_driver(&cxgb4_driver);
debugfs_remove(cxgb4_debugfs_root); /* NULL ok */
+ flush_workqueue(workq);
+ destroy_workqueue(workq);
}
module_init(cxgb4_init_module);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index b1d39b8d141a..d79980c5fc63 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -163,6 +163,12 @@ enum cxgb4_state {
CXGB4_STATE_DETACH
};
+enum cxgb4_control {
+ CXGB4_CONTROL_DB_FULL,
+ CXGB4_CONTROL_DB_EMPTY,
+ CXGB4_CONTROL_DB_DROP,
+};
+
struct pci_dev;
struct l2t_data;
struct net_device;
@@ -212,6 +218,7 @@ struct cxgb4_lld_info {
unsigned short ucq_density; /* # of user CQs/page */
void __iomem *gts_reg; /* address of GTS register */
void __iomem *db_reg; /* address of kernel doorbell */
+ int dbfifo_int_thresh; /* doorbell fifo int threshold */
};
struct cxgb4_uld_info {
@@ -220,11 +227,13 @@ struct cxgb4_uld_info {
int (*rx_handler)(void *handle, const __be64 *rsp,
const struct pkt_gl *gl);
int (*state_change)(void *handle, enum cxgb4_state new_state);
+ int (*control)(void *handle, enum cxgb4_control control, ...);
};
int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p);
int cxgb4_unregister_uld(enum cxgb4_uld type);
int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb);
+unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo);
unsigned int cxgb4_port_chan(const struct net_device *dev);
unsigned int cxgb4_port_viid(const struct net_device *dev);
unsigned int cxgb4_port_idx(const struct net_device *dev);
@@ -236,4 +245,6 @@ void cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask,
const unsigned int *pgsz_order);
struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl,
unsigned int skb_len, unsigned int pull_len);
+int cxgb4_sync_txq_pidx(struct net_device *dev, u16 qid, u16 pidx, u16 size);
+int cxgb4_flush_eq_cache(struct net_device *dev);
#endif /* !__CXGB4_OFLD_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 2dae7959f000..e111d974afd8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -767,8 +767,13 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *q,
static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n)
{
wmb(); /* write descriptors before telling HW */
- t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL),
- QID(q->cntxt_id) | PIDX(n));
+ spin_lock(&q->db_lock);
+ if (!q->db_disabled) {
+ t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL),
+ V_QID(q->cntxt_id) | V_PIDX(n));
+ }
+ q->db_pidx = q->pidx;
+ spin_unlock(&q->db_lock);
}
/**
@@ -2081,6 +2086,7 @@ static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id)
q->stops = q->restarts = 0;
q->stat = (void *)&q->desc[q->size];
q->cntxt_id = id;
+ spin_lock_init(&q->db_lock);
adap->sge.egr_map[id - adap->sge.egr_start] = q;
}
@@ -2415,6 +2421,18 @@ void t4_sge_init(struct adapter *adap)
RXPKTCPLMODE |
(STAT_LEN == 128 ? EGRSTATUSPAGESIZE : 0));
+ /*
+ * Set up to drop DOORBELL writes when the DOORBELL FIFO overflows
+ * and generate an interrupt when this occurs so we can recover.
+ */
+ t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS,
+ V_HP_INT_THRESH(M_HP_INT_THRESH) |
+ V_LP_INT_THRESH(M_LP_INT_THRESH),
+ V_HP_INT_THRESH(dbfifo_int_thresh) |
+ V_LP_INT_THRESH(dbfifo_int_thresh));
+ t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_ENABLE_DROP,
+ F_ENABLE_DROP);
+
for (i = v = 0; i < 32; i += 4)
v |= (PAGE_SHIFT - 10) << i;
t4_write_reg(adap, SGE_HOST_PAGE_SIZE, v);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index d1ec111aebd8..32e1dd566a14 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -868,11 +868,14 @@ int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port)
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
+typedef void (*int_handler_t)(struct adapter *adap);
+
struct intr_info {
unsigned int mask; /* bits to check in interrupt status */
const char *msg; /* message to print or NULL */
short stat_idx; /* stat counter to increment or -1 */
unsigned short fatal; /* whether the condition reported is fatal */
+ int_handler_t int_handler; /* platform-specific int handler */
};
/**
@@ -905,6 +908,8 @@ static int t4_handle_intr_status(struct adapter *adapter, unsigned int reg,
} else if (acts->msg && printk_ratelimit())
dev_warn(adapter->pdev_dev, "%s (0x%x)\n", acts->msg,
status & acts->mask);
+ if (acts->int_handler)
+ acts->int_handler(adapter);
mask |= acts->mask;
}
status &= mask;
@@ -1013,7 +1018,9 @@ static void sge_intr_handler(struct adapter *adapter)
{ ERR_INVALID_CIDX_INC,
"SGE GTS CIDX increment too large", -1, 0 },
{ ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 },
- { ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 },
+ { F_DBFIFO_LP_INT, NULL, -1, 0, t4_db_full },
+ { F_DBFIFO_HP_INT, NULL, -1, 0, t4_db_full },
+ { F_ERR_DROPPED_DB, NULL, -1, 0, t4_db_dropped },
{ ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0,
"SGE IQID > 1023 received CPL for FL", -1, 0 },
{ ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1,
@@ -1034,10 +1041,10 @@ static void sge_intr_handler(struct adapter *adapter)
};
v = (u64)t4_read_reg(adapter, SGE_INT_CAUSE1) |
- ((u64)t4_read_reg(adapter, SGE_INT_CAUSE2) << 32);
+ ((u64)t4_read_reg(adapter, SGE_INT_CAUSE2) << 32);
if (v) {
dev_alert(adapter->pdev_dev, "SGE parity error (%#llx)\n",
- (unsigned long long)v);
+ (unsigned long long)v);
t4_write_reg(adapter, SGE_INT_CAUSE1, v);
t4_write_reg(adapter, SGE_INT_CAUSE2, v >> 32);
}
@@ -1513,6 +1520,7 @@ void t4_intr_enable(struct adapter *adapter)
ERR_BAD_DB_PIDX2 | ERR_BAD_DB_PIDX1 |
ERR_BAD_DB_PIDX0 | ERR_ING_CTXT_PRIO |
ERR_EGR_CTXT_PRIO | INGRESS_SIZE_ERR |
+ F_DBFIFO_HP_INT | F_DBFIFO_LP_INT |
EGRESS_SIZE_ERR);
t4_write_reg(adapter, MYPF_REG(PL_PF_INT_ENABLE), PF_INTR_MASK);
t4_set_reg_field(adapter, PL_INT_MAP0, 0, 1 << pf);
@@ -1986,6 +1994,54 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
(var).retval_len16 = htonl(FW_LEN16(var)); \
} while (0)
+int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
+ u32 addr, u32 val)
+{
+ struct fw_ldst_cmd c;
+
+ memset(&c, 0, sizeof(c));
+ c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
+ F_FW_CMD_WRITE |
+ V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE));
+ c.cycles_to_len16 = htonl(FW_LEN16(c));
+ c.u.addrval.addr = htonl(addr);
+ c.u.addrval.val = htonl(val);
+
+ return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
+}
+
+/*
+ * t4_mem_win_read_len - read memory through PCIE memory window
+ * @adap: the adapter
+ * @addr: address of first byte requested aligned on 32b.
+ * @data: len bytes to hold the data read
+ * @len: amount of data to read from window. Must be <=
+ * MEMWIN0_APERATURE after adjusting for 16B alignment
+ * requirements of the the memory window.
+ *
+ * Read len bytes of data from MC starting at @addr.
+ */
+int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len)
+{
+ int i;
+ int off;
+
+ /*
+ * Align on a 16B boundary.
+ */
+ off = addr & 15;
+ if ((addr & 3) || (len + off) > MEMWIN0_APERTURE)
+ return -EINVAL;
+
+ t4_write_reg(adap, A_PCIE_MEM_ACCESS_OFFSET, addr & ~15);
+ t4_read_reg(adap, A_PCIE_MEM_ACCESS_OFFSET);
+
+ for (i = 0; i < len; i += 4)
+ *data++ = t4_read_reg(adap, (MEMWIN0_BASE + off + i));
+
+ return 0;
+}
+
/**
* t4_mdio_rd - read a PHY register through MDIO
* @adap: the adapter
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 0adc5bcec7c4..111fc323f155 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -190,6 +190,59 @@
#define SGE_DEBUG_DATA_LOW 0x10d4
#define SGE_INGRESS_QUEUES_PER_PAGE_PF 0x10f4
+#define S_LP_INT_THRESH 12
+#define V_LP_INT_THRESH(x) ((x) << S_LP_INT_THRESH)
+#define S_HP_INT_THRESH 28
+#define V_HP_INT_THRESH(x) ((x) << S_HP_INT_THRESH)
+#define A_SGE_DBFIFO_STATUS 0x10a4
+
+#define S_ENABLE_DROP 13
+#define V_ENABLE_DROP(x) ((x) << S_ENABLE_DROP)
+#define F_ENABLE_DROP V_ENABLE_DROP(1U)
+#define A_SGE_DOORBELL_CONTROL 0x10a8
+
+#define A_SGE_CTXT_CMD 0x11fc
+#define A_SGE_DBQ_CTXT_BADDR 0x1084
+
+#define A_SGE_PF_KDOORBELL 0x0
+
+#define S_QID 15
+#define V_QID(x) ((x) << S_QID)
+
+#define S_PIDX 0
+#define V_PIDX(x) ((x) << S_PIDX)
+
+#define M_LP_COUNT 0x7ffU
+#define S_LP_COUNT 0
+#define G_LP_COUNT(x) (((x) >> S_LP_COUNT) & M_LP_COUNT)
+
+#define M_HP_COUNT 0x7ffU
+#define S_HP_COUNT 16
+#define G_HP_COUNT(x) (((x) >> S_HP_COUNT) & M_HP_COUNT)
+
+#define A_SGE_INT_ENABLE3 0x1040
+
+#define S_DBFIFO_HP_INT 8
+#define V_DBFIFO_HP_INT(x) ((x) << S_DBFIFO_HP_INT)
+#define F_DBFIFO_HP_INT V_DBFIFO_HP_INT(1U)
+
+#define S_DBFIFO_LP_INT 7
+#define V_DBFIFO_LP_INT(x) ((x) << S_DBFIFO_LP_INT)
+#define F_DBFIFO_LP_INT V_DBFIFO_LP_INT(1U)
+
+#define S_DROPPED_DB 0
+#define V_DROPPED_DB(x) ((x) << S_DROPPED_DB)
+#define F_DROPPED_DB V_DROPPED_DB(1U)
+
+#define S_ERR_DROPPED_DB 18
+#define V_ERR_DROPPED_DB(x) ((x) << S_ERR_DROPPED_DB)
+#define F_ERR_DROPPED_DB V_ERR_DROPPED_DB(1U)
+
+#define A_PCIE_MEM_ACCESS_OFFSET 0x306c
+
+#define M_HP_INT_THRESH 0xfU
+#define M_LP_INT_THRESH 0xfU
+
#define PCIE_PF_CLI 0x44
#define PCIE_INT_CAUSE 0x3004
#define UNXSPLCPLERR 0x20000000U
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index edcfd7ec7802..ad53f796b574 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -1620,4 +1620,19 @@ struct fw_hdr {
#define FW_HDR_FW_VER_MINOR_GET(x) (((x) >> 16) & 0xff)
#define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff)
#define FW_HDR_FW_VER_BUILD_GET(x) (((x) >> 0) & 0xff)
+
+#define S_FW_CMD_OP 24
+#define V_FW_CMD_OP(x) ((x) << S_FW_CMD_OP)
+
+#define S_FW_CMD_REQUEST 23
+#define V_FW_CMD_REQUEST(x) ((x) << S_FW_CMD_REQUEST)
+#define F_FW_CMD_REQUEST V_FW_CMD_REQUEST(1U)
+
+#define S_FW_CMD_WRITE 21
+#define V_FW_CMD_WRITE(x) ((x) << S_FW_CMD_WRITE)
+#define F_FW_CMD_WRITE V_FW_CMD_WRITE(1U)
+
+#define S_FW_LDST_CMD_ADDRSPACE 0
+#define V_FW_LDST_CMD_ADDRSPACE(x) ((x) << S_FW_LDST_CMD_ADDRSPACE)
+
#endif /* _T4FW_INTERFACE_H_ */
diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c
index b9406cbfc180..845b2020f291 100644
--- a/drivers/net/ethernet/cirrus/cs89x0.c
+++ b/drivers/net/ethernet/cirrus/cs89x0.c
@@ -1,105 +1,27 @@
/* cs89x0.c: A Crystal Semiconductor (Now Cirrus Logic) CS89[02]0
- * driver for linux.
+ * driver for linux.
+ * Written 1996 by Russell Nelson, with reference to skeleton.c
+ * written 1993-1994 by Donald Becker.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * The author may be reached at nelson@crynwr.com, Crynwr
+ * Software, 521 Pleasant Valley Rd., Potsdam, NY 13676
+ *
+ * Other contributors:
+ * Mike Cruse : mcruse@cti-ltd.com
+ * Russ Nelson
+ * Melody Lee : ethernet@crystal.cirrus.com
+ * Alan Cox
+ * Andrew Morton
+ * Oskar Schirmer : oskar@scara.com
+ * Deepak Saxena : dsaxena@plexity.net
+ * Dmitry Pervushin : dpervushin@ru.mvista.com
+ * Deepak Saxena : dsaxena@plexity.net
+ * Domenico Andreoli : cavokz@gmail.com
*/
-/*
- Written 1996 by Russell Nelson, with reference to skeleton.c
- written 1993-1994 by Donald Becker.
-
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
- The author may be reached at nelson@crynwr.com, Crynwr
- Software, 521 Pleasant Valley Rd., Potsdam, NY 13676
-
- Changelog:
-
- Mike Cruse : mcruse@cti-ltd.com
- : Changes for Linux 2.0 compatibility.
- : Added dev_id parameter in net_interrupt(),
- : request_irq() and free_irq(). Just NULL for now.
-
- Mike Cruse : Added MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros
- : in net_open() and net_close() so kerneld would know
- : that the module is in use and wouldn't eject the
- : driver prematurely.
-
- Mike Cruse : Rewrote init_module() and cleanup_module using 8390.c
- : as an example. Disabled autoprobing in init_module(),
- : not a good thing to do to other devices while Linux
- : is running from all accounts.
-
- Russ Nelson : Jul 13 1998. Added RxOnly DMA support.
-
- Melody Lee : Aug 10 1999. Changes for Linux 2.2.5 compatibility.
- : email: ethernet@crystal.cirrus.com
-
- Alan Cox : Removed 1.2 support, added 2.1 extra counters.
-
- Andrew Morton : Kernel 2.3.48
- : Handle kmalloc() failures
- : Other resource allocation fixes
- : Add SMP locks
- : Integrate Russ Nelson's ALLOW_DMA functionality back in.
- : If ALLOW_DMA is true, make DMA runtime selectable
- : Folded in changes from Cirrus (Melody Lee
- : <klee@crystal.cirrus.com>)
- : Don't call netif_wake_queue() in net_send_packet()
- : Fixed an out-of-mem bug in dma_rx()
- : Updated Documentation/networking/cs89x0.txt
-
- Andrew Morton : Kernel 2.3.99-pre1
- : Use skb_reserve to longword align IP header (two places)
- : Remove a delay loop from dma_rx()
- : Replace '100' with HZ
- : Clean up a couple of skb API abuses
- : Added 'cs89x0_dma=N' kernel boot option
- : Correctly initialise lp->lock in non-module compile
-
- Andrew Morton : Kernel 2.3.99-pre4-1
- : MOD_INC/DEC race fix (see
- : http://www.uwsg.indiana.edu/hypermail/linux/kernel/0003.3/1532.html)
-
- Andrew Morton : Kernel 2.4.0-test7-pre2
- : Enhanced EEPROM support to cover more devices,
- : abstracted IRQ mapping to support CONFIG_ARCH_CLPS7500 arch
- : (Jason Gunthorpe <jgg@ualberta.ca>)
-
- Andrew Morton : Kernel 2.4.0-test11-pre4
- : Use dev->name in request_*() (Andrey Panin)
- : Fix an error-path memleak in init_module()
- : Preserve return value from request_irq()
- : Fix type of `media' module parm (Keith Owens)
- : Use SET_MODULE_OWNER()
- : Tidied up strange request_irq() abuse in net_open().
-
- Andrew Morton : Kernel 2.4.3-pre1
- : Request correct number of pages for DMA (Hugh Dickens)
- : Select PP_ChipID _after_ unregister_netdev in cleanup_module()
- : because unregister_netdev() calls get_stats.
- : Make `version[]' __initdata
- : Uninlined the read/write reg/word functions.
-
- Oskar Schirmer : oskar@scara.com
- : HiCO.SH4 (superh) support added (irq#1, cs89x0_media=)
-
- Deepak Saxena : dsaxena@plexity.net
- : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support
-
- Dmitry Pervushin : dpervushin@ru.mvista.com
- : PNX010X platform support
-
- Deepak Saxena : dsaxena@plexity.net
- : Intel IXDP2351 platform support
-
- Dmitry Pervushin : dpervushin@ru.mvista.com
- : PNX010X platform support
-
- Domenico Andreoli : cavokz@gmail.com
- : QQ2440 platform support
-
-*/
-
/*
* Set this to zero to disable DMA code
@@ -119,14 +41,12 @@
*/
#define DEBUGGING 1
-/*
- Sources:
-
- Crynwr packet driver epktisa.
-
- Crystal Semiconductor data sheets.
+/* Sources:
+ * Crynwr packet driver epktisa.
+ * Crystal Semiconductor data sheets.
+ */
-*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/printk.h>
@@ -147,8 +67,8 @@
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/gfp.h>
+#include <linux/io.h>
-#include <asm/io.h>
#include <asm/irq.h>
#include <linux/atomic.h>
#if ALLOW_DMA
@@ -157,35 +77,55 @@
#include "cs89x0.h"
+#define cs89_dbg(val, level, fmt, ...) \
+do { \
+ if (val <= net_debug) \
+ pr_##level(fmt, ##__VA_ARGS__); \
+} while (0)
+
static char version[] __initdata =
-"cs89x0.c: v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton\n";
+ "v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton";
#define DRV_NAME "cs89x0"
/* First, a few definitions that the brave might change.
- A zero-terminated list of I/O addresses to be probed. Some special flags..
- Addr & 1 = Read back the address port, look for signature and reset
- the page window before probing
- Addr & 3 = Reset the page window and probe
- The CLPS eval board has the Cirrus chip at 0x80090300, in ARM IO space,
- but it is possible that a Cirrus board could be plugged into the ISA
- slots. */
+ * A zero-terminated list of I/O addresses to be probed. Some special flags..
+ * Addr & 1 = Read back the address port, look for signature and reset
+ * the page window before probing
+ * Addr & 3 = Reset the page window and probe
+ * The CLPS eval board has the Cirrus chip at 0x80090300, in ARM IO space,
+ * but it is possible that a Cirrus board could be plugged into the ISA
+ * slots.
+ */
/* The cs8900 has 4 IRQ pins, software selectable. cs8900_irq_map maps
- them to system IRQ numbers. This mapping is card specific and is set to
- the configuration of the Cirrus Eval board for this chip. */
+ * them to system IRQ numbers. This mapping is card specific and is set to
+ * the configuration of the Cirrus Eval board for this chip.
+ */
#if defined(CONFIG_MACH_IXDP2351)
#define CS89x0_NONISA_IRQ
-static unsigned int netcard_portlist[] __used __initdata = {IXDP2351_VIRT_CS8900_BASE, 0};
-static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};
+static unsigned int netcard_portlist[] __used __initdata = {
+ IXDP2351_VIRT_CS8900_BASE, 0
+};
+static unsigned int cs8900_irq_map[] = {
+ IRQ_IXDP2351_CS8900, 0, 0, 0
+};
#elif defined(CONFIG_ARCH_IXDP2X01)
#define CS89x0_NONISA_IRQ
-static unsigned int netcard_portlist[] __used __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
-static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
+static unsigned int netcard_portlist[] __used __initdata = {
+ IXDP2X01_CS8900_VIRT_BASE, 0
+};
+static unsigned int cs8900_irq_map[] = {
+ IRQ_IXDP2X01_CS8900, 0, 0, 0
+};
#else
#ifndef CONFIG_CS89x0_PLATFORM
-static unsigned int netcard_portlist[] __used __initdata =
- { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
-static unsigned int cs8900_irq_map[] = {10,11,12,5};
+static unsigned int netcard_portlist[] __used __initdata = {
+ 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240,
+ 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0
+};
+static unsigned int cs8900_irq_map[] = {
+ 10, 11, 12, 5
+};
#endif
#endif
@@ -222,6 +162,8 @@ struct net_local {
int send_underrun; /* keep track of how many underruns in a row we get */
int force; /* force various values; see FORCE* above. */
spinlock_t lock;
+ void __iomem *virt_addr;/* CS89x0 virtual address. */
+ unsigned long size; /* Length of CS89x0 memory region. */
#if ALLOW_DMA
int use_dma; /* Flag: we're using dma */
int dma; /* DMA channel */
@@ -230,119 +172,42 @@ struct net_local {
unsigned char *end_dma_buff; /* points to the end of the buffer */
unsigned char *rx_dma_ptr; /* points to the next packet */
#endif
-#ifdef CONFIG_CS89x0_PLATFORM
- void __iomem *virt_addr;/* Virtual address for accessing the CS89x0. */
- unsigned long phys_addr;/* Physical address for accessing the CS89x0. */
- unsigned long size; /* Length of CS89x0 memory region. */
-#endif
};
-/* Index to functions, as function prototypes. */
-
-static int cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular);
-static int net_open(struct net_device *dev);
-static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t net_interrupt(int irq, void *dev_id);
-static void set_multicast_list(struct net_device *dev);
-static void net_timeout(struct net_device *dev);
-static void net_rx(struct net_device *dev);
-static int net_close(struct net_device *dev);
-static struct net_device_stats *net_get_stats(struct net_device *dev);
-static void reset_chip(struct net_device *dev);
-static int get_eeprom_data(struct net_device *dev, int off, int len, int *buffer);
-static int get_eeprom_cksum(int off, int len, int *buffer);
-static int set_mac_address(struct net_device *dev, void *addr);
-static void count_rx_errors(int status, struct net_device *dev);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void net_poll_controller(struct net_device *dev);
-#endif
-#if ALLOW_DMA
-static void get_dma_channel(struct net_device *dev);
-static void release_dma_buff(struct net_local *lp);
-#endif
-
/* Example routines you must write ;->. */
#define tx_done(dev) 1
/*
* Permit 'cs89x0_dma=N' in the kernel boot environment
*/
-#if !defined(MODULE) && (ALLOW_DMA != 0)
+#if !defined(MODULE)
+#if ALLOW_DMA
static int g_cs89x0_dma;
static int __init dma_fn(char *str)
{
- g_cs89x0_dma = simple_strtol(str,NULL,0);
+ g_cs89x0_dma = simple_strtol(str, NULL, 0);
return 1;
}
__setup("cs89x0_dma=", dma_fn);
-#endif /* !defined(MODULE) && (ALLOW_DMA != 0) */
+#endif /* ALLOW_DMA */
-#ifndef MODULE
static int g_cs89x0_media__force;
static int __init media_fn(char *str)
{
- if (!strcmp(str, "rj45")) g_cs89x0_media__force = FORCE_RJ45;
- else if (!strcmp(str, "aui")) g_cs89x0_media__force = FORCE_AUI;
- else if (!strcmp(str, "bnc")) g_cs89x0_media__force = FORCE_BNC;
+ if (!strcmp(str, "rj45"))
+ g_cs89x0_media__force = FORCE_RJ45;
+ else if (!strcmp(str, "aui"))
+ g_cs89x0_media__force = FORCE_AUI;
+ else if (!strcmp(str, "bnc"))
+ g_cs89x0_media__force = FORCE_BNC;
+
return 1;
}
__setup("cs89x0_media=", media_fn);
-
-
-#ifndef CONFIG_CS89x0_PLATFORM
-/* Check for a network adaptor of this type, and return '0' iff one exists.
- If dev->base_addr == 0, probe all likely locations.
- If dev->base_addr == 1, always return failure.
- If dev->base_addr == 2, allocate space for the device and return success
- (detachable devices only).
- Return 0 on success.
- */
-
-struct net_device * __init cs89x0_probe(int unit)
-{
- struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
- unsigned *port;
- int err = 0;
- int irq;
- int io;
-
- if (!dev)
- return ERR_PTR(-ENODEV);
-
- sprintf(dev->name, "eth%d", unit);
- netdev_boot_setup_check(dev);
- io = dev->base_addr;
- irq = dev->irq;
-
- if (net_debug)
- printk("cs89x0:cs89x0_probe(0x%x)\n", io);
-
- if (io > 0x1ff) { /* Check a single specified location. */
- err = cs89x0_probe1(dev, io, 0);
- } else if (io != 0) { /* Don't probe at all. */
- err = -ENXIO;
- } else {
- for (port = netcard_portlist; *port; port++) {
- if (cs89x0_probe1(dev, *port, 0) == 0)
- break;
- dev->irq = irq;
- }
- if (!*port)
- err = -ENODEV;
- }
- if (err)
- goto out;
- return dev;
-out:
- free_netdev(dev);
- printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n");
- return ERR_PTR(err);
-}
-#endif
#endif
#if defined(CONFIG_MACH_IXDP2351)
@@ -369,36 +234,22 @@ writeword(unsigned long base_addr, int portno, u16 value)
{
__raw_writel(value, base_addr + (portno << 1));
}
-#else
-static u16
-readword(unsigned long base_addr, int portno)
-{
- return inw(base_addr + portno);
-}
-
-static void
-writeword(unsigned long base_addr, int portno, u16 value)
-{
- outw(value, base_addr + portno);
-}
#endif
-static void
-readwords(unsigned long base_addr, int portno, void *buf, int length)
+static void readwords(struct net_local *lp, int portno, void *buf, int length)
{
u8 *buf8 = (u8 *)buf;
do {
u16 tmp16;
- tmp16 = readword(base_addr, portno);
+ tmp16 = ioread16(lp->virt_addr + portno);
*buf8++ = (u8)tmp16;
*buf8++ = (u8)(tmp16 >> 8);
} while (--length);
}
-static void
-writewords(unsigned long base_addr, int portno, void *buf, int length)
+static void writewords(struct net_local *lp, int portno, void *buf, int length)
{
u8 *buf8 = (u8 *)buf;
@@ -407,32 +258,37 @@ writewords(unsigned long base_addr, int portno, void *buf, int length)
tmp16 = *buf8++;
tmp16 |= (*buf8++) << 8;
- writeword(base_addr, portno, tmp16);
+ iowrite16(tmp16, lp->virt_addr + portno);
} while (--length);
}
static u16
readreg(struct net_device *dev, u16 regno)
{
- writeword(dev->base_addr, ADD_PORT, regno);
- return readword(dev->base_addr, DATA_PORT);
+ struct net_local *lp = netdev_priv(dev);
+
+ iowrite16(regno, lp->virt_addr + ADD_PORT);
+ return ioread16(lp->virt_addr + DATA_PORT);
}
static void
writereg(struct net_device *dev, u16 regno, u16 value)
{
- writeword(dev->base_addr, ADD_PORT, regno);
- writeword(dev->base_addr, DATA_PORT, value);
+ struct net_local *lp = netdev_priv(dev);
+
+ iowrite16(regno, lp->virt_addr + ADD_PORT);
+ iowrite16(value, lp->virt_addr + DATA_PORT);
}
static int __init
wait_eeprom_ready(struct net_device *dev)
{
int timeout = jiffies;
- /* check to see if the EEPROM is ready, a timeout is used -
- just in case EEPROM is ready when SI_BUSY in the
- PP_SelfST is clear */
- while(readreg(dev, PP_SelfST) & SI_BUSY)
+ /* check to see if the EEPROM is ready,
+ * a timeout is used just in case EEPROM is ready when
+ * SI_BUSY in the PP_SelfST is clear
+ */
+ while (readreg(dev, PP_SelfST) & SI_BUSY)
if (jiffies - timeout >= 40)
return -1;
return 0;
@@ -443,17 +299,19 @@ get_eeprom_data(struct net_device *dev, int off, int len, int *buffer)
{
int i;
- if (net_debug > 3) printk("EEPROM data from %x for %x:\n",off,len);
+ cs89_dbg(3, info, "EEPROM data from %x for %x:", off, len);
for (i = 0; i < len; i++) {
- if (wait_eeprom_ready(dev) < 0) return -1;
+ if (wait_eeprom_ready(dev) < 0)
+ return -1;
/* Now send the EEPROM read command and EEPROM location to read */
writereg(dev, PP_EECMD, (off + i) | EEPROM_READ_CMD);
- if (wait_eeprom_ready(dev) < 0) return -1;
+ if (wait_eeprom_ready(dev) < 0)
+ return -1;
buffer[i] = readreg(dev, PP_EEData);
- if (net_debug > 3) printk("%04x ", buffer[i]);
+ cs89_dbg(3, cont, " %04x", buffer[i]);
}
- if (net_debug > 3) printk("\n");
- return 0;
+ cs89_dbg(3, cont, "\n");
+ return 0;
}
static int __init
@@ -470,341 +328,52 @@ get_eeprom_cksum(int off, int len, int *buffer)
return -1;
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling receive - used by netconsole and other diagnostic tools
- * to allow network i/o with interrupts disabled.
- */
-static void net_poll_controller(struct net_device *dev)
-{
- disable_irq(dev->irq);
- net_interrupt(dev->irq, dev);
- enable_irq(dev->irq);
-}
-#endif
-
-static const struct net_device_ops net_ops = {
- .ndo_open = net_open,
- .ndo_stop = net_close,
- .ndo_tx_timeout = net_timeout,
- .ndo_start_xmit = net_send_packet,
- .ndo_get_stats = net_get_stats,
- .ndo_set_rx_mode = set_multicast_list,
- .ndo_set_mac_address = set_mac_address,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = net_poll_controller,
-#endif
- .ndo_change_mtu = eth_change_mtu,
- .ndo_validate_addr = eth_validate_addr,
-};
-
-/* This is the real probe routine. Linux has a history of friendly device
- probes on the ISA bus. A good device probes avoids doing writes, and
- verifies that the correct device exists and functions.
- Return 0 on success.
- */
-
-static int __init
-cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular)
+static void
+write_irq(struct net_device *dev, int chip_type, int irq)
{
- struct net_local *lp = netdev_priv(dev);
- static unsigned version_printed;
int i;
- int tmp;
- unsigned rev_type = 0;
- int eeprom_buff[CHKSUM_LEN];
- int retval;
-
- /* Initialize the device structure. */
- if (!modular) {
- memset(lp, 0, sizeof(*lp));
- spin_lock_init(&lp->lock);
-#ifndef MODULE
-#if ALLOW_DMA
- if (g_cs89x0_dma) {
- lp->use_dma = 1;
- lp->dma = g_cs89x0_dma;
- lp->dmasize = 16; /* Could make this an option... */
- }
-#endif
- lp->force = g_cs89x0_media__force;
-#endif
-
- }
-
- /* Grab the region so we can find another board if autoIRQ fails. */
- /* WTF is going on here? */
- if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) {
- printk(KERN_ERR "%s: request_region(0x%lx, 0x%x) failed\n",
- DRV_NAME, ioaddr, NETCARD_IO_EXTENT);
- retval = -EBUSY;
- goto out1;
- }
-
- /* if they give us an odd I/O address, then do ONE write to
- the address port, to get it back to address zero, where we
- expect to find the EISA signature word. An IO with a base of 0x3
- will skip the test for the ADD_PORT. */
- if (ioaddr & 1) {
- if (net_debug > 1)
- printk(KERN_INFO "%s: odd ioaddr 0x%lx\n", dev->name, ioaddr);
- if ((ioaddr & 2) != 2)
- if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) {
- printk(KERN_ERR "%s: bad signature 0x%x\n",
- dev->name, readword(ioaddr & ~3, ADD_PORT));
- retval = -ENODEV;
- goto out2;
- }
- }
-
- ioaddr &= ~3;
- printk(KERN_DEBUG "PP_addr at %lx[%x]: 0x%x\n",
- ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT));
- writeword(ioaddr, ADD_PORT, PP_ChipID);
-
- tmp = readword(ioaddr, DATA_PORT);
- if (tmp != CHIP_EISA_ID_SIG) {
- printk(KERN_DEBUG "%s: incorrect signature at %lx[%x]: 0x%x!="
- CHIP_EISA_ID_SIG_STR "\n",
- dev->name, ioaddr, DATA_PORT, tmp);
- retval = -ENODEV;
- goto out2;
- }
-
- /* Fill in the 'dev' fields. */
- dev->base_addr = ioaddr;
-
- /* get the chip type */
- rev_type = readreg(dev, PRODUCT_ID_ADD);
- lp->chip_type = rev_type &~ REVISON_BITS;
- lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
-
- /* Check the chip type and revision in order to set the correct send command
- CS8920 revision C and CS8900 revision F can use the faster send. */
- lp->send_cmd = TX_AFTER_381;
- if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
- lp->send_cmd = TX_NOW;
- if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
- lp->send_cmd = TX_NOW;
-
- if (net_debug && version_printed++ == 0)
- printk(version);
-
- printk(KERN_INFO "%s: cs89%c0%s rev %c found at %#3lx ",
- dev->name,
- lp->chip_type==CS8900?'0':'2',
- lp->chip_type==CS8920M?"M":"",
- lp->chip_revision,
- dev->base_addr);
-
- reset_chip(dev);
-
- /* Here we read the current configuration of the chip. If there
- is no Extended EEPROM then the idea is to not disturb the chip
- configuration, it should have been correctly setup by automatic
- EEPROM read on reset. So, if the chip says it read the EEPROM
- the driver will always do *something* instead of complain that
- adapter_cnf is 0. */
-
-
- if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) ==
- (EEPROM_OK|EEPROM_PRESENT)) {
- /* Load the MAC. */
- for (i=0; i < ETH_ALEN/2; i++) {
- unsigned int Addr;
- Addr = readreg(dev, PP_IA+i*2);
- dev->dev_addr[i*2] = Addr & 0xFF;
- dev->dev_addr[i*2+1] = Addr >> 8;
- }
-
- /* Load the Adapter Configuration.
- Note: Barring any more specific information from some
- other source (ie EEPROM+Schematics), we would not know
- how to operate a 10Base2 interface on the AUI port.
- However, since we do read the status of HCB1 and use
- settings that always result in calls to control_dc_dc(dev,0)
- a BNC interface should work if the enable pin
- (dc/dc converter) is on HCB1. It will be called AUI
- however. */
-
- lp->adapter_cnf = 0;
- i = readreg(dev, PP_LineCTL);
- /* Preserve the setting of the HCB1 pin. */
- if ((i & (HCB1 | HCB1_ENBL)) == (HCB1 | HCB1_ENBL))
- lp->adapter_cnf |= A_CNF_DC_DC_POLARITY;
- /* Save the sqelch bit */
- if ((i & LOW_RX_SQUELCH) == LOW_RX_SQUELCH)
- lp->adapter_cnf |= A_CNF_EXTND_10B_2 | A_CNF_LOW_RX_SQUELCH;
- /* Check if the card is in 10Base-t only mode */
- if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == 0)
- lp->adapter_cnf |= A_CNF_10B_T | A_CNF_MEDIA_10B_T;
- /* Check if the card is in AUI only mode */
- if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUI_ONLY)
- lp->adapter_cnf |= A_CNF_AUI | A_CNF_MEDIA_AUI;
- /* Check if the card is in Auto mode. */
- if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUTO_AUI_10BASET)
- lp->adapter_cnf |= A_CNF_AUI | A_CNF_10B_T |
- A_CNF_MEDIA_AUI | A_CNF_MEDIA_10B_T | A_CNF_MEDIA_AUTO;
-
- if (net_debug > 1)
- printk(KERN_INFO "%s: PP_LineCTL=0x%x, adapter_cnf=0x%x\n",
- dev->name, i, lp->adapter_cnf);
-
- /* IRQ. Other chips already probe, see below. */
- if (lp->chip_type == CS8900)
- lp->isa_config = readreg(dev, PP_CS8900_ISAINT) & INT_NO_MASK;
-
- printk( "[Cirrus EEPROM] ");
- }
-
- printk("\n");
-
- /* First check to see if an EEPROM is attached. */
-
- if ((readreg(dev, PP_SelfST) & EEPROM_PRESENT) == 0)
- printk(KERN_WARNING "cs89x0: No EEPROM, relying on command line....\n");
- else if (get_eeprom_data(dev, START_EEPROM_DATA,CHKSUM_LEN,eeprom_buff) < 0) {
- printk(KERN_WARNING "\ncs89x0: EEPROM read failed, relying on command line.\n");
- } else if (get_eeprom_cksum(START_EEPROM_DATA,CHKSUM_LEN,eeprom_buff) < 0) {
- /* Check if the chip was able to read its own configuration starting
- at 0 in the EEPROM*/
- if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) !=
- (EEPROM_OK|EEPROM_PRESENT))
- printk(KERN_WARNING "cs89x0: Extended EEPROM checksum bad and no Cirrus EEPROM, relying on command line\n");
-
- } else {
- /* This reads an extended EEPROM that is not documented
- in the CS8900 datasheet. */
-
- /* get transmission control word but keep the autonegotiation bits */
- if (!lp->auto_neg_cnf) lp->auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET/2];
- /* Store adapter configuration */
- if (!lp->adapter_cnf) lp->adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET/2];
- /* Store ISA configuration */
- lp->isa_config = eeprom_buff[ISA_CNF_OFFSET/2];
- dev->mem_start = eeprom_buff[PACKET_PAGE_OFFSET/2] << 8;
-
- /* eeprom_buff has 32-bit ints, so we can't just memcpy it */
- /* store the initial memory base address */
- for (i = 0; i < ETH_ALEN/2; i++) {
- dev->dev_addr[i*2] = eeprom_buff[i];
- dev->dev_addr[i*2+1] = eeprom_buff[i] >> 8;
- }
- if (net_debug > 1)
- printk(KERN_DEBUG "%s: new adapter_cnf: 0x%x\n",
- dev->name, lp->adapter_cnf);
- }
-
- /* allow them to force multiple transceivers. If they force multiple, autosense */
- {
- int count = 0;
- if (lp->force & FORCE_RJ45) {lp->adapter_cnf |= A_CNF_10B_T; count++; }
- if (lp->force & FORCE_AUI) {lp->adapter_cnf |= A_CNF_AUI; count++; }
- if (lp->force & FORCE_BNC) {lp->adapter_cnf |= A_CNF_10B_2; count++; }
- if (count > 1) {lp->adapter_cnf |= A_CNF_MEDIA_AUTO; }
- else if (lp->force & FORCE_RJ45){lp->adapter_cnf |= A_CNF_MEDIA_10B_T; }
- else if (lp->force & FORCE_AUI) {lp->adapter_cnf |= A_CNF_MEDIA_AUI; }
- else if (lp->force & FORCE_BNC) {lp->adapter_cnf |= A_CNF_MEDIA_10B_2; }
- }
-
- if (net_debug > 1)
- printk(KERN_DEBUG "%s: after force 0x%x, adapter_cnf=0x%x\n",
- dev->name, lp->force, lp->adapter_cnf);
-
- /* FIXME: We don't let you set dc-dc polarity or low RX squelch from the command line: add it here */
-
- /* FIXME: We don't let you set the IMM bit from the command line: add it to lp->auto_neg_cnf here */
-
- /* FIXME: we don't set the Ethernet address on the command line. Use
- ifconfig IFACE hw ether AABBCCDDEEFF */
-
- printk(KERN_INFO "cs89x0 media %s%s%s",
- (lp->adapter_cnf & A_CNF_10B_T)?"RJ-45,":"",
- (lp->adapter_cnf & A_CNF_AUI)?"AUI,":"",
- (lp->adapter_cnf & A_CNF_10B_2)?"BNC,":"");
-
- lp->irq_map = 0xffff;
- /* If this is a CS8900 then no pnp soft */
- if (lp->chip_type != CS8900 &&
- /* Check if the ISA IRQ has been set */
- (i = readreg(dev, PP_CS8920_ISAINT) & 0xff,
- (i != 0 && i < CS8920_NO_INTS))) {
- if (!dev->irq)
- dev->irq = i;
- } else {
- i = lp->isa_config & INT_NO_MASK;
+ if (chip_type == CS8900) {
#ifndef CONFIG_CS89x0_PLATFORM
- if (lp->chip_type == CS8900) {
-#ifdef CS89x0_NONISA_IRQ
- i = cs8900_irq_map[0];
+ /* Search the mapping table for the corresponding IRQ pin. */
+ for (i = 0; i != ARRAY_SIZE(cs8900_irq_map); i++)
+ if (cs8900_irq_map[i] == irq)
+ break;
+ /* Not found */
+ if (i == ARRAY_SIZE(cs8900_irq_map))
+ i = 3;
#else
- /* Translate the IRQ using the IRQ mapping table. */
- if (i >= ARRAY_SIZE(cs8900_irq_map))
- printk("\ncs89x0: invalid ISA interrupt number %d\n", i);
- else
- i = cs8900_irq_map[i];
-
- lp->irq_map = CS8900_IRQ_MAP; /* fixed IRQ map for CS8900 */
- } else {
- int irq_map_buff[IRQ_MAP_LEN/2];
-
- if (get_eeprom_data(dev, IRQ_MAP_EEPROM_DATA,
- IRQ_MAP_LEN/2,
- irq_map_buff) >= 0) {
- if ((irq_map_buff[0] & 0xff) == PNP_IRQ_FRMT)
- lp->irq_map = (irq_map_buff[0]>>8) | (irq_map_buff[1] << 8);
- }
-#endif
- }
-#endif
- if (!dev->irq)
- dev->irq = i;
- }
-
- printk(" IRQ %d", dev->irq);
-
-#if ALLOW_DMA
- if (lp->use_dma) {
- get_dma_channel(dev);
- printk(", DMA %d", dev->dma);
- }
- else
+ /* INTRQ0 pin is used for interrupt generation. */
+ i = 0;
#endif
- {
- printk(", programmed I/O");
+ writereg(dev, PP_CS8900_ISAINT, i);
+ } else {
+ writereg(dev, PP_CS8920_ISAINT, irq);
}
-
- /* print the ethernet address. */
- printk(", MAC %pM", dev->dev_addr);
-
- dev->netdev_ops = &net_ops;
- dev->watchdog_timeo = HZ;
-
- printk("\n");
- if (net_debug)
- printk("cs89x0_probe1() successful\n");
-
- retval = register_netdev(dev);
- if (retval)
- goto out3;
- return 0;
-out3:
- writeword(dev->base_addr, ADD_PORT, PP_ChipID);
-out2:
- release_region(ioaddr & ~3, NETCARD_IO_EXTENT);
-out1:
- return retval;
}
+static void
+count_rx_errors(int status, struct net_device *dev)
+{
+ dev->stats.rx_errors++;
+ if (status & RX_RUNT)
+ dev->stats.rx_length_errors++;
+ if (status & RX_EXTRA_DATA)
+ dev->stats.rx_length_errors++;
+ if ((status & RX_CRC_ERROR) && !(status & (RX_EXTRA_DATA | RX_RUNT)))
+ /* per str 172 */
+ dev->stats.rx_crc_errors++;
+ if (status & RX_DRIBBLE)
+ dev->stats.rx_frame_errors++;
+}
/*********************************
* This page contains DMA routines
-**********************************/
+ *********************************/
#if ALLOW_DMA
-#define dma_page_eq(ptr1, ptr2) ((long)(ptr1)>>17 == (long)(ptr2)>>17)
+#define dma_page_eq(ptr1, ptr2) ((long)(ptr1) >> 17 == (long)(ptr2) >> 17)
static void
get_dma_channel(struct net_device *dev)
@@ -833,11 +402,10 @@ write_dma(struct net_device *dev, int chip_type, int dma)
struct net_local *lp = netdev_priv(dev);
if ((lp->isa_config & ANY_ISA_DMA) == 0)
return;
- if (chip_type == CS8900) {
- writereg(dev, PP_CS8900_ISADMA, dma-5);
- } else {
+ if (chip_type == CS8900)
+ writereg(dev, PP_CS8900_ISADMA, dma - 5);
+ else
writereg(dev, PP_CS8920_ISADMA, dma);
- }
}
static void
@@ -847,18 +415,15 @@ set_dma_cfg(struct net_device *dev)
if (lp->use_dma) {
if ((lp->isa_config & ANY_ISA_DMA) == 0) {
- if (net_debug > 3)
- printk("set_dma_cfg(): no DMA\n");
+ cs89_dbg(3, err, "set_dma_cfg(): no DMA\n");
return;
}
if (lp->isa_config & ISA_RxDMA) {
lp->curr_rx_cfg |= RX_DMA_ONLY;
- if (net_debug > 3)
- printk("set_dma_cfg(): RX_DMA_ONLY\n");
+ cs89_dbg(3, info, "set_dma_cfg(): RX_DMA_ONLY\n");
} else {
lp->curr_rx_cfg |= AUTO_RX_DMA; /* not that we support it... */
- if (net_debug > 3)
- printk("set_dma_cfg(): AUTO_RX_DMA\n");
+ cs89_dbg(3, info, "set_dma_cfg(): AUTO_RX_DMA\n");
}
}
}
@@ -868,7 +433,7 @@ dma_bufcfg(struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
if (lp->use_dma)
- return (lp->isa_config & ANY_ISA_DMA)? RX_DMA_ENBL : 0;
+ return (lp->isa_config & ANY_ISA_DMA) ? RX_DMA_ENBL : 0;
else
return 0;
}
@@ -898,13 +463,13 @@ dma_rx(struct net_device *dev)
int status, length;
unsigned char *bp = lp->rx_dma_ptr;
- status = bp[0] + (bp[1]<<8);
- length = bp[2] + (bp[3]<<8);
+ status = bp[0] + (bp[1] << 8);
+ length = bp[2] + (bp[3] << 8);
bp += 4;
- if (net_debug > 5) {
- printk( "%s: receiving DMA packet at %lx, status %x, length %x\n",
- dev->name, (unsigned long)bp, status, length);
- }
+
+ cs89_dbg(5, debug, "%s: receiving DMA packet at %lx, status %x, length %x\n",
+ dev->name, (unsigned long)bp, status, length);
+
if ((status & RX_OK) == 0) {
count_rx_errors(status, dev);
goto skip_this_frame;
@@ -913,14 +478,16 @@ dma_rx(struct net_device *dev)
/* Malloc up new buffer. */
skb = netdev_alloc_skb(dev, length + 2);
if (skb == NULL) {
- if (net_debug) /* I don't think we want to do this to a stressed system */
- printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+ /* I don't think we want to do this to a stressed system */
+ cs89_dbg(0, err, "%s: Memory squeeze, dropping packet\n",
+ dev->name);
dev->stats.rx_dropped++;
/* AKPM: advance bp to the next frame */
skip_this_frame:
bp += (length + 3) & ~3;
- if (bp >= lp->end_dma_buff) bp -= lp->dmasize*1024;
+ if (bp >= lp->end_dma_buff)
+ bp -= lp->dmasize * 1024;
lp->rx_dma_ptr = bp;
return;
}
@@ -928,63 +495,38 @@ skip_this_frame:
if (bp + length > lp->end_dma_buff) {
int semi_cnt = lp->end_dma_buff - bp;
- memcpy(skb_put(skb,semi_cnt), bp, semi_cnt);
- memcpy(skb_put(skb,length - semi_cnt), lp->dma_buff,
+ memcpy(skb_put(skb, semi_cnt), bp, semi_cnt);
+ memcpy(skb_put(skb, length - semi_cnt), lp->dma_buff,
length - semi_cnt);
} else {
- memcpy(skb_put(skb,length), bp, length);
+ memcpy(skb_put(skb, length), bp, length);
}
bp += (length + 3) & ~3;
- if (bp >= lp->end_dma_buff) bp -= lp->dmasize*1024;
+ if (bp >= lp->end_dma_buff)
+ bp -= lp->dmasize*1024;
lp->rx_dma_ptr = bp;
- if (net_debug > 3) {
- printk( "%s: received %d byte DMA packet of type %x\n",
- dev->name, length,
- (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
- }
- skb->protocol=eth_type_trans(skb,dev);
+ cs89_dbg(3, info, "%s: received %d byte DMA packet of type %x\n",
+ dev->name, length,
+ ((skb->data[ETH_ALEN + ETH_ALEN] << 8) |
+ skb->data[ETH_ALEN + ETH_ALEN + 1]));
+
+ skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += length;
}
-#endif /* ALLOW_DMA */
-
-static void __init reset_chip(struct net_device *dev)
+static void release_dma_buff(struct net_local *lp)
{
-#if !defined(CONFIG_MACH_MX31ADS)
-#if !defined(CS89x0_NONISA_IRQ)
- struct net_local *lp = netdev_priv(dev);
- int ioaddr = dev->base_addr;
-#endif /* CS89x0_NONISA_IRQ */
- int reset_start_time;
-
- writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
-
- /* wait 30 ms */
- msleep(30);
-
-#if !defined(CS89x0_NONISA_IRQ)
- if (lp->chip_type != CS8900) {
- /* Hardware problem requires PNP registers to be reconfigured after a reset */
- writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT);
- outb(dev->irq, ioaddr + DATA_PORT);
- outb(0, ioaddr + DATA_PORT + 1);
-
- writeword(ioaddr, ADD_PORT, PP_CS8920_ISAMemB);
- outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT);
- outb((dev->mem_start >> 8) & 0xff, ioaddr + DATA_PORT + 1);
+ if (lp->dma_buff) {
+ free_pages((unsigned long)(lp->dma_buff),
+ get_order(lp->dmasize * 1024));
+ lp->dma_buff = NULL;
}
-#endif /* CS89x0_NONISA_IRQ */
-
- /* Wait until the chip is reset */
- reset_start_time = jiffies;
- while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)
- ;
-#endif /* !CONFIG_MACH_MX31ADS */
}
+#endif /* ALLOW_DMA */
static void
control_dc_dc(struct net_device *dev, int on_not_off)
@@ -993,8 +535,9 @@ control_dc_dc(struct net_device *dev, int on_not_off)
unsigned int selfcontrol;
int timenow = jiffies;
/* control the DC to DC convertor in the SelfControl register.
- Note: This is hooked up to a general purpose pin, might not
- always be a DC to DC convertor. */
+ * Note: This is hooked up to a general purpose pin, might not
+ * always be a DC to DC convertor.
+ */
selfcontrol = HCB1_ENBL; /* Enable the HCB1 bit as an output */
if (((lp->adapter_cnf & A_CNF_DC_DC_POLARITY) != 0) ^ on_not_off)
@@ -1008,6 +551,49 @@ control_dc_dc(struct net_device *dev, int on_not_off)
;
}
+/* send a test packet - return true if carrier bits are ok */
+static int
+send_test_pkt(struct net_device *dev)
+{
+ struct net_local *lp = netdev_priv(dev);
+ char test_packet[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 46, /* A 46 in network order */
+ 0, 0, /* DSAP=0 & SSAP=0 fields */
+ 0xf3, 0 /* Control (Test Req + P bit set) */
+ };
+ long timenow = jiffies;
+
+ writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_TX_ON);
+
+ memcpy(test_packet, dev->dev_addr, ETH_ALEN);
+ memcpy(test_packet + ETH_ALEN, dev->dev_addr, ETH_ALEN);
+
+ iowrite16(TX_AFTER_ALL, lp->virt_addr + TX_CMD_PORT);
+ iowrite16(ETH_ZLEN, lp->virt_addr + TX_LEN_PORT);
+
+ /* Test to see if the chip has allocated memory for the packet */
+ while (jiffies - timenow < 5)
+ if (readreg(dev, PP_BusST) & READY_FOR_TX_NOW)
+ break;
+ if (jiffies - timenow >= 5)
+ return 0; /* this shouldn't happen */
+
+ /* Write the contents of the packet */
+ writewords(lp, TX_FRAME_PORT, test_packet, (ETH_ZLEN + 1) >> 1);
+
+ cs89_dbg(1, debug, "Sending test packet ");
+ /* wait a couple of jiffies for packet to be received */
+ for (timenow = jiffies; jiffies - timenow < 3;)
+ ;
+ if ((readreg(dev, PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
+ cs89_dbg(1, cont, "succeeded\n");
+ return 1;
+ }
+ cs89_dbg(1, cont, "failed\n");
+ return 0;
+}
+
#define DETECTED_NONE 0
#define DETECTED_RJ45H 1
#define DETECTED_RJ45F 2
@@ -1021,40 +607,46 @@ detect_tp(struct net_device *dev)
int timenow = jiffies;
int fdx;
- if (net_debug > 1) printk("%s: Attempting TP\n", dev->name);
+ cs89_dbg(1, debug, "%s: Attempting TP\n", dev->name);
- /* If connected to another full duplex capable 10-Base-T card the link pulses
- seem to be lost when the auto detect bit in the LineCTL is set.
- To overcome this the auto detect bit will be cleared whilst testing the
- 10-Base-T interface. This would not be necessary for the sparrow chip but
- is simpler to do it anyway. */
- writereg(dev, PP_LineCTL, lp->linectl &~ AUI_ONLY);
+ /* If connected to another full duplex capable 10-Base-T card
+ * the link pulses seem to be lost when the auto detect bit in
+ * the LineCTL is set. To overcome this the auto detect bit will
+ * be cleared whilst testing the 10-Base-T interface. This would
+ * not be necessary for the sparrow chip but is simpler to do it
+ * anyway.
+ */
+ writereg(dev, PP_LineCTL, lp->linectl & ~AUI_ONLY);
control_dc_dc(dev, 0);
- /* Delay for the hardware to work out if the TP cable is present - 150ms */
- for (timenow = jiffies; jiffies - timenow < 15; )
- ;
+ /* Delay for the hardware to work out if the TP cable is present
+ * - 150ms
+ */
+ for (timenow = jiffies; jiffies - timenow < 15;)
+ ;
if ((readreg(dev, PP_LineST) & LINK_OK) == 0)
return DETECTED_NONE;
if (lp->chip_type == CS8900) {
- switch (lp->force & 0xf0) {
+ switch (lp->force & 0xf0) {
#if 0
- case FORCE_AUTO:
- printk("%s: cs8900 doesn't autonegotiate\n",dev->name);
- return DETECTED_NONE;
+ case FORCE_AUTO:
+ pr_info("%s: cs8900 doesn't autonegotiate\n",
+ dev->name);
+ return DETECTED_NONE;
#endif
- /* CS8900 doesn't support AUTO, change to HALF*/
- case FORCE_AUTO:
+ /* CS8900 doesn't support AUTO, change to HALF*/
+ case FORCE_AUTO:
lp->force &= ~FORCE_AUTO;
- lp->force |= FORCE_HALF;
+ lp->force |= FORCE_HALF;
break;
case FORCE_HALF:
break;
- case FORCE_FULL:
- writereg(dev, PP_TestCTL, readreg(dev, PP_TestCTL) | FDX_8900);
+ case FORCE_FULL:
+ writereg(dev, PP_TestCTL,
+ readreg(dev, PP_TestCTL) | FDX_8900);
break;
- }
+ }
fdx = readreg(dev, PP_TestCTL) & FDX_8900;
} else {
switch (lp->force & 0xf0) {
@@ -1067,15 +659,15 @@ detect_tp(struct net_device *dev)
case FORCE_FULL:
lp->auto_neg_cnf = RE_NEG_NOW | ALLOW_FDX;
break;
- }
+ }
writereg(dev, PP_AutoNegCTL, lp->auto_neg_cnf & AUTO_NEG_MASK);
if ((lp->auto_neg_cnf & AUTO_NEG_BITS) == AUTO_NEG_ENABLE) {
- printk(KERN_INFO "%s: negotiating duplex...\n",dev->name);
+ pr_info("%s: negotiating duplex...\n", dev->name);
while (readreg(dev, PP_AutoNegST) & AUTO_NEG_BUSY) {
if (jiffies - timenow > 4000) {
- printk(KERN_ERR "**** Full / half duplex auto-negotiation timed out ****\n");
+ pr_err("**** Full / half duplex auto-negotiation timed out ****\n");
break;
}
}
@@ -1088,56 +680,31 @@ detect_tp(struct net_device *dev)
return DETECTED_RJ45H;
}
-/* send a test packet - return true if carrier bits are ok */
static int
-send_test_pkt(struct net_device *dev)
+detect_bnc(struct net_device *dev)
{
- char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
- 0, 46, /* A 46 in network order */
- 0, 0, /* DSAP=0 & SSAP=0 fields */
- 0xf3, 0 /* Control (Test Req + P bit set) */ };
- long timenow = jiffies;
-
- writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_TX_ON);
-
- memcpy(test_packet, dev->dev_addr, ETH_ALEN);
- memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN);
-
- writeword(dev->base_addr, TX_CMD_PORT, TX_AFTER_ALL);
- writeword(dev->base_addr, TX_LEN_PORT, ETH_ZLEN);
+ struct net_local *lp = netdev_priv(dev);
- /* Test to see if the chip has allocated memory for the packet */
- while (jiffies - timenow < 5)
- if (readreg(dev, PP_BusST) & READY_FOR_TX_NOW)
- break;
- if (jiffies - timenow >= 5)
- return 0; /* this shouldn't happen */
+ cs89_dbg(1, debug, "%s: Attempting BNC\n", dev->name);
+ control_dc_dc(dev, 1);
- /* Write the contents of the packet */
- writewords(dev->base_addr, TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);
+ writereg(dev, PP_LineCTL, (lp->linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
- if (net_debug > 1) printk("Sending test packet ");
- /* wait a couple of jiffies for packet to be received */
- for (timenow = jiffies; jiffies - timenow < 3; )
- ;
- if ((readreg(dev, PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
- if (net_debug > 1) printk("succeeded\n");
- return 1;
- }
- if (net_debug > 1) printk("failed\n");
- return 0;
+ if (send_test_pkt(dev))
+ return DETECTED_BNC;
+ else
+ return DETECTED_NONE;
}
-
static int
detect_aui(struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
- if (net_debug > 1) printk("%s: Attempting AUI\n", dev->name);
+ cs89_dbg(1, debug, "%s: Attempting AUI\n", dev->name);
control_dc_dc(dev, 0);
- writereg(dev, PP_LineCTL, (lp->linectl &~ AUTO_AUI_10BASET) | AUI_ONLY);
+ writereg(dev, PP_LineCTL, (lp->linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
if (send_test_pkt(dev))
return DETECTED_AUI;
@@ -1145,45 +712,154 @@ detect_aui(struct net_device *dev)
return DETECTED_NONE;
}
-static int
-detect_bnc(struct net_device *dev)
+/* We have a good packet(s), get it/them out of the buffers. */
+static void
+net_rx(struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
+ struct sk_buff *skb;
+ int status, length;
- if (net_debug > 1) printk("%s: Attempting BNC\n", dev->name);
- control_dc_dc(dev, 1);
+ status = ioread16(lp->virt_addr + RX_FRAME_PORT);
+ length = ioread16(lp->virt_addr + RX_FRAME_PORT);
- writereg(dev, PP_LineCTL, (lp->linectl &~ AUTO_AUI_10BASET) | AUI_ONLY);
+ if ((status & RX_OK) == 0) {
+ count_rx_errors(status, dev);
+ return;
+ }
- if (send_test_pkt(dev))
- return DETECTED_BNC;
- else
- return DETECTED_NONE;
+ /* Malloc up new buffer. */
+ skb = netdev_alloc_skb(dev, length + 2);
+ if (skb == NULL) {
+#if 0 /* Again, this seems a cruel thing to do */
+ pr_warn("%s: Memory squeeze, dropping packet\n", dev->name);
+#endif
+ dev->stats.rx_dropped++;
+ return;
+ }
+ skb_reserve(skb, 2); /* longword align L3 header */
+
+ readwords(lp, RX_FRAME_PORT, skb_put(skb, length), length >> 1);
+ if (length & 1)
+ skb->data[length-1] = ioread16(lp->virt_addr + RX_FRAME_PORT);
+
+ cs89_dbg(3, debug, "%s: received %d byte packet of type %x\n",
+ dev->name, length,
+ (skb->data[ETH_ALEN + ETH_ALEN] << 8) |
+ skb->data[ETH_ALEN + ETH_ALEN + 1]);
+
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += length;
}
+/* The typical workload of the driver:
+ * Handle the network interface interrupts.
+ */
-static void
-write_irq(struct net_device *dev, int chip_type, int irq)
+static irqreturn_t net_interrupt(int irq, void *dev_id)
{
- int i;
+ struct net_device *dev = dev_id;
+ struct net_local *lp;
+ int status;
+ int handled = 0;
- if (chip_type == CS8900) {
-#ifndef CONFIG_CS89x0_PLATFORM
- /* Search the mapping table for the corresponding IRQ pin. */
- for (i = 0; i != ARRAY_SIZE(cs8900_irq_map); i++)
- if (cs8900_irq_map[i] == irq)
- break;
- /* Not found */
- if (i == ARRAY_SIZE(cs8900_irq_map))
- i = 3;
-#else
- /* INTRQ0 pin is used for interrupt generation. */
- i = 0;
+ lp = netdev_priv(dev);
+
+ /* we MUST read all the events out of the ISQ, otherwise we'll never
+ * get interrupted again. As a consequence, we can't have any limit
+ * on the number of times we loop in the interrupt handler. The
+ * hardware guarantees that eventually we'll run out of events. Of
+ * course, if you're on a slow machine, and packets are arriving
+ * faster than you can read them off, you're screwed. Hasta la
+ * vista, baby!
+ */
+ while ((status = ioread16(lp->virt_addr + ISQ_PORT))) {
+ cs89_dbg(4, debug, "%s: event=%04x\n", dev->name, status);
+ handled = 1;
+ switch (status & ISQ_EVENT_MASK) {
+ case ISQ_RECEIVER_EVENT:
+ /* Got a packet(s). */
+ net_rx(dev);
+ break;
+ case ISQ_TRANSMITTER_EVENT:
+ dev->stats.tx_packets++;
+ netif_wake_queue(dev); /* Inform upper layers. */
+ if ((status & (TX_OK |
+ TX_LOST_CRS |
+ TX_SQE_ERROR |
+ TX_LATE_COL |
+ TX_16_COL)) != TX_OK) {
+ if ((status & TX_OK) == 0)
+ dev->stats.tx_errors++;
+ if (status & TX_LOST_CRS)
+ dev->stats.tx_carrier_errors++;
+ if (status & TX_SQE_ERROR)
+ dev->stats.tx_heartbeat_errors++;
+ if (status & TX_LATE_COL)
+ dev->stats.tx_window_errors++;
+ if (status & TX_16_COL)
+ dev->stats.tx_aborted_errors++;
+ }
+ break;
+ case ISQ_BUFFER_EVENT:
+ if (status & READY_FOR_TX) {
+ /* we tried to transmit a packet earlier,
+ * but inexplicably ran out of buffers.
+ * That shouldn't happen since we only ever
+ * load one packet. Shrug. Do the right
+ * thing anyway.
+ */
+ netif_wake_queue(dev); /* Inform upper layers. */
+ }
+ if (status & TX_UNDERRUN) {
+ cs89_dbg(0, err, "%s: transmit underrun\n",
+ dev->name);
+ lp->send_underrun++;
+ if (lp->send_underrun == 3)
+ lp->send_cmd = TX_AFTER_381;
+ else if (lp->send_underrun == 6)
+ lp->send_cmd = TX_AFTER_ALL;
+ /* transmit cycle is done, although
+ * frame wasn't transmitted - this
+ * avoids having to wait for the upper
+ * layers to timeout on us, in the
+ * event of a tx underrun
+ */
+ netif_wake_queue(dev); /* Inform upper layers. */
+ }
+#if ALLOW_DMA
+ if (lp->use_dma && (status & RX_DMA)) {
+ int count = readreg(dev, PP_DmaFrameCnt);
+ while (count) {
+ cs89_dbg(5, debug,
+ "%s: receiving %d DMA frames\n",
+ dev->name, count);
+ if (count > 1)
+ cs89_dbg(2, debug,
+ "%s: receiving %d DMA frames\n",
+ dev->name, count);
+ dma_rx(dev);
+ if (--count == 0)
+ count = readreg(dev, PP_DmaFrameCnt);
+ if (count > 0)
+ cs89_dbg(2, debug,
+ "%s: continuing with %d DMA frames\n",
+ dev->name, count);
+ }
+ }
#endif
- writereg(dev, PP_CS8900_ISAINT, i);
- } else {
- writereg(dev, PP_CS8920_ISAINT, irq);
+ break;
+ case ISQ_RX_MISS_EVENT:
+ dev->stats.rx_missed_errors += (status >> 6);
+ break;
+ case ISQ_TX_COL_EVENT:
+ dev->stats.collisions += (status >> 6);
+ break;
+ }
}
+ return IRQ_RETVAL(handled);
}
/* Open/initialize the board. This is called (in the current kernel)
@@ -1192,7 +868,7 @@ write_irq(struct net_device *dev, int chip_type, int irq)
This routine should set everything up anew at each open, even
registers that "should" only need to be set once at boot, so that
there is non-reboot way to recover if something goes wrong.
- */
+*/
/* AKPM: do we need to do any locking here? */
@@ -1208,14 +884,15 @@ net_open(struct net_device *dev)
/* Allow interrupts to be generated by the chip */
/* Cirrus' release had this: */
#if 0
- writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
+ writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) | ENABLE_IRQ);
#endif
/* And 2.3.47 had this: */
writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
for (i = 2; i < CS8920_NO_INTS; i++) {
if ((1 << i) & lp->irq_map) {
- if (request_irq(i, net_interrupt, 0, dev->name, dev) == 0) {
+ if (request_irq(i, net_interrupt, 0, dev->name,
+ dev) == 0) {
dev->irq = i;
write_irq(dev, lp->chip_type, i);
/* writereg(dev, PP_BufCFG, GENERATE_SW_INTERRUPT); */
@@ -1226,23 +903,21 @@ net_open(struct net_device *dev)
if (i >= CS8920_NO_INTS) {
writereg(dev, PP_BusCTL, 0); /* disable interrupts. */
- printk(KERN_ERR "cs89x0: can't get an interrupt\n");
+ pr_err("can't get an interrupt\n");
ret = -EAGAIN;
goto bad_out;
}
- }
- else
- {
+ } else {
#if !defined(CS89x0_NONISA_IRQ) && !defined(CONFIG_CS89x0_PLATFORM)
if (((1 << dev->irq) & lp->irq_map) == 0) {
- printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
- dev->name, dev->irq, lp->irq_map);
+ pr_err("%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
+ dev->name, dev->irq, lp->irq_map);
ret = -EAGAIN;
goto bad_out;
}
#endif
/* FIXME: Cirrus' release had this: */
- writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
+ writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ);
/* And 2.3.47 had this: */
#if 0
writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
@@ -1250,147 +925,168 @@ net_open(struct net_device *dev)
write_irq(dev, lp->chip_type, dev->irq);
ret = request_irq(dev->irq, net_interrupt, 0, dev->name, dev);
if (ret) {
- printk(KERN_ERR "cs89x0: request_irq(%d) failed\n", dev->irq);
+ pr_err("request_irq(%d) failed\n", dev->irq);
goto bad_out;
}
}
#if ALLOW_DMA
- if (lp->use_dma) {
- if (lp->isa_config & ANY_ISA_DMA) {
- unsigned long flags;
- lp->dma_buff = (unsigned char *)__get_dma_pages(GFP_KERNEL,
- get_order(lp->dmasize * 1024));
-
- if (!lp->dma_buff) {
- printk(KERN_ERR "%s: cannot get %dK memory for DMA\n", dev->name, lp->dmasize);
- goto release_irq;
- }
- if (net_debug > 1) {
- printk( "%s: dma %lx %lx\n",
- dev->name,
- (unsigned long)lp->dma_buff,
- (unsigned long)isa_virt_to_bus(lp->dma_buff));
- }
- if ((unsigned long) lp->dma_buff >= MAX_DMA_ADDRESS ||
- !dma_page_eq(lp->dma_buff, lp->dma_buff+lp->dmasize*1024-1)) {
- printk(KERN_ERR "%s: not usable as DMA buffer\n", dev->name);
- goto release_irq;
- }
- memset(lp->dma_buff, 0, lp->dmasize * 1024); /* Why? */
- if (request_dma(dev->dma, dev->name)) {
- printk(KERN_ERR "%s: cannot get dma channel %d\n", dev->name, dev->dma);
- goto release_irq;
- }
- write_dma(dev, lp->chip_type, dev->dma);
- lp->rx_dma_ptr = lp->dma_buff;
- lp->end_dma_buff = lp->dma_buff + lp->dmasize*1024;
- spin_lock_irqsave(&lp->lock, flags);
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- set_dma_mode(dev->dma, DMA_RX_MODE); /* auto_init as well */
- set_dma_addr(dev->dma, isa_virt_to_bus(lp->dma_buff));
- set_dma_count(dev->dma, lp->dmasize*1024);
- enable_dma(dev->dma);
- spin_unlock_irqrestore(&lp->lock, flags);
+ if (lp->use_dma && (lp->isa_config & ANY_ISA_DMA)) {
+ unsigned long flags;
+ lp->dma_buff = (unsigned char *)__get_dma_pages(GFP_KERNEL,
+ get_order(lp->dmasize * 1024));
+ if (!lp->dma_buff) {
+ pr_err("%s: cannot get %dK memory for DMA\n",
+ dev->name, lp->dmasize);
+ goto release_irq;
+ }
+ cs89_dbg(1, debug, "%s: dma %lx %lx\n",
+ dev->name,
+ (unsigned long)lp->dma_buff,
+ (unsigned long)isa_virt_to_bus(lp->dma_buff));
+ if ((unsigned long)lp->dma_buff >= MAX_DMA_ADDRESS ||
+ !dma_page_eq(lp->dma_buff,
+ lp->dma_buff + lp->dmasize * 1024 - 1)) {
+ pr_err("%s: not usable as DMA buffer\n", dev->name);
+ goto release_irq;
}
+ memset(lp->dma_buff, 0, lp->dmasize * 1024); /* Why? */
+ if (request_dma(dev->dma, dev->name)) {
+ pr_err("%s: cannot get dma channel %d\n",
+ dev->name, dev->dma);
+ goto release_irq;
+ }
+ write_dma(dev, lp->chip_type, dev->dma);
+ lp->rx_dma_ptr = lp->dma_buff;
+ lp->end_dma_buff = lp->dma_buff + lp->dmasize * 1024;
+ spin_lock_irqsave(&lp->lock, flags);
+ disable_dma(dev->dma);
+ clear_dma_ff(dev->dma);
+ set_dma_mode(dev->dma, DMA_RX_MODE); /* auto_init as well */
+ set_dma_addr(dev->dma, isa_virt_to_bus(lp->dma_buff));
+ set_dma_count(dev->dma, lp->dmasize * 1024);
+ enable_dma(dev->dma);
+ spin_unlock_irqrestore(&lp->lock, flags);
}
#endif /* ALLOW_DMA */
/* set the Ethernet address */
- for (i=0; i < ETH_ALEN/2; i++)
- writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
+ for (i = 0; i < ETH_ALEN / 2; i++)
+ writereg(dev, PP_IA + i * 2,
+ (dev->dev_addr[i * 2] |
+ (dev->dev_addr[i * 2 + 1] << 8)));
/* while we're testing the interface, leave interrupts disabled */
writereg(dev, PP_BusCTL, MEMORY_ON);
/* Set the LineCTL quintuplet based on adapter configuration read from EEPROM */
- if ((lp->adapter_cnf & A_CNF_EXTND_10B_2) && (lp->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
- lp->linectl = LOW_RX_SQUELCH;
+ if ((lp->adapter_cnf & A_CNF_EXTND_10B_2) &&
+ (lp->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
+ lp->linectl = LOW_RX_SQUELCH;
else
- lp->linectl = 0;
-
- /* check to make sure that they have the "right" hardware available */
- switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
- case A_CNF_MEDIA_10B_T: result = lp->adapter_cnf & A_CNF_10B_T; break;
- case A_CNF_MEDIA_AUI: result = lp->adapter_cnf & A_CNF_AUI; break;
- case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;
- default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
- }
- if (!result) {
- printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name);
+ lp->linectl = 0;
+
+ /* check to make sure that they have the "right" hardware available */
+ switch (lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
+ case A_CNF_MEDIA_10B_T:
+ result = lp->adapter_cnf & A_CNF_10B_T;
+ break;
+ case A_CNF_MEDIA_AUI:
+ result = lp->adapter_cnf & A_CNF_AUI;
+ break;
+ case A_CNF_MEDIA_10B_2:
+ result = lp->adapter_cnf & A_CNF_10B_2;
+ break;
+ default:
+ result = lp->adapter_cnf & (A_CNF_10B_T |
+ A_CNF_AUI |
+ A_CNF_10B_2);
+ }
+ if (!result) {
+ pr_err("%s: EEPROM is configured for unavailable media\n",
+ dev->name);
release_dma:
#if ALLOW_DMA
free_dma(dev->dma);
release_irq:
release_dma_buff(lp);
#endif
- writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));
- free_irq(dev->irq, dev);
+ writereg(dev, PP_LineCTL,
+ readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));
+ free_irq(dev->irq, dev);
ret = -EAGAIN;
goto bad_out;
}
- /* set the hardware to the configured choice */
- switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
+ /* set the hardware to the configured choice */
+ switch (lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
case A_CNF_MEDIA_10B_T:
- result = detect_tp(dev);
- if (result==DETECTED_NONE) {
- printk(KERN_WARNING "%s: 10Base-T (RJ-45) has no cable\n", dev->name);
- if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
- result = DETECTED_RJ45H; /* Yes! I don't care if I see a link pulse */
- }
+ result = detect_tp(dev);
+ if (result == DETECTED_NONE) {
+ pr_warn("%s: 10Base-T (RJ-45) has no cable\n",
+ dev->name);
+ if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
+ result = DETECTED_RJ45H; /* Yes! I don't care if I see a link pulse */
+ }
break;
case A_CNF_MEDIA_AUI:
- result = detect_aui(dev);
- if (result==DETECTED_NONE) {
- printk(KERN_WARNING "%s: 10Base-5 (AUI) has no cable\n", dev->name);
- if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
- result = DETECTED_AUI; /* Yes! I don't care if I see a carrrier */
- }
+ result = detect_aui(dev);
+ if (result == DETECTED_NONE) {
+ pr_warn("%s: 10Base-5 (AUI) has no cable\n", dev->name);
+ if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
+ result = DETECTED_AUI; /* Yes! I don't care if I see a carrrier */
+ }
break;
case A_CNF_MEDIA_10B_2:
- result = detect_bnc(dev);
- if (result==DETECTED_NONE) {
- printk(KERN_WARNING "%s: 10Base-2 (BNC) has no cable\n", dev->name);
- if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
- result = DETECTED_BNC; /* Yes! I don't care if I can xmit a packet */
- }
+ result = detect_bnc(dev);
+ if (result == DETECTED_NONE) {
+ pr_warn("%s: 10Base-2 (BNC) has no cable\n", dev->name);
+ if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
+ result = DETECTED_BNC; /* Yes! I don't care if I can xmit a packet */
+ }
break;
case A_CNF_MEDIA_AUTO:
writereg(dev, PP_LineCTL, lp->linectl | AUTO_AUI_10BASET);
- if (lp->adapter_cnf & A_CNF_10B_T)
- if ((result = detect_tp(dev)) != DETECTED_NONE)
+ if (lp->adapter_cnf & A_CNF_10B_T) {
+ result = detect_tp(dev);
+ if (result != DETECTED_NONE)
break;
- if (lp->adapter_cnf & A_CNF_AUI)
- if ((result = detect_aui(dev)) != DETECTED_NONE)
+ }
+ if (lp->adapter_cnf & A_CNF_AUI) {
+ result = detect_aui(dev);
+ if (result != DETECTED_NONE)
break;
- if (lp->adapter_cnf & A_CNF_10B_2)
- if ((result = detect_bnc(dev)) != DETECTED_NONE)
+ }
+ if (lp->adapter_cnf & A_CNF_10B_2) {
+ result = detect_bnc(dev);
+ if (result != DETECTED_NONE)
break;
- printk(KERN_ERR "%s: no media detected\n", dev->name);
+ }
+ pr_err("%s: no media detected\n", dev->name);
goto release_dma;
}
- switch(result) {
+ switch (result) {
case DETECTED_NONE:
- printk(KERN_ERR "%s: no network cable attached to configured media\n", dev->name);
+ pr_err("%s: no network cable attached to configured media\n",
+ dev->name);
goto release_dma;
case DETECTED_RJ45H:
- printk(KERN_INFO "%s: using half-duplex 10Base-T (RJ-45)\n", dev->name);
+ pr_info("%s: using half-duplex 10Base-T (RJ-45)\n", dev->name);
break;
case DETECTED_RJ45F:
- printk(KERN_INFO "%s: using full-duplex 10Base-T (RJ-45)\n", dev->name);
+ pr_info("%s: using full-duplex 10Base-T (RJ-45)\n", dev->name);
break;
case DETECTED_AUI:
- printk(KERN_INFO "%s: using 10Base-5 (AUI)\n", dev->name);
+ pr_info("%s: using 10Base-5 (AUI)\n", dev->name);
break;
case DETECTED_BNC:
- printk(KERN_INFO "%s: using 10Base-2 (BNC)\n", dev->name);
+ pr_info("%s: using 10Base-2 (BNC)\n", dev->name);
break;
}
/* Turn on both receive and transmit operations */
- writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
+ writereg(dev, PP_LineCTL,
+ readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
/* Receive only error free packets addressed to this card */
lp->rx_mode = 0;
@@ -1405,358 +1101,653 @@ release_irq:
#endif
writereg(dev, PP_RxCFG, lp->curr_rx_cfg);
- writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |
- TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
+ writereg(dev, PP_TxCFG, (TX_LOST_CRS_ENBL |
+ TX_SQE_ERROR_ENBL |
+ TX_OK_ENBL |
+ TX_LATE_COL_ENBL |
+ TX_JBR_ENBL |
+ TX_ANY_COL_ENBL |
+ TX_16_COL_ENBL));
- writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |
+ writereg(dev, PP_BufCFG, (READY_FOR_TX_ENBL |
+ RX_MISS_COUNT_OVRFLOW_ENBL |
#if ALLOW_DMA
- dma_bufcfg(dev) |
+ dma_bufcfg(dev) |
#endif
- TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);
+ TX_COL_COUNT_OVRFLOW_ENBL |
+ TX_UNDERRUN_ENBL));
/* now that we've got our act together, enable everything */
- writereg(dev, PP_BusCTL, ENABLE_IRQ
- | (dev->mem_start?MEMORY_ON : 0) /* turn memory on */
+ writereg(dev, PP_BusCTL, (ENABLE_IRQ
+ | (dev->mem_start ? MEMORY_ON : 0) /* turn memory on */
#if ALLOW_DMA
- | dma_busctl(dev)
+ | dma_busctl(dev)
#endif
- );
- netif_start_queue(dev);
- if (net_debug > 1)
- printk("cs89x0: net_open() succeeded\n");
+ ));
+ netif_start_queue(dev);
+ cs89_dbg(1, debug, "net_open() succeeded\n");
return 0;
bad_out:
return ret;
}
+/* The inverse routine to net_open(). */
+static int
+net_close(struct net_device *dev)
+{
+#if ALLOW_DMA
+ struct net_local *lp = netdev_priv(dev);
+#endif
+
+ netif_stop_queue(dev);
+
+ writereg(dev, PP_RxCFG, 0);
+ writereg(dev, PP_TxCFG, 0);
+ writereg(dev, PP_BufCFG, 0);
+ writereg(dev, PP_BusCTL, 0);
+
+ free_irq(dev->irq, dev);
+
+#if ALLOW_DMA
+ if (lp->use_dma && lp->dma) {
+ free_dma(dev->dma);
+ release_dma_buff(lp);
+ }
+#endif
+
+ /* Update the statistics here. */
+ return 0;
+}
+
+/* Get the current statistics.
+ * This may be called with the card open or closed.
+ */
+static struct net_device_stats *
+net_get_stats(struct net_device *dev)
+{
+ struct net_local *lp = netdev_priv(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&lp->lock, flags);
+ /* Update the statistics from the device registers. */
+ dev->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
+ dev->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ return &dev->stats;
+}
+
static void net_timeout(struct net_device *dev)
{
/* If we get here, some higher level has decided we are broken.
There should really be a "kick me" function call instead. */
- if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
- tx_done(dev) ? "IRQ conflict ?" : "network cable problem");
+ cs89_dbg(0, err, "%s: transmit timed out, %s?\n",
+ dev->name,
+ tx_done(dev) ? "IRQ conflict" : "network cable problem");
/* Try to restart the adaptor. */
netif_wake_queue(dev);
}
-static netdev_tx_t net_send_packet(struct sk_buff *skb,struct net_device *dev)
+static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
unsigned long flags;
- if (net_debug > 3) {
- printk("%s: sent %d byte packet of type %x\n",
- dev->name, skb->len,
- (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
- }
+ cs89_dbg(3, debug, "%s: sent %d byte packet of type %x\n",
+ dev->name, skb->len,
+ ((skb->data[ETH_ALEN + ETH_ALEN] << 8) |
+ skb->data[ETH_ALEN + ETH_ALEN + 1]));
/* keep the upload from being interrupted, since we
- ask the chip to start transmitting before the
- whole packet has been completely uploaded. */
+ * ask the chip to start transmitting before the
+ * whole packet has been completely uploaded.
+ */
spin_lock_irqsave(&lp->lock, flags);
netif_stop_queue(dev);
/* initiate a transmit sequence */
- writeword(dev->base_addr, TX_CMD_PORT, lp->send_cmd);
- writeword(dev->base_addr, TX_LEN_PORT, skb->len);
+ iowrite16(lp->send_cmd, lp->virt_addr + TX_CMD_PORT);
+ iowrite16(skb->len, lp->virt_addr + TX_LEN_PORT);
/* Test to see if the chip has allocated memory for the packet */
if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
- /*
- * Gasp! It hasn't. But that shouldn't happen since
+ /* Gasp! It hasn't. But that shouldn't happen since
* we're waiting for TxOk, so return 1 and requeue this packet.
*/
spin_unlock_irqrestore(&lp->lock, flags);
- if (net_debug) printk("cs89x0: Tx buffer not free!\n");
+ cs89_dbg(0, err, "Tx buffer not free!\n");
return NETDEV_TX_BUSY;
}
/* Write the contents of the packet */
- writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
+ writewords(lp, TX_FRAME_PORT, skb->data, (skb->len + 1) >> 1);
spin_unlock_irqrestore(&lp->lock, flags);
dev->stats.tx_bytes += skb->len;
- dev_kfree_skb (skb);
+ dev_kfree_skb(skb);
- /*
- * We DO NOT call netif_wake_queue() here.
+ /* We DO NOT call netif_wake_queue() here.
* We also DO NOT call netif_start_queue().
*
* Either of these would cause another bottom half run through
- * net_send_packet() before this packet has fully gone out. That causes
- * us to hit the "Gasp!" above and the send is rescheduled. it runs like
- * a dog. We just return and wait for the Tx completion interrupt handler
- * to restart the netdevice layer
+ * net_send_packet() before this packet has fully gone out.
+ * That causes us to hit the "Gasp!" above and the send is rescheduled.
+ * it runs like a dog. We just return and wait for the Tx completion
+ * interrupt handler to restart the netdevice layer
*/
return NETDEV_TX_OK;
}
-/* The typical workload of the driver:
- Handle the network interface interrupts. */
+static void set_multicast_list(struct net_device *dev)
+{
+ struct net_local *lp = netdev_priv(dev);
+ unsigned long flags;
-static irqreturn_t net_interrupt(int irq, void *dev_id)
+ spin_lock_irqsave(&lp->lock, flags);
+ if (dev->flags & IFF_PROMISC)
+ lp->rx_mode = RX_ALL_ACCEPT;
+ else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev))
+ /* The multicast-accept list is initialized to accept-all,
+ * and we rely on higher-level filtering for now.
+ */
+ lp->rx_mode = RX_MULTCAST_ACCEPT;
+ else
+ lp->rx_mode = 0;
+
+ writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);
+
+ /* in promiscuous mode, we accept errored packets,
+ * so we have to enable interrupts on them also
+ */
+ writereg(dev, PP_RxCFG,
+ (lp->curr_rx_cfg |
+ (lp->rx_mode == RX_ALL_ACCEPT)
+ ? (RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | RX_EXTRA_DATA_ENBL)
+ : 0));
+ spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+static int set_mac_address(struct net_device *dev, void *p)
{
- struct net_device *dev = dev_id;
- struct net_local *lp;
- int ioaddr, status;
- int handled = 0;
+ int i;
+ struct sockaddr *addr = p;
- ioaddr = dev->base_addr;
- lp = netdev_priv(dev);
+ if (netif_running(dev))
+ return -EBUSY;
- /* we MUST read all the events out of the ISQ, otherwise we'll never
- get interrupted again. As a consequence, we can't have any limit
- on the number of times we loop in the interrupt handler. The
- hardware guarantees that eventually we'll run out of events. Of
- course, if you're on a slow machine, and packets are arriving
- faster than you can read them off, you're screwed. Hasta la
- vista, baby! */
- while ((status = readword(dev->base_addr, ISQ_PORT))) {
- if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
- handled = 1;
- switch(status & ISQ_EVENT_MASK) {
- case ISQ_RECEIVER_EVENT:
- /* Got a packet(s). */
- net_rx(dev);
- break;
- case ISQ_TRANSMITTER_EVENT:
- dev->stats.tx_packets++;
- netif_wake_queue(dev); /* Inform upper layers. */
- if ((status & ( TX_OK |
- TX_LOST_CRS |
- TX_SQE_ERROR |
- TX_LATE_COL |
- TX_16_COL)) != TX_OK) {
- if ((status & TX_OK) == 0)
- dev->stats.tx_errors++;
- if (status & TX_LOST_CRS)
- dev->stats.tx_carrier_errors++;
- if (status & TX_SQE_ERROR)
- dev->stats.tx_heartbeat_errors++;
- if (status & TX_LATE_COL)
- dev->stats.tx_window_errors++;
- if (status & TX_16_COL)
- dev->stats.tx_aborted_errors++;
- }
- break;
- case ISQ_BUFFER_EVENT:
- if (status & READY_FOR_TX) {
- /* we tried to transmit a packet earlier,
- but inexplicably ran out of buffers.
- That shouldn't happen since we only ever
- load one packet. Shrug. Do the right
- thing anyway. */
- netif_wake_queue(dev); /* Inform upper layers. */
- }
- if (status & TX_UNDERRUN) {
- if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
- lp->send_underrun++;
- if (lp->send_underrun == 3) lp->send_cmd = TX_AFTER_381;
- else if (lp->send_underrun == 6) lp->send_cmd = TX_AFTER_ALL;
- /* transmit cycle is done, although
- frame wasn't transmitted - this
- avoids having to wait for the upper
- layers to timeout on us, in the
- event of a tx underrun */
- netif_wake_queue(dev); /* Inform upper layers. */
- }
-#if ALLOW_DMA
- if (lp->use_dma && (status & RX_DMA)) {
- int count = readreg(dev, PP_DmaFrameCnt);
- while(count) {
- if (net_debug > 5)
- printk("%s: receiving %d DMA frames\n", dev->name, count);
- if (net_debug > 2 && count >1)
- printk("%s: receiving %d DMA frames\n", dev->name, count);
- dma_rx(dev);
- if (--count == 0)
- count = readreg(dev, PP_DmaFrameCnt);
- if (net_debug > 2 && count > 0)
- printk("%s: continuing with %d DMA frames\n", dev->name, count);
- }
- }
-#endif
- break;
- case ISQ_RX_MISS_EVENT:
- dev->stats.rx_missed_errors += (status >> 6);
- break;
- case ISQ_TX_COL_EVENT:
- dev->stats.collisions += (status >> 6);
- break;
- }
- }
- return IRQ_RETVAL(handled);
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ cs89_dbg(0, debug, "%s: Setting MAC address to %pM\n",
+ dev->name, dev->dev_addr);
+
+ /* set the Ethernet address */
+ for (i = 0; i < ETH_ALEN / 2; i++)
+ writereg(dev, PP_IA + i * 2,
+ (dev->dev_addr[i * 2] |
+ (dev->dev_addr[i * 2 + 1] << 8)));
+
+ return 0;
}
-static void
-count_rx_errors(int status, struct net_device *dev)
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void net_poll_controller(struct net_device *dev)
{
- dev->stats.rx_errors++;
- if (status & RX_RUNT)
- dev->stats.rx_length_errors++;
- if (status & RX_EXTRA_DATA)
- dev->stats.rx_length_errors++;
- if ((status & RX_CRC_ERROR) && !(status & (RX_EXTRA_DATA|RX_RUNT)))
- /* per str 172 */
- dev->stats.rx_crc_errors++;
- if (status & RX_DRIBBLE)
- dev->stats.rx_frame_errors++;
+ disable_irq(dev->irq);
+ net_interrupt(dev->irq, dev);
+ enable_irq(dev->irq);
}
+#endif
-/* We have a good packet(s), get it/them out of the buffers. */
-static void
-net_rx(struct net_device *dev)
+static const struct net_device_ops net_ops = {
+ .ndo_open = net_open,
+ .ndo_stop = net_close,
+ .ndo_tx_timeout = net_timeout,
+ .ndo_start_xmit = net_send_packet,
+ .ndo_get_stats = net_get_stats,
+ .ndo_set_rx_mode = set_multicast_list,
+ .ndo_set_mac_address = set_mac_address,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = net_poll_controller,
+#endif
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
+static void __init reset_chip(struct net_device *dev)
{
- struct sk_buff *skb;
- int status, length;
+#if !defined(CONFIG_MACH_MX31ADS)
+#if !defined(CS89x0_NONISA_IRQ)
+ struct net_local *lp = netdev_priv(dev);
+#endif /* CS89x0_NONISA_IRQ */
+ int reset_start_time;
- int ioaddr = dev->base_addr;
- status = readword(ioaddr, RX_FRAME_PORT);
- length = readword(ioaddr, RX_FRAME_PORT);
+ writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
- if ((status & RX_OK) == 0) {
- count_rx_errors(status, dev);
- return;
+ /* wait 30 ms */
+ msleep(30);
+
+#if !defined(CS89x0_NONISA_IRQ)
+ if (lp->chip_type != CS8900) {
+ /* Hardware problem requires PNP registers to be reconfigured after a reset */
+ iowrite16(PP_CS8920_ISAINT, lp->virt_addr + ADD_PORT);
+ iowrite8(dev->irq, lp->virt_addr + DATA_PORT);
+ iowrite8(0, lp->virt_addr + DATA_PORT + 1);
+
+ iowrite16(PP_CS8920_ISAMemB, lp->virt_addr + ADD_PORT);
+ iowrite8((dev->mem_start >> 16) & 0xff,
+ lp->virt_addr + DATA_PORT);
+ iowrite8((dev->mem_start >> 8) & 0xff,
+ lp->virt_addr + DATA_PORT + 1);
}
+#endif /* CS89x0_NONISA_IRQ */
- /* Malloc up new buffer. */
- skb = netdev_alloc_skb(dev, length + 2);
- if (skb == NULL) {
-#if 0 /* Again, this seems a cruel thing to do */
- printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
+ /* Wait until the chip is reset */
+ reset_start_time = jiffies;
+ while ((readreg(dev, PP_SelfST) & INIT_DONE) == 0 &&
+ jiffies - reset_start_time < 2)
+ ;
+#endif /* !CONFIG_MACH_MX31ADS */
+}
+
+/* This is the real probe routine.
+ * Linux has a history of friendly device probes on the ISA bus.
+ * A good device probes avoids doing writes, and
+ * verifies that the correct device exists and functions.
+ * Return 0 on success.
+ */
+static int __init
+cs89x0_probe1(struct net_device *dev, void __iomem *ioaddr, int modular)
+{
+ struct net_local *lp = netdev_priv(dev);
+ int i;
+ int tmp;
+ unsigned rev_type = 0;
+ int eeprom_buff[CHKSUM_LEN];
+ int retval;
+
+ /* Initialize the device structure. */
+ if (!modular) {
+ memset(lp, 0, sizeof(*lp));
+ spin_lock_init(&lp->lock);
+#ifndef MODULE
+#if ALLOW_DMA
+ if (g_cs89x0_dma) {
+ lp->use_dma = 1;
+ lp->dma = g_cs89x0_dma;
+ lp->dmasize = 16; /* Could make this an option... */
+ }
+#endif
+ lp->force = g_cs89x0_media__force;
#endif
- dev->stats.rx_dropped++;
- return;
}
- skb_reserve(skb, 2); /* longword align L3 header */
- readwords(ioaddr, RX_FRAME_PORT, skb_put(skb, length), length >> 1);
- if (length & 1)
- skb->data[length-1] = readword(ioaddr, RX_FRAME_PORT);
+ pr_debug("PP_addr at %p[%x]: 0x%x\n",
+ ioaddr, ADD_PORT, ioread16(ioaddr + ADD_PORT));
+ iowrite16(PP_ChipID, ioaddr + ADD_PORT);
- if (net_debug > 3) {
- printk( "%s: received %d byte packet of type %x\n",
- dev->name, length,
- (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
+ tmp = ioread16(ioaddr + DATA_PORT);
+ if (tmp != CHIP_EISA_ID_SIG) {
+ pr_debug("%s: incorrect signature at %p[%x]: 0x%x!="
+ CHIP_EISA_ID_SIG_STR "\n",
+ dev->name, ioaddr, DATA_PORT, tmp);
+ retval = -ENODEV;
+ goto out1;
}
- skb->protocol=eth_type_trans(skb,dev);
- netif_rx(skb);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += length;
-}
+ lp->virt_addr = ioaddr;
-#if ALLOW_DMA
-static void release_dma_buff(struct net_local *lp)
-{
- if (lp->dma_buff) {
- free_pages((unsigned long)(lp->dma_buff), get_order(lp->dmasize * 1024));
- lp->dma_buff = NULL;
+ /* get the chip type */
+ rev_type = readreg(dev, PRODUCT_ID_ADD);
+ lp->chip_type = rev_type & ~REVISON_BITS;
+ lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
+
+ /* Check the chip type and revision in order to set the correct
+ * send command. CS8920 revision C and CS8900 revision F can use
+ * the faster send.
+ */
+ lp->send_cmd = TX_AFTER_381;
+ if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
+ lp->send_cmd = TX_NOW;
+ if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
+ lp->send_cmd = TX_NOW;
+
+ pr_info_once("%s\n", version);
+
+ pr_info("%s: cs89%c0%s rev %c found at %p ",
+ dev->name,
+ lp->chip_type == CS8900 ? '0' : '2',
+ lp->chip_type == CS8920M ? "M" : "",
+ lp->chip_revision,
+ lp->virt_addr);
+
+ reset_chip(dev);
+
+ /* Here we read the current configuration of the chip.
+ * If there is no Extended EEPROM then the idea is to not disturb
+ * the chip configuration, it should have been correctly setup by
+ * automatic EEPROM read on reset. So, if the chip says it read
+ * the EEPROM the driver will always do *something* instead of
+ * complain that adapter_cnf is 0.
+ */
+
+ if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) ==
+ (EEPROM_OK | EEPROM_PRESENT)) {
+ /* Load the MAC. */
+ for (i = 0; i < ETH_ALEN / 2; i++) {
+ unsigned int Addr;
+ Addr = readreg(dev, PP_IA + i * 2);
+ dev->dev_addr[i * 2] = Addr & 0xFF;
+ dev->dev_addr[i * 2 + 1] = Addr >> 8;
+ }
+
+ /* Load the Adapter Configuration.
+ * Note: Barring any more specific information from some
+ * other source (ie EEPROM+Schematics), we would not know
+ * how to operate a 10Base2 interface on the AUI port.
+ * However, since we do read the status of HCB1 and use
+ * settings that always result in calls to control_dc_dc(dev,0)
+ * a BNC interface should work if the enable pin
+ * (dc/dc converter) is on HCB1.
+ * It will be called AUI however.
+ */
+
+ lp->adapter_cnf = 0;
+ i = readreg(dev, PP_LineCTL);
+ /* Preserve the setting of the HCB1 pin. */
+ if ((i & (HCB1 | HCB1_ENBL)) == (HCB1 | HCB1_ENBL))
+ lp->adapter_cnf |= A_CNF_DC_DC_POLARITY;
+ /* Save the sqelch bit */
+ if ((i & LOW_RX_SQUELCH) == LOW_RX_SQUELCH)
+ lp->adapter_cnf |= A_CNF_EXTND_10B_2 | A_CNF_LOW_RX_SQUELCH;
+ /* Check if the card is in 10Base-t only mode */
+ if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == 0)
+ lp->adapter_cnf |= A_CNF_10B_T | A_CNF_MEDIA_10B_T;
+ /* Check if the card is in AUI only mode */
+ if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUI_ONLY)
+ lp->adapter_cnf |= A_CNF_AUI | A_CNF_MEDIA_AUI;
+ /* Check if the card is in Auto mode. */
+ if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUTO_AUI_10BASET)
+ lp->adapter_cnf |= A_CNF_AUI | A_CNF_10B_T |
+ A_CNF_MEDIA_AUI | A_CNF_MEDIA_10B_T | A_CNF_MEDIA_AUTO;
+
+ cs89_dbg(1, info, "%s: PP_LineCTL=0x%x, adapter_cnf=0x%x\n",
+ dev->name, i, lp->adapter_cnf);
+
+ /* IRQ. Other chips already probe, see below. */
+ if (lp->chip_type == CS8900)
+ lp->isa_config = readreg(dev, PP_CS8900_ISAINT) & INT_NO_MASK;
+
+ pr_cont("[Cirrus EEPROM] ");
}
-}
-#endif
-/* The inverse routine to net_open(). */
-static int
-net_close(struct net_device *dev)
-{
-#if ALLOW_DMA
- struct net_local *lp = netdev_priv(dev);
-#endif
+ pr_cont("\n");
- netif_stop_queue(dev);
+ /* First check to see if an EEPROM is attached. */
- writereg(dev, PP_RxCFG, 0);
- writereg(dev, PP_TxCFG, 0);
- writereg(dev, PP_BufCFG, 0);
- writereg(dev, PP_BusCTL, 0);
+ if ((readreg(dev, PP_SelfST) & EEPROM_PRESENT) == 0)
+ pr_warn("No EEPROM, relying on command line....\n");
+ else if (get_eeprom_data(dev, START_EEPROM_DATA, CHKSUM_LEN, eeprom_buff) < 0) {
+ pr_warn("EEPROM read failed, relying on command line\n");
+ } else if (get_eeprom_cksum(START_EEPROM_DATA, CHKSUM_LEN, eeprom_buff) < 0) {
+ /* Check if the chip was able to read its own configuration starting
+ at 0 in the EEPROM*/
+ if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) !=
+ (EEPROM_OK | EEPROM_PRESENT))
+ pr_warn("Extended EEPROM checksum bad and no Cirrus EEPROM, relying on command line\n");
- free_irq(dev->irq, dev);
+ } else {
+ /* This reads an extended EEPROM that is not documented
+ * in the CS8900 datasheet.
+ */
-#if ALLOW_DMA
- if (lp->use_dma && lp->dma) {
- free_dma(dev->dma);
- release_dma_buff(lp);
+ /* get transmission control word but keep the autonegotiation bits */
+ if (!lp->auto_neg_cnf)
+ lp->auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET / 2];
+ /* Store adapter configuration */
+ if (!lp->adapter_cnf)
+ lp->adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET / 2];
+ /* Store ISA configuration */
+ lp->isa_config = eeprom_buff[ISA_CNF_OFFSET / 2];
+ dev->mem_start = eeprom_buff[PACKET_PAGE_OFFSET / 2] << 8;
+
+ /* eeprom_buff has 32-bit ints, so we can't just memcpy it */
+ /* store the initial memory base address */
+ for (i = 0; i < ETH_ALEN / 2; i++) {
+ dev->dev_addr[i * 2] = eeprom_buff[i];
+ dev->dev_addr[i * 2 + 1] = eeprom_buff[i] >> 8;
+ }
+ cs89_dbg(1, debug, "%s: new adapter_cnf: 0x%x\n",
+ dev->name, lp->adapter_cnf);
}
+
+ /* allow them to force multiple transceivers. If they force multiple, autosense */
+ {
+ int count = 0;
+ if (lp->force & FORCE_RJ45) {
+ lp->adapter_cnf |= A_CNF_10B_T;
+ count++;
+ }
+ if (lp->force & FORCE_AUI) {
+ lp->adapter_cnf |= A_CNF_AUI;
+ count++;
+ }
+ if (lp->force & FORCE_BNC) {
+ lp->adapter_cnf |= A_CNF_10B_2;
+ count++;
+ }
+ if (count > 1)
+ lp->adapter_cnf |= A_CNF_MEDIA_AUTO;
+ else if (lp->force & FORCE_RJ45)
+ lp->adapter_cnf |= A_CNF_MEDIA_10B_T;
+ else if (lp->force & FORCE_AUI)
+ lp->adapter_cnf |= A_CNF_MEDIA_AUI;
+ else if (lp->force & FORCE_BNC)
+ lp->adapter_cnf |= A_CNF_MEDIA_10B_2;
+ }
+
+ cs89_dbg(1, debug, "%s: after force 0x%x, adapter_cnf=0x%x\n",
+ dev->name, lp->force, lp->adapter_cnf);
+
+ /* FIXME: We don't let you set dc-dc polarity or low RX squelch from the command line: add it here */
+
+ /* FIXME: We don't let you set the IMM bit from the command line: add it to lp->auto_neg_cnf here */
+
+ /* FIXME: we don't set the Ethernet address on the command line. Use
+ * ifconfig IFACE hw ether AABBCCDDEEFF
+ */
+
+ pr_info("media %s%s%s",
+ (lp->adapter_cnf & A_CNF_10B_T) ? "RJ-45," : "",
+ (lp->adapter_cnf & A_CNF_AUI) ? "AUI," : "",
+ (lp->adapter_cnf & A_CNF_10B_2) ? "BNC," : "");
+
+ lp->irq_map = 0xffff;
+
+ /* If this is a CS8900 then no pnp soft */
+ if (lp->chip_type != CS8900 &&
+ /* Check if the ISA IRQ has been set */
+ (i = readreg(dev, PP_CS8920_ISAINT) & 0xff,
+ (i != 0 && i < CS8920_NO_INTS))) {
+ if (!dev->irq)
+ dev->irq = i;
+ } else {
+ i = lp->isa_config & INT_NO_MASK;
+#ifndef CONFIG_CS89x0_PLATFORM
+ if (lp->chip_type == CS8900) {
+#ifdef CS89x0_NONISA_IRQ
+ i = cs8900_irq_map[0];
+#else
+ /* Translate the IRQ using the IRQ mapping table. */
+ if (i >= ARRAY_SIZE(cs8900_irq_map))
+ pr_err("invalid ISA interrupt number %d\n", i);
+ else
+ i = cs8900_irq_map[i];
+
+ lp->irq_map = CS8900_IRQ_MAP; /* fixed IRQ map for CS8900 */
+ } else {
+ int irq_map_buff[IRQ_MAP_LEN/2];
+
+ if (get_eeprom_data(dev, IRQ_MAP_EEPROM_DATA,
+ IRQ_MAP_LEN / 2,
+ irq_map_buff) >= 0) {
+ if ((irq_map_buff[0] & 0xff) == PNP_IRQ_FRMT)
+ lp->irq_map = ((irq_map_buff[0] >> 8) |
+ (irq_map_buff[1] << 8));
+ }
#endif
+ }
+#endif
+ if (!dev->irq)
+ dev->irq = i;
+ }
- /* Update the statistics here. */
- return 0;
-}
+ pr_cont(" IRQ %d", dev->irq);
-/* Get the current statistics. This may be called with the card open or
- closed. */
-static struct net_device_stats *
-net_get_stats(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- unsigned long flags;
+#if ALLOW_DMA
+ if (lp->use_dma) {
+ get_dma_channel(dev);
+ pr_cont(", DMA %d", dev->dma);
+ } else
+#endif
+ pr_cont(", programmed I/O");
- spin_lock_irqsave(&lp->lock, flags);
- /* Update the statistics from the device registers. */
- dev->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
- dev->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
- spin_unlock_irqrestore(&lp->lock, flags);
+ /* print the ethernet address. */
+ pr_cont(", MAC %pM\n", dev->dev_addr);
- return &dev->stats;
+ dev->netdev_ops = &net_ops;
+ dev->watchdog_timeo = HZ;
+
+ cs89_dbg(0, info, "cs89x0_probe1() successful\n");
+
+ retval = register_netdev(dev);
+ if (retval)
+ goto out2;
+ return 0;
+out2:
+ iowrite16(PP_ChipID, lp->virt_addr + ADD_PORT);
+out1:
+ return retval;
}
-static void set_multicast_list(struct net_device *dev)
+#ifndef CONFIG_CS89x0_PLATFORM
+/*
+ * This function converts the I/O port addres used by the cs89x0_probe() and
+ * init_module() functions to the I/O memory address used by the
+ * cs89x0_probe1() function.
+ */
+static int __init
+cs89x0_ioport_probe(struct net_device *dev, unsigned long ioport, int modular)
{
struct net_local *lp = netdev_priv(dev);
- unsigned long flags;
+ int ret;
+ void __iomem *io_mem;
- spin_lock_irqsave(&lp->lock, flags);
- if(dev->flags&IFF_PROMISC)
- {
- lp->rx_mode = RX_ALL_ACCEPT;
+ if (!lp)
+ return -ENOMEM;
+
+ dev->base_addr = ioport;
+
+ if (!request_region(ioport, NETCARD_IO_EXTENT, DRV_NAME)) {
+ ret = -EBUSY;
+ goto out;
}
- else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev))
- {
- /* The multicast-accept list is initialized to accept-all, and we
- rely on higher-level filtering for now. */
- lp->rx_mode = RX_MULTCAST_ACCEPT;
+
+ io_mem = ioport_map(ioport & ~3, NETCARD_IO_EXTENT);
+ if (!io_mem) {
+ ret = -ENOMEM;
+ goto release;
}
- else
- lp->rx_mode = 0;
- writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);
+ /* if they give us an odd I/O address, then do ONE write to
+ * the address port, to get it back to address zero, where we
+ * expect to find the EISA signature word. An IO with a base of 0x3
+ * will skip the test for the ADD_PORT.
+ */
+ if (ioport & 1) {
+ cs89_dbg(1, info, "%s: odd ioaddr 0x%lx\n", dev->name, ioport);
+ if ((ioport & 2) != 2) {
+ if ((ioread16(io_mem + ADD_PORT) & ADD_MASK) !=
+ ADD_SIG) {
+ pr_err("%s: bad signature 0x%x\n",
+ dev->name, ioread16(io_mem + ADD_PORT));
+ ret = -ENODEV;
+ goto unmap;
+ }
+ }
+ }
- /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */
- writereg(dev, PP_RxCFG, lp->curr_rx_cfg |
- (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0));
- spin_unlock_irqrestore(&lp->lock, flags);
+ ret = cs89x0_probe1(dev, io_mem, modular);
+ if (!ret)
+ goto out;
+unmap:
+ ioport_unmap(io_mem);
+release:
+ release_region(ioport, NETCARD_IO_EXTENT);
+out:
+ return ret;
}
+#ifndef MODULE
+/* Check for a network adaptor of this type, and return '0' iff one exists.
+ * If dev->base_addr == 0, probe all likely locations.
+ * If dev->base_addr == 1, always return failure.
+ * If dev->base_addr == 2, allocate space for the device and return success
+ * (detachable devices only).
+ * Return 0 on success.
+ */
-static int set_mac_address(struct net_device *dev, void *p)
+struct net_device * __init cs89x0_probe(int unit)
{
- int i;
- struct sockaddr *addr = p;
-
- if (netif_running(dev))
- return -EBUSY;
+ struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
+ unsigned *port;
+ int err = 0;
+ int irq;
+ int io;
- memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+ if (!dev)
+ return ERR_PTR(-ENODEV);
- if (net_debug)
- printk("%s: Setting MAC address to %pM.\n",
- dev->name, dev->dev_addr);
+ sprintf(dev->name, "eth%d", unit);
+ netdev_boot_setup_check(dev);
+ io = dev->base_addr;
+ irq = dev->irq;
- /* set the Ethernet address */
- for (i=0; i < ETH_ALEN/2; i++)
- writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
+ cs89_dbg(0, info, "cs89x0_probe(0x%x)\n", io);
- return 0;
+ if (io > 0x1ff) { /* Check a single specified location. */
+ err = cs89x0_ioport_probe(dev, io, 0);
+ } else if (io != 0) { /* Don't probe at all. */
+ err = -ENXIO;
+ } else {
+ for (port = netcard_portlist; *port; port++) {
+ if (cs89x0_ioport_probe(dev, *port, 0) == 0)
+ break;
+ dev->irq = irq;
+ }
+ if (!*port)
+ err = -ENODEV;
+ }
+ if (err)
+ goto out;
+ return dev;
+out:
+ free_netdev(dev);
+ pr_warn("no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n");
+ return ERR_PTR(err);
}
+#endif
+#endif
#if defined(MODULE) && !defined(CONFIG_CS89x0_PLATFORM)
static struct net_device *dev_cs89x0;
-/*
- * Support the 'debug' module parm even if we're compiled for non-debug to
+/* Support the 'debug' module parm even if we're compiled for non-debug to
* avoid breaking someone's startup scripts
*/
@@ -1764,11 +1755,11 @@ static int io;
static int irq;
static int debug;
static char media[8];
-static int duplex=-1;
+static int duplex = -1;
static int use_dma; /* These generate unused var warnings if ALLOW_DMA = 0 */
static int dma;
-static int dmasize=16; /* or 64 */
+static int dmasize = 16; /* or 64 */
module_param(io, int, 0);
module_param(irq, int, 0);
@@ -1801,32 +1792,28 @@ MODULE_PARM_DESC(use_dma , "(ignored)");
MODULE_AUTHOR("Mike Cruse, Russwll Nelson <nelson@crynwr.com>, Andrew Morton");
MODULE_LICENSE("GPL");
-
/*
-* media=t - specify media type
- or media=2
- or media=aui
- or medai=auto
-* duplex=0 - specify forced half/full/autonegotiate duplex
-* debug=# - debug level
-
-
-* Default Chip Configuration:
- * DMA Burst = enabled
- * IOCHRDY Enabled = enabled
- * UseSA = enabled
- * CS8900 defaults to half-duplex if not specified on command-line
- * CS8920 defaults to autoneg if not specified on command-line
- * Use reset defaults for other config parameters
-
-* Assumptions:
- * media type specified is supported (circuitry is present)
- * if memory address is > 1MB, then required mem decode hw is present
- * if 10B-2, then agent other than driver will enable DC/DC converter
- (hw or software util)
-
-
-*/
+ * media=t - specify media type
+ * or media=2
+ * or media=aui
+ * or medai=auto
+ * duplex=0 - specify forced half/full/autonegotiate duplex
+ * debug=# - debug level
+ *
+ * Default Chip Configuration:
+ * DMA Burst = enabled
+ * IOCHRDY Enabled = enabled
+ * UseSA = enabled
+ * CS8900 defaults to half-duplex if not specified on command-line
+ * CS8920 defaults to autoneg if not specified on command-line
+ * Use reset defaults for other config parameters
+ *
+ * Assumptions:
+ * media type specified is supported (circuitry is present)
+ * if memory address is > 1MB, then required mem decode hw is present
+ * if 10B-2, then agent other than driver will enable DC/DC converter
+ * (hw or software util)
+ */
int __init init_module(void)
{
@@ -1856,8 +1843,8 @@ int __init init_module(void)
spin_lock_init(&lp->lock);
- /* boy, they'd better get these right */
- if (!strcmp(media, "rj45"))
+ /* boy, they'd better get these right */
+ if (!strcmp(media, "rj45"))
lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T;
else if (!strcmp(media, "aui"))
lp->adapter_cnf = A_CNF_MEDIA_AUI | A_CNF_AUI;
@@ -1866,27 +1853,28 @@ int __init init_module(void)
else
lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T;
- if (duplex==-1)
+ if (duplex == -1)
lp->auto_neg_cnf = AUTO_NEG_ENABLE;
- if (io == 0) {
- printk(KERN_ERR "cs89x0.c: Module autoprobing not allowed.\n");
- printk(KERN_ERR "cs89x0.c: Append io=0xNNN\n");
- ret = -EPERM;
+ if (io == 0) {
+ pr_err("Module autoprobing not allowed\n");
+ pr_err("Append io=0xNNN\n");
+ ret = -EPERM;
goto out;
- } else if (io <= 0x1ff) {
+ } else if (io <= 0x1ff) {
ret = -ENXIO;
goto out;
}
#if ALLOW_DMA
if (use_dma && dmasize != 16 && dmasize != 64) {
- printk(KERN_ERR "cs89x0.c: dma size must be either 16K or 64K, not %dK\n", dmasize);
+ pr_err("dma size must be either 16K or 64K, not %dK\n",
+ dmasize);
ret = -EPERM;
goto out;
}
#endif
- ret = cs89x0_probe1(dev, io, 1);
+ ret = cs89x0_ioport_probe(dev, io, 1);
if (ret)
goto out;
@@ -1900,8 +1888,11 @@ out:
void __exit
cleanup_module(void)
{
+ struct net_local *lp = netdev_priv(dev_cs89x0);
+
unregister_netdev(dev_cs89x0);
- writeword(dev_cs89x0->base_addr, ADD_PORT, PP_ChipID);
+ iowrite16(PP_ChipID, lp->virt_addr + ADD_PORT);
+ ioport_unmap(lp->virt_addr);
release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
free_netdev(dev_cs89x0);
}
@@ -1913,6 +1904,7 @@ static int __init cs89x0_platform_probe(struct platform_device *pdev)
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
struct net_local *lp;
struct resource *mem_res;
+ void __iomem *virt_addr;
int err;
if (!dev)
@@ -1923,29 +1915,28 @@ static int __init cs89x0_platform_probe(struct platform_device *pdev)
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->irq = platform_get_irq(pdev, 0);
if (mem_res == NULL || dev->irq <= 0) {
- dev_warn(&dev->dev, "memory/interrupt resource missing.\n");
+ dev_warn(&dev->dev, "memory/interrupt resource missing\n");
err = -ENXIO;
goto free;
}
- lp->phys_addr = mem_res->start;
lp->size = resource_size(mem_res);
- if (!request_mem_region(lp->phys_addr, lp->size, DRV_NAME)) {
- dev_warn(&dev->dev, "request_mem_region() failed.\n");
+ if (!request_mem_region(mem_res->start, lp->size, DRV_NAME)) {
+ dev_warn(&dev->dev, "request_mem_region() failed\n");
err = -EBUSY;
goto free;
}
- lp->virt_addr = ioremap(lp->phys_addr, lp->size);
- if (!lp->virt_addr) {
- dev_warn(&dev->dev, "ioremap() failed.\n");
+ virt_addr = ioremap(mem_res->start, lp->size);
+ if (!virt_addr) {
+ dev_warn(&dev->dev, "ioremap() failed\n");
err = -ENOMEM;
goto release;
}
- err = cs89x0_probe1(dev, (unsigned long)lp->virt_addr, 0);
+ err = cs89x0_probe1(dev, virt_addr, 0);
if (err) {
- dev_warn(&dev->dev, "no cs8900 or cs8920 detected.\n");
+ dev_warn(&dev->dev, "no cs8900 or cs8920 detected\n");
goto unmap;
}
@@ -1953,9 +1944,9 @@ static int __init cs89x0_platform_probe(struct platform_device *pdev)
return 0;
unmap:
- iounmap(lp->virt_addr);
+ iounmap(virt_addr);
release:
- release_mem_region(lp->phys_addr, lp->size);
+ release_mem_region(mem_res->start, lp->size);
free:
free_netdev(dev);
return err;
@@ -1965,10 +1956,16 @@ static int cs89x0_platform_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct net_local *lp = netdev_priv(dev);
+ struct resource *mem_res;
+ /* This platform_get_resource() call will not return NULL, because
+ * the same call in cs89x0_platform_probe() has returned a non NULL
+ * value.
+ */
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
unregister_netdev(dev);
iounmap(lp->virt_addr);
- release_mem_region(lp->phys_addr, lp->size);
+ release_mem_region(mem_res->start, lp->size);
free_netdev(dev);
return 0;
}
@@ -1996,13 +1993,3 @@ static void __exit cs89x0_cleanup(void)
module_exit(cs89x0_cleanup);
#endif /* CONFIG_CS89x0_PLATFORM */
-
-/*
- * Local variables:
- * version-control: t
- * kept-new-versions: 5
- * c-indent-level: 8
- * tab-width: 8
- * End:
- *
- */
diff --git a/drivers/net/ethernet/emulex/benet/Makefile b/drivers/net/ethernet/emulex/benet/Makefile
index a60cd8051135..1a91b276940d 100644
--- a/drivers/net/ethernet/emulex/benet/Makefile
+++ b/drivers/net/ethernet/emulex/benet/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_BE2NET) += be2net.o
-be2net-y := be_main.o be_cmds.o be_ethtool.o
+be2net-y := be_main.o be_cmds.o be_ethtool.o be_roce.o
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index ecf1a81f26e2..c5c4c0e83bd1 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -32,6 +32,7 @@
#include <linux/u64_stats_sync.h>
#include "be_hw.h"
+#include "be_roce.h"
#define DRV_VER "4.2.220u"
#define DRV_NAME "be2net"
@@ -102,7 +103,8 @@ static inline char *nic_name(struct pci_dev *pdev)
#define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */
#define MAX_TX_QS 8
-#define MAX_MSIX_VECTORS MAX_RSS_QS
+#define MAX_ROCE_EQS 5
+#define MAX_MSIX_VECTORS (MAX_RSS_QS + MAX_ROCE_EQS) /* RSS qs + RoCE */
#define BE_TX_BUDGET 256
#define BE_NAPI_WEIGHT 64
#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */
@@ -405,6 +407,17 @@ struct be_adapter {
u32 tx_fc; /* Tx flow control */
bool stats_cmd_sent;
u8 generation; /* BladeEngine ASIC generation */
+ u32 if_type;
+ struct {
+ u8 __iomem *base; /* Door Bell */
+ u32 size;
+ u32 total_size;
+ u64 io_addr;
+ } roce_db;
+ u32 num_msix_roce_vec;
+ struct ocrdma_dev *ocrdma_dev;
+ struct list_head entry;
+
u32 flash_status;
struct completion flash_compl;
@@ -421,6 +434,7 @@ struct be_adapter {
bool wol;
u32 max_pmac_cnt; /* Max secondary UC MACs programmable */
u32 uc_macs; /* Count of secondary UC MAC programmed */
+ u32 msg_enable;
};
#define be_physfn(adapter) (!adapter->virtfn)
@@ -440,6 +454,10 @@ struct be_adapter {
#define lancer_chip(adapter) ((adapter->pdev->device == OC_DEVICE_ID3) || \
(adapter->pdev->device == OC_DEVICE_ID4))
+#define be_roce_supported(adapter) ((adapter->if_type == SLI_INTF_TYPE_3 || \
+ adapter->sli_family == SKYHAWK_SLI_FAMILY) && \
+ (adapter->function_mode & RDMA_ENABLED))
+
extern const struct ethtool_ops be_ethtool_ops;
#define msix_enabled(adapter) (adapter->num_msix_vec > 0)
@@ -596,6 +614,12 @@ static inline bool be_is_wol_excluded(struct be_adapter *adapter)
}
}
+static inline bool be_type_2_3(struct be_adapter *adapter)
+{
+ return (adapter->if_type == SLI_INTF_TYPE_2 ||
+ adapter->if_type == SLI_INTF_TYPE_3) ? true : false;
+}
+
extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
u16 num_popped);
extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
@@ -603,4 +627,18 @@ extern void be_parse_stats(struct be_adapter *adapter);
extern int be_load_fw(struct be_adapter *adapter, u8 *func);
extern bool be_is_wol_supported(struct be_adapter *adapter);
extern bool be_pause_supported(struct be_adapter *adapter);
+extern u32 be_get_fw_log_level(struct be_adapter *adapter);
+
+/*
+ * internal function to initialize-cleanup roce device.
+ */
+extern void be_roce_dev_add(struct be_adapter *);
+extern void be_roce_dev_remove(struct be_adapter *);
+
+/*
+ * internal function to open-close roce device during ifup-ifdown.
+ */
+extern void be_roce_dev_open(struct be_adapter *);
+extern void be_roce_dev_close(struct be_adapter *);
+
#endif /* BE_H */
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 43167e863955..8d06ea381741 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -15,6 +15,7 @@
* Costa Mesa, CA 92626
*/
+#include <linux/module.h>
#include "be.h"
#include "be_cmds.h"
@@ -2589,4 +2590,98 @@ err:
mutex_unlock(&adapter->mbox_lock);
pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
return status;
+
+}
+int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_get_ext_fat_caps *req;
+ int status;
+
+ if (mutex_lock_interruptible(&adapter->mbox_lock))
+ return -1;
+
+ wrb = wrb_from_mbox(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+
+ req = cmd->va;
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_EXT_FAT_CAPABILITES,
+ cmd->size, wrb, cmd);
+ req->parameter_type = cpu_to_le32(1);
+
+ status = be_mbox_notify_wait(adapter);
+err:
+ mutex_unlock(&adapter->mbox_lock);
+ return status;
+}
+
+int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd,
+ struct be_fat_conf_params *configs)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_set_ext_fat_caps *req;
+ int status;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+
+ req = cmd->va;
+ memcpy(&req->set_params, configs, sizeof(struct be_fat_conf_params));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_SET_EXT_FAT_CAPABILITES,
+ cmd->size, wrb, cmd);
+
+ status = be_mcc_notify_wait(adapter);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ return status;
+}
+
+int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
+ int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
+{
+ struct be_adapter *adapter = netdev_priv(netdev_handle);
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *) wrb_payload;
+ struct be_cmd_req_hdr *req;
+ struct be_cmd_resp_hdr *resp;
+ int status;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+ req = embedded_payload(wrb);
+ resp = embedded_payload(wrb);
+
+ be_wrb_cmd_hdr_prepare(req, hdr->subsystem,
+ hdr->opcode, wrb_payload_size, wrb, NULL);
+ memcpy(req, wrb_payload, wrb_payload_size);
+ be_dws_cpu_to_le(req, wrb_payload_size);
+
+ status = be_mcc_notify_wait(adapter);
+ if (cmd_status)
+ *cmd_status = (status & 0xffff);
+ if (ext_status)
+ *ext_status = 0;
+ memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length);
+ be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ return status;
}
+EXPORT_SYMBOL(be_roce_mcc_cmd);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 944f031bd31e..9625bf420c16 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -189,6 +189,8 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_GET_PHY_DETAILS 102
#define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103
#define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121
+#define OPCODE_COMMON_GET_EXT_FAT_CAPABILITES 125
+#define OPCODE_COMMON_SET_EXT_FAT_CAPABILITES 126
#define OPCODE_COMMON_GET_MAC_LIST 147
#define OPCODE_COMMON_SET_MAC_LIST 148
#define OPCODE_COMMON_GET_HSW_CONFIG 152
@@ -1060,6 +1062,7 @@ struct be_cmd_resp_modify_eq_delay {
/* The HW can come up in either of the following multi-channel modes
* based on the skew/IPL.
*/
+#define RDMA_ENABLED 0x4
#define FLEX10_MODE 0x400
#define VNIC_MODE 0x20000
#define UMC_ENABLED 0x1000000
@@ -1602,6 +1605,56 @@ static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter)
}
}
+
+/************** get fat capabilites *******************/
+#define MAX_MODULES 27
+#define MAX_MODES 4
+#define MODE_UART 0
+#define FW_LOG_LEVEL_DEFAULT 48
+#define FW_LOG_LEVEL_FATAL 64
+
+struct ext_fat_mode {
+ u8 mode;
+ u8 rsvd0;
+ u16 port_mask;
+ u32 dbg_lvl;
+ u64 fun_mask;
+} __packed;
+
+struct ext_fat_modules {
+ u8 modules_str[32];
+ u32 modules_id;
+ u32 num_modes;
+ struct ext_fat_mode trace_lvl[MAX_MODES];
+} __packed;
+
+struct be_fat_conf_params {
+ u32 max_log_entries;
+ u32 log_entry_size;
+ u8 log_type;
+ u8 max_log_funs;
+ u8 max_log_ports;
+ u8 rsvd0;
+ u32 supp_modes;
+ u32 num_modules;
+ struct ext_fat_modules module[MAX_MODULES];
+} __packed;
+
+struct be_cmd_req_get_ext_fat_caps {
+ struct be_cmd_req_hdr hdr;
+ u32 parameter_type;
+};
+
+struct be_cmd_resp_get_ext_fat_caps {
+ struct be_cmd_resp_hdr hdr;
+ struct be_fat_conf_params get_params;
+};
+
+struct be_cmd_req_set_ext_fat_caps {
+ struct be_cmd_req_hdr hdr;
+ struct be_fat_conf_params set_params;
+};
+
extern int be_pci_fnum_get(struct be_adapter *adapter);
extern int be_cmd_POST(struct be_adapter *adapter);
extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
@@ -1707,4 +1760,9 @@ extern int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
extern int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
u32 domain, u16 intf_id);
extern int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter);
+extern int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd);
+extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd,
+ struct be_fat_conf_params *cfgs);
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index 747f68fa976d..63e51d476900 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -878,6 +878,81 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
return status;
}
+static u32 be_get_msg_level(struct net_device *netdev)
+{
+ struct be_adapter *adapter = netdev_priv(netdev);
+
+ if (lancer_chip(adapter)) {
+ dev_err(&adapter->pdev->dev, "Operation not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ return adapter->msg_enable;
+}
+
+static void be_set_fw_log_level(struct be_adapter *adapter, u32 level)
+{
+ struct be_dma_mem extfat_cmd;
+ struct be_fat_conf_params *cfgs;
+ int status;
+ int i, j;
+
+ memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
+ extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
+ extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
+ &extfat_cmd.dma);
+ if (!extfat_cmd.va) {
+ dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
+ __func__);
+ goto err;
+ }
+ status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
+ if (!status) {
+ cfgs = (struct be_fat_conf_params *)(extfat_cmd.va +
+ sizeof(struct be_cmd_resp_hdr));
+ for (i = 0; i < cfgs->num_modules; i++) {
+ for (j = 0; j < cfgs->module[i].num_modes; j++) {
+ if (cfgs->module[i].trace_lvl[j].mode ==
+ MODE_UART)
+ cfgs->module[i].trace_lvl[j].dbg_lvl =
+ cpu_to_le32(level);
+ }
+ }
+ status = be_cmd_set_ext_fat_capabilites(adapter, &extfat_cmd,
+ cfgs);
+ if (status)
+ dev_err(&adapter->pdev->dev,
+ "Message level set failed\n");
+ } else {
+ dev_err(&adapter->pdev->dev, "Message level get failed\n");
+ }
+
+ pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va,
+ extfat_cmd.dma);
+err:
+ return;
+}
+
+static void be_set_msg_level(struct net_device *netdev, u32 level)
+{
+ struct be_adapter *adapter = netdev_priv(netdev);
+
+ if (lancer_chip(adapter)) {
+ dev_err(&adapter->pdev->dev, "Operation not supported\n");
+ return;
+ }
+
+ if (adapter->msg_enable == level)
+ return;
+
+ if ((level & NETIF_MSG_HW) != (adapter->msg_enable & NETIF_MSG_HW))
+ be_set_fw_log_level(adapter, level & NETIF_MSG_HW ?
+ FW_LOG_LEVEL_DEFAULT : FW_LOG_LEVEL_FATAL);
+ adapter->msg_enable = level;
+
+ return;
+}
+
const struct ethtool_ops be_ethtool_ops = {
.get_settings = be_get_settings,
.get_drvinfo = be_get_drvinfo,
@@ -893,6 +968,8 @@ const struct ethtool_ops be_ethtool_ops = {
.set_pauseparam = be_set_pauseparam,
.get_strings = be_get_stat_strings,
.set_phys_id = be_set_phys_id,
+ .get_msglevel = be_get_msg_level,
+ .set_msglevel = be_set_msg_level,
.get_sset_count = be_get_sset_count,
.get_ethtool_stats = be_get_ethtool_stats,
.get_regs_len = be_get_reg_len,
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index f38b58c8dbba..d9fb0c501fa1 100644
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -100,11 +100,13 @@
#define SLI_INTF_REV_SHIFT 4
#define SLI_INTF_FT_MASK 0x00000001
+#define SLI_INTF_TYPE_2 2
+#define SLI_INTF_TYPE_3 3
/* SLI family */
#define BE_SLI_FAMILY 0x0
#define LANCER_A0_SLI_FAMILY 0xA
-
+#define SKYHAWK_SLI_FAMILY 0x2
/********* ISR0 Register offset **********/
#define CEV_ISR0_OFFSET 0xC18
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index a01f73467532..08efd308d78a 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -2151,10 +2151,17 @@ static uint be_num_rss_want(struct be_adapter *adapter)
static void be_msix_enable(struct be_adapter *adapter)
{
#define BE_MIN_MSIX_VECTORS 1
- int i, status, num_vec;
+ int i, status, num_vec, num_roce_vec = 0;
/* If RSS queues are not used, need a vec for default RX Q */
num_vec = min(be_num_rss_want(adapter), num_online_cpus());
+ if (be_roce_supported(adapter)) {
+ num_roce_vec = min_t(u32, MAX_ROCE_MSIX_VECTORS,
+ (num_online_cpus() + 1));
+ num_roce_vec = min(num_roce_vec, MAX_ROCE_EQS);
+ num_vec += num_roce_vec;
+ num_vec = min(num_vec, MAX_MSIX_VECTORS);
+ }
num_vec = max(num_vec, BE_MIN_MSIX_VECTORS);
for (i = 0; i < num_vec; i++)
@@ -2171,7 +2178,17 @@ static void be_msix_enable(struct be_adapter *adapter)
}
return;
done:
- adapter->num_msix_vec = num_vec;
+ if (be_roce_supported(adapter)) {
+ if (num_vec > num_roce_vec) {
+ adapter->num_msix_vec = num_vec - num_roce_vec;
+ adapter->num_msix_roce_vec =
+ num_vec - adapter->num_msix_vec;
+ } else {
+ adapter->num_msix_vec = num_vec;
+ adapter->num_msix_roce_vec = 0;
+ }
+ } else
+ adapter->num_msix_vec = num_vec;
return;
}
@@ -2283,6 +2300,8 @@ static int be_close(struct net_device *netdev)
struct be_eq_obj *eqo;
int i;
+ be_roce_dev_close(adapter);
+
be_async_mcc_disable(adapter);
if (!lancer_chip(adapter))
@@ -2391,6 +2410,7 @@ static int be_open(struct net_device *netdev)
if (!status)
be_link_status_update(adapter, link_status);
+ be_roce_dev_open(adapter);
return 0;
err:
be_close(adapter->netdev);
@@ -3232,6 +3252,24 @@ static void be_unmap_pci_bars(struct be_adapter *adapter)
iounmap(adapter->csr);
if (adapter->db)
iounmap(adapter->db);
+ if (adapter->roce_db.base)
+ pci_iounmap(adapter->pdev, adapter->roce_db.base);
+}
+
+static int lancer_roce_map_pci_bars(struct be_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ u8 __iomem *addr;
+
+ addr = pci_iomap(pdev, 2, 0);
+ if (addr == NULL)
+ return -ENOMEM;
+
+ adapter->roce_db.base = addr;
+ adapter->roce_db.io_addr = pci_resource_start(pdev, 2);
+ adapter->roce_db.size = 8192;
+ adapter->roce_db.total_size = pci_resource_len(pdev, 2);
+ return 0;
}
static int be_map_pci_bars(struct be_adapter *adapter)
@@ -3240,11 +3278,18 @@ static int be_map_pci_bars(struct be_adapter *adapter)
int db_reg;
if (lancer_chip(adapter)) {
- addr = ioremap_nocache(pci_resource_start(adapter->pdev, 0),
- pci_resource_len(adapter->pdev, 0));
- if (addr == NULL)
- return -ENOMEM;
- adapter->db = addr;
+ if (be_type_2_3(adapter)) {
+ addr = ioremap_nocache(
+ pci_resource_start(adapter->pdev, 0),
+ pci_resource_len(adapter->pdev, 0));
+ if (addr == NULL)
+ return -ENOMEM;
+ adapter->db = addr;
+ }
+ if (adapter->if_type == SLI_INTF_TYPE_3) {
+ if (lancer_roce_map_pci_bars(adapter))
+ goto pci_map_err;
+ }
return 0;
}
@@ -3269,14 +3314,19 @@ static int be_map_pci_bars(struct be_adapter *adapter)
if (addr == NULL)
goto pci_map_err;
adapter->db = addr;
-
+ if (adapter->sli_family == SKYHAWK_SLI_FAMILY) {
+ adapter->roce_db.size = 4096;
+ adapter->roce_db.io_addr =
+ pci_resource_start(adapter->pdev, db_reg);
+ adapter->roce_db.total_size =
+ pci_resource_len(adapter->pdev, db_reg);
+ }
return 0;
pci_map_err:
be_unmap_pci_bars(adapter);
return -ENOMEM;
}
-
static void be_ctrl_cleanup(struct be_adapter *adapter)
{
struct be_dma_mem *mem = &adapter->mbox_mem_alloced;
@@ -3382,6 +3432,8 @@ static void __devexit be_remove(struct pci_dev *pdev)
if (!adapter)
return;
+ be_roce_dev_remove(adapter);
+
unregister_netdev(adapter->netdev);
be_clear(adapter);
@@ -3403,9 +3455,43 @@ bool be_is_wol_supported(struct be_adapter *adapter)
!be_is_wol_excluded(adapter)) ? true : false;
}
+u32 be_get_fw_log_level(struct be_adapter *adapter)
+{
+ struct be_dma_mem extfat_cmd;
+ struct be_fat_conf_params *cfgs;
+ int status;
+ u32 level = 0;
+ int j;
+
+ memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
+ extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
+ extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
+ &extfat_cmd.dma);
+
+ if (!extfat_cmd.va) {
+ dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
+ __func__);
+ goto err;
+ }
+
+ status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
+ if (!status) {
+ cfgs = (struct be_fat_conf_params *)(extfat_cmd.va +
+ sizeof(struct be_cmd_resp_hdr));
+ for (j = 0; j < cfgs->module[0].num_modes; j++) {
+ if (cfgs->module[0].trace_lvl[j].mode == MODE_UART)
+ level = cfgs->module[0].trace_lvl[j].dbg_lvl;
+ }
+ }
+ pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va,
+ extfat_cmd.dma);
+err:
+ return level;
+}
static int be_get_initial_config(struct be_adapter *adapter)
{
int status;
+ u32 level;
status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
&adapter->function_mode, &adapter->function_caps);
@@ -3443,6 +3529,9 @@ static int be_get_initial_config(struct be_adapter *adapter)
if (be_is_wol_supported(adapter))
adapter->wol = true;
+ level = be_get_fw_log_level(adapter);
+ adapter->msg_enable = level <= FW_LOG_LEVEL_DEFAULT ? NETIF_MSG_HW : 0;
+
return 0;
}
@@ -3458,17 +3547,27 @@ static int be_dev_type_check(struct be_adapter *adapter)
break;
case BE_DEVICE_ID2:
case OC_DEVICE_ID2:
- case OC_DEVICE_ID5:
adapter->generation = BE_GEN3;
break;
case OC_DEVICE_ID3:
case OC_DEVICE_ID4:
pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+ adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
+ SLI_INTF_IF_TYPE_SHIFT;
if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
SLI_INTF_IF_TYPE_SHIFT;
-
if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) ||
- if_type != 0x02) {
+ !be_type_2_3(adapter)) {
+ dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
+ return -EINVAL;
+ }
+ adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
+ SLI_INTF_FAMILY_SHIFT);
+ adapter->generation = BE_GEN3;
+ break;
+ case OC_DEVICE_ID5:
+ pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+ if ((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) {
dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
return -EINVAL;
}
@@ -3737,6 +3836,8 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status != 0)
goto unsetup;
+ be_roce_dev_add(adapter);
+
dev_info(&pdev->dev, "%s: %s port %d\n", netdev->name, nic_name(pdev),
adapter->port_num);
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c
new file mode 100644
index 000000000000..deecc44b3617
--- /dev/null
+++ b/drivers/net/ethernet/emulex/benet/be_roce.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2005 - 2011 Emulex
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ */
+
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/module.h>
+
+#include "be.h"
+#include "be_cmds.h"
+
+static struct ocrdma_driver *ocrdma_drv;
+static LIST_HEAD(be_adapter_list);
+static DEFINE_MUTEX(be_adapter_list_lock);
+
+static void _be_roce_dev_add(struct be_adapter *adapter)
+{
+ struct be_dev_info dev_info;
+ int i, num_vec;
+ struct pci_dev *pdev = adapter->pdev;
+
+ if (!ocrdma_drv)
+ return;
+ if (pdev->device == OC_DEVICE_ID5) {
+ /* only msix is supported on these devices */
+ if (!msix_enabled(adapter))
+ return;
+ /* DPP region address and length */
+ dev_info.dpp_unmapped_addr = pci_resource_start(pdev, 2);
+ dev_info.dpp_unmapped_len = pci_resource_len(pdev, 2);
+ } else {
+ dev_info.dpp_unmapped_addr = 0;
+ dev_info.dpp_unmapped_len = 0;
+ }
+ dev_info.pdev = adapter->pdev;
+ if (adapter->sli_family == SKYHAWK_SLI_FAMILY)
+ dev_info.db = adapter->db;
+ else
+ dev_info.db = adapter->roce_db.base;
+ dev_info.unmapped_db = adapter->roce_db.io_addr;
+ dev_info.db_page_size = adapter->roce_db.size;
+ dev_info.db_total_size = adapter->roce_db.total_size;
+ dev_info.netdev = adapter->netdev;
+ memcpy(dev_info.mac_addr, adapter->netdev->dev_addr, ETH_ALEN);
+ dev_info.dev_family = adapter->sli_family;
+ if (msix_enabled(adapter)) {
+ /* provide all the vectors, so that EQ creation response
+ * can decide which one to use.
+ */
+ num_vec = adapter->num_msix_vec + adapter->num_msix_roce_vec;
+ dev_info.intr_mode = BE_INTERRUPT_MODE_MSIX;
+ dev_info.msix.num_vectors = min(num_vec, MAX_ROCE_MSIX_VECTORS);
+ /* provide start index of the vector,
+ * so in case of linear usage,
+ * it can use the base as starting point.
+ */
+ dev_info.msix.start_vector = adapter->num_evt_qs;
+ for (i = 0; i < dev_info.msix.num_vectors; i++) {
+ dev_info.msix.vector_list[i] =
+ adapter->msix_entries[i].vector;
+ }
+ } else {
+ dev_info.msix.num_vectors = 0;
+ dev_info.intr_mode = BE_INTERRUPT_MODE_INTX;
+ }
+ adapter->ocrdma_dev = ocrdma_drv->add(&dev_info);
+}
+
+void be_roce_dev_add(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ INIT_LIST_HEAD(&adapter->entry);
+ mutex_lock(&be_adapter_list_lock);
+ list_add_tail(&adapter->entry, &be_adapter_list);
+
+ /* invoke add() routine of roce driver only if
+ * valid driver registered with add method and add() is not yet
+ * invoked on a given adapter.
+ */
+ _be_roce_dev_add(adapter);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+void _be_roce_dev_remove(struct be_adapter *adapter)
+{
+ if (ocrdma_drv && ocrdma_drv->remove && adapter->ocrdma_dev)
+ ocrdma_drv->remove(adapter->ocrdma_dev);
+ adapter->ocrdma_dev = NULL;
+}
+
+void be_roce_dev_remove(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ mutex_lock(&be_adapter_list_lock);
+ _be_roce_dev_remove(adapter);
+ list_del(&adapter->entry);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+void _be_roce_dev_open(struct be_adapter *adapter)
+{
+ if (ocrdma_drv && adapter->ocrdma_dev &&
+ ocrdma_drv->state_change_handler)
+ ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 0);
+}
+
+void be_roce_dev_open(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ mutex_lock(&be_adapter_list_lock);
+ _be_roce_dev_open(adapter);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+void _be_roce_dev_close(struct be_adapter *adapter)
+{
+ if (ocrdma_drv && adapter->ocrdma_dev &&
+ ocrdma_drv->state_change_handler)
+ ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 1);
+}
+
+void be_roce_dev_close(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ mutex_lock(&be_adapter_list_lock);
+ _be_roce_dev_close(adapter);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+int be_roce_register_driver(struct ocrdma_driver *drv)
+{
+ struct be_adapter *dev;
+
+ mutex_lock(&be_adapter_list_lock);
+ if (ocrdma_drv) {
+ mutex_unlock(&be_adapter_list_lock);
+ return -EINVAL;
+ }
+ ocrdma_drv = drv;
+ list_for_each_entry(dev, &be_adapter_list, entry) {
+ struct net_device *netdev;
+ _be_roce_dev_add(dev);
+ netdev = dev->netdev;
+ if (netif_running(netdev) && netif_oper_up(netdev))
+ _be_roce_dev_open(dev);
+ }
+ mutex_unlock(&be_adapter_list_lock);
+ return 0;
+}
+EXPORT_SYMBOL(be_roce_register_driver);
+
+void be_roce_unregister_driver(struct ocrdma_driver *drv)
+{
+ struct be_adapter *dev;
+
+ mutex_lock(&be_adapter_list_lock);
+ list_for_each_entry(dev, &be_adapter_list, entry) {
+ if (dev->ocrdma_dev)
+ _be_roce_dev_remove(dev);
+ }
+ ocrdma_drv = NULL;
+ mutex_unlock(&be_adapter_list_lock);
+}
+EXPORT_SYMBOL(be_roce_unregister_driver);
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.h b/drivers/net/ethernet/emulex/benet/be_roce.h
new file mode 100644
index 000000000000..db4ea8081c07
--- /dev/null
+++ b/drivers/net/ethernet/emulex/benet/be_roce.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2005 - 2011 Emulex
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ */
+
+#ifndef BE_ROCE_H
+#define BE_ROCE_H
+
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+
+struct ocrdma_dev;
+
+enum be_interrupt_mode {
+ BE_INTERRUPT_MODE_MSIX = 0,
+ BE_INTERRUPT_MODE_INTX = 1,
+ BE_INTERRUPT_MODE_MSI = 2,
+};
+
+#define MAX_ROCE_MSIX_VECTORS 16
+struct be_dev_info {
+ u8 __iomem *db;
+ u64 unmapped_db;
+ u32 db_page_size;
+ u32 db_total_size;
+ u64 dpp_unmapped_addr;
+ u32 dpp_unmapped_len;
+ struct pci_dev *pdev;
+ struct net_device *netdev;
+ u8 mac_addr[ETH_ALEN];
+ u32 dev_family;
+ enum be_interrupt_mode intr_mode;
+ struct {
+ int num_vectors;
+ int start_vector;
+ u32 vector_list[MAX_ROCE_MSIX_VECTORS];
+ } msix;
+};
+
+/* ocrdma driver register's the callback functions with nic driver. */
+struct ocrdma_driver {
+ unsigned char name[32];
+ struct ocrdma_dev *(*add) (struct be_dev_info *dev_info);
+ void (*remove) (struct ocrdma_dev *);
+ void (*state_change_handler) (struct ocrdma_dev *, u32 new_state);
+};
+
+enum {
+ BE_DEV_UP = 0,
+ BE_DEV_DOWN = 1
+};
+
+/* APIs for RoCE driver to register callback handlers,
+ * which will be invoked when device is added, removed, ifup, ifdown
+ */
+int be_roce_register_driver(struct ocrdma_driver *drv);
+void be_roce_unregister_driver(struct ocrdma_driver *drv);
+
+/* API for RoCE driver to issue mailbox commands */
+int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
+ int wrb_payload_size, u16 *cmd_status, u16 *ext_status);
+
+#endif /* BE_ROCE_H */
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index 7fa0227c9c02..8f2cf8c09e2d 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -48,6 +48,7 @@
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_net.h>
+#include <linux/pinctrl/consumer.h>
#include <asm/cacheflush.h>
@@ -1543,6 +1544,7 @@ fec_probe(struct platform_device *pdev)
struct resource *r;
const struct of_device_id *of_id;
static int dev_id;
+ struct pinctrl *pinctrl;
of_id = of_match_device(fec_dt_ids, &pdev->dev);
if (of_id)
@@ -1610,6 +1612,12 @@ fec_probe(struct platform_device *pdev)
}
}
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ goto failed_pin;
+ }
+
fep->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(fep->clk)) {
ret = PTR_ERR(fep->clk);
@@ -1640,6 +1648,7 @@ failed_mii_init:
failed_init:
clk_disable_unprepare(fep->clk);
clk_put(fep->clk);
+failed_pin:
failed_clk:
for (i = 0; i < FEC_IRQ_NUM; i++) {
irq = platform_get_irq(pdev, i);
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 37b7d1c90723..95731c841044 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -493,7 +493,11 @@ out:
static void e1000_down_and_stop(struct e1000_adapter *adapter)
{
set_bit(__E1000_DOWN, &adapter->flags);
- cancel_work_sync(&adapter->reset_task);
+
+ /* Only kill reset task if adapter is not resetting */
+ if (!test_bit(__E1000_RESETTING, &adapter->flags))
+ cancel_work_sync(&adapter->reset_task);
+
cancel_delayed_work_sync(&adapter->watchdog_task);
cancel_delayed_work_sync(&adapter->phy_info_task);
cancel_delayed_work_sync(&adapter->fifo_stall_task);
diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c
index 8be20e7ea3d1..06fef5b44f77 100644
--- a/drivers/net/ethernet/mellanox/mlx4/alloc.c
+++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c
@@ -124,9 +124,6 @@ void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
spin_lock(&bitmap->lock);
bitmap_clear(bitmap->table, obj, cnt);
- bitmap->last = min(bitmap->last, obj);
- bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
- & bitmap->mask;
bitmap->avail += cnt;
spin_unlock(&bitmap->lock);
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 24429a99190d..68f5cd6cb3c7 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -118,6 +118,20 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags)
mlx4_dbg(dev, " %s\n", fname[i]);
}
+static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
+{
+ static const char * const fname[] = {
+ [0] = "RSS support",
+ [1] = "RSS Toeplitz Hash Function support",
+ [2] = "RSS XOR Hash Function support"
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(fname); ++i)
+ if (fname[i] && (flags & (1LL << i)))
+ mlx4_dbg(dev, " %s\n", fname[i]);
+}
+
int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg)
{
struct mlx4_cmd_mailbox *mailbox;
@@ -346,6 +360,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET 0x29
#define QUERY_DEV_CAP_MAX_RES_QP_OFFSET 0x2b
#define QUERY_DEV_CAP_MAX_GSO_OFFSET 0x2d
+#define QUERY_DEV_CAP_RSS_OFFSET 0x2e
#define QUERY_DEV_CAP_MAX_RDMA_OFFSET 0x2f
#define QUERY_DEV_CAP_RSZ_SRQ_OFFSET 0x33
#define QUERY_DEV_CAP_ACK_DELAY_OFFSET 0x35
@@ -390,6 +405,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98
#define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0
+ dev_cap->flags2 = 0;
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
@@ -439,6 +455,17 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
else
dev_cap->max_gso_sz = 1 << field;
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_RSS_OFFSET);
+ if (field & 0x20)
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_XOR;
+ if (field & 0x10)
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_TOP;
+ field &= 0xf;
+ if (field) {
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS;
+ dev_cap->max_rss_tbl_sz = 1 << field;
+ } else
+ dev_cap->max_rss_tbl_sz = 0;
MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RDMA_OFFSET);
dev_cap->max_rdma_global = 1 << (field & 0x3f);
MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET);
@@ -632,8 +659,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg);
mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz);
mlx4_dbg(dev, "Max counters: %d\n", dev_cap->max_counters);
+ mlx4_dbg(dev, "Max RSS Table size: %d\n", dev_cap->max_rss_tbl_sz);
dump_dev_cap_flags(dev, dev_cap->flags);
+ dump_dev_cap_flags2(dev, dev_cap->flags2);
out:
mlx4_free_cmd_mailbox(dev, mailbox);
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h
index e1a5fa56bcbc..64c0399e4b78 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.h
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.h
@@ -79,6 +79,7 @@ struct mlx4_dev_cap {
u64 trans_code[MLX4_MAX_PORTS + 1];
u16 stat_rate_support;
u64 flags;
+ u64 flags2;
int reserved_uars;
int uar_size;
int min_page_sz;
@@ -110,6 +111,7 @@ struct mlx4_dev_cap {
u32 reserved_lkey;
u64 max_icm_sz;
int max_gso_sz;
+ int max_rss_tbl_sz;
u8 supported_port_types[MLX4_MAX_PORTS + 1];
u8 suggested_type[MLX4_MAX_PORTS + 1];
u8 default_sense[MLX4_MAX_PORTS + 1];
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 984ace44104f..2e024a68fa81 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -272,10 +272,12 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.max_msg_sz = dev_cap->max_msg_sz;
dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1);
dev->caps.flags = dev_cap->flags;
+ dev->caps.flags2 = dev_cap->flags2;
dev->caps.bmme_flags = dev_cap->bmme_flags;
dev->caps.reserved_lkey = dev_cap->reserved_lkey;
dev->caps.stat_rate_support = dev_cap->stat_rate_support;
dev->caps.max_gso_sz = dev_cap->max_gso_sz;
+ dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz;
/* Sense port always allowed on supported devices for ConnectX1 and 2 */
if (dev->pdev->device != 0x1003)
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index d3469d8e3f0d..8d2666fcffd7 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -40,6 +40,7 @@
#include <linux/skbuff.h>
#include <linux/phy.h>
#include <linux/dma-mapping.h>
+#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/types.h>
@@ -340,13 +341,17 @@
*/
#define LPC_POWERDOWN_MACAHB (1 << 31)
-/* Upon the upcoming introduction of device tree usage in LPC32xx,
- * lpc_phy_interface_mode() and use_iram_for_net() will be extended with a
- * device parameter for access to device tree information at runtime, instead
- * of defining the values at compile time
- */
-static inline phy_interface_t lpc_phy_interface_mode(void)
+static phy_interface_t lpc_phy_interface_mode(struct device *dev)
{
+ if (dev && dev->of_node) {
+ const char *mode = of_get_property(dev->of_node,
+ "phy-mode", NULL);
+ if (mode && !strcmp(mode, "mii"))
+ return PHY_INTERFACE_MODE_MII;
+ return PHY_INTERFACE_MODE_RMII;
+ }
+
+ /* non-DT */
#ifdef CONFIG_ARCH_LPC32XX_MII_SUPPORT
return PHY_INTERFACE_MODE_MII;
#else
@@ -354,12 +359,16 @@ static inline phy_interface_t lpc_phy_interface_mode(void)
#endif
}
-static inline int use_iram_for_net(void)
+static bool use_iram_for_net(struct device *dev)
{
+ if (dev && dev->of_node)
+ return of_property_read_bool(dev->of_node, "use-iram");
+
+ /* non-DT */
#ifdef CONFIG_ARCH_LPC32XX_IRAM_FOR_NET
- return 1;
+ return true;
#else
- return 0;
+ return false;
#endif
}
@@ -664,7 +673,7 @@ static void __lpc_eth_init(struct netdata_local *pldat)
LPC_ENET_CLRT(pldat->net_base));
writel(LPC_IPGR_LOAD_PART2(0x12), LPC_ENET_IPGR(pldat->net_base));
- if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII)
+ if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII)
writel(LPC_COMMAND_PASSRUNTFRAME,
LPC_ENET_COMMAND(pldat->net_base));
else {
@@ -804,12 +813,13 @@ static int lpc_mii_probe(struct net_device *ndev)
}
/* Attach to the PHY */
- if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII)
+ if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII)
netdev_info(ndev, "using MII interface\n");
else
netdev_info(ndev, "using RMII interface\n");
phydev = phy_connect(ndev, dev_name(&phydev->dev),
- &lpc_handle_link_change, 0, lpc_phy_interface_mode());
+ &lpc_handle_link_change, 0,
+ lpc_phy_interface_mode(&pldat->pdev->dev));
if (IS_ERR(phydev)) {
netdev_err(ndev, "Could not attach to PHY\n");
@@ -843,7 +853,7 @@ static int lpc_mii_init(struct netdata_local *pldat)
}
/* Setup MII mode */
- if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII)
+ if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII)
writel(LPC_COMMAND_PASSRUNTFRAME,
LPC_ENET_COMMAND(pldat->net_base));
else {
@@ -1315,18 +1325,26 @@ static const struct net_device_ops lpc_netdev_ops = {
static int lpc_eth_drv_probe(struct platform_device *pdev)
{
struct resource *res;
- struct resource *dma_res;
struct net_device *ndev;
struct netdata_local *pldat;
struct phy_device *phydev;
dma_addr_t dma_handle;
int irq, ret;
+ u32 tmp;
+
+ /* Setup network interface for RMII or MII mode */
+ tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL);
+ tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK;
+ if (lpc_phy_interface_mode(&pdev->dev) == PHY_INTERFACE_MODE_MII)
+ tmp |= LPC32XX_CLKPWR_MACCTRL_USE_MII_PINS;
+ else
+ tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS;
+ __raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL);
/* Get platform resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
irq = platform_get_irq(pdev, 0);
- if ((!res) || (!dma_res) || (irq < 0) || (irq >= NR_IRQS)) {
+ if ((!res) || (irq < 0) || (irq >= NR_IRQS)) {
dev_err(&pdev->dev, "error getting resources.\n");
ret = -ENXIO;
goto err_exit;
@@ -1389,17 +1407,19 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
sizeof(struct txrx_desc_t) + sizeof(struct rx_status_t));
pldat->dma_buff_base_v = 0;
- if (use_iram_for_net()) {
- dma_handle = dma_res->start;
+ if (use_iram_for_net(&pldat->pdev->dev)) {
+ dma_handle = LPC32XX_IRAM_BASE;
if (pldat->dma_buff_size <= lpc32xx_return_iram_size())
pldat->dma_buff_base_v =
- io_p2v(dma_res->start);
+ io_p2v(LPC32XX_IRAM_BASE);
else
netdev_err(ndev,
"IRAM not big enough for net buffers, using SDRAM instead.\n");
}
if (pldat->dma_buff_base_v == 0) {
+ pldat->pdev->dev.coherent_dma_mask = 0xFFFFFFFF;
+ pldat->pdev->dev.dma_mask = &pldat->pdev->dev.coherent_dma_mask;
pldat->dma_buff_size = PAGE_ALIGN(pldat->dma_buff_size);
/* Allocate a chunk of memory for the DMA ethernet buffers
@@ -1488,7 +1508,7 @@ err_out_unregister_netdev:
platform_set_drvdata(pdev, NULL);
unregister_netdev(ndev);
err_out_dma_unmap:
- if (!use_iram_for_net() ||
+ if (!use_iram_for_net(&pldat->pdev->dev) ||
pldat->dma_buff_size > lpc32xx_return_iram_size())
dma_free_coherent(&pldat->pdev->dev, pldat->dma_buff_size,
pldat->dma_buff_base_v,
@@ -1515,7 +1535,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
unregister_netdev(ndev);
platform_set_drvdata(pdev, NULL);
- if (!use_iram_for_net() ||
+ if (!use_iram_for_net(&pldat->pdev->dev) ||
pldat->dma_buff_size > lpc32xx_return_iram_size())
dma_free_coherent(&pldat->pdev->dev, pldat->dma_buff_size,
pldat->dma_buff_base_v,
@@ -1584,6 +1604,14 @@ static int lpc_eth_drv_resume(struct platform_device *pdev)
}
#endif
+#ifdef CONFIG_OF
+static const struct of_device_id lpc_eth_match[] = {
+ { .compatible = "nxp,lpc-eth" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lpc_eth_match);
+#endif
+
static struct platform_driver lpc_eth_driver = {
.probe = lpc_eth_drv_probe,
.remove = __devexit_p(lpc_eth_drv_remove),
@@ -1593,6 +1621,7 @@ static struct platform_driver lpc_eth_driver = {
#endif
.driver = {
.name = MODNAME,
+ .of_match_table = of_match_ptr(lpc_eth_match),
},
};
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
index 0d725dc91bcb..8694124ef77d 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
@@ -1260,8 +1260,7 @@ next:
void
netxen_release_firmware(struct netxen_adapter *adapter)
{
- if (adapter->fw)
- release_firmware(adapter->fw);
+ release_firmware(adapter->fw);
adapter->fw = NULL;
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
index d32cf0ddf1b9..799fd40ed03a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
@@ -1321,8 +1321,7 @@ next:
void
qlcnic_release_firmware(struct qlcnic_adapter *adapter)
{
- if (adapter->fw)
- release_firmware(adapter->fw);
+ release_firmware(adapter->fw);
adapter->fw = NULL;
}
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 4f74b9762c29..00b4f56a671c 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -6051,7 +6051,7 @@ static int rtl_open(struct net_device *dev)
pm_runtime_get_sync(&pdev->dev);
/*
- * Rx and Tx desscriptors needs 256 bytes alignment.
+ * Rx and Tx descriptors needs 256 bytes alignment.
* dma_alloc_coherent provides more.
*/
tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c
index 8e9fda0c7aeb..2ed3ab4b3c2d 100644
--- a/drivers/net/ethernet/s6gmac.c
+++ b/drivers/net/ethernet/s6gmac.c
@@ -1,7 +1,7 @@
/*
* Ethernet driver for S6105 on chip network device
* (c)2008 emlix GmbH http://www.emlix.com
- * Authors: Oskar Schirmer <os@emlix.com>
+ * Authors: Oskar Schirmer <oskar@scara.com>
* Daniel Gloeckner <dg@emlix.com>
*
* This program is free software; you can redistribute it and/or
@@ -1070,4 +1070,4 @@ module_exit(s6gmac_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("S6105 on chip Ethernet driver");
-MODULE_AUTHOR("Oskar Schirmer <os@emlix.com>");
+MODULE_AUTHOR("Oskar Schirmer <oskar@scara.com>");
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index d07bc6de4387..70966330f44e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1640,7 +1640,7 @@ static const struct file_operations stmmac_rings_status_fops = {
.open = stmmac_sysfs_ring_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = single_release,
};
static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
@@ -1712,7 +1712,7 @@ static const struct file_operations stmmac_dma_cap_fops = {
.open = stmmac_sysfs_dma_cap_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = single_release,
};
static int stmmac_init_fs(struct net_device *dev)
diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index 8846516678c3..447a6932cab3 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -341,8 +341,8 @@ static int bdx_fw_load(struct bdx_priv *priv)
out:
if (master)
WRITE_REG(priv, regINIT_SEMAPHORE, 1);
- if (fw)
- release_firmware(fw);
+
+ release_firmware(fw);
if (rc) {
netdev_err(priv->ndev, "firmware loading failed\n");
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index 35758445297e..595205406d73 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -211,8 +211,8 @@ config KINGSUN_DONGLE
kingsun-sir.
config EP7211_DONGLE
- tristate "EP7211 I/R support"
- depends on IRTTY_SIR && ARCH_EP7211 && IRDA && EXPERIMENTAL
+ tristate "Cirrus Logic clps711x I/R support"
+ depends on IRTTY_SIR && ARCH_CLPS711X && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the Cirrus logic
EP7211 chipset's infrared module.
@@ -316,7 +316,7 @@ config AU1000_FIR
tristate "Alchemy IrDA SIR/FIR"
depends on IRDA && MIPS_ALCHEMY
help
- Say Y/M here to build suppor the the IrDA peripheral on the
+ Say Y/M here to build support the IrDA peripheral on the
Alchemy Au1000 and Au1100 SoCs.
Say M to build a module; it will be called au1k_ir.ko
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 72f687b40d66..f9a86bdb12fa 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1671,7 +1671,7 @@ static int irda_usb_probe(struct usb_interface *intf,
/* Is this really necessary? (no, except maybe for broken devices) */
if (usb_reset_configuration (dev) < 0) {
- err("reset_configuration failed");
+ dev_err(&intf->dev, "reset_configuration failed\n");
ret = -EIO;
goto err_out_3;
}
diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c
index 79aebeee928c..7b4833874ef5 100644
--- a/drivers/net/irda/kingsun-sir.c
+++ b/drivers/net/irda/kingsun-sir.c
@@ -134,14 +134,16 @@ static void kingsun_send_irq(struct urb *urb)
/* in process of stopping, just drop data */
if (!netif_running(kingsun->netdev)) {
- err("kingsun_send_irq: Network not running!");
+ dev_err(&kingsun->usbdev->dev,
+ "kingsun_send_irq: Network not running!\n");
return;
}
/* unlink, shutdown, unplug, other nasties */
if (urb->status != 0) {
- err("kingsun_send_irq: urb asynchronously failed - %d",
- urb->status);
+ dev_err(&kingsun->usbdev->dev,
+ "kingsun_send_irq: urb asynchronously failed - %d\n",
+ urb->status);
}
netif_wake_queue(netdev);
}
@@ -177,7 +179,8 @@ static netdev_tx_t kingsun_hard_xmit(struct sk_buff *skb,
kingsun, 1);
if ((ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC))) {
- err("kingsun_hard_xmit: failed tx_urb submit: %d", ret);
+ dev_err(&kingsun->usbdev->dev,
+ "kingsun_hard_xmit: failed tx_urb submit: %d\n", ret);
switch (ret) {
case -ENODEV:
case -EPIPE:
@@ -211,8 +214,9 @@ static void kingsun_rcv_irq(struct urb *urb)
/* unlink, shutdown, unplug, other nasties */
if (urb->status != 0) {
- err("kingsun_rcv_irq: urb asynchronously failed - %d",
- urb->status);
+ dev_err(&kingsun->usbdev->dev,
+ "kingsun_rcv_irq: urb asynchronously failed - %d\n",
+ urb->status);
kingsun->receiving = 0;
return;
}
@@ -238,8 +242,9 @@ static void kingsun_rcv_irq(struct urb *urb)
? 1 : 0;
}
} else if (urb->actual_length > 0) {
- err("%s(): Unexpected response length, expected %d got %d",
- __func__, kingsun->max_rx, urb->actual_length);
+ dev_err(&kingsun->usbdev->dev,
+ "%s(): Unexpected response length, expected %d got %d\n",
+ __func__, kingsun->max_rx, urb->actual_length);
}
/* This urb has already been filled in kingsun_net_open */
ret = usb_submit_urb(urb, GFP_ATOMIC);
@@ -286,7 +291,7 @@ static int kingsun_net_open(struct net_device *netdev)
sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
if (!kingsun->irlap) {
- err("kingsun-sir: irlap_open failed");
+ dev_err(&kingsun->usbdev->dev, "irlap_open failed\n");
goto free_mem;
}
@@ -298,7 +303,8 @@ static int kingsun_net_open(struct net_device *netdev)
kingsun->rx_urb->status = 0;
err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
if (err) {
- err("kingsun-sir: first urb-submit failed: %d", err);
+ dev_err(&kingsun->usbdev->dev,
+ "first urb-submit failed: %d\n", err);
goto close_irlap;
}
@@ -446,13 +452,15 @@ static int kingsun_probe(struct usb_interface *intf,
*/
interface = intf->cur_altsetting;
if (interface->desc.bNumEndpoints != 2) {
- err("kingsun-sir: expected 2 endpoints, found %d",
- interface->desc.bNumEndpoints);
+ dev_err(&intf->dev,
+ "kingsun-sir: expected 2 endpoints, found %d\n",
+ interface->desc.bNumEndpoints);
return -ENODEV;
}
endpoint = &interface->endpoint[KINGSUN_EP_IN].desc;
if (!usb_endpoint_is_int_in(endpoint)) {
- err("kingsun-sir: endpoint 0 is not interrupt IN");
+ dev_err(&intf->dev,
+ "kingsun-sir: endpoint 0 is not interrupt IN\n");
return -ENODEV;
}
@@ -460,14 +468,16 @@ static int kingsun_probe(struct usb_interface *intf,
pipe = usb_rcvintpipe(dev, ep_in);
maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
if (maxp_in > 255 || maxp_in <= 1) {
- err("%s: endpoint 0 has max packet size %d not in range",
- __FILE__, maxp_in);
+ dev_err(&intf->dev,
+ "endpoint 0 has max packet size %d not in range\n",
+ maxp_in);
return -ENODEV;
}
endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc;
if (!usb_endpoint_is_int_out(endpoint)) {
- err("kingsun-sir: endpoint 1 is not interrupt OUT");
+ dev_err(&intf->dev,
+ "kingsun-sir: endpoint 1 is not interrupt OUT\n");
return -ENODEV;
}
diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c
index abe689dffc72..824e2a93fe8a 100644
--- a/drivers/net/irda/ks959-sir.c
+++ b/drivers/net/irda/ks959-sir.c
@@ -247,8 +247,9 @@ static void ks959_speed_irq(struct urb *urb)
{
/* unlink, shutdown, unplug, other nasties */
if (urb->status != 0) {
- err("ks959_speed_irq: urb asynchronously failed - %d",
- urb->status);
+ dev_err(&urb->dev->dev,
+ "ks959_speed_irq: urb asynchronously failed - %d\n",
+ urb->status);
}
}
@@ -332,14 +333,16 @@ static void ks959_send_irq(struct urb *urb)
/* in process of stopping, just drop data */
if (!netif_running(kingsun->netdev)) {
- err("ks959_send_irq: Network not running!");
+ dev_err(&kingsun->usbdev->dev,
+ "ks959_send_irq: Network not running!\n");
return;
}
/* unlink, shutdown, unplug, other nasties */
if (urb->status != 0) {
- err("ks959_send_irq: urb asynchronously failed - %d",
- urb->status);
+ dev_err(&kingsun->usbdev->dev,
+ "ks959_send_irq: urb asynchronously failed - %d\n",
+ urb->status);
return;
}
@@ -358,8 +361,9 @@ static void ks959_send_irq(struct urb *urb)
if (kingsun->tx_buf_clear_used > 0) {
/* There is more data to be sent */
if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) {
- err("ks959_send_irq: failed tx_urb submit: %d",
- ret);
+ dev_err(&kingsun->usbdev->dev,
+ "ks959_send_irq: failed tx_urb submit: %d\n",
+ ret);
switch (ret) {
case -ENODEV:
case -EPIPE:
@@ -407,7 +411,8 @@ static netdev_tx_t ks959_hard_xmit(struct sk_buff *skb,
kingsun->tx_buf_clear_used = wraplen;
if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) {
- err("ks959_hard_xmit: failed tx_urb submit: %d", ret);
+ dev_err(&kingsun->usbdev->dev,
+ "ks959_hard_xmit: failed tx_urb submit: %d\n", ret);
switch (ret) {
case -ENODEV:
case -EPIPE:
@@ -442,8 +447,9 @@ static void ks959_rcv_irq(struct urb *urb)
/* unlink, shutdown, unplug, other nasties */
if (urb->status != 0) {
- err("kingsun_rcv_irq: urb asynchronously failed - %d",
- urb->status);
+ dev_err(&kingsun->usbdev->dev,
+ "kingsun_rcv_irq: urb asynchronously failed - %d\n",
+ urb->status);
kingsun->receiving = 0;
return;
}
@@ -536,7 +542,7 @@ static int ks959_net_open(struct net_device *netdev)
sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
if (!kingsun->irlap) {
- err("ks959-sir: irlap_open failed");
+ dev_err(&kingsun->usbdev->dev, "irlap_open failed\n");
goto free_mem;
}
@@ -549,7 +555,8 @@ static int ks959_net_open(struct net_device *netdev)
kingsun->rx_urb->status = 0;
err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
if (err) {
- err("ks959-sir: first urb-submit failed: %d", err);
+ dev_err(&kingsun->usbdev->dev,
+ "first urb-submit failed: %d\n", err);
goto close_irlap;
}
diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c
index f8c01088eeb7..5a278ab83c2f 100644
--- a/drivers/net/irda/ksdazzle-sir.c
+++ b/drivers/net/irda/ksdazzle-sir.c
@@ -168,10 +168,10 @@ struct ksdazzle_cb {
static void ksdazzle_speed_irq(struct urb *urb)
{
/* unlink, shutdown, unplug, other nasties */
- if (urb->status != 0) {
- err("ksdazzle_speed_irq: urb asynchronously failed - %d",
- urb->status);
- }
+ if (urb->status != 0)
+ dev_err(&urb->dev->dev,
+ "ksdazzle_speed_irq: urb asynchronously failed - %d\n",
+ urb->status);
}
/* Send a control request to change speed of the dongle */
@@ -245,14 +245,16 @@ static void ksdazzle_send_irq(struct urb *urb)
/* in process of stopping, just drop data */
if (!netif_running(kingsun->netdev)) {
- err("ksdazzle_send_irq: Network not running!");
+ dev_err(&kingsun->usbdev->dev,
+ "ksdazzle_send_irq: Network not running!\n");
return;
}
/* unlink, shutdown, unplug, other nasties */
if (urb->status != 0) {
- err("ksdazzle_send_irq: urb asynchronously failed - %d",
- urb->status);
+ dev_err(&kingsun->usbdev->dev,
+ "ksdazzle_send_irq: urb asynchronously failed - %d\n",
+ urb->status);
return;
}
@@ -271,7 +273,9 @@ static void ksdazzle_send_irq(struct urb *urb)
if (kingsun->tx_buf_clear_used > 0) {
/* There is more data to be sent */
if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) {
- err("ksdazzle_send_irq: failed tx_urb submit: %d", ret);
+ dev_err(&kingsun->usbdev->dev,
+ "ksdazzle_send_irq: failed tx_urb submit: %d\n",
+ ret);
switch (ret) {
case -ENODEV:
case -EPIPE:
@@ -320,7 +324,8 @@ static netdev_tx_t ksdazzle_hard_xmit(struct sk_buff *skb,
kingsun->tx_buf_clear_used = wraplen;
if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) {
- err("ksdazzle_hard_xmit: failed tx_urb submit: %d", ret);
+ dev_err(&kingsun->usbdev->dev,
+ "ksdazzle_hard_xmit: failed tx_urb submit: %d\n", ret);
switch (ret) {
case -ENODEV:
case -EPIPE:
@@ -355,8 +360,9 @@ static void ksdazzle_rcv_irq(struct urb *urb)
/* unlink, shutdown, unplug, other nasties */
if (urb->status != 0) {
- err("ksdazzle_rcv_irq: urb asynchronously failed - %d",
- urb->status);
+ dev_err(&kingsun->usbdev->dev,
+ "ksdazzle_rcv_irq: urb asynchronously failed - %d\n",
+ urb->status);
kingsun->receiving = 0;
return;
}
@@ -430,7 +436,7 @@ static int ksdazzle_net_open(struct net_device *netdev)
sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
if (!kingsun->irlap) {
- err("ksdazzle-sir: irlap_open failed");
+ dev_err(&kingsun->usbdev->dev, "irlap_open failed\n");
goto free_mem;
}
@@ -442,7 +448,7 @@ static int ksdazzle_net_open(struct net_device *netdev)
kingsun->rx_urb->status = 0;
err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
if (err) {
- err("ksdazzle-sir: first urb-submit failed: %d", err);
+ dev_err(&kingsun->usbdev->dev, "first urb-submit failed: %d\n", err);
goto close_irlap;
}
@@ -590,13 +596,14 @@ static int ksdazzle_probe(struct usb_interface *intf,
*/
interface = intf->cur_altsetting;
if (interface->desc.bNumEndpoints != 2) {
- err("ksdazzle: expected 2 endpoints, found %d",
- interface->desc.bNumEndpoints);
+ dev_err(&intf->dev, "ksdazzle: expected 2 endpoints, found %d\n",
+ interface->desc.bNumEndpoints);
return -ENODEV;
}
endpoint = &interface->endpoint[KINGSUN_EP_IN].desc;
if (!usb_endpoint_is_int_in(endpoint)) {
- err("ksdazzle: endpoint 0 is not interrupt IN");
+ dev_err(&intf->dev,
+ "ksdazzle: endpoint 0 is not interrupt IN\n");
return -ENODEV;
}
@@ -604,13 +611,16 @@ static int ksdazzle_probe(struct usb_interface *intf,
pipe = usb_rcvintpipe(dev, ep_in);
maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
if (maxp_in > 255 || maxp_in <= 1) {
- err("ksdazzle: endpoint 0 has max packet size %d not in range [2..255]", maxp_in);
+ dev_err(&intf->dev,
+ "ksdazzle: endpoint 0 has max packet size %d not in range [2..255]\n",
+ maxp_in);
return -ENODEV;
}
endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc;
if (!usb_endpoint_is_int_out(endpoint)) {
- err("ksdazzle: endpoint 1 is not interrupt OUT");
+ dev_err(&intf->dev,
+ "ksdazzle: endpoint 1 is not interrupt OUT\n");
return -ENODEV;
}
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index e6e59a078ef4..876e709b65ba 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -904,7 +904,7 @@ static int stir_net_open(struct net_device *netdev)
sprintf(hwname, "usb#%d", stir->usbdev->devnum);
stir->irlap = irlap_open(netdev, &stir->qos, hwname);
if (!stir->irlap) {
- err("stir4200: irlap_open failed");
+ dev_err(&stir->usbdev->dev, "irlap_open failed\n");
goto err_out5;
}
@@ -913,7 +913,7 @@ static int stir_net_open(struct net_device *netdev)
"%s", stir->netdev->name);
if (IS_ERR(stir->thread)) {
err = PTR_ERR(stir->thread);
- err("stir4200: unable to start kernel thread");
+ dev_err(&stir->usbdev->dev, "unable to start kernel thread\n");
goto err_out6;
}
@@ -1042,7 +1042,7 @@ static int stir_probe(struct usb_interface *intf,
ret = usb_reset_configuration(dev);
if (ret != 0) {
- err("stir4200: usb reset configuration failed");
+ dev_err(&intf->dev, "usb reset configuration failed\n");
goto err_out2;
}
diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c
index af95a98fd86f..a031f6b456b4 100644
--- a/drivers/net/ppp/ppp_async.c
+++ b/drivers/net/ppp/ppp_async.c
@@ -613,7 +613,7 @@ ppp_async_encode(struct asyncppp *ap)
*buf++ = PPP_FLAG;
ap->olim = buf;
- kfree_skb(ap->tpkt);
+ consume_skb(ap->tpkt);
ap->tpkt = NULL;
return 1;
}
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 21d7151fb0ab..5c0557222f20 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -1092,13 +1092,13 @@ pad_compress_skb(struct ppp *ppp, struct sk_buff *skb)
new_skb->data, skb->len + 2,
compressor_skb_size);
if (len > 0 && (ppp->flags & SC_CCP_UP)) {
- kfree_skb(skb);
+ consume_skb(skb);
skb = new_skb;
skb_put(skb, len);
skb_pull(skb, 2); /* pull off A/C bytes */
} else if (len == 0) {
/* didn't compress, or CCP not up yet */
- kfree_skb(new_skb);
+ consume_skb(new_skb);
new_skb = skb;
} else {
/*
@@ -1112,7 +1112,7 @@ pad_compress_skb(struct ppp *ppp, struct sk_buff *skb)
if (net_ratelimit())
netdev_err(ppp->dev, "ppp: compressor dropped pkt\n");
kfree_skb(skb);
- kfree_skb(new_skb);
+ consume_skb(new_skb);
new_skb = NULL;
}
return new_skb;
@@ -1178,7 +1178,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
!(ppp->flags & SC_NO_TCP_CCID));
if (cp == skb->data + 2) {
/* didn't compress */
- kfree_skb(new_skb);
+ consume_skb(new_skb);
} else {
if (cp[0] & SL_TYPE_COMPRESSED_TCP) {
proto = PPP_VJC_COMP;
@@ -1187,7 +1187,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
proto = PPP_VJC_UNCOMP;
cp[0] = skb->data[2];
}
- kfree_skb(skb);
+ consume_skb(skb);
skb = new_skb;
cp = skb_put(skb, len + 2);
cp[0] = 0;
@@ -1703,7 +1703,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
}
skb_reserve(ns, 2);
skb_copy_bits(skb, 0, skb_put(ns, skb->len), skb->len);
- kfree_skb(skb);
+ consume_skb(skb);
skb = ns;
}
else
@@ -1851,7 +1851,7 @@ ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb)
goto err;
}
- kfree_skb(skb);
+ consume_skb(skb);
skb = ns;
skb_put(skb, len);
skb_pull(skb, 2); /* pull off the A/C bytes */
diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c
index 55e466c511d5..1a12033d2efa 100644
--- a/drivers/net/ppp/ppp_synctty.c
+++ b/drivers/net/ppp/ppp_synctty.c
@@ -588,7 +588,7 @@ ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *skb)
skb_reserve(npkt,2);
skb_copy_from_linear_data(skb,
skb_put(npkt, skb->len), skb->len);
- kfree_skb(skb);
+ consume_skb(skb);
skb = npkt;
}
skb_push(skb,2);
@@ -656,7 +656,7 @@ ppp_sync_push(struct syncppp *ap)
if (sent < ap->tpkt->len) {
tty_stuffed = 1;
} else {
- kfree_skb(ap->tpkt);
+ consume_skb(ap->tpkt);
ap->tpkt = NULL;
clear_bit(XMIT_FULL, &ap->xmit_flags);
done = 1;
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index dd15b8f8aa0c..cbf7047decc0 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -984,8 +984,10 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
if (skb) {
total_len = min_t(size_t, total_len, skb->len);
error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len);
- if (error == 0)
- error = total_len;
+ if (error == 0) {
+ consume_skb(skb);
+ return total_len;
+ }
}
kfree_skb(skb);
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
index 72b50f57e7b2..1c98321b56cc 100644
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -209,7 +209,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
}
if (skb->sk)
skb_set_owner_w(new_skb, skb->sk);
- kfree_skb(skb);
+ consume_skb(skb);
skb = new_skb;
}
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index 42b5151aa78a..71e2b0523bc2 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -1647,6 +1647,7 @@ static struct usb_driver asix_driver = {
.resume = usbnet_resume,
.disconnect = usbnet_disconnect,
.supports_autosuspend = 1,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(asix_driver);
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index 182cfb4aeb1d..26c5bebd9eca 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -338,16 +338,18 @@ static void catc_irq_done(struct urb *urb)
} else {
catc->rx_urb->dev = catc->usbdev;
if ((res = usb_submit_urb(catc->rx_urb, GFP_ATOMIC)) < 0) {
- err("submit(rx_urb) status %d", res);
+ dev_err(&catc->usbdev->dev,
+ "submit(rx_urb) status %d\n", res);
}
}
}
resubmit:
res = usb_submit_urb (urb, GFP_ATOMIC);
if (res)
- err ("can't resubmit intr, %s-%s, status %d",
- catc->usbdev->bus->bus_name,
- catc->usbdev->devpath, res);
+ dev_err(&catc->usbdev->dev,
+ "can't resubmit intr, %s-%s, status %d\n",
+ catc->usbdev->bus->bus_name,
+ catc->usbdev->devpath, res);
}
/*
@@ -366,7 +368,8 @@ static int catc_tx_run(struct catc *catc)
catc->tx_urb->dev = catc->usbdev;
if ((status = usb_submit_urb(catc->tx_urb, GFP_ATOMIC)) < 0)
- err("submit(tx_urb), status %d", status);
+ dev_err(&catc->usbdev->dev, "submit(tx_urb), status %d\n",
+ status);
catc->tx_idx = !catc->tx_idx;
catc->tx_ptr = 0;
@@ -496,7 +499,8 @@ static void catc_ctrl_run(struct catc *catc)
memcpy(catc->ctrl_buf, q->buf, q->len);
if ((status = usb_submit_urb(catc->ctrl_urb, GFP_ATOMIC)))
- err("submit(ctrl_urb) status %d", status);
+ dev_err(&catc->usbdev->dev, "submit(ctrl_urb) status %d\n",
+ status);
}
static void catc_ctrl_done(struct urb *urb)
@@ -555,7 +559,7 @@ static int catc_ctrl_async(struct catc *catc, u8 dir, u8 request, u16 value,
catc->ctrl_head = (catc->ctrl_head + 1) & (CTRL_QUEUE - 1);
if (catc->ctrl_head == catc->ctrl_tail) {
- err("ctrl queue full");
+ dev_err(&catc->usbdev->dev, "ctrl queue full\n");
catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1);
retval = -1;
}
@@ -714,7 +718,8 @@ static int catc_open(struct net_device *netdev)
catc->irq_urb->dev = catc->usbdev;
if ((status = usb_submit_urb(catc->irq_urb, GFP_KERNEL)) < 0) {
- err("submit(irq_urb) status %d", status);
+ dev_err(&catc->usbdev->dev, "submit(irq_urb) status %d\n",
+ status);
return -1;
}
@@ -769,7 +774,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
if (usb_set_interface(usbdev,
intf->altsetting->desc.bInterfaceNumber, 1)) {
- err("Can't set altsetting 1.");
+ dev_err(&intf->dev, "Can't set altsetting 1.\n");
return -EIO;
}
@@ -799,7 +804,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
catc->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
if ((!catc->ctrl_urb) || (!catc->tx_urb) ||
(!catc->rx_urb) || (!catc->irq_urb)) {
- err("No free urbs available.");
+ dev_err(&intf->dev, "No free urbs available.\n");
usb_free_urb(catc->ctrl_urb);
usb_free_urb(catc->tx_urb);
usb_free_urb(catc->rx_urb);
@@ -947,6 +952,7 @@ static struct usb_driver catc_driver = {
.probe = catc_probe,
.disconnect = catc_disconnect,
.id_table = catc_id_table,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(catc_driver);
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index 3e41b00c6806..d848d4dd5754 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -457,6 +457,7 @@ static struct usb_driver usbpn_driver = {
.probe = usbpn_probe,
.disconnect = usbpn_disconnect,
.id_table = usbpn_ids,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(usbpn_driver);
diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c
index 685a4e22c768..434d5af8e6fb 100644
--- a/drivers/net/usb/cdc_eem.c
+++ b/drivers/net/usb/cdc_eem.c
@@ -368,6 +368,7 @@ static struct usb_driver eem_driver = {
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(eem_driver);
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 425e201f597c..a03de7197049 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -486,6 +486,7 @@ static const struct driver_info wwan_info = {
#define HUAWEI_VENDOR_ID 0x12D1
#define NOVATEL_VENDOR_ID 0x1410
+#define ZTE_VENDOR_ID 0x19D2
static const struct usb_device_id products [] = {
/*
@@ -618,6 +619,61 @@ static const struct usb_device_id products [] = {
.bInterfaceProtocol = USB_CDC_PROTO_NONE,
.driver_info = (unsigned long)&wwan_info,
}, {
+ /* ZTE (Vodafone) K3805-Z */
+ .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+ | USB_DEVICE_ID_MATCH_PRODUCT
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = ZTE_VENDOR_ID,
+ .idProduct = 0x1003,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE,
+ .driver_info = (unsigned long)&wwan_info,
+}, {
+ /* ZTE (Vodafone) K3806-Z */
+ .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+ | USB_DEVICE_ID_MATCH_PRODUCT
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = ZTE_VENDOR_ID,
+ .idProduct = 0x1015,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE,
+ .driver_info = (unsigned long)&wwan_info,
+}, {
+ /* ZTE (Vodafone) K4510-Z */
+ .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+ | USB_DEVICE_ID_MATCH_PRODUCT
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = ZTE_VENDOR_ID,
+ .idProduct = 0x1173,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE,
+ .driver_info = (unsigned long)&wwan_info,
+}, {
+ /* ZTE (Vodafone) K3770-Z */
+ .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+ | USB_DEVICE_ID_MATCH_PRODUCT
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = ZTE_VENDOR_ID,
+ .idProduct = 0x1177,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE,
+ .driver_info = (unsigned long)&wwan_info,
+}, {
+ /* ZTE (Vodafone) K3772-Z */
+ .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+ | USB_DEVICE_ID_MATCH_PRODUCT
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = ZTE_VENDOR_ID,
+ .idProduct = 0x1181,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE,
+ .driver_info = (unsigned long)&wwan_info,
+}, {
USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
USB_CDC_PROTO_NONE),
.driver_info = (unsigned long) &cdc_info,
@@ -649,6 +705,7 @@ static struct usb_driver cdc_driver = {
.resume = usbnet_resume,
.reset_resume = usbnet_resume,
.supports_autosuspend = 1,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(cdc_driver);
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 7adc9f6b0ea1..4b9513fcf275 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -1212,6 +1212,7 @@ static struct usb_driver cdc_ncm_driver = {
.resume = usbnet_resume,
.reset_resume = usbnet_resume,
.supports_autosuspend = 1,
+ .disable_hub_initiated_lpm = 1,
};
static const struct ethtool_ops cdc_ncm_ethtool_ops = {
diff --git a/drivers/net/usb/cdc_subset.c b/drivers/net/usb/cdc_subset.c
index b403d934e4e3..0d1fe89ae0bd 100644
--- a/drivers/net/usb/cdc_subset.c
+++ b/drivers/net/usb/cdc_subset.c
@@ -336,6 +336,7 @@ static struct usb_driver cdc_subset_driver = {
.resume = usbnet_resume,
.disconnect = usbnet_disconnect,
.id_table = products,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(cdc_subset_driver);
diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c
index 0e0531356e62..49ab45e17fe8 100644
--- a/drivers/net/usb/cx82310_eth.c
+++ b/drivers/net/usb/cx82310_eth.c
@@ -327,6 +327,7 @@ static struct usb_driver cx82310_driver = {
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(cx82310_driver);
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index b97226318ea5..e0433ce6ced7 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -670,6 +670,7 @@ static struct usb_driver dm9601_driver = {
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(dm9601_driver);
diff --git a/drivers/net/usb/gl620a.c b/drivers/net/usb/gl620a.c
index 38266bdae26b..db3c8021f2a3 100644
--- a/drivers/net/usb/gl620a.c
+++ b/drivers/net/usb/gl620a.c
@@ -225,6 +225,7 @@ static struct usb_driver gl620a_driver = {
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(gl620a_driver);
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 2d2a6882ba33..62f30b46fa42 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -106,13 +106,6 @@
#define MAX_RX_URBS 2
-static inline struct hso_serial *get_serial_by_tty(struct tty_struct *tty)
-{
- if (tty)
- return tty->driver_data;
- return NULL;
-}
-
/*****************************************************************************/
/* Debugging functions */
/*****************************************************************************/
@@ -255,9 +248,8 @@ struct hso_serial {
u8 dtr_state;
unsigned tx_urb_used:1;
+ struct tty_port port;
/* from usb_serial_port */
- struct tty_struct *tty;
- int open_count;
spinlock_t serial_lock;
int (*write_data) (struct hso_serial *serial);
@@ -1114,7 +1106,7 @@ static void hso_init_termios(struct ktermios *termios)
static void _hso_serial_set_termios(struct tty_struct *tty,
struct ktermios *old)
{
- struct hso_serial *serial = get_serial_by_tty(tty);
+ struct hso_serial *serial = tty->driver_data;
struct ktermios *termios;
if (!serial) {
@@ -1190,7 +1182,7 @@ static void put_rxbuf_data_and_resubmit_ctrl_urb(struct hso_serial *serial)
struct urb *urb;
urb = serial->rx_urb[0];
- if (serial->open_count > 0) {
+ if (serial->port.count > 0) {
count = put_rxbuf_data(urb, serial);
if (count == -1)
return;
@@ -1226,7 +1218,7 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb)
DUMP1(urb->transfer_buffer, urb->actual_length);
/* Anyone listening? */
- if (serial->open_count == 0)
+ if (serial->port.count == 0)
return;
if (status == 0) {
@@ -1268,7 +1260,7 @@ static void hso_unthrottle_tasklet(struct hso_serial *serial)
static void hso_unthrottle(struct tty_struct *tty)
{
- struct hso_serial *serial = get_serial_by_tty(tty);
+ struct hso_serial *serial = tty->driver_data;
tasklet_hi_schedule(&serial->unthrottle_tasklet);
}
@@ -1304,15 +1296,12 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
kref_get(&serial->parent->ref);
/* setup */
- spin_lock_irq(&serial->serial_lock);
tty->driver_data = serial;
- tty_kref_put(serial->tty);
- serial->tty = tty_kref_get(tty);
- spin_unlock_irq(&serial->serial_lock);
+ tty_port_tty_set(&serial->port, tty);
/* check for port already opened, if not set the termios */
- serial->open_count++;
- if (serial->open_count == 1) {
+ serial->port.count++;
+ if (serial->port.count == 1) {
serial->rx_state = RX_IDLE;
/* Force default termio settings */
_hso_serial_set_termios(tty, NULL);
@@ -1324,7 +1313,7 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
result = hso_start_serial_device(serial->parent, GFP_KERNEL);
if (result) {
hso_stop_serial_device(serial->parent);
- serial->open_count--;
+ serial->port.count--;
kref_put(&serial->parent->ref, hso_serial_ref_free);
}
} else {
@@ -1361,17 +1350,11 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)
/* reset the rts and dtr */
/* do the actual close */
- serial->open_count--;
+ serial->port.count--;
- if (serial->open_count <= 0) {
- serial->open_count = 0;
- spin_lock_irq(&serial->serial_lock);
- if (serial->tty == tty) {
- serial->tty->driver_data = NULL;
- serial->tty = NULL;
- tty_kref_put(tty);
- }
- spin_unlock_irq(&serial->serial_lock);
+ if (serial->port.count <= 0) {
+ serial->port.count = 0;
+ tty_port_tty_set(&serial->port, NULL);
if (!usb_gone)
hso_stop_serial_device(serial->parent);
tasklet_kill(&serial->unthrottle_tasklet);
@@ -1390,7 +1373,7 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)
static int hso_serial_write(struct tty_struct *tty, const unsigned char *buf,
int count)
{
- struct hso_serial *serial = get_serial_by_tty(tty);
+ struct hso_serial *serial = tty->driver_data;
int space, tx_bytes;
unsigned long flags;
@@ -1422,7 +1405,7 @@ out:
/* how much room is there for writing */
static int hso_serial_write_room(struct tty_struct *tty)
{
- struct hso_serial *serial = get_serial_by_tty(tty);
+ struct hso_serial *serial = tty->driver_data;
int room;
unsigned long flags;
@@ -1437,7 +1420,7 @@ static int hso_serial_write_room(struct tty_struct *tty)
/* setup the term */
static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old)
{
- struct hso_serial *serial = get_serial_by_tty(tty);
+ struct hso_serial *serial = tty->driver_data;
unsigned long flags;
if (old)
@@ -1446,7 +1429,7 @@ static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old)
/* the actual setup */
spin_lock_irqsave(&serial->serial_lock, flags);
- if (serial->open_count)
+ if (serial->port.count)
_hso_serial_set_termios(tty, old);
else
tty->termios = old;
@@ -1458,7 +1441,7 @@ static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old)
/* how many characters in the buffer */
static int hso_serial_chars_in_buffer(struct tty_struct *tty)
{
- struct hso_serial *serial = get_serial_by_tty(tty);
+ struct hso_serial *serial = tty->driver_data;
int chars;
unsigned long flags;
@@ -1629,7 +1612,7 @@ static int hso_get_count(struct tty_struct *tty,
struct serial_icounter_struct *icount)
{
struct uart_icount cnow;
- struct hso_serial *serial = get_serial_by_tty(tty);
+ struct hso_serial *serial = tty->driver_data;
struct hso_tiocmget *tiocmget = serial->tiocmget;
memset(icount, 0, sizeof(struct serial_icounter_struct));
@@ -1659,7 +1642,7 @@ static int hso_get_count(struct tty_struct *tty,
static int hso_serial_tiocmget(struct tty_struct *tty)
{
int retval;
- struct hso_serial *serial = get_serial_by_tty(tty);
+ struct hso_serial *serial = tty->driver_data;
struct hso_tiocmget *tiocmget;
u16 UART_state_bitmap;
@@ -1693,7 +1676,7 @@ static int hso_serial_tiocmset(struct tty_struct *tty,
int val = 0;
unsigned long flags;
int if_num;
- struct hso_serial *serial = get_serial_by_tty(tty);
+ struct hso_serial *serial = tty->driver_data;
/* sanity check */
if (!serial) {
@@ -1733,7 +1716,7 @@ static int hso_serial_tiocmset(struct tty_struct *tty,
static int hso_serial_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
- struct hso_serial *serial = get_serial_by_tty(tty);
+ struct hso_serial *serial = tty->driver_data;
int ret = 0;
D4("IOCTL cmd: %d, arg: %ld", cmd, arg);
@@ -1905,7 +1888,7 @@ static void intr_callback(struct urb *urb)
D1("Pending read interrupt on port %d\n", i);
spin_lock(&serial->serial_lock);
if (serial->rx_state == RX_IDLE &&
- serial->open_count > 0) {
+ serial->port.count > 0) {
/* Setup and send a ctrl req read on
* port i */
if (!serial->rx_urb_filled[0]) {
@@ -1954,14 +1937,13 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb)
spin_lock(&serial->serial_lock);
serial->tx_urb_used = 0;
- tty = tty_kref_get(serial->tty);
spin_unlock(&serial->serial_lock);
if (status) {
handle_usb_error(status, __func__, serial->parent);
- tty_kref_put(tty);
return;
}
hso_put_activity(serial->parent);
+ tty = tty_port_tty_get(&serial->port);
if (tty) {
tty_wakeup(tty);
tty_kref_put(tty);
@@ -2001,7 +1983,6 @@ static void ctrl_callback(struct urb *urb)
struct hso_serial *serial = urb->context;
struct usb_ctrlrequest *req;
int status = urb->status;
- struct tty_struct *tty;
/* sanity check */
if (!serial)
@@ -2009,11 +1990,9 @@ static void ctrl_callback(struct urb *urb)
spin_lock(&serial->serial_lock);
serial->tx_urb_used = 0;
- tty = tty_kref_get(serial->tty);
spin_unlock(&serial->serial_lock);
if (status) {
handle_usb_error(status, __func__, serial->parent);
- tty_kref_put(tty);
return;
}
@@ -2031,13 +2010,15 @@ static void ctrl_callback(struct urb *urb)
put_rxbuf_data_and_resubmit_ctrl_urb(serial);
spin_unlock(&serial->serial_lock);
} else {
+ struct tty_struct *tty = tty_port_tty_get(&serial->port);
hso_put_activity(serial->parent);
- if (tty)
+ if (tty) {
tty_wakeup(tty);
+ tty_kref_put(tty);
+ }
/* response to a write command */
hso_kick_transmit(serial);
}
- tty_kref_put(tty);
}
/* handle RX data for serial port */
@@ -2053,8 +2034,7 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
return -2;
}
- /* All callers to put_rxbuf_data hold serial_lock */
- tty = tty_kref_get(serial->tty);
+ tty = tty_port_tty_get(&serial->port);
/* Push data to tty */
if (tty) {
@@ -2074,12 +2054,12 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
write_length_remaining -= curr_write_len;
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
}
if (write_length_remaining == 0) {
serial->curr_rx_urb_offset = 0;
serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
}
- tty_kref_put(tty);
return write_length_remaining;
}
@@ -2320,6 +2300,7 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
serial->minor = minor;
serial->magic = HSO_SERIAL_MAGIC;
spin_lock_init(&serial->serial_lock);
+ tty_port_init(&serial->port);
serial->num_rx_urbs = num_urbs;
/* RX, allocate urb and initialize */
@@ -3098,7 +3079,7 @@ static int hso_resume(struct usb_interface *iface)
/* Start all serial ports */
for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {
if (serial_table[i] && (serial_table[i]->interface == iface)) {
- if (dev2ser(serial_table[i])->open_count) {
+ if (dev2ser(serial_table[i])->port.count) {
result =
hso_start_serial_device(serial_table[i], GFP_NOIO);
hso_kick_transmit(dev2ser(serial_table[i]));
@@ -3172,13 +3153,12 @@ static void hso_free_interface(struct usb_interface *interface)
if (serial_table[i] &&
(serial_table[i]->interface == interface)) {
hso_dev = dev2ser(serial_table[i]);
- spin_lock_irq(&hso_dev->serial_lock);
- tty = tty_kref_get(hso_dev->tty);
- spin_unlock_irq(&hso_dev->serial_lock);
- if (tty)
+ tty = tty_port_tty_get(&hso_dev->port);
+ if (tty) {
tty_hangup(tty);
+ tty_kref_put(tty);
+ }
mutex_lock(&hso_dev->parent->mutex);
- tty_kref_put(tty);
hso_dev->parent->usb_gone = 1;
mutex_unlock(&hso_dev->parent->mutex);
kref_put(&serial_table[i]->ref, hso_serial_ref_free);
@@ -3291,6 +3271,7 @@ static struct usb_driver hso_driver = {
.resume = hso_resume,
.reset_resume = hso_resume,
.supports_autosuspend = 1,
+ .disable_hub_initiated_lpm = 1,
};
static int __init hso_init(void)
@@ -3312,7 +3293,6 @@ static int __init hso_init(void)
return -ENOMEM;
/* fill in all needed values */
- tty_drv->magic = TTY_DRIVER_MAGIC;
tty_drv->driver_name = driver_name;
tty_drv->name = tty_filename;
@@ -3333,7 +3313,7 @@ static int __init hso_init(void)
if (result) {
printk(KERN_ERR "%s - tty_register_driver failed(%d)\n",
__func__, result);
- return result;
+ goto err_free_tty;
}
/* register this module as an usb driver */
@@ -3341,13 +3321,16 @@ static int __init hso_init(void)
if (result) {
printk(KERN_ERR "Could not register hso driver? error: %d\n",
result);
- /* cleanup serial interface */
- tty_unregister_driver(tty_drv);
- return result;
+ goto err_unreg_tty;
}
/* done */
return 0;
+err_unreg_tty:
+ tty_unregister_driver(tty_drv);
+err_free_tty:
+ put_tty_driver(tty_drv);
+ return result;
}
static void __exit hso_exit(void)
@@ -3355,6 +3338,7 @@ static void __exit hso_exit(void)
printk(KERN_INFO "hso: unloaded\n");
tty_unregister_driver(tty_drv);
+ put_tty_driver(tty_drv);
/* deregister the usb driver */
usb_deregister(&hso_driver);
}
diff --git a/drivers/net/usb/int51x1.c b/drivers/net/usb/int51x1.c
index 12a22a453ff1..8de641713d5f 100644
--- a/drivers/net/usb/int51x1.c
+++ b/drivers/net/usb/int51x1.c
@@ -236,6 +236,7 @@ static struct usb_driver int51x1_driver = {
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(int51x1_driver);
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
index dd78c4cbd459..964031e3da87 100644
--- a/drivers/net/usb/ipheth.c
+++ b/drivers/net/usb/ipheth.c
@@ -209,7 +209,8 @@ static void ipheth_rcvbulk_callback(struct urb *urb)
case 0:
break;
default:
- err("%s: urb status: %d", __func__, status);
+ dev_err(&dev->intf->dev, "%s: urb status: %d\n",
+ __func__, status);
return;
}
@@ -222,7 +223,8 @@ static void ipheth_rcvbulk_callback(struct urb *urb)
skb = dev_alloc_skb(len);
if (!skb) {
- err("%s: dev_alloc_skb: -ENOMEM", __func__);
+ dev_err(&dev->intf->dev, "%s: dev_alloc_skb: -ENOMEM\n",
+ __func__);
dev->net->stats.rx_dropped++;
return;
}
@@ -251,7 +253,8 @@ static void ipheth_sndbulk_callback(struct urb *urb)
status != -ENOENT &&
status != -ECONNRESET &&
status != -ESHUTDOWN)
- err("%s: urb status: %d", __func__, status);
+ dev_err(&dev->intf->dev, "%s: urb status: %d\n",
+ __func__, status);
dev_kfree_skb_irq(dev->tx_skb);
netif_wake_queue(dev->net);
@@ -271,7 +274,8 @@ static int ipheth_carrier_set(struct ipheth_device *dev)
dev->ctrl_buf, IPHETH_CTRL_BUF_SIZE,
IPHETH_CTRL_TIMEOUT);
if (retval < 0) {
- err("%s: usb_control_msg: %d", __func__, retval);
+ dev_err(&dev->intf->dev, "%s: usb_control_msg: %d\n",
+ __func__, retval);
return retval;
}
@@ -308,9 +312,11 @@ static int ipheth_get_macaddr(struct ipheth_device *dev)
IPHETH_CTRL_BUF_SIZE,
IPHETH_CTRL_TIMEOUT);
if (retval < 0) {
- err("%s: usb_control_msg: %d", __func__, retval);
+ dev_err(&dev->intf->dev, "%s: usb_control_msg: %d\n",
+ __func__, retval);
} else if (retval < ETH_ALEN) {
- err("%s: usb_control_msg: short packet: %d bytes",
+ dev_err(&dev->intf->dev,
+ "%s: usb_control_msg: short packet: %d bytes\n",
__func__, retval);
retval = -EINVAL;
} else {
@@ -335,7 +341,8 @@ static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags)
retval = usb_submit_urb(dev->rx_urb, mem_flags);
if (retval)
- err("%s: usb_submit_urb: %d", __func__, retval);
+ dev_err(&dev->intf->dev, "%s: usb_submit_urb: %d\n",
+ __func__, retval);
return retval;
}
@@ -396,7 +403,8 @@ static int ipheth_tx(struct sk_buff *skb, struct net_device *net)
retval = usb_submit_urb(dev->tx_urb, GFP_ATOMIC);
if (retval) {
- err("%s: usb_submit_urb: %d", __func__, retval);
+ dev_err(&dev->intf->dev, "%s: usb_submit_urb: %d\n",
+ __func__, retval);
dev->net->stats.tx_errors++;
dev_kfree_skb_irq(skb);
} else {
@@ -414,7 +422,7 @@ static void ipheth_tx_timeout(struct net_device *net)
{
struct ipheth_device *dev = netdev_priv(net);
- err("%s: TX timeout", __func__);
+ dev_err(&dev->intf->dev, "%s: TX timeout\n", __func__);
dev->net->stats.tx_errors++;
usb_unlink_urb(dev->tx_urb);
}
@@ -464,7 +472,7 @@ static int ipheth_probe(struct usb_interface *intf,
hintf = usb_altnum_to_altsetting(intf, IPHETH_ALT_INTFNUM);
if (hintf == NULL) {
retval = -ENODEV;
- err("Unable to find alternate settings interface");
+ dev_err(&intf->dev, "Unable to find alternate settings interface\n");
goto err_endpoints;
}
@@ -477,7 +485,7 @@ static int ipheth_probe(struct usb_interface *intf,
}
if (!(dev->bulk_in && dev->bulk_out)) {
retval = -ENODEV;
- err("Unable to find endpoints");
+ dev_err(&intf->dev, "Unable to find endpoints\n");
goto err_endpoints;
}
@@ -495,7 +503,7 @@ static int ipheth_probe(struct usb_interface *intf,
retval = ipheth_alloc_urbs(dev);
if (retval) {
- err("error allocating urbs: %d", retval);
+ dev_err(&intf->dev, "error allocating urbs: %d\n", retval);
goto err_alloc_urbs;
}
@@ -506,7 +514,7 @@ static int ipheth_probe(struct usb_interface *intf,
retval = register_netdev(netdev);
if (retval) {
- err("error registering netdev: %d", retval);
+ dev_err(&intf->dev, "error registering netdev: %d\n", retval);
retval = -EIO;
goto err_register_netdev;
}
@@ -546,6 +554,7 @@ static struct usb_driver ipheth_driver = {
.probe = ipheth_probe,
.disconnect = ipheth_disconnect,
.id_table = ipheth_table,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(ipheth_driver);
diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c
index 7562649b3d6b..92c49e0a59ec 100644
--- a/drivers/net/usb/kalmia.c
+++ b/drivers/net/usb/kalmia.c
@@ -372,7 +372,8 @@ static struct usb_driver kalmia_driver = {
.probe = usbnet_probe,
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
- .resume = usbnet_resume
+ .resume = usbnet_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(kalmia_driver);
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index df2a2cf35a99..d8ad55284389 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -179,6 +179,7 @@ static struct usb_driver kaweth_driver = {
.resume = kaweth_resume,
.id_table = usb_klsi_table,
.supports_autosuspend = 1,
+ .disable_hub_initiated_lpm = 1,
};
typedef __u8 eth_addr_t[6];
@@ -400,12 +401,13 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth,
ret = request_firmware(&fw, fwname, &kaweth->dev->dev);
if (ret) {
- err("Firmware request failed\n");
+ dev_err(&kaweth->intf->dev, "Firmware request failed\n");
return ret;
}
if (fw->size > KAWETH_FIRMWARE_BUF_SIZE) {
- err("Firmware too big: %zu", fw->size);
+ dev_err(&kaweth->intf->dev, "Firmware too big: %zu\n",
+ fw->size);
release_firmware(fw);
return -ENOSPC;
}
@@ -501,9 +503,10 @@ static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, gfp_t mf)
}
if (status)
- err ("can't resubmit intr, %s-%s, status %d",
- kaweth->dev->bus->bus_name,
- kaweth->dev->devpath, status);
+ dev_err(&kaweth->intf->dev,
+ "can't resubmit intr, %s-%s, status %d\n",
+ kaweth->dev->bus->bus_name,
+ kaweth->dev->devpath, status);
}
static void int_callback(struct urb *u)
@@ -576,7 +579,8 @@ static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth,
kaweth->suspend_lowmem_rx = 1;
schedule_delayed_work(&kaweth->lowmem_work, HZ/4);
}
- err("resubmitting rx_urb %d failed", result);
+ dev_err(&kaweth->intf->dev, "resubmitting rx_urb %d failed\n",
+ result);
} else {
kaweth->suspend_lowmem_rx = 0;
}
@@ -634,20 +638,21 @@ static void kaweth_usb_receive(struct urb *urb)
spin_unlock(&kaweth->device_lock);
if(status && status != -EREMOTEIO && count != 1) {
- err("%s RX status: %d count: %d packet_len: %d",
- net->name,
- status,
- count,
- (int)pkt_len);
+ dev_err(&kaweth->intf->dev,
+ "%s RX status: %d count: %d packet_len: %d\n",
+ net->name, status, count, (int)pkt_len);
kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
return;
}
if(kaweth->net && (count > 2)) {
if(pkt_len > (count - 2)) {
- err("Packet length too long for USB frame (pkt_len: %x, count: %x)",pkt_len, count);
- err("Packet len & 2047: %x", pkt_len & 2047);
- err("Count 2: %x", count2);
+ dev_err(&kaweth->intf->dev,
+ "Packet length too long for USB frame (pkt_len: %x, count: %x)\n",
+ pkt_len, count);
+ dev_err(&kaweth->intf->dev, "Packet len & 2047: %x\n",
+ pkt_len & 2047);
+ dev_err(&kaweth->intf->dev, "Count 2: %x\n", count2);
kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
return;
}
@@ -686,7 +691,7 @@ static int kaweth_open(struct net_device *net)
res = usb_autopm_get_interface(kaweth->intf);
if (res) {
- err("Interface cannot be resumed.");
+ dev_err(&kaweth->intf->dev, "Interface cannot be resumed.\n");
return -EIO;
}
res = kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL);
@@ -907,7 +912,8 @@ static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth)
KAWETH_CONTROL_TIMEOUT);
if(result < 0) {
- err("Failed to set Rx mode: %d", result);
+ dev_err(&kaweth->intf->dev, "Failed to set Rx mode: %d\n",
+ result);
}
else {
dbg("Set Rx mode to %d", packet_filter_bitmap);
@@ -1045,7 +1051,8 @@ static int kaweth_probe(
"kaweth/new_code.bin",
100,
2)) < 0) {
- err("Error downloading firmware (%d)", result);
+ dev_err(&intf->dev, "Error downloading firmware (%d)\n",
+ result);
goto err_fw;
}
@@ -1053,7 +1060,9 @@ static int kaweth_probe(
"kaweth/new_code_fix.bin",
100,
3)) < 0) {
- err("Error downloading firmware fix (%d)", result);
+ dev_err(&intf->dev,
+ "Error downloading firmware fix (%d)\n",
+ result);
goto err_fw;
}
@@ -1061,7 +1070,9 @@ static int kaweth_probe(
"kaweth/trigger_code.bin",
126,
2)) < 0) {
- err("Error downloading trigger code (%d)", result);
+ dev_err(&intf->dev,
+ "Error downloading trigger code (%d)\n",
+ result);
goto err_fw;
}
@@ -1070,13 +1081,14 @@ static int kaweth_probe(
"kaweth/trigger_code_fix.bin",
126,
3)) < 0) {
- err("Error downloading trigger code fix (%d)", result);
+ dev_err(&intf->dev, "Error downloading trigger code fix (%d)\n", result);
goto err_fw;
}
if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) {
- err("Error triggering firmware (%d)", result);
+ dev_err(&intf->dev, "Error triggering firmware (%d)\n",
+ result);
goto err_fw;
}
@@ -1091,7 +1103,7 @@ err_fw:
result = kaweth_read_configuration(kaweth);
if(result < 0) {
- err("Error reading configuration (%d), no net device created", result);
+ dev_err(&intf->dev, "Error reading configuration (%d), no net device created\n", result);
goto err_free_netdev;
}
@@ -1103,7 +1115,7 @@ err_fw:
if(!memcmp(&kaweth->configuration.hw_addr,
&bcast_addr,
sizeof(bcast_addr))) {
- err("Firmware not functioning properly, no net device created");
+ dev_err(&intf->dev, "Firmware not functioning properly, no net device created\n");
goto err_free_netdev;
}
@@ -1113,7 +1125,7 @@ err_fw:
}
if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) {
- err("Error setting SOFS wait");
+ dev_err(&intf->dev, "Error setting SOFS wait\n");
goto err_free_netdev;
}
@@ -1123,7 +1135,7 @@ err_fw:
KAWETH_PACKET_FILTER_MULTICAST);
if(result < 0) {
- err("Error setting receive filter");
+ dev_err(&intf->dev, "Error setting receive filter\n");
goto err_free_netdev;
}
@@ -1175,7 +1187,7 @@ err_fw:
SET_NETDEV_DEV(netdev, &intf->dev);
if (register_netdev(netdev) != 0) {
- err("Error registering netdev.");
+ dev_err(&intf->dev, "Error registering netdev.\n");
goto err_intfdata;
}
diff --git a/drivers/net/usb/lg-vl600.c b/drivers/net/usb/lg-vl600.c
index 45a981fde43f..808d6506da41 100644
--- a/drivers/net/usb/lg-vl600.c
+++ b/drivers/net/usb/lg-vl600.c
@@ -344,6 +344,7 @@ static struct usb_driver lg_vl600_driver = {
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(lg_vl600_driver);
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c
index c434b6ba0337..add1064f755d 100644
--- a/drivers/net/usb/mcs7830.c
+++ b/drivers/net/usb/mcs7830.c
@@ -690,6 +690,7 @@ static struct usb_driver mcs7830_driver = {
.suspend = usbnet_suspend,
.resume = usbnet_resume,
.reset_resume = mcs7830_reset_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(mcs7830_driver);
diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c
index 83f965cb69e7..28c4d513ba85 100644
--- a/drivers/net/usb/net1080.c
+++ b/drivers/net/usb/net1080.c
@@ -587,6 +587,7 @@ static struct usb_driver net1080_driver = {
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(net1080_driver);
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 752393092325..7023220456c5 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -1489,6 +1489,7 @@ static struct usb_driver pegasus_driver = {
.id_table = pegasus_ids,
.suspend = pegasus_suspend,
.resume = pegasus_resume,
+ .disable_hub_initiated_lpm = 1,
};
static void __init parse_id(char *id)
diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c
index b2b035e29978..4584b9a805b3 100644
--- a/drivers/net/usb/plusb.c
+++ b/drivers/net/usb/plusb.c
@@ -152,6 +152,7 @@ static struct usb_driver plusb_driver = {
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(plusb_driver);
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index d316503b35d4..380dbea6109d 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -356,10 +356,19 @@ static const struct driver_info qmi_wwan_gobi = {
};
/* ZTE suck at making USB descriptors */
+static const struct driver_info qmi_wwan_force_int1 = {
+ .description = "Qualcomm WWAN/QMI device",
+ .flags = FLAG_WWAN,
+ .bind = qmi_wwan_bind_shared,
+ .unbind = qmi_wwan_unbind_shared,
+ .manage_power = qmi_wwan_manage_power,
+ .data = BIT(1), /* interface whitelist bitmap */
+};
+
static const struct driver_info qmi_wwan_force_int4 = {
- .description = "Qualcomm Gobi wwan/QMI device",
+ .description = "Qualcomm WWAN/QMI device",
.flags = FLAG_WWAN,
- .bind = qmi_wwan_bind_gobi,
+ .bind = qmi_wwan_bind_shared,
.unbind = qmi_wwan_unbind_shared,
.manage_power = qmi_wwan_manage_power,
.data = BIT(4), /* interface whitelist bitmap */
@@ -401,6 +410,14 @@ static const struct usb_device_id products[] = {
.bInterfaceProtocol = 8, /* NOTE: This is the *slave* interface of the CDC Union! */
.driver_info = (unsigned long)&qmi_wwan_info,
},
+ { /* Vodafone/Huawei K5005 (12d1:14c8) and similar modems */
+ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = HUAWEI_VENDOR_ID,
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 56, /* NOTE: This is the *slave* interface of the CDC Union! */
+ .driver_info = (unsigned long)&qmi_wwan_info,
+ },
{ /* Huawei E392, E398 and possibly others in "Windows mode"
* using a combined control and data interface without any CDC
* functional descriptors
@@ -430,6 +447,15 @@ static const struct usb_device_id products[] = {
.bInterfaceProtocol = 0xff,
.driver_info = (unsigned long)&qmi_wwan_force_int4,
},
+ { /* ZTE (Vodafone) K3520-Z */
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x19d2,
+ .idProduct = 0x0055,
+ .bInterfaceClass = 0xff,
+ .bInterfaceSubClass = 0xff,
+ .bInterfaceProtocol = 0xff,
+ .driver_info = (unsigned long)&qmi_wwan_force_int1,
+ },
{ /* ZTE (Vodafone) K3565-Z */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x19d2,
@@ -457,6 +483,15 @@ static const struct usb_device_id products[] = {
.bInterfaceProtocol = 0xff,
.driver_info = (unsigned long)&qmi_wwan_force_int4,
},
+ { /* ZTE (Vodafone) K3765-Z */
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x19d2,
+ .idProduct = 0x2002,
+ .bInterfaceClass = 0xff,
+ .bInterfaceSubClass = 0xff,
+ .bInterfaceProtocol = 0xff,
+ .driver_info = (unsigned long)&qmi_wwan_force_int4,
+ },
{ /* ZTE (Vodafone) K4505-Z */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x19d2,
@@ -525,6 +560,7 @@ static struct usb_driver qmi_wwan_driver = {
.resume = qmi_wwan_resume,
.reset_resume = qmi_wwan_resume,
.supports_autosuspend = 1,
+ .disable_hub_initiated_lpm = 1,
};
static int __init qmi_wwan_init(void)
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
index 0d746b3fdef1..4a4335833c36 100644
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -638,6 +638,7 @@ static struct usb_driver rndis_driver = {
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(rndis_driver);
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index d363b31053da..0e2c92e0e532 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -203,7 +203,8 @@ static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size)
if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) {
if (ret == -ENODEV)
netif_device_detach(dev->netdev);
- err("control request submission failed: %d", ret);
+ dev_err(&dev->udev->dev,
+ "control request submission failed: %d\n", ret);
} else
set_bit(RX_REG_SET, &dev->flags);
@@ -516,9 +517,9 @@ resubmit:
if (res == -ENODEV)
netif_device_detach(dev->netdev);
else if (res)
- err ("can't resubmit intr, %s-%s/input0, status %d",
- dev->udev->bus->bus_name,
- dev->udev->devpath, res);
+ dev_err(&dev->udev->dev,
+ "can't resubmit intr, %s-%s/input0, status %d\n",
+ dev->udev->bus->bus_name, dev->udev->devpath, res);
}
static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message)
@@ -890,11 +891,11 @@ static int rtl8150_probe(struct usb_interface *intf,
dev->intr_interval = 100; /* 100ms */
if (!alloc_all_urbs(dev)) {
- err("out of memory");
+ dev_err(&intf->dev, "out of memory\n");
goto out;
}
if (!rtl8150_reset(dev)) {
- err("couldn't reset the device");
+ dev_err(&intf->dev, "couldn't reset the device\n");
goto out1;
}
fill_skb_pool(dev);
@@ -903,7 +904,7 @@ static int rtl8150_probe(struct usb_interface *intf,
usb_set_intfdata(intf, dev);
SET_NETDEV_DEV(netdev, &intf->dev);
if (register_netdev(netdev) != 0) {
- err("couldn't register the device");
+ dev_err(&intf->dev, "couldn't register the device\n");
goto out2;
}
@@ -947,7 +948,8 @@ static struct usb_driver rtl8150_driver = {
.disconnect = rtl8150_disconnect,
.id_table = rtl8150_table,
.suspend = rtl8150_suspend,
- .resume = rtl8150_resume
+ .resume = rtl8150_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(rtl8150_driver);
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c
index b59cf20c7817..3faef5670d1f 100644
--- a/drivers/net/usb/sierra_net.c
+++ b/drivers/net/usb/sierra_net.c
@@ -982,6 +982,7 @@ static struct usb_driver sierra_net_driver = {
.suspend = usbnet_suspend,
.resume = usbnet_resume,
.no_dynamic_id = 1,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(sierra_net_driver);
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index fb1a087b101d..1c6e51588da7 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1254,6 +1254,7 @@ static struct usb_driver smsc75xx_driver = {
.suspend = usbnet_suspend,
.resume = usbnet_resume,
.disconnect = usbnet_disconnect,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(smsc75xx_driver);
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 94ae66999f59..b1112e753859 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1297,6 +1297,7 @@ static struct usb_driver smsc95xx_driver = {
.suspend = usbnet_suspend,
.resume = usbnet_resume,
.disconnect = usbnet_disconnect,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(smsc95xx_driver);
diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c
index 34db195fb8b0..35c90307d473 100644
--- a/drivers/net/usb/zaurus.c
+++ b/drivers/net/usb/zaurus.c
@@ -377,6 +377,7 @@ static struct usb_driver zaurus_driver = {
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(zaurus_driver);
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index fa58c7869954..9ce6995e8d08 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -501,7 +501,9 @@ static void virtnet_napi_enable(struct virtnet_info *vi)
* We synchronize against interrupts via NAPI_STATE_SCHED */
if (napi_schedule_prep(&vi->napi)) {
virtqueue_disable_cb(vi->rvq);
+ local_bh_disable();
__napi_schedule(&vi->napi);
+ local_bh_enable();
}
}
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index d70ede7a7f96..d58431e99f73 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -203,37 +203,6 @@ config WANXL_BUILD_FIRMWARE
You should never need this option, say N.
-config PC300
- tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)"
- depends on HDLC && PCI && BROKEN
- ---help---
- This driver is broken because of struct tty_driver change.
-
- Driver for the Cyclades-PC300 synchronous communication boards.
-
- These boards provide synchronous serial interfaces to your
- Linux box (interfaces currently available are RS-232/V.35, X.21 and
- T1/E1). If you wish to support Multilink PPP, please select the
- option later and read the file README.mlppp provided by PC300
- package.
-
- To compile this as a module, choose M here: the module
- will be called pc300.
-
- If unsure, say N.
-
-config PC300_MLPPP
- bool "Cyclades-PC300 MLPPP support"
- depends on PC300 && PPP_MULTILINK && PPP_SYNC_TTY && HDLC_PPP
- help
- Multilink PPP over the PC300 synchronous communication boards.
-
-comment "Cyclades-PC300 MLPPP support is disabled."
- depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP)
-
-comment "Refer to the file README.mlppp, provided by PC300 package."
- depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP)
-
config PC300TOO
tristate "Cyclades PC300 RSV/X21 alternative support"
depends on HDLC && PCI
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
index 19d14bc28356..eac709bed7ae 100644
--- a/drivers/net/wan/Makefile
+++ b/drivers/net/wan/Makefile
@@ -17,10 +17,6 @@ obj-$(CONFIG_HDLC_FR) += hdlc_fr.o
obj-$(CONFIG_HDLC_PPP) += hdlc_ppp.o
obj-$(CONFIG_HDLC_X25) += hdlc_x25.o
-pc300-y := pc300_drv.o
-pc300-$(CONFIG_PC300_MLPPP) += pc300_tty.o
-pc300-objs := $(pc300-y)
-
obj-$(CONFIG_HOSTESS_SV11) += z85230.o hostess_sv11.o
obj-$(CONFIG_SEALEVEL_4021) += z85230.o sealevel.o
obj-$(CONFIG_COSA) += cosa.o
@@ -35,7 +31,6 @@ obj-$(CONFIG_SDLA) += sdla.o
obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o
obj-$(CONFIG_LAPBETHER) += lapbether.o
obj-$(CONFIG_SBNI) += sbni.o
-obj-$(CONFIG_PC300) += pc300.o
obj-$(CONFIG_N2) += n2.o
obj-$(CONFIG_C101) += c101.o
obj-$(CONFIG_WANXL) += wanxl.o
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 3df0146b797e..efc162e0b511 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -1955,7 +1955,7 @@ static int at76_hw_scan(struct ieee80211_hw *hw,
ret = at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan));
if (ret < 0) {
- err("CMD_SCAN failed: %d", ret);
+ wiphy_err(priv->hw->wiphy, "CMD_SCAN failed: %d\n", ret);
goto exit;
}
@@ -2486,6 +2486,7 @@ static struct usb_driver at76_driver = {
.probe = at76_probe,
.disconnect = at76_disconnect,
.id_table = dev_table,
+ .disable_hub_initiated_lpm = 1,
};
static int __init at76_mod_init(void)
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c
index ec7f1f5fd1ca..44a795f14da9 100644
--- a/drivers/net/wireless/ath/ath6kl/usb.c
+++ b/drivers/net/wireless/ath/ath6kl/usb.c
@@ -1182,6 +1182,7 @@ static struct usb_driver ath6kl_usb_driver = {
.disconnect = ath6kl_usb_remove,
.id_table = ath6kl_usb_ids,
.supports_autosuspend = true,
+ .disable_hub_initiated_lpm = 1,
};
static int ath6kl_usb_init(void)
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index f67cd952e741..aa327adcc3d8 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -1358,6 +1358,7 @@ static struct usb_driver ath9k_hif_usb_driver = {
#endif
.id_table = ath9k_hif_usb_ids,
.soft_unbind = 1,
+ .disable_hub_initiated_lpm = 1,
};
int ath9k_hif_usb_init(void)
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index 89821e4835c7..888152ce3eca 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -1159,6 +1159,7 @@ static struct usb_driver carl9170_driver = {
.resume = carl9170_usb_resume,
.reset_resume = carl9170_usb_resume,
#endif /* CONFIG_PM */
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(carl9170_driver);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index 1d67ecf681b7..c5a34ffe6459 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -1596,7 +1596,8 @@ static struct usb_driver brcmf_usbdrvr = {
.id_table = brcmf_usb_devid_table,
.suspend = brcmf_usb_suspend,
.resume = brcmf_usb_resume,
- .supports_autosuspend = 1
+ .supports_autosuspend = 1,
+ .disable_hub_initiated_lpm = 1,
};
void brcmf_usb_exit(void)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index 18a383798e5d..403de96f9747 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -759,7 +759,12 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
IWL_ERR(priv, "alloc_skb failed\n");
return;
}
- hdrlen = min_t(unsigned int, len, skb_tailroom(skb));
+ /* If frame is small enough to fit in skb->head, pull it completely.
+ * If not, only pull ieee80211_hdr so that splice() or TCP coalesce
+ * are more efficient.
+ */
+ hdrlen = (len <= skb_tailroom(skb)) ? len : sizeof(*hdr);
+
memcpy(skb_put(skb, hdrlen), hdr, hdrlen);
fraglen = len - hdrlen;
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 75403e6e3990..cd3b0d400618 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -1011,6 +1011,7 @@ static struct usb_driver if_usb_driver = {
.suspend = if_usb_suspend,
.resume = if_usb_resume,
.reset_resume = if_usb_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(if_usb_driver);
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c
index 7ced130f4f9e..19a5a92dd779 100644
--- a/drivers/net/wireless/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/libertas_tf/if_usb.c
@@ -920,6 +920,7 @@ static struct usb_driver if_usb_driver = {
.id_table = if_usb_table,
.suspend = if_usb_suspend,
.resume = if_usb_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(if_usb_driver);
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index f634d4582bfe..7f53cea2f205 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -1752,6 +1752,7 @@ static struct usb_driver orinoco_driver = {
.probe = ezusb_probe,
.disconnect = ezusb_disconnect,
.id_table = ezusb_table,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(orinoco_driver);
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index e1eac830e2fc..7f207b6e9552 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -1140,6 +1140,7 @@ static struct usb_driver p54u_driver = {
.reset_resume = p54u_resume,
#endif /* CONFIG_PM */
.soft_unbind = 1,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(p54u_driver);
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index b91d1bb30b41..c5404eb82b2f 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -3765,6 +3765,7 @@ static struct usb_driver rndis_wlan_driver = {
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(rndis_wlan_driver);
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index c88fd3e61090..669aecdb411d 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1980,6 +1980,7 @@ static struct usb_driver rt2500usb_driver = {
.disconnect = rt2x00usb_disconnect,
.suspend = rt2x00usb_suspend,
.resume = rt2x00usb_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(rt2500usb_driver);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 5601302d09ad..bf78317a6adb 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -1302,6 +1302,7 @@ static struct usb_driver rt2800usb_driver = {
.disconnect = rt2x00usb_disconnect,
.suspend = rt2x00usb_suspend,
.resume = rt2x00usb_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(rt2800usb_driver);
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 155136691a38..77ccbbc7da41 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2527,6 +2527,7 @@ static struct usb_driver rt73usb_driver = {
.disconnect = rt2x00usb_disconnect,
.suspend = rt2x00usb_suspend,
.resume = rt2x00usb_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(rt73usb_driver);
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index d8114962b0c9..4fb1ca1b86b9 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -1663,6 +1663,7 @@ static struct usb_driver rtl8187_driver = {
.id_table = rtl8187_table,
.probe = rtl8187_probe,
.disconnect = __devexit_p(rtl8187_disconnect),
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(rtl8187_driver);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
index 7737fb0c6661..d228358e6a40 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -373,6 +373,7 @@ static struct usb_driver rtl8192cu_driver = {
#ifdef CONFIG_AUTOSUSPEND
.supports_autosuspend = 1,
#endif
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(rtl8192cu_driver);
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
index a66b93b7ff9a..48273dd05b63 100644
--- a/drivers/net/wireless/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -1905,6 +1905,7 @@ static struct usb_driver zd1201_usb = {
.id_table = zd1201_table,
.suspend = zd1201_suspend,
.resume = zd1201_resume,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(zd1201_usb);
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index f766b3e67c6d..af83c43bcdb1 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -1542,6 +1542,7 @@ static struct usb_driver driver = {
.disconnect = disconnect,
.pre_reset = pre_reset,
.post_reset = post_reset,
+ .disable_hub_initiated_lpm = 1,
};
struct workqueue_struct *zd_workqueue;
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 66d96f14c274..7e262a6124c5 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -1,4 +1,5 @@
+#include <linux/device.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/module.h>
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 580644986945..d9bfd49b1935 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1260,3 +1260,44 @@ int of_alias_get_id(struct device_node *np, const char *stem)
return id;
}
EXPORT_SYMBOL_GPL(of_alias_get_id);
+
+const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
+ u32 *pu)
+{
+ const void *curv = cur;
+
+ if (!prop)
+ return NULL;
+
+ if (!cur) {
+ curv = prop->value;
+ goto out_val;
+ }
+
+ curv += sizeof(*cur);
+ if (curv >= prop->value + prop->length)
+ return NULL;
+
+out_val:
+ *pu = be32_to_cpup(curv);
+ return curv;
+}
+EXPORT_SYMBOL_GPL(of_prop_next_u32);
+
+const char *of_prop_next_string(struct property *prop, const char *cur)
+{
+ const void *curv = cur;
+
+ if (!prop)
+ return NULL;
+
+ if (!cur)
+ return prop->value;
+
+ curv += strlen(cur) + 1;
+ if (curv >= prop->value + prop->length)
+ return NULL;
+
+ return curv;
+}
+EXPORT_SYMBOL_GPL(of_prop_next_string);
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index e3b76d409dee..5003458980d3 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -348,7 +348,7 @@ int superio_fixup_irq(struct pci_dev *pcidev)
BUG();
return -1;
}
- printk("superio_fixup_irq(%s) ven 0x%x dev 0x%x from %p\n",
+ printk("superio_fixup_irq(%s) ven 0x%x dev 0x%x from %pf\n",
pci_name(pcidev),
pcidev->vendor, pcidev->device,
__builtin_return_address(0));
diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c
index 8bef6d60f88b..ee78e0ee6e05 100644
--- a/drivers/parport/parport_amiga.c
+++ b/drivers/parport/parport_amiga.c
@@ -48,23 +48,6 @@ static unsigned char amiga_read_data(struct parport *p)
return ciaa.prb;
}
-#if 0
-static unsigned char control_pc_to_amiga(unsigned char control)
-{
- unsigned char ret = 0;
-
- if (control & PARPORT_CONTROL_SELECT) /* XXX: What is SELECP? */
- ;
- if (control & PARPORT_CONTROL_INIT) /* INITP */
- /* reset connected to cpu reset pin */;
- if (control & PARPORT_CONTROL_AUTOFD) /* AUTOLF */
- /* Not connected */;
- if (control & PARPORT_CONTROL_STROBE) /* Strobe */
- /* Handled only directly by hardware */;
- return ret;
-}
-#endif
-
static unsigned char control_amiga_to_pc(unsigned char control)
{
return PARPORT_CONTROL_SELECT |
@@ -95,25 +78,6 @@ static unsigned char amiga_frob_control( struct parport *p, unsigned char mask,
return old;
}
-#if 0 /* currently unused */
-static unsigned char status_pc_to_amiga(unsigned char status)
-{
- unsigned char ret = 1;
-
- if (status & PARPORT_STATUS_BUSY) /* Busy */
- ret &= ~1;
- if (status & PARPORT_STATUS_ACK) /* Ack */
- /* handled in hardware */;
- if (status & PARPORT_STATUS_PAPEROUT) /* PaperOut */
- ret |= 2;
- if (status & PARPORT_STATUS_SELECT) /* select */
- ret |= 4;
- if (status & PARPORT_STATUS_ERROR) /* error */
- /* not connected */;
- return ret;
-}
-#endif
-
static unsigned char status_amiga_to_pc(unsigned char status)
{
unsigned char ret = PARPORT_STATUS_BUSY | PARPORT_STATUS_ACK | PARPORT_STATUS_ERROR;
diff --git a/drivers/parport/parport_atari.c b/drivers/parport/parport_atari.c
index 0b28fccec03f..7ad59ac68cf6 100644
--- a/drivers/parport/parport_atari.c
+++ b/drivers/parport/parport_atari.c
@@ -130,15 +130,6 @@ parport_atari_data_forward(struct parport *p)
static void
parport_atari_data_reverse(struct parport *p)
{
-#if 0 /* too dangerous, can kill sound chip */
- unsigned long flags;
-
- local_irq_save(flags);
- /* Soundchip port B as input. */
- sound_ym.rd_data_reg_sel = 7;
- sound_ym.wd_data = sound_ym.rd_data_reg_sel & ~0x40;
- local_irq_restore(flags);
-#endif
}
static struct parport_operations parport_atari_ops = {
diff --git a/drivers/parport/parport_mfc3.c b/drivers/parport/parport_mfc3.c
index 1c0c642b3e23..7578d79b3688 100644
--- a/drivers/parport/parport_mfc3.c
+++ b/drivers/parport/parport_mfc3.c
@@ -147,25 +147,6 @@ DPRINTK(KERN_DEBUG "frob_control mask %02x, value %02x\n",mask,val);
return old;
}
-#if 0 /* currently unused */
-static unsigned char status_pc_to_mfc3(unsigned char status)
-{
- unsigned char ret = 1;
-
- if (status & PARPORT_STATUS_BUSY) /* Busy */
- ret &= ~1;
- if (status & PARPORT_STATUS_ACK) /* Ack */
- ret |= 8;
- if (status & PARPORT_STATUS_PAPEROUT) /* PaperOut */
- ret |= 2;
- if (status & PARPORT_STATUS_SELECT) /* select */
- ret |= 4;
- if (status & PARPORT_STATUS_ERROR) /* error */
- ret |= 16;
- return ret;
-}
-#endif
-
static unsigned char status_mfc3_to_pc(unsigned char status)
{
unsigned char ret = PARPORT_STATUS_BUSY;
@@ -184,14 +165,6 @@ static unsigned char status_mfc3_to_pc(unsigned char status)
return ret;
}
-#if 0 /* currently unused */
-static void mfc3_write_status( struct parport *p, unsigned char status)
-{
-DPRINTK(KERN_DEBUG "write_status %02x\n",status);
- pia(p)->ppra = (pia(p)->ppra & 0xe0) | status_pc_to_mfc3(status);
-}
-#endif
-
static unsigned char mfc3_read_status(struct parport *p)
{
unsigned char status;
@@ -201,14 +174,6 @@ DPRINTK(KERN_DEBUG "read_status %02x\n", status);
return status;
}
-#if 0 /* currently unused */
-static void mfc3_change_mode( struct parport *p, int m)
-{
- /* XXX: This port only has one mode, and I am
- not sure about the corresponding PC-style mode*/
-}
-#endif
-
static int use_cnt = 0;
static irqreturn_t mfc3_interrupt(int irq, void *dev_id)
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 0cb64f50cecd..5abffe58a9d2 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -197,54 +197,6 @@ static int change_mode(struct parport *p, int m)
ECR_WRITE(p, oecr);
return 0;
}
-
-#ifdef CONFIG_PARPORT_1284
-/* Find FIFO lossage; FIFO is reset */
-#if 0
-static int get_fifo_residue(struct parport *p)
-{
- int residue;
- int cnfga;
- const struct parport_pc_private *priv = p->physport->private_data;
-
- /* Adjust for the contents of the FIFO. */
- for (residue = priv->fifo_depth; ; residue--) {
- if (inb(ECONTROL(p)) & 0x2)
- /* Full up. */
- break;
-
- outb(0, FIFO(p));
- }
-
- printk(KERN_DEBUG "%s: %d PWords were left in FIFO\n", p->name,
- residue);
-
- /* Reset the FIFO. */
- frob_set_mode(p, ECR_PS2);
-
- /* Now change to config mode and clean up. FIXME */
- frob_set_mode(p, ECR_CNF);
- cnfga = inb(CONFIGA(p));
- printk(KERN_DEBUG "%s: cnfgA contains 0x%02x\n", p->name, cnfga);
-
- if (!(cnfga & (1<<2))) {
- printk(KERN_DEBUG "%s: Accounting for extra byte\n", p->name);
- residue++;
- }
-
- /* Don't care about partial PWords until support is added for
- * PWord != 1 byte. */
-
- /* Back to PS2 mode. */
- frob_set_mode(p, ECR_PS2);
-
- DPRINTK(KERN_DEBUG
- "*** get_fifo_residue: done residue collecting (ecr = 0x%2.2x)\n",
- inb(ECONTROL(p)));
- return residue;
-}
-#endif /* 0 */
-#endif /* IEEE 1284 support */
#endif /* FIFO support */
/*
@@ -940,234 +892,6 @@ static size_t parport_pc_ecp_write_block_pio(struct parport *port,
return written;
}
-
-#if 0
-static size_t parport_pc_ecp_read_block_pio(struct parport *port,
- void *buf, size_t length,
- int flags)
-{
- size_t left = length;
- size_t fifofull;
- int r;
- const int fifo = FIFO(port);
- const struct parport_pc_private *priv = port->physport->private_data;
- const int fifo_depth = priv->fifo_depth;
- char *bufp = buf;
-
- port = port->physport;
- DPRINTK(KERN_DEBUG "parport_pc: parport_pc_ecp_read_block_pio\n");
- dump_parport_state("enter fcn", port);
-
- /* Special case: a timeout of zero means we cannot call schedule().
- * Also if O_NONBLOCK is set then use the default implementation. */
- if (port->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK)
- return parport_ieee1284_ecp_read_data(port, buf,
- length, flags);
-
- if (port->ieee1284.mode == IEEE1284_MODE_ECPRLE) {
- /* If the peripheral is allowed to send RLE compressed
- * data, it is possible for a byte to expand to 128
- * bytes in the FIFO. */
- fifofull = 128;
- } else {
- fifofull = fifo_depth;
- }
-
- /* If the caller wants less than a full FIFO's worth of data,
- * go through software emulation. Otherwise we may have to throw
- * away data. */
- if (length < fifofull)
- return parport_ieee1284_ecp_read_data(port, buf,
- length, flags);
-
- if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE) {
- /* change to reverse-idle phase (must be in forward-idle) */
-
- /* Event 38: Set nAutoFd low (also make sure nStrobe is high) */
- parport_frob_control(port,
- PARPORT_CONTROL_AUTOFD
- | PARPORT_CONTROL_STROBE,
- PARPORT_CONTROL_AUTOFD);
- parport_pc_data_reverse(port); /* Must be in PS2 mode */
- udelay(5);
- /* Event 39: Set nInit low to initiate bus reversal */
- parport_frob_control(port,
- PARPORT_CONTROL_INIT,
- 0);
- /* Event 40: Wait for nAckReverse (PError) to go low */
- r = parport_wait_peripheral(port, PARPORT_STATUS_PAPEROUT, 0);
- if (r) {
- printk(KERN_DEBUG "%s: PE timeout Event 40 (%d) "
- "in ecp_read_block_pio\n", port->name, r);
- return 0;
- }
- }
-
- /* Set up ECP FIFO mode.*/
-/* parport_pc_frob_control(port,
- PARPORT_CONTROL_STROBE |
- PARPORT_CONTROL_AUTOFD,
- PARPORT_CONTROL_AUTOFD); */
- r = change_mode(port, ECR_ECP); /* ECP FIFO */
- if (r)
- printk(KERN_DEBUG "%s: Warning change_mode ECR_ECP failed\n",
- port->name);
-
- port->ieee1284.phase = IEEE1284_PH_REV_DATA;
-
- /* the first byte must be collected manually */
- dump_parport_state("pre 43", port);
- /* Event 43: Wait for nAck to go low */
- r = parport_wait_peripheral(port, PARPORT_STATUS_ACK, 0);
- if (r) {
- /* timed out while reading -- no data */
- printk(KERN_DEBUG "PIO read timed out (initial byte)\n");
- goto out_no_data;
- }
- /* read byte */
- *bufp++ = inb(DATA(port));
- left--;
- dump_parport_state("43-44", port);
- /* Event 44: nAutoFd (HostAck) goes high to acknowledge */
- parport_pc_frob_control(port,
- PARPORT_CONTROL_AUTOFD,
- 0);
- dump_parport_state("pre 45", port);
- /* Event 45: Wait for nAck to go high */
- /* r = parport_wait_peripheral(port, PARPORT_STATUS_ACK,
- PARPORT_STATUS_ACK); */
- dump_parport_state("post 45", port);
- r = 0;
- if (r) {
- /* timed out while waiting for peripheral to respond to ack */
- printk(KERN_DEBUG "ECP PIO read timed out (waiting for nAck)\n");
-
- /* keep hold of the byte we've got already */
- goto out_no_data;
- }
- /* Event 46: nAutoFd (HostAck) goes low to accept more data */
- parport_pc_frob_control(port,
- PARPORT_CONTROL_AUTOFD,
- PARPORT_CONTROL_AUTOFD);
-
-
- dump_parport_state("rev idle", port);
- /* Do the transfer. */
- while (left > fifofull) {
- int ret;
- unsigned long expire = jiffies + port->cad->timeout;
- unsigned char ecrval = inb(ECONTROL(port));
-
- if (need_resched() && time_before(jiffies, expire))
- /* Can't yield the port. */
- schedule();
-
- /* At this point, the FIFO may already be full. In
- * that case ECP is already holding back the
- * peripheral (assuming proper design) with a delayed
- * handshake. Work fast to avoid a peripheral
- * timeout. */
-
- if (ecrval & 0x01) {
- /* FIFO is empty. Wait for interrupt. */
- dump_parport_state("FIFO empty", port);
-
- /* Anyone else waiting for the port? */
- if (port->waithead) {
- printk(KERN_DEBUG "Somebody wants the port\n");
- break;
- }
-
- /* Clear serviceIntr */
- ECR_WRITE(port, ecrval & ~(1<<2));
-false_alarm:
- dump_parport_state("waiting", port);
- ret = parport_wait_event(port, HZ);
- DPRINTK(KERN_DEBUG "parport_wait_event returned %d\n",
- ret);
- if (ret < 0)
- break;
- ret = 0;
- if (!time_before(jiffies, expire)) {
- /* Timed out. */
- dump_parport_state("timeout", port);
- printk(KERN_DEBUG "PIO read timed out\n");
- break;
- }
- ecrval = inb(ECONTROL(port));
- if (!(ecrval & (1<<2))) {
- if (need_resched() &&
- time_before(jiffies, expire)) {
- schedule();
- }
- goto false_alarm;
- }
-
- /* Depending on how the FIFO threshold was
- * set, how long interrupt service took, and
- * how fast the peripheral is, we might be
- * lucky and have a just filled FIFO. */
- continue;
- }
-
- if (ecrval & 0x02) {
- /* FIFO is full. */
- dump_parport_state("FIFO full", port);
- insb(fifo, bufp, fifo_depth);
- bufp += fifo_depth;
- left -= fifo_depth;
- continue;
- }
-
- DPRINTK(KERN_DEBUG
- "*** ecp_read_block_pio: reading one byte from the FIFO\n");
-
- /* FIFO not filled. We will cycle this loop for a while
- * and either the peripheral will fill it faster,
- * tripping a fast empty with insb, or we empty it. */
- *bufp++ = inb(fifo);
- left--;
- }
-
- /* scoop up anything left in the FIFO */
- while (left && !(inb(ECONTROL(port) & 0x01))) {
- *bufp++ = inb(fifo);
- left--;
- }
-
- port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
- dump_parport_state("rev idle2", port);
-
-out_no_data:
-
- /* Go to forward idle mode to shut the peripheral up (event 47). */
- parport_frob_control(port, PARPORT_CONTROL_INIT, PARPORT_CONTROL_INIT);
-
- /* event 49: PError goes high */
- r = parport_wait_peripheral(port,
- PARPORT_STATUS_PAPEROUT,
- PARPORT_STATUS_PAPEROUT);
- if (r) {
- printk(KERN_DEBUG
- "%s: PE timeout FWDIDLE (%d) in ecp_read_block_pio\n",
- port->name, r);
- }
-
- port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-
- /* Finish up. */
- {
- int lost = get_fifo_residue(port);
- if (lost)
- /* Shouldn't happen with compliant peripherals. */
- printk(KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n",
- port->name, lost);
- }
-
- dump_parport_state("fwd idle", port);
- return length - left;
-}
-#endif /* 0 */
#endif /* IEEE 1284 support */
#endif /* Allowed to use FIFO/DMA */
@@ -2351,7 +2075,7 @@ struct parport *parport_pc_probe_port(unsigned long int base,
printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
if (p->base_hi && priv->ecr)
- printk(" (0x%lx)", p->base_hi);
+ printk(KERN_CONT " (0x%lx)", p->base_hi);
if (p->irq == PARPORT_IRQ_AUTO) {
p->irq = PARPORT_IRQ_NONE;
parport_irq_probe(p);
@@ -2362,7 +2086,7 @@ struct parport *parport_pc_probe_port(unsigned long int base,
p->irq = PARPORT_IRQ_NONE;
}
if (p->irq != PARPORT_IRQ_NONE) {
- printk(", irq %d", p->irq);
+ printk(KERN_CONT ", irq %d", p->irq);
priv->ctr_writable |= 0x10;
if (p->dma == PARPORT_DMA_AUTO) {
@@ -2386,21 +2110,21 @@ struct parport *parport_pc_probe_port(unsigned long int base,
/* p->ops->ecp_read_data = parport_pc_ecp_read_block_pio; */
#endif /* IEEE 1284 support */
if (p->dma != PARPORT_DMA_NONE) {
- printk(", dma %d", p->dma);
+ printk(KERN_CONT ", dma %d", p->dma);
p->modes |= PARPORT_MODE_DMA;
} else
- printk(", using FIFO");
+ printk(KERN_CONT ", using FIFO");
} else
/* We can't use the DMA channel after all. */
p->dma = PARPORT_DMA_NONE;
#endif /* Allowed to use FIFO/DMA */
- printk(" [");
+ printk(KERN_CONT " [");
#define printmode(x) \
{\
if (p->modes & PARPORT_MODE_##x) {\
- printk("%s%s", f ? "," : "", #x);\
+ printk(KERN_CONT "%s%s", f ? "," : "", #x);\
f++;\
} \
}
@@ -2416,9 +2140,9 @@ struct parport *parport_pc_probe_port(unsigned long int base,
}
#undef printmode
#ifndef CONFIG_PARPORT_1284
- printk("(,...)");
+ printk(KERN_CONT "(,...)");
#endif /* CONFIG_PARPORT_1284 */
- printk("]\n");
+ printk(KERN_CONT "]\n");
if (probedirq != PARPORT_IRQ_NONE)
printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq);
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c
index 9390a534a2b2..983a2d2df659 100644
--- a/drivers/parport/parport_sunbpp.c
+++ b/drivers/parport/parport_sunbpp.c
@@ -82,27 +82,6 @@ static unsigned char parport_sunbpp_read_data(struct parport *p)
return sbus_readb(&regs->p_dr);
}
-#if 0
-static void control_pc_to_sunbpp(struct parport *p, unsigned char status)
-{
- struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
- unsigned char value_tcr = sbus_readb(&regs->p_tcr);
- unsigned char value_or = sbus_readb(&regs->p_or);
-
- if (status & PARPORT_CONTROL_STROBE)
- value_tcr |= P_TCR_DS;
- if (status & PARPORT_CONTROL_AUTOFD)
- value_or |= P_OR_AFXN;
- if (status & PARPORT_CONTROL_INIT)
- value_or |= P_OR_INIT;
- if (status & PARPORT_CONTROL_SELECT)
- value_or |= P_OR_SLCT_IN;
-
- sbus_writeb(value_or, &regs->p_or);
- sbus_writeb(value_tcr, &regs->p_tcr);
-}
-#endif
-
static unsigned char status_sunbpp_to_pc(struct parport *p)
{
struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 165274c064bc..01c001f3b766 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -2,7 +2,7 @@
# Makefile for the PCI bus specific drivers.
#
-obj-y += access.o bus.o probe.o remove.o pci.o \
+obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
irq.o vpd.o
obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
new file mode 100644
index 000000000000..a68dc613a5be
--- /dev/null
+++ b/drivers/pci/host-bridge.c
@@ -0,0 +1,96 @@
+/*
+ * host bridge related code
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+
+#include "pci.h"
+
+static struct pci_bus *find_pci_root_bus(struct pci_dev *dev)
+{
+ struct pci_bus *bus;
+
+ bus = dev->bus;
+ while (bus->parent)
+ bus = bus->parent;
+
+ return bus;
+}
+
+static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev)
+{
+ struct pci_bus *bus = find_pci_root_bus(dev);
+
+ return to_pci_host_bridge(bus->bridge);
+}
+
+void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
+ void (*release_fn)(struct pci_host_bridge *),
+ void *release_data)
+{
+ bridge->release_fn = release_fn;
+ bridge->release_data = release_data;
+}
+
+static bool resource_contains(struct resource *res1, struct resource *res2)
+{
+ return res1->start <= res2->start && res1->end >= res2->end;
+}
+
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ struct pci_host_bridge *bridge = find_pci_host_bridge(dev);
+ struct pci_host_bridge_window *window;
+ resource_size_t offset = 0;
+
+ list_for_each_entry(window, &bridge->windows, list) {
+ if (resource_type(res) != resource_type(window->res))
+ continue;
+
+ if (resource_contains(window->res, res)) {
+ offset = window->offset;
+ break;
+ }
+ }
+
+ region->start = res->start - offset;
+ region->end = res->end - offset;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+static bool region_contains(struct pci_bus_region *region1,
+ struct pci_bus_region *region2)
+{
+ return region1->start <= region2->start && region1->end >= region2->end;
+}
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ struct pci_host_bridge *bridge = find_pci_host_bridge(dev);
+ struct pci_host_bridge_window *window;
+ resource_size_t offset = 0;
+
+ list_for_each_entry(window, &bridge->windows, list) {
+ struct pci_bus_region bus_region;
+
+ if (resource_type(res) != resource_type(window->res))
+ continue;
+
+ bus_region.start = window->res->start - window->offset;
+ bus_region.end = window->res->end - window->offset;
+
+ if (region_contains(&bus_region, region)) {
+ offset = window->offset;
+ break;
+ }
+ }
+
+ res->start = region->start + offset;
+ res->end = region->end + offset;
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 1929c0c63b75..61e2fefeedab 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -223,7 +223,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
[PCI_D0] = ACPI_STATE_D0,
[PCI_D1] = ACPI_STATE_D1,
[PCI_D2] = ACPI_STATE_D2,
- [PCI_D3hot] = ACPI_STATE_D3_HOT,
+ [PCI_D3hot] = ACPI_STATE_D3,
[PCI_D3cold] = ACPI_STATE_D3
};
int error = -EINVAL;
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 6b54b23b990b..bf0cee629b60 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -421,6 +421,12 @@ static void pci_device_shutdown(struct device *dev)
pci_msix_shutdown(pci_dev);
/*
+ * Turn off Bus Master bit on the device to tell it to not
+ * continue to do DMA
+ */
+ pci_disable_device(pci_dev);
+
+ /*
* Devices may be enabled to wake up by runtime PM, but they need not
* be supposed to wake up the system from its "power off" state (e.g.
* ACPI S5). Therefore disable wakeup for all devices that aren't
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 111569ccab43..8f169002dc7e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -22,6 +22,7 @@
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/pm_runtime.h>
+#include <asm-generic/pci-bridge.h>
#include <asm/setup.h>
#include "pci.h"
@@ -3164,18 +3165,12 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe)
return 0;
}
-static int pci_dev_reset(struct pci_dev *dev, int probe)
+static int __pci_dev_reset(struct pci_dev *dev, int probe)
{
int rc;
might_sleep();
- if (!probe) {
- pci_cfg_access_lock(dev);
- /* block PM suspend, driver probe, etc. */
- device_lock(&dev->dev);
- }
-
rc = pci_dev_specific_reset(dev, probe);
if (rc != -ENOTTY)
goto done;
@@ -3194,14 +3189,27 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
rc = pci_parent_bus_reset(dev, probe);
done:
+ return rc;
+}
+
+static int pci_dev_reset(struct pci_dev *dev, int probe)
+{
+ int rc;
+
+ if (!probe) {
+ pci_cfg_access_lock(dev);
+ /* block PM suspend, driver probe, etc. */
+ device_lock(&dev->dev);
+ }
+
+ rc = __pci_dev_reset(dev, probe);
+
if (!probe) {
device_unlock(&dev->dev);
pci_cfg_access_unlock(dev);
}
-
return rc;
}
-
/**
* __pci_reset_function - reset a PCI device function
* @dev: PCI device to reset
@@ -3246,7 +3254,7 @@ EXPORT_SYMBOL_GPL(__pci_reset_function);
*/
int __pci_reset_function_locked(struct pci_dev *dev)
{
- return pci_dev_reset(dev, 1);
+ return __pci_dev_reset(dev, 0);
}
EXPORT_SYMBOL_GPL(__pci_reset_function_locked);
@@ -3893,6 +3901,8 @@ static int __init pci_setup(char *str)
pcie_bus_config = PCIE_BUS_PERFORMANCE;
} else if (!strncmp(str, "pcie_bus_peer2peer", 18)) {
pcie_bus_config = PCIE_BUS_PEER2PEER;
+ } else if (!strncmp(str, "pcie_scan_all", 13)) {
+ pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS);
} else {
printk(KERN_ERR "PCI: Unknown option `%s'\n",
str);
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 2f589a54f9bd..75915b30ad19 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -249,7 +249,7 @@ static int get_port_device_capability(struct pci_dev *dev)
int services = 0, pos;
u16 reg16;
u32 reg32;
- int cap_mask;
+ int cap_mask = 0;
int err;
if (pcie_ports_disabled)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5e1ca3c58a7d..658ac977cb56 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -10,18 +10,16 @@
#include <linux/module.h>
#include <linux/cpumask.h>
#include <linux/pci-aspm.h>
+#include <asm-generic/pci-bridge.h>
#include "pci.h"
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
#define CARDBUS_RESERVE_BUSNR 3
-static LIST_HEAD(pci_host_bridges);
-
/* Ugh. Need to stop exporting this to modules. */
LIST_HEAD(pci_root_buses);
EXPORT_SYMBOL(pci_root_buses);
-
static int find_anything(struct device *dev, void *data)
{
return 1;
@@ -44,82 +42,6 @@ int no_pci_devices(void)
}
EXPORT_SYMBOL(no_pci_devices);
-static struct pci_host_bridge *pci_host_bridge(struct pci_dev *dev)
-{
- struct pci_bus *bus;
- struct pci_host_bridge *bridge;
-
- bus = dev->bus;
- while (bus->parent)
- bus = bus->parent;
-
- list_for_each_entry(bridge, &pci_host_bridges, list) {
- if (bridge->bus == bus)
- return bridge;
- }
-
- return NULL;
-}
-
-static bool resource_contains(struct resource *res1, struct resource *res2)
-{
- return res1->start <= res2->start && res1->end >= res2->end;
-}
-
-void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
- struct resource *res)
-{
- struct pci_host_bridge *bridge = pci_host_bridge(dev);
- struct pci_host_bridge_window *window;
- resource_size_t offset = 0;
-
- list_for_each_entry(window, &bridge->windows, list) {
- if (resource_type(res) != resource_type(window->res))
- continue;
-
- if (resource_contains(window->res, res)) {
- offset = window->offset;
- break;
- }
- }
-
- region->start = res->start - offset;
- region->end = res->end - offset;
-}
-EXPORT_SYMBOL(pcibios_resource_to_bus);
-
-static bool region_contains(struct pci_bus_region *region1,
- struct pci_bus_region *region2)
-{
- return region1->start <= region2->start && region1->end >= region2->end;
-}
-
-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
- struct pci_bus_region *region)
-{
- struct pci_host_bridge *bridge = pci_host_bridge(dev);
- struct pci_host_bridge_window *window;
- struct pci_bus_region bus_region;
- resource_size_t offset = 0;
-
- list_for_each_entry(window, &bridge->windows, list) {
- if (resource_type(res) != resource_type(window->res))
- continue;
-
- bus_region.start = window->res->start - window->offset;
- bus_region.end = window->res->end - window->offset;
-
- if (region_contains(&bus_region, region)) {
- offset = window->offset;
- break;
- }
- }
-
- res->start = region->start + offset;
- res->end = region->end + offset;
-}
-EXPORT_SYMBOL(pcibios_bus_to_resource);
-
/*
* PCI Bus Class
*/
@@ -501,6 +423,19 @@ static struct pci_bus * pci_alloc_bus(void)
return b;
}
+static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
+{
+ struct pci_host_bridge *bridge;
+
+ bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
+ if (bridge) {
+ INIT_LIST_HEAD(&bridge->windows);
+ bridge->bus = b;
+ }
+
+ return bridge;
+}
+
static unsigned char pcix_bus_speed[] = {
PCI_SPEED_UNKNOWN, /* 0 */
PCI_SPEED_66MHz_PCIX, /* 1 */
@@ -1201,7 +1136,14 @@ int pci_cfg_space_size(struct pci_dev *dev)
static void pci_release_bus_bridge_dev(struct device *dev)
{
- kfree(dev);
+ struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
+
+ if (bridge->release_fn)
+ bridge->release_fn(bridge);
+
+ pci_free_resource_list(&bridge->windows);
+
+ kfree(bridge);
}
struct pci_dev *alloc_pci_dev(void)
@@ -1395,10 +1337,13 @@ static unsigned no_next_fn(struct pci_dev *dev, unsigned fn)
static int only_one_child(struct pci_bus *bus)
{
struct pci_dev *parent = bus->self;
+
if (!parent || !pci_is_pcie(parent))
return 0;
- if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
- parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
+ if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
+ return 1;
+ if (parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM &&
+ !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS))
return 1;
return 0;
}
@@ -1650,28 +1595,19 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
int error;
struct pci_host_bridge *bridge;
struct pci_bus *b, *b2;
- struct device *dev;
struct pci_host_bridge_window *window, *n;
struct resource *res;
resource_size_t offset;
char bus_addr[64];
char *fmt;
- bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
- if (!bridge)
- return NULL;
b = pci_alloc_bus();
if (!b)
- goto err_bus;
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- goto err_dev;
+ return NULL;
b->sysdata = sysdata;
b->ops = ops;
-
b2 = pci_find_bus(pci_domain_nr(b), bus);
if (b2) {
/* If we already got to this bus through a different bridge, ignore it */
@@ -1679,13 +1615,17 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
goto err_out;
}
- dev->parent = parent;
- dev->release = pci_release_bus_bridge_dev;
- dev_set_name(dev, "pci%04x:%02x", pci_domain_nr(b), bus);
- error = device_register(dev);
+ bridge = pci_alloc_host_bridge(b);
+ if (!bridge)
+ goto err_out;
+
+ bridge->dev.parent = parent;
+ bridge->dev.release = pci_release_bus_bridge_dev;
+ dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
+ error = device_register(&bridge->dev);
if (error)
- goto dev_reg_err;
- b->bridge = get_device(dev);
+ goto bridge_dev_reg_err;
+ b->bridge = get_device(&bridge->dev);
device_enable_async_suspend(b->bridge);
pci_set_bus_of_node(b);
@@ -1704,9 +1644,6 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
b->number = b->secondary = bus;
- bridge->bus = b;
- INIT_LIST_HEAD(&bridge->windows);
-
if (parent)
dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
else
@@ -1732,25 +1669,18 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
}
down_write(&pci_bus_sem);
- list_add_tail(&bridge->list, &pci_host_bridges);
list_add_tail(&b->node, &pci_root_buses);
up_write(&pci_bus_sem);
return b;
class_dev_reg_err:
- device_unregister(dev);
-dev_reg_err:
- down_write(&pci_bus_sem);
- list_del(&bridge->list);
- list_del(&b->node);
- up_write(&pci_bus_sem);
+ put_device(&bridge->dev);
+ device_unregister(&bridge->dev);
+bridge_dev_reg_err:
+ kfree(bridge);
err_out:
- kfree(dev);
-err_dev:
kfree(b);
-err_bus:
- kfree(bridge);
return NULL;
}
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 953ec3f08470..2a7521677541 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3097,16 +3097,74 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)
return 0;
}
+#include "../gpu/drm/i915/i915_reg.h"
+#define MSG_CTL 0x45010
+#define NSDE_PWR_STATE 0xd0100
+#define IGD_OPERATION_TIMEOUT 10000 /* set timeout 10 seconds */
+
+static int reset_ivb_igd(struct pci_dev *dev, int probe)
+{
+ void __iomem *mmio_base;
+ unsigned long timeout;
+ u32 val;
+
+ if (probe)
+ return 0;
+
+ mmio_base = pci_iomap(dev, 0, 0);
+ if (!mmio_base)
+ return -ENOMEM;
+
+ iowrite32(0x00000002, mmio_base + MSG_CTL);
+
+ /*
+ * Clobbering SOUTH_CHICKEN2 register is fine only if the next
+ * driver loaded sets the right bits. However, this's a reset and
+ * the bits have been set by i915 previously, so we clobber
+ * SOUTH_CHICKEN2 register directly here.
+ */
+ iowrite32(0x00000005, mmio_base + SOUTH_CHICKEN2);
+
+ val = ioread32(mmio_base + PCH_PP_CONTROL) & 0xfffffffe;
+ iowrite32(val, mmio_base + PCH_PP_CONTROL);
+
+ timeout = jiffies + msecs_to_jiffies(IGD_OPERATION_TIMEOUT);
+ do {
+ val = ioread32(mmio_base + PCH_PP_STATUS);
+ if ((val & 0xb0000000) == 0)
+ goto reset_complete;
+ msleep(10);
+ } while (time_before(jiffies, timeout));
+ dev_warn(&dev->dev, "timeout during reset\n");
+
+reset_complete:
+ iowrite32(0x00000002, mmio_base + NSDE_PWR_STATE);
+
+ pci_iounmap(dev, mmio_base);
+ return 0;
+}
+
#define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed
+#define PCI_DEVICE_ID_INTEL_IVB_M_VGA 0x0156
+#define PCI_DEVICE_ID_INTEL_IVB_M2_VGA 0x0166
static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
reset_intel_82599_sfp_virtfn },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M_VGA,
+ reset_ivb_igd },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M2_VGA,
+ reset_ivb_igd },
{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
reset_intel_generic_dev },
{ 0 }
};
+/*
+ * These device-specific reset methods are here rather than in a driver
+ * because when a host assigns a device to a guest VM, the host may need
+ * to reset the device but probably doesn't have a driver for it.
+ */
int pci_dev_specific_reset(struct pci_dev *dev, int probe)
{
const struct pci_dev_reset_methods *i;
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index bba3ab2066ee..8fd255f7ee40 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -217,7 +217,7 @@ config PCMCIA_PXA2XX
|| MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \
|| ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \
|| MACH_VPAC270 || MACH_BALLOON3 || MACH_COLIBRI \
- || MACH_COLIBRI320)
+ || MACH_COLIBRI320 || MACH_H4700)
select PCMCIA_SA1111 if ARCH_LUBBOCK && SA1111
select PCMCIA_SOC_COMMON
help
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 47525de6a631..7745b512a87c 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -69,6 +69,7 @@ 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
+pxa2xx-obj-$(CONFIG_MACH_H4700) += pxa2xx_hx4700.o
obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y)
diff --git a/drivers/pcmcia/pxa2xx_hx4700.c b/drivers/pcmcia/pxa2xx_hx4700.c
new file mode 100644
index 000000000000..7dfef3ee5b53
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_hx4700.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 Paul Parsons <lost.distance@yahoo.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/err.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <mach/hx4700.h>
+
+#include "soc_common.h"
+
+static struct gpio gpios[] = {
+ { GPIO114_HX4700_CF_RESET, GPIOF_OUT_INIT_LOW, "CF reset" },
+ { EGPIO4_CF_3V3_ON, GPIOF_OUT_INIT_LOW, "CF 3.3V enable" },
+};
+
+static int hx4700_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+ int ret;
+
+ ret = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+ if (ret)
+ goto out;
+
+ /*
+ * IRQ type must be set before soc_pcmcia_hw_init() calls request_irq().
+ * The asic3 default IRQ type is level trigger low level detect, exactly
+ * the the signal present on GPIOD4_CF_nCD when a CF card is inserted.
+ * If the IRQ type is not changed, the asic3 interrupt handler will loop
+ * repeatedly because it is unable to clear the level trigger interrupt.
+ */
+ irq_set_irq_type(gpio_to_irq(GPIOD4_CF_nCD), IRQ_TYPE_EDGE_BOTH);
+
+ skt->stat[SOC_STAT_CD].gpio = GPIOD4_CF_nCD;
+ skt->stat[SOC_STAT_CD].name = "PCMCIA CD";
+ skt->stat[SOC_STAT_RDY].gpio = GPIO60_HX4700_CF_RNB;
+ skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready";
+
+out:
+ return ret;
+}
+
+static void hx4700_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+ gpio_free_array(gpios, ARRAY_SIZE(gpios));
+}
+
+static void hx4700_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+ struct pcmcia_state *state)
+{
+ state->vs_3v = 1;
+ state->vs_Xv = 0;
+}
+
+static int hx4700_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+ const socket_state_t *state)
+{
+ switch (state->Vcc) {
+ case 0:
+ gpio_set_value(EGPIO4_CF_3V3_ON, 0);
+ break;
+ case 33:
+ gpio_set_value(EGPIO4_CF_3V3_ON, 1);
+ break;
+ default:
+ printk(KERN_ERR "pcmcia: Unsupported Vcc: %d\n", state->Vcc);
+ return -EINVAL;
+ }
+
+ gpio_set_value(GPIO114_HX4700_CF_RESET, (state->flags & SS_RESET) != 0);
+
+ return 0;
+}
+
+static struct pcmcia_low_level hx4700_pcmcia_ops = {
+ .owner = THIS_MODULE,
+ .nr = 1,
+ .hw_init = hx4700_pcmcia_hw_init,
+ .hw_shutdown = hx4700_pcmcia_hw_shutdown,
+ .socket_state = hx4700_pcmcia_socket_state,
+ .configure_socket = hx4700_pcmcia_configure_socket,
+};
+
+static struct platform_device *hx4700_pcmcia_device;
+
+static int __init hx4700_pcmcia_init(void)
+{
+ struct platform_device *pdev;
+
+ if (!machine_is_h4700())
+ return -ENODEV;
+
+ pdev = platform_device_register_data(NULL, "pxa2xx-pcmcia", -1,
+ &hx4700_pcmcia_ops, sizeof(hx4700_pcmcia_ops));
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+ hx4700_pcmcia_device = pdev;
+
+ return 0;
+}
+
+static void __exit hx4700_pcmcia_exit(void)
+{
+ platform_device_unregister(hx4700_pcmcia_device);
+}
+
+module_init(hx4700_pcmcia_init);
+module_exit(hx4700_pcmcia_exit);
+
+MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>");
+MODULE_DESCRIPTION("HP iPAQ hx4700 PCMCIA driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index abfb96408779..c6e6ae0aa3b1 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -4,7 +4,6 @@
config PINCTRL
bool
- depends on EXPERIMENTAL
if PINCTRL
@@ -27,6 +26,35 @@ config DEBUG_PINCTRL
help
Say Y here to add some extra checks and diagnostics to PINCTRL calls.
+config PINCTRL_IMX
+ bool
+ select PINMUX
+ select PINCONF
+
+config PINCTRL_IMX51
+ bool "IMX51 pinctrl driver"
+ depends on OF
+ depends on SOC_IMX51
+ select PINCTRL_IMX
+ help
+ Say Y here to enable the imx51 pinctrl driver
+
+config PINCTRL_IMX53
+ bool "IMX53 pinctrl driver"
+ depends on OF
+ depends on SOC_IMX53
+ select PINCTRL_IMX
+ help
+ Say Y here to enable the imx53 pinctrl driver
+
+config PINCTRL_IMX6Q
+ bool "IMX6Q pinctrl driver"
+ depends on OF
+ depends on SOC_IMX6Q
+ select PINCTRL_IMX
+ help
+ Say Y here to enable the imx6q pinctrl driver
+
config PINCTRL_PXA3xx
bool
select PINMUX
@@ -37,6 +65,31 @@ config PINCTRL_MMP2
select PINCTRL_PXA3xx
select PINCONF
+config PINCTRL_MXS
+ bool
+
+config PINCTRL_IMX23
+ bool
+ select PINMUX
+ select PINCONF
+ select PINCTRL_MXS
+
+config PINCTRL_IMX28
+ bool
+ select PINMUX
+ select PINCONF
+ select PINCTRL_MXS
+
+config PINCTRL_NOMADIK
+ bool "Nomadik pin controller driver"
+ depends on ARCH_U8500 || ARCH_NOMADIK
+ select PINMUX
+ select PINCONF
+
+config PINCTRL_DB8500
+ bool "DB8500 pin controller driver"
+ depends on PINCTRL_NOMADIK && ARCH_U8500
+
config PINCTRL_PXA168
bool "PXA168 pin controller driver"
depends on ARCH_MMP
@@ -84,6 +137,8 @@ config PINCTRL_COH901
COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
ports of 8 GPIO pins each.
+source "drivers/pinctrl/spear/Kconfig"
+
endmenu
endif
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 6d4150b4eced..8c074376cdea 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -5,9 +5,21 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG
obj-$(CONFIG_PINCTRL) += core.o
obj-$(CONFIG_PINMUX) += pinmux.o
obj-$(CONFIG_PINCONF) += pinconf.o
+ifeq ($(CONFIG_OF),y)
+obj-$(CONFIG_PINCTRL) += devicetree.o
+endif
obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
+obj-$(CONFIG_PINCTRL_IMX) += pinctrl-imx.o
+obj-$(CONFIG_PINCTRL_IMX51) += pinctrl-imx51.o
+obj-$(CONFIG_PINCTRL_IMX53) += pinctrl-imx53.o
+obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6q.o
obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o
obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o
+obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o
+obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o
+obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o
+obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o
+obj-$(CONFIG_PINCTRL_DB8500) += pinctrl-nomadik-db8500.o
obj-$(CONFIG_PINCTRL_PXA168) += pinctrl-pxa168.o
obj-$(CONFIG_PINCTRL_PXA910) += pinctrl-pxa910.o
obj-$(CONFIG_PINCTRL_SIRF) += pinctrl-sirf.o
@@ -16,3 +28,5 @@ obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
+
+obj-$(CONFIG_PLAT_SPEAR) += spear/
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index df6296c5f47b..c3b331b74fa0 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -23,9 +23,11 @@
#include <linux/sysfs.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/machine.h>
#include "core.h"
+#include "devicetree.h"
#include "pinmux.h"
#include "pinconf.h"
@@ -41,11 +43,13 @@ struct pinctrl_maps {
unsigned num_maps;
};
+static bool pinctrl_dummy_state;
+
/* Mutex taken by all entry points */
DEFINE_MUTEX(pinctrl_mutex);
/* Global list of pin control devices (struct pinctrl_dev) */
-static LIST_HEAD(pinctrldev_list);
+LIST_HEAD(pinctrldev_list);
/* List of pin controller handles (struct pinctrl) */
static LIST_HEAD(pinctrl_list);
@@ -59,6 +63,19 @@ static LIST_HEAD(pinctrl_maps);
_i_ < _maps_node_->num_maps; \
i++, _map_ = &_maps_node_->maps[_i_])
+/**
+ * pinctrl_provide_dummies() - indicate if pinctrl provides dummy state support
+ *
+ * Usually this function is called by platforms without pinctrl driver support
+ * but run with some shared drivers using pinctrl APIs.
+ * After calling this function, the pinctrl core will return successfully
+ * with creating a dummy state for the driver to keep going smoothly.
+ */
+void pinctrl_provide_dummies(void)
+{
+ pinctrl_dummy_state = true;
+}
+
const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev)
{
/* We're not allowed to register devices without name */
@@ -124,6 +141,25 @@ int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name)
}
/**
+ * pin_get_name_from_id() - look up a pin name from a pin id
+ * @pctldev: the pin control device to lookup the pin on
+ * @name: the name of the pin to look up
+ */
+const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin)
+{
+ const struct pin_desc *desc;
+
+ desc = pin_desc_get(pctldev, pin);
+ if (desc == NULL) {
+ dev_err(pctldev->dev, "failed to get pin(%d) name\n",
+ pin);
+ return NULL;
+ }
+
+ return desc->name;
+}
+
+/**
* pin_is_valid() - check if pin exists on controller
* @pctldev: the pin control device to check the pin on
* @pin: pin to check, use the local pin controller index number
@@ -255,7 +291,8 @@ pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio)
*
* Find the pin controller handling a certain GPIO pin from the pinspace of
* the GPIO subsystem, return the device and the matching GPIO range. Returns
- * negative if the GPIO range could not be found in any device.
+ * -EPROBE_DEFER if the GPIO range could not be found in any device since it
+ * may still have not been registered.
*/
static int pinctrl_get_device_gpio_range(unsigned gpio,
struct pinctrl_dev **outdev,
@@ -275,7 +312,7 @@ static int pinctrl_get_device_gpio_range(unsigned gpio,
}
}
- return -EINVAL;
+ return -EPROBE_DEFER;
}
/**
@@ -318,9 +355,10 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
const char *pin_group)
{
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
+ unsigned ngroups = pctlops->get_groups_count(pctldev);
unsigned group_selector = 0;
- while (pctlops->list_groups(pctldev, group_selector) >= 0) {
+ while (group_selector < ngroups) {
const char *gname = pctlops->get_group_name(pctldev,
group_selector);
if (!strcmp(gname, pin_group)) {
@@ -360,7 +398,7 @@ int pinctrl_request_gpio(unsigned gpio)
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
if (ret) {
mutex_unlock(&pinctrl_mutex);
- return -EINVAL;
+ return ret;
}
/* Convert to the pin controllers number space */
@@ -516,11 +554,14 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
setting->pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
if (setting->pctldev == NULL) {
- dev_err(p->dev, "unknown pinctrl device %s in map entry",
+ dev_info(p->dev, "unknown pinctrl device %s in map entry, deferring probe",
map->ctrl_dev_name);
kfree(setting);
- /* Eventually, this should trigger deferred probe */
- return -ENODEV;
+ /*
+ * OK let us guess that the driver is not there yet, and
+ * let's defer obtaining this pinctrl handle to later...
+ */
+ return -EPROBE_DEFER;
}
switch (map->type) {
@@ -579,6 +620,13 @@ static struct pinctrl *create_pinctrl(struct device *dev)
}
p->dev = dev;
INIT_LIST_HEAD(&p->states);
+ INIT_LIST_HEAD(&p->dt_maps);
+
+ ret = pinctrl_dt_to_map(p);
+ if (ret < 0) {
+ kfree(p);
+ return ERR_PTR(ret);
+ }
devname = dev_name(dev);
@@ -662,6 +710,8 @@ static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
kfree(state);
}
+ pinctrl_dt_free_maps(p);
+
if (inlist)
list_del(&p->node);
kfree(p);
@@ -685,8 +735,18 @@ static struct pinctrl_state *pinctrl_lookup_state_locked(struct pinctrl *p,
struct pinctrl_state *state;
state = find_state(p, name);
- if (!state)
- return ERR_PTR(-ENODEV);
+ if (!state) {
+ if (pinctrl_dummy_state) {
+ /* create dummy state */
+ dev_dbg(p->dev, "using pinctrl dummy state (%s)\n",
+ name);
+ state = create_state(p, name);
+ if (IS_ERR(state))
+ return state;
+ } else {
+ return ERR_PTR(-ENODEV);
+ }
+ }
return state;
}
@@ -787,15 +847,63 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
}
EXPORT_SYMBOL_GPL(pinctrl_select_state);
+static void devm_pinctrl_release(struct device *dev, void *res)
+{
+ pinctrl_put(*(struct pinctrl **)res);
+}
+
/**
- * pinctrl_register_mappings() - register a set of pin controller mappings
- * @maps: the pincontrol mappings table to register. This should probably be
- * marked with __initdata so it can be discarded after boot. This
- * function will perform a shallow copy for the mapping entries.
- * @num_maps: the number of maps in the mapping table
+ * struct devm_pinctrl_get() - Resource managed pinctrl_get()
+ * @dev: the device to obtain the handle for
+ *
+ * If there is a need to explicitly destroy the returned struct pinctrl,
+ * devm_pinctrl_put() should be used, rather than plain pinctrl_put().
*/
-int pinctrl_register_mappings(struct pinctrl_map const *maps,
- unsigned num_maps)
+struct pinctrl *devm_pinctrl_get(struct device *dev)
+{
+ struct pinctrl **ptr, *p;
+
+ ptr = devres_alloc(devm_pinctrl_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ p = pinctrl_get(dev);
+ if (!IS_ERR(p)) {
+ *ptr = p;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return p;
+}
+EXPORT_SYMBOL_GPL(devm_pinctrl_get);
+
+static int devm_pinctrl_match(struct device *dev, void *res, void *data)
+{
+ struct pinctrl **p = res;
+
+ return *p == data;
+}
+
+/**
+ * devm_pinctrl_put() - Resource managed pinctrl_put()
+ * @p: the pinctrl handle to release
+ *
+ * Deallocate a struct pinctrl obtained via devm_pinctrl_get(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_pinctrl_put(struct pinctrl *p)
+{
+ WARN_ON(devres_destroy(p->dev, devm_pinctrl_release,
+ devm_pinctrl_match, p));
+ pinctrl_put(p);
+}
+EXPORT_SYMBOL_GPL(devm_pinctrl_put);
+
+int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
+ bool dup, bool locked)
{
int i, ret;
struct pinctrl_maps *maps_node;
@@ -829,13 +937,13 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
case PIN_MAP_TYPE_MUX_GROUP:
ret = pinmux_validate_map(&maps[i], i);
if (ret < 0)
- return 0;
+ return ret;
break;
case PIN_MAP_TYPE_CONFIGS_PIN:
case PIN_MAP_TYPE_CONFIGS_GROUP:
ret = pinconf_validate_map(&maps[i], i);
if (ret < 0)
- return 0;
+ return ret;
break;
default:
pr_err("failed to register map %s (%d): invalid type given\n",
@@ -851,20 +959,52 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
}
maps_node->num_maps = num_maps;
- maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps, GFP_KERNEL);
- if (!maps_node->maps) {
- pr_err("failed to duplicate mapping table\n");
- kfree(maps_node);
- return -ENOMEM;
+ if (dup) {
+ maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps,
+ GFP_KERNEL);
+ if (!maps_node->maps) {
+ pr_err("failed to duplicate mapping table\n");
+ kfree(maps_node);
+ return -ENOMEM;
+ }
+ } else {
+ maps_node->maps = maps;
}
- mutex_lock(&pinctrl_mutex);
+ if (!locked)
+ mutex_lock(&pinctrl_mutex);
list_add_tail(&maps_node->node, &pinctrl_maps);
- mutex_unlock(&pinctrl_mutex);
+ if (!locked)
+ mutex_unlock(&pinctrl_mutex);
return 0;
}
+/**
+ * pinctrl_register_mappings() - register a set of pin controller mappings
+ * @maps: the pincontrol mappings table to register. This should probably be
+ * marked with __initdata so it can be discarded after boot. This
+ * function will perform a shallow copy for the mapping entries.
+ * @num_maps: the number of maps in the mapping table
+ */
+int pinctrl_register_mappings(struct pinctrl_map const *maps,
+ unsigned num_maps)
+{
+ return pinctrl_register_map(maps, num_maps, true, false);
+}
+
+void pinctrl_unregister_map(struct pinctrl_map const *map)
+{
+ struct pinctrl_maps *maps_node;
+
+ list_for_each_entry(maps_node, &pinctrl_maps, node) {
+ if (maps_node->maps == map) {
+ list_del(&maps_node->node);
+ return;
+ }
+ }
+}
+
#ifdef CONFIG_DEBUG_FS
static int pinctrl_pins_show(struct seq_file *s, void *what)
@@ -906,15 +1046,17 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
{
struct pinctrl_dev *pctldev = s->private;
const struct pinctrl_ops *ops = pctldev->desc->pctlops;
- unsigned selector = 0;
+ unsigned ngroups, selector = 0;
+ ngroups = ops->get_groups_count(pctldev);
mutex_lock(&pinctrl_mutex);
seq_puts(s, "registered pin groups:\n");
- while (ops->list_groups(pctldev, selector) >= 0) {
+ while (selector < ngroups) {
const unsigned *pins;
unsigned num_pins;
const char *gname = ops->get_group_name(pctldev, selector);
+ const char *pname;
int ret;
int i;
@@ -924,10 +1066,14 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
seq_printf(s, "%s [ERROR GETTING PINS]\n",
gname);
else {
- seq_printf(s, "group: %s, pins = [ ", gname);
- for (i = 0; i < num_pins; i++)
- seq_printf(s, "%d ", pins[i]);
- seq_puts(s, "]\n");
+ seq_printf(s, "group: %s\n", gname);
+ for (i = 0; i < num_pins; i++) {
+ pname = pin_get_name(pctldev, pins[i]);
+ if (WARN_ON(!pname))
+ return -EINVAL;
+ seq_printf(s, "pin %d (%s)\n", pins[i], pname);
+ }
+ seq_puts(s, "\n");
}
selector++;
}
@@ -1226,11 +1372,14 @@ static int pinctrl_check_ops(struct pinctrl_dev *pctldev)
const struct pinctrl_ops *ops = pctldev->desc->pctlops;
if (!ops ||
- !ops->list_groups ||
+ !ops->get_groups_count ||
!ops->get_group_name ||
!ops->get_group_pins)
return -EINVAL;
+ if (ops->dt_node_to_map && !ops->dt_free_map)
+ return -EINVAL;
+
return 0;
}
@@ -1268,37 +1417,29 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
/* check core ops for sanity */
ret = pinctrl_check_ops(pctldev);
if (ret) {
- pr_err("%s pinctrl ops lacks necessary functions\n",
- pctldesc->name);
+ dev_err(dev, "pinctrl ops lacks necessary functions\n");
goto out_err;
}
/* If we're implementing pinmuxing, check the ops for sanity */
if (pctldesc->pmxops) {
ret = pinmux_check_ops(pctldev);
- if (ret) {
- pr_err("%s pinmux ops lacks necessary functions\n",
- pctldesc->name);
+ if (ret)
goto out_err;
- }
}
/* If we're implementing pinconfig, check the ops for sanity */
if (pctldesc->confops) {
ret = pinconf_check_ops(pctldev);
- if (ret) {
- pr_err("%s pin config ops lacks necessary functions\n",
- pctldesc->name);
+ if (ret)
goto out_err;
- }
}
/* Register all the pins */
- pr_debug("try to register %d pins on %s...\n",
- pctldesc->npins, pctldesc->name);
+ dev_dbg(dev, "try to register %d pins ...\n", pctldesc->npins);
ret = pinctrl_register_pins(pctldev, pctldesc->pins, pctldesc->npins);
if (ret) {
- pr_err("error during pin registration\n");
+ dev_err(dev, "error during pin registration\n");
pinctrl_free_pindescs(pctldev, pctldesc->pins,
pctldesc->npins);
goto out_err;
@@ -1313,8 +1454,15 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
struct pinctrl_state *s =
pinctrl_lookup_state_locked(pctldev->p,
PINCTRL_STATE_DEFAULT);
- if (!IS_ERR(s))
- pinctrl_select_state_locked(pctldev->p, s);
+ if (IS_ERR(s)) {
+ dev_dbg(dev, "failed to lookup the default state\n");
+ } else {
+ ret = pinctrl_select_state_locked(pctldev->p, s);
+ if (ret) {
+ dev_err(dev,
+ "failed to select default state\n");
+ }
+ }
}
mutex_unlock(&pinctrl_mutex);
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 17ecf651b123..1f40ff68a8c4 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -52,12 +52,15 @@ struct pinctrl_dev {
* @dev: the device using this pin control handle
* @states: a list of states for this device
* @state: the current state
+ * @dt_maps: the mapping table chunks dynamically parsed from device tree for
+ * this device, if any
*/
struct pinctrl {
struct list_head node;
struct device *dev;
struct list_head states;
struct pinctrl_state *state;
+ struct list_head dt_maps;
};
/**
@@ -100,7 +103,8 @@ struct pinctrl_setting_configs {
* struct pinctrl_setting - an individual mux or config setting
* @node: list node for struct pinctrl_settings's @settings field
* @type: the type of setting
- * @pctldev: pin control device handling to be programmed
+ * @pctldev: pin control device handling to be programmed. Not used for
+ * PIN_MAP_TYPE_DUMMY_STATE.
* @data: Data specific to the setting type
*/
struct pinctrl_setting {
@@ -144,6 +148,7 @@ struct pin_desc {
struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name);
int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name);
+const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin);
int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
const char *pin_group);
@@ -153,4 +158,9 @@ static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev,
return radix_tree_lookup(&pctldev->pin_desc_tree, pin);
}
+int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
+ bool dup, bool locked);
+void pinctrl_unregister_map(struct pinctrl_map const *map);
+
extern struct mutex pinctrl_mutex;
+extern struct list_head pinctrldev_list;
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
new file mode 100644
index 000000000000..fcb1de45473c
--- /dev/null
+++ b/drivers/pinctrl/devicetree.c
@@ -0,0 +1,249 @@
+/*
+ * Device tree integration for the pin control subsystem
+ *
+ * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/slab.h>
+
+#include "core.h"
+#include "devicetree.h"
+
+/**
+ * struct pinctrl_dt_map - mapping table chunk parsed from device tree
+ * @node: list node for struct pinctrl's @dt_maps field
+ * @pctldev: the pin controller that allocated this struct, and will free it
+ * @maps: the mapping table entries
+ */
+struct pinctrl_dt_map {
+ struct list_head node;
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_map *map;
+ unsigned num_maps;
+};
+
+static void dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ if (pctldev) {
+ struct pinctrl_ops *ops = pctldev->desc->pctlops;
+ ops->dt_free_map(pctldev, map, num_maps);
+ } else {
+ /* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
+ kfree(map);
+ }
+}
+
+void pinctrl_dt_free_maps(struct pinctrl *p)
+{
+ struct pinctrl_dt_map *dt_map, *n1;
+
+ list_for_each_entry_safe(dt_map, n1, &p->dt_maps, node) {
+ pinctrl_unregister_map(dt_map->map);
+ list_del(&dt_map->node);
+ dt_free_map(dt_map->pctldev, dt_map->map,
+ dt_map->num_maps);
+ kfree(dt_map);
+ }
+
+ of_node_put(p->dev->of_node);
+}
+
+static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,
+ struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ int i;
+ struct pinctrl_dt_map *dt_map;
+
+ /* Initialize common mapping table entry fields */
+ for (i = 0; i < num_maps; i++) {
+ map[i].dev_name = dev_name(p->dev);
+ map[i].name = statename;
+ if (pctldev)
+ map[i].ctrl_dev_name = dev_name(pctldev->dev);
+ }
+
+ /* Remember the converted mapping table entries */
+ dt_map = kzalloc(sizeof(*dt_map), GFP_KERNEL);
+ if (!dt_map) {
+ dev_err(p->dev, "failed to alloc struct pinctrl_dt_map\n");
+ dt_free_map(pctldev, map, num_maps);
+ return -ENOMEM;
+ }
+
+ dt_map->pctldev = pctldev;
+ dt_map->map = map;
+ dt_map->num_maps = num_maps;
+ list_add_tail(&dt_map->node, &p->dt_maps);
+
+ return pinctrl_register_map(map, num_maps, false, true);
+}
+
+static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
+{
+ struct pinctrl_dev *pctldev;
+
+ list_for_each_entry(pctldev, &pinctrldev_list, node)
+ if (pctldev->dev->of_node == np)
+ return pctldev;
+
+ return NULL;
+}
+
+static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
+ struct device_node *np_config)
+{
+ struct device_node *np_pctldev;
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_ops *ops;
+ int ret;
+ struct pinctrl_map *map;
+ unsigned num_maps;
+
+ /* Find the pin controller containing np_config */
+ np_pctldev = of_node_get(np_config);
+ for (;;) {
+ np_pctldev = of_get_next_parent(np_pctldev);
+ if (!np_pctldev || of_node_is_root(np_pctldev)) {
+ dev_info(p->dev, "could not find pctldev for node %s, deferring probe\n",
+ np_config->full_name);
+ of_node_put(np_pctldev);
+ /* OK let's just assume this will appear later then */
+ return -EPROBE_DEFER;
+ }
+ pctldev = find_pinctrl_by_of_node(np_pctldev);
+ if (pctldev)
+ break;
+ }
+ of_node_put(np_pctldev);
+
+ /*
+ * Call pinctrl driver to parse device tree node, and
+ * generate mapping table entries
+ */
+ ops = pctldev->desc->pctlops;
+ if (!ops->dt_node_to_map) {
+ dev_err(p->dev, "pctldev %s doesn't support DT\n",
+ dev_name(pctldev->dev));
+ return -ENODEV;
+ }
+ ret = ops->dt_node_to_map(pctldev, np_config, &map, &num_maps);
+ if (ret < 0)
+ return ret;
+
+ /* Stash the mapping table chunk away for later use */
+ return dt_remember_or_free_map(p, statename, pctldev, map, num_maps);
+}
+
+static int dt_remember_dummy_state(struct pinctrl *p, const char *statename)
+{
+ struct pinctrl_map *map;
+
+ map = kzalloc(sizeof(*map), GFP_KERNEL);
+ if (!map) {
+ dev_err(p->dev, "failed to alloc struct pinctrl_map\n");
+ return -ENOMEM;
+ }
+
+ /* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
+ map->type = PIN_MAP_TYPE_DUMMY_STATE;
+
+ return dt_remember_or_free_map(p, statename, NULL, map, 1);
+}
+
+int pinctrl_dt_to_map(struct pinctrl *p)
+{
+ struct device_node *np = p->dev->of_node;
+ int state, ret;
+ char *propname;
+ struct property *prop;
+ const char *statename;
+ const __be32 *list;
+ int size, config;
+ phandle phandle;
+ struct device_node *np_config;
+
+ /* CONFIG_OF enabled, p->dev not instantiated from DT */
+ if (!np) {
+ dev_dbg(p->dev, "no of_node; not parsing pinctrl DT\n");
+ return 0;
+ }
+
+ /* We may store pointers to property names within the node */
+ of_node_get(np);
+
+ /* For each defined state ID */
+ for (state = 0; ; state++) {
+ /* Retrieve the pinctrl-* property */
+ propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
+ prop = of_find_property(np, propname, &size);
+ kfree(propname);
+ if (!prop)
+ break;
+ list = prop->value;
+ size /= sizeof(*list);
+
+ /* Determine whether pinctrl-names property names the state */
+ ret = of_property_read_string_index(np, "pinctrl-names",
+ state, &statename);
+ /*
+ * If not, statename is just the integer state ID. But rather
+ * than dynamically allocate it and have to free it later,
+ * just point part way into the property name for the string.
+ */
+ if (ret < 0) {
+ /* strlen("pinctrl-") == 8 */
+ statename = prop->name + 8;
+ }
+
+ /* For every referenced pin configuration node in it */
+ for (config = 0; config < size; config++) {
+ phandle = be32_to_cpup(list++);
+
+ /* Look up the pin configuration node */
+ np_config = of_find_node_by_phandle(phandle);
+ if (!np_config) {
+ dev_err(p->dev,
+ "prop %s index %i invalid phandle\n",
+ prop->name, config);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* Parse the node */
+ ret = dt_to_map_one_config(p, statename, np_config);
+ of_node_put(np_config);
+ if (ret < 0)
+ goto err;
+ }
+
+ /* No entries in DT? Generate a dummy state table entry */
+ if (!size) {
+ ret = dt_remember_dummy_state(p, statename);
+ if (ret < 0)
+ goto err;
+ }
+ }
+
+ return 0;
+
+err:
+ pinctrl_dt_free_maps(p);
+ return ret;
+}
diff --git a/drivers/pinctrl/devicetree.h b/drivers/pinctrl/devicetree.h
new file mode 100644
index 000000000000..760bc4960f58
--- /dev/null
+++ b/drivers/pinctrl/devicetree.h
@@ -0,0 +1,35 @@
+/*
+ * Internal interface to pinctrl device tree integration
+ *
+ * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef CONFIG_OF
+
+void pinctrl_dt_free_maps(struct pinctrl *p);
+int pinctrl_dt_to_map(struct pinctrl *p);
+
+#else
+
+static inline int pinctrl_dt_to_map(struct pinctrl *p)
+{
+ return 0;
+}
+
+static inline void pinctrl_dt_free_maps(struct pinctrl *p)
+{
+}
+
+#endif
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index 7321e8601294..43f474cdc110 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -28,11 +28,17 @@ int pinconf_check_ops(struct pinctrl_dev *pctldev)
const struct pinconf_ops *ops = pctldev->desc->confops;
/* We must be able to read out pin status */
- if (!ops->pin_config_get && !ops->pin_config_group_get)
+ if (!ops->pin_config_get && !ops->pin_config_group_get) {
+ dev_err(pctldev->dev,
+ "pinconf must be able to read out pin status\n");
return -EINVAL;
+ }
/* We have to be able to config the pins in SOME way */
- if (!ops->pin_config_set && !ops->pin_config_group_set)
+ if (!ops->pin_config_set && !ops->pin_config_group_set) {
+ dev_err(pctldev->dev,
+ "pinconf has to be able to set a pins config\n");
return -EINVAL;
+ }
return 0;
}
@@ -44,9 +50,9 @@ int pinconf_validate_map(struct pinctrl_map const *map, int i)
return -EINVAL;
}
- if (map->data.configs.num_configs &&
+ if (!map->data.configs.num_configs ||
!map->data.configs.configs) {
- pr_err("failed to register map %s (%d): no configs ptr given\n",
+ pr_err("failed to register map %s (%d): no configs given\n",
map->name, i);
return -EINVAL;
}
@@ -379,8 +385,16 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
{
+ struct pinctrl_dev *pctldev;
+ const struct pinconf_ops *confops;
int i;
+ pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
+ if (pctldev)
+ confops = pctldev->desc->confops;
+ else
+ confops = NULL;
+
switch (map->type) {
case PIN_MAP_TYPE_CONFIGS_PIN:
seq_printf(s, "pin ");
@@ -394,8 +408,15 @@ void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
seq_printf(s, "%s\n", map->data.configs.group_or_pin);
- for (i = 0; i < map->data.configs.num_configs; i++)
- seq_printf(s, "config %08lx\n", map->data.configs.configs[i]);
+ for (i = 0; i < map->data.configs.num_configs; i++) {
+ seq_printf(s, "config ");
+ if (confops && confops->pin_config_config_dbg_show)
+ confops->pin_config_config_dbg_show(pctldev, s,
+ map->data.configs.configs[i]);
+ else
+ seq_printf(s, "%08lx", map->data.configs.configs[i]);
+ seq_printf(s, "\n");
+ }
}
void pinconf_show_setting(struct seq_file *s,
@@ -403,6 +424,7 @@ void pinconf_show_setting(struct seq_file *s,
{
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
+ const struct pinconf_ops *confops = pctldev->desc->confops;
struct pin_desc *desc;
int i;
@@ -428,8 +450,15 @@ void pinconf_show_setting(struct seq_file *s,
* FIXME: We should really get the pin controler to dump the config
* values, so they can be decoded to something meaningful.
*/
- for (i = 0; i < setting->data.configs.num_configs; i++)
- seq_printf(s, " %08lx", setting->data.configs.configs[i]);
+ for (i = 0; i < setting->data.configs.num_configs; i++) {
+ seq_printf(s, " ");
+ if (confops && confops->pin_config_config_dbg_show)
+ confops->pin_config_config_dbg_show(pctldev, s,
+ setting->data.configs.configs[i]);
+ else
+ seq_printf(s, "%08lx",
+ setting->data.configs.configs[i]);
+ }
seq_printf(s, "\n");
}
@@ -448,10 +477,14 @@ static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
static int pinconf_pins_show(struct seq_file *s, void *what)
{
struct pinctrl_dev *pctldev = s->private;
+ const struct pinconf_ops *ops = pctldev->desc->confops;
unsigned i, pin;
+ if (!ops || !ops->pin_config_get)
+ return 0;
+
seq_puts(s, "Pin config settings per pin\n");
- seq_puts(s, "Format: pin (name): pinmux setting array\n");
+ seq_puts(s, "Format: pin (name): configs\n");
mutex_lock(&pinctrl_mutex);
@@ -495,17 +528,18 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
struct pinctrl_dev *pctldev = s->private;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
const struct pinconf_ops *ops = pctldev->desc->confops;
+ unsigned ngroups = pctlops->get_groups_count(pctldev);
unsigned selector = 0;
if (!ops || !ops->pin_config_group_get)
return 0;
seq_puts(s, "Pin config settings per pin group\n");
- seq_puts(s, "Format: group (name): pinmux setting array\n");
+ seq_puts(s, "Format: group (name): configs\n");
mutex_lock(&pinctrl_mutex);
- while (pctlops->list_groups(pctldev, selector) >= 0) {
+ while (selector < ngroups) {
const char *gname = pctlops->get_group_name(pctldev, selector);
seq_printf(s, "%u (%s):", selector, gname);
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index 54510de5e8c6..e3ed8cb072a5 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -19,11 +19,6 @@ int pinconf_map_to_setting(struct pinctrl_map const *map,
struct pinctrl_setting *setting);
void pinconf_free_setting(struct pinctrl_setting const *setting);
int pinconf_apply_setting(struct pinctrl_setting const *setting);
-void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map);
-void pinconf_show_setting(struct seq_file *s,
- struct pinctrl_setting const *setting);
-void pinconf_init_device_debugfs(struct dentry *devroot,
- struct pinctrl_dev *pctldev);
/*
* You will only be interested in these if you're using PINCONF
@@ -61,6 +56,18 @@ static inline int pinconf_apply_setting(struct pinctrl_setting const *setting)
return 0;
}
+#endif
+
+#if defined(CONFIG_PINCONF) && defined(CONFIG_DEBUG_FS)
+
+void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map);
+void pinconf_show_setting(struct seq_file *s,
+ struct pinctrl_setting const *setting);
+void pinconf_init_device_debugfs(struct dentry *devroot,
+ struct pinctrl_dev *pctldev);
+
+#else
+
static inline void pinconf_show_map(struct seq_file *s,
struct pinctrl_map const *map)
{
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index 0797eba3e33a..55697a5d7482 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -174,7 +174,7 @@ struct u300_gpio_confdata {
/* Initial configuration */
-static const struct __initdata u300_gpio_confdata
+static const struct __initconst u300_gpio_confdata
bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
/* Port 0, pins 0-7 */
{
@@ -255,7 +255,7 @@ bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
}
};
-static const struct __initdata u300_gpio_confdata
+static const struct __initconst u300_gpio_confdata
bs365_gpio_config[BS365_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
/* Port 0, pins 0-7 */
{
diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c
new file mode 100644
index 000000000000..f6e7c670906c
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx.c
@@ -0,0 +1,620 @@
+/*
+ * Core driver for the imx pin controller
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro Ltd.
+ *
+ * Author: Dong Aisheng <dong.aisheng@linaro.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.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/slab.h>
+
+#include "core.h"
+#include "pinctrl-imx.h"
+
+#define IMX_PMX_DUMP(info, p, m, c, n) \
+{ \
+ int i, j; \
+ printk("Format: Pin Mux Config\n"); \
+ for (i = 0; i < n; i++) { \
+ j = p[i]; \
+ printk("%s %d 0x%lx\n", \
+ info->pins[j].name, \
+ m[i], c[i]); \
+ } \
+}
+
+/* The bits in CONFIG cell defined in binding doc*/
+#define IMX_NO_PAD_CTL 0x80000000 /* no pin config need */
+#define IMX_PAD_SION 0x40000000 /* set SION */
+
+/**
+ * @dev: a pointer back to containing device
+ * @base: the offset to the controller in virtual memory
+ */
+struct imx_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+ void __iomem *base;
+ const struct imx_pinctrl_soc_info *info;
+};
+
+static const struct imx_pin_reg *imx_find_pin_reg(
+ const struct imx_pinctrl_soc_info *info,
+ unsigned pin, bool is_mux, unsigned mux)
+{
+ const struct imx_pin_reg *pin_reg = NULL;
+ int i;
+
+ for (i = 0; i < info->npin_regs; i++) {
+ pin_reg = &info->pin_regs[i];
+ if (pin_reg->pid != pin)
+ continue;
+ if (!is_mux)
+ break;
+ else if (pin_reg->mux_mode == (mux & IMX_MUX_MASK))
+ break;
+ }
+
+ if (!pin_reg) {
+ dev_err(info->dev, "Pin(%s): unable to find pin reg map\n",
+ info->pins[pin].name);
+ return NULL;
+ }
+
+ return pin_reg;
+}
+
+static const inline struct imx_pin_group *imx_pinctrl_find_group_by_name(
+ const struct imx_pinctrl_soc_info *info,
+ const char *name)
+{
+ const struct imx_pin_group *grp = NULL;
+ int i;
+
+ for (i = 0; i < info->ngroups; i++) {
+ if (!strcmp(info->groups[i].name, name)) {
+ grp = &info->groups[i];
+ break;
+ }
+ }
+
+ return grp;
+}
+
+static int imx_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+
+ return info->ngroups;
+}
+
+static const char *imx_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+
+ return info->groups[selector].name;
+}
+
+static int imx_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+ const unsigned **pins,
+ unsigned *npins)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+
+ if (selector >= info->ngroups)
+ return -EINVAL;
+
+ *pins = info->groups[selector].pins;
+ *npins = info->groups[selector].npins;
+
+ return 0;
+}
+
+static void imx_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+ unsigned offset)
+{
+ seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **map, unsigned *num_maps)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct imx_pin_group *grp;
+ struct pinctrl_map *new_map;
+ struct device_node *parent;
+ int map_num = 1;
+ int i;
+
+ /*
+ * first find the group of this node and check if we need create
+ * config maps for pins
+ */
+ grp = imx_pinctrl_find_group_by_name(info, np->name);
+ if (!grp) {
+ dev_err(info->dev, "unable to find group for node %s\n",
+ np->name);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < grp->npins; i++) {
+ if (!(grp->configs[i] & IMX_NO_PAD_CTL))
+ map_num++;
+ }
+
+ new_map = kmalloc(sizeof(struct pinctrl_map) * map_num, GFP_KERNEL);
+ if (!new_map)
+ return -ENOMEM;
+
+ *map = new_map;
+ *num_maps = map_num;
+
+ /* create mux map */
+ parent = of_get_parent(np);
+ if (!parent)
+ return -EINVAL;
+ new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+ new_map[0].data.mux.function = parent->name;
+ new_map[0].data.mux.group = np->name;
+ of_node_put(parent);
+
+ /* create config map */
+ new_map++;
+ for (i = 0; i < grp->npins; i++) {
+ if (!(grp->configs[i] & IMX_NO_PAD_CTL)) {
+ new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
+ new_map[i].data.configs.group_or_pin =
+ pin_get_name(pctldev, grp->pins[i]);
+ new_map[i].data.configs.configs = &grp->configs[i];
+ new_map[i].data.configs.num_configs = 1;
+ }
+ }
+
+ dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
+ new_map->data.mux.function, new_map->data.mux.group, map_num);
+
+ return 0;
+}
+
+static void imx_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ int i;
+
+ for (i = 0; i < num_maps; i++)
+ kfree(map);
+}
+
+static struct pinctrl_ops imx_pctrl_ops = {
+ .get_groups_count = imx_get_groups_count,
+ .get_group_name = imx_get_group_name,
+ .get_group_pins = imx_get_group_pins,
+ .pin_dbg_show = imx_pin_dbg_show,
+ .dt_node_to_map = imx_dt_node_to_map,
+ .dt_free_map = imx_dt_free_map,
+
+};
+
+static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct imx_pin_reg *pin_reg;
+ const unsigned *pins, *mux;
+ unsigned int npins, pin_id;
+ int i;
+
+ /*
+ * Configure the mux mode for each pin in the group for a specific
+ * function.
+ */
+ pins = info->groups[group].pins;
+ npins = info->groups[group].npins;
+ mux = info->groups[group].mux_mode;
+
+ WARN_ON(!pins || !npins || !mux);
+
+ dev_dbg(ipctl->dev, "enable function %s group %s\n",
+ info->functions[selector].name, info->groups[group].name);
+
+ for (i = 0; i < npins; i++) {
+ pin_id = pins[i];
+
+ pin_reg = imx_find_pin_reg(info, pin_id, 1, mux[i]);
+ if (!pin_reg)
+ return -EINVAL;
+
+ if (!pin_reg->mux_reg) {
+ dev_err(ipctl->dev, "Pin(%s) does not support mux function\n",
+ info->pins[pin_id].name);
+ return -EINVAL;
+ }
+
+ writel(mux[i], ipctl->base + pin_reg->mux_reg);
+ dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
+ pin_reg->mux_reg, mux[i]);
+
+ /* some pins also need select input setting, set it if found */
+ if (pin_reg->input_reg) {
+ writel(pin_reg->input_val, ipctl->base + pin_reg->input_reg);
+ dev_dbg(ipctl->dev,
+ "==>select_input: offset 0x%x val 0x%x\n",
+ pin_reg->input_reg, pin_reg->input_val);
+ }
+ }
+
+ return 0;
+}
+
+static int imx_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+
+ return info->nfunctions;
+}
+
+static const char *imx_pmx_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+
+ return info->functions[selector].name;
+}
+
+static int imx_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+
+ *groups = info->functions[selector].groups;
+ *num_groups = info->functions[selector].num_groups;
+
+ return 0;
+}
+
+static struct pinmux_ops imx_pmx_ops = {
+ .get_functions_count = imx_pmx_get_funcs_count,
+ .get_function_name = imx_pmx_get_func_name,
+ .get_function_groups = imx_pmx_get_groups,
+ .enable = imx_pmx_enable,
+};
+
+static int imx_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned pin_id, unsigned long *config)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct imx_pin_reg *pin_reg;
+
+ pin_reg = imx_find_pin_reg(info, pin_id, 0, 0);
+ if (!pin_reg)
+ return -EINVAL;
+
+ if (!pin_reg->conf_reg) {
+ dev_err(info->dev, "Pin(%s) does not support config function\n",
+ info->pins[pin_id].name);
+ return -EINVAL;
+ }
+
+ *config = readl(ipctl->base + pin_reg->conf_reg);
+
+ return 0;
+}
+
+static int imx_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned pin_id, unsigned long config)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct imx_pin_reg *pin_reg;
+
+ pin_reg = imx_find_pin_reg(info, pin_id, 0, 0);
+ if (!pin_reg)
+ return -EINVAL;
+
+ if (!pin_reg->conf_reg) {
+ dev_err(info->dev, "Pin(%s) does not support config function\n",
+ info->pins[pin_id].name);
+ return -EINVAL;
+ }
+
+ dev_dbg(ipctl->dev, "pinconf set pin %s\n",
+ info->pins[pin_id].name);
+
+ writel(config, ipctl->base + pin_reg->conf_reg);
+ dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n",
+ pin_reg->conf_reg, config);
+
+ return 0;
+}
+
+static void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned pin_id)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct imx_pin_reg *pin_reg;
+ unsigned long config;
+
+ pin_reg = imx_find_pin_reg(info, pin_id, 0, 0);
+ if (!pin_reg || !pin_reg->conf_reg) {
+ seq_printf(s, "N/A");
+ return;
+ }
+
+ config = readl(ipctl->base + pin_reg->conf_reg);
+ seq_printf(s, "0x%lx", config);
+}
+
+static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned group)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+ struct imx_pin_group *grp;
+ unsigned long config;
+ const char *name;
+ int i, ret;
+
+ if (group > info->ngroups)
+ return;
+
+ seq_printf(s, "\n");
+ grp = &info->groups[group];
+ for (i = 0; i < grp->npins; i++) {
+ name = pin_get_name(pctldev, grp->pins[i]);
+ ret = imx_pinconf_get(pctldev, grp->pins[i], &config);
+ if (ret)
+ return;
+ seq_printf(s, "%s: 0x%lx", name, config);
+ }
+}
+
+struct pinconf_ops imx_pinconf_ops = {
+ .pin_config_get = imx_pinconf_get,
+ .pin_config_set = imx_pinconf_set,
+ .pin_config_dbg_show = imx_pinconf_dbg_show,
+ .pin_config_group_dbg_show = imx_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc imx_pinctrl_desc = {
+ .pctlops = &imx_pctrl_ops,
+ .pmxops = &imx_pmx_ops,
+ .confops = &imx_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+/* decode pin id and mux from pin function id got from device tree*/
+static int imx_pinctrl_get_pin_id_and_mux(const struct imx_pinctrl_soc_info *info,
+ unsigned int pin_func_id, unsigned int *pin_id,
+ unsigned int *mux)
+{
+ if (pin_func_id > info->npin_regs)
+ return -EINVAL;
+
+ *pin_id = info->pin_regs[pin_func_id].pid;
+ *mux = info->pin_regs[pin_func_id].mux_mode;
+
+ return 0;
+}
+
+static int __devinit imx_pinctrl_parse_groups(struct device_node *np,
+ struct imx_pin_group *grp,
+ struct imx_pinctrl_soc_info *info,
+ u32 index)
+{
+ unsigned int pin_func_id;
+ int ret, size;
+ const const __be32 *list;
+ int i, j;
+ u32 config;
+
+ dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
+
+ /* Initialise group */
+ grp->name = np->name;
+
+ /*
+ * the binding format is fsl,pins = <PIN_FUNC_ID CONFIG ...>,
+ * do sanity check and calculate pins number
+ */
+ list = of_get_property(np, "fsl,pins", &size);
+ /* we do not check return since it's safe node passed down */
+ size /= sizeof(*list);
+ if (!size || size % 2) {
+ dev_err(info->dev, "wrong pins number or pins and configs should be pairs\n");
+ return -EINVAL;
+ }
+
+ grp->npins = size / 2;
+ grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
+ GFP_KERNEL);
+ grp->mux_mode = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
+ GFP_KERNEL);
+ grp->configs = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned long),
+ GFP_KERNEL);
+ for (i = 0, j = 0; i < size; i += 2, j++) {
+ pin_func_id = be32_to_cpu(*list++);
+ ret = imx_pinctrl_get_pin_id_and_mux(info, pin_func_id,
+ &grp->pins[j], &grp->mux_mode[j]);
+ if (ret) {
+ dev_err(info->dev, "get invalid pin function id\n");
+ return -EINVAL;
+ }
+ /* SION bit is in mux register */
+ config = be32_to_cpu(*list++);
+ if (config & IMX_PAD_SION)
+ grp->mux_mode[j] |= IOMUXC_CONFIG_SION;
+ grp->configs[j] = config & ~IMX_PAD_SION;
+ }
+
+#ifdef DEBUG
+ IMX_PMX_DUMP(info, grp->pins, grp->mux_mode, grp->configs, grp->npins);
+#endif
+ return 0;
+}
+
+static int __devinit imx_pinctrl_parse_functions(struct device_node *np,
+ struct imx_pinctrl_soc_info *info, u32 index)
+{
+ struct device_node *child;
+ struct imx_pmx_func *func;
+ struct imx_pin_group *grp;
+ int ret;
+ static u32 grp_index;
+ u32 i = 0;
+
+ dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
+
+ func = &info->functions[index];
+
+ /* Initialise function */
+ func->name = np->name;
+ func->num_groups = of_get_child_count(np);
+ if (func->num_groups <= 0) {
+ dev_err(info->dev, "no groups defined\n");
+ return -EINVAL;
+ }
+ func->groups = devm_kzalloc(info->dev,
+ func->num_groups * sizeof(char *), GFP_KERNEL);
+
+ for_each_child_of_node(np, child) {
+ func->groups[i] = child->name;
+ grp = &info->groups[grp_index++];
+ ret = imx_pinctrl_parse_groups(child, grp, info, i++);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __devinit imx_pinctrl_probe_dt(struct platform_device *pdev,
+ struct imx_pinctrl_soc_info *info)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *child;
+ int ret;
+ u32 nfuncs = 0;
+ u32 i = 0;
+
+ if (!np)
+ return -ENODEV;
+
+ nfuncs = of_get_child_count(np);
+ if (nfuncs <= 0) {
+ dev_err(&pdev->dev, "no functions defined\n");
+ return -EINVAL;
+ }
+
+ info->nfunctions = nfuncs;
+ info->functions = devm_kzalloc(&pdev->dev, nfuncs * sizeof(struct imx_pmx_func),
+ GFP_KERNEL);
+ if (!info->functions)
+ return -ENOMEM;
+
+ info->ngroups = 0;
+ for_each_child_of_node(np, child)
+ info->ngroups += of_get_child_count(child);
+ info->groups = devm_kzalloc(&pdev->dev, info->ngroups * sizeof(struct imx_pin_group),
+ GFP_KERNEL);
+ if (!info->groups)
+ return -ENOMEM;
+
+ for_each_child_of_node(np, child) {
+ ret = imx_pinctrl_parse_functions(child, info, i++);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to parse function\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int __devinit imx_pinctrl_probe(struct platform_device *pdev,
+ struct imx_pinctrl_soc_info *info)
+{
+ struct imx_pinctrl *ipctl;
+ struct resource *res;
+ int ret;
+
+ if (!info || !info->pins || !info->npins
+ || !info->pin_regs || !info->npin_regs) {
+ dev_err(&pdev->dev, "wrong pinctrl info\n");
+ return -EINVAL;
+ }
+ info->dev = &pdev->dev;
+
+ /* Create state holders etc for this driver */
+ ipctl = devm_kzalloc(&pdev->dev, sizeof(*ipctl), GFP_KERNEL);
+ if (!ipctl)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENOENT;
+
+ ipctl->base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!ipctl->base)
+ return -EBUSY;
+
+ imx_pinctrl_desc.name = dev_name(&pdev->dev);
+ imx_pinctrl_desc.pins = info->pins;
+ imx_pinctrl_desc.npins = info->npins;
+
+ ret = imx_pinctrl_probe_dt(pdev, info);
+ if (ret) {
+ dev_err(&pdev->dev, "fail to probe dt properties\n");
+ return ret;
+ }
+
+ ipctl->info = info;
+ ipctl->dev = info->dev;
+ platform_set_drvdata(pdev, ipctl);
+ ipctl->pctl = pinctrl_register(&imx_pinctrl_desc, &pdev->dev, ipctl);
+ if (!ipctl->pctl) {
+ dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");
+ return -EINVAL;
+ }
+
+ dev_info(&pdev->dev, "initialized IMX pinctrl driver\n");
+
+ return 0;
+}
+
+int __devexit imx_pinctrl_remove(struct platform_device *pdev)
+{
+ struct imx_pinctrl *ipctl = platform_get_drvdata(pdev);
+
+ pinctrl_unregister(ipctl->pctl);
+
+ return 0;
+}
diff --git a/drivers/pinctrl/pinctrl-imx.h b/drivers/pinctrl/pinctrl-imx.h
new file mode 100644
index 000000000000..9b65e7828f1d
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx.h
@@ -0,0 +1,106 @@
+/*
+ * IMX pinmux core definitions
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro Ltd.
+ *
+ * Author: Dong Aisheng <dong.aisheng@linaro.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.
+ */
+
+#ifndef __DRIVERS_PINCTRL_IMX_H
+#define __DRIVERS_PINCTRL_IMX_H
+
+struct platform_device;
+
+/**
+ * struct imx_pin_group - describes an IMX pin group
+ * @name: the name of this specific pin group
+ * @pins: an array of discrete physical pins used in this group, taken
+ * from the driver-local pin enumeration space
+ * @npins: the number of pins in this group array, i.e. the number of
+ * elements in .pins so we can iterate over that array
+ * @mux_mode: the mux mode for each pin in this group. The size of this
+ * array is the same as pins.
+ * @configs: the config for each pin in this group. The size of this
+ * array is the same as pins.
+ */
+struct imx_pin_group {
+ const char *name;
+ unsigned int *pins;
+ unsigned npins;
+ unsigned int *mux_mode;
+ unsigned long *configs;
+};
+
+/**
+ * struct imx_pmx_func - describes IMX pinmux functions
+ * @name: the name of this specific function
+ * @groups: corresponding pin groups
+ * @num_groups: the number of groups
+ */
+struct imx_pmx_func {
+ const char *name;
+ const char **groups;
+ unsigned num_groups;
+};
+
+/**
+ * struct imx_pin_reg - describe a pin reg map
+ * The last 3 members are used for select input setting
+ * @pid: pin id
+ * @mux_reg: mux register offset
+ * @conf_reg: config register offset
+ * @mux_mode: mux mode
+ * @input_reg: select input register offset for this mux if any
+ * 0 if no select input setting needed.
+ * @input_val: the value set to select input register
+ */
+struct imx_pin_reg {
+ u16 pid;
+ u16 mux_reg;
+ u16 conf_reg;
+ u8 mux_mode;
+ u16 input_reg;
+ u8 input_val;
+};
+
+struct imx_pinctrl_soc_info {
+ struct device *dev;
+ const struct pinctrl_pin_desc *pins;
+ unsigned int npins;
+ const struct imx_pin_reg *pin_regs;
+ unsigned int npin_regs;
+ struct imx_pin_group *groups;
+ unsigned int ngroups;
+ struct imx_pmx_func *functions;
+ unsigned int nfunctions;
+};
+
+#define NO_MUX 0x0
+#define NO_PAD 0x0
+
+#define IMX_PIN_REG(id, conf, mux, mode, input, val) \
+ { \
+ .pid = id, \
+ .conf_reg = conf, \
+ .mux_reg = mux, \
+ .mux_mode = mode, \
+ .input_reg = input, \
+ .input_val = val, \
+ }
+
+#define IMX_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
+
+#define PAD_CTL_MASK(len) ((1 << len) - 1)
+#define IMX_MUX_MASK 0x7
+#define IOMUXC_CONFIG_SION (0x1 << 4)
+
+int imx_pinctrl_probe(struct platform_device *pdev,
+ struct imx_pinctrl_soc_info *info);
+int imx_pinctrl_remove(struct platform_device *pdev);
+#endif /* __DRIVERS_PINCTRL_IMX_H */
diff --git a/drivers/pinctrl/pinctrl-imx23.c b/drivers/pinctrl/pinctrl-imx23.c
new file mode 100644
index 000000000000..75d3eff94296
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx23.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-mxs.h"
+
+enum imx23_pin_enum {
+ GPMI_D00 = PINID(0, 0),
+ GPMI_D01 = PINID(0, 1),
+ GPMI_D02 = PINID(0, 2),
+ GPMI_D03 = PINID(0, 3),
+ GPMI_D04 = PINID(0, 4),
+ GPMI_D05 = PINID(0, 5),
+ GPMI_D06 = PINID(0, 6),
+ GPMI_D07 = PINID(0, 7),
+ GPMI_D08 = PINID(0, 8),
+ GPMI_D09 = PINID(0, 9),
+ GPMI_D10 = PINID(0, 10),
+ GPMI_D11 = PINID(0, 11),
+ GPMI_D12 = PINID(0, 12),
+ GPMI_D13 = PINID(0, 13),
+ GPMI_D14 = PINID(0, 14),
+ GPMI_D15 = PINID(0, 15),
+ GPMI_CLE = PINID(0, 16),
+ GPMI_ALE = PINID(0, 17),
+ GPMI_CE2N = PINID(0, 18),
+ GPMI_RDY0 = PINID(0, 19),
+ GPMI_RDY1 = PINID(0, 20),
+ GPMI_RDY2 = PINID(0, 21),
+ GPMI_RDY3 = PINID(0, 22),
+ GPMI_WPN = PINID(0, 23),
+ GPMI_WRN = PINID(0, 24),
+ GPMI_RDN = PINID(0, 25),
+ AUART1_CTS = PINID(0, 26),
+ AUART1_RTS = PINID(0, 27),
+ AUART1_RX = PINID(0, 28),
+ AUART1_TX = PINID(0, 29),
+ I2C_SCL = PINID(0, 30),
+ I2C_SDA = PINID(0, 31),
+ LCD_D00 = PINID(1, 0),
+ LCD_D01 = PINID(1, 1),
+ LCD_D02 = PINID(1, 2),
+ LCD_D03 = PINID(1, 3),
+ LCD_D04 = PINID(1, 4),
+ LCD_D05 = PINID(1, 5),
+ LCD_D06 = PINID(1, 6),
+ LCD_D07 = PINID(1, 7),
+ LCD_D08 = PINID(1, 8),
+ LCD_D09 = PINID(1, 9),
+ LCD_D10 = PINID(1, 10),
+ LCD_D11 = PINID(1, 11),
+ LCD_D12 = PINID(1, 12),
+ LCD_D13 = PINID(1, 13),
+ LCD_D14 = PINID(1, 14),
+ LCD_D15 = PINID(1, 15),
+ LCD_D16 = PINID(1, 16),
+ LCD_D17 = PINID(1, 17),
+ LCD_RESET = PINID(1, 18),
+ LCD_RS = PINID(1, 19),
+ LCD_WR = PINID(1, 20),
+ LCD_CS = PINID(1, 21),
+ LCD_DOTCK = PINID(1, 22),
+ LCD_ENABLE = PINID(1, 23),
+ LCD_HSYNC = PINID(1, 24),
+ LCD_VSYNC = PINID(1, 25),
+ PWM0 = PINID(1, 26),
+ PWM1 = PINID(1, 27),
+ PWM2 = PINID(1, 28),
+ PWM3 = PINID(1, 29),
+ PWM4 = PINID(1, 30),
+ SSP1_CMD = PINID(2, 0),
+ SSP1_DETECT = PINID(2, 1),
+ SSP1_DATA0 = PINID(2, 2),
+ SSP1_DATA1 = PINID(2, 3),
+ SSP1_DATA2 = PINID(2, 4),
+ SSP1_DATA3 = PINID(2, 5),
+ SSP1_SCK = PINID(2, 6),
+ ROTARYA = PINID(2, 7),
+ ROTARYB = PINID(2, 8),
+ EMI_A00 = PINID(2, 9),
+ EMI_A01 = PINID(2, 10),
+ EMI_A02 = PINID(2, 11),
+ EMI_A03 = PINID(2, 12),
+ EMI_A04 = PINID(2, 13),
+ EMI_A05 = PINID(2, 14),
+ EMI_A06 = PINID(2, 15),
+ EMI_A07 = PINID(2, 16),
+ EMI_A08 = PINID(2, 17),
+ EMI_A09 = PINID(2, 18),
+ EMI_A10 = PINID(2, 19),
+ EMI_A11 = PINID(2, 20),
+ EMI_A12 = PINID(2, 21),
+ EMI_BA0 = PINID(2, 22),
+ EMI_BA1 = PINID(2, 23),
+ EMI_CASN = PINID(2, 24),
+ EMI_CE0N = PINID(2, 25),
+ EMI_CE1N = PINID(2, 26),
+ GPMI_CE1N = PINID(2, 27),
+ GPMI_CE0N = PINID(2, 28),
+ EMI_CKE = PINID(2, 29),
+ EMI_RASN = PINID(2, 30),
+ EMI_WEN = PINID(2, 31),
+ EMI_D00 = PINID(3, 0),
+ EMI_D01 = PINID(3, 1),
+ EMI_D02 = PINID(3, 2),
+ EMI_D03 = PINID(3, 3),
+ EMI_D04 = PINID(3, 4),
+ EMI_D05 = PINID(3, 5),
+ EMI_D06 = PINID(3, 6),
+ EMI_D07 = PINID(3, 7),
+ EMI_D08 = PINID(3, 8),
+ EMI_D09 = PINID(3, 9),
+ EMI_D10 = PINID(3, 10),
+ EMI_D11 = PINID(3, 11),
+ EMI_D12 = PINID(3, 12),
+ EMI_D13 = PINID(3, 13),
+ EMI_D14 = PINID(3, 14),
+ EMI_D15 = PINID(3, 15),
+ EMI_DQM0 = PINID(3, 16),
+ EMI_DQM1 = PINID(3, 17),
+ EMI_DQS0 = PINID(3, 18),
+ EMI_DQS1 = PINID(3, 19),
+ EMI_CLK = PINID(3, 20),
+ EMI_CLKN = PINID(3, 21),
+};
+
+static const struct pinctrl_pin_desc imx23_pins[] = {
+ MXS_PINCTRL_PIN(GPMI_D00),
+ MXS_PINCTRL_PIN(GPMI_D01),
+ MXS_PINCTRL_PIN(GPMI_D02),
+ MXS_PINCTRL_PIN(GPMI_D03),
+ MXS_PINCTRL_PIN(GPMI_D04),
+ MXS_PINCTRL_PIN(GPMI_D05),
+ MXS_PINCTRL_PIN(GPMI_D06),
+ MXS_PINCTRL_PIN(GPMI_D07),
+ MXS_PINCTRL_PIN(GPMI_D08),
+ MXS_PINCTRL_PIN(GPMI_D09),
+ MXS_PINCTRL_PIN(GPMI_D10),
+ MXS_PINCTRL_PIN(GPMI_D11),
+ MXS_PINCTRL_PIN(GPMI_D12),
+ MXS_PINCTRL_PIN(GPMI_D13),
+ MXS_PINCTRL_PIN(GPMI_D14),
+ MXS_PINCTRL_PIN(GPMI_D15),
+ MXS_PINCTRL_PIN(GPMI_CLE),
+ MXS_PINCTRL_PIN(GPMI_ALE),
+ MXS_PINCTRL_PIN(GPMI_CE2N),
+ MXS_PINCTRL_PIN(GPMI_RDY0),
+ MXS_PINCTRL_PIN(GPMI_RDY1),
+ MXS_PINCTRL_PIN(GPMI_RDY2),
+ MXS_PINCTRL_PIN(GPMI_RDY3),
+ MXS_PINCTRL_PIN(GPMI_WPN),
+ MXS_PINCTRL_PIN(GPMI_WRN),
+ MXS_PINCTRL_PIN(GPMI_RDN),
+ MXS_PINCTRL_PIN(AUART1_CTS),
+ MXS_PINCTRL_PIN(AUART1_RTS),
+ MXS_PINCTRL_PIN(AUART1_RX),
+ MXS_PINCTRL_PIN(AUART1_TX),
+ MXS_PINCTRL_PIN(I2C_SCL),
+ MXS_PINCTRL_PIN(I2C_SDA),
+ MXS_PINCTRL_PIN(LCD_D00),
+ MXS_PINCTRL_PIN(LCD_D01),
+ MXS_PINCTRL_PIN(LCD_D02),
+ MXS_PINCTRL_PIN(LCD_D03),
+ MXS_PINCTRL_PIN(LCD_D04),
+ MXS_PINCTRL_PIN(LCD_D05),
+ MXS_PINCTRL_PIN(LCD_D06),
+ MXS_PINCTRL_PIN(LCD_D07),
+ MXS_PINCTRL_PIN(LCD_D08),
+ MXS_PINCTRL_PIN(LCD_D09),
+ MXS_PINCTRL_PIN(LCD_D10),
+ MXS_PINCTRL_PIN(LCD_D11),
+ MXS_PINCTRL_PIN(LCD_D12),
+ MXS_PINCTRL_PIN(LCD_D13),
+ MXS_PINCTRL_PIN(LCD_D14),
+ MXS_PINCTRL_PIN(LCD_D15),
+ MXS_PINCTRL_PIN(LCD_D16),
+ MXS_PINCTRL_PIN(LCD_D17),
+ MXS_PINCTRL_PIN(LCD_RESET),
+ MXS_PINCTRL_PIN(LCD_RS),
+ MXS_PINCTRL_PIN(LCD_WR),
+ MXS_PINCTRL_PIN(LCD_CS),
+ MXS_PINCTRL_PIN(LCD_DOTCK),
+ MXS_PINCTRL_PIN(LCD_ENABLE),
+ MXS_PINCTRL_PIN(LCD_HSYNC),
+ MXS_PINCTRL_PIN(LCD_VSYNC),
+ MXS_PINCTRL_PIN(PWM0),
+ MXS_PINCTRL_PIN(PWM1),
+ MXS_PINCTRL_PIN(PWM2),
+ MXS_PINCTRL_PIN(PWM3),
+ MXS_PINCTRL_PIN(PWM4),
+ MXS_PINCTRL_PIN(SSP1_CMD),
+ MXS_PINCTRL_PIN(SSP1_DETECT),
+ MXS_PINCTRL_PIN(SSP1_DATA0),
+ MXS_PINCTRL_PIN(SSP1_DATA1),
+ MXS_PINCTRL_PIN(SSP1_DATA2),
+ MXS_PINCTRL_PIN(SSP1_DATA3),
+ MXS_PINCTRL_PIN(SSP1_SCK),
+ MXS_PINCTRL_PIN(ROTARYA),
+ MXS_PINCTRL_PIN(ROTARYB),
+ MXS_PINCTRL_PIN(EMI_A00),
+ MXS_PINCTRL_PIN(EMI_A01),
+ MXS_PINCTRL_PIN(EMI_A02),
+ MXS_PINCTRL_PIN(EMI_A03),
+ MXS_PINCTRL_PIN(EMI_A04),
+ MXS_PINCTRL_PIN(EMI_A05),
+ MXS_PINCTRL_PIN(EMI_A06),
+ MXS_PINCTRL_PIN(EMI_A07),
+ MXS_PINCTRL_PIN(EMI_A08),
+ MXS_PINCTRL_PIN(EMI_A09),
+ MXS_PINCTRL_PIN(EMI_A10),
+ MXS_PINCTRL_PIN(EMI_A11),
+ MXS_PINCTRL_PIN(EMI_A12),
+ MXS_PINCTRL_PIN(EMI_BA0),
+ MXS_PINCTRL_PIN(EMI_BA1),
+ MXS_PINCTRL_PIN(EMI_CASN),
+ MXS_PINCTRL_PIN(EMI_CE0N),
+ MXS_PINCTRL_PIN(EMI_CE1N),
+ MXS_PINCTRL_PIN(GPMI_CE1N),
+ MXS_PINCTRL_PIN(GPMI_CE0N),
+ MXS_PINCTRL_PIN(EMI_CKE),
+ MXS_PINCTRL_PIN(EMI_RASN),
+ MXS_PINCTRL_PIN(EMI_WEN),
+ MXS_PINCTRL_PIN(EMI_D00),
+ MXS_PINCTRL_PIN(EMI_D01),
+ MXS_PINCTRL_PIN(EMI_D02),
+ MXS_PINCTRL_PIN(EMI_D03),
+ MXS_PINCTRL_PIN(EMI_D04),
+ MXS_PINCTRL_PIN(EMI_D05),
+ MXS_PINCTRL_PIN(EMI_D06),
+ MXS_PINCTRL_PIN(EMI_D07),
+ MXS_PINCTRL_PIN(EMI_D08),
+ MXS_PINCTRL_PIN(EMI_D09),
+ MXS_PINCTRL_PIN(EMI_D10),
+ MXS_PINCTRL_PIN(EMI_D11),
+ MXS_PINCTRL_PIN(EMI_D12),
+ MXS_PINCTRL_PIN(EMI_D13),
+ MXS_PINCTRL_PIN(EMI_D14),
+ MXS_PINCTRL_PIN(EMI_D15),
+ MXS_PINCTRL_PIN(EMI_DQM0),
+ MXS_PINCTRL_PIN(EMI_DQM1),
+ MXS_PINCTRL_PIN(EMI_DQS0),
+ MXS_PINCTRL_PIN(EMI_DQS1),
+ MXS_PINCTRL_PIN(EMI_CLK),
+ MXS_PINCTRL_PIN(EMI_CLKN),
+};
+
+static struct mxs_regs imx23_regs = {
+ .muxsel = 0x100,
+ .drive = 0x200,
+ .pull = 0x400,
+};
+
+static struct mxs_pinctrl_soc_data imx23_pinctrl_data = {
+ .regs = &imx23_regs,
+ .pins = imx23_pins,
+ .npins = ARRAY_SIZE(imx23_pins),
+};
+
+static int __devinit imx23_pinctrl_probe(struct platform_device *pdev)
+{
+ return mxs_pinctrl_probe(pdev, &imx23_pinctrl_data);
+}
+
+static struct of_device_id imx23_pinctrl_of_match[] __devinitdata = {
+ { .compatible = "fsl,imx23-pinctrl", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx23_pinctrl_of_match);
+
+static struct platform_driver imx23_pinctrl_driver = {
+ .driver = {
+ .name = "imx23-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = imx23_pinctrl_of_match,
+ },
+ .probe = imx23_pinctrl_probe,
+ .remove = __devexit_p(mxs_pinctrl_remove),
+};
+
+static int __init imx23_pinctrl_init(void)
+{
+ return platform_driver_register(&imx23_pinctrl_driver);
+}
+arch_initcall(imx23_pinctrl_init);
+
+static void __exit imx23_pinctrl_exit(void)
+{
+ platform_driver_unregister(&imx23_pinctrl_driver);
+}
+module_exit(imx23_pinctrl_exit);
+
+MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
+MODULE_DESCRIPTION("Freescale i.MX23 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-imx28.c b/drivers/pinctrl/pinctrl-imx28.c
new file mode 100644
index 000000000000..b973026811a2
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx28.c
@@ -0,0 +1,421 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-mxs.h"
+
+enum imx28_pin_enum {
+ GPMI_D00 = PINID(0, 0),
+ GPMI_D01 = PINID(0, 1),
+ GPMI_D02 = PINID(0, 2),
+ GPMI_D03 = PINID(0, 3),
+ GPMI_D04 = PINID(0, 4),
+ GPMI_D05 = PINID(0, 5),
+ GPMI_D06 = PINID(0, 6),
+ GPMI_D07 = PINID(0, 7),
+ GPMI_CE0N = PINID(0, 16),
+ GPMI_CE1N = PINID(0, 17),
+ GPMI_CE2N = PINID(0, 18),
+ GPMI_CE3N = PINID(0, 19),
+ GPMI_RDY0 = PINID(0, 20),
+ GPMI_RDY1 = PINID(0, 21),
+ GPMI_RDY2 = PINID(0, 22),
+ GPMI_RDY3 = PINID(0, 23),
+ GPMI_RDN = PINID(0, 24),
+ GPMI_WRN = PINID(0, 25),
+ GPMI_ALE = PINID(0, 26),
+ GPMI_CLE = PINID(0, 27),
+ GPMI_RESETN = PINID(0, 28),
+ LCD_D00 = PINID(1, 0),
+ LCD_D01 = PINID(1, 1),
+ LCD_D02 = PINID(1, 2),
+ LCD_D03 = PINID(1, 3),
+ LCD_D04 = PINID(1, 4),
+ LCD_D05 = PINID(1, 5),
+ LCD_D06 = PINID(1, 6),
+ LCD_D07 = PINID(1, 7),
+ LCD_D08 = PINID(1, 8),
+ LCD_D09 = PINID(1, 9),
+ LCD_D10 = PINID(1, 10),
+ LCD_D11 = PINID(1, 11),
+ LCD_D12 = PINID(1, 12),
+ LCD_D13 = PINID(1, 13),
+ LCD_D14 = PINID(1, 14),
+ LCD_D15 = PINID(1, 15),
+ LCD_D16 = PINID(1, 16),
+ LCD_D17 = PINID(1, 17),
+ LCD_D18 = PINID(1, 18),
+ LCD_D19 = PINID(1, 19),
+ LCD_D20 = PINID(1, 20),
+ LCD_D21 = PINID(1, 21),
+ LCD_D22 = PINID(1, 22),
+ LCD_D23 = PINID(1, 23),
+ LCD_RD_E = PINID(1, 24),
+ LCD_WR_RWN = PINID(1, 25),
+ LCD_RS = PINID(1, 26),
+ LCD_CS = PINID(1, 27),
+ LCD_VSYNC = PINID(1, 28),
+ LCD_HSYNC = PINID(1, 29),
+ LCD_DOTCLK = PINID(1, 30),
+ LCD_ENABLE = PINID(1, 31),
+ SSP0_DATA0 = PINID(2, 0),
+ SSP0_DATA1 = PINID(2, 1),
+ SSP0_DATA2 = PINID(2, 2),
+ SSP0_DATA3 = PINID(2, 3),
+ SSP0_DATA4 = PINID(2, 4),
+ SSP0_DATA5 = PINID(2, 5),
+ SSP0_DATA6 = PINID(2, 6),
+ SSP0_DATA7 = PINID(2, 7),
+ SSP0_CMD = PINID(2, 8),
+ SSP0_DETECT = PINID(2, 9),
+ SSP0_SCK = PINID(2, 10),
+ SSP1_SCK = PINID(2, 12),
+ SSP1_CMD = PINID(2, 13),
+ SSP1_DATA0 = PINID(2, 14),
+ SSP1_DATA3 = PINID(2, 15),
+ SSP2_SCK = PINID(2, 16),
+ SSP2_MOSI = PINID(2, 17),
+ SSP2_MISO = PINID(2, 18),
+ SSP2_SS0 = PINID(2, 19),
+ SSP2_SS1 = PINID(2, 20),
+ SSP2_SS2 = PINID(2, 21),
+ SSP3_SCK = PINID(2, 24),
+ SSP3_MOSI = PINID(2, 25),
+ SSP3_MISO = PINID(2, 26),
+ SSP3_SS0 = PINID(2, 27),
+ AUART0_RX = PINID(3, 0),
+ AUART0_TX = PINID(3, 1),
+ AUART0_CTS = PINID(3, 2),
+ AUART0_RTS = PINID(3, 3),
+ AUART1_RX = PINID(3, 4),
+ AUART1_TX = PINID(3, 5),
+ AUART1_CTS = PINID(3, 6),
+ AUART1_RTS = PINID(3, 7),
+ AUART2_RX = PINID(3, 8),
+ AUART2_TX = PINID(3, 9),
+ AUART2_CTS = PINID(3, 10),
+ AUART2_RTS = PINID(3, 11),
+ AUART3_RX = PINID(3, 12),
+ AUART3_TX = PINID(3, 13),
+ AUART3_CTS = PINID(3, 14),
+ AUART3_RTS = PINID(3, 15),
+ PWM0 = PINID(3, 16),
+ PWM1 = PINID(3, 17),
+ PWM2 = PINID(3, 18),
+ SAIF0_MCLK = PINID(3, 20),
+ SAIF0_LRCLK = PINID(3, 21),
+ SAIF0_BITCLK = PINID(3, 22),
+ SAIF0_SDATA0 = PINID(3, 23),
+ I2C0_SCL = PINID(3, 24),
+ I2C0_SDA = PINID(3, 25),
+ SAIF1_SDATA0 = PINID(3, 26),
+ SPDIF = PINID(3, 27),
+ PWM3 = PINID(3, 28),
+ PWM4 = PINID(3, 29),
+ LCD_RESET = PINID(3, 30),
+ ENET0_MDC = PINID(4, 0),
+ ENET0_MDIO = PINID(4, 1),
+ ENET0_RX_EN = PINID(4, 2),
+ ENET0_RXD0 = PINID(4, 3),
+ ENET0_RXD1 = PINID(4, 4),
+ ENET0_TX_CLK = PINID(4, 5),
+ ENET0_TX_EN = PINID(4, 6),
+ ENET0_TXD0 = PINID(4, 7),
+ ENET0_TXD1 = PINID(4, 8),
+ ENET0_RXD2 = PINID(4, 9),
+ ENET0_RXD3 = PINID(4, 10),
+ ENET0_TXD2 = PINID(4, 11),
+ ENET0_TXD3 = PINID(4, 12),
+ ENET0_RX_CLK = PINID(4, 13),
+ ENET0_COL = PINID(4, 14),
+ ENET0_CRS = PINID(4, 15),
+ ENET_CLK = PINID(4, 16),
+ JTAG_RTCK = PINID(4, 20),
+ EMI_D00 = PINID(5, 0),
+ EMI_D01 = PINID(5, 1),
+ EMI_D02 = PINID(5, 2),
+ EMI_D03 = PINID(5, 3),
+ EMI_D04 = PINID(5, 4),
+ EMI_D05 = PINID(5, 5),
+ EMI_D06 = PINID(5, 6),
+ EMI_D07 = PINID(5, 7),
+ EMI_D08 = PINID(5, 8),
+ EMI_D09 = PINID(5, 9),
+ EMI_D10 = PINID(5, 10),
+ EMI_D11 = PINID(5, 11),
+ EMI_D12 = PINID(5, 12),
+ EMI_D13 = PINID(5, 13),
+ EMI_D14 = PINID(5, 14),
+ EMI_D15 = PINID(5, 15),
+ EMI_ODT0 = PINID(5, 16),
+ EMI_DQM0 = PINID(5, 17),
+ EMI_ODT1 = PINID(5, 18),
+ EMI_DQM1 = PINID(5, 19),
+ EMI_DDR_OPEN_FB = PINID(5, 20),
+ EMI_CLK = PINID(5, 21),
+ EMI_DQS0 = PINID(5, 22),
+ EMI_DQS1 = PINID(5, 23),
+ EMI_DDR_OPEN = PINID(5, 26),
+ EMI_A00 = PINID(6, 0),
+ EMI_A01 = PINID(6, 1),
+ EMI_A02 = PINID(6, 2),
+ EMI_A03 = PINID(6, 3),
+ EMI_A04 = PINID(6, 4),
+ EMI_A05 = PINID(6, 5),
+ EMI_A06 = PINID(6, 6),
+ EMI_A07 = PINID(6, 7),
+ EMI_A08 = PINID(6, 8),
+ EMI_A09 = PINID(6, 9),
+ EMI_A10 = PINID(6, 10),
+ EMI_A11 = PINID(6, 11),
+ EMI_A12 = PINID(6, 12),
+ EMI_A13 = PINID(6, 13),
+ EMI_A14 = PINID(6, 14),
+ EMI_BA0 = PINID(6, 16),
+ EMI_BA1 = PINID(6, 17),
+ EMI_BA2 = PINID(6, 18),
+ EMI_CASN = PINID(6, 19),
+ EMI_RASN = PINID(6, 20),
+ EMI_WEN = PINID(6, 21),
+ EMI_CE0N = PINID(6, 22),
+ EMI_CE1N = PINID(6, 23),
+ EMI_CKE = PINID(6, 24),
+};
+
+static const struct pinctrl_pin_desc imx28_pins[] = {
+ MXS_PINCTRL_PIN(GPMI_D00),
+ MXS_PINCTRL_PIN(GPMI_D01),
+ MXS_PINCTRL_PIN(GPMI_D02),
+ MXS_PINCTRL_PIN(GPMI_D03),
+ MXS_PINCTRL_PIN(GPMI_D04),
+ MXS_PINCTRL_PIN(GPMI_D05),
+ MXS_PINCTRL_PIN(GPMI_D06),
+ MXS_PINCTRL_PIN(GPMI_D07),
+ MXS_PINCTRL_PIN(GPMI_CE0N),
+ MXS_PINCTRL_PIN(GPMI_CE1N),
+ MXS_PINCTRL_PIN(GPMI_CE2N),
+ MXS_PINCTRL_PIN(GPMI_CE3N),
+ MXS_PINCTRL_PIN(GPMI_RDY0),
+ MXS_PINCTRL_PIN(GPMI_RDY1),
+ MXS_PINCTRL_PIN(GPMI_RDY2),
+ MXS_PINCTRL_PIN(GPMI_RDY3),
+ MXS_PINCTRL_PIN(GPMI_RDN),
+ MXS_PINCTRL_PIN(GPMI_WRN),
+ MXS_PINCTRL_PIN(GPMI_ALE),
+ MXS_PINCTRL_PIN(GPMI_CLE),
+ MXS_PINCTRL_PIN(GPMI_RESETN),
+ MXS_PINCTRL_PIN(LCD_D00),
+ MXS_PINCTRL_PIN(LCD_D01),
+ MXS_PINCTRL_PIN(LCD_D02),
+ MXS_PINCTRL_PIN(LCD_D03),
+ MXS_PINCTRL_PIN(LCD_D04),
+ MXS_PINCTRL_PIN(LCD_D05),
+ MXS_PINCTRL_PIN(LCD_D06),
+ MXS_PINCTRL_PIN(LCD_D07),
+ MXS_PINCTRL_PIN(LCD_D08),
+ MXS_PINCTRL_PIN(LCD_D09),
+ MXS_PINCTRL_PIN(LCD_D10),
+ MXS_PINCTRL_PIN(LCD_D11),
+ MXS_PINCTRL_PIN(LCD_D12),
+ MXS_PINCTRL_PIN(LCD_D13),
+ MXS_PINCTRL_PIN(LCD_D14),
+ MXS_PINCTRL_PIN(LCD_D15),
+ MXS_PINCTRL_PIN(LCD_D16),
+ MXS_PINCTRL_PIN(LCD_D17),
+ MXS_PINCTRL_PIN(LCD_D18),
+ MXS_PINCTRL_PIN(LCD_D19),
+ MXS_PINCTRL_PIN(LCD_D20),
+ MXS_PINCTRL_PIN(LCD_D21),
+ MXS_PINCTRL_PIN(LCD_D22),
+ MXS_PINCTRL_PIN(LCD_D23),
+ MXS_PINCTRL_PIN(LCD_RD_E),
+ MXS_PINCTRL_PIN(LCD_WR_RWN),
+ MXS_PINCTRL_PIN(LCD_RS),
+ MXS_PINCTRL_PIN(LCD_CS),
+ MXS_PINCTRL_PIN(LCD_VSYNC),
+ MXS_PINCTRL_PIN(LCD_HSYNC),
+ MXS_PINCTRL_PIN(LCD_DOTCLK),
+ MXS_PINCTRL_PIN(LCD_ENABLE),
+ MXS_PINCTRL_PIN(SSP0_DATA0),
+ MXS_PINCTRL_PIN(SSP0_DATA1),
+ MXS_PINCTRL_PIN(SSP0_DATA2),
+ MXS_PINCTRL_PIN(SSP0_DATA3),
+ MXS_PINCTRL_PIN(SSP0_DATA4),
+ MXS_PINCTRL_PIN(SSP0_DATA5),
+ MXS_PINCTRL_PIN(SSP0_DATA6),
+ MXS_PINCTRL_PIN(SSP0_DATA7),
+ MXS_PINCTRL_PIN(SSP0_CMD),
+ MXS_PINCTRL_PIN(SSP0_DETECT),
+ MXS_PINCTRL_PIN(SSP0_SCK),
+ MXS_PINCTRL_PIN(SSP1_SCK),
+ MXS_PINCTRL_PIN(SSP1_CMD),
+ MXS_PINCTRL_PIN(SSP1_DATA0),
+ MXS_PINCTRL_PIN(SSP1_DATA3),
+ MXS_PINCTRL_PIN(SSP2_SCK),
+ MXS_PINCTRL_PIN(SSP2_MOSI),
+ MXS_PINCTRL_PIN(SSP2_MISO),
+ MXS_PINCTRL_PIN(SSP2_SS0),
+ MXS_PINCTRL_PIN(SSP2_SS1),
+ MXS_PINCTRL_PIN(SSP2_SS2),
+ MXS_PINCTRL_PIN(SSP3_SCK),
+ MXS_PINCTRL_PIN(SSP3_MOSI),
+ MXS_PINCTRL_PIN(SSP3_MISO),
+ MXS_PINCTRL_PIN(SSP3_SS0),
+ MXS_PINCTRL_PIN(AUART0_RX),
+ MXS_PINCTRL_PIN(AUART0_TX),
+ MXS_PINCTRL_PIN(AUART0_CTS),
+ MXS_PINCTRL_PIN(AUART0_RTS),
+ MXS_PINCTRL_PIN(AUART1_RX),
+ MXS_PINCTRL_PIN(AUART1_TX),
+ MXS_PINCTRL_PIN(AUART1_CTS),
+ MXS_PINCTRL_PIN(AUART1_RTS),
+ MXS_PINCTRL_PIN(AUART2_RX),
+ MXS_PINCTRL_PIN(AUART2_TX),
+ MXS_PINCTRL_PIN(AUART2_CTS),
+ MXS_PINCTRL_PIN(AUART2_RTS),
+ MXS_PINCTRL_PIN(AUART3_RX),
+ MXS_PINCTRL_PIN(AUART3_TX),
+ MXS_PINCTRL_PIN(AUART3_CTS),
+ MXS_PINCTRL_PIN(AUART3_RTS),
+ MXS_PINCTRL_PIN(PWM0),
+ MXS_PINCTRL_PIN(PWM1),
+ MXS_PINCTRL_PIN(PWM2),
+ MXS_PINCTRL_PIN(SAIF0_MCLK),
+ MXS_PINCTRL_PIN(SAIF0_LRCLK),
+ MXS_PINCTRL_PIN(SAIF0_BITCLK),
+ MXS_PINCTRL_PIN(SAIF0_SDATA0),
+ MXS_PINCTRL_PIN(I2C0_SCL),
+ MXS_PINCTRL_PIN(I2C0_SDA),
+ MXS_PINCTRL_PIN(SAIF1_SDATA0),
+ MXS_PINCTRL_PIN(SPDIF),
+ MXS_PINCTRL_PIN(PWM3),
+ MXS_PINCTRL_PIN(PWM4),
+ MXS_PINCTRL_PIN(LCD_RESET),
+ MXS_PINCTRL_PIN(ENET0_MDC),
+ MXS_PINCTRL_PIN(ENET0_MDIO),
+ MXS_PINCTRL_PIN(ENET0_RX_EN),
+ MXS_PINCTRL_PIN(ENET0_RXD0),
+ MXS_PINCTRL_PIN(ENET0_RXD1),
+ MXS_PINCTRL_PIN(ENET0_TX_CLK),
+ MXS_PINCTRL_PIN(ENET0_TX_EN),
+ MXS_PINCTRL_PIN(ENET0_TXD0),
+ MXS_PINCTRL_PIN(ENET0_TXD1),
+ MXS_PINCTRL_PIN(ENET0_RXD2),
+ MXS_PINCTRL_PIN(ENET0_RXD3),
+ MXS_PINCTRL_PIN(ENET0_TXD2),
+ MXS_PINCTRL_PIN(ENET0_TXD3),
+ MXS_PINCTRL_PIN(ENET0_RX_CLK),
+ MXS_PINCTRL_PIN(ENET0_COL),
+ MXS_PINCTRL_PIN(ENET0_CRS),
+ MXS_PINCTRL_PIN(ENET_CLK),
+ MXS_PINCTRL_PIN(JTAG_RTCK),
+ MXS_PINCTRL_PIN(EMI_D00),
+ MXS_PINCTRL_PIN(EMI_D01),
+ MXS_PINCTRL_PIN(EMI_D02),
+ MXS_PINCTRL_PIN(EMI_D03),
+ MXS_PINCTRL_PIN(EMI_D04),
+ MXS_PINCTRL_PIN(EMI_D05),
+ MXS_PINCTRL_PIN(EMI_D06),
+ MXS_PINCTRL_PIN(EMI_D07),
+ MXS_PINCTRL_PIN(EMI_D08),
+ MXS_PINCTRL_PIN(EMI_D09),
+ MXS_PINCTRL_PIN(EMI_D10),
+ MXS_PINCTRL_PIN(EMI_D11),
+ MXS_PINCTRL_PIN(EMI_D12),
+ MXS_PINCTRL_PIN(EMI_D13),
+ MXS_PINCTRL_PIN(EMI_D14),
+ MXS_PINCTRL_PIN(EMI_D15),
+ MXS_PINCTRL_PIN(EMI_ODT0),
+ MXS_PINCTRL_PIN(EMI_DQM0),
+ MXS_PINCTRL_PIN(EMI_ODT1),
+ MXS_PINCTRL_PIN(EMI_DQM1),
+ MXS_PINCTRL_PIN(EMI_DDR_OPEN_FB),
+ MXS_PINCTRL_PIN(EMI_CLK),
+ MXS_PINCTRL_PIN(EMI_DQS0),
+ MXS_PINCTRL_PIN(EMI_DQS1),
+ MXS_PINCTRL_PIN(EMI_DDR_OPEN),
+ MXS_PINCTRL_PIN(EMI_A00),
+ MXS_PINCTRL_PIN(EMI_A01),
+ MXS_PINCTRL_PIN(EMI_A02),
+ MXS_PINCTRL_PIN(EMI_A03),
+ MXS_PINCTRL_PIN(EMI_A04),
+ MXS_PINCTRL_PIN(EMI_A05),
+ MXS_PINCTRL_PIN(EMI_A06),
+ MXS_PINCTRL_PIN(EMI_A07),
+ MXS_PINCTRL_PIN(EMI_A08),
+ MXS_PINCTRL_PIN(EMI_A09),
+ MXS_PINCTRL_PIN(EMI_A10),
+ MXS_PINCTRL_PIN(EMI_A11),
+ MXS_PINCTRL_PIN(EMI_A12),
+ MXS_PINCTRL_PIN(EMI_A13),
+ MXS_PINCTRL_PIN(EMI_A14),
+ MXS_PINCTRL_PIN(EMI_BA0),
+ MXS_PINCTRL_PIN(EMI_BA1),
+ MXS_PINCTRL_PIN(EMI_BA2),
+ MXS_PINCTRL_PIN(EMI_CASN),
+ MXS_PINCTRL_PIN(EMI_RASN),
+ MXS_PINCTRL_PIN(EMI_WEN),
+ MXS_PINCTRL_PIN(EMI_CE0N),
+ MXS_PINCTRL_PIN(EMI_CE1N),
+ MXS_PINCTRL_PIN(EMI_CKE),
+};
+
+static struct mxs_regs imx28_regs = {
+ .muxsel = 0x100,
+ .drive = 0x300,
+ .pull = 0x600,
+};
+
+static struct mxs_pinctrl_soc_data imx28_pinctrl_data = {
+ .regs = &imx28_regs,
+ .pins = imx28_pins,
+ .npins = ARRAY_SIZE(imx28_pins),
+};
+
+static int __devinit imx28_pinctrl_probe(struct platform_device *pdev)
+{
+ return mxs_pinctrl_probe(pdev, &imx28_pinctrl_data);
+}
+
+static struct of_device_id imx28_pinctrl_of_match[] __devinitdata = {
+ { .compatible = "fsl,imx28-pinctrl", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx28_pinctrl_of_match);
+
+static struct platform_driver imx28_pinctrl_driver = {
+ .driver = {
+ .name = "imx28-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = imx28_pinctrl_of_match,
+ },
+ .probe = imx28_pinctrl_probe,
+ .remove = __devexit_p(mxs_pinctrl_remove),
+};
+
+static int __init imx28_pinctrl_init(void)
+{
+ return platform_driver_register(&imx28_pinctrl_driver);
+}
+arch_initcall(imx28_pinctrl_init);
+
+static void __exit imx28_pinctrl_exit(void)
+{
+ platform_driver_unregister(&imx28_pinctrl_driver);
+}
+module_exit(imx28_pinctrl_exit);
+
+MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
+MODULE_DESCRIPTION("Freescale i.MX28 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-imx51.c b/drivers/pinctrl/pinctrl-imx51.c
new file mode 100644
index 000000000000..689b3c88dd2e
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx51.c
@@ -0,0 +1,1322 @@
+/*
+ * imx51 pinctrl driver based on imx pinmux core
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro, Inc.
+ *
+ * Author: Dong Aisheng <dong.aisheng@linaro.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.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-imx.h"
+
+enum imx51_pads {
+ MX51_PAD_EIM_D16 = 1,
+ MX51_PAD_EIM_D17 = 2,
+ MX51_PAD_EIM_D18 = 3,
+ MX51_PAD_EIM_D19 = 4,
+ MX51_PAD_EIM_D20 = 5,
+ MX51_PAD_EIM_D21 = 6,
+ MX51_PAD_EIM_D22 = 7,
+ MX51_PAD_EIM_D23 = 8,
+ MX51_PAD_EIM_D24 = 9,
+ MX51_PAD_EIM_D25 = 10,
+ MX51_PAD_EIM_D26 = 11,
+ MX51_PAD_EIM_D27 = 12,
+ MX51_PAD_EIM_D28 = 13,
+ MX51_PAD_EIM_D29 = 14,
+ MX51_PAD_EIM_D30 = 15,
+ MX51_PAD_EIM_D31 = 16,
+ MX51_PAD_EIM_A16 = 17,
+ MX51_PAD_EIM_A17 = 18,
+ MX51_PAD_EIM_A18 = 19,
+ MX51_PAD_EIM_A19 = 20,
+ MX51_PAD_EIM_A20 = 21,
+ MX51_PAD_EIM_A21 = 22,
+ MX51_PAD_EIM_A22 = 23,
+ MX51_PAD_EIM_A23 = 24,
+ MX51_PAD_EIM_A24 = 25,
+ MX51_PAD_EIM_A25 = 26,
+ MX51_PAD_EIM_A26 = 27,
+ MX51_PAD_EIM_A27 = 28,
+ MX51_PAD_EIM_EB0 = 29,
+ MX51_PAD_EIM_EB1 = 30,
+ MX51_PAD_EIM_EB2 = 31,
+ MX51_PAD_EIM_EB3 = 32,
+ MX51_PAD_EIM_OE = 33,
+ MX51_PAD_EIM_CS0 = 34,
+ MX51_PAD_EIM_CS1 = 35,
+ MX51_PAD_EIM_CS2 = 36,
+ MX51_PAD_EIM_CS3 = 37,
+ MX51_PAD_EIM_CS4 = 38,
+ MX51_PAD_EIM_CS5 = 39,
+ MX51_PAD_EIM_DTACK = 40,
+ MX51_PAD_EIM_LBA = 41,
+ MX51_PAD_EIM_CRE = 42,
+ MX51_PAD_DRAM_CS1 = 43,
+ MX51_PAD_NANDF_WE_B = 44,
+ MX51_PAD_NANDF_RE_B = 45,
+ MX51_PAD_NANDF_ALE = 46,
+ MX51_PAD_NANDF_CLE = 47,
+ MX51_PAD_NANDF_WP_B = 48,
+ MX51_PAD_NANDF_RB0 = 49,
+ MX51_PAD_NANDF_RB1 = 50,
+ MX51_PAD_NANDF_RB2 = 51,
+ MX51_PAD_NANDF_RB3 = 52,
+ MX51_PAD_GPIO_NAND = 53,
+ MX51_PAD_NANDF_CS0 = 54,
+ MX51_PAD_NANDF_CS1 = 55,
+ MX51_PAD_NANDF_CS2 = 56,
+ MX51_PAD_NANDF_CS3 = 57,
+ MX51_PAD_NANDF_CS4 = 58,
+ MX51_PAD_NANDF_CS5 = 59,
+ MX51_PAD_NANDF_CS6 = 60,
+ MX51_PAD_NANDF_CS7 = 61,
+ MX51_PAD_NANDF_RDY_INT = 62,
+ MX51_PAD_NANDF_D15 = 63,
+ MX51_PAD_NANDF_D14 = 64,
+ MX51_PAD_NANDF_D13 = 65,
+ MX51_PAD_NANDF_D12 = 66,
+ MX51_PAD_NANDF_D11 = 67,
+ MX51_PAD_NANDF_D10 = 68,
+ MX51_PAD_NANDF_D9 = 69,
+ MX51_PAD_NANDF_D8 = 70,
+ MX51_PAD_NANDF_D7 = 71,
+ MX51_PAD_NANDF_D6 = 72,
+ MX51_PAD_NANDF_D5 = 73,
+ MX51_PAD_NANDF_D4 = 74,
+ MX51_PAD_NANDF_D3 = 75,
+ MX51_PAD_NANDF_D2 = 76,
+ MX51_PAD_NANDF_D1 = 77,
+ MX51_PAD_NANDF_D0 = 78,
+ MX51_PAD_CSI1_D8 = 79,
+ MX51_PAD_CSI1_D9 = 80,
+ MX51_PAD_CSI1_D10 = 81,
+ MX51_PAD_CSI1_D11 = 82,
+ MX51_PAD_CSI1_D12 = 83,
+ MX51_PAD_CSI1_D13 = 84,
+ MX51_PAD_CSI1_D14 = 85,
+ MX51_PAD_CSI1_D15 = 86,
+ MX51_PAD_CSI1_D16 = 87,
+ MX51_PAD_CSI1_D17 = 88,
+ MX51_PAD_CSI1_D18 = 89,
+ MX51_PAD_CSI1_D19 = 90,
+ MX51_PAD_CSI1_VSYNC = 91,
+ MX51_PAD_CSI1_HSYNC = 92,
+ MX51_PAD_CSI1_PIXCLK = 93,
+ MX51_PAD_CSI1_MCLK = 94,
+ MX51_PAD_CSI2_D12 = 95,
+ MX51_PAD_CSI2_D13 = 96,
+ MX51_PAD_CSI2_D14 = 97,
+ MX51_PAD_CSI2_D15 = 98,
+ MX51_PAD_CSI2_D16 = 99,
+ MX51_PAD_CSI2_D17 = 100,
+ MX51_PAD_CSI2_D18 = 101,
+ MX51_PAD_CSI2_D19 = 102,
+ MX51_PAD_CSI2_VSYNC = 103,
+ MX51_PAD_CSI2_HSYNC = 104,
+ MX51_PAD_CSI2_PIXCLK = 105,
+ MX51_PAD_I2C1_CLK = 106,
+ MX51_PAD_I2C1_DAT = 107,
+ MX51_PAD_AUD3_BB_TXD = 108,
+ MX51_PAD_AUD3_BB_RXD = 109,
+ MX51_PAD_AUD3_BB_CK = 110,
+ MX51_PAD_AUD3_BB_FS = 111,
+ MX51_PAD_CSPI1_MOSI = 112,
+ MX51_PAD_CSPI1_MISO = 113,
+ MX51_PAD_CSPI1_SS0 = 114,
+ MX51_PAD_CSPI1_SS1 = 115,
+ MX51_PAD_CSPI1_RDY = 116,
+ MX51_PAD_CSPI1_SCLK = 117,
+ MX51_PAD_UART1_RXD = 118,
+ MX51_PAD_UART1_TXD = 119,
+ MX51_PAD_UART1_RTS = 120,
+ MX51_PAD_UART1_CTS = 121,
+ MX51_PAD_UART2_RXD = 122,
+ MX51_PAD_UART2_TXD = 123,
+ MX51_PAD_UART3_RXD = 124,
+ MX51_PAD_UART3_TXD = 125,
+ MX51_PAD_OWIRE_LINE = 126,
+ MX51_PAD_KEY_ROW0 = 127,
+ MX51_PAD_KEY_ROW1 = 128,
+ MX51_PAD_KEY_ROW2 = 129,
+ MX51_PAD_KEY_ROW3 = 130,
+ MX51_PAD_KEY_COL0 = 131,
+ MX51_PAD_KEY_COL1 = 132,
+ MX51_PAD_KEY_COL2 = 133,
+ MX51_PAD_KEY_COL3 = 134,
+ MX51_PAD_KEY_COL4 = 135,
+ MX51_PAD_KEY_COL5 = 136,
+ MX51_PAD_USBH1_CLK = 137,
+ MX51_PAD_USBH1_DIR = 138,
+ MX51_PAD_USBH1_STP = 139,
+ MX51_PAD_USBH1_NXT = 140,
+ MX51_PAD_USBH1_DATA0 = 141,
+ MX51_PAD_USBH1_DATA1 = 142,
+ MX51_PAD_USBH1_DATA2 = 143,
+ MX51_PAD_USBH1_DATA3 = 144,
+ MX51_PAD_USBH1_DATA4 = 145,
+ MX51_PAD_USBH1_DATA5 = 146,
+ MX51_PAD_USBH1_DATA6 = 147,
+ MX51_PAD_USBH1_DATA7 = 148,
+ MX51_PAD_DI1_PIN11 = 149,
+ MX51_PAD_DI1_PIN12 = 150,
+ MX51_PAD_DI1_PIN13 = 151,
+ MX51_PAD_DI1_D0_CS = 152,
+ MX51_PAD_DI1_D1_CS = 153,
+ MX51_PAD_DISPB2_SER_DIN = 154,
+ MX51_PAD_DISPB2_SER_DIO = 155,
+ MX51_PAD_DISPB2_SER_CLK = 156,
+ MX51_PAD_DISPB2_SER_RS = 157,
+ MX51_PAD_DISP1_DAT0 = 158,
+ MX51_PAD_DISP1_DAT1 = 159,
+ MX51_PAD_DISP1_DAT2 = 160,
+ MX51_PAD_DISP1_DAT3 = 161,
+ MX51_PAD_DISP1_DAT4 = 162,
+ MX51_PAD_DISP1_DAT5 = 163,
+ MX51_PAD_DISP1_DAT6 = 164,
+ MX51_PAD_DISP1_DAT7 = 165,
+ MX51_PAD_DISP1_DAT8 = 166,
+ MX51_PAD_DISP1_DAT9 = 167,
+ MX51_PAD_DISP1_DAT10 = 168,
+ MX51_PAD_DISP1_DAT11 = 169,
+ MX51_PAD_DISP1_DAT12 = 170,
+ MX51_PAD_DISP1_DAT13 = 171,
+ MX51_PAD_DISP1_DAT14 = 172,
+ MX51_PAD_DISP1_DAT15 = 173,
+ MX51_PAD_DISP1_DAT16 = 174,
+ MX51_PAD_DISP1_DAT17 = 175,
+ MX51_PAD_DISP1_DAT18 = 176,
+ MX51_PAD_DISP1_DAT19 = 177,
+ MX51_PAD_DISP1_DAT20 = 178,
+ MX51_PAD_DISP1_DAT21 = 179,
+ MX51_PAD_DISP1_DAT22 = 180,
+ MX51_PAD_DISP1_DAT23 = 181,
+ MX51_PAD_DI1_PIN3 = 182,
+ MX51_PAD_DI1_PIN2 = 183,
+ MX51_PAD_DI_GP2 = 184,
+ MX51_PAD_DI_GP3 = 185,
+ MX51_PAD_DI2_PIN4 = 186,
+ MX51_PAD_DI2_PIN2 = 187,
+ MX51_PAD_DI2_PIN3 = 188,
+ MX51_PAD_DI2_DISP_CLK = 189,
+ MX51_PAD_DI_GP4 = 190,
+ MX51_PAD_DISP2_DAT0 = 191,
+ MX51_PAD_DISP2_DAT1 = 192,
+ MX51_PAD_DISP2_DAT2 = 193,
+ MX51_PAD_DISP2_DAT3 = 194,
+ MX51_PAD_DISP2_DAT4 = 195,
+ MX51_PAD_DISP2_DAT5 = 196,
+ MX51_PAD_DISP2_DAT6 = 197,
+ MX51_PAD_DISP2_DAT7 = 198,
+ MX51_PAD_DISP2_DAT8 = 199,
+ MX51_PAD_DISP2_DAT9 = 200,
+ MX51_PAD_DISP2_DAT10 = 201,
+ MX51_PAD_DISP2_DAT11 = 202,
+ MX51_PAD_DISP2_DAT12 = 203,
+ MX51_PAD_DISP2_DAT13 = 204,
+ MX51_PAD_DISP2_DAT14 = 205,
+ MX51_PAD_DISP2_DAT15 = 206,
+ MX51_PAD_SD1_CMD = 207,
+ MX51_PAD_SD1_CLK = 208,
+ MX51_PAD_SD1_DATA0 = 209,
+ MX51_PAD_EIM_DA0 = 210,
+ MX51_PAD_EIM_DA1 = 211,
+ MX51_PAD_EIM_DA2 = 212,
+ MX51_PAD_EIM_DA3 = 213,
+ MX51_PAD_SD1_DATA1 = 214,
+ MX51_PAD_EIM_DA4 = 215,
+ MX51_PAD_EIM_DA5 = 216,
+ MX51_PAD_EIM_DA6 = 217,
+ MX51_PAD_EIM_DA7 = 218,
+ MX51_PAD_SD1_DATA2 = 219,
+ MX51_PAD_EIM_DA10 = 220,
+ MX51_PAD_EIM_DA11 = 221,
+ MX51_PAD_EIM_DA8 = 222,
+ MX51_PAD_EIM_DA9 = 223,
+ MX51_PAD_SD1_DATA3 = 224,
+ MX51_PAD_GPIO1_0 = 225,
+ MX51_PAD_GPIO1_1 = 226,
+ MX51_PAD_EIM_DA12 = 227,
+ MX51_PAD_EIM_DA13 = 228,
+ MX51_PAD_EIM_DA14 = 229,
+ MX51_PAD_EIM_DA15 = 230,
+ MX51_PAD_SD2_CMD = 231,
+ MX51_PAD_SD2_CLK = 232,
+ MX51_PAD_SD2_DATA0 = 233,
+ MX51_PAD_SD2_DATA1 = 234,
+ MX51_PAD_SD2_DATA2 = 235,
+ MX51_PAD_SD2_DATA3 = 236,
+ MX51_PAD_GPIO1_2 = 237,
+ MX51_PAD_GPIO1_3 = 238,
+ MX51_PAD_PMIC_INT_REQ = 239,
+ MX51_PAD_GPIO1_4 = 240,
+ MX51_PAD_GPIO1_5 = 241,
+ MX51_PAD_GPIO1_6 = 242,
+ MX51_PAD_GPIO1_7 = 243,
+ MX51_PAD_GPIO1_8 = 244,
+ MX51_PAD_GPIO1_9 = 245,
+};
+
+/* imx51 register maps */
+static struct imx_pin_reg imx51_pin_regs[] = {
+ IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 5, 0x000, 0), /* MX51_PAD_EIM_D16__AUD4_RXFS */
+ IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 7, 0x8d8, 0), /* MX51_PAD_EIM_D16__AUD5_TXD */
+ IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 0, 0x000, 0), /* MX51_PAD_EIM_D16__EIM_D16 */
+ IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 1, 0x000, 0), /* MX51_PAD_EIM_D16__GPIO2_0 */
+ IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 4, 0x9b4, 0), /* MX51_PAD_EIM_D16__I2C1_SDA */
+ IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 3, 0x000, 0), /* MX51_PAD_EIM_D16__UART2_CTS */
+ IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 2, 0x000, 0), /* MX51_PAD_EIM_D16__USBH2_DATA0 */
+ IMX_PIN_REG(MX51_PAD_EIM_D17, 0x3f4, 0x060, 7, 0x8d4, 0), /* MX51_PAD_EIM_D17__AUD5_RXD */
+ IMX_PIN_REG(MX51_PAD_EIM_D17, 0x3f4, 0x060, 0, 0x000, 0), /* MX51_PAD_EIM_D17__EIM_D17 */
+ IMX_PIN_REG(MX51_PAD_EIM_D17, 0x3f4, 0x060, 1, 0x000, 0), /* MX51_PAD_EIM_D17__GPIO2_1 */
+ IMX_PIN_REG(MX51_PAD_EIM_D17, 0x3f4, 0x060, 3, 0x9ec, 0), /* MX51_PAD_EIM_D17__UART2_RXD */
+ IMX_PIN_REG(MX51_PAD_EIM_D17, 0x3f4, 0x060, 4, 0x000, 0), /* MX51_PAD_EIM_D17__UART3_CTS */
+ IMX_PIN_REG(MX51_PAD_EIM_D17, 0x3f4, 0x060, 2, 0x000, 0), /* MX51_PAD_EIM_D17__USBH2_DATA1 */
+ IMX_PIN_REG(MX51_PAD_EIM_D18, 0x3f8, 0x064, 7, 0x8e4, 0), /* MX51_PAD_EIM_D18__AUD5_TXC */
+ IMX_PIN_REG(MX51_PAD_EIM_D18, 0x3f8, 0x064, 0, 0x000, 0), /* MX51_PAD_EIM_D18__EIM_D18 */
+ IMX_PIN_REG(MX51_PAD_EIM_D18, 0x3f8, 0x064, 1, 0x000, 0), /* MX51_PAD_EIM_D18__GPIO2_2 */
+ IMX_PIN_REG(MX51_PAD_EIM_D18, 0x3f8, 0x064, 3, 0x000, 0), /* MX51_PAD_EIM_D18__UART2_TXD */
+ IMX_PIN_REG(MX51_PAD_EIM_D18, 0x3f8, 0x064, 4, 0x9f0, 1), /* MX51_PAD_EIM_D18__UART3_RTS */
+ IMX_PIN_REG(MX51_PAD_EIM_D18, 0x3f8, 0x064, 2, 0x000, 0), /* MX51_PAD_EIM_D18__USBH2_DATA2 */
+ IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 5, 0x000, 0), /* MX51_PAD_EIM_D19__AUD4_RXC */
+ IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 7, 0x8e8, 0), /* MX51_PAD_EIM_D19__AUD5_TXFS */
+ IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 0, 0x000, 0), /* MX51_PAD_EIM_D19__EIM_D19 */
+ IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 1, 0x000, 0), /* MX51_PAD_EIM_D19__GPIO2_3 */
+ IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 4, 0x9b0, 0), /* MX51_PAD_EIM_D19__I2C1_SCL */
+ IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 3, 0x9e8, 1), /* MX51_PAD_EIM_D19__UART2_RTS */
+ IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 2, 0x000, 0), /* MX51_PAD_EIM_D19__USBH2_DATA3 */
+ IMX_PIN_REG(MX51_PAD_EIM_D20, 0x400, 0x06c, 5, 0x8c8, 0), /* MX51_PAD_EIM_D20__AUD4_TXD */
+ IMX_PIN_REG(MX51_PAD_EIM_D20, 0x400, 0x06c, 0, 0x000, 0), /* MX51_PAD_EIM_D20__EIM_D20 */
+ IMX_PIN_REG(MX51_PAD_EIM_D20, 0x400, 0x06c, 1, 0x000, 0), /* MX51_PAD_EIM_D20__GPIO2_4 */
+ IMX_PIN_REG(MX51_PAD_EIM_D20, 0x400, 0x06c, 4, 0x000, 0), /* MX51_PAD_EIM_D20__SRTC_ALARM_DEB */
+ IMX_PIN_REG(MX51_PAD_EIM_D20, 0x400, 0x06c, 2, 0x000, 0), /* MX51_PAD_EIM_D20__USBH2_DATA4 */
+ IMX_PIN_REG(MX51_PAD_EIM_D21, 0x404, 0x070, 5, 0x8c4, 0), /* MX51_PAD_EIM_D21__AUD4_RXD */
+ IMX_PIN_REG(MX51_PAD_EIM_D21, 0x404, 0x070, 0, 0x000, 0), /* MX51_PAD_EIM_D21__EIM_D21 */
+ IMX_PIN_REG(MX51_PAD_EIM_D21, 0x404, 0x070, 1, 0x000, 0), /* MX51_PAD_EIM_D21__GPIO2_5 */
+ IMX_PIN_REG(MX51_PAD_EIM_D21, 0x404, 0x070, 3, 0x000, 0), /* MX51_PAD_EIM_D21__SRTC_ALARM_DEB */
+ IMX_PIN_REG(MX51_PAD_EIM_D21, 0x404, 0x070, 2, 0x000, 0), /* MX51_PAD_EIM_D21__USBH2_DATA5 */
+ IMX_PIN_REG(MX51_PAD_EIM_D22, 0x408, 0x074, 5, 0x8cc, 0), /* MX51_PAD_EIM_D22__AUD4_TXC */
+ IMX_PIN_REG(MX51_PAD_EIM_D22, 0x408, 0x074, 0, 0x000, 0), /* MX51_PAD_EIM_D22__EIM_D22 */
+ IMX_PIN_REG(MX51_PAD_EIM_D22, 0x408, 0x074, 1, 0x000, 0), /* MX51_PAD_EIM_D22__GPIO2_6 */
+ IMX_PIN_REG(MX51_PAD_EIM_D22, 0x408, 0x074, 2, 0x000, 0), /* MX51_PAD_EIM_D22__USBH2_DATA6 */
+ IMX_PIN_REG(MX51_PAD_EIM_D23, 0x40c, 0x078, 5, 0x8d0, 0), /* MX51_PAD_EIM_D23__AUD4_TXFS */
+ IMX_PIN_REG(MX51_PAD_EIM_D23, 0x40c, 0x078, 0, 0x000, 0), /* MX51_PAD_EIM_D23__EIM_D23 */
+ IMX_PIN_REG(MX51_PAD_EIM_D23, 0x40c, 0x078, 1, 0x000, 0), /* MX51_PAD_EIM_D23__GPIO2_7 */
+ IMX_PIN_REG(MX51_PAD_EIM_D23, 0x40c, 0x078, 4, 0x000, 0), /* MX51_PAD_EIM_D23__SPDIF_OUT1 */
+ IMX_PIN_REG(MX51_PAD_EIM_D23, 0x40c, 0x078, 2, 0x000, 0), /* MX51_PAD_EIM_D23__USBH2_DATA7 */
+ IMX_PIN_REG(MX51_PAD_EIM_D24, 0x410, 0x07c, 5, 0x8f8, 0), /* MX51_PAD_EIM_D24__AUD6_RXFS */
+ IMX_PIN_REG(MX51_PAD_EIM_D24, 0x410, 0x07c, 0, 0x000, 0), /* MX51_PAD_EIM_D24__EIM_D24 */
+ IMX_PIN_REG(MX51_PAD_EIM_D24, 0x410, 0x07c, 1, 0x000, 0), /* MX51_PAD_EIM_D24__GPIO2_8 */
+ IMX_PIN_REG(MX51_PAD_EIM_D24, 0x410, 0x07c, 4, 0x9bc, 0), /* MX51_PAD_EIM_D24__I2C2_SDA */
+ IMX_PIN_REG(MX51_PAD_EIM_D24, 0x410, 0x07c, 3, 0x000, 0), /* MX51_PAD_EIM_D24__UART3_CTS */
+ IMX_PIN_REG(MX51_PAD_EIM_D24, 0x410, 0x07c, 2, 0x000, 0), /* MX51_PAD_EIM_D24__USBOTG_DATA0 */
+ IMX_PIN_REG(MX51_PAD_EIM_D25, 0x414, 0x080, 0, 0x000, 0), /* MX51_PAD_EIM_D25__EIM_D25 */
+ IMX_PIN_REG(MX51_PAD_EIM_D25, 0x414, 0x080, 1, 0x9c8, 0), /* MX51_PAD_EIM_D25__KEY_COL6 */
+ IMX_PIN_REG(MX51_PAD_EIM_D25, 0x414, 0x080, 4, 0x000, 0), /* MX51_PAD_EIM_D25__UART2_CTS */
+ IMX_PIN_REG(MX51_PAD_EIM_D25, 0x414, 0x080, 3, 0x9f4, 0), /* MX51_PAD_EIM_D25__UART3_RXD */
+ IMX_PIN_REG(MX51_PAD_EIM_D25, 0x414, 0x080, 2, 0x000, 0), /* MX51_PAD_EIM_D25__USBOTG_DATA1 */
+ IMX_PIN_REG(MX51_PAD_EIM_D26, 0x418, 0x084, 0, 0x000, 0), /* MX51_PAD_EIM_D26__EIM_D26 */
+ IMX_PIN_REG(MX51_PAD_EIM_D26, 0x418, 0x084, 1, 0x9cc, 0), /* MX51_PAD_EIM_D26__KEY_COL7 */
+ IMX_PIN_REG(MX51_PAD_EIM_D26, 0x418, 0x084, 4, 0x9e8, 3), /* MX51_PAD_EIM_D26__UART2_RTS */
+ IMX_PIN_REG(MX51_PAD_EIM_D26, 0x418, 0x084, 3, 0x000, 0), /* MX51_PAD_EIM_D26__UART3_TXD */
+ IMX_PIN_REG(MX51_PAD_EIM_D26, 0x418, 0x084, 2, 0x000, 0), /* MX51_PAD_EIM_D26__USBOTG_DATA2 */
+ IMX_PIN_REG(MX51_PAD_EIM_D27, 0x41c, 0x088, 5, 0x8f4, 0), /* MX51_PAD_EIM_D27__AUD6_RXC */
+ IMX_PIN_REG(MX51_PAD_EIM_D27, 0x41c, 0x088, 0, 0x000, 0), /* MX51_PAD_EIM_D27__EIM_D27 */
+ IMX_PIN_REG(MX51_PAD_EIM_D27, 0x41c, 0x088, 1, 0x000, 0), /* MX51_PAD_EIM_D27__GPIO2_9 */
+ IMX_PIN_REG(MX51_PAD_EIM_D27, 0x41c, 0x088, 4, 0x9b8, 0), /* MX51_PAD_EIM_D27__I2C2_SCL */
+ IMX_PIN_REG(MX51_PAD_EIM_D27, 0x41c, 0x088, 3, 0x9f0, 3), /* MX51_PAD_EIM_D27__UART3_RTS */
+ IMX_PIN_REG(MX51_PAD_EIM_D27, 0x41c, 0x088, 2, 0x000, 0), /* MX51_PAD_EIM_D27__USBOTG_DATA3 */
+ IMX_PIN_REG(MX51_PAD_EIM_D28, 0x420, 0x08c, 5, 0x8f0, 0), /* MX51_PAD_EIM_D28__AUD6_TXD */
+ IMX_PIN_REG(MX51_PAD_EIM_D28, 0x420, 0x08c, 0, 0x000, 0), /* MX51_PAD_EIM_D28__EIM_D28 */
+ IMX_PIN_REG(MX51_PAD_EIM_D28, 0x420, 0x08c, 1, 0x9d0, 0), /* MX51_PAD_EIM_D28__KEY_ROW4 */
+ IMX_PIN_REG(MX51_PAD_EIM_D28, 0x420, 0x08c, 2, 0x000, 0), /* MX51_PAD_EIM_D28__USBOTG_DATA4 */
+ IMX_PIN_REG(MX51_PAD_EIM_D29, 0x424, 0x090, 5, 0x8ec, 0), /* MX51_PAD_EIM_D29__AUD6_RXD */
+ IMX_PIN_REG(MX51_PAD_EIM_D29, 0x424, 0x090, 0, 0x000, 0), /* MX51_PAD_EIM_D29__EIM_D29 */
+ IMX_PIN_REG(MX51_PAD_EIM_D29, 0x424, 0x090, 1, 0x9d4, 0), /* MX51_PAD_EIM_D29__KEY_ROW5 */
+ IMX_PIN_REG(MX51_PAD_EIM_D29, 0x424, 0x090, 2, 0x000, 0), /* MX51_PAD_EIM_D29__USBOTG_DATA5 */
+ IMX_PIN_REG(MX51_PAD_EIM_D30, 0x428, 0x094, 5, 0x8fc, 0), /* MX51_PAD_EIM_D30__AUD6_TXC */
+ IMX_PIN_REG(MX51_PAD_EIM_D30, 0x428, 0x094, 0, 0x000, 0), /* MX51_PAD_EIM_D30__EIM_D30 */
+ IMX_PIN_REG(MX51_PAD_EIM_D30, 0x428, 0x094, 1, 0x9d8, 0), /* MX51_PAD_EIM_D30__KEY_ROW6 */
+ IMX_PIN_REG(MX51_PAD_EIM_D30, 0x428, 0x094, 2, 0x000, 0), /* MX51_PAD_EIM_D30__USBOTG_DATA6 */
+ IMX_PIN_REG(MX51_PAD_EIM_D31, 0x42c, 0x098, 5, 0x900, 0), /* MX51_PAD_EIM_D31__AUD6_TXFS */
+ IMX_PIN_REG(MX51_PAD_EIM_D31, 0x42c, 0x098, 0, 0x000, 0), /* MX51_PAD_EIM_D31__EIM_D31 */
+ IMX_PIN_REG(MX51_PAD_EIM_D31, 0x42c, 0x098, 1, 0x9dc, 0), /* MX51_PAD_EIM_D31__KEY_ROW7 */
+ IMX_PIN_REG(MX51_PAD_EIM_D31, 0x42c, 0x098, 2, 0x000, 0), /* MX51_PAD_EIM_D31__USBOTG_DATA7 */
+ IMX_PIN_REG(MX51_PAD_EIM_A16, 0x430, 0x09c, 0, 0x000, 0), /* MX51_PAD_EIM_A16__EIM_A16 */
+ IMX_PIN_REG(MX51_PAD_EIM_A16, 0x430, 0x09c, 1, 0x000, 0), /* MX51_PAD_EIM_A16__GPIO2_10 */
+ IMX_PIN_REG(MX51_PAD_EIM_A16, 0x430, 0x09c, 7, 0x000, 0), /* MX51_PAD_EIM_A16__OSC_FREQ_SEL0 */
+ IMX_PIN_REG(MX51_PAD_EIM_A17, 0x434, 0x0a0, 0, 0x000, 0), /* MX51_PAD_EIM_A17__EIM_A17 */
+ IMX_PIN_REG(MX51_PAD_EIM_A17, 0x434, 0x0a0, 1, 0x000, 0), /* MX51_PAD_EIM_A17__GPIO2_11 */
+ IMX_PIN_REG(MX51_PAD_EIM_A17, 0x434, 0x0a0, 7, 0x000, 0), /* MX51_PAD_EIM_A17__OSC_FREQ_SEL1 */
+ IMX_PIN_REG(MX51_PAD_EIM_A18, 0x438, 0x0a4, 7, 0x000, 0), /* MX51_PAD_EIM_A18__BOOT_LPB0 */
+ IMX_PIN_REG(MX51_PAD_EIM_A18, 0x438, 0x0a4, 0, 0x000, 0), /* MX51_PAD_EIM_A18__EIM_A18 */
+ IMX_PIN_REG(MX51_PAD_EIM_A18, 0x438, 0x0a4, 1, 0x000, 0), /* MX51_PAD_EIM_A18__GPIO2_12 */
+ IMX_PIN_REG(MX51_PAD_EIM_A19, 0x43c, 0x0a8, 7, 0x000, 0), /* MX51_PAD_EIM_A19__BOOT_LPB1 */
+ IMX_PIN_REG(MX51_PAD_EIM_A19, 0x43c, 0x0a8, 0, 0x000, 0), /* MX51_PAD_EIM_A19__EIM_A19 */
+ IMX_PIN_REG(MX51_PAD_EIM_A19, 0x43c, 0x0a8, 1, 0x000, 0), /* MX51_PAD_EIM_A19__GPIO2_13 */
+ IMX_PIN_REG(MX51_PAD_EIM_A20, 0x440, 0x0ac, 7, 0x000, 0), /* MX51_PAD_EIM_A20__BOOT_UART_SRC0 */
+ IMX_PIN_REG(MX51_PAD_EIM_A20, 0x440, 0x0ac, 0, 0x000, 0), /* MX51_PAD_EIM_A20__EIM_A20 */
+ IMX_PIN_REG(MX51_PAD_EIM_A20, 0x440, 0x0ac, 1, 0x000, 0), /* MX51_PAD_EIM_A20__GPIO2_14 */
+ IMX_PIN_REG(MX51_PAD_EIM_A21, 0x444, 0x0b0, 7, 0x000, 0), /* MX51_PAD_EIM_A21__BOOT_UART_SRC1 */
+ IMX_PIN_REG(MX51_PAD_EIM_A21, 0x444, 0x0b0, 0, 0x000, 0), /* MX51_PAD_EIM_A21__EIM_A21 */
+ IMX_PIN_REG(MX51_PAD_EIM_A21, 0x444, 0x0b0, 1, 0x000, 0), /* MX51_PAD_EIM_A21__GPIO2_15 */
+ IMX_PIN_REG(MX51_PAD_EIM_A22, 0x448, 0x0b4, 0, 0x000, 0), /* MX51_PAD_EIM_A22__EIM_A22 */
+ IMX_PIN_REG(MX51_PAD_EIM_A22, 0x448, 0x0b4, 1, 0x000, 0), /* MX51_PAD_EIM_A22__GPIO2_16 */
+ IMX_PIN_REG(MX51_PAD_EIM_A23, 0x44c, 0x0b8, 7, 0x000, 0), /* MX51_PAD_EIM_A23__BOOT_HPN_EN */
+ IMX_PIN_REG(MX51_PAD_EIM_A23, 0x44c, 0x0b8, 0, 0x000, 0), /* MX51_PAD_EIM_A23__EIM_A23 */
+ IMX_PIN_REG(MX51_PAD_EIM_A23, 0x44c, 0x0b8, 1, 0x000, 0), /* MX51_PAD_EIM_A23__GPIO2_17 */
+ IMX_PIN_REG(MX51_PAD_EIM_A24, 0x450, 0x0bc, 0, 0x000, 0), /* MX51_PAD_EIM_A24__EIM_A24 */
+ IMX_PIN_REG(MX51_PAD_EIM_A24, 0x450, 0x0bc, 1, 0x000, 0), /* MX51_PAD_EIM_A24__GPIO2_18 */
+ IMX_PIN_REG(MX51_PAD_EIM_A24, 0x450, 0x0bc, 2, 0x000, 0), /* MX51_PAD_EIM_A24__USBH2_CLK */
+ IMX_PIN_REG(MX51_PAD_EIM_A25, 0x454, 0x0c0, 6, 0x000, 0), /* MX51_PAD_EIM_A25__DISP1_PIN4 */
+ IMX_PIN_REG(MX51_PAD_EIM_A25, 0x454, 0x0c0, 0, 0x000, 0), /* MX51_PAD_EIM_A25__EIM_A25 */
+ IMX_PIN_REG(MX51_PAD_EIM_A25, 0x454, 0x0c0, 1, 0x000, 0), /* MX51_PAD_EIM_A25__GPIO2_19 */
+ IMX_PIN_REG(MX51_PAD_EIM_A25, 0x454, 0x0c0, 2, 0x000, 0), /* MX51_PAD_EIM_A25__USBH2_DIR */
+ IMX_PIN_REG(MX51_PAD_EIM_A26, 0x458, 0x0c4, 5, 0x9a0, 0), /* MX51_PAD_EIM_A26__CSI1_DATA_EN */
+ IMX_PIN_REG(MX51_PAD_EIM_A26, 0x458, 0x0c4, 6, 0x908, 0), /* MX51_PAD_EIM_A26__DISP2_EXT_CLK */
+ IMX_PIN_REG(MX51_PAD_EIM_A26, 0x458, 0x0c4, 0, 0x000, 0), /* MX51_PAD_EIM_A26__EIM_A26 */
+ IMX_PIN_REG(MX51_PAD_EIM_A26, 0x458, 0x0c4, 1, 0x000, 0), /* MX51_PAD_EIM_A26__GPIO2_20 */
+ IMX_PIN_REG(MX51_PAD_EIM_A26, 0x458, 0x0c4, 2, 0x000, 0), /* MX51_PAD_EIM_A26__USBH2_STP */
+ IMX_PIN_REG(MX51_PAD_EIM_A27, 0x45c, 0x0c8, 5, 0x99c, 0), /* MX51_PAD_EIM_A27__CSI2_DATA_EN */
+ IMX_PIN_REG(MX51_PAD_EIM_A27, 0x45c, 0x0c8, 6, 0x9a4, 0), /* MX51_PAD_EIM_A27__DISP1_PIN1 */
+ IMX_PIN_REG(MX51_PAD_EIM_A27, 0x45c, 0x0c8, 0, 0x000, 0), /* MX51_PAD_EIM_A27__EIM_A27 */
+ IMX_PIN_REG(MX51_PAD_EIM_A27, 0x45c, 0x0c8, 1, 0x000, 0), /* MX51_PAD_EIM_A27__GPIO2_21 */
+ IMX_PIN_REG(MX51_PAD_EIM_A27, 0x45c, 0x0c8, 2, 0x000, 0), /* MX51_PAD_EIM_A27__USBH2_NXT */
+ IMX_PIN_REG(MX51_PAD_EIM_EB0, 0x460, 0x0cc, 0, 0x000, 0), /* MX51_PAD_EIM_EB0__EIM_EB0 */
+ IMX_PIN_REG(MX51_PAD_EIM_EB1, 0x464, 0x0d0, 0, 0x000, 0), /* MX51_PAD_EIM_EB1__EIM_EB1 */
+ IMX_PIN_REG(MX51_PAD_EIM_EB2, 0x468, 0x0d4, 6, 0x8e0, 0), /* MX51_PAD_EIM_EB2__AUD5_RXFS */
+ IMX_PIN_REG(MX51_PAD_EIM_EB2, 0x468, 0x0d4, 5, 0x000, 0), /* MX51_PAD_EIM_EB2__CSI1_D2 */
+ IMX_PIN_REG(MX51_PAD_EIM_EB2, 0x468, 0x0d4, 0, 0x000, 0), /* MX51_PAD_EIM_EB2__EIM_EB2 */
+ IMX_PIN_REG(MX51_PAD_EIM_EB2, 0x468, 0x0d4, 3, 0x954, 0), /* MX51_PAD_EIM_EB2__FEC_MDIO */
+ IMX_PIN_REG(MX51_PAD_EIM_EB2, 0x468, 0x0d4, 1, 0x000, 0), /* MX51_PAD_EIM_EB2__GPIO2_22 */
+ IMX_PIN_REG(MX51_PAD_EIM_EB2, 0x468, 0x0d4, 7, 0x000, 0), /* MX51_PAD_EIM_EB2__GPT_CMPOUT1 */
+ IMX_PIN_REG(MX51_PAD_EIM_EB3, 0x46c, 0x0d8, 6, 0x8dc, 0), /* MX51_PAD_EIM_EB3__AUD5_RXC */
+ IMX_PIN_REG(MX51_PAD_EIM_EB3, 0x46c, 0x0d8, 5, 0x000, 0), /* MX51_PAD_EIM_EB3__CSI1_D3 */
+ IMX_PIN_REG(MX51_PAD_EIM_EB3, 0x46c, 0x0d8, 0, 0x000, 0), /* MX51_PAD_EIM_EB3__EIM_EB3 */
+ IMX_PIN_REG(MX51_PAD_EIM_EB3, 0x46c, 0x0d8, 3, 0x95c, 0), /* MX51_PAD_EIM_EB3__FEC_RDATA1 */
+ IMX_PIN_REG(MX51_PAD_EIM_EB3, 0x46c, 0x0d8, 1, 0x000, 0), /* MX51_PAD_EIM_EB3__GPIO2_23 */
+ IMX_PIN_REG(MX51_PAD_EIM_EB3, 0x46c, 0x0d8, 7, 0x000, 0), /* MX51_PAD_EIM_EB3__GPT_CMPOUT2 */
+ IMX_PIN_REG(MX51_PAD_EIM_OE, 0x470, 0x0dc, 0, 0x000, 0), /* MX51_PAD_EIM_OE__EIM_OE */
+ IMX_PIN_REG(MX51_PAD_EIM_OE, 0x470, 0x0dc, 1, 0x000, 0), /* MX51_PAD_EIM_OE__GPIO2_24 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS0, 0x474, 0x0e0, 0, 0x000, 0), /* MX51_PAD_EIM_CS0__EIM_CS0 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS0, 0x474, 0x0e0, 1, 0x000, 0), /* MX51_PAD_EIM_CS0__GPIO2_25 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS1, 0x478, 0x0e4, 0, 0x000, 0), /* MX51_PAD_EIM_CS1__EIM_CS1 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS1, 0x478, 0x0e4, 1, 0x000, 0), /* MX51_PAD_EIM_CS1__GPIO2_26 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS2, 0x47c, 0x0e8, 6, 0x8d8, 1), /* MX51_PAD_EIM_CS2__AUD5_TXD */
+ IMX_PIN_REG(MX51_PAD_EIM_CS2, 0x47c, 0x0e8, 5, 0x000, 0), /* MX51_PAD_EIM_CS2__CSI1_D4 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS2, 0x47c, 0x0e8, 0, 0x000, 0), /* MX51_PAD_EIM_CS2__EIM_CS2 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS2, 0x47c, 0x0e8, 3, 0x960, 0), /* MX51_PAD_EIM_CS2__FEC_RDATA2 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS2, 0x47c, 0x0e8, 1, 0x000, 0), /* MX51_PAD_EIM_CS2__GPIO2_27 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS2, 0x47c, 0x0e8, 2, 0x000, 0), /* MX51_PAD_EIM_CS2__USBOTG_STP */
+ IMX_PIN_REG(MX51_PAD_EIM_CS3, 0x480, 0x0ec, 6, 0x8d4, 1), /* MX51_PAD_EIM_CS3__AUD5_RXD */
+ IMX_PIN_REG(MX51_PAD_EIM_CS3, 0x480, 0x0ec, 5, 0x000, 0), /* MX51_PAD_EIM_CS3__CSI1_D5 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS3, 0x480, 0x0ec, 0, 0x000, 0), /* MX51_PAD_EIM_CS3__EIM_CS3 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS3, 0x480, 0x0ec, 3, 0x964, 0), /* MX51_PAD_EIM_CS3__FEC_RDATA3 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS3, 0x480, 0x0ec, 1, 0x000, 0), /* MX51_PAD_EIM_CS3__GPIO2_28 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS3, 0x480, 0x0ec, 2, 0x000, 0), /* MX51_PAD_EIM_CS3__USBOTG_NXT */
+ IMX_PIN_REG(MX51_PAD_EIM_CS4, 0x484, 0x0f0, 6, 0x8e4, 1), /* MX51_PAD_EIM_CS4__AUD5_TXC */
+ IMX_PIN_REG(MX51_PAD_EIM_CS4, 0x484, 0x0f0, 5, 0x000, 0), /* MX51_PAD_EIM_CS4__CSI1_D6 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS4, 0x484, 0x0f0, 0, 0x000, 0), /* MX51_PAD_EIM_CS4__EIM_CS4 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS4, 0x484, 0x0f0, 3, 0x970, 0), /* MX51_PAD_EIM_CS4__FEC_RX_ER */
+ IMX_PIN_REG(MX51_PAD_EIM_CS4, 0x484, 0x0f0, 1, 0x000, 0), /* MX51_PAD_EIM_CS4__GPIO2_29 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS4, 0x484, 0x0f0, 2, 0x000, 0), /* MX51_PAD_EIM_CS4__USBOTG_CLK */
+ IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 6, 0x8e8, 1), /* MX51_PAD_EIM_CS5__AUD5_TXFS */
+ IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 5, 0x000, 0), /* MX51_PAD_EIM_CS5__CSI1_D7 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 4, 0x904, 0), /* MX51_PAD_EIM_CS5__DISP1_EXT_CLK */
+ IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 0, 0x000, 0), /* MX51_PAD_EIM_CS5__EIM_CS5 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 3, 0x950, 0), /* MX51_PAD_EIM_CS5__FEC_CRS */
+ IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 1, 0x000, 0), /* MX51_PAD_EIM_CS5__GPIO2_30 */
+ IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 2, 0x000, 0), /* MX51_PAD_EIM_CS5__USBOTG_DIR */
+ IMX_PIN_REG(MX51_PAD_EIM_DTACK, 0x48c, 0x0f8, 0, 0x000, 0), /* MX51_PAD_EIM_DTACK__EIM_DTACK */
+ IMX_PIN_REG(MX51_PAD_EIM_DTACK, 0x48c, 0x0f8, 1, 0x000, 0), /* MX51_PAD_EIM_DTACK__GPIO2_31 */
+ IMX_PIN_REG(MX51_PAD_EIM_LBA, 0x494, 0x0fc, 0, 0x000, 0), /* MX51_PAD_EIM_LBA__EIM_LBA */
+ IMX_PIN_REG(MX51_PAD_EIM_LBA, 0x494, 0x0fc, 1, 0x978, 0), /* MX51_PAD_EIM_LBA__GPIO3_1 */
+ IMX_PIN_REG(MX51_PAD_EIM_CRE, 0x4a0, 0x100, 0, 0x000, 0), /* MX51_PAD_EIM_CRE__EIM_CRE */
+ IMX_PIN_REG(MX51_PAD_EIM_CRE, 0x4a0, 0x100, 1, 0x97c, 0), /* MX51_PAD_EIM_CRE__GPIO3_2 */
+ IMX_PIN_REG(MX51_PAD_DRAM_CS1, 0x4d0, 0x104, 0, 0x000, 0), /* MX51_PAD_DRAM_CS1__DRAM_CS1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_WE_B, 0x4e4, 0x108, 3, 0x980, 0), /* MX51_PAD_NANDF_WE_B__GPIO3_3 */
+ IMX_PIN_REG(MX51_PAD_NANDF_WE_B, 0x4e4, 0x108, 0, 0x000, 0), /* MX51_PAD_NANDF_WE_B__NANDF_WE_B */
+ IMX_PIN_REG(MX51_PAD_NANDF_WE_B, 0x4e4, 0x108, 1, 0x000, 0), /* MX51_PAD_NANDF_WE_B__PATA_DIOW */
+ IMX_PIN_REG(MX51_PAD_NANDF_WE_B, 0x4e4, 0x108, 2, 0x93c, 0), /* MX51_PAD_NANDF_WE_B__SD3_DATA0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RE_B, 0x4e8, 0x10c, 3, 0x984, 0), /* MX51_PAD_NANDF_RE_B__GPIO3_4 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RE_B, 0x4e8, 0x10c, 0, 0x000, 0), /* MX51_PAD_NANDF_RE_B__NANDF_RE_B */
+ IMX_PIN_REG(MX51_PAD_NANDF_RE_B, 0x4e8, 0x10c, 1, 0x000, 0), /* MX51_PAD_NANDF_RE_B__PATA_DIOR */
+ IMX_PIN_REG(MX51_PAD_NANDF_RE_B, 0x4e8, 0x10c, 2, 0x940, 0), /* MX51_PAD_NANDF_RE_B__SD3_DATA1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_ALE, 0x4ec, 0x110, 3, 0x988, 0), /* MX51_PAD_NANDF_ALE__GPIO3_5 */
+ IMX_PIN_REG(MX51_PAD_NANDF_ALE, 0x4ec, 0x110, 0, 0x000, 0), /* MX51_PAD_NANDF_ALE__NANDF_ALE */
+ IMX_PIN_REG(MX51_PAD_NANDF_ALE, 0x4ec, 0x110, 1, 0x000, 0), /* MX51_PAD_NANDF_ALE__PATA_BUFFER_EN */
+ IMX_PIN_REG(MX51_PAD_NANDF_CLE, 0x4f0, 0x114, 3, 0x98c, 0), /* MX51_PAD_NANDF_CLE__GPIO3_6 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CLE, 0x4f0, 0x114, 0, 0x000, 0), /* MX51_PAD_NANDF_CLE__NANDF_CLE */
+ IMX_PIN_REG(MX51_PAD_NANDF_CLE, 0x4f0, 0x114, 1, 0x000, 0), /* MX51_PAD_NANDF_CLE__PATA_RESET_B */
+ IMX_PIN_REG(MX51_PAD_NANDF_WP_B, 0x4f4, 0x118, 3, 0x990, 0), /* MX51_PAD_NANDF_WP_B__GPIO3_7 */
+ IMX_PIN_REG(MX51_PAD_NANDF_WP_B, 0x4f4, 0x118, 0, 0x000, 0), /* MX51_PAD_NANDF_WP_B__NANDF_WP_B */
+ IMX_PIN_REG(MX51_PAD_NANDF_WP_B, 0x4f4, 0x118, 1, 0x000, 0), /* MX51_PAD_NANDF_WP_B__PATA_DMACK */
+ IMX_PIN_REG(MX51_PAD_NANDF_WP_B, 0x4f4, 0x118, 2, 0x944, 0), /* MX51_PAD_NANDF_WP_B__SD3_DATA2 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB0, 0x4f8, 0x11c, 5, 0x930, 0), /* MX51_PAD_NANDF_RB0__ECSPI2_SS1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB0, 0x4f8, 0x11c, 3, 0x994, 0), /* MX51_PAD_NANDF_RB0__GPIO3_8 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB0, 0x4f8, 0x11c, 0, 0x000, 0), /* MX51_PAD_NANDF_RB0__NANDF_RB0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB0, 0x4f8, 0x11c, 1, 0x000, 0), /* MX51_PAD_NANDF_RB0__PATA_DMARQ */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB0, 0x4f8, 0x11c, 2, 0x948, 0), /* MX51_PAD_NANDF_RB0__SD3_DATA3 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB1, 0x4fc, 0x120, 6, 0x91c, 0), /* MX51_PAD_NANDF_RB1__CSPI_MOSI */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB1, 0x4fc, 0x120, 2, 0x000, 0), /* MX51_PAD_NANDF_RB1__ECSPI2_RDY */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB1, 0x4fc, 0x120, 3, 0x000, 0), /* MX51_PAD_NANDF_RB1__GPIO3_9 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB1, 0x4fc, 0x120, 0, 0x000, 0), /* MX51_PAD_NANDF_RB1__NANDF_RB1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB1, 0x4fc, 0x120, 1, 0x000, 0), /* MX51_PAD_NANDF_RB1__PATA_IORDY */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB1, 0x4fc, 0x120, 5, 0x000, 0), /* MX51_PAD_NANDF_RB1__SD4_CMD */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 5, 0x9a8, 0), /* MX51_PAD_NANDF_RB2__DISP2_WAIT */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 2, 0x000, 0), /* MX51_PAD_NANDF_RB2__ECSPI2_SCLK */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 1, 0x94c, 0), /* MX51_PAD_NANDF_RB2__FEC_COL */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 3, 0x000, 0), /* MX51_PAD_NANDF_RB2__GPIO3_10 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 0, 0x000, 0), /* MX51_PAD_NANDF_RB2__NANDF_RB2 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 7, 0x000, 0), /* MX51_PAD_NANDF_RB2__USBH3_H3_DP */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 6, 0xa20, 0), /* MX51_PAD_NANDF_RB2__USBH3_NXT */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 5, 0x000, 0), /* MX51_PAD_NANDF_RB3__DISP1_WAIT */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 2, 0x000, 0), /* MX51_PAD_NANDF_RB3__ECSPI2_MISO */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 1, 0x968, 0), /* MX51_PAD_NANDF_RB3__FEC_RX_CLK */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 3, 0x000, 0), /* MX51_PAD_NANDF_RB3__GPIO3_11 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 0, 0x000, 0), /* MX51_PAD_NANDF_RB3__NANDF_RB3 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 6, 0x9f8, 0), /* MX51_PAD_NANDF_RB3__USBH3_CLK */
+ IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 7, 0x000, 0), /* MX51_PAD_NANDF_RB3__USBH3_H3_DM */
+ IMX_PIN_REG(MX51_PAD_GPIO_NAND, 0x514, 0x12c, 0, 0x998, 0), /* MX51_PAD_GPIO_NAND__GPIO_NAND */
+ IMX_PIN_REG(MX51_PAD_GPIO_NAND, 0x514, 0x12c, 1, 0x000, 0), /* MX51_PAD_GPIO_NAND__PATA_INTRQ */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS0, 0x518, 0x130, 3, 0x000, 0), /* MX51_PAD_NANDF_CS0__GPIO3_16 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS0, 0x518, 0x130, 0, 0x000, 0), /* MX51_PAD_NANDF_CS0__NANDF_CS0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS1, 0x51c, 0x134, 3, 0x000, 0), /* MX51_PAD_NANDF_CS1__GPIO3_17 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS1, 0x51c, 0x134, 0, 0x000, 0), /* MX51_PAD_NANDF_CS1__NANDF_CS1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 6, 0x914, 0), /* MX51_PAD_NANDF_CS2__CSPI_SCLK */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 2, 0x000, 0), /* MX51_PAD_NANDF_CS2__FEC_TX_ER */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 3, 0x000, 0), /* MX51_PAD_NANDF_CS2__GPIO3_18 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 0, 0x000, 0), /* MX51_PAD_NANDF_CS2__NANDF_CS2 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 1, 0x000, 0), /* MX51_PAD_NANDF_CS2__PATA_CS_0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 5, 0x000, 0), /* MX51_PAD_NANDF_CS2__SD4_CLK */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 7, 0x000, 0), /* MX51_PAD_NANDF_CS2__USBH3_H1_DP */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS3, 0x524, 0x13c, 2, 0x000, 0), /* MX51_PAD_NANDF_CS3__FEC_MDC */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS3, 0x524, 0x13c, 3, 0x000, 0), /* MX51_PAD_NANDF_CS3__GPIO3_19 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS3, 0x524, 0x13c, 0, 0x000, 0), /* MX51_PAD_NANDF_CS3__NANDF_CS3 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS3, 0x524, 0x13c, 1, 0x000, 0), /* MX51_PAD_NANDF_CS3__PATA_CS_1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS3, 0x524, 0x13c, 5, 0x000, 0), /* MX51_PAD_NANDF_CS3__SD4_DAT0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS3, 0x524, 0x13c, 7, 0x000, 0), /* MX51_PAD_NANDF_CS3__USBH3_H1_DM */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS4, 0x528, 0x140, 2, 0x000, 0), /* MX51_PAD_NANDF_CS4__FEC_TDATA1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS4, 0x528, 0x140, 3, 0x000, 0), /* MX51_PAD_NANDF_CS4__GPIO3_20 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS4, 0x528, 0x140, 0, 0x000, 0), /* MX51_PAD_NANDF_CS4__NANDF_CS4 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS4, 0x528, 0x140, 1, 0x000, 0), /* MX51_PAD_NANDF_CS4__PATA_DA_0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS4, 0x528, 0x140, 5, 0x000, 0), /* MX51_PAD_NANDF_CS4__SD4_DAT1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS4, 0x528, 0x140, 7, 0xa24, 0), /* MX51_PAD_NANDF_CS4__USBH3_STP */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS5, 0x52c, 0x144, 2, 0x000, 0), /* MX51_PAD_NANDF_CS5__FEC_TDATA2 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS5, 0x52c, 0x144, 3, 0x000, 0), /* MX51_PAD_NANDF_CS5__GPIO3_21 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS5, 0x52c, 0x144, 0, 0x000, 0), /* MX51_PAD_NANDF_CS5__NANDF_CS5 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS5, 0x52c, 0x144, 1, 0x000, 0), /* MX51_PAD_NANDF_CS5__PATA_DA_1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS5, 0x52c, 0x144, 5, 0x000, 0), /* MX51_PAD_NANDF_CS5__SD4_DAT2 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS5, 0x52c, 0x144, 7, 0xa1c, 0), /* MX51_PAD_NANDF_CS5__USBH3_DIR */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS6, 0x530, 0x148, 7, 0x928, 0), /* MX51_PAD_NANDF_CS6__CSPI_SS3 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS6, 0x530, 0x148, 2, 0x000, 0), /* MX51_PAD_NANDF_CS6__FEC_TDATA3 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS6, 0x530, 0x148, 3, 0x000, 0), /* MX51_PAD_NANDF_CS6__GPIO3_22 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS6, 0x530, 0x148, 0, 0x000, 0), /* MX51_PAD_NANDF_CS6__NANDF_CS6 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS6, 0x530, 0x148, 1, 0x000, 0), /* MX51_PAD_NANDF_CS6__PATA_DA_2 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS6, 0x530, 0x148, 5, 0x000, 0), /* MX51_PAD_NANDF_CS6__SD4_DAT3 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS7, 0x534, 0x14c, 1, 0x000, 0), /* MX51_PAD_NANDF_CS7__FEC_TX_EN */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS7, 0x534, 0x14c, 3, 0x000, 0), /* MX51_PAD_NANDF_CS7__GPIO3_23 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS7, 0x534, 0x14c, 0, 0x000, 0), /* MX51_PAD_NANDF_CS7__NANDF_CS7 */
+ IMX_PIN_REG(MX51_PAD_NANDF_CS7, 0x534, 0x14c, 5, 0x000, 0), /* MX51_PAD_NANDF_CS7__SD3_CLK */
+ IMX_PIN_REG(MX51_PAD_NANDF_RDY_INT, 0x538, 0x150, 2, 0x000, 0), /* MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RDY_INT, 0x538, 0x150, 1, 0x974, 0), /* MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK */
+ IMX_PIN_REG(MX51_PAD_NANDF_RDY_INT, 0x538, 0x150, 3, 0x000, 0), /* MX51_PAD_NANDF_RDY_INT__GPIO3_24 */
+ IMX_PIN_REG(MX51_PAD_NANDF_RDY_INT, 0x538, 0x150, 0, 0x938, 0), /* MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT */
+ IMX_PIN_REG(MX51_PAD_NANDF_RDY_INT, 0x538, 0x150, 5, 0x000, 0), /* MX51_PAD_NANDF_RDY_INT__SD3_CMD */
+ IMX_PIN_REG(MX51_PAD_NANDF_D15, 0x53c, 0x154, 2, 0x000, 0), /* MX51_PAD_NANDF_D15__ECSPI2_MOSI */
+ IMX_PIN_REG(MX51_PAD_NANDF_D15, 0x53c, 0x154, 3, 0x000, 0), /* MX51_PAD_NANDF_D15__GPIO3_25 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D15, 0x53c, 0x154, 0, 0x000, 0), /* MX51_PAD_NANDF_D15__NANDF_D15 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D15, 0x53c, 0x154, 1, 0x000, 0), /* MX51_PAD_NANDF_D15__PATA_DATA15 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D15, 0x53c, 0x154, 5, 0x000, 0), /* MX51_PAD_NANDF_D15__SD3_DAT7 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D14, 0x540, 0x158, 2, 0x934, 0), /* MX51_PAD_NANDF_D14__ECSPI2_SS3 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D14, 0x540, 0x158, 3, 0x000, 0), /* MX51_PAD_NANDF_D14__GPIO3_26 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D14, 0x540, 0x158, 0, 0x000, 0), /* MX51_PAD_NANDF_D14__NANDF_D14 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D14, 0x540, 0x158, 1, 0x000, 0), /* MX51_PAD_NANDF_D14__PATA_DATA14 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D14, 0x540, 0x158, 5, 0x000, 0), /* MX51_PAD_NANDF_D14__SD3_DAT6 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D13, 0x544, 0x15c, 2, 0x000, 0), /* MX51_PAD_NANDF_D13__ECSPI2_SS2 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D13, 0x544, 0x15c, 3, 0x000, 0), /* MX51_PAD_NANDF_D13__GPIO3_27 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D13, 0x544, 0x15c, 0, 0x000, 0), /* MX51_PAD_NANDF_D13__NANDF_D13 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D13, 0x544, 0x15c, 1, 0x000, 0), /* MX51_PAD_NANDF_D13__PATA_DATA13 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D13, 0x544, 0x15c, 5, 0x000, 0), /* MX51_PAD_NANDF_D13__SD3_DAT5 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D12, 0x548, 0x160, 2, 0x930, 1), /* MX51_PAD_NANDF_D12__ECSPI2_SS1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D12, 0x548, 0x160, 3, 0x000, 0), /* MX51_PAD_NANDF_D12__GPIO3_28 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D12, 0x548, 0x160, 0, 0x000, 0), /* MX51_PAD_NANDF_D12__NANDF_D12 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D12, 0x548, 0x160, 1, 0x000, 0), /* MX51_PAD_NANDF_D12__PATA_DATA12 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D12, 0x548, 0x160, 5, 0x000, 0), /* MX51_PAD_NANDF_D12__SD3_DAT4 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D11, 0x54c, 0x164, 2, 0x96c, 0), /* MX51_PAD_NANDF_D11__FEC_RX_DV */
+ IMX_PIN_REG(MX51_PAD_NANDF_D11, 0x54c, 0x164, 3, 0x000, 0), /* MX51_PAD_NANDF_D11__GPIO3_29 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D11, 0x54c, 0x164, 0, 0x000, 0), /* MX51_PAD_NANDF_D11__NANDF_D11 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D11, 0x54c, 0x164, 1, 0x000, 0), /* MX51_PAD_NANDF_D11__PATA_DATA11 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D11, 0x54c, 0x164, 5, 0x948, 1), /* MX51_PAD_NANDF_D11__SD3_DATA3 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D10, 0x550, 0x168, 3, 0x000, 0), /* MX51_PAD_NANDF_D10__GPIO3_30 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D10, 0x550, 0x168, 0, 0x000, 0), /* MX51_PAD_NANDF_D10__NANDF_D10 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D10, 0x550, 0x168, 1, 0x000, 0), /* MX51_PAD_NANDF_D10__PATA_DATA10 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D10, 0x550, 0x168, 5, 0x944, 1), /* MX51_PAD_NANDF_D10__SD3_DATA2 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D9, 0x554, 0x16c, 2, 0x958, 0), /* MX51_PAD_NANDF_D9__FEC_RDATA0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D9, 0x554, 0x16c, 3, 0x000, 0), /* MX51_PAD_NANDF_D9__GPIO3_31 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D9, 0x554, 0x16c, 0, 0x000, 0), /* MX51_PAD_NANDF_D9__NANDF_D9 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D9, 0x554, 0x16c, 1, 0x000, 0), /* MX51_PAD_NANDF_D9__PATA_DATA9 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D9, 0x554, 0x16c, 5, 0x940, 1), /* MX51_PAD_NANDF_D9__SD3_DATA1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D8, 0x558, 0x170, 2, 0x000, 0), /* MX51_PAD_NANDF_D8__FEC_TDATA0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D8, 0x558, 0x170, 3, 0x000, 0), /* MX51_PAD_NANDF_D8__GPIO4_0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D8, 0x558, 0x170, 0, 0x000, 0), /* MX51_PAD_NANDF_D8__NANDF_D8 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D8, 0x558, 0x170, 1, 0x000, 0), /* MX51_PAD_NANDF_D8__PATA_DATA8 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D8, 0x558, 0x170, 5, 0x93c, 1), /* MX51_PAD_NANDF_D8__SD3_DATA0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D7, 0x55c, 0x174, 3, 0x000, 0), /* MX51_PAD_NANDF_D7__GPIO4_1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D7, 0x55c, 0x174, 0, 0x000, 0), /* MX51_PAD_NANDF_D7__NANDF_D7 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D7, 0x55c, 0x174, 1, 0x000, 0), /* MX51_PAD_NANDF_D7__PATA_DATA7 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D7, 0x55c, 0x174, 5, 0x9fc, 0), /* MX51_PAD_NANDF_D7__USBH3_DATA0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D6, 0x560, 0x178, 3, 0x000, 0), /* MX51_PAD_NANDF_D6__GPIO4_2 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D6, 0x560, 0x178, 0, 0x000, 0), /* MX51_PAD_NANDF_D6__NANDF_D6 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D6, 0x560, 0x178, 1, 0x000, 0), /* MX51_PAD_NANDF_D6__PATA_DATA6 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D6, 0x560, 0x178, 2, 0x000, 0), /* MX51_PAD_NANDF_D6__SD4_LCTL */
+ IMX_PIN_REG(MX51_PAD_NANDF_D6, 0x560, 0x178, 5, 0xa00, 0), /* MX51_PAD_NANDF_D6__USBH3_DATA1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D5, 0x564, 0x17c, 3, 0x000, 0), /* MX51_PAD_NANDF_D5__GPIO4_3 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D5, 0x564, 0x17c, 0, 0x000, 0), /* MX51_PAD_NANDF_D5__NANDF_D5 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D5, 0x564, 0x17c, 1, 0x000, 0), /* MX51_PAD_NANDF_D5__PATA_DATA5 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D5, 0x564, 0x17c, 2, 0x000, 0), /* MX51_PAD_NANDF_D5__SD4_WP */
+ IMX_PIN_REG(MX51_PAD_NANDF_D5, 0x564, 0x17c, 5, 0xa04, 0), /* MX51_PAD_NANDF_D5__USBH3_DATA2 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D4, 0x568, 0x180, 3, 0x000, 0), /* MX51_PAD_NANDF_D4__GPIO4_4 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D4, 0x568, 0x180, 0, 0x000, 0), /* MX51_PAD_NANDF_D4__NANDF_D4 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D4, 0x568, 0x180, 1, 0x000, 0), /* MX51_PAD_NANDF_D4__PATA_DATA4 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D4, 0x568, 0x180, 2, 0x000, 0), /* MX51_PAD_NANDF_D4__SD4_CD */
+ IMX_PIN_REG(MX51_PAD_NANDF_D4, 0x568, 0x180, 5, 0xa08, 0), /* MX51_PAD_NANDF_D4__USBH3_DATA3 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D3, 0x56c, 0x184, 3, 0x000, 0), /* MX51_PAD_NANDF_D3__GPIO4_5 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D3, 0x56c, 0x184, 0, 0x000, 0), /* MX51_PAD_NANDF_D3__NANDF_D3 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D3, 0x56c, 0x184, 1, 0x000, 0), /* MX51_PAD_NANDF_D3__PATA_DATA3 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D3, 0x56c, 0x184, 2, 0x000, 0), /* MX51_PAD_NANDF_D3__SD4_DAT4 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D3, 0x56c, 0x184, 5, 0xa0c, 0), /* MX51_PAD_NANDF_D3__USBH3_DATA4 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D2, 0x570, 0x188, 3, 0x000, 0), /* MX51_PAD_NANDF_D2__GPIO4_6 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D2, 0x570, 0x188, 0, 0x000, 0), /* MX51_PAD_NANDF_D2__NANDF_D2 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D2, 0x570, 0x188, 1, 0x000, 0), /* MX51_PAD_NANDF_D2__PATA_DATA2 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D2, 0x570, 0x188, 2, 0x000, 0), /* MX51_PAD_NANDF_D2__SD4_DAT5 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D2, 0x570, 0x188, 5, 0xa10, 0), /* MX51_PAD_NANDF_D2__USBH3_DATA5 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D1, 0x574, 0x18c, 3, 0x000, 0), /* MX51_PAD_NANDF_D1__GPIO4_7 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D1, 0x574, 0x18c, 0, 0x000, 0), /* MX51_PAD_NANDF_D1__NANDF_D1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D1, 0x574, 0x18c, 1, 0x000, 0), /* MX51_PAD_NANDF_D1__PATA_DATA1 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D1, 0x574, 0x18c, 2, 0x000, 0), /* MX51_PAD_NANDF_D1__SD4_DAT6 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D1, 0x574, 0x18c, 5, 0xa14, 0), /* MX51_PAD_NANDF_D1__USBH3_DATA6 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D0, 0x578, 0x190, 3, 0x000, 0), /* MX51_PAD_NANDF_D0__GPIO4_8 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D0, 0x578, 0x190, 0, 0x000, 0), /* MX51_PAD_NANDF_D0__NANDF_D0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D0, 0x578, 0x190, 1, 0x000, 0), /* MX51_PAD_NANDF_D0__PATA_DATA0 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D0, 0x578, 0x190, 2, 0x000, 0), /* MX51_PAD_NANDF_D0__SD4_DAT7 */
+ IMX_PIN_REG(MX51_PAD_NANDF_D0, 0x578, 0x190, 5, 0xa18, 0), /* MX51_PAD_NANDF_D0__USBH3_DATA7 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D8, 0x57c, 0x194, 0, 0x000, 0), /* MX51_PAD_CSI1_D8__CSI1_D8 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D8, 0x57c, 0x194, 3, 0x998, 1), /* MX51_PAD_CSI1_D8__GPIO3_12 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D9, 0x580, 0x198, 0, 0x000, 0), /* MX51_PAD_CSI1_D9__CSI1_D9 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D9, 0x580, 0x198, 3, 0x000, 0), /* MX51_PAD_CSI1_D9__GPIO3_13 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D10, 0x584, 0x19c, 0, 0x000, 0), /* MX51_PAD_CSI1_D10__CSI1_D10 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D11, 0x588, 0x1a0, 0, 0x000, 0), /* MX51_PAD_CSI1_D11__CSI1_D11 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D12, 0x58c, 0x1a4, 0, 0x000, 0), /* MX51_PAD_CSI1_D12__CSI1_D12 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D13, 0x590, 0x1a8, 0, 0x000, 0), /* MX51_PAD_CSI1_D13__CSI1_D13 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D14, 0x594, 0x1ac, 0, 0x000, 0), /* MX51_PAD_CSI1_D14__CSI1_D14 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D15, 0x598, 0x1b0, 0, 0x000, 0), /* MX51_PAD_CSI1_D15__CSI1_D15 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D16, 0x59c, 0x1b4, 0, 0x000, 0), /* MX51_PAD_CSI1_D16__CSI1_D16 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D17, 0x5a0, 0x1b8, 0, 0x000, 0), /* MX51_PAD_CSI1_D17__CSI1_D17 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D18, 0x5a4, 0x1bc, 0, 0x000, 0), /* MX51_PAD_CSI1_D18__CSI1_D18 */
+ IMX_PIN_REG(MX51_PAD_CSI1_D19, 0x5a8, 0x1c0, 0, 0x000, 0), /* MX51_PAD_CSI1_D19__CSI1_D19 */
+ IMX_PIN_REG(MX51_PAD_CSI1_VSYNC, 0x5ac, 0x1c4, 0, 0x000, 0), /* MX51_PAD_CSI1_VSYNC__CSI1_VSYNC */
+ IMX_PIN_REG(MX51_PAD_CSI1_VSYNC, 0x5ac, 0x1c4, 3, 0x000, 0), /* MX51_PAD_CSI1_VSYNC__GPIO3_14 */
+ IMX_PIN_REG(MX51_PAD_CSI1_HSYNC, 0x5b0, 0x1c8, 0, 0x000, 0), /* MX51_PAD_CSI1_HSYNC__CSI1_HSYNC */
+ IMX_PIN_REG(MX51_PAD_CSI1_HSYNC, 0x5b0, 0x1c8, 3, 0x000, 0), /* MX51_PAD_CSI1_HSYNC__GPIO3_15 */
+ IMX_PIN_REG(MX51_PAD_CSI1_PIXCLK, 0x5b4, NO_MUX, 0, 0x000, 0), /* MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK */
+ IMX_PIN_REG(MX51_PAD_CSI1_MCLK, 0x5b8, NO_MUX, 0, 0x000, 0), /* MX51_PAD_CSI1_MCLK__CSI1_MCLK */
+ IMX_PIN_REG(MX51_PAD_CSI2_D12, 0x5bc, 0x1cc, 0, 0x000, 0), /* MX51_PAD_CSI2_D12__CSI2_D12 */
+ IMX_PIN_REG(MX51_PAD_CSI2_D12, 0x5bc, 0x1cc, 3, 0x000, 0), /* MX51_PAD_CSI2_D12__GPIO4_9 */
+ IMX_PIN_REG(MX51_PAD_CSI2_D13, 0x5c0, 0x1d0, 0, 0x000, 0), /* MX51_PAD_CSI2_D13__CSI2_D13 */
+ IMX_PIN_REG(MX51_PAD_CSI2_D13, 0x5c0, 0x1d0, 3, 0x000, 0), /* MX51_PAD_CSI2_D13__GPIO4_10 */
+ IMX_PIN_REG(MX51_PAD_CSI2_D14, 0x5c4, 0x1d4, 0, 0x000, 0), /* MX51_PAD_CSI2_D14__CSI2_D14 */
+ IMX_PIN_REG(MX51_PAD_CSI2_D15, 0x5c8, 0x1d8, 0, 0x000, 0), /* MX51_PAD_CSI2_D15__CSI2_D15 */
+ IMX_PIN_REG(MX51_PAD_CSI2_D16, 0x5cc, 0x1dc, 0, 0x000, 0), /* MX51_PAD_CSI2_D16__CSI2_D16 */
+ IMX_PIN_REG(MX51_PAD_CSI2_D17, 0x5d0, 0x1e0, 0, 0x000, 0), /* MX51_PAD_CSI2_D17__CSI2_D17 */
+ IMX_PIN_REG(MX51_PAD_CSI2_D18, 0x5d4, 0x1e4, 0, 0x000, 0), /* MX51_PAD_CSI2_D18__CSI2_D18 */
+ IMX_PIN_REG(MX51_PAD_CSI2_D18, 0x5d4, 0x1e4, 3, 0x000, 0), /* MX51_PAD_CSI2_D18__GPIO4_11 */
+ IMX_PIN_REG(MX51_PAD_CSI2_D19, 0x5d8, 0x1e8, 0, 0x000, 0), /* MX51_PAD_CSI2_D19__CSI2_D19 */
+ IMX_PIN_REG(MX51_PAD_CSI2_D19, 0x5d8, 0x1e8, 3, 0x000, 0), /* MX51_PAD_CSI2_D19__GPIO4_12 */
+ IMX_PIN_REG(MX51_PAD_CSI2_VSYNC, 0x5dc, 0x1ec, 0, 0x000, 0), /* MX51_PAD_CSI2_VSYNC__CSI2_VSYNC */
+ IMX_PIN_REG(MX51_PAD_CSI2_VSYNC, 0x5dc, 0x1ec, 3, 0x000, 0), /* MX51_PAD_CSI2_VSYNC__GPIO4_13 */
+ IMX_PIN_REG(MX51_PAD_CSI2_HSYNC, 0x5e0, 0x1f0, 0, 0x000, 0), /* MX51_PAD_CSI2_HSYNC__CSI2_HSYNC */
+ IMX_PIN_REG(MX51_PAD_CSI2_HSYNC, 0x5e0, 0x1f0, 3, 0x000, 0), /* MX51_PAD_CSI2_HSYNC__GPIO4_14 */
+ IMX_PIN_REG(MX51_PAD_CSI2_PIXCLK, 0x5e4, 0x1f4, 0, 0x000, 0), /* MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK */
+ IMX_PIN_REG(MX51_PAD_CSI2_PIXCLK, 0x5e4, 0x1f4, 3, 0x000, 0), /* MX51_PAD_CSI2_PIXCLK__GPIO4_15 */
+ IMX_PIN_REG(MX51_PAD_I2C1_CLK, 0x5e8, 0x1f8, 3, 0x000, 0), /* MX51_PAD_I2C1_CLK__GPIO4_16 */
+ IMX_PIN_REG(MX51_PAD_I2C1_CLK, 0x5e8, 0x1f8, 0, 0x000, 0), /* MX51_PAD_I2C1_CLK__I2C1_CLK */
+ IMX_PIN_REG(MX51_PAD_I2C1_DAT, 0x5ec, 0x1fc, 3, 0x000, 0), /* MX51_PAD_I2C1_DAT__GPIO4_17 */
+ IMX_PIN_REG(MX51_PAD_I2C1_DAT, 0x5ec, 0x1fc, 0, 0x000, 0), /* MX51_PAD_I2C1_DAT__I2C1_DAT */
+ IMX_PIN_REG(MX51_PAD_AUD3_BB_TXD, 0x5f0, 0x200, 0, 0x000, 0), /* MX51_PAD_AUD3_BB_TXD__AUD3_TXD */
+ IMX_PIN_REG(MX51_PAD_AUD3_BB_TXD, 0x5f0, 0x200, 3, 0x000, 0), /* MX51_PAD_AUD3_BB_TXD__GPIO4_18 */
+ IMX_PIN_REG(MX51_PAD_AUD3_BB_RXD, 0x5f4, 0x204, 0, 0x000, 0), /* MX51_PAD_AUD3_BB_RXD__AUD3_RXD */
+ IMX_PIN_REG(MX51_PAD_AUD3_BB_RXD, 0x5f4, 0x204, 3, 0x000, 0), /* MX51_PAD_AUD3_BB_RXD__GPIO4_19 */
+ IMX_PIN_REG(MX51_PAD_AUD3_BB_RXD, 0x5f4, 0x204, 1, 0x9f4, 2), /* MX51_PAD_AUD3_BB_RXD__UART3_RXD */
+ IMX_PIN_REG(MX51_PAD_AUD3_BB_CK, 0x5f8, 0x208, 0, 0x000, 0), /* MX51_PAD_AUD3_BB_CK__AUD3_TXC */
+ IMX_PIN_REG(MX51_PAD_AUD3_BB_CK, 0x5f8, 0x208, 3, 0x000, 0), /* MX51_PAD_AUD3_BB_CK__GPIO4_20 */
+ IMX_PIN_REG(MX51_PAD_AUD3_BB_FS, 0x5fc, 0x20c, 0, 0x000, 0), /* MX51_PAD_AUD3_BB_FS__AUD3_TXFS */
+ IMX_PIN_REG(MX51_PAD_AUD3_BB_FS, 0x5fc, 0x20c, 3, 0x000, 0), /* MX51_PAD_AUD3_BB_FS__GPIO4_21 */
+ IMX_PIN_REG(MX51_PAD_AUD3_BB_FS, 0x5fc, 0x20c, 1, 0x000, 0), /* MX51_PAD_AUD3_BB_FS__UART3_TXD */
+ IMX_PIN_REG(MX51_PAD_CSPI1_MOSI, 0x600, 0x210, 0, 0x000, 0), /* MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI */
+ IMX_PIN_REG(MX51_PAD_CSPI1_MOSI, 0x600, 0x210, 3, 0x000, 0), /* MX51_PAD_CSPI1_MOSI__GPIO4_22 */
+ IMX_PIN_REG(MX51_PAD_CSPI1_MOSI, 0x600, 0x210, 1, 0x9b4, 1), /* MX51_PAD_CSPI1_MOSI__I2C1_SDA */
+ IMX_PIN_REG(MX51_PAD_CSPI1_MISO, 0x604, 0x214, 1, 0x8c4, 1), /* MX51_PAD_CSPI1_MISO__AUD4_RXD */
+ IMX_PIN_REG(MX51_PAD_CSPI1_MISO, 0x604, 0x214, 0, 0x000, 0), /* MX51_PAD_CSPI1_MISO__ECSPI1_MISO */
+ IMX_PIN_REG(MX51_PAD_CSPI1_MISO, 0x604, 0x214, 3, 0x000, 0), /* MX51_PAD_CSPI1_MISO__GPIO4_23 */
+ IMX_PIN_REG(MX51_PAD_CSPI1_SS0, 0x608, 0x218, 1, 0x8cc, 1), /* MX51_PAD_CSPI1_SS0__AUD4_TXC */
+ IMX_PIN_REG(MX51_PAD_CSPI1_SS0, 0x608, 0x218, 0, 0x000, 0), /* MX51_PAD_CSPI1_SS0__ECSPI1_SS0 */
+ IMX_PIN_REG(MX51_PAD_CSPI1_SS0, 0x608, 0x218, 3, 0x000, 0), /* MX51_PAD_CSPI1_SS0__GPIO4_24 */
+ IMX_PIN_REG(MX51_PAD_CSPI1_SS1, 0x60c, 0x21c, 1, 0x8c8, 1), /* MX51_PAD_CSPI1_SS1__AUD4_TXD */
+ IMX_PIN_REG(MX51_PAD_CSPI1_SS1, 0x60c, 0x21c, 0, 0x000, 0), /* MX51_PAD_CSPI1_SS1__ECSPI1_SS1 */
+ IMX_PIN_REG(MX51_PAD_CSPI1_SS1, 0x60c, 0x21c, 3, 0x000, 0), /* MX51_PAD_CSPI1_SS1__GPIO4_25 */
+ IMX_PIN_REG(MX51_PAD_CSPI1_RDY, 0x610, 0x220, 1, 0x8d0, 1), /* MX51_PAD_CSPI1_RDY__AUD4_TXFS */
+ IMX_PIN_REG(MX51_PAD_CSPI1_RDY, 0x610, 0x220, 0, 0x000, 0), /* MX51_PAD_CSPI1_RDY__ECSPI1_RDY */
+ IMX_PIN_REG(MX51_PAD_CSPI1_RDY, 0x610, 0x220, 3, 0x000, 0), /* MX51_PAD_CSPI1_RDY__GPIO4_26 */
+ IMX_PIN_REG(MX51_PAD_CSPI1_SCLK, 0x614, 0x224, 0, 0x000, 0), /* MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK */
+ IMX_PIN_REG(MX51_PAD_CSPI1_SCLK, 0x614, 0x224, 3, 0x000, 0), /* MX51_PAD_CSPI1_SCLK__GPIO4_27 */
+ IMX_PIN_REG(MX51_PAD_CSPI1_SCLK, 0x614, 0x224, 1, 0x9b0, 1), /* MX51_PAD_CSPI1_SCLK__I2C1_SCL */
+ IMX_PIN_REG(MX51_PAD_UART1_RXD, 0x618, 0x228, 3, 0x000, 0), /* MX51_PAD_UART1_RXD__GPIO4_28 */
+ IMX_PIN_REG(MX51_PAD_UART1_RXD, 0x618, 0x228, 0, 0x9e4, 0), /* MX51_PAD_UART1_RXD__UART1_RXD */
+ IMX_PIN_REG(MX51_PAD_UART1_TXD, 0x61c, 0x22c, 3, 0x000, 0), /* MX51_PAD_UART1_TXD__GPIO4_29 */
+ IMX_PIN_REG(MX51_PAD_UART1_TXD, 0x61c, 0x22c, 1, 0x000, 0), /* MX51_PAD_UART1_TXD__PWM2_PWMO */
+ IMX_PIN_REG(MX51_PAD_UART1_TXD, 0x61c, 0x22c, 0, 0x000, 0), /* MX51_PAD_UART1_TXD__UART1_TXD */
+ IMX_PIN_REG(MX51_PAD_UART1_RTS, 0x620, 0x230, 3, 0x000, 0), /* MX51_PAD_UART1_RTS__GPIO4_30 */
+ IMX_PIN_REG(MX51_PAD_UART1_RTS, 0x620, 0x230, 0, 0x9e0, 0), /* MX51_PAD_UART1_RTS__UART1_RTS */
+ IMX_PIN_REG(MX51_PAD_UART1_CTS, 0x624, 0x234, 3, 0x000, 0), /* MX51_PAD_UART1_CTS__GPIO4_31 */
+ IMX_PIN_REG(MX51_PAD_UART1_CTS, 0x624, 0x234, 0, 0x000, 0), /* MX51_PAD_UART1_CTS__UART1_CTS */
+ IMX_PIN_REG(MX51_PAD_UART2_RXD, 0x628, 0x238, 1, 0x000, 0), /* MX51_PAD_UART2_RXD__FIRI_TXD */
+ IMX_PIN_REG(MX51_PAD_UART2_RXD, 0x628, 0x238, 3, 0x000, 0), /* MX51_PAD_UART2_RXD__GPIO1_20 */
+ IMX_PIN_REG(MX51_PAD_UART2_RXD, 0x628, 0x238, 0, 0x9ec, 2), /* MX51_PAD_UART2_RXD__UART2_RXD */
+ IMX_PIN_REG(MX51_PAD_UART2_TXD, 0x62c, 0x23c, 1, 0x000, 0), /* MX51_PAD_UART2_TXD__FIRI_RXD */
+ IMX_PIN_REG(MX51_PAD_UART2_TXD, 0x62c, 0x23c, 3, 0x000, 0), /* MX51_PAD_UART2_TXD__GPIO1_21 */
+ IMX_PIN_REG(MX51_PAD_UART2_TXD, 0x62c, 0x23c, 0, 0x000, 0), /* MX51_PAD_UART2_TXD__UART2_TXD */
+ IMX_PIN_REG(MX51_PAD_UART3_RXD, 0x630, 0x240, 2, 0x000, 0), /* MX51_PAD_UART3_RXD__CSI1_D0 */
+ IMX_PIN_REG(MX51_PAD_UART3_RXD, 0x630, 0x240, 3, 0x000, 0), /* MX51_PAD_UART3_RXD__GPIO1_22 */
+ IMX_PIN_REG(MX51_PAD_UART3_RXD, 0x630, 0x240, 0, 0x000, 0), /* MX51_PAD_UART3_RXD__UART1_DTR */
+ IMX_PIN_REG(MX51_PAD_UART3_RXD, 0x630, 0x240, 1, 0x9f4, 4), /* MX51_PAD_UART3_RXD__UART3_RXD */
+ IMX_PIN_REG(MX51_PAD_UART3_TXD, 0x634, 0x244, 2, 0x000, 0), /* MX51_PAD_UART3_TXD__CSI1_D1 */
+ IMX_PIN_REG(MX51_PAD_UART3_TXD, 0x634, 0x244, 3, 0x000, 0), /* MX51_PAD_UART3_TXD__GPIO1_23 */
+ IMX_PIN_REG(MX51_PAD_UART3_TXD, 0x634, 0x244, 0, 0x000, 0), /* MX51_PAD_UART3_TXD__UART1_DSR */
+ IMX_PIN_REG(MX51_PAD_UART3_TXD, 0x634, 0x244, 1, 0x000, 0), /* MX51_PAD_UART3_TXD__UART3_TXD */
+ IMX_PIN_REG(MX51_PAD_OWIRE_LINE, 0x638, 0x248, 3, 0x000, 0), /* MX51_PAD_OWIRE_LINE__GPIO1_24 */
+ IMX_PIN_REG(MX51_PAD_OWIRE_LINE, 0x638, 0x248, 0, 0x000, 0), /* MX51_PAD_OWIRE_LINE__OWIRE_LINE */
+ IMX_PIN_REG(MX51_PAD_OWIRE_LINE, 0x638, 0x248, 6, 0x000, 0), /* MX51_PAD_OWIRE_LINE__SPDIF_OUT */
+ IMX_PIN_REG(MX51_PAD_KEY_ROW0, 0x63c, 0x24c, 0, 0x000, 0), /* MX51_PAD_KEY_ROW0__KEY_ROW0 */
+ IMX_PIN_REG(MX51_PAD_KEY_ROW1, 0x640, 0x250, 0, 0x000, 0), /* MX51_PAD_KEY_ROW1__KEY_ROW1 */
+ IMX_PIN_REG(MX51_PAD_KEY_ROW2, 0x644, 0x254, 0, 0x000, 0), /* MX51_PAD_KEY_ROW2__KEY_ROW2 */
+ IMX_PIN_REG(MX51_PAD_KEY_ROW3, 0x648, 0x258, 0, 0x000, 0), /* MX51_PAD_KEY_ROW3__KEY_ROW3 */
+ IMX_PIN_REG(MX51_PAD_KEY_COL0, 0x64c, 0x25c, 0, 0x000, 0), /* MX51_PAD_KEY_COL0__KEY_COL0 */
+ IMX_PIN_REG(MX51_PAD_KEY_COL0, 0x64c, 0x25c, 7, 0x90c, 0), /* MX51_PAD_KEY_COL0__PLL1_BYP */
+ IMX_PIN_REG(MX51_PAD_KEY_COL1, 0x650, 0x260, 0, 0x000, 0), /* MX51_PAD_KEY_COL1__KEY_COL1 */
+ IMX_PIN_REG(MX51_PAD_KEY_COL1, 0x650, 0x260, 7, 0x910, 0), /* MX51_PAD_KEY_COL1__PLL2_BYP */
+ IMX_PIN_REG(MX51_PAD_KEY_COL2, 0x654, 0x264, 0, 0x000, 0), /* MX51_PAD_KEY_COL2__KEY_COL2 */
+ IMX_PIN_REG(MX51_PAD_KEY_COL2, 0x654, 0x264, 7, 0x000, 0), /* MX51_PAD_KEY_COL2__PLL3_BYP */
+ IMX_PIN_REG(MX51_PAD_KEY_COL3, 0x658, 0x268, 0, 0x000, 0), /* MX51_PAD_KEY_COL3__KEY_COL3 */
+ IMX_PIN_REG(MX51_PAD_KEY_COL4, 0x65c, 0x26c, 3, 0x9b8, 1), /* MX51_PAD_KEY_COL4__I2C2_SCL */
+ IMX_PIN_REG(MX51_PAD_KEY_COL4, 0x65c, 0x26c, 0, 0x000, 0), /* MX51_PAD_KEY_COL4__KEY_COL4 */
+ IMX_PIN_REG(MX51_PAD_KEY_COL4, 0x65c, 0x26c, 6, 0x000, 0), /* MX51_PAD_KEY_COL4__SPDIF_OUT1 */
+ IMX_PIN_REG(MX51_PAD_KEY_COL4, 0x65c, 0x26c, 1, 0x000, 0), /* MX51_PAD_KEY_COL4__UART1_RI */
+ IMX_PIN_REG(MX51_PAD_KEY_COL4, 0x65c, 0x26c, 2, 0x9f0, 4), /* MX51_PAD_KEY_COL4__UART3_RTS */
+ IMX_PIN_REG(MX51_PAD_KEY_COL5, 0x660, 0x270, 3, 0x9bc, 1), /* MX51_PAD_KEY_COL5__I2C2_SDA */
+ IMX_PIN_REG(MX51_PAD_KEY_COL5, 0x660, 0x270, 0, 0x000, 0), /* MX51_PAD_KEY_COL5__KEY_COL5 */
+ IMX_PIN_REG(MX51_PAD_KEY_COL5, 0x660, 0x270, 1, 0x000, 0), /* MX51_PAD_KEY_COL5__UART1_DCD */
+ IMX_PIN_REG(MX51_PAD_KEY_COL5, 0x660, 0x270, 2, 0x000, 0), /* MX51_PAD_KEY_COL5__UART3_CTS */
+ IMX_PIN_REG(MX51_PAD_USBH1_CLK, 0x678, 0x278, 1, 0x914, 1), /* MX51_PAD_USBH1_CLK__CSPI_SCLK */
+ IMX_PIN_REG(MX51_PAD_USBH1_CLK, 0x678, 0x278, 2, 0x000, 0), /* MX51_PAD_USBH1_CLK__GPIO1_25 */
+ IMX_PIN_REG(MX51_PAD_USBH1_CLK, 0x678, 0x278, 5, 0x9b8, 2), /* MX51_PAD_USBH1_CLK__I2C2_SCL */
+ IMX_PIN_REG(MX51_PAD_USBH1_CLK, 0x678, 0x278, 0, 0x000, 0), /* MX51_PAD_USBH1_CLK__USBH1_CLK */
+ IMX_PIN_REG(MX51_PAD_USBH1_DIR, 0x67c, 0x27c, 1, 0x91c, 1), /* MX51_PAD_USBH1_DIR__CSPI_MOSI */
+ IMX_PIN_REG(MX51_PAD_USBH1_DIR, 0x67c, 0x27c, 2, 0x000, 0), /* MX51_PAD_USBH1_DIR__GPIO1_26 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DIR, 0x67c, 0x27c, 5, 0x9bc, 2), /* MX51_PAD_USBH1_DIR__I2C2_SDA */
+ IMX_PIN_REG(MX51_PAD_USBH1_DIR, 0x67c, 0x27c, 0, 0x000, 0), /* MX51_PAD_USBH1_DIR__USBH1_DIR */
+ IMX_PIN_REG(MX51_PAD_USBH1_STP, 0x680, 0x280, 1, 0x000, 0), /* MX51_PAD_USBH1_STP__CSPI_RDY */
+ IMX_PIN_REG(MX51_PAD_USBH1_STP, 0x680, 0x280, 2, 0x000, 0), /* MX51_PAD_USBH1_STP__GPIO1_27 */
+ IMX_PIN_REG(MX51_PAD_USBH1_STP, 0x680, 0x280, 5, 0x9f4, 6), /* MX51_PAD_USBH1_STP__UART3_RXD */
+ IMX_PIN_REG(MX51_PAD_USBH1_STP, 0x680, 0x280, 0, 0x000, 0), /* MX51_PAD_USBH1_STP__USBH1_STP */
+ IMX_PIN_REG(MX51_PAD_USBH1_NXT, 0x684, 0x284, 1, 0x918, 0), /* MX51_PAD_USBH1_NXT__CSPI_MISO */
+ IMX_PIN_REG(MX51_PAD_USBH1_NXT, 0x684, 0x284, 2, 0x000, 0), /* MX51_PAD_USBH1_NXT__GPIO1_28 */
+ IMX_PIN_REG(MX51_PAD_USBH1_NXT, 0x684, 0x284, 5, 0x000, 0), /* MX51_PAD_USBH1_NXT__UART3_TXD */
+ IMX_PIN_REG(MX51_PAD_USBH1_NXT, 0x684, 0x284, 0, 0x000, 0), /* MX51_PAD_USBH1_NXT__USBH1_NXT */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA0, 0x688, 0x288, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA0__GPIO1_11 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA0, 0x688, 0x288, 1, 0x000, 0), /* MX51_PAD_USBH1_DATA0__UART2_CTS */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA0, 0x688, 0x288, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA0__USBH1_DATA0 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA1, 0x68c, 0x28c, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA1__GPIO1_12 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA1, 0x68c, 0x28c, 1, 0x9ec, 4), /* MX51_PAD_USBH1_DATA1__UART2_RXD */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA1, 0x68c, 0x28c, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA1__USBH1_DATA1 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA2, 0x690, 0x290, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA2__GPIO1_13 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA2, 0x690, 0x290, 1, 0x000, 0), /* MX51_PAD_USBH1_DATA2__UART2_TXD */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA2, 0x690, 0x290, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA2__USBH1_DATA2 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA3, 0x694, 0x294, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA3__GPIO1_14 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA3, 0x694, 0x294, 1, 0x9e8, 5), /* MX51_PAD_USBH1_DATA3__UART2_RTS */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA3, 0x694, 0x294, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA3__USBH1_DATA3 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA4, 0x698, 0x298, 1, 0x000, 0), /* MX51_PAD_USBH1_DATA4__CSPI_SS0 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA4, 0x698, 0x298, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA4__GPIO1_15 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA4, 0x698, 0x298, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA4__USBH1_DATA4 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA5, 0x69c, 0x29c, 1, 0x920, 0), /* MX51_PAD_USBH1_DATA5__CSPI_SS1 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA5, 0x69c, 0x29c, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA5__GPIO1_16 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA5, 0x69c, 0x29c, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA5__USBH1_DATA5 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA6, 0x6a0, 0x2a0, 1, 0x928, 1), /* MX51_PAD_USBH1_DATA6__CSPI_SS3 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA6, 0x6a0, 0x2a0, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA6__GPIO1_17 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA6, 0x6a0, 0x2a0, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA6__USBH1_DATA6 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA7, 0x6a4, 0x2a4, 1, 0x000, 0), /* MX51_PAD_USBH1_DATA7__ECSPI1_SS3 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA7, 0x6a4, 0x2a4, 5, 0x934, 1), /* MX51_PAD_USBH1_DATA7__ECSPI2_SS3 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA7, 0x6a4, 0x2a4, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA7__GPIO1_18 */
+ IMX_PIN_REG(MX51_PAD_USBH1_DATA7, 0x6a4, 0x2a4, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA7__USBH1_DATA7 */
+ IMX_PIN_REG(MX51_PAD_DI1_PIN11, 0x6a8, 0x2a8, 0, 0x000, 0), /* MX51_PAD_DI1_PIN11__DI1_PIN11 */
+ IMX_PIN_REG(MX51_PAD_DI1_PIN11, 0x6a8, 0x2a8, 7, 0x000, 0), /* MX51_PAD_DI1_PIN11__ECSPI1_SS2 */
+ IMX_PIN_REG(MX51_PAD_DI1_PIN11, 0x6a8, 0x2a8, 4, 0x000, 0), /* MX51_PAD_DI1_PIN11__GPIO3_0 */
+ IMX_PIN_REG(MX51_PAD_DI1_PIN12, 0x6ac, 0x2ac, 0, 0x000, 0), /* MX51_PAD_DI1_PIN12__DI1_PIN12 */
+ IMX_PIN_REG(MX51_PAD_DI1_PIN12, 0x6ac, 0x2ac, 4, 0x978, 1), /* MX51_PAD_DI1_PIN12__GPIO3_1 */
+ IMX_PIN_REG(MX51_PAD_DI1_PIN13, 0x6b0, 0x2b0, 0, 0x000, 0), /* MX51_PAD_DI1_PIN13__DI1_PIN13 */
+ IMX_PIN_REG(MX51_PAD_DI1_PIN13, 0x6b0, 0x2b0, 4, 0x97c, 1), /* MX51_PAD_DI1_PIN13__GPIO3_2 */
+ IMX_PIN_REG(MX51_PAD_DI1_D0_CS, 0x6b4, 0x2b4, 0, 0x000, 0), /* MX51_PAD_DI1_D0_CS__DI1_D0_CS */
+ IMX_PIN_REG(MX51_PAD_DI1_D0_CS, 0x6b4, 0x2b4, 4, 0x980, 1), /* MX51_PAD_DI1_D0_CS__GPIO3_3 */
+ IMX_PIN_REG(MX51_PAD_DI1_D1_CS, 0x6b8, 0x2b8, 0, 0x000, 0), /* MX51_PAD_DI1_D1_CS__DI1_D1_CS */
+ IMX_PIN_REG(MX51_PAD_DI1_D1_CS, 0x6b8, 0x2b8, 2, 0x000, 0), /* MX51_PAD_DI1_D1_CS__DISP1_PIN14 */
+ IMX_PIN_REG(MX51_PAD_DI1_D1_CS, 0x6b8, 0x2b8, 3, 0x000, 0), /* MX51_PAD_DI1_D1_CS__DISP1_PIN5 */
+ IMX_PIN_REG(MX51_PAD_DI1_D1_CS, 0x6b8, 0x2b8, 4, 0x984, 1), /* MX51_PAD_DI1_D1_CS__GPIO3_4 */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_DIN, 0x6bc, 0x2bc, 2, 0x9a4, 1), /* MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1 */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_DIN, 0x6bc, 0x2bc, 0, 0x9c4, 0), /* MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_DIN, 0x6bc, 0x2bc, 4, 0x988, 1), /* MX51_PAD_DISPB2_SER_DIN__GPIO3_5 */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_DIO, 0x6c0, 0x2c0, 3, 0x000, 0), /* MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6 */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_DIO, 0x6c0, 0x2c0, 0, 0x9c4, 1), /* MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_DIO, 0x6c0, 0x2c0, 4, 0x98c, 1), /* MX51_PAD_DISPB2_SER_DIO__GPIO3_6 */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_CLK, 0x6c4, 0x2c4, 2, 0x000, 0), /* MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17 */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_CLK, 0x6c4, 0x2c4, 3, 0x000, 0), /* MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7 */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_CLK, 0x6c4, 0x2c4, 0, 0x000, 0), /* MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_CLK, 0x6c4, 0x2c4, 4, 0x990, 1), /* MX51_PAD_DISPB2_SER_CLK__GPIO3_7 */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_RS, 0x6c8, 0x2c8, 2, 0x000, 0), /* MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_RS, 0x6c8, 0x2c8, 2, 0x000, 0), /* MX51_PAD_DISPB2_SER_RS__DISP1_PIN16 */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_RS, 0x6c8, 0x2c8, 3, 0x000, 0), /* MX51_PAD_DISPB2_SER_RS__DISP1_PIN8 */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_RS, 0x6c8, 0x2c8, 0, 0x000, 0), /* MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_RS, 0x6c8, 0x2c8, 0, 0x000, 0), /* MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS */
+ IMX_PIN_REG(MX51_PAD_DISPB2_SER_RS, 0x6c8, 0x2c8, 4, 0x994, 1), /* MX51_PAD_DISPB2_SER_RS__GPIO3_8 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT0, 0x6cc, 0x2cc, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT0__DISP1_DAT0 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT1, 0x6d0, 0x2d0, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT1__DISP1_DAT1 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT2, 0x6d4, 0x2d4, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT2__DISP1_DAT2 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT3, 0x6d8, 0x2d8, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT3__DISP1_DAT3 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT4, 0x6dc, 0x2dc, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT4__DISP1_DAT4 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT5, 0x6e0, 0x2e0, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT5__DISP1_DAT5 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT6, 0x6e4, 0x2e4, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT6__BOOT_USB_SRC */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT6, 0x6e4, 0x2e4, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT6__DISP1_DAT6 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT7, 0x6e8, 0x2e8, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT7, 0x6e8, 0x2e8, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT7__DISP1_DAT7 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT8, 0x6ec, 0x2ec, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT8__BOOT_SRC0 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT8, 0x6ec, 0x2ec, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT8__DISP1_DAT8 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT9, 0x6f0, 0x2f0, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT9__BOOT_SRC1 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT9, 0x6f0, 0x2f0, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT9__DISP1_DAT9 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT10, 0x6f4, 0x2f4, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT10, 0x6f4, 0x2f4, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT10__DISP1_DAT10 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT11, 0x6f8, 0x2f8, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT11, 0x6f8, 0x2f8, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT11__DISP1_DAT11 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT12, 0x6fc, 0x2fc, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT12, 0x6fc, 0x2fc, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT12__DISP1_DAT12 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT13, 0x700, 0x300, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT13, 0x700, 0x300, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT13__DISP1_DAT13 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT14, 0x704, 0x304, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT14, 0x704, 0x304, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT14__DISP1_DAT14 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT15, 0x708, 0x308, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT15, 0x708, 0x308, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT15__DISP1_DAT15 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT16, 0x70c, 0x30c, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT16, 0x70c, 0x30c, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT16__DISP1_DAT16 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT17, 0x710, 0x310, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT17, 0x710, 0x310, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT17__DISP1_DAT17 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT18, 0x714, 0x314, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT18, 0x714, 0x314, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT18__DISP1_DAT18 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT18, 0x714, 0x314, 5, 0x000, 0), /* MX51_PAD_DISP1_DAT18__DISP2_PIN11 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT18, 0x714, 0x314, 4, 0x000, 0), /* MX51_PAD_DISP1_DAT18__DISP2_PIN5 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT19, 0x718, 0x318, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT19, 0x718, 0x318, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT19__DISP1_DAT19 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT19, 0x718, 0x318, 5, 0x000, 0), /* MX51_PAD_DISP1_DAT19__DISP2_PIN12 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT19, 0x718, 0x318, 4, 0x000, 0), /* MX51_PAD_DISP1_DAT19__DISP2_PIN6 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT20, 0x71c, 0x31c, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT20, 0x71c, 0x31c, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT20__DISP1_DAT20 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT20, 0x71c, 0x31c, 5, 0x000, 0), /* MX51_PAD_DISP1_DAT20__DISP2_PIN13 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT20, 0x71c, 0x31c, 4, 0x000, 0), /* MX51_PAD_DISP1_DAT20__DISP2_PIN7 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT21, 0x720, 0x320, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT21, 0x720, 0x320, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT21__DISP1_DAT21 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT21, 0x720, 0x320, 5, 0x000, 0), /* MX51_PAD_DISP1_DAT21__DISP2_PIN14 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT21, 0x720, 0x320, 4, 0x000, 0), /* MX51_PAD_DISP1_DAT21__DISP2_PIN8 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT22, 0x724, 0x324, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT22, 0x724, 0x324, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT22__DISP1_DAT22 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT22, 0x724, 0x324, 6, 0x000, 0), /* MX51_PAD_DISP1_DAT22__DISP2_D0_CS */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT22, 0x724, 0x324, 5, 0x000, 0), /* MX51_PAD_DISP1_DAT22__DISP2_DAT16 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT23, 0x728, 0x328, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT23, 0x728, 0x328, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT23__DISP1_DAT23 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT23, 0x728, 0x328, 6, 0x000, 0), /* MX51_PAD_DISP1_DAT23__DISP2_D1_CS */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT23, 0x728, 0x328, 5, 0x000, 0), /* MX51_PAD_DISP1_DAT23__DISP2_DAT17 */
+ IMX_PIN_REG(MX51_PAD_DISP1_DAT23, 0x728, 0x328, 4, 0x000, 0), /* MX51_PAD_DISP1_DAT23__DISP2_SER_CS */
+ IMX_PIN_REG(MX51_PAD_DI1_PIN3, 0x72c, 0x32c, 0, 0x000, 0), /* MX51_PAD_DI1_PIN3__DI1_PIN3 */
+ IMX_PIN_REG(MX51_PAD_DI1_PIN2, 0x734, 0x330, 0, 0x000, 0), /* MX51_PAD_DI1_PIN2__DI1_PIN2 */
+ IMX_PIN_REG(MX51_PAD_DI_GP2, 0x740, 0x338, 0, 0x000, 0), /* MX51_PAD_DI_GP2__DISP1_SER_CLK */
+ IMX_PIN_REG(MX51_PAD_DI_GP2, 0x740, 0x338, 2, 0x9a8, 1), /* MX51_PAD_DI_GP2__DISP2_WAIT */
+ IMX_PIN_REG(MX51_PAD_DI_GP3, 0x744, 0x33c, 3, 0x9a0, 1), /* MX51_PAD_DI_GP3__CSI1_DATA_EN */
+ IMX_PIN_REG(MX51_PAD_DI_GP3, 0x744, 0x33c, 0, 0x9c0, 0), /* MX51_PAD_DI_GP3__DISP1_SER_DIO */
+ IMX_PIN_REG(MX51_PAD_DI_GP3, 0x744, 0x33c, 2, 0x000, 0), /* MX51_PAD_DI_GP3__FEC_TX_ER */
+ IMX_PIN_REG(MX51_PAD_DI2_PIN4, 0x748, 0x340, 3, 0x99c, 1), /* MX51_PAD_DI2_PIN4__CSI2_DATA_EN */
+ IMX_PIN_REG(MX51_PAD_DI2_PIN4, 0x748, 0x340, 0, 0x000, 0), /* MX51_PAD_DI2_PIN4__DI2_PIN4 */
+ IMX_PIN_REG(MX51_PAD_DI2_PIN4, 0x748, 0x340, 2, 0x950, 1), /* MX51_PAD_DI2_PIN4__FEC_CRS */
+ IMX_PIN_REG(MX51_PAD_DI2_PIN2, 0x74c, 0x344, 0, 0x000, 0), /* MX51_PAD_DI2_PIN2__DI2_PIN2 */
+ IMX_PIN_REG(MX51_PAD_DI2_PIN2, 0x74c, 0x344, 2, 0x000, 0), /* MX51_PAD_DI2_PIN2__FEC_MDC */
+ IMX_PIN_REG(MX51_PAD_DI2_PIN3, 0x750, 0x348, 0, 0x000, 0), /* MX51_PAD_DI2_PIN3__DI2_PIN3 */
+ IMX_PIN_REG(MX51_PAD_DI2_PIN3, 0x750, 0x348, 2, 0x954, 1), /* MX51_PAD_DI2_PIN3__FEC_MDIO */
+ IMX_PIN_REG(MX51_PAD_DI2_DISP_CLK, 0x754, 0x34c, 0, 0x000, 0), /* MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK */
+ IMX_PIN_REG(MX51_PAD_DI2_DISP_CLK, 0x754, 0x34c, 2, 0x95c, 1), /* MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 */
+ IMX_PIN_REG(MX51_PAD_DI_GP4, 0x758, 0x350, 4, 0x000, 0), /* MX51_PAD_DI_GP4__DI2_PIN15 */
+ IMX_PIN_REG(MX51_PAD_DI_GP4, 0x758, 0x350, 0, 0x9c0, 1), /* MX51_PAD_DI_GP4__DISP1_SER_DIN */
+ IMX_PIN_REG(MX51_PAD_DI_GP4, 0x758, 0x350, 3, 0x000, 0), /* MX51_PAD_DI_GP4__DISP2_PIN1 */
+ IMX_PIN_REG(MX51_PAD_DI_GP4, 0x758, 0x350, 2, 0x960, 1), /* MX51_PAD_DI_GP4__FEC_RDATA2 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT0, 0x75c, 0x354, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT0__DISP2_DAT0 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT0, 0x75c, 0x354, 2, 0x964, 1), /* MX51_PAD_DISP2_DAT0__FEC_RDATA3 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT0, 0x75c, 0x354, 4, 0x9c8, 1), /* MX51_PAD_DISP2_DAT0__KEY_COL6 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT0, 0x75c, 0x354, 5, 0x9f4, 8), /* MX51_PAD_DISP2_DAT0__UART3_RXD */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT0, 0x75c, 0x354, 3, 0x9f8, 1), /* MX51_PAD_DISP2_DAT0__USBH3_CLK */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT1, 0x760, 0x358, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT1__DISP2_DAT1 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT1, 0x760, 0x358, 2, 0x970, 1), /* MX51_PAD_DISP2_DAT1__FEC_RX_ER */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT1, 0x760, 0x358, 4, 0x9cc, 1), /* MX51_PAD_DISP2_DAT1__KEY_COL7 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT1, 0x760, 0x358, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT1__UART3_TXD */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT1, 0x760, 0x358, 3, 0xa1c, 1), /* MX51_PAD_DISP2_DAT1__USBH3_DIR */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT2, 0x764, 0x35c, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT2__DISP2_DAT2 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT3, 0x768, 0x360, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT3__DISP2_DAT3 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT4, 0x76c, 0x364, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT4__DISP2_DAT4 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT5, 0x770, 0x368, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT5__DISP2_DAT5 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT6, 0x774, 0x36c, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT6__DISP2_DAT6 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT6, 0x774, 0x36c, 2, 0x000, 0), /* MX51_PAD_DISP2_DAT6__FEC_TDATA1 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT6, 0x774, 0x36c, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT6__GPIO1_19 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT6, 0x774, 0x36c, 4, 0x9d0, 1), /* MX51_PAD_DISP2_DAT6__KEY_ROW4 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT6, 0x774, 0x36c, 3, 0xa24, 1), /* MX51_PAD_DISP2_DAT6__USBH3_STP */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT7, 0x778, 0x370, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT7__DISP2_DAT7 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT7, 0x778, 0x370, 2, 0x000, 0), /* MX51_PAD_DISP2_DAT7__FEC_TDATA2 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT7, 0x778, 0x370, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT7__GPIO1_29 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT7, 0x778, 0x370, 4, 0x9d4, 1), /* MX51_PAD_DISP2_DAT7__KEY_ROW5 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT7, 0x778, 0x370, 3, 0xa20, 1), /* MX51_PAD_DISP2_DAT7__USBH3_NXT */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT8, 0x77c, 0x374, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT8__DISP2_DAT8 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT8, 0x77c, 0x374, 2, 0x000, 0), /* MX51_PAD_DISP2_DAT8__FEC_TDATA3 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT8, 0x77c, 0x374, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT8__GPIO1_30 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT8, 0x77c, 0x374, 4, 0x9d8, 1), /* MX51_PAD_DISP2_DAT8__KEY_ROW6 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT8, 0x77c, 0x374, 3, 0x9fc, 1), /* MX51_PAD_DISP2_DAT8__USBH3_DATA0 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT9, 0x780, 0x378, 4, 0x8f4, 1), /* MX51_PAD_DISP2_DAT9__AUD6_RXC */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT9, 0x780, 0x378, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT9__DISP2_DAT9 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT9, 0x780, 0x378, 2, 0x000, 0), /* MX51_PAD_DISP2_DAT9__FEC_TX_EN */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT9, 0x780, 0x378, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT9__GPIO1_31 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT9, 0x780, 0x378, 3, 0xa00, 1), /* MX51_PAD_DISP2_DAT9__USBH3_DATA1 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT10, 0x784, 0x37c, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT10__DISP2_DAT10 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT10, 0x784, 0x37c, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT10__DISP2_SER_CS */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT10, 0x784, 0x37c, 2, 0x94c, 1), /* MX51_PAD_DISP2_DAT10__FEC_COL */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT10, 0x784, 0x37c, 4, 0x9dc, 1), /* MX51_PAD_DISP2_DAT10__KEY_ROW7 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT10, 0x784, 0x37c, 3, 0xa04, 1), /* MX51_PAD_DISP2_DAT10__USBH3_DATA2 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT11, 0x788, 0x380, 4, 0x8f0, 1), /* MX51_PAD_DISP2_DAT11__AUD6_TXD */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT11, 0x788, 0x380, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT11__DISP2_DAT11 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT11, 0x788, 0x380, 2, 0x968, 1), /* MX51_PAD_DISP2_DAT11__FEC_RX_CLK */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT11, 0x788, 0x380, 7, 0x000, 0), /* MX51_PAD_DISP2_DAT11__GPIO1_10 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT11, 0x788, 0x380, 3, 0xa08, 1), /* MX51_PAD_DISP2_DAT11__USBH3_DATA3 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT12, 0x78c, 0x384, 4, 0x8ec, 1), /* MX51_PAD_DISP2_DAT12__AUD6_RXD */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT12, 0x78c, 0x384, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT12__DISP2_DAT12 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT12, 0x78c, 0x384, 2, 0x96c, 1), /* MX51_PAD_DISP2_DAT12__FEC_RX_DV */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT12, 0x78c, 0x384, 3, 0xa0c, 1), /* MX51_PAD_DISP2_DAT12__USBH3_DATA4 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT13, 0x790, 0x388, 4, 0x8fc, 1), /* MX51_PAD_DISP2_DAT13__AUD6_TXC */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT13, 0x790, 0x388, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT13__DISP2_DAT13 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT13, 0x790, 0x388, 2, 0x974, 1), /* MX51_PAD_DISP2_DAT13__FEC_TX_CLK */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT13, 0x790, 0x388, 3, 0xa10, 1), /* MX51_PAD_DISP2_DAT13__USBH3_DATA5 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT14, 0x794, 0x38c, 4, 0x900, 1), /* MX51_PAD_DISP2_DAT14__AUD6_TXFS */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT14, 0x794, 0x38c, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT14__DISP2_DAT14 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT14, 0x794, 0x38c, 2, 0x958, 1), /* MX51_PAD_DISP2_DAT14__FEC_RDATA0 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT14, 0x794, 0x38c, 3, 0xa14, 1), /* MX51_PAD_DISP2_DAT14__USBH3_DATA6 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT15, 0x798, 0x390, 4, 0x8f8, 1), /* MX51_PAD_DISP2_DAT15__AUD6_RXFS */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT15, 0x798, 0x390, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT15__DISP1_SER_CS */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT15, 0x798, 0x390, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT15__DISP2_DAT15 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT15, 0x798, 0x390, 2, 0x000, 0), /* MX51_PAD_DISP2_DAT15__FEC_TDATA0 */
+ IMX_PIN_REG(MX51_PAD_DISP2_DAT15, 0x798, 0x390, 3, 0xa18, 1), /* MX51_PAD_DISP2_DAT15__USBH3_DATA7 */
+ IMX_PIN_REG(MX51_PAD_SD1_CMD, 0x79c, 0x394, 1, 0x8e0, 1), /* MX51_PAD_SD1_CMD__AUD5_RXFS */
+ IMX_PIN_REG(MX51_PAD_SD1_CMD, 0x79c, 0x394, 2, 0x91c, 2), /* MX51_PAD_SD1_CMD__CSPI_MOSI */
+ IMX_PIN_REG(MX51_PAD_SD1_CMD, 0x79c, 0x394, 0, 0x000, 0), /* MX51_PAD_SD1_CMD__SD1_CMD */
+ IMX_PIN_REG(MX51_PAD_SD1_CLK, 0x7a0, 0x398, 1, 0x8dc, 1), /* MX51_PAD_SD1_CLK__AUD5_RXC */
+ IMX_PIN_REG(MX51_PAD_SD1_CLK, 0x7a0, 0x398, 2, 0x914, 2), /* MX51_PAD_SD1_CLK__CSPI_SCLK */
+ IMX_PIN_REG(MX51_PAD_SD1_CLK, 0x7a0, 0x398, 0, 0x000, 0), /* MX51_PAD_SD1_CLK__SD1_CLK */
+ IMX_PIN_REG(MX51_PAD_SD1_DATA0, 0x7a4, 0x39c, 1, 0x8d8, 2), /* MX51_PAD_SD1_DATA0__AUD5_TXD */
+ IMX_PIN_REG(MX51_PAD_SD1_DATA0, 0x7a4, 0x39c, 2, 0x918, 1), /* MX51_PAD_SD1_DATA0__CSPI_MISO */
+ IMX_PIN_REG(MX51_PAD_SD1_DATA0, 0x7a4, 0x39c, 0, 0x000, 0), /* MX51_PAD_SD1_DATA0__SD1_DATA0 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA0, NO_PAD, 0x01c, 0, 0x000, 0), /* MX51_PAD_EIM_DA0__EIM_DA0 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA1, NO_PAD, 0x020, 0, 0x000, 0), /* MX51_PAD_EIM_DA1__EIM_DA1 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA2, NO_PAD, 0x024, 0, 0x000, 0), /* MX51_PAD_EIM_DA2__EIM_DA2 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA3, NO_PAD, 0x028, 0, 0x000, 0), /* MX51_PAD_EIM_DA3__EIM_DA3 */
+ IMX_PIN_REG(MX51_PAD_SD1_DATA1, 0x7a8, 0x3a0, 1, 0x8d4, 2), /* MX51_PAD_SD1_DATA1__AUD5_RXD */
+ IMX_PIN_REG(MX51_PAD_SD1_DATA1, 0x7a8, 0x3a0, 0, 0x000, 0), /* MX51_PAD_SD1_DATA1__SD1_DATA1 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA4, NO_PAD, 0x02c, 0, 0x000, 0), /* MX51_PAD_EIM_DA4__EIM_DA4 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA5, NO_PAD, 0x030, 0, 0x000, 0), /* MX51_PAD_EIM_DA5__EIM_DA5 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA6, NO_PAD, 0x034, 0, 0x000, 0), /* MX51_PAD_EIM_DA6__EIM_DA6 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA7, NO_PAD, 0x038, 0, 0x000, 0), /* MX51_PAD_EIM_DA7__EIM_DA7 */
+ IMX_PIN_REG(MX51_PAD_SD1_DATA2, 0x7ac, 0x3a4, 1, 0x8e4, 2), /* MX51_PAD_SD1_DATA2__AUD5_TXC */
+ IMX_PIN_REG(MX51_PAD_SD1_DATA2, 0x7ac, 0x3a4, 0, 0x000, 0), /* MX51_PAD_SD1_DATA2__SD1_DATA2 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA10, NO_PAD, 0x044, 0, 0x000, 0), /* MX51_PAD_EIM_DA10__EIM_DA10 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA11, NO_PAD, 0x048, 0, 0x000, 0), /* MX51_PAD_EIM_DA11__EIM_DA11 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA8, NO_PAD, 0x03c, 0, 0x000, 0), /* MX51_PAD_EIM_DA8__EIM_DA8 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA9, NO_PAD, 0x040, 0, 0x000, 0), /* MX51_PAD_EIM_DA9__EIM_DA9 */
+ IMX_PIN_REG(MX51_PAD_SD1_DATA3, 0x7b0, 0x3a8, 1, 0x8e8, 2), /* MX51_PAD_SD1_DATA3__AUD5_TXFS */
+ IMX_PIN_REG(MX51_PAD_SD1_DATA3, 0x7b0, 0x3a8, 2, 0x920, 1), /* MX51_PAD_SD1_DATA3__CSPI_SS1 */
+ IMX_PIN_REG(MX51_PAD_SD1_DATA3, 0x7b0, 0x3a8, 0, 0x000, 0), /* MX51_PAD_SD1_DATA3__SD1_DATA3 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_0, 0x7b4, 0x3ac, 2, 0x924, 0), /* MX51_PAD_GPIO1_0__CSPI_SS2 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_0, 0x7b4, 0x3ac, 1, 0x000, 0), /* MX51_PAD_GPIO1_0__GPIO1_0 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_0, 0x7b4, 0x3ac, 0, 0x000, 0), /* MX51_PAD_GPIO1_0__SD1_CD */
+ IMX_PIN_REG(MX51_PAD_GPIO1_1, 0x7b8, 0x3b0, 2, 0x918, 2), /* MX51_PAD_GPIO1_1__CSPI_MISO */
+ IMX_PIN_REG(MX51_PAD_GPIO1_1, 0x7b8, 0x3b0, 1, 0x000, 0), /* MX51_PAD_GPIO1_1__GPIO1_1 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_1, 0x7b8, 0x3b0, 0, 0x000, 0), /* MX51_PAD_GPIO1_1__SD1_WP */
+ IMX_PIN_REG(MX51_PAD_EIM_DA12, NO_PAD, 0x04c, 0, 0x000, 0), /* MX51_PAD_EIM_DA12__EIM_DA12 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA13, NO_PAD, 0x050, 0, 0x000, 0), /* MX51_PAD_EIM_DA13__EIM_DA13 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA14, NO_PAD, 0x054, 0, 0x000, 0), /* MX51_PAD_EIM_DA14__EIM_DA14 */
+ IMX_PIN_REG(MX51_PAD_EIM_DA15, NO_PAD, 0x058, 0, 0x000, 0), /* MX51_PAD_EIM_DA15__EIM_DA15 */
+ IMX_PIN_REG(MX51_PAD_SD2_CMD, NO_PAD, 0x3b4, 2, 0x91c, 3), /* MX51_PAD_SD2_CMD__CSPI_MOSI */
+ IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 1, 0x9b0, 2), /* MX51_PAD_SD2_CMD__I2C1_SCL */
+ IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 0, 0x000, 0), /* MX51_PAD_SD2_CMD__SD2_CMD */
+ IMX_PIN_REG(MX51_PAD_SD2_CLK, 0x7c0, 0x3b8, 2, 0x914, 3), /* MX51_PAD_SD2_CLK__CSPI_SCLK */
+ IMX_PIN_REG(MX51_PAD_SD2_CLK, 0x7c0, 0x3b8, 1, 0x9b4, 2), /* MX51_PAD_SD2_CLK__I2C1_SDA */
+ IMX_PIN_REG(MX51_PAD_SD2_CLK, 0x7c0, 0x3b8, 0, 0x000, 0), /* MX51_PAD_SD2_CLK__SD2_CLK */
+ IMX_PIN_REG(MX51_PAD_SD2_DATA0, 0x7c4, 0x3bc, 2, 0x918, 3), /* MX51_PAD_SD2_DATA0__CSPI_MISO */
+ IMX_PIN_REG(MX51_PAD_SD2_DATA0, 0x7c4, 0x3bc, 1, 0x000, 0), /* MX51_PAD_SD2_DATA0__SD1_DAT4 */
+ IMX_PIN_REG(MX51_PAD_SD2_DATA0, 0x7c4, 0x3bc, 0, 0x000, 0), /* MX51_PAD_SD2_DATA0__SD2_DATA0 */
+ IMX_PIN_REG(MX51_PAD_SD2_DATA1, 0x7c8, 0x3c0, 1, 0x000, 0), /* MX51_PAD_SD2_DATA1__SD1_DAT5 */
+ IMX_PIN_REG(MX51_PAD_SD2_DATA1, 0x7c8, 0x3c0, 0, 0x000, 0), /* MX51_PAD_SD2_DATA1__SD2_DATA1 */
+ IMX_PIN_REG(MX51_PAD_SD2_DATA1, 0x7c8, 0x3c0, 2, 0x000, 0), /* MX51_PAD_SD2_DATA1__USBH3_H2_DP */
+ IMX_PIN_REG(MX51_PAD_SD2_DATA2, 0x7cc, 0x3c4, 1, 0x000, 0), /* MX51_PAD_SD2_DATA2__SD1_DAT6 */
+ IMX_PIN_REG(MX51_PAD_SD2_DATA2, 0x7cc, 0x3c4, 0, 0x000, 0), /* MX51_PAD_SD2_DATA2__SD2_DATA2 */
+ IMX_PIN_REG(MX51_PAD_SD2_DATA2, 0x7cc, 0x3c4, 2, 0x000, 0), /* MX51_PAD_SD2_DATA2__USBH3_H2_DM */
+ IMX_PIN_REG(MX51_PAD_SD2_DATA3, 0x7d0, 0x3c8, 2, 0x924, 1), /* MX51_PAD_SD2_DATA3__CSPI_SS2 */
+ IMX_PIN_REG(MX51_PAD_SD2_DATA3, 0x7d0, 0x3c8, 1, 0x000, 0), /* MX51_PAD_SD2_DATA3__SD1_DAT7 */
+ IMX_PIN_REG(MX51_PAD_SD2_DATA3, 0x7d0, 0x3c8, 0, 0x000, 0), /* MX51_PAD_SD2_DATA3__SD2_DATA3 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_2, 0x7d4, 0x3cc, 5, 0x000, 0), /* MX51_PAD_GPIO1_2__CCM_OUT_2 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_2, 0x7d4, 0x3cc, 0, 0x000, 0), /* MX51_PAD_GPIO1_2__GPIO1_2 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_2, 0x7d4, 0x3cc, 2, 0x9b8, 3), /* MX51_PAD_GPIO1_2__I2C2_SCL */
+ IMX_PIN_REG(MX51_PAD_GPIO1_2, 0x7d4, 0x3cc, 7, 0x90c, 1), /* MX51_PAD_GPIO1_2__PLL1_BYP */
+ IMX_PIN_REG(MX51_PAD_GPIO1_2, 0x7d4, 0x3cc, 1, 0x000, 0), /* MX51_PAD_GPIO1_2__PWM1_PWMO */
+ IMX_PIN_REG(MX51_PAD_GPIO1_3, 0x7d8, 0x3d0, 0, 0x000, 0), /* MX51_PAD_GPIO1_3__GPIO1_3 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_3, 0x7d8, 0x3d0, 2, 0x9bc, 3), /* MX51_PAD_GPIO1_3__I2C2_SDA */
+ IMX_PIN_REG(MX51_PAD_GPIO1_3, 0x7d8, 0x3d0, 7, 0x910, 1), /* MX51_PAD_GPIO1_3__PLL2_BYP */
+ IMX_PIN_REG(MX51_PAD_GPIO1_3, 0x7d8, 0x3d0, 1, 0x000, 0), /* MX51_PAD_GPIO1_3__PWM2_PWMO */
+ IMX_PIN_REG(MX51_PAD_PMIC_INT_REQ, 0x7fc, 0x3d4, 0, 0x000, 0), /* MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ */
+ IMX_PIN_REG(MX51_PAD_PMIC_INT_REQ, 0x7fc, 0x3d4, 1, 0x000, 0), /* MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B */
+ IMX_PIN_REG(MX51_PAD_GPIO1_4, 0x804, 0x3d8, 4, 0x908, 1), /* MX51_PAD_GPIO1_4__DISP2_EXT_CLK */
+ IMX_PIN_REG(MX51_PAD_GPIO1_4, 0x804, 0x3d8, 3, 0x938, 1), /* MX51_PAD_GPIO1_4__EIM_RDY */
+ IMX_PIN_REG(MX51_PAD_GPIO1_4, 0x804, 0x3d8, 0, 0x000, 0), /* MX51_PAD_GPIO1_4__GPIO1_4 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_4, 0x804, 0x3d8, 2, 0x000, 0), /* MX51_PAD_GPIO1_4__WDOG1_WDOG_B */
+ IMX_PIN_REG(MX51_PAD_GPIO1_5, 0x808, 0x3dc, 6, 0x000, 0), /* MX51_PAD_GPIO1_5__CSI2_MCLK */
+ IMX_PIN_REG(MX51_PAD_GPIO1_5, 0x808, 0x3dc, 3, 0x000, 0), /* MX51_PAD_GPIO1_5__DISP2_PIN16 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_5, 0x808, 0x3dc, 0, 0x000, 0), /* MX51_PAD_GPIO1_5__GPIO1_5 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_5, 0x808, 0x3dc, 2, 0x000, 0), /* MX51_PAD_GPIO1_5__WDOG2_WDOG_B */
+ IMX_PIN_REG(MX51_PAD_GPIO1_6, 0x80c, 0x3e0, 4, 0x000, 0), /* MX51_PAD_GPIO1_6__DISP2_PIN17 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_6, 0x80c, 0x3e0, 0, 0x000, 0), /* MX51_PAD_GPIO1_6__GPIO1_6 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_6, 0x80c, 0x3e0, 3, 0x000, 0), /* MX51_PAD_GPIO1_6__REF_EN_B */
+ IMX_PIN_REG(MX51_PAD_GPIO1_7, 0x810, 0x3e4, 3, 0x000, 0), /* MX51_PAD_GPIO1_7__CCM_OUT_0 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_7, 0x810, 0x3e4, 0, 0x000, 0), /* MX51_PAD_GPIO1_7__GPIO1_7 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_7, 0x810, 0x3e4, 6, 0x000, 0), /* MX51_PAD_GPIO1_7__SD2_WP */
+ IMX_PIN_REG(MX51_PAD_GPIO1_7, 0x810, 0x3e4, 2, 0x000, 0), /* MX51_PAD_GPIO1_7__SPDIF_OUT1 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_8, 0x814, 0x3e8, 2, 0x99c, 2), /* MX51_PAD_GPIO1_8__CSI2_DATA_EN */
+ IMX_PIN_REG(MX51_PAD_GPIO1_8, 0x814, 0x3e8, 0, 0x000, 0), /* MX51_PAD_GPIO1_8__GPIO1_8 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_8, 0x814, 0x3e8, 6, 0x000, 0), /* MX51_PAD_GPIO1_8__SD2_CD */
+ IMX_PIN_REG(MX51_PAD_GPIO1_8, 0x814, 0x3e8, 1, 0x000, 0), /* MX51_PAD_GPIO1_8__USBH3_PWR */
+ IMX_PIN_REG(MX51_PAD_GPIO1_9, 0x818, 0x3ec, 3, 0x000, 0), /* MX51_PAD_GPIO1_9__CCM_OUT_1 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_9, 0x818, 0x3ec, 2, 0x000, 0), /* MX51_PAD_GPIO1_9__DISP2_D1_CS */
+ IMX_PIN_REG(MX51_PAD_GPIO1_9, 0x818, 0x3ec, 7, 0x000, 0), /* MX51_PAD_GPIO1_9__DISP2_SER_CS */
+ IMX_PIN_REG(MX51_PAD_GPIO1_9, 0x818, 0x3ec, 0, 0x000, 0), /* MX51_PAD_GPIO1_9__GPIO1_9 */
+ IMX_PIN_REG(MX51_PAD_GPIO1_9, 0x818, 0x3ec, 6, 0x000, 0), /* MX51_PAD_GPIO1_9__SD2_LCTL */
+ IMX_PIN_REG(MX51_PAD_GPIO1_9, 0x818, 0x3ec, 1, 0x000, 0), /* MX51_PAD_GPIO1_9__USBH3_OC */
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx51_pinctrl_pads[] = {
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D16),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D17),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D18),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D19),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D20),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D21),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D22),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D23),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D24),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D25),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D26),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D27),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D28),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D29),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D30),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_D31),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_A16),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_A17),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_A18),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_A19),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_A20),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_A21),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_A22),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_A23),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_A24),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_A25),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_A26),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_A27),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_EB0),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_EB1),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_EB2),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_EB3),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_OE),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_CS0),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_CS1),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_CS2),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_CS3),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_CS4),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_CS5),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DTACK),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_LBA),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_CRE),
+ IMX_PINCTRL_PIN(MX51_PAD_DRAM_CS1),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_WE_B),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_RE_B),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_ALE),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_CLE),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_WP_B),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_RB0),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_RB1),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_RB2),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_RB3),
+ IMX_PINCTRL_PIN(MX51_PAD_GPIO_NAND),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_CS0),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_CS1),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_CS2),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_CS3),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_CS4),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_CS5),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_CS6),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_CS7),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_RDY_INT),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D15),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D14),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D13),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D12),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D11),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D10),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D9),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D8),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D7),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D6),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D5),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D4),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D3),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D2),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D1),
+ IMX_PINCTRL_PIN(MX51_PAD_NANDF_D0),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_D8),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_D9),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_D10),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_D11),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_D12),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_D13),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_D14),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_D15),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_D16),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_D17),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_D18),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_D19),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_VSYNC),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_HSYNC),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_PIXCLK),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI1_MCLK),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI2_D12),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI2_D13),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI2_D14),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI2_D15),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI2_D16),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI2_D17),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI2_D18),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI2_D19),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI2_VSYNC),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI2_HSYNC),
+ IMX_PINCTRL_PIN(MX51_PAD_CSI2_PIXCLK),
+ IMX_PINCTRL_PIN(MX51_PAD_I2C1_CLK),
+ IMX_PINCTRL_PIN(MX51_PAD_I2C1_DAT),
+ IMX_PINCTRL_PIN(MX51_PAD_AUD3_BB_TXD),
+ IMX_PINCTRL_PIN(MX51_PAD_AUD3_BB_RXD),
+ IMX_PINCTRL_PIN(MX51_PAD_AUD3_BB_CK),
+ IMX_PINCTRL_PIN(MX51_PAD_AUD3_BB_FS),
+ IMX_PINCTRL_PIN(MX51_PAD_CSPI1_MOSI),
+ IMX_PINCTRL_PIN(MX51_PAD_CSPI1_MISO),
+ IMX_PINCTRL_PIN(MX51_PAD_CSPI1_SS0),
+ IMX_PINCTRL_PIN(MX51_PAD_CSPI1_SS1),
+ IMX_PINCTRL_PIN(MX51_PAD_CSPI1_RDY),
+ IMX_PINCTRL_PIN(MX51_PAD_CSPI1_SCLK),
+ IMX_PINCTRL_PIN(MX51_PAD_UART1_RXD),
+ IMX_PINCTRL_PIN(MX51_PAD_UART1_TXD),
+ IMX_PINCTRL_PIN(MX51_PAD_UART1_RTS),
+ IMX_PINCTRL_PIN(MX51_PAD_UART1_CTS),
+ IMX_PINCTRL_PIN(MX51_PAD_UART2_RXD),
+ IMX_PINCTRL_PIN(MX51_PAD_UART2_TXD),
+ IMX_PINCTRL_PIN(MX51_PAD_UART3_RXD),
+ IMX_PINCTRL_PIN(MX51_PAD_UART3_TXD),
+ IMX_PINCTRL_PIN(MX51_PAD_OWIRE_LINE),
+ IMX_PINCTRL_PIN(MX51_PAD_KEY_ROW0),
+ IMX_PINCTRL_PIN(MX51_PAD_KEY_ROW1),
+ IMX_PINCTRL_PIN(MX51_PAD_KEY_ROW2),
+ IMX_PINCTRL_PIN(MX51_PAD_KEY_ROW3),
+ IMX_PINCTRL_PIN(MX51_PAD_KEY_COL0),
+ IMX_PINCTRL_PIN(MX51_PAD_KEY_COL1),
+ IMX_PINCTRL_PIN(MX51_PAD_KEY_COL2),
+ IMX_PINCTRL_PIN(MX51_PAD_KEY_COL3),
+ IMX_PINCTRL_PIN(MX51_PAD_KEY_COL4),
+ IMX_PINCTRL_PIN(MX51_PAD_KEY_COL5),
+ IMX_PINCTRL_PIN(MX51_PAD_USBH1_CLK),
+ IMX_PINCTRL_PIN(MX51_PAD_USBH1_DIR),
+ IMX_PINCTRL_PIN(MX51_PAD_USBH1_STP),
+ IMX_PINCTRL_PIN(MX51_PAD_USBH1_NXT),
+ IMX_PINCTRL_PIN(MX51_PAD_USBH1_DATA0),
+ IMX_PINCTRL_PIN(MX51_PAD_USBH1_DATA1),
+ IMX_PINCTRL_PIN(MX51_PAD_USBH1_DATA2),
+ IMX_PINCTRL_PIN(MX51_PAD_USBH1_DATA3),
+ IMX_PINCTRL_PIN(MX51_PAD_USBH1_DATA4),
+ IMX_PINCTRL_PIN(MX51_PAD_USBH1_DATA5),
+ IMX_PINCTRL_PIN(MX51_PAD_USBH1_DATA6),
+ IMX_PINCTRL_PIN(MX51_PAD_USBH1_DATA7),
+ IMX_PINCTRL_PIN(MX51_PAD_DI1_PIN11),
+ IMX_PINCTRL_PIN(MX51_PAD_DI1_PIN12),
+ IMX_PINCTRL_PIN(MX51_PAD_DI1_PIN13),
+ IMX_PINCTRL_PIN(MX51_PAD_DI1_D0_CS),
+ IMX_PINCTRL_PIN(MX51_PAD_DI1_D1_CS),
+ IMX_PINCTRL_PIN(MX51_PAD_DISPB2_SER_DIN),
+ IMX_PINCTRL_PIN(MX51_PAD_DISPB2_SER_DIO),
+ IMX_PINCTRL_PIN(MX51_PAD_DISPB2_SER_CLK),
+ IMX_PINCTRL_PIN(MX51_PAD_DISPB2_SER_RS),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT0),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT1),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT2),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT3),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT4),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT5),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT6),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT7),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT8),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT9),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT10),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT11),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT12),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT13),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT14),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT15),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT16),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT17),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT18),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT19),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT20),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT21),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT22),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP1_DAT23),
+ IMX_PINCTRL_PIN(MX51_PAD_DI1_PIN3),
+ IMX_PINCTRL_PIN(MX51_PAD_DI1_PIN2),
+ IMX_PINCTRL_PIN(MX51_PAD_DI_GP2),
+ IMX_PINCTRL_PIN(MX51_PAD_DI_GP3),
+ IMX_PINCTRL_PIN(MX51_PAD_DI2_PIN4),
+ IMX_PINCTRL_PIN(MX51_PAD_DI2_PIN2),
+ IMX_PINCTRL_PIN(MX51_PAD_DI2_PIN3),
+ IMX_PINCTRL_PIN(MX51_PAD_DI2_DISP_CLK),
+ IMX_PINCTRL_PIN(MX51_PAD_DI_GP4),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT0),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT1),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT2),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT3),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT4),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT5),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT6),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT7),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT8),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT9),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT10),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT11),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT12),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT13),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT14),
+ IMX_PINCTRL_PIN(MX51_PAD_DISP2_DAT15),
+ IMX_PINCTRL_PIN(MX51_PAD_SD1_CMD),
+ IMX_PINCTRL_PIN(MX51_PAD_SD1_CLK),
+ IMX_PINCTRL_PIN(MX51_PAD_SD1_DATA0),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA0),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA1),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA2),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA3),
+ IMX_PINCTRL_PIN(MX51_PAD_SD1_DATA1),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA4),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA5),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA6),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA7),
+ IMX_PINCTRL_PIN(MX51_PAD_SD1_DATA2),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA10),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA11),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA8),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA9),
+ IMX_PINCTRL_PIN(MX51_PAD_SD1_DATA3),
+ IMX_PINCTRL_PIN(MX51_PAD_GPIO1_0),
+ IMX_PINCTRL_PIN(MX51_PAD_GPIO1_1),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA12),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA13),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA14),
+ IMX_PINCTRL_PIN(MX51_PAD_EIM_DA15),
+ IMX_PINCTRL_PIN(MX51_PAD_SD2_CMD),
+ IMX_PINCTRL_PIN(MX51_PAD_SD2_CLK),
+ IMX_PINCTRL_PIN(MX51_PAD_SD2_DATA0),
+ IMX_PINCTRL_PIN(MX51_PAD_SD2_DATA1),
+ IMX_PINCTRL_PIN(MX51_PAD_SD2_DATA2),
+ IMX_PINCTRL_PIN(MX51_PAD_SD2_DATA3),
+ IMX_PINCTRL_PIN(MX51_PAD_GPIO1_2),
+ IMX_PINCTRL_PIN(MX51_PAD_GPIO1_3),
+ IMX_PINCTRL_PIN(MX51_PAD_PMIC_INT_REQ),
+ IMX_PINCTRL_PIN(MX51_PAD_GPIO1_4),
+ IMX_PINCTRL_PIN(MX51_PAD_GPIO1_5),
+ IMX_PINCTRL_PIN(MX51_PAD_GPIO1_6),
+ IMX_PINCTRL_PIN(MX51_PAD_GPIO1_7),
+ IMX_PINCTRL_PIN(MX51_PAD_GPIO1_8),
+ IMX_PINCTRL_PIN(MX51_PAD_GPIO1_9),
+};
+
+static struct imx_pinctrl_soc_info imx51_pinctrl_info = {
+ .pins = imx51_pinctrl_pads,
+ .npins = ARRAY_SIZE(imx51_pinctrl_pads),
+ .pin_regs = imx51_pin_regs,
+ .npin_regs = ARRAY_SIZE(imx51_pin_regs),
+};
+
+static struct of_device_id imx51_pinctrl_of_match[] __devinitdata = {
+ { .compatible = "fsl,imx51-iomuxc", },
+ { /* sentinel */ }
+};
+
+static int __devinit imx51_pinctrl_probe(struct platform_device *pdev)
+{
+ return imx_pinctrl_probe(pdev, &imx51_pinctrl_info);
+}
+
+static struct platform_driver imx51_pinctrl_driver = {
+ .driver = {
+ .name = "imx51-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(imx51_pinctrl_of_match),
+ },
+ .probe = imx51_pinctrl_probe,
+ .remove = __devexit_p(imx_pinctrl_remove),
+};
+
+static int __init imx51_pinctrl_init(void)
+{
+ return platform_driver_register(&imx51_pinctrl_driver);
+}
+arch_initcall(imx51_pinctrl_init);
+
+static void __exit imx51_pinctrl_exit(void)
+{
+ platform_driver_unregister(&imx51_pinctrl_driver);
+}
+module_exit(imx51_pinctrl_exit);
+MODULE_AUTHOR("Dong Aisheng <dong.aisheng@linaro.org>");
+MODULE_DESCRIPTION("Freescale IMX51 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-imx53.c b/drivers/pinctrl/pinctrl-imx53.c
new file mode 100644
index 000000000000..1f49e16a9bcd
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx53.c
@@ -0,0 +1,1649 @@
+/*
+ * imx53 pinctrl driver based on imx pinmux core
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro, Inc.
+ *
+ * Author: Dong Aisheng <dong.aisheng@linaro.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.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-imx.h"
+
+enum imx53_pads {
+ MX53_PAD_GPIO_19 = 1,
+ MX53_PAD_KEY_COL0 = 2,
+ MX53_PAD_KEY_ROW0 = 3,
+ MX53_PAD_KEY_COL1 = 4,
+ MX53_PAD_KEY_ROW1 = 5,
+ MX53_PAD_KEY_COL2 = 6,
+ MX53_PAD_KEY_ROW2 = 7,
+ MX53_PAD_KEY_COL3 = 8,
+ MX53_PAD_KEY_ROW3 = 9,
+ MX53_PAD_KEY_COL4 = 10,
+ MX53_PAD_KEY_ROW4 = 11,
+ MX53_PAD_DI0_DISP_CLK = 12,
+ MX53_PAD_DI0_PIN15 = 13,
+ MX53_PAD_DI0_PIN2 = 14,
+ MX53_PAD_DI0_PIN3 = 15,
+ MX53_PAD_DI0_PIN4 = 16,
+ MX53_PAD_DISP0_DAT0 = 17,
+ MX53_PAD_DISP0_DAT1 = 18,
+ MX53_PAD_DISP0_DAT2 = 19,
+ MX53_PAD_DISP0_DAT3 = 20,
+ MX53_PAD_DISP0_DAT4 = 21,
+ MX53_PAD_DISP0_DAT5 = 22,
+ MX53_PAD_DISP0_DAT6 = 23,
+ MX53_PAD_DISP0_DAT7 = 24,
+ MX53_PAD_DISP0_DAT8 = 25,
+ MX53_PAD_DISP0_DAT9 = 26,
+ MX53_PAD_DISP0_DAT10 = 27,
+ MX53_PAD_DISP0_DAT11 = 28,
+ MX53_PAD_DISP0_DAT12 = 29,
+ MX53_PAD_DISP0_DAT13 = 30,
+ MX53_PAD_DISP0_DAT14 = 31,
+ MX53_PAD_DISP0_DAT15 = 32,
+ MX53_PAD_DISP0_DAT16 = 33,
+ MX53_PAD_DISP0_DAT17 = 34,
+ MX53_PAD_DISP0_DAT18 = 35,
+ MX53_PAD_DISP0_DAT19 = 36,
+ MX53_PAD_DISP0_DAT20 = 37,
+ MX53_PAD_DISP0_DAT21 = 38,
+ MX53_PAD_DISP0_DAT22 = 39,
+ MX53_PAD_DISP0_DAT23 = 40,
+ MX53_PAD_CSI0_PIXCLK = 41,
+ MX53_PAD_CSI0_MCLK = 42,
+ MX53_PAD_CSI0_DATA_EN = 43,
+ MX53_PAD_CSI0_VSYNC = 44,
+ MX53_PAD_CSI0_DAT4 = 45,
+ MX53_PAD_CSI0_DAT5 = 46,
+ MX53_PAD_CSI0_DAT6 = 47,
+ MX53_PAD_CSI0_DAT7 = 48,
+ MX53_PAD_CSI0_DAT8 = 49,
+ MX53_PAD_CSI0_DAT9 = 50,
+ MX53_PAD_CSI0_DAT10 = 51,
+ MX53_PAD_CSI0_DAT11 = 52,
+ MX53_PAD_CSI0_DAT12 = 53,
+ MX53_PAD_CSI0_DAT13 = 54,
+ MX53_PAD_CSI0_DAT14 = 55,
+ MX53_PAD_CSI0_DAT15 = 56,
+ MX53_PAD_CSI0_DAT16 = 57,
+ MX53_PAD_CSI0_DAT17 = 58,
+ MX53_PAD_CSI0_DAT18 = 59,
+ MX53_PAD_CSI0_DAT19 = 60,
+ MX53_PAD_EIM_A25 = 61,
+ MX53_PAD_EIM_EB2 = 62,
+ MX53_PAD_EIM_D16 = 63,
+ MX53_PAD_EIM_D17 = 64,
+ MX53_PAD_EIM_D18 = 65,
+ MX53_PAD_EIM_D19 = 66,
+ MX53_PAD_EIM_D20 = 67,
+ MX53_PAD_EIM_D21 = 68,
+ MX53_PAD_EIM_D22 = 69,
+ MX53_PAD_EIM_D23 = 70,
+ MX53_PAD_EIM_EB3 = 71,
+ MX53_PAD_EIM_D24 = 72,
+ MX53_PAD_EIM_D25 = 73,
+ MX53_PAD_EIM_D26 = 74,
+ MX53_PAD_EIM_D27 = 75,
+ MX53_PAD_EIM_D28 = 76,
+ MX53_PAD_EIM_D29 = 77,
+ MX53_PAD_EIM_D30 = 78,
+ MX53_PAD_EIM_D31 = 79,
+ MX53_PAD_EIM_A24 = 80,
+ MX53_PAD_EIM_A23 = 81,
+ MX53_PAD_EIM_A22 = 82,
+ MX53_PAD_EIM_A21 = 83,
+ MX53_PAD_EIM_A20 = 84,
+ MX53_PAD_EIM_A19 = 85,
+ MX53_PAD_EIM_A18 = 86,
+ MX53_PAD_EIM_A17 = 87,
+ MX53_PAD_EIM_A16 = 88,
+ MX53_PAD_EIM_CS0 = 89,
+ MX53_PAD_EIM_CS1 = 90,
+ MX53_PAD_EIM_OE = 91,
+ MX53_PAD_EIM_RW = 92,
+ MX53_PAD_EIM_LBA = 93,
+ MX53_PAD_EIM_EB0 = 94,
+ MX53_PAD_EIM_EB1 = 95,
+ MX53_PAD_EIM_DA0 = 96,
+ MX53_PAD_EIM_DA1 = 97,
+ MX53_PAD_EIM_DA2 = 98,
+ MX53_PAD_EIM_DA3 = 99,
+ MX53_PAD_EIM_DA4 = 100,
+ MX53_PAD_EIM_DA5 = 101,
+ MX53_PAD_EIM_DA6 = 102,
+ MX53_PAD_EIM_DA7 = 103,
+ MX53_PAD_EIM_DA8 = 104,
+ MX53_PAD_EIM_DA9 = 105,
+ MX53_PAD_EIM_DA10 = 106,
+ MX53_PAD_EIM_DA11 = 107,
+ MX53_PAD_EIM_DA12 = 108,
+ MX53_PAD_EIM_DA13 = 109,
+ MX53_PAD_EIM_DA14 = 110,
+ MX53_PAD_EIM_DA15 = 111,
+ MX53_PAD_NANDF_WE_B = 112,
+ MX53_PAD_NANDF_RE_B = 113,
+ MX53_PAD_EIM_WAIT = 114,
+ MX53_PAD_LVDS1_TX3_P = 115,
+ MX53_PAD_LVDS1_TX2_P = 116,
+ MX53_PAD_LVDS1_CLK_P = 117,
+ MX53_PAD_LVDS1_TX1_P = 118,
+ MX53_PAD_LVDS1_TX0_P = 119,
+ MX53_PAD_LVDS0_TX3_P = 120,
+ MX53_PAD_LVDS0_CLK_P = 121,
+ MX53_PAD_LVDS0_TX2_P = 122,
+ MX53_PAD_LVDS0_TX1_P = 123,
+ MX53_PAD_LVDS0_TX0_P = 124,
+ MX53_PAD_GPIO_10 = 125,
+ MX53_PAD_GPIO_11 = 126,
+ MX53_PAD_GPIO_12 = 127,
+ MX53_PAD_GPIO_13 = 128,
+ MX53_PAD_GPIO_14 = 129,
+ MX53_PAD_NANDF_CLE = 130,
+ MX53_PAD_NANDF_ALE = 131,
+ MX53_PAD_NANDF_WP_B = 132,
+ MX53_PAD_NANDF_RB0 = 133,
+ MX53_PAD_NANDF_CS0 = 134,
+ MX53_PAD_NANDF_CS1 = 135,
+ MX53_PAD_NANDF_CS2 = 136,
+ MX53_PAD_NANDF_CS3 = 137,
+ MX53_PAD_FEC_MDIO = 138,
+ MX53_PAD_FEC_REF_CLK = 139,
+ MX53_PAD_FEC_RX_ER = 140,
+ MX53_PAD_FEC_CRS_DV = 141,
+ MX53_PAD_FEC_RXD1 = 142,
+ MX53_PAD_FEC_RXD0 = 143,
+ MX53_PAD_FEC_TX_EN = 144,
+ MX53_PAD_FEC_TXD1 = 145,
+ MX53_PAD_FEC_TXD0 = 146,
+ MX53_PAD_FEC_MDC = 147,
+ MX53_PAD_PATA_DIOW = 148,
+ MX53_PAD_PATA_DMACK = 149,
+ MX53_PAD_PATA_DMARQ = 150,
+ MX53_PAD_PATA_BUFFER_EN = 151,
+ MX53_PAD_PATA_INTRQ = 152,
+ MX53_PAD_PATA_DIOR = 153,
+ MX53_PAD_PATA_RESET_B = 154,
+ MX53_PAD_PATA_IORDY = 155,
+ MX53_PAD_PATA_DA_0 = 156,
+ MX53_PAD_PATA_DA_1 = 157,
+ MX53_PAD_PATA_DA_2 = 158,
+ MX53_PAD_PATA_CS_0 = 159,
+ MX53_PAD_PATA_CS_1 = 160,
+ MX53_PAD_PATA_DATA0 = 161,
+ MX53_PAD_PATA_DATA1 = 162,
+ MX53_PAD_PATA_DATA2 = 163,
+ MX53_PAD_PATA_DATA3 = 164,
+ MX53_PAD_PATA_DATA4 = 165,
+ MX53_PAD_PATA_DATA5 = 166,
+ MX53_PAD_PATA_DATA6 = 167,
+ MX53_PAD_PATA_DATA7 = 168,
+ MX53_PAD_PATA_DATA8 = 169,
+ MX53_PAD_PATA_DATA9 = 170,
+ MX53_PAD_PATA_DATA10 = 171,
+ MX53_PAD_PATA_DATA11 = 172,
+ MX53_PAD_PATA_DATA12 = 173,
+ MX53_PAD_PATA_DATA13 = 174,
+ MX53_PAD_PATA_DATA14 = 175,
+ MX53_PAD_PATA_DATA15 = 176,
+ MX53_PAD_SD1_DATA0 = 177,
+ MX53_PAD_SD1_DATA1 = 178,
+ MX53_PAD_SD1_CMD = 179,
+ MX53_PAD_SD1_DATA2 = 180,
+ MX53_PAD_SD1_CLK = 181,
+ MX53_PAD_SD1_DATA3 = 182,
+ MX53_PAD_SD2_CLK = 183,
+ MX53_PAD_SD2_CMD = 184,
+ MX53_PAD_SD2_DATA3 = 185,
+ MX53_PAD_SD2_DATA2 = 186,
+ MX53_PAD_SD2_DATA1 = 187,
+ MX53_PAD_SD2_DATA0 = 188,
+ MX53_PAD_GPIO_0 = 189,
+ MX53_PAD_GPIO_1 = 190,
+ MX53_PAD_GPIO_9 = 191,
+ MX53_PAD_GPIO_3 = 192,
+ MX53_PAD_GPIO_6 = 193,
+ MX53_PAD_GPIO_2 = 194,
+ MX53_PAD_GPIO_4 = 195,
+ MX53_PAD_GPIO_5 = 196,
+ MX53_PAD_GPIO_7 = 197,
+ MX53_PAD_GPIO_8 = 198,
+ MX53_PAD_GPIO_16 = 199,
+ MX53_PAD_GPIO_17 = 200,
+ MX53_PAD_GPIO_18 = 201,
+};
+
+/* imx53 register maps */
+static struct imx_pin_reg imx53_pin_regs[] = {
+ IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 0, 0x840, 0), /* MX53_PAD_GPIO_19__KPP_COL_5 */
+ IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 1, 0x000, 0), /* MX53_PAD_GPIO_19__GPIO4_5 */
+ IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 2, 0x000, 0), /* MX53_PAD_GPIO_19__CCM_CLKO */
+ IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 3, 0x000, 0), /* MX53_PAD_GPIO_19__SPDIF_OUT1 */
+ IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 4, 0x000, 0), /* MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2 */
+ IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 5, 0x000, 0), /* MX53_PAD_GPIO_19__ECSPI1_RDY */
+ IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 6, 0x000, 0), /* MX53_PAD_GPIO_19__FEC_TDATA_3 */
+ IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 7, 0x000, 0), /* MX53_PAD_GPIO_19__SRC_INT_BOOT */
+ IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 0, 0x000, 0), /* MX53_PAD_KEY_COL0__KPP_COL_0 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 1, 0x000, 0), /* MX53_PAD_KEY_COL0__GPIO4_6 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 2, 0x758, 0), /* MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC */
+ IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 4, 0x000, 0), /* MX53_PAD_KEY_COL0__UART4_TXD_MUX */
+ IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 5, 0x79C, 0), /* MX53_PAD_KEY_COL0__ECSPI1_SCLK */
+ IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 6, 0x000, 0), /* MX53_PAD_KEY_COL0__FEC_RDATA_3 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 7, 0x000, 0), /* MX53_PAD_KEY_COL0__SRC_ANY_PU_RST */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW0, 0x350, 0x028, 0, 0x000, 0), /* MX53_PAD_KEY_ROW0__KPP_ROW_0 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW0, 0x350, 0x028, 1, 0x000, 0), /* MX53_PAD_KEY_ROW0__GPIO4_7 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW0, 0x350, 0x028, 2, 0x74C, 0), /* MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW0, 0x350, 0x028, 4, 0x890, 1), /* MX53_PAD_KEY_ROW0__UART4_RXD_MUX */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW0, 0x350, 0x028, 5, 0x7A4, 0), /* MX53_PAD_KEY_ROW0__ECSPI1_MOSI */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW0, 0x350, 0x028, 6, 0x000, 0), /* MX53_PAD_KEY_ROW0__FEC_TX_ER */
+ IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 0, 0x000, 0), /* MX53_PAD_KEY_COL1__KPP_COL_1 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 1, 0x000, 0), /* MX53_PAD_KEY_COL1__GPIO4_8 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 2, 0x75C, 0), /* MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS */
+ IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 4, 0x000, 0), /* MX53_PAD_KEY_COL1__UART5_TXD_MUX */
+ IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 5, 0x7A0, 0), /* MX53_PAD_KEY_COL1__ECSPI1_MISO */
+ IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 6, 0x808, 0), /* MX53_PAD_KEY_COL1__FEC_RX_CLK */
+ IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 7, 0x000, 0), /* MX53_PAD_KEY_COL1__USBPHY1_TXREADY */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 0, 0x000, 0), /* MX53_PAD_KEY_ROW1__KPP_ROW_1 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 1, 0x000, 0), /* MX53_PAD_KEY_ROW1__GPIO4_9 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 2, 0x748, 0), /* MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 4, 0x898, 1), /* MX53_PAD_KEY_ROW1__UART5_RXD_MUX */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 5, 0x7A8, 0), /* MX53_PAD_KEY_ROW1__ECSPI1_SS0 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 6, 0x800, 0), /* MX53_PAD_KEY_ROW1__FEC_COL */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 7, 0x000, 0), /* MX53_PAD_KEY_ROW1__USBPHY1_RXVALID */
+ IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 0, 0x000, 0), /* MX53_PAD_KEY_COL2__KPP_COL_2 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 1, 0x000, 0), /* MX53_PAD_KEY_COL2__GPIO4_10 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 2, 0x000, 0), /* MX53_PAD_KEY_COL2__CAN1_TXCAN */
+ IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 4, 0x804, 0), /* MX53_PAD_KEY_COL2__FEC_MDIO */
+ IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 5, 0x7AC, 0), /* MX53_PAD_KEY_COL2__ECSPI1_SS1 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 6, 0x000, 0), /* MX53_PAD_KEY_COL2__FEC_RDATA_2 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 7, 0x000, 0), /* MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 0, 0x000, 0), /* MX53_PAD_KEY_ROW2__KPP_ROW_2 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 1, 0x000, 0), /* MX53_PAD_KEY_ROW2__GPIO4_11 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 2, 0x760, 0), /* MX53_PAD_KEY_ROW2__CAN1_RXCAN */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 4, 0x000, 0), /* MX53_PAD_KEY_ROW2__FEC_MDC */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 5, 0x7B0, 0), /* MX53_PAD_KEY_ROW2__ECSPI1_SS2 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 6, 0x000, 0), /* MX53_PAD_KEY_ROW2__FEC_TDATA_2 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 7, 0x000, 0), /* MX53_PAD_KEY_ROW2__USBPHY1_RXERROR */
+ IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 0, 0x000, 0), /* MX53_PAD_KEY_COL3__KPP_COL_3 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 1, 0x000, 0), /* MX53_PAD_KEY_COL3__GPIO4_12 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 2, 0x000, 0), /* MX53_PAD_KEY_COL3__USBOH3_H2_DP */
+ IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 3, 0x870, 0), /* MX53_PAD_KEY_COL3__SPDIF_IN1 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 4, 0x81C, 0), /* MX53_PAD_KEY_COL3__I2C2_SCL */
+ IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 5, 0x7B4, 0), /* MX53_PAD_KEY_COL3__ECSPI1_SS3 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 6, 0x000, 0), /* MX53_PAD_KEY_COL3__FEC_CRS */
+ IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 7, 0x000, 0), /* MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 0, 0x000, 0), /* MX53_PAD_KEY_ROW3__KPP_ROW_3 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 1, 0x000, 0), /* MX53_PAD_KEY_ROW3__GPIO4_13 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 2, 0x000, 0), /* MX53_PAD_KEY_ROW3__USBOH3_H2_DM */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 3, 0x768, 0), /* MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 4, 0x820, 0), /* MX53_PAD_KEY_ROW3__I2C2_SDA */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 5, 0x000, 0), /* MX53_PAD_KEY_ROW3__OSC32K_32K_OUT */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 6, 0x77C, 0), /* MX53_PAD_KEY_ROW3__CCM_PLL4_BYP */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 7, 0x000, 0), /* MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 0, 0x000, 0), /* MX53_PAD_KEY_COL4__KPP_COL_4 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 1, 0x000, 0), /* MX53_PAD_KEY_COL4__GPIO4_14 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 2, 0x000, 0), /* MX53_PAD_KEY_COL4__CAN2_TXCAN */
+ IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 3, 0x000, 0), /* MX53_PAD_KEY_COL4__IPU_SISG_4 */
+ IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 4, 0x894, 0), /* MX53_PAD_KEY_COL4__UART5_RTS */
+ IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 5, 0x89C, 0), /* MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC */
+ IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 7, 0x000, 0), /* MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 0, 0x000, 0), /* MX53_PAD_KEY_ROW4__KPP_ROW_4 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 1, 0x000, 0), /* MX53_PAD_KEY_ROW4__GPIO4_15 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 2, 0x764, 0), /* MX53_PAD_KEY_ROW4__CAN2_RXCAN */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 3, 0x000, 0), /* MX53_PAD_KEY_ROW4__IPU_SISG_5 */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 4, 0x000, 0), /* MX53_PAD_KEY_ROW4__UART5_CTS */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 5, 0x000, 0), /* MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR */
+ IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 7, 0x000, 0), /* MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID */
+ IMX_PIN_REG(MX53_PAD_DI0_DISP_CLK, 0x378, 0x04C, 0, 0x000, 0), /* MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK */
+ IMX_PIN_REG(MX53_PAD_DI0_DISP_CLK, 0x378, 0x04C, 1, 0x000, 0), /* MX53_PAD_DI0_DISP_CLK__GPIO4_16 */
+ IMX_PIN_REG(MX53_PAD_DI0_DISP_CLK, 0x378, 0x04C, 2, 0x000, 0), /* MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR */
+ IMX_PIN_REG(MX53_PAD_DI0_DISP_CLK, 0x378, 0x04C, 5, 0x000, 0), /* MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0 */
+ IMX_PIN_REG(MX53_PAD_DI0_DISP_CLK, 0x378, 0x04C, 6, 0x000, 0), /* MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0 */
+ IMX_PIN_REG(MX53_PAD_DI0_DISP_CLK, 0x378, 0x04C, 7, 0x000, 0), /* MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN15, 0x37C, 0x050, 0, 0x000, 0), /* MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN15, 0x37C, 0x050, 1, 0x000, 0), /* MX53_PAD_DI0_PIN15__GPIO4_17 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN15, 0x37C, 0x050, 2, 0x000, 0), /* MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN15, 0x37C, 0x050, 5, 0x000, 0), /* MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN15, 0x37C, 0x050, 6, 0x000, 0), /* MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN15, 0x37C, 0x050, 7, 0x000, 0), /* MX53_PAD_DI0_PIN15__USBPHY1_BVALID */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN2, 0x380, 0x054, 0, 0x000, 0), /* MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN2, 0x380, 0x054, 1, 0x000, 0), /* MX53_PAD_DI0_PIN2__GPIO4_18 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN2, 0x380, 0x054, 2, 0x000, 0), /* MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN2, 0x380, 0x054, 5, 0x000, 0), /* MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN2, 0x380, 0x054, 6, 0x000, 0), /* MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN2, 0x380, 0x054, 7, 0x000, 0), /* MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN3, 0x384, 0x058, 0, 0x000, 0), /* MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN3, 0x384, 0x058, 1, 0x000, 0), /* MX53_PAD_DI0_PIN3__GPIO4_19 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN3, 0x384, 0x058, 2, 0x000, 0), /* MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN3, 0x384, 0x058, 5, 0x000, 0), /* MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN3, 0x384, 0x058, 6, 0x000, 0), /* MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN3, 0x384, 0x058, 7, 0x000, 0), /* MX53_PAD_DI0_PIN3__USBPHY1_IDDIG */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 0, 0x000, 0), /* MX53_PAD_DI0_PIN4__IPU_DI0_PIN4 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 1, 0x000, 0), /* MX53_PAD_DI0_PIN4__GPIO4_20 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 2, 0x000, 0), /* MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 3, 0x7FC, 0), /* MX53_PAD_DI0_PIN4__ESDHC1_WP */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 5, 0x000, 0), /* MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 6, 0x000, 0), /* MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4 */
+ IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 7, 0x000, 0), /* MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT0__GPIO4_21 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 2, 0x780, 0), /* MX53_PAD_DISP0_DAT0__CSPI_SCLK */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT1__GPIO4_22 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 2, 0x788, 0), /* MX53_PAD_DISP0_DAT1__CSPI_MOSI */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT2__GPIO4_23 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 2, 0x784, 0), /* MX53_PAD_DISP0_DAT2__CSPI_MISO */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT3__GPIO4_24 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 2, 0x78C, 0), /* MX53_PAD_DISP0_DAT3__CSPI_SS0 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT4__GPIO4_25 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 2, 0x790, 0), /* MX53_PAD_DISP0_DAT4__CSPI_SS1 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT5__GPIO4_26 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 2, 0x794, 0), /* MX53_PAD_DISP0_DAT5__CSPI_SS2 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT6__GPIO4_27 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 2, 0x798, 0), /* MX53_PAD_DISP0_DAT6__CSPI_SS3 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT7__GPIO4_28 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 2, 0x000, 0), /* MX53_PAD_DISP0_DAT7__CSPI_RDY */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT8__GPIO4_29 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 2, 0x000, 0), /* MX53_PAD_DISP0_DAT8__PWM1_PWMO */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT8__USBPHY2_AVALID */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT9__GPIO4_30 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 2, 0x000, 0), /* MX53_PAD_DISP0_DAT9__PWM2_PWMO */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT10, 0x3B4, 0x088, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT10, 0x3B4, 0x088, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT10__GPIO4_31 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT10, 0x3B4, 0x088, 2, 0x000, 0), /* MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT10, 0x3B4, 0x088, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT10, 0x3B4, 0x088, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT10, 0x3B4, 0x088, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT11, 0x3B8, 0x08C, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT11, 0x3B8, 0x08C, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT11__GPIO5_5 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT11, 0x3B8, 0x08C, 2, 0x000, 0), /* MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT11, 0x3B8, 0x08C, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT11, 0x3B8, 0x08C, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT11, 0x3B8, 0x08C, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT12, 0x3BC, 0x090, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT12, 0x3BC, 0x090, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT12__GPIO5_6 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT12, 0x3BC, 0x090, 2, 0x000, 0), /* MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT12, 0x3BC, 0x090, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT12, 0x3BC, 0x090, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT12, 0x3BC, 0x090, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT13, 0x3C0, 0x094, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT13, 0x3C0, 0x094, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT13__GPIO5_7 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT13, 0x3C0, 0x094, 3, 0x754, 0), /* MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT13, 0x3C0, 0x094, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT13, 0x3C0, 0x094, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT13, 0x3C0, 0x094, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT14, 0x3C4, 0x098, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT14, 0x3C4, 0x098, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT14__GPIO5_8 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT14, 0x3C4, 0x098, 3, 0x750, 0), /* MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT14, 0x3C4, 0x098, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT14, 0x3C4, 0x098, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT14, 0x3C4, 0x098, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT15__GPIO5_9 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 2, 0x7AC, 1), /* MX53_PAD_DISP0_DAT15__ECSPI1_SS1 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 3, 0x7C8, 0), /* MX53_PAD_DISP0_DAT15__ECSPI2_SS1 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT16__GPIO5_10 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 2, 0x7C0, 0), /* MX53_PAD_DISP0_DAT16__ECSPI2_MOSI */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 3, 0x758, 1), /* MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 4, 0x868, 0), /* MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT17__GPIO5_11 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 2, 0x7BC, 0), /* MX53_PAD_DISP0_DAT17__ECSPI2_MISO */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 3, 0x74C, 1), /* MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 4, 0x86C, 0), /* MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT18__GPIO5_12 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 2, 0x7C4, 0), /* MX53_PAD_DISP0_DAT18__ECSPI2_SS0 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 3, 0x75C, 1), /* MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 4, 0x73C, 0), /* MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT19__GPIO5_13 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 2, 0x7B8, 0), /* MX53_PAD_DISP0_DAT19__ECSPI2_SCLK */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 3, 0x748, 1), /* MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 4, 0x738, 0), /* MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT20__GPIO5_14 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 2, 0x79C, 1), /* MX53_PAD_DISP0_DAT20__ECSPI1_SCLK */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 3, 0x740, 0), /* MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT20__SATA_PHY_TDI */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT21__GPIO5_15 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 2, 0x7A4, 1), /* MX53_PAD_DISP0_DAT21__ECSPI1_MOSI */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 3, 0x734, 0), /* MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT21__SATA_PHY_TDO */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT22__GPIO5_16 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 2, 0x7A0, 1), /* MX53_PAD_DISP0_DAT22__ECSPI1_MISO */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 3, 0x744, 0), /* MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT22__SATA_PHY_TCK */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT23__GPIO5_17 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 2, 0x7A8, 1), /* MX53_PAD_DISP0_DAT23__ECSPI1_SS0 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 3, 0x730, 0), /* MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28 */
+ IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT23__SATA_PHY_TMS */
+ IMX_PIN_REG(MX53_PAD_CSI0_PIXCLK, 0x3EC, 0x0C0, 0, 0x000, 0), /* MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK */
+ IMX_PIN_REG(MX53_PAD_CSI0_PIXCLK, 0x3EC, 0x0C0, 1, 0x000, 0), /* MX53_PAD_CSI0_PIXCLK__GPIO5_18 */
+ IMX_PIN_REG(MX53_PAD_CSI0_PIXCLK, 0x3EC, 0x0C0, 5, 0x000, 0), /* MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 */
+ IMX_PIN_REG(MX53_PAD_CSI0_PIXCLK, 0x3EC, 0x0C0, 6, 0x000, 0), /* MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29 */
+ IMX_PIN_REG(MX53_PAD_CSI0_MCLK, 0x3F0, 0x0C4, 0, 0x000, 0), /* MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC */
+ IMX_PIN_REG(MX53_PAD_CSI0_MCLK, 0x3F0, 0x0C4, 1, 0x000, 0), /* MX53_PAD_CSI0_MCLK__GPIO5_19 */
+ IMX_PIN_REG(MX53_PAD_CSI0_MCLK, 0x3F0, 0x0C4, 2, 0x000, 0), /* MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK */
+ IMX_PIN_REG(MX53_PAD_CSI0_MCLK, 0x3F0, 0x0C4, 5, 0x000, 0), /* MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 */
+ IMX_PIN_REG(MX53_PAD_CSI0_MCLK, 0x3F0, 0x0C4, 6, 0x000, 0), /* MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30 */
+ IMX_PIN_REG(MX53_PAD_CSI0_MCLK, 0x3F0, 0x0C4, 7, 0x000, 0), /* MX53_PAD_CSI0_MCLK__TPIU_TRCTL */
+ IMX_PIN_REG(MX53_PAD_CSI0_DATA_EN, 0x3F4, 0x0C8, 0, 0x000, 0), /* MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN */
+ IMX_PIN_REG(MX53_PAD_CSI0_DATA_EN, 0x3F4, 0x0C8, 1, 0x000, 0), /* MX53_PAD_CSI0_DATA_EN__GPIO5_20 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DATA_EN, 0x3F4, 0x0C8, 5, 0x000, 0), /* MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DATA_EN, 0x3F4, 0x0C8, 6, 0x000, 0), /* MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DATA_EN, 0x3F4, 0x0C8, 7, 0x000, 0), /* MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK */
+ IMX_PIN_REG(MX53_PAD_CSI0_VSYNC, 0x3F8, 0x0CC, 0, 0x000, 0), /* MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC */
+ IMX_PIN_REG(MX53_PAD_CSI0_VSYNC, 0x3F8, 0x0CC, 1, 0x000, 0), /* MX53_PAD_CSI0_VSYNC__GPIO5_21 */
+ IMX_PIN_REG(MX53_PAD_CSI0_VSYNC, 0x3F8, 0x0CC, 5, 0x000, 0), /* MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 */
+ IMX_PIN_REG(MX53_PAD_CSI0_VSYNC, 0x3F8, 0x0CC, 6, 0x000, 0), /* MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32 */
+ IMX_PIN_REG(MX53_PAD_CSI0_VSYNC, 0x3F8, 0x0CC, 7, 0x000, 0), /* MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT4__GPIO5_22 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 2, 0x840, 1), /* MX53_PAD_CSI0_DAT4__KPP_COL_5 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 3, 0x79C, 2), /* MX53_PAD_CSI0_DAT4__ECSPI1_SCLK */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT4__TPIU_TRACE_1 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT5__GPIO5_23 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 2, 0x84C, 0), /* MX53_PAD_CSI0_DAT5__KPP_ROW_5 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 3, 0x7A4, 2), /* MX53_PAD_CSI0_DAT5__ECSPI1_MOSI */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT5__TPIU_TRACE_2 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT6__GPIO5_24 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 2, 0x844, 0), /* MX53_PAD_CSI0_DAT6__KPP_COL_6 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 3, 0x7A0, 2), /* MX53_PAD_CSI0_DAT6__ECSPI1_MISO */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT6__TPIU_TRACE_3 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT7__GPIO5_25 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 2, 0x850, 0), /* MX53_PAD_CSI0_DAT7__KPP_ROW_6 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 3, 0x7A8, 2), /* MX53_PAD_CSI0_DAT7__ECSPI1_SS0 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT7__TPIU_TRACE_4 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT8__GPIO5_26 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 2, 0x848, 0), /* MX53_PAD_CSI0_DAT8__KPP_COL_7 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 3, 0x7B8, 1), /* MX53_PAD_CSI0_DAT8__ECSPI2_SCLK */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 5, 0x818, 0), /* MX53_PAD_CSI0_DAT8__I2C1_SDA */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT8__TPIU_TRACE_5 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT9__GPIO5_27 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 2, 0x854, 0), /* MX53_PAD_CSI0_DAT9__KPP_ROW_7 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 3, 0x7C0, 1), /* MX53_PAD_CSI0_DAT9__ECSPI2_MOSI */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 5, 0x814, 0), /* MX53_PAD_CSI0_DAT9__I2C1_SCL */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT9__TPIU_TRACE_6 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT10__GPIO5_28 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 2, 0x000, 0), /* MX53_PAD_CSI0_DAT10__UART1_TXD_MUX */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 3, 0x7BC, 1), /* MX53_PAD_CSI0_DAT10__ECSPI2_MISO */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT10__TPIU_TRACE_7 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT11__GPIO5_29 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 2, 0x878, 1), /* MX53_PAD_CSI0_DAT11__UART1_RXD_MUX */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 3, 0x7C4, 1), /* MX53_PAD_CSI0_DAT11__ECSPI2_SS0 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT11__TPIU_TRACE_8 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT12__GPIO5_30 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 2, 0x000, 0), /* MX53_PAD_CSI0_DAT12__UART4_TXD_MUX */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT12__TPIU_TRACE_9 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT13__GPIO5_31 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 2, 0x890, 3), /* MX53_PAD_CSI0_DAT13__UART4_RXD_MUX */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT13__TPIU_TRACE_10 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT14__GPIO6_0 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 2, 0x000, 0), /* MX53_PAD_CSI0_DAT14__UART5_TXD_MUX */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT14__TPIU_TRACE_11 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT15__GPIO6_1 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 2, 0x898, 3), /* MX53_PAD_CSI0_DAT15__UART5_RXD_MUX */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT15__TPIU_TRACE_12 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT16__GPIO6_2 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 2, 0x88C, 0), /* MX53_PAD_CSI0_DAT16__UART4_RTS */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT16__TPIU_TRACE_13 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT17__GPIO6_3 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 2, 0x000, 0), /* MX53_PAD_CSI0_DAT17__UART4_CTS */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT17__TPIU_TRACE_14 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT18__GPIO6_4 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 2, 0x894, 2), /* MX53_PAD_CSI0_DAT18__UART5_RTS */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT18__TPIU_TRACE_15 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT19__GPIO6_5 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 2, 0x000, 0), /* MX53_PAD_CSI0_DAT19__UART5_CTS */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48 */
+ IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK */
+ IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 0, 0x000, 0), /* MX53_PAD_EIM_A25__EMI_WEIM_A_25 */
+ IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 1, 0x000, 0), /* MX53_PAD_EIM_A25__GPIO5_2 */
+ IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 2, 0x000, 0), /* MX53_PAD_EIM_A25__ECSPI2_RDY */
+ IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 3, 0x000, 0), /* MX53_PAD_EIM_A25__IPU_DI1_PIN12 */
+ IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 4, 0x790, 1), /* MX53_PAD_EIM_A25__CSPI_SS1 */
+ IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 6, 0x000, 0), /* MX53_PAD_EIM_A25__IPU_DI0_D1_CS */
+ IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 7, 0x000, 0), /* MX53_PAD_EIM_A25__USBPHY1_BISTOK */
+ IMX_PIN_REG(MX53_PAD_EIM_EB2, 0x45C, 0x114, 0, 0x000, 0), /* MX53_PAD_EIM_EB2__EMI_WEIM_EB_2 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB2, 0x45C, 0x114, 1, 0x000, 0), /* MX53_PAD_EIM_EB2__GPIO2_30 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB2, 0x45C, 0x114, 2, 0x76C, 0), /* MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK */
+ IMX_PIN_REG(MX53_PAD_EIM_EB2, 0x45C, 0x114, 3, 0x000, 0), /* MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS */
+ IMX_PIN_REG(MX53_PAD_EIM_EB2, 0x45C, 0x114, 4, 0x7A8, 3), /* MX53_PAD_EIM_EB2__ECSPI1_SS0 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB2, 0x45C, 0x114, 5, 0x81C, 1), /* MX53_PAD_EIM_EB2__I2C2_SCL */
+ IMX_PIN_REG(MX53_PAD_EIM_D16, 0x460, 0x118, 0, 0x000, 0), /* MX53_PAD_EIM_D16__EMI_WEIM_D_16 */
+ IMX_PIN_REG(MX53_PAD_EIM_D16, 0x460, 0x118, 1, 0x000, 0), /* MX53_PAD_EIM_D16__GPIO3_16 */
+ IMX_PIN_REG(MX53_PAD_EIM_D16, 0x460, 0x118, 2, 0x000, 0), /* MX53_PAD_EIM_D16__IPU_DI0_PIN5 */
+ IMX_PIN_REG(MX53_PAD_EIM_D16, 0x460, 0x118, 3, 0x000, 0), /* MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK */
+ IMX_PIN_REG(MX53_PAD_EIM_D16, 0x460, 0x118, 4, 0x79C, 3), /* MX53_PAD_EIM_D16__ECSPI1_SCLK */
+ IMX_PIN_REG(MX53_PAD_EIM_D16, 0x460, 0x118, 5, 0x820, 1), /* MX53_PAD_EIM_D16__I2C2_SDA */
+ IMX_PIN_REG(MX53_PAD_EIM_D17, 0x464, 0x11C, 0, 0x000, 0), /* MX53_PAD_EIM_D17__EMI_WEIM_D_17 */
+ IMX_PIN_REG(MX53_PAD_EIM_D17, 0x464, 0x11C, 1, 0x000, 0), /* MX53_PAD_EIM_D17__GPIO3_17 */
+ IMX_PIN_REG(MX53_PAD_EIM_D17, 0x464, 0x11C, 2, 0x000, 0), /* MX53_PAD_EIM_D17__IPU_DI0_PIN6 */
+ IMX_PIN_REG(MX53_PAD_EIM_D17, 0x464, 0x11C, 3, 0x830, 0), /* MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN */
+ IMX_PIN_REG(MX53_PAD_EIM_D17, 0x464, 0x11C, 4, 0x7A0, 3), /* MX53_PAD_EIM_D17__ECSPI1_MISO */
+ IMX_PIN_REG(MX53_PAD_EIM_D17, 0x464, 0x11C, 5, 0x824, 0), /* MX53_PAD_EIM_D17__I2C3_SCL */
+ IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 0, 0x000, 0), /* MX53_PAD_EIM_D18__EMI_WEIM_D_18 */
+ IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 1, 0x000, 0), /* MX53_PAD_EIM_D18__GPIO3_18 */
+ IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 2, 0x000, 0), /* MX53_PAD_EIM_D18__IPU_DI0_PIN7 */
+ IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 3, 0x830, 1), /* MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO */
+ IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 4, 0x7A4, 3), /* MX53_PAD_EIM_D18__ECSPI1_MOSI */
+ IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 5, 0x828, 0), /* MX53_PAD_EIM_D18__I2C3_SDA */
+ IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 6, 0x000, 0), /* MX53_PAD_EIM_D18__IPU_DI1_D0_CS */
+ IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 0, 0x000, 0), /* MX53_PAD_EIM_D19__EMI_WEIM_D_19 */
+ IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 1, 0x000, 0), /* MX53_PAD_EIM_D19__GPIO3_19 */
+ IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 2, 0x000, 0), /* MX53_PAD_EIM_D19__IPU_DI0_PIN8 */
+ IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 3, 0x000, 0), /* MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS */
+ IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 4, 0x7AC, 2), /* MX53_PAD_EIM_D19__ECSPI1_SS1 */
+ IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 5, 0x000, 0), /* MX53_PAD_EIM_D19__EPIT1_EPITO */
+ IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 6, 0x000, 0), /* MX53_PAD_EIM_D19__UART1_CTS */
+ IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 7, 0x8A4, 0), /* MX53_PAD_EIM_D19__USBOH3_USBH2_OC */
+ IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 0, 0x000, 0), /* MX53_PAD_EIM_D20__EMI_WEIM_D_20 */
+ IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 1, 0x000, 0), /* MX53_PAD_EIM_D20__GPIO3_20 */
+ IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 2, 0x000, 0), /* MX53_PAD_EIM_D20__IPU_DI0_PIN16 */
+ IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 3, 0x000, 0), /* MX53_PAD_EIM_D20__IPU_SER_DISP0_CS */
+ IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 4, 0x78C, 1), /* MX53_PAD_EIM_D20__CSPI_SS0 */
+ IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 5, 0x000, 0), /* MX53_PAD_EIM_D20__EPIT2_EPITO */
+ IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 6, 0x874, 1), /* MX53_PAD_EIM_D20__UART1_RTS */
+ IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 7, 0x000, 0), /* MX53_PAD_EIM_D20__USBOH3_USBH2_PWR */
+ IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 0, 0x000, 0), /* MX53_PAD_EIM_D21__EMI_WEIM_D_21 */
+ IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 1, 0x000, 0), /* MX53_PAD_EIM_D21__GPIO3_21 */
+ IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 2, 0x000, 0), /* MX53_PAD_EIM_D21__IPU_DI0_PIN17 */
+ IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 3, 0x000, 0), /* MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK */
+ IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 4, 0x780, 1), /* MX53_PAD_EIM_D21__CSPI_SCLK */
+ IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 5, 0x814, 1), /* MX53_PAD_EIM_D21__I2C1_SCL */
+ IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 6, 0x89C, 1), /* MX53_PAD_EIM_D21__USBOH3_USBOTG_OC */
+ IMX_PIN_REG(MX53_PAD_EIM_D22, 0x478, 0x130, 0, 0x000, 0), /* MX53_PAD_EIM_D22__EMI_WEIM_D_22 */
+ IMX_PIN_REG(MX53_PAD_EIM_D22, 0x478, 0x130, 1, 0x000, 0), /* MX53_PAD_EIM_D22__GPIO3_22 */
+ IMX_PIN_REG(MX53_PAD_EIM_D22, 0x478, 0x130, 2, 0x000, 0), /* MX53_PAD_EIM_D22__IPU_DI0_PIN1 */
+ IMX_PIN_REG(MX53_PAD_EIM_D22, 0x478, 0x130, 3, 0x82C, 0), /* MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN */
+ IMX_PIN_REG(MX53_PAD_EIM_D22, 0x478, 0x130, 4, 0x784, 1), /* MX53_PAD_EIM_D22__CSPI_MISO */
+ IMX_PIN_REG(MX53_PAD_EIM_D22, 0x478, 0x130, 6, 0x000, 0), /* MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR */
+ IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 0, 0x000, 0), /* MX53_PAD_EIM_D23__EMI_WEIM_D_23 */
+ IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 1, 0x000, 0), /* MX53_PAD_EIM_D23__GPIO3_23 */
+ IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 2, 0x000, 0), /* MX53_PAD_EIM_D23__UART3_CTS */
+ IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 3, 0x000, 0), /* MX53_PAD_EIM_D23__UART1_DCD */
+ IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 4, 0x000, 0), /* MX53_PAD_EIM_D23__IPU_DI0_D0_CS */
+ IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 5, 0x000, 0), /* MX53_PAD_EIM_D23__IPU_DI1_PIN2 */
+ IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 6, 0x834, 0), /* MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN */
+ IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 7, 0x000, 0), /* MX53_PAD_EIM_D23__IPU_DI1_PIN14 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 0, 0x000, 0), /* MX53_PAD_EIM_EB3__EMI_WEIM_EB_3 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 1, 0x000, 0), /* MX53_PAD_EIM_EB3__GPIO2_31 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 2, 0x884, 1), /* MX53_PAD_EIM_EB3__UART3_RTS */
+ IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 3, 0x000, 0), /* MX53_PAD_EIM_EB3__UART1_RI */
+ IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 5, 0x000, 0), /* MX53_PAD_EIM_EB3__IPU_DI1_PIN3 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 6, 0x838, 0), /* MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC */
+ IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 7, 0x000, 0), /* MX53_PAD_EIM_EB3__IPU_DI1_PIN16 */
+ IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 0, 0x000, 0), /* MX53_PAD_EIM_D24__EMI_WEIM_D_24 */
+ IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 1, 0x000, 0), /* MX53_PAD_EIM_D24__GPIO3_24 */
+ IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 2, 0x000, 0), /* MX53_PAD_EIM_D24__UART3_TXD_MUX */
+ IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 3, 0x7B0, 1), /* MX53_PAD_EIM_D24__ECSPI1_SS2 */
+ IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 4, 0x794, 1), /* MX53_PAD_EIM_D24__CSPI_SS2 */
+ IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 5, 0x754, 1), /* MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS */
+ IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 6, 0x000, 0), /* MX53_PAD_EIM_D24__ECSPI2_SS2 */
+ IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 7, 0x000, 0), /* MX53_PAD_EIM_D24__UART1_DTR */
+ IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 0, 0x000, 0), /* MX53_PAD_EIM_D25__EMI_WEIM_D_25 */
+ IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 1, 0x000, 0), /* MX53_PAD_EIM_D25__GPIO3_25 */
+ IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 2, 0x888, 1), /* MX53_PAD_EIM_D25__UART3_RXD_MUX */
+ IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 3, 0x7B4, 1), /* MX53_PAD_EIM_D25__ECSPI1_SS3 */
+ IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 4, 0x798, 1), /* MX53_PAD_EIM_D25__CSPI_SS3 */
+ IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 5, 0x750, 1), /* MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC */
+ IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 6, 0x000, 0), /* MX53_PAD_EIM_D25__ECSPI2_SS3 */
+ IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 7, 0x000, 0), /* MX53_PAD_EIM_D25__UART1_DSR */
+ IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 0, 0x000, 0), /* MX53_PAD_EIM_D26__EMI_WEIM_D_26 */
+ IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 1, 0x000, 0), /* MX53_PAD_EIM_D26__GPIO3_26 */
+ IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 2, 0x000, 0), /* MX53_PAD_EIM_D26__UART2_TXD_MUX */
+ IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 3, 0x80C, 0), /* MX53_PAD_EIM_D26__FIRI_RXD */
+ IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 4, 0x000, 0), /* MX53_PAD_EIM_D26__IPU_CSI0_D_1 */
+ IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 5, 0x000, 0), /* MX53_PAD_EIM_D26__IPU_DI1_PIN11 */
+ IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 6, 0x000, 0), /* MX53_PAD_EIM_D26__IPU_SISG_2 */
+ IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 7, 0x000, 0), /* MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 */
+ IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 0, 0x000, 0), /* MX53_PAD_EIM_D27__EMI_WEIM_D_27 */
+ IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 1, 0x000, 0), /* MX53_PAD_EIM_D27__GPIO3_27 */
+ IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 2, 0x880, 1), /* MX53_PAD_EIM_D27__UART2_RXD_MUX */
+ IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 3, 0x000, 0), /* MX53_PAD_EIM_D27__FIRI_TXD */
+ IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 4, 0x000, 0), /* MX53_PAD_EIM_D27__IPU_CSI0_D_0 */
+ IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 5, 0x000, 0), /* MX53_PAD_EIM_D27__IPU_DI1_PIN13 */
+ IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 6, 0x000, 0), /* MX53_PAD_EIM_D27__IPU_SISG_3 */
+ IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 7, 0x000, 0), /* MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 */
+ IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 0, 0x000, 0), /* MX53_PAD_EIM_D28__EMI_WEIM_D_28 */
+ IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 1, 0x000, 0), /* MX53_PAD_EIM_D28__GPIO3_28 */
+ IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 2, 0x000, 0), /* MX53_PAD_EIM_D28__UART2_CTS */
+ IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 3, 0x82C, 1), /* MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO */
+ IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 4, 0x788, 1), /* MX53_PAD_EIM_D28__CSPI_MOSI */
+ IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 5, 0x818, 1), /* MX53_PAD_EIM_D28__I2C1_SDA */
+ IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 6, 0x000, 0), /* MX53_PAD_EIM_D28__IPU_EXT_TRIG */
+ IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 7, 0x000, 0), /* MX53_PAD_EIM_D28__IPU_DI0_PIN13 */
+ IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 0, 0x000, 0), /* MX53_PAD_EIM_D29__EMI_WEIM_D_29 */
+ IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 1, 0x000, 0), /* MX53_PAD_EIM_D29__GPIO3_29 */
+ IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 2, 0x87C, 1), /* MX53_PAD_EIM_D29__UART2_RTS */
+ IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 3, 0x000, 0), /* MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS */
+ IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 4, 0x78C, 2), /* MX53_PAD_EIM_D29__CSPI_SS0 */
+ IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 5, 0x000, 0), /* MX53_PAD_EIM_D29__IPU_DI1_PIN15 */
+ IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 6, 0x83C, 0), /* MX53_PAD_EIM_D29__IPU_CSI1_VSYNC */
+ IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 7, 0x000, 0), /* MX53_PAD_EIM_D29__IPU_DI0_PIN14 */
+ IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 0, 0x000, 0), /* MX53_PAD_EIM_D30__EMI_WEIM_D_30 */
+ IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 1, 0x000, 0), /* MX53_PAD_EIM_D30__GPIO3_30 */
+ IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 2, 0x000, 0), /* MX53_PAD_EIM_D30__UART3_CTS */
+ IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 3, 0x000, 0), /* MX53_PAD_EIM_D30__IPU_CSI0_D_3 */
+ IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 4, 0x000, 0), /* MX53_PAD_EIM_D30__IPU_DI0_PIN11 */
+ IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 5, 0x000, 0), /* MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 */
+ IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 6, 0x8A0, 0), /* MX53_PAD_EIM_D30__USBOH3_USBH1_OC */
+ IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 7, 0x8A4, 1), /* MX53_PAD_EIM_D30__USBOH3_USBH2_OC */
+ IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 0, 0x000, 0), /* MX53_PAD_EIM_D31__EMI_WEIM_D_31 */
+ IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 1, 0x000, 0), /* MX53_PAD_EIM_D31__GPIO3_31 */
+ IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 2, 0x884, 3), /* MX53_PAD_EIM_D31__UART3_RTS */
+ IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 3, 0x000, 0), /* MX53_PAD_EIM_D31__IPU_CSI0_D_2 */
+ IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 4, 0x000, 0), /* MX53_PAD_EIM_D31__IPU_DI0_PIN12 */
+ IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 5, 0x000, 0), /* MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 */
+ IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 6, 0x000, 0), /* MX53_PAD_EIM_D31__USBOH3_USBH1_PWR */
+ IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 7, 0x000, 0), /* MX53_PAD_EIM_D31__USBOH3_USBH2_PWR */
+ IMX_PIN_REG(MX53_PAD_EIM_A24, 0x4A8, 0x15C, 0, 0x000, 0), /* MX53_PAD_EIM_A24__EMI_WEIM_A_24 */
+ IMX_PIN_REG(MX53_PAD_EIM_A24, 0x4A8, 0x15C, 1, 0x000, 0), /* MX53_PAD_EIM_A24__GPIO5_4 */
+ IMX_PIN_REG(MX53_PAD_EIM_A24, 0x4A8, 0x15C, 2, 0x000, 0), /* MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 */
+ IMX_PIN_REG(MX53_PAD_EIM_A24, 0x4A8, 0x15C, 3, 0x000, 0), /* MX53_PAD_EIM_A24__IPU_CSI1_D_19 */
+ IMX_PIN_REG(MX53_PAD_EIM_A24, 0x4A8, 0x15C, 6, 0x000, 0), /* MX53_PAD_EIM_A24__IPU_SISG_2 */
+ IMX_PIN_REG(MX53_PAD_EIM_A24, 0x4A8, 0x15C, 7, 0x000, 0), /* MX53_PAD_EIM_A24__USBPHY2_BVALID */
+ IMX_PIN_REG(MX53_PAD_EIM_A23, 0x4AC, 0x160, 0, 0x000, 0), /* MX53_PAD_EIM_A23__EMI_WEIM_A_23 */
+ IMX_PIN_REG(MX53_PAD_EIM_A23, 0x4AC, 0x160, 1, 0x000, 0), /* MX53_PAD_EIM_A23__GPIO6_6 */
+ IMX_PIN_REG(MX53_PAD_EIM_A23, 0x4AC, 0x160, 2, 0x000, 0), /* MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 */
+ IMX_PIN_REG(MX53_PAD_EIM_A23, 0x4AC, 0x160, 3, 0x000, 0), /* MX53_PAD_EIM_A23__IPU_CSI1_D_18 */
+ IMX_PIN_REG(MX53_PAD_EIM_A23, 0x4AC, 0x160, 6, 0x000, 0), /* MX53_PAD_EIM_A23__IPU_SISG_3 */
+ IMX_PIN_REG(MX53_PAD_EIM_A23, 0x4AC, 0x160, 7, 0x000, 0), /* MX53_PAD_EIM_A23__USBPHY2_ENDSESSION */
+ IMX_PIN_REG(MX53_PAD_EIM_A22, 0x4B0, 0x164, 0, 0x000, 0), /* MX53_PAD_EIM_A22__EMI_WEIM_A_22 */
+ IMX_PIN_REG(MX53_PAD_EIM_A22, 0x4B0, 0x164, 1, 0x000, 0), /* MX53_PAD_EIM_A22__GPIO2_16 */
+ IMX_PIN_REG(MX53_PAD_EIM_A22, 0x4B0, 0x164, 2, 0x000, 0), /* MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 */
+ IMX_PIN_REG(MX53_PAD_EIM_A22, 0x4B0, 0x164, 3, 0x000, 0), /* MX53_PAD_EIM_A22__IPU_CSI1_D_17 */
+ IMX_PIN_REG(MX53_PAD_EIM_A22, 0x4B0, 0x164, 7, 0x000, 0), /* MX53_PAD_EIM_A22__SRC_BT_CFG1_7 */
+ IMX_PIN_REG(MX53_PAD_EIM_A21, 0x4B4, 0x168, 0, 0x000, 0), /* MX53_PAD_EIM_A21__EMI_WEIM_A_21 */
+ IMX_PIN_REG(MX53_PAD_EIM_A21, 0x4B4, 0x168, 1, 0x000, 0), /* MX53_PAD_EIM_A21__GPIO2_17 */
+ IMX_PIN_REG(MX53_PAD_EIM_A21, 0x4B4, 0x168, 2, 0x000, 0), /* MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 */
+ IMX_PIN_REG(MX53_PAD_EIM_A21, 0x4B4, 0x168, 3, 0x000, 0), /* MX53_PAD_EIM_A21__IPU_CSI1_D_16 */
+ IMX_PIN_REG(MX53_PAD_EIM_A21, 0x4B4, 0x168, 7, 0x000, 0), /* MX53_PAD_EIM_A21__SRC_BT_CFG1_6 */
+ IMX_PIN_REG(MX53_PAD_EIM_A20, 0x4B8, 0x16C, 0, 0x000, 0), /* MX53_PAD_EIM_A20__EMI_WEIM_A_20 */
+ IMX_PIN_REG(MX53_PAD_EIM_A20, 0x4B8, 0x16C, 1, 0x000, 0), /* MX53_PAD_EIM_A20__GPIO2_18 */
+ IMX_PIN_REG(MX53_PAD_EIM_A20, 0x4B8, 0x16C, 2, 0x000, 0), /* MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 */
+ IMX_PIN_REG(MX53_PAD_EIM_A20, 0x4B8, 0x16C, 3, 0x000, 0), /* MX53_PAD_EIM_A20__IPU_CSI1_D_15 */
+ IMX_PIN_REG(MX53_PAD_EIM_A20, 0x4B8, 0x16C, 7, 0x000, 0), /* MX53_PAD_EIM_A20__SRC_BT_CFG1_5 */
+ IMX_PIN_REG(MX53_PAD_EIM_A19, 0x4BC, 0x170, 0, 0x000, 0), /* MX53_PAD_EIM_A19__EMI_WEIM_A_19 */
+ IMX_PIN_REG(MX53_PAD_EIM_A19, 0x4BC, 0x170, 1, 0x000, 0), /* MX53_PAD_EIM_A19__GPIO2_19 */
+ IMX_PIN_REG(MX53_PAD_EIM_A19, 0x4BC, 0x170, 2, 0x000, 0), /* MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 */
+ IMX_PIN_REG(MX53_PAD_EIM_A19, 0x4BC, 0x170, 3, 0x000, 0), /* MX53_PAD_EIM_A19__IPU_CSI1_D_14 */
+ IMX_PIN_REG(MX53_PAD_EIM_A19, 0x4BC, 0x170, 7, 0x000, 0), /* MX53_PAD_EIM_A19__SRC_BT_CFG1_4 */
+ IMX_PIN_REG(MX53_PAD_EIM_A18, 0x4C0, 0x174, 0, 0x000, 0), /* MX53_PAD_EIM_A18__EMI_WEIM_A_18 */
+ IMX_PIN_REG(MX53_PAD_EIM_A18, 0x4C0, 0x174, 1, 0x000, 0), /* MX53_PAD_EIM_A18__GPIO2_20 */
+ IMX_PIN_REG(MX53_PAD_EIM_A18, 0x4C0, 0x174, 2, 0x000, 0), /* MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 */
+ IMX_PIN_REG(MX53_PAD_EIM_A18, 0x4C0, 0x174, 3, 0x000, 0), /* MX53_PAD_EIM_A18__IPU_CSI1_D_13 */
+ IMX_PIN_REG(MX53_PAD_EIM_A18, 0x4C0, 0x174, 7, 0x000, 0), /* MX53_PAD_EIM_A18__SRC_BT_CFG1_3 */
+ IMX_PIN_REG(MX53_PAD_EIM_A17, 0x4C4, 0x178, 0, 0x000, 0), /* MX53_PAD_EIM_A17__EMI_WEIM_A_17 */
+ IMX_PIN_REG(MX53_PAD_EIM_A17, 0x4C4, 0x178, 1, 0x000, 0), /* MX53_PAD_EIM_A17__GPIO2_21 */
+ IMX_PIN_REG(MX53_PAD_EIM_A17, 0x4C4, 0x178, 2, 0x000, 0), /* MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 */
+ IMX_PIN_REG(MX53_PAD_EIM_A17, 0x4C4, 0x178, 3, 0x000, 0), /* MX53_PAD_EIM_A17__IPU_CSI1_D_12 */
+ IMX_PIN_REG(MX53_PAD_EIM_A17, 0x4C4, 0x178, 7, 0x000, 0), /* MX53_PAD_EIM_A17__SRC_BT_CFG1_2 */
+ IMX_PIN_REG(MX53_PAD_EIM_A16, 0x4C8, 0x17C, 0, 0x000, 0), /* MX53_PAD_EIM_A16__EMI_WEIM_A_16 */
+ IMX_PIN_REG(MX53_PAD_EIM_A16, 0x4C8, 0x17C, 1, 0x000, 0), /* MX53_PAD_EIM_A16__GPIO2_22 */
+ IMX_PIN_REG(MX53_PAD_EIM_A16, 0x4C8, 0x17C, 2, 0x000, 0), /* MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK */
+ IMX_PIN_REG(MX53_PAD_EIM_A16, 0x4C8, 0x17C, 3, 0x000, 0), /* MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK */
+ IMX_PIN_REG(MX53_PAD_EIM_A16, 0x4C8, 0x17C, 7, 0x000, 0), /* MX53_PAD_EIM_A16__SRC_BT_CFG1_1 */
+ IMX_PIN_REG(MX53_PAD_EIM_CS0, 0x4CC, 0x180, 0, 0x000, 0), /* MX53_PAD_EIM_CS0__EMI_WEIM_CS_0 */
+ IMX_PIN_REG(MX53_PAD_EIM_CS0, 0x4CC, 0x180, 1, 0x000, 0), /* MX53_PAD_EIM_CS0__GPIO2_23 */
+ IMX_PIN_REG(MX53_PAD_EIM_CS0, 0x4CC, 0x180, 2, 0x7B8, 2), /* MX53_PAD_EIM_CS0__ECSPI2_SCLK */
+ IMX_PIN_REG(MX53_PAD_EIM_CS0, 0x4CC, 0x180, 3, 0x000, 0), /* MX53_PAD_EIM_CS0__IPU_DI1_PIN5 */
+ IMX_PIN_REG(MX53_PAD_EIM_CS1, 0x4D0, 0x184, 0, 0x000, 0), /* MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 */
+ IMX_PIN_REG(MX53_PAD_EIM_CS1, 0x4D0, 0x184, 1, 0x000, 0), /* MX53_PAD_EIM_CS1__GPIO2_24 */
+ IMX_PIN_REG(MX53_PAD_EIM_CS1, 0x4D0, 0x184, 2, 0x7C0, 2), /* MX53_PAD_EIM_CS1__ECSPI2_MOSI */
+ IMX_PIN_REG(MX53_PAD_EIM_CS1, 0x4D0, 0x184, 3, 0x000, 0), /* MX53_PAD_EIM_CS1__IPU_DI1_PIN6 */
+ IMX_PIN_REG(MX53_PAD_EIM_OE, 0x4D4, 0x188, 0, 0x000, 0), /* MX53_PAD_EIM_OE__EMI_WEIM_OE */
+ IMX_PIN_REG(MX53_PAD_EIM_OE, 0x4D4, 0x188, 1, 0x000, 0), /* MX53_PAD_EIM_OE__GPIO2_25 */
+ IMX_PIN_REG(MX53_PAD_EIM_OE, 0x4D4, 0x188, 2, 0x7BC, 2), /* MX53_PAD_EIM_OE__ECSPI2_MISO */
+ IMX_PIN_REG(MX53_PAD_EIM_OE, 0x4D4, 0x188, 3, 0x000, 0), /* MX53_PAD_EIM_OE__IPU_DI1_PIN7 */
+ IMX_PIN_REG(MX53_PAD_EIM_OE, 0x4D4, 0x188, 7, 0x000, 0), /* MX53_PAD_EIM_OE__USBPHY2_IDDIG */
+ IMX_PIN_REG(MX53_PAD_EIM_RW, 0x4D8, 0x18C, 0, 0x000, 0), /* MX53_PAD_EIM_RW__EMI_WEIM_RW */
+ IMX_PIN_REG(MX53_PAD_EIM_RW, 0x4D8, 0x18C, 1, 0x000, 0), /* MX53_PAD_EIM_RW__GPIO2_26 */
+ IMX_PIN_REG(MX53_PAD_EIM_RW, 0x4D8, 0x18C, 2, 0x7C4, 2), /* MX53_PAD_EIM_RW__ECSPI2_SS0 */
+ IMX_PIN_REG(MX53_PAD_EIM_RW, 0x4D8, 0x18C, 3, 0x000, 0), /* MX53_PAD_EIM_RW__IPU_DI1_PIN8 */
+ IMX_PIN_REG(MX53_PAD_EIM_RW, 0x4D8, 0x18C, 7, 0x000, 0), /* MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT */
+ IMX_PIN_REG(MX53_PAD_EIM_LBA, 0x4DC, 0x190, 0, 0x000, 0), /* MX53_PAD_EIM_LBA__EMI_WEIM_LBA */
+ IMX_PIN_REG(MX53_PAD_EIM_LBA, 0x4DC, 0x190, 1, 0x000, 0), /* MX53_PAD_EIM_LBA__GPIO2_27 */
+ IMX_PIN_REG(MX53_PAD_EIM_LBA, 0x4DC, 0x190, 2, 0x7C8, 1), /* MX53_PAD_EIM_LBA__ECSPI2_SS1 */
+ IMX_PIN_REG(MX53_PAD_EIM_LBA, 0x4DC, 0x190, 3, 0x000, 0), /* MX53_PAD_EIM_LBA__IPU_DI1_PIN17 */
+ IMX_PIN_REG(MX53_PAD_EIM_LBA, 0x4DC, 0x190, 7, 0x000, 0), /* MX53_PAD_EIM_LBA__SRC_BT_CFG1_0 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB0, 0x4E4, 0x194, 0, 0x000, 0), /* MX53_PAD_EIM_EB0__EMI_WEIM_EB_0 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB0, 0x4E4, 0x194, 1, 0x000, 0), /* MX53_PAD_EIM_EB0__GPIO2_28 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB0, 0x4E4, 0x194, 3, 0x000, 0), /* MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB0, 0x4E4, 0x194, 4, 0x000, 0), /* MX53_PAD_EIM_EB0__IPU_CSI1_D_11 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB0, 0x4E4, 0x194, 5, 0x810, 0), /* MX53_PAD_EIM_EB0__GPC_PMIC_RDY */
+ IMX_PIN_REG(MX53_PAD_EIM_EB0, 0x4E4, 0x194, 7, 0x000, 0), /* MX53_PAD_EIM_EB0__SRC_BT_CFG2_7 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB1, 0x4E8, 0x198, 0, 0x000, 0), /* MX53_PAD_EIM_EB1__EMI_WEIM_EB_1 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB1, 0x4E8, 0x198, 1, 0x000, 0), /* MX53_PAD_EIM_EB1__GPIO2_29 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB1, 0x4E8, 0x198, 3, 0x000, 0), /* MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB1, 0x4E8, 0x198, 4, 0x000, 0), /* MX53_PAD_EIM_EB1__IPU_CSI1_D_10 */
+ IMX_PIN_REG(MX53_PAD_EIM_EB1, 0x4E8, 0x198, 7, 0x000, 0), /* MX53_PAD_EIM_EB1__SRC_BT_CFG2_6 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA0, 0x4EC, 0x19C, 0, 0x000, 0), /* MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA0, 0x4EC, 0x19C, 1, 0x000, 0), /* MX53_PAD_EIM_DA0__GPIO3_0 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA0, 0x4EC, 0x19C, 3, 0x000, 0), /* MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA0, 0x4EC, 0x19C, 4, 0x000, 0), /* MX53_PAD_EIM_DA0__IPU_CSI1_D_9 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA0, 0x4EC, 0x19C, 7, 0x000, 0), /* MX53_PAD_EIM_DA0__SRC_BT_CFG2_5 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA1, 0x4F0, 0x1A0, 0, 0x000, 0), /* MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA1, 0x4F0, 0x1A0, 1, 0x000, 0), /* MX53_PAD_EIM_DA1__GPIO3_1 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA1, 0x4F0, 0x1A0, 3, 0x000, 0), /* MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA1, 0x4F0, 0x1A0, 4, 0x000, 0), /* MX53_PAD_EIM_DA1__IPU_CSI1_D_8 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA1, 0x4F0, 0x1A0, 7, 0x000, 0), /* MX53_PAD_EIM_DA1__SRC_BT_CFG2_4 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA2, 0x4F4, 0x1A4, 0, 0x000, 0), /* MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA2, 0x4F4, 0x1A4, 1, 0x000, 0), /* MX53_PAD_EIM_DA2__GPIO3_2 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA2, 0x4F4, 0x1A4, 3, 0x000, 0), /* MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA2, 0x4F4, 0x1A4, 4, 0x000, 0), /* MX53_PAD_EIM_DA2__IPU_CSI1_D_7 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA2, 0x4F4, 0x1A4, 7, 0x000, 0), /* MX53_PAD_EIM_DA2__SRC_BT_CFG2_3 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA3, 0x4F8, 0x1A8, 0, 0x000, 0), /* MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA3, 0x4F8, 0x1A8, 1, 0x000, 0), /* MX53_PAD_EIM_DA3__GPIO3_3 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA3, 0x4F8, 0x1A8, 3, 0x000, 0), /* MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA3, 0x4F8, 0x1A8, 4, 0x000, 0), /* MX53_PAD_EIM_DA3__IPU_CSI1_D_6 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA3, 0x4F8, 0x1A8, 7, 0x000, 0), /* MX53_PAD_EIM_DA3__SRC_BT_CFG2_2 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA4, 0x4FC, 0x1AC, 0, 0x000, 0), /* MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA4, 0x4FC, 0x1AC, 1, 0x000, 0), /* MX53_PAD_EIM_DA4__GPIO3_4 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA4, 0x4FC, 0x1AC, 3, 0x000, 0), /* MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA4, 0x4FC, 0x1AC, 4, 0x000, 0), /* MX53_PAD_EIM_DA4__IPU_CSI1_D_5 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA4, 0x4FC, 0x1AC, 7, 0x000, 0), /* MX53_PAD_EIM_DA4__SRC_BT_CFG3_7 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA5, 0x500, 0x1B0, 0, 0x000, 0), /* MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA5, 0x500, 0x1B0, 1, 0x000, 0), /* MX53_PAD_EIM_DA5__GPIO3_5 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA5, 0x500, 0x1B0, 3, 0x000, 0), /* MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA5, 0x500, 0x1B0, 4, 0x000, 0), /* MX53_PAD_EIM_DA5__IPU_CSI1_D_4 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA5, 0x500, 0x1B0, 7, 0x000, 0), /* MX53_PAD_EIM_DA5__SRC_BT_CFG3_6 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA6, 0x504, 0x1B4, 0, 0x000, 0), /* MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA6, 0x504, 0x1B4, 1, 0x000, 0), /* MX53_PAD_EIM_DA6__GPIO3_6 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA6, 0x504, 0x1B4, 3, 0x000, 0), /* MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA6, 0x504, 0x1B4, 4, 0x000, 0), /* MX53_PAD_EIM_DA6__IPU_CSI1_D_3 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA6, 0x504, 0x1B4, 7, 0x000, 0), /* MX53_PAD_EIM_DA6__SRC_BT_CFG3_5 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA7, 0x508, 0x1B8, 0, 0x000, 0), /* MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA7, 0x508, 0x1B8, 1, 0x000, 0), /* MX53_PAD_EIM_DA7__GPIO3_7 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA7, 0x508, 0x1B8, 3, 0x000, 0), /* MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA7, 0x508, 0x1B8, 4, 0x000, 0), /* MX53_PAD_EIM_DA7__IPU_CSI1_D_2 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA7, 0x508, 0x1B8, 7, 0x000, 0), /* MX53_PAD_EIM_DA7__SRC_BT_CFG3_4 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA8, 0x50C, 0x1BC, 0, 0x000, 0), /* MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA8, 0x50C, 0x1BC, 1, 0x000, 0), /* MX53_PAD_EIM_DA8__GPIO3_8 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA8, 0x50C, 0x1BC, 3, 0x000, 0), /* MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA8, 0x50C, 0x1BC, 4, 0x000, 0), /* MX53_PAD_EIM_DA8__IPU_CSI1_D_1 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA8, 0x50C, 0x1BC, 7, 0x000, 0), /* MX53_PAD_EIM_DA8__SRC_BT_CFG3_3 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA9, 0x510, 0x1C0, 0, 0x000, 0), /* MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA9, 0x510, 0x1C0, 1, 0x000, 0), /* MX53_PAD_EIM_DA9__GPIO3_9 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA9, 0x510, 0x1C0, 3, 0x000, 0), /* MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA9, 0x510, 0x1C0, 4, 0x000, 0), /* MX53_PAD_EIM_DA9__IPU_CSI1_D_0 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA9, 0x510, 0x1C0, 7, 0x000, 0), /* MX53_PAD_EIM_DA9__SRC_BT_CFG3_2 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA10, 0x514, 0x1C4, 0, 0x000, 0), /* MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA10, 0x514, 0x1C4, 1, 0x000, 0), /* MX53_PAD_EIM_DA10__GPIO3_10 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA10, 0x514, 0x1C4, 3, 0x000, 0), /* MX53_PAD_EIM_DA10__IPU_DI1_PIN15 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA10, 0x514, 0x1C4, 4, 0x834, 1), /* MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN */
+ IMX_PIN_REG(MX53_PAD_EIM_DA10, 0x514, 0x1C4, 7, 0x000, 0), /* MX53_PAD_EIM_DA10__SRC_BT_CFG3_1 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA11, 0x518, 0x1C8, 0, 0x000, 0), /* MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA11, 0x518, 0x1C8, 1, 0x000, 0), /* MX53_PAD_EIM_DA11__GPIO3_11 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA11, 0x518, 0x1C8, 3, 0x000, 0), /* MX53_PAD_EIM_DA11__IPU_DI1_PIN2 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA11, 0x518, 0x1C8, 4, 0x838, 1), /* MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC */
+ IMX_PIN_REG(MX53_PAD_EIM_DA12, 0x51C, 0x1CC, 0, 0x000, 0), /* MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA12, 0x51C, 0x1CC, 1, 0x000, 0), /* MX53_PAD_EIM_DA12__GPIO3_12 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA12, 0x51C, 0x1CC, 3, 0x000, 0), /* MX53_PAD_EIM_DA12__IPU_DI1_PIN3 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA12, 0x51C, 0x1CC, 4, 0x83C, 1), /* MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC */
+ IMX_PIN_REG(MX53_PAD_EIM_DA13, 0x520, 0x1D0, 0, 0x000, 0), /* MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA13, 0x520, 0x1D0, 1, 0x000, 0), /* MX53_PAD_EIM_DA13__GPIO3_13 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA13, 0x520, 0x1D0, 3, 0x000, 0), /* MX53_PAD_EIM_DA13__IPU_DI1_D0_CS */
+ IMX_PIN_REG(MX53_PAD_EIM_DA13, 0x520, 0x1D0, 4, 0x76C, 1), /* MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK */
+ IMX_PIN_REG(MX53_PAD_EIM_DA14, 0x524, 0x1D4, 0, 0x000, 0), /* MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA14, 0x524, 0x1D4, 1, 0x000, 0), /* MX53_PAD_EIM_DA14__GPIO3_14 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA14, 0x524, 0x1D4, 3, 0x000, 0), /* MX53_PAD_EIM_DA14__IPU_DI1_D1_CS */
+ IMX_PIN_REG(MX53_PAD_EIM_DA14, 0x524, 0x1D4, 4, 0x000, 0), /* MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK */
+ IMX_PIN_REG(MX53_PAD_EIM_DA15, 0x528, 0x1D8, 0, 0x000, 0), /* MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA15, 0x528, 0x1D8, 1, 0x000, 0), /* MX53_PAD_EIM_DA15__GPIO3_15 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA15, 0x528, 0x1D8, 3, 0x000, 0), /* MX53_PAD_EIM_DA15__IPU_DI1_PIN1 */
+ IMX_PIN_REG(MX53_PAD_EIM_DA15, 0x528, 0x1D8, 4, 0x000, 0), /* MX53_PAD_EIM_DA15__IPU_DI1_PIN4 */
+ IMX_PIN_REG(MX53_PAD_NANDF_WE_B, 0x52C, 0x1DC, 0, 0x000, 0), /* MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B */
+ IMX_PIN_REG(MX53_PAD_NANDF_WE_B, 0x52C, 0x1DC, 1, 0x000, 0), /* MX53_PAD_NANDF_WE_B__GPIO6_12 */
+ IMX_PIN_REG(MX53_PAD_NANDF_RE_B, 0x530, 0x1E0, 0, 0x000, 0), /* MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B */
+ IMX_PIN_REG(MX53_PAD_NANDF_RE_B, 0x530, 0x1E0, 1, 0x000, 0), /* MX53_PAD_NANDF_RE_B__GPIO6_13 */
+ IMX_PIN_REG(MX53_PAD_EIM_WAIT, 0x534, 0x1E4, 0, 0x000, 0), /* MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT */
+ IMX_PIN_REG(MX53_PAD_EIM_WAIT, 0x534, 0x1E4, 1, 0x000, 0), /* MX53_PAD_EIM_WAIT__GPIO5_0 */
+ IMX_PIN_REG(MX53_PAD_EIM_WAIT, 0x534, 0x1E4, 2, 0x000, 0), /* MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B */
+ IMX_PIN_REG(MX53_PAD_LVDS1_TX3_P, NO_PAD, 0x1EC, 0, 0x000, 0), /* MX53_PAD_LVDS1_TX3_P__GPIO6_22 */
+ IMX_PIN_REG(MX53_PAD_LVDS1_TX3_P, NO_PAD, 0x1EC, 1, 0x000, 0), /* MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 */
+ IMX_PIN_REG(MX53_PAD_LVDS1_TX2_P, NO_PAD, 0x1F0, 0, 0x000, 0), /* MX53_PAD_LVDS1_TX2_P__GPIO6_24 */
+ IMX_PIN_REG(MX53_PAD_LVDS1_TX2_P, NO_PAD, 0x1F0, 1, 0x000, 0), /* MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 */
+ IMX_PIN_REG(MX53_PAD_LVDS1_CLK_P, NO_PAD, 0x1F4, 0, 0x000, 0), /* MX53_PAD_LVDS1_CLK_P__GPIO6_26 */
+ IMX_PIN_REG(MX53_PAD_LVDS1_CLK_P, NO_PAD, 0x1F4, 1, 0x000, 0), /* MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK */
+ IMX_PIN_REG(MX53_PAD_LVDS1_TX1_P, NO_PAD, 0x1F8, 0, 0x000, 0), /* MX53_PAD_LVDS1_TX1_P__GPIO6_28 */
+ IMX_PIN_REG(MX53_PAD_LVDS1_TX1_P, NO_PAD, 0x1F8, 1, 0x000, 0), /* MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 */
+ IMX_PIN_REG(MX53_PAD_LVDS1_TX0_P, NO_PAD, 0x1FC, 0, 0x000, 0), /* MX53_PAD_LVDS1_TX0_P__GPIO6_30 */
+ IMX_PIN_REG(MX53_PAD_LVDS1_TX0_P, NO_PAD, 0x1FC, 1, 0x000, 0), /* MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 */
+ IMX_PIN_REG(MX53_PAD_LVDS0_TX3_P, NO_PAD, 0x200, 0, 0x000, 0), /* MX53_PAD_LVDS0_TX3_P__GPIO7_22 */
+ IMX_PIN_REG(MX53_PAD_LVDS0_TX3_P, NO_PAD, 0x200, 1, 0x000, 0), /* MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 */
+ IMX_PIN_REG(MX53_PAD_LVDS0_CLK_P, NO_PAD, 0x204, 0, 0x000, 0), /* MX53_PAD_LVDS0_CLK_P__GPIO7_24 */
+ IMX_PIN_REG(MX53_PAD_LVDS0_CLK_P, NO_PAD, 0x204, 1, 0x000, 0), /* MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK */
+ IMX_PIN_REG(MX53_PAD_LVDS0_TX2_P, NO_PAD, 0x208, 0, 0x000, 0), /* MX53_PAD_LVDS0_TX2_P__GPIO7_26 */
+ IMX_PIN_REG(MX53_PAD_LVDS0_TX2_P, NO_PAD, 0x208, 1, 0x000, 0), /* MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 */
+ IMX_PIN_REG(MX53_PAD_LVDS0_TX1_P, NO_PAD, 0x20C, 0, 0x000, 0), /* MX53_PAD_LVDS0_TX1_P__GPIO7_28 */
+ IMX_PIN_REG(MX53_PAD_LVDS0_TX1_P, NO_PAD, 0x20C, 1, 0x000, 0), /* MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 */
+ IMX_PIN_REG(MX53_PAD_LVDS0_TX0_P, NO_PAD, 0x210, 0, 0x000, 0), /* MX53_PAD_LVDS0_TX0_P__GPIO7_30 */
+ IMX_PIN_REG(MX53_PAD_LVDS0_TX0_P, NO_PAD, 0x210, 1, 0x000, 0), /* MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 */
+ IMX_PIN_REG(MX53_PAD_GPIO_10, 0x540, 0x214, 0, 0x000, 0), /* MX53_PAD_GPIO_10__GPIO4_0 */
+ IMX_PIN_REG(MX53_PAD_GPIO_10, 0x540, 0x214, 1, 0x000, 0), /* MX53_PAD_GPIO_10__OSC32k_32K_OUT */
+ IMX_PIN_REG(MX53_PAD_GPIO_11, 0x544, 0x218, 0, 0x000, 0), /* MX53_PAD_GPIO_11__GPIO4_1 */
+ IMX_PIN_REG(MX53_PAD_GPIO_12, 0x548, 0x21C, 0, 0x000, 0), /* MX53_PAD_GPIO_12__GPIO4_2 */
+ IMX_PIN_REG(MX53_PAD_GPIO_13, 0x54C, 0x220, 0, 0x000, 0), /* MX53_PAD_GPIO_13__GPIO4_3 */
+ IMX_PIN_REG(MX53_PAD_GPIO_14, 0x550, 0x224, 0, 0x000, 0), /* MX53_PAD_GPIO_14__GPIO4_4 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CLE, 0x5A0, 0x228, 0, 0x000, 0), /* MX53_PAD_NANDF_CLE__EMI_NANDF_CLE */
+ IMX_PIN_REG(MX53_PAD_NANDF_CLE, 0x5A0, 0x228, 1, 0x000, 0), /* MX53_PAD_NANDF_CLE__GPIO6_7 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CLE, 0x5A0, 0x228, 7, 0x000, 0), /* MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0 */
+ IMX_PIN_REG(MX53_PAD_NANDF_ALE, 0x5A4, 0x22C, 0, 0x000, 0), /* MX53_PAD_NANDF_ALE__EMI_NANDF_ALE */
+ IMX_PIN_REG(MX53_PAD_NANDF_ALE, 0x5A4, 0x22C, 1, 0x000, 0), /* MX53_PAD_NANDF_ALE__GPIO6_8 */
+ IMX_PIN_REG(MX53_PAD_NANDF_ALE, 0x5A4, 0x22C, 7, 0x000, 0), /* MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1 */
+ IMX_PIN_REG(MX53_PAD_NANDF_WP_B, 0x5A8, 0x230, 0, 0x000, 0), /* MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B */
+ IMX_PIN_REG(MX53_PAD_NANDF_WP_B, 0x5A8, 0x230, 1, 0x000, 0), /* MX53_PAD_NANDF_WP_B__GPIO6_9 */
+ IMX_PIN_REG(MX53_PAD_NANDF_WP_B, 0x5A8, 0x230, 7, 0x000, 0), /* MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2 */
+ IMX_PIN_REG(MX53_PAD_NANDF_RB0, 0x5AC, 0x234, 0, 0x000, 0), /* MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 */
+ IMX_PIN_REG(MX53_PAD_NANDF_RB0, 0x5AC, 0x234, 1, 0x000, 0), /* MX53_PAD_NANDF_RB0__GPIO6_10 */
+ IMX_PIN_REG(MX53_PAD_NANDF_RB0, 0x5AC, 0x234, 7, 0x000, 0), /* MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS0, 0x5B0, 0x238, 0, 0x000, 0), /* MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS0, 0x5B0, 0x238, 1, 0x000, 0), /* MX53_PAD_NANDF_CS0__GPIO6_11 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS0, 0x5B0, 0x238, 7, 0x000, 0), /* MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS1, 0x5B4, 0x23C, 0, 0x000, 0), /* MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS1, 0x5B4, 0x23C, 1, 0x000, 0), /* MX53_PAD_NANDF_CS1__GPIO6_14 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS1, 0x5B4, 0x23C, 6, 0x858, 0), /* MX53_PAD_NANDF_CS1__MLB_MLBCLK */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS1, 0x5B4, 0x23C, 7, 0x000, 0), /* MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 0, 0x000, 0), /* MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 1, 0x000, 0), /* MX53_PAD_NANDF_CS2__GPIO6_15 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 2, 0x000, 0), /* MX53_PAD_NANDF_CS2__IPU_SISG_0 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 3, 0x7E4, 0), /* MX53_PAD_NANDF_CS2__ESAI1_TX0 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 4, 0x000, 0), /* MX53_PAD_NANDF_CS2__EMI_WEIM_CRE */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 5, 0x000, 0), /* MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 6, 0x860, 0), /* MX53_PAD_NANDF_CS2__MLB_MLBSIG */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 7, 0x000, 0), /* MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 0, 0x000, 0), /* MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 1, 0x000, 0), /* MX53_PAD_NANDF_CS3__GPIO6_16 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 2, 0x000, 0), /* MX53_PAD_NANDF_CS3__IPU_SISG_1 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 3, 0x7E8, 0), /* MX53_PAD_NANDF_CS3__ESAI1_TX1 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 4, 0x000, 0), /* MX53_PAD_NANDF_CS3__EMI_WEIM_A_26 */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 6, 0x85C, 0), /* MX53_PAD_NANDF_CS3__MLB_MLBDAT */
+ IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 7, 0x000, 0), /* MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7 */
+ IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 0, 0x804, 1), /* MX53_PAD_FEC_MDIO__FEC_MDIO */
+ IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 1, 0x000, 0), /* MX53_PAD_FEC_MDIO__GPIO1_22 */
+ IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 2, 0x7DC, 0), /* MX53_PAD_FEC_MDIO__ESAI1_SCKR */
+ IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 3, 0x800, 1), /* MX53_PAD_FEC_MDIO__FEC_COL */
+ IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 4, 0x000, 0), /* MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2 */
+ IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 5, 0x000, 0), /* MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3 */
+ IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 6, 0x000, 0), /* MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49 */
+ IMX_PIN_REG(MX53_PAD_FEC_REF_CLK, 0x5C8, 0x24C, 0, 0x000, 0), /* MX53_PAD_FEC_REF_CLK__FEC_TX_CLK */
+ IMX_PIN_REG(MX53_PAD_FEC_REF_CLK, 0x5C8, 0x24C, 1, 0x000, 0), /* MX53_PAD_FEC_REF_CLK__GPIO1_23 */
+ IMX_PIN_REG(MX53_PAD_FEC_REF_CLK, 0x5C8, 0x24C, 2, 0x7CC, 0), /* MX53_PAD_FEC_REF_CLK__ESAI1_FSR */
+ IMX_PIN_REG(MX53_PAD_FEC_REF_CLK, 0x5C8, 0x24C, 5, 0x000, 0), /* MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 */
+ IMX_PIN_REG(MX53_PAD_FEC_REF_CLK, 0x5C8, 0x24C, 6, 0x000, 0), /* MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50 */
+ IMX_PIN_REG(MX53_PAD_FEC_RX_ER, 0x5CC, 0x250, 0, 0x000, 0), /* MX53_PAD_FEC_RX_ER__FEC_RX_ER */
+ IMX_PIN_REG(MX53_PAD_FEC_RX_ER, 0x5CC, 0x250, 1, 0x000, 0), /* MX53_PAD_FEC_RX_ER__GPIO1_24 */
+ IMX_PIN_REG(MX53_PAD_FEC_RX_ER, 0x5CC, 0x250, 2, 0x7D4, 0), /* MX53_PAD_FEC_RX_ER__ESAI1_HCKR */
+ IMX_PIN_REG(MX53_PAD_FEC_RX_ER, 0x5CC, 0x250, 3, 0x808, 1), /* MX53_PAD_FEC_RX_ER__FEC_RX_CLK */
+ IMX_PIN_REG(MX53_PAD_FEC_RX_ER, 0x5CC, 0x250, 4, 0x000, 0), /* MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3 */
+ IMX_PIN_REG(MX53_PAD_FEC_CRS_DV, 0x5D0, 0x254, 0, 0x000, 0), /* MX53_PAD_FEC_CRS_DV__FEC_RX_DV */
+ IMX_PIN_REG(MX53_PAD_FEC_CRS_DV, 0x5D0, 0x254, 1, 0x000, 0), /* MX53_PAD_FEC_CRS_DV__GPIO1_25 */
+ IMX_PIN_REG(MX53_PAD_FEC_CRS_DV, 0x5D0, 0x254, 2, 0x7E0, 0), /* MX53_PAD_FEC_CRS_DV__ESAI1_SCKT */
+ IMX_PIN_REG(MX53_PAD_FEC_RXD1, 0x5D4, 0x258, 0, 0x000, 0), /* MX53_PAD_FEC_RXD1__FEC_RDATA_1 */
+ IMX_PIN_REG(MX53_PAD_FEC_RXD1, 0x5D4, 0x258, 1, 0x000, 0), /* MX53_PAD_FEC_RXD1__GPIO1_26 */
+ IMX_PIN_REG(MX53_PAD_FEC_RXD1, 0x5D4, 0x258, 2, 0x7D0, 0), /* MX53_PAD_FEC_RXD1__ESAI1_FST */
+ IMX_PIN_REG(MX53_PAD_FEC_RXD1, 0x5D4, 0x258, 3, 0x860, 1), /* MX53_PAD_FEC_RXD1__MLB_MLBSIG */
+ IMX_PIN_REG(MX53_PAD_FEC_RXD1, 0x5D4, 0x258, 4, 0x000, 0), /* MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1 */
+ IMX_PIN_REG(MX53_PAD_FEC_RXD0, 0x5D8, 0x25C, 0, 0x000, 0), /* MX53_PAD_FEC_RXD0__FEC_RDATA_0 */
+ IMX_PIN_REG(MX53_PAD_FEC_RXD0, 0x5D8, 0x25C, 1, 0x000, 0), /* MX53_PAD_FEC_RXD0__GPIO1_27 */
+ IMX_PIN_REG(MX53_PAD_FEC_RXD0, 0x5D8, 0x25C, 2, 0x7D8, 0), /* MX53_PAD_FEC_RXD0__ESAI1_HCKT */
+ IMX_PIN_REG(MX53_PAD_FEC_RXD0, 0x5D8, 0x25C, 3, 0x000, 0), /* MX53_PAD_FEC_RXD0__OSC32k_32K_OUT */
+ IMX_PIN_REG(MX53_PAD_FEC_TX_EN, 0x5DC, 0x260, 0, 0x000, 0), /* MX53_PAD_FEC_TX_EN__FEC_TX_EN */
+ IMX_PIN_REG(MX53_PAD_FEC_TX_EN, 0x5DC, 0x260, 1, 0x000, 0), /* MX53_PAD_FEC_TX_EN__GPIO1_28 */
+ IMX_PIN_REG(MX53_PAD_FEC_TX_EN, 0x5DC, 0x260, 2, 0x7F0, 0), /* MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2 */
+ IMX_PIN_REG(MX53_PAD_FEC_TXD1, 0x5E0, 0x264, 0, 0x000, 0), /* MX53_PAD_FEC_TXD1__FEC_TDATA_1 */
+ IMX_PIN_REG(MX53_PAD_FEC_TXD1, 0x5E0, 0x264, 1, 0x000, 0), /* MX53_PAD_FEC_TXD1__GPIO1_29 */
+ IMX_PIN_REG(MX53_PAD_FEC_TXD1, 0x5E0, 0x264, 2, 0x7EC, 0), /* MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3 */
+ IMX_PIN_REG(MX53_PAD_FEC_TXD1, 0x5E0, 0x264, 3, 0x858, 1), /* MX53_PAD_FEC_TXD1__MLB_MLBCLK */
+ IMX_PIN_REG(MX53_PAD_FEC_TXD1, 0x5E0, 0x264, 4, 0x000, 0), /* MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK */
+ IMX_PIN_REG(MX53_PAD_FEC_TXD0, 0x5E4, 0x268, 0, 0x000, 0), /* MX53_PAD_FEC_TXD0__FEC_TDATA_0 */
+ IMX_PIN_REG(MX53_PAD_FEC_TXD0, 0x5E4, 0x268, 1, 0x000, 0), /* MX53_PAD_FEC_TXD0__GPIO1_30 */
+ IMX_PIN_REG(MX53_PAD_FEC_TXD0, 0x5E4, 0x268, 2, 0x7F4, 0), /* MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1 */
+ IMX_PIN_REG(MX53_PAD_FEC_TXD0, 0x5E4, 0x268, 7, 0x000, 0), /* MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0 */
+ IMX_PIN_REG(MX53_PAD_FEC_MDC, 0x5E8, 0x26C, 0, 0x000, 0), /* MX53_PAD_FEC_MDC__FEC_MDC */
+ IMX_PIN_REG(MX53_PAD_FEC_MDC, 0x5E8, 0x26C, 1, 0x000, 0), /* MX53_PAD_FEC_MDC__GPIO1_31 */
+ IMX_PIN_REG(MX53_PAD_FEC_MDC, 0x5E8, 0x26C, 2, 0x7F8, 0), /* MX53_PAD_FEC_MDC__ESAI1_TX5_RX0 */
+ IMX_PIN_REG(MX53_PAD_FEC_MDC, 0x5E8, 0x26C, 3, 0x85C, 1), /* MX53_PAD_FEC_MDC__MLB_MLBDAT */
+ IMX_PIN_REG(MX53_PAD_FEC_MDC, 0x5E8, 0x26C, 4, 0x000, 0), /* MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG */
+ IMX_PIN_REG(MX53_PAD_FEC_MDC, 0x5E8, 0x26C, 7, 0x000, 0), /* MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1 */
+ IMX_PIN_REG(MX53_PAD_PATA_DIOW, 0x5F0, 0x270, 0, 0x000, 0), /* MX53_PAD_PATA_DIOW__PATA_DIOW */
+ IMX_PIN_REG(MX53_PAD_PATA_DIOW, 0x5F0, 0x270, 1, 0x000, 0), /* MX53_PAD_PATA_DIOW__GPIO6_17 */
+ IMX_PIN_REG(MX53_PAD_PATA_DIOW, 0x5F0, 0x270, 3, 0x000, 0), /* MX53_PAD_PATA_DIOW__UART1_TXD_MUX */
+ IMX_PIN_REG(MX53_PAD_PATA_DIOW, 0x5F0, 0x270, 7, 0x000, 0), /* MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2 */
+ IMX_PIN_REG(MX53_PAD_PATA_DMACK, 0x5F4, 0x274, 0, 0x000, 0), /* MX53_PAD_PATA_DMACK__PATA_DMACK */
+ IMX_PIN_REG(MX53_PAD_PATA_DMACK, 0x5F4, 0x274, 1, 0x000, 0), /* MX53_PAD_PATA_DMACK__GPIO6_18 */
+ IMX_PIN_REG(MX53_PAD_PATA_DMACK, 0x5F4, 0x274, 3, 0x878, 3), /* MX53_PAD_PATA_DMACK__UART1_RXD_MUX */
+ IMX_PIN_REG(MX53_PAD_PATA_DMACK, 0x5F4, 0x274, 7, 0x000, 0), /* MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3 */
+ IMX_PIN_REG(MX53_PAD_PATA_DMARQ, 0x5F8, 0x278, 0, 0x000, 0), /* MX53_PAD_PATA_DMARQ__PATA_DMARQ */
+ IMX_PIN_REG(MX53_PAD_PATA_DMARQ, 0x5F8, 0x278, 1, 0x000, 0), /* MX53_PAD_PATA_DMARQ__GPIO7_0 */
+ IMX_PIN_REG(MX53_PAD_PATA_DMARQ, 0x5F8, 0x278, 3, 0x000, 0), /* MX53_PAD_PATA_DMARQ__UART2_TXD_MUX */
+ IMX_PIN_REG(MX53_PAD_PATA_DMARQ, 0x5F8, 0x278, 5, 0x000, 0), /* MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0 */
+ IMX_PIN_REG(MX53_PAD_PATA_DMARQ, 0x5F8, 0x278, 7, 0x000, 0), /* MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4 */
+ IMX_PIN_REG(MX53_PAD_PATA_BUFFER_EN, 0x5FC, 0x27C, 0, 0x000, 0), /* MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN */
+ IMX_PIN_REG(MX53_PAD_PATA_BUFFER_EN, 0x5FC, 0x27C, 1, 0x000, 0), /* MX53_PAD_PATA_BUFFER_EN__GPIO7_1 */
+ IMX_PIN_REG(MX53_PAD_PATA_BUFFER_EN, 0x5FC, 0x27C, 3, 0x880, 3), /* MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX */
+ IMX_PIN_REG(MX53_PAD_PATA_BUFFER_EN, 0x5FC, 0x27C, 5, 0x000, 0), /* MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1 */
+ IMX_PIN_REG(MX53_PAD_PATA_BUFFER_EN, 0x5FC, 0x27C, 7, 0x000, 0), /* MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5 */
+ IMX_PIN_REG(MX53_PAD_PATA_INTRQ, 0x600, 0x280, 0, 0x000, 0), /* MX53_PAD_PATA_INTRQ__PATA_INTRQ */
+ IMX_PIN_REG(MX53_PAD_PATA_INTRQ, 0x600, 0x280, 1, 0x000, 0), /* MX53_PAD_PATA_INTRQ__GPIO7_2 */
+ IMX_PIN_REG(MX53_PAD_PATA_INTRQ, 0x600, 0x280, 3, 0x000, 0), /* MX53_PAD_PATA_INTRQ__UART2_CTS */
+ IMX_PIN_REG(MX53_PAD_PATA_INTRQ, 0x600, 0x280, 4, 0x000, 0), /* MX53_PAD_PATA_INTRQ__CAN1_TXCAN */
+ IMX_PIN_REG(MX53_PAD_PATA_INTRQ, 0x600, 0x280, 5, 0x000, 0), /* MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2 */
+ IMX_PIN_REG(MX53_PAD_PATA_INTRQ, 0x600, 0x280, 7, 0x000, 0), /* MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6 */
+ IMX_PIN_REG(MX53_PAD_PATA_DIOR, 0x604, 0x284, 0, 0x000, 0), /* MX53_PAD_PATA_DIOR__PATA_DIOR */
+ IMX_PIN_REG(MX53_PAD_PATA_DIOR, 0x604, 0x284, 1, 0x000, 0), /* MX53_PAD_PATA_DIOR__GPIO7_3 */
+ IMX_PIN_REG(MX53_PAD_PATA_DIOR, 0x604, 0x284, 3, 0x87C, 3), /* MX53_PAD_PATA_DIOR__UART2_RTS */
+ IMX_PIN_REG(MX53_PAD_PATA_DIOR, 0x604, 0x284, 4, 0x760, 1), /* MX53_PAD_PATA_DIOR__CAN1_RXCAN */
+ IMX_PIN_REG(MX53_PAD_PATA_DIOR, 0x604, 0x284, 7, 0x000, 0), /* MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7 */
+ IMX_PIN_REG(MX53_PAD_PATA_RESET_B, 0x608, 0x288, 0, 0x000, 0), /* MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B */
+ IMX_PIN_REG(MX53_PAD_PATA_RESET_B, 0x608, 0x288, 1, 0x000, 0), /* MX53_PAD_PATA_RESET_B__GPIO7_4 */
+ IMX_PIN_REG(MX53_PAD_PATA_RESET_B, 0x608, 0x288, 2, 0x000, 0), /* MX53_PAD_PATA_RESET_B__ESDHC3_CMD */
+ IMX_PIN_REG(MX53_PAD_PATA_RESET_B, 0x608, 0x288, 3, 0x000, 0), /* MX53_PAD_PATA_RESET_B__UART1_CTS */
+ IMX_PIN_REG(MX53_PAD_PATA_RESET_B, 0x608, 0x288, 4, 0x000, 0), /* MX53_PAD_PATA_RESET_B__CAN2_TXCAN */
+ IMX_PIN_REG(MX53_PAD_PATA_RESET_B, 0x608, 0x288, 7, 0x000, 0), /* MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0 */
+ IMX_PIN_REG(MX53_PAD_PATA_IORDY, 0x60C, 0x28C, 0, 0x000, 0), /* MX53_PAD_PATA_IORDY__PATA_IORDY */
+ IMX_PIN_REG(MX53_PAD_PATA_IORDY, 0x60C, 0x28C, 1, 0x000, 0), /* MX53_PAD_PATA_IORDY__GPIO7_5 */
+ IMX_PIN_REG(MX53_PAD_PATA_IORDY, 0x60C, 0x28C, 2, 0x000, 0), /* MX53_PAD_PATA_IORDY__ESDHC3_CLK */
+ IMX_PIN_REG(MX53_PAD_PATA_IORDY, 0x60C, 0x28C, 3, 0x874, 3), /* MX53_PAD_PATA_IORDY__UART1_RTS */
+ IMX_PIN_REG(MX53_PAD_PATA_IORDY, 0x60C, 0x28C, 4, 0x764, 1), /* MX53_PAD_PATA_IORDY__CAN2_RXCAN */
+ IMX_PIN_REG(MX53_PAD_PATA_IORDY, 0x60C, 0x28C, 7, 0x000, 0), /* MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1 */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_0, 0x610, 0x290, 0, 0x000, 0), /* MX53_PAD_PATA_DA_0__PATA_DA_0 */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_0, 0x610, 0x290, 1, 0x000, 0), /* MX53_PAD_PATA_DA_0__GPIO7_6 */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_0, 0x610, 0x290, 2, 0x000, 0), /* MX53_PAD_PATA_DA_0__ESDHC3_RST */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_0, 0x610, 0x290, 4, 0x864, 0), /* MX53_PAD_PATA_DA_0__OWIRE_LINE */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_0, 0x610, 0x290, 7, 0x000, 0), /* MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2 */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_1, 0x614, 0x294, 0, 0x000, 0), /* MX53_PAD_PATA_DA_1__PATA_DA_1 */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_1, 0x614, 0x294, 1, 0x000, 0), /* MX53_PAD_PATA_DA_1__GPIO7_7 */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_1, 0x614, 0x294, 2, 0x000, 0), /* MX53_PAD_PATA_DA_1__ESDHC4_CMD */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_1, 0x614, 0x294, 4, 0x000, 0), /* MX53_PAD_PATA_DA_1__UART3_CTS */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_1, 0x614, 0x294, 7, 0x000, 0), /* MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3 */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_2, 0x618, 0x298, 0, 0x000, 0), /* MX53_PAD_PATA_DA_2__PATA_DA_2 */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_2, 0x618, 0x298, 1, 0x000, 0), /* MX53_PAD_PATA_DA_2__GPIO7_8 */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_2, 0x618, 0x298, 2, 0x000, 0), /* MX53_PAD_PATA_DA_2__ESDHC4_CLK */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_2, 0x618, 0x298, 4, 0x884, 5), /* MX53_PAD_PATA_DA_2__UART3_RTS */
+ IMX_PIN_REG(MX53_PAD_PATA_DA_2, 0x618, 0x298, 7, 0x000, 0), /* MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4 */
+ IMX_PIN_REG(MX53_PAD_PATA_CS_0, 0x61C, 0x29C, 0, 0x000, 0), /* MX53_PAD_PATA_CS_0__PATA_CS_0 */
+ IMX_PIN_REG(MX53_PAD_PATA_CS_0, 0x61C, 0x29C, 1, 0x000, 0), /* MX53_PAD_PATA_CS_0__GPIO7_9 */
+ IMX_PIN_REG(MX53_PAD_PATA_CS_0, 0x61C, 0x29C, 4, 0x000, 0), /* MX53_PAD_PATA_CS_0__UART3_TXD_MUX */
+ IMX_PIN_REG(MX53_PAD_PATA_CS_0, 0x61C, 0x29C, 7, 0x000, 0), /* MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5 */
+ IMX_PIN_REG(MX53_PAD_PATA_CS_1, 0x620, 0x2A0, 0, 0x000, 0), /* MX53_PAD_PATA_CS_1__PATA_CS_1 */
+ IMX_PIN_REG(MX53_PAD_PATA_CS_1, 0x620, 0x2A0, 1, 0x000, 0), /* MX53_PAD_PATA_CS_1__GPIO7_10 */
+ IMX_PIN_REG(MX53_PAD_PATA_CS_1, 0x620, 0x2A0, 4, 0x888, 3), /* MX53_PAD_PATA_CS_1__UART3_RXD_MUX */
+ IMX_PIN_REG(MX53_PAD_PATA_CS_1, 0x620, 0x2A0, 7, 0x000, 0), /* MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 0, 0x000, 0), /* MX53_PAD_PATA_DATA0__PATA_DATA_0 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 1, 0x000, 0), /* MX53_PAD_PATA_DATA0__GPIO2_0 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 3, 0x000, 0), /* MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 4, 0x000, 0), /* MX53_PAD_PATA_DATA0__ESDHC3_DAT4 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 5, 0x000, 0), /* MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 6, 0x000, 0), /* MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 7, 0x000, 0), /* MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA1, 0x62C, 0x2A8, 0, 0x000, 0), /* MX53_PAD_PATA_DATA1__PATA_DATA_1 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA1, 0x62C, 0x2A8, 1, 0x000, 0), /* MX53_PAD_PATA_DATA1__GPIO2_1 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA1, 0x62C, 0x2A8, 3, 0x000, 0), /* MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA1, 0x62C, 0x2A8, 4, 0x000, 0), /* MX53_PAD_PATA_DATA1__ESDHC3_DAT5 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA1, 0x62C, 0x2A8, 5, 0x000, 0), /* MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA1, 0x62C, 0x2A8, 6, 0x000, 0), /* MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA2, 0x630, 0x2AC, 0, 0x000, 0), /* MX53_PAD_PATA_DATA2__PATA_DATA_2 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA2, 0x630, 0x2AC, 1, 0x000, 0), /* MX53_PAD_PATA_DATA2__GPIO2_2 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA2, 0x630, 0x2AC, 3, 0x000, 0), /* MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA2, 0x630, 0x2AC, 4, 0x000, 0), /* MX53_PAD_PATA_DATA2__ESDHC3_DAT6 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA2, 0x630, 0x2AC, 5, 0x000, 0), /* MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA2, 0x630, 0x2AC, 6, 0x000, 0), /* MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA3, 0x634, 0x2B0, 0, 0x000, 0), /* MX53_PAD_PATA_DATA3__PATA_DATA_3 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA3, 0x634, 0x2B0, 1, 0x000, 0), /* MX53_PAD_PATA_DATA3__GPIO2_3 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA3, 0x634, 0x2B0, 3, 0x000, 0), /* MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA3, 0x634, 0x2B0, 4, 0x000, 0), /* MX53_PAD_PATA_DATA3__ESDHC3_DAT7 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA3, 0x634, 0x2B0, 5, 0x000, 0), /* MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA3, 0x634, 0x2B0, 6, 0x000, 0), /* MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA4, 0x638, 0x2B4, 0, 0x000, 0), /* MX53_PAD_PATA_DATA4__PATA_DATA_4 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA4, 0x638, 0x2B4, 1, 0x000, 0), /* MX53_PAD_PATA_DATA4__GPIO2_4 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA4, 0x638, 0x2B4, 3, 0x000, 0), /* MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA4, 0x638, 0x2B4, 4, 0x000, 0), /* MX53_PAD_PATA_DATA4__ESDHC4_DAT4 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA4, 0x638, 0x2B4, 5, 0x000, 0), /* MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA4, 0x638, 0x2B4, 6, 0x000, 0), /* MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA5, 0x63C, 0x2B8, 0, 0x000, 0), /* MX53_PAD_PATA_DATA5__PATA_DATA_5 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA5, 0x63C, 0x2B8, 1, 0x000, 0), /* MX53_PAD_PATA_DATA5__GPIO2_5 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA5, 0x63C, 0x2B8, 3, 0x000, 0), /* MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA5, 0x63C, 0x2B8, 4, 0x000, 0), /* MX53_PAD_PATA_DATA5__ESDHC4_DAT5 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA5, 0x63C, 0x2B8, 5, 0x000, 0), /* MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA5, 0x63C, 0x2B8, 6, 0x000, 0), /* MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA6, 0x640, 0x2BC, 0, 0x000, 0), /* MX53_PAD_PATA_DATA6__PATA_DATA_6 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA6, 0x640, 0x2BC, 1, 0x000, 0), /* MX53_PAD_PATA_DATA6__GPIO2_6 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA6, 0x640, 0x2BC, 3, 0x000, 0), /* MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA6, 0x640, 0x2BC, 4, 0x000, 0), /* MX53_PAD_PATA_DATA6__ESDHC4_DAT6 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA6, 0x640, 0x2BC, 5, 0x000, 0), /* MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA6, 0x640, 0x2BC, 6, 0x000, 0), /* MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA7, 0x644, 0x2C0, 0, 0x000, 0), /* MX53_PAD_PATA_DATA7__PATA_DATA_7 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA7, 0x644, 0x2C0, 1, 0x000, 0), /* MX53_PAD_PATA_DATA7__GPIO2_7 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA7, 0x644, 0x2C0, 3, 0x000, 0), /* MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA7, 0x644, 0x2C0, 4, 0x000, 0), /* MX53_PAD_PATA_DATA7__ESDHC4_DAT7 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA7, 0x644, 0x2C0, 5, 0x000, 0), /* MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA7, 0x644, 0x2C0, 6, 0x000, 0), /* MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 0, 0x000, 0), /* MX53_PAD_PATA_DATA8__PATA_DATA_8 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 1, 0x000, 0), /* MX53_PAD_PATA_DATA8__GPIO2_8 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 2, 0x000, 0), /* MX53_PAD_PATA_DATA8__ESDHC1_DAT4 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 3, 0x000, 0), /* MX53_PAD_PATA_DATA8__EMI_NANDF_D_8 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 4, 0x000, 0), /* MX53_PAD_PATA_DATA8__ESDHC3_DAT0 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 5, 0x000, 0), /* MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 6, 0x000, 0), /* MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 0, 0x000, 0), /* MX53_PAD_PATA_DATA9__PATA_DATA_9 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 1, 0x000, 0), /* MX53_PAD_PATA_DATA9__GPIO2_9 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 2, 0x000, 0), /* MX53_PAD_PATA_DATA9__ESDHC1_DAT5 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 3, 0x000, 0), /* MX53_PAD_PATA_DATA9__EMI_NANDF_D_9 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 4, 0x000, 0), /* MX53_PAD_PATA_DATA9__ESDHC3_DAT1 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 5, 0x000, 0), /* MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 6, 0x000, 0), /* MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 0, 0x000, 0), /* MX53_PAD_PATA_DATA10__PATA_DATA_10 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 1, 0x000, 0), /* MX53_PAD_PATA_DATA10__GPIO2_10 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 2, 0x000, 0), /* MX53_PAD_PATA_DATA10__ESDHC1_DAT6 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 3, 0x000, 0), /* MX53_PAD_PATA_DATA10__EMI_NANDF_D_10 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 4, 0x000, 0), /* MX53_PAD_PATA_DATA10__ESDHC3_DAT2 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 5, 0x000, 0), /* MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 6, 0x000, 0), /* MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 0, 0x000, 0), /* MX53_PAD_PATA_DATA11__PATA_DATA_11 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 1, 0x000, 0), /* MX53_PAD_PATA_DATA11__GPIO2_11 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 2, 0x000, 0), /* MX53_PAD_PATA_DATA11__ESDHC1_DAT7 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 3, 0x000, 0), /* MX53_PAD_PATA_DATA11__EMI_NANDF_D_11 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 4, 0x000, 0), /* MX53_PAD_PATA_DATA11__ESDHC3_DAT3 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 5, 0x000, 0), /* MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 6, 0x000, 0), /* MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 0, 0x000, 0), /* MX53_PAD_PATA_DATA12__PATA_DATA_12 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 1, 0x000, 0), /* MX53_PAD_PATA_DATA12__GPIO2_12 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 2, 0x000, 0), /* MX53_PAD_PATA_DATA12__ESDHC2_DAT4 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 3, 0x000, 0), /* MX53_PAD_PATA_DATA12__EMI_NANDF_D_12 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 4, 0x000, 0), /* MX53_PAD_PATA_DATA12__ESDHC4_DAT0 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 5, 0x000, 0), /* MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 6, 0x000, 0), /* MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 0, 0x000, 0), /* MX53_PAD_PATA_DATA13__PATA_DATA_13 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 1, 0x000, 0), /* MX53_PAD_PATA_DATA13__GPIO2_13 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 2, 0x000, 0), /* MX53_PAD_PATA_DATA13__ESDHC2_DAT5 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 3, 0x000, 0), /* MX53_PAD_PATA_DATA13__EMI_NANDF_D_13 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 4, 0x000, 0), /* MX53_PAD_PATA_DATA13__ESDHC4_DAT1 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 5, 0x000, 0), /* MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 6, 0x000, 0), /* MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 0, 0x000, 0), /* MX53_PAD_PATA_DATA14__PATA_DATA_14 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 1, 0x000, 0), /* MX53_PAD_PATA_DATA14__GPIO2_14 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 2, 0x000, 0), /* MX53_PAD_PATA_DATA14__ESDHC2_DAT6 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 3, 0x000, 0), /* MX53_PAD_PATA_DATA14__EMI_NANDF_D_14 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 4, 0x000, 0), /* MX53_PAD_PATA_DATA14__ESDHC4_DAT2 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 5, 0x000, 0), /* MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 6, 0x000, 0), /* MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 0, 0x000, 0), /* MX53_PAD_PATA_DATA15__PATA_DATA_15 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 1, 0x000, 0), /* MX53_PAD_PATA_DATA15__GPIO2_15 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 2, 0x000, 0), /* MX53_PAD_PATA_DATA15__ESDHC2_DAT7 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 3, 0x000, 0), /* MX53_PAD_PATA_DATA15__EMI_NANDF_D_15 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 4, 0x000, 0), /* MX53_PAD_PATA_DATA15__ESDHC4_DAT3 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 5, 0x000, 0), /* MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15 */
+ IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 6, 0x000, 0), /* MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA0, 0x66C, 0x2E4, 0, 0x000, 0), /* MX53_PAD_SD1_DATA0__ESDHC1_DAT0 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA0, 0x66C, 0x2E4, 1, 0x000, 0), /* MX53_PAD_SD1_DATA0__GPIO1_16 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA0, 0x66C, 0x2E4, 3, 0x000, 0), /* MX53_PAD_SD1_DATA0__GPT_CAPIN1 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA0, 0x66C, 0x2E4, 5, 0x784, 2), /* MX53_PAD_SD1_DATA0__CSPI_MISO */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA0, 0x66C, 0x2E4, 7, 0x778, 0), /* MX53_PAD_SD1_DATA0__CCM_PLL3_BYP */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA1, 0x670, 0x2E8, 0, 0x000, 0), /* MX53_PAD_SD1_DATA1__ESDHC1_DAT1 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA1, 0x670, 0x2E8, 1, 0x000, 0), /* MX53_PAD_SD1_DATA1__GPIO1_17 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA1, 0x670, 0x2E8, 3, 0x000, 0), /* MX53_PAD_SD1_DATA1__GPT_CAPIN2 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA1, 0x670, 0x2E8, 5, 0x78C, 3), /* MX53_PAD_SD1_DATA1__CSPI_SS0 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA1, 0x670, 0x2E8, 7, 0x77C, 1), /* MX53_PAD_SD1_DATA1__CCM_PLL4_BYP */
+ IMX_PIN_REG(MX53_PAD_SD1_CMD, 0x674, 0x2EC, 0, 0x000, 0), /* MX53_PAD_SD1_CMD__ESDHC1_CMD */
+ IMX_PIN_REG(MX53_PAD_SD1_CMD, 0x674, 0x2EC, 1, 0x000, 0), /* MX53_PAD_SD1_CMD__GPIO1_18 */
+ IMX_PIN_REG(MX53_PAD_SD1_CMD, 0x674, 0x2EC, 3, 0x000, 0), /* MX53_PAD_SD1_CMD__GPT_CMPOUT1 */
+ IMX_PIN_REG(MX53_PAD_SD1_CMD, 0x674, 0x2EC, 5, 0x788, 2), /* MX53_PAD_SD1_CMD__CSPI_MOSI */
+ IMX_PIN_REG(MX53_PAD_SD1_CMD, 0x674, 0x2EC, 7, 0x770, 0), /* MX53_PAD_SD1_CMD__CCM_PLL1_BYP */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 0, 0x000, 0), /* MX53_PAD_SD1_DATA2__ESDHC1_DAT2 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 1, 0x000, 0), /* MX53_PAD_SD1_DATA2__GPIO1_19 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 2, 0x000, 0), /* MX53_PAD_SD1_DATA2__GPT_CMPOUT2 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 3, 0x000, 0), /* MX53_PAD_SD1_DATA2__PWM2_PWMO */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 4, 0x000, 0), /* MX53_PAD_SD1_DATA2__WDOG1_WDOG_B */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 5, 0x790, 2), /* MX53_PAD_SD1_DATA2__CSPI_SS1 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 6, 0x000, 0), /* MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 7, 0x774, 0), /* MX53_PAD_SD1_DATA2__CCM_PLL2_BYP */
+ IMX_PIN_REG(MX53_PAD_SD1_CLK, 0x67C, 0x2F4, 0, 0x000, 0), /* MX53_PAD_SD1_CLK__ESDHC1_CLK */
+ IMX_PIN_REG(MX53_PAD_SD1_CLK, 0x67C, 0x2F4, 1, 0x000, 0), /* MX53_PAD_SD1_CLK__GPIO1_20 */
+ IMX_PIN_REG(MX53_PAD_SD1_CLK, 0x67C, 0x2F4, 2, 0x000, 0), /* MX53_PAD_SD1_CLK__OSC32k_32K_OUT */
+ IMX_PIN_REG(MX53_PAD_SD1_CLK, 0x67C, 0x2F4, 3, 0x000, 0), /* MX53_PAD_SD1_CLK__GPT_CLKIN */
+ IMX_PIN_REG(MX53_PAD_SD1_CLK, 0x67C, 0x2F4, 5, 0x780, 2), /* MX53_PAD_SD1_CLK__CSPI_SCLK */
+ IMX_PIN_REG(MX53_PAD_SD1_CLK, 0x67C, 0x2F4, 7, 0x000, 0), /* MX53_PAD_SD1_CLK__SATA_PHY_DTB_0 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 0, 0x000, 0), /* MX53_PAD_SD1_DATA3__ESDHC1_DAT3 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 1, 0x000, 0), /* MX53_PAD_SD1_DATA3__GPIO1_21 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 2, 0x000, 0), /* MX53_PAD_SD1_DATA3__GPT_CMPOUT3 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 3, 0x000, 0), /* MX53_PAD_SD1_DATA3__PWM1_PWMO */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 4, 0x000, 0), /* MX53_PAD_SD1_DATA3__WDOG2_WDOG_B */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 5, 0x794, 2), /* MX53_PAD_SD1_DATA3__CSPI_SS2 */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 6, 0x000, 0), /* MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB */
+ IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 7, 0x000, 0), /* MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1 */
+ IMX_PIN_REG(MX53_PAD_SD2_CLK, 0x688, 0x2FC, 0, 0x000, 0), /* MX53_PAD_SD2_CLK__ESDHC2_CLK */
+ IMX_PIN_REG(MX53_PAD_SD2_CLK, 0x688, 0x2FC, 1, 0x000, 0), /* MX53_PAD_SD2_CLK__GPIO1_10 */
+ IMX_PIN_REG(MX53_PAD_SD2_CLK, 0x688, 0x2FC, 2, 0x840, 2), /* MX53_PAD_SD2_CLK__KPP_COL_5 */
+ IMX_PIN_REG(MX53_PAD_SD2_CLK, 0x688, 0x2FC, 3, 0x73C, 1), /* MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS */
+ IMX_PIN_REG(MX53_PAD_SD2_CLK, 0x688, 0x2FC, 5, 0x780, 3), /* MX53_PAD_SD2_CLK__CSPI_SCLK */
+ IMX_PIN_REG(MX53_PAD_SD2_CLK, 0x688, 0x2FC, 7, 0x000, 0), /* MX53_PAD_SD2_CLK__SCC_RANDOM_V */
+ IMX_PIN_REG(MX53_PAD_SD2_CMD, 0x68C, 0x300, 0, 0x000, 0), /* MX53_PAD_SD2_CMD__ESDHC2_CMD */
+ IMX_PIN_REG(MX53_PAD_SD2_CMD, 0x68C, 0x300, 1, 0x000, 0), /* MX53_PAD_SD2_CMD__GPIO1_11 */
+ IMX_PIN_REG(MX53_PAD_SD2_CMD, 0x68C, 0x300, 2, 0x84C, 1), /* MX53_PAD_SD2_CMD__KPP_ROW_5 */
+ IMX_PIN_REG(MX53_PAD_SD2_CMD, 0x68C, 0x300, 3, 0x738, 1), /* MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC */
+ IMX_PIN_REG(MX53_PAD_SD2_CMD, 0x68C, 0x300, 5, 0x788, 3), /* MX53_PAD_SD2_CMD__CSPI_MOSI */
+ IMX_PIN_REG(MX53_PAD_SD2_CMD, 0x68C, 0x300, 7, 0x000, 0), /* MX53_PAD_SD2_CMD__SCC_RANDOM */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA3, 0x690, 0x304, 0, 0x000, 0), /* MX53_PAD_SD2_DATA3__ESDHC2_DAT3 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA3, 0x690, 0x304, 1, 0x000, 0), /* MX53_PAD_SD2_DATA3__GPIO1_12 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA3, 0x690, 0x304, 2, 0x844, 1), /* MX53_PAD_SD2_DATA3__KPP_COL_6 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA3, 0x690, 0x304, 3, 0x740, 1), /* MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA3, 0x690, 0x304, 5, 0x794, 3), /* MX53_PAD_SD2_DATA3__CSPI_SS2 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA3, 0x690, 0x304, 7, 0x000, 0), /* MX53_PAD_SD2_DATA3__SJC_DONE */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA2, 0x694, 0x308, 0, 0x000, 0), /* MX53_PAD_SD2_DATA2__ESDHC2_DAT2 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA2, 0x694, 0x308, 1, 0x000, 0), /* MX53_PAD_SD2_DATA2__GPIO1_13 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA2, 0x694, 0x308, 2, 0x850, 1), /* MX53_PAD_SD2_DATA2__KPP_ROW_6 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA2, 0x694, 0x308, 3, 0x734, 1), /* MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA2, 0x694, 0x308, 5, 0x790, 3), /* MX53_PAD_SD2_DATA2__CSPI_SS1 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA2, 0x694, 0x308, 7, 0x000, 0), /* MX53_PAD_SD2_DATA2__SJC_FAIL */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA1, 0x698, 0x30C, 0, 0x000, 0), /* MX53_PAD_SD2_DATA1__ESDHC2_DAT1 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA1, 0x698, 0x30C, 1, 0x000, 0), /* MX53_PAD_SD2_DATA1__GPIO1_14 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA1, 0x698, 0x30C, 2, 0x848, 1), /* MX53_PAD_SD2_DATA1__KPP_COL_7 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA1, 0x698, 0x30C, 3, 0x744, 0), /* MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA1, 0x698, 0x30C, 5, 0x78C, 4), /* MX53_PAD_SD2_DATA1__CSPI_SS0 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA1, 0x698, 0x30C, 7, 0x000, 0), /* MX53_PAD_SD2_DATA1__RTIC_SEC_VIO */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA0, 0x69C, 0x310, 0, 0x000, 0), /* MX53_PAD_SD2_DATA0__ESDHC2_DAT0 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA0, 0x69C, 0x310, 1, 0x000, 0), /* MX53_PAD_SD2_DATA0__GPIO1_15 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA0, 0x69C, 0x310, 2, 0x854, 1), /* MX53_PAD_SD2_DATA0__KPP_ROW_7 */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA0, 0x69C, 0x310, 3, 0x730, 1), /* MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA0, 0x69C, 0x310, 5, 0x784, 3), /* MX53_PAD_SD2_DATA0__CSPI_MISO */
+ IMX_PIN_REG(MX53_PAD_SD2_DATA0, 0x69C, 0x310, 7, 0x000, 0), /* MX53_PAD_SD2_DATA0__RTIC_DONE_INT */
+ IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 0, 0x000, 0), /* MX53_PAD_GPIO_0__CCM_CLKO */
+ IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 1, 0x000, 0), /* MX53_PAD_GPIO_0__GPIO1_0 */
+ IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 2, 0x840, 3), /* MX53_PAD_GPIO_0__KPP_COL_5 */
+ IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 3, 0x000, 0), /* MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK */
+ IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 4, 0x000, 0), /* MX53_PAD_GPIO_0__EPIT1_EPITO */
+ IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 5, 0x000, 0), /* MX53_PAD_GPIO_0__SRTC_ALARM_DEB */
+ IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 6, 0x000, 0), /* MX53_PAD_GPIO_0__USBOH3_USBH1_PWR */
+ IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 7, 0x000, 0), /* MX53_PAD_GPIO_0__CSU_TD */
+ IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 0, 0x7DC, 1), /* MX53_PAD_GPIO_1__ESAI1_SCKR */
+ IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 1, 0x000, 0), /* MX53_PAD_GPIO_1__GPIO1_1 */
+ IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 2, 0x84C, 2), /* MX53_PAD_GPIO_1__KPP_ROW_5 */
+ IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 3, 0x000, 0), /* MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK */
+ IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 4, 0x000, 0), /* MX53_PAD_GPIO_1__PWM2_PWMO */
+ IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 5, 0x000, 0), /* MX53_PAD_GPIO_1__WDOG2_WDOG_B */
+ IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 6, 0x000, 0), /* MX53_PAD_GPIO_1__ESDHC1_CD */
+ IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 7, 0x000, 0), /* MX53_PAD_GPIO_1__SRC_TESTER_ACK */
+ IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 0, 0x7CC, 1), /* MX53_PAD_GPIO_9__ESAI1_FSR */
+ IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 1, 0x000, 0), /* MX53_PAD_GPIO_9__GPIO1_9 */
+ IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 2, 0x844, 2), /* MX53_PAD_GPIO_9__KPP_COL_6 */
+ IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 3, 0x000, 0), /* MX53_PAD_GPIO_9__CCM_REF_EN_B */
+ IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 4, 0x000, 0), /* MX53_PAD_GPIO_9__PWM1_PWMO */
+ IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 5, 0x000, 0), /* MX53_PAD_GPIO_9__WDOG1_WDOG_B */
+ IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 6, 0x7FC, 1), /* MX53_PAD_GPIO_9__ESDHC1_WP */
+ IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 7, 0x000, 0), /* MX53_PAD_GPIO_9__SCC_FAIL_STATE */
+ IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 0, 0x7D4, 1), /* MX53_PAD_GPIO_3__ESAI1_HCKR */
+ IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 1, 0x000, 0), /* MX53_PAD_GPIO_3__GPIO1_3 */
+ IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 2, 0x824, 1), /* MX53_PAD_GPIO_3__I2C3_SCL */
+ IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 3, 0x000, 0), /* MX53_PAD_GPIO_3__DPLLIP1_TOG_EN */
+ IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 4, 0x000, 0), /* MX53_PAD_GPIO_3__CCM_CLKO2 */
+ IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 5, 0x000, 0), /* MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0 */
+ IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 6, 0x8A0, 1), /* MX53_PAD_GPIO_3__USBOH3_USBH1_OC */
+ IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 7, 0x858, 2), /* MX53_PAD_GPIO_3__MLB_MLBCLK */
+ IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 0, 0x7E0, 1), /* MX53_PAD_GPIO_6__ESAI1_SCKT */
+ IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 1, 0x000, 0), /* MX53_PAD_GPIO_6__GPIO1_6 */
+ IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 2, 0x828, 1), /* MX53_PAD_GPIO_6__I2C3_SDA */
+ IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 3, 0x000, 0), /* MX53_PAD_GPIO_6__CCM_CCM_OUT_0 */
+ IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 4, 0x000, 0), /* MX53_PAD_GPIO_6__CSU_CSU_INT_DEB */
+ IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 5, 0x000, 0), /* MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 */
+ IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 6, 0x000, 0), /* MX53_PAD_GPIO_6__ESDHC2_LCTL */
+ IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 7, 0x860, 2), /* MX53_PAD_GPIO_6__MLB_MLBSIG */
+ IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 0, 0x7D0, 1), /* MX53_PAD_GPIO_2__ESAI1_FST */
+ IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 1, 0x000, 0), /* MX53_PAD_GPIO_2__GPIO1_2 */
+ IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 2, 0x850, 2), /* MX53_PAD_GPIO_2__KPP_ROW_6 */
+ IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 3, 0x000, 0), /* MX53_PAD_GPIO_2__CCM_CCM_OUT_1 */
+ IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 4, 0x000, 0), /* MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 */
+ IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 5, 0x000, 0), /* MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2 */
+ IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 6, 0x000, 0), /* MX53_PAD_GPIO_2__ESDHC2_WP */
+ IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 7, 0x85C, 2), /* MX53_PAD_GPIO_2__MLB_MLBDAT */
+ IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 0, 0x7D8, 1), /* MX53_PAD_GPIO_4__ESAI1_HCKT */
+ IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 1, 0x000, 0), /* MX53_PAD_GPIO_4__GPIO1_4 */
+ IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 2, 0x848, 2), /* MX53_PAD_GPIO_4__KPP_COL_7 */
+ IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 3, 0x000, 0), /* MX53_PAD_GPIO_4__CCM_CCM_OUT_2 */
+ IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 4, 0x000, 0), /* MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 */
+ IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 5, 0x000, 0), /* MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3 */
+ IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 6, 0x000, 0), /* MX53_PAD_GPIO_4__ESDHC2_CD */
+ IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 7, 0x000, 0), /* MX53_PAD_GPIO_4__SCC_SEC_STATE */
+ IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 0, 0x7EC, 1), /* MX53_PAD_GPIO_5__ESAI1_TX2_RX3 */
+ IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 1, 0x000, 0), /* MX53_PAD_GPIO_5__GPIO1_5 */
+ IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 2, 0x854, 2), /* MX53_PAD_GPIO_5__KPP_ROW_7 */
+ IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 3, 0x000, 0), /* MX53_PAD_GPIO_5__CCM_CLKO */
+ IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 4, 0x000, 0), /* MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 */
+ IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 5, 0x000, 0), /* MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4 */
+ IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 6, 0x824, 2), /* MX53_PAD_GPIO_5__I2C3_SCL */
+ IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 7, 0x770, 1), /* MX53_PAD_GPIO_5__CCM_PLL1_BYP */
+ IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 0, 0x7F4, 1), /* MX53_PAD_GPIO_7__ESAI1_TX4_RX1 */
+ IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 1, 0x000, 0), /* MX53_PAD_GPIO_7__GPIO1_7 */
+ IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 2, 0x000, 0), /* MX53_PAD_GPIO_7__EPIT1_EPITO */
+ IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 3, 0x000, 0), /* MX53_PAD_GPIO_7__CAN1_TXCAN */
+ IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 4, 0x000, 0), /* MX53_PAD_GPIO_7__UART2_TXD_MUX */
+ IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 5, 0x80C, 1), /* MX53_PAD_GPIO_7__FIRI_RXD */
+ IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 6, 0x000, 0), /* MX53_PAD_GPIO_7__SPDIF_PLOCK */
+ IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 7, 0x774, 1), /* MX53_PAD_GPIO_7__CCM_PLL2_BYP */
+ IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 0, 0x7F8, 1), /* MX53_PAD_GPIO_8__ESAI1_TX5_RX0 */
+ IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 1, 0x000, 0), /* MX53_PAD_GPIO_8__GPIO1_8 */
+ IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 2, 0x000, 0), /* MX53_PAD_GPIO_8__EPIT2_EPITO */
+ IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 3, 0x760, 3), /* MX53_PAD_GPIO_8__CAN1_RXCAN */
+ IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 4, 0x880, 5), /* MX53_PAD_GPIO_8__UART2_RXD_MUX */
+ IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 5, 0x000, 0), /* MX53_PAD_GPIO_8__FIRI_TXD */
+ IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 6, 0x000, 0), /* MX53_PAD_GPIO_8__SPDIF_SRCLK */
+ IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 7, 0x778, 1), /* MX53_PAD_GPIO_8__CCM_PLL3_BYP */
+ IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 0, 0x7F0, 1), /* MX53_PAD_GPIO_16__ESAI1_TX3_RX2 */
+ IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 1, 0x000, 0), /* MX53_PAD_GPIO_16__GPIO7_11 */
+ IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 2, 0x000, 0), /* MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT */
+ IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 4, 0x000, 0), /* MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1 */
+ IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 5, 0x870, 1), /* MX53_PAD_GPIO_16__SPDIF_IN1 */
+ IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 6, 0x828, 2), /* MX53_PAD_GPIO_16__I2C3_SDA */
+ IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 7, 0x000, 0), /* MX53_PAD_GPIO_16__SJC_DE_B */
+ IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 0, 0x7E4, 1), /* MX53_PAD_GPIO_17__ESAI1_TX0 */
+ IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 1, 0x000, 0), /* MX53_PAD_GPIO_17__GPIO7_12 */
+ IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 2, 0x868, 1), /* MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0 */
+ IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 3, 0x810, 1), /* MX53_PAD_GPIO_17__GPC_PMIC_RDY */
+ IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 4, 0x000, 0), /* MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG */
+ IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 5, 0x000, 0), /* MX53_PAD_GPIO_17__SPDIF_OUT1 */
+ IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 6, 0x000, 0), /* MX53_PAD_GPIO_17__IPU_SNOOP2 */
+ IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 7, 0x000, 0), /* MX53_PAD_GPIO_17__SJC_JTAG_ACT */
+ IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 0, 0x7E8, 1), /* MX53_PAD_GPIO_18__ESAI1_TX1 */
+ IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 1, 0x000, 0), /* MX53_PAD_GPIO_18__GPIO7_13 */
+ IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 2, 0x86C, 1), /* MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1 */
+ IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 3, 0x864, 1), /* MX53_PAD_GPIO_18__OWIRE_LINE */
+ IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 4, 0x000, 0), /* MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG */
+ IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 5, 0x768, 1), /* MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK */
+ IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 6, 0x000, 0), /* MX53_PAD_GPIO_18__ESDHC1_LCTL */
+ IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 7, 0x000, 0), /* MX53_PAD_GPIO_18__SRC_SYSTEM_RST */
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx53_pinctrl_pads[] = {
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_19),
+ IMX_PINCTRL_PIN(MX53_PAD_KEY_COL0),
+ IMX_PINCTRL_PIN(MX53_PAD_KEY_ROW0),
+ IMX_PINCTRL_PIN(MX53_PAD_KEY_COL1),
+ IMX_PINCTRL_PIN(MX53_PAD_KEY_ROW1),
+ IMX_PINCTRL_PIN(MX53_PAD_KEY_COL2),
+ IMX_PINCTRL_PIN(MX53_PAD_KEY_ROW2),
+ IMX_PINCTRL_PIN(MX53_PAD_KEY_COL3),
+ IMX_PINCTRL_PIN(MX53_PAD_KEY_ROW3),
+ IMX_PINCTRL_PIN(MX53_PAD_KEY_COL4),
+ IMX_PINCTRL_PIN(MX53_PAD_KEY_ROW4),
+ IMX_PINCTRL_PIN(MX53_PAD_DI0_DISP_CLK),
+ IMX_PINCTRL_PIN(MX53_PAD_DI0_PIN15),
+ IMX_PINCTRL_PIN(MX53_PAD_DI0_PIN2),
+ IMX_PINCTRL_PIN(MX53_PAD_DI0_PIN3),
+ IMX_PINCTRL_PIN(MX53_PAD_DI0_PIN4),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT0),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT1),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT2),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT3),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT4),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT5),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT6),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT7),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT8),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT9),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT10),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT11),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT12),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT13),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT14),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT15),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT16),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT17),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT18),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT19),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT20),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT21),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT22),
+ IMX_PINCTRL_PIN(MX53_PAD_DISP0_DAT23),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_PIXCLK),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_MCLK),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DATA_EN),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_VSYNC),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT4),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT5),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT6),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT7),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT8),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT9),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT10),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT11),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT12),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT13),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT14),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT15),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT16),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT17),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT18),
+ IMX_PINCTRL_PIN(MX53_PAD_CSI0_DAT19),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_A25),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_EB2),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D16),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D17),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D18),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D19),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D20),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D21),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D22),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D23),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_EB3),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D24),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D25),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D26),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D27),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D28),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D29),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D30),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_D31),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_A24),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_A23),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_A22),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_A21),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_A20),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_A19),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_A18),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_A17),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_A16),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_CS0),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_CS1),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_OE),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_RW),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_LBA),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_EB0),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_EB1),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA0),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA1),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA2),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA3),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA4),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA5),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA6),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA7),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA8),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA9),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA10),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA11),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA12),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA13),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA14),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_DA15),
+ IMX_PINCTRL_PIN(MX53_PAD_NANDF_WE_B),
+ IMX_PINCTRL_PIN(MX53_PAD_NANDF_RE_B),
+ IMX_PINCTRL_PIN(MX53_PAD_EIM_WAIT),
+ IMX_PINCTRL_PIN(MX53_PAD_LVDS1_TX3_P),
+ IMX_PINCTRL_PIN(MX53_PAD_LVDS1_TX2_P),
+ IMX_PINCTRL_PIN(MX53_PAD_LVDS1_CLK_P),
+ IMX_PINCTRL_PIN(MX53_PAD_LVDS1_TX1_P),
+ IMX_PINCTRL_PIN(MX53_PAD_LVDS1_TX0_P),
+ IMX_PINCTRL_PIN(MX53_PAD_LVDS0_TX3_P),
+ IMX_PINCTRL_PIN(MX53_PAD_LVDS0_CLK_P),
+ IMX_PINCTRL_PIN(MX53_PAD_LVDS0_TX2_P),
+ IMX_PINCTRL_PIN(MX53_PAD_LVDS0_TX1_P),
+ IMX_PINCTRL_PIN(MX53_PAD_LVDS0_TX0_P),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_10),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_11),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_12),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_13),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_14),
+ IMX_PINCTRL_PIN(MX53_PAD_NANDF_CLE),
+ IMX_PINCTRL_PIN(MX53_PAD_NANDF_ALE),
+ IMX_PINCTRL_PIN(MX53_PAD_NANDF_WP_B),
+ IMX_PINCTRL_PIN(MX53_PAD_NANDF_RB0),
+ IMX_PINCTRL_PIN(MX53_PAD_NANDF_CS0),
+ IMX_PINCTRL_PIN(MX53_PAD_NANDF_CS1),
+ IMX_PINCTRL_PIN(MX53_PAD_NANDF_CS2),
+ IMX_PINCTRL_PIN(MX53_PAD_NANDF_CS3),
+ IMX_PINCTRL_PIN(MX53_PAD_FEC_MDIO),
+ IMX_PINCTRL_PIN(MX53_PAD_FEC_REF_CLK),
+ IMX_PINCTRL_PIN(MX53_PAD_FEC_RX_ER),
+ IMX_PINCTRL_PIN(MX53_PAD_FEC_CRS_DV),
+ IMX_PINCTRL_PIN(MX53_PAD_FEC_RXD1),
+ IMX_PINCTRL_PIN(MX53_PAD_FEC_RXD0),
+ IMX_PINCTRL_PIN(MX53_PAD_FEC_TX_EN),
+ IMX_PINCTRL_PIN(MX53_PAD_FEC_TXD1),
+ IMX_PINCTRL_PIN(MX53_PAD_FEC_TXD0),
+ IMX_PINCTRL_PIN(MX53_PAD_FEC_MDC),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DIOW),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DMACK),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DMARQ),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_BUFFER_EN),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_INTRQ),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DIOR),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_RESET_B),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_IORDY),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DA_0),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DA_1),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DA_2),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_CS_0),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_CS_1),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA0),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA1),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA2),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA3),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA4),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA5),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA6),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA7),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA8),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA9),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA10),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA11),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA12),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA13),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA14),
+ IMX_PINCTRL_PIN(MX53_PAD_PATA_DATA15),
+ IMX_PINCTRL_PIN(MX53_PAD_SD1_DATA0),
+ IMX_PINCTRL_PIN(MX53_PAD_SD1_DATA1),
+ IMX_PINCTRL_PIN(MX53_PAD_SD1_CMD),
+ IMX_PINCTRL_PIN(MX53_PAD_SD1_DATA2),
+ IMX_PINCTRL_PIN(MX53_PAD_SD1_CLK),
+ IMX_PINCTRL_PIN(MX53_PAD_SD1_DATA3),
+ IMX_PINCTRL_PIN(MX53_PAD_SD2_CLK),
+ IMX_PINCTRL_PIN(MX53_PAD_SD2_CMD),
+ IMX_PINCTRL_PIN(MX53_PAD_SD2_DATA3),
+ IMX_PINCTRL_PIN(MX53_PAD_SD2_DATA2),
+ IMX_PINCTRL_PIN(MX53_PAD_SD2_DATA1),
+ IMX_PINCTRL_PIN(MX53_PAD_SD2_DATA0),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_0),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_1),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_9),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_3),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_6),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_2),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_4),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_5),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_7),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_8),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_16),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_17),
+ IMX_PINCTRL_PIN(MX53_PAD_GPIO_18),
+};
+
+static struct imx_pinctrl_soc_info imx53_pinctrl_info = {
+ .pins = imx53_pinctrl_pads,
+ .npins = ARRAY_SIZE(imx53_pinctrl_pads),
+ .pin_regs = imx53_pin_regs,
+ .npin_regs = ARRAY_SIZE(imx53_pin_regs),
+};
+
+static struct of_device_id imx53_pinctrl_of_match[] __devinitdata = {
+ { .compatible = "fsl,imx53-iomuxc", },
+ { /* sentinel */ }
+};
+
+static int __devinit imx53_pinctrl_probe(struct platform_device *pdev)
+{
+ return imx_pinctrl_probe(pdev, &imx53_pinctrl_info);
+}
+
+static struct platform_driver imx53_pinctrl_driver = {
+ .driver = {
+ .name = "imx53-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(imx53_pinctrl_of_match),
+ },
+ .probe = imx53_pinctrl_probe,
+ .remove = __devexit_p(imx_pinctrl_remove),
+};
+
+static int __init imx53_pinctrl_init(void)
+{
+ return platform_driver_register(&imx53_pinctrl_driver);
+}
+arch_initcall(imx53_pinctrl_init);
+
+static void __exit imx53_pinctrl_exit(void)
+{
+ platform_driver_unregister(&imx53_pinctrl_driver);
+}
+module_exit(imx53_pinctrl_exit);
+MODULE_AUTHOR("Dong Aisheng <dong.aisheng@linaro.org>");
+MODULE_DESCRIPTION("Freescale IMX53 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-imx6q.c b/drivers/pinctrl/pinctrl-imx6q.c
new file mode 100644
index 000000000000..7737d4d71a3c
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx6q.c
@@ -0,0 +1,2331 @@
+/*
+ * imx6q pinctrl driver based on imx pinmux core
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro, Inc.
+ *
+ * Author: Dong Aisheng <dong.aisheng@linaro.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.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-imx.h"
+
+enum imx6q_pads {
+ MX6Q_PAD_SD2_DAT1 = 0,
+ MX6Q_PAD_SD2_DAT2 = 1,
+ MX6Q_PAD_SD2_DAT0 = 2,
+ MX6Q_PAD_RGMII_TXC = 3,
+ MX6Q_PAD_RGMII_TD0 = 4,
+ MX6Q_PAD_RGMII_TD1 = 5,
+ MX6Q_PAD_RGMII_TD2 = 6,
+ MX6Q_PAD_RGMII_TD3 = 7,
+ MX6Q_PAD_RGMII_RX_CTL = 8,
+ MX6Q_PAD_RGMII_RD0 = 9,
+ MX6Q_PAD_RGMII_TX_CTL = 10,
+ MX6Q_PAD_RGMII_RD1 = 11,
+ MX6Q_PAD_RGMII_RD2 = 12,
+ MX6Q_PAD_RGMII_RD3 = 13,
+ MX6Q_PAD_RGMII_RXC = 14,
+ MX6Q_PAD_EIM_A25 = 15,
+ MX6Q_PAD_EIM_EB2 = 16,
+ MX6Q_PAD_EIM_D16 = 17,
+ MX6Q_PAD_EIM_D17 = 18,
+ MX6Q_PAD_EIM_D18 = 19,
+ MX6Q_PAD_EIM_D19 = 20,
+ MX6Q_PAD_EIM_D20 = 21,
+ MX6Q_PAD_EIM_D21 = 22,
+ MX6Q_PAD_EIM_D22 = 23,
+ MX6Q_PAD_EIM_D23 = 24,
+ MX6Q_PAD_EIM_EB3 = 25,
+ MX6Q_PAD_EIM_D24 = 26,
+ MX6Q_PAD_EIM_D25 = 27,
+ MX6Q_PAD_EIM_D26 = 28,
+ MX6Q_PAD_EIM_D27 = 29,
+ MX6Q_PAD_EIM_D28 = 30,
+ MX6Q_PAD_EIM_D29 = 31,
+ MX6Q_PAD_EIM_D30 = 32,
+ MX6Q_PAD_EIM_D31 = 33,
+ MX6Q_PAD_EIM_A24 = 34,
+ MX6Q_PAD_EIM_A23 = 35,
+ MX6Q_PAD_EIM_A22 = 36,
+ MX6Q_PAD_EIM_A21 = 37,
+ MX6Q_PAD_EIM_A20 = 38,
+ MX6Q_PAD_EIM_A19 = 39,
+ MX6Q_PAD_EIM_A18 = 40,
+ MX6Q_PAD_EIM_A17 = 41,
+ MX6Q_PAD_EIM_A16 = 42,
+ MX6Q_PAD_EIM_CS0 = 43,
+ MX6Q_PAD_EIM_CS1 = 44,
+ MX6Q_PAD_EIM_OE = 45,
+ MX6Q_PAD_EIM_RW = 46,
+ MX6Q_PAD_EIM_LBA = 47,
+ MX6Q_PAD_EIM_EB0 = 48,
+ MX6Q_PAD_EIM_EB1 = 49,
+ MX6Q_PAD_EIM_DA0 = 50,
+ MX6Q_PAD_EIM_DA1 = 51,
+ MX6Q_PAD_EIM_DA2 = 52,
+ MX6Q_PAD_EIM_DA3 = 53,
+ MX6Q_PAD_EIM_DA4 = 54,
+ MX6Q_PAD_EIM_DA5 = 55,
+ MX6Q_PAD_EIM_DA6 = 56,
+ MX6Q_PAD_EIM_DA7 = 57,
+ MX6Q_PAD_EIM_DA8 = 58,
+ MX6Q_PAD_EIM_DA9 = 59,
+ MX6Q_PAD_EIM_DA10 = 60,
+ MX6Q_PAD_EIM_DA11 = 61,
+ MX6Q_PAD_EIM_DA12 = 62,
+ MX6Q_PAD_EIM_DA13 = 63,
+ MX6Q_PAD_EIM_DA14 = 64,
+ MX6Q_PAD_EIM_DA15 = 65,
+ MX6Q_PAD_EIM_WAIT = 66,
+ MX6Q_PAD_EIM_BCLK = 67,
+ MX6Q_PAD_DI0_DISP_CLK = 68,
+ MX6Q_PAD_DI0_PIN15 = 69,
+ MX6Q_PAD_DI0_PIN2 = 70,
+ MX6Q_PAD_DI0_PIN3 = 71,
+ MX6Q_PAD_DI0_PIN4 = 72,
+ MX6Q_PAD_DISP0_DAT0 = 73,
+ MX6Q_PAD_DISP0_DAT1 = 74,
+ MX6Q_PAD_DISP0_DAT2 = 75,
+ MX6Q_PAD_DISP0_DAT3 = 76,
+ MX6Q_PAD_DISP0_DAT4 = 77,
+ MX6Q_PAD_DISP0_DAT5 = 78,
+ MX6Q_PAD_DISP0_DAT6 = 79,
+ MX6Q_PAD_DISP0_DAT7 = 80,
+ MX6Q_PAD_DISP0_DAT8 = 81,
+ MX6Q_PAD_DISP0_DAT9 = 82,
+ MX6Q_PAD_DISP0_DAT10 = 83,
+ MX6Q_PAD_DISP0_DAT11 = 84,
+ MX6Q_PAD_DISP0_DAT12 = 85,
+ MX6Q_PAD_DISP0_DAT13 = 86,
+ MX6Q_PAD_DISP0_DAT14 = 87,
+ MX6Q_PAD_DISP0_DAT15 = 88,
+ MX6Q_PAD_DISP0_DAT16 = 89,
+ MX6Q_PAD_DISP0_DAT17 = 90,
+ MX6Q_PAD_DISP0_DAT18 = 91,
+ MX6Q_PAD_DISP0_DAT19 = 92,
+ MX6Q_PAD_DISP0_DAT20 = 93,
+ MX6Q_PAD_DISP0_DAT21 = 94,
+ MX6Q_PAD_DISP0_DAT22 = 95,
+ MX6Q_PAD_DISP0_DAT23 = 96,
+ MX6Q_PAD_ENET_MDIO = 97,
+ MX6Q_PAD_ENET_REF_CLK = 98,
+ MX6Q_PAD_ENET_RX_ER = 99,
+ MX6Q_PAD_ENET_CRS_DV = 100,
+ MX6Q_PAD_ENET_RXD1 = 101,
+ MX6Q_PAD_ENET_RXD0 = 102,
+ MX6Q_PAD_ENET_TX_EN = 103,
+ MX6Q_PAD_ENET_TXD1 = 104,
+ MX6Q_PAD_ENET_TXD0 = 105,
+ MX6Q_PAD_ENET_MDC = 106,
+ MX6Q_PAD_DRAM_D40 = 107,
+ MX6Q_PAD_DRAM_D41 = 108,
+ MX6Q_PAD_DRAM_D42 = 109,
+ MX6Q_PAD_DRAM_D43 = 110,
+ MX6Q_PAD_DRAM_D44 = 111,
+ MX6Q_PAD_DRAM_D45 = 112,
+ MX6Q_PAD_DRAM_D46 = 113,
+ MX6Q_PAD_DRAM_D47 = 114,
+ MX6Q_PAD_DRAM_SDQS5 = 115,
+ MX6Q_PAD_DRAM_DQM5 = 116,
+ MX6Q_PAD_DRAM_D32 = 117,
+ MX6Q_PAD_DRAM_D33 = 118,
+ MX6Q_PAD_DRAM_D34 = 119,
+ MX6Q_PAD_DRAM_D35 = 120,
+ MX6Q_PAD_DRAM_D36 = 121,
+ MX6Q_PAD_DRAM_D37 = 122,
+ MX6Q_PAD_DRAM_D38 = 123,
+ MX6Q_PAD_DRAM_D39 = 124,
+ MX6Q_PAD_DRAM_DQM4 = 125,
+ MX6Q_PAD_DRAM_SDQS4 = 126,
+ MX6Q_PAD_DRAM_D24 = 127,
+ MX6Q_PAD_DRAM_D25 = 128,
+ MX6Q_PAD_DRAM_D26 = 129,
+ MX6Q_PAD_DRAM_D27 = 130,
+ MX6Q_PAD_DRAM_D28 = 131,
+ MX6Q_PAD_DRAM_D29 = 132,
+ MX6Q_PAD_DRAM_SDQS3 = 133,
+ MX6Q_PAD_DRAM_D30 = 134,
+ MX6Q_PAD_DRAM_D31 = 135,
+ MX6Q_PAD_DRAM_DQM3 = 136,
+ MX6Q_PAD_DRAM_D16 = 137,
+ MX6Q_PAD_DRAM_D17 = 138,
+ MX6Q_PAD_DRAM_D18 = 139,
+ MX6Q_PAD_DRAM_D19 = 140,
+ MX6Q_PAD_DRAM_D20 = 141,
+ MX6Q_PAD_DRAM_D21 = 142,
+ MX6Q_PAD_DRAM_D22 = 143,
+ MX6Q_PAD_DRAM_SDQS2 = 144,
+ MX6Q_PAD_DRAM_D23 = 145,
+ MX6Q_PAD_DRAM_DQM2 = 146,
+ MX6Q_PAD_DRAM_A0 = 147,
+ MX6Q_PAD_DRAM_A1 = 148,
+ MX6Q_PAD_DRAM_A2 = 149,
+ MX6Q_PAD_DRAM_A3 = 150,
+ MX6Q_PAD_DRAM_A4 = 151,
+ MX6Q_PAD_DRAM_A5 = 152,
+ MX6Q_PAD_DRAM_A6 = 153,
+ MX6Q_PAD_DRAM_A7 = 154,
+ MX6Q_PAD_DRAM_A8 = 155,
+ MX6Q_PAD_DRAM_A9 = 156,
+ MX6Q_PAD_DRAM_A10 = 157,
+ MX6Q_PAD_DRAM_A11 = 158,
+ MX6Q_PAD_DRAM_A12 = 159,
+ MX6Q_PAD_DRAM_A13 = 160,
+ MX6Q_PAD_DRAM_A14 = 161,
+ MX6Q_PAD_DRAM_A15 = 162,
+ MX6Q_PAD_DRAM_CAS = 163,
+ MX6Q_PAD_DRAM_CS0 = 164,
+ MX6Q_PAD_DRAM_CS1 = 165,
+ MX6Q_PAD_DRAM_RAS = 166,
+ MX6Q_PAD_DRAM_RESET = 167,
+ MX6Q_PAD_DRAM_SDBA0 = 168,
+ MX6Q_PAD_DRAM_SDBA1 = 169,
+ MX6Q_PAD_DRAM_SDCLK_0 = 170,
+ MX6Q_PAD_DRAM_SDBA2 = 171,
+ MX6Q_PAD_DRAM_SDCKE0 = 172,
+ MX6Q_PAD_DRAM_SDCLK_1 = 173,
+ MX6Q_PAD_DRAM_SDCKE1 = 174,
+ MX6Q_PAD_DRAM_SDODT0 = 175,
+ MX6Q_PAD_DRAM_SDODT1 = 176,
+ MX6Q_PAD_DRAM_SDWE = 177,
+ MX6Q_PAD_DRAM_D0 = 178,
+ MX6Q_PAD_DRAM_D1 = 179,
+ MX6Q_PAD_DRAM_D2 = 180,
+ MX6Q_PAD_DRAM_D3 = 181,
+ MX6Q_PAD_DRAM_D4 = 182,
+ MX6Q_PAD_DRAM_D5 = 183,
+ MX6Q_PAD_DRAM_SDQS0 = 184,
+ MX6Q_PAD_DRAM_D6 = 185,
+ MX6Q_PAD_DRAM_D7 = 186,
+ MX6Q_PAD_DRAM_DQM0 = 187,
+ MX6Q_PAD_DRAM_D8 = 188,
+ MX6Q_PAD_DRAM_D9 = 189,
+ MX6Q_PAD_DRAM_D10 = 190,
+ MX6Q_PAD_DRAM_D11 = 191,
+ MX6Q_PAD_DRAM_D12 = 192,
+ MX6Q_PAD_DRAM_D13 = 193,
+ MX6Q_PAD_DRAM_D14 = 194,
+ MX6Q_PAD_DRAM_SDQS1 = 195,
+ MX6Q_PAD_DRAM_D15 = 196,
+ MX6Q_PAD_DRAM_DQM1 = 197,
+ MX6Q_PAD_DRAM_D48 = 198,
+ MX6Q_PAD_DRAM_D49 = 199,
+ MX6Q_PAD_DRAM_D50 = 200,
+ MX6Q_PAD_DRAM_D51 = 201,
+ MX6Q_PAD_DRAM_D52 = 202,
+ MX6Q_PAD_DRAM_D53 = 203,
+ MX6Q_PAD_DRAM_D54 = 204,
+ MX6Q_PAD_DRAM_D55 = 205,
+ MX6Q_PAD_DRAM_SDQS6 = 206,
+ MX6Q_PAD_DRAM_DQM6 = 207,
+ MX6Q_PAD_DRAM_D56 = 208,
+ MX6Q_PAD_DRAM_SDQS7 = 209,
+ MX6Q_PAD_DRAM_D57 = 210,
+ MX6Q_PAD_DRAM_D58 = 211,
+ MX6Q_PAD_DRAM_D59 = 212,
+ MX6Q_PAD_DRAM_D60 = 213,
+ MX6Q_PAD_DRAM_DQM7 = 214,
+ MX6Q_PAD_DRAM_D61 = 215,
+ MX6Q_PAD_DRAM_D62 = 216,
+ MX6Q_PAD_DRAM_D63 = 217,
+ MX6Q_PAD_KEY_COL0 = 218,
+ MX6Q_PAD_KEY_ROW0 = 219,
+ MX6Q_PAD_KEY_COL1 = 220,
+ MX6Q_PAD_KEY_ROW1 = 221,
+ MX6Q_PAD_KEY_COL2 = 222,
+ MX6Q_PAD_KEY_ROW2 = 223,
+ MX6Q_PAD_KEY_COL3 = 224,
+ MX6Q_PAD_KEY_ROW3 = 225,
+ MX6Q_PAD_KEY_COL4 = 226,
+ MX6Q_PAD_KEY_ROW4 = 227,
+ MX6Q_PAD_GPIO_0 = 228,
+ MX6Q_PAD_GPIO_1 = 229,
+ MX6Q_PAD_GPIO_9 = 230,
+ MX6Q_PAD_GPIO_3 = 231,
+ MX6Q_PAD_GPIO_6 = 232,
+ MX6Q_PAD_GPIO_2 = 233,
+ MX6Q_PAD_GPIO_4 = 234,
+ MX6Q_PAD_GPIO_5 = 235,
+ MX6Q_PAD_GPIO_7 = 236,
+ MX6Q_PAD_GPIO_8 = 237,
+ MX6Q_PAD_GPIO_16 = 238,
+ MX6Q_PAD_GPIO_17 = 239,
+ MX6Q_PAD_GPIO_18 = 240,
+ MX6Q_PAD_GPIO_19 = 241,
+ MX6Q_PAD_CSI0_PIXCLK = 242,
+ MX6Q_PAD_CSI0_MCLK = 243,
+ MX6Q_PAD_CSI0_DATA_EN = 244,
+ MX6Q_PAD_CSI0_VSYNC = 245,
+ MX6Q_PAD_CSI0_DAT4 = 246,
+ MX6Q_PAD_CSI0_DAT5 = 247,
+ MX6Q_PAD_CSI0_DAT6 = 248,
+ MX6Q_PAD_CSI0_DAT7 = 249,
+ MX6Q_PAD_CSI0_DAT8 = 250,
+ MX6Q_PAD_CSI0_DAT9 = 251,
+ MX6Q_PAD_CSI0_DAT10 = 252,
+ MX6Q_PAD_CSI0_DAT11 = 253,
+ MX6Q_PAD_CSI0_DAT12 = 254,
+ MX6Q_PAD_CSI0_DAT13 = 255,
+ MX6Q_PAD_CSI0_DAT14 = 256,
+ MX6Q_PAD_CSI0_DAT15 = 257,
+ MX6Q_PAD_CSI0_DAT16 = 258,
+ MX6Q_PAD_CSI0_DAT17 = 259,
+ MX6Q_PAD_CSI0_DAT18 = 260,
+ MX6Q_PAD_CSI0_DAT19 = 261,
+ MX6Q_PAD_JTAG_TMS = 262,
+ MX6Q_PAD_JTAG_MOD = 263,
+ MX6Q_PAD_JTAG_TRSTB = 264,
+ MX6Q_PAD_JTAG_TDI = 265,
+ MX6Q_PAD_JTAG_TCK = 266,
+ MX6Q_PAD_JTAG_TDO = 267,
+ MX6Q_PAD_LVDS1_TX3_P = 268,
+ MX6Q_PAD_LVDS1_TX2_P = 269,
+ MX6Q_PAD_LVDS1_CLK_P = 270,
+ MX6Q_PAD_LVDS1_TX1_P = 271,
+ MX6Q_PAD_LVDS1_TX0_P = 272,
+ MX6Q_PAD_LVDS0_TX3_P = 273,
+ MX6Q_PAD_LVDS0_CLK_P = 274,
+ MX6Q_PAD_LVDS0_TX2_P = 275,
+ MX6Q_PAD_LVDS0_TX1_P = 276,
+ MX6Q_PAD_LVDS0_TX0_P = 277,
+ MX6Q_PAD_TAMPER = 278,
+ MX6Q_PAD_PMIC_ON_REQ = 279,
+ MX6Q_PAD_PMIC_STBY_REQ = 280,
+ MX6Q_PAD_POR_B = 281,
+ MX6Q_PAD_BOOT_MODE1 = 282,
+ MX6Q_PAD_RESET_IN_B = 283,
+ MX6Q_PAD_BOOT_MODE0 = 284,
+ MX6Q_PAD_TEST_MODE = 285,
+ MX6Q_PAD_SD3_DAT7 = 286,
+ MX6Q_PAD_SD3_DAT6 = 287,
+ MX6Q_PAD_SD3_DAT5 = 288,
+ MX6Q_PAD_SD3_DAT4 = 289,
+ MX6Q_PAD_SD3_CMD = 290,
+ MX6Q_PAD_SD3_CLK = 291,
+ MX6Q_PAD_SD3_DAT0 = 292,
+ MX6Q_PAD_SD3_DAT1 = 293,
+ MX6Q_PAD_SD3_DAT2 = 294,
+ MX6Q_PAD_SD3_DAT3 = 295,
+ MX6Q_PAD_SD3_RST = 296,
+ MX6Q_PAD_NANDF_CLE = 297,
+ MX6Q_PAD_NANDF_ALE = 298,
+ MX6Q_PAD_NANDF_WP_B = 299,
+ MX6Q_PAD_NANDF_RB0 = 300,
+ MX6Q_PAD_NANDF_CS0 = 301,
+ MX6Q_PAD_NANDF_CS1 = 302,
+ MX6Q_PAD_NANDF_CS2 = 303,
+ MX6Q_PAD_NANDF_CS3 = 304,
+ MX6Q_PAD_SD4_CMD = 305,
+ MX6Q_PAD_SD4_CLK = 306,
+ MX6Q_PAD_NANDF_D0 = 307,
+ MX6Q_PAD_NANDF_D1 = 308,
+ MX6Q_PAD_NANDF_D2 = 309,
+ MX6Q_PAD_NANDF_D3 = 310,
+ MX6Q_PAD_NANDF_D4 = 311,
+ MX6Q_PAD_NANDF_D5 = 312,
+ MX6Q_PAD_NANDF_D6 = 313,
+ MX6Q_PAD_NANDF_D7 = 314,
+ MX6Q_PAD_SD4_DAT0 = 315,
+ MX6Q_PAD_SD4_DAT1 = 316,
+ MX6Q_PAD_SD4_DAT2 = 317,
+ MX6Q_PAD_SD4_DAT3 = 318,
+ MX6Q_PAD_SD4_DAT4 = 319,
+ MX6Q_PAD_SD4_DAT5 = 320,
+ MX6Q_PAD_SD4_DAT6 = 321,
+ MX6Q_PAD_SD4_DAT7 = 322,
+ MX6Q_PAD_SD1_DAT1 = 323,
+ MX6Q_PAD_SD1_DAT0 = 324,
+ MX6Q_PAD_SD1_DAT3 = 325,
+ MX6Q_PAD_SD1_CMD = 326,
+ MX6Q_PAD_SD1_DAT2 = 327,
+ MX6Q_PAD_SD1_CLK = 328,
+ MX6Q_PAD_SD2_CLK = 329,
+ MX6Q_PAD_SD2_CMD = 330,
+ MX6Q_PAD_SD2_DAT3 = 331,
+};
+
+/* imx6q register maps */
+static struct imx_pin_reg imx6q_pin_regs[] = {
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 0, 0x0000, 0), /* MX6Q_PAD_SD2_DAT1__USDHC2_DAT1 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 1, 0x0834, 0), /* MX6Q_PAD_SD2_DAT1__ECSPI5_SS0 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 2, 0x0000, 0), /* MX6Q_PAD_SD2_DAT1__WEIM_WEIM_CS_2 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 3, 0x07C8, 0), /* MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 4, 0x08F0, 0), /* MX6Q_PAD_SD2_DAT1__KPP_COL_7 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 5, 0x0000, 0), /* MX6Q_PAD_SD2_DAT1__GPIO_1_14 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 6, 0x0000, 0), /* MX6Q_PAD_SD2_DAT1__CCM_WAIT */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 7, 0x0000, 0), /* MX6Q_PAD_SD2_DAT1__ANATOP_TESTO_0 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 0, 0x0000, 0), /* MX6Q_PAD_SD2_DAT2__USDHC2_DAT2 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 1, 0x0838, 0), /* MX6Q_PAD_SD2_DAT2__ECSPI5_SS1 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 2, 0x0000, 0), /* MX6Q_PAD_SD2_DAT2__WEIM_WEIM_CS_3 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 3, 0x07B8, 0), /* MX6Q_PAD_SD2_DAT2__AUDMUX_AUD4_TXD */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 4, 0x08F8, 0), /* MX6Q_PAD_SD2_DAT2__KPP_ROW_6 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 5, 0x0000, 0), /* MX6Q_PAD_SD2_DAT2__GPIO_1_13 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 6, 0x0000, 0), /* MX6Q_PAD_SD2_DAT2__CCM_STOP */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 7, 0x0000, 0), /* MX6Q_PAD_SD2_DAT2__ANATOP_TESTO_1 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 0, 0x0000, 0), /* MX6Q_PAD_SD2_DAT0__USDHC2_DAT0 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 1, 0x082C, 0), /* MX6Q_PAD_SD2_DAT0__ECSPI5_MISO */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 3, 0x07B4, 0), /* MX6Q_PAD_SD2_DAT0__AUDMUX_AUD4_RXD */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 4, 0x08FC, 0), /* MX6Q_PAD_SD2_DAT0__KPP_ROW_7 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 5, 0x0000, 0), /* MX6Q_PAD_SD2_DAT0__GPIO_1_15 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 6, 0x0000, 0), /* MX6Q_PAD_SD2_DAT0__DCIC2_DCIC_OUT */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 7, 0x0000, 0), /* MX6Q_PAD_SD2_DAT0__TESTO_2 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TXC, 0x036C, 0x0058, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TXC, 0x036C, 0x0058, 1, 0x0000, 0), /* MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TXC, 0x036C, 0x0058, 2, 0x0918, 0), /* MX6Q_PAD_RGMII_TXC__SPDIF_SPDIF_EXTCLK */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TXC, 0x036C, 0x0058, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_TXC__GPIO_6_19 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TXC, 0x036C, 0x0058, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_TXC__MIPI_CORE_DPHY_IN_0 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TXC, 0x036C, 0x0058, 7, 0x0000, 0), /* MX6Q_PAD_RGMII_TXC__ANATOP_24M_OUT */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD0, 0x0370, 0x005C, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_TD0__MIPI_HSI_CRL_TX_RDY */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD0, 0x0370, 0x005C, 1, 0x0000, 0), /* MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD0, 0x0370, 0x005C, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_TD0__GPIO_6_20 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD0, 0x0370, 0x005C, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_TD0__MIPI_CORE_DPHY_IN_1 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD1, 0x0374, 0x0060, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_TD1__MIPI_HSI_CRL_RX_FLG */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD1, 0x0374, 0x0060, 1, 0x0000, 0), /* MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD1, 0x0374, 0x0060, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_TD1__GPIO_6_21 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD1, 0x0374, 0x0060, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_TD1__MIPI_CORE_DPHY_IN_2 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD1, 0x0374, 0x0060, 7, 0x0000, 0), /* MX6Q_PAD_RGMII_TD1__CCM_PLL3_BYP */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD2, 0x0378, 0x0064, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_TD2__MIPI_HSI_CRL_RX_DTA */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD2, 0x0378, 0x0064, 1, 0x0000, 0), /* MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD2, 0x0378, 0x0064, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_TD2__GPIO_6_22 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD2, 0x0378, 0x0064, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_TD2__MIPI_CORE_DPHY_IN_3 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD2, 0x0378, 0x0064, 7, 0x0000, 0), /* MX6Q_PAD_RGMII_TD2__CCM_PLL2_BYP */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD3, 0x037C, 0x0068, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_TD3__MIPI_HSI_CRL_RX_WAK */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD3, 0x037C, 0x0068, 1, 0x0000, 0), /* MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD3, 0x037C, 0x0068, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_TD3__GPIO_6_23 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TD3, 0x037C, 0x0068, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_TD3__MIPI_CORE_DPHY_IN_4 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RX_CTL, 0x0380, 0x006C, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RX_CTL, 0x0380, 0x006C, 1, 0x0858, 0), /* MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RX_CTL, 0x0380, 0x006C, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_RX_CTL__GPIO_6_24 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RX_CTL, 0x0380, 0x006C, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_RX_CTL__MIPI_DPHY_IN_5 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD0, 0x0384, 0x0070, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_RD0__MIPI_HSI_CRL_RX_RDY */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD0, 0x0384, 0x0070, 1, 0x0848, 0), /* MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD0, 0x0384, 0x0070, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_RD0__GPIO_6_25 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD0, 0x0384, 0x0070, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_RD0__MIPI_CORE_DPHY_IN_6 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TX_CTL, 0x0388, 0x0074, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TX_CTL, 0x0388, 0x0074, 1, 0x0000, 0), /* MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TX_CTL, 0x0388, 0x0074, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_TX_CTL__GPIO_6_26 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TX_CTL, 0x0388, 0x0074, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_TX_CTL__CORE_DPHY_IN_7 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_TX_CTL, 0x0388, 0x0074, 7, 0x083C, 0), /* MX6Q_PAD_RGMII_TX_CTL__ANATOP_REF_OUT */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD1, 0x038C, 0x0078, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_RD1__MIPI_HSI_CTRL_TX_FL */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD1, 0x038C, 0x0078, 1, 0x084C, 0), /* MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD1, 0x038C, 0x0078, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_RD1__GPIO_6_27 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD1, 0x038C, 0x0078, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_RD1__CORE_DPHY_TEST_IN_8 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD1, 0x038C, 0x0078, 7, 0x0000, 0), /* MX6Q_PAD_RGMII_RD1__SJC_FAIL */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD2, 0x0390, 0x007C, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_RD2__MIPI_HSI_CRL_TX_DTA */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD2, 0x0390, 0x007C, 1, 0x0850, 0), /* MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD2, 0x0390, 0x007C, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_RD2__GPIO_6_28 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD2, 0x0390, 0x007C, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_RD2__MIPI_CORE_DPHY_IN_9 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD3, 0x0394, 0x0080, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_RD3__MIPI_HSI_CRL_TX_WAK */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD3, 0x0394, 0x0080, 1, 0x0854, 0), /* MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD3, 0x0394, 0x0080, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_RD3__GPIO_6_29 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RD3, 0x0394, 0x0080, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_RD3__MIPI_CORE_DPHY_IN10 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RXC, 0x0398, 0x0084, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RXC, 0x0398, 0x0084, 1, 0x0844, 0), /* MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RXC, 0x0398, 0x0084, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_RXC__GPIO_6_30 */
+ IMX_PIN_REG(MX6Q_PAD_RGMII_RXC, 0x0398, 0x0084, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_RXC__MIPI_CORE_DPHY_IN11 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A25__WEIM_WEIM_A_25 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A25__ECSPI4_SS1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 2, 0x0000, 0), /* MX6Q_PAD_EIM_A25__ECSPI2_RDY */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A25__IPU1_DI1_PIN12 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A25__IPU1_DI0_D1_CS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A25__GPIO_5_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 6, 0x088C, 0), /* MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A25__PL301_PER1_HBURST_0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_EB2__WEIM_WEIM_EB_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 1, 0x0800, 0), /* MX6Q_PAD_EIM_EB2__ECSPI1_SS0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 2, 0x07EC, 0), /* MX6Q_PAD_EIM_EB2__CCM_DI1_EXT_CLK */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 3, 0x08D4, 0), /* MX6Q_PAD_EIM_EB2__IPU2_CSI1_D_19 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 4, 0x0890, 0), /* MX6Q_PAD_EIM_EB2__HDMI_TX_DDC_SCL */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_EB2__GPIO_2_30 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 6, 0x08A0, 0), /* MX6Q_PAD_EIM_EB2__I2C2_SCL */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_EB2__SRC_BT_CFG_30 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D16__WEIM_WEIM_D_16 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 1, 0x07F4, 0), /* MX6Q_PAD_EIM_D16__ECSPI1_SCLK */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D16__IPU1_DI0_PIN5 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 3, 0x08D0, 0), /* MX6Q_PAD_EIM_D16__IPU2_CSI1_D_18 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 4, 0x0894, 0), /* MX6Q_PAD_EIM_D16__HDMI_TX_DDC_SDA */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D16__GPIO_3_16 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 6, 0x08A4, 0), /* MX6Q_PAD_EIM_D16__I2C2_SDA */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D17__WEIM_WEIM_D_17 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 1, 0x07F8, 0), /* MX6Q_PAD_EIM_D17__ECSPI1_MISO */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D17__IPU1_DI0_PIN6 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 3, 0x08E0, 0), /* MX6Q_PAD_EIM_D17__IPU2_CSI1_PIXCLK */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 4, 0x0000, 0), /* MX6Q_PAD_EIM_D17__DCIC1_DCIC_OUT */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D17__GPIO_3_17 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 6, 0x08A8, 0), /* MX6Q_PAD_EIM_D17__I2C3_SCL */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D17__PL301_PER1_HBURST_1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D18__WEIM_WEIM_D_18 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 1, 0x07FC, 0), /* MX6Q_PAD_EIM_D18__ECSPI1_MOSI */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D18__IPU1_DI0_PIN7 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 3, 0x08CC, 0), /* MX6Q_PAD_EIM_D18__IPU2_CSI1_D_17 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 4, 0x0000, 0), /* MX6Q_PAD_EIM_D18__IPU1_DI1_D0_CS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D18__GPIO_3_18 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 6, 0x08AC, 0), /* MX6Q_PAD_EIM_D18__I2C3_SDA */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D18__PL301_PER1_HBURST_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D19__WEIM_WEIM_D_19 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 1, 0x0804, 0), /* MX6Q_PAD_EIM_D19__ECSPI1_SS1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D19__IPU1_DI0_PIN8 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 3, 0x08C8, 0), /* MX6Q_PAD_EIM_D19__IPU2_CSI1_D_16 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 4, 0x091C, 0), /* MX6Q_PAD_EIM_D19__UART1_CTS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D19__GPIO_3_19 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D19__EPIT1_EPITO */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D19__PL301_PER1_HRESP */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D20__WEIM_WEIM_D_20 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 1, 0x0824, 0), /* MX6Q_PAD_EIM_D20__ECSPI4_SS0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D20__IPU1_DI0_PIN16 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 3, 0x08C4, 0), /* MX6Q_PAD_EIM_D20__IPU2_CSI1_D_15 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 4, 0x091C, 1), /* MX6Q_PAD_EIM_D20__UART1_RTS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D20__GPIO_3_20 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D20__EPIT2_EPITO */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D21__WEIM_WEIM_D_21 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D21__ECSPI4_SCLK */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D21__IPU1_DI0_PIN17 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 3, 0x08B4, 0), /* MX6Q_PAD_EIM_D21__IPU2_CSI1_D_11 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 4, 0x0944, 0), /* MX6Q_PAD_EIM_D21__USBOH3_USBOTG_OC */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D21__GPIO_3_21 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 6, 0x0898, 0), /* MX6Q_PAD_EIM_D21__I2C1_SCL */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 7, 0x0914, 0), /* MX6Q_PAD_EIM_D21__SPDIF_IN1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D22__WEIM_WEIM_D_22 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D22__ECSPI4_MISO */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D22__IPU1_DI0_PIN1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 3, 0x08B0, 0), /* MX6Q_PAD_EIM_D22__IPU2_CSI1_D_10 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 4, 0x0000, 0), /* MX6Q_PAD_EIM_D22__USBOH3_USBOTG_PWR */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D22__GPIO_3_22 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D22__SPDIF_OUT1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D22__PL301_PER1_HWRITE */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D23__WEIM_WEIM_D_23 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D23__IPU1_DI0_D0_CS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 2, 0x092C, 0), /* MX6Q_PAD_EIM_D23__UART3_CTS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 3, 0x0000, 0), /* MX6Q_PAD_EIM_D23__UART1_DCD */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 4, 0x08D8, 0), /* MX6Q_PAD_EIM_D23__IPU2_CSI1_DATA_EN */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D23__GPIO_3_23 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D23__IPU1_DI1_PIN2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D23__IPU1_DI1_PIN14 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 0, 0x0000, 0), /* MX6Q_PAD_EIM_EB3__WEIM_WEIM_EB_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 1, 0x0000, 0), /* MX6Q_PAD_EIM_EB3__ECSPI4_RDY */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 2, 0x092C, 1), /* MX6Q_PAD_EIM_EB3__UART3_RTS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 3, 0x0000, 0), /* MX6Q_PAD_EIM_EB3__UART1_RI */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 4, 0x08DC, 0), /* MX6Q_PAD_EIM_EB3__IPU2_CSI1_HSYNC */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 5, 0x0000, 0), /* MX6Q_PAD_EIM_EB3__GPIO_2_31 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 6, 0x0000, 0), /* MX6Q_PAD_EIM_EB3__IPU1_DI1_PIN3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 7, 0x0000, 0), /* MX6Q_PAD_EIM_EB3__SRC_BT_CFG_31 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D24__WEIM_WEIM_D_24 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D24__ECSPI4_SS2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D24__UART3_TXD */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 3, 0x0808, 0), /* MX6Q_PAD_EIM_D24__ECSPI1_SS2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 4, 0x0000, 0), /* MX6Q_PAD_EIM_D24__ECSPI2_SS2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D24__GPIO_3_24 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 6, 0x07D8, 0), /* MX6Q_PAD_EIM_D24__AUDMUX_AUD5_RXFS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D24__UART1_DTR */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D25__WEIM_WEIM_D_25 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D25__ECSPI4_SS3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 2, 0x0930, 1), /* MX6Q_PAD_EIM_D25__UART3_RXD */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 3, 0x080C, 0), /* MX6Q_PAD_EIM_D25__ECSPI1_SS3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 4, 0x0000, 0), /* MX6Q_PAD_EIM_D25__ECSPI2_SS3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D25__GPIO_3_25 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 6, 0x07D4, 0), /* MX6Q_PAD_EIM_D25__AUDMUX_AUD5_RXC */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D25__UART1_DSR */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D26__WEIM_WEIM_D_26 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D26__IPU1_DI1_PIN11 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D26__IPU1_CSI0_D_1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 3, 0x08C0, 0), /* MX6Q_PAD_EIM_D26__IPU2_CSI1_D_14 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 4, 0x0000, 0), /* MX6Q_PAD_EIM_D26__UART2_TXD */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D26__GPIO_3_26 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D26__IPU1_SISG_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D26__IPU1_DISP1_DAT_22 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D27__WEIM_WEIM_D_27 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D27__IPU1_DI1_PIN13 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D27__IPU1_CSI0_D_0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 3, 0x08BC, 0), /* MX6Q_PAD_EIM_D27__IPU2_CSI1_D_13 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 4, 0x0928, 1), /* MX6Q_PAD_EIM_D27__UART2_RXD */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D27__GPIO_3_27 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D27__IPU1_SISG_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D27__IPU1_DISP1_DAT_23 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D28__WEIM_WEIM_D_28 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 1, 0x089C, 0), /* MX6Q_PAD_EIM_D28__I2C1_SDA */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D28__ECSPI4_MOSI */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 3, 0x08B8, 0), /* MX6Q_PAD_EIM_D28__IPU2_CSI1_D_12 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 4, 0x0924, 0), /* MX6Q_PAD_EIM_D28__UART2_CTS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D28__GPIO_3_28 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D28__IPU1_EXT_TRIG */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D28__IPU1_DI0_PIN13 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D29__WEIM_WEIM_D_29 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D29__IPU1_DI1_PIN15 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 2, 0x0824, 1), /* MX6Q_PAD_EIM_D29__ECSPI4_SS0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 4, 0x0924, 1), /* MX6Q_PAD_EIM_D29__UART2_RTS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D29__GPIO_3_29 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 6, 0x08E4, 0), /* MX6Q_PAD_EIM_D29__IPU2_CSI1_VSYNC */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D29__IPU1_DI0_PIN14 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D30__WEIM_WEIM_D_30 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D30__IPU1_DISP1_DAT_21 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D30__IPU1_DI0_PIN11 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 3, 0x0000, 0), /* MX6Q_PAD_EIM_D30__IPU1_CSI0_D_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 4, 0x092C, 2), /* MX6Q_PAD_EIM_D30__UART3_CTS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D30__GPIO_3_30 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 6, 0x0948, 0), /* MX6Q_PAD_EIM_D30__USBOH3_USBH1_OC */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D30__PL301_PER1_HPROT_0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D31__WEIM_WEIM_D_31 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D31__IPU1_DISP1_DAT_20 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D31__IPU1_DI0_PIN12 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 3, 0x0000, 0), /* MX6Q_PAD_EIM_D31__IPU1_CSI0_D_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 4, 0x092C, 3), /* MX6Q_PAD_EIM_D31__UART3_RTS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D31__GPIO_3_31 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D31__USBOH3_USBH1_PWR */
+ IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D31__PL301_PER1_HPROT_1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A24__WEIM_WEIM_A_24 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A24__IPU1_DISP1_DAT_19 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 2, 0x08D4, 1), /* MX6Q_PAD_EIM_A24__IPU2_CSI1_D_19 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A24__IPU2_SISG_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A24__IPU1_SISG_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A24__GPIO_5_4 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A24__PL301_PER1_HPROT_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A24__SRC_BT_CFG_24 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A23__WEIM_WEIM_A_23 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A23__IPU1_DISP1_DAT_18 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 2, 0x08D0, 1), /* MX6Q_PAD_EIM_A23__IPU2_CSI1_D_18 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A23__IPU2_SISG_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A23__IPU1_SISG_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A23__GPIO_6_6 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A23__PL301_PER1_HPROT_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A23__SRC_BT_CFG_23 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A22, 0x03F0, 0x00DC, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A22__WEIM_WEIM_A_22 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A22, 0x03F0, 0x00DC, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A22__IPU1_DISP1_DAT_17 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A22, 0x03F0, 0x00DC, 2, 0x08CC, 1), /* MX6Q_PAD_EIM_A22__IPU2_CSI1_D_17 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A22, 0x03F0, 0x00DC, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A22__GPIO_2_16 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A22, 0x03F0, 0x00DC, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A22__TPSMP_HDATA_0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A22, 0x03F0, 0x00DC, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A22__SRC_BT_CFG_22 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A21__WEIM_WEIM_A_21 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A21__IPU1_DISP1_DAT_16 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 2, 0x08C8, 1), /* MX6Q_PAD_EIM_A21__IPU2_CSI1_D_16 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A21__RESERVED_RESERVED */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A21__MIPI_CORE_DPHY_OUT_18 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A21__GPIO_2_17 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A21__TPSMP_HDATA_1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A21__SRC_BT_CFG_21 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A20__WEIM_WEIM_A_20 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A20__IPU1_DISP1_DAT_15 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 2, 0x08C4, 1), /* MX6Q_PAD_EIM_A20__IPU2_CSI1_D_15 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A20__RESERVED_RESERVED */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A20__MIPI_CORE_DPHY_OUT_19 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A20__GPIO_2_18 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A20__TPSMP_HDATA_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A20__SRC_BT_CFG_20 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A19__WEIM_WEIM_A_19 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A19__IPU1_DISP1_DAT_14 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 2, 0x08C0, 1), /* MX6Q_PAD_EIM_A19__IPU2_CSI1_D_14 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A19__RESERVED_RESERVED */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A19__MIPI_CORE_DPHY_OUT_20 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A19__GPIO_2_19 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A19__TPSMP_HDATA_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A19__SRC_BT_CFG_19 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A18__WEIM_WEIM_A_18 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A18__IPU1_DISP1_DAT_13 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 2, 0x08BC, 1), /* MX6Q_PAD_EIM_A18__IPU2_CSI1_D_13 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A18__RESERVED_RESERVED */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A18__MIPI_CORE_DPHY_OUT_21 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A18__GPIO_2_20 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A18__TPSMP_HDATA_4 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A18__SRC_BT_CFG_18 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A17__WEIM_WEIM_A_17 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A17__IPU1_DISP1_DAT_12 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 2, 0x08B8, 1), /* MX6Q_PAD_EIM_A17__IPU2_CSI1_D_12 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A17__RESERVED_RESERVED */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A17__MIPI_CORE_DPHY_OUT_22 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A17__GPIO_2_21 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A17__TPSMP_HDATA_5 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A17__SRC_BT_CFG_17 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A16__WEIM_WEIM_A_16 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A16__IPU1_DI1_DISP_CLK */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 2, 0x08E0, 1), /* MX6Q_PAD_EIM_A16__IPU2_CSI1_PIXCLK */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A16__MIPI_CORE_DPHY_OUT_23 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A16__GPIO_2_22 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A16__TPSMP_HDATA_6 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A16__SRC_BT_CFG_16 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_CS0, 0x040C, 0x00F8, 0, 0x0000, 0), /* MX6Q_PAD_EIM_CS0__WEIM_WEIM_CS_0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_CS0, 0x040C, 0x00F8, 1, 0x0000, 0), /* MX6Q_PAD_EIM_CS0__IPU1_DI1_PIN5 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_CS0, 0x040C, 0x00F8, 2, 0x0810, 0), /* MX6Q_PAD_EIM_CS0__ECSPI2_SCLK */
+ IMX_PIN_REG(MX6Q_PAD_EIM_CS0, 0x040C, 0x00F8, 4, 0x0000, 0), /* MX6Q_PAD_EIM_CS0__MIPI_CORE_DPHY_OUT_24 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_CS0, 0x040C, 0x00F8, 5, 0x0000, 0), /* MX6Q_PAD_EIM_CS0__GPIO_2_23 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_CS0, 0x040C, 0x00F8, 6, 0x0000, 0), /* MX6Q_PAD_EIM_CS0__TPSMP_HDATA_7 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_CS1, 0x0410, 0x00FC, 0, 0x0000, 0), /* MX6Q_PAD_EIM_CS1__WEIM_WEIM_CS_1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_CS1, 0x0410, 0x00FC, 1, 0x0000, 0), /* MX6Q_PAD_EIM_CS1__IPU1_DI1_PIN6 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_CS1, 0x0410, 0x00FC, 2, 0x0818, 0), /* MX6Q_PAD_EIM_CS1__ECSPI2_MOSI */
+ IMX_PIN_REG(MX6Q_PAD_EIM_CS1, 0x0410, 0x00FC, 4, 0x0000, 0), /* MX6Q_PAD_EIM_CS1__MIPI_CORE_DPHY_OUT_25 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_CS1, 0x0410, 0x00FC, 5, 0x0000, 0), /* MX6Q_PAD_EIM_CS1__GPIO_2_24 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_CS1, 0x0410, 0x00FC, 6, 0x0000, 0), /* MX6Q_PAD_EIM_CS1__TPSMP_HDATA_8 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_OE, 0x0414, 0x0100, 0, 0x0000, 0), /* MX6Q_PAD_EIM_OE__WEIM_WEIM_OE */
+ IMX_PIN_REG(MX6Q_PAD_EIM_OE, 0x0414, 0x0100, 1, 0x0000, 0), /* MX6Q_PAD_EIM_OE__IPU1_DI1_PIN7 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_OE, 0x0414, 0x0100, 2, 0x0814, 0), /* MX6Q_PAD_EIM_OE__ECSPI2_MISO */
+ IMX_PIN_REG(MX6Q_PAD_EIM_OE, 0x0414, 0x0100, 4, 0x0000, 0), /* MX6Q_PAD_EIM_OE__MIPI_CORE_DPHY_OUT_26 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_OE, 0x0414, 0x0100, 5, 0x0000, 0), /* MX6Q_PAD_EIM_OE__GPIO_2_25 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_OE, 0x0414, 0x0100, 6, 0x0000, 0), /* MX6Q_PAD_EIM_OE__TPSMP_HDATA_9 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 0, 0x0000, 0), /* MX6Q_PAD_EIM_RW__WEIM_WEIM_RW */
+ IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 1, 0x0000, 0), /* MX6Q_PAD_EIM_RW__IPU1_DI1_PIN8 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 2, 0x081C, 0), /* MX6Q_PAD_EIM_RW__ECSPI2_SS0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 4, 0x0000, 0), /* MX6Q_PAD_EIM_RW__MIPI_CORE_DPHY_OUT_27 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 5, 0x0000, 0), /* MX6Q_PAD_EIM_RW__GPIO_2_26 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 6, 0x0000, 0), /* MX6Q_PAD_EIM_RW__TPSMP_HDATA_10 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 7, 0x0000, 0), /* MX6Q_PAD_EIM_RW__SRC_BT_CFG_29 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_LBA, 0x041C, 0x0108, 0, 0x0000, 0), /* MX6Q_PAD_EIM_LBA__WEIM_WEIM_LBA */
+ IMX_PIN_REG(MX6Q_PAD_EIM_LBA, 0x041C, 0x0108, 1, 0x0000, 0), /* MX6Q_PAD_EIM_LBA__IPU1_DI1_PIN17 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_LBA, 0x041C, 0x0108, 2, 0x0820, 0), /* MX6Q_PAD_EIM_LBA__ECSPI2_SS1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_LBA, 0x041C, 0x0108, 5, 0x0000, 0), /* MX6Q_PAD_EIM_LBA__GPIO_2_27 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_LBA, 0x041C, 0x0108, 6, 0x0000, 0), /* MX6Q_PAD_EIM_LBA__TPSMP_HDATA_11 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_LBA, 0x041C, 0x0108, 7, 0x0000, 0), /* MX6Q_PAD_EIM_LBA__SRC_BT_CFG_26 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_EB0__WEIM_WEIM_EB_0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 1, 0x0000, 0), /* MX6Q_PAD_EIM_EB0__IPU1_DISP1_DAT_11 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 2, 0x08B4, 1), /* MX6Q_PAD_EIM_EB0__IPU2_CSI1_D_11 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 3, 0x0000, 0), /* MX6Q_PAD_EIM_EB0__MIPI_CORE_DPHY_OUT_0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 4, 0x07F0, 0), /* MX6Q_PAD_EIM_EB0__CCM_PMIC_RDY */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_EB0__GPIO_2_28 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 6, 0x0000, 0), /* MX6Q_PAD_EIM_EB0__TPSMP_HDATA_12 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_EB0__SRC_BT_CFG_27 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 0, 0x0000, 0), /* MX6Q_PAD_EIM_EB1__WEIM_WEIM_EB_1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 1, 0x0000, 0), /* MX6Q_PAD_EIM_EB1__IPU1_DISP1_DAT_10 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 2, 0x08B0, 1), /* MX6Q_PAD_EIM_EB1__IPU2_CSI1_D_10 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 3, 0x0000, 0), /* MX6Q_PAD_EIM_EB1__MIPI_CORE_DPHY__OUT_1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 5, 0x0000, 0), /* MX6Q_PAD_EIM_EB1__GPIO_2_29 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 6, 0x0000, 0), /* MX6Q_PAD_EIM_EB1__TPSMP_HDATA_13 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 7, 0x0000, 0), /* MX6Q_PAD_EIM_EB1__SRC_BT_CFG_28 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__WEIM_WEIM_DA_A_0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__IPU1_DISP1_DAT_9 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__IPU2_CSI1_D_9 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__MIPI_CORE_DPHY__OUT_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__GPIO_3_0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__TPSMP_HDATA_14 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__SRC_BT_CFG_0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__WEIM_WEIM_DA_A_1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__IPU1_DISP1_DAT_8 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__IPU2_CSI1_D_8 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__MIPI_CORE_DPHY_OUT_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__USBPHY1_TX_LS_MODE */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__GPIO_3_1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__TPSMP_HDATA_15 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__SRC_BT_CFG_1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__WEIM_WEIM_DA_A_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__IPU1_DISP1_DAT_7 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__IPU2_CSI1_D_7 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__MIPI_CORE_DPHY_OUT_4 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__USBPHY1_TX_HS_MODE */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__GPIO_3_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__TPSMP_HDATA_16 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__SRC_BT_CFG_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__WEIM_WEIM_DA_A_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__IPU1_DISP1_DAT_6 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__IPU2_CSI1_D_6 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__MIPI_CORE_DPHY_OUT_5 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__USBPHY1_TX_HIZ */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__GPIO_3_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__TPSMP_HDATA_17 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__SRC_BT_CFG_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__WEIM_WEIM_DA_A_4 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__IPU1_DISP1_DAT_5 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__IPU2_CSI1_D_5 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__MIPI_CORE_DPHY_OUT_6 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__ANATOP_USBPHY1_TX_EN */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__GPIO_3_4 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__TPSMP_HDATA_18 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__SRC_BT_CFG_4 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__WEIM_WEIM_DA_A_5 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__IPU1_DISP1_DAT_4 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__IPU2_CSI1_D_4 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__MIPI_CORE_DPHY_OUT_7 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__ANATOP_USBPHY1_TX_DP */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__GPIO_3_5 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__TPSMP_HDATA_19 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__SRC_BT_CFG_5 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__WEIM_WEIM_DA_A_6 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__IPU1_DISP1_DAT_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__IPU2_CSI1_D_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__MIPI_CORE_DPHY_OUT_8 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__ANATOP_USBPHY1_TX_DN */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__GPIO_3_6 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__TPSMP_HDATA_20 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__SRC_BT_CFG_6 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__WEIM_WEIM_DA_A_7 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__IPU1_DISP1_DAT_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__IPU2_CSI1_D_2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__MIPI_CORE_DPHY_OUT_9 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__GPIO_3_7 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__TPSMP_HDATA_21 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__SRC_BT_CFG_7 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__WEIM_WEIM_DA_A_8 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__IPU1_DISP1_DAT_1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__IPU2_CSI1_D_1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__MIPI_CORE_DPHY_OUT_10 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__GPIO_3_8 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__TPSMP_HDATA_22 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__SRC_BT_CFG_8 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__WEIM_WEIM_DA_A_9 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__IPU1_DISP1_DAT_0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__IPU2_CSI1_D_0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__MIPI_CORE_DPHY_OUT_11 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__GPIO_3_9 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__TPSMP_HDATA_23 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__SRC_BT_CFG_9 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA10__WEIM_WEIM_DA_A_10 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA10__IPU1_DI1_PIN15 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 2, 0x08D8, 1), /* MX6Q_PAD_EIM_DA10__IPU2_CSI1_DATA_EN */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA10__MIPI_CORE_DPHY_OUT12 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA10__GPIO_3_10 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA10__TPSMP_HDATA_24 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA10__SRC_BT_CFG_10 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__WEIM_WEIM_DA_A_11 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__IPU1_DI1_PIN2 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 2, 0x08DC, 1), /* MX6Q_PAD_EIM_DA11__IPU2_CSI1_HSYNC */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__MIPI_CORE_DPHY_OUT13 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__SDMA_DBG_EVT_CHN_6 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__GPIO_3_11 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__TPSMP_HDATA_25 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__SRC_BT_CFG_11 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__WEIM_WEIM_DA_A_12 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__IPU1_DI1_PIN3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 2, 0x08E4, 1), /* MX6Q_PAD_EIM_DA12__IPU2_CSI1_VSYNC */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__MIPI_CORE_DPHY_OUT14 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__SDMA_DEBUG_EVT_CHN_3 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__GPIO_3_12 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__TPSMP_HDATA_26 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__SRC_BT_CFG_12 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__WEIM_WEIM_DA_A_13 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__IPU1_DI1_D0_CS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 2, 0x07EC, 1), /* MX6Q_PAD_EIM_DA13__CCM_DI1_EXT_CLK */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__MIPI_CORE_DPHY_OUT15 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__SDMA_DEBUG_EVT_CHN_4 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__GPIO_3_13 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__TPSMP_HDATA_27 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__SRC_BT_CFG_13 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__WEIM_WEIM_DA_A_14 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__IPU1_DI1_D1_CS */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__CCM_DI0_EXT_CLK */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__MIPI_CORE_DPHY_OUT16 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__SDMA_DEBUG_EVT_CHN_5 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__GPIO_3_14 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__TPSMP_HDATA_28 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__SRC_BT_CFG_14 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__WEIM_WEIM_DA_A_15 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN1 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN4 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__MIPI_CORE_DPHY_OUT17 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__GPIO_3_15 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__TPSMP_HDATA_29 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__SRC_BT_CFG_15 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_WAIT, 0x0468, 0x0154, 0, 0x0000, 0), /* MX6Q_PAD_EIM_WAIT__WEIM_WEIM_WAIT */
+ IMX_PIN_REG(MX6Q_PAD_EIM_WAIT, 0x0468, 0x0154, 1, 0x0000, 0), /* MX6Q_PAD_EIM_WAIT__WEIM_WEIM_DTACK_B */
+ IMX_PIN_REG(MX6Q_PAD_EIM_WAIT, 0x0468, 0x0154, 5, 0x0000, 0), /* MX6Q_PAD_EIM_WAIT__GPIO_5_0 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_WAIT, 0x0468, 0x0154, 6, 0x0000, 0), /* MX6Q_PAD_EIM_WAIT__TPSMP_HDATA_30 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_WAIT, 0x0468, 0x0154, 7, 0x0000, 0), /* MX6Q_PAD_EIM_WAIT__SRC_BT_CFG_25 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_BCLK, 0x046C, 0x0158, 0, 0x0000, 0), /* MX6Q_PAD_EIM_BCLK__WEIM_WEIM_BCLK */
+ IMX_PIN_REG(MX6Q_PAD_EIM_BCLK, 0x046C, 0x0158, 1, 0x0000, 0), /* MX6Q_PAD_EIM_BCLK__IPU1_DI1_PIN16 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_BCLK, 0x046C, 0x0158, 5, 0x0000, 0), /* MX6Q_PAD_EIM_BCLK__GPIO_6_31 */
+ IMX_PIN_REG(MX6Q_PAD_EIM_BCLK, 0x046C, 0x0158, 6, 0x0000, 0), /* MX6Q_PAD_EIM_BCLK__TPSMP_HDATA_31 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_DISP_CLK, 0x0470, 0x015C, 0, 0x0000, 0), /* MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DSP_CLK */
+ IMX_PIN_REG(MX6Q_PAD_DI0_DISP_CLK, 0x0470, 0x015C, 1, 0x0000, 0), /* MX6Q_PAD_DI0_DISP_CLK__IPU2_DI0_DSP_CLK */
+ IMX_PIN_REG(MX6Q_PAD_DI0_DISP_CLK, 0x0470, 0x015C, 3, 0x0000, 0), /* MX6Q_PAD_DI0_DISP_CLK__MIPI_CR_DPY_OT28 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_DISP_CLK, 0x0470, 0x015C, 4, 0x0000, 0), /* MX6Q_PAD_DI0_DISP_CLK__SDMA_DBG_CR_STA0 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_DISP_CLK, 0x0470, 0x015C, 5, 0x0000, 0), /* MX6Q_PAD_DI0_DISP_CLK__GPIO_4_16 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_DISP_CLK, 0x0470, 0x015C, 6, 0x0000, 0), /* MX6Q_PAD_DI0_DISP_CLK__MMDC_DEBUG_0 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 0, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 1, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__IPU2_DI0_PIN15 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 2, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__AUDMUX_AUD6_TXC */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 3, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__MIPI_CR_DPHY_OUT_29 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 4, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__SDMA_DBG_CORE_STA_1 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 5, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__GPIO_4_17 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 6, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__MMDC_MMDC_DEBUG_1 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 0, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN2 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 1, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__IPU2_DI0_PIN2 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 2, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__AUDMUX_AUD6_TXD */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 3, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__MIPI_CR_DPHY_OUT_30 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 4, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__SDMA_DBG_CORE_STA_2 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 5, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__GPIO_4_18 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 6, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__MMDC_DEBUG_2 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 7, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__PL301_PER1_HADDR_9 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 0, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN3 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 1, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__IPU2_DI0_PIN3 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 2, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 3, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__MIPI_CORE_DPHY_OUT31 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 4, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__SDMA_DBG_CORE_STA_3 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 5, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__GPIO_4_19 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 6, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__MMDC_MMDC_DEBUG_3 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 7, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__PL301_PER1_HADDR_10 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 0, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__IPU1_DI0_PIN4 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 1, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__IPU2_DI0_PIN4 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 2, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__AUDMUX_AUD6_RXD */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 3, 0x094C, 0), /* MX6Q_PAD_DI0_PIN4__USDHC1_WP */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 4, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__SDMA_DEBUG_YIELD */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 5, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__GPIO_4_20 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 6, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__MMDC_MMDC_DEBUG_4 */
+ IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 7, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__PL301_PER1_HADDR_11 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__IPU2_DISP0_DAT_0 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__ECSPI3_SCLK */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__USDHC1_USDHC_DBG_0 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__SDMA_DBG_CORE_RUN */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__GPIO_4_21 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__MMDC_MMDC_DEBUG_5 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__IPU2_DISP0_DAT_1 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__ECSPI3_MOSI */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__USDHC1_USDHC_DBG_1 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__SDMA_DBG_EVT_CHNSL */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__GPIO_4_22 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__MMDC_DEBUG_6 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__PL301_PER1_HADR_12 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__IPU2_DISP0_DAT_2 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__ECSPI3_MISO */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__USDHC1_USDHC_DBG_2 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__SDMA_DEBUG_MODE */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__GPIO_4_23 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__MMDC_DEBUG_7 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__PL301_PER1_HADR_13 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__IPU2_DISP0_DAT_3 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__ECSPI3_SS0 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__USDHC1_USDHC_DBG_3 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__SDMA_DBG_BUS_ERROR */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__GPIO_4_24 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__MMDC_MMDC_DBG_8 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__PL301_PER1_HADR_14 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__IPU2_DISP0_DAT_4 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__ECSPI3_SS1 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__USDHC1_USDHC_DBG_4 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__GPIO_4_25 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__MMDC_MMDC_DEBUG_9 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__PL301_PER1_HADR_15 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__IPU2_DISP0_DAT_5 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__ECSPI3_SS2 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__AUDMUX_AUD6_RXFS */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__SDMA_DBG_MCH_DMBUS */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__GPIO_4_26 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__MMDC_DEBUG_10 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__PL301_PER1_HADR_16 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__IPU2_DISP0_DAT_6 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__ECSPI3_SS3 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__AUDMUX_AUD6_RXC */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__SDMA_DBG_RTBUF_WRT */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__GPIO_4_27 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__MMDC_DEBUG_11 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__PL301_PER1_HADR_17 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__IPU2_DISP0_DAT_7 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__ECSPI3_RDY */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__USDHC1_USDHC_DBG_5 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__SDMA_DBG_EVT_CHN_0 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__GPIO_4_28 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__MMDC_DEBUG_12 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__PL301_PER1_HADR_18 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__IPU2_DISP0_DAT_8 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__PWM1_PWMO */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__WDOG1_WDOG_B */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__SDMA_DBG_EVT_CHN_1 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__GPIO_4_29 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__MMDC_DEBUG_13 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__PL301_PER1_HADR_19 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__IPU2_DISP0_DAT_9 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__PWM2_PWMO */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__WDOG2_WDOG_B */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__SDMA_DBG_EVT_CHN_2 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__GPIO_4_30 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__MMDC_DEBUG_14 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__PL301_PER1_HADR_20 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__IPU2_DISP0_DAT_10 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__USDHC1_DBG_6 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__SDMA_DBG_EVT_CHN3 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__GPIO_4_31 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__MMDC_DEBUG_15 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__PL301_PER1_HADR21 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__IPU2_DISP0_DAT_11 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__USDHC1_USDHC_DBG7 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__SDMA_DBG_EVT_CHN4 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__GPIO_5_5 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__MMDC_DEBUG_16 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__PL301_PER1_HADR22 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__IPU2_DISP0_DAT_12 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__RESERVED_RESERVED */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__SDMA_DBG_EVT_CHN5 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__GPIO_5_6 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__MMDC_DEBUG_17 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__PL301_PER1_HADR23 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT13__IPU2_DISP0_DAT_13 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 3, 0x07D8, 1), /* MX6Q_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT13__SDMA_DBG_EVT_CHN0 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT13__GPIO_5_7 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT13__MMDC_DEBUG_18 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT13__PL301_PER1_HADR24 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT14, 0x04BC, 0x01A8, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT14, 0x04BC, 0x01A8, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT14__IPU2_DISP0_DAT_14 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT14, 0x04BC, 0x01A8, 3, 0x07D4, 1), /* MX6Q_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT14, 0x04BC, 0x01A8, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT14__SDMA_DBG_EVT_CHN1 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT14, 0x04BC, 0x01A8, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT14__GPIO_5_8 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT14, 0x04BC, 0x01A8, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT14__MMDC_DEBUG_19 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT15__IPU2_DISP0_DAT_15 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 2, 0x0804, 1), /* MX6Q_PAD_DISP0_DAT15__ECSPI1_SS1 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 3, 0x0820, 1), /* MX6Q_PAD_DISP0_DAT15__ECSPI2_SS1 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT15__SDMA_DBG_EVT_CHN2 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT15__GPIO_5_9 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT15__MMDC_DEBUG_20 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT15__PL301_PER1_HADR25 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT16__IPU2_DISP0_DAT_16 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 2, 0x0818, 1), /* MX6Q_PAD_DISP0_DAT16__ECSPI2_MOSI */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 3, 0x07DC, 0), /* MX6Q_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 4, 0x090C, 0), /* MX6Q_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT16__GPIO_5_10 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT16__MMDC_DEBUG_21 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT16__PL301_PER1_HADR26 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT17__IPU2_DISP0_DAT_17 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 2, 0x0814, 1), /* MX6Q_PAD_DISP0_DAT17__ECSPI2_MISO */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 3, 0x07D0, 0), /* MX6Q_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 4, 0x0910, 0), /* MX6Q_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT17__GPIO_5_11 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT17__MMDC_DEBUG_22 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT17__PL301_PER1_HADR27 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT18__IPU2_DISP0_DAT_18 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 2, 0x081C, 1), /* MX6Q_PAD_DISP0_DAT18__ECSPI2_SS0 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 3, 0x07E0, 0), /* MX6Q_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 4, 0x07C0, 0), /* MX6Q_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT18__GPIO_5_12 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT18__MMDC_DEBUG_23 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT18__WEIM_WEIM_CS_2 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT19__IPU2_DISP0_DAT_19 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 2, 0x0810, 1), /* MX6Q_PAD_DISP0_DAT19__ECSPI2_SCLK */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 3, 0x07CC, 0), /* MX6Q_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 4, 0x07BC, 0), /* MX6Q_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT19__GPIO_5_13 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT19__MMDC_DEBUG_24 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT19__WEIM_WEIM_CS_3 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT20__IPU2_DISP0_DAT_20 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 2, 0x07F4, 1), /* MX6Q_PAD_DISP0_DAT20__ECSPI1_SCLK */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 3, 0x07C4, 0), /* MX6Q_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT20__SDMA_DBG_EVT_CHN7 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT20__GPIO_5_14 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT20__MMDC_DEBUG_25 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT20__PL301_PER1_HADR28 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT21__IPU2_DISP0_DAT_21 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 2, 0x07FC, 1), /* MX6Q_PAD_DISP0_DAT21__ECSPI1_MOSI */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 3, 0x07B8, 1), /* MX6Q_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT21__SDMA_DBG_BUS_DEV0 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT21__GPIO_5_15 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT21__MMDC_DEBUG_26 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT21__PL301_PER1_HADR29 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT22__IPU2_DISP0_DAT_22 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 2, 0x07F8, 1), /* MX6Q_PAD_DISP0_DAT22__ECSPI1_MISO */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 3, 0x07C8, 1), /* MX6Q_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT22__SDMA_DBG_BUS_DEV1 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT22__GPIO_5_16 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT22__MMDC_DEBUG_27 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT22__PL301_PER1_HADR30 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT23__IPU2_DISP0_DAT_23 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 2, 0x0800, 1), /* MX6Q_PAD_DISP0_DAT23__ECSPI1_SS0 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 3, 0x07B4, 1), /* MX6Q_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT23__SDMA_DBG_BUS_DEV2 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT23__GPIO_5_17 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT23__MMDC_DEBUG_28 */
+ IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT23__PL301_PER1_HADR31 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 0, 0x0000, 0), /* MX6Q_PAD_ENET_MDIO__RESERVED_RESERVED */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 1, 0x0840, 0), /* MX6Q_PAD_ENET_MDIO__ENET_MDIO */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 2, 0x086C, 0), /* MX6Q_PAD_ENET_MDIO__ESAI1_SCKR */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 3, 0x0000, 0), /* MX6Q_PAD_ENET_MDIO__SDMA_DEBUG_BUS_DEV3 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 4, 0x0000, 0), /* MX6Q_PAD_ENET_MDIO__ENET_1588_EVT1_OUT */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 5, 0x0000, 0), /* MX6Q_PAD_ENET_MDIO__GPIO_1_22 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 6, 0x0000, 0), /* MX6Q_PAD_ENET_MDIO__SPDIF_PLOCK */
+ IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 0, 0x0000, 0), /* MX6Q_PAD_ENET_REF_CLK__RESERVED_RSRVED */
+ IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 1, 0x0000, 0), /* MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK */
+ IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 2, 0x085C, 0), /* MX6Q_PAD_ENET_REF_CLK__ESAI1_FSR */
+ IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 3, 0x0000, 0), /* MX6Q_PAD_ENET_REF_CLK__SDMA_DBGBUS_DEV4 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 5, 0x0000, 0), /* MX6Q_PAD_ENET_REF_CLK__GPIO_1_23 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 6, 0x0000, 0), /* MX6Q_PAD_ENET_REF_CLK__SPDIF_SRCLK */
+ IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 7, 0x0000, 0), /* MX6Q_PAD_ENET_REF_CLK__USBPHY1_RX_SQH */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 1, 0x0000, 0), /* MX6Q_PAD_ENET_RX_ER__ENET_RX_ER */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 2, 0x0864, 0), /* MX6Q_PAD_ENET_RX_ER__ESAI1_HCKR */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 3, 0x0914, 1), /* MX6Q_PAD_ENET_RX_ER__SPDIF_IN1 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 4, 0x0000, 0), /* MX6Q_PAD_ENET_RX_ER__ENET_1588_EVT2_OUT */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 5, 0x0000, 0), /* MX6Q_PAD_ENET_RX_ER__GPIO_1_24 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 6, 0x0000, 0), /* MX6Q_PAD_ENET_RX_ER__PHY_TDI */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 7, 0x0000, 0), /* MX6Q_PAD_ENET_RX_ER__USBPHY1_RX_HS_RXD */
+ IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 0, 0x0000, 0), /* MX6Q_PAD_ENET_CRS_DV__RESERVED_RSRVED */
+ IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 1, 0x0858, 1), /* MX6Q_PAD_ENET_CRS_DV__ENET_RX_EN */
+ IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 2, 0x0870, 0), /* MX6Q_PAD_ENET_CRS_DV__ESAI1_SCKT */
+ IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 3, 0x0918, 1), /* MX6Q_PAD_ENET_CRS_DV__SPDIF_EXTCLK */
+ IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 5, 0x0000, 0), /* MX6Q_PAD_ENET_CRS_DV__GPIO_1_25 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 6, 0x0000, 0), /* MX6Q_PAD_ENET_CRS_DV__PHY_TDO */
+ IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 7, 0x0000, 0), /* MX6Q_PAD_ENET_CRS_DV__USBPHY1_RX_FS_RXD */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 0, 0x0908, 0), /* MX6Q_PAD_ENET_RXD1__MLB_MLBSIG */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 1, 0x084C, 1), /* MX6Q_PAD_ENET_RXD1__ENET_RDATA_1 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 2, 0x0860, 0), /* MX6Q_PAD_ENET_RXD1__ESAI1_FST */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 4, 0x0000, 0), /* MX6Q_PAD_ENET_RXD1__ENET_1588_EVT3_OUT */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 5, 0x0000, 0), /* MX6Q_PAD_ENET_RXD1__GPIO_1_26 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 6, 0x0000, 0), /* MX6Q_PAD_ENET_RXD1__PHY_TCK */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 7, 0x0000, 0), /* MX6Q_PAD_ENET_RXD1__USBPHY1_RX_DISCON */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 0, 0x0000, 0), /* MX6Q_PAD_ENET_RXD0__OSC32K_32K_OUT */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 1, 0x0848, 1), /* MX6Q_PAD_ENET_RXD0__ENET_RDATA_0 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 2, 0x0868, 0), /* MX6Q_PAD_ENET_RXD0__ESAI1_HCKT */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 3, 0x0000, 0), /* MX6Q_PAD_ENET_RXD0__SPDIF_OUT1 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 5, 0x0000, 0), /* MX6Q_PAD_ENET_RXD0__GPIO_1_27 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 6, 0x0000, 0), /* MX6Q_PAD_ENET_RXD0__PHY_TMS */
+ IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 7, 0x0000, 0), /* MX6Q_PAD_ENET_RXD0__USBPHY1_PLL_CK20DIV */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TX_EN, 0x04FC, 0x01E8, 0, 0x0000, 0), /* MX6Q_PAD_ENET_TX_EN__RESERVED_RSRVED */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TX_EN, 0x04FC, 0x01E8, 1, 0x0000, 0), /* MX6Q_PAD_ENET_TX_EN__ENET_TX_EN */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TX_EN, 0x04FC, 0x01E8, 2, 0x0880, 0), /* MX6Q_PAD_ENET_TX_EN__ESAI1_TX3_RX2 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TX_EN, 0x04FC, 0x01E8, 5, 0x0000, 0), /* MX6Q_PAD_ENET_TX_EN__GPIO_1_28 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TX_EN, 0x04FC, 0x01E8, 6, 0x0000, 0), /* MX6Q_PAD_ENET_TX_EN__SATA_PHY_TDI */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TX_EN, 0x04FC, 0x01E8, 7, 0x0000, 0), /* MX6Q_PAD_ENET_TX_EN__USBPHY2_RX_SQH */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 0, 0x0900, 0), /* MX6Q_PAD_ENET_TXD1__MLB_MLBCLK */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 1, 0x0000, 0), /* MX6Q_PAD_ENET_TXD1__ENET_TDATA_1 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 2, 0x087C, 0), /* MX6Q_PAD_ENET_TXD1__ESAI1_TX2_RX3 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 4, 0x0000, 0), /* MX6Q_PAD_ENET_TXD1__ENET_1588_EVENT0_IN */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 5, 0x0000, 0), /* MX6Q_PAD_ENET_TXD1__GPIO_1_29 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 6, 0x0000, 0), /* MX6Q_PAD_ENET_TXD1__SATA_PHY_TDO */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 7, 0x0000, 0), /* MX6Q_PAD_ENET_TXD1__USBPHY2_RX_HS_RXD */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TXD0, 0x0504, 0x01F0, 0, 0x0000, 0), /* MX6Q_PAD_ENET_TXD0__RESERVED_RSRVED */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TXD0, 0x0504, 0x01F0, 1, 0x0000, 0), /* MX6Q_PAD_ENET_TXD0__ENET_TDATA_0 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TXD0, 0x0504, 0x01F0, 2, 0x0884, 0), /* MX6Q_PAD_ENET_TXD0__ESAI1_TX4_RX1 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TXD0, 0x0504, 0x01F0, 5, 0x0000, 0), /* MX6Q_PAD_ENET_TXD0__GPIO_1_30 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TXD0, 0x0504, 0x01F0, 6, 0x0000, 0), /* MX6Q_PAD_ENET_TXD0__SATA_PHY_TCK */
+ IMX_PIN_REG(MX6Q_PAD_ENET_TXD0, 0x0504, 0x01F0, 7, 0x0000, 0), /* MX6Q_PAD_ENET_TXD0__USBPHY2_RX_FS_RXD */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 0, 0x0904, 0), /* MX6Q_PAD_ENET_MDC__MLB_MLBDAT */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 1, 0x0000, 0), /* MX6Q_PAD_ENET_MDC__ENET_MDC */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 2, 0x0888, 0), /* MX6Q_PAD_ENET_MDC__ESAI1_TX5_RX0 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 4, 0x0000, 0), /* MX6Q_PAD_ENET_MDC__ENET_1588_EVENT1_IN */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 5, 0x0000, 0), /* MX6Q_PAD_ENET_MDC__GPIO_1_31 */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 6, 0x0000, 0), /* MX6Q_PAD_ENET_MDC__SATA_PHY_TMS */
+ IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 7, 0x0000, 0), /* MX6Q_PAD_ENET_MDC__USBPHY2_RX_DISCON */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D40, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D40__MMDC_DRAM_D_40 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D41, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D41__MMDC_DRAM_D_41 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D42, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D42__MMDC_DRAM_D_42 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D43, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D43__MMDC_DRAM_D_43 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D44, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D44__MMDC_DRAM_D_44 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D45, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D45__MMDC_DRAM_D_45 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D46, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D46__MMDC_DRAM_D_46 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D47, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D47__MMDC_DRAM_D_47 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS5, 0x050C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS5__MMDC_DRAM_SDQS_5 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_DQM5, 0x0510, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM5__MMDC_DRAM_DQM_5 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D32, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D32__MMDC_DRAM_D_32 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D33, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D33__MMDC_DRAM_D_33 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D34, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D34__MMDC_DRAM_D_34 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D35, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D35__MMDC_DRAM_D_35 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D36, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D36__MMDC_DRAM_D_36 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D37, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D37__MMDC_DRAM_D_37 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D38, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D38__MMDC_DRAM_D_38 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D39, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D39__MMDC_DRAM_D_39 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_DQM4, 0x0514, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM4__MMDC_DRAM_DQM_4 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS4, 0x0518, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS4__MMDC_DRAM_SDQS_4 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D24, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D24__MMDC_DRAM_D_24 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D25, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D25__MMDC_DRAM_D_25 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D26, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D26__MMDC_DRAM_D_26 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D27, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D27__MMDC_DRAM_D_27 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D28, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D28__MMDC_DRAM_D_28 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D29, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D29__MMDC_DRAM_D_29 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS3, 0x051C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS3__MMDC_DRAM_SDQS_3 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D30, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D30__MMDC_DRAM_D_30 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D31, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D31__MMDC_DRAM_D_31 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_DQM3, 0x0520, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM3__MMDC_DRAM_DQM_3 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D16, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D16__MMDC_DRAM_D_16 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D17, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D17__MMDC_DRAM_D_17 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D18, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D18__MMDC_DRAM_D_18 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D19, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D19__MMDC_DRAM_D_19 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D20, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D20__MMDC_DRAM_D_20 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D21, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D21__MMDC_DRAM_D_21 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D22, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D22__MMDC_DRAM_D_22 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS2, 0x0524, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS2__MMDC_DRAM_SDQS_2 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D23, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D23__MMDC_DRAM_D_23 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_DQM2, 0x0528, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM2__MMDC_DRAM_DQM_2 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A0, 0x052C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A0__MMDC_DRAM_A_0 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A1, 0x0530, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A1__MMDC_DRAM_A_1 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A2, 0x0534, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A2__MMDC_DRAM_A_2 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A3, 0x0538, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A3__MMDC_DRAM_A_3 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A4, 0x053C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A4__MMDC_DRAM_A_4 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A5, 0x0540, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A5__MMDC_DRAM_A_5 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A6, 0x0544, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A6__MMDC_DRAM_A_6 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A7, 0x0548, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A7__MMDC_DRAM_A_7 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A8, 0x054C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A8__MMDC_DRAM_A_8 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A9, 0x0550, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A9__MMDC_DRAM_A_9 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A10, 0x0554, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A10__MMDC_DRAM_A_10 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A11, 0x0558, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A11__MMDC_DRAM_A_11 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A12, 0x055C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A12__MMDC_DRAM_A_12 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A13, 0x0560, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A13__MMDC_DRAM_A_13 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A14, 0x0564, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A14__MMDC_DRAM_A_14 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_A15, 0x0568, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A15__MMDC_DRAM_A_15 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_CAS, 0x056C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_CAS__MMDC_DRAM_CAS */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_CS0, 0x0570, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_CS0__MMDC_DRAM_CS_0 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_CS1, 0x0574, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_CS1__MMDC_DRAM_CS_1 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_RAS, 0x0578, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_RAS__MMDC_DRAM_RAS */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_RESET, 0x057C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_RESET__MMDC_DRAM_RESET */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDBA0, 0x0580, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDBA0__MMDC_DRAM_SDBA_0 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDBA1, 0x0584, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDBA1__MMDC_DRAM_SDBA_1 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDCLK_0, 0x0588, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDCLK_0__MMDC_DRAM_SDCLK0 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDBA2, 0x058C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDBA2__MMDC_DRAM_SDBA_2 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDCKE0, 0x0590, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDCKE0__MMDC_DRAM_SDCKE_0 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDCLK_1, 0x0594, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDCLK_1__MMDC_DRAM_SDCLK1 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDCKE1, 0x0598, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDCKE1__MMDC_DRAM_SDCKE_1 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDODT0, 0x059C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDODT0__MMDC_DRAM_ODT_0 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDODT1, 0x05A0, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDODT1__MMDC_DRAM_ODT_1 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDWE, 0x05A4, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDWE__MMDC_DRAM_SDWE */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D0, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D0__MMDC_DRAM_D_0 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D1, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D1__MMDC_DRAM_D_1 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D2, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D2__MMDC_DRAM_D_2 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D3, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D3__MMDC_DRAM_D_3 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D4, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D4__MMDC_DRAM_D_4 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D5, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D5__MMDC_DRAM_D_5 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS0, 0x05A8, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS0__MMDC_DRAM_SDQS_0 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D6, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D6__MMDC_DRAM_D_6 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D7, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D7__MMDC_DRAM_D_7 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_DQM0, 0x05AC, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM0__MMDC_DRAM_DQM_0 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D8, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D8__MMDC_DRAM_D_8 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D9, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D9__MMDC_DRAM_D_9 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D10, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D10__MMDC_DRAM_D_10 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D11, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D11__MMDC_DRAM_D_11 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D12, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D12__MMDC_DRAM_D_12 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D13, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D13__MMDC_DRAM_D_13 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D14, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D14__MMDC_DRAM_D_14 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS1, 0x05B0, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS1__MMDC_DRAM_SDQS_1 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D15, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D15__MMDC_DRAM_D_15 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_DQM1, 0x05B4, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM1__MMDC_DRAM_DQM_1 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D48, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D48__MMDC_DRAM_D_48 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D49, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D49__MMDC_DRAM_D_49 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D50, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D50__MMDC_DRAM_D_50 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D51, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D51__MMDC_DRAM_D_51 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D52, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D52__MMDC_DRAM_D_52 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D53, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D53__MMDC_DRAM_D_53 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D54, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D54__MMDC_DRAM_D_54 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D55, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D55__MMDC_DRAM_D_55 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS6, 0x05B8, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS6__MMDC_DRAM_SDQS_6 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_DQM6, 0x05BC, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM6__MMDC_DRAM_DQM_6 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D56, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D56__MMDC_DRAM_D_56 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS7, 0x05C0, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS7__MMDC_DRAM_SDQS_7 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D57, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D57__MMDC_DRAM_D_57 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D58, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D58__MMDC_DRAM_D_58 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D59, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D59__MMDC_DRAM_D_59 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D60, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D60__MMDC_DRAM_D_60 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_DQM7, 0x05C4, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM7__MMDC_DRAM_DQM_7 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D61, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D61__MMDC_DRAM_D_61 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D62, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D62__MMDC_DRAM_D_62 */
+ IMX_PIN_REG(MX6Q_PAD_DRAM_D63, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D63__MMDC_DRAM_D_63 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 0, 0x07F4, 2), /* MX6Q_PAD_KEY_COL0__ECSPI1_SCLK */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 1, 0x0854, 1), /* MX6Q_PAD_KEY_COL0__ENET_RDATA_3 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 2, 0x07DC, 1), /* MX6Q_PAD_KEY_COL0__AUDMUX_AUD5_TXC */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 3, 0x0000, 0), /* MX6Q_PAD_KEY_COL0__KPP_COL_0 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 4, 0x0000, 0), /* MX6Q_PAD_KEY_COL0__UART4_TXD */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 5, 0x0000, 0), /* MX6Q_PAD_KEY_COL0__GPIO_4_6 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 6, 0x0000, 0), /* MX6Q_PAD_KEY_COL0__DCIC1_DCIC_OUT */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 7, 0x0000, 0), /* MX6Q_PAD_KEY_COL0__SRC_ANY_PU_RST */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 0, 0x07FC, 2), /* MX6Q_PAD_KEY_ROW0__ECSPI1_MOSI */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 1, 0x0000, 0), /* MX6Q_PAD_KEY_ROW0__ENET_TDATA_3 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 2, 0x07D0, 1), /* MX6Q_PAD_KEY_ROW0__AUDMUX_AUD5_TXD */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 3, 0x0000, 0), /* MX6Q_PAD_KEY_ROW0__KPP_ROW_0 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 4, 0x0938, 1), /* MX6Q_PAD_KEY_ROW0__UART4_RXD */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 5, 0x0000, 0), /* MX6Q_PAD_KEY_ROW0__GPIO_4_7 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 6, 0x0000, 0), /* MX6Q_PAD_KEY_ROW0__DCIC2_DCIC_OUT */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 7, 0x0000, 0), /* MX6Q_PAD_KEY_ROW0__PL301_PER1_HADR_0 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 0, 0x07F8, 2), /* MX6Q_PAD_KEY_COL1__ECSPI1_MISO */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 1, 0x0840, 1), /* MX6Q_PAD_KEY_COL1__ENET_MDIO */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 2, 0x07E0, 1), /* MX6Q_PAD_KEY_COL1__AUDMUX_AUD5_TXFS */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 3, 0x0000, 0), /* MX6Q_PAD_KEY_COL1__KPP_COL_1 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 4, 0x0000, 0), /* MX6Q_PAD_KEY_COL1__UART5_TXD */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 5, 0x0000, 0), /* MX6Q_PAD_KEY_COL1__GPIO_4_8 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 6, 0x0000, 0), /* MX6Q_PAD_KEY_COL1__USDHC1_VSELECT */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 7, 0x0000, 0), /* MX6Q_PAD_KEY_COL1__PL301MX_PER1_HADR_1 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 0, 0x0800, 2), /* MX6Q_PAD_KEY_ROW1__ECSPI1_SS0 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 1, 0x0000, 0), /* MX6Q_PAD_KEY_ROW1__ENET_COL */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 2, 0x07CC, 1), /* MX6Q_PAD_KEY_ROW1__AUDMUX_AUD5_RXD */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 3, 0x0000, 0), /* MX6Q_PAD_KEY_ROW1__KPP_ROW_1 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 4, 0x0940, 1), /* MX6Q_PAD_KEY_ROW1__UART5_RXD */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 5, 0x0000, 0), /* MX6Q_PAD_KEY_ROW1__GPIO_4_9 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 6, 0x0000, 0), /* MX6Q_PAD_KEY_ROW1__USDHC2_VSELECT */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 7, 0x0000, 0), /* MX6Q_PAD_KEY_ROW1__PL301_PER1_HADDR_2 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 0, 0x0804, 2), /* MX6Q_PAD_KEY_COL2__ECSPI1_SS1 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 1, 0x0850, 1), /* MX6Q_PAD_KEY_COL2__ENET_RDATA_2 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 2, 0x0000, 0), /* MX6Q_PAD_KEY_COL2__CAN1_TXCAN */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 3, 0x0000, 0), /* MX6Q_PAD_KEY_COL2__KPP_COL_2 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 4, 0x0000, 0), /* MX6Q_PAD_KEY_COL2__ENET_MDC */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 5, 0x0000, 0), /* MX6Q_PAD_KEY_COL2__GPIO_4_10 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 6, 0x0000, 0), /* MX6Q_PAD_KEY_COL2__USBOH3_H1_PWRCTL_WKP */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 7, 0x0000, 0), /* MX6Q_PAD_KEY_COL2__PL301_PER1_HADDR_3 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 0, 0x0808, 1), /* MX6Q_PAD_KEY_ROW2__ECSPI1_SS2 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 1, 0x0000, 0), /* MX6Q_PAD_KEY_ROW2__ENET_TDATA_2 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 2, 0x07E4, 0), /* MX6Q_PAD_KEY_ROW2__CAN1_RXCAN */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 3, 0x0000, 0), /* MX6Q_PAD_KEY_ROW2__KPP_ROW_2 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 4, 0x0000, 0), /* MX6Q_PAD_KEY_ROW2__USDHC2_VSELECT */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 5, 0x0000, 0), /* MX6Q_PAD_KEY_ROW2__GPIO_4_11 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 6, 0x088C, 1), /* MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 7, 0x0000, 0), /* MX6Q_PAD_KEY_ROW2__PL301_PER1_HADR_4 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 0, 0x080C, 1), /* MX6Q_PAD_KEY_COL3__ECSPI1_SS3 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 1, 0x0000, 0), /* MX6Q_PAD_KEY_COL3__ENET_CRS */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 2, 0x0890, 1), /* MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 3, 0x0000, 0), /* MX6Q_PAD_KEY_COL3__KPP_COL_3 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 4, 0x08A0, 1), /* MX6Q_PAD_KEY_COL3__I2C2_SCL */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 5, 0x0000, 0), /* MX6Q_PAD_KEY_COL3__GPIO_4_12 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 6, 0x0914, 2), /* MX6Q_PAD_KEY_COL3__SPDIF_IN1 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 7, 0x0000, 0), /* MX6Q_PAD_KEY_COL3__PL301_PER1_HADR_5 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 0, 0x0000, 0), /* MX6Q_PAD_KEY_ROW3__OSC32K_32K_OUT */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 1, 0x07B0, 0), /* MX6Q_PAD_KEY_ROW3__ASRC_ASRC_EXT_CLK */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 2, 0x0894, 1), /* MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 3, 0x0000, 0), /* MX6Q_PAD_KEY_ROW3__KPP_ROW_3 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 4, 0x08A4, 1), /* MX6Q_PAD_KEY_ROW3__I2C2_SDA */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 5, 0x0000, 0), /* MX6Q_PAD_KEY_ROW3__GPIO_4_13 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 6, 0x0000, 0), /* MX6Q_PAD_KEY_ROW3__USDHC1_VSELECT */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 7, 0x0000, 0), /* MX6Q_PAD_KEY_ROW3__PL301_PER1_HADR_6 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 0, 0x0000, 0), /* MX6Q_PAD_KEY_COL4__CAN2_TXCAN */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 1, 0x0000, 0), /* MX6Q_PAD_KEY_COL4__IPU1_SISG_4 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 2, 0x0944, 1), /* MX6Q_PAD_KEY_COL4__USBOH3_USBOTG_OC */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 3, 0x0000, 0), /* MX6Q_PAD_KEY_COL4__KPP_COL_4 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 4, 0x093C, 0), /* MX6Q_PAD_KEY_COL4__UART5_RTS */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 5, 0x0000, 0), /* MX6Q_PAD_KEY_COL4__GPIO_4_14 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 6, 0x0000, 0), /* MX6Q_PAD_KEY_COL4__MMDC_DEBUG_49 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 7, 0x0000, 0), /* MX6Q_PAD_KEY_COL4__PL301_PER1_HADDR_7 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 0, 0x07E8, 0), /* MX6Q_PAD_KEY_ROW4__CAN2_RXCAN */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 1, 0x0000, 0), /* MX6Q_PAD_KEY_ROW4__IPU1_SISG_5 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 2, 0x0000, 0), /* MX6Q_PAD_KEY_ROW4__USBOH3_USBOTG_PWR */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 3, 0x0000, 0), /* MX6Q_PAD_KEY_ROW4__KPP_ROW_4 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 4, 0x093C, 1), /* MX6Q_PAD_KEY_ROW4__UART5_CTS */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 5, 0x0000, 0), /* MX6Q_PAD_KEY_ROW4__GPIO_4_15 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 6, 0x0000, 0), /* MX6Q_PAD_KEY_ROW4__MMDC_DEBUG_50 */
+ IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 7, 0x0000, 0), /* MX6Q_PAD_KEY_ROW4__PL301_PER1_HADR_8 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 0, 0x0000, 0), /* MX6Q_PAD_GPIO_0__CCM_CLKO */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 2, 0x08E8, 0), /* MX6Q_PAD_GPIO_0__KPP_COL_5 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 3, 0x07B0, 1), /* MX6Q_PAD_GPIO_0__ASRC_ASRC_EXT_CLK */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_0__EPIT1_EPITO */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_0__GPIO_1_0 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_0__USBOH3_USBH1_PWR */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_0__SNVS_HP_WRAP_SNVS_VIO5 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 0, 0x086C, 1), /* MX6Q_PAD_GPIO_1__ESAI1_SCKR */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_1__WDOG2_WDOG_B */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 2, 0x08F4, 0), /* MX6Q_PAD_GPIO_1__KPP_ROW_5 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_1__PWM2_PWMO */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_1__GPIO_1_1 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_1__USDHC1_CD */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_1__SRC_TESTER_ACK */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 0, 0x085C, 1), /* MX6Q_PAD_GPIO_9__ESAI1_FSR */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_9__WDOG1_WDOG_B */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 2, 0x08EC, 0), /* MX6Q_PAD_GPIO_9__KPP_COL_6 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_9__CCM_REF_EN_B */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_9__PWM1_PWMO */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_9__GPIO_1_9 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 6, 0x094C, 1), /* MX6Q_PAD_GPIO_9__USDHC1_WP */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_9__SRC_EARLY_RST */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 0, 0x0864, 1), /* MX6Q_PAD_GPIO_3__ESAI1_HCKR */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_3__OBSERVE_MUX_INT_OUT0 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 2, 0x08A8, 1), /* MX6Q_PAD_GPIO_3__I2C3_SCL */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_3__ANATOP_24M_OUT */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_3__CCM_CLKO2 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_3__GPIO_1_3 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 6, 0x0948, 1), /* MX6Q_PAD_GPIO_3__USBOH3_USBH1_OC */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 7, 0x0900, 1), /* MX6Q_PAD_GPIO_3__MLB_MLBCLK */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 0, 0x0870, 1), /* MX6Q_PAD_GPIO_6__ESAI1_SCKT */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_6__OBSERVE_MUX_INT_OUT1 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 2, 0x08AC, 1), /* MX6Q_PAD_GPIO_6__I2C3_SDA */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_6__CCM_CCM_OUT_0 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_6__CSU_CSU_INT_DEB */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_6__GPIO_1_6 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_6__USDHC2_LCTL */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 7, 0x0908, 1), /* MX6Q_PAD_GPIO_6__MLB_MLBSIG */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 0, 0x0860, 1), /* MX6Q_PAD_GPIO_2__ESAI1_FST */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_2__OBSERVE_MUX_INT_OUT2 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 2, 0x08F8, 1), /* MX6Q_PAD_GPIO_2__KPP_ROW_6 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_2__CCM_CCM_OUT_1 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_2__GPIO_1_2 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_2__USDHC2_WP */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 7, 0x0904, 1), /* MX6Q_PAD_GPIO_2__MLB_MLBDAT */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 0, 0x0868, 1), /* MX6Q_PAD_GPIO_4__ESAI1_HCKT */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_4__OBSERVE_MUX_INT_OUT3 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 2, 0x08F0, 1), /* MX6Q_PAD_GPIO_4__KPP_COL_7 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_4__CCM_CCM_OUT_2 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_4__GPIO_1_4 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_4__USDHC2_CD */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_4__OCOTP_CRL_WRAR_FUSE_LA */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 0, 0x087C, 1), /* MX6Q_PAD_GPIO_5__ESAI1_TX2_RX3 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_5__OBSERVE_MUX_INT_OUT4 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 2, 0x08FC, 1), /* MX6Q_PAD_GPIO_5__KPP_ROW_7 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_5__CCM_CLKO */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_5__GPIO_1_5 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 6, 0x08A8, 2), /* MX6Q_PAD_GPIO_5__I2C3_SCL */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_5__CHEETAH_EVENTI */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 0, 0x0884, 1), /* MX6Q_PAD_GPIO_7__ESAI1_TX4_RX1 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_7__ECSPI5_RDY */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 2, 0x0000, 0), /* MX6Q_PAD_GPIO_7__EPIT1_EPITO */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_7__CAN1_TXCAN */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_7__UART2_TXD */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_7__GPIO_1_7 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_7__SPDIF_PLOCK */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_7__USBOH3_OTGUSB_HST_MODE */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 0, 0x0888, 1), /* MX6Q_PAD_GPIO_8__ESAI1_TX5_RX0 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_8__ANATOP_ANATOP_32K_OUT */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 2, 0x0000, 0), /* MX6Q_PAD_GPIO_8__EPIT2_EPITO */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 3, 0x07E4, 1), /* MX6Q_PAD_GPIO_8__CAN1_RXCAN */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 4, 0x0928, 3), /* MX6Q_PAD_GPIO_8__UART2_RXD */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_8__GPIO_1_8 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_8__SPDIF_SRCLK */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_8__USBOH3_OTG_PWRCTL_WAK */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 0, 0x0880, 1), /* MX6Q_PAD_GPIO_16__ESAI1_TX3_RX2 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_16__ENET_1588_EVENT2_IN */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 2, 0x083C, 1), /* MX6Q_PAD_GPIO_16__ENET_ETHERNET_REF_OUT */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_16__USDHC1_LCTL */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 4, 0x0914, 3), /* MX6Q_PAD_GPIO_16__SPDIF_IN1 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_16__GPIO_7_11 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 6, 0x08AC, 2), /* MX6Q_PAD_GPIO_16__I2C3_SDA */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_16__SJC_DE_B */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 0, 0x0874, 0), /* MX6Q_PAD_GPIO_17__ESAI1_TX0 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_17__ENET_1588_EVENT3_IN */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 2, 0x07F0, 1), /* MX6Q_PAD_GPIO_17__CCM_PMIC_RDY */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 3, 0x090C, 1), /* MX6Q_PAD_GPIO_17__SDMA_SDMA_EXT_EVENT_0 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_17__SPDIF_OUT1 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_17__GPIO_7_12 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_17__SJC_JTAG_ACT */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 0, 0x0878, 0), /* MX6Q_PAD_GPIO_18__ESAI1_TX1 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 1, 0x0844, 1), /* MX6Q_PAD_GPIO_18__ENET_RX_CLK */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 2, 0x0000, 0), /* MX6Q_PAD_GPIO_18__USDHC3_VSELECT */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 3, 0x0910, 1), /* MX6Q_PAD_GPIO_18__SDMA_SDMA_EXT_EVENT_1 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 4, 0x07B0, 2), /* MX6Q_PAD_GPIO_18__ASRC_ASRC_EXT_CLK */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_18__GPIO_7_13 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_18__SNVS_HP_WRA_SNVS_VIO5 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_18__SRC_SYSTEM_RST */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 0, 0x08E8, 1), /* MX6Q_PAD_GPIO_19__KPP_COL_5 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_19__ENET_1588_EVENT0_OUT */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 2, 0x0000, 0), /* MX6Q_PAD_GPIO_19__SPDIF_OUT1 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_19__CCM_CLKO */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_19__ECSPI1_RDY */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_19__GPIO_4_5 */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_19__ENET_TX_ER */
+ IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_19__SRC_INT_BOOT */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_PIXCLK, 0x0628, 0x0258, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_PIXCLK, 0x0628, 0x0258, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_PIXCLK__PCIE_CTRL_MUX_12 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_PIXCLK, 0x0628, 0x0258, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_PIXCLK, 0x0628, 0x0258, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_PIXCLK__GPIO_5_18 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_PIXCLK, 0x0628, 0x0258, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_PIXCLK___MMDC_DEBUG_29 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_PIXCLK, 0x0628, 0x0258, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_PIXCLK__CHEETAH_EVENTO */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__PCIE_CTRL_MUX_13 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 3, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__CCM_CLKO */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__GPIO_5_19 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__MMDC_MMDC_DEBUG_30 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__CHEETAH_TRCTL */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__IPU1_CSI0_DA_EN */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__WEIM_WEIM_D_0 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__PCIE_CTRL_MUX_14 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__GPIO_5_20 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__MMDC_DEBUG_31 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__CHEETAH_TRCLK */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__WEIM_WEIM_D_1 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__PCIE_CTRL_MUX_15 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__GPIO_5_21 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__MMDC_DEBUG_32 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__CHEETAH_TRACE_0 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT4__IPU1_CSI0_D_4 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT4__WEIM_WEIM_D_2 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 2, 0x07F4, 3), /* MX6Q_PAD_CSI0_DAT4__ECSPI1_SCLK */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 3, 0x08E8, 2), /* MX6Q_PAD_CSI0_DAT4__KPP_COL_5 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT4__GPIO_5_22 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT4__MMDC_DEBUG_43 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT4__CHEETAH_TRACE_1 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT5__IPU1_CSI0_D_5 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT5__WEIM_WEIM_D_3 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 2, 0x07FC, 3), /* MX6Q_PAD_CSI0_DAT5__ECSPI1_MOSI */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 3, 0x08F4, 1), /* MX6Q_PAD_CSI0_DAT5__KPP_ROW_5 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT5__GPIO_5_23 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT5__MMDC_MMDC_DEBUG_44 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT5__CHEETAH_TRACE_2 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT6__IPU1_CSI0_D_6 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT6__WEIM_WEIM_D_4 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 2, 0x07F8, 3), /* MX6Q_PAD_CSI0_DAT6__ECSPI1_MISO */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 3, 0x08EC, 1), /* MX6Q_PAD_CSI0_DAT6__KPP_COL_6 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT6__GPIO_5_24 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT6__MMDC_MMDC_DEBUG_45 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT6__CHEETAH_TRACE_3 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT7__IPU1_CSI0_D_7 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT7__WEIM_WEIM_D_5 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 2, 0x0800, 3), /* MX6Q_PAD_CSI0_DAT7__ECSPI1_SS0 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 3, 0x08F8, 2), /* MX6Q_PAD_CSI0_DAT7__KPP_ROW_6 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT7__GPIO_5_25 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT7__MMDC_MMDC_DEBUG_46 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT7__CHEETAH_TRACE_4 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT8__IPU1_CSI0_D_8 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT8__WEIM_WEIM_D_6 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 2, 0x0810, 2), /* MX6Q_PAD_CSI0_DAT8__ECSPI2_SCLK */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 3, 0x08F0, 2), /* MX6Q_PAD_CSI0_DAT8__KPP_COL_7 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 4, 0x089C, 1), /* MX6Q_PAD_CSI0_DAT8__I2C1_SDA */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT8__GPIO_5_26 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT8__MMDC_MMDC_DEBUG_47 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT8__CHEETAH_TRACE_5 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT9__IPU1_CSI0_D_9 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT9__WEIM_WEIM_D_7 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 2, 0x0818, 2), /* MX6Q_PAD_CSI0_DAT9__ECSPI2_MOSI */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 3, 0x08FC, 2), /* MX6Q_PAD_CSI0_DAT9__KPP_ROW_7 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 4, 0x0898, 1), /* MX6Q_PAD_CSI0_DAT9__I2C1_SCL */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT9__GPIO_5_27 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT9__MMDC_MMDC_DEBUG_48 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT9__CHEETAH_TRACE_6 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__IPU1_CSI0_D_10 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 2, 0x0814, 2), /* MX6Q_PAD_CSI0_DAT10__ECSPI2_MISO */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 3, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__UART1_TXD */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__GPIO_5_28 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__MMDC_MMDC_DEBUG_33 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__CHEETAH_TRACE_7 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT11__IPU1_CSI0_D_11 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 2, 0x081C, 2), /* MX6Q_PAD_CSI0_DAT11__ECSPI2_SS0 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 3, 0x0920, 1), /* MX6Q_PAD_CSI0_DAT11__UART1_RXD */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT11__GPIO_5_29 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT11__MMDC_MMDC_DEBUG_34 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT11__CHEETAH_TRACE_8 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__WEIM_WEIM_D_8 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__PCIE_CTRL_MUX_16 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 3, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__UART4_TXD */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__GPIO_5_30 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__MMDC_MMDC_DEBUG_35 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__CHEETAH_TRACE_9 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__WEIM_WEIM_D_9 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__PCIE_CTRL_MUX_17 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 3, 0x0938, 3), /* MX6Q_PAD_CSI0_DAT13__UART4_RXD */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__GPIO_5_31 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__MMDC_MMDC_DEBUG_36 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__CHEETAH_TRACE_10 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__WEIM_WEIM_D_10 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__PCIE_CTRL_MUX_18 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 3, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__UART5_TXD */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__GPIO_6_0 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__MMDC_MMDC_DEBUG_37 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__CHEETAH_TRACE_11 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__WEIM_WEIM_D_11 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__PCIE_CTRL_MUX_19 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 3, 0x0940, 3), /* MX6Q_PAD_CSI0_DAT15__UART5_RXD */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__GPIO_6_1 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__MMDC_MMDC_DEBUG_38 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__CHEETAH_TRACE_12 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__WEIM_WEIM_D_12 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__PCIE_CTRL_MUX_20 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 3, 0x0934, 0), /* MX6Q_PAD_CSI0_DAT16__UART4_RTS */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__GPIO_6_2 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__MMDC_MMDC_DEBUG_39 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__CHEETAH_TRACE_13 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__WEIM_WEIM_D_13 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__PCIE_CTRL_MUX_21 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 3, 0x0934, 1), /* MX6Q_PAD_CSI0_DAT17__UART4_CTS */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__GPIO_6_3 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__MMDC_MMDC_DEBUG_40 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__CHEETAH_TRACE_14 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__WEIM_WEIM_D_14 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__PCIE_CTRL_MUX_22 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 3, 0x093C, 2), /* MX6Q_PAD_CSI0_DAT18__UART5_RTS */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__GPIO_6_4 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__MMDC_MMDC_DEBUG_41 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__CHEETAH_TRACE_15 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__WEIM_WEIM_D_15 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__PCIE_CTRL_MUX_23 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 3, 0x093C, 3), /* MX6Q_PAD_CSI0_DAT19__UART5_CTS */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__GPIO_6_5 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__MMDC_MMDC_DEBUG_42 */
+ IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__ANATOP_TESTO_9 */
+ IMX_PIN_REG(MX6Q_PAD_JTAG_TMS, 0x0678, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_JTAG_TMS__SJC_TMS */
+ IMX_PIN_REG(MX6Q_PAD_JTAG_MOD, 0x067C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_JTAG_MOD__SJC_MOD */
+ IMX_PIN_REG(MX6Q_PAD_JTAG_TRSTB, 0x0680, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_JTAG_TRSTB__SJC_TRSTB */
+ IMX_PIN_REG(MX6Q_PAD_JTAG_TDI, 0x0684, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_JTAG_TDI__SJC_TDI */
+ IMX_PIN_REG(MX6Q_PAD_JTAG_TCK, 0x0688, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_JTAG_TCK__SJC_TCK */
+ IMX_PIN_REG(MX6Q_PAD_JTAG_TDO, 0x068C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_JTAG_TDO__SJC_TDO */
+ IMX_PIN_REG(MX6Q_PAD_LVDS1_TX3_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 */
+ IMX_PIN_REG(MX6Q_PAD_LVDS1_TX2_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 */
+ IMX_PIN_REG(MX6Q_PAD_LVDS1_CLK_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK */
+ IMX_PIN_REG(MX6Q_PAD_LVDS1_TX1_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 */
+ IMX_PIN_REG(MX6Q_PAD_LVDS1_TX0_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 */
+ IMX_PIN_REG(MX6Q_PAD_LVDS0_TX3_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 */
+ IMX_PIN_REG(MX6Q_PAD_LVDS0_CLK_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK */
+ IMX_PIN_REG(MX6Q_PAD_LVDS0_TX2_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 */
+ IMX_PIN_REG(MX6Q_PAD_LVDS0_TX1_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 */
+ IMX_PIN_REG(MX6Q_PAD_LVDS0_TX0_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 */
+ IMX_PIN_REG(MX6Q_PAD_TAMPER, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_TAMPER__SNVS_LP_WRAP_SNVS_TD1 */
+ IMX_PIN_REG(MX6Q_PAD_PMIC_ON_REQ, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_PMIC_ON_REQ__SNVS_LPWRAP_WKALM */
+ IMX_PIN_REG(MX6Q_PAD_PMIC_STBY_REQ, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_PMIC_STBY_REQ__CCM_PMIC_STBYRQ */
+ IMX_PIN_REG(MX6Q_PAD_POR_B, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_POR_B__SRC_POR_B */
+ IMX_PIN_REG(MX6Q_PAD_BOOT_MODE1, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_BOOT_MODE1__SRC_BOOT_MODE_1 */
+ IMX_PIN_REG(MX6Q_PAD_RESET_IN_B, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_RESET_IN_B__SRC_RESET_B */
+ IMX_PIN_REG(MX6Q_PAD_BOOT_MODE0, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_BOOT_MODE0__SRC_BOOT_MODE_0 */
+ IMX_PIN_REG(MX6Q_PAD_TEST_MODE, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_TEST_MODE__TCU_TEST_MODE */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__USDHC3_DAT7 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 1, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__UART1_TXD */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__PCIE_CTRL_MUX_24 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__USBOH3_UH3_DFD_OUT_0 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__USBOH3_UH2_DFD_OUT_0 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__GPIO_6_17 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__MIPI_CORE_DPHY_IN_12 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__USBPHY2_CLK20DIV */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__USDHC3_DAT6 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 1, 0x0920, 3), /* MX6Q_PAD_SD3_DAT6__UART1_RXD */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__PCIE_CTRL_MUX_25 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__USBOH3_UH3_DFD_OUT_1 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__USBOH3_UH2_DFD_OUT_1 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__GPIO_6_18 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__MIPI_CORE_DPHY_IN_13 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__ANATOP_TESTO_10 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__USDHC3_DAT5 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 1, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__UART2_TXD */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__PCIE_CTRL_MUX_26 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__USBOH3_UH3_DFD_OUT_2 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__USBOH3_UH2_DFD_OUT_2 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__GPIO_7_0 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__MIPI_CORE_DPHY_IN_14 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__ANATOP_TESTO_11 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__USDHC3_DAT4 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 1, 0x0928, 5), /* MX6Q_PAD_SD3_DAT4__UART2_RXD */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__PCIE_CTRL_MUX_27 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__USBOH3_UH3_DFD_OUT_3 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__USBOH3_UH2_DFD_OUT_3 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__GPIO_7_1 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__MIPI_CORE_DPHY_IN_15 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__ANATOP_TESTO_12 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 0, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__USDHC3_CMD */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 1, 0x0924, 2), /* MX6Q_PAD_SD3_CMD__UART2_CTS */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 2, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__CAN1_TXCAN */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 3, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__USBOH3_UH3_DFD_OUT_4 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 4, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__USBOH3_UH2_DFD_OUT_4 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 5, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__GPIO_7_2 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 6, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__MIPI_CORE_DPHY_IN_16 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 7, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__ANATOP_TESTO_13 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 0, 0x0000, 0), /* MX6Q_PAD_SD3_CLK__USDHC3_CLK */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 1, 0x0924, 3), /* MX6Q_PAD_SD3_CLK__UART2_RTS */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 2, 0x07E4, 2), /* MX6Q_PAD_SD3_CLK__CAN1_RXCAN */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 3, 0x0000, 0), /* MX6Q_PAD_SD3_CLK__USBOH3_UH3_DFD_OUT_5 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 4, 0x0000, 0), /* MX6Q_PAD_SD3_CLK__USBOH3_UH2_DFD_OUT_5 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 5, 0x0000, 0), /* MX6Q_PAD_SD3_CLK__GPIO_7_3 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 6, 0x0000, 0), /* MX6Q_PAD_SD3_CLK__MIPI_CORE_DPHY_IN_17 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 7, 0x0000, 0), /* MX6Q_PAD_SD3_CLK__ANATOP_TESTO_14 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__USDHC3_DAT0 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 1, 0x091C, 2), /* MX6Q_PAD_SD3_DAT0__UART1_CTS */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__CAN2_TXCAN */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__USBOH3_UH3_DFD_OUT_6 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__USBOH3_UH2_DFD_OUT_6 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__GPIO_7_4 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__MIPI_CORE_DPHY_IN_18 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__ANATOP_TESTO_15 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT1__USDHC3_DAT1 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 1, 0x091C, 3), /* MX6Q_PAD_SD3_DAT1__UART1_RTS */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 2, 0x07E8, 1), /* MX6Q_PAD_SD3_DAT1__CAN2_RXCAN */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT1__USBOH3_UH3_DFD_OUT_7 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT1__USBOH3_UH2_DFD_OUT_7 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT1__GPIO_7_5 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT1__MIPI_CORE_DPHY_IN_19 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT1__ANATOP_TESTI_0 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__USDHC3_DAT2 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__PCIE_CTRL_MUX_28 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__USBOH3_UH3_DFD_OUT_8 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__USBOH3_UH2_DFD_OUT_8 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__GPIO_7_6 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__MIPI_CORE_DPHY_IN_20 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__ANATOP_TESTI_1 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__USDHC3_DAT3 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 1, 0x092C, 4), /* MX6Q_PAD_SD3_DAT3__UART3_CTS */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__PCIE_CTRL_MUX_29 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__USBOH3_UH3_DFD_OUT_9 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__USBOH3_UH2_DFD_OUT_9 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__GPIO_7_7 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__MIPI_CORE_DPHY_IN_21 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__ANATOP_TESTI_2 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 0, 0x0000, 0), /* MX6Q_PAD_SD3_RST__USDHC3_RST */
+ IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 1, 0x092C, 5), /* MX6Q_PAD_SD3_RST__UART3_RTS */
+ IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 2, 0x0000, 0), /* MX6Q_PAD_SD3_RST__PCIE_CTRL_MUX_30 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 3, 0x0000, 0), /* MX6Q_PAD_SD3_RST__USBOH3_UH3_DFD_OUT_10 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 4, 0x0000, 0), /* MX6Q_PAD_SD3_RST__USBOH3_UH2_DFD_OUT_10 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 5, 0x0000, 0), /* MX6Q_PAD_SD3_RST__GPIO_7_8 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 6, 0x0000, 0), /* MX6Q_PAD_SD3_RST__MIPI_CORE_DPHY_IN_22 */
+ IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 7, 0x0000, 0), /* MX6Q_PAD_SD3_RST__ANATOP_ANATOP_TESTI_3 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__RAWNAND_CLE */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__IPU2_SISG_4 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__PCIE_CTRL_MUX_31 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__USBOH3_UH3_DFD_OT11 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__USBOH3_UH2_DFD_OT11 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__GPIO_6_7 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__MIPI_CORE_DPHY_IN23 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__TPSMP_HTRANS_0 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__RAWNAND_ALE */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__USDHC4_RST */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__PCIE_CTRL_MUX_0 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__USBOH3_UH3_DFD_OT12 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__USBOH3_UH2_DFD_OT12 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__GPIO_6_8 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__MIPI_CR_DPHY_IN_24 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__TPSMP_HTRANS_1 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__IPU2_SISG_5 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__PCIE_CTRL__MUX_1 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__USBOH3_UH3_DFDOT13 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__USBOH3_UH2_DFDOT13 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__GPIO_6_9 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__MIPI_CR_DPHY_OUT32 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__PL301_PER1_HSIZE_0 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__RAWNAND_READY0 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__IPU2_DI0_PIN1 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__PCIE_CTRL_MUX_2 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__USBOH3_UH3_DFD_OT14 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__USBOH3_UH2_DFD_OT14 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__GPIO_6_10 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__MIPI_CR_DPHY_OUT_33 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__PL301_PER1_HSIZE_1 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS0, 0x06CC, 0x02E4, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS0, 0x06CC, 0x02E4, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_CS0__USBOH3_UH3_DFD_OT15 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS0, 0x06CC, 0x02E4, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_CS0__USBOH3_UH2_DFD_OT15 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS0, 0x06CC, 0x02E4, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_CS0__GPIO_6_11 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS0, 0x06CC, 0x02E4, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_CS0__PL301_PER1_HSIZE_2 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS1, 0x06D0, 0x02E8, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS1, 0x06D0, 0x02E8, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_CS1__USDHC4_VSELECT */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS1, 0x06D0, 0x02E8, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_CS1__USDHC3_VSELECT */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS1, 0x06D0, 0x02E8, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_CS1__PCIE_CTRL_MUX_3 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS1, 0x06D0, 0x02E8, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_CS1__GPIO_6_14 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS1, 0x06D0, 0x02E8, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_CS1__PL301_PER1_HRDYOUT */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_CS2__IPU1_SISG_0 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 2, 0x0874, 1), /* MX6Q_PAD_NANDF_CS2__ESAI1_TX0 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_CS2__WEIM_WEIM_CRE */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_CS2__CCM_CLKO2 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_CS2__GPIO_6_15 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_CS2__IPU2_SISG_0 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__IPU1_SISG_1 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 2, 0x0878, 1), /* MX6Q_PAD_NANDF_CS3__ESAI1_TX1 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__WEIM_WEIM_A_26 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__PCIE_CTRL_MUX_4 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__GPIO_6_16 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__IPU2_SISG_1 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__TPSMP_CLK */
+ IMX_PIN_REG(MX6Q_PAD_SD4_CMD, 0x06DC, 0x02F4, 0, 0x0000, 0), /* MX6Q_PAD_SD4_CMD__USDHC4_CMD */
+ IMX_PIN_REG(MX6Q_PAD_SD4_CMD, 0x06DC, 0x02F4, 1, 0x0000, 0), /* MX6Q_PAD_SD4_CMD__RAWNAND_RDN */
+ IMX_PIN_REG(MX6Q_PAD_SD4_CMD, 0x06DC, 0x02F4, 2, 0x0000, 0), /* MX6Q_PAD_SD4_CMD__UART3_TXD */
+ IMX_PIN_REG(MX6Q_PAD_SD4_CMD, 0x06DC, 0x02F4, 4, 0x0000, 0), /* MX6Q_PAD_SD4_CMD__PCIE_CTRL_MUX_5 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_CMD, 0x06DC, 0x02F4, 5, 0x0000, 0), /* MX6Q_PAD_SD4_CMD__GPIO_7_9 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_CMD, 0x06DC, 0x02F4, 7, 0x0000, 0), /* MX6Q_PAD_SD4_CMD__TPSMP_HDATA_DIR */
+ IMX_PIN_REG(MX6Q_PAD_SD4_CLK, 0x06E0, 0x02F8, 0, 0x0000, 0), /* MX6Q_PAD_SD4_CLK__USDHC4_CLK */
+ IMX_PIN_REG(MX6Q_PAD_SD4_CLK, 0x06E0, 0x02F8, 1, 0x0000, 0), /* MX6Q_PAD_SD4_CLK__RAWNAND_WRN */
+ IMX_PIN_REG(MX6Q_PAD_SD4_CLK, 0x06E0, 0x02F8, 2, 0x0930, 3), /* MX6Q_PAD_SD4_CLK__UART3_RXD */
+ IMX_PIN_REG(MX6Q_PAD_SD4_CLK, 0x06E0, 0x02F8, 4, 0x0000, 0), /* MX6Q_PAD_SD4_CLK__PCIE_CTRL_MUX_6 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_CLK, 0x06E0, 0x02F8, 5, 0x0000, 0), /* MX6Q_PAD_SD4_CLK__GPIO_7_10 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__RAWNAND_D0 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__USDHC1_DAT4 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__GPU3D_GPU_DBG_OUT_0 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__USBOH3_UH2_DFD_OUT16 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__USBOH3_UH3_DFD_OUT16 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__GPIO_2_0 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__IPU1_IPU_DIAG_BUS_0 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__IPU2_IPU_DIAG_BUS_0 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__RAWNAND_D1 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__USDHC1_DAT5 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__GPU3D_GPU_DEBUG_OUT1 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__USBOH3_UH2_DFD_OUT17 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__USBOH3_UH3_DFD_OUT17 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__GPIO_2_1 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__IPU1_IPU_DIAG_BUS_1 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__IPU2_IPU_DIAG_BUS_1 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__RAWNAND_D2 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__USDHC1_DAT6 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__GPU3D_GPU_DBG_OUT_2 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__USBOH3_UH2_DFD_OUT18 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__USBOH3_UH3_DFD_OUT18 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__GPIO_2_2 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__IPU1_IPU_DIAG_BUS_2 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__IPU2_IPU_DIAG_BUS_2 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__RAWNAND_D3 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__USDHC1_DAT7 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__GPU3D_GPU_DBG_OUT_3 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__USBOH3_UH2_DFD_OUT19 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__USBOH3_UH3_DFD_OUT19 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__GPIO_2_3 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__IPU1_IPU_DIAG_BUS_3 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__IPU2_IPU_DIAG_BUS_3 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__RAWNAND_D4 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__USDHC2_DAT4 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__GPU3D_GPU_DBG_OUT_4 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__USBOH3_UH2_DFD_OUT20 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__USBOH3_UH3_DFD_OUT20 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__GPIO_2_4 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__IPU1_IPU_DIAG_BUS_4 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__IPU2_IPU_DIAG_BUS_4 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__RAWNAND_D5 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__USDHC2_DAT5 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__GPU3D_GPU_DBG_OUT_5 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__USBOH3_UH2_DFD_OUT21 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__USBOH3_UH3_DFD_OUT21 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__GPIO_2_5 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__IPU1_IPU_DIAG_BUS_5 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__IPU2_IPU_DIAG_BUS_5 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__RAWNAND_D6 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__USDHC2_DAT6 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__GPU3D_GPU_DBG_OUT_6 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__USBOH3_UH2_DFD_OUT22 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__USBOH3_UH3_DFD_OUT22 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__GPIO_2_6 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__IPU1_IPU_DIAG_BUS_6 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__IPU2_IPU_DIAG_BUS_6 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__RAWNAND_D7 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__USDHC2_DAT7 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__GPU3D_GPU_DBG_OUT_7 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__USBOH3_UH2_DFD_OUT23 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__USBOH3_UH3_DFD_OUT23 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__GPIO_2_7 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__IPU1_IPU_DIAG_BUS_7 */
+ IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__IPU2_IPU_DIAG_BUS_7 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__RAWNAND_D8 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 2, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__RAWNAND_DQS */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__USBOH3_UH2_DFD_OUT24 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__USBOH3_UH3_DFD_OUT24 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__GPIO_2_8 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__IPU1_IPU_DIAG_BUS_8 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__IPU2_IPU_DIAG_BUS_8 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__RAWNAND_D9 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 2, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__PWM3_PWMO */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__USBOH3_UH2_DFD_OUT25 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__USBOH3_UH3_DFD_OUT25 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__GPIO_2_9 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__IPU1_IPU_DIAG_BUS_9 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__IPU2_IPU_DIAG_BUS_9 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__RAWNAND_D10 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 2, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__PWM4_PWMO */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__USBOH3_UH2_DFD_OUT26 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__USBOH3_UH3_DFD_OUT26 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__GPIO_2_10 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__IPU1_IPU_DIAG_BUS_10 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__IPU2_IPU_DIAG_BUS_10 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__RAWNAND_D11 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__USBOH3_UH2_DFD_OUT27 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__USBOH3_UH3_DFD_OUT27 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__GPIO_2_11 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__IPU1_IPU_DIAG_BUS_11 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__IPU2_IPU_DIAG_BUS_11 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__RAWNAND_D12 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__USDHC4_DAT4 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 2, 0x0928, 6), /* MX6Q_PAD_SD4_DAT4__UART2_RXD */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__USBOH3_UH2_DFD_OUT28 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__USBOH3_UH3_DFD_OUT28 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__GPIO_2_12 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__IPU1_IPU_DIAG_BUS_12 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__IPU2_IPU_DIAG_BUS_12 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__RAWNAND_D13 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__USDHC4_DAT5 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 2, 0x0924, 4), /* MX6Q_PAD_SD4_DAT5__UART2_RTS */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__USBOH3_UH2_DFD_OUT29 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__USBOH3_UH3_DFD_OUT29 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__GPIO_2_13 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__IPU1_IPU_DIAG_BUS_13 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__IPU2_IPU_DIAG_BUS_13 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__RAWNAND_D14 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__USDHC4_DAT6 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 2, 0x0924, 5), /* MX6Q_PAD_SD4_DAT6__UART2_CTS */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__USBOH3_UH2_DFD_OUT30 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__USBOH3_UH3_DFD_OUT30 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__GPIO_2_14 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__IPU1_IPU_DIAG_BUS_14 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__IPU2_IPU_DIAG_BUS_14 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__RAWNAND_D15 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 2, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__UART2_TXD */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__USBOH3_UH2_DFD_OUT31 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__USBOH3_UH3_DFD_OUT31 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__GPIO_2_15 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__IPU1_IPU_DIAG_BUS_15 */
+ IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__IPU2_IPU_DIAG_BUS_15 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 0, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__USDHC1_DAT1 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 1, 0x0834, 1), /* MX6Q_PAD_SD1_DAT1__ECSPI5_SS0 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 2, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__PWM3_PWMO */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 3, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__GPT_CAPIN2 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 4, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__PCIE_CTRL_MUX_7 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 5, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__GPIO_1_17 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 6, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__HDMI_TX_OPHYDTB_0 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 7, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__ANATOP_TESTO_8 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 0, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__USDHC1_DAT0 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 1, 0x082C, 1), /* MX6Q_PAD_SD1_DAT0__ECSPI5_MISO */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 2, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__CAAM_WRAP_RNG_OSCOBS */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 3, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__GPT_CAPIN1 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 4, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__PCIE_CTRL_MUX_8 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 5, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__GPIO_1_16 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 6, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__HDMI_TX_OPHYDTB_1 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 7, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__ANATOP_TESTO_7 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 0, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__USDHC1_DAT3 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 1, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__ECSPI5_SS2 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 2, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__GPT_CMPOUT3 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 3, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__PWM1_PWMO */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 4, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__WDOG2_WDOG_B */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 5, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__GPIO_1_21 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 6, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__WDOG2_WDOG_RST_B_DEB */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 7, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__ANATOP_TESTO_6 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_CMD, 0x0730, 0x0348, 0, 0x0000, 0), /* MX6Q_PAD_SD1_CMD__USDHC1_CMD */
+ IMX_PIN_REG(MX6Q_PAD_SD1_CMD, 0x0730, 0x0348, 1, 0x0830, 0), /* MX6Q_PAD_SD1_CMD__ECSPI5_MOSI */
+ IMX_PIN_REG(MX6Q_PAD_SD1_CMD, 0x0730, 0x0348, 2, 0x0000, 0), /* MX6Q_PAD_SD1_CMD__PWM4_PWMO */
+ IMX_PIN_REG(MX6Q_PAD_SD1_CMD, 0x0730, 0x0348, 3, 0x0000, 0), /* MX6Q_PAD_SD1_CMD__GPT_CMPOUT1 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_CMD, 0x0730, 0x0348, 5, 0x0000, 0), /* MX6Q_PAD_SD1_CMD__GPIO_1_18 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_CMD, 0x0730, 0x0348, 7, 0x0000, 0), /* MX6Q_PAD_SD1_CMD__ANATOP_TESTO_5 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 0, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__USDHC1_DAT2 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 1, 0x0838, 1), /* MX6Q_PAD_SD1_DAT2__ECSPI5_SS1 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 2, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__GPT_CMPOUT2 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 3, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__PWM2_PWMO */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 4, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__WDOG1_WDOG_B */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 5, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__GPIO_1_19 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 6, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__WDOG1_WDOG_RST_B_DEB */
+ IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 7, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__ANATOP_TESTO_4 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 0, 0x0000, 0), /* MX6Q_PAD_SD1_CLK__USDHC1_CLK */
+ IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 1, 0x0828, 0), /* MX6Q_PAD_SD1_CLK__ECSPI5_SCLK */
+ IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 2, 0x0000, 0), /* MX6Q_PAD_SD1_CLK__OSC32K_32K_OUT */
+ IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 3, 0x0000, 0), /* MX6Q_PAD_SD1_CLK__GPT_CLKIN */
+ IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 5, 0x0000, 0), /* MX6Q_PAD_SD1_CLK__GPIO_1_20 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 6, 0x0000, 0), /* MX6Q_PAD_SD1_CLK__PHY_DTB_0 */
+ IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 7, 0x0000, 0), /* MX6Q_PAD_SD1_CLK__SATA_PHY_DTB_0 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 0, 0x0000, 0), /* MX6Q_PAD_SD2_CLK__USDHC2_CLK */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 1, 0x0828, 1), /* MX6Q_PAD_SD2_CLK__ECSPI5_SCLK */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 2, 0x08E8, 3), /* MX6Q_PAD_SD2_CLK__KPP_COL_5 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 3, 0x07C0, 1), /* MX6Q_PAD_SD2_CLK__AUDMUX_AUD4_RXFS */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 4, 0x0000, 0), /* MX6Q_PAD_SD2_CLK__PCIE_CTRL_MUX_9 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 5, 0x0000, 0), /* MX6Q_PAD_SD2_CLK__GPIO_1_10 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 6, 0x0000, 0), /* MX6Q_PAD_SD2_CLK__PHY_DTB_1 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 7, 0x0000, 0), /* MX6Q_PAD_SD2_CLK__SATA_PHY_DTB_1 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CMD, 0x0740, 0x0358, 0, 0x0000, 0), /* MX6Q_PAD_SD2_CMD__USDHC2_CMD */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CMD, 0x0740, 0x0358, 1, 0x0830, 1), /* MX6Q_PAD_SD2_CMD__ECSPI5_MOSI */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CMD, 0x0740, 0x0358, 2, 0x08F4, 2), /* MX6Q_PAD_SD2_CMD__KPP_ROW_5 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CMD, 0x0740, 0x0358, 3, 0x07BC, 1), /* MX6Q_PAD_SD2_CMD__AUDMUX_AUD4_RXC */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CMD, 0x0740, 0x0358, 4, 0x0000, 0), /* MX6Q_PAD_SD2_CMD__PCIE_CTRL_MUX_10 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_CMD, 0x0740, 0x0358, 5, 0x0000, 0), /* MX6Q_PAD_SD2_CMD__GPIO_1_11 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 0, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__USDHC2_DAT3 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 1, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__ECSPI5_SS3 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 2, 0x08EC, 2), /* MX6Q_PAD_SD2_DAT3__KPP_COL_6 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 3, 0x07C4, 1), /* MX6Q_PAD_SD2_DAT3__AUDMUX_AUD4_TXC */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 4, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__PCIE_CTRL_MUX_11 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 5, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__GPIO_1_12 */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 6, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__SJC_DONE */
+ IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 7, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__ANATOP_TESTO_3 */
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx6q_pinctrl_pads[] = {
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD2_DAT1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD2_DAT2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD2_DAT0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_RGMII_TXC),
+ IMX_PINCTRL_PIN(MX6Q_PAD_RGMII_TD0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_RGMII_TD1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_RGMII_TD2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_RGMII_TD3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_RGMII_RX_CTL),
+ IMX_PINCTRL_PIN(MX6Q_PAD_RGMII_RD0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_RGMII_TX_CTL),
+ IMX_PINCTRL_PIN(MX6Q_PAD_RGMII_RD1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_RGMII_RD2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_RGMII_RD3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_RGMII_RXC),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_A25),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_EB2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D16),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D17),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D18),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D19),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D20),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D21),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D22),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D23),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_EB3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D24),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D25),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D26),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D27),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D28),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D29),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D30),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_D31),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_A24),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_A23),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_A22),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_A21),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_A20),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_A19),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_A18),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_A17),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_A16),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_CS0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_CS1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_OE),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_RW),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_LBA),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_EB0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_EB1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA5),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA6),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA7),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA8),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA9),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA10),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA11),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA12),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA13),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA14),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_DA15),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_WAIT),
+ IMX_PINCTRL_PIN(MX6Q_PAD_EIM_BCLK),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DI0_DISP_CLK),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DI0_PIN15),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DI0_PIN2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DI0_PIN3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DI0_PIN4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT5),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT6),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT7),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT8),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT9),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT10),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT11),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT12),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT13),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT14),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT15),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT16),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT17),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT18),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT19),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT20),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT21),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT22),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DISP0_DAT23),
+ IMX_PINCTRL_PIN(MX6Q_PAD_ENET_MDIO),
+ IMX_PINCTRL_PIN(MX6Q_PAD_ENET_REF_CLK),
+ IMX_PINCTRL_PIN(MX6Q_PAD_ENET_RX_ER),
+ IMX_PINCTRL_PIN(MX6Q_PAD_ENET_CRS_DV),
+ IMX_PINCTRL_PIN(MX6Q_PAD_ENET_RXD1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_ENET_RXD0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_ENET_TX_EN),
+ IMX_PINCTRL_PIN(MX6Q_PAD_ENET_TXD1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_ENET_TXD0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_ENET_MDC),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D40),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D41),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D42),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D43),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D44),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D45),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D46),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D47),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS5),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM5),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D32),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D33),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D34),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D35),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D36),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D37),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D38),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D39),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D24),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D25),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D26),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D27),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D28),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D29),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D30),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D31),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D16),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D17),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D18),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D19),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D20),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D21),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D22),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D23),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A5),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A6),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A7),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A8),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A9),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A10),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A11),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A12),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A13),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A14),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A15),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_CAS),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_CS0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_CS1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_RAS),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_RESET),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDBA0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDBA1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDCLK_0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDBA2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDCKE0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDCLK_1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDCKE1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDODT0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDODT1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDWE),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D5),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D6),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D7),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D8),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D9),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D10),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D11),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D12),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D13),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D14),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D15),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D48),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D49),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D50),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D51),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D52),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D53),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D54),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D55),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS6),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM6),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D56),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS7),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D57),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D58),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D59),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D60),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM7),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D61),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D62),
+ IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D63),
+ IMX_PINCTRL_PIN(MX6Q_PAD_KEY_COL0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_KEY_ROW0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_KEY_COL1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_KEY_ROW1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_KEY_COL2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_KEY_ROW2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_KEY_COL3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_KEY_ROW3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_KEY_COL4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_KEY_ROW4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_9),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_6),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_5),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_7),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_8),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_16),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_17),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_18),
+ IMX_PINCTRL_PIN(MX6Q_PAD_GPIO_19),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_PIXCLK),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_MCLK),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DATA_EN),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_VSYNC),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT5),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT6),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT7),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT8),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT9),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT10),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT11),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT12),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT13),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT14),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT15),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT16),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT17),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT18),
+ IMX_PINCTRL_PIN(MX6Q_PAD_CSI0_DAT19),
+ IMX_PINCTRL_PIN(MX6Q_PAD_JTAG_TMS),
+ IMX_PINCTRL_PIN(MX6Q_PAD_JTAG_MOD),
+ IMX_PINCTRL_PIN(MX6Q_PAD_JTAG_TRSTB),
+ IMX_PINCTRL_PIN(MX6Q_PAD_JTAG_TDI),
+ IMX_PINCTRL_PIN(MX6Q_PAD_JTAG_TCK),
+ IMX_PINCTRL_PIN(MX6Q_PAD_JTAG_TDO),
+ IMX_PINCTRL_PIN(MX6Q_PAD_LVDS1_TX3_P),
+ IMX_PINCTRL_PIN(MX6Q_PAD_LVDS1_TX2_P),
+ IMX_PINCTRL_PIN(MX6Q_PAD_LVDS1_CLK_P),
+ IMX_PINCTRL_PIN(MX6Q_PAD_LVDS1_TX1_P),
+ IMX_PINCTRL_PIN(MX6Q_PAD_LVDS1_TX0_P),
+ IMX_PINCTRL_PIN(MX6Q_PAD_LVDS0_TX3_P),
+ IMX_PINCTRL_PIN(MX6Q_PAD_LVDS0_CLK_P),
+ IMX_PINCTRL_PIN(MX6Q_PAD_LVDS0_TX2_P),
+ IMX_PINCTRL_PIN(MX6Q_PAD_LVDS0_TX1_P),
+ IMX_PINCTRL_PIN(MX6Q_PAD_LVDS0_TX0_P),
+ IMX_PINCTRL_PIN(MX6Q_PAD_TAMPER),
+ IMX_PINCTRL_PIN(MX6Q_PAD_PMIC_ON_REQ),
+ IMX_PINCTRL_PIN(MX6Q_PAD_PMIC_STBY_REQ),
+ IMX_PINCTRL_PIN(MX6Q_PAD_POR_B),
+ IMX_PINCTRL_PIN(MX6Q_PAD_BOOT_MODE1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_RESET_IN_B),
+ IMX_PINCTRL_PIN(MX6Q_PAD_BOOT_MODE0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_TEST_MODE),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD3_DAT7),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD3_DAT6),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD3_DAT5),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD3_DAT4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD3_CMD),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD3_CLK),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD3_DAT0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD3_DAT1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD3_DAT2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD3_DAT3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD3_RST),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_CLE),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_ALE),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_WP_B),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_RB0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_CS0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_CS1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_CS2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_CS3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD4_CMD),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD4_CLK),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_D0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_D1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_D2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_D3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_D4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_D5),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_D6),
+ IMX_PINCTRL_PIN(MX6Q_PAD_NANDF_D7),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD4_DAT0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD4_DAT1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD4_DAT2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD4_DAT3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD4_DAT4),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD4_DAT5),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD4_DAT6),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD4_DAT7),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD1_DAT1),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD1_DAT0),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD1_DAT3),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD1_CMD),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD1_DAT2),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD1_CLK),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD2_CLK),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD2_CMD),
+ IMX_PINCTRL_PIN(MX6Q_PAD_SD2_DAT3),
+};
+
+static struct imx_pinctrl_soc_info imx6q_pinctrl_info = {
+ .pins = imx6q_pinctrl_pads,
+ .npins = ARRAY_SIZE(imx6q_pinctrl_pads),
+ .pin_regs = imx6q_pin_regs,
+ .npin_regs = ARRAY_SIZE(imx6q_pin_regs),
+};
+
+static struct of_device_id imx6q_pinctrl_of_match[] __devinitdata = {
+ { .compatible = "fsl,imx6q-iomuxc", },
+ { /* sentinel */ }
+};
+
+static int __devinit imx6q_pinctrl_probe(struct platform_device *pdev)
+{
+ return imx_pinctrl_probe(pdev, &imx6q_pinctrl_info);
+}
+
+static struct platform_driver imx6q_pinctrl_driver = {
+ .driver = {
+ .name = "imx6q-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(imx6q_pinctrl_of_match),
+ },
+ .probe = imx6q_pinctrl_probe,
+ .remove = __devexit_p(imx_pinctrl_remove),
+};
+
+static int __init imx6q_pinctrl_init(void)
+{
+ return platform_driver_register(&imx6q_pinctrl_driver);
+}
+arch_initcall(imx6q_pinctrl_init);
+
+static void __exit imx6q_pinctrl_exit(void)
+{
+ platform_driver_unregister(&imx6q_pinctrl_driver);
+}
+module_exit(imx6q_pinctrl_exit);
+MODULE_AUTHOR("Dong Aisheng <dong.aisheng@linaro.org>");
+MODULE_DESCRIPTION("Freescale IMX6Q pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c
new file mode 100644
index 000000000000..556e45a213eb
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-mxs.c
@@ -0,0 +1,528 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include "core.h"
+#include "pinctrl-mxs.h"
+
+#define SUFFIX_LEN 4
+
+struct mxs_pinctrl_data {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+ void __iomem *base;
+ struct mxs_pinctrl_soc_data *soc;
+};
+
+static int mxs_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+ return d->soc->ngroups;
+}
+
+static const char *mxs_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+ return d->soc->groups[group].name;
+}
+
+static int mxs_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
+ const unsigned **pins, unsigned *num_pins)
+{
+ struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+ *pins = d->soc->groups[group].pins;
+ *num_pins = d->soc->groups[group].npins;
+
+ return 0;
+}
+
+static void mxs_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+ unsigned offset)
+{
+ seq_printf(s, " %s", dev_name(pctldev->dev));
+}
+
+static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **map, unsigned *num_maps)
+{
+ struct pinctrl_map *new_map;
+ char *group = NULL;
+ unsigned new_num = 1;
+ unsigned long config = 0;
+ unsigned long *pconfig;
+ int length = strlen(np->name) + SUFFIX_LEN;
+ bool purecfg = false;
+ u32 val, reg;
+ int ret, i = 0;
+
+ /* Check for pin config node which has no 'reg' property */
+ if (of_property_read_u32(np, "reg", &reg))
+ purecfg = true;
+
+ ret = of_property_read_u32(np, "fsl,drive-strength", &val);
+ if (!ret)
+ config = val | MA_PRESENT;
+ ret = of_property_read_u32(np, "fsl,voltage", &val);
+ if (!ret)
+ config |= val << VOL_SHIFT | VOL_PRESENT;
+ ret = of_property_read_u32(np, "fsl,pull-up", &val);
+ if (!ret)
+ config |= val << PULL_SHIFT | PULL_PRESENT;
+
+ /* Check for group node which has both mux and config settings */
+ if (!purecfg && config)
+ new_num = 2;
+
+ new_map = kzalloc(sizeof(*new_map) * new_num, GFP_KERNEL);
+ if (!new_map)
+ return -ENOMEM;
+
+ if (!purecfg) {
+ new_map[i].type = PIN_MAP_TYPE_MUX_GROUP;
+ new_map[i].data.mux.function = np->name;
+
+ /* Compose group name */
+ group = kzalloc(length, GFP_KERNEL);
+ if (!group)
+ return -ENOMEM;
+ snprintf(group, length, "%s.%d", np->name, reg);
+ new_map[i].data.mux.group = group;
+ i++;
+ }
+
+ if (config) {
+ pconfig = kmemdup(&config, sizeof(config), GFP_KERNEL);
+ if (!pconfig) {
+ ret = -ENOMEM;
+ goto free;
+ }
+
+ new_map[i].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+ new_map[i].data.configs.group_or_pin = purecfg ? np->name :
+ group;
+ new_map[i].data.configs.configs = pconfig;
+ new_map[i].data.configs.num_configs = 1;
+ }
+
+ *map = new_map;
+ *num_maps = new_num;
+
+ return 0;
+
+free:
+ kfree(new_map);
+ return ret;
+}
+
+static void mxs_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ int i;
+
+ for (i = 0; i < num_maps; i++) {
+ if (map[i].type == PIN_MAP_TYPE_MUX_GROUP)
+ kfree(map[i].data.mux.group);
+ if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
+ kfree(map[i].data.configs.configs);
+ }
+
+ kfree(map);
+}
+
+static struct pinctrl_ops mxs_pinctrl_ops = {
+ .get_groups_count = mxs_get_groups_count,
+ .get_group_name = mxs_get_group_name,
+ .get_group_pins = mxs_get_group_pins,
+ .pin_dbg_show = mxs_pin_dbg_show,
+ .dt_node_to_map = mxs_dt_node_to_map,
+ .dt_free_map = mxs_dt_free_map,
+};
+
+static int mxs_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+ struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+ return d->soc->nfunctions;
+}
+
+static const char *mxs_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned function)
+{
+ struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+ return d->soc->functions[function].name;
+}
+
+static int mxs_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
+ unsigned group,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = d->soc->functions[group].groups;
+ *num_groups = d->soc->functions[group].ngroups;
+
+ return 0;
+}
+
+static int mxs_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+ struct mxs_group *g = &d->soc->groups[group];
+ void __iomem *reg;
+ u8 bank, shift;
+ u16 pin;
+ int i;
+
+ for (i = 0; i < g->npins; i++) {
+ bank = PINID_TO_BANK(g->pins[i]);
+ pin = PINID_TO_PIN(g->pins[i]);
+ reg = d->base + d->soc->regs->muxsel;
+ reg += bank * 0x20 + pin / 16 * 0x10;
+ shift = pin % 16 * 2;
+
+ writel(0x3 << shift, reg + CLR);
+ writel(g->muxsel[i] << shift, reg + SET);
+ }
+
+ return 0;
+}
+
+static struct pinmux_ops mxs_pinmux_ops = {
+ .get_functions_count = mxs_pinctrl_get_funcs_count,
+ .get_function_name = mxs_pinctrl_get_func_name,
+ .get_function_groups = mxs_pinctrl_get_func_groups,
+ .enable = mxs_pinctrl_enable,
+};
+
+static int mxs_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned pin, unsigned long *config)
+{
+ return -ENOTSUPP;
+}
+
+static int mxs_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned pin, unsigned long config)
+{
+ return -ENOTSUPP;
+}
+
+static int mxs_pinconf_group_get(struct pinctrl_dev *pctldev,
+ unsigned group, unsigned long *config)
+{
+ struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+ *config = d->soc->groups[group].config;
+
+ return 0;
+}
+
+static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned group, unsigned long config)
+{
+ struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+ struct mxs_group *g = &d->soc->groups[group];
+ void __iomem *reg;
+ u8 ma, vol, pull, bank, shift;
+ u16 pin;
+ int i;
+
+ ma = CONFIG_TO_MA(config);
+ vol = CONFIG_TO_VOL(config);
+ pull = CONFIG_TO_PULL(config);
+
+ for (i = 0; i < g->npins; i++) {
+ bank = PINID_TO_BANK(g->pins[i]);
+ pin = PINID_TO_PIN(g->pins[i]);
+
+ /* drive */
+ reg = d->base + d->soc->regs->drive;
+ reg += bank * 0x40 + pin / 8 * 0x10;
+
+ /* mA */
+ if (config & MA_PRESENT) {
+ shift = pin % 8 * 4;
+ writel(0x3 << shift, reg + CLR);
+ writel(ma << shift, reg + SET);
+ }
+
+ /* vol */
+ if (config & VOL_PRESENT) {
+ shift = pin % 8 * 4 + 2;
+ if (vol)
+ writel(1 << shift, reg + SET);
+ else
+ writel(1 << shift, reg + CLR);
+ }
+
+ /* pull */
+ if (config & PULL_PRESENT) {
+ reg = d->base + d->soc->regs->pull;
+ reg += bank * 0x10;
+ shift = pin;
+ if (pull)
+ writel(1 << shift, reg + SET);
+ else
+ writel(1 << shift, reg + CLR);
+ }
+ }
+
+ /* cache the config value for mxs_pinconf_group_get() */
+ g->config = config;
+
+ return 0;
+}
+
+static void mxs_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned pin)
+{
+ /* Not support */
+}
+
+static void mxs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned group)
+{
+ unsigned long config;
+
+ if (!mxs_pinconf_group_get(pctldev, group, &config))
+ seq_printf(s, "0x%lx", config);
+}
+
+struct pinconf_ops mxs_pinconf_ops = {
+ .pin_config_get = mxs_pinconf_get,
+ .pin_config_set = mxs_pinconf_set,
+ .pin_config_group_get = mxs_pinconf_group_get,
+ .pin_config_group_set = mxs_pinconf_group_set,
+ .pin_config_dbg_show = mxs_pinconf_dbg_show,
+ .pin_config_group_dbg_show = mxs_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc mxs_pinctrl_desc = {
+ .pctlops = &mxs_pinctrl_ops,
+ .pmxops = &mxs_pinmux_ops,
+ .confops = &mxs_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+static int __devinit mxs_pinctrl_parse_group(struct platform_device *pdev,
+ struct device_node *np, int idx,
+ const char **out_name)
+{
+ struct mxs_pinctrl_data *d = platform_get_drvdata(pdev);
+ struct mxs_group *g = &d->soc->groups[idx];
+ struct property *prop;
+ const char *propname = "fsl,pinmux-ids";
+ char *group;
+ int length = strlen(np->name) + SUFFIX_LEN;
+ int i;
+ u32 val;
+
+ group = devm_kzalloc(&pdev->dev, length, GFP_KERNEL);
+ if (!group)
+ return -ENOMEM;
+ if (of_property_read_u32(np, "reg", &val))
+ snprintf(group, length, "%s", np->name);
+ else
+ snprintf(group, length, "%s.%d", np->name, val);
+ g->name = group;
+
+ prop = of_find_property(np, propname, &length);
+ if (!prop)
+ return -EINVAL;
+ g->npins = length / sizeof(u32);
+
+ g->pins = devm_kzalloc(&pdev->dev, g->npins * sizeof(*g->pins),
+ GFP_KERNEL);
+ if (!g->pins)
+ return -ENOMEM;
+
+ g->muxsel = devm_kzalloc(&pdev->dev, g->npins * sizeof(*g->muxsel),
+ GFP_KERNEL);
+ if (!g->muxsel)
+ return -ENOMEM;
+
+ of_property_read_u32_array(np, propname, g->pins, g->npins);
+ for (i = 0; i < g->npins; i++) {
+ g->muxsel[i] = MUXID_TO_MUXSEL(g->pins[i]);
+ g->pins[i] = MUXID_TO_PINID(g->pins[i]);
+ }
+
+ if (out_name)
+ *out_name = g->name;
+
+ return 0;
+}
+
+static int __devinit mxs_pinctrl_probe_dt(struct platform_device *pdev,
+ struct mxs_pinctrl_data *d)
+{
+ struct mxs_pinctrl_soc_data *soc = d->soc;
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *child;
+ struct mxs_function *f;
+ const char *gpio_compat = "fsl,mxs-gpio";
+ const char *fn, *fnull = "";
+ int i = 0, idxf = 0, idxg = 0;
+ int ret;
+ u32 val;
+
+ child = of_get_next_child(np, NULL);
+ if (!child) {
+ dev_err(&pdev->dev, "no group is defined\n");
+ return -ENOENT;
+ }
+
+ /* Count total functions and groups */
+ fn = fnull;
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child, gpio_compat))
+ continue;
+ soc->ngroups++;
+ /* Skip pure pinconf node */
+ if (of_property_read_u32(child, "reg", &val))
+ continue;
+ if (strcmp(fn, child->name)) {
+ fn = child->name;
+ soc->nfunctions++;
+ }
+ }
+
+ soc->functions = devm_kzalloc(&pdev->dev, soc->nfunctions *
+ sizeof(*soc->functions), GFP_KERNEL);
+ if (!soc->functions)
+ return -ENOMEM;
+
+ soc->groups = devm_kzalloc(&pdev->dev, soc->ngroups *
+ sizeof(*soc->groups), GFP_KERNEL);
+ if (!soc->groups)
+ return -ENOMEM;
+
+ /* Count groups for each function */
+ fn = fnull;
+ f = &soc->functions[idxf];
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child, gpio_compat))
+ continue;
+ if (of_property_read_u32(child, "reg", &val))
+ continue;
+ if (strcmp(fn, child->name)) {
+ f = &soc->functions[idxf++];
+ f->name = fn = child->name;
+ }
+ f->ngroups++;
+ };
+
+ /* Get groups for each function */
+ idxf = 0;
+ fn = fnull;
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child, gpio_compat))
+ continue;
+ if (of_property_read_u32(child, "reg", &val)) {
+ ret = mxs_pinctrl_parse_group(pdev, child,
+ idxg++, NULL);
+ if (ret)
+ return ret;
+ continue;
+ }
+
+ if (strcmp(fn, child->name)) {
+ f = &soc->functions[idxf++];
+ f->groups = devm_kzalloc(&pdev->dev, f->ngroups *
+ sizeof(*f->groups),
+ GFP_KERNEL);
+ if (!f->groups)
+ return -ENOMEM;
+ fn = child->name;
+ i = 0;
+ }
+ ret = mxs_pinctrl_parse_group(pdev, child, idxg++,
+ &f->groups[i++]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+int __devinit mxs_pinctrl_probe(struct platform_device *pdev,
+ struct mxs_pinctrl_soc_data *soc)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct mxs_pinctrl_data *d;
+ int ret;
+
+ d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
+ if (!d)
+ return -ENOMEM;
+
+ d->dev = &pdev->dev;
+ d->soc = soc;
+
+ d->base = of_iomap(np, 0);
+ if (!d->base)
+ return -EADDRNOTAVAIL;
+
+ mxs_pinctrl_desc.pins = d->soc->pins;
+ mxs_pinctrl_desc.npins = d->soc->npins;
+ mxs_pinctrl_desc.name = dev_name(&pdev->dev);
+
+ platform_set_drvdata(pdev, d);
+
+ ret = mxs_pinctrl_probe_dt(pdev, d);
+ if (ret) {
+ dev_err(&pdev->dev, "dt probe failed: %d\n", ret);
+ goto err;
+ }
+
+ d->pctl = pinctrl_register(&mxs_pinctrl_desc, &pdev->dev, d);
+ if (!d->pctl) {
+ dev_err(&pdev->dev, "Couldn't register MXS pinctrl driver\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ iounmap(d->base);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mxs_pinctrl_probe);
+
+int __devexit mxs_pinctrl_remove(struct platform_device *pdev)
+{
+ struct mxs_pinctrl_data *d = platform_get_drvdata(pdev);
+
+ pinctrl_unregister(d->pctl);
+ iounmap(d->base);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mxs_pinctrl_remove);
diff --git a/drivers/pinctrl/pinctrl-mxs.h b/drivers/pinctrl/pinctrl-mxs.h
new file mode 100644
index 000000000000..fdd88d0bae22
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-mxs.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __PINCTRL_MXS_H
+#define __PINCTRL_MXS_H
+
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#define SET 0x4
+#define CLR 0x8
+#define TOG 0xc
+
+#define MXS_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
+#define PINID(bank, pin) ((bank) * 32 + (pin))
+
+/*
+ * pinmux-id bit field definitions
+ *
+ * bank: 15..12 (4)
+ * pin: 11..4 (8)
+ * muxsel: 3..0 (4)
+ */
+#define MUXID_TO_PINID(m) PINID((m) >> 12 & 0xf, (m) >> 4 & 0xff)
+#define MUXID_TO_MUXSEL(m) ((m) & 0xf)
+
+#define PINID_TO_BANK(p) ((p) >> 5)
+#define PINID_TO_PIN(p) ((p) % 32)
+
+/*
+ * pin config bit field definitions
+ *
+ * pull-up: 6..5 (2)
+ * voltage: 4..3 (2)
+ * mA: 2..0 (3)
+ *
+ * MSB of each field is presence bit for the config.
+ */
+#define PULL_PRESENT (1 << 6)
+#define PULL_SHIFT 5
+#define VOL_PRESENT (1 << 4)
+#define VOL_SHIFT 3
+#define MA_PRESENT (1 << 2)
+#define MA_SHIFT 0
+#define CONFIG_TO_PULL(c) ((c) >> PULL_SHIFT & 0x1)
+#define CONFIG_TO_VOL(c) ((c) >> VOL_SHIFT & 0x1)
+#define CONFIG_TO_MA(c) ((c) >> MA_SHIFT & 0x3)
+
+struct mxs_function {
+ const char *name;
+ const char **groups;
+ unsigned ngroups;
+};
+
+struct mxs_group {
+ const char *name;
+ unsigned int *pins;
+ unsigned npins;
+ u8 *muxsel;
+ u8 config;
+};
+
+struct mxs_regs {
+ u16 muxsel;
+ u16 drive;
+ u16 pull;
+};
+
+struct mxs_pinctrl_soc_data {
+ const struct mxs_regs *regs;
+ const struct pinctrl_pin_desc *pins;
+ unsigned npins;
+ struct mxs_function *functions;
+ unsigned nfunctions;
+ struct mxs_group *groups;
+ unsigned ngroups;
+};
+
+int mxs_pinctrl_probe(struct platform_device *pdev,
+ struct mxs_pinctrl_soc_data *soc);
+int mxs_pinctrl_remove(struct platform_device *pdev);
+
+#endif /* __PINCTRL_MXS_H */
diff --git a/drivers/pinctrl/pinctrl-nomadik-db8500.c b/drivers/pinctrl/pinctrl-nomadik-db8500.c
new file mode 100644
index 000000000000..8b2022276f71
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-nomadik-db8500.c
@@ -0,0 +1,857 @@
+#include <linux/kernel.h>
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-nomadik.h"
+
+/* All the pins that can be used for GPIO and some other functions */
+#define _GPIO(offset) (offset)
+
+#define DB8500_PIN_AJ5 _GPIO(0)
+#define DB8500_PIN_AJ3 _GPIO(1)
+#define DB8500_PIN_AH4 _GPIO(2)
+#define DB8500_PIN_AH3 _GPIO(3)
+#define DB8500_PIN_AH6 _GPIO(4)
+#define DB8500_PIN_AG6 _GPIO(5)
+#define DB8500_PIN_AF6 _GPIO(6)
+#define DB8500_PIN_AG5 _GPIO(7)
+#define DB8500_PIN_AD5 _GPIO(8)
+#define DB8500_PIN_AE4 _GPIO(9)
+#define DB8500_PIN_AF5 _GPIO(10)
+#define DB8500_PIN_AG4 _GPIO(11)
+#define DB8500_PIN_AC4 _GPIO(12)
+#define DB8500_PIN_AF3 _GPIO(13)
+#define DB8500_PIN_AE3 _GPIO(14)
+#define DB8500_PIN_AC3 _GPIO(15)
+#define DB8500_PIN_AD3 _GPIO(16)
+#define DB8500_PIN_AD4 _GPIO(17)
+#define DB8500_PIN_AC2 _GPIO(18)
+#define DB8500_PIN_AC1 _GPIO(19)
+#define DB8500_PIN_AB4 _GPIO(20)
+#define DB8500_PIN_AB3 _GPIO(21)
+#define DB8500_PIN_AA3 _GPIO(22)
+#define DB8500_PIN_AA4 _GPIO(23)
+#define DB8500_PIN_AB2 _GPIO(24)
+#define DB8500_PIN_Y4 _GPIO(25)
+#define DB8500_PIN_Y2 _GPIO(26)
+#define DB8500_PIN_AA2 _GPIO(27)
+#define DB8500_PIN_AA1 _GPIO(28)
+#define DB8500_PIN_W2 _GPIO(29)
+#define DB8500_PIN_W3 _GPIO(30)
+#define DB8500_PIN_V3 _GPIO(31)
+#define DB8500_PIN_V2 _GPIO(32)
+#define DB8500_PIN_AF2 _GPIO(33)
+#define DB8500_PIN_AE1 _GPIO(34)
+#define DB8500_PIN_AE2 _GPIO(35)
+#define DB8500_PIN_AG2 _GPIO(36)
+/* Hole */
+#define DB8500_PIN_F3 _GPIO(64)
+#define DB8500_PIN_F1 _GPIO(65)
+#define DB8500_PIN_G3 _GPIO(66)
+#define DB8500_PIN_G2 _GPIO(67)
+#define DB8500_PIN_E1 _GPIO(68)
+#define DB8500_PIN_E2 _GPIO(69)
+#define DB8500_PIN_G5 _GPIO(70)
+#define DB8500_PIN_G4 _GPIO(71)
+#define DB8500_PIN_H4 _GPIO(72)
+#define DB8500_PIN_H3 _GPIO(73)
+#define DB8500_PIN_J3 _GPIO(74)
+#define DB8500_PIN_H2 _GPIO(75)
+#define DB8500_PIN_J2 _GPIO(76)
+#define DB8500_PIN_H1 _GPIO(77)
+#define DB8500_PIN_F4 _GPIO(78)
+#define DB8500_PIN_E3 _GPIO(79)
+#define DB8500_PIN_E4 _GPIO(80)
+#define DB8500_PIN_D2 _GPIO(81)
+#define DB8500_PIN_C1 _GPIO(82)
+#define DB8500_PIN_D3 _GPIO(83)
+#define DB8500_PIN_C2 _GPIO(84)
+#define DB8500_PIN_D5 _GPIO(85)
+#define DB8500_PIN_C6 _GPIO(86)
+#define DB8500_PIN_B3 _GPIO(87)
+#define DB8500_PIN_C4 _GPIO(88)
+#define DB8500_PIN_E6 _GPIO(89)
+#define DB8500_PIN_A3 _GPIO(90)
+#define DB8500_PIN_B6 _GPIO(91)
+#define DB8500_PIN_D6 _GPIO(92)
+#define DB8500_PIN_B7 _GPIO(93)
+#define DB8500_PIN_D7 _GPIO(94)
+#define DB8500_PIN_E8 _GPIO(95)
+#define DB8500_PIN_D8 _GPIO(96)
+#define DB8500_PIN_D9 _GPIO(97)
+/* Hole */
+#define DB8500_PIN_A5 _GPIO(128)
+#define DB8500_PIN_B4 _GPIO(129)
+#define DB8500_PIN_C8 _GPIO(130)
+#define DB8500_PIN_A12 _GPIO(131)
+#define DB8500_PIN_C10 _GPIO(132)
+#define DB8500_PIN_B10 _GPIO(133)
+#define DB8500_PIN_B9 _GPIO(134)
+#define DB8500_PIN_A9 _GPIO(135)
+#define DB8500_PIN_C7 _GPIO(136)
+#define DB8500_PIN_A7 _GPIO(137)
+#define DB8500_PIN_C5 _GPIO(138)
+#define DB8500_PIN_C9 _GPIO(139)
+#define DB8500_PIN_B11 _GPIO(140)
+#define DB8500_PIN_C12 _GPIO(141)
+#define DB8500_PIN_C11 _GPIO(142)
+#define DB8500_PIN_D12 _GPIO(143)
+#define DB8500_PIN_B13 _GPIO(144)
+#define DB8500_PIN_C13 _GPIO(145)
+#define DB8500_PIN_D13 _GPIO(146)
+#define DB8500_PIN_C15 _GPIO(147)
+#define DB8500_PIN_B16 _GPIO(148)
+#define DB8500_PIN_B14 _GPIO(149)
+#define DB8500_PIN_C14 _GPIO(150)
+#define DB8500_PIN_D17 _GPIO(151)
+#define DB8500_PIN_D16 _GPIO(152)
+#define DB8500_PIN_B17 _GPIO(153)
+#define DB8500_PIN_C16 _GPIO(154)
+#define DB8500_PIN_C19 _GPIO(155)
+#define DB8500_PIN_C17 _GPIO(156)
+#define DB8500_PIN_A18 _GPIO(157)
+#define DB8500_PIN_C18 _GPIO(158)
+#define DB8500_PIN_B19 _GPIO(159)
+#define DB8500_PIN_B20 _GPIO(160)
+#define DB8500_PIN_D21 _GPIO(161)
+#define DB8500_PIN_D20 _GPIO(162)
+#define DB8500_PIN_C20 _GPIO(163)
+#define DB8500_PIN_B21 _GPIO(164)
+#define DB8500_PIN_C21 _GPIO(165)
+#define DB8500_PIN_A22 _GPIO(166)
+#define DB8500_PIN_B24 _GPIO(167)
+#define DB8500_PIN_C22 _GPIO(168)
+#define DB8500_PIN_D22 _GPIO(169)
+#define DB8500_PIN_C23 _GPIO(170)
+#define DB8500_PIN_D23 _GPIO(171)
+/* Hole */
+#define DB8500_PIN_AJ27 _GPIO(192)
+#define DB8500_PIN_AH27 _GPIO(193)
+#define DB8500_PIN_AF27 _GPIO(194)
+#define DB8500_PIN_AG28 _GPIO(195)
+#define DB8500_PIN_AG26 _GPIO(196)
+#define DB8500_PIN_AH24 _GPIO(197)
+#define DB8500_PIN_AG25 _GPIO(198)
+#define DB8500_PIN_AH23 _GPIO(199)
+#define DB8500_PIN_AH26 _GPIO(200)
+#define DB8500_PIN_AF24 _GPIO(201)
+#define DB8500_PIN_AF25 _GPIO(202)
+#define DB8500_PIN_AE23 _GPIO(203)
+#define DB8500_PIN_AF23 _GPIO(204)
+#define DB8500_PIN_AG23 _GPIO(205)
+#define DB8500_PIN_AG24 _GPIO(206)
+#define DB8500_PIN_AJ23 _GPIO(207)
+#define DB8500_PIN_AH16 _GPIO(208)
+#define DB8500_PIN_AG15 _GPIO(209)
+#define DB8500_PIN_AJ15 _GPIO(210)
+#define DB8500_PIN_AG14 _GPIO(211)
+#define DB8500_PIN_AF13 _GPIO(212)
+#define DB8500_PIN_AG13 _GPIO(213)
+#define DB8500_PIN_AH15 _GPIO(214)
+#define DB8500_PIN_AH13 _GPIO(215)
+#define DB8500_PIN_AG12 _GPIO(216)
+#define DB8500_PIN_AH12 _GPIO(217)
+#define DB8500_PIN_AH11 _GPIO(218)
+#define DB8500_PIN_AG10 _GPIO(219)
+#define DB8500_PIN_AH10 _GPIO(220)
+#define DB8500_PIN_AJ11 _GPIO(221)
+#define DB8500_PIN_AJ9 _GPIO(222)
+#define DB8500_PIN_AH9 _GPIO(223)
+#define DB8500_PIN_AG9 _GPIO(224)
+#define DB8500_PIN_AG8 _GPIO(225)
+#define DB8500_PIN_AF8 _GPIO(226)
+#define DB8500_PIN_AH7 _GPIO(227)
+#define DB8500_PIN_AJ6 _GPIO(228)
+#define DB8500_PIN_AG7 _GPIO(229)
+#define DB8500_PIN_AF7 _GPIO(230)
+/* Hole */
+#define DB8500_PIN_AF28 _GPIO(256)
+#define DB8500_PIN_AE29 _GPIO(257)
+#define DB8500_PIN_AD29 _GPIO(258)
+#define DB8500_PIN_AC29 _GPIO(259)
+#define DB8500_PIN_AD28 _GPIO(260)
+#define DB8500_PIN_AD26 _GPIO(261)
+#define DB8500_PIN_AE26 _GPIO(262)
+#define DB8500_PIN_AG29 _GPIO(263)
+#define DB8500_PIN_AE27 _GPIO(264)
+#define DB8500_PIN_AD27 _GPIO(265)
+#define DB8500_PIN_AC28 _GPIO(266)
+#define DB8500_PIN_AC27 _GPIO(267)
+
+/*
+ * The names of the pins are denoted by GPIO number and ball name, even
+ * though they can be used for other things than GPIO, this is the first
+ * column in the table of the data sheet and often used on schematics and
+ * such.
+ */
+static const struct pinctrl_pin_desc nmk_db8500_pins[] = {
+ PINCTRL_PIN(DB8500_PIN_AJ5, "GPIO0_AJ5"),
+ PINCTRL_PIN(DB8500_PIN_AJ3, "GPIO1_AJ3"),
+ PINCTRL_PIN(DB8500_PIN_AH4, "GPIO2_AH4"),
+ PINCTRL_PIN(DB8500_PIN_AH3, "GPIO3_AH3"),
+ PINCTRL_PIN(DB8500_PIN_AH6, "GPIO4_AH6"),
+ PINCTRL_PIN(DB8500_PIN_AG6, "GPIO5_AG6"),
+ PINCTRL_PIN(DB8500_PIN_AF6, "GPIO6_AF6"),
+ PINCTRL_PIN(DB8500_PIN_AG5, "GPIO7_AG5"),
+ PINCTRL_PIN(DB8500_PIN_AD5, "GPIO8_AD5"),
+ PINCTRL_PIN(DB8500_PIN_AE4, "GPIO9_AE4"),
+ PINCTRL_PIN(DB8500_PIN_AF5, "GPIO10_AF5"),
+ PINCTRL_PIN(DB8500_PIN_AG4, "GPIO11_AG4"),
+ PINCTRL_PIN(DB8500_PIN_AC4, "GPIO12_AC4"),
+ PINCTRL_PIN(DB8500_PIN_AF3, "GPIO13_AF3"),
+ PINCTRL_PIN(DB8500_PIN_AE3, "GPIO14_AE3"),
+ PINCTRL_PIN(DB8500_PIN_AC3, "GPIO15_AC3"),
+ PINCTRL_PIN(DB8500_PIN_AD3, "GPIO16_AD3"),
+ PINCTRL_PIN(DB8500_PIN_AD4, "GPIO17_AD4"),
+ PINCTRL_PIN(DB8500_PIN_AC2, "GPIO18_AC2"),
+ PINCTRL_PIN(DB8500_PIN_AC1, "GPIO19_AC1"),
+ PINCTRL_PIN(DB8500_PIN_AB4, "GPIO20_AB4"),
+ PINCTRL_PIN(DB8500_PIN_AB3, "GPIO21_AB3"),
+ PINCTRL_PIN(DB8500_PIN_AA3, "GPIO22_AA3"),
+ PINCTRL_PIN(DB8500_PIN_AA4, "GPIO23_AA4"),
+ PINCTRL_PIN(DB8500_PIN_AB2, "GPIO24_AB2"),
+ PINCTRL_PIN(DB8500_PIN_Y4, "GPIO25_Y4"),
+ PINCTRL_PIN(DB8500_PIN_Y2, "GPIO26_Y2"),
+ PINCTRL_PIN(DB8500_PIN_AA2, "GPIO27_AA2"),
+ PINCTRL_PIN(DB8500_PIN_AA1, "GPIO28_AA1"),
+ PINCTRL_PIN(DB8500_PIN_W2, "GPIO29_W2"),
+ PINCTRL_PIN(DB8500_PIN_W3, "GPIO30_W3"),
+ PINCTRL_PIN(DB8500_PIN_V3, "GPIO31_V3"),
+ PINCTRL_PIN(DB8500_PIN_V2, "GPIO32_V2"),
+ PINCTRL_PIN(DB8500_PIN_AF2, "GPIO33_AF2"),
+ PINCTRL_PIN(DB8500_PIN_AE1, "GPIO34_AE1"),
+ PINCTRL_PIN(DB8500_PIN_AE2, "GPIO35_AE2"),
+ PINCTRL_PIN(DB8500_PIN_AG2, "GPIO36_AG2"),
+ /* Hole */
+ PINCTRL_PIN(DB8500_PIN_F3, "GPIO64_F3"),
+ PINCTRL_PIN(DB8500_PIN_F1, "GPIO65_F1"),
+ PINCTRL_PIN(DB8500_PIN_G3, "GPIO66_G3"),
+ PINCTRL_PIN(DB8500_PIN_G2, "GPIO67_G2"),
+ PINCTRL_PIN(DB8500_PIN_E1, "GPIO68_E1"),
+ PINCTRL_PIN(DB8500_PIN_E2, "GPIO69_E2"),
+ PINCTRL_PIN(DB8500_PIN_G5, "GPIO70_G5"),
+ PINCTRL_PIN(DB8500_PIN_G4, "GPIO71_G4"),
+ PINCTRL_PIN(DB8500_PIN_H4, "GPIO72_H4"),
+ PINCTRL_PIN(DB8500_PIN_H3, "GPIO73_H3"),
+ PINCTRL_PIN(DB8500_PIN_J3, "GPIO74_J3"),
+ PINCTRL_PIN(DB8500_PIN_H2, "GPIO75_H2"),
+ PINCTRL_PIN(DB8500_PIN_J2, "GPIO76_J2"),
+ PINCTRL_PIN(DB8500_PIN_H1, "GPIO77_H1"),
+ PINCTRL_PIN(DB8500_PIN_F4, "GPIO78_F4"),
+ PINCTRL_PIN(DB8500_PIN_E3, "GPIO79_E3"),
+ PINCTRL_PIN(DB8500_PIN_E4, "GPIO80_E4"),
+ PINCTRL_PIN(DB8500_PIN_D2, "GPIO81_D2"),
+ PINCTRL_PIN(DB8500_PIN_C1, "GPIO82_C1"),
+ PINCTRL_PIN(DB8500_PIN_D3, "GPIO83_D3"),
+ PINCTRL_PIN(DB8500_PIN_C2, "GPIO84_C2"),
+ PINCTRL_PIN(DB8500_PIN_D5, "GPIO85_D5"),
+ PINCTRL_PIN(DB8500_PIN_C6, "GPIO86_C6"),
+ PINCTRL_PIN(DB8500_PIN_B3, "GPIO87_B3"),
+ PINCTRL_PIN(DB8500_PIN_C4, "GPIO88_C4"),
+ PINCTRL_PIN(DB8500_PIN_E6, "GPIO89_E6"),
+ PINCTRL_PIN(DB8500_PIN_A3, "GPIO90_A3"),
+ PINCTRL_PIN(DB8500_PIN_B6, "GPIO91_B6"),
+ PINCTRL_PIN(DB8500_PIN_D6, "GPIO92_D6"),
+ PINCTRL_PIN(DB8500_PIN_B7, "GPIO93_B7"),
+ PINCTRL_PIN(DB8500_PIN_D7, "GPIO94_D7"),
+ PINCTRL_PIN(DB8500_PIN_E8, "GPIO95_E8"),
+ PINCTRL_PIN(DB8500_PIN_D8, "GPIO96_D8"),
+ PINCTRL_PIN(DB8500_PIN_D9, "GPIO97_D9"),
+ /* Hole */
+ PINCTRL_PIN(DB8500_PIN_A5, "GPIO128_A5"),
+ PINCTRL_PIN(DB8500_PIN_B4, "GPIO129_B4"),
+ PINCTRL_PIN(DB8500_PIN_C8, "GPIO130_C8"),
+ PINCTRL_PIN(DB8500_PIN_A12, "GPIO131_A12"),
+ PINCTRL_PIN(DB8500_PIN_C10, "GPIO132_C10"),
+ PINCTRL_PIN(DB8500_PIN_B10, "GPIO133_B10"),
+ PINCTRL_PIN(DB8500_PIN_B9, "GPIO134_B9"),
+ PINCTRL_PIN(DB8500_PIN_A9, "GPIO135_A9"),
+ PINCTRL_PIN(DB8500_PIN_C7, "GPIO136_C7"),
+ PINCTRL_PIN(DB8500_PIN_A7, "GPIO137_A7"),
+ PINCTRL_PIN(DB8500_PIN_C5, "GPIO138_C5"),
+ PINCTRL_PIN(DB8500_PIN_C9, "GPIO139_C9"),
+ PINCTRL_PIN(DB8500_PIN_B11, "GPIO140_B11"),
+ PINCTRL_PIN(DB8500_PIN_C12, "GPIO141_C12"),
+ PINCTRL_PIN(DB8500_PIN_C11, "GPIO142_C11"),
+ PINCTRL_PIN(DB8500_PIN_D12, "GPIO143_D12"),
+ PINCTRL_PIN(DB8500_PIN_B13, "GPIO144_B13"),
+ PINCTRL_PIN(DB8500_PIN_C13, "GPIO145_C13"),
+ PINCTRL_PIN(DB8500_PIN_D13, "GPIO146_D13"),
+ PINCTRL_PIN(DB8500_PIN_C15, "GPIO147_C15"),
+ PINCTRL_PIN(DB8500_PIN_B16, "GPIO148_B16"),
+ PINCTRL_PIN(DB8500_PIN_B14, "GPIO149_B14"),
+ PINCTRL_PIN(DB8500_PIN_C14, "GPIO150_C14"),
+ PINCTRL_PIN(DB8500_PIN_D17, "GPIO151_D17"),
+ PINCTRL_PIN(DB8500_PIN_D16, "GPIO152_D16"),
+ PINCTRL_PIN(DB8500_PIN_B17, "GPIO153_B17"),
+ PINCTRL_PIN(DB8500_PIN_C16, "GPIO154_C16"),
+ PINCTRL_PIN(DB8500_PIN_C19, "GPIO155_C19"),
+ PINCTRL_PIN(DB8500_PIN_C17, "GPIO156_C17"),
+ PINCTRL_PIN(DB8500_PIN_A18, "GPIO157_A18"),
+ PINCTRL_PIN(DB8500_PIN_C18, "GPIO158_C18"),
+ PINCTRL_PIN(DB8500_PIN_B19, "GPIO159_B19"),
+ PINCTRL_PIN(DB8500_PIN_B20, "GPIO160_B20"),
+ PINCTRL_PIN(DB8500_PIN_D21, "GPIO161_D21"),
+ PINCTRL_PIN(DB8500_PIN_D20, "GPIO162_D20"),
+ PINCTRL_PIN(DB8500_PIN_C20, "GPIO163_C20"),
+ PINCTRL_PIN(DB8500_PIN_B21, "GPIO164_B21"),
+ PINCTRL_PIN(DB8500_PIN_C21, "GPIO165_C21"),
+ PINCTRL_PIN(DB8500_PIN_A22, "GPIO166_A22"),
+ PINCTRL_PIN(DB8500_PIN_B24, "GPIO167_B24"),
+ PINCTRL_PIN(DB8500_PIN_C22, "GPIO168_C22"),
+ PINCTRL_PIN(DB8500_PIN_D22, "GPIO169_D22"),
+ PINCTRL_PIN(DB8500_PIN_C23, "GPIO170_C23"),
+ PINCTRL_PIN(DB8500_PIN_D23, "GPIO171_D23"),
+ /* Hole */
+ PINCTRL_PIN(DB8500_PIN_AJ27, "GPIO192_AJ27"),
+ PINCTRL_PIN(DB8500_PIN_AH27, "GPIO193_AH27"),
+ PINCTRL_PIN(DB8500_PIN_AF27, "GPIO194_AF27"),
+ PINCTRL_PIN(DB8500_PIN_AG28, "GPIO195_AG28"),
+ PINCTRL_PIN(DB8500_PIN_AG26, "GPIO196_AG26"),
+ PINCTRL_PIN(DB8500_PIN_AH24, "GPIO197_AH24"),
+ PINCTRL_PIN(DB8500_PIN_AG25, "GPIO198_AG25"),
+ PINCTRL_PIN(DB8500_PIN_AH23, "GPIO199_AH23"),
+ PINCTRL_PIN(DB8500_PIN_AH26, "GPIO200_AH26"),
+ PINCTRL_PIN(DB8500_PIN_AF24, "GPIO201_AF24"),
+ PINCTRL_PIN(DB8500_PIN_AF25, "GPIO202_AF25"),
+ PINCTRL_PIN(DB8500_PIN_AE23, "GPIO203_AE23"),
+ PINCTRL_PIN(DB8500_PIN_AF23, "GPIO204_AF23"),
+ PINCTRL_PIN(DB8500_PIN_AG23, "GPIO205_AG23"),
+ PINCTRL_PIN(DB8500_PIN_AG24, "GPIO206_AG24"),
+ PINCTRL_PIN(DB8500_PIN_AJ23, "GPIO207_AJ23"),
+ PINCTRL_PIN(DB8500_PIN_AH16, "GPIO208_AH16"),
+ PINCTRL_PIN(DB8500_PIN_AG15, "GPIO209_AG15"),
+ PINCTRL_PIN(DB8500_PIN_AJ15, "GPIO210_AJ15"),
+ PINCTRL_PIN(DB8500_PIN_AG14, "GPIO211_AG14"),
+ PINCTRL_PIN(DB8500_PIN_AF13, "GPIO212_AF13"),
+ PINCTRL_PIN(DB8500_PIN_AG13, "GPIO213_AG13"),
+ PINCTRL_PIN(DB8500_PIN_AH15, "GPIO214_AH15"),
+ PINCTRL_PIN(DB8500_PIN_AH13, "GPIO215_AH13"),
+ PINCTRL_PIN(DB8500_PIN_AG12, "GPIO216_AG12"),
+ PINCTRL_PIN(DB8500_PIN_AH12, "GPIO217_AH12"),
+ PINCTRL_PIN(DB8500_PIN_AH11, "GPIO218_AH11"),
+ PINCTRL_PIN(DB8500_PIN_AG10, "GPIO219_AG10"),
+ PINCTRL_PIN(DB8500_PIN_AH10, "GPIO220_AH10"),
+ PINCTRL_PIN(DB8500_PIN_AJ11, "GPIO221_AJ11"),
+ PINCTRL_PIN(DB8500_PIN_AJ9, "GPIO222_AJ9"),
+ PINCTRL_PIN(DB8500_PIN_AH9, "GPIO223_AH9"),
+ PINCTRL_PIN(DB8500_PIN_AG9, "GPIO224_AG9"),
+ PINCTRL_PIN(DB8500_PIN_AG8, "GPIO225_AG8"),
+ PINCTRL_PIN(DB8500_PIN_AF8, "GPIO226_AF8"),
+ PINCTRL_PIN(DB8500_PIN_AH7, "GPIO227_AH7"),
+ PINCTRL_PIN(DB8500_PIN_AJ6, "GPIO228_AJ6"),
+ PINCTRL_PIN(DB8500_PIN_AG7, "GPIO229_AG7"),
+ PINCTRL_PIN(DB8500_PIN_AF7, "GPIO230_AF7"),
+ /* Hole */
+ PINCTRL_PIN(DB8500_PIN_AF28, "GPIO256_AF28"),
+ PINCTRL_PIN(DB8500_PIN_AE29, "GPIO257_AE29"),
+ PINCTRL_PIN(DB8500_PIN_AD29, "GPIO258_AD29"),
+ PINCTRL_PIN(DB8500_PIN_AC29, "GPIO259_AC29"),
+ PINCTRL_PIN(DB8500_PIN_AD28, "GPIO260_AD28"),
+ PINCTRL_PIN(DB8500_PIN_AD26, "GPIO261_AD26"),
+ PINCTRL_PIN(DB8500_PIN_AE26, "GPIO262_AE26"),
+ PINCTRL_PIN(DB8500_PIN_AG29, "GPIO263_AG29"),
+ PINCTRL_PIN(DB8500_PIN_AE27, "GPIO264_AE27"),
+ PINCTRL_PIN(DB8500_PIN_AD27, "GPIO265_AD27"),
+ PINCTRL_PIN(DB8500_PIN_AC28, "GPIO266_AC28"),
+ PINCTRL_PIN(DB8500_PIN_AC27, "GPIO267_AC27"),
+};
+
+#define DB8500_GPIO_RANGE(a, b, c) { .name = "DB8500", .id = a, .base = b, \
+ .pin_base = b, .npins = c }
+
+/*
+ * This matches the 32-pin gpio chips registered by the GPIO portion. This
+ * cannot be const since we assign the struct gpio_chip * pointer at runtime.
+ */
+static struct pinctrl_gpio_range nmk_db8500_ranges[] = {
+ DB8500_GPIO_RANGE(0, 0, 32),
+ DB8500_GPIO_RANGE(1, 32, 5),
+ DB8500_GPIO_RANGE(2, 64, 32),
+ DB8500_GPIO_RANGE(3, 96, 2),
+ DB8500_GPIO_RANGE(4, 128, 32),
+ DB8500_GPIO_RANGE(5, 160, 12),
+ DB8500_GPIO_RANGE(6, 192, 32),
+ DB8500_GPIO_RANGE(7, 224, 7),
+ DB8500_GPIO_RANGE(8, 256, 12),
+};
+
+/*
+ * Read the pin group names like this:
+ * u0_a_1 = first groups of pins for uart0 on alt function a
+ * i2c2_b_2 = second group of pins for i2c2 on alt function b
+ *
+ * The groups are arranged as sets per altfunction column, so we can
+ * mux in one group at a time by selecting the same altfunction for them
+ * all. When functions require pins on different altfunctions, you need
+ * to combine several groups.
+ */
+
+/* Altfunction A column */
+static const unsigned u0_a_1_pins[] = { DB8500_PIN_AJ5, DB8500_PIN_AJ3,
+ DB8500_PIN_AH4, DB8500_PIN_AH3 };
+static const unsigned u1rxtx_a_1_pins[] = { DB8500_PIN_AH6, DB8500_PIN_AG6 };
+static const unsigned u1ctsrts_a_1_pins[] = { DB8500_PIN_AF6, DB8500_PIN_AG5 };
+/* Image processor I2C line, this is driven by image processor firmware */
+static const unsigned ipi2c_a_1_pins[] = { DB8500_PIN_AD5, DB8500_PIN_AE4 };
+static const unsigned ipi2c_a_2_pins[] = { DB8500_PIN_AF5, DB8500_PIN_AG4 };
+/* MSP0 can only be on these pins, but TXD and RXD can be flipped */
+static const unsigned msp0txrx_a_1_pins[] = { DB8500_PIN_AC4, DB8500_PIN_AC3 };
+static const unsigned msp0tfstck_a_1_pins[] = { DB8500_PIN_AF3, DB8500_PIN_AE3 };
+static const unsigned msp0rfsrck_a_1_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 };
+/* Basic pins of the MMC/SD card 0 interface */
+static const unsigned mc0_a_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1,
+ DB8500_PIN_AB4, DB8500_PIN_AA3, DB8500_PIN_AA4, DB8500_PIN_AB2,
+ DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+/* Often only 4 bits are used, then these are not needed (only used for MMC) */
+static const unsigned mc0_dat47_a_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3,
+ DB8500_PIN_V3, DB8500_PIN_V2};
+static const unsigned mc0dat31dir_a_1_pins[] = { DB8500_PIN_AB3 };
+/* MSP1 can only be on these pins, but TXD and RXD can be flipped */
+static const unsigned msp1txrx_a_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AG2 };
+static const unsigned msp1_a_1_pins[] = { DB8500_PIN_AE1, DB8500_PIN_AE2 };
+/* LCD interface */
+static const unsigned lcdb_a_1_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1,
+ DB8500_PIN_G3, DB8500_PIN_G2 };
+static const unsigned lcdvsi0_a_1_pins[] = { DB8500_PIN_E1 };
+static const unsigned lcdvsi1_a_1_pins[] = { DB8500_PIN_E2 };
+static const unsigned lcd_d0_d7_a_1_pins[] = {
+ DB8500_PIN_G5, DB8500_PIN_G4, DB8500_PIN_H4, DB8500_PIN_H3,
+ DB8500_PIN_J3, DB8500_PIN_H2, DB8500_PIN_J2, DB8500_PIN_H1 };
+/* D8 thru D11 often used as TVOUT lines */
+static const unsigned lcd_d8_d11_a_1_pins[] = { DB8500_PIN_F4,
+ DB8500_PIN_E3, DB8500_PIN_E4, DB8500_PIN_D2 };
+static const unsigned lcd_d12_d23_a_1_pins[] = {
+ DB8500_PIN_C1, DB8500_PIN_D3, DB8500_PIN_C2, DB8500_PIN_D5,
+ DB8500_PIN_C6, DB8500_PIN_B3, DB8500_PIN_C4, DB8500_PIN_E6,
+ DB8500_PIN_A3, DB8500_PIN_B6, DB8500_PIN_D6, DB8500_PIN_B7 };
+static const unsigned kp_a_1_pins[] = { DB8500_PIN_D7, DB8500_PIN_E8,
+ DB8500_PIN_D8, DB8500_PIN_D9 };
+static const unsigned kpskaskb_a_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16 };
+static const unsigned kp_a_2_pins[] = {
+ DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
+ DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
+ DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21,
+ DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
+/* MC2 has 8 data lines and no direction control, so only for (e)MMC */
+static const unsigned mc2_a_1_pins[] = { DB8500_PIN_A5, DB8500_PIN_B4,
+ DB8500_PIN_C8, DB8500_PIN_A12, DB8500_PIN_C10, DB8500_PIN_B10,
+ DB8500_PIN_B9, DB8500_PIN_A9, DB8500_PIN_C7, DB8500_PIN_A7,
+ DB8500_PIN_C5 };
+static const unsigned ssp1_a_1_pins[] = { DB8500_PIN_C9, DB8500_PIN_B11,
+ DB8500_PIN_C12, DB8500_PIN_C11 };
+static const unsigned ssp0_a_1_pins[] = { DB8500_PIN_D12, DB8500_PIN_B13,
+ DB8500_PIN_C13, DB8500_PIN_D13 };
+static const unsigned i2c0_a_1_pins[] = { DB8500_PIN_C15, DB8500_PIN_B16 };
+/*
+ * Image processor GPIO pins are named "ipgpio" and have their own
+ * numberspace
+ */
+static const unsigned ipgpio0_a_1_pins[] = { DB8500_PIN_B14 };
+static const unsigned ipgpio1_a_1_pins[] = { DB8500_PIN_C14 };
+/* Three modem pins named RF_PURn, MODEM_STATE and MODEM_PWREN */
+static const unsigned modem_a_1_pins[] = { DB8500_PIN_D22, DB8500_PIN_C23,
+ DB8500_PIN_D23 };
+/*
+ * This MSP cannot switch RX and TX, SCK in a separate group since this
+ * seems to be optional.
+ */
+static const unsigned msp2sck_a_1_pins[] = { DB8500_PIN_AJ27 };
+static const unsigned msp2_a_1_pins[] = { DB8500_PIN_AH27, DB8500_PIN_AF27,
+ DB8500_PIN_AG28, DB8500_PIN_AG26 };
+static const unsigned mc4_a_1_pins[] = { DB8500_PIN_AH24, DB8500_PIN_AG25,
+ DB8500_PIN_AH23, DB8500_PIN_AH26, DB8500_PIN_AF24, DB8500_PIN_AF25,
+ DB8500_PIN_AE23, DB8500_PIN_AF23, DB8500_PIN_AG23, DB8500_PIN_AG24,
+ DB8500_PIN_AJ23 };
+/* MC1 has only 4 data pins, designed for SD or SDIO exclusively */
+static const unsigned mc1_a_1_pins[] = { DB8500_PIN_AH16, DB8500_PIN_AG15,
+ DB8500_PIN_AJ15, DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13,
+ DB8500_PIN_AH15 };
+static const unsigned mc1dir_a_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
+ DB8500_PIN_AH12, DB8500_PIN_AH11 };
+static const unsigned hsir_a_1_pins[] = { DB8500_PIN_AG10, DB8500_PIN_AH10 };
+static const unsigned hsit_a_1_pins[] = { DB8500_PIN_AJ11, DB8500_PIN_AJ9,
+ DB8500_PIN_AH9, DB8500_PIN_AG9, DB8500_PIN_AG8, DB8500_PIN_AF8 };
+static const unsigned clkout_a_1_pins[] = { DB8500_PIN_AH7, DB8500_PIN_AJ6 };
+static const unsigned clkout_a_2_pins[] = { DB8500_PIN_AG7, DB8500_PIN_AF7 };
+static const unsigned usb_a_1_pins[] = { DB8500_PIN_AF28, DB8500_PIN_AE29,
+ DB8500_PIN_AD29, DB8500_PIN_AC29, DB8500_PIN_AD28, DB8500_PIN_AD26,
+ DB8500_PIN_AE26, DB8500_PIN_AG29, DB8500_PIN_AE27, DB8500_PIN_AD27,
+ DB8500_PIN_AC28, DB8500_PIN_AC27 };
+
+/* Altfunction B column */
+static const unsigned trig_b_1_pins[] = { DB8500_PIN_AJ5, DB8500_PIN_AJ3 };
+static const unsigned i2c4_b_1_pins[] = { DB8500_PIN_AH6, DB8500_PIN_AG6 };
+static const unsigned i2c1_b_1_pins[] = { DB8500_PIN_AF6, DB8500_PIN_AG5 };
+static const unsigned i2c2_b_1_pins[] = { DB8500_PIN_AD5, DB8500_PIN_AE4 };
+static const unsigned i2c2_b_2_pins[] = { DB8500_PIN_AF5, DB8500_PIN_AG4 };
+static const unsigned msp0txrx_b_1_pins[] = { DB8500_PIN_AC4, DB8500_PIN_AC3 };
+static const unsigned i2c1_b_2_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 };
+/* Just RX and TX for UART2 */
+static const unsigned u2rxtx_b_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1 };
+static const unsigned uartmodtx_b_1_pins[] = { DB8500_PIN_AB4 };
+static const unsigned msp0sck_b_1_pins[] = { DB8500_PIN_AB3 };
+static const unsigned uartmodrx_b_1_pins[] = { DB8500_PIN_AA3 };
+static const unsigned stmmod_b_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_Y4,
+ DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+static const unsigned uartmodrx_b_2_pins[] = { DB8500_PIN_AB2 };
+static const unsigned spi3_b_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3,
+ DB8500_PIN_V3, DB8500_PIN_V2 };
+static const unsigned msp1txrx_b_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AG2 };
+static const unsigned kp_b_1_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1,
+ DB8500_PIN_G3, DB8500_PIN_G2, DB8500_PIN_E1, DB8500_PIN_E2,
+ DB8500_PIN_G5, DB8500_PIN_G4, DB8500_PIN_H4, DB8500_PIN_H3,
+ DB8500_PIN_J3, DB8500_PIN_H2, DB8500_PIN_J2, DB8500_PIN_H1,
+ DB8500_PIN_F4, DB8500_PIN_E3, DB8500_PIN_E4, DB8500_PIN_D2,
+ DB8500_PIN_C1, DB8500_PIN_D3, DB8500_PIN_C2, DB8500_PIN_D5 };
+static const unsigned sm_b_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3,
+ DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6,
+ DB8500_PIN_D6, DB8500_PIN_B7, DB8500_PIN_D7, DB8500_PIN_D8,
+ DB8500_PIN_D9, DB8500_PIN_A5, DB8500_PIN_B4, DB8500_PIN_C8,
+ DB8500_PIN_A12, DB8500_PIN_C10, DB8500_PIN_B10, DB8500_PIN_B9,
+ DB8500_PIN_A9, DB8500_PIN_C7, DB8500_PIN_A7, DB8500_PIN_C5,
+ DB8500_PIN_C9, DB8500_PIN_B14 };
+/* This chip select pin can be "ps0" in alt B so have it separately */
+static const unsigned smcs0_b_1_pins[] = { DB8500_PIN_E8 };
+static const unsigned ipgpio7_b_1_pins[] = { DB8500_PIN_B11 };
+static const unsigned ipgpio2_b_1_pins[] = { DB8500_PIN_C12 };
+static const unsigned ipgpio3_b_1_pins[] = { DB8500_PIN_C11 };
+static const unsigned lcdaclk_b_1_pins[] = { DB8500_PIN_C14 };
+static const unsigned lcda_b_1_pins[] = { DB8500_PIN_D22,
+ DB8500_PIN_C23, DB8500_PIN_D23 };
+static const unsigned lcd_b_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
+ DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
+ DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
+ DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21,
+ DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
+static const unsigned ddrtrig_b_1_pins[] = { DB8500_PIN_AJ27 };
+static const unsigned pwl_b_1_pins[] = { DB8500_PIN_AF25 };
+static const unsigned spi1_b_1_pins[] = { DB8500_PIN_AG15, DB8500_PIN_AF13,
+ DB8500_PIN_AG13, DB8500_PIN_AH15 };
+static const unsigned mc3_b_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
+ DB8500_PIN_AH12, DB8500_PIN_AH11, DB8500_PIN_AG10, DB8500_PIN_AH10,
+ DB8500_PIN_AJ11, DB8500_PIN_AJ9, DB8500_PIN_AH9, DB8500_PIN_AG9,
+ DB8500_PIN_AG8 };
+static const unsigned pwl_b_2_pins[] = { DB8500_PIN_AF8 };
+static const unsigned pwl_b_3_pins[] = { DB8500_PIN_AG7 };
+static const unsigned pwl_b_4_pins[] = { DB8500_PIN_AF7 };
+
+/* Altfunction C column */
+static const unsigned ipjtag_c_1_pins[] = { DB8500_PIN_AJ5, DB8500_PIN_AJ3,
+ DB8500_PIN_AH4, DB8500_PIN_AH3, DB8500_PIN_AH6 };
+static const unsigned ipgpio6_c_1_pins[] = { DB8500_PIN_AG6 };
+static const unsigned ipgpio0_c_1_pins[] = { DB8500_PIN_AF6 };
+static const unsigned ipgpio1_c_1_pins[] = { DB8500_PIN_AG5 };
+static const unsigned ipgpio3_c_1_pins[] = { DB8500_PIN_AF5 };
+static const unsigned ipgpio2_c_1_pins[] = { DB8500_PIN_AG4 };
+static const unsigned slim0_c_1_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 };
+/* Optional 4-bit Memory Stick interface */
+static const unsigned ms_c_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1,
+ DB8500_PIN_AB3, DB8500_PIN_AA3, DB8500_PIN_AA4, DB8500_PIN_AB2,
+ DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+static const unsigned iptrigout_c_1_pins[] = { DB8500_PIN_AB4 };
+static const unsigned u2rxtx_c_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3 };
+static const unsigned u2ctsrts_c_1_pins[] = { DB8500_PIN_V3, DB8500_PIN_V2 };
+static const unsigned u0_c_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AE1,
+ DB8500_PIN_AE2, DB8500_PIN_AG2 };
+static const unsigned ipgpio4_c_1_pins[] = { DB8500_PIN_F3 };
+static const unsigned ipgpio5_c_1_pins[] = { DB8500_PIN_F1 };
+static const unsigned ipgpio6_c_2_pins[] = { DB8500_PIN_G3 };
+static const unsigned ipgpio7_c_1_pins[] = { DB8500_PIN_G2 };
+static const unsigned smcleale_c_1_pins[] = { DB8500_PIN_E1, DB8500_PIN_E2 };
+static const unsigned stmape_c_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+ DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3 };
+static const unsigned u2rxtx_c_2_pins[] = { DB8500_PIN_H2, DB8500_PIN_J2 };
+static const unsigned ipgpio2_c_2_pins[] = { DB8500_PIN_F4 };
+static const unsigned ipgpio3_c_2_pins[] = { DB8500_PIN_E3 };
+static const unsigned ipgpio4_c_2_pins[] = { DB8500_PIN_E4 };
+static const unsigned ipgpio5_c_2_pins[] = { DB8500_PIN_D2 };
+static const unsigned mc5_c_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3,
+ DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6,
+ DB8500_PIN_D6, DB8500_PIN_B7, DB8500_PIN_D7, DB8500_PIN_D8,
+ DB8500_PIN_D9 };
+static const unsigned mc2rstn_c_1_pins[] = { DB8500_PIN_C8 };
+static const unsigned kp_c_1_pins[] = { DB8500_PIN_C9, DB8500_PIN_B11,
+ DB8500_PIN_C12, DB8500_PIN_C11, DB8500_PIN_D17, DB8500_PIN_D16,
+ DB8500_PIN_C23, DB8500_PIN_D23 };
+static const unsigned smps1_c_1_pins[] = { DB8500_PIN_B14 };
+static const unsigned u2rxtx_c_3_pins[] = { DB8500_PIN_B17, DB8500_PIN_C16 };
+static const unsigned stmape_c_2_pins[] = { DB8500_PIN_C19, DB8500_PIN_C17,
+ DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19 };
+static const unsigned uartmodrx_c_1_pins[] = { DB8500_PIN_D21 };
+static const unsigned uartmodtx_c_1_pins[] = { DB8500_PIN_D20 };
+static const unsigned stmmod_c_1_pins[] = { DB8500_PIN_C20, DB8500_PIN_B21,
+ DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24 };
+static const unsigned usbsim_c_1_pins[] = { DB8500_PIN_D22 };
+static const unsigned mc4rstn_c_1_pins[] = { DB8500_PIN_AF25 };
+static const unsigned clkout_c_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AH12 };
+static const unsigned i2c3_c_1_pins[] = { DB8500_PIN_AG12, DB8500_PIN_AH11 };
+static const unsigned spi0_c_1_pins[] = { DB8500_PIN_AH10, DB8500_PIN_AH9,
+ DB8500_PIN_AG9, DB8500_PIN_AG8 };
+static const unsigned usbsim_c_2_pins[] = { DB8500_PIN_AF8 };
+static const unsigned i2c3_c_2_pins[] = { DB8500_PIN_AG7, DB8500_PIN_AF7 };
+
+/* Other C1 column */
+static const unsigned kp_oc1_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3,
+ DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6,
+ DB8500_PIN_D6, DB8500_PIN_B7 };
+static const unsigned spi2_oc1_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
+ DB8500_PIN_AH12, DB8500_PIN_AH11 };
+
+#define DB8500_PIN_GROUP(a,b) { .name = #a, .pins = a##_pins, \
+ .npins = ARRAY_SIZE(a##_pins), .altsetting = b }
+
+static const struct nmk_pingroup nmk_db8500_groups[] = {
+ /* Altfunction A column */
+ DB8500_PIN_GROUP(u0_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(u1rxtx_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(u1ctsrts_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(ipi2c_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(ipi2c_a_2, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(msp0txrx_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(msp0tfstck_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(msp0rfsrck_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(mc0_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(msp1txrx_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(msp1_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(lcdb_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(lcdvsi0_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(lcdvsi1_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(lcd_d0_d7_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(lcd_d8_d11_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(lcd_d12_d23_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(kp_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(mc2_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(ssp1_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(ssp0_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(ipgpio0_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(ipgpio1_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(msp2sck_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(msp2_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(mc4_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(mc1_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(clkout_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(clkout_a_2, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A),
+ /* Altfunction B column */
+ DB8500_PIN_GROUP(trig_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(i2c4_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(i2c1_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(i2c2_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(i2c2_b_2, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(msp0txrx_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(i2c1_b_2, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(u2rxtx_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(uartmodtx_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(msp0sck_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(uartmodrx_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(stmmod_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(uartmodrx_b_2, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(spi3_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(msp1txrx_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(kp_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(sm_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(smcs0_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(ipgpio7_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(ipgpio2_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(ipgpio3_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(lcdaclk_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(lcda_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(lcd_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(ddrtrig_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(pwl_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(spi1_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(mc3_b_1, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(pwl_b_2, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(pwl_b_3, NMK_GPIO_ALT_B),
+ DB8500_PIN_GROUP(pwl_b_4, NMK_GPIO_ALT_B),
+ /* Altfunction C column */
+ DB8500_PIN_GROUP(ipjtag_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ipgpio6_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ipgpio0_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ipgpio1_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ipgpio3_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ipgpio2_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(slim0_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ms_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(iptrigout_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(u2rxtx_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(u2ctsrts_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(u0_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ipgpio4_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ipgpio5_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ipgpio6_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ipgpio7_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(smcleale_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(stmape_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(u2rxtx_c_2, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ipgpio2_c_2, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ipgpio3_c_2, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ipgpio4_c_2, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(ipgpio5_c_2, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(mc5_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(mc2rstn_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(kp_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(smps1_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(u2rxtx_c_3, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(stmape_c_2, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(uartmodrx_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(uartmodtx_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(stmmod_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(usbsim_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(mc4rstn_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(clkout_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(i2c3_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(usbsim_c_2, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(i2c3_c_2, NMK_GPIO_ALT_C),
+ /* Other alt C1 column, these are still configured as alt C */
+ DB8500_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(spi2_oc1_1, NMK_GPIO_ALT_C),
+};
+
+/* We use this macro to define the groups applicable to a function */
+#define DB8500_FUNC_GROUPS(a, b...) \
+static const char * const a##_groups[] = { b };
+
+DB8500_FUNC_GROUPS(u0, "u0_a_1", "u0_c_1");
+DB8500_FUNC_GROUPS(u1, "u1rxtx_a_1", "u1ctsrts_a_1");
+/*
+ * UART2 can be muxed out with just RX/TX in four places, CTS+RTS is however
+ * only available on two pins in alternative function C
+ */
+DB8500_FUNC_GROUPS(u2, "u2rxtx_b_1", "u2rxtx_c_1", "u2ctsrts_c_1",
+ "u2rxtx_c_2", "u2rxtx_c_3");
+DB8500_FUNC_GROUPS(ipi2c, "ipi2c_a_1", "ipi2c_a_2");
+/*
+ * MSP0 can only be on a certain set of pins, but the TX/RX pins can be
+ * switched around by selecting the altfunction A or B. The SCK pin is
+ * only available on the altfunction B.
+ */
+DB8500_FUNC_GROUPS(msp0, "msp0txrx_a_1", "msp0tfstck_a_1", "msp0rfstck_a_1",
+ "msp0txrx_b_1", "msp0sck_b_1");
+DB8500_FUNC_GROUPS(mc0, "mc0_a_1");
+/* MSP0 can swap RX/TX like MSP0 but has no SCK pin available */
+DB8500_FUNC_GROUPS(msp1, "msp1txrx_a_1", "msp1_a_1", "msp1txrx_b_1");
+DB8500_FUNC_GROUPS(lcdb, "lcdb_a_1");
+DB8500_FUNC_GROUPS(lcd, "lcdvsi0_a_1", "lcdvsi1_a_1", "lcd_d0_d7_a_1",
+ "lcd_d8_d11_a_1", "lcd_d12_d23_a_1", "lcd_b_1");
+DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_c_1", "kp_oc1_1");
+DB8500_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1");
+DB8500_FUNC_GROUPS(ssp1, "ssp1_a_1");
+DB8500_FUNC_GROUPS(ssp0, "ssp0_a_1");
+DB8500_FUNC_GROUPS(i2c0, "i2c0_a_1");
+/* The image processor has 8 GPIO pins that can be muxed out */
+DB8500_FUNC_GROUPS(ipgpio, "ipgpio0_a_1", "ipgpio1_a_1", "ipgpio7_b_1",
+ "ipgpio2_b_1", "ipgpio3_b_1", "ipgpio6_c_1", "ipgpio0_c_1",
+ "ipgpio1_c_1", "ipgpio3_c_1", "ipgpio2_c_1", "ipgpio4_c_1",
+ "ipgpio5_c_1", "ipgpio6_c_2", "ipgpio7_c_1", "ipgpio2_c_2",
+ "ipgpio3_c_2", "ipgpio4_c_2", "ipgpio5_c_2");
+/* MSP2 can not invert the RX/TX pins but has the optional SCK pin */
+DB8500_FUNC_GROUPS(msp2, "msp2sck_a_1", "msp2_a_1");
+DB8500_FUNC_GROUPS(mc4, "mc4_a_1", "mc4rstn_c_1");
+DB8500_FUNC_GROUPS(mc1, "mc1_a_1", "mc1dir_a_1");
+DB8500_FUNC_GROUPS(hsi, "hsir1_a_1", "hsit1_a_1");
+DB8500_FUNC_GROUPS(clkout, "clkout_a_1", "clkout_a_2", "clkout_c_1");
+DB8500_FUNC_GROUPS(usb, "usb_a_1");
+DB8500_FUNC_GROUPS(trig, "trig_b_1");
+DB8500_FUNC_GROUPS(i2c4, "i2c4_b_1");
+DB8500_FUNC_GROUPS(i2c1, "i2c1_b_1", "i2c1_b_2");
+DB8500_FUNC_GROUPS(i2c2, "i2c2_b_1", "i2c2_b_2");
+/*
+ * The modem UART can output its RX and TX pins in some different places,
+ * so select one of each.
+ */
+DB8500_FUNC_GROUPS(uartmod, "uartmodtx_b_1", "uartmodrx_b_1", "uartmodrx_b_2",
+ "uartmodrx_c_1", "uartmod_tx_c_1");
+DB8500_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_c_1");
+DB8500_FUNC_GROUPS(spi3, "spi3_b_1");
+/* Select between CS0 on alt B or PS1 on alt C */
+DB8500_FUNC_GROUPS(sm, "sm_b_1", "smcs0_b_1", "smcleale_c_1", "smps1_c_1");
+DB8500_FUNC_GROUPS(lcda, "lcdaclk_b_1", "lcda_b_1");
+DB8500_FUNC_GROUPS(ddrtrig, "ddrtrig_b_1");
+DB8500_FUNC_GROUPS(pwl, "pwl_b_1", "pwl_b_2", "pwl_b_3", "pwl_b_4");
+DB8500_FUNC_GROUPS(spi1, "spi1_b_1");
+DB8500_FUNC_GROUPS(mc3, "mc3_b_1");
+DB8500_FUNC_GROUPS(ipjtag, "ipjtag_c_1");
+DB8500_FUNC_GROUPS(slim0, "slim0_c_1");
+DB8500_FUNC_GROUPS(ms, "ms_c_1");
+DB8500_FUNC_GROUPS(iptrigout, "iptrigout_c_1");
+DB8500_FUNC_GROUPS(stmape, "stmape_c_1", "stmape_c_2");
+DB8500_FUNC_GROUPS(mc5, "mc5_c_1");
+DB8500_FUNC_GROUPS(usbsim, "usbsim_c_1", "usbsim_c_2");
+DB8500_FUNC_GROUPS(i2c3, "i2c3_c_1", "i2c3_c_2");
+DB8500_FUNC_GROUPS(spi0, "spi0_c_1");
+DB8500_FUNC_GROUPS(spi2, "spi2_oc1_1");
+
+#define FUNCTION(fname) \
+ { \
+ .name = #fname, \
+ .groups = fname##_groups, \
+ .ngroups = ARRAY_SIZE(fname##_groups), \
+ }
+
+static const struct nmk_function nmk_db8500_functions[] = {
+ FUNCTION(u0),
+ FUNCTION(u1),
+ FUNCTION(u2),
+ FUNCTION(ipi2c),
+ FUNCTION(msp0),
+ FUNCTION(mc0),
+ FUNCTION(msp1),
+ FUNCTION(lcdb),
+ FUNCTION(lcd),
+ FUNCTION(kp),
+ FUNCTION(mc2),
+ FUNCTION(ssp1),
+ FUNCTION(ssp0),
+ FUNCTION(i2c0),
+ FUNCTION(ipgpio),
+ FUNCTION(msp2),
+ FUNCTION(mc4),
+ FUNCTION(mc1),
+ FUNCTION(hsi),
+ FUNCTION(clkout),
+ FUNCTION(usb),
+ FUNCTION(trig),
+ FUNCTION(i2c4),
+ FUNCTION(i2c1),
+ FUNCTION(i2c2),
+ FUNCTION(uartmod),
+ FUNCTION(stmmod),
+ FUNCTION(spi3),
+ FUNCTION(sm),
+ FUNCTION(lcda),
+ FUNCTION(ddrtrig),
+ FUNCTION(pwl),
+ FUNCTION(spi1),
+ FUNCTION(mc3),
+ FUNCTION(ipjtag),
+ FUNCTION(slim0),
+ FUNCTION(ms),
+ FUNCTION(iptrigout),
+ FUNCTION(stmape),
+ FUNCTION(mc5),
+ FUNCTION(usbsim),
+ FUNCTION(i2c3),
+ FUNCTION(spi0),
+ FUNCTION(spi2),
+};
+
+static const struct nmk_pinctrl_soc_data nmk_db8500_soc = {
+ .gpio_ranges = nmk_db8500_ranges,
+ .gpio_num_ranges = ARRAY_SIZE(nmk_db8500_ranges),
+ .pins = nmk_db8500_pins,
+ .npins = ARRAY_SIZE(nmk_db8500_pins),
+ .functions = nmk_db8500_functions,
+ .nfunctions = ARRAY_SIZE(nmk_db8500_functions),
+ .groups = nmk_db8500_groups,
+ .ngroups = ARRAY_SIZE(nmk_db8500_groups),
+};
+
+void __devinit
+nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc)
+{
+ *soc = &nmk_db8500_soc;
+}
diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index 839624f9fe6a..b8e01c3eaa95 100644
--- a/drivers/gpio/gpio-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -22,14 +22,20 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/slab.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+/* Since we request GPIOs from ourself */
+#include <linux/pinctrl/consumer.h>
#include <asm/mach/irq.h>
#include <plat/pincfg.h>
#include <plat/gpio-nomadik.h>
-#include <mach/hardware.h>
-#include <asm/gpio.h>
+
+#include "pinctrl-nomadik.h"
/*
* The GPIO module in the Nomadik family of Systems-on-Chip is an
@@ -43,6 +49,7 @@
struct nmk_gpio_chip {
struct gpio_chip chip;
+ struct irq_domain *domain;
void __iomem *addr;
struct clk *clk;
unsigned int bank;
@@ -58,8 +65,16 @@ struct nmk_gpio_chip {
u32 real_wake;
u32 rwimsc;
u32 fwimsc;
- u32 slpm;
+ u32 rimsc;
+ u32 fimsc;
u32 pull_up;
+ u32 lowemi;
+};
+
+struct nmk_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+ const struct nmk_pinctrl_soc_data *soc;
};
static struct nmk_gpio_chip *
@@ -124,6 +139,24 @@ static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip,
}
}
+static void __nmk_gpio_set_lowemi(struct nmk_gpio_chip *nmk_chip,
+ unsigned offset, bool lowemi)
+{
+ u32 bit = BIT(offset);
+ bool enabled = nmk_chip->lowemi & bit;
+
+ if (lowemi == enabled)
+ return;
+
+ if (lowemi)
+ nmk_chip->lowemi |= bit;
+ else
+ nmk_chip->lowemi &= ~bit;
+
+ writel_relaxed(nmk_chip->lowemi,
+ nmk_chip->addr + NMK_GPIO_LOWEMI);
+}
+
static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip,
unsigned offset)
{
@@ -150,8 +183,8 @@ static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip,
unsigned offset, int gpio_mode,
bool glitch)
{
- u32 rwimsc = readl(nmk_chip->addr + NMK_GPIO_RWIMSC);
- u32 fwimsc = readl(nmk_chip->addr + NMK_GPIO_FWIMSC);
+ u32 rwimsc = nmk_chip->rwimsc;
+ u32 fwimsc = nmk_chip->fwimsc;
if (glitch && nmk_chip->set_ioforce) {
u32 bit = BIT(offset);
@@ -173,6 +206,36 @@ static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip,
}
}
+static void
+nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset)
+{
+ u32 falling = nmk_chip->fimsc & BIT(offset);
+ u32 rising = nmk_chip->rimsc & BIT(offset);
+ int gpio = nmk_chip->chip.base + offset;
+ int irq = NOMADIK_GPIO_TO_IRQ(gpio);
+ struct irq_data *d = irq_get_irq_data(irq);
+
+ if (!rising && !falling)
+ return;
+
+ if (!d || !irqd_irq_disabled(d))
+ return;
+
+ if (rising) {
+ nmk_chip->rimsc &= ~BIT(offset);
+ writel_relaxed(nmk_chip->rimsc,
+ nmk_chip->addr + NMK_GPIO_RIMSC);
+ }
+
+ if (falling) {
+ nmk_chip->fimsc &= ~BIT(offset);
+ writel_relaxed(nmk_chip->fimsc,
+ nmk_chip->addr + NMK_GPIO_FIMSC);
+ }
+
+ dev_dbg(nmk_chip->chip.dev, "%d: clearing interrupt mask\n", gpio);
+}
+
static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
pin_cfg_t cfg, bool sleep, unsigned int *slpmregs)
{
@@ -238,6 +301,17 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
__nmk_gpio_set_pull(nmk_chip, offset, pull);
}
+ __nmk_gpio_set_lowemi(nmk_chip, offset, PIN_LOWEMI(cfg));
+
+ /*
+ * If the pin is switching to altfunc, and there was an interrupt
+ * installed on it which has been lazy disabled, actually mask the
+ * interrupt to prevent spurious interrupts that would occur while the
+ * pin is under control of the peripheral. Only SKE does this.
+ */
+ if (af != NMK_GPIO_ALT_GPIO)
+ nmk_gpio_disable_lazy_irq(nmk_chip, offset);
+
/*
* If we've backed up the SLPM registers (glitch workaround), modify
* the backups since they will be restored.
@@ -334,7 +408,7 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
struct nmk_gpio_chip *nmk_chip;
int pin = PIN_NUM(cfgs[i]);
- nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(pin));
+ nmk_chip = nmk_gpio_chips[pin / NMK_GPIO_PER_CHIP];
if (!nmk_chip) {
ret = -EINVAL;
break;
@@ -342,7 +416,7 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
clk_enable(nmk_chip->clk);
spin_lock(&nmk_chip->lock);
- __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base,
+ __nmk_config_pin(nmk_chip, pin % NMK_GPIO_PER_CHIP,
cfgs[i], sleep, glitch ? slpm : NULL);
spin_unlock(&nmk_chip->lock);
clk_disable(nmk_chip->clk);
@@ -426,7 +500,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
struct nmk_gpio_chip *nmk_chip;
unsigned long flags;
- nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+ nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
if (!nmk_chip)
return -EINVAL;
@@ -434,7 +508,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
spin_lock(&nmk_chip->lock);
- __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode);
+ __nmk_gpio_set_slpm(nmk_chip, gpio % NMK_GPIO_PER_CHIP, mode);
spin_unlock(&nmk_chip->lock);
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
@@ -461,13 +535,13 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull)
struct nmk_gpio_chip *nmk_chip;
unsigned long flags;
- nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+ nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
if (!nmk_chip)
return -EINVAL;
clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_chip->lock, flags);
- __nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull);
+ __nmk_gpio_set_pull(nmk_chip, gpio % NMK_GPIO_PER_CHIP, pull);
spin_unlock_irqrestore(&nmk_chip->lock, flags);
clk_disable(nmk_chip->clk);
@@ -489,13 +563,13 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode)
struct nmk_gpio_chip *nmk_chip;
unsigned long flags;
- nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+ nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
if (!nmk_chip)
return -EINVAL;
clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_chip->lock, flags);
- __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode);
+ __nmk_gpio_set_mode(nmk_chip, gpio % NMK_GPIO_PER_CHIP, gpio_mode);
spin_unlock_irqrestore(&nmk_chip->lock, flags);
clk_disable(nmk_chip->clk);
@@ -508,11 +582,11 @@ int nmk_gpio_get_mode(int gpio)
struct nmk_gpio_chip *nmk_chip;
u32 afunc, bfunc, bit;
- nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+ nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
if (!nmk_chip)
return -EINVAL;
- bit = 1 << (gpio - nmk_chip->chip.base);
+ bit = 1 << (gpio % NMK_GPIO_PER_CHIP);
clk_enable(nmk_chip->clk);
@@ -529,21 +603,19 @@ EXPORT_SYMBOL(nmk_gpio_get_mode);
/* IRQ functions */
static inline int nmk_gpio_get_bitmask(int gpio)
{
- return 1 << (gpio % 32);
+ return 1 << (gpio % NMK_GPIO_PER_CHIP);
}
static void nmk_gpio_irq_ack(struct irq_data *d)
{
- int gpio;
struct nmk_gpio_chip *nmk_chip;
- gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
nmk_chip = irq_data_get_irq_chip_data(d);
if (!nmk_chip)
return;
clk_enable(nmk_chip->clk);
- writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC);
+ writel(nmk_gpio_get_bitmask(d->hwirq), nmk_chip->addr + NMK_GPIO_IC);
clk_disable(nmk_chip->clk);
}
@@ -556,37 +628,52 @@ static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
int gpio, enum nmk_gpio_irq_type which,
bool enable)
{
- u32 rimsc = which == WAKE ? NMK_GPIO_RWIMSC : NMK_GPIO_RIMSC;
- u32 fimsc = which == WAKE ? NMK_GPIO_FWIMSC : NMK_GPIO_FIMSC;
u32 bitmask = nmk_gpio_get_bitmask(gpio);
- u32 reg;
+ u32 *rimscval;
+ u32 *fimscval;
+ u32 rimscreg;
+ u32 fimscreg;
+
+ if (which == NORMAL) {
+ rimscreg = NMK_GPIO_RIMSC;
+ fimscreg = NMK_GPIO_FIMSC;
+ rimscval = &nmk_chip->rimsc;
+ fimscval = &nmk_chip->fimsc;
+ } else {
+ rimscreg = NMK_GPIO_RWIMSC;
+ fimscreg = NMK_GPIO_FWIMSC;
+ rimscval = &nmk_chip->rwimsc;
+ fimscval = &nmk_chip->fwimsc;
+ }
/* we must individually set/clear the two edges */
if (nmk_chip->edge_rising & bitmask) {
- reg = readl(nmk_chip->addr + rimsc);
if (enable)
- reg |= bitmask;
+ *rimscval |= bitmask;
else
- reg &= ~bitmask;
- writel(reg, nmk_chip->addr + rimsc);
+ *rimscval &= ~bitmask;
+ writel(*rimscval, nmk_chip->addr + rimscreg);
}
if (nmk_chip->edge_falling & bitmask) {
- reg = readl(nmk_chip->addr + fimsc);
if (enable)
- reg |= bitmask;
+ *fimscval |= bitmask;
else
- reg &= ~bitmask;
- writel(reg, nmk_chip->addr + fimsc);
+ *fimscval &= ~bitmask;
+ writel(*fimscval, nmk_chip->addr + fimscreg);
}
}
static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
int gpio, bool on)
{
- if (nmk_chip->sleepmode) {
- __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base,
- on ? NMK_GPIO_SLPM_WAKEUP_ENABLE
- : NMK_GPIO_SLPM_WAKEUP_DISABLE);
+ /*
+ * Ensure WAKEUP_ENABLE is on. No need to disable it if wakeup is
+ * disabled, since setting SLPM to 1 increases power consumption, and
+ * wakeup is anyhow controlled by the RIMSC and FIMSC registers.
+ */
+ if (nmk_chip->sleepmode && on) {
+ __nmk_gpio_set_slpm(nmk_chip, gpio % nmk_chip->chip.base,
+ NMK_GPIO_SLPM_WAKEUP_ENABLE);
}
__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
@@ -594,14 +681,12 @@ static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
{
- int gpio;
struct nmk_gpio_chip *nmk_chip;
unsigned long flags;
u32 bitmask;
- gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
nmk_chip = irq_data_get_irq_chip_data(d);
- bitmask = nmk_gpio_get_bitmask(gpio);
+ bitmask = nmk_gpio_get_bitmask(d->hwirq);
if (!nmk_chip)
return -EINVAL;
@@ -609,10 +694,10 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
spin_lock(&nmk_chip->lock);
- __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, enable);
+ __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, enable);
if (!(nmk_chip->real_wake & bitmask))
- __nmk_gpio_set_wake(nmk_chip, gpio, enable);
+ __nmk_gpio_set_wake(nmk_chip, d->hwirq, enable);
spin_unlock(&nmk_chip->lock);
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
@@ -636,20 +721,18 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
struct nmk_gpio_chip *nmk_chip;
unsigned long flags;
u32 bitmask;
- int gpio;
- gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
nmk_chip = irq_data_get_irq_chip_data(d);
if (!nmk_chip)
return -EINVAL;
- bitmask = nmk_gpio_get_bitmask(gpio);
+ bitmask = nmk_gpio_get_bitmask(d->hwirq);
clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
spin_lock(&nmk_chip->lock);
if (irqd_irq_disabled(d))
- __nmk_gpio_set_wake(nmk_chip, gpio, on);
+ __nmk_gpio_set_wake(nmk_chip, d->hwirq, on);
if (on)
nmk_chip->real_wake |= bitmask;
@@ -667,17 +750,14 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
bool enabled = !irqd_irq_disabled(d);
bool wake = irqd_is_wakeup_set(d);
- int gpio;
struct nmk_gpio_chip *nmk_chip;
unsigned long flags;
u32 bitmask;
- gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
nmk_chip = irq_data_get_irq_chip_data(d);
- bitmask = nmk_gpio_get_bitmask(gpio);
+ bitmask = nmk_gpio_get_bitmask(d->hwirq);
if (!nmk_chip)
return -EINVAL;
-
if (type & IRQ_TYPE_LEVEL_HIGH)
return -EINVAL;
if (type & IRQ_TYPE_LEVEL_LOW)
@@ -687,10 +767,10 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
spin_lock_irqsave(&nmk_chip->lock, flags);
if (enabled)
- __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false);
+ __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, false);
if (enabled || wake)
- __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false);
+ __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, false);
nmk_chip->edge_rising &= ~bitmask;
if (type & IRQ_TYPE_EDGE_RISING)
@@ -701,10 +781,10 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
nmk_chip->edge_falling |= bitmask;
if (enabled)
- __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true);
+ __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, true);
if (enabled || wake)
- __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
+ __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, true);
spin_unlock_irqrestore(&nmk_chip->lock, flags);
clk_disable(nmk_chip->clk);
@@ -750,7 +830,7 @@ static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
chained_irq_enter(host_chip, desc);
nmk_chip = irq_get_handler_data(irq);
- first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
+ first_irq = nmk_chip->domain->revmap_data.legacy.first_irq;
while (status) {
int bit = __ffs(status);
@@ -784,18 +864,6 @@ static void nmk_gpio_secondary_irq_handler(unsigned int irq,
static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
{
- unsigned int first_irq;
- int i;
-
- first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
- for (i = first_irq; i < first_irq + nmk_chip->chip.ngpio; i++) {
- irq_set_chip_and_handler(i, &nmk_gpio_irq_chip,
- handle_edge_irq);
- set_irq_flags(i, IRQF_VALID);
- irq_set_chip_data(i, nmk_chip);
- irq_set_irq_type(i, IRQ_TYPE_EDGE_FALLING);
- }
-
irq_set_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
irq_set_handler_data(nmk_chip->parent_irq, nmk_chip);
@@ -809,6 +877,25 @@ static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
}
/* I/O Functions */
+
+static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ /*
+ * Map back to global GPIO space and request muxing, the direction
+ * parameter does not matter for this controller.
+ */
+ int gpio = chip->base + offset;
+
+ return pinctrl_request_gpio(gpio);
+}
+
+static void nmk_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ int gpio = chip->base + offset;
+
+ pinctrl_free_gpio(gpio);
+}
+
static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
{
struct nmk_gpio_chip *nmk_chip =
@@ -872,21 +959,23 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
- return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset;
+ return irq_find_mapping(nmk_chip->domain, offset);
}
#ifdef CONFIG_DEBUG_FS
#include <linux/seq_file.h>
-static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+static void nmk_gpio_dbg_show_one(struct seq_file *s, struct gpio_chip *chip,
+ unsigned offset, unsigned gpio)
{
- int mode;
- unsigned i;
- unsigned gpio = chip->base;
- int is_out;
+ const char *label = gpiochip_is_requested(chip, offset);
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
+ int mode;
+ bool is_out;
+ bool pull;
+ u32 bit = 1 << offset;
const char *modes[] = {
[NMK_GPIO_ALT_GPIO] = "gpio",
[NMK_GPIO_ALT_A] = "altA",
@@ -895,61 +984,70 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
};
clk_enable(nmk_chip->clk);
-
- for (i = 0; i < chip->ngpio; i++, gpio++) {
- const char *label = gpiochip_is_requested(chip, i);
- bool pull;
- u32 bit = 1 << i;
-
- is_out = readl(nmk_chip->addr + NMK_GPIO_DIR) & bit;
- pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
- mode = nmk_gpio_get_mode(gpio);
- seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
- gpio, label ?: "(none)",
- is_out ? "out" : "in ",
- chip->get
- ? (chip->get(chip, i) ? "hi" : "lo")
- : "? ",
- (mode < 0) ? "unknown" : modes[mode],
- pull ? "pull" : "none");
-
- if (label && !is_out) {
- int irq = gpio_to_irq(gpio);
- struct irq_desc *desc = irq_to_desc(irq);
-
- /* This races with request_irq(), set_irq_type(),
- * and set_irq_wake() ... but those are "rare".
- */
- if (irq >= 0 && desc->action) {
- char *trigger;
- u32 bitmask = nmk_gpio_get_bitmask(gpio);
-
- if (nmk_chip->edge_rising & bitmask)
- trigger = "edge-rising";
- else if (nmk_chip->edge_falling & bitmask)
- trigger = "edge-falling";
- else
- trigger = "edge-undefined";
-
- seq_printf(s, " irq-%d %s%s",
- irq, trigger,
- irqd_is_wakeup_set(&desc->irq_data)
- ? " wakeup" : "");
- }
+ is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & bit);
+ pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
+ mode = nmk_gpio_get_mode(gpio);
+
+ seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
+ gpio, label ?: "(none)",
+ is_out ? "out" : "in ",
+ chip->get
+ ? (chip->get(chip, offset) ? "hi" : "lo")
+ : "? ",
+ (mode < 0) ? "unknown" : modes[mode],
+ pull ? "pull" : "none");
+
+ if (label && !is_out) {
+ int irq = gpio_to_irq(gpio);
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ /* This races with request_irq(), set_irq_type(),
+ * and set_irq_wake() ... but those are "rare".
+ */
+ if (irq >= 0 && desc->action) {
+ char *trigger;
+ u32 bitmask = nmk_gpio_get_bitmask(gpio);
+
+ if (nmk_chip->edge_rising & bitmask)
+ trigger = "edge-rising";
+ else if (nmk_chip->edge_falling & bitmask)
+ trigger = "edge-falling";
+ else
+ trigger = "edge-undefined";
+
+ seq_printf(s, " irq-%d %s%s",
+ irq, trigger,
+ irqd_is_wakeup_set(&desc->irq_data)
+ ? " wakeup" : "");
}
+ }
+ clk_disable(nmk_chip->clk);
+}
+static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+ unsigned i;
+ unsigned gpio = chip->base;
+
+ for (i = 0; i < chip->ngpio; i++, gpio++) {
+ nmk_gpio_dbg_show_one(s, chip, i, gpio);
seq_printf(s, "\n");
}
-
- clk_disable(nmk_chip->clk);
}
#else
+static inline void nmk_gpio_dbg_show_one(struct seq_file *s,
+ struct gpio_chip *chip,
+ unsigned offset, unsigned gpio)
+{
+}
#define nmk_gpio_dbg_show NULL
#endif
/* This structure is replicated for each GPIO block allocated at probe time */
static struct gpio_chip nmk_gpio_template = {
+ .request = nmk_gpio_request,
+ .free = nmk_gpio_free,
.direction_input = nmk_gpio_make_input,
.get = nmk_gpio_get_input,
.direction_output = nmk_gpio_make_output,
@@ -1008,21 +1106,11 @@ void nmk_gpio_wakeups_suspend(void)
clk_enable(chip->clk);
- chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
- chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
-
writel(chip->rwimsc & chip->real_wake,
chip->addr + NMK_GPIO_RWIMSC);
writel(chip->fwimsc & chip->real_wake,
chip->addr + NMK_GPIO_FWIMSC);
- if (chip->sleepmode) {
- chip->slpm = readl(chip->addr + NMK_GPIO_SLPC);
-
- /* 0 -> wakeup enable */
- writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
- }
-
clk_disable(chip->clk);
}
}
@@ -1042,9 +1130,6 @@ void nmk_gpio_wakeups_resume(void)
writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
- if (chip->sleepmode)
- writel(chip->slpm, chip->addr + NMK_GPIO_SLPC);
-
clk_disable(chip->clk);
}
}
@@ -1068,19 +1153,62 @@ void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up)
}
}
+int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct nmk_gpio_chip *nmk_chip = d->host_data;
+
+ if (!nmk_chip)
+ return -EINVAL;
+
+ irq_set_chip_and_handler(irq, &nmk_gpio_irq_chip, handle_edge_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ irq_set_chip_data(irq, nmk_chip);
+ irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);
+
+ return 0;
+}
+
+const struct irq_domain_ops nmk_gpio_irq_simple_ops = {
+ .map = nmk_gpio_irq_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
static int __devinit nmk_gpio_probe(struct platform_device *dev)
{
struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
+ struct device_node *np = dev->dev.of_node;
struct nmk_gpio_chip *nmk_chip;
struct gpio_chip *chip;
struct resource *res;
struct clk *clk;
int secondary_irq;
+ void __iomem *base;
int irq;
int ret;
- if (!pdata)
+ if (!pdata && !np) {
+ dev_err(&dev->dev, "No platform data or device tree found\n");
return -ENODEV;
+ }
+
+ if (np) {
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ if (of_get_property(np, "supports-sleepmode", NULL))
+ pdata->supports_sleepmode = true;
+
+ if (of_property_read_u32(np, "gpio-bank", &dev->id)) {
+ dev_err(&dev->dev, "gpio-bank property not found\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pdata->first_gpio = dev->id * NMK_GPIO_PER_CHIP;
+ pdata->num_gpio = NMK_GPIO_PER_CHIP;
+ }
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!res) {
@@ -1106,10 +1234,16 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
goto out;
}
+ base = ioremap(res->start, resource_size(res));
+ if (!base) {
+ ret = -ENOMEM;
+ goto out_release;
+ }
+
clk = clk_get(&dev->dev, NULL);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
- goto out_release;
+ goto out_unmap;
}
nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL);
@@ -1117,13 +1251,14 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
ret = -ENOMEM;
goto out_clk;
}
+
/*
* The virt address in nmk_chip->addr is in the nomadik register space,
* so we can simply convert the resource address, without remapping
*/
nmk_chip->bank = dev->id;
nmk_chip->clk = clk;
- nmk_chip->addr = io_p2v(res->start);
+ nmk_chip->addr = base;
nmk_chip->chip = nmk_gpio_template;
nmk_chip->parent_irq = irq;
nmk_chip->secondary_parent_irq = secondary_irq;
@@ -1139,6 +1274,14 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
chip->dev = &dev->dev;
chip->owner = THIS_MODULE;
+ clk_enable(nmk_chip->clk);
+ nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI);
+ clk_disable(nmk_chip->clk);
+
+#ifdef CONFIG_OF_GPIO
+ chip->of_node = np;
+#endif
+
ret = gpiochip_add(&nmk_chip->chip);
if (ret)
goto out_free;
@@ -1146,12 +1289,22 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips));
nmk_gpio_chips[nmk_chip->bank] = nmk_chip;
+
platform_set_drvdata(dev, nmk_chip);
+ nmk_chip->domain = irq_domain_add_legacy(np, NMK_GPIO_PER_CHIP,
+ NOMADIK_GPIO_TO_IRQ(pdata->first_gpio),
+ 0, &nmk_gpio_irq_simple_ops, nmk_chip);
+ if (!nmk_chip->domain) {
+ pr_err("%s: Failed to create irqdomain\n", np->full_name);
+ ret = -ENOSYS;
+ goto out_free;
+ }
+
nmk_gpio_init_irq(nmk_chip);
- dev_info(&dev->dev, "at address %p\n",
- nmk_chip->addr);
+ dev_info(&dev->dev, "at address %p\n", nmk_chip->addr);
+
return 0;
out_free:
@@ -1159,25 +1312,465 @@ out_free:
out_clk:
clk_disable(clk);
clk_put(clk);
+out_unmap:
+ iounmap(base);
out_release:
release_mem_region(res->start, resource_size(res));
out:
dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret,
pdata->first_gpio, pdata->first_gpio+31);
+ if (np)
+ kfree(pdata);
+
return ret;
}
+static int nmk_get_groups_cnt(struct pinctrl_dev *pctldev)
+{
+ struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+ return npct->soc->ngroups;
+}
+
+static const char *nmk_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+ return npct->soc->groups[selector].name;
+}
+
+static int nmk_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+ const unsigned **pins,
+ unsigned *num_pins)
+{
+ struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+ *pins = npct->soc->groups[selector].pins;
+ *num_pins = npct->soc->groups[selector].npins;
+ return 0;
+}
+
+static struct pinctrl_gpio_range *
+nmk_match_gpio_range(struct pinctrl_dev *pctldev, unsigned offset)
+{
+ struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+ int i;
+
+ for (i = 0; i < npct->soc->gpio_num_ranges; i++) {
+ struct pinctrl_gpio_range *range;
+
+ range = &npct->soc->gpio_ranges[i];
+ if (offset >= range->pin_base &&
+ offset <= (range->pin_base + range->npins - 1))
+ return range;
+ }
+ return NULL;
+}
+
+static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+ unsigned offset)
+{
+ struct pinctrl_gpio_range *range;
+ struct gpio_chip *chip;
+
+ range = nmk_match_gpio_range(pctldev, offset);
+ if (!range || !range->gc) {
+ seq_printf(s, "invalid pin offset");
+ return;
+ }
+ chip = range->gc;
+ nmk_gpio_dbg_show_one(s, chip, offset - chip->base, offset);
+}
+
+static struct pinctrl_ops nmk_pinctrl_ops = {
+ .get_groups_count = nmk_get_groups_cnt,
+ .get_group_name = nmk_get_group_name,
+ .get_group_pins = nmk_get_group_pins,
+ .pin_dbg_show = nmk_pin_dbg_show,
+};
+
+static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
+{
+ struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+ return npct->soc->nfunctions;
+}
+
+static const char *nmk_pmx_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned function)
+{
+ struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+ return npct->soc->functions[function].name;
+}
+
+static int nmk_pmx_get_func_groups(struct pinctrl_dev *pctldev,
+ unsigned function,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = npct->soc->functions[function].groups;
+ *num_groups = npct->soc->functions[function].ngroups;
+
+ return 0;
+}
+
+static int nmk_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
+ unsigned group)
+{
+ struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+ const struct nmk_pingroup *g;
+ static unsigned int slpm[NUM_BANKS];
+ unsigned long flags;
+ bool glitch;
+ int ret = -EINVAL;
+ int i;
+
+ g = &npct->soc->groups[group];
+
+ if (g->altsetting < 0)
+ return -EINVAL;
+
+ dev_dbg(npct->dev, "enable group %s, %u pins\n", g->name, g->npins);
+
+ /* Handle this special glitch on altfunction C */
+ glitch = (g->altsetting == NMK_GPIO_ALT_C);
+
+ if (glitch) {
+ spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+
+ /* Initially don't put any pins to sleep when switching */
+ memset(slpm, 0xff, sizeof(slpm));
+
+ /*
+ * Then mask the pins that need to be sleeping now when we're
+ * switching to the ALT C function.
+ */
+ for (i = 0; i < g->npins; i++)
+ slpm[g->pins[i] / NMK_GPIO_PER_CHIP] &= ~BIT(g->pins[i]);
+ nmk_gpio_glitch_slpm_init(slpm);
+ }
+
+ for (i = 0; i < g->npins; i++) {
+ struct pinctrl_gpio_range *range;
+ struct nmk_gpio_chip *nmk_chip;
+ struct gpio_chip *chip;
+ unsigned bit;
+
+ range = nmk_match_gpio_range(pctldev, g->pins[i]);
+ if (!range) {
+ dev_err(npct->dev,
+ "invalid pin offset %d in group %s at index %d\n",
+ g->pins[i], g->name, i);
+ goto out_glitch;
+ }
+ if (!range->gc) {
+ dev_err(npct->dev, "GPIO chip missing in range for pin offset %d in group %s at index %d\n",
+ g->pins[i], g->name, i);
+ goto out_glitch;
+ }
+ chip = range->gc;
+ nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
+ dev_dbg(npct->dev, "setting pin %d to altsetting %d\n", g->pins[i], g->altsetting);
+
+ clk_enable(nmk_chip->clk);
+ bit = g->pins[i] % NMK_GPIO_PER_CHIP;
+ /*
+ * If the pin is switching to altfunc, and there was an
+ * interrupt installed on it which has been lazy disabled,
+ * actually mask the interrupt to prevent spurious interrupts
+ * that would occur while the pin is under control of the
+ * peripheral. Only SKE does this.
+ */
+ nmk_gpio_disable_lazy_irq(nmk_chip, bit);
+
+ __nmk_gpio_set_mode_safe(nmk_chip, bit, g->altsetting, glitch);
+ clk_disable(nmk_chip->clk);
+ }
+
+ /* When all pins are successfully reconfigured we get here */
+ ret = 0;
+
+out_glitch:
+ if (glitch) {
+ nmk_gpio_glitch_slpm_restore(slpm);
+ spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+ }
+
+ return ret;
+}
+
+static void nmk_pmx_disable(struct pinctrl_dev *pctldev,
+ unsigned function, unsigned group)
+{
+ struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+ const struct nmk_pingroup *g;
+
+ g = &npct->soc->groups[group];
+
+ if (g->altsetting < 0)
+ return;
+
+ /* Poke out the mux, set the pin to some default state? */
+ dev_dbg(npct->dev, "disable group %s, %u pins\n", g->name, g->npins);
+}
+
+int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+ struct nmk_gpio_chip *nmk_chip;
+ struct gpio_chip *chip;
+ unsigned bit;
+
+ if (!range) {
+ dev_err(npct->dev, "invalid range\n");
+ return -EINVAL;
+ }
+ if (!range->gc) {
+ dev_err(npct->dev, "missing GPIO chip in range\n");
+ return -EINVAL;
+ }
+ chip = range->gc;
+ nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
+
+ dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);
+
+ clk_enable(nmk_chip->clk);
+ bit = offset % NMK_GPIO_PER_CHIP;
+ /* There is no glitch when converting any pin to GPIO */
+ __nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO);
+ clk_disable(nmk_chip->clk);
+
+ return 0;
+}
+
+void nmk_gpio_disable_free(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+ dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset);
+ /* Set the pin to some default state, GPIO is usually default */
+}
+
+static struct pinmux_ops nmk_pinmux_ops = {
+ .get_functions_count = nmk_pmx_get_funcs_cnt,
+ .get_function_name = nmk_pmx_get_func_name,
+ .get_function_groups = nmk_pmx_get_func_groups,
+ .enable = nmk_pmx_enable,
+ .disable = nmk_pmx_disable,
+ .gpio_request_enable = nmk_gpio_request_enable,
+ .gpio_disable_free = nmk_gpio_disable_free,
+};
+
+int nmk_pin_config_get(struct pinctrl_dev *pctldev,
+ unsigned pin,
+ unsigned long *config)
+{
+ /* Not implemented */
+ return -EINVAL;
+}
+
+int nmk_pin_config_set(struct pinctrl_dev *pctldev,
+ unsigned pin,
+ unsigned long config)
+{
+ static const char *pullnames[] = {
+ [NMK_GPIO_PULL_NONE] = "none",
+ [NMK_GPIO_PULL_UP] = "up",
+ [NMK_GPIO_PULL_DOWN] = "down",
+ [3] /* illegal */ = "??"
+ };
+ static const char *slpmnames[] = {
+ [NMK_GPIO_SLPM_INPUT] = "input/wakeup",
+ [NMK_GPIO_SLPM_NOCHANGE] = "no-change/no-wakeup",
+ };
+ struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+ struct nmk_gpio_chip *nmk_chip;
+ struct pinctrl_gpio_range *range;
+ struct gpio_chip *chip;
+ unsigned bit;
+
+ /*
+ * The pin config contains pin number and altfunction fields, here
+ * we just ignore that part. It's being handled by the framework and
+ * pinmux callback respectively.
+ */
+ pin_cfg_t cfg = (pin_cfg_t) config;
+ int pull = PIN_PULL(cfg);
+ int slpm = PIN_SLPM(cfg);
+ int output = PIN_DIR(cfg);
+ int val = PIN_VAL(cfg);
+ bool lowemi = PIN_LOWEMI(cfg);
+ bool gpiomode = PIN_GPIOMODE(cfg);
+ bool sleep = PIN_SLEEPMODE(cfg);
+
+ range = nmk_match_gpio_range(pctldev, pin);
+ if (!range) {
+ dev_err(npct->dev, "invalid pin offset %d\n", pin);
+ return -EINVAL;
+ }
+ if (!range->gc) {
+ dev_err(npct->dev, "GPIO chip missing in range for pin %d\n",
+ pin);
+ return -EINVAL;
+ }
+ chip = range->gc;
+ nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
+
+ if (sleep) {
+ int slpm_pull = PIN_SLPM_PULL(cfg);
+ int slpm_output = PIN_SLPM_DIR(cfg);
+ int slpm_val = PIN_SLPM_VAL(cfg);
+
+ /* All pins go into GPIO mode at sleep */
+ gpiomode = true;
+
+ /*
+ * 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");
+ }
+
+ dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: pull %s, slpm %s (%s%s), lowemi %s\n",
+ pin, cfg, pullnames[pull], slpmnames[slpm],
+ output ? "output " : "input",
+ output ? (val ? "high" : "low") : "",
+ lowemi ? "on" : "off" );
+
+ clk_enable(nmk_chip->clk);
+ bit = pin % NMK_GPIO_PER_CHIP;
+ if (gpiomode)
+ /* No glitch when going to GPIO mode */
+ __nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO);
+ if (output)
+ __nmk_gpio_make_output(nmk_chip, bit, val);
+ else {
+ __nmk_gpio_make_input(nmk_chip, bit);
+ __nmk_gpio_set_pull(nmk_chip, bit, pull);
+ }
+ /* TODO: isn't this only applicable on output pins? */
+ __nmk_gpio_set_lowemi(nmk_chip, bit, lowemi);
+
+ __nmk_gpio_set_slpm(nmk_chip, bit, slpm);
+ clk_disable(nmk_chip->clk);
+ return 0;
+}
+
+static struct pinconf_ops nmk_pinconf_ops = {
+ .pin_config_get = nmk_pin_config_get,
+ .pin_config_set = nmk_pin_config_set,
+};
+
+static struct pinctrl_desc nmk_pinctrl_desc = {
+ .name = "pinctrl-nomadik",
+ .pctlops = &nmk_pinctrl_ops,
+ .pmxops = &nmk_pinmux_ops,
+ .confops = &nmk_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
+{
+ const struct platform_device_id *platid = platform_get_device_id(pdev);
+ struct nmk_pinctrl *npct;
+ int i;
+
+ npct = devm_kzalloc(&pdev->dev, sizeof(*npct), GFP_KERNEL);
+ if (!npct)
+ return -ENOMEM;
+
+ /* Poke in other ASIC variants here */
+ if (platid->driver_data == PINCTRL_NMK_DB8500)
+ nmk_pinctrl_db8500_init(&npct->soc);
+
+ /*
+ * We need all the GPIO drivers to probe FIRST, or we will not be able
+ * to obtain references to the struct gpio_chip * for them, and we
+ * need this to proceed.
+ */
+ for (i = 0; i < npct->soc->gpio_num_ranges; i++) {
+ if (!nmk_gpio_chips[i]) {
+ dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i);
+ devm_kfree(&pdev->dev, npct);
+ return -EPROBE_DEFER;
+ }
+ npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[i]->chip;
+ }
+
+ nmk_pinctrl_desc.pins = npct->soc->pins;
+ nmk_pinctrl_desc.npins = npct->soc->npins;
+ npct->dev = &pdev->dev;
+ npct->pctl = pinctrl_register(&nmk_pinctrl_desc, &pdev->dev, npct);
+ if (!npct->pctl) {
+ dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n");
+ return -EINVAL;
+ }
+
+ /* We will handle a range of GPIO pins */
+ for (i = 0; i < npct->soc->gpio_num_ranges; i++)
+ pinctrl_add_gpio_range(npct->pctl, &npct->soc->gpio_ranges[i]);
+
+ platform_set_drvdata(pdev, npct);
+ dev_info(&pdev->dev, "initialized Nomadik pin control driver\n");
+
+ return 0;
+}
+
+static const struct of_device_id nmk_gpio_match[] = {
+ { .compatible = "st,nomadik-gpio", },
+ {}
+};
+
static struct platform_driver nmk_gpio_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "gpio",
+ .of_match_table = nmk_gpio_match,
},
.probe = nmk_gpio_probe,
};
+static const struct platform_device_id nmk_pinctrl_id[] = {
+ { "pinctrl-stn8815", PINCTRL_NMK_STN8815 },
+ { "pinctrl-db8500", PINCTRL_NMK_DB8500 },
+};
+
+static struct platform_driver nmk_pinctrl_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "pinctrl-nomadik",
+ },
+ .probe = nmk_pinctrl_probe,
+ .id_table = nmk_pinctrl_id,
+};
+
static int __init nmk_gpio_init(void)
{
- return platform_driver_register(&nmk_gpio_driver);
+ int ret;
+
+ ret = platform_driver_register(&nmk_gpio_driver);
+ if (ret)
+ return ret;
+ return platform_driver_register(&nmk_pinctrl_driver);
}
core_initcall(nmk_gpio_init);
diff --git a/drivers/pinctrl/pinctrl-nomadik.h b/drivers/pinctrl/pinctrl-nomadik.h
new file mode 100644
index 000000000000..bc91aed7185d
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-nomadik.h
@@ -0,0 +1,77 @@
+#ifndef PINCTRL_PINCTRL_NOMADIK_H
+#define PINCTRL_PINCTRL_NOMADIK_H
+
+#include <plat/gpio-nomadik.h>
+
+/* Package definitions */
+#define PINCTRL_NMK_STN8815 0
+#define PINCTRL_NMK_DB8500 1
+
+/**
+ * struct nmk_function - Nomadik pinctrl mux function
+ * @name: The name of the function, exported to pinctrl core.
+ * @groups: An array of pin groups that may select this function.
+ * @ngroups: The number of entries in @groups.
+ */
+struct nmk_function {
+ const char *name;
+ const char * const *groups;
+ unsigned ngroups;
+};
+
+/**
+ * struct nmk_pingroup - describes a Nomadik pin group
+ * @name: the name of this specific pin group
+ * @pins: an array of discrete physical pins used in this group, taken
+ * from the driver-local pin enumeration space
+ * @num_pins: the number of pins in this group array, i.e. the number of
+ * elements in .pins so we can iterate over that array
+ * @altsetting: the altsetting to apply to all pins in this group to
+ * configure them to be used by a function
+ */
+struct nmk_pingroup {
+ const char *name;
+ const unsigned int *pins;
+ const unsigned npins;
+ int altsetting;
+};
+
+/**
+ * struct nmk_pinctrl_soc_data - Nomadik pin controller per-SoC configuration
+ * @gpio_ranges: An array of GPIO ranges for this SoC
+ * @gpio_num_ranges: The number of GPIO ranges for this SoC
+ * @pins: An array describing all pins the pin controller affects.
+ * All pins which are also GPIOs must be listed first within the
+ * array, and be numbered identically to the GPIO controller's
+ * numbering.
+ * @npins: The number of entries in @pins.
+ * @functions: The functions supported on this SoC.
+ * @nfunction: The number of entries in @functions.
+ * @groups: An array describing all pin groups the pin SoC supports.
+ * @ngroups: The number of entries in @groups.
+ */
+struct nmk_pinctrl_soc_data {
+ struct pinctrl_gpio_range *gpio_ranges;
+ unsigned gpio_num_ranges;
+ const struct pinctrl_pin_desc *pins;
+ unsigned npins;
+ const struct nmk_function *functions;
+ unsigned nfunctions;
+ const struct nmk_pingroup *groups;
+ unsigned ngroups;
+};
+
+#ifdef CONFIG_PINCTRL_DB8500
+
+void nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc);
+
+#else
+
+static inline void
+nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc)
+{
+}
+
+#endif
+
+#endif /* PINCTRL_PINCTRL_NOMADIK_H */
diff --git a/drivers/pinctrl/pinctrl-pxa3xx.c b/drivers/pinctrl/pinctrl-pxa3xx.c
index 079dce0e93e9..f14cd6ba4c0b 100644
--- a/drivers/pinctrl/pinctrl-pxa3xx.c
+++ b/drivers/pinctrl/pinctrl-pxa3xx.c
@@ -25,20 +25,18 @@ static struct pinctrl_gpio_range pxa3xx_pinctrl_gpio_range = {
.pin_base = 0,
};
-static int pxa3xx_list_groups(struct pinctrl_dev *pctrldev, unsigned selector)
+static int pxa3xx_get_groups_count(struct pinctrl_dev *pctrldev)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
- if (selector >= info->num_grps)
- return -EINVAL;
- return 0;
+
+ return info->num_grps;
}
static const char *pxa3xx_get_group_name(struct pinctrl_dev *pctrldev,
unsigned selector)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
- if (selector >= info->num_grps)
- return NULL;
+
return info->grps[selector].name;
}
@@ -48,25 +46,23 @@ static int pxa3xx_get_group_pins(struct pinctrl_dev *pctrldev,
unsigned *num_pins)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
- if (selector >= info->num_grps)
- return -EINVAL;
+
*pins = info->grps[selector].pins;
*num_pins = info->grps[selector].npins;
return 0;
}
static struct pinctrl_ops pxa3xx_pctrl_ops = {
- .list_groups = pxa3xx_list_groups,
+ .get_groups_count = pxa3xx_get_groups_count,
.get_group_name = pxa3xx_get_group_name,
.get_group_pins = pxa3xx_get_group_pins,
};
-static int pxa3xx_pmx_list_func(struct pinctrl_dev *pctrldev, unsigned func)
+static int pxa3xx_pmx_get_funcs_count(struct pinctrl_dev *pctrldev)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
- if (func >= info->num_funcs)
- return -EINVAL;
- return 0;
+
+ return info->num_funcs;
}
static const char *pxa3xx_pmx_get_func_name(struct pinctrl_dev *pctrldev,
@@ -142,11 +138,6 @@ static int pxa3xx_pmx_enable(struct pinctrl_dev *pctrldev, unsigned func,
return 0;
}
-static void pxa3xx_pmx_disable(struct pinctrl_dev *pctrldev, unsigned func,
- unsigned group)
-{
-}
-
static int pxa3xx_pmx_request_gpio(struct pinctrl_dev *pctrldev,
struct pinctrl_gpio_range *range,
unsigned pin)
@@ -170,11 +161,10 @@ static int pxa3xx_pmx_request_gpio(struct pinctrl_dev *pctrldev,
}
static struct pinmux_ops pxa3xx_pmx_ops = {
- .list_functions = pxa3xx_pmx_list_func,
+ .get_functions_count = pxa3xx_pmx_get_funcs_count,
.get_function_name = pxa3xx_pmx_get_func_name,
.get_function_groups = pxa3xx_pmx_get_groups,
.enable = pxa3xx_pmx_enable,
- .disable = pxa3xx_pmx_disable,
.gpio_request_enable = pxa3xx_pmx_request_gpio,
};
diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c
index 6b3534cc051a..ba15b1a29e52 100644
--- a/drivers/pinctrl/pinctrl-sirf.c
+++ b/drivers/pinctrl/pinctrl-sirf.c
@@ -853,18 +853,14 @@ static const struct sirfsoc_pin_group sirfsoc_pin_groups[] = {
SIRFSOC_PIN_GROUP("gpsgrp", gps_pins),
};
-static int sirfsoc_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
+static int sirfsoc_get_groups_count(struct pinctrl_dev *pctldev)
{
- if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
- return -EINVAL;
- return 0;
+ return ARRAY_SIZE(sirfsoc_pin_groups);
}
static const char *sirfsoc_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
- if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
- return NULL;
return sirfsoc_pin_groups[selector].name;
}
@@ -872,8 +868,6 @@ static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector
const unsigned **pins,
unsigned *num_pins)
{
- if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
- return -EINVAL;
*pins = sirfsoc_pin_groups[selector].pins;
*num_pins = sirfsoc_pin_groups[selector].num_pins;
return 0;
@@ -886,7 +880,7 @@ static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s
}
static struct pinctrl_ops sirfsoc_pctrl_ops = {
- .list_groups = sirfsoc_list_groups,
+ .get_groups_count = sirfsoc_get_groups_count,
.get_group_name = sirfsoc_get_group_name,
.get_group_pins = sirfsoc_get_group_pins,
.pin_dbg_show = sirfsoc_pin_dbg_show,
@@ -1033,11 +1027,9 @@ static void sirfsoc_pinmux_disable(struct pinctrl_dev *pmxdev, unsigned selector
sirfsoc_pinmux_endisable(spmx, selector, false);
}
-static int sirfsoc_pinmux_list_funcs(struct pinctrl_dev *pmxdev, unsigned selector)
+static int sirfsoc_pinmux_get_funcs_count(struct pinctrl_dev *pmxdev)
{
- if (selector >= ARRAY_SIZE(sirfsoc_pmx_functions))
- return -EINVAL;
- return 0;
+ return ARRAY_SIZE(sirfsoc_pmx_functions);
}
static const char *sirfsoc_pinmux_get_func_name(struct pinctrl_dev *pctldev,
@@ -1074,9 +1066,9 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
}
static struct pinmux_ops sirfsoc_pinmux_ops = {
- .list_functions = sirfsoc_pinmux_list_funcs,
.enable = sirfsoc_pinmux_enable,
.disable = sirfsoc_pinmux_disable,
+ .get_functions_count = sirfsoc_pinmux_get_funcs_count,
.get_function_name = sirfsoc_pinmux_get_func_name,
.get_function_groups = sirfsoc_pinmux_get_groups,
.gpio_request_enable = sirfsoc_pinmux_request_gpio,
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
index 9b329688120c..b6934867d8d3 100644
--- a/drivers/pinctrl/pinctrl-tegra.c
+++ b/drivers/pinctrl/pinctrl-tegra.c
@@ -1,7 +1,7 @@
/*
* Driver for the NVIDIA Tegra pinmux
*
- * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
*
* Derived from code:
* Copyright (C) 2010 Google, Inc.
@@ -22,17 +22,19 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
+#include <linux/slab.h>
#include <mach/pinconf-tegra.h>
+#include "core.h"
#include "pinctrl-tegra.h"
-#define DRIVER_NAME "tegra-pinmux-disabled"
-
struct tegra_pmx {
struct device *dev;
struct pinctrl_dev *pctl;
@@ -53,15 +55,11 @@ static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg)
writel(val, pmx->regs[bank] + reg);
}
-static int tegra_pinctrl_list_groups(struct pinctrl_dev *pctldev,
- unsigned group)
+static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
- if (group >= pmx->soc->ngroups)
- return -EINVAL;
-
- return 0;
+ return pmx->soc->ngroups;
}
static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
@@ -69,9 +67,6 @@ static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
- if (group >= pmx->soc->ngroups)
- return NULL;
-
return pmx->soc->groups[group].name;
}
@@ -82,38 +77,259 @@ static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
- if (group >= pmx->soc->ngroups)
- return -EINVAL;
-
*pins = pmx->soc->groups[group].pins;
*num_pins = pmx->soc->groups[group].npins;
return 0;
}
+#ifdef CONFIG_DEBUG_FS
static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s,
unsigned offset)
{
- seq_printf(s, " " DRIVER_NAME);
+ seq_printf(s, " %s", dev_name(pctldev->dev));
+}
+#endif
+
+static int reserve_map(struct device *dev, struct pinctrl_map **map,
+ unsigned *reserved_maps, unsigned *num_maps,
+ unsigned reserve)
+{
+ unsigned old_num = *reserved_maps;
+ unsigned new_num = *num_maps + reserve;
+ struct pinctrl_map *new_map;
+
+ if (old_num >= new_num)
+ return 0;
+
+ new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
+ if (!new_map) {
+ dev_err(dev, "krealloc(map) failed\n");
+ return -ENOMEM;
+ }
+
+ memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
+
+ *map = new_map;
+ *reserved_maps = new_num;
+
+ return 0;
+}
+
+static int add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,
+ unsigned *num_maps, const char *group,
+ const char *function)
+{
+ if (WARN_ON(*num_maps == *reserved_maps))
+ return -ENOSPC;
+
+ (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
+ (*map)[*num_maps].data.mux.group = group;
+ (*map)[*num_maps].data.mux.function = function;
+ (*num_maps)++;
+
+ return 0;
+}
+
+static int add_map_configs(struct device *dev, struct pinctrl_map **map,
+ unsigned *reserved_maps, unsigned *num_maps,
+ const char *group, unsigned long *configs,
+ unsigned num_configs)
+{
+ unsigned long *dup_configs;
+
+ if (WARN_ON(*num_maps == *reserved_maps))
+ return -ENOSPC;
+
+ dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
+ GFP_KERNEL);
+ if (!dup_configs) {
+ dev_err(dev, "kmemdup(configs) failed\n");
+ return -ENOMEM;
+ }
+
+ (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+ (*map)[*num_maps].data.configs.group_or_pin = group;
+ (*map)[*num_maps].data.configs.configs = dup_configs;
+ (*map)[*num_maps].data.configs.num_configs = num_configs;
+ (*num_maps)++;
+
+ return 0;
+}
+
+static int add_config(struct device *dev, unsigned long **configs,
+ unsigned *num_configs, unsigned long config)
+{
+ unsigned old_num = *num_configs;
+ unsigned new_num = old_num + 1;
+ unsigned long *new_configs;
+
+ new_configs = krealloc(*configs, sizeof(*new_configs) * new_num,
+ GFP_KERNEL);
+ if (!new_configs) {
+ dev_err(dev, "krealloc(configs) failed\n");
+ return -ENOMEM;
+ }
+
+ new_configs[old_num] = config;
+
+ *configs = new_configs;
+ *num_configs = new_num;
+
+ return 0;
+}
+
+void tegra_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ int i;
+
+ for (i = 0; i < num_maps; i++)
+ if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
+ kfree(map[i].data.configs.configs);
+
+ kfree(map);
+}
+
+static const struct cfg_param {
+ const char *property;
+ enum tegra_pinconf_param param;
+} cfg_params[] = {
+ {"nvidia,pull", TEGRA_PINCONF_PARAM_PULL},
+ {"nvidia,tristate", TEGRA_PINCONF_PARAM_TRISTATE},
+ {"nvidia,enable-input", TEGRA_PINCONF_PARAM_ENABLE_INPUT},
+ {"nvidia,open-drain", TEGRA_PINCONF_PARAM_OPEN_DRAIN},
+ {"nvidia,lock", TEGRA_PINCONF_PARAM_LOCK},
+ {"nvidia,io-reset", TEGRA_PINCONF_PARAM_IORESET},
+ {"nvidia,high-speed-mode", TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE},
+ {"nvidia,schmitt", TEGRA_PINCONF_PARAM_SCHMITT},
+ {"nvidia,low-power-mode", TEGRA_PINCONF_PARAM_LOW_POWER_MODE},
+ {"nvidia,pull-down-strength", TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH},
+ {"nvidia,pull-up-strength", TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH},
+ {"nvidia,slew-rate-falling", TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING},
+ {"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING},
+};
+
+int tegra_pinctrl_dt_subnode_to_map(struct device *dev,
+ struct device_node *np,
+ struct pinctrl_map **map,
+ unsigned *reserved_maps,
+ unsigned *num_maps)
+{
+ int ret, i;
+ const char *function;
+ u32 val;
+ unsigned long config;
+ unsigned long *configs = NULL;
+ unsigned num_configs = 0;
+ unsigned reserve;
+ struct property *prop;
+ const char *group;
+
+ ret = of_property_read_string(np, "nvidia,function", &function);
+ if (ret < 0) {
+ /* EINVAL=missing, which is fine since it's optional */
+ if (ret != -EINVAL)
+ dev_err(dev,
+ "could not parse property nvidia,function\n");
+ function = NULL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
+ ret = of_property_read_u32(np, cfg_params[i].property, &val);
+ if (!ret) {
+ config = TEGRA_PINCONF_PACK(cfg_params[i].param, val);
+ ret = add_config(dev, &configs, &num_configs, config);
+ if (ret < 0)
+ goto exit;
+ /* EINVAL=missing, which is fine since it's optional */
+ } else if (ret != -EINVAL) {
+ dev_err(dev, "could not parse property %s\n",
+ cfg_params[i].property);
+ }
+ }
+
+ reserve = 0;
+ if (function != NULL)
+ reserve++;
+ if (num_configs)
+ reserve++;
+ ret = of_property_count_strings(np, "nvidia,pins");
+ if (ret < 0) {
+ dev_err(dev, "could not parse property nvidia,pins\n");
+ goto exit;
+ }
+ reserve *= ret;
+
+ ret = reserve_map(dev, map, reserved_maps, num_maps, reserve);
+ if (ret < 0)
+ goto exit;
+
+ of_property_for_each_string(np, "nvidia,pins", prop, group) {
+ if (function) {
+ ret = add_map_mux(map, reserved_maps, num_maps,
+ group, function);
+ if (ret < 0)
+ goto exit;
+ }
+
+ if (num_configs) {
+ ret = add_map_configs(dev, map, reserved_maps,
+ num_maps, group, configs,
+ num_configs);
+ if (ret < 0)
+ goto exit;
+ }
+ }
+
+ ret = 0;
+
+exit:
+ kfree(configs);
+ return ret;
+}
+
+int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np_config,
+ struct pinctrl_map **map, unsigned *num_maps)
+{
+ unsigned reserved_maps;
+ struct device_node *np;
+ int ret;
+
+ reserved_maps = 0;
+ *map = NULL;
+ *num_maps = 0;
+
+ for_each_child_of_node(np_config, np) {
+ ret = tegra_pinctrl_dt_subnode_to_map(pctldev->dev, np, map,
+ &reserved_maps, num_maps);
+ if (ret < 0) {
+ tegra_pinctrl_dt_free_map(pctldev, *map, *num_maps);
+ return ret;
+ }
+ }
+
+ return 0;
}
static struct pinctrl_ops tegra_pinctrl_ops = {
- .list_groups = tegra_pinctrl_list_groups,
+ .get_groups_count = tegra_pinctrl_get_groups_count,
.get_group_name = tegra_pinctrl_get_group_name,
.get_group_pins = tegra_pinctrl_get_group_pins,
+#ifdef CONFIG_DEBUG_FS
.pin_dbg_show = tegra_pinctrl_pin_dbg_show,
+#endif
+ .dt_node_to_map = tegra_pinctrl_dt_node_to_map,
+ .dt_free_map = tegra_pinctrl_dt_free_map,
};
-static int tegra_pinctrl_list_funcs(struct pinctrl_dev *pctldev,
- unsigned function)
+static int tegra_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
- if (function >= pmx->soc->nfunctions)
- return -EINVAL;
-
- return 0;
+ return pmx->soc->nfunctions;
}
static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
@@ -121,9 +337,6 @@ static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
- if (function >= pmx->soc->nfunctions)
- return NULL;
-
return pmx->soc->functions[function].name;
}
@@ -134,9 +347,6 @@ static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
- if (function >= pmx->soc->nfunctions)
- return -EINVAL;
-
*groups = pmx->soc->functions[function].groups;
*num_groups = pmx->soc->functions[function].ngroups;
@@ -151,18 +361,16 @@ static int tegra_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function,
int i;
u32 val;
- if (group >= pmx->soc->ngroups)
- return -EINVAL;
g = &pmx->soc->groups[group];
- if (g->mux_reg < 0)
+ if (WARN_ON(g->mux_reg < 0))
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(g->funcs); i++) {
if (g->funcs[i] == function)
break;
}
- if (i == ARRAY_SIZE(g->funcs))
+ if (WARN_ON(i == ARRAY_SIZE(g->funcs)))
return -EINVAL;
val = pmx_readl(pmx, g->mux_bank, g->mux_reg);
@@ -180,11 +388,9 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
const struct tegra_pingroup *g;
u32 val;
- if (group >= pmx->soc->ngroups)
- return;
g = &pmx->soc->groups[group];
- if (g->mux_reg < 0)
+ if (WARN_ON(g->mux_reg < 0))
return;
val = pmx_readl(pmx, g->mux_bank, g->mux_reg);
@@ -194,7 +400,7 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
}
static struct pinmux_ops tegra_pinmux_ops = {
- .list_functions = tegra_pinctrl_list_funcs,
+ .get_functions_count = tegra_pinctrl_get_funcs_count,
.get_function_name = tegra_pinctrl_get_func_name,
.get_function_groups = tegra_pinctrl_get_func_groups,
.enable = tegra_pinctrl_enable,
@@ -204,6 +410,7 @@ static struct pinmux_ops tegra_pinmux_ops = {
static int tegra_pinconf_reg(struct tegra_pmx *pmx,
const struct tegra_pingroup *g,
enum tegra_pinconf_param param,
+ bool report_err,
s8 *bank, s16 *reg, s8 *bit, s8 *width)
{
switch (param) {
@@ -291,9 +498,10 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
}
if (*reg < 0) {
- dev_err(pmx->dev,
- "Config param %04x not supported on group %s\n",
- param, g->name);
+ if (report_err)
+ dev_err(pmx->dev,
+ "Config param %04x not supported on group %s\n",
+ param, g->name);
return -ENOTSUPP;
}
@@ -303,12 +511,14 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
static int tegra_pinconf_get(struct pinctrl_dev *pctldev,
unsigned pin, unsigned long *config)
{
+ dev_err(pctldev->dev, "pin_config_get op not supported\n");
return -ENOTSUPP;
}
static int tegra_pinconf_set(struct pinctrl_dev *pctldev,
unsigned pin, unsigned long config)
{
+ dev_err(pctldev->dev, "pin_config_set op not supported\n");
return -ENOTSUPP;
}
@@ -324,11 +534,10 @@ static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev,
s16 reg;
u32 val, mask;
- if (group >= pmx->soc->ngroups)
- return -EINVAL;
g = &pmx->soc->groups[group];
- ret = tegra_pinconf_reg(pmx, g, param, &bank, &reg, &bit, &width);
+ ret = tegra_pinconf_reg(pmx, g, param, true, &bank, &reg, &bit,
+ &width);
if (ret < 0)
return ret;
@@ -353,11 +562,10 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
s16 reg;
u32 val, mask;
- if (group >= pmx->soc->ngroups)
- return -EINVAL;
g = &pmx->soc->groups[group];
- ret = tegra_pinconf_reg(pmx, g, param, &bank, &reg, &bit, &width);
+ ret = tegra_pinconf_reg(pmx, g, param, true, &bank, &reg, &bit,
+ &width);
if (ret < 0)
return ret;
@@ -365,8 +573,10 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
/* LOCK can't be cleared */
if (param == TEGRA_PINCONF_PARAM_LOCK) {
- if ((val & BIT(bit)) && !arg)
+ if ((val & BIT(bit)) && !arg) {
+ dev_err(pctldev->dev, "LOCK bit cannot be cleared\n");
return -EINVAL;
+ }
}
/* Special-case Boolean values; allow any non-zero as true */
@@ -375,8 +585,12 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
/* Range-check user-supplied value */
mask = (1 << width) - 1;
- if (arg & ~mask)
+ if (arg & ~mask) {
+ dev_err(pctldev->dev,
+ "config %lx: %x too big for %d bit register\n",
+ config, arg, width);
return -EINVAL;
+ }
/* Update register */
val &= ~(mask << bit);
@@ -386,23 +600,78 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
return 0;
}
+#ifdef CONFIG_DEBUG_FS
static void tegra_pinconf_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned offset)
{
}
+static const char *strip_prefix(const char *s)
+{
+ const char *comma = strchr(s, ',');
+ if (!comma)
+ return s;
+
+ return comma + 1;
+}
+
static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
- struct seq_file *s, unsigned selector)
+ struct seq_file *s, unsigned group)
{
+ struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+ const struct tegra_pingroup *g;
+ int i, ret;
+ s8 bank, bit, width;
+ s16 reg;
+ u32 val;
+
+ g = &pmx->soc->groups[group];
+
+ for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
+ ret = tegra_pinconf_reg(pmx, g, cfg_params[i].param, false,
+ &bank, &reg, &bit, &width);
+ if (ret < 0)
+ continue;
+
+ val = pmx_readl(pmx, bank, reg);
+ val >>= bit;
+ val &= (1 << width) - 1;
+
+ seq_printf(s, "\n\t%s=%u",
+ strip_prefix(cfg_params[i].property), val);
+ }
}
+static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s,
+ unsigned long config)
+{
+ enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(config);
+ u16 arg = TEGRA_PINCONF_UNPACK_ARG(config);
+ const char *pname = "unknown";
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
+ if (cfg_params[i].param == param) {
+ pname = cfg_params[i].property;
+ break;
+ }
+ }
+
+ seq_printf(s, "%s=%d", strip_prefix(pname), arg);
+}
+#endif
+
struct pinconf_ops tegra_pinconf_ops = {
.pin_config_get = tegra_pinconf_get,
.pin_config_set = tegra_pinconf_set,
.pin_config_group_get = tegra_pinconf_group_get,
.pin_config_group_set = tegra_pinconf_group_set,
+#ifdef CONFIG_DEBUG_FS
.pin_config_dbg_show = tegra_pinconf_dbg_show,
.pin_config_group_dbg_show = tegra_pinconf_group_dbg_show,
+ .pin_config_config_dbg_show = tegra_pinconf_config_dbg_show,
+#endif
};
static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = {
@@ -412,60 +681,29 @@ static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = {
};
static struct pinctrl_desc tegra_pinctrl_desc = {
- .name = DRIVER_NAME,
.pctlops = &tegra_pinctrl_ops,
.pmxops = &tegra_pinmux_ops,
.confops = &tegra_pinconf_ops,
.owner = THIS_MODULE,
};
-static struct of_device_id tegra_pinctrl_of_match[] __devinitdata = {
-#ifdef CONFIG_PINCTRL_TEGRA20
- {
- .compatible = "nvidia,tegra20-pinmux-disabled",
- .data = tegra20_pinctrl_init,
- },
-#endif
-#ifdef CONFIG_PINCTRL_TEGRA30
- {
- .compatible = "nvidia,tegra30-pinmux-disabled",
- .data = tegra30_pinctrl_init,
- },
-#endif
- {},
-};
-
-static int __devinit tegra_pinctrl_probe(struct platform_device *pdev)
+int __devinit tegra_pinctrl_probe(struct platform_device *pdev,
+ const struct tegra_pinctrl_soc_data *soc_data)
{
- const struct of_device_id *match;
- tegra_pinctrl_soc_initf initf = NULL;
struct tegra_pmx *pmx;
struct resource *res;
int i;
- match = of_match_device(tegra_pinctrl_of_match, &pdev->dev);
- if (match)
- initf = (tegra_pinctrl_soc_initf)match->data;
-#ifdef CONFIG_PINCTRL_TEGRA20
- if (!initf)
- initf = tegra20_pinctrl_init;
-#endif
- if (!initf) {
- dev_err(&pdev->dev,
- "Could not determine SoC-specific init func\n");
- return -EINVAL;
- }
-
pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
if (!pmx) {
dev_err(&pdev->dev, "Can't alloc tegra_pmx\n");
return -ENOMEM;
}
pmx->dev = &pdev->dev;
-
- (*initf)(&pmx->soc);
+ pmx->soc = soc_data;
tegra_pinctrl_gpio_range.npins = pmx->soc->ngpios;
+ tegra_pinctrl_desc.name = dev_name(&pdev->dev);
tegra_pinctrl_desc.pins = pmx->soc->pins;
tegra_pinctrl_desc.npins = pmx->soc->npins;
@@ -520,8 +758,9 @@ static int __devinit tegra_pinctrl_probe(struct platform_device *pdev)
return 0;
}
+EXPORT_SYMBOL_GPL(tegra_pinctrl_probe);
-static int __devexit tegra_pinctrl_remove(struct platform_device *pdev)
+int __devexit tegra_pinctrl_remove(struct platform_device *pdev)
{
struct tegra_pmx *pmx = platform_get_drvdata(pdev);
@@ -530,30 +769,4 @@ static int __devexit tegra_pinctrl_remove(struct platform_device *pdev)
return 0;
}
-
-static struct platform_driver tegra_pinctrl_driver = {
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- .of_match_table = tegra_pinctrl_of_match,
- },
- .probe = tegra_pinctrl_probe,
- .remove = __devexit_p(tegra_pinctrl_remove),
-};
-
-static int __init tegra_pinctrl_init(void)
-{
- return platform_driver_register(&tegra_pinctrl_driver);
-}
-arch_initcall(tegra_pinctrl_init);
-
-static void __exit tegra_pinctrl_exit(void)
-{
- platform_driver_unregister(&tegra_pinctrl_driver);
-}
-module_exit(tegra_pinctrl_exit);
-
-MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
-MODULE_DESCRIPTION("NVIDIA Tegra pinctrl driver");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, tegra_pinctrl_of_match);
+EXPORT_SYMBOL_GPL(tegra_pinctrl_remove);
diff --git a/drivers/pinctrl/pinctrl-tegra.h b/drivers/pinctrl/pinctrl-tegra.h
index 782c795326ef..705c007a38cc 100644
--- a/drivers/pinctrl/pinctrl-tegra.h
+++ b/drivers/pinctrl/pinctrl-tegra.h
@@ -139,25 +139,8 @@ struct tegra_pinctrl_soc_data {
unsigned ngroups;
};
-/**
- * tegra_pinctrl_soc_initf() - Retrieve pin controller details for a SoC.
- * @soc_data: This pointer must be updated to point at a struct containing
- * details of the SoC.
- */
-typedef void (*tegra_pinctrl_soc_initf)(
- const struct tegra_pinctrl_soc_data **soc_data);
-
-/**
- * tegra20_pinctrl_init() - Retrieve pin controller details for Tegra20
- * @soc_data: This pointer will be updated to point at a struct containing
- * details of Tegra20's pin controller.
- */
-void tegra20_pinctrl_init(const struct tegra_pinctrl_soc_data **soc_data);
-/**
- * tegra30_pinctrl_init() - Retrieve pin controller details for Tegra20
- * @soc_data: This pointer will be updated to point at a struct containing
- * details of Tegra30's pin controller.
- */
-void tegra30_pinctrl_init(const struct tegra_pinctrl_soc_data **soc_data);
+int tegra_pinctrl_probe(struct platform_device *pdev,
+ const struct tegra_pinctrl_soc_data *soc_data);
+int tegra_pinctrl_remove(struct platform_device *pdev);
#endif
diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c
index f69ff96aa292..a74f9a568536 100644
--- a/drivers/pinctrl/pinctrl-tegra20.c
+++ b/drivers/pinctrl/pinctrl-tegra20.c
@@ -1,7 +1,7 @@
/*
* Pinctrl data for the NVIDIA Tegra20 pinmux
*
- * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
*
* Derived from code:
* Copyright (C) 2010 Google, Inc.
@@ -17,6 +17,8 @@
* more details.
*/
+#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
@@ -2854,7 +2856,39 @@ static const struct tegra_pinctrl_soc_data tegra20_pinctrl = {
.ngroups = ARRAY_SIZE(tegra20_groups),
};
-void __devinit tegra20_pinctrl_init(const struct tegra_pinctrl_soc_data **soc)
+static int __devinit tegra20_pinctrl_probe(struct platform_device *pdev)
{
- *soc = &tegra20_pinctrl;
+ return tegra_pinctrl_probe(pdev, &tegra20_pinctrl);
}
+
+static struct of_device_id tegra20_pinctrl_of_match[] __devinitdata = {
+ { .compatible = "nvidia,tegra20-pinmux", },
+ { },
+};
+
+static struct platform_driver tegra20_pinctrl_driver = {
+ .driver = {
+ .name = "tegra20-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = tegra20_pinctrl_of_match,
+ },
+ .probe = tegra20_pinctrl_probe,
+ .remove = __devexit_p(tegra_pinctrl_remove),
+};
+
+static int __init tegra20_pinctrl_init(void)
+{
+ return platform_driver_register(&tegra20_pinctrl_driver);
+}
+arch_initcall(tegra20_pinctrl_init);
+
+static void __exit tegra20_pinctrl_exit(void)
+{
+ platform_driver_unregister(&tegra20_pinctrl_driver);
+}
+module_exit(tegra20_pinctrl_exit);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("NVIDIA Tegra20 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, tegra20_pinctrl_of_match);
diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c
index 4d7571d4a431..0386fdf0da16 100644
--- a/drivers/pinctrl/pinctrl-tegra30.c
+++ b/drivers/pinctrl/pinctrl-tegra30.c
@@ -1,7 +1,7 @@
/*
* Pinctrl data for the NVIDIA Tegra30 pinmux
*
- * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -13,6 +13,8 @@
* more details.
*/
+#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
@@ -3720,7 +3722,39 @@ static const struct tegra_pinctrl_soc_data tegra30_pinctrl = {
.ngroups = ARRAY_SIZE(tegra30_groups),
};
-void __devinit tegra30_pinctrl_init(const struct tegra_pinctrl_soc_data **soc)
+static int __devinit tegra30_pinctrl_probe(struct platform_device *pdev)
{
- *soc = &tegra30_pinctrl;
+ return tegra_pinctrl_probe(pdev, &tegra30_pinctrl);
}
+
+static struct of_device_id tegra30_pinctrl_of_match[] __devinitdata = {
+ { .compatible = "nvidia,tegra30-pinmux", },
+ { },
+};
+
+static struct platform_driver tegra30_pinctrl_driver = {
+ .driver = {
+ .name = "tegra30-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = tegra30_pinctrl_of_match,
+ },
+ .probe = tegra30_pinctrl_probe,
+ .remove = __devexit_p(tegra_pinctrl_remove),
+};
+
+static int __init tegra30_pinctrl_init(void)
+{
+ return platform_driver_register(&tegra30_pinctrl_driver);
+}
+arch_initcall(tegra30_pinctrl_init);
+
+static void __exit tegra30_pinctrl_exit(void)
+{
+ platform_driver_unregister(&tegra30_pinctrl_driver);
+}
+module_exit(tegra30_pinctrl_exit);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("NVIDIA Tegra30 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, tegra30_pinctrl_of_match);
diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c
index 26eb8ccd72d5..05d029911be6 100644
--- a/drivers/pinctrl/pinctrl-u300.c
+++ b/drivers/pinctrl/pinctrl-u300.c
@@ -836,18 +836,14 @@ static const struct u300_pin_group u300_pin_groups[] = {
},
};
-static int u300_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
+static int u300_get_groups_count(struct pinctrl_dev *pctldev)
{
- if (selector >= ARRAY_SIZE(u300_pin_groups))
- return -EINVAL;
- return 0;
+ return ARRAY_SIZE(u300_pin_groups);
}
static const char *u300_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
- if (selector >= ARRAY_SIZE(u300_pin_groups))
- return NULL;
return u300_pin_groups[selector].name;
}
@@ -855,8 +851,6 @@ static int u300_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
const unsigned **pins,
unsigned *num_pins)
{
- if (selector >= ARRAY_SIZE(u300_pin_groups))
- return -EINVAL;
*pins = u300_pin_groups[selector].pins;
*num_pins = u300_pin_groups[selector].num_pins;
return 0;
@@ -869,7 +863,7 @@ static void u300_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
}
static struct pinctrl_ops u300_pctrl_ops = {
- .list_groups = u300_list_groups,
+ .get_groups_count = u300_get_groups_count,
.get_group_name = u300_get_group_name,
.get_group_pins = u300_get_group_pins,
.pin_dbg_show = u300_pin_dbg_show,
@@ -991,11 +985,9 @@ static void u300_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
u300_pmx_endisable(upmx, selector, false);
}
-static int u300_pmx_list_funcs(struct pinctrl_dev *pctldev, unsigned selector)
+static int u300_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
{
- if (selector >= ARRAY_SIZE(u300_pmx_functions))
- return -EINVAL;
- return 0;
+ return ARRAY_SIZE(u300_pmx_functions);
}
static const char *u300_pmx_get_func_name(struct pinctrl_dev *pctldev,
@@ -1014,7 +1006,7 @@ static int u300_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
}
static struct pinmux_ops u300_pmx_ops = {
- .list_functions = u300_pmx_list_funcs,
+ .get_functions_count = u300_pmx_get_funcs_count,
.get_function_name = u300_pmx_get_func_name,
.get_function_groups = u300_pmx_get_groups,
.enable = u300_pmx_enable,
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 4e62783a573a..3d5ac73bd5a7 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -33,22 +33,25 @@
int pinmux_check_ops(struct pinctrl_dev *pctldev)
{
const struct pinmux_ops *ops = pctldev->desc->pmxops;
+ unsigned nfuncs;
unsigned selector = 0;
/* Check that we implement required operations */
- if (!ops->list_functions ||
+ if (!ops ||
+ !ops->get_functions_count ||
!ops->get_function_name ||
!ops->get_function_groups ||
- !ops->enable ||
- !ops->disable)
+ !ops->enable) {
+ dev_err(pctldev->dev, "pinmux ops lacks necessary functions\n");
return -EINVAL;
-
+ }
/* Check that all functions registered have names */
- while (ops->list_functions(pctldev, selector) >= 0) {
+ nfuncs = ops->get_functions_count(pctldev);
+ while (selector < nfuncs) {
const char *fname = ops->get_function_name(pctldev,
selector);
if (!fname) {
- pr_err("pinmux ops has no name for function%u\n",
+ dev_err(pctldev->dev, "pinmux ops has no name for function%u\n",
selector);
return -EINVAL;
}
@@ -85,20 +88,23 @@ static int pin_request(struct pinctrl_dev *pctldev,
const struct pinmux_ops *ops = pctldev->desc->pmxops;
int status = -EINVAL;
- dev_dbg(pctldev->dev, "request pin %d for %s\n", pin, owner);
-
desc = pin_desc_get(pctldev, pin);
if (desc == NULL) {
dev_err(pctldev->dev,
- "pin is not registered so it cannot be requested\n");
+ "pin %d is not registered so it cannot be requested\n",
+ pin);
goto out;
}
+ dev_dbg(pctldev->dev, "request pin %d (%s) for %s\n",
+ pin, desc->name, owner);
+
if (gpio_range) {
/* There's no need to support multiple GPIO requests */
if (desc->gpio_owner) {
dev_err(pctldev->dev,
- "pin already requested\n");
+ "pin %s already requested by %s; cannot claim for %s\n",
+ desc->name, desc->gpio_owner, owner);
goto out;
}
@@ -106,7 +112,8 @@ static int pin_request(struct pinctrl_dev *pctldev,
} else {
if (desc->mux_usecount && strcmp(desc->mux_owner, owner)) {
dev_err(pctldev->dev,
- "pin already requested\n");
+ "pin %s already requested by %s; cannot claim for %s\n",
+ desc->name, desc->mux_owner, owner);
goto out;
}
@@ -139,8 +146,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
status = 0;
if (status) {
- dev_err(pctldev->dev, "->request on device %s failed for pin %d\n",
- pctldev->desc->name, pin);
+ dev_err(pctldev->dev, "request() failed for pin %d\n", pin);
module_put(pctldev->owner);
}
@@ -157,7 +163,7 @@ out_free_pin:
out:
if (status)
dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
- pin, owner, status);
+ pin, owner, status);
return status;
}
@@ -287,10 +293,11 @@ static int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
const char *function)
{
const struct pinmux_ops *ops = pctldev->desc->pmxops;
+ unsigned nfuncs = ops->get_functions_count(pctldev);
unsigned selector = 0;
/* See if this pctldev has this function */
- while (ops->list_functions(pctldev, selector) >= 0) {
+ while (selector < nfuncs) {
const char *fname = ops->get_function_name(pctldev,
selector);
@@ -319,18 +326,32 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
const unsigned *pins;
unsigned num_pins;
- setting->data.mux.func =
- pinmux_func_name_to_selector(pctldev, map->data.mux.function);
- if (setting->data.mux.func < 0)
- return setting->data.mux.func;
+ if (!pmxops) {
+ dev_err(pctldev->dev, "does not support mux function\n");
+ return -EINVAL;
+ }
+
+ ret = pinmux_func_name_to_selector(pctldev, map->data.mux.function);
+ if (ret < 0) {
+ dev_err(pctldev->dev, "invalid function %s in map table\n",
+ map->data.mux.function);
+ return ret;
+ }
+ setting->data.mux.func = ret;
ret = pmxops->get_function_groups(pctldev, setting->data.mux.func,
&groups, &num_groups);
- if (ret < 0)
+ if (ret < 0) {
+ dev_err(pctldev->dev, "can't query groups for function %s\n",
+ map->data.mux.function);
return ret;
- if (!num_groups)
+ }
+ if (!num_groups) {
+ dev_err(pctldev->dev,
+ "function %s can't be selected on any group\n",
+ map->data.mux.function);
return -EINVAL;
-
+ }
if (map->data.mux.group) {
bool found = false;
group = map->data.mux.group;
@@ -340,15 +361,23 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
break;
}
}
- if (!found)
+ if (!found) {
+ dev_err(pctldev->dev,
+ "invalid group \"%s\" for function \"%s\"\n",
+ group, map->data.mux.function);
return -EINVAL;
+ }
} else {
group = groups[0];
}
- setting->data.mux.group = pinctrl_get_group_selector(pctldev, group);
- if (setting->data.mux.group < 0)
- return setting->data.mux.group;
+ ret = pinctrl_get_group_selector(pctldev, group);
+ if (ret < 0) {
+ dev_err(pctldev->dev, "invalid group %s in map table\n",
+ map->data.mux.group);
+ return ret;
+ }
+ setting->data.mux.group = ret;
ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins,
&num_pins);
@@ -364,7 +393,7 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
ret = pin_request(pctldev, pins[i], map->dev_name, NULL);
if (ret) {
dev_err(pctldev->dev,
- "could not get request pin %d on device %s\n",
+ "could not request pin %d on device %s\n",
pins[i], pinctrl_dev_get_name(pctldev));
/* On error release all taken pins */
i--; /* this pin just failed */
@@ -467,7 +496,8 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
desc->mux_setting = NULL;
}
- ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);
+ if (ops->disable)
+ ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);
}
#ifdef CONFIG_DEBUG_FS
@@ -477,11 +507,15 @@ static int pinmux_functions_show(struct seq_file *s, void *what)
{
struct pinctrl_dev *pctldev = s->private;
const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
+ unsigned nfuncs;
unsigned func_selector = 0;
- mutex_lock(&pinctrl_mutex);
+ if (!pmxops)
+ return 0;
- while (pmxops->list_functions(pctldev, func_selector) >= 0) {
+ mutex_lock(&pinctrl_mutex);
+ nfuncs = pmxops->get_functions_count(pctldev);
+ while (func_selector < nfuncs) {
const char *func = pmxops->get_function_name(pctldev,
func_selector);
const char * const *groups;
@@ -515,6 +549,9 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
unsigned i, pin;
+ if (!pmxops)
+ return 0;
+
seq_puts(s, "Pinmux settings per pin\n");
seq_puts(s, "Format: pin (name): mux_owner gpio_owner hog?\n");
diff --git a/drivers/pinctrl/pinmux.h b/drivers/pinctrl/pinmux.h
index 6fc47003e95d..d1a98b1c9fce 100644
--- a/drivers/pinctrl/pinmux.h
+++ b/drivers/pinctrl/pinmux.h
@@ -31,12 +31,6 @@ void pinmux_free_setting(struct pinctrl_setting const *setting);
int pinmux_enable_setting(struct pinctrl_setting const *setting);
void pinmux_disable_setting(struct pinctrl_setting const *setting);
-void pinmux_show_map(struct seq_file *s, struct pinctrl_map const *map);
-void pinmux_show_setting(struct seq_file *s,
- struct pinctrl_setting const *setting);
-void pinmux_init_device_debugfs(struct dentry *devroot,
- struct pinctrl_dev *pctldev);
-
#else
static inline int pinmux_check_ops(struct pinctrl_dev *pctldev)
@@ -89,6 +83,18 @@ static inline void pinmux_disable_setting(
{
}
+#endif
+
+#if defined(CONFIG_PINMUX) && defined(CONFIG_DEBUG_FS)
+
+void pinmux_show_map(struct seq_file *s, struct pinctrl_map const *map);
+void pinmux_show_setting(struct seq_file *s,
+ struct pinctrl_setting const *setting);
+void pinmux_init_device_debugfs(struct dentry *devroot,
+ struct pinctrl_dev *pctldev);
+
+#else
+
static inline void pinmux_show_map(struct seq_file *s,
struct pinctrl_map const *map)
{
diff --git a/drivers/pinctrl/spear/Kconfig b/drivers/pinctrl/spear/Kconfig
new file mode 100644
index 000000000000..6a2596b4f359
--- /dev/null
+++ b/drivers/pinctrl/spear/Kconfig
@@ -0,0 +1,34 @@
+#
+# ST Microelectronics SPEAr PINCTRL drivers
+#
+
+if PLAT_SPEAR
+
+config PINCTRL_SPEAR
+ bool
+ depends on OF
+ select PINMUX
+ help
+ This enables pin control drivers for SPEAr Platform
+
+config PINCTRL_SPEAR3XX
+ bool
+ depends on ARCH_SPEAR3XX
+ select PINCTRL_SPEAR
+
+config PINCTRL_SPEAR300
+ bool "ST Microelectronics SPEAr300 SoC pin controller driver"
+ depends on MACH_SPEAR300
+ select PINCTRL_SPEAR3XX
+
+config PINCTRL_SPEAR310
+ bool "ST Microelectronics SPEAr310 SoC pin controller driver"
+ depends on MACH_SPEAR310
+ select PINCTRL_SPEAR3XX
+
+config PINCTRL_SPEAR320
+ bool "ST Microelectronics SPEAr320 SoC pin controller driver"
+ depends on MACH_SPEAR320
+ select PINCTRL_SPEAR3XX
+
+endif
diff --git a/drivers/pinctrl/spear/Makefile b/drivers/pinctrl/spear/Makefile
new file mode 100644
index 000000000000..15dcb85da22d
--- /dev/null
+++ b/drivers/pinctrl/spear/Makefile
@@ -0,0 +1,7 @@
+# SPEAr pinmux support
+
+obj-$(CONFIG_PINCTRL_SPEAR) += pinctrl-spear.o
+obj-$(CONFIG_PINCTRL_SPEAR3XX) += pinctrl-spear3xx.o
+obj-$(CONFIG_PINCTRL_SPEAR300) += pinctrl-spear300.o
+obj-$(CONFIG_PINCTRL_SPEAR310) += pinctrl-spear310.o
+obj-$(CONFIG_PINCTRL_SPEAR320) += pinctrl-spear320.o
diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
new file mode 100644
index 000000000000..5ae50aadf885
--- /dev/null
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -0,0 +1,354 @@
+/*
+ * Driver for the ST Microelectronics SPEAr pinmux
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * Inspired from:
+ * - U300 Pinctl drivers
+ * - Tegra Pinctl drivers
+ *
+ * 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/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "pinctrl-spear.h"
+
+#define DRIVER_NAME "spear-pinmux"
+
+static inline u32 pmx_readl(struct spear_pmx *pmx, u32 reg)
+{
+ return readl_relaxed(pmx->vbase + reg);
+}
+
+static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
+{
+ writel_relaxed(val, pmx->vbase + reg);
+}
+
+static int set_mode(struct spear_pmx *pmx, int mode)
+{
+ struct spear_pmx_mode *pmx_mode = NULL;
+ int i;
+ u32 val;
+
+ if (!pmx->machdata->pmx_modes || !pmx->machdata->npmx_modes)
+ return -EINVAL;
+
+ for (i = 0; i < pmx->machdata->npmx_modes; i++) {
+ if (pmx->machdata->pmx_modes[i]->mode == (1 << mode)) {
+ pmx_mode = pmx->machdata->pmx_modes[i];
+ break;
+ }
+ }
+
+ if (!pmx_mode)
+ return -EINVAL;
+
+ val = pmx_readl(pmx, pmx_mode->reg);
+ val &= ~pmx_mode->mask;
+ val |= pmx_mode->val;
+ pmx_writel(pmx, val, pmx_mode->reg);
+
+ pmx->machdata->mode = pmx_mode->mode;
+ dev_info(pmx->dev, "Configured Mode: %s with id: %x\n\n",
+ pmx_mode->name ? pmx_mode->name : "no_name",
+ pmx_mode->reg);
+
+ return 0;
+}
+
+void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg)
+{
+ struct spear_pingroup *pgroup;
+ struct spear_modemux *modemux;
+ int i, j, group;
+
+ for (group = 0; group < machdata->ngroups; group++) {
+ pgroup = machdata->groups[group];
+
+ for (i = 0; i < pgroup->nmodemuxs; i++) {
+ modemux = &pgroup->modemuxs[i];
+
+ for (j = 0; j < modemux->nmuxregs; j++)
+ if (modemux->muxregs[j].reg == 0xFFFF)
+ modemux->muxregs[j].reg = reg;
+ }
+ }
+}
+
+static int spear_pinctrl_get_groups_cnt(struct pinctrl_dev *pctldev)
+{
+ struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+ return pmx->machdata->ngroups;
+}
+
+static const char *spear_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+ return pmx->machdata->groups[group]->name;
+}
+
+static int spear_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins, unsigned *num_pins)
+{
+ struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+ *pins = pmx->machdata->groups[group]->pins;
+ *num_pins = pmx->machdata->groups[group]->npins;
+
+ return 0;
+}
+
+static void spear_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned offset)
+{
+ seq_printf(s, " " DRIVER_NAME);
+}
+
+int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np_config,
+ struct pinctrl_map **map, unsigned *num_maps)
+{
+ struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+ struct device_node *np;
+ struct property *prop;
+ const char *function, *group;
+ int ret, index = 0, count = 0;
+
+ /* calculate number of maps required */
+ for_each_child_of_node(np_config, np) {
+ ret = of_property_read_string(np, "st,function", &function);
+ if (ret < 0)
+ return ret;
+
+ ret = of_property_count_strings(np, "st,pins");
+ if (ret < 0)
+ return ret;
+
+ count += ret;
+ }
+
+ if (!count) {
+ dev_err(pmx->dev, "No child nodes passed via DT\n");
+ return -ENODEV;
+ }
+
+ *map = kzalloc(sizeof(**map) * count, GFP_KERNEL);
+ if (!*map)
+ return -ENOMEM;
+
+ for_each_child_of_node(np_config, np) {
+ of_property_read_string(np, "st,function", &function);
+ of_property_for_each_string(np, "st,pins", prop, group) {
+ (*map)[index].type = PIN_MAP_TYPE_MUX_GROUP;
+ (*map)[index].data.mux.group = group;
+ (*map)[index].data.mux.function = function;
+ index++;
+ }
+ }
+
+ *num_maps = count;
+
+ return 0;
+}
+
+void spear_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ kfree(map);
+}
+
+static struct pinctrl_ops spear_pinctrl_ops = {
+ .get_groups_count = spear_pinctrl_get_groups_cnt,
+ .get_group_name = spear_pinctrl_get_group_name,
+ .get_group_pins = spear_pinctrl_get_group_pins,
+ .pin_dbg_show = spear_pinctrl_pin_dbg_show,
+ .dt_node_to_map = spear_pinctrl_dt_node_to_map,
+ .dt_free_map = spear_pinctrl_dt_free_map,
+};
+
+static int spear_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+ struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+ return pmx->machdata->nfunctions;
+}
+
+static const char *spear_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned function)
+{
+ struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+ return pmx->machdata->functions[function]->name;
+}
+
+static int spear_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
+ unsigned function, const char *const **groups,
+ unsigned * const ngroups)
+{
+ struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = pmx->machdata->functions[function]->groups;
+ *ngroups = pmx->machdata->functions[function]->ngroups;
+
+ return 0;
+}
+
+static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
+ unsigned function, unsigned group, bool enable)
+{
+ struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+ const struct spear_pingroup *pgroup;
+ const struct spear_modemux *modemux;
+ struct spear_muxreg *muxreg;
+ u32 val, temp;
+ int i, j;
+ bool found = false;
+
+ pgroup = pmx->machdata->groups[group];
+
+ for (i = 0; i < pgroup->nmodemuxs; i++) {
+ modemux = &pgroup->modemuxs[i];
+
+ /* SoC have any modes */
+ if (pmx->machdata->modes_supported) {
+ if (!(pmx->machdata->mode & modemux->modes))
+ continue;
+ }
+
+ found = true;
+ for (j = 0; j < modemux->nmuxregs; j++) {
+ muxreg = &modemux->muxregs[j];
+
+ val = pmx_readl(pmx, muxreg->reg);
+ val &= ~muxreg->mask;
+
+ if (enable)
+ temp = muxreg->val;
+ else
+ temp = ~muxreg->val;
+
+ val |= temp;
+ pmx_writel(pmx, val, muxreg->reg);
+ }
+ }
+
+ if (!found) {
+ dev_err(pmx->dev, "pinmux group: %s not supported\n",
+ pgroup->name);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int spear_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function,
+ unsigned group)
+{
+ return spear_pinctrl_endisable(pctldev, function, group, true);
+}
+
+static void spear_pinctrl_disable(struct pinctrl_dev *pctldev,
+ unsigned function, unsigned group)
+{
+ spear_pinctrl_endisable(pctldev, function, group, false);
+}
+
+static struct pinmux_ops spear_pinmux_ops = {
+ .get_functions_count = spear_pinctrl_get_funcs_count,
+ .get_function_name = spear_pinctrl_get_func_name,
+ .get_function_groups = spear_pinctrl_get_func_groups,
+ .enable = spear_pinctrl_enable,
+ .disable = spear_pinctrl_disable,
+};
+
+static struct pinctrl_desc spear_pinctrl_desc = {
+ .name = DRIVER_NAME,
+ .pctlops = &spear_pinctrl_ops,
+ .pmxops = &spear_pinmux_ops,
+ .owner = THIS_MODULE,
+};
+
+int __devinit spear_pinctrl_probe(struct platform_device *pdev,
+ struct spear_pinctrl_machdata *machdata)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *res;
+ struct spear_pmx *pmx;
+
+ if (!machdata)
+ return -ENODEV;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
+ if (!pmx) {
+ dev_err(&pdev->dev, "Can't alloc spear_pmx\n");
+ return -ENOMEM;
+ }
+
+ pmx->vbase = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!pmx->vbase) {
+ dev_err(&pdev->dev, "Couldn't ioremap at index 0\n");
+ return -ENODEV;
+ }
+
+ pmx->dev = &pdev->dev;
+ pmx->machdata = machdata;
+
+ /* configure mode, if supported by SoC */
+ if (machdata->modes_supported) {
+ int mode = 0;
+
+ if (of_property_read_u32(np, "st,pinmux-mode", &mode)) {
+ dev_err(&pdev->dev, "OF: pinmux mode not passed\n");
+ return -EINVAL;
+ }
+
+ if (set_mode(pmx, mode)) {
+ dev_err(&pdev->dev, "OF: Couldn't configure mode: %x\n",
+ mode);
+ return -EINVAL;
+ }
+ }
+
+ platform_set_drvdata(pdev, pmx);
+
+ spear_pinctrl_desc.pins = machdata->pins;
+ spear_pinctrl_desc.npins = machdata->npins;
+
+ pmx->pctl = pinctrl_register(&spear_pinctrl_desc, &pdev->dev, pmx);
+ if (IS_ERR(pmx->pctl)) {
+ dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
+ return PTR_ERR(pmx->pctl);
+ }
+
+ return 0;
+}
+
+int __devexit spear_pinctrl_remove(struct platform_device *pdev)
+{
+ struct spear_pmx *pmx = platform_get_drvdata(pdev);
+
+ pinctrl_unregister(pmx->pctl);
+
+ return 0;
+}
diff --git a/drivers/pinctrl/spear/pinctrl-spear.h b/drivers/pinctrl/spear/pinctrl-spear.h
new file mode 100644
index 000000000000..47a6b5b72f90
--- /dev/null
+++ b/drivers/pinctrl/spear/pinctrl-spear.h
@@ -0,0 +1,142 @@
+/*
+ * Driver header file for the ST Microelectronics SPEAr pinmux
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PINMUX_SPEAR_H__
+#define __PINMUX_SPEAR_H__
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/types.h>
+
+struct platform_device;
+struct device;
+
+/**
+ * struct spear_pmx_mode - SPEAr pmx mode
+ * @name: name of pmx mode
+ * @mode: mode id
+ * @reg: register for configuring this mode
+ * @mask: mask of this mode in reg
+ * @val: val to be configured at reg after doing (val & mask)
+ */
+struct spear_pmx_mode {
+ const char *const name;
+ u16 mode;
+ u16 reg;
+ u16 mask;
+ u32 val;
+};
+
+/**
+ * struct spear_muxreg - SPEAr mux reg configuration
+ * @reg: register offset
+ * @mask: mask bits
+ * @val: val to be written on mask bits
+ */
+struct spear_muxreg {
+ u16 reg;
+ u32 mask;
+ u32 val;
+};
+
+/**
+ * struct spear_modemux - SPEAr mode mux configuration
+ * @modes: mode ids supported by this group of muxregs
+ * @nmuxregs: number of muxreg configurations to be done for modes
+ * @muxregs: array of muxreg configurations to be done for modes
+ */
+struct spear_modemux {
+ u16 modes;
+ u8 nmuxregs;
+ struct spear_muxreg *muxregs;
+};
+
+/**
+ * struct spear_pingroup - SPEAr pin group configurations
+ * @name: name of pin group
+ * @pins: array containing pin numbers
+ * @npins: size of pins array
+ * @modemuxs: array of modemux configurations for this pin group
+ * @nmodemuxs: size of array modemuxs
+ *
+ * A representation of a group of pins in the SPEAr pin controller. Each group
+ * allows some parameter or parameters to be configured.
+ */
+struct spear_pingroup {
+ const char *name;
+ const unsigned *pins;
+ unsigned npins;
+ struct spear_modemux *modemuxs;
+ unsigned nmodemuxs;
+};
+
+/**
+ * struct spear_function - SPEAr pinctrl mux function
+ * @name: The name of the function, exported to pinctrl core.
+ * @groups: An array of pin groups that may select this function.
+ * @ngroups: The number of entries in @groups.
+ */
+struct spear_function {
+ const char *name;
+ const char *const *groups;
+ unsigned ngroups;
+};
+
+/**
+ * struct spear_pinctrl_machdata - SPEAr pin controller machine driver
+ * configuration
+ * @pins: An array describing all pins the pin controller affects.
+ * All pins which are also GPIOs must be listed first within the *array,
+ * and be numbered identically to the GPIO controller's *numbering.
+ * @npins: The numbmer of entries in @pins.
+ * @functions: An array describing all mux functions the SoC supports.
+ * @nfunctions: The numbmer of entries in @functions.
+ * @groups: An array describing all pin groups the pin SoC supports.
+ * @ngroups: The numbmer of entries in @groups.
+ *
+ * @modes_supported: Does SoC support modes
+ * @mode: mode configured from probe
+ * @pmx_modes: array of modes supported by SoC
+ * @npmx_modes: number of entries in pmx_modes.
+ */
+struct spear_pinctrl_machdata {
+ const struct pinctrl_pin_desc *pins;
+ unsigned npins;
+ struct spear_function **functions;
+ unsigned nfunctions;
+ struct spear_pingroup **groups;
+ unsigned ngroups;
+
+ bool modes_supported;
+ u16 mode;
+ struct spear_pmx_mode **pmx_modes;
+ unsigned npmx_modes;
+};
+
+/**
+ * struct spear_pmx - SPEAr pinctrl mux
+ * @dev: pointer to struct dev of platform_device registered
+ * @pctl: pointer to struct pinctrl_dev
+ * @machdata: pointer to SoC or machine specific structure
+ * @vbase: virtual base address of pinmux controller
+ */
+struct spear_pmx {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+ struct spear_pinctrl_machdata *machdata;
+ void __iomem *vbase;
+};
+
+/* exported routines */
+void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg);
+int __devinit spear_pinctrl_probe(struct platform_device *pdev,
+ struct spear_pinctrl_machdata *machdata);
+int __devexit spear_pinctrl_remove(struct platform_device *pdev);
+#endif /* __PINMUX_SPEAR_H__ */
diff --git a/drivers/pinctrl/spear/pinctrl-spear300.c b/drivers/pinctrl/spear/pinctrl-spear300.c
new file mode 100644
index 000000000000..9c82a35e4e78
--- /dev/null
+++ b/drivers/pinctrl/spear/pinctrl-spear300.c
@@ -0,0 +1,708 @@
+/*
+ * Driver for the ST Microelectronics SPEAr300 pinmux
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "pinctrl-spear3xx.h"
+
+#define DRIVER_NAME "spear300-pinmux"
+
+/* addresses */
+#define PMX_CONFIG_REG 0x00
+#define MODE_CONFIG_REG 0x04
+
+/* modes */
+#define NAND_MODE (1 << 0)
+#define NOR_MODE (1 << 1)
+#define PHOTO_FRAME_MODE (1 << 2)
+#define LEND_IP_PHONE_MODE (1 << 3)
+#define HEND_IP_PHONE_MODE (1 << 4)
+#define LEND_WIFI_PHONE_MODE (1 << 5)
+#define HEND_WIFI_PHONE_MODE (1 << 6)
+#define ATA_PABX_WI2S_MODE (1 << 7)
+#define ATA_PABX_I2S_MODE (1 << 8)
+#define CAML_LCDW_MODE (1 << 9)
+#define CAMU_LCD_MODE (1 << 10)
+#define CAMU_WLCD_MODE (1 << 11)
+#define CAML_LCD_MODE (1 << 12)
+
+static struct spear_pmx_mode pmx_mode_nand = {
+ .name = "nand",
+ .mode = NAND_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x0000000F,
+ .val = 0x00,
+};
+
+static struct spear_pmx_mode pmx_mode_nor = {
+ .name = "nor",
+ .mode = NOR_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x0000000F,
+ .val = 0x01,
+};
+
+static struct spear_pmx_mode pmx_mode_photo_frame = {
+ .name = "photo frame mode",
+ .mode = PHOTO_FRAME_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x0000000F,
+ .val = 0x02,
+};
+
+static struct spear_pmx_mode pmx_mode_lend_ip_phone = {
+ .name = "lend ip phone mode",
+ .mode = LEND_IP_PHONE_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x0000000F,
+ .val = 0x03,
+};
+
+static struct spear_pmx_mode pmx_mode_hend_ip_phone = {
+ .name = "hend ip phone mode",
+ .mode = HEND_IP_PHONE_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x0000000F,
+ .val = 0x04,
+};
+
+static struct spear_pmx_mode pmx_mode_lend_wifi_phone = {
+ .name = "lend wifi phone mode",
+ .mode = LEND_WIFI_PHONE_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x0000000F,
+ .val = 0x05,
+};
+
+static struct spear_pmx_mode pmx_mode_hend_wifi_phone = {
+ .name = "hend wifi phone mode",
+ .mode = HEND_WIFI_PHONE_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x0000000F,
+ .val = 0x06,
+};
+
+static struct spear_pmx_mode pmx_mode_ata_pabx_wi2s = {
+ .name = "ata pabx wi2s mode",
+ .mode = ATA_PABX_WI2S_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x0000000F,
+ .val = 0x07,
+};
+
+static struct spear_pmx_mode pmx_mode_ata_pabx_i2s = {
+ .name = "ata pabx i2s mode",
+ .mode = ATA_PABX_I2S_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x0000000F,
+ .val = 0x08,
+};
+
+static struct spear_pmx_mode pmx_mode_caml_lcdw = {
+ .name = "caml lcdw mode",
+ .mode = CAML_LCDW_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x0000000F,
+ .val = 0x0C,
+};
+
+static struct spear_pmx_mode pmx_mode_camu_lcd = {
+ .name = "camu lcd mode",
+ .mode = CAMU_LCD_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x0000000F,
+ .val = 0x0D,
+};
+
+static struct spear_pmx_mode pmx_mode_camu_wlcd = {
+ .name = "camu wlcd mode",
+ .mode = CAMU_WLCD_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x0000000F,
+ .val = 0xE,
+};
+
+static struct spear_pmx_mode pmx_mode_caml_lcd = {
+ .name = "caml lcd mode",
+ .mode = CAML_LCD_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x0000000F,
+ .val = 0x0F,
+};
+
+static struct spear_pmx_mode *spear300_pmx_modes[] = {
+ &pmx_mode_nand,
+ &pmx_mode_nor,
+ &pmx_mode_photo_frame,
+ &pmx_mode_lend_ip_phone,
+ &pmx_mode_hend_ip_phone,
+ &pmx_mode_lend_wifi_phone,
+ &pmx_mode_hend_wifi_phone,
+ &pmx_mode_ata_pabx_wi2s,
+ &pmx_mode_ata_pabx_i2s,
+ &pmx_mode_caml_lcdw,
+ &pmx_mode_camu_lcd,
+ &pmx_mode_camu_wlcd,
+ &pmx_mode_caml_lcd,
+};
+
+/* fsmc_2chips_pins */
+static const unsigned fsmc_2chips_pins[] = { 1, 97 };
+static struct spear_muxreg fsmc_2chips_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_FIRDA_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux fsmc_2chips_modemux[] = {
+ {
+ .modes = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE |
+ ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE,
+ .muxregs = fsmc_2chips_muxreg,
+ .nmuxregs = ARRAY_SIZE(fsmc_2chips_muxreg),
+ },
+};
+
+static struct spear_pingroup fsmc_2chips_pingroup = {
+ .name = "fsmc_2chips_grp",
+ .pins = fsmc_2chips_pins,
+ .npins = ARRAY_SIZE(fsmc_2chips_pins),
+ .modemuxs = fsmc_2chips_modemux,
+ .nmodemuxs = ARRAY_SIZE(fsmc_2chips_modemux),
+};
+
+/* fsmc_4chips_pins */
+static const unsigned fsmc_4chips_pins[] = { 1, 2, 3, 97 };
+static struct spear_muxreg fsmc_4chips_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_FIRDA_MASK | PMX_UART0_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux fsmc_4chips_modemux[] = {
+ {
+ .modes = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE |
+ ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE,
+ .muxregs = fsmc_4chips_muxreg,
+ .nmuxregs = ARRAY_SIZE(fsmc_4chips_muxreg),
+ },
+};
+
+static struct spear_pingroup fsmc_4chips_pingroup = {
+ .name = "fsmc_4chips_grp",
+ .pins = fsmc_4chips_pins,
+ .npins = ARRAY_SIZE(fsmc_4chips_pins),
+ .modemuxs = fsmc_4chips_modemux,
+ .nmodemuxs = ARRAY_SIZE(fsmc_4chips_modemux),
+};
+
+static const char *const fsmc_grps[] = { "fsmc_2chips_grp", "fsmc_4chips_grp"
+};
+static struct spear_function fsmc_function = {
+ .name = "fsmc",
+ .groups = fsmc_grps,
+ .ngroups = ARRAY_SIZE(fsmc_grps),
+};
+
+/* clcd_lcdmode_pins */
+static const unsigned clcd_lcdmode_pins[] = { 49, 50 };
+static struct spear_muxreg clcd_lcdmode_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux clcd_lcdmode_modemux[] = {
+ {
+ .modes = HEND_IP_PHONE_MODE | HEND_WIFI_PHONE_MODE |
+ CAMU_LCD_MODE | CAML_LCD_MODE,
+ .muxregs = clcd_lcdmode_muxreg,
+ .nmuxregs = ARRAY_SIZE(clcd_lcdmode_muxreg),
+ },
+};
+
+static struct spear_pingroup clcd_lcdmode_pingroup = {
+ .name = "clcd_lcdmode_grp",
+ .pins = clcd_lcdmode_pins,
+ .npins = ARRAY_SIZE(clcd_lcdmode_pins),
+ .modemuxs = clcd_lcdmode_modemux,
+ .nmodemuxs = ARRAY_SIZE(clcd_lcdmode_modemux),
+};
+
+/* clcd_pfmode_pins */
+static const unsigned clcd_pfmode_pins[] = { 47, 48, 49, 50 };
+static struct spear_muxreg clcd_pfmode_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_2_3_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux clcd_pfmode_modemux[] = {
+ {
+ .modes = PHOTO_FRAME_MODE,
+ .muxregs = clcd_pfmode_muxreg,
+ .nmuxregs = ARRAY_SIZE(clcd_pfmode_muxreg),
+ },
+};
+
+static struct spear_pingroup clcd_pfmode_pingroup = {
+ .name = "clcd_pfmode_grp",
+ .pins = clcd_pfmode_pins,
+ .npins = ARRAY_SIZE(clcd_pfmode_pins),
+ .modemuxs = clcd_pfmode_modemux,
+ .nmodemuxs = ARRAY_SIZE(clcd_pfmode_modemux),
+};
+
+static const char *const clcd_grps[] = { "clcd_lcdmode_grp", "clcd_pfmode_grp"
+};
+static struct spear_function clcd_function = {
+ .name = "clcd",
+ .groups = clcd_grps,
+ .ngroups = ARRAY_SIZE(clcd_grps),
+};
+
+/* tdm_pins */
+static const unsigned tdm_pins[] = { 34, 35, 36, 37, 38 };
+static struct spear_muxreg tdm_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK | PMX_SSP_CS_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux tdm_modemux[] = {
+ {
+ .modes = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
+ HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE
+ | HEND_WIFI_PHONE_MODE | ATA_PABX_WI2S_MODE
+ | ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
+ | CAMU_WLCD_MODE | CAML_LCD_MODE,
+ .muxregs = tdm_muxreg,
+ .nmuxregs = ARRAY_SIZE(tdm_muxreg),
+ },
+};
+
+static struct spear_pingroup tdm_pingroup = {
+ .name = "tdm_grp",
+ .pins = tdm_pins,
+ .npins = ARRAY_SIZE(tdm_pins),
+ .modemuxs = tdm_modemux,
+ .nmodemuxs = ARRAY_SIZE(tdm_modemux),
+};
+
+static const char *const tdm_grps[] = { "tdm_grp" };
+static struct spear_function tdm_function = {
+ .name = "tdm",
+ .groups = tdm_grps,
+ .ngroups = ARRAY_SIZE(tdm_grps),
+};
+
+/* i2c_clk_pins */
+static const unsigned i2c_clk_pins[] = { 45, 46, 47, 48 };
+static struct spear_muxreg i2c_clk_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux i2c_clk_modemux[] = {
+ {
+ .modes = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE |
+ LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE |
+ ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE | CAML_LCDW_MODE
+ | CAML_LCD_MODE,
+ .muxregs = i2c_clk_muxreg,
+ .nmuxregs = ARRAY_SIZE(i2c_clk_muxreg),
+ },
+};
+
+static struct spear_pingroup i2c_clk_pingroup = {
+ .name = "i2c_clk_grp_grp",
+ .pins = i2c_clk_pins,
+ .npins = ARRAY_SIZE(i2c_clk_pins),
+ .modemuxs = i2c_clk_modemux,
+ .nmodemuxs = ARRAY_SIZE(i2c_clk_modemux),
+};
+
+static const char *const i2c_grps[] = { "i2c_clk_grp" };
+static struct spear_function i2c_function = {
+ .name = "i2c1",
+ .groups = i2c_grps,
+ .ngroups = ARRAY_SIZE(i2c_grps),
+};
+
+/* caml_pins */
+static const unsigned caml_pins[] = { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 };
+static struct spear_muxreg caml_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux caml_modemux[] = {
+ {
+ .modes = CAML_LCDW_MODE | CAML_LCD_MODE,
+ .muxregs = caml_muxreg,
+ .nmuxregs = ARRAY_SIZE(caml_muxreg),
+ },
+};
+
+static struct spear_pingroup caml_pingroup = {
+ .name = "caml_grp",
+ .pins = caml_pins,
+ .npins = ARRAY_SIZE(caml_pins),
+ .modemuxs = caml_modemux,
+ .nmodemuxs = ARRAY_SIZE(caml_modemux),
+};
+
+/* camu_pins */
+static const unsigned camu_pins[] = { 16, 17, 18, 19, 20, 21, 45, 46, 47, 48 };
+static struct spear_muxreg camu_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK | PMX_MII_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux camu_modemux[] = {
+ {
+ .modes = CAMU_LCD_MODE | CAMU_WLCD_MODE,
+ .muxregs = camu_muxreg,
+ .nmuxregs = ARRAY_SIZE(camu_muxreg),
+ },
+};
+
+static struct spear_pingroup camu_pingroup = {
+ .name = "camu_grp",
+ .pins = camu_pins,
+ .npins = ARRAY_SIZE(camu_pins),
+ .modemuxs = camu_modemux,
+ .nmodemuxs = ARRAY_SIZE(camu_modemux),
+};
+
+static const char *const cam_grps[] = { "caml_grp", "camu_grp" };
+static struct spear_function cam_function = {
+ .name = "cam",
+ .groups = cam_grps,
+ .ngroups = ARRAY_SIZE(cam_grps),
+};
+
+/* dac_pins */
+static const unsigned dac_pins[] = { 43, 44 };
+static struct spear_muxreg dac_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_0_1_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux dac_modemux[] = {
+ {
+ .modes = ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
+ | CAMU_WLCD_MODE | CAML_LCD_MODE,
+ .muxregs = dac_muxreg,
+ .nmuxregs = ARRAY_SIZE(dac_muxreg),
+ },
+};
+
+static struct spear_pingroup dac_pingroup = {
+ .name = "dac_grp",
+ .pins = dac_pins,
+ .npins = ARRAY_SIZE(dac_pins),
+ .modemuxs = dac_modemux,
+ .nmodemuxs = ARRAY_SIZE(dac_modemux),
+};
+
+static const char *const dac_grps[] = { "dac_grp" };
+static struct spear_function dac_function = {
+ .name = "dac",
+ .groups = dac_grps,
+ .ngroups = ARRAY_SIZE(dac_grps),
+};
+
+/* i2s_pins */
+static const unsigned i2s_pins[] = { 39, 40, 41, 42 };
+static struct spear_muxreg i2s_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux i2s_modemux[] = {
+ {
+ .modes = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE
+ | LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE |
+ ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
+ | CAMU_WLCD_MODE | CAML_LCD_MODE,
+ .muxregs = i2s_muxreg,
+ .nmuxregs = ARRAY_SIZE(i2s_muxreg),
+ },
+};
+
+static struct spear_pingroup i2s_pingroup = {
+ .name = "i2s_grp",
+ .pins = i2s_pins,
+ .npins = ARRAY_SIZE(i2s_pins),
+ .modemuxs = i2s_modemux,
+ .nmodemuxs = ARRAY_SIZE(i2s_modemux),
+};
+
+static const char *const i2s_grps[] = { "i2s_grp" };
+static struct spear_function i2s_function = {
+ .name = "i2s",
+ .groups = i2s_grps,
+ .ngroups = ARRAY_SIZE(i2s_grps),
+};
+
+/* sdhci_4bit_pins */
+static const unsigned sdhci_4bit_pins[] = { 28, 29, 30, 31, 32, 33 };
+static struct spear_muxreg sdhci_4bit_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
+ PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
+ PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux sdhci_4bit_modemux[] = {
+ {
+ .modes = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
+ HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
+ HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE |
+ CAMU_WLCD_MODE | CAML_LCD_MODE | ATA_PABX_WI2S_MODE,
+ .muxregs = sdhci_4bit_muxreg,
+ .nmuxregs = ARRAY_SIZE(sdhci_4bit_muxreg),
+ },
+};
+
+static struct spear_pingroup sdhci_4bit_pingroup = {
+ .name = "sdhci_4bit_grp",
+ .pins = sdhci_4bit_pins,
+ .npins = ARRAY_SIZE(sdhci_4bit_pins),
+ .modemuxs = sdhci_4bit_modemux,
+ .nmodemuxs = ARRAY_SIZE(sdhci_4bit_modemux),
+};
+
+/* sdhci_8bit_pins */
+static const unsigned sdhci_8bit_pins[] = { 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33 };
+static struct spear_muxreg sdhci_8bit_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
+ PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
+ PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK | PMX_MII_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux sdhci_8bit_modemux[] = {
+ {
+ .modes = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
+ HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
+ HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE |
+ CAMU_WLCD_MODE | CAML_LCD_MODE,
+ .muxregs = sdhci_8bit_muxreg,
+ .nmuxregs = ARRAY_SIZE(sdhci_8bit_muxreg),
+ },
+};
+
+static struct spear_pingroup sdhci_8bit_pingroup = {
+ .name = "sdhci_8bit_grp",
+ .pins = sdhci_8bit_pins,
+ .npins = ARRAY_SIZE(sdhci_8bit_pins),
+ .modemuxs = sdhci_8bit_modemux,
+ .nmodemuxs = ARRAY_SIZE(sdhci_8bit_modemux),
+};
+
+static const char *const sdhci_grps[] = { "sdhci_4bit_grp", "sdhci_8bit_grp" };
+static struct spear_function sdhci_function = {
+ .name = "sdhci",
+ .groups = sdhci_grps,
+ .ngroups = ARRAY_SIZE(sdhci_grps),
+};
+
+/* gpio1_0_to_3_pins */
+static const unsigned gpio1_0_to_3_pins[] = { 39, 40, 41, 42 };
+static struct spear_muxreg gpio1_0_to_3_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux gpio1_0_to_3_modemux[] = {
+ {
+ .modes = PHOTO_FRAME_MODE,
+ .muxregs = gpio1_0_to_3_muxreg,
+ .nmuxregs = ARRAY_SIZE(gpio1_0_to_3_muxreg),
+ },
+};
+
+static struct spear_pingroup gpio1_0_to_3_pingroup = {
+ .name = "gpio1_0_to_3_grp",
+ .pins = gpio1_0_to_3_pins,
+ .npins = ARRAY_SIZE(gpio1_0_to_3_pins),
+ .modemuxs = gpio1_0_to_3_modemux,
+ .nmodemuxs = ARRAY_SIZE(gpio1_0_to_3_modemux),
+};
+
+/* gpio1_4_to_7_pins */
+static const unsigned gpio1_4_to_7_pins[] = { 43, 44, 45, 46 };
+
+static struct spear_muxreg gpio1_4_to_7_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux gpio1_4_to_7_modemux[] = {
+ {
+ .modes = PHOTO_FRAME_MODE,
+ .muxregs = gpio1_4_to_7_muxreg,
+ .nmuxregs = ARRAY_SIZE(gpio1_4_to_7_muxreg),
+ },
+};
+
+static struct spear_pingroup gpio1_4_to_7_pingroup = {
+ .name = "gpio1_4_to_7_grp",
+ .pins = gpio1_4_to_7_pins,
+ .npins = ARRAY_SIZE(gpio1_4_to_7_pins),
+ .modemuxs = gpio1_4_to_7_modemux,
+ .nmodemuxs = ARRAY_SIZE(gpio1_4_to_7_modemux),
+};
+
+static const char *const gpio1_grps[] = { "gpio1_0_to_3_grp", "gpio1_4_to_7_grp"
+};
+static struct spear_function gpio1_function = {
+ .name = "gpio1",
+ .groups = gpio1_grps,
+ .ngroups = ARRAY_SIZE(gpio1_grps),
+};
+
+/* pingroups */
+static struct spear_pingroup *spear300_pingroups[] = {
+ SPEAR3XX_COMMON_PINGROUPS,
+ &fsmc_2chips_pingroup,
+ &fsmc_4chips_pingroup,
+ &clcd_lcdmode_pingroup,
+ &clcd_pfmode_pingroup,
+ &tdm_pingroup,
+ &i2c_clk_pingroup,
+ &caml_pingroup,
+ &camu_pingroup,
+ &dac_pingroup,
+ &i2s_pingroup,
+ &sdhci_4bit_pingroup,
+ &sdhci_8bit_pingroup,
+ &gpio1_0_to_3_pingroup,
+ &gpio1_4_to_7_pingroup,
+};
+
+/* functions */
+static struct spear_function *spear300_functions[] = {
+ SPEAR3XX_COMMON_FUNCTIONS,
+ &fsmc_function,
+ &clcd_function,
+ &tdm_function,
+ &i2c_function,
+ &cam_function,
+ &dac_function,
+ &i2s_function,
+ &sdhci_function,
+ &gpio1_function,
+};
+
+static struct of_device_id spear300_pinctrl_of_match[] __devinitdata = {
+ {
+ .compatible = "st,spear300-pinmux",
+ },
+ {},
+};
+
+static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ spear3xx_machdata.groups = spear300_pingroups;
+ spear3xx_machdata.ngroups = ARRAY_SIZE(spear300_pingroups);
+ spear3xx_machdata.functions = spear300_functions;
+ spear3xx_machdata.nfunctions = ARRAY_SIZE(spear300_functions);
+
+ spear3xx_machdata.modes_supported = true;
+ spear3xx_machdata.pmx_modes = spear300_pmx_modes;
+ spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear300_pmx_modes);
+
+ pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
+
+ ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int __devexit spear300_pinctrl_remove(struct platform_device *pdev)
+{
+ return spear_pinctrl_remove(pdev);
+}
+
+static struct platform_driver spear300_pinctrl_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = spear300_pinctrl_of_match,
+ },
+ .probe = spear300_pinctrl_probe,
+ .remove = __devexit_p(spear300_pinctrl_remove),
+};
+
+static int __init spear300_pinctrl_init(void)
+{
+ return platform_driver_register(&spear300_pinctrl_driver);
+}
+arch_initcall(spear300_pinctrl_init);
+
+static void __exit spear300_pinctrl_exit(void)
+{
+ platform_driver_unregister(&spear300_pinctrl_driver);
+}
+module_exit(spear300_pinctrl_exit);
+
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
+MODULE_DESCRIPTION("ST Microelectronics SPEAr300 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, spear300_pinctrl_of_match);
diff --git a/drivers/pinctrl/spear/pinctrl-spear310.c b/drivers/pinctrl/spear/pinctrl-spear310.c
new file mode 100644
index 000000000000..1a9707605125
--- /dev/null
+++ b/drivers/pinctrl/spear/pinctrl-spear310.c
@@ -0,0 +1,431 @@
+/*
+ * Driver for the ST Microelectronics SPEAr310 pinmux
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "pinctrl-spear3xx.h"
+
+#define DRIVER_NAME "spear310-pinmux"
+
+/* addresses */
+#define PMX_CONFIG_REG 0x08
+
+/* emi_cs_0_to_5_pins */
+static const unsigned emi_cs_0_to_5_pins[] = { 45, 46, 47, 48, 49, 50 };
+static struct spear_muxreg emi_cs_0_to_5_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux emi_cs_0_to_5_modemux[] = {
+ {
+ .muxregs = emi_cs_0_to_5_muxreg,
+ .nmuxregs = ARRAY_SIZE(emi_cs_0_to_5_muxreg),
+ },
+};
+
+static struct spear_pingroup emi_cs_0_to_5_pingroup = {
+ .name = "emi_cs_0_to_5_grp",
+ .pins = emi_cs_0_to_5_pins,
+ .npins = ARRAY_SIZE(emi_cs_0_to_5_pins),
+ .modemuxs = emi_cs_0_to_5_modemux,
+ .nmodemuxs = ARRAY_SIZE(emi_cs_0_to_5_modemux),
+};
+
+static const char *const emi_cs_0_to_5_grps[] = { "emi_cs_0_to_5_grp" };
+static struct spear_function emi_cs_0_to_5_function = {
+ .name = "emi",
+ .groups = emi_cs_0_to_5_grps,
+ .ngroups = ARRAY_SIZE(emi_cs_0_to_5_grps),
+};
+
+/* uart1_pins */
+static const unsigned uart1_pins[] = { 0, 1 };
+static struct spear_muxreg uart1_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_FIRDA_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux uart1_modemux[] = {
+ {
+ .muxregs = uart1_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart1_muxreg),
+ },
+};
+
+static struct spear_pingroup uart1_pingroup = {
+ .name = "uart1_grp",
+ .pins = uart1_pins,
+ .npins = ARRAY_SIZE(uart1_pins),
+ .modemuxs = uart1_modemux,
+ .nmodemuxs = ARRAY_SIZE(uart1_modemux),
+};
+
+static const char *const uart1_grps[] = { "uart1_grp" };
+static struct spear_function uart1_function = {
+ .name = "uart1",
+ .groups = uart1_grps,
+ .ngroups = ARRAY_SIZE(uart1_grps),
+};
+
+/* uart2_pins */
+static const unsigned uart2_pins[] = { 43, 44 };
+static struct spear_muxreg uart2_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_0_1_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux uart2_modemux[] = {
+ {
+ .muxregs = uart2_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart2_muxreg),
+ },
+};
+
+static struct spear_pingroup uart2_pingroup = {
+ .name = "uart2_grp",
+ .pins = uart2_pins,
+ .npins = ARRAY_SIZE(uart2_pins),
+ .modemuxs = uart2_modemux,
+ .nmodemuxs = ARRAY_SIZE(uart2_modemux),
+};
+
+static const char *const uart2_grps[] = { "uart2_grp" };
+static struct spear_function uart2_function = {
+ .name = "uart2",
+ .groups = uart2_grps,
+ .ngroups = ARRAY_SIZE(uart2_grps),
+};
+
+/* uart3_pins */
+static const unsigned uart3_pins[] = { 37, 38 };
+static struct spear_muxreg uart3_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux uart3_modemux[] = {
+ {
+ .muxregs = uart3_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart3_muxreg),
+ },
+};
+
+static struct spear_pingroup uart3_pingroup = {
+ .name = "uart3_grp",
+ .pins = uart3_pins,
+ .npins = ARRAY_SIZE(uart3_pins),
+ .modemuxs = uart3_modemux,
+ .nmodemuxs = ARRAY_SIZE(uart3_modemux),
+};
+
+static const char *const uart3_grps[] = { "uart3_grp" };
+static struct spear_function uart3_function = {
+ .name = "uart3",
+ .groups = uart3_grps,
+ .ngroups = ARRAY_SIZE(uart3_grps),
+};
+
+/* uart4_pins */
+static const unsigned uart4_pins[] = { 39, 40 };
+static struct spear_muxreg uart4_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux uart4_modemux[] = {
+ {
+ .muxregs = uart4_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart4_muxreg),
+ },
+};
+
+static struct spear_pingroup uart4_pingroup = {
+ .name = "uart4_grp",
+ .pins = uart4_pins,
+ .npins = ARRAY_SIZE(uart4_pins),
+ .modemuxs = uart4_modemux,
+ .nmodemuxs = ARRAY_SIZE(uart4_modemux),
+};
+
+static const char *const uart4_grps[] = { "uart4_grp" };
+static struct spear_function uart4_function = {
+ .name = "uart4",
+ .groups = uart4_grps,
+ .ngroups = ARRAY_SIZE(uart4_grps),
+};
+
+/* uart5_pins */
+static const unsigned uart5_pins[] = { 41, 42 };
+static struct spear_muxreg uart5_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux uart5_modemux[] = {
+ {
+ .muxregs = uart5_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart5_muxreg),
+ },
+};
+
+static struct spear_pingroup uart5_pingroup = {
+ .name = "uart5_grp",
+ .pins = uart5_pins,
+ .npins = ARRAY_SIZE(uart5_pins),
+ .modemuxs = uart5_modemux,
+ .nmodemuxs = ARRAY_SIZE(uart5_modemux),
+};
+
+static const char *const uart5_grps[] = { "uart5_grp" };
+static struct spear_function uart5_function = {
+ .name = "uart5",
+ .groups = uart5_grps,
+ .ngroups = ARRAY_SIZE(uart5_grps),
+};
+
+/* fsmc_pins */
+static const unsigned fsmc_pins[] = { 34, 35, 36 };
+static struct spear_muxreg fsmc_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_SSP_CS_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux fsmc_modemux[] = {
+ {
+ .muxregs = fsmc_muxreg,
+ .nmuxregs = ARRAY_SIZE(fsmc_muxreg),
+ },
+};
+
+static struct spear_pingroup fsmc_pingroup = {
+ .name = "fsmc_grp",
+ .pins = fsmc_pins,
+ .npins = ARRAY_SIZE(fsmc_pins),
+ .modemuxs = fsmc_modemux,
+ .nmodemuxs = ARRAY_SIZE(fsmc_modemux),
+};
+
+static const char *const fsmc_grps[] = { "fsmc_grp" };
+static struct spear_function fsmc_function = {
+ .name = "fsmc",
+ .groups = fsmc_grps,
+ .ngroups = ARRAY_SIZE(fsmc_grps),
+};
+
+/* rs485_0_pins */
+static const unsigned rs485_0_pins[] = { 19, 20, 21, 22, 23 };
+static struct spear_muxreg rs485_0_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux rs485_0_modemux[] = {
+ {
+ .muxregs = rs485_0_muxreg,
+ .nmuxregs = ARRAY_SIZE(rs485_0_muxreg),
+ },
+};
+
+static struct spear_pingroup rs485_0_pingroup = {
+ .name = "rs485_0_grp",
+ .pins = rs485_0_pins,
+ .npins = ARRAY_SIZE(rs485_0_pins),
+ .modemuxs = rs485_0_modemux,
+ .nmodemuxs = ARRAY_SIZE(rs485_0_modemux),
+};
+
+static const char *const rs485_0_grps[] = { "rs485_0" };
+static struct spear_function rs485_0_function = {
+ .name = "rs485_0",
+ .groups = rs485_0_grps,
+ .ngroups = ARRAY_SIZE(rs485_0_grps),
+};
+
+/* rs485_1_pins */
+static const unsigned rs485_1_pins[] = { 14, 15, 16, 17, 18 };
+static struct spear_muxreg rs485_1_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux rs485_1_modemux[] = {
+ {
+ .muxregs = rs485_1_muxreg,
+ .nmuxregs = ARRAY_SIZE(rs485_1_muxreg),
+ },
+};
+
+static struct spear_pingroup rs485_1_pingroup = {
+ .name = "rs485_1_grp",
+ .pins = rs485_1_pins,
+ .npins = ARRAY_SIZE(rs485_1_pins),
+ .modemuxs = rs485_1_modemux,
+ .nmodemuxs = ARRAY_SIZE(rs485_1_modemux),
+};
+
+static const char *const rs485_1_grps[] = { "rs485_1" };
+static struct spear_function rs485_1_function = {
+ .name = "rs485_1",
+ .groups = rs485_1_grps,
+ .ngroups = ARRAY_SIZE(rs485_1_grps),
+};
+
+/* tdm_pins */
+static const unsigned tdm_pins[] = { 10, 11, 12, 13 };
+static struct spear_muxreg tdm_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_modemux tdm_modemux[] = {
+ {
+ .muxregs = tdm_muxreg,
+ .nmuxregs = ARRAY_SIZE(tdm_muxreg),
+ },
+};
+
+static struct spear_pingroup tdm_pingroup = {
+ .name = "tdm_grp",
+ .pins = tdm_pins,
+ .npins = ARRAY_SIZE(tdm_pins),
+ .modemuxs = tdm_modemux,
+ .nmodemuxs = ARRAY_SIZE(tdm_modemux),
+};
+
+static const char *const tdm_grps[] = { "tdm_grp" };
+static struct spear_function tdm_function = {
+ .name = "tdm",
+ .groups = tdm_grps,
+ .ngroups = ARRAY_SIZE(tdm_grps),
+};
+
+/* pingroups */
+static struct spear_pingroup *spear310_pingroups[] = {
+ SPEAR3XX_COMMON_PINGROUPS,
+ &emi_cs_0_to_5_pingroup,
+ &uart1_pingroup,
+ &uart2_pingroup,
+ &uart3_pingroup,
+ &uart4_pingroup,
+ &uart5_pingroup,
+ &fsmc_pingroup,
+ &rs485_0_pingroup,
+ &rs485_1_pingroup,
+ &tdm_pingroup,
+};
+
+/* functions */
+static struct spear_function *spear310_functions[] = {
+ SPEAR3XX_COMMON_FUNCTIONS,
+ &emi_cs_0_to_5_function,
+ &uart1_function,
+ &uart2_function,
+ &uart3_function,
+ &uart4_function,
+ &uart5_function,
+ &fsmc_function,
+ &rs485_0_function,
+ &rs485_1_function,
+ &tdm_function,
+};
+
+static struct of_device_id spear310_pinctrl_of_match[] __devinitdata = {
+ {
+ .compatible = "st,spear310-pinmux",
+ },
+ {},
+};
+
+static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ spear3xx_machdata.groups = spear310_pingroups;
+ spear3xx_machdata.ngroups = ARRAY_SIZE(spear310_pingroups);
+ spear3xx_machdata.functions = spear310_functions;
+ spear3xx_machdata.nfunctions = ARRAY_SIZE(spear310_functions);
+
+ pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
+
+ spear3xx_machdata.modes_supported = false;
+
+ ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int __devexit spear310_pinctrl_remove(struct platform_device *pdev)
+{
+ return spear_pinctrl_remove(pdev);
+}
+
+static struct platform_driver spear310_pinctrl_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = spear310_pinctrl_of_match,
+ },
+ .probe = spear310_pinctrl_probe,
+ .remove = __devexit_p(spear310_pinctrl_remove),
+};
+
+static int __init spear310_pinctrl_init(void)
+{
+ return platform_driver_register(&spear310_pinctrl_driver);
+}
+arch_initcall(spear310_pinctrl_init);
+
+static void __exit spear310_pinctrl_exit(void)
+{
+ platform_driver_unregister(&spear310_pinctrl_driver);
+}
+module_exit(spear310_pinctrl_exit);
+
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
+MODULE_DESCRIPTION("ST Microelectronics SPEAr310 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, SPEAr310_pinctrl_of_match);
diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c
new file mode 100644
index 000000000000..de726e6c283a
--- /dev/null
+++ b/drivers/pinctrl/spear/pinctrl-spear320.c
@@ -0,0 +1,3468 @@
+/*
+ * Driver for the ST Microelectronics SPEAr320 pinmux
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "pinctrl-spear3xx.h"
+
+#define DRIVER_NAME "spear320-pinmux"
+
+/* addresses */
+#define PMX_CONFIG_REG 0x0C
+#define MODE_CONFIG_REG 0x10
+#define MODE_EXT_CONFIG_REG 0x18
+
+/* modes */
+#define AUTO_NET_SMII_MODE (1 << 0)
+#define AUTO_NET_MII_MODE (1 << 1)
+#define AUTO_EXP_MODE (1 << 2)
+#define SMALL_PRINTERS_MODE (1 << 3)
+#define EXTENDED_MODE (1 << 4)
+
+static struct spear_pmx_mode pmx_mode_auto_net_smii = {
+ .name = "Automation Networking SMII mode",
+ .mode = AUTO_NET_SMII_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x00000007,
+ .val = 0x0,
+};
+
+static struct spear_pmx_mode pmx_mode_auto_net_mii = {
+ .name = "Automation Networking MII mode",
+ .mode = AUTO_NET_MII_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x00000007,
+ .val = 0x1,
+};
+
+static struct spear_pmx_mode pmx_mode_auto_exp = {
+ .name = "Automation Expanded mode",
+ .mode = AUTO_EXP_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x00000007,
+ .val = 0x2,
+};
+
+static struct spear_pmx_mode pmx_mode_small_printers = {
+ .name = "Small Printers mode",
+ .mode = SMALL_PRINTERS_MODE,
+ .reg = MODE_CONFIG_REG,
+ .mask = 0x00000007,
+ .val = 0x3,
+};
+
+static struct spear_pmx_mode pmx_mode_extended = {
+ .name = "extended mode",
+ .mode = EXTENDED_MODE,
+ .reg = MODE_EXT_CONFIG_REG,
+ .mask = 0x00000001,
+ .val = 0x1,
+};
+
+static struct spear_pmx_mode *spear320_pmx_modes[] = {
+ &pmx_mode_auto_net_smii,
+ &pmx_mode_auto_net_mii,
+ &pmx_mode_auto_exp,
+ &pmx_mode_small_printers,
+ &pmx_mode_extended,
+};
+
+/* Extended mode registers and their offsets */
+#define EXT_CTRL_REG 0x0018
+ #define MII_MDIO_MASK (1 << 4)
+ #define MII_MDIO_10_11_VAL 0
+ #define MII_MDIO_81_VAL (1 << 4)
+ #define EMI_FSMC_DYNAMIC_MUX_MASK (1 << 5)
+ #define MAC_MODE_MII 0
+ #define MAC_MODE_RMII 1
+ #define MAC_MODE_SMII 2
+ #define MAC_MODE_SS_SMII 3
+ #define MAC_MODE_MASK 0x3
+ #define MAC1_MODE_SHIFT 16
+ #define MAC2_MODE_SHIFT 18
+
+#define IP_SEL_PAD_0_9_REG 0x00A4
+ #define PMX_PL_0_1_MASK (0x3F << 0)
+ #define PMX_UART2_PL_0_1_VAL 0x0
+ #define PMX_I2C2_PL_0_1_VAL (0x4 | (0x4 << 3))
+
+ #define PMX_PL_2_3_MASK (0x3F << 6)
+ #define PMX_I2C2_PL_2_3_VAL 0x0
+ #define PMX_UART6_PL_2_3_VAL ((0x1 << 6) | (0x1 << 9))
+ #define PMX_UART1_ENH_PL_2_3_VAL ((0x4 << 6) | (0x4 << 9))
+
+ #define PMX_PL_4_5_MASK (0x3F << 12)
+ #define PMX_UART5_PL_4_5_VAL ((0x1 << 12) | (0x1 << 15))
+ #define PMX_UART1_ENH_PL_4_5_VAL ((0x4 << 12) | (0x4 << 15))
+ #define PMX_PL_5_MASK (0x7 << 15)
+ #define PMX_TOUCH_Y_PL_5_VAL 0x0
+
+ #define PMX_PL_6_7_MASK (0x3F << 18)
+ #define PMX_PL_6_MASK (0x7 << 18)
+ #define PMX_PL_7_MASK (0x7 << 21)
+ #define PMX_UART4_PL_6_7_VAL ((0x1 << 18) | (0x1 << 21))
+ #define PMX_PWM_3_PL_6_VAL (0x2 << 18)
+ #define PMX_PWM_2_PL_7_VAL (0x2 << 21)
+ #define PMX_UART1_ENH_PL_6_7_VAL ((0x4 << 18) | (0x4 << 21))
+
+ #define PMX_PL_8_9_MASK (0x3F << 24)
+ #define PMX_UART3_PL_8_9_VAL ((0x1 << 24) | (0x1 << 27))
+ #define PMX_PWM_0_1_PL_8_9_VAL ((0x2 << 24) | (0x2 << 27))
+ #define PMX_I2C1_PL_8_9_VAL ((0x4 << 24) | (0x4 << 27))
+
+#define IP_SEL_PAD_10_19_REG 0x00A8
+ #define PMX_PL_10_11_MASK (0x3F << 0)
+ #define PMX_SMII_PL_10_11_VAL 0
+ #define PMX_RMII_PL_10_11_VAL ((0x4 << 0) | (0x4 << 3))
+
+ #define PMX_PL_12_MASK (0x7 << 6)
+ #define PMX_PWM3_PL_12_VAL 0
+ #define PMX_SDHCI_CD_PL_12_VAL (0x4 << 6)
+
+ #define PMX_PL_13_14_MASK (0x3F << 9)
+ #define PMX_PL_13_MASK (0x7 << 9)
+ #define PMX_PL_14_MASK (0x7 << 12)
+ #define PMX_SSP2_PL_13_14_15_16_VAL 0
+ #define PMX_UART4_PL_13_14_VAL ((0x1 << 9) | (0x1 << 12))
+ #define PMX_RMII_PL_13_14_VAL ((0x4 << 9) | (0x4 << 12))
+ #define PMX_PWM2_PL_13_VAL (0x2 << 9)
+ #define PMX_PWM1_PL_14_VAL (0x2 << 12)
+
+ #define PMX_PL_15_MASK (0x7 << 15)
+ #define PMX_PWM0_PL_15_VAL (0x2 << 15)
+ #define PMX_PL_15_16_MASK (0x3F << 15)
+ #define PMX_UART3_PL_15_16_VAL ((0x1 << 15) | (0x1 << 18))
+ #define PMX_RMII_PL_15_16_VAL ((0x4 << 15) | (0x4 << 18))
+
+ #define PMX_PL_17_18_MASK (0x3F << 21)
+ #define PMX_SSP1_PL_17_18_19_20_VAL 0
+ #define PMX_RMII_PL_17_18_VAL ((0x4 << 21) | (0x4 << 24))
+
+ #define PMX_PL_19_MASK (0x7 << 27)
+ #define PMX_I2C2_PL_19_VAL (0x1 << 27)
+ #define PMX_RMII_PL_19_VAL (0x4 << 27)
+
+#define IP_SEL_PAD_20_29_REG 0x00AC
+ #define PMX_PL_20_MASK (0x7 << 0)
+ #define PMX_I2C2_PL_20_VAL (0x1 << 0)
+ #define PMX_RMII_PL_20_VAL (0x4 << 0)
+
+ #define PMX_PL_21_TO_27_MASK (0x1FFFFF << 3)
+ #define PMX_SMII_PL_21_TO_27_VAL 0
+ #define PMX_RMII_PL_21_TO_27_VAL ((0x4 << 3) | (0x4 << 6) | (0x4 << 9) | (0x4 << 12) | (0x4 << 15) | (0x4 << 18) | (0x4 << 21))
+
+ #define PMX_PL_28_29_MASK (0x3F << 24)
+ #define PMX_PL_28_MASK (0x7 << 24)
+ #define PMX_PL_29_MASK (0x7 << 27)
+ #define PMX_UART1_PL_28_29_VAL 0
+ #define PMX_PWM_3_PL_28_VAL (0x4 << 24)
+ #define PMX_PWM_2_PL_29_VAL (0x4 << 27)
+
+#define IP_SEL_PAD_30_39_REG 0x00B0
+ #define PMX_PL_30_31_MASK (0x3F << 0)
+ #define PMX_CAN1_PL_30_31_VAL (0)
+ #define PMX_PL_30_MASK (0x7 << 0)
+ #define PMX_PL_31_MASK (0x7 << 3)
+ #define PMX_PWM1_EXT_PL_30_VAL (0x4 << 0)
+ #define PMX_PWM0_EXT_PL_31_VAL (0x4 << 3)
+ #define PMX_UART1_ENH_PL_31_VAL (0x3 << 3)
+
+ #define PMX_PL_32_33_MASK (0x3F << 6)
+ #define PMX_CAN0_PL_32_33_VAL 0
+ #define PMX_UART1_ENH_PL_32_33_VAL ((0x3 << 6) | (0x3 << 9))
+ #define PMX_SSP2_PL_32_33_VAL ((0x4 << 6) | (0x4 << 9))
+
+ #define PMX_PL_34_MASK (0x7 << 12)
+ #define PMX_PWM2_PL_34_VAL 0
+ #define PMX_UART1_ENH_PL_34_VAL (0x2 << 12)
+ #define PMX_SSP2_PL_34_VAL (0x4 << 12)
+
+ #define PMX_PL_35_MASK (0x7 << 15)
+ #define PMX_I2S_REF_CLK_PL_35_VAL 0
+ #define PMX_UART1_ENH_PL_35_VAL (0x2 << 15)
+ #define PMX_SSP2_PL_35_VAL (0x4 << 15)
+
+ #define PMX_PL_36_MASK (0x7 << 18)
+ #define PMX_TOUCH_X_PL_36_VAL 0
+ #define PMX_UART1_ENH_PL_36_VAL (0x2 << 18)
+ #define PMX_SSP1_PL_36_VAL (0x4 << 18)
+
+ #define PMX_PL_37_38_MASK (0x3F << 21)
+ #define PMX_PWM0_1_PL_37_38_VAL 0
+ #define PMX_UART5_PL_37_38_VAL ((0x2 << 21) | (0x2 << 24))
+ #define PMX_SSP1_PL_37_38_VAL ((0x4 << 21) | (0x4 << 24))
+
+ #define PMX_PL_39_MASK (0x7 << 27)
+ #define PMX_I2S_PL_39_VAL 0
+ #define PMX_UART4_PL_39_VAL (0x2 << 27)
+ #define PMX_SSP1_PL_39_VAL (0x4 << 27)
+
+#define IP_SEL_PAD_40_49_REG 0x00B4
+ #define PMX_PL_40_MASK (0x7 << 0)
+ #define PMX_I2S_PL_40_VAL 0
+ #define PMX_UART4_PL_40_VAL (0x2 << 0)
+ #define PMX_PWM3_PL_40_VAL (0x4 << 0)
+
+ #define PMX_PL_41_42_MASK (0x3F << 3)
+ #define PMX_PL_41_MASK (0x7 << 3)
+ #define PMX_PL_42_MASK (0x7 << 6)
+ #define PMX_I2S_PL_41_42_VAL 0
+ #define PMX_UART3_PL_41_42_VAL ((0x2 << 3) | (0x2 << 6))
+ #define PMX_PWM2_PL_41_VAL (0x4 << 3)
+ #define PMX_PWM1_PL_42_VAL (0x4 << 6)
+
+ #define PMX_PL_43_MASK (0x7 << 9)
+ #define PMX_SDHCI_PL_43_VAL 0
+ #define PMX_UART1_ENH_PL_43_VAL (0x2 << 9)
+ #define PMX_PWM0_PL_43_VAL (0x4 << 9)
+
+ #define PMX_PL_44_45_MASK (0x3F << 12)
+ #define PMX_SDHCI_PL_44_45_VAL 0
+ #define PMX_UART1_ENH_PL_44_45_VAL ((0x2 << 12) | (0x2 << 15))
+ #define PMX_SSP2_PL_44_45_VAL ((0x4 << 12) | (0x4 << 15))
+
+ #define PMX_PL_46_47_MASK (0x3F << 18)
+ #define PMX_SDHCI_PL_46_47_VAL 0
+ #define PMX_FSMC_EMI_PL_46_47_VAL ((0x2 << 18) | (0x2 << 21))
+ #define PMX_SSP2_PL_46_47_VAL ((0x4 << 18) | (0x4 << 21))
+
+ #define PMX_PL_48_49_MASK (0x3F << 24)
+ #define PMX_SDHCI_PL_48_49_VAL 0
+ #define PMX_FSMC_EMI_PL_48_49_VAL ((0x2 << 24) | (0x2 << 27))
+ #define PMX_SSP1_PL_48_49_VAL ((0x4 << 24) | (0x4 << 27))
+
+#define IP_SEL_PAD_50_59_REG 0x00B8
+ #define PMX_PL_50_51_MASK (0x3F << 0)
+ #define PMX_EMI_PL_50_51_VAL ((0x2 << 0) | (0x2 << 3))
+ #define PMX_SSP1_PL_50_51_VAL ((0x4 << 0) | (0x4 << 3))
+ #define PMX_PL_50_MASK (0x7 << 0)
+ #define PMX_PL_51_MASK (0x7 << 3)
+ #define PMX_SDHCI_PL_50_VAL 0
+ #define PMX_SDHCI_CD_PL_51_VAL 0
+
+ #define PMX_PL_52_53_MASK (0x3F << 6)
+ #define PMX_FSMC_PL_52_53_VAL 0
+ #define PMX_EMI_PL_52_53_VAL ((0x2 << 6) | (0x2 << 9))
+ #define PMX_UART3_PL_52_53_VAL ((0x4 << 6) | (0x4 << 9))
+
+ #define PMX_PL_54_55_56_MASK (0x1FF << 12)
+ #define PMX_FSMC_EMI_PL_54_55_56_VAL ((0x2 << 12) | (0x2 << 15) | (0x2 << 18))
+
+ #define PMX_PL_57_MASK (0x7 << 21)
+ #define PMX_FSMC_PL_57_VAL 0
+ #define PMX_PWM3_PL_57_VAL (0x4 << 21)
+
+ #define PMX_PL_58_59_MASK (0x3F << 24)
+ #define PMX_PL_58_MASK (0x7 << 24)
+ #define PMX_PL_59_MASK (0x7 << 27)
+ #define PMX_FSMC_EMI_PL_58_59_VAL ((0x2 << 24) | (0x2 << 27))
+ #define PMX_PWM2_PL_58_VAL (0x4 << 24)
+ #define PMX_PWM1_PL_59_VAL (0x4 << 27)
+
+#define IP_SEL_PAD_60_69_REG 0x00BC
+ #define PMX_PL_60_MASK (0x7 << 0)
+ #define PMX_FSMC_PL_60_VAL 0
+ #define PMX_PWM0_PL_60_VAL (0x4 << 0)
+
+ #define PMX_PL_61_TO_64_MASK (0xFFF << 3)
+ #define PMX_FSMC_PL_61_TO_64_VAL ((0x2 << 3) | (0x2 << 6) | (0x2 << 9) | (0x2 << 12))
+ #define PMX_SSP2_PL_61_TO_64_VAL ((0x4 << 3) | (0x4 << 6) | (0x4 << 9) | (0x4 << 12))
+
+ #define PMX_PL_65_TO_68_MASK (0xFFF << 15)
+ #define PMX_FSMC_PL_65_TO_68_VAL ((0x2 << 15) | (0x2 << 18) | (0x2 << 21) | (0x2 << 24))
+ #define PMX_SSP1_PL_65_TO_68_VAL ((0x4 << 15) | (0x4 << 18) | (0x4 << 21) | (0x4 << 24))
+
+ #define PMX_PL_69_MASK (0x7 << 27)
+ #define PMX_CLCD_PL_69_VAL (0)
+ #define PMX_EMI_PL_69_VAL (0x2 << 27)
+ #define PMX_SPP_PL_69_VAL (0x3 << 27)
+ #define PMX_UART5_PL_69_VAL (0x4 << 27)
+
+#define IP_SEL_PAD_70_79_REG 0x00C0
+ #define PMX_PL_70_MASK (0x7 << 0)
+ #define PMX_CLCD_PL_70_VAL (0)
+ #define PMX_FSMC_EMI_PL_70_VAL (0x2 << 0)
+ #define PMX_SPP_PL_70_VAL (0x3 << 0)
+ #define PMX_UART5_PL_70_VAL (0x4 << 0)
+
+ #define PMX_PL_71_72_MASK (0x3F << 3)
+ #define PMX_CLCD_PL_71_72_VAL (0)
+ #define PMX_FSMC_EMI_PL_71_72_VAL ((0x2 << 3) | (0x2 << 6))
+ #define PMX_SPP_PL_71_72_VAL ((0x3 << 3) | (0x3 << 6))
+ #define PMX_UART4_PL_71_72_VAL ((0x4 << 3) | (0x4 << 6))
+
+ #define PMX_PL_73_MASK (0x7 << 9)
+ #define PMX_CLCD_PL_73_VAL (0)
+ #define PMX_FSMC_EMI_PL_73_VAL (0x2 << 9)
+ #define PMX_SPP_PL_73_VAL (0x3 << 9)
+ #define PMX_UART3_PL_73_VAL (0x4 << 9)
+
+ #define PMX_PL_74_MASK (0x7 << 12)
+ #define PMX_CLCD_PL_74_VAL (0)
+ #define PMX_EMI_PL_74_VAL (0x2 << 12)
+ #define PMX_SPP_PL_74_VAL (0x3 << 12)
+ #define PMX_UART3_PL_74_VAL (0x4 << 12)
+
+ #define PMX_PL_75_76_MASK (0x3F << 15)
+ #define PMX_CLCD_PL_75_76_VAL (0)
+ #define PMX_EMI_PL_75_76_VAL ((0x2 << 15) | (0x2 << 18))
+ #define PMX_SPP_PL_75_76_VAL ((0x3 << 15) | (0x3 << 18))
+ #define PMX_I2C2_PL_75_76_VAL ((0x4 << 15) | (0x4 << 18))
+
+ #define PMX_PL_77_78_79_MASK (0x1FF << 21)
+ #define PMX_CLCD_PL_77_78_79_VAL (0)
+ #define PMX_EMI_PL_77_78_79_VAL ((0x2 << 21) | (0x2 << 24) | (0x2 << 27))
+ #define PMX_SPP_PL_77_78_79_VAL ((0x3 << 21) | (0x3 << 24) | (0x3 << 27))
+ #define PMX_RS485_PL_77_78_79_VAL ((0x4 << 21) | (0x4 << 24) | (0x4 << 27))
+
+#define IP_SEL_PAD_80_89_REG 0x00C4
+ #define PMX_PL_80_TO_85_MASK (0x3FFFF << 0)
+ #define PMX_CLCD_PL_80_TO_85_VAL 0
+ #define PMX_MII2_PL_80_TO_85_VAL ((0x1 << 0) | (0x1 << 3) | (0x1 << 6) | (0x1 << 9) | (0x1 << 12) | (0x1 << 15))
+ #define PMX_EMI_PL_80_TO_85_VAL ((0x2 << 0) | (0x2 << 3) | (0x2 << 6) | (0x2 << 9) | (0x2 << 12) | (0x2 << 15))
+ #define PMX_SPP_PL_80_TO_85_VAL ((0x3 << 0) | (0x3 << 3) | (0x3 << 6) | (0x3 << 9) | (0x3 << 12) | (0x3 << 15))
+ #define PMX_UART1_ENH_PL_80_TO_85_VAL ((0x4 << 0) | (0x4 << 3) | (0x4 << 6) | (0x4 << 9) | (0x4 << 12) | (0x4 << 15))
+
+ #define PMX_PL_86_87_MASK (0x3F << 18)
+ #define PMX_PL_86_MASK (0x7 << 18)
+ #define PMX_PL_87_MASK (0x7 << 21)
+ #define PMX_CLCD_PL_86_87_VAL 0
+ #define PMX_MII2_PL_86_87_VAL ((0x1 << 18) | (0x1 << 21))
+ #define PMX_EMI_PL_86_87_VAL ((0x2 << 18) | (0x2 << 21))
+ #define PMX_PWM3_PL_86_VAL (0x4 << 18)
+ #define PMX_PWM2_PL_87_VAL (0x4 << 21)
+
+ #define PMX_PL_88_89_MASK (0x3F << 24)
+ #define PMX_CLCD_PL_88_89_VAL 0
+ #define PMX_MII2_PL_88_89_VAL ((0x1 << 24) | (0x1 << 27))
+ #define PMX_EMI_PL_88_89_VAL ((0x2 << 24) | (0x2 << 27))
+ #define PMX_UART6_PL_88_89_VAL ((0x3 << 24) | (0x3 << 27))
+ #define PMX_PWM0_1_PL_88_89_VAL ((0x4 << 24) | (0x4 << 27))
+
+#define IP_SEL_PAD_90_99_REG 0x00C8
+ #define PMX_PL_90_91_MASK (0x3F << 0)
+ #define PMX_CLCD_PL_90_91_VAL 0
+ #define PMX_MII2_PL_90_91_VAL ((0x1 << 0) | (0x1 << 3))
+ #define PMX_EMI1_PL_90_91_VAL ((0x2 << 0) | (0x2 << 3))
+ #define PMX_UART5_PL_90_91_VAL ((0x3 << 0) | (0x3 << 3))
+ #define PMX_SSP2_PL_90_91_VAL ((0x4 << 0) | (0x4 << 3))
+
+ #define PMX_PL_92_93_MASK (0x3F << 6)
+ #define PMX_CLCD_PL_92_93_VAL 0
+ #define PMX_MII2_PL_92_93_VAL ((0x1 << 6) | (0x1 << 9))
+ #define PMX_EMI1_PL_92_93_VAL ((0x2 << 6) | (0x2 << 9))
+ #define PMX_UART4_PL_92_93_VAL ((0x3 << 6) | (0x3 << 9))
+ #define PMX_SSP2_PL_92_93_VAL ((0x4 << 6) | (0x4 << 9))
+
+ #define PMX_PL_94_95_MASK (0x3F << 12)
+ #define PMX_CLCD_PL_94_95_VAL 0
+ #define PMX_MII2_PL_94_95_VAL ((0x1 << 12) | (0x1 << 15))
+ #define PMX_EMI1_PL_94_95_VAL ((0x2 << 12) | (0x2 << 15))
+ #define PMX_UART3_PL_94_95_VAL ((0x3 << 12) | (0x3 << 15))
+ #define PMX_SSP1_PL_94_95_VAL ((0x4 << 12) | (0x4 << 15))
+
+ #define PMX_PL_96_97_MASK (0x3F << 18)
+ #define PMX_CLCD_PL_96_97_VAL 0
+ #define PMX_MII2_PL_96_97_VAL ((0x1 << 18) | (0x1 << 21))
+ #define PMX_EMI1_PL_96_97_VAL ((0x2 << 18) | (0x2 << 21))
+ #define PMX_I2C2_PL_96_97_VAL ((0x3 << 18) | (0x3 << 21))
+ #define PMX_SSP1_PL_96_97_VAL ((0x4 << 18) | (0x4 << 21))
+
+ #define PMX_PL_98_MASK (0x7 << 24)
+ #define PMX_CLCD_PL_98_VAL 0
+ #define PMX_I2C1_PL_98_VAL (0x2 << 24)
+ #define PMX_UART3_PL_98_VAL (0x4 << 24)
+
+ #define PMX_PL_99_MASK (0x7 << 27)
+ #define PMX_SDHCI_PL_99_VAL 0
+ #define PMX_I2C1_PL_99_VAL (0x2 << 27)
+ #define PMX_UART3_PL_99_VAL (0x4 << 27)
+
+#define IP_SEL_MIX_PAD_REG 0x00CC
+ #define PMX_PL_100_101_MASK (0x3F << 0)
+ #define PMX_SDHCI_PL_100_101_VAL 0
+ #define PMX_UART4_PL_100_101_VAL ((0x4 << 0) | (0x4 << 3))
+
+ #define PMX_SSP1_PORT_SEL_MASK (0x7 << 8)
+ #define PMX_SSP1_PORT_94_TO_97_VAL 0
+ #define PMX_SSP1_PORT_65_TO_68_VAL (0x1 << 8)
+ #define PMX_SSP1_PORT_48_TO_51_VAL (0x2 << 8)
+ #define PMX_SSP1_PORT_36_TO_39_VAL (0x3 << 8)
+ #define PMX_SSP1_PORT_17_TO_20_VAL (0x4 << 8)
+
+ #define PMX_SSP2_PORT_SEL_MASK (0x7 << 11)
+ #define PMX_SSP2_PORT_90_TO_93_VAL 0
+ #define PMX_SSP2_PORT_61_TO_64_VAL (0x1 << 11)
+ #define PMX_SSP2_PORT_44_TO_47_VAL (0x2 << 11)
+ #define PMX_SSP2_PORT_32_TO_35_VAL (0x3 << 11)
+ #define PMX_SSP2_PORT_13_TO_16_VAL (0x4 << 11)
+
+ #define PMX_UART1_ENH_PORT_SEL_MASK (0x3 << 14)
+ #define PMX_UART1_ENH_PORT_81_TO_85_VAL 0
+ #define PMX_UART1_ENH_PORT_44_45_34_36_VAL (0x1 << 14)
+ #define PMX_UART1_ENH_PORT_32_TO_34_36_VAL (0x2 << 14)
+ #define PMX_UART1_ENH_PORT_3_TO_5_7_VAL (0x3 << 14)
+
+ #define PMX_UART3_PORT_SEL_MASK (0x7 << 16)
+ #define PMX_UART3_PORT_94_VAL 0
+ #define PMX_UART3_PORT_73_VAL (0x1 << 16)
+ #define PMX_UART3_PORT_52_VAL (0x2 << 16)
+ #define PMX_UART3_PORT_41_VAL (0x3 << 16)
+ #define PMX_UART3_PORT_15_VAL (0x4 << 16)
+ #define PMX_UART3_PORT_8_VAL (0x5 << 16)
+ #define PMX_UART3_PORT_99_VAL (0x6 << 16)
+
+ #define PMX_UART4_PORT_SEL_MASK (0x7 << 19)
+ #define PMX_UART4_PORT_92_VAL 0
+ #define PMX_UART4_PORT_71_VAL (0x1 << 19)
+ #define PMX_UART4_PORT_39_VAL (0x2 << 19)
+ #define PMX_UART4_PORT_13_VAL (0x3 << 19)
+ #define PMX_UART4_PORT_6_VAL (0x4 << 19)
+ #define PMX_UART4_PORT_101_VAL (0x5 << 19)
+
+ #define PMX_UART5_PORT_SEL_MASK (0x3 << 22)
+ #define PMX_UART5_PORT_90_VAL 0
+ #define PMX_UART5_PORT_69_VAL (0x1 << 22)
+ #define PMX_UART5_PORT_37_VAL (0x2 << 22)
+ #define PMX_UART5_PORT_4_VAL (0x3 << 22)
+
+ #define PMX_UART6_PORT_SEL_MASK (0x1 << 24)
+ #define PMX_UART6_PORT_88_VAL 0
+ #define PMX_UART6_PORT_2_VAL (0x1 << 24)
+
+ #define PMX_I2C1_PORT_SEL_MASK (0x1 << 25)
+ #define PMX_I2C1_PORT_8_9_VAL 0
+ #define PMX_I2C1_PORT_98_99_VAL (0x1 << 25)
+
+ #define PMX_I2C2_PORT_SEL_MASK (0x3 << 26)
+ #define PMX_I2C2_PORT_96_97_VAL 0
+ #define PMX_I2C2_PORT_75_76_VAL (0x1 << 26)
+ #define PMX_I2C2_PORT_19_20_VAL (0x2 << 26)
+ #define PMX_I2C2_PORT_2_3_VAL (0x3 << 26)
+ #define PMX_I2C2_PORT_0_1_VAL (0x4 << 26)
+
+ #define PMX_SDHCI_CD_PORT_SEL_MASK (0x1 << 29)
+ #define PMX_SDHCI_CD_PORT_12_VAL 0
+ #define PMX_SDHCI_CD_PORT_51_VAL (0x1 << 29)
+
+/* Pad multiplexing for CLCD device */
+static const unsigned clcd_pins[] = { 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97 };
+static struct spear_muxreg clcd_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_60_69_REG,
+ .mask = PMX_PL_69_MASK,
+ .val = PMX_CLCD_PL_69_VAL,
+ }, {
+ .reg = IP_SEL_PAD_70_79_REG,
+ .mask = PMX_PL_70_MASK | PMX_PL_71_72_MASK | PMX_PL_73_MASK |
+ PMX_PL_74_MASK | PMX_PL_75_76_MASK |
+ PMX_PL_77_78_79_MASK,
+ .val = PMX_CLCD_PL_70_VAL | PMX_CLCD_PL_71_72_VAL |
+ PMX_CLCD_PL_73_VAL | PMX_CLCD_PL_74_VAL |
+ PMX_CLCD_PL_75_76_VAL | PMX_CLCD_PL_77_78_79_VAL,
+ }, {
+ .reg = IP_SEL_PAD_80_89_REG,
+ .mask = PMX_PL_80_TO_85_MASK | PMX_PL_86_87_MASK |
+ PMX_PL_88_89_MASK,
+ .val = PMX_CLCD_PL_80_TO_85_VAL | PMX_CLCD_PL_86_87_VAL |
+ PMX_CLCD_PL_88_89_VAL,
+ }, {
+ .reg = IP_SEL_PAD_90_99_REG,
+ .mask = PMX_PL_90_91_MASK | PMX_PL_92_93_MASK |
+ PMX_PL_94_95_MASK | PMX_PL_96_97_MASK | PMX_PL_98_MASK,
+ .val = PMX_CLCD_PL_90_91_VAL | PMX_CLCD_PL_92_93_VAL |
+ PMX_CLCD_PL_94_95_VAL | PMX_CLCD_PL_96_97_VAL |
+ PMX_CLCD_PL_98_VAL,
+ },
+};
+
+static struct spear_modemux clcd_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = clcd_muxreg,
+ .nmuxregs = ARRAY_SIZE(clcd_muxreg),
+ },
+};
+
+static struct spear_pingroup clcd_pingroup = {
+ .name = "clcd_grp",
+ .pins = clcd_pins,
+ .npins = ARRAY_SIZE(clcd_pins),
+ .modemuxs = clcd_modemux,
+ .nmodemuxs = ARRAY_SIZE(clcd_modemux),
+};
+
+static const char *const clcd_grps[] = { "clcd_grp" };
+static struct spear_function clcd_function = {
+ .name = "clcd",
+ .groups = clcd_grps,
+ .ngroups = ARRAY_SIZE(clcd_grps),
+};
+
+/* Pad multiplexing for EMI (Parallel NOR flash) device */
+static const unsigned emi_pins[] = { 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97 };
+static struct spear_muxreg emi_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg emi_ext_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_40_49_REG,
+ .mask = PMX_PL_46_47_MASK | PMX_PL_48_49_MASK,
+ .val = PMX_FSMC_EMI_PL_46_47_VAL | PMX_FSMC_EMI_PL_48_49_VAL,
+ }, {
+ .reg = IP_SEL_PAD_50_59_REG,
+ .mask = PMX_PL_50_51_MASK | PMX_PL_52_53_MASK |
+ PMX_PL_54_55_56_MASK | PMX_PL_58_59_MASK,
+ .val = PMX_EMI_PL_50_51_VAL | PMX_EMI_PL_52_53_VAL |
+ PMX_FSMC_EMI_PL_54_55_56_VAL |
+ PMX_FSMC_EMI_PL_58_59_VAL,
+ }, {
+ .reg = IP_SEL_PAD_60_69_REG,
+ .mask = PMX_PL_69_MASK,
+ .val = PMX_EMI_PL_69_VAL,
+ }, {
+ .reg = IP_SEL_PAD_70_79_REG,
+ .mask = PMX_PL_70_MASK | PMX_PL_71_72_MASK | PMX_PL_73_MASK |
+ PMX_PL_74_MASK | PMX_PL_75_76_MASK |
+ PMX_PL_77_78_79_MASK,
+ .val = PMX_FSMC_EMI_PL_70_VAL | PMX_FSMC_EMI_PL_71_72_VAL |
+ PMX_FSMC_EMI_PL_73_VAL | PMX_EMI_PL_74_VAL |
+ PMX_EMI_PL_75_76_VAL | PMX_EMI_PL_77_78_79_VAL,
+ }, {
+ .reg = IP_SEL_PAD_80_89_REG,
+ .mask = PMX_PL_80_TO_85_MASK | PMX_PL_86_87_MASK |
+ PMX_PL_88_89_MASK,
+ .val = PMX_EMI_PL_80_TO_85_VAL | PMX_EMI_PL_86_87_VAL |
+ PMX_EMI_PL_88_89_VAL,
+ }, {
+ .reg = IP_SEL_PAD_90_99_REG,
+ .mask = PMX_PL_90_91_MASK | PMX_PL_92_93_MASK |
+ PMX_PL_94_95_MASK | PMX_PL_96_97_MASK,
+ .val = PMX_EMI1_PL_90_91_VAL | PMX_EMI1_PL_92_93_VAL |
+ PMX_EMI1_PL_94_95_VAL | PMX_EMI1_PL_96_97_VAL,
+ }, {
+ .reg = EXT_CTRL_REG,
+ .mask = EMI_FSMC_DYNAMIC_MUX_MASK,
+ .val = EMI_FSMC_DYNAMIC_MUX_MASK,
+ },
+};
+
+static struct spear_modemux emi_modemux[] = {
+ {
+ .modes = AUTO_EXP_MODE | EXTENDED_MODE,
+ .muxregs = emi_muxreg,
+ .nmuxregs = ARRAY_SIZE(emi_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = emi_ext_muxreg,
+ .nmuxregs = ARRAY_SIZE(emi_ext_muxreg),
+ },
+};
+
+static struct spear_pingroup emi_pingroup = {
+ .name = "emi_grp",
+ .pins = emi_pins,
+ .npins = ARRAY_SIZE(emi_pins),
+ .modemuxs = emi_modemux,
+ .nmodemuxs = ARRAY_SIZE(emi_modemux),
+};
+
+static const char *const emi_grps[] = { "emi_grp" };
+static struct spear_function emi_function = {
+ .name = "emi",
+ .groups = emi_grps,
+ .ngroups = ARRAY_SIZE(emi_grps),
+};
+
+/* Pad multiplexing for FSMC (NAND flash) device */
+static const unsigned fsmc_8bit_pins[] = { 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68 };
+static struct spear_muxreg fsmc_8bit_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_50_59_REG,
+ .mask = PMX_PL_52_53_MASK | PMX_PL_54_55_56_MASK |
+ PMX_PL_57_MASK | PMX_PL_58_59_MASK,
+ .val = PMX_FSMC_PL_52_53_VAL | PMX_FSMC_EMI_PL_54_55_56_VAL |
+ PMX_FSMC_PL_57_VAL | PMX_FSMC_EMI_PL_58_59_VAL,
+ }, {
+ .reg = IP_SEL_PAD_60_69_REG,
+ .mask = PMX_PL_60_MASK | PMX_PL_61_TO_64_MASK |
+ PMX_PL_65_TO_68_MASK,
+ .val = PMX_FSMC_PL_60_VAL | PMX_FSMC_PL_61_TO_64_VAL |
+ PMX_FSMC_PL_65_TO_68_VAL,
+ }, {
+ .reg = EXT_CTRL_REG,
+ .mask = EMI_FSMC_DYNAMIC_MUX_MASK,
+ .val = EMI_FSMC_DYNAMIC_MUX_MASK,
+ },
+};
+
+static struct spear_modemux fsmc_8bit_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = fsmc_8bit_muxreg,
+ .nmuxregs = ARRAY_SIZE(fsmc_8bit_muxreg),
+ },
+};
+
+static struct spear_pingroup fsmc_8bit_pingroup = {
+ .name = "fsmc_8bit_grp",
+ .pins = fsmc_8bit_pins,
+ .npins = ARRAY_SIZE(fsmc_8bit_pins),
+ .modemuxs = fsmc_8bit_modemux,
+ .nmodemuxs = ARRAY_SIZE(fsmc_8bit_modemux),
+};
+
+static const unsigned fsmc_16bit_pins[] = { 46, 47, 48, 49, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 71, 72, 73 };
+static struct spear_muxreg fsmc_16bit_autoexp_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg fsmc_16bit_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_40_49_REG,
+ .mask = PMX_PL_46_47_MASK | PMX_PL_48_49_MASK,
+ .val = PMX_FSMC_EMI_PL_46_47_VAL | PMX_FSMC_EMI_PL_48_49_VAL,
+ }, {
+ .reg = IP_SEL_PAD_70_79_REG,
+ .mask = PMX_PL_70_MASK | PMX_PL_71_72_MASK | PMX_PL_73_MASK,
+ .val = PMX_FSMC_EMI_PL_70_VAL | PMX_FSMC_EMI_PL_71_72_VAL |
+ PMX_FSMC_EMI_PL_73_VAL,
+ }
+};
+
+static struct spear_modemux fsmc_16bit_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = fsmc_8bit_muxreg,
+ .nmuxregs = ARRAY_SIZE(fsmc_8bit_muxreg),
+ }, {
+ .modes = AUTO_EXP_MODE | EXTENDED_MODE,
+ .muxregs = fsmc_16bit_autoexp_muxreg,
+ .nmuxregs = ARRAY_SIZE(fsmc_16bit_autoexp_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = fsmc_16bit_muxreg,
+ .nmuxregs = ARRAY_SIZE(fsmc_16bit_muxreg),
+ },
+};
+
+static struct spear_pingroup fsmc_16bit_pingroup = {
+ .name = "fsmc_16bit_grp",
+ .pins = fsmc_16bit_pins,
+ .npins = ARRAY_SIZE(fsmc_16bit_pins),
+ .modemuxs = fsmc_16bit_modemux,
+ .nmodemuxs = ARRAY_SIZE(fsmc_16bit_modemux),
+};
+
+static const char *const fsmc_grps[] = { "fsmc_8bit_grp", "fsmc_16bit_grp" };
+static struct spear_function fsmc_function = {
+ .name = "fsmc",
+ .groups = fsmc_grps,
+ .ngroups = ARRAY_SIZE(fsmc_grps),
+};
+
+/* Pad multiplexing for SPP device */
+static const unsigned spp_pins[] = { 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85 };
+static struct spear_muxreg spp_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_60_69_REG,
+ .mask = PMX_PL_69_MASK,
+ .val = PMX_SPP_PL_69_VAL,
+ }, {
+ .reg = IP_SEL_PAD_70_79_REG,
+ .mask = PMX_PL_70_MASK | PMX_PL_71_72_MASK | PMX_PL_73_MASK |
+ PMX_PL_74_MASK | PMX_PL_75_76_MASK |
+ PMX_PL_77_78_79_MASK,
+ .val = PMX_SPP_PL_70_VAL | PMX_SPP_PL_71_72_VAL |
+ PMX_SPP_PL_73_VAL | PMX_SPP_PL_74_VAL |
+ PMX_SPP_PL_75_76_VAL | PMX_SPP_PL_77_78_79_VAL,
+ }, {
+ .reg = IP_SEL_PAD_80_89_REG,
+ .mask = PMX_PL_80_TO_85_MASK,
+ .val = PMX_SPP_PL_80_TO_85_VAL,
+ },
+};
+
+static struct spear_modemux spp_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = spp_muxreg,
+ .nmuxregs = ARRAY_SIZE(spp_muxreg),
+ },
+};
+
+static struct spear_pingroup spp_pingroup = {
+ .name = "spp_grp",
+ .pins = spp_pins,
+ .npins = ARRAY_SIZE(spp_pins),
+ .modemuxs = spp_modemux,
+ .nmodemuxs = ARRAY_SIZE(spp_modemux),
+};
+
+static const char *const spp_grps[] = { "spp_grp" };
+static struct spear_function spp_function = {
+ .name = "spp",
+ .groups = spp_grps,
+ .ngroups = ARRAY_SIZE(spp_grps),
+};
+
+/* Pad multiplexing for SDHCI device */
+static const unsigned sdhci_led_pins[] = { 34 };
+static struct spear_muxreg sdhci_led_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_SSP_CS_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg sdhci_led_ext_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_34_MASK,
+ .val = PMX_PWM2_PL_34_VAL,
+ },
+};
+
+static struct spear_modemux sdhci_led_modemux[] = {
+ {
+ .modes = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | EXTENDED_MODE,
+ .muxregs = sdhci_led_muxreg,
+ .nmuxregs = ARRAY_SIZE(sdhci_led_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = sdhci_led_ext_muxreg,
+ .nmuxregs = ARRAY_SIZE(sdhci_led_ext_muxreg),
+ },
+};
+
+static struct spear_pingroup sdhci_led_pingroup = {
+ .name = "sdhci_led_grp",
+ .pins = sdhci_led_pins,
+ .npins = ARRAY_SIZE(sdhci_led_pins),
+ .modemuxs = sdhci_led_modemux,
+ .nmodemuxs = ARRAY_SIZE(sdhci_led_modemux),
+};
+
+static const unsigned sdhci_cd_12_pins[] = { 12, 43, 44, 45, 46, 47, 48, 49,
+ 50};
+static const unsigned sdhci_cd_51_pins[] = { 43, 44, 45, 46, 47, 48, 49, 50, 51
+};
+static struct spear_muxreg sdhci_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg sdhci_ext_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_40_49_REG,
+ .mask = PMX_PL_43_MASK | PMX_PL_44_45_MASK | PMX_PL_46_47_MASK |
+ PMX_PL_48_49_MASK,
+ .val = PMX_SDHCI_PL_43_VAL | PMX_SDHCI_PL_44_45_VAL |
+ PMX_SDHCI_PL_46_47_VAL | PMX_SDHCI_PL_48_49_VAL,
+ }, {
+ .reg = IP_SEL_PAD_50_59_REG,
+ .mask = PMX_PL_50_MASK,
+ .val = PMX_SDHCI_PL_50_VAL,
+ }, {
+ .reg = IP_SEL_PAD_90_99_REG,
+ .mask = PMX_PL_99_MASK,
+ .val = PMX_SDHCI_PL_99_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_PL_100_101_MASK,
+ .val = PMX_SDHCI_PL_100_101_VAL,
+ },
+};
+
+static struct spear_muxreg sdhci_cd_12_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_10_19_REG,
+ .mask = PMX_PL_12_MASK,
+ .val = PMX_SDHCI_CD_PL_12_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_SDHCI_CD_PORT_SEL_MASK,
+ .val = PMX_SDHCI_CD_PORT_12_VAL,
+ },
+};
+
+static struct spear_muxreg sdhci_cd_51_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_50_59_REG,
+ .mask = PMX_PL_51_MASK,
+ .val = PMX_SDHCI_CD_PL_51_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_SDHCI_CD_PORT_SEL_MASK,
+ .val = PMX_SDHCI_CD_PORT_51_VAL,
+ },
+};
+
+#define pmx_sdhci_common_modemux \
+ { \
+ .modes = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | \
+ SMALL_PRINTERS_MODE | EXTENDED_MODE, \
+ .muxregs = sdhci_muxreg, \
+ .nmuxregs = ARRAY_SIZE(sdhci_muxreg), \
+ }, { \
+ .modes = EXTENDED_MODE, \
+ .muxregs = sdhci_ext_muxreg, \
+ .nmuxregs = ARRAY_SIZE(sdhci_ext_muxreg), \
+ }
+
+static struct spear_modemux sdhci_modemux[][3] = {
+ {
+ /* select pin 12 for cd */
+ pmx_sdhci_common_modemux,
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = sdhci_cd_12_muxreg,
+ .nmuxregs = ARRAY_SIZE(sdhci_cd_12_muxreg),
+ },
+ }, {
+ /* select pin 51 for cd */
+ pmx_sdhci_common_modemux,
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = sdhci_cd_51_muxreg,
+ .nmuxregs = ARRAY_SIZE(sdhci_cd_51_muxreg),
+ },
+ }
+};
+
+static struct spear_pingroup sdhci_pingroup[] = {
+ {
+ .name = "sdhci_cd_12_grp",
+ .pins = sdhci_cd_12_pins,
+ .npins = ARRAY_SIZE(sdhci_cd_12_pins),
+ .modemuxs = sdhci_modemux[0],
+ .nmodemuxs = ARRAY_SIZE(sdhci_modemux[0]),
+ }, {
+ .name = "sdhci_cd_51_grp",
+ .pins = sdhci_cd_51_pins,
+ .npins = ARRAY_SIZE(sdhci_cd_51_pins),
+ .modemuxs = sdhci_modemux[1],
+ .nmodemuxs = ARRAY_SIZE(sdhci_modemux[1]),
+ },
+};
+
+static const char *const sdhci_grps[] = { "sdhci_cd_12_grp", "sdhci_cd_51_grp",
+ "sdhci_led_grp" };
+
+static struct spear_function sdhci_function = {
+ .name = "sdhci",
+ .groups = sdhci_grps,
+ .ngroups = ARRAY_SIZE(sdhci_grps),
+};
+
+/* Pad multiplexing for I2S device */
+static const unsigned i2s_pins[] = { 35, 39, 40, 41, 42 };
+static struct spear_muxreg i2s_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_SSP_CS_MASK,
+ .val = 0,
+ }, {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg i2s_ext_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_35_MASK | PMX_PL_39_MASK,
+ .val = PMX_I2S_REF_CLK_PL_35_VAL | PMX_I2S_PL_39_VAL,
+ }, {
+ .reg = IP_SEL_PAD_40_49_REG,
+ .mask = PMX_PL_40_MASK | PMX_PL_41_42_MASK,
+ .val = PMX_I2S_PL_40_VAL | PMX_I2S_PL_41_42_VAL,
+ },
+};
+
+static struct spear_modemux i2s_modemux[] = {
+ {
+ .modes = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | EXTENDED_MODE,
+ .muxregs = i2s_muxreg,
+ .nmuxregs = ARRAY_SIZE(i2s_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = i2s_ext_muxreg,
+ .nmuxregs = ARRAY_SIZE(i2s_ext_muxreg),
+ },
+};
+
+static struct spear_pingroup i2s_pingroup = {
+ .name = "i2s_grp",
+ .pins = i2s_pins,
+ .npins = ARRAY_SIZE(i2s_pins),
+ .modemuxs = i2s_modemux,
+ .nmodemuxs = ARRAY_SIZE(i2s_modemux),
+};
+
+static const char *const i2s_grps[] = { "i2s_grp" };
+static struct spear_function i2s_function = {
+ .name = "i2s",
+ .groups = i2s_grps,
+ .ngroups = ARRAY_SIZE(i2s_grps),
+};
+
+/* Pad multiplexing for UART1 device */
+static const unsigned uart1_pins[] = { 28, 29 };
+static struct spear_muxreg uart1_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg uart1_ext_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_20_29_REG,
+ .mask = PMX_PL_28_29_MASK,
+ .val = PMX_UART1_PL_28_29_VAL,
+ },
+};
+
+static struct spear_modemux uart1_modemux[] = {
+ {
+ .modes = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | AUTO_EXP_MODE
+ | SMALL_PRINTERS_MODE | EXTENDED_MODE,
+ .muxregs = uart1_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart1_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart1_ext_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart1_ext_muxreg),
+ },
+};
+
+static struct spear_pingroup uart1_pingroup = {
+ .name = "uart1_grp",
+ .pins = uart1_pins,
+ .npins = ARRAY_SIZE(uart1_pins),
+ .modemuxs = uart1_modemux,
+ .nmodemuxs = ARRAY_SIZE(uart1_modemux),
+};
+
+static const char *const uart1_grps[] = { "uart1_grp" };
+static struct spear_function uart1_function = {
+ .name = "uart1",
+ .groups = uart1_grps,
+ .ngroups = ARRAY_SIZE(uart1_grps),
+};
+
+/* Pad multiplexing for UART1 Modem device */
+static const unsigned uart1_modem_2_to_7_pins[] = { 2, 3, 4, 5, 6, 7 };
+static const unsigned uart1_modem_31_to_36_pins[] = { 31, 32, 33, 34, 35, 36 };
+static const unsigned uart1_modem_34_to_45_pins[] = { 34, 35, 36, 43, 44, 45 };
+static const unsigned uart1_modem_80_to_85_pins[] = { 80, 81, 82, 83, 84, 85 };
+
+static struct spear_muxreg uart1_modem_ext_2_to_7_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MASK | PMX_I2C_MASK | PMX_SSP_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_0_9_REG,
+ .mask = PMX_PL_2_3_MASK | PMX_PL_6_7_MASK,
+ .val = PMX_UART1_ENH_PL_2_3_VAL | PMX_UART1_ENH_PL_4_5_VAL |
+ PMX_UART1_ENH_PL_6_7_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART1_ENH_PORT_SEL_MASK,
+ .val = PMX_UART1_ENH_PORT_3_TO_5_7_VAL,
+ },
+};
+
+static struct spear_muxreg uart1_modem_31_to_36_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_GPIO_PIN3_MASK | PMX_GPIO_PIN4_MASK |
+ PMX_GPIO_PIN5_MASK | PMX_SSP_CS_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg uart1_modem_ext_31_to_36_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_31_MASK | PMX_PL_32_33_MASK | PMX_PL_34_MASK |
+ PMX_PL_35_MASK | PMX_PL_36_MASK,
+ .val = PMX_UART1_ENH_PL_31_VAL | PMX_UART1_ENH_PL_32_33_VAL |
+ PMX_UART1_ENH_PL_34_VAL | PMX_UART1_ENH_PL_35_VAL |
+ PMX_UART1_ENH_PL_36_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART1_ENH_PORT_SEL_MASK,
+ .val = PMX_UART1_ENH_PORT_32_TO_34_36_VAL,
+ },
+};
+
+static struct spear_muxreg uart1_modem_34_to_45_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK |
+ PMX_SSP_CS_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg uart1_modem_ext_34_to_45_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_34_MASK | PMX_PL_35_MASK | PMX_PL_36_MASK,
+ .val = PMX_UART1_ENH_PL_34_VAL | PMX_UART1_ENH_PL_35_VAL |
+ PMX_UART1_ENH_PL_36_VAL,
+ }, {
+ .reg = IP_SEL_PAD_40_49_REG,
+ .mask = PMX_PL_43_MASK | PMX_PL_44_45_MASK,
+ .val = PMX_UART1_ENH_PL_43_VAL | PMX_UART1_ENH_PL_44_45_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART1_ENH_PORT_SEL_MASK,
+ .val = PMX_UART1_ENH_PORT_44_45_34_36_VAL,
+ },
+};
+
+static struct spear_muxreg uart1_modem_ext_80_to_85_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_80_89_REG,
+ .mask = PMX_PL_80_TO_85_MASK,
+ .val = PMX_UART1_ENH_PL_80_TO_85_VAL,
+ }, {
+ .reg = IP_SEL_PAD_40_49_REG,
+ .mask = PMX_PL_43_MASK | PMX_PL_44_45_MASK,
+ .val = PMX_UART1_ENH_PL_43_VAL | PMX_UART1_ENH_PL_44_45_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART1_ENH_PORT_SEL_MASK,
+ .val = PMX_UART1_ENH_PORT_81_TO_85_VAL,
+ },
+};
+
+static struct spear_modemux uart1_modem_2_to_7_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart1_modem_ext_2_to_7_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart1_modem_ext_2_to_7_muxreg),
+ },
+};
+
+static struct spear_modemux uart1_modem_31_to_36_modemux[] = {
+ {
+ .modes = SMALL_PRINTERS_MODE | EXTENDED_MODE,
+ .muxregs = uart1_modem_31_to_36_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart1_modem_31_to_36_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart1_modem_ext_31_to_36_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart1_modem_ext_31_to_36_muxreg),
+ },
+};
+
+static struct spear_modemux uart1_modem_34_to_45_modemux[] = {
+ {
+ .modes = AUTO_EXP_MODE | EXTENDED_MODE,
+ .muxregs = uart1_modem_34_to_45_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart1_modem_34_to_45_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart1_modem_ext_34_to_45_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart1_modem_ext_34_to_45_muxreg),
+ },
+};
+
+static struct spear_modemux uart1_modem_80_to_85_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart1_modem_ext_80_to_85_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart1_modem_ext_80_to_85_muxreg),
+ },
+};
+
+static struct spear_pingroup uart1_modem_pingroup[] = {
+ {
+ .name = "uart1_modem_2_to_7_grp",
+ .pins = uart1_modem_2_to_7_pins,
+ .npins = ARRAY_SIZE(uart1_modem_2_to_7_pins),
+ .modemuxs = uart1_modem_2_to_7_modemux,
+ .nmodemuxs = ARRAY_SIZE(uart1_modem_2_to_7_modemux),
+ }, {
+ .name = "uart1_modem_31_to_36_grp",
+ .pins = uart1_modem_31_to_36_pins,
+ .npins = ARRAY_SIZE(uart1_modem_31_to_36_pins),
+ .modemuxs = uart1_modem_31_to_36_modemux,
+ .nmodemuxs = ARRAY_SIZE(uart1_modem_31_to_36_modemux),
+ }, {
+ .name = "uart1_modem_34_to_45_grp",
+ .pins = uart1_modem_34_to_45_pins,
+ .npins = ARRAY_SIZE(uart1_modem_34_to_45_pins),
+ .modemuxs = uart1_modem_34_to_45_modemux,
+ .nmodemuxs = ARRAY_SIZE(uart1_modem_34_to_45_modemux),
+ }, {
+ .name = "uart1_modem_80_to_85_grp",
+ .pins = uart1_modem_80_to_85_pins,
+ .npins = ARRAY_SIZE(uart1_modem_80_to_85_pins),
+ .modemuxs = uart1_modem_80_to_85_modemux,
+ .nmodemuxs = ARRAY_SIZE(uart1_modem_80_to_85_modemux),
+ },
+};
+
+static const char *const uart1_modem_grps[] = { "uart1_modem_2_to_7_grp",
+ "uart1_modem_31_to_36_grp", "uart1_modem_34_to_45_grp",
+ "uart1_modem_80_to_85_grp" };
+static struct spear_function uart1_modem_function = {
+ .name = "uart1_modem",
+ .groups = uart1_modem_grps,
+ .ngroups = ARRAY_SIZE(uart1_modem_grps),
+};
+
+/* Pad multiplexing for UART2 device */
+static const unsigned uart2_pins[] = { 0, 1 };
+static struct spear_muxreg uart2_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_FIRDA_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg uart2_ext_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_0_9_REG,
+ .mask = PMX_PL_0_1_MASK,
+ .val = PMX_UART2_PL_0_1_VAL,
+ },
+};
+
+static struct spear_modemux uart2_modemux[] = {
+ {
+ .modes = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | AUTO_EXP_MODE
+ | SMALL_PRINTERS_MODE | EXTENDED_MODE,
+ .muxregs = uart2_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart2_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart2_ext_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart2_ext_muxreg),
+ },
+};
+
+static struct spear_pingroup uart2_pingroup = {
+ .name = "uart2_grp",
+ .pins = uart2_pins,
+ .npins = ARRAY_SIZE(uart2_pins),
+ .modemuxs = uart2_modemux,
+ .nmodemuxs = ARRAY_SIZE(uart2_modemux),
+};
+
+static const char *const uart2_grps[] = { "uart2_grp" };
+static struct spear_function uart2_function = {
+ .name = "uart2",
+ .groups = uart2_grps,
+ .ngroups = ARRAY_SIZE(uart2_grps),
+};
+
+/* Pad multiplexing for uart3 device */
+static const unsigned uart3_pins[][2] = { { 8, 9 }, { 15, 16 }, { 41, 42 },
+ { 52, 53 }, { 73, 74 }, { 94, 95 }, { 98, 99 } };
+
+static struct spear_muxreg uart3_ext_8_9_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_SSP_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_0_9_REG,
+ .mask = PMX_PL_8_9_MASK,
+ .val = PMX_UART3_PL_8_9_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART3_PORT_SEL_MASK,
+ .val = PMX_UART3_PORT_8_VAL,
+ },
+};
+
+static struct spear_muxreg uart3_ext_15_16_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_10_19_REG,
+ .mask = PMX_PL_15_16_MASK,
+ .val = PMX_UART3_PL_15_16_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART3_PORT_SEL_MASK,
+ .val = PMX_UART3_PORT_15_VAL,
+ },
+};
+
+static struct spear_muxreg uart3_ext_41_42_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_40_49_REG,
+ .mask = PMX_PL_41_42_MASK,
+ .val = PMX_UART3_PL_41_42_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART3_PORT_SEL_MASK,
+ .val = PMX_UART3_PORT_41_VAL,
+ },
+};
+
+static struct spear_muxreg uart3_ext_52_53_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_50_59_REG,
+ .mask = PMX_PL_52_53_MASK,
+ .val = PMX_UART3_PL_52_53_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART3_PORT_SEL_MASK,
+ .val = PMX_UART3_PORT_52_VAL,
+ },
+};
+
+static struct spear_muxreg uart3_ext_73_74_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_70_79_REG,
+ .mask = PMX_PL_73_MASK | PMX_PL_74_MASK,
+ .val = PMX_UART3_PL_73_VAL | PMX_UART3_PL_74_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART3_PORT_SEL_MASK,
+ .val = PMX_UART3_PORT_73_VAL,
+ },
+};
+
+static struct spear_muxreg uart3_ext_94_95_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_90_99_REG,
+ .mask = PMX_PL_94_95_MASK,
+ .val = PMX_UART3_PL_94_95_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART3_PORT_SEL_MASK,
+ .val = PMX_UART3_PORT_94_VAL,
+ },
+};
+
+static struct spear_muxreg uart3_ext_98_99_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_90_99_REG,
+ .mask = PMX_PL_98_MASK | PMX_PL_99_MASK,
+ .val = PMX_UART3_PL_98_VAL | PMX_UART3_PL_99_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART3_PORT_SEL_MASK,
+ .val = PMX_UART3_PORT_99_VAL,
+ },
+};
+
+static struct spear_modemux uart3_modemux[][1] = {
+ {
+ /* Select signals on pins 8_9 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart3_ext_8_9_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart3_ext_8_9_muxreg),
+ },
+ }, {
+ /* Select signals on pins 15_16 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart3_ext_15_16_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart3_ext_15_16_muxreg),
+ },
+ }, {
+ /* Select signals on pins 41_42 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart3_ext_41_42_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart3_ext_41_42_muxreg),
+ },
+ }, {
+ /* Select signals on pins 52_53 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart3_ext_52_53_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart3_ext_52_53_muxreg),
+ },
+ }, {
+ /* Select signals on pins 73_74 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart3_ext_73_74_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart3_ext_73_74_muxreg),
+ },
+ }, {
+ /* Select signals on pins 94_95 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart3_ext_94_95_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart3_ext_94_95_muxreg),
+ },
+ }, {
+ /* Select signals on pins 98_99 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart3_ext_98_99_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart3_ext_98_99_muxreg),
+ },
+ },
+};
+
+static struct spear_pingroup uart3_pingroup[] = {
+ {
+ .name = "uart3_8_9_grp",
+ .pins = uart3_pins[0],
+ .npins = ARRAY_SIZE(uart3_pins[0]),
+ .modemuxs = uart3_modemux[0],
+ .nmodemuxs = ARRAY_SIZE(uart3_modemux[0]),
+ }, {
+ .name = "uart3_15_16_grp",
+ .pins = uart3_pins[1],
+ .npins = ARRAY_SIZE(uart3_pins[1]),
+ .modemuxs = uart3_modemux[1],
+ .nmodemuxs = ARRAY_SIZE(uart3_modemux[1]),
+ }, {
+ .name = "uart3_41_42_grp",
+ .pins = uart3_pins[2],
+ .npins = ARRAY_SIZE(uart3_pins[2]),
+ .modemuxs = uart3_modemux[2],
+ .nmodemuxs = ARRAY_SIZE(uart3_modemux[2]),
+ }, {
+ .name = "uart3_52_53_grp",
+ .pins = uart3_pins[3],
+ .npins = ARRAY_SIZE(uart3_pins[3]),
+ .modemuxs = uart3_modemux[3],
+ .nmodemuxs = ARRAY_SIZE(uart3_modemux[3]),
+ }, {
+ .name = "uart3_73_74_grp",
+ .pins = uart3_pins[4],
+ .npins = ARRAY_SIZE(uart3_pins[4]),
+ .modemuxs = uart3_modemux[4],
+ .nmodemuxs = ARRAY_SIZE(uart3_modemux[4]),
+ }, {
+ .name = "uart3_94_95_grp",
+ .pins = uart3_pins[5],
+ .npins = ARRAY_SIZE(uart3_pins[5]),
+ .modemuxs = uart3_modemux[5],
+ .nmodemuxs = ARRAY_SIZE(uart3_modemux[5]),
+ }, {
+ .name = "uart3_98_99_grp",
+ .pins = uart3_pins[6],
+ .npins = ARRAY_SIZE(uart3_pins[6]),
+ .modemuxs = uart3_modemux[6],
+ .nmodemuxs = ARRAY_SIZE(uart3_modemux[6]),
+ },
+};
+
+static const char *const uart3_grps[] = { "uart3_8_9_grp", "uart3_15_16_grp",
+ "uart3_41_42_grp", "uart3_52_53_grp", "uart3_73_74_grp",
+ "uart3_94_95_grp", "uart3_98_99_grp" };
+
+static struct spear_function uart3_function = {
+ .name = "uart3",
+ .groups = uart3_grps,
+ .ngroups = ARRAY_SIZE(uart3_grps),
+};
+
+/* Pad multiplexing for uart4 device */
+static const unsigned uart4_pins[][2] = { { 6, 7 }, { 13, 14 }, { 39, 40 },
+ { 71, 72 }, { 92, 93 }, { 100, 101 } };
+
+static struct spear_muxreg uart4_ext_6_7_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_SSP_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_0_9_REG,
+ .mask = PMX_PL_6_7_MASK,
+ .val = PMX_UART4_PL_6_7_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART4_PORT_SEL_MASK,
+ .val = PMX_UART4_PORT_6_VAL,
+ },
+};
+
+static struct spear_muxreg uart4_ext_13_14_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_10_19_REG,
+ .mask = PMX_PL_13_14_MASK,
+ .val = PMX_UART4_PL_13_14_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART4_PORT_SEL_MASK,
+ .val = PMX_UART4_PORT_13_VAL,
+ },
+};
+
+static struct spear_muxreg uart4_ext_39_40_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_39_MASK,
+ .val = PMX_UART4_PL_39_VAL,
+ }, {
+ .reg = IP_SEL_PAD_40_49_REG,
+ .mask = PMX_PL_40_MASK,
+ .val = PMX_UART4_PL_40_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART4_PORT_SEL_MASK,
+ .val = PMX_UART4_PORT_39_VAL,
+ },
+};
+
+static struct spear_muxreg uart4_ext_71_72_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_70_79_REG,
+ .mask = PMX_PL_71_72_MASK,
+ .val = PMX_UART4_PL_71_72_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART4_PORT_SEL_MASK,
+ .val = PMX_UART4_PORT_71_VAL,
+ },
+};
+
+static struct spear_muxreg uart4_ext_92_93_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_90_99_REG,
+ .mask = PMX_PL_92_93_MASK,
+ .val = PMX_UART4_PL_92_93_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART4_PORT_SEL_MASK,
+ .val = PMX_UART4_PORT_92_VAL,
+ },
+};
+
+static struct spear_muxreg uart4_ext_100_101_muxreg[] = {
+ {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_PL_100_101_MASK |
+ PMX_UART4_PORT_SEL_MASK,
+ .val = PMX_UART4_PL_100_101_VAL |
+ PMX_UART4_PORT_101_VAL,
+ },
+};
+
+static struct spear_modemux uart4_modemux[][1] = {
+ {
+ /* Select signals on pins 6_7 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart4_ext_6_7_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart4_ext_6_7_muxreg),
+ },
+ }, {
+ /* Select signals on pins 13_14 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart4_ext_13_14_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart4_ext_13_14_muxreg),
+ },
+ }, {
+ /* Select signals on pins 39_40 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart4_ext_39_40_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart4_ext_39_40_muxreg),
+ },
+ }, {
+ /* Select signals on pins 71_72 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart4_ext_71_72_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart4_ext_71_72_muxreg),
+ },
+ }, {
+ /* Select signals on pins 92_93 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart4_ext_92_93_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart4_ext_92_93_muxreg),
+ },
+ }, {
+ /* Select signals on pins 100_101_ */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart4_ext_100_101_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart4_ext_100_101_muxreg),
+ },
+ },
+};
+
+static struct spear_pingroup uart4_pingroup[] = {
+ {
+ .name = "uart4_6_7_grp",
+ .pins = uart4_pins[0],
+ .npins = ARRAY_SIZE(uart4_pins[0]),
+ .modemuxs = uart4_modemux[0],
+ .nmodemuxs = ARRAY_SIZE(uart4_modemux[0]),
+ }, {
+ .name = "uart4_13_14_grp",
+ .pins = uart4_pins[1],
+ .npins = ARRAY_SIZE(uart4_pins[1]),
+ .modemuxs = uart4_modemux[1],
+ .nmodemuxs = ARRAY_SIZE(uart4_modemux[1]),
+ }, {
+ .name = "uart4_39_40_grp",
+ .pins = uart4_pins[2],
+ .npins = ARRAY_SIZE(uart4_pins[2]),
+ .modemuxs = uart4_modemux[2],
+ .nmodemuxs = ARRAY_SIZE(uart4_modemux[2]),
+ }, {
+ .name = "uart4_71_72_grp",
+ .pins = uart4_pins[3],
+ .npins = ARRAY_SIZE(uart4_pins[3]),
+ .modemuxs = uart4_modemux[3],
+ .nmodemuxs = ARRAY_SIZE(uart4_modemux[3]),
+ }, {
+ .name = "uart4_92_93_grp",
+ .pins = uart4_pins[4],
+ .npins = ARRAY_SIZE(uart4_pins[4]),
+ .modemuxs = uart4_modemux[4],
+ .nmodemuxs = ARRAY_SIZE(uart4_modemux[4]),
+ }, {
+ .name = "uart4_100_101_grp",
+ .pins = uart4_pins[5],
+ .npins = ARRAY_SIZE(uart4_pins[5]),
+ .modemuxs = uart4_modemux[5],
+ .nmodemuxs = ARRAY_SIZE(uart4_modemux[5]),
+ },
+};
+
+static const char *const uart4_grps[] = { "uart4_6_7_grp", "uart4_13_14_grp",
+ "uart4_39_40_grp", "uart4_71_72_grp", "uart4_92_93_grp",
+ "uart4_100_101_grp" };
+
+static struct spear_function uart4_function = {
+ .name = "uart4",
+ .groups = uart4_grps,
+ .ngroups = ARRAY_SIZE(uart4_grps),
+};
+
+/* Pad multiplexing for uart5 device */
+static const unsigned uart5_pins[][2] = { { 4, 5 }, { 37, 38 }, { 69, 70 },
+ { 90, 91 } };
+
+static struct spear_muxreg uart5_ext_4_5_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_I2C_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_0_9_REG,
+ .mask = PMX_PL_4_5_MASK,
+ .val = PMX_UART5_PL_4_5_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART5_PORT_SEL_MASK,
+ .val = PMX_UART5_PORT_4_VAL,
+ },
+};
+
+static struct spear_muxreg uart5_ext_37_38_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_37_38_MASK,
+ .val = PMX_UART5_PL_37_38_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART5_PORT_SEL_MASK,
+ .val = PMX_UART5_PORT_37_VAL,
+ },
+};
+
+static struct spear_muxreg uart5_ext_69_70_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_60_69_REG,
+ .mask = PMX_PL_69_MASK,
+ .val = PMX_UART5_PL_69_VAL,
+ }, {
+ .reg = IP_SEL_PAD_70_79_REG,
+ .mask = PMX_PL_70_MASK,
+ .val = PMX_UART5_PL_70_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART5_PORT_SEL_MASK,
+ .val = PMX_UART5_PORT_69_VAL,
+ },
+};
+
+static struct spear_muxreg uart5_ext_90_91_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_90_99_REG,
+ .mask = PMX_PL_90_91_MASK,
+ .val = PMX_UART5_PL_90_91_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART5_PORT_SEL_MASK,
+ .val = PMX_UART5_PORT_90_VAL,
+ },
+};
+
+static struct spear_modemux uart5_modemux[][1] = {
+ {
+ /* Select signals on pins 4_5 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart5_ext_4_5_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart5_ext_4_5_muxreg),
+ },
+ }, {
+ /* Select signals on pins 37_38 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart5_ext_37_38_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart5_ext_37_38_muxreg),
+ },
+ }, {
+ /* Select signals on pins 69_70 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart5_ext_69_70_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart5_ext_69_70_muxreg),
+ },
+ }, {
+ /* Select signals on pins 90_91 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart5_ext_90_91_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart5_ext_90_91_muxreg),
+ },
+ },
+};
+
+static struct spear_pingroup uart5_pingroup[] = {
+ {
+ .name = "uart5_4_5_grp",
+ .pins = uart5_pins[0],
+ .npins = ARRAY_SIZE(uart5_pins[0]),
+ .modemuxs = uart5_modemux[0],
+ .nmodemuxs = ARRAY_SIZE(uart5_modemux[0]),
+ }, {
+ .name = "uart5_37_38_grp",
+ .pins = uart5_pins[1],
+ .npins = ARRAY_SIZE(uart5_pins[1]),
+ .modemuxs = uart5_modemux[1],
+ .nmodemuxs = ARRAY_SIZE(uart5_modemux[1]),
+ }, {
+ .name = "uart5_69_70_grp",
+ .pins = uart5_pins[2],
+ .npins = ARRAY_SIZE(uart5_pins[2]),
+ .modemuxs = uart5_modemux[2],
+ .nmodemuxs = ARRAY_SIZE(uart5_modemux[2]),
+ }, {
+ .name = "uart5_90_91_grp",
+ .pins = uart5_pins[3],
+ .npins = ARRAY_SIZE(uart5_pins[3]),
+ .modemuxs = uart5_modemux[3],
+ .nmodemuxs = ARRAY_SIZE(uart5_modemux[3]),
+ },
+};
+
+static const char *const uart5_grps[] = { "uart5_4_5_grp", "uart5_37_38_grp",
+ "uart5_69_70_grp", "uart5_90_91_grp" };
+static struct spear_function uart5_function = {
+ .name = "uart5",
+ .groups = uart5_grps,
+ .ngroups = ARRAY_SIZE(uart5_grps),
+};
+
+/* Pad multiplexing for uart6 device */
+static const unsigned uart6_pins[][2] = { { 2, 3 }, { 88, 89 } };
+static struct spear_muxreg uart6_ext_2_3_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_0_9_REG,
+ .mask = PMX_PL_2_3_MASK,
+ .val = PMX_UART6_PL_2_3_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART6_PORT_SEL_MASK,
+ .val = PMX_UART6_PORT_2_VAL,
+ },
+};
+
+static struct spear_muxreg uart6_ext_88_89_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_80_89_REG,
+ .mask = PMX_PL_88_89_MASK,
+ .val = PMX_UART6_PL_88_89_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_UART6_PORT_SEL_MASK,
+ .val = PMX_UART6_PORT_88_VAL,
+ },
+};
+
+static struct spear_modemux uart6_modemux[][1] = {
+ {
+ /* Select signals on pins 2_3 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart6_ext_2_3_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart6_ext_2_3_muxreg),
+ },
+ }, {
+ /* Select signals on pins 88_89 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = uart6_ext_88_89_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart6_ext_88_89_muxreg),
+ },
+ },
+};
+
+static struct spear_pingroup uart6_pingroup[] = {
+ {
+ .name = "uart6_2_3_grp",
+ .pins = uart6_pins[0],
+ .npins = ARRAY_SIZE(uart6_pins[0]),
+ .modemuxs = uart6_modemux[0],
+ .nmodemuxs = ARRAY_SIZE(uart6_modemux[0]),
+ }, {
+ .name = "uart6_88_89_grp",
+ .pins = uart6_pins[1],
+ .npins = ARRAY_SIZE(uart6_pins[1]),
+ .modemuxs = uart6_modemux[1],
+ .nmodemuxs = ARRAY_SIZE(uart6_modemux[1]),
+ },
+};
+
+static const char *const uart6_grps[] = { "uart6_2_3_grp", "uart6_88_89_grp" };
+static struct spear_function uart6_function = {
+ .name = "uart6",
+ .groups = uart6_grps,
+ .ngroups = ARRAY_SIZE(uart6_grps),
+};
+
+/* UART - RS485 pmx */
+static const unsigned rs485_pins[] = { 77, 78, 79 };
+static struct spear_muxreg rs485_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_70_79_REG,
+ .mask = PMX_PL_77_78_79_MASK,
+ .val = PMX_RS485_PL_77_78_79_VAL,
+ },
+};
+
+static struct spear_modemux rs485_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = rs485_muxreg,
+ .nmuxregs = ARRAY_SIZE(rs485_muxreg),
+ },
+};
+
+static struct spear_pingroup rs485_pingroup = {
+ .name = "rs485_grp",
+ .pins = rs485_pins,
+ .npins = ARRAY_SIZE(rs485_pins),
+ .modemuxs = rs485_modemux,
+ .nmodemuxs = ARRAY_SIZE(rs485_modemux),
+};
+
+static const char *const rs485_grps[] = { "rs485_grp" };
+static struct spear_function rs485_function = {
+ .name = "rs485",
+ .groups = rs485_grps,
+ .ngroups = ARRAY_SIZE(rs485_grps),
+};
+
+/* Pad multiplexing for Touchscreen device */
+static const unsigned touchscreen_pins[] = { 5, 36 };
+static struct spear_muxreg touchscreen_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_I2C_MASK | PMX_SSP_CS_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg touchscreen_ext_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_0_9_REG,
+ .mask = PMX_PL_5_MASK,
+ .val = PMX_TOUCH_Y_PL_5_VAL,
+ }, {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_36_MASK,
+ .val = PMX_TOUCH_X_PL_36_VAL,
+ },
+};
+
+static struct spear_modemux touchscreen_modemux[] = {
+ {
+ .modes = AUTO_NET_SMII_MODE | EXTENDED_MODE,
+ .muxregs = touchscreen_muxreg,
+ .nmuxregs = ARRAY_SIZE(touchscreen_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = touchscreen_ext_muxreg,
+ .nmuxregs = ARRAY_SIZE(touchscreen_ext_muxreg),
+ },
+};
+
+static struct spear_pingroup touchscreen_pingroup = {
+ .name = "touchscreen_grp",
+ .pins = touchscreen_pins,
+ .npins = ARRAY_SIZE(touchscreen_pins),
+ .modemuxs = touchscreen_modemux,
+ .nmodemuxs = ARRAY_SIZE(touchscreen_modemux),
+};
+
+static const char *const touchscreen_grps[] = { "touchscreen_grp" };
+static struct spear_function touchscreen_function = {
+ .name = "touchscreen",
+ .groups = touchscreen_grps,
+ .ngroups = ARRAY_SIZE(touchscreen_grps),
+};
+
+/* Pad multiplexing for CAN device */
+static const unsigned can0_pins[] = { 32, 33 };
+static struct spear_muxreg can0_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg can0_ext_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_32_33_MASK,
+ .val = PMX_CAN0_PL_32_33_VAL,
+ },
+};
+
+static struct spear_modemux can0_modemux[] = {
+ {
+ .modes = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | AUTO_EXP_MODE
+ | EXTENDED_MODE,
+ .muxregs = can0_muxreg,
+ .nmuxregs = ARRAY_SIZE(can0_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = can0_ext_muxreg,
+ .nmuxregs = ARRAY_SIZE(can0_ext_muxreg),
+ },
+};
+
+static struct spear_pingroup can0_pingroup = {
+ .name = "can0_grp",
+ .pins = can0_pins,
+ .npins = ARRAY_SIZE(can0_pins),
+ .modemuxs = can0_modemux,
+ .nmodemuxs = ARRAY_SIZE(can0_modemux),
+};
+
+static const char *const can0_grps[] = { "can0_grp" };
+static struct spear_function can0_function = {
+ .name = "can0",
+ .groups = can0_grps,
+ .ngroups = ARRAY_SIZE(can0_grps),
+};
+
+static const unsigned can1_pins[] = { 30, 31 };
+static struct spear_muxreg can1_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg can1_ext_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_30_31_MASK,
+ .val = PMX_CAN1_PL_30_31_VAL,
+ },
+};
+
+static struct spear_modemux can1_modemux[] = {
+ {
+ .modes = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | AUTO_EXP_MODE
+ | EXTENDED_MODE,
+ .muxregs = can1_muxreg,
+ .nmuxregs = ARRAY_SIZE(can1_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = can1_ext_muxreg,
+ .nmuxregs = ARRAY_SIZE(can1_ext_muxreg),
+ },
+};
+
+static struct spear_pingroup can1_pingroup = {
+ .name = "can1_grp",
+ .pins = can1_pins,
+ .npins = ARRAY_SIZE(can1_pins),
+ .modemuxs = can1_modemux,
+ .nmodemuxs = ARRAY_SIZE(can1_modemux),
+};
+
+static const char *const can1_grps[] = { "can1_grp" };
+static struct spear_function can1_function = {
+ .name = "can1",
+ .groups = can1_grps,
+ .ngroups = ARRAY_SIZE(can1_grps),
+};
+
+/* Pad multiplexing for PWM0_1 device */
+static const unsigned pwm0_1_pins[][2] = { { 37, 38 }, { 14, 15 }, { 8, 9 },
+ { 30, 31 }, { 42, 43 }, { 59, 60 }, { 88, 89 } };
+
+static struct spear_muxreg pwm0_1_pin_8_9_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_SSP_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_0_9_REG,
+ .mask = PMX_PL_8_9_MASK,
+ .val = PMX_PWM_0_1_PL_8_9_VAL,
+ },
+};
+
+static struct spear_muxreg pwm0_1_autoexpsmallpri_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg pwm0_1_pin_14_15_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_10_19_REG,
+ .mask = PMX_PL_14_MASK | PMX_PL_15_MASK,
+ .val = PMX_PWM1_PL_14_VAL | PMX_PWM0_PL_15_VAL,
+ },
+};
+
+static struct spear_muxreg pwm0_1_pin_30_31_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_30_MASK | PMX_PL_31_MASK,
+ .val = PMX_PWM1_EXT_PL_30_VAL | PMX_PWM0_EXT_PL_31_VAL,
+ },
+};
+
+static struct spear_muxreg pwm0_1_net_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg pwm0_1_pin_37_38_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_37_38_MASK,
+ .val = PMX_PWM0_1_PL_37_38_VAL,
+ },
+};
+
+static struct spear_muxreg pwm0_1_pin_42_43_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK | PMX_TIMER_0_1_MASK ,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_40_49_REG,
+ .mask = PMX_PL_42_MASK | PMX_PL_43_MASK,
+ .val = PMX_PWM1_PL_42_VAL |
+ PMX_PWM0_PL_43_VAL,
+ },
+};
+
+static struct spear_muxreg pwm0_1_pin_59_60_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_50_59_REG,
+ .mask = PMX_PL_59_MASK,
+ .val = PMX_PWM1_PL_59_VAL,
+ }, {
+ .reg = IP_SEL_PAD_60_69_REG,
+ .mask = PMX_PL_60_MASK,
+ .val = PMX_PWM0_PL_60_VAL,
+ },
+};
+
+static struct spear_muxreg pwm0_1_pin_88_89_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_80_89_REG,
+ .mask = PMX_PL_88_89_MASK,
+ .val = PMX_PWM0_1_PL_88_89_VAL,
+ },
+};
+
+static struct spear_modemux pwm0_1_pin_8_9_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm0_1_pin_8_9_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm0_1_pin_8_9_muxreg),
+ },
+};
+
+static struct spear_modemux pwm0_1_pin_14_15_modemux[] = {
+ {
+ .modes = AUTO_EXP_MODE | SMALL_PRINTERS_MODE | EXTENDED_MODE,
+ .muxregs = pwm0_1_autoexpsmallpri_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm0_1_autoexpsmallpri_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm0_1_pin_14_15_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm0_1_pin_14_15_muxreg),
+ },
+};
+
+static struct spear_modemux pwm0_1_pin_30_31_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm0_1_pin_30_31_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm0_1_pin_30_31_muxreg),
+ },
+};
+
+static struct spear_modemux pwm0_1_pin_37_38_modemux[] = {
+ {
+ .modes = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | EXTENDED_MODE,
+ .muxregs = pwm0_1_net_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm0_1_net_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm0_1_pin_37_38_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm0_1_pin_37_38_muxreg),
+ },
+};
+
+static struct spear_modemux pwm0_1_pin_42_43_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm0_1_pin_42_43_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm0_1_pin_42_43_muxreg),
+ },
+};
+
+static struct spear_modemux pwm0_1_pin_59_60_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm0_1_pin_59_60_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm0_1_pin_59_60_muxreg),
+ },
+};
+
+static struct spear_modemux pwm0_1_pin_88_89_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm0_1_pin_88_89_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm0_1_pin_88_89_muxreg),
+ },
+};
+
+static struct spear_pingroup pwm0_1_pingroup[] = {
+ {
+ .name = "pwm0_1_pin_8_9_grp",
+ .pins = pwm0_1_pins[0],
+ .npins = ARRAY_SIZE(pwm0_1_pins[0]),
+ .modemuxs = pwm0_1_pin_8_9_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm0_1_pin_8_9_modemux),
+ }, {
+ .name = "pwm0_1_pin_14_15_grp",
+ .pins = pwm0_1_pins[1],
+ .npins = ARRAY_SIZE(pwm0_1_pins[1]),
+ .modemuxs = pwm0_1_pin_14_15_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm0_1_pin_14_15_modemux),
+ }, {
+ .name = "pwm0_1_pin_30_31_grp",
+ .pins = pwm0_1_pins[2],
+ .npins = ARRAY_SIZE(pwm0_1_pins[2]),
+ .modemuxs = pwm0_1_pin_30_31_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm0_1_pin_30_31_modemux),
+ }, {
+ .name = "pwm0_1_pin_37_38_grp",
+ .pins = pwm0_1_pins[3],
+ .npins = ARRAY_SIZE(pwm0_1_pins[3]),
+ .modemuxs = pwm0_1_pin_37_38_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm0_1_pin_37_38_modemux),
+ }, {
+ .name = "pwm0_1_pin_42_43_grp",
+ .pins = pwm0_1_pins[4],
+ .npins = ARRAY_SIZE(pwm0_1_pins[4]),
+ .modemuxs = pwm0_1_pin_42_43_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm0_1_pin_42_43_modemux),
+ }, {
+ .name = "pwm0_1_pin_59_60_grp",
+ .pins = pwm0_1_pins[5],
+ .npins = ARRAY_SIZE(pwm0_1_pins[5]),
+ .modemuxs = pwm0_1_pin_59_60_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm0_1_pin_59_60_modemux),
+ }, {
+ .name = "pwm0_1_pin_88_89_grp",
+ .pins = pwm0_1_pins[6],
+ .npins = ARRAY_SIZE(pwm0_1_pins[6]),
+ .modemuxs = pwm0_1_pin_88_89_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm0_1_pin_88_89_modemux),
+ },
+};
+
+static const char *const pwm0_1_grps[] = { "pwm0_1_pin_8_9_grp",
+ "pwm0_1_pin_14_15_grp", "pwm0_1_pin_30_31_grp", "pwm0_1_pin_37_38_grp",
+ "pwm0_1_pin_42_43_grp", "pwm0_1_pin_59_60_grp", "pwm0_1_pin_88_89_grp"
+};
+
+static struct spear_function pwm0_1_function = {
+ .name = "pwm0_1",
+ .groups = pwm0_1_grps,
+ .ngroups = ARRAY_SIZE(pwm0_1_grps),
+};
+
+/* Pad multiplexing for PWM2 device */
+static const unsigned pwm2_pins[][1] = { { 7 }, { 13 }, { 29 }, { 34 }, { 41 },
+ { 58 }, { 87 } };
+static struct spear_muxreg pwm2_net_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_SSP_CS_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg pwm2_pin_7_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_0_9_REG,
+ .mask = PMX_PL_7_MASK,
+ .val = PMX_PWM_2_PL_7_VAL,
+ },
+};
+
+static struct spear_muxreg pwm2_autoexpsmallpri_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg pwm2_pin_13_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_10_19_REG,
+ .mask = PMX_PL_13_MASK,
+ .val = PMX_PWM2_PL_13_VAL,
+ },
+};
+
+static struct spear_muxreg pwm2_pin_29_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_GPIO_PIN1_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_20_29_REG,
+ .mask = PMX_PL_29_MASK,
+ .val = PMX_PWM_2_PL_29_VAL,
+ },
+};
+
+static struct spear_muxreg pwm2_pin_34_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_SSP_CS_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_34_MASK,
+ .val = PMX_PWM2_PL_34_VAL,
+ },
+};
+
+static struct spear_muxreg pwm2_pin_41_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_40_49_REG,
+ .mask = PMX_PL_41_MASK,
+ .val = PMX_PWM2_PL_41_VAL,
+ },
+};
+
+static struct spear_muxreg pwm2_pin_58_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_50_59_REG,
+ .mask = PMX_PL_58_MASK,
+ .val = PMX_PWM2_PL_58_VAL,
+ },
+};
+
+static struct spear_muxreg pwm2_pin_87_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_80_89_REG,
+ .mask = PMX_PL_87_MASK,
+ .val = PMX_PWM2_PL_87_VAL,
+ },
+};
+
+static struct spear_modemux pwm2_pin_7_modemux[] = {
+ {
+ .modes = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | EXTENDED_MODE,
+ .muxregs = pwm2_net_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm2_net_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm2_pin_7_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm2_pin_7_muxreg),
+ },
+};
+static struct spear_modemux pwm2_pin_13_modemux[] = {
+ {
+ .modes = AUTO_EXP_MODE | SMALL_PRINTERS_MODE | EXTENDED_MODE,
+ .muxregs = pwm2_autoexpsmallpri_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm2_autoexpsmallpri_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm2_pin_13_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm2_pin_13_muxreg),
+ },
+};
+static struct spear_modemux pwm2_pin_29_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm2_pin_29_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm2_pin_29_muxreg),
+ },
+};
+static struct spear_modemux pwm2_pin_34_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm2_pin_34_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm2_pin_34_muxreg),
+ },
+};
+
+static struct spear_modemux pwm2_pin_41_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm2_pin_41_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm2_pin_41_muxreg),
+ },
+};
+
+static struct spear_modemux pwm2_pin_58_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm2_pin_58_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm2_pin_58_muxreg),
+ },
+};
+
+static struct spear_modemux pwm2_pin_87_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm2_pin_87_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm2_pin_87_muxreg),
+ },
+};
+
+static struct spear_pingroup pwm2_pingroup[] = {
+ {
+ .name = "pwm2_pin_7_grp",
+ .pins = pwm2_pins[0],
+ .npins = ARRAY_SIZE(pwm2_pins[0]),
+ .modemuxs = pwm2_pin_7_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm2_pin_7_modemux),
+ }, {
+ .name = "pwm2_pin_13_grp",
+ .pins = pwm2_pins[1],
+ .npins = ARRAY_SIZE(pwm2_pins[1]),
+ .modemuxs = pwm2_pin_13_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm2_pin_13_modemux),
+ }, {
+ .name = "pwm2_pin_29_grp",
+ .pins = pwm2_pins[2],
+ .npins = ARRAY_SIZE(pwm2_pins[2]),
+ .modemuxs = pwm2_pin_29_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm2_pin_29_modemux),
+ }, {
+ .name = "pwm2_pin_34_grp",
+ .pins = pwm2_pins[3],
+ .npins = ARRAY_SIZE(pwm2_pins[3]),
+ .modemuxs = pwm2_pin_34_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm2_pin_34_modemux),
+ }, {
+ .name = "pwm2_pin_41_grp",
+ .pins = pwm2_pins[4],
+ .npins = ARRAY_SIZE(pwm2_pins[4]),
+ .modemuxs = pwm2_pin_41_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm2_pin_41_modemux),
+ }, {
+ .name = "pwm2_pin_58_grp",
+ .pins = pwm2_pins[5],
+ .npins = ARRAY_SIZE(pwm2_pins[5]),
+ .modemuxs = pwm2_pin_58_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm2_pin_58_modemux),
+ }, {
+ .name = "pwm2_pin_87_grp",
+ .pins = pwm2_pins[6],
+ .npins = ARRAY_SIZE(pwm2_pins[6]),
+ .modemuxs = pwm2_pin_87_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm2_pin_87_modemux),
+ },
+};
+
+static const char *const pwm2_grps[] = { "pwm2_pin_7_grp", "pwm2_pin_13_grp",
+ "pwm2_pin_29_grp", "pwm2_pin_34_grp", "pwm2_pin_41_grp",
+ "pwm2_pin_58_grp", "pwm2_pin_87_grp" };
+static struct spear_function pwm2_function = {
+ .name = "pwm2",
+ .groups = pwm2_grps,
+ .ngroups = ARRAY_SIZE(pwm2_grps),
+};
+
+/* Pad multiplexing for PWM3 device */
+static const unsigned pwm3_pins[][1] = { { 6 }, { 12 }, { 28 }, { 40 }, { 57 },
+ { 86 } };
+static struct spear_muxreg pwm3_pin_6_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_SSP_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_0_9_REG,
+ .mask = PMX_PL_6_MASK,
+ .val = PMX_PWM_3_PL_6_VAL,
+ },
+};
+
+static struct spear_muxreg pwm3_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg pwm3_pin_12_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_10_19_REG,
+ .mask = PMX_PL_12_MASK,
+ .val = PMX_PWM3_PL_12_VAL,
+ },
+};
+
+static struct spear_muxreg pwm3_pin_28_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_GPIO_PIN0_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_20_29_REG,
+ .mask = PMX_PL_28_MASK,
+ .val = PMX_PWM_3_PL_28_VAL,
+ },
+};
+
+static struct spear_muxreg pwm3_pin_40_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_40_49_REG,
+ .mask = PMX_PL_40_MASK,
+ .val = PMX_PWM3_PL_40_VAL,
+ },
+};
+
+static struct spear_muxreg pwm3_pin_57_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_50_59_REG,
+ .mask = PMX_PL_57_MASK,
+ .val = PMX_PWM3_PL_57_VAL,
+ },
+};
+
+static struct spear_muxreg pwm3_pin_86_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_80_89_REG,
+ .mask = PMX_PL_86_MASK,
+ .val = PMX_PWM3_PL_86_VAL,
+ },
+};
+
+static struct spear_modemux pwm3_pin_6_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm3_pin_6_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm3_pin_6_muxreg),
+ },
+};
+
+static struct spear_modemux pwm3_pin_12_modemux[] = {
+ {
+ .modes = AUTO_EXP_MODE | SMALL_PRINTERS_MODE |
+ AUTO_NET_SMII_MODE | EXTENDED_MODE,
+ .muxregs = pwm3_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm3_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm3_pin_12_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm3_pin_12_muxreg),
+ },
+};
+
+static struct spear_modemux pwm3_pin_28_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm3_pin_28_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm3_pin_28_muxreg),
+ },
+};
+
+static struct spear_modemux pwm3_pin_40_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm3_pin_40_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm3_pin_40_muxreg),
+ },
+};
+
+static struct spear_modemux pwm3_pin_57_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm3_pin_57_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm3_pin_57_muxreg),
+ },
+};
+
+static struct spear_modemux pwm3_pin_86_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = pwm3_pin_86_muxreg,
+ .nmuxregs = ARRAY_SIZE(pwm3_pin_86_muxreg),
+ },
+};
+
+static struct spear_pingroup pwm3_pingroup[] = {
+ {
+ .name = "pwm3_pin_6_grp",
+ .pins = pwm3_pins[0],
+ .npins = ARRAY_SIZE(pwm3_pins[0]),
+ .modemuxs = pwm3_pin_6_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm3_pin_6_modemux),
+ }, {
+ .name = "pwm3_pin_12_grp",
+ .pins = pwm3_pins[1],
+ .npins = ARRAY_SIZE(pwm3_pins[1]),
+ .modemuxs = pwm3_pin_12_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm3_pin_12_modemux),
+ }, {
+ .name = "pwm3_pin_28_grp",
+ .pins = pwm3_pins[2],
+ .npins = ARRAY_SIZE(pwm3_pins[2]),
+ .modemuxs = pwm3_pin_28_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm3_pin_28_modemux),
+ }, {
+ .name = "pwm3_pin_40_grp",
+ .pins = pwm3_pins[3],
+ .npins = ARRAY_SIZE(pwm3_pins[3]),
+ .modemuxs = pwm3_pin_40_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm3_pin_40_modemux),
+ }, {
+ .name = "pwm3_pin_57_grp",
+ .pins = pwm3_pins[4],
+ .npins = ARRAY_SIZE(pwm3_pins[4]),
+ .modemuxs = pwm3_pin_57_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm3_pin_57_modemux),
+ }, {
+ .name = "pwm3_pin_86_grp",
+ .pins = pwm3_pins[5],
+ .npins = ARRAY_SIZE(pwm3_pins[5]),
+ .modemuxs = pwm3_pin_86_modemux,
+ .nmodemuxs = ARRAY_SIZE(pwm3_pin_86_modemux),
+ },
+};
+
+static const char *const pwm3_grps[] = { "pwm3_pin_6_grp", "pwm3_pin_12_grp",
+ "pwm3_pin_28_grp", "pwm3_pin_40_grp", "pwm3_pin_57_grp",
+ "pwm3_pin_86_grp" };
+static struct spear_function pwm3_function = {
+ .name = "pwm3",
+ .groups = pwm3_grps,
+ .ngroups = ARRAY_SIZE(pwm3_grps),
+};
+
+/* Pad multiplexing for SSP1 device */
+static const unsigned ssp1_pins[][2] = { { 17, 20 }, { 36, 39 }, { 48, 51 },
+ { 65, 68 }, { 94, 97 } };
+static struct spear_muxreg ssp1_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg ssp1_ext_17_20_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_10_19_REG,
+ .mask = PMX_PL_17_18_MASK | PMX_PL_19_MASK,
+ .val = PMX_SSP1_PL_17_18_19_20_VAL,
+ }, {
+ .reg = IP_SEL_PAD_20_29_REG,
+ .mask = PMX_PL_20_MASK,
+ .val = PMX_SSP1_PL_17_18_19_20_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_SSP1_PORT_SEL_MASK,
+ .val = PMX_SSP1_PORT_17_TO_20_VAL,
+ },
+};
+
+static struct spear_muxreg ssp1_ext_36_39_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MODEM_MASK | PMX_SSP_CS_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_36_MASK | PMX_PL_37_38_MASK | PMX_PL_39_MASK,
+ .val = PMX_SSP1_PL_36_VAL | PMX_SSP1_PL_37_38_VAL |
+ PMX_SSP1_PL_39_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_SSP1_PORT_SEL_MASK,
+ .val = PMX_SSP1_PORT_36_TO_39_VAL,
+ },
+};
+
+static struct spear_muxreg ssp1_ext_48_51_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_40_49_REG,
+ .mask = PMX_PL_48_49_MASK,
+ .val = PMX_SSP1_PL_48_49_VAL,
+ }, {
+ .reg = IP_SEL_PAD_50_59_REG,
+ .mask = PMX_PL_50_51_MASK,
+ .val = PMX_SSP1_PL_50_51_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_SSP1_PORT_SEL_MASK,
+ .val = PMX_SSP1_PORT_48_TO_51_VAL,
+ },
+};
+
+static struct spear_muxreg ssp1_ext_65_68_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_60_69_REG,
+ .mask = PMX_PL_65_TO_68_MASK,
+ .val = PMX_SSP1_PL_65_TO_68_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_SSP1_PORT_SEL_MASK,
+ .val = PMX_SSP1_PORT_65_TO_68_VAL,
+ },
+};
+
+static struct spear_muxreg ssp1_ext_94_97_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_90_99_REG,
+ .mask = PMX_PL_94_95_MASK | PMX_PL_96_97_MASK,
+ .val = PMX_SSP1_PL_94_95_VAL | PMX_SSP1_PL_96_97_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_SSP1_PORT_SEL_MASK,
+ .val = PMX_SSP1_PORT_94_TO_97_VAL,
+ },
+};
+
+static struct spear_modemux ssp1_17_20_modemux[] = {
+ {
+ .modes = SMALL_PRINTERS_MODE | AUTO_NET_SMII_MODE |
+ EXTENDED_MODE,
+ .muxregs = ssp1_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp1_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = ssp1_ext_17_20_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp1_ext_17_20_muxreg),
+ },
+};
+
+static struct spear_modemux ssp1_36_39_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = ssp1_ext_36_39_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp1_ext_36_39_muxreg),
+ },
+};
+
+static struct spear_modemux ssp1_48_51_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = ssp1_ext_48_51_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp1_ext_48_51_muxreg),
+ },
+};
+static struct spear_modemux ssp1_65_68_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = ssp1_ext_65_68_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp1_ext_65_68_muxreg),
+ },
+};
+
+static struct spear_modemux ssp1_94_97_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = ssp1_ext_94_97_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp1_ext_94_97_muxreg),
+ },
+};
+
+static struct spear_pingroup ssp1_pingroup[] = {
+ {
+ .name = "ssp1_17_20_grp",
+ .pins = ssp1_pins[0],
+ .npins = ARRAY_SIZE(ssp1_pins[0]),
+ .modemuxs = ssp1_17_20_modemux,
+ .nmodemuxs = ARRAY_SIZE(ssp1_17_20_modemux),
+ }, {
+ .name = "ssp1_36_39_grp",
+ .pins = ssp1_pins[1],
+ .npins = ARRAY_SIZE(ssp1_pins[1]),
+ .modemuxs = ssp1_36_39_modemux,
+ .nmodemuxs = ARRAY_SIZE(ssp1_36_39_modemux),
+ }, {
+ .name = "ssp1_48_51_grp",
+ .pins = ssp1_pins[2],
+ .npins = ARRAY_SIZE(ssp1_pins[2]),
+ .modemuxs = ssp1_48_51_modemux,
+ .nmodemuxs = ARRAY_SIZE(ssp1_48_51_modemux),
+ }, {
+ .name = "ssp1_65_68_grp",
+ .pins = ssp1_pins[3],
+ .npins = ARRAY_SIZE(ssp1_pins[3]),
+ .modemuxs = ssp1_65_68_modemux,
+ .nmodemuxs = ARRAY_SIZE(ssp1_65_68_modemux),
+ }, {
+ .name = "ssp1_94_97_grp",
+ .pins = ssp1_pins[4],
+ .npins = ARRAY_SIZE(ssp1_pins[4]),
+ .modemuxs = ssp1_94_97_modemux,
+ .nmodemuxs = ARRAY_SIZE(ssp1_94_97_modemux),
+ },
+};
+
+static const char *const ssp1_grps[] = { "ssp1_17_20_grp", "ssp1_36_39_grp",
+ "ssp1_48_51_grp", "ssp1_65_68_grp", "ssp1_94_97_grp"
+};
+static struct spear_function ssp1_function = {
+ .name = "ssp1",
+ .groups = ssp1_grps,
+ .ngroups = ARRAY_SIZE(ssp1_grps),
+};
+
+/* Pad multiplexing for SSP2 device */
+static const unsigned ssp2_pins[][2] = { { 13, 16 }, { 32, 35 }, { 44, 47 },
+ { 61, 64 }, { 90, 93 } };
+static struct spear_muxreg ssp2_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg ssp2_ext_13_16_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_10_19_REG,
+ .mask = PMX_PL_13_14_MASK | PMX_PL_15_16_MASK,
+ .val = PMX_SSP2_PL_13_14_15_16_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_SSP2_PORT_SEL_MASK,
+ .val = PMX_SSP2_PORT_13_TO_16_VAL,
+ },
+};
+
+static struct spear_muxreg ssp2_ext_32_35_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_SSP_CS_MASK | PMX_GPIO_PIN4_MASK |
+ PMX_GPIO_PIN5_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_30_39_REG,
+ .mask = PMX_PL_32_33_MASK | PMX_PL_34_MASK | PMX_PL_35_MASK,
+ .val = PMX_SSP2_PL_32_33_VAL | PMX_SSP2_PL_34_VAL |
+ PMX_SSP2_PL_35_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_SSP2_PORT_SEL_MASK,
+ .val = PMX_SSP2_PORT_32_TO_35_VAL,
+ },
+};
+
+static struct spear_muxreg ssp2_ext_44_47_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_40_49_REG,
+ .mask = PMX_PL_44_45_MASK | PMX_PL_46_47_MASK,
+ .val = PMX_SSP2_PL_44_45_VAL | PMX_SSP2_PL_46_47_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_SSP2_PORT_SEL_MASK,
+ .val = PMX_SSP2_PORT_44_TO_47_VAL,
+ },
+};
+
+static struct spear_muxreg ssp2_ext_61_64_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_60_69_REG,
+ .mask = PMX_PL_61_TO_64_MASK,
+ .val = PMX_SSP2_PL_61_TO_64_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_SSP2_PORT_SEL_MASK,
+ .val = PMX_SSP2_PORT_61_TO_64_VAL,
+ },
+};
+
+static struct spear_muxreg ssp2_ext_90_93_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_90_99_REG,
+ .mask = PMX_PL_90_91_MASK | PMX_PL_92_93_MASK,
+ .val = PMX_SSP2_PL_90_91_VAL | PMX_SSP2_PL_92_93_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_SSP2_PORT_SEL_MASK,
+ .val = PMX_SSP2_PORT_90_TO_93_VAL,
+ },
+};
+
+static struct spear_modemux ssp2_13_16_modemux[] = {
+ {
+ .modes = AUTO_NET_SMII_MODE | EXTENDED_MODE,
+ .muxregs = ssp2_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp2_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = ssp2_ext_13_16_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp2_ext_13_16_muxreg),
+ },
+};
+
+static struct spear_modemux ssp2_32_35_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = ssp2_ext_32_35_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp2_ext_32_35_muxreg),
+ },
+};
+
+static struct spear_modemux ssp2_44_47_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = ssp2_ext_44_47_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp2_ext_44_47_muxreg),
+ },
+};
+
+static struct spear_modemux ssp2_61_64_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = ssp2_ext_61_64_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp2_ext_61_64_muxreg),
+ },
+};
+
+static struct spear_modemux ssp2_90_93_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = ssp2_ext_90_93_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp2_ext_90_93_muxreg),
+ },
+};
+
+static struct spear_pingroup ssp2_pingroup[] = {
+ {
+ .name = "ssp2_13_16_grp",
+ .pins = ssp2_pins[0],
+ .npins = ARRAY_SIZE(ssp2_pins[0]),
+ .modemuxs = ssp2_13_16_modemux,
+ .nmodemuxs = ARRAY_SIZE(ssp2_13_16_modemux),
+ }, {
+ .name = "ssp2_32_35_grp",
+ .pins = ssp2_pins[1],
+ .npins = ARRAY_SIZE(ssp2_pins[1]),
+ .modemuxs = ssp2_32_35_modemux,
+ .nmodemuxs = ARRAY_SIZE(ssp2_32_35_modemux),
+ }, {
+ .name = "ssp2_44_47_grp",
+ .pins = ssp2_pins[2],
+ .npins = ARRAY_SIZE(ssp2_pins[2]),
+ .modemuxs = ssp2_44_47_modemux,
+ .nmodemuxs = ARRAY_SIZE(ssp2_44_47_modemux),
+ }, {
+ .name = "ssp2_61_64_grp",
+ .pins = ssp2_pins[3],
+ .npins = ARRAY_SIZE(ssp2_pins[3]),
+ .modemuxs = ssp2_61_64_modemux,
+ .nmodemuxs = ARRAY_SIZE(ssp2_61_64_modemux),
+ }, {
+ .name = "ssp2_90_93_grp",
+ .pins = ssp2_pins[4],
+ .npins = ARRAY_SIZE(ssp2_pins[4]),
+ .modemuxs = ssp2_90_93_modemux,
+ .nmodemuxs = ARRAY_SIZE(ssp2_90_93_modemux),
+ },
+};
+
+static const char *const ssp2_grps[] = { "ssp2_13_16_grp", "ssp2_32_35_grp",
+ "ssp2_44_47_grp", "ssp2_61_64_grp", "ssp2_90_93_grp" };
+static struct spear_function ssp2_function = {
+ .name = "ssp2",
+ .groups = ssp2_grps,
+ .ngroups = ARRAY_SIZE(ssp2_grps),
+};
+
+/* Pad multiplexing for cadence mii2 as mii device */
+static const unsigned mii2_pins[] = { 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97 };
+static struct spear_muxreg mii2_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_80_89_REG,
+ .mask = PMX_PL_80_TO_85_MASK | PMX_PL_86_87_MASK |
+ PMX_PL_88_89_MASK,
+ .val = PMX_MII2_PL_80_TO_85_VAL | PMX_MII2_PL_86_87_VAL |
+ PMX_MII2_PL_88_89_VAL,
+ }, {
+ .reg = IP_SEL_PAD_90_99_REG,
+ .mask = PMX_PL_90_91_MASK | PMX_PL_92_93_MASK |
+ PMX_PL_94_95_MASK | PMX_PL_96_97_MASK,
+ .val = PMX_MII2_PL_90_91_VAL | PMX_MII2_PL_92_93_VAL |
+ PMX_MII2_PL_94_95_VAL | PMX_MII2_PL_96_97_VAL,
+ }, {
+ .reg = EXT_CTRL_REG,
+ .mask = (MAC_MODE_MASK << MAC2_MODE_SHIFT) |
+ (MAC_MODE_MASK << MAC1_MODE_SHIFT) |
+ MII_MDIO_MASK,
+ .val = (MAC_MODE_MII << MAC2_MODE_SHIFT) |
+ (MAC_MODE_MII << MAC1_MODE_SHIFT) |
+ MII_MDIO_81_VAL,
+ },
+};
+
+static struct spear_modemux mii2_modemux[] = {
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = mii2_muxreg,
+ .nmuxregs = ARRAY_SIZE(mii2_muxreg),
+ },
+};
+
+static struct spear_pingroup mii2_pingroup = {
+ .name = "mii2_grp",
+ .pins = mii2_pins,
+ .npins = ARRAY_SIZE(mii2_pins),
+ .modemuxs = mii2_modemux,
+ .nmodemuxs = ARRAY_SIZE(mii2_modemux),
+};
+
+static const char *const mii2_grps[] = { "mii2_grp" };
+static struct spear_function mii2_function = {
+ .name = "mii2",
+ .groups = mii2_grps,
+ .ngroups = ARRAY_SIZE(mii2_grps),
+};
+
+/* Pad multiplexing for cadence mii 1_2 as smii or rmii device */
+static const unsigned smii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27 };
+static const unsigned rmii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 };
+static struct spear_muxreg mii0_1_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ },
+};
+
+static struct spear_muxreg smii0_1_ext_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_10_19_REG,
+ .mask = PMX_PL_10_11_MASK,
+ .val = PMX_SMII_PL_10_11_VAL,
+ }, {
+ .reg = IP_SEL_PAD_20_29_REG,
+ .mask = PMX_PL_21_TO_27_MASK,
+ .val = PMX_SMII_PL_21_TO_27_VAL,
+ }, {
+ .reg = EXT_CTRL_REG,
+ .mask = (MAC_MODE_MASK << MAC2_MODE_SHIFT) |
+ (MAC_MODE_MASK << MAC1_MODE_SHIFT) |
+ MII_MDIO_MASK,
+ .val = (MAC_MODE_SMII << MAC2_MODE_SHIFT)
+ | (MAC_MODE_SMII << MAC1_MODE_SHIFT)
+ | MII_MDIO_10_11_VAL,
+ },
+};
+
+static struct spear_muxreg rmii0_1_ext_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_10_19_REG,
+ .mask = PMX_PL_10_11_MASK | PMX_PL_13_14_MASK |
+ PMX_PL_15_16_MASK | PMX_PL_17_18_MASK | PMX_PL_19_MASK,
+ .val = PMX_RMII_PL_10_11_VAL | PMX_RMII_PL_13_14_VAL |
+ PMX_RMII_PL_15_16_VAL | PMX_RMII_PL_17_18_VAL |
+ PMX_RMII_PL_19_VAL,
+ }, {
+ .reg = IP_SEL_PAD_20_29_REG,
+ .mask = PMX_PL_20_MASK | PMX_PL_21_TO_27_MASK,
+ .val = PMX_RMII_PL_20_VAL | PMX_RMII_PL_21_TO_27_VAL,
+ }, {
+ .reg = EXT_CTRL_REG,
+ .mask = (MAC_MODE_MASK << MAC2_MODE_SHIFT) |
+ (MAC_MODE_MASK << MAC1_MODE_SHIFT) |
+ MII_MDIO_MASK,
+ .val = (MAC_MODE_RMII << MAC2_MODE_SHIFT)
+ | (MAC_MODE_RMII << MAC1_MODE_SHIFT)
+ | MII_MDIO_10_11_VAL,
+ },
+};
+
+static struct spear_modemux mii0_1_modemux[][2] = {
+ {
+ /* configure as smii */
+ {
+ .modes = AUTO_NET_SMII_MODE | AUTO_EXP_MODE |
+ SMALL_PRINTERS_MODE | EXTENDED_MODE,
+ .muxregs = mii0_1_muxreg,
+ .nmuxregs = ARRAY_SIZE(mii0_1_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = smii0_1_ext_muxreg,
+ .nmuxregs = ARRAY_SIZE(smii0_1_ext_muxreg),
+ },
+ }, {
+ /* configure as rmii */
+ {
+ .modes = AUTO_NET_SMII_MODE | AUTO_EXP_MODE |
+ SMALL_PRINTERS_MODE | EXTENDED_MODE,
+ .muxregs = mii0_1_muxreg,
+ .nmuxregs = ARRAY_SIZE(mii0_1_muxreg),
+ }, {
+ .modes = EXTENDED_MODE,
+ .muxregs = rmii0_1_ext_muxreg,
+ .nmuxregs = ARRAY_SIZE(rmii0_1_ext_muxreg),
+ },
+ },
+};
+
+static struct spear_pingroup mii0_1_pingroup[] = {
+ {
+ .name = "smii0_1_grp",
+ .pins = smii0_1_pins,
+ .npins = ARRAY_SIZE(smii0_1_pins),
+ .modemuxs = mii0_1_modemux[0],
+ .nmodemuxs = ARRAY_SIZE(mii0_1_modemux[0]),
+ }, {
+ .name = "rmii0_1_grp",
+ .pins = rmii0_1_pins,
+ .npins = ARRAY_SIZE(rmii0_1_pins),
+ .modemuxs = mii0_1_modemux[1],
+ .nmodemuxs = ARRAY_SIZE(mii0_1_modemux[1]),
+ },
+};
+
+static const char *const mii0_1_grps[] = { "smii0_1_grp", "rmii0_1_grp" };
+static struct spear_function mii0_1_function = {
+ .name = "mii0_1",
+ .groups = mii0_1_grps,
+ .ngroups = ARRAY_SIZE(mii0_1_grps),
+};
+
+/* Pad multiplexing for i2c1 device */
+static const unsigned i2c1_pins[][2] = { { 8, 9 }, { 98, 99 } };
+static struct spear_muxreg i2c1_ext_8_9_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_SSP_CS_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_0_9_REG,
+ .mask = PMX_PL_8_9_MASK,
+ .val = PMX_I2C1_PL_8_9_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_I2C1_PORT_SEL_MASK,
+ .val = PMX_I2C1_PORT_8_9_VAL,
+ },
+};
+
+static struct spear_muxreg i2c1_ext_98_99_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_90_99_REG,
+ .mask = PMX_PL_98_MASK | PMX_PL_99_MASK,
+ .val = PMX_I2C1_PL_98_VAL | PMX_I2C1_PL_99_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_I2C1_PORT_SEL_MASK,
+ .val = PMX_I2C1_PORT_98_99_VAL,
+ },
+};
+
+static struct spear_modemux i2c1_modemux[][1] = {
+ {
+ /* Select signals on pins 8-9 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = i2c1_ext_8_9_muxreg,
+ .nmuxregs = ARRAY_SIZE(i2c1_ext_8_9_muxreg),
+ },
+ }, {
+ /* Select signals on pins 98-99 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = i2c1_ext_98_99_muxreg,
+ .nmuxregs = ARRAY_SIZE(i2c1_ext_98_99_muxreg),
+ },
+ },
+};
+
+static struct spear_pingroup i2c1_pingroup[] = {
+ {
+ .name = "i2c1_8_9_grp",
+ .pins = i2c1_pins[0],
+ .npins = ARRAY_SIZE(i2c1_pins[0]),
+ .modemuxs = i2c1_modemux[0],
+ .nmodemuxs = ARRAY_SIZE(i2c1_modemux[0]),
+ }, {
+ .name = "i2c1_98_99_grp",
+ .pins = i2c1_pins[1],
+ .npins = ARRAY_SIZE(i2c1_pins[1]),
+ .modemuxs = i2c1_modemux[1],
+ .nmodemuxs = ARRAY_SIZE(i2c1_modemux[1]),
+ },
+};
+
+static const char *const i2c1_grps[] = { "i2c1_8_9_grp", "i2c1_98_99_grp" };
+static struct spear_function i2c1_function = {
+ .name = "i2c1",
+ .groups = i2c1_grps,
+ .ngroups = ARRAY_SIZE(i2c1_grps),
+};
+
+/* Pad multiplexing for i2c2 device */
+static const unsigned i2c2_pins[][2] = { { 0, 1 }, { 2, 3 }, { 19, 20 },
+ { 75, 76 }, { 96, 97 } };
+static struct spear_muxreg i2c2_ext_0_1_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_FIRDA_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_0_9_REG,
+ .mask = PMX_PL_0_1_MASK,
+ .val = PMX_I2C2_PL_0_1_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_I2C2_PORT_SEL_MASK,
+ .val = PMX_I2C2_PORT_0_1_VAL,
+ },
+};
+
+static struct spear_muxreg i2c2_ext_2_3_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_UART0_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_0_9_REG,
+ .mask = PMX_PL_2_3_MASK,
+ .val = PMX_I2C2_PL_2_3_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_I2C2_PORT_SEL_MASK,
+ .val = PMX_I2C2_PORT_2_3_VAL,
+ },
+};
+
+static struct spear_muxreg i2c2_ext_19_20_muxreg[] = {
+ {
+ .reg = PMX_CONFIG_REG,
+ .mask = PMX_MII_MASK,
+ .val = 0,
+ }, {
+ .reg = IP_SEL_PAD_10_19_REG,
+ .mask = PMX_PL_19_MASK,
+ .val = PMX_I2C2_PL_19_VAL,
+ }, {
+ .reg = IP_SEL_PAD_20_29_REG,
+ .mask = PMX_PL_20_MASK,
+ .val = PMX_I2C2_PL_20_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_I2C2_PORT_SEL_MASK,
+ .val = PMX_I2C2_PORT_19_20_VAL,
+ },
+};
+
+static struct spear_muxreg i2c2_ext_75_76_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_70_79_REG,
+ .mask = PMX_PL_75_76_MASK,
+ .val = PMX_I2C2_PL_75_76_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_I2C2_PORT_SEL_MASK,
+ .val = PMX_I2C2_PORT_75_76_VAL,
+ },
+};
+
+static struct spear_muxreg i2c2_ext_96_97_muxreg[] = {
+ {
+ .reg = IP_SEL_PAD_90_99_REG,
+ .mask = PMX_PL_96_97_MASK,
+ .val = PMX_I2C2_PL_96_97_VAL,
+ }, {
+ .reg = IP_SEL_MIX_PAD_REG,
+ .mask = PMX_I2C2_PORT_SEL_MASK,
+ .val = PMX_I2C2_PORT_96_97_VAL,
+ },
+};
+
+static struct spear_modemux i2c2_modemux[][1] = {
+ {
+ /* Select signals on pins 0_1 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = i2c2_ext_0_1_muxreg,
+ .nmuxregs = ARRAY_SIZE(i2c2_ext_0_1_muxreg),
+ },
+ }, {
+ /* Select signals on pins 2_3 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = i2c2_ext_2_3_muxreg,
+ .nmuxregs = ARRAY_SIZE(i2c2_ext_2_3_muxreg),
+ },
+ }, {
+ /* Select signals on pins 19_20 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = i2c2_ext_19_20_muxreg,
+ .nmuxregs = ARRAY_SIZE(i2c2_ext_19_20_muxreg),
+ },
+ }, {
+ /* Select signals on pins 75_76 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = i2c2_ext_75_76_muxreg,
+ .nmuxregs = ARRAY_SIZE(i2c2_ext_75_76_muxreg),
+ },
+ }, {
+ /* Select signals on pins 96_97 */
+ {
+ .modes = EXTENDED_MODE,
+ .muxregs = i2c2_ext_96_97_muxreg,
+ .nmuxregs = ARRAY_SIZE(i2c2_ext_96_97_muxreg),
+ },
+ },
+};
+
+static struct spear_pingroup i2c2_pingroup[] = {
+ {
+ .name = "i2c2_0_1_grp",
+ .pins = i2c2_pins[0],
+ .npins = ARRAY_SIZE(i2c2_pins[0]),
+ .modemuxs = i2c2_modemux[0],
+ .nmodemuxs = ARRAY_SIZE(i2c2_modemux[0]),
+ }, {
+ .name = "i2c2_2_3_grp",
+ .pins = i2c2_pins[1],
+ .npins = ARRAY_SIZE(i2c2_pins[1]),
+ .modemuxs = i2c2_modemux[1],
+ .nmodemuxs = ARRAY_SIZE(i2c2_modemux[1]),
+ }, {
+ .name = "i2c2_19_20_grp",
+ .pins = i2c2_pins[2],
+ .npins = ARRAY_SIZE(i2c2_pins[2]),
+ .modemuxs = i2c2_modemux[2],
+ .nmodemuxs = ARRAY_SIZE(i2c2_modemux[2]),
+ }, {
+ .name = "i2c2_75_76_grp",
+ .pins = i2c2_pins[3],
+ .npins = ARRAY_SIZE(i2c2_pins[3]),
+ .modemuxs = i2c2_modemux[3],
+ .nmodemuxs = ARRAY_SIZE(i2c2_modemux[3]),
+ }, {
+ .name = "i2c2_96_97_grp",
+ .pins = i2c2_pins[4],
+ .npins = ARRAY_SIZE(i2c2_pins[4]),
+ .modemuxs = i2c2_modemux[4],
+ .nmodemuxs = ARRAY_SIZE(i2c2_modemux[4]),
+ },
+};
+
+static const char *const i2c2_grps[] = { "i2c2_0_1_grp", "i2c2_2_3_grp",
+ "i2c2_19_20_grp", "i2c2_75_76_grp", "i2c2_96_97_grp" };
+static struct spear_function i2c2_function = {
+ .name = "i2c2",
+ .groups = i2c2_grps,
+ .ngroups = ARRAY_SIZE(i2c2_grps),
+};
+
+/* pingroups */
+static struct spear_pingroup *spear320_pingroups[] = {
+ SPEAR3XX_COMMON_PINGROUPS,
+ &clcd_pingroup,
+ &emi_pingroup,
+ &fsmc_8bit_pingroup,
+ &fsmc_16bit_pingroup,
+ &spp_pingroup,
+ &sdhci_led_pingroup,
+ &sdhci_pingroup[0],
+ &sdhci_pingroup[1],
+ &i2s_pingroup,
+ &uart1_pingroup,
+ &uart1_modem_pingroup[0],
+ &uart1_modem_pingroup[1],
+ &uart1_modem_pingroup[2],
+ &uart1_modem_pingroup[3],
+ &uart2_pingroup,
+ &uart3_pingroup[0],
+ &uart3_pingroup[1],
+ &uart3_pingroup[2],
+ &uart3_pingroup[3],
+ &uart3_pingroup[4],
+ &uart3_pingroup[5],
+ &uart3_pingroup[6],
+ &uart4_pingroup[0],
+ &uart4_pingroup[1],
+ &uart4_pingroup[2],
+ &uart4_pingroup[3],
+ &uart4_pingroup[4],
+ &uart4_pingroup[5],
+ &uart5_pingroup[0],
+ &uart5_pingroup[1],
+ &uart5_pingroup[2],
+ &uart5_pingroup[3],
+ &uart6_pingroup[0],
+ &uart6_pingroup[1],
+ &rs485_pingroup,
+ &touchscreen_pingroup,
+ &can0_pingroup,
+ &can1_pingroup,
+ &pwm0_1_pingroup[0],
+ &pwm0_1_pingroup[1],
+ &pwm0_1_pingroup[2],
+ &pwm0_1_pingroup[3],
+ &pwm0_1_pingroup[4],
+ &pwm0_1_pingroup[5],
+ &pwm0_1_pingroup[6],
+ &pwm2_pingroup[0],
+ &pwm2_pingroup[1],
+ &pwm2_pingroup[2],
+ &pwm2_pingroup[3],
+ &pwm2_pingroup[4],
+ &pwm2_pingroup[5],
+ &pwm2_pingroup[6],
+ &pwm3_pingroup[0],
+ &pwm3_pingroup[1],
+ &pwm3_pingroup[2],
+ &pwm3_pingroup[3],
+ &pwm3_pingroup[4],
+ &pwm3_pingroup[5],
+ &ssp1_pingroup[0],
+ &ssp1_pingroup[1],
+ &ssp1_pingroup[2],
+ &ssp1_pingroup[3],
+ &ssp1_pingroup[4],
+ &ssp2_pingroup[0],
+ &ssp2_pingroup[1],
+ &ssp2_pingroup[2],
+ &ssp2_pingroup[3],
+ &ssp2_pingroup[4],
+ &mii2_pingroup,
+ &mii0_1_pingroup[0],
+ &mii0_1_pingroup[1],
+ &i2c1_pingroup[0],
+ &i2c1_pingroup[1],
+ &i2c2_pingroup[0],
+ &i2c2_pingroup[1],
+ &i2c2_pingroup[2],
+ &i2c2_pingroup[3],
+ &i2c2_pingroup[4],
+};
+
+/* functions */
+static struct spear_function *spear320_functions[] = {
+ SPEAR3XX_COMMON_FUNCTIONS,
+ &clcd_function,
+ &emi_function,
+ &fsmc_function,
+ &spp_function,
+ &sdhci_function,
+ &i2s_function,
+ &uart1_function,
+ &uart1_modem_function,
+ &uart2_function,
+ &uart3_function,
+ &uart4_function,
+ &uart5_function,
+ &uart6_function,
+ &rs485_function,
+ &touchscreen_function,
+ &can0_function,
+ &can1_function,
+ &pwm0_1_function,
+ &pwm2_function,
+ &pwm3_function,
+ &ssp1_function,
+ &ssp2_function,
+ &mii2_function,
+ &mii0_1_function,
+ &i2c1_function,
+ &i2c2_function,
+};
+
+static struct of_device_id spear320_pinctrl_of_match[] __devinitdata = {
+ {
+ .compatible = "st,spear320-pinmux",
+ },
+ {},
+};
+
+static int __devinit spear320_pinctrl_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ spear3xx_machdata.groups = spear320_pingroups;
+ spear3xx_machdata.ngroups = ARRAY_SIZE(spear320_pingroups);
+ spear3xx_machdata.functions = spear320_functions;
+ spear3xx_machdata.nfunctions = ARRAY_SIZE(spear320_functions);
+
+ spear3xx_machdata.modes_supported = true;
+ spear3xx_machdata.pmx_modes = spear320_pmx_modes;
+ spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear320_pmx_modes);
+
+ pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
+
+ ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int __devexit spear320_pinctrl_remove(struct platform_device *pdev)
+{
+ return spear_pinctrl_remove(pdev);
+}
+
+static struct platform_driver spear320_pinctrl_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = spear320_pinctrl_of_match,
+ },
+ .probe = spear320_pinctrl_probe,
+ .remove = __devexit_p(spear320_pinctrl_remove),
+};
+
+static int __init spear320_pinctrl_init(void)
+{
+ return platform_driver_register(&spear320_pinctrl_driver);
+}
+arch_initcall(spear320_pinctrl_init);
+
+static void __exit spear320_pinctrl_exit(void)
+{
+ platform_driver_unregister(&spear320_pinctrl_driver);
+}
+module_exit(spear320_pinctrl_exit);
+
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
+MODULE_DESCRIPTION("ST Microelectronics SPEAr320 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, spear320_pinctrl_of_match);
diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.c b/drivers/pinctrl/spear/pinctrl-spear3xx.c
new file mode 100644
index 000000000000..832049a8b1c9
--- /dev/null
+++ b/drivers/pinctrl/spear/pinctrl-spear3xx.c
@@ -0,0 +1,588 @@
+/*
+ * Driver for the ST Microelectronics SPEAr3xx pinmux
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-spear3xx.h"
+
+/* pins */
+static const struct pinctrl_pin_desc spear3xx_pins[] = {
+ PINCTRL_PIN(0, "PLGPIO0"),
+ PINCTRL_PIN(1, "PLGPIO1"),
+ PINCTRL_PIN(2, "PLGPIO2"),
+ PINCTRL_PIN(3, "PLGPIO3"),
+ PINCTRL_PIN(4, "PLGPIO4"),
+ PINCTRL_PIN(5, "PLGPIO5"),
+ PINCTRL_PIN(6, "PLGPIO6"),
+ PINCTRL_PIN(7, "PLGPIO7"),
+ PINCTRL_PIN(8, "PLGPIO8"),
+ PINCTRL_PIN(9, "PLGPIO9"),
+ PINCTRL_PIN(10, "PLGPIO10"),
+ PINCTRL_PIN(11, "PLGPIO11"),
+ PINCTRL_PIN(12, "PLGPIO12"),
+ PINCTRL_PIN(13, "PLGPIO13"),
+ PINCTRL_PIN(14, "PLGPIO14"),
+ PINCTRL_PIN(15, "PLGPIO15"),
+ PINCTRL_PIN(16, "PLGPIO16"),
+ PINCTRL_PIN(17, "PLGPIO17"),
+ PINCTRL_PIN(18, "PLGPIO18"),
+ PINCTRL_PIN(19, "PLGPIO19"),
+ PINCTRL_PIN(20, "PLGPIO20"),
+ PINCTRL_PIN(21, "PLGPIO21"),
+ PINCTRL_PIN(22, "PLGPIO22"),
+ PINCTRL_PIN(23, "PLGPIO23"),
+ PINCTRL_PIN(24, "PLGPIO24"),
+ PINCTRL_PIN(25, "PLGPIO25"),
+ PINCTRL_PIN(26, "PLGPIO26"),
+ PINCTRL_PIN(27, "PLGPIO27"),
+ PINCTRL_PIN(28, "PLGPIO28"),
+ PINCTRL_PIN(29, "PLGPIO29"),
+ PINCTRL_PIN(30, "PLGPIO30"),
+ PINCTRL_PIN(31, "PLGPIO31"),
+ PINCTRL_PIN(32, "PLGPIO32"),
+ PINCTRL_PIN(33, "PLGPIO33"),
+ PINCTRL_PIN(34, "PLGPIO34"),
+ PINCTRL_PIN(35, "PLGPIO35"),
+ PINCTRL_PIN(36, "PLGPIO36"),
+ PINCTRL_PIN(37, "PLGPIO37"),
+ PINCTRL_PIN(38, "PLGPIO38"),
+ PINCTRL_PIN(39, "PLGPIO39"),
+ PINCTRL_PIN(40, "PLGPIO40"),
+ PINCTRL_PIN(41, "PLGPIO41"),
+ PINCTRL_PIN(42, "PLGPIO42"),
+ PINCTRL_PIN(43, "PLGPIO43"),
+ PINCTRL_PIN(44, "PLGPIO44"),
+ PINCTRL_PIN(45, "PLGPIO45"),
+ PINCTRL_PIN(46, "PLGPIO46"),
+ PINCTRL_PIN(47, "PLGPIO47"),
+ PINCTRL_PIN(48, "PLGPIO48"),
+ PINCTRL_PIN(49, "PLGPIO49"),
+ PINCTRL_PIN(50, "PLGPIO50"),
+ PINCTRL_PIN(51, "PLGPIO51"),
+ PINCTRL_PIN(52, "PLGPIO52"),
+ PINCTRL_PIN(53, "PLGPIO53"),
+ PINCTRL_PIN(54, "PLGPIO54"),
+ PINCTRL_PIN(55, "PLGPIO55"),
+ PINCTRL_PIN(56, "PLGPIO56"),
+ PINCTRL_PIN(57, "PLGPIO57"),
+ PINCTRL_PIN(58, "PLGPIO58"),
+ PINCTRL_PIN(59, "PLGPIO59"),
+ PINCTRL_PIN(60, "PLGPIO60"),
+ PINCTRL_PIN(61, "PLGPIO61"),
+ PINCTRL_PIN(62, "PLGPIO62"),
+ PINCTRL_PIN(63, "PLGPIO63"),
+ PINCTRL_PIN(64, "PLGPIO64"),
+ PINCTRL_PIN(65, "PLGPIO65"),
+ PINCTRL_PIN(66, "PLGPIO66"),
+ PINCTRL_PIN(67, "PLGPIO67"),
+ PINCTRL_PIN(68, "PLGPIO68"),
+ PINCTRL_PIN(69, "PLGPIO69"),
+ PINCTRL_PIN(70, "PLGPIO70"),
+ PINCTRL_PIN(71, "PLGPIO71"),
+ PINCTRL_PIN(72, "PLGPIO72"),
+ PINCTRL_PIN(73, "PLGPIO73"),
+ PINCTRL_PIN(74, "PLGPIO74"),
+ PINCTRL_PIN(75, "PLGPIO75"),
+ PINCTRL_PIN(76, "PLGPIO76"),
+ PINCTRL_PIN(77, "PLGPIO77"),
+ PINCTRL_PIN(78, "PLGPIO78"),
+ PINCTRL_PIN(79, "PLGPIO79"),
+ PINCTRL_PIN(80, "PLGPIO80"),
+ PINCTRL_PIN(81, "PLGPIO81"),
+ PINCTRL_PIN(82, "PLGPIO82"),
+ PINCTRL_PIN(83, "PLGPIO83"),
+ PINCTRL_PIN(84, "PLGPIO84"),
+ PINCTRL_PIN(85, "PLGPIO85"),
+ PINCTRL_PIN(86, "PLGPIO86"),
+ PINCTRL_PIN(87, "PLGPIO87"),
+ PINCTRL_PIN(88, "PLGPIO88"),
+ PINCTRL_PIN(89, "PLGPIO89"),
+ PINCTRL_PIN(90, "PLGPIO90"),
+ PINCTRL_PIN(91, "PLGPIO91"),
+ PINCTRL_PIN(92, "PLGPIO92"),
+ PINCTRL_PIN(93, "PLGPIO93"),
+ PINCTRL_PIN(94, "PLGPIO94"),
+ PINCTRL_PIN(95, "PLGPIO95"),
+ PINCTRL_PIN(96, "PLGPIO96"),
+ PINCTRL_PIN(97, "PLGPIO97"),
+ PINCTRL_PIN(98, "PLGPIO98"),
+ PINCTRL_PIN(99, "PLGPIO99"),
+ PINCTRL_PIN(100, "PLGPIO100"),
+ PINCTRL_PIN(101, "PLGPIO101"),
+};
+
+/* firda_pins */
+static const unsigned firda_pins[] = { 0, 1 };
+static struct spear_muxreg firda_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_FIRDA_MASK,
+ .val = PMX_FIRDA_MASK,
+ },
+};
+
+static struct spear_modemux firda_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = firda_muxreg,
+ .nmuxregs = ARRAY_SIZE(firda_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_firda_pingroup = {
+ .name = "firda_grp",
+ .pins = firda_pins,
+ .npins = ARRAY_SIZE(firda_pins),
+ .modemuxs = firda_modemux,
+ .nmodemuxs = ARRAY_SIZE(firda_modemux),
+};
+
+static const char *const firda_grps[] = { "firda_grp" };
+struct spear_function spear3xx_firda_function = {
+ .name = "firda",
+ .groups = firda_grps,
+ .ngroups = ARRAY_SIZE(firda_grps),
+};
+
+/* i2c_pins */
+static const unsigned i2c_pins[] = { 4, 5 };
+static struct spear_muxreg i2c_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_I2C_MASK,
+ .val = PMX_I2C_MASK,
+ },
+};
+
+static struct spear_modemux i2c_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = i2c_muxreg,
+ .nmuxregs = ARRAY_SIZE(i2c_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_i2c_pingroup = {
+ .name = "i2c0_grp",
+ .pins = i2c_pins,
+ .npins = ARRAY_SIZE(i2c_pins),
+ .modemuxs = i2c_modemux,
+ .nmodemuxs = ARRAY_SIZE(i2c_modemux),
+};
+
+static const char *const i2c_grps[] = { "i2c0_grp" };
+struct spear_function spear3xx_i2c_function = {
+ .name = "i2c0",
+ .groups = i2c_grps,
+ .ngroups = ARRAY_SIZE(i2c_grps),
+};
+
+/* ssp_cs_pins */
+static const unsigned ssp_cs_pins[] = { 34, 35, 36 };
+static struct spear_muxreg ssp_cs_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_SSP_CS_MASK,
+ .val = PMX_SSP_CS_MASK,
+ },
+};
+
+static struct spear_modemux ssp_cs_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = ssp_cs_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp_cs_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_ssp_cs_pingroup = {
+ .name = "ssp_cs_grp",
+ .pins = ssp_cs_pins,
+ .npins = ARRAY_SIZE(ssp_cs_pins),
+ .modemuxs = ssp_cs_modemux,
+ .nmodemuxs = ARRAY_SIZE(ssp_cs_modemux),
+};
+
+static const char *const ssp_cs_grps[] = { "ssp_cs_grp" };
+struct spear_function spear3xx_ssp_cs_function = {
+ .name = "ssp_cs",
+ .groups = ssp_cs_grps,
+ .ngroups = ARRAY_SIZE(ssp_cs_grps),
+};
+
+/* ssp_pins */
+static const unsigned ssp_pins[] = { 6, 7, 8, 9 };
+static struct spear_muxreg ssp_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_SSP_MASK,
+ .val = PMX_SSP_MASK,
+ },
+};
+
+static struct spear_modemux ssp_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = ssp_muxreg,
+ .nmuxregs = ARRAY_SIZE(ssp_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_ssp_pingroup = {
+ .name = "ssp0_grp",
+ .pins = ssp_pins,
+ .npins = ARRAY_SIZE(ssp_pins),
+ .modemuxs = ssp_modemux,
+ .nmodemuxs = ARRAY_SIZE(ssp_modemux),
+};
+
+static const char *const ssp_grps[] = { "ssp0_grp" };
+struct spear_function spear3xx_ssp_function = {
+ .name = "ssp0",
+ .groups = ssp_grps,
+ .ngroups = ARRAY_SIZE(ssp_grps),
+};
+
+/* mii_pins */
+static const unsigned mii_pins[] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27 };
+static struct spear_muxreg mii_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_MII_MASK,
+ .val = PMX_MII_MASK,
+ },
+};
+
+static struct spear_modemux mii_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = mii_muxreg,
+ .nmuxregs = ARRAY_SIZE(mii_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_mii_pingroup = {
+ .name = "mii0_grp",
+ .pins = mii_pins,
+ .npins = ARRAY_SIZE(mii_pins),
+ .modemuxs = mii_modemux,
+ .nmodemuxs = ARRAY_SIZE(mii_modemux),
+};
+
+static const char *const mii_grps[] = { "mii0_grp" };
+struct spear_function spear3xx_mii_function = {
+ .name = "mii0",
+ .groups = mii_grps,
+ .ngroups = ARRAY_SIZE(mii_grps),
+};
+
+/* gpio0_pin0_pins */
+static const unsigned gpio0_pin0_pins[] = { 28 };
+static struct spear_muxreg gpio0_pin0_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_GPIO_PIN0_MASK,
+ .val = PMX_GPIO_PIN0_MASK,
+ },
+};
+
+static struct spear_modemux gpio0_pin0_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = gpio0_pin0_muxreg,
+ .nmuxregs = ARRAY_SIZE(gpio0_pin0_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_gpio0_pin0_pingroup = {
+ .name = "gpio0_pin0_grp",
+ .pins = gpio0_pin0_pins,
+ .npins = ARRAY_SIZE(gpio0_pin0_pins),
+ .modemuxs = gpio0_pin0_modemux,
+ .nmodemuxs = ARRAY_SIZE(gpio0_pin0_modemux),
+};
+
+/* gpio0_pin1_pins */
+static const unsigned gpio0_pin1_pins[] = { 29 };
+static struct spear_muxreg gpio0_pin1_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_GPIO_PIN1_MASK,
+ .val = PMX_GPIO_PIN1_MASK,
+ },
+};
+
+static struct spear_modemux gpio0_pin1_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = gpio0_pin1_muxreg,
+ .nmuxregs = ARRAY_SIZE(gpio0_pin1_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_gpio0_pin1_pingroup = {
+ .name = "gpio0_pin1_grp",
+ .pins = gpio0_pin1_pins,
+ .npins = ARRAY_SIZE(gpio0_pin1_pins),
+ .modemuxs = gpio0_pin1_modemux,
+ .nmodemuxs = ARRAY_SIZE(gpio0_pin1_modemux),
+};
+
+/* gpio0_pin2_pins */
+static const unsigned gpio0_pin2_pins[] = { 30 };
+static struct spear_muxreg gpio0_pin2_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_GPIO_PIN2_MASK,
+ .val = PMX_GPIO_PIN2_MASK,
+ },
+};
+
+static struct spear_modemux gpio0_pin2_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = gpio0_pin2_muxreg,
+ .nmuxregs = ARRAY_SIZE(gpio0_pin2_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_gpio0_pin2_pingroup = {
+ .name = "gpio0_pin2_grp",
+ .pins = gpio0_pin2_pins,
+ .npins = ARRAY_SIZE(gpio0_pin2_pins),
+ .modemuxs = gpio0_pin2_modemux,
+ .nmodemuxs = ARRAY_SIZE(gpio0_pin2_modemux),
+};
+
+/* gpio0_pin3_pins */
+static const unsigned gpio0_pin3_pins[] = { 31 };
+static struct spear_muxreg gpio0_pin3_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_GPIO_PIN3_MASK,
+ .val = PMX_GPIO_PIN3_MASK,
+ },
+};
+
+static struct spear_modemux gpio0_pin3_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = gpio0_pin3_muxreg,
+ .nmuxregs = ARRAY_SIZE(gpio0_pin3_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_gpio0_pin3_pingroup = {
+ .name = "gpio0_pin3_grp",
+ .pins = gpio0_pin3_pins,
+ .npins = ARRAY_SIZE(gpio0_pin3_pins),
+ .modemuxs = gpio0_pin3_modemux,
+ .nmodemuxs = ARRAY_SIZE(gpio0_pin3_modemux),
+};
+
+/* gpio0_pin4_pins */
+static const unsigned gpio0_pin4_pins[] = { 32 };
+static struct spear_muxreg gpio0_pin4_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_GPIO_PIN4_MASK,
+ .val = PMX_GPIO_PIN4_MASK,
+ },
+};
+
+static struct spear_modemux gpio0_pin4_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = gpio0_pin4_muxreg,
+ .nmuxregs = ARRAY_SIZE(gpio0_pin4_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_gpio0_pin4_pingroup = {
+ .name = "gpio0_pin4_grp",
+ .pins = gpio0_pin4_pins,
+ .npins = ARRAY_SIZE(gpio0_pin4_pins),
+ .modemuxs = gpio0_pin4_modemux,
+ .nmodemuxs = ARRAY_SIZE(gpio0_pin4_modemux),
+};
+
+/* gpio0_pin5_pins */
+static const unsigned gpio0_pin5_pins[] = { 33 };
+static struct spear_muxreg gpio0_pin5_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_GPIO_PIN5_MASK,
+ .val = PMX_GPIO_PIN5_MASK,
+ },
+};
+
+static struct spear_modemux gpio0_pin5_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = gpio0_pin5_muxreg,
+ .nmuxregs = ARRAY_SIZE(gpio0_pin5_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_gpio0_pin5_pingroup = {
+ .name = "gpio0_pin5_grp",
+ .pins = gpio0_pin5_pins,
+ .npins = ARRAY_SIZE(gpio0_pin5_pins),
+ .modemuxs = gpio0_pin5_modemux,
+ .nmodemuxs = ARRAY_SIZE(gpio0_pin5_modemux),
+};
+
+static const char *const gpio0_grps[] = { "gpio0_pin0_grp", "gpio0_pin1_grp",
+ "gpio0_pin2_grp", "gpio0_pin3_grp", "gpio0_pin4_grp", "gpio0_pin5_grp",
+};
+struct spear_function spear3xx_gpio0_function = {
+ .name = "gpio0",
+ .groups = gpio0_grps,
+ .ngroups = ARRAY_SIZE(gpio0_grps),
+};
+
+/* uart0_ext_pins */
+static const unsigned uart0_ext_pins[] = { 37, 38, 39, 40, 41, 42 };
+static struct spear_muxreg uart0_ext_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = PMX_UART0_MODEM_MASK,
+ },
+};
+
+static struct spear_modemux uart0_ext_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = uart0_ext_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart0_ext_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_uart0_ext_pingroup = {
+ .name = "uart0_ext_grp",
+ .pins = uart0_ext_pins,
+ .npins = ARRAY_SIZE(uart0_ext_pins),
+ .modemuxs = uart0_ext_modemux,
+ .nmodemuxs = ARRAY_SIZE(uart0_ext_modemux),
+};
+
+static const char *const uart0_ext_grps[] = { "uart0_ext_grp" };
+struct spear_function spear3xx_uart0_ext_function = {
+ .name = "uart0_ext",
+ .groups = uart0_ext_grps,
+ .ngroups = ARRAY_SIZE(uart0_ext_grps),
+};
+
+/* uart0_pins */
+static const unsigned uart0_pins[] = { 2, 3 };
+static struct spear_muxreg uart0_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_UART0_MASK,
+ .val = PMX_UART0_MASK,
+ },
+};
+
+static struct spear_modemux uart0_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = uart0_muxreg,
+ .nmuxregs = ARRAY_SIZE(uart0_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_uart0_pingroup = {
+ .name = "uart0_grp",
+ .pins = uart0_pins,
+ .npins = ARRAY_SIZE(uart0_pins),
+ .modemuxs = uart0_modemux,
+ .nmodemuxs = ARRAY_SIZE(uart0_modemux),
+};
+
+static const char *const uart0_grps[] = { "uart0_grp" };
+struct spear_function spear3xx_uart0_function = {
+ .name = "uart0",
+ .groups = uart0_grps,
+ .ngroups = ARRAY_SIZE(uart0_grps),
+};
+
+/* timer_0_1_pins */
+static const unsigned timer_0_1_pins[] = { 43, 44, 47, 48 };
+static struct spear_muxreg timer_0_1_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_TIMER_0_1_MASK,
+ .val = PMX_TIMER_0_1_MASK,
+ },
+};
+
+static struct spear_modemux timer_0_1_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = timer_0_1_muxreg,
+ .nmuxregs = ARRAY_SIZE(timer_0_1_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_timer_0_1_pingroup = {
+ .name = "timer_0_1_grp",
+ .pins = timer_0_1_pins,
+ .npins = ARRAY_SIZE(timer_0_1_pins),
+ .modemuxs = timer_0_1_modemux,
+ .nmodemuxs = ARRAY_SIZE(timer_0_1_modemux),
+};
+
+static const char *const timer_0_1_grps[] = { "timer_0_1_grp" };
+struct spear_function spear3xx_timer_0_1_function = {
+ .name = "timer_0_1",
+ .groups = timer_0_1_grps,
+ .ngroups = ARRAY_SIZE(timer_0_1_grps),
+};
+
+/* timer_2_3_pins */
+static const unsigned timer_2_3_pins[] = { 45, 46, 49, 50 };
+static struct spear_muxreg timer_2_3_muxreg[] = {
+ {
+ .reg = -1,
+ .mask = PMX_TIMER_2_3_MASK,
+ .val = PMX_TIMER_2_3_MASK,
+ },
+};
+
+static struct spear_modemux timer_2_3_modemux[] = {
+ {
+ .modes = ~0,
+ .muxregs = timer_2_3_muxreg,
+ .nmuxregs = ARRAY_SIZE(timer_2_3_muxreg),
+ },
+};
+
+struct spear_pingroup spear3xx_timer_2_3_pingroup = {
+ .name = "timer_2_3_grp",
+ .pins = timer_2_3_pins,
+ .npins = ARRAY_SIZE(timer_2_3_pins),
+ .modemuxs = timer_2_3_modemux,
+ .nmodemuxs = ARRAY_SIZE(timer_2_3_modemux),
+};
+
+static const char *const timer_2_3_grps[] = { "timer_2_3_grp" };
+struct spear_function spear3xx_timer_2_3_function = {
+ .name = "timer_2_3",
+ .groups = timer_2_3_grps,
+ .ngroups = ARRAY_SIZE(timer_2_3_grps),
+};
+
+struct spear_pinctrl_machdata spear3xx_machdata = {
+ .pins = spear3xx_pins,
+ .npins = ARRAY_SIZE(spear3xx_pins),
+};
diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.h b/drivers/pinctrl/spear/pinctrl-spear3xx.h
new file mode 100644
index 000000000000..5d5fdd8df7b8
--- /dev/null
+++ b/drivers/pinctrl/spear/pinctrl-spear3xx.h
@@ -0,0 +1,92 @@
+/*
+ * Header file for the ST Microelectronics SPEAr3xx pinmux
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PINMUX_SPEAR3XX_H__
+#define __PINMUX_SPEAR3XX_H__
+
+#include "pinctrl-spear.h"
+
+/* pad mux declarations */
+#define PMX_FIRDA_MASK (1 << 14)
+#define PMX_I2C_MASK (1 << 13)
+#define PMX_SSP_CS_MASK (1 << 12)
+#define PMX_SSP_MASK (1 << 11)
+#define PMX_MII_MASK (1 << 10)
+#define PMX_GPIO_PIN0_MASK (1 << 9)
+#define PMX_GPIO_PIN1_MASK (1 << 8)
+#define PMX_GPIO_PIN2_MASK (1 << 7)
+#define PMX_GPIO_PIN3_MASK (1 << 6)
+#define PMX_GPIO_PIN4_MASK (1 << 5)
+#define PMX_GPIO_PIN5_MASK (1 << 4)
+#define PMX_UART0_MODEM_MASK (1 << 3)
+#define PMX_UART0_MASK (1 << 2)
+#define PMX_TIMER_2_3_MASK (1 << 1)
+#define PMX_TIMER_0_1_MASK (1 << 0)
+
+extern struct spear_pingroup spear3xx_firda_pingroup;
+extern struct spear_pingroup spear3xx_gpio0_pin0_pingroup;
+extern struct spear_pingroup spear3xx_gpio0_pin1_pingroup;
+extern struct spear_pingroup spear3xx_gpio0_pin2_pingroup;
+extern struct spear_pingroup spear3xx_gpio0_pin3_pingroup;
+extern struct spear_pingroup spear3xx_gpio0_pin4_pingroup;
+extern struct spear_pingroup spear3xx_gpio0_pin5_pingroup;
+extern struct spear_pingroup spear3xx_i2c_pingroup;
+extern struct spear_pingroup spear3xx_mii_pingroup;
+extern struct spear_pingroup spear3xx_ssp_cs_pingroup;
+extern struct spear_pingroup spear3xx_ssp_pingroup;
+extern struct spear_pingroup spear3xx_timer_0_1_pingroup;
+extern struct spear_pingroup spear3xx_timer_2_3_pingroup;
+extern struct spear_pingroup spear3xx_uart0_ext_pingroup;
+extern struct spear_pingroup spear3xx_uart0_pingroup;
+
+#define SPEAR3XX_COMMON_PINGROUPS \
+ &spear3xx_firda_pingroup, \
+ &spear3xx_gpio0_pin0_pingroup, \
+ &spear3xx_gpio0_pin1_pingroup, \
+ &spear3xx_gpio0_pin2_pingroup, \
+ &spear3xx_gpio0_pin3_pingroup, \
+ &spear3xx_gpio0_pin4_pingroup, \
+ &spear3xx_gpio0_pin5_pingroup, \
+ &spear3xx_i2c_pingroup, \
+ &spear3xx_mii_pingroup, \
+ &spear3xx_ssp_cs_pingroup, \
+ &spear3xx_ssp_pingroup, \
+ &spear3xx_timer_0_1_pingroup, \
+ &spear3xx_timer_2_3_pingroup, \
+ &spear3xx_uart0_ext_pingroup, \
+ &spear3xx_uart0_pingroup
+
+extern struct spear_function spear3xx_firda_function;
+extern struct spear_function spear3xx_gpio0_function;
+extern struct spear_function spear3xx_i2c_function;
+extern struct spear_function spear3xx_mii_function;
+extern struct spear_function spear3xx_ssp_cs_function;
+extern struct spear_function spear3xx_ssp_function;
+extern struct spear_function spear3xx_timer_0_1_function;
+extern struct spear_function spear3xx_timer_2_3_function;
+extern struct spear_function spear3xx_uart0_ext_function;
+extern struct spear_function spear3xx_uart0_function;
+
+#define SPEAR3XX_COMMON_FUNCTIONS \
+ &spear3xx_firda_function, \
+ &spear3xx_gpio0_function, \
+ &spear3xx_i2c_function, \
+ &spear3xx_mii_function, \
+ &spear3xx_ssp_cs_function, \
+ &spear3xx_ssp_function, \
+ &spear3xx_timer_0_1_function, \
+ &spear3xx_timer_2_3_function, \
+ &spear3xx_uart0_ext_function, \
+ &spear3xx_uart0_function
+
+extern struct spear_pinctrl_machdata spear3xx_machdata;
+
+#endif /* __PINMUX_SPEAR3XX_H__ */
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index 6b26666b37f2..c4c1a5444b38 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -1,7 +1,7 @@
/*-*-linux-c-*-*/
/*
- Copyright (C) 2007,2008 Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
+ Copyright (C) 2007,2008 Jonathan Woithe <jwoithe@just42.net>
Copyright (C) 2008 Peter Gruber <nokos@gmx.net>
Copyright (C) 2008 Tony Vroon <tony@linx.net>
Based on earlier work:
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index 222ccd872ac5..f5d6d379f2fb 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -451,7 +451,7 @@ static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di,
}
/*
- * Return the battery Voltage in milivolts
+ * Return the battery Voltage in millivolts
* Or < 0 if something fails.
*/
static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
index a409fa050a1a..93d0a8b7718a 100644
--- a/drivers/ps3/ps3av.c
+++ b/drivers/ps3/ps3av.c
@@ -338,7 +338,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
mutex_unlock(&ps3av->mutex);
return 0;
- err:
+err:
mutex_unlock(&ps3av->mutex);
printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res);
return res;
@@ -477,7 +477,6 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
return 0;
}
-
EXPORT_SYMBOL_GPL(ps3av_set_audio_mode);
static int ps3av_set_videomode(void)
@@ -501,7 +500,7 @@ static void ps3av_set_videomode_packet(u32 id)
video_mode = &video_mode_table[id & PS3AV_MODE_MASK];
- avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */
+ avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */
avb_param.num_of_audio_pkt = 0;
avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi +
ps3av->av_hw_conf.num_of_avmulti;
@@ -521,7 +520,7 @@ static void ps3av_set_videomode_packet(u32 id)
#ifndef PS3AV_HDMI_YUV
if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
- av_video_cs = RGB8; /* use RGB for HDMI */
+ av_video_cs = RGB8; /* use RGB for HDMI */
#endif
len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len],
ps3av->av_port[i],
@@ -590,8 +589,8 @@ static void ps3avd(struct work_struct *work)
#define SHIFT_VESA 8
static const struct {
- unsigned mask : 19;
- unsigned id : 4;
+ unsigned mask:19;
+ unsigned id:4;
} ps3av_preferred_modes[] = {
{ PS3AV_RESBIT_WUXGA << SHIFT_VESA, PS3AV_MODE_WUXGA },
{ PS3AV_RESBIT_1920x1080P << SHIFT_60, PS3AV_MODE_1080P60 },
@@ -667,7 +666,8 @@ static enum ps3av_mode_num ps3av_hdmi_get_id(struct ps3av_info_monitor *info)
return id;
}
-static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info)
+static void ps3av_monitor_info_dump(
+ const struct ps3av_pkt_av_get_monitor_info *monitor_info)
{
const struct ps3av_info_monitor *info = &monitor_info->info;
const struct ps3av_info_audio *audio = info->audio;
@@ -717,8 +717,8 @@ static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *
/* audio block */
for (i = 0; i < info->num_of_audio_block; i++) {
- pr_debug("audio[%d] type: %02x max_ch: %02x fs: %02x sbit: "
- "%02x\n",
+ pr_debug(
+ "audio[%d] type: %02x max_ch: %02x fs: %02x sbit: %02x\n",
i, audio->type, audio->max_num_of_ch, audio->fs,
audio->sbit);
audio++;
@@ -870,21 +870,18 @@ int ps3av_set_video_mode(int id)
return 0;
}
-
EXPORT_SYMBOL_GPL(ps3av_set_video_mode);
int ps3av_get_auto_mode(void)
{
return ps3av_auto_videomode(&ps3av->av_hw_conf);
}
-
EXPORT_SYMBOL_GPL(ps3av_get_auto_mode);
int ps3av_get_mode(void)
{
return ps3av ? ps3av->ps3av_mode : 0;
}
-
EXPORT_SYMBOL_GPL(ps3av_get_mode);
/* get resolution by video_mode */
@@ -902,7 +899,6 @@ int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres)
*yres = video_mode_table[id].y;
return 0;
}
-
EXPORT_SYMBOL_GPL(ps3av_video_mode2res);
/* mute */
@@ -911,7 +907,6 @@ int ps3av_video_mute(int mute)
return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON
: PS3AV_CMD_MUTE_OFF);
}
-
EXPORT_SYMBOL_GPL(ps3av_video_mute);
/* mute analog output only */
@@ -935,7 +930,6 @@ int ps3av_audio_mute(int mute)
return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON
: PS3AV_CMD_MUTE_OFF);
}
-
EXPORT_SYMBOL_GPL(ps3av_audio_mute);
static int __devinit ps3av_probe(struct ps3_system_bus_device *dev)
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index 5648dad71fb3..ffdf712f9a67 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -70,7 +70,7 @@ config DP83640_PHY
using the SO_TIMESTAMPING API.
In order for this to work, your MAC driver must also
- implement the skb_tx_timetamp() function.
+ implement the skb_tx_timestamp() function.
config PTP_1588_CLOCK_PCH
tristate "Intel PCH EG20T as PTP clock"
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index 28b81ae4cf7f..c3482b954cb7 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -27,13 +27,8 @@ struct pm8607_regulator_info {
unsigned int *vol_table;
unsigned int *vol_suspend;
- int vol_reg;
- int vol_shift;
- int vol_nbits;
int update_reg;
int update_bit;
- int enable_reg;
- int enable_bit;
int slope_double;
};
@@ -216,7 +211,7 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
int ret = -EINVAL;
- if (info->vol_table && (index < (1 << info->vol_nbits))) {
+ if (info->vol_table && (index < rdev->desc->n_voltages)) {
ret = info->vol_table[index];
if (info->slope_double)
ret <<= 1;
@@ -224,51 +219,16 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
return ret;
}
-static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
+static int pm8607_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
{
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
- int i, ret = -ENOENT;
-
- if (info->slope_double) {
- min_uV = min_uV >> 1;
- max_uV = max_uV >> 1;
- }
- if (info->vol_table) {
- for (i = 0; i < (1 << info->vol_nbits); i++) {
- if (!info->vol_table[i])
- break;
- if ((min_uV <= info->vol_table[i])
- && (max_uV >= info->vol_table[i])) {
- ret = i;
- break;
- }
- }
- }
- if (ret < 0)
- pr_err("invalid voltage range (%d %d) uV\n", min_uV, max_uV);
- return ret;
-}
-
-static int pm8607_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *selector)
-{
- struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
- uint8_t val, mask;
+ uint8_t val;
int ret;
- if (min_uV > max_uV) {
- pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
- return -EINVAL;
- }
+ val = (uint8_t)(selector << (ffs(rdev->desc->vsel_mask) - 1));
- ret = choose_voltage(rdev, min_uV, max_uV);
- if (ret < 0)
- return -EINVAL;
- *selector = ret;
- val = (uint8_t)(ret << info->vol_shift);
- mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
-
- ret = pm860x_set_bits(info->i2c, info->vol_reg, mask, val);
+ ret = pm860x_set_bits(info->i2c, rdev->desc->vsel_reg,
+ rdev->desc->vsel_mask, val);
if (ret)
return ret;
switch (info->desc.id) {
@@ -282,60 +242,16 @@ static int pm8607_set_voltage(struct regulator_dev *rdev,
return ret;
}
-static int pm8607_get_voltage(struct regulator_dev *rdev)
-{
- struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
- uint8_t val, mask;
- int ret;
-
- ret = pm860x_reg_read(info->i2c, info->vol_reg);
- if (ret < 0)
- return ret;
-
- mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
- val = ((unsigned char)ret & mask) >> info->vol_shift;
-
- return pm8607_list_voltage(rdev, val);
-}
-
-static int pm8607_enable(struct regulator_dev *rdev)
-{
- struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
-
- return pm860x_set_bits(info->i2c, info->enable_reg,
- 1 << info->enable_bit,
- 1 << info->enable_bit);
-}
-
-static int pm8607_disable(struct regulator_dev *rdev)
-{
- struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
-
- return pm860x_set_bits(info->i2c, info->enable_reg,
- 1 << info->enable_bit, 0);
-}
-
-static int pm8607_is_enabled(struct regulator_dev *rdev)
-{
- struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
- int ret;
-
- ret = pm860x_reg_read(info->i2c, info->enable_reg);
- if (ret < 0)
- return ret;
-
- return !!((unsigned char)ret & (1 << info->enable_bit));
-}
-
static struct regulator_ops pm8607_regulator_ops = {
- .set_voltage = pm8607_set_voltage,
- .get_voltage = pm8607_get_voltage,
- .enable = pm8607_enable,
- .disable = pm8607_disable,
- .is_enabled = pm8607_is_enabled,
+ .list_voltage = pm8607_list_voltage,
+ .set_voltage_sel = pm8607_set_voltage_sel,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
};
-#define PM8607_DVC(vreg, nbits, ureg, ubit, ereg, ebit) \
+#define PM8607_DVC(vreg, ureg, ubit, ereg, ebit) \
{ \
.desc = { \
.name = #vreg, \
@@ -343,20 +259,20 @@ static struct regulator_ops pm8607_regulator_ops = {
.type = REGULATOR_VOLTAGE, \
.id = PM8607_ID_##vreg, \
.owner = THIS_MODULE, \
+ .n_voltages = ARRAY_SIZE(vreg##_table), \
+ .vsel_reg = PM8607_##vreg, \
+ .vsel_mask = ARRAY_SIZE(vreg##_table) - 1, \
+ .enable_reg = PM8607_##ereg, \
+ .enable_mask = 1 << (ebit), \
}, \
- .vol_reg = PM8607_##vreg, \
- .vol_shift = (0), \
- .vol_nbits = (nbits), \
.update_reg = PM8607_##ureg, \
.update_bit = (ubit), \
- .enable_reg = PM8607_##ereg, \
- .enable_bit = (ebit), \
.slope_double = (0), \
.vol_table = (unsigned int *)&vreg##_table, \
.vol_suspend = (unsigned int *)&vreg##_suspend_table, \
}
-#define PM8607_LDO(_id, vreg, shift, nbits, ereg, ebit) \
+#define PM8607_LDO(_id, vreg, shift, ereg, ebit) \
{ \
.desc = { \
.name = "LDO" #_id, \
@@ -364,35 +280,35 @@ static struct regulator_ops pm8607_regulator_ops = {
.type = REGULATOR_VOLTAGE, \
.id = PM8607_ID_LDO##_id, \
.owner = THIS_MODULE, \
+ .n_voltages = ARRAY_SIZE(LDO##_id##_table), \
+ .vsel_reg = PM8607_##vreg, \
+ .vsel_mask = (ARRAY_SIZE(LDO##_id##_table) - 1) << (shift), \
+ .enable_reg = PM8607_##ereg, \
+ .enable_mask = 1 << (ebit), \
}, \
- .vol_reg = PM8607_##vreg, \
- .vol_shift = (shift), \
- .vol_nbits = (nbits), \
- .enable_reg = PM8607_##ereg, \
- .enable_bit = (ebit), \
.slope_double = (0), \
.vol_table = (unsigned int *)&LDO##_id##_table, \
.vol_suspend = (unsigned int *)&LDO##_id##_suspend_table, \
}
static struct pm8607_regulator_info pm8607_regulator_info[] = {
- PM8607_DVC(BUCK1, 6, GO, 0, SUPPLIES_EN11, 0),
- PM8607_DVC(BUCK2, 6, GO, 1, SUPPLIES_EN11, 1),
- PM8607_DVC(BUCK3, 6, GO, 2, SUPPLIES_EN11, 2),
-
- PM8607_LDO( 1, LDO1, 0, 2, SUPPLIES_EN11, 3),
- PM8607_LDO( 2, LDO2, 0, 3, SUPPLIES_EN11, 4),
- PM8607_LDO( 3, LDO3, 0, 3, SUPPLIES_EN11, 5),
- PM8607_LDO( 4, LDO4, 0, 3, SUPPLIES_EN11, 6),
- PM8607_LDO( 5, LDO5, 0, 2, SUPPLIES_EN11, 7),
- PM8607_LDO( 6, LDO6, 0, 3, SUPPLIES_EN12, 0),
- PM8607_LDO( 7, LDO7, 0, 3, SUPPLIES_EN12, 1),
- PM8607_LDO( 8, LDO8, 0, 3, SUPPLIES_EN12, 2),
- PM8607_LDO( 9, LDO9, 0, 3, SUPPLIES_EN12, 3),
- PM8607_LDO(10, LDO10, 0, 4, SUPPLIES_EN12, 4),
- PM8607_LDO(12, LDO12, 0, 4, SUPPLIES_EN12, 5),
- PM8607_LDO(13, VIBRATOR_SET, 1, 3, VIBRATOR_SET, 0),
- PM8607_LDO(14, LDO14, 0, 3, SUPPLIES_EN12, 6),
+ PM8607_DVC(BUCK1, GO, 0, SUPPLIES_EN11, 0),
+ PM8607_DVC(BUCK2, GO, 1, SUPPLIES_EN11, 1),
+ PM8607_DVC(BUCK3, GO, 2, SUPPLIES_EN11, 2),
+
+ PM8607_LDO(1, LDO1, 0, SUPPLIES_EN11, 3),
+ PM8607_LDO(2, LDO2, 0, SUPPLIES_EN11, 4),
+ PM8607_LDO(3, LDO3, 0, SUPPLIES_EN11, 5),
+ PM8607_LDO(4, LDO4, 0, SUPPLIES_EN11, 6),
+ PM8607_LDO(5, LDO5, 0, SUPPLIES_EN11, 7),
+ PM8607_LDO(6, LDO6, 0, SUPPLIES_EN12, 0),
+ PM8607_LDO(7, LDO7, 0, SUPPLIES_EN12, 1),
+ PM8607_LDO(8, LDO8, 0, SUPPLIES_EN12, 2),
+ PM8607_LDO(9, LDO9, 0, SUPPLIES_EN12, 3),
+ PM8607_LDO(10, LDO10, 0, SUPPLIES_EN12, 4),
+ PM8607_LDO(12, LDO12, 0, SUPPLIES_EN12, 5),
+ PM8607_LDO(13, VIBRATOR_SET, 1, VIBRATOR_SET, 0),
+ PM8607_LDO(14, LDO14, 0, SUPPLIES_EN12, 6),
};
static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
@@ -400,6 +316,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm8607_regulator_info *info = NULL;
struct regulator_init_data *pdata = pdev->dev.platform_data;
+ struct regulator_config config = { };
struct resource *res;
int i;
@@ -425,9 +342,17 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double)
info->slope_double = 1;
+ config.dev = &pdev->dev;
+ config.init_data = pdata;
+ config.driver_data = info;
+
+ if (chip->id == CHIP_PM8607)
+ config.regmap = chip->regmap;
+ else
+ config.regmap = chip->regmap_companion;
+
/* replace driver_data with info */
- info->regulator = regulator_register(&info->desc, &pdev->dev,
- pdata, info, NULL);
+ info->regulator = regulator_register(&info->desc, &config);
if (IS_ERR(info->regulator)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
info->desc.name);
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 36db5a441eba..c86b8864e411 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -223,6 +223,16 @@ config REGULATOR_PCF50633
Say Y here to support the voltage regulators and convertors
on PCF50633
+config REGULATOR_RC5T583
+ tristate "RICOH RC5T583 Power regulators"
+ depends on MFD_RC5T583
+ help
+ Select this option to enable the power regulator of RICOH
+ PMIC RC5T583.
+ This driver supports the control of different power rails of device
+ through regulator interface. The device supports multiple DCDC/LDO
+ outputs which can be controlled by i2c communication.
+
config REGULATOR_S5M8767
tristate "Samsung S5M8767A voltage regulator"
depends on MFD_S5M_CORE
@@ -258,6 +268,18 @@ config REGULATOR_DB8500_PRCMU
This driver supports the voltage domain regulators controlled by the
DB8500 PRCMU
+config REGULATOR_PALMAS
+ tristate "TI Palmas PMIC Regulators"
+ depends on MFD_PALMAS
+ help
+ If you wish to control the regulators on the Palmas series of
+ chips say Y here. This will enable support for all the software
+ controllable SMPS/LDO regulators.
+
+ The regulators available on Palmas series chips vary depending
+ on the muxing. This is handled automatically in the driver by
+ reading the mux info from OTP.
+
config REGULATOR_TPS6105X
tristate "TI TPS6105X Power regulators"
depends on TPS6105X
@@ -268,11 +290,11 @@ config REGULATOR_TPS6105X
audio amplifiers.
config REGULATOR_TPS62360
- tristate "TI TPS62360 Power Regulator"
+ tristate "TI TPS6236x Power Regulator"
depends on I2C
select REGMAP_I2C
help
- This driver supports TPS62360 voltage regulator chip. This
+ This driver supports TPS6236x voltage regulator chip. This
regulator is meant for processor core supply. This chip is
high-frequency synchronous step down dc-dc converter optimized
for battery-powered portable applications.
@@ -294,6 +316,13 @@ config REGULATOR_TPS6507X
three step-down converters and two general-purpose LDO voltage regulators.
It supports TI's software based Class-2 SmartReflex implementation.
+config REGULATOR_TPS65090
+ tristate "TI TPS65090 Power regulator"
+ depends on MFD_TPS65090
+ help
+ This driver provides support for the voltage regulators on the
+ TI TPS65090 PMIC.
+
config REGULATOR_TPS65217
tristate "TI TPS65217 Power regulators"
depends on MFD_TPS65217
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 94b52745e957..977fd46909ab 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
-obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
@@ -20,6 +19,7 @@ obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
+obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o
@@ -33,13 +33,16 @@ obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
+obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
+obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
+obj-$(CONFIG_REGULATOR_TPS65090) += tps65090-regulator.o
obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o
obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c
index 9ed5c5d84e12..06776ca945f2 100644
--- a/drivers/regulator/aat2870-regulator.c
+++ b/drivers/regulator/aat2870-regulator.c
@@ -24,7 +24,6 @@
#include <linux/err.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
@@ -178,6 +177,7 @@ static struct aat2870_regulator *aat2870_get_regulator(int id)
static int aat2870_regulator_probe(struct platform_device *pdev)
{
struct aat2870_regulator *ri;
+ struct regulator_config config = { 0 };
struct regulator_dev *rdev;
ri = aat2870_get_regulator(pdev->id);
@@ -187,8 +187,11 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
}
ri->aat2870 = dev_get_drvdata(pdev->dev.parent);
- rdev = regulator_register(&ri->desc, &pdev->dev,
- pdev->dev.platform_data, ri, NULL);
+ config.dev = &pdev->dev;
+ config.driver_data = ri;
+ config.init_data = pdev->dev.platform_data;
+
+ rdev = regulator_register(&ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "Failed to register regulator %s\n",
ri->desc.name);
@@ -231,3 +234,4 @@ module_exit(aat2870_regulator_exit);
MODULE_DESCRIPTION("AnalogicTech AAT2870 Regulator");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");
+MODULE_ALIAS("platform:aat2870-regulator");
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
index 042271aace6a..03f4d9c604ec 100644
--- a/drivers/regulator/ab3100.c
+++ b/drivers/regulator/ab3100.c
@@ -13,7 +13,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
-#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/mfd/abx500.h>
@@ -305,53 +304,12 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg)
return abreg->typ_voltages[regval];
}
-static int ab3100_get_best_voltage_index(struct regulator_dev *reg,
- int min_uV, int max_uV)
-{
- struct ab3100_regulator *abreg = reg->reg_data;
- int i;
- int bestmatch;
- int bestindex;
-
- /*
- * Locate the minimum voltage fitting the criteria on
- * this regulator. The switchable voltages are not
- * in strict falling order so we need to check them
- * all for the best match.
- */
- bestmatch = INT_MAX;
- bestindex = -1;
- for (i = 0; i < abreg->voltages_len; i++) {
- if (abreg->typ_voltages[i] <= max_uV &&
- abreg->typ_voltages[i] >= min_uV &&
- abreg->typ_voltages[i] < bestmatch) {
- bestmatch = abreg->typ_voltages[i];
- bestindex = i;
- }
- }
-
- if (bestindex < 0) {
- dev_warn(&reg->dev, "requested %d<=x<=%d uV, out of range!\n",
- min_uV, max_uV);
- return -EINVAL;
- }
- return bestindex;
-}
-
-static int ab3100_set_voltage_regulator(struct regulator_dev *reg,
- int min_uV, int max_uV,
- unsigned *selector)
+static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg,
+ unsigned selector)
{
struct ab3100_regulator *abreg = reg->reg_data;
u8 regval;
int err;
- int bestindex;
-
- bestindex = ab3100_get_best_voltage_index(reg, min_uV, max_uV);
- if (bestindex < 0)
- return bestindex;
-
- *selector = bestindex;
err = abx500_get_register_interruptible(abreg->dev, 0,
abreg->regreg, &regval);
@@ -364,7 +322,7 @@ static int ab3100_set_voltage_regulator(struct regulator_dev *reg,
/* The highest three bits control the variable regulators */
regval &= ~0xE0;
- regval |= (bestindex << 5);
+ regval |= (selector << 5);
err = abx500_set_register_interruptible(abreg->dev, 0,
abreg->regreg, regval);
@@ -392,7 +350,7 @@ static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,
return -EINVAL;
/* LDO E and BUCK have special suspend voltages you can set */
- bestindex = ab3100_get_best_voltage_index(reg, uV, uV);
+ bestindex = regulator_map_voltage_iterate(reg, uV, uV);
err = abx500_get_register_interruptible(abreg->dev, 0,
targetreg, &regval);
@@ -464,7 +422,7 @@ static struct regulator_ops regulator_ops_variable = {
.disable = ab3100_disable_regulator,
.is_enabled = ab3100_is_enabled_regulator,
.get_voltage = ab3100_get_voltage_regulator,
- .set_voltage = ab3100_set_voltage_regulator,
+ .set_voltage_sel = ab3100_set_voltage_regulator_sel,
.list_voltage = ab3100_list_voltage_regulator,
.enable_time = ab3100_enable_time_regulator,
};
@@ -474,7 +432,7 @@ static struct regulator_ops regulator_ops_variable_sleepable = {
.disable = ab3100_disable_regulator,
.is_enabled = ab3100_is_enabled_regulator,
.get_voltage = ab3100_get_voltage_regulator,
- .set_voltage = ab3100_set_voltage_regulator,
+ .set_voltage_sel = ab3100_set_voltage_regulator_sel,
.set_suspend_voltage = ab3100_set_suspend_voltage_regulator,
.list_voltage = ab3100_list_voltage_regulator,
.enable_time = ab3100_enable_time_regulator,
@@ -582,6 +540,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
{
struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
+ struct regulator_config config = { };
int err = 0;
u8 data;
int i;
@@ -627,15 +586,15 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
reg->dev = &pdev->dev;
reg->plfdata = plfdata;
+ config.dev = &pdev->dev;
+ config.driver_data = reg;
+ config.init_data = &plfdata->reg_constraints[i];
+
/*
* Register the regulator, pass around
* the ab3100_regulator struct
*/
- rdev = regulator_register(&ab3100_regulator_desc[i],
- &pdev->dev,
- &plfdata->reg_constraints[i],
- reg, NULL);
-
+ rdev = regulator_register(&ab3100_regulator_desc[i], &config);
if (IS_ERR(rdev)) {
err = PTR_ERR(rdev);
dev_err(&pdev->dev,
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
index c7ee4c15d6f5..e1b8c54ace5a 100644
--- a/drivers/regulator/ab8500.c
+++ b/drivers/regulator/ab8500.c
@@ -18,9 +18,12 @@
#include <linux/platform_device.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
+#include <linux/of.h>
+#include <linux/regulator/of_regulator.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/ab8500.h>
+#include <linux/slab.h>
/**
* struct ab8500_regulator_info - ab8500 regulator information
@@ -234,25 +237,8 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev)
return val;
}
-static int ab8500_get_best_voltage_index(struct regulator_dev *rdev,
- int min_uV, int max_uV)
-{
- struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
- int i;
-
- /* check the supported voltage */
- for (i = 0; i < info->voltages_len; i++) {
- if ((info->voltages[i] >= min_uV) &&
- (info->voltages[i] <= max_uV))
- return i;
- }
-
- return -EINVAL;
-}
-
-static int ab8500_regulator_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV,
- unsigned *selector)
+static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned selector)
{
int ret;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
@@ -263,18 +249,8 @@ static int ab8500_regulator_set_voltage(struct regulator_dev *rdev,
return -EINVAL;
}
- /* get the appropriate voltages within the range */
- ret = ab8500_get_best_voltage_index(rdev, min_uV, max_uV);
- if (ret < 0) {
- dev_err(rdev_get_dev(rdev),
- "couldn't get best voltage for regulator\n");
- return ret;
- }
-
- *selector = ret;
-
/* set the registers for the request */
- regval = (u8)ret;
+ regval = (u8)selector;
ret = abx500_mask_and_set_register_interruptible(info->dev,
info->voltage_bank, info->voltage_reg,
info->voltage_mask, regval);
@@ -319,7 +295,7 @@ static struct regulator_ops ab8500_regulator_ops = {
.disable = ab8500_regulator_disable,
.is_enabled = ab8500_regulator_is_enabled,
.get_voltage_sel = ab8500_regulator_get_voltage_sel,
- .set_voltage = ab8500_regulator_set_voltage,
+ .set_voltage_sel = ab8500_regulator_set_voltage_sel,
.list_voltage = ab8500_list_voltage,
.enable_time = ab8500_regulator_enable_time,
.set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
@@ -735,12 +711,139 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
REG_INIT(AB8500_REGUCTRLDISCH2, 0x04, 0x44, 0x16),
};
+static __devinit int
+ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
+{
+ int err;
+
+ if (value & ~ab8500_reg_init[id].mask) {
+ dev_err(&pdev->dev,
+ "Configuration error: value outside mask.\n");
+ return -EINVAL;
+ }
+
+ err = abx500_mask_and_set_register_interruptible(
+ &pdev->dev,
+ ab8500_reg_init[id].bank,
+ ab8500_reg_init[id].addr,
+ ab8500_reg_init[id].mask,
+ value);
+ if (err < 0) {
+ dev_err(&pdev->dev,
+ "Failed to initialize 0x%02x, 0x%02x.\n",
+ ab8500_reg_init[id].bank,
+ ab8500_reg_init[id].addr);
+ return err;
+ }
+
+ dev_vdbg(&pdev->dev,
+ "init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
+ ab8500_reg_init[id].bank,
+ ab8500_reg_init[id].addr,
+ ab8500_reg_init[id].mask,
+ value);
+
+ return 0;
+}
+
+static __devinit int ab8500_regulator_register(struct platform_device *pdev,
+ struct regulator_init_data *init_data,
+ int id,
+ struct device_node *np)
+{
+ struct ab8500_regulator_info *info = NULL;
+ struct regulator_config config = { };
+ int err;
+
+ /* assign per-regulator data */
+ info = &ab8500_regulator_info[id];
+ info->dev = &pdev->dev;
+
+ config.dev = &pdev->dev;
+ config.init_data = init_data;
+ config.driver_data = info;
+ config.of_node = np;
+
+ /* fix for hardware before ab8500v2.0 */
+ if (abx500_get_chip_id(info->dev) < 0x20) {
+ if (info->desc.id == AB8500_LDO_AUX3) {
+ info->desc.n_voltages =
+ ARRAY_SIZE(ldo_vauxn_voltages);
+ info->voltages = ldo_vauxn_voltages;
+ info->voltages_len =
+ ARRAY_SIZE(ldo_vauxn_voltages);
+ info->voltage_mask = 0xf;
+ }
+ }
+
+ /* register regulator with framework */
+ info->regulator = regulator_register(&info->desc, &config);
+ if (IS_ERR(info->regulator)) {
+ err = PTR_ERR(info->regulator);
+ dev_err(&pdev->dev, "failed to register regulator %s\n",
+ info->desc.name);
+ /* when we fail, un-register all earlier regulators */
+ while (--id >= 0) {
+ info = &ab8500_regulator_info[id];
+ regulator_unregister(info->regulator);
+ }
+ return err;
+ }
+
+ return 0;
+}
+
+static struct of_regulator_match ab8500_regulator_matches[] = {
+ { .name = "LDO-AUX1", .driver_data = (void *) AB8500_LDO_AUX1, },
+ { .name = "LDO-AUX2", .driver_data = (void *) AB8500_LDO_AUX2, },
+ { .name = "LDO-AUX3", .driver_data = (void *) AB8500_LDO_AUX3, },
+ { .name = "LDO-INTCORE", .driver_data = (void *) AB8500_LDO_INTCORE, },
+ { .name = "LDO-TVOUT", .driver_data = (void *) AB8500_LDO_TVOUT, },
+ { .name = "LDO-USB", .driver_data = (void *) AB8500_LDO_USB, },
+ { .name = "LDO-AUDIO", .driver_data = (void *) AB8500_LDO_AUDIO, },
+ { .name = "LDO-ANAMIC1", .driver_data = (void *) AB8500_LDO_ANAMIC1, },
+ { .name = "LDO-ANAMIC2", .driver_data = (void *) AB8500_LDO_ANAMIC2, },
+ { .name = "LDO-DMIC", .driver_data = (void *) AB8500_LDO_DMIC, },
+ { .name = "LDO-ANA", .driver_data = (void *) AB8500_LDO_ANA, },
+};
+
+static __devinit int
+ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
+{
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
+ err = ab8500_regulator_register(
+ pdev, ab8500_regulator_matches[i].init_data,
+ i, ab8500_regulator_matches[i].of_node);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
{
struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
struct ab8500_platform_data *pdata;
+ struct device_node *np = pdev->dev.of_node;
int i, err;
+ if (np) {
+ err = of_regulator_match(&pdev->dev, np,
+ ab8500_regulator_matches,
+ ARRAY_SIZE(ab8500_regulator_matches));
+ if (err < 0) {
+ dev_err(&pdev->dev,
+ "Error parsing regulator init data: %d\n", err);
+ return err;
+ }
+
+ err = ab8500_regulator_of_probe(pdev, np);
+ return err;
+ }
+
if (!ab8500) {
dev_err(&pdev->dev, "null mfd parent\n");
return -EINVAL;
@@ -759,8 +862,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
/* initialize registers */
for (i = 0; i < pdata->num_regulator_reg_init; i++) {
- int id;
- u8 value;
+ int id, value;
id = pdata->regulator_reg_init[i].id;
value = pdata->regulator_reg_init[i].value;
@@ -771,70 +873,17 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
"Configuration error: id outside range.\n");
return -EINVAL;
}
- if (value & ~ab8500_reg_init[id].mask) {
- dev_err(&pdev->dev,
- "Configuration error: value outside mask.\n");
- return -EINVAL;
- }
- /* initialize register */
- err = abx500_mask_and_set_register_interruptible(&pdev->dev,
- ab8500_reg_init[id].bank,
- ab8500_reg_init[id].addr,
- ab8500_reg_init[id].mask,
- value);
- if (err < 0) {
- dev_err(&pdev->dev,
- "Failed to initialize 0x%02x, 0x%02x.\n",
- ab8500_reg_init[id].bank,
- ab8500_reg_init[id].addr);
+ err = ab8500_regulator_init_registers(pdev, id, value);
+ if (err < 0)
return err;
- }
- dev_vdbg(&pdev->dev,
- " init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
- ab8500_reg_init[id].bank,
- ab8500_reg_init[id].addr,
- ab8500_reg_init[id].mask,
- value);
}
/* register all regulators */
for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
- struct ab8500_regulator_info *info = NULL;
-
- /* assign per-regulator data */
- info = &ab8500_regulator_info[i];
- info->dev = &pdev->dev;
-
- /* fix for hardware before ab8500v2.0 */
- if (abx500_get_chip_id(info->dev) < 0x20) {
- if (info->desc.id == AB8500_LDO_AUX3) {
- info->desc.n_voltages =
- ARRAY_SIZE(ldo_vauxn_voltages);
- info->voltages = ldo_vauxn_voltages;
- info->voltages_len =
- ARRAY_SIZE(ldo_vauxn_voltages);
- info->voltage_mask = 0xf;
- }
- }
-
- /* register regulator with framework */
- info->regulator = regulator_register(&info->desc, &pdev->dev,
- &pdata->regulator[i], info, NULL);
- if (IS_ERR(info->regulator)) {
- err = PTR_ERR(info->regulator);
- dev_err(&pdev->dev, "failed to register regulator %s\n",
- info->desc.name);
- /* when we fail, un-register all earlier regulators */
- while (--i >= 0) {
- info = &ab8500_regulator_info[i];
- regulator_unregister(info->regulator);
- }
+ err = ab8500_regulator_register(pdev, &pdata->regulator[i], i, NULL);
+ if (err < 0)
return err;
- }
-
- dev_vdbg(rdev_get_dev(info->regulator),
- "%s-probed\n", info->desc.name);
}
return 0;
@@ -857,12 +906,18 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id ab8500_regulator_match[] = {
+ { .compatible = "stericsson,ab8500-regulator", },
+ {}
+};
+
static struct platform_driver ab8500_regulator_driver = {
.probe = ab8500_regulator_probe,
.remove = __devexit_p(ab8500_regulator_remove),
.driver = {
.name = "ab8500-regulator",
.owner = THIS_MODULE,
+ .of_match_table = ab8500_regulator_match,
},
};
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
index 26d23adfc66f..46d05f38baf8 100644
--- a/drivers/regulator/ad5398.c
+++ b/drivers/regulator/ad5398.c
@@ -99,8 +99,8 @@ static int ad5398_set_current_limit(struct regulator_dev *rdev, int min_uA, int
if (ad5398_calc_current(chip, selector) > max_uA)
return -EINVAL;
- dev_dbg(&client->dev, "changing current %dmA\n",
- ad5398_calc_current(chip, selector) / 1000);
+ dev_dbg(&client->dev, "changing current %duA\n",
+ ad5398_calc_current(chip, selector));
/* read chip enable bit */
ret = ad5398_read_reg(client, &data);
@@ -184,7 +184,7 @@ static struct regulator_ops ad5398_ops = {
.is_enabled = ad5398_is_enabled,
};
-static struct regulator_desc ad5398_reg = {
+static const struct regulator_desc ad5398_reg = {
.name = "isink",
.id = 0,
.ops = &ad5398_ops,
@@ -212,6 +212,7 @@ static int __devinit ad5398_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regulator_init_data *init_data = client->dev.platform_data;
+ struct regulator_config config = { };
struct ad5398_chip_info *chip;
const struct ad5398_current_data_format *df =
(struct ad5398_current_data_format *)id->driver_data;
@@ -220,10 +221,14 @@ static int __devinit ad5398_probe(struct i2c_client *client,
if (!init_data)
return -EINVAL;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
+ config.dev = &client->dev;
+ config.init_data = init_data;
+ config.driver_data = chip;
+
chip->client = client;
chip->min_uA = df->min_uA;
@@ -232,8 +237,7 @@ static int __devinit ad5398_probe(struct i2c_client *client,
chip->current_offset = df->current_offset;
chip->current_mask = (chip->current_level - 1) << chip->current_offset;
- chip->rdev = regulator_register(&ad5398_reg, &client->dev,
- init_data, chip, NULL);
+ chip->rdev = regulator_register(&ad5398_reg, &config);
if (IS_ERR(chip->rdev)) {
ret = PTR_ERR(chip->rdev);
dev_err(&client->dev, "failed to register %s %s\n",
@@ -246,7 +250,6 @@ static int __devinit ad5398_probe(struct i2c_client *client,
return 0;
err:
- kfree(chip);
return ret;
}
@@ -255,8 +258,6 @@ static int __devexit ad5398_remove(struct i2c_client *client)
struct ad5398_chip_info *chip = i2c_get_clientdata(client);
regulator_unregister(chip->rdev);
- kfree(chip);
-
return 0;
}
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 81fd606e47bc..49b2112b0486 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -122,6 +122,7 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
struct anatop_regulator *sreg;
struct regulator_init_data *initdata;
struct anatop *anatopmfd = dev_get_drvdata(pdev->dev.parent);
+ struct regulator_config config = { };
int ret = 0;
initdata = of_get_regulator_init_data(dev, np);
@@ -178,9 +179,13 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage)
/ 25000 + 1;
+ config.dev = &pdev->dev;
+ config.init_data = initdata;
+ config.driver_data = sreg;
+ config.of_node = pdev->dev.of_node;
+
/* register regulator */
- rdev = regulator_register(rdesc, dev,
- initdata, sreg, pdev->dev.of_node);
+ rdev = regulator_register(rdesc, &config);
if (IS_ERR(rdev)) {
dev_err(dev, "failed to register %s\n",
rdesc->name);
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 046fb1bd8619..7584a74eec8a 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -24,6 +24,7 @@
#include <linux/suspend.h>
#include <linux/delay.h>
#include <linux/of.h>
+#include <linux/regmap.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/driver.h>
@@ -74,6 +75,7 @@ struct regulator_map {
struct regulator {
struct device *dev;
struct list_head list;
+ unsigned int always_on:1;
int uA_load;
int min_uV;
int max_uV;
@@ -155,6 +157,17 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp
return regnode;
}
+static int _regulator_can_change_status(struct regulator_dev *rdev)
+{
+ if (!rdev->constraints)
+ return 0;
+
+ if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
+ return 1;
+ else
+ return 0;
+}
+
/* Platform voltage constraint check */
static int regulator_check_voltage(struct regulator_dev *rdev,
int *min_uV, int *max_uV)
@@ -649,7 +662,7 @@ static void drms_uA_update(struct regulator_dev *rdev)
/* get input voltage */
input_uV = 0;
if (rdev->supply)
- input_uV = _regulator_get_voltage(rdev);
+ input_uV = regulator_get_voltage(rdev->supply);
if (input_uV <= 0)
input_uV = rdev->constraints->input_uV;
if (input_uV <= 0)
@@ -673,17 +686,14 @@ static int suspend_set_state(struct regulator_dev *rdev,
struct regulator_state *rstate)
{
int ret = 0;
- bool can_set_state;
-
- can_set_state = rdev->desc->ops->set_suspend_enable &&
- rdev->desc->ops->set_suspend_disable;
/* If we have no suspend mode configration don't set anything;
- * only warn if the driver actually makes the suspend mode
- * configurable.
+ * only warn if the driver implements set_suspend_voltage or
+ * set_suspend_mode callback.
*/
if (!rstate->enabled && !rstate->disabled) {
- if (can_set_state)
+ if (rdev->desc->ops->set_suspend_voltage ||
+ rdev->desc->ops->set_suspend_mode)
rdev_warn(rdev, "No configuration\n");
return 0;
}
@@ -693,15 +703,13 @@ static int suspend_set_state(struct regulator_dev *rdev,
return -EINVAL;
}
- if (!can_set_state) {
- rdev_err(rdev, "no way to set suspend state\n");
- return -EINVAL;
- }
-
- if (rstate->enabled)
+ if (rstate->enabled && rdev->desc->ops->set_suspend_enable)
ret = rdev->desc->ops->set_suspend_enable(rdev);
- else
+ else if (rstate->disabled && rdev->desc->ops->set_suspend_disable)
ret = rdev->desc->ops->set_suspend_disable(rdev);
+ else /* OK if set_suspend_enable or set_suspend_disable is NULL */
+ ret = 0;
+
if (ret < 0) {
rdev_err(rdev, "failed to enabled/disable\n");
return ret;
@@ -1146,6 +1154,15 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
&regulator->max_uV);
}
+ /*
+ * Check now if the regulator is an always on regulator - if
+ * it is then we don't need to do nearly so much work for
+ * enable/disable calls.
+ */
+ if (!_regulator_can_change_status(rdev) &&
+ _regulator_is_enabled(rdev))
+ regulator->always_on = true;
+
mutex_unlock(&rdev->mutex);
return regulator;
link_name_err:
@@ -1169,26 +1186,52 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev)
}
static struct regulator_dev *regulator_dev_lookup(struct device *dev,
- const char *supply)
+ const char *supply,
+ int *ret)
{
struct regulator_dev *r;
struct device_node *node;
+ struct regulator_map *map;
+ const char *devname = NULL;
/* first do a dt based lookup */
if (dev && dev->of_node) {
node = of_get_regulator(dev, supply);
- if (node)
+ if (node) {
list_for_each_entry(r, &regulator_list, list)
if (r->dev.parent &&
node == r->dev.of_node)
return r;
+ } else {
+ /*
+ * If we couldn't even get the node then it's
+ * not just that the device didn't register
+ * yet, there's no node and we'll never
+ * succeed.
+ */
+ *ret = -ENODEV;
+ }
}
/* if not found, try doing it non-dt way */
+ if (dev)
+ devname = dev_name(dev);
+
list_for_each_entry(r, &regulator_list, list)
if (strcmp(rdev_get_name(r), supply) == 0)
return r;
+ list_for_each_entry(map, &regulator_map_list, list) {
+ /* If the mapping has a device set up it must match */
+ if (map->dev_name &&
+ (!devname || strcmp(map->dev_name, devname)))
+ continue;
+
+ if (strcmp(map->supply, supply) == 0)
+ return map->regulator;
+ }
+
+
return NULL;
}
@@ -1197,7 +1240,6 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
int exclusive)
{
struct regulator_dev *rdev;
- struct regulator_map *map;
struct regulator *regulator = ERR_PTR(-EPROBE_DEFER);
const char *devname = NULL;
int ret;
@@ -1212,22 +1254,10 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
mutex_lock(&regulator_list_mutex);
- rdev = regulator_dev_lookup(dev, id);
+ rdev = regulator_dev_lookup(dev, id, &ret);
if (rdev)
goto found;
- list_for_each_entry(map, &regulator_map_list, list) {
- /* If the mapping has a device set up it must match */
- if (map->dev_name &&
- (!devname || strcmp(map->dev_name, devname)))
- continue;
-
- if (strcmp(map->supply, id) == 0) {
- rdev = map->regulator;
- goto found;
- }
- }
-
if (board_wants_dummy_regulator) {
rdev = dummy_regulator_rdev;
goto found;
@@ -1438,17 +1468,6 @@ void devm_regulator_put(struct regulator *regulator)
}
EXPORT_SYMBOL_GPL(devm_regulator_put);
-static int _regulator_can_change_status(struct regulator_dev *rdev)
-{
- if (!rdev->constraints)
- return 0;
-
- if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
- return 1;
- else
- return 0;
-}
-
/* locks held by regulator_enable() */
static int _regulator_enable(struct regulator_dev *rdev)
{
@@ -1528,6 +1547,9 @@ int regulator_enable(struct regulator *regulator)
struct regulator_dev *rdev = regulator->rdev;
int ret = 0;
+ if (regulator->always_on)
+ return 0;
+
if (rdev->supply) {
ret = regulator_enable(rdev->supply);
if (ret != 0)
@@ -1606,6 +1628,9 @@ int regulator_disable(struct regulator *regulator)
struct regulator_dev *rdev = regulator->rdev;
int ret = 0;
+ if (regulator->always_on)
+ return 0;
+
mutex_lock(&rdev->mutex);
ret = _regulator_disable(rdev);
mutex_unlock(&rdev->mutex);
@@ -1714,6 +1739,9 @@ int regulator_disable_deferred(struct regulator *regulator, int ms)
struct regulator_dev *rdev = regulator->rdev;
int ret;
+ if (regulator->always_on)
+ return 0;
+
mutex_lock(&rdev->mutex);
rdev->deferred_disables++;
mutex_unlock(&rdev->mutex);
@@ -1727,6 +1755,61 @@ int regulator_disable_deferred(struct regulator *regulator, int ms)
}
EXPORT_SYMBOL_GPL(regulator_disable_deferred);
+/**
+ * regulator_is_enabled_regmap - standard is_enabled() for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their descriptor and then use
+ * this as their is_enabled operation, saving some code.
+ */
+int regulator_is_enabled_regmap(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
+ if (ret != 0)
+ return ret;
+
+ return (val & rdev->desc->enable_mask) != 0;
+}
+EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
+
+/**
+ * regulator_enable_regmap - standard enable() for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their descriptor and then use
+ * this as their enable() operation, saving some code.
+ */
+int regulator_enable_regmap(struct regulator_dev *rdev)
+{
+ return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+ rdev->desc->enable_mask,
+ rdev->desc->enable_mask);
+}
+EXPORT_SYMBOL_GPL(regulator_enable_regmap);
+
+/**
+ * regulator_disable_regmap - standard disable() for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their descriptor and then use
+ * this as their disable() operation, saving some code.
+ */
+int regulator_disable_regmap(struct regulator_dev *rdev)
+{
+ return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+ rdev->desc->enable_mask, 0);
+}
+EXPORT_SYMBOL_GPL(regulator_disable_regmap);
+
static int _regulator_is_enabled(struct regulator_dev *rdev)
{
/* If we don't know then assume that the regulator is always on */
@@ -1752,6 +1835,9 @@ int regulator_is_enabled(struct regulator *regulator)
{
int ret;
+ if (regulator->always_on)
+ return 1;
+
mutex_lock(&regulator->rdev->mutex);
ret = _regulator_is_enabled(regulator->rdev);
mutex_unlock(&regulator->rdev->mutex);
@@ -1777,6 +1863,26 @@ int regulator_count_voltages(struct regulator *regulator)
EXPORT_SYMBOL_GPL(regulator_count_voltages);
/**
+ * regulator_list_voltage_linear - List voltages with simple calculation
+ *
+ * @rdev: Regulator device
+ * @selector: Selector to convert into a voltage
+ *
+ * Regulators with a simple linear mapping between voltages and
+ * selectors can set min_uV and uV_step in the regulator descriptor
+ * and then use this function as their list_voltage() operation,
+ */
+int regulator_list_voltage_linear(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ if (selector >= rdev->desc->n_voltages)
+ return -EINVAL;
+
+ return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
+}
+EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
+
+/**
* regulator_list_voltage - enumerate supported voltages
* @regulator: regulator source
* @selector: identify voltage to list
@@ -1840,75 +1946,183 @@ int regulator_is_supported_voltage(struct regulator *regulator,
}
EXPORT_SYMBOL_GPL(regulator_is_supported_voltage);
+/**
+ * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * vsel_reg and vsel_mask fields in their descriptor and then use this
+ * as their get_voltage_vsel operation, saving some code.
+ */
+int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
+ if (ret != 0)
+ return ret;
+
+ val &= rdev->desc->vsel_mask;
+ val >>= ffs(rdev->desc->vsel_mask) - 1;
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap);
+
+/**
+ * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users
+ *
+ * @rdev: regulator to operate on
+ * @sel: Selector to set
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * vsel_reg and vsel_mask fields in their descriptor and then use this
+ * as their set_voltage_vsel operation, saving some code.
+ */
+int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel)
+{
+ sel <<= ffs(rdev->desc->vsel_mask) - 1;
+
+ return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
+ rdev->desc->vsel_mask, sel);
+}
+EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap);
+
+/**
+ * regulator_map_voltage_iterate - map_voltage() based on list_voltage()
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers implementing set_voltage_sel() and list_voltage() can use
+ * this as their map_voltage() operation. It will find a suitable
+ * voltage by calling list_voltage() until it gets something in bounds
+ * for the requested voltages.
+ */
+int regulator_map_voltage_iterate(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ int best_val = INT_MAX;
+ int selector = 0;
+ int i, ret;
+
+ /* Find the smallest voltage that falls within the specified
+ * range.
+ */
+ for (i = 0; i < rdev->desc->n_voltages; i++) {
+ ret = rdev->desc->ops->list_voltage(rdev, i);
+ if (ret < 0)
+ continue;
+
+ if (ret < best_val && ret >= min_uV && ret <= max_uV) {
+ best_val = ret;
+ selector = i;
+ }
+ }
+
+ if (best_val != INT_MAX)
+ return selector;
+ else
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
+
+/**
+ * regulator_map_voltage_linear - map_voltage() for simple linear mappings
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers providing min_uV and uV_step in their regulator_desc can
+ * use this as their map_voltage() operation.
+ */
+int regulator_map_voltage_linear(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ int ret, voltage;
+
+ if (!rdev->desc->uV_step) {
+ BUG_ON(!rdev->desc->uV_step);
+ return -EINVAL;
+ }
+
+ ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
+ if (ret < 0)
+ return ret;
+
+ /* Map back into a voltage to verify we're still in bounds */
+ voltage = rdev->desc->ops->list_voltage(rdev, ret);
+ if (voltage < min_uV || voltage > max_uV)
+ return -EINVAL;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
+
static int _regulator_do_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
int ret;
int delay = 0;
+ int best_val;
unsigned int selector;
+ int old_selector = -1;
trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
min_uV += rdev->constraints->uV_offset;
max_uV += rdev->constraints->uV_offset;
+ /*
+ * If we can't obtain the old selector there is not enough
+ * info to call set_voltage_time_sel().
+ */
+ if (rdev->desc->ops->set_voltage_time_sel &&
+ rdev->desc->ops->get_voltage_sel) {
+ old_selector = rdev->desc->ops->get_voltage_sel(rdev);
+ if (old_selector < 0)
+ return old_selector;
+ }
+
if (rdev->desc->ops->set_voltage) {
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
&selector);
-
- if (rdev->desc->ops->list_voltage)
- selector = rdev->desc->ops->list_voltage(rdev,
- selector);
- else
- selector = -1;
} else if (rdev->desc->ops->set_voltage_sel) {
- int best_val = INT_MAX;
- int i;
-
- selector = 0;
-
- /* Find the smallest voltage that falls within the specified
- * range.
- */
- for (i = 0; i < rdev->desc->n_voltages; i++) {
- ret = rdev->desc->ops->list_voltage(rdev, i);
- if (ret < 0)
- continue;
+ if (rdev->desc->ops->map_voltage)
+ ret = rdev->desc->ops->map_voltage(rdev, min_uV,
+ max_uV);
+ else
+ ret = regulator_map_voltage_iterate(rdev, min_uV,
+ max_uV);
- if (ret < best_val && ret >= min_uV && ret <= max_uV) {
- best_val = ret;
- selector = i;
- }
+ if (ret >= 0) {
+ selector = ret;
+ ret = rdev->desc->ops->set_voltage_sel(rdev, ret);
}
+ } else {
+ ret = -EINVAL;
+ }
- /*
- * If we can't obtain the old selector there is not enough
- * info to call set_voltage_time_sel().
- */
- if (rdev->desc->ops->set_voltage_time_sel &&
- rdev->desc->ops->get_voltage_sel) {
- unsigned int old_selector = 0;
+ if (rdev->desc->ops->list_voltage)
+ best_val = rdev->desc->ops->list_voltage(rdev, selector);
+ else
+ best_val = -1;
- ret = rdev->desc->ops->get_voltage_sel(rdev);
- if (ret < 0)
- return ret;
- old_selector = ret;
- ret = rdev->desc->ops->set_voltage_time_sel(rdev,
- old_selector, selector);
- if (ret < 0)
- rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", ret);
- else
- delay = ret;
- }
+ /* Call set_voltage_time_sel if successfully obtained old_selector */
+ if (ret == 0 && old_selector >= 0 &&
+ rdev->desc->ops->set_voltage_time_sel) {
- if (best_val != INT_MAX) {
- ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
- selector = best_val;
- } else {
- ret = -EINVAL;
+ delay = rdev->desc->ops->set_voltage_time_sel(rdev,
+ old_selector, selector);
+ if (delay < 0) {
+ rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n",
+ delay);
+ delay = 0;
}
- } else {
- ret = -EINVAL;
}
/* Insert any necessary delays */
@@ -1923,7 +2137,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
NULL);
- trace_regulator_set_voltage_complete(rdev_get_name(rdev), selector);
+ trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
return ret;
}
@@ -2327,6 +2541,9 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
*/
ret = -EINVAL;
+ if (!rdev->desc->ops->set_mode)
+ goto out;
+
/* get output voltage */
output_uV = _regulator_get_voltage(rdev);
if (output_uV <= 0) {
@@ -2528,9 +2745,13 @@ int regulator_bulk_enable(int num_consumers,
int i;
int ret = 0;
- for (i = 0; i < num_consumers; i++)
- async_schedule_domain(regulator_bulk_enable_async,
- &consumers[i], &async_domain);
+ for (i = 0; i < num_consumers; i++) {
+ if (consumers[i].consumer->always_on)
+ consumers[i].ret = 0;
+ else
+ async_schedule_domain(regulator_bulk_enable_async,
+ &consumers[i], &async_domain);
+ }
async_synchronize_full_domain(&async_domain);
@@ -2569,7 +2790,7 @@ int regulator_bulk_disable(int num_consumers,
struct regulator_bulk_data *consumers)
{
int i;
- int ret;
+ int ret, r;
for (i = num_consumers - 1; i >= 0; --i) {
ret = regulator_disable(consumers[i].consumer);
@@ -2581,8 +2802,12 @@ int regulator_bulk_disable(int num_consumers,
err:
pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
- for (++i; i < num_consumers; ++i)
- regulator_enable(consumers[i].consumer);
+ for (++i; i < num_consumers; ++i) {
+ r = regulator_enable(consumers[i].consumer);
+ if (r != 0)
+ pr_err("Failed to reename %s: %d\n",
+ consumers[i].supply, r);
+ }
return ret;
}
@@ -2759,10 +2984,6 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
return status;
}
- /* suspend mode constraints need multiple supporting methods */
- if (!(ops->set_suspend_enable && ops->set_suspend_disable))
- return status;
-
status = device_create_file(dev, &dev_attr_suspend_standby_state);
if (status < 0)
return status;
@@ -2823,28 +3044,29 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
/**
* regulator_register - register regulator
* @regulator_desc: regulator to register
- * @dev: struct device for the regulator
- * @init_data: platform provided init data, passed through by driver
- * @driver_data: private regulator data
- * @of_node: OpenFirmware node to parse for device tree bindings (may be
- * NULL).
+ * @config: runtime configuration for regulator
*
* Called by regulator drivers to register a regulator.
* Returns 0 on success.
*/
-struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
- struct device *dev, const struct regulator_init_data *init_data,
- void *driver_data, struct device_node *of_node)
+struct regulator_dev *
+regulator_register(const struct regulator_desc *regulator_desc,
+ const struct regulator_config *config)
{
const struct regulation_constraints *constraints = NULL;
+ const struct regulator_init_data *init_data;
static atomic_t regulator_no = ATOMIC_INIT(0);
struct regulator_dev *rdev;
+ struct device *dev;
int ret, i;
const char *supply = NULL;
- if (regulator_desc == NULL)
+ if (regulator_desc == NULL || config == NULL)
return ERR_PTR(-EINVAL);
+ dev = config->dev;
+ WARN_ON(!dev);
+
if (regulator_desc->name == NULL || regulator_desc->ops == NULL)
return ERR_PTR(-EINVAL);
@@ -2868,6 +3090,8 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
return ERR_PTR(-EINVAL);
}
+ init_data = config->init_data;
+
rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
if (rdev == NULL)
return ERR_PTR(-ENOMEM);
@@ -2875,9 +3099,10 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
mutex_lock(&regulator_list_mutex);
mutex_init(&rdev->mutex);
- rdev->reg_data = driver_data;
+ rdev->reg_data = config->driver_data;
rdev->owner = regulator_desc->owner;
rdev->desc = regulator_desc;
+ rdev->regmap = config->regmap;
INIT_LIST_HEAD(&rdev->consumer_list);
INIT_LIST_HEAD(&rdev->list);
BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
@@ -2892,7 +3117,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
/* register with sysfs */
rdev->dev.class = &regulator_class;
- rdev->dev.of_node = of_node;
+ rdev->dev.of_node = config->of_node;
rdev->dev.parent = dev;
dev_set_name(&rdev->dev, "regulator.%d",
atomic_inc_return(&regulator_no) - 1);
@@ -2925,7 +3150,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
if (supply) {
struct regulator_dev *r;
- r = regulator_dev_lookup(dev, supply);
+ r = regulator_dev_lookup(dev, supply, &ret);
if (!r) {
dev_err(dev, "Failed to find supply %s\n", supply);
@@ -2938,8 +3163,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
goto scrub;
/* Enable supply if rail is enabled */
- if (rdev->desc->ops->is_enabled &&
- rdev->desc->ops->is_enabled(rdev)) {
+ if (_regulator_is_enabled(rdev)) {
ret = regulator_enable(rdev->supply);
if (ret < 0)
goto scrub;
@@ -2971,6 +3195,8 @@ unset_supplies:
unset_regulator_supplies(rdev);
scrub:
+ if (rdev->supply)
+ regulator_put(rdev->supply);
kfree(rdev->constraints);
device_unregister(&rdev->dev);
/* device core frees rdev */
@@ -3069,7 +3295,7 @@ int regulator_suspend_finish(void)
goto unlock;
if (!ops->disable)
goto unlock;
- if (ops->is_enabled && !ops->is_enabled(rdev))
+ if (!_regulator_is_enabled(rdev))
goto unlock;
error = ops->disable(rdev);
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
index 1851f0929ef0..1005f5f7e603 100644
--- a/drivers/regulator/da903x.c
+++ b/drivers/regulator/da903x.c
@@ -76,9 +76,7 @@
struct da903x_regulator_info {
struct regulator_desc desc;
- int min_uV;
int max_uV;
- int step_uV;
int vol_reg;
int vol_shift;
int vol_nbits;
@@ -88,10 +86,6 @@ struct da903x_regulator_info {
int enable_bit;
};
-static int da9034_ldo12_data[] = { 1700, 1750, 1800, 1850, 1900, 1950,
- 2000, 2050, 2700, 2750, 2800, 2850,
- 2900, 2950, 3000, 3050 };
-
static inline struct device *to_da903x_dev(struct regulator_dev *rdev)
{
return rdev_get_dev(rdev)->parent->parent;
@@ -100,34 +94,26 @@ static inline struct device *to_da903x_dev(struct regulator_dev *rdev)
static inline int check_range(struct da903x_regulator_info *info,
int min_uV, int max_uV)
{
- if (min_uV < info->min_uV || min_uV > info->max_uV)
+ if (min_uV < info->desc.min_uV || min_uV > info->max_uV)
return -EINVAL;
return 0;
}
/* DA9030/DA9034 common operations */
-static int da903x_set_ldo_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *selector)
+static int da903x_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
{
struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da9034_dev = to_da903x_dev(rdev);
uint8_t val, mask;
- if (check_range(info, min_uV, max_uV)) {
- pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
- return -EINVAL;
- }
-
- val = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
- *selector = val;
- val <<= info->vol_shift;
+ val = selector << info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
return da903x_update(da9034_dev, info->vol_reg, val, mask);
}
-static int da903x_get_voltage(struct regulator_dev *rdev)
+static int da903x_get_voltage_sel(struct regulator_dev *rdev)
{
struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da9034_dev = to_da903x_dev(rdev);
@@ -141,7 +127,7 @@ static int da903x_get_voltage(struct regulator_dev *rdev)
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
val = (val & mask) >> info->vol_shift;
- return info->min_uV + info->step_uV * val;
+ return val;
}
static int da903x_enable(struct regulator_dev *rdev)
@@ -176,35 +162,16 @@ static int da903x_is_enabled(struct regulator_dev *rdev)
return !!(reg_val & (1 << info->enable_bit));
}
-static int da903x_list_voltage(struct regulator_dev *rdev, unsigned selector)
-{
- struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
- int ret;
-
- ret = info->min_uV + info->step_uV * selector;
- if (ret > info->max_uV)
- return -EINVAL;
- return ret;
-}
-
/* DA9030 specific operations */
-static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV,
- unsigned *selector)
+static int da9030_set_ldo1_15_voltage_sel(struct regulator_dev *rdev,
+ unsigned selector)
{
struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da903x_dev = to_da903x_dev(rdev);
uint8_t val, mask;
int ret;
- if (check_range(info, min_uV, max_uV)) {
- pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
- return -EINVAL;
- }
-
- val = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
- *selector = val;
- val <<= info->vol_shift;
+ val = selector << info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
val |= DA9030_LDO_UNLOCK; /* have to set UNLOCK bits */
mask |= DA9030_LDO_UNLOCK_MASK;
@@ -217,73 +184,57 @@ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev,
return da903x_update(da903x_dev, info->vol_reg, val, mask);
}
-static int da9030_set_ldo14_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV,
- unsigned *selector)
+static int da9030_map_ldo14_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
{
struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
- struct device *da903x_dev = to_da903x_dev(rdev);
- uint8_t val, mask;
- int thresh;
+ int thresh, sel;
if (check_range(info, min_uV, max_uV)) {
pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
return -EINVAL;
}
- thresh = (info->max_uV + info->min_uV) / 2;
+ thresh = (info->max_uV + info->desc.min_uV) / 2;
if (min_uV < thresh) {
- val = DIV_ROUND_UP(thresh - min_uV, info->step_uV);
- val |= 0x4;
+ sel = DIV_ROUND_UP(thresh - min_uV, info->desc.uV_step);
+ sel |= 0x4;
} else {
- val = DIV_ROUND_UP(min_uV - thresh, info->step_uV);
+ sel = DIV_ROUND_UP(min_uV - thresh, info->desc.uV_step);
}
- *selector = val;
- val <<= info->vol_shift;
- mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
-
- return da903x_update(da903x_dev, info->vol_reg, val, mask);
+ return sel;
}
-static int da9030_get_ldo14_voltage(struct regulator_dev *rdev)
+static int da9030_list_ldo14_voltage(struct regulator_dev *rdev,
+ unsigned selector)
{
struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
- struct device *da903x_dev = to_da903x_dev(rdev);
- uint8_t val, mask;
- int ret;
+ int volt;
- ret = da903x_read(da903x_dev, info->vol_reg, &val);
- if (ret)
- return ret;
+ if (selector & 0x4)
+ volt = rdev->desc->min_uV +
+ rdev->desc->uV_step * (3 - (selector & ~0x4));
+ else
+ volt = (info->max_uV + rdev->desc->min_uV) / 2 +
+ rdev->desc->uV_step * (selector & ~0x4);
- mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
- val = (val & mask) >> info->vol_shift;
+ if (volt > info->max_uV)
+ return -EINVAL;
- if (val & 0x4)
- return info->min_uV + info->step_uV * (3 - (val & ~0x4));
- else
- return (info->max_uV + info->min_uV) / 2 +
- info->step_uV * (val & ~0x4);
+ return volt;
}
/* DA9034 specific operations */
-static int da9034_set_dvc_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *selector)
+static int da9034_set_dvc_voltage_sel(struct regulator_dev *rdev,
+ unsigned selector)
{
struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da9034_dev = to_da903x_dev(rdev);
uint8_t val, mask;
int ret;
- if (check_range(info, min_uV, max_uV)) {
- pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
- return -EINVAL;
- }
-
- val = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
- *selector = val;
- val <<= info->vol_shift;
+ val = selector << info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
ret = da903x_update(da9034_dev, info->vol_reg, val, mask);
@@ -295,59 +246,45 @@ static int da9034_set_dvc_voltage(struct regulator_dev *rdev,
return ret;
}
-static int da9034_set_ldo12_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *selector)
+static int da9034_map_ldo12_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
{
struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
- struct device *da9034_dev = to_da903x_dev(rdev);
- uint8_t val, mask;
+ int sel;
if (check_range(info, min_uV, max_uV)) {
pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
return -EINVAL;
}
- val = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
- val = (val >= 20) ? val - 12 : ((val > 7) ? 8 : val);
- *selector = val;
- val <<= info->vol_shift;
- mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+ sel = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step);
+ sel = (sel >= 20) ? sel - 12 : ((sel > 7) ? 8 : sel);
- return da903x_update(da9034_dev, info->vol_reg, val, mask);
+ return sel;
}
-static int da9034_get_ldo12_voltage(struct regulator_dev *rdev)
+static int da9034_list_ldo12_voltage(struct regulator_dev *rdev,
+ unsigned selector)
{
struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
- struct device *da9034_dev = to_da903x_dev(rdev);
- uint8_t val, mask;
- int ret;
-
- ret = da903x_read(da9034_dev, info->vol_reg, &val);
- if (ret)
- return ret;
-
- mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
- val = (val & mask) >> info->vol_shift;
+ int volt;
- if (val >= 8)
- return 2700000 + info->step_uV * (val - 8);
-
- return info->min_uV + info->step_uV * val;
-}
+ if (selector >= 8)
+ volt = 2700000 + rdev->desc->uV_step * (selector - 8);
+ else
+ volt = rdev->desc->min_uV + rdev->desc->uV_step * selector;
-static int da9034_list_ldo12_voltage(struct regulator_dev *rdev,
- unsigned selector)
-{
- if (selector >= ARRAY_SIZE(da9034_ldo12_data))
+ if (volt > info->max_uV)
return -EINVAL;
- return da9034_ldo12_data[selector] * 1000;
+
+ return volt;
}
static struct regulator_ops da903x_regulator_ldo_ops = {
- .set_voltage = da903x_set_ldo_voltage,
- .get_voltage = da903x_get_voltage,
- .list_voltage = da903x_list_voltage,
+ .set_voltage_sel = da903x_set_voltage_sel,
+ .get_voltage_sel = da903x_get_voltage_sel,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
.enable = da903x_enable,
.disable = da903x_disable,
.is_enabled = da903x_is_enabled,
@@ -355,9 +292,10 @@ static struct regulator_ops da903x_regulator_ldo_ops = {
/* NOTE: this is dedicated for the insane DA9030 LDO14 */
static struct regulator_ops da9030_regulator_ldo14_ops = {
- .set_voltage = da9030_set_ldo14_voltage,
- .get_voltage = da9030_get_ldo14_voltage,
- .list_voltage = da903x_list_voltage,
+ .set_voltage_sel = da903x_set_voltage_sel,
+ .get_voltage_sel = da903x_get_voltage_sel,
+ .list_voltage = da9030_list_ldo14_voltage,
+ .map_voltage = da9030_map_ldo14_voltage,
.enable = da903x_enable,
.disable = da903x_disable,
.is_enabled = da903x_is_enabled,
@@ -365,18 +303,20 @@ static struct regulator_ops da9030_regulator_ldo14_ops = {
/* NOTE: this is dedicated for the DA9030 LDO1 and LDO15 that have locks */
static struct regulator_ops da9030_regulator_ldo1_15_ops = {
- .set_voltage = da9030_set_ldo1_15_voltage,
- .get_voltage = da903x_get_voltage,
- .list_voltage = da903x_list_voltage,
+ .set_voltage_sel = da9030_set_ldo1_15_voltage_sel,
+ .get_voltage_sel = da903x_get_voltage_sel,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
.enable = da903x_enable,
.disable = da903x_disable,
.is_enabled = da903x_is_enabled,
};
static struct regulator_ops da9034_regulator_dvc_ops = {
- .set_voltage = da9034_set_dvc_voltage,
- .get_voltage = da903x_get_voltage,
- .list_voltage = da903x_list_voltage,
+ .set_voltage_sel = da9034_set_dvc_voltage_sel,
+ .get_voltage_sel = da903x_get_voltage_sel,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
.enable = da903x_enable,
.disable = da903x_disable,
.is_enabled = da903x_is_enabled,
@@ -384,9 +324,10 @@ static struct regulator_ops da9034_regulator_dvc_ops = {
/* NOTE: this is dedicated for the insane LDO12 */
static struct regulator_ops da9034_regulator_ldo12_ops = {
- .set_voltage = da9034_set_ldo12_voltage,
- .get_voltage = da9034_get_ldo12_voltage,
+ .set_voltage_sel = da903x_set_voltage_sel,
+ .get_voltage_sel = da903x_get_voltage_sel,
.list_voltage = da9034_list_ldo12_voltage,
+ .map_voltage = da9034_map_ldo12_voltage,
.enable = da903x_enable,
.disable = da903x_disable,
.is_enabled = da903x_is_enabled,
@@ -401,10 +342,10 @@ static struct regulator_ops da9034_regulator_ldo12_ops = {
.id = _pmic##_ID_LDO##_id, \
.n_voltages = (step) ? ((max - min) / step + 1) : 1, \
.owner = THIS_MODULE, \
+ .min_uV = (min) * 1000, \
+ .uV_step = (step) * 1000, \
}, \
- .min_uV = (min) * 1000, \
.max_uV = (max) * 1000, \
- .step_uV = (step) * 1000, \
.vol_reg = _pmic##_##vreg, \
.vol_shift = (shift), \
.vol_nbits = (nbits), \
@@ -421,10 +362,10 @@ static struct regulator_ops da9034_regulator_ldo12_ops = {
.id = _pmic##_ID_##_id, \
.n_voltages = (step) ? ((max - min) / step + 1) : 1, \
.owner = THIS_MODULE, \
+ .min_uV = (min) * 1000, \
+ .uV_step = (step) * 1000, \
}, \
- .min_uV = (min) * 1000, \
.max_uV = (max) * 1000, \
- .step_uV = (step) * 1000, \
.vol_reg = _pmic##_##vreg, \
.vol_shift = (0), \
.vol_nbits = (nbits), \
@@ -517,6 +458,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev)
{
struct da903x_regulator_info *ri = NULL;
struct regulator_dev *rdev;
+ struct regulator_config config = { };
ri = find_regulator_info(pdev->id);
if (ri == NULL) {
@@ -527,7 +469,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev)
/* Workaround for the weird LDO12 voltage setting */
if (ri->desc.id == DA9034_ID_LDO12) {
ri->desc.ops = &da9034_regulator_ldo12_ops;
- ri->desc.n_voltages = ARRAY_SIZE(da9034_ldo12_data);
+ ri->desc.n_voltages = 16;
}
if (ri->desc.id == DA9030_ID_LDO14)
@@ -536,8 +478,11 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev)
if (ri->desc.id == DA9030_ID_LDO1 || ri->desc.id == DA9030_ID_LDO15)
ri->desc.ops = &da9030_regulator_ldo1_15_ops;
- rdev = regulator_register(&ri->desc, &pdev->dev,
- pdev->dev.platform_data, ri, NULL);
+ config.dev = &pdev->dev;
+ config.init_data = pdev->dev.platform_data;
+ config.driver_data = ri;
+
+ rdev = regulator_register(&ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
ri->desc.name);
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
index 09915e89705d..88976d8d44ed 100644
--- a/drivers/regulator/da9052-regulator.c
+++ b/drivers/regulator/da9052-regulator.c
@@ -19,6 +19,10 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#include <linux/regulator/of_regulator.h>
+#endif
#include <linux/mfd/da9052/da9052.h>
#include <linux/mfd/da9052/reg.h>
@@ -37,6 +41,22 @@
#define DA9052_BUCK_ILIM_MASK_EVEN 0x0c
#define DA9052_BUCK_ILIM_MASK_ODD 0xc0
+/* DA9052 REGULATOR IDs */
+#define DA9052_ID_BUCK1 0
+#define DA9052_ID_BUCK2 1
+#define DA9052_ID_BUCK3 2
+#define DA9052_ID_BUCK4 3
+#define DA9052_ID_LDO1 4
+#define DA9052_ID_LDO2 5
+#define DA9052_ID_LDO3 6
+#define DA9052_ID_LDO4 7
+#define DA9052_ID_LDO5 8
+#define DA9052_ID_LDO6 9
+#define DA9052_ID_LDO7 10
+#define DA9052_ID_LDO8 11
+#define DA9052_ID_LDO9 12
+#define DA9052_ID_LDO10 13
+
static const u32 da9052_current_limits[3][4] = {
{700000, 800000, 1000000, 1200000}, /* DA9052-BC BUCKs */
{1600000, 2000000, 2400000, 3000000}, /* DA9053-AA/Bx BUCK-CORE */
@@ -50,8 +70,6 @@ struct da9052_regulator_info {
int step_uV;
int min_uV;
int max_uV;
- unsigned char volt_shift;
- unsigned char en_bit;
unsigned char activate_bit;
};
@@ -70,42 +88,6 @@ static int verify_range(struct da9052_regulator_info *info,
return 0;
}
-static int da9052_regulator_enable(struct regulator_dev *rdev)
-{
- struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
- struct da9052_regulator_info *info = regulator->info;
- int offset = rdev_get_id(rdev);
-
- return da9052_reg_update(regulator->da9052,
- DA9052_BUCKCORE_REG + offset,
- 1 << info->en_bit, 1 << info->en_bit);
-}
-
-static int da9052_regulator_disable(struct regulator_dev *rdev)
-{
- struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
- struct da9052_regulator_info *info = regulator->info;
- int offset = rdev_get_id(rdev);
-
- return da9052_reg_update(regulator->da9052,
- DA9052_BUCKCORE_REG + offset,
- 1 << info->en_bit, 0);
-}
-
-static int da9052_regulator_is_enabled(struct regulator_dev *rdev)
-{
- struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
- struct da9052_regulator_info *info = regulator->info;
- int offset = rdev_get_id(rdev);
- int ret;
-
- ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
- if (ret < 0)
- return ret;
-
- return ret & (1 << info->en_bit);
-}
-
static int da9052_dcdc_get_current_limit(struct regulator_dev *rdev)
{
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
@@ -173,36 +155,23 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
reg_val << 6);
}
-static int da9052_list_buckperi_voltage(struct regulator_dev *rdev,
- unsigned int selector)
-{
- struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
- struct da9052_regulator_info *info = regulator->info;
- int volt_uV;
-
- if ((regulator->da9052->chip_id == DA9052) &&
- (selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) {
- volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV)
- + info->min_uV);
- volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)
- * (DA9052_BUCK_PERI_3uV_STEP);
- } else
- volt_uV = (selector * info->step_uV) + info->min_uV;
-
- if (volt_uV > info->max_uV)
- return -EINVAL;
-
- return volt_uV;
-}
-
static int da9052_list_voltage(struct regulator_dev *rdev,
unsigned int selector)
{
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
struct da9052_regulator_info *info = regulator->info;
+ int id = rdev_get_id(rdev);
int volt_uV;
- volt_uV = info->min_uV + info->step_uV * selector;
+ if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052)
+ && (selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) {
+ volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV)
+ + info->min_uV);
+ volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)
+ * (DA9052_BUCK_PERI_3uV_STEP);
+ } else {
+ volt_uV = (selector * info->step_uV) + info->min_uV;
+ }
if (volt_uV > info->max_uV)
return -EINVAL;
@@ -210,103 +179,13 @@ static int da9052_list_voltage(struct regulator_dev *rdev,
return volt_uV;
}
-static int da9052_regulator_set_voltage_int(struct regulator_dev *rdev,
- int min_uV, int max_uV,
- unsigned int *selector)
-{
- struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
- struct da9052_regulator_info *info = regulator->info;
- int offset = rdev_get_id(rdev);
- int ret;
-
- ret = verify_range(info, min_uV, max_uV);
- if (ret < 0)
- return ret;
-
- if (min_uV < info->min_uV)
- min_uV = info->min_uV;
-
- *selector = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
-
- ret = da9052_list_voltage(rdev, *selector);
- if (ret < 0)
- return ret;
-
- return da9052_reg_update(regulator->da9052,
- DA9052_BUCKCORE_REG + offset,
- (1 << info->volt_shift) - 1, *selector);
-}
-
-static int da9052_set_ldo_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV,
- unsigned int *selector)
-{
- return da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
-}
-
-static int da9052_set_ldo5_6_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV,
- unsigned int *selector)
-{
- struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
- struct da9052_regulator_info *info = regulator->info;
- int ret;
-
- ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
- if (ret < 0)
- return ret;
-
- /* Some LDOs are DVC controlled which requires enabling of
- * the LDO activate bit to implment the changes on the
- * LDO output.
- */
- return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
- info->activate_bit, info->activate_bit);
-}
-
-static int da9052_set_dcdc_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV,
- unsigned int *selector)
-{
- struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
- struct da9052_regulator_info *info = regulator->info;
- int ret;
-
- ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
- if (ret < 0)
- return ret;
-
- /* Some DCDCs are DVC controlled which requires enabling of
- * the DCDC activate bit to implment the changes on the
- * DCDC output.
- */
- return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
- info->activate_bit, info->activate_bit);
-}
-
-static int da9052_get_regulator_voltage_sel(struct regulator_dev *rdev)
-{
- struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
- struct da9052_regulator_info *info = regulator->info;
- int offset = rdev_get_id(rdev);
- int ret;
-
- ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
- if (ret < 0)
- return ret;
-
- ret &= ((1 << info->volt_shift) - 1);
-
- return ret;
-}
-
-static int da9052_set_buckperi_voltage(struct regulator_dev *rdev, int min_uV,
- int max_uV, unsigned int *selector)
+static int da9052_map_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
{
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
struct da9052_regulator_info *info = regulator->info;
- int offset = rdev_get_id(rdev);
- int ret;
+ int id = rdev_get_id(rdev);
+ int ret, sel;
ret = verify_range(info, min_uV, max_uV);
if (ret < 0)
@@ -315,192 +194,147 @@ static int da9052_set_buckperi_voltage(struct regulator_dev *rdev, int min_uV,
if (min_uV < info->min_uV)
min_uV = info->min_uV;
- if ((regulator->da9052->chip_id == DA9052) &&
- (min_uV >= DA9052_CONST_3uV))
- *selector = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV +
- DIV_ROUND_UP(min_uV - DA9052_CONST_3uV,
- DA9052_BUCK_PERI_3uV_STEP);
- else
- *selector = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
+ if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052)
+ && (min_uV >= DA9052_CONST_3uV)) {
+ sel = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV +
+ DIV_ROUND_UP(min_uV - DA9052_CONST_3uV,
+ DA9052_BUCK_PERI_3uV_STEP);
+ } else {
+ sel = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
+ }
- ret = da9052_list_buckperi_voltage(rdev, *selector);
+ ret = da9052_list_voltage(rdev, sel);
if (ret < 0)
return ret;
- return da9052_reg_update(regulator->da9052,
- DA9052_BUCKCORE_REG + offset,
- (1 << info->volt_shift) - 1, *selector);
+ return sel;
}
-static int da9052_get_buckperi_voltage_sel(struct regulator_dev *rdev)
+static int da9052_regulator_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int selector)
{
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
struct da9052_regulator_info *info = regulator->info;
- int offset = rdev_get_id(rdev);
+ int id = rdev_get_id(rdev);
int ret;
- ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
+ ret = da9052_reg_update(regulator->da9052, rdev->desc->vsel_reg,
+ rdev->desc->vsel_mask, selector);
if (ret < 0)
return ret;
- ret &= ((1 << info->volt_shift) - 1);
+ /* Some LDOs and DCDCs are DVC controlled which requires enabling of
+ * the activate bit to implment the changes on the output.
+ */
+ switch (id) {
+ case DA9052_ID_BUCK1:
+ case DA9052_ID_BUCK2:
+ case DA9052_ID_BUCK3:
+ case DA9052_ID_LDO2:
+ case DA9052_ID_LDO3:
+ ret = da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
+ info->activate_bit, info->activate_bit);
+ break;
+ }
return ret;
}
-static struct regulator_ops da9052_buckperi_ops = {
- .list_voltage = da9052_list_buckperi_voltage,
- .get_voltage_sel = da9052_get_buckperi_voltage_sel,
- .set_voltage = da9052_set_buckperi_voltage,
-
- .get_current_limit = da9052_dcdc_get_current_limit,
- .set_current_limit = da9052_dcdc_set_current_limit,
-
- .is_enabled = da9052_regulator_is_enabled,
- .enable = da9052_regulator_enable,
- .disable = da9052_regulator_disable,
-};
-
static struct regulator_ops da9052_dcdc_ops = {
- .set_voltage = da9052_set_dcdc_voltage,
.get_current_limit = da9052_dcdc_get_current_limit,
.set_current_limit = da9052_dcdc_set_current_limit,
.list_voltage = da9052_list_voltage,
- .get_voltage_sel = da9052_get_regulator_voltage_sel,
- .is_enabled = da9052_regulator_is_enabled,
- .enable = da9052_regulator_enable,
- .disable = da9052_regulator_disable,
-};
-
-static struct regulator_ops da9052_ldo5_6_ops = {
- .set_voltage = da9052_set_ldo5_6_voltage,
-
- .list_voltage = da9052_list_voltage,
- .get_voltage_sel = da9052_get_regulator_voltage_sel,
- .is_enabled = da9052_regulator_is_enabled,
- .enable = da9052_regulator_enable,
- .disable = da9052_regulator_disable,
+ .map_voltage = da9052_map_voltage,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = da9052_regulator_set_voltage_sel,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
};
static struct regulator_ops da9052_ldo_ops = {
- .set_voltage = da9052_set_ldo_voltage,
-
.list_voltage = da9052_list_voltage,
- .get_voltage_sel = da9052_get_regulator_voltage_sel,
- .is_enabled = da9052_regulator_is_enabled,
- .enable = da9052_regulator_enable,
- .disable = da9052_regulator_disable,
+ .map_voltage = da9052_map_voltage,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = da9052_regulator_set_voltage_sel,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
};
-#define DA9052_LDO5_6(_id, step, min, max, sbits, ebits, abits) \
-{\
- .reg_desc = {\
- .name = "LDO" #_id,\
- .ops = &da9052_ldo5_6_ops,\
- .type = REGULATOR_VOLTAGE,\
- .id = _id,\
- .n_voltages = (max - min) / step + 1, \
- .owner = THIS_MODULE,\
- },\
- .min_uV = (min) * 1000,\
- .max_uV = (max) * 1000,\
- .step_uV = (step) * 1000,\
- .volt_shift = (sbits),\
- .en_bit = (ebits),\
- .activate_bit = (abits),\
-}
-
#define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \
{\
.reg_desc = {\
- .name = "LDO" #_id,\
+ .name = #_id,\
.ops = &da9052_ldo_ops,\
.type = REGULATOR_VOLTAGE,\
- .id = _id,\
+ .id = DA9052_ID_##_id,\
.n_voltages = (max - min) / step + 1, \
.owner = THIS_MODULE,\
+ .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
+ .vsel_mask = (1 << (sbits)) - 1,\
+ .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
+ .enable_mask = 1 << (ebits),\
},\
.min_uV = (min) * 1000,\
.max_uV = (max) * 1000,\
.step_uV = (step) * 1000,\
- .volt_shift = (sbits),\
- .en_bit = (ebits),\
.activate_bit = (abits),\
}
#define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \
{\
.reg_desc = {\
- .name = "BUCK" #_id,\
+ .name = #_id,\
.ops = &da9052_dcdc_ops,\
.type = REGULATOR_VOLTAGE,\
- .id = _id,\
+ .id = DA9052_ID_##_id,\
.n_voltages = (max - min) / step + 1, \
.owner = THIS_MODULE,\
+ .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
+ .vsel_mask = (1 << (sbits)) - 1,\
+ .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
+ .enable_mask = 1 << (ebits),\
},\
.min_uV = (min) * 1000,\
.max_uV = (max) * 1000,\
.step_uV = (step) * 1000,\
- .volt_shift = (sbits),\
- .en_bit = (ebits),\
- .activate_bit = (abits),\
-}
-
-#define DA9052_BUCKPERI(_id, step, min, max, sbits, ebits, abits) \
-{\
- .reg_desc = {\
- .name = "BUCK" #_id,\
- .ops = &da9052_buckperi_ops,\
- .type = REGULATOR_VOLTAGE,\
- .id = _id,\
- .n_voltages = (max - min) / step + 1, \
- .owner = THIS_MODULE,\
- },\
- .min_uV = (min) * 1000,\
- .max_uV = (max) * 1000,\
- .step_uV = (step) * 1000,\
- .volt_shift = (sbits),\
- .en_bit = (ebits),\
.activate_bit = (abits),\
}
static struct da9052_regulator_info da9052_regulator_info[] = {
- /* Buck1 - 4 */
- DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
- DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
- DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
- DA9052_BUCKPERI(3, 50, 1800, 3600, 5, 6, 0),
- /* LD01 - LDO10 */
- DA9052_LDO(4, 50, 600, 1800, 5, 6, 0),
- DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
- DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
- DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0),
- DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0),
- DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0),
+ DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
+ DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
+ DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
+ DA9052_DCDC(BUCK4, 50, 1800, 3600, 5, 6, 0),
+ DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
+ DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
+ DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
+ DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0),
+ DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0),
+ DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0),
};
static struct da9052_regulator_info da9053_regulator_info[] = {
- /* Buck1 - 4 */
- DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
- DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
- DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
- DA9052_BUCKPERI(3, 25, 925, 2500, 6, 6, 0),
- /* LD01 - LDO10 */
- DA9052_LDO(4, 50, 600, 1800, 5, 6, 0),
- DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
- DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
- DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0),
- DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0),
- DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0),
+ DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
+ DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
+ DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
+ DA9052_DCDC(BUCK4, 25, 925, 2500, 6, 6, 0),
+ DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
+ DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
+ DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
+ DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0),
+ DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0),
+ DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0),
};
static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
@@ -533,10 +367,10 @@ static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
static int __devinit da9052_regulator_probe(struct platform_device *pdev)
{
+ struct regulator_config config = { };
struct da9052_regulator *regulator;
struct da9052 *da9052;
struct da9052_pdata *pdata;
- int ret;
regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9052_regulator),
GFP_KERNEL);
@@ -551,26 +385,49 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev)
pdev->id);
if (regulator->info == NULL) {
dev_err(&pdev->dev, "invalid regulator ID specified\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
+
+ config.dev = &pdev->dev;
+ config.driver_data = regulator;
+ config.regmap = da9052->regmap;
+ if (pdata && pdata->regulators) {
+ config.init_data = pdata->regulators[pdev->id];
+ } else {
+#ifdef CONFIG_OF
+ struct device_node *nproot = da9052->dev->of_node;
+ struct device_node *np;
+
+ if (!nproot)
+ return -ENODEV;
+
+ nproot = of_find_node_by_name(nproot, "regulators");
+ if (!nproot)
+ return -ENODEV;
+
+ for (np = of_get_next_child(nproot, NULL); np;
+ np = of_get_next_child(nproot, np)) {
+ if (!of_node_cmp(np->name,
+ regulator->info->reg_desc.name)) {
+ config.init_data = of_get_regulator_init_data(
+ &pdev->dev, np);
+ break;
+ }
+ }
+#endif
+ }
+
regulator->rdev = regulator_register(&regulator->info->reg_desc,
- &pdev->dev,
- pdata->regulators[pdev->id],
- regulator, NULL);
+ &config);
if (IS_ERR(regulator->rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
regulator->info->reg_desc.name);
- ret = PTR_ERR(regulator->rdev);
- goto err;
+ return PTR_ERR(regulator->rdev);
}
platform_set_drvdata(pdev, regulator);
return 0;
-err:
- devm_kfree(&pdev->dev, regulator);
- return ret;
}
static int __devexit da9052_regulator_remove(struct platform_device *pdev)
@@ -578,8 +435,6 @@ static int __devexit da9052_regulator_remove(struct platform_device *pdev)
struct da9052_regulator *regulator = platform_get_drvdata(pdev);
regulator_unregister(regulator->rdev);
- devm_kfree(&pdev->dev, regulator);
-
return 0;
}
diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c
index 4bd25e75efa0..968f97f3cb3d 100644
--- a/drivers/regulator/db8500-prcmu.c
+++ b/drivers/regulator/db8500-prcmu.c
@@ -17,6 +17,8 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/db8500-prcmu.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/of.h>
#include <linux/module.h>
#include "dbx500-prcmu.h"
@@ -410,45 +412,120 @@ dbx500_regulator_info[DB8500_NUM_REGULATORS] = {
},
};
+static __devinit int db8500_regulator_register(struct platform_device *pdev,
+ struct regulator_init_data *init_data,
+ int id,
+ struct device_node *np)
+{
+ struct dbx500_regulator_info *info;
+ struct regulator_config config = { };
+ int err;
+
+ /* assign per-regulator data */
+ info = &dbx500_regulator_info[id];
+ info->dev = &pdev->dev;
+
+ config.dev = &pdev->dev;
+ config.init_data = init_data;
+ config.driver_data = info;
+ config.of_node = np;
+
+ /* register with the regulator framework */
+ info->rdev = regulator_register(&info->desc, &config);
+ if (IS_ERR(info->rdev)) {
+ err = PTR_ERR(info->rdev);
+ dev_err(&pdev->dev, "failed to register %s: err %i\n",
+ info->desc.name, err);
+
+ /* if failing, unregister all earlier regulators */
+ while (--id >= 0) {
+ info = &dbx500_regulator_info[id];
+ regulator_unregister(info->rdev);
+ }
+ return err;
+ }
+
+ dev_dbg(rdev_get_dev(info->rdev),
+ "regulator-%s-probed\n", info->desc.name);
+
+ return 0;
+}
+
+static struct of_regulator_match db8500_regulator_matches[] = {
+ { .name = "db8500-vape", .driver_data = (void *) DB8500_REGULATOR_VAPE, },
+ { .name = "db8500-varm", .driver_data = (void *) DB8500_REGULATOR_VARM, },
+ { .name = "db8500-vmodem", .driver_data = (void *) DB8500_REGULATOR_VMODEM, },
+ { .name = "db8500-vpll", .driver_data = (void *) DB8500_REGULATOR_VPLL, },
+ { .name = "db8500-vsmps1", .driver_data = (void *) DB8500_REGULATOR_VSMPS1, },
+ { .name = "db8500-vsmps2", .driver_data = (void *) DB8500_REGULATOR_VSMPS2, },
+ { .name = "db8500-vsmps3", .driver_data = (void *) DB8500_REGULATOR_VSMPS3, },
+ { .name = "db8500-vrf1", .driver_data = (void *) DB8500_REGULATOR_VRF1, },
+ { .name = "db8500-sva-mmdsp", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SVAMMDSP, },
+ { .name = "db8500-sva-mmdsp-ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SVAMMDSPRET, },
+ { .name = "db8500-sva-pipe", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SVAPIPE, },
+ { .name = "db8500-sia-mmdsp", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SIAMMDSP, },
+ { .name = "db8500-sia-mmdsp-ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SIAMMDSPRET, },
+ { .name = "db8500-sia-pipe", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SIAPIPE, },
+ { .name = "db8500-sga", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SGA, },
+ { .name = "db8500-b2r2-mcde", .driver_data = (void *) DB8500_REGULATOR_SWITCH_B2R2_MCDE, },
+ { .name = "db8500-esram12", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM12, },
+ { .name = "db8500-esram12-ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM12RET, },
+ { .name = "db8500-esram34", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34, },
+ { .name = "db8500-esram34-ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34RET, },
+};
+
+static __devinit int
+db8500_regulator_of_probe(struct platform_device *pdev,
+ struct device_node *np)
+{
+ int i, err;
+
+ for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) {
+ err = db8500_regulator_register(
+ pdev, db8500_regulator_matches[i].init_data,
+ i, db8500_regulator_matches[i].of_node);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
static int __devinit db8500_regulator_probe(struct platform_device *pdev)
{
struct regulator_init_data *db8500_init_data =
dev_get_platdata(&pdev->dev);
+ struct device_node *np = pdev->dev.of_node;
int i, err;
/* register all regulators */
- for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) {
- struct dbx500_regulator_info *info;
- struct regulator_init_data *init_data = &db8500_init_data[i];
-
- /* assign per-regulator data */
- info = &dbx500_regulator_info[i];
- info->dev = &pdev->dev;
-
- /* register with the regulator framework */
- info->rdev = regulator_register(&info->desc, &pdev->dev,
- init_data, info, NULL);
- if (IS_ERR(info->rdev)) {
- err = PTR_ERR(info->rdev);
- dev_err(&pdev->dev, "failed to register %s: err %i\n",
- info->desc.name, err);
-
- /* if failing, unregister all earlier regulators */
- while (--i >= 0) {
- info = &dbx500_regulator_info[i];
- regulator_unregister(info->rdev);
- }
+ if (np) {
+ err = of_regulator_match(&pdev->dev, np,
+ db8500_regulator_matches,
+ ARRAY_SIZE(db8500_regulator_matches));
+ if (err < 0) {
+ dev_err(&pdev->dev,
+ "Error parsing regulator init data: %d\n", err);
return err;
}
- dev_dbg(rdev_get_dev(info->rdev),
- "regulator-%s-probed\n", info->desc.name);
+ err = db8500_regulator_of_probe(pdev, np);
+ if (err)
+ return err;
+ } else {
+ for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) {
+ err = db8500_regulator_register(pdev,
+ &db8500_init_data[i],
+ i, NULL);
+ if (err)
+ return err;
+ }
}
+
err = ux500_regulator_debug_init(pdev,
dbx500_regulator_info,
ARRAY_SIZE(dbx500_regulator_info));
-
- return err;
+ return 0;
}
static int __exit db8500_regulator_remove(struct platform_device *pdev)
@@ -470,10 +547,16 @@ static int __exit db8500_regulator_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id db8500_prcmu_regulator_match[] = {
+ { .compatible = "stericsson,db8500-prcmu-regulator", },
+ {}
+};
+
static struct platform_driver db8500_regulator_driver = {
.driver = {
.name = "db8500-prcmu-regulators",
.owner = THIS_MODULE,
+ .of_match_table = db8500_prcmu_regulator_match,
},
.probe = db8500_regulator_probe,
.remove = __exit_p(db8500_regulator_remove),
diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c
index 0ee00de4be72..86f655c7f7a1 100644
--- a/drivers/regulator/dummy.c
+++ b/drivers/regulator/dummy.c
@@ -39,10 +39,13 @@ static struct regulator_desc dummy_desc = {
static int __devinit dummy_regulator_probe(struct platform_device *pdev)
{
+ struct regulator_config config = { };
int ret;
- dummy_regulator_rdev = regulator_register(&dummy_desc, NULL,
- &dummy_initdata, NULL, NULL);
+ config.dev = &pdev->dev;
+ config.init_data = &dummy_initdata;
+
+ dummy_regulator_rdev = regulator_register(&dummy_desc, &config);
if (IS_ERR(dummy_regulator_rdev)) {
ret = PTR_ERR(dummy_regulator_rdev);
pr_err("Failed to register regulator: %d\n", ret);
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 40f38030b394..f09fe7b20e82 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -25,7 +25,6 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/fixed.h>
#include <linux/gpio.h>
-#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
@@ -91,6 +90,9 @@ of_get_fixed_voltage_config(struct device *dev)
if (of_find_property(np, "enable-active-high", NULL))
config->enable_high = true;
+ if (of_find_property(np, "gpio-open-drain", NULL))
+ config->gpio_is_open_drain = true;
+
return config;
}
@@ -105,10 +107,8 @@ static int fixed_voltage_enable(struct regulator_dev *dev)
{
struct fixed_voltage_data *data = rdev_get_drvdata(dev);
- if (gpio_is_valid(data->gpio)) {
- gpio_set_value_cansleep(data->gpio, data->enable_high);
- data->is_enabled = true;
- }
+ gpio_set_value_cansleep(data->gpio, data->enable_high);
+ data->is_enabled = true;
return 0;
}
@@ -117,10 +117,8 @@ static int fixed_voltage_disable(struct regulator_dev *dev)
{
struct fixed_voltage_data *data = rdev_get_drvdata(dev);
- if (gpio_is_valid(data->gpio)) {
- gpio_set_value_cansleep(data->gpio, !data->enable_high);
- data->is_enabled = false;
- }
+ gpio_set_value_cansleep(data->gpio, !data->enable_high);
+ data->is_enabled = false;
return 0;
}
@@ -153,7 +151,7 @@ static int fixed_voltage_list_voltage(struct regulator_dev *dev,
return data->microvolts;
}
-static struct regulator_ops fixed_voltage_ops = {
+static struct regulator_ops fixed_voltage_gpio_ops = {
.is_enabled = fixed_voltage_is_enabled,
.enable = fixed_voltage_enable,
.disable = fixed_voltage_disable,
@@ -162,10 +160,16 @@ static struct regulator_ops fixed_voltage_ops = {
.list_voltage = fixed_voltage_list_voltage,
};
+static struct regulator_ops fixed_voltage_ops = {
+ .get_voltage = fixed_voltage_get_voltage,
+ .list_voltage = fixed_voltage_list_voltage,
+};
+
static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
{
struct fixed_voltage_config *config;
struct fixed_voltage_data *drvdata;
+ struct regulator_config cfg = { };
int ret;
if (pdev->dev.of_node)
@@ -176,7 +180,8 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
if (!config)
return -ENOMEM;
- drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL);
+ drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
+ GFP_KERNEL);
if (drvdata == NULL) {
dev_err(&pdev->dev, "Failed to allocate device data\n");
ret = -ENOMEM;
@@ -191,7 +196,6 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
}
drvdata->desc.type = REGULATOR_VOLTAGE;
drvdata->desc.owner = THIS_MODULE;
- drvdata->desc.ops = &fixed_voltage_ops;
if (config->microvolts)
drvdata->desc.n_voltages = 1;
@@ -201,6 +205,7 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
drvdata->startup_delay = config->startup_delay;
if (gpio_is_valid(config->gpio)) {
+ int gpio_flag;
drvdata->enable_high = config->enable_high;
/* FIXME: Remove below print warning
@@ -218,39 +223,39 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
dev_warn(&pdev->dev,
"using GPIO 0 for regulator enable control\n");
- ret = gpio_request(config->gpio, config->supply_name);
- if (ret) {
- dev_err(&pdev->dev,
- "Could not obtain regulator enable GPIO %d: %d\n",
- config->gpio, ret);
- goto err_name;
- }
-
- /* set output direction without changing state
+ /*
+ * set output direction without changing state
* to prevent glitch
*/
drvdata->is_enabled = config->enabled_at_boot;
ret = drvdata->is_enabled ?
config->enable_high : !config->enable_high;
+ gpio_flag = ret ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+
+ if (config->gpio_is_open_drain)
+ gpio_flag |= GPIOF_OPEN_DRAIN;
- ret = gpio_direction_output(config->gpio, ret);
+ ret = gpio_request_one(config->gpio, gpio_flag,
+ config->supply_name);
if (ret) {
dev_err(&pdev->dev,
- "Could not configure regulator enable GPIO %d direction: %d\n",
+ "Could not obtain regulator enable GPIO %d: %d\n",
config->gpio, ret);
- goto err_gpio;
+ goto err_name;
}
+ drvdata->desc.ops = &fixed_voltage_gpio_ops;
+
} else {
- /* Regulator without GPIO control is considered
- * always enabled
- */
- drvdata->is_enabled = true;
+ drvdata->desc.ops = &fixed_voltage_ops;
}
- drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
- config->init_data, drvdata,
- pdev->dev.of_node);
+ cfg.dev = &pdev->dev;
+ cfg.init_data = config->init_data;
+ cfg.driver_data = drvdata;
+ cfg.of_node = pdev->dev.of_node;
+
+ drvdata->dev = regulator_register(&drvdata->desc, &cfg);
if (IS_ERR(drvdata->dev)) {
ret = PTR_ERR(drvdata->dev);
dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
@@ -270,7 +275,6 @@ err_gpio:
err_name:
kfree(drvdata->desc.name);
err:
- kfree(drvdata);
return ret;
}
@@ -282,7 +286,6 @@ static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
if (gpio_is_valid(drvdata->gpio))
gpio_free(drvdata->gpio);
kfree(drvdata->desc.name);
- kfree(drvdata);
return 0;
}
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index 42e1cb1835e5..9997d7aaca84 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -30,7 +30,6 @@
#include <linux/regulator/machine.h>
#include <linux/regulator/gpio-regulator.h>
#include <linux/gpio.h>
-#include <linux/delay.h>
#include <linux/slab.h>
struct gpio_regulator_data {
@@ -105,15 +104,15 @@ static int gpio_regulator_set_value(struct regulator_dev *dev,
int min, int max)
{
struct gpio_regulator_data *data = rdev_get_drvdata(dev);
- int ptr, target, state;
+ int ptr, target, state, best_val = INT_MAX;
- target = -1;
for (ptr = 0; ptr < data->nr_states; ptr++)
- if (data->states[ptr].value >= min &&
+ if (data->states[ptr].value < best_val &&
+ data->states[ptr].value >= min &&
data->states[ptr].value <= max)
target = data->states[ptr].gpios;
- if (target < 0)
+ if (best_val == INT_MAX)
return -EINVAL;
for (ptr = 0; ptr < data->nr_gpios; ptr++) {
@@ -172,9 +171,11 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
{
struct gpio_regulator_config *config = pdev->dev.platform_data;
struct gpio_regulator_data *drvdata;
+ struct regulator_config cfg = { };
int ptr, ret, state;
- drvdata = kzalloc(sizeof(struct gpio_regulator_data), GFP_KERNEL);
+ drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
+ GFP_KERNEL);
if (drvdata == NULL) {
dev_err(&pdev->dev, "Failed to allocate device data\n");
return -ENOMEM;
@@ -283,8 +284,11 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
}
drvdata->state = state;
- drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
- config->init_data, drvdata, NULL);
+ cfg.dev = &pdev->dev;
+ cfg.init_data = config->init_data;
+ cfg.driver_data = &drvdata;
+
+ drvdata->dev = regulator_register(&drvdata->desc, &cfg);
if (IS_ERR(drvdata->dev)) {
ret = PTR_ERR(drvdata->dev);
dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
@@ -307,7 +311,6 @@ err_memgpio:
err_name:
kfree(drvdata->desc.name);
err:
- kfree(drvdata);
return ret;
}
@@ -326,7 +329,6 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev)
gpio_free(drvdata->enable_gpio);
kfree(drvdata->desc.name);
- kfree(drvdata);
return 0;
}
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
index 775f5fd208c3..56d273f25603 100644
--- a/drivers/regulator/isl6271a-regulator.c
+++ b/drivers/regulator/isl6271a-regulator.c
@@ -22,7 +22,6 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/i2c.h>
-#include <linux/delay.h>
#include <linux/slab.h>
#define ISL6271A_VOLTAGE_MIN 850000
@@ -36,47 +35,30 @@ struct isl_pmic {
struct mutex mtx;
};
-static int isl6271a_get_voltage(struct regulator_dev *dev)
+static int isl6271a_get_voltage_sel(struct regulator_dev *dev)
{
struct isl_pmic *pmic = rdev_get_drvdata(dev);
- int idx, data;
+ int idx;
mutex_lock(&pmic->mtx);
idx = i2c_smbus_read_byte(pmic->client);
- if (idx < 0) {
+ if (idx < 0)
dev_err(&pmic->client->dev, "Error getting voltage\n");
- data = idx;
- goto out;
- }
-
- /* Convert the data from chip to microvolts */
- data = ISL6271A_VOLTAGE_MIN + (ISL6271A_VOLTAGE_STEP * (idx & 0xf));
-out:
mutex_unlock(&pmic->mtx);
- return data;
+ return idx;
}
-static int isl6271a_set_voltage(struct regulator_dev *dev,
- int minuV, int maxuV,
- unsigned *selector)
+static int isl6271a_set_voltage_sel(struct regulator_dev *dev,
+ unsigned selector)
{
struct isl_pmic *pmic = rdev_get_drvdata(dev);
- int err, data;
-
- if (minuV < ISL6271A_VOLTAGE_MIN || minuV > ISL6271A_VOLTAGE_MAX)
- return -EINVAL;
- if (maxuV < ISL6271A_VOLTAGE_MIN || maxuV > ISL6271A_VOLTAGE_MAX)
- return -EINVAL;
-
- data = DIV_ROUND_UP(minuV - ISL6271A_VOLTAGE_MIN,
- ISL6271A_VOLTAGE_STEP);
- *selector = data;
+ int err;
mutex_lock(&pmic->mtx);
- err = i2c_smbus_write_byte(pmic->client, data);
+ err = i2c_smbus_write_byte(pmic->client, selector);
if (err < 0)
dev_err(&pmic->client->dev, "Error setting voltage\n");
@@ -84,15 +66,11 @@ static int isl6271a_set_voltage(struct regulator_dev *dev,
return err;
}
-static int isl6271a_list_voltage(struct regulator_dev *dev, unsigned selector)
-{
- return ISL6271A_VOLTAGE_MIN + (ISL6271A_VOLTAGE_STEP * selector);
-}
-
static struct regulator_ops isl_core_ops = {
- .get_voltage = isl6271a_get_voltage,
- .set_voltage = isl6271a_set_voltage,
- .list_voltage = isl6271a_list_voltage,
+ .get_voltage_sel = isl6271a_get_voltage_sel,
+ .set_voltage_sel = isl6271a_set_voltage_sel,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
};
static int isl6271a_get_fixed_voltage(struct regulator_dev *dev)
@@ -112,7 +90,7 @@ static struct regulator_ops isl_fixed_ops = {
.list_voltage = isl6271a_list_fixed_voltage,
};
-static struct regulator_desc isl_rd[] = {
+static const struct regulator_desc isl_rd[] = {
{
.name = "Core Buck",
.id = 0,
@@ -120,6 +98,8 @@ static struct regulator_desc isl_rd[] = {
.ops = &isl_core_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
+ .min_uV = ISL6271A_VOLTAGE_MIN,
+ .uV_step = ISL6271A_VOLTAGE_STEP,
}, {
.name = "LDO1",
.id = 1,
@@ -140,6 +120,7 @@ static struct regulator_desc isl_rd[] = {
static int __devinit isl6271a_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
+ struct regulator_config config = { };
struct regulator_init_data *init_data = i2c->dev.platform_data;
struct isl_pmic *pmic;
int err, i;
@@ -147,12 +128,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c,
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
- if (!init_data) {
- dev_err(&i2c->dev, "no platform data supplied\n");
- return -EIO;
- }
-
- pmic = kzalloc(sizeof(struct isl_pmic), GFP_KERNEL);
+ pmic = devm_kzalloc(&i2c->dev, sizeof(struct isl_pmic), GFP_KERNEL);
if (!pmic)
return -ENOMEM;
@@ -161,8 +137,14 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c,
mutex_init(&pmic->mtx);
for (i = 0; i < 3; i++) {
- pmic->rdev[i] = regulator_register(&isl_rd[i], &i2c->dev,
- init_data, pmic, NULL);
+ config.dev = &i2c->dev;
+ if (i == 0)
+ config.init_data = init_data;
+ else
+ config.init_data = 0;
+ config.driver_data = pmic;
+
+ pmic->rdev[i] = regulator_register(&isl_rd[i], &config);
if (IS_ERR(pmic->rdev[i])) {
dev_err(&i2c->dev, "failed to register %s\n", id->name);
err = PTR_ERR(pmic->rdev[i]);
@@ -177,8 +159,6 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c,
error:
while (--i >= 0)
regulator_unregister(pmic->rdev[i]);
-
- kfree(pmic);
return err;
}
@@ -189,9 +169,6 @@ static int __devexit isl6271a_remove(struct i2c_client *i2c)
for (i = 0; i < 3; i++)
regulator_unregister(pmic->rdev[i]);
-
- kfree(pmic);
-
return 0;
}
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 0cfabd318a59..981bea9cb9d7 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -124,6 +124,10 @@ static const int *ldo_voltage_map[] = {
static int lp3971_ldo_list_voltage(struct regulator_dev *dev, unsigned index)
{
int ldo = rdev_get_id(dev) - LP3971_LDO1;
+
+ if (index > LDO_VOL_MAX_IDX)
+ return -EINVAL;
+
return 1000 * LDO_VOL_VALUE_MAP(ldo)[index];
}
@@ -168,32 +172,15 @@ static int lp3971_ldo_get_voltage(struct regulator_dev *dev)
return 1000 * LDO_VOL_VALUE_MAP(ldo)[val];
}
-static int lp3971_ldo_set_voltage(struct regulator_dev *dev,
- int min_uV, int max_uV,
- unsigned int *selector)
+static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev,
+ unsigned int selector)
{
struct lp3971 *lp3971 = rdev_get_drvdata(dev);
int ldo = rdev_get_id(dev) - LP3971_LDO1;
- int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
- const int *vol_map = LDO_VOL_VALUE_MAP(ldo);
- u16 val;
-
- if (min_vol < vol_map[LDO_VOL_MIN_IDX] ||
- min_vol > vol_map[LDO_VOL_MAX_IDX])
- return -EINVAL;
-
- for (val = LDO_VOL_MIN_IDX; val <= LDO_VOL_MAX_IDX; val++)
- if (vol_map[val] >= min_vol)
- break;
-
- if (val > LDO_VOL_MAX_IDX || vol_map[val] > max_vol)
- return -EINVAL;
-
- *selector = val;
return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo),
LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo),
- val << LDO_VOL_CONTR_SHIFT(ldo));
+ selector << LDO_VOL_CONTR_SHIFT(ldo));
}
static struct regulator_ops lp3971_ldo_ops = {
@@ -202,11 +189,14 @@ static struct regulator_ops lp3971_ldo_ops = {
.enable = lp3971_ldo_enable,
.disable = lp3971_ldo_disable,
.get_voltage = lp3971_ldo_get_voltage,
- .set_voltage = lp3971_ldo_set_voltage,
+ .set_voltage_sel = lp3971_ldo_set_voltage_sel,
};
static int lp3971_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
{
+ if (index < BUCK_TARGET_VOL_MIN_IDX || index > BUCK_TARGET_VOL_MAX_IDX)
+ return -EINVAL;
+
return 1000 * buck_voltage_map[index];
}
@@ -259,33 +249,15 @@ static int lp3971_dcdc_get_voltage(struct regulator_dev *dev)
return val;
}
-static int lp3971_dcdc_set_voltage(struct regulator_dev *dev,
- int min_uV, int max_uV,
- unsigned int *selector)
+static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev,
+ unsigned int selector)
{
struct lp3971 *lp3971 = rdev_get_drvdata(dev);
int buck = rdev_get_id(dev) - LP3971_DCDC1;
- int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
- const int *vol_map = buck_voltage_map;
- u16 val;
int ret;
- if (min_vol < vol_map[BUCK_TARGET_VOL_MIN_IDX] ||
- min_vol > vol_map[BUCK_TARGET_VOL_MAX_IDX])
- return -EINVAL;
-
- for (val = BUCK_TARGET_VOL_MIN_IDX; val <= BUCK_TARGET_VOL_MAX_IDX;
- val++)
- if (vol_map[val] >= min_vol)
- break;
-
- if (val > BUCK_TARGET_VOL_MAX_IDX || vol_map[val] > max_vol)
- return -EINVAL;
-
- *selector = val;
-
ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck),
- BUCK_TARGET_VOL_MASK, val);
+ BUCK_TARGET_VOL_MASK, selector);
if (ret)
return ret;
@@ -306,10 +278,10 @@ static struct regulator_ops lp3971_dcdc_ops = {
.enable = lp3971_dcdc_enable,
.disable = lp3971_dcdc_disable,
.get_voltage = lp3971_dcdc_get_voltage,
- .set_voltage = lp3971_dcdc_set_voltage,
+ .set_voltage_sel = lp3971_dcdc_set_voltage_sel,
};
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc regulators[] = {
{
.name = "LDO1",
.id = LP3971_LDO1,
@@ -449,10 +421,15 @@ static int __devinit setup_regulators(struct lp3971 *lp3971,
/* Instantiate the regulators */
for (i = 0; i < pdata->num_regulators; i++) {
+ struct regulator_config config = { };
struct lp3971_regulator_subdev *reg = &pdata->regulators[i];
- lp3971->rdev[i] = regulator_register(&regulators[reg->id],
- lp3971->dev, reg->initdata, lp3971, NULL);
+ config.dev = lp3971->dev;
+ config.init_data = reg->initdata;
+ config.driver_data = lp3971;
+
+ lp3971->rdev[i] = regulator_register(&regulators[reg->id],
+ &config);
if (IS_ERR(lp3971->rdev[i])) {
err = PTR_ERR(lp3971->rdev[i]);
dev_err(lp3971->dev, "regulator init failed: %d\n",
@@ -545,23 +522,7 @@ static struct i2c_driver lp3971_i2c_driver = {
.id_table = lp3971_i2c_id,
};
-static int __init lp3971_module_init(void)
-{
- int ret;
-
- ret = i2c_add_driver(&lp3971_i2c_driver);
- if (ret != 0)
- pr_err("Failed to register I2C driver: %d\n", ret);
-
- return ret;
-}
-module_init(lp3971_module_init);
-
-static void __exit lp3971_module_exit(void)
-{
- i2c_del_driver(&lp3971_i2c_driver);
-}
-module_exit(lp3971_module_exit);
+module_i2c_driver(lp3971_i2c_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marek Szyprowski <m.szyprowski@samsung.com>");
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
index 49a15eefe5fe..de073df7d344 100644
--- a/drivers/regulator/lp3972.c
+++ b/drivers/regulator/lp3972.c
@@ -245,6 +245,11 @@ static int lp3972_set_bits(struct lp3972 *lp3972, u8 reg, u16 mask, u16 val)
static int lp3972_ldo_list_voltage(struct regulator_dev *dev, unsigned index)
{
int ldo = rdev_get_id(dev) - LP3972_LDO1;
+
+ if (index < LP3972_LDO_VOL_MIN_IDX(ldo) ||
+ index > LP3972_LDO_VOL_MAX_IDX(ldo))
+ return -EINVAL;
+
return 1000 * LP3972_LDO_VOL_VALUE_MAP(ldo)[index];
}
@@ -292,34 +297,16 @@ static int lp3972_ldo_get_voltage(struct regulator_dev *dev)
return 1000 * LP3972_LDO_VOL_VALUE_MAP(ldo)[val];
}
-static int lp3972_ldo_set_voltage(struct regulator_dev *dev,
- int min_uV, int max_uV,
- unsigned int *selector)
+static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev,
+ unsigned int selector)
{
struct lp3972 *lp3972 = rdev_get_drvdata(dev);
int ldo = rdev_get_id(dev) - LP3972_LDO1;
- int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
- const int *vol_map = LP3972_LDO_VOL_VALUE_MAP(ldo);
- u16 val;
int shift, ret;
- if (min_vol < vol_map[LP3972_LDO_VOL_MIN_IDX(ldo)] ||
- min_vol > vol_map[LP3972_LDO_VOL_MAX_IDX(ldo)])
- return -EINVAL;
-
- for (val = LP3972_LDO_VOL_MIN_IDX(ldo);
- val <= LP3972_LDO_VOL_MAX_IDX(ldo); val++)
- if (vol_map[val] >= min_vol)
- break;
-
- if (val > LP3972_LDO_VOL_MAX_IDX(ldo) || vol_map[val] > max_vol)
- return -EINVAL;
-
- *selector = val;
-
shift = LP3972_LDO_VOL_CONTR_SHIFT(ldo);
ret = lp3972_set_bits(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo),
- LP3972_LDO_VOL_MASK(ldo) << shift, val << shift);
+ LP3972_LDO_VOL_MASK(ldo) << shift, selector << shift);
if (ret)
return ret;
@@ -355,12 +342,17 @@ static struct regulator_ops lp3972_ldo_ops = {
.enable = lp3972_ldo_enable,
.disable = lp3972_ldo_disable,
.get_voltage = lp3972_ldo_get_voltage,
- .set_voltage = lp3972_ldo_set_voltage,
+ .set_voltage_sel = lp3972_ldo_set_voltage_sel,
};
static int lp3972_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
{
int buck = rdev_get_id(dev) - LP3972_DCDC1;
+
+ if (index < LP3972_BUCK_VOL_MIN_IDX(buck) ||
+ index > LP3972_BUCK_VOL_MAX_IDX(buck))
+ return -EINVAL;
+
return 1000 * buck_voltage_map[buck][index];
}
@@ -419,34 +411,15 @@ static int lp3972_dcdc_get_voltage(struct regulator_dev *dev)
return val;
}
-static int lp3972_dcdc_set_voltage(struct regulator_dev *dev,
- int min_uV, int max_uV,
- unsigned int *selector)
+static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev,
+ unsigned int selector)
{
struct lp3972 *lp3972 = rdev_get_drvdata(dev);
int buck = rdev_get_id(dev) - LP3972_DCDC1;
- int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
- const int *vol_map = buck_voltage_map[buck];
- u16 val;
int ret;
- if (min_vol < vol_map[LP3972_BUCK_VOL_MIN_IDX(buck)] ||
- min_vol > vol_map[LP3972_BUCK_VOL_MAX_IDX(buck)])
- return -EINVAL;
-
- for (val = LP3972_BUCK_VOL_MIN_IDX(buck);
- val <= LP3972_BUCK_VOL_MAX_IDX(buck); val++)
- if (vol_map[val] >= min_vol)
- break;
-
- if (val > LP3972_BUCK_VOL_MAX_IDX(buck) ||
- vol_map[val] > max_vol)
- return -EINVAL;
-
- *selector = val;
-
ret = lp3972_set_bits(lp3972, LP3972_BUCK_VOL1_REG(buck),
- LP3972_BUCK_VOL_MASK, val);
+ LP3972_BUCK_VOL_MASK, selector);
if (ret)
return ret;
@@ -468,10 +441,10 @@ static struct regulator_ops lp3972_dcdc_ops = {
.enable = lp3972_dcdc_enable,
.disable = lp3972_dcdc_disable,
.get_voltage = lp3972_dcdc_get_voltage,
- .set_voltage = lp3972_dcdc_set_voltage,
+ .set_voltage_sel = lp3972_dcdc_set_voltage_sel,
};
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc regulators[] = {
{
.name = "LDO1",
.id = LP3972_LDO1,
@@ -554,9 +527,14 @@ static int __devinit setup_regulators(struct lp3972 *lp3972,
/* Instantiate the regulators */
for (i = 0; i < pdata->num_regulators; i++) {
struct lp3972_regulator_subdev *reg = &pdata->regulators[i];
- lp3972->rdev[i] = regulator_register(&regulators[reg->id],
- lp3972->dev, reg->initdata, lp3972, NULL);
+ struct regulator_config config = { };
+ config.dev = lp3972->dev;
+ config.init_data = reg->initdata;
+ config.driver_data = lp3972;
+
+ lp3972->rdev[i] = regulator_register(&regulators[reg->id],
+ &config);
if (IS_ERR(lp3972->rdev[i])) {
err = PTR_ERR(lp3972->rdev[i]);
dev_err(lp3972->dev, "regulator init failed: %d\n",
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index 282d2ee0604e..b9444ee08da9 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -161,7 +161,7 @@ static struct regulator_ops max1586_v6_ops = {
.list_voltage = max1586_v6_list,
};
-static struct regulator_desc max1586_reg[] = {
+static const struct regulator_desc max1586_reg[] = {
{
.name = "Output_V3",
.id = MAX1586_V3,
@@ -185,21 +185,21 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client,
{
struct regulator_dev **rdev;
struct max1586_platform_data *pdata = client->dev.platform_data;
+ struct regulator_config config = { };
struct max1586_data *max1586;
int i, id, ret = -ENOMEM;
- max1586 = kzalloc(sizeof(struct max1586_data) +
+ max1586 = devm_kzalloc(&client->dev, sizeof(struct max1586_data) +
sizeof(struct regulator_dev *) * (MAX1586_V6 + 1),
GFP_KERNEL);
if (!max1586)
- goto out;
+ return -ENOMEM;
max1586->client = client;
- if (!pdata->v3_gain) {
- ret = -EINVAL;
- goto out_unmap;
- }
+ if (!pdata->v3_gain)
+ return -EINVAL;
+
max1586->min_uV = MAX1586_V3_MIN_UV / 1000 * pdata->v3_gain / 1000;
max1586->max_uV = MAX1586_V3_MAX_UV / 1000 * pdata->v3_gain / 1000;
@@ -212,9 +212,12 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client,
dev_err(&client->dev, "invalid regulator id %d\n", id);
goto err;
}
- rdev[i] = regulator_register(&max1586_reg[id], &client->dev,
- pdata->subdevs[i].platform_data,
- max1586, NULL);
+
+ config.dev = &client->dev;
+ config.init_data = pdata->subdevs[i].platform_data;
+ config.driver_data = max1586;
+
+ rdev[i] = regulator_register(&max1586_reg[id], &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
dev_err(&client->dev, "failed to register %s\n",
@@ -230,9 +233,6 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client,
err:
while (--i >= 0)
regulator_unregister(rdev[i]);
-out_unmap:
- kfree(max1586);
-out:
return ret;
}
@@ -244,8 +244,6 @@ static int __devexit max1586_pmic_remove(struct i2c_client *client)
for (i = 0; i <= MAX1586_V6; i++)
if (max1586->rdev[i])
regulator_unregister(max1586->rdev[i]);
- kfree(max1586);
-
return 0;
}
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index 824c650436ed..1f4bb80457b3 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -53,7 +53,6 @@ struct max8649_regulator_info {
struct device *dev;
struct regmap *regmap;
- int vol_reg;
unsigned mode:2; /* bit[1:0] = VID1, VID0 */
unsigned extclk_freq:2;
unsigned extclk:1;
@@ -61,53 +60,6 @@ struct max8649_regulator_info {
unsigned ramp_down:1;
};
-/* I2C operations */
-
-static inline int check_range(int min_uV, int max_uV)
-{
- if ((min_uV < MAX8649_DCDC_VMIN) || (max_uV > MAX8649_DCDC_VMAX)
- || (min_uV > max_uV))
- return -EINVAL;
- return 0;
-}
-
-static int max8649_list_voltage(struct regulator_dev *rdev, unsigned index)
-{
- return (MAX8649_DCDC_VMIN + index * MAX8649_DCDC_STEP);
-}
-
-static int max8649_get_voltage(struct regulator_dev *rdev)
-{
- struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
- unsigned int val;
- unsigned char data;
- int ret;
-
- ret = regmap_read(info->regmap, info->vol_reg, &val);
- if (ret != 0)
- return ret;
- data = (unsigned char)val & MAX8649_VOL_MASK;
- return max8649_list_voltage(rdev, data);
-}
-
-static int max8649_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *selector)
-{
- struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
- unsigned char data, mask;
-
- if (check_range(min_uV, max_uV)) {
- dev_err(info->dev, "invalid voltage range (%d, %d) uV\n",
- min_uV, max_uV);
- return -EINVAL;
- }
- data = DIV_ROUND_UP(min_uV - MAX8649_DCDC_VMIN, MAX8649_DCDC_STEP);
- mask = MAX8649_VOL_MASK;
- *selector = data & mask;
-
- return regmap_update_bits(info->regmap, info->vol_reg, mask, data);
-}
-
/* EN_PD means pulldown on EN input */
static int max8649_enable(struct regulator_dev *rdev)
{
@@ -145,11 +97,11 @@ static int max8649_enable_time(struct regulator_dev *rdev)
unsigned int val;
/* get voltage */
- ret = regmap_read(info->regmap, info->vol_reg, &val);
+ ret = regmap_read(info->regmap, rdev->desc->vsel_reg, &val);
if (ret != 0)
return ret;
val &= MAX8649_VOL_MASK;
- voltage = max8649_list_voltage(rdev, (unsigned char)val); /* uV */
+ voltage = regulator_list_voltage_linear(rdev, (unsigned char)val);
/* get rate */
ret = regmap_read(info->regmap, MAX8649_RAMP, &val);
@@ -167,11 +119,11 @@ static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode)
switch (mode) {
case REGULATOR_MODE_FAST:
- regmap_update_bits(info->regmap, info->vol_reg, MAX8649_FORCE_PWM,
- MAX8649_FORCE_PWM);
+ regmap_update_bits(info->regmap, rdev->desc->vsel_reg,
+ MAX8649_FORCE_PWM, MAX8649_FORCE_PWM);
break;
case REGULATOR_MODE_NORMAL:
- regmap_update_bits(info->regmap, info->vol_reg,
+ regmap_update_bits(info->regmap, rdev->desc->vsel_reg,
MAX8649_FORCE_PWM, 0);
break;
default:
@@ -186,7 +138,7 @@ static unsigned int max8649_get_mode(struct regulator_dev *rdev)
unsigned int val;
int ret;
- ret = regmap_read(info->regmap, info->vol_reg, &val);
+ ret = regmap_read(info->regmap, rdev->desc->vsel_reg, &val);
if (ret != 0)
return ret;
if (val & MAX8649_FORCE_PWM)
@@ -195,9 +147,10 @@ static unsigned int max8649_get_mode(struct regulator_dev *rdev)
}
static struct regulator_ops max8649_dcdc_ops = {
- .set_voltage = max8649_set_voltage,
- .get_voltage = max8649_get_voltage,
- .list_voltage = max8649_list_voltage,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
.enable = max8649_enable,
.disable = max8649_disable,
.is_enabled = max8649_is_enabled,
@@ -213,6 +166,9 @@ static struct regulator_desc dcdc_desc = {
.type = REGULATOR_VOLTAGE,
.n_voltages = 1 << 6,
.owner = THIS_MODULE,
+ .vsel_mask = MAX8649_VOL_MASK,
+ .min_uV = MAX8649_DCDC_VMIN,
+ .uV_step = MAX8649_DCDC_STEP,
};
static struct regmap_config max8649_regmap_config = {
@@ -225,21 +181,23 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
{
struct max8649_platform_data *pdata = client->dev.platform_data;
struct max8649_regulator_info *info = NULL;
+ struct regulator_config config = { };
unsigned int val;
unsigned char data;
int ret;
- info = kzalloc(sizeof(struct max8649_regulator_info), GFP_KERNEL);
+ info = devm_kzalloc(&client->dev, sizeof(struct max8649_regulator_info),
+ GFP_KERNEL);
if (!info) {
dev_err(&client->dev, "No enough memory\n");
return -ENOMEM;
}
- info->regmap = regmap_init_i2c(client, &max8649_regmap_config);
+ info->regmap = devm_regmap_init_i2c(client, &max8649_regmap_config);
if (IS_ERR(info->regmap)) {
ret = PTR_ERR(info->regmap);
dev_err(&client->dev, "Failed to allocate register map: %d\n", ret);
- goto fail;
+ return ret;
}
info->dev = &client->dev;
@@ -248,16 +206,16 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
info->mode = pdata->mode;
switch (info->mode) {
case 0:
- info->vol_reg = MAX8649_MODE0;
+ dcdc_desc.vsel_reg = MAX8649_MODE0;
break;
case 1:
- info->vol_reg = MAX8649_MODE1;
+ dcdc_desc.vsel_reg = MAX8649_MODE1;
break;
case 2:
- info->vol_reg = MAX8649_MODE2;
+ dcdc_desc.vsel_reg = MAX8649_MODE2;
break;
case 3:
- info->vol_reg = MAX8649_MODE3;
+ dcdc_desc.vsel_reg = MAX8649_MODE3;
break;
default:
break;
@@ -267,7 +225,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
if (ret != 0) {
dev_err(info->dev, "Failed to detect ID of MAX8649:%d\n",
ret);
- goto out;
+ return ret;
}
dev_info(info->dev, "Detected MAX8649 (ID:%x)\n", val);
@@ -277,7 +235,8 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
/* enable/disable external clock synchronization */
info->extclk = pdata->extclk;
data = (info->extclk) ? MAX8649_SYNC_EXTCLK : 0;
- regmap_update_bits(info->regmap, info->vol_reg, MAX8649_SYNC_EXTCLK, data);
+ regmap_update_bits(info->regmap, dcdc_desc.vsel_reg,
+ MAX8649_SYNC_EXTCLK, data);
if (info->extclk) {
/* set external clock frequency */
info->extclk_freq = pdata->extclk_freq;
@@ -297,22 +256,18 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
MAX8649_RAMP_DOWN);
}
- info->regulator = regulator_register(&dcdc_desc, &client->dev,
- pdata->regulator, info, NULL);
+ config.dev = &client->dev;
+ config.init_data = pdata->regulator;
+ config.driver_data = info;
+
+ info->regulator = regulator_register(&dcdc_desc, &config);
if (IS_ERR(info->regulator)) {
dev_err(info->dev, "failed to register regulator %s\n",
dcdc_desc.name);
- ret = PTR_ERR(info->regulator);
- goto out;
+ return PTR_ERR(info->regulator);
}
- dev_info(info->dev, "Max8649 regulator device is detected.\n");
return 0;
-out:
- regmap_exit(info->regmap);
-fail:
- kfree(info);
- return ret;
}
static int __devexit max8649_regulator_remove(struct i2c_client *client)
@@ -322,8 +277,6 @@ static int __devexit max8649_regulator_remove(struct i2c_client *client)
if (info) {
if (info->regulator)
regulator_unregister(info->regulator);
- regmap_exit(info->regmap);
- kfree(info);
}
return 0;
@@ -360,4 +313,3 @@ module_exit(max8649_exit);
MODULE_DESCRIPTION("MAXIM 8649 voltage regulator driver");
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
MODULE_LICENSE("GPL");
-
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index 4c5b05311f47..8d531742f593 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -126,42 +126,22 @@ static int max8660_dcdc_disable(struct regulator_dev *rdev)
return max8660_write(max8660, MAX8660_OVER1, mask, 0);
}
-static int max8660_dcdc_list(struct regulator_dev *rdev, unsigned selector)
-{
- if (selector > MAX8660_DCDC_MAX_SEL)
- return -EINVAL;
- return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP;
-}
-
-static int max8660_dcdc_get(struct regulator_dev *rdev)
+static int max8660_dcdc_get_voltage_sel(struct regulator_dev *rdev)
{
struct max8660 *max8660 = rdev_get_drvdata(rdev);
+
u8 reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2;
u8 selector = max8660->shadow_regs[reg];
- return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP;
+ return selector;
}
-static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV,
- unsigned int *s)
+static int max8660_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int selector)
{
struct max8660 *max8660 = rdev_get_drvdata(rdev);
- u8 reg, selector, bits;
+ u8 reg, bits;
int ret;
- if (min_uV < MAX8660_DCDC_MIN_UV || min_uV > MAX8660_DCDC_MAX_UV)
- return -EINVAL;
- if (max_uV < MAX8660_DCDC_MIN_UV || max_uV > MAX8660_DCDC_MAX_UV)
- return -EINVAL;
-
- selector = DIV_ROUND_UP(min_uV - MAX8660_DCDC_MIN_UV,
- MAX8660_DCDC_STEP);
-
- ret = max8660_dcdc_list(rdev, selector);
- if (ret < 0 || ret > max_uV)
- return -EINVAL;
-
- *s = selector;
-
reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2;
ret = max8660_write(max8660, reg, 0, selector);
if (ret)
@@ -174,9 +154,10 @@ static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV,
static struct regulator_ops max8660_dcdc_ops = {
.is_enabled = max8660_dcdc_is_enabled,
- .list_voltage = max8660_dcdc_list,
- .set_voltage = max8660_dcdc_set,
- .get_voltage = max8660_dcdc_get,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .set_voltage_sel = max8660_dcdc_set_voltage_sel,
+ .get_voltage_sel = max8660_dcdc_get_voltage_sel,
};
@@ -184,42 +165,20 @@ static struct regulator_ops max8660_dcdc_ops = {
* LDO5 functions
*/
-static int max8660_ldo5_list(struct regulator_dev *rdev, unsigned selector)
-{
- if (selector > MAX8660_LDO5_MAX_SEL)
- return -EINVAL;
- return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP;
-}
-
-static int max8660_ldo5_get(struct regulator_dev *rdev)
+static int max8660_ldo5_get_voltage_sel(struct regulator_dev *rdev)
{
struct max8660 *max8660 = rdev_get_drvdata(rdev);
- u8 selector = max8660->shadow_regs[MAX8660_MDTV2];
- return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP;
+ u8 selector = max8660->shadow_regs[MAX8660_MDTV2];
+ return selector;
}
-static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV,
- unsigned int *s)
+static int max8660_ldo5_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int selector)
{
struct max8660 *max8660 = rdev_get_drvdata(rdev);
- u8 selector;
int ret;
- if (min_uV < MAX8660_LDO5_MIN_UV || min_uV > MAX8660_LDO5_MAX_UV)
- return -EINVAL;
- if (max_uV < MAX8660_LDO5_MIN_UV || max_uV > MAX8660_LDO5_MAX_UV)
- return -EINVAL;
-
- selector = DIV_ROUND_UP(min_uV - MAX8660_LDO5_MIN_UV,
- MAX8660_LDO5_STEP);
-
- ret = max8660_ldo5_list(rdev, selector);
- if (ret < 0 || ret > max_uV)
- return -EINVAL;
-
- *s = selector;
-
ret = max8660_write(max8660, MAX8660_MDTV2, 0, selector);
if (ret)
return ret;
@@ -229,9 +188,10 @@ static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV,
}
static struct regulator_ops max8660_ldo5_ops = {
- .list_voltage = max8660_ldo5_list,
- .set_voltage = max8660_ldo5_set,
- .get_voltage = max8660_ldo5_get,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .set_voltage_sel = max8660_ldo5_set_voltage_sel,
+ .get_voltage_sel = max8660_ldo5_get_voltage_sel,
};
@@ -261,59 +221,38 @@ static int max8660_ldo67_disable(struct regulator_dev *rdev)
return max8660_write(max8660, MAX8660_OVER2, mask, 0);
}
-static int max8660_ldo67_list(struct regulator_dev *rdev, unsigned selector)
-{
- if (selector > MAX8660_LDO67_MAX_SEL)
- return -EINVAL;
- return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP;
-}
-
-static int max8660_ldo67_get(struct regulator_dev *rdev)
+static int max8660_ldo67_get_voltage_sel(struct regulator_dev *rdev)
{
struct max8660 *max8660 = rdev_get_drvdata(rdev);
+
u8 shift = (rdev_get_id(rdev) == MAX8660_V6) ? 0 : 4;
u8 selector = (max8660->shadow_regs[MAX8660_L12VCR] >> shift) & 0xf;
-
- return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP;
+ return selector;
}
-static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV,
- int max_uV, unsigned int *s)
+static int max8660_ldo67_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int selector)
{
struct max8660 *max8660 = rdev_get_drvdata(rdev);
- u8 selector;
- int ret;
-
- if (min_uV < MAX8660_LDO67_MIN_UV || min_uV > MAX8660_LDO67_MAX_UV)
- return -EINVAL;
- if (max_uV < MAX8660_LDO67_MIN_UV || max_uV > MAX8660_LDO67_MAX_UV)
- return -EINVAL;
-
- selector = DIV_ROUND_UP(min_uV - MAX8660_LDO67_MIN_UV,
- MAX8660_LDO67_STEP);
-
- ret = max8660_ldo67_list(rdev, selector);
- if (ret < 0 || ret > max_uV)
- return -EINVAL;
-
- *s = selector;
if (rdev_get_id(rdev) == MAX8660_V6)
return max8660_write(max8660, MAX8660_L12VCR, 0xf0, selector);
else
- return max8660_write(max8660, MAX8660_L12VCR, 0x0f, selector << 4);
+ return max8660_write(max8660, MAX8660_L12VCR, 0x0f,
+ selector << 4);
}
static struct regulator_ops max8660_ldo67_ops = {
.is_enabled = max8660_ldo67_is_enabled,
.enable = max8660_ldo67_enable,
.disable = max8660_ldo67_disable,
- .list_voltage = max8660_ldo67_list,
- .get_voltage = max8660_ldo67_get,
- .set_voltage = max8660_ldo67_set,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = max8660_ldo67_get_voltage_sel,
+ .set_voltage_sel = max8660_ldo67_set_voltage_sel,
};
-static struct regulator_desc max8660_reg[] = {
+static const struct regulator_desc max8660_reg[] = {
{
.name = "V3(DCDC)",
.id = MAX8660_V3,
@@ -321,6 +260,8 @@ static struct regulator_desc max8660_reg[] = {
.type = REGULATOR_VOLTAGE,
.n_voltages = MAX8660_DCDC_MAX_SEL + 1,
.owner = THIS_MODULE,
+ .min_uV = MAX8660_DCDC_MIN_UV,
+ .uV_step = MAX8660_DCDC_STEP,
},
{
.name = "V4(DCDC)",
@@ -329,6 +270,8 @@ static struct regulator_desc max8660_reg[] = {
.type = REGULATOR_VOLTAGE,
.n_voltages = MAX8660_DCDC_MAX_SEL + 1,
.owner = THIS_MODULE,
+ .min_uV = MAX8660_DCDC_MIN_UV,
+ .uV_step = MAX8660_DCDC_STEP,
},
{
.name = "V5(LDO)",
@@ -337,6 +280,8 @@ static struct regulator_desc max8660_reg[] = {
.type = REGULATOR_VOLTAGE,
.n_voltages = MAX8660_LDO5_MAX_SEL + 1,
.owner = THIS_MODULE,
+ .min_uV = MAX8660_LDO5_MIN_UV,
+ .uV_step = MAX8660_LDO5_STEP,
},
{
.name = "V6(LDO)",
@@ -345,6 +290,8 @@ static struct regulator_desc max8660_reg[] = {
.type = REGULATOR_VOLTAGE,
.n_voltages = MAX8660_LDO67_MAX_SEL + 1,
.owner = THIS_MODULE,
+ .min_uV = MAX8660_LDO67_MIN_UV,
+ .uV_step = MAX8660_LDO67_STEP,
},
{
.name = "V7(LDO)",
@@ -353,6 +300,8 @@ static struct regulator_desc max8660_reg[] = {
.type = REGULATOR_VOLTAGE,
.n_voltages = MAX8660_LDO67_MAX_SEL + 1,
.owner = THIS_MODULE,
+ .min_uV = MAX8660_LDO67_MIN_UV,
+ .uV_step = MAX8660_LDO67_STEP,
},
};
@@ -361,21 +310,20 @@ static int __devinit max8660_probe(struct i2c_client *client,
{
struct regulator_dev **rdev;
struct max8660_platform_data *pdata = client->dev.platform_data;
+ struct regulator_config config = { };
struct max8660 *max8660;
int boot_on, i, id, ret = -EINVAL;
if (pdata->num_subdevs > MAX8660_V_END) {
dev_err(&client->dev, "Too many regulators found!\n");
- goto out;
+ return -EINVAL;
}
- max8660 = kzalloc(sizeof(struct max8660) +
+ max8660 = devm_kzalloc(&client->dev, sizeof(struct max8660) +
sizeof(struct regulator_dev *) * MAX8660_V_END,
GFP_KERNEL);
- if (!max8660) {
- ret = -ENOMEM;
- goto out;
- }
+ if (!max8660)
+ return -ENOMEM;
max8660->client = client;
rdev = max8660->rdev;
@@ -404,7 +352,7 @@ static int __devinit max8660_probe(struct i2c_client *client,
for (i = 0; i < pdata->num_subdevs; i++) {
if (!pdata->subdevs[i].platform_data)
- goto err_free;
+ goto err_out;
boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
@@ -430,7 +378,7 @@ static int __devinit max8660_probe(struct i2c_client *client,
case MAX8660_V7:
if (!strcmp(i2c_id->name, "max8661")) {
dev_err(&client->dev, "Regulator not on this chip!\n");
- goto err_free;
+ goto err_out;
}
if (boot_on)
@@ -440,7 +388,7 @@ static int __devinit max8660_probe(struct i2c_client *client,
default:
dev_err(&client->dev, "invalid regulator %s\n",
pdata->subdevs[i].name);
- goto err_free;
+ goto err_out;
}
}
@@ -449,9 +397,11 @@ static int __devinit max8660_probe(struct i2c_client *client,
id = pdata->subdevs[i].id;
- rdev[i] = regulator_register(&max8660_reg[id], &client->dev,
- pdata->subdevs[i].platform_data,
- max8660, NULL);
+ config.dev = &client->dev;
+ config.init_data = pdata->subdevs[i].platform_data;
+ config.driver_data = max8660;
+
+ rdev[i] = regulator_register(&max8660_reg[id], &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
dev_err(&client->dev, "failed to register %s\n",
@@ -461,15 +411,12 @@ static int __devinit max8660_probe(struct i2c_client *client,
}
i2c_set_clientdata(client, max8660);
- dev_info(&client->dev, "Maxim 8660/8661 regulator driver loaded\n");
return 0;
err_unregister:
while (--i >= 0)
regulator_unregister(rdev[i]);
-err_free:
- kfree(max8660);
-out:
+err_out:
return ret;
}
@@ -481,8 +428,6 @@ static int __devexit max8660_remove(struct i2c_client *client)
for (i = 0; i < MAX8660_V_END; i++)
if (max8660->rdev[i])
regulator_unregister(max8660->rdev[i]);
- kfree(max8660);
-
return 0;
}
diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c
index 2f242f43096e..43dc97ec3932 100644
--- a/drivers/regulator/max8925-regulator.c
+++ b/drivers/regulator/max8925-regulator.c
@@ -38,50 +38,20 @@ struct max8925_regulator_info {
struct i2c_client *i2c;
struct max8925_chip *chip;
- int min_uV;
- int max_uV;
- int step_uV;
int vol_reg;
- int vol_shift;
- int vol_nbits;
int enable_reg;
};
-static inline int check_range(struct max8925_regulator_info *info,
- int min_uV, int max_uV)
-{
- if (min_uV < info->min_uV || min_uV > info->max_uV)
- return -EINVAL;
-
- return 0;
-}
-
-static int max8925_list_voltage(struct regulator_dev *rdev, unsigned index)
-{
- struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
- return info->min_uV + index * info->step_uV;
-}
-
-static int max8925_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned int *selector)
+static int max8925_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int selector)
{
struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
- unsigned char data, mask;
-
- if (check_range(info, min_uV, max_uV)) {
- dev_err(info->chip->dev, "invalid voltage range (%d, %d) uV\n",
- min_uV, max_uV);
- return -EINVAL;
- }
- data = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
- *selector = data;
- data <<= info->vol_shift;
- mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+ unsigned char mask = rdev->desc->n_voltages - 1;
- return max8925_set_bits(info->i2c, info->vol_reg, mask, data);
+ return max8925_set_bits(info->i2c, info->vol_reg, mask, selector);
}
-static int max8925_get_voltage(struct regulator_dev *rdev)
+static int max8925_get_voltage_sel(struct regulator_dev *rdev)
{
struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
unsigned char data, mask;
@@ -90,10 +60,10 @@ static int max8925_get_voltage(struct regulator_dev *rdev)
ret = max8925_reg_read(info->i2c, info->vol_reg);
if (ret < 0)
return ret;
- mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
- data = (ret & mask) >> info->vol_shift;
+ mask = rdev->desc->n_voltages - 1;
+ data = ret & mask;
- return max8925_list_voltage(rdev, data);
+ return data;
}
static int max8925_enable(struct regulator_dev *rdev)
@@ -163,8 +133,10 @@ static int max8925_set_dvm_disable(struct regulator_dev *rdev)
}
static struct regulator_ops max8925_regulator_sdv_ops = {
- .set_voltage = max8925_set_voltage,
- .get_voltage = max8925_get_voltage,
+ .map_voltage = regulator_map_voltage_linear,
+ .list_voltage = regulator_list_voltage_linear,
+ .set_voltage_sel = max8925_set_voltage_sel,
+ .get_voltage_sel = max8925_get_voltage_sel,
.enable = max8925_enable,
.disable = max8925_disable,
.is_enabled = max8925_is_enabled,
@@ -174,8 +146,10 @@ static struct regulator_ops max8925_regulator_sdv_ops = {
};
static struct regulator_ops max8925_regulator_ldo_ops = {
- .set_voltage = max8925_set_voltage,
- .get_voltage = max8925_get_voltage,
+ .map_voltage = regulator_map_voltage_linear,
+ .list_voltage = regulator_list_voltage_linear,
+ .set_voltage_sel = max8925_set_voltage_sel,
+ .get_voltage_sel = max8925_get_voltage_sel,
.enable = max8925_enable,
.disable = max8925_disable,
.is_enabled = max8925_is_enabled,
@@ -189,13 +163,11 @@ static struct regulator_ops max8925_regulator_ldo_ops = {
.type = REGULATOR_VOLTAGE, \
.id = MAX8925_ID_SD##_id, \
.owner = THIS_MODULE, \
+ .n_voltages = 64, \
+ .min_uV = min * 1000, \
+ .uV_step = step * 1000, \
}, \
- .min_uV = min * 1000, \
- .max_uV = max * 1000, \
- .step_uV = step * 1000, \
.vol_reg = MAX8925_SDV##_id, \
- .vol_shift = 0, \
- .vol_nbits = 6, \
.enable_reg = MAX8925_SDCTL##_id, \
}
@@ -207,13 +179,11 @@ static struct regulator_ops max8925_regulator_ldo_ops = {
.type = REGULATOR_VOLTAGE, \
.id = MAX8925_ID_LDO##_id, \
.owner = THIS_MODULE, \
+ .n_voltages = 64, \
+ .min_uV = min * 1000, \
+ .uV_step = step * 1000, \
}, \
- .min_uV = min * 1000, \
- .max_uV = max * 1000, \
- .step_uV = step * 1000, \
.vol_reg = MAX8925_LDOVOUT##_id, \
- .vol_shift = 0, \
- .vol_nbits = 6, \
.enable_reg = MAX8925_LDOCTL##_id, \
}
@@ -261,6 +231,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
{
struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct max8925_platform_data *pdata = chip->dev->platform_data;
+ struct regulator_config config = { };
struct max8925_regulator_info *ri;
struct regulator_dev *rdev;
@@ -272,8 +243,11 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
ri->i2c = chip->i2c;
ri->chip = chip;
- rdev = regulator_register(&ri->desc, &pdev->dev,
- pdata->regulator[pdev->id], ri, NULL);
+ config.dev = &pdev->dev;
+ config.init_data = pdata->regulator[pdev->id];
+ config.driver_data = ri;
+
+ rdev = regulator_register(&ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
ri->desc.name);
@@ -319,4 +293,3 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
MODULE_DESCRIPTION("Regulator Driver for Maxim 8925 PMIC");
MODULE_ALIAS("platform:max8925-regulator");
-
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index 75d89400c123..910c9b26d499 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -69,11 +69,6 @@ static int max8952_write_reg(struct max8952_data *max8952,
return i2c_smbus_write_byte_data(max8952->client, reg, value);
}
-static int max8952_voltage(struct max8952_data *max8952, u8 mode)
-{
- return (max8952->pdata->dvs_mode[mode] * 10 + 770) * 1000;
-}
-
static int max8952_list_voltage(struct regulator_dev *rdev,
unsigned int selector)
{
@@ -82,7 +77,7 @@ static int max8952_list_voltage(struct regulator_dev *rdev,
if (rdev_get_id(rdev) != 0)
return -EINVAL;
- return max8952_voltage(max8952, selector);
+ return (max8952->pdata->dvs_mode[selector] * 10 + 770) * 1000;
}
static int max8952_is_enabled(struct regulator_dev *rdev)
@@ -117,7 +112,7 @@ static int max8952_disable(struct regulator_dev *rdev)
return 0;
}
-static int max8952_get_voltage(struct regulator_dev *rdev)
+static int max8952_get_voltage_sel(struct regulator_dev *rdev)
{
struct max8952_data *max8952 = rdev_get_drvdata(rdev);
u8 vid = 0;
@@ -127,14 +122,13 @@ static int max8952_get_voltage(struct regulator_dev *rdev)
if (max8952->vid1)
vid += 2;
- return max8952_voltage(max8952, vid);
+ return vid;
}
-static int max8952_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *selector)
+static int max8952_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned selector)
{
struct max8952_data *max8952 = rdev_get_drvdata(rdev);
- s8 vid = -1, i;
if (!gpio_is_valid(max8952->pdata->gpio_vid0) ||
!gpio_is_valid(max8952->pdata->gpio_vid1)) {
@@ -142,23 +136,10 @@ static int max8952_set_voltage(struct regulator_dev *rdev,
return -EPERM;
}
- for (i = 0; i < MAX8952_NUM_DVS_MODE; i++) {
- int volt = max8952_voltage(max8952, i);
-
- /* Set the voltage as low as possible within the range */
- if (volt <= max_uV && volt >= min_uV)
- if (vid == -1 || max8952_voltage(max8952, vid) > volt)
- vid = i;
- }
-
- if (vid >= 0 && vid < MAX8952_NUM_DVS_MODE) {
- max8952->vid0 = (vid % 2 == 1);
- max8952->vid1 = (((vid >> 1) % 2) == 1);
- *selector = vid;
- gpio_set_value(max8952->pdata->gpio_vid0, max8952->vid0);
- gpio_set_value(max8952->pdata->gpio_vid1, max8952->vid1);
- } else
- return -EINVAL;
+ max8952->vid0 = selector & 0x1;
+ max8952->vid1 = (selector >> 1) & 0x1;
+ gpio_set_value(max8952->pdata->gpio_vid0, max8952->vid0);
+ gpio_set_value(max8952->pdata->gpio_vid1, max8952->vid1);
return 0;
}
@@ -168,12 +149,12 @@ static struct regulator_ops max8952_ops = {
.is_enabled = max8952_is_enabled,
.enable = max8952_enable,
.disable = max8952_disable,
- .get_voltage = max8952_get_voltage,
- .set_voltage = max8952_set_voltage,
+ .get_voltage_sel = max8952_get_voltage_sel,
+ .set_voltage_sel = max8952_set_voltage_sel,
.set_suspend_disable = max8952_disable,
};
-static struct regulator_desc regulator = {
+static const struct regulator_desc regulator = {
.name = "MAX8952_VOUT",
.id = 0,
.n_voltages = MAX8952_NUM_DVS_MODE,
@@ -187,6 +168,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct max8952_platform_data *pdata = client->dev.platform_data;
+ struct regulator_config config = { };
struct max8952_data *max8952;
int ret = 0, err = 0;
@@ -199,7 +181,8 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
return -EIO;
- max8952 = kzalloc(sizeof(struct max8952_data), GFP_KERNEL);
+ max8952 = devm_kzalloc(&client->dev, sizeof(struct max8952_data),
+ GFP_KERNEL);
if (!max8952)
return -ENOMEM;
@@ -207,18 +190,21 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
max8952->dev = &client->dev;
max8952->pdata = pdata;
- max8952->rdev = regulator_register(&regulator, max8952->dev,
- &pdata->reg_data, max8952, NULL);
+ config.dev = max8952->dev;
+ config.init_data = &pdata->reg_data;
+ config.driver_data = max8952;
+
+ max8952->rdev = regulator_register(&regulator, &config);
if (IS_ERR(max8952->rdev)) {
ret = PTR_ERR(max8952->rdev);
dev_err(max8952->dev, "regulator init failed (%d)\n", ret);
- goto err_reg;
+ return ret;
}
max8952->en = !!(pdata->reg_data.constraints.boot_on);
- max8952->vid0 = (pdata->default_mode % 2) == 1;
- max8952->vid1 = ((pdata->default_mode >> 1) % 2) == 1;
+ max8952->vid0 = pdata->default_mode & 0x1;
+ max8952->vid1 = (pdata->default_mode >> 1) & 0x1;
if (gpio_is_valid(pdata->gpio_en)) {
if (!gpio_request(pdata->gpio_en, "MAX8952 EN"))
@@ -241,13 +227,13 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
gpio_is_valid(pdata->gpio_vid1)) {
if (!gpio_request(pdata->gpio_vid0, "MAX8952 VID0"))
gpio_direction_output(pdata->gpio_vid0,
- (pdata->default_mode) % 2);
+ (pdata->default_mode) & 0x1);
else
err = 1;
if (!gpio_request(pdata->gpio_vid1, "MAX8952 VID1"))
gpio_direction_output(pdata->gpio_vid1,
- (pdata->default_mode >> 1) % 2);
+ (pdata->default_mode >> 1) & 0x1);
else {
if (!err)
gpio_free(pdata->gpio_vid0);
@@ -310,10 +296,6 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
i2c_set_clientdata(client, max8952);
return 0;
-
-err_reg:
- kfree(max8952);
- return ret;
}
static int __devexit max8952_pmic_remove(struct i2c_client *client)
@@ -327,8 +309,6 @@ static int __devexit max8952_pmic_remove(struct i2c_client *client)
gpio_free(pdata->gpio_vid0);
gpio_free(pdata->gpio_vid1);
gpio_free(pdata->gpio_en);
-
- kfree(max8952);
return 0;
}
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index 17a58c56eebf..704cd49ef375 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -22,7 +22,6 @@
*/
#include <linux/bug.h>
-#include <linux/delay.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/slab.h>
@@ -68,29 +67,28 @@ struct voltage_map_desc {
int min;
int max;
int step;
- unsigned int n_bits;
};
/* Voltage maps in mV */
static const struct voltage_map_desc ldo_voltage_map_desc = {
- .min = 800, .max = 3950, .step = 50, .n_bits = 6,
+ .min = 800, .max = 3950, .step = 50,
}; /* LDO1 ~ 18, 21 all */
static const struct voltage_map_desc buck1245_voltage_map_desc = {
- .min = 650, .max = 2225, .step = 25, .n_bits = 6,
+ .min = 650, .max = 2225, .step = 25,
}; /* Buck1, 2, 4, 5 */
static const struct voltage_map_desc buck37_voltage_map_desc = {
- .min = 750, .max = 3900, .step = 50, .n_bits = 6,
+ .min = 750, .max = 3900, .step = 50,
}; /* Buck3, 7 */
/* current map in mA */
static const struct voltage_map_desc charger_current_map_desc = {
- .min = 200, .max = 950, .step = 50, .n_bits = 4,
+ .min = 200, .max = 950, .step = 50,
};
static const struct voltage_map_desc topoff_current_map_desc = {
- .min = 50, .max = 200, .step = 10, .n_bits = 4,
+ .min = 50, .max = 200, .step = 10,
};
static const struct voltage_map_desc *reg_voltage_map[] = {
@@ -279,9 +277,7 @@ static int max8997_reg_is_enabled(struct regulator_dev *rdev)
u8 val;
ret = max8997_get_enable_register(rdev, &reg, &mask, &pattern);
- if (ret == -EINVAL)
- return 1; /* "not controllable" */
- else if (ret)
+ if (ret)
return ret;
ret = max8997_read_reg(i2c, reg, &val);
@@ -320,6 +316,7 @@ static int max8997_reg_disable(struct regulator_dev *rdev)
static int max8997_get_voltage_register(struct regulator_dev *rdev,
int *_reg, int *_shift, int *_mask)
{
+ struct max8997_data *max8997 = rdev_get_drvdata(rdev);
int rid = rdev_get_id(rdev);
int reg, shift = 0, mask = 0x3f;
@@ -329,9 +326,13 @@ static int max8997_get_voltage_register(struct regulator_dev *rdev,
break;
case MAX8997_BUCK1:
reg = MAX8997_REG_BUCK1DVS1;
+ if (max8997->buck1_gpiodvs)
+ reg += max8997->buck125_gpioindex;
break;
case MAX8997_BUCK2:
reg = MAX8997_REG_BUCK2DVS1;
+ if (max8997->buck2_gpiodvs)
+ reg += max8997->buck125_gpioindex;
break;
case MAX8997_BUCK3:
reg = MAX8997_REG_BUCK3DVS;
@@ -341,6 +342,8 @@ static int max8997_get_voltage_register(struct regulator_dev *rdev,
break;
case MAX8997_BUCK5:
reg = MAX8997_REG_BUCK5DVS1;
+ if (max8997->buck5_gpiodvs)
+ reg += max8997->buck125_gpioindex;
break;
case MAX8997_BUCK7:
reg = MAX8997_REG_BUCK7DVS;
@@ -376,23 +379,17 @@ static int max8997_get_voltage_register(struct regulator_dev *rdev,
return 0;
}
-static int max8997_get_voltage(struct regulator_dev *rdev)
+static int max8997_get_voltage_sel(struct regulator_dev *rdev)
{
struct max8997_data *max8997 = rdev_get_drvdata(rdev);
struct i2c_client *i2c = max8997->iodev->i2c;
int reg, shift, mask, ret;
- int rid = rdev_get_id(rdev);
u8 val;
ret = max8997_get_voltage_register(rdev, &reg, &shift, &mask);
if (ret)
return ret;
- if ((rid == MAX8997_BUCK1 && max8997->buck1_gpiodvs) ||
- (rid == MAX8997_BUCK2 && max8997->buck2_gpiodvs) ||
- (rid == MAX8997_BUCK5 && max8997->buck5_gpiodvs))
- reg += max8997->buck125_gpioindex;
-
ret = max8997_read_reg(i2c, reg, &val);
if (ret)
return ret;
@@ -400,22 +397,14 @@ static int max8997_get_voltage(struct regulator_dev *rdev)
val >>= shift;
val &= mask;
- if (rdev->desc && rdev->desc->ops && rdev->desc->ops->list_voltage)
- return rdev->desc->ops->list_voltage(rdev, val);
-
- /*
- * max8997_list_voltage returns value for any rdev with voltage_map,
- * which works for "CHARGER" and "CHARGER TOPOFF" that do not have
- * list_voltage ops (they are current regulators).
- */
- return max8997_list_voltage(rdev, val);
+ return val;
}
static inline int max8997_get_voltage_proper_val(
const struct voltage_map_desc *desc,
int min_vol, int max_vol)
{
- int i = 0;
+ int i;
if (desc == NULL)
return -EINVAL;
@@ -423,14 +412,12 @@ static inline int max8997_get_voltage_proper_val(
if (max_vol < desc->min || min_vol > desc->max)
return -EINVAL;
- while (desc->min + desc->step * i < min_vol &&
- desc->min + desc->step * i < desc->max)
- i++;
+ if (min_vol < desc->min)
+ min_vol = desc->min;
- if (desc->min + desc->step * i > max_vol)
- return -EINVAL;
+ i = DIV_ROUND_UP(min_vol - desc->min, desc->step);
- if (i >= (1 << desc->n_bits))
+ if (desc->min + desc->step * i > max_vol)
return -EINVAL;
return i;
@@ -499,9 +486,7 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
const struct voltage_map_desc *desc;
int rid = rdev_get_id(rdev);
- int reg, shift = 0, mask, ret;
- int i;
- u8 org;
+ int i, reg, shift, mask, ret;
switch (rid) {
case MAX8997_LDO1 ... MAX8997_LDO21:
@@ -530,21 +515,50 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
if (ret)
return ret;
- max8997_read_reg(i2c, reg, &org);
- org = (org & mask) >> shift;
-
ret = max8997_update_reg(i2c, reg, i << shift, mask << shift);
*selector = i;
- if (rid == MAX8997_BUCK1 || rid == MAX8997_BUCK2 ||
- rid == MAX8997_BUCK4 || rid == MAX8997_BUCK5) {
- /* If the voltage is increasing */
- if (org < i)
- udelay(DIV_ROUND_UP(desc->step * (i - org),
- max8997->ramp_delay));
+ return ret;
+}
+
+static int max8997_set_voltage_ldobuck_time_sel(struct regulator_dev *rdev,
+ unsigned int old_selector,
+ unsigned int new_selector)
+{
+ struct max8997_data *max8997 = rdev_get_drvdata(rdev);
+ int rid = rdev_get_id(rdev);
+ const struct voltage_map_desc *desc = reg_voltage_map[rid];
+
+ /* Delay is required only if the voltage is increasing */
+ if (old_selector >= new_selector)
+ return 0;
+
+ /* No need to delay if gpio_dvs_mode */
+ switch (rid) {
+ case MAX8997_BUCK1:
+ if (max8997->buck1_gpiodvs)
+ return 0;
+ break;
+ case MAX8997_BUCK2:
+ if (max8997->buck2_gpiodvs)
+ return 0;
+ break;
+ case MAX8997_BUCK5:
+ if (max8997->buck5_gpiodvs)
+ return 0;
+ break;
}
- return ret;
+ switch (rid) {
+ case MAX8997_BUCK1:
+ case MAX8997_BUCK2:
+ case MAX8997_BUCK4:
+ case MAX8997_BUCK5:
+ return DIV_ROUND_UP(desc->step * (new_selector - old_selector),
+ max8997->ramp_delay);
+ }
+
+ return 0;
}
/*
@@ -751,11 +765,6 @@ static int max8997_set_voltage_safeout(struct regulator_dev *rdev,
return ret;
}
-static int max8997_reg_enable_suspend(struct regulator_dev *rdev)
-{
- return 0;
-}
-
static int max8997_reg_disable_suspend(struct regulator_dev *rdev)
{
struct max8997_data *max8997 = rdev_get_drvdata(rdev);
@@ -788,9 +797,9 @@ static struct regulator_ops max8997_ldo_ops = {
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
.disable = max8997_reg_disable,
- .get_voltage = max8997_get_voltage,
+ .get_voltage_sel = max8997_get_voltage_sel,
.set_voltage = max8997_set_voltage_ldobuck,
- .set_suspend_enable = max8997_reg_enable_suspend,
+ .set_voltage_time_sel = max8997_set_voltage_ldobuck_time_sel,
.set_suspend_disable = max8997_reg_disable_suspend,
};
@@ -799,9 +808,9 @@ static struct regulator_ops max8997_buck_ops = {
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
.disable = max8997_reg_disable,
- .get_voltage = max8997_get_voltage,
+ .get_voltage_sel = max8997_get_voltage_sel,
.set_voltage = max8997_set_voltage_buck,
- .set_suspend_enable = max8997_reg_enable_suspend,
+ .set_voltage_time_sel = max8997_set_voltage_ldobuck_time_sel,
.set_suspend_disable = max8997_reg_disable_suspend,
};
@@ -810,7 +819,6 @@ static struct regulator_ops max8997_fixedvolt_ops = {
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
.disable = max8997_reg_disable,
- .set_suspend_enable = max8997_reg_enable_suspend,
.set_suspend_disable = max8997_reg_disable_suspend,
};
@@ -819,144 +827,117 @@ static struct regulator_ops max8997_safeout_ops = {
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
.disable = max8997_reg_disable,
- .get_voltage = max8997_get_voltage,
+ .get_voltage_sel = max8997_get_voltage_sel,
.set_voltage = max8997_set_voltage_safeout,
- .set_suspend_enable = max8997_reg_enable_suspend,
.set_suspend_disable = max8997_reg_disable_suspend,
};
static struct regulator_ops max8997_fixedstate_ops = {
.list_voltage = max8997_list_voltage_charger_cv,
- .get_voltage = max8997_get_voltage,
+ .get_voltage_sel = max8997_get_voltage_sel,
.set_voltage = max8997_set_voltage_charger_cv,
};
-static int max8997_set_voltage_ldobuck_wrap(struct regulator_dev *rdev,
- int min_uV, int max_uV)
+static int max8997_set_current_limit(struct regulator_dev *rdev,
+ int min_uA, int max_uA)
{
unsigned dummy;
+ int rid = rdev_get_id(rdev);
+
+ if (rid != MAX8997_CHARGER && rid != MAX8997_CHARGER_TOPOFF)
+ return -EINVAL;
- return max8997_set_voltage_ldobuck(rdev, min_uV, max_uV, &dummy);
+ /* Reuse max8997_set_voltage_ldobuck to set current_limit. */
+ return max8997_set_voltage_ldobuck(rdev, min_uA, max_uA, &dummy);
}
+static int max8997_get_current_limit(struct regulator_dev *rdev)
+{
+ int sel, rid = rdev_get_id(rdev);
+
+ if (rid != MAX8997_CHARGER && rid != MAX8997_CHARGER_TOPOFF)
+ return -EINVAL;
+
+ sel = max8997_get_voltage_sel(rdev);
+ if (sel < 0)
+ return sel;
+
+ /* Reuse max8997_list_voltage to get current_limit. */
+ return max8997_list_voltage(rdev, sel);
+}
static struct regulator_ops max8997_charger_ops = {
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
.disable = max8997_reg_disable,
- .get_current_limit = max8997_get_voltage,
- .set_current_limit = max8997_set_voltage_ldobuck_wrap,
+ .get_current_limit = max8997_get_current_limit,
+ .set_current_limit = max8997_set_current_limit,
};
static struct regulator_ops max8997_charger_fixedstate_ops = {
- .is_enabled = max8997_reg_is_enabled,
- .get_current_limit = max8997_get_voltage,
- .set_current_limit = max8997_set_voltage_ldobuck_wrap,
+ .get_current_limit = max8997_get_current_limit,
+ .set_current_limit = max8997_set_current_limit,
};
-#define regulator_desc_ldo(num) { \
- .name = "LDO"#num, \
- .id = MAX8997_LDO##num, \
- .ops = &max8997_ldo_ops, \
+#define MAX8997_VOLTAGE_REGULATOR(_name, _ops) {\
+ .name = #_name, \
+ .id = MAX8997_##_name, \
+ .ops = &_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}
-#define regulator_desc_buck(num) { \
- .name = "BUCK"#num, \
- .id = MAX8997_BUCK##num, \
- .ops = &max8997_buck_ops, \
- .type = REGULATOR_VOLTAGE, \
+
+#define MAX8997_CURRENT_REGULATOR(_name, _ops) {\
+ .name = #_name, \
+ .id = MAX8997_##_name, \
+ .ops = &_ops, \
+ .type = REGULATOR_CURRENT, \
.owner = THIS_MODULE, \
}
static struct regulator_desc regulators[] = {
- regulator_desc_ldo(1),
- regulator_desc_ldo(2),
- regulator_desc_ldo(3),
- regulator_desc_ldo(4),
- regulator_desc_ldo(5),
- regulator_desc_ldo(6),
- regulator_desc_ldo(7),
- regulator_desc_ldo(8),
- regulator_desc_ldo(9),
- regulator_desc_ldo(10),
- regulator_desc_ldo(11),
- regulator_desc_ldo(12),
- regulator_desc_ldo(13),
- regulator_desc_ldo(14),
- regulator_desc_ldo(15),
- regulator_desc_ldo(16),
- regulator_desc_ldo(17),
- regulator_desc_ldo(18),
- regulator_desc_ldo(21),
- regulator_desc_buck(1),
- regulator_desc_buck(2),
- regulator_desc_buck(3),
- regulator_desc_buck(4),
- regulator_desc_buck(5),
- {
- .name = "BUCK6",
- .id = MAX8997_BUCK6,
- .ops = &max8997_fixedvolt_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- regulator_desc_buck(7),
- {
- .name = "EN32KHz_AP",
- .id = MAX8997_EN32KHZ_AP,
- .ops = &max8997_fixedvolt_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- }, {
- .name = "EN32KHz_CP",
- .id = MAX8997_EN32KHZ_CP,
- .ops = &max8997_fixedvolt_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- }, {
- .name = "ENVICHG",
- .id = MAX8997_ENVICHG,
- .ops = &max8997_fixedvolt_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- }, {
- .name = "ESAFEOUT1",
- .id = MAX8997_ESAFEOUT1,
- .ops = &max8997_safeout_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- }, {
- .name = "ESAFEOUT2",
- .id = MAX8997_ESAFEOUT2,
- .ops = &max8997_safeout_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- }, {
- .name = "CHARGER_CV",
- .id = MAX8997_CHARGER_CV,
- .ops = &max8997_fixedstate_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- }, {
- .name = "CHARGER",
- .id = MAX8997_CHARGER,
- .ops = &max8997_charger_ops,
- .type = REGULATOR_CURRENT,
- .owner = THIS_MODULE,
- }, {
- .name = "CHARGER_TOPOFF",
- .id = MAX8997_CHARGER_TOPOFF,
- .ops = &max8997_charger_fixedstate_ops,
- .type = REGULATOR_CURRENT,
- .owner = THIS_MODULE,
- },
+ MAX8997_VOLTAGE_REGULATOR(LDO1, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO2, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO3, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO4, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO5, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO6, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO7, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO8, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO9, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO10, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO11, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO12, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO13, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO14, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO15, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO16, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO17, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO18, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(LDO21, max8997_ldo_ops),
+ MAX8997_VOLTAGE_REGULATOR(BUCK1, max8997_buck_ops),
+ MAX8997_VOLTAGE_REGULATOR(BUCK2, max8997_buck_ops),
+ MAX8997_VOLTAGE_REGULATOR(BUCK3, max8997_buck_ops),
+ MAX8997_VOLTAGE_REGULATOR(BUCK4, max8997_buck_ops),
+ MAX8997_VOLTAGE_REGULATOR(BUCK5, max8997_buck_ops),
+ MAX8997_VOLTAGE_REGULATOR(BUCK6, max8997_fixedvolt_ops),
+ MAX8997_VOLTAGE_REGULATOR(BUCK7, max8997_buck_ops),
+ MAX8997_VOLTAGE_REGULATOR(EN32KHZ_AP, max8997_fixedvolt_ops),
+ MAX8997_VOLTAGE_REGULATOR(EN32KHZ_CP, max8997_fixedvolt_ops),
+ MAX8997_VOLTAGE_REGULATOR(ENVICHG, max8997_fixedvolt_ops),
+ MAX8997_VOLTAGE_REGULATOR(ESAFEOUT1, max8997_safeout_ops),
+ MAX8997_VOLTAGE_REGULATOR(ESAFEOUT2, max8997_safeout_ops),
+ MAX8997_VOLTAGE_REGULATOR(CHARGER_CV, max8997_fixedstate_ops),
+ MAX8997_CURRENT_REGULATOR(CHARGER, max8997_charger_ops),
+ MAX8997_CURRENT_REGULATOR(CHARGER_TOPOFF,
+ max8997_charger_fixedstate_ops),
};
static __devinit int max8997_pmic_probe(struct platform_device *pdev)
{
struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+ struct regulator_config config = { };
struct regulator_dev **rdev;
struct max8997_data *max8997;
struct i2c_client *i2c;
@@ -968,16 +949,15 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
return -ENODEV;
}
- max8997 = kzalloc(sizeof(struct max8997_data), GFP_KERNEL);
+ max8997 = devm_kzalloc(&pdev->dev, sizeof(struct max8997_data),
+ GFP_KERNEL);
if (!max8997)
return -ENOMEM;
size = sizeof(struct regulator_dev *) * pdata->num_regulators;
- max8997->rdev = kzalloc(size, GFP_KERNEL);
- if (!max8997->rdev) {
- kfree(max8997);
+ max8997->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ if (!max8997->rdev)
return -ENOMEM;
- }
rdev = max8997->rdev;
max8997->dev = &pdev->dev;
@@ -1001,7 +981,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
pdata->buck1_voltage[i] / 1000 +
buck1245_voltage_map_desc.step);
if (ret < 0)
- goto err_alloc;
+ goto err_out;
max8997->buck2_vol[i] = ret =
max8997_get_voltage_proper_val(
@@ -1010,7 +990,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
pdata->buck2_voltage[i] / 1000 +
buck1245_voltage_map_desc.step);
if (ret < 0)
- goto err_alloc;
+ goto err_out;
max8997->buck5_vol[i] = ret =
max8997_get_voltage_proper_val(
@@ -1019,7 +999,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
pdata->buck5_voltage[i] / 1000 +
buck1245_voltage_map_desc.step);
if (ret < 0)
- goto err_alloc;
+ goto err_out;
if (max_buck1 < max8997->buck1_vol[i])
max_buck1 = max8997->buck1_vol[i];
@@ -1052,7 +1032,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
!gpio_is_valid(pdata->buck125_gpios[2])) {
dev_err(&pdev->dev, "GPIO NOT VALID\n");
ret = -EINVAL;
- goto err_alloc;
+ goto err_out;
}
ret = gpio_request(pdata->buck125_gpios[0],
@@ -1061,7 +1041,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "Duplicated gpio request"
" on SET1\n");
else if (ret)
- goto err_alloc;
+ goto err_out;
else
gpio1set = true;
@@ -1073,7 +1053,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
else if (ret) {
if (gpio1set)
gpio_free(pdata->buck125_gpios[0]);
- goto err_alloc;
+ goto err_out;
} else
gpio2set = true;
@@ -1087,7 +1067,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
gpio_free(pdata->buck125_gpios[0]);
if (gpio2set)
gpio_free(pdata->buck125_gpios[1]);
- goto err_alloc;
+ goto err_out;
}
gpio_direction_output(pdata->buck125_gpios[0],
@@ -1140,8 +1120,11 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
else if (id == MAX8997_CHARGER_CV)
regulators[id].n_voltages = 16;
- rdev[i] = regulator_register(&regulators[id], max8997->dev,
- pdata->regulators[i].initdata, max8997, NULL);
+ config.dev = max8997->dev;
+ config.init_data = pdata->regulators[i].initdata;
+ config.driver_data = max8997;
+
+ rdev[i] = regulator_register(&regulators[id], &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
dev_err(max8997->dev, "regulator init failed for %d\n",
@@ -1153,13 +1136,9 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
return 0;
err:
- for (i = 0; i < max8997->num_regulators; i++)
- if (rdev[i])
- regulator_unregister(rdev[i]);
-err_alloc:
- kfree(max8997->rdev);
- kfree(max8997);
-
+ while (--i >= 0)
+ regulator_unregister(rdev[i]);
+err_out:
return ret;
}
@@ -1170,12 +1149,7 @@ static int __devexit max8997_pmic_remove(struct platform_device *pdev)
int i;
for (i = 0; i < max8997->num_regulators; i++)
- if (rdev[i])
- regulator_unregister(rdev[i]);
-
- kfree(max8997->rdev);
- kfree(max8997);
-
+ regulator_unregister(rdev[i]);
return 0;
}
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
index 5890265eeacc..18bb58b9b96e 100644
--- a/drivers/regulator/max8998.c
+++ b/drivers/regulator/max8998.c
@@ -28,7 +28,6 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
-#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/mfd/max8998.h>
@@ -277,7 +276,7 @@ static int max8998_get_voltage_register(struct regulator_dev *rdev,
return 0;
}
-static int max8998_get_voltage(struct regulator_dev *rdev)
+static int max8998_get_voltage_sel(struct regulator_dev *rdev)
{
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
struct i2c_client *i2c = max8998->iodev->i2c;
@@ -295,7 +294,7 @@ static int max8998_get_voltage(struct regulator_dev *rdev)
val >>= shift;
val &= mask;
- return max8998_list_voltage(rdev, val);
+ return val;
}
static int max8998_set_voltage_ldo(struct regulator_dev *rdev,
@@ -306,8 +305,7 @@ static int max8998_set_voltage_ldo(struct regulator_dev *rdev,
int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
const struct voltage_map_desc *desc;
int ldo = rdev_get_id(rdev);
- int reg, shift = 0, mask, ret;
- int i = 0;
+ int reg, shift = 0, mask, ret, i;
if (ldo >= ARRAY_SIZE(ldo_voltage_map))
return -EINVAL;
@@ -319,9 +317,10 @@ static int max8998_set_voltage_ldo(struct regulator_dev *rdev,
if (max_vol < desc->min || min_vol > desc->max)
return -EINVAL;
- while (desc->min + desc->step*i < min_vol &&
- desc->min + desc->step*i < desc->max)
- i++;
+ if (min_vol < desc->min)
+ min_vol = desc->min;
+
+ i = DIV_ROUND_UP(min_vol - desc->min, desc->step);
if (desc->min + desc->step*i > max_vol)
return -EINVAL;
@@ -359,8 +358,7 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
const struct voltage_map_desc *desc;
int buck = rdev_get_id(rdev);
int reg, shift = 0, mask, ret;
- int difference = 0, i = 0, j = 0, previous_vol = 0;
- u8 val = 0;
+ int i, j, previous_sel;
static u8 buck1_last_val;
if (buck >= ARRAY_SIZE(ldo_voltage_map))
@@ -374,9 +372,10 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
if (max_vol < desc->min || min_vol > desc->max)
return -EINVAL;
- while (desc->min + desc->step*i < min_vol &&
- desc->min + desc->step*i < desc->max)
- i++;
+ if (min_vol < desc->min)
+ min_vol = desc->min;
+
+ i = DIV_ROUND_UP(min_vol - desc->min, desc->step);
if (desc->min + desc->step*i > max_vol)
return -EINVAL;
@@ -387,13 +386,14 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
if (ret)
return ret;
- previous_vol = max8998_get_voltage(rdev);
+ previous_sel = max8998_get_voltage_sel(rdev);
/* Check if voltage needs to be changed */
/* if previous_voltage equal new voltage, return */
- if (previous_vol == max8998_list_voltage(rdev, i)) {
+ if (previous_sel == i) {
dev_dbg(max8998->dev, "No voltage change, old:%d, new:%d\n",
- previous_vol, max8998_list_voltage(rdev, i));
+ max8998_list_voltage(rdev, previous_sel),
+ max8998_list_voltage(rdev, i));
return ret;
}
@@ -482,19 +482,40 @@ buck2_exit:
break;
}
+ return ret;
+}
+
+static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev,
+ unsigned int old_selector,
+ unsigned int new_selector)
+{
+ struct max8998_data *max8998 = rdev_get_drvdata(rdev);
+ struct i2c_client *i2c = max8998->iodev->i2c;
+ const struct voltage_map_desc *desc;
+ int buck = rdev_get_id(rdev);
+ u8 val = 0;
+ int difference, ret;
+
+ if (buck < MAX8998_BUCK1 || buck > MAX8998_BUCK4)
+ return -EINVAL;
+
+ desc = ldo_voltage_map[buck];
+
/* Voltage stabilization */
- max8998_read_reg(i2c, MAX8998_REG_ONOFF4, &val);
+ ret = max8998_read_reg(i2c, MAX8998_REG_ONOFF4, &val);
+ if (ret)
+ return ret;
/* lp3974 hasn't got ENRAMP bit - ramp is assumed as true */
/* MAX8998 has ENRAMP bit implemented, so test it*/
if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP))
- return ret;
+ return 0;
- difference = desc->min + desc->step*i - previous_vol/1000;
+ difference = (new_selector - old_selector) * desc->step;
if (difference > 0)
- udelay(difference / ((val & 0x0f) + 1));
+ return difference / ((val & 0x0f) + 1);
- return ret;
+ return 0;
}
static struct regulator_ops max8998_ldo_ops = {
@@ -502,7 +523,7 @@ static struct regulator_ops max8998_ldo_ops = {
.is_enabled = max8998_ldo_is_enabled,
.enable = max8998_ldo_enable,
.disable = max8998_ldo_disable,
- .get_voltage = max8998_get_voltage,
+ .get_voltage_sel = max8998_get_voltage_sel,
.set_voltage = max8998_set_voltage_ldo,
.set_suspend_enable = max8998_ldo_enable,
.set_suspend_disable = max8998_ldo_disable,
@@ -513,8 +534,9 @@ static struct regulator_ops max8998_buck_ops = {
.is_enabled = max8998_ldo_is_enabled,
.enable = max8998_ldo_enable,
.disable = max8998_ldo_disable,
- .get_voltage = max8998_get_voltage,
+ .get_voltage_sel = max8998_get_voltage_sel,
.set_voltage = max8998_set_voltage_buck,
+ .set_voltage_time_sel = max8998_set_voltage_buck_time_sel,
.set_suspend_enable = max8998_ldo_enable,
.set_suspend_disable = max8998_ldo_disable,
};
@@ -685,6 +707,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
{
struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
+ struct regulator_config config = { };
struct regulator_dev **rdev;
struct max8998_data *max8998;
struct i2c_client *i2c;
@@ -695,16 +718,15 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
return -ENODEV;
}
- max8998 = kzalloc(sizeof(struct max8998_data), GFP_KERNEL);
+ max8998 = devm_kzalloc(&pdev->dev, sizeof(struct max8998_data),
+ GFP_KERNEL);
if (!max8998)
return -ENOMEM;
size = sizeof(struct regulator_dev *) * pdata->num_regulators;
- max8998->rdev = kzalloc(size, GFP_KERNEL);
- if (!max8998->rdev) {
- kfree(max8998);
+ max8998->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ if (!max8998->rdev)
return -ENOMEM;
- }
rdev = max8998->rdev;
max8998->dev = &pdev->dev;
@@ -728,14 +750,14 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
printk(KERN_ERR "MAX8998 SET1 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck1_set1);
ret = -EIO;
- goto err_free_mem;
+ goto err_out;
}
/* Check if SET2 is not equal to 0 */
if (!pdata->buck1_set2) {
printk(KERN_ERR "MAX8998 SET2 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck1_set2);
ret = -EIO;
- goto err_free_mem;
+ goto err_out;
}
gpio_request(pdata->buck1_set1, "MAX8998 BUCK1_SET1");
@@ -755,7 +777,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck1_vol[0] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i);
if (ret)
- goto err_free_mem;
+ goto err_out;
/* Set predefined value for BUCK1 register 2 */
i = 0;
@@ -767,7 +789,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck1_vol[1] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i);
if (ret)
- goto err_free_mem;
+ goto err_out;
/* Set predefined value for BUCK1 register 3 */
i = 0;
@@ -779,7 +801,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck1_vol[2] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i);
if (ret)
- goto err_free_mem;
+ goto err_out;
/* Set predefined value for BUCK1 register 4 */
i = 0;
@@ -791,7 +813,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck1_vol[3] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i);
if (ret)
- goto err_free_mem;
+ goto err_out;
}
@@ -801,7 +823,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
printk(KERN_ERR "MAX8998 SET3 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck2_set3);
ret = -EIO;
- goto err_free_mem;
+ goto err_out;
}
gpio_request(pdata->buck2_set3, "MAX8998 BUCK2_SET3");
gpio_direction_output(pdata->buck2_set3,
@@ -816,7 +838,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck2_vol[0] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i);
if (ret)
- goto err_free_mem;
+ goto err_out;
/* BUCK2 register 2 */
i = 0;
@@ -827,7 +849,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck2_vol[1] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i);
if (ret)
- goto err_free_mem;
+ goto err_out;
}
for (i = 0; i < pdata->num_regulators; i++) {
@@ -840,8 +862,12 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
int count = (desc->max - desc->min) / desc->step + 1;
regulators[index].n_voltages = count;
}
- rdev[i] = regulator_register(&regulators[index], max8998->dev,
- pdata->regulators[i].initdata, max8998, NULL);
+
+ config.dev = max8998->dev;
+ config.init_data = pdata->regulators[i].initdata;
+ config.driver_data = max8998;
+
+ rdev[i] = regulator_register(&regulators[index], &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
dev_err(max8998->dev, "regulator init failed\n");
@@ -853,14 +879,9 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
return 0;
err:
- for (i = 0; i < max8998->num_regulators; i++)
- if (rdev[i])
- regulator_unregister(rdev[i]);
-
-err_free_mem:
- kfree(max8998->rdev);
- kfree(max8998);
-
+ while (--i >= 0)
+ regulator_unregister(rdev[i]);
+err_out:
return ret;
}
@@ -871,12 +892,7 @@ static int __devexit max8998_pmic_remove(struct platform_device *pdev)
int i;
for (i = 0; i < max8998->num_regulators; i++)
- if (rdev[i])
- regulator_unregister(rdev[i]);
-
- kfree(max8998->rdev);
- kfree(max8998);
-
+ regulator_unregister(rdev[i]);
return 0;
}
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
index 6c0face87ffe..7dcdfa283e93 100644
--- a/drivers/regulator/mc13783-regulator.c
+++ b/drivers/regulator/mc13783-regulator.c
@@ -340,6 +340,7 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
struct mc13xxx_regulator_platform_data *pdata =
dev_get_platdata(&pdev->dev);
struct mc13xxx_regulator_init_data *init_data;
+ struct regulator_config config = { };
int i, ret;
dev_dbg(&pdev->dev, "%s id %d\n", __func__, pdev->id);
@@ -357,11 +358,16 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
priv->mc13xxx = mc13783;
for (i = 0; i < pdata->num_regulators; i++) {
+ struct regulator_desc *desc;
+
init_data = &pdata->regulators[i];
- priv->regulators[i] = regulator_register(
- &mc13783_regulators[init_data->id].desc,
- &pdev->dev, init_data->init_data, priv, NULL);
+ desc = &mc13783_regulators[init_data->id].desc;
+
+ config.dev = &pdev->dev;
+ config.init_data = init_data->init_data;
+ config.driver_data = priv;
+ priv->regulators[i] = regulator_register(desc, &config);
if (IS_ERR(priv->regulators[i])) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
mc13783_regulators[i].desc.name);
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
index 845aa2263b8a..970a233dbe46 100644
--- a/drivers/regulator/mc13892-regulator.c
+++ b/drivers/regulator/mc13892-regulator.c
@@ -428,24 +428,15 @@ static int mc13892_sw_regulator_get_voltage(struct regulator_dev *rdev)
return val;
}
-static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *selector)
+static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned selector)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int hi, value, mask, id = rdev_get_id(rdev);
u32 valread;
int ret;
- dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
- __func__, id, min_uV, max_uV);
-
- /* Find the best index */
- value = mc13xxx_get_best_voltage_index(rdev, min_uV, max_uV);
- dev_dbg(rdev_get_dev(rdev), "%s best value: %d\n", __func__, value);
- if (value < 0)
- return value;
-
- value = mc13892_regulators[id].voltages[value];
+ value = mc13892_regulators[id].voltages[selector];
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(priv->mc13xxx,
@@ -480,7 +471,7 @@ err:
static struct regulator_ops mc13892_sw_regulator_ops = {
.is_enabled = mc13xxx_sw_regulator_is_enabled,
.list_voltage = mc13xxx_regulator_list_voltage,
- .set_voltage = mc13892_sw_regulator_set_voltage,
+ .set_voltage_sel = mc13892_sw_regulator_set_voltage_sel,
.get_voltage = mc13892_sw_regulator_get_voltage,
};
@@ -528,6 +519,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
struct mc13xxx_regulator_platform_data *pdata =
dev_get_platdata(&pdev->dev);
struct mc13xxx_regulator_init_data *mc13xxx_data;
+ struct regulator_config config = { };
int i, ret;
int num_regulators = 0;
u32 val;
@@ -597,9 +589,12 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
}
desc = &mc13892_regulators[id].desc;
- priv->regulators[i] = regulator_register(
- desc, &pdev->dev, init_data, priv, node);
+ config.dev = &pdev->dev;
+ config.init_data = init_data;
+ config.driver_data = priv;
+ config.of_node = node;
+ priv->regulators[i] = regulator_register(desc, &config);
if (IS_ERR(priv->regulators[i])) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
mc13892_regulators[i].desc.name);
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c
index 62dcd0a432bb..4fa9704739bc 100644
--- a/drivers/regulator/mc13xxx-regulator-core.c
+++ b/drivers/regulator/mc13xxx-regulator-core.c
@@ -94,62 +94,18 @@ int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev,
}
EXPORT_SYMBOL_GPL(mc13xxx_regulator_list_voltage);
-int mc13xxx_get_best_voltage_index(struct regulator_dev *rdev,
- int min_uV, int max_uV)
+static int mc13xxx_regulator_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned selector)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
- int reg_id = rdev_get_id(rdev);
- int i;
- int bestmatch;
- int bestindex;
-
- /*
- * Locate the minimum voltage fitting the criteria on
- * this regulator. The switchable voltages are not
- * in strict falling order so we need to check them
- * all for the best match.
- */
- bestmatch = INT_MAX;
- bestindex = -1;
- for (i = 0; i < mc13xxx_regulators[reg_id].desc.n_voltages; i++) {
- if (mc13xxx_regulators[reg_id].voltages[i] >= min_uV &&
- mc13xxx_regulators[reg_id].voltages[i] < bestmatch) {
- bestmatch = mc13xxx_regulators[reg_id].voltages[i];
- bestindex = i;
- }
- }
-
- if (bestindex < 0 || bestmatch > max_uV) {
- dev_warn(&rdev->dev, "no possible value for %d<=x<=%d uV\n",
- min_uV, max_uV);
- return -EINVAL;
- }
- return bestindex;
-}
-EXPORT_SYMBOL_GPL(mc13xxx_get_best_voltage_index);
-
-static int mc13xxx_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
- int max_uV, unsigned *selector)
-{
- struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
- struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
- int value, id = rdev_get_id(rdev);
+ int id = rdev_get_id(rdev);
int ret;
- dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
- __func__, id, min_uV, max_uV);
-
- /* Find the best index */
- value = mc13xxx_get_best_voltage_index(rdev, min_uV, max_uV);
- dev_dbg(rdev_get_dev(rdev), "%s best value: %d\n", __func__, value);
- if (value < 0)
- return value;
-
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg,
mc13xxx_regulators[id].vsel_mask,
- value << mc13xxx_regulators[id].vsel_shift);
+ selector << mc13xxx_regulators[id].vsel_shift);
mc13xxx_unlock(priv->mc13xxx);
return ret;
@@ -187,7 +143,7 @@ struct regulator_ops mc13xxx_regulator_ops = {
.disable = mc13xxx_regulator_disable,
.is_enabled = mc13xxx_regulator_is_enabled,
.list_voltage = mc13xxx_regulator_list_voltage,
- .set_voltage = mc13xxx_regulator_set_voltage,
+ .set_voltage_sel = mc13xxx_regulator_set_voltage_sel,
.get_voltage = mc13xxx_regulator_get_voltage,
};
EXPORT_SYMBOL_GPL(mc13xxx_regulator_ops);
diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h
index b3961c658b05..044aba4d28ec 100644
--- a/drivers/regulator/mc13xxx.h
+++ b/drivers/regulator/mc13xxx.h
@@ -35,8 +35,6 @@ struct mc13xxx_regulator_priv {
extern int mc13xxx_sw_regulator(struct regulator_dev *rdev);
extern int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev);
-extern int mc13xxx_get_best_voltage_index(struct regulator_dev *rdev,
- int min_uV, int max_uV);
extern int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev,
unsigned selector);
extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev,
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 679734d26a16..56593b75168a 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
static void of_get_regulation_constraints(struct device_node *np,
struct regulator_init_data **init_data)
@@ -85,3 +86,49 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
return init_data;
}
EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
+
+/**
+ * of_regulator_match - extract regulator init data
+ * @dev: device requesting the data
+ * @node: parent device node of the regulators
+ * @matches: match table for the regulators
+ * @num_matches: number of entries in match table
+ *
+ * This function uses a match table specified by the regulator driver and
+ * looks up the corresponding init data in the device tree. Note that the
+ * match table is modified in place.
+ *
+ * Returns the number of matches found or a negative error code on failure.
+ */
+int of_regulator_match(struct device *dev, struct device_node *node,
+ struct of_regulator_match *matches,
+ unsigned int num_matches)
+{
+ unsigned int count = 0;
+ unsigned int i;
+
+ if (!dev || !node)
+ return -EINVAL;
+
+ for (i = 0; i < num_matches; i++) {
+ struct of_regulator_match *match = &matches[i];
+ struct device_node *child;
+
+ child = of_find_node_by_name(node, match->name);
+ if (!child)
+ continue;
+
+ match->init_data = of_get_regulator_init_data(dev, child);
+ if (!match->init_data) {
+ dev_err(dev, "failed to parse DT for regulator %s\n",
+ child->name);
+ return -EINVAL;
+ }
+
+ match->of_node = child;
+ count++;
+ }
+
+ return count;
+}
+EXPORT_SYMBOL_GPL(of_regulator_match);
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
new file mode 100644
index 000000000000..c4435f608df7
--- /dev/null
+++ b/drivers/regulator/palmas-regulator.c
@@ -0,0 +1,822 @@
+/*
+ * Driver for Regulator part of Palmas PMIC Chips
+ *
+ * Copyright 2011-2012 Texas Instruments Inc.
+ *
+ * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/mfd/palmas.h>
+
+struct regs_info {
+ char *name;
+ u8 vsel_addr;
+ u8 ctrl_addr;
+ u8 tstep_addr;
+};
+
+static const struct regs_info palmas_regs_info[] = {
+ {
+ .name = "SMPS12",
+ .vsel_addr = PALMAS_SMPS12_VOLTAGE,
+ .ctrl_addr = PALMAS_SMPS12_CTRL,
+ .tstep_addr = PALMAS_SMPS12_TSTEP,
+ },
+ {
+ .name = "SMPS123",
+ .vsel_addr = PALMAS_SMPS12_VOLTAGE,
+ .ctrl_addr = PALMAS_SMPS12_CTRL,
+ .tstep_addr = PALMAS_SMPS12_TSTEP,
+ },
+ {
+ .name = "SMPS3",
+ .vsel_addr = PALMAS_SMPS3_VOLTAGE,
+ .ctrl_addr = PALMAS_SMPS3_CTRL,
+ },
+ {
+ .name = "SMPS45",
+ .vsel_addr = PALMAS_SMPS45_VOLTAGE,
+ .ctrl_addr = PALMAS_SMPS45_CTRL,
+ .tstep_addr = PALMAS_SMPS45_TSTEP,
+ },
+ {
+ .name = "SMPS457",
+ .vsel_addr = PALMAS_SMPS45_VOLTAGE,
+ .ctrl_addr = PALMAS_SMPS45_CTRL,
+ .tstep_addr = PALMAS_SMPS45_TSTEP,
+ },
+ {
+ .name = "SMPS6",
+ .vsel_addr = PALMAS_SMPS6_VOLTAGE,
+ .ctrl_addr = PALMAS_SMPS6_CTRL,
+ .tstep_addr = PALMAS_SMPS6_TSTEP,
+ },
+ {
+ .name = "SMPS7",
+ .vsel_addr = PALMAS_SMPS7_VOLTAGE,
+ .ctrl_addr = PALMAS_SMPS7_CTRL,
+ },
+ {
+ .name = "SMPS8",
+ .vsel_addr = PALMAS_SMPS8_VOLTAGE,
+ .ctrl_addr = PALMAS_SMPS8_CTRL,
+ .tstep_addr = PALMAS_SMPS8_TSTEP,
+ },
+ {
+ .name = "SMPS9",
+ .vsel_addr = PALMAS_SMPS9_VOLTAGE,
+ .ctrl_addr = PALMAS_SMPS9_CTRL,
+ },
+ {
+ .name = "SMPS10",
+ },
+ {
+ .name = "LDO1",
+ .vsel_addr = PALMAS_LDO1_VOLTAGE,
+ .ctrl_addr = PALMAS_LDO1_CTRL,
+ },
+ {
+ .name = "LDO2",
+ .vsel_addr = PALMAS_LDO2_VOLTAGE,
+ .ctrl_addr = PALMAS_LDO2_CTRL,
+ },
+ {
+ .name = "LDO3",
+ .vsel_addr = PALMAS_LDO3_VOLTAGE,
+ .ctrl_addr = PALMAS_LDO3_CTRL,
+ },
+ {
+ .name = "LDO4",
+ .vsel_addr = PALMAS_LDO4_VOLTAGE,
+ .ctrl_addr = PALMAS_LDO4_CTRL,
+ },
+ {
+ .name = "LDO5",
+ .vsel_addr = PALMAS_LDO5_VOLTAGE,
+ .ctrl_addr = PALMAS_LDO5_CTRL,
+ },
+ {
+ .name = "LDO6",
+ .vsel_addr = PALMAS_LDO6_VOLTAGE,
+ .ctrl_addr = PALMAS_LDO6_CTRL,
+ },
+ {
+ .name = "LDO7",
+ .vsel_addr = PALMAS_LDO7_VOLTAGE,
+ .ctrl_addr = PALMAS_LDO7_CTRL,
+ },
+ {
+ .name = "LDO8",
+ .vsel_addr = PALMAS_LDO8_VOLTAGE,
+ .ctrl_addr = PALMAS_LDO8_CTRL,
+ },
+ {
+ .name = "LDO9",
+ .vsel_addr = PALMAS_LDO9_VOLTAGE,
+ .ctrl_addr = PALMAS_LDO9_CTRL,
+ },
+ {
+ .name = "LDOLN",
+ .vsel_addr = PALMAS_LDOLN_VOLTAGE,
+ .ctrl_addr = PALMAS_LDOLN_CTRL,
+ },
+ {
+ .name = "LDOUSB",
+ .vsel_addr = PALMAS_LDOUSB_VOLTAGE,
+ .ctrl_addr = PALMAS_LDOUSB_CTRL,
+ },
+};
+
+#define SMPS_CTRL_MODE_OFF 0x00
+#define SMPS_CTRL_MODE_ON 0x01
+#define SMPS_CTRL_MODE_ECO 0x02
+#define SMPS_CTRL_MODE_PWM 0x03
+
+/* These values are derived from the data sheet. And are the number of steps
+ * where there is a voltage change, the ranges at beginning and end of register
+ * max/min values where there are no change are ommitted.
+ *
+ * So they are basically (maxV-minV)/stepV
+ */
+#define PALMAS_SMPS_NUM_VOLTAGES 116
+#define PALMAS_SMPS10_NUM_VOLTAGES 2
+#define PALMAS_LDO_NUM_VOLTAGES 50
+
+#define SMPS10_VSEL (1<<3)
+#define SMPS10_BOOST_EN (1<<2)
+#define SMPS10_BYPASS_EN (1<<1)
+#define SMPS10_SWITCH_EN (1<<0)
+
+#define REGULATOR_SLAVE 0
+
+static int palmas_smps_read(struct palmas *palmas, unsigned int reg,
+ unsigned int *dest)
+{
+ unsigned int addr;
+
+ addr = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE, reg);
+
+ return regmap_read(palmas->regmap[REGULATOR_SLAVE], addr, dest);
+}
+
+static int palmas_smps_write(struct palmas *palmas, unsigned int reg,
+ unsigned int value)
+{
+ unsigned int addr;
+
+ addr = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE, reg);
+
+ return regmap_write(palmas->regmap[REGULATOR_SLAVE], addr, value);
+}
+
+static int palmas_ldo_read(struct palmas *palmas, unsigned int reg,
+ unsigned int *dest)
+{
+ unsigned int addr;
+
+ addr = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE, reg);
+
+ return regmap_read(palmas->regmap[REGULATOR_SLAVE], addr, dest);
+}
+
+static int palmas_ldo_write(struct palmas *palmas, unsigned int reg,
+ unsigned int value)
+{
+ unsigned int addr;
+
+ addr = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE, reg);
+
+ return regmap_write(palmas->regmap[REGULATOR_SLAVE], addr, value);
+}
+
+static int palmas_is_enabled_smps(struct regulator_dev *dev)
+{
+ struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ int id = rdev_get_id(dev);
+ unsigned int reg;
+
+ palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
+
+ reg &= PALMAS_SMPS12_CTRL_STATUS_MASK;
+ reg >>= PALMAS_SMPS12_CTRL_STATUS_SHIFT;
+
+ return !!(reg);
+}
+
+static int palmas_enable_smps(struct regulator_dev *dev)
+{
+ struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ int id = rdev_get_id(dev);
+ unsigned int reg;
+
+ palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
+
+ reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
+ reg |= SMPS_CTRL_MODE_ON;
+
+ palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg);
+
+ return 0;
+}
+
+static int palmas_disable_smps(struct regulator_dev *dev)
+{
+ struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ int id = rdev_get_id(dev);
+ unsigned int reg;
+
+ palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
+
+ reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
+
+ palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg);
+
+ return 0;
+}
+
+
+static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
+{
+ struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ int id = rdev_get_id(dev);
+ unsigned int reg;
+
+ palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
+ reg &= ~PALMAS_SMPS12_CTRL_STATUS_MASK;
+ reg >>= PALMAS_SMPS12_CTRL_STATUS_SHIFT;
+
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ reg |= SMPS_CTRL_MODE_ON;
+ break;
+ case REGULATOR_MODE_IDLE:
+ reg |= SMPS_CTRL_MODE_ECO;
+ break;
+ case REGULATOR_MODE_FAST:
+ reg |= SMPS_CTRL_MODE_PWM;
+ break;
+ default:
+ return -EINVAL;
+ }
+ palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg);
+
+ return 0;
+}
+
+static unsigned int palmas_get_mode_smps(struct regulator_dev *dev)
+{
+ struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ int id = rdev_get_id(dev);
+ unsigned int reg;
+
+ palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
+ reg &= PALMAS_SMPS12_CTRL_STATUS_MASK;
+ reg >>= PALMAS_SMPS12_CTRL_STATUS_SHIFT;
+
+ switch (reg) {
+ case SMPS_CTRL_MODE_ON:
+ return REGULATOR_MODE_NORMAL;
+ case SMPS_CTRL_MODE_ECO:
+ return REGULATOR_MODE_IDLE;
+ case SMPS_CTRL_MODE_PWM:
+ return REGULATOR_MODE_FAST;
+ }
+
+ return 0;
+}
+
+static int palmas_list_voltage_smps(struct regulator_dev *dev,
+ unsigned selector)
+{
+ struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ int id = rdev_get_id(dev);
+ int mult = 1;
+
+ if (!selector)
+ return 0;
+
+ /* Read the multiplier set in VSEL register to return
+ * the correct voltage.
+ */
+ if (pmic->range[id])
+ mult = 2;
+
+ /* Voltage is (0.49V + (selector * 0.01V)) * RANGE
+ * as defined in data sheet. RANGE is either x1 or x2
+ */
+ return (490000 + (selector * 10000)) * mult;
+}
+
+static int palmas_get_voltage_smps_sel(struct regulator_dev *dev)
+{
+ struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ int id = rdev_get_id(dev);
+ int selector;
+ unsigned int reg;
+ unsigned int addr;
+
+ addr = palmas_regs_info[id].vsel_addr;
+
+ palmas_smps_read(pmic->palmas, addr, &reg);
+
+ selector = reg & PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
+
+ /* Adjust selector to match list_voltage ranges */
+ if ((selector > 0) && (selector < 6))
+ selector = 6;
+ if (!selector)
+ selector = 5;
+ if (selector > 121)
+ selector = 121;
+ selector -= 5;
+
+ return selector;
+}
+
+static int palmas_set_voltage_smps_sel(struct regulator_dev *dev,
+ unsigned selector)
+{
+ struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ int id = rdev_get_id(dev);
+ unsigned int reg = 0;
+ unsigned int addr;
+
+ addr = palmas_regs_info[id].vsel_addr;
+
+ /* Make sure we don't change the value of RANGE */
+ if (pmic->range[id])
+ reg |= PALMAS_SMPS12_VOLTAGE_RANGE;
+
+ /* Adjust the linux selector into range used in VSEL register */
+ if (selector)
+ reg |= selector + 5;
+
+ palmas_smps_write(pmic->palmas, addr, reg);
+
+ return 0;
+}
+
+static int palmas_map_voltage_smps(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ int ret, voltage;
+
+ ret = ((min_uV - 500000) / 10000) + 1;
+ if (ret < 0)
+ return ret;
+
+ /* Map back into a voltage to verify we're still in bounds */
+ voltage = palmas_list_voltage_smps(rdev, ret);
+ if (voltage < min_uV || voltage > max_uV)
+ return -EINVAL;
+
+ return ret;
+}
+
+static struct regulator_ops palmas_ops_smps = {
+ .is_enabled = palmas_is_enabled_smps,
+ .enable = palmas_enable_smps,
+ .disable = palmas_disable_smps,
+ .set_mode = palmas_set_mode_smps,
+ .get_mode = palmas_get_mode_smps,
+ .get_voltage_sel = palmas_get_voltage_smps_sel,
+ .set_voltage_sel = palmas_set_voltage_smps_sel,
+ .list_voltage = palmas_list_voltage_smps,
+ .map_voltage = palmas_map_voltage_smps,
+};
+
+static int palmas_list_voltage_smps10(struct regulator_dev *dev,
+ unsigned selector)
+{
+ return 3750000 + (selector * 1250000);
+}
+
+static struct regulator_ops palmas_ops_smps10 = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = palmas_list_voltage_smps10,
+};
+
+static int palmas_is_enabled_ldo(struct regulator_dev *dev)
+{
+ struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ int id = rdev_get_id(dev);
+ unsigned int reg;
+
+ palmas_ldo_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
+
+ reg &= PALMAS_LDO1_CTRL_STATUS;
+
+ return !!(reg);
+}
+
+static int palmas_list_voltage_ldo(struct regulator_dev *dev,
+ unsigned selector)
+{
+ if (!selector)
+ return 0;
+
+ /* voltage is 0.85V + (selector * 0.05v) */
+ return 850000 + (selector * 50000);
+}
+
+static int palmas_get_voltage_ldo_sel(struct regulator_dev *dev)
+{
+ struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ int id = rdev_get_id(dev);
+ int selector;
+ unsigned int reg;
+ unsigned int addr;
+
+ addr = palmas_regs_info[id].vsel_addr;
+
+ palmas_ldo_read(pmic->palmas, addr, &reg);
+
+ selector = reg & PALMAS_LDO1_VOLTAGE_VSEL_MASK;
+
+ /* Adjust selector to match list_voltage ranges */
+ if (selector > 49)
+ selector = 49;
+
+ return selector;
+}
+
+static int palmas_set_voltage_ldo_sel(struct regulator_dev *dev,
+ unsigned selector)
+{
+ struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ int id = rdev_get_id(dev);
+ unsigned int reg = 0;
+ unsigned int addr;
+
+ addr = palmas_regs_info[id].vsel_addr;
+
+ reg = selector;
+
+ palmas_ldo_write(pmic->palmas, addr, reg);
+
+ return 0;
+}
+
+static int palmas_map_voltage_ldo(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ int ret, voltage;
+
+ ret = ((min_uV - 900000) / 50000) + 1;
+ if (ret < 0)
+ return ret;
+
+ /* Map back into a voltage to verify we're still in bounds */
+ voltage = palmas_list_voltage_ldo(rdev, ret);
+ if (voltage < min_uV || voltage > max_uV)
+ return -EINVAL;
+
+ return ret;
+}
+
+static struct regulator_ops palmas_ops_ldo = {
+ .is_enabled = palmas_is_enabled_ldo,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = palmas_get_voltage_ldo_sel,
+ .set_voltage_sel = palmas_set_voltage_ldo_sel,
+ .list_voltage = palmas_list_voltage_ldo,
+ .map_voltage = palmas_map_voltage_ldo,
+};
+
+/*
+ * setup the hardware based sleep configuration of the SMPS/LDO regulators
+ * from the platform data. This is different to the software based control
+ * supported by the regulator framework as it is controlled by toggling
+ * pins on the PMIC such as PREQ, SYSEN, ...
+ */
+static int palmas_smps_init(struct palmas *palmas, int id,
+ struct palmas_reg_init *reg_init)
+{
+ unsigned int reg;
+ unsigned int addr;
+ int ret;
+
+ addr = palmas_regs_info[id].ctrl_addr;
+
+ ret = palmas_smps_read(palmas, addr, &reg);
+ if (ret)
+ return ret;
+
+ if (id != PALMAS_REG_SMPS10) {
+ if (reg_init->warm_reset)
+ reg |= PALMAS_SMPS12_CTRL_WR_S;
+
+ if (reg_init->roof_floor)
+ reg |= PALMAS_SMPS12_CTRL_ROOF_FLOOR_EN;
+
+ if (reg_init->mode_sleep) {
+ reg &= ~PALMAS_SMPS12_CTRL_MODE_SLEEP_MASK;
+ reg |= reg_init->mode_sleep <<
+ PALMAS_SMPS12_CTRL_MODE_SLEEP_SHIFT;
+ }
+ } else {
+ if (reg_init->mode_sleep) {
+ reg &= ~PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK;
+ reg |= reg_init->mode_sleep <<
+ PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT;
+ }
+
+ }
+ ret = palmas_smps_write(palmas, addr, reg);
+ if (ret)
+ return ret;
+
+ if (palmas_regs_info[id].tstep_addr && reg_init->tstep) {
+ addr = palmas_regs_info[id].tstep_addr;
+
+ reg = reg_init->tstep & PALMAS_SMPS12_TSTEP_TSTEP_MASK;
+
+ ret = palmas_smps_write(palmas, addr, reg);
+ if (ret)
+ return ret;
+ }
+
+ if (palmas_regs_info[id].vsel_addr && reg_init->vsel) {
+ addr = palmas_regs_info[id].vsel_addr;
+
+ reg = reg_init->vsel;
+
+ ret = palmas_smps_write(palmas, addr, reg);
+ if (ret)
+ return ret;
+ }
+
+
+ return 0;
+}
+
+static int palmas_ldo_init(struct palmas *palmas, int id,
+ struct palmas_reg_init *reg_init)
+{
+ unsigned int reg;
+ unsigned int addr;
+ int ret;
+
+ addr = palmas_regs_info[id].ctrl_addr;
+
+ ret = palmas_smps_read(palmas, addr, &reg);
+ if (ret)
+ return ret;
+
+ if (reg_init->warm_reset)
+ reg |= PALMAS_LDO1_CTRL_WR_S;
+
+ if (reg_init->mode_sleep)
+ reg |= PALMAS_LDO1_CTRL_MODE_SLEEP;
+
+ ret = palmas_smps_write(palmas, addr, reg);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static __devinit int palmas_probe(struct platform_device *pdev)
+{
+ struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+ struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data;
+ struct regulator_dev *rdev;
+ struct regulator_config config = { };
+ struct palmas_pmic *pmic;
+ struct palmas_reg_init *reg_init;
+ int id = 0, ret;
+ unsigned int addr, reg;
+
+ if (!pdata)
+ return -EINVAL;
+ if (!pdata->reg_data)
+ return -EINVAL;
+
+ pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
+ if (!pmic)
+ return -ENOMEM;
+
+ pmic->dev = &pdev->dev;
+ pmic->palmas = palmas;
+ palmas->pmic = pmic;
+ platform_set_drvdata(pdev, pmic);
+
+ ret = palmas_smps_read(palmas, PALMAS_SMPS_CTRL, &reg);
+ if (ret)
+ goto err_unregister_regulator;
+
+ if (reg & PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN)
+ pmic->smps123 = 1;
+
+ if (reg & PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN)
+ pmic->smps457 = 1;
+
+ config.regmap = palmas->regmap[REGULATOR_SLAVE];
+ config.dev = &pdev->dev;
+ config.driver_data = pmic;
+
+ for (id = 0; id < PALMAS_REG_LDO1; id++) {
+
+ /*
+ * Miss out regulators which are not available due
+ * to slaving configurations.
+ */
+ switch (id) {
+ case PALMAS_REG_SMPS12:
+ case PALMAS_REG_SMPS3:
+ if (pmic->smps123)
+ continue;
+ break;
+ case PALMAS_REG_SMPS123:
+ if (!pmic->smps123)
+ continue;
+ break;
+ case PALMAS_REG_SMPS45:
+ case PALMAS_REG_SMPS7:
+ if (pmic->smps457)
+ continue;
+ break;
+ case PALMAS_REG_SMPS457:
+ if (!pmic->smps457)
+ continue;
+ }
+
+ /* Register the regulators */
+ pmic->desc[id].name = palmas_regs_info[id].name;
+ pmic->desc[id].id = id;
+
+ if (id != PALMAS_REG_SMPS10) {
+ pmic->desc[id].ops = &palmas_ops_smps;
+ pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
+ } else {
+ pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES;
+ pmic->desc[id].ops = &palmas_ops_smps10;
+ pmic->desc[id].vsel_reg = PALMAS_SMPS10_CTRL;
+ pmic->desc[id].vsel_mask = SMPS10_VSEL;
+ pmic->desc[id].enable_reg = PALMAS_SMPS10_STATUS;
+ pmic->desc[id].enable_mask = SMPS10_BOOST_EN;
+ }
+
+ pmic->desc[id].type = REGULATOR_VOLTAGE;
+ pmic->desc[id].owner = THIS_MODULE;
+
+ /* Initialise sleep/init values from platform data */
+ if (pdata && pdata->reg_init) {
+ reg_init = pdata->reg_init[id];
+ if (reg_init) {
+ ret = palmas_smps_init(palmas, id, reg_init);
+ if (ret)
+ goto err_unregister_regulator;
+ }
+ }
+
+ /*
+ * read and store the RANGE bit for later use
+ * This must be done before regulator is probed otherwise
+ * we error in probe with unsuportable ranges.
+ */
+ if (id != PALMAS_REG_SMPS10) {
+ addr = palmas_regs_info[id].vsel_addr;
+
+ ret = palmas_smps_read(pmic->palmas, addr, &reg);
+ if (ret)
+ goto err_unregister_regulator;
+ if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
+ pmic->range[id] = 1;
+ }
+
+ if (pdata && pdata->reg_data)
+ config.init_data = pdata->reg_data[id];
+ else
+ config.init_data = NULL;
+
+ rdev = regulator_register(&pmic->desc[id], &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev,
+ "failed to register %s regulator\n",
+ pdev->name);
+ ret = PTR_ERR(rdev);
+ goto err_unregister_regulator;
+ }
+
+ /* Save regulator for cleanup */
+ pmic->rdev[id] = rdev;
+ }
+
+ /* Start this loop from the id left from previous loop */
+ for (; id < PALMAS_NUM_REGS; id++) {
+
+ /* Miss out regulators which are not available due
+ * to alternate functions.
+ */
+
+ /* Register the regulators */
+ pmic->desc[id].name = palmas_regs_info[id].name;
+ pmic->desc[id].id = id;
+ pmic->desc[id].n_voltages = PALMAS_LDO_NUM_VOLTAGES;
+
+ pmic->desc[id].ops = &palmas_ops_ldo;
+
+ pmic->desc[id].type = REGULATOR_VOLTAGE;
+ pmic->desc[id].owner = THIS_MODULE;
+ pmic->desc[id].enable_reg = palmas_regs_info[id].ctrl_addr;
+ pmic->desc[id].enable_mask = PALMAS_LDO1_CTRL_MODE_ACTIVE;
+
+ if (pdata && pdata->reg_data)
+ config.init_data = pdata->reg_data[id];
+ else
+ config.init_data = NULL;
+
+ rdev = regulator_register(&pmic->desc[id], &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev,
+ "failed to register %s regulator\n",
+ pdev->name);
+ ret = PTR_ERR(rdev);
+ goto err_unregister_regulator;
+ }
+
+ /* Save regulator for cleanup */
+ pmic->rdev[id] = rdev;
+
+ /* Initialise sleep/init values from platform data */
+ if (pdata->reg_init) {
+ reg_init = pdata->reg_init[id];
+ if (reg_init) {
+ ret = palmas_ldo_init(palmas, id, reg_init);
+ if (ret)
+ goto err_unregister_regulator;
+ }
+ }
+ }
+
+ return 0;
+
+err_unregister_regulator:
+ while (--id >= 0)
+ regulator_unregister(pmic->rdev[id]);
+ kfree(pmic->rdev);
+ kfree(pmic->desc);
+ kfree(pmic);
+ return ret;
+}
+
+static int __devexit palmas_remove(struct platform_device *pdev)
+{
+ struct palmas_pmic *pmic = platform_get_drvdata(pdev);
+ int id;
+
+ for (id = 0; id < PALMAS_NUM_REGS; id++)
+ regulator_unregister(pmic->rdev[id]);
+
+ kfree(pmic->rdev);
+ kfree(pmic->desc);
+ kfree(pmic);
+ return 0;
+}
+
+static struct platform_driver palmas_driver = {
+ .driver = {
+ .name = "palmas-pmic",
+ .owner = THIS_MODULE,
+ },
+ .probe = palmas_probe,
+ .remove = __devexit_p(palmas_remove),
+};
+
+static int __init palmas_init(void)
+{
+ return platform_driver_register(&palmas_driver);
+}
+subsys_initcall(palmas_init);
+
+static void __exit palmas_exit(void)
+{
+ platform_driver_unregister(&palmas_driver);
+}
+module_exit(palmas_exit);
+
+MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
+MODULE_DESCRIPTION("Palmas voltage regulator driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:palmas-pmic");
diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c
index a5aab1b08bcf..8211101121f0 100644
--- a/drivers/regulator/pcap-regulator.c
+++ b/drivers/regulator/pcap-regulator.c
@@ -150,57 +150,33 @@ static struct pcap_regulator vreg_table[] = {
VREG_INFO(SW2S, PCAP_REG_LOWPWR, NA, 20, NA, NA), */
};
-static int pcap_regulator_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV,
- unsigned *selector)
+static int pcap_regulator_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned selector)
{
struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
void *pcap = rdev_get_drvdata(rdev);
- int uV;
- u8 i;
/* the regulator doesn't support voltage switching */
if (vreg->n_voltages == 1)
return -EINVAL;
- for (i = 0; i < vreg->n_voltages; i++) {
- /* For V1 the first is not the best match */
- if (i == 0 && rdev_get_id(rdev) == V1)
- i = 1;
- else if (i + 1 == vreg->n_voltages && rdev_get_id(rdev) == V1)
- i = 0;
-
- uV = vreg->voltage_table[i] * 1000;
- if (min_uV <= uV && uV <= max_uV) {
- *selector = i;
- return ezx_pcap_set_bits(pcap, vreg->reg,
- (vreg->n_voltages - 1) << vreg->index,
- i << vreg->index);
- }
-
- if (i == 0 && rdev_get_id(rdev) == V1)
- i = vreg->n_voltages - 1;
- }
-
- /* the requested voltage range is not supported by this regulator */
- return -EINVAL;
+ return ezx_pcap_set_bits(pcap, vreg->reg,
+ (vreg->n_voltages - 1) << vreg->index,
+ selector << vreg->index);
}
-static int pcap_regulator_get_voltage(struct regulator_dev *rdev)
+static int pcap_regulator_get_voltage_sel(struct regulator_dev *rdev)
{
struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
void *pcap = rdev_get_drvdata(rdev);
u32 tmp;
- int mV;
if (vreg->n_voltages == 1)
- return vreg->voltage_table[0] * 1000;
+ return 0;
ezx_pcap_read(pcap, vreg->reg, &tmp);
tmp = ((tmp >> vreg->index) & (vreg->n_voltages - 1));
- mV = vreg->voltage_table[tmp];
-
- return mV * 1000;
+ return tmp;
}
static int pcap_regulator_enable(struct regulator_dev *rdev)
@@ -248,8 +224,8 @@ static int pcap_regulator_list_voltage(struct regulator_dev *rdev,
static struct regulator_ops pcap_regulator_ops = {
.list_voltage = pcap_regulator_list_voltage,
- .set_voltage = pcap_regulator_set_voltage,
- .get_voltage = pcap_regulator_get_voltage,
+ .set_voltage_sel = pcap_regulator_set_voltage_sel,
+ .get_voltage_sel = pcap_regulator_get_voltage_sel,
.enable = pcap_regulator_enable,
.disable = pcap_regulator_disable,
.is_enabled = pcap_regulator_is_enabled,
@@ -265,7 +241,7 @@ static struct regulator_ops pcap_regulator_ops = {
.owner = THIS_MODULE, \
}
-static struct regulator_desc pcap_regulators[] = {
+static const struct regulator_desc pcap_regulators[] = {
VREG(V1), VREG(V2), VREG(V3), VREG(V4), VREG(V5), VREG(V6), VREG(V7),
VREG(V8), VREG(V9), VREG(V10), VREG(VAUX1), VREG(VAUX2), VREG(VAUX3),
VREG(VAUX4), VREG(VSIM), VREG(VSIM2), VREG(VVIB), VREG(SW1), VREG(SW2),
@@ -275,9 +251,13 @@ static int __devinit pcap_regulator_probe(struct platform_device *pdev)
{
struct regulator_dev *rdev;
void *pcap = dev_get_drvdata(pdev->dev.parent);
+ struct regulator_config config = { };
+
+ config.dev = &pdev->dev;
+ config.init_data = pdev->dev.platform_data;
+ config.driver_data = pcap;
- rdev = regulator_register(&pcap_regulators[pdev->id], &pdev->dev,
- pdev->dev.platform_data, pcap, NULL);
+ rdev = regulator_register(&pcap_regulators[pdev->id], &config);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c
index 6db46c632f13..3c9d14c0017b 100644
--- a/drivers/regulator/pcf50633-regulator.c
+++ b/drivers/regulator/pcf50633-regulator.c
@@ -24,35 +24,25 @@
#include <linux/mfd/pcf50633/core.h>
#include <linux/mfd/pcf50633/pmic.h>
-#define PCF50633_REGULATOR(_name, _id, _n) \
- { \
- .name = _name, \
- .id = _id, \
- .ops = &pcf50633_regulator_ops, \
- .n_voltages = _n, \
- .type = REGULATOR_VOLTAGE, \
- .owner = THIS_MODULE, \
+#define PCF50633_REGULATOR(_name, _id, _n) \
+ { \
+ .name = _name, \
+ .id = PCF50633_REGULATOR_##_id, \
+ .ops = &pcf50633_regulator_ops, \
+ .n_voltages = _n, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .vsel_reg = PCF50633_REG_##_id##OUT, \
+ .vsel_mask = 0xff, \
+ .enable_reg = PCF50633_REG_##_id##OUT + 1, \
+ .enable_mask = PCF50633_REGULATOR_ON, \
}
-static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = {
- [PCF50633_REGULATOR_AUTO] = PCF50633_REG_AUTOOUT,
- [PCF50633_REGULATOR_DOWN1] = PCF50633_REG_DOWN1OUT,
- [PCF50633_REGULATOR_DOWN2] = PCF50633_REG_DOWN2OUT,
- [PCF50633_REGULATOR_MEMLDO] = PCF50633_REG_MEMLDOOUT,
- [PCF50633_REGULATOR_LDO1] = PCF50633_REG_LDO1OUT,
- [PCF50633_REGULATOR_LDO2] = PCF50633_REG_LDO2OUT,
- [PCF50633_REGULATOR_LDO3] = PCF50633_REG_LDO3OUT,
- [PCF50633_REGULATOR_LDO4] = PCF50633_REG_LDO4OUT,
- [PCF50633_REGULATOR_LDO5] = PCF50633_REG_LDO5OUT,
- [PCF50633_REGULATOR_LDO6] = PCF50633_REG_LDO6OUT,
- [PCF50633_REGULATOR_HCLDO] = PCF50633_REG_HCLDOOUT,
-};
-
/* Bits from voltage value */
static u8 auto_voltage_bits(unsigned int millivolts)
{
if (millivolts < 1800)
- return 0;
+ return 0x2f;
if (millivolts > 3800)
return 0xff;
@@ -87,6 +77,9 @@ static u8 ldo_voltage_bits(unsigned int millivolts)
/* Obtain voltage value from bits */
static unsigned int auto_voltage_value(u8 bits)
{
+ /* AUTOOUT: 00000000 to 00101110 are reserved.
+ * Return 0 for bits in reserved range, which means this selector code
+ * can't be used on this system */
if (bits < 0x2f)
return 0;
@@ -123,7 +116,7 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
millivolts = min_uV / 1000;
- regnr = pcf50633_regulator_registers[regulator_id];
+ regnr = rdev->desc->vsel_reg;
switch (regulator_id) {
case PCF50633_REGULATOR_AUTO:
@@ -154,20 +147,22 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
return pcf50633_reg_write(pcf, regnr, volt_bits);
}
-static int pcf50633_regulator_voltage_value(enum pcf50633_regulator_id id,
- u8 bits)
+static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
+ unsigned int index)
{
+ int regulator_id = rdev_get_id(rdev);
+
int millivolts;
- switch (id) {
+ switch (regulator_id) {
case PCF50633_REGULATOR_AUTO:
- millivolts = auto_voltage_value(bits);
+ millivolts = auto_voltage_value(index);
break;
case PCF50633_REGULATOR_DOWN1:
- millivolts = down_voltage_value(bits);
+ millivolts = down_voltage_value(index);
break;
case PCF50633_REGULATOR_DOWN2:
- millivolts = down_voltage_value(bits);
+ millivolts = down_voltage_value(index);
break;
case PCF50633_REGULATOR_LDO1:
case PCF50633_REGULATOR_LDO2:
@@ -177,7 +172,7 @@ static int pcf50633_regulator_voltage_value(enum pcf50633_regulator_id id,
case PCF50633_REGULATOR_LDO6:
case PCF50633_REGULATOR_HCLDO:
case PCF50633_REGULATOR_MEMLDO:
- millivolts = ldo_voltage_value(bits);
+ millivolts = ldo_voltage_value(index);
break;
default:
return -EINVAL;
@@ -186,140 +181,44 @@ static int pcf50633_regulator_voltage_value(enum pcf50633_regulator_id id,
return millivolts * 1000;
}
-static int pcf50633_regulator_get_voltage(struct regulator_dev *rdev)
-{
- struct pcf50633 *pcf;
- int regulator_id;
- u8 volt_bits, regnr;
-
- pcf = rdev_get_drvdata(rdev);
-
- regulator_id = rdev_get_id(rdev);
- if (regulator_id >= PCF50633_NUM_REGULATORS)
- return -EINVAL;
-
- regnr = pcf50633_regulator_registers[regulator_id];
-
- volt_bits = pcf50633_reg_read(pcf, regnr);
-
- return pcf50633_regulator_voltage_value(regulator_id, volt_bits);
-}
-
-static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
- unsigned int index)
-{
- struct pcf50633 *pcf;
- int regulator_id;
-
- pcf = rdev_get_drvdata(rdev);
-
- regulator_id = rdev_get_id(rdev);
-
- switch (regulator_id) {
- case PCF50633_REGULATOR_AUTO:
- index += 0x2f;
- break;
- default:
- break;
- }
-
- return pcf50633_regulator_voltage_value(regulator_id, index);
-}
-
-static int pcf50633_regulator_enable(struct regulator_dev *rdev)
-{
- struct pcf50633 *pcf = rdev_get_drvdata(rdev);
- int regulator_id;
- u8 regnr;
-
- regulator_id = rdev_get_id(rdev);
- if (regulator_id >= PCF50633_NUM_REGULATORS)
- return -EINVAL;
-
- /* The *ENA register is always one after the *OUT register */
- regnr = pcf50633_regulator_registers[regulator_id] + 1;
-
- return pcf50633_reg_set_bit_mask(pcf, regnr, PCF50633_REGULATOR_ON,
- PCF50633_REGULATOR_ON);
-}
-
-static int pcf50633_regulator_disable(struct regulator_dev *rdev)
-{
- struct pcf50633 *pcf = rdev_get_drvdata(rdev);
- int regulator_id;
- u8 regnr;
-
- regulator_id = rdev_get_id(rdev);
- if (regulator_id >= PCF50633_NUM_REGULATORS)
- return -EINVAL;
-
- /* the *ENA register is always one after the *OUT register */
- regnr = pcf50633_regulator_registers[regulator_id] + 1;
-
- return pcf50633_reg_set_bit_mask(pcf, regnr,
- PCF50633_REGULATOR_ON, 0);
-}
-
-static int pcf50633_regulator_is_enabled(struct regulator_dev *rdev)
-{
- struct pcf50633 *pcf = rdev_get_drvdata(rdev);
- int regulator_id = rdev_get_id(rdev);
- u8 regnr;
-
- regulator_id = rdev_get_id(rdev);
- if (regulator_id >= PCF50633_NUM_REGULATORS)
- return -EINVAL;
-
- /* the *ENA register is always one after the *OUT register */
- regnr = pcf50633_regulator_registers[regulator_id] + 1;
-
- return pcf50633_reg_read(pcf, regnr) & PCF50633_REGULATOR_ON;
-}
-
static struct regulator_ops pcf50633_regulator_ops = {
.set_voltage = pcf50633_regulator_set_voltage,
- .get_voltage = pcf50633_regulator_get_voltage,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = pcf50633_regulator_list_voltage,
- .enable = pcf50633_regulator_enable,
- .disable = pcf50633_regulator_disable,
- .is_enabled = pcf50633_regulator_is_enabled,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
};
-static struct regulator_desc regulators[] = {
- [PCF50633_REGULATOR_AUTO] =
- PCF50633_REGULATOR("auto", PCF50633_REGULATOR_AUTO, 81),
- [PCF50633_REGULATOR_DOWN1] =
- PCF50633_REGULATOR("down1", PCF50633_REGULATOR_DOWN1, 96),
- [PCF50633_REGULATOR_DOWN2] =
- PCF50633_REGULATOR("down2", PCF50633_REGULATOR_DOWN2, 96),
- [PCF50633_REGULATOR_LDO1] =
- PCF50633_REGULATOR("ldo1", PCF50633_REGULATOR_LDO1, 28),
- [PCF50633_REGULATOR_LDO2] =
- PCF50633_REGULATOR("ldo2", PCF50633_REGULATOR_LDO2, 28),
- [PCF50633_REGULATOR_LDO3] =
- PCF50633_REGULATOR("ldo3", PCF50633_REGULATOR_LDO3, 28),
- [PCF50633_REGULATOR_LDO4] =
- PCF50633_REGULATOR("ldo4", PCF50633_REGULATOR_LDO4, 28),
- [PCF50633_REGULATOR_LDO5] =
- PCF50633_REGULATOR("ldo5", PCF50633_REGULATOR_LDO5, 28),
- [PCF50633_REGULATOR_LDO6] =
- PCF50633_REGULATOR("ldo6", PCF50633_REGULATOR_LDO6, 28),
- [PCF50633_REGULATOR_HCLDO] =
- PCF50633_REGULATOR("hcldo", PCF50633_REGULATOR_HCLDO, 28),
- [PCF50633_REGULATOR_MEMLDO] =
- PCF50633_REGULATOR("memldo", PCF50633_REGULATOR_MEMLDO, 28),
+static const struct regulator_desc regulators[] = {
+ [PCF50633_REGULATOR_AUTO] = PCF50633_REGULATOR("auto", AUTO, 128),
+ [PCF50633_REGULATOR_DOWN1] = PCF50633_REGULATOR("down1", DOWN1, 96),
+ [PCF50633_REGULATOR_DOWN2] = PCF50633_REGULATOR("down2", DOWN2, 96),
+ [PCF50633_REGULATOR_LDO1] = PCF50633_REGULATOR("ldo1", LDO1, 28),
+ [PCF50633_REGULATOR_LDO2] = PCF50633_REGULATOR("ldo2", LDO2, 28),
+ [PCF50633_REGULATOR_LDO3] = PCF50633_REGULATOR("ldo3", LDO3, 28),
+ [PCF50633_REGULATOR_LDO4] = PCF50633_REGULATOR("ldo4", LDO4, 28),
+ [PCF50633_REGULATOR_LDO5] = PCF50633_REGULATOR("ldo5", LDO5, 28),
+ [PCF50633_REGULATOR_LDO6] = PCF50633_REGULATOR("ldo6", LDO6, 28),
+ [PCF50633_REGULATOR_HCLDO] = PCF50633_REGULATOR("hcldo", HCLDO, 28),
+ [PCF50633_REGULATOR_MEMLDO] = PCF50633_REGULATOR("memldo", MEMLDO, 28),
};
static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
{
struct regulator_dev *rdev;
struct pcf50633 *pcf;
+ struct regulator_config config = { };
/* Already set by core driver */
pcf = dev_to_pcf50633(pdev->dev.parent);
- rdev = regulator_register(&regulators[pdev->id], &pdev->dev,
- pdev->dev.platform_data, pcf, NULL);
+ config.dev = &pdev->dev;
+ config.init_data = pdev->dev.platform_data;
+ config.driver_data = pcf;
+ config.regmap = pcf->regmap;
+
+ rdev = regulator_register(&regulators[pdev->id], &config);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c
new file mode 100644
index 000000000000..1d34e64a1307
--- /dev/null
+++ b/drivers/regulator/rc5t583-regulator.c
@@ -0,0 +1,255 @@
+/*
+ * Regulator driver for RICOH RC5T583 power management chip.
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
+ * Author: Laxman dewangan <ldewangan@nvidia.com>
+ *
+ * based on code
+ * Copyright (C) 2011 RICOH COMPANY,LTD
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/gpio.h>
+#include <linux/mfd/rc5t583.h>
+
+struct rc5t583_regulator_info {
+ int deepsleep_id;
+
+ /* Regulator register address.*/
+ uint8_t reg_disc_reg;
+ uint8_t disc_bit;
+ uint8_t deepsleep_reg;
+
+ /* Regulator specific turn-on delay and voltage settling time*/
+ int enable_uv_per_us;
+ int change_uv_per_us;
+
+ /* Used by regulator core */
+ struct regulator_desc desc;
+};
+
+struct rc5t583_regulator {
+ struct rc5t583_regulator_info *reg_info;
+
+ /* Devices */
+ struct device *dev;
+ struct rc5t583 *mfd;
+ struct regulator_dev *rdev;
+};
+
+static int rc5t583_regulator_enable_time(struct regulator_dev *rdev)
+{
+ struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
+ int vsel = regulator_get_voltage_sel_regmap(rdev);
+ int curr_uV = regulator_list_voltage_linear(rdev, vsel);
+
+ return DIV_ROUND_UP(curr_uV, reg->reg_info->enable_uv_per_us);
+}
+
+static int rc5t583_set_voltage_time_sel(struct regulator_dev *rdev,
+ unsigned int old_selector, unsigned int new_selector)
+{
+ struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
+ int old_uV, new_uV;
+ old_uV = regulator_list_voltage_linear(rdev, old_selector);
+
+ if (old_uV < 0)
+ return old_uV;
+
+ new_uV = regulator_list_voltage_linear(rdev, new_selector);
+ if (new_uV < 0)
+ return new_uV;
+
+ return DIV_ROUND_UP(abs(old_uV - new_uV),
+ reg->reg_info->change_uv_per_us);
+}
+
+
+static struct regulator_ops rc5t583_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .enable_time = rc5t583_regulator_enable_time,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .set_voltage_time_sel = rc5t583_set_voltage_time_sel,
+};
+
+#define RC5T583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, \
+ _vout_mask, _min_mv, _max_mv, _step_uV, _enable_mv) \
+{ \
+ .reg_disc_reg = RC5T583_REG_##_disc_reg, \
+ .disc_bit = _disc_bit, \
+ .deepsleep_reg = RC5T583_REG_##_id##DAC_DS, \
+ .enable_uv_per_us = _enable_mv * 1000, \
+ .change_uv_per_us = 40 * 1000, \
+ .deepsleep_id = RC5T583_DS_##_id, \
+ .desc = { \
+ .name = "rc5t583-regulator-"#_id, \
+ .id = RC5T583_REGULATOR_##_id, \
+ .n_voltages = (_max_mv - _min_mv) * 1000 / _step_uV + 1, \
+ .ops = &rc5t583_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .vsel_reg = RC5T583_REG_##_id##DAC, \
+ .vsel_mask = _vout_mask, \
+ .enable_reg = RC5T583_REG_##_en_reg, \
+ .enable_mask = BIT(_en_bit), \
+ .min_uV = _min_mv * 1000, \
+ .uV_step = _step_uV, \
+ }, \
+}
+
+static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = {
+ RC5T583_REG(DC0, DC0CTL, 0, DC0CTL, 1, 0x7F, 700, 1500, 12500, 4),
+ RC5T583_REG(DC1, DC1CTL, 0, DC1CTL, 1, 0x7F, 700, 1500, 12500, 14),
+ RC5T583_REG(DC2, DC2CTL, 0, DC2CTL, 1, 0x7F, 900, 2400, 12500, 14),
+ RC5T583_REG(DC3, DC3CTL, 0, DC3CTL, 1, 0x7F, 900, 2400, 12500, 14),
+ RC5T583_REG(LDO0, LDOEN2, 0, LDODIS2, 0, 0x7F, 900, 3400, 25000, 160),
+ RC5T583_REG(LDO1, LDOEN2, 1, LDODIS2, 1, 0x7F, 900, 3400, 25000, 160),
+ RC5T583_REG(LDO2, LDOEN2, 2, LDODIS2, 2, 0x7F, 900, 3400, 25000, 160),
+ RC5T583_REG(LDO3, LDOEN2, 3, LDODIS2, 3, 0x7F, 900, 3400, 25000, 160),
+ RC5T583_REG(LDO4, LDOEN2, 4, LDODIS2, 4, 0x3F, 750, 1500, 12500, 133),
+ RC5T583_REG(LDO5, LDOEN2, 5, LDODIS2, 5, 0x7F, 900, 3400, 25000, 267),
+ RC5T583_REG(LDO6, LDOEN2, 6, LDODIS2, 6, 0x7F, 900, 3400, 25000, 133),
+ RC5T583_REG(LDO7, LDOEN2, 7, LDODIS2, 7, 0x7F, 900, 3400, 25000, 233),
+ RC5T583_REG(LDO8, LDOEN1, 0, LDODIS1, 0, 0x7F, 900, 3400, 25000, 233),
+ RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, 0x7F, 900, 3400, 25000, 133),
+};
+
+static int __devinit rc5t583_regulator_probe(struct platform_device *pdev)
+{
+ struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
+ struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
+ struct regulator_init_data *reg_data;
+ struct regulator_config config = { };
+ struct rc5t583_regulator *reg = NULL;
+ struct rc5t583_regulator *regs;
+ struct regulator_dev *rdev;
+ struct rc5t583_regulator_info *ri;
+ int ret;
+ int id;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "No platform data, exiting...\n");
+ return -ENODEV;
+ }
+
+ regs = devm_kzalloc(&pdev->dev, RC5T583_REGULATOR_MAX *
+ sizeof(struct rc5t583_regulator), GFP_KERNEL);
+ if (!regs) {
+ dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
+ return -ENOMEM;
+ }
+
+
+ for (id = 0; id < RC5T583_REGULATOR_MAX; ++id) {
+ reg_data = pdata->reg_init_data[id];
+
+ /* No need to register if there is no regulator data */
+ if (!reg_data)
+ continue;
+
+ reg = &regs[id];
+ ri = &rc5t583_reg_info[id];
+ reg->reg_info = ri;
+ reg->mfd = rc5t583;
+ reg->dev = &pdev->dev;
+
+ if (ri->deepsleep_id == RC5T583_DS_NONE)
+ goto skip_ext_pwr_config;
+
+ ret = rc5t583_ext_power_req_config(rc5t583->dev,
+ ri->deepsleep_id,
+ pdata->regulator_ext_pwr_control[id],
+ pdata->regulator_deepsleep_slot[id]);
+ /*
+ * Configuring external control is not a major issue,
+ * just give warning.
+ */
+ if (ret < 0)
+ dev_warn(&pdev->dev,
+ "Failed to configure ext control %d\n", id);
+
+skip_ext_pwr_config:
+ config.dev = &pdev->dev;
+ config.init_data = reg_data;
+ config.driver_data = reg;
+ config.regmap = rc5t583->regmap;
+
+ rdev = regulator_register(&ri->desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "Failed to register regulator %s\n",
+ ri->desc.name);
+ ret = PTR_ERR(rdev);
+ goto clean_exit;
+ }
+ reg->rdev = rdev;
+ }
+ platform_set_drvdata(pdev, regs);
+ return 0;
+
+clean_exit:
+ while (--id >= 0)
+ regulator_unregister(regs[id].rdev);
+
+ return ret;
+}
+
+static int __devexit rc5t583_regulator_remove(struct platform_device *pdev)
+{
+ struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
+ int id;
+
+ for (id = 0; id < RC5T583_REGULATOR_MAX; ++id)
+ regulator_unregister(regs[id].rdev);
+ return 0;
+}
+
+static struct platform_driver rc5t583_regulator_driver = {
+ .driver = {
+ .name = "rc5t583-regulator",
+ .owner = THIS_MODULE,
+ },
+ .probe = rc5t583_regulator_probe,
+ .remove = __devexit_p(rc5t583_regulator_remove),
+};
+
+static int __init rc5t583_regulator_init(void)
+{
+ return platform_driver_register(&rc5t583_regulator_driver);
+}
+subsys_initcall(rc5t583_regulator_init);
+
+static void __exit rc5t583_regulator_exit(void)
+{
+ platform_driver_unregister(&rc5t583_regulator_driver);
+}
+module_exit(rc5t583_regulator_exit);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("RC5T583 regulator driver");
+MODULE_ALIAS("platform:rc5t583-regulator");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index 4ca2db059004..290d6fc01029 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -12,7 +12,6 @@
*/
#include <linux/bug.h>
-#include <linux/delay.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/slab.h>
@@ -28,6 +27,7 @@ struct s5m8767_info {
struct s5m87xx_dev *iodev;
int num_regulators;
struct regulator_dev **rdev;
+ struct s5m_opmode_data *opmode;
int ramp_delay;
bool buck2_ramp;
@@ -141,9 +141,56 @@ static int s5m8767_list_voltage(struct regulator_dev *rdev,
return val;
}
-static int s5m8767_get_register(struct regulator_dev *rdev, int *reg)
+static unsigned int s5m8767_opmode_reg[][4] = {
+ /* {OFF, ON, LOWPOWER, SUSPEND} */
+ /* LDO1 ... LDO28 */
+ {0x0, 0x3, 0x2, 0x1}, /* LDO1 */
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x0, 0x0, 0x0},
+ {0x0, 0x3, 0x2, 0x1}, /* LDO5 */
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1}, /* LDO10 */
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1}, /* LDO15 */
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x0, 0x0, 0x0},
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1}, /* LDO20 */
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x0, 0x0, 0x0},
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1}, /* LDO25 */
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1},
+ {0x0, 0x3, 0x2, 0x1}, /* LDO28 */
+
+ /* BUCK1 ... BUCK9 */
+ {0x0, 0x3, 0x1, 0x1}, /* BUCK1 */
+ {0x0, 0x3, 0x1, 0x1},
+ {0x0, 0x3, 0x1, 0x1},
+ {0x0, 0x3, 0x1, 0x1},
+ {0x0, 0x3, 0x2, 0x1}, /* BUCK5 */
+ {0x0, 0x3, 0x1, 0x1},
+ {0x0, 0x3, 0x1, 0x1},
+ {0x0, 0x3, 0x1, 0x1},
+ {0x0, 0x3, 0x1, 0x1}, /* BUCK9 */
+};
+
+static int s5m8767_get_register(struct regulator_dev *rdev, int *reg,
+ int *enable_ctrl)
{
int reg_id = rdev_get_id(rdev);
+ unsigned int mode;
+ struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
switch (reg_id) {
case S5M8767_LDO1 ... S5M8767_LDO2:
@@ -168,6 +215,8 @@ static int s5m8767_get_register(struct regulator_dev *rdev, int *reg)
return -EINVAL;
}
+ mode = s5m8767->opmode[reg_id].mode;
+ *enable_ctrl = s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;
return 0;
}
@@ -175,10 +224,10 @@ static int s5m8767_reg_is_enabled(struct regulator_dev *rdev)
{
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
int ret, reg;
- int mask = 0xc0, pattern = 0xc0;
+ int mask = 0xc0, enable_ctrl;
u8 val;
- ret = s5m8767_get_register(rdev, &reg);
+ ret = s5m8767_get_register(rdev, &reg, &enable_ctrl);
if (ret == -EINVAL)
return 1;
else if (ret)
@@ -188,33 +237,33 @@ static int s5m8767_reg_is_enabled(struct regulator_dev *rdev)
if (ret)
return ret;
- return (val & mask) == pattern;
+ return (val & mask) == enable_ctrl;
}
static int s5m8767_reg_enable(struct regulator_dev *rdev)
{
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
int ret, reg;
- int mask = 0xc0, pattern = 0xc0;
+ int mask = 0xc0, enable_ctrl;
- ret = s5m8767_get_register(rdev, &reg);
+ ret = s5m8767_get_register(rdev, &reg, &enable_ctrl);
if (ret)
return ret;
- return s5m_reg_update(s5m8767->iodev, reg, pattern, mask);
+ return s5m_reg_update(s5m8767->iodev, reg, enable_ctrl, mask);
}
static int s5m8767_reg_disable(struct regulator_dev *rdev)
{
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
int ret, reg;
- int mask = 0xc0, pattern = 0xc0;
+ int mask = 0xc0, enable_ctrl;
- ret = s5m8767_get_register(rdev, &reg);
+ ret = s5m8767_get_register(rdev, &reg, &enable_ctrl);
if (ret)
return ret;
- return s5m_reg_update(s5m8767->iodev, reg, ~pattern, mask);
+ return s5m_reg_update(s5m8767->iodev, reg, ~mask, mask);
}
static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg)
@@ -297,7 +346,10 @@ static int s5m8767_convert_voltage_to_sel(
if (max_vol < desc->min || min_vol > desc->max)
return -EINVAL;
- selector = (min_vol - desc->min) / desc->step;
+ if (min_vol < desc->min)
+ min_vol = desc->min;
+
+ selector = DIV_ROUND_UP(min_vol - desc->min, desc->step);
if (desc->min + desc->step * selector > max_vol)
return -EINVAL;
@@ -305,14 +357,33 @@ static int s5m8767_convert_voltage_to_sel(
return selector;
}
+static inline void s5m8767_set_high(struct s5m8767_info *s5m8767)
+{
+ int temp_index = s5m8767->buck_gpioindex;
+
+ gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
+ gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
+ gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
+}
+
+static inline void s5m8767_set_low(struct s5m8767_info *s5m8767)
+{
+ int temp_index = s5m8767->buck_gpioindex;
+
+ gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
+ gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
+ gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
+}
+
static int s5m8767_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV, unsigned *selector)
{
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
const struct s5m_voltage_desc *desc;
int reg_id = rdev_get_id(rdev);
- int sel, reg, mask, ret;
+ int sel, reg, mask, ret = 0, old_index, index = 0;
u8 val;
+ u8 *buck234_vol = NULL;
switch (reg_id) {
case S5M8767_LDO1 ... S5M8767_LDO28:
@@ -320,6 +391,12 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev,
break;
case S5M8767_BUCK1 ... S5M8767_BUCK6:
mask = 0xff;
+ if (reg_id == S5M8767_BUCK2 && s5m8767->buck2_gpiodvs)
+ buck234_vol = &s5m8767->buck2_vol[0];
+ else if (reg_id == S5M8767_BUCK3 && s5m8767->buck3_gpiodvs)
+ buck234_vol = &s5m8767->buck3_vol[0];
+ else if (reg_id == S5M8767_BUCK4 && s5m8767->buck4_gpiodvs)
+ buck234_vol = &s5m8767->buck4_vol[0];
break;
case S5M8767_BUCK7 ... S5M8767_BUCK8:
return -EINVAL;
@@ -336,102 +413,32 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev,
if (sel < 0)
return sel;
- ret = s5m8767_get_voltage_register(rdev, &reg);
- if (ret)
- return ret;
-
- s5m_reg_read(s5m8767->iodev, reg, &val);
- val &= ~mask;
- val |= sel;
-
- ret = s5m_reg_write(s5m8767->iodev, reg, val);
- *selector = sel;
-
- return ret;
-}
-
-static inline void s5m8767_set_high(struct s5m8767_info *s5m8767)
-{
- int temp_index = s5m8767->buck_gpioindex;
-
- gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
- gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
- gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
-}
-
-static inline void s5m8767_set_low(struct s5m8767_info *s5m8767)
-{
- int temp_index = s5m8767->buck_gpioindex;
-
- gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
- gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
- gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
-}
-
-static int s5m8767_set_voltage_buck(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *selector)
-{
- struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
- int reg_id = rdev_get_id(rdev);
- const struct s5m_voltage_desc *desc;
- int new_val, old_val, i = 0;
-
- if (reg_id < S5M8767_BUCK1 || reg_id > S5M8767_BUCK6)
- return -EINVAL;
-
- switch (reg_id) {
- case S5M8767_BUCK1:
- return s5m8767_set_voltage(rdev, min_uV, max_uV, selector);
- case S5M8767_BUCK2 ... S5M8767_BUCK4:
- break;
- case S5M8767_BUCK5 ... S5M8767_BUCK6:
- return s5m8767_set_voltage(rdev, min_uV, max_uV, selector);
- case S5M8767_BUCK9:
- return s5m8767_set_voltage(rdev, min_uV, max_uV, selector);
- }
+ /* buck234_vol != NULL means to control buck234 voltage via DVS GPIO */
+ if (buck234_vol) {
+ while (*buck234_vol != sel) {
+ buck234_vol++;
+ index++;
+ }
+ old_index = s5m8767->buck_gpioindex;
+ s5m8767->buck_gpioindex = index;
+
+ if (index > old_index)
+ s5m8767_set_high(s5m8767);
+ else
+ s5m8767_set_low(s5m8767);
+ } else {
+ ret = s5m8767_get_voltage_register(rdev, &reg);
+ if (ret)
+ return ret;
- desc = reg_voltage_map[reg_id];
- new_val = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV);
- if (new_val < 0)
- return new_val;
+ s5m_reg_read(s5m8767->iodev, reg, &val);
+ val = (val & ~mask) | sel;
- switch (reg_id) {
- case S5M8767_BUCK2:
- if (s5m8767->buck2_gpiodvs) {
- while (s5m8767->buck2_vol[i] != new_val)
- i++;
- } else
- return s5m8767_set_voltage(rdev, min_uV,
- max_uV, selector);
- break;
- case S5M8767_BUCK3:
- if (s5m8767->buck3_gpiodvs) {
- while (s5m8767->buck3_vol[i] != new_val)
- i++;
- } else
- return s5m8767_set_voltage(rdev, min_uV,
- max_uV, selector);
- break;
- case S5M8767_BUCK4:
- if (s5m8767->buck3_gpiodvs) {
- while (s5m8767->buck4_vol[i] != new_val)
- i++;
- } else
- return s5m8767_set_voltage(rdev, min_uV,
- max_uV, selector);
- break;
+ ret = s5m_reg_write(s5m8767->iodev, reg, val);
}
- old_val = s5m8767->buck_gpioindex;
- s5m8767->buck_gpioindex = i;
-
- if (i > old_val)
- s5m8767_set_high(s5m8767);
- else
- s5m8767_set_low(s5m8767);
-
- *selector = new_val;
- return 0;
+ *selector = sel;
+ return ret;
}
static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
@@ -450,7 +457,7 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
return 0;
}
-static struct regulator_ops s5m8767_ldo_ops = {
+static struct regulator_ops s5m8767_ops = {
.list_voltage = s5m8767_list_voltage,
.is_enabled = s5m8767_reg_is_enabled,
.enable = s5m8767_reg_enable,
@@ -460,75 +467,59 @@ static struct regulator_ops s5m8767_ldo_ops = {
.set_voltage_time_sel = s5m8767_set_voltage_time_sel,
};
-static struct regulator_ops s5m8767_buck_ops = {
- .list_voltage = s5m8767_list_voltage,
- .is_enabled = s5m8767_reg_is_enabled,
- .enable = s5m8767_reg_enable,
- .disable = s5m8767_reg_disable,
- .get_voltage_sel = s5m8767_get_voltage_sel,
- .set_voltage = s5m8767_set_voltage_buck,
- .set_voltage_time_sel = s5m8767_set_voltage_time_sel,
-};
-
-#define regulator_desc_ldo(num) { \
- .name = "LDO"#num, \
- .id = S5M8767_LDO##num, \
- .ops = &s5m8767_ldo_ops, \
- .type = REGULATOR_VOLTAGE, \
- .owner = THIS_MODULE, \
-}
-#define regulator_desc_buck(num) { \
- .name = "BUCK"#num, \
- .id = S5M8767_BUCK##num, \
- .ops = &s5m8767_buck_ops, \
+#define s5m8767_regulator_desc(_name) { \
+ .name = #_name, \
+ .id = S5M8767_##_name, \
+ .ops = &s5m8767_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}
static struct regulator_desc regulators[] = {
- regulator_desc_ldo(1),
- regulator_desc_ldo(2),
- regulator_desc_ldo(3),
- regulator_desc_ldo(4),
- regulator_desc_ldo(5),
- regulator_desc_ldo(6),
- regulator_desc_ldo(7),
- regulator_desc_ldo(8),
- regulator_desc_ldo(9),
- regulator_desc_ldo(10),
- regulator_desc_ldo(11),
- regulator_desc_ldo(12),
- regulator_desc_ldo(13),
- regulator_desc_ldo(14),
- regulator_desc_ldo(15),
- regulator_desc_ldo(16),
- regulator_desc_ldo(17),
- regulator_desc_ldo(18),
- regulator_desc_ldo(19),
- regulator_desc_ldo(20),
- regulator_desc_ldo(21),
- regulator_desc_ldo(22),
- regulator_desc_ldo(23),
- regulator_desc_ldo(24),
- regulator_desc_ldo(25),
- regulator_desc_ldo(26),
- regulator_desc_ldo(27),
- regulator_desc_ldo(28),
- regulator_desc_buck(1),
- regulator_desc_buck(2),
- regulator_desc_buck(3),
- regulator_desc_buck(4),
- regulator_desc_buck(5),
- regulator_desc_buck(6),
- regulator_desc_buck(7),
- regulator_desc_buck(8),
- regulator_desc_buck(9),
+ s5m8767_regulator_desc(LDO1),
+ s5m8767_regulator_desc(LDO2),
+ s5m8767_regulator_desc(LDO3),
+ s5m8767_regulator_desc(LDO4),
+ s5m8767_regulator_desc(LDO5),
+ s5m8767_regulator_desc(LDO6),
+ s5m8767_regulator_desc(LDO7),
+ s5m8767_regulator_desc(LDO8),
+ s5m8767_regulator_desc(LDO9),
+ s5m8767_regulator_desc(LDO10),
+ s5m8767_regulator_desc(LDO11),
+ s5m8767_regulator_desc(LDO12),
+ s5m8767_regulator_desc(LDO13),
+ s5m8767_regulator_desc(LDO14),
+ s5m8767_regulator_desc(LDO15),
+ s5m8767_regulator_desc(LDO16),
+ s5m8767_regulator_desc(LDO17),
+ s5m8767_regulator_desc(LDO18),
+ s5m8767_regulator_desc(LDO19),
+ s5m8767_regulator_desc(LDO20),
+ s5m8767_regulator_desc(LDO21),
+ s5m8767_regulator_desc(LDO22),
+ s5m8767_regulator_desc(LDO23),
+ s5m8767_regulator_desc(LDO24),
+ s5m8767_regulator_desc(LDO25),
+ s5m8767_regulator_desc(LDO26),
+ s5m8767_regulator_desc(LDO27),
+ s5m8767_regulator_desc(LDO28),
+ s5m8767_regulator_desc(BUCK1),
+ s5m8767_regulator_desc(BUCK2),
+ s5m8767_regulator_desc(BUCK3),
+ s5m8767_regulator_desc(BUCK4),
+ s5m8767_regulator_desc(BUCK5),
+ s5m8767_regulator_desc(BUCK6),
+ s5m8767_regulator_desc(BUCK7),
+ s5m8767_regulator_desc(BUCK8),
+ s5m8767_regulator_desc(BUCK9),
};
static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
{
struct s5m87xx_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct s5m_platform_data *pdata = dev_get_platdata(iodev->dev);
+ struct regulator_config config = { };
struct regulator_dev **rdev;
struct s5m8767_info *s5m8767;
int i, ret, size;
@@ -586,6 +577,7 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
s5m8767->buck2_ramp = pdata->buck2_ramp_enable;
s5m8767->buck3_ramp = pdata->buck3_ramp_enable;
s5m8767->buck4_ramp = pdata->buck4_ramp_enable;
+ s5m8767->opmode = pdata->opmode;
for (i = 0; i < 8; i++) {
if (s5m8767->buck2_gpiodvs) {
@@ -723,8 +715,11 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
regulators[id].n_voltages =
(desc->max - desc->min) / desc->step + 1;
- rdev[i] = regulator_register(&regulators[id], s5m8767->dev,
- pdata->regulators[i].initdata, s5m8767, NULL);
+ config.dev = s5m8767->dev;
+ config.init_data = pdata->regulators[i].initdata;
+ config.driver_data = s5m8767;
+
+ rdev[i] = regulator_register(&regulators[id], &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
dev_err(s5m8767->dev, "regulator init failed for %d\n",
diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c
index d9278da18a9e..d840d8440a91 100644
--- a/drivers/regulator/tps6105x-regulator.c
+++ b/drivers/regulator/tps6105x-regulator.c
@@ -123,7 +123,7 @@ static struct regulator_ops tps6105x_regulator_ops = {
.list_voltage = tps6105x_regulator_list_voltage,
};
-static struct regulator_desc tps6105x_regulator_desc = {
+static const struct regulator_desc tps6105x_regulator_desc = {
.name = "tps6105x-boost",
.ops = &tps6105x_regulator_ops,
.type = REGULATOR_VOLTAGE,
@@ -139,6 +139,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
{
struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
struct tps6105x_platform_data *pdata = tps6105x->pdata;
+ struct regulator_config config = { };
int ret;
/* This instance is not set for regulator mode so bail out */
@@ -148,11 +149,13 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
return 0;
}
+ config.dev = &tps6105x->client->dev;
+ config.init_data = pdata->regulator_data;
+ config.driver_data = tps6105x;
+
/* Register regulator with framework */
tps6105x->regulator = regulator_register(&tps6105x_regulator_desc,
- &tps6105x->client->dev,
- pdata->regulator_data, tps6105x,
- NULL);
+ &config);
if (IS_ERR(tps6105x->regulator)) {
ret = PTR_ERR(tps6105x->regulator);
dev_err(&tps6105x->client->dev,
diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
index e2ec73068ee2..e534269ed44a 100644
--- a/drivers/regulator/tps62360-regulator.c
+++ b/drivers/regulator/tps62360-regulator.c
@@ -1,7 +1,7 @@
/*
* tps62360.c -- TI tps62360
*
- * Driver for processor core supply tps62360 and tps62361B
+ * Driver for processor core supply tps62360, tps62361B, tps62362 and tps62363.
*
* Copyright (c) 2012, NVIDIA Corporation.
*
@@ -26,13 +26,16 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/of_regulator.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/tps62360.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
-#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/regmap.h>
@@ -46,20 +49,20 @@
#define REG_RAMPCTRL 6
#define REG_CHIPID 8
-enum chips {TPS62360, TPS62361};
+#define FORCE_PWM_ENABLE BIT(7)
-#define TPS62360_BASE_VOLTAGE 770
+enum chips {TPS62360, TPS62361, TPS62362, TPS62363};
+
+#define TPS62360_BASE_VOLTAGE 770000
#define TPS62360_N_VOLTAGES 64
-#define TPS62361_BASE_VOLTAGE 500
+#define TPS62361_BASE_VOLTAGE 500000
#define TPS62361_N_VOLTAGES 128
/* tps 62360 chip information */
struct tps62360_chip {
- const char *name;
struct device *dev;
struct regulator_desc desc;
- struct i2c_client *client;
struct regulator_dev *rdev;
struct regmap *regmap;
int chip_id;
@@ -68,12 +71,12 @@ struct tps62360_chip {
int voltage_base;
u8 voltage_reg_mask;
bool en_internal_pulldn;
- bool en_force_pwm;
bool en_discharge;
bool valid_gpios;
int lru_index[4];
int curr_vset_vsel[4];
int curr_vset_id;
+ int change_uv_per_us;
};
/*
@@ -99,6 +102,7 @@ static bool find_voltage_set_register(struct tps62360_chip *tps,
bool found = false;
int new_vset_reg = tps->lru_index[3];
int found_index = 3;
+
for (i = 0; i < 4; ++i) {
if (tps->curr_vset_vsel[tps->lru_index[i]] == req_vsel) {
new_vset_reg = tps->lru_index[i];
@@ -117,7 +121,7 @@ update_lru_index:
return found;
}
-static int tps62360_dcdc_get_voltage(struct regulator_dev *dev)
+static int tps62360_dcdc_get_voltage_sel(struct regulator_dev *dev)
{
struct tps62360_chip *tps = rdev_get_drvdata(dev);
int vsel;
@@ -126,196 +130,312 @@ static int tps62360_dcdc_get_voltage(struct regulator_dev *dev)
ret = regmap_read(tps->regmap, REG_VSET0 + tps->curr_vset_id, &data);
if (ret < 0) {
- dev_err(tps->dev, "%s: Error in reading register %d\n",
- __func__, REG_VSET0 + tps->curr_vset_id);
+ dev_err(tps->dev, "%s(): register %d read failed with err %d\n",
+ __func__, REG_VSET0 + tps->curr_vset_id, ret);
return ret;
}
vsel = (int)data & tps->voltage_reg_mask;
- return (tps->voltage_base + vsel * 10) * 1000;
+ return vsel;
}
-static int tps62360_dcdc_set_voltage(struct regulator_dev *dev,
- int min_uV, int max_uV, unsigned *selector)
+static int tps62360_dcdc_set_voltage_sel(struct regulator_dev *dev,
+ unsigned selector)
{
struct tps62360_chip *tps = rdev_get_drvdata(dev);
- int vsel;
int ret;
bool found = false;
int new_vset_id = tps->curr_vset_id;
- if (max_uV < min_uV)
- return -EINVAL;
-
- if (min_uV >
- ((tps->voltage_base + (tps->desc.n_voltages - 1) * 10) * 1000))
- return -EINVAL;
-
- if (max_uV < tps->voltage_base * 1000)
- return -EINVAL;
-
- vsel = DIV_ROUND_UP(min_uV - (tps->voltage_base * 1000), 10000);
- if (selector)
- *selector = (vsel & tps->voltage_reg_mask);
-
/*
* If gpios are available to select the VSET register then least
* recently used register for new configuration.
*/
if (tps->valid_gpios)
- found = find_voltage_set_register(tps, vsel, &new_vset_id);
+ found = find_voltage_set_register(tps, selector, &new_vset_id);
if (!found) {
ret = regmap_update_bits(tps->regmap, REG_VSET0 + new_vset_id,
- tps->voltage_reg_mask, vsel);
+ tps->voltage_reg_mask, selector);
if (ret < 0) {
- dev_err(tps->dev, "%s: Error in updating register %d\n",
- __func__, REG_VSET0 + new_vset_id);
+ dev_err(tps->dev,
+ "%s(): register %d update failed with err %d\n",
+ __func__, REG_VSET0 + new_vset_id, ret);
return ret;
}
tps->curr_vset_id = new_vset_id;
- tps->curr_vset_vsel[new_vset_id] = vsel;
+ tps->curr_vset_vsel[new_vset_id] = selector;
}
/* Select proper VSET register vio gpios */
if (tps->valid_gpios) {
- gpio_set_value_cansleep(tps->vsel0_gpio,
- new_vset_id & 0x1);
+ gpio_set_value_cansleep(tps->vsel0_gpio, new_vset_id & 0x1);
gpio_set_value_cansleep(tps->vsel1_gpio,
(new_vset_id >> 1) & 0x1);
}
return 0;
}
-static int tps62360_dcdc_list_voltage(struct regulator_dev *dev,
- unsigned selector)
+static int tps62360_set_voltage_time_sel(struct regulator_dev *rdev,
+ unsigned int old_selector, unsigned int new_selector)
{
- struct tps62360_chip *tps = rdev_get_drvdata(dev);
+ struct tps62360_chip *tps = rdev_get_drvdata(rdev);
+ int old_uV, new_uV;
- if (selector >= tps->desc.n_voltages)
- return -EINVAL;
- return (tps->voltage_base + selector * 10) * 1000;
+ old_uV = regulator_list_voltage_linear(rdev, old_selector);
+ if (old_uV < 0)
+ return old_uV;
+
+ new_uV = regulator_list_voltage_linear(rdev, new_selector);
+ if (new_uV < 0)
+ return new_uV;
+
+ return DIV_ROUND_UP(abs(old_uV - new_uV), tps->change_uv_per_us);
}
-static struct regulator_ops tps62360_dcdc_ops = {
- .get_voltage = tps62360_dcdc_get_voltage,
- .set_voltage = tps62360_dcdc_set_voltage,
- .list_voltage = tps62360_dcdc_list_voltage,
-};
+static int tps62360_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ struct tps62360_chip *tps = rdev_get_drvdata(rdev);
+ int i;
+ int val;
+ int ret;
+
+ /* Enable force PWM mode in FAST mode only. */
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ val = FORCE_PWM_ENABLE;
+ break;
+
+ case REGULATOR_MODE_NORMAL:
+ val = 0;
+ break;
-static int tps62360_init_force_pwm(struct tps62360_chip *tps,
- struct tps62360_regulator_platform_data *pdata,
- int vset_id)
+ default:
+ return -EINVAL;
+ }
+
+ if (!tps->valid_gpios) {
+ ret = regmap_update_bits(tps->regmap,
+ REG_VSET0 + tps->curr_vset_id, FORCE_PWM_ENABLE, val);
+ if (ret < 0)
+ dev_err(tps->dev,
+ "%s(): register %d update failed with err %d\n",
+ __func__, REG_VSET0 + tps->curr_vset_id, ret);
+ return ret;
+ }
+
+ /* If gpios are valid then all register set need to be control */
+ for (i = 0; i < 4; ++i) {
+ ret = regmap_update_bits(tps->regmap,
+ REG_VSET0 + i, FORCE_PWM_ENABLE, val);
+ if (ret < 0) {
+ dev_err(tps->dev,
+ "%s(): register %d update failed with err %d\n",
+ __func__, REG_VSET0 + i, ret);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static unsigned int tps62360_get_mode(struct regulator_dev *rdev)
{
+ struct tps62360_chip *tps = rdev_get_drvdata(rdev);
unsigned int data;
int ret;
- ret = regmap_read(tps->regmap, REG_VSET0 + vset_id, &data);
+
+ ret = regmap_read(tps->regmap, REG_VSET0 + tps->curr_vset_id, &data);
if (ret < 0) {
- dev_err(tps->dev, "%s() fails in writing reg %d\n",
- __func__, REG_VSET0 + vset_id);
+ dev_err(tps->dev, "%s(): register %d read failed with err %d\n",
+ __func__, REG_VSET0 + tps->curr_vset_id, ret);
return ret;
}
- tps->curr_vset_vsel[vset_id] = data & tps->voltage_reg_mask;
- if (pdata->en_force_pwm)
- data |= BIT(7);
- else
- data &= ~BIT(7);
- ret = regmap_write(tps->regmap, REG_VSET0 + vset_id, data);
- if (ret < 0)
- dev_err(tps->dev, "%s() fails in writing reg %d\n",
- __func__, REG_VSET0 + vset_id);
- return ret;
+ return (data & FORCE_PWM_ENABLE) ?
+ REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
}
-static int tps62360_init_dcdc(struct tps62360_chip *tps,
+static struct regulator_ops tps62360_dcdc_ops = {
+ .get_voltage_sel = tps62360_dcdc_get_voltage_sel,
+ .set_voltage_sel = tps62360_dcdc_set_voltage_sel,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .set_voltage_time_sel = tps62360_set_voltage_time_sel,
+ .set_mode = tps62360_set_mode,
+ .get_mode = tps62360_get_mode,
+};
+
+static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
struct tps62360_regulator_platform_data *pdata)
{
int ret;
- int i;
+ unsigned int ramp_ctrl;
- /* Initailize internal pull up/down control */
+ /* Initialize internal pull up/down control */
if (tps->en_internal_pulldn)
ret = regmap_write(tps->regmap, REG_CONTROL, 0xE0);
else
ret = regmap_write(tps->regmap, REG_CONTROL, 0x0);
if (ret < 0) {
- dev_err(tps->dev, "%s() fails in writing reg %d\n",
- __func__, REG_CONTROL);
+ dev_err(tps->dev,
+ "%s(): register %d write failed with err %d\n",
+ __func__, REG_CONTROL, ret);
return ret;
}
- /* Initailize force PWM mode */
- if (tps->valid_gpios) {
- for (i = 0; i < 4; ++i) {
- ret = tps62360_init_force_pwm(tps, pdata, i);
- if (ret < 0)
- return ret;
- }
- } else {
- ret = tps62360_init_force_pwm(tps, pdata, tps->curr_vset_id);
- if (ret < 0)
- return ret;
- }
-
/* Reset output discharge path to reduce power consumption */
ret = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), 0);
- if (ret < 0)
- dev_err(tps->dev, "%s() fails in updating reg %d\n",
- __func__, REG_RAMPCTRL);
+ if (ret < 0) {
+ dev_err(tps->dev,
+ "%s(): register %d update failed with err %d\n",
+ __func__, REG_RAMPCTRL, ret);
+ return ret;
+ }
+
+ /* Get ramp value from ramp control register */
+ ret = regmap_read(tps->regmap, REG_RAMPCTRL, &ramp_ctrl);
+ if (ret < 0) {
+ dev_err(tps->dev,
+ "%s(): register %d read failed with err %d\n",
+ __func__, REG_RAMPCTRL, ret);
+ return ret;
+ }
+ ramp_ctrl = (ramp_ctrl >> 4) & 0x7;
+
+ /* ramp mV/us = 32/(2^ramp_ctrl) */
+ tps->change_uv_per_us = DIV_ROUND_UP(32000, BIT(ramp_ctrl));
return ret;
}
static const struct regmap_config tps62360_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = REG_CHIPID,
+ .cache_type = REGCACHE_RBTREE,
};
+static struct tps62360_regulator_platform_data *
+ of_get_tps62360_platform_data(struct device *dev)
+{
+ struct tps62360_regulator_platform_data *pdata;
+ struct device_node *np = dev->of_node;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(dev, "Memory alloc failed for platform data\n");
+ return NULL;
+ }
+
+ pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node);
+ if (!pdata->reg_init_data) {
+ dev_err(dev, "Not able to get OF regulator init data\n");
+ return NULL;
+ }
+
+ pdata->vsel0_gpio = of_get_named_gpio(np, "vsel0-gpio", 0);
+ pdata->vsel1_gpio = of_get_named_gpio(np, "vsel1-gpio", 0);
+
+ if (of_find_property(np, "ti,vsel0-state-high", NULL))
+ pdata->vsel0_def_state = 1;
+
+ if (of_find_property(np, "ti,vsel1-state-high", NULL))
+ pdata->vsel1_def_state = 1;
+
+ if (of_find_property(np, "ti,enable-pull-down", NULL))
+ pdata->en_internal_pulldn = true;
+
+ if (of_find_property(np, "ti,enable-vout-discharge", NULL))
+ pdata->en_discharge = true;
+
+ return pdata;
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id tps62360_of_match[] = {
+ { .compatible = "ti,tps62360", .data = (void *)TPS62360},
+ { .compatible = "ti,tps62361", .data = (void *)TPS62361},
+ { .compatible = "ti,tps62362", .data = (void *)TPS62362},
+ { .compatible = "ti,tps62363", .data = (void *)TPS62363},
+ {},
+};
+MODULE_DEVICE_TABLE(of, tps62360_of_match);
+#endif
+
static int __devinit tps62360_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct regulator_config config = { };
struct tps62360_regulator_platform_data *pdata;
struct regulator_dev *rdev;
struct tps62360_chip *tps;
int ret;
int i;
+ int chip_id;
pdata = client->dev.platform_data;
+ chip_id = id->driver_data;
+
+ if (client->dev.of_node) {
+ const struct of_device_id *match;
+ match = of_match_device(of_match_ptr(tps62360_of_match),
+ &client->dev);
+ if (!match) {
+ dev_err(&client->dev, "Error: No device match found\n");
+ return -ENODEV;
+ }
+ chip_id = (int)match->data;
+ if (!pdata)
+ pdata = of_get_tps62360_platform_data(&client->dev);
+ }
+
if (!pdata) {
- dev_err(&client->dev, "%s() Err: Platform data not found\n",
+ dev_err(&client->dev, "%s(): Platform data not found\n",
__func__);
return -EIO;
}
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
if (!tps) {
- dev_err(&client->dev, "%s() Err: Memory allocation fails\n",
+ dev_err(&client->dev, "%s(): Memory allocation failed\n",
__func__);
return -ENOMEM;
}
- tps->en_force_pwm = pdata->en_force_pwm;
tps->en_discharge = pdata->en_discharge;
tps->en_internal_pulldn = pdata->en_internal_pulldn;
tps->vsel0_gpio = pdata->vsel0_gpio;
tps->vsel1_gpio = pdata->vsel1_gpio;
- tps->client = client;
tps->dev = &client->dev;
- tps->name = id->name;
- tps->voltage_base = (id->driver_data == TPS62360) ?
- TPS62360_BASE_VOLTAGE : TPS62361_BASE_VOLTAGE;
- tps->voltage_reg_mask = (id->driver_data == TPS62360) ? 0x3F : 0x7F;
+
+ switch (chip_id) {
+ case TPS62360:
+ case TPS62362:
+ tps->voltage_base = TPS62360_BASE_VOLTAGE;
+ tps->voltage_reg_mask = 0x3F;
+ tps->desc.n_voltages = TPS62360_N_VOLTAGES;
+ break;
+ case TPS62361:
+ case TPS62363:
+ tps->voltage_base = TPS62361_BASE_VOLTAGE;
+ tps->voltage_reg_mask = 0x7F;
+ tps->desc.n_voltages = TPS62361_N_VOLTAGES;
+ break;
+ default:
+ return -ENODEV;
+ }
tps->desc.name = id->name;
tps->desc.id = 0;
- tps->desc.n_voltages = (id->driver_data == TPS62360) ?
- TPS62360_N_VOLTAGES : TPS62361_N_VOLTAGES;
tps->desc.ops = &tps62360_dcdc_ops;
tps->desc.type = REGULATOR_VOLTAGE;
tps->desc.owner = THIS_MODULE;
- tps->regmap = regmap_init_i2c(client, &tps62360_regmap_config);
+ tps->desc.min_uV = tps->voltage_base;
+ tps->desc.uV_step = 10000;
+
+ tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config);
if (IS_ERR(tps->regmap)) {
ret = PTR_ERR(tps->regmap);
- dev_err(&client->dev, "%s() Err: Failed to allocate register"
- "map: %d\n", __func__, ret);
+ dev_err(&client->dev,
+ "%s(): regmap allocation failed with err %d\n",
+ __func__, ret);
return ret;
}
i2c_set_clientdata(client, tps);
@@ -326,35 +446,26 @@ static int __devinit tps62360_probe(struct i2c_client *client,
tps->valid_gpios = false;
if (gpio_is_valid(tps->vsel0_gpio) && gpio_is_valid(tps->vsel1_gpio)) {
- ret = gpio_request(tps->vsel0_gpio, "tps62360-vsel0");
+ int gpio_flags;
+ gpio_flags = (pdata->vsel0_def_state) ?
+ GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+ ret = gpio_request_one(tps->vsel0_gpio,
+ gpio_flags, "tps62360-vsel0");
if (ret) {
dev_err(&client->dev,
- "Err: Could not obtain vsel0 GPIO %d: %d\n",
- tps->vsel0_gpio, ret);
- goto err_gpio0;
- }
- ret = gpio_direction_output(tps->vsel0_gpio,
- pdata->vsel0_def_state);
- if (ret) {
- dev_err(&client->dev, "Err: Could not set direction of"
- "vsel0 GPIO %d: %d\n", tps->vsel0_gpio, ret);
- gpio_free(tps->vsel0_gpio);
+ "%s(): Could not obtain vsel0 GPIO %d: %d\n",
+ __func__, tps->vsel0_gpio, ret);
goto err_gpio0;
}
- ret = gpio_request(tps->vsel1_gpio, "tps62360-vsel1");
+ gpio_flags = (pdata->vsel1_def_state) ?
+ GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+ ret = gpio_request_one(tps->vsel1_gpio,
+ gpio_flags, "tps62360-vsel1");
if (ret) {
dev_err(&client->dev,
- "Err: Could not obtain vsel1 GPIO %d: %d\n",
- tps->vsel1_gpio, ret);
- goto err_gpio1;
- }
- ret = gpio_direction_output(tps->vsel1_gpio,
- pdata->vsel1_def_state);
- if (ret) {
- dev_err(&client->dev, "Err: Could not set direction of"
- "vsel1 GPIO %d: %d\n", tps->vsel1_gpio, ret);
- gpio_free(tps->vsel1_gpio);
+ "%s(): Could not obtain vsel1 GPIO %d: %d\n",
+ __func__, tps->vsel1_gpio, ret);
goto err_gpio1;
}
tps->valid_gpios = true;
@@ -371,17 +482,22 @@ static int __devinit tps62360_probe(struct i2c_client *client,
ret = tps62360_init_dcdc(tps, pdata);
if (ret < 0) {
- dev_err(tps->dev, "%s() Err: Init fails with = %d\n",
+ dev_err(tps->dev, "%s(): Init failed with err = %d\n",
__func__, ret);
goto err_init;
}
+ config.dev = &client->dev;
+ config.init_data = pdata->reg_init_data;
+ config.driver_data = tps;
+ config.of_node = client->dev.of_node;
+
/* Register the regulators */
- rdev = regulator_register(&tps->desc, &client->dev,
- &pdata->reg_init_data, tps, NULL);
+ rdev = regulator_register(&tps->desc, &config);
if (IS_ERR(rdev)) {
- dev_err(tps->dev, "%s() Err: Failed to register %s\n",
- __func__, id->name);
+ dev_err(tps->dev,
+ "%s(): regulator register failed with err %s\n",
+ __func__, id->name);
ret = PTR_ERR(rdev);
goto err_init;
}
@@ -396,7 +512,6 @@ err_gpio1:
if (gpio_is_valid(tps->vsel0_gpio))
gpio_free(tps->vsel0_gpio);
err_gpio0:
- regmap_exit(tps->regmap);
return ret;
}
@@ -417,7 +532,6 @@ static int __devexit tps62360_remove(struct i2c_client *client)
gpio_free(tps->vsel0_gpio);
regulator_unregister(tps->rdev);
- regmap_exit(tps->regmap);
return 0;
}
@@ -432,13 +546,16 @@ static void tps62360_shutdown(struct i2c_client *client)
/* Configure the output discharge path */
st = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), BIT(2));
if (st < 0)
- dev_err(tps->dev, "%s() fails in updating reg %d\n",
- __func__, REG_RAMPCTRL);
+ dev_err(tps->dev,
+ "%s(): register %d update failed with err %d\n",
+ __func__, REG_RAMPCTRL, st);
}
static const struct i2c_device_id tps62360_id[] = {
{.name = "tps62360", .driver_data = TPS62360},
{.name = "tps62361", .driver_data = TPS62361},
+ {.name = "tps62362", .driver_data = TPS62362},
+ {.name = "tps62363", .driver_data = TPS62363},
{},
};
@@ -448,6 +565,7 @@ static struct i2c_driver tps62360_i2c_driver = {
.driver = {
.name = "tps62360",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tps62360_of_match),
},
.probe = tps62360_probe,
.remove = __devexit_p(tps62360_remove),
@@ -468,5 +586,5 @@ static void __exit tps62360_cleanup(void)
module_exit(tps62360_cleanup);
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
-MODULE_DESCRIPTION("TPS62360 voltage regulator driver");
+MODULE_DESCRIPTION("TPS6236x voltage regulator driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index 43e4902d7af8..f841bd0db6aa 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -23,7 +23,6 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/i2c.h>
-#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/regmap.h>
@@ -72,7 +71,7 @@
/* LDO_CTRL bitfields */
#define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id) ((ldo_id)*4)
-#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id) (0xF0 >> ((ldo_id)*4))
+#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id) (0x0F << ((ldo_id)*4))
/* Number of step-down converters available */
#define TPS65023_NUM_DCDC 3
@@ -139,7 +138,6 @@ struct tps_info {
/* PMIC details */
struct tps_pmic {
struct regulator_desc desc[TPS65023_NUM_REGULATOR];
- struct i2c_client *client;
struct regulator_dev *rdev[TPS65023_NUM_REGULATOR];
const struct tps_info *info[TPS65023_NUM_REGULATOR];
struct regmap *regmap;
@@ -152,96 +150,6 @@ struct tps_driver_data {
u8 core_regulator;
};
-static int tps65023_dcdc_is_enabled(struct regulator_dev *dev)
-{
- struct tps_pmic *tps = rdev_get_drvdata(dev);
- int data, dcdc = rdev_get_id(dev);
- int ret;
- u8 shift;
-
- if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
- return -EINVAL;
-
- shift = TPS65023_NUM_REGULATOR - dcdc;
- ret = regmap_read(tps->regmap, TPS65023_REG_REG_CTRL, &data);
-
- if (ret != 0)
- return ret;
- else
- return (data & 1<<shift) ? 1 : 0;
-}
-
-static int tps65023_ldo_is_enabled(struct regulator_dev *dev)
-{
- struct tps_pmic *tps = rdev_get_drvdata(dev);
- int data, ldo = rdev_get_id(dev);
- int ret;
- u8 shift;
-
- if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
- return -EINVAL;
-
- shift = (ldo == TPS65023_LDO_1 ? 1 : 2);
- ret = regmap_read(tps->regmap, TPS65023_REG_REG_CTRL, &data);
-
- if (ret != 0)
- return ret;
- else
- return (data & 1<<shift) ? 1 : 0;
-}
-
-static int tps65023_dcdc_enable(struct regulator_dev *dev)
-{
- struct tps_pmic *tps = rdev_get_drvdata(dev);
- int dcdc = rdev_get_id(dev);
- u8 shift;
-
- if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
- return -EINVAL;
-
- shift = TPS65023_NUM_REGULATOR - dcdc;
- return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 1 << shift);
-}
-
-static int tps65023_dcdc_disable(struct regulator_dev *dev)
-{
- struct tps_pmic *tps = rdev_get_drvdata(dev);
- int dcdc = rdev_get_id(dev);
- u8 shift;
-
- if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
- return -EINVAL;
-
- shift = TPS65023_NUM_REGULATOR - dcdc;
- return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 0);
-}
-
-static int tps65023_ldo_enable(struct regulator_dev *dev)
-{
- struct tps_pmic *tps = rdev_get_drvdata(dev);
- int ldo = rdev_get_id(dev);
- u8 shift;
-
- if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
- return -EINVAL;
-
- shift = (ldo == TPS65023_LDO_1 ? 1 : 2);
- return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 1 << shift);
-}
-
-static int tps65023_ldo_disable(struct regulator_dev *dev)
-{
- struct tps_pmic *tps = rdev_get_drvdata(dev);
- int ldo = rdev_get_id(dev);
- u8 shift;
-
- if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
- return -EINVAL;
-
- shift = (ldo == TPS65023_LDO_1 ? 1 : 2);
- return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 0);
-}
-
static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
{
struct tps_pmic *tps = rdev_get_drvdata(dev);
@@ -261,50 +169,28 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
return tps->info[dcdc]->min_uV;
}
-static int tps65023_dcdc_set_voltage(struct regulator_dev *dev,
- int min_uV, int max_uV,
- unsigned *selector)
+static int tps65023_dcdc_set_voltage_sel(struct regulator_dev *dev,
+ unsigned selector)
{
struct tps_pmic *tps = rdev_get_drvdata(dev);
int dcdc = rdev_get_id(dev);
- int vsel;
int ret;
if (dcdc != tps->core_regulator)
return -EINVAL;
- if (min_uV < tps->info[dcdc]->min_uV
- || min_uV > tps->info[dcdc]->max_uV)
- return -EINVAL;
- if (max_uV < tps->info[dcdc]->min_uV
- || max_uV > tps->info[dcdc]->max_uV)
- return -EINVAL;
-
- for (vsel = 0; vsel < tps->info[dcdc]->table_len; vsel++) {
- int mV = tps->info[dcdc]->table[vsel];
- int uV = mV * 1000;
-
- /* Break at the first in-range value */
- if (min_uV <= uV && uV <= max_uV)
- break;
- }
- *selector = vsel;
-
- if (vsel == tps->info[dcdc]->table_len)
- goto failed;
-
- ret = regmap_write(tps->regmap, TPS65023_REG_DEF_CORE, vsel);
+ ret = regmap_write(tps->regmap, TPS65023_REG_DEF_CORE, selector);
+ if (ret)
+ goto out;
/* Tell the chip that we have changed the value in DEFCORE
* and its time to update the core voltage
*/
- regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2,
- TPS65023_REG_CTRL2_GO, TPS65023_REG_CTRL2_GO);
+ ret = regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2,
+ TPS65023_REG_CTRL2_GO, TPS65023_REG_CTRL2_GO);
+out:
return ret;
-
-failed:
- return -EINVAL;
}
static int tps65023_ldo_get_voltage(struct regulator_dev *dev)
@@ -325,42 +211,15 @@ static int tps65023_ldo_get_voltage(struct regulator_dev *dev)
return tps->info[ldo]->table[data] * 1000;
}
-static int tps65023_ldo_set_voltage(struct regulator_dev *dev,
- int min_uV, int max_uV, unsigned *selector)
+static int tps65023_ldo_set_voltage_sel(struct regulator_dev *dev,
+ unsigned selector)
{
struct tps_pmic *tps = rdev_get_drvdata(dev);
- int data, vsel, ldo = rdev_get_id(dev);
- int ret;
-
- if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
- return -EINVAL;
+ int ldo_index = rdev_get_id(dev) - TPS65023_LDO_1;
- if (min_uV < tps->info[ldo]->min_uV || min_uV > tps->info[ldo]->max_uV)
- return -EINVAL;
- if (max_uV < tps->info[ldo]->min_uV || max_uV > tps->info[ldo]->max_uV)
- return -EINVAL;
-
- for (vsel = 0; vsel < tps->info[ldo]->table_len; vsel++) {
- int mV = tps->info[ldo]->table[vsel];
- int uV = mV * 1000;
-
- /* Break at the first in-range value */
- if (min_uV <= uV && uV <= max_uV)
- break;
- }
-
- if (vsel == tps->info[ldo]->table_len)
- return -EINVAL;
-
- *selector = vsel;
-
- ret = regmap_read(tps->regmap, TPS65023_REG_LDO_CTRL, &data);
- if (ret != 0)
- return ret;
-
- data &= TPS65023_LDO_CTRL_LDOx_MASK(ldo - TPS65023_LDO_1);
- data |= (vsel << (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1)));
- return regmap_write(tps->regmap, TPS65023_REG_LDO_CTRL, data);
+ return regmap_update_bits(tps->regmap, TPS65023_REG_LDO_CTRL,
+ TPS65023_LDO_CTRL_LDOx_MASK(ldo_index),
+ selector << TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_index));
}
static int tps65023_dcdc_list_voltage(struct regulator_dev *dev,
@@ -398,21 +257,21 @@ static int tps65023_ldo_list_voltage(struct regulator_dev *dev,
/* Operations permitted on VDCDCx */
static struct regulator_ops tps65023_dcdc_ops = {
- .is_enabled = tps65023_dcdc_is_enabled,
- .enable = tps65023_dcdc_enable,
- .disable = tps65023_dcdc_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
.get_voltage = tps65023_dcdc_get_voltage,
- .set_voltage = tps65023_dcdc_set_voltage,
+ .set_voltage_sel = tps65023_dcdc_set_voltage_sel,
.list_voltage = tps65023_dcdc_list_voltage,
};
/* Operations permitted on LDOx */
static struct regulator_ops tps65023_ldo_ops = {
- .is_enabled = tps65023_ldo_is_enabled,
- .enable = tps65023_ldo_enable,
- .disable = tps65023_ldo_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
.get_voltage = tps65023_ldo_get_voltage,
- .set_voltage = tps65023_ldo_set_voltage,
+ .set_voltage_sel = tps65023_ldo_set_voltage_sel,
.list_voltage = tps65023_ldo_list_voltage,
};
@@ -426,6 +285,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
{
const struct tps_driver_data *drv_data = (void *)id->driver_data;
const struct tps_info *info = drv_data->info;
+ struct regulator_config config = { };
struct regulator_init_data *init_data;
struct regulator_dev *rdev;
struct tps_pmic *tps;
@@ -443,20 +303,19 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
if (!init_data)
return -EIO;
- tps = kzalloc(sizeof(*tps), GFP_KERNEL);
+ tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
if (!tps)
return -ENOMEM;
- tps->regmap = regmap_init_i2c(client, &tps65023_regmap_config);
+ tps->regmap = devm_regmap_init_i2c(client, &tps65023_regmap_config);
if (IS_ERR(tps->regmap)) {
error = PTR_ERR(tps->regmap);
dev_err(&client->dev, "Failed to allocate register map: %d\n",
error);
- goto fail_alloc;
+ return error;
}
/* common for all regulators */
- tps->client = client;
tps->core_regulator = drv_data->core_regulator;
for (i = 0; i < TPS65023_NUM_REGULATOR; i++, info++, init_data++) {
@@ -471,9 +330,22 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
tps->desc[i].type = REGULATOR_VOLTAGE;
tps->desc[i].owner = THIS_MODULE;
+ tps->desc[i].enable_reg = TPS65023_REG_REG_CTRL;
+ if (i == TPS65023_LDO_1)
+ tps->desc[i].enable_mask = 1 << 1;
+ else if (i == TPS65023_LDO_2)
+ tps->desc[i].enable_mask = 1 << 2;
+ else /* DCDCx */
+ tps->desc[i].enable_mask =
+ 1 << (TPS65023_NUM_REGULATOR - i);
+
+ config.dev = &client->dev;
+ config.init_data = init_data;
+ config.driver_data = tps;
+ config.regmap = tps->regmap;
+
/* Register the regulators */
- rdev = regulator_register(&tps->desc[i], &client->dev,
- init_data, tps, NULL);
+ rdev = regulator_register(&tps->desc[i], &config);
if (IS_ERR(rdev)) {
dev_err(&client->dev, "failed to register %s\n",
id->name);
@@ -496,19 +368,9 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
fail:
while (--i >= 0)
regulator_unregister(tps->rdev[i]);
-
- regmap_exit(tps->regmap);
- fail_alloc:
- kfree(tps);
return error;
}
-/**
- * tps_65023_remove - TPS65023 driver i2c remove handler
- * @client: i2c driver client device structure
- *
- * Unregister TPS driver as an i2c client device driver
- */
static int __devexit tps_65023_remove(struct i2c_client *client)
{
struct tps_pmic *tps = i2c_get_clientdata(client);
@@ -516,10 +378,6 @@ static int __devexit tps_65023_remove(struct i2c_client *client)
for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
regulator_unregister(tps->rdev[i]);
-
- regmap_exit(tps->regmap);
- kfree(tps);
-
return 0;
}
@@ -638,13 +496,13 @@ static struct tps_driver_data tps65020_drv_data = {
};
static struct tps_driver_data tps65021_drv_data = {
- .info = tps65021_regs,
- .core_regulator = TPS65023_DCDC_3,
+ .info = tps65021_regs,
+ .core_regulator = TPS65023_DCDC_3,
};
static struct tps_driver_data tps65023_drv_data = {
- .info = tps65023_regs,
- .core_regulator = TPS65023_DCDC_1,
+ .info = tps65023_regs,
+ .core_regulator = TPS65023_DCDC_1,
};
static const struct i2c_device_id tps_65023_id[] = {
@@ -669,22 +527,12 @@ static struct i2c_driver tps_65023_i2c_driver = {
.id_table = tps_65023_id,
};
-/**
- * tps_65023_init
- *
- * Module init function
- */
static int __init tps_65023_init(void)
{
return i2c_add_driver(&tps_65023_i2c_driver);
}
subsys_initcall(tps_65023_init);
-/**
- * tps_65023_cleanup
- *
- * Module exit function
- */
static void __exit tps_65023_cleanup(void)
{
i2c_del_driver(&tps_65023_i2c_driver);
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index 832833fe8aad..da38be1016aa 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -23,7 +23,6 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/tps6507x.h>
-#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/mfd/tps6507x.h>
@@ -283,7 +282,7 @@ static int tps6507x_pmic_disable(struct regulator_dev *dev)
1 << shift);
}
-static int tps6507x_pmic_get_voltage(struct regulator_dev *dev)
+static int tps6507x_pmic_get_voltage_sel(struct regulator_dev *dev)
{
struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
int data, rid = rdev_get_id(dev);
@@ -325,7 +324,7 @@ static int tps6507x_pmic_get_voltage(struct regulator_dev *dev)
return data;
data &= mask;
- return tps->info[rid]->table[data] * 1000;
+ return data;
}
static int tps6507x_pmic_set_voltage_sel(struct regulator_dev *dev,
@@ -395,7 +394,7 @@ static struct regulator_ops tps6507x_pmic_ops = {
.is_enabled = tps6507x_pmic_is_enabled,
.enable = tps6507x_pmic_enable,
.disable = tps6507x_pmic_disable,
- .get_voltage = tps6507x_pmic_get_voltage,
+ .get_voltage_sel = tps6507x_pmic_get_voltage_sel,
.set_voltage_sel = tps6507x_pmic_set_voltage_sel,
.list_voltage = tps6507x_pmic_list_voltage,
};
@@ -404,6 +403,7 @@ static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
{
struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
struct tps_info *info = &tps6507x_pmic_regs[0];
+ struct regulator_config config = { };
struct regulator_init_data *init_data;
struct regulator_dev *rdev;
struct tps6507x_pmic *tps;
@@ -428,7 +428,7 @@ static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
if (!init_data)
return -EINVAL;
- tps = kzalloc(sizeof(*tps), GFP_KERNEL);
+ tps = devm_kzalloc(&pdev->dev, sizeof(*tps), GFP_KERNEL);
if (!tps)
return -ENOMEM;
@@ -453,8 +453,11 @@ static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
tps->desc[i].type = REGULATOR_VOLTAGE;
tps->desc[i].owner = THIS_MODULE;
- rdev = regulator_register(&tps->desc[i],
- tps6507x_dev->dev, init_data, tps, NULL);
+ config.dev = tps6507x_dev->dev;
+ config.init_data = init_data;
+ config.driver_data = tps;
+
+ rdev = regulator_register(&tps->desc[i], &config);
if (IS_ERR(rdev)) {
dev_err(tps6507x_dev->dev,
"failed to register %s regulator\n",
@@ -475,8 +478,6 @@ static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
fail:
while (--i >= 0)
regulator_unregister(tps->rdev[i]);
-
- kfree(tps);
return error;
}
@@ -488,9 +489,6 @@ static int __devexit tps6507x_pmic_remove(struct platform_device *pdev)
for (i = 0; i < TPS6507X_NUM_REGULATOR; i++)
regulator_unregister(tps->rdev[i]);
-
- kfree(tps);
-
return 0;
}
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
new file mode 100644
index 000000000000..001ad554ac62
--- /dev/null
+++ b/drivers/regulator/tps65090-regulator.c
@@ -0,0 +1,150 @@
+/*
+ * Regulator driver for tps65090 power management chip.
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/tps65090.h>
+#include <linux/regulator/tps65090-regulator.h>
+
+struct tps65090_regulator {
+ int id;
+ /* used by regulator core */
+ struct regulator_desc desc;
+
+ /* Device */
+ struct device *dev;
+};
+
+static struct regulator_ops tps65090_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+#define tps65090_REG(_id) \
+{ \
+ .id = TPS65090_ID_##_id, \
+ .desc = { \
+ .name = tps65090_rails(_id), \
+ .id = TPS65090_ID_##_id, \
+ .ops = &tps65090_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .enable_reg = (TPS65090_ID_##_id) + 12, \
+ .enable_mask = BIT(0), \
+ }, \
+}
+
+static struct tps65090_regulator TPS65090_regulator[] = {
+ tps65090_REG(DCDC1),
+ tps65090_REG(DCDC2),
+ tps65090_REG(DCDC3),
+ tps65090_REG(FET1),
+ tps65090_REG(FET2),
+ tps65090_REG(FET3),
+ tps65090_REG(FET4),
+ tps65090_REG(FET5),
+ tps65090_REG(FET6),
+ tps65090_REG(FET7),
+};
+
+static inline struct tps65090_regulator *find_regulator_info(int id)
+{
+ struct tps65090_regulator *ri;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(TPS65090_regulator); i++) {
+ ri = &TPS65090_regulator[i];
+ if (ri->desc.id == id)
+ return ri;
+ }
+ return NULL;
+}
+
+static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
+{
+ struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent);
+ struct tps65090_regulator *ri = NULL;
+ struct regulator_config config = { };
+ struct regulator_dev *rdev;
+ struct tps65090_regulator_platform_data *tps_pdata;
+ int id = pdev->id;
+
+ dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
+
+ ri = find_regulator_info(id);
+ if (ri == NULL) {
+ dev_err(&pdev->dev, "invalid regulator ID specified\n");
+ return -EINVAL;
+ }
+ tps_pdata = pdev->dev.platform_data;
+ ri->dev = &pdev->dev;
+
+ config.dev = &pdev->dev;
+ config.init_data = &tps_pdata->regulator;
+ config.driver_data = ri;
+ config.regmap = tps65090_mfd->rmap;
+
+ rdev = regulator_register(&ri->desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register regulator %s\n",
+ ri->desc.name);
+ return PTR_ERR(rdev);
+ }
+
+ platform_set_drvdata(pdev, rdev);
+ return 0;
+}
+
+static int __devexit tps65090_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+ regulator_unregister(rdev);
+ return 0;
+}
+
+static struct platform_driver tps65090_regulator_driver = {
+ .driver = {
+ .name = "tps65090-regulator",
+ .owner = THIS_MODULE,
+ },
+ .probe = tps65090_regulator_probe,
+ .remove = __devexit_p(tps65090_regulator_remove),
+};
+
+static int __init tps65090_regulator_init(void)
+{
+ return platform_driver_register(&tps65090_regulator_driver);
+}
+subsys_initcall(tps65090_regulator_init);
+
+static void __exit tps65090_regulator_exit(void)
+{
+ platform_driver_unregister(&tps65090_regulator_driver);
+}
+module_exit(tps65090_regulator_exit);
+
+MODULE_DESCRIPTION("tps65090 regulator driver");
+MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
index e39521b42772..9d371d2cbcae 100644
--- a/drivers/regulator/tps65217-regulator.c
+++ b/drivers/regulator/tps65217-regulator.c
@@ -213,65 +213,56 @@ static int tps65217_pmic_get_voltage_sel(struct regulator_dev *dev)
return selector;
}
-static int tps65217_pmic_ldo1_set_voltage_sel(struct regulator_dev *dev,
- unsigned selector)
+static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev,
+ unsigned selector)
{
+ int ret;
struct tps65217 *tps = rdev_get_drvdata(dev);
- int ldo = rdev_get_id(dev);
+ unsigned int rid = rdev_get_id(dev);
- if (ldo != TPS65217_LDO_1)
- return -EINVAL;
+ /* Set the voltage based on vsel value and write protect level is 2 */
+ ret = tps65217_set_bits(tps, tps->info[rid]->set_vout_reg,
+ tps->info[rid]->set_vout_mask,
+ selector, TPS65217_PROTECT_L2);
- if (selector >= tps->info[ldo]->table_len)
- return -EINVAL;
+ /* Set GO bit for DCDCx to initiate voltage transistion */
+ switch (rid) {
+ case TPS65217_DCDC_1 ... TPS65217_DCDC_3:
+ ret = tps65217_set_bits(tps, TPS65217_REG_DEFSLEW,
+ TPS65217_DEFSLEW_GO, TPS65217_DEFSLEW_GO,
+ TPS65217_PROTECT_L2);
+ break;
+ }
- /* Set the voltage based on vsel value and write protect level is 2 */
- return tps65217_set_bits(tps, tps->info[ldo]->set_vout_reg,
- tps->info[ldo]->set_vout_mask,
- selector, TPS65217_PROTECT_L2);
+ return ret;
}
-static int tps65217_pmic_set_voltage(struct regulator_dev *dev,
- int min_uV, int max_uV, unsigned *selector)
+static int tps65217_pmic_map_voltage(struct regulator_dev *dev,
+ int min_uV, int max_uV)
{
- int ret;
+
struct tps65217 *tps = rdev_get_drvdata(dev);
- unsigned int rid = rdev_get_id(dev);
+ unsigned int sel, rid = rdev_get_id(dev);
+ int ret;
- /* LDO1 implements set_voltage_sel callback */
+ /* LDO1 uses regulator_map_voltage_iterate() */
if (rid == TPS65217_LDO_1)
return -EINVAL;
if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
return -EINVAL;
- if (min_uV < tps->info[rid]->min_uV
- || min_uV > tps->info[rid]->max_uV)
+ if (min_uV < tps->info[rid]->min_uV || min_uV > tps->info[rid]->max_uV)
return -EINVAL;
- if (max_uV < tps->info[rid]->min_uV
- || max_uV > tps->info[rid]->max_uV)
+ if (max_uV < tps->info[rid]->min_uV || max_uV > tps->info[rid]->max_uV)
return -EINVAL;
- ret = tps->info[rid]->uv_to_vsel(min_uV, selector);
+ ret = tps->info[rid]->uv_to_vsel(min_uV, &sel);
if (ret)
return ret;
- /* Set the voltage based on vsel value and write protect level is 2 */
- ret = tps65217_set_bits(tps, tps->info[rid]->set_vout_reg,
- tps->info[rid]->set_vout_mask,
- *selector, TPS65217_PROTECT_L2);
-
- /* Set GO bit for DCDCx to initiate voltage transistion */
- switch (rid) {
- case TPS65217_DCDC_1 ... TPS65217_DCDC_3:
- ret = tps65217_set_bits(tps, TPS65217_REG_DEFSLEW,
- TPS65217_DEFSLEW_GO, TPS65217_DEFSLEW_GO,
- TPS65217_PROTECT_L2);
- break;
- }
-
- return ret;
+ return sel;
}
static int tps65217_pmic_list_voltage(struct regulator_dev *dev,
@@ -298,8 +289,9 @@ static struct regulator_ops tps65217_pmic_ops = {
.enable = tps65217_pmic_enable,
.disable = tps65217_pmic_disable,
.get_voltage_sel = tps65217_pmic_get_voltage_sel,
- .set_voltage = tps65217_pmic_set_voltage,
+ .set_voltage_sel = tps65217_pmic_set_voltage_sel,
.list_voltage = tps65217_pmic_list_voltage,
+ .map_voltage = tps65217_pmic_map_voltage,
};
/* Operations permitted on LDO1 */
@@ -308,11 +300,11 @@ static struct regulator_ops tps65217_pmic_ldo1_ops = {
.enable = tps65217_pmic_enable,
.disable = tps65217_pmic_disable,
.get_voltage_sel = tps65217_pmic_get_voltage_sel,
- .set_voltage_sel = tps65217_pmic_ldo1_set_voltage_sel,
+ .set_voltage_sel = tps65217_pmic_set_voltage_sel,
.list_voltage = tps65217_pmic_list_voltage,
};
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc regulators[] = {
TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, tps65217_pmic_ops, 64),
TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, tps65217_pmic_ops, 64),
TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, tps65217_pmic_ops, 64),
@@ -327,13 +319,17 @@ static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
struct regulator_dev *rdev;
struct tps65217 *tps;
struct tps_info *info = &tps65217_pmic_regs[pdev->id];
+ struct regulator_config config = { };
/* Already set by core driver */
tps = dev_to_tps65217(pdev->dev.parent);
tps->info[pdev->id] = info;
- rdev = regulator_register(&regulators[pdev->id], &pdev->dev,
- pdev->dev.platform_data, tps, NULL);
+ config.dev = &pdev->dev;
+ config.init_data = pdev->dev.platform_data;
+ config.driver_data = tps;
+
+ rdev = regulator_register(&regulators[pdev->id], &config);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c
index 4a421be6d4f2..b88b3df82381 100644
--- a/drivers/regulator/tps6524x-regulator.c
+++ b/drivers/regulator/tps6524x-regulator.c
@@ -458,12 +458,10 @@ static int list_voltage(struct regulator_dev *rdev, unsigned selector)
info->voltages[selector] : -EINVAL);
}
-static int set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
- unsigned *selector)
+static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
{
const struct supply_info *info;
struct tps6524x *hw;
- unsigned i;
hw = rdev_get_drvdata(rdev);
info = &supply_info[rdev_get_id(rdev)];
@@ -471,20 +469,10 @@ static int set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
if (info->flags & FIXED_VOLTAGE)
return -EINVAL;
- for (i = 0; i < info->n_voltages; i++)
- if (min_uV <= info->voltages[i] &&
- max_uV >= info->voltages[i])
- break;
-
- if (i >= info->n_voltages)
- i = info->n_voltages - 1;
-
- *selector = i;
-
- return write_field(hw, &info->voltage, i);
+ return write_field(hw, &info->voltage, selector);
}
-static int get_voltage(struct regulator_dev *rdev)
+static int get_voltage_sel(struct regulator_dev *rdev)
{
const struct supply_info *info;
struct tps6524x *hw;
@@ -502,7 +490,7 @@ static int get_voltage(struct regulator_dev *rdev)
if (WARN_ON(ret >= info->n_voltages))
return -EIO;
- return info->voltages[ret];
+ return ret;
}
static int set_current_limit(struct regulator_dev *rdev, int min_uA,
@@ -587,8 +575,8 @@ static struct regulator_ops regulator_ops = {
.is_enabled = is_supply_enabled,
.enable = enable_supply,
.disable = disable_supply,
- .get_voltage = get_voltage,
- .set_voltage = set_voltage,
+ .get_voltage_sel = get_voltage_sel,
+ .set_voltage_sel = set_voltage_sel,
.list_voltage = list_voltage,
.set_current_limit = set_current_limit,
.get_current_limit = get_current_limit,
@@ -607,7 +595,6 @@ static int pmic_remove(struct spi_device *spi)
hw->rdev[i] = NULL;
}
spi_set_drvdata(spi, NULL);
- kfree(hw);
return 0;
}
@@ -617,6 +604,7 @@ static int __devinit pmic_probe(struct spi_device *spi)
struct device *dev = &spi->dev;
const struct supply_info *info = supply_info;
struct regulator_init_data *init_data;
+ struct regulator_config config = { };
int ret = 0, i;
init_data = dev->platform_data;
@@ -625,7 +613,7 @@ static int __devinit pmic_probe(struct spi_device *spi)
return -EINVAL;
}
- hw = kzalloc(sizeof(struct tps6524x), GFP_KERNEL);
+ hw = devm_kzalloc(&spi->dev, sizeof(struct tps6524x), GFP_KERNEL);
if (!hw) {
dev_err(dev, "cannot allocate regulator private data\n");
return -ENOMEM;
@@ -648,8 +636,11 @@ static int __devinit pmic_probe(struct spi_device *spi)
if (info->flags & FIXED_VOLTAGE)
hw->desc[i].n_voltages = 1;
- hw->rdev[i] = regulator_register(&hw->desc[i], dev,
- init_data, hw, NULL);
+ config.dev = dev;
+ config.init_data = init_data;
+ config.driver_data = hw;
+
+ hw->rdev[i] = regulator_register(&hw->desc[i], &config);
if (IS_ERR(hw->rdev[i])) {
ret = PTR_ERR(hw->rdev[i]);
hw->rdev[i] = NULL;
@@ -673,17 +664,7 @@ static struct spi_driver pmic_driver = {
},
};
-static int __init pmic_driver_init(void)
-{
- return spi_register_driver(&pmic_driver);
-}
-module_init(pmic_driver_init);
-
-static void __exit pmic_driver_exit(void)
-{
- spi_unregister_driver(&pmic_driver);
-}
-module_exit(pmic_driver_exit);
+module_spi_driver(pmic_driver);
MODULE_DESCRIPTION("TPS6524X PMIC Driver");
MODULE_AUTHOR("Cyril Chemparathy");
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index cfc1f16f7771..c0a214575380 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -75,8 +75,7 @@ static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev)
return rdev_get_dev(rdev)->parent->parent;
}
-static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev,
- unsigned selector)
+static int tps6586x_list_voltage(struct regulator_dev *rdev, unsigned selector)
{
struct tps6586x_regulator *info = rdev_get_drvdata(rdev);
int rid = rdev_get_id(rdev);
@@ -89,47 +88,34 @@ static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev,
}
-static int __tps6586x_ldo_set_voltage(struct device *parent,
- struct tps6586x_regulator *ri,
- int min_uV, int max_uV,
- unsigned *selector)
+static int tps6586x_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned selector)
{
- int val, uV;
+ struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
+ struct device *parent = to_tps6586x_dev(rdev);
+ int ret, val, rid = rdev_get_id(rdev);
uint8_t mask;
- for (val = 0; val < ri->desc.n_voltages; val++) {
- uV = ri->voltages[val] * 1000;
-
- /* LDO0 has minimal voltage 1.2 rather than 1.25 */
- if (ri->desc.id == TPS6586X_ID_LDO_0 && val == 0)
- uV -= 50 * 1000;
-
- /* use the first in-range value */
- if (min_uV <= uV && uV <= max_uV) {
-
- *selector = val;
+ val = selector << ri->volt_shift;
+ mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift;
- val <<= ri->volt_shift;
- mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift;
+ ret = tps6586x_update(parent, ri->volt_reg, val, mask);
+ if (ret)
+ return ret;
- return tps6586x_update(parent, ri->volt_reg, val, mask);
- }
+ /* Update go bit for DVM regulators */
+ switch (rid) {
+ case TPS6586X_ID_LDO_2:
+ case TPS6586X_ID_LDO_4:
+ case TPS6586X_ID_SM_0:
+ case TPS6586X_ID_SM_1:
+ ret = tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit);
+ break;
}
-
- return -EINVAL;
-}
-
-static int tps6586x_ldo_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *selector)
-{
- struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
- struct device *parent = to_tps6586x_dev(rdev);
-
- return __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV,
- selector);
+ return ret;
}
-static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev)
+static int tps6586x_get_voltage_sel(struct regulator_dev *rdev)
{
struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps6586x_dev(rdev);
@@ -146,22 +132,7 @@ static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev)
if (val >= ri->desc.n_voltages)
BUG();
- return ri->voltages[val] * 1000;
-}
-
-static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *selector)
-{
- struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
- struct device *parent = to_tps6586x_dev(rdev);
- int ret;
-
- ret = __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV,
- selector);
- if (ret)
- return ret;
-
- return tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit);
+ return val;
}
static int tps6586x_regulator_enable(struct regulator_dev *rdev)
@@ -196,20 +167,10 @@ static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev)
return !!(reg_val & (1 << ri->enable_bit[0]));
}
-static struct regulator_ops tps6586x_regulator_ldo_ops = {
- .list_voltage = tps6586x_ldo_list_voltage,
- .get_voltage = tps6586x_ldo_get_voltage,
- .set_voltage = tps6586x_ldo_set_voltage,
-
- .is_enabled = tps6586x_regulator_is_enabled,
- .enable = tps6586x_regulator_enable,
- .disable = tps6586x_regulator_disable,
-};
-
-static struct regulator_ops tps6586x_regulator_dvm_ops = {
- .list_voltage = tps6586x_ldo_list_voltage,
- .get_voltage = tps6586x_ldo_get_voltage,
- .set_voltage = tps6586x_dvm_set_voltage,
+static struct regulator_ops tps6586x_regulator_ops = {
+ .list_voltage = tps6586x_list_voltage,
+ .get_voltage_sel = tps6586x_get_voltage_sel,
+ .set_voltage_sel = tps6586x_set_voltage_sel,
.is_enabled = tps6586x_regulator_is_enabled,
.enable = tps6586x_regulator_enable,
@@ -241,11 +202,11 @@ static int tps6586x_dvm_voltages[] = {
1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500,
};
-#define TPS6586X_REGULATOR(_id, vdata, _ops, vreg, shift, nbits, \
+#define TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1) \
.desc = { \
.name = "REG-" #_id, \
- .ops = &tps6586x_regulator_##_ops, \
+ .ops = &tps6586x_regulator_ops, \
.type = REGULATOR_VOLTAGE, \
.id = TPS6586X_ID_##_id, \
.n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages), \
@@ -267,14 +228,14 @@ static int tps6586x_dvm_voltages[] = {
#define TPS6586X_LDO(_id, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1) \
{ \
- TPS6586X_REGULATOR(_id, vdata, ldo_ops, vreg, shift, nbits, \
+ TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits, \
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, \
+ TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1) \
TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \
}
@@ -384,6 +345,7 @@ static inline struct tps6586x_regulator *find_regulator_info(int id)
static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
{
struct tps6586x_regulator *ri = NULL;
+ struct regulator_config config = { };
struct regulator_dev *rdev;
int id = pdev->id;
int err;
@@ -400,8 +362,12 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
if (err)
return err;
- rdev = regulator_register(&ri->desc, &pdev->dev,
- pdev->dev.platform_data, ri, NULL);
+ config.dev = &pdev->dev;
+ config.of_node = pdev->dev.of_node;
+ config.init_data = pdev->dev.platform_data;
+ config.driver_data = ri;
+
+ rdev = regulator_register(&ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
ri->desc.name);
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
index 4a37c2b6367f..4e01a423471b 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -20,10 +20,10 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
-#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/mfd/tps65910.h>
+#include <linux/regulator/of_regulator.h>
#define TPS65910_SUPPLY_STATE_ENABLED 0x1
#define EXT_SLEEP_CONTROL (TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1 | \
@@ -31,54 +31,54 @@
TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3 | \
TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP)
-/* supported VIO voltages in milivolts */
+/* supported VIO voltages in millivolts */
static const u16 VIO_VSEL_table[] = {
1500, 1800, 2500, 3300,
};
/* VSEL tables for TPS65910 specific LDOs and dcdc's */
-/* supported VDD3 voltages in milivolts */
+/* supported VDD3 voltages in millivolts */
static const u16 VDD3_VSEL_table[] = {
5000,
};
-/* supported VDIG1 voltages in milivolts */
+/* supported VDIG1 voltages in millivolts */
static const u16 VDIG1_VSEL_table[] = {
1200, 1500, 1800, 2700,
};
-/* supported VDIG2 voltages in milivolts */
+/* supported VDIG2 voltages in millivolts */
static const u16 VDIG2_VSEL_table[] = {
1000, 1100, 1200, 1800,
};
-/* supported VPLL voltages in milivolts */
+/* supported VPLL voltages in millivolts */
static const u16 VPLL_VSEL_table[] = {
1000, 1100, 1800, 2500,
};
-/* supported VDAC voltages in milivolts */
+/* supported VDAC voltages in millivolts */
static const u16 VDAC_VSEL_table[] = {
1800, 2600, 2800, 2850,
};
-/* supported VAUX1 voltages in milivolts */
+/* supported VAUX1 voltages in millivolts */
static const u16 VAUX1_VSEL_table[] = {
1800, 2500, 2800, 2850,
};
-/* supported VAUX2 voltages in milivolts */
+/* supported VAUX2 voltages in millivolts */
static const u16 VAUX2_VSEL_table[] = {
1800, 2800, 2900, 3300,
};
-/* supported VAUX33 voltages in milivolts */
+/* supported VAUX33 voltages in millivolts */
static const u16 VAUX33_VSEL_table[] = {
1800, 2000, 2800, 3300,
};
-/* supported VMMC voltages in milivolts */
+/* supported VMMC voltages in millivolts */
static const u16 VMMC_VSEL_table[] = {
1800, 2800, 3000, 3300,
};
@@ -94,11 +94,11 @@ struct tps_info {
static struct tps_info tps65910_regs[] = {
{
- .name = "VRTC",
+ .name = "vrtc",
.enable_time_us = 2200,
},
{
- .name = "VIO",
+ .name = "vio",
.min_uV = 1500000,
.max_uV = 3300000,
.n_voltages = ARRAY_SIZE(VIO_VSEL_table),
@@ -106,19 +106,19 @@ static struct tps_info tps65910_regs[] = {
.enable_time_us = 350,
},
{
- .name = "VDD1",
+ .name = "vdd1",
.min_uV = 600000,
.max_uV = 4500000,
.enable_time_us = 350,
},
{
- .name = "VDD2",
+ .name = "vdd2",
.min_uV = 600000,
.max_uV = 4500000,
.enable_time_us = 350,
},
{
- .name = "VDD3",
+ .name = "vdd3",
.min_uV = 5000000,
.max_uV = 5000000,
.n_voltages = ARRAY_SIZE(VDD3_VSEL_table),
@@ -126,7 +126,7 @@ static struct tps_info tps65910_regs[] = {
.enable_time_us = 200,
},
{
- .name = "VDIG1",
+ .name = "vdig1",
.min_uV = 1200000,
.max_uV = 2700000,
.n_voltages = ARRAY_SIZE(VDIG1_VSEL_table),
@@ -134,7 +134,7 @@ static struct tps_info tps65910_regs[] = {
.enable_time_us = 100,
},
{
- .name = "VDIG2",
+ .name = "vdig2",
.min_uV = 1000000,
.max_uV = 1800000,
.n_voltages = ARRAY_SIZE(VDIG2_VSEL_table),
@@ -142,7 +142,7 @@ static struct tps_info tps65910_regs[] = {
.enable_time_us = 100,
},
{
- .name = "VPLL",
+ .name = "vpll",
.min_uV = 1000000,
.max_uV = 2500000,
.n_voltages = ARRAY_SIZE(VPLL_VSEL_table),
@@ -150,7 +150,7 @@ static struct tps_info tps65910_regs[] = {
.enable_time_us = 100,
},
{
- .name = "VDAC",
+ .name = "vdac",
.min_uV = 1800000,
.max_uV = 2850000,
.n_voltages = ARRAY_SIZE(VDAC_VSEL_table),
@@ -158,7 +158,7 @@ static struct tps_info tps65910_regs[] = {
.enable_time_us = 100,
},
{
- .name = "VAUX1",
+ .name = "vaux1",
.min_uV = 1800000,
.max_uV = 2850000,
.n_voltages = ARRAY_SIZE(VAUX1_VSEL_table),
@@ -166,7 +166,7 @@ static struct tps_info tps65910_regs[] = {
.enable_time_us = 100,
},
{
- .name = "VAUX2",
+ .name = "vaux2",
.min_uV = 1800000,
.max_uV = 3300000,
.n_voltages = ARRAY_SIZE(VAUX2_VSEL_table),
@@ -174,7 +174,7 @@ static struct tps_info tps65910_regs[] = {
.enable_time_us = 100,
},
{
- .name = "VAUX33",
+ .name = "vaux33",
.min_uV = 1800000,
.max_uV = 3300000,
.n_voltages = ARRAY_SIZE(VAUX33_VSEL_table),
@@ -182,7 +182,7 @@ static struct tps_info tps65910_regs[] = {
.enable_time_us = 100,
},
{
- .name = "VMMC",
+ .name = "vmmc",
.min_uV = 1800000,
.max_uV = 3300000,
.n_voltages = ARRAY_SIZE(VMMC_VSEL_table),
@@ -193,11 +193,11 @@ static struct tps_info tps65910_regs[] = {
static struct tps_info tps65911_regs[] = {
{
- .name = "VRTC",
+ .name = "vrtc",
.enable_time_us = 2200,
},
{
- .name = "VIO",
+ .name = "vio",
.min_uV = 1500000,
.max_uV = 3300000,
.n_voltages = ARRAY_SIZE(VIO_VSEL_table),
@@ -205,77 +205,77 @@ static struct tps_info tps65911_regs[] = {
.enable_time_us = 350,
},
{
- .name = "VDD1",
+ .name = "vdd1",
.min_uV = 600000,
.max_uV = 4500000,
.n_voltages = 73,
.enable_time_us = 350,
},
{
- .name = "VDD2",
+ .name = "vdd2",
.min_uV = 600000,
.max_uV = 4500000,
.n_voltages = 73,
.enable_time_us = 350,
},
{
- .name = "VDDCTRL",
+ .name = "vddctrl",
.min_uV = 600000,
.max_uV = 1400000,
.n_voltages = 65,
.enable_time_us = 900,
},
{
- .name = "LDO1",
+ .name = "ldo1",
.min_uV = 1000000,
.max_uV = 3300000,
.n_voltages = 47,
.enable_time_us = 420,
},
{
- .name = "LDO2",
+ .name = "ldo2",
.min_uV = 1000000,
.max_uV = 3300000,
.n_voltages = 47,
.enable_time_us = 420,
},
{
- .name = "LDO3",
+ .name = "ldo3",
.min_uV = 1000000,
.max_uV = 3300000,
.n_voltages = 24,
.enable_time_us = 230,
},
{
- .name = "LDO4",
+ .name = "ldo4",
.min_uV = 1000000,
.max_uV = 3300000,
.n_voltages = 47,
.enable_time_us = 230,
},
{
- .name = "LDO5",
+ .name = "ldo5",
.min_uV = 1000000,
.max_uV = 3300000,
.n_voltages = 24,
.enable_time_us = 230,
},
{
- .name = "LDO6",
+ .name = "ldo6",
.min_uV = 1000000,
.max_uV = 3300000,
.n_voltages = 24,
.enable_time_us = 230,
},
{
- .name = "LDO7",
+ .name = "ldo7",
.min_uV = 1000000,
.max_uV = 3300000,
.n_voltages = 24,
.enable_time_us = 230,
},
{
- .name = "LDO8",
+ .name = "ldo8",
.min_uV = 1000000,
.max_uV = 3300000,
.n_voltages = 24,
@@ -467,48 +467,6 @@ static int tps65911_get_ctrl_register(int id)
}
}
-static int tps65910_is_enabled(struct regulator_dev *dev)
-{
- struct tps65910_reg *pmic = rdev_get_drvdata(dev);
- int reg, value, id = rdev_get_id(dev);
-
- reg = pmic->get_ctrl_reg(id);
- if (reg < 0)
- return reg;
-
- value = tps65910_reg_read(pmic, reg);
- if (value < 0)
- return value;
-
- return value & TPS65910_SUPPLY_STATE_ENABLED;
-}
-
-static int tps65910_enable(struct regulator_dev *dev)
-{
- struct tps65910_reg *pmic = rdev_get_drvdata(dev);
- struct tps65910 *mfd = pmic->mfd;
- int reg, id = rdev_get_id(dev);
-
- reg = pmic->get_ctrl_reg(id);
- if (reg < 0)
- return reg;
-
- return tps65910_set_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED);
-}
-
-static int tps65910_disable(struct regulator_dev *dev)
-{
- struct tps65910_reg *pmic = rdev_get_drvdata(dev);
- struct tps65910 *mfd = pmic->mfd;
- int reg, id = rdev_get_id(dev);
-
- reg = pmic->get_ctrl_reg(id);
- if (reg < 0)
- return reg;
-
- return tps65910_clear_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED);
-}
-
static int tps65910_enable_time(struct regulator_dev *dev)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
@@ -621,10 +579,10 @@ static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev)
return -EINVAL;
}
-static int tps65910_get_voltage(struct regulator_dev *dev)
+static int tps65910_get_voltage_sel(struct regulator_dev *dev)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
- int reg, value, id = rdev_get_id(dev), voltage = 0;
+ int reg, value, id = rdev_get_id(dev);
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
@@ -651,9 +609,7 @@ static int tps65910_get_voltage(struct regulator_dev *dev)
return -EINVAL;
}
- voltage = pmic->info[id]->voltage_table[value] * 1000;
-
- return voltage;
+ return value;
}
static int tps65910_get_voltage_vdd3(struct regulator_dev *dev)
@@ -661,10 +617,10 @@ static int tps65910_get_voltage_vdd3(struct regulator_dev *dev)
return 5 * 1000 * 1000;
}
-static int tps65911_get_voltage(struct regulator_dev *dev)
+static int tps65911_get_voltage_sel(struct regulator_dev *dev)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
- int step_mv, id = rdev_get_id(dev);
+ int id = rdev_get_id(dev);
u8 value, reg;
reg = pmic->get_ctrl_reg(id);
@@ -677,13 +633,6 @@ static int tps65911_get_voltage(struct regulator_dev *dev)
case TPS65911_REG_LDO4:
value &= LDO1_SEL_MASK;
value >>= LDO_SEL_SHIFT;
- /* The first 5 values of the selector correspond to 1V */
- if (value < 5)
- value = 0;
- else
- value -= 4;
-
- step_mv = 50;
break;
case TPS65911_REG_LDO3:
case TPS65911_REG_LDO5:
@@ -692,23 +641,16 @@ static int tps65911_get_voltage(struct regulator_dev *dev)
case TPS65911_REG_LDO8:
value &= LDO3_SEL_MASK;
value >>= LDO_SEL_SHIFT;
- /* The first 3 values of the selector correspond to 1V */
- if (value < 3)
- value = 0;
- else
- value -= 2;
-
- step_mv = 100;
break;
case TPS65910_REG_VIO:
value &= LDO_SEL_MASK;
value >>= LDO_SEL_SHIFT;
- return pmic->info[id]->voltage_table[value] * 1000;
+ break;
default:
return -EINVAL;
}
- return (LDO_MIN_VOLT + value * step_mv) * 1000;
+ return value;
}
static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev,
@@ -914,9 +856,9 @@ static int tps65910_set_voltage_dcdc_time_sel(struct regulator_dev *dev,
/* Regulator ops (except VRTC) */
static struct regulator_ops tps65910_ops_dcdc = {
- .is_enabled = tps65910_is_enabled,
- .enable = tps65910_enable,
- .disable = tps65910_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
.enable_time = tps65910_enable_time,
.set_mode = tps65910_set_mode,
.get_mode = tps65910_get_mode,
@@ -927,9 +869,9 @@ static struct regulator_ops tps65910_ops_dcdc = {
};
static struct regulator_ops tps65910_ops_vdd3 = {
- .is_enabled = tps65910_is_enabled,
- .enable = tps65910_enable,
- .disable = tps65910_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
.enable_time = tps65910_enable_time,
.set_mode = tps65910_set_mode,
.get_mode = tps65910_get_mode,
@@ -938,25 +880,25 @@ static struct regulator_ops tps65910_ops_vdd3 = {
};
static struct regulator_ops tps65910_ops = {
- .is_enabled = tps65910_is_enabled,
- .enable = tps65910_enable,
- .disable = tps65910_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
.enable_time = tps65910_enable_time,
.set_mode = tps65910_set_mode,
.get_mode = tps65910_get_mode,
- .get_voltage = tps65910_get_voltage,
+ .get_voltage_sel = tps65910_get_voltage_sel,
.set_voltage_sel = tps65910_set_voltage_sel,
.list_voltage = tps65910_list_voltage,
};
static struct regulator_ops tps65911_ops = {
- .is_enabled = tps65910_is_enabled,
- .enable = tps65910_enable,
- .disable = tps65910_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
.enable_time = tps65910_enable_time,
.set_mode = tps65910_set_mode,
.get_mode = tps65910_get_mode,
- .get_voltage = tps65911_get_voltage,
+ .get_voltage_sel = tps65911_get_voltage_sel,
.set_voltage_sel = tps65911_set_voltage_sel,
.list_voltage = tps65911_list_voltage,
};
@@ -1094,23 +1036,141 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic,
return ret;
}
+#ifdef CONFIG_OF
+
+static struct of_regulator_match tps65910_matches[] = {
+ { .name = "vrtc", .driver_data = (void *) &tps65910_regs[0] },
+ { .name = "vio", .driver_data = (void *) &tps65910_regs[1] },
+ { .name = "vdd1", .driver_data = (void *) &tps65910_regs[2] },
+ { .name = "vdd2", .driver_data = (void *) &tps65910_regs[3] },
+ { .name = "vdd3", .driver_data = (void *) &tps65910_regs[4] },
+ { .name = "vdig1", .driver_data = (void *) &tps65910_regs[5] },
+ { .name = "vdig2", .driver_data = (void *) &tps65910_regs[6] },
+ { .name = "vpll", .driver_data = (void *) &tps65910_regs[7] },
+ { .name = "vdac", .driver_data = (void *) &tps65910_regs[8] },
+ { .name = "vaux1", .driver_data = (void *) &tps65910_regs[9] },
+ { .name = "vaux2", .driver_data = (void *) &tps65910_regs[10] },
+ { .name = "vaux33", .driver_data = (void *) &tps65910_regs[11] },
+ { .name = "vmmc", .driver_data = (void *) &tps65910_regs[12] },
+};
+
+static struct of_regulator_match tps65911_matches[] = {
+ { .name = "vrtc", .driver_data = (void *) &tps65911_regs[0] },
+ { .name = "vio", .driver_data = (void *) &tps65911_regs[1] },
+ { .name = "vdd1", .driver_data = (void *) &tps65911_regs[2] },
+ { .name = "vdd2", .driver_data = (void *) &tps65911_regs[3] },
+ { .name = "vddctrl", .driver_data = (void *) &tps65911_regs[4] },
+ { .name = "ldo1", .driver_data = (void *) &tps65911_regs[5] },
+ { .name = "ldo2", .driver_data = (void *) &tps65911_regs[6] },
+ { .name = "ldo3", .driver_data = (void *) &tps65911_regs[7] },
+ { .name = "ldo4", .driver_data = (void *) &tps65911_regs[8] },
+ { .name = "ldo5", .driver_data = (void *) &tps65911_regs[9] },
+ { .name = "ldo6", .driver_data = (void *) &tps65911_regs[10] },
+ { .name = "ldo7", .driver_data = (void *) &tps65911_regs[11] },
+ { .name = "ldo8", .driver_data = (void *) &tps65911_regs[12] },
+};
+
+static struct tps65910_board *tps65910_parse_dt_reg_data(
+ struct platform_device *pdev,
+ struct of_regulator_match **tps65910_reg_matches)
+{
+ struct tps65910_board *pmic_plat_data;
+ struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
+ struct device_node *np = pdev->dev.parent->of_node;
+ struct device_node *regulators;
+ struct of_regulator_match *matches;
+ unsigned int prop;
+ int idx = 0, ret, count;
+
+ pmic_plat_data = devm_kzalloc(&pdev->dev, sizeof(*pmic_plat_data),
+ GFP_KERNEL);
+
+ if (!pmic_plat_data) {
+ dev_err(&pdev->dev, "Failure to alloc pdata for regulators.\n");
+ return NULL;
+ }
+
+ regulators = of_find_node_by_name(np, "regulators");
+ if (!regulators) {
+ dev_err(&pdev->dev, "regulator node not found\n");
+ return NULL;
+ }
+
+ switch (tps65910_chip_id(tps65910)) {
+ case TPS65910:
+ count = ARRAY_SIZE(tps65910_matches);
+ matches = tps65910_matches;
+ break;
+ case TPS65911:
+ count = ARRAY_SIZE(tps65911_matches);
+ matches = tps65911_matches;
+ break;
+ default:
+ dev_err(&pdev->dev, "Invalid tps chip version\n");
+ return NULL;
+ }
+
+ ret = of_regulator_match(pdev->dev.parent, regulators, matches, count);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
+ ret);
+ return NULL;
+ }
+
+ *tps65910_reg_matches = matches;
+
+ for (idx = 0; idx < count; idx++) {
+ if (!matches[idx].init_data || !matches[idx].of_node)
+ continue;
+
+ pmic_plat_data->tps65910_pmic_init_data[idx] =
+ matches[idx].init_data;
+
+ ret = of_property_read_u32(matches[idx].of_node,
+ "ti,regulator-ext-sleep-control", &prop);
+ if (!ret)
+ pmic_plat_data->regulator_ext_sleep_control[idx] = prop;
+ }
+
+ return pmic_plat_data;
+}
+#else
+static inline struct tps65910_board *tps65910_parse_dt_reg_data(
+ struct platform_device *pdev,
+ struct of_regulator_match **tps65910_reg_matches)
+{
+ *tps65910_reg_matches = NULL;
+ return 0;
+}
+#endif
+
static __devinit int tps65910_probe(struct platform_device *pdev)
{
struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
+ struct regulator_config config = { };
struct tps_info *info;
struct regulator_init_data *reg_data;
struct regulator_dev *rdev;
struct tps65910_reg *pmic;
struct tps65910_board *pmic_plat_data;
+ struct of_regulator_match *tps65910_reg_matches = NULL;
int i, err;
pmic_plat_data = dev_get_platdata(tps65910->dev);
- if (!pmic_plat_data)
+ if (!pmic_plat_data && tps65910->dev->of_node)
+ pmic_plat_data = tps65910_parse_dt_reg_data(pdev,
+ &tps65910_reg_matches);
+
+ if (!pmic_plat_data) {
+ dev_err(&pdev->dev, "Platform data not found\n");
return -EINVAL;
+ }
- pmic = kzalloc(sizeof(*pmic), GFP_KERNEL);
- if (!pmic)
+ pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
+ if (!pmic) {
+ dev_err(&pdev->dev, "Memory allocation failed for pmic\n");
return -ENOMEM;
+ }
mutex_init(&pmic->mutex);
pmic->mfd = tps65910;
@@ -1134,30 +1194,29 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
info = tps65911_regs;
break;
default:
- pr_err("Invalid tps chip version\n");
- kfree(pmic);
+ dev_err(&pdev->dev, "Invalid tps chip version\n");
return -ENODEV;
}
- pmic->desc = kcalloc(pmic->num_regulators,
+ pmic->desc = devm_kzalloc(&pdev->dev, pmic->num_regulators *
sizeof(struct regulator_desc), GFP_KERNEL);
if (!pmic->desc) {
- err = -ENOMEM;
- goto err_free_pmic;
+ dev_err(&pdev->dev, "Memory alloc fails for desc\n");
+ return -ENOMEM;
}
- pmic->info = kcalloc(pmic->num_regulators,
+ pmic->info = devm_kzalloc(&pdev->dev, pmic->num_regulators *
sizeof(struct tps_info *), GFP_KERNEL);
if (!pmic->info) {
- err = -ENOMEM;
- goto err_free_desc;
+ dev_err(&pdev->dev, "Memory alloc fails for info\n");
+ return -ENOMEM;
}
- pmic->rdev = kcalloc(pmic->num_regulators,
+ pmic->rdev = devm_kzalloc(&pdev->dev, pmic->num_regulators *
sizeof(struct regulator_dev *), GFP_KERNEL);
if (!pmic->rdev) {
- err = -ENOMEM;
- goto err_free_info;
+ dev_err(&pdev->dev, "Memory alloc fails for rdev\n");
+ return -ENOMEM;
}
for (i = 0; i < pmic->num_regulators && i < TPS65910_NUM_REGS;
@@ -1205,9 +1264,18 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
pmic->desc[i].type = REGULATOR_VOLTAGE;
pmic->desc[i].owner = THIS_MODULE;
+ pmic->desc[i].enable_reg = pmic->get_ctrl_reg(i);
+ pmic->desc[i].enable_mask = TPS65910_SUPPLY_STATE_ENABLED;
+
+ config.dev = tps65910->dev;
+ config.init_data = reg_data;
+ config.driver_data = pmic;
+ config.regmap = tps65910->regmap;
+
+ if (tps65910_reg_matches)
+ config.of_node = tps65910_reg_matches[i].of_node;
- rdev = regulator_register(&pmic->desc[i],
- tps65910->dev, reg_data, pmic, NULL);
+ rdev = regulator_register(&pmic->desc[i], &config);
if (IS_ERR(rdev)) {
dev_err(tps65910->dev,
"failed to register %s regulator\n",
@@ -1224,13 +1292,6 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
err_unregister_regulator:
while (--i >= 0)
regulator_unregister(pmic->rdev[i]);
- kfree(pmic->rdev);
-err_free_info:
- kfree(pmic->info);
-err_free_desc:
- kfree(pmic->desc);
-err_free_pmic:
- kfree(pmic);
return err;
}
@@ -1242,10 +1303,6 @@ static int __devexit tps65910_remove(struct platform_device *pdev)
for (i = 0; i < pmic->num_regulators; i++)
regulator_unregister(pmic->rdev[i]);
- kfree(pmic->rdev);
- kfree(pmic->info);
- kfree(pmic->desc);
- kfree(pmic);
return 0;
}
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
index b36799b1f530..18b2a1dcb4b5 100644
--- a/drivers/regulator/tps65912-regulator.c
+++ b/drivers/regulator/tps65912-regulator.c
@@ -20,7 +20,6 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
-#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/mfd/tps65912.h>
@@ -372,12 +371,14 @@ static unsigned int tps65912_get_mode(struct regulator_dev *dev)
return mode;
}
-static int tps65912_list_voltage_dcdc(struct regulator_dev *dev,
- unsigned selector)
+static int tps65912_list_voltage(struct regulator_dev *dev, unsigned selector)
{
struct tps65912_reg *pmic = rdev_get_drvdata(dev);
int range, voltage = 0, id = rdev_get_id(dev);
+ if (id >= TPS65912_REG_LDO1 && id <= TPS65912_REG_LDO10)
+ return tps65912_vsel_to_uv_ldo(selector);
+
if (id > TPS65912_REG_DCDC4)
return -EINVAL;
@@ -404,7 +405,7 @@ static int tps65912_list_voltage_dcdc(struct regulator_dev *dev,
return voltage;
}
-static int tps65912_get_voltage_dcdc(struct regulator_dev *dev)
+static int tps65912_get_voltage_sel(struct regulator_dev *dev)
{
struct tps65912_reg *pmic = rdev_get_drvdata(dev);
struct tps65912 *mfd = pmic->mfd;
@@ -418,7 +419,7 @@ static int tps65912_get_voltage_dcdc(struct regulator_dev *dev)
vsel = tps65912_reg_read(mfd, reg);
vsel &= 0x3F;
- return tps65912_list_voltage_dcdc(dev, vsel);
+ return vsel;
}
static int tps65912_set_voltage_sel(struct regulator_dev *dev,
@@ -436,32 +437,6 @@ static int tps65912_set_voltage_sel(struct regulator_dev *dev,
return tps65912_reg_write(mfd, reg, selector | value);
}
-static int tps65912_get_voltage_ldo(struct regulator_dev *dev)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int id = rdev_get_id(dev);
- int vsel = 0;
- u8 reg;
-
- reg = tps65912_get_sel_register(pmic, id);
- vsel = tps65912_reg_read(mfd, reg);
- vsel &= 0x3F;
-
- return tps65912_vsel_to_uv_ldo(vsel);
-}
-
-static int tps65912_list_voltage_ldo(struct regulator_dev *dev,
- unsigned selector)
-{
- int ldo = rdev_get_id(dev);
-
- if (ldo < TPS65912_REG_LDO1 || ldo > TPS65912_REG_LDO10)
- return -EINVAL;
-
- return tps65912_vsel_to_uv_ldo(selector);
-}
-
/* Operations permitted on DCDCx */
static struct regulator_ops tps65912_ops_dcdc = {
.is_enabled = tps65912_reg_is_enabled,
@@ -469,9 +444,9 @@ static struct regulator_ops tps65912_ops_dcdc = {
.disable = tps65912_reg_disable,
.set_mode = tps65912_set_mode,
.get_mode = tps65912_get_mode,
- .get_voltage = tps65912_get_voltage_dcdc,
+ .get_voltage_sel = tps65912_get_voltage_sel,
.set_voltage_sel = tps65912_set_voltage_sel,
- .list_voltage = tps65912_list_voltage_dcdc,
+ .list_voltage = tps65912_list_voltage,
};
/* Operations permitted on LDOx */
@@ -479,14 +454,15 @@ static struct regulator_ops tps65912_ops_ldo = {
.is_enabled = tps65912_reg_is_enabled,
.enable = tps65912_reg_enable,
.disable = tps65912_reg_disable,
- .get_voltage = tps65912_get_voltage_ldo,
+ .get_voltage_sel = tps65912_get_voltage_sel,
.set_voltage_sel = tps65912_set_voltage_sel,
- .list_voltage = tps65912_list_voltage_ldo,
+ .list_voltage = tps65912_list_voltage,
};
static __devinit int tps65912_probe(struct platform_device *pdev)
{
struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
+ struct regulator_config config = { };
struct tps_info *info;
struct regulator_init_data *reg_data;
struct regulator_dev *rdev;
@@ -500,7 +476,7 @@ static __devinit int tps65912_probe(struct platform_device *pdev)
reg_data = pmic_plat_data->tps65912_pmic_init_data;
- pmic = kzalloc(sizeof(*pmic), GFP_KERNEL);
+ pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
if (!pmic)
return -ENOMEM;
@@ -524,8 +500,12 @@ static __devinit int tps65912_probe(struct platform_device *pdev)
pmic->desc[i].type = REGULATOR_VOLTAGE;
pmic->desc[i].owner = THIS_MODULE;
range = tps65912_get_range(pmic, i);
- rdev = regulator_register(&pmic->desc[i],
- tps65912->dev, reg_data, pmic, NULL);
+
+ config.dev = tps65912->dev;
+ config.init_data = reg_data;
+ config.driver_data = pmic;
+
+ rdev = regulator_register(&pmic->desc[i], &config);
if (IS_ERR(rdev)) {
dev_err(tps65912->dev,
"failed to register %s regulator\n",
@@ -542,8 +522,6 @@ static __devinit int tps65912_probe(struct platform_device *pdev)
err:
while (--i >= 0)
regulator_unregister(pmic->rdev[i]);
-
- kfree(pmic);
return err;
}
@@ -554,8 +532,6 @@ static int __devexit tps65912_remove(struct platform_device *pdev)
for (i = 0; i < TPS65912_NUM_REGULATOR; i++)
regulator_unregister(tps65912_reg->rdev[i]);
-
- kfree(tps65912_reg);
return 0;
}
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 9cdfc389ca26..c7390711d954 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -12,7 +12,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
-#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -175,15 +174,14 @@ static int twl6030reg_is_enabled(struct regulator_dev *rdev)
struct twlreg_info *info = rdev_get_drvdata(rdev);
int grp = 0, val;
- if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
- grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
- if (grp < 0)
- return grp;
-
- if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
+ if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) {
+ grp = twlreg_grp(rdev);
+ if (grp < 0)
+ return grp;
grp &= P1_GRP_6030;
- else
+ } else {
grp = 1;
+ }
val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
val = TWL6030_CFG_STATE_APP(val);
@@ -197,7 +195,7 @@ static int twl4030reg_enable(struct regulator_dev *rdev)
int grp;
int ret;
- grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
+ grp = twlreg_grp(rdev);
if (grp < 0)
return grp;
@@ -205,8 +203,6 @@ static int twl4030reg_enable(struct regulator_dev *rdev)
ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
- udelay(info->delay);
-
return ret;
}
@@ -217,17 +213,28 @@ static int twl6030reg_enable(struct regulator_dev *rdev)
int ret;
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
- grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
+ grp = twlreg_grp(rdev);
if (grp < 0)
return grp;
ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE,
grp << TWL6030_CFG_STATE_GRP_SHIFT |
TWL6030_CFG_STATE_ON);
+ return ret;
+}
- udelay(info->delay);
+static int twl4030reg_enable_time(struct regulator_dev *rdev)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
- return ret;
+ return info->delay;
+}
+
+static int twl6030reg_enable_time(struct regulator_dev *rdev)
+{
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
+
+ return info->delay;
}
static int twl4030reg_disable(struct regulator_dev *rdev)
@@ -236,7 +243,7 @@ static int twl4030reg_disable(struct regulator_dev *rdev)
int grp;
int ret;
- grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
+ grp = twlreg_grp(rdev);
if (grp < 0)
return grp;
@@ -348,7 +355,7 @@ static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
int val;
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
- grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
+ grp = twlreg_grp(rdev);
if (grp < 0)
return grp;
@@ -388,14 +395,12 @@ static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
* VAUX3 at 3V is incorrectly listed in some TI manuals as unsupported.
* TI are revising the twl5030/tps659x0 specs to support that 3.0V setting.
*/
-#ifdef CONFIG_TWL4030_ALLOW_UNSUPPORTED
-#define UNSUP_MASK 0x0000
-#else
#define UNSUP_MASK 0x8000
-#endif
#define UNSUP(x) (UNSUP_MASK | (x))
-#define IS_UNSUP(x) (UNSUP_MASK & (x))
+#define IS_UNSUP(info, x) \
+ ((UNSUP_MASK & (x)) && \
+ !((info)->features & TWL4030_ALLOW_UNSUPPORTED))
#define LDO_MV(x) (~UNSUP_MASK & (x))
@@ -469,35 +474,16 @@ static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
struct twlreg_info *info = rdev_get_drvdata(rdev);
int mV = info->table[index];
- return IS_UNSUP(mV) ? 0 : (LDO_MV(mV) * 1000);
+ return IS_UNSUP(info, mV) ? 0 : (LDO_MV(mV) * 1000);
}
static int
-twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
- unsigned *selector)
+twl4030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
- int vsel;
- for (vsel = 0; vsel < info->table_len; vsel++) {
- int mV = info->table[vsel];
- int uV;
-
- if (IS_UNSUP(mV))
- continue;
- uV = LDO_MV(mV) * 1000;
-
- /* REVISIT for VAUX2, first match may not be best/lowest */
-
- /* use the first in-range value */
- if (min_uV <= uV && uV <= max_uV) {
- *selector = vsel;
- return twlreg_write(info, TWL_MODULE_PM_RECEIVER,
- VREG_VOLTAGE, vsel);
- }
- }
-
- return -EDOM;
+ return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE,
+ selector);
}
static int twl4030ldo_get_voltage(struct regulator_dev *rdev)
@@ -516,12 +502,13 @@ static int twl4030ldo_get_voltage(struct regulator_dev *rdev)
static struct regulator_ops twl4030ldo_ops = {
.list_voltage = twl4030ldo_list_voltage,
- .set_voltage = twl4030ldo_set_voltage,
+ .set_voltage_sel = twl4030ldo_set_voltage_sel,
.get_voltage = twl4030ldo_get_voltage,
.enable = twl4030reg_enable,
.disable = twl4030reg_disable,
.is_enabled = twl4030reg_is_enabled,
+ .enable_time = twl4030reg_enable_time,
.set_mode = twl4030reg_set_mode,
@@ -642,6 +629,7 @@ static struct regulator_ops twl6030ldo_ops = {
.enable = twl6030reg_enable,
.disable = twl6030reg_disable,
.is_enabled = twl6030reg_is_enabled,
+ .enable_time = twl6030reg_enable_time,
.set_mode = twl6030reg_set_mode,
@@ -675,6 +663,7 @@ static struct regulator_ops twl4030fixed_ops = {
.enable = twl4030reg_enable,
.disable = twl4030reg_disable,
.is_enabled = twl4030reg_is_enabled,
+ .enable_time = twl4030reg_enable_time,
.set_mode = twl4030reg_set_mode,
@@ -689,6 +678,7 @@ static struct regulator_ops twl6030fixed_ops = {
.enable = twl6030reg_enable,
.disable = twl6030reg_disable,
.is_enabled = twl6030reg_is_enabled,
+ .enable_time = twl6030reg_enable_time,
.set_mode = twl6030reg_set_mode,
@@ -699,6 +689,7 @@ static struct regulator_ops twl6030_fixed_resource = {
.enable = twl6030reg_enable,
.disable = twl6030reg_disable,
.is_enabled = twl6030reg_is_enabled,
+ .enable_time = twl6030reg_enable_time,
.get_status = twl6030reg_get_status,
};
@@ -806,10 +797,7 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
vsel = 0;
else if ((min_uV >= 600000) && (min_uV <= 1300000)) {
int calc_uV;
- vsel = (min_uV - 600000) / 125;
- if (vsel % 100)
- vsel += 100;
- vsel /= 100;
+ vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
vsel++;
calc_uV = twl6030smps_list_voltage(rdev, vsel);
if (calc_uV > max_uV)
@@ -836,10 +824,7 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
vsel = 0;
else if ((min_uV >= 700000) && (min_uV <= 1420000)) {
int calc_uV;
- vsel = (min_uV - 700000) / 125;
- if (vsel % 100)
- vsel += 100;
- vsel /= 100;
+ vsel = DIV_ROUND_UP(min_uV - 700000, 12500);
vsel++;
calc_uV = twl6030smps_list_voltage(rdev, vsel);
if (calc_uV > max_uV)
@@ -862,24 +847,18 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
return -EINVAL;
break;
case SMPS_EXTENDED_EN:
- if (min_uV == 0)
+ if (min_uV == 0) {
vsel = 0;
- else if ((min_uV >= 1852000) && (max_uV <= 4013600)) {
- vsel = (min_uV - 1852000) / 386;
- if (vsel % 100)
- vsel += 100;
- vsel /= 100;
+ } else if ((min_uV >= 1852000) && (max_uV <= 4013600)) {
+ vsel = DIV_ROUND_UP(min_uV - 1852000, 38600);
vsel++;
}
break;
case SMPS_OFFSET_EN|SMPS_EXTENDED_EN:
- if (min_uV == 0)
+ if (min_uV == 0) {
vsel = 0;
- else if ((min_uV >= 2161000) && (max_uV <= 4321000)) {
- vsel = (min_uV - 2161000) / 386;
- if (vsel % 100)
- vsel += 100;
- vsel /= 100;
+ } else if ((min_uV >= 2161000) && (max_uV <= 4321000)) {
+ vsel = DIV_ROUND_UP(min_uV - 2161000, 38600);
vsel++;
}
break;
@@ -907,6 +886,7 @@ static struct regulator_ops twlsmps_ops = {
.enable = twl6030reg_enable,
.disable = twl6030reg_disable,
.is_enabled = twl6030reg_is_enabled,
+ .enable_time = twl6030reg_enable_time,
.set_mode = twl6030reg_set_mode,
@@ -1194,6 +1174,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
struct regulator_dev *rdev;
struct twl_regulator_driver_data *drvdata;
const struct of_device_id *match;
+ struct regulator_config config = { };
match = of_match_device(twl_of_match, &pdev->dev);
if (match) {
@@ -1207,10 +1188,12 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
initdata = pdev->dev.platform_data;
for (i = 0, info = NULL; i < ARRAY_SIZE(twl_of_match); i++) {
info = twl_of_match[i].data;
- if (!info || info->desc.id != id)
- continue;
- break;
+ if (info && info->desc.id == id)
+ break;
}
+ if (i == ARRAY_SIZE(twl_of_match))
+ return -ENODEV;
+
drvdata = initdata->driver_data;
if (!drvdata)
return -EINVAL;
@@ -1273,8 +1256,12 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
break;
}
- rdev = regulator_register(&info->desc, &pdev->dev, initdata, info,
- pdev->dev.of_node);
+ config.dev = &pdev->dev;
+ config.init_data = initdata;
+ config.driver_data = info;
+ config.of_node = pdev->dev.of_node;
+
+ rdev = regulator_register(&info->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "can't register %s, %ld\n",
info->desc.name, PTR_ERR(rdev));
diff --git a/drivers/regulator/userspace-consumer.c b/drivers/regulator/userspace-consumer.c
index 518667ef9a0d..a7c8deb5f28f 100644
--- a/drivers/regulator/userspace-consumer.c
+++ b/drivers/regulator/userspace-consumer.c
@@ -115,7 +115,9 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev)
if (!pdata)
return -EINVAL;
- drvdata = kzalloc(sizeof(struct userspace_consumer_data), GFP_KERNEL);
+ drvdata = devm_kzalloc(&pdev->dev,
+ sizeof(struct userspace_consumer_data),
+ GFP_KERNEL);
if (drvdata == NULL)
return -ENOMEM;
@@ -125,16 +127,16 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev)
mutex_init(&drvdata->lock);
- ret = regulator_bulk_get(&pdev->dev, drvdata->num_supplies,
- drvdata->supplies);
+ ret = devm_regulator_bulk_get(&pdev->dev, drvdata->num_supplies,
+ drvdata->supplies);
if (ret) {
dev_err(&pdev->dev, "Failed to get supplies: %d\n", ret);
- goto err_alloc_supplies;
+ return ret;
}
ret = sysfs_create_group(&pdev->dev.kobj, &attr_group);
if (ret != 0)
- goto err_create_attrs;
+ return ret;
if (pdata->init_on) {
ret = regulator_bulk_enable(drvdata->num_supplies,
@@ -154,11 +156,6 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev)
err_enable:
sysfs_remove_group(&pdev->dev.kobj, &attr_group);
-err_create_attrs:
- regulator_bulk_free(drvdata->num_supplies, drvdata->supplies);
-
-err_alloc_supplies:
- kfree(drvdata);
return ret;
}
@@ -171,9 +168,6 @@ static int regulator_userspace_consumer_remove(struct platform_device *pdev)
if (data->enabled)
regulator_bulk_disable(data->num_supplies, data->supplies);
- regulator_bulk_free(data->num_supplies, data->supplies);
- kfree(data);
-
return 0;
}
diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c
index ee0b161c998f..c038e7422538 100644
--- a/drivers/regulator/virtual.c
+++ b/drivers/regulator/virtual.c
@@ -121,7 +121,7 @@ static ssize_t set_min_uV(struct device *dev, struct device_attribute *attr,
struct virtual_consumer_data *data = dev_get_drvdata(dev);
long val;
- if (strict_strtol(buf, 10, &val) != 0)
+ if (kstrtol(buf, 10, &val) != 0)
return count;
mutex_lock(&data->lock);
@@ -147,7 +147,7 @@ static ssize_t set_max_uV(struct device *dev, struct device_attribute *attr,
struct virtual_consumer_data *data = dev_get_drvdata(dev);
long val;
- if (strict_strtol(buf, 10, &val) != 0)
+ if (kstrtol(buf, 10, &val) != 0)
return count;
mutex_lock(&data->lock);
@@ -173,7 +173,7 @@ static ssize_t set_min_uA(struct device *dev, struct device_attribute *attr,
struct virtual_consumer_data *data = dev_get_drvdata(dev);
long val;
- if (strict_strtol(buf, 10, &val) != 0)
+ if (kstrtol(buf, 10, &val) != 0)
return count;
mutex_lock(&data->lock);
@@ -199,7 +199,7 @@ static ssize_t set_max_uA(struct device *dev, struct device_attribute *attr,
struct virtual_consumer_data *data = dev_get_drvdata(dev);
long val;
- if (strict_strtol(buf, 10, &val) != 0)
+ if (kstrtol(buf, 10, &val) != 0)
return count;
mutex_lock(&data->lock);
@@ -291,18 +291,19 @@ static int __devinit regulator_virtual_probe(struct platform_device *pdev)
struct virtual_consumer_data *drvdata;
int ret;
- drvdata = kzalloc(sizeof(struct virtual_consumer_data), GFP_KERNEL);
+ drvdata = devm_kzalloc(&pdev->dev, sizeof(struct virtual_consumer_data),
+ GFP_KERNEL);
if (drvdata == NULL)
return -ENOMEM;
mutex_init(&drvdata->lock);
- drvdata->regulator = regulator_get(&pdev->dev, reg_id);
+ drvdata->regulator = devm_regulator_get(&pdev->dev, reg_id);
if (IS_ERR(drvdata->regulator)) {
ret = PTR_ERR(drvdata->regulator);
dev_err(&pdev->dev, "Failed to obtain supply '%s': %d\n",
reg_id, ret);
- goto err;
+ return ret;
}
ret = sysfs_create_group(&pdev->dev.kobj,
@@ -310,7 +311,7 @@ static int __devinit regulator_virtual_probe(struct platform_device *pdev)
if (ret != 0) {
dev_err(&pdev->dev,
"Failed to create attribute group: %d\n", ret);
- goto err_regulator;
+ return ret;
}
drvdata->mode = regulator_get_mode(drvdata->regulator);
@@ -318,12 +319,6 @@ static int __devinit regulator_virtual_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, drvdata);
return 0;
-
-err_regulator:
- regulator_put(drvdata->regulator);
-err:
- kfree(drvdata);
- return ret;
}
static int __devexit regulator_virtual_remove(struct platform_device *pdev)
@@ -334,9 +329,6 @@ static int __devexit regulator_virtual_remove(struct platform_device *pdev)
if (drvdata->enabled)
regulator_disable(drvdata->regulator);
- regulator_put(drvdata->regulator);
-
- kfree(drvdata);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index ff810e787eac..a885911bb5fc 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -35,7 +35,7 @@
#define WM831X_DCDC_MODE_IDLE 2
#define WM831X_DCDC_MODE_STANDBY 3
-#define WM831X_DCDC_MAX_NAME 6
+#define WM831X_DCDC_MAX_NAME 9
/* Register offsets in control block */
#define WM831X_DCDC_CONTROL_1 0
@@ -50,6 +50,7 @@
struct wm831x_dcdc {
char name[WM831X_DCDC_MAX_NAME];
+ char supply_name[WM831X_DCDC_MAX_NAME];
struct regulator_desc desc;
int base;
struct wm831x *wm831x;
@@ -60,41 +61,6 @@ struct wm831x_dcdc {
int dvs_vsel;
};
-static int wm831x_dcdc_is_enabled(struct regulator_dev *rdev)
-{
- struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = dcdc->wm831x;
- int mask = 1 << rdev_get_id(rdev);
- int reg;
-
- reg = wm831x_reg_read(wm831x, WM831X_DCDC_ENABLE);
- if (reg < 0)
- return reg;
-
- if (reg & mask)
- return 1;
- else
- return 0;
-}
-
-static int wm831x_dcdc_enable(struct regulator_dev *rdev)
-{
- struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = dcdc->wm831x;
- int mask = 1 << rdev_get_id(rdev);
-
- return wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE, mask, mask);
-}
-
-static int wm831x_dcdc_disable(struct regulator_dev *rdev)
-{
- struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = dcdc->wm831x;
- int mask = 1 << rdev_get_id(rdev);
-
- return wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE, mask, 0);
-}
-
static unsigned int wm831x_dcdc_get_mode(struct regulator_dev *rdev)
{
@@ -414,9 +380,9 @@ static struct regulator_ops wm831x_buckv_ops = {
.set_current_limit = wm831x_buckv_set_current_limit,
.get_current_limit = wm831x_buckv_get_current_limit,
- .is_enabled = wm831x_dcdc_is_enabled,
- .enable = wm831x_dcdc_enable,
- .disable = wm831x_dcdc_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
.get_status = wm831x_dcdc_get_status,
.get_mode = wm831x_dcdc_get_mode,
.set_mode = wm831x_dcdc_set_mode,
@@ -437,23 +403,17 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
if (!pdata || !pdata->dvs_gpio)
return;
- ret = gpio_request(pdata->dvs_gpio, "DCDC DVS");
- if (ret < 0) {
- dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n",
- dcdc->name, ret);
- return;
- }
-
/* gpiolib won't let us read the GPIO status so pick the higher
* of the two existing voltages so we take it as platform data.
*/
dcdc->dvs_gpio_state = pdata->dvs_init_state;
- ret = gpio_direction_output(pdata->dvs_gpio, dcdc->dvs_gpio_state);
+ ret = gpio_request_one(pdata->dvs_gpio,
+ dcdc->dvs_gpio_state ? GPIOF_INIT_HIGH : 0,
+ "DCDC DVS");
if (ret < 0) {
- dev_err(wm831x->dev, "Failed to enable %s DVS GPIO: %d\n",
+ dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n",
dcdc->name, ret);
- gpio_free(pdata->dvs_gpio);
return;
}
@@ -498,6 +458,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+ struct regulator_config config = { };
int id;
struct wm831x_dcdc *dcdc;
struct resource *res;
@@ -511,9 +472,6 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);
- if (pdata == NULL || pdata->dcdc[id] == NULL)
- return -ENODEV;
-
dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc),
GFP_KERNEL);
if (dcdc == NULL) {
@@ -533,11 +491,18 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1);
dcdc->desc.name = dcdc->name;
+
+ snprintf(dcdc->supply_name, sizeof(dcdc->supply_name),
+ "DC%dVDD", id + 1);
+ dcdc->desc.supply_name = dcdc->supply_name;
+
dcdc->desc.id = id;
dcdc->desc.type = REGULATOR_VOLTAGE;
dcdc->desc.n_voltages = WM831X_BUCKV_MAX_SELECTOR + 1;
dcdc->desc.ops = &wm831x_buckv_ops;
dcdc->desc.owner = THIS_MODULE;
+ dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;
+ dcdc->desc.enable_mask = 1 << id;
ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG);
if (ret < 0) {
@@ -553,11 +518,16 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
}
dcdc->dvs_vsel = ret & WM831X_DC1_DVS_VSEL_MASK;
- if (pdata->dcdc[id])
+ if (pdata && pdata->dcdc[id])
wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data);
- dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev,
- pdata->dcdc[id], dcdc, NULL);
+ config.dev = pdev->dev.parent;
+ if (pdata)
+ config.init_data = pdata->dcdc[id];
+ config.driver_data = dcdc;
+ config.regmap = wm831x->regmap;
+
+ dcdc->regulator = regulator_register(&dcdc->desc, &config);
if (IS_ERR(dcdc->regulator)) {
ret = PTR_ERR(dcdc->regulator);
dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -675,29 +645,15 @@ static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev,
return wm831x_buckp_set_voltage_int(rdev, reg, uV, uV, &selector);
}
-static int wm831x_buckp_get_voltage_sel(struct regulator_dev *rdev)
-{
- struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = dcdc->wm831x;
- u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
- int val;
-
- val = wm831x_reg_read(wm831x, reg);
- if (val < 0)
- return val;
-
- return val & WM831X_DC3_ON_VSEL_MASK;
-}
-
static struct regulator_ops wm831x_buckp_ops = {
.set_voltage = wm831x_buckp_set_voltage,
- .get_voltage_sel = wm831x_buckp_get_voltage_sel,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = wm831x_buckp_list_voltage,
.set_suspend_voltage = wm831x_buckp_set_suspend_voltage,
- .is_enabled = wm831x_dcdc_is_enabled,
- .enable = wm831x_dcdc_enable,
- .disable = wm831x_dcdc_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
.get_status = wm831x_dcdc_get_status,
.get_mode = wm831x_dcdc_get_mode,
.set_mode = wm831x_dcdc_set_mode,
@@ -708,6 +664,7 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+ struct regulator_config config = { };
int id;
struct wm831x_dcdc *dcdc;
struct resource *res;
@@ -721,9 +678,6 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);
- if (pdata == NULL || pdata->dcdc[id] == NULL)
- return -ENODEV;
-
dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc),
GFP_KERNEL);
if (dcdc == NULL) {
@@ -743,14 +697,28 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1);
dcdc->desc.name = dcdc->name;
+
+ snprintf(dcdc->supply_name, sizeof(dcdc->supply_name),
+ "DC%dVDD", id + 1);
+ dcdc->desc.supply_name = dcdc->supply_name;
+
dcdc->desc.id = id;
dcdc->desc.type = REGULATOR_VOLTAGE;
dcdc->desc.n_voltages = WM831X_BUCKP_MAX_SELECTOR + 1;
dcdc->desc.ops = &wm831x_buckp_ops;
dcdc->desc.owner = THIS_MODULE;
-
- dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev,
- pdata->dcdc[id], dcdc, NULL);
+ dcdc->desc.vsel_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
+ dcdc->desc.vsel_mask = WM831X_DC3_ON_VSEL_MASK;
+ dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;
+ dcdc->desc.enable_mask = 1 << id;
+
+ config.dev = pdev->dev.parent;
+ if (pdata)
+ config.init_data = pdata->dcdc[id];
+ config.driver_data = dcdc;
+ config.regmap = wm831x->regmap;
+
+ dcdc->regulator = regulator_register(&dcdc->desc, &config);
if (IS_ERR(dcdc->regulator)) {
ret = PTR_ERR(dcdc->regulator);
dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -832,15 +800,16 @@ static int wm831x_boostp_get_status(struct regulator_dev *rdev)
static struct regulator_ops wm831x_boostp_ops = {
.get_status = wm831x_boostp_get_status,
- .is_enabled = wm831x_dcdc_is_enabled,
- .enable = wm831x_dcdc_enable,
- .disable = wm831x_dcdc_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
};
static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+ struct regulator_config config = { };
int id = pdev->id % ARRAY_SIZE(pdata->dcdc);
struct wm831x_dcdc *dcdc;
struct resource *res;
@@ -851,7 +820,7 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
if (pdata == NULL || pdata->dcdc[id] == NULL)
return -ENODEV;
- dcdc = kzalloc(sizeof(struct wm831x_dcdc), GFP_KERNEL);
+ dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL);
if (dcdc == NULL) {
dev_err(&pdev->dev, "Unable to allocate private data\n");
return -ENOMEM;
@@ -873,9 +842,16 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
dcdc->desc.type = REGULATOR_VOLTAGE;
dcdc->desc.ops = &wm831x_boostp_ops;
dcdc->desc.owner = THIS_MODULE;
+ dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;
+ dcdc->desc.enable_mask = 1 << id;
- dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev,
- pdata->dcdc[id], dcdc, NULL);
+ config.dev = pdev->dev.parent;
+ if (pdata)
+ config.init_data = pdata->dcdc[id];
+ config.driver_data = dcdc;
+ config.regmap = wm831x->regmap;
+
+ dcdc->regulator = regulator_register(&dcdc->desc, &config);
if (IS_ERR(dcdc->regulator)) {
ret = PTR_ERR(dcdc->regulator);
dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -900,7 +876,6 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
err_regulator:
regulator_unregister(dcdc->regulator);
err:
- kfree(dcdc);
return ret;
}
@@ -912,7 +887,6 @@ static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
free_irq(platform_get_irq_byname(pdev, "UV"), dcdc);
regulator_unregister(dcdc->regulator);
- kfree(dcdc);
return 0;
}
@@ -936,9 +910,9 @@ static struct platform_driver wm831x_boostp_driver = {
#define WM831X_EPE_BASE 6
static struct regulator_ops wm831x_epe_ops = {
- .is_enabled = wm831x_dcdc_is_enabled,
- .enable = wm831x_dcdc_enable,
- .disable = wm831x_dcdc_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
.get_status = wm831x_dcdc_get_status,
};
@@ -946,16 +920,14 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+ struct regulator_config config = { };
int id = pdev->id % ARRAY_SIZE(pdata->epe);
struct wm831x_dcdc *dcdc;
int ret;
dev_dbg(&pdev->dev, "Probing EPE%d\n", id + 1);
- if (pdata == NULL || pdata->epe[id] == NULL)
- return -ENODEV;
-
- dcdc = kzalloc(sizeof(struct wm831x_dcdc), GFP_KERNEL);
+ dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL);
if (dcdc == NULL) {
dev_err(&pdev->dev, "Unable to allocate private data\n");
return -ENOMEM;
@@ -972,9 +944,16 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev)
dcdc->desc.ops = &wm831x_epe_ops;
dcdc->desc.type = REGULATOR_VOLTAGE;
dcdc->desc.owner = THIS_MODULE;
+ dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;
+ dcdc->desc.enable_mask = 1 << dcdc->desc.id;
+
+ config.dev = pdev->dev.parent;
+ if (pdata)
+ config.init_data = pdata->epe[id];
+ config.driver_data = dcdc;
+ config.regmap = wm831x->regmap;
- dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev,
- pdata->epe[id], dcdc, NULL);
+ dcdc->regulator = regulator_register(&dcdc->desc, &config);
if (IS_ERR(dcdc->regulator)) {
ret = PTR_ERR(dcdc->regulator);
dev_err(wm831x->dev, "Failed to register EPE%d: %d\n",
@@ -987,7 +966,6 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev)
return 0;
err:
- kfree(dcdc);
return ret;
}
@@ -996,9 +974,7 @@ static __devexit int wm831x_epe_remove(struct platform_device *pdev)
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
-
regulator_unregister(dcdc->regulator);
- kfree(dcdc);
return 0;
}
diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c
index b414e09c5620..b50ab778b098 100644
--- a/drivers/regulator/wm831x-isink.c
+++ b/drivers/regulator/wm831x-isink.c
@@ -154,6 +154,7 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev)
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
struct wm831x_isink *isink;
int id = pdev->id % ARRAY_SIZE(pdata->isink);
+ struct regulator_config config = { };
struct resource *res;
int ret, irq;
@@ -189,8 +190,11 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev)
isink->desc.type = REGULATOR_CURRENT;
isink->desc.owner = THIS_MODULE;
- isink->regulator = regulator_register(&isink->desc, &pdev->dev,
- pdata->isink[id], isink, NULL);
+ config.dev = pdev->dev.parent;
+ config.init_data = pdata->isink[id];
+ config.driver_data = isink;
+
+ isink->regulator = regulator_register(&isink->desc, &config);
if (IS_ERR(isink->regulator)) {
ret = PTR_ERR(isink->regulator);
dev_err(wm831x->dev, "Failed to register ISINK%d: %d\n",
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index 641e9f6499d1..aa1f8b3fbe16 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -25,7 +25,7 @@
#include <linux/mfd/wm831x/regulator.h>
#include <linux/mfd/wm831x/pdata.h>
-#define WM831X_LDO_MAX_NAME 6
+#define WM831X_LDO_MAX_NAME 9
#define WM831X_LDO_CONTROL 0
#define WM831X_LDO_ON_CONTROL 1
@@ -36,6 +36,7 @@
struct wm831x_ldo {
char name[WM831X_LDO_MAX_NAME];
+ char supply_name[WM831X_LDO_MAX_NAME];
struct regulator_desc desc;
int base;
struct wm831x *wm831x;
@@ -46,41 +47,6 @@ struct wm831x_ldo {
* Shared
*/
-static int wm831x_ldo_is_enabled(struct regulator_dev *rdev)
-{
- struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = ldo->wm831x;
- int mask = 1 << rdev_get_id(rdev);
- int reg;
-
- reg = wm831x_reg_read(wm831x, WM831X_LDO_ENABLE);
- if (reg < 0)
- return reg;
-
- if (reg & mask)
- return 1;
- else
- return 0;
-}
-
-static int wm831x_ldo_enable(struct regulator_dev *rdev)
-{
- struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = ldo->wm831x;
- int mask = 1 << rdev_get_id(rdev);
-
- return wm831x_set_bits(wm831x, WM831X_LDO_ENABLE, mask, mask);
-}
-
-static int wm831x_ldo_disable(struct regulator_dev *rdev)
-{
- struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = ldo->wm831x;
- int mask = 1 << rdev_get_id(rdev);
-
- return wm831x_set_bits(wm831x, WM831X_LDO_ENABLE, mask, 0);
-}
-
static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data)
{
struct wm831x_ldo *ldo = data;
@@ -105,7 +71,7 @@ static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev,
/* 0.9-1.6V in 50mV steps */
if (selector <= WM831X_GP_LDO_SELECTOR_LOW)
return 900000 + (selector * 50000);
- /* 1.7-3.3V in 50mV steps */
+ /* 1.7-3.3V in 100mV steps */
if (selector <= WM831X_GP_LDO_MAX_SELECTOR)
return 1600000 + ((selector - WM831X_GP_LDO_SELECTOR_LOW)
* 100000);
@@ -160,22 +126,6 @@ static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
return wm831x_gp_ldo_set_voltage_int(rdev, reg, uV, uV, &selector);
}
-static int wm831x_gp_ldo_get_voltage_sel(struct regulator_dev *rdev)
-{
- struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = ldo->wm831x;
- int reg = ldo->base + WM831X_LDO_ON_CONTROL;
- int ret;
-
- ret = wm831x_reg_read(wm831x, reg);
- if (ret < 0)
- return ret;
-
- ret &= WM831X_LDO1_ON_VSEL_MASK;
-
- return ret;
-}
-
static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev)
{
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
@@ -293,7 +243,7 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev,
static struct regulator_ops wm831x_gp_ldo_ops = {
.list_voltage = wm831x_gp_ldo_list_voltage,
- .get_voltage_sel = wm831x_gp_ldo_get_voltage_sel,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage = wm831x_gp_ldo_set_voltage,
.set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage,
.get_mode = wm831x_gp_ldo_get_mode,
@@ -301,15 +251,16 @@ static struct regulator_ops wm831x_gp_ldo_ops = {
.get_status = wm831x_gp_ldo_get_status,
.get_optimum_mode = wm831x_gp_ldo_get_optimum_mode,
- .is_enabled = wm831x_ldo_is_enabled,
- .enable = wm831x_ldo_enable,
- .disable = wm831x_ldo_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
};
static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+ struct regulator_config config = { };
int id;
struct wm831x_ldo *ldo;
struct resource *res;
@@ -323,9 +274,6 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
- if (pdata == NULL || pdata->ldo[id] == NULL)
- return -ENODEV;
-
ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);
if (ldo == NULL) {
dev_err(&pdev->dev, "Unable to allocate private data\n");
@@ -344,14 +292,28 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1);
ldo->desc.name = ldo->name;
+
+ snprintf(ldo->supply_name, sizeof(ldo->supply_name),
+ "LDO%dVDD", id + 1);
+ ldo->desc.supply_name = ldo->supply_name;
+
ldo->desc.id = id;
ldo->desc.type = REGULATOR_VOLTAGE;
ldo->desc.n_voltages = WM831X_GP_LDO_MAX_SELECTOR + 1;
ldo->desc.ops = &wm831x_gp_ldo_ops;
ldo->desc.owner = THIS_MODULE;
-
- ldo->regulator = regulator_register(&ldo->desc, &pdev->dev,
- pdata->ldo[id], ldo, NULL);
+ ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL;
+ ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK;
+ ldo->desc.enable_reg = WM831X_LDO_ENABLE;
+ ldo->desc.enable_mask = 1 << id;
+
+ config.dev = pdev->dev.parent;
+ if (pdata)
+ config.init_data = pdata->ldo[id];
+ config.driver_data = ldo;
+ config.regmap = wm831x->regmap;
+
+ ldo->regulator = regulator_register(&ldo->desc, &config);
if (IS_ERR(ldo->regulator)) {
ret = PTR_ERR(ldo->regulator);
dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -414,7 +376,7 @@ static int wm831x_aldo_list_voltage(struct regulator_dev *rdev,
/* 1-1.6V in 50mV steps */
if (selector <= WM831X_ALDO_SELECTOR_LOW)
return 1000000 + (selector * 50000);
- /* 1.7-3.5V in 50mV steps */
+ /* 1.7-3.5V in 100mV steps */
if (selector <= WM831X_ALDO_MAX_SELECTOR)
return 1600000 + ((selector - WM831X_ALDO_SELECTOR_LOW)
* 100000);
@@ -468,22 +430,6 @@ static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
return wm831x_aldo_set_voltage_int(rdev, reg, uV, uV, &selector);
}
-static int wm831x_aldo_get_voltage_sel(struct regulator_dev *rdev)
-{
- struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = ldo->wm831x;
- int reg = ldo->base + WM831X_LDO_ON_CONTROL;
- int ret;
-
- ret = wm831x_reg_read(wm831x, reg);
- if (ret < 0)
- return ret;
-
- ret &= WM831X_LDO7_ON_VSEL_MASK;
-
- return ret;
-}
-
static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev)
{
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
@@ -559,22 +505,23 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev)
static struct regulator_ops wm831x_aldo_ops = {
.list_voltage = wm831x_aldo_list_voltage,
- .get_voltage_sel = wm831x_aldo_get_voltage_sel,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage = wm831x_aldo_set_voltage,
.set_suspend_voltage = wm831x_aldo_set_suspend_voltage,
.get_mode = wm831x_aldo_get_mode,
.set_mode = wm831x_aldo_set_mode,
.get_status = wm831x_aldo_get_status,
- .is_enabled = wm831x_ldo_is_enabled,
- .enable = wm831x_ldo_enable,
- .disable = wm831x_ldo_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
};
static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+ struct regulator_config config = { };
int id;
struct wm831x_ldo *ldo;
struct resource *res;
@@ -588,9 +535,6 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
- if (pdata == NULL || pdata->ldo[id] == NULL)
- return -ENODEV;
-
ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);
if (ldo == NULL) {
dev_err(&pdev->dev, "Unable to allocate private data\n");
@@ -609,14 +553,28 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1);
ldo->desc.name = ldo->name;
+
+ snprintf(ldo->supply_name, sizeof(ldo->supply_name),
+ "LDO%dVDD", id + 1);
+ ldo->desc.supply_name = ldo->supply_name;
+
ldo->desc.id = id;
ldo->desc.type = REGULATOR_VOLTAGE;
ldo->desc.n_voltages = WM831X_ALDO_MAX_SELECTOR + 1;
ldo->desc.ops = &wm831x_aldo_ops;
ldo->desc.owner = THIS_MODULE;
-
- ldo->regulator = regulator_register(&ldo->desc, &pdev->dev,
- pdata->ldo[id], ldo, NULL);
+ ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL;
+ ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK;
+ ldo->desc.enable_reg = WM831X_LDO_ENABLE;
+ ldo->desc.enable_mask = 1 << id;
+
+ config.dev = pdev->dev.parent;
+ if (pdata)
+ config.init_data = pdata->ldo[id];
+ config.driver_data = ldo;
+ config.regmap = wm831x->regmap;
+
+ ldo->regulator = regulator_register(&ldo->desc, &config);
if (IS_ERR(ldo->regulator)) {
ret = PTR_ERR(ldo->regulator);
dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -668,15 +626,6 @@ static struct platform_driver wm831x_aldo_driver = {
#define WM831X_ALIVE_LDO_MAX_SELECTOR 0xf
-static int wm831x_alive_ldo_list_voltage(struct regulator_dev *rdev,
- unsigned int selector)
-{
- /* 0.8-1.55V in 50mV steps */
- if (selector <= WM831X_ALIVE_LDO_MAX_SELECTOR)
- return 800000 + (selector * 50000);
- return -EINVAL;
-}
-
static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev,
int reg,
int min_uV, int max_uV,
@@ -688,7 +637,7 @@ static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev,
vsel = (min_uV - 800000) / 50000;
- ret = wm831x_alive_ldo_list_voltage(rdev, vsel);
+ ret = regulator_list_voltage_linear(rdev, vsel);
if (ret < 0)
return ret;
if (ret < min_uV || ret > max_uV)
@@ -720,22 +669,6 @@ static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev,
return wm831x_alive_ldo_set_voltage_int(rdev, reg, uV, uV, &selector);
}
-static int wm831x_alive_ldo_get_voltage_sel(struct regulator_dev *rdev)
-{
- struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = ldo->wm831x;
- int reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL;
- int ret;
-
- ret = wm831x_reg_read(wm831x, reg);
- if (ret < 0)
- return ret;
-
- ret &= WM831X_LDO11_ON_VSEL_MASK;
-
- return ret;
-}
-
static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
{
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
@@ -754,21 +687,22 @@ static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
}
static struct regulator_ops wm831x_alive_ldo_ops = {
- .list_voltage = wm831x_alive_ldo_list_voltage,
- .get_voltage_sel = wm831x_alive_ldo_get_voltage_sel,
+ .list_voltage = regulator_list_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage = wm831x_alive_ldo_set_voltage,
.set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage,
.get_status = wm831x_alive_ldo_get_status,
- .is_enabled = wm831x_ldo_is_enabled,
- .enable = wm831x_ldo_enable,
- .disable = wm831x_ldo_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
};
static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+ struct regulator_config config = { };
int id;
struct wm831x_ldo *ldo;
struct resource *res;
@@ -783,9 +717,6 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
- if (pdata == NULL || pdata->ldo[id] == NULL)
- return -ENODEV;
-
ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);
if (ldo == NULL) {
dev_err(&pdev->dev, "Unable to allocate private data\n");
@@ -804,14 +735,30 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1);
ldo->desc.name = ldo->name;
+
+ snprintf(ldo->supply_name, sizeof(ldo->supply_name),
+ "LDO%dVDD", id + 1);
+ ldo->desc.supply_name = ldo->supply_name;
+
ldo->desc.id = id;
ldo->desc.type = REGULATOR_VOLTAGE;
ldo->desc.n_voltages = WM831X_ALIVE_LDO_MAX_SELECTOR + 1;
ldo->desc.ops = &wm831x_alive_ldo_ops;
ldo->desc.owner = THIS_MODULE;
-
- ldo->regulator = regulator_register(&ldo->desc, &pdev->dev,
- pdata->ldo[id], ldo, NULL);
+ ldo->desc.vsel_reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL;
+ ldo->desc.vsel_mask = WM831X_LDO11_ON_VSEL_MASK;
+ ldo->desc.enable_reg = WM831X_LDO_ENABLE;
+ ldo->desc.enable_mask = 1 << id;
+ ldo->desc.min_uV = 800000;
+ ldo->desc.uV_step = 50000;
+
+ config.dev = pdev->dev.parent;
+ if (pdata)
+ config.init_data = pdata->ldo[id];
+ config.driver_data = ldo;
+ config.regmap = wm831x->regmap;
+
+ ldo->regulator = regulator_register(&ldo->desc, &config);
if (IS_ERR(ldo->regulator)) {
ret = PTR_ERR(ldo->regulator);
dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 05ecfb872319..94e550dc70b6 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -1269,7 +1269,7 @@ static struct regulator_ops wm8350_isink_ops = {
.enable_time = wm8350_isink_enable_time,
};
-static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
+static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
{
.name = "DCDC1",
.id = WM8350_DCDC_1,
@@ -1398,6 +1398,7 @@ static irqreturn_t pmic_uv_handler(int irq, void *data)
static int wm8350_regulator_probe(struct platform_device *pdev)
{
struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
+ struct regulator_config config = { };
struct regulator_dev *rdev;
int ret;
u16 val;
@@ -1425,10 +1426,12 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
break;
}
+ config.dev = &pdev->dev;
+ config.init_data = pdev->dev.platform_data;
+ config.driver_data = dev_get_drvdata(&pdev->dev);
+
/* register regulator */
- rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev,
- pdev->dev.platform_data,
- dev_get_drvdata(&pdev->dev), NULL);
+ rdev = regulator_register(&wm8350_reg[pdev->id], &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register %s\n",
wm8350_reg[pdev->id].name);
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
index 8477153780b6..69a2b7ce5e4a 100644
--- a/drivers/regulator/wm8400-regulator.c
+++ b/drivers/regulator/wm8400-regulator.c
@@ -19,31 +19,6 @@
#include <linux/regulator/driver.h>
#include <linux/mfd/wm8400-private.h>
-static int wm8400_ldo_is_enabled(struct regulator_dev *dev)
-{
- struct wm8400 *wm8400 = rdev_get_drvdata(dev);
- u16 val;
-
- val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
- return (val & WM8400_LDO1_ENA) != 0;
-}
-
-static int wm8400_ldo_enable(struct regulator_dev *dev)
-{
- struct wm8400 *wm8400 = rdev_get_drvdata(dev);
-
- return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
- WM8400_LDO1_ENA, WM8400_LDO1_ENA);
-}
-
-static int wm8400_ldo_disable(struct regulator_dev *dev)
-{
- struct wm8400 *wm8400 = rdev_get_drvdata(dev);
-
- return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
- WM8400_LDO1_ENA, 0);
-}
-
static int wm8400_ldo_list_voltage(struct regulator_dev *dev,
unsigned selector)
{
@@ -56,21 +31,9 @@ static int wm8400_ldo_list_voltage(struct regulator_dev *dev,
return 1600000 + ((selector - 14) * 100000);
}
-static int wm8400_ldo_get_voltage_sel(struct regulator_dev *dev)
+static int wm8400_ldo_map_voltage(struct regulator_dev *dev,
+ int min_uV, int max_uV)
{
- struct wm8400 *wm8400 = rdev_get_drvdata(dev);
- u16 val;
-
- val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
- val &= WM8400_LDO1_VSEL_MASK;
-
- return val;
-}
-
-static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
- int min_uV, int max_uV, unsigned *selector)
-{
- struct wm8400 *wm8400 = rdev_get_drvdata(dev);
u16 val;
if (min_uV < 900000 || min_uV > 3300000)
@@ -94,92 +57,19 @@ static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
val += 0xf;
}
- *selector = val;
-
- return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
- WM8400_LDO1_VSEL_MASK, val);
+ return val;
}
static struct regulator_ops wm8400_ldo_ops = {
- .is_enabled = wm8400_ldo_is_enabled,
- .enable = wm8400_ldo_enable,
- .disable = wm8400_ldo_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
.list_voltage = wm8400_ldo_list_voltage,
- .get_voltage_sel = wm8400_ldo_get_voltage_sel,
- .set_voltage = wm8400_ldo_set_voltage,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .map_voltage = wm8400_ldo_map_voltage,
};
-static int wm8400_dcdc_is_enabled(struct regulator_dev *dev)
-{
- struct wm8400 *wm8400 = rdev_get_drvdata(dev);
- int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
- u16 val;
-
- val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
- return (val & WM8400_DC1_ENA) != 0;
-}
-
-static int wm8400_dcdc_enable(struct regulator_dev *dev)
-{
- struct wm8400 *wm8400 = rdev_get_drvdata(dev);
- int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
-
- return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
- WM8400_DC1_ENA, WM8400_DC1_ENA);
-}
-
-static int wm8400_dcdc_disable(struct regulator_dev *dev)
-{
- struct wm8400 *wm8400 = rdev_get_drvdata(dev);
- int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
-
- return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
- WM8400_DC1_ENA, 0);
-}
-
-static int wm8400_dcdc_list_voltage(struct regulator_dev *dev,
- unsigned selector)
-{
- if (selector > WM8400_DC1_VSEL_MASK)
- return -EINVAL;
-
- return 850000 + (selector * 25000);
-}
-
-static int wm8400_dcdc_get_voltage_sel(struct regulator_dev *dev)
-{
- struct wm8400 *wm8400 = rdev_get_drvdata(dev);
- u16 val;
- int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
-
- val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
- val &= WM8400_DC1_VSEL_MASK;
-
- return val;
-}
-
-static int wm8400_dcdc_set_voltage(struct regulator_dev *dev,
- int min_uV, int max_uV, unsigned *selector)
-{
- struct wm8400 *wm8400 = rdev_get_drvdata(dev);
- u16 val;
- int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
-
- if (min_uV < 850000)
- return -EINVAL;
-
- val = DIV_ROUND_UP(min_uV - 850000, 25000);
-
- if (850000 + (25000 * val) > max_uV)
- return -EINVAL;
- BUG_ON(850000 + (25000 * val) < min_uV);
-
- *selector = val;
-
- return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
- WM8400_DC1_VSEL_MASK, val);
-}
-
static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev)
{
struct wm8400 *wm8400 = rdev_get_drvdata(dev);
@@ -258,12 +148,12 @@ static unsigned int wm8400_dcdc_get_optimum_mode(struct regulator_dev *dev,
}
static struct regulator_ops wm8400_dcdc_ops = {
- .is_enabled = wm8400_dcdc_is_enabled,
- .enable = wm8400_dcdc_enable,
- .disable = wm8400_dcdc_disable,
- .list_voltage = wm8400_dcdc_list_voltage,
- .get_voltage_sel = wm8400_dcdc_get_voltage_sel,
- .set_voltage = wm8400_dcdc_set_voltage,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_mode = wm8400_dcdc_get_mode,
.set_mode = wm8400_dcdc_set_mode,
.get_optimum_mode = wm8400_dcdc_get_optimum_mode,
@@ -274,7 +164,11 @@ static struct regulator_desc regulators[] = {
.name = "LDO1",
.id = WM8400_LDO1,
.ops = &wm8400_ldo_ops,
+ .enable_reg = WM8400_LDO1_CONTROL,
+ .enable_mask = WM8400_LDO1_ENA,
.n_voltages = WM8400_LDO1_VSEL_MASK + 1,
+ .vsel_reg = WM8400_LDO1_CONTROL,
+ .vsel_mask = WM8400_LDO1_VSEL_MASK,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
@@ -282,15 +176,23 @@ static struct regulator_desc regulators[] = {
.name = "LDO2",
.id = WM8400_LDO2,
.ops = &wm8400_ldo_ops,
+ .enable_reg = WM8400_LDO2_CONTROL,
+ .enable_mask = WM8400_LDO2_ENA,
.n_voltages = WM8400_LDO2_VSEL_MASK + 1,
.type = REGULATOR_VOLTAGE,
+ .vsel_reg = WM8400_LDO2_CONTROL,
+ .vsel_mask = WM8400_LDO2_VSEL_MASK,
.owner = THIS_MODULE,
},
{
.name = "LDO3",
.id = WM8400_LDO3,
.ops = &wm8400_ldo_ops,
+ .enable_reg = WM8400_LDO3_CONTROL,
+ .enable_mask = WM8400_LDO3_ENA,
.n_voltages = WM8400_LDO3_VSEL_MASK + 1,
+ .vsel_reg = WM8400_LDO3_CONTROL,
+ .vsel_mask = WM8400_LDO3_VSEL_MASK,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
@@ -298,7 +200,11 @@ static struct regulator_desc regulators[] = {
.name = "LDO4",
.id = WM8400_LDO4,
.ops = &wm8400_ldo_ops,
+ .enable_reg = WM8400_LDO4_CONTROL,
+ .enable_mask = WM8400_LDO4_ENA,
.n_voltages = WM8400_LDO4_VSEL_MASK + 1,
+ .vsel_reg = WM8400_LDO4_CONTROL,
+ .vsel_mask = WM8400_LDO4_VSEL_MASK,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
@@ -306,7 +212,13 @@ static struct regulator_desc regulators[] = {
.name = "DCDC1",
.id = WM8400_DCDC1,
.ops = &wm8400_dcdc_ops,
+ .enable_reg = WM8400_DCDC1_CONTROL_1,
+ .enable_mask = WM8400_DC1_ENA_MASK,
.n_voltages = WM8400_DC1_VSEL_MASK + 1,
+ .vsel_reg = WM8400_DCDC1_CONTROL_1,
+ .vsel_mask = WM8400_DC1_VSEL_MASK,
+ .min_uV = 850000,
+ .uV_step = 25000,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
@@ -314,7 +226,13 @@ static struct regulator_desc regulators[] = {
.name = "DCDC2",
.id = WM8400_DCDC2,
.ops = &wm8400_dcdc_ops,
+ .enable_reg = WM8400_DCDC2_CONTROL_1,
+ .enable_mask = WM8400_DC1_ENA_MASK,
.n_voltages = WM8400_DC2_VSEL_MASK + 1,
+ .vsel_reg = WM8400_DCDC2_CONTROL_1,
+ .vsel_mask = WM8400_DC2_VSEL_MASK,
+ .min_uV = 850000,
+ .uV_step = 25000,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
@@ -323,11 +241,15 @@ static struct regulator_desc regulators[] = {
static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
{
struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]);
+ struct regulator_config config = { };
struct regulator_dev *rdev;
- rdev = regulator_register(&regulators[pdev->id], &pdev->dev,
- pdev->dev.platform_data, wm8400, NULL);
+ config.dev = &pdev->dev;
+ config.init_data = pdev->dev.platform_data;
+ config.driver_data = wm8400;
+ config.regmap = wm8400->regmap;
+ rdev = regulator_register(&regulators[pdev->id], &config);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
index 75ed402d9f43..9a994316e63c 100644
--- a/drivers/regulator/wm8994-regulator.c
+++ b/drivers/regulator/wm8994-regulator.c
@@ -86,36 +86,6 @@ static int wm8994_ldo1_list_voltage(struct regulator_dev *rdev,
return (selector * 100000) + 2400000;
}
-static int wm8994_ldo1_get_voltage_sel(struct regulator_dev *rdev)
-{
- struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
- int val;
-
- val = wm8994_reg_read(ldo->wm8994, WM8994_LDO_1);
- if (val < 0)
- return val;
-
- return (val & WM8994_LDO1_VSEL_MASK) >> WM8994_LDO1_VSEL_SHIFT;
-}
-
-static int wm8994_ldo1_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *s)
-{
- struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
- int selector, v;
-
- selector = (min_uV - 2400000) / 100000;
- v = wm8994_ldo1_list_voltage(rdev, selector);
- if (v < 0 || v > max_uV)
- return -EINVAL;
-
- *s = selector;
- selector <<= WM8994_LDO1_VSEL_SHIFT;
-
- return wm8994_set_bits(ldo->wm8994, WM8994_LDO_1,
- WM8994_LDO1_VSEL_MASK, selector);
-}
-
static struct regulator_ops wm8994_ldo1_ops = {
.enable = wm8994_ldo_enable,
.disable = wm8994_ldo_disable,
@@ -123,8 +93,8 @@ static struct regulator_ops wm8994_ldo1_ops = {
.enable_time = wm8994_ldo_enable_time,
.list_voltage = wm8994_ldo1_list_voltage,
- .get_voltage_sel = wm8994_ldo1_get_voltage_sel,
- .set_voltage = wm8994_ldo1_set_voltage,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
};
static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
@@ -153,51 +123,6 @@ static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
}
}
-static int wm8994_ldo2_get_voltage_sel(struct regulator_dev *rdev)
-{
- struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
- int val;
-
- val = wm8994_reg_read(ldo->wm8994, WM8994_LDO_2);
- if (val < 0)
- return val;
-
- return (val & WM8994_LDO2_VSEL_MASK) >> WM8994_LDO2_VSEL_SHIFT;
-}
-
-static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *s)
-{
- struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
- int selector, v;
-
- switch (ldo->wm8994->type) {
- case WM8994:
- selector = (min_uV - 900000) / 100000;
- break;
- case WM8958:
- selector = (min_uV - 1000000) / 100000;
- break;
- case WM1811:
- selector = (min_uV - 950000) / 100000;
- if (selector == 0)
- selector = 1;
- break;
- default:
- return -EINVAL;
- }
-
- v = wm8994_ldo2_list_voltage(rdev, selector);
- if (v < 0 || v > max_uV)
- return -EINVAL;
-
- *s = selector;
- selector <<= WM8994_LDO2_VSEL_SHIFT;
-
- return wm8994_set_bits(ldo->wm8994, WM8994_LDO_2,
- WM8994_LDO2_VSEL_MASK, selector);
-}
-
static struct regulator_ops wm8994_ldo2_ops = {
.enable = wm8994_ldo_enable,
.disable = wm8994_ldo_disable,
@@ -205,16 +130,18 @@ static struct regulator_ops wm8994_ldo2_ops = {
.enable_time = wm8994_ldo_enable_time,
.list_voltage = wm8994_ldo2_list_voltage,
- .get_voltage_sel = wm8994_ldo2_get_voltage_sel,
- .set_voltage = wm8994_ldo2_set_voltage,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
};
-static struct regulator_desc wm8994_ldo_desc[] = {
+static const struct regulator_desc wm8994_ldo_desc[] = {
{
.name = "LDO1",
.id = 1,
.type = REGULATOR_VOLTAGE,
.n_voltages = WM8994_LDO1_MAX_SELECTOR + 1,
+ .vsel_reg = WM8994_LDO_1,
+ .vsel_mask = WM8994_LDO1_VSEL_MASK,
.ops = &wm8994_ldo1_ops,
.owner = THIS_MODULE,
},
@@ -223,6 +150,8 @@ static struct regulator_desc wm8994_ldo_desc[] = {
.id = 2,
.type = REGULATOR_VOLTAGE,
.n_voltages = WM8994_LDO2_MAX_SELECTOR + 1,
+ .vsel_reg = WM8994_LDO_2,
+ .vsel_mask = WM8994_LDO2_VSEL_MASK,
.ops = &wm8994_ldo2_ops,
.owner = THIS_MODULE,
},
@@ -233,14 +162,12 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
struct wm8994_pdata *pdata = wm8994->dev->platform_data;
int id = pdev->id % ARRAY_SIZE(pdata->ldo);
+ struct regulator_config config = { };
struct wm8994_ldo *ldo;
int ret;
dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
- if (!pdata)
- return -ENODEV;
-
ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm8994_ldo), GFP_KERNEL);
if (ldo == NULL) {
dev_err(&pdev->dev, "Unable to allocate private data\n");
@@ -252,24 +179,22 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) {
ldo->enable = pdata->ldo[id].enable;
- ret = gpio_request(ldo->enable, "WM8994 LDO enable");
+ ret = gpio_request_one(ldo->enable, 0, "WM8994 LDO enable");
if (ret < 0) {
dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n",
ret);
goto err;
}
-
- ret = gpio_direction_output(ldo->enable, ldo->is_enabled);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to set GPIO up: %d\n",
- ret);
- goto err_gpio;
- }
} else
ldo->is_enabled = true;
- ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &pdev->dev,
- pdata->ldo[id].init_data, ldo, NULL);
+ config.dev = wm8994->dev;
+ config.driver_data = ldo;
+ config.regmap = wm8994->regmap;
+ if (pdata)
+ config.init_data = pdata->ldo[id].init_data;
+
+ ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &config);
if (IS_ERR(ldo->regulator)) {
ret = PTR_ERR(ldo->regulator);
dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index e756a0df3664..d6f8adaa26ef 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1105,8 +1105,7 @@ static void rproc_fw_config_virtio(const struct firmware *fw, void *context)
goto out;
out:
- if (fw)
- release_firmware(fw);
+ release_firmware(fw);
/* allow rproc_unregister() contexts, if any, to proceed */
complete_all(&rproc->firmware_loading_complete);
}
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 8c8377d50c4c..4161bfe462cd 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -838,7 +838,7 @@ config RTC_DRV_AT32AP700X
config RTC_DRV_AT91RM9200
tristate "AT91RM9200 or some AT91SAM9 RTC"
- depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
+ depends on ARCH_AT91
help
Driver for the internal RTC (Realtime Clock) module found on
Atmel AT91RM9200's and some AT91SAM9 chips. On AT91SAM9 chips
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index 684ef4bbfce4..f027c063fb20 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -312,6 +312,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
int ret;
struct pl031_local *ldata;
struct rtc_class_ops *ops = id->data;
+ unsigned long time;
ret = amba_request_regions(adev, NULL);
if (ret)
@@ -343,6 +344,23 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN,
ldata->base + RTC_CR);
+ /*
+ * On ST PL031 variants, the RTC reset value does not provide correct
+ * weekday for 2000-01-01. Correct the erroneous sunday to saturday.
+ */
+ if (ldata->hw_designer == AMBA_VENDOR_ST) {
+ if (readl(ldata->base + RTC_YDR) == 0x2000) {
+ time = readl(ldata->base + RTC_DR);
+ if ((time &
+ (RTC_MON_MASK | RTC_MDAY_MASK | RTC_WDAY_MASK))
+ == 0x02120000) {
+ time = time | (0x7 << RTC_WDAY_SHIFT);
+ writel(0x2000, ldata->base + RTC_YLR);
+ writel(time, ldata->base + RTC_LR);
+ }
+ }
+ }
+
ldata->rtc = rtc_device_register("pl031", &adev->dev, ops,
THIS_MODULE);
if (IS_ERR(ldata->rtc)) {
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 4f9f1dcc1551..6c0116d48c74 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -20,6 +20,7 @@
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/reboot.h>
+#include <linux/serial.h> /* ASYNC_* flags */
#include <linux/slab.h>
#include <asm/ccwdev.h>
#include <asm/cio.h>
@@ -44,14 +45,11 @@
#define RAW3215_TIMEOUT HZ/10 /* time for delayed output */
#define RAW3215_FIXED 1 /* 3215 console device is not be freed */
-#define RAW3215_ACTIVE 2 /* set if the device is in use */
#define RAW3215_WORKING 4 /* set if a request is being worked on */
#define RAW3215_THROTTLED 8 /* set if reading is disabled */
#define RAW3215_STOPPED 16 /* set if writing is disabled */
-#define RAW3215_CLOSING 32 /* set while in close process */
#define RAW3215_TIMER_RUNS 64 /* set if the output delay timer is on */
#define RAW3215_FLUSHING 128 /* set to flush buffer (no delay) */
-#define RAW3215_FROZEN 256 /* set if 3215 is frozen for suspend */
#define TAB_STOP_SIZE 8 /* tab stop size */
@@ -76,6 +74,7 @@ struct raw3215_req {
} __attribute__ ((aligned(8)));
struct raw3215_info {
+ struct tty_port port;
struct ccw_device *cdev; /* device for tty driver */
spinlock_t *lock; /* pointer to irq lock */
int flags; /* state flags */
@@ -84,7 +83,6 @@ struct raw3215_info {
int head; /* first free byte in output buffer */
int count; /* number of bytes in output buffer */
int written; /* number of bytes in write requests */
- struct tty_struct *tty; /* pointer to tty structure if present */
struct raw3215_req *queued_read; /* pointer to queued read requests */
struct raw3215_req *queued_write;/* pointer to queued write requests */
struct tasklet_struct tlet; /* tasklet to invoke tty_wakeup */
@@ -293,7 +291,7 @@ static void raw3215_timeout(unsigned long __data)
if (raw->flags & RAW3215_TIMER_RUNS) {
del_timer(&raw->timer);
raw->flags &= ~RAW3215_TIMER_RUNS;
- if (!(raw->flags & RAW3215_FROZEN)) {
+ if (!(raw->port.flags & ASYNC_SUSPENDED)) {
raw3215_mk_write_req(raw);
raw3215_start_io(raw);
}
@@ -309,7 +307,8 @@ static void raw3215_timeout(unsigned long __data)
*/
static inline void raw3215_try_io(struct raw3215_info *raw)
{
- if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FROZEN))
+ if (!(raw->port.flags & ASYNC_INITIALIZED) ||
+ (raw->port.flags & ASYNC_SUSPENDED))
return;
if (raw->queued_read != NULL)
raw3215_start_io(raw);
@@ -324,10 +323,7 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
}
} else if (!(raw->flags & RAW3215_TIMER_RUNS)) {
/* delay small writes */
- init_timer(&raw->timer);
raw->timer.expires = RAW3215_TIMEOUT + jiffies;
- raw->timer.data = (unsigned long) raw;
- raw->timer.function = raw3215_timeout;
add_timer(&raw->timer);
raw->flags |= RAW3215_TIMER_RUNS;
}
@@ -340,17 +336,21 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
static void raw3215_wakeup(unsigned long data)
{
struct raw3215_info *raw = (struct raw3215_info *) data;
- tty_wakeup(raw->tty);
+ struct tty_struct *tty;
+
+ tty = tty_port_tty_get(&raw->port);
+ tty_wakeup(tty);
+ tty_kref_put(tty);
}
/*
* Try to start the next IO and wake up processes waiting on the tty.
*/
-static void raw3215_next_io(struct raw3215_info *raw)
+static void raw3215_next_io(struct raw3215_info *raw, struct tty_struct *tty)
{
raw3215_mk_write_req(raw);
raw3215_try_io(raw);
- if (raw->tty && RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE)
+ if (tty && RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE)
tasklet_schedule(&raw->tlet);
}
@@ -368,10 +368,11 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
raw = dev_get_drvdata(&cdev->dev);
req = (struct raw3215_req *) intparm;
+ tty = tty_port_tty_get(&raw->port);
cstat = irb->scsw.cmd.cstat;
dstat = irb->scsw.cmd.dstat;
if (cstat != 0)
- raw3215_next_io(raw);
+ raw3215_next_io(raw, tty);
if (dstat & 0x01) { /* we got a unit exception */
dstat &= ~0x01; /* we can ignore it */
}
@@ -381,13 +382,13 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
break;
/* Attention interrupt, someone hit the enter key */
raw3215_mk_read_req(raw);
- raw3215_next_io(raw);
+ raw3215_next_io(raw, tty);
break;
case 0x08:
case 0x0C:
/* Channel end interrupt. */
if ((raw = req->info) == NULL)
- return; /* That shouldn't happen ... */
+ goto put_tty; /* That shouldn't happen ... */
if (req->type == RAW3215_READ) {
/* store residual count, then wait for device end */
req->residual = irb->scsw.cmd.count;
@@ -397,11 +398,10 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
case 0x04:
/* Device end interrupt. */
if ((raw = req->info) == NULL)
- return; /* That shouldn't happen ... */
- if (req->type == RAW3215_READ && raw->tty != NULL) {
+ goto put_tty; /* That shouldn't happen ... */
+ if (req->type == RAW3215_READ && tty != NULL) {
unsigned int cchar;
- tty = raw->tty;
count = 160 - req->residual;
EBCASC(raw->inbuf, count);
cchar = ctrlchar_handle(raw->inbuf, count, tty);
@@ -411,7 +411,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
case CTRLCHAR_CTRL:
tty_insert_flip_char(tty, cchar, TTY_NORMAL);
- tty_flip_buffer_push(raw->tty);
+ tty_flip_buffer_push(tty);
break;
case CTRLCHAR_NONE:
@@ -424,7 +424,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
} else
count -= 2;
tty_insert_flip_string(tty, raw->inbuf, count);
- tty_flip_buffer_push(raw->tty);
+ tty_flip_buffer_push(tty);
break;
}
} else if (req->type == RAW3215_WRITE) {
@@ -439,7 +439,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
raw->queued_read == NULL) {
wake_up_interruptible(&raw->empty_wait);
}
- raw3215_next_io(raw);
+ raw3215_next_io(raw, tty);
break;
default:
/* Strange interrupt, I'll do my best to clean up */
@@ -451,9 +451,10 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
raw->flags &= ~RAW3215_WORKING;
raw3215_free_req(req);
}
- raw3215_next_io(raw);
+ raw3215_next_io(raw, tty);
}
- return;
+put_tty:
+ tty_kref_put(tty);
}
/*
@@ -487,7 +488,7 @@ static void raw3215_make_room(struct raw3215_info *raw, unsigned int length)
/* While console is frozen for suspend we have no other
* choice but to drop message from the buffer to make
* room for even more messages. */
- if (raw->flags & RAW3215_FROZEN) {
+ if (raw->port.flags & ASYNC_SUSPENDED) {
raw3215_drop_line(raw);
continue;
}
@@ -609,10 +610,10 @@ static int raw3215_startup(struct raw3215_info *raw)
{
unsigned long flags;
- if (raw->flags & RAW3215_ACTIVE)
+ if (raw->port.flags & ASYNC_INITIALIZED)
return 0;
raw->line_pos = 0;
- raw->flags |= RAW3215_ACTIVE;
+ raw->port.flags |= ASYNC_INITIALIZED;
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
raw3215_try_io(raw);
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
@@ -628,14 +629,15 @@ static void raw3215_shutdown(struct raw3215_info *raw)
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
- if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FIXED))
+ if (!(raw->port.flags & ASYNC_INITIALIZED) ||
+ (raw->flags & RAW3215_FIXED))
return;
/* Wait for outstanding requests, then free irq */
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
if ((raw->flags & RAW3215_WORKING) ||
raw->queued_write != NULL ||
raw->queued_read != NULL) {
- raw->flags |= RAW3215_CLOSING;
+ raw->port.flags |= ASYNC_CLOSING;
add_wait_queue(&raw->empty_wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
@@ -643,11 +645,41 @@ static void raw3215_shutdown(struct raw3215_info *raw)
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
remove_wait_queue(&raw->empty_wait, &wait);
set_current_state(TASK_RUNNING);
- raw->flags &= ~(RAW3215_ACTIVE | RAW3215_CLOSING);
+ raw->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING);
}
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
}
+static struct raw3215_info *raw3215_alloc_info(void)
+{
+ struct raw3215_info *info;
+
+ info = kzalloc(sizeof(struct raw3215_info), GFP_KERNEL | GFP_DMA);
+ if (!info)
+ return NULL;
+
+ info->buffer = kzalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
+ info->inbuf = kzalloc(RAW3215_INBUF_SIZE, GFP_KERNEL | GFP_DMA);
+ if (!info->buffer || !info->inbuf) {
+ kfree(info);
+ return NULL;
+ }
+
+ setup_timer(&info->timer, raw3215_timeout, (unsigned long)info);
+ init_waitqueue_head(&info->empty_wait);
+ tasklet_init(&info->tlet, raw3215_wakeup, (unsigned long)info);
+ tty_port_init(&info->port);
+
+ return info;
+}
+
+static void raw3215_free_info(struct raw3215_info *raw)
+{
+ kfree(raw->inbuf);
+ kfree(raw->buffer);
+ kfree(raw);
+}
+
static int raw3215_probe (struct ccw_device *cdev)
{
struct raw3215_info *raw;
@@ -656,11 +688,15 @@ static int raw3215_probe (struct ccw_device *cdev)
/* Console is special. */
if (raw3215[0] && (raw3215[0] == dev_get_drvdata(&cdev->dev)))
return 0;
- raw = kmalloc(sizeof(struct raw3215_info) +
- RAW3215_INBUF_SIZE, GFP_KERNEL|GFP_DMA);
+
+ raw = raw3215_alloc_info();
if (raw == NULL)
return -ENOMEM;
+ raw->cdev = cdev;
+ dev_set_drvdata(&cdev->dev, raw);
+ cdev->handler = raw3215_irq;
+
spin_lock(&raw3215_device_lock);
for (line = 0; line < NR_3215; line++) {
if (!raw3215[line]) {
@@ -670,28 +706,10 @@ static int raw3215_probe (struct ccw_device *cdev)
}
spin_unlock(&raw3215_device_lock);
if (line == NR_3215) {
- kfree(raw);
+ raw3215_free_info(raw);
return -ENODEV;
}
- raw->cdev = cdev;
- raw->inbuf = (char *) raw + sizeof(struct raw3215_info);
- memset(raw, 0, sizeof(struct raw3215_info));
- raw->buffer = kmalloc(RAW3215_BUFFER_SIZE,
- GFP_KERNEL|GFP_DMA);
- if (raw->buffer == NULL) {
- spin_lock(&raw3215_device_lock);
- raw3215[line] = NULL;
- spin_unlock(&raw3215_device_lock);
- kfree(raw);
- return -ENOMEM;
- }
- init_waitqueue_head(&raw->empty_wait);
- tasklet_init(&raw->tlet, raw3215_wakeup, (unsigned long) raw);
-
- dev_set_drvdata(&cdev->dev, raw);
- cdev->handler = raw3215_irq;
-
return 0;
}
@@ -703,8 +721,7 @@ static void raw3215_remove (struct ccw_device *cdev)
raw = dev_get_drvdata(&cdev->dev);
if (raw) {
dev_set_drvdata(&cdev->dev, NULL);
- kfree(raw->buffer);
- kfree(raw);
+ raw3215_free_info(raw);
}
}
@@ -741,7 +758,7 @@ static int raw3215_pm_stop(struct ccw_device *cdev)
raw = dev_get_drvdata(&cdev->dev);
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
raw3215_make_room(raw, RAW3215_BUFFER_SIZE);
- raw->flags |= RAW3215_FROZEN;
+ raw->port.flags |= ASYNC_SUSPENDED;
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
return 0;
}
@@ -754,7 +771,7 @@ static int raw3215_pm_start(struct ccw_device *cdev)
/* Allow I/O again and flush output buffer. */
raw = dev_get_drvdata(&cdev->dev);
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
- raw->flags &= ~RAW3215_FROZEN;
+ raw->port.flags &= ~ASYNC_SUSPENDED;
raw->flags |= RAW3215_FLUSHING;
raw3215_try_io(raw);
raw->flags &= ~RAW3215_FLUSHING;
@@ -827,7 +844,7 @@ static void con3215_flush(void)
unsigned long flags;
raw = raw3215[0]; /* console 3215 is the first one */
- if (raw->flags & RAW3215_FROZEN)
+ if (raw->port.flags & ASYNC_SUSPENDED)
/* The console is still frozen for suspend. */
if (ccw_device_force_console())
/* Forcing didn't work, no panic message .. */
@@ -897,23 +914,16 @@ static int __init con3215_init(void)
if (IS_ERR(cdev))
return -ENODEV;
- raw3215[0] = raw = (struct raw3215_info *)
- kzalloc(sizeof(struct raw3215_info), GFP_KERNEL | GFP_DMA);
- raw->buffer = kzalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
- raw->inbuf = kzalloc(RAW3215_INBUF_SIZE, GFP_KERNEL | GFP_DMA);
+ raw3215[0] = raw = raw3215_alloc_info();
raw->cdev = cdev;
dev_set_drvdata(&cdev->dev, raw);
cdev->handler = raw3215_irq;
raw->flags |= RAW3215_FIXED;
- init_waitqueue_head(&raw->empty_wait);
- tasklet_init(&raw->tlet, raw3215_wakeup, (unsigned long) raw);
/* Request the console irq */
if (raw3215_startup(raw) != 0) {
- kfree(raw->inbuf);
- kfree(raw->buffer);
- kfree(raw);
+ raw3215_free_info(raw);
raw3215[0] = NULL;
return -ENODEV;
}
@@ -940,7 +950,7 @@ static int tty3215_open(struct tty_struct *tty, struct file * filp)
return -ENODEV;
tty->driver_data = raw;
- raw->tty = tty;
+ tty_port_tty_set(&raw->port, tty);
tty->low_latency = 0; /* don't use bottom half for pushing chars */
/*
@@ -971,7 +981,7 @@ static void tty3215_close(struct tty_struct *tty, struct file * filp)
raw3215_shutdown(raw);
tasklet_kill(&raw->tlet);
tty->closing = 0;
- raw->tty = NULL;
+ tty_port_tty_set(&raw->port, NULL);
}
/*
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 806588192483..7ef9cfdc17d8 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -199,7 +199,7 @@ handle_diacr(struct kbd_data *kbd, unsigned int ch)
if (ch == ' ' || ch == d)
return d;
- kbd_put_queue(kbd->tty, d);
+ kbd_put_queue(kbd->port, d);
return ch;
}
@@ -221,7 +221,7 @@ k_self(struct kbd_data *kbd, unsigned char value)
{
if (kbd->diacr)
value = handle_diacr(kbd, value);
- kbd_put_queue(kbd->tty, value);
+ kbd_put_queue(kbd->port, value);
}
/*
@@ -239,7 +239,7 @@ static void
k_fn(struct kbd_data *kbd, unsigned char value)
{
if (kbd->func_table[value])
- kbd_puts_queue(kbd->tty, kbd->func_table[value]);
+ kbd_puts_queue(kbd->port, kbd->func_table[value]);
}
static void
@@ -257,20 +257,20 @@ k_spec(struct kbd_data *kbd, unsigned char value)
* but we need only 16 bits here
*/
static void
-to_utf8(struct tty_struct *tty, ushort c)
+to_utf8(struct tty_port *port, ushort c)
{
if (c < 0x80)
/* 0******* */
- kbd_put_queue(tty, c);
+ kbd_put_queue(port, c);
else if (c < 0x800) {
/* 110***** 10****** */
- kbd_put_queue(tty, 0xc0 | (c >> 6));
- kbd_put_queue(tty, 0x80 | (c & 0x3f));
+ kbd_put_queue(port, 0xc0 | (c >> 6));
+ kbd_put_queue(port, 0x80 | (c & 0x3f));
} else {
/* 1110**** 10****** 10****** */
- kbd_put_queue(tty, 0xe0 | (c >> 12));
- kbd_put_queue(tty, 0x80 | ((c >> 6) & 0x3f));
- kbd_put_queue(tty, 0x80 | (c & 0x3f));
+ kbd_put_queue(port, 0xe0 | (c >> 12));
+ kbd_put_queue(port, 0x80 | ((c >> 6) & 0x3f));
+ kbd_put_queue(port, 0x80 | (c & 0x3f));
}
}
@@ -283,7 +283,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
unsigned short keysym;
unsigned char type, value;
- if (!kbd || !kbd->tty)
+ if (!kbd)
return;
if (keycode >= 384)
@@ -323,7 +323,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
#endif
(*k_handler[type])(kbd, value);
} else
- to_utf8(kbd->tty, keysym);
+ to_utf8(kbd->port, keysym);
}
/*
@@ -457,6 +457,7 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs,
int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg)
{
+ struct tty_struct *tty;
void __user *argp;
unsigned int ct;
int perm;
@@ -467,7 +468,10 @@ int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg)
* To have permissions to do most of the vt ioctls, we either have
* to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
*/
- perm = current->signal->tty == kbd->tty || capable(CAP_SYS_TTY_CONFIG);
+ tty = tty_port_tty_get(kbd->port);
+ /* FIXME this test is pretty racy */
+ perm = current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG);
+ tty_kref_put(tty);
switch (cmd) {
case KDGKBTYPE:
return put_user(KB_101, (char __user *)argp);
diff --git a/drivers/s390/char/keyboard.h b/drivers/s390/char/keyboard.h
index 7e736aaeae6e..f682f4e49680 100644
--- a/drivers/s390/char/keyboard.h
+++ b/drivers/s390/char/keyboard.h
@@ -21,7 +21,7 @@ typedef void (fn_handler_fn)(struct kbd_data *);
*/
struct kbd_data {
- struct tty_struct *tty;
+ struct tty_port *port;
unsigned short **key_maps;
char **func_table;
fn_handler_fn **fn_handler;
@@ -42,16 +42,24 @@ int kbd_ioctl(struct kbd_data *, unsigned int, unsigned long);
* Helper Functions.
*/
static inline void
-kbd_put_queue(struct tty_struct *tty, int ch)
+kbd_put_queue(struct tty_port *port, int ch)
{
+ struct tty_struct *tty = tty_port_tty_get(port);
+ if (!tty)
+ return;
tty_insert_flip_char(tty, ch, 0);
tty_schedule_flip(tty);
+ tty_kref_put(tty);
}
static inline void
-kbd_puts_queue(struct tty_struct *tty, char *cp)
+kbd_puts_queue(struct tty_port *port, char *cp)
{
+ struct tty_struct *tty = tty_port_tty_get(port);
+ if (!tty)
+ return;
while (*cp)
tty_insert_flip_char(tty, *cp++, 0);
tty_schedule_flip(tty);
+ tty_kref_put(tty);
}
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 231a1d85127b..36506366158d 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -352,7 +352,17 @@ out:
static int sclp_assign_storage(u16 rn)
{
- return do_assign_storage(0x000d0001, rn);
+ unsigned long long start, address;
+ int rc;
+
+ rc = do_assign_storage(0x000d0001, rn);
+ if (rc)
+ goto out;
+ start = address = rn2addr(rn);
+ for (; address < start + rzm; address += PAGE_SIZE)
+ page_set_storage_key(address, PAGE_DEFAULT_KEY, 0);
+out:
+ return rc;
}
static int sclp_unassign_storage(u16 rn)
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 40a9d69c898e..e66a75b3822c 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -48,7 +48,7 @@ static struct sclp_buffer *sclp_ttybuf;
/* Timer for delayed output of console messages. */
static struct timer_list sclp_tty_timer;
-static struct tty_struct *sclp_tty;
+static struct tty_port sclp_port;
static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE];
static unsigned short int sclp_tty_chars_count;
@@ -64,7 +64,7 @@ static int sclp_tty_columns = 80;
static int
sclp_tty_open(struct tty_struct *tty, struct file *filp)
{
- sclp_tty = tty;
+ tty_port_tty_set(&sclp_port, tty);
tty->driver_data = NULL;
tty->low_latency = 0;
return 0;
@@ -76,7 +76,7 @@ sclp_tty_close(struct tty_struct *tty, struct file *filp)
{
if (tty->count > 1)
return;
- sclp_tty = NULL;
+ tty_port_tty_set(&sclp_port, NULL);
}
/*
@@ -108,6 +108,7 @@ sclp_tty_write_room (struct tty_struct *tty)
static void
sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
{
+ struct tty_struct *tty;
unsigned long flags;
void *page;
@@ -126,8 +127,10 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
spin_unlock_irqrestore(&sclp_tty_lock, flags);
} while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback));
/* check if the tty needs a wake up call */
- if (sclp_tty != NULL) {
- tty_wakeup(sclp_tty);
+ tty = tty_port_tty_get(&sclp_port);
+ if (tty != NULL) {
+ tty_wakeup(tty);
+ tty_kref_put(tty);
}
}
@@ -326,21 +329,22 @@ sclp_tty_flush_buffer(struct tty_struct *tty)
static void
sclp_tty_input(unsigned char* buf, unsigned int count)
{
+ struct tty_struct *tty = tty_port_tty_get(&sclp_port);
unsigned int cchar;
/*
* If this tty driver is currently closed
* then throw the received input away.
*/
- if (sclp_tty == NULL)
+ if (tty == NULL)
return;
- cchar = ctrlchar_handle(buf, count, sclp_tty);
+ cchar = ctrlchar_handle(buf, count, tty);
switch (cchar & CTRLCHAR_MASK) {
case CTRLCHAR_SYSRQ:
break;
case CTRLCHAR_CTRL:
- tty_insert_flip_char(sclp_tty, cchar, TTY_NORMAL);
- tty_flip_buffer_push(sclp_tty);
+ tty_insert_flip_char(tty, cchar, TTY_NORMAL);
+ tty_flip_buffer_push(tty);
break;
case CTRLCHAR_NONE:
/* send (normal) input to line discipline */
@@ -348,13 +352,14 @@ sclp_tty_input(unsigned char* buf, unsigned int count)
(strncmp((const char *) buf + count - 2, "^n", 2) &&
strncmp((const char *) buf + count - 2, "\252n", 2))) {
/* add the auto \n */
- tty_insert_flip_string(sclp_tty, buf, count);
- tty_insert_flip_char(sclp_tty, '\n', TTY_NORMAL);
+ tty_insert_flip_string(tty, buf, count);
+ tty_insert_flip_char(tty, '\n', TTY_NORMAL);
} else
- tty_insert_flip_string(sclp_tty, buf, count - 2);
- tty_flip_buffer_push(sclp_tty);
+ tty_insert_flip_string(tty, buf, count - 2);
+ tty_flip_buffer_push(tty);
break;
}
+ tty_kref_put(tty);
}
/*
@@ -543,7 +548,7 @@ sclp_tty_init(void)
sclp_tty_tolower = 1;
}
sclp_tty_chars_count = 0;
- sclp_tty = NULL;
+ tty_port_init(&sclp_port);
rc = sclp_register(&sclp_input_event);
if (rc) {
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index b635472ae660..edfc0fd73dc6 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -34,7 +34,6 @@
#define SCLP_VT220_DEVICE_NAME "ttysclp"
#define SCLP_VT220_CONSOLE_NAME "ttyS"
#define SCLP_VT220_CONSOLE_INDEX 1 /* console=ttyS1 */
-#define SCLP_VT220_BUF_SIZE 80
/* Representation of a single write request */
struct sclp_vt220_request {
@@ -56,8 +55,7 @@ struct sclp_vt220_sccb {
/* Structures and data needed to register tty driver */
static struct tty_driver *sclp_vt220_driver;
-/* The tty_struct that the kernel associated with us */
-static struct tty_struct *sclp_vt220_tty;
+static struct tty_port sclp_vt220_port;
/* Lock to protect internal data from concurrent access */
static spinlock_t sclp_vt220_lock;
@@ -116,6 +114,7 @@ static struct sclp_register sclp_vt220_register = {
static void
sclp_vt220_process_queue(struct sclp_vt220_request *request)
{
+ struct tty_struct *tty;
unsigned long flags;
void *page;
@@ -141,8 +140,10 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request)
if (request == NULL && sclp_vt220_flush_later)
sclp_vt220_emit_current();
/* Check if the tty needs a wake up call */
- if (sclp_vt220_tty != NULL) {
- tty_wakeup(sclp_vt220_tty);
+ tty = tty_port_tty_get(&sclp_vt220_port);
+ if (tty) {
+ tty_wakeup(tty);
+ tty_kref_put(tty);
}
}
@@ -460,11 +461,12 @@ sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count)
static void
sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
{
+ struct tty_struct *tty = tty_port_tty_get(&sclp_vt220_port);
char *buffer;
unsigned int count;
/* Ignore input if device is not open */
- if (sclp_vt220_tty == NULL)
+ if (tty == NULL)
return;
buffer = (char *) ((addr_t) evbuf + sizeof(struct evbuf_header));
@@ -478,10 +480,11 @@ sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
/* Send input to line discipline */
buffer++;
count--;
- tty_insert_flip_string(sclp_vt220_tty, buffer, count);
- tty_flip_buffer_push(sclp_vt220_tty);
+ tty_insert_flip_string(tty, buffer, count);
+ tty_flip_buffer_push(tty);
break;
}
+ tty_kref_put(tty);
}
/*
@@ -491,10 +494,7 @@ static int
sclp_vt220_open(struct tty_struct *tty, struct file *filp)
{
if (tty->count == 1) {
- sclp_vt220_tty = tty;
- tty->driver_data = kmalloc(SCLP_VT220_BUF_SIZE, GFP_KERNEL);
- if (tty->driver_data == NULL)
- return -ENOMEM;
+ tty_port_tty_set(&sclp_vt220_port, tty);
tty->low_latency = 0;
if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
tty->winsize.ws_row = 24;
@@ -510,11 +510,8 @@ sclp_vt220_open(struct tty_struct *tty, struct file *filp)
static void
sclp_vt220_close(struct tty_struct *tty, struct file *filp)
{
- if (tty->count == 1) {
- sclp_vt220_tty = NULL;
- kfree(tty->driver_data);
- tty->driver_data = NULL;
- }
+ if (tty->count == 1)
+ tty_port_tty_set(&sclp_vt220_port, NULL);
}
/*
@@ -635,9 +632,9 @@ static int __init __sclp_vt220_init(int num_pages)
INIT_LIST_HEAD(&sclp_vt220_empty);
INIT_LIST_HEAD(&sclp_vt220_outqueue);
init_timer(&sclp_vt220_timer);
+ tty_port_init(&sclp_vt220_port);
sclp_vt220_current_request = NULL;
sclp_vt220_buffered_chars = 0;
- sclp_vt220_tty = NULL;
sclp_vt220_flush_later = 0;
/* Allocate pages for output buffering */
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index 267b54e8ff5a..bc6c7cfd36b6 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -154,12 +154,6 @@ struct tape_discipline {
struct tape_request *(*read_block)(struct tape_device *, size_t);
struct tape_request *(*write_block)(struct tape_device *, size_t);
void (*process_eov)(struct tape_device*);
-#ifdef CONFIG_S390_TAPE_BLOCK
- /* Block device stuff. */
- struct tape_request *(*bread)(struct tape_device *, struct request *);
- void (*check_locate)(struct tape_device *, struct tape_request *);
- void (*free_bread)(struct tape_request *);
-#endif
/* ioctl function for additional ioctls. */
int (*ioctl_fn)(struct tape_device *, unsigned int, unsigned long);
/* Array of tape commands with TAPE_NR_MTOPS entries */
@@ -182,26 +176,6 @@ struct tape_char_data {
int block_size; /* of size block_size. */
};
-#ifdef CONFIG_S390_TAPE_BLOCK
-/* Block Frontend Data */
-struct tape_blk_data
-{
- struct tape_device * device;
- /* Block device request queue. */
- struct request_queue * request_queue;
- spinlock_t request_queue_lock;
-
- /* Task to move entries from block request to CCS request queue. */
- struct work_struct requeue_task;
- atomic_t requeue_scheduled;
-
- /* Current position on the tape. */
- long block_position;
- int medium_changed;
- struct gendisk * disk;
-};
-#endif
-
/* Tape Info */
struct tape_device {
/* entry in tape_device_list */
@@ -248,10 +222,6 @@ struct tape_device {
/* Character device frontend data */
struct tape_char_data char_data;
-#ifdef CONFIG_S390_TAPE_BLOCK
- /* Block dev frontend data */
- struct tape_blk_data blk_data;
-#endif
/* Function to start or stop the next request later. */
struct delayed_work tape_dnr;
@@ -313,19 +283,6 @@ extern void tapechar_exit(void);
extern int tapechar_setup_device(struct tape_device *);
extern void tapechar_cleanup_device(struct tape_device *);
-/* Externals from tape_block.c */
-#ifdef CONFIG_S390_TAPE_BLOCK
-extern int tapeblock_init (void);
-extern void tapeblock_exit(void);
-extern int tapeblock_setup_device(struct tape_device *);
-extern void tapeblock_cleanup_device(struct tape_device *);
-#else
-static inline int tapeblock_init (void) {return 0;}
-static inline void tapeblock_exit (void) {;}
-static inline int tapeblock_setup_device(struct tape_device *t) {return 0;}
-static inline void tapeblock_cleanup_device (struct tape_device *t) {;}
-#endif
-
/* tape initialisation functions */
#ifdef CONFIG_PROC_FS
extern void tape_proc_init (void);
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 934ef33eb9a4..b28de80b7ca4 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -323,20 +323,6 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
inhibit_cu_recovery = (*device->modeset_byte & 0x80) ? 1 : 0;
sense = irb->ecw;
-#ifdef CONFIG_S390_TAPE_BLOCK
- if (request->op == TO_BLOCK) {
- /*
- * Recovery for block device requests. Set the block_position
- * to something invalid and retry.
- */
- device->blk_data.block_position = -1;
- if (request->retries-- <= 0)
- return tape_34xx_erp_failed(request, -EIO);
- else
- return tape_34xx_erp_retry(request);
- }
-#endif
-
if (
sense[0] & SENSE_COMMAND_REJECT &&
sense[1] & SENSE_WRITE_PROTECT
@@ -1129,123 +1115,6 @@ tape_34xx_mtseek(struct tape_device *device, int mt_count)
return tape_do_io_free(device, request);
}
-#ifdef CONFIG_S390_TAPE_BLOCK
-/*
- * Tape block read for 34xx.
- */
-static struct tape_request *
-tape_34xx_bread(struct tape_device *device, struct request *req)
-{
- struct tape_request *request;
- struct ccw1 *ccw;
- int count = 0;
- unsigned off;
- char *dst;
- struct bio_vec *bv;
- struct req_iterator iter;
- struct tape_34xx_block_id * start_block;
-
- DBF_EVENT(6, "xBREDid:");
-
- /* Count the number of blocks for the request. */
- rq_for_each_segment(bv, req, iter)
- count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9);
-
- /* Allocate the ccw request. */
- request = tape_alloc_request(3+count+1, 8);
- if (IS_ERR(request))
- return request;
-
- /* Setup ccws. */
- request->op = TO_BLOCK;
- start_block = (struct tape_34xx_block_id *) request->cpdata;
- start_block->block = blk_rq_pos(req) >> TAPEBLOCK_HSEC_S2B;
- DBF_EVENT(6, "start_block = %i\n", start_block->block);
-
- ccw = request->cpaddr;
- ccw = tape_ccw_cc(ccw, MODE_SET_DB, 1, device->modeset_byte);
-
- /*
- * We always setup a nop after the mode set ccw. This slot is
- * used in tape_std_check_locate to insert a locate ccw if the
- * current tape position doesn't match the start block to be read.
- * The second nop will be filled with a read block id which is in
- * turn used by tape_34xx_free_bread to populate the segment bid
- * table.
- */
- ccw = tape_ccw_cc(ccw, NOP, 0, NULL);
- ccw = tape_ccw_cc(ccw, NOP, 0, NULL);
-
- rq_for_each_segment(bv, req, iter) {
- dst = kmap(bv->bv_page) + bv->bv_offset;
- for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) {
- ccw->flags = CCW_FLAG_CC;
- ccw->cmd_code = READ_FORWARD;
- ccw->count = TAPEBLOCK_HSEC_SIZE;
- set_normalized_cda(ccw, (void*) __pa(dst));
- ccw++;
- dst += TAPEBLOCK_HSEC_SIZE;
- }
- }
-
- ccw = tape_ccw_end(ccw, NOP, 0, NULL);
- DBF_EVENT(6, "xBREDccwg\n");
- return request;
-}
-
-static void
-tape_34xx_free_bread (struct tape_request *request)
-{
- struct ccw1* ccw;
-
- ccw = request->cpaddr;
- if ((ccw + 2)->cmd_code == READ_BLOCK_ID) {
- struct {
- struct tape_34xx_block_id cbid;
- struct tape_34xx_block_id dbid;
- } __attribute__ ((packed)) *rbi_data;
-
- rbi_data = request->cpdata;
-
- if (request->device)
- tape_34xx_add_sbid(request->device, rbi_data->cbid);
- }
-
- /* Last ccw is a nop and doesn't need clear_normalized_cda */
- for (; ccw->flags & CCW_FLAG_CC; ccw++)
- if (ccw->cmd_code == READ_FORWARD)
- clear_normalized_cda(ccw);
- tape_free_request(request);
-}
-
-/*
- * check_locate is called just before the tape request is passed to
- * the common io layer for execution. It has to check the current
- * tape position and insert a locate ccw if it doesn't match the
- * start block for the request.
- */
-static void
-tape_34xx_check_locate(struct tape_device *device, struct tape_request *request)
-{
- struct tape_34xx_block_id * start_block;
-
- start_block = (struct tape_34xx_block_id *) request->cpdata;
- if (start_block->block == device->blk_data.block_position)
- return;
-
- DBF_LH(4, "Block seek(%06d+%06d)\n", start_block->block, device->bof);
- start_block->wrap = 0;
- start_block->segment = 1;
- start_block->format = (*device->modeset_byte & 0x08) ?
- TAPE34XX_FMT_3480_XF :
- TAPE34XX_FMT_3480;
- start_block->block = start_block->block + device->bof;
- tape_34xx_merge_sbid(device, start_block);
- tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata);
- tape_ccw_cc(request->cpaddr + 2, READ_BLOCK_ID, 8, request->cpdata);
-}
-#endif
-
/*
* List of 3480/3490 magnetic tape commands.
*/
@@ -1295,11 +1164,6 @@ static struct tape_discipline tape_discipline_34xx = {
.irq = tape_34xx_irq,
.read_block = tape_std_read_block,
.write_block = tape_std_write_block,
-#ifdef CONFIG_S390_TAPE_BLOCK
- .bread = tape_34xx_bread,
- .free_bread = tape_34xx_free_bread,
- .check_locate = tape_34xx_check_locate,
-#endif
.ioctl_fn = tape_34xx_ioctl,
.mtop_array = tape_34xx_mtop
};
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 49c6aab7ad78..a5c6614b0db2 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -670,92 +670,6 @@ tape_3590_schedule_work(struct tape_device *device, enum tape_op op)
return 0;
}
-#ifdef CONFIG_S390_TAPE_BLOCK
-/*
- * Tape Block READ
- */
-static struct tape_request *
-tape_3590_bread(struct tape_device *device, struct request *req)
-{
- struct tape_request *request;
- struct ccw1 *ccw;
- int count = 0, start_block;
- unsigned off;
- char *dst;
- struct bio_vec *bv;
- struct req_iterator iter;
-
- DBF_EVENT(6, "xBREDid:");
- start_block = blk_rq_pos(req) >> TAPEBLOCK_HSEC_S2B;
- DBF_EVENT(6, "start_block = %i\n", start_block);
-
- rq_for_each_segment(bv, req, iter)
- count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9);
-
- request = tape_alloc_request(2 + count + 1, 4);
- if (IS_ERR(request))
- return request;
- request->op = TO_BLOCK;
- *(__u32 *) request->cpdata = start_block;
- ccw = request->cpaddr;
- ccw = tape_ccw_cc(ccw, MODE_SET_DB, 1, device->modeset_byte);
-
- /*
- * We always setup a nop after the mode set ccw. This slot is
- * used in tape_std_check_locate to insert a locate ccw if the
- * current tape position doesn't match the start block to be read.
- */
- ccw = tape_ccw_cc(ccw, NOP, 0, NULL);
-
- rq_for_each_segment(bv, req, iter) {
- dst = page_address(bv->bv_page) + bv->bv_offset;
- for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) {
- ccw->flags = CCW_FLAG_CC;
- ccw->cmd_code = READ_FORWARD;
- ccw->count = TAPEBLOCK_HSEC_SIZE;
- set_normalized_cda(ccw, (void *) __pa(dst));
- ccw++;
- dst += TAPEBLOCK_HSEC_SIZE;
- }
- BUG_ON(off > bv->bv_len);
- }
- ccw = tape_ccw_end(ccw, NOP, 0, NULL);
- DBF_EVENT(6, "xBREDccwg\n");
- return request;
-}
-
-static void
-tape_3590_free_bread(struct tape_request *request)
-{
- struct ccw1 *ccw;
-
- /* Last ccw is a nop and doesn't need clear_normalized_cda */
- for (ccw = request->cpaddr; ccw->flags & CCW_FLAG_CC; ccw++)
- if (ccw->cmd_code == READ_FORWARD)
- clear_normalized_cda(ccw);
- tape_free_request(request);
-}
-
-/*
- * check_locate is called just before the tape request is passed to
- * the common io layer for execution. It has to check the current
- * tape position and insert a locate ccw if it doesn't match the
- * start block for the request.
- */
-static void
-tape_3590_check_locate(struct tape_device *device, struct tape_request *request)
-{
- __u32 *start_block;
-
- start_block = (__u32 *) request->cpdata;
- if (*start_block != device->blk_data.block_position) {
- /* Add the start offset of the file to get the real block. */
- *start_block += device->bof;
- tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata);
- }
-}
-#endif
-
static void tape_3590_med_state_set(struct tape_device *device,
struct tape_3590_med_sense *sense)
{
@@ -1423,20 +1337,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
{
struct tape_3590_sense *sense;
-#ifdef CONFIG_S390_TAPE_BLOCK
- if (request->op == TO_BLOCK) {
- /*
- * Recovery for block device requests. Set the block_position
- * to something invalid and retry.
- */
- device->blk_data.block_position = -1;
- if (request->retries-- <= 0)
- return tape_3590_erp_failed(device, request, irb, -EIO);
- else
- return tape_3590_erp_retry(device, request, irb);
- }
-#endif
-
sense = (struct tape_3590_sense *) irb->ecw;
DBF_EVENT(6, "Unit Check: RQC = %x\n", sense->rc_rqc);
@@ -1729,11 +1629,6 @@ static struct tape_discipline tape_discipline_3590 = {
.irq = tape_3590_irq,
.read_block = tape_std_read_block,
.write_block = tape_std_write_block,
-#ifdef CONFIG_S390_TAPE_BLOCK
- .bread = tape_3590_bread,
- .free_bread = tape_3590_free_bread,
- .check_locate = tape_3590_check_locate,
-#endif
.ioctl_fn = tape_3590_ioctl,
.mtop_array = tape_3590_mtop
};
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 87cd0ab242de..46886a7578c6 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -161,11 +161,6 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
if (rc)
return rc;
-#ifdef CONFIG_S390_TAPE_BLOCK
- /* Changes position. */
- device->blk_data.medium_changed = 1;
-#endif
-
DBF_EVENT(6, "TCHAR:nbytes: %lx\n", block_size);
/* Let the discipline build the ccw chain. */
request = device->discipline->read_block(device, block_size);
@@ -218,11 +213,6 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t
if (rc)
return rc;
-#ifdef CONFIG_S390_TAPE_BLOCK
- /* Changes position. */
- device->blk_data.medium_changed = 1;
-#endif
-
DBF_EVENT(6,"TCHAR:nbytes: %lx\n", block_size);
DBF_EVENT(6, "TCHAR:nblocks: %x\n", nblocks);
/* Let the discipline build the ccw chain. */
@@ -379,9 +369,6 @@ __tapechar_ioctl(struct tape_device *device,
case MTBSFM:
case MTFSFM:
case MTSEEK:
-#ifdef CONFIG_S390_TAPE_BLOCK
- device->blk_data.medium_changed = 1;
-#endif
if (device->required_tapemarks)
tape_std_terminate_write(device);
default:
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index b3a3e8e8656e..585618663ba4 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -401,9 +401,6 @@ tape_generic_online(struct tape_device *device,
rc = tapechar_setup_device(device);
if (rc)
goto out_minor;
- rc = tapeblock_setup_device(device);
- if (rc)
- goto out_char;
tape_state_set(device, TS_UNUSED);
@@ -411,8 +408,6 @@ tape_generic_online(struct tape_device *device,
return 0;
-out_char:
- tapechar_cleanup_device(device);
out_minor:
tape_remove_minor(device);
out_discipline:
@@ -426,7 +421,6 @@ out:
static void
tape_cleanup_device(struct tape_device *device)
{
- tapeblock_cleanup_device(device);
tapechar_cleanup_device(device);
device->discipline->cleanup_device(device);
module_put(device->discipline->owner);
@@ -785,10 +779,6 @@ __tape_start_io(struct tape_device *device, struct tape_request *request)
{
int rc;
-#ifdef CONFIG_S390_TAPE_BLOCK
- if (request->op == TO_BLOCK)
- device->discipline->check_locate(device, request);
-#endif
rc = ccw_device_start(
device->cdev,
request->cpaddr,
@@ -1253,7 +1243,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
}
/*
- * Tape device open function used by tape_char & tape_block frontends.
+ * Tape device open function used by tape_char frontend.
*/
int
tape_open(struct tape_device *device)
@@ -1283,7 +1273,7 @@ tape_open(struct tape_device *device)
}
/*
- * Tape device release function used by tape_char & tape_block frontends.
+ * Tape device release function used by tape_char frontend.
*/
int
tape_release(struct tape_device *device)
@@ -1344,7 +1334,6 @@ tape_init (void)
DBF_EVENT(3, "tape init\n");
tape_proc_init();
tapechar_init ();
- tapeblock_init ();
return 0;
}
@@ -1358,7 +1347,6 @@ tape_exit(void)
/* Get rid of the frontends */
tapechar_exit();
- tapeblock_exit();
tape_proc_cleanup();
debug_unregister (TAPE_DBF_AREA);
}
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index b43445a55cb6..10ec690197cb 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -61,7 +61,7 @@ struct tty3270_line {
*/
struct tty3270 {
struct raw3270_view view;
- struct tty_struct *tty; /* Pointer to tty structure */
+ struct tty_port port;
void **freemem_pages; /* Array of pages used for freemem. */
struct list_head freemem; /* List of free memory for strings. */
@@ -324,9 +324,8 @@ tty3270_blank_line(struct tty3270 *tp)
static void
tty3270_write_callback(struct raw3270_request *rq, void *data)
{
- struct tty3270 *tp;
+ struct tty3270 *tp = container_of(rq->view, struct tty3270, view);
- tp = (struct tty3270 *) rq->view;
if (rq->rc != 0) {
/* Write wasn't successful. Refresh all. */
tp->update_flags = TTY_UPDATE_ALL;
@@ -450,10 +449,9 @@ tty3270_rcl_add(struct tty3270 *tp, char *input, int len)
static void
tty3270_rcl_backward(struct kbd_data *kbd)
{
- struct tty3270 *tp;
+ struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
struct string *s;
- tp = kbd->tty->driver_data;
spin_lock_bh(&tp->view.lock);
if (tp->inattr == TF_INPUT) {
if (tp->rcl_walk && tp->rcl_walk->prev != &tp->rcl_lines)
@@ -478,9 +476,8 @@ tty3270_rcl_backward(struct kbd_data *kbd)
static void
tty3270_exit_tty(struct kbd_data *kbd)
{
- struct tty3270 *tp;
+ struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
- tp = kbd->tty->driver_data;
raw3270_deactivate_view(&tp->view);
}
@@ -490,10 +487,9 @@ tty3270_exit_tty(struct kbd_data *kbd)
static void
tty3270_scroll_forward(struct kbd_data *kbd)
{
- struct tty3270 *tp;
+ struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
int nr_up;
- tp = kbd->tty->driver_data;
spin_lock_bh(&tp->view.lock);
nr_up = tp->nr_up - tp->view.rows + 2;
if (nr_up < 0)
@@ -513,10 +509,9 @@ tty3270_scroll_forward(struct kbd_data *kbd)
static void
tty3270_scroll_backward(struct kbd_data *kbd)
{
- struct tty3270 *tp;
+ struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
int nr_up;
- tp = kbd->tty->driver_data;
spin_lock_bh(&tp->view.lock);
nr_up = tp->nr_up + tp->view.rows - 2;
if (nr_up + tp->view.rows - 2 > tp->nr_lines)
@@ -537,11 +532,10 @@ static void
tty3270_read_tasklet(struct raw3270_request *rrq)
{
static char kreset_data = TW_KR;
- struct tty3270 *tp;
+ struct tty3270 *tp = container_of(rrq->view, struct tty3270, view);
char *input;
int len;
- tp = (struct tty3270 *) rrq->view;
spin_lock_bh(&tp->view.lock);
/*
* Two AID keys are special: For 0x7d (enter) the input line
@@ -577,13 +571,10 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
raw3270_request_add_data(tp->kreset, &kreset_data, 1);
raw3270_start(&tp->view, tp->kreset);
- /* Emit input string. */
- if (tp->tty) {
- while (len-- > 0)
- kbd_keycode(tp->kbd, *input++);
- /* Emit keycode for AID byte. */
- kbd_keycode(tp->kbd, 256 + tp->input->string[0]);
- }
+ while (len-- > 0)
+ kbd_keycode(tp->kbd, *input++);
+ /* Emit keycode for AID byte. */
+ kbd_keycode(tp->kbd, 256 + tp->input->string[0]);
raw3270_request_reset(rrq);
xchg(&tp->read, rrq);
@@ -596,9 +587,10 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
static void
tty3270_read_callback(struct raw3270_request *rq, void *data)
{
+ struct tty3270 *tp = container_of(rq->view, struct tty3270, view);
raw3270_get_view(rq->view);
/* Schedule tasklet to pass input to tty. */
- tasklet_schedule(&((struct tty3270 *) rq->view)->readlet);
+ tasklet_schedule(&tp->readlet);
}
/*
@@ -635,9 +627,8 @@ tty3270_issue_read(struct tty3270 *tp, int lock)
static int
tty3270_activate(struct raw3270_view *view)
{
- struct tty3270 *tp;
+ struct tty3270 *tp = container_of(view, struct tty3270, view);
- tp = (struct tty3270 *) view;
tp->update_flags = TTY_UPDATE_ALL;
tty3270_set_timer(tp, 1);
return 0;
@@ -646,9 +637,8 @@ tty3270_activate(struct raw3270_view *view)
static void
tty3270_deactivate(struct raw3270_view *view)
{
- struct tty3270 *tp;
+ struct tty3270 *tp = container_of(view, struct tty3270, view);
- tp = (struct tty3270 *) view;
del_timer(&tp->timer);
}
@@ -690,6 +680,17 @@ tty3270_alloc_view(void)
if (!tp->freemem_pages)
goto out_tp;
INIT_LIST_HEAD(&tp->freemem);
+ INIT_LIST_HEAD(&tp->lines);
+ INIT_LIST_HEAD(&tp->update);
+ INIT_LIST_HEAD(&tp->rcl_lines);
+ tp->rcl_max = 20;
+ tty_port_init(&tp->port);
+ setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
+ (unsigned long) tp);
+ tasklet_init(&tp->readlet,
+ (void (*)(unsigned long)) tty3270_read_tasklet,
+ (unsigned long) tp->read);
+
for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) {
tp->freemem_pages[pages] = (void *)
__get_free_pages(GFP_KERNEL|GFP_DMA, 0);
@@ -794,16 +795,15 @@ tty3270_free_screen(struct tty3270 *tp)
static void
tty3270_release(struct raw3270_view *view)
{
- struct tty3270 *tp;
- struct tty_struct *tty;
+ struct tty3270 *tp = container_of(view, struct tty3270, view);
+ struct tty_struct *tty = tty_port_tty_get(&tp->port);
- tp = (struct tty3270 *) view;
- tty = tp->tty;
if (tty) {
tty->driver_data = NULL;
- tp->tty = tp->kbd->tty = NULL;
+ tty_port_tty_set(&tp->port, NULL);
tty_hangup(tty);
raw3270_put_view(&tp->view);
+ tty_kref_put(tty);
}
}
@@ -813,8 +813,9 @@ tty3270_release(struct raw3270_view *view)
static void
tty3270_free(struct raw3270_view *view)
{
- tty3270_free_screen((struct tty3270 *) view);
- tty3270_free_view((struct tty3270 *) view);
+ struct tty3270 *tp = container_of(view, struct tty3270, view);
+ tty3270_free_screen(tp);
+ tty3270_free_view(tp);
}
/*
@@ -823,14 +824,13 @@ tty3270_free(struct raw3270_view *view)
static void
tty3270_del_views(void)
{
- struct tty3270 *tp;
int i;
for (i = 0; i < tty3270_max_index; i++) {
- tp = (struct tty3270 *)
+ struct raw3270_view *view =
raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR);
- if (!IS_ERR(tp))
- raw3270_del_view(&tp->view);
+ if (!IS_ERR(view))
+ raw3270_del_view(view);
}
}
@@ -848,22 +848,23 @@ static struct raw3270_fn tty3270_fn = {
static int
tty3270_open(struct tty_struct *tty, struct file * filp)
{
+ struct raw3270_view *view;
struct tty3270 *tp;
int i, rc;
if (tty->count > 1)
return 0;
/* Check if the tty3270 is already there. */
- tp = (struct tty3270 *)
- raw3270_find_view(&tty3270_fn,
+ view = raw3270_find_view(&tty3270_fn,
tty->index + RAW3270_FIRSTMINOR);
- if (!IS_ERR(tp)) {
+ if (!IS_ERR(view)) {
+ tp = container_of(view, struct tty3270, view);
tty->driver_data = tp;
tty->winsize.ws_row = tp->view.rows - 2;
tty->winsize.ws_col = tp->view.cols;
tty->low_latency = 0;
- tp->tty = tty;
- tp->kbd->tty = tty;
+ /* why to reassign? */
+ tty_port_tty_set(&tp->port, tty);
tp->inattr = TF_INPUT;
return 0;
}
@@ -871,7 +872,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
tty3270_max_index = tty->index + 1;
/* Quick exit if there is no device for tty->index. */
- if (PTR_ERR(tp) == -ENODEV)
+ if (PTR_ERR(view) == -ENODEV)
return -ENODEV;
/* Allocate tty3270 structure on first open. */
@@ -879,16 +880,6 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
if (IS_ERR(tp))
return PTR_ERR(tp);
- INIT_LIST_HEAD(&tp->lines);
- INIT_LIST_HEAD(&tp->update);
- INIT_LIST_HEAD(&tp->rcl_lines);
- tp->rcl_max = 20;
- setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
- (unsigned long) tp);
- tasklet_init(&tp->readlet,
- (void (*)(unsigned long)) tty3270_read_tasklet,
- (unsigned long) tp->read);
-
rc = raw3270_add_view(&tp->view, &tty3270_fn,
tty->index + RAW3270_FIRSTMINOR);
if (rc) {
@@ -903,7 +894,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
return rc;
}
- tp->tty = tty;
+ tty_port_tty_set(&tp->port, tty);
tty->low_latency = 0;
tty->driver_data = tp;
tty->winsize.ws_row = tp->view.rows - 2;
@@ -917,7 +908,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
for (i = 0; i < tp->view.rows - 2; i++)
tty3270_blank_line(tp);
- tp->kbd->tty = tty;
+ tp->kbd->port = &tp->port;
tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty;
tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward;
tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward;
@@ -935,14 +926,13 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
static void
tty3270_close(struct tty_struct *tty, struct file * filp)
{
- struct tty3270 *tp;
+ struct tty3270 *tp = tty->driver_data;
if (tty->count > 1)
return;
- tp = (struct tty3270 *) tty->driver_data;
if (tp) {
tty->driver_data = NULL;
- tp->tty = tp->kbd->tty = NULL;
+ tty_port_tty_set(&tp->port, NULL);
raw3270_put_view(&tp->view);
}
}
@@ -1391,7 +1381,7 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
tty3270_lf(tp);
break;
case 'Z': /* Respond ID. */
- kbd_puts_queue(tp->tty, "\033[?6c");
+ kbd_puts_queue(&tp->port, "\033[?6c");
break;
case '7': /* Save cursor position. */
tp->saved_cx = tp->cx;
@@ -1437,11 +1427,11 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
tp->esc_state = ESnormal;
if (ch == 'n' && !tp->esc_ques) {
if (tp->esc_par[0] == 5) /* Status report. */
- kbd_puts_queue(tp->tty, "\033[0n");
+ kbd_puts_queue(&tp->port, "\033[0n");
else if (tp->esc_par[0] == 6) { /* Cursor report. */
char buf[40];
sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1);
- kbd_puts_queue(tp->tty, buf);
+ kbd_puts_queue(&tp->port, buf);
}
return;
}
@@ -1513,12 +1503,13 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
* String write routine for 3270 ttys
*/
static void
-tty3270_do_write(struct tty3270 *tp, const unsigned char *buf, int count)
+tty3270_do_write(struct tty3270 *tp, struct tty_struct *tty,
+ const unsigned char *buf, int count)
{
int i_msg, i;
spin_lock_bh(&tp->view.lock);
- for (i_msg = 0; !tp->tty->stopped && i_msg < count; i_msg++) {
+ for (i_msg = 0; !tty->stopped && i_msg < count; i_msg++) {
if (tp->esc_state != 0) {
/* Continue escape sequence. */
tty3270_escape_sequence(tp, buf[i_msg]);
@@ -1595,10 +1586,10 @@ tty3270_write(struct tty_struct * tty,
if (!tp)
return 0;
if (tp->char_count > 0) {
- tty3270_do_write(tp, tp->char_buf, tp->char_count);
+ tty3270_do_write(tp, tty, tp->char_buf, tp->char_count);
tp->char_count = 0;
}
- tty3270_do_write(tp, buf, count);
+ tty3270_do_write(tp, tty, buf, count);
return count;
}
@@ -1629,7 +1620,7 @@ tty3270_flush_chars(struct tty_struct *tty)
if (!tp)
return;
if (tp->char_count > 0) {
- tty3270_do_write(tp, tp->char_buf, tp->char_count);
+ tty3270_do_write(tp, tty, tp->char_buf, tp->char_count);
tp->char_count = 0;
}
}
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 5f1dc6fb5708..731470e68493 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -1,7 +1,7 @@
/*
* bus driver for ccwgroup
*
- * Copyright IBM Corp. 2002, 2009
+ * Copyright IBM Corp. 2002, 2012
*
* Author(s): Arnd Bergmann (arndb@de.ibm.com)
* Cornelia Huck (cornelia.huck@de.ibm.com)
@@ -15,10 +15,13 @@
#include <linux/ctype.h>
#include <linux/dcache.h>
+#include <asm/cio.h>
#include <asm/ccwdev.h>
#include <asm/ccwgroup.h>
-#define CCW_BUS_ID_SIZE 20
+#include "device.h"
+
+#define CCW_BUS_ID_SIZE 10
/* In Linux 2.4, we had a channel device layer called "chandev"
* that did all sorts of obscure stuff for networking devices.
@@ -27,19 +30,6 @@
* to devices that use multiple subchannels.
*/
-/* a device matches a driver if all its slave devices match the same
- * entry of the driver */
-static int ccwgroup_bus_match(struct device *dev, struct device_driver * drv)
-{
- struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
- struct ccwgroup_driver *gdrv = to_ccwgroupdrv(drv);
-
- if (gdev->creator_id == gdrv->driver_id)
- return 1;
-
- return 0;
-}
-
static struct bus_type ccwgroup_bus_type;
static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
@@ -254,9 +244,10 @@ static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
return 0;
}
-static int __get_next_bus_id(const char **buf, char *bus_id)
+static int __get_next_id(const char **buf, struct ccw_dev_id *id)
{
- int rc, len;
+ unsigned int cssid, ssid, devno;
+ int ret = 0, len;
char *start, *end;
start = (char *)*buf;
@@ -271,49 +262,40 @@ static int __get_next_bus_id(const char **buf, char *bus_id)
len = end - start + 1;
end++;
}
- if (len < CCW_BUS_ID_SIZE) {
- strlcpy(bus_id, start, len);
- rc = 0;
+ if (len <= CCW_BUS_ID_SIZE) {
+ if (sscanf(start, "%2x.%1x.%04x", &cssid, &ssid, &devno) != 3)
+ ret = -EINVAL;
} else
- rc = -EINVAL;
- *buf = end;
- return rc;
-}
-
-static int __is_valid_bus_id(char bus_id[CCW_BUS_ID_SIZE])
-{
- int cssid, ssid, devno;
+ ret = -EINVAL;
- /* Must be of form %x.%x.%04x */
- if (sscanf(bus_id, "%x.%1x.%04x", &cssid, &ssid, &devno) != 3)
- return 0;
- return 1;
+ if (!ret) {
+ id->ssid = ssid;
+ id->devno = devno;
+ }
+ *buf = end;
+ return ret;
}
/**
- * ccwgroup_create_from_string() - create and register a ccw group device
- * @root: parent device for the new device
- * @creator_id: identifier of creating driver
- * @cdrv: ccw driver of slave devices
+ * ccwgroup_create_dev() - create and register a ccw group device
+ * @parent: parent device for the new device
+ * @gdrv: driver for the new group device
* @num_devices: number of slave devices
* @buf: buffer containing comma separated bus ids of slave devices
*
- * Create and register a new ccw group device as a child of @root. Slave
- * devices are obtained from the list of bus ids given in @buf and must all
- * belong to @cdrv.
+ * Create and register a new ccw group device as a child of @parent. Slave
+ * devices are obtained from the list of bus ids given in @buf.
* Returns:
* %0 on success and an error code on failure.
* Context:
* non-atomic
*/
-int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
- struct ccw_driver *cdrv, int num_devices,
- const char *buf)
+int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv,
+ int num_devices, const char *buf)
{
struct ccwgroup_device *gdev;
+ struct ccw_dev_id dev_id;
int rc, i;
- char tmp_bus_id[CCW_BUS_ID_SIZE];
- const char *curr_buf;
gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]),
GFP_KERNEL);
@@ -323,29 +305,24 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
atomic_set(&gdev->onoff, 0);
mutex_init(&gdev->reg_mutex);
mutex_lock(&gdev->reg_mutex);
- gdev->creator_id = creator_id;
gdev->count = num_devices;
gdev->dev.bus = &ccwgroup_bus_type;
- gdev->dev.parent = root;
+ gdev->dev.parent = parent;
gdev->dev.release = ccwgroup_release;
device_initialize(&gdev->dev);
- curr_buf = buf;
- for (i = 0; i < num_devices && curr_buf; i++) {
- rc = __get_next_bus_id(&curr_buf, tmp_bus_id);
+ for (i = 0; i < num_devices && buf; i++) {
+ rc = __get_next_id(&buf, &dev_id);
if (rc != 0)
goto error;
- if (!__is_valid_bus_id(tmp_bus_id)) {
- rc = -EINVAL;
- goto error;
- }
- gdev->cdev[i] = get_ccwdev_by_busid(cdrv, tmp_bus_id);
+ gdev->cdev[i] = get_ccwdev_by_dev_id(&dev_id);
/*
* All devices have to be of the same type in
* order to be grouped.
*/
- if (!gdev->cdev[i]
- || gdev->cdev[i]->id.driver_info !=
+ if (!gdev->cdev[i] || !gdev->cdev[i]->drv ||
+ gdev->cdev[i]->drv != gdev->cdev[0]->drv ||
+ gdev->cdev[i]->id.driver_info !=
gdev->cdev[0]->id.driver_info) {
rc = -EINVAL;
goto error;
@@ -361,18 +338,25 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
spin_unlock_irq(gdev->cdev[i]->ccwlock);
}
/* Check for sufficient number of bus ids. */
- if (i < num_devices && !curr_buf) {
+ if (i < num_devices) {
rc = -EINVAL;
goto error;
}
/* Check for trailing stuff. */
- if (i == num_devices && strlen(curr_buf) > 0) {
+ if (i == num_devices && strlen(buf) > 0) {
rc = -EINVAL;
goto error;
}
dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev));
gdev->dev.groups = ccwgroup_attr_groups;
+
+ if (gdrv) {
+ gdev->dev.driver = &gdrv->driver;
+ rc = gdrv->setup ? gdrv->setup(gdev) : 0;
+ if (rc)
+ goto error;
+ }
rc = device_add(&gdev->dev);
if (rc)
goto error;
@@ -397,7 +381,7 @@ error:
put_device(&gdev->dev);
return rc;
}
-EXPORT_SYMBOL(ccwgroup_create_from_string);
+EXPORT_SYMBOL(ccwgroup_create_dev);
static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
void *data)
@@ -440,14 +424,6 @@ module_exit(cleanup_ccwgroup);
/************************** driver stuff ******************************/
-static int ccwgroup_probe(struct device *dev)
-{
- struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
- struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
-
- return gdrv->probe ? gdrv->probe(gdev) : -ENODEV;
-}
-
static int ccwgroup_remove(struct device *dev)
{
struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
@@ -542,8 +518,6 @@ static const struct dev_pm_ops ccwgroup_pm_ops = {
static struct bus_type ccwgroup_bus_type = {
.name = "ccwgroup",
- .match = ccwgroup_bus_match,
- .probe = ccwgroup_probe,
.remove = ccwgroup_remove,
.shutdown = ccwgroup_shutdown,
.pm = &ccwgroup_pm_ops,
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index a49c46c91983..a6ddaed8793d 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -656,51 +656,34 @@ static struct io_subchannel_private console_priv;
static int console_subchannel_in_use;
/*
- * Use cio_tpi to get a pending interrupt and call the interrupt handler.
- * Return non-zero if an interrupt was processed, zero otherwise.
+ * Use cio_tsch to update the subchannel status and call the interrupt handler
+ * if status had been pending. Called with the console_subchannel lock.
*/
-static int cio_tpi(void)
+static void cio_tsch(struct subchannel *sch)
{
- struct tpi_info *tpi_info;
- struct subchannel *sch;
struct irb *irb;
int irq_context;
- tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id;
- if (tpi(NULL) != 1)
- return 0;
- kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
- if (tpi_info->adapter_IO) {
- do_adapter_IO(tpi_info->isc);
- return 1;
- }
irb = (struct irb *)&S390_lowcore.irb;
/* Store interrupt response block to lowcore. */
- if (tsch(tpi_info->schid, irb) != 0) {
+ if (tsch(sch->schid, irb) != 0)
/* Not status pending or not operational. */
- kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
- return 1;
- }
- sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
- if (!sch) {
- kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
- return 1;
- }
+ return;
+ memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
+ /* Call interrupt handler with updated status. */
irq_context = in_interrupt();
- if (!irq_context)
+ if (!irq_context) {
local_bh_disable();
- irq_enter();
- spin_lock(sch->lock);
- memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
+ irq_enter();
+ }
if (sch->driver && sch->driver->irq)
sch->driver->irq(sch);
else
kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
- spin_unlock(sch->lock);
- irq_exit();
- if (!irq_context)
+ if (!irq_context) {
+ irq_exit();
_local_bh_enable();
- return 1;
+ }
}
void *cio_get_console_priv(void)
@@ -712,34 +695,16 @@ void *cio_get_console_priv(void)
* busy wait for the next interrupt on the console
*/
void wait_cons_dev(void)
- __releases(console_subchannel.lock)
- __acquires(console_subchannel.lock)
{
- unsigned long cr6 __attribute__ ((aligned (8)));
- unsigned long save_cr6 __attribute__ ((aligned (8)));
-
- /*
- * before entering the spinlock we may already have
- * processed the interrupt on a different CPU...
- */
if (!console_subchannel_in_use)
return;
- /* disable all but the console isc */
- __ctl_store (save_cr6, 6, 6);
- cr6 = 1UL << (31 - CONSOLE_ISC);
- __ctl_load (cr6, 6, 6);
-
- do {
- spin_unlock(console_subchannel.lock);
- if (!cio_tpi())
- cpu_relax();
- spin_lock(console_subchannel.lock);
- } while (console_subchannel.schib.scsw.cmd.actl != 0);
- /*
- * restore previous isc value
- */
- __ctl_load (save_cr6, 6, 6);
+ while (1) {
+ cio_tsch(&console_subchannel);
+ if (console_subchannel.schib.scsw.cmd.actl == 0)
+ break;
+ udelay_simple(100);
+ }
}
static int
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 02d015259461..f8f952d52045 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -695,7 +695,17 @@ static int match_dev_id(struct device *dev, void *data)
return ccw_dev_id_is_equal(&cdev->private->dev_id, dev_id);
}
-static struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id)
+/**
+ * get_ccwdev_by_dev_id() - obtain device from a ccw device id
+ * @dev_id: id of the device to be searched
+ *
+ * This function searches all devices attached to the ccw bus for a device
+ * matching @dev_id.
+ * Returns:
+ * If a device is found its reference count is increased and returned;
+ * else %NULL is returned.
+ */
+struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id)
{
struct device *dev;
@@ -703,6 +713,7 @@ static struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id)
return dev ? to_ccwdev(dev) : NULL;
}
+EXPORT_SYMBOL_GPL(get_ccwdev_by_dev_id);
static void ccw_device_do_unbind_bind(struct ccw_device *cdev)
{
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 179824b3082f..6bace6942396 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -101,6 +101,7 @@ int ccw_device_test_sense_data(struct ccw_device *);
void ccw_device_schedule_sch_unregister(struct ccw_device *);
int ccw_purge_blacklisted(void);
void ccw_device_sched_todo(struct ccw_device *cdev, enum cdev_todo todo);
+struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id);
/* Function prototypes for device status and basic sense stuff. */
void ccw_device_accumulate_irb(struct ccw_device *, struct irb *);
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 35c685c374e9..7493efafa0d5 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -63,7 +63,7 @@ static inline int do_siga_input(unsigned long schid, unsigned int mask,
" ipm %0\n"
" srl %0,28\n"
: "=d" (cc)
- : "d" (__fc), "d" (__schid), "d" (__mask) : "cc", "memory");
+ : "d" (__fc), "d" (__schid), "d" (__mask) : "cc");
return cc;
}
@@ -74,7 +74,7 @@ static inline int do_siga_input(unsigned long schid, unsigned int mask,
* @bb: busy bit indicator, set only if SIGA-w/wt could not access a buffer
* @fc: function code to perform
*
- * Returns cc or QDIO_ERROR_SIGA_ACCESS_EXCEPTION.
+ * Returns condition code.
* Note: For IQDC unicast queues only the highest priority queue is processed.
*/
static inline int do_siga_output(unsigned long schid, unsigned long mask,
@@ -85,18 +85,16 @@ static inline int do_siga_output(unsigned long schid, unsigned long mask,
register unsigned long __schid asm("1") = schid;
register unsigned long __mask asm("2") = mask;
register unsigned long __aob asm("3") = aob;
- int cc = QDIO_ERROR_SIGA_ACCESS_EXCEPTION;
+ int cc;
asm volatile(
" siga 0\n"
- "0: ipm %0\n"
+ " ipm %0\n"
" srl %0,28\n"
- "1:\n"
- EX_TABLE(0b, 1b)
- : "+d" (cc), "+d" (__fc), "+d" (__schid), "+d" (__mask),
- "+d" (__aob)
- : : "cc", "memory");
- *bb = ((unsigned int) __fc) >> 31;
+ : "=d" (cc), "+d" (__fc), "+d" (__aob)
+ : "d" (__schid), "d" (__mask)
+ : "cc");
+ *bb = __fc >> 31;
return cc;
}
@@ -167,7 +165,7 @@ again:
DBF_ERROR("%4x EQBS ERROR", SCH_NO(q));
DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
- q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
+ q->handler(q->irq_ptr->cdev, QDIO_ERROR_GET_BUF_STATE,
q->nr, q->first_to_kick, count, q->irq_ptr->int_parm);
return 0;
}
@@ -215,7 +213,7 @@ again:
DBF_ERROR("%4x SQBS ERROR", SCH_NO(q));
DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
- q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
+ q->handler(q->irq_ptr->cdev, QDIO_ERROR_SET_BUF_STATE,
q->nr, q->first_to_kick, count, q->irq_ptr->int_parm);
return 0;
}
@@ -313,7 +311,7 @@ static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output,
cc = do_siga_sync(schid, output, input, fc);
if (unlikely(cc))
DBF_ERROR("%4x SIGA-S:%2d", SCH_NO(q), cc);
- return cc;
+ return (cc) ? -EIO : 0;
}
static inline int qdio_siga_sync_q(struct qdio_q *q)
@@ -384,7 +382,7 @@ static inline int qdio_siga_input(struct qdio_q *q)
cc = do_siga_input(schid, q->mask, fc);
if (unlikely(cc))
DBF_ERROR("%4x SIGA-R:%2d", SCH_NO(q), cc);
- return cc;
+ return (cc) ? -EIO : 0;
}
#define qdio_siga_sync_out(q) qdio_siga_sync(q, ~0U, 0)
@@ -443,7 +441,7 @@ static void process_buffer_error(struct qdio_q *q, int count)
unsigned char state = (q->is_input_q) ? SLSB_P_INPUT_NOT_INIT :
SLSB_P_OUTPUT_NOT_INIT;
- q->qdio_error |= QDIO_ERROR_SLSB_STATE;
+ q->qdio_error = QDIO_ERROR_SLSB_STATE;
/* special handling for no target buffer empty */
if ((!q->is_input_q &&
@@ -519,7 +517,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
int count, stop;
unsigned char state = 0;
- q->timestamp = get_clock_fast();
+ q->timestamp = get_clock();
/*
* Don't check 128 buffers, as otherwise qdio_inbound_q_moved
@@ -575,7 +573,7 @@ static int qdio_inbound_q_moved(struct qdio_q *q)
bufnr = get_inbound_buffer_frontier(q);
- if ((bufnr != q->last_move) || q->qdio_error) {
+ if (bufnr != q->last_move) {
q->last_move = bufnr;
if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR)
q->u.in.timestamp = get_clock();
@@ -790,7 +788,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
int count, stop;
unsigned char state = 0;
- q->timestamp = get_clock_fast();
+ q->timestamp = get_clock();
if (need_siga_sync(q))
if (((queue_type(q) != QDIO_IQDIO_QFMT) &&
@@ -863,7 +861,7 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q)
bufnr = get_outbound_buffer_frontier(q);
- if ((bufnr != q->last_move) || q->qdio_error) {
+ if (bufnr != q->last_move) {
q->last_move = bufnr;
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr);
return 1;
@@ -894,13 +892,16 @@ retry:
goto retry;
}
DBF_ERROR("%4x cc2 BBC:%1d", SCH_NO(q), q->nr);
- cc |= QDIO_ERROR_SIGA_BUSY;
- } else
+ cc = -EBUSY;
+ } else {
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d", q->nr);
+ cc = -ENOBUFS;
+ }
break;
case 1:
case 3:
DBF_ERROR("%4x SIGA-W:%1d", SCH_NO(q), cc);
+ cc = -EIO;
break;
}
if (retries) {
@@ -1090,7 +1091,7 @@ static void qdio_handle_activate_check(struct ccw_device *cdev,
}
count = sub_buf(q->first_to_check, q->first_to_kick);
- q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
+ q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE,
q->nr, q->first_to_kick, count, irq_ptr->int_parm);
no_handler:
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
@@ -1691,7 +1692,7 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
"do%02x b:%02x c:%02x", callflags, bufnr, count);
if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)
- return -EBUSY;
+ return -EIO;
if (!count)
return 0;
if (callflags & QDIO_FLAG_SYNC_INPUT)
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 7e9a72eb2fe0..b987d4619586 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -215,7 +215,7 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind)
register struct ap_queue_status reg1_out asm ("1");
register void *reg2 asm ("2") = ind;
asm volatile(
- ".long 0xb2af0000" /* PQAP(RAPQ) */
+ ".long 0xb2af0000" /* PQAP(AQIC) */
: "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
:
: "cc" );
@@ -232,7 +232,7 @@ __ap_query_functions(ap_qid_t qid, unsigned int *functions)
register unsigned long reg2 asm ("2");
asm volatile(
- ".long 0xb2af0000\n"
+ ".long 0xb2af0000\n" /* PQAP(TAPQ) */
"0:\n"
EX_TABLE(0b, 0b)
: "+d" (reg0), "+d" (reg1), "=d" (reg2)
@@ -391,7 +391,7 @@ __ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length,
reg0 |= 0x400000UL;
asm volatile (
- "0: .long 0xb2ad0042\n" /* DQAP */
+ "0: .long 0xb2ad0042\n" /* NQAP */
" brc 2,0b"
: "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
: "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg)
@@ -450,7 +450,7 @@ __ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
asm volatile(
- "0: .long 0xb2ae0064\n"
+ "0: .long 0xb2ae0064\n" /* DQAP */
" brc 6,0b\n"
: "+d" (reg0), "=d" (reg1), "+d" (reg2),
"+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
@@ -836,12 +836,12 @@ static void __ap_flush_queue(struct ap_device *ap_dev)
list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
list_del_init(&ap_msg->list);
ap_dev->pendingq_count--;
- ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+ ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
}
list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
list_del_init(&ap_msg->list);
ap_dev->requestq_count--;
- ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+ ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
}
}
@@ -1329,7 +1329,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
continue;
list_del_init(&ap_msg->list);
ap_dev->pendingq_count--;
- ap_dev->drv->receive(ap_dev, ap_msg, ap_dev->reply);
+ ap_msg->receive(ap_dev, ap_msg, ap_dev->reply);
break;
}
if (ap_dev->queue_count > 0)
@@ -1450,10 +1450,10 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms
return -EBUSY;
case AP_RESPONSE_REQ_FAC_NOT_INST:
case AP_RESPONSE_MESSAGE_TOO_BIG:
- ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
+ ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
return -EINVAL;
default: /* Device is gone. */
- ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+ ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
return -ENODEV;
}
} else {
@@ -1471,6 +1471,10 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
unsigned long flags;
int rc;
+ /* For asynchronous message handling a valid receive-callback
+ * is required. */
+ BUG_ON(!ap_msg->receive);
+
spin_lock_bh(&ap_dev->lock);
if (!ap_dev->unregistered) {
/* Make room on the queue by polling for finished requests. */
@@ -1482,7 +1486,7 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
if (rc == -ENODEV)
ap_dev->unregistered = 1;
} else {
- ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+ ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
rc = -ENODEV;
}
spin_unlock_bh(&ap_dev->lock);
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index d960a6309eec..726fc65809d8 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -136,9 +136,6 @@ struct ap_driver {
int (*probe)(struct ap_device *);
void (*remove)(struct ap_device *);
- /* receive is called from tasklet context */
- void (*receive)(struct ap_device *, struct ap_message *,
- struct ap_message *);
int request_timeout; /* request timeout in jiffies */
};
@@ -183,6 +180,9 @@ struct ap_message {
void *private; /* ap driver private pointer. */
unsigned int special:1; /* Used for special commands. */
+ /* receive is called from tasklet context */
+ void (*receive)(struct ap_device *, struct ap_message *,
+ struct ap_message *);
};
#define AP_DEVICE(dt) \
@@ -199,6 +199,7 @@ static inline void ap_init_message(struct ap_message *ap_msg)
ap_msg->psmid = 0;
ap_msg->length = 0;
ap_msg->special = 0;
+ ap_msg->receive = NULL;
}
/*
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index 084286728166..46812440425a 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -77,7 +77,6 @@ static void zcrypt_cex2a_receive(struct ap_device *, struct ap_message *,
static struct ap_driver zcrypt_cex2a_driver = {
.probe = zcrypt_cex2a_probe,
.remove = zcrypt_cex2a_remove,
- .receive = zcrypt_cex2a_receive,
.ids = zcrypt_cex2a_ids,
.request_timeout = CEX2A_CLEANUP_TIME,
};
@@ -349,6 +348,7 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev,
ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
+ ap_msg.receive = zcrypt_cex2a_receive;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
ap_msg.private = &work;
@@ -390,6 +390,7 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev,
ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
+ ap_msg.receive = zcrypt_cex2a_receive;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
ap_msg.private = &work;
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index 0effca925451..ad7951c21b79 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -67,7 +67,6 @@ static void zcrypt_pcica_receive(struct ap_device *, struct ap_message *,
static struct ap_driver zcrypt_pcica_driver = {
.probe = zcrypt_pcica_probe,
.remove = zcrypt_pcica_remove,
- .receive = zcrypt_pcica_receive,
.ids = zcrypt_pcica_ids,
.request_timeout = PCICA_CLEANUP_TIME,
};
@@ -284,6 +283,7 @@ static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev,
ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
+ ap_msg.receive = zcrypt_pcica_receive;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
ap_msg.private = &work;
@@ -322,6 +322,7 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev,
ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
+ ap_msg.receive = zcrypt_pcica_receive;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
ap_msg.private = &work;
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
index f9523c0cc8d2..e5dd335fda53 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ b/drivers/s390/crypto/zcrypt_pcicc.c
@@ -79,7 +79,6 @@ static void zcrypt_pcicc_receive(struct ap_device *, struct ap_message *,
static struct ap_driver zcrypt_pcicc_driver = {
.probe = zcrypt_pcicc_probe,
.remove = zcrypt_pcicc_remove,
- .receive = zcrypt_pcicc_receive,
.ids = zcrypt_pcicc_ids,
.request_timeout = PCICC_CLEANUP_TIME,
};
@@ -488,6 +487,7 @@ static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev,
ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
+ ap_msg.receive = zcrypt_pcicc_receive;
ap_msg.length = PAGE_SIZE;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
@@ -527,6 +527,7 @@ static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev,
ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
+ ap_msg.receive = zcrypt_pcicc_receive;
ap_msg.length = PAGE_SIZE;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index cf1cbd4747f4..f7cc43401816 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -89,7 +89,6 @@ static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *,
static struct ap_driver zcrypt_pcixcc_driver = {
.probe = zcrypt_pcixcc_probe,
.remove = zcrypt_pcixcc_remove,
- .receive = zcrypt_pcixcc_receive,
.ids = zcrypt_pcixcc_ids,
.request_timeout = PCIXCC_CLEANUP_TIME,
};
@@ -698,6 +697,7 @@ static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
+ ap_msg.receive = zcrypt_pcixcc_receive;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
ap_msg.private = &resp_type;
@@ -738,6 +738,7 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
+ ap_msg.receive = zcrypt_pcixcc_receive;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
ap_msg.private = &resp_type;
@@ -778,6 +779,7 @@ static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
+ ap_msg.receive = zcrypt_pcixcc_receive;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
ap_msg.private = &resp_type;
@@ -818,6 +820,7 @@ static long zcrypt_pcixcc_rng(struct zcrypt_device *zdev,
ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
+ ap_msg.receive = zcrypt_pcixcc_receive;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
ap_msg.private = &resp_type;
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index b41fae37d3af..6b1ff90d2f00 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -136,7 +136,6 @@ static inline void
claw_set_busy(struct net_device *dev)
{
((struct claw_privbk *)dev->ml_priv)->tbusy = 1;
- eieio();
}
static inline void
@@ -144,13 +143,11 @@ claw_clear_busy(struct net_device *dev)
{
clear_bit(0, &(((struct claw_privbk *) dev->ml_priv)->tbusy));
netif_wake_queue(dev);
- eieio();
}
static inline int
claw_check_busy(struct net_device *dev)
{
- eieio();
return ((struct claw_privbk *) dev->ml_priv)->tbusy;
}
@@ -233,8 +230,6 @@ static ssize_t claw_rbuff_show(struct device *dev,
static ssize_t claw_rbuff_write(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count);
-static int claw_add_files(struct device *dev);
-static void claw_remove_files(struct device *dev);
/* Functions for System Validate */
static int claw_process_control( struct net_device *dev, struct ccwbk * p_ccw);
@@ -267,12 +262,10 @@ static struct ccwgroup_driver claw_group_driver = {
.owner = THIS_MODULE,
.name = "claw",
},
- .max_slaves = 2,
- .driver_id = 0xC3D3C1E6,
- .probe = claw_probe,
- .remove = claw_remove_device,
- .set_online = claw_new_device,
- .set_offline = claw_shutdown_device,
+ .setup = claw_probe,
+ .remove = claw_remove_device,
+ .set_online = claw_new_device,
+ .set_offline = claw_shutdown_device,
.prepare = claw_pm_prepare,
};
@@ -293,30 +286,24 @@ static struct ccw_driver claw_ccw_driver = {
.int_class = IOINT_CLW,
};
-static ssize_t
-claw_driver_group_store(struct device_driver *ddrv, const char *buf,
- size_t count)
+static ssize_t claw_driver_group_store(struct device_driver *ddrv,
+ const char *buf, size_t count)
{
int err;
- err = ccwgroup_create_from_string(claw_root_dev,
- claw_group_driver.driver_id,
- &claw_ccw_driver, 2, buf);
+ err = ccwgroup_create_dev(claw_root_dev, &claw_group_driver, 2, buf);
return err ? err : count;
}
-
static DRIVER_ATTR(group, 0200, NULL, claw_driver_group_store);
-static struct attribute *claw_group_attrs[] = {
+static struct attribute *claw_drv_attrs[] = {
&driver_attr_group.attr,
NULL,
};
-
-static struct attribute_group claw_group_attr_group = {
- .attrs = claw_group_attrs,
+static struct attribute_group claw_drv_attr_group = {
+ .attrs = claw_drv_attrs,
};
-
-static const struct attribute_group *claw_group_attr_groups[] = {
- &claw_group_attr_group,
+static const struct attribute_group *claw_drv_attr_groups[] = {
+ &claw_drv_attr_group,
NULL,
};
@@ -324,60 +311,6 @@ static const struct attribute_group *claw_group_attr_groups[] = {
* Key functions
*/
-/*----------------------------------------------------------------*
- * claw_probe *
- * this function is called for each CLAW device. *
- *----------------------------------------------------------------*/
-static int
-claw_probe(struct ccwgroup_device *cgdev)
-{
- int rc;
- struct claw_privbk *privptr=NULL;
-
- CLAW_DBF_TEXT(2, setup, "probe");
- if (!get_device(&cgdev->dev))
- return -ENODEV;
- privptr = kzalloc(sizeof(struct claw_privbk), GFP_KERNEL);
- dev_set_drvdata(&cgdev->dev, privptr);
- if (privptr == NULL) {
- probe_error(cgdev);
- put_device(&cgdev->dev);
- CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
- return -ENOMEM;
- }
- privptr->p_mtc_envelope= kzalloc( MAX_ENVELOPE_SIZE, GFP_KERNEL);
- privptr->p_env = kzalloc(sizeof(struct claw_env), GFP_KERNEL);
- if ((privptr->p_mtc_envelope==NULL) || (privptr->p_env==NULL)) {
- probe_error(cgdev);
- put_device(&cgdev->dev);
- CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
- return -ENOMEM;
- }
- memcpy(privptr->p_env->adapter_name,WS_NAME_NOT_DEF,8);
- memcpy(privptr->p_env->host_name,WS_NAME_NOT_DEF,8);
- memcpy(privptr->p_env->api_type,WS_NAME_NOT_DEF,8);
- privptr->p_env->packing = 0;
- privptr->p_env->write_buffers = 5;
- privptr->p_env->read_buffers = 5;
- privptr->p_env->read_size = CLAW_FRAME_SIZE;
- privptr->p_env->write_size = CLAW_FRAME_SIZE;
- rc = claw_add_files(&cgdev->dev);
- if (rc) {
- probe_error(cgdev);
- put_device(&cgdev->dev);
- dev_err(&cgdev->dev, "Creating the /proc files for a new"
- " CLAW device failed\n");
- CLAW_DBF_TEXT_(2, setup, "probex%d", rc);
- return rc;
- }
- privptr->p_env->p_priv = privptr;
- cgdev->cdev[0]->handler = claw_irq_handler;
- cgdev->cdev[1]->handler = claw_irq_handler;
- CLAW_DBF_TEXT(2, setup, "prbext 0");
-
- return 0;
-} /* end of claw_probe */
-
/*-------------------------------------------------------------------*
* claw_tx *
*-------------------------------------------------------------------*/
@@ -3093,7 +3026,6 @@ claw_remove_device(struct ccwgroup_device *cgdev)
dev_info(&cgdev->dev, " will be removed.\n");
if (cgdev->state == CCWGROUP_ONLINE)
claw_shutdown_device(cgdev);
- claw_remove_files(&cgdev->dev);
kfree(priv->p_mtc_envelope);
priv->p_mtc_envelope=NULL;
kfree(priv->p_env);
@@ -3321,7 +3253,6 @@ claw_rbuff_write(struct device *dev, struct device_attribute *attr,
CLAW_DBF_TEXT_(2, setup, "RB=%d", p_env->read_buffers);
return count;
}
-
static DEVICE_ATTR(read_buffer, 0644, claw_rbuff_show, claw_rbuff_write);
static struct attribute *claw_attr[] = {
@@ -3332,40 +3263,73 @@ static struct attribute *claw_attr[] = {
&dev_attr_host_name.attr,
NULL,
};
-
static struct attribute_group claw_attr_group = {
.attrs = claw_attr,
};
+static const struct attribute_group *claw_attr_groups[] = {
+ &claw_attr_group,
+ NULL,
+};
+static const struct device_type claw_devtype = {
+ .name = "claw",
+ .groups = claw_attr_groups,
+};
-static int
-claw_add_files(struct device *dev)
+/*----------------------------------------------------------------*
+ * claw_probe *
+ * this function is called for each CLAW device. *
+ *----------------------------------------------------------------*/
+static int claw_probe(struct ccwgroup_device *cgdev)
{
- CLAW_DBF_TEXT(2, setup, "add_file");
- return sysfs_create_group(&dev->kobj, &claw_attr_group);
-}
+ struct claw_privbk *privptr = NULL;
-static void
-claw_remove_files(struct device *dev)
-{
- CLAW_DBF_TEXT(2, setup, "rem_file");
- sysfs_remove_group(&dev->kobj, &claw_attr_group);
-}
+ CLAW_DBF_TEXT(2, setup, "probe");
+ if (!get_device(&cgdev->dev))
+ return -ENODEV;
+ privptr = kzalloc(sizeof(struct claw_privbk), GFP_KERNEL);
+ dev_set_drvdata(&cgdev->dev, privptr);
+ if (privptr == NULL) {
+ probe_error(cgdev);
+ put_device(&cgdev->dev);
+ CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
+ return -ENOMEM;
+ }
+ privptr->p_mtc_envelope = kzalloc(MAX_ENVELOPE_SIZE, GFP_KERNEL);
+ privptr->p_env = kzalloc(sizeof(struct claw_env), GFP_KERNEL);
+ if ((privptr->p_mtc_envelope == NULL) || (privptr->p_env == NULL)) {
+ probe_error(cgdev);
+ put_device(&cgdev->dev);
+ CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
+ return -ENOMEM;
+ }
+ memcpy(privptr->p_env->adapter_name, WS_NAME_NOT_DEF, 8);
+ memcpy(privptr->p_env->host_name, WS_NAME_NOT_DEF, 8);
+ memcpy(privptr->p_env->api_type, WS_NAME_NOT_DEF, 8);
+ privptr->p_env->packing = 0;
+ privptr->p_env->write_buffers = 5;
+ privptr->p_env->read_buffers = 5;
+ privptr->p_env->read_size = CLAW_FRAME_SIZE;
+ privptr->p_env->write_size = CLAW_FRAME_SIZE;
+ privptr->p_env->p_priv = privptr;
+ cgdev->cdev[0]->handler = claw_irq_handler;
+ cgdev->cdev[1]->handler = claw_irq_handler;
+ cgdev->dev.type = &claw_devtype;
+ CLAW_DBF_TEXT(2, setup, "prbext 0");
+
+ return 0;
+} /* end of claw_probe */
/*--------------------------------------------------------------------*
* claw_init and cleanup *
*---------------------------------------------------------------------*/
-static void __exit
-claw_cleanup(void)
+static void __exit claw_cleanup(void)
{
- driver_remove_file(&claw_group_driver.driver,
- &driver_attr_group);
ccwgroup_driver_unregister(&claw_group_driver);
ccw_driver_unregister(&claw_ccw_driver);
root_device_unregister(claw_root_dev);
claw_unregister_debug_facility();
pr_info("Driver unloaded\n");
-
}
/**
@@ -3374,8 +3338,7 @@ claw_cleanup(void)
*
* @return 0 on success, !0 on error.
*/
-static int __init
-claw_init(void)
+static int __init claw_init(void)
{
int ret = 0;
@@ -3394,7 +3357,7 @@ claw_init(void)
ret = ccw_driver_register(&claw_ccw_driver);
if (ret)
goto ccw_err;
- claw_group_driver.driver.groups = claw_group_attr_groups;
+ claw_group_driver.driver.groups = claw_drv_attr_groups;
ret = ccwgroup_driver_register(&claw_group_driver);
if (ret)
goto ccwgroup_err;
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 11f3b071f305..3cd25544a27a 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -1296,6 +1296,11 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
}
+static const struct device_type ctcm_devtype = {
+ .name = "ctcm",
+ .groups = ctcm_attr_groups,
+};
+
/**
* Add ctcm specific attributes.
* Add ctcm private data.
@@ -1307,7 +1312,6 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
static int ctcm_probe_device(struct ccwgroup_device *cgdev)
{
struct ctcm_priv *priv;
- int rc;
CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
"%s %p",
@@ -1324,17 +1328,11 @@ static int ctcm_probe_device(struct ccwgroup_device *cgdev)
put_device(&cgdev->dev);
return -ENOMEM;
}
-
- rc = ctcm_add_files(&cgdev->dev);
- if (rc) {
- kfree(priv);
- put_device(&cgdev->dev);
- return rc;
- }
priv->buffer_size = CTCM_BUFSIZE_DEFAULT;
cgdev->cdev[0]->handler = ctcm_irq_handler;
cgdev->cdev[1]->handler = ctcm_irq_handler;
dev_set_drvdata(&cgdev->dev, priv);
+ cgdev->dev.type = &ctcm_devtype;
return 0;
}
@@ -1611,11 +1609,6 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
goto out_dev;
}
- if (ctcm_add_attributes(&cgdev->dev)) {
- result = -ENODEV;
- goto out_unregister;
- }
-
strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));
dev_info(&dev->dev,
@@ -1629,8 +1622,6 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
priv->channel[CTCM_WRITE]->id, priv->protocol);
return 0;
-out_unregister:
- unregister_netdev(dev);
out_dev:
ctcm_free_netdevice(dev);
out_ccw2:
@@ -1669,7 +1660,6 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev)
/* Close the device */
ctcm_close(dev);
dev->flags &= ~IFF_RUNNING;
- ctcm_remove_attributes(&cgdev->dev);
channel_free(priv->channel[CTCM_READ]);
} else
dev = NULL;
@@ -1711,7 +1701,6 @@ static void ctcm_remove_device(struct ccwgroup_device *cgdev)
if (cgdev->state == CCWGROUP_ONLINE)
ctcm_shutdown_device(cgdev);
- ctcm_remove_files(&cgdev->dev);
dev_set_drvdata(&cgdev->dev, NULL);
kfree(priv);
put_device(&cgdev->dev);
@@ -1778,9 +1767,7 @@ static struct ccwgroup_driver ctcm_group_driver = {
.owner = THIS_MODULE,
.name = CTC_DRIVER_NAME,
},
- .max_slaves = 2,
- .driver_id = 0xC3E3C3D4, /* CTCM */
- .probe = ctcm_probe_device,
+ .setup = ctcm_probe_device,
.remove = ctcm_remove_device,
.set_online = ctcm_new_device,
.set_offline = ctcm_shutdown_device,
@@ -1789,31 +1776,25 @@ static struct ccwgroup_driver ctcm_group_driver = {
.restore = ctcm_pm_resume,
};
-static ssize_t
-ctcm_driver_group_store(struct device_driver *ddrv, const char *buf,
- size_t count)
+static ssize_t ctcm_driver_group_store(struct device_driver *ddrv,
+ const char *buf, size_t count)
{
int err;
- err = ccwgroup_create_from_string(ctcm_root_dev,
- ctcm_group_driver.driver_id,
- &ctcm_ccw_driver, 2, buf);
+ err = ccwgroup_create_dev(ctcm_root_dev, &ctcm_group_driver, 2, buf);
return err ? err : count;
}
-
static DRIVER_ATTR(group, 0200, NULL, ctcm_driver_group_store);
-static struct attribute *ctcm_group_attrs[] = {
+static struct attribute *ctcm_drv_attrs[] = {
&driver_attr_group.attr,
NULL,
};
-
-static struct attribute_group ctcm_group_attr_group = {
- .attrs = ctcm_group_attrs,
+static struct attribute_group ctcm_drv_attr_group = {
+ .attrs = ctcm_drv_attrs,
};
-
-static const struct attribute_group *ctcm_group_attr_groups[] = {
- &ctcm_group_attr_group,
+static const struct attribute_group *ctcm_drv_attr_groups[] = {
+ &ctcm_drv_attr_group,
NULL,
};
@@ -1829,7 +1810,6 @@ static const struct attribute_group *ctcm_group_attr_groups[] = {
*/
static void __exit ctcm_exit(void)
{
- driver_remove_file(&ctcm_group_driver.driver, &driver_attr_group);
ccwgroup_driver_unregister(&ctcm_group_driver);
ccw_driver_unregister(&ctcm_ccw_driver);
root_device_unregister(ctcm_root_dev);
@@ -1867,7 +1847,7 @@ static int __init ctcm_init(void)
ret = ccw_driver_register(&ctcm_ccw_driver);
if (ret)
goto ccw_err;
- ctcm_group_driver.driver.groups = ctcm_group_attr_groups;
+ ctcm_group_driver.driver.groups = ctcm_drv_attr_groups;
ret = ccwgroup_driver_register(&ctcm_group_driver);
if (ret)
goto ccwgroup_err;
diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h
index 24d5215eb0c4..b9056a55d995 100644
--- a/drivers/s390/net/ctcm_main.h
+++ b/drivers/s390/net/ctcm_main.h
@@ -225,13 +225,7 @@ struct ctcm_priv {
int ctcm_open(struct net_device *dev);
int ctcm_close(struct net_device *dev);
-/*
- * prototypes for non-static sysfs functions
- */
-int ctcm_add_attributes(struct device *dev);
-void ctcm_remove_attributes(struct device *dev);
-int ctcm_add_files(struct device *dev);
-void ctcm_remove_files(struct device *dev);
+extern const struct attribute_group *ctcm_attr_groups[];
/*
* Compatibility macros for busy handling
diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c
index 650aec1839e9..0c27ae726475 100644
--- a/drivers/s390/net/ctcm_sysfs.c
+++ b/drivers/s390/net/ctcm_sysfs.c
@@ -13,6 +13,7 @@
#define KMSG_COMPONENT "ctcm"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#include <linux/device.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include "ctcm_main.h"
@@ -108,10 +109,12 @@ static void ctcm_print_statistics(struct ctcm_priv *priv)
}
static ssize_t stats_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
struct ctcm_priv *priv = dev_get_drvdata(dev);
- if (!priv)
+
+ if (!priv || gdev->state != CCWGROUP_ONLINE)
return -ENODEV;
ctcm_print_statistics(priv);
return sprintf(buf, "0\n");
@@ -190,34 +193,14 @@ static struct attribute *ctcm_attr[] = {
&dev_attr_protocol.attr,
&dev_attr_type.attr,
&dev_attr_buffer.attr,
+ &dev_attr_stats.attr,
NULL,
};
static struct attribute_group ctcm_attr_group = {
.attrs = ctcm_attr,
};
-
-int ctcm_add_attributes(struct device *dev)
-{
- int rc;
-
- rc = device_create_file(dev, &dev_attr_stats);
-
- return rc;
-}
-
-void ctcm_remove_attributes(struct device *dev)
-{
- device_remove_file(dev, &dev_attr_stats);
-}
-
-int ctcm_add_files(struct device *dev)
-{
- return sysfs_create_group(&dev->kobj, &ctcm_attr_group);
-}
-
-void ctcm_remove_files(struct device *dev)
-{
- sysfs_remove_group(&dev->kobj, &ctcm_attr_group);
-}
-
+const struct attribute_group *ctcm_attr_groups[] = {
+ &ctcm_attr_group,
+ NULL,
+};
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 6056cf6da035..a3adf4b1c60d 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -2040,10 +2040,17 @@ static struct attribute * lcs_attrs[] = {
&dev_attr_recover.attr,
NULL,
};
-
static struct attribute_group lcs_attr_group = {
.attrs = lcs_attrs,
};
+static const struct attribute_group *lcs_attr_groups[] = {
+ &lcs_attr_group,
+ NULL,
+};
+static const struct device_type lcs_devtype = {
+ .name = "lcs",
+ .groups = lcs_attr_groups,
+};
/**
* lcs_probe_device is called on establishing a new ccwgroup_device.
@@ -2052,7 +2059,6 @@ static int
lcs_probe_device(struct ccwgroup_device *ccwgdev)
{
struct lcs_card *card;
- int ret;
if (!get_device(&ccwgdev->dev))
return -ENODEV;
@@ -2064,12 +2070,6 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev)
put_device(&ccwgdev->dev);
return -ENOMEM;
}
- ret = sysfs_create_group(&ccwgdev->dev.kobj, &lcs_attr_group);
- if (ret) {
- lcs_free_card(card);
- put_device(&ccwgdev->dev);
- return ret;
- }
dev_set_drvdata(&ccwgdev->dev, card);
ccwgdev->cdev[0]->handler = lcs_irq;
ccwgdev->cdev[1]->handler = lcs_irq;
@@ -2078,7 +2078,9 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev)
card->thread_start_mask = 0;
card->thread_allowed_mask = 0;
card->thread_running_mask = 0;
- return 0;
+ ccwgdev->dev.type = &lcs_devtype;
+
+ return 0;
}
static int
@@ -2306,9 +2308,9 @@ lcs_remove_device(struct ccwgroup_device *ccwgdev)
}
if (card->dev)
unregister_netdev(card->dev);
- sysfs_remove_group(&ccwgdev->dev.kobj, &lcs_attr_group);
lcs_cleanup_card(card);
lcs_free_card(card);
+ dev_set_drvdata(&ccwgdev->dev, NULL);
put_device(&ccwgdev->dev);
}
@@ -2393,9 +2395,7 @@ static struct ccwgroup_driver lcs_group_driver = {
.owner = THIS_MODULE,
.name = "lcs",
},
- .max_slaves = 2,
- .driver_id = 0xD3C3E2,
- .probe = lcs_probe_device,
+ .setup = lcs_probe_device,
.remove = lcs_remove_device,
.set_online = lcs_new_device,
.set_offline = lcs_shutdown_device,
@@ -2406,30 +2406,24 @@ static struct ccwgroup_driver lcs_group_driver = {
.restore = lcs_restore,
};
-static ssize_t
-lcs_driver_group_store(struct device_driver *ddrv, const char *buf,
- size_t count)
+static ssize_t lcs_driver_group_store(struct device_driver *ddrv,
+ const char *buf, size_t count)
{
int err;
- err = ccwgroup_create_from_string(lcs_root_dev,
- lcs_group_driver.driver_id,
- &lcs_ccw_driver, 2, buf);
+ err = ccwgroup_create_dev(lcs_root_dev, &lcs_group_driver, 2, buf);
return err ? err : count;
}
-
static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store);
-static struct attribute *lcs_group_attrs[] = {
+static struct attribute *lcs_drv_attrs[] = {
&driver_attr_group.attr,
NULL,
};
-
-static struct attribute_group lcs_group_attr_group = {
- .attrs = lcs_group_attrs,
+static struct attribute_group lcs_drv_attr_group = {
+ .attrs = lcs_drv_attrs,
};
-
-static const struct attribute_group *lcs_group_attr_groups[] = {
- &lcs_group_attr_group,
+static const struct attribute_group *lcs_drv_attr_groups[] = {
+ &lcs_drv_attr_group,
NULL,
};
@@ -2453,7 +2447,7 @@ __init lcs_init_module(void)
rc = ccw_driver_register(&lcs_ccw_driver);
if (rc)
goto ccw_err;
- lcs_group_driver.driver.groups = lcs_group_attr_groups;
+ lcs_group_driver.driver.groups = lcs_drv_attr_groups;
rc = ccwgroup_driver_register(&lcs_group_driver);
if (rc)
goto ccwgroup_err;
@@ -2479,8 +2473,6 @@ __exit lcs_cleanup_module(void)
{
pr_info("Terminating lcs module.\n");
LCS_DBF_TEXT(0, trace, "cleanup");
- driver_remove_file(&lcs_group_driver.driver,
- &driver_attr_group);
ccwgroup_driver_unregister(&lcs_group_driver);
ccw_driver_unregister(&lcs_ccw_driver);
root_device_unregister(lcs_root_dev);
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 40285dc9ae5c..06e8f31ff3dc 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -707,7 +707,16 @@ struct qeth_discipline {
qdio_handler_t *input_handler;
qdio_handler_t *output_handler;
int (*recover)(void *ptr);
- struct ccwgroup_driver *ccwgdriver;
+ int (*setup) (struct ccwgroup_device *);
+ void (*remove) (struct ccwgroup_device *);
+ int (*set_online) (struct ccwgroup_device *);
+ int (*set_offline) (struct ccwgroup_device *);
+ void (*shutdown)(struct ccwgroup_device *);
+ int (*prepare) (struct ccwgroup_device *);
+ void (*complete) (struct ccwgroup_device *);
+ int (*freeze)(struct ccwgroup_device *);
+ int (*thaw) (struct ccwgroup_device *);
+ int (*restore)(struct ccwgroup_device *);
};
struct qeth_vlan_vid {
@@ -771,7 +780,7 @@ struct qeth_card {
struct qeth_perf_stats perf_stats;
int read_or_write_problem;
struct qeth_osn_info osn_info;
- struct qeth_discipline discipline;
+ struct qeth_discipline *discipline;
atomic_t force_alloc_skb;
struct service_level qeth_service_level;
struct qdio_ssqd_desc ssqd;
@@ -837,16 +846,15 @@ static inline int qeth_is_diagass_supported(struct qeth_card *card,
return card->info.diagass_support & (__u32)cmd;
}
-extern struct ccwgroup_driver qeth_l2_ccwgroup_driver;
-extern struct ccwgroup_driver qeth_l3_ccwgroup_driver;
+extern struct qeth_discipline qeth_l2_discipline;
+extern struct qeth_discipline qeth_l3_discipline;
+extern const struct attribute_group *qeth_generic_attr_groups[];
+extern const struct attribute_group *qeth_osn_attr_groups[];
+
const char *qeth_get_cardname_short(struct qeth_card *);
int qeth_realloc_buffer_pool(struct qeth_card *, int);
int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id);
void qeth_core_free_discipline(struct qeth_card *);
-int qeth_core_create_device_attributes(struct device *);
-void qeth_core_remove_device_attributes(struct device *);
-int qeth_core_create_osn_attributes(struct device *);
-void qeth_core_remove_osn_attributes(struct device *);
void qeth_buffer_reclaim_work(struct work_struct *);
/* exports for qeth discipline device drivers */
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index e000001539bf..e118e1e1e1c1 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -1363,7 +1363,7 @@ static void qeth_start_kernel_thread(struct work_struct *work)
card->write.state != CH_STATE_UP)
return;
if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) {
- ts = kthread_run(card->discipline.recover, (void *)card,
+ ts = kthread_run(card->discipline->recover, (void *)card,
"qeth_recover");
if (IS_ERR(ts)) {
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
@@ -3337,7 +3337,7 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
if (rc) {
queue->card->stats.tx_errors += count;
/* ignore temporary SIGA errors without busy condition */
- if (rc == QDIO_ERROR_SIGA_TARGET)
+ if (rc == -ENOBUFS)
return;
QETH_CARD_TEXT(queue->card, 2, "flushbuf");
QETH_CARD_TEXT_(queue->card, 2, " q%d", queue->queue_no);
@@ -3531,7 +3531,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
int i;
QETH_CARD_TEXT(card, 6, "qdouhdl");
- if (qdio_error & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
+ if (qdio_error & QDIO_ERROR_FATAL) {
QETH_CARD_TEXT(card, 2, "achkcond");
netif_stop_queue(card->dev);
qeth_schedule_recovery(card);
@@ -4627,7 +4627,7 @@ static int qeth_qdio_establish(struct qeth_card *card)
goto out_free_in_sbals;
}
for (i = 0; i < card->qdio.no_in_queues; ++i)
- queue_start_poll[i] = card->discipline.start_poll;
+ queue_start_poll[i] = card->discipline->start_poll;
qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll);
@@ -4651,8 +4651,8 @@ static int qeth_qdio_establish(struct qeth_card *card)
init_data.qib_param_field = qib_param_field;
init_data.no_input_qs = card->qdio.no_in_queues;
init_data.no_output_qs = card->qdio.no_out_queues;
- init_data.input_handler = card->discipline.input_handler;
- init_data.output_handler = card->discipline.output_handler;
+ init_data.input_handler = card->discipline->input_handler;
+ init_data.output_handler = card->discipline->output_handler;
init_data.queue_start_poll_array = queue_start_poll;
init_data.int_parm = (unsigned long) card;
init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
@@ -4737,13 +4737,6 @@ static struct ccw_driver qeth_ccw_driver = {
.remove = ccwgroup_remove_ccwdev,
};
-static int qeth_core_driver_group(const char *buf, struct device *root_dev,
- unsigned long driver_id)
-{
- return ccwgroup_create_from_string(root_dev, driver_id,
- &qeth_ccw_driver, 3, buf);
-}
-
int qeth_core_hardsetup_card(struct qeth_card *card)
{
int retries = 0;
@@ -5040,17 +5033,15 @@ int qeth_core_load_discipline(struct qeth_card *card,
mutex_lock(&qeth_mod_mutex);
switch (discipline) {
case QETH_DISCIPLINE_LAYER3:
- card->discipline.ccwgdriver = try_then_request_module(
- symbol_get(qeth_l3_ccwgroup_driver),
- "qeth_l3");
+ card->discipline = try_then_request_module(
+ symbol_get(qeth_l3_discipline), "qeth_l3");
break;
case QETH_DISCIPLINE_LAYER2:
- card->discipline.ccwgdriver = try_then_request_module(
- symbol_get(qeth_l2_ccwgroup_driver),
- "qeth_l2");
+ card->discipline = try_then_request_module(
+ symbol_get(qeth_l2_discipline), "qeth_l2");
break;
}
- if (!card->discipline.ccwgdriver) {
+ if (!card->discipline) {
dev_err(&card->gdev->dev, "There is no kernel module to "
"support discipline %d\n", discipline);
rc = -EINVAL;
@@ -5062,12 +5053,21 @@ int qeth_core_load_discipline(struct qeth_card *card,
void qeth_core_free_discipline(struct qeth_card *card)
{
if (card->options.layer2)
- symbol_put(qeth_l2_ccwgroup_driver);
+ symbol_put(qeth_l2_discipline);
else
- symbol_put(qeth_l3_ccwgroup_driver);
- card->discipline.ccwgdriver = NULL;
+ symbol_put(qeth_l3_discipline);
+ card->discipline = NULL;
}
+static const struct device_type qeth_generic_devtype = {
+ .name = "qeth_generic",
+ .groups = qeth_generic_attr_groups,
+};
+static const struct device_type qeth_osn_devtype = {
+ .name = "qeth_osn",
+ .groups = qeth_osn_attr_groups,
+};
+
static int qeth_core_probe_device(struct ccwgroup_device *gdev)
{
struct qeth_card *card;
@@ -5122,18 +5122,17 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
}
if (card->info.type == QETH_CARD_TYPE_OSN)
- rc = qeth_core_create_osn_attributes(dev);
+ gdev->dev.type = &qeth_osn_devtype;
else
- rc = qeth_core_create_device_attributes(dev);
- if (rc)
- goto err_dbf;
+ gdev->dev.type = &qeth_generic_devtype;
+
switch (card->info.type) {
case QETH_CARD_TYPE_OSN:
case QETH_CARD_TYPE_OSM:
rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
if (rc)
- goto err_attr;
- rc = card->discipline.ccwgdriver->probe(card->gdev);
+ goto err_dbf;
+ rc = card->discipline->setup(card->gdev);
if (rc)
goto err_disc;
case QETH_CARD_TYPE_OSD:
@@ -5151,11 +5150,6 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
err_disc:
qeth_core_free_discipline(card);
-err_attr:
- if (card->info.type == QETH_CARD_TYPE_OSN)
- qeth_core_remove_osn_attributes(dev);
- else
- qeth_core_remove_device_attributes(dev);
err_dbf:
debug_unregister(card->debug);
err_card:
@@ -5172,14 +5166,8 @@ static void qeth_core_remove_device(struct ccwgroup_device *gdev)
QETH_DBF_TEXT(SETUP, 2, "removedv");
- if (card->info.type == QETH_CARD_TYPE_OSN) {
- qeth_core_remove_osn_attributes(&gdev->dev);
- } else {
- qeth_core_remove_device_attributes(&gdev->dev);
- }
-
- if (card->discipline.ccwgdriver) {
- card->discipline.ccwgdriver->remove(gdev);
+ if (card->discipline) {
+ card->discipline->remove(gdev);
qeth_core_free_discipline(card);
}
@@ -5199,7 +5187,7 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev)
int rc = 0;
int def_discipline;
- if (!card->discipline.ccwgdriver) {
+ if (!card->discipline) {
if (card->info.type == QETH_CARD_TYPE_IQD)
def_discipline = QETH_DISCIPLINE_LAYER3;
else
@@ -5207,11 +5195,11 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev)
rc = qeth_core_load_discipline(card, def_discipline);
if (rc)
goto err;
- rc = card->discipline.ccwgdriver->probe(card->gdev);
+ rc = card->discipline->setup(card->gdev);
if (rc)
goto err;
}
- rc = card->discipline.ccwgdriver->set_online(gdev);
+ rc = card->discipline->set_online(gdev);
err:
return rc;
}
@@ -5219,58 +5207,52 @@ err:
static int qeth_core_set_offline(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
- return card->discipline.ccwgdriver->set_offline(gdev);
+ return card->discipline->set_offline(gdev);
}
static void qeth_core_shutdown(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
- if (card->discipline.ccwgdriver &&
- card->discipline.ccwgdriver->shutdown)
- card->discipline.ccwgdriver->shutdown(gdev);
+ if (card->discipline && card->discipline->shutdown)
+ card->discipline->shutdown(gdev);
}
static int qeth_core_prepare(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
- if (card->discipline.ccwgdriver &&
- card->discipline.ccwgdriver->prepare)
- return card->discipline.ccwgdriver->prepare(gdev);
+ if (card->discipline && card->discipline->prepare)
+ return card->discipline->prepare(gdev);
return 0;
}
static void qeth_core_complete(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
- if (card->discipline.ccwgdriver &&
- card->discipline.ccwgdriver->complete)
- card->discipline.ccwgdriver->complete(gdev);
+ if (card->discipline && card->discipline->complete)
+ card->discipline->complete(gdev);
}
static int qeth_core_freeze(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
- if (card->discipline.ccwgdriver &&
- card->discipline.ccwgdriver->freeze)
- return card->discipline.ccwgdriver->freeze(gdev);
+ if (card->discipline && card->discipline->freeze)
+ return card->discipline->freeze(gdev);
return 0;
}
static int qeth_core_thaw(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
- if (card->discipline.ccwgdriver &&
- card->discipline.ccwgdriver->thaw)
- return card->discipline.ccwgdriver->thaw(gdev);
+ if (card->discipline && card->discipline->thaw)
+ return card->discipline->thaw(gdev);
return 0;
}
static int qeth_core_restore(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
- if (card->discipline.ccwgdriver &&
- card->discipline.ccwgdriver->restore)
- return card->discipline.ccwgdriver->restore(gdev);
+ if (card->discipline && card->discipline->restore)
+ return card->discipline->restore(gdev);
return 0;
}
@@ -5279,8 +5261,7 @@ static struct ccwgroup_driver qeth_core_ccwgroup_driver = {
.owner = THIS_MODULE,
.name = "qeth",
},
- .driver_id = 0xD8C5E3C8,
- .probe = qeth_core_probe_device,
+ .setup = qeth_core_probe_device,
.remove = qeth_core_remove_device,
.set_online = qeth_core_set_online,
.set_offline = qeth_core_set_offline,
@@ -5292,21 +5273,30 @@ static struct ccwgroup_driver qeth_core_ccwgroup_driver = {
.restore = qeth_core_restore,
};
-static ssize_t
-qeth_core_driver_group_store(struct device_driver *ddrv, const char *buf,
- size_t count)
+static ssize_t qeth_core_driver_group_store(struct device_driver *ddrv,
+ const char *buf, size_t count)
{
int err;
- err = qeth_core_driver_group(buf, qeth_core_root_dev,
- qeth_core_ccwgroup_driver.driver_id);
- if (err)
- return err;
- else
- return count;
-}
+ err = ccwgroup_create_dev(qeth_core_root_dev,
+ &qeth_core_ccwgroup_driver, 3, buf);
+
+ return err ? err : count;
+}
static DRIVER_ATTR(group, 0200, NULL, qeth_core_driver_group_store);
+static struct attribute *qeth_drv_attrs[] = {
+ &driver_attr_group.attr,
+ NULL,
+};
+static struct attribute_group qeth_drv_attr_group = {
+ .attrs = qeth_drv_attrs,
+};
+static const struct attribute_group *qeth_drv_attr_groups[] = {
+ &qeth_drv_attr_group,
+ NULL,
+};
+
static struct {
const char str[ETH_GSTRING_LEN];
} qeth_ethtool_stats_keys[] = {
@@ -5544,49 +5534,41 @@ static int __init qeth_core_init(void)
rc = qeth_register_dbf_views();
if (rc)
goto out_err;
- rc = ccw_driver_register(&qeth_ccw_driver);
- if (rc)
- goto ccw_err;
- rc = ccwgroup_driver_register(&qeth_core_ccwgroup_driver);
- if (rc)
- goto ccwgroup_err;
- rc = driver_create_file(&qeth_core_ccwgroup_driver.driver,
- &driver_attr_group);
- if (rc)
- goto driver_err;
qeth_core_root_dev = root_device_register("qeth");
rc = IS_ERR(qeth_core_root_dev) ? PTR_ERR(qeth_core_root_dev) : 0;
if (rc)
goto register_err;
-
qeth_core_header_cache = kmem_cache_create("qeth_hdr",
sizeof(struct qeth_hdr) + ETH_HLEN, 64, 0, NULL);
if (!qeth_core_header_cache) {
rc = -ENOMEM;
goto slab_err;
}
-
qeth_qdio_outbuf_cache = kmem_cache_create("qeth_buf",
sizeof(struct qeth_qdio_out_buffer), 0, 0, NULL);
if (!qeth_qdio_outbuf_cache) {
rc = -ENOMEM;
goto cqslab_err;
}
+ rc = ccw_driver_register(&qeth_ccw_driver);
+ if (rc)
+ goto ccw_err;
+ qeth_core_ccwgroup_driver.driver.groups = qeth_drv_attr_groups;
+ rc = ccwgroup_driver_register(&qeth_core_ccwgroup_driver);
+ if (rc)
+ goto ccwgroup_err;
return 0;
+
+ccwgroup_err:
+ ccw_driver_unregister(&qeth_ccw_driver);
+ccw_err:
+ kmem_cache_destroy(qeth_qdio_outbuf_cache);
cqslab_err:
kmem_cache_destroy(qeth_core_header_cache);
slab_err:
root_device_unregister(qeth_core_root_dev);
register_err:
- driver_remove_file(&qeth_core_ccwgroup_driver.driver,
- &driver_attr_group);
-driver_err:
- ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
-ccwgroup_err:
- ccw_driver_unregister(&qeth_ccw_driver);
-ccw_err:
- QETH_DBF_MESSAGE(2, "Initialization failed with code %d\n", rc);
qeth_unregister_dbf_views();
out_err:
pr_err("Initializing the qeth device driver failed\n");
@@ -5595,13 +5577,11 @@ out_err:
static void __exit qeth_core_exit(void)
{
- root_device_unregister(qeth_core_root_dev);
- driver_remove_file(&qeth_core_ccwgroup_driver.driver,
- &driver_attr_group);
ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
ccw_driver_unregister(&qeth_ccw_driver);
kmem_cache_destroy(qeth_qdio_outbuf_cache);
kmem_cache_destroy(qeth_core_header_cache);
+ root_device_unregister(qeth_core_root_dev);
qeth_unregister_dbf_views();
pr_info("core functions removed\n");
}
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
index 0a8e86c1b0ea..f163af575c48 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -434,8 +434,8 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
goto out;
else {
card->info.mac_bits = 0;
- if (card->discipline.ccwgdriver) {
- card->discipline.ccwgdriver->remove(card->gdev);
+ if (card->discipline) {
+ card->discipline->remove(card->gdev);
qeth_core_free_discipline(card);
}
}
@@ -444,7 +444,7 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
if (rc)
goto out;
- rc = card->discipline.ccwgdriver->probe(card->gdev);
+ rc = card->discipline->setup(card->gdev);
out:
mutex_unlock(&card->discipline_mutex);
return rc ? rc : count;
@@ -693,7 +693,6 @@ static struct attribute *qeth_blkt_device_attrs[] = {
&dev_attr_inter_jumbo.attr,
NULL,
};
-
static struct attribute_group qeth_device_blkt_group = {
.name = "blkt",
.attrs = qeth_blkt_device_attrs,
@@ -716,11 +715,16 @@ static struct attribute *qeth_device_attrs[] = {
&dev_attr_hw_trap.attr,
NULL,
};
-
static struct attribute_group qeth_device_attr_group = {
.attrs = qeth_device_attrs,
};
+const struct attribute_group *qeth_generic_attr_groups[] = {
+ &qeth_device_attr_group,
+ &qeth_device_blkt_group,
+ NULL,
+};
+
static struct attribute *qeth_osn_device_attrs[] = {
&dev_attr_state.attr,
&dev_attr_chpid.attr,
@@ -730,37 +734,10 @@ static struct attribute *qeth_osn_device_attrs[] = {
&dev_attr_recover.attr,
NULL,
};
-
static struct attribute_group qeth_osn_device_attr_group = {
.attrs = qeth_osn_device_attrs,
};
-
-int qeth_core_create_device_attributes(struct device *dev)
-{
- int ret;
- ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group);
- if (ret)
- return ret;
- ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group);
- if (ret)
- sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
-
- return 0;
-}
-
-void qeth_core_remove_device_attributes(struct device *dev)
-{
- sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
- sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group);
-}
-
-int qeth_core_create_osn_attributes(struct device *dev)
-{
- return sysfs_create_group(&dev->kobj, &qeth_osn_device_attr_group);
-}
-
-void qeth_core_remove_osn_attributes(struct device *dev)
-{
- sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group);
- return;
-}
+const struct attribute_group *qeth_osn_attr_groups[] = {
+ &qeth_osn_device_attr_group,
+ NULL,
+};
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 0e7c29d1d7ef..426986518e96 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -882,12 +882,6 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
INIT_LIST_HEAD(&card->mc_list);
card->options.layer2 = 1;
card->info.hwtrap = 0;
- card->discipline.start_poll = qeth_qdio_start_poll;
- card->discipline.input_handler = (qdio_handler_t *)
- qeth_qdio_input_handler;
- card->discipline.output_handler = (qdio_handler_t *)
- qeth_qdio_output_handler;
- card->discipline.recover = qeth_l2_recover;
return 0;
}
@@ -1227,8 +1221,12 @@ out:
return rc;
}
-struct ccwgroup_driver qeth_l2_ccwgroup_driver = {
- .probe = qeth_l2_probe_device,
+struct qeth_discipline qeth_l2_discipline = {
+ .start_poll = qeth_qdio_start_poll,
+ .input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
+ .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
+ .recover = qeth_l2_recover,
+ .setup = qeth_l2_probe_device,
.remove = qeth_l2_remove_device,
.set_online = qeth_l2_set_online,
.set_offline = qeth_l2_set_offline,
@@ -1237,7 +1235,7 @@ struct ccwgroup_driver qeth_l2_ccwgroup_driver = {
.thaw = qeth_l2_pm_resume,
.restore = qeth_l2_pm_resume,
};
-EXPORT_SYMBOL_GPL(qeth_l2_ccwgroup_driver);
+EXPORT_SYMBOL_GPL(qeth_l2_discipline);
static int qeth_osn_send_control_data(struct qeth_card *card, int len,
struct qeth_cmd_buffer *iob)
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index e7ad03209cb2..7be5e9775691 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -3298,12 +3298,6 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
qeth_l3_create_device_attributes(&gdev->dev);
card->options.layer2 = 0;
card->info.hwtrap = 0;
- card->discipline.start_poll = qeth_qdio_start_poll;
- card->discipline.input_handler = (qdio_handler_t *)
- qeth_qdio_input_handler;
- card->discipline.output_handler = (qdio_handler_t *)
- qeth_qdio_output_handler;
- card->discipline.recover = qeth_l3_recover;
return 0;
}
@@ -3578,8 +3572,12 @@ out:
return rc;
}
-struct ccwgroup_driver qeth_l3_ccwgroup_driver = {
- .probe = qeth_l3_probe_device,
+struct qeth_discipline qeth_l3_discipline = {
+ .start_poll = qeth_qdio_start_poll,
+ .input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
+ .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
+ .recover = qeth_l3_recover,
+ .setup = qeth_l3_probe_device,
.remove = qeth_l3_remove_device,
.set_online = qeth_l3_set_online,
.set_offline = qeth_l3_set_offline,
@@ -3588,7 +3586,7 @@ struct ccwgroup_driver qeth_l3_ccwgroup_driver = {
.thaw = qeth_l3_pm_resume,
.restore = qeth_l3_pm_resume,
};
-EXPORT_SYMBOL_GPL(qeth_l3_ccwgroup_driver);
+EXPORT_SYMBOL_GPL(qeth_l3_discipline);
static int qeth_l3_ip_event(struct notifier_block *this,
unsigned long event, void *ptr)
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 7a66d0e97dd3..e9559782d3ec 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -408,6 +408,7 @@ config BLK_DEV_3W_XXXX_RAID
config SCSI_HPSA
tristate "HP Smart Array SCSI driver"
depends on PCI && SCSI
+ select CHECK_SIGNATURE
help
This driver supports HP Smart Array Controllers (circa 2009).
It is a SCSI alternative to the cciss driver, which is a block
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c
index 2bee51506a91..762820636304 100644
--- a/drivers/scsi/aacraid/src.c
+++ b/drivers/scsi/aacraid/src.c
@@ -424,6 +424,8 @@ static int aac_src_deliver_message(struct fib *fib)
static int aac_src_ioremap(struct aac_dev *dev, u32 size)
{
if (!size) {
+ iounmap(dev->regs.src.bar1);
+ dev->regs.src.bar1 = NULL;
iounmap(dev->regs.src.bar0);
dev->base = dev->regs.src.bar0 = NULL;
return 0;
diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c
index 390168f62a13..5fdca93892ad 100644
--- a/drivers/scsi/aic94xx/aic94xx_seq.c
+++ b/drivers/scsi/aic94xx/aic94xx_seq.c
@@ -1228,8 +1228,7 @@ static int asd_seq_start_lseq(struct asd_ha_struct *asd_ha, int lseq)
int asd_release_firmware(void)
{
- if (sequencer_fw)
- release_firmware(sequencer_fw);
+ release_firmware(sequencer_fw);
return 0;
}
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index 04a154f87e3e..df740cbbaef4 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -572,7 +572,7 @@ static void falcon_get_lock(void)
}
-int __init atari_scsi_detect(struct scsi_host_template *host)
+static int __init atari_scsi_detect(struct scsi_host_template *host)
{
static int called = 0;
struct Scsi_Host *instance;
@@ -724,7 +724,7 @@ int __init atari_scsi_detect(struct scsi_host_template *host)
return 1;
}
-int atari_scsi_release(struct Scsi_Host *sh)
+static int atari_scsi_release(struct Scsi_Host *sh)
{
if (IS_A_TT())
free_irq(IRQ_TT_MFP_SCSI, sh);
@@ -734,17 +734,21 @@ int atari_scsi_release(struct Scsi_Host *sh)
return 1;
}
-void __init atari_scsi_setup(char *str, int *ints)
+#ifndef MODULE
+static int __init atari_scsi_setup(char *str)
{
/* Format of atascsi parameter is:
* atascsi=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
* Defaults depend on TT or Falcon, hostid determined at run time.
* Negative values mean don't change.
*/
+ int ints[6];
+
+ get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] < 1) {
printk("atari_scsi_setup: no arguments!\n");
- return;
+ return 0;
}
if (ints[0] >= 1) {
@@ -777,9 +781,14 @@ void __init atari_scsi_setup(char *str, int *ints)
setup_use_tagged_queuing = !!ints[5];
}
#endif
+
+ return 1;
}
-int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
+__setup("atascsi=", atari_scsi_setup);
+#endif /* !MODULE */
+
+static int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
{
int rv;
struct NCR5380_hostdata *hostdata =
@@ -852,7 +861,7 @@ static void __init atari_scsi_reset_boot(void)
#endif
-const char *atari_scsi_info(struct Scsi_Host *host)
+static const char *atari_scsi_info(struct Scsi_Host *host)
{
/* atari_scsi_detect() is verbose enough... */
static const char string[] = "Atari native SCSI";
@@ -862,8 +871,9 @@ const char *atari_scsi_info(struct Scsi_Host *host)
#if defined(REAL_DMA)
-unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance, void *data,
- unsigned long count, int dir)
+static unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance,
+ void *data, unsigned long count,
+ int dir)
{
unsigned long addr = virt_to_phys(data);
diff --git a/drivers/scsi/atari_scsi.h b/drivers/scsi/atari_scsi.h
index efadb8d567c2..bd52df78b209 100644
--- a/drivers/scsi/atari_scsi.h
+++ b/drivers/scsi/atari_scsi.h
@@ -18,11 +18,6 @@
/* (I_HAVE_OVERRUNS stuff removed) */
#ifndef ASM
-int atari_scsi_detect (struct scsi_host_template *);
-const char *atari_scsi_info (struct Scsi_Host *);
-int atari_scsi_reset (Scsi_Cmnd *, unsigned int);
-int atari_scsi_release (struct Scsi_Host *);
-
/* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. Higher
* values should work, too; try it! (but cmd_per_lun costs memory!) */
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h
index 1d7b976c850f..a50b6a9030e8 100644
--- a/drivers/scsi/be2iscsi/be.h
+++ b/drivers/scsi/be2iscsi/be.h
@@ -132,10 +132,6 @@ struct be_ctrl_info {
((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \
(size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K))
-/* Byte offset into the page corresponding to given address */
-#define OFFSET_IN_PAGE(addr) \
- ((size_t)(addr) & (PAGE_SIZE_4K-1))
-
/* Returns bit offset within a DWORD of a bitfield */
#define AMAP_BIT_OFFSET(_struct, field) \
(((size_t)&(((_struct *)0)->field))%32)
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index cdb15364bc69..d2e9e933f7a3 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -15,6 +15,8 @@
* Costa Mesa, CA 92626
*/
+#include <scsi/iscsi_proto.h>
+
#include "be.h"
#include "be_mgmt.h"
#include "be_main.h"
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
index 8b40a5b4366c..b0b36c6a145f 100644
--- a/drivers/scsi/be2iscsi/be_cmds.h
+++ b/drivers/scsi/be2iscsi/be_cmds.h
@@ -23,7 +23,7 @@
* firmware in the BE. These requests are communicated to the processor
* using Work Request Blocks (WRBs) submitted to the MCC-WRB ring or via one
* WRB inside a MAILBOX.
- * The commands are serviced by the ARM processor in the BladeEngine's MPU.
+ * The commands are serviced by the ARM processor in the OneConnect's MPU.
*/
struct be_sge {
u32 pa_lo;
@@ -163,7 +163,8 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES 3
#define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG 7
#define OPCODE_COMMON_ISCSI_NTWK_SET_VLAN 14
-#define OPCODE_COMMON_ISCSI_NTWK_CONFIGURE_STATELESS_IP_ADDR 17
+#define OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR 17
+#define OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR 18
#define OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR 21
#define OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY 22
#define OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY 23
@@ -274,15 +275,15 @@ struct mgmt_conn_login_options {
struct mgmt_auth_method_format auth_data;
} __packed;
-struct ip_address_format {
+struct ip_addr_format {
u16 size_of_structure;
u8 reserved;
u8 ip_type;
- u8 ip_address[16];
+ u8 addr[16];
u32 rsvd0;
} __packed;
-struct mgmt_conn_info {
+struct mgmt_conn_info {
u32 connection_handle;
u32 connection_status;
u16 src_port;
@@ -290,9 +291,9 @@ struct mgmt_conn_info {
u16 dest_port_redirected;
u16 cid;
u32 estimated_throughput;
- struct ip_address_format src_ipaddr;
- struct ip_address_format dest_ipaddr;
- struct ip_address_format dest_ipaddr_redirected;
+ struct ip_addr_format src_ipaddr;
+ struct ip_addr_format dest_ipaddr;
+ struct ip_addr_format dest_ipaddr_redirected;
struct mgmt_conn_login_options negotiated_login_options;
} __packed;
@@ -322,43 +323,115 @@ struct mgmt_session_info {
struct mgmt_conn_info conn_list[1];
} __packed;
-struct be_cmd_req_get_session {
+struct be_cmd_get_session_req {
struct be_cmd_req_hdr hdr;
u32 session_handle;
} __packed;
-struct be_cmd_resp_get_session {
+struct be_cmd_get_session_resp {
struct be_cmd_resp_hdr hdr;
struct mgmt_session_info session_info;
} __packed;
struct mac_addr {
- u16 size_of_struct;
+ u16 size_of_structure;
u8 addr[ETH_ALEN];
} __packed;
-struct be_cmd_req_get_boot_target {
+struct be_cmd_get_boot_target_req {
struct be_cmd_req_hdr hdr;
} __packed;
-struct be_cmd_resp_get_boot_target {
+struct be_cmd_get_boot_target_resp {
struct be_cmd_resp_hdr hdr;
u32 boot_session_count;
int boot_session_handle;
};
-struct be_cmd_req_mac_query {
+struct be_cmd_mac_query_req {
struct be_cmd_req_hdr hdr;
u8 type;
u8 permanent;
u16 if_id;
} __packed;
-struct be_cmd_resp_mac_query {
+struct be_cmd_get_mac_resp {
struct be_cmd_resp_hdr hdr;
struct mac_addr mac;
};
+struct be_ip_addr_subnet_format {
+ u16 size_of_structure;
+ u8 ip_type;
+ u8 ipv6_prefix_length;
+ u8 addr[16];
+ u8 subnet_mask[16];
+ u32 rsvd0;
+} __packed;
+
+struct be_cmd_get_if_info_req {
+ struct be_cmd_req_hdr hdr;
+ u32 interface_hndl;
+ u32 ip_type;
+} __packed;
+
+struct be_cmd_get_if_info_resp {
+ struct be_cmd_req_hdr hdr;
+ u32 interface_hndl;
+ u32 vlan_priority;
+ u32 ip_addr_count;
+ u32 dhcp_state;
+ struct be_ip_addr_subnet_format ip_addr;
+} __packed;
+
+struct be_ip_addr_record {
+ u32 action;
+ u32 interface_hndl;
+ struct be_ip_addr_subnet_format ip_addr;
+ u32 status;
+} __packed;
+
+struct be_ip_addr_record_params {
+ u32 record_entry_count;
+ struct be_ip_addr_record ip_record;
+} __packed;
+
+struct be_cmd_set_ip_addr_req {
+ struct be_cmd_req_hdr hdr;
+ struct be_ip_addr_record_params ip_params;
+} __packed;
+
+
+struct be_cmd_set_dhcp_req {
+ struct be_cmd_req_hdr hdr;
+ u32 interface_hndl;
+ u32 ip_type;
+ u32 flags;
+ u32 retry_count;
+} __packed;
+
+struct be_cmd_rel_dhcp_req {
+ struct be_cmd_req_hdr hdr;
+ u32 interface_hndl;
+ u32 ip_type;
+} __packed;
+
+struct be_cmd_set_def_gateway_req {
+ struct be_cmd_req_hdr hdr;
+ u32 action;
+ struct ip_addr_format ip_addr;
+} __packed;
+
+struct be_cmd_get_def_gateway_req {
+ struct be_cmd_req_hdr hdr;
+ u32 ip_type;
+} __packed;
+
+struct be_cmd_get_def_gateway_resp {
+ struct be_cmd_req_hdr hdr;
+ struct ip_addr_format ip_addr;
+} __packed;
+
/******************** Create CQ ***************************/
/**
* Pseudo amap definition in which each bit of the actual structure is defined
@@ -489,7 +562,7 @@ struct be_cmd_req_modify_eq_delay {
#define ETH_ALEN 6
-struct be_cmd_req_get_mac_addr {
+struct be_cmd_get_nic_conf_req {
struct be_cmd_req_hdr hdr;
u32 nic_port_count;
u32 speed;
@@ -501,7 +574,7 @@ struct be_cmd_req_get_mac_addr {
u32 rsvd[23];
};
-struct be_cmd_resp_get_mac_addr {
+struct be_cmd_get_nic_conf_resp {
struct be_cmd_resp_hdr hdr;
u32 nic_port_count;
u32 speed;
@@ -513,6 +586,39 @@ struct be_cmd_resp_get_mac_addr {
u32 rsvd[23];
};
+#define BEISCSI_ALIAS_LEN 32
+
+struct be_cmd_hba_name {
+ struct be_cmd_req_hdr hdr;
+ u16 flags;
+ u16 rsvd0;
+ u8 initiator_name[ISCSI_NAME_LEN];
+ u8 initiator_alias[BEISCSI_ALIAS_LEN];
+} __packed;
+
+struct be_cmd_ntwk_link_status_req {
+ struct be_cmd_req_hdr hdr;
+ u32 rsvd0;
+} __packed;
+
+/*** Port Speed Values ***/
+#define BE2ISCSI_LINK_SPEED_ZERO 0x00
+#define BE2ISCSI_LINK_SPEED_10MBPS 0x01
+#define BE2ISCSI_LINK_SPEED_100MBPS 0x02
+#define BE2ISCSI_LINK_SPEED_1GBPS 0x03
+#define BE2ISCSI_LINK_SPEED_10GBPS 0x04
+struct be_cmd_ntwk_link_status_resp {
+ struct be_cmd_resp_hdr hdr;
+ u8 phys_port;
+ u8 mac_duplex;
+ u8 mac_speed;
+ u8 mac_fault;
+ u8 mgmt_mac_duplex;
+ u8 mgmt_mac_speed;
+ u16 qos_link_speed;
+ u32 logical_link_speed;
+} __packed;
+
int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
struct be_queue_info *eq, int eq_delay);
@@ -530,11 +636,8 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba,
int be_poll_mcc(struct be_ctrl_info *ctrl);
int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba);
-unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba);
-unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba);
-unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba,
- u32 boot_session_handle,
- struct be_dma_mem *nonemb_cmd);
+unsigned int be_cmd_get_initname(struct beiscsi_hba *phba);
+unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba);
void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag);
/*ISCSI Functuions */
@@ -715,7 +818,7 @@ struct be_eq_delay_params_in {
struct tcp_connect_and_offload_in {
struct be_cmd_req_hdr hdr;
- struct ip_address_format ip_address;
+ struct ip_addr_format ip_address;
u16 tcp_port;
u16 cid;
u16 cq_id;
@@ -792,13 +895,14 @@ struct be_fw_cfg {
u32 function_caps;
} __packed;
-struct be_all_if_id {
+struct be_cmd_get_all_if_id_req {
struct be_cmd_req_hdr hdr;
u32 if_count;
u32 if_hndl_list[1];
} __packed;
#define ISCSI_OPCODE_SCSI_DATA_OUT 5
+#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY 5
#define OPCODE_COMMON_MODIFY_EQ_DELAY 41
#define OPCODE_COMMON_ISCSI_CLEANUP 59
#define OPCODE_COMMON_TCP_UPLOAD 56
@@ -810,6 +914,8 @@ struct be_all_if_id {
#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41
#define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42
#define OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET 52
+#define OPCODE_COMMON_WRITE_FLASH 96
+#define OPCODE_COMMON_READ_FLASH 97
/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */
#define CMD_ISCSI_COMMAND_INVALIDATE 1
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index 33c8f09c7ac1..43f35034585d 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -23,6 +23,8 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_netlink.h>
+#include <net/netlink.h>
#include <scsi/scsi.h>
#include "be_iscsi.h"
@@ -207,6 +209,301 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid);
}
+static int beiscsi_create_ipv4_iface(struct beiscsi_hba *phba)
+{
+ if (phba->ipv4_iface)
+ return 0;
+
+ phba->ipv4_iface = iscsi_create_iface(phba->shost,
+ &beiscsi_iscsi_transport,
+ ISCSI_IFACE_TYPE_IPV4,
+ 0, 0);
+ if (!phba->ipv4_iface) {
+ shost_printk(KERN_ERR, phba->shost, "Could not "
+ "create default IPv4 address.\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba)
+{
+ if (phba->ipv6_iface)
+ return 0;
+
+ phba->ipv6_iface = iscsi_create_iface(phba->shost,
+ &beiscsi_iscsi_transport,
+ ISCSI_IFACE_TYPE_IPV6,
+ 0, 0);
+ if (!phba->ipv6_iface) {
+ shost_printk(KERN_ERR, phba->shost, "Could not "
+ "create default IPv6 address.\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+void beiscsi_create_def_ifaces(struct beiscsi_hba *phba)
+{
+ struct be_cmd_get_if_info_resp if_info;
+
+ if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info))
+ beiscsi_create_ipv4_iface(phba);
+
+ if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info))
+ beiscsi_create_ipv6_iface(phba);
+}
+
+void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba)
+{
+ if (phba->ipv6_iface)
+ iscsi_destroy_iface(phba->ipv6_iface);
+ if (phba->ipv4_iface)
+ iscsi_destroy_iface(phba->ipv4_iface);
+}
+
+static int
+beiscsi_set_static_ip(struct Scsi_Host *shost,
+ struct iscsi_iface_param_info *iface_param,
+ void *data, uint32_t dt_len)
+{
+ struct beiscsi_hba *phba = iscsi_host_priv(shost);
+ struct iscsi_iface_param_info *iface_ip = NULL;
+ struct iscsi_iface_param_info *iface_subnet = NULL;
+ struct nlattr *nla;
+ int ret;
+
+
+ switch (iface_param->param) {
+ case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
+ nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
+ if (nla)
+ iface_ip = nla_data(nla);
+
+ nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
+ if (nla)
+ iface_subnet = nla_data(nla);
+ break;
+ case ISCSI_NET_PARAM_IPV4_ADDR:
+ iface_ip = iface_param;
+ nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
+ if (nla)
+ iface_subnet = nla_data(nla);
+ break;
+ case ISCSI_NET_PARAM_IPV4_SUBNET:
+ iface_subnet = iface_param;
+ nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
+ if (nla)
+ iface_ip = nla_data(nla);
+ break;
+ default:
+ shost_printk(KERN_ERR, shost, "Unsupported param %d\n",
+ iface_param->param);
+ }
+
+ if (!iface_ip || !iface_subnet) {
+ shost_printk(KERN_ERR, shost, "IP and Subnet Mask required\n");
+ return -EINVAL;
+ }
+
+ ret = mgmt_set_ip(phba, iface_ip, iface_subnet,
+ ISCSI_BOOTPROTO_STATIC);
+
+ return ret;
+}
+
+static int
+beiscsi_set_ipv4(struct Scsi_Host *shost,
+ struct iscsi_iface_param_info *iface_param,
+ void *data, uint32_t dt_len)
+{
+ struct beiscsi_hba *phba = iscsi_host_priv(shost);
+ int ret = 0;
+
+ /* Check the param */
+ switch (iface_param->param) {
+ case ISCSI_NET_PARAM_IPV4_GW:
+ ret = mgmt_set_gateway(phba, iface_param);
+ break;
+ case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
+ if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP)
+ ret = mgmt_set_ip(phba, iface_param,
+ NULL, ISCSI_BOOTPROTO_DHCP);
+ else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC)
+ ret = beiscsi_set_static_ip(shost, iface_param,
+ data, dt_len);
+ else
+ shost_printk(KERN_ERR, shost, "Invalid BOOTPROTO: %d\n",
+ iface_param->value[0]);
+ break;
+ case ISCSI_NET_PARAM_IFACE_ENABLE:
+ if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
+ ret = beiscsi_create_ipv4_iface(phba);
+ else
+ iscsi_destroy_iface(phba->ipv4_iface);
+ break;
+ case ISCSI_NET_PARAM_IPV4_SUBNET:
+ case ISCSI_NET_PARAM_IPV4_ADDR:
+ ret = beiscsi_set_static_ip(shost, iface_param,
+ data, dt_len);
+ break;
+ default:
+ shost_printk(KERN_ERR, shost, "Param %d not supported\n",
+ iface_param->param);
+ }
+
+ return ret;
+}
+
+static int
+beiscsi_set_ipv6(struct Scsi_Host *shost,
+ struct iscsi_iface_param_info *iface_param,
+ void *data, uint32_t dt_len)
+{
+ struct beiscsi_hba *phba = iscsi_host_priv(shost);
+ int ret = 0;
+
+ switch (iface_param->param) {
+ case ISCSI_NET_PARAM_IFACE_ENABLE:
+ if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
+ ret = beiscsi_create_ipv6_iface(phba);
+ else {
+ iscsi_destroy_iface(phba->ipv6_iface);
+ ret = 0;
+ }
+ break;
+ case ISCSI_NET_PARAM_IPV6_ADDR:
+ ret = mgmt_set_ip(phba, iface_param, NULL,
+ ISCSI_BOOTPROTO_STATIC);
+ break;
+ default:
+ shost_printk(KERN_ERR, shost, "Param %d not supported\n",
+ iface_param->param);
+ }
+
+ return ret;
+}
+
+int be2iscsi_iface_set_param(struct Scsi_Host *shost,
+ void *data, uint32_t dt_len)
+{
+ struct iscsi_iface_param_info *iface_param = NULL;
+ struct nlattr *attrib;
+ uint32_t rm_len = dt_len;
+ int ret = 0 ;
+
+ nla_for_each_attr(attrib, data, dt_len, rm_len) {
+ iface_param = nla_data(attrib);
+
+ if (iface_param->param_type != ISCSI_NET_PARAM)
+ continue;
+
+ /*
+ * BE2ISCSI only supports 1 interface
+ */
+ if (iface_param->iface_num) {
+ shost_printk(KERN_ERR, shost, "Invalid iface_num %d."
+ "Only iface_num 0 is supported.\n",
+ iface_param->iface_num);
+ return -EINVAL;
+ }
+
+ switch (iface_param->iface_type) {
+ case ISCSI_IFACE_TYPE_IPV4:
+ ret = beiscsi_set_ipv4(shost, iface_param,
+ data, dt_len);
+ break;
+ case ISCSI_IFACE_TYPE_IPV6:
+ ret = beiscsi_set_ipv6(shost, iface_param,
+ data, dt_len);
+ break;
+ default:
+ shost_printk(KERN_ERR, shost,
+ "Invalid iface type :%d passed\n",
+ iface_param->iface_type);
+ break;
+ }
+
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
+ struct iscsi_iface *iface, int param,
+ char *buf)
+{
+ struct be_cmd_get_if_info_resp if_info;
+ int len, ip_type = BE2_IPV4;
+
+ memset(&if_info, 0, sizeof(if_info));
+
+ if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
+ ip_type = BE2_IPV6;
+
+ len = mgmt_get_if_info(phba, ip_type, &if_info);
+ if (len)
+ return len;
+
+ switch (param) {
+ case ISCSI_NET_PARAM_IPV4_ADDR:
+ len = sprintf(buf, "%pI4\n", &if_info.ip_addr.addr);
+ break;
+ case ISCSI_NET_PARAM_IPV6_ADDR:
+ len = sprintf(buf, "%pI6\n", &if_info.ip_addr.addr);
+ break;
+ case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
+ if (!if_info.dhcp_state)
+ len = sprintf(buf, "static");
+ else
+ len = sprintf(buf, "dhcp");
+ break;
+ case ISCSI_NET_PARAM_IPV4_SUBNET:
+ len = sprintf(buf, "%pI4\n", &if_info.ip_addr.subnet_mask);
+ break;
+ default:
+ WARN_ON(1);
+ }
+
+ return len;
+}
+
+int be2iscsi_iface_get_param(struct iscsi_iface *iface,
+ enum iscsi_param_type param_type,
+ int param, char *buf)
+{
+ struct Scsi_Host *shost = iscsi_iface_to_shost(iface);
+ struct beiscsi_hba *phba = iscsi_host_priv(shost);
+ struct be_cmd_get_def_gateway_resp gateway;
+ int len = -ENOSYS;
+
+ switch (param) {
+ case ISCSI_NET_PARAM_IPV4_ADDR:
+ case ISCSI_NET_PARAM_IPV4_SUBNET:
+ case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
+ case ISCSI_NET_PARAM_IPV6_ADDR:
+ len = be2iscsi_get_if_param(phba, iface, param, buf);
+ break;
+ case ISCSI_NET_PARAM_IFACE_ENABLE:
+ len = sprintf(buf, "enabled");
+ break;
+ case ISCSI_NET_PARAM_IPV4_GW:
+ memset(&gateway, 0, sizeof(gateway));
+ len = mgmt_get_gateway(phba, BE2_IPV4, &gateway);
+ if (!len)
+ len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr);
+ break;
+ default:
+ len = -ENOSYS;
+ }
+
+ return len;
+}
+
/**
* beiscsi_ep_get_param - get the iscsi parameter
* @ep: pointer to iscsi ep
@@ -221,7 +518,7 @@ int beiscsi_ep_get_param(struct iscsi_endpoint *ep,
struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
int len = 0;
- SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_param, param= %d\n", param);
+ SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_get_param, param= %d\n", param);
switch (param) {
case ISCSI_PARAM_CONN_PORT:
@@ -279,6 +576,121 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
}
/**
+ * beiscsi_get_initname - Read Initiator Name from flash
+ * @buf: buffer bointer
+ * @phba: The device priv structure instance
+ *
+ * returns number of bytes
+ */
+static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba)
+{
+ int rc;
+ unsigned int tag, wrb_num;
+ unsigned short status, extd_status;
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_hba_name *resp;
+ struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+
+ tag = be_cmd_get_initname(phba);
+ if (!tag) {
+ SE_DEBUG(DBG_LVL_1, "Getting Initiator Name Failed\n");
+ return -EBUSY;
+ } else
+ wait_event_interruptible(phba->ctrl.mcc_wait[tag],
+ phba->ctrl.mcc_numtag[tag]);
+
+ wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
+ extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
+ status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+
+ if (status || extd_status) {
+ SE_DEBUG(DBG_LVL_1, "MailBox Command Failed with "
+ "status = %d extd_status = %d\n",
+ status, extd_status);
+ free_mcc_tag(&phba->ctrl, tag);
+ return -EAGAIN;
+ }
+ wrb = queue_get_wrb(mccq, wrb_num);
+ free_mcc_tag(&phba->ctrl, tag);
+ resp = embedded_payload(wrb);
+ rc = sprintf(buf, "%s\n", resp->initiator_name);
+ return rc;
+}
+
+/**
+ * beiscsi_get_port_state - Get the Port State
+ * @shost : pointer to scsi_host structure
+ *
+ * returns number of bytes
+ */
+static void beiscsi_get_port_state(struct Scsi_Host *shost)
+{
+ struct beiscsi_hba *phba = iscsi_host_priv(shost);
+ struct iscsi_cls_host *ihost = shost->shost_data;
+
+ ihost->port_state = (phba->state == BE_ADAPTER_UP) ?
+ ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN;
+}
+
+/**
+ * beiscsi_get_port_speed - Get the Port Speed from Adapter
+ * @shost : pointer to scsi_host structure
+ *
+ * returns Success/Failure
+ */
+static int beiscsi_get_port_speed(struct Scsi_Host *shost)
+{
+ unsigned int tag, wrb_num;
+ unsigned short status, extd_status;
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_ntwk_link_status_resp *resp;
+ struct beiscsi_hba *phba = iscsi_host_priv(shost);
+ struct iscsi_cls_host *ihost = shost->shost_data;
+ struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+
+ tag = be_cmd_get_port_speed(phba);
+ if (!tag) {
+ SE_DEBUG(DBG_LVL_1, "Getting Port Speed Failed\n");
+ return -EBUSY;
+ } else
+ wait_event_interruptible(phba->ctrl.mcc_wait[tag],
+ phba->ctrl.mcc_numtag[tag]);
+
+ wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
+ extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
+ status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+
+ if (status || extd_status) {
+ SE_DEBUG(DBG_LVL_1, "MailBox Command Failed with "
+ "status = %d extd_status = %d\n",
+ status, extd_status);
+ free_mcc_tag(&phba->ctrl, tag);
+ return -EAGAIN;
+ }
+ wrb = queue_get_wrb(mccq, wrb_num);
+ free_mcc_tag(&phba->ctrl, tag);
+ resp = embedded_payload(wrb);
+
+ switch (resp->mac_speed) {
+ case BE2ISCSI_LINK_SPEED_10MBPS:
+ ihost->port_speed = ISCSI_PORT_SPEED_10MBPS;
+ break;
+ case BE2ISCSI_LINK_SPEED_100MBPS:
+ ihost->port_speed = BE2ISCSI_LINK_SPEED_100MBPS;
+ break;
+ case BE2ISCSI_LINK_SPEED_1GBPS:
+ ihost->port_speed = ISCSI_PORT_SPEED_1GBPS;
+ break;
+ case BE2ISCSI_LINK_SPEED_10GBPS:
+ ihost->port_speed = ISCSI_PORT_SPEED_10GBPS;
+ break;
+ default:
+ ihost->port_speed = ISCSI_PORT_SPEED_UNKNOWN;
+ }
+ return 0;
+}
+
+/**
* beiscsi_get_host_param - get the iscsi parameter
* @shost: pointer to scsi_host structure
* @param: parameter type identifier
@@ -301,6 +713,27 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
return status;
}
break;
+ case ISCSI_HOST_PARAM_INITIATOR_NAME:
+ status = beiscsi_get_initname(buf, phba);
+ if (status < 0) {
+ SE_DEBUG(DBG_LVL_1,
+ "Retreiving Initiator Name Failed\n");
+ return status;
+ }
+ break;
+ case ISCSI_HOST_PARAM_PORT_STATE:
+ beiscsi_get_port_state(shost);
+ status = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost));
+ break;
+ case ISCSI_HOST_PARAM_PORT_SPEED:
+ status = beiscsi_get_port_speed(shost);
+ if (status) {
+ SE_DEBUG(DBG_LVL_1,
+ "Retreiving Port Speed Failed\n");
+ return status;
+ }
+ status = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost));
+ break;
default:
return iscsi_host_get_param(shost, param, buf);
}
@@ -309,46 +742,21 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba)
{
- struct be_cmd_resp_get_mac_addr *resp;
- struct be_mcc_wrb *wrb;
- unsigned int tag, wrb_num;
- unsigned short status, extd_status;
- struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+ struct be_cmd_get_nic_conf_resp resp;
int rc;
- if (phba->read_mac_address)
- return sysfs_format_mac(buf, phba->mac_address,
- ETH_ALEN);
+ if (strlen(phba->mac_address))
+ return strlcpy(buf, phba->mac_address, PAGE_SIZE);
- tag = be_cmd_get_mac_addr(phba);
- if (!tag) {
- SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n");
- return -EBUSY;
- } else
- wait_event_interruptible(phba->ctrl.mcc_wait[tag],
- phba->ctrl.mcc_numtag[tag]);
+ memset(&resp, 0, sizeof(resp));
+ rc = mgmt_get_nic_conf(phba, &resp);
+ if (rc)
+ return rc;
- wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
- extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
- status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
- if (status || extd_status) {
- SE_DEBUG(DBG_LVL_1, "Failed to get be_cmd_get_mac_addr"
- " status = %d extd_status = %d\n",
- status, extd_status);
- free_mcc_tag(&phba->ctrl, tag);
- return -EAGAIN;
- }
- wrb = queue_get_wrb(mccq, wrb_num);
- free_mcc_tag(&phba->ctrl, tag);
- resp = embedded_payload(wrb);
- memcpy(phba->mac_address, resp->mac_address, ETH_ALEN);
- rc = sysfs_format_mac(buf, phba->mac_address,
- ETH_ALEN);
- phba->read_mac_address = 1;
- return rc;
+ memcpy(phba->mac_address, resp.mac_address, ETH_ALEN);
+ return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
}
-
/**
* beiscsi_conn_get_stats - get the iscsi stats
* @cls_conn: pointer to iscsi cls conn
@@ -736,11 +1144,24 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
umode_t be2iscsi_attr_is_visible(int param_type, int param)
{
switch (param_type) {
+ case ISCSI_NET_PARAM:
+ switch (param) {
+ case ISCSI_NET_PARAM_IFACE_ENABLE:
+ case ISCSI_NET_PARAM_IPV4_ADDR:
+ case ISCSI_NET_PARAM_IPV4_SUBNET:
+ case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
+ case ISCSI_NET_PARAM_IPV4_GW:
+ case ISCSI_NET_PARAM_IPV6_ADDR:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
case ISCSI_HOST_PARAM:
switch (param) {
case ISCSI_HOST_PARAM_HWADDRESS:
- case ISCSI_HOST_PARAM_IPADDRESS:
case ISCSI_HOST_PARAM_INITIATOR_NAME:
+ case ISCSI_HOST_PARAM_PORT_STATE:
+ case ISCSI_HOST_PARAM_PORT_SPEED:
return S_IRUGO;
default:
return 0;
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h
index 5c45be134501..8b826fc06bcc 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.h
+++ b/drivers/scsi/be2iscsi/be_iscsi.h
@@ -25,6 +25,21 @@
#define BE2_IPV4 0x1
#define BE2_IPV6 0x10
+#define BE2_DHCP_V4 0x05
+
+#define NON_BLOCKING 0x0
+#define BLOCKING 0x1
+
+void beiscsi_create_def_ifaces(struct beiscsi_hba *phba);
+
+void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba);
+
+int be2iscsi_iface_get_param(struct iscsi_iface *iface,
+ enum iscsi_param_type param_type,
+ int param, char *buf);
+
+int be2iscsi_iface_set_param(struct Scsi_Host *shost,
+ void *data, uint32_t count);
umode_t be2iscsi_attr_is_visible(int param_type, int param);
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 375756fa95cf..0b1d99c99fd2 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -28,8 +28,11 @@
#include <linux/semaphore.h>
#include <linux/iscsi_boot_sysfs.h>
#include <linux/module.h>
+#include <linux/bsg-lib.h>
#include <scsi/libiscsi.h>
+#include <scsi/scsi_bsg_iscsi.h>
+#include <scsi/scsi_netlink.h>
#include <scsi/scsi_transport_iscsi.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_cmnd.h>
@@ -48,7 +51,8 @@ static unsigned int num_hba = 0;
MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR);
-MODULE_AUTHOR("ServerEngines Corporation");
+MODULE_VERSION(BUILD_STR);
+MODULE_AUTHOR("Emulex Corporation");
MODULE_LICENSE("GPL");
module_param(be_iopoll_budget, int, 0);
module_param(enable_msix, int, 0);
@@ -147,15 +151,15 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
struct invalidate_command_table *inv_tbl;
struct be_dma_mem nonemb_cmd;
unsigned int cid, tag, i, num_invalidate;
- int rc = FAILED;
/* invalidate iocbs */
cls_session = starget_to_session(scsi_target(sc->device));
session = cls_session->dd_data;
spin_lock_bh(&session->lock);
- if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN)
- goto unlock;
-
+ if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) {
+ spin_unlock_bh(&session->lock);
+ return FAILED;
+ }
conn = session->leadconn;
beiscsi_conn = conn->dd_data;
phba = beiscsi_conn->phba;
@@ -208,9 +212,6 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return iscsi_eh_device_reset(sc);
-unlock:
- spin_unlock_bh(&session->lock);
- return rc;
}
static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
@@ -230,10 +231,10 @@ static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
case ISCSI_BOOT_TGT_IP_ADDR:
if (boot_conn->dest_ipaddr.ip_type == 0x1)
rc = sprintf(buf, "%pI4\n",
- (char *)&boot_conn->dest_ipaddr.ip_address);
+ (char *)&boot_conn->dest_ipaddr.addr);
else
rc = sprintf(str, "%pI6\n",
- (char *)&boot_conn->dest_ipaddr.ip_address);
+ (char *)&boot_conn->dest_ipaddr.addr);
break;
case ISCSI_BOOT_TGT_PORT:
rc = sprintf(str, "%d\n", boot_conn->dest_port);
@@ -311,12 +312,8 @@ static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)
rc = sprintf(str, "0\n");
break;
case ISCSI_BOOT_ETH_MAC:
- rc = beiscsi_get_macaddr(buf, phba);
- if (rc < 0) {
- SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n");
- return rc;
- }
- break;
+ rc = beiscsi_get_macaddr(str, phba);
+ break;
default:
rc = -ENOSYS;
break;
@@ -394,7 +391,7 @@ MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
static struct scsi_host_template beiscsi_sht = {
.module = THIS_MODULE,
- .name = "ServerEngines 10Gbe open-iscsi Initiator Driver",
+ .name = "Emulex 10Gbe open-iscsi Initiator Driver",
.proc_name = DRV_NAME,
.queuecommand = iscsi_queuecommand,
.change_queue_depth = iscsi_change_queue_depth,
@@ -409,6 +406,8 @@ static struct scsi_host_template beiscsi_sht = {
.max_sectors = BEISCSI_MAX_SECTORS,
.cmd_per_lun = BEISCSI_CMD_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
+ .vendor_id = SCSI_NL_VID_TYPE_PCI | BE_VENDOR_ID,
+
};
static struct scsi_transport_template *beiscsi_scsi_transport;
@@ -435,6 +434,7 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
phba->shost = shost;
phba->pcidev = pci_dev_get(pcidev);
pci_set_drvdata(pcidev, phba);
+ phba->interface_handle = 0xFFFFFFFF;
if (iscsi_host_add(shost, &phba->pcidev->dev))
goto free_devices;
@@ -544,8 +544,7 @@ static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev)
&mbox_mem_alloc->dma);
if (!mbox_mem_alloc->va) {
beiscsi_unmap_pci_function(phba);
- status = -ENOMEM;
- return status;
+ return -ENOMEM;
}
mbox_mem_align->size = sizeof(struct be_mcc_mailbox);
@@ -1252,9 +1251,9 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
task = pwrb_handle->pio_handle;
io_task = task->dd_data;
- spin_lock(&phba->mgmt_sgl_lock);
+ spin_lock_bh(&phba->mgmt_sgl_lock);
free_mgmt_sgl_handle(phba, io_task->psgl_handle);
- spin_unlock(&phba->mgmt_sgl_lock);
+ spin_unlock_bh(&phba->mgmt_sgl_lock);
spin_lock_bh(&session->lock);
free_wrb_handle(phba, pwrb_context, pwrb_handle);
spin_unlock_bh(&session->lock);
@@ -1370,8 +1369,6 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
struct be_bus_address phys_addr;
struct list_head *pbusy_list;
struct async_pdu_handle *pasync_handle = NULL;
- int buffer_len = 0;
- unsigned char buffer_index = -1;
unsigned char is_header = 0;
phys_addr.u.a32.address_lo =
@@ -1392,22 +1389,11 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
pbusy_list = hwi_get_async_busy_list(pasync_ctx, 1,
(pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
index) / 32] & PDUCQE_INDEX_MASK));
-
- buffer_len = (unsigned int)(phys_addr.u.a64.address -
- pasync_ctx->async_header.pa_base.u.a64.address);
-
- buffer_index = buffer_len /
- pasync_ctx->async_header.buffer_size;
-
break;
case UNSOL_DATA_NOTIFY:
pbusy_list = hwi_get_async_busy_list(pasync_ctx, 0, (pdpdu_cqe->
dw[offsetof(struct amap_i_t_dpdu_cqe,
index) / 32] & PDUCQE_INDEX_MASK));
- buffer_len = (unsigned long)(phys_addr.u.a64.address -
- pasync_ctx->async_data.pa_base.u.
- a64.address);
- buffer_index = buffer_len / pasync_ctx->async_data.buffer_size;
break;
default:
pbusy_list = NULL;
@@ -1418,11 +1404,9 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
return NULL;
}
- WARN_ON(!(buffer_index <= pasync_ctx->async_data.num_entries));
WARN_ON(list_empty(pbusy_list));
list_for_each_entry(pasync_handle, pbusy_list, link) {
- WARN_ON(pasync_handle->consumed);
- if (pasync_handle->index == buffer_index)
+ if (pasync_handle->pa.u.a64.address == phys_addr.u.a64.address)
break;
}
@@ -1449,15 +1433,13 @@ hwi_update_async_writables(struct hwi_async_pdu_context *pasync_ctx,
unsigned int num_entries, writables = 0;
unsigned int *pep_read_ptr, *pwritables;
-
+ num_entries = pasync_ctx->num_entries;
if (is_header) {
pep_read_ptr = &pasync_ctx->async_header.ep_read_ptr;
pwritables = &pasync_ctx->async_header.writables;
- num_entries = pasync_ctx->async_header.num_entries;
} else {
pep_read_ptr = &pasync_ctx->async_data.ep_read_ptr;
pwritables = &pasync_ctx->async_data.writables;
- num_entries = pasync_ctx->async_data.num_entries;
}
while ((*pep_read_ptr) != cq_index) {
@@ -1491,14 +1473,13 @@ hwi_update_async_writables(struct hwi_async_pdu_context *pasync_ctx,
return 0;
}
-static unsigned int hwi_free_async_msg(struct beiscsi_hba *phba,
+static void hwi_free_async_msg(struct beiscsi_hba *phba,
unsigned int cri)
{
struct hwi_controller *phwi_ctrlr;
struct hwi_async_pdu_context *pasync_ctx;
struct async_pdu_handle *pasync_handle, *tmp_handle;
struct list_head *plist;
- unsigned int i = 0;
phwi_ctrlr = phba->phwi_ctrlr;
pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
@@ -1508,23 +1489,20 @@ static unsigned int hwi_free_async_msg(struct beiscsi_hba *phba,
list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) {
list_del(&pasync_handle->link);
- if (i == 0) {
+ if (pasync_handle->is_header) {
list_add_tail(&pasync_handle->link,
&pasync_ctx->async_header.free_list);
pasync_ctx->async_header.free_entries++;
- i++;
} else {
list_add_tail(&pasync_handle->link,
&pasync_ctx->async_data.free_list);
pasync_ctx->async_data.free_entries++;
- i++;
}
}
INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wait_queue.list);
pasync_ctx->async_entry[cri].wait_queue.hdr_received = 0;
pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0;
- return 0;
}
static struct phys_addr *
@@ -1557,16 +1535,15 @@ static void hwi_post_async_buffers(struct beiscsi_hba *phba,
phwi_ctrlr = phba->phwi_ctrlr;
pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
+ num_entries = pasync_ctx->num_entries;
if (is_header) {
- num_entries = pasync_ctx->async_header.num_entries;
writables = min(pasync_ctx->async_header.writables,
pasync_ctx->async_header.free_entries);
pfree_link = pasync_ctx->async_header.free_list.next;
host_write_num = pasync_ctx->async_header.host_write_ptr;
ring_id = phwi_ctrlr->default_pdu_hdr.id;
} else {
- num_entries = pasync_ctx->async_data.num_entries;
writables = min(pasync_ctx->async_data.writables,
pasync_ctx->async_data.free_entries);
pfree_link = pasync_ctx->async_data.free_list.next;
@@ -1673,7 +1650,7 @@ hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn,
}
memcpy(pfirst_buffer + offset,
pasync_handle->pbuffer, buf_len);
- offset = buf_len;
+ offset += buf_len;
}
index++;
}
@@ -1682,10 +1659,9 @@ hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn,
(beiscsi_conn->beiscsi_conn_cid -
phba->fw_config.iscsi_cid_start),
phdr, hdr_len, pfirst_buffer,
- buf_len);
+ offset);
- if (status == 0)
- hwi_free_async_msg(phba, cri);
+ hwi_free_async_msg(phba, cri);
return 0;
}
@@ -2229,7 +2205,7 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
struct mem_array *mem_arr, *mem_arr_orig;
unsigned int i, j, alloc_size, curr_alloc_size;
- phba->phwi_ctrlr = kmalloc(phba->params.hwi_ws_sz, GFP_KERNEL);
+ phba->phwi_ctrlr = kzalloc(phba->params.hwi_ws_sz, GFP_KERNEL);
if (!phba->phwi_ctrlr)
return -ENOMEM;
@@ -2349,27 +2325,21 @@ static void iscsi_init_global_templates(struct beiscsi_hba *phba)
AMAP_SET_BITS(struct amap_pdu_nop_out, i_bit, pnop_out, 0);
}
-static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
+static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
{
struct be_mem_descriptor *mem_descr_wrbh, *mem_descr_wrb;
- struct wrb_handle *pwrb_handle;
+ struct wrb_handle *pwrb_handle = NULL;
struct hwi_controller *phwi_ctrlr;
struct hwi_wrb_context *pwrb_context;
- struct iscsi_wrb *pwrb;
- unsigned int num_cxn_wrbh;
- unsigned int num_cxn_wrb, j, idx, index;
+ struct iscsi_wrb *pwrb = NULL;
+ unsigned int num_cxn_wrbh = 0;
+ unsigned int num_cxn_wrb = 0, j, idx = 0, index;
mem_descr_wrbh = phba->init_mem;
mem_descr_wrbh += HWI_MEM_WRBH;
mem_descr_wrb = phba->init_mem;
mem_descr_wrb += HWI_MEM_WRB;
-
- idx = 0;
- pwrb_handle = mem_descr_wrbh->mem_array[idx].virtual_address;
- num_cxn_wrbh = ((mem_descr_wrbh->mem_array[idx].size) /
- ((sizeof(struct wrb_handle)) *
- phba->params.wrbs_per_cxn));
phwi_ctrlr = phba->phwi_ctrlr;
for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
@@ -2377,12 +2347,32 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
pwrb_context->pwrb_handle_base =
kzalloc(sizeof(struct wrb_handle *) *
phba->params.wrbs_per_cxn, GFP_KERNEL);
+ if (!pwrb_context->pwrb_handle_base) {
+ shost_printk(KERN_ERR, phba->shost,
+ "Mem Alloc Failed. Failing to load\n");
+ goto init_wrb_hndl_failed;
+ }
pwrb_context->pwrb_handle_basestd =
kzalloc(sizeof(struct wrb_handle *) *
phba->params.wrbs_per_cxn, GFP_KERNEL);
+ if (!pwrb_context->pwrb_handle_basestd) {
+ shost_printk(KERN_ERR, phba->shost,
+ "Mem Alloc Failed. Failing to load\n");
+ goto init_wrb_hndl_failed;
+ }
+ if (!num_cxn_wrbh) {
+ pwrb_handle =
+ mem_descr_wrbh->mem_array[idx].virtual_address;
+ num_cxn_wrbh = ((mem_descr_wrbh->mem_array[idx].size) /
+ ((sizeof(struct wrb_handle)) *
+ phba->params.wrbs_per_cxn));
+ idx++;
+ }
+ pwrb_context->alloc_index = 0;
+ pwrb_context->wrb_handles_available = 0;
+ pwrb_context->free_index = 0;
+
if (num_cxn_wrbh) {
- pwrb_context->alloc_index = 0;
- pwrb_context->wrb_handles_available = 0;
for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
pwrb_context->pwrb_handle_base[j] = pwrb_handle;
pwrb_context->pwrb_handle_basestd[j] =
@@ -2391,49 +2381,21 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
pwrb_handle->wrb_index = j;
pwrb_handle++;
}
- pwrb_context->free_index = 0;
- num_cxn_wrbh--;
- } else {
- idx++;
- pwrb_handle =
- mem_descr_wrbh->mem_array[idx].virtual_address;
- num_cxn_wrbh =
- ((mem_descr_wrbh->mem_array[idx].size) /
- ((sizeof(struct wrb_handle)) *
- phba->params.wrbs_per_cxn));
- pwrb_context->alloc_index = 0;
- for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
- pwrb_context->pwrb_handle_base[j] = pwrb_handle;
- pwrb_context->pwrb_handle_basestd[j] =
- pwrb_handle;
- pwrb_context->wrb_handles_available++;
- pwrb_handle->wrb_index = j;
- pwrb_handle++;
- }
- pwrb_context->free_index = 0;
num_cxn_wrbh--;
}
}
idx = 0;
- pwrb = mem_descr_wrb->mem_array[idx].virtual_address;
- num_cxn_wrb = (mem_descr_wrb->mem_array[idx].size) /
- ((sizeof(struct iscsi_wrb) *
- phba->params.wrbs_per_cxn));
for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
pwrb_context = &phwi_ctrlr->wrb_context[index];
- if (num_cxn_wrb) {
- for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
- pwrb_handle = pwrb_context->pwrb_handle_base[j];
- pwrb_handle->pwrb = pwrb;
- pwrb++;
- }
- num_cxn_wrb--;
- } else {
- idx++;
+ if (!num_cxn_wrb) {
pwrb = mem_descr_wrb->mem_array[idx].virtual_address;
num_cxn_wrb = (mem_descr_wrb->mem_array[idx].size) /
- ((sizeof(struct iscsi_wrb) *
- phba->params.wrbs_per_cxn));
+ ((sizeof(struct iscsi_wrb) *
+ phba->params.wrbs_per_cxn));
+ idx++;
+ }
+
+ if (num_cxn_wrb) {
for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
pwrb_handle = pwrb_context->pwrb_handle_base[j];
pwrb_handle->pwrb = pwrb;
@@ -2442,6 +2404,14 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
num_cxn_wrb--;
}
}
+ return 0;
+init_wrb_hndl_failed:
+ for (j = index; j > 0; j--) {
+ pwrb_context = &phwi_ctrlr->wrb_context[j];
+ kfree(pwrb_context->pwrb_handle_base);
+ kfree(pwrb_context->pwrb_handle_basestd);
+ }
+ return -ENOMEM;
}
static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
@@ -2450,7 +2420,7 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
struct hba_parameters *p = &phba->params;
struct hwi_async_pdu_context *pasync_ctx;
struct async_pdu_handle *pasync_header_h, *pasync_data_h;
- unsigned int index;
+ unsigned int index, idx, num_per_mem, num_async_data;
struct be_mem_descriptor *mem_descr;
mem_descr = (struct be_mem_descriptor *)phba->init_mem;
@@ -2462,10 +2432,8 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx;
memset(pasync_ctx, 0, sizeof(*pasync_ctx));
- pasync_ctx->async_header.num_entries = p->asyncpdus_per_ctrl;
- pasync_ctx->async_header.buffer_size = p->defpdu_hdr_sz;
- pasync_ctx->async_data.buffer_size = p->defpdu_data_sz;
- pasync_ctx->async_data.num_entries = p->asyncpdus_per_ctrl;
+ pasync_ctx->num_entries = p->asyncpdus_per_ctrl;
+ pasync_ctx->buffer_size = p->defpdu_hdr_sz;
mem_descr = (struct be_mem_descriptor *)phba->init_mem;
mem_descr += HWI_MEM_ASYNC_HEADER_BUF;
@@ -2510,19 +2478,6 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
pasync_ctx->async_header.writables = 0;
INIT_LIST_HEAD(&pasync_ctx->async_header.free_list);
- mem_descr = (struct be_mem_descriptor *)phba->init_mem;
- mem_descr += HWI_MEM_ASYNC_DATA_BUF;
- if (mem_descr->mem_array[0].virtual_address) {
- SE_DEBUG(DBG_LVL_8,
- "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_BUF"
- "va=%p\n", mem_descr->mem_array[0].virtual_address);
- } else
- shost_printk(KERN_WARNING, phba->shost,
- "No Virtual address\n");
- pasync_ctx->async_data.va_base =
- mem_descr->mem_array[0].virtual_address;
- pasync_ctx->async_data.pa_base.u.a64.address =
- mem_descr->mem_array[0].bus_address.u.a64.address;
mem_descr = (struct be_mem_descriptor *)phba->init_mem;
mem_descr += HWI_MEM_ASYNC_DATA_RING;
@@ -2553,6 +2508,25 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
pasync_data_h =
(struct async_pdu_handle *)pasync_ctx->async_data.handle_base;
+ mem_descr = (struct be_mem_descriptor *)phba->init_mem;
+ mem_descr += HWI_MEM_ASYNC_DATA_BUF;
+ if (mem_descr->mem_array[0].virtual_address) {
+ SE_DEBUG(DBG_LVL_8,
+ "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_BUF"
+ "va=%p\n", mem_descr->mem_array[0].virtual_address);
+ } else
+ shost_printk(KERN_WARNING, phba->shost,
+ "No Virtual address\n");
+ idx = 0;
+ pasync_ctx->async_data.va_base =
+ mem_descr->mem_array[idx].virtual_address;
+ pasync_ctx->async_data.pa_base.u.a64.address =
+ mem_descr->mem_array[idx].bus_address.u.a64.address;
+
+ num_async_data = ((mem_descr->mem_array[idx].size) /
+ phba->params.defpdu_data_sz);
+ num_per_mem = 0;
+
for (index = 0; index < p->asyncpdus_per_ctrl; index++) {
pasync_header_h->cri = -1;
pasync_header_h->index = (char)index;
@@ -2578,14 +2552,29 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
pasync_data_h->cri = -1;
pasync_data_h->index = (char)index;
INIT_LIST_HEAD(&pasync_data_h->link);
+
+ if (!num_async_data) {
+ num_per_mem = 0;
+ idx++;
+ pasync_ctx->async_data.va_base =
+ mem_descr->mem_array[idx].virtual_address;
+ pasync_ctx->async_data.pa_base.u.a64.address =
+ mem_descr->mem_array[idx].
+ bus_address.u.a64.address;
+
+ num_async_data = ((mem_descr->mem_array[idx].size) /
+ phba->params.defpdu_data_sz);
+ }
pasync_data_h->pbuffer =
(void *)((unsigned long)
(pasync_ctx->async_data.va_base) +
- (p->defpdu_data_sz * index));
+ (p->defpdu_data_sz * num_per_mem));
pasync_data_h->pa.u.a64.address =
pasync_ctx->async_data.pa_base.u.a64.address +
- (p->defpdu_data_sz * index);
+ (p->defpdu_data_sz * num_per_mem);
+ num_per_mem++;
+ num_async_data--;
list_add_tail(&pasync_data_h->link,
&pasync_ctx->async_data.free_list);
@@ -2913,9 +2902,11 @@ beiscsi_post_pages(struct beiscsi_hba *phba)
static void be_queue_free(struct beiscsi_hba *phba, struct be_queue_info *q)
{
struct be_dma_mem *mem = &q->dma_mem;
- if (mem->va)
+ if (mem->va) {
pci_free_consistent(phba->pcidev, mem->size,
mem->va, mem->dma);
+ mem->va = NULL;
+ }
}
static int be_queue_alloc(struct beiscsi_hba *phba, struct be_queue_info *q,
@@ -3215,7 +3206,7 @@ static int hwi_init_port(struct beiscsi_hba *phba)
error:
shost_printk(KERN_ERR, phba->shost, "hwi_init_port failed");
hwi_cleanup(phba);
- return -ENOMEM;
+ return status;
}
static int hwi_init_controller(struct beiscsi_hba *phba)
@@ -3236,7 +3227,9 @@ static int hwi_init_controller(struct beiscsi_hba *phba)
}
iscsi_init_global_templates(phba);
- beiscsi_init_wrb_handle(phba);
+ if (beiscsi_init_wrb_handle(phba))
+ return -ENOMEM;
+
hwi_init_async_pdu_ctx(phba);
if (hwi_init_port(phba) != 0) {
shost_printk(KERN_ERR, phba->shost,
@@ -3288,7 +3281,7 @@ static int beiscsi_init_controller(struct beiscsi_hba *phba)
free_init:
beiscsi_free_mem(phba);
- return -ENOMEM;
+ return ret;
}
static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)
@@ -3475,8 +3468,8 @@ static void hwi_disable_intr(struct beiscsi_hba *phba)
static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
{
- struct be_cmd_resp_get_boot_target *boot_resp;
- struct be_cmd_resp_get_session *session_resp;
+ struct be_cmd_get_boot_target_resp *boot_resp;
+ struct be_cmd_get_session_resp *session_resp;
struct be_mcc_wrb *wrb;
struct be_dma_mem nonemb_cmd;
unsigned int tag, wrb_num;
@@ -3484,9 +3477,9 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
int ret = -ENOMEM;
- tag = beiscsi_get_boot_target(phba);
+ tag = mgmt_get_boot_target(phba);
if (!tag) {
- SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n");
+ SE_DEBUG(DBG_LVL_1, "beiscsi_get_boot_info Failed\n");
return -EAGAIN;
} else
wait_event_interruptible(phba->ctrl.mcc_wait[tag],
@@ -3496,7 +3489,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
if (status || extd_status) {
- SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed"
+ SE_DEBUG(DBG_LVL_1, "beiscsi_get_boot_info Failed"
" status = %d extd_status = %d\n",
status, extd_status);
free_mcc_tag(&phba->ctrl, tag);
@@ -3522,8 +3515,8 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
}
memset(nonemb_cmd.va, 0, sizeof(*session_resp));
- tag = beiscsi_get_session_info(phba,
- boot_resp->boot_session_handle, &nonemb_cmd);
+ tag = mgmt_get_session_info(phba, boot_resp->boot_session_handle,
+ &nonemb_cmd);
if (!tag) {
SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info"
" Failed\n");
@@ -3696,6 +3689,57 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba)
kfree(phba->ep_array);
}
+static void beiscsi_cleanup_task(struct iscsi_task *task)
+{
+ struct beiscsi_io_task *io_task = task->dd_data;
+ struct iscsi_conn *conn = task->conn;
+ struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+ struct beiscsi_hba *phba = beiscsi_conn->phba;
+ struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess;
+ struct hwi_wrb_context *pwrb_context;
+ struct hwi_controller *phwi_ctrlr;
+
+ phwi_ctrlr = phba->phwi_ctrlr;
+ pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid
+ - phba->fw_config.iscsi_cid_start];
+
+ if (io_task->cmd_bhs) {
+ pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
+ io_task->bhs_pa.u.a64.address);
+ io_task->cmd_bhs = NULL;
+ }
+
+ if (task->sc) {
+ if (io_task->pwrb_handle) {
+ free_wrb_handle(phba, pwrb_context,
+ io_task->pwrb_handle);
+ io_task->pwrb_handle = NULL;
+ }
+
+ if (io_task->psgl_handle) {
+ spin_lock(&phba->io_sgl_lock);
+ free_io_sgl_handle(phba, io_task->psgl_handle);
+ spin_unlock(&phba->io_sgl_lock);
+ io_task->psgl_handle = NULL;
+ }
+ } else {
+ if (!beiscsi_conn->login_in_progress) {
+ if (io_task->pwrb_handle) {
+ free_wrb_handle(phba, pwrb_context,
+ io_task->pwrb_handle);
+ io_task->pwrb_handle = NULL;
+ }
+ if (io_task->psgl_handle) {
+ spin_lock(&phba->mgmt_sgl_lock);
+ free_mgmt_sgl_handle(phba,
+ io_task->psgl_handle);
+ spin_unlock(&phba->mgmt_sgl_lock);
+ io_task->psgl_handle = NULL;
+ }
+ }
+ }
+}
+
void
beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
struct beiscsi_offload_params *params)
@@ -3704,12 +3748,19 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
struct iscsi_target_context_update_wrb *pwrb = NULL;
struct be_mem_descriptor *mem_descr;
struct beiscsi_hba *phba = beiscsi_conn->phba;
+ struct iscsi_task *task = beiscsi_conn->task;
+ struct iscsi_session *session = task->conn->session;
u32 doorbell = 0;
/*
* We can always use 0 here because it is reserved by libiscsi for
* login/startup related tasks.
*/
+ beiscsi_conn->login_in_progress = 0;
+ spin_lock_bh(&session->lock);
+ beiscsi_cleanup_task(task);
+ spin_unlock_bh(&session->lock);
+
pwrb_handle = alloc_wrb_handle(phba, (beiscsi_conn->beiscsi_conn_cid -
phba->fw_config.iscsi_cid_start));
pwrb = (struct iscsi_target_context_update_wrb *)pwrb_handle->pwrb;
@@ -3823,7 +3874,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr;
task->hdr_max = sizeof(struct be_cmd_bhs);
io_task->psgl_handle = NULL;
- io_task->psgl_handle = NULL;
+ io_task->pwrb_handle = NULL;
if (task->sc) {
spin_lock(&phba->io_sgl_lock);
@@ -3865,6 +3916,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
io_task->pwrb_handle =
beiscsi_conn->plogin_wrb_handle;
}
+ beiscsi_conn->task = task;
} else {
spin_lock(&phba->mgmt_sgl_lock);
io_task->psgl_handle = alloc_mgmt_sgl_handle(phba);
@@ -3907,53 +3959,11 @@ free_hndls:
io_task->pwrb_handle = NULL;
pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
io_task->bhs_pa.u.a64.address);
+ io_task->cmd_bhs = NULL;
SE_DEBUG(DBG_LVL_1, "Alloc of SGL_ICD Failed\n");
return -ENOMEM;
}
-static void beiscsi_cleanup_task(struct iscsi_task *task)
-{
- struct beiscsi_io_task *io_task = task->dd_data;
- struct iscsi_conn *conn = task->conn;
- struct beiscsi_conn *beiscsi_conn = conn->dd_data;
- struct beiscsi_hba *phba = beiscsi_conn->phba;
- struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess;
- struct hwi_wrb_context *pwrb_context;
- struct hwi_controller *phwi_ctrlr;
-
- phwi_ctrlr = phba->phwi_ctrlr;
- pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid
- - phba->fw_config.iscsi_cid_start];
- if (io_task->pwrb_handle) {
- free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
- io_task->pwrb_handle = NULL;
- }
-
- if (io_task->cmd_bhs) {
- pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
- io_task->bhs_pa.u.a64.address);
- }
-
- if (task->sc) {
- if (io_task->psgl_handle) {
- spin_lock(&phba->io_sgl_lock);
- free_io_sgl_handle(phba, io_task->psgl_handle);
- spin_unlock(&phba->io_sgl_lock);
- io_task->psgl_handle = NULL;
- }
- } else {
- if (task->hdr &&
- ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN))
- return;
- if (io_task->psgl_handle) {
- spin_lock(&phba->mgmt_sgl_lock);
- free_mgmt_sgl_handle(phba, io_task->psgl_handle);
- spin_unlock(&phba->mgmt_sgl_lock);
- io_task->psgl_handle = NULL;
- }
- }
-}
-
static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
unsigned int num_sg, unsigned int xferlen,
unsigned int writedir)
@@ -3993,7 +4003,8 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
&io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb,
- cpu_to_be16(*(unsigned short *)&io_task->cmd_bhs->iscsi_hdr.lun));
+ cpu_to_be16(*(unsigned short *)
+ &io_task->cmd_bhs->iscsi_hdr.lun));
AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, xferlen);
AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
io_task->pwrb_handle->wrb_index);
@@ -4126,6 +4137,76 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
return beiscsi_iotask(task, sg, num_sg, xferlen, writedir);
}
+/**
+ * beiscsi_bsg_request - handle bsg request from ISCSI transport
+ * @job: job to handle
+ */
+static int beiscsi_bsg_request(struct bsg_job *job)
+{
+ struct Scsi_Host *shost;
+ struct beiscsi_hba *phba;
+ struct iscsi_bsg_request *bsg_req = job->request;
+ int rc = -EINVAL;
+ unsigned int tag;
+ struct be_dma_mem nonemb_cmd;
+ struct be_cmd_resp_hdr *resp;
+ struct iscsi_bsg_reply *bsg_reply = job->reply;
+ unsigned short status, extd_status;
+
+ shost = iscsi_job_to_shost(job);
+ phba = iscsi_host_priv(shost);
+
+ switch (bsg_req->msgcode) {
+ case ISCSI_BSG_HST_VENDOR:
+ nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
+ job->request_payload.payload_len,
+ &nonemb_cmd.dma);
+ if (nonemb_cmd.va == NULL) {
+ SE_DEBUG(DBG_LVL_1, "Failed to allocate memory for "
+ "beiscsi_bsg_request\n");
+ return -EIO;
+ }
+ tag = mgmt_vendor_specific_fw_cmd(&phba->ctrl, phba, job,
+ &nonemb_cmd);
+ if (!tag) {
+ SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n");
+ pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
+ nonemb_cmd.va, nonemb_cmd.dma);
+ return -EAGAIN;
+ } else
+ wait_event_interruptible(phba->ctrl.mcc_wait[tag],
+ phba->ctrl.mcc_numtag[tag]);
+ extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
+ status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+ free_mcc_tag(&phba->ctrl, tag);
+ resp = (struct be_cmd_resp_hdr *)nonemb_cmd.va;
+ sg_copy_from_buffer(job->reply_payload.sg_list,
+ job->reply_payload.sg_cnt,
+ nonemb_cmd.va, (resp->response_length
+ + sizeof(*resp)));
+ bsg_reply->reply_payload_rcv_len = resp->response_length;
+ bsg_reply->result = status;
+ bsg_job_done(job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+ pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
+ nonemb_cmd.va, nonemb_cmd.dma);
+ if (status || extd_status) {
+ SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed"
+ " status = %d extd_status = %d\n",
+ status, extd_status);
+ return -EIO;
+ }
+ break;
+
+ default:
+ SE_DEBUG(DBG_LVL_1, "Unsupported bsg command: 0x%x\n",
+ bsg_req->msgcode);
+ break;
+ }
+
+ return rc;
+}
+
static void beiscsi_quiesce(struct beiscsi_hba *phba)
{
struct hwi_controller *phwi_ctrlr;
@@ -4183,6 +4264,7 @@ static void beiscsi_remove(struct pci_dev *pcidev)
return;
}
+ beiscsi_destroy_def_ifaces(phba);
beiscsi_quiesce(phba);
iscsi_boot_destroy_kset(phba->boot_kset);
iscsi_host_remove(phba->shost);
@@ -4267,8 +4349,11 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
phba->num_cpus = num_cpus;
SE_DEBUG(DBG_LVL_8, "num_cpus = %d\n", phba->num_cpus);
- if (enable_msix)
+ if (enable_msix) {
beiscsi_msix_enable(phba);
+ if (!phba->msix_enabled)
+ phba->num_cpus = 1;
+ }
ret = be_ctrl_init(phba, pcidev);
if (ret) {
shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
@@ -4366,8 +4451,9 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
* iscsi boot.
*/
shost_printk(KERN_ERR, phba->shost, "Could not set up "
- "iSCSI boot info.");
+ "iSCSI boot info.\n");
+ beiscsi_create_def_ifaces(phba);
SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n");
return 0;
@@ -4418,6 +4504,8 @@ struct iscsi_transport beiscsi_iscsi_transport = {
.bind_conn = beiscsi_conn_bind,
.destroy_conn = iscsi_conn_teardown,
.attr_is_visible = be2iscsi_attr_is_visible,
+ .set_iface_param = be2iscsi_iface_set_param,
+ .get_iface_param = be2iscsi_iface_get_param,
.set_param = beiscsi_set_param,
.get_conn_param = iscsi_conn_get_param,
.get_session_param = iscsi_session_get_param,
@@ -4435,6 +4523,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
.ep_poll = beiscsi_ep_poll,
.ep_disconnect = beiscsi_ep_disconnect,
.session_recovery_timedout = iscsi_session_recovery_timedout,
+ .bsg_request = beiscsi_bsg_request,
};
static struct pci_driver beiscsi_pci_driver = {
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
index b4a06d5e5f9e..40fea6ec879c 100644
--- a/drivers/scsi/be2iscsi/be_main.h
+++ b/drivers/scsi/be2iscsi/be_main.h
@@ -34,9 +34,9 @@
#include "be.h"
#define DRV_NAME "be2iscsi"
-#define BUILD_STR "4.1.239.0"
-#define BE_NAME "ServerEngines BladeEngine2" \
- "Linux iSCSI Driver version" BUILD_STR
+#define BUILD_STR "4.2.162.0"
+#define BE_NAME "Emulex OneConnect" \
+ "Open-iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver"
#define BE_VENDOR_ID 0x19A2
@@ -316,6 +316,8 @@ struct beiscsi_hba {
struct iscsi_endpoint **ep_array;
struct iscsi_boot_kset *boot_kset;
struct Scsi_Host *shost;
+ struct iscsi_iface *ipv4_iface;
+ struct iscsi_iface *ipv6_iface;
struct {
/**
* group together since they are used most frequently
@@ -345,7 +347,7 @@ struct beiscsi_hba {
struct work_struct work_cqs; /* The work being queued */
struct be_ctrl_info ctrl;
unsigned int generation;
- unsigned int read_mac_address;
+ unsigned int interface_handle;
struct mgmt_session_info boot_sess;
struct invalidate_command_table inv_tbl[128];
@@ -525,8 +527,6 @@ struct hwi_async_pdu_context {
unsigned int free_entries;
unsigned int busy_entries;
- unsigned int buffer_size;
- unsigned int num_entries;
struct list_head free_list;
} async_header;
@@ -543,11 +543,12 @@ struct hwi_async_pdu_context {
unsigned int free_entries;
unsigned int busy_entries;
- unsigned int buffer_size;
struct list_head free_list;
- unsigned int num_entries;
} async_data;
+ unsigned int buffer_size;
+ unsigned int num_entries;
+
/**
* This is a varying size list! Do not add anything
* after this entry!!
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index 44762cfa3e12..01bb04cd9e75 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -17,15 +17,17 @@
* Costa Mesa, CA 92626
*/
+#include <linux/bsg-lib.h>
+#include <scsi/scsi_transport_iscsi.h>
+#include <scsi/scsi_bsg_iscsi.h>
#include "be_mgmt.h"
#include "be_iscsi.h"
-#include <scsi/scsi_transport_iscsi.h>
-unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba)
+unsigned int mgmt_get_boot_target(struct beiscsi_hba *phba)
{
struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb;
- struct be_cmd_req_get_mac_addr *req;
+ struct be_cmd_get_boot_target_req *req;
unsigned int tag = 0;
SE_DEBUG(DBG_LVL_8, "In bescsi_get_boot_target\n");
@@ -42,22 +44,22 @@ unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba)
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET,
- sizeof(*req));
+ sizeof(struct be_cmd_get_boot_target_resp));
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
return tag;
}
-unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba,
- u32 boot_session_handle,
- struct be_dma_mem *nonemb_cmd)
+unsigned int mgmt_get_session_info(struct beiscsi_hba *phba,
+ u32 boot_session_handle,
+ struct be_dma_mem *nonemb_cmd)
{
struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb;
unsigned int tag = 0;
- struct be_cmd_req_get_session *req;
- struct be_cmd_resp_get_session *resp;
+ struct be_cmd_get_session_req *req;
+ struct be_cmd_get_session_resp *resp;
struct be_sge *sge;
SE_DEBUG(DBG_LVL_8, "In beiscsi_get_session_info\n");
@@ -187,6 +189,72 @@ int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
return status;
}
+unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
+ struct beiscsi_hba *phba,
+ struct bsg_job *job,
+ struct be_dma_mem *nonemb_cmd)
+{
+ struct be_cmd_resp_hdr *resp;
+ struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
+ struct be_sge *mcc_sge = nonembedded_sgl(wrb);
+ unsigned int tag = 0;
+ struct iscsi_bsg_request *bsg_req = job->request;
+ struct be_bsg_vendor_cmd *req = nonemb_cmd->va;
+ unsigned short region, sector_size, sector, offset;
+
+ nonemb_cmd->size = job->request_payload.payload_len;
+ memset(nonemb_cmd->va, 0, nonemb_cmd->size);
+ resp = nonemb_cmd->va;
+ region = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
+ sector_size = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
+ sector = bsg_req->rqst_data.h_vendor.vendor_cmd[3];
+ offset = bsg_req->rqst_data.h_vendor.vendor_cmd[4];
+ req->region = region;
+ req->sector = sector;
+ req->offset = offset;
+ spin_lock(&ctrl->mbox_lock);
+ memset(wrb, 0, sizeof(*wrb));
+
+ switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) {
+ case BEISCSI_WRITE_FLASH:
+ offset = sector * sector_size + offset;
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
+ OPCODE_COMMON_WRITE_FLASH, sizeof(*req));
+ sg_copy_to_buffer(job->request_payload.sg_list,
+ job->request_payload.sg_cnt,
+ nonemb_cmd->va + offset, job->request_len);
+ break;
+ case BEISCSI_READ_FLASH:
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
+ OPCODE_COMMON_READ_FLASH, sizeof(*req));
+ break;
+ default:
+ shost_printk(KERN_WARNING, phba->shost,
+ "Unsupported cmd = 0x%x\n\n", bsg_req->rqst_data.
+ h_vendor.vendor_cmd[0]);
+ spin_unlock(&ctrl->mbox_lock);
+ return -ENOSYS;
+ }
+
+ tag = alloc_mcc_tag(phba);
+ if (!tag) {
+ spin_unlock(&ctrl->mbox_lock);
+ return tag;
+ }
+
+ be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false,
+ job->request_payload.sg_cnt);
+ mcc_sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
+ mcc_sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
+ mcc_sge->len = cpu_to_le32(nonemb_cmd->size);
+ wrb->tag0 |= tag;
+
+ be_mcc_notify(phba);
+
+ spin_unlock(&ctrl->mbox_lock);
+ return tag;
+}
+
int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
{
struct be_ctrl_info *ctrl = &phba->ctrl;
@@ -328,7 +396,6 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
struct sockaddr *dst_addr,
struct beiscsi_endpoint *beiscsi_ep,
struct be_dma_mem *nonemb_cmd)
-
{
struct hwi_controller *phwi_ctrlr;
struct hwi_context_memory *phwi_context;
@@ -374,17 +441,17 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
if (dst_addr->sa_family == PF_INET) {
__be32 s_addr = daddr_in->sin_addr.s_addr;
req->ip_address.ip_type = BE2_IPV4;
- req->ip_address.ip_address[0] = s_addr & 0x000000ff;
- req->ip_address.ip_address[1] = (s_addr & 0x0000ff00) >> 8;
- req->ip_address.ip_address[2] = (s_addr & 0x00ff0000) >> 16;
- req->ip_address.ip_address[3] = (s_addr & 0xff000000) >> 24;
+ req->ip_address.addr[0] = s_addr & 0x000000ff;
+ req->ip_address.addr[1] = (s_addr & 0x0000ff00) >> 8;
+ req->ip_address.addr[2] = (s_addr & 0x00ff0000) >> 16;
+ req->ip_address.addr[3] = (s_addr & 0xff000000) >> 24;
req->tcp_port = ntohs(daddr_in->sin_port);
beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr;
beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port);
beiscsi_ep->ip_type = BE2_IPV4;
} else if (dst_addr->sa_family == PF_INET6) {
req->ip_address.ip_type = BE2_IPV6;
- memcpy(&req->ip_address.ip_address,
+ memcpy(&req->ip_address.addr,
&daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
req->tcp_port = ntohs(daddr_in6->sin6_port);
beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port);
@@ -419,14 +486,399 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
return tag;
}
-unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba)
+unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba)
{
struct be_ctrl_info *ctrl = &phba->ctrl;
- struct be_mcc_wrb *wrb;
- struct be_cmd_req_get_mac_addr *req;
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_cmd_get_all_if_id_req *req = embedded_payload(wrb);
+ struct be_cmd_get_all_if_id_req *pbe_allid = req;
+ int status = 0;
+
+ memset(wrb, 0, sizeof(*wrb));
+
+ spin_lock(&ctrl->mbox_lock);
+
+ be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
+ OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID,
+ sizeof(*req));
+ status = be_mbox_notify(ctrl);
+ if (!status)
+ phba->interface_handle = pbe_allid->if_hndl_list[0];
+ else {
+ shost_printk(KERN_WARNING, phba->shost,
+ "Failed in mgmt_get_all_if_id\n");
+ }
+ spin_unlock(&ctrl->mbox_lock);
+
+ return status;
+}
+
+static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba,
+ struct be_dma_mem *nonemb_cmd, void *resp_buf,
+ int resp_buf_len)
+{
+ struct be_ctrl_info *ctrl = &phba->ctrl;
+ struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
+ unsigned short status, extd_status;
+ struct be_sge *sge;
+ unsigned int tag;
+ int rc = 0;
+
+ spin_lock(&ctrl->mbox_lock);
+ tag = alloc_mcc_tag(phba);
+ if (!tag) {
+ spin_unlock(&ctrl->mbox_lock);
+ rc = -ENOMEM;
+ goto free_cmd;
+ }
+ memset(wrb, 0, sizeof(*wrb));
+ wrb->tag0 |= tag;
+ sge = nonembedded_sgl(wrb);
+
+ be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1);
+ sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
+ sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
+ sge->len = cpu_to_le32(nonemb_cmd->size);
+
+ be_mcc_notify(phba);
+ spin_unlock(&ctrl->mbox_lock);
+
+ wait_event_interruptible(phba->ctrl.mcc_wait[tag],
+ phba->ctrl.mcc_numtag[tag]);
+
+ extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
+ status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+ if (status || extd_status) {
+ SE_DEBUG(DBG_LVL_1,
+ "mgmt_exec_nonemb_cmd Failed status = %d"
+ "extd_status = %d\n", status, extd_status);
+ rc = -EIO;
+ goto free_tag;
+ }
+
+ if (resp_buf)
+ memcpy(resp_buf, nonemb_cmd->va, resp_buf_len);
+
+free_tag:
+ free_mcc_tag(&phba->ctrl, tag);
+free_cmd:
+ pci_free_consistent(ctrl->pdev, nonemb_cmd->size,
+ nonemb_cmd->va, nonemb_cmd->dma);
+ return rc;
+}
+
+static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd,
+ int iscsi_cmd, int size)
+{
+ cmd->va = pci_alloc_consistent(phba->ctrl.pdev, sizeof(size),
+ &cmd->dma);
+ if (!cmd->va) {
+ SE_DEBUG(DBG_LVL_1, "Failed to allocate memory for if info\n");
+ return -ENOMEM;
+ }
+ memset(cmd->va, 0, sizeof(size));
+ cmd->size = size;
+ be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size);
+ return 0;
+}
+
+static int
+mgmt_static_ip_modify(struct beiscsi_hba *phba,
+ struct be_cmd_get_if_info_resp *if_info,
+ struct iscsi_iface_param_info *ip_param,
+ struct iscsi_iface_param_info *subnet_param,
+ uint32_t ip_action)
+{
+ struct be_cmd_set_ip_addr_req *req;
+ struct be_dma_mem nonemb_cmd;
+ uint32_t ip_type;
+ int rc;
+
+ rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
+ OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,
+ sizeof(*req));
+ if (rc)
+ return rc;
+
+ ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ?
+ BE2_IPV6 : BE2_IPV4 ;
+
+ req = nonemb_cmd.va;
+ req->ip_params.record_entry_count = 1;
+ req->ip_params.ip_record.action = ip_action;
+ req->ip_params.ip_record.interface_hndl =
+ phba->interface_handle;
+ req->ip_params.ip_record.ip_addr.size_of_structure =
+ sizeof(struct be_ip_addr_subnet_format);
+ req->ip_params.ip_record.ip_addr.ip_type = ip_type;
+
+ if (ip_action == IP_ACTION_ADD) {
+ memcpy(req->ip_params.ip_record.ip_addr.addr, ip_param->value,
+ ip_param->len);
+
+ if (subnet_param)
+ memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
+ subnet_param->value, subnet_param->len);
+ } else {
+ memcpy(req->ip_params.ip_record.ip_addr.addr,
+ if_info->ip_addr.addr, ip_param->len);
+
+ memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
+ if_info->ip_addr.subnet_mask, ip_param->len);
+ }
+
+ rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
+ if (rc < 0)
+ shost_printk(KERN_WARNING, phba->shost,
+ "Failed to Modify existing IP Address\n");
+ return rc;
+}
+
+static int mgmt_modify_gateway(struct beiscsi_hba *phba, uint8_t *gt_addr,
+ uint32_t gtway_action, uint32_t param_len)
+{
+ struct be_cmd_set_def_gateway_req *req;
+ struct be_dma_mem nonemb_cmd;
+ int rt_val;
+
+
+ rt_val = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
+ OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY,
+ sizeof(*req));
+ if (rt_val)
+ return rt_val;
+
+ req = nonemb_cmd.va;
+ req->action = gtway_action;
+ req->ip_addr.ip_type = BE2_IPV4;
+
+ memcpy(req->ip_addr.addr, gt_addr, param_len);
+
+ return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
+}
+
+int mgmt_set_ip(struct beiscsi_hba *phba,
+ struct iscsi_iface_param_info *ip_param,
+ struct iscsi_iface_param_info *subnet_param,
+ uint32_t boot_proto)
+{
+ struct be_cmd_get_def_gateway_resp gtway_addr_set;
+ struct be_cmd_get_if_info_resp if_info;
+ struct be_cmd_set_dhcp_req *dhcpreq;
+ struct be_cmd_rel_dhcp_req *reldhcp;
+ struct be_dma_mem nonemb_cmd;
+ uint8_t *gtway_addr;
+ uint32_t ip_type;
+ int rc;
+
+ if (mgmt_get_all_if_id(phba))
+ return -EIO;
+
+ memset(&if_info, 0, sizeof(if_info));
+ ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ?
+ BE2_IPV6 : BE2_IPV4 ;
+
+ rc = mgmt_get_if_info(phba, ip_type, &if_info);
+ if (rc)
+ return rc;
+
+ if (boot_proto == ISCSI_BOOTPROTO_DHCP) {
+ if (if_info.dhcp_state) {
+ shost_printk(KERN_WARNING, phba->shost,
+ "DHCP Already Enabled\n");
+ return 0;
+ }
+ /* The ip_param->len is 1 in DHCP case. Setting
+ proper IP len as this it is used while
+ freeing the Static IP.
+ */
+ ip_param->len = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ?
+ IP_V6_LEN : IP_V4_LEN;
+
+ } else {
+ if (if_info.dhcp_state) {
+
+ memset(&if_info, 0, sizeof(if_info));
+ rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
+ OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR,
+ sizeof(*reldhcp));
+
+ if (rc)
+ return rc;
+
+ reldhcp = nonemb_cmd.va;
+ reldhcp->interface_hndl = phba->interface_handle;
+ reldhcp->ip_type = ip_type;
+
+ rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
+ if (rc < 0) {
+ shost_printk(KERN_WARNING, phba->shost,
+ "Failed to Delete existing dhcp\n");
+ return rc;
+ }
+ }
+ }
+
+ /* Delete the Static IP Set */
+ if (if_info.ip_addr.addr[0]) {
+ rc = mgmt_static_ip_modify(phba, &if_info, ip_param, NULL,
+ IP_ACTION_DEL);
+ if (rc)
+ return rc;
+ }
+
+ /* Delete the Gateway settings if mode change is to DHCP */
+ if (boot_proto == ISCSI_BOOTPROTO_DHCP) {
+ memset(&gtway_addr_set, 0, sizeof(gtway_addr_set));
+ rc = mgmt_get_gateway(phba, BE2_IPV4, &gtway_addr_set);
+ if (rc) {
+ shost_printk(KERN_WARNING, phba->shost,
+ "Failed to Get Gateway Addr\n");
+ return rc;
+ }
+
+ if (gtway_addr_set.ip_addr.addr[0]) {
+ gtway_addr = (uint8_t *)&gtway_addr_set.ip_addr.addr;
+ rc = mgmt_modify_gateway(phba, gtway_addr,
+ IP_ACTION_DEL, IP_V4_LEN);
+
+ if (rc) {
+ shost_printk(KERN_WARNING, phba->shost,
+ "Failed to clear Gateway Addr Set\n");
+ return rc;
+ }
+ }
+ }
+
+ /* Set Adapter to DHCP/Static Mode */
+ if (boot_proto == ISCSI_BOOTPROTO_DHCP) {
+ rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
+ OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR,
+ sizeof(*dhcpreq));
+ if (rc)
+ return rc;
+
+ dhcpreq = nonemb_cmd.va;
+ dhcpreq->flags = BLOCKING;
+ dhcpreq->retry_count = 1;
+ dhcpreq->interface_hndl = phba->interface_handle;
+ dhcpreq->ip_type = BE2_DHCP_V4;
+
+ return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
+ } else {
+ return mgmt_static_ip_modify(phba, &if_info, ip_param,
+ subnet_param, IP_ACTION_ADD);
+ }
+
+ return rc;
+}
+
+int mgmt_set_gateway(struct beiscsi_hba *phba,
+ struct iscsi_iface_param_info *gateway_param)
+{
+ struct be_cmd_get_def_gateway_resp gtway_addr_set;
+ uint8_t *gtway_addr;
+ int rt_val;
+
+ memset(&gtway_addr_set, 0, sizeof(gtway_addr_set));
+ rt_val = mgmt_get_gateway(phba, BE2_IPV4, &gtway_addr_set);
+ if (rt_val) {
+ shost_printk(KERN_WARNING, phba->shost,
+ "Failed to Get Gateway Addr\n");
+ return rt_val;
+ }
+
+ if (gtway_addr_set.ip_addr.addr[0]) {
+ gtway_addr = (uint8_t *)&gtway_addr_set.ip_addr.addr;
+ rt_val = mgmt_modify_gateway(phba, gtway_addr, IP_ACTION_DEL,
+ gateway_param->len);
+ if (rt_val) {
+ shost_printk(KERN_WARNING, phba->shost,
+ "Failed to clear Gateway Addr Set\n");
+ return rt_val;
+ }
+ }
+
+ gtway_addr = (uint8_t *)&gateway_param->value;
+ rt_val = mgmt_modify_gateway(phba, gtway_addr, IP_ACTION_ADD,
+ gateway_param->len);
+
+ if (rt_val)
+ shost_printk(KERN_WARNING, phba->shost,
+ "Failed to Set Gateway Addr\n");
+
+ return rt_val;
+}
+
+int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type,
+ struct be_cmd_get_def_gateway_resp *gateway)
+{
+ struct be_cmd_get_def_gateway_req *req;
+ struct be_dma_mem nonemb_cmd;
+ int rc;
+
+ rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
+ OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY,
+ sizeof(*gateway));
+ if (rc)
+ return rc;
+
+ req = nonemb_cmd.va;
+ req->ip_type = ip_type;
+
+ return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, gateway,
+ sizeof(*gateway));
+}
+
+int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type,
+ struct be_cmd_get_if_info_resp *if_info)
+{
+ struct be_cmd_get_if_info_req *req;
+ struct be_dma_mem nonemb_cmd;
+ int rc;
+
+ if (mgmt_get_all_if_id(phba))
+ return -EIO;
+
+ rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
+ OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO,
+ sizeof(*if_info));
+ if (rc)
+ return rc;
+
+ req = nonemb_cmd.va;
+ req->interface_hndl = phba->interface_handle;
+ req->ip_type = ip_type;
+
+ return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, if_info,
+ sizeof(*if_info));
+}
+
+int mgmt_get_nic_conf(struct beiscsi_hba *phba,
+ struct be_cmd_get_nic_conf_resp *nic)
+{
+ struct be_dma_mem nonemb_cmd;
+ int rc;
+
+ rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
+ OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
+ sizeof(*nic));
+ if (rc)
+ return rc;
+
+ return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, nic, sizeof(*nic));
+}
+
+
+
+unsigned int be_cmd_get_initname(struct beiscsi_hba *phba)
+{
unsigned int tag = 0;
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_hba_name *req;
+ struct be_ctrl_info *ctrl = &phba->ctrl;
- SE_DEBUG(DBG_LVL_8, "In be_cmd_get_mac_addr\n");
spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
@@ -438,12 +890,38 @@ unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba)
req = embedded_payload(wrb);
wrb->tag0 |= tag;
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
- OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
- sizeof(*req));
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
+ OPCODE_ISCSI_INI_CFG_GET_HBA_NAME,
+ sizeof(*req));
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
return tag;
}
+unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba)
+{
+ unsigned int tag = 0;
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_ntwk_link_status_req *req;
+ struct be_ctrl_info *ctrl = &phba->ctrl;
+
+ spin_lock(&ctrl->mbox_lock);
+ tag = alloc_mcc_tag(phba);
+ if (!tag) {
+ spin_unlock(&ctrl->mbox_lock);
+ return tag;
+ }
+
+ wrb = wrb_from_mccq(phba);
+ req = embedded_payload(wrb);
+ wrb->tag0 |= tag;
+ be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_NTWK_LINK_STATUS_QUERY,
+ sizeof(*req));
+
+ be_mcc_notify(phba);
+ spin_unlock(&ctrl->mbox_lock);
+ return tag;
+}
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h
index 08428824ace2..5c2e37693ca8 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.h
+++ b/drivers/scsi/be2iscsi/be_mgmt.h
@@ -20,11 +20,16 @@
#ifndef _BEISCSI_MGMT_
#define _BEISCSI_MGMT_
-#include <linux/types.h>
-#include <linux/list.h>
+#include <scsi/scsi_bsg_iscsi.h>
#include "be_iscsi.h"
#include "be_main.h"
+#define IP_ACTION_ADD 0x01
+#define IP_ACTION_DEL 0x02
+
+#define IP_V6_LEN 16
+#define IP_V4_LEN 4
+
/**
* Pseudo amap definition in which each bit of the actual structure is defined
* as a byte: used to calculate offset/shift/mask of each field
@@ -98,6 +103,10 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
struct invalidate_command_table *inv_tbl,
unsigned int num_invalidate, unsigned int cid,
struct be_dma_mem *nonemb_cmd);
+unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
+ struct beiscsi_hba *phba,
+ struct bsg_job *job,
+ struct be_dma_mem *nonemb_cmd);
struct iscsi_invalidate_connection_params_in {
struct be_cmd_req_hdr hdr;
@@ -204,6 +213,13 @@ struct be_mgmt_controller_attributes_resp {
struct mgmt_controller_attributes params;
} __packed;
+struct be_bsg_vendor_cmd {
+ struct be_cmd_req_hdr hdr;
+ unsigned short region;
+ unsigned short offset;
+ unsigned short sector;
+} __packed;
+
/* configuration management */
#define GET_MGMT_CONTROLLER_WS(phba) (phba->pmgmt_ws)
@@ -219,12 +235,15 @@ struct be_mgmt_controller_attributes_resp {
/* the CMD_RESPONSE_HEADER */
#define ISCSI_GET_PDU_TEMPLATE_ADDRESS(pc, pa) {\
- pa->lo = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\
+ pa->lo = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\
bus_address.u.a32.address_lo; \
- pa->hi = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\
+ pa->hi = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\
bus_address.u.a32.address_hi; \
}
+#define BEISCSI_WRITE_FLASH 0
+#define BEISCSI_READ_FLASH 1
+
struct beiscsi_endpoint {
struct beiscsi_hba *phba;
struct beiscsi_sess *sess;
@@ -248,4 +267,27 @@ unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
unsigned short issue_reset,
unsigned short savecfg_flag);
+int mgmt_set_ip(struct beiscsi_hba *phba,
+ struct iscsi_iface_param_info *ip_param,
+ struct iscsi_iface_param_info *subnet_param,
+ uint32_t boot_proto);
+
+unsigned int mgmt_get_boot_target(struct beiscsi_hba *phba);
+
+unsigned int mgmt_get_session_info(struct beiscsi_hba *phba,
+ u32 boot_session_handle,
+ struct be_dma_mem *nonemb_cmd);
+
+int mgmt_get_nic_conf(struct beiscsi_hba *phba,
+ struct be_cmd_get_nic_conf_resp *mac);
+
+int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type,
+ struct be_cmd_get_if_info_resp *if_info);
+
+int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type,
+ struct be_cmd_get_def_gateway_resp *gateway);
+
+int mgmt_set_gateway(struct beiscsi_hba *phba,
+ struct iscsi_iface_param_info *gateway_param);
+
#endif
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
index e75e07d25915..51c9e1345719 100644
--- a/drivers/scsi/bfa/bfa_fcs.h
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -799,9 +799,6 @@ struct bfad_port_s *bfa_fcb_lport_new(struct bfad_s *bfad,
enum bfa_lport_role roles,
struct bfad_vf_s *vf_drv,
struct bfad_vport_s *vp_drv);
-void bfa_fcb_lport_delete(struct bfad_s *bfad, enum bfa_lport_role roles,
- struct bfad_vf_s *vf_drv,
- struct bfad_vport_s *vp_drv);
/*
* vport callbacks
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 5d2a1307e5ce..937000db62a8 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -616,7 +616,7 @@ bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
__port_action[port->fabric->fab_type].online(port);
wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
- BFA_LOG(KERN_INFO, bfad, bfa_log_level,
+ BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
"Logical port online: WWN = %s Role = %s\n",
lpwwn_buf, "Initiator");
bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_ONLINE);
@@ -639,12 +639,12 @@ bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
if (bfa_sm_cmp_state(port->fabric,
bfa_fcs_fabric_sm_online) == BFA_TRUE) {
- BFA_LOG(KERN_ERR, bfad, bfa_log_level,
+ BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
"Logical port lost fabric connectivity: WWN = %s Role = %s\n",
lpwwn_buf, "Initiator");
bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
} else {
- BFA_LOG(KERN_INFO, bfad, bfa_log_level,
+ BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
"Logical port taken offline: WWN = %s Role = %s\n",
lpwwn_buf, "Initiator");
bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_OFFLINE);
@@ -709,14 +709,10 @@ bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DELETE);
/* Base port will be deleted by the OS driver */
- if (port->vport) {
- bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
- port->fabric->vf_drv,
- port->vport ? port->vport->vport_drv : NULL);
+ if (port->vport)
bfa_fcs_vport_delete_comp(port->vport);
- } else {
+ else
bfa_wc_down(&port->fabric->wc);
- }
}
@@ -5714,17 +5710,23 @@ bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
(struct bfad_vport_s *)vport->vport_drv;
bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
+ bfa_lps_delete(vport->lps);
- if (vport_drv->comp_del)
+ if (vport_drv->comp_del) {
complete(vport_drv->comp_del);
- else
- kfree(vport_drv);
+ return;
+ }
- bfa_lps_delete(vport->lps);
+ /*
+ * We queue the vport delete work to the IM work_q from here.
+ * The memory for the bfad_vport_s is freed from the FC function
+ * template vport_delete entry point.
+ */
+ if (vport_drv)
+ bfad_im_port_delete(vport_drv->drv_port.bfad,
+ &vport_drv->drv_port);
}
-
-
/*
* fcs_vport_public FCS virtual port public interfaces
*/
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 404fd10ddb21..2e4b0be14a20 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -456,23 +456,6 @@ bfa_fcb_lport_new(struct bfad_s *bfad, struct bfa_fcs_lport_s *port,
return port_drv;
}
-void
-bfa_fcb_lport_delete(struct bfad_s *bfad, enum bfa_lport_role roles,
- struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
-{
- struct bfad_port_s *port_drv;
-
- /* this will be only called from rmmod context */
- if (vp_drv && !vp_drv->comp_del) {
- port_drv = (vp_drv) ? (&(vp_drv)->drv_port) :
- ((vf_drv) ? (&(vf_drv)->base_port) :
- (&(bfad)->pport));
- bfa_trc(bfad, roles);
- if (roles & BFA_LPORT_ROLE_FCP_IM)
- bfad_im_port_delete(bfad, port_drv);
- }
-}
-
/*
* FCS RPORT alloc callback, after successful PLOGI by FCS
*/
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index 7b1ecd2b3ffe..8b6c6bf7837e 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -497,6 +497,7 @@ bfad_im_vport_delete(struct fc_vport *fc_vport)
if (im_port->flags & BFAD_PORT_DELETE) {
bfad_scsi_host_free(bfad, im_port);
list_del(&vport->list_entry);
+ kfree(vport);
return 0;
}
@@ -758,25 +759,10 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
else if (!strcmp(model, "Brocade-804"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 8Gbps FC HBA for HP Bladesystem C-class");
- else if (!strcmp(model, "Brocade-902") ||
- !strcmp(model, "Brocade-1741"))
+ else if (!strcmp(model, "Brocade-1741"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 10Gbps CNA for Dell M-Series Blade Servers");
- else if (strstr(model, "Brocade-1560")) {
- if (nports == 1)
- snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
- "Brocade 16Gbps PCIe single port FC HBA");
- else
- snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
- "Brocade 16Gbps PCIe dual port FC HBA");
- } else if (strstr(model, "Brocade-1710")) {
- if (nports == 1)
- snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
- "Brocade 10Gbps single port CNA");
- else
- snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
- "Brocade 10Gbps dual port CNA");
- } else if (strstr(model, "Brocade-1860")) {
+ else if (strstr(model, "Brocade-1860")) {
if (nports == 1 && bfa_ioc_is_cna(&bfad->bfa.ioc))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 10Gbps single port CNA");
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
index 495a841645f9..25093a04123b 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
@@ -1,6 +1,6 @@
/* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI
*
- * Copyright (c) 2006 - 2011 Broadcom Corporation
+ * Copyright (c) 2006 - 2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
index 72118db89a20..dc0a08e69c82 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
@@ -1,6 +1,6 @@
/* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI.
*
- * Copyright (c) 2006 - 2011 Broadcom Corporation
+ * Copyright (c) 2006 - 2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 0bd70e80efe4..0c53c28dc3d3 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -1,6 +1,6 @@
/* bnx2i.h: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2011 Broadcom Corporation
+ * Copyright (c) 2006 - 2012 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index f9d6f4129093..ece47e502282 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1,6 +1,6 @@
/* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2011 Broadcom Corporation
+ * Copyright (c) 2006 - 2012 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 4927cca733d3..8b6816706ee5 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -1,6 +1,6 @@
/* bnx2i.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2011 Broadcom Corporation
+ * Copyright (c) 2006 - 2012 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -18,8 +18,8 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list);
static u32 adapter_count;
#define DRV_MODULE_NAME "bnx2i"
-#define DRV_MODULE_VERSION "2.7.0.3"
-#define DRV_MODULE_RELDATE "Jun 15, 2011"
+#define DRV_MODULE_VERSION "2.7.2.2"
+#define DRV_MODULE_RELDATE "Apr 25, 2012"
static char version[] __devinitdata =
"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 1a44b45e7bef..f8d516b53161 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1,7 +1,7 @@
/*
* bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2011 Broadcom Corporation
+ * Copyright (c) 2006 - 2012 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -2244,6 +2244,7 @@ static struct scsi_host_template bnx2i_host_template = {
.eh_device_reset_handler = iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target,
.change_queue_depth = iscsi_change_queue_depth,
+ .target_alloc = iscsi_target_alloc,
.can_queue = 2048,
.max_sectors = 127,
.cmd_per_lun = 128,
diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c
index 83a77f7244d2..c61cf7a43658 100644
--- a/drivers/scsi/bnx2i/bnx2i_sysfs.c
+++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c
@@ -1,6 +1,6 @@
/* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2004 - 2011 Broadcom Corporation
+ * Copyright (c) 2004 - 2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 04c5cea47a22..fda9cdea0e60 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -55,11 +55,16 @@
#define ALUA_FAILOVER_TIMEOUT (60 * HZ)
#define ALUA_FAILOVER_RETRIES 5
+/* flags passed from user level */
+#define ALUA_OPTIMIZE_STPG 1
+
struct alua_dh_data {
int group_id;
int rel_port;
int tpgs;
int state;
+ int pref;
+ unsigned flags; /* used for optimizing STPG */
unsigned char inq[ALUA_INQUIRY_SIZE];
unsigned char *buff;
int bufflen;
@@ -554,14 +559,16 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
for (k = 4, ucp = h->buff + 4; k < len; k += off, ucp += off) {
if (h->group_id == (ucp[2] << 8) + ucp[3]) {
h->state = ucp[0] & 0x0f;
+ h->pref = ucp[0] >> 7;
valid_states = ucp[1];
}
off = 8 + (ucp[7] * 4);
}
sdev_printk(KERN_INFO, sdev,
- "%s: port group %02x state %c supports %c%c%c%c%c%c%c\n",
+ "%s: port group %02x state %c %s supports %c%c%c%c%c%c%c\n",
ALUA_DH_NAME, h->group_id, print_alua_state(h->state),
+ h->pref ? "preferred" : "non-preferred",
valid_states&TPGS_SUPPORT_TRANSITION?'T':'t',
valid_states&TPGS_SUPPORT_OFFLINE?'O':'o',
valid_states&TPGS_SUPPORT_LBA_DEPENDENT?'L':'l',
@@ -621,6 +628,37 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
out:
return err;
}
+/*
+ * alua_set_params - set/unset the optimize flag
+ * @sdev: device on the path to be activated
+ * params - parameters in the following format
+ * "no_of_params\0param1\0param2\0param3\0...\0"
+ * For example, to set the flag pass the following parameters
+ * from multipath.conf
+ * hardware_handler "2 alua 1"
+ */
+static int alua_set_params(struct scsi_device *sdev, const char *params)
+{
+ struct alua_dh_data *h = get_alua_data(sdev);
+ unsigned int optimize = 0, argc;
+ const char *p = params;
+ int result = SCSI_DH_OK;
+
+ if ((sscanf(params, "%u", &argc) != 1) || (argc != 1))
+ return -EINVAL;
+
+ while (*p++)
+ ;
+ if ((sscanf(p, "%u", &optimize) != 1) || (optimize > 1))
+ return -EINVAL;
+
+ if (optimize)
+ h->flags |= ALUA_OPTIMIZE_STPG;
+ else
+ h->flags &= ~ALUA_OPTIMIZE_STPG;
+
+ return result;
+}
/*
* alua_activate - activate a path
@@ -637,14 +675,37 @@ static int alua_activate(struct scsi_device *sdev,
{
struct alua_dh_data *h = get_alua_data(sdev);
int err = SCSI_DH_OK;
+ int stpg = 0;
err = alua_rtpg(sdev, h);
if (err != SCSI_DH_OK)
goto out;
- if (h->tpgs & TPGS_MODE_EXPLICIT &&
- h->state != TPGS_STATE_OPTIMIZED &&
- h->state != TPGS_STATE_LBA_DEPENDENT) {
+ if (h->tpgs & TPGS_MODE_EXPLICIT) {
+ switch (h->state) {
+ case TPGS_STATE_NONOPTIMIZED:
+ stpg = 1;
+ if ((h->flags & ALUA_OPTIMIZE_STPG) &&
+ (!h->pref) &&
+ (h->tpgs & TPGS_MODE_IMPLICIT))
+ stpg = 0;
+ break;
+ case TPGS_STATE_STANDBY:
+ stpg = 1;
+ break;
+ case TPGS_STATE_UNAVAILABLE:
+ case TPGS_STATE_OFFLINE:
+ err = SCSI_DH_IO;
+ break;
+ case TPGS_STATE_TRANSITIONING:
+ err = SCSI_DH_RETRY;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (stpg) {
h->callback_fn = fn;
h->callback_data = data;
err = submit_stpg(h);
@@ -698,6 +759,7 @@ static struct scsi_device_handler alua_dh = {
.prep_fn = alua_prep_fn,
.check_sense = alua_check_sense,
.activate = alua_activate,
+ .set_params = alua_set_params,
.match = alua_match,
};
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 394ed9e79fd4..34552bf1c023 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -1000,7 +1000,7 @@ static int esp_check_spur_intr(struct esp *esp)
static void esp_schedule_reset(struct esp *esp)
{
- esp_log_reset("ESP: esp_schedule_reset() from %p\n",
+ esp_log_reset("ESP: esp_schedule_reset() from %pf\n",
__builtin_return_address(0));
esp->flags |= ESP_FLAG_RESETTING;
esp_event(esp, ESP_EVENT_RESET);
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 335e85192807..76e3d0b5bfa6 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -411,20 +411,18 @@ out:
}
/**
- * fcoe_interface_cleanup() - Clean up a FCoE interface
+ * fcoe_interface_remove() - remove FCoE interface from netdev
* @fcoe: The FCoE interface to be cleaned up
*
* Caller must be holding the RTNL mutex
*/
-static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
+static void fcoe_interface_remove(struct fcoe_interface *fcoe)
{
struct net_device *netdev = fcoe->netdev;
struct fcoe_ctlr *fip = &fcoe->ctlr;
u8 flogi_maddr[ETH_ALEN];
const struct net_device_ops *ops;
- rtnl_lock();
-
/*
* Don't listen for Ethernet packets anymore.
* synchronize_net() ensures that the packet handlers are not running
@@ -453,12 +451,28 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE"
" specific feature for LLD.\n");
}
+ fcoe->removed = 1;
+}
+
+
+/**
+ * fcoe_interface_cleanup() - Clean up a FCoE interface
+ * @fcoe: The FCoE interface to be cleaned up
+ */
+static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
+{
+ struct net_device *netdev = fcoe->netdev;
+ struct fcoe_ctlr *fip = &fcoe->ctlr;
+ rtnl_lock();
+ if (!fcoe->removed)
+ fcoe_interface_remove(fcoe);
rtnl_unlock();
/* Release the self-reference taken during fcoe_interface_create() */
/* tear-down the FCoE controller */
fcoe_ctlr_destroy(fip);
+ scsi_host_put(fcoe->ctlr.lp->host);
kfree(fcoe);
dev_put(netdev);
module_put(THIS_MODULE);
@@ -522,13 +536,11 @@ static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr)
struct fcoe_port *port = lport_priv(lport);
struct fcoe_interface *fcoe = port->priv;
- rtnl_lock();
if (!is_zero_ether_addr(port->data_src_addr))
dev_uc_del(fcoe->netdev, port->data_src_addr);
if (!is_zero_ether_addr(addr))
dev_uc_add(fcoe->netdev, addr);
memcpy(port->data_src_addr, addr, ETH_ALEN);
- rtnl_unlock();
}
/**
@@ -941,6 +953,10 @@ static void fcoe_if_destroy(struct fc_lport *lport)
rtnl_lock();
if (!is_zero_ether_addr(port->data_src_addr))
dev_uc_del(netdev, port->data_src_addr);
+ if (lport->vport)
+ synchronize_net();
+ else
+ fcoe_interface_remove(fcoe);
rtnl_unlock();
/* Free queued packets for the per-CPU receive threads */
@@ -959,8 +975,12 @@ static void fcoe_if_destroy(struct fc_lport *lport)
/* Free memory used by statistical counters */
fc_lport_free_stats(lport);
- /* Release the Scsi_Host */
- scsi_host_put(lport->host);
+ /*
+ * Release the Scsi_Host for vport but hold on to
+ * master lport until it fcoe interface fully cleaned-up.
+ */
+ if (lport->vport)
+ scsi_host_put(lport->host);
}
/**
@@ -2274,10 +2294,9 @@ static void fcoe_percpu_clean(struct fc_lport *lport)
continue;
skb = dev_alloc_skb(0);
- if (!skb) {
- spin_unlock_bh(&pp->fcoe_rx_list.lock);
+ if (!skb)
continue;
- }
+
skb->destructor = fcoe_percpu_flush_done;
spin_lock_bh(&pp->fcoe_rx_list.lock);
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 3c2733a12aa1..96ac938d39cc 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -71,7 +71,8 @@ do { \
* @ctlr: The FCoE controller (for FIP)
* @oem: The offload exchange manager for all local port
* instances associated with this port
- * This structure is 1:1 with a net devive.
+ * @removed: Indicates fcoe interface removed from net device
+ * This structure is 1:1 with a net device.
*/
struct fcoe_interface {
struct list_head list;
@@ -81,6 +82,7 @@ struct fcoe_interface {
struct packet_type fip_packet_type;
struct fcoe_ctlr ctlr;
struct fc_exch_mgr *oem;
+ u8 removed;
};
#define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr)
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 249a106888d9..5a4c7250aa77 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -1883,7 +1883,13 @@ static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip,
frame = (struct fip_frame *)skb->data;
memset(frame, 0, len);
memcpy(frame->eth.h_dest, dest, ETH_ALEN);
- memcpy(frame->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
+
+ if (sub == FIP_SC_VN_BEACON) {
+ hton24(frame->eth.h_source, FIP_VN_FC_MAP);
+ hton24(frame->eth.h_source + 3, fip->port_id);
+ } else {
+ memcpy(frame->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
+ }
frame->eth.h_proto = htons(ETH_P_FIP);
frame->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 500e20dd56ec..796482badf13 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -159,6 +159,7 @@ static int hpsa_change_queue_depth(struct scsi_device *sdev,
int qdepth, int reason);
static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd);
+static int hpsa_eh_abort_handler(struct scsi_cmnd *scsicmd);
static int hpsa_slave_alloc(struct scsi_device *sdev);
static void hpsa_slave_destroy(struct scsi_device *sdev);
@@ -171,7 +172,7 @@ static void check_ioctl_unit_attention(struct ctlr_info *h,
static void calc_bucket_map(int *bucket, int num_buckets,
int nsgs, int *bucket_map);
static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h);
-static inline u32 next_command(struct ctlr_info *h);
+static inline u32 next_command(struct ctlr_info *h, u8 q);
static int __devinit hpsa_find_cfg_addrs(struct pci_dev *pdev,
void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index,
u64 *cfg_offset);
@@ -180,6 +181,7 @@ static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id);
static int __devinit hpsa_wait_for_board_state(struct pci_dev *pdev,
void __iomem *vaddr, int wait_for_ready);
+static inline void finish_cmd(struct CommandList *c);
#define BOARD_NOT_READY 0
#define BOARD_READY 1
@@ -234,6 +236,16 @@ static int check_for_unit_attention(struct ctlr_info *h,
return 1;
}
+static int check_for_busy(struct ctlr_info *h, struct CommandList *c)
+{
+ if (c->err_info->CommandStatus != CMD_TARGET_STATUS ||
+ (c->err_info->ScsiStatus != SAM_STAT_BUSY &&
+ c->err_info->ScsiStatus != SAM_STAT_TASK_SET_FULL))
+ return 0;
+ dev_warn(&h->pdev->dev, HPSA "device busy");
+ return 1;
+}
+
static ssize_t host_store_rescan(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
@@ -368,7 +380,7 @@ static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[])
}
static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
- "UNKNOWN"
+ "1(ADM)", "UNKNOWN"
};
#define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 1)
@@ -497,6 +509,7 @@ static struct scsi_host_template hpsa_driver_template = {
.change_queue_depth = hpsa_change_queue_depth,
.this_id = -1,
.use_clustering = ENABLE_CLUSTERING,
+ .eh_abort_handler = hpsa_eh_abort_handler,
.eh_device_reset_handler = hpsa_eh_device_reset_handler,
.ioctl = hpsa_ioctl,
.slave_alloc = hpsa_slave_alloc,
@@ -516,24 +529,28 @@ static inline void addQ(struct list_head *list, struct CommandList *c)
list_add_tail(&c->list, list);
}
-static inline u32 next_command(struct ctlr_info *h)
+static inline u32 next_command(struct ctlr_info *h, u8 q)
{
u32 a;
+ struct reply_pool *rq = &h->reply_queue[q];
+ unsigned long flags;
if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant)))
- return h->access.command_completed(h);
+ return h->access.command_completed(h, q);
- if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
- a = *(h->reply_pool_head); /* Next cmd in ring buffer */
- (h->reply_pool_head)++;
+ if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
+ a = rq->head[rq->current_entry];
+ rq->current_entry++;
+ spin_lock_irqsave(&h->lock, flags);
h->commands_outstanding--;
+ spin_unlock_irqrestore(&h->lock, flags);
} else {
a = FIFO_EMPTY;
}
/* Check for wraparound */
- if (h->reply_pool_head == (h->reply_pool + h->max_commands)) {
- h->reply_pool_head = h->reply_pool;
- h->reply_pool_wraparound ^= 1;
+ if (rq->current_entry == h->max_commands) {
+ rq->current_entry = 0;
+ rq->wraparound ^= 1;
}
return a;
}
@@ -544,8 +561,41 @@ static inline u32 next_command(struct ctlr_info *h)
*/
static void set_performant_mode(struct ctlr_info *h, struct CommandList *c)
{
- if (likely(h->transMethod & CFGTBL_Trans_Performant))
+ if (likely(h->transMethod & CFGTBL_Trans_Performant)) {
c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1);
+ if (likely(h->msix_vector))
+ c->Header.ReplyQueue =
+ smp_processor_id() % h->nreply_queues;
+ }
+}
+
+static int is_firmware_flash_cmd(u8 *cdb)
+{
+ return cdb[0] == BMIC_WRITE && cdb[6] == BMIC_FLASH_FIRMWARE;
+}
+
+/*
+ * During firmware flash, the heartbeat register may not update as frequently
+ * as it should. So we dial down lockup detection during firmware flash. and
+ * dial it back up when firmware flash completes.
+ */
+#define HEARTBEAT_SAMPLE_INTERVAL_DURING_FLASH (240 * HZ)
+#define HEARTBEAT_SAMPLE_INTERVAL (30 * HZ)
+static void dial_down_lockup_detection_during_fw_flash(struct ctlr_info *h,
+ struct CommandList *c)
+{
+ if (!is_firmware_flash_cmd(c->Request.CDB))
+ return;
+ atomic_inc(&h->firmware_flash_in_progress);
+ h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL_DURING_FLASH;
+}
+
+static void dial_up_lockup_detection_on_fw_flash_complete(struct ctlr_info *h,
+ struct CommandList *c)
+{
+ if (is_firmware_flash_cmd(c->Request.CDB) &&
+ atomic_dec_and_test(&h->firmware_flash_in_progress))
+ h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL;
}
static void enqueue_cmd_and_start_io(struct ctlr_info *h,
@@ -554,11 +604,12 @@ static void enqueue_cmd_and_start_io(struct ctlr_info *h,
unsigned long flags;
set_performant_mode(h, c);
+ dial_down_lockup_detection_during_fw_flash(h, c);
spin_lock_irqsave(&h->lock, flags);
addQ(&h->reqQ, c);
h->Qdepth++;
- start_io(h);
spin_unlock_irqrestore(&h->lock, flags);
+ start_io(h);
}
static inline void removeQ(struct CommandList *c)
@@ -1193,7 +1244,7 @@ static void complete_scsi_command(struct CommandList *cp)
break;
}
/* Must be some other type of check condition */
- dev_warn(&h->pdev->dev, "cp %p has check condition: "
+ dev_dbg(&h->pdev->dev, "cp %p has check condition: "
"unknown type: "
"Sense: 0x%x, ASC: 0x%x, ASCQ: 0x%x, "
"Returning result: 0x%x, "
@@ -1370,16 +1421,24 @@ static void hpsa_scsi_do_simple_cmd_core_if_no_lockup(struct ctlr_info *h,
}
}
+#define MAX_DRIVER_CMD_RETRIES 25
static void hpsa_scsi_do_simple_cmd_with_retry(struct ctlr_info *h,
struct CommandList *c, int data_direction)
{
- int retry_count = 0;
+ int backoff_time = 10, retry_count = 0;
do {
memset(c->err_info, 0, sizeof(*c->err_info));
hpsa_scsi_do_simple_cmd_core(h, c);
retry_count++;
- } while (check_for_unit_attention(h, c) && retry_count <= 3);
+ if (retry_count > 3) {
+ msleep(backoff_time);
+ if (backoff_time < 1000)
+ backoff_time *= 2;
+ }
+ } while ((check_for_unit_attention(h, c) ||
+ check_for_busy(h, c)) &&
+ retry_count <= MAX_DRIVER_CMD_RETRIES);
hpsa_pci_unmap(h->pdev, c, 1, data_direction);
}
@@ -2065,9 +2124,8 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
done(cmd);
return 0;
}
- /* Need a lock as this is being allocated from the pool */
- c = cmd_alloc(h);
spin_unlock_irqrestore(&h->lock, flags);
+ c = cmd_alloc(h);
if (c == NULL) { /* trouble... */
dev_err(&h->pdev->dev, "cmd_alloc returned NULL!\n");
return SCSI_MLQUEUE_HOST_BUSY;
@@ -2334,6 +2392,261 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
return FAILED;
}
+static void swizzle_abort_tag(u8 *tag)
+{
+ u8 original_tag[8];
+
+ memcpy(original_tag, tag, 8);
+ tag[0] = original_tag[3];
+ tag[1] = original_tag[2];
+ tag[2] = original_tag[1];
+ tag[3] = original_tag[0];
+ tag[4] = original_tag[7];
+ tag[5] = original_tag[6];
+ tag[6] = original_tag[5];
+ tag[7] = original_tag[4];
+}
+
+static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr,
+ struct CommandList *abort, int swizzle)
+{
+ int rc = IO_OK;
+ struct CommandList *c;
+ struct ErrorInfo *ei;
+
+ c = cmd_special_alloc(h);
+ if (c == NULL) { /* trouble... */
+ dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+ return -ENOMEM;
+ }
+
+ fill_cmd(c, HPSA_ABORT_MSG, h, abort, 0, 0, scsi3addr, TYPE_MSG);
+ if (swizzle)
+ swizzle_abort_tag(&c->Request.CDB[4]);
+ hpsa_scsi_do_simple_cmd_core(h, c);
+ dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: do_simple_cmd_core completed.\n",
+ __func__, abort->Header.Tag.upper, abort->Header.Tag.lower);
+ /* no unmap needed here because no data xfer. */
+
+ ei = c->err_info;
+ switch (ei->CommandStatus) {
+ case CMD_SUCCESS:
+ break;
+ case CMD_UNABORTABLE: /* Very common, don't make noise. */
+ rc = -1;
+ break;
+ default:
+ dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: interpreting error.\n",
+ __func__, abort->Header.Tag.upper,
+ abort->Header.Tag.lower);
+ hpsa_scsi_interpret_error(c);
+ rc = -1;
+ break;
+ }
+ cmd_special_free(h, c);
+ dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: Finished.\n", __func__,
+ abort->Header.Tag.upper, abort->Header.Tag.lower);
+ return rc;
+}
+
+/*
+ * hpsa_find_cmd_in_queue
+ *
+ * Used to determine whether a command (find) is still present
+ * in queue_head. Optionally excludes the last element of queue_head.
+ *
+ * This is used to avoid unnecessary aborts. Commands in h->reqQ have
+ * not yet been submitted, and so can be aborted by the driver without
+ * sending an abort to the hardware.
+ *
+ * Returns pointer to command if found in queue, NULL otherwise.
+ */
+static struct CommandList *hpsa_find_cmd_in_queue(struct ctlr_info *h,
+ struct scsi_cmnd *find, struct list_head *queue_head)
+{
+ unsigned long flags;
+ struct CommandList *c = NULL; /* ptr into cmpQ */
+
+ if (!find)
+ return 0;
+ spin_lock_irqsave(&h->lock, flags);
+ list_for_each_entry(c, queue_head, list) {
+ if (c->scsi_cmd == NULL) /* e.g.: passthru ioctl */
+ continue;
+ if (c->scsi_cmd == find) {
+ spin_unlock_irqrestore(&h->lock, flags);
+ return c;
+ }
+ }
+ spin_unlock_irqrestore(&h->lock, flags);
+ return NULL;
+}
+
+static struct CommandList *hpsa_find_cmd_in_queue_by_tag(struct ctlr_info *h,
+ u8 *tag, struct list_head *queue_head)
+{
+ unsigned long flags;
+ struct CommandList *c;
+
+ spin_lock_irqsave(&h->lock, flags);
+ list_for_each_entry(c, queue_head, list) {
+ if (memcmp(&c->Header.Tag, tag, 8) != 0)
+ continue;
+ spin_unlock_irqrestore(&h->lock, flags);
+ return c;
+ }
+ spin_unlock_irqrestore(&h->lock, flags);
+ return NULL;
+}
+
+/* Some Smart Arrays need the abort tag swizzled, and some don't. It's hard to
+ * tell which kind we're dealing with, so we send the abort both ways. There
+ * shouldn't be any collisions between swizzled and unswizzled tags due to the
+ * way we construct our tags but we check anyway in case the assumptions which
+ * make this true someday become false.
+ */
+static int hpsa_send_abort_both_ways(struct ctlr_info *h,
+ unsigned char *scsi3addr, struct CommandList *abort)
+{
+ u8 swizzled_tag[8];
+ struct CommandList *c;
+ int rc = 0, rc2 = 0;
+
+ /* we do not expect to find the swizzled tag in our queue, but
+ * check anyway just to be sure the assumptions which make this
+ * the case haven't become wrong.
+ */
+ memcpy(swizzled_tag, &abort->Request.CDB[4], 8);
+ swizzle_abort_tag(swizzled_tag);
+ c = hpsa_find_cmd_in_queue_by_tag(h, swizzled_tag, &h->cmpQ);
+ if (c != NULL) {
+ dev_warn(&h->pdev->dev, "Unexpectedly found byte-swapped tag in completion queue.\n");
+ return hpsa_send_abort(h, scsi3addr, abort, 0);
+ }
+ rc = hpsa_send_abort(h, scsi3addr, abort, 0);
+
+ /* if the command is still in our queue, we can't conclude that it was
+ * aborted (it might have just completed normally) but in any case
+ * we don't need to try to abort it another way.
+ */
+ c = hpsa_find_cmd_in_queue(h, abort->scsi_cmd, &h->cmpQ);
+ if (c)
+ rc2 = hpsa_send_abort(h, scsi3addr, abort, 1);
+ return rc && rc2;
+}
+
+/* Send an abort for the specified command.
+ * If the device and controller support it,
+ * send a task abort request.
+ */
+static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
+{
+
+ int i, rc;
+ struct ctlr_info *h;
+ struct hpsa_scsi_dev_t *dev;
+ struct CommandList *abort; /* pointer to command to be aborted */
+ struct CommandList *found;
+ struct scsi_cmnd *as; /* ptr to scsi cmd inside aborted command. */
+ char msg[256]; /* For debug messaging. */
+ int ml = 0;
+
+ /* Find the controller of the command to be aborted */
+ h = sdev_to_hba(sc->device);
+ if (WARN(h == NULL,
+ "ABORT REQUEST FAILED, Controller lookup failed.\n"))
+ return FAILED;
+
+ /* Check that controller supports some kind of task abort */
+ if (!(HPSATMF_PHYS_TASK_ABORT & h->TMFSupportFlags) &&
+ !(HPSATMF_LOG_TASK_ABORT & h->TMFSupportFlags))
+ return FAILED;
+
+ memset(msg, 0, sizeof(msg));
+ ml += sprintf(msg+ml, "ABORT REQUEST on C%d:B%d:T%d:L%d ",
+ h->scsi_host->host_no, sc->device->channel,
+ sc->device->id, sc->device->lun);
+
+ /* Find the device of the command to be aborted */
+ dev = sc->device->hostdata;
+ if (!dev) {
+ dev_err(&h->pdev->dev, "%s FAILED, Device lookup failed.\n",
+ msg);
+ return FAILED;
+ }
+
+ /* Get SCSI command to be aborted */
+ abort = (struct CommandList *) sc->host_scribble;
+ if (abort == NULL) {
+ dev_err(&h->pdev->dev, "%s FAILED, Command to abort is NULL.\n",
+ msg);
+ return FAILED;
+ }
+
+ ml += sprintf(msg+ml, "Tag:0x%08x:%08x ",
+ abort->Header.Tag.upper, abort->Header.Tag.lower);
+ as = (struct scsi_cmnd *) abort->scsi_cmd;
+ if (as != NULL)
+ ml += sprintf(msg+ml, "Command:0x%x SN:0x%lx ",
+ as->cmnd[0], as->serial_number);
+ dev_dbg(&h->pdev->dev, "%s\n", msg);
+ dev_warn(&h->pdev->dev, "Abort request on C%d:B%d:T%d:L%d\n",
+ h->scsi_host->host_no, dev->bus, dev->target, dev->lun);
+
+ /* Search reqQ to See if command is queued but not submitted,
+ * if so, complete the command with aborted status and remove
+ * it from the reqQ.
+ */
+ found = hpsa_find_cmd_in_queue(h, sc, &h->reqQ);
+ if (found) {
+ found->err_info->CommandStatus = CMD_ABORTED;
+ finish_cmd(found);
+ dev_info(&h->pdev->dev, "%s Request SUCCEEDED (driver queue).\n",
+ msg);
+ return SUCCESS;
+ }
+
+ /* not in reqQ, if also not in cmpQ, must have already completed */
+ found = hpsa_find_cmd_in_queue(h, sc, &h->cmpQ);
+ if (!found) {
+ dev_dbg(&h->pdev->dev, "%s Request FAILED (not known to driver).\n",
+ msg);
+ return SUCCESS;
+ }
+
+ /*
+ * Command is in flight, or possibly already completed
+ * by the firmware (but not to the scsi mid layer) but we can't
+ * distinguish which. Send the abort down.
+ */
+ rc = hpsa_send_abort_both_ways(h, dev->scsi3addr, abort);
+ if (rc != 0) {
+ dev_dbg(&h->pdev->dev, "%s Request FAILED.\n", msg);
+ dev_warn(&h->pdev->dev, "FAILED abort on device C%d:B%d:T%d:L%d\n",
+ h->scsi_host->host_no,
+ dev->bus, dev->target, dev->lun);
+ return FAILED;
+ }
+ dev_info(&h->pdev->dev, "%s REQUEST SUCCEEDED.\n", msg);
+
+ /* If the abort(s) above completed and actually aborted the
+ * command, then the command to be aborted should already be
+ * completed. If not, wait around a bit more to see if they
+ * manage to complete normally.
+ */
+#define ABORT_COMPLETE_WAIT_SECS 30
+ for (i = 0; i < ABORT_COMPLETE_WAIT_SECS * 10; i++) {
+ found = hpsa_find_cmd_in_queue(h, sc, &h->cmpQ);
+ if (!found)
+ return SUCCESS;
+ msleep(100);
+ }
+ dev_warn(&h->pdev->dev, "%s FAILED. Aborted command has not completed after %d seconds.\n",
+ msg, ABORT_COMPLETE_WAIT_SECS);
+ return FAILED;
+}
+
+
/*
* For operations that cannot sleep, a command block is allocated at init,
* and managed by cmd_alloc() and cmd_free() using a simple bitmap to track
@@ -2346,14 +2659,21 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
int i;
union u64bit temp64;
dma_addr_t cmd_dma_handle, err_dma_handle;
+ unsigned long flags;
+ spin_lock_irqsave(&h->lock, flags);
do {
i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds);
- if (i == h->nr_cmds)
+ if (i == h->nr_cmds) {
+ spin_unlock_irqrestore(&h->lock, flags);
return NULL;
+ }
} while (test_and_set_bit
(i & (BITS_PER_LONG - 1),
h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0);
+ h->nr_allocs++;
+ spin_unlock_irqrestore(&h->lock, flags);
+
c = h->cmd_pool + i;
memset(c, 0, sizeof(*c));
cmd_dma_handle = h->cmd_pool_dhandle
@@ -2362,7 +2682,6 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
memset(c->err_info, 0, sizeof(*c->err_info));
err_dma_handle = h->errinfo_pool_dhandle
+ i * sizeof(*c->err_info);
- h->nr_allocs++;
c->cmdindex = i;
@@ -2418,11 +2737,14 @@ static struct CommandList *cmd_special_alloc(struct ctlr_info *h)
static void cmd_free(struct ctlr_info *h, struct CommandList *c)
{
int i;
+ unsigned long flags;
i = c - h->cmd_pool;
+ spin_lock_irqsave(&h->lock, flags);
clear_bit(i & (BITS_PER_LONG - 1),
h->cmd_pool_bits + (i / BITS_PER_LONG));
h->nr_frees++;
+ spin_unlock_irqrestore(&h->lock, flags);
}
static void cmd_special_free(struct ctlr_info *h, struct CommandList *c)
@@ -2866,6 +3188,7 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
int cmd_type)
{
int pci_dir = XFER_NONE;
+ struct CommandList *a; /* for commands to be aborted */
c->cmd_type = CMD_IOCTL_PEND;
c->Header.ReplyQueue = 0;
@@ -2949,8 +3272,35 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
c->Request.CDB[5] = 0x00;
c->Request.CDB[6] = 0x00;
c->Request.CDB[7] = 0x00;
+ break;
+ case HPSA_ABORT_MSG:
+ a = buff; /* point to command to be aborted */
+ dev_dbg(&h->pdev->dev, "Abort Tag:0x%08x:%08x using request Tag:0x%08x:%08x\n",
+ a->Header.Tag.upper, a->Header.Tag.lower,
+ c->Header.Tag.upper, c->Header.Tag.lower);
+ c->Request.CDBLen = 16;
+ c->Request.Type.Type = TYPE_MSG;
+ c->Request.Type.Attribute = ATTR_SIMPLE;
+ c->Request.Type.Direction = XFER_WRITE;
+ c->Request.Timeout = 0; /* Don't time out */
+ c->Request.CDB[0] = HPSA_TASK_MANAGEMENT;
+ c->Request.CDB[1] = HPSA_TMF_ABORT_TASK;
+ c->Request.CDB[2] = 0x00; /* reserved */
+ c->Request.CDB[3] = 0x00; /* reserved */
+ /* Tag to abort goes in CDB[4]-CDB[11] */
+ c->Request.CDB[4] = a->Header.Tag.lower & 0xFF;
+ c->Request.CDB[5] = (a->Header.Tag.lower >> 8) & 0xFF;
+ c->Request.CDB[6] = (a->Header.Tag.lower >> 16) & 0xFF;
+ c->Request.CDB[7] = (a->Header.Tag.lower >> 24) & 0xFF;
+ c->Request.CDB[8] = a->Header.Tag.upper & 0xFF;
+ c->Request.CDB[9] = (a->Header.Tag.upper >> 8) & 0xFF;
+ c->Request.CDB[10] = (a->Header.Tag.upper >> 16) & 0xFF;
+ c->Request.CDB[11] = (a->Header.Tag.upper >> 24) & 0xFF;
+ c->Request.CDB[12] = 0x00; /* reserved */
+ c->Request.CDB[13] = 0x00; /* reserved */
+ c->Request.CDB[14] = 0x00; /* reserved */
+ c->Request.CDB[15] = 0x00; /* reserved */
break;
-
default:
dev_warn(&h->pdev->dev, "unknown message type %d\n",
cmd);
@@ -2998,7 +3348,9 @@ static void __iomem *remap_pci_mem(ulong base, ulong size)
static void start_io(struct ctlr_info *h)
{
struct CommandList *c;
+ unsigned long flags;
+ spin_lock_irqsave(&h->lock, flags);
while (!list_empty(&h->reqQ)) {
c = list_entry(h->reqQ.next, struct CommandList, list);
/* can't do anything if fifo is full */
@@ -3011,17 +3363,28 @@ static void start_io(struct ctlr_info *h)
removeQ(c);
h->Qdepth--;
- /* Tell the controller execute command */
- h->access.submit_command(h, c);
-
/* Put job onto the completed Q */
addQ(&h->cmpQ, c);
+
+ /* Must increment commands_outstanding before unlocking
+ * and submitting to avoid race checking for fifo full
+ * condition.
+ */
+ h->commands_outstanding++;
+ if (h->commands_outstanding > h->max_outstanding)
+ h->max_outstanding = h->commands_outstanding;
+
+ /* Tell the controller execute command */
+ spin_unlock_irqrestore(&h->lock, flags);
+ h->access.submit_command(h, c);
+ spin_lock_irqsave(&h->lock, flags);
}
+ spin_unlock_irqrestore(&h->lock, flags);
}
-static inline unsigned long get_next_completion(struct ctlr_info *h)
+static inline unsigned long get_next_completion(struct ctlr_info *h, u8 q)
{
- return h->access.command_completed(h);
+ return h->access.command_completed(h, q);
}
static inline bool interrupt_pending(struct ctlr_info *h)
@@ -3045,9 +3408,14 @@ static inline int bad_tag(struct ctlr_info *h, u32 tag_index,
return 0;
}
-static inline void finish_cmd(struct CommandList *c, u32 raw_tag)
+static inline void finish_cmd(struct CommandList *c)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&c->h->lock, flags);
removeQ(c);
+ spin_unlock_irqrestore(&c->h->lock, flags);
+ dial_up_lockup_detection_on_fw_flash_complete(c->h, c);
if (likely(c->cmd_type == CMD_SCSI))
complete_scsi_command(c);
else if (c->cmd_type == CMD_IOCTL_PEND)
@@ -3075,36 +3443,38 @@ static inline u32 hpsa_tag_discard_error_bits(struct ctlr_info *h, u32 tag)
}
/* process completion of an indexed ("direct lookup") command */
-static inline u32 process_indexed_cmd(struct ctlr_info *h,
+static inline void process_indexed_cmd(struct ctlr_info *h,
u32 raw_tag)
{
u32 tag_index;
struct CommandList *c;
tag_index = hpsa_tag_to_index(raw_tag);
- if (bad_tag(h, tag_index, raw_tag))
- return next_command(h);
- c = h->cmd_pool + tag_index;
- finish_cmd(c, raw_tag);
- return next_command(h);
+ if (!bad_tag(h, tag_index, raw_tag)) {
+ c = h->cmd_pool + tag_index;
+ finish_cmd(c);
+ }
}
/* process completion of a non-indexed command */
-static inline u32 process_nonindexed_cmd(struct ctlr_info *h,
+static inline void process_nonindexed_cmd(struct ctlr_info *h,
u32 raw_tag)
{
u32 tag;
struct CommandList *c = NULL;
+ unsigned long flags;
tag = hpsa_tag_discard_error_bits(h, raw_tag);
+ spin_lock_irqsave(&h->lock, flags);
list_for_each_entry(c, &h->cmpQ, list) {
if ((c->busaddr & 0xFFFFFFE0) == (tag & 0xFFFFFFE0)) {
- finish_cmd(c, raw_tag);
- return next_command(h);
+ spin_unlock_irqrestore(&h->lock, flags);
+ finish_cmd(c);
+ return;
}
}
+ spin_unlock_irqrestore(&h->lock, flags);
bad_tag(h, h->nr_cmds + 1, raw_tag);
- return next_command(h);
}
/* Some controllers, like p400, will give us one interrupt
@@ -3126,10 +3496,20 @@ static int ignore_bogus_interrupt(struct ctlr_info *h)
return 1;
}
-static irqreturn_t hpsa_intx_discard_completions(int irq, void *dev_id)
+/*
+ * Convert &h->q[x] (passed to interrupt handlers) back to h.
+ * Relies on (h-q[x] == x) being true for x such that
+ * 0 <= x < MAX_REPLY_QUEUES.
+ */
+static struct ctlr_info *queue_to_hba(u8 *queue)
{
- struct ctlr_info *h = dev_id;
- unsigned long flags;
+ return container_of((queue - *queue), struct ctlr_info, q[0]);
+}
+
+static irqreturn_t hpsa_intx_discard_completions(int irq, void *queue)
+{
+ struct ctlr_info *h = queue_to_hba(queue);
+ u8 q = *(u8 *) queue;
u32 raw_tag;
if (ignore_bogus_interrupt(h))
@@ -3137,74 +3517,68 @@ static irqreturn_t hpsa_intx_discard_completions(int irq, void *dev_id)
if (interrupt_not_for_us(h))
return IRQ_NONE;
- spin_lock_irqsave(&h->lock, flags);
h->last_intr_timestamp = get_jiffies_64();
while (interrupt_pending(h)) {
- raw_tag = get_next_completion(h);
+ raw_tag = get_next_completion(h, q);
while (raw_tag != FIFO_EMPTY)
- raw_tag = next_command(h);
+ raw_tag = next_command(h, q);
}
- spin_unlock_irqrestore(&h->lock, flags);
return IRQ_HANDLED;
}
-static irqreturn_t hpsa_msix_discard_completions(int irq, void *dev_id)
+static irqreturn_t hpsa_msix_discard_completions(int irq, void *queue)
{
- struct ctlr_info *h = dev_id;
- unsigned long flags;
+ struct ctlr_info *h = queue_to_hba(queue);
u32 raw_tag;
+ u8 q = *(u8 *) queue;
if (ignore_bogus_interrupt(h))
return IRQ_NONE;
- spin_lock_irqsave(&h->lock, flags);
h->last_intr_timestamp = get_jiffies_64();
- raw_tag = get_next_completion(h);
+ raw_tag = get_next_completion(h, q);
while (raw_tag != FIFO_EMPTY)
- raw_tag = next_command(h);
- spin_unlock_irqrestore(&h->lock, flags);
+ raw_tag = next_command(h, q);
return IRQ_HANDLED;
}
-static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id)
+static irqreturn_t do_hpsa_intr_intx(int irq, void *queue)
{
- struct ctlr_info *h = dev_id;
- unsigned long flags;
+ struct ctlr_info *h = queue_to_hba((u8 *) queue);
u32 raw_tag;
+ u8 q = *(u8 *) queue;
if (interrupt_not_for_us(h))
return IRQ_NONE;
- spin_lock_irqsave(&h->lock, flags);
h->last_intr_timestamp = get_jiffies_64();
while (interrupt_pending(h)) {
- raw_tag = get_next_completion(h);
+ raw_tag = get_next_completion(h, q);
while (raw_tag != FIFO_EMPTY) {
- if (hpsa_tag_contains_index(raw_tag))
- raw_tag = process_indexed_cmd(h, raw_tag);
+ if (likely(hpsa_tag_contains_index(raw_tag)))
+ process_indexed_cmd(h, raw_tag);
else
- raw_tag = process_nonindexed_cmd(h, raw_tag);
+ process_nonindexed_cmd(h, raw_tag);
+ raw_tag = next_command(h, q);
}
}
- spin_unlock_irqrestore(&h->lock, flags);
return IRQ_HANDLED;
}
-static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id)
+static irqreturn_t do_hpsa_intr_msi(int irq, void *queue)
{
- struct ctlr_info *h = dev_id;
- unsigned long flags;
+ struct ctlr_info *h = queue_to_hba(queue);
u32 raw_tag;
+ u8 q = *(u8 *) queue;
- spin_lock_irqsave(&h->lock, flags);
h->last_intr_timestamp = get_jiffies_64();
- raw_tag = get_next_completion(h);
+ raw_tag = get_next_completion(h, q);
while (raw_tag != FIFO_EMPTY) {
- if (hpsa_tag_contains_index(raw_tag))
- raw_tag = process_indexed_cmd(h, raw_tag);
+ if (likely(hpsa_tag_contains_index(raw_tag)))
+ process_indexed_cmd(h, raw_tag);
else
- raw_tag = process_nonindexed_cmd(h, raw_tag);
+ process_nonindexed_cmd(h, raw_tag);
+ raw_tag = next_command(h, q);
}
- spin_unlock_irqrestore(&h->lock, flags);
return IRQ_HANDLED;
}
@@ -3638,10 +4012,13 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr)
static void __devinit hpsa_interrupt_mode(struct ctlr_info *h)
{
#ifdef CONFIG_PCI_MSI
- int err;
- struct msix_entry hpsa_msix_entries[4] = { {0, 0}, {0, 1},
- {0, 2}, {0, 3}
- };
+ int err, i;
+ struct msix_entry hpsa_msix_entries[MAX_REPLY_QUEUES];
+
+ for (i = 0; i < MAX_REPLY_QUEUES; i++) {
+ hpsa_msix_entries[i].vector = 0;
+ hpsa_msix_entries[i].entry = i;
+ }
/* Some boards advertise MSI but don't really support it */
if ((h->board_id == 0x40700E11) || (h->board_id == 0x40800E11) ||
@@ -3649,12 +4026,11 @@ static void __devinit hpsa_interrupt_mode(struct ctlr_info *h)
goto default_int_mode;
if (pci_find_capability(h->pdev, PCI_CAP_ID_MSIX)) {
dev_info(&h->pdev->dev, "MSIX\n");
- err = pci_enable_msix(h->pdev, hpsa_msix_entries, 4);
+ err = pci_enable_msix(h->pdev, hpsa_msix_entries,
+ MAX_REPLY_QUEUES);
if (!err) {
- h->intr[0] = hpsa_msix_entries[0].vector;
- h->intr[1] = hpsa_msix_entries[1].vector;
- h->intr[2] = hpsa_msix_entries[2].vector;
- h->intr[3] = hpsa_msix_entries[3].vector;
+ for (i = 0; i < MAX_REPLY_QUEUES; i++)
+ h->intr[i] = hpsa_msix_entries[i].vector;
h->msix_vector = 1;
return;
}
@@ -3705,14 +4081,6 @@ static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
return ARRAY_SIZE(products) - 1; /* generic unknown smart array */
}
-static inline bool hpsa_board_disabled(struct pci_dev *pdev)
-{
- u16 command;
-
- (void) pci_read_config_word(pdev, PCI_COMMAND, &command);
- return ((command & PCI_COMMAND_MEMORY) == 0);
-}
-
static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
unsigned long *memory_bar)
{
@@ -3838,14 +4206,14 @@ static void __devinit hpsa_find_board_params(struct ctlr_info *h)
h->maxsgentries = 31; /* default to traditional values */
h->chainsize = 0;
}
+
+ /* Find out what task management functions are supported and cache */
+ h->TMFSupportFlags = readl(&(h->cfgtable->TMFSupportFlags));
}
static inline bool hpsa_CISS_signature_present(struct ctlr_info *h)
{
- if ((readb(&h->cfgtable->Signature[0]) != 'C') ||
- (readb(&h->cfgtable->Signature[1]) != 'I') ||
- (readb(&h->cfgtable->Signature[2]) != 'S') ||
- (readb(&h->cfgtable->Signature[3]) != 'S')) {
+ if (!check_signature(h->cfgtable->Signature, "CISS", 4)) {
dev_warn(&h->pdev->dev, "not a valid CISS config table\n");
return false;
}
@@ -3932,11 +4300,6 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h)
h->product_name = products[prod_index].product_name;
h->access = *(products[prod_index].access);
- if (hpsa_board_disabled(h->pdev)) {
- dev_warn(&h->pdev->dev, "controller appears to be disabled\n");
- return -ENODEV;
- }
-
pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S |
PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
@@ -3946,6 +4309,9 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h)
return err;
}
+ /* Enable bus mastering (pci_disable_device may disable this) */
+ pci_set_master(h->pdev);
+
err = pci_request_regions(h->pdev, HPSA);
if (err) {
dev_err(&h->pdev->dev,
@@ -3987,10 +4353,7 @@ err_out_free_res:
iounmap(h->cfgtable);
if (h->vaddr)
iounmap(h->vaddr);
- /*
- * Deliberately omit pci_disable_device(): it does something nasty to
- * Smart Array controllers that pci_enable_device does not undo
- */
+ pci_disable_device(h->pdev);
pci_release_regions(h->pdev);
return err;
}
@@ -4081,14 +4444,33 @@ static int hpsa_request_irq(struct ctlr_info *h,
irqreturn_t (*msixhandler)(int, void *),
irqreturn_t (*intxhandler)(int, void *))
{
- int rc;
+ int rc, i;
- if (h->msix_vector || h->msi_vector)
- rc = request_irq(h->intr[h->intr_mode], msixhandler,
- 0, h->devname, h);
- else
- rc = request_irq(h->intr[h->intr_mode], intxhandler,
- IRQF_SHARED, h->devname, h);
+ /*
+ * initialize h->q[x] = x so that interrupt handlers know which
+ * queue to process.
+ */
+ for (i = 0; i < MAX_REPLY_QUEUES; i++)
+ h->q[i] = (u8) i;
+
+ if (h->intr_mode == PERF_MODE_INT && h->msix_vector) {
+ /* If performant mode and MSI-X, use multiple reply queues */
+ for (i = 0; i < MAX_REPLY_QUEUES; i++)
+ rc = request_irq(h->intr[i], msixhandler,
+ 0, h->devname,
+ &h->q[i]);
+ } else {
+ /* Use single reply pool */
+ if (h->msix_vector || h->msi_vector) {
+ rc = request_irq(h->intr[h->intr_mode],
+ msixhandler, 0, h->devname,
+ &h->q[h->intr_mode]);
+ } else {
+ rc = request_irq(h->intr[h->intr_mode],
+ intxhandler, IRQF_SHARED, h->devname,
+ &h->q[h->intr_mode]);
+ }
+ }
if (rc) {
dev_err(&h->pdev->dev, "unable to get irq %d for %s\n",
h->intr[h->intr_mode], h->devname);
@@ -4121,15 +4503,38 @@ static int __devinit hpsa_kdump_soft_reset(struct ctlr_info *h)
return 0;
}
-static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h)
+static void free_irqs(struct ctlr_info *h)
{
- free_irq(h->intr[h->intr_mode], h);
+ int i;
+
+ if (!h->msix_vector || h->intr_mode != PERF_MODE_INT) {
+ /* Single reply queue, only one irq to free */
+ i = h->intr_mode;
+ free_irq(h->intr[i], &h->q[i]);
+ return;
+ }
+
+ for (i = 0; i < MAX_REPLY_QUEUES; i++)
+ free_irq(h->intr[i], &h->q[i]);
+}
+
+static void hpsa_free_irqs_and_disable_msix(struct ctlr_info *h)
+{
+ free_irqs(h);
#ifdef CONFIG_PCI_MSI
- if (h->msix_vector)
- pci_disable_msix(h->pdev);
- else if (h->msi_vector)
- pci_disable_msi(h->pdev);
+ if (h->msix_vector) {
+ if (h->pdev->msix_enabled)
+ pci_disable_msix(h->pdev);
+ } else if (h->msi_vector) {
+ if (h->pdev->msi_enabled)
+ pci_disable_msi(h->pdev);
+ }
#endif /* CONFIG_PCI_MSI */
+}
+
+static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h)
+{
+ hpsa_free_irqs_and_disable_msix(h);
hpsa_free_sg_chain_blocks(h);
hpsa_free_cmd_pool(h);
kfree(h->blockFetchTable);
@@ -4165,7 +4570,7 @@ static void fail_all_cmds_on_list(struct ctlr_info *h, struct list_head *list)
while (!list_empty(list)) {
c = list_entry(list->next, struct CommandList, list);
c->err_info->CommandStatus = CMD_HARDWARE_ERR;
- finish_cmd(c, c->Header.Tag.lower);
+ finish_cmd(c);
}
}
@@ -4188,9 +4593,6 @@ static void controller_lockup_detected(struct ctlr_info *h)
spin_unlock_irqrestore(&h->lock, flags);
}
-#define HEARTBEAT_SAMPLE_INTERVAL (10 * HZ)
-#define HEARTBEAT_CHECK_MINIMUM_INTERVAL (HEARTBEAT_SAMPLE_INTERVAL / 2)
-
static void detect_controller_lockup(struct ctlr_info *h)
{
u64 now;
@@ -4201,7 +4603,7 @@ static void detect_controller_lockup(struct ctlr_info *h)
now = get_jiffies_64();
/* If we've received an interrupt recently, we're ok. */
if (time_after64(h->last_intr_timestamp +
- (HEARTBEAT_CHECK_MINIMUM_INTERVAL), now))
+ (h->heartbeat_sample_interval), now))
return;
/*
@@ -4210,7 +4612,7 @@ static void detect_controller_lockup(struct ctlr_info *h)
* otherwise don't care about signals in this thread.
*/
if (time_after64(h->last_heartbeat_timestamp +
- (HEARTBEAT_CHECK_MINIMUM_INTERVAL), now))
+ (h->heartbeat_sample_interval), now))
return;
/* If heartbeat has not changed since we last looked, we're not ok. */
@@ -4252,6 +4654,7 @@ static void add_ctlr_to_lockup_detector_list(struct ctlr_info *h)
{
unsigned long flags;
+ h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL;
spin_lock_irqsave(&lockup_detector_lock, flags);
list_add_tail(&h->lockup_list, &hpsa_ctlr_list);
spin_unlock_irqrestore(&lockup_detector_lock, flags);
@@ -4391,7 +4794,7 @@ reinit_after_soft_reset:
spin_lock_irqsave(&h->lock, flags);
h->access.set_intr_mask(h, HPSA_INTR_OFF);
spin_unlock_irqrestore(&h->lock, flags);
- free_irq(h->intr[h->intr_mode], h);
+ free_irqs(h);
rc = hpsa_request_irq(h, hpsa_msix_discard_completions,
hpsa_intx_discard_completions);
if (rc) {
@@ -4441,7 +4844,7 @@ reinit_after_soft_reset:
clean4:
hpsa_free_sg_chain_blocks(h);
hpsa_free_cmd_pool(h);
- free_irq(h->intr[h->intr_mode], h);
+ free_irqs(h);
clean2:
clean1:
kfree(h);
@@ -4484,13 +4887,7 @@ static void hpsa_shutdown(struct pci_dev *pdev)
*/
hpsa_flush_cache(h);
h->access.set_intr_mask(h, HPSA_INTR_OFF);
- free_irq(h->intr[h->intr_mode], h);
-#ifdef CONFIG_PCI_MSI
- if (h->msix_vector)
- pci_disable_msix(h->pdev);
- else if (h->msi_vector)
- pci_disable_msi(h->pdev);
-#endif /* CONFIG_PCI_MSI */
+ hpsa_free_irqs_and_disable_msix(h);
}
static void __devexit hpsa_free_device_info(struct ctlr_info *h)
@@ -4529,10 +4926,7 @@ static void __devexit hpsa_remove_one(struct pci_dev *pdev)
kfree(h->cmd_pool_bits);
kfree(h->blockFetchTable);
kfree(h->hba_inquiry_data);
- /*
- * Deliberately omit pci_disable_device(): it does something nasty to
- * Smart Array controllers that pci_enable_device does not undo
- */
+ pci_disable_device(pdev);
pci_release_regions(pdev);
pci_set_drvdata(pdev, NULL);
kfree(h);
@@ -4627,11 +5021,8 @@ static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h,
* 10 = 6 s/g entry or 24k
*/
- h->reply_pool_wraparound = 1; /* spec: init to 1 */
-
/* Controller spec: zero out this buffer. */
memset(h->reply_pool, 0, h->reply_pool_size);
- h->reply_pool_head = h->reply_pool;
bft[7] = SG_ENTRIES_IN_CMD + 4;
calc_bucket_map(bft, ARRAY_SIZE(bft),
@@ -4641,12 +5032,19 @@ static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h,
/* size of controller ring buffer */
writel(h->max_commands, &h->transtable->RepQSize);
- writel(1, &h->transtable->RepQCount);
+ writel(h->nreply_queues, &h->transtable->RepQCount);
writel(0, &h->transtable->RepQCtrAddrLow32);
writel(0, &h->transtable->RepQCtrAddrHigh32);
- writel(h->reply_pool_dhandle, &h->transtable->RepQAddr0Low32);
- writel(0, &h->transtable->RepQAddr0High32);
- writel(CFGTBL_Trans_Performant | use_short_tags,
+
+ for (i = 0; i < h->nreply_queues; i++) {
+ writel(0, &h->transtable->RepQAddr[i].upper);
+ writel(h->reply_pool_dhandle +
+ (h->max_commands * sizeof(u64) * i),
+ &h->transtable->RepQAddr[i].lower);
+ }
+
+ writel(CFGTBL_Trans_Performant | use_short_tags |
+ CFGTBL_Trans_enable_directed_msix,
&(h->cfgtable->HostWrite.TransportRequest));
writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
hpsa_wait_for_mode_change_ack(h);
@@ -4664,6 +5062,7 @@ static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h,
static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
{
u32 trans_support;
+ int i;
if (hpsa_simple_mode)
return;
@@ -4672,12 +5071,20 @@ static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
if (!(trans_support & PERFORMANT_MODE))
return;
+ h->nreply_queues = h->msix_vector ? MAX_REPLY_QUEUES : 1;
hpsa_get_max_perf_mode_cmds(h);
/* Performant mode ring buffer and supporting data structures */
- h->reply_pool_size = h->max_commands * sizeof(u64);
+ h->reply_pool_size = h->max_commands * sizeof(u64) * h->nreply_queues;
h->reply_pool = pci_alloc_consistent(h->pdev, h->reply_pool_size,
&(h->reply_pool_dhandle));
+ for (i = 0; i < h->nreply_queues; i++) {
+ h->reply_queue[i].head = &h->reply_pool[h->max_commands * i];
+ h->reply_queue[i].size = h->max_commands;
+ h->reply_queue[i].wraparound = 1; /* spec: init to 1 */
+ h->reply_queue[i].current_entry = 0;
+ }
+
/* Need a block fetch table for performant mode */
h->blockFetchTable = kmalloc(((SG_ENTRIES_IN_CMD + 1) *
sizeof(u32)), GFP_KERNEL);
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 7b28d54fa878..981647989bfd 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -34,7 +34,7 @@ struct access_method {
void (*set_intr_mask)(struct ctlr_info *h, unsigned long val);
unsigned long (*fifo_full)(struct ctlr_info *h);
bool (*intr_pending)(struct ctlr_info *h);
- unsigned long (*command_completed)(struct ctlr_info *h);
+ unsigned long (*command_completed)(struct ctlr_info *h, u8 q);
};
struct hpsa_scsi_dev_t {
@@ -48,6 +48,13 @@ struct hpsa_scsi_dev_t {
unsigned char raid_level; /* from inquiry page 0xC1 */
};
+struct reply_pool {
+ u64 *head;
+ size_t size;
+ u8 wraparound;
+ u32 current_entry;
+};
+
struct ctlr_info {
int ctlr;
char devname[8];
@@ -68,7 +75,7 @@ struct ctlr_info {
# define DOORBELL_INT 1
# define SIMPLE_MODE_INT 2
# define MEMQ_MODE_INT 3
- unsigned int intr[4];
+ unsigned int intr[MAX_REPLY_QUEUES];
unsigned int msix_vector;
unsigned int msi_vector;
int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */
@@ -78,7 +85,6 @@ struct ctlr_info {
struct list_head reqQ;
struct list_head cmpQ;
unsigned int Qdepth;
- unsigned int maxQsinceinit;
unsigned int maxSG;
spinlock_t lock;
int maxsgentries;
@@ -111,20 +117,45 @@ struct ctlr_info {
unsigned long transMethod;
/*
- * Performant mode completion buffer
+ * Performant mode completion buffers
*/
u64 *reply_pool;
- dma_addr_t reply_pool_dhandle;
- u64 *reply_pool_head;
size_t reply_pool_size;
- unsigned char reply_pool_wraparound;
+ struct reply_pool reply_queue[MAX_REPLY_QUEUES];
+ u8 nreply_queues;
+ dma_addr_t reply_pool_dhandle;
u32 *blockFetchTable;
unsigned char *hba_inquiry_data;
u64 last_intr_timestamp;
u32 last_heartbeat;
u64 last_heartbeat_timestamp;
+ u32 heartbeat_sample_interval;
+ atomic_t firmware_flash_in_progress;
u32 lockup_detected;
struct list_head lockup_list;
+ /* Address of h->q[x] is passed to intr handler to know which queue */
+ u8 q[MAX_REPLY_QUEUES];
+ u32 TMFSupportFlags; /* cache what task mgmt funcs are supported. */
+#define HPSATMF_BITS_SUPPORTED (1 << 0)
+#define HPSATMF_PHYS_LUN_RESET (1 << 1)
+#define HPSATMF_PHYS_NEX_RESET (1 << 2)
+#define HPSATMF_PHYS_TASK_ABORT (1 << 3)
+#define HPSATMF_PHYS_TSET_ABORT (1 << 4)
+#define HPSATMF_PHYS_CLEAR_ACA (1 << 5)
+#define HPSATMF_PHYS_CLEAR_TSET (1 << 6)
+#define HPSATMF_PHYS_QRY_TASK (1 << 7)
+#define HPSATMF_PHYS_QRY_TSET (1 << 8)
+#define HPSATMF_PHYS_QRY_ASYNC (1 << 9)
+#define HPSATMF_MASK_SUPPORTED (1 << 16)
+#define HPSATMF_LOG_LUN_RESET (1 << 17)
+#define HPSATMF_LOG_NEX_RESET (1 << 18)
+#define HPSATMF_LOG_TASK_ABORT (1 << 19)
+#define HPSATMF_LOG_TSET_ABORT (1 << 20)
+#define HPSATMF_LOG_CLEAR_ACA (1 << 21)
+#define HPSATMF_LOG_CLEAR_TSET (1 << 22)
+#define HPSATMF_LOG_QRY_TASK (1 << 23)
+#define HPSATMF_LOG_QRY_TSET (1 << 24)
+#define HPSATMF_LOG_QRY_ASYNC (1 << 25)
};
#define HPSA_ABORT_MSG 0
#define HPSA_DEVICE_RESET_MSG 1
@@ -216,9 +247,6 @@ static void SA5_submit_command(struct ctlr_info *h,
c->Header.Tag.lower);
writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
(void) readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
- h->commands_outstanding++;
- if (h->commands_outstanding > h->max_outstanding)
- h->max_outstanding = h->commands_outstanding;
}
/*
@@ -254,16 +282,17 @@ static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val)
}
}
-static unsigned long SA5_performant_completed(struct ctlr_info *h)
+static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
{
- unsigned long register_value = FIFO_EMPTY;
+ struct reply_pool *rq = &h->reply_queue[q];
+ unsigned long flags, register_value = FIFO_EMPTY;
- /* flush the controller write of the reply queue by reading
- * outbound doorbell status register.
- */
- register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
/* msi auto clears the interrupt pending bit. */
if (!(h->msi_vector || h->msix_vector)) {
+ /* flush the controller write of the reply queue by reading
+ * outbound doorbell status register.
+ */
+ register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
writel(SA5_OUTDB_CLEAR_PERF_BIT, h->vaddr + SA5_OUTDB_CLEAR);
/* Do a read in order to flush the write to the controller
* (as per spec.)
@@ -271,19 +300,20 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h)
register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
}
- if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
- register_value = *(h->reply_pool_head);
- (h->reply_pool_head)++;
+ if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
+ register_value = rq->head[rq->current_entry];
+ rq->current_entry++;
+ spin_lock_irqsave(&h->lock, flags);
h->commands_outstanding--;
+ spin_unlock_irqrestore(&h->lock, flags);
} else {
register_value = FIFO_EMPTY;
}
/* Check for wraparound */
- if (h->reply_pool_head == (h->reply_pool + h->max_commands)) {
- h->reply_pool_head = h->reply_pool;
- h->reply_pool_wraparound ^= 1;
+ if (rq->current_entry == h->max_commands) {
+ rq->current_entry = 0;
+ rq->wraparound ^= 1;
}
-
return register_value;
}
@@ -303,13 +333,18 @@ static unsigned long SA5_fifo_full(struct ctlr_info *h)
* returns value read from hardware.
* returns FIFO_EMPTY if there is nothing to read
*/
-static unsigned long SA5_completed(struct ctlr_info *h)
+static unsigned long SA5_completed(struct ctlr_info *h,
+ __attribute__((unused)) u8 q)
{
unsigned long register_value
= readl(h->vaddr + SA5_REPLY_PORT_OFFSET);
+ unsigned long flags;
- if (register_value != FIFO_EMPTY)
+ if (register_value != FIFO_EMPTY) {
+ spin_lock_irqsave(&h->lock, flags);
h->commands_outstanding--;
+ spin_unlock_irqrestore(&h->lock, flags);
+ }
#ifdef HPSA_DEBUG
if (register_value != FIFO_EMPTY)
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 8049815d8c1e..a894f2eca7ac 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -82,6 +82,29 @@
#define TYPE_CMD 0x00
#define TYPE_MSG 0x01
+/* Message Types */
+#define HPSA_TASK_MANAGEMENT 0x00
+#define HPSA_RESET 0x01
+#define HPSA_SCAN 0x02
+#define HPSA_NOOP 0x03
+
+#define HPSA_CTLR_RESET_TYPE 0x00
+#define HPSA_BUS_RESET_TYPE 0x01
+#define HPSA_TARGET_RESET_TYPE 0x03
+#define HPSA_LUN_RESET_TYPE 0x04
+#define HPSA_NEXUS_RESET_TYPE 0x05
+
+/* Task Management Functions */
+#define HPSA_TMF_ABORT_TASK 0x00
+#define HPSA_TMF_ABORT_TASK_SET 0x01
+#define HPSA_TMF_CLEAR_ACA 0x02
+#define HPSA_TMF_CLEAR_TASK_SET 0x03
+#define HPSA_TMF_QUERY_TASK 0x04
+#define HPSA_TMF_QUERY_TASK_SET 0x05
+#define HPSA_TMF_QUERY_ASYNCEVENT 0x06
+
+
+
/* config space register offsets */
#define CFG_VENDORID 0x00
#define CFG_DEVICEID 0x02
@@ -106,6 +129,7 @@
#define CFGTBL_Trans_Simple 0x00000002l
#define CFGTBL_Trans_Performant 0x00000004l
#define CFGTBL_Trans_use_short_tags 0x20000000l
+#define CFGTBL_Trans_enable_directed_msix (1 << 30)
#define CFGTBL_BusType_Ultra2 0x00000001l
#define CFGTBL_BusType_Ultra3 0x00000002l
@@ -162,6 +186,7 @@ struct SenseSubsystem_info {
#define BMIC_WRITE 0x27
#define BMIC_CACHE_FLUSH 0xc2
#define HPSA_CACHE_FLUSH 0x01 /* C2 was already being used by HPSA */
+#define BMIC_FLASH_FIRMWARE 0xF7
/* Command List Structure */
union SCSI3Addr {
@@ -337,11 +362,17 @@ struct CfgTable {
u32 MaxPhysicalDevices;
u32 MaxPhysicalDrivesPerLogicalUnit;
u32 MaxPerformantModeCommands;
- u8 reserved[0x78 - 0x58];
+ u32 MaxBlockFetch;
+ u32 PowerConservationSupport;
+ u32 PowerConservationEnable;
+ u32 TMFSupportFlags;
+ u8 TMFTagMask[8];
+ u8 reserved[0x78 - 0x70];
u32 misc_fw_support; /* offset 0x78 */
#define MISC_FW_DOORBELL_RESET (0x02)
#define MISC_FW_DOORBELL_RESET2 (0x010)
u8 driver_version[32];
+
};
#define NUM_BLOCKFETCH_ENTRIES 8
@@ -351,8 +382,8 @@ struct TransTable_struct {
u32 RepQCount;
u32 RepQCtrAddrLow32;
u32 RepQCtrAddrHigh32;
- u32 RepQAddr0Low32;
- u32 RepQAddr0High32;
+#define MAX_REPLY_QUEUES 8
+ struct vals32 RepQAddr[MAX_REPLY_QUEUES];
};
struct hpsa_pci_info {
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index d4bf9c12ecd4..45385f531649 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -192,22 +192,27 @@ static bool sci_controller_completion_queue_has_entries(struct isci_host *ihost)
static bool sci_controller_isr(struct isci_host *ihost)
{
- if (sci_controller_completion_queue_has_entries(ihost)) {
+ if (sci_controller_completion_queue_has_entries(ihost))
return true;
- } else {
- /*
- * we have a spurious interrupt it could be that we have already
- * emptied the completion queue from a previous interrupt */
- writel(SMU_ISR_COMPLETION, &ihost->smu_registers->interrupt_status);
- /*
- * There is a race in the hardware that could cause us not to be notified
- * of an interrupt completion if we do not take this step. We will mask
- * then unmask the interrupts so if there is another interrupt pending
- * the clearing of the interrupt source we get the next interrupt message. */
+ /* we have a spurious interrupt it could be that we have already
+ * emptied the completion queue from a previous interrupt
+ * FIXME: really!?
+ */
+ writel(SMU_ISR_COMPLETION, &ihost->smu_registers->interrupt_status);
+
+ /* There is a race in the hardware that could cause us not to be
+ * notified of an interrupt completion if we do not take this
+ * step. We will mask then unmask the interrupts so if there is
+ * another interrupt pending the clearing of the interrupt
+ * source we get the next interrupt message.
+ */
+ spin_lock(&ihost->scic_lock);
+ if (test_bit(IHOST_IRQ_ENABLED, &ihost->flags)) {
writel(0xFF000000, &ihost->smu_registers->interrupt_mask);
writel(0, &ihost->smu_registers->interrupt_mask);
}
+ spin_unlock(&ihost->scic_lock);
return false;
}
@@ -642,7 +647,6 @@ static void isci_host_start_complete(struct isci_host *ihost, enum sci_status co
if (completion_status != SCI_SUCCESS)
dev_info(&ihost->pdev->dev,
"controller start timed out, continuing...\n");
- isci_host_change_state(ihost, isci_ready);
clear_bit(IHOST_START_PENDING, &ihost->flags);
wake_up(&ihost->eventq);
}
@@ -657,12 +661,7 @@ int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time)
sas_drain_work(ha);
- dev_dbg(&ihost->pdev->dev,
- "%s: ihost->status = %d, time = %ld\n",
- __func__, isci_host_get_state(ihost), time);
-
return 1;
-
}
/**
@@ -704,14 +703,15 @@ static u32 sci_controller_get_suggested_start_timeout(struct isci_host *ihost)
static void sci_controller_enable_interrupts(struct isci_host *ihost)
{
- BUG_ON(ihost->smu_registers == NULL);
+ set_bit(IHOST_IRQ_ENABLED, &ihost->flags);
writel(0, &ihost->smu_registers->interrupt_mask);
}
void sci_controller_disable_interrupts(struct isci_host *ihost)
{
- BUG_ON(ihost->smu_registers == NULL);
+ clear_bit(IHOST_IRQ_ENABLED, &ihost->flags);
writel(0xffffffff, &ihost->smu_registers->interrupt_mask);
+ readl(&ihost->smu_registers->interrupt_mask); /* flush */
}
static void sci_controller_enable_port_task_scheduler(struct isci_host *ihost)
@@ -822,7 +822,7 @@ static void sci_controller_initialize_unsolicited_frame_queue(struct isci_host *
&ihost->scu_registers->sdma.unsolicited_frame_put_pointer);
}
-static void sci_controller_transition_to_ready(struct isci_host *ihost, enum sci_status status)
+void sci_controller_transition_to_ready(struct isci_host *ihost, enum sci_status status)
{
if (ihost->sm.current_state_id == SCIC_STARTING) {
/*
@@ -849,6 +849,7 @@ static bool is_phy_starting(struct isci_phy *iphy)
case SCI_PHY_SUB_AWAIT_SATA_POWER:
case SCI_PHY_SUB_AWAIT_SATA_PHY_EN:
case SCI_PHY_SUB_AWAIT_SATA_SPEED_EN:
+ case SCI_PHY_SUB_AWAIT_OSSP_EN:
case SCI_PHY_SUB_AWAIT_SIG_FIS_UF:
case SCI_PHY_SUB_FINAL:
return true;
@@ -857,6 +858,39 @@ static bool is_phy_starting(struct isci_phy *iphy)
}
}
+bool is_controller_start_complete(struct isci_host *ihost)
+{
+ int i;
+
+ for (i = 0; i < SCI_MAX_PHYS; i++) {
+ struct isci_phy *iphy = &ihost->phys[i];
+ u32 state = iphy->sm.current_state_id;
+
+ /* in apc mode we need to check every phy, in
+ * mpc mode we only need to check phys that have
+ * been configured into a port
+ */
+ if (is_port_config_apc(ihost))
+ /* pass */;
+ else if (!phy_get_non_dummy_port(iphy))
+ continue;
+
+ /* The controller start operation is complete iff:
+ * - all links have been given an opportunity to start
+ * - have no indication of a connected device
+ * - have an indication of a connected device and it has
+ * finished the link training process.
+ */
+ if ((iphy->is_in_link_training == false && state == SCI_PHY_INITIAL) ||
+ (iphy->is_in_link_training == false && state == SCI_PHY_STOPPED) ||
+ (iphy->is_in_link_training == true && is_phy_starting(iphy)) ||
+ (ihost->port_agent.phy_ready_mask != ihost->port_agent.phy_configured_mask))
+ return false;
+ }
+
+ return true;
+}
+
/**
* sci_controller_start_next_phy - start phy
* @scic: controller
@@ -877,36 +911,7 @@ static enum sci_status sci_controller_start_next_phy(struct isci_host *ihost)
return status;
if (ihost->next_phy_to_start >= SCI_MAX_PHYS) {
- bool is_controller_start_complete = true;
- u32 state;
- u8 index;
-
- for (index = 0; index < SCI_MAX_PHYS; index++) {
- iphy = &ihost->phys[index];
- state = iphy->sm.current_state_id;
-
- if (!phy_get_non_dummy_port(iphy))
- continue;
-
- /* The controller start operation is complete iff:
- * - all links have been given an opportunity to start
- * - have no indication of a connected device
- * - have an indication of a connected device and it has
- * finished the link training process.
- */
- if ((iphy->is_in_link_training == false && state == SCI_PHY_INITIAL) ||
- (iphy->is_in_link_training == false && state == SCI_PHY_STOPPED) ||
- (iphy->is_in_link_training == true && is_phy_starting(iphy)) ||
- (ihost->port_agent.phy_ready_mask != ihost->port_agent.phy_configured_mask)) {
- is_controller_start_complete = false;
- break;
- }
- }
-
- /*
- * The controller has successfully finished the start process.
- * Inform the SCI Core user and transition to the READY state. */
- if (is_controller_start_complete == true) {
+ if (is_controller_start_complete(ihost)) {
sci_controller_transition_to_ready(ihost, SCI_SUCCESS);
sci_del_timer(&ihost->phy_timer);
ihost->phy_startup_timer_pending = false;
@@ -987,9 +992,8 @@ static enum sci_status sci_controller_start(struct isci_host *ihost,
u16 index;
if (ihost->sm.current_state_id != SCIC_INITIALIZED) {
- dev_warn(&ihost->pdev->dev,
- "SCIC Controller start operation requested in "
- "invalid state\n");
+ dev_warn(&ihost->pdev->dev, "%s invalid state: %d\n",
+ __func__, ihost->sm.current_state_id);
return SCI_FAILURE_INVALID_STATE;
}
@@ -1053,9 +1057,8 @@ void isci_host_scan_start(struct Scsi_Host *shost)
spin_unlock_irq(&ihost->scic_lock);
}
-static void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion_status)
+static void isci_host_stop_complete(struct isci_host *ihost)
{
- isci_host_change_state(ihost, isci_stopped);
sci_controller_disable_interrupts(ihost);
clear_bit(IHOST_STOP_PENDING, &ihost->flags);
wake_up(&ihost->eventq);
@@ -1074,6 +1077,32 @@ static void sci_controller_completion_handler(struct isci_host *ihost)
writel(0, &ihost->smu_registers->interrupt_mask);
}
+void ireq_done(struct isci_host *ihost, struct isci_request *ireq, struct sas_task *task)
+{
+ task->lldd_task = NULL;
+ if (!test_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags) &&
+ !(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
+ if (test_bit(IREQ_COMPLETE_IN_TARGET, &ireq->flags)) {
+ /* Normal notification (task_done) */
+ dev_dbg(&ihost->pdev->dev,
+ "%s: Normal - ireq/task = %p/%p\n",
+ __func__, ireq, task);
+
+ task->task_done(task);
+ } else {
+ dev_dbg(&ihost->pdev->dev,
+ "%s: Error - ireq/task = %p/%p\n",
+ __func__, ireq, task);
+
+ sas_task_abort(task);
+ }
+ }
+ if (test_and_clear_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags))
+ wake_up_all(&ihost->eventq);
+
+ if (!test_bit(IREQ_NO_AUTO_FREE_TAG, &ireq->flags))
+ isci_free_tag(ihost, ireq->io_tag);
+}
/**
* isci_host_completion_routine() - This function is the delayed service
* routine that calls the sci core library's completion handler. It's
@@ -1082,107 +1111,15 @@ static void sci_controller_completion_handler(struct isci_host *ihost)
* @data: This parameter specifies the ISCI host object
*
*/
-static void isci_host_completion_routine(unsigned long data)
+void isci_host_completion_routine(unsigned long data)
{
struct isci_host *ihost = (struct isci_host *)data;
- struct list_head completed_request_list;
- struct list_head errored_request_list;
- struct list_head *current_position;
- struct list_head *next_position;
- struct isci_request *request;
- struct isci_request *next_request;
- struct sas_task *task;
u16 active;
- INIT_LIST_HEAD(&completed_request_list);
- INIT_LIST_HEAD(&errored_request_list);
-
spin_lock_irq(&ihost->scic_lock);
-
sci_controller_completion_handler(ihost);
-
- /* Take the lists of completed I/Os from the host. */
-
- list_splice_init(&ihost->requests_to_complete,
- &completed_request_list);
-
- /* Take the list of errored I/Os from the host. */
- list_splice_init(&ihost->requests_to_errorback,
- &errored_request_list);
-
spin_unlock_irq(&ihost->scic_lock);
- /* Process any completions in the lists. */
- list_for_each_safe(current_position, next_position,
- &completed_request_list) {
-
- request = list_entry(current_position, struct isci_request,
- completed_node);
- task = isci_request_access_task(request);
-
- /* Normal notification (task_done) */
- dev_dbg(&ihost->pdev->dev,
- "%s: Normal - request/task = %p/%p\n",
- __func__,
- request,
- task);
-
- /* Return the task to libsas */
- if (task != NULL) {
-
- task->lldd_task = NULL;
- if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
-
- /* If the task is already in the abort path,
- * the task_done callback cannot be called.
- */
- task->task_done(task);
- }
- }
-
- spin_lock_irq(&ihost->scic_lock);
- isci_free_tag(ihost, request->io_tag);
- spin_unlock_irq(&ihost->scic_lock);
- }
- list_for_each_entry_safe(request, next_request, &errored_request_list,
- completed_node) {
-
- task = isci_request_access_task(request);
-
- /* Use sas_task_abort */
- dev_warn(&ihost->pdev->dev,
- "%s: Error - request/task = %p/%p\n",
- __func__,
- request,
- task);
-
- if (task != NULL) {
-
- /* Put the task into the abort path if it's not there
- * already.
- */
- if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED))
- sas_task_abort(task);
-
- } else {
- /* This is a case where the request has completed with a
- * status such that it needed further target servicing,
- * but the sas_task reference has already been removed
- * from the request. Since it was errored, it was not
- * being aborted, so there is nothing to do except free
- * it.
- */
-
- spin_lock_irq(&ihost->scic_lock);
- /* Remove the request from the remote device's list
- * of pending requests.
- */
- list_del_init(&request->dev_node);
- isci_free_tag(ihost, request->io_tag);
- spin_unlock_irq(&ihost->scic_lock);
- }
- }
-
/* the coalesence timeout doubles at each encoding step, so
* update it based on the ilog2 value of the outstanding requests
*/
@@ -1213,9 +1150,8 @@ static void isci_host_completion_routine(unsigned long data)
static enum sci_status sci_controller_stop(struct isci_host *ihost, u32 timeout)
{
if (ihost->sm.current_state_id != SCIC_READY) {
- dev_warn(&ihost->pdev->dev,
- "SCIC Controller stop operation requested in "
- "invalid state\n");
+ dev_warn(&ihost->pdev->dev, "%s invalid state: %d\n",
+ __func__, ihost->sm.current_state_id);
return SCI_FAILURE_INVALID_STATE;
}
@@ -1241,7 +1177,7 @@ static enum sci_status sci_controller_reset(struct isci_host *ihost)
switch (ihost->sm.current_state_id) {
case SCIC_RESET:
case SCIC_READY:
- case SCIC_STOPPED:
+ case SCIC_STOPPING:
case SCIC_FAILED:
/*
* The reset operation is not a graceful cleanup, just
@@ -1250,13 +1186,50 @@ static enum sci_status sci_controller_reset(struct isci_host *ihost)
sci_change_state(&ihost->sm, SCIC_RESETTING);
return SCI_SUCCESS;
default:
- dev_warn(&ihost->pdev->dev,
- "SCIC Controller reset operation requested in "
- "invalid state\n");
+ dev_warn(&ihost->pdev->dev, "%s invalid state: %d\n",
+ __func__, ihost->sm.current_state_id);
return SCI_FAILURE_INVALID_STATE;
}
}
+static enum sci_status sci_controller_stop_phys(struct isci_host *ihost)
+{
+ u32 index;
+ enum sci_status status;
+ enum sci_status phy_status;
+
+ status = SCI_SUCCESS;
+
+ for (index = 0; index < SCI_MAX_PHYS; index++) {
+ phy_status = sci_phy_stop(&ihost->phys[index]);
+
+ if (phy_status != SCI_SUCCESS &&
+ phy_status != SCI_FAILURE_INVALID_STATE) {
+ status = SCI_FAILURE;
+
+ dev_warn(&ihost->pdev->dev,
+ "%s: Controller stop operation failed to stop "
+ "phy %d because of status %d.\n",
+ __func__,
+ ihost->phys[index].phy_index, phy_status);
+ }
+ }
+
+ return status;
+}
+
+
+/**
+ * isci_host_deinit - shutdown frame reception and dma
+ * @ihost: host to take down
+ *
+ * This is called in either the driver shutdown or the suspend path. In
+ * the shutdown case libsas went through port teardown and normal device
+ * removal (i.e. physical links stayed up to service scsi_device removal
+ * commands). In the suspend case we disable the hardware without
+ * notifying libsas of the link down events since we want libsas to
+ * remember the domain across the suspend/resume cycle
+ */
void isci_host_deinit(struct isci_host *ihost)
{
int i;
@@ -1265,17 +1238,6 @@ void isci_host_deinit(struct isci_host *ihost)
for (i = 0; i < isci_gpio_count(ihost); i++)
writel(SGPIO_HW_CONTROL, &ihost->scu_registers->peg0.sgpio.output_data_select[i]);
- isci_host_change_state(ihost, isci_stopping);
- for (i = 0; i < SCI_MAX_PORTS; i++) {
- struct isci_port *iport = &ihost->ports[i];
- struct isci_remote_device *idev, *d;
-
- list_for_each_entry_safe(idev, d, &iport->remote_dev_list, node) {
- if (test_bit(IDEV_ALLOCATED, &idev->flags))
- isci_remote_device_stop(ihost, idev);
- }
- }
-
set_bit(IHOST_STOP_PENDING, &ihost->flags);
spin_lock_irq(&ihost->scic_lock);
@@ -1284,12 +1246,21 @@ void isci_host_deinit(struct isci_host *ihost)
wait_for_stop(ihost);
+ /* phy stop is after controller stop to allow port and device to
+ * go idle before shutting down the phys, but the expectation is
+ * that i/o has been shut off well before we reach this
+ * function.
+ */
+ sci_controller_stop_phys(ihost);
+
/* disable sgpio: where the above wait should give time for the
* enclosure to sample the gpios going inactive
*/
writel(0, &ihost->scu_registers->peg0.sgpio.interface_control);
+ spin_lock_irq(&ihost->scic_lock);
sci_controller_reset(ihost);
+ spin_unlock_irq(&ihost->scic_lock);
/* Cancel any/all outstanding port timers */
for (i = 0; i < ihost->logical_port_entries; i++) {
@@ -1328,29 +1299,6 @@ static void __iomem *smu_base(struct isci_host *isci_host)
return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id;
}
-static void isci_user_parameters_get(struct sci_user_parameters *u)
-{
- int i;
-
- for (i = 0; i < SCI_MAX_PHYS; i++) {
- struct sci_phy_user_params *u_phy = &u->phys[i];
-
- u_phy->max_speed_generation = phy_gen;
-
- /* we are not exporting these for now */
- u_phy->align_insertion_frequency = 0x7f;
- u_phy->in_connection_align_insertion_frequency = 0xff;
- u_phy->notify_enable_spin_up_insertion_frequency = 0x33;
- }
-
- u->stp_inactivity_timeout = stp_inactive_to;
- u->ssp_inactivity_timeout = ssp_inactive_to;
- u->stp_max_occupancy_timeout = stp_max_occ_to;
- u->ssp_max_occupancy_timeout = ssp_max_occ_to;
- u->no_outbound_task_timeout = no_outbound_task_to;
- u->max_concurr_spinup = max_concurr_spinup;
-}
-
static void sci_controller_initial_state_enter(struct sci_base_state_machine *sm)
{
struct isci_host *ihost = container_of(sm, typeof(*ihost), sm);
@@ -1510,32 +1458,6 @@ static void sci_controller_ready_state_exit(struct sci_base_state_machine *sm)
sci_controller_set_interrupt_coalescence(ihost, 0, 0);
}
-static enum sci_status sci_controller_stop_phys(struct isci_host *ihost)
-{
- u32 index;
- enum sci_status status;
- enum sci_status phy_status;
-
- status = SCI_SUCCESS;
-
- for (index = 0; index < SCI_MAX_PHYS; index++) {
- phy_status = sci_phy_stop(&ihost->phys[index]);
-
- if (phy_status != SCI_SUCCESS &&
- phy_status != SCI_FAILURE_INVALID_STATE) {
- status = SCI_FAILURE;
-
- dev_warn(&ihost->pdev->dev,
- "%s: Controller stop operation failed to stop "
- "phy %d because of status %d.\n",
- __func__,
- ihost->phys[index].phy_index, phy_status);
- }
- }
-
- return status;
-}
-
static enum sci_status sci_controller_stop_ports(struct isci_host *ihost)
{
u32 index;
@@ -1595,10 +1517,11 @@ static void sci_controller_stopping_state_enter(struct sci_base_state_machine *s
{
struct isci_host *ihost = container_of(sm, typeof(*ihost), sm);
- /* Stop all of the components for this controller */
- sci_controller_stop_phys(ihost);
- sci_controller_stop_ports(ihost);
sci_controller_stop_devices(ihost);
+ sci_controller_stop_ports(ihost);
+
+ if (!sci_controller_has_remote_devices_stopping(ihost))
+ isci_host_stop_complete(ihost);
}
static void sci_controller_stopping_state_exit(struct sci_base_state_machine *sm)
@@ -1624,6 +1547,9 @@ static void sci_controller_reset_hardware(struct isci_host *ihost)
/* The write to the UFQGP clears the UFQPR */
writel(0, &ihost->scu_registers->sdma.unsolicited_frame_get_pointer);
+
+ /* clear all interrupts */
+ writel(~SMU_INTERRUPT_STATUS_RESERVED_MASK, &ihost->smu_registers->interrupt_status);
}
static void sci_controller_resetting_state_enter(struct sci_base_state_machine *sm)
@@ -1655,59 +1581,9 @@ static const struct sci_base_state sci_controller_state_table[] = {
.enter_state = sci_controller_stopping_state_enter,
.exit_state = sci_controller_stopping_state_exit,
},
- [SCIC_STOPPED] = {},
[SCIC_FAILED] = {}
};
-static void sci_controller_set_default_config_parameters(struct isci_host *ihost)
-{
- /* these defaults are overridden by the platform / firmware */
- u16 index;
-
- /* Default to APC mode. */
- ihost->oem_parameters.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
-
- /* Default to APC mode. */
- ihost->oem_parameters.controller.max_concurr_spin_up = 1;
-
- /* Default to no SSC operation. */
- ihost->oem_parameters.controller.do_enable_ssc = false;
-
- /* Default to short cables on all phys. */
- ihost->oem_parameters.controller.cable_selection_mask = 0;
-
- /* Initialize all of the port parameter information to narrow ports. */
- for (index = 0; index < SCI_MAX_PORTS; index++) {
- ihost->oem_parameters.ports[index].phy_mask = 0;
- }
-
- /* Initialize all of the phy parameter information. */
- for (index = 0; index < SCI_MAX_PHYS; index++) {
- /* Default to 3G (i.e. Gen 2). */
- ihost->user_parameters.phys[index].max_speed_generation =
- SCIC_SDS_PARM_GEN2_SPEED;
-
- /* the frequencies cannot be 0 */
- ihost->user_parameters.phys[index].align_insertion_frequency = 0x7f;
- ihost->user_parameters.phys[index].in_connection_align_insertion_frequency = 0xff;
- ihost->user_parameters.phys[index].notify_enable_spin_up_insertion_frequency = 0x33;
-
- /*
- * Previous Vitesse based expanders had a arbitration issue that
- * is worked around by having the upper 32-bits of SAS address
- * with a value greater then the Vitesse company identifier.
- * Hence, usage of 0x5FCFFFFF. */
- ihost->oem_parameters.phys[index].sas_address.low = 0x1 + ihost->id;
- ihost->oem_parameters.phys[index].sas_address.high = 0x5FCFFFFF;
- }
-
- ihost->user_parameters.stp_inactivity_timeout = 5;
- ihost->user_parameters.ssp_inactivity_timeout = 5;
- ihost->user_parameters.stp_max_occupancy_timeout = 5;
- ihost->user_parameters.ssp_max_occupancy_timeout = 20;
- ihost->user_parameters.no_outbound_task_timeout = 2;
-}
-
static void controller_timeout(unsigned long data)
{
struct sci_timer *tmr = (struct sci_timer *)data;
@@ -1724,7 +1600,7 @@ static void controller_timeout(unsigned long data)
sci_controller_transition_to_ready(ihost, SCI_FAILURE_TIMEOUT);
else if (sm->current_state_id == SCIC_STOPPING) {
sci_change_state(sm, SCIC_FAILED);
- isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT);
+ isci_host_stop_complete(ihost);
} else /* / @todo Now what do we want to do in this case? */
dev_err(&ihost->pdev->dev,
"%s: Controller timer fired when controller was not "
@@ -1764,9 +1640,6 @@ static enum sci_status sci_controller_construct(struct isci_host *ihost,
sci_init_timer(&ihost->timer, controller_timeout);
- /* Initialize the User and OEM parameters to default values. */
- sci_controller_set_default_config_parameters(ihost);
-
return sci_controller_reset(ihost);
}
@@ -1846,27 +1719,6 @@ int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version)
return 0;
}
-static enum sci_status sci_oem_parameters_set(struct isci_host *ihost)
-{
- u32 state = ihost->sm.current_state_id;
- struct isci_pci_info *pci_info = to_pci_info(ihost->pdev);
-
- if (state == SCIC_RESET ||
- state == SCIC_INITIALIZING ||
- state == SCIC_INITIALIZED) {
- u8 oem_version = pci_info->orom ? pci_info->orom->hdr.version :
- ISCI_ROM_VER_1_0;
-
- if (sci_oem_parameters_validate(&ihost->oem_parameters,
- oem_version))
- return SCI_FAILURE_INVALID_PARAMETER_VALUE;
-
- return SCI_SUCCESS;
- }
-
- return SCI_FAILURE_INVALID_STATE;
-}
-
static u8 max_spin_up(struct isci_host *ihost)
{
if (ihost->user_parameters.max_concurr_spinup)
@@ -1914,7 +1766,7 @@ static void power_control_timeout(unsigned long data)
ihost->power_control.phys_granted_power++;
sci_phy_consume_power_handler(iphy);
- if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) {
+ if (iphy->protocol == SAS_PROTOCOL_SSP) {
u8 j;
for (j = 0; j < SCI_MAX_PHYS; j++) {
@@ -1988,7 +1840,7 @@ void sci_controller_power_control_queue_insert(struct isci_host *ihost,
sizeof(current_phy->frame_rcvd.iaf.sas_addr));
if (current_phy->sm.current_state_id == SCI_PHY_READY &&
- current_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS &&
+ current_phy->protocol == SAS_PROTOCOL_SSP &&
other == 0) {
sci_phy_consume_power_handler(iphy);
break;
@@ -2279,9 +2131,8 @@ static enum sci_status sci_controller_initialize(struct isci_host *ihost)
unsigned long i, state, val;
if (ihost->sm.current_state_id != SCIC_RESET) {
- dev_warn(&ihost->pdev->dev,
- "SCIC Controller initialize operation requested "
- "in invalid state\n");
+ dev_warn(&ihost->pdev->dev, "%s invalid state: %d\n",
+ __func__, ihost->sm.current_state_id);
return SCI_FAILURE_INVALID_STATE;
}
@@ -2384,96 +2235,76 @@ static enum sci_status sci_controller_initialize(struct isci_host *ihost)
return result;
}
-static enum sci_status sci_user_parameters_set(struct isci_host *ihost,
- struct sci_user_parameters *sci_parms)
-{
- u32 state = ihost->sm.current_state_id;
-
- if (state == SCIC_RESET ||
- state == SCIC_INITIALIZING ||
- state == SCIC_INITIALIZED) {
- u16 index;
-
- /*
- * Validate the user parameters. If they are not legal, then
- * return a failure.
- */
- for (index = 0; index < SCI_MAX_PHYS; index++) {
- struct sci_phy_user_params *user_phy;
-
- user_phy = &sci_parms->phys[index];
-
- if (!((user_phy->max_speed_generation <=
- SCIC_SDS_PARM_MAX_SPEED) &&
- (user_phy->max_speed_generation >
- SCIC_SDS_PARM_NO_SPEED)))
- return SCI_FAILURE_INVALID_PARAMETER_VALUE;
-
- if (user_phy->in_connection_align_insertion_frequency <
- 3)
- return SCI_FAILURE_INVALID_PARAMETER_VALUE;
-
- if ((user_phy->in_connection_align_insertion_frequency <
- 3) ||
- (user_phy->align_insertion_frequency == 0) ||
- (user_phy->
- notify_enable_spin_up_insertion_frequency ==
- 0))
- return SCI_FAILURE_INVALID_PARAMETER_VALUE;
- }
-
- if ((sci_parms->stp_inactivity_timeout == 0) ||
- (sci_parms->ssp_inactivity_timeout == 0) ||
- (sci_parms->stp_max_occupancy_timeout == 0) ||
- (sci_parms->ssp_max_occupancy_timeout == 0) ||
- (sci_parms->no_outbound_task_timeout == 0))
- return SCI_FAILURE_INVALID_PARAMETER_VALUE;
-
- memcpy(&ihost->user_parameters, sci_parms, sizeof(*sci_parms));
-
- return SCI_SUCCESS;
- }
-
- return SCI_FAILURE_INVALID_STATE;
-}
-
-static int sci_controller_mem_init(struct isci_host *ihost)
+static int sci_controller_dma_alloc(struct isci_host *ihost)
{
struct device *dev = &ihost->pdev->dev;
- dma_addr_t dma;
size_t size;
- int err;
+ int i;
+
+ /* detect re-initialization */
+ if (ihost->completion_queue)
+ return 0;
size = SCU_MAX_COMPLETION_QUEUE_ENTRIES * sizeof(u32);
- ihost->completion_queue = dmam_alloc_coherent(dev, size, &dma, GFP_KERNEL);
+ ihost->completion_queue = dmam_alloc_coherent(dev, size, &ihost->cq_dma,
+ GFP_KERNEL);
if (!ihost->completion_queue)
return -ENOMEM;
- writel(lower_32_bits(dma), &ihost->smu_registers->completion_queue_lower);
- writel(upper_32_bits(dma), &ihost->smu_registers->completion_queue_upper);
-
size = ihost->remote_node_entries * sizeof(union scu_remote_node_context);
- ihost->remote_node_context_table = dmam_alloc_coherent(dev, size, &dma,
+ ihost->remote_node_context_table = dmam_alloc_coherent(dev, size, &ihost->rnc_dma,
GFP_KERNEL);
+
if (!ihost->remote_node_context_table)
return -ENOMEM;
- writel(lower_32_bits(dma), &ihost->smu_registers->remote_node_context_lower);
- writel(upper_32_bits(dma), &ihost->smu_registers->remote_node_context_upper);
-
size = ihost->task_context_entries * sizeof(struct scu_task_context),
- ihost->task_context_table = dmam_alloc_coherent(dev, size, &dma, GFP_KERNEL);
+ ihost->task_context_table = dmam_alloc_coherent(dev, size, &ihost->tc_dma,
+ GFP_KERNEL);
if (!ihost->task_context_table)
return -ENOMEM;
- ihost->task_context_dma = dma;
- writel(lower_32_bits(dma), &ihost->smu_registers->host_task_table_lower);
- writel(upper_32_bits(dma), &ihost->smu_registers->host_task_table_upper);
+ size = SCI_UFI_TOTAL_SIZE;
+ ihost->ufi_buf = dmam_alloc_coherent(dev, size, &ihost->ufi_dma, GFP_KERNEL);
+ if (!ihost->ufi_buf)
+ return -ENOMEM;
+
+ for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) {
+ struct isci_request *ireq;
+ dma_addr_t dma;
+
+ ireq = dmam_alloc_coherent(dev, sizeof(*ireq), &dma, GFP_KERNEL);
+ if (!ireq)
+ return -ENOMEM;
+
+ ireq->tc = &ihost->task_context_table[i];
+ ireq->owning_controller = ihost;
+ ireq->request_daddr = dma;
+ ireq->isci_host = ihost;
+ ihost->reqs[i] = ireq;
+ }
+
+ return 0;
+}
+
+static int sci_controller_mem_init(struct isci_host *ihost)
+{
+ int err = sci_controller_dma_alloc(ihost);
- err = sci_unsolicited_frame_control_construct(ihost);
if (err)
return err;
+ writel(lower_32_bits(ihost->cq_dma), &ihost->smu_registers->completion_queue_lower);
+ writel(upper_32_bits(ihost->cq_dma), &ihost->smu_registers->completion_queue_upper);
+
+ writel(lower_32_bits(ihost->rnc_dma), &ihost->smu_registers->remote_node_context_lower);
+ writel(upper_32_bits(ihost->rnc_dma), &ihost->smu_registers->remote_node_context_upper);
+
+ writel(lower_32_bits(ihost->tc_dma), &ihost->smu_registers->host_task_table_lower);
+ writel(upper_32_bits(ihost->tc_dma), &ihost->smu_registers->host_task_table_upper);
+
+ sci_unsolicited_frame_control_construct(ihost);
+
/*
* Inform the silicon as to the location of the UF headers and
* address table.
@@ -2491,22 +2322,22 @@ static int sci_controller_mem_init(struct isci_host *ihost)
return 0;
}
+/**
+ * isci_host_init - (re-)initialize hardware and internal (private) state
+ * @ihost: host to init
+ *
+ * Any public facing objects (like asd_sas_port, and asd_sas_phys), or
+ * one-time initialization objects like locks and waitqueues, are
+ * not touched (they are initialized in isci_host_alloc)
+ */
int isci_host_init(struct isci_host *ihost)
{
- int err = 0, i;
+ int i, err;
enum sci_status status;
- struct sci_user_parameters sci_user_params;
- struct isci_pci_info *pci_info = to_pci_info(ihost->pdev);
-
- spin_lock_init(&ihost->state_lock);
- spin_lock_init(&ihost->scic_lock);
- init_waitqueue_head(&ihost->eventq);
-
- isci_host_change_state(ihost, isci_starting);
-
- status = sci_controller_construct(ihost, scu_base(ihost),
- smu_base(ihost));
+ spin_lock_irq(&ihost->scic_lock);
+ status = sci_controller_construct(ihost, scu_base(ihost), smu_base(ihost));
+ spin_unlock_irq(&ihost->scic_lock);
if (status != SCI_SUCCESS) {
dev_err(&ihost->pdev->dev,
"%s: sci_controller_construct failed - status = %x\n",
@@ -2515,48 +2346,6 @@ int isci_host_init(struct isci_host *ihost)
return -ENODEV;
}
- ihost->sas_ha.dev = &ihost->pdev->dev;
- ihost->sas_ha.lldd_ha = ihost;
-
- /*
- * grab initial values stored in the controller object for OEM and USER
- * parameters
- */
- isci_user_parameters_get(&sci_user_params);
- status = sci_user_parameters_set(ihost, &sci_user_params);
- if (status != SCI_SUCCESS) {
- dev_warn(&ihost->pdev->dev,
- "%s: sci_user_parameters_set failed\n",
- __func__);
- return -ENODEV;
- }
-
- /* grab any OEM parameters specified in orom */
- if (pci_info->orom) {
- status = isci_parse_oem_parameters(&ihost->oem_parameters,
- pci_info->orom,
- ihost->id);
- if (status != SCI_SUCCESS) {
- dev_warn(&ihost->pdev->dev,
- "parsing firmware oem parameters failed\n");
- return -EINVAL;
- }
- }
-
- status = sci_oem_parameters_set(ihost);
- if (status != SCI_SUCCESS) {
- dev_warn(&ihost->pdev->dev,
- "%s: sci_oem_parameters_set failed\n",
- __func__);
- return -ENODEV;
- }
-
- tasklet_init(&ihost->completion_tasklet,
- isci_host_completion_routine, (unsigned long)ihost);
-
- INIT_LIST_HEAD(&ihost->requests_to_complete);
- INIT_LIST_HEAD(&ihost->requests_to_errorback);
-
spin_lock_irq(&ihost->scic_lock);
status = sci_controller_initialize(ihost);
spin_unlock_irq(&ihost->scic_lock);
@@ -2572,43 +2361,12 @@ int isci_host_init(struct isci_host *ihost)
if (err)
return err;
- for (i = 0; i < SCI_MAX_PORTS; i++)
- isci_port_init(&ihost->ports[i], ihost, i);
-
- for (i = 0; i < SCI_MAX_PHYS; i++)
- isci_phy_init(&ihost->phys[i], ihost, i);
-
/* enable sgpio */
writel(1, &ihost->scu_registers->peg0.sgpio.interface_control);
for (i = 0; i < isci_gpio_count(ihost); i++)
writel(SGPIO_HW_CONTROL, &ihost->scu_registers->peg0.sgpio.output_data_select[i]);
writel(0, &ihost->scu_registers->peg0.sgpio.vendor_specific_code);
- for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
- struct isci_remote_device *idev = &ihost->devices[i];
-
- INIT_LIST_HEAD(&idev->reqs_in_process);
- INIT_LIST_HEAD(&idev->node);
- }
-
- for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) {
- struct isci_request *ireq;
- dma_addr_t dma;
-
- ireq = dmam_alloc_coherent(&ihost->pdev->dev,
- sizeof(struct isci_request), &dma,
- GFP_KERNEL);
- if (!ireq)
- return -ENOMEM;
-
- ireq->tc = &ihost->task_context_table[i];
- ireq->owning_controller = ihost;
- spin_lock_init(&ireq->state_lock);
- ireq->request_daddr = dma;
- ireq->isci_host = ihost;
- ihost->reqs[i] = ireq;
- }
-
return 0;
}
@@ -2654,7 +2412,7 @@ void sci_controller_link_down(struct isci_host *ihost, struct isci_port *iport,
}
}
-static bool sci_controller_has_remote_devices_stopping(struct isci_host *ihost)
+bool sci_controller_has_remote_devices_stopping(struct isci_host *ihost)
{
u32 index;
@@ -2680,7 +2438,7 @@ void sci_controller_remote_device_stopped(struct isci_host *ihost,
}
if (!sci_controller_has_remote_devices_stopping(ihost))
- sci_change_state(&ihost->sm, SCIC_STOPPED);
+ isci_host_stop_complete(ihost);
}
void sci_controller_post_request(struct isci_host *ihost, u32 request)
@@ -2842,7 +2600,8 @@ enum sci_status sci_controller_start_io(struct isci_host *ihost,
enum sci_status status;
if (ihost->sm.current_state_id != SCIC_READY) {
- dev_warn(&ihost->pdev->dev, "invalid state to start I/O");
+ dev_warn(&ihost->pdev->dev, "%s invalid state: %d\n",
+ __func__, ihost->sm.current_state_id);
return SCI_FAILURE_INVALID_STATE;
}
@@ -2866,22 +2625,26 @@ enum sci_status sci_controller_terminate_request(struct isci_host *ihost,
enum sci_status status;
if (ihost->sm.current_state_id != SCIC_READY) {
- dev_warn(&ihost->pdev->dev,
- "invalid state to terminate request\n");
+ dev_warn(&ihost->pdev->dev, "%s invalid state: %d\n",
+ __func__, ihost->sm.current_state_id);
return SCI_FAILURE_INVALID_STATE;
}
-
status = sci_io_request_terminate(ireq);
- if (status != SCI_SUCCESS)
- return status;
- /*
- * Utilize the original post context command and or in the POST_TC_ABORT
- * request sub-type.
- */
- sci_controller_post_request(ihost,
- ireq->post_context | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT);
- return SCI_SUCCESS;
+ dev_dbg(&ihost->pdev->dev, "%s: status=%d; ireq=%p; flags=%lx\n",
+ __func__, status, ireq, ireq->flags);
+
+ if ((status == SCI_SUCCESS) &&
+ !test_bit(IREQ_PENDING_ABORT, &ireq->flags) &&
+ !test_and_set_bit(IREQ_TC_ABORT_POSTED, &ireq->flags)) {
+ /* Utilize the original post context command and or in the
+ * POST_TC_ABORT request sub-type.
+ */
+ sci_controller_post_request(
+ ihost, ireq->post_context |
+ SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT);
+ }
+ return status;
}
/**
@@ -2915,7 +2678,8 @@ enum sci_status sci_controller_complete_io(struct isci_host *ihost,
clear_bit(IREQ_ACTIVE, &ireq->flags);
return SCI_SUCCESS;
default:
- dev_warn(&ihost->pdev->dev, "invalid state to complete I/O");
+ dev_warn(&ihost->pdev->dev, "%s invalid state: %d\n",
+ __func__, ihost->sm.current_state_id);
return SCI_FAILURE_INVALID_STATE;
}
@@ -2926,7 +2690,8 @@ enum sci_status sci_controller_continue_io(struct isci_request *ireq)
struct isci_host *ihost = ireq->owning_controller;
if (ihost->sm.current_state_id != SCIC_READY) {
- dev_warn(&ihost->pdev->dev, "invalid state to continue I/O");
+ dev_warn(&ihost->pdev->dev, "%s invalid state: %d\n",
+ __func__, ihost->sm.current_state_id);
return SCI_FAILURE_INVALID_STATE;
}
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index adbad69d1069..9ab58e0540e7 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -55,6 +55,7 @@
#ifndef _SCI_HOST_H_
#define _SCI_HOST_H_
+#include <scsi/sas_ata.h>
#include "remote_device.h"
#include "phy.h"
#include "isci.h"
@@ -108,6 +109,8 @@ struct sci_port_configuration_agent;
typedef void (*port_config_fn)(struct isci_host *,
struct sci_port_configuration_agent *,
struct isci_port *, struct isci_phy *);
+bool is_port_config_apc(struct isci_host *ihost);
+bool is_controller_start_complete(struct isci_host *ihost);
struct sci_port_configuration_agent {
u16 phy_configured_mask;
@@ -157,13 +160,17 @@ struct isci_host {
struct sci_power_control power_control;
u8 io_request_sequence[SCI_MAX_IO_REQUESTS];
struct scu_task_context *task_context_table;
- dma_addr_t task_context_dma;
+ dma_addr_t tc_dma;
union scu_remote_node_context *remote_node_context_table;
+ dma_addr_t rnc_dma;
u32 *completion_queue;
+ dma_addr_t cq_dma;
u32 completion_queue_get;
u32 logical_port_entries;
u32 remote_node_entries;
u32 task_context_entries;
+ void *ufi_buf;
+ dma_addr_t ufi_dma;
struct sci_unsolicited_frame_control uf_control;
/* phy startup */
@@ -190,17 +197,13 @@ struct isci_host {
struct asd_sas_port sas_ports[SCI_MAX_PORTS];
struct sas_ha_struct sas_ha;
- spinlock_t state_lock;
struct pci_dev *pdev;
- enum isci_status status;
#define IHOST_START_PENDING 0
#define IHOST_STOP_PENDING 1
+ #define IHOST_IRQ_ENABLED 2
unsigned long flags;
wait_queue_head_t eventq;
- struct Scsi_Host *shost;
struct tasklet_struct completion_tasklet;
- struct list_head requests_to_complete;
- struct list_head requests_to_errorback;
spinlock_t scic_lock;
struct isci_request *reqs[SCI_MAX_IO_REQUESTS];
struct isci_remote_device devices[SCI_MAX_REMOTE_DEVICES];
@@ -274,13 +277,6 @@ enum sci_controller_states {
SCIC_STOPPING,
/**
- * This state indicates that the controller has successfully been stopped.
- * In this state no new IO operations are permitted.
- * This state is entered from the STOPPING state.
- */
- SCIC_STOPPED,
-
- /**
* This state indicates that the controller could not successfully be
* initialized. In this state no new IO operations are permitted.
* This state is entered from the INITIALIZING state.
@@ -309,32 +305,16 @@ static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
return pci_get_drvdata(pdev);
}
+static inline struct Scsi_Host *to_shost(struct isci_host *ihost)
+{
+ return ihost->sas_ha.core.shost;
+}
+
#define for_each_isci_host(id, ihost, pdev) \
for (id = 0, ihost = to_pci_info(pdev)->hosts[id]; \
id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \
ihost = to_pci_info(pdev)->hosts[++id])
-static inline enum isci_status isci_host_get_state(struct isci_host *isci_host)
-{
- return isci_host->status;
-}
-
-static inline void isci_host_change_state(struct isci_host *isci_host,
- enum isci_status status)
-{
- unsigned long flags;
-
- dev_dbg(&isci_host->pdev->dev,
- "%s: isci_host = %p, state = 0x%x",
- __func__,
- isci_host,
- status);
- spin_lock_irqsave(&isci_host->state_lock, flags);
- isci_host->status = status;
- spin_unlock_irqrestore(&isci_host->state_lock, flags);
-
-}
-
static inline void wait_for_start(struct isci_host *ihost)
{
wait_event(ihost->eventq, !test_bit(IHOST_START_PENDING, &ihost->flags));
@@ -360,6 +340,11 @@ static inline struct isci_host *dev_to_ihost(struct domain_device *dev)
return dev->port->ha->lldd_ha;
}
+static inline struct isci_host *idev_to_ihost(struct isci_remote_device *idev)
+{
+ return dev_to_ihost(idev->domain_dev);
+}
+
/* we always use protocol engine group zero */
#define ISCI_PEG 0
@@ -378,8 +363,7 @@ static inline int sci_remote_device_node_count(struct isci_remote_device *idev)
{
struct domain_device *dev = idev->domain_dev;
- if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) &&
- !idev->is_direct_attached)
+ if (dev_is_sata(dev) && dev->parent)
return SCU_STP_REMOTE_NODE_COUNT;
return SCU_SSP_REMOTE_NODE_COUNT;
}
@@ -475,36 +459,17 @@ void sci_controller_free_remote_node_context(
struct isci_remote_device *idev,
u16 node_id);
-struct isci_request *sci_request_by_tag(struct isci_host *ihost,
- u16 io_tag);
-
-void sci_controller_power_control_queue_insert(
- struct isci_host *ihost,
- struct isci_phy *iphy);
-
-void sci_controller_power_control_queue_remove(
- struct isci_host *ihost,
- struct isci_phy *iphy);
-
-void sci_controller_link_up(
- struct isci_host *ihost,
- struct isci_port *iport,
- struct isci_phy *iphy);
-
-void sci_controller_link_down(
- struct isci_host *ihost,
- struct isci_port *iport,
- struct isci_phy *iphy);
-
-void sci_controller_remote_device_stopped(
- struct isci_host *ihost,
- struct isci_remote_device *idev);
-
-void sci_controller_copy_task_context(
- struct isci_host *ihost,
- struct isci_request *ireq);
-
-void sci_controller_register_setup(struct isci_host *ihost);
+struct isci_request *sci_request_by_tag(struct isci_host *ihost, u16 io_tag);
+void sci_controller_power_control_queue_insert(struct isci_host *ihost,
+ struct isci_phy *iphy);
+void sci_controller_power_control_queue_remove(struct isci_host *ihost,
+ struct isci_phy *iphy);
+void sci_controller_link_up(struct isci_host *ihost, struct isci_port *iport,
+ struct isci_phy *iphy);
+void sci_controller_link_down(struct isci_host *ihost, struct isci_port *iport,
+ struct isci_phy *iphy);
+void sci_controller_remote_device_stopped(struct isci_host *ihost,
+ struct isci_remote_device *idev);
enum sci_status sci_controller_continue_io(struct isci_request *ireq);
int isci_host_scan_finished(struct Scsi_Host *, unsigned long);
@@ -512,29 +477,14 @@ void isci_host_scan_start(struct Scsi_Host *);
u16 isci_alloc_tag(struct isci_host *ihost);
enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag);
void isci_tci_free(struct isci_host *ihost, u16 tci);
+void ireq_done(struct isci_host *ihost, struct isci_request *ireq, struct sas_task *task);
int isci_host_init(struct isci_host *);
-
-void isci_host_init_controller_names(
- struct isci_host *isci_host,
- unsigned int controller_idx);
-
-void isci_host_deinit(
- struct isci_host *);
-
-void isci_host_port_link_up(
- struct isci_host *,
- struct isci_port *,
- struct isci_phy *);
-int isci_host_dev_found(struct domain_device *);
-
-void isci_host_remote_device_start_complete(
- struct isci_host *,
- struct isci_remote_device *,
- enum sci_status);
-
-void sci_controller_disable_interrupts(
- struct isci_host *ihost);
+void isci_host_completion_routine(unsigned long data);
+void isci_host_deinit(struct isci_host *);
+void sci_controller_disable_interrupts(struct isci_host *ihost);
+bool sci_controller_has_remote_devices_stopping(struct isci_host *ihost);
+void sci_controller_transition_to_ready(struct isci_host *ihost, enum sci_status status);
enum sci_status sci_controller_start_io(
struct isci_host *ihost,
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 5137db5a5d85..47e28b555029 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -271,13 +271,12 @@ static void isci_unregister(struct isci_host *isci_host)
if (!isci_host)
return;
- shost = isci_host->shost;
-
sas_unregister_ha(&isci_host->sas_ha);
- sas_remove_host(isci_host->shost);
- scsi_remove_host(isci_host->shost);
- scsi_host_put(isci_host->shost);
+ shost = to_shost(isci_host);
+ sas_remove_host(shost);
+ scsi_remove_host(shost);
+ scsi_host_put(shost);
}
static int __devinit isci_pci_init(struct pci_dev *pdev)
@@ -397,38 +396,199 @@ static int isci_setup_interrupts(struct pci_dev *pdev)
return err;
}
+static void isci_user_parameters_get(struct sci_user_parameters *u)
+{
+ int i;
+
+ for (i = 0; i < SCI_MAX_PHYS; i++) {
+ struct sci_phy_user_params *u_phy = &u->phys[i];
+
+ u_phy->max_speed_generation = phy_gen;
+
+ /* we are not exporting these for now */
+ u_phy->align_insertion_frequency = 0x7f;
+ u_phy->in_connection_align_insertion_frequency = 0xff;
+ u_phy->notify_enable_spin_up_insertion_frequency = 0x33;
+ }
+
+ u->stp_inactivity_timeout = stp_inactive_to;
+ u->ssp_inactivity_timeout = ssp_inactive_to;
+ u->stp_max_occupancy_timeout = stp_max_occ_to;
+ u->ssp_max_occupancy_timeout = ssp_max_occ_to;
+ u->no_outbound_task_timeout = no_outbound_task_to;
+ u->max_concurr_spinup = max_concurr_spinup;
+}
+
+static enum sci_status sci_user_parameters_set(struct isci_host *ihost,
+ struct sci_user_parameters *sci_parms)
+{
+ u16 index;
+
+ /*
+ * Validate the user parameters. If they are not legal, then
+ * return a failure.
+ */
+ for (index = 0; index < SCI_MAX_PHYS; index++) {
+ struct sci_phy_user_params *u;
+
+ u = &sci_parms->phys[index];
+
+ if (!((u->max_speed_generation <= SCIC_SDS_PARM_MAX_SPEED) &&
+ (u->max_speed_generation > SCIC_SDS_PARM_NO_SPEED)))
+ return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+ if (u->in_connection_align_insertion_frequency < 3)
+ return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+ if ((u->in_connection_align_insertion_frequency < 3) ||
+ (u->align_insertion_frequency == 0) ||
+ (u->notify_enable_spin_up_insertion_frequency == 0))
+ return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+ }
+
+ if ((sci_parms->stp_inactivity_timeout == 0) ||
+ (sci_parms->ssp_inactivity_timeout == 0) ||
+ (sci_parms->stp_max_occupancy_timeout == 0) ||
+ (sci_parms->ssp_max_occupancy_timeout == 0) ||
+ (sci_parms->no_outbound_task_timeout == 0))
+ return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+ memcpy(&ihost->user_parameters, sci_parms, sizeof(*sci_parms));
+
+ return SCI_SUCCESS;
+}
+
+static void sci_oem_defaults(struct isci_host *ihost)
+{
+ /* these defaults are overridden by the platform / firmware */
+ struct sci_user_parameters *user = &ihost->user_parameters;
+ struct sci_oem_params *oem = &ihost->oem_parameters;
+ int i;
+
+ /* Default to APC mode. */
+ oem->controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
+
+ /* Default to APC mode. */
+ oem->controller.max_concurr_spin_up = 1;
+
+ /* Default to no SSC operation. */
+ oem->controller.do_enable_ssc = false;
+
+ /* Default to short cables on all phys. */
+ oem->controller.cable_selection_mask = 0;
+
+ /* Initialize all of the port parameter information to narrow ports. */
+ for (i = 0; i < SCI_MAX_PORTS; i++)
+ oem->ports[i].phy_mask = 0;
+
+ /* Initialize all of the phy parameter information. */
+ for (i = 0; i < SCI_MAX_PHYS; i++) {
+ /* Default to 3G (i.e. Gen 2). */
+ user->phys[i].max_speed_generation = SCIC_SDS_PARM_GEN2_SPEED;
+
+ /* the frequencies cannot be 0 */
+ user->phys[i].align_insertion_frequency = 0x7f;
+ user->phys[i].in_connection_align_insertion_frequency = 0xff;
+ user->phys[i].notify_enable_spin_up_insertion_frequency = 0x33;
+
+ /* Previous Vitesse based expanders had a arbitration issue that
+ * is worked around by having the upper 32-bits of SAS address
+ * with a value greater then the Vitesse company identifier.
+ * Hence, usage of 0x5FCFFFFF.
+ */
+ oem->phys[i].sas_address.low = 0x1 + ihost->id;
+ oem->phys[i].sas_address.high = 0x5FCFFFFF;
+ }
+
+ user->stp_inactivity_timeout = 5;
+ user->ssp_inactivity_timeout = 5;
+ user->stp_max_occupancy_timeout = 5;
+ user->ssp_max_occupancy_timeout = 20;
+ user->no_outbound_task_timeout = 2;
+}
+
static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
{
- struct isci_host *isci_host;
+ struct isci_orom *orom = to_pci_info(pdev)->orom;
+ struct sci_user_parameters sci_user_params;
+ u8 oem_version = ISCI_ROM_VER_1_0;
+ struct isci_host *ihost;
struct Scsi_Host *shost;
- int err;
+ int err, i;
- isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL);
- if (!isci_host)
+ ihost = devm_kzalloc(&pdev->dev, sizeof(*ihost), GFP_KERNEL);
+ if (!ihost)
return NULL;
- isci_host->pdev = pdev;
- isci_host->id = id;
+ ihost->pdev = pdev;
+ ihost->id = id;
+ spin_lock_init(&ihost->scic_lock);
+ init_waitqueue_head(&ihost->eventq);
+ ihost->sas_ha.dev = &ihost->pdev->dev;
+ ihost->sas_ha.lldd_ha = ihost;
+ tasklet_init(&ihost->completion_tasklet,
+ isci_host_completion_routine, (unsigned long)ihost);
+
+ /* validate module parameters */
+ /* TODO: kill struct sci_user_parameters and reference directly */
+ sci_oem_defaults(ihost);
+ isci_user_parameters_get(&sci_user_params);
+ if (sci_user_parameters_set(ihost, &sci_user_params)) {
+ dev_warn(&pdev->dev,
+ "%s: sci_user_parameters_set failed\n", __func__);
+ return NULL;
+ }
+
+ /* sanity check platform (or 'firmware') oem parameters */
+ if (orom) {
+ if (id < 0 || id >= SCI_MAX_CONTROLLERS || id > orom->hdr.num_elements) {
+ dev_warn(&pdev->dev, "parsing firmware oem parameters failed\n");
+ return NULL;
+ }
+ ihost->oem_parameters = orom->ctrl[id];
+ oem_version = orom->hdr.version;
+ }
+
+ /* validate oem parameters (platform, firmware, or built-in defaults) */
+ if (sci_oem_parameters_validate(&ihost->oem_parameters, oem_version)) {
+ dev_warn(&pdev->dev, "oem parameter validation failed\n");
+ return NULL;
+ }
+
+ for (i = 0; i < SCI_MAX_PORTS; i++) {
+ struct isci_port *iport = &ihost->ports[i];
+
+ INIT_LIST_HEAD(&iport->remote_dev_list);
+ iport->isci_host = ihost;
+ }
+
+ for (i = 0; i < SCI_MAX_PHYS; i++)
+ isci_phy_init(&ihost->phys[i], ihost, i);
+
+ for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
+ struct isci_remote_device *idev = &ihost->devices[i];
+
+ INIT_LIST_HEAD(&idev->node);
+ }
shost = scsi_host_alloc(&isci_sht, sizeof(void *));
if (!shost)
return NULL;
- isci_host->shost = shost;
dev_info(&pdev->dev, "%sSCU controller %d: phy 3-0 cables: "
"{%s, %s, %s, %s}\n",
- (is_cable_select_overridden() ? "* " : ""), isci_host->id,
- lookup_cable_names(decode_cable_selection(isci_host, 3)),
- lookup_cable_names(decode_cable_selection(isci_host, 2)),
- lookup_cable_names(decode_cable_selection(isci_host, 1)),
- lookup_cable_names(decode_cable_selection(isci_host, 0)));
+ (is_cable_select_overridden() ? "* " : ""), ihost->id,
+ lookup_cable_names(decode_cable_selection(ihost, 3)),
+ lookup_cable_names(decode_cable_selection(ihost, 2)),
+ lookup_cable_names(decode_cable_selection(ihost, 1)),
+ lookup_cable_names(decode_cable_selection(ihost, 0)));
- err = isci_host_init(isci_host);
+ err = isci_host_init(ihost);
if (err)
goto err_shost;
- SHOST_TO_SAS_HA(shost) = &isci_host->sas_ha;
- isci_host->sas_ha.core.shost = shost;
+ SHOST_TO_SAS_HA(shost) = &ihost->sas_ha;
+ ihost->sas_ha.core.shost = shost;
shost->transportt = isci_transport_template;
shost->max_id = ~0;
@@ -439,11 +599,11 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
if (err)
goto err_shost;
- err = isci_register_sas_ha(isci_host);
+ err = isci_register_sas_ha(ihost);
if (err)
goto err_shost_remove;
- return isci_host;
+ return ihost;
err_shost_remove:
scsi_remove_host(shost);
@@ -476,7 +636,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
if (!orom)
orom = isci_request_oprom(pdev);
- for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) {
+ for (i = 0; orom && i < num_controllers(pdev); i++) {
if (sci_oem_parameters_validate(&orom->ctrl[i],
orom->hdr.version)) {
dev_warn(&pdev->dev,
@@ -525,11 +685,11 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
pci_info->hosts[i] = h;
/* turn on DIF support */
- scsi_host_set_prot(h->shost,
+ scsi_host_set_prot(to_shost(h),
SHOST_DIF_TYPE1_PROTECTION |
SHOST_DIF_TYPE2_PROTECTION |
SHOST_DIF_TYPE3_PROTECTION);
- scsi_host_set_guard(h->shost, SHOST_DIX_GUARD_CRC);
+ scsi_host_set_guard(to_shost(h), SHOST_DIX_GUARD_CRC);
}
err = isci_setup_interrupts(pdev);
@@ -537,7 +697,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
goto err_host_alloc;
for_each_isci_host(i, isci_host, pdev)
- scsi_scan_host(isci_host->shost);
+ scsi_scan_host(to_shost(isci_host));
return 0;
diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c
index fab3586840b5..18f43d4c30ba 100644
--- a/drivers/scsi/isci/phy.c
+++ b/drivers/scsi/isci/phy.c
@@ -580,7 +580,7 @@ static void sci_phy_start_sas_link_training(struct isci_phy *iphy)
sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SAS_SPEED_EN);
- iphy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS;
+ iphy->protocol = SAS_PROTOCOL_SSP;
}
static void sci_phy_start_sata_link_training(struct isci_phy *iphy)
@@ -591,7 +591,7 @@ static void sci_phy_start_sata_link_training(struct isci_phy *iphy)
*/
sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SATA_POWER);
- iphy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
+ iphy->protocol = SAS_PROTOCOL_SATA;
}
/**
@@ -668,6 +668,19 @@ static const char *phy_event_name(u32 event_code)
phy_to_host(iphy)->id, iphy->phy_index, \
phy_state_name(state), phy_event_name(code), code)
+
+void scu_link_layer_set_txcomsas_timeout(struct isci_phy *iphy, u32 timeout)
+{
+ u32 val;
+
+ /* Extend timeout */
+ val = readl(&iphy->link_layer_registers->transmit_comsas_signal);
+ val &= ~SCU_SAS_LLTXCOMSAS_GEN_VAL(NEGTIME, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_MASK);
+ val |= SCU_SAS_LLTXCOMSAS_GEN_VAL(NEGTIME, timeout);
+
+ writel(val, &iphy->link_layer_registers->transmit_comsas_signal);
+}
+
enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
{
enum sci_phy_states state = iphy->sm.current_state_id;
@@ -683,6 +696,13 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
sci_phy_start_sata_link_training(iphy);
iphy->is_in_link_training = true;
break;
+ case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:
+ /* Extend timeout value */
+ scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_EXTENDED);
+
+ /* Start the oob/sn state machine over again */
+ sci_change_state(&iphy->sm, SCI_PHY_STARTING);
+ break;
default:
phy_event_dbg(iphy, state, event_code);
return SCI_FAILURE;
@@ -717,9 +737,19 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
sci_phy_start_sata_link_training(iphy);
break;
case SCU_EVENT_LINK_FAILURE:
+ /* Change the timeout value to default */
+ scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
+
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
+ case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:
+ /* Extend the timeout value */
+ scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_EXTENDED);
+
+ /* Start the oob/sn state machine over again */
+ sci_change_state(&iphy->sm, SCI_PHY_STARTING);
+ break;
default:
phy_event_warn(iphy, state, event_code);
return SCI_FAILURE;
@@ -740,7 +770,14 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
sci_phy_start_sata_link_training(iphy);
break;
case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:
+ /* Extend the timeout value */
+ scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_EXTENDED);
+
+ /* Start the oob/sn state machine over again */
+ sci_change_state(&iphy->sm, SCI_PHY_STARTING);
+ break;
case SCU_EVENT_LINK_FAILURE:
+ scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
case SCU_EVENT_HARD_RESET_RECEIVED:
/* Start the oob/sn state machine over again */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
@@ -753,6 +790,9 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
case SCI_PHY_SUB_AWAIT_SAS_POWER:
switch (scu_get_event_code(event_code)) {
case SCU_EVENT_LINK_FAILURE:
+ /* Change the timeout value to default */
+ scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
+
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
@@ -764,6 +804,9 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
case SCI_PHY_SUB_AWAIT_SATA_POWER:
switch (scu_get_event_code(event_code)) {
case SCU_EVENT_LINK_FAILURE:
+ /* Change the timeout value to default */
+ scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
+
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
@@ -788,6 +831,9 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
case SCI_PHY_SUB_AWAIT_SATA_PHY_EN:
switch (scu_get_event_code(event_code)) {
case SCU_EVENT_LINK_FAILURE:
+ /* Change the timeout value to default */
+ scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
+
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
@@ -797,7 +843,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
*/
break;
case SCU_EVENT_SATA_PHY_DETECTED:
- iphy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
+ iphy->protocol = SAS_PROTOCOL_SATA;
/* We have received the SATA PHY notification change state */
sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SATA_SPEED_EN);
@@ -836,6 +882,9 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
SCI_PHY_SUB_AWAIT_SIG_FIS_UF);
break;
case SCU_EVENT_LINK_FAILURE:
+ /* Change the timeout value to default */
+ scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
+
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
@@ -859,6 +908,9 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
break;
case SCU_EVENT_LINK_FAILURE:
+ /* Change the timeout value to default */
+ scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
+
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
@@ -871,16 +923,26 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
case SCI_PHY_READY:
switch (scu_get_event_code(event_code)) {
case SCU_EVENT_LINK_FAILURE:
+ /* Set default timeout */
+ scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
+
/* Link failure change state back to the starting state */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
break;
case SCU_EVENT_BROADCAST_CHANGE:
+ case SCU_EVENT_BROADCAST_SES:
+ case SCU_EVENT_BROADCAST_RESERVED0:
+ case SCU_EVENT_BROADCAST_RESERVED1:
+ case SCU_EVENT_BROADCAST_EXPANDER:
+ case SCU_EVENT_BROADCAST_AEN:
/* Broadcast change received. Notify the port. */
if (phy_get_non_dummy_port(iphy) != NULL)
sci_port_broadcast_change_received(iphy->owning_port, iphy);
else
iphy->bcn_received_while_port_unassigned = true;
break;
+ case SCU_EVENT_BROADCAST_RESERVED3:
+ case SCU_EVENT_BROADCAST_RESERVED4:
default:
phy_event_warn(iphy, state, event_code);
return SCI_FAILURE_INVALID_STATE;
@@ -1215,7 +1277,7 @@ static void sci_phy_starting_state_enter(struct sci_base_state_machine *sm)
scu_link_layer_start_oob(iphy);
/* We don't know what kind of phy we are going to be just yet */
- iphy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
+ iphy->protocol = SAS_PROTOCOL_NONE;
iphy->bcn_received_while_port_unassigned = false;
if (iphy->sm.previous_state_id == SCI_PHY_READY)
@@ -1250,7 +1312,7 @@ static void sci_phy_resetting_state_enter(struct sci_base_state_machine *sm)
*/
sci_port_deactivate_phy(iphy->owning_port, iphy, false);
- if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) {
+ if (iphy->protocol == SAS_PROTOCOL_SSP) {
scu_link_layer_tx_hard_reset(iphy);
} else {
/* The SCU does not need to have a discrete reset state so
@@ -1316,7 +1378,7 @@ void sci_phy_construct(struct isci_phy *iphy,
iphy->owning_port = iport;
iphy->phy_index = phy_index;
iphy->bcn_received_while_port_unassigned = false;
- iphy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
+ iphy->protocol = SAS_PROTOCOL_NONE;
iphy->link_layer_registers = NULL;
iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;
@@ -1380,12 +1442,14 @@ int isci_phy_control(struct asd_sas_phy *sas_phy,
switch (func) {
case PHY_FUNC_DISABLE:
spin_lock_irqsave(&ihost->scic_lock, flags);
+ scu_link_layer_start_oob(iphy);
sci_phy_stop(iphy);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
break;
case PHY_FUNC_LINK_RESET:
spin_lock_irqsave(&ihost->scic_lock, flags);
+ scu_link_layer_start_oob(iphy);
sci_phy_stop(iphy);
sci_phy_start(iphy);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h
index 0e45833ba06d..45fecfa36a98 100644
--- a/drivers/scsi/isci/phy.h
+++ b/drivers/scsi/isci/phy.h
@@ -76,13 +76,6 @@
*/
#define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 250
-enum sci_phy_protocol {
- SCIC_SDS_PHY_PROTOCOL_UNKNOWN,
- SCIC_SDS_PHY_PROTOCOL_SAS,
- SCIC_SDS_PHY_PROTOCOL_SATA,
- SCIC_SDS_MAX_PHY_PROTOCOLS
-};
-
/**
* isci_phy - hba local phy infrastructure
* @sm:
@@ -95,7 +88,7 @@ struct isci_phy {
struct sci_base_state_machine sm;
struct isci_port *owning_port;
enum sas_linkrate max_negotiated_speed;
- enum sci_phy_protocol protocol;
+ enum sas_protocol protocol;
u8 phy_index;
bool bcn_received_while_port_unassigned;
bool is_in_link_training;
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 5fada73b71ff..2fb85bf75449 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -184,7 +184,7 @@ static void isci_port_link_up(struct isci_host *isci_host,
sci_port_get_properties(iport, &properties);
- if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) {
+ if (iphy->protocol == SAS_PROTOCOL_SATA) {
u64 attached_sas_address;
iphy->sas_phy.oob_mode = SATA_OOB_MODE;
@@ -204,7 +204,7 @@ static void isci_port_link_up(struct isci_host *isci_host,
memcpy(&iphy->sas_phy.attached_sas_addr,
&attached_sas_address, sizeof(attached_sas_address));
- } else if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) {
+ } else if (iphy->protocol == SAS_PROTOCOL_SSP) {
iphy->sas_phy.oob_mode = SAS_OOB_MODE;
iphy->sas_phy.frame_rcvd_size = sizeof(struct sas_identify_frame);
@@ -251,10 +251,10 @@ static void isci_port_link_down(struct isci_host *isci_host,
if (isci_phy->sas_phy.port &&
isci_phy->sas_phy.port->num_phys == 1) {
/* change the state for all devices on this port. The
- * next task sent to this device will be returned as
- * SAS_TASK_UNDELIVERED, and the scsi mid layer will
- * remove the target
- */
+ * next task sent to this device will be returned as
+ * SAS_TASK_UNDELIVERED, and the scsi mid layer will
+ * remove the target
+ */
list_for_each_entry(isci_device,
&isci_port->remote_dev_list,
node) {
@@ -517,7 +517,7 @@ void sci_port_get_attached_sas_address(struct isci_port *iport, struct sci_sas_a
*/
iphy = sci_port_get_a_connected_phy(iport);
if (iphy) {
- if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) {
+ if (iphy->protocol != SAS_PROTOCOL_SATA) {
sci_phy_get_attached_sas_address(iphy, sas);
} else {
sci_phy_get_sas_address(iphy, sas);
@@ -624,7 +624,7 @@ static void sci_port_activate_phy(struct isci_port *iport,
{
struct isci_host *ihost = iport->owning_controller;
- if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA && (flags & PF_RESUME))
+ if (iphy->protocol != SAS_PROTOCOL_SATA && (flags & PF_RESUME))
sci_phy_resume(iphy);
iport->active_phy_mask |= 1 << iphy->phy_index;
@@ -751,12 +751,10 @@ static bool sci_port_is_wide(struct isci_port *iport)
* wide ports and direct attached phys. Since there are no wide ported SATA
* devices this could become an invalid port configuration.
*/
-bool sci_port_link_detected(
- struct isci_port *iport,
- struct isci_phy *iphy)
+bool sci_port_link_detected(struct isci_port *iport, struct isci_phy *iphy)
{
if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) &&
- (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)) {
+ (iphy->protocol == SAS_PROTOCOL_SATA)) {
if (sci_port_is_wide(iport)) {
sci_port_invalid_link_up(iport, iphy);
return false;
@@ -1201,6 +1199,8 @@ enum sci_status sci_port_add_phy(struct isci_port *iport,
enum sci_status status;
enum sci_port_states state;
+ sci_port_bcn_enable(iport);
+
state = iport->sm.current_state_id;
switch (state) {
case SCI_PORT_STOPPED: {
@@ -1548,6 +1548,29 @@ static void sci_port_failed_state_enter(struct sci_base_state_machine *sm)
isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT);
}
+void sci_port_set_hang_detection_timeout(struct isci_port *iport, u32 timeout)
+{
+ int phy_index;
+ u32 phy_mask = iport->active_phy_mask;
+
+ if (timeout)
+ ++iport->hang_detect_users;
+ else if (iport->hang_detect_users > 1)
+ --iport->hang_detect_users;
+ else
+ iport->hang_detect_users = 0;
+
+ if (timeout || (iport->hang_detect_users == 0)) {
+ for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) {
+ if ((phy_mask >> phy_index) & 1) {
+ writel(timeout,
+ &iport->phy_table[phy_index]
+ ->link_layer_registers
+ ->link_layer_hang_detection_timeout);
+ }
+ }
+ }
+}
/* --------------------------------------------------------------------------- */
static const struct sci_base_state sci_port_state_table[] = {
@@ -1596,6 +1619,7 @@ void sci_port_construct(struct isci_port *iport, u8 index,
iport->started_request_count = 0;
iport->assigned_device_count = 0;
+ iport->hang_detect_users = 0;
iport->reserved_rni = SCU_DUMMY_INDEX;
iport->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG;
@@ -1608,13 +1632,6 @@ void sci_port_construct(struct isci_port *iport, u8 index,
iport->phy_table[index] = NULL;
}
-void isci_port_init(struct isci_port *iport, struct isci_host *ihost, int index)
-{
- INIT_LIST_HEAD(&iport->remote_dev_list);
- INIT_LIST_HEAD(&iport->domain_dev_list);
- iport->isci_host = ihost;
-}
-
void sci_port_broadcast_change_received(struct isci_port *iport, struct isci_phy *iphy)
{
struct isci_host *ihost = iport->owning_controller;
@@ -1671,17 +1688,6 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
__func__, iport, status);
}
-
- /* If the hard reset for the port has failed, consider this
- * the same as link failures on all phys in the port.
- */
- if (ret != TMF_RESP_FUNC_COMPLETE) {
-
- dev_err(&ihost->pdev->dev,
- "%s: iport = %p; hard reset failed "
- "(0x%x) - driving explicit link fail for all phys\n",
- __func__, iport, iport->hard_reset_status);
- }
return ret;
}
@@ -1740,7 +1746,7 @@ void isci_port_formed(struct asd_sas_phy *phy)
struct isci_host *ihost = phy->ha->lldd_ha;
struct isci_phy *iphy = to_iphy(phy);
struct asd_sas_port *port = phy->port;
- struct isci_port *iport;
+ struct isci_port *iport = NULL;
unsigned long flags;
int i;
diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h
index 6b56240c2051..861e8f72811b 100644
--- a/drivers/scsi/isci/port.h
+++ b/drivers/scsi/isci/port.h
@@ -97,7 +97,6 @@ enum isci_status {
struct isci_port {
struct isci_host *isci_host;
struct list_head remote_dev_list;
- struct list_head domain_dev_list;
#define IPORT_RESET_PENDING 0
unsigned long state;
enum sci_status hard_reset_status;
@@ -112,6 +111,7 @@ struct isci_port {
u16 reserved_tag;
u32 started_request_count;
u32 assigned_device_count;
+ u32 hang_detect_users;
u32 not_ready_reason;
struct isci_phy *phy_table[SCI_MAX_PHYS];
struct isci_host *owning_controller;
@@ -270,14 +270,13 @@ void sci_port_get_attached_sas_address(
struct isci_port *iport,
struct sci_sas_address *sas_address);
+void sci_port_set_hang_detection_timeout(
+ struct isci_port *isci_port,
+ u32 timeout);
+
void isci_port_formed(struct asd_sas_phy *);
void isci_port_deformed(struct asd_sas_phy *);
-void isci_port_init(
- struct isci_port *port,
- struct isci_host *host,
- int index);
-
int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport,
struct isci_phy *iphy);
int isci_ata_check_ready(struct domain_device *dev);
diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c
index 6d1e9544cbe5..cd962da4a57a 100644
--- a/drivers/scsi/isci/port_config.c
+++ b/drivers/scsi/isci/port_config.c
@@ -57,7 +57,7 @@
#define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10)
#define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10)
-#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (250)
+#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (1000)
enum SCIC_SDS_APC_ACTIVITY {
SCIC_SDS_APC_SKIP_PHY,
@@ -472,13 +472,9 @@ sci_apc_agent_validate_phy_configuration(struct isci_host *ihost,
* down event or a link up event where we can not yet tell to which a phy
* belongs.
*/
-static void sci_apc_agent_start_timer(
- struct sci_port_configuration_agent *port_agent,
- u32 timeout)
+static void sci_apc_agent_start_timer(struct sci_port_configuration_agent *port_agent,
+ u32 timeout)
{
- if (port_agent->timer_pending)
- sci_del_timer(&port_agent->timer);
-
port_agent->timer_pending = true;
sci_mod_timer(&port_agent->timer, timeout);
}
@@ -697,6 +693,9 @@ static void apc_agent_timeout(unsigned long data)
&ihost->phys[index], false);
}
+ if (is_controller_start_complete(ihost))
+ sci_controller_transition_to_ready(ihost, SCI_SUCCESS);
+
done:
spin_unlock_irqrestore(&ihost->scic_lock, flags);
}
@@ -732,6 +731,11 @@ void sci_port_configuration_agent_construct(
}
}
+bool is_port_config_apc(struct isci_host *ihost)
+{
+ return ihost->port_agent.link_up_handler == sci_apc_agent_link_up;
+}
+
enum sci_status sci_port_configuration_agent_initialize(
struct isci_host *ihost,
struct sci_port_configuration_agent *port_agent)
diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c
index 9b8117b9d756..4d95654c3fd4 100644
--- a/drivers/scsi/isci/probe_roms.c
+++ b/drivers/scsi/isci/probe_roms.c
@@ -112,18 +112,6 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev)
return rom;
}
-enum sci_status isci_parse_oem_parameters(struct sci_oem_params *oem,
- struct isci_orom *orom, int scu_index)
-{
- /* check for valid inputs */
- if (scu_index < 0 || scu_index >= SCI_MAX_CONTROLLERS ||
- scu_index > orom->hdr.num_elements || !oem)
- return -EINVAL;
-
- *oem = orom->ctrl[scu_index];
- return 0;
-}
-
struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw)
{
struct isci_orom *orom = NULL, *data;
diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h
index bb0e9d4d97c9..e08b578241f8 100644
--- a/drivers/scsi/isci/probe_roms.h
+++ b/drivers/scsi/isci/probe_roms.h
@@ -156,8 +156,6 @@ int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version);
struct isci_orom;
struct isci_orom *isci_request_oprom(struct pci_dev *pdev);
-enum sci_status isci_parse_oem_parameters(struct sci_oem_params *oem,
- struct isci_orom *orom, int scu_index);
struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw);
struct isci_orom *isci_get_efi_var(struct pci_dev *pdev);
diff --git a/drivers/scsi/isci/registers.h b/drivers/scsi/isci/registers.h
index 7eb0ccd45fe6..97f3ceb8d724 100644
--- a/drivers/scsi/isci/registers.h
+++ b/drivers/scsi/isci/registers.h
@@ -1239,6 +1239,14 @@ struct scu_transport_layer_registers {
#define SCU_SAS_LLCTL_GEN_BIT(name) \
SCU_GEN_BIT(SCU_SAS_LINK_LAYER_CONTROL_ ## name)
+#define SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT (0xF0)
+#define SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_EXTENDED (0x1FF)
+#define SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_SHIFT (0)
+#define SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_MASK (0x3FF)
+
+#define SCU_SAS_LLTXCOMSAS_GEN_VAL(name, value) \
+ SCU_GEN_VALUE(SCU_SAS_LINK_LAYER_TXCOMSAS_ ## name, value)
+
/* #define SCU_FRXHECR_DCNT_OFFSET 0x00B0 */
#define SCU_PSZGCR_OFFSET 0x00E4
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index 8f501b0a81d6..c3aa6c5457b9 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -72,46 +72,11 @@ const char *dev_state_name(enum sci_remote_device_states state)
}
#undef C
-/**
- * isci_remote_device_not_ready() - This function is called by the ihost when
- * the remote device is not ready. We mark the isci device as ready (not
- * "ready_for_io") and signal the waiting proccess.
- * @isci_host: This parameter specifies the isci host object.
- * @isci_device: This parameter specifies the remote device
- *
- * sci_lock is held on entrance to this function.
- */
-static void isci_remote_device_not_ready(struct isci_host *ihost,
- struct isci_remote_device *idev, u32 reason)
+enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev,
+ enum sci_remote_node_suspension_reasons reason)
{
- struct isci_request *ireq;
-
- dev_dbg(&ihost->pdev->dev,
- "%s: isci_device = %p\n", __func__, idev);
-
- switch (reason) {
- case SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED:
- set_bit(IDEV_GONE, &idev->flags);
- break;
- case SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED:
- set_bit(IDEV_IO_NCQERROR, &idev->flags);
-
- /* Kill all outstanding requests for the device. */
- list_for_each_entry(ireq, &idev->reqs_in_process, dev_node) {
-
- dev_dbg(&ihost->pdev->dev,
- "%s: isci_device = %p request = %p\n",
- __func__, idev, ireq);
-
- sci_controller_terminate_request(ihost,
- idev,
- ireq);
- }
- /* Fall through into the default case... */
- default:
- clear_bit(IDEV_IO_READY, &idev->flags);
- break;
- }
+ return sci_remote_node_context_suspend(&idev->rnc, reason,
+ SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT);
}
/**
@@ -133,18 +98,29 @@ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote
wake_up(&ihost->eventq);
}
-/* called once the remote node context is ready to be freed.
- * The remote device can now report that its stop operation is complete. none
- */
-static void rnc_destruct_done(void *_dev)
+static enum sci_status sci_remote_device_terminate_req(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev,
+ int check_abort,
+ struct isci_request *ireq)
{
- struct isci_remote_device *idev = _dev;
+ if (!test_bit(IREQ_ACTIVE, &ireq->flags) ||
+ (ireq->target_device != idev) ||
+ (check_abort && !test_bit(IREQ_PENDING_ABORT, &ireq->flags)))
+ return SCI_SUCCESS;
- BUG_ON(idev->started_request_count != 0);
- sci_change_state(&idev->sm, SCI_DEV_STOPPED);
+ dev_dbg(&ihost->pdev->dev,
+ "%s: idev=%p; flags=%lx; req=%p; req target=%p\n",
+ __func__, idev, idev->flags, ireq, ireq->target_device);
+
+ set_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags);
+
+ return sci_controller_terminate_request(ihost, idev, ireq);
}
-static enum sci_status sci_remote_device_terminate_requests(struct isci_remote_device *idev)
+static enum sci_status sci_remote_device_terminate_reqs_checkabort(
+ struct isci_remote_device *idev,
+ int chk)
{
struct isci_host *ihost = idev->owning_port->owning_controller;
enum sci_status status = SCI_SUCCESS;
@@ -154,18 +130,210 @@ static enum sci_status sci_remote_device_terminate_requests(struct isci_remote_d
struct isci_request *ireq = ihost->reqs[i];
enum sci_status s;
- if (!test_bit(IREQ_ACTIVE, &ireq->flags) ||
- ireq->target_device != idev)
- continue;
-
- s = sci_controller_terminate_request(ihost, idev, ireq);
+ s = sci_remote_device_terminate_req(ihost, idev, chk, ireq);
if (s != SCI_SUCCESS)
status = s;
}
+ return status;
+}
+
+static bool isci_compare_suspendcount(
+ struct isci_remote_device *idev,
+ u32 localcount)
+{
+ smp_rmb();
+
+ /* Check for a change in the suspend count, or the RNC
+ * being destroyed.
+ */
+ return (localcount != idev->rnc.suspend_count)
+ || sci_remote_node_context_is_being_destroyed(&idev->rnc);
+}
+
+static bool isci_check_reqterm(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev,
+ struct isci_request *ireq,
+ u32 localcount)
+{
+ unsigned long flags;
+ bool res;
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+ res = isci_compare_suspendcount(idev, localcount)
+ && !test_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+
+ return res;
+}
+
+static bool isci_check_devempty(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev,
+ u32 localcount)
+{
+ unsigned long flags;
+ bool res;
+
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+ res = isci_compare_suspendcount(idev, localcount)
+ && idev->started_request_count == 0;
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+
+ return res;
+}
+
+enum sci_status isci_remote_device_terminate_requests(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev,
+ struct isci_request *ireq)
+{
+ enum sci_status status = SCI_SUCCESS;
+ unsigned long flags;
+ u32 rnc_suspend_count;
+
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+
+ if (isci_get_device(idev) == NULL) {
+ dev_dbg(&ihost->pdev->dev, "%s: failed isci_get_device(idev=%p)\n",
+ __func__, idev);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ status = SCI_FAILURE;
+ } else {
+ /* If already suspended, don't wait for another suspension. */
+ smp_rmb();
+ rnc_suspend_count
+ = sci_remote_node_context_is_suspended(&idev->rnc)
+ ? 0 : idev->rnc.suspend_count;
+
+ dev_dbg(&ihost->pdev->dev,
+ "%s: idev=%p, ireq=%p; started_request_count=%d, "
+ "rnc_suspend_count=%d, rnc.suspend_count=%d"
+ "about to wait\n",
+ __func__, idev, ireq, idev->started_request_count,
+ rnc_suspend_count, idev->rnc.suspend_count);
+
+ #define MAX_SUSPEND_MSECS 10000
+ if (ireq) {
+ /* Terminate a specific TC. */
+ set_bit(IREQ_NO_AUTO_FREE_TAG, &ireq->flags);
+ sci_remote_device_terminate_req(ihost, idev, 0, ireq);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ if (!wait_event_timeout(ihost->eventq,
+ isci_check_reqterm(ihost, idev, ireq,
+ rnc_suspend_count),
+ msecs_to_jiffies(MAX_SUSPEND_MSECS))) {
+
+ dev_warn(&ihost->pdev->dev, "%s host%d timeout single\n",
+ __func__, ihost->id);
+ dev_dbg(&ihost->pdev->dev,
+ "%s: ******* Timeout waiting for "
+ "suspend; idev=%p, current state %s; "
+ "started_request_count=%d, flags=%lx\n\t"
+ "rnc_suspend_count=%d, rnc.suspend_count=%d "
+ "RNC: current state %s, current "
+ "suspend_type %x dest state %d;\n"
+ "ireq=%p, ireq->flags = %lx\n",
+ __func__, idev,
+ dev_state_name(idev->sm.current_state_id),
+ idev->started_request_count, idev->flags,
+ rnc_suspend_count, idev->rnc.suspend_count,
+ rnc_state_name(idev->rnc.sm.current_state_id),
+ idev->rnc.suspend_type,
+ idev->rnc.destination_state,
+ ireq, ireq->flags);
+ }
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+ clear_bit(IREQ_NO_AUTO_FREE_TAG, &ireq->flags);
+ if (!test_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags))
+ isci_free_tag(ihost, ireq->io_tag);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ } else {
+ /* Terminate all TCs. */
+ sci_remote_device_terminate_requests(idev);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ if (!wait_event_timeout(ihost->eventq,
+ isci_check_devempty(ihost, idev,
+ rnc_suspend_count),
+ msecs_to_jiffies(MAX_SUSPEND_MSECS))) {
+
+ dev_warn(&ihost->pdev->dev, "%s host%d timeout all\n",
+ __func__, ihost->id);
+ dev_dbg(&ihost->pdev->dev,
+ "%s: ******* Timeout waiting for "
+ "suspend; idev=%p, current state %s; "
+ "started_request_count=%d, flags=%lx\n\t"
+ "rnc_suspend_count=%d, "
+ "RNC: current state %s, "
+ "rnc.suspend_count=%d, current "
+ "suspend_type %x dest state %d\n",
+ __func__, idev,
+ dev_state_name(idev->sm.current_state_id),
+ idev->started_request_count, idev->flags,
+ rnc_suspend_count,
+ rnc_state_name(idev->rnc.sm.current_state_id),
+ idev->rnc.suspend_count,
+ idev->rnc.suspend_type,
+ idev->rnc.destination_state);
+ }
+ }
+ dev_dbg(&ihost->pdev->dev, "%s: idev=%p, wait done\n",
+ __func__, idev);
+ isci_put_device(idev);
+ }
return status;
}
+/**
+* isci_remote_device_not_ready() - This function is called by the ihost when
+* the remote device is not ready. We mark the isci device as ready (not
+* "ready_for_io") and signal the waiting proccess.
+* @isci_host: This parameter specifies the isci host object.
+* @isci_device: This parameter specifies the remote device
+*
+* sci_lock is held on entrance to this function.
+*/
+static void isci_remote_device_not_ready(struct isci_host *ihost,
+ struct isci_remote_device *idev,
+ u32 reason)
+{
+ dev_dbg(&ihost->pdev->dev,
+ "%s: isci_device = %p; reason = %d\n", __func__, idev, reason);
+
+ switch (reason) {
+ case SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED:
+ set_bit(IDEV_IO_NCQERROR, &idev->flags);
+
+ /* Suspend the remote device so the I/O can be terminated. */
+ sci_remote_device_suspend(idev, SCI_SW_SUSPEND_NORMAL);
+
+ /* Kill all outstanding requests for the device. */
+ sci_remote_device_terminate_requests(idev);
+
+ /* Fall through into the default case... */
+ default:
+ clear_bit(IDEV_IO_READY, &idev->flags);
+ break;
+ }
+}
+
+/* called once the remote node context is ready to be freed.
+ * The remote device can now report that its stop operation is complete. none
+ */
+static void rnc_destruct_done(void *_dev)
+{
+ struct isci_remote_device *idev = _dev;
+
+ BUG_ON(idev->started_request_count != 0);
+ sci_change_state(&idev->sm, SCI_DEV_STOPPED);
+}
+
+enum sci_status sci_remote_device_terminate_requests(
+ struct isci_remote_device *idev)
+{
+ return sci_remote_device_terminate_reqs_checkabort(idev, 0);
+}
+
enum sci_status sci_remote_device_stop(struct isci_remote_device *idev,
u32 timeout)
{
@@ -201,13 +369,16 @@ enum sci_status sci_remote_device_stop(struct isci_remote_device *idev,
case SCI_SMP_DEV_IDLE:
case SCI_SMP_DEV_CMD:
sci_change_state(sm, SCI_DEV_STOPPING);
- if (idev->started_request_count == 0) {
+ if (idev->started_request_count == 0)
sci_remote_node_context_destruct(&idev->rnc,
- rnc_destruct_done, idev);
- return SCI_SUCCESS;
- } else
- return sci_remote_device_terminate_requests(idev);
- break;
+ rnc_destruct_done,
+ idev);
+ else {
+ sci_remote_device_suspend(
+ idev, SCI_SW_SUSPEND_LINKHANG_DETECT);
+ sci_remote_device_terminate_requests(idev);
+ }
+ return SCI_SUCCESS;
case SCI_DEV_STOPPING:
/* All requests should have been terminated, but if there is an
* attempt to stop a device already in the stopping state, then
@@ -265,22 +436,6 @@ enum sci_status sci_remote_device_reset_complete(struct isci_remote_device *idev
return SCI_SUCCESS;
}
-enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev,
- u32 suspend_type)
-{
- struct sci_base_state_machine *sm = &idev->sm;
- enum sci_remote_device_states state = sm->current_state_id;
-
- if (state != SCI_STP_DEV_CMD) {
- dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %s\n",
- __func__, dev_state_name(state));
- return SCI_FAILURE_INVALID_STATE;
- }
-
- return sci_remote_node_context_suspend(&idev->rnc,
- suspend_type, NULL, NULL);
-}
-
enum sci_status sci_remote_device_frame_handler(struct isci_remote_device *idev,
u32 frame_index)
{
@@ -412,9 +567,9 @@ static void atapi_remote_device_resume_done(void *_dev)
enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
u32 event_code)
{
+ enum sci_status status;
struct sci_base_state_machine *sm = &idev->sm;
enum sci_remote_device_states state = sm->current_state_id;
- enum sci_status status;
switch (scu_get_event_type(event_code)) {
case SCU_EVENT_TYPE_RNC_OPS_MISC:
@@ -427,9 +582,7 @@ enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
status = SCI_SUCCESS;
/* Suspend the associated RNC */
- sci_remote_node_context_suspend(&idev->rnc,
- SCI_SOFTWARE_SUSPENSION,
- NULL, NULL);
+ sci_remote_device_suspend(idev, SCI_SW_SUSPEND_NORMAL);
dev_dbg(scirdev_to_dev(idev),
"%s: device: %p event code: %x: %s\n",
@@ -455,6 +608,10 @@ enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
if (status != SCI_SUCCESS)
return status;
+ /* Decode device-specific states that may require an RNC resume during
+ * normal operation. When the abort path is active, these resumes are
+ * managed when the abort path exits.
+ */
if (state == SCI_STP_DEV_ATAPI_ERROR) {
/* For ATAPI error state resume the RNC right away. */
if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX ||
@@ -743,10 +900,6 @@ enum sci_status sci_remote_device_start_task(struct isci_host *ihost,
if (status != SCI_SUCCESS)
return status;
- status = sci_remote_node_context_start_task(&idev->rnc, ireq);
- if (status != SCI_SUCCESS)
- goto out;
-
status = sci_request_start(ireq);
if (status != SCI_SUCCESS)
goto out;
@@ -765,11 +918,11 @@ enum sci_status sci_remote_device_start_task(struct isci_host *ihost,
* the correct action when the remote node context is suspended
* and later resumed.
*/
- sci_remote_node_context_suspend(&idev->rnc,
- SCI_SOFTWARE_SUSPENSION, NULL, NULL);
- sci_remote_node_context_resume(&idev->rnc,
- sci_remote_device_continue_request,
- idev);
+ sci_remote_device_suspend(idev,
+ SCI_SW_SUSPEND_LINKHANG_DETECT);
+
+ status = sci_remote_node_context_start_task(&idev->rnc, ireq,
+ sci_remote_device_continue_request, idev);
out:
sci_remote_device_start_request(idev, ireq, status);
@@ -783,7 +936,9 @@ enum sci_status sci_remote_device_start_task(struct isci_host *ihost,
if (status != SCI_SUCCESS)
return status;
- status = sci_remote_node_context_start_task(&idev->rnc, ireq);
+ /* Resume the RNC as needed: */
+ status = sci_remote_node_context_start_task(&idev->rnc, ireq,
+ NULL, NULL);
if (status != SCI_SUCCESS)
break;
@@ -892,7 +1047,7 @@ static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_
* here should go through isci_remote_device_nuke_requests.
* If we hit this condition, we will need a way to complete
* io requests in process */
- BUG_ON(!list_empty(&idev->reqs_in_process));
+ BUG_ON(idev->started_request_count > 0);
sci_remote_device_destruct(idev);
list_del_init(&idev->node);
@@ -954,14 +1109,21 @@ static void sci_remote_device_ready_state_exit(struct sci_base_state_machine *sm
static void sci_remote_device_resetting_state_enter(struct sci_base_state_machine *sm)
{
struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
+ struct isci_host *ihost = idev->owning_port->owning_controller;
- sci_remote_node_context_suspend(
- &idev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL);
+ dev_dbg(&ihost->pdev->dev,
+ "%s: isci_device = %p\n", __func__, idev);
+
+ sci_remote_device_suspend(idev, SCI_SW_SUSPEND_LINKHANG_DETECT);
}
static void sci_remote_device_resetting_state_exit(struct sci_base_state_machine *sm)
{
struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
+ struct isci_host *ihost = idev->owning_port->owning_controller;
+
+ dev_dbg(&ihost->pdev->dev,
+ "%s: isci_device = %p\n", __func__, idev);
sci_remote_node_context_resume(&idev->rnc, NULL, NULL);
}
@@ -1113,33 +1275,20 @@ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport,
{
enum sci_status status;
struct sci_port_properties properties;
- struct domain_device *dev = idev->domain_dev;
sci_remote_device_construct(iport, idev);
- /*
- * This information is request to determine how many remote node context
- * entries will be needed to store the remote node.
- */
- idev->is_direct_attached = true;
-
sci_port_get_properties(iport, &properties);
/* Get accurate port width from port's phy mask for a DA device. */
idev->device_port_width = hweight32(properties.phy_mask);
status = sci_controller_allocate_remote_node_context(iport->owning_controller,
- idev,
- &idev->rnc.remote_node_index);
+ idev,
+ &idev->rnc.remote_node_index);
if (status != SCI_SUCCESS)
return status;
- if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV ||
- (dev->tproto & SAS_PROTOCOL_STP) || dev_is_expander(dev))
- /* pass */;
- else
- return SCI_FAILURE_UNSUPPORTED_PROTOCOL;
-
idev->connection_rate = sci_port_get_max_allowed_speed(iport);
return SCI_SUCCESS;
@@ -1171,19 +1320,13 @@ static enum sci_status sci_remote_device_ea_construct(struct isci_port *iport,
if (status != SCI_SUCCESS)
return status;
- if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV ||
- (dev->tproto & SAS_PROTOCOL_STP) || dev_is_expander(dev))
- /* pass */;
- else
- return SCI_FAILURE_UNSUPPORTED_PROTOCOL;
-
- /*
- * For SAS-2 the physical link rate is actually a logical link
+ /* For SAS-2 the physical link rate is actually a logical link
* rate that incorporates multiplexing. The SCU doesn't
* incorporate multiplexing and for the purposes of the
* connection the logical link rate is that same as the
* physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay
- * one another, so this code works for both situations. */
+ * one another, so this code works for both situations.
+ */
idev->connection_rate = min_t(u16, sci_port_get_max_allowed_speed(iport),
dev->linkrate);
@@ -1193,6 +1336,105 @@ static enum sci_status sci_remote_device_ea_construct(struct isci_port *iport,
return SCI_SUCCESS;
}
+enum sci_status sci_remote_device_resume(
+ struct isci_remote_device *idev,
+ scics_sds_remote_node_context_callback cb_fn,
+ void *cb_p)
+{
+ enum sci_status status;
+
+ status = sci_remote_node_context_resume(&idev->rnc, cb_fn, cb_p);
+ if (status != SCI_SUCCESS)
+ dev_dbg(scirdev_to_dev(idev), "%s: failed to resume: %d\n",
+ __func__, status);
+ return status;
+}
+
+static void isci_remote_device_resume_from_abort_complete(void *cbparam)
+{
+ struct isci_remote_device *idev = cbparam;
+ struct isci_host *ihost = idev->owning_port->owning_controller;
+ scics_sds_remote_node_context_callback abort_resume_cb =
+ idev->abort_resume_cb;
+
+ dev_dbg(scirdev_to_dev(idev), "%s: passing-along resume: %p\n",
+ __func__, abort_resume_cb);
+
+ if (abort_resume_cb != NULL) {
+ idev->abort_resume_cb = NULL;
+ abort_resume_cb(idev->abort_resume_cbparam);
+ }
+ clear_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);
+ wake_up(&ihost->eventq);
+}
+
+static bool isci_remote_device_test_resume_done(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev)
+{
+ unsigned long flags;
+ bool done;
+
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+ done = !test_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags)
+ || test_bit(IDEV_STOP_PENDING, &idev->flags)
+ || sci_remote_node_context_is_being_destroyed(&idev->rnc);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+
+ return done;
+}
+
+void isci_remote_device_wait_for_resume_from_abort(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev)
+{
+ dev_dbg(&ihost->pdev->dev, "%s: starting resume wait: %p\n",
+ __func__, idev);
+
+ #define MAX_RESUME_MSECS 10000
+ if (!wait_event_timeout(ihost->eventq,
+ isci_remote_device_test_resume_done(ihost, idev),
+ msecs_to_jiffies(MAX_RESUME_MSECS))) {
+
+ dev_warn(&ihost->pdev->dev, "%s: #### Timeout waiting for "
+ "resume: %p\n", __func__, idev);
+ }
+ clear_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);
+
+ dev_dbg(&ihost->pdev->dev, "%s: resume wait done: %p\n",
+ __func__, idev);
+}
+
+enum sci_status isci_remote_device_resume_from_abort(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev)
+{
+ unsigned long flags;
+ enum sci_status status = SCI_SUCCESS;
+ int destroyed;
+
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+ /* Preserve any current resume callbacks, for instance from other
+ * resumptions.
+ */
+ idev->abort_resume_cb = idev->rnc.user_callback;
+ idev->abort_resume_cbparam = idev->rnc.user_cookie;
+ set_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);
+ clear_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags);
+ destroyed = sci_remote_node_context_is_being_destroyed(&idev->rnc);
+ if (!destroyed)
+ status = sci_remote_device_resume(
+ idev, isci_remote_device_resume_from_abort_complete,
+ idev);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ if (!destroyed && (status == SCI_SUCCESS))
+ isci_remote_device_wait_for_resume_from_abort(ihost, idev);
+ else
+ clear_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);
+
+ return status;
+}
+
/**
* sci_remote_device_start() - This method will start the supplied remote
* device. This method enables normal IO requests to flow through to the
@@ -1207,7 +1449,7 @@ static enum sci_status sci_remote_device_ea_construct(struct isci_port *iport,
* the device when there have been no phys added to it.
*/
static enum sci_status sci_remote_device_start(struct isci_remote_device *idev,
- u32 timeout)
+ u32 timeout)
{
struct sci_base_state_machine *sm = &idev->sm;
enum sci_remote_device_states state = sm->current_state_id;
@@ -1219,9 +1461,8 @@ static enum sci_status sci_remote_device_start(struct isci_remote_device *idev,
return SCI_FAILURE_INVALID_STATE;
}
- status = sci_remote_node_context_resume(&idev->rnc,
- remote_device_resume_done,
- idev);
+ status = sci_remote_device_resume(idev, remote_device_resume_done,
+ idev);
if (status != SCI_SUCCESS)
return status;
@@ -1259,20 +1500,6 @@ static enum sci_status isci_remote_device_construct(struct isci_port *iport,
return status;
}
-void isci_remote_device_nuke_requests(struct isci_host *ihost, struct isci_remote_device *idev)
-{
- DECLARE_COMPLETION_ONSTACK(aborted_task_completion);
-
- dev_dbg(&ihost->pdev->dev,
- "%s: idev = %p\n", __func__, idev);
-
- /* Cleanup all requests pending for this device. */
- isci_terminate_pending_requests(ihost, idev);
-
- dev_dbg(&ihost->pdev->dev,
- "%s: idev = %p, done\n", __func__, idev);
-}
-
/**
* This function builds the isci_remote_device when a libsas dev_found message
* is received.
@@ -1297,10 +1524,6 @@ isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport)
dev_warn(&ihost->pdev->dev, "%s: failed\n", __func__);
return NULL;
}
-
- if (WARN_ONCE(!list_empty(&idev->reqs_in_process), "found requests in process\n"))
- return NULL;
-
if (WARN_ONCE(!list_empty(&idev->node), "found non-idle remote device\n"))
return NULL;
@@ -1342,14 +1565,8 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem
spin_lock_irqsave(&ihost->scic_lock, flags);
idev->domain_dev->lldd_dev = NULL; /* disable new lookups */
set_bit(IDEV_GONE, &idev->flags);
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
-
- /* Kill all outstanding requests. */
- isci_remote_device_nuke_requests(ihost, idev);
set_bit(IDEV_STOP_PENDING, &idev->flags);
-
- spin_lock_irqsave(&ihost->scic_lock, flags);
status = sci_remote_device_stop(idev, 50);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
@@ -1359,6 +1576,9 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem
else
wait_for_device_stop(ihost, idev);
+ dev_dbg(&ihost->pdev->dev,
+ "%s: isci_device = %p, waiting done.\n", __func__, idev);
+
return status;
}
@@ -1434,3 +1654,73 @@ int isci_remote_device_found(struct domain_device *dev)
return status == SCI_SUCCESS ? 0 : -ENODEV;
}
+
+enum sci_status isci_remote_device_suspend_terminate(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev,
+ struct isci_request *ireq)
+{
+ unsigned long flags;
+ enum sci_status status;
+
+ /* Put the device into suspension. */
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+ set_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags);
+ sci_remote_device_suspend(idev, SCI_SW_SUSPEND_LINKHANG_DETECT);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+
+ /* Terminate and wait for the completions. */
+ status = isci_remote_device_terminate_requests(ihost, idev, ireq);
+ if (status != SCI_SUCCESS)
+ dev_dbg(&ihost->pdev->dev,
+ "%s: isci_remote_device_terminate_requests(%p) "
+ "returned %d!\n",
+ __func__, idev, status);
+
+ /* NOTE: RNC resumption is left to the caller! */
+ return status;
+}
+
+int isci_remote_device_is_safe_to_abort(
+ struct isci_remote_device *idev)
+{
+ return sci_remote_node_context_is_safe_to_abort(&idev->rnc);
+}
+
+enum sci_status sci_remote_device_abort_requests_pending_abort(
+ struct isci_remote_device *idev)
+{
+ return sci_remote_device_terminate_reqs_checkabort(idev, 1);
+}
+
+enum sci_status isci_remote_device_reset_complete(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev)
+{
+ unsigned long flags;
+ enum sci_status status;
+
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+ status = sci_remote_device_reset_complete(idev);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+
+ return status;
+}
+
+void isci_dev_set_hang_detection_timeout(
+ struct isci_remote_device *idev,
+ u32 timeout)
+{
+ if (dev_is_sata(idev->domain_dev)) {
+ if (timeout) {
+ if (test_and_set_bit(IDEV_RNC_LLHANG_ENABLED,
+ &idev->flags))
+ return; /* Already enabled. */
+ } else if (!test_and_clear_bit(IDEV_RNC_LLHANG_ENABLED,
+ &idev->flags))
+ return; /* Not enabled. */
+
+ sci_port_set_hang_detection_timeout(idev->owning_port,
+ timeout);
+ }
+}
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
index 58637ee08f55..7674caae1d88 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -85,27 +85,38 @@ struct isci_remote_device {
#define IDEV_GONE 3
#define IDEV_IO_READY 4
#define IDEV_IO_NCQERROR 5
+ #define IDEV_RNC_LLHANG_ENABLED 6
+ #define IDEV_ABORT_PATH_ACTIVE 7
+ #define IDEV_ABORT_PATH_RESUME_PENDING 8
unsigned long flags;
struct kref kref;
struct isci_port *isci_port;
struct domain_device *domain_dev;
struct list_head node;
- struct list_head reqs_in_process;
struct sci_base_state_machine sm;
u32 device_port_width;
enum sas_linkrate connection_rate;
- bool is_direct_attached;
struct isci_port *owning_port;
struct sci_remote_node_context rnc;
/* XXX unify with device reference counting and delete */
u32 started_request_count;
struct isci_request *working_request;
u32 not_ready_reason;
+ scics_sds_remote_node_context_callback abort_resume_cb;
+ void *abort_resume_cbparam;
};
#define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000
/* device reference routines must be called under sci_lock */
+static inline struct isci_remote_device *isci_get_device(
+ struct isci_remote_device *idev)
+{
+ if (idev)
+ kref_get(&idev->kref);
+ return idev;
+}
+
static inline struct isci_remote_device *isci_lookup_device(struct domain_device *dev)
{
struct isci_remote_device *idev = dev->lldd_dev;
@@ -302,6 +313,8 @@ static inline void sci_remote_device_decrement_request_count(struct isci_remote_
idev->started_request_count--;
}
+void isci_dev_set_hang_detection_timeout(struct isci_remote_device *idev, u32 timeout);
+
enum sci_status sci_remote_device_frame_handler(
struct isci_remote_device *idev,
u32 frame_index);
@@ -325,12 +338,50 @@ enum sci_status sci_remote_device_complete_io(
struct isci_remote_device *idev,
struct isci_request *ireq);
-enum sci_status sci_remote_device_suspend(
- struct isci_remote_device *idev,
- u32 suspend_type);
-
void sci_remote_device_post_request(
struct isci_remote_device *idev,
u32 request);
+enum sci_status sci_remote_device_terminate_requests(
+ struct isci_remote_device *idev);
+
+int isci_remote_device_is_safe_to_abort(
+ struct isci_remote_device *idev);
+
+enum sci_status
+sci_remote_device_abort_requests_pending_abort(
+ struct isci_remote_device *idev);
+
+enum sci_status isci_remote_device_suspend(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev);
+
+enum sci_status sci_remote_device_resume(
+ struct isci_remote_device *idev,
+ scics_sds_remote_node_context_callback cb_fn,
+ void *cb_p);
+
+enum sci_status isci_remote_device_resume_from_abort(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev);
+
+enum sci_status isci_remote_device_reset(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev);
+
+enum sci_status isci_remote_device_reset_complete(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev);
+
+enum sci_status isci_remote_device_suspend_terminate(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev,
+ struct isci_request *ireq);
+
+enum sci_status isci_remote_device_terminate_requests(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev,
+ struct isci_request *ireq);
+enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev,
+ enum sci_remote_node_suspension_reasons reason);
#endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */
diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c
index 3a9463481f38..1910100638a2 100644
--- a/drivers/scsi/isci/remote_node_context.c
+++ b/drivers/scsi/isci/remote_node_context.c
@@ -52,7 +52,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
+#include <scsi/sas_ata.h>
#include "host.h"
#include "isci.h"
#include "remote_device.h"
@@ -90,6 +90,15 @@ bool sci_remote_node_context_is_ready(
return false;
}
+bool sci_remote_node_context_is_suspended(struct sci_remote_node_context *sci_rnc)
+{
+ u32 current_state = sci_rnc->sm.current_state_id;
+
+ if (current_state == SCI_RNC_TX_RX_SUSPENDED)
+ return true;
+ return false;
+}
+
static union scu_remote_node_context *sci_rnc_by_id(struct isci_host *ihost, u16 id)
{
if (id < ihost->remote_node_entries &&
@@ -131,7 +140,7 @@ static void sci_remote_node_context_construct_buffer(struct sci_remote_node_cont
rnc->ssp.arbitration_wait_time = 0;
- if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
+ if (dev_is_sata(dev)) {
rnc->ssp.connection_occupancy_timeout =
ihost->user_parameters.stp_max_occupancy_timeout;
rnc->ssp.connection_inactivity_timeout =
@@ -151,7 +160,6 @@ static void sci_remote_node_context_construct_buffer(struct sci_remote_node_cont
rnc->ssp.oaf_source_zone_group = 0;
rnc->ssp.oaf_more_compatibility_features = 0;
}
-
/**
*
* @sci_rnc:
@@ -165,23 +173,30 @@ static void sci_remote_node_context_construct_buffer(struct sci_remote_node_cont
static void sci_remote_node_context_setup_to_resume(
struct sci_remote_node_context *sci_rnc,
scics_sds_remote_node_context_callback callback,
- void *callback_parameter)
+ void *callback_parameter,
+ enum sci_remote_node_context_destination_state dest_param)
{
- if (sci_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) {
- sci_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY;
- sci_rnc->user_callback = callback;
- sci_rnc->user_cookie = callback_parameter;
+ if (sci_rnc->destination_state != RNC_DEST_FINAL) {
+ sci_rnc->destination_state = dest_param;
+ if (callback != NULL) {
+ sci_rnc->user_callback = callback;
+ sci_rnc->user_cookie = callback_parameter;
+ }
}
}
-static void sci_remote_node_context_setup_to_destory(
+static void sci_remote_node_context_setup_to_destroy(
struct sci_remote_node_context *sci_rnc,
scics_sds_remote_node_context_callback callback,
void *callback_parameter)
{
- sci_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL;
+ struct isci_host *ihost = idev_to_ihost(rnc_to_dev(sci_rnc));
+
+ sci_rnc->destination_state = RNC_DEST_FINAL;
sci_rnc->user_callback = callback;
sci_rnc->user_cookie = callback_parameter;
+
+ wake_up(&ihost->eventq);
}
/**
@@ -203,9 +218,19 @@ static void sci_remote_node_context_notify_user(
static void sci_remote_node_context_continue_state_transitions(struct sci_remote_node_context *rnc)
{
- if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
+ switch (rnc->destination_state) {
+ case RNC_DEST_READY:
+ case RNC_DEST_SUSPENDED_RESUME:
+ rnc->destination_state = RNC_DEST_READY;
+ /* Fall through... */
+ case RNC_DEST_FINAL:
sci_remote_node_context_resume(rnc, rnc->user_callback,
- rnc->user_cookie);
+ rnc->user_cookie);
+ break;
+ default:
+ rnc->destination_state = RNC_DEST_UNSPECIFIED;
+ break;
+ }
}
static void sci_remote_node_context_validate_context_buffer(struct sci_remote_node_context *sci_rnc)
@@ -219,13 +244,12 @@ static void sci_remote_node_context_validate_context_buffer(struct sci_remote_no
rnc_buffer->ssp.is_valid = true;
- if (!idev->is_direct_attached &&
- (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP))) {
+ if (dev_is_sata(dev) && dev->parent) {
sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_96);
} else {
sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_32);
- if (idev->is_direct_attached)
+ if (!dev->parent)
sci_port_setup_transports(idev->owning_port,
sci_rnc->remote_node_index);
}
@@ -248,13 +272,18 @@ static void sci_remote_node_context_invalidate_context_buffer(struct sci_remote_
static void sci_remote_node_context_initial_state_enter(struct sci_base_state_machine *sm)
{
struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
+ struct isci_remote_device *idev = rnc_to_dev(rnc);
+ struct isci_host *ihost = idev->owning_port->owning_controller;
/* Check to see if we have gotten back to the initial state because
* someone requested to destroy the remote node context object.
*/
if (sm->previous_state_id == SCI_RNC_INVALIDATING) {
- rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
+ rnc->destination_state = RNC_DEST_UNSPECIFIED;
sci_remote_node_context_notify_user(rnc);
+
+ smp_wmb();
+ wake_up(&ihost->eventq);
}
}
@@ -269,6 +298,8 @@ static void sci_remote_node_context_invalidating_state_enter(struct sci_base_sta
{
struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
+ /* Terminate all outstanding requests. */
+ sci_remote_device_terminate_requests(rnc_to_dev(rnc));
sci_remote_node_context_invalidate_context_buffer(rnc);
}
@@ -287,10 +318,8 @@ static void sci_remote_node_context_resuming_state_enter(struct sci_base_state_m
* resume because of a target reset we also need to update
* the STPTLDARNI register with the RNi of the device
*/
- if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) &&
- idev->is_direct_attached)
- sci_port_setup_transports(idev->owning_port,
- rnc->remote_node_index);
+ if (dev_is_sata(dev) && !dev->parent)
+ sci_port_setup_transports(idev->owning_port, rnc->remote_node_index);
sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME);
}
@@ -298,10 +327,22 @@ static void sci_remote_node_context_resuming_state_enter(struct sci_base_state_m
static void sci_remote_node_context_ready_state_enter(struct sci_base_state_machine *sm)
{
struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
+ enum sci_remote_node_context_destination_state dest_select;
+ int tell_user = 1;
+
+ dest_select = rnc->destination_state;
+ rnc->destination_state = RNC_DEST_UNSPECIFIED;
- rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
+ if ((dest_select == RNC_DEST_SUSPENDED) ||
+ (dest_select == RNC_DEST_SUSPENDED_RESUME)) {
+ sci_remote_node_context_suspend(
+ rnc, rnc->suspend_reason,
+ SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT);
- if (rnc->user_callback)
+ if (dest_select == RNC_DEST_SUSPENDED_RESUME)
+ tell_user = 0; /* Wait until ready again. */
+ }
+ if (tell_user)
sci_remote_node_context_notify_user(rnc);
}
@@ -315,10 +356,34 @@ static void sci_remote_node_context_tx_suspended_state_enter(struct sci_base_sta
static void sci_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_state_machine *sm)
{
struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
+ struct isci_remote_device *idev = rnc_to_dev(rnc);
+ struct isci_host *ihost = idev->owning_port->owning_controller;
+ u32 new_count = rnc->suspend_count + 1;
+
+ if (new_count == 0)
+ rnc->suspend_count = 1;
+ else
+ rnc->suspend_count = new_count;
+ smp_wmb();
+ /* Terminate outstanding requests pending abort. */
+ sci_remote_device_abort_requests_pending_abort(idev);
+
+ wake_up(&ihost->eventq);
sci_remote_node_context_continue_state_transitions(rnc);
}
+static void sci_remote_node_context_await_suspend_state_exit(
+ struct sci_base_state_machine *sm)
+{
+ struct sci_remote_node_context *rnc
+ = container_of(sm, typeof(*rnc), sm);
+ struct isci_remote_device *idev = rnc_to_dev(rnc);
+
+ if (dev_is_sata(idev->domain_dev))
+ isci_dev_set_hang_detection_timeout(idev, 0);
+}
+
static const struct sci_base_state sci_remote_node_context_state_table[] = {
[SCI_RNC_INITIAL] = {
.enter_state = sci_remote_node_context_initial_state_enter,
@@ -341,7 +406,9 @@ static const struct sci_base_state sci_remote_node_context_state_table[] = {
[SCI_RNC_TX_RX_SUSPENDED] = {
.enter_state = sci_remote_node_context_tx_rx_suspended_state_enter,
},
- [SCI_RNC_AWAIT_SUSPENSION] = { },
+ [SCI_RNC_AWAIT_SUSPENSION] = {
+ .exit_state = sci_remote_node_context_await_suspend_state_exit,
+ },
};
void sci_remote_node_context_construct(struct sci_remote_node_context *rnc,
@@ -350,7 +417,7 @@ void sci_remote_node_context_construct(struct sci_remote_node_context *rnc,
memset(rnc, 0, sizeof(struct sci_remote_node_context));
rnc->remote_node_index = remote_node_index;
- rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
+ rnc->destination_state = RNC_DEST_UNSPECIFIED;
sci_init_sm(&rnc->sm, sci_remote_node_context_state_table, SCI_RNC_INITIAL);
}
@@ -359,6 +426,7 @@ enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_con
u32 event_code)
{
enum scis_sds_remote_node_context_states state;
+ u32 next_state;
state = sci_rnc->sm.current_state_id;
switch (state) {
@@ -373,18 +441,18 @@ enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_con
break;
case SCI_RNC_INVALIDATING:
if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) {
- if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
- state = SCI_RNC_INITIAL;
+ if (sci_rnc->destination_state == RNC_DEST_FINAL)
+ next_state = SCI_RNC_INITIAL;
else
- state = SCI_RNC_POSTING;
- sci_change_state(&sci_rnc->sm, state);
+ next_state = SCI_RNC_POSTING;
+ sci_change_state(&sci_rnc->sm, next_state);
} else {
switch (scu_get_event_type(event_code)) {
case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
/* We really dont care if the hardware is going to suspend
* the device since it's being invalidated anyway */
- dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)),
+ dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
"%s: SCIC Remote Node Context 0x%p was "
"suspeneded by hardware while being "
"invalidated.\n", __func__, sci_rnc);
@@ -403,7 +471,7 @@ enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_con
case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
/* We really dont care if the hardware is going to suspend
* the device since it's being resumed anyway */
- dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)),
+ dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
"%s: SCIC Remote Node Context 0x%p was "
"suspeneded by hardware while being resumed.\n",
__func__, sci_rnc);
@@ -417,11 +485,11 @@ enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_con
switch (scu_get_event_type(event_code)) {
case SCU_EVENT_TL_RNC_SUSPEND_TX:
sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED);
- sci_rnc->suspension_code = scu_get_event_specifier(event_code);
+ sci_rnc->suspend_type = scu_get_event_type(event_code);
break;
case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED);
- sci_rnc->suspension_code = scu_get_event_specifier(event_code);
+ sci_rnc->suspend_type = scu_get_event_type(event_code);
break;
default:
goto out;
@@ -430,27 +498,29 @@ enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_con
case SCI_RNC_AWAIT_SUSPENSION:
switch (scu_get_event_type(event_code)) {
case SCU_EVENT_TL_RNC_SUSPEND_TX:
- sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED);
- sci_rnc->suspension_code = scu_get_event_specifier(event_code);
+ next_state = SCI_RNC_TX_SUSPENDED;
break;
case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
- sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED);
- sci_rnc->suspension_code = scu_get_event_specifier(event_code);
+ next_state = SCI_RNC_TX_RX_SUSPENDED;
break;
default:
goto out;
}
+ if (sci_rnc->suspend_type == scu_get_event_type(event_code))
+ sci_change_state(&sci_rnc->sm, next_state);
break;
default:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
- "%s: invalid state %d\n", __func__, state);
+ "%s: invalid state: %s\n", __func__,
+ rnc_state_name(state));
return SCI_FAILURE_INVALID_STATE;
}
return SCI_SUCCESS;
out:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
- "%s: code: %#x state: %d\n", __func__, event_code, state);
+ "%s: code: %#x state: %s\n", __func__, event_code,
+ rnc_state_name(state));
return SCI_FAILURE;
}
@@ -464,20 +534,23 @@ enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context
state = sci_rnc->sm.current_state_id;
switch (state) {
case SCI_RNC_INVALIDATING:
- sci_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p);
+ sci_remote_node_context_setup_to_destroy(sci_rnc, cb_fn, cb_p);
return SCI_SUCCESS;
case SCI_RNC_POSTING:
case SCI_RNC_RESUMING:
case SCI_RNC_READY:
case SCI_RNC_TX_SUSPENDED:
case SCI_RNC_TX_RX_SUSPENDED:
- case SCI_RNC_AWAIT_SUSPENSION:
- sci_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p);
+ sci_remote_node_context_setup_to_destroy(sci_rnc, cb_fn, cb_p);
sci_change_state(&sci_rnc->sm, SCI_RNC_INVALIDATING);
return SCI_SUCCESS;
+ case SCI_RNC_AWAIT_SUSPENSION:
+ sci_remote_node_context_setup_to_destroy(sci_rnc, cb_fn, cb_p);
+ return SCI_SUCCESS;
case SCI_RNC_INITIAL:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
- "%s: invalid state %d\n", __func__, state);
+ "%s: invalid state: %s\n", __func__,
+ rnc_state_name(state));
/* We have decided that the destruct request on the remote node context
* can not fail since it is either in the initial/destroyed state or is
* can be destroyed.
@@ -485,35 +558,101 @@ enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context
return SCI_SUCCESS;
default:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
- "%s: invalid state %d\n", __func__, state);
+ "%s: invalid state %s\n", __func__,
+ rnc_state_name(state));
return SCI_FAILURE_INVALID_STATE;
}
}
-enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *sci_rnc,
- u32 suspend_type,
- scics_sds_remote_node_context_callback cb_fn,
- void *cb_p)
+enum sci_status sci_remote_node_context_suspend(
+ struct sci_remote_node_context *sci_rnc,
+ enum sci_remote_node_suspension_reasons suspend_reason,
+ u32 suspend_type)
{
- enum scis_sds_remote_node_context_states state;
+ enum scis_sds_remote_node_context_states state
+ = sci_rnc->sm.current_state_id;
+ struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
+ enum sci_status status = SCI_FAILURE_INVALID_STATE;
+ enum sci_remote_node_context_destination_state dest_param =
+ RNC_DEST_UNSPECIFIED;
+
+ dev_dbg(scirdev_to_dev(idev),
+ "%s: current state %s, current suspend_type %x dest state %d,"
+ " arg suspend_reason %d, arg suspend_type %x",
+ __func__, rnc_state_name(state), sci_rnc->suspend_type,
+ sci_rnc->destination_state, suspend_reason,
+ suspend_type);
+
+ /* Disable automatic state continuations if explicitly suspending. */
+ if ((suspend_reason == SCI_HW_SUSPEND) ||
+ (sci_rnc->destination_state == RNC_DEST_FINAL))
+ dest_param = sci_rnc->destination_state;
- state = sci_rnc->sm.current_state_id;
- if (state != SCI_RNC_READY) {
+ switch (state) {
+ case SCI_RNC_READY:
+ break;
+ case SCI_RNC_INVALIDATING:
+ if (sci_rnc->destination_state == RNC_DEST_FINAL) {
+ dev_warn(scirdev_to_dev(idev),
+ "%s: already destroying %p\n",
+ __func__, sci_rnc);
+ return SCI_FAILURE_INVALID_STATE;
+ }
+ /* Fall through and handle like SCI_RNC_POSTING */
+ case SCI_RNC_RESUMING:
+ /* Fall through and handle like SCI_RNC_POSTING */
+ case SCI_RNC_POSTING:
+ /* Set the destination state to AWAIT - this signals the
+ * entry into the SCI_RNC_READY state that a suspension
+ * needs to be done immediately.
+ */
+ if (sci_rnc->destination_state != RNC_DEST_FINAL)
+ sci_rnc->destination_state = RNC_DEST_SUSPENDED;
+ sci_rnc->suspend_type = suspend_type;
+ sci_rnc->suspend_reason = suspend_reason;
+ return SCI_SUCCESS;
+
+ case SCI_RNC_TX_SUSPENDED:
+ if (suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX)
+ status = SCI_SUCCESS;
+ break;
+ case SCI_RNC_TX_RX_SUSPENDED:
+ if (suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX_RX)
+ status = SCI_SUCCESS;
+ break;
+ case SCI_RNC_AWAIT_SUSPENSION:
+ if ((sci_rnc->suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX_RX)
+ || (suspend_type == sci_rnc->suspend_type))
+ return SCI_SUCCESS;
+ break;
+ default:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
- "%s: invalid state %d\n", __func__, state);
+ "%s: invalid state %s\n", __func__,
+ rnc_state_name(state));
return SCI_FAILURE_INVALID_STATE;
}
+ sci_rnc->destination_state = dest_param;
+ sci_rnc->suspend_type = suspend_type;
+ sci_rnc->suspend_reason = suspend_reason;
+
+ if (status == SCI_SUCCESS) { /* Already in the destination state? */
+ struct isci_host *ihost = idev->owning_port->owning_controller;
+
+ wake_up_all(&ihost->eventq); /* Let observers look. */
+ return SCI_SUCCESS;
+ }
+ if ((suspend_reason == SCI_SW_SUSPEND_NORMAL) ||
+ (suspend_reason == SCI_SW_SUSPEND_LINKHANG_DETECT)) {
- sci_rnc->user_callback = cb_fn;
- sci_rnc->user_cookie = cb_p;
- sci_rnc->suspension_code = suspend_type;
+ if (suspend_reason == SCI_SW_SUSPEND_LINKHANG_DETECT)
+ isci_dev_set_hang_detection_timeout(idev, 0x00000001);
- if (suspend_type == SCI_SOFTWARE_SUSPENSION) {
- sci_remote_device_post_request(rnc_to_dev(sci_rnc),
- SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX);
+ sci_remote_device_post_request(
+ idev, SCI_SOFTWARE_SUSPEND_CMD);
}
+ if (state != SCI_RNC_AWAIT_SUSPENSION)
+ sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION);
- sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION);
return SCI_SUCCESS;
}
@@ -522,56 +661,86 @@ enum sci_status sci_remote_node_context_resume(struct sci_remote_node_context *s
void *cb_p)
{
enum scis_sds_remote_node_context_states state;
+ struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
state = sci_rnc->sm.current_state_id;
+ dev_dbg(scirdev_to_dev(idev),
+ "%s: state %s, cb_fn = %p, cb_p = %p; dest_state = %d; "
+ "dev resume path %s\n",
+ __func__, rnc_state_name(state), cb_fn, cb_p,
+ sci_rnc->destination_state,
+ test_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags)
+ ? "<abort active>" : "<normal>");
+
switch (state) {
case SCI_RNC_INITIAL:
if (sci_rnc->remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
return SCI_FAILURE_INVALID_STATE;
- sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p);
- sci_remote_node_context_construct_buffer(sci_rnc);
- sci_change_state(&sci_rnc->sm, SCI_RNC_POSTING);
+ sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p,
+ RNC_DEST_READY);
+ if (!test_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags)) {
+ sci_remote_node_context_construct_buffer(sci_rnc);
+ sci_change_state(&sci_rnc->sm, SCI_RNC_POSTING);
+ }
return SCI_SUCCESS;
+
case SCI_RNC_POSTING:
case SCI_RNC_INVALIDATING:
case SCI_RNC_RESUMING:
- if (sci_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
- return SCI_FAILURE_INVALID_STATE;
-
- sci_rnc->user_callback = cb_fn;
- sci_rnc->user_cookie = cb_p;
+ /* We are still waiting to post when a resume was
+ * requested.
+ */
+ switch (sci_rnc->destination_state) {
+ case RNC_DEST_SUSPENDED:
+ case RNC_DEST_SUSPENDED_RESUME:
+ /* Previously waiting to suspend after posting.
+ * Now continue onto resumption.
+ */
+ sci_remote_node_context_setup_to_resume(
+ sci_rnc, cb_fn, cb_p,
+ RNC_DEST_SUSPENDED_RESUME);
+ break;
+ default:
+ sci_remote_node_context_setup_to_resume(
+ sci_rnc, cb_fn, cb_p,
+ RNC_DEST_READY);
+ break;
+ }
return SCI_SUCCESS;
- case SCI_RNC_TX_SUSPENDED: {
- struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
- struct domain_device *dev = idev->domain_dev;
-
- sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p);
-
- /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */
- if (dev->dev_type == SAS_END_DEV || dev_is_expander(dev))
- sci_change_state(&sci_rnc->sm, SCI_RNC_RESUMING);
- else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
- if (idev->is_direct_attached) {
- /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */
- sci_change_state(&sci_rnc->sm, SCI_RNC_RESUMING);
- } else {
- sci_change_state(&sci_rnc->sm, SCI_RNC_INVALIDATING);
+
+ case SCI_RNC_TX_SUSPENDED:
+ case SCI_RNC_TX_RX_SUSPENDED:
+ {
+ struct domain_device *dev = idev->domain_dev;
+ /* If this is an expander attached SATA device we must
+ * invalidate and repost the RNC since this is the only
+ * way to clear the TCi to NCQ tag mapping table for
+ * the RNi. All other device types we can just resume.
+ */
+ sci_remote_node_context_setup_to_resume(
+ sci_rnc, cb_fn, cb_p, RNC_DEST_READY);
+
+ if (!test_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags)) {
+ if ((dev_is_sata(dev) && dev->parent) ||
+ (sci_rnc->destination_state == RNC_DEST_FINAL))
+ sci_change_state(&sci_rnc->sm,
+ SCI_RNC_INVALIDATING);
+ else
+ sci_change_state(&sci_rnc->sm,
+ SCI_RNC_RESUMING);
}
- } else
- return SCI_FAILURE;
+ }
return SCI_SUCCESS;
- }
- case SCI_RNC_TX_RX_SUSPENDED:
- sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p);
- sci_change_state(&sci_rnc->sm, SCI_RNC_RESUMING);
- return SCI_FAILURE_INVALID_STATE;
+
case SCI_RNC_AWAIT_SUSPENSION:
- sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p);
+ sci_remote_node_context_setup_to_resume(
+ sci_rnc, cb_fn, cb_p, RNC_DEST_SUSPENDED_RESUME);
return SCI_SUCCESS;
default:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
- "%s: invalid state %d\n", __func__, state);
+ "%s: invalid state %s\n", __func__,
+ rnc_state_name(state));
return SCI_FAILURE_INVALID_STATE;
}
}
@@ -590,35 +759,51 @@ enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context
case SCI_RNC_TX_RX_SUSPENDED:
case SCI_RNC_AWAIT_SUSPENSION:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
- "%s: invalid state %d\n", __func__, state);
+ "%s: invalid state %s\n", __func__,
+ rnc_state_name(state));
return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
default:
- break;
+ dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)),
+ "%s: invalid state %s\n", __func__,
+ rnc_state_name(state));
+ return SCI_FAILURE_INVALID_STATE;
}
- dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)),
- "%s: requested to start IO while still resuming, %d\n",
- __func__, state);
- return SCI_FAILURE_INVALID_STATE;
}
-enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_context *sci_rnc,
- struct isci_request *ireq)
+enum sci_status sci_remote_node_context_start_task(
+ struct sci_remote_node_context *sci_rnc,
+ struct isci_request *ireq,
+ scics_sds_remote_node_context_callback cb_fn,
+ void *cb_p)
+{
+ enum sci_status status = sci_remote_node_context_resume(sci_rnc,
+ cb_fn, cb_p);
+ if (status != SCI_SUCCESS)
+ dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
+ "%s: resume failed: %d\n", __func__, status);
+ return status;
+}
+
+int sci_remote_node_context_is_safe_to_abort(
+ struct sci_remote_node_context *sci_rnc)
{
enum scis_sds_remote_node_context_states state;
state = sci_rnc->sm.current_state_id;
switch (state) {
+ case SCI_RNC_INVALIDATING:
+ case SCI_RNC_TX_RX_SUSPENDED:
+ return 1;
+ case SCI_RNC_POSTING:
case SCI_RNC_RESUMING:
case SCI_RNC_READY:
- case SCI_RNC_AWAIT_SUSPENSION:
- return SCI_SUCCESS;
case SCI_RNC_TX_SUSPENDED:
- case SCI_RNC_TX_RX_SUSPENDED:
- sci_remote_node_context_resume(sci_rnc, NULL, NULL);
- return SCI_SUCCESS;
+ case SCI_RNC_AWAIT_SUSPENSION:
+ case SCI_RNC_INITIAL:
+ return 0;
default:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
"%s: invalid state %d\n", __func__, state);
- return SCI_FAILURE_INVALID_STATE;
+ return 0;
}
}
diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h
index a241e0f4c865..a703b9ce0c2c 100644
--- a/drivers/scsi/isci/remote_node_context.h
+++ b/drivers/scsi/isci/remote_node_context.h
@@ -75,8 +75,13 @@
*/
#define SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 0x0FFF
-#define SCU_HARDWARE_SUSPENSION (0)
-#define SCI_SOFTWARE_SUSPENSION (1)
+enum sci_remote_node_suspension_reasons {
+ SCI_HW_SUSPEND,
+ SCI_SW_SUSPEND_NORMAL,
+ SCI_SW_SUSPEND_LINKHANG_DETECT
+};
+#define SCI_SOFTWARE_SUSPEND_CMD SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX
+#define SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT SCU_EVENT_TL_RNC_SUSPEND_TX_RX
struct isci_request;
struct isci_remote_device;
@@ -137,9 +142,13 @@ const char *rnc_state_name(enum scis_sds_remote_node_context_states state);
* node context.
*/
enum sci_remote_node_context_destination_state {
- SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED,
- SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY,
- SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL
+ RNC_DEST_UNSPECIFIED,
+ RNC_DEST_READY,
+ RNC_DEST_FINAL,
+ RNC_DEST_SUSPENDED, /* Set when suspend during post/invalidate */
+ RNC_DEST_SUSPENDED_RESUME /* Set when a resume was done during posting
+ * or invalidating and already suspending.
+ */
};
/**
@@ -156,10 +165,12 @@ struct sci_remote_node_context {
u16 remote_node_index;
/**
- * This field is the recored suspension code or the reason for the remote node
+ * This field is the recored suspension type of the remote node
* context suspension.
*/
- u32 suspension_code;
+ u32 suspend_type;
+ enum sci_remote_node_suspension_reasons suspend_reason;
+ u32 suspend_count;
/**
* This field is true if the remote node context is resuming from its current
@@ -193,6 +204,8 @@ void sci_remote_node_context_construct(struct sci_remote_node_context *rnc,
bool sci_remote_node_context_is_ready(
struct sci_remote_node_context *sci_rnc);
+bool sci_remote_node_context_is_suspended(struct sci_remote_node_context *sci_rnc);
+
enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_context *sci_rnc,
u32 event_code);
enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context *sci_rnc,
@@ -200,14 +213,24 @@ enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context
void *callback_parameter);
enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *sci_rnc,
u32 suspend_type,
- scics_sds_remote_node_context_callback cb_fn,
- void *cb_p);
+ u32 suspension_code);
enum sci_status sci_remote_node_context_resume(struct sci_remote_node_context *sci_rnc,
scics_sds_remote_node_context_callback cb_fn,
void *cb_p);
enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_context *sci_rnc,
- struct isci_request *ireq);
+ struct isci_request *ireq,
+ scics_sds_remote_node_context_callback cb_fn,
+ void *cb_p);
enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context *sci_rnc,
struct isci_request *ireq);
+int sci_remote_node_context_is_safe_to_abort(
+ struct sci_remote_node_context *sci_rnc);
+static inline bool sci_remote_node_context_is_being_destroyed(
+ struct sci_remote_node_context *sci_rnc)
+{
+ return (sci_rnc->destination_state == RNC_DEST_FINAL)
+ || ((sci_rnc->sm.current_state_id == SCI_RNC_INITIAL)
+ && (sci_rnc->destination_state == RNC_DEST_UNSPECIFIED));
+}
#endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index 2def1e3960f6..7a0431c73493 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -92,11 +92,11 @@ static dma_addr_t to_sgl_element_pair_dma(struct isci_host *ihost,
if (idx == 0) {
offset = (void *) &ireq->tc->sgl_pair_ab -
(void *) &ihost->task_context_table[0];
- return ihost->task_context_dma + offset;
+ return ihost->tc_dma + offset;
} else if (idx == 1) {
offset = (void *) &ireq->tc->sgl_pair_cd -
(void *) &ihost->task_context_table[0];
- return ihost->task_context_dma + offset;
+ return ihost->tc_dma + offset;
}
return sci_io_request_get_dma_addr(ireq, &ireq->sg_table[idx - 2]);
@@ -730,7 +730,7 @@ static enum sci_status sci_io_request_construct_basic_ssp(struct isci_request *i
{
struct sas_task *task = isci_request_access_task(ireq);
- ireq->protocol = SCIC_SSP_PROTOCOL;
+ ireq->protocol = SAS_PROTOCOL_SSP;
scu_ssp_io_request_construct_task_context(ireq,
task->data_dir,
@@ -763,7 +763,7 @@ static enum sci_status sci_io_request_construct_basic_sata(struct isci_request *
bool copy = false;
struct sas_task *task = isci_request_access_task(ireq);
- ireq->protocol = SCIC_STP_PROTOCOL;
+ ireq->protocol = SAS_PROTOCOL_STP;
copy = (task->data_dir == DMA_NONE) ? false : true;
@@ -863,6 +863,8 @@ sci_io_request_terminate(struct isci_request *ireq)
switch (state) {
case SCI_REQ_CONSTRUCTED:
+ /* Set to make sure no HW terminate posting is done: */
+ set_bit(IREQ_TC_ABORT_POSTED, &ireq->flags);
ireq->scu_status = SCU_TASK_DONE_TASK_ABORT;
ireq->sci_status = SCI_FAILURE_IO_TERMINATED;
sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
@@ -883,8 +885,7 @@ sci_io_request_terminate(struct isci_request *ireq)
case SCI_REQ_ATAPI_WAIT_PIO_SETUP:
case SCI_REQ_ATAPI_WAIT_D2H:
case SCI_REQ_ATAPI_WAIT_TC_COMP:
- sci_change_state(&ireq->sm, SCI_REQ_ABORTING);
- return SCI_SUCCESS;
+ /* Fall through and change state to ABORTING... */
case SCI_REQ_TASK_WAIT_TC_RESP:
/* The task frame was already confirmed to have been
* sent by the SCU HW. Since the state machine is
@@ -893,20 +894,21 @@ sci_io_request_terminate(struct isci_request *ireq)
* and don't wait for the task response.
*/
sci_change_state(&ireq->sm, SCI_REQ_ABORTING);
- sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
- return SCI_SUCCESS;
+ /* Fall through and handle like ABORTING... */
case SCI_REQ_ABORTING:
- /* If a request has a termination requested twice, return
- * a failure indication, since HW confirmation of the first
- * abort is still outstanding.
+ if (!isci_remote_device_is_safe_to_abort(ireq->target_device))
+ set_bit(IREQ_PENDING_ABORT, &ireq->flags);
+ else
+ clear_bit(IREQ_PENDING_ABORT, &ireq->flags);
+ /* If the request is only waiting on the remote device
+ * suspension, return SUCCESS so the caller will wait too.
*/
+ return SCI_SUCCESS;
case SCI_REQ_COMPLETED:
default:
dev_warn(&ireq->owning_controller->pdev->dev,
"%s: SCIC IO Request requested to abort while in wrong "
- "state %d\n",
- __func__,
- ireq->sm.current_state_id);
+ "state %d\n", __func__, ireq->sm.current_state_id);
break;
}
@@ -1070,7 +1072,7 @@ request_started_state_tc_event(struct isci_request *ireq,
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_SDBFIS):
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR):
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR):
- if (ireq->protocol == SCIC_STP_PROTOCOL) {
+ if (ireq->protocol == SAS_PROTOCOL_STP) {
ireq->scu_status = SCU_GET_COMPLETION_TL_STATUS(completion_code) >>
SCU_COMPLETION_TL_STATUS_SHIFT;
ireq->sci_status = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
@@ -2117,7 +2119,7 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq
*/
if (ireq->stp.rsp.fis_type == FIS_REGD2H) {
sci_remote_device_suspend(ireq->target_device,
- SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)));
+ SCI_SW_SUSPEND_NORMAL);
ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE;
ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
@@ -2138,13 +2140,6 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq
/* TODO We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR
* - this comes only for B0
*/
- case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN):
- case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
- case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR):
- case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR):
- sci_remote_device_suspend(ireq->target_device,
- SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)));
- /* Fall through to the default case */
default:
/* All other completion status cause the IO to be complete. */
ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code);
@@ -2262,15 +2257,151 @@ static enum sci_status atapi_data_tc_completion_handler(struct isci_request *ire
return status;
}
+static int sci_request_smp_completion_status_is_tx_suspend(
+ unsigned int completion_status)
+{
+ switch (completion_status) {
+ case SCU_TASK_OPEN_REJECT_WRONG_DESTINATION:
+ case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1:
+ case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2:
+ case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3:
+ case SCU_TASK_OPEN_REJECT_BAD_DESTINATION:
+ case SCU_TASK_OPEN_REJECT_ZONE_VIOLATION:
+ return 1;
+ }
+ return 0;
+}
+
+static int sci_request_smp_completion_status_is_tx_rx_suspend(
+ unsigned int completion_status)
+{
+ return 0; /* There are no Tx/Rx SMP suspend conditions. */
+}
+
+static int sci_request_ssp_completion_status_is_tx_suspend(
+ unsigned int completion_status)
+{
+ switch (completion_status) {
+ case SCU_TASK_DONE_TX_RAW_CMD_ERR:
+ case SCU_TASK_DONE_LF_ERR:
+ case SCU_TASK_OPEN_REJECT_WRONG_DESTINATION:
+ case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1:
+ case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2:
+ case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3:
+ case SCU_TASK_OPEN_REJECT_BAD_DESTINATION:
+ case SCU_TASK_OPEN_REJECT_ZONE_VIOLATION:
+ case SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY:
+ case SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED:
+ case SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED:
+ return 1;
+ }
+ return 0;
+}
+
+static int sci_request_ssp_completion_status_is_tx_rx_suspend(
+ unsigned int completion_status)
+{
+ return 0; /* There are no Tx/Rx SSP suspend conditions. */
+}
+
+static int sci_request_stpsata_completion_status_is_tx_suspend(
+ unsigned int completion_status)
+{
+ switch (completion_status) {
+ case SCU_TASK_DONE_TX_RAW_CMD_ERR:
+ case SCU_TASK_DONE_LL_R_ERR:
+ case SCU_TASK_DONE_LL_PERR:
+ case SCU_TASK_DONE_REG_ERR:
+ case SCU_TASK_DONE_SDB_ERR:
+ case SCU_TASK_OPEN_REJECT_WRONG_DESTINATION:
+ case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1:
+ case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2:
+ case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3:
+ case SCU_TASK_OPEN_REJECT_BAD_DESTINATION:
+ case SCU_TASK_OPEN_REJECT_ZONE_VIOLATION:
+ case SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY:
+ case SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED:
+ case SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED:
+ return 1;
+ }
+ return 0;
+}
+
+
+static int sci_request_stpsata_completion_status_is_tx_rx_suspend(
+ unsigned int completion_status)
+{
+ switch (completion_status) {
+ case SCU_TASK_DONE_LF_ERR:
+ case SCU_TASK_DONE_LL_SY_TERM:
+ case SCU_TASK_DONE_LL_LF_TERM:
+ case SCU_TASK_DONE_BREAK_RCVD:
+ case SCU_TASK_DONE_INV_FIS_LEN:
+ case SCU_TASK_DONE_UNEXP_FIS:
+ case SCU_TASK_DONE_UNEXP_SDBFIS:
+ case SCU_TASK_DONE_MAX_PLD_ERR:
+ return 1;
+ }
+ return 0;
+}
+
+static void sci_request_handle_suspending_completions(
+ struct isci_request *ireq,
+ u32 completion_code)
+{
+ int is_tx = 0;
+ int is_tx_rx = 0;
+
+ switch (ireq->protocol) {
+ case SAS_PROTOCOL_SMP:
+ is_tx = sci_request_smp_completion_status_is_tx_suspend(
+ completion_code);
+ is_tx_rx = sci_request_smp_completion_status_is_tx_rx_suspend(
+ completion_code);
+ break;
+ case SAS_PROTOCOL_SSP:
+ is_tx = sci_request_ssp_completion_status_is_tx_suspend(
+ completion_code);
+ is_tx_rx = sci_request_ssp_completion_status_is_tx_rx_suspend(
+ completion_code);
+ break;
+ case SAS_PROTOCOL_STP:
+ is_tx = sci_request_stpsata_completion_status_is_tx_suspend(
+ completion_code);
+ is_tx_rx =
+ sci_request_stpsata_completion_status_is_tx_rx_suspend(
+ completion_code);
+ break;
+ default:
+ dev_warn(&ireq->isci_host->pdev->dev,
+ "%s: request %p has no valid protocol\n",
+ __func__, ireq);
+ break;
+ }
+ if (is_tx || is_tx_rx) {
+ BUG_ON(is_tx && is_tx_rx);
+
+ sci_remote_node_context_suspend(
+ &ireq->target_device->rnc,
+ SCI_HW_SUSPEND,
+ (is_tx_rx) ? SCU_EVENT_TL_RNC_SUSPEND_TX_RX
+ : SCU_EVENT_TL_RNC_SUSPEND_TX);
+ }
+}
+
enum sci_status
sci_io_request_tc_completion(struct isci_request *ireq,
- u32 completion_code)
+ u32 completion_code)
{
enum sci_base_request_states state;
struct isci_host *ihost = ireq->owning_controller;
state = ireq->sm.current_state_id;
+ /* Decode those completions that signal upcoming suspension events. */
+ sci_request_handle_suspending_completions(
+ ireq, SCU_GET_COMPLETION_TL_STATUS(completion_code));
+
switch (state) {
case SCI_REQ_STARTED:
return request_started_state_tc_event(ireq, completion_code);
@@ -2362,9 +2493,6 @@ static void isci_request_process_response_iu(
* @request: This parameter is the completed isci_request object.
* @response_ptr: This parameter specifies the service response for the I/O.
* @status_ptr: This parameter specifies the exec status for the I/O.
- * @complete_to_host_ptr: This parameter specifies the action to be taken by
- * the LLDD with respect to completing this request or forcing an abort
- * condition on the I/O.
* @open_rej_reason: This parameter specifies the encoded reason for the
* abandon-class reject.
*
@@ -2375,14 +2503,12 @@ static void isci_request_set_open_reject_status(
struct sas_task *task,
enum service_response *response_ptr,
enum exec_status *status_ptr,
- enum isci_completion_selection *complete_to_host_ptr,
enum sas_open_rej_reason open_rej_reason)
{
/* Task in the target is done. */
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
*response_ptr = SAS_TASK_UNDELIVERED;
*status_ptr = SAS_OPEN_REJECT;
- *complete_to_host_ptr = isci_perform_normal_io_completion;
task->task_status.open_rej_reason = open_rej_reason;
}
@@ -2392,9 +2518,6 @@ static void isci_request_set_open_reject_status(
* @request: This parameter is the completed isci_request object.
* @response_ptr: This parameter specifies the service response for the I/O.
* @status_ptr: This parameter specifies the exec status for the I/O.
- * @complete_to_host_ptr: This parameter specifies the action to be taken by
- * the LLDD with respect to completing this request or forcing an abort
- * condition on the I/O.
*
* none.
*/
@@ -2403,8 +2526,7 @@ static void isci_request_handle_controller_specific_errors(
struct isci_request *request,
struct sas_task *task,
enum service_response *response_ptr,
- enum exec_status *status_ptr,
- enum isci_completion_selection *complete_to_host_ptr)
+ enum exec_status *status_ptr)
{
unsigned int cstatus;
@@ -2445,9 +2567,6 @@ static void isci_request_handle_controller_specific_errors(
*status_ptr = SAS_ABORTED_TASK;
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
-
- *complete_to_host_ptr =
- isci_perform_normal_io_completion;
} else {
/* Task in the target is not done. */
*response_ptr = SAS_TASK_UNDELIVERED;
@@ -2458,9 +2577,6 @@ static void isci_request_handle_controller_specific_errors(
*status_ptr = SAM_STAT_TASK_ABORTED;
clear_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
-
- *complete_to_host_ptr =
- isci_perform_error_io_completion;
}
break;
@@ -2489,8 +2605,6 @@ static void isci_request_handle_controller_specific_errors(
*status_ptr = SAS_ABORTED_TASK;
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
-
- *complete_to_host_ptr = isci_perform_normal_io_completion;
break;
@@ -2501,7 +2615,7 @@ static void isci_request_handle_controller_specific_errors(
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_WRONG_DEST);
+ SAS_OREJ_WRONG_DEST);
break;
case SCU_TASK_OPEN_REJECT_ZONE_VIOLATION:
@@ -2511,56 +2625,56 @@ static void isci_request_handle_controller_specific_errors(
*/
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_RESV_AB0);
+ SAS_OREJ_RESV_AB0);
break;
case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_RESV_AB1);
+ SAS_OREJ_RESV_AB1);
break;
case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_RESV_AB2);
+ SAS_OREJ_RESV_AB2);
break;
case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_RESV_AB3);
+ SAS_OREJ_RESV_AB3);
break;
case SCU_TASK_OPEN_REJECT_BAD_DESTINATION:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_BAD_DEST);
+ SAS_OREJ_BAD_DEST);
break;
case SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_STP_NORES);
+ SAS_OREJ_STP_NORES);
break;
case SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_EPROTO);
+ SAS_OREJ_EPROTO);
break;
case SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_CONN_RATE);
+ SAS_OREJ_CONN_RATE);
break;
case SCU_TASK_DONE_LL_R_ERR:
@@ -2592,95 +2706,12 @@ static void isci_request_handle_controller_specific_errors(
*response_ptr = SAS_TASK_UNDELIVERED;
*status_ptr = SAM_STAT_TASK_ABORTED;
- if (task->task_proto == SAS_PROTOCOL_SMP) {
+ if (task->task_proto == SAS_PROTOCOL_SMP)
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
-
- *complete_to_host_ptr = isci_perform_normal_io_completion;
- } else {
+ else
clear_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
-
- *complete_to_host_ptr = isci_perform_error_io_completion;
- }
- break;
- }
-}
-
-/**
- * isci_task_save_for_upper_layer_completion() - This function saves the
- * request for later completion to the upper layer driver.
- * @host: This parameter is a pointer to the host on which the the request
- * should be queued (either as an error or success).
- * @request: This parameter is the completed request.
- * @response: This parameter is the response code for the completed task.
- * @status: This parameter is the status code for the completed task.
- *
- * none.
- */
-static void isci_task_save_for_upper_layer_completion(
- struct isci_host *host,
- struct isci_request *request,
- enum service_response response,
- enum exec_status status,
- enum isci_completion_selection task_notification_selection)
-{
- struct sas_task *task = isci_request_access_task(request);
-
- task_notification_selection
- = isci_task_set_completion_status(task, response, status,
- task_notification_selection);
-
- /* Tasks aborted specifically by a call to the lldd_abort_task
- * function should not be completed to the host in the regular path.
- */
- switch (task_notification_selection) {
-
- case isci_perform_normal_io_completion:
- /* Normal notification (task_done) */
-
- /* Add to the completed list. */
- list_add(&request->completed_node,
- &host->requests_to_complete);
-
- /* Take the request off the device's pending request list. */
- list_del_init(&request->dev_node);
- break;
-
- case isci_perform_aborted_io_completion:
- /* No notification to libsas because this request is
- * already in the abort path.
- */
- /* Wake up whatever process was waiting for this
- * request to complete.
- */
- WARN_ON(request->io_request_completion == NULL);
-
- if (request->io_request_completion != NULL) {
-
- /* Signal whoever is waiting that this
- * request is complete.
- */
- complete(request->io_request_completion);
- }
- break;
-
- case isci_perform_error_io_completion:
- /* Use sas_task_abort */
- /* Add to the aborted list. */
- list_add(&request->completed_node,
- &host->requests_to_errorback);
- break;
-
- default:
- /* Add to the error to libsas list. */
- list_add(&request->completed_node,
- &host->requests_to_errorback);
break;
}
- dev_dbg(&host->pdev->dev,
- "%s: %d - task = %p, response=%d (%d), status=%d (%d)\n",
- __func__, task_notification_selection, task,
- (task) ? task->task_status.resp : 0, response,
- (task) ? task->task_status.stat : 0, status);
}
static void isci_process_stp_response(struct sas_task *task, struct dev_to_host_fis *fis)
@@ -2715,295 +2746,164 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
struct isci_remote_device *idev = request->target_device;
enum service_response response = SAS_TASK_UNDELIVERED;
enum exec_status status = SAS_ABORTED_TASK;
- enum isci_request_status request_status;
- enum isci_completion_selection complete_to_host
- = isci_perform_normal_io_completion;
dev_dbg(&ihost->pdev->dev,
- "%s: request = %p, task = %p,\n"
+ "%s: request = %p, task = %p, "
"task->data_dir = %d completion_status = 0x%x\n",
- __func__,
- request,
- task,
- task->data_dir,
- completion_status);
+ __func__, request, task, task->data_dir, completion_status);
- spin_lock(&request->state_lock);
- request_status = request->status;
+ /* The request is done from an SCU HW perspective. */
- /* Decode the request status. Note that if the request has been
- * aborted by a task management function, we don't care
- * what the status is.
- */
- switch (request_status) {
-
- case aborted:
- /* "aborted" indicates that the request was aborted by a task
- * management function, since once a task management request is
- * perfomed by the device, the request only completes because
- * of the subsequent driver terminate.
- *
- * Aborted also means an external thread is explicitly managing
- * this request, so that we do not complete it up the stack.
- *
- * The target is still there (since the TMF was successful).
- */
- set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
- response = SAS_TASK_COMPLETE;
+ /* This is an active request being completed from the core. */
+ switch (completion_status) {
- /* See if the device has been/is being stopped. Note
- * that we ignore the quiesce state, since we are
- * concerned about the actual device state.
- */
- if (!idev)
- status = SAS_DEVICE_UNKNOWN;
- else
- status = SAS_ABORTED_TASK;
+ case SCI_IO_FAILURE_RESPONSE_VALID:
+ dev_dbg(&ihost->pdev->dev,
+ "%s: SCI_IO_FAILURE_RESPONSE_VALID (%p/%p)\n",
+ __func__, request, task);
+
+ if (sas_protocol_ata(task->task_proto)) {
+ isci_process_stp_response(task, &request->stp.rsp);
+ } else if (SAS_PROTOCOL_SSP == task->task_proto) {
+
+ /* crack the iu response buffer. */
+ resp_iu = &request->ssp.rsp;
+ isci_request_process_response_iu(task, resp_iu,
+ &ihost->pdev->dev);
+
+ } else if (SAS_PROTOCOL_SMP == task->task_proto) {
+
+ dev_err(&ihost->pdev->dev,
+ "%s: SCI_IO_FAILURE_RESPONSE_VALID: "
+ "SAS_PROTOCOL_SMP protocol\n",
+ __func__);
- complete_to_host = isci_perform_aborted_io_completion;
- /* This was an aborted request. */
+ } else
+ dev_err(&ihost->pdev->dev,
+ "%s: unknown protocol\n", __func__);
- spin_unlock(&request->state_lock);
+ /* use the task status set in the task struct by the
+ * isci_request_process_response_iu call.
+ */
+ set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
+ response = task->task_status.resp;
+ status = task->task_status.stat;
break;
- case aborting:
- /* aborting means that the task management function tried and
- * failed to abort the request. We need to note the request
- * as SAS_TASK_UNDELIVERED, so that the scsi mid layer marks the
- * target as down.
- *
- * Aborting also means an external thread is explicitly managing
- * this request, so that we do not complete it up the stack.
- */
+ case SCI_IO_SUCCESS:
+ case SCI_IO_SUCCESS_IO_DONE_EARLY:
+
+ response = SAS_TASK_COMPLETE;
+ status = SAM_STAT_GOOD;
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
- response = SAS_TASK_UNDELIVERED;
- if (!idev)
- /* The device has been /is being stopped. Note that
- * we ignore the quiesce state, since we are
- * concerned about the actual device state.
- */
- status = SAS_DEVICE_UNKNOWN;
- else
- status = SAS_PHY_DOWN;
+ if (completion_status == SCI_IO_SUCCESS_IO_DONE_EARLY) {
- complete_to_host = isci_perform_aborted_io_completion;
+ /* This was an SSP / STP / SATA transfer.
+ * There is a possibility that less data than
+ * the maximum was transferred.
+ */
+ u32 transferred_length = sci_req_tx_bytes(request);
- /* This was an aborted request. */
+ task->task_status.residual
+ = task->total_xfer_len - transferred_length;
+
+ /* If there were residual bytes, call this an
+ * underrun.
+ */
+ if (task->task_status.residual != 0)
+ status = SAS_DATA_UNDERRUN;
- spin_unlock(&request->state_lock);
+ dev_dbg(&ihost->pdev->dev,
+ "%s: SCI_IO_SUCCESS_IO_DONE_EARLY %d\n",
+ __func__, status);
+
+ } else
+ dev_dbg(&ihost->pdev->dev, "%s: SCI_IO_SUCCESS\n",
+ __func__);
break;
- case terminating:
+ case SCI_IO_FAILURE_TERMINATED:
- /* This was an terminated request. This happens when
- * the I/O is being terminated because of an action on
- * the device (reset, tear down, etc.), and the I/O needs
- * to be completed up the stack.
- */
+ dev_dbg(&ihost->pdev->dev,
+ "%s: SCI_IO_FAILURE_TERMINATED (%p/%p)\n",
+ __func__, request, task);
+
+ /* The request was terminated explicitly. */
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
response = SAS_TASK_UNDELIVERED;
/* See if the device has been/is being stopped. Note
- * that we ignore the quiesce state, since we are
- * concerned about the actual device state.
- */
+ * that we ignore the quiesce state, since we are
+ * concerned about the actual device state.
+ */
if (!idev)
status = SAS_DEVICE_UNKNOWN;
else
status = SAS_ABORTED_TASK;
-
- complete_to_host = isci_perform_aborted_io_completion;
-
- /* This was a terminated request. */
-
- spin_unlock(&request->state_lock);
break;
- case dead:
- /* This was a terminated request that timed-out during the
- * termination process. There is no task to complete to
- * libsas.
- */
- complete_to_host = isci_perform_normal_io_completion;
- spin_unlock(&request->state_lock);
- break;
+ case SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR:
- default:
-
- /* The request is done from an SCU HW perspective. */
- request->status = completed;
-
- spin_unlock(&request->state_lock);
-
- /* This is an active request being completed from the core. */
- switch (completion_status) {
-
- case SCI_IO_FAILURE_RESPONSE_VALID:
- dev_dbg(&ihost->pdev->dev,
- "%s: SCI_IO_FAILURE_RESPONSE_VALID (%p/%p)\n",
- __func__,
- request,
- task);
-
- if (sas_protocol_ata(task->task_proto)) {
- isci_process_stp_response(task, &request->stp.rsp);
- } else if (SAS_PROTOCOL_SSP == task->task_proto) {
-
- /* crack the iu response buffer. */
- resp_iu = &request->ssp.rsp;
- isci_request_process_response_iu(task, resp_iu,
- &ihost->pdev->dev);
-
- } else if (SAS_PROTOCOL_SMP == task->task_proto) {
-
- dev_err(&ihost->pdev->dev,
- "%s: SCI_IO_FAILURE_RESPONSE_VALID: "
- "SAS_PROTOCOL_SMP protocol\n",
- __func__);
-
- } else
- dev_err(&ihost->pdev->dev,
- "%s: unknown protocol\n", __func__);
-
- /* use the task status set in the task struct by the
- * isci_request_process_response_iu call.
- */
- set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
- response = task->task_status.resp;
- status = task->task_status.stat;
- break;
+ isci_request_handle_controller_specific_errors(idev, request,
+ task, &response,
+ &status);
+ break;
- case SCI_IO_SUCCESS:
- case SCI_IO_SUCCESS_IO_DONE_EARLY:
+ case SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED:
+ /* This is a special case, in that the I/O completion
+ * is telling us that the device needs a reset.
+ * In order for the device reset condition to be
+ * noticed, the I/O has to be handled in the error
+ * handler. Set the reset flag and cause the
+ * SCSI error thread to be scheduled.
+ */
+ spin_lock_irqsave(&task->task_state_lock, task_flags);
+ task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
+ spin_unlock_irqrestore(&task->task_state_lock, task_flags);
- response = SAS_TASK_COMPLETE;
- status = SAM_STAT_GOOD;
- set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
+ /* Fail the I/O. */
+ response = SAS_TASK_UNDELIVERED;
+ status = SAM_STAT_TASK_ABORTED;
- if (completion_status == SCI_IO_SUCCESS_IO_DONE_EARLY) {
+ clear_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
+ break;
- /* This was an SSP / STP / SATA transfer.
- * There is a possibility that less data than
- * the maximum was transferred.
- */
- u32 transferred_length = sci_req_tx_bytes(request);
+ case SCI_FAILURE_RETRY_REQUIRED:
- task->task_status.residual
- = task->total_xfer_len - transferred_length;
+ /* Fail the I/O so it can be retried. */
+ response = SAS_TASK_UNDELIVERED;
+ if (!idev)
+ status = SAS_DEVICE_UNKNOWN;
+ else
+ status = SAS_ABORTED_TASK;
- /* If there were residual bytes, call this an
- * underrun.
- */
- if (task->task_status.residual != 0)
- status = SAS_DATA_UNDERRUN;
+ set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
+ break;
- dev_dbg(&ihost->pdev->dev,
- "%s: SCI_IO_SUCCESS_IO_DONE_EARLY %d\n",
- __func__,
- status);
- } else
- dev_dbg(&ihost->pdev->dev,
- "%s: SCI_IO_SUCCESS\n",
- __func__);
+ default:
+ /* Catch any otherwise unhandled error codes here. */
+ dev_dbg(&ihost->pdev->dev,
+ "%s: invalid completion code: 0x%x - "
+ "isci_request = %p\n",
+ __func__, completion_status, request);
- break;
+ response = SAS_TASK_UNDELIVERED;
- case SCI_IO_FAILURE_TERMINATED:
- dev_dbg(&ihost->pdev->dev,
- "%s: SCI_IO_FAILURE_TERMINATED (%p/%p)\n",
- __func__,
- request,
- task);
+ /* See if the device has been/is being stopped. Note
+ * that we ignore the quiesce state, since we are
+ * concerned about the actual device state.
+ */
+ if (!idev)
+ status = SAS_DEVICE_UNKNOWN;
+ else
+ status = SAS_ABORTED_TASK;
- /* The request was terminated explicitly. No handling
- * is needed in the SCSI error handler path.
- */
+ if (SAS_PROTOCOL_SMP == task->task_proto)
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
- response = SAS_TASK_UNDELIVERED;
-
- /* See if the device has been/is being stopped. Note
- * that we ignore the quiesce state, since we are
- * concerned about the actual device state.
- */
- if (!idev)
- status = SAS_DEVICE_UNKNOWN;
- else
- status = SAS_ABORTED_TASK;
-
- complete_to_host = isci_perform_normal_io_completion;
- break;
-
- case SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR:
-
- isci_request_handle_controller_specific_errors(
- idev, request, task, &response, &status,
- &complete_to_host);
-
- break;
-
- case SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED:
- /* This is a special case, in that the I/O completion
- * is telling us that the device needs a reset.
- * In order for the device reset condition to be
- * noticed, the I/O has to be handled in the error
- * handler. Set the reset flag and cause the
- * SCSI error thread to be scheduled.
- */
- spin_lock_irqsave(&task->task_state_lock, task_flags);
- task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
- spin_unlock_irqrestore(&task->task_state_lock, task_flags);
-
- /* Fail the I/O. */
- response = SAS_TASK_UNDELIVERED;
- status = SAM_STAT_TASK_ABORTED;
-
- complete_to_host = isci_perform_error_io_completion;
+ else
clear_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
- break;
-
- case SCI_FAILURE_RETRY_REQUIRED:
-
- /* Fail the I/O so it can be retried. */
- response = SAS_TASK_UNDELIVERED;
- if (!idev)
- status = SAS_DEVICE_UNKNOWN;
- else
- status = SAS_ABORTED_TASK;
-
- complete_to_host = isci_perform_normal_io_completion;
- set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
- break;
-
-
- default:
- /* Catch any otherwise unhandled error codes here. */
- dev_dbg(&ihost->pdev->dev,
- "%s: invalid completion code: 0x%x - "
- "isci_request = %p\n",
- __func__, completion_status, request);
-
- response = SAS_TASK_UNDELIVERED;
-
- /* See if the device has been/is being stopped. Note
- * that we ignore the quiesce state, since we are
- * concerned about the actual device state.
- */
- if (!idev)
- status = SAS_DEVICE_UNKNOWN;
- else
- status = SAS_ABORTED_TASK;
-
- if (SAS_PROTOCOL_SMP == task->task_proto) {
- set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
- complete_to_host = isci_perform_normal_io_completion;
- } else {
- clear_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
- complete_to_host = isci_perform_error_io_completion;
- }
- break;
- }
break;
}
@@ -3038,10 +2938,18 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
break;
}
- /* Put the completed request on the correct list */
- isci_task_save_for_upper_layer_completion(ihost, request, response,
- status, complete_to_host
- );
+ spin_lock_irqsave(&task->task_state_lock, task_flags);
+
+ task->task_status.resp = response;
+ task->task_status.stat = status;
+
+ if (test_bit(IREQ_COMPLETE_IN_TARGET, &request->flags)) {
+ /* Normal notification (task_done) */
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
+ task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
+ SAS_TASK_STATE_PENDING);
+ }
+ spin_unlock_irqrestore(&task->task_state_lock, task_flags);
/* complete the io request to the core. */
sci_controller_complete_io(ihost, request->target_device, request);
@@ -3051,6 +2959,8 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
* task to recognize the already completed case.
*/
set_bit(IREQ_TERMINATED, &request->flags);
+
+ ireq_done(ihost, request, task);
}
static void sci_request_started_state_enter(struct sci_base_state_machine *sm)
@@ -3169,7 +3079,7 @@ sci_general_request_construct(struct isci_host *ihost,
sci_init_sm(&ireq->sm, sci_request_state_table, SCI_REQ_INIT);
ireq->target_device = idev;
- ireq->protocol = SCIC_NO_PROTOCOL;
+ ireq->protocol = SAS_PROTOCOL_NONE;
ireq->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX;
ireq->sci_status = SCI_SUCCESS;
@@ -3193,7 +3103,7 @@ sci_io_request_construct(struct isci_host *ihost,
if (dev->dev_type == SAS_END_DEV)
/* pass */;
- else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP))
+ else if (dev_is_sata(dev))
memset(&ireq->stp.cmd, 0, sizeof(ireq->stp.cmd));
else if (dev_is_expander(dev))
/* pass */;
@@ -3215,10 +3125,15 @@ enum sci_status sci_task_request_construct(struct isci_host *ihost,
/* Build the common part of the request */
sci_general_request_construct(ihost, idev, ireq);
- if (dev->dev_type == SAS_END_DEV ||
- dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
+ if (dev->dev_type == SAS_END_DEV || dev_is_sata(dev)) {
set_bit(IREQ_TMF, &ireq->flags);
memset(ireq->tc, 0, sizeof(struct scu_task_context));
+
+ /* Set the protocol indicator. */
+ if (dev_is_sata(dev))
+ ireq->protocol = SAS_PROTOCOL_STP;
+ else
+ ireq->protocol = SAS_PROTOCOL_SSP;
} else
status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
@@ -3311,7 +3226,7 @@ sci_io_request_construct_smp(struct device *dev,
if (!dma_map_sg(dev, sg, 1, DMA_TO_DEVICE))
return SCI_FAILURE;
- ireq->protocol = SCIC_SMP_PROTOCOL;
+ ireq->protocol = SAS_PROTOCOL_SMP;
/* byte swap the smp request. */
@@ -3496,9 +3411,6 @@ static struct isci_request *isci_request_from_tag(struct isci_host *ihost, u16 t
ireq->io_request_completion = NULL;
ireq->flags = 0;
ireq->num_sg_entries = 0;
- INIT_LIST_HEAD(&ireq->completed_node);
- INIT_LIST_HEAD(&ireq->dev_node);
- isci_request_change_state(ireq, allocated);
return ireq;
}
@@ -3582,26 +3494,15 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide
spin_unlock_irqrestore(&ihost->scic_lock, flags);
return status;
}
-
/* Either I/O started OK, or the core has signaled that
* the device needs a target reset.
- *
- * In either case, hold onto the I/O for later.
- *
- * Update it's status and add it to the list in the
- * remote device object.
*/
- list_add(&ireq->dev_node, &idev->reqs_in_process);
-
- if (status == SCI_SUCCESS) {
- isci_request_change_state(ireq, started);
- } else {
+ if (status != SCI_SUCCESS) {
/* The request did not really start in the
* hardware, so clear the request handle
* here so no terminations will be done.
*/
set_bit(IREQ_TERMINATED, &ireq->flags);
- isci_request_change_state(ireq, completed);
}
spin_unlock_irqrestore(&ihost->scic_lock, flags);
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h
index 057f2378452d..aff95317fcf4 100644
--- a/drivers/scsi/isci/request.h
+++ b/drivers/scsi/isci/request.h
@@ -61,30 +61,6 @@
#include "scu_task_context.h"
/**
- * struct isci_request_status - This enum defines the possible states of an I/O
- * request.
- *
- *
- */
-enum isci_request_status {
- unallocated = 0x00,
- allocated = 0x01,
- started = 0x02,
- completed = 0x03,
- aborting = 0x04,
- aborted = 0x05,
- terminating = 0x06,
- dead = 0x07
-};
-
-enum sci_request_protocol {
- SCIC_NO_PROTOCOL,
- SCIC_SMP_PROTOCOL,
- SCIC_SSP_PROTOCOL,
- SCIC_STP_PROTOCOL
-}; /* XXX remove me, use sas_task.{dev|task_proto} instead */;
-
-/**
* isci_stp_request - extra request infrastructure to handle pio/atapi protocol
* @pio_len - number of bytes requested at PIO setup
* @status - pio setup ending status value to tell us if we need
@@ -104,11 +80,14 @@ struct isci_stp_request {
};
struct isci_request {
- enum isci_request_status status;
#define IREQ_COMPLETE_IN_TARGET 0
#define IREQ_TERMINATED 1
#define IREQ_TMF 2
#define IREQ_ACTIVE 3
+ #define IREQ_PENDING_ABORT 4 /* Set == device was not suspended yet */
+ #define IREQ_TC_ABORT_POSTED 5
+ #define IREQ_ABORT_PATH_ACTIVE 6
+ #define IREQ_NO_AUTO_FREE_TAG 7 /* Set when being explicitly managed */
unsigned long flags;
/* XXX kill ttype and ttype_ptr, allocate full sas_task */
union ttype_ptr_union {
@@ -116,11 +95,6 @@ struct isci_request {
struct isci_tmf *tmf_task_ptr; /* When ttype==tmf_task */
} ttype_ptr;
struct isci_host *isci_host;
- /* For use in the requests_to_{complete|abort} lists: */
- struct list_head completed_node;
- /* For use in the reqs_in_process list: */
- struct list_head dev_node;
- spinlock_t state_lock;
dma_addr_t request_daddr;
dma_addr_t zero_scatter_daddr;
unsigned int num_sg_entries;
@@ -140,7 +114,7 @@ struct isci_request {
struct isci_host *owning_controller;
struct isci_remote_device *target_device;
u16 io_tag;
- enum sci_request_protocol protocol;
+ enum sas_protocol protocol;
u32 scu_status; /* hardware result */
u32 sci_status; /* upper layer disposition */
u32 post_context;
@@ -309,92 +283,6 @@ sci_io_request_get_dma_addr(struct isci_request *ireq, void *virt_addr)
return ireq->request_daddr + (requested_addr - base_addr);
}
-/**
- * isci_request_change_state() - This function sets the status of the request
- * object.
- * @request: This parameter points to the isci_request object
- * @status: This Parameter is the new status of the object
- *
- */
-static inline enum isci_request_status
-isci_request_change_state(struct isci_request *isci_request,
- enum isci_request_status status)
-{
- enum isci_request_status old_state;
- unsigned long flags;
-
- dev_dbg(&isci_request->isci_host->pdev->dev,
- "%s: isci_request = %p, state = 0x%x\n",
- __func__,
- isci_request,
- status);
-
- BUG_ON(isci_request == NULL);
-
- spin_lock_irqsave(&isci_request->state_lock, flags);
- old_state = isci_request->status;
- isci_request->status = status;
- spin_unlock_irqrestore(&isci_request->state_lock, flags);
-
- return old_state;
-}
-
-/**
- * isci_request_change_started_to_newstate() - This function sets the status of
- * the request object.
- * @request: This parameter points to the isci_request object
- * @status: This Parameter is the new status of the object
- *
- * state previous to any change.
- */
-static inline enum isci_request_status
-isci_request_change_started_to_newstate(struct isci_request *isci_request,
- struct completion *completion_ptr,
- enum isci_request_status newstate)
-{
- enum isci_request_status old_state;
- unsigned long flags;
-
- spin_lock_irqsave(&isci_request->state_lock, flags);
-
- old_state = isci_request->status;
-
- if (old_state == started || old_state == aborting) {
- BUG_ON(isci_request->io_request_completion != NULL);
-
- isci_request->io_request_completion = completion_ptr;
- isci_request->status = newstate;
- }
-
- spin_unlock_irqrestore(&isci_request->state_lock, flags);
-
- dev_dbg(&isci_request->isci_host->pdev->dev,
- "%s: isci_request = %p, old_state = 0x%x\n",
- __func__,
- isci_request,
- old_state);
-
- return old_state;
-}
-
-/**
- * isci_request_change_started_to_aborted() - This function sets the status of
- * the request object.
- * @request: This parameter points to the isci_request object
- * @completion_ptr: This parameter is saved as the kernel completion structure
- * signalled when the old request completes.
- *
- * state previous to any change.
- */
-static inline enum isci_request_status
-isci_request_change_started_to_aborted(struct isci_request *isci_request,
- struct completion *completion_ptr)
-{
- return isci_request_change_started_to_newstate(isci_request,
- completion_ptr,
- aborted);
-}
-
#define isci_request_access_task(req) ((req)->ttype_ptr.io_task_ptr)
#define isci_request_access_tmf(req) ((req)->ttype_ptr.tmf_task_ptr)
@@ -404,8 +292,6 @@ struct isci_request *isci_tmf_request_from_tag(struct isci_host *ihost,
u16 tag);
int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev,
struct sas_task *task, u16 tag);
-void isci_terminate_pending_requests(struct isci_host *ihost,
- struct isci_remote_device *idev);
enum sci_status
sci_task_request_construct(struct isci_host *ihost,
struct isci_remote_device *idev,
@@ -421,5 +307,4 @@ static inline int isci_task_is_ncq_recovery(struct sas_task *task)
task->ata_task.fis.lbal == ATA_LOG_SATA_NCQ);
}
-
#endif /* !defined(_ISCI_REQUEST_H_) */
diff --git a/drivers/scsi/isci/scu_completion_codes.h b/drivers/scsi/isci/scu_completion_codes.h
index c8b329c695f9..071cb74a211c 100644
--- a/drivers/scsi/isci/scu_completion_codes.h
+++ b/drivers/scsi/isci/scu_completion_codes.h
@@ -224,6 +224,7 @@
* 32-bit value like we want, each immediate value must be cast to a u32.
*/
#define SCU_TASK_DONE_GOOD ((u32)0x00)
+#define SCU_TASK_DONE_TX_RAW_CMD_ERR ((u32)0x08)
#define SCU_TASK_DONE_CRC_ERR ((u32)0x14)
#define SCU_TASK_DONE_CHECK_RESPONSE ((u32)0x14)
#define SCU_TASK_DONE_GEN_RESPONSE ((u32)0x15)
@@ -237,6 +238,7 @@
#define SCU_TASK_DONE_LL_LF_TERM ((u32)0x1A)
#define SCU_TASK_DONE_DATA_LEN_ERR ((u32)0x1A)
#define SCU_TASK_DONE_LL_CL_TERM ((u32)0x1B)
+#define SCU_TASK_DONE_BREAK_RCVD ((u32)0x1B)
#define SCU_TASK_DONE_LL_ABORT_ERR ((u32)0x1B)
#define SCU_TASK_DONE_SEQ_INV_TYPE ((u32)0x1C)
#define SCU_TASK_DONE_UNEXP_XR ((u32)0x1C)
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index 374254ede9d4..6bc74eb012c9 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -78,54 +78,25 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task,
enum exec_status status)
{
- enum isci_completion_selection disposition;
+ unsigned long flags;
- disposition = isci_perform_normal_io_completion;
- disposition = isci_task_set_completion_status(task, response, status,
- disposition);
+ /* Normal notification (task_done) */
+ dev_dbg(&ihost->pdev->dev, "%s: task = %p, response=%d, status=%d\n",
+ __func__, task, response, status);
- /* Tasks aborted specifically by a call to the lldd_abort_task
- * function should not be completed to the host in the regular path.
- */
- switch (disposition) {
- case isci_perform_normal_io_completion:
- /* Normal notification (task_done) */
- dev_dbg(&ihost->pdev->dev,
- "%s: Normal - task = %p, response=%d, "
- "status=%d\n",
- __func__, task, response, status);
-
- task->lldd_task = NULL;
- task->task_done(task);
- break;
-
- case isci_perform_aborted_io_completion:
- /*
- * No notification because this request is already in the
- * abort path.
- */
- dev_dbg(&ihost->pdev->dev,
- "%s: Aborted - task = %p, response=%d, "
- "status=%d\n",
- __func__, task, response, status);
- break;
+ spin_lock_irqsave(&task->task_state_lock, flags);
- case isci_perform_error_io_completion:
- /* Use sas_task_abort */
- dev_dbg(&ihost->pdev->dev,
- "%s: Error - task = %p, response=%d, "
- "status=%d\n",
- __func__, task, response, status);
- sas_task_abort(task);
- break;
+ task->task_status.resp = response;
+ task->task_status.stat = status;
- default:
- dev_dbg(&ihost->pdev->dev,
- "%s: isci task notification default case!",
- __func__);
- sas_task_abort(task);
- break;
- }
+ /* Normal notification (task_done) */
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
+ task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
+ SAS_TASK_STATE_PENDING);
+ task->lldd_task = NULL;
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+ task->task_done(task);
}
#define for_each_sas_task(num, task) \
@@ -289,60 +260,6 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost,
return ireq;
}
-/**
-* isci_request_mark_zombie() - This function must be called with scic_lock held.
-*/
-static void isci_request_mark_zombie(struct isci_host *ihost, struct isci_request *ireq)
-{
- struct completion *tmf_completion = NULL;
- struct completion *req_completion;
-
- /* Set the request state to "dead". */
- ireq->status = dead;
-
- req_completion = ireq->io_request_completion;
- ireq->io_request_completion = NULL;
-
- if (test_bit(IREQ_TMF, &ireq->flags)) {
- /* Break links with the TMF request. */
- struct isci_tmf *tmf = isci_request_access_tmf(ireq);
-
- /* In the case where a task request is dying,
- * the thread waiting on the complete will sit and
- * timeout unless we wake it now. Since the TMF
- * has a default error status, complete it here
- * to wake the waiting thread.
- */
- if (tmf) {
- tmf_completion = tmf->complete;
- tmf->complete = NULL;
- }
- ireq->ttype_ptr.tmf_task_ptr = NULL;
- dev_dbg(&ihost->pdev->dev, "%s: tmf_code %d, managed tag %#x\n",
- __func__, tmf->tmf_code, tmf->io_tag);
- } else {
- /* Break links with the sas_task - the callback is done
- * elsewhere.
- */
- struct sas_task *task = isci_request_access_task(ireq);
-
- if (task)
- task->lldd_task = NULL;
-
- ireq->ttype_ptr.io_task_ptr = NULL;
- }
-
- dev_warn(&ihost->pdev->dev, "task context unrecoverable (tag: %#x)\n",
- ireq->io_tag);
-
- /* Don't force waiting threads to timeout. */
- if (req_completion)
- complete(req_completion);
-
- if (tmf_completion != NULL)
- complete(tmf_completion);
-}
-
static int isci_task_execute_tmf(struct isci_host *ihost,
struct isci_remote_device *idev,
struct isci_tmf *tmf, unsigned long timeout_ms)
@@ -400,17 +317,11 @@ static int isci_task_execute_tmf(struct isci_host *ihost,
spin_unlock_irqrestore(&ihost->scic_lock, flags);
goto err_tci;
}
-
- if (tmf->cb_state_func != NULL)
- tmf->cb_state_func(isci_tmf_started, tmf, tmf->cb_data);
-
- isci_request_change_state(ireq, started);
-
- /* add the request to the remote device request list. */
- list_add(&ireq->dev_node, &idev->reqs_in_process);
-
spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ /* The RNC must be unsuspended before the TMF can get a response. */
+ isci_remote_device_resume_from_abort(ihost, idev);
+
/* Wait for the TMF to complete, or a timeout. */
timeleft = wait_for_completion_timeout(&completion,
msecs_to_jiffies(timeout_ms));
@@ -419,32 +330,7 @@ static int isci_task_execute_tmf(struct isci_host *ihost,
/* The TMF did not complete - this could be because
* of an unplug. Terminate the TMF request now.
*/
- spin_lock_irqsave(&ihost->scic_lock, flags);
-
- if (tmf->cb_state_func != NULL)
- tmf->cb_state_func(isci_tmf_timed_out, tmf,
- tmf->cb_data);
-
- sci_controller_terminate_request(ihost, idev, ireq);
-
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
-
- timeleft = wait_for_completion_timeout(
- &completion,
- msecs_to_jiffies(ISCI_TERMINATION_TIMEOUT_MSEC));
-
- if (!timeleft) {
- /* Strange condition - the termination of the TMF
- * request timed-out.
- */
- spin_lock_irqsave(&ihost->scic_lock, flags);
-
- /* If the TMF status has not changed, kill it. */
- if (tmf->status == SCI_FAILURE_TIMEOUT)
- isci_request_mark_zombie(ihost, ireq);
-
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
- }
+ isci_remote_device_suspend_terminate(ihost, idev, ireq);
}
isci_print_tmf(ihost, tmf);
@@ -476,315 +362,21 @@ static int isci_task_execute_tmf(struct isci_host *ihost,
}
static void isci_task_build_tmf(struct isci_tmf *tmf,
- enum isci_tmf_function_codes code,
- void (*tmf_sent_cb)(enum isci_tmf_cb_state,
- struct isci_tmf *,
- void *),
- void *cb_data)
+ enum isci_tmf_function_codes code)
{
memset(tmf, 0, sizeof(*tmf));
-
- tmf->tmf_code = code;
- tmf->cb_state_func = tmf_sent_cb;
- tmf->cb_data = cb_data;
+ tmf->tmf_code = code;
}
static void isci_task_build_abort_task_tmf(struct isci_tmf *tmf,
enum isci_tmf_function_codes code,
- void (*tmf_sent_cb)(enum isci_tmf_cb_state,
- struct isci_tmf *,
- void *),
struct isci_request *old_request)
{
- isci_task_build_tmf(tmf, code, tmf_sent_cb, old_request);
+ isci_task_build_tmf(tmf, code);
tmf->io_tag = old_request->io_tag;
}
/**
- * isci_task_validate_request_to_abort() - This function checks the given I/O
- * against the "started" state. If the request is still "started", it's
- * state is changed to aborted. NOTE: isci_host->scic_lock MUST BE HELD
- * BEFORE CALLING THIS FUNCTION.
- * @isci_request: This parameter specifies the request object to control.
- * @isci_host: This parameter specifies the ISCI host object
- * @isci_device: This is the device to which the request is pending.
- * @aborted_io_completion: This is a completion structure that will be added to
- * the request in case it is changed to aborting; this completion is
- * triggered when the request is fully completed.
- *
- * Either "started" on successful change of the task status to "aborted", or
- * "unallocated" if the task cannot be controlled.
- */
-static enum isci_request_status isci_task_validate_request_to_abort(
- struct isci_request *isci_request,
- struct isci_host *isci_host,
- struct isci_remote_device *isci_device,
- struct completion *aborted_io_completion)
-{
- enum isci_request_status old_state = unallocated;
-
- /* Only abort the task if it's in the
- * device's request_in_process list
- */
- if (isci_request && !list_empty(&isci_request->dev_node)) {
- old_state = isci_request_change_started_to_aborted(
- isci_request, aborted_io_completion);
-
- }
-
- return old_state;
-}
-
-static int isci_request_is_dealloc_managed(enum isci_request_status stat)
-{
- switch (stat) {
- case aborted:
- case aborting:
- case terminating:
- case completed:
- case dead:
- return true;
- default:
- return false;
- }
-}
-
-/**
- * isci_terminate_request_core() - This function will terminate the given
- * request, and wait for it to complete. This function must only be called
- * from a thread that can wait. Note that the request is terminated and
- * completed (back to the host, if started there).
- * @ihost: This SCU.
- * @idev: The target.
- * @isci_request: The I/O request to be terminated.
- *
- */
-static void isci_terminate_request_core(struct isci_host *ihost,
- struct isci_remote_device *idev,
- struct isci_request *isci_request)
-{
- enum sci_status status = SCI_SUCCESS;
- bool was_terminated = false;
- bool needs_cleanup_handling = false;
- unsigned long flags;
- unsigned long termination_completed = 1;
- struct completion *io_request_completion;
-
- dev_dbg(&ihost->pdev->dev,
- "%s: device = %p; request = %p\n",
- __func__, idev, isci_request);
-
- spin_lock_irqsave(&ihost->scic_lock, flags);
-
- io_request_completion = isci_request->io_request_completion;
-
- /* Note that we are not going to control
- * the target to abort the request.
- */
- set_bit(IREQ_COMPLETE_IN_TARGET, &isci_request->flags);
-
- /* Make sure the request wasn't just sitting around signalling
- * device condition (if the request handle is NULL, then the
- * request completed but needed additional handling here).
- */
- if (!test_bit(IREQ_TERMINATED, &isci_request->flags)) {
- was_terminated = true;
- needs_cleanup_handling = true;
- status = sci_controller_terminate_request(ihost,
- idev,
- isci_request);
- }
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
-
- /*
- * The only time the request to terminate will
- * fail is when the io request is completed and
- * being aborted.
- */
- if (status != SCI_SUCCESS) {
- dev_dbg(&ihost->pdev->dev,
- "%s: sci_controller_terminate_request"
- " returned = 0x%x\n",
- __func__, status);
-
- isci_request->io_request_completion = NULL;
-
- } else {
- if (was_terminated) {
- dev_dbg(&ihost->pdev->dev,
- "%s: before completion wait (%p/%p)\n",
- __func__, isci_request, io_request_completion);
-
- /* Wait here for the request to complete. */
- termination_completed
- = wait_for_completion_timeout(
- io_request_completion,
- msecs_to_jiffies(ISCI_TERMINATION_TIMEOUT_MSEC));
-
- if (!termination_completed) {
-
- /* The request to terminate has timed out. */
- spin_lock_irqsave(&ihost->scic_lock, flags);
-
- /* Check for state changes. */
- if (!test_bit(IREQ_TERMINATED,
- &isci_request->flags)) {
-
- /* The best we can do is to have the
- * request die a silent death if it
- * ever really completes.
- */
- isci_request_mark_zombie(ihost,
- isci_request);
- needs_cleanup_handling = true;
- } else
- termination_completed = 1;
-
- spin_unlock_irqrestore(&ihost->scic_lock,
- flags);
-
- if (!termination_completed) {
-
- dev_dbg(&ihost->pdev->dev,
- "%s: *** Timeout waiting for "
- "termination(%p/%p)\n",
- __func__, io_request_completion,
- isci_request);
-
- /* The request can no longer be referenced
- * safely since it may go away if the
- * termination every really does complete.
- */
- isci_request = NULL;
- }
- }
- if (termination_completed)
- dev_dbg(&ihost->pdev->dev,
- "%s: after completion wait (%p/%p)\n",
- __func__, isci_request, io_request_completion);
- }
-
- if (termination_completed) {
-
- isci_request->io_request_completion = NULL;
-
- /* Peek at the status of the request. This will tell
- * us if there was special handling on the request such that it
- * needs to be detached and freed here.
- */
- spin_lock_irqsave(&isci_request->state_lock, flags);
-
- needs_cleanup_handling
- = isci_request_is_dealloc_managed(
- isci_request->status);
-
- spin_unlock_irqrestore(&isci_request->state_lock, flags);
-
- }
- if (needs_cleanup_handling) {
-
- dev_dbg(&ihost->pdev->dev,
- "%s: cleanup isci_device=%p, request=%p\n",
- __func__, idev, isci_request);
-
- if (isci_request != NULL) {
- spin_lock_irqsave(&ihost->scic_lock, flags);
- isci_free_tag(ihost, isci_request->io_tag);
- isci_request_change_state(isci_request, unallocated);
- list_del_init(&isci_request->dev_node);
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
- }
- }
- }
-}
-
-/**
- * isci_terminate_pending_requests() - This function will change the all of the
- * requests on the given device's state to "aborting", will terminate the
- * requests, and wait for them to complete. This function must only be
- * called from a thread that can wait. Note that the requests are all
- * terminated and completed (back to the host, if started there).
- * @isci_host: This parameter specifies SCU.
- * @idev: This parameter specifies the target.
- *
- */
-void isci_terminate_pending_requests(struct isci_host *ihost,
- struct isci_remote_device *idev)
-{
- struct completion request_completion;
- enum isci_request_status old_state;
- unsigned long flags;
- LIST_HEAD(list);
-
- spin_lock_irqsave(&ihost->scic_lock, flags);
- list_splice_init(&idev->reqs_in_process, &list);
-
- /* assumes that isci_terminate_request_core deletes from the list */
- while (!list_empty(&list)) {
- struct isci_request *ireq = list_entry(list.next, typeof(*ireq), dev_node);
-
- /* Change state to "terminating" if it is currently
- * "started".
- */
- old_state = isci_request_change_started_to_newstate(ireq,
- &request_completion,
- terminating);
- switch (old_state) {
- case started:
- case completed:
- case aborting:
- break;
- default:
- /* termination in progress, or otherwise dispositioned.
- * We know the request was on 'list' so should be safe
- * to move it back to reqs_in_process
- */
- list_move(&ireq->dev_node, &idev->reqs_in_process);
- ireq = NULL;
- break;
- }
-
- if (!ireq)
- continue;
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
-
- init_completion(&request_completion);
-
- dev_dbg(&ihost->pdev->dev,
- "%s: idev=%p request=%p; task=%p old_state=%d\n",
- __func__, idev, ireq,
- (!test_bit(IREQ_TMF, &ireq->flags)
- ? isci_request_access_task(ireq)
- : NULL),
- old_state);
-
- /* If the old_state is started:
- * This request was not already being aborted. If it had been,
- * then the aborting I/O (ie. the TMF request) would not be in
- * the aborting state, and thus would be terminated here. Note
- * that since the TMF completion's call to the kernel function
- * "complete()" does not happen until the pending I/O request
- * terminate fully completes, we do not have to implement a
- * special wait here for already aborting requests - the
- * termination of the TMF request will force the request
- * to finish it's already started terminate.
- *
- * If old_state == completed:
- * This request completed from the SCU hardware perspective
- * and now just needs cleaning up in terms of freeing the
- * request and potentially calling up to libsas.
- *
- * If old_state == aborting:
- * This request has already gone through a TMF timeout, but may
- * not have been terminated; needs cleaning up at least.
- */
- isci_terminate_request_core(ihost, idev, ireq);
- spin_lock_irqsave(&ihost->scic_lock, flags);
- }
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
-}
-
-/**
* isci_task_send_lu_reset_sas() - This function is called by of the SAS Domain
* Template functions.
* @lun: This parameter specifies the lun to be reset.
@@ -807,7 +399,7 @@ static int isci_task_send_lu_reset_sas(
* value is "TMF_RESP_FUNC_COMPLETE", or the request timed-out (or
* was otherwise unable to be executed ("TMF_RESP_FUNC_FAILED").
*/
- isci_task_build_tmf(&tmf, isci_tmf_ssp_lun_reset, NULL, NULL);
+ isci_task_build_tmf(&tmf, isci_tmf_ssp_lun_reset);
#define ISCI_LU_RESET_TIMEOUT_MS 2000 /* 2 second timeout. */
ret = isci_task_execute_tmf(isci_host, isci_device, &tmf, ISCI_LU_RESET_TIMEOUT_MS);
@@ -826,42 +418,44 @@ static int isci_task_send_lu_reset_sas(
int isci_task_lu_reset(struct domain_device *dev, u8 *lun)
{
- struct isci_host *isci_host = dev_to_ihost(dev);
- struct isci_remote_device *isci_device;
+ struct isci_host *ihost = dev_to_ihost(dev);
+ struct isci_remote_device *idev;
unsigned long flags;
- int ret;
+ int ret = TMF_RESP_FUNC_COMPLETE;
- spin_lock_irqsave(&isci_host->scic_lock, flags);
- isci_device = isci_lookup_device(dev);
- spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+ idev = isci_get_device(dev->lldd_dev);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
- dev_dbg(&isci_host->pdev->dev,
+ dev_dbg(&ihost->pdev->dev,
"%s: domain_device=%p, isci_host=%p; isci_device=%p\n",
- __func__, dev, isci_host, isci_device);
+ __func__, dev, ihost, idev);
- if (!isci_device) {
- /* If the device is gone, stop the escalations. */
- dev_dbg(&isci_host->pdev->dev, "%s: No dev\n", __func__);
+ if (!idev) {
+ /* If the device is gone, escalate to I_T_Nexus_Reset. */
+ dev_dbg(&ihost->pdev->dev, "%s: No dev\n", __func__);
- ret = TMF_RESP_FUNC_COMPLETE;
+ ret = TMF_RESP_FUNC_FAILED;
goto out;
}
- /* Send the task management part of the reset. */
- if (dev_is_sata(dev)) {
- sas_ata_schedule_reset(dev);
- ret = TMF_RESP_FUNC_COMPLETE;
- } else
- ret = isci_task_send_lu_reset_sas(isci_host, isci_device, lun);
-
- /* If the LUN reset worked, all the I/O can now be terminated. */
- if (ret == TMF_RESP_FUNC_COMPLETE)
- /* Terminate all I/O now. */
- isci_terminate_pending_requests(isci_host,
- isci_device);
-
+ /* Suspend the RNC, kill all TCs */
+ if (isci_remote_device_suspend_terminate(ihost, idev, NULL)
+ != SCI_SUCCESS) {
+ /* The suspend/terminate only fails if isci_get_device fails */
+ ret = TMF_RESP_FUNC_FAILED;
+ goto out;
+ }
+ /* All pending I/Os have been terminated and cleaned up. */
+ if (!test_bit(IDEV_GONE, &idev->flags)) {
+ if (dev_is_sata(dev))
+ sas_ata_schedule_reset(dev);
+ else
+ /* Send the task management part of the reset. */
+ ret = isci_task_send_lu_reset_sas(ihost, idev, lun);
+ }
out:
- isci_put_device(isci_device);
+ isci_put_device(idev);
return ret;
}
@@ -882,63 +476,6 @@ int isci_task_clear_nexus_ha(struct sas_ha_struct *ha)
/* Task Management Functions. Must be called from process context. */
/**
- * isci_abort_task_process_cb() - This is a helper function for the abort task
- * TMF command. It manages the request state with respect to the successful
- * transmission / completion of the abort task request.
- * @cb_state: This parameter specifies when this function was called - after
- * the TMF request has been started and after it has timed-out.
- * @tmf: This parameter specifies the TMF in progress.
- *
- *
- */
-static void isci_abort_task_process_cb(
- enum isci_tmf_cb_state cb_state,
- struct isci_tmf *tmf,
- void *cb_data)
-{
- struct isci_request *old_request;
-
- old_request = (struct isci_request *)cb_data;
-
- dev_dbg(&old_request->isci_host->pdev->dev,
- "%s: tmf=%p, old_request=%p\n",
- __func__, tmf, old_request);
-
- switch (cb_state) {
-
- case isci_tmf_started:
- /* The TMF has been started. Nothing to do here, since the
- * request state was already set to "aborted" by the abort
- * task function.
- */
- if ((old_request->status != aborted)
- && (old_request->status != completed))
- dev_dbg(&old_request->isci_host->pdev->dev,
- "%s: Bad request status (%d): tmf=%p, old_request=%p\n",
- __func__, old_request->status, tmf, old_request);
- break;
-
- case isci_tmf_timed_out:
-
- /* Set the task's state to "aborting", since the abort task
- * function thread set it to "aborted" (above) in anticipation
- * of the task management request working correctly. Since the
- * timeout has now fired, the TMF request failed. We set the
- * state such that the request completion will indicate the
- * device is no longer present.
- */
- isci_request_change_state(old_request, aborting);
- break;
-
- default:
- dev_dbg(&old_request->isci_host->pdev->dev,
- "%s: Bad cb_state (%d): tmf=%p, old_request=%p\n",
- __func__, cb_state, tmf, old_request);
- break;
- }
-}
-
-/**
* isci_task_abort_task() - This function is one of the SAS Domain Template
* functions. This function is called by libsas to abort a specified task.
* @task: This parameter specifies the SAS task to abort.
@@ -947,22 +484,20 @@ static void isci_abort_task_process_cb(
*/
int isci_task_abort_task(struct sas_task *task)
{
- struct isci_host *isci_host = dev_to_ihost(task->dev);
+ struct isci_host *ihost = dev_to_ihost(task->dev);
DECLARE_COMPLETION_ONSTACK(aborted_io_completion);
struct isci_request *old_request = NULL;
- enum isci_request_status old_state;
- struct isci_remote_device *isci_device = NULL;
+ struct isci_remote_device *idev = NULL;
struct isci_tmf tmf;
int ret = TMF_RESP_FUNC_FAILED;
unsigned long flags;
- int perform_termination = 0;
/* Get the isci_request reference from the task. Note that
* this check does not depend on the pending request list
* in the device, because tasks driving resets may land here
* after completion in the core.
*/
- spin_lock_irqsave(&isci_host->scic_lock, flags);
+ spin_lock_irqsave(&ihost->scic_lock, flags);
spin_lock(&task->task_state_lock);
old_request = task->lldd_task;
@@ -971,20 +506,29 @@ int isci_task_abort_task(struct sas_task *task)
if (!(task->task_state_flags & SAS_TASK_STATE_DONE) &&
(task->task_state_flags & SAS_TASK_AT_INITIATOR) &&
old_request)
- isci_device = isci_lookup_device(task->dev);
+ idev = isci_get_device(task->dev->lldd_dev);
spin_unlock(&task->task_state_lock);
- spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
- dev_dbg(&isci_host->pdev->dev,
- "%s: dev = %p, task = %p, old_request == %p\n",
- __func__, isci_device, task, old_request);
+ dev_warn(&ihost->pdev->dev,
+ "%s: dev = %p (%s%s), task = %p, old_request == %p\n",
+ __func__, idev,
+ (dev_is_sata(task->dev) ? "STP/SATA"
+ : ((dev_is_expander(task->dev))
+ ? "SMP"
+ : "SSP")),
+ ((idev) ? ((test_bit(IDEV_GONE, &idev->flags))
+ ? " IDEV_GONE"
+ : "")
+ : " <NULL>"),
+ task, old_request);
/* Device reset conditions signalled in task_state_flags are the
* responsbility of libsas to observe at the start of the error
* handler thread.
*/
- if (!isci_device || !old_request) {
+ if (!idev || !old_request) {
/* The request has already completed and there
* is nothing to do here other than to set the task
* done bit, and indicate that the task abort function
@@ -998,108 +542,72 @@ int isci_task_abort_task(struct sas_task *task)
ret = TMF_RESP_FUNC_COMPLETE;
- dev_dbg(&isci_host->pdev->dev,
- "%s: abort task not needed for %p\n",
- __func__, task);
+ dev_warn(&ihost->pdev->dev,
+ "%s: abort task not needed for %p\n",
+ __func__, task);
goto out;
}
-
- spin_lock_irqsave(&isci_host->scic_lock, flags);
-
- /* Check the request status and change to "aborted" if currently
- * "starting"; if true then set the I/O kernel completion
- * struct that will be triggered when the request completes.
- */
- old_state = isci_task_validate_request_to_abort(
- old_request, isci_host, isci_device,
- &aborted_io_completion);
- if ((old_state != started) &&
- (old_state != completed) &&
- (old_state != aborting)) {
-
- spin_unlock_irqrestore(&isci_host->scic_lock, flags);
-
- /* The request was already being handled by someone else (because
- * they got to set the state away from started).
- */
- dev_dbg(&isci_host->pdev->dev,
- "%s: device = %p; old_request %p already being aborted\n",
- __func__,
- isci_device, old_request);
- ret = TMF_RESP_FUNC_COMPLETE;
+ /* Suspend the RNC, kill the TC */
+ if (isci_remote_device_suspend_terminate(ihost, idev, old_request)
+ != SCI_SUCCESS) {
+ dev_warn(&ihost->pdev->dev,
+ "%s: isci_remote_device_reset_terminate(dev=%p, "
+ "req=%p, task=%p) failed\n",
+ __func__, idev, old_request, task);
+ ret = TMF_RESP_FUNC_FAILED;
goto out;
}
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+
if (task->task_proto == SAS_PROTOCOL_SMP ||
sas_protocol_ata(task->task_proto) ||
- test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) {
+ test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags) ||
+ test_bit(IDEV_GONE, &idev->flags)) {
- spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
- dev_dbg(&isci_host->pdev->dev,
- "%s: %s request"
- " or complete_in_target (%d), thus no TMF\n",
- __func__,
- ((task->task_proto == SAS_PROTOCOL_SMP)
- ? "SMP"
- : (sas_protocol_ata(task->task_proto)
- ? "SATA/STP"
- : "<other>")
- ),
- test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags));
-
- if (test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) {
- spin_lock_irqsave(&task->task_state_lock, flags);
- task->task_state_flags |= SAS_TASK_STATE_DONE;
- task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
- SAS_TASK_STATE_PENDING);
- spin_unlock_irqrestore(&task->task_state_lock, flags);
- ret = TMF_RESP_FUNC_COMPLETE;
- } else {
- spin_lock_irqsave(&task->task_state_lock, flags);
- task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
- SAS_TASK_STATE_PENDING);
- spin_unlock_irqrestore(&task->task_state_lock, flags);
- }
+ /* No task to send, so explicitly resume the device here */
+ isci_remote_device_resume_from_abort(ihost, idev);
- /* STP and SMP devices are not sent a TMF, but the
- * outstanding I/O request is terminated below. This is
- * because SATA/STP and SMP discovery path timeouts directly
- * call the abort task interface for cleanup.
- */
- perform_termination = 1;
+ dev_warn(&ihost->pdev->dev,
+ "%s: %s request"
+ " or complete_in_target (%d), "
+ "or IDEV_GONE (%d), thus no TMF\n",
+ __func__,
+ ((task->task_proto == SAS_PROTOCOL_SMP)
+ ? "SMP"
+ : (sas_protocol_ata(task->task_proto)
+ ? "SATA/STP"
+ : "<other>")
+ ),
+ test_bit(IREQ_COMPLETE_IN_TARGET,
+ &old_request->flags),
+ test_bit(IDEV_GONE, &idev->flags));
+
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
+ SAS_TASK_STATE_PENDING);
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+ ret = TMF_RESP_FUNC_COMPLETE;
} else {
/* Fill in the tmf stucture */
isci_task_build_abort_task_tmf(&tmf, isci_tmf_ssp_task_abort,
- isci_abort_task_process_cb,
old_request);
- spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ /* Send the task management request. */
#define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* 1/2 second timeout */
- ret = isci_task_execute_tmf(isci_host, isci_device, &tmf,
+ ret = isci_task_execute_tmf(ihost, idev, &tmf,
ISCI_ABORT_TASK_TIMEOUT_MS);
-
- if (ret == TMF_RESP_FUNC_COMPLETE)
- perform_termination = 1;
- else
- dev_dbg(&isci_host->pdev->dev,
- "%s: isci_task_send_tmf failed\n", __func__);
}
- if (perform_termination) {
- set_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags);
-
- /* Clean up the request on our side, and wait for the aborted
- * I/O to complete.
- */
- isci_terminate_request_core(isci_host, isci_device,
- old_request);
- }
-
- /* Make sure we do not leave a reference to aborted_io_completion */
- old_request->io_request_completion = NULL;
- out:
- isci_put_device(isci_device);
+out:
+ dev_warn(&ihost->pdev->dev,
+ "%s: Done; dev = %p, task = %p , old_request == %p\n",
+ __func__, idev, task, old_request);
+ isci_put_device(idev);
return ret;
}
@@ -1195,14 +703,11 @@ isci_task_request_complete(struct isci_host *ihost,
{
struct isci_tmf *tmf = isci_request_access_tmf(ireq);
struct completion *tmf_complete = NULL;
- struct completion *request_complete = ireq->io_request_completion;
dev_dbg(&ihost->pdev->dev,
"%s: request = %p, status=%d\n",
__func__, ireq, completion_status);
- isci_request_change_state(ireq, completed);
-
set_bit(IREQ_COMPLETE_IN_TARGET, &ireq->flags);
if (tmf) {
@@ -1226,20 +731,11 @@ isci_task_request_complete(struct isci_host *ihost,
*/
set_bit(IREQ_TERMINATED, &ireq->flags);
- /* As soon as something is in the terminate path, deallocation is
- * managed there. Note that the final non-managed state of a task
- * request is "completed".
- */
- if ((ireq->status == completed) ||
- !isci_request_is_dealloc_managed(ireq->status)) {
- isci_request_change_state(ireq, unallocated);
- isci_free_tag(ihost, ireq->io_tag);
- list_del_init(&ireq->dev_node);
- }
+ if (test_and_clear_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags))
+ wake_up_all(&ihost->eventq);
- /* "request_complete" is set if the task was being terminated. */
- if (request_complete)
- complete(request_complete);
+ if (!test_bit(IREQ_NO_AUTO_FREE_TAG, &ireq->flags))
+ isci_free_tag(ihost, ireq->io_tag);
/* The task management part completes last. */
if (tmf_complete)
@@ -1250,48 +746,38 @@ static int isci_reset_device(struct isci_host *ihost,
struct domain_device *dev,
struct isci_remote_device *idev)
{
- int rc;
- unsigned long flags;
- enum sci_status status;
+ int rc = TMF_RESP_FUNC_COMPLETE, reset_stat = -1;
struct sas_phy *phy = sas_get_local_phy(dev);
struct isci_port *iport = dev->port->lldd_port;
dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev);
- spin_lock_irqsave(&ihost->scic_lock, flags);
- status = sci_remote_device_reset(idev);
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
-
- if (status != SCI_SUCCESS) {
- dev_dbg(&ihost->pdev->dev,
- "%s: sci_remote_device_reset(%p) returned %d!\n",
- __func__, idev, status);
+ /* Suspend the RNC, terminate all outstanding TCs. */
+ if (isci_remote_device_suspend_terminate(ihost, idev, NULL)
+ != SCI_SUCCESS) {
rc = TMF_RESP_FUNC_FAILED;
goto out;
}
-
- if (scsi_is_sas_phy_local(phy)) {
- struct isci_phy *iphy = &ihost->phys[phy->number];
-
- rc = isci_port_perform_hard_reset(ihost, iport, iphy);
- } else
- rc = sas_phy_reset(phy, !dev_is_sata(dev));
-
- /* Terminate in-progress I/O now. */
- isci_remote_device_nuke_requests(ihost, idev);
-
- /* Since all pending TCs have been cleaned, resume the RNC. */
- spin_lock_irqsave(&ihost->scic_lock, flags);
- status = sci_remote_device_reset_complete(idev);
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
-
- if (status != SCI_SUCCESS) {
- dev_dbg(&ihost->pdev->dev,
- "%s: sci_remote_device_reset_complete(%p) "
- "returned %d!\n", __func__, idev, status);
+ /* Note that since the termination for outstanding requests succeeded,
+ * this function will return success. This is because the resets will
+ * only fail if the device has been removed (ie. hotplug), and the
+ * primary duty of this function is to cleanup tasks, so that is the
+ * relevant status.
+ */
+ if (!test_bit(IDEV_GONE, &idev->flags)) {
+ if (scsi_is_sas_phy_local(phy)) {
+ struct isci_phy *iphy = &ihost->phys[phy->number];
+
+ reset_stat = isci_port_perform_hard_reset(ihost, iport,
+ iphy);
+ } else
+ reset_stat = sas_phy_reset(phy, !dev_is_sata(dev));
}
+ /* Explicitly resume the RNC here, since there was no task sent. */
+ isci_remote_device_resume_from_abort(ihost, idev);
- dev_dbg(&ihost->pdev->dev, "%s: idev %p complete.\n", __func__, idev);
+ dev_dbg(&ihost->pdev->dev, "%s: idev %p complete, reset_stat=%d.\n",
+ __func__, idev, reset_stat);
out:
sas_put_local_phy(phy);
return rc;
@@ -1305,7 +791,7 @@ int isci_task_I_T_nexus_reset(struct domain_device *dev)
int ret;
spin_lock_irqsave(&ihost->scic_lock, flags);
- idev = isci_lookup_device(dev);
+ idev = isci_get_device(dev->lldd_dev);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
if (!idev) {
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
index 7b6d0e32fd9b..9c06cbad1d26 100644
--- a/drivers/scsi/isci/task.h
+++ b/drivers/scsi/isci/task.h
@@ -63,19 +63,6 @@
struct isci_request;
/**
- * enum isci_tmf_cb_state - This enum defines the possible states in which the
- * TMF callback function is invoked during the TMF execution process.
- *
- *
- */
-enum isci_tmf_cb_state {
-
- isci_tmf_init_state = 0,
- isci_tmf_started,
- isci_tmf_timed_out
-};
-
-/**
* enum isci_tmf_function_codes - This enum defines the possible preparations
* of task management requests.
*
@@ -87,6 +74,7 @@ enum isci_tmf_function_codes {
isci_tmf_ssp_task_abort = TMF_ABORT_TASK,
isci_tmf_ssp_lun_reset = TMF_LU_RESET,
};
+
/**
* struct isci_tmf - This class represents the task management object which
* acts as an interface to libsas for processing task management requests
@@ -106,15 +94,6 @@ struct isci_tmf {
u16 io_tag;
enum isci_tmf_function_codes tmf_code;
int status;
-
- /* The optional callback function allows the user process to
- * track the TMF transmit / timeout conditions.
- */
- void (*cb_state_func)(
- enum isci_tmf_cb_state,
- struct isci_tmf *, void *);
- void *cb_data;
-
};
static inline void isci_print_tmf(struct isci_host *ihost, struct isci_tmf *tmf)
@@ -208,113 +187,4 @@ int isci_queuecommand(
struct scsi_cmnd *scsi_cmd,
void (*donefunc)(struct scsi_cmnd *));
-/**
- * enum isci_completion_selection - This enum defines the possible actions to
- * take with respect to a given request's notification back to libsas.
- *
- *
- */
-enum isci_completion_selection {
-
- isci_perform_normal_io_completion, /* Normal notify (task_done) */
- isci_perform_aborted_io_completion, /* No notification. */
- isci_perform_error_io_completion /* Use sas_task_abort */
-};
-
-/**
- * isci_task_set_completion_status() - This function sets the completion status
- * for the request.
- * @task: This parameter is the completed request.
- * @response: This parameter is the response code for the completed task.
- * @status: This parameter is the status code for the completed task.
- *
-* @return The new notification mode for the request.
-*/
-static inline enum isci_completion_selection
-isci_task_set_completion_status(
- struct sas_task *task,
- enum service_response response,
- enum exec_status status,
- enum isci_completion_selection task_notification_selection)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&task->task_state_lock, flags);
-
- /* If a device reset is being indicated, make sure the I/O
- * is in the error path.
- */
- if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) {
- /* Fail the I/O to make sure it goes into the error path. */
- response = SAS_TASK_UNDELIVERED;
- status = SAM_STAT_TASK_ABORTED;
-
- task_notification_selection = isci_perform_error_io_completion;
- }
- task->task_status.resp = response;
- task->task_status.stat = status;
-
- switch (task->task_proto) {
-
- case SAS_PROTOCOL_SATA:
- case SAS_PROTOCOL_STP:
- case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
-
- if (task_notification_selection
- == isci_perform_error_io_completion) {
- /* SATA/STP I/O has it's own means of scheduling device
- * error handling on the normal path.
- */
- task_notification_selection
- = isci_perform_normal_io_completion;
- }
- break;
- default:
- break;
- }
-
- switch (task_notification_selection) {
-
- case isci_perform_error_io_completion:
-
- if (task->task_proto == SAS_PROTOCOL_SMP) {
- /* There is no error escalation in the SMP case.
- * Convert to a normal completion to avoid the
- * timeout in the discovery path and to let the
- * next action take place quickly.
- */
- task_notification_selection
- = isci_perform_normal_io_completion;
-
- /* Fall through to the normal case... */
- } else {
- /* Use sas_task_abort */
- /* Leave SAS_TASK_STATE_DONE clear
- * Leave SAS_TASK_AT_INITIATOR set.
- */
- break;
- }
-
- case isci_perform_aborted_io_completion:
- /* This path can occur with task-managed requests as well as
- * requests terminated because of LUN or device resets.
- */
- /* Fall through to the normal case... */
- case isci_perform_normal_io_completion:
- /* Normal notification (task_done) */
- task->task_state_flags |= SAS_TASK_STATE_DONE;
- task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
- SAS_TASK_STATE_PENDING);
- break;
- default:
- WARN_ONCE(1, "unknown task_notification_selection: %d\n",
- task_notification_selection);
- break;
- }
-
- spin_unlock_irqrestore(&task->task_state_lock, flags);
-
- return task_notification_selection;
-
-}
#endif /* !defined(_SCI_TASK_H_) */
diff --git a/drivers/scsi/isci/unsolicited_frame_control.c b/drivers/scsi/isci/unsolicited_frame_control.c
index 16f88ab939c8..04a6d0d59a22 100644
--- a/drivers/scsi/isci/unsolicited_frame_control.c
+++ b/drivers/scsi/isci/unsolicited_frame_control.c
@@ -57,31 +57,19 @@
#include "unsolicited_frame_control.h"
#include "registers.h"
-int sci_unsolicited_frame_control_construct(struct isci_host *ihost)
+void sci_unsolicited_frame_control_construct(struct isci_host *ihost)
{
struct sci_unsolicited_frame_control *uf_control = &ihost->uf_control;
struct sci_unsolicited_frame *uf;
- u32 buf_len, header_len, i;
- dma_addr_t dma;
- size_t size;
- void *virt;
-
- /*
- * Prepare all of the memory sizes for the UF headers, UF address
- * table, and UF buffers themselves.
- */
- buf_len = SCU_MAX_UNSOLICITED_FRAMES * SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
- header_len = SCU_MAX_UNSOLICITED_FRAMES * sizeof(struct scu_unsolicited_frame_header);
- size = buf_len + header_len + SCU_MAX_UNSOLICITED_FRAMES * sizeof(uf_control->address_table.array[0]);
+ dma_addr_t dma = ihost->ufi_dma;
+ void *virt = ihost->ufi_buf;
+ int i;
/*
* The Unsolicited Frame buffers are set at the start of the UF
* memory descriptor entry. The headers and address table will be
* placed after the buffers.
*/
- virt = dmam_alloc_coherent(&ihost->pdev->dev, size, &dma, GFP_KERNEL);
- if (!virt)
- return -ENOMEM;
/*
* Program the location of the UF header table into the SCU.
@@ -93,8 +81,8 @@ int sci_unsolicited_frame_control_construct(struct isci_host *ihost)
* headers, since we program the UF address table pointers to
* NULL.
*/
- uf_control->headers.physical_address = dma + buf_len;
- uf_control->headers.array = virt + buf_len;
+ uf_control->headers.physical_address = dma + SCI_UFI_BUF_SIZE;
+ uf_control->headers.array = virt + SCI_UFI_BUF_SIZE;
/*
* Program the location of the UF address table into the SCU.
@@ -103,8 +91,8 @@ int sci_unsolicited_frame_control_construct(struct isci_host *ihost)
* byte boundary already due to above programming headers being on a
* 64-bit boundary and headers are on a 64-bytes in size.
*/
- uf_control->address_table.physical_address = dma + buf_len + header_len;
- uf_control->address_table.array = virt + buf_len + header_len;
+ uf_control->address_table.physical_address = dma + SCI_UFI_BUF_SIZE + SCI_UFI_HDR_SIZE;
+ uf_control->address_table.array = virt + SCI_UFI_BUF_SIZE + SCI_UFI_HDR_SIZE;
uf_control->get = 0;
/*
@@ -135,8 +123,6 @@ int sci_unsolicited_frame_control_construct(struct isci_host *ihost)
virt += SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
dma += SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
}
-
- return 0;
}
enum sci_status sci_unsolicited_frame_control_get_header(struct sci_unsolicited_frame_control *uf_control,
diff --git a/drivers/scsi/isci/unsolicited_frame_control.h b/drivers/scsi/isci/unsolicited_frame_control.h
index 75d896686f5a..1bc551ec611f 100644
--- a/drivers/scsi/isci/unsolicited_frame_control.h
+++ b/drivers/scsi/isci/unsolicited_frame_control.h
@@ -257,9 +257,13 @@ struct sci_unsolicited_frame_control {
};
+#define SCI_UFI_BUF_SIZE (SCU_MAX_UNSOLICITED_FRAMES * SCU_UNSOLICITED_FRAME_BUFFER_SIZE)
+#define SCI_UFI_HDR_SIZE (SCU_MAX_UNSOLICITED_FRAMES * sizeof(struct scu_unsolicited_frame_header))
+#define SCI_UFI_TOTAL_SIZE (SCI_UFI_BUF_SIZE + SCI_UFI_HDR_SIZE + SCU_MAX_UNSOLICITED_FRAMES * sizeof(u64))
+
struct isci_host;
-int sci_unsolicited_frame_control_construct(struct isci_host *ihost);
+void sci_unsolicited_frame_control_construct(struct isci_host *ihost);
enum sci_status sci_unsolicited_frame_control_get_header(
struct sci_unsolicited_frame_control *uf_control,
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index cc83b66d45b7..c1402fb499ab 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -648,6 +648,7 @@ int fc_lport_destroy(struct fc_lport *lport)
lport->tt.fcp_abort_io(lport);
lport->tt.disc_stop_final(lport);
lport->tt.exch_mgr_reset(lport, 0, 0);
+ cancel_delayed_work_sync(&lport->retry_work);
fc_fc4_del_lport(lport);
return 0;
}
@@ -1564,7 +1565,6 @@ static void fc_lport_timeout(struct work_struct *work)
switch (lport->state) {
case LPORT_ST_DISABLED:
- WARN_ON(1);
break;
case LPORT_ST_READY:
break;
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 3a1ffdd6d831..e5da6da20f8a 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -93,6 +93,9 @@ struct lpfc_sli2_slim;
/* lpfc wait event data ready flag */
#define LPFC_DATA_READY (1<<0)
+/* queue dump line buffer size */
+#define LPFC_LBUF_SZ 128
+
enum lpfc_polling_flags {
ENABLE_FCP_RING_POLLING = 0x1,
DISABLE_FCP_RING_INT = 0x2
@@ -620,6 +623,7 @@ struct lpfc_hba {
#define HBA_AER_ENABLED 0x1000 /* AER enabled with HBA */
#define HBA_DEVLOSS_TMO 0x2000 /* HBA in devloss timeout */
#define HBA_RRQ_ACTIVE 0x4000 /* process the rrq active list */
+#define HBA_FCP_IOQ_FLUSH 0x8000 /* FCP I/O queues being flushed */
uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
struct lpfc_dmabuf slim2p;
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 141e4b40bb55..253d9a857346 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2009-2011 Emulex. All rights reserved. *
+ * Copyright (C) 2009-2012 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
@@ -599,6 +599,7 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
cmdiocbq->iocb_cmpl = lpfc_bsg_rport_els_cmp;
cmdiocbq->context1 = dd_data;
+ cmdiocbq->context_un.ndlp = ndlp;
cmdiocbq->context2 = rspiocbq;
dd_data->type = TYPE_IOCB;
dd_data->context_un.iocb.cmdiocbq = cmdiocbq;
@@ -3978,6 +3979,7 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
} else if (subsys == SLI_CONFIG_SUBSYS_COMN) {
switch (opcode) {
case COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES:
+ case COMN_OPCODE_GET_CNTL_ATTRIBUTES:
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
"3106 Handled SLI_CONFIG "
"subsys_comn, opcode:x%x\n",
diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h
index edfe61fc52b1..67f7d0a160d1 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.h
+++ b/drivers/scsi/lpfc/lpfc_bsg.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2010 Emulex. All rights reserved. *
+ * Copyright (C) 2010-2012 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
@@ -249,6 +249,7 @@ struct lpfc_sli_config_emb1_subsys {
#define COMN_OPCODE_READ_OBJECT_LIST 0xAD
#define COMN_OPCODE_DELETE_OBJECT 0xAE
#define COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES 0x79
+#define COMN_OPCODE_GET_CNTL_ATTRIBUTES 0x20
uint32_t timeout;
uint32_t request_length;
uint32_t word9;
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 330dd7192a7f..9b2a16f3bc79 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -254,6 +254,7 @@ int
lpfc_sli_handle_fast_ring_event(struct lpfc_hba *,
struct lpfc_sli_ring *, uint32_t);
+struct lpfc_iocbq *__lpfc_sli_get_iocbq(struct lpfc_hba *);
struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
void lpfc_sli_release_iocbq(struct lpfc_hba *, struct lpfc_iocbq *);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *);
@@ -460,6 +461,7 @@ int lpfc_hba_init_link_fc_topology(struct lpfc_hba *, uint32_t, uint32_t);
int lpfc_issue_reg_vfi(struct lpfc_vport *);
int lpfc_issue_unreg_vfi(struct lpfc_vport *);
int lpfc_selective_reset(struct lpfc_hba *);
-int lpfc_sli4_read_config(struct lpfc_hba *phba);
-int lpfc_scsi_buf_update(struct lpfc_hba *phba);
-void lpfc_sli4_node_prep(struct lpfc_hba *phba);
+int lpfc_sli4_read_config(struct lpfc_hba *);
+void lpfc_sli4_node_prep(struct lpfc_hba *);
+int lpfc_sli4_xri_sgl_update(struct lpfc_hba *);
+void lpfc_free_sgl_list(struct lpfc_hba *, struct list_head *);
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index af04b0d6688d..3217d63ed282 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -4466,3 +4466,49 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
#endif
return;
}
+
+/*
+ * Driver debug utility routines outside of debugfs. The debug utility
+ * routines implemented here is intended to be used in the instrumented
+ * debug driver for debugging host or port issues.
+ */
+
+/**
+ * lpfc_debug_dump_all_queues - dump all the queues with a hba
+ * @phba: Pointer to HBA context object.
+ *
+ * This function dumps entries of all the queues asociated with the @phba.
+ **/
+void
+lpfc_debug_dump_all_queues(struct lpfc_hba *phba)
+{
+ int fcp_wqidx;
+
+ /*
+ * Dump Work Queues (WQs)
+ */
+ lpfc_debug_dump_mbx_wq(phba);
+ lpfc_debug_dump_els_wq(phba);
+
+ for (fcp_wqidx = 0; fcp_wqidx < phba->cfg_fcp_wq_count; fcp_wqidx++)
+ lpfc_debug_dump_fcp_wq(phba, fcp_wqidx);
+
+ lpfc_debug_dump_hdr_rq(phba);
+ lpfc_debug_dump_dat_rq(phba);
+ /*
+ * Dump Complete Queues (CQs)
+ */
+ lpfc_debug_dump_mbx_cq(phba);
+ lpfc_debug_dump_els_cq(phba);
+
+ for (fcp_wqidx = 0; fcp_wqidx < phba->cfg_fcp_wq_count; fcp_wqidx++)
+ lpfc_debug_dump_fcp_cq(phba, fcp_wqidx);
+
+ /*
+ * Dump Event Queues (EQs)
+ */
+ lpfc_debug_dump_sp_eq(phba);
+
+ for (fcp_wqidx = 0; fcp_wqidx < phba->cfg_fcp_wq_count; fcp_wqidx++)
+ lpfc_debug_dump_fcp_eq(phba, fcp_wqidx);
+}
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
index f83bd944edd8..616c400dae14 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.h
+++ b/drivers/scsi/lpfc/lpfc_debugfs.h
@@ -267,3 +267,421 @@ struct lpfc_idiag {
#define LPFC_DISC_TRC_DISCOVERY 0xef /* common mask for general
* discovery */
#endif /* H_LPFC_DEBUG_FS */
+
+
+/*
+ * Driver debug utility routines outside of debugfs. The debug utility
+ * routines implemented here is intended to be used in the instrumented
+ * debug driver for debugging host or port issues.
+ */
+
+/**
+ * lpfc_debug_dump_qe - dump an specific entry from a queue
+ * @q: Pointer to the queue descriptor.
+ * @idx: Index to the entry on the queue.
+ *
+ * This function dumps an entry indexed by @idx from a queue specified by the
+ * queue descriptor @q.
+ **/
+static inline void
+lpfc_debug_dump_qe(struct lpfc_queue *q, uint32_t idx)
+{
+ char line_buf[LPFC_LBUF_SZ];
+ int i, esize, qe_word_cnt, len;
+ uint32_t *pword;
+
+ /* sanity checks */
+ if (!q)
+ return;
+ if (idx >= q->entry_count)
+ return;
+
+ esize = q->entry_size;
+ qe_word_cnt = esize / sizeof(uint32_t);
+ pword = q->qe[idx].address;
+
+ len = 0;
+ len += snprintf(line_buf+len, LPFC_LBUF_SZ-len, "QE[%04d]: ", idx);
+ if (qe_word_cnt > 8)
+ printk(KERN_ERR "%s\n", line_buf);
+
+ for (i = 0; i < qe_word_cnt; i++) {
+ if (!(i % 8)) {
+ if (i != 0)
+ printk(KERN_ERR "%s\n", line_buf);
+ if (qe_word_cnt > 8) {
+ len = 0;
+ memset(line_buf, 0, LPFC_LBUF_SZ);
+ len += snprintf(line_buf+len, LPFC_LBUF_SZ-len,
+ "%03d: ", i);
+ }
+ }
+ len += snprintf(line_buf+len, LPFC_LBUF_SZ-len, "%08x ",
+ ((uint32_t)*pword) & 0xffffffff);
+ pword++;
+ }
+ if (qe_word_cnt <= 8 || (i - 1) % 8)
+ printk(KERN_ERR "%s\n", line_buf);
+}
+
+/**
+ * lpfc_debug_dump_q - dump all entries from an specific queue
+ * @q: Pointer to the queue descriptor.
+ *
+ * This function dumps all entries from a queue specified by the queue
+ * descriptor @q.
+ **/
+static inline void
+lpfc_debug_dump_q(struct lpfc_queue *q)
+{
+ int idx, entry_count;
+
+ /* sanity check */
+ if (!q)
+ return;
+
+ dev_printk(KERN_ERR, &(((q->phba))->pcidev)->dev,
+ "%d: [qid:%d, type:%d, subtype:%d, "
+ "qe_size:%d, qe_count:%d, "
+ "host_index:%d, port_index:%d]\n",
+ (q->phba)->brd_no,
+ q->queue_id, q->type, q->subtype,
+ q->entry_size, q->entry_count,
+ q->host_index, q->hba_index);
+ entry_count = q->entry_count;
+ for (idx = 0; idx < entry_count; idx++)
+ lpfc_debug_dump_qe(q, idx);
+ printk(KERN_ERR "\n");
+}
+
+/**
+ * lpfc_debug_dump_fcp_wq - dump all entries from a fcp work queue
+ * @phba: Pointer to HBA context object.
+ * @fcp_wqidx: Index to a FCP work queue.
+ *
+ * This function dumps all entries from a FCP work queue specified by the
+ * @fcp_wqidx.
+ **/
+static inline void
+lpfc_debug_dump_fcp_wq(struct lpfc_hba *phba, int fcp_wqidx)
+{
+ /* sanity check */
+ if (fcp_wqidx >= phba->cfg_fcp_wq_count)
+ return;
+
+ printk(KERN_ERR "FCP WQ: WQ[Idx:%d|Qid:%d]\n",
+ fcp_wqidx, phba->sli4_hba.fcp_wq[fcp_wqidx]->queue_id);
+ lpfc_debug_dump_q(phba->sli4_hba.fcp_wq[fcp_wqidx]);
+}
+
+/**
+ * lpfc_debug_dump_fcp_cq - dump all entries from a fcp work queue's cmpl queue
+ * @phba: Pointer to HBA context object.
+ * @fcp_wqidx: Index to a FCP work queue.
+ *
+ * This function dumps all entries from a FCP complete queue which is
+ * associated to the FCP work queue specified by the @fcp_wqidx.
+ **/
+static inline void
+lpfc_debug_dump_fcp_cq(struct lpfc_hba *phba, int fcp_wqidx)
+{
+ int fcp_cqidx, fcp_cqid;
+
+ /* sanity check */
+ if (fcp_wqidx >= phba->cfg_fcp_wq_count)
+ return;
+
+ fcp_cqid = phba->sli4_hba.fcp_wq[fcp_wqidx]->assoc_qid;
+ for (fcp_cqidx = 0; fcp_cqidx < phba->cfg_fcp_eq_count; fcp_cqidx++)
+ if (phba->sli4_hba.fcp_cq[fcp_cqidx]->queue_id == fcp_cqid)
+ break;
+ if (fcp_cqidx >= phba->cfg_fcp_eq_count)
+ return;
+
+ printk(KERN_ERR "FCP CQ: WQ[Idx:%d|Qid%d]->CQ[Idx%d|Qid%d]:\n",
+ fcp_wqidx, phba->sli4_hba.fcp_wq[fcp_wqidx]->queue_id,
+ fcp_cqidx, fcp_cqid);
+ lpfc_debug_dump_q(phba->sli4_hba.fcp_cq[fcp_cqidx]);
+}
+
+/**
+ * lpfc_debug_dump_fcp_eq - dump all entries from a fcp work queue's evt queue
+ * @phba: Pointer to HBA context object.
+ * @fcp_wqidx: Index to a FCP work queue.
+ *
+ * This function dumps all entries from a FCP event queue which is
+ * associated to the FCP work queue specified by the @fcp_wqidx.
+ **/
+static inline void
+lpfc_debug_dump_fcp_eq(struct lpfc_hba *phba, int fcp_wqidx)
+{
+ struct lpfc_queue *qdesc;
+ int fcp_eqidx, fcp_eqid;
+ int fcp_cqidx, fcp_cqid;
+
+ /* sanity check */
+ if (fcp_wqidx >= phba->cfg_fcp_wq_count)
+ return;
+ fcp_cqid = phba->sli4_hba.fcp_wq[fcp_wqidx]->assoc_qid;
+ for (fcp_cqidx = 0; fcp_cqidx < phba->cfg_fcp_eq_count; fcp_cqidx++)
+ if (phba->sli4_hba.fcp_cq[fcp_cqidx]->queue_id == fcp_cqid)
+ break;
+ if (fcp_cqidx >= phba->cfg_fcp_eq_count)
+ return;
+
+ if (phba->cfg_fcp_eq_count == 0) {
+ fcp_eqidx = -1;
+ fcp_eqid = phba->sli4_hba.sp_eq->queue_id;
+ qdesc = phba->sli4_hba.sp_eq;
+ } else {
+ fcp_eqidx = fcp_cqidx;
+ fcp_eqid = phba->sli4_hba.fp_eq[fcp_eqidx]->queue_id;
+ qdesc = phba->sli4_hba.fp_eq[fcp_eqidx];
+ }
+
+ printk(KERN_ERR "FCP EQ: WQ[Idx:%d|Qid:%d]->CQ[Idx:%d|Qid:%d]->"
+ "EQ[Idx:%d|Qid:%d]\n",
+ fcp_wqidx, phba->sli4_hba.fcp_wq[fcp_wqidx]->queue_id,
+ fcp_cqidx, fcp_cqid, fcp_eqidx, fcp_eqid);
+ lpfc_debug_dump_q(qdesc);
+}
+
+/**
+ * lpfc_debug_dump_els_wq - dump all entries from the els work queue
+ * @phba: Pointer to HBA context object.
+ *
+ * This function dumps all entries from the ELS work queue.
+ **/
+static inline void
+lpfc_debug_dump_els_wq(struct lpfc_hba *phba)
+{
+ printk(KERN_ERR "ELS WQ: WQ[Qid:%d]:\n",
+ phba->sli4_hba.els_wq->queue_id);
+ lpfc_debug_dump_q(phba->sli4_hba.els_wq);
+}
+
+/**
+ * lpfc_debug_dump_mbx_wq - dump all entries from the mbox work queue
+ * @phba: Pointer to HBA context object.
+ *
+ * This function dumps all entries from the MBOX work queue.
+ **/
+static inline void
+lpfc_debug_dump_mbx_wq(struct lpfc_hba *phba)
+{
+ printk(KERN_ERR "MBX WQ: WQ[Qid:%d]\n",
+ phba->sli4_hba.mbx_wq->queue_id);
+ lpfc_debug_dump_q(phba->sli4_hba.mbx_wq);
+}
+
+/**
+ * lpfc_debug_dump_dat_rq - dump all entries from the receive data queue
+ * @phba: Pointer to HBA context object.
+ *
+ * This function dumps all entries from the receive data queue.
+ **/
+static inline void
+lpfc_debug_dump_dat_rq(struct lpfc_hba *phba)
+{
+ printk(KERN_ERR "DAT RQ: RQ[Qid:%d]\n",
+ phba->sli4_hba.dat_rq->queue_id);
+ lpfc_debug_dump_q(phba->sli4_hba.dat_rq);
+}
+
+/**
+ * lpfc_debug_dump_hdr_rq - dump all entries from the receive header queue
+ * @phba: Pointer to HBA context object.
+ *
+ * This function dumps all entries from the receive header queue.
+ **/
+static inline void
+lpfc_debug_dump_hdr_rq(struct lpfc_hba *phba)
+{
+ printk(KERN_ERR "HDR RQ: RQ[Qid:%d]\n",
+ phba->sli4_hba.hdr_rq->queue_id);
+ lpfc_debug_dump_q(phba->sli4_hba.hdr_rq);
+}
+
+/**
+ * lpfc_debug_dump_els_cq - dump all entries from the els complete queue
+ * @phba: Pointer to HBA context object.
+ *
+ * This function dumps all entries from the els complete queue.
+ **/
+static inline void
+lpfc_debug_dump_els_cq(struct lpfc_hba *phba)
+{
+ printk(KERN_ERR "ELS CQ: WQ[Qid:%d]->CQ[Qid:%d]\n",
+ phba->sli4_hba.els_wq->queue_id,
+ phba->sli4_hba.els_cq->queue_id);
+ lpfc_debug_dump_q(phba->sli4_hba.els_cq);
+}
+
+/**
+ * lpfc_debug_dump_mbx_cq - dump all entries from the mbox complete queue
+ * @phba: Pointer to HBA context object.
+ *
+ * This function dumps all entries from the mbox complete queue.
+ **/
+static inline void
+lpfc_debug_dump_mbx_cq(struct lpfc_hba *phba)
+{
+ printk(KERN_ERR "MBX CQ: WQ[Qid:%d]->CQ[Qid:%d]\n",
+ phba->sli4_hba.mbx_wq->queue_id,
+ phba->sli4_hba.mbx_cq->queue_id);
+ lpfc_debug_dump_q(phba->sli4_hba.mbx_cq);
+}
+
+/**
+ * lpfc_debug_dump_sp_eq - dump all entries from slow-path event queue
+ * @phba: Pointer to HBA context object.
+ *
+ * This function dumps all entries from the slow-path event queue.
+ **/
+static inline void
+lpfc_debug_dump_sp_eq(struct lpfc_hba *phba)
+{
+ printk(KERN_ERR "SP EQ: WQ[Qid:%d/Qid:%d]->CQ[Qid:%d/Qid:%d]->"
+ "EQ[Qid:%d]:\n",
+ phba->sli4_hba.mbx_wq->queue_id,
+ phba->sli4_hba.els_wq->queue_id,
+ phba->sli4_hba.mbx_cq->queue_id,
+ phba->sli4_hba.els_cq->queue_id,
+ phba->sli4_hba.sp_eq->queue_id);
+ lpfc_debug_dump_q(phba->sli4_hba.sp_eq);
+}
+
+/**
+ * lpfc_debug_dump_wq_by_id - dump all entries from a work queue by queue id
+ * @phba: Pointer to HBA context object.
+ * @qid: Work queue identifier.
+ *
+ * This function dumps all entries from a work queue identified by the queue
+ * identifier.
+ **/
+static inline void
+lpfc_debug_dump_wq_by_id(struct lpfc_hba *phba, int qid)
+{
+ int wq_idx;
+
+ for (wq_idx = 0; wq_idx < phba->cfg_fcp_wq_count; wq_idx++)
+ if (phba->sli4_hba.fcp_wq[wq_idx]->queue_id == qid)
+ break;
+ if (wq_idx < phba->cfg_fcp_wq_count) {
+ printk(KERN_ERR "FCP WQ[Idx:%d|Qid:%d]\n", wq_idx, qid);
+ lpfc_debug_dump_q(phba->sli4_hba.fcp_wq[wq_idx]);
+ return;
+ }
+
+ if (phba->sli4_hba.els_wq->queue_id == qid) {
+ printk(KERN_ERR "ELS WQ[Qid:%d]\n", qid);
+ lpfc_debug_dump_q(phba->sli4_hba.els_wq);
+ }
+}
+
+/**
+ * lpfc_debug_dump_mq_by_id - dump all entries from a mbox queue by queue id
+ * @phba: Pointer to HBA context object.
+ * @qid: Mbox work queue identifier.
+ *
+ * This function dumps all entries from a mbox work queue identified by the
+ * queue identifier.
+ **/
+static inline void
+lpfc_debug_dump_mq_by_id(struct lpfc_hba *phba, int qid)
+{
+ if (phba->sli4_hba.mbx_wq->queue_id == qid) {
+ printk(KERN_ERR "MBX WQ[Qid:%d]\n", qid);
+ lpfc_debug_dump_q(phba->sli4_hba.mbx_wq);
+ }
+}
+
+/**
+ * lpfc_debug_dump_rq_by_id - dump all entries from a receive queue by queue id
+ * @phba: Pointer to HBA context object.
+ * @qid: Receive queue identifier.
+ *
+ * This function dumps all entries from a receive queue identified by the
+ * queue identifier.
+ **/
+static inline void
+lpfc_debug_dump_rq_by_id(struct lpfc_hba *phba, int qid)
+{
+ if (phba->sli4_hba.hdr_rq->queue_id == qid) {
+ printk(KERN_ERR "HDR RQ[Qid:%d]\n", qid);
+ lpfc_debug_dump_q(phba->sli4_hba.hdr_rq);
+ return;
+ }
+ if (phba->sli4_hba.dat_rq->queue_id == qid) {
+ printk(KERN_ERR "DAT RQ[Qid:%d]\n", qid);
+ lpfc_debug_dump_q(phba->sli4_hba.dat_rq);
+ }
+}
+
+/**
+ * lpfc_debug_dump_cq_by_id - dump all entries from a cmpl queue by queue id
+ * @phba: Pointer to HBA context object.
+ * @qid: Complete queue identifier.
+ *
+ * This function dumps all entries from a complete queue identified by the
+ * queue identifier.
+ **/
+static inline void
+lpfc_debug_dump_cq_by_id(struct lpfc_hba *phba, int qid)
+{
+ int cq_idx = 0;
+
+ do {
+ if (phba->sli4_hba.fcp_cq[cq_idx]->queue_id == qid)
+ break;
+ } while (++cq_idx < phba->cfg_fcp_eq_count);
+
+ if (cq_idx < phba->cfg_fcp_eq_count) {
+ printk(KERN_ERR "FCP CQ[Idx:%d|Qid:%d]\n", cq_idx, qid);
+ lpfc_debug_dump_q(phba->sli4_hba.fcp_cq[cq_idx]);
+ return;
+ }
+
+ if (phba->sli4_hba.els_cq->queue_id == qid) {
+ printk(KERN_ERR "ELS CQ[Qid:%d]\n", qid);
+ lpfc_debug_dump_q(phba->sli4_hba.els_cq);
+ return;
+ }
+
+ if (phba->sli4_hba.mbx_cq->queue_id == qid) {
+ printk(KERN_ERR "MBX CQ[Qid:%d]\n", qid);
+ lpfc_debug_dump_q(phba->sli4_hba.mbx_cq);
+ }
+}
+
+/**
+ * lpfc_debug_dump_eq_by_id - dump all entries from an event queue by queue id
+ * @phba: Pointer to HBA context object.
+ * @qid: Complete queue identifier.
+ *
+ * This function dumps all entries from an event queue identified by the
+ * queue identifier.
+ **/
+static inline void
+lpfc_debug_dump_eq_by_id(struct lpfc_hba *phba, int qid)
+{
+ int eq_idx;
+
+ for (eq_idx = 0; eq_idx < phba->cfg_fcp_eq_count; eq_idx++) {
+ if (phba->sli4_hba.fp_eq[eq_idx]->queue_id == qid)
+ break;
+ }
+
+ if (eq_idx < phba->cfg_fcp_eq_count) {
+ printk(KERN_ERR "FCP EQ[Idx:%d|Qid:%d]\n", eq_idx, qid);
+ lpfc_debug_dump_q(phba->sli4_hba.fp_eq[eq_idx]);
+ return;
+ }
+
+ if (phba->sli4_hba.sp_eq->queue_id == qid) {
+ printk(KERN_ERR "SP EQ[|Qid:%d]\n", qid);
+ lpfc_debug_dump_q(phba->sli4_hba.sp_eq);
+ }
+}
+
+void lpfc_debug_dump_all_queues(struct lpfc_hba *);
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 3407b39e0a3f..d54ae1999797 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -230,27 +230,43 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
INIT_LIST_HEAD(&pbuflist->list);
- icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
- icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
- icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
- icmd->un.elsreq64.remoteID = did; /* DID */
if (expectRsp) {
+ icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
+ icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
+ icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64));
+
+ icmd->un.elsreq64.remoteID = did; /* DID */
icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
icmd->ulpTimeout = phba->fc_ratov * 2;
} else {
- icmd->un.elsreq64.bdl.bdeSize = sizeof(struct ulp_bde64);
+ icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
+ icmd->un.xseq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
+ icmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
+ icmd->un.xseq64.bdl.bdeSize = sizeof(struct ulp_bde64);
+ icmd->un.xseq64.xmit_els_remoteID = did; /* DID */
icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX;
}
icmd->ulpBdeCount = 1;
icmd->ulpLe = 1;
icmd->ulpClass = CLASS3;
- if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
- icmd->un.elsreq64.myID = vport->fc_myDID;
+ /*
+ * If we have NPIV enabled, we want to send ELS traffic by VPI.
+ * For SLI4, since the driver controls VPIs we also want to include
+ * all ELS pt2pt protocol traffic as well.
+ */
+ if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) ||
+ ((phba->sli_rev == LPFC_SLI_REV4) &&
+ (vport->fc_flag & FC_PT2PT))) {
+
+ if (expectRsp) {
+ icmd->un.elsreq64.myID = vport->fc_myDID;
+
+ /* For ELS_REQUEST64_CR, use the VPI by default */
+ icmd->ulpContext = phba->vpi_ids[vport->vpi];
+ }
- /* For ELS_REQUEST64_CR, use the VPI by default */
- icmd->ulpContext = phba->vpi_ids[vport->vpi];
icmd->ulpCt_h = 0;
/* The CT field must be 0=INVALID_RPI for the ECHO cmd */
if (elscmd == ELS_CMD_ECHO)
@@ -438,9 +454,10 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport)
int rc = 0;
sp = &phba->fc_fabparam;
- /* move forward in case of SLI4 FC port loopback test */
+ /* move forward in case of SLI4 FC port loopback test and pt2pt mode */
if ((phba->sli_rev == LPFC_SLI_REV4) &&
- !(phba->link_flag & LS_LOOPBACK_MODE)) {
+ !(phba->link_flag & LS_LOOPBACK_MODE) &&
+ !(vport->fc_flag & FC_PT2PT)) {
ndlp = lpfc_findnode_did(vport, Fabric_DID);
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
rc = -ENODEV;
@@ -707,14 +724,17 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
lpfc_sli4_unreg_all_rpis(vport);
lpfc_mbx_unreg_vpi(vport);
spin_lock_irq(shost->host_lock);
- vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
- /*
- * If VPI is unreged, driver need to do INIT_VPI
- * before re-registering
- */
vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
spin_unlock_irq(shost->host_lock);
}
+
+ /*
+ * For SLI3 and SLI4, the VPI needs to be reregistered in
+ * response to this fabric parameter change event.
+ */
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+ spin_unlock_irq(shost->host_lock);
} else if ((phba->sli_rev == LPFC_SLI_REV4) &&
!(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
/*
@@ -817,6 +837,17 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
mempool_free(mbox, phba->mbox_mem_pool);
goto fail;
}
+
+ /*
+ * For SLI4, the VFI/VPI are registered AFTER the
+ * Nport with the higher WWPN sends the PLOGI with
+ * an assigned NPortId.
+ */
+
+ /* not equal */
+ if ((phba->sli_rev == LPFC_SLI_REV4) && rc)
+ lpfc_issue_reg_vfi(vport);
+
/* Decrement ndlp reference count indicating that ndlp can be
* safely released when other references to it are done.
*/
@@ -2972,7 +3003,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
* ABTS we cannot generate and RRQ.
*/
lpfc_set_rrq_active(phba, ndlp,
- cmdiocb->sli4_xritag, 0, 0);
+ cmdiocb->sli4_lxritag, 0, 0);
}
break;
case IOSTAT_LOCAL_REJECT:
@@ -3803,10 +3834,11 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
/* Xmit ELS ACC response tag <ulpIoTag> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
- "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
+ "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x "
+ "fc_flag x%x\n",
elsiocb->iotag, elsiocb->iocb.ulpContext,
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
- ndlp->nlp_rpi);
+ ndlp->nlp_rpi, vport->fc_flag);
if (ndlp->nlp_flag & NLP_LOGO_ACC) {
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_LOGO_ACC;
@@ -4936,8 +4968,6 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 1;
}
- did = Fabric_DID;
-
if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1))) {
/* For a FLOGI we accept, then if our portname is greater
* then the remote portname we initiate Nport login.
@@ -4976,26 +5006,82 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_PT2PT_PLOGI;
spin_unlock_irq(shost->host_lock);
+
+ /* If we have the high WWPN we can assign our own
+ * myDID; otherwise, we have to WAIT for a PLOGI
+ * from the remote NPort to find out what it
+ * will be.
+ */
+ vport->fc_myDID = PT2PT_LocalID;
}
+
+ /*
+ * The vport state should go to LPFC_FLOGI only
+ * AFTER we issue a FLOGI, not receive one.
+ */
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_PT2PT;
vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
spin_unlock_irq(shost->host_lock);
+
+ /*
+ * We temporarily set fc_myDID to make it look like we are
+ * a Fabric. This is done just so we end up with the right
+ * did / sid on the FLOGI ACC rsp.
+ */
+ did = vport->fc_myDID;
+ vport->fc_myDID = Fabric_DID;
+
} else {
/* Reject this request because invalid parameters */
stat.un.b.lsRjtRsvd0 = 0;
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
stat.un.b.vendorUnique = 0;
+
+ /*
+ * We temporarily set fc_myDID to make it look like we are
+ * a Fabric. This is done just so we end up with the right
+ * did / sid on the FLOGI LS_RJT rsp.
+ */
+ did = vport->fc_myDID;
+ vport->fc_myDID = Fabric_DID;
+
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
NULL);
+
+ /* Now lets put fc_myDID back to what its supposed to be */
+ vport->fc_myDID = did;
+
return 1;
}
/* Send back ACC */
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
+ /* Now lets put fc_myDID back to what its supposed to be */
+ vport->fc_myDID = did;
+
+ if (!(vport->fc_flag & FC_PT2PT_PLOGI)) {
+
+ mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+ if (!mbox)
+ goto fail;
+
+ lpfc_config_link(phba, mbox);
+
+ mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+ mbox->vport = vport;
+ rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+ if (rc == MBX_NOT_FINISHED) {
+ mempool_free(mbox, phba->mbox_mem_pool);
+ goto fail;
+ }
+ }
+
return 0;
+fail:
+ return 1;
}
/**
@@ -5176,7 +5262,6 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
cmdsize = sizeof(struct RLS_RSP) + sizeof(uint32_t);
- mempool_free(pmb, phba->mbox_mem_pool);
elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize,
lpfc_max_els_tries, ndlp,
ndlp->nlp_DID, ELS_CMD_ACC);
@@ -5184,8 +5269,10 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
/* Decrement the ndlp reference count from previous mbox command */
lpfc_nlp_put(ndlp);
- if (!elsiocb)
+ if (!elsiocb) {
+ mempool_free(pmb, phba->mbox_mem_pool);
return;
+ }
icmd = &elsiocb->iocb;
icmd->ulpContext = rxid;
@@ -5202,7 +5289,7 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
rls_rsp->primSeqErrCnt = cpu_to_be32(mb->un.varRdLnk.primSeqErrCnt);
rls_rsp->invalidXmitWord = cpu_to_be32(mb->un.varRdLnk.invalidXmitWord);
rls_rsp->crcCnt = cpu_to_be32(mb->un.varRdLnk.crcCnt);
-
+ mempool_free(pmb, phba->mbox_mem_pool);
/* Xmit ELS RLS ACC response tag <ulpIoTag> */
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS,
"2874 Xmit ELS RLS ACC response tag x%x xri x%x, "
@@ -5586,7 +5673,7 @@ lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
pcmd += sizeof(uint32_t);
els_rrq = (struct RRQ *) pcmd;
- bf_set(rrq_oxid, els_rrq, rrq->xritag);
+ bf_set(rrq_oxid, els_rrq, phba->sli4_hba.xri_ids[rrq->xritag]);
bf_set(rrq_rxid, els_rrq, rrq->rxid);
bf_set(rrq_did, els_rrq, vport->fc_myDID);
els_rrq->rrq = cpu_to_be32(els_rrq->rrq);
@@ -7873,7 +7960,9 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba,
sglq_entry->state = SGL_FREED;
spin_unlock(&phba->sli4_hba.abts_sgl_list_lock);
spin_unlock_irqrestore(&phba->hbalock, iflag);
- lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1);
+ lpfc_set_rrq_active(phba, ndlp,
+ sglq_entry->sli4_lxritag,
+ rxid, 1);
/* Check if TXQ queue needs to be serviced */
if (pring->txq_cnt)
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index b507536dc5b5..5bb269e224f6 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -713,6 +713,7 @@ lpfc_do_work(void *p)
int rc;
set_user_nice(current, -20);
+ current->flags |= PF_NOFREEZE;
phba->data_flags = 0;
while (!kthread_should_stop()) {
@@ -1094,7 +1095,7 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
/* Start discovery by sending a FLOGI. port_state is identically
* LPFC_FLOGI while waiting for FLOGI cmpl
*/
- if (vport->port_state != LPFC_FLOGI)
+ if (vport->port_state != LPFC_FLOGI || vport->fc_flag & FC_PT2PT_PLOGI)
lpfc_initial_flogi(vport);
return;
@@ -2881,9 +2882,14 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
}
if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
- /* For private loop just start discovery and we are done. */
- if ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
- !(vport->fc_flag & FC_PUBLIC_LOOP)) {
+ /*
+ * For private loop or for NPort pt2pt,
+ * just start discovery and we are done.
+ */
+ if ((vport->fc_flag & FC_PT2PT) ||
+ ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
+ !(vport->fc_flag & FC_PUBLIC_LOOP))) {
+
/* Use loop map to make discovery list */
lpfc_disc_list_loopmap(vport);
/* Start discovery */
@@ -5490,9 +5496,9 @@ lpfc_nlp_release(struct kref *kref)
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE,
- "0279 lpfc_nlp_release: ndlp:x%p "
+ "0279 lpfc_nlp_release: ndlp:x%p did %x "
"usgmap:x%x refcnt:%d\n",
- (void *)ndlp, ndlp->nlp_usg_map,
+ (void *)ndlp, ndlp->nlp_DID, ndlp->nlp_usg_map,
atomic_read(&ndlp->kref.refcount));
/* remove ndlp from action. */
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 5f280b5ae3db..41bb1d2fb625 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -3374,6 +3374,9 @@ typedef struct {
WORD5 w5; /* Header control/status word */
} XMT_SEQ_FIELDS64;
+/* This word is remote ports D_ID for XMIT_ELS_RSP64 */
+#define xmit_els_remoteID xrsqRo
+
/* IOCB Command template for 64 bit RCV_SEQUENCE64 */
typedef struct {
struct ulp_bde64 rcvBde;
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 91f09761bd32..f1946dfda5b4 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -228,19 +228,15 @@ struct lpfc_sli4_flags {
#define lpfc_idx_rsrc_rdy_MASK 0x00000001
#define lpfc_idx_rsrc_rdy_WORD word0
#define LPFC_IDX_RSRC_RDY 1
-#define lpfc_xri_rsrc_rdy_SHIFT 1
-#define lpfc_xri_rsrc_rdy_MASK 0x00000001
-#define lpfc_xri_rsrc_rdy_WORD word0
-#define LPFC_XRI_RSRC_RDY 1
-#define lpfc_rpi_rsrc_rdy_SHIFT 2
+#define lpfc_rpi_rsrc_rdy_SHIFT 1
#define lpfc_rpi_rsrc_rdy_MASK 0x00000001
#define lpfc_rpi_rsrc_rdy_WORD word0
#define LPFC_RPI_RSRC_RDY 1
-#define lpfc_vpi_rsrc_rdy_SHIFT 3
+#define lpfc_vpi_rsrc_rdy_SHIFT 2
#define lpfc_vpi_rsrc_rdy_MASK 0x00000001
#define lpfc_vpi_rsrc_rdy_WORD word0
#define LPFC_VPI_RSRC_RDY 1
-#define lpfc_vfi_rsrc_rdy_SHIFT 4
+#define lpfc_vfi_rsrc_rdy_SHIFT 3
#define lpfc_vfi_rsrc_rdy_MASK 0x00000001
#define lpfc_vfi_rsrc_rdy_WORD word0
#define LPFC_VFI_RSRC_RDY 1
@@ -3299,7 +3295,13 @@ struct els_request64_wqe {
struct xmit_els_rsp64_wqe {
struct ulp_bde64 bde;
uint32_t response_payload_len;
- uint32_t rsvd4;
+ uint32_t word4;
+#define els_rsp64_sid_SHIFT 0
+#define els_rsp64_sid_MASK 0x00FFFFFF
+#define els_rsp64_sid_WORD word4
+#define els_rsp64_sp_SHIFT 24
+#define els_rsp64_sp_MASK 0x00000001
+#define els_rsp64_sp_WORD word4
struct wqe_did wqe_dest;
struct wqe_common wqe_com; /* words 6-11 */
uint32_t word12;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 9598fdcb08ab..411ed48d79da 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -64,8 +64,8 @@ static int lpfc_sli4_queue_verify(struct lpfc_hba *);
static int lpfc_create_bootstrap_mbox(struct lpfc_hba *);
static int lpfc_setup_endian_order(struct lpfc_hba *);
static void lpfc_destroy_bootstrap_mbox(struct lpfc_hba *);
-static void lpfc_free_sgl_list(struct lpfc_hba *);
-static int lpfc_init_sgl_list(struct lpfc_hba *);
+static void lpfc_free_els_sgl_list(struct lpfc_hba *);
+static void lpfc_init_sgl_list(struct lpfc_hba *);
static int lpfc_init_active_sgl_array(struct lpfc_hba *);
static void lpfc_free_active_sgl(struct lpfc_hba *);
static int lpfc_hba_down_post_s3(struct lpfc_hba *phba);
@@ -2767,47 +2767,14 @@ lpfc_offline(struct lpfc_hba *phba)
}
/**
- * lpfc_scsi_buf_update - Update the scsi_buffers that are already allocated.
- * @phba: pointer to lpfc hba data structure.
- *
- * This routine goes through all the scsi buffers in the system and updates the
- * Physical XRIs assigned to the SCSI buffer because these may change after any
- * firmware reset
- *
- * Return codes
- * 0 - successful (for now, it always returns 0)
- **/
-int
-lpfc_scsi_buf_update(struct lpfc_hba *phba)
-{
- struct lpfc_scsi_buf *sb, *sb_next;
-
- spin_lock_irq(&phba->hbalock);
- spin_lock(&phba->scsi_buf_list_lock);
- list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) {
- sb->cur_iocbq.sli4_xritag =
- phba->sli4_hba.xri_ids[sb->cur_iocbq.sli4_lxritag];
- set_bit(sb->cur_iocbq.sli4_lxritag, phba->sli4_hba.xri_bmask);
- phba->sli4_hba.max_cfg_param.xri_used++;
- phba->sli4_hba.xri_count++;
- }
- spin_unlock(&phba->scsi_buf_list_lock);
- spin_unlock_irq(&phba->hbalock);
- return 0;
-}
-
-/**
* lpfc_scsi_free - Free all the SCSI buffers and IOCBs from driver lists
* @phba: pointer to lpfc hba data structure.
*
* This routine is to free all the SCSI buffers and IOCBs from the driver
* list back to kernel. It is called from lpfc_pci_remove_one to free
* the internal resources before the device is removed from the system.
- *
- * Return codes
- * 0 - successful (for now, it always returns 0)
**/
-static int
+static void
lpfc_scsi_free(struct lpfc_hba *phba)
{
struct lpfc_scsi_buf *sb, *sb_next;
@@ -2833,7 +2800,178 @@ lpfc_scsi_free(struct lpfc_hba *phba)
}
spin_unlock_irq(&phba->hbalock);
+}
+
+/**
+ * lpfc_sli4_xri_sgl_update - update xri-sgl sizing and mapping
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine first calculates the sizes of the current els and allocated
+ * scsi sgl lists, and then goes through all sgls to updates the physical
+ * XRIs assigned due to port function reset. During port initialization, the
+ * current els and allocated scsi sgl lists are 0s.
+ *
+ * Return codes
+ * 0 - successful (for now, it always returns 0)
+ **/
+int
+lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba)
+{
+ struct lpfc_sglq *sglq_entry = NULL, *sglq_entry_next = NULL;
+ struct lpfc_scsi_buf *psb = NULL, *psb_next = NULL;
+ uint16_t i, lxri, xri_cnt, els_xri_cnt, scsi_xri_cnt;
+ LIST_HEAD(els_sgl_list);
+ LIST_HEAD(scsi_sgl_list);
+ int rc;
+
+ /*
+ * update on pci function's els xri-sgl list
+ */
+ els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba);
+ if (els_xri_cnt > phba->sli4_hba.els_xri_cnt) {
+ /* els xri-sgl expanded */
+ xri_cnt = els_xri_cnt - phba->sli4_hba.els_xri_cnt;
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "3157 ELS xri-sgl count increased from "
+ "%d to %d\n", phba->sli4_hba.els_xri_cnt,
+ els_xri_cnt);
+ /* allocate the additional els sgls */
+ for (i = 0; i < xri_cnt; i++) {
+ sglq_entry = kzalloc(sizeof(struct lpfc_sglq),
+ GFP_KERNEL);
+ if (sglq_entry == NULL) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "2562 Failure to allocate an "
+ "ELS sgl entry:%d\n", i);
+ rc = -ENOMEM;
+ goto out_free_mem;
+ }
+ sglq_entry->buff_type = GEN_BUFF_TYPE;
+ sglq_entry->virt = lpfc_mbuf_alloc(phba, 0,
+ &sglq_entry->phys);
+ if (sglq_entry->virt == NULL) {
+ kfree(sglq_entry);
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "2563 Failure to allocate an "
+ "ELS mbuf:%d\n", i);
+ rc = -ENOMEM;
+ goto out_free_mem;
+ }
+ sglq_entry->sgl = sglq_entry->virt;
+ memset(sglq_entry->sgl, 0, LPFC_BPL_SIZE);
+ sglq_entry->state = SGL_FREED;
+ list_add_tail(&sglq_entry->list, &els_sgl_list);
+ }
+ spin_lock(&phba->hbalock);
+ list_splice_init(&els_sgl_list, &phba->sli4_hba.lpfc_sgl_list);
+ spin_unlock(&phba->hbalock);
+ } else if (els_xri_cnt < phba->sli4_hba.els_xri_cnt) {
+ /* els xri-sgl shrinked */
+ xri_cnt = phba->sli4_hba.els_xri_cnt - els_xri_cnt;
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "3158 ELS xri-sgl count decreased from "
+ "%d to %d\n", phba->sli4_hba.els_xri_cnt,
+ els_xri_cnt);
+ spin_lock_irq(&phba->hbalock);
+ list_splice_init(&phba->sli4_hba.lpfc_sgl_list, &els_sgl_list);
+ spin_unlock_irq(&phba->hbalock);
+ /* release extra els sgls from list */
+ for (i = 0; i < xri_cnt; i++) {
+ list_remove_head(&els_sgl_list,
+ sglq_entry, struct lpfc_sglq, list);
+ if (sglq_entry) {
+ lpfc_mbuf_free(phba, sglq_entry->virt,
+ sglq_entry->phys);
+ kfree(sglq_entry);
+ }
+ }
+ spin_lock_irq(&phba->hbalock);
+ list_splice_init(&els_sgl_list, &phba->sli4_hba.lpfc_sgl_list);
+ spin_unlock_irq(&phba->hbalock);
+ } else
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "3163 ELS xri-sgl count unchanged: %d\n",
+ els_xri_cnt);
+ phba->sli4_hba.els_xri_cnt = els_xri_cnt;
+
+ /* update xris to els sgls on the list */
+ sglq_entry = NULL;
+ sglq_entry_next = NULL;
+ list_for_each_entry_safe(sglq_entry, sglq_entry_next,
+ &phba->sli4_hba.lpfc_sgl_list, list) {
+ lxri = lpfc_sli4_next_xritag(phba);
+ if (lxri == NO_XRI) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "2400 Failed to allocate xri for "
+ "ELS sgl\n");
+ rc = -ENOMEM;
+ goto out_free_mem;
+ }
+ sglq_entry->sli4_lxritag = lxri;
+ sglq_entry->sli4_xritag = phba->sli4_hba.xri_ids[lxri];
+ }
+
+ /*
+ * update on pci function's allocated scsi xri-sgl list
+ */
+ phba->total_scsi_bufs = 0;
+
+ /* maximum number of xris available for scsi buffers */
+ phba->sli4_hba.scsi_xri_max = phba->sli4_hba.max_cfg_param.max_xri -
+ els_xri_cnt;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "2401 Current allocated SCSI xri-sgl count:%d, "
+ "maximum SCSI xri count:%d\n",
+ phba->sli4_hba.scsi_xri_cnt,
+ phba->sli4_hba.scsi_xri_max);
+
+ spin_lock_irq(&phba->scsi_buf_list_lock);
+ list_splice_init(&phba->lpfc_scsi_buf_list, &scsi_sgl_list);
+ spin_unlock_irq(&phba->scsi_buf_list_lock);
+
+ if (phba->sli4_hba.scsi_xri_cnt > phba->sli4_hba.scsi_xri_max) {
+ /* max scsi xri shrinked below the allocated scsi buffers */
+ scsi_xri_cnt = phba->sli4_hba.scsi_xri_cnt -
+ phba->sli4_hba.scsi_xri_max;
+ /* release the extra allocated scsi buffers */
+ for (i = 0; i < scsi_xri_cnt; i++) {
+ list_remove_head(&scsi_sgl_list, psb,
+ struct lpfc_scsi_buf, list);
+ pci_pool_free(phba->lpfc_scsi_dma_buf_pool, psb->data,
+ psb->dma_handle);
+ kfree(psb);
+ }
+ spin_lock_irq(&phba->scsi_buf_list_lock);
+ phba->sli4_hba.scsi_xri_cnt -= scsi_xri_cnt;
+ spin_unlock_irq(&phba->scsi_buf_list_lock);
+ }
+
+ /* update xris associated to remaining allocated scsi buffers */
+ psb = NULL;
+ psb_next = NULL;
+ list_for_each_entry_safe(psb, psb_next, &scsi_sgl_list, list) {
+ lxri = lpfc_sli4_next_xritag(phba);
+ if (lxri == NO_XRI) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "2560 Failed to allocate xri for "
+ "scsi buffer\n");
+ rc = -ENOMEM;
+ goto out_free_mem;
+ }
+ psb->cur_iocbq.sli4_lxritag = lxri;
+ psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri];
+ }
+ spin_lock(&phba->scsi_buf_list_lock);
+ list_splice_init(&scsi_sgl_list, &phba->lpfc_scsi_buf_list);
+ spin_unlock(&phba->scsi_buf_list_lock);
+
return 0;
+
+out_free_mem:
+ lpfc_free_els_sgl_list(phba);
+ lpfc_scsi_free(phba);
+ return rc;
}
/**
@@ -4636,18 +4774,15 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
if (rc)
goto out_free_bsmbx;
- /* Initialize and populate the iocb list per host */
- rc = lpfc_init_sgl_list(phba);
- if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "1400 Failed to initialize sgl list.\n");
- goto out_destroy_cq_event_pool;
- }
+ /* Initialize sgl lists per host */
+ lpfc_init_sgl_list(phba);
+
+ /* Allocate and initialize active sgl array */
rc = lpfc_init_active_sgl_array(phba);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"1430 Failed to initialize sgl list.\n");
- goto out_free_sgl_list;
+ goto out_destroy_cq_event_pool;
}
rc = lpfc_sli4_init_rpi_hdrs(phba);
if (rc) {
@@ -4722,8 +4857,6 @@ out_remove_rpi_hdrs:
lpfc_sli4_remove_rpi_hdrs(phba);
out_free_active_sgl:
lpfc_free_active_sgl(phba);
-out_free_sgl_list:
- lpfc_free_sgl_list(phba);
out_destroy_cq_event_pool:
lpfc_sli4_cq_event_pool_destroy(phba);
out_free_bsmbx:
@@ -4760,10 +4893,7 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
/* Free the ELS sgl list */
lpfc_free_active_sgl(phba);
- lpfc_free_sgl_list(phba);
-
- /* Free the SCSI sgl management array */
- kfree(phba->sli4_hba.lpfc_scsi_psb_array);
+ lpfc_free_els_sgl_list(phba);
/* Free the completion queue EQ event pool */
lpfc_sli4_cq_event_release_all(phba);
@@ -4990,29 +5120,42 @@ out_free_iocbq:
}
/**
- * lpfc_free_sgl_list - Free sgl list.
+ * lpfc_free_sgl_list - Free a given sgl list.
* @phba: pointer to lpfc hba data structure.
+ * @sglq_list: pointer to the head of sgl list.
*
- * This routine is invoked to free the driver's sgl list and memory.
+ * This routine is invoked to free a give sgl list and memory.
**/
-static void
-lpfc_free_sgl_list(struct lpfc_hba *phba)
+void
+lpfc_free_sgl_list(struct lpfc_hba *phba, struct list_head *sglq_list)
{
struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
+
+ list_for_each_entry_safe(sglq_entry, sglq_next, sglq_list, list) {
+ list_del(&sglq_entry->list);
+ lpfc_mbuf_free(phba, sglq_entry->virt, sglq_entry->phys);
+ kfree(sglq_entry);
+ }
+}
+
+/**
+ * lpfc_free_els_sgl_list - Free els sgl list.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to free the driver's els sgl list and memory.
+ **/
+static void
+lpfc_free_els_sgl_list(struct lpfc_hba *phba)
+{
LIST_HEAD(sglq_list);
+ /* Retrieve all els sgls from driver list */
spin_lock_irq(&phba->hbalock);
list_splice_init(&phba->sli4_hba.lpfc_sgl_list, &sglq_list);
spin_unlock_irq(&phba->hbalock);
- list_for_each_entry_safe(sglq_entry, sglq_next,
- &sglq_list, list) {
- list_del(&sglq_entry->list);
- lpfc_mbuf_free(phba, sglq_entry->virt, sglq_entry->phys);
- kfree(sglq_entry);
- phba->sli4_hba.total_sglq_bufs--;
- }
- kfree(phba->sli4_hba.lpfc_els_sgl_array);
+ /* Now free the sgl list */
+ lpfc_free_sgl_list(phba, &sglq_list);
}
/**
@@ -5057,99 +5200,19 @@ lpfc_free_active_sgl(struct lpfc_hba *phba)
* This routine is invoked to allocate and initizlize the driver's sgl
* list and set up the sgl xritag tag array accordingly.
*
- * Return codes
- * 0 - successful
- * other values - error
**/
-static int
+static void
lpfc_init_sgl_list(struct lpfc_hba *phba)
{
- struct lpfc_sglq *sglq_entry = NULL;
- int i;
- int els_xri_cnt;
-
- els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba);
- lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- "2400 ELS XRI count %d.\n",
- els_xri_cnt);
/* Initialize and populate the sglq list per host/VF. */
INIT_LIST_HEAD(&phba->sli4_hba.lpfc_sgl_list);
INIT_LIST_HEAD(&phba->sli4_hba.lpfc_abts_els_sgl_list);
- /* Sanity check on XRI management */
- if (phba->sli4_hba.max_cfg_param.max_xri <= els_xri_cnt) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2562 No room left for SCSI XRI allocation: "
- "max_xri=%d, els_xri=%d\n",
- phba->sli4_hba.max_cfg_param.max_xri,
- els_xri_cnt);
- return -ENOMEM;
- }
-
- /* Allocate memory for the ELS XRI management array */
- phba->sli4_hba.lpfc_els_sgl_array =
- kzalloc((sizeof(struct lpfc_sglq *) * els_xri_cnt),
- GFP_KERNEL);
-
- if (!phba->sli4_hba.lpfc_els_sgl_array) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2401 Failed to allocate memory for ELS "
- "XRI management array of size %d.\n",
- els_xri_cnt);
- return -ENOMEM;
- }
+ /* els xri-sgl book keeping */
+ phba->sli4_hba.els_xri_cnt = 0;
- /* Keep the SCSI XRI into the XRI management array */
- phba->sli4_hba.scsi_xri_max =
- phba->sli4_hba.max_cfg_param.max_xri - els_xri_cnt;
+ /* scsi xri-buffer book keeping */
phba->sli4_hba.scsi_xri_cnt = 0;
- phba->sli4_hba.lpfc_scsi_psb_array =
- kzalloc((sizeof(struct lpfc_scsi_buf *) *
- phba->sli4_hba.scsi_xri_max), GFP_KERNEL);
-
- if (!phba->sli4_hba.lpfc_scsi_psb_array) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2563 Failed to allocate memory for SCSI "
- "XRI management array of size %d.\n",
- phba->sli4_hba.scsi_xri_max);
- kfree(phba->sli4_hba.lpfc_els_sgl_array);
- return -ENOMEM;
- }
-
- for (i = 0; i < els_xri_cnt; i++) {
- sglq_entry = kzalloc(sizeof(struct lpfc_sglq), GFP_KERNEL);
- if (sglq_entry == NULL) {
- printk(KERN_ERR "%s: only allocated %d sgls of "
- "expected %d count. Unloading driver.\n",
- __func__, i, els_xri_cnt);
- goto out_free_mem;
- }
-
- sglq_entry->buff_type = GEN_BUFF_TYPE;
- sglq_entry->virt = lpfc_mbuf_alloc(phba, 0, &sglq_entry->phys);
- if (sglq_entry->virt == NULL) {
- kfree(sglq_entry);
- printk(KERN_ERR "%s: failed to allocate mbuf.\n"
- "Unloading driver.\n", __func__);
- goto out_free_mem;
- }
- sglq_entry->sgl = sglq_entry->virt;
- memset(sglq_entry->sgl, 0, LPFC_BPL_SIZE);
-
- /* The list order is used by later block SGL registraton */
- spin_lock_irq(&phba->hbalock);
- sglq_entry->state = SGL_FREED;
- list_add_tail(&sglq_entry->list, &phba->sli4_hba.lpfc_sgl_list);
- phba->sli4_hba.lpfc_els_sgl_array[i] = sglq_entry;
- phba->sli4_hba.total_sglq_bufs++;
- spin_unlock_irq(&phba->hbalock);
- }
- return 0;
-
-out_free_mem:
- kfree(phba->sli4_hba.lpfc_scsi_psb_array);
- lpfc_free_sgl_list(phba);
- return -ENOMEM;
}
/**
@@ -7320,9 +7383,11 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
phba->sli4_hba.u.if_type2.ERR2regaddr);
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2890 Port error detected during port "
- "reset(%d): port status reg 0x%x, "
+ "reset(%d): wait_tmo:%d ms, "
+ "port status reg 0x%x, "
"error 1=0x%x, error 2=0x%x\n",
- num_resets, reg_data.word0,
+ num_resets, rdy_chk*10,
+ reg_data.word0,
phba->work_status[0],
phba->work_status[1]);
rc = -ENODEV;
@@ -8694,8 +8759,11 @@ lpfc_pci_remove_one_s3(struct pci_dev *pdev)
/* Release all the vports against this physical port */
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
- for (i = 1; i <= phba->max_vports && vports[i] != NULL; i++)
+ for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
+ if (vports[i]->port_type == LPFC_PHYSICAL_PORT)
+ continue;
fc_vport_terminate(vports[i]->fc_vport);
+ }
lpfc_destroy_vport_work_array(phba, vports);
/* Remove FC host and then SCSI host with the physical port */
@@ -9115,8 +9183,12 @@ lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *phba)
return 50;
else if (max_xri <= 1024)
return 100;
- else
+ else if (max_xri <= 1536)
return 150;
+ else if (max_xri <= 2048)
+ return 200;
+ else
+ return 250;
} else
return 0;
}
@@ -9455,8 +9527,11 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
/* Release all the vports against this physical port */
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
- for (i = 1; i <= phba->max_vports && vports[i] != NULL; i++)
+ for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
+ if (vports[i]->port_type == LPFC_PHYSICAL_PORT)
+ continue;
fc_vport_terminate(vports[i]->fc_vport);
+ }
lpfc_destroy_vport_work_array(phba, vports);
/* Remove FC host and then SCSI host with the physical port */
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 15ca2a9a0cdd..9133a97f045f 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -367,8 +367,10 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 1;
}
+ /* Check for Nport to NPort pt2pt protocol */
if ((vport->fc_flag & FC_PT2PT) &&
!(vport->fc_flag & FC_PT2PT_PLOGI)) {
+
/* rcv'ed PLOGI decides what our NPortId will be */
vport->fc_myDID = icmd->un.rcvels.parmRo;
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
@@ -382,6 +384,13 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
mempool_free(mbox, phba->mbox_mem_pool);
goto out;
}
+ /*
+ * For SLI4, the VFI/VPI are registered AFTER the
+ * Nport with the higher WWPN sends us a PLOGI with
+ * our assigned NPortId.
+ */
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ lpfc_issue_reg_vfi(vport);
lpfc_can_disctmo(vport);
}
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 88f3a83dbd2e..66e09069f281 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -399,6 +399,14 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
num_rsrc_err = atomic_read(&phba->num_rsrc_err);
num_cmd_success = atomic_read(&phba->num_cmd_success);
+ /*
+ * The error and success command counters are global per
+ * driver instance. If another handler has already
+ * operated on this error event, just exit.
+ */
+ if (num_rsrc_err == 0)
+ return;
+
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
@@ -688,7 +696,8 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
rrq_empty = list_empty(&phba->active_rrq_list);
spin_unlock_irqrestore(&phba->hbalock, iflag);
if (ndlp) {
- lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1);
+ lpfc_set_rrq_active(phba, ndlp,
+ psb->cur_iocbq.sli4_lxritag, rxid, 1);
lpfc_sli4_abts_err_handler(phba, ndlp, axri);
}
lpfc_release_scsi_buf_s4(phba, psb);
@@ -718,72 +727,162 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
}
/**
- * lpfc_sli4_repost_scsi_sgl_list - Repsot the Scsi buffers sgl pages as block
+ * lpfc_sli4_post_scsi_sgl_list - Psot blocks of scsi buffer sgls from a list
* @phba: pointer to lpfc hba data structure.
+ * @post_sblist: pointer to the scsi buffer list.
*
- * This routine walks the list of scsi buffers that have been allocated and
- * repost them to the HBA by using SGL block post. This is needed after a
- * pci_function_reset/warm_start or start. The lpfc_hba_down_post_s4 routine
- * is responsible for moving all scsi buffers on the lpfc_abts_scsi_sgl_list
- * to the lpfc_scsi_buf_list. If the repost fails, reject all scsi buffers.
+ * This routine walks a list of scsi buffers that was passed in. It attempts
+ * to construct blocks of scsi buffer sgls which contains contiguous xris and
+ * uses the non-embedded SGL block post mailbox commands to post to the port.
+ * For single SCSI buffer sgl with non-contiguous xri, if any, it shall use
+ * embedded SGL post mailbox command for posting. The @post_sblist passed in
+ * must be local list, thus no lock is needed when manipulate the list.
*
- * Returns: 0 = success, non-zero failure.
+ * Returns: 0 = failure, non-zero number of successfully posted buffers.
**/
int
-lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
+lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba,
+ struct list_head *post_sblist, int sb_count)
{
- struct lpfc_scsi_buf *psb;
- int index, status, bcnt = 0, rcnt = 0, rc = 0;
- LIST_HEAD(sblist);
-
- for (index = 0; index < phba->sli4_hba.scsi_xri_cnt; index++) {
- psb = phba->sli4_hba.lpfc_scsi_psb_array[index];
- if (psb) {
- /* Remove from SCSI buffer list */
- list_del(&psb->list);
- /* Add it to a local SCSI buffer list */
- list_add_tail(&psb->list, &sblist);
- if (++rcnt == LPFC_NEMBED_MBOX_SGL_CNT) {
- bcnt = rcnt;
- rcnt = 0;
+ struct lpfc_scsi_buf *psb, *psb_next;
+ int status;
+ int post_cnt = 0, block_cnt = 0, num_posting = 0, num_posted = 0;
+ dma_addr_t pdma_phys_bpl1;
+ int last_xritag = NO_XRI;
+ LIST_HEAD(prep_sblist);
+ LIST_HEAD(blck_sblist);
+ LIST_HEAD(scsi_sblist);
+
+ /* sanity check */
+ if (sb_count <= 0)
+ return -EINVAL;
+
+ list_for_each_entry_safe(psb, psb_next, post_sblist, list) {
+ list_del_init(&psb->list);
+ block_cnt++;
+ if ((last_xritag != NO_XRI) &&
+ (psb->cur_iocbq.sli4_xritag != last_xritag + 1)) {
+ /* a hole in xri block, form a sgl posting block */
+ list_splice_init(&prep_sblist, &blck_sblist);
+ post_cnt = block_cnt - 1;
+ /* prepare list for next posting block */
+ list_add_tail(&psb->list, &prep_sblist);
+ block_cnt = 1;
+ } else {
+ /* prepare list for next posting block */
+ list_add_tail(&psb->list, &prep_sblist);
+ /* enough sgls for non-embed sgl mbox command */
+ if (block_cnt == LPFC_NEMBED_MBOX_SGL_CNT) {
+ list_splice_init(&prep_sblist, &blck_sblist);
+ post_cnt = block_cnt;
+ block_cnt = 0;
}
- } else
- /* A hole present in the XRI array, need to skip */
- bcnt = rcnt;
+ }
+ num_posting++;
+ last_xritag = psb->cur_iocbq.sli4_xritag;
- if (index == phba->sli4_hba.scsi_xri_cnt - 1)
- /* End of XRI array for SCSI buffer, complete */
- bcnt = rcnt;
+ /* end of repost sgl list condition for SCSI buffers */
+ if (num_posting == sb_count) {
+ if (post_cnt == 0) {
+ /* last sgl posting block */
+ list_splice_init(&prep_sblist, &blck_sblist);
+ post_cnt = block_cnt;
+ } else if (block_cnt == 1) {
+ /* last single sgl with non-contiguous xri */
+ if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
+ pdma_phys_bpl1 = psb->dma_phys_bpl +
+ SGL_PAGE_SIZE;
+ else
+ pdma_phys_bpl1 = 0;
+ status = lpfc_sli4_post_sgl(phba,
+ psb->dma_phys_bpl,
+ pdma_phys_bpl1,
+ psb->cur_iocbq.sli4_xritag);
+ if (status) {
+ /* failure, put on abort scsi list */
+ psb->exch_busy = 1;
+ } else {
+ /* success, put on SCSI buffer list */
+ psb->exch_busy = 0;
+ psb->status = IOSTAT_SUCCESS;
+ num_posted++;
+ }
+ /* success, put on SCSI buffer sgl list */
+ list_add_tail(&psb->list, &scsi_sblist);
+ }
+ }
- /* Continue until collect up to a nembed page worth of sgls */
- if (bcnt == 0)
+ /* continue until a nembed page worth of sgls */
+ if (post_cnt == 0)
continue;
- /* Now, post the SCSI buffer list sgls as a block */
- if (!phba->sli4_hba.extents_in_use)
- status = lpfc_sli4_post_scsi_sgl_block(phba,
- &sblist,
- bcnt);
- else
- status = lpfc_sli4_post_scsi_sgl_blk_ext(phba,
- &sblist,
- bcnt);
- /* Reset SCSI buffer count for next round of posting */
- bcnt = 0;
- while (!list_empty(&sblist)) {
- list_remove_head(&sblist, psb, struct lpfc_scsi_buf,
- list);
+
+ /* post block of SCSI buffer list sgls */
+ status = lpfc_sli4_post_scsi_sgl_block(phba, &blck_sblist,
+ post_cnt);
+
+ /* don't reset xirtag due to hole in xri block */
+ if (block_cnt == 0)
+ last_xritag = NO_XRI;
+
+ /* reset SCSI buffer post count for next round of posting */
+ post_cnt = 0;
+
+ /* put posted SCSI buffer-sgl posted on SCSI buffer sgl list */
+ while (!list_empty(&blck_sblist)) {
+ list_remove_head(&blck_sblist, psb,
+ struct lpfc_scsi_buf, list);
if (status) {
- /* Put this back on the abort scsi list */
+ /* failure, put on abort scsi list */
psb->exch_busy = 1;
- rc++;
} else {
+ /* success, put on SCSI buffer list */
psb->exch_busy = 0;
psb->status = IOSTAT_SUCCESS;
+ num_posted++;
}
- /* Put it back into the SCSI buffer list */
- lpfc_release_scsi_buf_s4(phba, psb);
+ list_add_tail(&psb->list, &scsi_sblist);
}
}
+ /* Push SCSI buffers with sgl posted to the availble list */
+ while (!list_empty(&scsi_sblist)) {
+ list_remove_head(&scsi_sblist, psb,
+ struct lpfc_scsi_buf, list);
+ lpfc_release_scsi_buf_s4(phba, psb);
+ }
+ return num_posted;
+}
+
+/**
+ * lpfc_sli4_repost_scsi_sgl_list - Repsot all the allocated scsi buffer sgls
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine walks the list of scsi buffers that have been allocated and
+ * repost them to the port by using SGL block post. This is needed after a
+ * pci_function_reset/warm_start or start. The lpfc_hba_down_post_s4 routine
+ * is responsible for moving all scsi buffers on the lpfc_abts_scsi_sgl_list
+ * to the lpfc_scsi_buf_list. If the repost fails, reject all scsi buffers.
+ *
+ * Returns: 0 = success, non-zero failure.
+ **/
+int
+lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
+{
+ LIST_HEAD(post_sblist);
+ int num_posted, rc = 0;
+
+ /* get all SCSI buffers need to repost to a local list */
+ spin_lock(&phba->scsi_buf_list_lock);
+ list_splice_init(&phba->lpfc_scsi_buf_list, &post_sblist);
+ spin_unlock(&phba->scsi_buf_list_lock);
+
+ /* post the list of scsi buffer sgls to port if available */
+ if (!list_empty(&post_sblist)) {
+ num_posted = lpfc_sli4_post_scsi_sgl_list(phba, &post_sblist,
+ phba->sli4_hba.scsi_xri_cnt);
+ /* failed to post any scsi buffer, return error */
+ if (num_posted == 0)
+ rc = -EIO;
+ }
return rc;
}
@@ -792,12 +891,13 @@ lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
* @vport: The virtual port for which this call being executed.
* @num_to_allocate: The requested number of buffers to allocate.
*
- * This routine allocates a scsi buffer for device with SLI-4 interface spec,
+ * This routine allocates scsi buffers for device with SLI-4 interface spec,
* the scsi buffer contains all the necessary information needed to initiate
- * a SCSI I/O.
+ * a SCSI I/O. After allocating up to @num_to_allocate SCSI buffers and put
+ * them on a list, it post them to the port by using SGL block post.
*
* Return codes:
- * int - number of scsi buffers that were allocated.
+ * int - number of scsi buffers that were allocated and posted.
* 0 = failure, less than num_to_alloc is a partial failure.
**/
static int
@@ -810,22 +910,21 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
dma_addr_t pdma_phys_fcp_cmd;
dma_addr_t pdma_phys_fcp_rsp;
dma_addr_t pdma_phys_bpl, pdma_phys_bpl1;
- uint16_t iotag, last_xritag = NO_XRI, lxri = 0;
- int status = 0, index;
- int bcnt;
- int non_sequential_xri = 0;
- LIST_HEAD(sblist);
+ uint16_t iotag, lxri = 0;
+ int bcnt, num_posted;
+ LIST_HEAD(prep_sblist);
+ LIST_HEAD(post_sblist);
+ LIST_HEAD(scsi_sblist);
for (bcnt = 0; bcnt < num_to_alloc; bcnt++) {
psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
if (!psb)
break;
-
/*
- * Get memory from the pci pool to map the virt space to pci bus
- * space for an I/O. The DMA buffer includes space for the
- * struct fcp_cmnd, struct fcp_rsp and the number of bde's
- * necessary to support the sg_tablesize.
+ * Get memory from the pci pool to map the virt space to
+ * pci bus space for an I/O. The DMA buffer includes space
+ * for the struct fcp_cmnd, struct fcp_rsp and the number
+ * of bde's necessary to support the sg_tablesize.
*/
psb->data = pci_pool_alloc(phba->lpfc_scsi_dma_buf_pool,
GFP_KERNEL, &psb->dma_handle);
@@ -833,8 +932,6 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
kfree(psb);
break;
}
-
- /* Initialize virtual ptrs to dma_buf region. */
memset(psb->data, 0, phba->cfg_sg_dma_buf_size);
/* Allocate iotag for psb->cur_iocbq. */
@@ -855,16 +952,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
}
psb->cur_iocbq.sli4_lxritag = lxri;
psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri];
- if (last_xritag != NO_XRI
- && psb->cur_iocbq.sli4_xritag != (last_xritag+1)) {
- non_sequential_xri = 1;
- } else
- list_add_tail(&psb->list, &sblist);
- last_xritag = psb->cur_iocbq.sli4_xritag;
-
- index = phba->sli4_hba.scsi_xri_cnt++;
psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP;
-
psb->fcp_bpl = psb->data;
psb->fcp_cmnd = (psb->data + phba->cfg_sg_dma_buf_size)
- (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
@@ -880,9 +968,9 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
pdma_phys_fcp_rsp = pdma_phys_fcp_cmd + sizeof(struct fcp_cmnd);
/*
- * The first two bdes are the FCP_CMD and FCP_RSP. The balance
- * are sg list bdes. Initialize the first two and leave the
- * rest for queuecommand.
+ * The first two bdes are the FCP_CMD and FCP_RSP.
+ * The balance are sg list bdes. Initialize the
+ * first two and leave the rest for queuecommand.
*/
sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_cmd));
sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_cmd));
@@ -917,62 +1005,31 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
iocb->ulpBdeCount = 1;
iocb->ulpLe = 1;
iocb->ulpClass = CLASS3;
- psb->cur_iocbq.context1 = psb;
+ psb->cur_iocbq.context1 = psb;
if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
pdma_phys_bpl1 = pdma_phys_bpl + SGL_PAGE_SIZE;
else
pdma_phys_bpl1 = 0;
psb->dma_phys_bpl = pdma_phys_bpl;
- phba->sli4_hba.lpfc_scsi_psb_array[index] = psb;
- if (non_sequential_xri) {
- status = lpfc_sli4_post_sgl(phba, pdma_phys_bpl,
- pdma_phys_bpl1,
- psb->cur_iocbq.sli4_xritag);
- if (status) {
- /* Put this back on the abort scsi list */
- psb->exch_busy = 1;
- } else {
- psb->exch_busy = 0;
- psb->status = IOSTAT_SUCCESS;
- }
- /* Put it back into the SCSI buffer list */
- lpfc_release_scsi_buf_s4(phba, psb);
- break;
- }
- }
- if (bcnt) {
- if (!phba->sli4_hba.extents_in_use)
- status = lpfc_sli4_post_scsi_sgl_block(phba,
- &sblist,
- bcnt);
- else
- status = lpfc_sli4_post_scsi_sgl_blk_ext(phba,
- &sblist,
- bcnt);
-
- if (status) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
- "3021 SCSI SGL post error %d\n",
- status);
- bcnt = 0;
- }
- /* Reset SCSI buffer count for next round of posting */
- while (!list_empty(&sblist)) {
- list_remove_head(&sblist, psb, struct lpfc_scsi_buf,
- list);
- if (status) {
- /* Put this back on the abort scsi list */
- psb->exch_busy = 1;
- } else {
- psb->exch_busy = 0;
- psb->status = IOSTAT_SUCCESS;
- }
- /* Put it back into the SCSI buffer list */
- lpfc_release_scsi_buf_s4(phba, psb);
- }
+
+ /* add the scsi buffer to a post list */
+ list_add_tail(&psb->list, &post_sblist);
+ spin_lock_irq(&phba->scsi_buf_list_lock);
+ phba->sli4_hba.scsi_xri_cnt++;
+ spin_unlock_irq(&phba->scsi_buf_list_lock);
}
+ lpfc_printf_log(phba, KERN_INFO, LOG_BG,
+ "3021 Allocate %d out of %d requested new SCSI "
+ "buffers\n", bcnt, num_to_alloc);
+
+ /* post the list of scsi buffer sgls to port if available */
+ if (!list_empty(&post_sblist))
+ num_posted = lpfc_sli4_post_scsi_sgl_list(phba,
+ &post_sblist, bcnt);
+ else
+ num_posted = 0;
- return bcnt + non_sequential_xri;
+ return num_posted;
}
/**
@@ -1043,7 +1100,7 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list,
list) {
if (lpfc_test_rrq_active(phba, ndlp,
- lpfc_cmd->cur_iocbq.sli4_xritag))
+ lpfc_cmd->cur_iocbq.sli4_lxritag))
continue;
list_del(&lpfc_cmd->list);
found = 1;
@@ -1897,7 +1954,9 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
dma_addr_t physaddr;
int i = 0, num_bde = 0, status;
int datadir = sc->sc_data_direction;
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
uint32_t rc;
+#endif
uint32_t checking = 1;
uint32_t reftag;
unsigned blksize;
@@ -2034,7 +2093,9 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
int datadir = sc->sc_data_direction;
unsigned char pgdone = 0, alldone = 0;
unsigned blksize;
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
uint32_t rc;
+#endif
uint32_t checking = 1;
uint32_t reftag;
uint8_t txop, rxop;
@@ -2253,7 +2314,9 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
uint32_t reftag;
unsigned blksize;
uint8_t txop, rxop;
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
uint32_t rc;
+#endif
uint32_t checking = 1;
uint32_t dma_len;
uint32_t dma_offset = 0;
@@ -2383,7 +2446,9 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
uint32_t reftag;
uint8_t txop, rxop;
uint32_t dma_len;
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
uint32_t rc;
+#endif
uint32_t checking = 1;
uint32_t dma_offset = 0;
int num_sge = 0;
@@ -3604,11 +3669,16 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
logit = LOG_FCP | LOG_FCP_UNDER;
lpfc_printf_vlog(vport, KERN_WARNING, logit,
"9030 FCP cmd x%x failed <%d/%d> "
- "status: x%x result: x%x Data: x%x x%x\n",
+ "status: x%x result: x%x "
+ "sid: x%x did: x%x oxid: x%x "
+ "Data: x%x x%x\n",
cmd->cmnd[0],
cmd->device ? cmd->device->id : 0xffff,
cmd->device ? cmd->device->lun : 0xffff,
lpfc_cmd->status, lpfc_cmd->result,
+ vport->fc_myDID, pnode->nlp_DID,
+ phba->sli_rev == LPFC_SLI_REV4 ?
+ lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff,
pIocbOut->iocb.ulpContext,
lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
@@ -3689,8 +3759,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
* ABTS we cannot generate and RRQ.
*/
lpfc_set_rrq_active(phba, pnode,
- lpfc_cmd->cur_iocbq.sli4_xritag,
- 0, 0);
+ lpfc_cmd->cur_iocbq.sli4_lxritag,
+ 0, 0);
}
/* else: fall through */
default:
@@ -4348,8 +4418,20 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
ret = fc_block_scsi_eh(cmnd);
if (ret)
return ret;
+
+ spin_lock_irq(&phba->hbalock);
+ /* driver queued commands are in process of being flushed */
+ if (phba->hba_flag & HBA_FCP_IOQ_FLUSH) {
+ spin_unlock_irq(&phba->hbalock);
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
+ "3168 SCSI Layer abort requested I/O has been "
+ "flushed by LLD.\n");
+ return FAILED;
+ }
+
lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
if (!lpfc_cmd) {
+ spin_unlock_irq(&phba->hbalock);
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
"2873 SCSI Layer I/O Abort Request IO CMPL Status "
"x%x ID %d LUN %d\n",
@@ -4357,23 +4439,34 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
return SUCCESS;
}
+ iocb = &lpfc_cmd->cur_iocbq;
+ /* the command is in process of being cancelled */
+ if (!(iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ)) {
+ spin_unlock_irq(&phba->hbalock);
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
+ "3169 SCSI Layer abort requested I/O has been "
+ "cancelled by LLD.\n");
+ return FAILED;
+ }
/*
* If pCmd field of the corresponding lpfc_scsi_buf structure
* points to a different SCSI command, then the driver has
* already completed this command, but the midlayer did not
- * see the completion before the eh fired. Just return
- * SUCCESS.
+ * see the completion before the eh fired. Just return SUCCESS.
*/
- iocb = &lpfc_cmd->cur_iocbq;
- if (lpfc_cmd->pCmd != cmnd)
- goto out;
+ if (lpfc_cmd->pCmd != cmnd) {
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
+ "3170 SCSI Layer abort requested I/O has been "
+ "completed by LLD.\n");
+ goto out_unlock;
+ }
BUG_ON(iocb->context1 != lpfc_cmd);
- abtsiocb = lpfc_sli_get_iocbq(phba);
+ abtsiocb = __lpfc_sli_get_iocbq(phba);
if (abtsiocb == NULL) {
ret = FAILED;
- goto out;
+ goto out_unlock;
}
/*
@@ -4405,6 +4498,9 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
abtsiocb->vport = vport;
+ /* no longer need the lock after this point */
+ spin_unlock_irq(&phba->hbalock);
+
if (lpfc_sli_issue_iocb(phba, LPFC_FCP_RING, abtsiocb, 0) ==
IOCB_ERROR) {
lpfc_sli_release_iocbq(phba, abtsiocb);
@@ -4421,10 +4517,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
wait_event_timeout(waitq,
(lpfc_cmd->pCmd != cmnd),
(2*vport->cfg_devloss_tmo*HZ));
-
- spin_lock_irq(shost->host_lock);
lpfc_cmd->waitq = NULL;
- spin_unlock_irq(shost->host_lock);
if (lpfc_cmd->pCmd == cmnd) {
ret = FAILED;
@@ -4434,8 +4527,11 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
"LUN %d\n",
ret, cmnd->device->id, cmnd->device->lun);
}
+ goto out;
- out:
+out_unlock:
+ spin_unlock_irq(&phba->hbalock);
+out:
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
"0749 SCSI Layer I/O Abort Request Status x%x ID %d "
"LUN %d\n", ret, cmnd->device->id,
@@ -4863,6 +4959,43 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
}
/**
+ * lpfc_host_reset_handler - scsi_host_template eh_host_reset_handler entry pt
+ * @cmnd: Pointer to scsi_cmnd data structure.
+ *
+ * This routine does host reset to the adaptor port. It brings the HBA
+ * offline, performs a board restart, and then brings the board back online.
+ * The lpfc_offline calls lpfc_sli_hba_down which will abort and local
+ * reject all outstanding SCSI commands to the host and error returned
+ * back to SCSI mid-level. As this will be SCSI mid-level's last resort
+ * of error handling, it will only return error if resetting of the adapter
+ * is not successful; in all other cases, will return success.
+ *
+ * Return code :
+ * 0x2003 - Error
+ * 0x2002 - Success
+ **/
+static int
+lpfc_host_reset_handler(struct scsi_cmnd *cmnd)
+{
+ struct Scsi_Host *shost = cmnd->device->host;
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ int rc, ret = SUCCESS;
+
+ lpfc_offline_prep(phba);
+ lpfc_offline(phba);
+ rc = lpfc_sli_brdrestart(phba);
+ if (rc)
+ ret = FAILED;
+ lpfc_online(phba);
+ lpfc_unblock_mgmt_io(phba);
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+ "3172 SCSI layer issued Host Reset Data: x%x\n", ret);
+ return ret;
+}
+
+/**
* lpfc_slave_alloc - scsi_host_template slave_alloc entry point
* @sdev: Pointer to scsi_device.
*
@@ -4994,6 +5127,7 @@ struct scsi_host_template lpfc_template = {
.eh_device_reset_handler = lpfc_device_reset_handler,
.eh_target_reset_handler = lpfc_target_reset_handler,
.eh_bus_reset_handler = lpfc_bus_reset_handler,
+ .eh_host_reset_handler = lpfc_host_reset_handler,
.slave_alloc = lpfc_slave_alloc,
.slave_configure = lpfc_slave_configure,
.slave_destroy = lpfc_slave_destroy,
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index dbaf5b963bff..b4720a109817 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -67,6 +67,8 @@ static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *,
struct hbq_dmabuf *);
static int lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *, struct lpfc_queue *,
struct lpfc_cqe *);
+static int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *, struct list_head *,
+ int);
static IOCB_t *
lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq)
@@ -500,7 +502,7 @@ lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
* allocation is successful, it returns pointer to the newly
* allocated iocb object else it returns NULL.
**/
-static struct lpfc_iocbq *
+struct lpfc_iocbq *
__lpfc_sli_get_iocbq(struct lpfc_hba *phba)
{
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
@@ -875,6 +877,9 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq)
} else if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) &&
!(piocbq->iocb_flag & LPFC_IO_LIBDFC))
ndlp = piocbq->context_un.ndlp;
+ else if ((piocbq->iocb.ulpCommand == CMD_ELS_REQUEST64_CR) &&
+ (piocbq->iocb_flag & LPFC_IO_LIBDFC))
+ ndlp = piocbq->context_un.ndlp;
else
ndlp = piocbq->context1;
@@ -883,7 +888,7 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq)
while (!found) {
if (!sglq)
return NULL;
- if (lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) {
+ if (lpfc_test_rrq_active(phba, ndlp, sglq->sli4_lxritag)) {
/* This xri has an rrq outstanding for this DID.
* put it back in the list and get another xri.
*/
@@ -1257,7 +1262,7 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb)
{
list_add_tail(&piocb->list, &pring->txcmplq);
- piocb->iocb_flag |= LPFC_IO_ON_Q;
+ piocb->iocb_flag |= LPFC_IO_ON_TXCMPLQ;
pring->txcmplq_cnt++;
if (pring->txcmplq_cnt > pring->txcmplq_max)
pring->txcmplq_max = pring->txcmplq_cnt;
@@ -2556,9 +2561,9 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
if (iotag != 0 && iotag <= phba->sli.last_iotag) {
cmd_iocb = phba->sli.iocbq_lookup[iotag];
list_del_init(&cmd_iocb->list);
- if (cmd_iocb->iocb_flag & LPFC_IO_ON_Q) {
+ if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) {
pring->txcmplq_cnt--;
- cmd_iocb->iocb_flag &= ~LPFC_IO_ON_Q;
+ cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ;
}
return cmd_iocb;
}
@@ -2591,14 +2596,14 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba,
if (iotag != 0 && iotag <= phba->sli.last_iotag) {
cmd_iocb = phba->sli.iocbq_lookup[iotag];
- list_del_init(&cmd_iocb->list);
- if (cmd_iocb->iocb_flag & LPFC_IO_ON_Q) {
- cmd_iocb->iocb_flag &= ~LPFC_IO_ON_Q;
+ if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) {
+ /* remove from txcmpl queue list */
+ list_del_init(&cmd_iocb->list);
+ cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ;
pring->txcmplq_cnt--;
+ return cmd_iocb;
}
- return cmd_iocb;
}
-
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0372 iotag x%x is out off range: max iotag (x%x)\n",
iotag, phba->sli.last_iotag);
@@ -3466,6 +3471,9 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba)
/* Retrieve everything on the txcmplq */
list_splice_init(&pring->txcmplq, &txcmplq);
pring->txcmplq_cnt = 0;
+
+ /* Indicate the I/O queues are flushed */
+ phba->hba_flag |= HBA_FCP_IOQ_FLUSH;
spin_unlock_irq(&phba->hbalock);
/* Flush the txq */
@@ -3877,6 +3885,7 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
uint16_t cfg_value;
+ int rc;
/* Reset HBA */
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
@@ -3905,12 +3914,12 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba)
/* Perform FCoE PCI function reset */
lpfc_sli4_queue_destroy(phba);
- lpfc_pci_function_reset(phba);
+ rc = lpfc_pci_function_reset(phba);
/* Restore PCI cmd register */
pci_write_config_word(phba->pcidev, PCI_COMMAND, cfg_value);
- return 0;
+ return rc;
}
/**
@@ -4002,6 +4011,7 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
uint32_t hba_aer_enabled;
+ int rc;
/* Restart HBA */
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
@@ -4011,7 +4021,7 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
/* Take PCIe device Advanced Error Reporting (AER) state */
hba_aer_enabled = phba->hba_flag & HBA_AER_ENABLED;
- lpfc_sli4_brdreset(phba);
+ rc = lpfc_sli4_brdreset(phba);
spin_lock_irq(&phba->hbalock);
phba->pport->stopped = 0;
@@ -4028,7 +4038,7 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
lpfc_hba_down_post(phba);
- return 0;
+ return rc;
}
/**
@@ -4967,7 +4977,12 @@ lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type,
&rsrc_info->u.rsp);
*extnt_size = bf_get(lpfc_mbx_get_rsrc_extent_info_size,
&rsrc_info->u.rsp);
- err_exit:
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "3162 Retrieved extents type-%d from port: count:%d, "
+ "size:%d\n", type, *extnt_count, *extnt_size);
+
+err_exit:
mempool_free(mbox, phba->mbox_mem_pool);
return rc;
}
@@ -5051,7 +5066,7 @@ lpfc_sli4_chk_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type)
* 0: if successful
**/
static int
-lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
+lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t extnt_cnt,
uint16_t type, bool *emb, LPFC_MBOXQ_t *mbox)
{
int rc = 0;
@@ -5060,7 +5075,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
uint32_t alloc_len, mbox_tmo;
/* Calculate the total requested length of the dma memory */
- req_len = *extnt_cnt * sizeof(uint16_t);
+ req_len = extnt_cnt * sizeof(uint16_t);
/*
* Calculate the size of an embedded mailbox. The uint32_t
@@ -5075,7 +5090,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
*/
*emb = LPFC_SLI4_MBX_EMBED;
if (req_len > emb_len) {
- req_len = *extnt_cnt * sizeof(uint16_t) +
+ req_len = extnt_cnt * sizeof(uint16_t) +
sizeof(union lpfc_sli4_cfg_shdr) +
sizeof(uint32_t);
*emb = LPFC_SLI4_MBX_NEMBED;
@@ -5091,7 +5106,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
"size (x%x)\n", alloc_len, req_len);
return -ENOMEM;
}
- rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, *extnt_cnt, type, *emb);
+ rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, extnt_cnt, type, *emb);
if (unlikely(rc))
return -EIO;
@@ -5149,17 +5164,15 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type)
return -ENOMEM;
}
- lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_INIT,
- "2903 Available Resource Extents "
- "for resource type 0x%x: Count: 0x%x, "
- "Size 0x%x\n", type, rsrc_cnt,
- rsrc_size);
+ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_INIT | LOG_SLI,
+ "2903 Post resource extents type-0x%x: "
+ "count:%d, size %d\n", type, rsrc_cnt, rsrc_size);
mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox)
return -ENOMEM;
- rc = lpfc_sli4_cfg_post_extnts(phba, &rsrc_cnt, type, &emb, mbox);
+ rc = lpfc_sli4_cfg_post_extnts(phba, rsrc_cnt, type, &emb, mbox);
if (unlikely(rc)) {
rc = -EIO;
goto err_exit;
@@ -5250,6 +5263,7 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type)
rc = -ENOMEM;
goto err_exit;
}
+ phba->sli4_hba.max_cfg_param.xri_used = 0;
phba->sli4_hba.xri_ids = kzalloc(rsrc_id_cnt *
sizeof(uint16_t),
GFP_KERNEL);
@@ -5420,7 +5434,6 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type)
case LPFC_RSC_TYPE_FCOE_XRI:
kfree(phba->sli4_hba.xri_bmask);
kfree(phba->sli4_hba.xri_ids);
- bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0);
list_for_each_entry_safe(rsrc_blk, rsrc_blk_next,
&phba->sli4_hba.lpfc_xri_blk_list, list) {
list_del_init(&rsrc_blk->list);
@@ -5612,7 +5625,6 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
goto free_vpi_ids;
}
phba->sli4_hba.max_cfg_param.xri_used = 0;
- phba->sli4_hba.xri_count = 0;
phba->sli4_hba.xri_ids = kzalloc(count *
sizeof(uint16_t),
GFP_KERNEL);
@@ -5694,7 +5706,6 @@ lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba)
bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0);
kfree(phba->sli4_hba.xri_bmask);
kfree(phba->sli4_hba.xri_ids);
- bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0);
kfree(phba->sli4_hba.vfi_bmask);
kfree(phba->sli4_hba.vfi_ids);
bf_set(lpfc_vfi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0);
@@ -5853,6 +5864,149 @@ lpfc_sli4_get_allocated_extnts(struct lpfc_hba *phba, uint16_t type,
}
/**
+ * lpfc_sli4_repost_els_sgl_list - Repsot the els buffers sgl pages as block
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine walks the list of els buffers that have been allocated and
+ * repost them to the port by using SGL block post. This is needed after a
+ * pci_function_reset/warm_start or start. It attempts to construct blocks
+ * of els buffer sgls which contains contiguous xris and uses the non-embedded
+ * SGL block post mailbox commands to post them to the port. For single els
+ * buffer sgl with non-contiguous xri, if any, it shall use embedded SGL post
+ * mailbox command for posting.
+ *
+ * Returns: 0 = success, non-zero failure.
+ **/
+static int
+lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba)
+{
+ struct lpfc_sglq *sglq_entry = NULL;
+ struct lpfc_sglq *sglq_entry_next = NULL;
+ struct lpfc_sglq *sglq_entry_first = NULL;
+ int status, post_cnt = 0, num_posted = 0, block_cnt = 0;
+ int last_xritag = NO_XRI;
+ LIST_HEAD(prep_sgl_list);
+ LIST_HEAD(blck_sgl_list);
+ LIST_HEAD(allc_sgl_list);
+ LIST_HEAD(post_sgl_list);
+ LIST_HEAD(free_sgl_list);
+
+ spin_lock(&phba->hbalock);
+ list_splice_init(&phba->sli4_hba.lpfc_sgl_list, &allc_sgl_list);
+ spin_unlock(&phba->hbalock);
+
+ list_for_each_entry_safe(sglq_entry, sglq_entry_next,
+ &allc_sgl_list, list) {
+ list_del_init(&sglq_entry->list);
+ block_cnt++;
+ if ((last_xritag != NO_XRI) &&
+ (sglq_entry->sli4_xritag != last_xritag + 1)) {
+ /* a hole in xri block, form a sgl posting block */
+ list_splice_init(&prep_sgl_list, &blck_sgl_list);
+ post_cnt = block_cnt - 1;
+ /* prepare list for next posting block */
+ list_add_tail(&sglq_entry->list, &prep_sgl_list);
+ block_cnt = 1;
+ } else {
+ /* prepare list for next posting block */
+ list_add_tail(&sglq_entry->list, &prep_sgl_list);
+ /* enough sgls for non-embed sgl mbox command */
+ if (block_cnt == LPFC_NEMBED_MBOX_SGL_CNT) {
+ list_splice_init(&prep_sgl_list,
+ &blck_sgl_list);
+ post_cnt = block_cnt;
+ block_cnt = 0;
+ }
+ }
+ num_posted++;
+
+ /* keep track of last sgl's xritag */
+ last_xritag = sglq_entry->sli4_xritag;
+
+ /* end of repost sgl list condition for els buffers */
+ if (num_posted == phba->sli4_hba.els_xri_cnt) {
+ if (post_cnt == 0) {
+ list_splice_init(&prep_sgl_list,
+ &blck_sgl_list);
+ post_cnt = block_cnt;
+ } else if (block_cnt == 1) {
+ status = lpfc_sli4_post_sgl(phba,
+ sglq_entry->phys, 0,
+ sglq_entry->sli4_xritag);
+ if (!status) {
+ /* successful, put sgl to posted list */
+ list_add_tail(&sglq_entry->list,
+ &post_sgl_list);
+ } else {
+ /* Failure, put sgl to free list */
+ lpfc_printf_log(phba, KERN_WARNING,
+ LOG_SLI,
+ "3159 Failed to post els "
+ "sgl, xritag:x%x\n",
+ sglq_entry->sli4_xritag);
+ list_add_tail(&sglq_entry->list,
+ &free_sgl_list);
+ spin_lock_irq(&phba->hbalock);
+ phba->sli4_hba.els_xri_cnt--;
+ spin_unlock_irq(&phba->hbalock);
+ }
+ }
+ }
+
+ /* continue until a nembed page worth of sgls */
+ if (post_cnt == 0)
+ continue;
+
+ /* post the els buffer list sgls as a block */
+ status = lpfc_sli4_post_els_sgl_list(phba, &blck_sgl_list,
+ post_cnt);
+
+ if (!status) {
+ /* success, put sgl list to posted sgl list */
+ list_splice_init(&blck_sgl_list, &post_sgl_list);
+ } else {
+ /* Failure, put sgl list to free sgl list */
+ sglq_entry_first = list_first_entry(&blck_sgl_list,
+ struct lpfc_sglq,
+ list);
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "3160 Failed to post els sgl-list, "
+ "xritag:x%x-x%x\n",
+ sglq_entry_first->sli4_xritag,
+ (sglq_entry_first->sli4_xritag +
+ post_cnt - 1));
+ list_splice_init(&blck_sgl_list, &free_sgl_list);
+ spin_lock_irq(&phba->hbalock);
+ phba->sli4_hba.els_xri_cnt -= post_cnt;
+ spin_unlock_irq(&phba->hbalock);
+ }
+
+ /* don't reset xirtag due to hole in xri block */
+ if (block_cnt == 0)
+ last_xritag = NO_XRI;
+
+ /* reset els sgl post count for next round of posting */
+ post_cnt = 0;
+ }
+
+ /* free the els sgls failed to post */
+ lpfc_free_sgl_list(phba, &free_sgl_list);
+
+ /* push els sgls posted to the availble list */
+ if (!list_empty(&post_sgl_list)) {
+ spin_lock(&phba->hbalock);
+ list_splice_init(&post_sgl_list,
+ &phba->sli4_hba.lpfc_sgl_list);
+ spin_unlock(&phba->hbalock);
+ } else {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "3161 Failure to post els sgl to port.\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+/**
* lpfc_sli4_hba_setup - SLI4 device intialization PCI function
* @phba: Pointer to HBA context object.
*
@@ -5923,6 +6077,8 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
else
phba->hba_flag &= ~HBA_FIP_SUPPORT;
+ phba->hba_flag &= ~HBA_FCP_IOQ_FLUSH;
+
if (phba->sli_rev != LPFC_SLI_REV4) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
"0376 READ_REV Error. SLI Level %d "
@@ -6063,8 +6219,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
"rc = x%x\n", rc);
goto out_free_mbox;
}
- /* update physical xri mappings in the scsi buffers */
- lpfc_scsi_buf_update(phba);
/* Read the port's service parameters. */
rc = lpfc_read_sparam(phba, mboxq, vport->vpi);
@@ -6105,28 +6259,26 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn);
fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn);
- /* Register SGL pool to the device using non-embedded mailbox command */
- if (!phba->sli4_hba.extents_in_use) {
- rc = lpfc_sli4_post_els_sgl_list(phba);
- if (unlikely(rc)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
- "0582 Error %d during els sgl post "
- "operation\n", rc);
- rc = -ENODEV;
- goto out_free_mbox;
- }
- } else {
- rc = lpfc_sli4_post_els_sgl_list_ext(phba);
- if (unlikely(rc)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
- "2560 Error %d during els sgl post "
- "operation\n", rc);
- rc = -ENODEV;
- goto out_free_mbox;
- }
+ /* update host els and scsi xri-sgl sizes and mappings */
+ rc = lpfc_sli4_xri_sgl_update(phba);
+ if (unlikely(rc)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ "1400 Failed to update xri-sgl size and "
+ "mapping: %d\n", rc);
+ goto out_free_mbox;
}
- /* Register SCSI SGL pool to the device */
+ /* register the els sgl pool to the port */
+ rc = lpfc_sli4_repost_els_sgl_list(phba);
+ if (unlikely(rc)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ "0582 Error %d during els sgl post "
+ "operation\n", rc);
+ rc = -ENODEV;
+ goto out_free_mbox;
+ }
+
+ /* register the allocated scsi sgl pool to the port */
rc = lpfc_sli4_repost_scsi_sgl_list(phba);
if (unlikely(rc)) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
@@ -7060,14 +7212,19 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
if (rc != MBX_SUCCESS)
lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
"(%d):2541 Mailbox command x%x "
- "(x%x/x%x) cannot issue Data: "
- "x%x x%x\n",
+ "(x%x/x%x) failure: "
+ "mqe_sta: x%x mcqe_sta: x%x/x%x "
+ "Data: x%x x%x\n,",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
lpfc_sli_config_mbox_subsys_get(phba,
mboxq),
lpfc_sli_config_mbox_opcode_get(phba,
mboxq),
+ bf_get(lpfc_mqe_status, &mboxq->u.mqe),
+ bf_get(lpfc_mcqe_status, &mboxq->mcqe),
+ bf_get(lpfc_mcqe_ext_status,
+ &mboxq->mcqe),
psli->sli_flag, flag);
return rc;
} else if (flag == MBX_POLL) {
@@ -7086,18 +7243,22 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
/* Successfully blocked, now issue sync mbox cmd */
rc = lpfc_sli4_post_sync_mbox(phba, mboxq);
if (rc != MBX_SUCCESS)
- lpfc_printf_log(phba, KERN_ERR,
+ lpfc_printf_log(phba, KERN_WARNING,
LOG_MBOX | LOG_SLI,
- "(%d):2597 Mailbox command "
- "x%x (x%x/x%x) cannot issue "
- "Data: x%x x%x\n",
- mboxq->vport ?
- mboxq->vport->vpi : 0,
+ "(%d):2597 Sync Mailbox command "
+ "x%x (x%x/x%x) failure: "
+ "mqe_sta: x%x mcqe_sta: x%x/x%x "
+ "Data: x%x x%x\n,",
+ mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
lpfc_sli_config_mbox_subsys_get(phba,
mboxq),
lpfc_sli_config_mbox_opcode_get(phba,
mboxq),
+ bf_get(lpfc_mqe_status, &mboxq->u.mqe),
+ bf_get(lpfc_mcqe_status, &mboxq->mcqe),
+ bf_get(lpfc_mcqe_ext_status,
+ &mboxq->mcqe),
psli->sli_flag, flag);
/* Unblock the async mailbox posting afterward */
lpfc_sli4_async_mbox_unblock(phba);
@@ -7712,7 +7873,10 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
switch (iocbq->iocb.ulpCommand) {
case CMD_ELS_REQUEST64_CR:
- ndlp = (struct lpfc_nodelist *)iocbq->context1;
+ if (iocbq->iocb_flag & LPFC_IO_LIBDFC)
+ ndlp = iocbq->context_un.ndlp;
+ else
+ ndlp = (struct lpfc_nodelist *)iocbq->context1;
if (!iocbq->iocb.ulpLe) {
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"2007 Only Limited Edition cmd Format"
@@ -7751,9 +7915,13 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
bf_set(els_req64_sp, &wqe->els_req, 1);
bf_set(els_req64_sid, &wqe->els_req,
iocbq->vport->fc_myDID);
+ if ((*pcmd == ELS_CMD_FLOGI) &&
+ !(phba->fc_topology ==
+ LPFC_TOPOLOGY_LOOP))
+ bf_set(els_req64_sid, &wqe->els_req, 0);
bf_set(wqe_ct, &wqe->els_req.wqe_com, 1);
bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com,
- phba->vpi_ids[phba->pport->vpi]);
+ phba->vpi_ids[iocbq->vport->vpi]);
} else if (pcmd && iocbq->context1) {
bf_set(wqe_ct, &wqe->els_req.wqe_com, 0);
bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com,
@@ -7908,11 +8076,25 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
/* words0-2 BDE memcpy */
/* word3 iocb=iotag32 wqe=response_payload_len */
wqe->xmit_els_rsp.response_payload_len = xmit_len;
- /* word4 iocb=did wge=rsvd. */
- wqe->xmit_els_rsp.rsvd4 = 0;
+ /* word4 */
+ wqe->xmit_els_rsp.word4 = 0;
/* word5 iocb=rsvd wge=did */
bf_set(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest,
- iocbq->iocb.un.elsreq64.remoteID);
+ iocbq->iocb.un.xseq64.xmit_els_remoteID);
+
+ if_type = bf_get(lpfc_sli_intf_if_type,
+ &phba->sli4_hba.sli_intf);
+ if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+ if (iocbq->vport->fc_flag & FC_PT2PT) {
+ bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1);
+ bf_set(els_rsp64_sid, &wqe->xmit_els_rsp,
+ iocbq->vport->fc_myDID);
+ if (iocbq->vport->fc_myDID == Fabric_DID) {
+ bf_set(wqe_els_did,
+ &wqe->xmit_els_rsp.wqe_dest, 0);
+ }
+ }
+ }
bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com,
((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l));
bf_set(wqe_pu, &wqe->xmit_els_rsp.wqe_com, iocbq->iocb.ulpPU);
@@ -7932,11 +8114,11 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
pcmd = (uint32_t *) (((struct lpfc_dmabuf *)
iocbq->context2)->virt);
if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
- bf_set(els_req64_sp, &wqe->els_req, 1);
- bf_set(els_req64_sid, &wqe->els_req,
+ bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1);
+ bf_set(els_rsp64_sid, &wqe->xmit_els_rsp,
iocbq->vport->fc_myDID);
- bf_set(wqe_ct, &wqe->els_req.wqe_com, 1);
- bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com,
+ bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com, 1);
+ bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com,
phba->vpi_ids[phba->pport->vpi]);
}
command_type = OTHER_COMMAND;
@@ -13080,9 +13262,7 @@ lpfc_sli4_alloc_xri(struct lpfc_hba *phba)
} else {
set_bit(xri, phba->sli4_hba.xri_bmask);
phba->sli4_hba.max_cfg_param.xri_used++;
- phba->sli4_hba.xri_count++;
}
-
spin_unlock_irq(&phba->hbalock);
return xri;
}
@@ -13098,7 +13278,6 @@ void
__lpfc_sli4_free_xri(struct lpfc_hba *phba, int xri)
{
if (test_and_clear_bit(xri, phba->sli4_hba.xri_bmask)) {
- phba->sli4_hba.xri_count--;
phba->sli4_hba.max_cfg_param.xri_used--;
}
}
@@ -13134,46 +13313,45 @@ lpfc_sli4_next_xritag(struct lpfc_hba *phba)
uint16_t xri_index;
xri_index = lpfc_sli4_alloc_xri(phba);
- if (xri_index != NO_XRI)
- return xri_index;
-
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2004 Failed to allocate XRI.last XRITAG is %d"
- " Max XRI is %d, Used XRI is %d\n",
- xri_index,
- phba->sli4_hba.max_cfg_param.max_xri,
- phba->sli4_hba.max_cfg_param.xri_used);
- return NO_XRI;
+ if (xri_index == NO_XRI)
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "2004 Failed to allocate XRI.last XRITAG is %d"
+ " Max XRI is %d, Used XRI is %d\n",
+ xri_index,
+ phba->sli4_hba.max_cfg_param.max_xri,
+ phba->sli4_hba.max_cfg_param.xri_used);
+ return xri_index;
}
/**
* lpfc_sli4_post_els_sgl_list - post a block of ELS sgls to the port.
* @phba: pointer to lpfc hba data structure.
+ * @post_sgl_list: pointer to els sgl entry list.
+ * @count: number of els sgl entries on the list.
*
* This routine is invoked to post a block of driver's sgl pages to the
* HBA using non-embedded mailbox command. No Lock is held. This routine
* is only called when the driver is loading and after all IO has been
* stopped.
**/
-int
-lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba)
+static int
+lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba,
+ struct list_head *post_sgl_list,
+ int post_cnt)
{
- struct lpfc_sglq *sglq_entry;
+ struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
struct lpfc_mbx_post_uembed_sgl_page1 *sgl;
struct sgl_page_pairs *sgl_pg_pairs;
void *viraddr;
LPFC_MBOXQ_t *mbox;
uint32_t reqlen, alloclen, pg_pairs;
uint32_t mbox_tmo;
- uint16_t xritag_start = 0, lxri = 0;
- int els_xri_cnt, rc = 0;
+ uint16_t xritag_start = 0;
+ int rc = 0;
uint32_t shdr_status, shdr_add_status;
union lpfc_sli4_cfg_shdr *shdr;
- /* The number of sgls to be posted */
- els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba);
-
- reqlen = els_xri_cnt * sizeof(struct sgl_page_pairs) +
+ reqlen = phba->sli4_hba.els_xri_cnt * sizeof(struct sgl_page_pairs) +
sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t);
if (reqlen > SLI4_PAGE_SIZE) {
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
@@ -13203,25 +13381,8 @@ lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba)
sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr;
sgl_pg_pairs = &sgl->sgl_pg_pairs;
- for (pg_pairs = 0; pg_pairs < els_xri_cnt; pg_pairs++) {
- sglq_entry = phba->sli4_hba.lpfc_els_sgl_array[pg_pairs];
-
- /*
- * Assign the sglq a physical xri only if the driver has not
- * initialized those resources. A port reset only needs
- * the sglq's posted.
- */
- if (bf_get(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags) !=
- LPFC_XRI_RSRC_RDY) {
- lxri = lpfc_sli4_next_xritag(phba);
- if (lxri == NO_XRI) {
- lpfc_sli4_mbox_cmd_free(phba, mbox);
- return -ENOMEM;
- }
- sglq_entry->sli4_lxritag = lxri;
- sglq_entry->sli4_xritag = phba->sli4_hba.xri_ids[lxri];
- }
-
+ pg_pairs = 0;
+ list_for_each_entry_safe(sglq_entry, sglq_next, post_sgl_list, list) {
/* Set up the sge entry */
sgl_pg_pairs->sgl_pg0_addr_lo =
cpu_to_le32(putPaddrLow(sglq_entry->phys));
@@ -13236,11 +13397,12 @@ lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba)
if (pg_pairs == 0)
xritag_start = sglq_entry->sli4_xritag;
sgl_pg_pairs++;
+ pg_pairs++;
}
/* Complete initialization and perform endian conversion. */
bf_set(lpfc_post_sgl_pages_xri, sgl, xritag_start);
- bf_set(lpfc_post_sgl_pages_xricnt, sgl, els_xri_cnt);
+ bf_set(lpfc_post_sgl_pages_xricnt, sgl, phba->sli4_hba.els_xri_cnt);
sgl->word0 = cpu_to_le32(sgl->word0);
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
@@ -13260,183 +13422,6 @@ lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba)
shdr_status, shdr_add_status, rc);
rc = -ENXIO;
}
-
- if (rc == 0)
- bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags,
- LPFC_XRI_RSRC_RDY);
- return rc;
-}
-
-/**
- * lpfc_sli4_post_els_sgl_list_ext - post a block of ELS sgls to the port.
- * @phba: pointer to lpfc hba data structure.
- *
- * This routine is invoked to post a block of driver's sgl pages to the
- * HBA using non-embedded mailbox command. No Lock is held. This routine
- * is only called when the driver is loading and after all IO has been
- * stopped.
- **/
-int
-lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba)
-{
- struct lpfc_sglq *sglq_entry;
- struct lpfc_mbx_post_uembed_sgl_page1 *sgl;
- struct sgl_page_pairs *sgl_pg_pairs;
- void *viraddr;
- LPFC_MBOXQ_t *mbox;
- uint32_t reqlen, alloclen, index;
- uint32_t mbox_tmo;
- uint16_t rsrc_start, rsrc_size, els_xri_cnt, post_els_xri_cnt;
- uint16_t xritag_start = 0, lxri = 0;
- struct lpfc_rsrc_blks *rsrc_blk;
- int cnt, ttl_cnt, rc = 0;
- int loop_cnt;
- uint32_t shdr_status, shdr_add_status;
- union lpfc_sli4_cfg_shdr *shdr;
-
- /* The number of sgls to be posted */
- els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba);
-
- reqlen = els_xri_cnt * sizeof(struct sgl_page_pairs) +
- sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t);
- if (reqlen > SLI4_PAGE_SIZE) {
- lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
- "2989 Block sgl registration required DMA "
- "size (%d) great than a page\n", reqlen);
- return -ENOMEM;
- }
-
- cnt = 0;
- ttl_cnt = 0;
- post_els_xri_cnt = els_xri_cnt;
- list_for_each_entry(rsrc_blk, &phba->sli4_hba.lpfc_xri_blk_list,
- list) {
- rsrc_start = rsrc_blk->rsrc_start;
- rsrc_size = rsrc_blk->rsrc_size;
-
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "3014 Working ELS Extent start %d, cnt %d\n",
- rsrc_start, rsrc_size);
-
- loop_cnt = min(post_els_xri_cnt, rsrc_size);
- if (loop_cnt < post_els_xri_cnt) {
- post_els_xri_cnt -= loop_cnt;
- ttl_cnt += loop_cnt;
- } else
- ttl_cnt += post_els_xri_cnt;
-
- mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
- if (!mbox)
- return -ENOMEM;
- /*
- * Allocate DMA memory and set up the non-embedded mailbox
- * command.
- */
- alloclen = lpfc_sli4_config(phba, mbox,
- LPFC_MBOX_SUBSYSTEM_FCOE,
- LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES,
- reqlen, LPFC_SLI4_MBX_NEMBED);
- if (alloclen < reqlen) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2987 Allocated DMA memory size (%d) "
- "is less than the requested DMA memory "
- "size (%d)\n", alloclen, reqlen);
- lpfc_sli4_mbox_cmd_free(phba, mbox);
- return -ENOMEM;
- }
-
- /* Set up the SGL pages in the non-embedded DMA pages */
- viraddr = mbox->sge_array->addr[0];
- sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr;
- sgl_pg_pairs = &sgl->sgl_pg_pairs;
-
- /*
- * The starting resource may not begin at zero. Control
- * the loop variants via the block resource parameters,
- * but handle the sge pointers with a zero-based index
- * that doesn't get reset per loop pass.
- */
- for (index = rsrc_start;
- index < rsrc_start + loop_cnt;
- index++) {
- sglq_entry = phba->sli4_hba.lpfc_els_sgl_array[cnt];
-
- /*
- * Assign the sglq a physical xri only if the driver
- * has not initialized those resources. A port reset
- * only needs the sglq's posted.
- */
- if (bf_get(lpfc_xri_rsrc_rdy,
- &phba->sli4_hba.sli4_flags) !=
- LPFC_XRI_RSRC_RDY) {
- lxri = lpfc_sli4_next_xritag(phba);
- if (lxri == NO_XRI) {
- lpfc_sli4_mbox_cmd_free(phba, mbox);
- rc = -ENOMEM;
- goto err_exit;
- }
- sglq_entry->sli4_lxritag = lxri;
- sglq_entry->sli4_xritag =
- phba->sli4_hba.xri_ids[lxri];
- }
-
- /* Set up the sge entry */
- sgl_pg_pairs->sgl_pg0_addr_lo =
- cpu_to_le32(putPaddrLow(sglq_entry->phys));
- sgl_pg_pairs->sgl_pg0_addr_hi =
- cpu_to_le32(putPaddrHigh(sglq_entry->phys));
- sgl_pg_pairs->sgl_pg1_addr_lo =
- cpu_to_le32(putPaddrLow(0));
- sgl_pg_pairs->sgl_pg1_addr_hi =
- cpu_to_le32(putPaddrHigh(0));
-
- /* Track the starting physical XRI for the mailbox. */
- if (index == rsrc_start)
- xritag_start = sglq_entry->sli4_xritag;
- sgl_pg_pairs++;
- cnt++;
- }
-
- /* Complete initialization and perform endian conversion. */
- rsrc_blk->rsrc_used += loop_cnt;
- bf_set(lpfc_post_sgl_pages_xri, sgl, xritag_start);
- bf_set(lpfc_post_sgl_pages_xricnt, sgl, loop_cnt);
- sgl->word0 = cpu_to_le32(sgl->word0);
-
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "3015 Post ELS Extent SGL, start %d, "
- "cnt %d, used %d\n",
- xritag_start, loop_cnt, rsrc_blk->rsrc_used);
- if (!phba->sli4_hba.intr_enable)
- rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
- else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
- rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
- }
- shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
- shdr_status = bf_get(lpfc_mbox_hdr_status,
- &shdr->response);
- shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
- &shdr->response);
- if (rc != MBX_TIMEOUT)
- lpfc_sli4_mbox_cmd_free(phba, mbox);
- if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2988 POST_SGL_BLOCK mailbox "
- "command failed status x%x "
- "add_status x%x mbx status x%x\n",
- shdr_status, shdr_add_status, rc);
- rc = -ENXIO;
- goto err_exit;
- }
- if (ttl_cnt >= els_xri_cnt)
- break;
- }
-
- err_exit:
- if (rc == 0)
- bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags,
- LPFC_XRI_RSRC_RDY);
return rc;
}
@@ -13452,8 +13437,9 @@ lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba)
*
**/
int
-lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist,
- int cnt)
+lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba,
+ struct list_head *sblist,
+ int count)
{
struct lpfc_scsi_buf *psb;
struct lpfc_mbx_post_uembed_sgl_page1 *sgl;
@@ -13469,7 +13455,7 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist,
union lpfc_sli4_cfg_shdr *shdr;
/* Calculate the requested length of the dma memory */
- reqlen = cnt * sizeof(struct sgl_page_pairs) +
+ reqlen = count * sizeof(struct sgl_page_pairs) +
sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t);
if (reqlen > SLI4_PAGE_SIZE) {
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
@@ -13553,169 +13539,6 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist,
}
/**
- * lpfc_sli4_post_scsi_sgl_blk_ext - post a block of scsi sgls to the port.
- * @phba: pointer to lpfc hba data structure.
- * @sblist: pointer to scsi buffer list.
- * @count: number of scsi buffers on the list.
- *
- * This routine is invoked to post a block of @count scsi sgl pages from a
- * SCSI buffer list @sblist to the HBA using non-embedded mailbox command.
- * No Lock is held.
- *
- **/
-int
-lpfc_sli4_post_scsi_sgl_blk_ext(struct lpfc_hba *phba, struct list_head *sblist,
- int cnt)
-{
- struct lpfc_scsi_buf *psb = NULL;
- struct lpfc_mbx_post_uembed_sgl_page1 *sgl;
- struct sgl_page_pairs *sgl_pg_pairs;
- void *viraddr;
- LPFC_MBOXQ_t *mbox;
- uint32_t reqlen, alloclen, pg_pairs;
- uint32_t mbox_tmo;
- uint16_t xri_start = 0, scsi_xri_start;
- uint16_t rsrc_range;
- int rc = 0, avail_cnt;
- uint32_t shdr_status, shdr_add_status;
- dma_addr_t pdma_phys_bpl1;
- union lpfc_sli4_cfg_shdr *shdr;
- struct lpfc_rsrc_blks *rsrc_blk;
- uint32_t xri_cnt = 0;
-
- /* Calculate the total requested length of the dma memory */
- reqlen = cnt * sizeof(struct sgl_page_pairs) +
- sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t);
- if (reqlen > SLI4_PAGE_SIZE) {
- lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
- "2932 Block sgl registration required DMA "
- "size (%d) great than a page\n", reqlen);
- return -ENOMEM;
- }
-
- /*
- * The use of extents requires the driver to post the sgl headers
- * in multiple postings to meet the contiguous resource assignment.
- */
- psb = list_prepare_entry(psb, sblist, list);
- scsi_xri_start = phba->sli4_hba.scsi_xri_start;
- list_for_each_entry(rsrc_blk, &phba->sli4_hba.lpfc_xri_blk_list,
- list) {
- rsrc_range = rsrc_blk->rsrc_start + rsrc_blk->rsrc_size;
- if (rsrc_range < scsi_xri_start)
- continue;
- else if (rsrc_blk->rsrc_used >= rsrc_blk->rsrc_size)
- continue;
- else
- avail_cnt = rsrc_blk->rsrc_size - rsrc_blk->rsrc_used;
-
- reqlen = (avail_cnt * sizeof(struct sgl_page_pairs)) +
- sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t);
- /*
- * Allocate DMA memory and set up the non-embedded mailbox
- * command. The mbox is used to post an SGL page per loop
- * but the DMA memory has a use-once semantic so the mailbox
- * is used and freed per loop pass.
- */
- mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
- if (!mbox) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2933 Failed to allocate mbox cmd "
- "memory\n");
- return -ENOMEM;
- }
- alloclen = lpfc_sli4_config(phba, mbox,
- LPFC_MBOX_SUBSYSTEM_FCOE,
- LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES,
- reqlen,
- LPFC_SLI4_MBX_NEMBED);
- if (alloclen < reqlen) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2934 Allocated DMA memory size (%d) "
- "is less than the requested DMA memory "
- "size (%d)\n", alloclen, reqlen);
- lpfc_sli4_mbox_cmd_free(phba, mbox);
- return -ENOMEM;
- }
-
- /* Get the first SGE entry from the non-embedded DMA memory */
- viraddr = mbox->sge_array->addr[0];
-
- /* Set up the SGL pages in the non-embedded DMA pages */
- sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr;
- sgl_pg_pairs = &sgl->sgl_pg_pairs;
-
- /* pg_pairs tracks posted SGEs per loop iteration. */
- pg_pairs = 0;
- list_for_each_entry_continue(psb, sblist, list) {
- /* Set up the sge entry */
- sgl_pg_pairs->sgl_pg0_addr_lo =
- cpu_to_le32(putPaddrLow(psb->dma_phys_bpl));
- sgl_pg_pairs->sgl_pg0_addr_hi =
- cpu_to_le32(putPaddrHigh(psb->dma_phys_bpl));
- if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
- pdma_phys_bpl1 = psb->dma_phys_bpl +
- SGL_PAGE_SIZE;
- else
- pdma_phys_bpl1 = 0;
- sgl_pg_pairs->sgl_pg1_addr_lo =
- cpu_to_le32(putPaddrLow(pdma_phys_bpl1));
- sgl_pg_pairs->sgl_pg1_addr_hi =
- cpu_to_le32(putPaddrHigh(pdma_phys_bpl1));
- /* Keep the first xri for this extent. */
- if (pg_pairs == 0)
- xri_start = psb->cur_iocbq.sli4_xritag;
- sgl_pg_pairs++;
- pg_pairs++;
- xri_cnt++;
-
- /*
- * Track two exit conditions - the loop has constructed
- * all of the caller's SGE pairs or all available
- * resource IDs in this extent are consumed.
- */
- if ((xri_cnt == cnt) || (pg_pairs >= avail_cnt))
- break;
- }
- rsrc_blk->rsrc_used += pg_pairs;
- bf_set(lpfc_post_sgl_pages_xri, sgl, xri_start);
- bf_set(lpfc_post_sgl_pages_xricnt, sgl, pg_pairs);
-
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "3016 Post SCSI Extent SGL, start %d, cnt %d "
- "blk use %d\n",
- xri_start, pg_pairs, rsrc_blk->rsrc_used);
- /* Perform endian conversion if necessary */
- sgl->word0 = cpu_to_le32(sgl->word0);
- if (!phba->sli4_hba.intr_enable)
- rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
- else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
- rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
- }
- shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
- shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
- shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
- &shdr->response);
- if (rc != MBX_TIMEOUT)
- lpfc_sli4_mbox_cmd_free(phba, mbox);
- if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2935 POST_SGL_BLOCK mailbox command "
- "failed status x%x add_status x%x "
- "mbx status x%x\n",
- shdr_status, shdr_add_status, rc);
- return -ENXIO;
- }
-
- /* Post only what is requested. */
- if (xri_cnt >= cnt)
- break;
- }
- return rc;
-}
-
-/**
* lpfc_fc_frame_check - Check that this frame is a valid frame to handle
* @phba: pointer to lpfc_hba struct that the frame was received on
* @fc_hdr: A pointer to the FC Header data (In Big Endian Format)
@@ -13839,8 +13662,13 @@ lpfc_fc_frame_to_vport(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr,
uint32_t did = (fc_hdr->fh_d_id[0] << 16 |
fc_hdr->fh_d_id[1] << 8 |
fc_hdr->fh_d_id[2]);
+
if (did == Fabric_DID)
return phba->pport;
+ if ((phba->pport->fc_flag & FC_PT2PT) &&
+ !(phba->link_state == LPFC_HBA_READY))
+ return phba->pport;
+
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
@@ -14133,7 +13961,6 @@ lpfc_sli4_xri_inrange(struct lpfc_hba *phba,
return NO_XRI;
}
-
/**
* lpfc_sli4_seq_abort_rsp - bls rsp to sequence abort
* @phba: Pointer to HBA context object.
@@ -14148,7 +13975,7 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
{
struct lpfc_iocbq *ctiocb = NULL;
struct lpfc_nodelist *ndlp;
- uint16_t oxid, rxid;
+ uint16_t oxid, rxid, xri, lxri;
uint32_t sid, fctl;
IOCB_t *icmd;
int rc;
@@ -14167,8 +13994,6 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
"SID:x%x\n", oxid, sid);
return;
}
- if (lpfc_sli4_xri_inrange(phba, rxid))
- lpfc_set_rrq_active(phba, ndlp, rxid, oxid, 0);
/* Allocate buffer for rsp iocb */
ctiocb = lpfc_sli_get_iocbq(phba);
@@ -14199,13 +14024,24 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
ctiocb->sli4_lxritag = NO_XRI;
ctiocb->sli4_xritag = NO_XRI;
+ if (fctl & FC_FC_EX_CTX)
+ /* Exchange responder sent the abort so we
+ * own the oxid.
+ */
+ xri = oxid;
+ else
+ xri = rxid;
+ lxri = lpfc_sli4_xri_inrange(phba, xri);
+ if (lxri != NO_XRI)
+ lpfc_set_rrq_active(phba, ndlp, lxri,
+ (xri == oxid) ? rxid : oxid, 0);
/* If the oxid maps to the FCP XRI range or if it is out of range,
* send a BLS_RJT. The driver no longer has that exchange.
* Override the IOCB for a BA_RJT.
*/
- if (oxid > (phba->sli4_hba.max_cfg_param.max_xri +
+ if (xri > (phba->sli4_hba.max_cfg_param.max_xri +
phba->sli4_hba.max_cfg_param.xri_base) ||
- oxid > (lpfc_sli4_get_els_iocb_cnt(phba) +
+ xri > (lpfc_sli4_get_els_iocb_cnt(phba) +
phba->sli4_hba.max_cfg_param.xri_base)) {
icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT;
bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0);
@@ -14377,7 +14213,15 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
/* Initialize the first IOCB. */
first_iocbq->iocb.unsli3.rcvsli3.acc_len = 0;
first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS;
- first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX;
+
+ /* Check FC Header to see what TYPE of frame we are rcv'ing */
+ if (sli4_type_from_fc_hdr(fc_hdr) == FC_TYPE_ELS) {
+ first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_ELS64_CX;
+ first_iocbq->iocb.un.rcvels.parmRo =
+ sli4_did_from_fc_hdr(fc_hdr);
+ first_iocbq->iocb.ulpPU = PARM_NPIV_DID;
+ } else
+ first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX;
first_iocbq->iocb.ulpContext = NO_XRI;
first_iocbq->iocb.unsli3.rcvsli3.ox_id =
be16_to_cpu(fc_hdr->fh_ox_id);
@@ -14507,6 +14351,7 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
struct fc_frame_header *fc_hdr;
struct lpfc_vport *vport;
uint32_t fcfi;
+ uint32_t did;
/* Process each received buffer */
fc_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt;
@@ -14522,12 +14367,32 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
else
fcfi = bf_get(lpfc_rcqe_fcf_id,
&dmabuf->cq_event.cqe.rcqe_cmpl);
+
vport = lpfc_fc_frame_to_vport(phba, fc_hdr, fcfi);
- if (!vport || !(vport->vpi_state & LPFC_VPI_REGISTERED)) {
+ if (!vport) {
/* throw out the frame */
lpfc_in_buf_free(phba, &dmabuf->dbuf);
return;
}
+
+ /* d_id this frame is directed to */
+ did = sli4_did_from_fc_hdr(fc_hdr);
+
+ /* vport is registered unless we rcv a FLOGI directed to Fabric_DID */
+ if (!(vport->vpi_state & LPFC_VPI_REGISTERED) &&
+ (did != Fabric_DID)) {
+ /*
+ * Throw out the frame if we are not pt2pt.
+ * The pt2pt protocol allows for discovery frames
+ * to be received without a registered VPI.
+ */
+ if (!(vport->fc_flag & FC_PT2PT) ||
+ (phba->link_state == LPFC_HBA_READY)) {
+ lpfc_in_buf_free(phba, &dmabuf->dbuf);
+ return;
+ }
+ }
+
/* Handle the basic abort sequence (BA_ABTS) event */
if (fc_hdr->fh_r_ctl == FC_RCTL_BA_ABTS) {
lpfc_sli4_handle_unsol_abort(vport, dmabuf);
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index 3290b8e7ab65..2626f58c0747 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -68,7 +68,7 @@ struct lpfc_iocbq {
#define LPFC_EXCHANGE_BUSY 0x40 /* SLI4 hba reported XB in response */
#define LPFC_USE_FCPWQIDX 0x80 /* Submit to specified FCPWQ index */
#define DSS_SECURITY_OP 0x100 /* security IO */
-#define LPFC_IO_ON_Q 0x200 /* The IO is still on the TXCMPLQ */
+#define LPFC_IO_ON_TXCMPLQ 0x200 /* The IO is still on the TXCMPLQ */
#define LPFC_IO_DIF 0x400 /* T10 DIF IO */
#define LPFC_FIP_ELS_ID_MASK 0xc000 /* ELS_ID range 0-3, non-shifted mask */
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index c19d139618b7..a4a77080091b 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -75,11 +75,19 @@
(fc_hdr)->fh_s_id[1] << 8 | \
(fc_hdr)->fh_s_id[2])
+#define sli4_did_from_fc_hdr(fc_hdr) \
+ ((fc_hdr)->fh_d_id[0] << 16 | \
+ (fc_hdr)->fh_d_id[1] << 8 | \
+ (fc_hdr)->fh_d_id[2])
+
#define sli4_fctl_from_fc_hdr(fc_hdr) \
((fc_hdr)->fh_f_ctl[0] << 16 | \
(fc_hdr)->fh_f_ctl[1] << 8 | \
(fc_hdr)->fh_f_ctl[2])
+#define sli4_type_from_fc_hdr(fc_hdr) \
+ ((fc_hdr)->fh_type)
+
#define LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT 12000
enum lpfc_sli4_queue_type {
@@ -493,14 +501,12 @@ struct lpfc_sli4_hba {
uint16_t next_rpi;
uint16_t scsi_xri_max;
uint16_t scsi_xri_cnt;
+ uint16_t els_xri_cnt;
uint16_t scsi_xri_start;
struct list_head lpfc_free_sgl_list;
struct list_head lpfc_sgl_list;
- struct lpfc_sglq **lpfc_els_sgl_array;
struct list_head lpfc_abts_els_sgl_list;
- struct lpfc_scsi_buf **lpfc_scsi_psb_array;
struct list_head lpfc_abts_scsi_buf_list;
- uint32_t total_sglq_bufs;
struct lpfc_sglq **lpfc_sglq_active_list;
struct list_head lpfc_rpi_hdr_list;
unsigned long *rpi_bmask;
@@ -509,7 +515,6 @@ struct lpfc_sli4_hba {
struct list_head lpfc_rpi_blk_list;
unsigned long *xri_bmask;
uint16_t *xri_ids;
- uint16_t xri_count;
struct list_head lpfc_xri_blk_list;
unsigned long *vfi_bmask;
uint16_t *vfi_ids;
@@ -614,11 +619,7 @@ int lpfc_sli4_post_sgl(struct lpfc_hba *, dma_addr_t, dma_addr_t, uint16_t);
int lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *);
uint16_t lpfc_sli4_next_xritag(struct lpfc_hba *);
int lpfc_sli4_post_async_mbox(struct lpfc_hba *);
-int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba);
-int lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba);
int lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *, struct list_head *, int);
-int lpfc_sli4_post_scsi_sgl_blk_ext(struct lpfc_hba *, struct list_head *,
- int);
struct lpfc_cq_event *__lpfc_sli4_cq_event_alloc(struct lpfc_hba *);
struct lpfc_cq_event *lpfc_sli4_cq_event_alloc(struct lpfc_hba *);
void __lpfc_sli4_cq_event_release(struct lpfc_hba *, struct lpfc_cq_event *);
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 25cefc254b76..59c57a409981 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "8.3.30"
+#define LPFC_DRIVER_VERSION "8.3.31"
#define LPFC_DRIVER_NAME "lpfc"
#define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp"
#define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp"
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index e5f416f8042d..e8f892647681 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -33,9 +33,9 @@
/*
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "00.00.06.14-rc1"
-#define MEGASAS_RELDATE "Jan. 6, 2012"
-#define MEGASAS_EXT_VERSION "Fri. Jan. 6 17:00:00 PDT 2012"
+#define MEGASAS_VERSION "00.00.06.15-rc1"
+#define MEGASAS_RELDATE "Mar. 19, 2012"
+#define MEGASAS_EXT_VERSION "Mon. Mar. 19 17:00:00 PDT 2012"
/*
* Device IDs
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 8b300be44284..dc27598785e5 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* FILE: megaraid_sas_base.c
- * Version : v00.00.06.14-rc1
+ * Version : v00.00.06.15-rc1
*
* Authors: LSI Corporation
* Sreenivas Bagalkote
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index 294abb0defa6..e3d251a2e26a 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -362,15 +362,20 @@ MR_BuildRaidContext(struct megasas_instance *instance,
/* assume this IO needs the full row - we'll adjust if not true */
regSize = stripSize;
- /* If IO spans more than 1 strip, fp is not possible
- FP is not possible for writes on non-0 raid levels
- FP is not possible if LD is not capable */
- if (num_strips > 1 || (!isRead && raid->level != 0) ||
- !raid->capability.fpCapable) {
+ /* Check if we can send this I/O via FastPath */
+ if (raid->capability.fpCapable) {
+ if (isRead)
+ io_info->fpOkForIo = (raid->capability.fpReadCapable &&
+ ((num_strips == 1) ||
+ raid->capability.
+ fpReadAcrossStripe));
+ else
+ io_info->fpOkForIo = (raid->capability.fpWriteCapable &&
+ ((num_strips == 1) ||
+ raid->capability.
+ fpWriteAcrossStripe));
+ } else
io_info->fpOkForIo = FALSE;
- } else {
- io_info->fpOkForIo = TRUE;
- }
if (numRows == 1) {
/* single-strip IOs can always lock only the data needed */
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index bfd87fab39aa..a610cf1d4847 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -634,9 +634,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
fusion->reply_frames_desc_phys;
IOCInitMessage->SystemRequestFrameBaseAddress =
fusion->io_request_frames_phys;
- /* Set to 0 for none or 1 MSI-X vectors */
- IOCInitMessage->HostMSIxVectors = (instance->msix_vectors > 0 ?
- instance->msix_vectors : 0);
+ IOCInitMessage->HostMSIxVectors = instance->msix_vectors;
init_frame = (struct megasas_init_frame *)cmd->frame;
memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h
index a01f0aa66f20..a80f3220c641 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2.h
@@ -8,7 +8,7 @@
* scatter/gather formats.
* Creation Date: June 21, 2006
*
- * mpi2.h Version: 02.00.22
+ * mpi2.h Version: 02.00.23
*
* Version History
* ---------------
@@ -71,6 +71,7 @@
* 03-09-11 02.00.20 Bumped MPI2_HEADER_VERSION_UNIT.
* 05-25-11 02.00.21 Bumped MPI2_HEADER_VERSION_UNIT.
* 08-24-11 02.00.22 Bumped MPI2_HEADER_VERSION_UNIT.
+ * 11-18-11 02.00.23 Bumped MPI2_HEADER_VERSION_UNIT.
* --------------------------------------------------------------------------
*/
@@ -96,7 +97,7 @@
#define MPI2_VERSION_02_00 (0x0200)
/* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT (0x16)
+#define MPI2_HEADER_VERSION_UNIT (0x17)
#define MPI2_HEADER_VERSION_DEV (0x00)
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
@@ -480,7 +481,7 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION
MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR RAIDAcceleratorSuccess;
U64 Words;
} MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION,
- Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t;
+Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t;
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
index 3a023dad77a1..737fa8cfb54a 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
@@ -6,7 +6,7 @@
* Title: MPI Configuration messages and pages
* Creation Date: November 10, 2006
*
- * mpi2_cnfg.h Version: 02.00.21
+ * mpi2_cnfg.h Version: 02.00.22
*
* Version History
* ---------------
@@ -146,7 +146,9 @@
* Added SpinupFlags field containing a Disable Spin-up
* bit to the MPI2_SAS_IOUNIT4_SPINUP_GROUP fields of
* SAS IO Unit Page 4.
-
+ * 11-18-11 02.00.22 Added define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT.
+ * Added UEFIVersion field to BIOS Page 1 and defined new
+ * BiosOptions bits.
* --------------------------------------------------------------------------
*/
@@ -1131,9 +1133,10 @@ typedef struct _MPI2_CONFIG_PAGE_IOC_6
} MPI2_CONFIG_PAGE_IOC_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_6,
Mpi2IOCPage6_t, MPI2_POINTER pMpi2IOCPage6_t;
-#define MPI2_IOCPAGE6_PAGEVERSION (0x04)
+#define MPI2_IOCPAGE6_PAGEVERSION (0x05)
/* defines for IOC Page 6 CapabilitiesFlags */
+#define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT (0x00000020)
#define MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT (0x00000010)
#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT (0x00000008)
#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT (0x00000004)
@@ -1204,24 +1207,29 @@ typedef struct _MPI2_CONFIG_PAGE_IOC_8
typedef struct _MPI2_CONFIG_PAGE_BIOS_1
{
- MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
- U32 BiosOptions; /* 0x04 */
- U32 IOCSettings; /* 0x08 */
- U32 Reserved1; /* 0x0C */
- U32 DeviceSettings; /* 0x10 */
- U16 NumberOfDevices; /* 0x14 */
- U16 Reserved2; /* 0x16 */
- U16 IOTimeoutBlockDevicesNonRM; /* 0x18 */
- U16 IOTimeoutSequential; /* 0x1A */
- U16 IOTimeoutOther; /* 0x1C */
- U16 IOTimeoutBlockDevicesRM; /* 0x1E */
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 BiosOptions; /* 0x04 */
+ U32 IOCSettings; /* 0x08 */
+ U32 Reserved1; /* 0x0C */
+ U32 DeviceSettings; /* 0x10 */
+ U16 NumberOfDevices; /* 0x14 */
+ U16 UEFIVersion; /* 0x16 */
+ U16 IOTimeoutBlockDevicesNonRM; /* 0x18 */
+ U16 IOTimeoutSequential; /* 0x1A */
+ U16 IOTimeoutOther; /* 0x1C */
+ U16 IOTimeoutBlockDevicesRM; /* 0x1E */
} MPI2_CONFIG_PAGE_BIOS_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_1,
Mpi2BiosPage1_t, MPI2_POINTER pMpi2BiosPage1_t;
-#define MPI2_BIOSPAGE1_PAGEVERSION (0x04)
+#define MPI2_BIOSPAGE1_PAGEVERSION (0x05)
/* values for BIOS Page 1 BiosOptions field */
-#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
+#define MPI2_BIOSPAGE1_OPTIONS_MASK_UEFI_HII_REGISTRATION (0x00000006)
+#define MPI2_BIOSPAGE1_OPTIONS_ENABLE_UEFI_HII (0x00000000)
+#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_UEFI_HII (0x00000002)
+#define MPI2_BIOSPAGE1_OPTIONS_VERSION_CHECK_UEFI_HII (0x00000004)
+
+#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
/* values for BIOS Page 1 IOCSettings field */
#define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000)
@@ -1248,6 +1256,13 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_1
#define MPI2_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002)
#define MPI2_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001)
+/* defines for BIOS Page 1 UEFIVersion field */
+#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_MASK (0xFF00)
+#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_SHIFT (8)
+#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_MASK (0x00FF)
+#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_SHIFT (0)
+
+
/* BIOS Page 2 */
@@ -2216,6 +2231,27 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_8 {
+/* SAS IO Unit Page 16 */
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT16 {
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U64 TimeStamp; /* 0x08 */
+ U32 Reserved1; /* 0x10 */
+ U32 Reserved2; /* 0x14 */
+ U32 FastPathPendedRequests; /* 0x18 */
+ U32 FastPathUnPendedRequests; /* 0x1C */
+ U32 FastPathHostRequestStarts; /* 0x20 */
+ U32 FastPathFirmwareRequestStarts; /* 0x24 */
+ U32 FastPathHostCompletions; /* 0x28 */
+ U32 FastPathFirmwareCompletions; /* 0x2C */
+ U32 NonFastPathRequestStarts; /* 0x30 */
+ U32 NonFastPathHostCompletions; /* 0x30 */
+} MPI2_CONFIG_PAGE_SASIOUNIT16,
+MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT16,
+Mpi2SasIOUnitPage16_t, MPI2_POINTER pMpi2SasIOUnitPage16_t;
+
+#define MPI2_SASIOUNITPAGE16_PAGEVERSION (0x00)
+
/****************************************************************************
* SAS Expander Config Pages
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 8a59a772fdf2..6102ef2cb2d8 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -699,6 +699,11 @@ _base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
u16 ioc_status;
mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+ if (unlikely(!mpi_reply)) {
+ printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
if ((ioc_status & MPI2_IOCSTATUS_MASK) &&
@@ -930,16 +935,18 @@ _base_interrupt(int irq, void *bus_id)
else if (request_desript_type ==
MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS)
goto next;
- if (smid)
+ if (smid) {
cb_idx = _base_get_cb_idx(ioc, smid);
- if (smid && cb_idx != 0xFF) {
- rc = mpt_callbacks[cb_idx](ioc, smid, msix_index,
- reply);
+ if ((likely(cb_idx < MPT_MAX_CALLBACKS))
+ && (likely(mpt_callbacks[cb_idx] != NULL))) {
+ rc = mpt_callbacks[cb_idx](ioc, smid,
+ msix_index, reply);
if (reply)
- _base_display_reply_info(ioc, smid, msix_index,
- reply);
+ _base_display_reply_info(ioc, smid,
+ msix_index, reply);
if (rc)
mpt2sas_base_free_smid(ioc, smid);
+ }
}
if (!smid)
_base_async_event(ioc, msix_index, reply);
@@ -3343,7 +3350,7 @@ _base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
}
pfacts = &ioc->pfacts[port];
- memset(pfacts, 0, sizeof(Mpi2PortFactsReply_t));
+ memset(pfacts, 0, sizeof(struct mpt2sas_port_facts));
pfacts->PortNumber = mpi_reply.PortNumber;
pfacts->VP_ID = mpi_reply.VP_ID;
pfacts->VF_ID = mpi_reply.VF_ID;
@@ -3385,7 +3392,7 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
}
facts = &ioc->facts;
- memset(facts, 0, sizeof(Mpi2IOCFactsReply_t));
+ memset(facts, 0, sizeof(struct mpt2sas_facts));
facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion);
facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion);
facts->VP_ID = mpi_reply.VP_ID;
@@ -4153,7 +4160,8 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
if (ioc->is_driver_loading) {
if (ioc->is_warpdrive && ioc->manu_pg10.OEMIdentifier
== 0x80) {
- hide_flag = (u8) (ioc->manu_pg10.OEMSpecificFlags0 &
+ hide_flag = (u8) (
+ le32_to_cpu(ioc->manu_pg10.OEMSpecificFlags0) &
MFG_PAGE10_HIDE_SSDS_MASK);
if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK)
ioc->mfg_pg10_hide_flag = hide_flag;
@@ -4262,7 +4270,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
goto out_free_resources;
ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts,
- sizeof(Mpi2PortFactsReply_t), GFP_KERNEL);
+ sizeof(struct mpt2sas_port_facts), GFP_KERNEL);
if (!ioc->pfacts) {
r = -ENOMEM;
goto out_free_resources;
@@ -4279,7 +4287,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
goto out_free_resources;
init_waitqueue_head(&ioc->reset_wq);
-
/* allocate memory pd handle bitmask list */
ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8);
if (ioc->facts.MaxDevHandle % 8)
@@ -4290,7 +4297,12 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
r = -ENOMEM;
goto out_free_resources;
}
-
+ ioc->blocking_handles = kzalloc(ioc->pd_handles_sz,
+ GFP_KERNEL);
+ if (!ioc->blocking_handles) {
+ r = -ENOMEM;
+ goto out_free_resources;
+ }
ioc->fwfault_debug = mpt2sas_fwfault_debug;
/* base internal command bits */
@@ -4377,6 +4389,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
if (ioc->is_warpdrive)
kfree(ioc->reply_post_host_index);
kfree(ioc->pd_handles);
+ kfree(ioc->blocking_handles);
kfree(ioc->tm_cmds.reply);
kfree(ioc->transport_cmds.reply);
kfree(ioc->scsih_cmds.reply);
@@ -4418,6 +4431,7 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
if (ioc->is_warpdrive)
kfree(ioc->reply_post_host_index);
kfree(ioc->pd_handles);
+ kfree(ioc->blocking_handles);
kfree(ioc->pfacts);
kfree(ioc->ctl_cmds.reply);
kfree(ioc->ctl_cmds.sense);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index c7459fdc06cc..b6dd3a5de7f9 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -69,8 +69,8 @@
#define MPT2SAS_DRIVER_NAME "mpt2sas"
#define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION "12.100.00.00"
-#define MPT2SAS_MAJOR_VERSION 12
+#define MPT2SAS_DRIVER_VERSION "13.100.00.00"
+#define MPT2SAS_MAJOR_VERSION 13
#define MPT2SAS_MINOR_VERSION 100
#define MPT2SAS_BUILD_VERSION 00
#define MPT2SAS_RELEASE_VERSION 00
@@ -720,6 +720,7 @@ typedef void (*MPT2SAS_FLUSH_RUNNING_CMDS)(struct MPT2SAS_ADAPTER *ioc);
* @io_missing_delay: time for IO completed by fw when PDR enabled
* @device_missing_delay: time for device missing by fw when PDR enabled
* @sas_id : used for setting volume target IDs
+ * @blocking_handles: bitmask used to identify which devices need blocking
* @pd_handles : bitmask for PD handles
* @pd_handles_sz : size of pd_handle bitmask
* @config_page_sz: config page size
@@ -889,7 +890,7 @@ struct MPT2SAS_ADAPTER {
u8 io_missing_delay;
u16 device_missing_delay;
int sas_id;
-
+ void *blocking_handles;
void *pd_handles;
u16 pd_handles_sz;
@@ -1058,7 +1059,8 @@ int mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle,
void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
-void mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
+void mpt2sas_device_remove_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
+ u64 sas_address);
struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc,
u16 handle);
struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 3b9a28efea82..49bdd2dc8452 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -620,11 +620,10 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg,
* @ioc: per adapter object
* @karg - (struct mpt2_ioctl_command)
* @mf - pointer to mf in user space
- * @state - NON_BLOCKING or BLOCKING
*/
static long
-_ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
- struct mpt2_ioctl_command karg, void __user *mf, enum block_state state)
+_ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command karg,
+ void __user *mf)
{
MPI2RequestHeader_t *mpi_request = NULL, *request;
MPI2DefaultReply_t *mpi_reply;
@@ -647,11 +646,6 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
issue_reset = 0;
- if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
- return -EAGAIN;
- else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
- return -ERESTARTSYS;
-
if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
ioc->name, __func__);
@@ -871,8 +865,16 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
if (smp_request->PassthroughFlags &
MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE)
data = (u8 *)&smp_request->SGL;
- else
+ else {
+ if (unlikely(data_out == NULL)) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ mpt2sas_base_free_smid(ioc, smid);
+ ret = -EINVAL;
+ goto out;
+ }
data = data_out;
+ }
if (data[1] == 0x91 && (data[10] == 1 || data[10] == 2)) {
ioc->ioc_link_reset_in_progress = 1;
@@ -985,7 +987,8 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
ret = -ENODATA;
if ((mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
mpi_request->Function ==
- MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
+ MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
+ mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH)) {
printk(MPT2SAS_INFO_FMT "issue target reset: handle "
"= (0x%04x)\n", ioc->name,
le16_to_cpu(mpi_request->FunctionDependent1));
@@ -1013,27 +1016,24 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
kfree(mpi_request);
ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
- mutex_unlock(&ioc->ctl_cmds.mutex);
return ret;
}
/**
* _ctl_getiocinfo - main handler for MPT2IOCINFO opcode
+ * @ioc: per adapter object
* @arg - user space buffer containing ioctl content
*/
static long
-_ctl_getiocinfo(void __user *arg)
+_ctl_getiocinfo(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{
struct mpt2_ioctl_iocinfo karg;
- struct MPT2SAS_ADAPTER *ioc;
if (copy_from_user(&karg, arg, sizeof(karg))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
return -EFAULT;
}
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
__func__));
@@ -1069,21 +1069,19 @@ _ctl_getiocinfo(void __user *arg)
/**
* _ctl_eventquery - main handler for MPT2EVENTQUERY opcode
+ * @ioc: per adapter object
* @arg - user space buffer containing ioctl content
*/
static long
-_ctl_eventquery(void __user *arg)
+_ctl_eventquery(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{
struct mpt2_ioctl_eventquery karg;
- struct MPT2SAS_ADAPTER *ioc;
if (copy_from_user(&karg, arg, sizeof(karg))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
return -EFAULT;
}
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
__func__));
@@ -1102,21 +1100,19 @@ _ctl_eventquery(void __user *arg)
/**
* _ctl_eventenable - main handler for MPT2EVENTENABLE opcode
+ * @ioc: per adapter object
* @arg - user space buffer containing ioctl content
*/
static long
-_ctl_eventenable(void __user *arg)
+_ctl_eventenable(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{
struct mpt2_ioctl_eventenable karg;
- struct MPT2SAS_ADAPTER *ioc;
if (copy_from_user(&karg, arg, sizeof(karg))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
return -EFAULT;
}
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
__func__));
@@ -1142,13 +1138,13 @@ _ctl_eventenable(void __user *arg)
/**
* _ctl_eventreport - main handler for MPT2EVENTREPORT opcode
+ * @ioc: per adapter object
* @arg - user space buffer containing ioctl content
*/
static long
-_ctl_eventreport(void __user *arg)
+_ctl_eventreport(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{
struct mpt2_ioctl_eventreport karg;
- struct MPT2SAS_ADAPTER *ioc;
u32 number_bytes, max_events, max;
struct mpt2_ioctl_eventreport __user *uarg = arg;
@@ -1157,8 +1153,6 @@ _ctl_eventreport(void __user *arg)
__FILE__, __LINE__, __func__);
return -EFAULT;
}
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
__func__));
@@ -1188,13 +1182,13 @@ _ctl_eventreport(void __user *arg)
/**
* _ctl_do_reset - main handler for MPT2HARDRESET opcode
+ * @ioc: per adapter object
* @arg - user space buffer containing ioctl content
*/
static long
-_ctl_do_reset(void __user *arg)
+_ctl_do_reset(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{
struct mpt2_ioctl_diag_reset karg;
- struct MPT2SAS_ADAPTER *ioc;
int retval;
if (copy_from_user(&karg, arg, sizeof(karg))) {
@@ -1202,8 +1196,6 @@ _ctl_do_reset(void __user *arg)
__FILE__, __LINE__, __func__);
return -EFAULT;
}
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
if (ioc->shost_recovery || ioc->pci_error_recovery ||
ioc->is_driver_loading)
@@ -1292,13 +1284,13 @@ _ctl_btdh_search_raid_device(struct MPT2SAS_ADAPTER *ioc,
/**
* _ctl_btdh_mapping - main handler for MPT2BTDHMAPPING opcode
+ * @ioc: per adapter object
* @arg - user space buffer containing ioctl content
*/
static long
-_ctl_btdh_mapping(void __user *arg)
+_ctl_btdh_mapping(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{
struct mpt2_ioctl_btdh_mapping karg;
- struct MPT2SAS_ADAPTER *ioc;
int rc;
if (copy_from_user(&karg, arg, sizeof(karg))) {
@@ -1306,8 +1298,6 @@ _ctl_btdh_mapping(void __user *arg)
__FILE__, __LINE__, __func__);
return -EFAULT;
}
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__));
@@ -1576,17 +1566,16 @@ mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc, u8 bits_to_register)
/**
* _ctl_diag_register - application register with driver
+ * @ioc: per adapter object
* @arg - user space buffer containing ioctl content
- * @state - NON_BLOCKING or BLOCKING
*
* This will allow the driver to setup any required buffers that will be
* needed by firmware to communicate with the driver.
*/
static long
-_ctl_diag_register(void __user *arg, enum block_state state)
+_ctl_diag_register(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{
struct mpt2_diag_register karg;
- struct MPT2SAS_ADAPTER *ioc;
long rc;
if (copy_from_user(&karg, arg, sizeof(karg))) {
@@ -1594,30 +1583,23 @@ _ctl_diag_register(void __user *arg, enum block_state state)
__FILE__, __LINE__, __func__);
return -EFAULT;
}
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
- if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
- return -EAGAIN;
- else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
- return -ERESTARTSYS;
rc = _ctl_diag_register_2(ioc, &karg);
- mutex_unlock(&ioc->ctl_cmds.mutex);
return rc;
}
/**
* _ctl_diag_unregister - application unregister with driver
+ * @ioc: per adapter object
* @arg - user space buffer containing ioctl content
*
* This will allow the driver to cleanup any memory allocated for diag
* messages and to free up any resources.
*/
static long
-_ctl_diag_unregister(void __user *arg)
+_ctl_diag_unregister(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{
struct mpt2_diag_unregister karg;
- struct MPT2SAS_ADAPTER *ioc;
void *request_data;
dma_addr_t request_data_dma;
u32 request_data_sz;
@@ -1628,8 +1610,6 @@ _ctl_diag_unregister(void __user *arg)
__FILE__, __LINE__, __func__);
return -EFAULT;
}
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__));
@@ -1678,6 +1658,7 @@ _ctl_diag_unregister(void __user *arg)
/**
* _ctl_diag_query - query relevant info associated with diag buffers
+ * @ioc: per adapter object
* @arg - user space buffer containing ioctl content
*
* The application will send only buffer_type and unique_id. Driver will
@@ -1685,10 +1666,9 @@ _ctl_diag_unregister(void __user *arg)
* 0x00, the driver will return info specified by Buffer Type.
*/
static long
-_ctl_diag_query(void __user *arg)
+_ctl_diag_query(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{
struct mpt2_diag_query karg;
- struct MPT2SAS_ADAPTER *ioc;
void *request_data;
int i;
u8 buffer_type;
@@ -1698,8 +1678,6 @@ _ctl_diag_query(void __user *arg)
__FILE__, __LINE__, __func__);
return -EFAULT;
}
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__));
@@ -1866,17 +1844,15 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
/**
* _ctl_diag_release - request to send Diag Release Message to firmware
* @arg - user space buffer containing ioctl content
- * @state - NON_BLOCKING or BLOCKING
*
* This allows ownership of the specified buffer to returned to the driver,
* allowing an application to read the buffer without fear that firmware is
* overwritting information in the buffer.
*/
static long
-_ctl_diag_release(void __user *arg, enum block_state state)
+_ctl_diag_release(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{
struct mpt2_diag_release karg;
- struct MPT2SAS_ADAPTER *ioc;
void *request_data;
int rc;
u8 buffer_type;
@@ -1887,8 +1863,6 @@ _ctl_diag_release(void __user *arg, enum block_state state)
__FILE__, __LINE__, __func__);
return -EFAULT;
}
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__));
@@ -1942,32 +1916,25 @@ _ctl_diag_release(void __user *arg, enum block_state state)
return 0;
}
- if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
- return -EAGAIN;
- else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
- return -ERESTARTSYS;
-
rc = _ctl_send_release(ioc, buffer_type, &issue_reset);
if (issue_reset)
mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- mutex_unlock(&ioc->ctl_cmds.mutex);
return rc;
}
/**
* _ctl_diag_read_buffer - request for copy of the diag buffer
+ * @ioc: per adapter object
* @arg - user space buffer containing ioctl content
- * @state - NON_BLOCKING or BLOCKING
*/
static long
-_ctl_diag_read_buffer(void __user *arg, enum block_state state)
+_ctl_diag_read_buffer(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{
struct mpt2_diag_read_buffer karg;
struct mpt2_diag_read_buffer __user *uarg = arg;
- struct MPT2SAS_ADAPTER *ioc;
void *request_data, *diag_data;
Mpi2DiagBufferPostRequest_t *mpi_request;
Mpi2DiagBufferPostReply_t *mpi_reply;
@@ -1983,8 +1950,6 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
__FILE__, __LINE__, __func__);
return -EFAULT;
}
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__));
@@ -2055,10 +2020,6 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
}
/* Get a free request frame and save the message context.
*/
- if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
- return -EAGAIN;
- else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
- return -ERESTARTSYS;
if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
@@ -2139,115 +2100,170 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
out:
ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
- mutex_unlock(&ioc->ctl_cmds.mutex);
return rc;
}
+
+#ifdef CONFIG_COMPAT
+/**
+ * _ctl_compat_mpt_command - convert 32bit pointers to 64bit.
+ * @ioc: per adapter object
+ * @cmd - ioctl opcode
+ * @arg - (struct mpt2_ioctl_command32)
+ *
+ * MPT2COMMAND32 - Handle 32bit applications running on 64bit os.
+ */
+static long
+_ctl_compat_mpt_command(struct MPT2SAS_ADAPTER *ioc, unsigned cmd,
+ void __user *arg)
+{
+ struct mpt2_ioctl_command32 karg32;
+ struct mpt2_ioctl_command32 __user *uarg;
+ struct mpt2_ioctl_command karg;
+
+ if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32))
+ return -EINVAL;
+
+ uarg = (struct mpt2_ioctl_command32 __user *) arg;
+
+ if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+
+ memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
+ karg.hdr.ioc_number = karg32.hdr.ioc_number;
+ karg.hdr.port_number = karg32.hdr.port_number;
+ karg.hdr.max_data_size = karg32.hdr.max_data_size;
+ karg.timeout = karg32.timeout;
+ karg.max_reply_bytes = karg32.max_reply_bytes;
+ karg.data_in_size = karg32.data_in_size;
+ karg.data_out_size = karg32.data_out_size;
+ karg.max_sense_bytes = karg32.max_sense_bytes;
+ karg.data_sge_offset = karg32.data_sge_offset;
+ karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr);
+ karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr);
+ karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr);
+ karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr);
+ return _ctl_do_mpt_command(ioc, karg, &uarg->mf);
+}
+#endif
+
/**
* _ctl_ioctl_main - main ioctl entry point
* @file - (struct file)
* @cmd - ioctl opcode
* @arg -
+ * compat - handles 32 bit applications in 64bit os
*/
static long
-_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg)
+_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
+ u8 compat)
{
+ struct MPT2SAS_ADAPTER *ioc;
+ struct mpt2_ioctl_header ioctl_header;
enum block_state state;
long ret = -EINVAL;
- state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING :
- BLOCKING;
+ /* get IOCTL header */
+ if (copy_from_user(&ioctl_header, (char __user *)arg,
+ sizeof(struct mpt2_ioctl_header))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+
+ if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+ if (ioc->shost_recovery || ioc->pci_error_recovery ||
+ ioc->is_driver_loading)
+ return -EAGAIN;
+
+ state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
+ if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
+ return -EAGAIN;
+ else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
+ return -ERESTARTSYS;
switch (cmd) {
case MPT2IOCINFO:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_iocinfo))
- ret = _ctl_getiocinfo(arg);
+ ret = _ctl_getiocinfo(ioc, arg);
break;
+#ifdef CONFIG_COMPAT
+ case MPT2COMMAND32:
+#endif
case MPT2COMMAND:
{
- struct mpt2_ioctl_command karg;
struct mpt2_ioctl_command __user *uarg;
- struct MPT2SAS_ADAPTER *ioc;
-
+ struct mpt2_ioctl_command karg;
+#ifdef CONFIG_COMPAT
+ if (compat) {
+ ret = _ctl_compat_mpt_command(ioc, cmd, arg);
+ break;
+ }
+#endif
if (copy_from_user(&karg, arg, sizeof(karg))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
- return -EFAULT;
+ ret = -EFAULT;
+ break;
}
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 ||
- !ioc)
- return -ENODEV;
-
- if (ioc->shost_recovery || ioc->pci_error_recovery ||
- ioc->is_driver_loading)
- return -EAGAIN;
-
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) {
uarg = arg;
- ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf, state);
+ ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf);
}
break;
}
case MPT2EVENTQUERY:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventquery))
- ret = _ctl_eventquery(arg);
+ ret = _ctl_eventquery(ioc, arg);
break;
case MPT2EVENTENABLE:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventenable))
- ret = _ctl_eventenable(arg);
+ ret = _ctl_eventenable(ioc, arg);
break;
case MPT2EVENTREPORT:
- ret = _ctl_eventreport(arg);
+ ret = _ctl_eventreport(ioc, arg);
break;
case MPT2HARDRESET:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_diag_reset))
- ret = _ctl_do_reset(arg);
+ ret = _ctl_do_reset(ioc, arg);
break;
case MPT2BTDHMAPPING:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_btdh_mapping))
- ret = _ctl_btdh_mapping(arg);
+ ret = _ctl_btdh_mapping(ioc, arg);
break;
case MPT2DIAGREGISTER:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_register))
- ret = _ctl_diag_register(arg, state);
+ ret = _ctl_diag_register(ioc, arg);
break;
case MPT2DIAGUNREGISTER:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_unregister))
- ret = _ctl_diag_unregister(arg);
+ ret = _ctl_diag_unregister(ioc, arg);
break;
case MPT2DIAGQUERY:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_query))
- ret = _ctl_diag_query(arg);
+ ret = _ctl_diag_query(ioc, arg);
break;
case MPT2DIAGRELEASE:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_release))
- ret = _ctl_diag_release(arg, state);
+ ret = _ctl_diag_release(ioc, arg);
break;
case MPT2DIAGREADBUFFER:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_read_buffer))
- ret = _ctl_diag_read_buffer(arg, state);
+ ret = _ctl_diag_read_buffer(ioc, arg);
break;
default:
- {
- struct mpt2_ioctl_command karg;
- struct MPT2SAS_ADAPTER *ioc;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
-
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 ||
- !ioc)
- return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT
"unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd));
break;
}
- }
+
+ mutex_unlock(&ioc->ctl_cmds.mutex);
return ret;
}
@@ -2262,66 +2278,11 @@ _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret;
- mutex_lock(&_ctl_mutex);
- ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
- mutex_unlock(&_ctl_mutex);
+ ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0);
return ret;
}
-
#ifdef CONFIG_COMPAT
/**
- * _ctl_compat_mpt_command - convert 32bit pointers to 64bit.
- * @file - (struct file)
- * @cmd - ioctl opcode
- * @arg - (struct mpt2_ioctl_command32)
- *
- * MPT2COMMAND32 - Handle 32bit applications running on 64bit os.
- */
-static long
-_ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg)
-{
- struct mpt2_ioctl_command32 karg32;
- struct mpt2_ioctl_command32 __user *uarg;
- struct mpt2_ioctl_command karg;
- struct MPT2SAS_ADAPTER *ioc;
- enum block_state state;
-
- if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32))
- return -EINVAL;
-
- uarg = (struct mpt2_ioctl_command32 __user *) arg;
-
- if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
- if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
-
- if (ioc->shost_recovery || ioc->pci_error_recovery ||
- ioc->is_driver_loading)
- return -EAGAIN;
-
- memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
- karg.hdr.ioc_number = karg32.hdr.ioc_number;
- karg.hdr.port_number = karg32.hdr.port_number;
- karg.hdr.max_data_size = karg32.hdr.max_data_size;
- karg.timeout = karg32.timeout;
- karg.max_reply_bytes = karg32.max_reply_bytes;
- karg.data_in_size = karg32.data_in_size;
- karg.data_out_size = karg32.data_out_size;
- karg.max_sense_bytes = karg32.max_sense_bytes;
- karg.data_sge_offset = karg32.data_sge_offset;
- karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr);
- karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr);
- karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr);
- karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr);
- state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
- return _ctl_do_mpt_command(ioc, karg, &uarg->mf, state);
-}
-
-/**
* _ctl_ioctl_compat - main ioctl entry point (compat)
* @file -
* @cmd -
@@ -2334,12 +2295,7 @@ _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
{
long ret;
- mutex_lock(&_ctl_mutex);
- if (cmd == MPT2COMMAND32)
- ret = _ctl_compat_mpt_command(file, cmd, arg);
- else
- ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
- mutex_unlock(&_ctl_mutex);
+ ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1);
return ret;
}
#endif
@@ -2884,7 +2840,7 @@ _ctl_host_trace_buffer_enable_store(struct device *cdev,
struct mpt2_diag_register diag_register;
u8 issue_reset = 0;
- if (sscanf(buf, "%s", str) != 1)
+ if (sscanf(buf, "%9s", str) != 1)
return -EINVAL;
if (!strcmp(str, "post")) {
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index d953a57e779d..76973e8ca4ba 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -579,14 +579,12 @@ _scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc,
return;
spin_lock_irqsave(&ioc->sas_device_lock, flags);
- if (mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
- sas_device->sas_address)) {
- list_del(&sas_device->list);
- kfree(sas_device);
- }
+ list_del(&sas_device->list);
+ kfree(sas_device);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
}
+
/**
* _scsih_sas_device_add - insert sas_device to the list.
* @ioc: per adapter object
@@ -645,8 +643,8 @@ _scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc,
spin_lock_irqsave(&ioc->sas_device_lock, flags);
list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
_scsih_determine_boot_device(ioc, sas_device, 0);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
}
/**
@@ -755,7 +753,6 @@ _scsih_raid_device_add(struct MPT2SAS_ADAPTER *ioc,
* @ioc: per adapter object
* @raid_device: raid_device object
*
- * This is removed from the raid_device_list link list.
*/
static void
_scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc,
@@ -765,7 +762,6 @@ _scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc,
spin_lock_irqsave(&ioc->raid_device_lock, flags);
list_del(&raid_device->list);
- memset(raid_device, 0, sizeof(struct _raid_device));
kfree(raid_device);
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
}
@@ -1199,10 +1195,10 @@ _scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
sas_device_priv_data->sas_target->sas_address);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (sas_device && sas_device->device_info &
MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
max_depth = MPT2SAS_SATA_QUEUE_DEPTH;
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
not_sata:
@@ -1299,7 +1295,8 @@ _scsih_target_alloc(struct scsi_target *starget)
sas_target_priv_data->handle = raid_device->handle;
sas_target_priv_data->sas_address = raid_device->wwid;
sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
- sas_target_priv_data->raid_device = raid_device;
+ if (ioc->is_warpdrive)
+ sas_target_priv_data->raid_device = raid_device;
raid_device->starget = starget;
}
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
@@ -1465,12 +1462,12 @@ _scsih_slave_destroy(struct scsi_device *sdev)
/**
* _scsih_display_sata_capabilities - sata capabilities
* @ioc: per adapter object
- * @sas_device: the sas_device object
+ * @handle: device handle
* @sdev: scsi device struct
*/
static void
_scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_device *sas_device, struct scsi_device *sdev)
+ u16 handle, struct scsi_device *sdev)
{
Mpi2ConfigReply_t mpi_reply;
Mpi2SasDevicePage0_t sas_device_pg0;
@@ -1479,7 +1476,7 @@ _scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc,
u32 device_info;
if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
- MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, sas_device->handle))) {
+ MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
return;
@@ -1537,27 +1534,40 @@ _scsih_get_resync(struct device *dev)
Mpi2RaidVolPage0_t vol_pg0;
Mpi2ConfigReply_t mpi_reply;
u32 volume_status_flags;
- u8 percent_complete = 0;
+ u8 percent_complete;
+ u16 handle;
+
+ percent_complete = 0;
+ handle = 0;
+ if (ioc->is_warpdrive)
+ goto out;
spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
sdev->channel);
+ if (raid_device) {
+ handle = raid_device->handle;
+ percent_complete = raid_device->percent_complete;
+ }
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- if (!raid_device || ioc->is_warpdrive)
+ if (!handle)
goto out;
if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
- MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle,
+ MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
sizeof(Mpi2RaidVolPage0_t))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
+ percent_complete = 0;
goto out;
}
volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags);
- if (volume_status_flags & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS)
- percent_complete = raid_device->percent_complete;
+ if (!(volume_status_flags &
+ MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS))
+ percent_complete = 0;
+
out:
raid_set_resync(mpt2sas_raid_template, dev, percent_complete);
}
@@ -1577,17 +1587,20 @@ _scsih_get_state(struct device *dev)
Mpi2ConfigReply_t mpi_reply;
u32 volstate;
enum raid_state state = RAID_STATE_UNKNOWN;
+ u16 handle = 0;
spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
sdev->channel);
+ if (raid_device)
+ handle = raid_device->handle;
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
if (!raid_device)
goto out;
if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
- MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle,
+ MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
sizeof(Mpi2RaidVolPage0_t))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
@@ -1620,14 +1633,14 @@ _scsih_get_state(struct device *dev)
/**
* _scsih_set_level - set raid level
* @sdev: scsi device struct
- * @raid_device: raid_device object
+ * @volume_type: volume type
*/
static void
-_scsih_set_level(struct scsi_device *sdev, struct _raid_device *raid_device)
+_scsih_set_level(struct scsi_device *sdev, u8 volume_type)
{
enum raid_level level = RAID_LEVEL_UNKNOWN;
- switch (raid_device->volume_type) {
+ switch (volume_type) {
case MPI2_RAID_VOL_TYPE_RAID0:
level = RAID_LEVEL_0;
break;
@@ -1722,6 +1735,7 @@ _scsih_disable_ddio(struct MPT2SAS_ADAPTER *ioc)
struct _raid_device *raid_device;
u16 handle;
u16 ioc_status;
+ unsigned long flags;
handle = 0xFFFF;
while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
@@ -1731,9 +1745,11 @@ _scsih_disable_ddio(struct MPT2SAS_ADAPTER *ioc)
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
handle = le16_to_cpu(vol_pg1.DevHandle);
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
if (raid_device)
raid_device->direct_io_enabled = 0;
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
}
return;
}
@@ -1838,7 +1854,8 @@ _scsih_init_warpdrive_properties(struct MPT2SAS_ADAPTER *ioc,
if (mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
&pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
vol_pg0->PhysDisk[count].PhysDiskNum) ||
- pd_pg0.DevHandle == MPT2SAS_INVALID_DEVICE_HANDLE) {
+ le16_to_cpu(pd_pg0.DevHandle) ==
+ MPT2SAS_INVALID_DEVICE_HANDLE) {
printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is "
"disabled for the drive with handle(0x%04x) member"
"handle retrieval failed for member number=%d\n",
@@ -1968,19 +1985,21 @@ _scsih_slave_configure(struct scsi_device *sdev)
u8 ssp_target = 0;
char *ds = "";
char *r_level = "";
+ u16 handle, volume_handle = 0;
+ u64 volume_wwid = 0;
qdepth = 1;
sas_device_priv_data = sdev->hostdata;
sas_device_priv_data->configured_lun = 1;
sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT;
sas_target_priv_data = sas_device_priv_data->sas_target;
+ handle = sas_target_priv_data->handle;
/* raid volume handling */
if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
spin_lock_irqsave(&ioc->raid_device_lock, flags);
- raid_device = _scsih_raid_device_find_by_handle(ioc,
- sas_target_priv_data->handle);
+ raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
if (!raid_device) {
dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
@@ -1989,8 +2008,6 @@ _scsih_slave_configure(struct scsi_device *sdev)
return 1;
}
- _scsih_get_volume_capabilities(ioc, raid_device);
-
if (_scsih_get_volume_capabilities(ioc, raid_device)) {
dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
"failure at %s:%d/%s()!\n", ioc->name, __FILE__,
@@ -2058,68 +2075,67 @@ _scsih_slave_configure(struct scsi_device *sdev)
_scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
/* raid transport support */
if (!ioc->is_warpdrive)
- _scsih_set_level(sdev, raid_device);
+ _scsih_set_level(sdev, raid_device->volume_type);
return 0;
}
/* non-raid handling */
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
- sas_device_priv_data->sas_target->sas_address);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (sas_device) {
- if (sas_target_priv_data->flags &
- MPT_TARGET_FLAGS_RAID_COMPONENT) {
- if (mpt2sas_config_get_volume_handle(ioc,
- sas_device->handle, &sas_device->volume_handle)) {
- dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name,
- __FILE__, __LINE__, __func__));
- return 1;
- }
- if (sas_device->volume_handle &&
- mpt2sas_config_get_volume_wwid(ioc,
- sas_device->volume_handle,
- &sas_device->volume_wwid)) {
- dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name,
- __FILE__, __LINE__, __func__));
- return 1;
- }
+ if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
+ if (mpt2sas_config_get_volume_handle(ioc, handle,
+ &volume_handle)) {
+ dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+ "failure at %s:%d/%s()!\n", ioc->name,
+ __FILE__, __LINE__, __func__));
+ return 1;
}
- if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
- qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
- ssp_target = 1;
- ds = "SSP";
- } else {
- qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
- if (sas_device->device_info &
- MPI2_SAS_DEVICE_INFO_STP_TARGET)
- ds = "STP";
- else if (sas_device->device_info &
- MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
- ds = "SATA";
+ if (volume_handle && mpt2sas_config_get_volume_wwid(ioc,
+ volume_handle, &volume_wwid)) {
+ dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+ "failure at %s:%d/%s()!\n", ioc->name,
+ __FILE__, __LINE__, __func__));
+ return 1;
}
+ }
- sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
- "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
- ds, sas_device->handle,
- (unsigned long long)sas_device->sas_address,
- sas_device->phy,
- (unsigned long long)sas_device->device_name);
- sdev_printk(KERN_INFO, sdev, "%s: "
- "enclosure_logical_id(0x%016llx), slot(%d)\n", ds,
- (unsigned long long) sas_device->enclosure_logical_id,
- sas_device->slot);
-
- if (!ssp_target)
- _scsih_display_sata_capabilities(ioc, sas_device, sdev);
- } else {
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_device_priv_data->sas_target->sas_address);
+ if (!sas_device) {
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
- "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
- __func__));
+ "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
+ __LINE__, __func__));
return 1;
}
+ sas_device->volume_handle = volume_handle;
+ sas_device->volume_wwid = volume_wwid;
+ if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
+ qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
+ ssp_target = 1;
+ ds = "SSP";
+ } else {
+ qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
+ if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
+ ds = "STP";
+ else if (sas_device->device_info &
+ MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
+ ds = "SATA";
+ }
+ sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
+ "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
+ ds, sas_device->handle,
+ (unsigned long long)sas_device->sas_address,
+ sas_device->phy,
+ (unsigned long long)sas_device->device_name);
+ sdev_printk(KERN_INFO, sdev, "%s: "
+ "enclosure_logical_id(0x%016llx), slot(%d)\n", ds,
+ (unsigned long long) sas_device->enclosure_logical_id,
+ sas_device->slot);
+
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (!ssp_target)
+ _scsih_display_sata_capabilities(ioc, handle, sdev);
+
_scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
@@ -2899,7 +2915,7 @@ _scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
* During device pull we need to appropiately set the sdev state.
*/
static void
-_scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+_scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
{
struct MPT2SAS_DEVICE *sas_device_priv_data;
struct scsi_device *sdev;
@@ -2910,10 +2926,12 @@ _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
continue;
if (!sas_device_priv_data->block)
continue;
- if (sas_device_priv_data->sas_target->handle == handle) {
+ if (sas_device_priv_data->sas_target->sas_address ==
+ sas_address) {
dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
MPT2SAS_INFO_FMT "SDEV_RUNNING: "
- "handle(0x%04x)\n", ioc->name, handle));
+ "sas address(0x%016llx)\n", ioc->name,
+ (unsigned long long)sas_address));
sas_device_priv_data->block = 0;
scsi_internal_device_unblock(sdev);
}
@@ -3006,10 +3024,10 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc,
sas_device =
mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
mpt2sas_port->remote_identify.sas_address);
+ if (sas_device)
+ set_bit(sas_device->handle,
+ ioc->blocking_handles);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (!sas_device)
- continue;
- _scsih_block_io_device(ioc, sas_device->handle);
}
}
@@ -3020,12 +3038,9 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc,
SAS_EDGE_EXPANDER_DEVICE ||
mpt2sas_port->remote_identify.device_type ==
SAS_FANOUT_EXPANDER_DEVICE) {
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
expander_sibling =
mpt2sas_scsih_expander_find_by_sas_address(
ioc, mpt2sas_port->remote_identify.sas_address);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
_scsih_block_io_to_children_attached_to_ex(ioc,
expander_sibling);
}
@@ -3124,7 +3139,7 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting delete flag: "
"handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle,
(unsigned long long)sas_address));
- _scsih_ublock_io_device(ioc, handle);
+ _scsih_ublock_io_device(ioc, sas_address);
sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
}
@@ -3174,16 +3189,19 @@ static u8
_scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
u8 msix_index, u32 reply)
{
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
Mpi2SasIoUnitControlReply_t *mpi_reply =
mpt2sas_base_get_reply_virt_addr(ioc, reply);
-#endif
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
- "sc_complete:handle(0x%04x), (open) "
- "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
- ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
- le16_to_cpu(mpi_reply->IOCStatus),
- le32_to_cpu(mpi_reply->IOCLogInfo)));
+ if (likely(mpi_reply)) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
+ "sc_complete:handle(0x%04x), (open) "
+ "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
+ le16_to_cpu(mpi_reply->IOCStatus),
+ le32_to_cpu(mpi_reply->IOCLogInfo)));
+ } else {
+ printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ }
return 1;
}
@@ -3262,7 +3280,11 @@ _scsih_tm_volume_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
"progress!\n", __func__, ioc->name));
return 1;
}
-
+ if (unlikely(!mpi_reply)) {
+ printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return 1;
+ }
mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid);
handle = le16_to_cpu(mpi_request_tm->DevHandle);
if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
@@ -3325,7 +3347,11 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
"operational\n", __func__, ioc->name));
return 1;
}
-
+ if (unlikely(!mpi_reply)) {
+ printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return 1;
+ }
mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid);
handle = le16_to_cpu(mpi_request_tm->DevHandle);
if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
@@ -3441,14 +3467,20 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc,
_scsih_block_io_to_children_attached_directly(ioc, event_data);
return;
}
-
- if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING
- || event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) {
+ if (event_data->ExpStatus ==
+ MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) {
+ /* put expander attached devices into blocking state */
spin_lock_irqsave(&ioc->sas_node_lock, flags);
sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
expander_handle);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
_scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+ do {
+ handle = find_first_bit(ioc->blocking_handles,
+ ioc->facts.MaxDevHandle);
+ if (handle < ioc->facts.MaxDevHandle)
+ _scsih_block_io_device(ioc, handle);
+ } while (test_and_clear_bit(handle, ioc->blocking_handles));
} else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
_scsih_block_io_to_children_attached_directly(ioc, event_data);
@@ -4446,8 +4478,8 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
!= MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) {
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
ioc->scsi_lookup[smid - 1].scmd = scmd;
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
_scsih_scsi_direct_io_set(ioc, smid, 0);
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
mpi_request->DevHandle =
cpu_to_le16(sas_device_priv_data->sas_target->handle);
@@ -5020,13 +5052,11 @@ mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
spin_lock_irqsave(&ioc->sas_node_lock, flags);
sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
sas_address);
- if (!sas_expander) {
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- return;
- }
- list_del(&sas_expander->list);
+ if (sas_expander)
+ list_del(&sas_expander->list);
spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- _scsih_expander_node_remove(ioc, sas_expander);
+ if (sas_expander)
+ _scsih_expander_node_remove(ioc, sas_expander);
}
/**
@@ -5106,6 +5136,7 @@ _scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
struct MPT2SAS_TARGET *sas_target_priv_data;
u32 device_info;
+
if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
return;
@@ -5139,21 +5170,24 @@ _scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
sas_target_priv_data->handle = handle;
sas_device->handle = handle;
}
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
/* check if device is present */
if (!(le16_to_cpu(sas_device_pg0.Flags) &
MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
printk(MPT2SAS_ERR_FMT "device is not present "
"handle(0x%04x), flags!!!\n", ioc->name, handle);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
return;
}
/* check if there were any issues with discovery */
if (_scsih_check_access_status(ioc, sas_address, handle,
- sas_device_pg0.AccessStatus))
+ sas_device_pg0.AccessStatus)) {
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
return;
- _scsih_ublock_io_device(ioc, handle);
+ }
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ _scsih_ublock_io_device(ioc, sas_address);
}
@@ -5280,54 +5314,71 @@ static void
_scsih_remove_device(struct MPT2SAS_ADAPTER *ioc,
struct _sas_device *sas_device)
{
- struct _sas_device sas_device_backup;
struct MPT2SAS_TARGET *sas_target_priv_data;
- if (!sas_device)
- return;
-
- memcpy(&sas_device_backup, sas_device, sizeof(struct _sas_device));
- _scsih_sas_device_remove(ioc, sas_device);
-
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: "
"handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
- sas_device_backup.handle, (unsigned long long)
- sas_device_backup.sas_address));
+ sas_device->handle, (unsigned long long)
+ sas_device->sas_address));
- if (sas_device_backup.starget && sas_device_backup.starget->hostdata) {
- sas_target_priv_data = sas_device_backup.starget->hostdata;
+ if (sas_device->starget && sas_device->starget->hostdata) {
+ sas_target_priv_data = sas_device->starget->hostdata;
sas_target_priv_data->deleted = 1;
- _scsih_ublock_io_device(ioc, sas_device_backup.handle);
+ _scsih_ublock_io_device(ioc, sas_device->sas_address);
sas_target_priv_data->handle =
MPT2SAS_INVALID_DEVICE_HANDLE;
}
- _scsih_ublock_io_device(ioc, sas_device_backup.handle);
-
if (!ioc->hide_drives)
mpt2sas_transport_port_remove(ioc,
- sas_device_backup.sas_address,
- sas_device_backup.sas_address_parent);
+ sas_device->sas_address,
+ sas_device->sas_address_parent);
printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr"
- "(0x%016llx)\n", ioc->name, sas_device_backup.handle,
- (unsigned long long) sas_device_backup.sas_address);
+ "(0x%016llx)\n", ioc->name, sas_device->handle,
+ (unsigned long long) sas_device->sas_address);
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit: "
"handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
- sas_device_backup.handle, (unsigned long long)
- sas_device_backup.sas_address));
+ sas_device->handle, (unsigned long long)
+ sas_device->sas_address));
+ kfree(sas_device);
+}
+/**
+ * _scsih_device_remove_by_handle - removing device object by handle
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * Return nothing.
+ */
+static void
+_scsih_device_remove_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ struct _sas_device *sas_device;
+ unsigned long flags;
+
+ if (ioc->shost_recovery)
+ return;
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ if (sas_device)
+ list_del(&sas_device->list);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (sas_device)
+ _scsih_remove_device(ioc, sas_device);
}
/**
- * mpt2sas_device_remove - removing device object
+ * mpt2sas_device_remove_by_sas_address - removing device object by sas address
* @ioc: per adapter object
- * @sas_address: expander sas_address
+ * @sas_address: device sas_address
*
* Return nothing.
*/
void
-mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
+mpt2sas_device_remove_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
+ u64 sas_address)
{
struct _sas_device *sas_device;
unsigned long flags;
@@ -5338,14 +5389,12 @@ mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
sas_address);
- if (!sas_device) {
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return;
- }
+ if (sas_device)
+ list_del(&sas_device->list);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- _scsih_remove_device(ioc, sas_device);
+ if (sas_device)
+ _scsih_remove_device(ioc, sas_device);
}
-
#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
/**
* _scsih_sas_topology_change_event_debug - debug for topology event
@@ -5442,7 +5491,6 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
u16 reason_code;
u8 phy_number, max_phys;
struct _sas_node *sas_expander;
- struct _sas_device *sas_device;
u64 sas_address;
unsigned long flags;
u8 link_rate, prev_link_rate;
@@ -5477,15 +5525,17 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
spin_lock_irqsave(&ioc->sas_node_lock, flags);
sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
parent_handle);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
if (sas_expander) {
sas_address = sas_expander->sas_address;
max_phys = sas_expander->num_phys;
} else if (parent_handle < ioc->sas_hba.num_phys) {
sas_address = ioc->sas_hba.sas_address;
max_phys = ioc->sas_hba.num_phys;
- } else
+ } else {
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
return;
+ }
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
/* handle siblings events */
for (i = 0; i < event_data->NumEntries; i++) {
@@ -5540,16 +5590,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
break;
case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc,
- handle);
- if (!sas_device) {
- spin_unlock_irqrestore(&ioc->sas_device_lock,
- flags);
- break;
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- _scsih_remove_device(ioc, sas_device);
+ _scsih_device_remove_by_handle(ioc, handle);
break;
}
}
@@ -5672,20 +5713,24 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc,
sas_address = le64_to_cpu(event_data->SASAddress);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
sas_address);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (!sas_device || !sas_device->starget)
+ if (!sas_device || !sas_device->starget) {
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
return;
+ }
target_priv_data = sas_device->starget->hostdata;
- if (!target_priv_data)
+ if (!target_priv_data) {
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
return;
+ }
if (event_data->ReasonCode ==
MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
target_priv_data->tm_busy = 1;
else
target_priv_data->tm_busy = 0;
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
}
#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
@@ -5950,30 +5995,6 @@ _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
}
/**
- * _scsih_reprobe_target - reprobing target
- * @starget: scsi target struct
- * @no_uld_attach: sdev->no_uld_attach flag setting
- *
- * Note: no_uld_attach flag determines whether the disk device is attached
- * to block layer. A value of `1` means to not attach.
- **/
-static void
-_scsih_reprobe_target(struct scsi_target *starget, int no_uld_attach)
-{
- struct MPT2SAS_TARGET *sas_target_priv_data;
-
- if (starget == NULL)
- return;
- sas_target_priv_data = starget->hostdata;
- if (no_uld_attach)
- sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
- else
- sas_target_priv_data->flags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
-
- starget_for_each_device(starget, no_uld_attach ? (void *)1 : NULL,
- _scsih_reprobe_lun);
-}
-/**
* _scsih_sas_volume_add - add new volume
* @ioc: per adapter object
* @element: IR config element data
@@ -6024,8 +6045,11 @@ _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc,
raid_device->id, 0);
if (rc)
_scsih_raid_device_remove(ioc, raid_device);
- } else
+ } else {
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
_scsih_determine_boot_device(ioc, raid_device, 1);
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+ }
}
/**
@@ -6042,21 +6066,25 @@ _scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, u16 handle)
struct _raid_device *raid_device;
unsigned long flags;
struct MPT2SAS_TARGET *sas_target_priv_data;
+ struct scsi_target *starget = NULL;
spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- if (!raid_device)
- return;
- if (raid_device->starget) {
- sas_target_priv_data = raid_device->starget->hostdata;
- sas_target_priv_data->deleted = 1;
- scsi_remove_target(&raid_device->starget->dev);
+ if (raid_device) {
+ if (raid_device->starget) {
+ starget = raid_device->starget;
+ sas_target_priv_data = starget->hostdata;
+ sas_target_priv_data->deleted = 1;
+ }
+ printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
+ "(0x%016llx)\n", ioc->name, raid_device->handle,
+ (unsigned long long) raid_device->wwid);
+ list_del(&raid_device->list);
+ kfree(raid_device);
}
- printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
- "(0x%016llx)\n", ioc->name, raid_device->handle,
- (unsigned long long) raid_device->wwid);
- _scsih_raid_device_remove(ioc, raid_device);
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+ if (starget)
+ scsi_remove_target(&starget->dev);
}
/**
@@ -6072,20 +6100,31 @@ _scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc,
Mpi2EventIrConfigElement_t *element)
{
struct _sas_device *sas_device;
+ struct scsi_target *starget = NULL;
+ struct MPT2SAS_TARGET *sas_target_priv_data;
unsigned long flags;
u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ if (sas_device) {
+ sas_device->volume_handle = 0;
+ sas_device->volume_wwid = 0;
+ clear_bit(handle, ioc->pd_handles);
+ if (sas_device->starget && sas_device->starget->hostdata) {
+ starget = sas_device->starget;
+ sas_target_priv_data = starget->hostdata;
+ sas_target_priv_data->flags &=
+ ~MPT_TARGET_FLAGS_RAID_COMPONENT;
+ }
+ }
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (!sas_device)
return;
/* exposing raid component */
- sas_device->volume_handle = 0;
- sas_device->volume_wwid = 0;
- clear_bit(handle, ioc->pd_handles);
- _scsih_reprobe_target(sas_device->starget, 0);
+ if (starget)
+ starget_for_each_device(starget, NULL, _scsih_reprobe_lun);
}
/**
@@ -6101,23 +6140,38 @@ _scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc,
Mpi2EventIrConfigElement_t *element)
{
struct _sas_device *sas_device;
+ struct scsi_target *starget = NULL;
+ struct MPT2SAS_TARGET *sas_target_priv_data;
unsigned long flags;
u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
+ u16 volume_handle = 0;
+ u64 volume_wwid = 0;
+
+ mpt2sas_config_get_volume_handle(ioc, handle, &volume_handle);
+ if (volume_handle)
+ mpt2sas_config_get_volume_wwid(ioc, volume_handle,
+ &volume_wwid);
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ if (sas_device) {
+ set_bit(handle, ioc->pd_handles);
+ if (sas_device->starget && sas_device->starget->hostdata) {
+ starget = sas_device->starget;
+ sas_target_priv_data = starget->hostdata;
+ sas_target_priv_data->flags |=
+ MPT_TARGET_FLAGS_RAID_COMPONENT;
+ sas_device->volume_handle = volume_handle;
+ sas_device->volume_wwid = volume_wwid;
+ }
+ }
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (!sas_device)
return;
/* hiding raid component */
- mpt2sas_config_get_volume_handle(ioc, handle,
- &sas_device->volume_handle);
- mpt2sas_config_get_volume_wwid(ioc, sas_device->volume_handle,
- &sas_device->volume_wwid);
- set_bit(handle, ioc->pd_handles);
- _scsih_reprobe_target(sas_device->starget, 1);
-
+ if (starget)
+ starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun);
}
/**
@@ -6132,16 +6186,9 @@ static void
_scsih_sas_pd_delete(struct MPT2SAS_ADAPTER *ioc,
Mpi2EventIrConfigElement_t *element)
{
- struct _sas_device *sas_device;
- unsigned long flags;
u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (!sas_device)
- return;
- _scsih_remove_device(ioc, sas_device);
+ _scsih_device_remove_by_handle(ioc, handle);
}
/**
@@ -6583,18 +6630,13 @@ _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc,
/* code added for raid transport support */
if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
- handle = le16_to_cpu(event_data->VolDevHandle);
-
spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ handle = le16_to_cpu(event_data->VolDevHandle);
raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-
- if (!raid_device)
- return;
-
- if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC)
+ if (raid_device)
raid_device->percent_complete =
event_data->PercentComplete;
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
}
}
@@ -6761,13 +6803,18 @@ _scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid,
* required data for Direct IO
*/
_scsih_init_warpdrive_properties(ioc, raid_device);
- if (raid_device->handle == handle)
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ if (raid_device->handle == handle) {
+ spin_unlock_irqrestore(&ioc->raid_device_lock,
+ flags);
return;
+ }
printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
raid_device->handle);
raid_device->handle = handle;
if (sas_target_priv_data)
sas_target_priv_data->handle = handle;
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
return;
}
}
@@ -6939,58 +6986,56 @@ static void
_scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
{
struct _sas_device *sas_device, *sas_device_next;
- struct _sas_node *sas_expander;
+ struct _sas_node *sas_expander, *sas_expander_next;
struct _raid_device *raid_device, *raid_device_next;
+ struct list_head tmp_list;
+ unsigned long flags;
printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n",
ioc->name);
+ /* removing unresponding end devices */
+ printk(MPT2SAS_INFO_FMT "removing unresponding devices: end-devices\n",
+ ioc->name);
list_for_each_entry_safe(sas_device, sas_device_next,
&ioc->sas_device_list, list) {
- if (sas_device->responding) {
+ if (!sas_device->responding)
+ mpt2sas_device_remove_by_sas_address(ioc,
+ sas_device->sas_address);
+ else
sas_device->responding = 0;
- continue;
- }
- if (sas_device->starget)
- starget_printk(KERN_INFO, sas_device->starget,
- "removing: handle(0x%04x), sas_addr(0x%016llx), "
- "enclosure logical id(0x%016llx), slot(%d)\n",
- sas_device->handle,
- (unsigned long long)sas_device->sas_address,
- (unsigned long long)
- sas_device->enclosure_logical_id,
- sas_device->slot);
- _scsih_remove_device(ioc, sas_device);
}
- if (!ioc->ir_firmware)
- goto retry_expander_search;
-
- list_for_each_entry_safe(raid_device, raid_device_next,
- &ioc->raid_device_list, list) {
- if (raid_device->responding) {
- raid_device->responding = 0;
- continue;
- }
- if (raid_device->starget) {
- starget_printk(KERN_INFO, raid_device->starget,
- "removing: handle(0x%04x), wwid(0x%016llx)\n",
- raid_device->handle,
- (unsigned long long)raid_device->wwid);
- scsi_remove_target(&raid_device->starget->dev);
+ /* removing unresponding volumes */
+ if (ioc->ir_firmware) {
+ printk(MPT2SAS_INFO_FMT "removing unresponding devices: "
+ "volumes\n", ioc->name);
+ list_for_each_entry_safe(raid_device, raid_device_next,
+ &ioc->raid_device_list, list) {
+ if (!raid_device->responding)
+ _scsih_sas_volume_delete(ioc,
+ raid_device->handle);
+ else
+ raid_device->responding = 0;
}
- _scsih_raid_device_remove(ioc, raid_device);
}
-
- retry_expander_search:
- sas_expander = NULL;
- list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
- if (sas_expander->responding) {
+ /* removing unresponding expanders */
+ printk(MPT2SAS_INFO_FMT "removing unresponding devices: expanders\n",
+ ioc->name);
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ INIT_LIST_HEAD(&tmp_list);
+ list_for_each_entry_safe(sas_expander, sas_expander_next,
+ &ioc->sas_expander_list, list) {
+ if (!sas_expander->responding)
+ list_move_tail(&sas_expander->list, &tmp_list);
+ else
sas_expander->responding = 0;
- continue;
- }
- mpt2sas_expander_remove(ioc, sas_expander->sas_address);
- goto retry_expander_search;
+ }
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+ list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list,
+ list) {
+ list_del(&sas_expander->list);
+ _scsih_expander_node_remove(ioc, sas_expander);
}
printk(MPT2SAS_INFO_FMT "removing unresponding devices: complete\n",
ioc->name);
@@ -7043,6 +7088,7 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
struct _sas_device *sas_device;
struct _sas_node *expander_device;
static struct _raid_device *raid_device;
+ unsigned long flags;
printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name);
@@ -7057,8 +7103,10 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
handle = le16_to_cpu(expander_pg0.DevHandle);
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
expander_device = mpt2sas_scsih_expander_find_by_sas_address(
ioc, le64_to_cpu(expander_pg0.SASAddress));
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
if (expander_device)
_scsih_refresh_expander_links(ioc, expander_device,
handle);
@@ -7080,7 +7128,9 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
break;
phys_disk_num = pd_pg0.PhysDiskNum;
handle = le16_to_cpu(pd_pg0.DevHandle);
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (sas_device)
continue;
if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
@@ -7107,8 +7157,10 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
handle = le16_to_cpu(volume_pg1.DevHandle);
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_wwid(ioc,
le64_to_cpu(volume_pg1.WWID));
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
if (raid_device)
continue;
if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
@@ -7140,8 +7192,10 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
if (!(_scsih_is_end_device(
le32_to_cpu(sas_device_pg0.DeviceInfo))))
continue;
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
le64_to_cpu(sas_device_pg0.SASAddress));
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (sas_device)
continue;
parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
@@ -7235,7 +7289,7 @@ _firmware_event_work(struct work_struct *work)
switch (fw_event->event) {
case MPT2SAS_REMOVE_UNRESPONDING_DEVICES:
- while (scsi_host_in_recovery(ioc->shost))
+ while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery)
ssleep(1);
_scsih_remove_unresponding_sas_devices(ioc);
_scsih_scan_for_devices_after_reset(ioc);
@@ -7313,6 +7367,13 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
return 1;
mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+
+ if (unlikely(!mpi_reply)) {
+ printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return 1;
+ }
+
event = le16_to_cpu(mpi_reply->Event);
switch (event) {
@@ -7353,14 +7414,14 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
case MPI2_EVENT_LOG_ENTRY_ADDED:
{
Mpi2EventDataLogEntryAdded_t *log_entry;
- u32 *log_code;
+ __le32 *log_code;
if (!ioc->is_warpdrive)
break;
log_entry = (Mpi2EventDataLogEntryAdded_t *)
mpi_reply->EventData;
- log_code = (u32 *)log_entry->LogData;
+ log_code = (__le32 *)log_entry->LogData;
if (le16_to_cpu(log_entry->LogEntryQualifier)
!= MPT2_WARPDRIVE_LOGENTRY)
@@ -7487,7 +7548,7 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
return;
if (mpt2sas_port->remote_identify.device_type ==
SAS_END_DEVICE)
- mpt2sas_device_remove(ioc,
+ mpt2sas_device_remove_by_sas_address(ioc,
mpt2sas_port->remote_identify.sas_address);
else if (mpt2sas_port->remote_identify.device_type ==
SAS_EDGE_EXPANDER_DEVICE ||
@@ -7661,7 +7722,7 @@ _scsih_remove(struct pci_dev *pdev)
&ioc->sas_hba.sas_port_list, port_list) {
if (mpt2sas_port->remote_identify.device_type ==
SAS_END_DEVICE)
- mpt2sas_device_remove(ioc,
+ mpt2sas_device_remove_by_sas_address(ioc,
mpt2sas_port->remote_identify.sas_address);
else if (mpt2sas_port->remote_identify.device_type ==
SAS_EDGE_EXPANDER_DEVICE ||
@@ -7733,11 +7794,11 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
if (rc)
_scsih_raid_device_remove(ioc, raid_device);
} else {
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = device;
handle = sas_device->handle;
sas_address_parent = sas_device->sas_address_parent;
sas_address = sas_device->sas_address;
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
list_move_tail(&sas_device->list, &ioc->sas_device_list);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
@@ -8061,8 +8122,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
out_thread_fail:
list_del(&ioc->list);
scsi_remove_host(shost);
- scsi_host_put(shost);
out_add_shost_fail:
+ scsi_host_put(shost);
return -ENODEV;
}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index 831047466a5a..c6cf20f60720 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -163,12 +163,15 @@ _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
return -EIO;
}
- memset(identify, 0, sizeof(*identify));
+ memset(identify, 0, sizeof(struct sas_identify));
device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
/* sas_address */
identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
+ /* phy number of the parent device this device is linked to */
+ identify->phy_identifier = sas_device_pg0.PhyNum;
+
/* device_type */
switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
@@ -484,7 +487,7 @@ _transport_delete_port(struct MPT2SAS_ADAPTER *ioc,
ioc->logging_level |= MPT_DEBUG_TRANSPORT;
if (device_type == SAS_END_DEVICE)
- mpt2sas_device_remove(ioc, sas_address);
+ mpt2sas_device_remove_by_sas_address(ioc, sas_address);
else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
device_type == SAS_FANOUT_EXPANDER_DEVICE)
mpt2sas_expander_remove(ioc, sas_address);
@@ -792,9 +795,10 @@ mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
spin_lock_irqsave(&ioc->sas_node_lock, flags);
sas_node = _transport_sas_node_find_by_sas_address(ioc,
sas_address_parent);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- if (!sas_node)
+ if (!sas_node) {
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
return;
+ }
list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
port_list) {
if (mpt2sas_port->remote_identify.sas_address != sas_address)
@@ -804,8 +808,10 @@ mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
goto out;
}
out:
- if (!found)
+ if (!found) {
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
return;
+ }
for (i = 0; i < sas_node->num_phys; i++) {
if (sas_node->phy[i].remote_identify.sas_address == sas_address)
@@ -813,6 +819,7 @@ mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
sizeof(struct sas_identify));
}
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
list_for_each_entry_safe(mpt2sas_phy, next_phy,
&mpt2sas_port->phy_list, port_siblings) {
if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
@@ -986,12 +993,14 @@ mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
spin_lock_irqsave(&ioc->sas_node_lock, flags);
sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- if (!sas_node)
+ if (!sas_node) {
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
return;
+ }
mpt2sas_phy = &sas_node->phy[phy_number];
mpt2sas_phy->attached_handle = handle;
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
_transport_set_identify(ioc, handle,
&mpt2sas_phy->remote_identify);
@@ -1310,17 +1319,20 @@ _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
struct _sas_device *sas_device;
unsigned long flags;
+ int rc;
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
rphy->identify.sas_address);
+ if (sas_device) {
+ *identifier = sas_device->enclosure_logical_id;
+ rc = 0;
+ } else {
+ *identifier = 0;
+ rc = -ENXIO;
+ }
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- if (!sas_device)
- return -ENXIO;
-
- *identifier = sas_device->enclosure_logical_id;
- return 0;
+ return rc;
}
/**
@@ -1335,16 +1347,17 @@ _transport_get_bay_identifier(struct sas_rphy *rphy)
struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
struct _sas_device *sas_device;
unsigned long flags;
+ int rc;
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
rphy->identify.sas_address);
+ if (sas_device)
+ rc = sas_device->slot;
+ else
+ rc = -ENXIO;
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- if (!sas_device)
- return -ENXIO;
-
- return sas_device->slot;
+ return rc;
}
/* phy control request structure */
@@ -1629,11 +1642,13 @@ _transport_phy_enable(struct sas_phy *phy, int enable)
{
struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
+ Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
Mpi2ConfigReply_t mpi_reply;
u16 ioc_status;
u16 sz;
int rc = 0;
unsigned long flags;
+ int i, discovery_active;
spin_lock_irqsave(&ioc->sas_node_lock, flags);
if (_transport_sas_node_find_by_sas_address(ioc,
@@ -1651,7 +1666,50 @@ _transport_phy_enable(struct sas_phy *phy, int enable)
/* handle hba phys */
- /* sas_iounit page 1 */
+ /* read sas_iounit page 0 */
+ sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
+ sizeof(Mpi2SasIOUnit0PhyData_t));
+ sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
+ if (!sas_iounit_pg0) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ rc = -ENOMEM;
+ goto out;
+ }
+ if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
+ sas_iounit_pg0, sz))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ rc = -ENXIO;
+ goto out;
+ }
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ rc = -EIO;
+ goto out;
+ }
+
+ /* unable to enable/disable phys when when discovery is active */
+ for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) {
+ if (sas_iounit_pg0->PhyData[i].PortFlags &
+ MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) {
+ printk(MPT2SAS_ERR_FMT "discovery is active on "
+ "port = %d, phy = %d: unable to enable/disable "
+ "phys, try again later!\n", ioc->name,
+ sas_iounit_pg0->PhyData[i].Port, i);
+ discovery_active = 1;
+ }
+ }
+
+ if (discovery_active) {
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ /* read sas_iounit page 1 */
sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
sizeof(Mpi2SasIOUnit1PhyData_t));
sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
@@ -1676,7 +1734,18 @@ _transport_phy_enable(struct sas_phy *phy, int enable)
rc = -EIO;
goto out;
}
-
+ /* copy Port/PortFlags/PhyFlags from page 0 */
+ for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
+ sas_iounit_pg1->PhyData[i].Port =
+ sas_iounit_pg0->PhyData[i].Port;
+ sas_iounit_pg1->PhyData[i].PortFlags =
+ (sas_iounit_pg0->PhyData[i].PortFlags &
+ MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG);
+ sas_iounit_pg1->PhyData[i].PhyFlags =
+ (sas_iounit_pg0->PhyData[i].PhyFlags &
+ (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED +
+ MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED));
+ }
if (enable)
sas_iounit_pg1->PhyData[phy->number].PhyFlags
&= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
@@ -1692,6 +1761,7 @@ _transport_phy_enable(struct sas_phy *phy, int enable)
out:
kfree(sas_iounit_pg1);
+ kfree(sas_iounit_pg0);
return rc;
}
@@ -1828,7 +1898,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
Mpi2SmpPassthroughRequest_t *mpi_request;
Mpi2SmpPassthroughReply_t *mpi_reply;
- int rc;
+ int rc, i;
u16 smid;
u32 ioc_state;
unsigned long timeleft;
@@ -1837,24 +1907,20 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
u8 issue_reset = 0;
dma_addr_t dma_addr_in = 0;
dma_addr_t dma_addr_out = 0;
+ dma_addr_t pci_dma_in = 0;
+ dma_addr_t pci_dma_out = 0;
+ void *pci_addr_in = NULL;
+ void *pci_addr_out = NULL;
u16 wait_state_count;
struct request *rsp = req->next_rq;
+ struct bio_vec *bvec = NULL;
if (!rsp) {
printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
"missing\n", ioc->name, __func__);
return -EINVAL;
}
-
- /* do we need to support multiple segments? */
- if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
- printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, "
- "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt,
- blk_rq_bytes(req), rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
- return -EINVAL;
- }
-
- if (ioc->shost_recovery) {
+ if (ioc->shost_recovery || ioc->pci_error_recovery) {
printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
__func__, ioc->name);
return -EFAULT;
@@ -1872,6 +1938,59 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
}
ioc->transport_cmds.status = MPT2_CMD_PENDING;
+ /* Check if the request is split across multiple segments */
+ if (req->bio->bi_vcnt > 1) {
+ u32 offset = 0;
+
+ /* Allocate memory and copy the request */
+ pci_addr_out = pci_alloc_consistent(ioc->pdev,
+ blk_rq_bytes(req), &pci_dma_out);
+ if (!pci_addr_out) {
+ printk(MPT2SAS_INFO_FMT "%s(): PCI Addr out = NULL\n",
+ ioc->name, __func__);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ bio_for_each_segment(bvec, req->bio, i) {
+ memcpy(pci_addr_out + offset,
+ page_address(bvec->bv_page) + bvec->bv_offset,
+ bvec->bv_len);
+ offset += bvec->bv_len;
+ }
+ } else {
+ dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
+ blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
+ if (!dma_addr_out) {
+ printk(MPT2SAS_INFO_FMT "%s(): DMA Addr out = NULL\n",
+ ioc->name, __func__);
+ rc = -ENOMEM;
+ goto free_pci;
+ }
+ }
+
+ /* Check if the response needs to be populated across
+ * multiple segments */
+ if (rsp->bio->bi_vcnt > 1) {
+ pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp),
+ &pci_dma_in);
+ if (!pci_addr_in) {
+ printk(MPT2SAS_INFO_FMT "%s(): PCI Addr in = NULL\n",
+ ioc->name, __func__);
+ rc = -ENOMEM;
+ goto unmap;
+ }
+ } else {
+ dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
+ blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
+ if (!dma_addr_in) {
+ printk(MPT2SAS_INFO_FMT "%s(): DMA Addr in = NULL\n",
+ ioc->name, __func__);
+ rc = -ENOMEM;
+ goto unmap;
+ }
+ }
+
wait_state_count = 0;
ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
@@ -1880,7 +1999,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
"%s: failed due to ioc not operational\n",
ioc->name, __func__);
rc = -EFAULT;
- goto out;
+ goto unmap;
}
ssleep(1);
ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
@@ -1897,7 +2016,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
ioc->name, __func__);
rc = -EAGAIN;
- goto out;
+ goto unmap;
}
rc = 0;
@@ -1919,16 +2038,14 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
- blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
- if (!dma_addr_out) {
- mpt2sas_base_free_smid(ioc, smid);
- goto unmap;
+ if (req->bio->bi_vcnt > 1) {
+ ioc->base_add_sg_single(psge, sgl_flags |
+ (blk_rq_bytes(req) - 4), pci_dma_out);
+ } else {
+ ioc->base_add_sg_single(psge, sgl_flags |
+ (blk_rq_bytes(req) - 4), dma_addr_out);
}
- ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(req) - 4),
- dma_addr_out);
-
/* incr sgel */
psge += ioc->sge_size;
@@ -1937,16 +2054,14 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
MPI2_SGE_FLAGS_END_OF_LIST);
sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
- dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
- blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
- if (!dma_addr_in) {
- mpt2sas_base_free_smid(ioc, smid);
- goto unmap;
+ if (rsp->bio->bi_vcnt > 1) {
+ ioc->base_add_sg_single(psge, sgl_flags |
+ (blk_rq_bytes(rsp) + 4), pci_dma_in);
+ } else {
+ ioc->base_add_sg_single(psge, sgl_flags |
+ (blk_rq_bytes(rsp) + 4), dma_addr_in);
}
- ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4),
- dma_addr_in);
-
dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
"sending smp request\n", ioc->name, __func__));
@@ -1982,6 +2097,27 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
req->resid_len = 0;
rsp->resid_len -=
le16_to_cpu(mpi_reply->ResponseDataLength);
+ /* check if the resp needs to be copied from the allocated
+ * pci mem */
+ if (rsp->bio->bi_vcnt > 1) {
+ u32 offset = 0;
+ u32 bytes_to_copy =
+ le16_to_cpu(mpi_reply->ResponseDataLength);
+ bio_for_each_segment(bvec, rsp->bio, i) {
+ if (bytes_to_copy <= bvec->bv_len) {
+ memcpy(page_address(bvec->bv_page) +
+ bvec->bv_offset, pci_addr_in +
+ offset, bytes_to_copy);
+ break;
+ } else {
+ memcpy(page_address(bvec->bv_page) +
+ bvec->bv_offset, pci_addr_in +
+ offset, bvec->bv_len);
+ bytes_to_copy -= bvec->bv_len;
+ }
+ offset += bvec->bv_len;
+ }
+ }
} else {
dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
"%s - no reply\n", ioc->name, __func__));
@@ -2003,6 +2139,15 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
PCI_DMA_BIDIRECTIONAL);
+ free_pci:
+ if (pci_addr_out)
+ pci_free_consistent(ioc->pdev, blk_rq_bytes(req), pci_addr_out,
+ pci_dma_out);
+
+ if (pci_addr_in)
+ pci_free_consistent(ioc->pdev, blk_rq_bytes(rsp), pci_addr_in,
+ pci_dma_in);
+
out:
ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
mutex_unlock(&ioc->transport_cmds.mutex);
diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h
index 944afada61ee..c3d20c8d4abe 100644
--- a/drivers/scsi/pm8001/pm8001_defs.h
+++ b/drivers/scsi/pm8001/pm8001_defs.h
@@ -66,9 +66,10 @@ enum port_type {
/* driver compile-time configuration */
#define PM8001_MAX_CCB 512 /* max ccbs supported */
+#define PM8001_MPI_QUEUE 1024 /* maximum mpi queue entries */
#define PM8001_MAX_INB_NUM 1
#define PM8001_MAX_OUTB_NUM 1
-#define PM8001_CAN_QUEUE 128 /* SCSI Queue depth */
+#define PM8001_CAN_QUEUE 508 /* SCSI Queue depth */
/* unchangeable hardware details */
#define PM8001_MAX_PHYS 8 /* max. possible phys */
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 9d82ee5c10de..bf54aafc2d71 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -192,7 +192,7 @@ init_default_table_values(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->main_cfg_tbl.fatal_err_interrupt = 0x01;
for (i = 0; i < qn; i++) {
pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt =
- 0x00000100 | (0x00000040 << 16) | (0x00<<30);
+ PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30);
pm8001_ha->inbnd_q_tbl[i].upper_base_addr =
pm8001_ha->memoryMap.region[IB].phys_addr_hi;
pm8001_ha->inbnd_q_tbl[i].lower_base_addr =
@@ -218,7 +218,7 @@ init_default_table_values(struct pm8001_hba_info *pm8001_ha)
}
for (i = 0; i < qn; i++) {
pm8001_ha->outbnd_q_tbl[i].element_size_cnt =
- 256 | (64 << 16) | (1<<30);
+ PM8001_MPI_QUEUE | (64 << 16) | (0x01<<30);
pm8001_ha->outbnd_q_tbl[i].upper_base_addr =
pm8001_ha->memoryMap.region[OB].phys_addr_hi;
pm8001_ha->outbnd_q_tbl[i].lower_base_addr =
@@ -1245,7 +1245,7 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ,
/* Stores the new consumer index */
consumer_index = pm8001_read_32(circularQ->ci_virt);
circularQ->consumer_index = cpu_to_le32(consumer_index);
- if (((circularQ->producer_idx + bcCount) % 256) ==
+ if (((circularQ->producer_idx + bcCount) % PM8001_MPI_QUEUE) ==
le32_to_cpu(circularQ->consumer_index)) {
*messagePtr = NULL;
return -1;
@@ -1253,7 +1253,8 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ,
/* get memory IOMB buffer address */
offset = circularQ->producer_idx * 64;
/* increment to next bcCount element */
- circularQ->producer_idx = (circularQ->producer_idx + bcCount) % 256;
+ circularQ->producer_idx = (circularQ->producer_idx + bcCount)
+ % PM8001_MPI_QUEUE;
/* Adds that distance to the base of the region virtual address plus
the message header size*/
msgHeader = (struct mpi_msg_hdr *)(circularQ->base_virt + offset);
@@ -1326,7 +1327,8 @@ static u32 mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
return 0;
}
/* free the circular queue buffer elements associated with the message*/
- circularQ->consumer_idx = (circularQ->consumer_idx + bc) % 256;
+ circularQ->consumer_idx = (circularQ->consumer_idx + bc)
+ % PM8001_MPI_QUEUE;
/* update the CI of outbound queue */
pm8001_cw32(pm8001_ha, circularQ->ci_pci_bar, circularQ->ci_offset,
circularQ->consumer_idx);
@@ -1383,7 +1385,8 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
circularQ->consumer_idx =
(circularQ->consumer_idx +
((le32_to_cpu(msgHeader_tmp)
- >> 24) & 0x1f)) % 256;
+ >> 24) & 0x1f))
+ % PM8001_MPI_QUEUE;
msgHeader_tmp = 0;
pm8001_write_32(msgHeader, 0, 0);
/* update the CI of outbound queue */
@@ -1396,7 +1399,7 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
circularQ->consumer_idx =
(circularQ->consumer_idx +
((le32_to_cpu(msgHeader_tmp) >> 24) &
- 0x1f)) % 256;
+ 0x1f)) % PM8001_MPI_QUEUE;
msgHeader_tmp = 0;
pm8001_write_32(msgHeader, 0, 0);
/* update the CI of outbound queue */
@@ -3357,7 +3360,7 @@ mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
struct fw_control_ex fw_control_context;
struct fw_flash_Update_resp *ppayload =
(struct fw_flash_Update_resp *)(piomb + 4);
- u32 tag = ppayload->tag;
+ u32 tag = le32_to_cpu(ppayload->tag);
struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[tag];
status = le32_to_cpu(ppayload->status);
memcpy(&fw_control_context,
@@ -3703,8 +3706,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
*/
static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
{
- u32 pHeader = (u32)*(u32 *)piomb;
- u8 opc = (u8)(pHeader & 0xFFF);
+ __le32 pHeader = *(__le32 *)piomb;
+ u8 opc = (u8)((le32_to_cpu(pHeader)) & 0xFFF);
PM8001_MSG_DBG(pm8001_ha, pm8001_printk("process_one_iomb:"));
diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h
index 1a4611eb0321..d437309cb1e1 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.h
+++ b/drivers/scsi/pm8001/pm8001_hwi.h
@@ -599,7 +599,7 @@ struct fw_flash_Update_req {
*
*/
struct fw_flash_Update_resp {
- dma_addr_t tag;
+ __le32 tag;
__le32 status;
u32 reserved[13];
} __attribute__((packed, aligned(4)));
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 36efaa7c3a54..0267c22f8741 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -235,15 +235,15 @@ static int __devinit pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->memoryMap.region[PI].alignment = 4;
/* MPI Memory region 5 inbound queues */
- pm8001_ha->memoryMap.region[IB].num_elements = 256;
+ pm8001_ha->memoryMap.region[IB].num_elements = PM8001_MPI_QUEUE;
pm8001_ha->memoryMap.region[IB].element_size = 64;
- pm8001_ha->memoryMap.region[IB].total_len = 256 * 64;
+ pm8001_ha->memoryMap.region[IB].total_len = PM8001_MPI_QUEUE * 64;
pm8001_ha->memoryMap.region[IB].alignment = 64;
- /* MPI Memory region 6 inbound queues */
- pm8001_ha->memoryMap.region[OB].num_elements = 256;
+ /* MPI Memory region 6 outbound queues */
+ pm8001_ha->memoryMap.region[OB].num_elements = PM8001_MPI_QUEUE;
pm8001_ha->memoryMap.region[OB].element_size = 64;
- pm8001_ha->memoryMap.region[OB].total_len = 256 * 64;
+ pm8001_ha->memoryMap.region[OB].total_len = PM8001_MPI_QUEUE * 64;
pm8001_ha->memoryMap.region[OB].alignment = 64;
/* Memory region write DMA*/
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 6c6486f626ee..538230be5cca 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -4473,17 +4473,14 @@ qla1280_exit(void)
pci_unregister_driver(&qla1280_pci_driver);
/* release any allocated firmware images */
for (i = 0; i < QL_NUM_FW_IMAGES; i++) {
- if (qla1280_fw_tbl[i].fw) {
- release_firmware(qla1280_fw_tbl[i].fw);
- qla1280_fw_tbl[i].fw = NULL;
- }
+ release_firmware(qla1280_fw_tbl[i].fw);
+ qla1280_fw_tbl[i].fw = NULL;
}
}
module_init(qla1280_init);
module_exit(qla1280_exit);
-
MODULE_AUTHOR("Qlogic & Jes Sorensen");
MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7db803377c64..c9c56a8427f3 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4122,8 +4122,7 @@ qla2x00_release_firmware(void)
mutex_lock(&qla_fw_lock);
for (idx = 0; idx < FW_BLOBS; idx++)
- if (qla_fw_blobs[idx].fw)
- release_firmware(qla_fw_blobs[idx].fw);
+ release_firmware(qla_fw_blobs[idx].fw);
mutex_unlock(&qla_fw_lock);
}
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 07322ecff90d..61c82a345f82 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -90,6 +90,12 @@ unsigned int scsi_logging_level;
EXPORT_SYMBOL(scsi_logging_level);
#endif
+#if IS_ENABLED(CONFIG_PM) || IS_ENABLED(CONFIG_BLK_DEV_SD)
+/* sd and scsi_pm need to coordinate flushing async actions */
+LIST_HEAD(scsi_sd_probe_domain);
+EXPORT_SYMBOL(scsi_sd_probe_domain);
+#endif
+
/* NB: These are exposed through /proc/scsi/scsi and form part of the ABI.
* You may not alter any existing entry (although adding new ones is
* encouraged once assigned by ANSI/INCITS T10
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 386f0c53bea7..d0f71e5d065f 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -664,7 +664,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
}
/**
- * scsi_eh_prep_cmnd - Save a scsi command info as part of error recory
+ * scsi_eh_prep_cmnd - Save a scsi command info as part of error recovery
* @scmd: SCSI command structure to hijack
* @ses: structure to save restore information
* @cmnd: CDB to send. Can be NULL if no new cmnd is needed
@@ -739,7 +739,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
EXPORT_SYMBOL(scsi_eh_prep_cmnd);
/**
- * scsi_eh_restore_cmnd - Restore a scsi command info as part of error recory
+ * scsi_eh_restore_cmnd - Restore a scsi command info as part of error recovery
* @scmd: SCSI command structure to restore
* @ses: saved information from a coresponding call to scsi_eh_prep_cmnd
*
@@ -762,7 +762,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
EXPORT_SYMBOL(scsi_eh_restore_cmnd);
/**
- * scsi_send_eh_cmnd - submit a scsi command as part of error recory
+ * scsi_send_eh_cmnd - submit a scsi command as part of error recovery
* @scmd: SCSI command structure to hijack
* @cmnd: CDB to send
* @cmnd_size: size in bytes of @cmnd
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 5dfd7495d1a1..62ddfd31d4ce 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -2348,10 +2348,14 @@ EXPORT_SYMBOL(scsi_device_quiesce);
*
* Must be called with user context, may sleep.
*/
-void
-scsi_device_resume(struct scsi_device *sdev)
+void scsi_device_resume(struct scsi_device *sdev)
{
- if(scsi_device_set_state(sdev, SDEV_RUNNING))
+ /* check if the device state was mutated prior to resume, and if
+ * so assume the state is being managed elsewhere (for example
+ * device deleted during suspend)
+ */
+ if (sdev->sdev_state != SDEV_QUIESCE ||
+ scsi_device_set_state(sdev, SDEV_RUNNING))
return;
scsi_run_queue(sdev->request_queue);
}
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index c4670642d023..f661a41fa4c6 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -97,7 +97,7 @@ static int scsi_bus_prepare(struct device *dev)
{
if (scsi_is_sdev_device(dev)) {
/* sd probing uses async_schedule. Wait until it finishes. */
- async_synchronize_full();
+ async_synchronize_full_domain(&scsi_sd_probe_domain);
} else if (scsi_is_host_device(dev)) {
/* Wait until async scanning is finished */
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index be4fa6d179b1..07ce3f51701d 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -163,6 +163,8 @@ static inline int scsi_autopm_get_host(struct Scsi_Host *h) { return 0; }
static inline void scsi_autopm_put_host(struct Scsi_Host *h) {}
#endif /* CONFIG_PM_RUNTIME */
+extern struct list_head scsi_sd_probe_domain;
+
/*
* internal scsi timeout functions: for use by mid-layer and transport
* classes.
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 80fbe2ac0b47..579760420d53 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -2808,17 +2808,20 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
FC_RPORT_DEVLOSS_PENDING |
FC_RPORT_DEVLOSS_CALLBK_DONE);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
/* if target, initiate a scan */
if (rport->scsi_target_id != -1) {
+ scsi_target_unblock(&rport->dev);
+
+ spin_lock_irqsave(shost->host_lock,
+ flags);
rport->flags |= FC_RPORT_SCAN_PENDING;
scsi_queue_work(shost,
&rport->scan_work);
spin_unlock_irqrestore(shost->host_lock,
flags);
- scsi_target_unblock(&rport->dev);
- } else
- spin_unlock_irqrestore(shost->host_lock,
- flags);
+ }
fc_bsg_goose_queue(rport);
@@ -2876,16 +2879,17 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
if (fci->f->dd_fcrport_size)
memset(rport->dd_data, 0,
fci->f->dd_fcrport_size);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ if (ids->roles & FC_PORT_ROLE_FCP_TARGET) {
+ scsi_target_unblock(&rport->dev);
- if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
/* initiate a scan of the target */
+ spin_lock_irqsave(shost->host_lock, flags);
rport->flags |= FC_RPORT_SCAN_PENDING;
scsi_queue_work(shost, &rport->scan_work);
spin_unlock_irqrestore(shost->host_lock, flags);
- scsi_target_unblock(&rport->dev);
- } else
- spin_unlock_irqrestore(shost->host_lock, flags);
-
+ }
return rport;
}
}
@@ -3083,12 +3087,12 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
/* ensure any stgt delete functions are done */
fc_flush_work(shost);
+ scsi_target_unblock(&rport->dev);
/* initiate a scan of the target */
spin_lock_irqsave(shost->host_lock, flags);
rport->flags |= FC_RPORT_SCAN_PENDING;
scsi_queue_work(shost, &rport->scan_work);
spin_unlock_irqrestore(shost->host_lock, flags);
- scsi_target_unblock(&rport->dev);
}
}
EXPORT_SYMBOL(fc_remote_port_rolechg);
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index a2715c31e754..cf08071a9b6e 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -1010,10 +1010,10 @@ spi_dv_device(struct scsi_device *sdev)
u8 *buffer;
const int len = SPI_MAX_ECHO_BUFFER_SIZE*2;
- if (unlikely(scsi_device_get(sdev)))
+ if (unlikely(spi_dv_in_progress(starget)))
return;
- if (unlikely(spi_dv_in_progress(starget)))
+ if (unlikely(scsi_device_get(sdev)))
return;
spi_dv_in_progress(starget) = 1;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 5ba5c2a9e8e9..6f0a4c612b3b 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -65,6 +65,7 @@
#include <scsi/scsicam.h>
#include "sd.h"
+#include "scsi_priv.h"
#include "scsi_logging.h"
MODULE_AUTHOR("Eric Youngdale");
@@ -2722,7 +2723,7 @@ static int sd_probe(struct device *dev)
dev_set_drvdata(dev, sdkp);
get_device(&sdkp->dev); /* prevent release before async_schedule */
- async_schedule(sd_probe_async, sdkp);
+ async_schedule_domain(sd_probe_async, sdkp, &scsi_sd_probe_domain);
return 0;
@@ -2756,7 +2757,7 @@ static int sd_remove(struct device *dev)
sdkp = dev_get_drvdata(dev);
scsi_autopm_get_device(sdkp->device);
- async_synchronize_full();
+ async_synchronize_full_domain(&scsi_sd_probe_domain);
blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn);
blk_queue_unprep_rq(sdkp->device->request_queue, NULL);
device_del(&sdkp->dev);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index eacd46bb36b9..9c5c5f2b3962 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -104,7 +104,7 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ;
static int sg_add(struct device *, struct class_interface *);
static void sg_remove(struct device *, struct class_interface *);
-static DEFINE_MUTEX(sg_mutex);
+static DEFINE_SPINLOCK(sg_open_exclusive_lock);
static DEFINE_IDR(sg_index_idr);
static DEFINE_RWLOCK(sg_index_lock); /* Also used to lock
@@ -137,13 +137,15 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */
char res_used; /* 1 -> using reserve buffer, 0 -> not ... */
char orphan; /* 1 -> drop on sight, 0 -> normal */
char sg_io_owned; /* 1 -> packet belongs to SG_IO */
- volatile char done; /* 0->before bh, 1->before read, 2->read */
+ /* done protected by rq_list_lock */
+ char done; /* 0->before bh, 1->before read, 2->read */
struct request *rq;
struct bio *bio;
struct execute_work ew;
} Sg_request;
typedef struct sg_fd { /* holds the state of a file descriptor */
+ /* sfd_siblings is protected by sg_index_lock */
struct list_head sfd_siblings;
struct sg_device *parentdp; /* owning device */
wait_queue_head_t read_wait; /* queue read until command done */
@@ -157,7 +159,6 @@ typedef struct sg_fd { /* holds the state of a file descriptor */
Sg_request req_arr[SG_MAX_QUEUE]; /* used as singly-linked list */
char low_dma; /* as in parent but possibly overridden to 1 */
char force_packid; /* 1 -> pack_id input to read(), 0 -> ignored */
- volatile char closed; /* 1 -> fd closed but request(s) outstanding */
char cmd_q; /* 1 -> allow command queuing, 0 -> don't */
char next_cmd_len; /* 0 -> automatic (def), >0 -> use on next write() */
char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */
@@ -171,9 +172,11 @@ typedef struct sg_device { /* holds the state of each scsi generic device */
wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */
int sg_tablesize; /* adapter's max scatter-gather table size */
u32 index; /* device index number */
+ /* sfds is protected by sg_index_lock */
struct list_head sfds;
volatile char detached; /* 0->attached, 1->detached pending removal */
- volatile char exclude; /* opened for exclusive access */
+ /* exclude protected by sg_open_exclusive_lock */
+ char exclude; /* opened for exclusive access */
char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */
struct gendisk *disk;
struct cdev * cdev; /* char_dev [sysfs: /sys/cdev/major/sg<n>] */
@@ -221,6 +224,38 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd)
return blk_verify_command(cmd, filp->f_mode & FMODE_WRITE);
}
+static int get_exclude(Sg_device *sdp)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&sg_open_exclusive_lock, flags);
+ ret = sdp->exclude;
+ spin_unlock_irqrestore(&sg_open_exclusive_lock, flags);
+ return ret;
+}
+
+static int set_exclude(Sg_device *sdp, char val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&sg_open_exclusive_lock, flags);
+ sdp->exclude = val;
+ spin_unlock_irqrestore(&sg_open_exclusive_lock, flags);
+ return val;
+}
+
+static int sfds_list_empty(Sg_device *sdp)
+{
+ unsigned long flags;
+ int ret;
+
+ read_lock_irqsave(&sg_index_lock, flags);
+ ret = list_empty(&sdp->sfds);
+ read_unlock_irqrestore(&sg_index_lock, flags);
+ return ret;
+}
+
static int
sg_open(struct inode *inode, struct file *filp)
{
@@ -232,7 +267,6 @@ sg_open(struct inode *inode, struct file *filp)
int res;
int retval;
- mutex_lock(&sg_mutex);
nonseekable_open(inode, filp);
SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags));
sdp = sg_get_dev(dev);
@@ -264,25 +298,22 @@ sg_open(struct inode *inode, struct file *filp)
retval = -EPERM; /* Can't lock it with read only access */
goto error_out;
}
- if (!list_empty(&sdp->sfds) && (flags & O_NONBLOCK)) {
+ if (!sfds_list_empty(sdp) && (flags & O_NONBLOCK)) {
retval = -EBUSY;
goto error_out;
}
- res = 0;
- __wait_event_interruptible(sdp->o_excl_wait,
- ((!list_empty(&sdp->sfds) || sdp->exclude) ? 0 : (sdp->exclude = 1)), res);
+ res = wait_event_interruptible(sdp->o_excl_wait,
+ ((!sfds_list_empty(sdp) || get_exclude(sdp)) ? 0 : set_exclude(sdp, 1)));
if (res) {
retval = res; /* -ERESTARTSYS because signal hit process */
goto error_out;
}
- } else if (sdp->exclude) { /* some other fd has an exclusive lock on dev */
+ } else if (get_exclude(sdp)) { /* some other fd has an exclusive lock on dev */
if (flags & O_NONBLOCK) {
retval = -EBUSY;
goto error_out;
}
- res = 0;
- __wait_event_interruptible(sdp->o_excl_wait, (!sdp->exclude),
- res);
+ res = wait_event_interruptible(sdp->o_excl_wait, !get_exclude(sdp));
if (res) {
retval = res; /* -ERESTARTSYS because signal hit process */
goto error_out;
@@ -292,7 +323,7 @@ sg_open(struct inode *inode, struct file *filp)
retval = -ENODEV;
goto error_out;
}
- if (list_empty(&sdp->sfds)) { /* no existing opens on this device */
+ if (sfds_list_empty(sdp)) { /* no existing opens on this device */
sdp->sgdebug = 0;
q = sdp->device->request_queue;
sdp->sg_tablesize = queue_max_segments(q);
@@ -301,7 +332,7 @@ sg_open(struct inode *inode, struct file *filp)
filp->private_data = sfp;
else {
if (flags & O_EXCL) {
- sdp->exclude = 0; /* undo if error */
+ set_exclude(sdp, 0); /* undo if error */
wake_up_interruptible(&sdp->o_excl_wait);
}
retval = -ENOMEM;
@@ -317,7 +348,6 @@ sdp_put:
sg_put:
if (sdp)
sg_put_dev(sdp);
- mutex_unlock(&sg_mutex);
return retval;
}
@@ -332,9 +362,7 @@ sg_release(struct inode *inode, struct file *filp)
return -ENXIO;
SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name));
- sfp->closed = 1;
-
- sdp->exclude = 0;
+ set_exclude(sdp, 0);
wake_up_interruptible(&sdp->o_excl_wait);
scsi_autopm_put_device(sdp->device);
@@ -398,19 +426,14 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
retval = -EAGAIN;
goto free_old_hdr;
}
- while (1) {
- retval = 0; /* following macro beats race condition */
- __wait_event_interruptible(sfp->read_wait,
- (sdp->detached ||
- (srp = sg_get_rq_mark(sfp, req_pack_id))),
- retval);
- if (sdp->detached) {
- retval = -ENODEV;
- goto free_old_hdr;
- }
- if (0 == retval)
- break;
-
+ retval = wait_event_interruptible(sfp->read_wait,
+ (sdp->detached ||
+ (srp = sg_get_rq_mark(sfp, req_pack_id))));
+ if (sdp->detached) {
+ retval = -ENODEV;
+ goto free_old_hdr;
+ }
+ if (retval) {
/* -ERESTARTSYS as signal hit process */
goto free_old_hdr;
}
@@ -771,7 +794,18 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
return 0;
}
-static int
+static int srp_done(Sg_fd *sfp, Sg_request *srp)
+{
+ unsigned long flags;
+ int ret;
+
+ read_lock_irqsave(&sfp->rq_list_lock, flags);
+ ret = srp->done;
+ read_unlock_irqrestore(&sfp->rq_list_lock, flags);
+ return ret;
+}
+
+static long
sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
{
void __user *p = (void __user *)arg;
@@ -791,40 +825,30 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
switch (cmd_in) {
case SG_IO:
- {
- int blocking = 1; /* ignore O_NONBLOCK flag */
-
- if (sdp->detached)
- return -ENODEV;
- if (!scsi_block_when_processing_errors(sdp->device))
- return -ENXIO;
- if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR))
- return -EFAULT;
- result =
- sg_new_write(sfp, filp, p, SZ_SG_IO_HDR,
- blocking, read_only, 1, &srp);
- if (result < 0)
- return result;
- while (1) {
- result = 0; /* following macro to beat race condition */
- __wait_event_interruptible(sfp->read_wait,
- (srp->done || sdp->detached),
- result);
- if (sdp->detached)
- return -ENODEV;
- write_lock_irq(&sfp->rq_list_lock);
- if (srp->done) {
- srp->done = 2;
- write_unlock_irq(&sfp->rq_list_lock);
- break;
- }
- srp->orphan = 1;
- write_unlock_irq(&sfp->rq_list_lock);
- return result; /* -ERESTARTSYS because signal hit process */
- }
+ if (sdp->detached)
+ return -ENODEV;
+ if (!scsi_block_when_processing_errors(sdp->device))
+ return -ENXIO;
+ if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR))
+ return -EFAULT;
+ result = sg_new_write(sfp, filp, p, SZ_SG_IO_HDR,
+ 1, read_only, 1, &srp);
+ if (result < 0)
+ return result;
+ result = wait_event_interruptible(sfp->read_wait,
+ (srp_done(sfp, srp) || sdp->detached));
+ if (sdp->detached)
+ return -ENODEV;
+ write_lock_irq(&sfp->rq_list_lock);
+ if (srp->done) {
+ srp->done = 2;
+ write_unlock_irq(&sfp->rq_list_lock);
result = sg_new_read(sfp, p, SZ_SG_IO_HDR, srp);
return (result < 0) ? result : 0;
}
+ srp->orphan = 1;
+ write_unlock_irq(&sfp->rq_list_lock);
+ return result; /* -ERESTARTSYS because signal hit process */
case SG_SET_TIMEOUT:
result = get_user(val, ip);
if (result)
@@ -1091,18 +1115,6 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
}
}
-static long
-sg_unlocked_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
-{
- int ret;
-
- mutex_lock(&sg_mutex);
- ret = sg_ioctl(filp, cmd_in, arg);
- mutex_unlock(&sg_mutex);
-
- return ret;
-}
-
#ifdef CONFIG_COMPAT
static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
{
@@ -1136,8 +1148,11 @@ sg_poll(struct file *filp, poll_table * wait)
int count = 0;
unsigned long iflags;
- if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))
- || sfp->closed)
+ sfp = filp->private_data;
+ if (!sfp)
+ return POLLERR;
+ sdp = sfp->parentdp;
+ if (!sdp)
return POLLERR;
poll_wait(filp, &sfp->read_wait, wait);
read_lock_irqsave(&sfp->rq_list_lock, iflags);
@@ -1347,7 +1362,7 @@ static const struct file_operations sg_fops = {
.read = sg_read,
.write = sg_write,
.poll = sg_poll,
- .unlocked_ioctl = sg_unlocked_ioctl,
+ .unlocked_ioctl = sg_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = sg_compat_ioctl,
#endif
@@ -2312,7 +2327,7 @@ struct sg_proc_leaf {
const struct file_operations * fops;
};
-static struct sg_proc_leaf sg_proc_leaf_arr[] = {
+static const struct sg_proc_leaf sg_proc_leaf_arr[] = {
{"allow_dio", &adio_fops},
{"debug", &debug_fops},
{"def_reserved_size", &dressz_fops},
@@ -2332,7 +2347,7 @@ sg_proc_init(void)
if (!sg_proc_sgp)
return 1;
for (k = 0; k < num_leaves; ++k) {
- struct sg_proc_leaf *leaf = &sg_proc_leaf_arr[k];
+ const struct sg_proc_leaf *leaf = &sg_proc_leaf_arr[k];
umode_t mask = leaf->fops->write ? S_IRUGO | S_IWUSR : S_IRUGO;
proc_create(leaf->name, mask, sg_proc_sgp, leaf->fops);
}
@@ -2533,9 +2548,9 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
fp->reserve.bufflen,
(int) fp->reserve.k_use_sg,
(int) fp->low_dma);
- seq_printf(s, " cmd_q=%d f_packid=%d k_orphan=%d closed=%d\n",
+ seq_printf(s, " cmd_q=%d f_packid=%d k_orphan=%d closed=0\n",
(int) fp->cmd_q, (int) fp->force_packid,
- (int) fp->keep_orphan, (int) fp->closed);
+ (int) fp->keep_orphan);
for (m = 0, srp = fp->headrp;
srp != NULL;
++m, srp = srp->nextrp) {
@@ -2612,7 +2627,7 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v)
scsidp->lun,
scsidp->host->hostt->emulated);
seq_printf(s, " sg_tablesize=%d excl=%d\n",
- sdp->sg_tablesize, sdp->exclude);
+ sdp->sg_tablesize, get_exclude(sdp));
sg_proc_debug_helper(s, sdp);
}
read_unlock_irqrestore(&sg_index_lock, iflags);
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index ea35632b986c..b548923785ed 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -35,8 +35,8 @@ struct st_request {
/* The tape buffer descriptor. */
struct st_buffer {
unsigned char dma; /* DMA-able buffer */
- unsigned char do_dio; /* direct i/o set up? */
unsigned char cleared; /* internal buffer cleared after open? */
+ unsigned short do_dio; /* direct i/o set up? */
int buffer_size;
int buffer_blocks;
int buffer_bytes;
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 83a1972a1999..528d52beaa1c 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -785,12 +785,22 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
/*
* If there is an error; offline the device since all
* error recovery strategies would have already been
- * deployed on the host side.
+ * deployed on the host side. However, if the command
+ * were a pass-through command deal with it appropriately.
*/
- if (vm_srb->srb_status == SRB_STATUS_ERROR)
- scmnd->result = DID_TARGET_FAILURE << 16;
- else
- scmnd->result = vm_srb->scsi_status;
+ scmnd->result = vm_srb->scsi_status;
+
+ if (vm_srb->srb_status == SRB_STATUS_ERROR) {
+ switch (scmnd->cmnd[0]) {
+ case ATA_16:
+ case ATA_12:
+ set_host_byte(scmnd, DID_PASSTHROUGH);
+ break;
+ default:
+ set_host_byte(scmnd, DID_TARGET_FAILURE);
+ }
+ }
+
/*
* If the LUN is invalid; remove the device.
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 52b96e8bf92e..4e010b727818 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1032,11 +1032,11 @@ static int ufshcd_initialize_hba(struct ufs_hba *hba)
return -EIO;
/* Configure UTRL and UTMRL base address registers */
- writel(hba->utrdl_dma_addr,
- (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L));
writel(lower_32_bits(hba->utrdl_dma_addr),
+ (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L));
+ writel(upper_32_bits(hba->utrdl_dma_addr),
(hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_H));
- writel(hba->utmrdl_dma_addr,
+ writel(lower_32_bits(hba->utmrdl_dma_addr),
(hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_L));
writel(upper_32_bits(hba->utmrdl_dma_addr),
(hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_H));
@@ -1160,7 +1160,7 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index)
task_result = be32_to_cpu(task_rsp_upiup->header.dword_1);
task_result = ((task_result & MASK_TASK_RESPONSE) >> 8);
- if (task_result != UPIU_TASK_MANAGEMENT_FUNC_COMPL ||
+ if (task_result != UPIU_TASK_MANAGEMENT_FUNC_COMPL &&
task_result != UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED)
task_result = FAILED;
} else {
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
index 91b6d52f74eb..f0d015dd0fef 100644
--- a/drivers/sh/clk/cpg.c
+++ b/drivers/sh/clk/cpg.c
@@ -2,6 +2,7 @@
* Helper routines for SuperH Clock Pulse Generator blocks (CPG).
*
* Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2010 - 2012 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -13,26 +14,44 @@
#include <linux/io.h>
#include <linux/sh_clk.h>
-static int sh_clk_mstp32_enable(struct clk *clk)
+static unsigned int sh_clk_read(struct clk *clk)
{
- iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
- clk->mapped_reg);
+ if (clk->flags & CLK_ENABLE_REG_8BIT)
+ return ioread8(clk->mapped_reg);
+ else if (clk->flags & CLK_ENABLE_REG_16BIT)
+ return ioread16(clk->mapped_reg);
+
+ return ioread32(clk->mapped_reg);
+}
+
+static void sh_clk_write(int value, struct clk *clk)
+{
+ if (clk->flags & CLK_ENABLE_REG_8BIT)
+ iowrite8(value, clk->mapped_reg);
+ else if (clk->flags & CLK_ENABLE_REG_16BIT)
+ iowrite16(value, clk->mapped_reg);
+ else
+ iowrite32(value, clk->mapped_reg);
+}
+
+static int sh_clk_mstp_enable(struct clk *clk)
+{
+ sh_clk_write(sh_clk_read(clk) & ~(1 << clk->enable_bit), clk);
return 0;
}
-static void sh_clk_mstp32_disable(struct clk *clk)
+static void sh_clk_mstp_disable(struct clk *clk)
{
- iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
- clk->mapped_reg);
+ sh_clk_write(sh_clk_read(clk) | (1 << clk->enable_bit), clk);
}
-static struct sh_clk_ops sh_clk_mstp32_clk_ops = {
- .enable = sh_clk_mstp32_enable,
- .disable = sh_clk_mstp32_disable,
+static struct sh_clk_ops sh_clk_mstp_clk_ops = {
+ .enable = sh_clk_mstp_enable,
+ .disable = sh_clk_mstp_disable,
.recalc = followparent_recalc,
};
-int __init sh_clk_mstp32_register(struct clk *clks, int nr)
+int __init sh_clk_mstp_register(struct clk *clks, int nr)
{
struct clk *clkp;
int ret = 0;
@@ -40,7 +59,7 @@ int __init sh_clk_mstp32_register(struct clk *clks, int nr)
for (k = 0; !ret && (k < nr); k++) {
clkp = clks + k;
- clkp->ops = &sh_clk_mstp32_clk_ops;
+ clkp->ops = &sh_clk_mstp_clk_ops;
ret |= clk_register(clkp);
}
@@ -72,7 +91,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
table, NULL);
- idx = ioread32(clk->mapped_reg) & 0x003f;
+ idx = sh_clk_read(clk) & 0x003f;
return clk->freq_table[idx].frequency;
}
@@ -98,10 +117,10 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
if (ret < 0)
return ret;
- value = ioread32(clk->mapped_reg) &
+ value = sh_clk_read(clk) &
~(((1 << clk->src_width) - 1) << clk->src_shift);
- iowrite32(value | (i << clk->src_shift), clk->mapped_reg);
+ sh_clk_write(value | (i << clk->src_shift), clk);
/* Rebuild the frequency table */
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
@@ -119,10 +138,10 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
if (idx < 0)
return idx;
- value = ioread32(clk->mapped_reg);
+ value = sh_clk_read(clk);
value &= ~0x3f;
value |= idx;
- iowrite32(value, clk->mapped_reg);
+ sh_clk_write(value, clk);
return 0;
}
@@ -133,9 +152,9 @@ static int sh_clk_div6_enable(struct clk *clk)
ret = sh_clk_div6_set_rate(clk, clk->rate);
if (ret == 0) {
- value = ioread32(clk->mapped_reg);
+ value = sh_clk_read(clk);
value &= ~0x100; /* clear stop bit to enable clock */
- iowrite32(value, clk->mapped_reg);
+ sh_clk_write(value, clk);
}
return ret;
}
@@ -144,10 +163,10 @@ static void sh_clk_div6_disable(struct clk *clk)
{
unsigned long value;
- value = ioread32(clk->mapped_reg);
+ value = sh_clk_read(clk);
value |= 0x100; /* stop clock */
value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
- iowrite32(value, clk->mapped_reg);
+ sh_clk_write(value, clk);
}
static struct sh_clk_ops sh_clk_div6_clk_ops = {
@@ -182,7 +201,7 @@ static int __init sh_clk_init_parent(struct clk *clk)
return -EINVAL;
}
- val = (ioread32(clk->mapped_reg) >> clk->src_shift);
+ val = (sh_clk_read(clk) >> clk->src_shift);
val &= (1 << clk->src_width) - 1;
if (val >= clk->parent_num) {
@@ -252,7 +271,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk)
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
table, &clk->arch_flags);
- idx = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0x000f;
+ idx = (sh_clk_read(clk) >> clk->enable_bit) & 0x000f;
return clk->freq_table[idx].frequency;
}
@@ -270,15 +289,15 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
*/
if (parent->flags & CLK_ENABLE_ON_INIT)
- value = ioread32(clk->mapped_reg) & ~(1 << 7);
+ value = sh_clk_read(clk) & ~(1 << 7);
else
- value = ioread32(clk->mapped_reg) | (1 << 7);
+ value = sh_clk_read(clk) | (1 << 7);
ret = clk_reparent(clk, parent);
if (ret < 0)
return ret;
- iowrite32(value, clk->mapped_reg);
+ sh_clk_write(value, clk);
/* Rebiuld the frequency table */
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
@@ -295,10 +314,10 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
if (idx < 0)
return idx;
- value = ioread32(clk->mapped_reg);
+ value = sh_clk_read(clk);
value &= ~(0xf << clk->enable_bit);
value |= (idx << clk->enable_bit);
- iowrite32(value, clk->mapped_reg);
+ sh_clk_write(value, clk);
if (d4t->kick)
d4t->kick(clk);
@@ -308,13 +327,13 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
static int sh_clk_div4_enable(struct clk *clk)
{
- iowrite32(ioread32(clk->mapped_reg) & ~(1 << 8), clk->mapped_reg);
+ sh_clk_write(sh_clk_read(clk) & ~(1 << 8), clk);
return 0;
}
static void sh_clk_div4_disable(struct clk *clk)
{
- iowrite32(ioread32(clk->mapped_reg) | (1 << 8), clk->mapped_reg);
+ sh_clk_write(sh_clk_read(clk) | (1 << 8), clk);
}
static struct sh_clk_ops sh_clk_div4_clk_ops = {
diff --git a/drivers/sh/intc/dynamic.c b/drivers/sh/intc/dynamic.c
index 5fea1ee8799a..14eb01ef5d72 100644
--- a/drivers/sh/intc/dynamic.c
+++ b/drivers/sh/intc/dynamic.c
@@ -55,11 +55,3 @@ void destroy_irq(unsigned int irq)
{
irq_free_desc(irq);
}
-
-void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs)
-{
- int i;
-
- for (i = 0; i < nr_vecs; i++)
- irq_reserve_irq(evt2irq(vectors[i].vect));
-}
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 570f22053be8..69c9a6601f45 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -37,6 +37,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
#include <mach/spi.h>
@@ -758,6 +759,7 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
struct spi_master *master;
struct spi_imx_data *spi_imx;
struct resource *res;
+ struct pinctrl *pinctrl;
int i, ret, num_cs;
if (!np && !mxc_platform_info) {
@@ -845,6 +847,12 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
goto out_iounmap;
}
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ goto out_free_irq;
+ }
+
spi_imx->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(spi_imx->clk)) {
dev_err(&pdev->dev, "unable to get clock\n");
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 97d412d91458..05e33c700750 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -24,8 +24,6 @@ menuconfig STAGING
if STAGING
-source "drivers/staging/serial/Kconfig"
-
source "drivers/staging/et131x/Kconfig"
source "drivers/staging/slicoss/Kconfig"
@@ -68,14 +66,10 @@ source "drivers/staging/octeon/Kconfig"
source "drivers/staging/serqt_usb2/Kconfig"
-source "drivers/staging/quatech_usb2/Kconfig"
-
source "drivers/staging/vt6655/Kconfig"
source "drivers/staging/vt6656/Kconfig"
-source "drivers/staging/vme/Kconfig"
-
source "drivers/staging/sep/Kconfig"
source "drivers/staging/iio/Kconfig"
@@ -116,12 +110,12 @@ source "drivers/staging/cptm1217/Kconfig"
source "drivers/staging/ste_rmi4/Kconfig"
-source "drivers/staging/mei/Kconfig"
-
source "drivers/staging/nvec/Kconfig"
source "drivers/staging/media/Kconfig"
+source "drivers/staging/net/Kconfig"
+
source "drivers/staging/omapdrm/Kconfig"
source "drivers/staging/android/Kconfig"
@@ -132,4 +126,10 @@ source "drivers/staging/ramster/Kconfig"
source "drivers/staging/ozwpan/Kconfig"
+source "drivers/staging/ccg/Kconfig"
+
+source "drivers/staging/ipack/Kconfig"
+
+source "drivers/staging/gdm72xx/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index ffe7d44374e6..a987b3ad380b 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -3,8 +3,8 @@
# fix for build system bug...
obj-$(CONFIG_STAGING) += staging.o
-obj-y += serial/
obj-y += media/
+obj-y += net/
obj-$(CONFIG_ET131X) += et131x/
obj-$(CONFIG_SLICOSS) += slicoss/
obj-$(CONFIG_USBIP_CORE) += usbip/
@@ -25,11 +25,11 @@ obj-$(CONFIG_TRANZPORT) += frontier/
obj-$(CONFIG_IDE_PHISON) += phison/
obj-$(CONFIG_LINE6_USB) += line6/
obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/
-obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
obj-$(CONFIG_VT6655) += vt6655/
obj-$(CONFIG_VT6656) += vt6656/
obj-$(CONFIG_VME_BUS) += vme/
+obj-$(CONFIG_IPACK_BUS) += ipack/
obj-$(CONFIG_DX_SEP) += sep/
obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_ZRAM) += zram/
@@ -50,10 +50,11 @@ obj-$(CONFIG_FT1000) += ft1000/
obj-$(CONFIG_SPEAKUP) += speakup/
obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/
-obj-$(CONFIG_INTEL_MEI) += mei/
obj-$(CONFIG_MFD_NVEC) += nvec/
obj-$(CONFIG_DRM_OMAP) += omapdrm/
obj-$(CONFIG_ANDROID) += android/
obj-$(CONFIG_PHONE) += telephony/
obj-$(CONFIG_RAMSTER) += ramster/
obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/
+obj-$(CONFIG_USB_G_CCG) += ccg/
+obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index eb1dee26bda3..0e16b594460f 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -25,17 +25,9 @@ config ANDROID_LOGGER
tristate "Android log driver"
default n
-config ANDROID_PERSISTENT_RAM
- bool
- depends on HAVE_MEMBLOCK
- select REED_SOLOMON
- select REED_SOLOMON_ENC8
- select REED_SOLOMON_DEC8
-
config ANDROID_RAM_CONSOLE
bool "Android RAM buffer console"
- depends on !S390 && !UML && HAVE_MEMBLOCK
- select ANDROID_PERSISTENT_RAM
+ depends on !S390 && !UML && HAVE_MEMBLOCK && PSTORE_RAM=y
default n
config ANDROID_TIMED_OUTPUT
@@ -53,33 +45,14 @@ config ANDROID_LOW_MEMORY_KILLER
---help---
Register processes to be killed when memory is low
-source "drivers/staging/android/switch/Kconfig"
-
-config ANDROID_INTF_ALARM
+config ANDROID_INTF_ALARM_DEV
bool "Android alarm driver"
depends on RTC_CLASS
default n
help
Provides non-wakeup and rtc backed wakeup alarms based on rtc or
elapsed realtime, and a non-wakeup alarm on the monotonic clock.
- Also provides an interface to set the wall time which must be used
- for elapsed realtime to work.
-
-config ANDROID_INTF_ALARM_DEV
- bool "Android alarm device"
- depends on ANDROID_INTF_ALARM
- default y
- help
- Exports the alarm interface to user-space.
-
-config ANDROID_ALARM_OLDDRV_COMPAT
- bool "Android Alarm compatability with old drivers"
- depends on ANDROID_INTF_ALARM
- default n
- help
- Provides preprocessor alias to aid compatability with
- older out-of-tree drivers that use the Android Alarm
- in-kernel API. This will be removed eventually.
+ Also exports the alarm interface to user-space.
endif # if ANDROID
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile
index 9b6c9ed91f69..98711e2b2afa 100644
--- a/drivers/staging/android/Makefile
+++ b/drivers/staging/android/Makefile
@@ -1,11 +1,8 @@
obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o
obj-$(CONFIG_ASHMEM) += ashmem.o
obj-$(CONFIG_ANDROID_LOGGER) += logger.o
-obj-$(CONFIG_ANDROID_PERSISTENT_RAM) += persistent_ram.o
obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o
obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o
obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o
obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
-obj-$(CONFIG_ANDROID_SWITCH) += switch/
-obj-$(CONFIG_ANDROID_INTF_ALARM) += alarm.o
obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o
diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c
index 03efb34cbe2e..53ce6ecf390a 100644
--- a/drivers/staging/android/alarm-dev.c
+++ b/drivers/staging/android/alarm-dev.c
@@ -22,19 +22,9 @@
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
+#include <linux/alarmtimer.h>
#include "android_alarm.h"
-/* XXX - Hack out wakelocks, while they are out of tree */
-struct wake_lock {
- int i;
-};
-#define wake_lock(x)
-#define wake_lock_timeout(x, y)
-#define wake_unlock(x)
-#define WAKE_LOCK_SUSPEND 0
-#define wake_lock_init(x, y, z) ((x)->i = 1)
-#define wake_lock_destroy(x)
-
#define ANDROID_ALARM_PRINT_INFO (1U << 0)
#define ANDROID_ALARM_PRINT_IO (1U << 1)
#define ANDROID_ALARM_PRINT_INT (1U << 2)
@@ -54,19 +44,65 @@ module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
ANDROID_ALARM_RTC_WAKEUP_MASK | \
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK)
-/* support old usespace code */
+/* support old userspace code */
#define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */
#define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t)
static int alarm_opened;
static DEFINE_SPINLOCK(alarm_slock);
-static struct wake_lock alarm_wake_lock;
+static struct wakeup_source alarm_wake_lock;
static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue);
static uint32_t alarm_pending;
static uint32_t alarm_enabled;
static uint32_t wait_pending;
-static struct android_alarm alarms[ANDROID_ALARM_TYPE_COUNT];
+struct devalarm {
+ union {
+ struct hrtimer hrt;
+ struct alarm alrm;
+ } u;
+ enum android_alarm_type type;
+};
+
+static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT];
+
+
+static int is_wakeup(enum android_alarm_type type)
+{
+ if (type == ANDROID_ALARM_RTC_WAKEUP ||
+ type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP)
+ return 1;
+ return 0;
+}
+
+
+static void devalarm_start(struct devalarm *alrm, ktime_t exp)
+{
+ if (is_wakeup(alrm->type))
+ alarm_start(&alrm->u.alrm, exp);
+ else
+ hrtimer_start(&alrm->u.hrt, exp, HRTIMER_MODE_ABS);
+}
+
+
+static int devalarm_try_to_cancel(struct devalarm *alrm)
+{
+ int ret;
+ if (is_wakeup(alrm->type))
+ ret = alarm_try_to_cancel(&alrm->u.alrm);
+ else
+ ret = hrtimer_try_to_cancel(&alrm->u.hrt);
+ return ret;
+}
+
+static void devalarm_cancel(struct devalarm *alrm)
+{
+ if (is_wakeup(alrm->type))
+ alarm_cancel(&alrm->u.alrm);
+ else
+ hrtimer_cancel(&alrm->u.hrt);
+}
+
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
@@ -75,6 +111,8 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct timespec new_alarm_time;
struct timespec new_rtc_time;
struct timespec tmp_time;
+ struct rtc_time new_rtc_tm;
+ struct rtc_device *rtc_dev;
enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
uint32_t alarm_type_mask = 1U << alarm_type;
@@ -101,11 +139,11 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case ANDROID_ALARM_CLEAR(0):
spin_lock_irqsave(&alarm_slock, flags);
pr_alarm(IO, "alarm %d clear\n", alarm_type);
- android_alarm_try_to_cancel(&alarms[alarm_type]);
+ devalarm_try_to_cancel(&alarms[alarm_type]);
if (alarm_pending) {
alarm_pending &= ~alarm_type_mask;
if (!alarm_pending && !wait_pending)
- wake_unlock(&alarm_wake_lock);
+ __pm_relax(&alarm_wake_lock);
}
alarm_enabled &= ~alarm_type_mask;
spin_unlock_irqrestore(&alarm_slock, flags);
@@ -132,8 +170,7 @@ from_old_alarm_set:
pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
alarm_enabled |= alarm_type_mask;
- android_alarm_start_range(&alarms[alarm_type],
- timespec_to_ktime(new_alarm_time),
+ devalarm_start(&alarms[alarm_type],
timespec_to_ktime(new_alarm_time));
spin_unlock_irqrestore(&alarm_slock, flags);
if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
@@ -144,7 +181,7 @@ from_old_alarm_set:
spin_lock_irqsave(&alarm_slock, flags);
pr_alarm(IO, "alarm wait\n");
if (!alarm_pending && wait_pending) {
- wake_unlock(&alarm_wake_lock);
+ __pm_relax(&alarm_wake_lock);
wait_pending = 0;
}
spin_unlock_irqrestore(&alarm_slock, flags);
@@ -163,7 +200,13 @@ from_old_alarm_set:
rv = -EFAULT;
goto err1;
}
- rv = android_alarm_set_rtc(new_rtc_time);
+ rtc_time_to_tm(new_rtc_time.tv_sec, &new_rtc_tm);
+ rtc_dev = alarmtimer_get_rtcdev();
+ rv = do_settimeofday(&new_rtc_time);
+ if (rv < 0)
+ goto err1;
+ if (rtc_dev)
+ rv = rtc_set_time(rtc_dev, &new_rtc_tm);
spin_lock_irqsave(&alarm_slock, flags);
alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
wake_up(&alarm_wait_queue);
@@ -179,8 +222,7 @@ from_old_alarm_set:
break;
case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
case ANDROID_ALARM_ELAPSED_REALTIME:
- tmp_time =
- ktime_to_timespec(alarm_get_elapsed_realtime());
+ get_monotonic_boottime(&tmp_time);
break;
case ANDROID_ALARM_TYPE_COUNT:
case ANDROID_ALARM_SYSTEMTIME:
@@ -224,14 +266,14 @@ static int alarm_release(struct inode *inode, struct file *file)
alarm_enabled &= ~alarm_type_mask;
}
spin_unlock_irqrestore(&alarm_slock, flags);
- android_alarm_cancel(&alarms[i]);
+ devalarm_cancel(&alarms[i]);
spin_lock_irqsave(&alarm_slock, flags);
}
if (alarm_pending | wait_pending) {
if (alarm_pending)
pr_alarm(INFO, "alarm_release: clear "
"pending alarms %x\n", alarm_pending);
- wake_unlock(&alarm_wake_lock);
+ __pm_relax(&alarm_wake_lock);
wait_pending = 0;
alarm_pending = 0;
}
@@ -241,15 +283,15 @@ static int alarm_release(struct inode *inode, struct file *file)
return 0;
}
-static void alarm_triggered(struct android_alarm *alarm)
+static void devalarm_triggered(struct devalarm *alarm)
{
unsigned long flags;
uint32_t alarm_type_mask = 1U << alarm->type;
- pr_alarm(INT, "alarm_triggered type %d\n", alarm->type);
+ pr_alarm(INT, "devalarm_triggered type %d\n", alarm->type);
spin_lock_irqsave(&alarm_slock, flags);
if (alarm_enabled & alarm_type_mask) {
- wake_lock_timeout(&alarm_wake_lock, 5 * HZ);
+ __pm_wakeup_event(&alarm_wake_lock, 5000); /* 5secs */
alarm_enabled &= ~alarm_type_mask;
alarm_pending |= alarm_type_mask;
wake_up(&alarm_wait_queue);
@@ -257,6 +299,25 @@ static void alarm_triggered(struct android_alarm *alarm)
spin_unlock_irqrestore(&alarm_slock, flags);
}
+
+static enum hrtimer_restart devalarm_hrthandler(struct hrtimer *hrt)
+{
+ struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt);
+
+ devalarm_triggered(devalrm);
+ return HRTIMER_NORESTART;
+}
+
+static enum alarmtimer_restart devalarm_alarmhandler(struct alarm *alrm,
+ ktime_t now)
+{
+ struct devalarm *devalrm = container_of(alrm, struct devalarm, u.alrm);
+
+ devalarm_triggered(devalrm);
+ return ALARMTIMER_NORESTART;
+}
+
+
static const struct file_operations alarm_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = alarm_ioctl,
@@ -279,17 +340,31 @@ static int __init alarm_dev_init(void)
if (err)
return err;
- for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++)
- android_alarm_init(&alarms[i], i, alarm_triggered);
- wake_lock_init(&alarm_wake_lock, WAKE_LOCK_SUSPEND, "alarm");
+ alarm_init(&alarms[ANDROID_ALARM_RTC_WAKEUP].u.alrm,
+ ALARM_REALTIME, devalarm_alarmhandler);
+ hrtimer_init(&alarms[ANDROID_ALARM_RTC].u.hrt,
+ CLOCK_REALTIME, HRTIMER_MODE_ABS);
+ alarm_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].u.alrm,
+ ALARM_BOOTTIME, devalarm_alarmhandler);
+ hrtimer_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME].u.hrt,
+ CLOCK_BOOTTIME, HRTIMER_MODE_ABS);
+ hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt,
+ CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+
+ for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) {
+ alarms[i].type = i;
+ if (!is_wakeup(i))
+ alarms[i].u.hrt.function = devalarm_hrthandler;
+ }
+ wakeup_source_init(&alarm_wake_lock, "alarm");
return 0;
}
static void __exit alarm_dev_exit(void)
{
misc_deregister(&alarm_device);
- wake_lock_destroy(&alarm_wake_lock);
+ wakeup_source_trash(&alarm_wake_lock);
}
module_init(alarm_dev_init);
diff --git a/drivers/staging/android/alarm.c b/drivers/staging/android/alarm.c
deleted file mode 100644
index c68950b9e08f..000000000000
--- a/drivers/staging/android/alarm.c
+++ /dev/null
@@ -1,601 +0,0 @@
-/* drivers/rtc/alarm.c
- *
- * Copyright (C) 2007-2009 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/time.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/miscdevice.h>
-#include <linux/platform_device.h>
-#include <linux/rtc.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include "android_alarm.h"
-
-/* XXX - Hack out wakelocks, while they are out of tree */
-struct wake_lock {
- int i;
-};
-#define wake_lock(x)
-#define wake_lock_timeout(x, y)
-#define wake_unlock(x)
-#define WAKE_LOCK_SUSPEND 0
-#define wake_lock_init(x, y, z) ((x)->i = 1)
-#define wake_lock_destroy(x)
-
-#define ANDROID_ALARM_PRINT_ERROR (1U << 0)
-#define ANDROID_ALARM_PRINT_INIT_STATUS (1U << 1)
-#define ANDROID_ALARM_PRINT_TSET (1U << 2)
-#define ANDROID_ALARM_PRINT_CALL (1U << 3)
-#define ANDROID_ALARM_PRINT_SUSPEND (1U << 4)
-#define ANDROID_ALARM_PRINT_INT (1U << 5)
-#define ANDROID_ALARM_PRINT_FLOW (1U << 6)
-
-static int debug_mask = ANDROID_ALARM_PRINT_ERROR | \
- ANDROID_ALARM_PRINT_INIT_STATUS;
-module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
-
-#define pr_alarm(debug_level_mask, args...) \
- do { \
- if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) { \
- pr_info(args); \
- } \
- } while (0)
-
-#define ANDROID_ALARM_WAKEUP_MASK ( \
- ANDROID_ALARM_RTC_WAKEUP_MASK | \
- ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK)
-
-/* support old usespace code */
-#define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */
-#define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t)
-
-struct alarm_queue {
- struct rb_root alarms;
- struct rb_node *first;
- struct hrtimer timer;
- ktime_t delta;
- bool stopped;
- ktime_t stopped_time;
-};
-
-static struct rtc_device *alarm_rtc_dev;
-static DEFINE_SPINLOCK(alarm_slock);
-static DEFINE_MUTEX(alarm_setrtc_mutex);
-static struct wake_lock alarm_rtc_wake_lock;
-static struct platform_device *alarm_platform_dev;
-struct alarm_queue alarms[ANDROID_ALARM_TYPE_COUNT];
-static bool suspended;
-
-static void update_timer_locked(struct alarm_queue *base, bool head_removed)
-{
- struct android_alarm *alarm;
- bool is_wakeup = base == &alarms[ANDROID_ALARM_RTC_WAKEUP] ||
- base == &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP];
-
- if (base->stopped) {
- pr_alarm(FLOW, "changed alarm while setting the wall time\n");
- return;
- }
-
- if (is_wakeup && !suspended && head_removed)
- wake_unlock(&alarm_rtc_wake_lock);
-
- if (!base->first)
- return;
-
- alarm = container_of(base->first, struct android_alarm, node);
-
- pr_alarm(FLOW, "selected alarm, type %d, func %pF at %lld\n",
- alarm->type, alarm->function, ktime_to_ns(alarm->expires));
-
- if (is_wakeup && suspended) {
- pr_alarm(FLOW, "changed alarm while suspened\n");
- wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ);
- return;
- }
-
- hrtimer_try_to_cancel(&base->timer);
- base->timer.node.expires = ktime_add(base->delta, alarm->expires);
- base->timer._softexpires = ktime_add(base->delta, alarm->softexpires);
- hrtimer_start_expires(&base->timer, HRTIMER_MODE_ABS);
-}
-
-static void alarm_enqueue_locked(struct android_alarm *alarm)
-{
- struct alarm_queue *base = &alarms[alarm->type];
- struct rb_node **link = &base->alarms.rb_node;
- struct rb_node *parent = NULL;
- struct android_alarm *entry;
- int leftmost = 1;
- bool was_first = false;
-
- pr_alarm(FLOW, "added alarm, type %d, func %pF at %lld\n",
- alarm->type, alarm->function, ktime_to_ns(alarm->expires));
-
- if (base->first == &alarm->node) {
- base->first = rb_next(&alarm->node);
- was_first = true;
- }
- if (!RB_EMPTY_NODE(&alarm->node)) {
- rb_erase(&alarm->node, &base->alarms);
- RB_CLEAR_NODE(&alarm->node);
- }
-
- while (*link) {
- parent = *link;
- entry = rb_entry(parent, struct android_alarm, node);
- /*
- * We dont care about collisions. Nodes with
- * the same expiry time stay together.
- */
- if (alarm->expires.tv64 < entry->expires.tv64) {
- link = &(*link)->rb_left;
- } else {
- link = &(*link)->rb_right;
- leftmost = 0;
- }
- }
- if (leftmost)
- base->first = &alarm->node;
- if (leftmost || was_first)
- update_timer_locked(base, was_first);
-
- rb_link_node(&alarm->node, parent, link);
- rb_insert_color(&alarm->node, &base->alarms);
-}
-
-/**
- * android_alarm_init - initialize an alarm
- * @alarm: the alarm to be initialized
- * @type: the alarm type to be used
- * @function: alarm callback function
- */
-void android_alarm_init(struct android_alarm *alarm,
- enum android_alarm_type type, void (*function)(struct android_alarm *))
-{
- RB_CLEAR_NODE(&alarm->node);
- alarm->type = type;
- alarm->function = function;
-
- pr_alarm(FLOW, "created alarm, type %d, func %pF\n", type, function);
-}
-
-
-/**
- * android_alarm_start_range - (re)start an alarm
- * @alarm: the alarm to be added
- * @start: earliest expiry time
- * @end: expiry time
- */
-void android_alarm_start_range(struct android_alarm *alarm, ktime_t start,
- ktime_t end)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&alarm_slock, flags);
- alarm->softexpires = start;
- alarm->expires = end;
- alarm_enqueue_locked(alarm);
- spin_unlock_irqrestore(&alarm_slock, flags);
-}
-
-/**
- * android_alarm_try_to_cancel - try to deactivate an alarm
- * @alarm: alarm to stop
- *
- * Returns:
- * 0 when the alarm was not active
- * 1 when the alarm was active
- * -1 when the alarm may currently be excuting the callback function and
- * cannot be stopped (it may also be inactive)
- */
-int android_alarm_try_to_cancel(struct android_alarm *alarm)
-{
- struct alarm_queue *base = &alarms[alarm->type];
- unsigned long flags;
- bool first = false;
- int ret = 0;
-
- spin_lock_irqsave(&alarm_slock, flags);
- if (!RB_EMPTY_NODE(&alarm->node)) {
- pr_alarm(FLOW, "canceled alarm, type %d, func %pF at %lld\n",
- alarm->type, alarm->function,
- ktime_to_ns(alarm->expires));
- ret = 1;
- if (base->first == &alarm->node) {
- base->first = rb_next(&alarm->node);
- first = true;
- }
- rb_erase(&alarm->node, &base->alarms);
- RB_CLEAR_NODE(&alarm->node);
- if (first)
- update_timer_locked(base, true);
- } else
- pr_alarm(FLOW, "tried to cancel alarm, type %d, func %pF\n",
- alarm->type, alarm->function);
- spin_unlock_irqrestore(&alarm_slock, flags);
- if (!ret && hrtimer_callback_running(&base->timer))
- ret = -1;
- return ret;
-}
-
-/**
- * android_alarm_cancel - cancel an alarm and wait for the handler to finish.
- * @alarm: the alarm to be cancelled
- *
- * Returns:
- * 0 when the alarm was not active
- * 1 when the alarm was active
- */
-int android_alarm_cancel(struct android_alarm *alarm)
-{
- for (;;) {
- int ret = android_alarm_try_to_cancel(alarm);
- if (ret >= 0)
- return ret;
- cpu_relax();
- }
-}
-
-/**
- * alarm_set_rtc - set the kernel and rtc walltime
- * @new_time: timespec value containing the new time
- */
-int android_alarm_set_rtc(struct timespec new_time)
-{
- int i;
- int ret;
- unsigned long flags;
- struct rtc_time rtc_new_rtc_time;
- struct timespec tmp_time;
-
- rtc_time_to_tm(new_time.tv_sec, &rtc_new_rtc_time);
-
- pr_alarm(TSET, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n",
- new_time.tv_sec, new_time.tv_nsec,
- rtc_new_rtc_time.tm_hour, rtc_new_rtc_time.tm_min,
- rtc_new_rtc_time.tm_sec, rtc_new_rtc_time.tm_mon + 1,
- rtc_new_rtc_time.tm_mday,
- rtc_new_rtc_time.tm_year + 1900);
-
- mutex_lock(&alarm_setrtc_mutex);
- spin_lock_irqsave(&alarm_slock, flags);
- wake_lock(&alarm_rtc_wake_lock);
- getnstimeofday(&tmp_time);
- for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
- hrtimer_try_to_cancel(&alarms[i].timer);
- alarms[i].stopped = true;
- alarms[i].stopped_time = timespec_to_ktime(tmp_time);
- }
- alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta =
- alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta =
- ktime_sub(alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta,
- timespec_to_ktime(timespec_sub(tmp_time, new_time)));
- spin_unlock_irqrestore(&alarm_slock, flags);
- ret = do_settimeofday(&new_time);
- spin_lock_irqsave(&alarm_slock, flags);
- for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
- alarms[i].stopped = false;
- update_timer_locked(&alarms[i], false);
- }
- spin_unlock_irqrestore(&alarm_slock, flags);
- if (ret < 0) {
- pr_alarm(ERROR, "alarm_set_rtc: Failed to set time\n");
- goto err;
- }
- if (!alarm_rtc_dev) {
- pr_alarm(ERROR,
- "alarm_set_rtc: no RTC, time will be lost on reboot\n");
- goto err;
- }
- ret = rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time);
- if (ret < 0)
- pr_alarm(ERROR, "alarm_set_rtc: "
- "Failed to set RTC, time will be lost on reboot\n");
-err:
- wake_unlock(&alarm_rtc_wake_lock);
- mutex_unlock(&alarm_setrtc_mutex);
- return ret;
-}
-
-/**
- * alarm_get_elapsed_realtime - get the elapsed real time in ktime_t format
- *
- * returns the time in ktime_t format
- */
-ktime_t alarm_get_elapsed_realtime(void)
-{
- ktime_t now;
- unsigned long flags;
- struct alarm_queue *base = &alarms[ANDROID_ALARM_ELAPSED_REALTIME];
-
- spin_lock_irqsave(&alarm_slock, flags);
- now = base->stopped ? base->stopped_time : ktime_get_real();
- now = ktime_sub(now, base->delta);
- spin_unlock_irqrestore(&alarm_slock, flags);
- return now;
-}
-
-static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer)
-{
- struct alarm_queue *base;
- struct android_alarm *alarm;
- unsigned long flags;
- ktime_t now;
-
- spin_lock_irqsave(&alarm_slock, flags);
-
- base = container_of(timer, struct alarm_queue, timer);
- now = base->stopped ? base->stopped_time : hrtimer_cb_get_time(timer);
- now = ktime_sub(now, base->delta);
-
- pr_alarm(INT, "alarm_timer_triggered type %ld at %lld\n",
- base - alarms, ktime_to_ns(now));
-
- while (base->first) {
- alarm = container_of(base->first, struct android_alarm, node);
- if (alarm->softexpires.tv64 > now.tv64) {
- pr_alarm(FLOW, "don't call alarm, %pF, %lld (s %lld)\n",
- alarm->function, ktime_to_ns(alarm->expires),
- ktime_to_ns(alarm->softexpires));
- break;
- }
- base->first = rb_next(&alarm->node);
- rb_erase(&alarm->node, &base->alarms);
- RB_CLEAR_NODE(&alarm->node);
- pr_alarm(CALL, "call alarm, type %d, func %pF, %lld (s %lld)\n",
- alarm->type, alarm->function,
- ktime_to_ns(alarm->expires),
- ktime_to_ns(alarm->softexpires));
- spin_unlock_irqrestore(&alarm_slock, flags);
- alarm->function(alarm);
- spin_lock_irqsave(&alarm_slock, flags);
- }
- if (!base->first)
- pr_alarm(FLOW, "no more alarms of type %ld\n", base - alarms);
- update_timer_locked(base, true);
- spin_unlock_irqrestore(&alarm_slock, flags);
- return HRTIMER_NORESTART;
-}
-
-static void alarm_triggered_func(void *p)
-{
- struct rtc_device *rtc = alarm_rtc_dev;
- if (!(rtc->irq_data & RTC_AF))
- return;
- pr_alarm(INT, "rtc alarm triggered\n");
- wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ);
-}
-
-static int alarm_suspend(struct platform_device *pdev, pm_message_t state)
-{
- int err = 0;
- unsigned long flags;
- struct rtc_wkalrm rtc_alarm;
- struct rtc_time rtc_current_rtc_time;
- unsigned long rtc_current_time;
- unsigned long rtc_alarm_time;
- struct timespec rtc_delta;
- struct timespec wall_time;
- struct alarm_queue *wakeup_queue = NULL;
- struct alarm_queue *tmp_queue = NULL;
-
- pr_alarm(SUSPEND, "alarm_suspend(%p, %d)\n", pdev, state.event);
-
- spin_lock_irqsave(&alarm_slock, flags);
- suspended = true;
- spin_unlock_irqrestore(&alarm_slock, flags);
-
- hrtimer_cancel(&alarms[ANDROID_ALARM_RTC_WAKEUP].timer);
- hrtimer_cancel(&alarms[
- ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].timer);
-
- tmp_queue = &alarms[ANDROID_ALARM_RTC_WAKEUP];
- if (tmp_queue->first)
- wakeup_queue = tmp_queue;
- tmp_queue = &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP];
- if (tmp_queue->first && (!wakeup_queue ||
- hrtimer_get_expires(&tmp_queue->timer).tv64 <
- hrtimer_get_expires(&wakeup_queue->timer).tv64))
- wakeup_queue = tmp_queue;
- if (wakeup_queue) {
- rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time);
- getnstimeofday(&wall_time);
- rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time);
- set_normalized_timespec(&rtc_delta,
- wall_time.tv_sec - rtc_current_time,
- wall_time.tv_nsec);
-
- rtc_alarm_time = timespec_sub(ktime_to_timespec(
- hrtimer_get_expires(&wakeup_queue->timer)),
- rtc_delta).tv_sec;
-
- rtc_time_to_tm(rtc_alarm_time, &rtc_alarm.time);
- rtc_alarm.enabled = 1;
- rtc_set_alarm(alarm_rtc_dev, &rtc_alarm);
- rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time);
- rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time);
- pr_alarm(SUSPEND,
- "rtc alarm set at %ld, now %ld, rtc delta %ld.%09ld\n",
- rtc_alarm_time, rtc_current_time,
- rtc_delta.tv_sec, rtc_delta.tv_nsec);
- if (rtc_current_time + 1 >= rtc_alarm_time) {
- pr_alarm(SUSPEND, "alarm about to go off\n");
- memset(&rtc_alarm, 0, sizeof(rtc_alarm));
- rtc_alarm.enabled = 0;
- rtc_set_alarm(alarm_rtc_dev, &rtc_alarm);
-
- spin_lock_irqsave(&alarm_slock, flags);
- suspended = false;
- wake_lock_timeout(&alarm_rtc_wake_lock, 2 * HZ);
- update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP],
- false);
- update_timer_locked(&alarms[
- ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], false);
- err = -EBUSY;
- spin_unlock_irqrestore(&alarm_slock, flags);
- }
- }
- return err;
-}
-
-static int alarm_resume(struct platform_device *pdev)
-{
- struct rtc_wkalrm alarm;
- unsigned long flags;
-
- pr_alarm(SUSPEND, "alarm_resume(%p)\n", pdev);
-
- memset(&alarm, 0, sizeof(alarm));
- alarm.enabled = 0;
- rtc_set_alarm(alarm_rtc_dev, &alarm);
-
- spin_lock_irqsave(&alarm_slock, flags);
- suspended = false;
- update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], false);
- update_timer_locked(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP],
- false);
- spin_unlock_irqrestore(&alarm_slock, flags);
-
- return 0;
-}
-
-static struct rtc_task alarm_rtc_task = {
- .func = alarm_triggered_func
-};
-
-static int rtc_alarm_add_device(struct device *dev,
- struct class_interface *class_intf)
-{
- int err;
- struct rtc_device *rtc = to_rtc_device(dev);
-
- mutex_lock(&alarm_setrtc_mutex);
-
- if (alarm_rtc_dev) {
- err = -EBUSY;
- goto err1;
- }
-
- alarm_platform_dev =
- platform_device_register_simple("alarm", -1, NULL, 0);
- if (IS_ERR(alarm_platform_dev)) {
- err = PTR_ERR(alarm_platform_dev);
- goto err2;
- }
- err = rtc_irq_register(rtc, &alarm_rtc_task);
- if (err)
- goto err3;
- alarm_rtc_dev = rtc;
- pr_alarm(INIT_STATUS, "using rtc device, %s, for alarms", rtc->name);
- mutex_unlock(&alarm_setrtc_mutex);
-
- return 0;
-
-err3:
- platform_device_unregister(alarm_platform_dev);
-err2:
-err1:
- mutex_unlock(&alarm_setrtc_mutex);
- return err;
-}
-
-static void rtc_alarm_remove_device(struct device *dev,
- struct class_interface *class_intf)
-{
- if (dev == &alarm_rtc_dev->dev) {
- pr_alarm(INIT_STATUS, "lost rtc device for alarms");
- rtc_irq_unregister(alarm_rtc_dev, &alarm_rtc_task);
- platform_device_unregister(alarm_platform_dev);
- alarm_rtc_dev = NULL;
- }
-}
-
-static struct class_interface rtc_alarm_interface = {
- .add_dev = &rtc_alarm_add_device,
- .remove_dev = &rtc_alarm_remove_device,
-};
-
-static struct platform_driver alarm_driver = {
- .suspend = alarm_suspend,
- .resume = alarm_resume,
- .driver = {
- .name = "alarm"
- }
-};
-
-static int __init alarm_late_init(void)
-{
- unsigned long flags;
- struct timespec tmp_time, system_time;
-
- /* this needs to run after the rtc is read at boot */
- spin_lock_irqsave(&alarm_slock, flags);
- /* We read the current rtc and system time so we can later calulate
- * elasped realtime to be (boot_systemtime + rtc - boot_rtc) ==
- * (rtc - (boot_rtc - boot_systemtime))
- */
- getnstimeofday(&tmp_time);
- ktime_get_ts(&system_time);
- alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta =
- alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta =
- timespec_to_ktime(timespec_sub(tmp_time, system_time));
-
- spin_unlock_irqrestore(&alarm_slock, flags);
- return 0;
-}
-
-static int __init alarm_driver_init(void)
-{
- int err;
- int i;
-
- for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
- hrtimer_init(&alarms[i].timer,
- CLOCK_REALTIME, HRTIMER_MODE_ABS);
- alarms[i].timer.function = alarm_timer_triggered;
- }
- hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].timer,
- CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
- alarms[ANDROID_ALARM_SYSTEMTIME].timer.function = alarm_timer_triggered;
- err = platform_driver_register(&alarm_driver);
- if (err < 0)
- goto err1;
- wake_lock_init(&alarm_rtc_wake_lock, WAKE_LOCK_SUSPEND, "alarm_rtc");
- rtc_alarm_interface.class = rtc_class;
- err = class_interface_register(&rtc_alarm_interface);
- if (err < 0)
- goto err2;
-
- return 0;
-
-err2:
- wake_lock_destroy(&alarm_rtc_wake_lock);
- platform_driver_unregister(&alarm_driver);
-err1:
- return err;
-}
-
-static void __exit alarm_exit(void)
-{
- class_interface_unregister(&rtc_alarm_interface);
- wake_lock_destroy(&alarm_rtc_wake_lock);
- platform_driver_unregister(&alarm_driver);
-}
-
-late_initcall(alarm_late_init);
-module_init(alarm_driver_init);
-module_exit(alarm_exit);
-
diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h
index 6eecbde2ef6f..d0cafd637199 100644
--- a/drivers/staging/android/android_alarm.h
+++ b/drivers/staging/android/android_alarm.h
@@ -33,65 +33,6 @@ enum android_alarm_type {
/* ANDROID_ALARM_TIME_CHANGE = 16 */
};
-#ifdef __KERNEL__
-
-#include <linux/ktime.h>
-#include <linux/rbtree.h>
-
-/*
- * The alarm interface is similar to the hrtimer interface but adds support
- * for wakeup from suspend. It also adds an elapsed realtime clock that can
- * be used for periodic timers that need to keep runing while the system is
- * suspended and not be disrupted when the wall time is set.
- */
-
-/**
- * struct alarm - the basic alarm structure
- * @node: red black tree node for time ordered insertion
- * @type: alarm type. rtc/elapsed-realtime/systemtime, wakeup/non-wakeup.
- * @softexpires: the absolute earliest expiry time of the alarm.
- * @expires: the absolute expiry time.
- * @function: alarm expiry callback function
- *
- * The alarm structure must be initialized by alarm_init()
- *
- */
-
-struct android_alarm {
- struct rb_node node;
- enum android_alarm_type type;
- ktime_t softexpires;
- ktime_t expires;
- void (*function)(struct android_alarm *);
-};
-
-void android_alarm_init(struct android_alarm *alarm,
- enum android_alarm_type type, void (*function)(struct android_alarm *));
-void android_alarm_start_range(struct android_alarm *alarm, ktime_t start,
- ktime_t end);
-int android_alarm_try_to_cancel(struct android_alarm *alarm);
-int android_alarm_cancel(struct android_alarm *alarm);
-ktime_t alarm_get_elapsed_realtime(void);
-
-/* set rtc while preserving elapsed realtime */
-int android_alarm_set_rtc(const struct timespec ts);
-
-#ifdef CONFIG_ANDROID_ALARM_OLDDRV_COMPAT
-/*
- * Some older drivers depend on the old API,
- * so provide compatability macros for now.
- */
-#define alarm android_alarm
-#define alarm_init(x, y, z) android_alarm_init(x, y, z)
-#define alarm_start_range(x, y, z) android_alarm_start_range(x, y, z)
-#define alarm_try_to_cancel(x) android_alarm_try_to_cancel(x)
-#define alarm_cancel(x) android_alarm_cancel(x)
-#define alarm_set_rtc(x) android_alarm_set_rtc(x)
-#endif
-
-
-#endif
-
enum android_alarm_return_flags {
ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP,
ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC,
diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h
index 25ab6f2759e9..2f7d195d8b15 100644
--- a/drivers/staging/android/binder.h
+++ b/drivers/staging/android/binder.h
@@ -53,17 +53,17 @@ struct flat_binder_object {
/* 8 bytes of data. */
union {
- void *binder; /* local object */
+ void __user *binder; /* local object */
signed long handle; /* remote object */
};
/* extra data associated with local object */
- void *cookie;
+ void __user *cookie;
};
/*
* On 64-bit platforms where user code may run in 32-bits the driver must
- * translate the buffer (and local binder) addresses apropriately.
+ * translate the buffer (and local binder) addresses appropriately.
*/
struct binder_write_read {
@@ -139,9 +139,9 @@ struct binder_transaction_data {
union {
struct {
/* transaction data */
- const void *buffer;
+ const void __user *buffer;
/* offsets from buffer to flat_binder_object structs */
- const void *offsets;
+ const void __user *offsets;
} ptr;
uint8_t buf[8];
} data;
diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c
index ea69b6a77dac..b2e71c6fd175 100644
--- a/drivers/staging/android/logger.c
+++ b/drivers/staging/android/logger.c
@@ -25,6 +25,7 @@
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/vmalloc.h>
#include "logger.h"
#include <asm/ioctls.h>
@@ -45,8 +46,12 @@ struct logger_log {
size_t w_off; /* current write head offset */
size_t head; /* new readers start here */
size_t size; /* size of the log */
+ struct list_head logs; /* list of log channels (myself)*/
};
+static LIST_HEAD(log_list);
+
+
/*
* struct logger_reader - a logging device open for reading
*
@@ -60,9 +65,9 @@ struct logger_reader {
};
/* logger_offset - returns index 'n' into the log via (optimized) modulus */
-size_t logger_offset(struct logger_log *log, size_t n)
+static size_t logger_offset(struct logger_log *log, size_t n)
{
- return n & (log->size-1);
+ return n & (log->size - 1);
}
@@ -348,7 +353,7 @@ static ssize_t do_write_log_from_user(struct logger_log *log,
* writev(), and aio_write(). Writes are our fast path, and we try to optimize
* them above all else.
*/
-ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
+static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t ppos)
{
struct logger_log *log = file_get_log(iocb->ki_filp);
@@ -408,7 +413,15 @@ ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
return ret;
}
-static struct logger_log *get_log_from_minor(int);
+static struct logger_log *get_log_from_minor(int minor)
+{
+ struct logger_log *log;
+
+ list_for_each_entry(log, &log_list, logs)
+ if (log->misc.minor == minor)
+ return log;
+ return NULL;
+}
/*
* logger_open - the log's open() file operation
@@ -565,80 +578,84 @@ static const struct file_operations logger_fops = {
};
/*
- * Defines a log structure with name 'NAME' and a size of 'SIZE' bytes, which
- * must be a power of two, greater than LOGGER_ENTRY_MAX_LEN, and less than
- * LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
+ * Log size must be a power of two, greater than LOGGER_ENTRY_MAX_LEN,
+ * and less than LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
*/
-#define DEFINE_LOGGER_DEVICE(VAR, NAME, SIZE) \
-static unsigned char _buf_ ## VAR[SIZE]; \
-static struct logger_log VAR = { \
- .buffer = _buf_ ## VAR, \
- .misc = { \
- .minor = MISC_DYNAMIC_MINOR, \
- .name = NAME, \
- .fops = &logger_fops, \
- .parent = NULL, \
- }, \
- .wq = __WAIT_QUEUE_HEAD_INITIALIZER(VAR .wq), \
- .readers = LIST_HEAD_INIT(VAR .readers), \
- .mutex = __MUTEX_INITIALIZER(VAR .mutex), \
- .w_off = 0, \
- .head = 0, \
- .size = SIZE, \
-};
+static int __init create_log(char *log_name, int size)
+{
+ int ret = 0;
+ struct logger_log *log;
+ unsigned char *buffer;
-DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 256*1024)
-DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024)
-DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 256*1024)
-DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 256*1024)
+ buffer = vmalloc(size);
+ if (buffer == NULL)
+ return -ENOMEM;
-static struct logger_log *get_log_from_minor(int minor)
-{
- if (log_main.misc.minor == minor)
- return &log_main;
- if (log_events.misc.minor == minor)
- return &log_events;
- if (log_radio.misc.minor == minor)
- return &log_radio;
- if (log_system.misc.minor == minor)
- return &log_system;
- return NULL;
-}
+ log = kzalloc(sizeof(struct logger_log), GFP_KERNEL);
+ if (log == NULL) {
+ ret = -ENOMEM;
+ goto out_free_buffer;
+ }
+ log->buffer = buffer;
-static int __init init_log(struct logger_log *log)
-{
- int ret;
+ log->misc.minor = MISC_DYNAMIC_MINOR;
+ log->misc.name = kstrdup(log_name, GFP_KERNEL);
+ if (log->misc.name == NULL) {
+ ret = -ENOMEM;
+ goto out_free_log;
+ }
+
+ log->misc.fops = &logger_fops;
+ log->misc.parent = NULL;
+ init_waitqueue_head(&log->wq);
+ INIT_LIST_HEAD(&log->readers);
+ mutex_init(&log->mutex);
+ log->w_off = 0;
+ log->head = 0;
+ log->size = size;
+
+ INIT_LIST_HEAD(&log->logs);
+ list_add_tail(&log->logs, &log_list);
+
+ /* finally, initialize the misc device for this log */
ret = misc_register(&log->misc);
if (unlikely(ret)) {
printk(KERN_ERR "logger: failed to register misc "
"device for log '%s'!\n", log->misc.name);
- return ret;
+ goto out_free_log;
}
printk(KERN_INFO "logger: created %luK log '%s'\n",
(unsigned long) log->size >> 10, log->misc.name);
return 0;
+
+out_free_log:
+ kfree(log);
+
+out_free_buffer:
+ vfree(buffer);
+ return ret;
}
static int __init logger_init(void)
{
int ret;
- ret = init_log(&log_main);
+ ret = create_log(LOGGER_LOG_MAIN, 256*1024);
if (unlikely(ret))
goto out;
- ret = init_log(&log_events);
+ ret = create_log(LOGGER_LOG_EVENTS, 256*1024);
if (unlikely(ret))
goto out;
- ret = init_log(&log_radio);
+ ret = create_log(LOGGER_LOG_RADIO, 256*1024);
if (unlikely(ret))
goto out;
- ret = init_log(&log_system);
+ ret = create_log(LOGGER_LOG_SYSTEM, 256*1024);
if (unlikely(ret))
goto out;
diff --git a/drivers/staging/android/ram_console.c b/drivers/staging/android/ram_console.c
index ce140ffc54ea..82323bb1d1a3 100644
--- a/drivers/staging/android/ram_console.c
+++ b/drivers/staging/android/ram_console.c
@@ -21,7 +21,7 @@
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/io.h>
-#include "persistent_ram.h"
+#include <linux/pstore_ram.h>
#include "ram_console.h"
static struct persistent_ram_zone *ram_console_zone;
diff --git a/drivers/staging/android/switch/Kconfig b/drivers/staging/android/switch/Kconfig
deleted file mode 100644
index 36846f62f4bc..000000000000
--- a/drivers/staging/android/switch/Kconfig
+++ /dev/null
@@ -1,11 +0,0 @@
-menuconfig ANDROID_SWITCH
- tristate "Android Switch class support"
- help
- Say Y here to enable Android switch class support. This allows
- monitoring switches by userspace via sysfs and uevent.
-
-config ANDROID_SWITCH_GPIO
- tristate "Android GPIO Switch support"
- depends on GENERIC_GPIO && ANDROID_SWITCH
- help
- Say Y here to enable GPIO based switch support.
diff --git a/drivers/staging/android/switch/Makefile b/drivers/staging/android/switch/Makefile
deleted file mode 100644
index d76bfdcedfaf..000000000000
--- a/drivers/staging/android/switch/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-# Android Switch Class Driver
-obj-$(CONFIG_ANDROID_SWITCH) += switch_class.o
-obj-$(CONFIG_ANDROID_SWITCH_GPIO) += switch_gpio.o
-
diff --git a/drivers/staging/android/switch/switch.h b/drivers/staging/android/switch/switch.h
deleted file mode 100644
index 4fcb3109875a..000000000000
--- a/drivers/staging/android/switch/switch.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Switch class driver
- *
- * Copyright (C) 2008 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
-*/
-
-#ifndef __LINUX_SWITCH_H__
-#define __LINUX_SWITCH_H__
-
-struct switch_dev {
- const char *name;
- struct device *dev;
- int index;
- int state;
-
- ssize_t (*print_name)(struct switch_dev *sdev, char *buf);
- ssize_t (*print_state)(struct switch_dev *sdev, char *buf);
-};
-
-struct gpio_switch_platform_data {
- const char *name;
- unsigned gpio;
-
- /* if NULL, switch_dev.name will be printed */
- const char *name_on;
- const char *name_off;
- /* if NULL, "0" or "1" will be printed */
- const char *state_on;
- const char *state_off;
-};
-
-extern int switch_dev_register(struct switch_dev *sdev);
-extern void switch_dev_unregister(struct switch_dev *sdev);
-
-static inline int switch_get_state(struct switch_dev *sdev)
-{
- return sdev->state;
-}
-
-extern void switch_set_state(struct switch_dev *sdev, int state);
-
-#endif /* __LINUX_SWITCH_H__ */
diff --git a/drivers/staging/android/switch/switch_class.c b/drivers/staging/android/switch/switch_class.c
deleted file mode 100644
index 74680446fc66..000000000000
--- a/drivers/staging/android/switch/switch_class.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * switch_class.c
- *
- * Copyright (C) 2008 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
-*/
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/err.h>
-#include "switch.h"
-
-struct class *switch_class;
-static atomic_t device_count;
-
-static ssize_t state_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct switch_dev *sdev = (struct switch_dev *)
- dev_get_drvdata(dev);
-
- if (sdev->print_state) {
- int ret = sdev->print_state(sdev, buf);
- if (ret >= 0)
- return ret;
- }
- return sprintf(buf, "%d\n", sdev->state);
-}
-
-static ssize_t name_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct switch_dev *sdev = (struct switch_dev *)
- dev_get_drvdata(dev);
-
- if (sdev->print_name) {
- int ret = sdev->print_name(sdev, buf);
- if (ret >= 0)
- return ret;
- }
- return sprintf(buf, "%s\n", sdev->name);
-}
-
-static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, state_show, NULL);
-static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, name_show, NULL);
-
-void switch_set_state(struct switch_dev *sdev, int state)
-{
- char name_buf[120];
- char state_buf[120];
- char *prop_buf;
- char *envp[3];
- int env_offset = 0;
- int length;
-
- if (sdev->state != state) {
- sdev->state = state;
-
- prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
- if (prop_buf) {
- length = name_show(sdev->dev, NULL, prop_buf);
- if (length > 0) {
- if (prop_buf[length - 1] == '\n')
- prop_buf[length - 1] = 0;
- snprintf(name_buf, sizeof(name_buf),
- "SWITCH_NAME=%s", prop_buf);
- envp[env_offset++] = name_buf;
- }
- length = state_show(sdev->dev, NULL, prop_buf);
- if (length > 0) {
- if (prop_buf[length - 1] == '\n')
- prop_buf[length - 1] = 0;
- snprintf(state_buf, sizeof(state_buf),
- "SWITCH_STATE=%s", prop_buf);
- envp[env_offset++] = state_buf;
- }
- envp[env_offset] = NULL;
- kobject_uevent_env(&sdev->dev->kobj, KOBJ_CHANGE, envp);
- free_page((unsigned long)prop_buf);
- } else {
- printk(KERN_ERR "out of memory in switch_set_state\n");
- kobject_uevent(&sdev->dev->kobj, KOBJ_CHANGE);
- }
- }
-}
-EXPORT_SYMBOL_GPL(switch_set_state);
-
-static int create_switch_class(void)
-{
- if (!switch_class) {
- switch_class = class_create(THIS_MODULE, "switch");
- if (IS_ERR(switch_class))
- return PTR_ERR(switch_class);
- atomic_set(&device_count, 0);
- }
-
- return 0;
-}
-
-int switch_dev_register(struct switch_dev *sdev)
-{
- int ret;
-
- if (!switch_class) {
- ret = create_switch_class();
- if (ret < 0)
- return ret;
- }
-
- sdev->index = atomic_inc_return(&device_count);
- sdev->dev = device_create(switch_class, NULL,
- MKDEV(0, sdev->index), NULL, sdev->name);
- if (IS_ERR(sdev->dev))
- return PTR_ERR(sdev->dev);
-
- ret = device_create_file(sdev->dev, &dev_attr_state);
- if (ret < 0)
- goto err_create_file_1;
- ret = device_create_file(sdev->dev, &dev_attr_name);
- if (ret < 0)
- goto err_create_file_2;
-
- dev_set_drvdata(sdev->dev, sdev);
- sdev->state = 0;
- return 0;
-
-err_create_file_2:
- device_remove_file(sdev->dev, &dev_attr_state);
-err_create_file_1:
- device_destroy(switch_class, MKDEV(0, sdev->index));
- printk(KERN_ERR "switch: Failed to register driver %s\n", sdev->name);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(switch_dev_register);
-
-void switch_dev_unregister(struct switch_dev *sdev)
-{
- device_remove_file(sdev->dev, &dev_attr_name);
- device_remove_file(sdev->dev, &dev_attr_state);
- device_destroy(switch_class, MKDEV(0, sdev->index));
- dev_set_drvdata(sdev->dev, NULL);
-}
-EXPORT_SYMBOL_GPL(switch_dev_unregister);
-
-static int __init switch_class_init(void)
-{
- return create_switch_class();
-}
-
-static void __exit switch_class_exit(void)
-{
- class_destroy(switch_class);
-}
-
-module_init(switch_class_init);
-module_exit(switch_class_exit);
-
-MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
-MODULE_DESCRIPTION("Switch class driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/android/switch/switch_gpio.c b/drivers/staging/android/switch/switch_gpio.c
deleted file mode 100644
index 38b2c2f6004e..000000000000
--- a/drivers/staging/android/switch/switch_gpio.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * switch_gpio.c
- *
- * Copyright (C) 2008 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/gpio.h>
-#include "switch.h"
-
-struct gpio_switch_data {
- struct switch_dev sdev;
- unsigned gpio;
- const char *name_on;
- const char *name_off;
- const char *state_on;
- const char *state_off;
- int irq;
- struct work_struct work;
-};
-
-static void gpio_switch_work(struct work_struct *work)
-{
- int state;
- struct gpio_switch_data *data =
- container_of(work, struct gpio_switch_data, work);
-
- state = gpio_get_value(data->gpio);
- switch_set_state(&data->sdev, state);
-}
-
-static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
-{
- struct gpio_switch_data *switch_data =
- (struct gpio_switch_data *)dev_id;
-
- schedule_work(&switch_data->work);
- return IRQ_HANDLED;
-}
-
-static ssize_t switch_gpio_print_state(struct switch_dev *sdev, char *buf)
-{
- struct gpio_switch_data *switch_data =
- container_of(sdev, struct gpio_switch_data, sdev);
- const char *state;
- if (switch_get_state(sdev))
- state = switch_data->state_on;
- else
- state = switch_data->state_off;
-
- if (state)
- return sprintf(buf, "%s\n", state);
- return -1;
-}
-
-static int gpio_switch_probe(struct platform_device *pdev)
-{
- struct gpio_switch_platform_data *pdata = pdev->dev.platform_data;
- struct gpio_switch_data *switch_data;
- int ret = 0;
-
- if (!pdata)
- return -EBUSY;
-
- switch_data = kzalloc(sizeof(struct gpio_switch_data), GFP_KERNEL);
- if (!switch_data)
- return -ENOMEM;
-
- switch_data->sdev.name = pdata->name;
- switch_data->gpio = pdata->gpio;
- switch_data->name_on = pdata->name_on;
- switch_data->name_off = pdata->name_off;
- switch_data->state_on = pdata->state_on;
- switch_data->state_off = pdata->state_off;
- switch_data->sdev.print_state = switch_gpio_print_state;
-
- ret = switch_dev_register(&switch_data->sdev);
- if (ret < 0)
- goto err_switch_dev_register;
-
- ret = gpio_request(switch_data->gpio, pdev->name);
- if (ret < 0)
- goto err_request_gpio;
-
- ret = gpio_direction_input(switch_data->gpio);
- if (ret < 0)
- goto err_set_gpio_input;
-
- INIT_WORK(&switch_data->work, gpio_switch_work);
-
- switch_data->irq = gpio_to_irq(switch_data->gpio);
- if (switch_data->irq < 0) {
- ret = switch_data->irq;
- goto err_detect_irq_num_failed;
- }
-
- ret = request_irq(switch_data->irq, gpio_irq_handler,
- IRQF_TRIGGER_LOW, pdev->name, switch_data);
- if (ret < 0)
- goto err_request_irq;
-
- /* Perform initial detection */
- gpio_switch_work(&switch_data->work);
-
- return 0;
-
-err_request_irq:
-err_detect_irq_num_failed:
-err_set_gpio_input:
- gpio_free(switch_data->gpio);
-err_request_gpio:
- switch_dev_unregister(&switch_data->sdev);
-err_switch_dev_register:
- kfree(switch_data);
-
- return ret;
-}
-
-static int __devexit gpio_switch_remove(struct platform_device *pdev)
-{
- struct gpio_switch_data *switch_data = platform_get_drvdata(pdev);
-
- cancel_work_sync(&switch_data->work);
- gpio_free(switch_data->gpio);
- switch_dev_unregister(&switch_data->sdev);
- kfree(switch_data);
-
- return 0;
-}
-
-static struct platform_driver gpio_switch_driver = {
- .probe = gpio_switch_probe,
- .remove = __devexit_p(gpio_switch_remove),
- .driver = {
- .name = "switch-gpio",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init gpio_switch_init(void)
-{
- return platform_driver_register(&gpio_switch_driver);
-}
-
-static void __exit gpio_switch_exit(void)
-{
- platform_driver_unregister(&gpio_switch_driver);
-}
-
-module_init(gpio_switch_init);
-module_exit(gpio_switch_exit);
-
-MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
-MODULE_DESCRIPTION("GPIO Switch driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/android/timed_output.c b/drivers/staging/android/timed_output.c
index f373422308e0..38d930cadad3 100644
--- a/drivers/staging/android/timed_output.c
+++ b/drivers/staging/android/timed_output.c
@@ -99,6 +99,7 @@ EXPORT_SYMBOL_GPL(timed_output_dev_register);
void timed_output_dev_unregister(struct timed_output_dev *tdev)
{
+ tdev->enable(tdev, 0);
device_remove_file(tdev->dev, &dev_attr_enable);
device_destroy(timed_output_class, MKDEV(0, tdev->index));
dev_set_drvdata(tdev->dev, NULL);
diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c
index 83549d9cfefc..510d79639217 100644
--- a/drivers/staging/asus_oled/asus_oled.c
+++ b/drivers/staging/asus_oled/asus_oled.c
@@ -782,20 +782,20 @@ static int __init asus_oled_init(void)
oled_class = class_create(THIS_MODULE, ASUS_OLED_UNDERSCORE_NAME);
if (IS_ERR(oled_class)) {
- err("Error creating " ASUS_OLED_UNDERSCORE_NAME " class");
+ printk(KERN_ERR "Error creating " ASUS_OLED_UNDERSCORE_NAME " class\n");
return PTR_ERR(oled_class);
}
retval = class_create_file(oled_class, &class_attr_version.attr);
if (retval) {
- err("Error creating class version file");
+ printk(KERN_ERR "Error creating class version file\n");
goto error;
}
retval = usb_register(&oled_driver);
if (retval) {
- err("usb_register failed. Error number %d", retval);
+ printk(KERN_ERR "usb_register failed. Error number %d\n", retval);
goto error;
}
diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h
index 20cca24ff5f0..aa51d17be5a1 100644
--- a/drivers/staging/bcm/Adapter.h
+++ b/drivers/staging/bcm/Adapter.h
@@ -7,168 +7,145 @@
#define MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES 256
#include "Debug.h"
-struct _LEADER
-{
- USHORT Vcid;
- USHORT PLength;
- UCHAR Status;
+struct _LEADER {
+ USHORT Vcid;
+ USHORT PLength;
+ UCHAR Status;
UCHAR Unused[3];
-}__attribute__((packed));
-typedef struct _LEADER LEADER,*PLEADER;
+} __packed;
+typedef struct _LEADER LEADER, *PLEADER;
-struct _PACKETTOSEND
-{
+struct _PACKETTOSEND {
LEADER Leader;
UCHAR ucPayload;
-}__attribute__((packed));
+} __packed;
typedef struct _PACKETTOSEND PACKETTOSEND, *PPACKETTOSEND;
-
-struct _CONTROL_PACKET
-{
+struct _CONTROL_PACKET {
PVOID ControlBuff;
UINT ControlBuffLen;
- struct _CONTROL_PACKET* next;
-}__attribute__((packed));
-typedef struct _CONTROL_PACKET CONTROL_PACKET,*PCONTROL_PACKET;
-
+ struct _CONTROL_PACKET *next;
+} __packed;
+typedef struct _CONTROL_PACKET CONTROL_PACKET, *PCONTROL_PACKET;
-struct link_request
-{
+struct link_request {
LEADER Leader;
UCHAR szData[4];
-}__attribute__((packed));
+} __packed;
typedef struct link_request LINK_REQUEST, *PLINK_REQUEST;
-
-//classification extension is added
-typedef struct _ADD_CONNECTION
-{
- ULONG SrcIpAddressCount;
- ULONG SrcIpAddress[MAX_CONNECTIONS];
- ULONG SrcIpMask[MAX_CONNECTIONS];
-
- ULONG DestIpAddressCount;
- ULONG DestIpAddress[MAX_CONNECTIONS];
- ULONG DestIpMask[MAX_CONNECTIONS];
-
- USHORT SrcPortBegin;
- USHORT SrcPortEnd;
-
- USHORT DestPortBegin;
- USHORT DestPortEnd;
-
- UCHAR SrcTOS;
- UCHAR SrcProtocol;
-} ADD_CONNECTION,*PADD_CONNECTION;
-
-
-typedef struct _CLASSIFICATION_RULE
-{
- UCHAR ucIPSrcAddrLen;
- UCHAR ucIPSrcAddr[32];
- UCHAR ucIPDestAddrLen;
- UCHAR ucIPDestAddr[32];
- UCHAR ucSrcPortRangeLen;
- UCHAR ucSrcPortRange[4];
- UCHAR ucDestPortRangeLen;
- UCHAR ucDestPortRange[4];
- USHORT usVcid;
-} CLASSIFICATION_RULE,*PCLASSIFICATION_RULE;
-
-typedef struct _CLASSIFICATION_ONLY
-{
- USHORT usVcid;
- ULONG DestIpAddress;
- ULONG DestIpMask;
- USHORT usPortLo;
- USHORT usPortHi;
- BOOLEAN bIpVersion;
- UCHAR ucDestinationAddress[16];
+/* classification extension is added */
+typedef struct _ADD_CONNECTION {
+ ULONG SrcIpAddressCount;
+ ULONG SrcIpAddress[MAX_CONNECTIONS];
+ ULONG SrcIpMask[MAX_CONNECTIONS];
+
+ ULONG DestIpAddressCount;
+ ULONG DestIpAddress[MAX_CONNECTIONS];
+ ULONG DestIpMask[MAX_CONNECTIONS];
+
+ USHORT SrcPortBegin;
+ USHORT SrcPortEnd;
+
+ USHORT DestPortBegin;
+ USHORT DestPortEnd;
+
+ UCHAR SrcTOS;
+ UCHAR SrcProtocol;
+} ADD_CONNECTION, *PADD_CONNECTION;
+
+typedef struct _CLASSIFICATION_RULE {
+ UCHAR ucIPSrcAddrLen;
+ UCHAR ucIPSrcAddr[32];
+ UCHAR ucIPDestAddrLen;
+ UCHAR ucIPDestAddr[32];
+ UCHAR ucSrcPortRangeLen;
+ UCHAR ucSrcPortRange[4];
+ UCHAR ucDestPortRangeLen;
+ UCHAR ucDestPortRange[4];
+ USHORT usVcid;
+} CLASSIFICATION_RULE, *PCLASSIFICATION_RULE;
+
+typedef struct _CLASSIFICATION_ONLY {
+ USHORT usVcid;
+ ULONG DestIpAddress;
+ ULONG DestIpMask;
+ USHORT usPortLo;
+ USHORT usPortHi;
+ BOOLEAN bIpVersion;
+ UCHAR ucDestinationAddress[16];
} CLASSIFICATION_ONLY, *PCLASSIFICATION_ONLY;
-
#define MAX_IP_RANGE_LENGTH 4
#define MAX_PORT_RANGE 4
#define MAX_PROTOCOL_LENGTH 32
#define IPV6_ADDRESS_SIZEINBYTES 0x10
-typedef union _U_IP_ADDRESS
-{
- struct
- {
- ULONG ulIpv4Addr[MAX_IP_RANGE_LENGTH];//Source Ip Address Range
- ULONG ulIpv4Mask[MAX_IP_RANGE_LENGTH];//Source Ip Mask Address Range
+typedef union _U_IP_ADDRESS {
+ struct {
+ ULONG ulIpv4Addr[MAX_IP_RANGE_LENGTH]; /* Source Ip Address Range */
+ ULONG ulIpv4Mask[MAX_IP_RANGE_LENGTH]; /* Source Ip Mask Address Range */
};
- struct
- {
- ULONG ulIpv6Addr[MAX_IP_RANGE_LENGTH * 4];//Source Ip Address Range
- ULONG ulIpv6Mask[MAX_IP_RANGE_LENGTH * 4];//Source Ip Mask Address Range
-
+ struct {
+ ULONG ulIpv6Addr[MAX_IP_RANGE_LENGTH * 4]; /* Source Ip Address Range */
+ ULONG ulIpv6Mask[MAX_IP_RANGE_LENGTH * 4]; /* Source Ip Mask Address Range */
};
- struct
- {
- UCHAR ucIpv4Address[MAX_IP_RANGE_LENGTH * IP_LENGTH_OF_ADDRESS];
- UCHAR ucIpv4Mask[MAX_IP_RANGE_LENGTH * IP_LENGTH_OF_ADDRESS];
+ struct {
+ UCHAR ucIpv4Address[MAX_IP_RANGE_LENGTH * IP_LENGTH_OF_ADDRESS];
+ UCHAR ucIpv4Mask[MAX_IP_RANGE_LENGTH * IP_LENGTH_OF_ADDRESS];
};
- struct
- {
- UCHAR ucIpv6Address[MAX_IP_RANGE_LENGTH * IPV6_ADDRESS_SIZEINBYTES];
- UCHAR ucIpv6Mask[MAX_IP_RANGE_LENGTH * IPV6_ADDRESS_SIZEINBYTES];
+ struct {
+ UCHAR ucIpv6Address[MAX_IP_RANGE_LENGTH * IPV6_ADDRESS_SIZEINBYTES];
+ UCHAR ucIpv6Mask[MAX_IP_RANGE_LENGTH * IPV6_ADDRESS_SIZEINBYTES];
};
-}U_IP_ADDRESS;
+} U_IP_ADDRESS;
struct _packet_info;
-typedef struct _S_HDR_SUPRESSION_CONTEXTINFO
-{
+typedef struct _S_HDR_SUPRESSION_CONTEXTINFO {
+ UCHAR ucaHdrSupressionInBuf[MAX_PHS_LENGTHS]; /* Intermediate buffer to accumulate pkt Header for PHS */
+ UCHAR ucaHdrSupressionOutBuf[MAX_PHS_LENGTHS + PHSI_LEN]; /* Intermediate buffer containing pkt Header after PHS */
+} S_HDR_SUPRESSION_CONTEXTINFO;
+
+typedef struct _S_CLASSIFIER_RULE {
+ ULONG ulSFID;
+ UCHAR ucReserved[2];
+ B_UINT16 uiClassifierRuleIndex;
+ BOOLEAN bUsed;
+ USHORT usVCID_Value;
+ B_UINT8 u8ClassifierRulePriority; /* This field detemines the Classifier Priority */
+ U_IP_ADDRESS stSrcIpAddress;
+ UCHAR ucIPSourceAddressLength; /* Ip Source Address Length */
- UCHAR ucaHdrSupressionInBuf[MAX_PHS_LENGTHS]; //Intermediate buffer to accumulate pkt Header for PHS
- UCHAR ucaHdrSupressionOutBuf[MAX_PHS_LENGTHS + PHSI_LEN]; //Intermediate buffer containing pkt Header after PHS
+ U_IP_ADDRESS stDestIpAddress;
+ UCHAR ucIPDestinationAddressLength; /* Ip Destination Address Length */
+ UCHAR ucIPTypeOfServiceLength; /* Type of service Length */
+ UCHAR ucTosLow; /* Tos Low */
+ UCHAR ucTosHigh; /* Tos High */
+ UCHAR ucTosMask; /* Tos Mask */
-}S_HDR_SUPRESSION_CONTEXTINFO;
+ UCHAR ucProtocolLength; /* protocol Length */
+ UCHAR ucProtocol[MAX_PROTOCOL_LENGTH]; /* protocol Length */
+ USHORT usSrcPortRangeLo[MAX_PORT_RANGE];
+ USHORT usSrcPortRangeHi[MAX_PORT_RANGE];
+ UCHAR ucSrcPortRangeLength;
+ USHORT usDestPortRangeLo[MAX_PORT_RANGE];
+ USHORT usDestPortRangeHi[MAX_PORT_RANGE];
+ UCHAR ucDestPortRangeLength;
-typedef struct _S_CLASSIFIER_RULE
-{
- ULONG ulSFID;
- UCHAR ucReserved[2];
- B_UINT16 uiClassifierRuleIndex;
- BOOLEAN bUsed;
- USHORT usVCID_Value;
- B_UINT8 u8ClassifierRulePriority; //This field detemines the Classifier Priority
- U_IP_ADDRESS stSrcIpAddress;
- UCHAR ucIPSourceAddressLength;//Ip Source Address Length
-
- U_IP_ADDRESS stDestIpAddress;
- UCHAR ucIPDestinationAddressLength;//Ip Destination Address Length
- UCHAR ucIPTypeOfServiceLength;//Type of service Length
- UCHAR ucTosLow;//Tos Low
- UCHAR ucTosHigh;//Tos High
- UCHAR ucTosMask;//Tos Mask
-
- UCHAR ucProtocolLength;//protocol Length
- UCHAR ucProtocol[MAX_PROTOCOL_LENGTH];//protocol Length
- USHORT usSrcPortRangeLo[MAX_PORT_RANGE];
- USHORT usSrcPortRangeHi[MAX_PORT_RANGE];
- UCHAR ucSrcPortRangeLength;
-
- USHORT usDestPortRangeLo[MAX_PORT_RANGE];
- USHORT usDestPortRangeHi[MAX_PORT_RANGE];
- UCHAR ucDestPortRangeLength;
-
- BOOLEAN bProtocolValid;
- BOOLEAN bTOSValid;
- BOOLEAN bDestIpValid;
- BOOLEAN bSrcIpValid;
-
- //For IPv6 Addressing
- UCHAR ucDirection;
- BOOLEAN bIpv6Protocol;
- UINT32 u32PHSRuleID;
- S_PHS_RULE sPhsRule;
- UCHAR u8AssociatedPHSI;
-
- //Classification fields for ETH CS
+ BOOLEAN bProtocolValid;
+ BOOLEAN bTOSValid;
+ BOOLEAN bDestIpValid;
+ BOOLEAN bSrcIpValid;
+
+ /* For IPv6 Addressing */
+ UCHAR ucDirection;
+ BOOLEAN bIpv6Protocol;
+ UINT32 u32PHSRuleID;
+ S_PHS_RULE sPhsRule;
+ UCHAR u8AssociatedPHSI;
+
+ /* Classification fields for ETH CS */
UCHAR ucEthCSSrcMACLen;
UCHAR au8EThCSSrcMAC[MAC_ADDRESS_SIZE];
UCHAR au8EThCSSrcMACMask[MAC_ADDRESS_SIZE];
@@ -180,71 +157,67 @@ typedef struct _S_CLASSIFIER_RULE
UCHAR usUserPriority[2];
USHORT usVLANID;
USHORT usValidityBitMap;
-}S_CLASSIFIER_RULE;
-//typedef struct _S_CLASSIFIER_RULE S_CLASSIFIER_RULE;
-
-typedef struct _S_FRAGMENTED_PACKET_INFO
-{
- BOOLEAN bUsed;
- ULONG ulSrcIpAddress;
- USHORT usIpIdentification;
- S_CLASSIFIER_RULE *pstMatchedClassifierEntry;
- BOOLEAN bOutOfOrderFragment;
-}S_FRAGMENTED_PACKET_INFO,*PS_FRAGMENTED_PACKET_INFO;
-
-struct _packet_info
-{
- //classification extension Rule
- ULONG ulSFID;
- USHORT usVCID_Value;
- UINT uiThreshold;
- // This field determines the priority of the SF Queues
- B_UINT8 u8TrafficPriority;
-
- BOOLEAN bValid;
- BOOLEAN bActive;
- BOOLEAN bActivateRequestSent;
-
- B_UINT8 u8QueueType;//BE or rtPS
-
- UINT uiMaxBucketSize;//maximum size of the bucket for the queue
- UINT uiCurrentQueueDepthOnTarget;
- UINT uiCurrentBytesOnHost;
- UINT uiCurrentPacketsOnHost;
- UINT uiDroppedCountBytes;
- UINT uiDroppedCountPackets;
- UINT uiSentBytes;
- UINT uiSentPackets;
- UINT uiCurrentDrainRate;
- UINT uiThisPeriodSentBytes;
+} S_CLASSIFIER_RULE;
+/* typedef struct _S_CLASSIFIER_RULE S_CLASSIFIER_RULE; */
+
+typedef struct _S_FRAGMENTED_PACKET_INFO {
+ BOOLEAN bUsed;
+ ULONG ulSrcIpAddress;
+ USHORT usIpIdentification;
+ S_CLASSIFIER_RULE *pstMatchedClassifierEntry;
+ BOOLEAN bOutOfOrderFragment;
+} S_FRAGMENTED_PACKET_INFO, *PS_FRAGMENTED_PACKET_INFO;
+
+struct _packet_info {
+ /* classification extension Rule */
+ ULONG ulSFID;
+ USHORT usVCID_Value;
+ UINT uiThreshold;
+ /* This field determines the priority of the SF Queues */
+ B_UINT8 u8TrafficPriority;
+
+ BOOLEAN bValid;
+ BOOLEAN bActive;
+ BOOLEAN bActivateRequestSent;
+
+ B_UINT8 u8QueueType; /* BE or rtPS */
+
+ UINT uiMaxBucketSize; /* maximum size of the bucket for the queue */
+ UINT uiCurrentQueueDepthOnTarget;
+ UINT uiCurrentBytesOnHost;
+ UINT uiCurrentPacketsOnHost;
+ UINT uiDroppedCountBytes;
+ UINT uiDroppedCountPackets;
+ UINT uiSentBytes;
+ UINT uiSentPackets;
+ UINT uiCurrentDrainRate;
+ UINT uiThisPeriodSentBytes;
LARGE_INTEGER liDrainCalculated;
- UINT uiCurrentTokenCount;
- LARGE_INTEGER liLastUpdateTokenAt;
- UINT uiMaxAllowedRate;
- UINT NumOfPacketsSent;
- UCHAR ucDirection;
- USHORT usCID;
+ UINT uiCurrentTokenCount;
+ LARGE_INTEGER liLastUpdateTokenAt;
+ UINT uiMaxAllowedRate;
+ UINT NumOfPacketsSent;
+ UCHAR ucDirection;
+ USHORT usCID;
S_MIBS_EXTSERVICEFLOW_PARAMETERS stMibsExtServiceFlowTable;
- UINT uiCurrentRxRate;
- UINT uiThisPeriodRxBytes;
- UINT uiTotalRxBytes;
- UINT uiTotalTxBytes;
- UINT uiPendedLast;
- UCHAR ucIpVersion;
-
- union
- {
- struct
- {
- struct sk_buff* FirstTxQueue;
- struct sk_buff* LastTxQueue;
+ UINT uiCurrentRxRate;
+ UINT uiThisPeriodRxBytes;
+ UINT uiTotalRxBytes;
+ UINT uiTotalTxBytes;
+ UINT uiPendedLast;
+ UCHAR ucIpVersion;
+
+ union {
+ struct {
+ struct sk_buff *FirstTxQueue;
+ struct sk_buff *LastTxQueue;
};
- struct
- {
- struct sk_buff* ControlHead;
- struct sk_buff* ControlTail;
+ struct {
+ struct sk_buff *ControlHead;
+ struct sk_buff *ControlTail;
};
};
+
BOOLEAN bProtocolValid;
BOOLEAN bTOSValid;
BOOLEAN bDestIpValid;
@@ -255,226 +228,209 @@ struct _packet_info
BOOLEAN bAuthorizedSet;
BOOLEAN bClassifierPriority;
UCHAR ucServiceClassName[MAX_CLASS_NAME_LENGTH];
- BOOLEAN bHeaderSuppressionEnabled;
+ BOOLEAN bHeaderSuppressionEnabled;
spinlock_t SFQueueLock;
- void *pstSFIndication;
+ void *pstSFIndication;
struct timeval stLastUpdateTokenAt;
- atomic_t uiPerSFTxResourceCount;
+ atomic_t uiPerSFTxResourceCount;
UINT uiMaxLatency;
- UCHAR bIPCSSupport;
- UCHAR bEthCSSupport;
+ UCHAR bIPCSSupport;
+ UCHAR bEthCSSupport;
};
typedef struct _packet_info PacketInfo;
-
-typedef struct _PER_TARANG_DATA
-{
- struct _PER_TARANG_DATA * next;
- struct _MINI_ADAPTER * Adapter;
- struct sk_buff* RxAppControlHead;
- struct sk_buff* RxAppControlTail;
- volatile INT AppCtrlQueueLen;
- BOOLEAN MacTracingEnabled;
- BOOLEAN bApplicationToExit;
- S_MIBS_DROPPED_APP_CNTRL_MESSAGES stDroppedAppCntrlMsgs;
- ULONG RxCntrlMsgBitMask;
+typedef struct _PER_TARANG_DATA {
+ struct _PER_TARANG_DATA *next;
+ struct _MINI_ADAPTER *Adapter;
+ struct sk_buff *RxAppControlHead;
+ struct sk_buff *RxAppControlTail;
+ int AppCtrlQueueLen;
+ BOOLEAN MacTracingEnabled;
+ BOOLEAN bApplicationToExit;
+ S_MIBS_DROPPED_APP_CNTRL_MESSAGES stDroppedAppCntrlMsgs;
+ ULONG RxCntrlMsgBitMask;
} PER_TARANG_DATA, *PPER_TARANG_DATA;
-
#ifdef REL_4_1
-typedef struct _TARGET_PARAMS
-{
- B_UINT32 m_u32CfgVersion;
-
- // Scanning Related Params
- B_UINT32 m_u32CenterFrequency;
- B_UINT32 m_u32BandAScan;
- B_UINT32 m_u32BandBScan;
- B_UINT32 m_u32BandCScan;
-
- // QoS Params
- B_UINT32 m_u32minGrantsize; // size of minimum grant is 0 or 6
- B_UINT32 m_u32PHSEnable;
-
- // HO Params
- B_UINT32 m_u32HoEnable;
- B_UINT32 m_u32HoReserved1;
- B_UINT32 m_u32HoReserved2;
-
- // Power Control Params
- B_UINT32 m_u32MimoEnable;
- B_UINT32 m_u32SecurityEnable;
+typedef struct _TARGET_PARAMS {
+ B_UINT32 m_u32CfgVersion;
+
+ /* Scanning Related Params */
+ B_UINT32 m_u32CenterFrequency;
+ B_UINT32 m_u32BandAScan;
+ B_UINT32 m_u32BandBScan;
+ B_UINT32 m_u32BandCScan;
+
+ /* QoS Params */
+ B_UINT32 m_u32minGrantsize; /* size of minimum grant is 0 or 6 */
+ B_UINT32 m_u32PHSEnable;
+
+ /* HO Params */
+ B_UINT32 m_u32HoEnable;
+ B_UINT32 m_u32HoReserved1;
+ B_UINT32 m_u32HoReserved2;
+
+ /* Power Control Params */
+ B_UINT32 m_u32MimoEnable;
+ B_UINT32 m_u32SecurityEnable;
/*
- * bit 1: 1 Idlemode enable;
- * bit 2: 1 Sleepmode Enable
- */
- B_UINT32 m_u32PowerSavingModesEnable;
- /* PowerSaving Mode Options:
- bit 0 = 1: CPE mode - to keep pcmcia if alive;
- bit 1 = 1: CINR reporing in Idlemode Msg
- bit 2 = 1: Default PSC Enable in sleepmode*/
- B_UINT32 m_u32PowerSavingModeOptions;
-
- B_UINT32 m_u32ArqEnable;
-
- // From Version #3, the HARQ section renamed as general
- B_UINT32 m_u32HarqEnable;
- // EEPROM Param Location
- B_UINT32 m_u32EEPROMFlag;
- /* BINARY TYPE - 4th MSByte:
- * Interface Type - 3rd MSByte:
- * Vendor Type - 2nd MSByte
- */
- // Unused - LSByte
- B_UINT32 m_u32Customize;
- B_UINT32 m_u32ConfigBW; /* In Hz */
- B_UINT32 m_u32ShutDownTimer;
-
-
- B_UINT32 m_u32RadioParameter;
- B_UINT32 m_u32PhyParameter1;
- B_UINT32 m_u32PhyParameter2;
- B_UINT32 m_u32PhyParameter3;
+ * bit 1: 1 Idlemode enable;
+ * bit 2: 1 Sleepmode Enable
+ */
+ B_UINT32 m_u32PowerSavingModesEnable;
+ /* PowerSaving Mode Options:
+ * bit 0 = 1: CPE mode - to keep pcmcia if alive;
+ * bit 1 = 1: CINR reporing in Idlemode Msg
+ * bit 2 = 1: Default PSC Enable in sleepmode
+ */
+ B_UINT32 m_u32PowerSavingModeOptions;
+
+ B_UINT32 m_u32ArqEnable;
+
+ /* From Version #3, the HARQ section renamed as general */
+ B_UINT32 m_u32HarqEnable;
+ /* EEPROM Param Location */
+ B_UINT32 m_u32EEPROMFlag;
+ /* BINARY TYPE - 4th MSByte:
+ * Interface Type - 3rd MSByte:
+ * Vendor Type - 2nd MSByte
+ */
+ /* Unused - LSByte */
+ B_UINT32 m_u32Customize;
+ B_UINT32 m_u32ConfigBW; /* In Hz */
+ B_UINT32 m_u32ShutDownTimer;
+ B_UINT32 m_u32RadioParameter;
+ B_UINT32 m_u32PhyParameter1;
+ B_UINT32 m_u32PhyParameter2;
+ B_UINT32 m_u32PhyParameter3;
/* in eval mode only;
- * lower 16bits = basic cid for testing;
- * then bit 16 is test cqich,
- * bit 17 test init rang;
- * bit 18 test periodic rang
- * bit 19 is test harq ack/nack
- */
- B_UINT32 m_u32TestOptions;
-
+ * lower 16bits = basic cid for testing;
+ * then bit 16 is test cqich,
+ * bit 17 test init rang;
+ * bit 18 test periodic rang
+ * bit 19 is test harq ack/nack
+ */
+ B_UINT32 m_u32TestOptions;
B_UINT32 m_u32MaxMACDataperDLFrame;
B_UINT32 m_u32MaxMACDataperULFrame;
-
B_UINT32 m_u32Corr2MacFlags;
- //adding driver params.
- B_UINT32 HostDrvrConfig1;
- B_UINT32 HostDrvrConfig2;
- B_UINT32 HostDrvrConfig3;
- B_UINT32 HostDrvrConfig4;
- B_UINT32 HostDrvrConfig5;
- B_UINT32 HostDrvrConfig6;
- B_UINT32 m_u32SegmentedPUSCenable;
-
- // BAMC enable - but 4.x does not support this feature
- // This is added just to sync 4.x and 5.x CFGs
+ /* adding driver params. */
+ B_UINT32 HostDrvrConfig1;
+ B_UINT32 HostDrvrConfig2;
+ B_UINT32 HostDrvrConfig3;
+ B_UINT32 HostDrvrConfig4;
+ B_UINT32 HostDrvrConfig5;
+ B_UINT32 HostDrvrConfig6;
+ B_UINT32 m_u32SegmentedPUSCenable;
+
+ /* BAMC enable - but 4.x does not support this feature
+ * This is added just to sync 4.x and 5.x CFGs
+ */
B_UINT32 m_u32BandAMCEnable;
} STARGETPARAMS, *PSTARGETPARAMS;
#endif
-typedef struct _STTARGETDSXBUFFER
-{
- ULONG ulTargetDsxBuffer;
- B_UINT16 tid;
- BOOLEAN valid;
-}STTARGETDSXBUFFER, *PSTTARGETDSXBUFFER;
+typedef struct _STTARGETDSXBUFFER {
+ ULONG ulTargetDsxBuffer;
+ B_UINT16 tid;
+ BOOLEAN valid;
+} STTARGETDSXBUFFER, *PSTTARGETDSXBUFFER;
-typedef INT (*FP_FLASH_WRITE)(struct _MINI_ADAPTER*,UINT,PVOID);
+typedef int (*FP_FLASH_WRITE)(struct _MINI_ADAPTER *, UINT, PVOID);
-typedef INT (*FP_FLASH_WRITE_STATUS)(struct _MINI_ADAPTER*,UINT,PVOID);
+typedef int (*FP_FLASH_WRITE_STATUS)(struct _MINI_ADAPTER *, UINT, PVOID);
-/**
-Driver adapter data structure
-*/
-struct _MINI_ADAPTER
-{
- struct _MINI_ADAPTER *next;
+/*
+ * Driver adapter data structure
+ */
+struct _MINI_ADAPTER {
+ struct _MINI_ADAPTER *next;
struct net_device *dev;
u32 msg_enable;
-
- CHAR *caDsxReqResp;
+ CHAR *caDsxReqResp;
atomic_t ApplicationRunning;
- volatile INT CtrlQueueLen;
- atomic_t AppCtrlQueueLen;
- BOOLEAN AppCtrlQueueOverFlow;
+ BOOLEAN AppCtrlQueueOverFlow;
atomic_t CurrentApplicationCount;
- atomic_t RegisteredApplicationCount;
- BOOLEAN LinkUpStatus;
- BOOLEAN TimerActive;
+ atomic_t RegisteredApplicationCount;
+ BOOLEAN LinkUpStatus;
+ BOOLEAN TimerActive;
u32 StatisticsPointer;
struct sk_buff *RxControlHead;
struct sk_buff *RxControlTail;
-
struct semaphore RxAppControlQueuelock;
struct semaphore fw_download_sema;
-
- PPER_TARANG_DATA pTarangs;
- spinlock_t control_queue_lock;
+ PPER_TARANG_DATA pTarangs;
+ spinlock_t control_queue_lock;
wait_queue_head_t process_read_wait_queue;
- // the pointer to the first packet we have queued in send
- // deserialized miniport support variables
- atomic_t TotalPacketCount;
- atomic_t TxPktAvail;
-
- // this to keep track of the Tx and Rx MailBox Registers.
- atomic_t CurrNumFreeTxDesc;
- // to keep track the no of byte received
- USHORT PrevNumRecvDescs;
- USHORT CurrNumRecvDescs;
- UINT u32TotalDSD;
- PacketInfo PackInfo[NO_OF_QUEUES];
+ /* the pointer to the first packet we have queued in send
+ * deserialized miniport support variables
+ */
+ atomic_t TotalPacketCount;
+ atomic_t TxPktAvail;
+
+ /* this to keep track of the Tx and Rx MailBox Registers. */
+ atomic_t CurrNumFreeTxDesc;
+ /* to keep track the no of byte received */
+ USHORT PrevNumRecvDescs;
+ USHORT CurrNumRecvDescs;
+ UINT u32TotalDSD;
+ PacketInfo PackInfo[NO_OF_QUEUES];
S_CLASSIFIER_RULE astClassifierTable[MAX_CLASSIFIERS];
- BOOLEAN TransferMode;
+ BOOLEAN TransferMode;
/*************** qos ******************/
- BOOLEAN bETHCSEnabled;
-
- ULONG BEBucketSize;
- ULONG rtPSBucketSize;
- UCHAR LinkStatus;
- BOOLEAN AutoLinkUp;
- BOOLEAN AutoSyncup;
-
- int major;
- int minor;
- wait_queue_head_t tx_packet_wait_queue;
- wait_queue_head_t process_rx_cntrlpkt;
- atomic_t process_waiting;
- BOOLEAN fw_download_done;
-
- char *txctlpacket[MAX_CNTRL_PKTS];
- atomic_t cntrlpktCnt ;
- atomic_t index_app_read_cntrlpkt;
- atomic_t index_wr_txcntrlpkt;
- atomic_t index_rd_txcntrlpkt;
- UINT index_datpkt;
- struct semaphore rdmwrmsync;
+ BOOLEAN bETHCSEnabled;
+ ULONG BEBucketSize;
+ ULONG rtPSBucketSize;
+ UCHAR LinkStatus;
+ BOOLEAN AutoLinkUp;
+ BOOLEAN AutoSyncup;
+
+ int major;
+ int minor;
+ wait_queue_head_t tx_packet_wait_queue;
+ wait_queue_head_t process_rx_cntrlpkt;
+ atomic_t process_waiting;
+ BOOLEAN fw_download_done;
+
+ char *txctlpacket[MAX_CNTRL_PKTS];
+ atomic_t cntrlpktCnt ;
+ atomic_t index_app_read_cntrlpkt;
+ atomic_t index_wr_txcntrlpkt;
+ atomic_t index_rd_txcntrlpkt;
+ UINT index_datpkt;
+ struct semaphore rdmwrmsync;
STTARGETDSXBUFFER astTargetDsxBuffer[MAX_TARGET_DSX_BUFFERS];
ULONG ulFreeTargetBufferCnt;
- ULONG ulCurrentTargetBuffer;
- ULONG ulTotalTargetBuffersAvailable;
-
- unsigned long chip_id;
-
- wait_queue_head_t lowpower_mode_wait_queue;
-
+ ULONG ulCurrentTargetBuffer;
+ ULONG ulTotalTargetBuffersAvailable;
+ unsigned long chip_id;
+ wait_queue_head_t lowpower_mode_wait_queue;
BOOLEAN bFlashBoot;
BOOLEAN bBinDownloaded;
BOOLEAN bCfgDownloaded;
BOOLEAN bSyncUpRequestSent;
USHORT usBestEffortQueueIndex;
-
- wait_queue_head_t ioctl_fw_dnld_wait_queue;
- BOOLEAN waiting_to_fw_download_done;
- pid_t fw_download_process_pid;
+ wait_queue_head_t ioctl_fw_dnld_wait_queue;
+ BOOLEAN waiting_to_fw_download_done;
+ pid_t fw_download_process_pid;
PSTARGETPARAMS pstargetparams;
- BOOLEAN device_removed;
- BOOLEAN DeviceAccess;
- BOOLEAN bIsAutoCorrectEnabled;
- BOOLEAN bDDRInitDone;
- INT DDRSetting;
- ULONG ulPowerSaveMode;
- spinlock_t txtransmitlock;
- B_UINT8 txtransmit_running;
+ BOOLEAN device_removed;
+ BOOLEAN DeviceAccess;
+ BOOLEAN bIsAutoCorrectEnabled;
+ BOOLEAN bDDRInitDone;
+ int DDRSetting;
+ ULONG ulPowerSaveMode;
+ spinlock_t txtransmitlock;
+ B_UINT8 txtransmit_running;
/* Thread for control packet handling */
- struct task_struct *control_packet_handler;
+ struct task_struct *control_packet_handler;
/* thread for transmitting packets. */
- struct task_struct *transmit_packet_thread;
+ struct task_struct *transmit_packet_thread;
/* LED Related Structures */
LED_INFO_STRUCT LEDInfo;
@@ -482,39 +438,38 @@ struct _MINI_ADAPTER
/* Driver State for LED Blinking */
LedEventInfo_t DriverState;
/* Interface Specific */
- PVOID pvInterfaceAdapter;
- int (*bcm_file_download)( PVOID,
- struct file *,
- unsigned int);
- int (*bcm_file_readback_from_chip)( PVOID,
- struct file *,
- unsigned int);
- INT (*interface_rdm)(PVOID,
- UINT ,
- PVOID ,
- INT);
- INT (*interface_wrm)(PVOID,
- UINT ,
- PVOID ,
- INT);
+ PVOID pvInterfaceAdapter;
+ int (*bcm_file_download)(PVOID,
+ struct file *,
+ unsigned int);
+ int (*bcm_file_readback_from_chip)(PVOID,
+ struct file *,
+ unsigned int);
+ int (*interface_rdm)(PVOID,
+ UINT,
+ PVOID,
+ int);
+ int (*interface_wrm)(PVOID,
+ UINT,
+ PVOID,
+ int);
int (*interface_transmit)(PVOID, PVOID , UINT);
BOOLEAN IdleMode;
BOOLEAN bDregRequestSentInIdleMode;
BOOLEAN bTriedToWakeUpFromlowPowerMode;
BOOLEAN bShutStatus;
BOOLEAN bWakeUpDevice;
- unsigned int usIdleModePattern;
- //BOOLEAN bTriedToWakeUpFromShutdown;
+ unsigned int usIdleModePattern;
+ /* BOOLEAN bTriedToWakeUpFromShutdown; */
BOOLEAN bLinkDownRequested;
-
- int downloadDDR;
- PHS_DEVICE_EXTENSION stBCMPhsContext;
- S_HDR_SUPRESSION_CONTEXTINFO stPhsTxContextInfo;
+ int downloadDDR;
+ PHS_DEVICE_EXTENSION stBCMPhsContext;
+ S_HDR_SUPRESSION_CONTEXTINFO stPhsTxContextInfo;
uint8_t ucaPHSPktRestoreBuf[2048];
uint8_t bPHSEnabled;
BOOLEAN AutoFirmDld;
- BOOLEAN bMipsConfig;
- BOOLEAN bDPLLConfig;
+ BOOLEAN bMipsConfig;
+ BOOLEAN bDPLLConfig;
UINT32 aTxPktSizeHist[MIBS_MAX_HIST_ENTRIES];
UINT32 aRxPktSizeHist[MIBS_MAX_HIST_ENTRIES];
S_FRAGMENTED_PACKET_INFO astFragmentedPktClassifierTable[MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES];
@@ -527,108 +482,101 @@ struct _MINI_ADAPTER
BOOLEAN bStatusWrite;
UINT uiNVMDSDSize;
UINT uiVendorExtnFlag;
- //it will always represent chosen DSD at any point of time.
- // Generally it is Active DSD but in case of NVM RD/WR it might be different.
+ /* it will always represent chosen DSD at any point of time.
+ * Generally it is Active DSD but in case of NVM RD/WR it might be different.
+ */
UINT ulFlashCalStart;
- ULONG ulFlashControlSectionStart;
- ULONG ulFlashWriteSize;
- ULONG ulFlashID;
- FP_FLASH_WRITE fpFlashWrite;
- FP_FLASH_WRITE_STATUS fpFlashWriteWithStatusCheck;
-
+ ULONG ulFlashControlSectionStart;
+ ULONG ulFlashWriteSize;
+ ULONG ulFlashID;
+ FP_FLASH_WRITE fpFlashWrite;
+ FP_FLASH_WRITE_STATUS fpFlashWriteWithStatusCheck;
struct semaphore NVMRdmWrmLock;
+ struct device *pstCreatedClassDevice;
- struct device *pstCreatedClassDevice;
-
-// BOOLEAN InterfaceUpStatus;
- PFLASH2X_CS_INFO psFlash2xCSInfo;
- PFLASH_CS_INFO psFlashCSInfo ;
+ /* BOOLEAN InterfaceUpStatus; */
+ PFLASH2X_CS_INFO psFlash2xCSInfo;
+ PFLASH_CS_INFO psFlashCSInfo;
PFLASH2X_VENDORSPECIFIC_INFO psFlash2xVendorInfo;
- UINT uiFlashBaseAdd; //Flash start address
- UINT uiActiveISOOffset; //Active ISO offset chosen before f/w download
- FLASH2X_SECTION_VAL eActiveISO; //Active ISO section val
- FLASH2X_SECTION_VAL eActiveDSD; //Active DSD val chosen before f/w download
- UINT uiActiveDSDOffsetAtFwDld; //For accessing Active DSD chosen before f/w download
- UINT uiFlashLayoutMajorVersion ;
- UINT uiFlashLayoutMinorVersion;
- BOOLEAN bAllDSDWriteAllow ;
- BOOLEAN bSigCorrupted ;
- //this should be set who so ever want to change the Headers. after Wrtie it should be reset immediately.
- BOOLEAN bHeaderChangeAllowed ;
- INT SelectedChip ;
- BOOLEAN bEndPointHalted;
- //while bFlashRawRead will be true, Driver ignore map lay out and consider flash as of without any map.
- BOOLEAN bFlashRawRead;
- BOOLEAN bPreparingForLowPowerMode ;
- BOOLEAN bDoSuspend ;
- UINT syscfgBefFwDld ;
- BOOLEAN StopAllXaction ;
- UINT32 liTimeSinceLastNetEntry; //Used to Support extended CAPI requirements from
+ UINT uiFlashBaseAdd; /* Flash start address */
+ UINT uiActiveISOOffset; /* Active ISO offset chosen before f/w download */
+ FLASH2X_SECTION_VAL eActiveISO; /* Active ISO section val */
+ FLASH2X_SECTION_VAL eActiveDSD; /* Active DSD val chosen before f/w download */
+ UINT uiActiveDSDOffsetAtFwDld; /* For accessing Active DSD chosen before f/w download */
+ UINT uiFlashLayoutMajorVersion;
+ UINT uiFlashLayoutMinorVersion;
+ BOOLEAN bAllDSDWriteAllow;
+ BOOLEAN bSigCorrupted;
+ /* this should be set who so ever want to change the Headers. after Wrtie it should be reset immediately. */
+ BOOLEAN bHeaderChangeAllowed;
+ int SelectedChip;
+ BOOLEAN bEndPointHalted;
+ /* while bFlashRawRead will be true, Driver ignore map lay out and consider flash as of without any map. */
+ BOOLEAN bFlashRawRead;
+ BOOLEAN bPreparingForLowPowerMode;
+ BOOLEAN bDoSuspend;
+ UINT syscfgBefFwDld;
+ BOOLEAN StopAllXaction;
+ UINT32 liTimeSinceLastNetEntry; /* Used to Support extended CAPI requirements from */
struct semaphore LowPowerModeSync;
- ULONG liDrainCalculated;
- UINT gpioBitMap;
-
- S_BCM_DEBUG_STATE stDebugState;
-
+ ULONG liDrainCalculated;
+ UINT gpioBitMap;
+ S_BCM_DEBUG_STATE stDebugState;
};
typedef struct _MINI_ADAPTER MINI_ADAPTER, *PMINI_ADAPTER;
-#define GET_BCM_ADAPTER(net_dev) netdev_priv(net_dev)
+#define GET_BCM_ADAPTER(net_dev) netdev_priv(net_dev)
struct _ETH_HEADER_STRUC {
- UCHAR au8DestinationAddress[6];
- UCHAR au8SourceAddress[6];
- USHORT u16Etype;
-}__attribute__((packed));
+ UCHAR au8DestinationAddress[6];
+ UCHAR au8SourceAddress[6];
+ USHORT u16Etype;
+} __packed;
typedef struct _ETH_HEADER_STRUC ETH_HEADER_STRUC, *PETH_HEADER_STRUC;
+typedef struct FirmwareInfo {
+ void __user *pvMappedFirmwareAddress;
+ ULONG u32FirmwareLength;
+ ULONG u32StartingAddress;
+} __packed FIRMWARE_INFO, *PFIRMWARE_INFO;
-typedef struct FirmwareInfo
-{
- void __user * pvMappedFirmwareAddress;
- ULONG u32FirmwareLength;
- ULONG u32StartingAddress;
-}__attribute__((packed)) FIRMWARE_INFO, *PFIRMWARE_INFO;
-
-// holds the value of net_device structure..
+/* holds the value of net_device structure.. */
extern struct net_device *gblpnetdev;
-typedef struct _cntl_pkt{
- PMINI_ADAPTER Adapter;
- PLEADER PLeader;
-}cntl_pkt;
+typedef struct _cntl_pkt {
+ PMINI_ADAPTER Adapter;
+ PLEADER PLeader;
+} cntl_pkt;
typedef LINK_REQUEST CONTROL_MESSAGE;
-typedef struct _DDR_SETTING
-{
+typedef struct _DDR_SETTING {
UINT ulRegAddress;
UINT ulRegValue;
-}DDR_SETTING, *PDDR_SETTING;
+} DDR_SETTING, *PDDR_SETTING;
typedef DDR_SETTING DDR_SET_NODE, *PDDR_SET_NODE;
-INT
-InitAdapter(PMINI_ADAPTER psAdapter);
-
-// =====================================================================
-// Beceem vendor request codes for EP0
-// =====================================================================
+int InitAdapter(PMINI_ADAPTER psAdapter);
-#define BCM_REQUEST_READ 0x2
-#define BCM_REQUEST_WRITE 0x1
-#define EP2_MPS_REG 0x0F0110A0
-#define EP2_MPS 0x40
+/* =====================================================================
+ * Beceem vendor request codes for EP0
+ * =====================================================================
+ */
-#define EP2_CFG_REG 0x0F0110A8
-#define EP2_CFG_INT 0x27
-#define EP2_CFG_BULK 0x25
+#define BCM_REQUEST_READ 0x2
+#define BCM_REQUEST_WRITE 0x1
+#define EP2_MPS_REG 0x0F0110A0
+#define EP2_MPS 0x40
-#define EP4_MPS_REG 0x0F0110F0
-#define EP4_MPS 0x8C
+#define EP2_CFG_REG 0x0F0110A8
+#define EP2_CFG_INT 0x27
+#define EP2_CFG_BULK 0x25
-#define EP4_CFG_REG 0x0F0110F8
+#define EP4_MPS_REG 0x0F0110F0
+#define EP4_MPS 0x8C
-#define ISO_MPS_REG 0x0F0110C8
-#define ISO_MPS 0x00000000
+#define EP4_CFG_REG 0x0F0110F8
+#define ISO_MPS_REG 0x0F0110C8
+#define ISO_MPS 0x00000000
#define EP1 0
#define EP2 1
@@ -637,12 +585,9 @@ InitAdapter(PMINI_ADAPTER psAdapter);
#define EP5 4
#define EP6 5
-
-typedef enum eInterface_setting
-{
+typedef enum eInterface_setting {
DEFAULT_SETTING_0 = 0,
ALTERNATE_SETTING_1 = 1,
-}INTERFACE_SETTING;
-
-#endif //__ADAPTER_H__
+} INTERFACE_SETTING;
+#endif /* __ADAPTER_H__ */
diff --git a/drivers/staging/bcm/DDRInit.c b/drivers/staging/bcm/DDRInit.c
index 1c7db81a1ee8..2b46f4d4ef0e 100644
--- a/drivers/staging/bcm/DDRInit.c
+++ b/drivers/staging/bcm/DDRInit.c
@@ -1115,20 +1115,20 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
{
case DDR_80_MHZ:
psDDRSetting = asT3LP_DDRSetting80MHz;
- RegCount = (sizeof(asT3LP_DDRSetting80MHz)/sizeof(DDR_SET_NODE));
+ RegCount = ARRAY_SIZE(asT3LP_DDRSetting80MHz);
RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ;
psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
break;
case DDR_100_MHZ:
psDDRSetting = asT3LP_DDRSetting100MHz;
- RegCount = (sizeof(asT3LP_DDRSetting100MHz)/sizeof(DDR_SET_NODE));
+ RegCount = ARRAY_SIZE(asT3LP_DDRSetting100MHz);
RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ;
psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
break;
case DDR_133_MHZ:
bOverrideSelfRefresh = TRUE;
psDDRSetting = asT3LP_DDRSetting133MHz;
- RegCount = (sizeof(asT3LP_DDRSetting133MHz)/sizeof(DDR_SET_NODE));
+ RegCount = ARRAY_SIZE(asT3LP_DDRSetting133MHz);
RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
break;
@@ -1146,20 +1146,20 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
{
case DDR_80_MHZ:
psDDRSetting = asT3LPB_DDRSetting80MHz;
- RegCount=(sizeof(asT3LPB_DDRSetting80MHz)/sizeof(DDR_SET_NODE));
+ RegCount=ARRAY_SIZE(asT3LPB_DDRSetting80MHz);
RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ;
psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
break;
case DDR_100_MHZ:
psDDRSetting = asT3LPB_DDRSetting100MHz;
- RegCount = (sizeof(asT3LPB_DDRSetting100MHz)/sizeof(DDR_SET_NODE));
+ RegCount = ARRAY_SIZE(asT3LPB_DDRSetting100MHz);
RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ;
psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
break;
case DDR_133_MHZ:
bOverrideSelfRefresh = TRUE;
psDDRSetting = asT3LPB_DDRSetting133MHz;
- RegCount = (sizeof(asT3LPB_DDRSetting133MHz)/sizeof(DDR_SET_NODE));
+ RegCount = ARRAY_SIZE(asT3LPB_DDRSetting133MHz);
RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
break;
@@ -1167,7 +1167,7 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
case DDR_160_MHZ:
bOverrideSelfRefresh = TRUE;
psDDRSetting = asT3LPB_DDRSetting160MHz;
- RegCount = sizeof(asT3LPB_DDRSetting160MHz)/sizeof(DDR_SET_NODE);
+ RegCount = ARRAY_SIZE(asT3LPB_DDRSetting160MHz);
RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ;
psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ;
@@ -1181,19 +1181,19 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
{
case DDR_80_MHZ:
psDDRSetting = asT3_DDRSetting80MHz;
- RegCount = (sizeof(asT3_DDRSetting80MHz)/sizeof(DDR_SET_NODE));
+ RegCount = ARRAY_SIZE(asT3_DDRSetting80MHz);
RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ;
psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
break;
case DDR_100_MHZ:
psDDRSetting = asT3_DDRSetting100MHz;
- RegCount = (sizeof(asT3_DDRSetting100MHz)/sizeof(DDR_SET_NODE));
+ RegCount = ARRAY_SIZE(asT3_DDRSetting100MHz);
RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ;
psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
break;
case DDR_133_MHZ:
psDDRSetting = asT3_DDRSetting133MHz;
- RegCount = (sizeof(asT3_DDRSetting133MHz)/sizeof(DDR_SET_NODE));
+ RegCount = ARRAY_SIZE(asT3_DDRSetting133MHz);
RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
break;
@@ -1207,20 +1207,20 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
{
case DDR_80_MHZ:
psDDRSetting = asT3B_DDRSetting80MHz;
- RegCount = (sizeof(asT3B_DDRSetting80MHz)/sizeof(DDR_SET_NODE));
+ RegCount = ARRAY_SIZE(asT3B_DDRSetting80MHz);
RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ;
psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
break;
case DDR_100_MHZ:
psDDRSetting = asT3B_DDRSetting100MHz;
- RegCount = (sizeof(asT3B_DDRSetting100MHz)/sizeof(DDR_SET_NODE));
+ RegCount = ARRAY_SIZE(asT3B_DDRSetting100MHz);
RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ;
psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
break;
case DDR_133_MHZ:
bOverrideSelfRefresh = TRUE;
psDDRSetting = asT3B_DDRSetting133MHz;
- RegCount = (sizeof(asT3B_DDRSetting133MHz)/sizeof(DDR_SET_NODE));
+ RegCount = ARRAY_SIZE(asT3B_DDRSetting133MHz);
RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
break;
diff --git a/drivers/staging/bcm/IPv6Protocol.c b/drivers/staging/bcm/IPv6Protocol.c
index 5b4fd372ec36..1da21642c18e 100644
--- a/drivers/staging/bcm/IPv6Protocol.c
+++ b/drivers/staging/bcm/IPv6Protocol.c
@@ -1,51 +1,52 @@
#include "headers.h"
-static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header);
-static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header);
+static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,
+ IPV6Header *pstIpv6Header);
+static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,
+ IPV6Header *pstIpv6Header);
static VOID DumpIpv6Header(IPV6Header *pstIpv6Header);
-static UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader,BOOLEAN *bParseDone,USHORT *pusPayloadLength)
+static UCHAR *GetNextIPV6ChainedHeader(UCHAR **ppucPayload,
+ UCHAR *pucNextHeader, BOOLEAN *bParseDone, USHORT *pusPayloadLength)
{
UCHAR *pucRetHeaderPtr = NULL;
UCHAR *pucPayloadPtr = NULL;
USHORT usNextHeaderOffset = 0 ;
- PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
- if((NULL == ppucPayload) || (*pusPayloadLength == 0) || (*bParseDone))
- {
+ if ((ppucPayload == NULL) || (*pusPayloadLength == 0) ||
+ (*bParseDone)) {
*bParseDone = TRUE;
return NULL;
-
}
pucRetHeaderPtr = *ppucPayload;
pucPayloadPtr = *ppucPayload;
- if(!pucRetHeaderPtr || !pucPayloadPtr)
- {
+ if (!pucRetHeaderPtr || !pucPayloadPtr) {
*bParseDone = TRUE;
return NULL;
}
- //Get the Nextt Header Type
+ /* Get the Nextt Header Type */
*bParseDone = FALSE;
-
- switch(*pucNextHeader)
- {
+ switch (*pucNextHeader) {
case IPV6HDR_TYPE_HOPBYHOP:
{
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 HopByHop Header");
- usNextHeaderOffset+=sizeof(IPV6HopByHopOptionsHeader);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 HopByHop Header");
+ usNextHeaderOffset += sizeof(IPV6HopByHopOptionsHeader);
}
break;
case IPV6HDR_TYPE_ROUTING:
{
IPV6RoutingHeader *pstIpv6RoutingHeader;
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Routing Header");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 Routing Header");
pstIpv6RoutingHeader = (IPV6RoutingHeader *)pucPayloadPtr;
usNextHeaderOffset += sizeof(IPV6RoutingHeader);
usNextHeaderOffset += pstIpv6RoutingHeader->ucNumAddresses * IPV6_ADDRESS_SIZEINBYTES;
@@ -54,8 +55,10 @@ static UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader
break;
case IPV6HDR_TYPE_FRAGMENTATION:
{
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Fragmentation Header");
- usNextHeaderOffset+= sizeof(IPV6FragmentHeader);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "\nIPv6 Fragmentation Header");
+ usNextHeaderOffset += sizeof(IPV6FragmentHeader);
}
break;
@@ -63,9 +66,11 @@ static UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader
{
IPV6DestOptionsHeader *pstIpv6DestOptsHdr = (IPV6DestOptionsHeader *)pucPayloadPtr;
int nTotalOptions = pstIpv6DestOptsHdr->ucHdrExtLen;
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 DestOpts Header Header");
- usNextHeaderOffset+= sizeof(IPV6DestOptionsHeader);
- usNextHeaderOffset+= nTotalOptions * IPV6_DESTOPTS_HDR_OPTIONSIZE ;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "\nIPv6 DestOpts Header Header");
+ usNextHeaderOffset += sizeof(IPV6DestOptionsHeader);
+ usNextHeaderOffset += nTotalOptions * IPV6_DESTOPTS_HDR_OPTIONSIZE ;
}
break;
@@ -73,36 +78,43 @@ static UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader
{
IPV6AuthenticationHeader *pstIpv6AuthHdr = (IPV6AuthenticationHeader *)pucPayloadPtr;
int nHdrLen = pstIpv6AuthHdr->ucLength;
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Authentication Header");
- usNextHeaderOffset+= nHdrLen * 4;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "\nIPv6 Authentication Header");
+ usNextHeaderOffset += nHdrLen * 4;
}
break;
case IPV6HDR_TYPE_ENCRYPTEDSECURITYPAYLOAD:
{
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Encrypted Security Payload Header");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "\nIPv6 Encrypted Security Payload Header");
*bParseDone = TRUE;
}
break;
case IPV6_ICMP_HDR_TYPE:
{
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " ICMP Header");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nICMP Header");
*bParseDone = TRUE;
}
break;
case TCP_HEADER_TYPE:
{
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nTCP Header");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nTCP Header");
*bParseDone = TRUE;
}
break;
case UDP_HEADER_TYPE:
{
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nUDP Header");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nUDP Header");
*bParseDone = TRUE;
}
break;
- default :
+ default:
{
*bParseDone = TRUE;
@@ -112,53 +124,49 @@ static UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader
}
- if(*bParseDone == FALSE)
- {
- if(*pusPayloadLength <= usNextHeaderOffset)
- {
+ if (*bParseDone == FALSE) {
+ if (*pusPayloadLength <= usNextHeaderOffset) {
*bParseDone = TRUE;
- }
- else
- {
+ } else {
*pucNextHeader = *pucPayloadPtr;
- pucPayloadPtr+=usNextHeaderOffset;
- (*pusPayloadLength)-=usNextHeaderOffset;
+ pucPayloadPtr += usNextHeaderOffset;
+ (*pusPayloadLength) -= usNextHeaderOffset;
}
}
-
-
*ppucPayload = pucPayloadPtr;
return pucRetHeaderPtr;
}
-static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload,USHORT *pusSrcPort,USHORT *pusDestPort,USHORT usPayloadLength,UCHAR ucNextHeader)
+static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload, USHORT *pusSrcPort,
+ USHORT *pusDestPort, USHORT usPayloadLength, UCHAR ucNextHeader)
{
UCHAR *pIpv6HdrScanContext = pucPayload;
BOOLEAN bDone = FALSE;
- UCHAR ucHeaderType =0;
+ UCHAR ucHeaderType = 0;
UCHAR *pucNextHeader = NULL;
- PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
- if( !pucPayload || (usPayloadLength == 0))
- {
+ if (!pucPayload || (usPayloadLength == 0))
return 0;
- }
*pusSrcPort = *pusDestPort = 0;
ucHeaderType = ucNextHeader;
- while(!bDone)
- {
- pucNextHeader = GetNextIPV6ChainedHeader(&pIpv6HdrScanContext,&ucHeaderType,&bDone,&usPayloadLength);
- if(bDone)
- {
- if((ucHeaderType==TCP_HEADER_TYPE) || (ucHeaderType == UDP_HEADER_TYPE))
- {
- *pusSrcPort=*((PUSHORT)(pucNextHeader));
- *pusDestPort=*((PUSHORT)(pucNextHeader+2));
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nProtocol Ports - Src Port :0x%x Dest Port : 0x%x",ntohs(*pusSrcPort),ntohs(*pusDestPort));
+ while (!bDone) {
+ pucNextHeader = GetNextIPV6ChainedHeader(&pIpv6HdrScanContext,
+ &ucHeaderType, &bDone, &usPayloadLength);
+ if (bDone) {
+ if ((ucHeaderType == TCP_HEADER_TYPE) ||
+ (ucHeaderType == UDP_HEADER_TYPE)) {
+ *pusSrcPort = *((PUSHORT)(pucNextHeader));
+ *pusDestPort = *((PUSHORT)(pucNextHeader+2));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "\nProtocol Ports - Src Port :0x%x Dest Port : 0x%x",
+ ntohs(*pusSrcPort),
+ ntohs(*pusDestPort));
}
break;
@@ -168,92 +176,111 @@ static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload,USHORT *pusSrcPort,USHORT *p
}
-
-USHORT IpVersion6(PMINI_ADAPTER Adapter, /**< Pointer to the driver control structure */
- PVOID pcIpHeader, /**<Pointer to the IP Hdr of the packet*/
- S_CLASSIFIER_RULE *pstClassifierRule )
+/*
+ * Arg 1 PMINI_ADAPTER Adapter is a pointer ot the driver contorl structure
+ * Arg 2 PVOID pcIpHeader is a pointer to the IP header of the packet
+ */
+USHORT IpVersion6(PMINI_ADAPTER Adapter, PVOID pcIpHeader,
+ S_CLASSIFIER_RULE *pstClassifierRule)
{
USHORT ushDestPort = 0;
USHORT ushSrcPort = 0;
- UCHAR ucNextProtocolAboveIP =0;
+ UCHAR ucNextProtocolAboveIP = 0;
IPV6Header *pstIpv6Header = NULL;
BOOLEAN bClassificationSucceed = FALSE;
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "IpVersion6 ==========>\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "IpVersion6 ==========>\n");
pstIpv6Header = (IPV6Header *)pcIpHeader;
DumpIpv6Header(pstIpv6Header);
- //Try to get the next higher layer protocol and the Ports Nos if TCP or UDP
+ /*
+ * Try to get the next higher layer protocol
+ * and the Ports Nos if TCP or UDP
+ */
ucNextProtocolAboveIP = GetIpv6ProtocolPorts((UCHAR *)(pcIpHeader + sizeof(IPV6Header)),
&ushSrcPort,
&ushDestPort,
pstIpv6Header->usPayloadLength,
pstIpv6Header->ucNextHeader);
- do
- {
- if(0 == pstClassifierRule->ucDirection)
- {
- //cannot be processed for classification.
- // it is a down link connection
+ do {
+ if (pstClassifierRule->ucDirection == 0) {
+ /*
+ * cannot be processed for classification.
+ * it is a down link connection
+ */
break;
}
- if(!pstClassifierRule->bIpv6Protocol)
- {
- //We are looking for Ipv6 Classifiers . Lets ignore this classifier and try the next one.
+ if (!pstClassifierRule->bIpv6Protocol) {
+ /*
+ * We are looking for Ipv6 Classifiers
+ * Lets ignore this classifier and try the next one
+ */
break;
}
- bClassificationSucceed=MatchSrcIpv6Address(pstClassifierRule,pstIpv6Header);
- if(!bClassificationSucceed)
- break;
+ bClassificationSucceed = MatchSrcIpv6Address(pstClassifierRule,
+ pstIpv6Header);
+ if (!bClassificationSucceed)
+ break;
- bClassificationSucceed=MatchDestIpv6Address(pstClassifierRule,pstIpv6Header);
- if(!bClassificationSucceed)
- break;
+ bClassificationSucceed = MatchDestIpv6Address(pstClassifierRule,
+ pstIpv6Header);
+ if (!bClassificationSucceed)
+ break;
- //Match the protocol type.For IPv6 the next protocol at end of Chain of IPv6 prot headers
- bClassificationSucceed=MatchProtocol(pstClassifierRule,ucNextProtocolAboveIP);
- if(!bClassificationSucceed)
- break;
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Protocol Matched");
+ /*
+ * Match the protocol type.
+ * For IPv6 the next protocol at end of
+ * Chain of IPv6 prot headers
+ */
+ bClassificationSucceed = MatchProtocol(pstClassifierRule,
+ ucNextProtocolAboveIP);
+ if (!bClassificationSucceed)
+ break;
- if((ucNextProtocolAboveIP == TCP_HEADER_TYPE) || (ucNextProtocolAboveIP == UDP_HEADER_TYPE))
- {
- //Match Src Port
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Source Port:%x\n",ntohs(ushSrcPort));
- bClassificationSucceed=MatchSrcPort(pstClassifierRule,ntohs(ushSrcPort));
- if(!bClassificationSucceed)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 Protocol Matched");
+
+ if ((ucNextProtocolAboveIP == TCP_HEADER_TYPE) ||
+ (ucNextProtocolAboveIP == UDP_HEADER_TYPE)) {
+ /* Match Src Port */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 Source Port:%x\n",
+ ntohs(ushSrcPort));
+ bClassificationSucceed = MatchSrcPort(pstClassifierRule,
+ ntohs(ushSrcPort));
+ if (!bClassificationSucceed)
break;
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Src Port Matched");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 Src Port Matched");
- //Match Dest Port
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Destination Port:%x\n",ntohs(ushDestPort));
- bClassificationSucceed=MatchDestPort(pstClassifierRule,ntohs(ushDestPort));
- if(!bClassificationSucceed)
+ /* Match Dest Port */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 Destination Port:%x\n",
+ ntohs(ushDestPort));
+ bClassificationSucceed = MatchDestPort(pstClassifierRule,
+ ntohs(ushDestPort));
+ if (!bClassificationSucceed)
break;
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Dest Port Matched");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 Dest Port Matched");
}
- }while(0);
+ } while (0);
- if(TRUE==bClassificationSucceed)
- {
+ if (bClassificationSucceed == TRUE) {
INT iMatchedSFQueueIndex = 0;
- iMatchedSFQueueIndex = SearchSfid(Adapter,pstClassifierRule->ulSFID);
- if(iMatchedSFQueueIndex >= NO_OF_QUEUES)
- {
+ iMatchedSFQueueIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
+ if (iMatchedSFQueueIndex >= NO_OF_QUEUES) {
bClassificationSucceed = FALSE;
- }
- else
- {
- if(FALSE == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
- {
+ } else {
+ if (Adapter->PackInfo[iMatchedSFQueueIndex].bActive == FALSE)
bClassificationSucceed = FALSE;
- }
}
}
@@ -261,52 +288,55 @@ USHORT IpVersion6(PMINI_ADAPTER Adapter, /**< Pointer to the driver control stru
}
-static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header)
+static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,
+ IPV6Header *pstIpv6Header)
{
- UINT uiLoopIndex=0;
- UINT uiIpv6AddIndex=0;
- UINT uiIpv6AddrNoLongWords = 4;
+ UINT uiLoopIndex = 0;
+ UINT uiIpv6AddIndex = 0;
+ UINT uiIpv6AddrNoLongWords = 4;
ULONG aulSrcIP[4];
- PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
/*
- //This is the no. of Src Addresses ie Range of IP Addresses contained
- //in the classifier rule for which we need to match
- */
+ * This is the no. of Src Addresses ie Range of IP Addresses contained
+ * in the classifier rule for which we need to match
+ */
UINT uiCountIPSrcAddresses = (UINT)pstClassifierRule->ucIPSourceAddressLength;
- if(0 == uiCountIPSrcAddresses)
+ if (uiCountIPSrcAddresses == 0)
return TRUE;
- //First Convert the Ip Address in the packet to Host Endian order
- for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
- {
- aulSrcIP[uiIpv6AddIndex]=ntohl(pstIpv6Header->ulSrcIpAddress[uiIpv6AddIndex]);
- }
+ /* First Convert the Ip Address in the packet to Host Endian order */
+ for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++)
+ aulSrcIP[uiIpv6AddIndex] = ntohl(pstIpv6Header->ulSrcIpAddress[uiIpv6AddIndex]);
- for(uiLoopIndex=0;uiLoopIndex<uiCountIPSrcAddresses;uiLoopIndex+=uiIpv6AddrNoLongWords)
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Address In Received Packet : \n ");
+ for (uiLoopIndex = 0; uiLoopIndex < uiCountIPSrcAddresses; uiLoopIndex += uiIpv6AddrNoLongWords) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "\n Src Ipv6 Address In Received Packet :\n ");
DumpIpv6Address(aulSrcIP);
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Mask In Classifier Rule: \n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "\n Src Ipv6 Mask In Classifier Rule:\n");
DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex]);
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Address In Classifier Rule : \n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "\n Src Ipv6 Address In Classifier Rule :\n");
DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex]);
- for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
- {
- if((pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulSrcIP[uiIpv6AddIndex])
- != pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex])
- {
- //Match failed for current Ipv6 Address.Try next Ipv6 Address
+ for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
+ if ((pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulSrcIP[uiIpv6AddIndex])
+ != pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
+ /*
+ * Match failed for current Ipv6 Address
+ * Try next Ipv6 Address
+ */
break;
}
- if(uiIpv6AddIndex == uiIpv6AddrNoLongWords-1)
- {
- //Match Found
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Ipv6 Src Ip Address Matched\n");
+ if (uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) {
+ /* Match Found */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "Ipv6 Src Ip Address Matched\n");
return TRUE;
}
}
@@ -314,52 +344,56 @@ static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Head
return FALSE;
}
-static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header)
+static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,
+ IPV6Header *pstIpv6Header)
{
- UINT uiLoopIndex=0;
- UINT uiIpv6AddIndex=0;
- UINT uiIpv6AddrNoLongWords = 4;
+ UINT uiLoopIndex = 0;
+ UINT uiIpv6AddIndex = 0;
+ UINT uiIpv6AddrNoLongWords = 4;
ULONG aulDestIP[4];
- PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
/*
- //This is the no. of Destination Addresses ie Range of IP Addresses contained
- //in the classifier rule for which we need to match
- */
+ * This is the no. of Destination Addresses
+ * ie Range of IP Addresses contained in the classifier rule
+ * for which we need to match
+ */
UINT uiCountIPDestinationAddresses = (UINT)pstClassifierRule->ucIPDestinationAddressLength;
- if(0 == uiCountIPDestinationAddresses)
+ if (uiCountIPDestinationAddresses == 0)
return TRUE;
- //First Convert the Ip Address in the packet to Host Endian order
- for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
- {
- aulDestIP[uiIpv6AddIndex]=ntohl(pstIpv6Header->ulDestIpAddress[uiIpv6AddIndex]);
- }
+ /* First Convert the Ip Address in the packet to Host Endian order */
+ for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++)
+ aulDestIP[uiIpv6AddIndex] = ntohl(pstIpv6Header->ulDestIpAddress[uiIpv6AddIndex]);
- for(uiLoopIndex=0;uiLoopIndex<uiCountIPDestinationAddresses;uiLoopIndex+=uiIpv6AddrNoLongWords)
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Address In Received Packet : \n ");
+ for (uiLoopIndex = 0; uiLoopIndex < uiCountIPDestinationAddresses; uiLoopIndex += uiIpv6AddrNoLongWords) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "\n Destination Ipv6 Address In Received Packet :\n ");
DumpIpv6Address(aulDestIP);
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Mask In Classifier Rule: \n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "\n Destination Ipv6 Mask In Classifier Rule :\n");
DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex]);
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Address In Classifier Rule : \n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "\n Destination Ipv6 Address In Classifier Rule :\n");
DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex]);
- for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
- {
- if((pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulDestIP[uiIpv6AddIndex])
- != pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex])
- {
- //Match failed for current Ipv6 Address.Try next Ipv6 Address
+ for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
+ if ((pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulDestIP[uiIpv6AddIndex])
+ != pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
+ /*
+ * Match failed for current Ipv6 Address.
+ * Try next Ipv6 Address
+ */
break;
}
- if(uiIpv6AddIndex == uiIpv6AddrNoLongWords-1)
- {
- //Match Found
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Ipv6 Destination Ip Address Matched\n");
+ if (uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) {
+ /* Match Found */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "Ipv6 Destination Ip Address Matched\n");
return TRUE;
}
}
@@ -371,11 +405,11 @@ static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Hea
VOID DumpIpv6Address(ULONG *puIpv6Address)
{
UINT uiIpv6AddrNoLongWords = 4;
- UINT uiIpv6AddIndex=0;
- PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
- for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, ":%lx",puIpv6Address[uiIpv6AddIndex]);
+ UINT uiIpv6AddIndex = 0;
+ PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ ":%lx", puIpv6Address[uiIpv6AddIndex]);
}
}
@@ -383,22 +417,35 @@ VOID DumpIpv6Address(ULONG *puIpv6Address)
static VOID DumpIpv6Header(IPV6Header *pstIpv6Header)
{
UCHAR ucVersion;
- UCHAR ucPrio ;
- PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "----Ipv6 Header---");
+ UCHAR ucPrio;
+ PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "----Ipv6 Header---");
ucVersion = pstIpv6Header->ucVersionPrio & 0xf0;
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Version : %x \n",ucVersion);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Version : %x\n", ucVersion);
ucPrio = pstIpv6Header->ucVersionPrio & 0x0f;
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Priority : %x \n",ucPrio);
- //BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Flow Label : %x \n",(pstIpv6Header->ucVersionPrio &0xf0);
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Payload Length : %x \n",ntohs(pstIpv6Header->usPayloadLength));
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Next Header : %x \n",pstIpv6Header->ucNextHeader);
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Hop Limit : %x \n",pstIpv6Header->ucHopLimit);
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Src Address :\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Priority : %x\n", ucPrio);
+ /*
+ * BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ * "Flow Label : %x\n",(pstIpv6Header->ucVersionPrio &0xf0);
+ */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Payload Length : %x\n",
+ ntohs(pstIpv6Header->usPayloadLength));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Next Header : %x\n", pstIpv6Header->ucNextHeader);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Hop Limit : %x\n", pstIpv6Header->ucHopLimit);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Src Address :\n");
DumpIpv6Address(pstIpv6Header->ulSrcIpAddress);
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Dest Address :\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Dest Address :\n");
DumpIpv6Address(pstIpv6Header->ulDestIpAddress);
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "----Ipv6 Header End---");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "----Ipv6 Header End---");
}
diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c
index c7725e141fd5..8223a6913fc5 100644
--- a/drivers/staging/bcm/Misc.c
+++ b/drivers/staging/bcm/Misc.c
@@ -835,7 +835,7 @@ int reset_card_proc(PMINI_ADAPTER ps_adapter)
Bcm_kill_all_URBs(psIntfAdapter);
/* Reset the UMA-B Device */
if (ps_adapter->chip_id >= T3LPB) {
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reseting UMA-B\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Resetting UMA-B\n");
retval = usb_reset_device(psIntfAdapter->udev);
psIntfAdapter->psAdapter->StopAllXaction = FALSE;
diff --git a/drivers/staging/ccg/Kconfig b/drivers/staging/ccg/Kconfig
new file mode 100644
index 000000000000..ff05e52392bf
--- /dev/null
+++ b/drivers/staging/ccg/Kconfig
@@ -0,0 +1,20 @@
+if USB_GADGET
+
+config USB_G_CCG
+ tristate "Configurable Composite Gadget (STAGING)"
+ depends on STAGING && !USB_ZERO && !USB_ZERO_HNPTEST && !USB_AUDIO && !GADGET_UAC1 && !USB_ETH && !USB_ETH_RNDIS && !USB_ETH_EEM && !USB_G_NCM && !USB_GADGETFS && !USB_FUNCTIONFS && !USB_FUNCTIONFS_ETH && !USB_FUNCTIONFS_RNDIS && !USB_FUNCTIONFS_GENERIC && !USB_FILE_STORAGE && !USB_FILE_STORAGE_TEST && !USB_MASS_STORAGE && !USB_G_SERIAL && !USB_MIDI_GADGET && !USB_G_PRINTER && !USB_CDC_COMPOSITE && !USB_G_NOKIA && !USB_G_ACM_MS && !USB_G_MULTI && !USB_G_MULTI_RNDIS && !USB_G_MULTI_CDC && !USB_G_HID && !USB_G_DBGP && !USB_G_WEBCAM
+ help
+ The Configurable Composite Gadget supports multiple USB
+ functions: acm, mass storage, rndis and FunctionFS.
+ Each function can be configured and enabled/disabled
+ dynamically from userspace through a sysfs interface.
+
+ In order to compile this (either as a module or built-in),
+ "USB Gadget Drivers" and anything under it must not be
+ selected compiled-in in
+ Device Drivers->USB Support->USB Gadget Support.
+ However, you can say "M" there, if you do, the
+ Configurable Composite Gadget can be compiled "M" only
+ or not at all.
+
+endif # USB_GADGET
diff --git a/drivers/staging/ccg/Makefile b/drivers/staging/ccg/Makefile
new file mode 100644
index 000000000000..693da637a6d8
--- /dev/null
+++ b/drivers/staging/ccg/Makefile
@@ -0,0 +1,4 @@
+g_ccg-y := ccg.o
+ccflags-y += -Idrivers/usb/gadget
+
+obj-$(CONFIG_USB_G_CCG) += g_ccg.o
diff --git a/drivers/staging/ccg/TODO b/drivers/staging/ccg/TODO
new file mode 100644
index 000000000000..18612fe70171
--- /dev/null
+++ b/drivers/staging/ccg/TODO
@@ -0,0 +1,6 @@
+TODO:
+ - change configuration interface from sysfs to configfs
+
+Please send patches to Greg Kroah-Hartmann <gregkh@linuxfoundation.org>,
+Andrzej Pietrasiewicz <andrzej.p@samsung.com>, and
+Cc: Mike Lockwood <lockwood@android.com>
diff --git a/drivers/staging/ccg/ccg.c b/drivers/staging/ccg/ccg.c
new file mode 100644
index 000000000000..a5b36a97598d
--- /dev/null
+++ b/drivers/staging/ccg/ccg.c
@@ -0,0 +1,1299 @@
+/*
+ * Configurable Composite Gadget
+ *
+ * Initially contributed as "Android Composite Gdaget" by:
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.com>
+ * Benoit Goby <benoit@android.com>
+ *
+ * Tailoring it to become a generic Configurable Composite Gadget is
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+#include <linux/platform_device.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/composite.h>
+#include <linux/usb/gadget.h>
+
+#include "gadget_chips.h"
+
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module. So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "../../usb/gadget/usbstring.c"
+#include "../../usb/gadget/config.c"
+#include "../../usb/gadget/epautoconf.c"
+#include "../../usb/gadget/composite.c"
+
+#include "../../usb/gadget/f_mass_storage.c"
+#include "../../usb/gadget/u_serial.c"
+#include "../../usb/gadget/f_acm.c"
+#define USB_ETH_RNDIS y
+#include "../../usb/gadget/f_rndis.c"
+#include "../../usb/gadget/rndis.c"
+#include "../../usb/gadget/u_ether.c"
+#include "../../usb/gadget/f_fs.c"
+
+MODULE_AUTHOR("Mike Lockwood, Andrzej Pietrasiewicz");
+MODULE_DESCRIPTION("Configurable Composite USB Gadget");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+
+static const char longname[] = "Configurable Composite Gadget";
+
+/* Default vendor and product IDs, overridden by userspace */
+#define VENDOR_ID 0x1d6b /* Linux Foundation */
+#define PRODUCT_ID 0x0107
+#define GFS_MAX_DEVS 10
+
+struct ccg_usb_function {
+ char *name;
+ void *config;
+
+ struct device *dev;
+ char *dev_name;
+ struct device_attribute **attributes;
+
+ /* for ccg_dev.enabled_functions */
+ struct list_head enabled_list;
+
+ /* Optional: initialization during gadget bind */
+ int (*init)(struct ccg_usb_function *, struct usb_composite_dev *);
+ /* Optional: cleanup during gadget unbind */
+ void (*cleanup)(struct ccg_usb_function *);
+
+ int (*bind_config)(struct ccg_usb_function *,
+ struct usb_configuration *);
+
+ /* Optional: called when the configuration is removed */
+ void (*unbind_config)(struct ccg_usb_function *,
+ struct usb_configuration *);
+ /* Optional: handle ctrl requests before the device is configured */
+ int (*ctrlrequest)(struct ccg_usb_function *,
+ struct usb_composite_dev *,
+ const struct usb_ctrlrequest *);
+};
+
+struct ffs_obj {
+ const char *name;
+ bool mounted;
+ bool desc_ready;
+ bool used;
+ struct ffs_data *ffs_data;
+};
+
+struct ccg_dev {
+ struct ccg_usb_function **functions;
+ struct list_head enabled_functions;
+ struct usb_composite_dev *cdev;
+ struct device *dev;
+
+ bool enabled;
+ struct mutex mutex;
+ bool connected;
+ bool sw_connected;
+ struct work_struct work;
+
+ unsigned int max_func_num;
+ unsigned int func_num;
+ struct ffs_obj ffs_tab[GFS_MAX_DEVS];
+};
+
+static struct class *ccg_class;
+static struct ccg_dev *_ccg_dev;
+static int ccg_bind_config(struct usb_configuration *c);
+static void ccg_unbind_config(struct usb_configuration *c);
+
+static char func_names_buf[256];
+
+static struct usb_device_descriptor device_desc = {
+ .bLength = sizeof(device_desc),
+ .bDescriptorType = USB_DT_DEVICE,
+ .bcdUSB = __constant_cpu_to_le16(0x0200),
+ .bDeviceClass = USB_CLASS_PER_INTERFACE,
+ .idVendor = __constant_cpu_to_le16(VENDOR_ID),
+ .idProduct = __constant_cpu_to_le16(PRODUCT_ID),
+ .bcdDevice = __constant_cpu_to_le16(0xffff),
+ .bNumConfigurations = 1,
+};
+
+static struct usb_configuration ccg_config_driver = {
+ .label = "ccg",
+ .unbind = ccg_unbind_config,
+ .bConfigurationValue = 1,
+ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+ .bMaxPower = 0xFA, /* 500ma */
+};
+
+static void ccg_work(struct work_struct *data)
+{
+ struct ccg_dev *dev = container_of(data, struct ccg_dev, work);
+ struct usb_composite_dev *cdev = dev->cdev;
+ static char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL };
+ static char *connected[2] = { "USB_STATE=CONNECTED", NULL };
+ static char *configured[2] = { "USB_STATE=CONFIGURED", NULL };
+ char **uevent_envp = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cdev->lock, flags);
+ if (cdev->config)
+ uevent_envp = configured;
+ else if (dev->connected != dev->sw_connected)
+ uevent_envp = dev->connected ? connected : disconnected;
+ dev->sw_connected = dev->connected;
+ spin_unlock_irqrestore(&cdev->lock, flags);
+
+ if (uevent_envp) {
+ kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, uevent_envp);
+ pr_info("%s: sent uevent %s\n", __func__, uevent_envp[0]);
+ } else {
+ pr_info("%s: did not send uevent (%d %d %p)\n", __func__,
+ dev->connected, dev->sw_connected, cdev->config);
+ }
+}
+
+
+/*-------------------------------------------------------------------------*/
+/* Supported functions initialization */
+
+static struct ffs_obj *functionfs_find_dev(struct ccg_dev *dev,
+ const char *dev_name)
+{
+ int i;
+
+ for (i = 0; i < dev->max_func_num; i++)
+ if (strcmp(dev->ffs_tab[i].name, dev_name) == 0)
+ return &dev->ffs_tab[i];
+
+ return NULL;
+}
+
+static bool functionfs_all_ready(struct ccg_dev *dev)
+{
+ int i;
+
+ for (i = 0; i < dev->max_func_num; i++)
+ if (dev->ffs_tab[i].used && !dev->ffs_tab[i].desc_ready)
+ return false;
+
+ return true;
+}
+
+static int functionfs_ready_callback(struct ffs_data *ffs)
+{
+ struct ffs_obj *ffs_obj;
+ int ret;
+
+ mutex_lock(&_ccg_dev->mutex);
+
+ ffs_obj = ffs->private_data;
+ if (!ffs_obj) {
+ ret = -EINVAL;
+ goto done;
+ }
+ if (WARN_ON(ffs_obj->desc_ready)) {
+ ret = -EBUSY;
+ goto done;
+ }
+ ffs_obj->ffs_data = ffs;
+
+ if (functionfs_all_ready(_ccg_dev)) {
+ ret = -EBUSY;
+ goto done;
+ }
+ ffs_obj->desc_ready = true;
+
+done:
+ mutex_unlock(&_ccg_dev->mutex);
+ return ret;
+}
+
+static void reset_usb(struct ccg_dev *dev)
+{
+ /* Cancel pending control requests */
+ usb_ep_dequeue(dev->cdev->gadget->ep0, dev->cdev->req);
+ usb_remove_config(dev->cdev, &ccg_config_driver);
+ dev->enabled = false;
+ usb_gadget_disconnect(dev->cdev->gadget);
+}
+
+static void functionfs_closed_callback(struct ffs_data *ffs)
+{
+ struct ffs_obj *ffs_obj;
+
+ mutex_lock(&_ccg_dev->mutex);
+
+ ffs_obj = ffs->private_data;
+ if (!ffs_obj)
+ goto done;
+
+ ffs_obj->desc_ready = false;
+
+ if (_ccg_dev->enabled)
+ reset_usb(_ccg_dev);
+
+done:
+ mutex_unlock(&_ccg_dev->mutex);
+}
+
+static void *functionfs_acquire_dev_callback(const char *dev_name)
+{
+ struct ffs_obj *ffs_dev;
+
+ mutex_lock(&_ccg_dev->mutex);
+
+ ffs_dev = functionfs_find_dev(_ccg_dev, dev_name);
+ if (!ffs_dev) {
+ ffs_dev = ERR_PTR(-ENODEV);
+ goto done;
+ }
+
+ if (ffs_dev->mounted) {
+ ffs_dev = ERR_PTR(-EBUSY);
+ goto done;
+ }
+ ffs_dev->mounted = true;
+
+done:
+ mutex_unlock(&_ccg_dev->mutex);
+ return ffs_dev;
+}
+
+static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
+{
+ struct ffs_obj *ffs_dev;
+
+ mutex_lock(&_ccg_dev->mutex);
+
+ ffs_dev = ffs_data->private_data;
+ if (ffs_dev)
+ ffs_dev->mounted = false;
+
+ mutex_unlock(&_ccg_dev->mutex);
+}
+
+static int functionfs_function_init(struct ccg_usb_function *f,
+ struct usb_composite_dev *cdev)
+{
+ return functionfs_init();
+}
+
+static void functionfs_function_cleanup(struct ccg_usb_function *f)
+{
+ functionfs_cleanup();
+}
+
+static int functionfs_function_bind_config(struct ccg_usb_function *f,
+ struct usb_configuration *c)
+{
+ struct ccg_dev *dev = _ccg_dev;
+ int i, ret;
+
+ for (i = dev->max_func_num; i--; ) {
+ if (!dev->ffs_tab[i].used)
+ continue;
+ ret = functionfs_bind(dev->ffs_tab[i].ffs_data, c->cdev);
+ if (unlikely(ret < 0)) {
+ while (++i < dev->max_func_num)
+ functionfs_unbind(dev->ffs_tab[i].ffs_data);
+ return ret;
+ }
+ }
+
+ for (i = dev->max_func_num; i--; ) {
+ if (!dev->ffs_tab[i].used)
+ continue;
+ ret = functionfs_bind_config(c->cdev, c,
+ dev->ffs_tab[i].ffs_data);
+ if (unlikely(ret < 0))
+ return ret;
+ }
+
+ return 0;
+}
+
+static void functionfs_function_unbind_config(struct ccg_usb_function *f,
+ struct usb_configuration *c)
+{
+ struct ccg_dev *dev = _ccg_dev;
+ int i;
+
+ for (i = dev->max_func_num; i--; )
+ if (dev->ffs_tab[i].ffs_data)
+ functionfs_unbind(dev->ffs_tab[i].ffs_data);
+}
+
+static ssize_t functionfs_user_functions_show(struct device *_dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ccg_dev *dev = _ccg_dev;
+ char *buff = buf;
+ int i;
+
+ mutex_lock(&dev->mutex);
+
+ for (i = 0; i < dev->max_func_num; i++)
+ buff += snprintf(buff, PAGE_SIZE + buf - buff, "%s,",
+ dev->ffs_tab[i].name);
+
+ mutex_unlock(&dev->mutex);
+
+ if (buff != buf)
+ *(buff - 1) = '\n';
+ return buff - buf;
+}
+
+static ssize_t functionfs_user_functions_store(struct device *_dev,
+ struct device_attribute *attr,
+ const char *buff, size_t size)
+{
+ struct ccg_dev *dev = _ccg_dev;
+ char *name, *b;
+ ssize_t ret = size;
+ int i;
+
+ buff = skip_spaces(buff);
+ if (!*buff)
+ return -EINVAL;
+
+ mutex_lock(&dev->mutex);
+
+ if (dev->enabled) {
+ ret = -EBUSY;
+ goto end;
+ }
+
+ for (i = 0; i < dev->max_func_num; i++)
+ if (dev->ffs_tab[i].mounted) {
+ ret = -EBUSY;
+ goto end;
+ }
+
+ strlcpy(func_names_buf, buff, sizeof(func_names_buf));
+ b = strim(func_names_buf);
+
+ /* replace the list of functions */
+ dev->max_func_num = 0;
+ while (b) {
+ name = strsep(&b, ",");
+ if (dev->max_func_num == GFS_MAX_DEVS) {
+ ret = -ENOSPC;
+ goto end;
+ }
+ if (functionfs_find_dev(dev, name)) {
+ ret = -EEXIST;
+ continue;
+ }
+ dev->ffs_tab[dev->max_func_num++].name = name;
+ }
+
+end:
+ mutex_unlock(&dev->mutex);
+ return ret;
+}
+
+static DEVICE_ATTR(user_functions, S_IRUGO | S_IWUSR,
+ functionfs_user_functions_show,
+ functionfs_user_functions_store);
+
+static ssize_t functionfs_max_user_functions_show(struct device *_dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d", GFS_MAX_DEVS);
+}
+
+static DEVICE_ATTR(max_user_functions, S_IRUGO,
+ functionfs_max_user_functions_show, NULL);
+
+static struct device_attribute *functionfs_function_attributes[] = {
+ &dev_attr_user_functions,
+ &dev_attr_max_user_functions,
+ NULL
+};
+
+static struct ccg_usb_function functionfs_function = {
+ .name = "fs",
+ .init = functionfs_function_init,
+ .cleanup = functionfs_function_cleanup,
+ .bind_config = functionfs_function_bind_config,
+ .unbind_config = functionfs_function_unbind_config,
+ .attributes = functionfs_function_attributes,
+};
+
+#define MAX_ACM_INSTANCES 4
+struct acm_function_config {
+ int instances;
+};
+
+static int
+acm_function_init(struct ccg_usb_function *f, struct usb_composite_dev *cdev)
+{
+ f->config = kzalloc(sizeof(struct acm_function_config), GFP_KERNEL);
+ if (!f->config)
+ return -ENOMEM;
+
+ return gserial_setup(cdev->gadget, MAX_ACM_INSTANCES);
+}
+
+static void acm_function_cleanup(struct ccg_usb_function *f)
+{
+ gserial_cleanup();
+ kfree(f->config);
+ f->config = NULL;
+}
+
+static int
+acm_function_bind_config(struct ccg_usb_function *f,
+ struct usb_configuration *c)
+{
+ int i;
+ int ret = 0;
+ struct acm_function_config *config = f->config;
+
+ for (i = 0; i < config->instances; i++) {
+ ret = acm_bind_config(c, i);
+ if (ret) {
+ pr_err("Could not bind acm%u config\n", i);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static ssize_t acm_instances_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ccg_usb_function *f = dev_get_drvdata(dev);
+ struct acm_function_config *config = f->config;
+ return sprintf(buf, "%d\n", config->instances);
+}
+
+static ssize_t acm_instances_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct ccg_usb_function *f = dev_get_drvdata(dev);
+ struct acm_function_config *config = f->config;
+ int value;
+ int ret = 0;
+
+ ret = kstrtoint(buf, 10, &value);
+ if (ret)
+ return ret;
+
+ if (value > MAX_ACM_INSTANCES)
+ return -EINVAL;
+
+ config->instances = value;
+
+ return size;
+}
+
+static DEVICE_ATTR(instances, S_IRUGO | S_IWUSR, acm_instances_show,
+ acm_instances_store);
+static struct device_attribute *acm_function_attributes[] = {
+ &dev_attr_instances,
+ NULL
+};
+
+static struct ccg_usb_function acm_function = {
+ .name = "acm",
+ .init = acm_function_init,
+ .cleanup = acm_function_cleanup,
+ .bind_config = acm_function_bind_config,
+ .attributes = acm_function_attributes,
+};
+
+struct rndis_function_config {
+ u8 ethaddr[ETH_ALEN];
+ u32 vendorID;
+ char manufacturer[256];
+ /* "Wireless" RNDIS; auto-detected by Windows */
+ bool wceis;
+};
+
+static int rndis_function_init(struct ccg_usb_function *f,
+ struct usb_composite_dev *cdev)
+{
+ f->config = kzalloc(sizeof(struct rndis_function_config), GFP_KERNEL);
+ if (!f->config)
+ return -ENOMEM;
+ return 0;
+}
+
+static void rndis_function_cleanup(struct ccg_usb_function *f)
+{
+ kfree(f->config);
+ f->config = NULL;
+}
+
+static int rndis_function_bind_config(struct ccg_usb_function *f,
+ struct usb_configuration *c)
+{
+ int ret;
+ struct rndis_function_config *rndis = f->config;
+
+ if (!rndis) {
+ pr_err("%s: rndis_pdata\n", __func__);
+ return -1;
+ }
+
+ pr_info("%s MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", __func__,
+ rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2],
+ rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]);
+
+ ret = gether_setup_name(c->cdev->gadget, rndis->ethaddr, "rndis");
+ if (ret) {
+ pr_err("%s: gether_setup failed\n", __func__);
+ return ret;
+ }
+
+ if (rndis->wceis) {
+ /* "Wireless" RNDIS; auto-detected by Windows */
+ rndis_iad_descriptor.bFunctionClass =
+ USB_CLASS_WIRELESS_CONTROLLER;
+ rndis_iad_descriptor.bFunctionSubClass = 0x01;
+ rndis_iad_descriptor.bFunctionProtocol = 0x03;
+ rndis_control_intf.bInterfaceClass =
+ USB_CLASS_WIRELESS_CONTROLLER;
+ rndis_control_intf.bInterfaceSubClass = 0x01;
+ rndis_control_intf.bInterfaceProtocol = 0x03;
+ }
+
+ return rndis_bind_config_vendor(c, rndis->ethaddr, rndis->vendorID,
+ rndis->manufacturer);
+}
+
+static void rndis_function_unbind_config(struct ccg_usb_function *f,
+ struct usb_configuration *c)
+{
+ gether_cleanup();
+}
+
+static ssize_t rndis_manufacturer_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ccg_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+ return sprintf(buf, "%s\n", config->manufacturer);
+}
+
+static ssize_t rndis_manufacturer_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct ccg_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+
+ if (size >= sizeof(config->manufacturer))
+ return -EINVAL;
+ memcpy(config->manufacturer, buf, size);
+ config->manufacturer[size] = 0;
+
+ return size;
+}
+
+static DEVICE_ATTR(manufacturer, S_IRUGO | S_IWUSR, rndis_manufacturer_show,
+ rndis_manufacturer_store);
+
+static ssize_t rndis_wceis_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ccg_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+ return sprintf(buf, "%d\n", config->wceis);
+}
+
+static ssize_t rndis_wceis_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct ccg_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+ int value;
+ int ret;
+
+ ret = kstrtoint(buf, 10, &value);
+ if (ret)
+ return ret;
+
+ config->wceis = value;
+
+ return size;
+}
+
+static DEVICE_ATTR(wceis, S_IRUGO | S_IWUSR, rndis_wceis_show,
+ rndis_wceis_store);
+
+static ssize_t rndis_ethaddr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ccg_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *rndis = f->config;
+ return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2],
+ rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]);
+}
+
+static ssize_t rndis_ethaddr_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct ccg_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *rndis = f->config;
+ unsigned char tmp[6];
+
+ if (sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+ tmp + 0, tmp + 1, tmp + 2, tmp + 3, tmp + 4, tmp + 5) !=
+ ETH_ALEN)
+ return -EINVAL;
+
+ memcpy(rndis->ethaddr, tmp, ETH_ALEN);
+
+ return ETH_ALEN;
+
+}
+
+static DEVICE_ATTR(ethaddr, S_IRUGO | S_IWUSR, rndis_ethaddr_show,
+ rndis_ethaddr_store);
+
+static ssize_t rndis_vendorID_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ccg_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+ return sprintf(buf, "%04x\n", config->vendorID);
+}
+
+static ssize_t rndis_vendorID_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct ccg_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+ int value;
+ int ret;
+
+ ret = kstrtou32(buf, 16, &value);
+ if (ret)
+ return ret;
+
+ config->vendorID = value;
+
+ return size;
+}
+
+static DEVICE_ATTR(vendorID, S_IRUGO | S_IWUSR, rndis_vendorID_show,
+ rndis_vendorID_store);
+
+static struct device_attribute *rndis_function_attributes[] = {
+ &dev_attr_manufacturer,
+ &dev_attr_wceis,
+ &dev_attr_ethaddr,
+ &dev_attr_vendorID,
+ NULL
+};
+
+static struct ccg_usb_function rndis_function = {
+ .name = "rndis",
+ .init = rndis_function_init,
+ .cleanup = rndis_function_cleanup,
+ .bind_config = rndis_function_bind_config,
+ .unbind_config = rndis_function_unbind_config,
+ .attributes = rndis_function_attributes,
+};
+
+static int mass_storage_function_init(struct ccg_usb_function *f,
+ struct usb_composite_dev *cdev)
+{
+ struct fsg_config fsg;
+ struct fsg_common *common;
+ int err;
+
+ memset(&fsg, 0, sizeof fsg);
+ fsg.nluns = 1;
+ fsg.luns[0].removable = 1;
+ fsg.vendor_name = iManufacturer;
+ fsg.product_name = iProduct;
+
+ common = fsg_common_init(NULL, cdev, &fsg);
+ if (IS_ERR(common))
+ return PTR_ERR(common);
+
+ err = sysfs_create_link(&f->dev->kobj,
+ &common->luns[0].dev.kobj,
+ "lun");
+ if (err) {
+ fsg_common_put(common);
+ return err;
+ }
+
+ f->config = common;
+ return 0;
+}
+
+static void mass_storage_function_cleanup(struct ccg_usb_function *f)
+{
+ fsg_common_put(f->config);
+ f->config = NULL;
+}
+
+static int mass_storage_function_bind_config(struct ccg_usb_function *f,
+ struct usb_configuration *c)
+{
+ struct fsg_common *common = f->config;
+ return fsg_bind_config(c->cdev, c, common);
+}
+
+static struct ccg_usb_function mass_storage_function = {
+ .name = "mass_storage",
+ .init = mass_storage_function_init,
+ .cleanup = mass_storage_function_cleanup,
+ .bind_config = mass_storage_function_bind_config,
+};
+
+static struct ccg_usb_function *supported_functions[] = {
+ &functionfs_function,
+ &acm_function,
+ &rndis_function,
+ &mass_storage_function,
+ NULL
+};
+
+
+static int ccg_init_functions(struct ccg_usb_function **functions,
+ struct usb_composite_dev *cdev)
+{
+ struct ccg_dev *dev = _ccg_dev;
+ struct ccg_usb_function *f;
+ struct device_attribute **attrs;
+ struct device_attribute *attr;
+ int err;
+ int index = 0;
+
+ for (; (f = *functions++); index++) {
+ f->dev_name = kasprintf(GFP_KERNEL, "f_%s", f->name);
+ if (!f->dev_name) {
+ pr_err("%s: Failed to alloc name %s", __func__,
+ f->name);
+ err = -ENOMEM;
+ goto err_alloc;
+ }
+ f->dev = device_create(ccg_class, dev->dev,
+ MKDEV(0, index), f, f->dev_name);
+ if (IS_ERR(f->dev)) {
+ pr_err("%s: Failed to create dev %s", __func__,
+ f->dev_name);
+ err = PTR_ERR(f->dev);
+ f->dev = NULL;
+ goto err_create;
+ }
+
+ if (f->init) {
+ err = f->init(f, cdev);
+ if (err) {
+ pr_err("%s: Failed to init %s", __func__,
+ f->name);
+ goto err_out;
+ }
+ }
+
+ attrs = f->attributes;
+ if (attrs) {
+ while ((attr = *attrs++) && !err)
+ err = device_create_file(f->dev, attr);
+ }
+ if (err) {
+ pr_err("%s: Failed to create function %s attributes",
+ __func__, f->name);
+ goto err_uninit;
+ }
+ }
+ return 0;
+
+err_uninit:
+ if (f->cleanup)
+ f->cleanup(f);
+err_out:
+ device_destroy(ccg_class, f->dev->devt);
+ f->dev = NULL;
+err_create:
+ kfree(f->dev_name);
+err_alloc:
+ return err;
+}
+
+static void ccg_cleanup_functions(struct ccg_usb_function **functions)
+{
+ struct ccg_usb_function *f;
+
+ while (*functions) {
+ f = *functions++;
+
+ if (f->dev) {
+ if (f->cleanup)
+ f->cleanup(f);
+ device_destroy(ccg_class, f->dev->devt);
+ kfree(f->dev_name);
+ }
+ }
+}
+
+static int ccg_bind_enabled_functions(struct ccg_dev *dev,
+ struct usb_configuration *c)
+{
+ struct ccg_usb_function *f;
+ int ret;
+
+ list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
+ ret = f->bind_config(f, c);
+ if (ret) {
+ pr_err("%s: %s failed", __func__, f->name);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static void ccg_unbind_enabled_functions(struct ccg_dev *dev,
+ struct usb_configuration *c)
+{
+ struct ccg_usb_function *f;
+
+ list_for_each_entry(f, &dev->enabled_functions, enabled_list)
+ if (f->unbind_config)
+ f->unbind_config(f, c);
+}
+
+static int ccg_enable_function(struct ccg_dev *dev, char *name)
+{
+ struct ccg_usb_function **functions = dev->functions;
+ struct ccg_usb_function *f;
+ while ((f = *functions++)) {
+ if (!strcmp(name, f->name)) {
+ list_add_tail(&f->enabled_list,
+ &dev->enabled_functions);
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+/*-------------------------------------------------------------------------*/
+/* /sys/class/ccg_usb/ccg%d/ interface */
+
+static ssize_t
+functions_show(struct device *pdev, struct device_attribute *attr, char *buf)
+{
+ struct ccg_dev *dev = dev_get_drvdata(pdev);
+ struct ccg_usb_function *f;
+ char *buff = buf;
+ int i;
+
+ mutex_lock(&dev->mutex);
+
+ list_for_each_entry(f, &dev->enabled_functions, enabled_list)
+ buff += sprintf(buff, "%s,", f->name);
+ for (i = 0; i < dev->max_func_num; i++)
+ if (dev->ffs_tab[i].used)
+ buff += sprintf(buff, "%s", dev->ffs_tab[i].name);
+
+ mutex_unlock(&dev->mutex);
+
+ if (buff != buf)
+ *(buff-1) = '\n';
+ return buff - buf;
+}
+
+static ssize_t
+functions_store(struct device *pdev, struct device_attribute *attr,
+ const char *buff, size_t size)
+{
+ struct ccg_dev *dev = dev_get_drvdata(pdev);
+ char *name;
+ char buf[256], *b;
+ int err, i;
+ bool functionfs_enabled;
+
+ buff = skip_spaces(buff);
+ if (!*buff)
+ return -EINVAL;
+
+ mutex_lock(&dev->mutex);
+
+ if (dev->enabled) {
+ mutex_unlock(&dev->mutex);
+ return -EBUSY;
+ }
+
+ INIT_LIST_HEAD(&dev->enabled_functions);
+ functionfs_enabled = false;
+ for (i = 0; i < dev->max_func_num; i++)
+ dev->ffs_tab[i].used = false;
+
+ strlcpy(buf, buff, sizeof(buf));
+ b = strim(buf);
+
+ while (b) {
+ struct ffs_obj *user_func;
+
+ name = strsep(&b, ",");
+ /* handle FunctionFS implicitly */
+ if (!strcmp(name, functionfs_function.name)) {
+ pr_err("ccg_usb: Cannot explicitly enable '%s'", name);
+ continue;
+ }
+ user_func = functionfs_find_dev(dev, name);
+ if (user_func)
+ name = functionfs_function.name;
+ err = 0;
+ if (!user_func || !functionfs_enabled)
+ err = ccg_enable_function(dev, name);
+ if (err)
+ pr_err("ccg_usb: Cannot enable '%s'", name);
+ else if (user_func) {
+ user_func->used = true;
+ dev->func_num++;
+ functionfs_enabled = true;
+ }
+ }
+
+ mutex_unlock(&dev->mutex);
+
+ return size;
+}
+
+static ssize_t enable_show(struct device *pdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct ccg_dev *dev = dev_get_drvdata(pdev);
+ return sprintf(buf, "%d\n", dev->enabled);
+}
+
+static ssize_t enable_store(struct device *pdev, struct device_attribute *attr,
+ const char *buff, size_t size)
+{
+ struct ccg_dev *dev = dev_get_drvdata(pdev);
+ struct usb_composite_dev *cdev = dev->cdev;
+ int enabled = 0;
+
+ mutex_lock(&dev->mutex);
+ sscanf(buff, "%d", &enabled);
+ if (enabled && dev->func_num && !functionfs_all_ready(dev)) {
+ mutex_unlock(&dev->mutex);
+ return -ENODEV;
+ }
+
+ if (enabled && !dev->enabled) {
+ int ret;
+
+ cdev->next_string_id = 0;
+ /*
+ * Update values in composite driver's copy of
+ * device descriptor.
+ */
+ cdev->desc.bDeviceClass = device_desc.bDeviceClass;
+ cdev->desc.bDeviceSubClass = device_desc.bDeviceSubClass;
+ cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol;
+ cdev->desc.idVendor = idVendor;
+ cdev->desc.idProduct = idProduct;
+ cdev->desc.bcdDevice = bcdDevice;
+
+ usb_add_config(cdev, &ccg_config_driver, ccg_bind_config);
+ dev->enabled = true;
+ ret = usb_gadget_connect(cdev->gadget);
+ if (ret) {
+ dev->enabled = false;
+ usb_remove_config(cdev, &ccg_config_driver);
+ }
+ } else if (!enabled && dev->enabled) {
+ reset_usb(dev);
+ } else {
+ pr_err("ccg_usb: already %s\n",
+ dev->enabled ? "enabled" : "disabled");
+ }
+
+ mutex_unlock(&dev->mutex);
+ return size;
+}
+
+static ssize_t state_show(struct device *pdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct ccg_dev *dev = dev_get_drvdata(pdev);
+ struct usb_composite_dev *cdev = dev->cdev;
+ char *state = "DISCONNECTED";
+ unsigned long flags;
+
+ if (!cdev)
+ goto out;
+
+ spin_lock_irqsave(&cdev->lock, flags);
+ if (cdev->config)
+ state = "CONFIGURED";
+ else if (dev->connected)
+ state = "CONNECTED";
+ spin_unlock_irqrestore(&cdev->lock, flags);
+out:
+ return sprintf(buf, "%s\n", state);
+}
+
+#define DESCRIPTOR_ATTR(field, format_string) \
+static ssize_t \
+field ## _show(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return sprintf(buf, format_string, device_desc.field); \
+} \
+static ssize_t \
+field ## _store(struct device *dev, struct device_attribute *attr, \
+ const char *buf, size_t size) \
+{ \
+ int value; \
+ if (sscanf(buf, format_string, &value) == 1) { \
+ device_desc.field = value; \
+ return size; \
+ } \
+ return -1; \
+} \
+static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store);
+
+DESCRIPTOR_ATTR(bDeviceClass, "%d\n")
+DESCRIPTOR_ATTR(bDeviceSubClass, "%d\n")
+DESCRIPTOR_ATTR(bDeviceProtocol, "%d\n")
+
+static DEVICE_ATTR(functions, S_IRUGO | S_IWUSR, functions_show,
+ functions_store);
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
+static DEVICE_ATTR(state, S_IRUGO, state_show, NULL);
+
+static struct device_attribute *ccg_usb_attributes[] = {
+ &dev_attr_bDeviceClass,
+ &dev_attr_bDeviceSubClass,
+ &dev_attr_bDeviceProtocol,
+ &dev_attr_functions,
+ &dev_attr_enable,
+ &dev_attr_state,
+ NULL
+};
+
+/*-------------------------------------------------------------------------*/
+/* Composite driver */
+
+static int ccg_bind_config(struct usb_configuration *c)
+{
+ struct ccg_dev *dev = _ccg_dev;
+ int ret = 0;
+
+ ret = ccg_bind_enabled_functions(dev, c);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void ccg_unbind_config(struct usb_configuration *c)
+{
+ struct ccg_dev *dev = _ccg_dev;
+
+ ccg_unbind_enabled_functions(dev, c);
+
+ usb_ep_autoconfig_reset(dev->cdev->gadget);
+}
+
+static int ccg_bind(struct usb_composite_dev *cdev)
+{
+ struct ccg_dev *dev = _ccg_dev;
+ struct usb_gadget *gadget = cdev->gadget;
+ int gcnum, ret;
+
+ /*
+ * Start disconnected. Userspace will connect the gadget once
+ * it is done configuring the functions.
+ */
+ usb_gadget_disconnect(gadget);
+
+ ret = ccg_init_functions(dev->functions, cdev);
+ if (ret)
+ return ret;
+
+ gcnum = usb_gadget_controller_number(gadget);
+ if (gcnum >= 0)
+ device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
+ else {
+ pr_warning("%s: controller '%s' not recognized\n",
+ longname, gadget->name);
+ device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
+ }
+
+ usb_gadget_set_selfpowered(gadget);
+ dev->cdev = cdev;
+
+ return 0;
+}
+
+static int ccg_usb_unbind(struct usb_composite_dev *cdev)
+{
+ struct ccg_dev *dev = _ccg_dev;
+
+ cancel_work_sync(&dev->work);
+ ccg_cleanup_functions(dev->functions);
+ return 0;
+}
+
+static struct usb_composite_driver ccg_usb_driver = {
+ .name = "configurable_usb",
+ .dev = &device_desc,
+ .unbind = ccg_usb_unbind,
+ .needs_serial = true,
+ .iManufacturer = "Linux Foundation",
+ .iProduct = longname,
+ .iSerialNumber = "1234567890123456",
+};
+
+static int ccg_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *c)
+{
+ struct ccg_dev *dev = _ccg_dev;
+ struct usb_composite_dev *cdev = get_gadget_data(gadget);
+ struct usb_request *req = cdev->req;
+ struct ccg_usb_function *f;
+ int value = -EOPNOTSUPP;
+ unsigned long flags;
+
+ req->zero = 0;
+ req->complete = composite_setup_complete;
+ req->length = 0;
+ gadget->ep0->driver_data = cdev;
+
+ list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
+ if (f->ctrlrequest) {
+ value = f->ctrlrequest(f, cdev, c);
+ if (value >= 0)
+ break;
+ }
+ }
+
+ if (value < 0)
+ value = composite_setup(gadget, c);
+
+ spin_lock_irqsave(&cdev->lock, flags);
+ if (!dev->connected) {
+ dev->connected = 1;
+ schedule_work(&dev->work);
+ } else if (c->bRequest == USB_REQ_SET_CONFIGURATION &&
+ cdev->config) {
+ schedule_work(&dev->work);
+ }
+ spin_unlock_irqrestore(&cdev->lock, flags);
+
+ return value;
+}
+
+static void ccg_disconnect(struct usb_gadget *gadget)
+{
+ struct ccg_dev *dev = _ccg_dev;
+ struct usb_composite_dev *cdev = get_gadget_data(gadget);
+ unsigned long flags;
+
+ composite_disconnect(gadget);
+
+ spin_lock_irqsave(&cdev->lock, flags);
+ dev->connected = 0;
+ schedule_work(&dev->work);
+ spin_unlock_irqrestore(&cdev->lock, flags);
+}
+
+static int ccg_create_device(struct ccg_dev *dev)
+{
+ struct device_attribute **attrs = ccg_usb_attributes;
+ struct device_attribute *attr;
+ int err;
+
+ dev->dev = device_create(ccg_class, NULL, MKDEV(0, 0), NULL, "ccg0");
+ if (IS_ERR(dev->dev))
+ return PTR_ERR(dev->dev);
+
+ dev_set_drvdata(dev->dev, dev);
+
+ while ((attr = *attrs++)) {
+ err = device_create_file(dev->dev, attr);
+ if (err) {
+ device_destroy(ccg_class, dev->dev->devt);
+ return err;
+ }
+ }
+ return 0;
+}
+
+
+static int __init init(void)
+{
+ struct ccg_dev *dev;
+ int err;
+
+ ccg_class = class_create(THIS_MODULE, "ccg_usb");
+ if (IS_ERR(ccg_class))
+ return PTR_ERR(ccg_class);
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->functions = supported_functions;
+ INIT_LIST_HEAD(&dev->enabled_functions);
+ INIT_WORK(&dev->work, ccg_work);
+ mutex_init(&dev->mutex);
+
+ err = ccg_create_device(dev);
+ if (err) {
+ class_destroy(ccg_class);
+ kfree(dev);
+ return err;
+ }
+
+ _ccg_dev = dev;
+
+ /* Override composite driver functions */
+ composite_driver.setup = ccg_setup;
+ composite_driver.disconnect = ccg_disconnect;
+
+ err = usb_composite_probe(&ccg_usb_driver, ccg_bind);
+ if (err) {
+ class_destroy(ccg_class);
+ kfree(dev);
+ }
+
+ return err;
+}
+module_init(init);
+
+static void __exit cleanup(void)
+{
+ usb_composite_unregister(&ccg_usb_driver);
+ class_destroy(ccg_class);
+ kfree(_ccg_dev);
+ _ccg_dev = NULL;
+}
+module_exit(cleanup);
diff --git a/drivers/staging/ccg/sysfs-class-ccg_usb b/drivers/staging/ccg/sysfs-class-ccg_usb
new file mode 100644
index 000000000000..dd12a332fb00
--- /dev/null
+++ b/drivers/staging/ccg/sysfs-class-ccg_usb
@@ -0,0 +1,158 @@
+What: /sys/class/ccg_usb
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ The ccg_usb/ class subdirectory belongs to ccg
+ USB gadget.
+
+What: /sys/class/ccg_usb/ccgX
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ The /sys/class/ccg_usb/ccg{0,1,2,3...} class
+ subdirectories correspond to each ccg gadget device;
+ at the time of this writing there is only ccg0 and it
+ represents the ccg gadget.
+
+What: /sys/class/ccg_usb/ccgX/functions
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ A comma-separated list of USB function names to be activated
+ in this ccg gadget. It includes both the functions provided
+ in-kernel by the ccg gadget and the functions provided from
+ userspace through FunctionFS.
+
+What: /sys/class/ccg_usb/ccgX/enable
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ A flag activating/deactivating the ccg usb gadget.
+
+What: /sys/class/ccg_usb/ccgX/state
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ Configurable usb gadget state:
+
+ DISCONNECTED
+ CONNECTED
+ CONFIGURED
+
+What: /sys/class/ccg_usb/ccgX/f_acm/
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ The /sys/class/ccg_usb/ccgX/f_acm subdirectory
+ corresponds to the gadget's USB CDC serial (ACM) function
+ driver.
+
+What: /sys/class/ccg_usb/ccgX/f_acm/instances
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ Maximum number of the /dev/ttyGS<X> interface the driver uses.
+
+What: /sys/class/ccg_usb/ccgX/f_fs
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ The /sys/class/ccg_usb/ccgX/f_fs subdirectory
+ corresponds to the gadget's FunctionFS driver.
+
+What: /sys/class/ccg_usb/ccgX/f_fs/user_functions
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ A comma-separeted list of USB function names to be supported
+ from userspace. No other userspace FunctionFS functions can
+ be supported than listed here. However, the actual activation
+ of these functions is still done through
+ /sys/class/ccg_usb/ccgX/functions, where it is possible
+ to specify any subset (including maximum and empty) of
+ /sys/class/ccg_usb/ccgX/f_fs/user_functions.
+
+What: /sys/class/ccg_usb/ccgX/f_fs/max_user_functions
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ Maximum number of USB functions to be supported from userspace.
+
+What: /sys/class/ccg_usb/ccgX/f_rndis
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ The /sys/class/ccg_usb/ccgX/f_rndis subdirectory
+ corresponds to the gadget's RNDIS driver.
+
+What: /sys/class/ccg_usb/ccgX/f_rndis/manufacturer
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ RNDIS Ethernet port manufacturer string.
+
+What: /sys/class/ccg_usb/ccgX/f_rndis/wceis
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ RNDIS Ethernet port wireless flag.
+
+What: /sys/class/ccg_usb/ccgX/f_rndis/ethaddr
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ RNDIS Ethernet port Ethernet address.
+
+What: /sys/class/ccg_usb/ccgX/f_rndis/vendorID
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ RNDIS Ethernet port vendor ID.
+
+What: /sys/class/ccg_usb/ccgX/f_mass_storage
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ The /sys/class/ccg_usb/ccgX/f_mass_storage subdirectory
+ corresponds to the gadget's USB mass storage driver.
+
+What: /sys/class/ccg_usb/ccgX/f_mass_storage/lun
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ The /sys/class/ccg_usb/ccgX/f_mass_storage/lun
+ subdirectory corresponds to the gadget's USB mass storage
+ driver and its underlying storage.
+
+What: /sys/class/ccg_usb/ccgX/f_mass_storage/lun
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ The /sys/class/ccg_usb/ccgX/f_mass_storage/lun
+ subdirectory corresponds to the gadget's USB mass storage
+ driver and its underlying storage.
+
+What: /sys/class/ccg_usb/ccgX/f_mass_storage/lun/file
+Date: May 2012
+KernelVersion: 3.4
+Contact: linux-usb@vger.kernel.org
+Description:
+ Gadget's USB mass storage underlying file.
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index 12c691d90900..3bbe3fd103f3 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -1,6 +1,5 @@
config COMEDI
tristate "Data acquisition support (comedi)"
- default N
depends on m
depends on BROKEN || FRV || M32R || MN10300 || SUPERH || TILE || X86
---help---
@@ -14,10 +13,29 @@ config COMEDI_DEBUG
This is an option for use by developers; most people should
say N here. This enables comedi core and driver debugging.
+config COMEDI_DEFAULT_BUF_SIZE_KB
+ int "Comedi default initial asynchronous buffer size in KiB"
+ default "2048"
+ depends on COMEDI != n
+ ---help---
+ This is the default asynchronous buffer size which is used for
+ commands running in the background in kernel space. This
+ defaults to 2048 KiB of memory so that a 16 channel card
+ running at 10 kHz has of 2-4 seconds of buffer.
+
+config COMEDI_DEFAULT_BUF_MAXSIZE_KB
+ int "Comedi default maximum asynchronous buffer size in KiB"
+ default "20480"
+ depends on COMEDI != n
+ ---help---
+ This is the default maximum asynchronous buffer size which can
+ be requested by a userspace program without root privileges.
+ This is set to 20480 KiB so that a fast I/O card with 16
+ channels running at 100 kHz has 2-4 seconds of buffer.
+
menuconfig COMEDI_MISC_DRIVERS
tristate "Comedi misc drivers"
depends on COMEDI
- default N
---help---
Enable comedi misc drivers to be built
@@ -35,7 +53,6 @@ config COMEDI_KCOMEDILIB
config COMEDI_BOND
tristate "Device bonding support"
depends on COMEDI_KCOMEDILIB
- default N
---help---
Enable support for a driver to 'bond' (merge) multiple subdevices
from multiple devices together as one.
@@ -46,7 +63,6 @@ config COMEDI_BOND
config COMEDI_TEST
tristate "Fake waveform generator support"
select COMEDI_FC
- default N
---help---
Enable support for the fake waveform generator.
This driver is mainly for testing purposes, but can also be used to
@@ -58,7 +74,6 @@ config COMEDI_TEST
config COMEDI_PARPORT
tristate "Parallel port support"
- default N
---help---
Enable support for the standard parallel port.
A cheap and easy way to get a few more digital I/O lines. Steal
@@ -70,7 +85,6 @@ config COMEDI_PARPORT
config COMEDI_SERIAL2002
tristate "Driver for serial connected hardware"
- default N
---help---
Enable support for serial connected hardware
@@ -79,7 +93,6 @@ config COMEDI_SERIAL2002
config COMEDI_SKEL
tristate "Comedi skeleton driver"
- default N
---help---
Build the Skeleton driver, an example for driver writers
@@ -91,7 +104,6 @@ endif # COMEDI_MISC_DRIVERS
menuconfig COMEDI_ISA_DRIVERS
tristate "Comedi ISA and PC/104 drivers"
depends on COMEDI && ISA
- default N
---help---
Enable comedi ISA and PC/104 drivers to be built
@@ -103,7 +115,6 @@ if COMEDI_ISA_DRIVERS && ISA
config COMEDI_ACL7225B
tristate "ADlink NuDAQ ACL-7225b and compatibles support"
- default N
---help---
Enable support for ADlink NuDAQ ACL-7225b and compatibles,
ADlink ACL-7225b (acl7225b), ICP P16R16DIO (p16r16dio)
@@ -113,7 +124,6 @@ config COMEDI_ACL7225B
config COMEDI_PCL711
tristate "Advantech PCL-711/711b and ADlink ACL-8112 ISA card support"
- default N
---help---
Enable support for Advantech PCL-711 and 711b, ADlink ACL-8112
@@ -123,7 +133,6 @@ config COMEDI_PCL711
config COMEDI_PCL724
tristate "Advantech PCL-722/724/731 and ADlink ACL-7122/7124/PET-48DIO"
select COMEDI_8255
- default N
---help---
Enable support for Advantech PCL-724, PCL-722, PCL-731 and
ADlink ACL-7122, ACL-7124, PET-48DIO ISA cards
@@ -133,7 +142,6 @@ config COMEDI_PCL724
config COMEDI_PCL725
tristate "Advantech PCL-725 and compatible ISA card support"
- default N
---help---
Enable support for Advantech PCL-725 and compatible ISA cards.
@@ -142,7 +150,6 @@ config COMEDI_PCL725
config COMEDI_PCL726
tristate "Advantech PCL-726 and compatible ISA card support"
- default N
---help---
Enable support for Advantech PCL-726 and compatible ISA cards.
@@ -151,7 +158,6 @@ config COMEDI_PCL726
config COMEDI_PCL730
tristate "Advantech PCL-730 and ADlink ACL-7130 ISA card support"
- default N
---help---
Enable support for Advantech PCL-730, ICP ISO-730 and ADlink
ACL-7130 ISA cards
@@ -162,7 +168,6 @@ config COMEDI_PCL730
config COMEDI_PCL812
tristate "Advantech PCL-812/813 and ADlink ACL-8112/8113/8113/8216"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for Advantech PCL-812/PG, PCL-813/B, ADLink
ACL-8112DG/HG/PG, ACL-8113, ACL-8216, ICP DAS A-821PGH/PGL/PGL-NDA,
@@ -174,7 +179,6 @@ config COMEDI_PCL812
config COMEDI_PCL816
tristate "Advantech PCL-814 and PCL-816 ISA card support"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for Advantech PCL-814 and PCL-816 ISA cards
@@ -184,7 +188,6 @@ config COMEDI_PCL816
config COMEDI_PCL818
tristate "Advantech PCL-718 and PCL-818 ISA card support"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for Advantech PCL-818 ISA cards
PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818 and PCL-718
@@ -195,7 +198,6 @@ config COMEDI_PCL818
config COMEDI_PCM3724
tristate "Advantech PCM-3724 PC/104 card support"
select COMEDI_8255
- default N
---help---
Enable support for Advantech PCM-3724 PC/104 cards.
@@ -204,16 +206,43 @@ config COMEDI_PCM3724
config COMEDI_PCM3730
tristate "Advantech PCM-3730 and clone PC/104 board support"
- default N
---help---
Enable support for Advantech PCM-3730 and clone PC/104 boards
To compile this driver as a module, choose M here: the module will be
called pcm3730.
+config COMEDI_AMPLC_DIO200_ISA
+ tristate "Amplicon PC212E/PC214E/PC215E/PC218E/PC272E"
+ select COMEDI_AMPLC_DIO200
+ depends on COMEDI_ISA_DRIVERS
+ ---help---
+ Enable support for Amplicon PC212E, PC214E, PC215E, PC218E and
+ PC272E ISA DIO boards
+
+ To compile this driver as a module, choose M here: the module will be
+ called amplc_dio200.
+
+config COMEDI_AMPLC_PC236_ISA
+ tristate "Amplicon PC36AT DIO board support"
+ select COMEDI_AMPLC_PC236
+ ---help---
+ Enable support for Amplicon PC36AT ISA DIO board.
+
+ To compile this driver as a module, choose M here: the module will be
+ called amplc_pc236.
+
+config COMEDI_AMPLC_PC263_ISA
+ tristate "Amplicon PC263 relay board support"
+ select COMEDI_AMPLC_PC263
+ ---help---
+ Enable support for Amplicon PC263 ISA relay board.
+
+ To compile this driver as a module, choose M here: the module will be
+ called amplc_pc263.
+
config COMEDI_RTI800
tristate "Analog Devices RTI-800/815 ISA card support"
- default N
---help---
Enable support for Analog Devices RTI-800/815 ISA cards
@@ -222,7 +251,6 @@ config COMEDI_RTI800
config COMEDI_RTI802
tristate "Analog Devices RTI-802 ISA card support"
- default N
---help---
Enable support for Analog Devices RTI-802 ISA cards
@@ -233,18 +261,29 @@ config COMEDI_DAS16M1
tristate "MeasurementComputing CIO-DAS16/M1DAS-16 ISA card support"
select COMEDI_8255
select COMEDI_FC
- default N
---help---
Enable support for Measurement Computing CIO-DAS16/M1 ISA cards.
To compile this driver as a module, choose M here: the module will be
called das16m1.
+config COMEDI_DAS08_ISA
+ tristate "DAS-08 compatible ISA and PC/104 card support"
+ select COMEDI_DAS08
+ ---help---
+ Enable support for Keithley Metrabyte/ComputerBoards DAS08
+ and compatible ISA and PC/104 cards:
+ Keithley Metrabyte/ComputerBoards DAS08, DAS08-PGM, DAS08-PGH,
+ DAS08-PGL, DAS08-AOH, DAS08-AOL, DAS08-AOM, DAS08/JR-AO,
+ DAS08/JR-16-AO, PC104-DAS08, DAS08/JR/16.
+
+ To compile this driver as a module, choose M here: the module will be
+ called das08.
+
config COMEDI_DAS16
tristate "DAS-16 compatible ISA and PC/104 card support"
select COMEDI_8255
select COMEDI_FC
- default N
---help---
Enable support for Keithley Metrabyte/ComputerBoards DAS16
and compatible ISA and PC/104 cards:
@@ -261,7 +300,6 @@ config COMEDI_DAS16
config COMEDI_DAS800
tristate "DAS800 and compatible ISA card support"
select COMEDI_FC
- default N
---help---
Enable support for Keithley Metrabyte DAS800 and compatible ISA cards
Keithley Metrabyte DAS-800, DAS-801, DAS-802
@@ -275,7 +313,6 @@ config COMEDI_DAS1800
tristate "DAS1800 and compatible ISA card support"
depends on VIRT_TO_BUS
select COMEDI_FC
- default N
---help---
Enable support for DAS1800 and compatible ISA cards
Keithley Metrabyte DAS-1701ST, DAS-1701ST-DA, DAS-1701/AO,
@@ -289,7 +326,6 @@ config COMEDI_DAS1800
config COMEDI_DAS6402
tristate "DAS6402 and compatible ISA card support"
- default N
---help---
Enable support for DAS6402 and compatible ISA cards
Computerboards, Keithley Metrabyte DAS6402 and compatibles
@@ -299,7 +335,6 @@ config COMEDI_DAS6402
config COMEDI_DT2801
tristate "Data Translation DT2801 ISA card support"
- default N
---help---
Enable support for Data Translation DT2801 ISA cards
@@ -308,7 +343,6 @@ config COMEDI_DT2801
config COMEDI_DT2811
tristate "Data Translation DT2811 ISA card support"
- default N
---help---
Enable support for Data Translation DT2811 ISA cards
@@ -317,7 +351,6 @@ config COMEDI_DT2811
config COMEDI_DT2814
tristate "Data Translation DT2814 ISA card support"
- default N
---help---
Enable support for Data Translation DT2814 ISA cards
@@ -326,7 +359,6 @@ config COMEDI_DT2814
config COMEDI_DT2815
tristate "Data Translation DT2815 ISA card support"
- default N
---help---
Enable support for Data Translation DT2815 ISA cards
@@ -335,7 +367,6 @@ config COMEDI_DT2815
config COMEDI_DT2817
tristate "Data Translation DT2817 ISA card support"
- default N
---help---
Enable support for Data Translation DT2817 ISA cards
@@ -346,7 +377,6 @@ config COMEDI_DT282X
tristate "Data Translation DT2821 series and DT-EZ ISA card support"
select COMEDI_FC
depends on VIRT_TO_BUS
- default N
---help---
Enable support for Data Translation DT2821 series including DT-EZ
DT2821, DT2821-F-16SE, DT2821-F-8DI, DT2821-G-16SE, DT2821-G-8DI,
@@ -358,7 +388,6 @@ config COMEDI_DT282X
config COMEDI_DMM32AT
tristate "Diamond Systems MM-32-AT PC/104 board support"
- default N
---help---
Enable support for Diamond Systems MM-32-AT PC/104 boards
@@ -367,7 +396,6 @@ config COMEDI_DMM32AT
config COMEDI_FL512
tristate "FL512 ISA card support"
- default N
---help---
Enable support for FL512 ISA card
@@ -377,7 +405,6 @@ config COMEDI_FL512
config COMEDI_AIO_AIO12_8
tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support"
select COMEDI_8255
- default N
---help---
Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board
@@ -386,7 +413,6 @@ config COMEDI_AIO_AIO12_8
config COMEDI_AIO_IIRO_16
tristate "I/O Products PC/104 IIRO16 Board support"
- default N
---help---
Enable support for I/O Products PC/104 IIRO16 Relay And Isolated
Input Board
@@ -396,7 +422,6 @@ config COMEDI_AIO_IIRO_16
config COMEDI_C6XDIGIO
tristate "Mechatronic Systems Inc. C6x_DIGIO DSP daughter card support"
- default N
---help---
Enable support for Mechatronic Systems Inc. C6x_DIGIO DSP daughter
card
@@ -406,7 +431,6 @@ config COMEDI_C6XDIGIO
config COMEDI_MPC624
tristate "Micro/sys MPC-624 PC/104 board support"
- default N
---help---
Enable support for Micro/sys MPC-624 PC/104 board
@@ -415,7 +439,6 @@ config COMEDI_MPC624
config COMEDI_ADQ12B
tristate "MicroAxial ADQ12-B data acquisition and control card support"
- default N
---help---
Enable MicroAxial ADQ12-B daq and control card support.
@@ -426,7 +449,6 @@ config COMEDI_NI_AT_A2150
tristate "NI AT-A2150 ISA card support"
depends on COMEDI_NI_COMMON
depends on VIRT_TO_BUS
- default N
---help---
Enable support for National Instruments AT-A2150 cards
@@ -436,7 +458,6 @@ config COMEDI_NI_AT_A2150
config COMEDI_NI_AT_AO
tristate "NI AT-AO-6/10 EISA card support"
depends on COMEDI_NI_COMMON
- default N
---help---
Enable support for National Instruments AT-AO-6/10 cards
@@ -447,7 +468,6 @@ config COMEDI_NI_ATMIO
tristate "NI AT-MIO E series ISA-PNP card support"
depends on ISAPNP && COMEDI_NI_TIO && COMEDI_NI_COMMON
select COMEDI_8255
- default N
---help---
Enable support for National Instruments AT-MIO E series cards
National Instruments AT-MIO-16E-1 (ni_atmio),
@@ -461,7 +481,6 @@ config COMEDI_NI_ATMIO16D
tristate "NI AT-MIO16/AT-MIO16D series ISA-PNP card support"
depends on ISAPNP && COMEDI_NI_COMMON
select COMEDI_8255
- default N
---help---
Enable support for National Instruments AT-MIO16/AT-MIO16D cards.
@@ -470,7 +489,6 @@ config COMEDI_NI_ATMIO16D
config COMEDI_PCMAD
tristate "Winsystems PCM-A/D12 and PCM-A/D16 PC/104 board support"
- default N
---help---
Enable support for Winsystems PCM-A/D12 and PCM-A/D16 PC/104 boards.
@@ -479,7 +497,6 @@ config COMEDI_PCMAD
config COMEDI_PCMDA12
tristate "Winsystems PCM-D/A-12 8-channel AO PC/104 board support"
- default N
---help---
Enable support for Winsystems PCM-D/A-12 8-channel AO PC/104 boards.
Note that the board is not ISA-PNP capable and thus needs the I/O
@@ -490,7 +507,6 @@ config COMEDI_PCMDA12
config COMEDI_PCMMIO
tristate "Winsystems PCM-MIO PC/104 board support"
- default N
---help---
Enable support for Winsystems PCM-MIO multifunction PC/104 boards.
@@ -499,7 +515,6 @@ config COMEDI_PCMMIO
config COMEDI_PCMUIO
tristate "Winsystems PCM-UIO48A and PCM-UIO96A PC/104 board support"
- default N
---help---
Enable support for PCM-UIO48A and PCM-UIO96A PC/104 boards.
@@ -508,7 +523,6 @@ config COMEDI_PCMUIO
config COMEDI_MULTIQ3
tristate "Quanser Consulting MultiQ-3 ISA card support"
- default N
---help---
Enable support for Quanser Consulting MultiQ-3 ISA cards
@@ -517,7 +531,6 @@ config COMEDI_MULTIQ3
config COMEDI_POC
tristate "Generic driver for very simple devices"
- default N
---help---
Enable generic support for very simple / POC (Piece of Crap) boards,
Keithley Metrabyte DAC-02 (dac02), Advantech PCL-733 (pcl733) and
@@ -531,7 +544,6 @@ endif # COMEDI_ISA_DRIVERS
menuconfig COMEDI_PCI_DRIVERS
tristate "Comedi PCI drivers"
depends on COMEDI && PCI
- default N
---help---
Enable comedi PCI drivers to be built
@@ -544,7 +556,6 @@ if COMEDI_PCI_DRIVERS && PCI
config COMEDI_ADDI_APCI_035
tristate "ADDI-DATA APCI_035 support"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for ADDI-DATA APCI_035 cards
@@ -554,7 +565,6 @@ config COMEDI_ADDI_APCI_035
config COMEDI_ADDI_APCI_1032
tristate "ADDI-DATA APCI_1032 support"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for ADDI-DATA APCI_1032 cards
@@ -564,7 +574,6 @@ config COMEDI_ADDI_APCI_1032
config COMEDI_ADDI_APCI_1500
tristate "ADDI-DATA APCI_1500 support"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for ADDI-DATA APCI_1500 cards
@@ -574,7 +583,6 @@ config COMEDI_ADDI_APCI_1500
config COMEDI_ADDI_APCI_1516
tristate "ADDI-DATA APCI_1516 support"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for ADDI-DATA APCI_1516 cards
@@ -584,7 +592,6 @@ config COMEDI_ADDI_APCI_1516
config COMEDI_ADDI_APCI_1564
tristate "ADDI-DATA APCI_1564 support"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for ADDI-DATA APCI_1564 cards
@@ -594,7 +601,6 @@ config COMEDI_ADDI_APCI_1564
config COMEDI_ADDI_APCI_16XX
tristate "ADDI-DATA APCI_16xx support"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for ADDI-DATA APCI_16xx cards
@@ -604,7 +610,6 @@ config COMEDI_ADDI_APCI_16XX
config COMEDI_ADDI_APCI_2016
tristate "ADDI-DATA APCI_2016 support"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for ADDI-DATA APCI_2016 cards
@@ -614,7 +619,6 @@ config COMEDI_ADDI_APCI_2016
config COMEDI_ADDI_APCI_2032
tristate "ADDI-DATA APCI_2032 support"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for ADDI-DATA APCI_2032 cards
@@ -624,7 +628,6 @@ config COMEDI_ADDI_APCI_2032
config COMEDI_ADDI_APCI_2200
tristate "ADDI-DATA APCI_2200 support"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for ADDI-DATA APCI_2200 cards
@@ -635,7 +638,6 @@ config COMEDI_ADDI_APCI_3001
tristate "ADDI-DATA APCI_3001 support"
depends on VIRT_TO_BUS
select COMEDI_FC
- default N
---help---
Enable support for ADDI-DATA APCI_3001 cards
@@ -646,7 +648,6 @@ config COMEDI_ADDI_APCI_3120
tristate "ADDI-DATA APCI_3520 support"
depends on VIRT_TO_BUS
select COMEDI_FC
- default N
---help---
Enable support for ADDI-DATA APCI_3520 cards
@@ -656,7 +657,6 @@ config COMEDI_ADDI_APCI_3120
config COMEDI_ADDI_APCI_3501
tristate "ADDI-DATA APCI_3501 support"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for ADDI-DATA APCI_3501 cards
@@ -666,7 +666,6 @@ config COMEDI_ADDI_APCI_3501
config COMEDI_ADDI_APCI_3XXX
tristate "ADDI-DATA APCI_3xxx support"
depends on VIRT_TO_BUS
- default N
---help---
Enable support for ADDI-DATA APCI_3xxx cards
@@ -676,7 +675,6 @@ config COMEDI_ADDI_APCI_3XXX
config COMEDI_ADL_PCI6208
tristate "ADLink PCI-6208A support"
select COMEDI_8255
- default N
---help---
Enable support for ADLink PCI-6208A cards
@@ -685,7 +683,6 @@ config COMEDI_ADL_PCI6208
config COMEDI_ADL_PCI7230
tristate "ADLink PCI-7230 digital io board support"
- default N
---help---
Enable support for ADlink PCI-7230 digital io board support
@@ -694,7 +691,6 @@ config COMEDI_ADL_PCI7230
config COMEDI_ADL_PCI7296
tristate "ADLink PCI-7296 96 ch. digital io board support"
- default N
---help---
Enable support for ADlink PCI-7296 96 ch. digital io board support
@@ -703,7 +699,6 @@ config COMEDI_ADL_PCI7296
config COMEDI_ADL_PCI7432
tristate "ADLink PCI-7432 64 ch. isolated digital io board support"
- default N
---help---
Enable support for ADlink PCI-7432 64 ch. isolated digital io board
@@ -712,7 +707,6 @@ config COMEDI_ADL_PCI7432
config COMEDI_ADL_PCI8164
tristate "ADLink PCI-8164 4 Axes Motion Control board support"
- default N
---help---
Enable support for ADlink PCI-8164 4 Axes Motion Control board
@@ -722,7 +716,6 @@ config COMEDI_ADL_PCI8164
config COMEDI_ADL_PCI9111
tristate "ADLink PCI-9111HR support"
select COMEDI_FC
- default N
---help---
Enable support for ADlink PCI9111 cards
@@ -733,7 +726,6 @@ config COMEDI_ADL_PCI9118
tristate "ADLink PCI-9118DG, PCI-9118HG, PCI-9118HR support"
select COMEDI_FC
depends on VIRT_TO_BUS
- default N
---help---
Enable support for ADlink PCI-9118DG, PCI-9118HG, PCI-9118HR cards
@@ -742,7 +734,6 @@ config COMEDI_ADL_PCI9118
config COMEDI_ADV_PCI1710
tristate "Advantech PCI-171x, PCI-1720 and PCI-1731 support"
- default N
---help---
Enable support for Advantech PCI-1710, PCI-1710HG, PCI-1711,
PCI-1713, PCI-1720 and PCI-1731
@@ -752,7 +743,6 @@ config COMEDI_ADV_PCI1710
config COMEDI_ADV_PCI1723
tristate "Advantech PCI-1723 support"
- default N
---help---
Enable support for Advantech PCI-1723 cards
@@ -762,7 +752,6 @@ config COMEDI_ADV_PCI1723
config COMEDI_ADV_PCI_DIO
tristate "Advantech PCI DIO card support"
select COMEDI_8255
- default N
---help---
Enable support for Advantech PCI DIO cards
PCI-1730, PCI-1733, PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U,
@@ -772,31 +761,29 @@ config COMEDI_ADV_PCI_DIO
To compile this driver as a module, choose M here: the module will be
called adv_pci_dio.
-config COMEDI_AMPLC_DIO200
- tristate "Amplicon PC272E and PCI272 DIO board support"
- select COMEDI_8255
- default N
+config COMEDI_AMPLC_DIO200_PCI
+ tristate "Amplicon PCI215 and PCI272 DIO board support"
+ select COMEDI_AMPLC_DIO200
---help---
- Enable support for Amplicon PC272E and PCI272 DIO boards
+ Enable support for Amplicon PCI215 and PCI272 DIO boards.
To compile this driver as a module, choose M here: the module will be
called amplc_dio200.
-config COMEDI_AMPLC_PC236
- tristate "Amplicon PC36AT and PCI236 DIO board support"
- select COMEDI_8255
- default N
+config COMEDI_AMPLC_PC236_PCI
+ tristate "Amplicon PCI236 DIO board support"
+ select COMEDI_AMPLC_PC236
---help---
- Enable support for Amplicon PC36AT and PCI236 DIO boards
+ Enable support for Amplicon PCI236 DIO board.
To compile this driver as a module, choose M here: the module will be
called amplc_pc236.
-config COMEDI_AMPLC_PC263
- tristate "Amplicon PC263 and PCI263 relay board support"
- default N
+config COMEDI_AMPLC_PC263_PCI
+ tristate "Amplicon PCI263 relay board support"
+ select COMEDI_AMPLC_PC263
---help---
- Enable support for Amplicon PC263 and PCI263 relay boards
+ Enable support for Amplicon PCI263 relay board.
To compile this driver as a module, choose M here: the module will be
called amplc_pc263.
@@ -804,7 +791,6 @@ config COMEDI_AMPLC_PC263
config COMEDI_AMPLC_PCI224
tristate "Amplicon PCI224 and PCI234 support"
select COMEDI_FC
- default N
---help---
Enable support for Amplicon PCI224 and PCI234 AO boards
@@ -814,7 +800,6 @@ config COMEDI_AMPLC_PCI224
config COMEDI_AMPLC_PCI230
tristate "Amplicon PCI230 and PCI260 support"
select COMEDI_8255
- default N
---help---
Enable support for Amplicon PCI230 and PCI260 Multifunction I/O
boards
@@ -824,16 +809,23 @@ config COMEDI_AMPLC_PCI230
config COMEDI_CONTEC_PCI_DIO
tristate "Contec PIO1616L digital I/O board support"
- default N
---help---
Enable support for the Contec PIO1616L digital I/O board
To compile this driver as a module, choose M here: the module will be
called contec_pci_dio.
+config COMEDI_DAS08_PCI
+ tristate "DAS-08 PCI support"
+ select COMEDI_DAS08
+ ---help---
+ Enable support for PCI DAS-08 cards.
+
+ To compile this driver as a module, choose M here: the module will be
+ called das08.
+
config COMEDI_DT3000
tristate "Data Translation DT3000 series support"
- default N
---help---
Enable support for Data Translation DT3000 series
DT3001, DT3001-PGL, DT3002, DT3003, DT3003-PGL, DT3004, DT3005 and
@@ -844,7 +836,6 @@ config COMEDI_DT3000
config COMEDI_DYNA_PCI10XX
tristate "Dynalog PCI DAQ series support"
- default N
---help---
Enable support for Dynalog PCI DAQ series
PCI-1050
@@ -854,7 +845,6 @@ config COMEDI_DYNA_PCI10XX
config COMEDI_UNIOXX5
tristate "Fastwel UNIOxx-5 analog and digital io board support"
- default N
---help---
Enable support for Fastwel UNIOxx-5 (analog and digital i/o) boards
@@ -864,7 +854,6 @@ config COMEDI_UNIOXX5
config COMEDI_GSC_HPDI
tristate "General Standards PCI-HPDI32 / PMC-HPDI32 support"
select COMEDI_FC
- default N
---help---
Enable support for General Standards Corporation high speed parallel
digital interface rs485 boards PCI-HPDI32 and PMC-HPDI32.
@@ -875,7 +864,6 @@ config COMEDI_GSC_HPDI
config COMEDI_ICP_MULTI
tristate "Inova ICP_MULTI support"
- default N
---help---
Enable support for Inova ICP_MULTI card
@@ -884,7 +872,6 @@ config COMEDI_ICP_MULTI
config COMEDI_II_PCI20KC
tristate "Intelligent Instruments PCI-20001C carrier support"
- default N
---help---
Enable support for Intelligent Instruments PCI-20001C carrier
PCI-20001, PCI-20006 and PCI-20341
@@ -895,7 +882,6 @@ config COMEDI_II_PCI20KC
config COMEDI_DAQBOARD2000
tristate "IOtech DAQboard/2000 support"
select COMEDI_8255
- default N
---help---
Enable support for the IOtech DAQboard/2000
@@ -904,7 +890,6 @@ config COMEDI_DAQBOARD2000
config COMEDI_JR3_PCI
tristate "JR3/PCI force sensor board support"
- default N
---help---
Enable support for JR3/PCI force sensor boards
@@ -913,7 +898,6 @@ config COMEDI_JR3_PCI
config COMEDI_KE_COUNTER
tristate "Kolter-Electronic PCI Counter 1 card support"
- default N
---help---
Enable support for Kolter-Electronic PCI Counter 1 cards
@@ -924,7 +908,6 @@ config COMEDI_CB_PCIDAS64
tristate "MeasurementComputing PCI-DAS 64xx, 60xx, and 4020 support"
select COMEDI_8255
select COMEDI_FC
- default N
---help---
Enable support for ComputerBoards/MeasurementComputing PCI-DAS 64xx,
60xx, and 4020 series with the PLX 9080 PCI controller
@@ -936,7 +919,6 @@ config COMEDI_CB_PCIDAS
tristate "MeasurementComputing PCI-DAS support"
select COMEDI_8255
select COMEDI_FC
- default N
---help---
Enable support for ComputerBoards/MeasurementComputing PCI-DAS with
AMCC S5933 PCIcontroller: PCI-DAS1602/16, PCI-DAS1602/16jr,
@@ -949,7 +931,6 @@ config COMEDI_CB_PCIDAS
config COMEDI_CB_PCIDDA
tristate "MeasurementComputing PCI-DDA series support"
select COMEDI_8255
- default N
---help---
Enable support for ComputerBoards/MeasurementComputing PCI-DDA
series: PCI-DDA08/12, PCI-DDA04/12, PCI-DDA02/12, PCI-DDA08/16,
@@ -961,7 +942,6 @@ config COMEDI_CB_PCIDDA
config COMEDI_CB_PCIDIO
tristate "MeasurementComputing PCI-DIO series support"
select COMEDI_8255
- default N
---help---
Enable support for ComputerBoards/MeasurementComputing PCI-DIO series
PCI-DIO24, PCI-DIO24H and PCI-DIO48H
@@ -972,7 +952,6 @@ config COMEDI_CB_PCIDIO
config COMEDI_CB_PCIMDAS
tristate "MeasurementComputing PCIM-DAS1602/16 support"
select COMEDI_8255
- default N
---help---
Enable support for ComputerBoards/MeasurementComputing PCI Migration
series PCIM-DAS1602/16
@@ -983,7 +962,6 @@ config COMEDI_CB_PCIMDAS
config COMEDI_CB_PCIMDDA
tristate "MeasurementComputing PCIM-DDA06-16 support"
select COMEDI_8255
- default N
---help---
Enable support for ComputerBoards/MeasurementComputing PCIM-DDA06-16
@@ -992,7 +970,6 @@ config COMEDI_CB_PCIMDDA
config COMEDI_ME4000
tristate "Meilhaus ME-4000 support"
- default N
---help---
Enable support for Meilhaus PCI data acquisition cards
ME-4650, ME-4670i, ME-4680, ME-4680i and ME-4680is
@@ -1002,7 +979,6 @@ config COMEDI_ME4000
config COMEDI_ME_DAQ
tristate "Meilhaus ME-2000i, ME-2600i, ME-3000vm1 support"
- default N
---help---
Enable support for Meilhaus PCI data acquisition cards
ME-2000i, ME-2600i and ME-3000vm1
@@ -1013,7 +989,6 @@ config COMEDI_ME_DAQ
config COMEDI_NI_6527
tristate "NI 6527 support"
depends on COMEDI_MITE
- default N
---help---
Enable support for the National Instruments 6527 PCI card
@@ -1023,7 +998,6 @@ config COMEDI_NI_6527
config COMEDI_NI_65XX
tristate "NI 65xx static dio PCI card support"
depends on COMEDI_MITE
- default N
---help---
Enable support for National Instruments 65xx static dio boards.
Supported devices: National Instruments PCI-6509 (ni_65xx),
@@ -1037,7 +1011,6 @@ config COMEDI_NI_65XX
config COMEDI_NI_660X
tristate "NI 660x counter/timer PCI card support"
depends on COMEDI_NI_TIO && COMEDI_NI_COMMON
- default N
---help---
Enable support for National Instruments PCI-6601 (ni_660x), PCI-6602,
PXI-6602 and PXI-6608.
@@ -1048,7 +1021,6 @@ config COMEDI_NI_660X
config COMEDI_NI_670X
tristate "NI 670x PCI card support"
depends on COMEDI_MITE
- default N
---help---
Enable support for National Instruments PCI-6703 and PCI-6704
@@ -1059,7 +1031,6 @@ config COMEDI_NI_PCIDIO
tristate "NI PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503 support"
depends on COMEDI_MITE
select COMEDI_8255
- default N
---help---
Enable support for National Instruments PCI-DIO-32HS, PXI-6533,
PCI-DIO-96, PCI-DIO-96B, PXI-6508, PCI-6503, PCI-6503B, PCI-6503X,
@@ -1075,7 +1046,6 @@ config COMEDI_NI_PCIMIO
depends on COMEDI_NI_TIO && COMEDI_NI_COMMON
select COMEDI_8255
select COMEDI_FC
- default N
---help---
Enable support for National Instruments PCI-MIO-E series and M series
(all boards): PCI-MIO-16XE-10, PXI-6030E, PCI-MIO-16E-1,
@@ -1094,7 +1064,6 @@ config COMEDI_NI_PCIMIO
config COMEDI_RTD520
tristate "Real Time Devices PCI4520/DM7520 support"
select COMEDI_8255
- default N
---help---
Enable support for Real Time Devices PCI4520/DM7520
@@ -1103,7 +1072,6 @@ config COMEDI_RTD520
config COMEDI_S526
tristate "Sensoray s526 support"
- default N
---help---
Enable support for Sensoray s526
@@ -1113,7 +1081,6 @@ config COMEDI_S526
config COMEDI_S626
tristate "Sensoray 626 support"
select COMEDI_FC
- default N
---help---
Enable support for Sensoray 626
@@ -1122,7 +1089,6 @@ config COMEDI_S626
config COMEDI_SSV_DNP
tristate "SSV Embedded Systems DIL/Net-PC support"
- default N
---help---
Enable support for SSV Embedded Systems DIL/Net-PC
@@ -1134,7 +1100,6 @@ endif # COMEDI_PCI_DRIVERS
menuconfig COMEDI_PCMCIA_DRIVERS
tristate "Comedi PCMCIA drivers"
depends on COMEDI && (PCMCIA || PCCARD)
- default N
---help---
Enable comedi PCMCIA and PCCARD drivers to be built
@@ -1146,7 +1111,6 @@ if COMEDI_PCMCIA_DRIVERS && PCMCIA
config COMEDI_CB_DAS16_CS
tristate "CB DAS16 series PCMCIA support"
- default N
---help---
Enable support for the ComputerBoards/MeasurementComputing PCMCIA
cards DAS16/16, PCM-DAS16D/12 and PCM-DAS16s/16
@@ -1157,7 +1121,6 @@ config COMEDI_CB_DAS16_CS
config COMEDI_DAS08_CS
tristate "CB DAS08 PCMCIA support"
select COMEDI_DAS08
- default N
---help---
Enable support for the ComputerBoards/MeasurementComputing DAS-08
PCMCIA card
@@ -1168,7 +1131,6 @@ config COMEDI_DAS08_CS
config COMEDI_NI_DAQ_700_CS
tristate "NI DAQCard-700 PCMCIA support"
depends on COMEDI_NI_COMMON
- default N
---help---
Enable support for the National Instruments PCMCIA DAQCard-700 DIO
@@ -1179,7 +1141,6 @@ config COMEDI_NI_DAQ_DIO24_CS
tristate "NI DAQ-Card DIO-24 PCMCIA support"
depends on COMEDI_NI_COMMON
select COMEDI_8255
- default N
---help---
Enable support for the National Instruments PCMCIA DAQ-Card DIO-24
@@ -1189,7 +1150,6 @@ config COMEDI_NI_DAQ_DIO24_CS
config COMEDI_NI_LABPC_CS
tristate "NI DAQCard-1200 PCMCIA support"
depends on COMEDI_NI_LABPC
- default N
---help---
Enable support for the National Instruments PCMCIA DAQCard-1200
@@ -1201,7 +1161,6 @@ config COMEDI_NI_MIO_CS
depends on COMEDI_NI_TIO && COMEDI_NI_COMMON
select COMEDI_8255
select COMEDI_FC
- default N
---help---
Enable support for the National Instruments PCMCIA DAQCard E series
DAQCard-ai-16xe-50, DAQCard-ai-16e-4, DAQCard-6062E, DAQCard-6024E
@@ -1212,7 +1171,6 @@ config COMEDI_NI_MIO_CS
config COMEDI_QUATECH_DAQP_CS
tristate "Quatech DAQP PCMCIA data capture card support"
- default N
---help---
Enable support for the Quatech DAQP PCMCIA data capture cards
DAQP-208 and DAQP-308
@@ -1225,7 +1183,6 @@ endif # COMEDI_PCMCIA_DRIVERS
menuconfig COMEDI_USB_DRIVERS
tristate "Comedi USB drivers"
depends on COMEDI && USB
- default N
---help---
Enable comedi USB drivers to be built
@@ -1237,7 +1194,6 @@ if COMEDI_USB_DRIVERS && USB
config COMEDI_DT9812
tristate "DataTranslation DT9812 USB module support"
- default N
---help---
Enable support for the Data Translation DT9812 USB module
@@ -1246,7 +1202,6 @@ config COMEDI_DT9812
config COMEDI_USBDUX
tristate "ITL USB-DUX-D support"
- default N
---help---
Enable support for the Incite Technology Ltd USB-DUX-D Board
@@ -1256,7 +1211,6 @@ config COMEDI_USBDUX
config COMEDI_USBDUXFAST
tristate "ITL USB-DUXfast support"
select COMEDI_FC
- default N
---help---
Enable support for the Incite Technology Ltd USB-DUXfast Board
@@ -1266,7 +1220,6 @@ config COMEDI_USBDUXFAST
config COMEDI_USBDUXSIGMA
tristate "ITL USB-DUXsigma support"
select COMEDI_FC
- default N
---help---
Enable support for the Incite Technology Ltd USB-DUXsigma Board
@@ -1275,7 +1228,6 @@ config COMEDI_USBDUXSIGMA
config COMEDI_VMK80XX
tristate "Velleman VM110/VM140 USB Board support"
- default N
---help---
Build the Velleman USB Board Low-Level Driver supporting the
K8055/K8061 aka VM110/VM140 devices
@@ -1288,7 +1240,6 @@ endif # COMEDI_USB_DRIVERS
menuconfig COMEDI_NI_COMMON
tristate "Comedi National Instruments card support"
depends on COMEDI
- default N
---help---
Enable comedi support for National Instruments cards.
Modules in this section are used by many comedi NI drivers.
@@ -1302,7 +1253,6 @@ if COMEDI_NI_COMMON
config COMEDI_MITE
tristate "NI Mite PCI interface chip support"
depends on PCI
- default N
---help---
Enable support for National Instruments Mite PCI interface chip
@@ -1312,7 +1262,6 @@ config COMEDI_MITE
config COMEDI_NI_TIO
tristate "NI general purpose counter support"
depends on COMEDI_MITE
- default N
---help---
Enable support for National Instruments general purpose counters.
This module is not used directly by end-users. Rather, it
@@ -1328,7 +1277,6 @@ config COMEDI_NI_LABPC
select COMEDI_8255
select COMEDI_FC
depends on VIRT_TO_BUS
- default N
---help---
Enable support for National Instruments Lab-PC and compatibles
Lab-PC-1200, Lab-PC-1200AI, Lab-PC+ and PCI-1200.
@@ -1343,7 +1291,6 @@ endif # COMEDI_NI_COMMON
config COMEDI_8255
tristate "Generic 8255 support"
depends on COMEDI
- default N
---help---
Enable generic 8255 support.
@@ -1357,24 +1304,9 @@ config COMEDI_8255
To compile this driver as a module, choose M here: the module will be
called 8255.
-config COMEDI_DAS08
- tristate "DAS-08 compatible support"
- depends on COMEDI
- select COMEDI_8255
- default N
- ---help---
- Enable support for DAS08 and compatible ISA, PC/104 and PCI cards.
-
- Note that PCMCIA DAS08 cards are not directly supported by this
- driver, and need a separate driver as a wrapper.
-
- To compile this driver as a module, choose M here: the module will be
- called das08.
-
config COMEDI_FC
tristate "Comedi shared functions for low-level driver support"
depends on COMEDI
- default N
---help---
Enable support for shared functions for low-level drivers.
This module is not used directly by end-users. Rather, it
@@ -1382,3 +1314,22 @@ config COMEDI_FC
To compile this driver as a module, choose M here: the module will be
called comedi_fc.
+
+config COMEDI_AMPLC_DIO200
+ tristate
+ depends on COMEDI
+ select COMEDI_8255
+
+config COMEDI_AMPLC_PC236
+ tristate
+ depends on COMEDI
+ select COMEDI_8255
+
+config COMEDI_AMPLC_PC263
+ tristate
+ depends on COMEDI
+
+config COMEDI_DAS08
+ tristate
+ depends on COMEDI
+ select COMEDI_8255
diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
index 14ea35ac0156..8ea55aef10a7 100644
--- a/drivers/staging/comedi/comedi.h
+++ b/drivers/staging/comedi/comedi.h
@@ -465,7 +465,7 @@
/* only relevant to kernel modules. */
#define COMEDI_CB_EOS 1 /* end of scan */
-#define COMEDI_CB_EOA 2 /* end of acquisition */
+#define COMEDI_CB_EOA 2 /* end of acquisition/output */
#define COMEDI_CB_BLOCK 4 /* data has arrived:
* wakes up read() / write() */
#define COMEDI_CB_EOBUF 8 /* DEPRECATED: end of buffer */
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 9bcf87ae4c00..76776571ed91 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -58,14 +58,35 @@ MODULE_LICENSE("GPL");
#ifdef CONFIG_COMEDI_DEBUG
int comedi_debug;
EXPORT_SYMBOL(comedi_debug);
-module_param(comedi_debug, int, 0644);
+module_param(comedi_debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(comedi_debug,
+ "enable comedi core and driver debugging if non-zero (default 0)"
+ );
#endif
bool comedi_autoconfig = 1;
-module_param(comedi_autoconfig, bool, 0444);
+module_param(comedi_autoconfig, bool, S_IRUGO);
+MODULE_PARM_DESC(comedi_autoconfig,
+ "enable drivers to auto-configure comedi devices (default 1)");
static int comedi_num_legacy_minors;
-module_param(comedi_num_legacy_minors, int, 0444);
+module_param(comedi_num_legacy_minors, int, S_IRUGO);
+MODULE_PARM_DESC(comedi_num_legacy_minors,
+ "number of comedi minor devices to reserve for non-auto-configured devices (default 0)"
+ );
+
+unsigned int comedi_default_buf_size_kb = CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB;
+module_param(comedi_default_buf_size_kb, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(comedi_default_buf_size_kb,
+ "default asynchronous buffer size in KiB (default "
+ __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB) ")");
+
+unsigned int comedi_default_buf_maxsize_kb
+ = CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB;
+module_param(comedi_default_buf_maxsize_kb, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(comedi_default_buf_maxsize_kb,
+ "default maximum size of asynchronous buffer in KiB (default "
+ __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB) ")");
static DEFINE_SPINLOCK(comedi_file_info_table_lock);
static struct comedi_device_file_info
@@ -108,15 +129,283 @@ static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
static int comedi_fasync(int fd, struct file *file, int on);
static int is_device_busy(struct comedi_device *dev);
+
static int resize_async_buffer(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_async *async, unsigned new_size);
+ struct comedi_async *async, unsigned new_size)
+{
+ int retval;
+
+ if (new_size > async->max_bufsize)
+ return -EPERM;
+
+ if (s->busy) {
+ DPRINTK("subdevice is busy, cannot resize buffer\n");
+ return -EBUSY;
+ }
+ if (async->mmap_count) {
+ DPRINTK("subdevice is mmapped, cannot resize buffer\n");
+ return -EBUSY;
+ }
+
+ if (!async->prealloc_buf)
+ return -EINVAL;
+
+ /* make sure buffer is an integral number of pages
+ * (we round up) */
+ new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
+
+ retval = comedi_buf_alloc(dev, s, new_size);
+ if (retval < 0)
+ return retval;
+
+ if (s->buf_change) {
+ retval = s->buf_change(dev, s, new_size);
+ if (retval < 0)
+ return retval;
+ }
+
+ DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
+ dev->minor, (int)(s - dev->subdevices), async->prealloc_bufsz);
+ return 0;
+}
+
+/* sysfs attribute files */
+
+static const unsigned bytes_per_kibi = 1024;
+
+static ssize_t show_max_read_buffer_kb(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t retval;
+ struct comedi_device_file_info *info = dev_get_drvdata(dev);
+ unsigned max_buffer_size_kb = 0;
+ struct comedi_subdevice *const read_subdevice =
+ comedi_get_read_subdevice(info);
+
+ mutex_lock(&info->device->mutex);
+ if (read_subdevice &&
+ (read_subdevice->subdev_flags & SDF_CMD_READ) &&
+ read_subdevice->async) {
+ max_buffer_size_kb = read_subdevice->async->max_bufsize /
+ bytes_per_kibi;
+ }
+ retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
+ mutex_unlock(&info->device->mutex);
+
+ return retval;
+}
+
+static ssize_t store_max_read_buffer_kb(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct comedi_device_file_info *info = dev_get_drvdata(dev);
+ unsigned int new_max_size_kb;
+ unsigned int new_max_size;
+ int ret;
+ struct comedi_subdevice *const read_subdevice =
+ comedi_get_read_subdevice(info);
+
+ ret = kstrtouint(buf, 10, &new_max_size_kb);
+ if (ret)
+ return ret;
+ if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
+ return -EINVAL;
+ new_max_size = new_max_size_kb * bytes_per_kibi;
+
+ mutex_lock(&info->device->mutex);
+ if (read_subdevice == NULL ||
+ (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
+ read_subdevice->async == NULL) {
+ mutex_unlock(&info->device->mutex);
+ return -EINVAL;
+ }
+ read_subdevice->async->max_bufsize = new_max_size;
+ mutex_unlock(&info->device->mutex);
+
+ return count;
+}
+
+static ssize_t show_read_buffer_kb(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t retval;
+ struct comedi_device_file_info *info = dev_get_drvdata(dev);
+ unsigned buffer_size_kb = 0;
+ struct comedi_subdevice *const read_subdevice =
+ comedi_get_read_subdevice(info);
+
+ mutex_lock(&info->device->mutex);
+ if (read_subdevice &&
+ (read_subdevice->subdev_flags & SDF_CMD_READ) &&
+ read_subdevice->async) {
+ buffer_size_kb = read_subdevice->async->prealloc_bufsz /
+ bytes_per_kibi;
+ }
+ retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
+ mutex_unlock(&info->device->mutex);
+
+ return retval;
+}
+
+static ssize_t store_read_buffer_kb(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct comedi_device_file_info *info = dev_get_drvdata(dev);
+ unsigned int new_size_kb;
+ unsigned int new_size;
+ int retval;
+ int ret;
+ struct comedi_subdevice *const read_subdevice =
+ comedi_get_read_subdevice(info);
+
+ ret = kstrtouint(buf, 10, &new_size_kb);
+ if (ret)
+ return ret;
+ if (new_size_kb > (UINT_MAX / bytes_per_kibi))
+ return -EINVAL;
+ new_size = new_size_kb * bytes_per_kibi;
+
+ mutex_lock(&info->device->mutex);
+ if (read_subdevice == NULL ||
+ (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
+ read_subdevice->async == NULL) {
+ mutex_unlock(&info->device->mutex);
+ return -EINVAL;
+ }
+ retval = resize_async_buffer(info->device, read_subdevice,
+ read_subdevice->async, new_size);
+ mutex_unlock(&info->device->mutex);
+
+ if (retval < 0)
+ return retval;
+ return count;
+}
+
+static ssize_t show_max_write_buffer_kb(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t retval;
+ struct comedi_device_file_info *info = dev_get_drvdata(dev);
+ unsigned max_buffer_size_kb = 0;
+ struct comedi_subdevice *const write_subdevice =
+ comedi_get_write_subdevice(info);
+
+ mutex_lock(&info->device->mutex);
+ if (write_subdevice &&
+ (write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
+ write_subdevice->async) {
+ max_buffer_size_kb = write_subdevice->async->max_bufsize /
+ bytes_per_kibi;
+ }
+ retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
+ mutex_unlock(&info->device->mutex);
+
+ return retval;
+}
+
+static ssize_t store_max_write_buffer_kb(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct comedi_device_file_info *info = dev_get_drvdata(dev);
+ unsigned int new_max_size_kb;
+ unsigned int new_max_size;
+ int ret;
+ struct comedi_subdevice *const write_subdevice =
+ comedi_get_write_subdevice(info);
+
+ ret = kstrtouint(buf, 10, &new_max_size_kb);
+ if (ret)
+ return ret;
+ if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
+ return -EINVAL;
+ new_max_size = new_max_size_kb * bytes_per_kibi;
+
+ mutex_lock(&info->device->mutex);
+ if (write_subdevice == NULL ||
+ (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
+ write_subdevice->async == NULL) {
+ mutex_unlock(&info->device->mutex);
+ return -EINVAL;
+ }
+ write_subdevice->async->max_bufsize = new_max_size;
+ mutex_unlock(&info->device->mutex);
+
+ return count;
+}
+
+static ssize_t show_write_buffer_kb(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t retval;
+ struct comedi_device_file_info *info = dev_get_drvdata(dev);
+ unsigned buffer_size_kb = 0;
+ struct comedi_subdevice *const write_subdevice =
+ comedi_get_write_subdevice(info);
+
+ mutex_lock(&info->device->mutex);
+ if (write_subdevice &&
+ (write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
+ write_subdevice->async) {
+ buffer_size_kb = write_subdevice->async->prealloc_bufsz /
+ bytes_per_kibi;
+ }
+ retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
+ mutex_unlock(&info->device->mutex);
-/* declarations for sysfs attribute files */
-static struct device_attribute dev_attr_max_read_buffer_kb;
-static struct device_attribute dev_attr_read_buffer_kb;
-static struct device_attribute dev_attr_max_write_buffer_kb;
-static struct device_attribute dev_attr_write_buffer_kb;
+ return retval;
+}
+
+static ssize_t store_write_buffer_kb(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct comedi_device_file_info *info = dev_get_drvdata(dev);
+ unsigned int new_size_kb;
+ unsigned int new_size;
+ int retval;
+ int ret;
+ struct comedi_subdevice *const write_subdevice =
+ comedi_get_write_subdevice(info);
+
+ ret = kstrtouint(buf, 10, &new_size_kb);
+ if (ret)
+ return ret;
+ if (new_size_kb > (UINT_MAX / bytes_per_kibi))
+ return -EINVAL;
+ new_size = ((uint64_t) new_size_kb) * bytes_per_kibi;
+
+ mutex_lock(&info->device->mutex);
+ if (write_subdevice == NULL ||
+ (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
+ write_subdevice->async == NULL) {
+ mutex_unlock(&info->device->mutex);
+ return -EINVAL;
+ }
+ retval = resize_async_buffer(info->device, write_subdevice,
+ write_subdevice->async, new_size);
+ mutex_unlock(&info->device->mutex);
+
+ if (retval < 0)
+ return retval;
+ return count;
+}
+
+static struct device_attribute comedi_dev_attrs[] = {
+ __ATTR(max_read_buffer_kb, S_IRUGO | S_IWUSR,
+ show_max_read_buffer_kb, store_max_read_buffer_kb),
+ __ATTR(read_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP,
+ show_read_buffer_kb, store_read_buffer_kb),
+ __ATTR(max_write_buffer_kb, S_IRUGO | S_IWUSR,
+ show_max_write_buffer_kb, store_max_write_buffer_kb),
+ __ATTR(write_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP,
+ show_write_buffer_kb, store_write_buffer_kb),
+ __ATTR_NULL
+};
static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
@@ -280,7 +569,7 @@ static int do_devconfig_ioctl(struct comedi_device *dev,
if (ret == 0) {
if (!try_module_get(dev->driver->module)) {
comedi_device_detach(dev);
- return -ENOSYS;
+ ret = -ENOSYS;
}
}
@@ -1545,7 +1834,7 @@ done:
return retval;
}
-static unsigned int comedi_poll(struct file *file, poll_table * wait)
+static unsigned int comedi_poll(struct file *file, poll_table *wait)
{
unsigned int mask = 0;
const unsigned minor = iminor(file->f_dentry->d_inode);
@@ -2054,6 +2343,8 @@ static int __init comedi_init(void)
return PTR_ERR(comedi_class);
}
+ comedi_class->dev_attrs = comedi_dev_attrs;
+
/* XXX requires /proc interface */
comedi_proc_init();
@@ -2192,11 +2483,9 @@ static void comedi_device_cleanup(struct comedi_device *dev)
int comedi_alloc_board_minor(struct device *hardware_device)
{
- unsigned long flags;
struct comedi_device_file_info *info;
struct device *csdev;
unsigned i;
- int retval;
info = kzalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
if (info == NULL)
@@ -2206,15 +2495,16 @@ int comedi_alloc_board_minor(struct device *hardware_device)
kfree(info);
return -ENOMEM;
}
+ info->hardware_device = hardware_device;
comedi_device_init(info->device);
- spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+ spin_lock(&comedi_file_info_table_lock);
for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) {
if (comedi_file_info_table[i] == NULL) {
comedi_file_info_table[i] = info;
break;
}
}
- spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+ spin_unlock(&comedi_file_info_table_lock);
if (i == COMEDI_NUM_BOARD_MINORS) {
comedi_device_cleanup(info->device);
kfree(info->device);
@@ -2230,55 +2520,19 @@ int comedi_alloc_board_minor(struct device *hardware_device)
if (!IS_ERR(csdev))
info->device->class_dev = csdev;
dev_set_drvdata(csdev, info);
- retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb);
- if (retval) {
- printk(KERN_ERR
- "comedi: "
- "failed to create sysfs attribute file \"%s\".\n",
- dev_attr_max_read_buffer_kb.attr.name);
- comedi_free_board_minor(i);
- return retval;
- }
- retval = device_create_file(csdev, &dev_attr_read_buffer_kb);
- if (retval) {
- printk(KERN_ERR
- "comedi: "
- "failed to create sysfs attribute file \"%s\".\n",
- dev_attr_read_buffer_kb.attr.name);
- comedi_free_board_minor(i);
- return retval;
- }
- retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb);
- if (retval) {
- printk(KERN_ERR
- "comedi: "
- "failed to create sysfs attribute file \"%s\".\n",
- dev_attr_max_write_buffer_kb.attr.name);
- comedi_free_board_minor(i);
- return retval;
- }
- retval = device_create_file(csdev, &dev_attr_write_buffer_kb);
- if (retval) {
- printk(KERN_ERR
- "comedi: "
- "failed to create sysfs attribute file \"%s\".\n",
- dev_attr_write_buffer_kb.attr.name);
- comedi_free_board_minor(i);
- return retval;
- }
+
return i;
}
void comedi_free_board_minor(unsigned minor)
{
- unsigned long flags;
struct comedi_device_file_info *info;
BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
- spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+ spin_lock(&comedi_file_info_table_lock);
info = comedi_file_info_table[minor];
comedi_file_info_table[minor] = NULL;
- spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+ spin_unlock(&comedi_file_info_table_lock);
if (info) {
struct comedi_device *dev = info->device;
@@ -2294,14 +2548,29 @@ void comedi_free_board_minor(unsigned minor)
}
}
+int comedi_find_board_minor(struct device *hardware_device)
+{
+ int minor;
+ struct comedi_device_file_info *info;
+
+ for (minor = 0; minor < COMEDI_NUM_BOARD_MINORS; minor++) {
+ spin_lock(&comedi_file_info_table_lock);
+ info = comedi_file_info_table[minor];
+ if (info && info->hardware_device == hardware_device) {
+ spin_unlock(&comedi_file_info_table_lock);
+ return minor;
+ }
+ spin_unlock(&comedi_file_info_table_lock);
+ }
+ return -ENODEV;
+}
+
int comedi_alloc_subdevice_minor(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- unsigned long flags;
struct comedi_device_file_info *info;
struct device *csdev;
unsigned i;
- int retval;
info = kmalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
if (info == NULL)
@@ -2309,14 +2578,14 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev,
info->device = dev;
info->read_subdevice = s;
info->write_subdevice = s;
- spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+ spin_lock(&comedi_file_info_table_lock);
for (i = COMEDI_FIRST_SUBDEVICE_MINOR; i < COMEDI_NUM_MINORS; ++i) {
if (comedi_file_info_table[i] == NULL) {
comedi_file_info_table[i] = info;
break;
}
}
- spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+ spin_unlock(&comedi_file_info_table_lock);
if (i == COMEDI_NUM_MINORS) {
kfree(info);
printk(KERN_ERR
@@ -2331,48 +2600,12 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev,
if (!IS_ERR(csdev))
s->class_dev = csdev;
dev_set_drvdata(csdev, info);
- retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb);
- if (retval) {
- printk(KERN_ERR
- "comedi: "
- "failed to create sysfs attribute file \"%s\".\n",
- dev_attr_max_read_buffer_kb.attr.name);
- comedi_free_subdevice_minor(s);
- return retval;
- }
- retval = device_create_file(csdev, &dev_attr_read_buffer_kb);
- if (retval) {
- printk(KERN_ERR
- "comedi: "
- "failed to create sysfs attribute file \"%s\".\n",
- dev_attr_read_buffer_kb.attr.name);
- comedi_free_subdevice_minor(s);
- return retval;
- }
- retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb);
- if (retval) {
- printk(KERN_ERR
- "comedi: "
- "failed to create sysfs attribute file \"%s\".\n",
- dev_attr_max_write_buffer_kb.attr.name);
- comedi_free_subdevice_minor(s);
- return retval;
- }
- retval = device_create_file(csdev, &dev_attr_write_buffer_kb);
- if (retval) {
- printk(KERN_ERR
- "comedi: "
- "failed to create sysfs attribute file \"%s\".\n",
- dev_attr_write_buffer_kb.attr.name);
- comedi_free_subdevice_minor(s);
- return retval;
- }
+
return i;
}
void comedi_free_subdevice_minor(struct comedi_subdevice *s)
{
- unsigned long flags;
struct comedi_device_file_info *info;
if (s == NULL)
@@ -2383,10 +2616,10 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s)
BUG_ON(s->minor >= COMEDI_NUM_MINORS);
BUG_ON(s->minor < COMEDI_FIRST_SUBDEVICE_MINOR);
- spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+ spin_lock(&comedi_file_info_table_lock);
info = comedi_file_info_table[s->minor];
comedi_file_info_table[s->minor] = NULL;
- spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+ spin_unlock(&comedi_file_info_table_lock);
if (s->class_dev) {
device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
@@ -2397,310 +2630,12 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s)
struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor)
{
- unsigned long flags;
struct comedi_device_file_info *info;
BUG_ON(minor >= COMEDI_NUM_MINORS);
- spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+ spin_lock(&comedi_file_info_table_lock);
info = comedi_file_info_table[minor];
- spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+ spin_unlock(&comedi_file_info_table_lock);
return info;
}
EXPORT_SYMBOL_GPL(comedi_get_device_file_info);
-
-static int resize_async_buffer(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_async *async, unsigned new_size)
-{
- int retval;
-
- if (new_size > async->max_bufsize)
- return -EPERM;
-
- if (s->busy) {
- DPRINTK("subdevice is busy, cannot resize buffer\n");
- return -EBUSY;
- }
- if (async->mmap_count) {
- DPRINTK("subdevice is mmapped, cannot resize buffer\n");
- return -EBUSY;
- }
-
- if (!async->prealloc_buf)
- return -EINVAL;
-
- /* make sure buffer is an integral number of pages
- * (we round up) */
- new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
-
- retval = comedi_buf_alloc(dev, s, new_size);
- if (retval < 0)
- return retval;
-
- if (s->buf_change) {
- retval = s->buf_change(dev, s, new_size);
- if (retval < 0)
- return retval;
- }
-
- DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
- dev->minor, (int)(s - dev->subdevices), async->prealloc_bufsz);
- return 0;
-}
-
-/* sysfs attribute files */
-
-static const unsigned bytes_per_kibi = 1024;
-
-static ssize_t show_max_read_buffer_kb(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- ssize_t retval;
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- unsigned max_buffer_size_kb = 0;
- struct comedi_subdevice *const read_subdevice =
- comedi_get_read_subdevice(info);
-
- mutex_lock(&info->device->mutex);
- if (read_subdevice &&
- (read_subdevice->subdev_flags & SDF_CMD_READ) &&
- read_subdevice->async) {
- max_buffer_size_kb = read_subdevice->async->max_bufsize /
- bytes_per_kibi;
- }
- retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
- mutex_unlock(&info->device->mutex);
-
- return retval;
-}
-
-static ssize_t store_max_read_buffer_kb(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- unsigned int new_max_size_kb;
- unsigned int new_max_size;
- int ret;
- struct comedi_subdevice *const read_subdevice =
- comedi_get_read_subdevice(info);
-
- ret = kstrtouint(buf, 10, &new_max_size_kb);
- if (ret)
- return ret;
- if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
- return -EINVAL;
- new_max_size = new_max_size_kb * bytes_per_kibi;
-
- mutex_lock(&info->device->mutex);
- if (read_subdevice == NULL ||
- (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
- read_subdevice->async == NULL) {
- mutex_unlock(&info->device->mutex);
- return -EINVAL;
- }
- read_subdevice->async->max_bufsize = new_max_size;
- mutex_unlock(&info->device->mutex);
-
- return count;
-}
-
-static struct device_attribute dev_attr_max_read_buffer_kb = {
- .attr = {
- .name = "max_read_buffer_kb",
- .mode = S_IRUGO | S_IWUSR},
- .show = &show_max_read_buffer_kb,
- .store = &store_max_read_buffer_kb
-};
-
-static ssize_t show_read_buffer_kb(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- ssize_t retval;
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- unsigned buffer_size_kb = 0;
- struct comedi_subdevice *const read_subdevice =
- comedi_get_read_subdevice(info);
-
- mutex_lock(&info->device->mutex);
- if (read_subdevice &&
- (read_subdevice->subdev_flags & SDF_CMD_READ) &&
- read_subdevice->async) {
- buffer_size_kb = read_subdevice->async->prealloc_bufsz /
- bytes_per_kibi;
- }
- retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
- mutex_unlock(&info->device->mutex);
-
- return retval;
-}
-
-static ssize_t store_read_buffer_kb(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- unsigned int new_size_kb;
- unsigned int new_size;
- int retval;
- int ret;
- struct comedi_subdevice *const read_subdevice =
- comedi_get_read_subdevice(info);
-
- ret = kstrtouint(buf, 10, &new_size_kb);
- if (ret)
- return ret;
- if (new_size_kb > (UINT_MAX / bytes_per_kibi))
- return -EINVAL;
- new_size = new_size_kb * bytes_per_kibi;
-
- mutex_lock(&info->device->mutex);
- if (read_subdevice == NULL ||
- (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
- read_subdevice->async == NULL) {
- mutex_unlock(&info->device->mutex);
- return -EINVAL;
- }
- retval = resize_async_buffer(info->device, read_subdevice,
- read_subdevice->async, new_size);
- mutex_unlock(&info->device->mutex);
-
- if (retval < 0)
- return retval;
- return count;
-}
-
-static struct device_attribute dev_attr_read_buffer_kb = {
- .attr = {
- .name = "read_buffer_kb",
- .mode = S_IRUGO | S_IWUSR | S_IWGRP},
- .show = &show_read_buffer_kb,
- .store = &store_read_buffer_kb
-};
-
-static ssize_t show_max_write_buffer_kb(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- ssize_t retval;
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- unsigned max_buffer_size_kb = 0;
- struct comedi_subdevice *const write_subdevice =
- comedi_get_write_subdevice(info);
-
- mutex_lock(&info->device->mutex);
- if (write_subdevice &&
- (write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
- write_subdevice->async) {
- max_buffer_size_kb = write_subdevice->async->max_bufsize /
- bytes_per_kibi;
- }
- retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
- mutex_unlock(&info->device->mutex);
-
- return retval;
-}
-
-static ssize_t store_max_write_buffer_kb(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- unsigned int new_max_size_kb;
- unsigned int new_max_size;
- int ret;
- struct comedi_subdevice *const write_subdevice =
- comedi_get_write_subdevice(info);
-
- ret = kstrtouint(buf, 10, &new_max_size_kb);
- if (ret)
- return ret;
- if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
- return -EINVAL;
- new_max_size = new_max_size_kb * bytes_per_kibi;
-
- mutex_lock(&info->device->mutex);
- if (write_subdevice == NULL ||
- (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
- write_subdevice->async == NULL) {
- mutex_unlock(&info->device->mutex);
- return -EINVAL;
- }
- write_subdevice->async->max_bufsize = new_max_size;
- mutex_unlock(&info->device->mutex);
-
- return count;
-}
-
-static struct device_attribute dev_attr_max_write_buffer_kb = {
- .attr = {
- .name = "max_write_buffer_kb",
- .mode = S_IRUGO | S_IWUSR},
- .show = &show_max_write_buffer_kb,
- .store = &store_max_write_buffer_kb
-};
-
-static ssize_t show_write_buffer_kb(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- ssize_t retval;
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- unsigned buffer_size_kb = 0;
- struct comedi_subdevice *const write_subdevice =
- comedi_get_write_subdevice(info);
-
- mutex_lock(&info->device->mutex);
- if (write_subdevice &&
- (write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
- write_subdevice->async) {
- buffer_size_kb = write_subdevice->async->prealloc_bufsz /
- bytes_per_kibi;
- }
- retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
- mutex_unlock(&info->device->mutex);
-
- return retval;
-}
-
-static ssize_t store_write_buffer_kb(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- unsigned int new_size_kb;
- unsigned int new_size;
- int retval;
- int ret;
- struct comedi_subdevice *const write_subdevice =
- comedi_get_write_subdevice(info);
-
- ret = kstrtouint(buf, 10, &new_size_kb);
- if (ret)
- return ret;
- if (new_size_kb > (UINT_MAX / bytes_per_kibi))
- return -EINVAL;
- new_size = ((uint64_t) new_size_kb) * bytes_per_kibi;
-
- mutex_lock(&info->device->mutex);
- if (write_subdevice == NULL ||
- (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
- write_subdevice->async == NULL) {
- mutex_unlock(&info->device->mutex);
- return -EINVAL;
- }
- retval = resize_async_buffer(info->device, write_subdevice,
- write_subdevice->async, new_size);
- mutex_unlock(&info->device->mutex);
-
- if (retval < 0)
- return retval;
- return count;
-}
-
-static struct device_attribute dev_attr_write_buffer_kb = {
- .attr = {
- .name = "write_buffer_kb",
- .mode = S_IRUGO | S_IWUSR | S_IWGRP},
- .show = &show_write_buffer_kb,
- .store = &store_write_buffer_kb
-};
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index 7a0d4bcbc355..134be93eaa6d 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -180,13 +180,18 @@ struct comedi_async {
unsigned int x);
};
+struct pci_dev;
+struct usb_interface;
+
struct comedi_driver {
struct comedi_driver *next;
const char *driver_name;
struct module *module;
int (*attach) (struct comedi_device *, struct comedi_devconfig *);
- int (*detach) (struct comedi_device *);
+ void (*detach) (struct comedi_device *);
+ int (*attach_pci) (struct comedi_device *, struct pci_dev *);
+ int (*attach_usb) (struct comedi_device *, struct usb_interface *);
/* number of elements in board_name and board_id arrays */
unsigned int num_names;
@@ -230,10 +235,16 @@ struct comedi_device {
void (*close) (struct comedi_device *dev);
};
+static inline const void *comedi_board(struct comedi_device *dev)
+{
+ return dev->board_ptr;
+}
+
struct comedi_device_file_info {
struct comedi_device *device;
struct comedi_subdevice *read_subdevice;
struct comedi_subdevice *write_subdevice;
+ struct device *hardware_device;
};
#ifdef CONFIG_COMEDI_DEBUG
@@ -287,6 +298,56 @@ int comedi_device_attach(struct comedi_device *dev,
int comedi_driver_register(struct comedi_driver *);
int comedi_driver_unregister(struct comedi_driver *);
+/**
+ * module_comedi_driver() - Helper macro for registering a comedi driver
+ * @__comedi_driver: comedi_driver struct
+ *
+ * Helper macro for comedi drivers which do not do anything special in module
+ * init/exit. This eliminates a lot of boilerplate. Each module may only use
+ * this macro once, and calling it replaces module_init() and module_exit().
+ */
+#define module_comedi_driver(__comedi_driver) \
+ module_driver(__comedi_driver, comedi_driver_register, \
+ comedi_driver_unregister)
+
+struct pci_driver;
+
+int comedi_pci_driver_register(struct comedi_driver *, struct pci_driver *);
+void comedi_pci_driver_unregister(struct comedi_driver *, struct pci_driver *);
+
+/**
+ * module_comedi_pci_driver() - Helper macro for registering a comedi PCI driver
+ * @__comedi_driver: comedi_driver struct
+ * @__pci_driver: pci_driver struct
+ *
+ * Helper macro for comedi PCI drivers which do not do anything special
+ * in module init/exit. This eliminates a lot of boilerplate. Each
+ * module may only use this macro once, and calling it replaces
+ * module_init() and module_exit()
+ */
+#define module_comedi_pci_driver(__comedi_driver, __pci_driver) \
+ module_driver(__comedi_driver, comedi_pci_driver_register, \
+ comedi_pci_driver_unregister, &(__pci_driver))
+
+struct usb_driver;
+
+int comedi_usb_driver_register(struct comedi_driver *, struct usb_driver *);
+void comedi_usb_driver_unregister(struct comedi_driver *, struct usb_driver *);
+
+/**
+ * module_comedi_usb_driver() - Helper macro for registering a comedi USB driver
+ * @__comedi_driver: comedi_driver struct
+ * @__usb_driver: usb_driver struct
+ *
+ * Helper macro for comedi USB drivers which do not do anything special
+ * in module init/exit. This eliminates a lot of boilerplate. Each
+ * module may only use this macro once, and calling it replaces
+ * module_init() and module_exit()
+ */
+#define module_comedi_usb_driver(__comedi_driver, __usb_driver) \
+ module_driver(__comedi_driver, comedi_usb_driver_register, \
+ comedi_usb_driver_unregister, &(__usb_driver))
+
void init_polling(void);
void cleanup_polling(void);
void start_polling(struct comedi_device *);
@@ -456,11 +517,12 @@ static inline void *comedi_aux_data(int options[], int n)
int comedi_alloc_subdevice_minor(struct comedi_device *dev,
struct comedi_subdevice *s);
void comedi_free_subdevice_minor(struct comedi_subdevice *s);
-int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name);
+int comedi_pci_auto_config(struct pci_dev *pcidev,
+ struct comedi_driver *driver);
void comedi_pci_auto_unconfig(struct pci_dev *pcidev);
-struct usb_device; /* forward declaration */
-int comedi_usb_auto_config(struct usb_device *usbdev, const char *board_name);
-void comedi_usb_auto_unconfig(struct usb_device *usbdev);
+int comedi_usb_auto_config(struct usb_interface *intf,
+ struct comedi_driver *driver);
+void comedi_usb_auto_unconfig(struct usb_interface *intf);
#ifdef CONFIG_COMEDI_PCI_DRIVERS
#define CONFIG_COMEDI_PCI
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index bf185e2807d1..1c3d6386ea36 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -106,6 +106,26 @@ void comedi_device_detach(struct comedi_device *dev)
__comedi_device_detach(dev);
}
+/* do a little post-config cleanup */
+/* called with module refcount incremented, decrements it */
+static int comedi_device_postconfig(struct comedi_device *dev)
+{
+ int ret = postconfig(dev);
+ module_put(dev->driver->module);
+ if (ret < 0) {
+ __comedi_device_detach(dev);
+ return ret;
+ }
+ if (!dev->board_name) {
+ printk(KERN_WARNING "BUG: dev->board_name=<%p>\n",
+ dev->board_name);
+ dev->board_name = "BUG";
+ }
+ smp_wmb();
+ dev->attached = 1;
+ return 0;
+}
+
int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
struct comedi_driver *driv;
@@ -121,59 +141,36 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
if (driv->num_names) {
dev->board_ptr = comedi_recognize(driv, it->board_name);
- if (dev->board_ptr == NULL) {
- module_put(driv->module);
- continue;
- }
- } else {
- if (strcmp(driv->driver_name, it->board_name)) {
- module_put(driv->module);
+ if (dev->board_ptr)
+ break;
+ } else if (strcmp(driv->driver_name, it->board_name))
+ break;
+ module_put(driv->module);
+ }
+ if (driv == NULL) {
+ /* recognize has failed if we get here */
+ /* report valid board names before returning error */
+ for (driv = comedi_drivers; driv; driv = driv->next) {
+ if (!try_module_get(driv->module)) {
+ printk(KERN_INFO
+ "comedi: failed to increment module count\n");
continue;
}
+ comedi_report_boards(driv);
+ module_put(driv->module);
}
- /* initialize dev->driver here so
- * comedi_error() can be called from attach */
- dev->driver = driv;
- ret = driv->attach(dev, it);
- if (ret < 0) {
- module_put(dev->driver->module);
- __comedi_device_detach(dev);
- return ret;
- }
- goto attached;
+ return -EIO;
}
-
- /* recognize has failed if we get here */
- /* report valid board names before returning error */
- for (driv = comedi_drivers; driv; driv = driv->next) {
- if (!try_module_get(driv->module)) {
- printk(KERN_INFO
- "comedi: failed to increment module count\n");
- continue;
- }
- comedi_report_boards(driv);
- module_put(driv->module);
- }
- return -EIO;
-
-attached:
- /* do a little post-config cleanup */
- ret = postconfig(dev);
- module_put(dev->driver->module);
+ /* initialize dev->driver here so
+ * comedi_error() can be called from attach */
+ dev->driver = driv;
+ ret = driv->attach(dev, it);
if (ret < 0) {
+ module_put(dev->driver->module);
__comedi_device_detach(dev);
return ret;
}
-
- if (!dev->board_name) {
- printk(KERN_WARNING "BUG: dev->board_name=<%p>\n",
- dev->board_name);
- dev->board_name = "BUG";
- }
- smp_wmb();
- dev->attached = 1;
-
- return 0;
+ return comedi_device_postconfig(dev);
}
int comedi_driver_register(struct comedi_driver *driver)
@@ -242,6 +239,8 @@ static int postconfig(struct comedi_device *dev)
s->len_chanlist = 1;
if (s->do_cmd) {
+ unsigned int buf_size;
+
BUG_ON((s->subdev_flags & (SDF_CMD_READ |
SDF_CMD_WRITE)) == 0);
BUG_ON(!s->do_cmdtest);
@@ -257,19 +256,20 @@ static int postconfig(struct comedi_device *dev)
async->subdevice = s;
s->async = async;
-#define DEFAULT_BUF_MAXSIZE (64*1024)
-#define DEFAULT_BUF_SIZE (64*1024)
-
- async->max_bufsize = DEFAULT_BUF_MAXSIZE;
+ async->max_bufsize =
+ comedi_default_buf_maxsize_kb * 1024;
+ buf_size = comedi_default_buf_size_kb * 1024;
+ if (buf_size > async->max_bufsize)
+ buf_size = async->max_bufsize;
async->prealloc_buf = NULL;
async->prealloc_bufsz = 0;
- if (comedi_buf_alloc(dev, s, DEFAULT_BUF_SIZE) < 0) {
+ if (comedi_buf_alloc(dev, s, buf_size) < 0) {
printk(KERN_INFO "Buffer allocation failed\n");
return -ENOMEM;
}
if (s->buf_change) {
- ret = s->buf_change(dev, s, DEFAULT_BUF_SIZE);
+ ret = s->buf_change(dev, s, buf_size);
if (ret < 0)
return ret;
}
@@ -814,67 +814,102 @@ void comedi_reset_async_buf(struct comedi_async *async)
async->events = 0;
}
-static int comedi_auto_config(struct device *hardware_device,
- const char *board_name, const int *options,
- unsigned num_options)
+static int
+comedi_auto_config_helper(struct device *hardware_device,
+ struct comedi_driver *driver,
+ int (*attach_wrapper) (struct comedi_device *,
+ void *), void *context)
{
- struct comedi_devconfig it;
int minor;
struct comedi_device_file_info *dev_file_info;
- int retval;
- unsigned *private_data = NULL;
+ struct comedi_device *comedi_dev;
+ int ret;
- if (!comedi_autoconfig) {
- dev_set_drvdata(hardware_device, NULL);
+ if (!comedi_autoconfig)
return 0;
- }
minor = comedi_alloc_board_minor(hardware_device);
if (minor < 0)
return minor;
- private_data = kmalloc(sizeof(unsigned), GFP_KERNEL);
- if (private_data == NULL) {
- retval = -ENOMEM;
- goto cleanup;
+ dev_file_info = comedi_get_device_file_info(minor);
+ comedi_dev = dev_file_info->device;
+
+ mutex_lock(&comedi_dev->mutex);
+ if (comedi_dev->attached)
+ ret = -EBUSY;
+ else if (!try_module_get(driver->module)) {
+ printk(KERN_INFO "comedi: failed to increment module count\n");
+ ret = -EIO;
+ } else {
+ /* set comedi_dev->driver here for attach wrapper */
+ comedi_dev->driver = driver;
+ ret = (*attach_wrapper)(comedi_dev, context);
+ if (ret < 0) {
+ module_put(driver->module);
+ __comedi_device_detach(comedi_dev);
+ } else {
+ ret = comedi_device_postconfig(comedi_dev);
+ }
}
- *private_data = minor;
- dev_set_drvdata(hardware_device, private_data);
+ mutex_unlock(&comedi_dev->mutex);
- dev_file_info = comedi_get_device_file_info(minor);
+ if (ret < 0)
+ comedi_free_board_minor(minor);
+ return ret;
+}
+
+static int comedi_auto_config_wrapper(struct comedi_device *dev, void *context)
+{
+ struct comedi_devconfig *it = context;
+ struct comedi_driver *driv = dev->driver;
+
+ if (driv->num_names) {
+ /* look for generic board entry matching driver name, which
+ * has already been copied to it->board_name */
+ dev->board_ptr = comedi_recognize(driv, it->board_name);
+ if (dev->board_ptr == NULL) {
+ printk(KERN_WARNING
+ "comedi: auto config failed to find board entry"
+ " '%s' for driver '%s'\n", it->board_name,
+ driv->driver_name);
+ comedi_report_boards(driv);
+ return -EINVAL;
+ }
+ }
+ return driv->attach(dev, it);
+}
+
+static int comedi_auto_config(struct device *hardware_device,
+ struct comedi_driver *driver, const int *options,
+ unsigned num_options)
+{
+ struct comedi_devconfig it;
memset(&it, 0, sizeof(it));
- strncpy(it.board_name, board_name, COMEDI_NAMELEN);
+ strncpy(it.board_name, driver->driver_name, COMEDI_NAMELEN);
it.board_name[COMEDI_NAMELEN - 1] = '\0';
BUG_ON(num_options > COMEDI_NDEVCONFOPTS);
memcpy(it.options, options, num_options * sizeof(int));
-
- mutex_lock(&dev_file_info->device->mutex);
- retval = comedi_device_attach(dev_file_info->device, &it);
- mutex_unlock(&dev_file_info->device->mutex);
-
-cleanup:
- if (retval < 0) {
- kfree(private_data);
- comedi_free_board_minor(minor);
- }
- return retval;
+ return comedi_auto_config_helper(hardware_device, driver,
+ comedi_auto_config_wrapper, &it);
}
static void comedi_auto_unconfig(struct device *hardware_device)
{
- unsigned *minor = (unsigned *)dev_get_drvdata(hardware_device);
- if (minor == NULL)
- return;
-
- BUG_ON(*minor >= COMEDI_NUM_BOARD_MINORS);
+ int minor;
- comedi_free_board_minor(*minor);
- dev_set_drvdata(hardware_device, NULL);
- kfree(minor);
+ if (hardware_device == NULL)
+ return;
+ minor = comedi_find_board_minor(hardware_device);
+ if (minor < 0)
+ return;
+ BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
+ comedi_free_board_minor(minor);
}
-int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name)
+static int comedi_old_pci_auto_config(struct pci_dev *pcidev,
+ struct comedi_driver *driver)
{
int options[2];
@@ -883,9 +918,30 @@ int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name)
/* pci slot */
options[1] = PCI_SLOT(pcidev->devfn);
- return comedi_auto_config(&pcidev->dev, board_name,
+ return comedi_auto_config(&pcidev->dev, driver,
options, ARRAY_SIZE(options));
}
+
+static int comedi_pci_attach_wrapper(struct comedi_device *dev, void *pcidev)
+{
+ return dev->driver->attach_pci(dev, pcidev);
+}
+
+static int comedi_new_pci_auto_config(struct pci_dev *pcidev,
+ struct comedi_driver *driver)
+{
+ return comedi_auto_config_helper(&pcidev->dev, driver,
+ comedi_pci_attach_wrapper, pcidev);
+}
+
+int comedi_pci_auto_config(struct pci_dev *pcidev, struct comedi_driver *driver)
+{
+
+ if (driver->attach_pci)
+ return comedi_new_pci_auto_config(pcidev, driver);
+ else
+ return comedi_old_pci_auto_config(pcidev, driver);
+}
EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
@@ -894,16 +950,96 @@ void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
}
EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
-int comedi_usb_auto_config(struct usb_device *usbdev, const char *board_name)
+int comedi_pci_driver_register(struct comedi_driver *comedi_driver,
+ struct pci_driver *pci_driver)
+{
+ int ret;
+
+ ret = comedi_driver_register(comedi_driver);
+ if (ret < 0)
+ return ret;
+
+ /* FIXME: Remove this test after auditing all comedi pci drivers */
+ if (!pci_driver->name)
+ pci_driver->name = comedi_driver->driver_name;
+
+ ret = pci_register_driver(pci_driver);
+ if (ret < 0) {
+ comedi_driver_unregister(comedi_driver);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(comedi_pci_driver_register);
+
+void comedi_pci_driver_unregister(struct comedi_driver *comedi_driver,
+ struct pci_driver *pci_driver)
+{
+ pci_unregister_driver(pci_driver);
+ comedi_driver_unregister(comedi_driver);
+}
+EXPORT_SYMBOL_GPL(comedi_pci_driver_unregister);
+
+static int comedi_old_usb_auto_config(struct usb_interface *intf,
+ struct comedi_driver *driver)
+{
+ return comedi_auto_config(&intf->dev, driver, NULL, 0);
+}
+
+static int comedi_usb_attach_wrapper(struct comedi_device *dev, void *intf)
+{
+ return dev->driver->attach_usb(dev, intf);
+}
+
+static int comedi_new_usb_auto_config(struct usb_interface *intf,
+ struct comedi_driver *driver)
+{
+ return comedi_auto_config_helper(&intf->dev, driver,
+ comedi_usb_attach_wrapper, intf);
+}
+
+int comedi_usb_auto_config(struct usb_interface *intf,
+ struct comedi_driver *driver)
{
- BUG_ON(usbdev == NULL);
- return comedi_auto_config(&usbdev->dev, board_name, NULL, 0);
+ BUG_ON(intf == NULL);
+ if (driver->attach_usb)
+ return comedi_new_usb_auto_config(intf, driver);
+ else
+ return comedi_old_usb_auto_config(intf, driver);
}
EXPORT_SYMBOL_GPL(comedi_usb_auto_config);
-void comedi_usb_auto_unconfig(struct usb_device *usbdev)
+void comedi_usb_auto_unconfig(struct usb_interface *intf)
{
- BUG_ON(usbdev == NULL);
- comedi_auto_unconfig(&usbdev->dev);
+ BUG_ON(intf == NULL);
+ comedi_auto_unconfig(&intf->dev);
}
EXPORT_SYMBOL_GPL(comedi_usb_auto_unconfig);
+
+int comedi_usb_driver_register(struct comedi_driver *comedi_driver,
+ struct usb_driver *usb_driver)
+{
+ int ret;
+
+ ret = comedi_driver_register(comedi_driver);
+ if (ret < 0)
+ return ret;
+
+ ret = usb_register(usb_driver);
+ if (ret < 0) {
+ comedi_driver_unregister(comedi_driver);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(comedi_usb_driver_register);
+
+void comedi_usb_driver_unregister(struct comedi_driver *comedi_driver,
+ struct usb_driver *usb_driver)
+{
+ usb_deregister(usb_driver);
+ comedi_driver_unregister(comedi_driver);
+}
+EXPORT_SYMBOL_GPL(comedi_usb_driver_unregister);
diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
index 6c26ac887eee..27e39e4eb6b3 100644
--- a/drivers/staging/comedi/drivers/8255.c
+++ b/drivers/staging/comedi/drivers/8255.c
@@ -107,31 +107,6 @@ struct subdev_8255_struct {
#define CALLBACK_FUNC (((struct subdev_8255_struct *)s->private)->cb_func)
#define subdevpriv ((struct subdev_8255_struct *)s->private)
-static int dev_8255_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int dev_8255_detach(struct comedi_device *dev);
-static struct comedi_driver driver_8255 = {
- .driver_name = "8255",
- .module = THIS_MODULE,
- .attach = dev_8255_attach,
- .detach = dev_8255_detach,
-};
-
-static int __init driver_8255_init_module(void)
-{
- return comedi_driver_register(&driver_8255);
-}
-
-static void __exit driver_8255_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_8255);
-}
-
-module_init(driver_8255_init_module);
-module_exit(driver_8255_cleanup_module);
-
-static void do_config(struct comedi_device *dev, struct comedi_subdevice *s);
-
void subdev_8255_interrupt(struct comedi_device *dev,
struct comedi_subdevice *s)
{
@@ -185,6 +160,23 @@ static int subdev_8255_insn(struct comedi_device *dev,
return 2;
}
+static void do_config(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+ int config;
+
+ config = CR_CW;
+ /* 1 in io_bits indicates output, 1 in config indicates input */
+ if (!(s->io_bits & 0x0000ff))
+ config |= CR_A_IO;
+ if (!(s->io_bits & 0x00ff00))
+ config |= CR_B_IO;
+ if (!(s->io_bits & 0x0f0000))
+ config |= CR_C_LO_IO;
+ if (!(s->io_bits & 0xf00000))
+ config |= CR_C_HI_IO;
+ CALLBACK_FUNC(1, _8255_CR, config, CALLBACK_ARG);
+}
+
static int subdev_8255_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -222,23 +214,6 @@ static int subdev_8255_insn_config(struct comedi_device *dev,
return 1;
}
-static void do_config(struct comedi_device *dev, struct comedi_subdevice *s)
-{
- int config;
-
- config = CR_CW;
- /* 1 in io_bits indicates output, 1 in config indicates input */
- if (!(s->io_bits & 0x0000ff))
- config |= CR_A_IO;
- if (!(s->io_bits & 0x00ff00))
- config |= CR_B_IO;
- if (!(s->io_bits & 0x0f0000))
- config |= CR_C_LO_IO;
- if (!(s->io_bits & 0xf00000))
- config |= CR_C_HI_IO;
- CALLBACK_FUNC(1, _8255_CR, config, CALLBACK_ARG);
-}
-
static int subdev_8255_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
@@ -442,14 +417,12 @@ static int dev_8255_attach(struct comedi_device *dev,
return 0;
}
-static int dev_8255_detach(struct comedi_device *dev)
+static void dev_8255_detach(struct comedi_device *dev)
{
int i;
unsigned long iobase;
struct comedi_subdevice *s;
- printk(KERN_INFO "comedi%d: 8255: remove\n", dev->minor);
-
for (i = 0; i < dev->n_subdevices; i++) {
s = dev->subdevices + i;
if (s->type != COMEDI_SUBD_UNUSED) {
@@ -458,10 +431,16 @@ static int dev_8255_detach(struct comedi_device *dev)
}
subdev_8255_cleanup(dev, s);
}
-
- return 0;
}
+static struct comedi_driver dev_8255_driver = {
+ .driver_name = "8255",
+ .module = THIS_MODULE,
+ .attach = dev_8255_attach,
+ .detach = dev_8255_detach,
+};
+module_comedi_driver(dev_8255_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c
index 9def2250bb80..4e4fc418655f 100644
--- a/drivers/staging/comedi/drivers/acl7225b.c
+++ b/drivers/staging/comedi/drivers/acl7225b.c
@@ -22,46 +22,13 @@ Devices: [Adlink] ACL-7225b (acl7225b), [ICP] P16R16DIO (p16r16dio)
#define ACL7225_DI_LO 2 /* Digital input low byte (DI0-DI7) */
#define ACL7225_DI_HI 3 /* Digital input high byte (DI8-DI15) */
-static int acl7225b_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int acl7225b_detach(struct comedi_device *dev);
-
struct boardtype {
const char *name; /* driver name */
int io_range; /* len of I/O space */
};
-static const struct boardtype boardtypes[] = {
- {"acl7225b", ACL7225_SIZE,},
- {"p16r16dio", P16R16DIO_SIZE,},
-};
-
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
#define this_board ((const struct boardtype *)dev->board_ptr)
-static struct comedi_driver driver_acl7225b = {
- .driver_name = "acl7225b",
- .module = THIS_MODULE,
- .attach = acl7225b_attach,
- .detach = acl7225b_detach,
- .board_name = &boardtypes[0].name,
- .num_names = n_boardtypes,
- .offset = sizeof(struct boardtype),
-};
-
-static int __init driver_acl7225b_init_module(void)
-{
- return comedi_driver_register(&driver_acl7225b);
-}
-
-static void __exit driver_acl7225b_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_acl7225b);
-}
-
-module_init(driver_acl7225b_init_module);
-module_exit(driver_acl7225b_cleanup_module);
-
static int acl7225b_do_insn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -152,16 +119,28 @@ static int acl7225b_attach(struct comedi_device *dev,
return 0;
}
-static int acl7225b_detach(struct comedi_device *dev)
+static void acl7225b_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: acl7225b: remove\n", dev->minor);
-
if (dev->iobase)
release_region(dev->iobase, this_board->io_range);
-
- return 0;
}
+static const struct boardtype boardtypes[] = {
+ { "acl7225b", ACL7225_SIZE, },
+ { "p16r16dio", P16R16DIO_SIZE, },
+};
+
+static struct comedi_driver acl7225b_driver = {
+ .driver_name = "acl7225b",
+ .module = THIS_MODULE,
+ .attach = acl7225b_attach,
+ .detach = acl7225b_detach,
+ .board_name = &boardtypes[0].name,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .offset = sizeof(struct boardtype),
+};
+module_comedi_driver(acl7225b_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index ca5bd9b8704a..44aaf8351ba3 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -224,2318 +224,1213 @@ MODULE_DEVICE_TABLE(pci, addi_apci_tbl);
static const struct addi_board boardtypes[] = {
#ifdef CONFIG_APCI_3120
- {"apci3120",
- APCI3120_BOARD_VENDOR_ID,
- 0x818D,
- AMCC_OP_REG_SIZE,
- APCI3120_ADDRESS_RANGE,
- 8,
- 0,
- ADDIDATA_NO_EEPROM,
- NULL,
- 16,
- 8,
- 16,
- 8,
- 0xffff,
- 0x3fff,
- &range_apci3120_ai,
- &range_apci3120_ao,
- 4,
- 4,
- 0x0f,
- 0,
- NULL,
- 1,
- 1,
- 1,
- 10000,
- 100000,
- v_APCI3120_Interrupt,
- i_APCI3120_Reset,
- i_APCI3120_InsnConfigAnalogInput,
- i_APCI3120_InsnReadAnalogInput,
- NULL,
- NULL,
- i_APCI3120_CommandTestAnalogInput,
- i_APCI3120_CommandAnalogInput,
- i_APCI3120_StopCyclicAcquisition,
- NULL,
- i_APCI3120_InsnWriteAnalogOutput,
- NULL,
- NULL,
- i_APCI3120_InsnReadDigitalInput,
- NULL,
- i_APCI3120_InsnBitsDigitalInput,
- i_APCI3120_InsnConfigDigitalOutput,
- i_APCI3120_InsnWriteDigitalOutput,
- i_APCI3120_InsnBitsDigitalOutput,
- NULL,
- i_APCI3120_InsnConfigTimer,
- i_APCI3120_InsnWriteTimer,
- i_APCI3120_InsnReadTimer,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci3120",
+ .i_VendorId = APCI3120_BOARD_VENDOR_ID,
+ .i_DeviceId = 0x818D,
+ .i_IorangeBase0 = AMCC_OP_REG_SIZE,
+ .i_IorangeBase1 = APCI3120_ADDRESS_RANGE,
+ .i_IorangeBase2 = 8,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .i_NbrAiChannel = 16,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 16,
+ .i_NbrAoChannel = 8,
+ .i_AiMaxdata = 0xffff,
+ .i_AoMaxdata = 0x3fff,
+ .pr_AiRangelist = &range_apci3120_ai,
+ .pr_AoRangelist = &range_apci3120_ao,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 0x0f,
+ .i_Dma = 1,
+ .i_Timer = 1,
+ .b_AvailableConvertUnit = 1,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .ui_MinDelaytimeNs = 100000,
+ .interrupt = v_APCI3120_Interrupt,
+ .reset = i_APCI3120_Reset,
+ .ai_config = i_APCI3120_InsnConfigAnalogInput,
+ .ai_read = i_APCI3120_InsnReadAnalogInput,
+ .ai_cmdtest = i_APCI3120_CommandTestAnalogInput,
+ .ai_cmd = i_APCI3120_CommandAnalogInput,
+ .ai_cancel = i_APCI3120_StopCyclicAcquisition,
+ .ao_write = i_APCI3120_InsnWriteAnalogOutput,
+ .di_read = i_APCI3120_InsnReadDigitalInput,
+ .di_bits = i_APCI3120_InsnBitsDigitalInput,
+ .do_config = i_APCI3120_InsnConfigDigitalOutput,
+ .do_write = i_APCI3120_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3120_InsnBitsDigitalOutput,
+ .timer_config = i_APCI3120_InsnConfigTimer,
+ .timer_write = i_APCI3120_InsnWriteTimer,
+ .timer_read = i_APCI3120_InsnReadTimer,
+ },
#endif
#ifdef CONFIG_APCI_1032
- {"apci1032",
- APCI1032_BOARD_VENDOR_ID,
- 0x1003,
- 4,
- APCI1032_ADDRESS_RANGE,
- 0,
- 0,
- ADDIDATA_EEPROM,
- ADDIDATA_93C76,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- NULL,
- NULL,
- 32,
- 0,
- 0,
- 0,
- NULL,
- 0,
- 0,
- 0,
- 0,
- 0,
- v_APCI1032_Interrupt,
- i_APCI1032_Reset,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI1032_ConfigDigitalInput,
- i_APCI1032_Read1DigitalInput,
- NULL,
- i_APCI1032_ReadMoreDigitalInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci1032",
+ .i_VendorId = APCI1032_BOARD_VENDOR_ID,
+ .i_DeviceId = 0x1003,
+ .i_IorangeBase0 = 4,
+ .i_IorangeBase1 = APCI1032_ADDRESS_RANGE,
+ .i_PCIEeprom = ADDIDATA_EEPROM,
+ .pc_EepromChip = ADDIDATA_93C76,
+ .i_NbrDiChannel = 32,
+ .interrupt = v_APCI1032_Interrupt,
+ .reset = i_APCI1032_Reset,
+ .di_config = i_APCI1032_ConfigDigitalInput,
+ .di_read = i_APCI1032_Read1DigitalInput,
+ .di_bits = i_APCI1032_ReadMoreDigitalInput,
+ },
#endif
#ifdef CONFIG_APCI_1516
- {"apci1516",
- APCI1516_BOARD_VENDOR_ID,
- 0x1001,
- 128,
- APCI1516_ADDRESS_RANGE,
- 32,
- 0,
- ADDIDATA_EEPROM,
- ADDIDATA_S5920,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- NULL,
- NULL,
- 8,
- 8,
- 0,
- 0,
- NULL,
- 0,
- 1,
- 0,
- 0,
- 0,
- NULL,
- i_APCI1516_Reset,
- NULL, NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI1516_Read1DigitalInput,
- NULL,
- i_APCI1516_ReadMoreDigitalInput,
- i_APCI1516_ConfigDigitalOutput,
- i_APCI1516_WriteDigitalOutput,
- i_APCI1516_ReadDigitalOutput,
- NULL,
- i_APCI1516_ConfigWatchdog,
- i_APCI1516_StartStopWriteWatchdog,
- i_APCI1516_ReadWatchdog,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci1516",
+ .i_VendorId = APCI1516_BOARD_VENDOR_ID,
+ .i_DeviceId = 0x1001,
+ .i_IorangeBase0 = 128,
+ .i_IorangeBase1 = APCI1516_ADDRESS_RANGE,
+ .i_IorangeBase2 = 32,
+ .i_PCIEeprom = ADDIDATA_EEPROM,
+ .pc_EepromChip = ADDIDATA_S5920,
+ .i_NbrDiChannel = 8,
+ .i_NbrDoChannel = 8,
+ .i_Timer = 1,
+ .reset = i_APCI1516_Reset,
+ .di_read = i_APCI1516_Read1DigitalInput,
+ .di_bits = i_APCI1516_ReadMoreDigitalInput,
+ .do_config = i_APCI1516_ConfigDigitalOutput,
+ .do_write = i_APCI1516_WriteDigitalOutput,
+ .do_bits = i_APCI1516_ReadDigitalOutput,
+ .timer_config = i_APCI1516_ConfigWatchdog,
+ .timer_write = i_APCI1516_StartStopWriteWatchdog,
+ .timer_read = i_APCI1516_ReadWatchdog,
+ },
#endif
#ifdef CONFIG_APCI_2016
- {"apci2016",
- APCI2016_BOARD_VENDOR_ID,
- 0x1002,
- 128,
- APCI2016_ADDRESS_RANGE,
- 32,
- 0,
- ADDIDATA_EEPROM,
- ADDIDATA_S5920,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- NULL,
- NULL,
- 0,
- 16,
- 0,
- 0,
- NULL,
- 0,
- 1,
- 0,
- 0,
- 0,
- NULL,
- i_APCI2016_Reset,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI2016_ConfigDigitalOutput,
- i_APCI2016_WriteDigitalOutput,
- i_APCI2016_BitsDigitalOutput,
- NULL,
- i_APCI2016_ConfigWatchdog,
- i_APCI2016_StartStopWriteWatchdog,
- i_APCI2016_ReadWatchdog,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci2016",
+ .i_VendorId = APCI2016_BOARD_VENDOR_ID,
+ .i_DeviceId = 0x1002,
+ .i_IorangeBase0 = 128,
+ .i_IorangeBase1 = APCI2016_ADDRESS_RANGE,
+ .i_IorangeBase2 = 32,
+ .i_PCIEeprom = ADDIDATA_EEPROM,
+ .pc_EepromChip = ADDIDATA_S5920,
+ .i_NbrDoChannel = 16,
+ .i_Timer = 1,
+ .reset = i_APCI2016_Reset,
+ .do_config = i_APCI2016_ConfigDigitalOutput,
+ .do_write = i_APCI2016_WriteDigitalOutput,
+ .do_bits = i_APCI2016_BitsDigitalOutput,
+ .timer_config = i_APCI2016_ConfigWatchdog,
+ .timer_write = i_APCI2016_StartStopWriteWatchdog,
+ .timer_read = i_APCI2016_ReadWatchdog,
+ },
#endif
#ifdef CONFIG_APCI_2032
- {"apci2032",
- APCI2032_BOARD_VENDOR_ID,
- 0x1004,
- 4,
- APCI2032_ADDRESS_RANGE,
- 0,
- 0,
- ADDIDATA_EEPROM,
- ADDIDATA_93C76,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- NULL,
- NULL,
- 0,
- 32,
- 0xffffffff,
- 0,
- NULL,
- 0,
- 1,
- 0,
- 0,
- 0,
- v_APCI2032_Interrupt,
- i_APCI2032_Reset,
- NULL, NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI2032_ConfigDigitalOutput,
- i_APCI2032_WriteDigitalOutput,
- i_APCI2032_ReadDigitalOutput,
- i_APCI2032_ReadInterruptStatus,
- i_APCI2032_ConfigWatchdog,
- i_APCI2032_StartStopWriteWatchdog,
- i_APCI2032_ReadWatchdog,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci2032",
+ .i_VendorId = APCI2032_BOARD_VENDOR_ID,
+ .i_DeviceId = 0x1004,
+ .i_IorangeBase0 = 4,
+ .i_IorangeBase1 = APCI2032_ADDRESS_RANGE,
+ .i_PCIEeprom = ADDIDATA_EEPROM,
+ .pc_EepromChip = ADDIDATA_93C76,
+ .i_NbrDoChannel = 32,
+ .i_DoMaxdata = 0xffffffff,
+ .i_Timer = 1,
+ .interrupt = v_APCI2032_Interrupt,
+ .reset = i_APCI2032_Reset,
+ .do_config = i_APCI2032_ConfigDigitalOutput,
+ .do_write = i_APCI2032_WriteDigitalOutput,
+ .do_bits = i_APCI2032_ReadDigitalOutput,
+ .do_read = i_APCI2032_ReadInterruptStatus,
+ .timer_config = i_APCI2032_ConfigWatchdog,
+ .timer_write = i_APCI2032_StartStopWriteWatchdog,
+ .timer_read = i_APCI2032_ReadWatchdog,
+ },
#endif
#ifdef CONFIG_APCI_2200
- {"apci2200",
- APCI2200_BOARD_VENDOR_ID,
- 0x1005,
- 4,
- APCI2200_ADDRESS_RANGE,
- 0,
- 0,
- ADDIDATA_EEPROM,
- ADDIDATA_93C76,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- NULL,
- NULL,
- 8,
- 16,
- 0,
- 0,
- NULL,
- 0,
- 1,
- 0,
- 0,
- 0,
- NULL,
- i_APCI2200_Reset,
- NULL, NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI2200_Read1DigitalInput,
- NULL,
- i_APCI2200_ReadMoreDigitalInput,
- i_APCI2200_ConfigDigitalOutput,
- i_APCI2200_WriteDigitalOutput,
- i_APCI2200_ReadDigitalOutput,
- NULL,
- i_APCI2200_ConfigWatchdog,
- i_APCI2200_StartStopWriteWatchdog,
- i_APCI2200_ReadWatchdog,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci2200",
+ .i_VendorId = APCI2200_BOARD_VENDOR_ID,
+ .i_DeviceId = 0x1005,
+ .i_IorangeBase0 = 4,
+ .i_IorangeBase1 = APCI2200_ADDRESS_RANGE,
+ .i_PCIEeprom = ADDIDATA_EEPROM,
+ .pc_EepromChip = ADDIDATA_93C76,
+ .i_NbrDiChannel = 8,
+ .i_NbrDoChannel = 16,
+ .i_Timer = 1,
+ .reset = i_APCI2200_Reset,
+ .di_read = i_APCI2200_Read1DigitalInput,
+ .di_bits = i_APCI2200_ReadMoreDigitalInput,
+ .do_config = i_APCI2200_ConfigDigitalOutput,
+ .do_write = i_APCI2200_WriteDigitalOutput,
+ .do_bits = i_APCI2200_ReadDigitalOutput,
+ .timer_config = i_APCI2200_ConfigWatchdog,
+ .timer_write = i_APCI2200_StartStopWriteWatchdog,
+ .timer_read = i_APCI2200_ReadWatchdog,
+ },
#endif
#ifdef CONFIG_APCI_1564
- {"apci1564",
- APCI1564_BOARD_VENDOR_ID,
- 0x1006,
- 128,
- APCI1564_ADDRESS_RANGE,
- 0,
- 0,
- ADDIDATA_EEPROM,
- ADDIDATA_93C76,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- NULL,
- NULL,
- 32,
- 32,
- 0xffffffff,
- 0,
- NULL,
- 0,
- 1,
- 0,
- 0,
- 0,
- v_APCI1564_Interrupt,
- i_APCI1564_Reset,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI1564_ConfigDigitalInput,
- i_APCI1564_Read1DigitalInput,
- NULL,
- i_APCI1564_ReadMoreDigitalInput,
- i_APCI1564_ConfigDigitalOutput,
- i_APCI1564_WriteDigitalOutput,
- i_APCI1564_ReadDigitalOutput,
- i_APCI1564_ReadInterruptStatus,
- i_APCI1564_ConfigTimerCounterWatchdog,
- i_APCI1564_StartStopWriteTimerCounterWatchdog,
- i_APCI1564_ReadTimerCounterWatchdog,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci1564",
+ .i_VendorId = APCI1564_BOARD_VENDOR_ID,
+ .i_DeviceId = 0x1006,
+ .i_IorangeBase0 = 128,
+ .i_IorangeBase1 = APCI1564_ADDRESS_RANGE,
+ .i_PCIEeprom = ADDIDATA_EEPROM,
+ .pc_EepromChip = ADDIDATA_93C76,
+ .i_NbrDiChannel = 32,
+ .i_NbrDoChannel = 32,
+ .i_DoMaxdata = 0xffffffff,
+ .i_Timer = 1,
+ .interrupt = v_APCI1564_Interrupt,
+ .reset = i_APCI1564_Reset,
+ .di_config = i_APCI1564_ConfigDigitalInput,
+ .di_read = i_APCI1564_Read1DigitalInput,
+ .di_bits = i_APCI1564_ReadMoreDigitalInput,
+ .do_config = i_APCI1564_ConfigDigitalOutput,
+ .do_write = i_APCI1564_WriteDigitalOutput,
+ .do_bits = i_APCI1564_ReadDigitalOutput,
+ .do_read = i_APCI1564_ReadInterruptStatus,
+ .timer_config = i_APCI1564_ConfigTimerCounterWatchdog,
+ .timer_write = i_APCI1564_StartStopWriteTimerCounterWatchdog,
+ .timer_read = i_APCI1564_ReadTimerCounterWatchdog,
+ },
#endif
#ifdef CONFIG_APCI_1500
- {"apci1500",
- APCI1500_BOARD_VENDOR_ID,
- 0x80fc,
- 128,
- APCI1500_ADDRESS_RANGE,
- 4,
- 0,
- ADDIDATA_NO_EEPROM,
- NULL,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- NULL,
- NULL,
- 16,
- 16,
- 0xffff,
- 0,
- NULL,
- 0,
- 1,
- 0,
- 0,
- 0,
- v_APCI1500_Interrupt,
- i_APCI1500_Reset,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI1500_ConfigDigitalInputEvent,
- i_APCI1500_Initialisation,
- i_APCI1500_StartStopInputEvent,
- i_APCI1500_ReadMoreDigitalInput,
- i_APCI1500_ConfigDigitalOutputErrorInterrupt,
- i_APCI1500_WriteDigitalOutput,
- i_APCI1500_ConfigureInterrupt,
- NULL,
- i_APCI1500_ConfigCounterTimerWatchdog,
- i_APCI1500_StartStopTriggerTimerCounterWatchdog,
- i_APCI1500_ReadInterruptMask,
- i_APCI1500_ReadCounterTimerWatchdog,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci1500",
+ .i_VendorId = APCI1500_BOARD_VENDOR_ID,
+ .i_DeviceId = 0x80fc,
+ .i_IorangeBase0 = 128,
+ .i_IorangeBase1 = APCI1500_ADDRESS_RANGE,
+ .i_IorangeBase2 = 4,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .i_NbrDiChannel = 16,
+ .i_NbrDoChannel = 16,
+ .i_DoMaxdata = 0xffff,
+ .i_Timer = 1,
+ .interrupt = v_APCI1500_Interrupt,
+ .reset = i_APCI1500_Reset,
+ .di_config = i_APCI1500_ConfigDigitalInputEvent,
+ .di_read = i_APCI1500_Initialisation,
+ .di_write = i_APCI1500_StartStopInputEvent,
+ .di_bits = i_APCI1500_ReadMoreDigitalInput,
+ .do_config = i_APCI1500_ConfigDigitalOutputErrorInterrupt,
+ .do_write = i_APCI1500_WriteDigitalOutput,
+ .do_bits = i_APCI1500_ConfigureInterrupt,
+ .timer_config = i_APCI1500_ConfigCounterTimerWatchdog,
+ .timer_write = i_APCI1500_StartStopTriggerTimerCounterWatchdog,
+ .timer_read = i_APCI1500_ReadInterruptMask,
+ .timer_bits = i_APCI1500_ReadCounterTimerWatchdog,
+ },
#endif
#ifdef CONFIG_APCI_3001
- {"apci3001",
- APCI3120_BOARD_VENDOR_ID,
- 0x828D,
- AMCC_OP_REG_SIZE,
- APCI3120_ADDRESS_RANGE,
- 8,
- 0,
- ADDIDATA_NO_EEPROM,
- NULL,
- 16,
- 8,
- 16,
- 0,
- 0xfff,
- 0,
- &range_apci3120_ai,
- NULL,
- 4,
- 4,
- 0x0f,
- 0,
- NULL,
- 1,
- 1,
- 1,
- 10000,
- 100000,
- v_APCI3120_Interrupt,
- i_APCI3120_Reset,
- i_APCI3120_InsnConfigAnalogInput,
- i_APCI3120_InsnReadAnalogInput,
- NULL,
- NULL,
- i_APCI3120_CommandTestAnalogInput,
- i_APCI3120_CommandAnalogInput,
- i_APCI3120_StopCyclicAcquisition,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3120_InsnReadDigitalInput,
- NULL,
- i_APCI3120_InsnBitsDigitalInput,
- i_APCI3120_InsnConfigDigitalOutput,
- i_APCI3120_InsnWriteDigitalOutput,
- i_APCI3120_InsnBitsDigitalOutput,
- NULL,
- i_APCI3120_InsnConfigTimer,
- i_APCI3120_InsnWriteTimer,
- i_APCI3120_InsnReadTimer,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci3001",
+ .i_VendorId = APCI3120_BOARD_VENDOR_ID,
+ .i_DeviceId = 0x828D,
+ .i_IorangeBase0 = AMCC_OP_REG_SIZE,
+ .i_IorangeBase1 = APCI3120_ADDRESS_RANGE,
+ .i_IorangeBase2 = 8,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .i_NbrAiChannel = 16,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 16,
+ .i_AiMaxdata = 0xfff,
+ .pr_AiRangelist = &range_apci3120_ai,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 0x0f,
+ .i_Dma = 1,
+ .i_Timer = 1,
+ .b_AvailableConvertUnit = 1,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .ui_MinDelaytimeNs = 100000,
+ .interrupt = v_APCI3120_Interrupt,
+ .reset = i_APCI3120_Reset,
+ .ai_config = i_APCI3120_InsnConfigAnalogInput,
+ .ai_read = i_APCI3120_InsnReadAnalogInput,
+ .ai_cmdtest = i_APCI3120_CommandTestAnalogInput,
+ .ai_cmd = i_APCI3120_CommandAnalogInput,
+ .ai_cancel = i_APCI3120_StopCyclicAcquisition,
+ .di_read = i_APCI3120_InsnReadDigitalInput,
+ .di_bits = i_APCI3120_InsnBitsDigitalInput,
+ .do_config = i_APCI3120_InsnConfigDigitalOutput,
+ .do_write = i_APCI3120_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3120_InsnBitsDigitalOutput,
+ .timer_config = i_APCI3120_InsnConfigTimer,
+ .timer_write = i_APCI3120_InsnWriteTimer,
+ .timer_read = i_APCI3120_InsnReadTimer,
+ },
#endif
#ifdef CONFIG_APCI_3501
- {"apci3501",
- APCI3501_BOARD_VENDOR_ID,
- 0x3001,
- 64,
- APCI3501_ADDRESS_RANGE,
- 0,
- 0,
- ADDIDATA_EEPROM,
- ADDIDATA_S5933,
- 0,
- 0,
- 0,
- 8,
- 0,
- 16383,
- NULL,
- &range_apci3501_ao,
- 2,
- 2,
- 0x3,
- 0,
- NULL,
- 0,
- 1,
- 0,
- 0,
- 0,
- v_APCI3501_Interrupt,
- i_APCI3501_Reset,
- NULL, NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3501_ConfigAnalogOutput,
- i_APCI3501_WriteAnalogOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3501_ReadDigitalInput,
- i_APCI3501_ConfigDigitalOutput,
- i_APCI3501_WriteDigitalOutput,
- i_APCI3501_ReadDigitalOutput,
- NULL,
- i_APCI3501_ConfigTimerCounterWatchdog,
- i_APCI3501_StartStopWriteTimerCounterWatchdog,
- i_APCI3501_ReadTimerCounterWatchdog,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci3501",
+ .i_VendorId = APCI3501_BOARD_VENDOR_ID,
+ .i_DeviceId = 0x3001,
+ .i_IorangeBase0 = 64,
+ .i_IorangeBase1 = APCI3501_ADDRESS_RANGE,
+ .i_PCIEeprom = ADDIDATA_EEPROM,
+ .pc_EepromChip = ADDIDATA_S5933,
+ .i_AoMaxdata = 16383,
+ .pr_AoRangelist = &range_apci3501_ao,
+ .i_NbrDiChannel = 2,
+ .i_NbrDoChannel = 2,
+ .i_DoMaxdata = 0x3,
+ .i_Timer = 1,
+ .interrupt = v_APCI3501_Interrupt,
+ .reset = i_APCI3501_Reset,
+ .ao_config = i_APCI3501_ConfigAnalogOutput,
+ .ao_write = i_APCI3501_WriteAnalogOutput,
+ .di_bits = i_APCI3501_ReadDigitalInput,
+ .do_config = i_APCI3501_ConfigDigitalOutput,
+ .do_write = i_APCI3501_WriteDigitalOutput,
+ .do_bits = i_APCI3501_ReadDigitalOutput,
+ .timer_config = i_APCI3501_ConfigTimerCounterWatchdog,
+ .timer_write = i_APCI3501_StartStopWriteTimerCounterWatchdog,
+ .timer_read = i_APCI3501_ReadTimerCounterWatchdog,
+ },
#endif
#ifdef CONFIG_APCI_035
- {"apci035",
- APCI035_BOARD_VENDOR_ID,
- 0x0300,
- 127,
- APCI035_ADDRESS_RANGE,
- 0,
- 0,
- 1,
- ADDIDATA_S5920,
- 16,
- 8,
- 16,
- 0,
- 0xff,
- 0,
- &range_apci035_ai,
- NULL,
- 0,
- 0,
- 0,
- 0,
- NULL,
- 0,
- 1,
- 0,
- 10000,
- 100000,
- v_APCI035_Interrupt,
- i_APCI035_Reset,
- i_APCI035_ConfigAnalogInput,
- i_APCI035_ReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI035_ConfigTimerWatchdog,
- i_APCI035_StartStopWriteTimerWatchdog,
- i_APCI035_ReadTimerWatchdog,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci035",
+ .i_VendorId = APCI035_BOARD_VENDOR_ID,
+ .i_DeviceId = 0x0300,
+ .i_IorangeBase0 = 127,
+ .i_IorangeBase1 = APCI035_ADDRESS_RANGE,
+ .i_PCIEeprom = 1,
+ .pc_EepromChip = ADDIDATA_S5920,
+ .i_NbrAiChannel = 16,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 16,
+ .i_AiMaxdata = 0xff,
+ .pr_AiRangelist = &range_apci035_ai,
+ .i_Timer = 1,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .ui_MinDelaytimeNs = 100000,
+ .interrupt = v_APCI035_Interrupt,
+ .reset = i_APCI035_Reset,
+ .ai_config = i_APCI035_ConfigAnalogInput,
+ .ai_read = i_APCI035_ReadAnalogInput,
+ .timer_config = i_APCI035_ConfigTimerWatchdog,
+ .timer_write = i_APCI035_StartStopWriteTimerWatchdog,
+ .timer_read = i_APCI035_ReadTimerWatchdog,
+ },
#endif
#ifdef CONFIG_APCI_3200
- {"apci3200",
- APCI3200_BOARD_VENDOR_ID,
- 0x3000,
- 128,
- 256,
- 4,
- 4,
- ADDIDATA_EEPROM,
- ADDIDATA_S5920,
- 16,
- 8,
- 16,
- 0,
- 0x3ffff,
- 0,
- &range_apci3200_ai,
- NULL,
- 4,
- 4,
- 0,
- 0,
- NULL,
- 0,
- 0,
- 0,
- 10000,
- 100000,
- v_APCI3200_Interrupt,
- i_APCI3200_Reset,
- i_APCI3200_ConfigAnalogInput,
- i_APCI3200_ReadAnalogInput,
- i_APCI3200_InsnWriteReleaseAnalogInput,
- i_APCI3200_InsnBits_AnalogInput_Test,
- i_APCI3200_CommandTestAnalogInput,
- i_APCI3200_CommandAnalogInput,
- i_APCI3200_StopCyclicAcquisition,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3200_ReadDigitalInput,
- i_APCI3200_ConfigDigitalOutput,
- i_APCI3200_WriteDigitalOutput,
- i_APCI3200_ReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci3200",
+ .i_VendorId = APCI3200_BOARD_VENDOR_ID,
+ .i_DeviceId = 0x3000,
+ .i_IorangeBase0 = 128,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 4,
+ .i_IorangeBase3 = 4,
+ .i_PCIEeprom = ADDIDATA_EEPROM,
+ .pc_EepromChip = ADDIDATA_S5920,
+ .i_NbrAiChannel = 16,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 16,
+ .i_AiMaxdata = 0x3ffff,
+ .pr_AiRangelist = &range_apci3200_ai,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .ui_MinDelaytimeNs = 100000,
+ .interrupt = v_APCI3200_Interrupt,
+ .reset = i_APCI3200_Reset,
+ .ai_config = i_APCI3200_ConfigAnalogInput,
+ .ai_read = i_APCI3200_ReadAnalogInput,
+ .ai_write = i_APCI3200_InsnWriteReleaseAnalogInput,
+ .ai_bits = i_APCI3200_InsnBits_AnalogInput_Test,
+ .ai_cmdtest = i_APCI3200_CommandTestAnalogInput,
+ .ai_cmd = i_APCI3200_CommandAnalogInput,
+ .ai_cancel = i_APCI3200_StopCyclicAcquisition,
+ .di_bits = i_APCI3200_ReadDigitalInput,
+ .do_config = i_APCI3200_ConfigDigitalOutput,
+ .do_write = i_APCI3200_WriteDigitalOutput,
+ .do_bits = i_APCI3200_ReadDigitalOutput,
+ },
#endif
#ifdef CONFIG_APCI_3300
/* Begin JK .20.10.2004 = APCI-3300 integration */
- {"apci3300",
- APCI3200_BOARD_VENDOR_ID,
- 0x3007,
- 128,
- 256,
- 4,
- 4,
- ADDIDATA_EEPROM,
- ADDIDATA_S5920,
- 0,
- 8,
- 8,
- 0,
- 0x3ffff,
- 0,
- &range_apci3300_ai,
- NULL,
- 4,
- 4,
- 0,
- 0,
- NULL,
- 0,
- 0,
- 0,
- 10000,
- 100000,
- v_APCI3200_Interrupt,
- i_APCI3200_Reset,
- i_APCI3200_ConfigAnalogInput,
- i_APCI3200_ReadAnalogInput,
- i_APCI3200_InsnWriteReleaseAnalogInput,
- i_APCI3200_InsnBits_AnalogInput_Test,
- i_APCI3200_CommandTestAnalogInput,
- i_APCI3200_CommandAnalogInput,
- i_APCI3200_StopCyclicAcquisition,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3200_ReadDigitalInput,
- i_APCI3200_ConfigDigitalOutput,
- i_APCI3200_WriteDigitalOutput,
- i_APCI3200_ReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci3300",
+ .i_VendorId = APCI3200_BOARD_VENDOR_ID,
+ .i_DeviceId = 0x3007,
+ .i_IorangeBase0 = 128,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 4,
+ .i_IorangeBase3 = 4,
+ .i_PCIEeprom = ADDIDATA_EEPROM,
+ .pc_EepromChip = ADDIDATA_S5920,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 8,
+ .i_AiMaxdata = 0x3ffff,
+ .pr_AiRangelist = &range_apci3300_ai,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .ui_MinDelaytimeNs = 100000,
+ .interrupt = v_APCI3200_Interrupt,
+ .reset = i_APCI3200_Reset,
+ .ai_config = i_APCI3200_ConfigAnalogInput,
+ .ai_read = i_APCI3200_ReadAnalogInput,
+ .ai_write = i_APCI3200_InsnWriteReleaseAnalogInput,
+ .ai_bits = i_APCI3200_InsnBits_AnalogInput_Test,
+ .ai_cmdtest = i_APCI3200_CommandTestAnalogInput,
+ .ai_cmd = i_APCI3200_CommandAnalogInput,
+ .ai_cancel = i_APCI3200_StopCyclicAcquisition,
+ .di_bits = i_APCI3200_ReadDigitalInput,
+ .do_config = i_APCI3200_ConfigDigitalOutput,
+ .do_write = i_APCI3200_WriteDigitalOutput,
+ .do_bits = i_APCI3200_ReadDigitalOutput,
+ },
#endif
#ifdef CONFIG_APCI_1710
- {"apci1710", APCI1710_BOARD_VENDOR_ID, APCI1710_BOARD_DEVICE_ID,
- 128,
- 8,
- 256,
- 0,
- ADDIDATA_NO_EEPROM,
- NULL,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- NULL,
- NULL,
- 0,
- 0,
- 0,
- 0,
- NULL,
- 0,
- 0,
- 0,
- 0,
- 0,
- v_APCI1710_Interrupt,
- i_APCI1710_Reset,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ {
+ .pc_DriverName = "apci1710",
+ .i_VendorId = APCI1710_BOARD_VENDOR_ID,
+ .i_DeviceId = APCI1710_BOARD_DEVICE_ID,
+ .i_IorangeBase0 = 128,
+ .i_IorangeBase1 = 8,
+ .i_IorangeBase2 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .interrupt = v_APCI1710_Interrupt,
+ .reset = i_APCI1710_Reset,
+ },
#endif
#ifdef CONFIG_APCI_16XX
- {"apci1648",
- PCI_VENDOR_ID_ADDIDATA,
- 0x1009,
- 128,
- 0,
- 0,
- 0,
- ADDIDATA_NO_EEPROM,
- NULL,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- NULL,
- NULL,
- 0,
- 0,
- 0,
- 48,
- &range_apci16xx_ttl,
- 0,
- 0,
- 0,
- 0,
- 0,
- NULL,
- i_APCI16XX_Reset,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI16XX_InsnConfigInitTTLIO,
- i_APCI16XX_InsnBitsReadTTLIO,
- i_APCI16XX_InsnReadTTLIOAllPortValue,
- i_APCI16XX_InsnBitsWriteTTLIO},
-
- {"apci1696",
- PCI_VENDOR_ID_ADDIDATA,
- 0x100A,
- 128,
- 0,
- 0,
- 0,
- ADDIDATA_NO_EEPROM,
- NULL,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- NULL,
- NULL,
- 0,
- 0,
- 0,
- 96,
- &range_apci16xx_ttl,
- 0,
- 0,
- 0,
- 0,
- 0,
- NULL,
- i_APCI16XX_Reset,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI16XX_InsnConfigInitTTLIO,
- i_APCI16XX_InsnBitsReadTTLIO,
- i_APCI16XX_InsnReadTTLIOAllPortValue,
- i_APCI16XX_InsnBitsWriteTTLIO},
+ {
+ .pc_DriverName = "apci1648",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x1009,
+ .i_IorangeBase0 = 128,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .i_NbrTTLChannel = 48,
+ .pr_TTLRangelist = &range_apci16xx_ttl,
+ .reset = i_APCI16XX_Reset,
+ .ttl_config = i_APCI16XX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI16XX_InsnBitsReadTTLIO,
+ .ttl_read = i_APCI16XX_InsnReadTTLIOAllPortValue,
+ .ttl_write = i_APCI16XX_InsnBitsWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci1696",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x100A,
+ .i_IorangeBase0 = 128,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .i_NbrTTLChannel = 96,
+ .pr_TTLRangelist = &range_apci16xx_ttl,
+ .reset = i_APCI16XX_Reset,
+ .ttl_config = i_APCI16XX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI16XX_InsnBitsReadTTLIO,
+ .ttl_read = i_APCI16XX_InsnReadTTLIOAllPortValue,
+ .ttl_write = i_APCI16XX_InsnBitsWriteTTLIO,
+ },
#endif
#ifdef CONFIG_APCI_3XXX
- {"apci3000-16",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3010,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 16,
- 8,
- 16,
- 0,
- 4095,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 0,
- 0,
- 0,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 10000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3000-8",
- PCI_VENDOR_ID_ADDIDATA,
- 0x300F,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 8,
- 4,
- 8,
- 0,
- 4095,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 0,
- 0,
- 0,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 10000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3000-4",
- PCI_VENDOR_ID_ADDIDATA,
- 0x300E,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 4,
- 2,
- 4,
- 0,
- 4095,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 0,
- 0,
- 0,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 10000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3006-16",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3013,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 16,
- 8,
- 16,
- 0,
- 65535,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 0,
- 0,
- 0,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 10000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3006-8",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3014,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 8,
- 4,
- 8,
- 0,
- 65535,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 0,
- 0,
- 0,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 10000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3006-4",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3015,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 4,
- 2,
- 4,
- 0,
- 65535,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 0,
- 0,
- 0,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 10000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3010-16",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3016,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 16,
- 8,
- 16,
- 0,
- 4095,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 4,
- 4,
- 1,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 5000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3010-8",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3017,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 8,
- 4,
- 8,
- 0,
- 4095,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 4,
- 4,
- 1,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 5000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3010-4",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3018,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 4,
- 2,
- 4,
- 0,
- 4095,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 4,
- 4,
- 1,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 5000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3016-16",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3019,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 16,
- 8,
- 16,
- 0,
- 65535,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 4,
- 4,
- 1,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 5000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3016-8",
- PCI_VENDOR_ID_ADDIDATA,
- 0x301A,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 8,
- 4,
- 8,
- 0,
- 65535,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 4,
- 4,
- 1,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 5000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3016-4",
- PCI_VENDOR_ID_ADDIDATA,
- 0x301B,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 4,
- 2,
- 4,
- 0,
- 65535,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 4,
- 4,
- 1,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 5000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3100-16-4",
- PCI_VENDOR_ID_ADDIDATA,
- 0x301C,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 16,
- 8,
- 16,
- 4,
- 4095,
- 4095,
- &range_apci3XXX_ai,
- &range_apci3XXX_ao,
- 0,
- 0,
- 0,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 10000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnWriteAnalogOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3100-8-4",
- PCI_VENDOR_ID_ADDIDATA,
- 0x301D,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 8,
- 4,
- 8,
- 4,
- 4095,
- 4095,
- &range_apci3XXX_ai,
- &range_apci3XXX_ao,
- 0,
- 0,
- 0,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 10000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnWriteAnalogOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3106-16-4",
- PCI_VENDOR_ID_ADDIDATA,
- 0x301E,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 16,
- 8,
- 16,
- 4,
- 65535,
- 4095,
- &range_apci3XXX_ai,
- &range_apci3XXX_ao,
- 0,
- 0,
- 0,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 10000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnWriteAnalogOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3106-8-4",
- PCI_VENDOR_ID_ADDIDATA,
- 0x301F,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 8,
- 4,
- 8,
- 4,
- 65535,
- 4095,
- &range_apci3XXX_ai,
- &range_apci3XXX_ao,
- 0,
- 0,
- 0,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 10000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnWriteAnalogOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3110-16-4",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3020,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 16,
- 8,
- 16,
- 4,
- 4095,
- 4095,
- &range_apci3XXX_ai,
- &range_apci3XXX_ao,
- 4,
- 4,
- 1,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 5000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnWriteAnalogOutput,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3110-8-4",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3021,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 8,
- 4,
- 8,
- 4,
- 4095,
- 4095,
- &range_apci3XXX_ai,
- &range_apci3XXX_ao,
- 4,
- 4,
- 1,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 5000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnWriteAnalogOutput,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3116-16-4",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3022,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 16,
- 8,
- 16,
- 4,
- 65535,
- 4095,
- &range_apci3XXX_ai,
- &range_apci3XXX_ao,
- 4,
- 4,
- 1,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 5000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnWriteAnalogOutput,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3116-8-4",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3023,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 8,
- 4,
- 8,
- 4,
- 65535,
- 4095,
- &range_apci3XXX_ai,
- &range_apci3XXX_ao,
- 4,
- 4,
- 1,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 6,
- 5000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnWriteAnalogOutput,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
-
- {"apci3003",
- PCI_VENDOR_ID_ADDIDATA,
- 0x300B,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 0,
- 4,
- 4,
- 0,
- 65535,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 4,
- 4,
- 1,
- 0,
- NULL,
- 0,
- 0,
- 7,
- 2500,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
-
- {"apci3002-16",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3002,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 0,
- 16,
- 16,
- 0,
- 65535,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 4,
- 4,
- 1,
- 0,
- NULL,
- 0,
- 0,
- 6,
- 5000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
-
- {"apci3002-8",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3003,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 0,
- 8,
- 8,
- 0,
- 65535,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 4,
- 4,
- 1,
- 0,
- NULL,
- 0,
- 0,
- 6,
- 5000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
-
- {"apci3002-4",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3004,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 0,
- 4,
- 4,
- 0,
- 65535,
- 0,
- &range_apci3XXX_ai,
- NULL,
- 4,
- 4,
- 1,
- 0,
- NULL,
- 0,
- 0,
- 6,
- 5000,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- i_APCI3XXX_InsnConfigAnalogInput,
- i_APCI3XXX_InsnReadAnalogInput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnReadDigitalInput,
- NULL,
- i_APCI3XXX_InsnBitsDigitalInput,
- NULL,
- i_APCI3XXX_InsnWriteDigitalOutput,
- i_APCI3XXX_InsnBitsDigitalOutput,
- i_APCI3XXX_InsnReadDigitalOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
-
- {"apci3500",
- PCI_VENDOR_ID_ADDIDATA,
- 0x3024,
- 256,
- 256,
- 256,
- 256,
- ADDIDATA_NO_EEPROM,
- ADDIDATA_9054,
- 0,
- 0,
- 0,
- 4,
- 0,
- 4095,
- NULL,
- &range_apci3XXX_ao,
- 0,
- 0,
- 0,
- 24,
- &range_apci3XXX_ttl,
- 0,
- 0,
- 0,
- 0,
- 0,
- v_APCI3XXX_Interrupt,
- i_APCI3XXX_Reset,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnWriteAnalogOutput,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- i_APCI3XXX_InsnConfigInitTTLIO,
- i_APCI3XXX_InsnBitsTTLIO,
- i_APCI3XXX_InsnReadTTLIO,
- i_APCI3XXX_InsnWriteTTLIO},
+ {
+ .pc_DriverName = "apci3000-16",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3010,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 16,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 16,
+ .i_AiMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3000-8",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x300F,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 8,
+ .i_NbrAiChannelDiff = 4,
+ .i_AiChannelList = 8,
+ .i_AiMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3000-4",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x300E,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 4,
+ .i_NbrAiChannelDiff = 2,
+ .i_AiChannelList = 4,
+ .i_AiMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3006-16",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3013,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 16,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 16,
+ .i_AiMaxdata = 65535,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3006-8",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3014,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 8,
+ .i_NbrAiChannelDiff = 4,
+ .i_AiChannelList = 8,
+ .i_AiMaxdata = 65535,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3006-4",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3015,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 4,
+ .i_NbrAiChannelDiff = 2,
+ .i_AiChannelList = 4,
+ .i_AiMaxdata = 65535,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3010-16",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3016,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 16,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 16,
+ .i_AiMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 5000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3010-8",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3017,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 8,
+ .i_NbrAiChannelDiff = 4,
+ .i_AiChannelList = 8,
+ .i_AiMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 5000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3010-4",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3018,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 4,
+ .i_NbrAiChannelDiff = 2,
+ .i_AiChannelList = 4,
+ .i_AiMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 5000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3016-16",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3019,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 16,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 16,
+ .i_AiMaxdata = 65535,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 5000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3016-8",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x301A,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 8,
+ .i_NbrAiChannelDiff = 4,
+ .i_AiChannelList = 8,
+ .i_AiMaxdata = 65535,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 5000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3016-4",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x301B,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 4,
+ .i_NbrAiChannelDiff = 2,
+ .i_AiChannelList = 4,
+ .i_AiMaxdata = 65535,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 5000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3100-16-4",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x301C,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 16,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 16,
+ .i_NbrAoChannel = 4,
+ .i_AiMaxdata = 4095,
+ .i_AoMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .pr_AoRangelist = &range_apci3XXX_ao,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3100-8-4",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x301D,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 8,
+ .i_NbrAiChannelDiff = 4,
+ .i_AiChannelList = 8,
+ .i_NbrAoChannel = 4,
+ .i_AiMaxdata = 4095,
+ .i_AoMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .pr_AoRangelist = &range_apci3XXX_ao,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3106-16-4",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x301E,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 16,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 16,
+ .i_NbrAoChannel = 4,
+ .i_AiMaxdata = 65535,
+ .i_AoMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .pr_AoRangelist = &range_apci3XXX_ao,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3106-8-4",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x301F,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 8,
+ .i_NbrAiChannelDiff = 4,
+ .i_AiChannelList = 8,
+ .i_NbrAoChannel = 4,
+ .i_AiMaxdata = 65535,
+ .i_AoMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .pr_AoRangelist = &range_apci3XXX_ao,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 10000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3110-16-4",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3020,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 16,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 16,
+ .i_NbrAoChannel = 4,
+ .i_AiMaxdata = 4095,
+ .i_AoMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .pr_AoRangelist = &range_apci3XXX_ao,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 5000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3110-8-4",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3021,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 8,
+ .i_NbrAiChannelDiff = 4,
+ .i_AiChannelList = 8,
+ .i_NbrAoChannel = 4,
+ .i_AiMaxdata = 4095,
+ .i_AoMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .pr_AoRangelist = &range_apci3XXX_ao,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 5000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3116-16-4",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3022,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 16,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 16,
+ .i_NbrAoChannel = 4,
+ .i_AiMaxdata = 65535,
+ .i_AoMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .pr_AoRangelist = &range_apci3XXX_ao,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 5000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3116-8-4",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3023,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannel = 8,
+ .i_NbrAiChannelDiff = 4,
+ .i_AiChannelList = 8,
+ .i_NbrAoChannel = 4,
+ .i_AiMaxdata = 65535,
+ .i_AoMaxdata = 4095,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .pr_AoRangelist = &range_apci3XXX_ao,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 5000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ }, {
+ .pc_DriverName = "apci3003",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x300B,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannelDiff = 4,
+ .i_AiChannelList = 4,
+ .i_AiMaxdata = 65535,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .b_AvailableConvertUnit = 7,
+ .ui_MinAcquisitiontimeNs = 2500,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ }, {
+ .pc_DriverName = "apci3002-16",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3002,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannelDiff = 16,
+ .i_AiChannelList = 16,
+ .i_AiMaxdata = 65535,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 5000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ }, {
+ .pc_DriverName = "apci3002-8",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3003,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannelDiff = 8,
+ .i_AiChannelList = 8,
+ .i_AiMaxdata = 65535,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 5000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ }, {
+ .pc_DriverName = "apci3002-4",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3004,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAiChannelDiff = 4,
+ .i_AiChannelList = 4,
+ .i_AiMaxdata = 65535,
+ .pr_AiRangelist = &range_apci3XXX_ai,
+ .i_NbrDiChannel = 4,
+ .i_NbrDoChannel = 4,
+ .i_DoMaxdata = 1,
+ .b_AvailableConvertUnit = 6,
+ .ui_MinAcquisitiontimeNs = 5000,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
+ .ai_read = i_APCI3XXX_InsnReadAnalogInput,
+ .di_read = i_APCI3XXX_InsnReadDigitalInput,
+ .di_bits = i_APCI3XXX_InsnBitsDigitalInput,
+ .do_write = i_APCI3XXX_InsnWriteDigitalOutput,
+ .do_bits = i_APCI3XXX_InsnBitsDigitalOutput,
+ .do_read = i_APCI3XXX_InsnReadDigitalOutput,
+ }, {
+ .pc_DriverName = "apci3500",
+ .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
+ .i_DeviceId = 0x3024,
+ .i_IorangeBase0 = 256,
+ .i_IorangeBase1 = 256,
+ .i_IorangeBase2 = 256,
+ .i_IorangeBase3 = 256,
+ .i_PCIEeprom = ADDIDATA_NO_EEPROM,
+ .pc_EepromChip = ADDIDATA_9054,
+ .i_NbrAoChannel = 4,
+ .i_AoMaxdata = 4095,
+ .pr_AoRangelist = &range_apci3XXX_ao,
+ .i_NbrTTLChannel = 24,
+ .pr_TTLRangelist = &range_apci3XXX_ttl,
+ .interrupt = v_APCI3XXX_Interrupt,
+ .reset = i_APCI3XXX_Reset,
+ .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
+ .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
+ .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
+ .ttl_read = i_APCI3XXX_InsnReadTTLIO,
+ .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ },
#endif
};
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct addi_board))
-
static struct comedi_driver driver_addi = {
.driver_name = ADDIDATA_DRIVER_NAME,
.module = THIS_MODULE,
.attach = i_ADDI_Attach,
.detach = i_ADDI_Detach,
- .num_names = n_boardtypes,
+ .num_names = ARRAY_SIZE(boardtypes),
.board_name = &boardtypes[0].pc_DriverName,
.offset = sizeof(struct addi_board),
};
@@ -2543,7 +1438,7 @@ static struct comedi_driver driver_addi = {
static int __devinit driver_addi_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_addi.driver_name);
+ return comedi_pci_auto_config(dev, &driver_addi);
}
static void __devexit driver_addi_pci_remove(struct pci_dev *dev)
@@ -2821,16 +1716,13 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* Set the initialisation flag */
devpriv->b_AiInitialisation = 1;
- s->insn_config =
- this_board->i_hwdrv_InsnConfigAnalogInput;
- s->insn_read = this_board->i_hwdrv_InsnReadAnalogInput;
- s->insn_write =
- this_board->i_hwdrv_InsnWriteAnalogInput;
- s->insn_bits = this_board->i_hwdrv_InsnBitsAnalogInput;
- s->do_cmdtest =
- this_board->i_hwdrv_CommandTestAnalogInput;
- s->do_cmd = this_board->i_hwdrv_CommandAnalogInput;
- s->cancel = this_board->i_hwdrv_CancelAnalogInput;
+ s->insn_config = this_board->ai_config;
+ s->insn_read = this_board->ai_read;
+ s->insn_write = this_board->ai_write;
+ s->insn_bits = this_board->ai_bits;
+ s->do_cmdtest = this_board->ai_cmdtest;
+ s->do_cmd = this_board->ai_cmd;
+ s->cancel = this_board->ai_cancel;
} else {
s->type = COMEDI_SUBD_UNUSED;
@@ -2846,10 +1738,8 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->len_chanlist =
devpriv->s_EeParameters.i_NbrAoChannel;
s->range_table = this_board->pr_AoRangelist;
- s->insn_config =
- this_board->i_hwdrv_InsnConfigAnalogOutput;
- s->insn_write =
- this_board->i_hwdrv_InsnWriteAnalogOutput;
+ s->insn_config = this_board->ao_config;
+ s->insn_write = this_board->ao_write;
} else {
s->type = COMEDI_SUBD_UNUSED;
}
@@ -2864,12 +1754,10 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->s_EeParameters.i_NbrDiChannel;
s->range_table = &range_digital;
s->io_bits = 0; /* all bits input */
- s->insn_config =
- this_board->i_hwdrv_InsnConfigDigitalInput;
- s->insn_read = this_board->i_hwdrv_InsnReadDigitalInput;
- s->insn_write =
- this_board->i_hwdrv_InsnWriteDigitalInput;
- s->insn_bits = this_board->i_hwdrv_InsnBitsDigitalInput;
+ s->insn_config = this_board->di_config;
+ s->insn_read = this_board->di_read;
+ s->insn_write = this_board->di_write;
+ s->insn_bits = this_board->di_bits;
} else {
s->type = COMEDI_SUBD_UNUSED;
}
@@ -2886,13 +1774,11 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->range_table = &range_digital;
s->io_bits = 0xf; /* all bits output */
- s->insn_config = this_board->i_hwdrv_InsnConfigDigitalOutput; /* for digital output memory.. */
- s->insn_write =
- this_board->i_hwdrv_InsnWriteDigitalOutput;
- s->insn_bits =
- this_board->i_hwdrv_InsnBitsDigitalOutput;
- s->insn_read =
- this_board->i_hwdrv_InsnReadDigitalOutput;
+ /* insn_config - for digital output memory */
+ s->insn_config = this_board->do_config;
+ s->insn_write = this_board->do_write;
+ s->insn_bits = this_board->do_bits;
+ s->insn_read = this_board->do_read;
} else {
s->type = COMEDI_SUBD_UNUSED;
}
@@ -2907,10 +1793,10 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->len_chanlist = 1;
s->range_table = &range_digital;
- s->insn_write = this_board->i_hwdrv_InsnWriteTimer;
- s->insn_read = this_board->i_hwdrv_InsnReadTimer;
- s->insn_config = this_board->i_hwdrv_InsnConfigTimer;
- s->insn_bits = this_board->i_hwdrv_InsnBitsTimer;
+ s->insn_write = this_board->timer_write;
+ s->insn_read = this_board->timer_read;
+ s->insn_config = this_board->timer_config;
+ s->insn_bits = this_board->timer_bits;
} else {
s->type = COMEDI_SUBD_UNUSED;
}
@@ -2926,10 +1812,10 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->io_bits = 0; /* all bits input */
s->len_chanlist = this_board->i_NbrTTLChannel;
s->range_table = &range_digital;
- s->insn_config = this_board->i_hwdr_ConfigInitTTLIO;
- s->insn_bits = this_board->i_hwdr_ReadTTLIOBits;
- s->insn_read = this_board->i_hwdr_ReadTTLIOAllPortValue;
- s->insn_write = this_board->i_hwdr_WriteTTLIOChlOnOff;
+ s->insn_config = this_board->ttl_config;
+ s->insn_bits = this_board->ttl_bits;
+ s->insn_read = this_board->ttl_read;
+ s->insn_write = this_board->ttl_write;
} else {
s->type = COMEDI_SUBD_UNUSED;
}
@@ -2953,50 +1839,22 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-/*
-+----------------------------------------------------------------------------+
-| Function name : static int i_ADDI_Detach(struct comedi_device *dev) |
-| |
-| |
-+----------------------------------------------------------------------------+
-| Task : Deallocates resources of the addi_common driver |
-| Free the DMA buffers, unregister irq. |
-| |
-+----------------------------------------------------------------------------+
-| Input Parameters : struct comedi_device *dev |
-| |
-| |
-+----------------------------------------------------------------------------+
-| Return Value : 0 |
-| |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_ADDI_Detach(struct comedi_device *dev)
+static void i_ADDI_Detach(struct comedi_device *dev)
{
-
if (dev->private) {
- if (devpriv->b_ValidDriver) {
+ if (devpriv->b_ValidDriver)
i_ADDI_Reset(dev);
- }
-
- if (dev->irq) {
+ if (dev->irq)
free_irq(dev->irq, dev);
- }
-
- if ((this_board->pc_EepromChip == NULL)
- || (strcmp(this_board->pc_EepromChip,
- ADDIDATA_9054) != 0)) {
- if (devpriv->allocated) {
+ if ((this_board->pc_EepromChip == NULL) ||
+ (strcmp(this_board->pc_EepromChip, ADDIDATA_9054) != 0)) {
+ if (devpriv->allocated)
i_pci_card_free(devpriv->amcc);
- }
-
if (devpriv->ul_DmaBufferVirtual[0]) {
free_pages((unsigned long)devpriv->
ul_DmaBufferVirtual[0],
devpriv->ui_DmaBufferPages[0]);
}
-
if (devpriv->ul_DmaBufferVirtual[1]) {
free_pages((unsigned long)devpriv->
ul_DmaBufferVirtual[1],
@@ -3004,20 +1862,14 @@ static int i_ADDI_Detach(struct comedi_device *dev)
}
} else {
iounmap(devpriv->dw_AiBase);
-
- if (devpriv->allocated) {
+ if (devpriv->allocated)
i_pci_card_free(devpriv->amcc);
- }
}
-
if (pci_list_builded) {
- /* v_pci_card_list_cleanup(PCI_VENDOR_ID_AMCC); */
v_pci_card_list_cleanup(this_board->i_VendorId);
pci_list_builded = 0;
}
}
-
- return 0;
}
/*
@@ -3041,7 +1893,7 @@ static int i_ADDI_Detach(struct comedi_device *dev)
static int i_ADDI_Reset(struct comedi_device *dev)
{
- this_board->i_hwdrv_Reset(dev);
+ this_board->reset(dev);
return 0;
}
@@ -3067,7 +1919,7 @@ static int i_ADDI_Reset(struct comedi_device *dev)
static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
- this_board->v_hwdrv_Interrupt(irq, d);
+ this_board->interrupt(irq, d);
return IRQ_RETVAL(1);
}
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
index c6980b7dfea0..2c3f34703dd2 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
@@ -94,111 +94,72 @@ struct addi_board {
unsigned int ui_MinDelaytimeNs; /* Minimum Delay in Nano secs */
/* interrupt and reset */
- void (*v_hwdrv_Interrupt)(int irq, void *d);
- int (*i_hwdrv_Reset)(struct comedi_device *dev);
+ void (*interrupt)(int irq, void *d);
+ int (*reset)(struct comedi_device *);
/* Subdevice functions */
/* ANALOG INPUT */
- int (*i_hwdrv_InsnConfigAnalogInput)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdrv_InsnReadAnalogInput)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdrv_InsnWriteAnalogInput)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdrv_InsnBitsAnalogInput)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdrv_CommandTestAnalogInput)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd);
- int (*i_hwdrv_CommandAnalogInput)(struct comedi_device *dev,
- struct comedi_subdevice *s);
- int (*i_hwdrv_CancelAnalogInput)(struct comedi_device *dev,
- struct comedi_subdevice *s);
+ int (*ai_config)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*ai_read)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*ai_write)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*ai_bits)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*ai_cmdtest)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_cmd *);
+ int (*ai_cmd)(struct comedi_device *, struct comedi_subdevice *);
+ int (*ai_cancel)(struct comedi_device *, struct comedi_subdevice *);
/* Analog Output */
- int (*i_hwdrv_InsnConfigAnalogOutput)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdrv_InsnWriteAnalogOutput)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdrv_InsnBitsAnalogOutput)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
+ int (*ao_config)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*ao_write)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*ao_bits)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
/* Digital Input */
- int (*i_hwdrv_InsnConfigDigitalInput) (struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdrv_InsnReadDigitalInput) (struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdrv_InsnWriteDigitalInput) (struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdrv_InsnBitsDigitalInput) (struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
+ int (*di_config)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*di_read)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*di_write)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*di_bits)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
/* Digital Output */
- int (*i_hwdrv_InsnConfigDigitalOutput)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdrv_InsnWriteDigitalOutput)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdrv_InsnBitsDigitalOutput)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdrv_InsnReadDigitalOutput)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
+ int (*do_config)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*do_write)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*do_bits)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*do_read)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
/* TIMER */
- int (*i_hwdrv_InsnConfigTimer)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
- int (*i_hwdrv_InsnWriteTimer)(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdrv_InsnReadTimer)(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
- int (*i_hwdrv_InsnBitsTimer)(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
+ int (*timer_config)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*timer_write)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*timer_read)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*timer_bits)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
/* TTL IO */
- int (*i_hwdr_ConfigInitTTLIO)(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdr_ReadTTLIOBits)(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
- int (*i_hwdr_ReadTTLIOAllPortValue)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
- int (*i_hwdr_WriteTTLIOChlOnOff)(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
+ int (*ttl_config)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*ttl_bits)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*ttl_read)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+ int (*ttl_write)(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
};
/* MODULE INFO STRUCTURE */
@@ -455,7 +416,7 @@ static unsigned short pci_list_builded; /* set to 1 when list of card is known *
/* Function declarations */
static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int i_ADDI_Detach(struct comedi_device *dev);
+static void i_ADDI_Detach(struct comedi_device *dev);
static int i_ADDI_Reset(struct comedi_device *dev);
static irqreturn_t v_ADDI_Interrupt(int irq, void *d);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
index e886ced4978f..ffe390c6da83 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
@@ -156,7 +156,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subd
} else
us_ConvertTiming = (unsigned short) (devpriv->ui_EocEosConversionTime / 1000); /* nano to useconds */
- /* this_board->i_hwdrv_InsnReadAnalogInput(dev,us_ConvertTiming,insn->n,&insn->chanspec,data,insn->unused[0]); */
+ /* this_board->ai_read(dev,us_ConvertTiming,insn->n,&insn->chanspec,data,insn->unused[0]); */
/* Clear software registers */
devpriv->b_TimerSelectMode = 0;
@@ -670,7 +670,7 @@ int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subde
/* mode 1 */
devpriv->ui_AiTimer0 = cmd->convert_arg; /* timer constant in nano seconds */
- /* return this_board->i_hwdrv_CommandAnalogInput(1,dev,s); */
+ /* return this_board->ai_cmd(1,dev,s); */
return i_APCI3120_CyclicAnalogInput(1, dev, s);
}
@@ -680,7 +680,7 @@ int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subde
/* mode 2 */
devpriv->ui_AiTimer1 = cmd->scan_begin_arg;
devpriv->ui_AiTimer0 = cmd->convert_arg; /* variable changed timer2 to timer0 */
- /* return this_board->i_hwdrv_CommandAnalogInput(2,dev,s); */
+ /* return this_board->ai_cmd(2,dev,s); */
return i_APCI3120_CyclicAnalogInput(2, dev, s);
}
return -1;
@@ -1922,7 +1922,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevic
ui_Timervalue2 = data[1] / 1000; /* convert nano seconds to u seconds */
- /* this_board->i_hwdrv_InsnConfigTimer(dev, ui_Timervalue2,(unsigned char)data[0]); */
+ /* this_board->timer_config(dev, ui_Timervalue2,(unsigned char)data[0]); */
us_TmpValue = (unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
/*
@@ -2092,7 +2092,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice
ui_Timervalue2 = 0;
}
- /* this_board->i_hwdrv_InsnWriteTimer(dev,data[0],ui_Timervalue2); */
+ /* this_board->timer_write(dev,data[0],ui_Timervalue2); */
switch (data[0]) {
case APCI3120_START:
@@ -2260,7 +2260,7 @@ int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice
comedi_error(dev, "\nread:timer2 not configured ");
}
- /* this_board->i_hwdrv_InsnReadTimer(dev,data); */
+ /* this_board->timer_read(dev,data); */
if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
/* Read the LOW unsigned short of Timer 2 register */
@@ -2331,7 +2331,7 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
ui_Chan = CR_CHAN(insn->chanspec); /* channel specified */
- /* this_board->i_hwdrv_InsnReadDigitalInput(dev,ui_Chan,data); */
+ /* this_board->di_read(dev,ui_Chan,data); */
if (ui_Chan <= 3) {
ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS);
@@ -2379,7 +2379,7 @@ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_sub
*****/
*data = (ui_TmpValue >> 8) & 0xf;
- /* this_board->i_hwdrv_InsnBitsDigitalInput(dev,data); */
+ /* this_board->di_bits(dev,data); */
return insn->n;
}
@@ -2595,7 +2595,7 @@ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
ui_Range = CR_RANGE(insn->chanspec);
ui_Channel = CR_CHAN(insn->chanspec);
- /* this_board->i_hwdrv_InsnWriteAnalogOutput(dev, ui_Range, ui_Channel,data[0]); */
+ /* this_board->ao_write(dev, ui_Range, ui_Channel,data[0]); */
if (ui_Range) { /* if 1 then unipolar */
if (data[0] != 0)
diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
index 4fc9e8520217..de8c68af3210 100644
--- a/drivers/staging/comedi/drivers/adl_pci6208.c
+++ b/drivers/staging/comedi/drivers/adl_pci6208.c
@@ -54,8 +54,6 @@ References:
#include "../comedidev.h"
#include "comedi_pci.h"
-#define PCI6208_DRIVER_NAME "adl_pci6208"
-
/* Board descriptions */
struct pci6208_board {
const char *name;
@@ -85,17 +83,6 @@ static const struct pci6208_board pci6208_boards[] = {
}
};
-/* This is used by modprobe to translate PCI IDs to drivers. Should
- * only be used for PCI and ISA-PnP devices */
-static DEFINE_PCI_DEVICE_TABLE(pci6208_pci_table) = {
- /* { PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
- /* { PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
- { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x6208) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, pci6208_pci_table);
-
/* Will be initialized in pci6208_find device(). */
#define thisboard ((const struct pci6208_board *)dev->board_ptr)
@@ -107,157 +94,6 @@ struct pci6208_private {
#define devpriv ((struct pci6208_private *)dev->private)
-static int pci6208_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pci6208_detach(struct comedi_device *dev);
-
-static struct comedi_driver driver_pci6208 = {
- .driver_name = PCI6208_DRIVER_NAME,
- .module = THIS_MODULE,
- .attach = pci6208_attach,
- .detach = pci6208_detach,
-};
-
-static int __devinit driver_pci6208_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, driver_pci6208.driver_name);
-}
-
-static void __devexit driver_pci6208_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver driver_pci6208_pci_driver = {
- .id_table = pci6208_pci_table,
- .probe = &driver_pci6208_pci_probe,
- .remove = __devexit_p(&driver_pci6208_pci_remove)
-};
-
-static int __init driver_pci6208_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_pci6208);
- if (retval < 0)
- return retval;
-
- driver_pci6208_pci_driver.name = (char *)driver_pci6208.driver_name;
- return pci_register_driver(&driver_pci6208_pci_driver);
-}
-
-static void __exit driver_pci6208_cleanup_module(void)
-{
- pci_unregister_driver(&driver_pci6208_pci_driver);
- comedi_driver_unregister(&driver_pci6208);
-}
-
-module_init(driver_pci6208_init_module);
-module_exit(driver_pci6208_cleanup_module);
-
-static int pci6208_find_device(struct comedi_device *dev, int bus, int slot);
-static int
-pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
- int dev_minor);
-
-/*read/write functions*/
-static int pci6208_ao_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int pci6208_ao_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-/* static int pci6208_dio_insn_bits (struct comedi_device *dev,
- * struct comedi_subdevice *s, */
-/* struct comedi_insn *insn,unsigned int *data); */
-/* static int pci6208_dio_insn_config(struct comedi_device *dev,
- * struct comedi_subdevice *s, */
-/* struct comedi_insn *insn,unsigned int *data); */
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
-static int pci6208_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- int retval;
- unsigned long io_base;
-
- printk(KERN_INFO "comedi%d: pci6208: ", dev->minor);
-
- retval = alloc_private(dev, sizeof(struct pci6208_private));
- if (retval < 0)
- return retval;
-
- retval = pci6208_find_device(dev, it->options[0], it->options[1]);
- if (retval < 0)
- return retval;
-
- retval = pci6208_pci_setup(devpriv->pci_dev, &io_base, dev->minor);
- if (retval < 0)
- return retval;
-
- dev->iobase = io_base;
- dev->board_name = thisboard->name;
-
-/*
- * Allocate the subdevice structures. alloc_subdevice() is a
- * convenient macro defined in comedidev.h.
- */
- if (alloc_subdevices(dev, 2) < 0)
- return -ENOMEM;
-
- s = dev->subdevices + 0;
- /* analog output subdevice */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE; /* anything else to add here?? */
- s->n_chan = thisboard->ao_chans;
- s->maxdata = 0xffff; /* 16-bit DAC */
- s->range_table = &range_bipolar10; /* this needs to be checked. */
- s->insn_write = pci6208_ao_winsn;
- s->insn_read = pci6208_ao_rinsn;
-
- /* s=dev->subdevices+1; */
- /* digital i/o subdevice */
- /* s->type=COMEDI_SUBD_DIO; */
- /* s->subdev_flags=SDF_READABLE|SDF_WRITABLE; */
- /* s->n_chan=16; */
- /* s->maxdata=1; */
- /* s->range_table=&range_digital; */
- /* s->insn_bits = pci6208_dio_insn_bits; */
- /* s->insn_config = pci6208_dio_insn_config; */
-
- printk(KERN_INFO "attached\n");
-
- return 1;
-}
-
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int pci6208_detach(struct comedi_device *dev)
-{
- printk(KERN_INFO "comedi%d: pci6208: remove\n", dev->minor);
-
- if (devpriv && devpriv->pci_dev) {
- if (dev->iobase)
- comedi_pci_disable(devpriv->pci_dev);
- pci_dev_put(devpriv->pci_dev);
- }
-
- return 0;
-}
-
static int pci6208_ao_winsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -410,7 +246,7 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
/* Enable PCI device and request regions */
- if (comedi_pci_enable(pci_dev, PCI6208_DRIVER_NAME) < 0) {
+ if (comedi_pci_enable(pci_dev, "adl_pci6208") < 0) {
printk(KERN_ERR "comedi%d: Failed to enable PCI device "
"and request regions\n",
dev_minor);
@@ -442,6 +278,103 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
return 0;
}
+static int pci6208_attach(struct comedi_device *dev,
+ struct comedi_devconfig *it)
+{
+ struct comedi_subdevice *s;
+ int retval;
+ unsigned long io_base;
+
+ printk(KERN_INFO "comedi%d: pci6208: ", dev->minor);
+
+ retval = alloc_private(dev, sizeof(struct pci6208_private));
+ if (retval < 0)
+ return retval;
+
+ retval = pci6208_find_device(dev, it->options[0], it->options[1]);
+ if (retval < 0)
+ return retval;
+
+ retval = pci6208_pci_setup(devpriv->pci_dev, &io_base, dev->minor);
+ if (retval < 0)
+ return retval;
+
+ dev->iobase = io_base;
+ dev->board_name = thisboard->name;
+
+ if (alloc_subdevices(dev, 2) < 0)
+ return -ENOMEM;
+
+ s = dev->subdevices + 0;
+ /* analog output subdevice */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE; /* anything else to add here?? */
+ s->n_chan = thisboard->ao_chans;
+ s->maxdata = 0xffff; /* 16-bit DAC */
+ s->range_table = &range_bipolar10; /* this needs to be checked. */
+ s->insn_write = pci6208_ao_winsn;
+ s->insn_read = pci6208_ao_rinsn;
+
+ /* s=dev->subdevices+1; */
+ /* digital i/o subdevice */
+ /* s->type=COMEDI_SUBD_DIO; */
+ /* s->subdev_flags=SDF_READABLE|SDF_WRITABLE; */
+ /* s->n_chan=16; */
+ /* s->maxdata=1; */
+ /* s->range_table=&range_digital; */
+ /* s->insn_bits = pci6208_dio_insn_bits; */
+ /* s->insn_config = pci6208_dio_insn_config; */
+
+ printk(KERN_INFO "attached\n");
+
+ return 1;
+}
+
+static void pci6208_detach(struct comedi_device *dev)
+{
+ if (devpriv && devpriv->pci_dev) {
+ if (dev->iobase)
+ comedi_pci_disable(devpriv->pci_dev);
+ pci_dev_put(devpriv->pci_dev);
+ }
+}
+
+static struct comedi_driver adl_pci6208_driver = {
+ .driver_name = "adl_pci6208",
+ .module = THIS_MODULE,
+ .attach = pci6208_attach,
+ .detach = pci6208_detach,
+};
+
+static int __devinit adl_pci6208_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &adl_pci6208_driver);
+}
+
+static void __devexit adl_pci6208_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+/* This is used by modprobe to translate PCI IDs to drivers. Should
+ * only be used for PCI and ISA-PnP devices */
+static DEFINE_PCI_DEVICE_TABLE(adl_pci6208_pci_table) = {
+ /* { PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
+ /* { PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x6208) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, adl_pci6208_pci_table);
+
+static struct pci_driver adl_pci6208_pci_driver = {
+ .name = "adl_pci6208",
+ .id_table = adl_pci6208_pci_table,
+ .probe = adl_pci6208_pci_probe,
+ .remove = __devexit_p(adl_pci6208_pci_remove),
+};
+module_comedi_pci_driver(adl_pci6208_driver, adl_pci6208_pci_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/adl_pci7230.c b/drivers/staging/comedi/drivers/adl_pci7230.c
index 20d570554fa4..e8053bc825f4 100644
--- a/drivers/staging/comedi/drivers/adl_pci7230.c
+++ b/drivers/staging/comedi/drivers/adl_pci7230.c
@@ -43,13 +43,6 @@ Configuration Options:
#define PCI_DEVICE_ID_PCI7230 0x7230
-static DEFINE_PCI_DEVICE_TABLE(adl_pci7230_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7230) },
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, adl_pci7230_pci_table);
-
struct adl_pci7230_private {
int data;
struct pci_dev *pci_dev;
@@ -57,27 +50,36 @@ struct adl_pci7230_private {
#define devpriv ((struct adl_pci7230_private *)dev->private)
-static int adl_pci7230_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int adl_pci7230_detach(struct comedi_device *dev);
-static struct comedi_driver driver_adl_pci7230 = {
- .driver_name = "adl_pci7230",
- .module = THIS_MODULE,
- .attach = adl_pci7230_attach,
- .detach = adl_pci7230_detach,
-};
+static int adl_pci7230_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ if (insn->n != 2)
+ return -EINVAL;
+
+ if (data[0]) {
+ s->state &= ~data[0];
+ s->state |= (data[0] & data[1]);
+
+ outl((s->state << 16) & 0xffffffff, dev->iobase + PCI7230_DO);
+ }
-/* Digital IO */
+ return 2;
+}
static int adl_pci7230_di_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
- unsigned int *data);
+ unsigned int *data)
+{
+ if (insn->n != 2)
+ return -EINVAL;
-static int adl_pci7230_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
+ data[1] = inl(dev->iobase + PCI7230_DI) & 0xffffffff;
+
+ return 2;
+}
static int adl_pci7230_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
@@ -148,89 +150,46 @@ static int adl_pci7230_attach(struct comedi_device *dev,
return 1;
}
-static int adl_pci7230_detach(struct comedi_device *dev)
+static void adl_pci7230_detach(struct comedi_device *dev)
{
- printk(KERN_DEBUG "comedi%d: pci7230: remove\n", dev->minor);
-
if (devpriv && devpriv->pci_dev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
pci_dev_put(devpriv->pci_dev);
}
-
- return 0;
-}
-
-static int adl_pci7230_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- if (insn->n != 2)
- return -EINVAL;
-
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
-
- outl((s->state << 16) & 0xffffffff, dev->iobase + PCI7230_DO);
- }
-
- return 2;
}
-static int adl_pci7230_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- if (insn->n != 2)
- return -EINVAL;
-
- data[1] = inl(dev->iobase + PCI7230_DI) & 0xffffffff;
-
- return 2;
-}
+static struct comedi_driver adl_pci7230_driver = {
+ .driver_name = "adl_pci7230",
+ .module = THIS_MODULE,
+ .attach = adl_pci7230_attach,
+ .detach = adl_pci7230_detach,
+};
-static int __devinit driver_adl_pci7230_pci_probe(struct pci_dev *dev,
- const struct pci_device_id
- *ent)
+static int __devinit adl_pci7230_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_adl_pci7230.driver_name);
+ return comedi_pci_auto_config(dev, &adl_pci7230_driver);
}
-static void __devexit driver_adl_pci7230_pci_remove(struct pci_dev *dev)
+static void __devexit adl_pci7230_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_adl_pci7230_pci_driver = {
- .id_table = adl_pci7230_pci_table,
- .probe = &driver_adl_pci7230_pci_probe,
- .remove = __devexit_p(&driver_adl_pci7230_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(adl_pci7230_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7230) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, adl_pci7230_pci_table);
-static int __init driver_adl_pci7230_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_adl_pci7230);
- if (retval < 0)
- return retval;
-
- driver_adl_pci7230_pci_driver.name =
- (char *)driver_adl_pci7230.driver_name;
- return pci_register_driver(&driver_adl_pci7230_pci_driver);
-}
-
-static void __exit driver_adl_pci7230_cleanup_module(void)
-{
- pci_unregister_driver(&driver_adl_pci7230_pci_driver);
- comedi_driver_unregister(&driver_adl_pci7230);
-}
-
-module_init(driver_adl_pci7230_init_module);
-module_exit(driver_adl_pci7230_cleanup_module);
+static struct pci_driver adl_pci7230_pci_driver = {
+ .name = "adl_pci7230",
+ .id_table = adl_pci7230_pci_table,
+ .probe = adl_pci7230_pci_probe,
+ .remove = __devexit_p(adl_pci7230_pci_remove),
+};
+module_comedi_pci_driver(adl_pci7230_driver, adl_pci7230_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c
index 9a2320537bdb..b4dae3b7598b 100644
--- a/drivers/staging/comedi/drivers/adl_pci7296.c
+++ b/drivers/staging/comedi/drivers/adl_pci7296.c
@@ -48,13 +48,6 @@ Configuration Options:
#define PCI_DEVICE_ID_PCI7296 0x7296
-static DEFINE_PCI_DEVICE_TABLE(adl_pci7296_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7296) },
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, adl_pci7296_pci_table);
-
struct adl_pci7296_private {
int data;
struct pci_dev *pci_dev;
@@ -63,16 +56,6 @@ struct adl_pci7296_private {
#define devpriv ((struct adl_pci7296_private *)dev->private)
static int adl_pci7296_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int adl_pci7296_detach(struct comedi_device *dev);
-static struct comedi_driver driver_adl_pci7296 = {
- .driver_name = "adl_pci7296",
- .module = THIS_MODULE,
- .attach = adl_pci7296_attach,
- .detach = adl_pci7296_detach,
-};
-
-static int adl_pci7296_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
struct pci_dev *pcidev = NULL;
@@ -151,66 +134,52 @@ static int adl_pci7296_attach(struct comedi_device *dev,
return -EIO;
}
-static int adl_pci7296_detach(struct comedi_device *dev)
+static void adl_pci7296_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: pci7432: remove\n", dev->minor);
-
if (devpriv && devpriv->pci_dev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
pci_dev_put(devpriv->pci_dev);
}
- /* detach four 8255 digital io subdevices */
if (dev->subdevices) {
subdev_8255_cleanup(dev, dev->subdevices + 0);
subdev_8255_cleanup(dev, dev->subdevices + 1);
subdev_8255_cleanup(dev, dev->subdevices + 2);
subdev_8255_cleanup(dev, dev->subdevices + 3);
-
}
-
- return 0;
}
-static int __devinit driver_adl_pci7296_pci_probe(struct pci_dev *dev,
- const struct pci_device_id
- *ent)
+static struct comedi_driver adl_pci7296_driver = {
+ .driver_name = "adl_pci7296",
+ .module = THIS_MODULE,
+ .attach = adl_pci7296_attach,
+ .detach = adl_pci7296_detach,
+};
+
+static int __devinit adl_pci7296_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_adl_pci7296.driver_name);
+ return comedi_pci_auto_config(dev, &adl_pci7296_driver);
}
-static void __devexit driver_adl_pci7296_pci_remove(struct pci_dev *dev)
+static void __devexit adl_pci7296_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_adl_pci7296_pci_driver = {
- .id_table = adl_pci7296_pci_table,
- .probe = &driver_adl_pci7296_pci_probe,
- .remove = __devexit_p(&driver_adl_pci7296_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(adl_pci7296_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7296) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, adl_pci7296_pci_table);
-static int __init driver_adl_pci7296_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_adl_pci7296);
- if (retval < 0)
- return retval;
-
- driver_adl_pci7296_pci_driver.name =
- (char *)driver_adl_pci7296.driver_name;
- return pci_register_driver(&driver_adl_pci7296_pci_driver);
-}
-
-static void __exit driver_adl_pci7296_cleanup_module(void)
-{
- pci_unregister_driver(&driver_adl_pci7296_pci_driver);
- comedi_driver_unregister(&driver_adl_pci7296);
-}
-
-module_init(driver_adl_pci7296_init_module);
-module_exit(driver_adl_pci7296_cleanup_module);
+static struct pci_driver adl_pci7296_pci_driver = {
+ .name = "adl_pci7296",
+ .id_table = adl_pci7296_pci_table,
+ .probe = adl_pci7296_pci_probe,
+ .remove = __devexit_p(adl_pci7296_pci_remove),
+};
+module_comedi_pci_driver(adl_pci7296_driver, adl_pci7296_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c
index 86ee21976041..9cbfb61a4478 100644
--- a/drivers/staging/comedi/drivers/adl_pci7432.c
+++ b/drivers/staging/comedi/drivers/adl_pci7432.c
@@ -43,13 +43,6 @@ Configuration Options:
#define PCI_DEVICE_ID_PCI7432 0x7432
-static DEFINE_PCI_DEVICE_TABLE(adl_pci7432_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432) },
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, adl_pci7432_pci_table);
-
struct adl_pci7432_private {
int data;
struct pci_dev *pci_dev;
@@ -57,29 +50,44 @@ struct adl_pci7432_private {
#define devpriv ((struct adl_pci7432_private *)dev->private)
-static int adl_pci7432_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int adl_pci7432_detach(struct comedi_device *dev);
-static struct comedi_driver driver_adl_pci7432 = {
- .driver_name = "adl_pci7432",
- .module = THIS_MODULE,
- .attach = adl_pci7432_attach,
- .detach = adl_pci7432_detach,
-};
+static int adl_pci7432_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ printk(KERN_DEBUG "comedi: pci7432_do_insn_bits called\n");
+ printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
+
+ if (insn->n != 2)
+ return -EINVAL;
-/* Digital IO */
+ if (data[0]) {
+ s->state &= ~data[0];
+ s->state |= (data[0] & data[1]);
+
+ printk(KERN_DEBUG "comedi: out: %8x on iobase %4lx\n", s->state,
+ dev->iobase + PCI7432_DO);
+ outl(s->state & 0xffffffff, dev->iobase + PCI7432_DO);
+ }
+ return 2;
+}
static int adl_pci7432_di_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
- unsigned int *data);
+ unsigned int *data)
+{
+ printk(KERN_DEBUG "comedi: pci7432_di_insn_bits called\n");
+ printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
-static int adl_pci7432_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
+ if (insn->n != 2)
+ return -EINVAL;
+
+ data[1] = inl(dev->iobase + PCI7432_DI) & 0xffffffff;
+ printk(KERN_DEBUG "comedi: data1 %8x\n", data[1]);
-/* */
+ return 2;
+}
static int adl_pci7432_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
@@ -153,97 +161,46 @@ static int adl_pci7432_attach(struct comedi_device *dev,
return -EIO;
}
-static int adl_pci7432_detach(struct comedi_device *dev)
+static void adl_pci7432_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: pci7432: remove\n", dev->minor);
-
if (devpriv && devpriv->pci_dev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
pci_dev_put(devpriv->pci_dev);
}
-
- return 0;
}
-static int adl_pci7432_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- printk(KERN_DEBUG "comedi: pci7432_do_insn_bits called\n");
- printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
-
- if (insn->n != 2)
- return -EINVAL;
-
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
-
- printk(KERN_DEBUG "comedi: out: %8x on iobase %4lx\n", s->state,
- dev->iobase + PCI7432_DO);
- outl(s->state & 0xffffffff, dev->iobase + PCI7432_DO);
- }
- return 2;
-}
-
-static int adl_pci7432_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- printk(KERN_DEBUG "comedi: pci7432_di_insn_bits called\n");
- printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
-
- if (insn->n != 2)
- return -EINVAL;
-
- data[1] = inl(dev->iobase + PCI7432_DI) & 0xffffffff;
- printk(KERN_DEBUG "comedi: data1 %8x\n", data[1]);
-
- return 2;
-}
+static struct comedi_driver adl_pci7432_driver = {
+ .driver_name = "adl_pci7432",
+ .module = THIS_MODULE,
+ .attach = adl_pci7432_attach,
+ .detach = adl_pci7432_detach,
+};
-static int __devinit driver_adl_pci7432_pci_probe(struct pci_dev *dev,
- const struct pci_device_id
- *ent)
+static int __devinit adl_pci7432_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_adl_pci7432.driver_name);
+ return comedi_pci_auto_config(dev, &adl_pci7432_driver);
}
-static void __devexit driver_adl_pci7432_pci_remove(struct pci_dev *dev)
+static void __devexit adl_pci7432_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_adl_pci7432_pci_driver = {
- .id_table = adl_pci7432_pci_table,
- .probe = &driver_adl_pci7432_pci_probe,
- .remove = __devexit_p(&driver_adl_pci7432_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(adl_pci7432_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, adl_pci7432_pci_table);
-static int __init driver_adl_pci7432_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_adl_pci7432);
- if (retval < 0)
- return retval;
-
- driver_adl_pci7432_pci_driver.name =
- (char *)driver_adl_pci7432.driver_name;
- return pci_register_driver(&driver_adl_pci7432_pci_driver);
-}
-
-static void __exit driver_adl_pci7432_cleanup_module(void)
-{
- pci_unregister_driver(&driver_adl_pci7432_pci_driver);
- comedi_driver_unregister(&driver_adl_pci7432);
-}
-
-module_init(driver_adl_pci7432_init_module);
-module_exit(driver_adl_pci7432_cleanup_module);
+static struct pci_driver adl_pci7432_pci_driver = {
+ .name = "adl_pci7432",
+ .id_table = adl_pci7432_pci_table,
+ .probe = adl_pci7432_pci_probe,
+ .remove = __devexit_p(adl_pci7432_pci_remove),
+};
+module_comedi_pci_driver(adl_pci7432_driver, adl_pci7432_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
index 3b83d65bc1bc..409ef13ad090 100644
--- a/drivers/staging/comedi/drivers/adl_pci8164.c
+++ b/drivers/staging/comedi/drivers/adl_pci8164.c
@@ -56,13 +56,6 @@ Configuration Options:
#define PCI_DEVICE_ID_PCI8164 0x8164
-static DEFINE_PCI_DEVICE_TABLE(adl_pci8164_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI8164) },
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, adl_pci8164_pci_table);
-
struct adl_pci8164_private {
int data;
struct pci_dev *pci_dev;
@@ -70,159 +63,6 @@ struct adl_pci8164_private {
#define devpriv ((struct adl_pci8164_private *)dev->private)
-static int adl_pci8164_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int adl_pci8164_detach(struct comedi_device *dev);
-static struct comedi_driver driver_adl_pci8164 = {
- .driver_name = "adl_pci8164",
- .module = THIS_MODULE,
- .attach = adl_pci8164_attach,
- .detach = adl_pci8164_detach,
-};
-
-static int adl_pci8164_insn_read_msts(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
-
-static int adl_pci8164_insn_read_ssts(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
-
-static int adl_pci8164_insn_read_buf0(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
-
-static int adl_pci8164_insn_read_buf1(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
-
-static int adl_pci8164_insn_write_cmd(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
-
-static int adl_pci8164_insn_write_otp(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
-
-static int adl_pci8164_insn_write_buf0(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
-
-static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
-
-static int adl_pci8164_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- struct comedi_subdevice *s;
- int bus, slot;
-
- printk(KERN_INFO "comedi: attempt to attach...\n");
- printk(KERN_INFO "comedi%d: adl_pci8164\n", dev->minor);
-
- dev->board_name = "pci8164";
- bus = it->options[0];
- slot = it->options[1];
-
- if (alloc_private(dev, sizeof(struct adl_pci8164_private)) < 0)
- return -ENOMEM;
-
- if (alloc_subdevices(dev, 4) < 0)
- return -ENOMEM;
-
- for_each_pci_dev(pcidev) {
- if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
- pcidev->device == PCI_DEVICE_ID_PCI8164) {
- if (bus || slot) {
- /* requested particular bus/slot */
- if (pcidev->bus->number != bus
- || PCI_SLOT(pcidev->devfn) != slot)
- continue;
- }
- devpriv->pci_dev = pcidev;
- if (comedi_pci_enable(pcidev, "adl_pci8164") < 0) {
- printk(KERN_ERR "comedi%d: Failed to enable "
- "PCI device and request regions\n", dev->minor);
- return -EIO;
- }
- dev->iobase = pci_resource_start(pcidev, 2);
- printk(KERN_DEBUG "comedi: base addr %4lx\n",
- dev->iobase);
-
- s = dev->subdevices + 0;
- s->type = COMEDI_SUBD_PROC;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 4;
- s->maxdata = 0xffff;
- s->len_chanlist = 4;
- /* s->range_table = &range_axis; */
- s->insn_read = adl_pci8164_insn_read_msts;
- s->insn_write = adl_pci8164_insn_write_cmd;
-
- s = dev->subdevices + 1;
- s->type = COMEDI_SUBD_PROC;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 4;
- s->maxdata = 0xffff;
- s->len_chanlist = 4;
- /* s->range_table = &range_axis; */
- s->insn_read = adl_pci8164_insn_read_ssts;
- s->insn_write = adl_pci8164_insn_write_otp;
-
- s = dev->subdevices + 2;
- s->type = COMEDI_SUBD_PROC;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 4;
- s->maxdata = 0xffff;
- s->len_chanlist = 4;
- /* s->range_table = &range_axis; */
- s->insn_read = adl_pci8164_insn_read_buf0;
- s->insn_write = adl_pci8164_insn_write_buf0;
-
- s = dev->subdevices + 3;
- s->type = COMEDI_SUBD_PROC;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 4;
- s->maxdata = 0xffff;
- s->len_chanlist = 4;
- /* s->range_table = &range_axis; */
- s->insn_read = adl_pci8164_insn_read_buf1;
- s->insn_write = adl_pci8164_insn_write_buf1;
-
- printk(KERN_INFO "comedi: attached\n");
-
- return 1;
- }
- }
-
- printk(KERN_ERR "comedi%d: no supported board found!"
- "(req. bus/slot : %d/%d)\n", dev->minor, bus, slot);
- return -EIO;
-}
-
-static int adl_pci8164_detach(struct comedi_device *dev)
-{
- printk(KERN_INFO "comedi%d: pci8164: remove\n", dev->minor);
-
- if (devpriv && devpriv->pci_dev) {
- if (dev->iobase)
- comedi_pci_disable(devpriv->pci_dev);
- pci_dev_put(devpriv->pci_dev);
- }
-
- return 0;
-}
-
/*
all the read commands are the same except for the addition a constant
* const to the data for inw()
@@ -384,45 +224,136 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
return 2;
}
-static int __devinit driver_adl_pci8164_pci_probe(struct pci_dev *dev,
- const struct pci_device_id
- *ent)
+static int adl_pci8164_attach(struct comedi_device *dev,
+ struct comedi_devconfig *it)
{
- return comedi_pci_auto_config(dev, driver_adl_pci8164.driver_name);
+ struct pci_dev *pcidev = NULL;
+ struct comedi_subdevice *s;
+ int bus, slot;
+
+ printk(KERN_INFO "comedi: attempt to attach...\n");
+ printk(KERN_INFO "comedi%d: adl_pci8164\n", dev->minor);
+
+ dev->board_name = "pci8164";
+ bus = it->options[0];
+ slot = it->options[1];
+
+ if (alloc_private(dev, sizeof(struct adl_pci8164_private)) < 0)
+ return -ENOMEM;
+
+ if (alloc_subdevices(dev, 4) < 0)
+ return -ENOMEM;
+
+ for_each_pci_dev(pcidev) {
+ if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
+ pcidev->device == PCI_DEVICE_ID_PCI8164) {
+ if (bus || slot) {
+ /* requested particular bus/slot */
+ if (pcidev->bus->number != bus
+ || PCI_SLOT(pcidev->devfn) != slot)
+ continue;
+ }
+ devpriv->pci_dev = pcidev;
+ if (comedi_pci_enable(pcidev, "adl_pci8164") < 0) {
+ printk(KERN_ERR "comedi%d: Failed to enable "
+ "PCI device and request regions\n", dev->minor);
+ return -EIO;
+ }
+ dev->iobase = pci_resource_start(pcidev, 2);
+ printk(KERN_DEBUG "comedi: base addr %4lx\n",
+ dev->iobase);
+
+ s = dev->subdevices + 0;
+ s->type = COMEDI_SUBD_PROC;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 4;
+ s->maxdata = 0xffff;
+ s->len_chanlist = 4;
+ /* s->range_table = &range_axis; */
+ s->insn_read = adl_pci8164_insn_read_msts;
+ s->insn_write = adl_pci8164_insn_write_cmd;
+
+ s = dev->subdevices + 1;
+ s->type = COMEDI_SUBD_PROC;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 4;
+ s->maxdata = 0xffff;
+ s->len_chanlist = 4;
+ /* s->range_table = &range_axis; */
+ s->insn_read = adl_pci8164_insn_read_ssts;
+ s->insn_write = adl_pci8164_insn_write_otp;
+
+ s = dev->subdevices + 2;
+ s->type = COMEDI_SUBD_PROC;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 4;
+ s->maxdata = 0xffff;
+ s->len_chanlist = 4;
+ /* s->range_table = &range_axis; */
+ s->insn_read = adl_pci8164_insn_read_buf0;
+ s->insn_write = adl_pci8164_insn_write_buf0;
+
+ s = dev->subdevices + 3;
+ s->type = COMEDI_SUBD_PROC;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 4;
+ s->maxdata = 0xffff;
+ s->len_chanlist = 4;
+ /* s->range_table = &range_axis; */
+ s->insn_read = adl_pci8164_insn_read_buf1;
+ s->insn_write = adl_pci8164_insn_write_buf1;
+
+ printk(KERN_INFO "comedi: attached\n");
+
+ return 1;
+ }
+ }
+
+ printk(KERN_ERR "comedi%d: no supported board found!"
+ "(req. bus/slot : %d/%d)\n", dev->minor, bus, slot);
+ return -EIO;
}
-static void __devexit driver_adl_pci8164_pci_remove(struct pci_dev *dev)
+static void adl_pci8164_detach(struct comedi_device *dev)
{
- comedi_pci_auto_unconfig(dev);
+ if (devpriv && devpriv->pci_dev) {
+ if (dev->iobase)
+ comedi_pci_disable(devpriv->pci_dev);
+ pci_dev_put(devpriv->pci_dev);
+ }
}
-static struct pci_driver driver_adl_pci8164_pci_driver = {
- .id_table = adl_pci8164_pci_table,
- .probe = &driver_adl_pci8164_pci_probe,
- .remove = __devexit_p(&driver_adl_pci8164_pci_remove)
+static struct comedi_driver adl_pci8164_driver = {
+ .driver_name = "adl_pci8164",
+ .module = THIS_MODULE,
+ .attach = adl_pci8164_attach,
+ .detach = adl_pci8164_detach,
};
-static int __init driver_adl_pci8164_init_module(void)
+static int __devinit adl_pci8164_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- int retval;
-
- retval = comedi_driver_register(&driver_adl_pci8164);
- if (retval < 0)
- return retval;
-
- driver_adl_pci8164_pci_driver.name =
- (char *)driver_adl_pci8164.driver_name;
- return pci_register_driver(&driver_adl_pci8164_pci_driver);
+ return comedi_pci_auto_config(dev, &adl_pci8164_driver);
}
-static void __exit driver_adl_pci8164_cleanup_module(void)
+static void __devexit adl_pci8164_pci_remove(struct pci_dev *dev)
{
- pci_unregister_driver(&driver_adl_pci8164_pci_driver);
- comedi_driver_unregister(&driver_adl_pci8164);
+ comedi_pci_auto_unconfig(dev);
}
-module_init(driver_adl_pci8164_init_module);
-module_exit(driver_adl_pci8164_cleanup_module);
+static DEFINE_PCI_DEVICE_TABLE(adl_pci8164_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI8164) },
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, adl_pci8164_pci_table);
+
+static struct pci_driver adl_pci8164_pci_driver = {
+ .name = "adl_pci8164",
+ .id_table = adl_pci8164_pci_table,
+ .probe = adl_pci8164_pci_probe,
+ .remove = __devexit_p(adl_pci8164_pci_remove),
+};
+module_comedi_pci_driver(adl_pci8164_driver, adl_pci8164_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index 2a9bd88a4abb..ccfb1a52154e 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -289,16 +289,6 @@ TODO:
PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \
} while (0)
-/* Function prototypes */
-
-static int pci9111_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pci9111_detach(struct comedi_device *dev);
-static void pci9111_ai_munge(struct comedi_device *dev,
- struct comedi_subdevice *s, void *data,
- unsigned int num_bytes,
- unsigned int start_chan_index);
-
static const struct comedi_lrange pci9111_hr_ai_range = {
5,
{
@@ -310,14 +300,6 @@ static const struct comedi_lrange pci9111_hr_ai_range = {
}
};
-static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) },
- /* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
-
/* */
/* Board specification structure */
/* */
@@ -354,51 +336,6 @@ static const struct pci9111_board pci9111_boards[] = {
#define pci9111_board_nbr \
(sizeof(pci9111_boards)/sizeof(struct pci9111_board))
-static struct comedi_driver pci9111_driver = {
- .driver_name = PCI9111_DRIVER_NAME,
- .module = THIS_MODULE,
- .attach = pci9111_attach,
- .detach = pci9111_detach,
-};
-
-static int __devinit pci9111_driver_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, pci9111_driver.driver_name);
-}
-
-static void __devexit pci9111_driver_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver pci9111_driver_pci_driver = {
- .id_table = pci9111_pci_table,
- .probe = &pci9111_driver_pci_probe,
- .remove = __devexit_p(&pci9111_driver_pci_remove)
-};
-
-static int __init pci9111_driver_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&pci9111_driver);
- if (retval < 0)
- return retval;
-
- pci9111_driver_pci_driver.name = (char *)pci9111_driver.driver_name;
- return pci_register_driver(&pci9111_driver_pci_driver);
-}
-
-static void __exit pci9111_driver_cleanup_module(void)
-{
- pci_unregister_driver(&pci9111_driver_pci_driver);
- comedi_driver_unregister(&pci9111_driver);
-}
-
-module_init(pci9111_driver_init_module);
-module_exit(pci9111_driver_cleanup_module);
-
/* Private data structure */
struct pci9111_private_data {
@@ -1445,31 +1382,54 @@ found:
return 0;
}
-/* Detach */
-
-static int pci9111_detach(struct comedi_device *dev)
+static void pci9111_detach(struct comedi_device *dev)
{
- /* Reset device */
-
if (dev->private != NULL) {
if (dev_private->is_valid)
pci9111_reset(dev);
-
}
- /* Release previously allocated irq */
-
if (dev->irq != 0)
free_irq(dev->irq, dev);
-
if (dev_private != NULL && dev_private->pci_device != NULL) {
if (dev->iobase)
comedi_pci_disable(dev_private->pci_device);
pci_dev_put(dev_private->pci_device);
}
+}
- return 0;
+static struct comedi_driver adl_pci9111_driver = {
+ .driver_name = "adl_pci9111",
+ .module = THIS_MODULE,
+ .attach = pci9111_attach,
+ .detach = pci9111_detach,
+};
+
+static int __devinit pci9111_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &adl_pci9111_driver);
}
+static void __devexit pci9111_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) },
+ /* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
+
+static struct pci_driver adl_pci9111_pci_driver = {
+ .name = "adl_pci9111",
+ .id_table = pci9111_pci_table,
+ .probe = pci9111_pci_probe,
+ .remove = __devexit_p(pci9111_pci_remove),
+};
+module_comedi_pci_driver(adl_pci9111_driver, adl_pci9111_pci_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index f17654e44aef..78645863297b 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -221,10 +221,6 @@ static const struct comedi_lrange range_pci9118hg = { 8, {
* of BIP/UNI ranges
*/
-static int pci9118_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pci9118_detach(struct comedi_device *dev);
-
struct boardtype {
const char *name; /* board name */
int vendor_id; /* PCI vendor a device ID of card */
@@ -252,81 +248,6 @@ struct boardtype {
};
-static DEFINE_PCI_DEVICE_TABLE(pci9118_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, pci9118_pci_table);
-
-static const struct boardtype boardtypes[] = {
- {"pci9118dg", PCI_VENDOR_ID_AMCC, 0x80d9,
- AMCC_OP_REG_SIZE, IORANGE_9118,
- 16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
- &range_pci9118dg_hr, &range_bipolar10,
- 3000, 12, 512},
- {"pci9118hg", PCI_VENDOR_ID_AMCC, 0x80d9,
- AMCC_OP_REG_SIZE, IORANGE_9118,
- 16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
- &range_pci9118hg, &range_bipolar10,
- 3000, 12, 512},
- {"pci9118hr", PCI_VENDOR_ID_AMCC, 0x80d9,
- AMCC_OP_REG_SIZE, IORANGE_9118,
- 16, 8, 256, PCI9118_CHANLEN, 2, 0xffff, 0x0fff,
- &range_pci9118dg_hr, &range_bipolar10,
- 10000, 40, 512},
-};
-
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
-
-static struct comedi_driver driver_pci9118 = {
- .driver_name = "adl_pci9118",
- .module = THIS_MODULE,
- .attach = pci9118_attach,
- .detach = pci9118_detach,
- .num_names = n_boardtypes,
- .board_name = &boardtypes[0].name,
- .offset = sizeof(struct boardtype),
-};
-
-static int __devinit driver_pci9118_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, driver_pci9118.driver_name);
-}
-
-static void __devexit driver_pci9118_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver driver_pci9118_pci_driver = {
- .id_table = pci9118_pci_table,
- .probe = &driver_pci9118_pci_probe,
- .remove = __devexit_p(&driver_pci9118_pci_remove)
-};
-
-static int __init driver_pci9118_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_pci9118);
- if (retval < 0)
- return retval;
-
- driver_pci9118_pci_driver.name = (char *)driver_pci9118.driver_name;
- return pci_register_driver(&driver_pci9118_pci_driver);
-}
-
-static void __exit driver_pci9118_cleanup_module(void)
-{
- pci_unregister_driver(&driver_pci9118_pci_driver);
- comedi_driver_unregister(&driver_pci9118);
-}
-
-module_init(driver_pci9118_init_module);
-module_exit(driver_pci9118_cleanup_module);
-
struct pci9118_private {
unsigned long iobase_a; /* base+size for AMCC chip */
unsigned int master; /* master capable */
@@ -2190,9 +2111,6 @@ static int pci9118_reset(struct comedi_device *dev)
return 0;
}
-/*
-==============================================================================
-*/
static int pci9118_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
@@ -2435,10 +2353,7 @@ static int pci9118_attach(struct comedi_device *dev,
return 0;
}
-/*
-==============================================================================
-*/
-static int pci9118_detach(struct comedi_device *dev)
+static void pci9118_detach(struct comedi_device *dev)
{
if (dev->private) {
if (devpriv->valid)
@@ -2458,13 +2373,100 @@ static int pci9118_detach(struct comedi_device *dev)
free_pages((unsigned long)devpriv->dmabuf_virt[1],
devpriv->dmabuf_pages[1]);
}
+}
- return 0;
+static const struct boardtype boardtypes[] = {
+ {
+ .name = "pci9118dg",
+ .vendor_id = PCI_VENDOR_ID_AMCC,
+ .device_id = 0x80d9,
+ .iorange_amcc = AMCC_OP_REG_SIZE,
+ .iorange_9118 = IORANGE_9118,
+ .n_aichan = 16,
+ .n_aichand = 8,
+ .mux_aichan = 256,
+ .n_aichanlist = PCI9118_CHANLEN,
+ .n_aochan = 2,
+ .ai_maxdata = 0x0fff,
+ .ao_maxdata = 0x0fff,
+ .rangelist_ai = &range_pci9118dg_hr,
+ .rangelist_ao = &range_bipolar10,
+ .ai_ns_min = 3000,
+ .ai_pacer_min = 12,
+ .half_fifo_size = 512,
+ }, {
+ .name = "pci9118hg",
+ .vendor_id = PCI_VENDOR_ID_AMCC,
+ .device_id = 0x80d9,
+ .iorange_amcc = AMCC_OP_REG_SIZE,
+ .iorange_9118 = IORANGE_9118,
+ .n_aichan = 16,
+ .n_aichand = 8,
+ .mux_aichan = 256,
+ .n_aichanlist = PCI9118_CHANLEN,
+ .n_aochan = 2,
+ .ai_maxdata = 0x0fff,
+ .ao_maxdata = 0x0fff,
+ .rangelist_ai = &range_pci9118hg,
+ .rangelist_ao = &range_bipolar10,
+ .ai_ns_min = 3000,
+ .ai_pacer_min = 12,
+ .half_fifo_size = 512,
+ }, {
+ .name = "pci9118hr",
+ .vendor_id = PCI_VENDOR_ID_AMCC,
+ .device_id = 0x80d9,
+ .iorange_amcc = AMCC_OP_REG_SIZE,
+ .iorange_9118 = IORANGE_9118,
+ .n_aichan = 16,
+ .n_aichand = 8,
+ .mux_aichan = 256,
+ .n_aichanlist = PCI9118_CHANLEN,
+ .n_aochan = 2,
+ .ai_maxdata = 0xffff,
+ .ao_maxdata = 0x0fff,
+ .rangelist_ai = &range_pci9118dg_hr,
+ .rangelist_ao = &range_bipolar10,
+ .ai_ns_min = 10000,
+ .ai_pacer_min = 40,
+ .half_fifo_size = 512,
+ },
+};
+
+static struct comedi_driver adl_pci9118_driver = {
+ .driver_name = "adl_pci9118",
+ .module = THIS_MODULE,
+ .attach = pci9118_attach,
+ .detach = pci9118_detach,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .board_name = &boardtypes[0].name,
+ .offset = sizeof(struct boardtype),
+};
+
+static int __devinit adl_pci9118_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &adl_pci9118_driver);
}
-/*
-==============================================================================
-*/
+static void __devexit adl_pci9118_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(adl_pci9118_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, adl_pci9118_pci_table);
+
+static struct pci_driver adl_pci9118_pci_driver = {
+ .name = "adl_pci9118",
+ .id_table = adl_pci9118_pci_table,
+ .probe = adl_pci9118_pci_probe,
+ .remove = __devexit_p(adl_pci9118_pci_remove),
+};
+module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
index 5361f318b010..7d585a12050f 100644
--- a/drivers/staging/comedi/drivers/adq12b.c
+++ b/drivers/staging/comedi/drivers/adq12b.c
@@ -125,24 +125,6 @@ struct adq12b_board {
int do_chans;
};
-static const struct adq12b_board adq12b_boards[] = {
- {
- .name = "adq12b",
- .ai_se_chans = 16,
- .ai_diff_chans = 8,
- .ai_bits = 12,
- .di_chans = 5,
- .do_chans = 8}
-/* potentially, more adq-based deviced will be added */
-/*,
- .name = "adq12b",
- .ai_chans = 16, // this is just for reference, hardcoded again later
- .ai_bits = 12,
- .di_chans = 8,
- .do_chans = 5
- }*/
-};
-
#define thisboard ((const struct adq12b_board *)dev->board_ptr)
struct adq12b_private {
@@ -156,41 +138,88 @@ struct adq12b_private {
#define devpriv ((struct adq12b_private *)dev->private)
/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
+ * "instructions" read/write data in "one-shot" or "software-triggered"
+ * mode.
*/
-static int adq12b_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int adq12b_detach(struct comedi_device *dev);
-
-static struct comedi_driver driver_adq12b = {
- .driver_name = "adq12b",
- .module = THIS_MODULE,
- .attach = adq12b_attach,
- .detach = adq12b_detach,
- .board_name = &adq12b_boards[0].name,
- .offset = sizeof(struct adq12b_board),
- .num_names = ARRAY_SIZE(adq12b_boards),
-};
static int adq12b_ai_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data);
+ unsigned int *data)
+{
+ int n, i;
+ int range, channel;
+ unsigned char hi, lo, status;
+
+ /* change channel and range only if it is different from the previous */
+ range = CR_RANGE(insn->chanspec);
+ channel = CR_CHAN(insn->chanspec);
+ if (channel != devpriv->last_channel || range != devpriv->last_range) {
+ outb((range << 4) | channel, dev->iobase + ADQ12B_CTREG);
+ udelay(50); /* wait for the mux to settle */
+ }
+
+ /* trigger conversion */
+ status = inb(dev->iobase + ADQ12B_ADLOW);
+
+ /* convert n samples */
+ for (n = 0; n < insn->n; n++) {
+
+ /* wait for end of conversion */
+ i = 0;
+ do {
+ /* udelay(1); */
+ status = inb(dev->iobase + ADQ12B_STINR);
+ status = status & ADQ12B_EOC;
+ } while (status == 0 && ++i < TIMEOUT);
+ /* } while (++i < 10); */
+
+ /* read data */
+ hi = inb(dev->iobase + ADQ12B_ADHIG);
+ lo = inb(dev->iobase + ADQ12B_ADLOW);
+
+ /* printk("debug: chan=%d range=%d status=%d hi=%d lo=%d\n",
+ channel, range, status, hi, lo); */
+ data[n] = (hi << 8) | lo;
+
+ }
+
+ /* return the number of samples read/written */
+ return n;
+}
+
static int adq12b_di_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
+ struct comedi_insn *insn, unsigned int *data)
+{
+
+ /* only bits 0-4 have information about digital inputs */
+ data[1] = (inb(dev->iobase + ADQ12B_STINR) & (0x1f));
+
+ return 2;
+}
+
static int adq12b_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
+ struct comedi_insn *insn, unsigned int *data)
+{
+ int channel;
+
+ for (channel = 0; channel < 8; channel++)
+ if (((data[0] >> channel) & 0x01) != 0)
+ outb((((data[1] >> channel) & 0x01) << 3) | channel,
+ dev->iobase + ADQ12B_OUTBR);
+
+ /* store information to retrieve when asked for reading */
+ if (data[0]) {
+ devpriv->digital_state &= ~data[0];
+ devpriv->digital_state |= (data[0] & data[1]);
+ }
+
+ data[1] = devpriv->digital_state;
+
+ return 2;
+}
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
struct comedi_subdevice *s;
@@ -295,125 +324,34 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int adq12b_detach(struct comedi_device *dev)
+static void adq12b_detach(struct comedi_device *dev)
{
if (dev->iobase)
release_region(dev->iobase, ADQ12B_SIZE);
-
kfree(devpriv);
-
- printk(KERN_INFO "comedi%d: adq12b: removed\n", dev->minor);
-
- return 0;
-}
-
-/*
- * "instructions" read/write data in "one-shot" or "software-triggered"
- * mode.
- */
-
-static int adq12b_ai_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
-{
- int n, i;
- int range, channel;
- unsigned char hi, lo, status;
-
- /* change channel and range only if it is different from the previous */
- range = CR_RANGE(insn->chanspec);
- channel = CR_CHAN(insn->chanspec);
- if (channel != devpriv->last_channel || range != devpriv->last_range) {
- outb((range << 4) | channel, dev->iobase + ADQ12B_CTREG);
- udelay(50); /* wait for the mux to settle */
- }
-
- /* trigger conversion */
- status = inb(dev->iobase + ADQ12B_ADLOW);
-
- /* convert n samples */
- for (n = 0; n < insn->n; n++) {
-
- /* wait for end of conversion */
- i = 0;
- do {
- /* udelay(1); */
- status = inb(dev->iobase + ADQ12B_STINR);
- status = status & ADQ12B_EOC;
- } while (status == 0 && ++i < TIMEOUT);
- /* } while (++i < 10); */
-
- /* read data */
- hi = inb(dev->iobase + ADQ12B_ADHIG);
- lo = inb(dev->iobase + ADQ12B_ADLOW);
-
- /* printk("debug: chan=%d range=%d status=%d hi=%d lo=%d\n",
- channel, range, status, hi, lo); */
- data[n] = (hi << 8) | lo;
-
- }
-
- /* return the number of samples read/written */
- return n;
-}
-
-static int adq12b_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
-
- /* only bits 0-4 have information about digital inputs */
- data[1] = (inb(dev->iobase + ADQ12B_STINR) & (0x1f));
-
- return 2;
}
-static int adq12b_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- int channel;
-
- for (channel = 0; channel < 8; channel++)
- if (((data[0] >> channel) & 0x01) != 0)
- outb((((data[1] >> channel) & 0x01) << 3) | channel,
- dev->iobase + ADQ12B_OUTBR);
-
- /* store information to retrieve when asked for reading */
- if (data[0]) {
- devpriv->digital_state &= ~data[0];
- devpriv->digital_state |= (data[0] & data[1]);
- }
-
- data[1] = devpriv->digital_state;
-
- return 2;
-}
-
-/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
- */
-static int __init driver_adq12b_init_module(void)
-{
- return comedi_driver_register(&driver_adq12b);
-}
-
-static void __exit driver_adq12b_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_adq12b);
-}
+static const struct adq12b_board adq12b_boards[] = {
+ {
+ .name = "adq12b",
+ .ai_se_chans = 16,
+ .ai_diff_chans = 8,
+ .ai_bits = 12,
+ .di_chans = 5,
+ .do_chans = 8,
+ },
+};
-module_init(driver_adq12b_init_module);
-module_exit(driver_adq12b_cleanup_module);
+static struct comedi_driver adq12b_driver = {
+ .driver_name = "adq12b",
+ .module = THIS_MODULE,
+ .attach = adq12b_attach,
+ .detach = adq12b_detach,
+ .board_name = &adq12b_boards[0].name,
+ .offset = sizeof(struct adq12b_board),
+ .num_names = ARRAY_SIZE(adq12b_boards),
+};
+module_comedi_driver(adq12b_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index 8318c82a555a..de8c98cfe367 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -191,10 +191,6 @@ static const struct comedi_lrange range_pci171x_da = { 2, {
}
};
-static int pci1710_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pci1710_detach(struct comedi_device *dev);
-
struct boardtype {
const char *name; /* board name */
int device_id;
@@ -216,17 +212,6 @@ struct boardtype {
unsigned int fifo_half_size; /* size of FIFO/2 */
};
-static DEFINE_PCI_DEVICE_TABLE(pci1710_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1710) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1711) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1713) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1720) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1731) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, pci1710_pci_table);
-
static const struct boardtype boardtypes[] = {
{"pci1710", 0x1710,
IORANGE_171x, 1, TYPE_PCI171X,
@@ -264,18 +249,6 @@ static const struct boardtype boardtypes[] = {
{.name = DRV_NAME},
};
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
-
-static struct comedi_driver driver_pci1710 = {
- .driver_name = DRV_NAME,
- .module = THIS_MODULE,
- .attach = pci1710_attach,
- .detach = pci1710_detach,
- .num_names = n_boardtypes,
- .board_name = &boardtypes[0].name,
- .offset = sizeof(struct boardtype),
-};
-
struct pci1710_private {
struct pci_dev *pcidev; /* ptr to PCI device */
char valid; /* card is usable */
@@ -676,7 +649,9 @@ static void interrupt_pci1710_every_sample(void *d)
s->async->buf_int_count, s->async->buf_int_ptr,
s->async->buf_user_count, s->async->buf_user_ptr);
DPRINTK("adv_pci1710 EDBG: EOS2\n");
- if ((!devpriv->neverending_ai) && (devpriv->ai_act_scan >= devpriv->ai_scans)) { /* all data sampled */
+ if ((!devpriv->neverending_ai) &&
+ (devpriv->ai_act_scan >= devpriv->ai_scans)) {
+ /* all data sampled */
pci171x_ai_cancel(dev, s);
s->async->events |= COMEDI_CB_EOA;
comedi_event(dev, s);
@@ -804,8 +779,8 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d)
irq);
if (!dev->attached) /* is device attached? */
return IRQ_NONE; /* no, exit */
-
- if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ)) /* is this interrupt from our board? */
+ /* is this interrupt from our board? */
+ if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ))
return IRQ_NONE; /* no, exit */
DPRINTK("adv_pci1710 EDBG: interrupt_service_pci1710() ST: %4x\n",
@@ -814,7 +789,7 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d)
if (devpriv->ai_et) { /* Switch from initial TRIG_EXT to TRIG_xxx. */
devpriv->ai_et = 0;
devpriv->CntrlReg &= Control_CNT0;
- devpriv->CntrlReg |= Control_SW; /* set software trigger */
+ devpriv->CntrlReg |= Control_SW; /* set software trigger */
outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
devpriv->CntrlReg = devpriv->ai_et_CntrlReg;
outb(0, dev->iobase + PCI171x_CLRFIFO);
@@ -865,7 +840,8 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev,
devpriv->neverending_ai = 0;
devpriv->CntrlReg &= Control_CNT0;
- if ((devpriv->ai_flags & TRIG_WAKE_EOS)) { /* don't we want wake up every scan? devpriv->ai_eos=1; */
+ /* don't we want wake up every scan? devpriv->ai_eos=1; */
+ if ((devpriv->ai_flags & TRIG_WAKE_EOS)) {
devpriv->ai_eos = 1;
} else {
devpriv->CntrlReg |= Control_ONEFH;
@@ -982,13 +958,13 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
#ifdef PCI171X_EXTDEBUG
pci171x_cmdtest_out(1, cmd);
#endif
- DPRINTK
- ("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=1\n",
- err);
+ DPRINTK(
+ "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=1\n",
+ err);
return 1;
}
- /* step 2: make sure trigger sources are unique and mutually compatible */
+ /* step2: make sure trigger srcs are unique and mutually compatible */
if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) {
cmd->start_src = TRIG_NOW;
@@ -1015,9 +991,9 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
#ifdef PCI171X_EXTDEBUG
pci171x_cmdtest_out(2, cmd);
#endif
- DPRINTK
- ("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=2\n",
- err);
+ DPRINTK(
+ "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=2\n",
+ err);
return 2;
}
@@ -1065,9 +1041,9 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
#ifdef PCI171X_EXTDEBUG
pci171x_cmdtest_out(3, cmd);
#endif
- DPRINTK
- ("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=3\n",
- err);
+ DPRINTK(
+ "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=3\n",
+ err);
return 3;
}
@@ -1160,48 +1136,41 @@ static int check_channel_list(struct comedi_device *dev,
return 0;
}
- if (n_chan > 1) {
- chansegment[0] = chanlist[0]; /* first channel is every time ok */
- for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { /* build part of chanlist */
- /* printk("%d. %d %d\n",i,CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i])); */
- if (chanlist[0] == chanlist[i])
- break; /* we detect loop, this must by finish */
- if (CR_CHAN(chanlist[i]) & 1) /* odd channel cann't by differencial */
- if (CR_AREF(chanlist[i]) == AREF_DIFF) {
- comedi_error(dev,
- "Odd channel can't be differential input!\n");
- return 0;
- }
- nowmustbechan =
- (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
- if (CR_AREF(chansegment[i - 1]) == AREF_DIFF)
- nowmustbechan = (nowmustbechan + 1) % s->n_chan;
- if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continuous :-( */
- printk
- ("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
- i, CR_CHAN(chanlist[i]), nowmustbechan,
- CR_CHAN(chanlist[0]));
- return 0;
- }
- chansegment[i] = chanlist[i]; /* well, this is next correct channel in list */
+ if (n_chan == 1)
+ return 1; /* seglen=1 */
+
+ chansegment[0] = chanlist[0]; /* first channel is every time ok */
+ for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
+ if (chanlist[0] == chanlist[i])
+ break; /* we detected a loop, stop */
+ if ((CR_CHAN(chanlist[i]) & 1) &&
+ (CR_AREF(chanlist[i]) == AREF_DIFF)) {
+ comedi_error(dev, "Odd channel cannot be differential input!\n");
+ return 0;
}
+ nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
+ if (CR_AREF(chansegment[i - 1]) == AREF_DIFF)
+ nowmustbechan = (nowmustbechan + 1) % s->n_chan;
+ if (nowmustbechan != CR_CHAN(chanlist[i])) {
+ printk("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
+ i, CR_CHAN(chanlist[i]), nowmustbechan,
+ CR_CHAN(chanlist[0]));
+ return 0;
+ }
+ chansegment[i] = chanlist[i]; /* next correct channel in list */
+ }
- for (i = 0, segpos = 0; i < n_chan; i++) { /* check whole chanlist */
- /* printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i])); */
- if (chanlist[i] != chansegment[i % seglen]) {
- printk
- ("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
- i, CR_CHAN(chansegment[i]),
- CR_RANGE(chansegment[i]),
- CR_AREF(chansegment[i]),
- CR_CHAN(chanlist[i % seglen]),
- CR_RANGE(chanlist[i % seglen]),
- CR_AREF(chansegment[i % seglen]));
- return 0; /* chan/gain list is strange */
- }
+ for (i = 0, segpos = 0; i < n_chan; i++) {
+ if (chanlist[i] != chansegment[i % seglen]) {
+ printk("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
+ i, CR_CHAN(chansegment[i]),
+ CR_RANGE(chansegment[i]),
+ CR_AREF(chansegment[i]),
+ CR_CHAN(chanlist[i % seglen]),
+ CR_RANGE(chanlist[i % seglen]),
+ CR_AREF(chansegment[i % seglen]));
+ return 0;
}
- } else {
- seglen = 1;
}
return seglen;
}
@@ -1221,14 +1190,14 @@ static void setup_channel_list(struct comedi_device *dev,
DPRINTK("SegLen: %d\n", seglen);
for (i = 0; i < seglen; i++) { /* store range list to card */
chanprog = muxonechan[CR_CHAN(chanlist[i])];
- outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */
+ outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */
range = this_board->rangecode_ai[CR_RANGE(chanlist[i])];
if (CR_AREF(chanlist[i]) == AREF_DIFF)
range |= 0x0020;
- outw(range, dev->iobase + PCI171x_RANGE); /* select gain */
+ outw(range, dev->iobase + PCI171x_RANGE); /* select gain */
#ifdef PCI171x_PARANOIDCHECK
devpriv->act_chanlist[i] =
- (CR_CHAN(chanlist[i]) << 12) & 0xf000;
+ (CR_CHAN(chanlist[i]) << 12) & 0xf000;
#endif
DPRINTK("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
devpriv->act_chanlist[i]);
@@ -1236,13 +1205,14 @@ static void setup_channel_list(struct comedi_device *dev,
#ifdef PCI171x_PARANOIDCHECK
for ( ; i < n_chan; i++) { /* store remainder of channel list */
devpriv->act_chanlist[i] =
- (CR_CHAN(chanlist[i]) << 12) & 0xf000;
+ (CR_CHAN(chanlist[i]) << 12) & 0xf000;
}
#endif
devpriv->ai_et_MuxVal =
- CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8);
- outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); /* select channel interval to scan */
+ CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8);
+ /* select channel interval to scan */
+ outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX);
DPRINTK("MUX: %4x L%4x.H%4x\n",
CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8),
CR_CHAN(chanlist[0]), CR_CHAN(chanlist[seglen - 1]));
@@ -1365,9 +1335,6 @@ static int pci1710_reset(struct comedi_device *dev)
DPRINTK("adv_pci1710 EDBG: END: pci1710_reset(...)\n");
}
-/*
-==============================================================================
-*/
static int pci1710_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
@@ -1398,13 +1365,13 @@ static int pci1710_attach(struct comedi_device *dev,
while (NULL != (pcidev = pci_get_device(PCI_VENDOR_ID_ADVANTECH,
PCI_ANY_ID, pcidev))) {
if (strcmp(this_board->name, DRV_NAME) == 0) {
- for (i = 0; i < n_boardtypes; ++i) {
+ for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
if (pcidev->device == boardtypes[i].device_id) {
board_index = i;
break;
}
}
- if (i == n_boardtypes)
+ if (i == ARRAY_SIZE(boardtypes))
continue;
} else {
if (pcidev->device != boardtypes[board_index].device_id)
@@ -1584,12 +1551,8 @@ static int pci1710_attach(struct comedi_device *dev,
return 0;
}
-/*
-==============================================================================
-*/
-static int pci1710_detach(struct comedi_device *dev)
+static void pci1710_detach(struct comedi_device *dev)
{
-
if (dev->private) {
if (devpriv->valid)
pci1710_reset(dev);
@@ -1598,57 +1561,49 @@ static int pci1710_detach(struct comedi_device *dev)
if (devpriv->pcidev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pcidev);
-
pci_dev_put(devpriv->pcidev);
}
}
-
- return 0;
}
-/*
-==============================================================================
-*/
-static int __devinit driver_pci1710_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static struct comedi_driver adv_pci1710_driver = {
+ .driver_name = "adv_pci1710",
+ .module = THIS_MODULE,
+ .attach = pci1710_attach,
+ .detach = pci1710_detach,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .board_name = &boardtypes[0].name,
+ .offset = sizeof(struct boardtype),
+};
+
+static int __devinit adv_pci1710_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_pci1710.driver_name);
+ return comedi_pci_auto_config(dev, &adv_pci1710_driver);
}
-static void __devexit driver_pci1710_pci_remove(struct pci_dev *dev)
+static void __devexit adv_pci1710_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_pci1710_pci_driver = {
- .id_table = pci1710_pci_table,
- .probe = &driver_pci1710_pci_probe,
- .remove = __devexit_p(&driver_pci1710_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(adv_pci1710_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1710) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1711) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1713) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1720) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1731) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, adv_pci1710_pci_table);
-static int __init driver_pci1710_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_pci1710);
- if (retval < 0)
- return retval;
-
- driver_pci1710_pci_driver.name = (char *)driver_pci1710.driver_name;
- return pci_register_driver(&driver_pci1710_pci_driver);
-}
-
-static void __exit driver_pci1710_cleanup_module(void)
-{
- pci_unregister_driver(&driver_pci1710_pci_driver);
- comedi_driver_unregister(&driver_pci1710);
-}
-
-module_init(driver_pci1710_init_module);
-module_exit(driver_pci1710_cleanup_module);
-/*
-==============================================================================
-*/
+static struct pci_driver adv_pci1710_pci_driver = {
+ .name = "adv_pci1710",
+ .id_table = adv_pci1710_pci_table,
+ .probe = adv_pci1710_pci_probe,
+ .remove = __devexit_p(adv_pci1710_pci_remove),
+};
+module_comedi_pci_driver(adv_pci1710_driver, adv_pci1710_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
index 29455a8e88b4..336addcbce3a 100644
--- a/drivers/staging/comedi/drivers/adv_pci1723.c
+++ b/drivers/staging/comedi/drivers/adv_pci1723.c
@@ -150,36 +150,6 @@ static const struct pci1723_board boardtypes[] = {
},
};
-/*
- * This is used by modprobe to translate PCI IDs to drivers.
- * Should only be used for PCI and ISA-PnP devices
- */
-static DEFINE_PCI_DEVICE_TABLE(pci1723_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1723) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, pci1723_pci_table);
-
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int pci1723_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pci1723_detach(struct comedi_device *dev);
-
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pci1723_board))
-
-static struct comedi_driver driver_pci1723 = {
- .driver_name = "adv_pci1723",
- .module = THIS_MODULE,
- .attach = pci1723_attach,
- .detach = pci1723_detach,
-};
-
/* This structure is for data unique to this hardware driver. */
struct pci1723_private {
int valid; /* card is usable; */
@@ -319,10 +289,6 @@ static int pci1723_dio_insn_bits(struct comedi_device *dev,
return 2;
}
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a pci1723 board.
- */
static int pci1723_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
@@ -465,73 +431,50 @@ static int pci1723_attach(struct comedi_device *dev,
return 0;
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int pci1723_detach(struct comedi_device *dev)
+static void pci1723_detach(struct comedi_device *dev)
{
- printk(KERN_ERR "comedi%d: pci1723: remove\n", dev->minor);
-
if (dev->private) {
if (devpriv->valid)
pci1723_reset(dev);
-
if (devpriv->pcidev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pcidev);
pci_dev_put(devpriv->pcidev);
}
}
-
- return 0;
}
-/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
- */
-static int __devinit driver_pci1723_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static struct comedi_driver adv_pci1723_driver = {
+ .driver_name = "adv_pci1723",
+ .module = THIS_MODULE,
+ .attach = pci1723_attach,
+ .detach = pci1723_detach,
+};
+
+static int __devinit adv_pci1723_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_pci1723.driver_name);
+ return comedi_pci_auto_config(dev, &adv_pci1723_driver);
}
-static void __devexit driver_pci1723_pci_remove(struct pci_dev *dev)
+static void __devexit adv_pci1723_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_pci1723_pci_driver = {
- .id_table = pci1723_pci_table,
- .probe = &driver_pci1723_pci_probe,
- .remove = __devexit_p(&driver_pci1723_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(adv_pci1723_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1723) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, adv_pci1723_pci_table);
-static int __init driver_pci1723_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_pci1723);
- if (retval < 0)
- return retval;
-
- driver_pci1723_pci_driver.name = (char *)driver_pci1723.driver_name;
- return pci_register_driver(&driver_pci1723_pci_driver);
-}
-
-static void __exit driver_pci1723_cleanup_module(void)
-{
- pci_unregister_driver(&driver_pci1723_pci_driver);
- comedi_driver_unregister(&driver_pci1723);
-}
-
-module_init(driver_pci1723_init_module);
-module_exit(driver_pci1723_cleanup_module);
+static struct pci_driver adv_pci1723_pci_driver = {
+ .name = "adv_pci1723",
+ .id_table = adv_pci1723_pci_table,
+ .probe = adv_pci1723_pci_probe,
+ .remove = __devexit_p(adv_pci1723_pci_remove),
+};
+module_comedi_pci_driver(adv_pci1723_driver, adv_pci1723_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index 7af068f4a749..43a32dc12cde 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -237,10 +237,6 @@ enum hw_io_access {
#define OMBCMD_RETRY 0x03 /* 3 times try request before error */
-static int pci_dio_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pci_dio_detach(struct comedi_device *dev);
-
struct diosubd_data {
int chans; /* num of chans */
int addr; /* PCI address ofset */
@@ -263,26 +259,6 @@ struct dio_boardtype {
enum hw_io_access io_access;
};
-static DEFINE_PCI_DEVICE_TABLE(pci_dio_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1730) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1733) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1734) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1735) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1736) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1739) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1750) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1751) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1752) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1753) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1754) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1756) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1760) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1762) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, pci_dio_pci_table);
-
static const struct dio_boardtype boardtypes[] = {
{"pci1730", PCI_VENDOR_ID_ADVANTECH, 0x1730, PCIDIO_MAINREG,
TYPE_PCI1730,
@@ -406,15 +382,6 @@ static const struct dio_boardtype boardtypes[] = {
IO_16b}
};
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct dio_boardtype))
-
-static struct comedi_driver driver_pci_dio = {
- .driver_name = "adv_pci_dio",
- .module = THIS_MODULE,
- .attach = pci_dio_attach,
- .detach = pci_dio_detach
-};
-
struct pci_dio_private {
struct pci_dio_private *prev; /* previous private struct */
struct pci_dio_private *next; /* next private struct */
@@ -1116,9 +1083,6 @@ static int CheckAndAllocCard(struct comedi_device *dev,
return 1;
}
-/*
-==============================================================================
-*/
static int pci_dio_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
@@ -1134,7 +1098,7 @@ static int pci_dio_attach(struct comedi_device *dev,
for_each_pci_dev(pcidev) {
/* loop through cards supported by this driver */
- for (i = 0; i < n_boardtypes; ++i) {
+ for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
if (boardtypes[i].vendor_id != pcidev->vendor)
continue;
if (boardtypes[i].device_id != pcidev->device)
@@ -1162,7 +1126,7 @@ static int pci_dio_attach(struct comedi_device *dev,
return -EIO;
}
- if (comedi_pci_enable(pcidev, driver_pci_dio.driver_name)) {
+ if (comedi_pci_enable(pcidev, dev->driver->driver_name)) {
dev_err(dev->hw_dev, "Error: Can't enable PCI device and request regions!\n");
return -EIO;
}
@@ -1246,10 +1210,7 @@ static int pci_dio_attach(struct comedi_device *dev,
return 0;
}
-/*
-==============================================================================
-*/
-static int pci_dio_detach(struct comedi_device *dev)
+static void pci_dio_detach(struct comedi_device *dev)
{
int i, j;
struct comedi_subdevice *s;
@@ -1258,20 +1219,14 @@ static int pci_dio_detach(struct comedi_device *dev)
if (dev->private) {
if (devpriv->valid)
pci_dio_reset(dev);
-
-
- /* This shows the silliness of using this kind of
- * scheme for numbering subdevices. Don't do it. --ds */
subdev = 0;
for (i = 0; i < MAX_DI_SUBDEVS; i++) {
if (this_board->sdi[i].chans)
subdev++;
-
}
for (i = 0; i < MAX_DO_SUBDEVS; i++) {
if (this_board->sdo[i].chans)
subdev++;
-
}
for (i = 0; i < MAX_DIO_SUBDEVG; i++) {
for (j = 0; j < this_board->sdio[i].regs; j++) {
@@ -1280,82 +1235,73 @@ static int pci_dio_detach(struct comedi_device *dev)
subdev++;
}
}
-
if (this_board->boardid.chans)
subdev++;
-
for (i = 0; i < MAX_8254_SUBDEVS; i++)
if (this_board->s8254[i].chans)
subdev++;
-
for (i = 0; i < dev->n_subdevices; i++) {
s = dev->subdevices + i;
s->private = NULL;
}
-
if (devpriv->pcidev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pcidev);
-
pci_dev_put(devpriv->pcidev);
}
-
if (devpriv->prev)
devpriv->prev->next = devpriv->next;
else
pci_priv = devpriv->next;
-
if (devpriv->next)
devpriv->next->prev = devpriv->prev;
-
}
-
- return 0;
}
-/*
-==============================================================================
-*/
-static int __devinit driver_pci_dio_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static struct comedi_driver adv_pci_dio_driver = {
+ .driver_name = "adv_pci_dio",
+ .module = THIS_MODULE,
+ .attach = pci_dio_attach,
+ .detach = pci_dio_detach
+};
+
+static int __devinit adv_pci_dio_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_pci_dio.driver_name);
+ return comedi_pci_auto_config(dev, &adv_pci_dio_driver);
}
-static void __devexit driver_pci_dio_pci_remove(struct pci_dev *dev)
+static void __devexit adv_pci_dio_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_pci_dio_pci_driver = {
- .id_table = pci_dio_pci_table,
- .probe = &driver_pci_dio_pci_probe,
- .remove = __devexit_p(&driver_pci_dio_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(adv_pci_dio_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1730) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1733) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1734) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1735) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1736) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1739) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1750) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1751) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1752) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1753) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1754) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1756) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1760) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1762) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, adv_pci_dio_pci_table);
-static int __init driver_pci_dio_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_pci_dio);
- if (retval < 0)
- return retval;
-
- driver_pci_dio_pci_driver.name = (char *)driver_pci_dio.driver_name;
- return pci_register_driver(&driver_pci_dio_pci_driver);
-}
-
-static void __exit driver_pci_dio_cleanup_module(void)
-{
- pci_unregister_driver(&driver_pci_dio_pci_driver);
- comedi_driver_unregister(&driver_pci_dio);
-}
-
-module_init(driver_pci_dio_init_module);
-module_exit(driver_pci_dio_cleanup_module);
-/*
-==============================================================================
-*/
+static struct pci_driver adv_pci_dio_pci_driver = {
+ .name = "adv_pci_dio",
+ .id_table = adv_pci_dio_pci_table,
+ .probe = adv_pci_dio_pci_probe,
+ .remove = __devexit_p(adv_pci_dio_pci_remove),
+};
+module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
index b0f98e5e4bf3..64d82bc4ffe4 100644
--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
+++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
@@ -209,36 +209,23 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
return 0;
}
-static int aio_aio12_8_detach(struct comedi_device *dev)
+static void aio_aio12_8_detach(struct comedi_device *dev)
{
subdev_8255_cleanup(dev, &dev->subdevices[2]);
if (dev->iobase)
release_region(dev->iobase, 24);
- return 0;
}
-static struct comedi_driver driver_aio_aio12_8 = {
- .driver_name = "aio_aio12_8",
- .module = THIS_MODULE,
- .attach = aio_aio12_8_attach,
- .detach = aio_aio12_8_detach,
- .board_name = &board_types[0].name,
- .num_names = 1,
- .offset = sizeof(struct aio12_8_boardtype),
+static struct comedi_driver aio_aio12_8_driver = {
+ .driver_name = "aio_aio12_8",
+ .module = THIS_MODULE,
+ .attach = aio_aio12_8_attach,
+ .detach = aio_aio12_8_detach,
+ .board_name = &board_types[0].name,
+ .num_names = ARRAY_SIZE(board_types),
+ .offset = sizeof(struct aio12_8_boardtype),
};
-
-static int __init driver_aio_aio12_8_init_module(void)
-{
- return comedi_driver_register(&driver_aio_aio12_8);
-}
-
-static void __exit driver_aio_aio12_8_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_aio_aio12_8);
-}
-
-module_init(driver_aio_aio12_8_init_module);
-module_exit(driver_aio_aio12_8_cleanup_module);
+module_comedi_driver(aio_aio12_8_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
index 160b0a0f4f1e..04f6f94b1f47 100644
--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
+++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
@@ -67,30 +67,41 @@ struct aio_iiro_16_private {
#define devpriv ((struct aio_iiro_16_private *) dev->private)
-static int aio_iiro_16_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-
-static int aio_iiro_16_detach(struct comedi_device *dev);
-
-static struct comedi_driver driver_aio_iiro_16 = {
- .driver_name = "aio_iiro_16",
- .module = THIS_MODULE,
- .attach = aio_iiro_16_attach,
- .detach = aio_iiro_16_detach,
- .board_name = &aio_iiro_16_boards[0].name,
- .offset = sizeof(struct aio_iiro_16_board),
- .num_names = ARRAY_SIZE(aio_iiro_16_boards),
-};
+static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ if (insn->n != 2)
+ return -EINVAL;
+
+ if (data[0]) {
+ s->state &= ~data[0];
+ s->state |= data[0] & data[1];
+ outb(s->state & 0xff, dev->iobase + AIO_IIRO_16_RELAY_0_7);
+ outb((s->state >> 8) & 0xff,
+ dev->iobase + AIO_IIRO_16_RELAY_8_15);
+ }
+
+ data[1] = s->state;
+
+ return 2;
+}
static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
- unsigned int *data);
+ unsigned int *data)
+{
+ if (insn->n != 2)
+ return -EINVAL;
-static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
+ data[1] = 0;
+ data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_0_7);
+ data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_8_15) << 8;
+
+ return 2;
+}
static int aio_iiro_16_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
@@ -138,64 +149,22 @@ static int aio_iiro_16_attach(struct comedi_device *dev,
return 1;
}
-static int aio_iiro_16_detach(struct comedi_device *dev)
+static void aio_iiro_16_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: aio_iiro_16: remove\n", dev->minor);
-
if (dev->iobase)
release_region(dev->iobase, AIO_IIRO_16_SIZE);
-
- return 0;
-}
-
-static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- if (insn->n != 2)
- return -EINVAL;
-
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
- outb(s->state & 0xff, dev->iobase + AIO_IIRO_16_RELAY_0_7);
- outb((s->state >> 8) & 0xff,
- dev->iobase + AIO_IIRO_16_RELAY_8_15);
- }
-
- data[1] = s->state;
-
- return 2;
-}
-
-static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- if (insn->n != 2)
- return -EINVAL;
-
- data[1] = 0;
- data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_0_7);
- data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_8_15) << 8;
-
- return 2;
-}
-
-static int __init driver_aio_iiro_16_init_module(void)
-{
- return comedi_driver_register(&driver_aio_iiro_16);
}
-static void __exit driver_aio_iiro_16_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_aio_iiro_16);
-}
-
-module_init(driver_aio_iiro_16_init_module);
-module_exit(driver_aio_iiro_16_cleanup_module);
+static struct comedi_driver aio_iiro_16_driver = {
+ .driver_name = "aio_iiro_16",
+ .module = THIS_MODULE,
+ .attach = aio_iiro_16_attach,
+ .detach = aio_iiro_16_detach,
+ .board_name = &aio_iiro_16_boards[0].name,
+ .offset = sizeof(struct aio_iiro_16_board),
+ .num_names = ARRAY_SIZE(aio_iiro_16_boards),
+};
+module_comedi_driver(aio_iiro_16_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index 566cc4411452..c9c5d97b3ca2 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -217,6 +217,14 @@ order they appear in the channel list.
#define DIO200_DRIVER_NAME "amplc_dio200"
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA_MODULE
+#define CONFIG_COMEDI_AMPLC_DIO200_ISA
+#endif
+
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI_MODULE
+#define CONFIG_COMEDI_AMPLC_DIO200_PCI
+#endif
+
/* PCI IDs */
#define PCI_VENDOR_ID_AMPLICON 0x14dc
#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
@@ -274,10 +282,14 @@ enum dio200_model {
};
enum dio200_layout {
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
pc212_layout,
pc214_layout,
+#endif
pc215_layout,
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
pc218_layout,
+#endif
pc272_layout
};
@@ -290,6 +302,7 @@ struct dio200_board {
};
static const struct dio200_board dio200_boards[] = {
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
{
.name = "pc212e",
.bustype = isa_bustype,
@@ -308,15 +321,6 @@ static const struct dio200_board dio200_boards[] = {
.model = pc215e_model,
.layout = pc215_layout,
},
-#ifdef CONFIG_COMEDI_PCI
- {
- .name = "pci215",
- .devid = PCI_DEVICE_ID_AMPLICON_PCI215,
- .bustype = pci_bustype,
- .model = pci215_model,
- .layout = pc215_layout,
- },
-#endif
{
.name = "pc218e",
.bustype = isa_bustype,
@@ -329,7 +333,15 @@ static const struct dio200_board dio200_boards[] = {
.model = pc272e_model,
.layout = pc272_layout,
},
-#ifdef CONFIG_COMEDI_PCI
+#endif
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
+ {
+ .name = "pci215",
+ .devid = PCI_DEVICE_ID_AMPLICON_PCI215,
+ .bustype = pci_bustype,
+ .model = pci215_model,
+ .layout = pc215_layout,
+ },
{
.name = "pci272",
.devid = PCI_DEVICE_ID_AMPLICON_PCI272,
@@ -337,8 +349,6 @@ static const struct dio200_board dio200_boards[] = {
.model = pci272_model,
.layout = pc272_layout,
},
-#endif
-#ifdef CONFIG_COMEDI_PCI
{
.name = DIO200_DRIVER_NAME,
.devid = PCI_DEVICE_ID_INVALID,
@@ -367,6 +377,7 @@ struct dio200_layout_struct {
};
static const struct dio200_layout_struct dio200_layouts[] = {
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
[pc212_layout] = {
.n_subdevs = 6,
.sdtype = {sd_8255, sd_8254, sd_8254, sd_8254,
@@ -385,6 +396,7 @@ static const struct dio200_layout_struct dio200_layouts[] = {
.has_int_sce = 0,
.has_clk_gat_sce = 0,
},
+#endif
[pc215_layout] = {
.n_subdevs = 5,
.sdtype = {sd_8255, sd_8255, sd_8254,
@@ -394,6 +406,7 @@ static const struct dio200_layout_struct dio200_layouts[] = {
.has_int_sce = 1,
.has_clk_gat_sce = 1,
},
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
[pc218_layout] = {
.n_subdevs = 7,
.sdtype = {sd_8254, sd_8254, sd_8255, sd_8254,
@@ -405,6 +418,7 @@ static const struct dio200_layout_struct dio200_layouts[] = {
.has_int_sce = 1,
.has_clk_gat_sce = 1,
},
+#endif
[pc272_layout] = {
.n_subdevs = 4,
.sdtype = {sd_8255, sd_8255, sd_8255,
@@ -419,7 +433,7 @@ static const struct dio200_layout_struct dio200_layouts[] = {
* PCI driver table.
*/
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) },
@@ -427,7 +441,7 @@ static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
};
MODULE_DEVICE_TABLE(pci, dio200_pci_table);
-#endif /* CONFIG_COMEDI_PCI */
+#endif /* CONFIG_COMEDI_AMPLC_DIO200_PCI */
/*
* Useful for shorthand access to the particular board structure
@@ -441,7 +455,7 @@ MODULE_DEVICE_TABLE(pci, dio200_pci_table);
feel free to suggest moving the variable to the struct comedi_device struct.
*/
struct dio200_private {
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
struct pci_dev *pci_dev; /* PCI device */
#endif
int intr_sd;
@@ -479,7 +493,7 @@ struct dio200_subdev_intr {
*/
static int dio200_attach(struct comedi_device *dev,
struct comedi_devconfig *it);
-static int dio200_detach(struct comedi_device *dev);
+static void dio200_detach(struct comedi_device *dev);
static struct comedi_driver driver_amplc_dio200 = {
.driver_name = DIO200_DRIVER_NAME,
.module = THIS_MODULE,
@@ -490,12 +504,12 @@ static struct comedi_driver driver_amplc_dio200 = {
.num_names = ARRAY_SIZE(dio200_boards),
};
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
static int __devinit driver_amplc_dio200_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
- return comedi_pci_auto_config(dev, driver_amplc_dio200.driver_name);
+ return comedi_pci_auto_config(dev, &driver_amplc_dio200);
}
static void __devexit driver_amplc_dio200_pci_remove(struct pci_dev *dev)
@@ -549,7 +563,7 @@ module_exit(driver_amplc_dio200_cleanup_module);
* This function looks for a PCI device matching the requested board name,
* bus and slot.
*/
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
static int
dio200_find_pci(struct comedi_device *dev, int bus, int slot,
struct pci_dev **pci_dev_p)
@@ -611,6 +625,7 @@ dio200_find_pci(struct comedi_device *dev, int bus, int slot,
* This function checks and requests an I/O region, reporting an error
* if there is a conflict.
*/
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
static int
dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
{
@@ -621,6 +636,7 @@ dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
}
return 0;
}
+#endif
/*
* 'insn_bits' function for an 'INTERRUPT' subdevice.
@@ -1332,7 +1348,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
unsigned long iobase = 0;
unsigned int irq = 0;
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
struct pci_dev *pci_dev = NULL;
int bus = 0, slot = 0;
#endif
@@ -1354,12 +1370,14 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* Process options. */
switch (thisboard->bustype) {
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
case isa_bustype:
iobase = it->options[0];
irq = it->options[1];
share_irq = 0;
break;
-#ifdef CONFIG_COMEDI_PCI
+#endif
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
case pci_bustype:
bus = it->options[0];
slot = it->options[1];
@@ -1382,7 +1400,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->intr_sd = -1;
/* Enable device and reserve I/O spaces. */
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
if (pci_dev) {
ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
if (ret < 0) {
@@ -1396,9 +1414,11 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
} else
#endif
{
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE);
if (ret < 0)
return ret;
+#endif
}
dev->iobase = iobase;
@@ -1474,12 +1494,19 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
- if (thisboard->bustype == isa_bustype) {
+ switch (thisboard->bustype) {
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
+ case isa_bustype:
printk("(base %#lx) ", iobase);
- } else {
-#ifdef CONFIG_COMEDI_PCI
+ break;
+#endif
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
+ case pci_bustype:
printk("(pci %s) ", pci_name(pci_dev));
+ break;
#endif
+ default:
+ break;
}
if (irq)
printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
@@ -1491,22 +1518,11 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 1;
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int dio200_detach(struct comedi_device *dev)
+static void dio200_detach(struct comedi_device *dev)
{
const struct dio200_layout_struct *layout;
unsigned n;
- printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
- DIO200_DRIVER_NAME);
-
if (dev->irq)
free_irq(dev->irq, dev);
if (dev->subdevices) {
@@ -1529,7 +1545,7 @@ static int dio200_detach(struct comedi_device *dev)
}
}
if (devpriv) {
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
if (devpriv->pci_dev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
@@ -1537,15 +1553,12 @@ static int dio200_detach(struct comedi_device *dev)
} else
#endif
{
+#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
if (dev->iobase)
release_region(dev->iobase, DIO200_IO_SIZE);
+#endif
}
}
- if (dev->board_name)
- printk(KERN_INFO "comedi%d: %s removed\n",
- dev->minor, dev->board_name);
-
- return 0;
}
MODULE_AUTHOR("Comedi http://www.comedi.org");
diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
index 7972cadd403e..57ba3228b1a9 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236.c
@@ -63,6 +63,14 @@ unused.
#define PC236_DRIVER_NAME "amplc_pc236"
+#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA_MODULE
+#define CONFIG_COMEDI_AMPLC_PC236_ISA
+#endif
+
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI_MODULE
+#define CONFIG_COMEDI_AMPLC_PC236_PCI
+#endif
+
/* PCI236 PCI configuration register information */
#define PCI_VENDOR_ID_AMPLICON 0x14dc
#define PCI_DEVICE_ID_AMPLICON_PCI236 0x0009
@@ -106,13 +114,15 @@ struct pc236_board {
enum pc236_model model;
};
static const struct pc236_board pc236_boards[] = {
+#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
{
.name = "pc36at",
.fancy_name = "PC36AT",
.bustype = isa_bustype,
.model = pc36at_model,
},
-#ifdef CONFIG_COMEDI_PCI
+#endif
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
{
.name = "pci236",
.fancy_name = "PCI236",
@@ -120,8 +130,6 @@ static const struct pc236_board pc236_boards[] = {
.bustype = pci_bustype,
.model = pci236_model,
},
-#endif
-#ifdef CONFIG_COMEDI_PCI
{
.name = PC236_DRIVER_NAME,
.fancy_name = PC236_DRIVER_NAME,
@@ -132,14 +140,14 @@ static const struct pc236_board pc236_boards[] = {
#endif
};
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236) },
{0}
};
MODULE_DEVICE_TABLE(pci, pc236_pci_table);
-#endif /* CONFIG_COMEDI_PCI */
+#endif /* CONFIG_COMEDI_AMPLC_PC236_PCI */
/*
* Useful for shorthand access to the particular board structure
@@ -151,7 +159,7 @@ MODULE_DEVICE_TABLE(pci, pc236_pci_table);
feel free to suggest moving the variable to the struct comedi_device struct.
*/
struct pc236_private {
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
/* PCI device */
struct pci_dev *pci_dev;
unsigned long lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */
@@ -168,7 +176,7 @@ struct pc236_private {
* the device code.
*/
static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int pc236_detach(struct comedi_device *dev);
+static void pc236_detach(struct comedi_device *dev);
static struct comedi_driver driver_amplc_pc236 = {
.driver_name = PC236_DRIVER_NAME,
.module = THIS_MODULE,
@@ -179,12 +187,12 @@ static struct comedi_driver driver_amplc_pc236 = {
.num_names = ARRAY_SIZE(pc236_boards),
};
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
static int __devinit driver_amplc_pc236_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
- return comedi_pci_auto_config(dev, driver_amplc_pc236.driver_name);
+ return comedi_pci_auto_config(dev, &driver_amplc_pc236);
}
static void __devexit driver_amplc_pc236_pci_remove(struct pci_dev *dev)
@@ -234,8 +242,10 @@ module_init(driver_amplc_pc236_init_module);
module_exit(driver_amplc_pc236_cleanup_module);
#endif
+#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
static int pc236_request_region(unsigned minor, unsigned long from,
unsigned long extent);
+#endif
static void pc236_intr_disable(struct comedi_device *dev);
static void pc236_intr_enable(struct comedi_device *dev);
static int pc236_intr_check(struct comedi_device *dev);
@@ -255,7 +265,7 @@ static irqreturn_t pc236_interrupt(int irq, void *d);
* This function looks for a PCI device matching the requested board name,
* bus and slot.
*/
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
static int
pc236_find_pci(struct comedi_device *dev, int bus, int slot,
struct pci_dev **pci_dev_p)
@@ -324,7 +334,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
unsigned long iobase = 0;
unsigned int irq = 0;
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
struct pci_dev *pci_dev = NULL;
int bus = 0, slot = 0;
#endif
@@ -345,12 +355,14 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* Process options. */
switch (thisboard->bustype) {
+#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
case isa_bustype:
iobase = it->options[0];
irq = it->options[1];
share_irq = 0;
break;
-#ifdef CONFIG_COMEDI_PCI
+#endif
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
case pci_bustype:
bus = it->options[0];
slot = it->options[1];
@@ -361,7 +373,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
devpriv->pci_dev = pci_dev;
break;
-#endif /* CONFIG_COMEDI_PCI */
+#endif
default:
printk(KERN_ERR
"comedi%d: %s: BUG! cannot determine board type!\n",
@@ -376,7 +388,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev->board_name = thisboard->name;
/* Enable device and reserve I/O spaces. */
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
if (pci_dev) {
ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME);
@@ -392,9 +404,11 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
} else
#endif
{
+#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
ret = pc236_request_region(dev->minor, iobase, PC236_IO_SIZE);
if (ret < 0)
return ret;
+#endif
}
dev->iobase = iobase;
@@ -439,12 +453,19 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
}
printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
- if (thisboard->bustype == isa_bustype) {
+ switch (thisboard->bustype) {
+#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
+ case isa_bustype:
printk("(base %#lx) ", iobase);
- } else {
-#ifdef CONFIG_COMEDI_PCI
+ break;
+#endif
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
+ case pci_bustype:
printk("(pci %s) ", pci_name(pci_dev));
+ break;
#endif
+ default:
+ break;
}
if (irq)
printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
@@ -456,27 +477,16 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 1;
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int pc236_detach(struct comedi_device *dev)
+static void pc236_detach(struct comedi_device *dev)
{
- printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
- PC236_DRIVER_NAME);
if (devpriv)
pc236_intr_disable(dev);
-
if (dev->irq)
free_irq(dev->irq, dev);
if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 0);
if (devpriv) {
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
if (devpriv->pci_dev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
@@ -484,21 +494,19 @@ static int pc236_detach(struct comedi_device *dev)
} else
#endif
{
+#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
if (dev->iobase)
release_region(dev->iobase, PC236_IO_SIZE);
+#endif
}
}
- if (dev->board_name) {
- printk(KERN_INFO "comedi%d: %s removed\n",
- dev->minor, dev->board_name);
- }
- return 0;
}
/*
* This function checks and requests an I/O region, reporting an error
* if there is a conflict.
*/
+#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
static int pc236_request_region(unsigned minor, unsigned long from,
unsigned long extent)
{
@@ -509,6 +517,7 @@ static int pc236_request_region(unsigned minor, unsigned long from,
}
return 0;
}
+#endif
/*
* This function is called to mark the interrupt as disabled (no command
@@ -521,7 +530,7 @@ static void pc236_intr_disable(struct comedi_device *dev)
spin_lock_irqsave(&dev->spinlock, flags);
devpriv->enable_irq = 0;
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
if (devpriv->lcr_iobase)
outl(PCI236_INTR_DISABLE, devpriv->lcr_iobase + PLX9052_INTCSR);
#endif
@@ -539,7 +548,7 @@ static void pc236_intr_enable(struct comedi_device *dev)
spin_lock_irqsave(&dev->spinlock, flags);
devpriv->enable_irq = 1;
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
if (devpriv->lcr_iobase)
outl(PCI236_INTR_ENABLE, devpriv->lcr_iobase + PLX9052_INTCSR);
#endif
@@ -561,7 +570,7 @@ static int pc236_intr_check(struct comedi_device *dev)
spin_lock_irqsave(&dev->spinlock, flags);
if (devpriv->enable_irq) {
retval = 1;
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
if (devpriv->lcr_iobase) {
if ((inl(devpriv->lcr_iobase + PLX9052_INTCSR)
& PLX9052_INTCSR_LI1STAT_MASK)
diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
index 191ac0d23ce7..974d7450051e 100644
--- a/drivers/staging/comedi/drivers/amplc_pc263.c
+++ b/drivers/staging/comedi/drivers/amplc_pc263.c
@@ -50,6 +50,14 @@ The state of the outputs can be read.
#define PC263_DRIVER_NAME "amplc_pc263"
+#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA_MODULE
+#define CONFIG_COMEDI_AMPLC_PC263_ISA
+#endif
+
+#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI_MODULE
+#define CONFIG_COMEDI_AMPLC_PC263_PCI
+#endif
+
/* PCI263 PCI configuration register information */
#define PCI_VENDOR_ID_AMPLICON 0x14dc
#define PCI_DEVICE_ID_AMPLICON_PCI263 0x000c
@@ -73,13 +81,15 @@ struct pc263_board {
enum pc263_model model;
};
static const struct pc263_board pc263_boards[] = {
+#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
{
.name = "pc263",
.fancy_name = "PC263",
.bustype = isa_bustype,
.model = pc263_model,
},
-#ifdef CONFIG_COMEDI_PCI
+#endif
+#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
{
.name = "pci263",
.fancy_name = "PCI263",
@@ -87,8 +97,6 @@ static const struct pc263_board pc263_boards[] = {
.bustype = pci_bustype,
.model = pci263_model,
},
-#endif
-#ifdef CONFIG_COMEDI_PCI
{
.name = PC263_DRIVER_NAME,
.fancy_name = PC263_DRIVER_NAME,
@@ -99,14 +107,14 @@ static const struct pc263_board pc263_boards[] = {
#endif
};
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) },
{0}
};
MODULE_DEVICE_TABLE(pci, pc263_pci_table);
-#endif /* CONFIG_COMEDI_PCI */
+#endif /* CONFIG_COMEDI_AMPLC_PC263_PCI */
/*
* Useful for shorthand access to the particular board structure
@@ -117,14 +125,14 @@ MODULE_DEVICE_TABLE(pci, pc263_pci_table);
several hardware drivers keep similar information in this structure,
feel free to suggest moving the variable to the struct comedi_device struct.
*/
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
struct pc263_private {
/* PCI device. */
struct pci_dev *pci_dev;
};
#define devpriv ((struct pc263_private *)dev->private)
-#endif /* CONFIG_COMEDI_PCI */
+#endif /* CONFIG_COMEDI_AMPLC_PC263_PCI */
/*
* The struct comedi_driver structure tells the Comedi core module
@@ -133,7 +141,7 @@ struct pc263_private {
* the device code.
*/
static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int pc263_detach(struct comedi_device *dev);
+static void pc263_detach(struct comedi_device *dev);
static struct comedi_driver driver_amplc_pc263 = {
.driver_name = PC263_DRIVER_NAME,
.module = THIS_MODULE,
@@ -144,8 +152,10 @@ static struct comedi_driver driver_amplc_pc263 = {
.num_names = ARRAY_SIZE(pc263_boards),
};
+#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
static int pc263_request_region(unsigned minor, unsigned long from,
unsigned long extent);
+#endif
static int pc263_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
@@ -157,7 +167,7 @@ static int pc263_dio_insn_config(struct comedi_device *dev,
* This function looks for a PCI device matching the requested board name,
* bus and slot.
*/
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
static int
pc263_find_pci(struct comedi_device *dev, int bus, int slot,
struct pci_dev **pci_dev_p)
@@ -225,7 +235,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
struct comedi_subdevice *s;
unsigned long iobase = 0;
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
struct pci_dev *pci_dev = NULL;
int bus = 0, slot = 0;
#endif
@@ -237,7 +247,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
* Allocate the private structure area. alloc_private() is a
* convenient macro defined in comedidev.h.
*/
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
ret = alloc_private(dev, sizeof(struct pc263_private));
if (ret < 0) {
printk(KERN_ERR "comedi%d: error! out of memory!\n",
@@ -247,10 +257,12 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
#endif
/* Process options. */
switch (thisboard->bustype) {
+#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
case isa_bustype:
iobase = it->options[0];
break;
-#ifdef CONFIG_COMEDI_PCI
+#endif
+#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
case pci_bustype:
bus = it->options[0];
slot = it->options[1];
@@ -260,7 +272,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
devpriv->pci_dev = pci_dev;
break;
-#endif /* CONFIG_COMEDI_PCI */
+#endif
default:
printk(KERN_ERR
"comedi%d: %s: BUG! cannot determine board type!\n",
@@ -275,7 +287,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev->board_name = thisboard->name;
/* Enable device and reserve I/O spaces. */
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
if (pci_dev) {
ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME);
if (ret < 0) {
@@ -289,9 +301,11 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
} else
#endif
{
+#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
ret = pc263_request_region(dev->minor, iobase, PC263_IO_SIZE);
if (ret < 0)
return ret;
+#endif
}
dev->iobase = iobase;
@@ -322,12 +336,18 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->state = s->state | (inb(dev->iobase) << 8);
printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
- if (thisboard->bustype == isa_bustype) {
+ switch (thisboard->bustype) {
+#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
+ case isa_bustype:
printk("(base %#lx) ", iobase);
- } else {
-#ifdef CONFIG_COMEDI_PCI
+ break;
+#endif
+#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
printk("(pci %s) ", pci_name(pci_dev));
+ break;
#endif
+ default:
+ break;
}
printk("attached\n");
@@ -335,23 +355,13 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 1;
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int pc263_detach(struct comedi_device *dev)
+static void pc263_detach(struct comedi_device *dev)
{
- printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
- PC263_DRIVER_NAME);
-
-#ifdef CONFIG_COMEDI_PCI
- if (devpriv) {
+#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
+ if (devpriv)
#endif
-#ifdef CONFIG_COMEDI_PCI
+ {
+#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
if (devpriv->pci_dev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
@@ -359,21 +369,19 @@ static int pc263_detach(struct comedi_device *dev)
} else
#endif
{
+#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
if (dev->iobase)
release_region(dev->iobase, PC263_IO_SIZE);
+#endif
}
}
- if (dev->board_name) {
- printk(KERN_INFO "comedi%d: %s removed\n",
- dev->minor, dev->board_name);
- }
- return 0;
}
/*
* This function checks and requests an I/O region, reporting an error
* if there is a conflict.
*/
+#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
static int pc263_request_region(unsigned minor, unsigned long from,
unsigned long extent)
{
@@ -384,6 +392,7 @@ static int pc263_request_region(unsigned minor, unsigned long from,
}
return 0;
}
+#endif
/* DIO devices are slightly special. Although it is possible to
* implement the insn_read/insn_write interface, it is much more
@@ -429,12 +438,12 @@ static int pc263_dio_insn_config(struct comedi_device *dev,
* A convenient macro that defines init_module() and cleanup_module(),
* as necessary.
*/
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
static int __devinit driver_amplc_pc263_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
- return comedi_pci_auto_config(dev, driver_amplc_pc263.driver_name);
+ return comedi_pci_auto_config(dev, &driver_amplc_pc263);
}
static void __devexit driver_amplc_pc263_pci_remove(struct pci_dev *dev)
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index b278917cec25..fbf19cae8747 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -380,18 +380,6 @@ static const struct pci224_board pci224_boards[] = {
};
/*
- * PCI driver table.
- */
-
-static DEFINE_PCI_DEVICE_TABLE(pci224_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI224) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI234) },
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, pci224_pci_table);
-
-/*
* Useful for shorthand access to the particular board structure
*/
#define thisboard ((struct pci224_board *)dev->board_ptr)
@@ -422,65 +410,6 @@ struct pci224_private {
#define devpriv ((struct pci224_private *)dev->private)
/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int pci224_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pci224_detach(struct comedi_device *dev);
-static struct comedi_driver driver_amplc_pci224 = {
- .driver_name = DRIVER_NAME,
- .module = THIS_MODULE,
- .attach = pci224_attach,
- .detach = pci224_detach,
- .board_name = &pci224_boards[0].name,
- .offset = sizeof(struct pci224_board),
- .num_names = ARRAY_SIZE(pci224_boards),
-};
-
-static int __devinit driver_amplc_pci224_pci_probe(struct pci_dev *dev,
- const struct pci_device_id
- *ent)
-{
- return comedi_pci_auto_config(dev, driver_amplc_pci224.driver_name);
-}
-
-static void __devexit driver_amplc_pci224_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver driver_amplc_pci224_pci_driver = {
- .id_table = pci224_pci_table,
- .probe = &driver_amplc_pci224_pci_probe,
- .remove = __devexit_p(&driver_amplc_pci224_pci_remove)
-};
-
-static int __init driver_amplc_pci224_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_amplc_pci224);
- if (retval < 0)
- return retval;
-
- driver_amplc_pci224_pci_driver.name =
- (char *)driver_amplc_pci224.driver_name;
- return pci_register_driver(&driver_amplc_pci224_pci_driver);
-}
-
-static void __exit driver_amplc_pci224_cleanup_module(void)
-{
- pci_unregister_driver(&driver_amplc_pci224_pci_driver);
- comedi_driver_unregister(&driver_amplc_pci224);
-}
-
-module_init(driver_amplc_pci224_init_module);
-module_exit(driver_amplc_pci224_cleanup_module);
-
-/*
* Called from the 'insn_write' function to perform a single write.
*/
static void
@@ -1312,6 +1241,20 @@ static irqreturn_t pci224_interrupt(int irq, void *d)
}
/*
+ * This function looks for a board matching the supplied PCI device.
+ */
+static const struct pci224_board
+*pci224_find_pci_board(struct pci_dev *pci_dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pci224_boards); i++)
+ if (pci_dev->device == pci224_boards[i].devid)
+ return &pci224_boards[i];
+ return NULL;
+}
+
+/*
* This function looks for a PCI device matching the requested board name,
* bus and slot.
*/
@@ -1336,17 +1279,12 @@ pci224_find_pci(struct comedi_device *dev, int bus, int slot,
}
if (thisboard->model == any_model) {
/* Match any supported model. */
- int i;
-
- for (i = 0; i < ARRAY_SIZE(pci224_boards); i++) {
- if (pci_dev->device == pci224_boards[i].devid) {
- /* Change board_ptr to matched board. */
- dev->board_ptr = &pci224_boards[i];
- break;
- }
- }
- if (i == ARRAY_SIZE(pci224_boards))
+ const struct pci224_board *board_ptr;
+ board_ptr = pci224_find_pci_board(pci_dev);
+ if (board_ptr == NULL)
continue;
+ /* Change board_ptr to matched board. */
+ dev->board_ptr = board_ptr;
} else {
/* Match specific model name. */
if (thisboard->devid != pci_dev->device)
@@ -1370,35 +1308,16 @@ pci224_find_pci(struct comedi_device *dev, int bus, int slot,
}
/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
+ * Common part of attach and attach_pci.
*/
-static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int pci224_attach_common(struct comedi_device *dev,
+ struct pci_dev *pci_dev, int *options)
{
struct comedi_subdevice *s;
- struct pci_dev *pci_dev;
unsigned int irq;
- int bus = 0, slot = 0;
unsigned n;
int ret;
- printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, DRIVER_NAME);
-
- bus = it->options[0];
- slot = it->options[1];
- ret = alloc_private(dev, sizeof(struct pci224_private));
- if (ret < 0) {
- printk(KERN_ERR "comedi%d: error! out of memory!\n",
- dev->minor);
- return ret;
- }
-
- ret = pci224_find_pci(dev, bus, slot, &pci_dev);
- if (ret < 0)
- return ret;
-
devpriv->pci_dev = pci_dev;
ret = comedi_pci_enable(pci_dev, DRIVER_NAME);
if (ret < 0) {
@@ -1483,24 +1402,26 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!s->range_table_list)
return -ENOMEM;
- for (n = 2; n < 3 + s->n_chan; n++) {
- if (it->options[n] < 0 || it->options[n] > 1) {
- printk(KERN_WARNING "comedi%d: %s: warning! "
- "bad options[%u]=%d\n",
- dev->minor, DRIVER_NAME, n,
- it->options[n]);
+ if (options) {
+ for (n = 2; n < 3 + s->n_chan; n++) {
+ if (options[n] < 0 || options[n] > 1) {
+ printk(KERN_WARNING
+ "comedi%d: %s: warning! bad options[%u]=%d\n",
+ dev->minor, DRIVER_NAME, n,
+ options[n]);
+ }
}
}
for (n = 0; n < s->n_chan; n++) {
- if (n < COMEDI_NDEVCONFOPTS - 3 &&
- it->options[3 + n] == 1) {
- if (it->options[2] == 1)
+ if (n < COMEDI_NDEVCONFOPTS - 3 && options &&
+ options[3 + n] == 1) {
+ if (options[2] == 1)
range_table_list[n] = &range_pci234_ext;
else
range_table_list[n] = &range_bipolar5;
} else {
- if (it->options[2] == 1) {
+ if (options && options[2] == 1) {
range_table_list[n] =
&range_pci234_ext2;
} else {
@@ -1511,14 +1432,14 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->hwrange = hwrange_pci234;
} else {
/* PCI224 range options. */
- if (it->options[2] == 1) {
+ if (options && options[2] == 1) {
s->range_table = &range_pci224_external;
devpriv->hwrange = hwrange_pci224_external;
} else {
- if (it->options[2] != 0) {
+ if (options && options[2] != 0) {
printk(KERN_WARNING "comedi%d: %s: warning! "
"bad options[2]=%d\n",
- dev->minor, DRIVER_NAME, it->options[2]);
+ dev->minor, DRIVER_NAME, options[2]);
}
s->range_table = &range_pci224_internal;
devpriv->hwrange = hwrange_pci224_internal;
@@ -1552,21 +1473,59 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 1;
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int pci224_detach(struct comedi_device *dev)
+static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+{
+ struct pci_dev *pci_dev;
+ int bus, slot;
+ int ret;
+
+ printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, DRIVER_NAME);
+
+ bus = it->options[0];
+ slot = it->options[1];
+ ret = alloc_private(dev, sizeof(struct pci224_private));
+ if (ret < 0) {
+ printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ dev->minor);
+ return ret;
+ }
+
+ ret = pci224_find_pci(dev, bus, slot, &pci_dev);
+ if (ret < 0)
+ return ret;
+
+ return pci224_attach_common(dev, pci_dev, it->options);
+}
+
+static int
+pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev)
{
- printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor, DRIVER_NAME);
+ int ret;
+
+ printk(KERN_DEBUG "comedi%d: %s: attach_pci %s\n", dev->minor,
+ DRIVER_NAME, pci_name(pci_dev));
+
+ ret = alloc_private(dev, sizeof(struct pci224_private));
+ if (ret < 0) {
+ printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ dev->minor);
+ return ret;
+ }
+ dev->board_ptr = pci224_find_pci_board(pci_dev);
+ if (dev->board_ptr == NULL) {
+ printk(KERN_ERR
+ "comedi%d: %s: BUG! cannot determine board type!\n",
+ dev->minor, DRIVER_NAME);
+ return -EINVAL;
+ }
+ return pci224_attach_common(dev, pci_dev, NULL);
+}
+
+static void pci224_detach(struct comedi_device *dev)
+{
if (dev->irq)
free_irq(dev->irq, dev);
-
if (dev->subdevices) {
struct comedi_subdevice *s;
@@ -1581,18 +1540,49 @@ static int pci224_detach(struct comedi_device *dev)
if (devpriv->pci_dev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
-
pci_dev_put(devpriv->pci_dev);
}
}
- if (dev->board_name) {
- printk(KERN_INFO "comedi%d: %s removed\n",
- dev->minor, dev->board_name);
- }
+}
- return 0;
+static struct comedi_driver amplc_pci224_driver = {
+ .driver_name = "amplc_pci224",
+ .module = THIS_MODULE,
+ .attach = pci224_attach,
+ .detach = pci224_detach,
+ .attach_pci = pci224_attach_pci,
+ .board_name = &pci224_boards[0].name,
+ .offset = sizeof(struct pci224_board),
+ .num_names = ARRAY_SIZE(pci224_boards),
+};
+
+static int __devinit amplc_pci224_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id
+ *ent)
+{
+ return comedi_pci_auto_config(dev, &amplc_pci224_driver);
}
+static void __devexit amplc_pci224_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(amplc_pci224_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI224) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI234) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, amplc_pci224_pci_table);
+
+static struct pci_driver amplc_pci224_pci_driver = {
+ .name = "amplc_pci224",
+ .id_table = amplc_pci224_pci_table,
+ .probe = amplc_pci224_pci_probe,
+ .remove = __devexit_p(amplc_pci224_pci_remove),
+};
+module_comedi_pci_driver(amplc_pci224_driver, amplc_pci224_pci_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index 538979551c8e..d4c80b1281f2 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -500,13 +500,6 @@ static const struct pci230_board pci230_boards[] = {
},
};
-static DEFINE_PCI_DEVICE_TABLE(pci230_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) },
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, pci230_pci_table);
/*
* Useful for shorthand access to the particular board structure
*/
@@ -595,65 +588,6 @@ static const struct comedi_lrange pci230_ao_range = { 2, {
/* PCI230 daccon bipolar flag for each analogue output range. */
static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int pci230_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pci230_detach(struct comedi_device *dev);
-static struct comedi_driver driver_amplc_pci230 = {
- .driver_name = "amplc_pci230",
- .module = THIS_MODULE,
- .attach = pci230_attach,
- .detach = pci230_detach,
- .board_name = &pci230_boards[0].name,
- .offset = sizeof(pci230_boards[0]),
- .num_names = ARRAY_SIZE(pci230_boards),
-};
-
-static int __devinit driver_amplc_pci230_pci_probe(struct pci_dev *dev,
- const struct pci_device_id
- *ent)
-{
- return comedi_pci_auto_config(dev, driver_amplc_pci230.driver_name);
-}
-
-static void __devexit driver_amplc_pci230_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver driver_amplc_pci230_pci_driver = {
- .id_table = pci230_pci_table,
- .probe = &driver_amplc_pci230_pci_probe,
- .remove = __devexit_p(&driver_amplc_pci230_pci_remove)
-};
-
-static int __init driver_amplc_pci230_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_amplc_pci230);
- if (retval < 0)
- return retval;
-
- driver_amplc_pci230_pci_driver.name =
- (char *)driver_amplc_pci230.driver_name;
- return pci_register_driver(&driver_amplc_pci230_pci_driver);
-}
-
-static void __exit driver_amplc_pci230_cleanup_module(void)
-{
- pci_unregister_driver(&driver_amplc_pci230_pci_driver);
- comedi_driver_unregister(&driver_amplc_pci230);
-}
-
-module_init(driver_amplc_pci230_init_module);
-module_exit(driver_amplc_pci230_cleanup_module);
-
static int pci230_ai_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn,
unsigned int *data);
@@ -1003,35 +937,19 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 1;
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int pci230_detach(struct comedi_device *dev)
+static void pci230_detach(struct comedi_device *dev)
{
- printk("comedi%d: amplc_pci230: remove\n", dev->minor);
-
if (dev->subdevices && thisboard->have_dio)
- /* Clean up dio subdevice. */
subdev_8255_cleanup(dev, dev->subdevices + 2);
-
if (dev->irq)
free_irq(dev->irq, dev);
-
if (devpriv) {
if (devpriv->pci_dev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
-
pci_dev_put(devpriv->pci_dev);
}
}
-
- return 0;
}
static int get_resources(struct comedi_device *dev, unsigned int res_mask,
@@ -3048,6 +2966,42 @@ static int pci230_ai_cancel(struct comedi_device *dev,
return 0;
}
+static struct comedi_driver amplc_pci230_driver = {
+ .driver_name = "amplc_pci230",
+ .module = THIS_MODULE,
+ .attach = pci230_attach,
+ .detach = pci230_detach,
+ .board_name = &pci230_boards[0].name,
+ .offset = sizeof(pci230_boards[0]),
+ .num_names = ARRAY_SIZE(pci230_boards),
+};
+
+static int __devinit amplc_pci230_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &amplc_pci230_driver);
+}
+
+static void __devexit amplc_pci230_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(amplc_pci230_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, amplc_pci230_pci_table);
+
+static struct pci_driver amplc_pci230_pci_driver = {
+ .name = "amplc_pci230",
+ .id_table = amplc_pci230_pci_table,
+ .probe = amplc_pci230_pci_probe,
+ .remove = __devexit_p(amplc_pci230_pci_remove)
+};
+module_comedi_pci_driver(amplc_pci230_driver, amplc_pci230_pci_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
index 11cdaf2a5aa5..fb9951a746a6 100644
--- a/drivers/staging/comedi/drivers/c6xdigio.c
+++ b/drivers/staging/comedi/drivers/c6xdigio.c
@@ -97,16 +97,6 @@ union encvaluetype {
#define C6XDIGIO_TIME_OUT 20
-static int c6xdigio_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int c6xdigio_detach(struct comedi_device *dev);
-struct comedi_driver driver_c6xdigio = {
- .driver_name = "c6xdigio",
- .module = THIS_MODULE,
- .attach = c6xdigio_attach,
- .detach = c6xdigio_detach,
-};
-
static void C6X_pwmInit(unsigned long baseAddr)
{
int timeout = 0;
@@ -407,10 +397,6 @@ static void board_init(struct comedi_device *dev)
}
-/* static void board_halt(struct comedi_device *dev) { */
-/* C6X_pwmInit(dev->iobase); */
-/* } */
-
/*
options[0] - I/O port
options[1] - irq
@@ -500,36 +486,22 @@ static int c6xdigio_attach(struct comedi_device *dev,
return 0;
}
-static int c6xdigio_detach(struct comedi_device *dev)
+static void c6xdigio_detach(struct comedi_device *dev)
{
- /* board_halt(dev); may not need this */
-
- printk(KERN_DEBUG "comedi%d: c6xdigio: remove\n", dev->minor);
-
if (dev->iobase)
release_region(dev->iobase, C6XDIGIO_SIZE);
-
- /* Not using IRQ so I am not sure if I need this */
if (dev->irq)
free_irq(dev->irq, dev);
-
pnp_unregister_driver(&c6xdigio_pnp_driver);
-
- return 0;
-}
-
-static int __init driver_c6xdigio_init_module(void)
-{
- return comedi_driver_register(&driver_c6xdigio);
}
-static void __exit driver_c6xdigio_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_c6xdigio);
-}
-
-module_init(driver_c6xdigio_init_module);
-module_exit(driver_c6xdigio_cleanup_module);
+static struct comedi_driver c6xdigio_driver = {
+ .driver_name = "c6xdigio",
+ .module = THIS_MODULE,
+ .attach = c6xdigio_attach,
+ .detach = c6xdigio_detach,
+};
+module_comedi_driver(c6xdigio_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 49404f49f7b7..35159235a1b6 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -91,7 +91,7 @@ struct das16cs_private {
static int das16cs_attach(struct comedi_device *dev,
struct comedi_devconfig *it);
-static int das16cs_detach(struct comedi_device *dev);
+static void das16cs_detach(struct comedi_device *dev);
static struct comedi_driver driver_das16cs = {
.driver_name = "cb_das16_cs",
.module = THIS_MODULE,
@@ -255,15 +255,10 @@ static int das16cs_attach(struct comedi_device *dev,
return 1;
}
-static int das16cs_detach(struct comedi_device *dev)
+static void das16cs_detach(struct comedi_device *dev)
{
- dev_dbg(dev->hw_dev, "comedi%d: das16cs: remove\n", dev->minor);
-
if (dev->irq)
free_irq(dev->irq, dev);
-
-
- return 0;
}
static irqreturn_t das16cs_interrupt(int irq, void *d)
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index 7e4ffcfdac62..ee9e084bb96c 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -405,20 +405,6 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
},
};
-static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0001) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000f) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0010) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0019) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001c) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x004c) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001a) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001b) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
-
/*
* Useful for shorthand access to the particular board structure
*/
@@ -462,22 +448,6 @@ struct cb_pcidas_private {
*/
#define devpriv ((struct cb_pcidas_private *)dev->private)
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int cb_pcidas_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int cb_pcidas_detach(struct comedi_device *dev);
-static struct comedi_driver driver_cb_pcidas = {
- .driver_name = "cb_pcidas",
- .module = THIS_MODULE,
- .attach = cb_pcidas_attach,
- .detach = cb_pcidas_detach,
-};
-
static int cb_pcidas_ai_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
@@ -756,26 +726,12 @@ found:
return 1;
}
-/*
- * cb_pcidas_detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int cb_pcidas_detach(struct comedi_device *dev)
+static void cb_pcidas_detach(struct comedi_device *dev)
{
-
if (devpriv) {
if (devpriv->s5933_config) {
- /* disable and clear interrupts on amcc s5933 */
outl(INTCSR_INBOX_INTR_STATUS,
devpriv->s5933_config + AMCC_OP_REG_INTCSR);
-#ifdef CB_PCIDAS_DEBUG
- dev_dbg(dev->hw_dev, "detaching, incsr is 0x%x\n",
- inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR));
-#endif
}
}
if (dev->irq)
@@ -787,8 +743,6 @@ static int cb_pcidas_detach(struct comedi_device *dev)
comedi_pci_disable(devpriv->pci_dev);
pci_dev_put(devpriv->pci_dev);
}
-
- return 0;
}
/*
@@ -1918,47 +1872,44 @@ static int nvram_read(struct comedi_device *dev, unsigned int address,
return 0;
}
-/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
- */
-static int __devinit driver_cb_pcidas_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static struct comedi_driver cb_pcidas_driver = {
+ .driver_name = "cb_pcidas",
+ .module = THIS_MODULE,
+ .attach = cb_pcidas_attach,
+ .detach = cb_pcidas_detach,
+};
+
+static int __devinit cb_pcidas_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_cb_pcidas.driver_name);
+ return comedi_pci_auto_config(dev, &cb_pcidas_driver);
}
-static void __devexit driver_cb_pcidas_pci_remove(struct pci_dev *dev)
+static void __devexit cb_pcidas_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_cb_pcidas_pci_driver = {
- .id_table = cb_pcidas_pci_table,
- .probe = &driver_cb_pcidas_pci_probe,
- .remove = __devexit_p(&driver_cb_pcidas_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0001) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000f) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0010) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0019) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001c) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x004c) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001a) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001b) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
-static int __init driver_cb_pcidas_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_cb_pcidas);
- if (retval < 0)
- return retval;
-
- driver_cb_pcidas_pci_driver.name = (char *)driver_cb_pcidas.driver_name;
- return pci_register_driver(&driver_cb_pcidas_pci_driver);
-}
-
-static void __exit driver_cb_pcidas_cleanup_module(void)
-{
- pci_unregister_driver(&driver_cb_pcidas_pci_driver);
- comedi_driver_unregister(&driver_cb_pcidas);
-}
-
-module_init(driver_cb_pcidas_init_module);
-module_exit(driver_cb_pcidas_cleanup_module);
+static struct pci_driver cb_pcidas_pci_driver = {
+ .name = "cb_pcidas",
+ .id_table = cb_pcidas_pci_table,
+ .probe = cb_pcidas_pci_probe,
+ .remove = __devexit_p(cb_pcidas_pci_remove)
+};
+module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index 915157d47805..9d0b8754ff5b 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -1026,31 +1026,6 @@ static const struct pcidas64_board pcidas64_boards[] = {
#endif
};
-static DEFINE_PCI_DEVICE_TABLE(pcidas64_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x001d) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x001e) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0035) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0036) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0037) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0052) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x005d) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x005e) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x005f) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0061) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0062) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0063) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0064) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0066) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0067) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0068) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x006f) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0078) },
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0079) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, pcidas64_pci_table);
-
static inline struct pcidas64_board *board(const struct comedi_device *dev)
{
return (struct pcidas64_board *)dev->board_ptr;
@@ -1127,21 +1102,6 @@ static inline struct pcidas64_private *priv(struct comedi_device *dev)
return dev->private;
}
-/*
- * The comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int detach(struct comedi_device *dev);
-static struct comedi_driver driver_cb_pcidas = {
- .driver_name = "cb_pcidas64",
- .module = THIS_MODULE,
- .attach = attach,
- .detach = detach,
-};
-
static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
@@ -1216,44 +1176,6 @@ static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags);
static void load_ao_dma(struct comedi_device *dev,
const struct comedi_cmd *cmd);
-static int __devinit driver_cb_pcidas_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, driver_cb_pcidas.driver_name);
-}
-
-static void __devexit driver_cb_pcidas_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver driver_cb_pcidas_pci_driver = {
- .id_table = pcidas64_pci_table,
- .probe = &driver_cb_pcidas_pci_probe,
- .remove = __devexit_p(&driver_cb_pcidas_pci_remove)
-};
-
-static int __init driver_cb_pcidas_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_cb_pcidas);
- if (retval < 0)
- return retval;
-
- driver_cb_pcidas_pci_driver.name = (char *)driver_cb_pcidas.driver_name;
- return pci_register_driver(&driver_cb_pcidas_pci_driver);
-}
-
-static void __exit driver_cb_pcidas_cleanup_module(void)
-{
- pci_unregister_driver(&driver_cb_pcidas_pci_driver);
- comedi_driver_unregister(&driver_cb_pcidas);
-}
-
-module_init(driver_cb_pcidas_init_module);
-module_exit(driver_cb_pcidas_cleanup_module);
-
static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev,
unsigned int range_index)
{
@@ -1781,7 +1703,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev_dbg(dev->hw_dev, "Found %s on bus %i, slot %i\n", board(dev)->name,
pcidev->bus->number, PCI_SLOT(pcidev->devfn));
- if (comedi_pci_enable(pcidev, driver_cb_pcidas.driver_name)) {
+ if (comedi_pci_enable(pcidev, dev->driver->driver_name)) {
dev_warn(dev->hw_dev, "failed to enable PCI device and request regions\n");
return -EIO;
}
@@ -1868,15 +1790,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int detach(struct comedi_device *dev)
+static void detach(struct comedi_device *dev)
{
unsigned int i;
@@ -1938,8 +1852,6 @@ static int detach(struct comedi_device *dev)
}
if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 4);
-
- return 0;
}
static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
@@ -4315,6 +4227,56 @@ static void i2c_write(struct comedi_device *dev, unsigned int address,
i2c_stop(dev);
}
+static struct comedi_driver cb_pcidas64_driver = {
+ .driver_name = "cb_pcidas64",
+ .module = THIS_MODULE,
+ .attach = attach,
+ .detach = detach,
+};
+
+static int __devinit cb_pcidas64_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &cb_pcidas64_driver);
+}
+
+static void __devexit cb_pcidas64_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(cb_pcidas64_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x001d) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x001e) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0035) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0036) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0037) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0052) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x005d) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x005e) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x005f) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0061) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0062) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0063) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0064) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0066) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0067) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0068) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x006f) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0078) },
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0079) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, cb_pcidas64_pci_table);
+
+static struct pci_driver cb_pcidas64_pci_driver = {
+ .name = "cb_pcidas64",
+ .id_table = cb_pcidas64_pci_table,
+ .probe = cb_pcidas64_pci_probe,
+ .remove = __devexit_p(cb_pcidas64_pci_remove),
+};
+module_comedi_pci_driver(cb_pcidas64_driver, cb_pcidas64_pci_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index abba220a767f..25ebca11eadc 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -51,9 +51,12 @@ Please report success/failure with other different cards to
#include "comedi_pci.h"
#include "8255.h"
-#define PCI_VENDOR_ID_CB 0x1307 /* PCI vendor number of ComputerBoards */
+
+/* PCI vendor number of ComputerBoards */
+#define PCI_VENDOR_ID_CB 0x1307
#define EEPROM_SIZE 128 /* number of entries in eeprom */
-#define MAX_AO_CHANNELS 8 /* maximum number of ao channels for supported boards */
+/* maximum number of ao channels for supported boards */
+#define MAX_AO_CHANNELS 8
/* PCI-DDA base addresses */
#define DIGITALIO_BADRINDEX 2
@@ -94,20 +97,26 @@ Please report success/failure with other different cards to
#define DACALIBRATION1 4 /* D/A CALIBRATION REGISTER 1 */
/* write bits */
-#define SERIAL_IN_BIT 0x1 /* serial data input for eeprom, caldacs, reference dac */
+/* serial data input for eeprom, caldacs, reference dac */
+#define SERIAL_IN_BIT 0x1
#define CAL_CHANNEL_MASK (0x7 << 1)
#define CAL_CHANNEL_BITS(channel) (((channel) << 1) & CAL_CHANNEL_MASK)
/* read bits */
#define CAL_COUNTER_MASK 0x1f
-#define CAL_COUNTER_OVERFLOW_BIT 0x20 /* calibration counter overflow status bit */
-#define AO_BELOW_REF_BIT 0x40 /* analog output is less than reference dac voltage */
+/* calibration counter overflow status bit */
+#define CAL_COUNTER_OVERFLOW_BIT 0x20
+/* analog output is less than reference dac voltage */
+#define AO_BELOW_REF_BIT 0x40
#define SERIAL_OUT_BIT 0x80 /* serial data out, for reading from eeprom */
#define DACALIBRATION2 6 /* D/A CALIBRATION REGISTER 2 */
#define SELECT_EEPROM_BIT 0x1 /* send serial data in to eeprom */
-#define DESELECT_REF_DAC_BIT 0x2 /* don't send serial data to MAX542 reference dac */
-#define DESELECT_CALDAC_BIT(n) (0x4 << (n)) /* don't send serial data to caldac n */
-#define DUMMY_BIT 0x40 /* manual says to set this bit with no explanation */
+/* don't send serial data to MAX542 reference dac */
+#define DESELECT_REF_DAC_BIT 0x2
+/* don't send serial data to caldac n */
+#define DESELECT_CALDAC_BIT(n) (0x4 << (n))
+/* manual says to set this bit with no explanation */
+#define DUMMY_BIT 0x40
#define DADATA 8 /* FIRST D/A DATA REGISTER (0) */
@@ -195,26 +204,17 @@ static const struct cb_pcidda_board cb_pcidda_boards[] = {
},
};
-static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0020) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0021) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0022) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0023) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0024) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0025) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
-
/*
* Useful for shorthand access to the particular board structure
*/
#define thisboard ((const struct cb_pcidda_board *)dev->board_ptr)
-/* this structure is for data unique to this hardware driver. If
- several hardware drivers keep similar information in this structure,
- feel free to suggest moving the variable to the struct comedi_device struct. */
+/*
+ * this structure is for data unique to this hardware driver. If
+ * several hardware drivers keep similar information in this structure,
+ * feel free to suggest moving the variable to the struct comedi_device
+ * struct.
+ */
struct cb_pcidda_private {
int data;
@@ -227,8 +227,10 @@ struct cb_pcidda_private {
/* unsigned long control_status; */
/* unsigned long adc_fifo; */
- unsigned int dac_cal1_bits; /* bits last written to da calibration register 1 */
- unsigned int ao_range[MAX_AO_CHANNELS]; /* current range settings for output channels */
+ /* bits last written to da calibration register 1 */
+ unsigned int dac_cal1_bits;
+ /* current range settings for output channels */
+ unsigned int ao_range[MAX_AO_CHANNELS];
u16 eeprom_data[EEPROM_SIZE]; /* software copy of board's eeprom */
};
@@ -238,9 +240,6 @@ struct cb_pcidda_private {
*/
#define devpriv ((struct cb_pcidda_private *)dev->private)
-static int cb_pcidda_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int cb_pcidda_detach(struct comedi_device *dev);
/* static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */
static int cb_pcidda_ao_winsn(struct comedi_device *dev,
struct comedi_subdevice *s,
@@ -259,19 +258,6 @@ static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
unsigned int range);
/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static struct comedi_driver driver_cb_pcidda = {
- .driver_name = "cb_pcidda",
- .module = THIS_MODULE,
- .attach = cb_pcidda_attach,
- .detach = cb_pcidda_detach,
-};
-
-/*
* Attach is called by the Comedi core to configure the driver
* for a particular board.
*/
@@ -377,7 +363,8 @@ found:
dev_dbg(dev->hw_dev, "eeprom:\n");
for (index = 0; index < EEPROM_SIZE; index++) {
devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
- dev_dbg(dev->hw_dev, "%i:0x%x\n", index, devpriv->eeprom_data[index]);
+ dev_dbg(dev->hw_dev, "%i:0x%x\n", index,
+ devpriv->eeprom_data[index]);
}
/* set calibrations dacs */
@@ -387,19 +374,8 @@ found:
return 1;
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int cb_pcidda_detach(struct comedi_device *dev)
+static void cb_pcidda_detach(struct comedi_device *dev)
{
-/*
- * Deallocate the I/O ports.
- */
if (devpriv) {
if (devpriv->pci_dev) {
if (devpriv->dac)
@@ -407,13 +383,10 @@ static int cb_pcidda_detach(struct comedi_device *dev)
pci_dev_put(devpriv->pci_dev);
}
}
- /* cleanup 8255 */
if (dev->subdevices) {
subdev_8255_cleanup(dev, dev->subdevices + 1);
subdev_8255_cleanup(dev, dev->subdevices + 2);
}
-
- return 0;
}
/*
@@ -484,7 +457,10 @@ static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and mutually compatible */
+ /*
+ * step 2: make sure trigger sources are unique and mutually
+ * compatible
+ */
/* note that mutual compatibility is not an issue here */
if (cmd->scan_begin_src != TRIG_TIMER
@@ -696,8 +672,10 @@ static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
unsigned int i;
unsigned int cal2_bits;
unsigned int value;
- const int max_num_caldacs = 4; /* one caldac for every two dac channels */
- const int read_instruction = 0x6; /* bits to send to tell eeprom we want to read */
+ /* one caldac for every two dac channels */
+ const int max_num_caldacs = 4;
+ /* bits to send to tell eeprom we want to read */
+ const int read_instruction = 0x6;
const int instruction_length = 3;
const int address_length = 8;
@@ -729,9 +707,11 @@ static void cb_pcidda_write_caldac(struct comedi_device *dev,
{
unsigned int cal2_bits;
unsigned int i;
- const int num_channel_bits = 3; /* caldacs use 3 bit channel specification */
+ /* caldacs use 3 bit channel specification */
+ const int num_channel_bits = 3;
const int num_caldac_bits = 8; /* 8 bit calibration dacs */
- const int max_num_caldacs = 4; /* one caldac for every two dac channels */
+ /* one caldac for every two dac channels */
+ const int max_num_caldacs = 4;
/* write 3 bit channel */
cb_pcidda_serial_out(dev, channel, num_channel_bits);
@@ -790,14 +770,20 @@ static unsigned int offset_eeprom_address(unsigned int ao_channel,
return 0x7 + 2 * range + 12 * ao_channel;
}
-/* returns eeprom address that provides gain calibration for given ao channel and range */
+/*
+ * returns eeprom address that provides gain calibration for given ao
+ * channel and range
+ */
static unsigned int gain_eeprom_address(unsigned int ao_channel,
unsigned int range)
{
return 0x8 + 2 * range + 12 * ao_channel;
}
-/* returns upper byte of eeprom entry, which gives the coarse adjustment values */
+/*
+ * returns upper byte of eeprom entry, which gives the coarse adjustment
+ * values
+ */
static unsigned int eeprom_coarse_byte(unsigned int word)
{
return (word >> 8) & 0xff;
@@ -815,7 +801,7 @@ static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
{
unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
- /* remember range so we can tell when we need to readjust calibration */
+ /* remember range so we can tell when we need to readjust calibration */
devpriv->ao_range[channel] = range;
/* get values from eeprom data */
@@ -843,47 +829,42 @@ static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
fine_gain_channel(channel), fine_gain);
}
-/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
- */
-static int __devinit driver_cb_pcidda_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static struct comedi_driver cb_pcidda_driver = {
+ .driver_name = "cb_pcidda",
+ .module = THIS_MODULE,
+ .attach = cb_pcidda_attach,
+ .detach = cb_pcidda_detach,
+};
+
+static int __devinit cb_pcidda_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_cb_pcidda.driver_name);
+ return comedi_pci_auto_config(dev, &cb_pcidda_driver);
}
-static void __devexit driver_cb_pcidda_pci_remove(struct pci_dev *dev)
+static void __devexit cb_pcidda_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_cb_pcidda_pci_driver = {
- .id_table = cb_pcidda_pci_table,
- .probe = &driver_cb_pcidda_pci_probe,
- .remove = __devexit_p(&driver_cb_pcidda_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0020) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0021) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0022) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0023) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0024) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0025) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
-static int __init driver_cb_pcidda_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_cb_pcidda);
- if (retval < 0)
- return retval;
-
- driver_cb_pcidda_pci_driver.name = (char *)driver_cb_pcidda.driver_name;
- return pci_register_driver(&driver_cb_pcidda_pci_driver);
-}
-
-static void __exit driver_cb_pcidda_cleanup_module(void)
-{
- pci_unregister_driver(&driver_cb_pcidda_pci_driver);
- comedi_driver_unregister(&driver_cb_pcidda);
-}
-
-module_init(driver_cb_pcidda_init_module);
-module_exit(driver_cb_pcidda_cleanup_module);
+static struct pci_driver cb_pcidda_pci_driver = {
+ .name = "cb_pcidda",
+ .id_table = cb_pcidda_pci_table,
+ .probe = cb_pcidda_pci_probe,
+ .remove = __devexit_p(cb_pcidda_pci_remove),
+};
+module_comedi_pci_driver(cb_pcidda_driver, cb_pcidda_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
index 8f3215239a15..713132c8dbb5 100644
--- a/drivers/staging/comedi/drivers/cb_pcidio.c
+++ b/drivers/staging/comedi/drivers/cb_pcidio.c
@@ -86,19 +86,6 @@ static const struct pcidio_board pcidio_boards[] = {
},
};
-/* This is used by modprobe to translate PCI IDs to drivers. Should
- * only be used for PCI and ISA-PnP devices */
-/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded
- * upstream. */
-static DEFINE_PCI_DEVICE_TABLE(pcidio_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0028) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0014) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000b) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, pcidio_pci_table);
-
/*
* Useful for shorthand access to the particular board structure
*/
@@ -125,59 +112,6 @@ struct pcidio_private {
*/
#define devpriv ((struct pcidio_private *)dev->private)
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int pcidio_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcidio_detach(struct comedi_device *dev);
-static struct comedi_driver driver_cb_pcidio = {
- .driver_name = "cb_pcidio",
- .module = THIS_MODULE,
- .attach = pcidio_attach,
- .detach = pcidio_detach,
-
-/* It is not necessary to implement the following members if you are
- * writing a driver for a ISA PnP or PCI card */
-
- /* Most drivers will support multiple types of boards by
- * having an array of board structures. These were defined
- * in pcidio_boards[] above. Note that the element 'name'
- * was first in the structure -- Comedi uses this fact to
- * extract the name of the board without knowing any details
- * about the structure except for its length.
- * When a device is attached (by comedi_config), the name
- * of the device is given to Comedi, and Comedi tries to
- * match it by going through the list of board names. If
- * there is a match, the address of the pointer is put
- * into dev->board_ptr and driver->attach() is called.
- *
- * Note that these are not necessary if you can determine
- * the type of board in software. ISA PnP, PCI, and PCMCIA
- * devices are such boards.
- */
-
-/* The following fields should NOT be initialized if you are dealing
- * with PCI devices
- *
- * .board_name = pcidio_boards,
- * .offset = sizeof(struct pcidio_board),
- * .num_names = sizeof(pcidio_boards) / sizeof(structpcidio_board),
- */
-
-};
-
-/*------------------------------- FUNCTIONS -----------------------------------*/
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
struct pci_dev *pcidev = NULL;
@@ -261,15 +195,7 @@ found:
return 1;
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int pcidio_detach(struct comedi_device *dev)
+static void pcidio_detach(struct comedi_device *dev)
{
if (devpriv) {
if (devpriv->pci_dev) {
@@ -283,50 +209,41 @@ static int pcidio_detach(struct comedi_device *dev)
for (i = 0; i < thisboard->n_8255; i++)
subdev_8255_cleanup(dev, dev->subdevices + i);
}
- return 0;
}
-/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
- */
-static int __devinit driver_cb_pcidio_pci_probe(struct pci_dev *dev,
+static struct comedi_driver cb_pcidio_driver = {
+ .driver_name = "cb_pcidio",
+ .module = THIS_MODULE,
+ .attach = pcidio_attach,
+ .detach = pcidio_detach,
+};
+
+static int __devinit cb_pcidio_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_cb_pcidio.driver_name);
+ return comedi_pci_auto_config(dev, &cb_pcidio_driver);
}
-static void __devexit driver_cb_pcidio_pci_remove(struct pci_dev *dev)
+static void __devexit cb_pcidio_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_cb_pcidio_pci_driver = {
- .id_table = pcidio_pci_table,
- .probe = &driver_cb_pcidio_pci_probe,
- .remove = __devexit_p(&driver_cb_pcidio_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(cb_pcidio_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0028) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0014) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000b) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, cb_pcidio_pci_table);
-static int __init driver_cb_pcidio_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_cb_pcidio);
- if (retval < 0)
- return retval;
-
- driver_cb_pcidio_pci_driver.name = (char *)driver_cb_pcidio.driver_name;
- return pci_register_driver(&driver_cb_pcidio_pci_driver);
-}
-
-static void __exit driver_cb_pcidio_cleanup_module(void)
-{
- pci_unregister_driver(&driver_cb_pcidio_pci_driver);
- comedi_driver_unregister(&driver_cb_pcidio);
-}
-
-module_init(driver_cb_pcidio_init_module);
-module_exit(driver_cb_pcidio_cleanup_module);
+static struct pci_driver cb_pcidio_pci_driver = {
+ .name = "cb_pcidio",
+ .id_table = cb_pcidio_pci_table,
+ .probe = cb_pcidio_pci_probe,
+ .remove = __devexit_p(cb_pcidio_pci_remove),
+};
+module_comedi_pci_driver(cb_pcidio_driver, cb_pcidio_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index 8ba694263bd3..5f834d02ec24 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -123,15 +123,6 @@ static const struct cb_pcimdas_board cb_pcimdas_boards[] = {
},
};
-/* This is used by modprobe to translate PCI IDs to drivers. Should
- * only be used for PCI and ISA-PnP devices */
-static DEFINE_PCI_DEVICE_TABLE(cb_pcimdas_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0056) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, cb_pcimdas_pci_table);
-
#define N_BOARDS 1 /* Max number of boards supported */
/*
@@ -139,9 +130,12 @@ MODULE_DEVICE_TABLE(pci, cb_pcimdas_pci_table);
*/
#define thisboard ((const struct cb_pcimdas_board *)dev->board_ptr)
-/* this structure is for data unique to this hardware driver. If
- several hardware drivers keep similar information in this structure,
- feel free to suggest moving the variable to the struct comedi_device struct. */
+/*
+ * this structure is for data unique to this hardware driver. If
+ * several hardware drivers keep similar information in this structure,
+ * feel free to suggest moving the variable to the struct comedi_device
+ * struct.
+ */
struct cb_pcimdas_private {
int data;
@@ -172,22 +166,6 @@ struct cb_pcimdas_private {
*/
#define devpriv ((struct cb_pcimdas_private *)dev->private)
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int cb_pcimdas_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int cb_pcimdas_detach(struct comedi_device *dev);
-static struct comedi_driver driver_cb_pcimdas = {
- .driver_name = "cb_pcimdas",
- .module = THIS_MODULE,
- .attach = cb_pcimdas_attach,
- .detach = cb_pcimdas_detach,
-};
-
static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
@@ -317,7 +295,8 @@ found:
s->subdev_flags = SDF_WRITABLE;
s->n_chan = thisboard->ao_nchan;
s->maxdata = 1 << thisboard->ao_bits;
- s->range_table = &range_unknown; /* ranges are hardware settable, but not software readable. */
+ /* ranges are hardware settable, but not software readable. */
+ s->range_table = &range_unknown;
s->insn_write = &cb_pcimdas_ao_winsn;
s->insn_read = &cb_pcimdas_ao_rinsn;
@@ -331,29 +310,8 @@ found:
return 1;
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int cb_pcimdas_detach(struct comedi_device *dev)
+static void cb_pcimdas_detach(struct comedi_device *dev)
{
- if (devpriv) {
- dev_dbg(dev->hw_dev, "devpriv->BADR0 = 0x%lx\n",
- devpriv->BADR0);
- dev_dbg(dev->hw_dev, "devpriv->BADR1 = 0x%lx\n",
- devpriv->BADR1);
- dev_dbg(dev->hw_dev, "devpriv->BADR2 = 0x%lx\n",
- devpriv->BADR2);
- dev_dbg(dev->hw_dev, "devpriv->BADR3 = 0x%lx\n",
- devpriv->BADR3);
- dev_dbg(dev->hw_dev, "devpriv->BADR4 = 0x%lx\n",
- devpriv->BADR4);
- }
-
if (dev->irq)
free_irq(dev->irq, dev);
if (devpriv) {
@@ -363,8 +321,6 @@ static int cb_pcimdas_detach(struct comedi_device *dev)
pci_dev_put(devpriv->pci_dev);
}
}
-
- return 0;
}
/*
@@ -402,7 +358,10 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
outb(0x01, devpriv->BADR3 + 6); /* set bursting off, conversions on */
outb(0x00, devpriv->BADR3 + 7); /* set range to 10V. UP/BP is controlled by a switch on the board */
- /* write channel limits to multiplexer, set Low (bits 0-3) and High (bits 4-7) channels to chan. */
+ /*
+ * write channel limits to multiplexer, set Low (bits 0-3) and
+ * High (bits 4-7) channels to chan.
+ */
chanlims = chan | (chan << 4);
outb(chanlims, devpriv->BADR3 + 0);
@@ -479,49 +438,37 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
return i;
}
-/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
- */
-static int __devinit driver_cb_pcimdas_pci_probe(struct pci_dev *dev,
- const struct pci_device_id
- *ent)
+static struct comedi_driver cb_pcimdas_driver = {
+ .driver_name = "cb_pcimdas",
+ .module = THIS_MODULE,
+ .attach = cb_pcimdas_attach,
+ .detach = cb_pcimdas_detach,
+};
+
+static int __devinit cb_pcimdas_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_cb_pcimdas.driver_name);
+ return comedi_pci_auto_config(dev, &cb_pcimdas_driver);
}
-static void __devexit driver_cb_pcimdas_pci_remove(struct pci_dev *dev)
+static void __devexit cb_pcimdas_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_cb_pcimdas_pci_driver = {
- .id_table = cb_pcimdas_pci_table,
- .probe = &driver_cb_pcimdas_pci_probe,
- .remove = __devexit_p(&driver_cb_pcimdas_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(cb_pcimdas_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0056) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, cb_pcimdas_pci_table);
-static int __init driver_cb_pcimdas_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_cb_pcimdas);
- if (retval < 0)
- return retval;
-
- driver_cb_pcimdas_pci_driver.name =
- (char *)driver_cb_pcimdas.driver_name;
- return pci_register_driver(&driver_cb_pcimdas_pci_driver);
-}
-
-static void __exit driver_cb_pcimdas_cleanup_module(void)
-{
- pci_unregister_driver(&driver_cb_pcimdas_pci_driver);
- comedi_driver_unregister(&driver_cb_pcimdas);
-}
-
-module_init(driver_cb_pcimdas_init_module);
-module_exit(driver_cb_pcimdas_cleanup_module);
+static struct pci_driver cb_pcimdas_pci_driver = {
+ .name = "cb_pcimdas",
+ .id_table = cb_pcimdas_pci_table,
+ .probe = cb_pcimdas_pci_probe,
+ .remove = __devexit_p(cb_pcimdas_pci_remove),
+};
+module_comedi_pci_driver(cb_pcimdas_driver, cb_pcimdas_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
index 40bddfa22220..b339685e234d 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
@@ -140,17 +140,6 @@ static const struct board_struct boards[] = {
#define REG_SZ (thisboard->reg_sz)
#define REGS_BADRINDEX (thisboard->regs_badrindex)
-/* This is used by modprobe to translate PCI IDs to drivers. Should
- * only be used for PCI and ISA-PnP devices */
-/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded
- * upstream. */
-static DEFINE_PCI_DEVICE_TABLE(pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, PCI_ID_PCIM_DDA06_16) },
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, pci_table);
-
/*
* this structure is for data unique to this hardware driver. If
* several hardware drivers keep similar information in this structure,
@@ -161,7 +150,6 @@ struct board_private_struct {
unsigned long registers; /* set by probe */
unsigned long dio_registers;
char attached_to_8255; /* boolean */
- char attached_successfully; /* boolean */
/* would be useful for a PCI device */
struct pci_dev *pci_dev;
@@ -177,66 +165,6 @@ struct board_private_struct {
*/
#define devpriv ((struct board_private_struct *)dev->private)
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int detach(struct comedi_device *dev);
-static struct comedi_driver cb_pcimdda_driver = {
- .driver_name = "cb_pcimdda",
- .module = THIS_MODULE,
- .attach = attach,
- .detach = detach,
-};
-
-MODULE_AUTHOR("Calin A. Culianu <calin@rtlab.org>");
-MODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA "
- "series. Currently only supports PCIM-DDA06-16 (which "
- "also happens to be the only board in this series. :) ) ");
-MODULE_LICENSE("GPL");
-static int __devinit cb_pcimdda_driver_pci_probe(struct pci_dev *dev,
- const struct pci_device_id
- *ent)
-{
- return comedi_pci_auto_config(dev, cb_pcimdda_driver.driver_name);
-}
-
-static void __devexit cb_pcimdda_driver_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver cb_pcimdda_driver_pci_driver = {
- .id_table = pci_table,
- .probe = &cb_pcimdda_driver_pci_probe,
- .remove = __devexit_p(&cb_pcimdda_driver_pci_remove)
-};
-
-static int __init cb_pcimdda_driver_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&cb_pcimdda_driver);
- if (retval < 0)
- return retval;
-
- cb_pcimdda_driver_pci_driver.name =
- (char *)cb_pcimdda_driver.driver_name;
- return pci_register_driver(&cb_pcimdda_driver_pci_driver);
-}
-
-static void __exit cb_pcimdda_driver_cleanup_module(void)
-{
- pci_unregister_driver(&cb_pcimdda_driver_pci_driver);
- comedi_driver_unregister(&cb_pcimdda_driver);
-}
-
-module_init(cb_pcimdda_driver_init_module);
-module_exit(cb_pcimdda_driver_cleanup_module);
-
static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
@@ -354,44 +282,24 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->type = COMEDI_SUBD_UNUSED;
}
- devpriv->attached_successfully = 1;
-
printk("attached\n");
return 1;
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int detach(struct comedi_device *dev)
+static void detach(struct comedi_device *dev)
{
if (devpriv) {
-
if (dev->subdevices && devpriv->attached_to_8255) {
- /* de-register us from the 8255 driver */
subdev_8255_cleanup(dev, dev->subdevices + 2);
devpriv->attached_to_8255 = 0;
}
-
if (devpriv->pci_dev) {
if (devpriv->registers)
comedi_pci_disable(devpriv->pci_dev);
pci_dev_put(devpriv->pci_dev);
}
-
- if (devpriv->attached_successfully && thisboard)
- printk("comedi%d: %s: detached\n", dev->minor,
- thisboard->name);
-
}
-
- return 0;
}
static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
@@ -515,3 +423,41 @@ static int probe(struct comedi_device *dev, const struct comedi_devconfig *it)
"card found at the requested position\n");
return -ENODEV;
}
+
+static struct comedi_driver cb_pcimdda_driver = {
+ .driver_name = "cb_pcimdda",
+ .module = THIS_MODULE,
+ .attach = attach,
+ .detach = detach,
+};
+
+static int __devinit cb_pcimdda_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &cb_pcimdda_driver);
+}
+
+static void __devexit cb_pcimdda_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(cb_pcimdda_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, PCI_ID_PCIM_DDA06_16) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, cb_pcimdda_pci_table);
+
+static struct pci_driver cb_pcimdda_driver_pci_driver = {
+ .name = "cb_pcimdda",
+ .id_table = cb_pcimdda_pci_table,
+ .probe = cb_pcimdda_pci_probe,
+ .remove = __devexit_p(cb_pcimdda_pci_remove),
+};
+module_comedi_pci_driver(cb_pcimdda_driver, cb_pcimdda_driver_pci_driver);
+
+MODULE_AUTHOR("Calin A. Culianu <calin@rtlab.org>");
+MODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA "
+ "series. Currently only supports PCIM-DDA06-16 (which "
+ "also happens to be the only board in this series. :) ) ");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
index d8aefb23d6b9..29412de06c31 100644
--- a/drivers/staging/comedi/drivers/comedi_bond.c
+++ b/drivers/staging/comedi/drivers/comedi_bond.c
@@ -60,7 +60,6 @@ Configuration Options:
#define MAX_CHANS 256
#define MODULE_NAME "comedi_bond"
-MODULE_LICENSE("GPL");
#ifndef STR
# define STR1(x) #x
# define STR(x) STR1(x)
@@ -79,10 +78,6 @@ MODULE_PARM_DESC(debug, "If true, print extra cryptic debugging output useful"
} while (0)
#define WARNING(x...) printk(KERN_WARNING MODULE_NAME ": WARNING: "x)
#define ERROR(x...) printk(KERN_ERR MODULE_NAME ": INTERNAL ERROR: "x)
-MODULE_AUTHOR("Calin A. Culianu");
-MODULE_DESCRIPTION(MODULE_NAME "A driver for COMEDI to bond multiple COMEDI "
- "devices together as one. In the words of John Lennon: "
- "'And the world will live as one...'");
/*
* Board descriptions for two imaginary boards. Describing the
@@ -93,12 +88,6 @@ struct BondingBoard {
const char *name;
};
-static const struct BondingBoard bondingBoards[] = {
- {
- .name = MODULE_NAME,
- },
-};
-
/*
* Useful for shorthand access to the particular board structure
*/
@@ -133,129 +122,6 @@ struct Private {
*/
#define devpriv ((struct Private *)dev->private)
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int bonding_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int bonding_detach(struct comedi_device *dev);
-/** Build Private array of all devices.. */
-static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it);
-static void doDevUnconfig(struct comedi_device *dev);
-/* Ugly implementation of realloc that always copies memory around -- I'm lazy,
- * what can I say? I like to do wasteful memcopies.. :) */
-static void *Realloc(const void *ptr, size_t len, size_t old_len);
-
-static struct comedi_driver driver_bonding = {
- .driver_name = MODULE_NAME,
- .module = THIS_MODULE,
- .attach = bonding_attach,
- .detach = bonding_detach,
- /* It is not necessary to implement the following members if you are
- * writing a driver for a ISA PnP or PCI card */
- /* Most drivers will support multiple types of boards by
- * having an array of board structures. These were defined
- * in skel_boards[] above. Note that the element 'name'
- * was first in the structure -- Comedi uses this fact to
- * extract the name of the board without knowing any details
- * about the structure except for its length.
- * When a device is attached (by comedi_config), the name
- * of the device is given to Comedi, and Comedi tries to
- * match it by going through the list of board names. If
- * there is a match, the address of the pointer is put
- * into dev->board_ptr and driver->attach() is called.
- *
- * Note that these are not necessary if you can determine
- * the type of board in software. ISA PnP, PCI, and PCMCIA
- * devices are such boards.
- */
- .board_name = &bondingBoards[0].name,
- .offset = sizeof(struct BondingBoard),
- .num_names = ARRAY_SIZE(bondingBoards),
-};
-
-static int bonding_dio_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int bonding_dio_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data);
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
-static int bonding_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
-
- LOG_MSG("comedi%d\n", dev->minor);
-
- /*
- * Allocate the private structure area. alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
- if (alloc_private(dev, sizeof(struct Private)) < 0)
- return -ENOMEM;
-
- /*
- * Setup our bonding from config params.. sets up our Private struct..
- */
- if (!doDevConfig(dev, it))
- return -EINVAL;
-
- /*
- * Initialize dev->board_name. Note that we can use the "thisboard"
- * macro now, since we just initialized it in the last line.
- */
- dev->board_name = devpriv->name;
-
- /*
- * Allocate the subdevice structures. alloc_subdevice() is a
- * convenient macro defined in comedidev.h.
- */
- if (alloc_subdevices(dev, 1) < 0)
- return -ENOMEM;
-
- s = dev->subdevices + 0;
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = devpriv->nchans;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = bonding_dio_insn_bits;
- s->insn_config = bonding_dio_insn_config;
-
- LOG_MSG("attached with %u DIO channels coming from %u different "
- "subdevices all bonded together. "
- "John Lennon would be proud!\n",
- devpriv->nchans, devpriv->ndevs);
-
- return 1;
-}
-
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int bonding_detach(struct comedi_device *dev)
-{
- LOG_MSG("comedi%d: remove\n", dev->minor);
- doDevUnconfig(dev);
- return 0;
-}
-
/* DIO devices are slightly special. Although it is possible to
* implement the insn_read/insn_write interface, it is much more
* useful to applications if you implement the insn_bits interface.
@@ -466,7 +332,57 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
return 1;
}
-static void doDevUnconfig(struct comedi_device *dev)
+static int bonding_attach(struct comedi_device *dev,
+ struct comedi_devconfig *it)
+{
+ struct comedi_subdevice *s;
+
+ LOG_MSG("comedi%d\n", dev->minor);
+
+ /*
+ * Allocate the private structure area. alloc_private() is a
+ * convenient macro defined in comedidev.h.
+ */
+ if (alloc_private(dev, sizeof(struct Private)) < 0)
+ return -ENOMEM;
+
+ /*
+ * Setup our bonding from config params.. sets up our Private struct..
+ */
+ if (!doDevConfig(dev, it))
+ return -EINVAL;
+
+ /*
+ * Initialize dev->board_name. Note that we can use the "thisboard"
+ * macro now, since we just initialized it in the last line.
+ */
+ dev->board_name = devpriv->name;
+
+ /*
+ * Allocate the subdevice structures. alloc_subdevice() is a
+ * convenient macro defined in comedidev.h.
+ */
+ if (alloc_subdevices(dev, 1) < 0)
+ return -ENOMEM;
+
+ s = dev->subdevices + 0;
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = devpriv->nchans;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = bonding_dio_insn_bits;
+ s->insn_config = bonding_dio_insn_config;
+
+ LOG_MSG("attached with %u DIO channels coming from %u different "
+ "subdevices all bonded together. "
+ "John Lennon would be proud!\n",
+ devpriv->nchans, devpriv->ndevs);
+
+ return 1;
+}
+
+static void bonding_detach(struct comedi_device *dev)
{
unsigned long devs_closed = 0;
@@ -490,15 +406,25 @@ static void doDevUnconfig(struct comedi_device *dev)
}
}
-static int __init init(void)
-{
- return comedi_driver_register(&driver_bonding);
-}
+static const struct BondingBoard bondingBoards[] = {
+ {
+ .name = "comedi_bond",
+ },
+};
-static void __exit cleanup(void)
-{
- comedi_driver_unregister(&driver_bonding);
-}
+static struct comedi_driver bonding_driver = {
+ .driver_name = "comedi_bond",
+ .module = THIS_MODULE,
+ .attach = bonding_attach,
+ .detach = bonding_detach,
+ .board_name = &bondingBoards[0].name,
+ .offset = sizeof(struct BondingBoard),
+ .num_names = ARRAY_SIZE(bondingBoards),
+};
+module_comedi_driver(bonding_driver);
-module_init(init);
-module_exit(cleanup);
+MODULE_AUTHOR("Calin A. Culianu");
+MODULE_DESCRIPTION(MODULE_NAME "A driver for COMEDI to bond multiple COMEDI "
+ "devices together as one. In the words of John Lennon: "
+ "'And the world will live as one...'");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
index 21d834dd92b6..bff5dcd76107 100644
--- a/drivers/staging/comedi/drivers/comedi_parport.c
+++ b/drivers/staging/comedi/drivers/comedi_parport.c
@@ -91,29 +91,6 @@ pin, which can be used to wake up tasks.
#define PARPORT_B 1
#define PARPORT_C 2
-static int parport_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int parport_detach(struct comedi_device *dev);
-static struct comedi_driver driver_parport = {
- .driver_name = "comedi_parport",
- .module = THIS_MODULE,
- .attach = parport_attach,
- .detach = parport_detach,
-};
-
-static int __init driver_parport_init_module(void)
-{
- return comedi_driver_register(&driver_parport);
-}
-
-static void __exit driver_parport_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_parport);
-}
-
-module_init(driver_parport_init_module);
-module_exit(driver_parport_cleanup_module);
-
struct parport_private {
unsigned int a_data;
unsigned int c_data;
@@ -395,19 +372,22 @@ static int parport_attach(struct comedi_device *dev,
return 1;
}
-static int parport_detach(struct comedi_device *dev)
+static void parport_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: parport: remove\n", dev->minor);
-
if (dev->iobase)
release_region(dev->iobase, PARPORT_SIZE);
-
if (dev->irq)
free_irq(dev->irq, dev);
-
- return 0;
}
+static struct comedi_driver parport_driver = {
+ .driver_name = "comedi_parport",
+ .module = THIS_MODULE,
+ .attach = parport_attach,
+ .detach = parport_detach,
+};
+module_comedi_driver(parport_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
index a804742b8022..873e37450bba 100644
--- a/drivers/staging/comedi/drivers/comedi_test.c
+++ b/drivers/staging/comedi/drivers/comedi_test.c
@@ -67,15 +67,6 @@ struct waveform_board {
#define N_CHANS 8
-static const struct waveform_board waveform_boards[] = {
- {
- .name = "comedi_test",
- .ai_chans = N_CHANS,
- .ai_bits = 16,
- .have_dio = 0,
- },
-};
-
#define thisboard ((const struct waveform_board *)dev->board_ptr)
/* Data unique to this driver */
@@ -94,54 +85,6 @@ struct waveform_private {
};
#define devpriv ((struct waveform_private *)dev->private)
-static int waveform_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int waveform_detach(struct comedi_device *dev);
-static struct comedi_driver driver_waveform = {
- .driver_name = "comedi_test",
- .module = THIS_MODULE,
- .attach = waveform_attach,
- .detach = waveform_detach,
- .board_name = &waveform_boards[0].name,
- .offset = sizeof(struct waveform_board),
- .num_names = ARRAY_SIZE(waveform_boards),
-};
-
-static int __init driver_waveform_init_module(void)
-{
- return comedi_driver_register(&driver_waveform);
-}
-
-static void __exit driver_waveform_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_waveform);
-}
-
-module_init(driver_waveform_init_module);
-module_exit(driver_waveform_cleanup_module);
-
-static int waveform_ai_cmdtest(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd);
-static int waveform_ai_cmd(struct comedi_device *dev,
- struct comedi_subdevice *s);
-static int waveform_ai_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s);
-static int waveform_ai_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int waveform_ao_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static short fake_sawtooth(struct comedi_device *dev, unsigned int range,
- unsigned long current_time);
-static short fake_squarewave(struct comedi_device *dev, unsigned int range,
- unsigned long current_time);
-static short fake_flatline(struct comedi_device *dev, unsigned int range,
- unsigned long current_time);
-static short fake_waveform(struct comedi_device *dev, unsigned int channel,
- unsigned int range, unsigned long current_time);
-
/* 1000 nanosec in a microsec */
static const int nano_per_micro = 1000;
@@ -154,6 +97,78 @@ static const struct comedi_lrange waveform_ai_ranges = {
}
};
+static short fake_sawtooth(struct comedi_device *dev, unsigned int range_index,
+ unsigned long current_time)
+{
+ struct comedi_subdevice *s = dev->read_subdev;
+ unsigned int offset = s->maxdata / 2;
+ u64 value;
+ const struct comedi_krange *krange =
+ &s->range_table->range[range_index];
+ u64 binary_amplitude;
+
+ binary_amplitude = s->maxdata;
+ binary_amplitude *= devpriv->uvolt_amplitude;
+ do_div(binary_amplitude, krange->max - krange->min);
+
+ current_time %= devpriv->usec_period;
+ value = current_time;
+ value *= binary_amplitude * 2;
+ do_div(value, devpriv->usec_period);
+ value -= binary_amplitude; /* get rid of sawtooth's dc offset */
+
+ return offset + value;
+}
+
+static short fake_squarewave(struct comedi_device *dev,
+ unsigned int range_index,
+ unsigned long current_time)
+{
+ struct comedi_subdevice *s = dev->read_subdev;
+ unsigned int offset = s->maxdata / 2;
+ u64 value;
+ const struct comedi_krange *krange =
+ &s->range_table->range[range_index];
+ current_time %= devpriv->usec_period;
+
+ value = s->maxdata;
+ value *= devpriv->uvolt_amplitude;
+ do_div(value, krange->max - krange->min);
+
+ if (current_time < devpriv->usec_period / 2)
+ value *= -1;
+
+ return offset + value;
+}
+
+static short fake_flatline(struct comedi_device *dev, unsigned int range_index,
+ unsigned long current_time)
+{
+ return dev->read_subdev->maxdata / 2;
+}
+
+/* generates a different waveform depending on what channel is read */
+static short fake_waveform(struct comedi_device *dev, unsigned int channel,
+ unsigned int range, unsigned long current_time)
+{
+ enum {
+ SAWTOOTH_CHAN,
+ SQUARE_CHAN,
+ };
+ switch (channel) {
+ case SAWTOOTH_CHAN:
+ return fake_sawtooth(dev, range, current_time);
+ break;
+ case SQUARE_CHAN:
+ return fake_squarewave(dev, range, current_time);
+ break;
+ default:
+ break;
+ }
+
+ return fake_flatline(dev, range, current_time);
+}
+
/*
This is the background routine used to generate arbitrary data.
It should run in the background; therefore it is scheduled by
@@ -217,84 +232,6 @@ static void waveform_ai_interrupt(unsigned long arg)
comedi_event(dev, dev->read_subdev);
}
-static int waveform_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- int amplitude = it->options[0];
- int period = it->options[1];
- int i;
-
- dev->board_name = thisboard->name;
-
- if (alloc_private(dev, sizeof(struct waveform_private)) < 0)
- return -ENOMEM;
-
- /* set default amplitude and period */
- if (amplitude <= 0)
- amplitude = 1000000; /* 1 volt */
- if (period <= 0)
- period = 100000; /* 0.1 sec */
-
- devpriv->uvolt_amplitude = amplitude;
- devpriv->usec_period = period;
-
- dev->n_subdevices = 2;
- if (alloc_subdevices(dev, dev->n_subdevices) < 0)
- return -ENOMEM;
-
- s = dev->subdevices + 0;
- dev->read_subdev = s;
- /* analog input subdevice */
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
- s->n_chan = thisboard->ai_chans;
- s->maxdata = (1 << thisboard->ai_bits) - 1;
- s->range_table = &waveform_ai_ranges;
- s->len_chanlist = s->n_chan * 2;
- s->insn_read = waveform_ai_insn_read;
- s->do_cmd = waveform_ai_cmd;
- s->do_cmdtest = waveform_ai_cmdtest;
- s->cancel = waveform_ai_cancel;
-
- s = dev->subdevices + 1;
- dev->write_subdev = s;
- /* analog output subdevice (loopback) */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
- s->n_chan = thisboard->ai_chans;
- s->maxdata = (1 << thisboard->ai_bits) - 1;
- s->range_table = &waveform_ai_ranges;
- s->len_chanlist = s->n_chan * 2;
- s->insn_write = waveform_ao_insn_write;
- s->do_cmd = NULL;
- s->do_cmdtest = NULL;
- s->cancel = NULL;
-
- /* Our default loopback value is just a 0V flatline */
- for (i = 0; i < s->n_chan; i++)
- devpriv->ao_loopbacks[i] = s->maxdata / 2;
-
- init_timer(&(devpriv->timer));
- devpriv->timer.function = waveform_ai_interrupt;
- devpriv->timer.data = (unsigned long)dev;
-
- printk(KERN_INFO "comedi%d: comedi_test: "
- "%i microvolt, %li microsecond waveform attached\n", dev->minor,
- devpriv->uvolt_amplitude, devpriv->usec_period);
- return 1;
-}
-
-static int waveform_detach(struct comedi_device *dev)
-{
- printk("comedi%d: comedi_test: remove\n", dev->minor);
-
- if (dev->private)
- waveform_ai_cancel(dev, dev->read_subdev);
-
- return 0;
-}
-
static int waveform_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
@@ -465,78 +402,6 @@ static int waveform_ai_cancel(struct comedi_device *dev,
return 0;
}
-static short fake_sawtooth(struct comedi_device *dev, unsigned int range_index,
- unsigned long current_time)
-{
- struct comedi_subdevice *s = dev->read_subdev;
- unsigned int offset = s->maxdata / 2;
- u64 value;
- const struct comedi_krange *krange =
- &s->range_table->range[range_index];
- u64 binary_amplitude;
-
- binary_amplitude = s->maxdata;
- binary_amplitude *= devpriv->uvolt_amplitude;
- do_div(binary_amplitude, krange->max - krange->min);
-
- current_time %= devpriv->usec_period;
- value = current_time;
- value *= binary_amplitude * 2;
- do_div(value, devpriv->usec_period);
- value -= binary_amplitude; /* get rid of sawtooth's dc offset */
-
- return offset + value;
-}
-
-static short fake_squarewave(struct comedi_device *dev,
- unsigned int range_index,
- unsigned long current_time)
-{
- struct comedi_subdevice *s = dev->read_subdev;
- unsigned int offset = s->maxdata / 2;
- u64 value;
- const struct comedi_krange *krange =
- &s->range_table->range[range_index];
- current_time %= devpriv->usec_period;
-
- value = s->maxdata;
- value *= devpriv->uvolt_amplitude;
- do_div(value, krange->max - krange->min);
-
- if (current_time < devpriv->usec_period / 2)
- value *= -1;
-
- return offset + value;
-}
-
-static short fake_flatline(struct comedi_device *dev, unsigned int range_index,
- unsigned long current_time)
-{
- return dev->read_subdev->maxdata / 2;
-}
-
-/* generates a different waveform depending on what channel is read */
-static short fake_waveform(struct comedi_device *dev, unsigned int channel,
- unsigned int range, unsigned long current_time)
-{
- enum {
- SAWTOOTH_CHAN,
- SQUARE_CHAN,
- };
- switch (channel) {
- case SAWTOOTH_CHAN:
- return fake_sawtooth(dev, range, current_time);
- break;
- case SQUARE_CHAN:
- return fake_squarewave(dev, range, current_time);
- break;
- default:
- break;
- }
-
- return fake_flatline(dev, range, current_time);
-}
-
static int waveform_ai_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -561,6 +426,100 @@ static int waveform_ao_insn_write(struct comedi_device *dev,
return insn->n;
}
+static int waveform_attach(struct comedi_device *dev,
+ struct comedi_devconfig *it)
+{
+ struct comedi_subdevice *s;
+ int amplitude = it->options[0];
+ int period = it->options[1];
+ int i;
+
+ dev->board_name = thisboard->name;
+
+ if (alloc_private(dev, sizeof(struct waveform_private)) < 0)
+ return -ENOMEM;
+
+ /* set default amplitude and period */
+ if (amplitude <= 0)
+ amplitude = 1000000; /* 1 volt */
+ if (period <= 0)
+ period = 100000; /* 0.1 sec */
+
+ devpriv->uvolt_amplitude = amplitude;
+ devpriv->usec_period = period;
+
+ dev->n_subdevices = 2;
+ if (alloc_subdevices(dev, dev->n_subdevices) < 0)
+ return -ENOMEM;
+
+ s = dev->subdevices + 0;
+ dev->read_subdev = s;
+ /* analog input subdevice */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
+ s->n_chan = thisboard->ai_chans;
+ s->maxdata = (1 << thisboard->ai_bits) - 1;
+ s->range_table = &waveform_ai_ranges;
+ s->len_chanlist = s->n_chan * 2;
+ s->insn_read = waveform_ai_insn_read;
+ s->do_cmd = waveform_ai_cmd;
+ s->do_cmdtest = waveform_ai_cmdtest;
+ s->cancel = waveform_ai_cancel;
+
+ s = dev->subdevices + 1;
+ dev->write_subdev = s;
+ /* analog output subdevice (loopback) */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
+ s->n_chan = thisboard->ai_chans;
+ s->maxdata = (1 << thisboard->ai_bits) - 1;
+ s->range_table = &waveform_ai_ranges;
+ s->len_chanlist = s->n_chan * 2;
+ s->insn_write = waveform_ao_insn_write;
+ s->do_cmd = NULL;
+ s->do_cmdtest = NULL;
+ s->cancel = NULL;
+
+ /* Our default loopback value is just a 0V flatline */
+ for (i = 0; i < s->n_chan; i++)
+ devpriv->ao_loopbacks[i] = s->maxdata / 2;
+
+ init_timer(&(devpriv->timer));
+ devpriv->timer.function = waveform_ai_interrupt;
+ devpriv->timer.data = (unsigned long)dev;
+
+ printk(KERN_INFO "comedi%d: comedi_test: "
+ "%i microvolt, %li microsecond waveform attached\n", dev->minor,
+ devpriv->uvolt_amplitude, devpriv->usec_period);
+ return 1;
+}
+
+static void waveform_detach(struct comedi_device *dev)
+{
+ if (dev->private)
+ waveform_ai_cancel(dev, dev->read_subdev);
+}
+
+static const struct waveform_board waveform_boards[] = {
+ {
+ .name = "comedi_test",
+ .ai_chans = N_CHANS,
+ .ai_bits = 16,
+ .have_dio = 0,
+ },
+};
+
+static struct comedi_driver waveform_driver = {
+ .driver_name = "comedi_test",
+ .module = THIS_MODULE,
+ .attach = waveform_attach,
+ .detach = waveform_detach,
+ .board_name = &waveform_boards[0].name,
+ .offset = sizeof(struct waveform_board),
+ .num_names = ARRAY_SIZE(waveform_boards),
+};
+module_comedi_driver(waveform_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index e3659bd6e85e..b8bac80f2baf 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -56,13 +56,6 @@ static const struct contec_board contec_boards[] = {
};
#define PCI_DEVICE_ID_PIO1616L 0x8172
-static DEFINE_PCI_DEVICE_TABLE(contec_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L),
- .driver_data = PIO1616L },
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, contec_pci_table);
#define thisboard ((const struct contec_board *)dev->board_ptr)
@@ -75,30 +68,42 @@ struct contec_private {
#define devpriv ((struct contec_private *)dev->private)
-static int contec_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int contec_detach(struct comedi_device *dev);
-static struct comedi_driver driver_contec = {
- .driver_name = "contec_pci_dio",
- .module = THIS_MODULE,
- .attach = contec_attach,
- .detach = contec_detach,
-};
+static int contec_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+
+ dev_dbg(dev->hw_dev, "contec_do_insn_bits called\n");
+ dev_dbg(dev->hw_dev, "data: %d %d\n", data[0], data[1]);
+
+ if (insn->n != 2)
+ return -EINVAL;
+
+ if (data[0]) {
+ s->state &= ~data[0];
+ s->state |= data[0] & data[1];
+ dev_dbg(dev->hw_dev, "out: %d on %lx\n", s->state,
+ dev->iobase + thisboard->out_offs);
+ outw(s->state, dev->iobase + thisboard->out_offs);
+ }
+ return 2;
+}
-/* Classic digital IO */
static int contec_di_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int contec_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
+ struct comedi_insn *insn, unsigned int *data)
+{
+
+ dev_dbg(dev->hw_dev, "contec_di_insn_bits called\n");
+ dev_dbg(dev->hw_dev, "data: %d %d\n", data[0], data[1]);
-#if 0
-static int contec_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_cmd *cmd);
+ if (insn->n != 2)
+ return -EINVAL;
-static int contec_ns_to_timer(unsigned int *ns, int round);
-#endif
+ data[1] = inw(dev->iobase + thisboard->in_offs);
+
+ return 2;
+}
static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
@@ -164,107 +169,47 @@ static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return -EIO;
}
-static int contec_detach(struct comedi_device *dev)
+static void contec_detach(struct comedi_device *dev)
{
- printk("comedi%d: contec: remove\n", dev->minor);
-
if (devpriv && devpriv->pci_dev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
pci_dev_put(devpriv->pci_dev);
}
-
- return 0;
-}
-
-#if 0
-static int contec_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_cmd *cmd)
-{
- printk("contec_cmdtest called\n");
- return 0;
-}
-
-static int contec_ns_to_timer(unsigned int *ns, int round)
-{
- return *ns;
-}
-#endif
-
-static int contec_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
-
- dev_dbg(dev->hw_dev, "contec_do_insn_bits called\n");
- dev_dbg(dev->hw_dev, "data: %d %d\n", data[0], data[1]);
-
- if (insn->n != 2)
- return -EINVAL;
-
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
- dev_dbg(dev->hw_dev, "out: %d on %lx\n", s->state,
- dev->iobase + thisboard->out_offs);
- outw(s->state, dev->iobase + thisboard->out_offs);
- }
- return 2;
}
-static int contec_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
-
- dev_dbg(dev->hw_dev, "contec_di_insn_bits called\n");
- dev_dbg(dev->hw_dev, "data: %d %d\n", data[0], data[1]);
-
- if (insn->n != 2)
- return -EINVAL;
-
- data[1] = inw(dev->iobase + thisboard->in_offs);
-
- return 2;
-}
+static struct comedi_driver contec_pci_dio_driver = {
+ .driver_name = "contec_pci_dio",
+ .module = THIS_MODULE,
+ .attach = contec_attach,
+ .detach = contec_detach,
+};
-static int __devinit driver_contec_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static int __devinit contec_pci_dio_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_contec.driver_name);
+ return comedi_pci_auto_config(dev, &contec_pci_dio_driver);
}
-static void __devexit driver_contec_pci_remove(struct pci_dev *dev)
+static void __devexit contec_pci_dio_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_contec_pci_driver = {
- .id_table = contec_pci_table,
- .probe = &driver_contec_pci_probe,
- .remove = __devexit_p(&driver_contec_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(contec_pci_dio_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L),
+ .driver_data = PIO1616L },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, contec_pci_dio_pci_table);
-static int __init driver_contec_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_contec);
- if (retval < 0)
- return retval;
-
- driver_contec_pci_driver.name = (char *)driver_contec.driver_name;
- return pci_register_driver(&driver_contec_pci_driver);
-}
-
-static void __exit driver_contec_cleanup_module(void)
-{
- pci_unregister_driver(&driver_contec_pci_driver);
- comedi_driver_unregister(&driver_contec);
-}
-
-module_init(driver_contec_init_module);
-module_exit(driver_contec_cleanup_module);
+static struct pci_driver contec_pci_dio_pci_driver = {
+ .name = "contec_pci_dio",
+ .id_table = contec_pci_dio_pci_table,
+ .probe = contec_pci_dio_pci_probe,
+ .remove = __devexit_p(contec_pci_dio_pci_remove),
+};
+module_comedi_pci_driver(contec_pci_dio_driver, contec_pci_dio_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
index e61c6a8f2857..696b58ca2e59 100644
--- a/drivers/staging/comedi/drivers/daqboard2000.c
+++ b/drivers/staging/comedi/drivers/daqboard2000.c
@@ -301,17 +301,6 @@ struct daqboard2000_hw {
#define DAQBOARD2000_PosRefDacSelect 0x0100
#define DAQBOARD2000_NegRefDacSelect 0x0000
-static int daqboard2000_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int daqboard2000_detach(struct comedi_device *dev);
-
-static struct comedi_driver driver_daqboard2000 = {
- .driver_name = "daqboard2000",
- .module = THIS_MODULE,
- .attach = daqboard2000_attach,
- .detach = daqboard2000_detach,
-};
-
struct daq200_boardtype {
const char *name;
int id;
@@ -321,16 +310,8 @@ static const struct daq200_boardtype boardtypes[] = {
{"ids4", DAQBOARD2000_SUBSYSTEM_IDS4},
};
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct daq200_boardtype))
#define this_board ((const struct daq200_boardtype *)dev->board_ptr)
-static DEFINE_PCI_DEVICE_TABLE(daqboard2000_pci_table) = {
- { PCI_DEVICE(0x1616, 0x0409) },
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, daqboard2000_pci_table);
-
struct daqboard2000_private {
enum {
card_daqboard_2000
@@ -412,9 +393,12 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev,
DAQBOARD2000_AcqResetScanListFifo |
DAQBOARD2000_AcqResetResultsFifo | DAQBOARD2000_AcqResetConfigPipe;
- /* If pacer clock is not set to some high value (> 10 us), we
- risk multiple samples to be put into the result FIFO. */
- fpga->acqPacerClockDivLow = 1000000; /* 1 second, should be long enough */
+ /*
+ * If pacer clock is not set to some high value (> 10 us), we
+ * risk multiple samples to be put into the result FIFO.
+ */
+ /* 1 second, should be long enough */
+ fpga->acqPacerClockDivLow = 1000000;
fpga->acqPacerClockDivHigh = 0;
gain = CR_RANGE(insn->chanspec);
@@ -761,7 +745,7 @@ static int daqboard2000_attach(struct comedi_device *dev,
devpriv->pci_dev = card;
id = ((u32) card->
subsystem_device << 16) | card->subsystem_vendor;
- for (i = 0; i < n_boardtypes; i++) {
+ for (i = 0; i < ARRAY_SIZE(boardtypes); i++) {
if (boardtypes[i].id == id) {
dev_dbg(dev->hw_dev, "%s\n",
boardtypes[i].name);
@@ -852,14 +836,12 @@ out:
return result;
}
-static int daqboard2000_detach(struct comedi_device *dev)
+static void daqboard2000_detach(struct comedi_device *dev)
{
if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 2);
-
if (dev->irq)
free_irq(dev->irq, dev);
-
if (devpriv) {
if (devpriv->daq)
iounmap(devpriv->daq);
@@ -871,48 +853,39 @@ static int daqboard2000_detach(struct comedi_device *dev)
pci_dev_put(devpriv->pci_dev);
}
}
- return 0;
}
-static int __devinit driver_daqboard2000_pci_probe(struct pci_dev *dev,
- const struct pci_device_id
- *ent)
+static struct comedi_driver daqboard2000_driver = {
+ .driver_name = "daqboard2000",
+ .module = THIS_MODULE,
+ .attach = daqboard2000_attach,
+ .detach = daqboard2000_detach,
+};
+
+static int __devinit daqboard2000_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_daqboard2000.driver_name);
+ return comedi_pci_auto_config(dev, &daqboard2000_driver);
}
-static void __devexit driver_daqboard2000_pci_remove(struct pci_dev *dev)
+static void __devexit daqboard2000_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_daqboard2000_pci_driver = {
- .id_table = daqboard2000_pci_table,
- .probe = &driver_daqboard2000_pci_probe,
- .remove = __devexit_p(&driver_daqboard2000_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(daqboard2000_pci_table) = {
+ { PCI_DEVICE(0x1616, 0x0409) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, daqboard2000_pci_table);
-static int __init driver_daqboard2000_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_daqboard2000);
- if (retval < 0)
- return retval;
-
- driver_daqboard2000_pci_driver.name =
- (char *)driver_daqboard2000.driver_name;
- return pci_register_driver(&driver_daqboard2000_pci_driver);
-}
-
-static void __exit driver_daqboard2000_cleanup_module(void)
-{
- pci_unregister_driver(&driver_daqboard2000_pci_driver);
- comedi_driver_unregister(&driver_daqboard2000);
-}
-
-module_init(driver_daqboard2000_init_module);
-module_exit(driver_daqboard2000_cleanup_module);
+static struct pci_driver daqboard2000_pci_driver = {
+ .name = "daqboard2000",
+ .id_table = daqboard2000_pci_table,
+ .probe = daqboard2000_pci_probe,
+ .remove = __devexit_p(daqboard2000_pci_remove),
+};
+module_comedi_pci_driver(daqboard2000_driver, daqboard2000_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
index c2dd0ed36a73..1f319435e23f 100644
--- a/drivers/staging/comedi/drivers/das08.c
+++ b/drivers/staging/comedi/drivers/das08.c
@@ -61,6 +61,20 @@
#define DRV_NAME "das08"
+#ifdef CONFIG_COMEDI_DAS08_ISA_MODULE
+#define CONFIG_COMEDI_DAS08_ISA
+#endif
+#ifdef CONFIG_COMEDI_DAS08_PCI_MODULE
+#define CONFIG_COMEDI_DAS08_PCI
+#endif
+#ifdef CONFIG_COMEDI_DAS08_CS_MODULE
+#define CONFIG_COMEDI_DAS08_CS
+#endif
+
+#if defined(CONFIG_COMEDI_DAS08_ISA) || defined(CONFIG_COMEDI_DAS08_PCI)
+#define DO_COMEDI_DRIVER_REGISTER
+#endif
+
#define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307
#define PCI_DEVICE_ID_PCIDAS08 0x29
#define PCIDAS08_SIZE 0x54
@@ -160,6 +174,7 @@ static int das08_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
+#ifdef CONFIG_COMEDI_DAS08_ISA
static int das08jr_di_rbits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
@@ -172,6 +187,7 @@ static int das08jr_ao_winsn(struct comedi_device *dev,
static int das08ao_ao_winsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
+#endif
static void i8254_set_mode_low(unsigned int base, int channel,
unsigned int mode);
@@ -253,7 +269,9 @@ static const int *const das08_gainlists[] = {
das08_pgm_gainlist,
};
+#ifdef DO_COMEDI_DRIVER_REGISTER
static const struct das08_board_struct das08_boards[] = {
+#ifdef CONFIG_COMEDI_DAS08_ISA
{
.name = "isa-das08", /* cio-das08.pdf */
.bustype = isa,
@@ -395,25 +413,6 @@ static const struct das08_board_struct das08_boards[] = {
.i8254_offset = 0x04,
.iosize = 16, /* unchecked */
},
-#ifdef CONFIG_COMEDI_PCI
- {
- .name = "das08", /* pci-das08 */
- .id = PCI_DEVICE_ID_PCIDAS08,
- .bustype = pci,
- .ai = das08_ai_rinsn,
- .ai_nbits = 12,
- .ai_pg = das08_bipolar5,
- .ai_encoding = das08_encode12,
- .ao = NULL,
- .ao_nbits = 0,
- .di = das08_di_rbits,
- .do_ = das08_do_wbits,
- .do_nchan = 4,
- .i8255_offset = 0,
- .i8254_offset = 4,
- .iosize = 8,
- },
-#endif
{
.name = "pc104-das08",
.bustype = pc104,
@@ -462,9 +461,30 @@ static const struct das08_board_struct das08_boards[] = {
.name = "das08-pga-g2", /* a KM board */
},
#endif
+#endif /* CONFIG_COMEDI_DAS08_ISA */
+#ifdef CONFIG_COMEDI_DAS08_PCI
+ {
+ .name = "das08", /* pci-das08 */
+ .id = PCI_DEVICE_ID_PCIDAS08,
+ .bustype = pci,
+ .ai = das08_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_pg = das08_bipolar5,
+ .ai_encoding = das08_encode12,
+ .ao = NULL,
+ .ao_nbits = 0,
+ .di = das08_di_rbits,
+ .do_ = das08_do_wbits,
+ .do_nchan = 4,
+ .i8255_offset = 0,
+ .i8254_offset = 4,
+ .iosize = 8,
+ },
+#endif /* CONFIG_COMEDI_DAS08_PCI */
};
+#endif /* DO_COMEDI_DRIVER_REGISTER */
-#ifdef CONFIG_COMEDI_PCMCIA
+#ifdef CONFIG_COMEDI_DAS08_CS
struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS] = {
{
.name = "pcm-das08",
@@ -504,7 +524,7 @@ struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS] = {
};
#endif
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_DAS08_PCI
static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, PCI_DEVICE_ID_PCIDAS08) },
{0}
@@ -619,6 +639,7 @@ static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
return 2;
}
+#ifdef CONFIG_COMEDI_DAS08_ISA
static int das08jr_di_rbits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -628,7 +649,9 @@ static int das08jr_di_rbits(struct comedi_device *dev,
return 2;
}
+#endif
+#ifdef CONFIG_COMEDI_DAS08_ISA
static int das08jr_do_wbits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -643,7 +666,9 @@ static int das08jr_do_wbits(struct comedi_device *dev,
return 2;
}
+#endif
+#ifdef CONFIG_COMEDI_DAS08_ISA
static int das08jr_ao_winsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -672,6 +697,7 @@ static int das08jr_ao_winsn(struct comedi_device *dev,
return n;
}
+#endif
/*
*
@@ -679,6 +705,7 @@ static int das08jr_ao_winsn(struct comedi_device *dev,
* a different method to force an update.
*
*/
+#ifdef CONFIG_COMEDI_DAS08_ISA
static int das08ao_ao_winsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -707,6 +734,7 @@ static int das08ao_ao_winsn(struct comedi_device *dev,
return n;
}
+#endif
static unsigned int i8254_read_channel_low(unsigned int base, int chan)
{
@@ -842,6 +870,7 @@ static int das08_counter_config(struct comedi_device *dev,
return 2;
}
+#ifdef DO_COMEDI_DRIVER_REGISTER
static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it);
static struct comedi_driver driver_das08 = {
@@ -853,6 +882,7 @@ static struct comedi_driver driver_das08 = {
.num_names = sizeof(das08_boards) / sizeof(struct das08_board_struct),
.offset = sizeof(struct das08_board_struct),
};
+#endif
int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
{
@@ -972,11 +1002,12 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
}
EXPORT_SYMBOL_GPL(das08_common_attach);
+#ifdef DO_COMEDI_DRIVER_REGISTER
static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
int ret;
unsigned long iobase;
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_DAS08_PCI
unsigned long pci_iobase = 0;
struct pci_dev *pdev = NULL;
#endif
@@ -986,9 +1017,9 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
printk(KERN_INFO "comedi%d: das08: ", dev->minor);
+#ifdef CONFIG_COMEDI_DAS08_PCI
/* deal with a pci board */
if (thisboard->bustype == pci) {
-#ifdef CONFIG_COMEDI_PCI
if (it->options[0] || it->options[1]) {
printk("bus %i slot %i ",
it->options[0], it->options[1]);
@@ -1037,32 +1068,26 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* Enable local interrupt 1 and pci interrupt */
outw(INTR1_ENABLE | PCI_INTR_ENABLE, pci_iobase + INTCSR);
#endif
-#else /* CONFIG_COMEDI_PCI */
- printk(KERN_ERR "this driver has not been built with PCI support.\n");
- return -EINVAL;
-#endif /* CONFIG_COMEDI_PCI */
- } else {
+ } else
+#endif /* CONFIG_COMEDI_DAS08_PCI */
+ {
iobase = it->options[0];
}
printk(KERN_INFO "\n");
return das08_common_attach(dev, iobase);
}
+#endif /* DO_COMEDI_DRIVER_REGISTER */
-
-int das08_common_detach(struct comedi_device *dev)
+void das08_common_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: das08: remove\n", dev->minor);
-
if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 4);
-
- /* deallocate ioports for non-pcmcia, non-pci boards */
if ((thisboard->bustype != pcmcia) && (thisboard->bustype != pci)) {
if (dev->iobase)
release_region(dev->iobase, thisboard->iosize);
}
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_DAS08_PCI
if (devpriv) {
if (devpriv->pdev) {
if (devpriv->pci_iobase)
@@ -1072,16 +1097,14 @@ int das08_common_detach(struct comedi_device *dev)
}
}
#endif
-
- return 0;
}
EXPORT_SYMBOL_GPL(das08_common_detach);
-#ifdef CONFIG_COMEDI_PCI
+#ifdef CONFIG_COMEDI_DAS08_PCI
static int __devinit driver_das08_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_das08.driver_name);
+ return comedi_pci_auto_config(dev, &driver_das08);
}
static void __devexit driver_das08_pci_remove(struct pci_dev *dev)
@@ -1094,43 +1117,38 @@ static struct pci_driver driver_das08_pci_driver = {
.probe = &driver_das08_pci_probe,
.remove = __devexit_p(&driver_das08_pci_remove)
};
+#endif /* CONFIG_COMEDI_DAS08_PCI */
static int __init driver_das08_init_module(void)
{
- int retval;
+ int retval = 0;
+#ifdef DO_COMEDI_DRIVER_REGISTER
retval = comedi_driver_register(&driver_das08);
if (retval < 0)
return retval;
-
+#endif
+#ifdef CONFIG_COMEDI_DAS08_PCI
driver_das08_pci_driver.name = (char *)driver_das08.driver_name;
- return pci_register_driver(&driver_das08_pci_driver);
+ retval = pci_register_driver(&driver_das08_pci_driver);
+#endif
+ return retval;
}
static void __exit driver_das08_cleanup_module(void)
{
+#ifdef CONFIG_COMEDI_DAS08_PCI
pci_unregister_driver(&driver_das08_pci_driver);
+#endif
+#ifdef DO_COMEDI_DRIVER_REGISTER
comedi_driver_unregister(&driver_das08);
+#endif
}
module_init(driver_das08_init_module);
module_exit(driver_das08_cleanup_module);
-#else
-static int __init driver_das08_init_module(void)
-{
- return comedi_driver_register(&driver_das08);
-}
-
-static void __exit driver_das08_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_das08);
-}
-
-module_init(driver_das08_init_module);
-module_exit(driver_das08_cleanup_module);
-#endif
-#ifdef CONFIG_COMEDI_PCMCIA
+#ifdef CONFIG_COMEDI_DAS08_CS
EXPORT_SYMBOL_GPL(das08_cs_boards);
#endif
diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h
index 2a30d764ddfc..0b92f24b261f 100644
--- a/drivers/staging/comedi/drivers/das08.h
+++ b/drivers/staging/comedi/drivers/das08.h
@@ -74,6 +74,6 @@ struct das08_private_struct {
extern struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS];
int das08_common_attach(struct comedi_device *dev, unsigned long iobase);
-int das08_common_detach(struct comedi_device *dev);
+void das08_common_detach(struct comedi_device *dev);
#endif /* _DAS08_H */
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index e7905bac92da..998444c1ba32 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -339,38 +339,6 @@ struct munge_info {
unsigned have_byte:1;
};
-static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_cmd *cmd);
-static int das16_cmd_exec(struct comedi_device *dev,
- struct comedi_subdevice *s);
-static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
-static void das16_ai_munge(struct comedi_device *dev,
- struct comedi_subdevice *s, void *array,
- unsigned int num_bytes,
- unsigned int start_chan_index);
-
-static void das16_reset(struct comedi_device *dev);
-static irqreturn_t das16_dma_interrupt(int irq, void *d);
-static void das16_timer_interrupt(unsigned long arg);
-static void das16_interrupt(struct comedi_device *dev);
-
-static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
- int flags);
-static int das1600_mode_detect(struct comedi_device *dev);
-static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
- struct comedi_cmd cmd);
-
-static void reg_dump(struct comedi_device *dev);
-
struct das16_board {
const char *name;
void *ai;
@@ -389,344 +357,6 @@ struct das16_board {
unsigned int id;
};
-static const struct das16_board das16_boards[] = {
- {
- .name = "das-16",
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 15000,
- .ai_pg = das16_pg_none,
- .ao = das16_ao_winsn,
- .ao_nbits = 12,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x10,
- .i8254_offset = 0x0c,
- .size = 0x14,
- .id = 0x00,
- },
- {
- .name = "das-16g",
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 15000,
- .ai_pg = das16_pg_none,
- .ao = das16_ao_winsn,
- .ao_nbits = 12,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x10,
- .i8254_offset = 0x0c,
- .size = 0x14,
- .id = 0x00,
- },
- {
- .name = "das-16f",
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 8500,
- .ai_pg = das16_pg_none,
- .ao = das16_ao_winsn,
- .ao_nbits = 12,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x10,
- .i8254_offset = 0x0c,
- .size = 0x14,
- .id = 0x00,
- },
- {
- .name = "cio-das16", /* cio-das16.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 20000,
- .ai_pg = das16_pg_none,
- .ao = das16_ao_winsn,
- .ao_nbits = 12,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x10,
- .i8254_offset = 0x0c,
- .size = 0x14,
- .id = 0x80,
- },
- {
- .name = "cio-das16/f", /* das16.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 10000,
- .ai_pg = das16_pg_none,
- .ao = das16_ao_winsn,
- .ao_nbits = 12,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x10,
- .i8254_offset = 0x0c,
- .size = 0x14,
- .id = 0x80,
- },
- {
- .name = "cio-das16/jr", /* cio-das16jr.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 7692,
- .ai_pg = das16_pg_16jr,
- .ao = NULL,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0,
- .i8254_offset = 0x0c,
- .size = 0x10,
- .id = 0x00,
- },
- {
- .name = "pc104-das16jr", /* pc104-das16jr_xx.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 3300,
- .ai_pg = das16_pg_16jr,
- .ao = NULL,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0,
- .i8254_offset = 0x0c,
- .size = 0x10,
- .id = 0x00,
- },
- {
- .name = "cio-das16jr/16", /* cio-das16jr_16.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 16,
- .ai_speed = 10000,
- .ai_pg = das16_pg_16jr_16,
- .ao = NULL,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0,
- .i8254_offset = 0x0c,
- .size = 0x10,
- .id = 0x00,
- },
- {
- .name = "pc104-das16jr/16", /* pc104-das16jr_xx.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 16,
- .ai_speed = 10000,
- .ai_pg = das16_pg_16jr_16,
- .ao = NULL,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0,
- .i8254_offset = 0x0c,
- .size = 0x10,
- .id = 0x00,
- },
- {
- .name = "das-1201", /* 4924.pdf (keithley user's manual) */
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 20000,
- .ai_pg = das16_pg_none,
- .ao = NULL,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x400,
- .i8254_offset = 0x0c,
- .size = 0x408,
- .id = 0x20,
- },
- {
- .name = "das-1202", /* 4924.pdf (keithley user's manual) */
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 10000,
- .ai_pg = das16_pg_none,
- .ao = NULL,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x400,
- .i8254_offset = 0x0c,
- .size = 0x408,
- .id = 0x20,
- },
- {
- /* 4919.pdf and 4922.pdf (keithley user's manual) */
- .name = "das-1401",
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 10000,
- .ai_pg = das16_pg_1601,
- .ao = NULL,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x0,
- .i8254_offset = 0x0c,
- .size = 0x408,
- .id = 0xc0 /* 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
- },
- {
- /* 4919.pdf and 4922.pdf (keithley user's manual) */
- .name = "das-1402",
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 10000,
- .ai_pg = das16_pg_1602,
- .ao = NULL,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x0,
- .i8254_offset = 0x0c,
- .size = 0x408,
- .id = 0xc0 /* 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
- },
- {
- .name = "das-1601", /* 4919.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 10000,
- .ai_pg = das16_pg_1601,
- .ao = das16_ao_winsn,
- .ao_nbits = 12,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x400,
- .i8254_offset = 0x0c,
- .size = 0x408,
- .id = 0xc0},
- {
- .name = "das-1602", /* 4919.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 10000,
- .ai_pg = das16_pg_1602,
- .ao = das16_ao_winsn,
- .ao_nbits = 12,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x400,
- .i8254_offset = 0x0c,
- .size = 0x408,
- .id = 0xc0},
- {
- .name = "cio-das1401/12", /* cio-das1400_series.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 6250,
- .ai_pg = das16_pg_1601,
- .ao = NULL,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0,
- .i8254_offset = 0x0c,
- .size = 0x408,
- .id = 0xc0},
- {
- .name = "cio-das1402/12", /* cio-das1400_series.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 6250,
- .ai_pg = das16_pg_1602,
- .ao = NULL,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0,
- .i8254_offset = 0x0c,
- .size = 0x408,
- .id = 0xc0},
- {
- .name = "cio-das1402/16", /* cio-das1400_series.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 16,
- .ai_speed = 10000,
- .ai_pg = das16_pg_1602,
- .ao = NULL,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0,
- .i8254_offset = 0x0c,
- .size = 0x408,
- .id = 0xc0},
- {
- .name = "cio-das1601/12", /* cio-das160x-1x.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 6250,
- .ai_pg = das16_pg_1601,
- .ao = das16_ao_winsn,
- .ao_nbits = 12,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x400,
- .i8254_offset = 0x0c,
- .size = 0x408,
- .id = 0xc0},
- {
- .name = "cio-das1602/12", /* cio-das160x-1x.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 10000,
- .ai_pg = das16_pg_1602,
- .ao = das16_ao_winsn,
- .ao_nbits = 12,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x400,
- .i8254_offset = 0x0c,
- .size = 0x408,
- .id = 0xc0},
- {
- .name = "cio-das1602/16", /* cio-das160x-1x.pdf */
- .ai = das16_ai_rinsn,
- .ai_nbits = 16,
- .ai_speed = 10000,
- .ai_pg = das16_pg_1602,
- .ao = das16_ao_winsn,
- .ao_nbits = 12,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0x400,
- .i8254_offset = 0x0c,
- .size = 0x408,
- .id = 0xc0},
- {
- .name = "cio-das16/330", /* ? */
- .ai = das16_ai_rinsn,
- .ai_nbits = 12,
- .ai_speed = 3030,
- .ai_pg = das16_pg_16jr,
- .ao = NULL,
- .di = das16_di_rbits,
- .do_ = das16_do_wbits,
- .i8255_offset = 0,
- .i8254_offset = 0x0c,
- .size = 0x14,
- .id = 0xf0},
-#if 0
- {
- .name = "das16/330i", /* ? */
- },
- {
- .name = "das16/jr/ctr5", /* ? */
- },
- {
- /* cio-das16_m1_16.pdf, this board is a bit quirky, no dma */
- .name = "cio-das16/m1/16",
- },
-#endif
-};
-
-static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int das16_detach(struct comedi_device *dev);
-static struct comedi_driver driver_das16 = {
- .driver_name = "das16",
- .module = THIS_MODULE,
- .attach = das16_attach,
- .detach = das16_detach,
- .board_name = &das16_boards[0].name,
- .num_names = ARRAY_SIZE(das16_boards),
- .offset = sizeof(das16_boards[0]),
-};
-
#define DAS16_TIMEOUT 1000
/* Period for timer interrupt in jiffies. It's a function
@@ -926,6 +556,62 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
return 0;
}
+/* utility function that suggests a dma transfer size in bytes */
+static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
+ struct comedi_cmd cmd)
+{
+ unsigned int size;
+ unsigned int freq;
+
+ /* if we are using timer interrupt, we don't care how long it
+ * will take to complete transfer since it will be interrupted
+ * by timer interrupt */
+ if (devpriv->timer_mode)
+ return DAS16_DMA_SIZE;
+
+ /* otherwise, we are relying on dma terminal count interrupt,
+ * so pick a reasonable size */
+ if (cmd.convert_src == TRIG_TIMER)
+ freq = 1000000000 / cmd.convert_arg;
+ else if (cmd.scan_begin_src == TRIG_TIMER)
+ freq = (1000000000 / cmd.scan_begin_arg) * cmd.chanlist_len;
+ /* return some default value */
+ else
+ freq = 0xffffffff;
+
+ if (cmd.flags & TRIG_WAKE_EOS) {
+ size = sample_size * cmd.chanlist_len;
+ } else {
+ /* make buffer fill in no more than 1/3 second */
+ size = (freq / 3) * sample_size;
+ }
+
+ /* set a minimum and maximum size allowed */
+ if (size > DAS16_DMA_SIZE)
+ size = DAS16_DMA_SIZE - DAS16_DMA_SIZE % sample_size;
+ else if (size < sample_size)
+ size = sample_size;
+
+ if (cmd.stop_src == TRIG_COUNT && size > devpriv->adc_byte_count)
+ size = devpriv->adc_byte_count;
+
+ return size;
+}
+
+static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
+ int rounding_flags)
+{
+ i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
+ &(devpriv->divisor2), &ns,
+ rounding_flags & TRIG_ROUND_MASK);
+
+ /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
+ i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2);
+ i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2);
+
+ return ns;
+}
+
static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
{
struct comedi_async *async = s->async;
@@ -1170,34 +856,6 @@ static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
return i;
}
-static irqreturn_t das16_dma_interrupt(int irq, void *d)
-{
- int status;
- struct comedi_device *dev = d;
-
- status = inb(dev->iobase + DAS16_STATUS);
-
- if ((status & DAS16_INT) == 0) {
- DEBUG_PRINT("spurious interrupt\n");
- return IRQ_NONE;
- }
-
- /* clear interrupt */
- outb(0x00, dev->iobase + DAS16_STATUS);
- das16_interrupt(dev);
- return IRQ_HANDLED;
-}
-
-static void das16_timer_interrupt(unsigned long arg)
-{
- struct comedi_device *dev = (struct comedi_device *)arg;
-
- das16_interrupt(dev);
-
- if (devpriv->timer_running)
- mod_timer(&devpriv->timer, jiffies + timer_period());
-}
-
/* the pc104-das16jr (at least) has problems if the dma
transfer is interrupted in the middle of transferring
a 16 bit sample, so this function takes care to get
@@ -1309,18 +967,32 @@ static void das16_interrupt(struct comedi_device *dev)
cfc_handle_events(dev, s);
}
-static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
- int rounding_flags)
+static irqreturn_t das16_dma_interrupt(int irq, void *d)
{
- i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
- &(devpriv->divisor2), &ns,
- rounding_flags & TRIG_ROUND_MASK);
+ int status;
+ struct comedi_device *dev = d;
- /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
- i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2);
- i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2);
+ status = inb(dev->iobase + DAS16_STATUS);
- return ns;
+ if ((status & DAS16_INT) == 0) {
+ DEBUG_PRINT("spurious interrupt\n");
+ return IRQ_NONE;
+ }
+
+ /* clear interrupt */
+ outb(0x00, dev->iobase + DAS16_STATUS);
+ das16_interrupt(dev);
+ return IRQ_HANDLED;
+}
+
+static void das16_timer_interrupt(unsigned long arg)
+{
+ struct comedi_device *dev = (struct comedi_device *)arg;
+
+ das16_interrupt(dev);
+
+ if (devpriv->timer_running)
+ mod_timer(&devpriv->timer, jiffies + timer_period());
}
static void reg_dump(struct comedi_device *dev)
@@ -1394,6 +1066,22 @@ static int das1600_mode_detect(struct comedi_device *dev)
return 0;
}
+static void das16_ai_munge(struct comedi_device *dev,
+ struct comedi_subdevice *s, void *array,
+ unsigned int num_bytes,
+ unsigned int start_chan_index)
+{
+ unsigned int i, num_samples = num_bytes / sizeof(short);
+ short *data = array;
+
+ for (i = 0; i < num_samples; i++) {
+ data[i] = le16_to_cpu(data[i]);
+ if (thisboard->ai_nbits == 12)
+ data[i] = (data[i] >> 4) & 0xfff;
+
+ }
+}
+
/*
*
* Options list:
@@ -1402,7 +1090,6 @@ static int das1600_mode_detect(struct comedi_device *dev)
* 2 DMA
* 3 Clock speed (in MHz)
*/
-
static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
struct comedi_subdevice *s;
@@ -1675,15 +1362,11 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int das16_detach(struct comedi_device *dev)
+static void das16_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: das16: remove\n", dev->minor);
-
das16_reset(dev);
-
if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 4);
-
if (devpriv) {
int i;
for (i = 0; i < 2; i++) {
@@ -1698,10 +1381,8 @@ static int das16_detach(struct comedi_device *dev)
kfree(devpriv->user_ai_range_table);
kfree(devpriv->user_ao_range_table);
}
-
if (dev->irq)
free_irq(dev->irq, dev);
-
if (dev->iobase) {
if (thisboard->size < 0x400) {
release_region(dev->iobase, thisboard->size);
@@ -1711,80 +1392,318 @@ static int das16_detach(struct comedi_device *dev)
thisboard->size & 0x3ff);
}
}
-
- return 0;
}
-static int __init driver_das16_init_module(void)
-{
- return comedi_driver_register(&driver_das16);
-}
-
-static void __exit driver_das16_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_das16);
-}
-
-module_init(driver_das16_init_module);
-module_exit(driver_das16_cleanup_module);
-
-/* utility function that suggests a dma transfer size in bytes */
-static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
- struct comedi_cmd cmd)
-{
- unsigned int size;
- unsigned int freq;
-
- /* if we are using timer interrupt, we don't care how long it
- * will take to complete transfer since it will be interrupted
- * by timer interrupt */
- if (devpriv->timer_mode)
- return DAS16_DMA_SIZE;
-
- /* otherwise, we are relying on dma terminal count interrupt,
- * so pick a reasonable size */
- if (cmd.convert_src == TRIG_TIMER)
- freq = 1000000000 / cmd.convert_arg;
- else if (cmd.scan_begin_src == TRIG_TIMER)
- freq = (1000000000 / cmd.scan_begin_arg) * cmd.chanlist_len;
- /* return some default value */
- else
- freq = 0xffffffff;
-
- if (cmd.flags & TRIG_WAKE_EOS) {
- size = sample_size * cmd.chanlist_len;
- } else {
- /* make buffer fill in no more than 1/3 second */
- size = (freq / 3) * sample_size;
- }
-
- /* set a minimum and maximum size allowed */
- if (size > DAS16_DMA_SIZE)
- size = DAS16_DMA_SIZE - DAS16_DMA_SIZE % sample_size;
- else if (size < sample_size)
- size = sample_size;
-
- if (cmd.stop_src == TRIG_COUNT && size > devpriv->adc_byte_count)
- size = devpriv->adc_byte_count;
-
- return size;
-}
-
-static void das16_ai_munge(struct comedi_device *dev,
- struct comedi_subdevice *s, void *array,
- unsigned int num_bytes,
- unsigned int start_chan_index)
-{
- unsigned int i, num_samples = num_bytes / sizeof(short);
- short *data = array;
-
- for (i = 0; i < num_samples; i++) {
- data[i] = le16_to_cpu(data[i]);
- if (thisboard->ai_nbits == 12)
- data[i] = (data[i] >> 4) & 0xfff;
+static const struct das16_board das16_boards[] = {
+ {
+ .name = "das-16",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 15000,
+ .ai_pg = das16_pg_none,
+ .ao = das16_ao_winsn,
+ .ao_nbits = 12,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x10,
+ .i8254_offset = 0x0c,
+ .size = 0x14,
+ .id = 0x00,
+ }, {
+ .name = "das-16g",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 15000,
+ .ai_pg = das16_pg_none,
+ .ao = das16_ao_winsn,
+ .ao_nbits = 12,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x10,
+ .i8254_offset = 0x0c,
+ .size = 0x14,
+ .id = 0x00,
+ }, {
+ .name = "das-16f",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 8500,
+ .ai_pg = das16_pg_none,
+ .ao = das16_ao_winsn,
+ .ao_nbits = 12,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x10,
+ .i8254_offset = 0x0c,
+ .size = 0x14,
+ .id = 0x00,
+ }, {
+ .name = "cio-das16",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 20000,
+ .ai_pg = das16_pg_none,
+ .ao = das16_ao_winsn,
+ .ao_nbits = 12,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x10,
+ .i8254_offset = 0x0c,
+ .size = 0x14,
+ .id = 0x80,
+ }, {
+ .name = "cio-das16/f",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 10000,
+ .ai_pg = das16_pg_none,
+ .ao = das16_ao_winsn,
+ .ao_nbits = 12,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x10,
+ .i8254_offset = 0x0c,
+ .size = 0x14,
+ .id = 0x80,
+ }, {
+ .name = "cio-das16/jr",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 7692,
+ .ai_pg = das16_pg_16jr,
+ .ao = NULL,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0,
+ .i8254_offset = 0x0c,
+ .size = 0x10,
+ .id = 0x00,
+ }, {
+ .name = "pc104-das16jr",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 3300,
+ .ai_pg = das16_pg_16jr,
+ .ao = NULL,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0,
+ .i8254_offset = 0x0c,
+ .size = 0x10,
+ .id = 0x00,
+ }, {
+ .name = "cio-das16jr/16",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 16,
+ .ai_speed = 10000,
+ .ai_pg = das16_pg_16jr_16,
+ .ao = NULL,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0,
+ .i8254_offset = 0x0c,
+ .size = 0x10,
+ .id = 0x00,
+ }, {
+ .name = "pc104-das16jr/16",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 16,
+ .ai_speed = 10000,
+ .ai_pg = das16_pg_16jr_16,
+ .ao = NULL,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0,
+ .i8254_offset = 0x0c,
+ .size = 0x10,
+ .id = 0x00,
+ }, {
+ .name = "das-1201",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 20000,
+ .ai_pg = das16_pg_none,
+ .ao = NULL,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x400,
+ .i8254_offset = 0x0c,
+ .size = 0x408,
+ .id = 0x20,
+ }, {
+ .name = "das-1202",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 10000,
+ .ai_pg = das16_pg_none,
+ .ao = NULL,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x400,
+ .i8254_offset = 0x0c,
+ .size = 0x408,
+ .id = 0x20,
+ }, {
+ .name = "das-1401",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 10000,
+ .ai_pg = das16_pg_1601,
+ .ao = NULL,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x0,
+ .i8254_offset = 0x0c,
+ .size = 0x408,
+ .id = 0xc0,
+ }, {
+ .name = "das-1402",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 10000,
+ .ai_pg = das16_pg_1602,
+ .ao = NULL,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x0,
+ .i8254_offset = 0x0c,
+ .size = 0x408,
+ .id = 0xc0,
+ }, {
+ .name = "das-1601",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 10000,
+ .ai_pg = das16_pg_1601,
+ .ao = das16_ao_winsn,
+ .ao_nbits = 12,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x400,
+ .i8254_offset = 0x0c,
+ .size = 0x408,
+ .id = 0xc0,
+ }, {
+ .name = "das-1602",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 10000,
+ .ai_pg = das16_pg_1602,
+ .ao = das16_ao_winsn,
+ .ao_nbits = 12,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x400,
+ .i8254_offset = 0x0c,
+ .size = 0x408,
+ .id = 0xc0,
+ }, {
+ .name = "cio-das1401/12",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 6250,
+ .ai_pg = das16_pg_1601,
+ .ao = NULL,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0,
+ .i8254_offset = 0x0c,
+ .size = 0x408,
+ .id = 0xc0,
+ }, {
+ .name = "cio-das1402/12",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 6250,
+ .ai_pg = das16_pg_1602,
+ .ao = NULL,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0,
+ .i8254_offset = 0x0c,
+ .size = 0x408,
+ .id = 0xc0,
+ }, {
+ .name = "cio-das1402/16",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 16,
+ .ai_speed = 10000,
+ .ai_pg = das16_pg_1602,
+ .ao = NULL,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0,
+ .i8254_offset = 0x0c,
+ .size = 0x408,
+ .id = 0xc0,
+ }, {
+ .name = "cio-das1601/12",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 6250,
+ .ai_pg = das16_pg_1601,
+ .ao = das16_ao_winsn,
+ .ao_nbits = 12,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x400,
+ .i8254_offset = 0x0c,
+ .size = 0x408,
+ .id = 0xc0,
+ }, {
+ .name = "cio-das1602/12",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 10000,
+ .ai_pg = das16_pg_1602,
+ .ao = das16_ao_winsn,
+ .ao_nbits = 12,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x400,
+ .i8254_offset = 0x0c,
+ .size = 0x408,
+ .id = 0xc0,
+ }, {
+ .name = "cio-das1602/16",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 16,
+ .ai_speed = 10000,
+ .ai_pg = das16_pg_1602,
+ .ao = das16_ao_winsn,
+ .ao_nbits = 12,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0x400,
+ .i8254_offset = 0x0c,
+ .size = 0x408,
+ .id = 0xc0,
+ }, {
+ .name = "cio-das16/330",
+ .ai = das16_ai_rinsn,
+ .ai_nbits = 12,
+ .ai_speed = 3030,
+ .ai_pg = das16_pg_16jr,
+ .ao = NULL,
+ .di = das16_di_rbits,
+ .do_ = das16_do_wbits,
+ .i8255_offset = 0,
+ .i8254_offset = 0x0c,
+ .size = 0x14,
+ .id = 0xf0,
+ },
+};
- }
-}
+static struct comedi_driver das16_driver = {
+ .driver_name = "das16",
+ .module = THIS_MODULE,
+ .attach = das16_attach,
+ .detach = das16_detach,
+ .board_name = &das16_boards[0].name,
+ .num_names = ARRAY_SIZE(das16_boards),
+ .offset = sizeof(das16_boards[0]),
+};
+module_comedi_driver(das16_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
index 5376e718e3d7..d2e1490cd808 100644
--- a/drivers/staging/comedi/drivers/das16m1.c
+++ b/drivers/staging/comedi/drivers/das16m1.c
@@ -132,57 +132,11 @@ static const struct comedi_lrange range_das16m1 = { 9,
}
};
-static int das16m1_do_wbits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int das16m1_di_rbits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int das16m1_ai_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static int das16m1_cmd_test(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_cmd *cmd);
-static int das16m1_cmd_exec(struct comedi_device *dev,
- struct comedi_subdevice *s);
-static int das16m1_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s);
-
-static int das16m1_poll(struct comedi_device *dev, struct comedi_subdevice *s);
-static irqreturn_t das16m1_interrupt(int irq, void *d);
-static void das16m1_handler(struct comedi_device *dev, unsigned int status);
-
-static unsigned int das16m1_set_pacer(struct comedi_device *dev,
- unsigned int ns, int round_flag);
-
-static int das16m1_irq_bits(unsigned int irq);
-
struct das16m1_board {
const char *name;
unsigned int ai_speed;
};
-static const struct das16m1_board das16m1_boards[] = {
- {
- .name = "cio-das16/m1", /* CIO-DAS16_M1.pdf */
- .ai_speed = 1000, /* 1MHz max speed */
- },
-};
-
-static int das16m1_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int das16m1_detach(struct comedi_device *dev);
-static struct comedi_driver driver_das16m1 = {
- .driver_name = "das16m1",
- .module = THIS_MODULE,
- .attach = das16m1_attach,
- .detach = das16m1_detach,
- .board_name = &das16m1_boards[0].name,
- .num_names = ARRAY_SIZE(das16m1_boards),
- .offset = sizeof(das16m1_boards[0]),
-};
-
struct das16m1_private_struct {
unsigned int control_state;
volatile unsigned int adc_count; /* number of samples completed */
@@ -198,22 +152,17 @@ struct das16m1_private_struct {
#define devpriv ((struct das16m1_private_struct *)(dev->private))
#define thisboard ((const struct das16m1_board *)(dev->board_ptr))
-static int __init driver_das16m1_init_module(void)
+static inline short munge_sample(short data)
{
- return comedi_driver_register(&driver_das16m1);
+ return (data >> 4) & 0xfff;
}
-static void __exit driver_das16m1_cleanup_module(void)
+static void munge_sample_array(short *array, unsigned int num_elements)
{
- comedi_driver_unregister(&driver_das16m1);
-}
-
-module_init(driver_das16m1_init_module);
-module_exit(driver_das16m1_cleanup_module);
+ unsigned int i;
-static inline short munge_sample(short data)
-{
- return (data >> 4) & 0xfff;
+ for (i = 0; i < num_elements; i++)
+ array[i] = munge_sample(array[i]);
}
static int das16m1_cmd_test(struct comedi_device *dev,
@@ -340,6 +289,25 @@ static int das16m1_cmd_test(struct comedi_device *dev,
return 0;
}
+/* This function takes a time in nanoseconds and sets the *
+ * 2 pacer clocks to the closest frequency possible. It also *
+ * returns the actual sampling period. */
+static unsigned int das16m1_set_pacer(struct comedi_device *dev,
+ unsigned int ns, int rounding_flags)
+{
+ i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL, &(devpriv->divisor1),
+ &(devpriv->divisor2), &ns,
+ rounding_flags & TRIG_ROUND_MASK);
+
+ /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
+ i8254_load(dev->iobase + DAS16M1_8254_SECOND, 0, 1, devpriv->divisor1,
+ 2);
+ i8254_load(dev->iobase + DAS16M1_8254_SECOND, 0, 2, devpriv->divisor2,
+ 2);
+
+ return ns;
+}
+
static int das16m1_cmd_exec(struct comedi_device *dev,
struct comedi_subdevice *s)
{
@@ -484,57 +452,6 @@ static int das16m1_do_wbits(struct comedi_device *dev,
return 2;
}
-static int das16m1_poll(struct comedi_device *dev, struct comedi_subdevice *s)
-{
- unsigned long flags;
- unsigned int status;
-
- /* prevent race with interrupt handler */
- spin_lock_irqsave(&dev->spinlock, flags);
- status = inb(dev->iobase + DAS16M1_CS);
- das16m1_handler(dev, status);
- spin_unlock_irqrestore(&dev->spinlock, flags);
-
- return s->async->buf_write_count - s->async->buf_read_count;
-}
-
-static irqreturn_t das16m1_interrupt(int irq, void *d)
-{
- int status;
- struct comedi_device *dev = d;
-
- if (dev->attached == 0) {
- comedi_error(dev, "premature interrupt");
- return IRQ_HANDLED;
- }
- /* prevent race with comedi_poll() */
- spin_lock(&dev->spinlock);
-
- status = inb(dev->iobase + DAS16M1_CS);
-
- if ((status & (IRQDATA | OVRUN)) == 0) {
- comedi_error(dev, "spurious interrupt");
- spin_unlock(&dev->spinlock);
- return IRQ_NONE;
- }
-
- das16m1_handler(dev, status);
-
- /* clear interrupt */
- outb(0, dev->iobase + DAS16M1_CLEAR_INTR);
-
- spin_unlock(&dev->spinlock);
- return IRQ_HANDLED;
-}
-
-static void munge_sample_array(short *array, unsigned int num_elements)
-{
- unsigned int i;
-
- for (i = 0; i < num_elements; i++)
- array[i] = munge_sample(array[i]);
-}
-
static void das16m1_handler(struct comedi_device *dev, unsigned int status)
{
struct comedi_subdevice *s;
@@ -596,23 +513,47 @@ static void das16m1_handler(struct comedi_device *dev, unsigned int status)
}
-/* This function takes a time in nanoseconds and sets the *
- * 2 pacer clocks to the closest frequency possible. It also *
- * returns the actual sampling period. */
-static unsigned int das16m1_set_pacer(struct comedi_device *dev,
- unsigned int ns, int rounding_flags)
+static int das16m1_poll(struct comedi_device *dev, struct comedi_subdevice *s)
{
- i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL, &(devpriv->divisor1),
- &(devpriv->divisor2), &ns,
- rounding_flags & TRIG_ROUND_MASK);
+ unsigned long flags;
+ unsigned int status;
- /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
- i8254_load(dev->iobase + DAS16M1_8254_SECOND, 0, 1, devpriv->divisor1,
- 2);
- i8254_load(dev->iobase + DAS16M1_8254_SECOND, 0, 2, devpriv->divisor2,
- 2);
+ /* prevent race with interrupt handler */
+ spin_lock_irqsave(&dev->spinlock, flags);
+ status = inb(dev->iobase + DAS16M1_CS);
+ das16m1_handler(dev, status);
+ spin_unlock_irqrestore(&dev->spinlock, flags);
- return ns;
+ return s->async->buf_write_count - s->async->buf_read_count;
+}
+
+static irqreturn_t das16m1_interrupt(int irq, void *d)
+{
+ int status;
+ struct comedi_device *dev = d;
+
+ if (dev->attached == 0) {
+ comedi_error(dev, "premature interrupt");
+ return IRQ_HANDLED;
+ }
+ /* prevent race with comedi_poll() */
+ spin_lock(&dev->spinlock);
+
+ status = inb(dev->iobase + DAS16M1_CS);
+
+ if ((status & (IRQDATA | OVRUN)) == 0) {
+ comedi_error(dev, "spurious interrupt");
+ spin_unlock(&dev->spinlock);
+ return IRQ_NONE;
+ }
+
+ das16m1_handler(dev, status);
+
+ /* clear interrupt */
+ outb(0, dev->iobase + DAS16M1_CLEAR_INTR);
+
+ spin_unlock(&dev->spinlock);
+ return IRQ_HANDLED;
}
static int das16m1_irq_bits(unsigned int irq)
@@ -656,7 +597,6 @@ static int das16m1_irq_bits(unsigned int irq)
* 0 I/O base
* 1 IRQ
*/
-
static int das16m1_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
@@ -673,12 +613,12 @@ static int das16m1_attach(struct comedi_device *dev,
dev->board_name = thisboard->name;
- if (!request_region(iobase, DAS16M1_SIZE, driver_das16m1.driver_name)) {
+ if (!request_region(iobase, DAS16M1_SIZE, dev->driver->driver_name)) {
comedi_error(dev, "I/O port conflict\n");
return -EIO;
}
if (!request_region(iobase + DAS16M1_82C55, DAS16M1_SIZE2,
- driver_das16m1.driver_name)) {
+ dev->driver->driver_name)) {
release_region(iobase, DAS16M1_SIZE);
comedi_error(dev, "I/O port conflict\n");
return -EIO;
@@ -690,7 +630,7 @@ static int das16m1_attach(struct comedi_device *dev,
/* make sure it is valid */
if (das16m1_irq_bits(irq) >= 0) {
ret = request_irq(irq, das16m1_interrupt, 0,
- driver_das16m1.driver_name, dev);
+ dev->driver->driver_name, dev);
if (ret < 0)
return ret;
dev->irq = irq;
@@ -763,25 +703,36 @@ static int das16m1_attach(struct comedi_device *dev,
return 0;
}
-static int das16m1_detach(struct comedi_device *dev)
+static void das16m1_detach(struct comedi_device *dev)
{
-
-/* das16m1_reset(dev); */
-
if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 3);
-
if (dev->irq)
free_irq(dev->irq, dev);
-
if (dev->iobase) {
release_region(dev->iobase, DAS16M1_SIZE);
release_region(dev->iobase + DAS16M1_82C55, DAS16M1_SIZE2);
}
-
- return 0;
}
+static const struct das16m1_board das16m1_boards[] = {
+ {
+ .name = "cio-das16/m1", /* CIO-DAS16_M1.pdf */
+ .ai_speed = 1000, /* 1MHz max speed */
+ },
+};
+
+static struct comedi_driver das16m1_driver = {
+ .driver_name = "das16m1",
+ .module = THIS_MODULE,
+ .attach = das16m1_attach,
+ .detach = das16m1_detach,
+ .board_name = &das16m1_boards[0].name,
+ .num_names = ARRAY_SIZE(das16m1_boards),
+ .offset = sizeof(das16m1_boards[0]),
+};
+module_comedi_driver(das16m1_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index 99ada5a53b9e..2ac344354c1d 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -183,9 +183,6 @@ enum {
das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
};
-static int das1800_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int das1800_detach(struct comedi_device *dev);
static int das1800_probe(struct comedi_device *dev);
static int das1800_cancel(struct comedi_device *dev,
struct comedi_subdevice *s);
@@ -518,33 +515,6 @@ static const struct comedi_lrange range_ao_2 = {
};
*/
-static struct comedi_driver driver_das1800 = {
- .driver_name = "das1800",
- .module = THIS_MODULE,
- .attach = das1800_attach,
- .detach = das1800_detach,
- .num_names = ARRAY_SIZE(das1800_boards),
- .board_name = &das1800_boards[0].name,
- .offset = sizeof(struct das1800_board),
-};
-
-/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
- */
-static int __init driver_das1800_init_module(void)
-{
- return comedi_driver_register(&driver_das1800);
-}
-
-static void __exit driver_das1800_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_das1800);
-}
-
-module_init(driver_das1800_init_module);
-module_exit(driver_das1800_cleanup_module);
-
static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
unsigned int dma1)
{
@@ -579,7 +549,7 @@ static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
return -EINVAL;
break;
}
- if (request_dma(dma0, driver_das1800.driver_name)) {
+ if (request_dma(dma0, dev->driver->driver_name)) {
dev_err(dev->hw_dev, "failed to allocate dma channel %i\n",
dma0);
return -EINVAL;
@@ -587,7 +557,7 @@ static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
devpriv->dma0 = dma0;
devpriv->dma_current = dma0;
if (dma1) {
- if (request_dma(dma1, driver_das1800.driver_name)) {
+ if (request_dma(dma1, dev->driver->driver_name)) {
dev_err(dev->hw_dev, "failed to allocate dma channel %i\n",
dma1);
return -EINVAL;
@@ -633,7 +603,7 @@ static int das1800_attach(struct comedi_device *dev,
return -ENOMEM;
printk(KERN_DEBUG "comedi%d: %s: io 0x%lx", dev->minor,
- driver_das1800.driver_name, iobase);
+ dev->driver->driver_name, iobase);
if (irq) {
printk(KERN_CONT ", irq %u", irq);
if (dma0) {
@@ -650,7 +620,7 @@ static int das1800_attach(struct comedi_device *dev,
}
/* check if io addresses are available */
- if (!request_region(iobase, DAS1800_SIZE, driver_das1800.driver_name)) {
+ if (!request_region(iobase, DAS1800_SIZE, dev->driver->driver_name)) {
printk
(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n",
iobase, iobase + DAS1800_SIZE - 1);
@@ -671,7 +641,7 @@ static int das1800_attach(struct comedi_device *dev,
if (thisboard->ao_ability == 2) {
iobase2 = iobase + IOBASE2;
if (!request_region(iobase2, DAS1800_SIZE,
- driver_das1800.driver_name)) {
+ dev->driver->driver_name)) {
printk
(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n",
iobase2, iobase2 + DAS1800_SIZE - 1);
@@ -683,7 +653,7 @@ static int das1800_attach(struct comedi_device *dev,
/* grab our IRQ */
if (irq) {
if (request_irq(irq, das1800_interrupt, 0,
- driver_das1800.driver_name, dev)) {
+ dev->driver->driver_name, dev)) {
dev_dbg(dev->hw_dev, "unable to allocate irq %u\n",
irq);
return -EINVAL;
@@ -797,9 +767,8 @@ static int das1800_attach(struct comedi_device *dev,
return 0;
};
-static int das1800_detach(struct comedi_device *dev)
+static void das1800_detach(struct comedi_device *dev)
{
- /* only free stuff if it has been allocated by _attach */
if (dev->iobase)
release_region(dev->iobase, DAS1800_SIZE);
if (dev->irq)
@@ -814,11 +783,6 @@ static int das1800_detach(struct comedi_device *dev)
kfree(devpriv->ai_buf0);
kfree(devpriv->ai_buf1);
}
-
- dev_dbg(dev->hw_dev, "comedi%d: %s: remove\n", dev->minor,
- driver_das1800.driver_name);
-
- return 0;
};
/* probes and checks das-1800 series board type
@@ -1811,6 +1775,17 @@ static unsigned int suggest_transfer_size(struct comedi_cmd *cmd)
return size;
}
+static struct comedi_driver das1800_driver = {
+ .driver_name = "das1800",
+ .module = THIS_MODULE,
+ .attach = das1800_attach,
+ .detach = das1800_detach,
+ .num_names = ARRAY_SIZE(das1800_boards),
+ .board_name = &das1800_boards[0].name,
+ .offset = sizeof(struct das1800_board),
+};
+module_comedi_driver(das1800_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
index f25684145e84..881f392d1dba 100644
--- a/drivers/staging/comedi/drivers/das6402.c
+++ b/drivers/staging/comedi/drivers/das6402.c
@@ -99,29 +99,6 @@ This driver has suffered bitrot.
#define C2 0x80
#define RWLH 0x30
-static int das6402_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int das6402_detach(struct comedi_device *dev);
-static struct comedi_driver driver_das6402 = {
- .driver_name = "das6402",
- .module = THIS_MODULE,
- .attach = das6402_attach,
- .detach = das6402_detach,
-};
-
-static int __init driver_das6402_init_module(void)
-{
- return comedi_driver_register(&driver_das6402);
-}
-
-static void __exit driver_das6402_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_das6402);
-}
-
-module_init(driver_das6402_init_module);
-module_exit(driver_das6402_cleanup_module);
-
struct das6402_private {
int ai_bytes_to_read;
@@ -130,7 +107,14 @@ struct das6402_private {
#define devpriv ((struct das6402_private *)dev->private)
static void das6402_ai_fifo_dregs(struct comedi_device *dev,
- struct comedi_subdevice *s);
+ struct comedi_subdevice *s)
+{
+ while (1) {
+ if (!(inb(dev->iobase + 8) & 0x01))
+ return;
+ comedi_buf_put(s->async, inw(dev->iobase));
+ }
+}
static void das6402_setcounter(struct comedi_device *dev)
{
@@ -209,16 +193,6 @@ static void das6402_ai_fifo_read(struct comedi_device *dev, short *data, int n)
}
#endif
-static void das6402_ai_fifo_dregs(struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- while (1) {
- if (!(inb(dev->iobase + 8) & 0x01))
- return;
- comedi_buf_put(s->async, inw(dev->iobase));
- }
-}
-
static int das6402_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
@@ -300,16 +274,6 @@ static int board_init(struct comedi_device *dev)
return 0;
}
-static int das6402_detach(struct comedi_device *dev)
-{
- if (dev->irq)
- free_irq(dev->irq, dev);
- if (dev->iobase)
- release_region(dev->iobase, DAS6402_SIZE);
-
- return 0;
-}
-
static int das6402_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
@@ -363,6 +327,22 @@ static int das6402_attach(struct comedi_device *dev,
return 0;
}
+static void das6402_detach(struct comedi_device *dev)
+{
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ if (dev->iobase)
+ release_region(dev->iobase, DAS6402_SIZE);
+}
+
+static struct comedi_driver das6402_driver = {
+ .driver_name = "das6402",
+ .module = THIS_MODULE,
+ .attach = das6402_attach,
+ .detach = das6402_detach,
+};
+module_comedi_driver(das6402_driver)
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index 6e347b40fe61..a3a54e1c5c98 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -245,7 +245,7 @@ struct das800_private {
static int das800_attach(struct comedi_device *dev,
struct comedi_devconfig *it);
-static int das800_detach(struct comedi_device *dev);
+static void das800_detach(struct comedi_device *dev);
static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
static struct comedi_driver driver_das800 = {
@@ -556,16 +556,12 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
};
-static int das800_detach(struct comedi_device *dev)
+static void das800_detach(struct comedi_device *dev)
{
- dev_info(dev->hw_dev, "comedi%d: das800: remove\n", dev->minor);
-
- /* only free stuff if it has been allocated by _attach */
if (dev->iobase)
release_region(dev->iobase, DAS800_SIZE);
if (dev->irq)
free_irq(dev->irq, dev);
- return 0;
};
static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index 2b4e6e6eb825..83828903db4b 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -224,7 +224,7 @@ struct dmm32at_private {
*/
static int dmm32at_attach(struct comedi_device *dev,
struct comedi_devconfig *it);
-static int dmm32at_detach(struct comedi_device *dev);
+static void dmm32at_detach(struct comedi_device *dev);
static struct comedi_driver driver_dmm32at = {
.driver_name = "dmm32at",
.module = THIS_MODULE,
@@ -450,23 +450,12 @@ static int dmm32at_attach(struct comedi_device *dev,
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int dmm32at_detach(struct comedi_device *dev)
+static void dmm32at_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: dmm32at: remove\n", dev->minor);
if (dev->irq)
free_irq(dev->irq, dev);
if (dev->iobase)
release_region(dev->iobase, DMM32AT_MEMSIZE);
-
- return 0;
}
/*
diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
index b85c8366a396..625bd617a8e9 100644
--- a/drivers/staging/comedi/drivers/dt2801.c
+++ b/drivers/staging/comedi/drivers/dt2801.c
@@ -88,29 +88,6 @@ Configuration options:
#define DT2801_STATUS 1
#define DT2801_CMD 1
-static int dt2801_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int dt2801_detach(struct comedi_device *dev);
-static struct comedi_driver driver_dt2801 = {
- .driver_name = "dt2801",
- .module = THIS_MODULE,
- .attach = dt2801_attach,
- .detach = dt2801_detach,
-};
-
-static int __init driver_dt2801_init_module(void)
-{
- return comedi_driver_register(&driver_dt2801);
-}
-
-static void __exit driver_dt2801_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_dt2801);
-}
-
-module_init(driver_dt2801_init_module);
-module_exit(driver_dt2801_cleanup_module);
-
#if 0
/* ignore 'defined but not used' warning */
static const struct comedi_lrange range_dt2801_ai_pgh_bipolar = { 4, {
@@ -258,22 +235,6 @@ struct dt2801_private {
#define devpriv ((struct dt2801_private *)dev->private)
-static int dt2801_ai_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int dt2801_ao_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int dt2801_ao_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int dt2801_dio_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int dt2801_dio_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
/* These are the low-level routines:
writecommand: write a command to the board
writedata: write data byte
@@ -503,6 +464,123 @@ static const struct comedi_lrange *ai_range_lkup(int type, int opt)
return &range_unknown;
}
+static int dt2801_error(struct comedi_device *dev, int stat)
+{
+ if (stat < 0) {
+ if (stat == -ETIME)
+ printk("dt2801: timeout\n");
+ else
+ printk("dt2801: error %d\n", stat);
+ return stat;
+ }
+ printk("dt2801: error status 0x%02x, resetting...\n", stat);
+
+ dt2801_reset(dev);
+ dt2801_reset(dev);
+
+ return -EIO;
+}
+
+static int dt2801_ai_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ int d;
+ int stat;
+ int i;
+
+ for (i = 0; i < insn->n; i++) {
+ stat = dt2801_writecmd(dev, DT_C_READ_ADIM);
+ dt2801_writedata(dev, CR_RANGE(insn->chanspec));
+ dt2801_writedata(dev, CR_CHAN(insn->chanspec));
+ stat = dt2801_readdata2(dev, &d);
+
+ if (stat != 0)
+ return dt2801_error(dev, stat);
+
+ data[i] = d;
+ }
+
+ return i;
+}
+
+static int dt2801_ao_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ data[0] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
+
+ return 1;
+}
+
+static int dt2801_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ dt2801_writecmd(dev, DT_C_WRITE_DAIM);
+ dt2801_writedata(dev, CR_CHAN(insn->chanspec));
+ dt2801_writedata2(dev, data[0]);
+
+ devpriv->ao_readback[CR_CHAN(insn->chanspec)] = data[0];
+
+ return 1;
+}
+
+static int dt2801_dio_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ int which = 0;
+
+ if (s == dev->subdevices + 4)
+ which = 1;
+
+ if (insn->n != 2)
+ return -EINVAL;
+ if (data[0]) {
+ s->state &= ~data[0];
+ s->state |= (data[0] & data[1]);
+ dt2801_writecmd(dev, DT_C_WRITE_DIG);
+ dt2801_writedata(dev, which);
+ dt2801_writedata(dev, s->state);
+ }
+ dt2801_writecmd(dev, DT_C_READ_DIG);
+ dt2801_writedata(dev, which);
+ dt2801_readdata(dev, data + 1);
+
+ return 2;
+}
+
+static int dt2801_dio_insn_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ int which = 0;
+
+ if (s == dev->subdevices + 4)
+ which = 1;
+
+ /* configure */
+ switch (data[0]) {
+ case INSN_CONFIG_DIO_OUTPUT:
+ s->io_bits = 0xff;
+ dt2801_writecmd(dev, DT_C_SET_DIGOUT);
+ break;
+ case INSN_CONFIG_DIO_INPUT:
+ s->io_bits = 0;
+ dt2801_writecmd(dev, DT_C_SET_DIGIN);
+ break;
+ case INSN_CONFIG_DIO_QUERY:
+ data[1] = s->io_bits ? COMEDI_OUTPUT : COMEDI_INPUT;
+ return insn->n;
+ default:
+ return -EINVAL;
+ }
+ dt2801_writedata(dev, which);
+
+ return 1;
+}
+
/*
options:
[0] - i/o base
@@ -615,130 +693,19 @@ out:
return ret;
}
-static int dt2801_detach(struct comedi_device *dev)
+static void dt2801_detach(struct comedi_device *dev)
{
if (dev->iobase)
release_region(dev->iobase, DT2801_IOSIZE);
-
- return 0;
-}
-
-static int dt2801_error(struct comedi_device *dev, int stat)
-{
- if (stat < 0) {
- if (stat == -ETIME)
- printk("dt2801: timeout\n");
- else
- printk("dt2801: error %d\n", stat);
- return stat;
- }
- printk("dt2801: error status 0x%02x, resetting...\n", stat);
-
- dt2801_reset(dev);
- dt2801_reset(dev);
-
- return -EIO;
-}
-
-static int dt2801_ai_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- int d;
- int stat;
- int i;
-
- for (i = 0; i < insn->n; i++) {
- stat = dt2801_writecmd(dev, DT_C_READ_ADIM);
- dt2801_writedata(dev, CR_RANGE(insn->chanspec));
- dt2801_writedata(dev, CR_CHAN(insn->chanspec));
- stat = dt2801_readdata2(dev, &d);
-
- if (stat != 0)
- return dt2801_error(dev, stat);
-
- data[i] = d;
- }
-
- return i;
-}
-
-static int dt2801_ao_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- data[0] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
-
- return 1;
-}
-
-static int dt2801_ao_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- dt2801_writecmd(dev, DT_C_WRITE_DAIM);
- dt2801_writedata(dev, CR_CHAN(insn->chanspec));
- dt2801_writedata2(dev, data[0]);
-
- devpriv->ao_readback[CR_CHAN(insn->chanspec)] = data[0];
-
- return 1;
-}
-
-static int dt2801_dio_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- int which = 0;
-
- if (s == dev->subdevices + 4)
- which = 1;
-
- if (insn->n != 2)
- return -EINVAL;
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
- dt2801_writecmd(dev, DT_C_WRITE_DIG);
- dt2801_writedata(dev, which);
- dt2801_writedata(dev, s->state);
- }
- dt2801_writecmd(dev, DT_C_READ_DIG);
- dt2801_writedata(dev, which);
- dt2801_readdata(dev, data + 1);
-
- return 2;
}
-static int dt2801_dio_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- int which = 0;
-
- if (s == dev->subdevices + 4)
- which = 1;
-
- /* configure */
- switch (data[0]) {
- case INSN_CONFIG_DIO_OUTPUT:
- s->io_bits = 0xff;
- dt2801_writecmd(dev, DT_C_SET_DIGOUT);
- break;
- case INSN_CONFIG_DIO_INPUT:
- s->io_bits = 0;
- dt2801_writecmd(dev, DT_C_SET_DIGIN);
- break;
- case INSN_CONFIG_DIO_QUERY:
- data[1] = s->io_bits ? COMEDI_OUTPUT : COMEDI_INPUT;
- return insn->n;
- default:
- return -EINVAL;
- }
- dt2801_writedata(dev, which);
-
- return 1;
-}
+static struct comedi_driver dt2801_driver = {
+ .driver_name = "dt2801",
+ .module = THIS_MODULE,
+ .attach = dt2801_attach,
+ .detach = dt2801_detach,
+};
+module_comedi_driver(dt2801_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
index 0131d5225b52..106ffea30b95 100644
--- a/drivers/staging/comedi/drivers/dt2811.c
+++ b/drivers/staging/comedi/drivers/dt2811.c
@@ -211,61 +211,8 @@ struct dt2811_board {
const struct comedi_lrange *unip_5;
};
-static const struct dt2811_board boardtypes[] = {
- {"dt2811-pgh",
- &range_dt2811_pgh_ai_5_bipolar,
- &range_dt2811_pgh_ai_2_5_bipolar,
- &range_dt2811_pgh_ai_5_unipolar,
- },
- {"dt2811-pgl",
- &range_dt2811_pgl_ai_5_bipolar,
- &range_dt2811_pgl_ai_2_5_bipolar,
- &range_dt2811_pgl_ai_5_unipolar,
- },
-};
-
#define this_board ((const struct dt2811_board *)dev->board_ptr)
-static int dt2811_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int dt2811_detach(struct comedi_device *dev);
-static struct comedi_driver driver_dt2811 = {
- .driver_name = "dt2811",
- .module = THIS_MODULE,
- .attach = dt2811_attach,
- .detach = dt2811_detach,
- .board_name = &boardtypes[0].name,
- .num_names = ARRAY_SIZE(boardtypes),
- .offset = sizeof(struct dt2811_board),
-};
-
-static int __init driver_dt2811_init_module(void)
-{
- return comedi_driver_register(&driver_dt2811);
-}
-
-static void __exit driver_dt2811_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_dt2811);
-}
-
-module_init(driver_dt2811_init_module);
-module_exit(driver_dt2811_cleanup_module);
-
-static int dt2811_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int dt2811_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int dt2811_ao_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int dt2811_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int dt2811_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
enum { card_2811_pgh, card_2811_pgl };
struct dt2811_private {
@@ -317,6 +264,120 @@ static irqreturn_t dt2811_interrupt(int irq, void *d)
}
#endif
+static int dt2811_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ int chan = CR_CHAN(insn->chanspec);
+ int timeout = DT2811_TIMEOUT;
+ int i;
+
+ for (i = 0; i < insn->n; i++) {
+ outb(chan, dev->iobase + DT2811_ADGCR);
+
+ while (timeout
+ && inb(dev->iobase + DT2811_ADCSR) & DT2811_ADBUSY)
+ timeout--;
+ if (!timeout)
+ return -ETIME;
+
+ data[i] = inb(dev->iobase + DT2811_ADDATLO);
+ data[i] |= inb(dev->iobase + DT2811_ADDATHI) << 8;
+ data[i] &= 0xfff;
+ }
+
+ return i;
+}
+
+#if 0
+/* Wow. This is code from the Comedi stone age. But it hasn't been
+ * replaced, so I'll let it stay. */
+int dt2811_adtrig(kdev_t minor, comedi_adtrig *adtrig)
+{
+ struct comedi_device *dev = comedi_devices + minor;
+
+ if (adtrig->n < 1)
+ return 0;
+ dev->curadchan = adtrig->chan;
+ switch (dev->i_admode) {
+ case COMEDI_MDEMAND:
+ dev->ntrig = adtrig->n - 1;
+ /* not necessary */
+ /*printk("dt2811: AD soft trigger\n"); */
+ /*outb(DT2811_CLRERROR|DT2811_INTENB,
+ dev->iobase+DT2811_ADCSR); */
+ outb(dev->curadchan, dev->iobase + DT2811_ADGCR);
+ do_gettimeofday(&trigtime);
+ break;
+ case COMEDI_MCONTS:
+ dev->ntrig = adtrig->n;
+ break;
+ }
+
+ return 0;
+}
+#endif
+
+static int dt2811_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ int i;
+ int chan;
+
+ chan = CR_CHAN(insn->chanspec);
+
+ for (i = 0; i < insn->n; i++) {
+ outb(data[i] & 0xff, dev->iobase + DT2811_DADAT0LO + 2 * chan);
+ outb((data[i] >> 8) & 0xff,
+ dev->iobase + DT2811_DADAT0HI + 2 * chan);
+ devpriv->ao_readback[chan] = data[i];
+ }
+
+ return i;
+}
+
+static int dt2811_ao_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ int i;
+ int chan;
+
+ chan = CR_CHAN(insn->chanspec);
+
+ for (i = 0; i < insn->n; i++)
+ data[i] = devpriv->ao_readback[chan];
+
+ return i;
+}
+
+static int dt2811_di_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ if (insn->n != 2)
+ return -EINVAL;
+
+ data[1] = inb(dev->iobase + DT2811_DIO);
+
+ return 2;
+}
+
+static int dt2811_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ if (insn->n != 2)
+ return -EINVAL;
+
+ s->state &= ~data[0];
+ s->state |= data[0] & data[1];
+ outb(s->state, dev->iobase + DT2811_DIO);
+
+ data[1] = s->state;
+
+ return 2;
+}
+
/*
options[0] Board base address
options[1] IRQ
@@ -337,7 +398,6 @@ static irqreturn_t dt2811_interrupt(int irq, void *d)
1 == bipolar 2.5V (-2.5V -- +2.5V)
2 == unipolar 5V (0V -- +5V)
*/
-
static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
/* int i, irq; */
@@ -511,131 +571,38 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int dt2811_detach(struct comedi_device *dev)
+static void dt2811_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: dt2811: remove\n", dev->minor);
-
if (dev->irq)
free_irq(dev->irq, dev);
if (dev->iobase)
release_region(dev->iobase, DT2811_SIZE);
-
- return 0;
-}
-
-static int dt2811_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- int chan = CR_CHAN(insn->chanspec);
- int timeout = DT2811_TIMEOUT;
- int i;
-
- for (i = 0; i < insn->n; i++) {
- outb(chan, dev->iobase + DT2811_ADGCR);
-
- while (timeout
- && inb(dev->iobase + DT2811_ADCSR) & DT2811_ADBUSY)
- timeout--;
- if (!timeout)
- return -ETIME;
-
- data[i] = inb(dev->iobase + DT2811_ADDATLO);
- data[i] |= inb(dev->iobase + DT2811_ADDATHI) << 8;
- data[i] &= 0xfff;
- }
-
- return i;
}
-#if 0
-/* Wow. This is code from the Comedi stone age. But it hasn't been
- * replaced, so I'll let it stay. */
-int dt2811_adtrig(kdev_t minor, comedi_adtrig *adtrig)
-{
- struct comedi_device *dev = comedi_devices + minor;
-
- if (adtrig->n < 1)
- return 0;
- dev->curadchan = adtrig->chan;
- switch (dev->i_admode) {
- case COMEDI_MDEMAND:
- dev->ntrig = adtrig->n - 1;
- /* not necessary */
- /*printk("dt2811: AD soft trigger\n"); */
- /*outb(DT2811_CLRERROR|DT2811_INTENB,
- dev->iobase+DT2811_ADCSR); */
- outb(dev->curadchan, dev->iobase + DT2811_ADGCR);
- do_gettimeofday(&trigtime);
- break;
- case COMEDI_MCONTS:
- dev->ntrig = adtrig->n;
- break;
- }
-
- return 0;
-}
-#endif
-
-static int dt2811_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- int i;
- int chan;
-
- chan = CR_CHAN(insn->chanspec);
-
- for (i = 0; i < insn->n; i++) {
- outb(data[i] & 0xff, dev->iobase + DT2811_DADAT0LO + 2 * chan);
- outb((data[i] >> 8) & 0xff,
- dev->iobase + DT2811_DADAT0HI + 2 * chan);
- devpriv->ao_readback[chan] = data[i];
- }
-
- return i;
-}
-
-static int dt2811_ao_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- int i;
- int chan;
-
- chan = CR_CHAN(insn->chanspec);
-
- for (i = 0; i < insn->n; i++)
- data[i] = devpriv->ao_readback[chan];
-
- return i;
-}
-
-static int dt2811_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- if (insn->n != 2)
- return -EINVAL;
-
- data[1] = inb(dev->iobase + DT2811_DIO);
-
- return 2;
-}
-
-static int dt2811_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- if (insn->n != 2)
- return -EINVAL;
-
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
- outb(s->state, dev->iobase + DT2811_DIO);
-
- data[1] = s->state;
+static const struct dt2811_board boardtypes[] = {
+ {
+ .name = "dt2811-pgh",
+ .bip_5 = &range_dt2811_pgh_ai_5_bipolar,
+ .bip_2_5 = &range_dt2811_pgh_ai_2_5_bipolar,
+ .unip_5 = &range_dt2811_pgh_ai_5_unipolar,
+ }, {
+ .name = "dt2811-pgl",
+ .bip_5 = &range_dt2811_pgl_ai_5_bipolar,
+ .bip_2_5 = &range_dt2811_pgl_ai_2_5_bipolar,
+ .unip_5 = &range_dt2811_pgl_ai_5_unipolar,
+ },
+};
- return 2;
-}
+static struct comedi_driver dt2811_driver = {
+ .driver_name = "dt2811",
+ .module = THIS_MODULE,
+ .attach = dt2811_attach,
+ .detach = dt2811_detach,
+ .board_name = &boardtypes[0].name,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .offset = sizeof(struct dt2811_board),
+};
+module_comedi_driver(dt2811_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
index 1c6248cf5928..fa4ade61be5f 100644
--- a/drivers/staging/comedi/drivers/dt2814.c
+++ b/drivers/staging/comedi/drivers/dt2814.c
@@ -60,31 +60,6 @@ addition, the clock does not seem to be very accurate.
#define DT2814_ENB 0x10
#define DT2814_CHANMASK 0x0f
-static int dt2814_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int dt2814_detach(struct comedi_device *dev);
-static struct comedi_driver driver_dt2814 = {
- .driver_name = "dt2814",
- .module = THIS_MODULE,
- .attach = dt2814_attach,
- .detach = dt2814_detach,
-};
-
-static int __init driver_dt2814_init_module(void)
-{
- return comedi_driver_register(&driver_dt2814);
-}
-
-static void __exit driver_dt2814_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_dt2814);
-}
-
-module_init(driver_dt2814_init_module);
-module_exit(driver_dt2814_cleanup_module);
-
-static irqreturn_t dt2814_interrupt(int irq, void *dev);
-
struct dt2814_private {
int ntrig;
@@ -260,6 +235,45 @@ static int dt2814_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
}
+static irqreturn_t dt2814_interrupt(int irq, void *d)
+{
+ int lo, hi;
+ struct comedi_device *dev = d;
+ struct comedi_subdevice *s;
+ int data;
+
+ if (!dev->attached) {
+ comedi_error(dev, "spurious interrupt");
+ return IRQ_HANDLED;
+ }
+
+ s = dev->subdevices + 0;
+
+ hi = inb(dev->iobase + DT2814_DATA);
+ lo = inb(dev->iobase + DT2814_DATA);
+
+ data = (hi << 4) | (lo >> 4);
+
+ if (!(--devpriv->ntrig)) {
+ int i;
+
+ outb(0, dev->iobase + DT2814_CSR);
+ /* note: turning off timed mode triggers another
+ sample. */
+
+ for (i = 0; i < DT2814_TIMEOUT; i++) {
+ if (inb(dev->iobase + DT2814_CSR) & DT2814_FINISH)
+ break;
+ }
+ inb(dev->iobase + DT2814_DATA);
+ inb(dev->iobase + DT2814_DATA);
+
+ s->async->events |= COMEDI_CB_EOA;
+ }
+ comedi_event(dev, s);
+ return IRQ_HANDLED;
+}
+
static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
int i, irq;
@@ -347,57 +361,21 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int dt2814_detach(struct comedi_device *dev)
+static void dt2814_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: dt2814: remove\n", dev->minor);
-
if (dev->irq)
free_irq(dev->irq, dev);
-
if (dev->iobase)
release_region(dev->iobase, DT2814_SIZE);
-
- return 0;
}
-static irqreturn_t dt2814_interrupt(int irq, void *d)
-{
- int lo, hi;
- struct comedi_device *dev = d;
- struct comedi_subdevice *s;
- int data;
-
- if (!dev->attached) {
- comedi_error(dev, "spurious interrupt");
- return IRQ_HANDLED;
- }
-
- s = dev->subdevices + 0;
-
- hi = inb(dev->iobase + DT2814_DATA);
- lo = inb(dev->iobase + DT2814_DATA);
-
- data = (hi << 4) | (lo >> 4);
-
- if (!(--devpriv->ntrig)) {
- int i;
-
- outb(0, dev->iobase + DT2814_CSR);
- /* note: turning off timed mode triggers another
- sample. */
-
- for (i = 0; i < DT2814_TIMEOUT; i++) {
- if (inb(dev->iobase + DT2814_CSR) & DT2814_FINISH)
- break;
- }
- inb(dev->iobase + DT2814_DATA);
- inb(dev->iobase + DT2814_DATA);
-
- s->async->events |= COMEDI_CB_EOA;
- }
- comedi_event(dev, s);
- return IRQ_HANDLED;
-}
+static struct comedi_driver dt2814_driver = {
+ .driver_name = "dt2814",
+ .module = THIS_MODULE,
+ .attach = dt2814_attach,
+ .detach = dt2814_detach,
+};
+module_comedi_driver(dt2814_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
index 4155da43fd51..bbab712be4b9 100644
--- a/drivers/staging/comedi/drivers/dt2815.c
+++ b/drivers/staging/comedi/drivers/dt2815.c
@@ -72,31 +72,6 @@ static const struct comedi_lrange
#define DT2815_DATA 0
#define DT2815_STATUS 1
-static int dt2815_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int dt2815_detach(struct comedi_device *dev);
-static struct comedi_driver driver_dt2815 = {
- .driver_name = "dt2815",
- .module = THIS_MODULE,
- .attach = dt2815_attach,
- .detach = dt2815_detach,
-};
-
-static int __init driver_dt2815_init_module(void)
-{
- return comedi_driver_register(&driver_dt2815);
-}
-
-static void __exit driver_dt2815_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_dt2815);
-}
-
-module_init(driver_dt2815_init_module);
-module_exit(driver_dt2815_cleanup_module);
-
-static void dt2815_free_resources(struct comedi_device *dev);
-
struct dt2815_private {
const struct comedi_lrange *range_type_list[8];
@@ -252,20 +227,19 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static void dt2815_free_resources(struct comedi_device *dev)
+static void dt2815_detach(struct comedi_device *dev)
{
if (dev->iobase)
release_region(dev->iobase, DT2815_SIZE);
}
-static int dt2815_detach(struct comedi_device *dev)
-{
- printk(KERN_INFO "comedi%d: dt2815: remove\n", dev->minor);
-
- dt2815_free_resources(dev);
-
- return 0;
-}
+static struct comedi_driver dt2815_driver = {
+ .driver_name = "dt2815",
+ .module = THIS_MODULE,
+ .attach = dt2815_attach,
+ .detach = dt2815_detach,
+};
+module_comedi_driver(dt2815_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
index 99c1584153d7..1ee10e7bf1d2 100644
--- a/drivers/staging/comedi/drivers/dt2817.c
+++ b/drivers/staging/comedi/drivers/dt2817.c
@@ -47,29 +47,6 @@ Configuration options:
#define DT2817_CR 0
#define DT2817_DATA 1
-static int dt2817_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int dt2817_detach(struct comedi_device *dev);
-static struct comedi_driver driver_dt2817 = {
- .driver_name = "dt2817",
- .module = THIS_MODULE,
- .attach = dt2817_attach,
- .detach = dt2817_detach,
-};
-
-static int __init driver_dt2817_init_module(void)
-{
- return comedi_driver_register(&driver_dt2817);
-}
-
-static void __exit driver_dt2817_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_dt2817);
-}
-
-module_init(driver_dt2817_init_module);
-module_exit(driver_dt2817_cleanup_module);
-
static int dt2817_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -182,16 +159,20 @@ static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int dt2817_detach(struct comedi_device *dev)
+static void dt2817_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: dt2817: remove\n", dev->minor);
-
if (dev->iobase)
release_region(dev->iobase, DT2817_SIZE);
-
- return 0;
}
+static struct comedi_driver dt2817_driver = {
+ .driver_name = "dt2817",
+ .module = THIS_MODULE,
+ .attach = dt2817_attach,
+ .detach = dt2817_detach,
+};
+module_comedi_driver(dt2817_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index 95ebc267bb74..736d8facaee8 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -221,136 +221,6 @@ struct dt282x_board {
int dabits;
};
-static const struct dt282x_board boardtypes[] = {
- {.name = "dt2821",
- .adbits = 12,
- .adchan_se = 16,
- .adchan_di = 8,
- .ai_speed = 20000,
- .ispgl = 0,
- .dachan = 2,
- .dabits = 12,
- },
- {.name = "dt2821-f",
- .adbits = 12,
- .adchan_se = 16,
- .adchan_di = 8,
- .ai_speed = 6500,
- .ispgl = 0,
- .dachan = 2,
- .dabits = 12,
- },
- {.name = "dt2821-g",
- .adbits = 12,
- .adchan_se = 16,
- .adchan_di = 8,
- .ai_speed = 4000,
- .ispgl = 0,
- .dachan = 2,
- .dabits = 12,
- },
- {.name = "dt2823",
- .adbits = 16,
- .adchan_se = 0,
- .adchan_di = 4,
- .ai_speed = 10000,
- .ispgl = 0,
- .dachan = 2,
- .dabits = 16,
- },
- {.name = "dt2824-pgh",
- .adbits = 12,
- .adchan_se = 16,
- .adchan_di = 8,
- .ai_speed = 20000,
- .ispgl = 0,
- .dachan = 0,
- .dabits = 0,
- },
- {.name = "dt2824-pgl",
- .adbits = 12,
- .adchan_se = 16,
- .adchan_di = 8,
- .ai_speed = 20000,
- .ispgl = 1,
- .dachan = 0,
- .dabits = 0,
- },
- {.name = "dt2825",
- .adbits = 12,
- .adchan_se = 16,
- .adchan_di = 8,
- .ai_speed = 20000,
- .ispgl = 1,
- .dachan = 2,
- .dabits = 12,
- },
- {.name = "dt2827",
- .adbits = 16,
- .adchan_se = 0,
- .adchan_di = 4,
- .ai_speed = 10000,
- .ispgl = 0,
- .dachan = 2,
- .dabits = 12,
- },
- {.name = "dt2828",
- .adbits = 12,
- .adchan_se = 4,
- .adchan_di = 0,
- .ai_speed = 10000,
- .ispgl = 0,
- .dachan = 2,
- .dabits = 12,
- },
- {.name = "dt2829",
- .adbits = 16,
- .adchan_se = 8,
- .adchan_di = 0,
- .ai_speed = 33250,
- .ispgl = 0,
- .dachan = 2,
- .dabits = 16,
- },
- {.name = "dt21-ez",
- .adbits = 12,
- .adchan_se = 16,
- .adchan_di = 8,
- .ai_speed = 10000,
- .ispgl = 0,
- .dachan = 2,
- .dabits = 12,
- },
- {.name = "dt23-ez",
- .adbits = 16,
- .adchan_se = 16,
- .adchan_di = 8,
- .ai_speed = 10000,
- .ispgl = 0,
- .dachan = 0,
- .dabits = 0,
- },
- {.name = "dt24-ez",
- .adbits = 12,
- .adchan_se = 16,
- .adchan_di = 8,
- .ai_speed = 10000,
- .ispgl = 0,
- .dachan = 0,
- .dabits = 0,
- },
- {.name = "dt24-ez-pgl",
- .adbits = 12,
- .adchan_se = 16,
- .adchan_di = 8,
- .ai_speed = 10000,
- .ispgl = 1,
- .dachan = 0,
- .dabits = 0,
- },
-};
-
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct dt282x_board))
#define this_board ((const struct dt282x_board *)dev->board_ptr)
struct dt282x_private {
@@ -411,33 +281,6 @@ struct dt282x_private {
b \
} while (0)
-static int dt282x_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int dt282x_detach(struct comedi_device *dev);
-static struct comedi_driver driver_dt282x = {
- .driver_name = "dt282x",
- .module = THIS_MODULE,
- .attach = dt282x_attach,
- .detach = dt282x_detach,
- .board_name = &boardtypes[0].name,
- .num_names = n_boardtypes,
- .offset = sizeof(struct dt282x_board),
-};
-
-static int __init driver_dt282x_init_module(void)
-{
- return comedi_driver_register(&driver_dt282x);
-}
-
-static void __exit driver_dt282x_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_dt282x);
-}
-
-module_init(driver_dt282x_init_module);
-module_exit(driver_dt282x_cleanup_module);
-
-static void free_resources(struct comedi_device *dev);
static int prep_ai_dma(struct comedi_device *dev, int chan, int size);
static int prep_ao_dma(struct comedi_device *dev, int chan, int size);
static int dt282x_ai_cancel(struct comedi_device *dev,
@@ -1271,6 +1114,52 @@ enum { /* i/o base, irq, dma channels */
opt_ai_range, opt_ao0_range, opt_ao1_range, /* range */
};
+static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2)
+{
+ int ret;
+
+ devpriv->usedma = 0;
+
+ if (!dma1 && !dma2) {
+ printk(KERN_ERR " (no dma)");
+ return 0;
+ }
+
+ if (dma1 == dma2 || dma1 < 5 || dma2 < 5 || dma1 > 7 || dma2 > 7)
+ return -EINVAL;
+
+ if (dma2 < dma1) {
+ int i;
+ i = dma1;
+ dma1 = dma2;
+ dma2 = i;
+ }
+
+ ret = request_dma(dma1, "dt282x A");
+ if (ret)
+ return -EBUSY;
+ devpriv->dma[0].chan = dma1;
+
+ ret = request_dma(dma2, "dt282x B");
+ if (ret)
+ return -EBUSY;
+ devpriv->dma[1].chan = dma2;
+
+ devpriv->dma_maxsize = PAGE_SIZE;
+ devpriv->dma[0].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
+ devpriv->dma[1].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
+ if (!devpriv->dma[0].buf || !devpriv->dma[1].buf) {
+ printk(KERN_ERR " can't get DMA memory");
+ return -ENOMEM;
+ }
+
+ printk(KERN_INFO " (dma=%d,%d)", dma1, dma2);
+
+ devpriv->usedma = 1;
+
+ return 0;
+}
+
/*
options:
0 i/o base
@@ -1442,7 +1331,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static void free_resources(struct comedi_device *dev)
+static void dt282x_detach(struct comedi_device *dev)
{
if (dev->irq)
free_irq(dev->irq, dev);
@@ -1460,60 +1349,146 @@ static void free_resources(struct comedi_device *dev)
}
}
-static int dt282x_detach(struct comedi_device *dev)
-{
- printk(KERN_INFO "comedi%d: dt282x: remove\n", dev->minor);
-
- free_resources(dev);
-
- return 0;
-}
-
-static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2)
-{
- int ret;
-
- devpriv->usedma = 0;
-
- if (!dma1 && !dma2) {
- printk(KERN_ERR " (no dma)");
- return 0;
- }
-
- if (dma1 == dma2 || dma1 < 5 || dma2 < 5 || dma1 > 7 || dma2 > 7)
- return -EINVAL;
-
- if (dma2 < dma1) {
- int i;
- i = dma1;
- dma1 = dma2;
- dma2 = i;
- }
-
- ret = request_dma(dma1, "dt282x A");
- if (ret)
- return -EBUSY;
- devpriv->dma[0].chan = dma1;
-
- ret = request_dma(dma2, "dt282x B");
- if (ret)
- return -EBUSY;
- devpriv->dma[1].chan = dma2;
-
- devpriv->dma_maxsize = PAGE_SIZE;
- devpriv->dma[0].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
- devpriv->dma[1].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
- if (!devpriv->dma[0].buf || !devpriv->dma[1].buf) {
- printk(KERN_ERR " can't get DMA memory");
- return -ENOMEM;
- }
-
- printk(KERN_INFO " (dma=%d,%d)", dma1, dma2);
-
- devpriv->usedma = 1;
+static const struct dt282x_board boardtypes[] = {
+ {
+ .name = "dt2821",
+ .adbits = 12,
+ .adchan_se = 16,
+ .adchan_di = 8,
+ .ai_speed = 20000,
+ .ispgl = 0,
+ .dachan = 2,
+ .dabits = 12,
+ }, {
+ .name = "dt2821-f",
+ .adbits = 12,
+ .adchan_se = 16,
+ .adchan_di = 8,
+ .ai_speed = 6500,
+ .ispgl = 0,
+ .dachan = 2,
+ .dabits = 12,
+ }, {
+ .name = "dt2821-g",
+ .adbits = 12,
+ .adchan_se = 16,
+ .adchan_di = 8,
+ .ai_speed = 4000,
+ .ispgl = 0,
+ .dachan = 2,
+ .dabits = 12,
+ }, {
+ .name = "dt2823",
+ .adbits = 16,
+ .adchan_se = 0,
+ .adchan_di = 4,
+ .ai_speed = 10000,
+ .ispgl = 0,
+ .dachan = 2,
+ .dabits = 16,
+ }, {
+ .name = "dt2824-pgh",
+ .adbits = 12,
+ .adchan_se = 16,
+ .adchan_di = 8,
+ .ai_speed = 20000,
+ .ispgl = 0,
+ .dachan = 0,
+ .dabits = 0,
+ }, {
+ .name = "dt2824-pgl",
+ .adbits = 12,
+ .adchan_se = 16,
+ .adchan_di = 8,
+ .ai_speed = 20000,
+ .ispgl = 1,
+ .dachan = 0,
+ .dabits = 0,
+ }, {
+ .name = "dt2825",
+ .adbits = 12,
+ .adchan_se = 16,
+ .adchan_di = 8,
+ .ai_speed = 20000,
+ .ispgl = 1,
+ .dachan = 2,
+ .dabits = 12,
+ }, {
+ .name = "dt2827",
+ .adbits = 16,
+ .adchan_se = 0,
+ .adchan_di = 4,
+ .ai_speed = 10000,
+ .ispgl = 0,
+ .dachan = 2,
+ .dabits = 12,
+ }, {
+ .name = "dt2828",
+ .adbits = 12,
+ .adchan_se = 4,
+ .adchan_di = 0,
+ .ai_speed = 10000,
+ .ispgl = 0,
+ .dachan = 2,
+ .dabits = 12,
+ }, {
+ .name = "dt2829",
+ .adbits = 16,
+ .adchan_se = 8,
+ .adchan_di = 0,
+ .ai_speed = 33250,
+ .ispgl = 0,
+ .dachan = 2,
+ .dabits = 16,
+ }, {
+ .name = "dt21-ez",
+ .adbits = 12,
+ .adchan_se = 16,
+ .adchan_di = 8,
+ .ai_speed = 10000,
+ .ispgl = 0,
+ .dachan = 2,
+ .dabits = 12,
+ }, {
+ .name = "dt23-ez",
+ .adbits = 16,
+ .adchan_se = 16,
+ .adchan_di = 8,
+ .ai_speed = 10000,
+ .ispgl = 0,
+ .dachan = 0,
+ .dabits = 0,
+ }, {
+ .name = "dt24-ez",
+ .adbits = 12,
+ .adchan_se = 16,
+ .adchan_di = 8,
+ .ai_speed = 10000,
+ .ispgl = 0,
+ .dachan = 0,
+ .dabits = 0,
+ }, {
+ .name = "dt24-ez-pgl",
+ .adbits = 12,
+ .adchan_se = 16,
+ .adchan_di = 8,
+ .ai_speed = 10000,
+ .ispgl = 1,
+ .dachan = 0,
+ .dabits = 0,
+ },
+};
- return 0;
-}
+static struct comedi_driver dt282x_driver = {
+ .driver_name = "dt282x",
+ .module = THIS_MODULE,
+ .attach = dt282x_attach,
+ .detach = dt282x_detach,
+ .board_name = &boardtypes[0].name,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .offset = sizeof(struct dt282x_board),
+};
+module_comedi_driver(dt282x_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 0a7979e52999..0d273269b572 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -164,19 +164,6 @@ static const struct dt3k_boardtype dt3k_boardtypes[] = {
#define n_dt3k_boards sizeof(dt3k_boardtypes)/sizeof(struct dt3k_boardtype)
#define this_board ((const struct dt3k_boardtype *)dev->board_ptr)
-static DEFINE_PCI_DEVICE_TABLE(dt3k_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0022) },
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0027) },
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0023) },
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0024) },
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0028) },
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0025) },
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0026) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, dt3k_pci_table);
-
#define DT3000_SIZE (4*0x1000)
/* dual-ported RAM location definitions */
@@ -276,54 +263,6 @@ struct dt3k_private {
#define devpriv ((struct dt3k_private *)dev->private)
-static int dt3000_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int dt3000_detach(struct comedi_device *dev);
-static struct comedi_driver driver_dt3000 = {
- .driver_name = "dt3000",
- .module = THIS_MODULE,
- .attach = dt3000_attach,
- .detach = dt3000_detach,
-};
-
-static int __devinit driver_dt3000_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, driver_dt3000.driver_name);
-}
-
-static void __devexit driver_dt3000_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver driver_dt3000_pci_driver = {
- .id_table = dt3k_pci_table,
- .probe = &driver_dt3000_pci_probe,
- .remove = __devexit_p(&driver_dt3000_pci_remove)
-};
-
-static int __init driver_dt3000_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_dt3000);
- if (retval < 0)
- return retval;
-
- driver_dt3000_pci_driver.name = (char *)driver_dt3000.driver_name;
- return pci_register_driver(&driver_dt3000_pci_driver);
-}
-
-static void __exit driver_dt3000_cleanup_module(void)
-{
- pci_unregister_driver(&driver_dt3000_pci_driver);
- comedi_driver_unregister(&driver_dt3000);
-}
-
-module_init(driver_dt3000_init_module);
-module_exit(driver_dt3000_cleanup_module);
-
static void dt3k_ai_empty_fifo(struct comedi_device *dev,
struct comedi_subdevice *s);
static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg,
@@ -841,7 +780,77 @@ static int dt3k_mem_insn_read(struct comedi_device *dev,
return i;
}
-static int dt_pci_probe(struct comedi_device *dev, int bus, int slot);
+static int setup_pci(struct comedi_device *dev)
+{
+ resource_size_t addr;
+ int ret;
+
+ ret = comedi_pci_enable(devpriv->pci_dev, "dt3000");
+ if (ret < 0)
+ return ret;
+
+ addr = pci_resource_start(devpriv->pci_dev, 0);
+ devpriv->phys_addr = addr;
+ devpriv->io_addr = ioremap(devpriv->phys_addr, DT3000_SIZE);
+ if (!devpriv->io_addr)
+ return -ENOMEM;
+#if DEBUG
+ printk("0x%08llx mapped to %p, ",
+ (unsigned long long)devpriv->phys_addr, devpriv->io_addr);
+#endif
+
+ return 0;
+}
+
+static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board)
+{
+ int i;
+
+ for (from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from);
+ from != NULL;
+ from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from)) {
+ for (i = 0; i < n_dt3k_boards; i++) {
+ if (from->device == dt3k_boardtypes[i].device_id) {
+ *board = i;
+ return from;
+ }
+ }
+ printk
+ ("unknown Data Translation PCI device found with device_id=0x%04x\n",
+ from->device);
+ }
+ *board = -1;
+ return from;
+}
+
+static int dt_pci_probe(struct comedi_device *dev, int bus, int slot)
+{
+ int board;
+ int ret;
+ struct pci_dev *pcidev;
+
+ pcidev = NULL;
+ while ((pcidev = dt_pci_find_device(pcidev, &board)) != NULL) {
+ if ((bus == 0 && slot == 0) ||
+ (pcidev->bus->number == bus &&
+ PCI_SLOT(pcidev->devfn) == slot)) {
+ break;
+ }
+ }
+ devpriv->pci_dev = pcidev;
+
+ if (board >= 0)
+ dev->board_ptr = dt3k_boardtypes + board;
+
+ if (!devpriv->pci_dev)
+ return 0;
+
+ ret = setup_pci(dev);
+ if (ret < 0)
+ return ret;
+
+ return 1;
+}
static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
@@ -935,11 +944,10 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int dt3000_detach(struct comedi_device *dev)
+static void dt3000_detach(struct comedi_device *dev)
{
if (dev->irq)
free_irq(dev->irq, dev);
-
if (devpriv) {
if (devpriv->pci_dev) {
if (devpriv->phys_addr)
@@ -949,85 +957,45 @@ static int dt3000_detach(struct comedi_device *dev)
if (devpriv->io_addr)
iounmap(devpriv->io_addr);
}
- /* XXX */
-
- return 0;
}
-static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board);
-static int setup_pci(struct comedi_device *dev);
+static struct comedi_driver dt3000_driver = {
+ .driver_name = "dt3000",
+ .module = THIS_MODULE,
+ .attach = dt3000_attach,
+ .detach = dt3000_detach,
+};
-static int dt_pci_probe(struct comedi_device *dev, int bus, int slot)
+static int __devinit dt3000_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- int board;
- int ret;
- struct pci_dev *pcidev;
-
- pcidev = NULL;
- while ((pcidev = dt_pci_find_device(pcidev, &board)) != NULL) {
- if ((bus == 0 && slot == 0) ||
- (pcidev->bus->number == bus &&
- PCI_SLOT(pcidev->devfn) == slot)) {
- break;
- }
- }
- devpriv->pci_dev = pcidev;
-
- if (board >= 0)
- dev->board_ptr = dt3k_boardtypes + board;
-
- if (!devpriv->pci_dev)
- return 0;
-
- ret = setup_pci(dev);
- if (ret < 0)
- return ret;
-
- return 1;
+ return comedi_pci_auto_config(dev, &dt3000_driver);
}
-static int setup_pci(struct comedi_device *dev)
+static void __devexit dt3000_pci_remove(struct pci_dev *dev)
{
- resource_size_t addr;
- int ret;
-
- ret = comedi_pci_enable(devpriv->pci_dev, "dt3000");
- if (ret < 0)
- return ret;
-
- addr = pci_resource_start(devpriv->pci_dev, 0);
- devpriv->phys_addr = addr;
- devpriv->io_addr = ioremap(devpriv->phys_addr, DT3000_SIZE);
- if (!devpriv->io_addr)
- return -ENOMEM;
-#if DEBUG
- printk("0x%08llx mapped to %p, ",
- (unsigned long long)devpriv->phys_addr, devpriv->io_addr);
-#endif
-
- return 0;
+ comedi_pci_auto_unconfig(dev);
}
-static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board)
-{
- int i;
+static DEFINE_PCI_DEVICE_TABLE(dt3000_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0022) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0027) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0023) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0024) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0028) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0025) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0026) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, dt3000_pci_table);
- for (from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from);
- from != NULL;
- from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from)) {
- for (i = 0; i < n_dt3k_boards; i++) {
- if (from->device == dt3k_boardtypes[i].device_id) {
- *board = i;
- return from;
- }
- }
- printk
- ("unknown Data Translation PCI device found with device_id=0x%04x\n",
- from->device);
- }
- *board = -1;
- return from;
-}
+static struct pci_driver dt3000_pci_driver = {
+ .name = "dt3000",
+ .id_table = dt3000_pci_table,
+ .probe = dt3000_pci_probe,
+ .remove = __devexit_p(dt3000_pci_remove),
+};
+module_comedi_pci_driver(dt3000_driver, dt3000_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
index e86ab5862895..22cda5c76ce4 100644
--- a/drivers/staging/comedi/drivers/dt9812.c
+++ b/drivers/staging/comedi/drivers/dt9812.c
@@ -196,7 +196,7 @@ struct dt9812_flash_data {
};
#define DT9812_MAX_NUM_MULTI_BYTE_RDS \
- ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / sizeof(u8))
+ ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / sizeof(u8))
struct dt9812_read_multi {
u8 count;
@@ -209,8 +209,8 @@ struct dt9812_write_byte {
};
#define DT9812_MAX_NUM_MULTI_BYTE_WRTS \
- ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / \
- sizeof(struct dt9812_write_byte))
+ ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / \
+ sizeof(struct dt9812_write_byte))
struct dt9812_write_multi {
u8 count;
@@ -224,7 +224,8 @@ struct dt9812_rmw_byte {
};
#define DT9812_MAX_NUM_MULTI_BYTE_RMWS \
- ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / sizeof(struct dt9812_rmw_byte))
+ ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / \
+ sizeof(struct dt9812_rmw_byte))
struct dt9812_rmw_multi {
u8 count;
@@ -365,7 +366,7 @@ static int dt9812_read_info(struct usb_dt9812 *dev, int offset, void *buf,
}
static int dt9812_read_multiple_registers(struct usb_dt9812 *dev, int reg_count,
- u8 * address, u8 * value)
+ u8 *address, u8 *value)
{
struct dt9812_usb_cmd cmd;
int i, count, retval;
@@ -391,8 +392,8 @@ static int dt9812_read_multiple_registers(struct usb_dt9812 *dev, int reg_count,
}
static int dt9812_write_multiple_registers(struct usb_dt9812 *dev,
- int reg_count, u8 * address,
- u8 * value)
+ int reg_count, u8 *address,
+ u8 *value)
{
struct dt9812_usb_cmd cmd;
int i, count, retval;
@@ -430,7 +431,7 @@ static int dt9812_rmw_multiple_registers(struct usb_dt9812 *dev, int reg_count,
return retval;
}
-static int dt9812_digital_in(struct slot_dt9812 *slot, u8 * bits)
+static int dt9812_digital_in(struct slot_dt9812 *slot, u8 *bits)
{
int result = -ENODEV;
@@ -476,7 +477,7 @@ static int dt9812_digital_out(struct slot_dt9812 *slot, u8 bits)
return result;
}
-static int dt9812_digital_out_shadow(struct slot_dt9812 *slot, u8 * bits)
+static int dt9812_digital_out_shadow(struct slot_dt9812 *slot, u8 *bits)
{
int result = -ENODEV;
@@ -547,12 +548,12 @@ static void dt9812_configure_gain(struct usb_dt9812 *dev,
rmw->or_value = F020_MASK_ADC0CF_AMP0GN2;
break;
default:
- err("Illegal gain %d\n", gain);
+ dev_err(&dev->interface->dev, "Illegal gain %d\n", gain);
}
}
-static int dt9812_analog_in(struct slot_dt9812 *slot, int channel, u16 * value,
+static int dt9812_analog_in(struct slot_dt9812 *slot, int channel, u16 *value,
enum dt9812_gain gain)
{
struct dt9812_rmw_byte rmw[3];
@@ -619,7 +620,7 @@ exit:
}
static int dt9812_analog_out_shadow(struct slot_dt9812 *slot, int channel,
- u16 * value)
+ u16 *value)
{
int result = -ENODEV;
@@ -715,7 +716,7 @@ static int dt9812_probe(struct usb_interface *interface,
iface_desc = interface->cur_altsetting;
if (iface_desc->desc.bNumEndpoints != 5) {
- err("Wrong number of endpints.");
+ dev_err(&interface->dev, "Wrong number of endpoints.\n");
retval = -ENODEV;
goto error;
}
@@ -781,22 +782,22 @@ static int dt9812_probe(struct usb_interface *interface,
}
if (dt9812_read_info(dev, 1, &dev->vendor, sizeof(dev->vendor)) != 0) {
- err("Failed to read vendor.");
+ dev_err(&interface->dev, "Failed to read vendor.\n");
retval = -ENODEV;
goto error;
}
if (dt9812_read_info(dev, 3, &dev->product, sizeof(dev->product)) != 0) {
- err("Failed to read product.");
+ dev_err(&interface->dev, "Failed to read product.\n");
retval = -ENODEV;
goto error;
}
if (dt9812_read_info(dev, 5, &dev->device, sizeof(dev->device)) != 0) {
- err("Failed to read device.");
+ dev_err(&interface->dev, "Failed to read device.\n");
retval = -ENODEV;
goto error;
}
if (dt9812_read_info(dev, 7, &dev->serial, sizeof(dev->serial)) != 0) {
- err("Failed to read serial.");
+ dev_err(&interface->dev, "Failed to read serial.\n");
retval = -ENODEV;
goto error;
}
@@ -1110,9 +1111,9 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int dt9812_detach(struct comedi_device *dev)
+static void dt9812_detach(struct comedi_device *dev)
{
- return 0;
+ /* Nothing to cleanup */
}
static struct comedi_driver dt9812_comedi_driver = {
@@ -1146,7 +1147,9 @@ static int __init usb_dt9812_init(void)
result = comedi_driver_register(&dt9812_comedi_driver);
if (result) {
usb_deregister(&dt9812_usb_driver);
- err("comedi_driver_register failed. Error number %d", result);
+ printk(KERN_ERR KBUILD_MODNAME
+ ": comedi_driver_register failed. Error number %d\n",
+ result);
}
return result;
diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
index da8a2bf31657..b0cec7b1b0c9 100644
--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
+++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
@@ -48,17 +48,6 @@
static DEFINE_MUTEX(start_stop_sem);
-static DEFINE_PCI_DEVICE_TABLE(dyna_pci10xx_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_DYNALOG, 0x1050) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, dyna_pci10xx_pci_table);
-
-static int dyna_pci10xx_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int dyna_pci10xx_detach(struct comedi_device *dev);
-
static const struct comedi_lrange range_pci1050_ai = { 3, {
BIP_RANGE(10),
BIP_RANGE(5),
@@ -113,16 +102,6 @@ static const struct boardtype boardtypes[] = {
{.name = DRV_NAME},
};
-static struct comedi_driver driver_dyna_pci10xx = {
- .driver_name = DRV_NAME,
- .module = THIS_MODULE,
- .attach = dyna_pci10xx_attach,
- .detach = dyna_pci10xx_detach,
- .board_name = &boardtypes[0].name,
- .offset = sizeof(struct boardtype),
- .num_names = ARRAY_SIZE(boardtypes),
-};
-
struct dyna_pci10xx_private {
struct pci_dev *pci_dev; /* ptr to PCI device */
char valid; /* card is usable */
@@ -408,54 +387,48 @@ found:
return 1;
}
-static int dyna_pci10xx_detach(struct comedi_device *dev)
+static void dyna_pci10xx_detach(struct comedi_device *dev)
{
if (devpriv && devpriv->pci_dev) {
comedi_pci_disable(devpriv->pci_dev);
mutex_destroy(&devpriv->mutex);
}
-
- return 0;
}
-static int __devinit driver_dyna_pci10xx_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static struct comedi_driver dyna_pci10xx_driver = {
+ .driver_name = "dyna_pci10xx",
+ .module = THIS_MODULE,
+ .attach = dyna_pci10xx_attach,
+ .detach = dyna_pci10xx_detach,
+ .board_name = &boardtypes[0].name,
+ .offset = sizeof(struct boardtype),
+ .num_names = ARRAY_SIZE(boardtypes),
+};
+
+static int __devinit dyna_pci10xx_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_dyna_pci10xx.driver_name);
+ return comedi_pci_auto_config(dev, &dyna_pci10xx_driver);
}
-static void __devexit driver_dyna_pci10xx_pci_remove(struct pci_dev *dev)
+static void __devexit dyna_pci10xx_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_dyna_pci10xx_pci_driver = {
- .id_table = dyna_pci10xx_pci_table,
- .probe = &driver_dyna_pci10xx_pci_probe,
- .remove = __devexit_p(&driver_dyna_pci10xx_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(dyna_pci10xx_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_DYNALOG, 0x1050) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, dyna_pci10xx_pci_table);
-static int __init driver_dyna_pci10xx_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_dyna_pci10xx);
- if (retval < 0)
- return retval;
-
- driver_dyna_pci10xx_pci_driver.name =
- (char *)driver_dyna_pci10xx.driver_name;
- return pci_register_driver(&driver_dyna_pci10xx_pci_driver);
-}
-
-static void __exit driver_dyna_pci10xx_cleanup_module(void)
-{
- pci_unregister_driver(&driver_dyna_pci10xx_pci_driver);
- comedi_driver_unregister(&driver_dyna_pci10xx);
-}
-
-module_init(driver_dyna_pci10xx_init_module);
-module_exit(driver_dyna_pci10xx_cleanup_module);
+static struct pci_driver dyna_pci10xx_pci_driver = {
+ .name = "dyna_pci10xx",
+ .id_table = dyna_pci10xx_pci_table,
+ .probe = dyna_pci10xx_pci_probe,
+ .remove = __devexit_p(dyna_pci10xx_pci_remove),
+};
+module_comedi_pci_driver(dyna_pci10xx_driver, dyna_pci10xx_pci_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Prashant Shah <pshah.mumbai@gmail.com>");
diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
index 7f49add60b21..d23814450b40 100644
--- a/drivers/staging/comedi/drivers/fl512.c
+++ b/drivers/staging/comedi/drivers/fl512.c
@@ -42,38 +42,6 @@ static const struct comedi_lrange range_fl512 = { 4, {
}
};
-static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int fl512_detach(struct comedi_device *dev);
-
-static struct comedi_driver driver_fl512 = {
- .driver_name = "fl512",
- .module = THIS_MODULE,
- .attach = fl512_attach,
- .detach = fl512_detach,
-};
-
-static int __init driver_fl512_init_module(void)
-{
- return comedi_driver_register(&driver_fl512);
-}
-
-static void __exit driver_fl512_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_fl512);
-}
-
-module_init(driver_fl512_init_module);
-module_exit(driver_fl512_cleanup_module);
-
-static int fl512_ai_insn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data);
-static int fl512_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int fl512_ao_insn_readback(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
/*
* fl512_ai_insn : this is the analog input function
*/
@@ -140,9 +108,6 @@ static int fl512_ao_insn_readback(struct comedi_device *dev,
return n;
}
-/*
- * start attach
- */
static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
unsigned long iobase;
@@ -209,14 +174,20 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 1;
}
-static int fl512_detach(struct comedi_device *dev)
+static void fl512_detach(struct comedi_device *dev)
{
if (dev->iobase)
release_region(dev->iobase, FL512_SIZE);
- printk(KERN_INFO "comedi%d: fl512: dummy i detach\n", dev->minor);
- return 0;
}
+static struct comedi_driver fl512_driver = {
+ .driver_name = "fl512",
+ .module = THIS_MODULE,
+ .attach = fl512_attach,
+ .detach = fl512_detach,
+};
+module_comedi_driver(fl512_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
index bc020dea141b..8aece08bd0dd 100644
--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
+++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
@@ -53,8 +53,6 @@ support could be added to this driver.
#include "plx9080.h"
#include "comedi_fc.h"
-static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int hpdi_detach(struct comedi_device *dev);
static void abort_dma(struct comedi_device *dev, unsigned int channel);
static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
@@ -287,15 +285,6 @@ static const struct hpdi_board hpdi_boards[] = {
#endif
};
-static DEFINE_PCI_DEVICE_TABLE(hpdi_pci_table) = {
- {
- PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080, PCI_VENDOR_ID_PLX,
- 0x2400, 0, 0, 0}, {
- 0}
-};
-
-MODULE_DEVICE_TABLE(pci, hpdi_pci_table);
-
static inline struct hpdi_board *board(const struct comedi_device *dev)
{
return (struct hpdi_board *)dev->board_ptr;
@@ -338,51 +327,6 @@ static inline struct hpdi_private *priv(struct comedi_device *dev)
return dev->private;
}
-static struct comedi_driver driver_hpdi = {
- .driver_name = "gsc_hpdi",
- .module = THIS_MODULE,
- .attach = hpdi_attach,
- .detach = hpdi_detach,
-};
-
-static int __devinit driver_hpdi_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, driver_hpdi.driver_name);
-}
-
-static void __devexit driver_hpdi_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver driver_hpdi_pci_driver = {
- .id_table = hpdi_pci_table,
- .probe = &driver_hpdi_pci_probe,
- .remove = __devexit_p(&driver_hpdi_pci_remove)
-};
-
-static int __init driver_hpdi_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_hpdi);
- if (retval < 0)
- return retval;
-
- driver_hpdi_pci_driver.name = (char *)driver_hpdi.driver_name;
- return pci_register_driver(&driver_hpdi_pci_driver);
-}
-
-static void __exit driver_hpdi_cleanup_module(void)
-{
- pci_unregister_driver(&driver_hpdi_pci_driver);
- comedi_driver_unregister(&driver_hpdi);
-}
-
-module_init(driver_hpdi_init_module);
-module_exit(driver_hpdi_cleanup_module);
-
static int dio_config_insn(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn,
unsigned int *data)
@@ -645,7 +589,7 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
"gsc_hpdi: found %s on bus %i, slot %i\n", board(dev)->name,
pcidev->bus->number, PCI_SLOT(pcidev->devfn));
- if (comedi_pci_enable(pcidev, driver_hpdi.driver_name)) {
+ if (comedi_pci_enable(pcidev, dev->driver->driver_name)) {
printk(KERN_WARNING
" failed enable PCI device and request regions\n");
return -EIO;
@@ -679,7 +623,7 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* get irq */
if (request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED,
- driver_hpdi.driver_name, dev)) {
+ dev->driver->driver_name, dev)) {
printk(KERN_WARNING
" unable to allocate irq %u\n", pcidev->irq);
return -EINVAL;
@@ -720,12 +664,10 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return init_hpdi(dev);
}
-static int hpdi_detach(struct comedi_device *dev)
+static void hpdi_detach(struct comedi_device *dev)
{
unsigned int i;
- printk(KERN_WARNING "comedi%d: gsc_hpdi: remove\n", dev->minor);
-
if (dev->irq)
free_irq(dev->irq, dev);
if ((priv(dev)) && (priv(dev)->hw_dev)) {
@@ -758,7 +700,6 @@ static int hpdi_detach(struct comedi_device *dev)
comedi_pci_disable(priv(dev)->hw_dev);
pci_dev_put(priv(dev)->hw_dev);
}
- return 0;
}
static int dio_config_block_size(struct comedi_device *dev, unsigned int *data)
@@ -1113,6 +1054,39 @@ static int hpdi_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
return 0;
}
+static struct comedi_driver gsc_hpdi_driver = {
+ .driver_name = "gsc_hpdi",
+ .module = THIS_MODULE,
+ .attach = hpdi_attach,
+ .detach = hpdi_detach,
+};
+
+static int __devinit gsc_hpdi_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &gsc_hpdi_driver);
+}
+
+static void __devexit gsc_hpdi_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(gsc_hpdi_pci_table) = {
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080, PCI_VENDOR_ID_PLX,
+ 0x2400, 0, 0, 0},
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, gsc_hpdi_pci_table);
+
+static struct pci_driver gsc_hpdi_pci_driver = {
+ .name = "gsc_hpdi",
+ .id_table = gsc_hpdi_pci_table,
+ .probe = gsc_hpdi_pci_probe,
+ .remove = __devexit_p(gsc_hpdi_pci_remove)
+};
+module_comedi_pci_driver(gsc_hpdi_driver, gsc_hpdi_pci_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
index 126550f3c02b..fdc596fb0990 100644
--- a/drivers/staging/comedi/drivers/icp_multi.c
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -121,15 +121,6 @@ static const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 };
/*
==============================================================================
- Forward declarations
-==============================================================================
-*/
-static int icp_multi_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int icp_multi_detach(struct comedi_device *dev);
-
-/*
-==============================================================================
Data & Structure declarations
==============================================================================
*/
@@ -154,50 +145,6 @@ struct boardtype {
const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
};
-static const struct boardtype boardtypes[] = {
- {"icp_multi", /* Driver name */
- DEVICE_ID, /* PCI device ID */
- IORANGE_ICP_MULTI, /* I/O range length */
- 1, /* 1=Card supports interrupts */
- TYPE_ICP_MULTI, /* Card type = ICP MULTI */
- 16, /* Num of A/D channels */
- 8, /* Num of A/D channels in diff mode */
- 4, /* Num of D/A channels */
- 16, /* Num of digital inputs */
- 8, /* Num of digital outputs */
- 4, /* Num of counters */
- 0x0fff, /* Resolution of A/D */
- 0x0fff, /* Resolution of D/A */
- &range_analog, /* Rangelist for A/D */
- range_codes_analog, /* Range codes for programming */
- &range_analog}, /* Rangelist for D/A */
-};
-
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
-
-static struct comedi_driver driver_icp_multi = {
- .driver_name = "icp_multi",
- .module = THIS_MODULE,
- .attach = icp_multi_attach,
- .detach = icp_multi_detach,
- .num_names = n_boardtypes,
- .board_name = &boardtypes[0].name,
- .offset = sizeof(struct boardtype),
-};
-
-static int __init driver_icp_multi_init_module(void)
-{
- return comedi_driver_register(&driver_icp_multi);
-}
-
-static void __exit driver_icp_multi_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_icp_multi);
-}
-
-module_init(driver_icp_multi_init_module);
-module_exit(driver_icp_multi_cleanup_module);
-
struct icp_multi_private {
struct pcilst_struct *card; /* pointer to card */
char valid; /* card is usable */
@@ -222,25 +169,81 @@ struct icp_multi_private {
/*
==============================================================================
- More forward declarations
+
+Name: setup_channel_list
+
+Description:
+ This function sets the appropriate channel selection,
+ differential input mode and range bits in the ADC Command/
+ Status register.
+
+Parameters:
+ struct comedi_device *dev Pointer to current service structure
+ struct comedi_subdevice *s Pointer to current subdevice structure
+ unsigned int *chanlist Pointer to packed channel list
+ unsigned int n_chan Number of channels to scan
+
+Returns:Void
+
==============================================================================
*/
-
-#if 0
-static int check_channel_list(struct comedi_device *dev,
- struct comedi_subdevice *s,
- unsigned int *chanlist, unsigned int n_chan);
-#endif
static void setup_channel_list(struct comedi_device *dev,
struct comedi_subdevice *s,
- unsigned int *chanlist, unsigned int n_chan);
-static int icp_multi_reset(struct comedi_device *dev);
+ unsigned int *chanlist, unsigned int n_chan)
+{
+ unsigned int i, range, chanprog;
+ unsigned int diff;
-/*
-==============================================================================
- Functions
-==============================================================================
-*/
+#ifdef ICP_MULTI_EXTDEBUG
+ printk(KERN_DEBUG
+ "icp multi EDBG: setup_channel_list(...,%d)\n", n_chan);
+#endif
+ devpriv->act_chanlist_len = n_chan;
+ devpriv->act_chanlist_pos = 0;
+
+ for (i = 0; i < n_chan; i++) {
+ /* Get channel */
+ chanprog = CR_CHAN(chanlist[i]);
+
+ /* Determine if it is a differential channel (Bit 15 = 1) */
+ if (CR_AREF(chanlist[i]) == AREF_DIFF) {
+ diff = 1;
+ chanprog &= 0x0007;
+ } else {
+ diff = 0;
+ chanprog &= 0x000f;
+ }
+
+ /* Clear channel, range and input mode bits
+ * in A/D command/status register */
+ devpriv->AdcCmdStatus &= 0xf00f;
+
+ /* Set channel number and differential mode status bit */
+ if (diff) {
+ /* Set channel number, bits 9-11 & mode, bit 6 */
+ devpriv->AdcCmdStatus |= (chanprog << 9);
+ devpriv->AdcCmdStatus |= ADC_DI;
+ } else
+ /* Set channel number, bits 8-11 */
+ devpriv->AdcCmdStatus |= (chanprog << 8);
+
+ /* Get range for current channel */
+ range = this_board->rangecode[CR_RANGE(chanlist[i])];
+ /* Set range. bits 4-5 */
+ devpriv->AdcCmdStatus |= range;
+
+ /* Output channel, range, mode to ICP Multi */
+ writew(devpriv->AdcCmdStatus,
+ devpriv->io_addr + ICP_MULTI_ADC_CSR);
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk(KERN_DEBUG
+ "GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
+ devpriv->act_chanlist[i]);
+#endif
+ }
+
+}
/*
==============================================================================
@@ -764,84 +767,6 @@ static int check_channel_list(struct comedi_device *dev,
/*
==============================================================================
-Name: setup_channel_list
-
-Description:
- This function sets the appropriate channel selection,
- differential input mode and range bits in the ADC Command/
- Status register.
-
-Parameters:
- struct comedi_device *dev Pointer to current service structure
- struct comedi_subdevice *s Pointer to current subdevice structure
- unsigned int *chanlist Pointer to packed channel list
- unsigned int n_chan Number of channels to scan
-
-Returns:Void
-
-==============================================================================
-*/
-static void setup_channel_list(struct comedi_device *dev,
- struct comedi_subdevice *s,
- unsigned int *chanlist, unsigned int n_chan)
-{
- unsigned int i, range, chanprog;
- unsigned int diff;
-
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "icp multi EDBG: setup_channel_list(...,%d)\n", n_chan);
-#endif
- devpriv->act_chanlist_len = n_chan;
- devpriv->act_chanlist_pos = 0;
-
- for (i = 0; i < n_chan; i++) {
- /* Get channel */
- chanprog = CR_CHAN(chanlist[i]);
-
- /* Determine if it is a differential channel (Bit 15 = 1) */
- if (CR_AREF(chanlist[i]) == AREF_DIFF) {
- diff = 1;
- chanprog &= 0x0007;
- } else {
- diff = 0;
- chanprog &= 0x000f;
- }
-
- /* Clear channel, range and input mode bits
- * in A/D command/status register */
- devpriv->AdcCmdStatus &= 0xf00f;
-
- /* Set channel number and differential mode status bit */
- if (diff) {
- /* Set channel number, bits 9-11 & mode, bit 6 */
- devpriv->AdcCmdStatus |= (chanprog << 9);
- devpriv->AdcCmdStatus |= ADC_DI;
- } else
- /* Set channel number, bits 8-11 */
- devpriv->AdcCmdStatus |= (chanprog << 8);
-
- /* Get range for current channel */
- range = this_board->rangecode[CR_RANGE(chanlist[i])];
- /* Set range. bits 4-5 */
- devpriv->AdcCmdStatus |= range;
-
- /* Output channel, range, mode to ICP Multi */
- writew(devpriv->AdcCmdStatus,
- devpriv->io_addr + ICP_MULTI_ADC_CSR);
-
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
- devpriv->act_chanlist[i]);
-#endif
- }
-
-}
-
-/*
-==============================================================================
-
Name: icp_multi_reset
Description:
@@ -897,23 +822,6 @@ static int icp_multi_reset(struct comedi_device *dev)
return 0;
}
-/*
-==============================================================================
-
-Name: icp_multi_attach
-
-Description:
- This function sets up all the appropriate data for the current
- device.
-
-Parameters:
- struct comedi_device *dev Pointer to current device structure
- struct comedi_devconfig *it Pointer to current device configuration
-
-Returns:int 0 = success
-
-==============================================================================
-*/
static int icp_multi_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
@@ -1099,44 +1007,53 @@ static int icp_multi_attach(struct comedi_device *dev,
return 0;
}
-/*
-==============================================================================
-
-Name: icp_multi_detach
-
-Description:
- This function releases all the resources used by the current
- device.
-
-Parameters:
- struct comedi_device *dev Pointer to current device structure
-
-Returns:int 0 = success
-
-==============================================================================
-*/
-static int icp_multi_detach(struct comedi_device *dev)
+static void icp_multi_detach(struct comedi_device *dev)
{
-
if (dev->private)
if (devpriv->valid)
icp_multi_reset(dev);
-
if (dev->irq)
free_irq(dev->irq, dev);
-
if (dev->private && devpriv->io_addr)
iounmap(devpriv->io_addr);
-
if (dev->private && devpriv->card)
pci_card_free(devpriv->card);
-
if (--pci_list_builded == 0)
pci_card_list_cleanup(PCI_VENDOR_ID_ICP);
-
- return 0;
}
+static const struct boardtype boardtypes[] = {
+ {
+ .name = "icp_multi",
+ .device_id = DEVICE_ID,
+ .iorange = IORANGE_ICP_MULTI,
+ .have_irq = 1,
+ .cardtype = TYPE_ICP_MULTI,
+ .n_aichan = 16,
+ .n_aichand = 8,
+ .n_aochan = 4,
+ .n_dichan = 16,
+ .n_dochan = 8,
+ .n_ctrs = 4,
+ .ai_maxdata = 0x0fff,
+ .ao_maxdata = 0x0fff,
+ .rangelist_ai = &range_analog,
+ .rangecode = range_codes_analog,
+ .rangelist_ao = &range_analog,
+ },
+};
+
+static struct comedi_driver icp_multi_driver = {
+ .driver_name = "icp_multi",
+ .module = THIS_MODULE,
+ .attach = icp_multi_attach,
+ .detach = icp_multi_detach,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .board_name = &boardtypes[0].name,
+ .offset = sizeof(struct boardtype),
+};
+module_comedi_driver(icp_multi_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
index e4711ef54719..f0a579a04a7d 100644
--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
+++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
@@ -159,17 +159,6 @@ struct pci20xxx_private {
#define devpriv ((struct pci20xxx_private *)dev->private)
#define CHAN (CR_CHAN(it->chanlist[0]))
-static int pci20xxx_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pci20xxx_detach(struct comedi_device *dev);
-
-static struct comedi_driver driver_pci20xxx = {
- .driver_name = "ii_pci20kc",
- .module = THIS_MODULE,
- .attach = pci20xxx_attach,
- .detach = pci20xxx_detach,
-};
-
static int pci20006_init(struct comedi_device *dev, struct comedi_subdevice *s,
int opt0, int opt1);
static int pci20341_init(struct comedi_device *dev, struct comedi_subdevice *s,
@@ -275,11 +264,9 @@ static int pci20xxx_attach(struct comedi_device *dev,
return 1;
}
-static int pci20xxx_detach(struct comedi_device *dev)
+static void pci20xxx_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: pci20xxx: remove\n", dev->minor);
-
- return 0;
+ /* Nothing to cleanup */
}
/* pci20006m */
@@ -666,18 +653,13 @@ static unsigned int pci20xxx_di(struct comedi_device *dev,
}
#endif
-static int __init driver_pci20xxx_init_module(void)
-{
- return comedi_driver_register(&driver_pci20xxx);
-}
-
-static void __exit driver_pci20xxx_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_pci20xxx);
-}
-
-module_init(driver_pci20xxx_init_module);
-module_exit(driver_pci20xxx_cleanup_module);
+static struct comedi_driver pci20xxx_driver = {
+ .driver_name = "ii_pci20kc",
+ .module = THIS_MODULE,
+ .attach = pci20xxx_attach,
+ .detach = pci20xxx_detach,
+};
+module_comedi_driver(pci20xxx_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index 6a79ba10630d..d536a11edb95 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -59,28 +59,6 @@ Devices: [JR3] PCI force sensor board (jr3_pci)
#define PCI_DEVICE_ID_JR3_3_CHANNEL 0x3113
#define PCI_DEVICE_ID_JR3_4_CHANNEL 0x3114
-static int jr3_pci_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int jr3_pci_detach(struct comedi_device *dev);
-
-static struct comedi_driver driver_jr3_pci = {
- .driver_name = "jr3_pci",
- .module = THIS_MODULE,
- .attach = jr3_pci_attach,
- .detach = jr3_pci_detach,
-};
-
-static DEFINE_PCI_DEVICE_TABLE(jr3_pci_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL) },
- { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL_NEW) },
- { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_2_CHANNEL) },
- { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_3_CHANNEL) },
- { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_4_CHANNEL) },
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, jr3_pci_pci_table);
-
struct jr3_pci_dev_private {
struct pci_dev *pci_dev;
@@ -948,9 +926,7 @@ out:
return result;
}
-MODULE_FIRMWARE("comedi/jr3pci.idm");
-
-static int jr3_pci_detach(struct comedi_device *dev)
+static void jr3_pci_detach(struct comedi_device *dev)
{
int i;
struct jr3_pci_dev_private *devpriv = dev->private;
@@ -962,56 +938,52 @@ static int jr3_pci_detach(struct comedi_device *dev)
for (i = 0; i < devpriv->n_channels; i++)
kfree(dev->subdevices[i].private);
}
-
if (devpriv->iobase)
iounmap((void *)devpriv->iobase);
if (devpriv->pci_enabled)
comedi_pci_disable(devpriv->pci_dev);
-
if (devpriv->pci_dev)
pci_dev_put(devpriv->pci_dev);
}
- return 0;
}
-static int __devinit driver_jr3_pci_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static struct comedi_driver jr3_pci_driver = {
+ .driver_name = "jr3_pci",
+ .module = THIS_MODULE,
+ .attach = jr3_pci_attach,
+ .detach = jr3_pci_detach,
+};
+
+static int __devinit jr3_pci_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_jr3_pci.driver_name);
+ return comedi_pci_auto_config(dev, &jr3_pci_driver);
}
-static void __devexit driver_jr3_pci_pci_remove(struct pci_dev *dev)
+static void __devexit jr3_pci_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_jr3_pci_pci_driver = {
- .id_table = jr3_pci_pci_table,
- .probe = &driver_jr3_pci_pci_probe,
- .remove = __devexit_p(&driver_jr3_pci_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(jr3_pci_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL) },
+ { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL_NEW) },
+ { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_2_CHANNEL) },
+ { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_3_CHANNEL) },
+ { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_4_CHANNEL) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, jr3_pci_pci_table);
-static int __init driver_jr3_pci_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_jr3_pci);
- if (retval < 0)
- return retval;
-
- driver_jr3_pci_pci_driver.name = (char *)driver_jr3_pci.driver_name;
- return pci_register_driver(&driver_jr3_pci_pci_driver);
-}
-
-static void __exit driver_jr3_pci_cleanup_module(void)
-{
- pci_unregister_driver(&driver_jr3_pci_pci_driver);
- comedi_driver_unregister(&driver_jr3_pci);
-}
-
-module_init(driver_jr3_pci_init_module);
-module_exit(driver_jr3_pci_cleanup_module);
+static struct pci_driver jr3_pci_pci_driver = {
+ .name = "jr3_pci",
+ .id_table = jr3_pci_pci_table,
+ .probe = jr3_pci_pci_probe,
+ .remove = __devexit_p(jr3_pci_pci_remove),
+};
+module_comedi_pci_driver(jr3_pci_driver, jr3_pci_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("comedi/jr3pci.idm");
diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
index 4e9e9a078652..09d191844bf8 100644
--- a/drivers/staging/comedi/drivers/ke_counter.c
+++ b/drivers/staging/comedi/drivers/ke_counter.c
@@ -46,18 +46,6 @@ Kolter Electronic PCI Counter Card.
#define PCI_VENDOR_ID_KOLTER 0x1001
#define CNT_CARD_DEVICE_ID 0x0014
-/*-- function prototypes ----------------------------------------------------*/
-
-static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int cnt_detach(struct comedi_device *dev);
-
-static DEFINE_PCI_DEVICE_TABLE(cnt_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_KOLTER, CNT_CARD_DEVICE_ID) },
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, cnt_pci_table);
-
/*-- board specification structure ------------------------------------------*/
struct cnt_board_struct {
@@ -87,51 +75,6 @@ struct cnt_device_private {
#define devpriv ((struct cnt_device_private *)dev->private)
-static struct comedi_driver cnt_driver = {
- .driver_name = CNT_DRIVER_NAME,
- .module = THIS_MODULE,
- .attach = cnt_attach,
- .detach = cnt_detach,
-};
-
-static int __devinit cnt_driver_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, cnt_driver.driver_name);
-}
-
-static void __devexit cnt_driver_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver cnt_driver_pci_driver = {
- .id_table = cnt_pci_table,
- .probe = &cnt_driver_pci_probe,
- .remove = __devexit_p(&cnt_driver_pci_remove)
-};
-
-static int __init cnt_driver_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&cnt_driver);
- if (retval < 0)
- return retval;
-
- cnt_driver_pci_driver.name = (char *)cnt_driver.driver_name;
- return pci_register_driver(&cnt_driver_pci_driver);
-}
-
-static void __exit cnt_driver_cleanup_module(void)
-{
- pci_unregister_driver(&cnt_driver_pci_driver);
- comedi_driver_unregister(&cnt_driver);
-}
-
-module_init(cnt_driver_init_module);
-module_exit(cnt_driver_cleanup_module);
-
/*-- counter write ----------------------------------------------------------*/
/* This should be used only for resetting the counters; maybe it is better
@@ -181,8 +124,6 @@ static int cnt_rinsn(struct comedi_device *dev,
return 1;
}
-/*-- attach -----------------------------------------------------------------*/
-
static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
struct comedi_subdevice *subdevice;
@@ -278,20 +219,47 @@ found:
return 0;
}
-/*-- detach -----------------------------------------------------------------*/
-
-static int cnt_detach(struct comedi_device *dev)
+static void cnt_detach(struct comedi_device *dev)
{
if (devpriv && devpriv->pcidev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pcidev);
pci_dev_put(devpriv->pcidev);
}
- printk(KERN_INFO "comedi%d: " CNT_DRIVER_NAME " remove\n",
- dev->minor);
- return 0;
}
+static struct comedi_driver ke_counter_driver = {
+ .driver_name = "ke_counter",
+ .module = THIS_MODULE,
+ .attach = cnt_attach,
+ .detach = cnt_detach,
+};
+
+static int __devinit ke_counter_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &ke_counter_driver);
+}
+
+static void __devexit ke_counter_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(ke_counter_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_KOLTER, CNT_CARD_DEVICE_ID) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, ke_counter_pci_table);
+
+static struct pci_driver ke_counter_pci_driver = {
+ .name = "ke_counter",
+ .id_table = ke_counter_pci_table,
+ .probe = ke_counter_pci_probe,
+ .remove = __devexit_p(ke_counter_pci_remove),
+};
+module_comedi_pci_driver(ke_counter_driver, ke_counter_pci_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index b0bc6bb877ab..8ca1b54600db 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -65,30 +65,6 @@ broken.
#include "me4000_fw.h"
#endif
-/*=============================================================================
- PCI device table.
- This is used by modprobe to translate PCI IDs to drivers.
- ===========================================================================*/
-
-static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4650) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4660) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4661) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4662) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4663) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4670) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4671) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4672) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4673) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4680) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4681) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4682) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4683) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, me4000_pci_table);
-
static const struct me4000_board me4000_boards[] = {
{"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0} },
@@ -113,22 +89,8 @@ static const struct me4000_board me4000_boards[] = {
#define ME4000_BOARD_VERSIONS (ARRAY_SIZE(me4000_boards) - 1)
/*-----------------------------------------------------------------------------
- Comedi function prototypes
- ---------------------------------------------------------------------------*/
-static int me4000_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int me4000_detach(struct comedi_device *dev);
-static struct comedi_driver driver_me4000 = {
- .driver_name = "me4000",
- .module = THIS_MODULE,
- .attach = me4000_attach,
- .detach = me4000_detach,
-};
-
-/*-----------------------------------------------------------------------------
Meilhaus function prototypes
---------------------------------------------------------------------------*/
-static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it);
static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p);
static int init_board_info(struct comedi_device *dev,
struct pci_dev *pci_dev_p);
@@ -139,76 +101,10 @@ static int init_cnt_context(struct comedi_device *dev);
static int xilinx_download(struct comedi_device *dev);
static int reset_board(struct comedi_device *dev);
-static int me4000_dio_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static int me4000_dio_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static int cnt_reset(struct comedi_device *dev, unsigned int channel);
-
-static int cnt_config(struct comedi_device *dev,
- unsigned int channel, unsigned int mode);
-
-static int me4000_cnt_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static int me4000_cnt_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static int me4000_cnt_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static int me4000_ai_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *subdevice,
- struct comedi_insn *insn, unsigned int *data);
-
-static int me4000_ai_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s);
-
-static int ai_check_chanlist(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd);
-
-static int ai_round_cmd_args(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd,
- unsigned int *init_ticks,
- unsigned int *scan_ticks,
- unsigned int *chan_ticks);
-
-static int ai_prepare(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd,
- unsigned int init_ticks,
- unsigned int scan_ticks, unsigned int chan_ticks);
-
static int ai_write_chanlist(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd);
-static irqreturn_t me4000_ai_isr(int irq, void *dev_id);
-
-static int me4000_ai_do_cmd_test(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd);
-
-static int me4000_ai_do_cmd(struct comedi_device *dev,
- struct comedi_subdevice *s);
-
-static int me4000_ao_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static int me4000_ao_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
/*-----------------------------------------------------------------------------
Meilhaus inline functions
---------------------------------------------------------------------------*/
@@ -262,130 +158,6 @@ static const struct comedi_lrange me4000_ao_range = {
}
};
-static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- int result;
-
- CALL_PDEBUG("In me4000_attach()\n");
-
- result = me4000_probe(dev, it);
- if (result)
- return result;
-
- /*
- * Allocate the subdevice structures. alloc_subdevice() is a
- * convenient macro defined in comedidev.h. It relies on
- * n_subdevices being set correctly.
- */
- if (alloc_subdevices(dev, 4) < 0)
- return -ENOMEM;
-
- /*=========================================================================
- Analog input subdevice
- ========================================================================*/
-
- s = dev->subdevices + 0;
-
- if (thisboard->ai.count) {
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags =
- SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
- s->n_chan = thisboard->ai.count;
- s->maxdata = 0xFFFF; /* 16 bit ADC */
- s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
- s->range_table = &me4000_ai_range;
- s->insn_read = me4000_ai_insn_read;
-
- if (info->irq > 0) {
- if (request_irq(info->irq, me4000_ai_isr,
- IRQF_SHARED, "ME-4000", dev)) {
- printk
- ("comedi%d: me4000: me4000_attach(): "
- "Unable to allocate irq\n", dev->minor);
- } else {
- dev->read_subdev = s;
- s->subdev_flags |= SDF_CMD_READ;
- s->cancel = me4000_ai_cancel;
- s->do_cmdtest = me4000_ai_do_cmd_test;
- s->do_cmd = me4000_ai_do_cmd;
- }
- } else {
- printk(KERN_WARNING
- "comedi%d: me4000: me4000_attach(): "
- "No interrupt available\n", dev->minor);
- }
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
-
- /*=========================================================================
- Analog output subdevice
- ========================================================================*/
-
- s = dev->subdevices + 1;
-
- if (thisboard->ao.count) {
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
- s->n_chan = thisboard->ao.count;
- s->maxdata = 0xFFFF; /* 16 bit DAC */
- s->range_table = &me4000_ao_range;
- s->insn_write = me4000_ao_insn_write;
- s->insn_read = me4000_ao_insn_read;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
-
- /*=========================================================================
- Digital I/O subdevice
- ========================================================================*/
-
- s = dev->subdevices + 2;
-
- if (thisboard->dio.count) {
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = thisboard->dio.count * 8;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = me4000_dio_insn_bits;
- s->insn_config = me4000_dio_insn_config;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
-
- /*
- * Check for optoisolated ME-4000 version. If one the first
- * port is a fixed output port and the second is a fixed input port.
- */
- if (!me4000_inl(dev, info->dio_context.dir_reg)) {
- s->io_bits |= 0xFF;
- me4000_outl(dev, ME4000_DIO_CTRL_BIT_MODE_0,
- info->dio_context.dir_reg);
- }
-
- /*=========================================================================
- Counter subdevice
- ========================================================================*/
-
- s = dev->subdevices + 3;
-
- if (thisboard->cnt.count) {
- s->type = COMEDI_SUBD_COUNTER;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = thisboard->cnt.count;
- s->maxdata = 0xFFFF; /* 16 bit counters */
- s->insn_read = me4000_cnt_insn_read;
- s->insn_write = me4000_cnt_insn_write;
- s->insn_config = me4000_cnt_insn_config;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
-
- return 0;
-}
-
static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
{
struct pci_dev *pci_device = NULL;
@@ -920,22 +692,6 @@ static int reset_board(struct comedi_device *dev)
return 0;
}
-static int me4000_detach(struct comedi_device *dev)
-{
- CALL_PDEBUG("In me4000_detach()\n");
-
- if (info) {
- if (info->pci_dev_p) {
- reset_board(dev);
- if (info->plx_regbase)
- comedi_pci_disable(info->pci_dev_p);
- pci_dev_put(info->pci_dev_p);
- }
- }
-
- return 0;
-}
-
/*=============================================================================
Analog input section
===========================================================================*/
@@ -2424,43 +2180,185 @@ static int me4000_cnt_insn_write(struct comedi_device *dev,
return 1;
}
-static int __devinit driver_me4000_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
- return comedi_pci_auto_config(dev, driver_me4000.driver_name);
+ struct comedi_subdevice *s;
+ int result;
+
+ CALL_PDEBUG("In me4000_attach()\n");
+
+ result = me4000_probe(dev, it);
+ if (result)
+ return result;
+
+ /*
+ * Allocate the subdevice structures. alloc_subdevice() is a
+ * convenient macro defined in comedidev.h. It relies on
+ * n_subdevices being set correctly.
+ */
+ if (alloc_subdevices(dev, 4) < 0)
+ return -ENOMEM;
+
+ /*=========================================================================
+ Analog input subdevice
+ ========================================================================*/
+
+ s = dev->subdevices + 0;
+
+ if (thisboard->ai.count) {
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags =
+ SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
+ s->n_chan = thisboard->ai.count;
+ s->maxdata = 0xFFFF; /* 16 bit ADC */
+ s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
+ s->range_table = &me4000_ai_range;
+ s->insn_read = me4000_ai_insn_read;
+
+ if (info->irq > 0) {
+ if (request_irq(info->irq, me4000_ai_isr,
+ IRQF_SHARED, "ME-4000", dev)) {
+ printk
+ ("comedi%d: me4000: me4000_attach(): "
+ "Unable to allocate irq\n", dev->minor);
+ } else {
+ dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
+ s->cancel = me4000_ai_cancel;
+ s->do_cmdtest = me4000_ai_do_cmd_test;
+ s->do_cmd = me4000_ai_do_cmd;
+ }
+ } else {
+ printk(KERN_WARNING
+ "comedi%d: me4000: me4000_attach(): "
+ "No interrupt available\n", dev->minor);
+ }
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ /*=========================================================================
+ Analog output subdevice
+ ========================================================================*/
+
+ s = dev->subdevices + 1;
+
+ if (thisboard->ao.count) {
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
+ s->n_chan = thisboard->ao.count;
+ s->maxdata = 0xFFFF; /* 16 bit DAC */
+ s->range_table = &me4000_ao_range;
+ s->insn_write = me4000_ao_insn_write;
+ s->insn_read = me4000_ao_insn_read;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ /*=========================================================================
+ Digital I/O subdevice
+ ========================================================================*/
+
+ s = dev->subdevices + 2;
+
+ if (thisboard->dio.count) {
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = thisboard->dio.count * 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = me4000_dio_insn_bits;
+ s->insn_config = me4000_dio_insn_config;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ /*
+ * Check for optoisolated ME-4000 version. If one the first
+ * port is a fixed output port and the second is a fixed input port.
+ */
+ if (!me4000_inl(dev, info->dio_context.dir_reg)) {
+ s->io_bits |= 0xFF;
+ me4000_outl(dev, ME4000_DIO_CTRL_BIT_MODE_0,
+ info->dio_context.dir_reg);
+ }
+
+ /*=========================================================================
+ Counter subdevice
+ ========================================================================*/
+
+ s = dev->subdevices + 3;
+
+ if (thisboard->cnt.count) {
+ s->type = COMEDI_SUBD_COUNTER;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = thisboard->cnt.count;
+ s->maxdata = 0xFFFF; /* 16 bit counters */
+ s->insn_read = me4000_cnt_insn_read;
+ s->insn_write = me4000_cnt_insn_write;
+ s->insn_config = me4000_cnt_insn_config;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ return 0;
}
-static void __devexit driver_me4000_pci_remove(struct pci_dev *dev)
+static void me4000_detach(struct comedi_device *dev)
{
- comedi_pci_auto_unconfig(dev);
+ if (info) {
+ if (info->pci_dev_p) {
+ reset_board(dev);
+ if (info->plx_regbase)
+ comedi_pci_disable(info->pci_dev_p);
+ pci_dev_put(info->pci_dev_p);
+ }
+ }
}
-static struct pci_driver driver_me4000_pci_driver = {
- .id_table = me4000_pci_table,
- .probe = &driver_me4000_pci_probe,
- .remove = __devexit_p(&driver_me4000_pci_remove)
+static struct comedi_driver me4000_driver = {
+ .driver_name = "me4000",
+ .module = THIS_MODULE,
+ .attach = me4000_attach,
+ .detach = me4000_detach,
};
-static int __init driver_me4000_init_module(void)
+static int __devinit me4000_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- int retval;
-
- retval = comedi_driver_register(&driver_me4000);
- if (retval < 0)
- return retval;
-
- driver_me4000_pci_driver.name = (char *)driver_me4000.driver_name;
- return pci_register_driver(&driver_me4000_pci_driver);
+ return comedi_pci_auto_config(dev, &me4000_driver);
}
-static void __exit driver_me4000_cleanup_module(void)
+static void __devexit me4000_pci_remove(struct pci_dev *dev)
{
- pci_unregister_driver(&driver_me4000_pci_driver);
- comedi_driver_unregister(&driver_me4000);
+ comedi_pci_auto_unconfig(dev);
}
-module_init(driver_me4000_init_module);
-module_exit(driver_me4000_cleanup_module);
+static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4650) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4660) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4661) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4662) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4663) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4670) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4671) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4672) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4673) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4680) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4681) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4682) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4683) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, me4000_pci_table);
+
+static struct pci_driver me4000_pci_driver = {
+ .name = "me4000",
+ .id_table = me4000_pci_table,
+ .probe = me4000_pci_probe,
+ .remove = __devexit_p(me4000_pci_remove),
+};
+module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
index 8b812e41c52b..ffe251250e6f 100644
--- a/drivers/staging/comedi/drivers/me_daq.c
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -146,10 +146,6 @@ from http://www.comedi.org
#define ME_COUNTER_STARTDATA_B 0x0022 /* - | W */
#define ME_COUNTER_VALUE_B 0x0022 /* R | - */
-/* Function prototypes */
-static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int me_detach(struct comedi_device *dev);
-
static const struct comedi_lrange me2000_ai_range = {
8,
{
@@ -187,14 +183,6 @@ static const struct comedi_lrange me2600_ao_range = {
}
};
-static DEFINE_PCI_DEVICE_TABLE(me_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2600_DEVICE_ID) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2000_DEVICE_ID) },
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, me_pci_table);
-
/* Board specification structure */
struct me_board {
const char *name; /* driver name */
@@ -247,51 +235,6 @@ static const struct me_board me_boards[] = {
#define me_board_nbr (sizeof(me_boards)/sizeof(struct me_board))
-static struct comedi_driver me_driver = {
- .driver_name = ME_DRIVER_NAME,
- .module = THIS_MODULE,
- .attach = me_attach,
- .detach = me_detach,
-};
-
-static int __devinit me_driver_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, me_driver.driver_name);
-}
-
-static void __devexit me_driver_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver me_driver_pci_driver = {
- .id_table = me_pci_table,
- .probe = &me_driver_pci_probe,
- .remove = __devexit_p(&me_driver_pci_remove)
-};
-
-static int __init me_driver_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&me_driver);
- if (retval < 0)
- return retval;
-
- me_driver_pci_driver.name = (char *)me_driver.driver_name;
- return pci_register_driver(&me_driver_pci_driver);
-}
-
-static void __exit me_driver_cleanup_module(void)
-{
- pci_unregister_driver(&me_driver_pci_driver);
- comedi_driver_unregister(&me_driver);
-}
-
-module_init(me_driver_init_module);
-module_exit(me_driver_cleanup_module);
-
/* Private data structure */
struct me_private_data {
struct pci_dev *pci_device;
@@ -669,12 +612,6 @@ static int me_reset(struct comedi_device *dev)
return 0;
}
-/*
- * Attach
- *
- * - Register PCI device
- * - Declare device driver capability
- */
static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
struct pci_dev *pci_device = NULL;
@@ -869,8 +806,7 @@ found:
return 0;
}
-/* Detach */
-static int me_detach(struct comedi_device *dev)
+static void me_detach(struct comedi_device *dev)
{
if (dev_private) {
if (dev_private->me_regbase) {
@@ -882,13 +818,44 @@ static int me_detach(struct comedi_device *dev)
if (dev_private->pci_device) {
if (dev_private->plx_regbase_size)
comedi_pci_disable(dev_private->pci_device);
-
pci_dev_put(dev_private->pci_device);
}
}
- return 0;
}
+static struct comedi_driver me_daq_driver = {
+ .driver_name = "me_daq",
+ .module = THIS_MODULE,
+ .attach = me_attach,
+ .detach = me_detach,
+};
+
+static int __devinit me_daq_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &me_daq_driver);
+}
+
+static void __devexit me_daq_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(me_daq_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2600_DEVICE_ID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2000_DEVICE_ID) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, me_daq_pci_table);
+
+static struct pci_driver me_daq_pci_driver = {
+ .name = "me_daq",
+ .id_table = me_daq_pci_table,
+ .probe = me_daq_pci_probe,
+ .remove = __devexit_p(me_daq_pci_remove),
+};
+module_comedi_pci_driver(me_daq_driver, me_daq_pci_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h
index 999551f54c2a..83f1b27a4720 100644
--- a/drivers/staging/comedi/drivers/mite.h
+++ b/drivers/staging/comedi/drivers/mite.h
@@ -66,9 +66,9 @@ struct mite_struct {
struct pci_dev *pcidev;
resource_size_t mite_phys_addr;
- void *mite_io_addr;
+ void __iomem *mite_io_addr;
resource_size_t daq_phys_addr;
- void *daq_io_addr;
+ void __iomem *daq_io_addr;
struct mite_channel channels[MAX_MITE_DMA_CHANNELS];
short channel_allocated[MAX_MITE_DMA_CHANNELS];
diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
index dd09a6d46e5c..4304e864a4d4 100644
--- a/drivers/staging/comedi/drivers/mpc624.c
+++ b/drivers/staging/comedi/drivers/mpc624.c
@@ -148,131 +148,6 @@ static const struct comedi_lrange range_mpc624_bipolar10 = {
}
};
-/* -------------------------------------------------------------------------- */
-static int mpc624_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int mpc624_detach(struct comedi_device *dev);
-/* -------------------------------------------------------------------------- */
-static struct comedi_driver driver_mpc624 = {
- .driver_name = "mpc624",
- .module = THIS_MODULE,
- .attach = mpc624_attach,
- .detach = mpc624_detach
-};
-
-/* -------------------------------------------------------------------------- */
-static int mpc624_ai_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data);
-/* -------------------------------------------------------------------------- */
-static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- unsigned long iobase;
-
- iobase = it->options[0];
- printk(KERN_INFO "comedi%d: mpc624 [0x%04lx, ", dev->minor, iobase);
- if (request_region(iobase, MPC624_SIZE, "mpc624") == NULL) {
- printk(KERN_ERR "I/O port(s) in use\n");
- return -EIO;
- }
-
- dev->iobase = iobase;
- dev->board_name = "mpc624";
-
- /* Private structure initialization */
- if (alloc_private(dev, sizeof(struct skel_private)) < 0)
- return -ENOMEM;
-
- switch (it->options[1]) {
- case 0:
- devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz;
- printk(KERN_INFO "3.52 kHz, ");
- break;
- case 1:
- devpriv->ulConvertionRate = MPC624_SPEED_1_76_kHz;
- printk(KERN_INFO "1.76 kHz, ");
- break;
- case 2:
- devpriv->ulConvertionRate = MPC624_SPEED_880_Hz;
- printk(KERN_INFO "880 Hz, ");
- break;
- case 3:
- devpriv->ulConvertionRate = MPC624_SPEED_440_Hz;
- printk(KERN_INFO "440 Hz, ");
- break;
- case 4:
- devpriv->ulConvertionRate = MPC624_SPEED_220_Hz;
- printk(KERN_INFO "220 Hz, ");
- break;
- case 5:
- devpriv->ulConvertionRate = MPC624_SPEED_110_Hz;
- printk(KERN_INFO "110 Hz, ");
- break;
- case 6:
- devpriv->ulConvertionRate = MPC624_SPEED_55_Hz;
- printk(KERN_INFO "55 Hz, ");
- break;
- case 7:
- devpriv->ulConvertionRate = MPC624_SPEED_27_5_Hz;
- printk(KERN_INFO "27.5 Hz, ");
- break;
- case 8:
- devpriv->ulConvertionRate = MPC624_SPEED_13_75_Hz;
- printk(KERN_INFO "13.75 Hz, ");
- break;
- case 9:
- devpriv->ulConvertionRate = MPC624_SPEED_6_875_Hz;
- printk(KERN_INFO "6.875 Hz, ");
- break;
- default:
- printk
- (KERN_ERR "illegal conversion rate setting!"
- " Valid numbers are 0..9. Using 9 => 6.875 Hz, ");
- devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz;
- }
-
- /* Subdevices structures */
- if (alloc_subdevices(dev, 1) < 0)
- return -ENOMEM;
-
- s = dev->subdevices + 0;
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_DIFF;
- s->n_chan = 8;
- switch (it->options[1]) {
- default:
- s->maxdata = 0x3FFFFFFF;
- printk(KERN_INFO "30 bit, ");
- }
-
- switch (it->options[1]) {
- case 0:
- s->range_table = &range_mpc624_bipolar1;
- printk(KERN_INFO "1.01V]: ");
- break;
- default:
- s->range_table = &range_mpc624_bipolar10;
- printk(KERN_INFO "10.1V]: ");
- }
- s->len_chanlist = 1;
- s->insn_read = mpc624_ai_rinsn;
-
- printk(KERN_INFO "attached\n");
-
- return 1;
-}
-
-static int mpc624_detach(struct comedi_device *dev)
-{
- printk(KERN_INFO "comedi%d: mpc624: remove\n", dev->minor);
-
- if (dev->iobase)
- release_region(dev->iobase, MPC624_SIZE);
-
- return 0;
-}
-
/* Timeout 200ms */
#define TIMEOUT 200
@@ -406,18 +281,117 @@ static int mpc624_ai_rinsn(struct comedi_device *dev,
return n;
}
-static int __init driver_mpc624_init_module(void)
+static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
- return comedi_driver_register(&driver_mpc624);
+ struct comedi_subdevice *s;
+ unsigned long iobase;
+
+ iobase = it->options[0];
+ printk(KERN_INFO "comedi%d: mpc624 [0x%04lx, ", dev->minor, iobase);
+ if (request_region(iobase, MPC624_SIZE, "mpc624") == NULL) {
+ printk(KERN_ERR "I/O port(s) in use\n");
+ return -EIO;
+ }
+
+ dev->iobase = iobase;
+ dev->board_name = "mpc624";
+
+ /* Private structure initialization */
+ if (alloc_private(dev, sizeof(struct skel_private)) < 0)
+ return -ENOMEM;
+
+ switch (it->options[1]) {
+ case 0:
+ devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz;
+ printk(KERN_INFO "3.52 kHz, ");
+ break;
+ case 1:
+ devpriv->ulConvertionRate = MPC624_SPEED_1_76_kHz;
+ printk(KERN_INFO "1.76 kHz, ");
+ break;
+ case 2:
+ devpriv->ulConvertionRate = MPC624_SPEED_880_Hz;
+ printk(KERN_INFO "880 Hz, ");
+ break;
+ case 3:
+ devpriv->ulConvertionRate = MPC624_SPEED_440_Hz;
+ printk(KERN_INFO "440 Hz, ");
+ break;
+ case 4:
+ devpriv->ulConvertionRate = MPC624_SPEED_220_Hz;
+ printk(KERN_INFO "220 Hz, ");
+ break;
+ case 5:
+ devpriv->ulConvertionRate = MPC624_SPEED_110_Hz;
+ printk(KERN_INFO "110 Hz, ");
+ break;
+ case 6:
+ devpriv->ulConvertionRate = MPC624_SPEED_55_Hz;
+ printk(KERN_INFO "55 Hz, ");
+ break;
+ case 7:
+ devpriv->ulConvertionRate = MPC624_SPEED_27_5_Hz;
+ printk(KERN_INFO "27.5 Hz, ");
+ break;
+ case 8:
+ devpriv->ulConvertionRate = MPC624_SPEED_13_75_Hz;
+ printk(KERN_INFO "13.75 Hz, ");
+ break;
+ case 9:
+ devpriv->ulConvertionRate = MPC624_SPEED_6_875_Hz;
+ printk(KERN_INFO "6.875 Hz, ");
+ break;
+ default:
+ printk
+ (KERN_ERR "illegal conversion rate setting!"
+ " Valid numbers are 0..9. Using 9 => 6.875 Hz, ");
+ devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz;
+ }
+
+ /* Subdevices structures */
+ if (alloc_subdevices(dev, 1) < 0)
+ return -ENOMEM;
+
+ s = dev->subdevices + 0;
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_DIFF;
+ s->n_chan = 8;
+ switch (it->options[1]) {
+ default:
+ s->maxdata = 0x3FFFFFFF;
+ printk(KERN_INFO "30 bit, ");
+ }
+
+ switch (it->options[1]) {
+ case 0:
+ s->range_table = &range_mpc624_bipolar1;
+ printk(KERN_INFO "1.01V]: ");
+ break;
+ default:
+ s->range_table = &range_mpc624_bipolar10;
+ printk(KERN_INFO "10.1V]: ");
+ }
+ s->len_chanlist = 1;
+ s->insn_read = mpc624_ai_rinsn;
+
+ printk(KERN_INFO "attached\n");
+
+ return 1;
}
-static void __exit driver_mpc624_cleanup_module(void)
+static void mpc624_detach(struct comedi_device *dev)
{
- comedi_driver_unregister(&driver_mpc624);
+ if (dev->iobase)
+ release_region(dev->iobase, MPC624_SIZE);
}
-module_init(driver_mpc624_init_module);
-module_exit(driver_mpc624_cleanup_module);
+static struct comedi_driver mpc624_driver = {
+ .driver_name = "mpc624",
+ .module = THIS_MODULE,
+ .attach = mpc624_attach,
+ .detach = mpc624_detach
+};
+module_comedi_driver(mpc624_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c
index 5f6816a3fe8c..364470e4458f 100644
--- a/drivers/staging/comedi/drivers/mpc8260cpm.c
+++ b/drivers/staging/comedi/drivers/mpc8260cpm.c
@@ -46,75 +46,6 @@ struct mpc8260cpm_private {
#define devpriv ((struct mpc8260cpm_private *)dev->private)
-static int mpc8260cpm_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int mpc8260cpm_detach(struct comedi_device *dev);
-static struct comedi_driver driver_mpc8260cpm = {
- .driver_name = "mpc8260cpm",
- .module = THIS_MODULE,
- .attach = mpc8260cpm_attach,
- .detach = mpc8260cpm_detach,
-};
-
-static int __init driver_mpc8260cpm_init_module(void)
-{
- return comedi_driver_register(&driver_mpc8260cpm);
-}
-
-static void __exit driver_mpc8260cpm_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_mpc8260cpm);
-}
-
-module_init(driver_mpc8260cpm_init_module);
-module_exit(driver_mpc8260cpm_cleanup_module);
-
-static int mpc8260cpm_dio_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int mpc8260cpm_dio_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static int mpc8260cpm_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- int i;
-
- printk("comedi%d: mpc8260cpm: ", dev->minor);
-
- dev->board_ptr = mpc8260cpm_boards + dev->board;
-
- dev->board_name = thisboard->name;
-
- if (alloc_private(dev, sizeof(struct mpc8260cpm_private)) < 0)
- return -ENOMEM;
-
- if (alloc_subdevices(dev, 4) < 0)
- return -ENOMEM;
-
- for (i = 0; i < 4; i++) {
- s = dev->subdevices + i;
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 32;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_config = mpc8260cpm_dio_config;
- s->insn_bits = mpc8260cpm_dio_bits;
- }
-
- return 1;
-}
-
-static int mpc8260cpm_detach(struct comedi_device *dev)
-{
- printk("comedi%d: mpc8260cpm: remove\n", dev->minor);
-
- return 0;
-}
-
static unsigned long *cpm_pdat(int port)
{
switch (port) {
@@ -184,3 +115,48 @@ static int mpc8260cpm_dio_bits(struct comedi_device *dev,
return 2;
}
+
+static int mpc8260cpm_attach(struct comedi_device *dev,
+ struct comedi_devconfig *it)
+{
+ struct comedi_subdevice *s;
+ int i;
+
+ printk("comedi%d: mpc8260cpm: ", dev->minor);
+
+ dev->board_ptr = mpc8260cpm_boards + dev->board;
+
+ dev->board_name = thisboard->name;
+
+ if (alloc_private(dev, sizeof(struct mpc8260cpm_private)) < 0)
+ return -ENOMEM;
+
+ if (alloc_subdevices(dev, 4) < 0)
+ return -ENOMEM;
+
+ for (i = 0; i < 4; i++) {
+ s = dev->subdevices + i;
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 32;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_config = mpc8260cpm_dio_config;
+ s->insn_bits = mpc8260cpm_dio_bits;
+ }
+
+ return 1;
+}
+
+static void mpc8260cpm_detach(struct comedi_device *dev)
+{
+ /* Nothing to cleanup */
+}
+
+static struct comedi_driver mpc8260cpm_driver = {
+ .driver_name = "mpc8260cpm",
+ .module = THIS_MODULE,
+ .attach = mpc8260cpm_attach,
+ .detach = mpc8260cpm_detach,
+};
+module_comedi_driver(mpc8260cpm_driver);
diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
index dace902d3bce..e951e73d66f5 100644
--- a/drivers/staging/comedi/drivers/multiq3.c
+++ b/drivers/staging/comedi/drivers/multiq3.c
@@ -83,29 +83,6 @@ Devices: [Quanser Consulting] MultiQ-3 (multiq3)
#define MULTIQ3_TIMEOUT 30
-static int multiq3_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int multiq3_detach(struct comedi_device *dev);
-static struct comedi_driver driver_multiq3 = {
- .driver_name = "multiq3",
- .module = THIS_MODULE,
- .attach = multiq3_attach,
- .detach = multiq3_detach,
-};
-
-static int __init driver_multiq3_init_module(void)
-{
- return comedi_driver_register(&driver_multiq3);
-}
-
-static void __exit driver_multiq3_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_multiq3);
-}
-
-module_init(driver_multiq3_init_module);
-module_exit(driver_multiq3_cleanup_module);
-
struct multiq3_private {
unsigned int ao_readback[2];
};
@@ -338,18 +315,22 @@ static int multiq3_attach(struct comedi_device *dev,
return 0;
}
-static int multiq3_detach(struct comedi_device *dev)
+static void multiq3_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: multiq3: remove\n", dev->minor);
-
if (dev->iobase)
release_region(dev->iobase, MULTIQ3_SIZE);
if (dev->irq)
free_irq(dev->irq, dev);
-
- return 0;
}
+static struct comedi_driver multiq3_driver = {
+ .driver_name = "multiq3",
+ .module = THIS_MODULE,
+ .attach = multiq3_attach,
+ .detach = multiq3_detach,
+};
+module_comedi_driver(multiq3_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
index 54741c9e1af5..b02aa0efcd86 100644
--- a/drivers/staging/comedi/drivers/ni_6527.c
+++ b/drivers/staging/comedi/drivers/ni_6527.c
@@ -78,7 +78,7 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800
static int ni6527_attach(struct comedi_device *dev,
struct comedi_devconfig *it);
-static int ni6527_detach(struct comedi_device *dev);
+static void ni6527_detach(struct comedi_device *dev);
static struct comedi_driver driver_ni6527 = {
.driver_name = "ni6527",
.module = THIS_MODULE,
@@ -449,19 +449,15 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int ni6527_detach(struct comedi_device *dev)
+static void ni6527_detach(struct comedi_device *dev)
{
if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr)
writeb(0x00,
devpriv->mite->daq_io_addr + Master_Interrupt_Control);
-
if (dev->irq)
free_irq(dev->irq, dev);
-
if (devpriv && devpriv->mite)
mite_unsetup(devpriv->mite);
-
- return 0;
}
static int ni6527_find_device(struct comedi_device *dev, int bus, int slot)
@@ -493,7 +489,7 @@ static int ni6527_find_device(struct comedi_device *dev, int bus, int slot)
static int __devinit driver_ni6527_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_ni6527.driver_name);
+ return comedi_pci_auto_config(dev, &driver_ni6527);
}
static void __devexit driver_ni6527_pci_remove(struct pci_dev *dev)
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index 403fc0997d37..0d27a9323bc0 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -111,7 +111,7 @@ static inline unsigned Filter_Enable(unsigned port)
static int ni_65xx_attach(struct comedi_device *dev,
struct comedi_devconfig *it);
-static int ni_65xx_detach(struct comedi_device *dev);
+static void ni_65xx_detach(struct comedi_device *dev);
static struct comedi_driver driver_ni_65xx = {
.driver_name = "ni_65xx",
.module = THIS_MODULE,
@@ -784,7 +784,7 @@ static int ni_65xx_attach(struct comedi_device *dev,
return 0;
}
-static int ni_65xx_detach(struct comedi_device *dev)
+static void ni_65xx_detach(struct comedi_device *dev)
{
if (private(dev) && private(dev)->mite
&& private(dev)->mite->daq_io_addr) {
@@ -792,10 +792,8 @@ static int ni_65xx_detach(struct comedi_device *dev)
private(dev)->mite->daq_io_addr +
Master_Interrupt_Control);
}
-
if (dev->irq)
free_irq(dev->irq, dev);
-
if (private(dev)) {
unsigned i;
for (i = 0; i < dev->n_subdevices; ++i) {
@@ -805,7 +803,6 @@ static int ni_65xx_detach(struct comedi_device *dev)
if (private(dev)->mite)
mite_unsetup(private(dev)->mite);
}
- return 0;
}
static int ni_65xx_find_device(struct comedi_device *dev, int bus, int slot)
@@ -837,7 +834,7 @@ static int ni_65xx_find_device(struct comedi_device *dev, int bus, int slot)
static int __devinit driver_ni_65xx_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_ni_65xx.driver_name);
+ return comedi_pci_auto_config(dev, &driver_ni_65xx);
}
static void __devexit driver_ni_65xx_pci_remove(struct pci_dev *dev)
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index 35f3a4749825..8c40730e296a 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -458,7 +458,7 @@ static inline const struct ni_660x_board *board(struct comedi_device *dev)
static int ni_660x_attach(struct comedi_device *dev,
struct comedi_devconfig *it);
-static int ni_660x_detach(struct comedi_device *dev);
+static void ni_660x_detach(struct comedi_device *dev);
static void init_tio_chip(struct comedi_device *dev, int chipset);
static void ni_660x_select_pfi_output(struct comedi_device *dev,
unsigned pfi_channel,
@@ -474,7 +474,7 @@ static struct comedi_driver driver_ni_660x = {
static int __devinit driver_ni_660x_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_ni_660x.driver_name);
+ return comedi_pci_auto_config(dev, &driver_ni_660x);
}
static void __devexit driver_ni_660x_pci_remove(struct pci_dev *dev)
@@ -761,7 +761,7 @@ static inline void ni_660x_write_register(struct comedi_device *dev,
unsigned chip_index, unsigned bits,
enum NI_660x_Register reg)
{
- void *const write_address =
+ void __iomem *write_address =
private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
registerData[reg].offset;
@@ -784,7 +784,7 @@ static inline unsigned ni_660x_read_register(struct comedi_device *dev,
unsigned chip_index,
enum NI_660x_Register reg)
{
- void *const read_address =
+ void __iomem *read_address =
private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
registerData[reg].offset;
@@ -1188,14 +1188,10 @@ static int ni_660x_attach(struct comedi_device *dev,
return 0;
}
-static int ni_660x_detach(struct comedi_device *dev)
+static void ni_660x_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: ni_660x: remove\n", dev->minor);
-
- /* Free irq */
if (dev->irq)
free_irq(dev->irq, dev);
-
if (dev->private) {
if (private(dev)->counter_dev)
ni_gpct_device_destroy(private(dev)->counter_dev);
@@ -1204,7 +1200,6 @@ static int ni_660x_detach(struct comedi_device *dev)
mite_unsetup(private(dev)->mite);
}
}
- return 0;
}
static int
diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
index d8d91f90060e..a9cf94fd0c30 100644
--- a/drivers/staging/comedi/drivers/ni_670x.c
+++ b/drivers/staging/comedi/drivers/ni_670x.c
@@ -111,7 +111,7 @@ struct ni_670x_private {
static int ni_670x_attach(struct comedi_device *dev,
struct comedi_devconfig *it);
-static int ni_670x_detach(struct comedi_device *dev);
+static void ni_670x_detach(struct comedi_device *dev);
static struct comedi_driver driver_ni_670x = {
.driver_name = "ni_670x",
@@ -123,7 +123,7 @@ static struct comedi_driver driver_ni_670x = {
static int __devinit driver_ni_670x_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_ni_670x.driver_name);
+ return comedi_pci_auto_config(dev, &driver_ni_670x);
}
static void __devexit driver_ni_670x_pci_remove(struct pci_dev *dev)
@@ -249,19 +249,13 @@ static int ni_670x_attach(struct comedi_device *dev,
return 1;
}
-static int ni_670x_detach(struct comedi_device *dev)
+static void ni_670x_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: ni_670x: remove\n", dev->minor);
-
kfree(dev->subdevices[0].range_table_list);
-
if (dev->private && devpriv->mite)
mite_unsetup(devpriv->mite);
-
if (dev->irq)
free_irq(dev->irq, dev);
-
- return 0;
}
static int ni_670x_ao_winsn(struct comedi_device *dev,
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index c25e44c1905e..ae896a094150 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -171,46 +171,13 @@ struct a2150_private {
#define devpriv ((struct a2150_private *)dev->private)
-static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int a2150_detach(struct comedi_device *dev);
static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
-static struct comedi_driver driver_a2150 = {
- .driver_name = "ni_at_a2150",
- .module = THIS_MODULE,
- .attach = a2150_attach,
- .detach = a2150_detach,
-};
-
-static irqreturn_t a2150_interrupt(int irq, void *d);
-static int a2150_ai_cmdtest(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_cmd *cmd);
-static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
-static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
int flags);
-static int a2150_probe(struct comedi_device *dev);
static int a2150_set_chanlist(struct comedi_device *dev,
unsigned int start_channel,
unsigned int num_channels);
-/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
- */
-static int __init driver_a2150_init_module(void)
-{
- return comedi_driver_register(&driver_a2150);
-}
-
-static void __exit driver_a2150_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_a2150);
-}
-
-module_init(driver_a2150_init_module);
-module_exit(driver_a2150_cleanup_module);
-
#ifdef A2150_DEBUG
static void ni_dump_regs(struct comedi_device *dev)
@@ -331,161 +298,6 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
return IRQ_HANDLED;
}
-/* probes board type, returns offset */
-static int a2150_probe(struct comedi_device *dev)
-{
- int status = inw(dev->iobase + STATUS_REG);
- return ID_BITS(status);
-}
-
-static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- unsigned long iobase = it->options[0];
- unsigned int irq = it->options[1];
- unsigned int dma = it->options[2];
- static const int timeout = 2000;
- int i;
-
- printk("comedi%d: %s: io 0x%lx", dev->minor, driver_a2150.driver_name,
- iobase);
- if (irq) {
- printk(", irq %u", irq);
- } else {
- printk(", no irq");
- }
- if (dma) {
- printk(", dma %u", dma);
- } else {
- printk(", no dma");
- }
- printk("\n");
-
- /* allocate and initialize dev->private */
- if (alloc_private(dev, sizeof(struct a2150_private)) < 0)
- return -ENOMEM;
-
- if (iobase == 0) {
- printk(" io base address required\n");
- return -EINVAL;
- }
-
- /* check if io addresses are available */
- if (!request_region(iobase, A2150_SIZE, driver_a2150.driver_name)) {
- printk(" I/O port conflict\n");
- return -EIO;
- }
- dev->iobase = iobase;
-
- /* grab our IRQ */
- if (irq) {
- /* check that irq is supported */
- if (irq < 3 || irq == 8 || irq == 13 || irq > 15) {
- printk(" invalid irq line %u\n", irq);
- return -EINVAL;
- }
- if (request_irq(irq, a2150_interrupt, 0,
- driver_a2150.driver_name, dev)) {
- printk("unable to allocate irq %u\n", irq);
- return -EINVAL;
- }
- devpriv->irq_dma_bits |= IRQ_LVL_BITS(irq);
- dev->irq = irq;
- }
- /* initialize dma */
- if (dma) {
- if (dma == 4 || dma > 7) {
- printk(" invalid dma channel %u\n", dma);
- return -EINVAL;
- }
- if (request_dma(dma, driver_a2150.driver_name)) {
- printk(" failed to allocate dma channel %u\n", dma);
- return -EINVAL;
- }
- devpriv->dma = dma;
- devpriv->dma_buffer =
- kmalloc(A2150_DMA_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
- if (devpriv->dma_buffer == NULL)
- return -ENOMEM;
-
- disable_dma(dma);
- set_dma_mode(dma, DMA_MODE_READ);
-
- devpriv->irq_dma_bits |= DMA_CHAN_BITS(dma);
- }
-
- dev->board_ptr = a2150_boards + a2150_probe(dev);
- dev->board_name = thisboard->name;
-
- if (alloc_subdevices(dev, 1) < 0)
- return -ENOMEM;
-
- /* analog input subdevice */
- s = dev->subdevices + 0;
- dev->read_subdev = s;
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER | SDF_CMD_READ;
- s->n_chan = 4;
- s->len_chanlist = 4;
- s->maxdata = 0xffff;
- s->range_table = &range_a2150;
- s->do_cmd = a2150_ai_cmd;
- s->do_cmdtest = a2150_ai_cmdtest;
- s->insn_read = a2150_ai_rinsn;
- s->cancel = a2150_cancel;
-
- /* need to do this for software counting of completed conversions, to
- * prevent hardware count from stopping acquisition */
- outw(HW_COUNT_DISABLE, dev->iobase + I8253_MODE_REG);
-
- /* set card's irq and dma levels */
- outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
-
- /* reset and sync adc clock circuitry */
- outw_p(DPD_BIT | APD_BIT, dev->iobase + CONFIG_REG);
- outw_p(DPD_BIT, dev->iobase + CONFIG_REG);
- /* initialize configuration register */
- devpriv->config_bits = 0;
- outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
- /* wait until offset calibration is done, then enable analog inputs */
- for (i = 0; i < timeout; i++) {
- if ((DCAL_BIT & inw(dev->iobase + STATUS_REG)) == 0)
- break;
- udelay(1000);
- }
- if (i == timeout) {
- printk
- (" timed out waiting for offset calibration to complete\n");
- return -ETIME;
- }
- devpriv->config_bits |= ENABLE0_BIT | ENABLE1_BIT;
- outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
-
- return 0;
-};
-
-static int a2150_detach(struct comedi_device *dev)
-{
- printk("comedi%d: %s: remove\n", dev->minor, driver_a2150.driver_name);
-
- /* only free stuff if it has been allocated by _attach */
- if (dev->iobase) {
- /* put board in power-down mode */
- outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG);
- release_region(dev->iobase, A2150_SIZE);
- }
-
- if (dev->irq)
- free_irq(dev->irq, dev);
- if (devpriv) {
- if (devpriv->dma)
- free_dma(devpriv->dma);
- kfree(devpriv->dma_buffer);
- }
-
- return 0;
-};
-
static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{
/* disable dma on card */
@@ -539,7 +351,10 @@ static int a2150_ai_cmdtest(struct comedi_device *dev,
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and mutually compatible */
+ /*
+ * step 2: make sure trigger sources are unique and mutually
+ * compatible
+ */
if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
err++;
@@ -771,7 +586,10 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
/* start acquisition for soft trigger */
outw(0, dev->iobase + FIFO_START_REG);
- /* there is a 35.6 sample delay for data to get through the antialias filter */
+ /*
+ * there is a 35.6 sample delay for data to get through the
+ * antialias filter
+ */
for (n = 0; n < filter_delay; n++) {
for (i = 0; i < timeout; i++) {
if (inw(dev->iobase + STATUS_REG) & FNE_BIT)
@@ -812,8 +630,10 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
return n;
}
-/* sets bits in devpriv->clock_bits to nearest approximation of requested period,
- * adjusts requested period to actual timing. */
+/*
+ * sets bits in devpriv->clock_bits to nearest approximation of requested
+ * period, adjusts requested period to actual timing.
+ */
static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
int flags)
{
@@ -920,6 +740,162 @@ static int a2150_set_chanlist(struct comedi_device *dev,
return 0;
}
+/* probes board type, returns offset */
+static int a2150_probe(struct comedi_device *dev)
+{
+ int status = inw(dev->iobase + STATUS_REG);
+ return ID_BITS(status);
+}
+
+static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+{
+ struct comedi_subdevice *s;
+ unsigned long iobase = it->options[0];
+ unsigned int irq = it->options[1];
+ unsigned int dma = it->options[2];
+ static const int timeout = 2000;
+ int i;
+
+ printk("comedi%d: %s: io 0x%lx", dev->minor, dev->driver->driver_name,
+ iobase);
+ if (irq) {
+ printk(", irq %u", irq);
+ } else {
+ printk(", no irq");
+ }
+ if (dma) {
+ printk(", dma %u", dma);
+ } else {
+ printk(", no dma");
+ }
+ printk("\n");
+
+ /* allocate and initialize dev->private */
+ if (alloc_private(dev, sizeof(struct a2150_private)) < 0)
+ return -ENOMEM;
+
+ if (iobase == 0) {
+ printk(" io base address required\n");
+ return -EINVAL;
+ }
+
+ /* check if io addresses are available */
+ if (!request_region(iobase, A2150_SIZE, dev->driver->driver_name)) {
+ printk(" I/O port conflict\n");
+ return -EIO;
+ }
+ dev->iobase = iobase;
+
+ /* grab our IRQ */
+ if (irq) {
+ /* check that irq is supported */
+ if (irq < 3 || irq == 8 || irq == 13 || irq > 15) {
+ printk(" invalid irq line %u\n", irq);
+ return -EINVAL;
+ }
+ if (request_irq(irq, a2150_interrupt, 0,
+ dev->driver->driver_name, dev)) {
+ printk("unable to allocate irq %u\n", irq);
+ return -EINVAL;
+ }
+ devpriv->irq_dma_bits |= IRQ_LVL_BITS(irq);
+ dev->irq = irq;
+ }
+ /* initialize dma */
+ if (dma) {
+ if (dma == 4 || dma > 7) {
+ printk(" invalid dma channel %u\n", dma);
+ return -EINVAL;
+ }
+ if (request_dma(dma, dev->driver->driver_name)) {
+ printk(" failed to allocate dma channel %u\n", dma);
+ return -EINVAL;
+ }
+ devpriv->dma = dma;
+ devpriv->dma_buffer =
+ kmalloc(A2150_DMA_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
+ if (devpriv->dma_buffer == NULL)
+ return -ENOMEM;
+
+ disable_dma(dma);
+ set_dma_mode(dma, DMA_MODE_READ);
+
+ devpriv->irq_dma_bits |= DMA_CHAN_BITS(dma);
+ }
+
+ dev->board_ptr = a2150_boards + a2150_probe(dev);
+ dev->board_name = thisboard->name;
+
+ if (alloc_subdevices(dev, 1) < 0)
+ return -ENOMEM;
+
+ /* analog input subdevice */
+ s = dev->subdevices + 0;
+ dev->read_subdev = s;
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER | SDF_CMD_READ;
+ s->n_chan = 4;
+ s->len_chanlist = 4;
+ s->maxdata = 0xffff;
+ s->range_table = &range_a2150;
+ s->do_cmd = a2150_ai_cmd;
+ s->do_cmdtest = a2150_ai_cmdtest;
+ s->insn_read = a2150_ai_rinsn;
+ s->cancel = a2150_cancel;
+
+ /* need to do this for software counting of completed conversions, to
+ * prevent hardware count from stopping acquisition */
+ outw(HW_COUNT_DISABLE, dev->iobase + I8253_MODE_REG);
+
+ /* set card's irq and dma levels */
+ outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
+
+ /* reset and sync adc clock circuitry */
+ outw_p(DPD_BIT | APD_BIT, dev->iobase + CONFIG_REG);
+ outw_p(DPD_BIT, dev->iobase + CONFIG_REG);
+ /* initialize configuration register */
+ devpriv->config_bits = 0;
+ outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
+ /* wait until offset calibration is done, then enable analog inputs */
+ for (i = 0; i < timeout; i++) {
+ if ((DCAL_BIT & inw(dev->iobase + STATUS_REG)) == 0)
+ break;
+ udelay(1000);
+ }
+ if (i == timeout) {
+ printk
+ (" timed out waiting for offset calibration to complete\n");
+ return -ETIME;
+ }
+ devpriv->config_bits |= ENABLE0_BIT | ENABLE1_BIT;
+ outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
+
+ return 0;
+};
+
+static void a2150_detach(struct comedi_device *dev)
+{
+ if (dev->iobase) {
+ outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG);
+ release_region(dev->iobase, A2150_SIZE);
+ }
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ if (devpriv) {
+ if (devpriv->dma)
+ free_dma(devpriv->dma);
+ kfree(devpriv->dma_buffer);
+ }
+};
+
+static struct comedi_driver ni_at_a2150_driver = {
+ .driver_name = "ni_at_a2150",
+ .module = THIS_MODULE,
+ .attach = a2150_attach,
+ .detach = a2150_detach,
+};
+module_comedi_driver(ni_at_a2150_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
index 138dcc2275ab..c43dd8ada1da 100644
--- a/drivers/staging/comedi/drivers/ni_at_ao.c
+++ b/drivers/staging/comedi/drivers/ni_at_ao.c
@@ -157,17 +157,6 @@ struct atao_board {
int n_ao_chans;
};
-static const struct atao_board atao_boards[] = {
- {
- .name = "ai-ao-6",
- .n_ao_chans = 6,
- },
- {
- .name = "ai-ao-10",
- .n_ao_chans = 10,
- },
-};
-
#define thisboard ((struct atao_board *)dev->board_ptr)
struct atao_private {
@@ -182,133 +171,6 @@ struct atao_private {
#define devpriv ((struct atao_private *)dev->private)
-static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int atao_detach(struct comedi_device *dev);
-static struct comedi_driver driver_atao = {
- .driver_name = "ni_at_ao",
- .module = THIS_MODULE,
- .attach = atao_attach,
- .detach = atao_detach,
- .board_name = &atao_boards[0].name,
- .offset = sizeof(struct atao_board),
- .num_names = ARRAY_SIZE(atao_boards),
-};
-
-static int __init driver_atao_init_module(void)
-{
- return comedi_driver_register(&driver_atao);
-}
-
-static void __exit driver_atao_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_atao);
-}
-
-module_init(driver_atao_init_module);
-module_exit(driver_atao_cleanup_module);
-
-static void atao_reset(struct comedi_device *dev);
-
-static int atao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int atao_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int atao_dio_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int atao_dio_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int atao_calib_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int atao_calib_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- unsigned long iobase;
- int ao_unipolar;
-
- iobase = it->options[0];
- if (iobase == 0)
- iobase = 0x1c0;
- ao_unipolar = it->options[3];
-
- printk(KERN_INFO "comedi%d: ni_at_ao: 0x%04lx", dev->minor, iobase);
-
- if (!request_region(iobase, ATAO_SIZE, "ni_at_ao")) {
- printk(" I/O port conflict\n");
- return -EIO;
- }
- dev->iobase = iobase;
-
- /* dev->board_ptr = atao_probe(dev); */
-
- dev->board_name = thisboard->name;
-
- if (alloc_private(dev, sizeof(struct atao_private)) < 0)
- return -ENOMEM;
-
- if (alloc_subdevices(dev, 4) < 0)
- return -ENOMEM;
-
- s = dev->subdevices + 0;
- /* analog output subdevice */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = thisboard->n_ao_chans;
- s->maxdata = (1 << 12) - 1;
- if (ao_unipolar)
- s->range_table = &range_unipolar10;
- else
- s->range_table = &range_bipolar10;
- s->insn_write = &atao_ao_winsn;
- s->insn_read = &atao_ao_rinsn;
-
- s = dev->subdevices + 1;
- /* digital i/o subdevice */
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 8;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = atao_dio_insn_bits;
- s->insn_config = atao_dio_insn_config;
-
- s = dev->subdevices + 2;
- /* caldac subdevice */
- s->type = COMEDI_SUBD_CALIB;
- s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
- s->n_chan = 21;
- s->maxdata = 0xff;
- s->insn_read = atao_calib_insn_read;
- s->insn_write = atao_calib_insn_write;
-
- s = dev->subdevices + 3;
- /* eeprom subdevice */
- /* s->type=COMEDI_SUBD_EEPROM; */
- s->type = COMEDI_SUBD_UNUSED;
-
- atao_reset(dev);
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-static int atao_detach(struct comedi_device *dev)
-{
- printk(KERN_INFO "comedi%d: atao: remove\n", dev->minor);
-
- if (dev->iobase)
- release_region(dev->iobase, ATAO_SIZE);
-
- return 0;
-}
-
static void atao_reset(struct comedi_device *dev)
{
/* This is the reset sequence described in the manual */
@@ -471,6 +333,106 @@ static int atao_calib_insn_write(struct comedi_device *dev,
return insn->n;
}
+static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+{
+ struct comedi_subdevice *s;
+ unsigned long iobase;
+ int ao_unipolar;
+
+ iobase = it->options[0];
+ if (iobase == 0)
+ iobase = 0x1c0;
+ ao_unipolar = it->options[3];
+
+ printk(KERN_INFO "comedi%d: ni_at_ao: 0x%04lx", dev->minor, iobase);
+
+ if (!request_region(iobase, ATAO_SIZE, "ni_at_ao")) {
+ printk(" I/O port conflict\n");
+ return -EIO;
+ }
+ dev->iobase = iobase;
+
+ /* dev->board_ptr = atao_probe(dev); */
+
+ dev->board_name = thisboard->name;
+
+ if (alloc_private(dev, sizeof(struct atao_private)) < 0)
+ return -ENOMEM;
+
+ if (alloc_subdevices(dev, 4) < 0)
+ return -ENOMEM;
+
+ s = dev->subdevices + 0;
+ /* analog output subdevice */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = thisboard->n_ao_chans;
+ s->maxdata = (1 << 12) - 1;
+ if (ao_unipolar)
+ s->range_table = &range_unipolar10;
+ else
+ s->range_table = &range_bipolar10;
+ s->insn_write = &atao_ao_winsn;
+ s->insn_read = &atao_ao_rinsn;
+
+ s = dev->subdevices + 1;
+ /* digital i/o subdevice */
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = atao_dio_insn_bits;
+ s->insn_config = atao_dio_insn_config;
+
+ s = dev->subdevices + 2;
+ /* caldac subdevice */
+ s->type = COMEDI_SUBD_CALIB;
+ s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
+ s->n_chan = 21;
+ s->maxdata = 0xff;
+ s->insn_read = atao_calib_insn_read;
+ s->insn_write = atao_calib_insn_write;
+
+ s = dev->subdevices + 3;
+ /* eeprom subdevice */
+ /* s->type=COMEDI_SUBD_EEPROM; */
+ s->type = COMEDI_SUBD_UNUSED;
+
+ atao_reset(dev);
+
+ printk(KERN_INFO "\n");
+
+ return 0;
+}
+
+static void atao_detach(struct comedi_device *dev)
+{
+ if (dev->iobase)
+ release_region(dev->iobase, ATAO_SIZE);
+}
+
+static const struct atao_board atao_boards[] = {
+ {
+ .name = "ai-ao-6",
+ .n_ao_chans = 6,
+ }, {
+ .name = "ai-ao-10",
+ .n_ao_chans = 10,
+ },
+};
+
+static struct comedi_driver ni_at_ao_driver = {
+ .driver_name = "ni_at_ao",
+ .module = THIS_MODULE,
+ .attach = atao_attach,
+ .detach = atao_detach,
+ .board_name = &atao_boards[0].name,
+ .offset = sizeof(struct atao_board),
+ .num_names = ARRAY_SIZE(atao_boards),
+};
+module_comedi_driver(ni_at_ao_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
index 647c228abfbf..6448373878ed 100644
--- a/drivers/staging/comedi/drivers/ni_atmio.c
+++ b/drivers/staging/comedi/drivers/ni_atmio.c
@@ -343,49 +343,8 @@ static struct pnp_device_id device_ids[] = {
MODULE_DEVICE_TABLE(pnp, device_ids);
-static int ni_atmio_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int ni_atmio_detach(struct comedi_device *dev);
-static struct comedi_driver driver_atmio = {
- .driver_name = "ni_atmio",
- .module = THIS_MODULE,
- .attach = ni_atmio_attach,
- .detach = ni_atmio_detach,
-};
-
-static int __init driver_atmio_init_module(void)
-{
- return comedi_driver_register(&driver_atmio);
-}
-
-static void __exit driver_atmio_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_atmio);
-}
-
-module_init(driver_atmio_init_module);
-module_exit(driver_atmio_cleanup_module);
-
#include "ni_mio_common.c"
-static int ni_getboardtype(struct comedi_device *dev);
-
-/* clean up allocated resources */
-static int ni_atmio_detach(struct comedi_device *dev)
-{
- mio_common_detach(dev);
-
- if (dev->iobase)
- release_region(dev->iobase, NI_SIZE);
- if (dev->irq)
- free_irq(dev->irq, dev);
-
- if (devpriv->isapnp_dev)
- pnp_device_detach(devpriv->isapnp_dev);
-
- return 0;
-}
-
static int ni_isapnp_find_board(struct pnp_dev **dev)
{
struct pnp_dev *isapnp_dev = NULL;
@@ -424,6 +383,26 @@ static int ni_isapnp_find_board(struct pnp_dev **dev)
return 0;
}
+static int ni_getboardtype(struct comedi_device *dev)
+{
+ int device_id = ni_read_eeprom(dev, 511);
+ int i;
+
+ for (i = 0; i < n_ni_boards; i++) {
+ if (ni_boards[i].device_id == device_id)
+ return i;
+
+ }
+ if (device_id == 255)
+ printk(" can't find board\n");
+ else if (device_id == 0)
+ printk(" EEPROM read error (?) or device not found\n");
+ else
+ printk(" unknown device ID %d -- contact author\n", device_id);
+
+ return -1;
+}
+
static int ni_atmio_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
@@ -518,22 +497,21 @@ static int ni_atmio_attach(struct comedi_device *dev,
return 0;
}
-static int ni_getboardtype(struct comedi_device *dev)
+static void ni_atmio_detach(struct comedi_device *dev)
{
- int device_id = ni_read_eeprom(dev, 511);
- int i;
-
- for (i = 0; i < n_ni_boards; i++) {
- if (ni_boards[i].device_id == device_id)
- return i;
-
- }
- if (device_id == 255)
- printk(" can't find board\n");
- else if (device_id == 0)
- printk(" EEPROM read error (?) or device not found\n");
- else
- printk(" unknown device ID %d -- contact author\n", device_id);
-
- return -1;
+ mio_common_detach(dev);
+ if (dev->iobase)
+ release_region(dev->iobase, NI_SIZE);
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ if (devpriv->isapnp_dev)
+ pnp_device_detach(devpriv->isapnp_dev);
}
+
+static struct comedi_driver ni_atmio_driver = {
+ .driver_name = "ni_atmio",
+ .module = THIS_MODULE,
+ .attach = ni_atmio_attach,
+ .detach = ni_atmio_detach,
+};
+module_comedi_driver(ni_atmio_driver);
diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
index 285b933551ab..4f6145326747 100644
--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
+++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
@@ -110,60 +110,8 @@ struct atmio16_board_t {
int has_8255;
};
-static const struct atmio16_board_t atmio16_boards[] = {
- {
- .name = "atmio16",
- .has_8255 = 0,
- },
- {
- .name = "atmio16d",
- .has_8255 = 1,
- },
-};
-
-#define n_atmio16_boards ARRAY_SIZE(atmio16_boards)
-
#define boardtype ((const struct atmio16_board_t *)dev->board_ptr)
-/* function prototypes */
-static int atmio16d_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int atmio16d_detach(struct comedi_device *dev);
-static irqreturn_t atmio16d_interrupt(int irq, void *d);
-static int atmio16d_ai_cmdtest(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd);
-static int atmio16d_ai_cmd(struct comedi_device *dev,
- struct comedi_subdevice *s);
-static int atmio16d_ai_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s);
-static void reset_counters(struct comedi_device *dev);
-static void reset_atmio16d(struct comedi_device *dev);
-
-/* main driver struct */
-static struct comedi_driver driver_atmio16d = {
- .driver_name = "atmio16",
- .module = THIS_MODULE,
- .attach = atmio16d_attach,
- .detach = atmio16d_detach,
- .board_name = &atmio16_boards[0].name,
- .num_names = n_atmio16_boards,
- .offset = sizeof(struct atmio16_board_t),
-};
-
-static int __init driver_atmio16d_init_module(void)
-{
- return comedi_driver_register(&driver_atmio16d);
-}
-
-static void __exit driver_atmio16d_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_atmio16d);
-}
-
-module_init(driver_atmio16d_init_module);
-module_exit(driver_atmio16d_cleanup_module);
-
/* range structs */
static const struct comedi_lrange range_atmio16d_ai_10_bipolar = { 4, {
BIP_RANGE
@@ -881,24 +829,38 @@ static int atmio16d_attach(struct comedi_device *dev,
return 0;
}
-static int atmio16d_detach(struct comedi_device *dev)
+static void atmio16d_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: atmio16d: remove\n", dev->minor);
-
if (dev->subdevices && boardtype->has_8255)
subdev_8255_cleanup(dev, dev->subdevices + 3);
-
if (dev->irq)
free_irq(dev->irq, dev);
-
reset_atmio16d(dev);
-
if (dev->iobase)
release_region(dev->iobase, ATMIO16D_SIZE);
-
- return 0;
}
+static const struct atmio16_board_t atmio16_boards[] = {
+ {
+ .name = "atmio16",
+ .has_8255 = 0,
+ }, {
+ .name = "atmio16d",
+ .has_8255 = 1,
+ },
+};
+
+static struct comedi_driver atmio16d_driver = {
+ .driver_name = "atmio16",
+ .module = THIS_MODULE,
+ .attach = atmio16d_attach,
+ .detach = atmio16d_detach,
+ .board_name = &atmio16_boards[0].name,
+ .num_names = ARRAY_SIZE(atmio16_boards),
+ .offset = sizeof(struct atmio16_board_t),
+};
+module_comedi_driver(atmio16d_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index e2420123db87..75764e8d27eb 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -57,7 +57,7 @@ static struct pcmcia_device *pcmcia_cur_dev;
static int dio700_attach(struct comedi_device *dev,
struct comedi_devconfig *it);
-static int dio700_detach(struct comedi_device *dev);
+static void dio700_detach(struct comedi_device *dev);
enum dio700_bustype { pcmcia_bustype };
@@ -419,19 +419,14 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
};
-static int dio700_detach(struct comedi_device *dev)
+static void dio700_detach(struct comedi_device *dev)
{
- printk(KERN_ERR "comedi%d: ni_daq_700: cs-remove\n", dev->minor);
-
if (dev->subdevices)
subdev_700_cleanup(dev, dev->subdevices + 0);
-
if (thisboard->bustype != pcmcia_bustype && dev->iobase)
release_region(dev->iobase, DIO700_SIZE);
if (dev->irq)
free_irq(dev->irq, dev);
-
- return 0;
};
static void dio700_config(struct pcmcia_device *link);
@@ -472,18 +467,12 @@ static int dio700_cs_attach(struct pcmcia_device *link)
static void dio700_cs_detach(struct pcmcia_device *link)
{
-
- printk(KERN_INFO "ni_daq_700: cs-detach!\n");
-
- dev_dbg(&link->dev, "dio700_cs_detach\n");
-
((struct local_info_t *)link->priv)->stop = 1;
dio700_release(link);
/* This points to the parent struct local_info_t struct */
kfree(link->priv);
-
-} /* dio700_cs_detach */
+}
static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
void *priv_data)
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index c0423a8c3e36..493a22788637 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -57,7 +57,7 @@ static struct pcmcia_device *pcmcia_cur_dev;
#define DIO24_SIZE 4 /* size of io region used by board */
static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int dio24_detach(struct comedi_device *dev);
+static void dio24_detach(struct comedi_device *dev);
enum dio24_bustype { pcmcia_bustype };
@@ -168,19 +168,14 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
};
-static int dio24_detach(struct comedi_device *dev)
+static void dio24_detach(struct comedi_device *dev)
{
- dev_info(dev->hw_dev, "comedi%d: ni_daq_dio24: remove\n", dev->minor);
-
if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 0);
-
if (thisboard->bustype != pcmcia_bustype && dev->iobase)
release_region(dev->iobase, DIO24_SIZE);
if (dev->irq)
free_irq(dev->irq, dev);
-
- return 0;
};
static void dio24_config(struct pcmcia_device *link);
@@ -221,18 +216,12 @@ static int dio24_cs_attach(struct pcmcia_device *link)
static void dio24_cs_detach(struct pcmcia_device *link)
{
-
- printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - cs-detach!\n");
-
- dev_dbg(&link->dev, "dio24_cs_detach\n");
-
((struct local_info_t *)link->priv)->stop = 1;
dio24_release(link);
/* This points to the parent local_info_t struct */
kfree(link->priv);
-
-} /* dio24_cs_detach */
+}
static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
void *priv_data)
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index 721b2be22500..53349777246b 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -805,13 +805,10 @@ static int labpc_find_device(struct comedi_device *dev, int bus, int slot)
}
#endif
-int labpc_common_detach(struct comedi_device *dev)
+void labpc_common_detach(struct comedi_device *dev)
{
- printk(KERN_ERR "comedi%d: ni_labpc: detach\n", dev->minor);
-
if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 2);
-
#ifdef CONFIG_ISA_DMA_API
/* only free stuff if it has been allocated by _attach */
kfree(devpriv->dma_buffer);
@@ -826,8 +823,6 @@ int labpc_common_detach(struct comedi_device *dev)
if (devpriv->mite)
mite_unsetup(devpriv->mite);
#endif
-
- return 0;
};
EXPORT_SYMBOL_GPL(labpc_common_detach);
@@ -2141,7 +2136,7 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel,
static int __devinit driver_labpc_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_labpc.driver_name);
+ return comedi_pci_auto_config(dev, &driver_labpc);
}
static void __devexit driver_labpc_pci_remove(struct pci_dev *dev)
diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h
index 422cee58a967..e052ed3ba544 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.h
+++ b/drivers/staging/comedi/drivers/ni_labpc.h
@@ -103,7 +103,7 @@ struct labpc_private {
int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
unsigned int irq, unsigned int dma);
-int labpc_common_detach(struct comedi_device *dev);
+void labpc_common_detach(struct comedi_device *dev);
extern const int labpc_1200_is_unipolar[];
extern const int labpc_1200_ai_gain_bits[];
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index ff3840544dd4..dbb61b6b3ed1 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -188,21 +188,13 @@ static int labpc_cs_attach(struct pcmcia_device *link)
static void labpc_cs_detach(struct pcmcia_device *link)
{
- dev_dbg(&link->dev, "labpc_cs_detach\n");
-
- /*
- If the device is currently configured and active, we won't
- actually delete it yet. Instead, it is marked so that when
- the release() function is called, that will trigger a proper
- detach().
- */
((struct local_info_t *)link->priv)->stop = 1;
labpc_release(link);
/* This points to the parent local_info_t struct (may be null) */
kfree(link->priv);
-} /* labpc_cs_detach */
+}
static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
void *priv_data)
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index 53ec24bb6dce..b85765d266c2 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -227,7 +227,7 @@ static uint16_t mio_cs_win_in(struct comedi_device *dev, int addr)
static int mio_cs_attach(struct comedi_device *dev,
struct comedi_devconfig *it);
-static int mio_cs_detach(struct comedi_device *dev);
+static void mio_cs_detach(struct comedi_device *dev);
static struct comedi_driver driver_ni_mio_cs = {
.driver_name = "ni_mio_cs",
.module = THIS_MODULE,
@@ -240,18 +240,11 @@ static struct comedi_driver driver_ni_mio_cs = {
static int ni_getboardtype(struct comedi_device *dev,
struct pcmcia_device *link);
-/* clean up allocated resources */
-/* called when driver is removed */
-static int mio_cs_detach(struct comedi_device *dev)
+static void mio_cs_detach(struct comedi_device *dev)
{
mio_common_detach(dev);
-
- /* PCMCIA layer frees the IO region */
-
if (dev->irq)
free_irq(dev->irq, dev);
-
- return 0;
}
static void mio_cs_config(struct pcmcia_device *link);
@@ -276,8 +269,6 @@ static void cs_release(struct pcmcia_device *link)
static void cs_detach(struct pcmcia_device *link)
{
- DPRINTK("cs_detach(link=%p)\n", link);
-
cs_release(link);
}
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index 1df8fcbcd108..37b700830e21 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -293,18 +293,9 @@ enum FPGA_Control_Bits {
#define IntEn (TransferReady|CountExpired|Waited|PrimaryTC|SecondaryTC)
#endif
-static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int nidio_detach(struct comedi_device *dev);
static int ni_pcidio_cancel(struct comedi_device *dev,
struct comedi_subdevice *s);
-static struct comedi_driver driver_pcidio = {
- .driver_name = "ni_pcidio",
- .module = THIS_MODULE,
- .attach = nidio_attach,
- .detach = nidio_detach,
-};
-
struct nidio_board {
int dev_id;
@@ -381,22 +372,6 @@ static const struct nidio_board nidio_boards[] = {
#define n_nidio_boards ARRAY_SIZE(nidio_boards)
#define this_board ((const struct nidio_board *)dev->board_ptr)
-static DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = {
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1150)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1320)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x12b0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0160)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1630)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x13c0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0400)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1250)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x17d0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1800)},
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table);
-
struct nidio96_private {
struct mite_struct *mite;
int boardtype;
@@ -414,7 +389,6 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev,
static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
static int ni_pcidio_inttrig(struct comedi_device *dev,
struct comedi_subdevice *s, unsigned int trignum);
-static int nidio_find_device(struct comedi_device *dev, int bus, int slot);
static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode);
static int setup_mite_dma(struct comedi_device *dev,
struct comedi_subdevice *s);
@@ -1205,6 +1179,33 @@ static int pci_6534_upload_firmware(struct comedi_device *dev, int options[])
return 0;
}
+static int nidio_find_device(struct comedi_device *dev, int bus, int slot)
+{
+ struct mite_struct *mite;
+ int i;
+
+ for (mite = mite_devices; mite; mite = mite->next) {
+ if (mite->used)
+ continue;
+ if (bus || slot) {
+ if (bus != mite->pcidev->bus->number ||
+ slot != PCI_SLOT(mite->pcidev->devfn))
+ continue;
+ }
+ for (i = 0; i < n_nidio_boards; i++) {
+ if (mite_device_id(mite) == nidio_boards[i].dev_id) {
+ dev->board_ptr = nidio_boards + i;
+ devpriv->mite = mite;
+
+ return 0;
+ }
+ }
+ }
+ printk(KERN_WARNING "no device found\n");
+ mite_list_devices();
+ return -EIO;
+}
+
static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
struct comedi_subdevice *s;
@@ -1306,7 +1307,7 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int nidio_detach(struct comedi_device *dev)
+static void nidio_detach(struct comedi_device *dev)
{
int i;
@@ -1314,10 +1315,8 @@ static int nidio_detach(struct comedi_device *dev)
for (i = 0; i < this_board->n_8255; i++)
subdev_8255_cleanup(dev, dev->subdevices + i);
}
-
if (dev->irq)
free_irq(dev->irq, dev);
-
if (devpriv) {
if (devpriv->di_mite_ring) {
mite_free_ring(devpriv->di_mite_ring);
@@ -1326,73 +1325,48 @@ static int nidio_detach(struct comedi_device *dev)
if (devpriv->mite)
mite_unsetup(devpriv->mite);
}
- return 0;
}
-static int nidio_find_device(struct comedi_device *dev, int bus, int slot)
-{
- struct mite_struct *mite;
- int i;
-
- for (mite = mite_devices; mite; mite = mite->next) {
- if (mite->used)
- continue;
- if (bus || slot) {
- if (bus != mite->pcidev->bus->number ||
- slot != PCI_SLOT(mite->pcidev->devfn))
- continue;
- }
- for (i = 0; i < n_nidio_boards; i++) {
- if (mite_device_id(mite) == nidio_boards[i].dev_id) {
- dev->board_ptr = nidio_boards + i;
- devpriv->mite = mite;
-
- return 0;
- }
- }
- }
- printk(KERN_WARNING "no device found\n");
- mite_list_devices();
- return -EIO;
-}
+static struct comedi_driver ni_pcidio_driver = {
+ .driver_name = "ni_pcidio",
+ .module = THIS_MODULE,
+ .attach = nidio_attach,
+ .detach = nidio_detach,
+};
-static int __devinit driver_pcidio_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static int __devinit ni_pcidio_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_pcidio.driver_name);
+ return comedi_pci_auto_config(dev, &ni_pcidio_driver);
}
-static void __devexit driver_pcidio_pci_remove(struct pci_dev *dev)
+static void __devexit ni_pcidio_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_pcidio_pci_driver = {
- .id_table = ni_pcidio_pci_table,
- .probe = &driver_pcidio_pci_probe,
- .remove = __devexit_p(&driver_pcidio_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1150) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1320) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x12b0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0160) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1630) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x13c0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0400) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1250) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x17d0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1800) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table);
-static int __init driver_pcidio_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_pcidio);
- if (retval < 0)
- return retval;
-
- driver_pcidio_pci_driver.name = (char *)driver_pcidio.driver_name;
- return pci_register_driver(&driver_pcidio_pci_driver);
-}
-
-static void __exit driver_pcidio_cleanup_module(void)
-{
- pci_unregister_driver(&driver_pcidio_pci_driver);
- comedi_driver_unregister(&driver_pcidio);
-}
-
-module_init(driver_pcidio_init_module);
-module_exit(driver_pcidio_cleanup_module);
+static struct pci_driver ni_pcidio_pci_driver = {
+ .name = "ni_pcidio",
+ .id_table = ni_pcidio_pci_table,
+ .probe = ni_pcidio_pci_probe,
+ .remove = __devexit_p(ni_pcidio_pci_remove),
+};
+module_comedi_pci_driver(ni_pcidio_driver, ni_pcidio_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index 27baefa32b17..3974c0d98d2a 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -129,66 +129,6 @@ Bugs:
#define DRV_NAME "ni_pcimio"
-/* The following two tables must be in the same order */
-static DEFINE_PCI_DEVICE_TABLE(ni_pci_table) = {
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0162)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1170)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1180)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1190)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x11b0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x11c0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x11d0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1270)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1330)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1340)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1350)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x14e0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x14f0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1580)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x15b0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1880)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1870)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x18b0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x18c0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2410)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2420)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2430)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2890)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x28c0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2a60)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2a70)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2a80)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2ab0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b80)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b90)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c80)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2ca0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70aa)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70ab)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70ac)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70af)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b4)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b6)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b7)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b8)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70bc)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70bd)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70bf)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70c0)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70f2)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x710d)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x716c)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x716d)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x717f)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x71bc)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x717d)},
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x72e8)},
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, ni_pci_table);
-
/* These are not all the possible ao ranges for 628x boards.
They can do OFFSET +- REFERENCE where OFFSET can be
0V, 5V, APFI<0,1>, or AO<0...3> and RANGE can
@@ -1250,54 +1190,6 @@ static const struct ni_board_struct ni_boards[] = {
#define n_pcimio_boards ARRAY_SIZE(ni_boards)
-static int pcimio_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcimio_detach(struct comedi_device *dev);
-static struct comedi_driver driver_pcimio = {
- .driver_name = DRV_NAME,
- .module = THIS_MODULE,
- .attach = pcimio_attach,
- .detach = pcimio_detach,
-};
-
-static int __devinit driver_pcimio_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, driver_pcimio.driver_name);
-}
-
-static void __devexit driver_pcimio_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver driver_pcimio_pci_driver = {
- .id_table = ni_pci_table,
- .probe = &driver_pcimio_pci_probe,
- .remove = __devexit_p(&driver_pcimio_pci_remove)
-};
-
-static int __init driver_pcimio_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_pcimio);
- if (retval < 0)
- return retval;
-
- driver_pcimio_pci_driver.name = (char *)driver_pcimio.driver_name;
- return pci_register_driver(&driver_pcimio_pci_driver);
-}
-
-static void __exit driver_pcimio_cleanup_module(void)
-{
- pci_unregister_driver(&driver_pcimio_pci_driver);
- comedi_driver_unregister(&driver_pcimio);
-}
-
-module_init(driver_pcimio_init_module);
-module_exit(driver_pcimio_cleanup_module);
-
struct ni_private {
NI_PRIVATE_COMMON};
#define devpriv ((struct ni_private *)dev->private)
@@ -1681,13 +1573,11 @@ static void init_6143(struct comedi_device *dev)
ni_writew(devpriv->ai_calib_source, Calibration_Channel_6143);
}
-/* cleans up allocated resources */
-static int pcimio_detach(struct comedi_device *dev)
+static void pcimio_detach(struct comedi_device *dev)
{
mio_common_detach(dev);
if (dev->irq)
free_irq(dev->irq, dev);
-
if (dev->private) {
mite_free_ring(devpriv->ai_mite_ring);
mite_free_ring(devpriv->ao_mite_ring);
@@ -1697,8 +1587,6 @@ static int pcimio_detach(struct comedi_device *dev)
if (devpriv->mite)
mite_unsetup(devpriv->mite);
}
-
- return 0;
}
static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
@@ -1874,6 +1762,90 @@ static int pcimio_dio_change(struct comedi_device *dev,
return 0;
}
+static struct comedi_driver ni_pcimio_driver = {
+ .driver_name = "ni_pcimio",
+ .module = THIS_MODULE,
+ .attach = pcimio_attach,
+ .detach = pcimio_detach,
+};
+
+static int __devinit ni_pcimio_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &ni_pcimio_driver);
+}
+
+static void __devexit ni_pcimio_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(ni_pcimio_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0162) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1170) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1180) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1190) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x11b0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x11c0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x11d0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1270) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1330) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1340) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1350) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x14e0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x14f0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1580) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x15b0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1880) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1870) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x18b0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x18c0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2410) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2420) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2430) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2890) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x28c0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2a60) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2a70) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2a80) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2ab0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b80) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b90) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c80) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2ca0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70aa) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70ab) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70ac) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70af) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b6) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b7) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b8) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70bc) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70bd) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70bf) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70c0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70f2) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x710d) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x716c) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x716d) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x717f) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x71bc) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x717d) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x72e8) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, ni_pcimio_pci_table);
+
+static struct pci_driver ni_pcimio_pci_driver = {
+ .name = "ni_pcimio",
+ .id_table = ni_pcimio_pci_table,
+ .probe = ni_pcimio_pci_probe,
+ .remove = __devexit_p(ni_pcimio_pci_remove)
+};
+module_comedi_pci_driver(ni_pcimio_driver, ni_pcimio_pci_driver)
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h
index c4ca53785832..5e00212aa022 100644
--- a/drivers/staging/comedi/drivers/ni_tio_internal.h
+++ b/drivers/staging/comedi/drivers/ni_tio_internal.h
@@ -362,8 +362,8 @@ static inline enum ni_gpct_register NITIO_Gi_ABZ_Reg(int counter_index)
return 0;
}
-static inline enum ni_gpct_register NITIO_Gi_Interrupt_Acknowledge_Reg(int
- counter_index)
+static inline enum ni_gpct_register NITIO_Gi_Interrupt_Acknowledge_Reg(
+ int counter_index)
{
switch (counter_index) {
case 0:
@@ -407,8 +407,8 @@ static inline enum ni_gpct_register NITIO_Gi_Status_Reg(int counter_index)
return 0;
}
-static inline enum ni_gpct_register NITIO_Gi_Interrupt_Enable_Reg(int
- counter_index)
+static inline enum ni_gpct_register NITIO_Gi_Interrupt_Enable_Reg(
+ int counter_index)
{
switch (counter_index) {
case 0:
@@ -472,15 +472,22 @@ enum Gi_Counting_Mode_Reg_Bits {
Gi_Index_Phase_LowA_HighB = 0x1 << Gi_Index_Phase_Bitshift,
Gi_Index_Phase_HighA_LowB = 0x2 << Gi_Index_Phase_Bitshift,
Gi_Index_Phase_HighA_HighB = 0x3 << Gi_Index_Phase_Bitshift,
- Gi_HW_Arm_Enable_Bit = 0x80, /* from m-series example code, not documented in 660x register level manual */
- Gi_660x_HW_Arm_Select_Mask = 0x7 << Gi_HW_Arm_Select_Shift, /* from m-series example code, not documented in 660x register level manual */
+ /* from m-series example code, not documented in 660x register level
+ * manual */
+ Gi_HW_Arm_Enable_Bit = 0x80,
+ /* from m-series example code, not documented in 660x register level
+ * manual */
+ Gi_660x_HW_Arm_Select_Mask = 0x7 << Gi_HW_Arm_Select_Shift,
Gi_660x_Prescale_X8_Bit = 0x1000,
Gi_M_Series_Prescale_X8_Bit = 0x2000,
Gi_M_Series_HW_Arm_Select_Mask = 0x1f << Gi_HW_Arm_Select_Shift,
- /* must be set for clocks over 40MHz, which includes synchronous counting and quadrature modes */
+ /* must be set for clocks over 40MHz, which includes synchronous
+ * counting and quadrature modes */
Gi_660x_Alternate_Sync_Bit = 0x2000,
Gi_M_Series_Alternate_Sync_Bit = 0x4000,
- Gi_660x_Prescale_X2_Bit = 0x4000, /* from m-series example code, not documented in 660x register level manual */
+ /* from m-series example code, not documented in 660x register level
+ * manual */
+ Gi_660x_Prescale_X2_Bit = 0x4000,
Gi_M_Series_Prescale_X2_Bit = 0x8000,
};
@@ -503,7 +510,8 @@ enum Gi_Mode_Bits {
Gi_Level_Gating_Bits = 0x1,
Gi_Rising_Edge_Gating_Bits = 0x2,
Gi_Falling_Edge_Gating_Bits = 0x3,
- Gi_Gate_On_Both_Edges_Bit = 0x4, /* used in conjunction with rising edge gating mode */
+ Gi_Gate_On_Both_Edges_Bit = 0x4, /* used in conjunction with
+ * rising edge gating mode */
Gi_Trigger_Mode_for_Edge_Gate_Mask = 0x18,
Gi_Edge_Gate_Starts_Stops_Bits = 0x0,
Gi_Edge_Gate_Stops_Starts_Bits = 0x8,
@@ -686,11 +694,10 @@ static inline unsigned Gi_Gate_Interrupt_Enable_Bit(unsigned counter_index)
{
unsigned bit;
- if (counter_index % 2) {
+ if (counter_index % 2)
bit = G1_Gate_Interrupt_Enable_Bit;
- } else {
+ else
bit = G0_Gate_Interrupt_Enable_Bit;
- }
return bit;
}
@@ -748,8 +755,9 @@ static inline void ni_tio_set_bits_transient(struct ni_gpct *counter,
}
/* ni_tio_set_bits( ) is for safely writing to registers whose bits may be
-twiddled in interrupt context, or whose software copy may be read in interrupt context.
-*/
+ * twiddled in interrupt context, or whose software copy may be read in
+ * interrupt context.
+ */
static inline void ni_tio_set_bits(struct ni_gpct *counter,
enum ni_gpct_register register_index,
unsigned bit_mask, unsigned bit_values)
diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
index b44386a6b636..2e7753f988aa 100644
--- a/drivers/staging/comedi/drivers/pcl711.c
+++ b/drivers/staging/comedi/drivers/pcl711.c
@@ -148,42 +148,8 @@ struct pcl711_board {
const struct comedi_lrange *ai_range_type;
};
-static const struct pcl711_board boardtypes[] = {
- {"pcl711", 0, 0, 0, 5, 8, 1, 0, &range_bipolar5},
- {"pcl711b", 1, 0, 0, 5, 8, 1, 7, &range_pcl711b_ai},
- {"acl8112hg", 0, 1, 0, 12, 16, 2, 15, &range_acl8112hg_ai},
- {"acl8112dg", 0, 1, 1, 9, 16, 2, 15, &range_acl8112dg_ai},
-};
-
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl711_board))
#define this_board ((const struct pcl711_board *)dev->board_ptr)
-static int pcl711_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcl711_detach(struct comedi_device *dev);
-static struct comedi_driver driver_pcl711 = {
- .driver_name = "pcl711",
- .module = THIS_MODULE,
- .attach = pcl711_attach,
- .detach = pcl711_detach,
- .board_name = &boardtypes[0].name,
- .num_names = n_boardtypes,
- .offset = sizeof(struct pcl711_board),
-};
-
-static int __init driver_pcl711_init_module(void)
-{
- return comedi_driver_register(&driver_pcl711);
-}
-
-static void __exit driver_pcl711_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_pcl711);
-}
-
-module_init(driver_pcl711_init_module);
-module_exit(driver_pcl711_cleanup_module);
-
struct pcl711_private {
int board;
@@ -513,21 +479,6 @@ static int pcl711_do_insn_bits(struct comedi_device *dev,
return 2;
}
-/* Free any resources that we have claimed */
-static int pcl711_detach(struct comedi_device *dev)
-{
- printk(KERN_INFO "comedi%d: pcl711: remove\n", dev->minor);
-
- if (dev->irq)
- free_irq(dev->irq, dev);
-
- if (dev->iobase)
- release_region(dev->iobase, PCL711_SIZE);
-
- return 0;
-}
-
-/* Initialization */
static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
int ret;
@@ -640,6 +591,32 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
+static void pcl711_detach(struct comedi_device *dev)
+{
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ if (dev->iobase)
+ release_region(dev->iobase, PCL711_SIZE);
+}
+
+static const struct pcl711_board boardtypes[] = {
+ { "pcl711", 0, 0, 0, 5, 8, 1, 0, &range_bipolar5 },
+ { "pcl711b", 1, 0, 0, 5, 8, 1, 7, &range_pcl711b_ai },
+ { "acl8112hg", 0, 1, 0, 12, 16, 2, 15, &range_acl8112hg_ai },
+ { "acl8112dg", 0, 1, 1, 9, 16, 2, 15, &range_acl8112dg_ai },
+};
+
+static struct comedi_driver pcl711_driver = {
+ .driver_name = "pcl711",
+ .module = THIS_MODULE,
+ .attach = pcl711_attach,
+ .detach = pcl711_detach,
+ .board_name = &boardtypes[0].name,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .offset = sizeof(struct pcl711_board),
+};
+module_comedi_driver(pcl711_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
index 61b075db66ef..1f66fe1c7d5e 100644
--- a/drivers/staging/comedi/drivers/pcl724.c
+++ b/drivers/staging/comedi/drivers/pcl724.c
@@ -56,10 +56,6 @@ See the source for configuration details.
/* #define PCL724_IRQ 1 no IRQ support now */
-static int pcl724_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcl724_detach(struct comedi_device *dev);
-
struct pcl724_board {
const char *name; /* board name */
@@ -71,41 +67,8 @@ struct pcl724_board {
char is_pet48;
};
-static const struct pcl724_board boardtypes[] = {
- {"pcl724", 24, 1, 0x00fc, PCL724_SIZE, 0, 0,},
- {"pcl722", 144, 6, 0x00fc, PCL722_SIZE, 1, 0,},
- {"pcl731", 48, 2, 0x9cfc, PCL731_SIZE, 0, 0,},
- {"acl7122", 144, 6, 0x9ee8, PCL722_SIZE, 1, 0,},
- {"acl7124", 24, 1, 0x00fc, PCL724_SIZE, 0, 0,},
- {"pet48dio", 48, 2, 0x9eb8, PET48_SIZE, 0, 1,},
-};
-
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl724_board))
#define this_board ((const struct pcl724_board *)dev->board_ptr)
-static struct comedi_driver driver_pcl724 = {
- .driver_name = "pcl724",
- .module = THIS_MODULE,
- .attach = pcl724_attach,
- .detach = pcl724_detach,
- .board_name = &boardtypes[0].name,
- .num_names = n_boardtypes,
- .offset = sizeof(struct pcl724_board),
-};
-
-static int __init driver_pcl724_init_module(void)
-{
- return comedi_driver_register(&driver_pcl724);
-}
-
-static void __exit driver_pcl724_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_pcl724);
-}
-
-module_init(driver_pcl724_init_module);
-module_exit(driver_pcl724_cleanup_module);
-
static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
{
unsigned long iobase = arg;
@@ -214,25 +177,39 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int pcl724_detach(struct comedi_device *dev)
+static void pcl724_detach(struct comedi_device *dev)
{
int i;
- /* printk("comedi%d: pcl724: remove\n",dev->minor); */
-
for (i = 0; i < dev->n_subdevices; i++)
subdev_8255_cleanup(dev, dev->subdevices + i);
-
#ifdef PCL724_IRQ
if (dev->irq)
free_irq(dev->irq, dev);
#endif
-
release_region(dev->iobase, this_board->io_range);
-
- return 0;
}
+static const struct pcl724_board boardtypes[] = {
+ { "pcl724", 24, 1, 0x00fc, PCL724_SIZE, 0, 0, },
+ { "pcl722", 144, 6, 0x00fc, PCL722_SIZE, 1, 0, },
+ { "pcl731", 48, 2, 0x9cfc, PCL731_SIZE, 0, 0, },
+ { "acl7122", 144, 6, 0x9ee8, PCL722_SIZE, 1, 0, },
+ { "acl7124", 24, 1, 0x00fc, PCL724_SIZE, 0, 0, },
+ { "pet48dio", 48, 2, 0x9eb8, PET48_SIZE, 0, 1, },
+};
+
+static struct comedi_driver pcl724_driver = {
+ .driver_name = "pcl724",
+ .module = THIS_MODULE,
+ .attach = pcl724_attach,
+ .detach = pcl724_detach,
+ .board_name = &boardtypes[0].name,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .offset = sizeof(struct pcl724_board),
+};
+module_comedi_driver(pcl724_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c
index 24b223ca4399..83a6fa53dddd 100644
--- a/drivers/staging/comedi/drivers/pcl725.c
+++ b/drivers/staging/comedi/drivers/pcl725.c
@@ -20,29 +20,6 @@ Devices: [Advantech] PCL-725 (pcl725)
#define PCL725_DO 0
#define PCL725_DI 1
-static int pcl725_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcl725_detach(struct comedi_device *dev);
-static struct comedi_driver driver_pcl725 = {
- .driver_name = "pcl725",
- .module = THIS_MODULE,
- .attach = pcl725_attach,
- .detach = pcl725_detach,
-};
-
-static int __init driver_pcl725_init_module(void)
-{
- return comedi_driver_register(&driver_pcl725);
-}
-
-static void __exit driver_pcl725_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_pcl725);
-}
-
-module_init(driver_pcl725_init_module);
-module_exit(driver_pcl725_cleanup_module);
-
static int pcl725_do_insn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
@@ -112,16 +89,20 @@ static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int pcl725_detach(struct comedi_device *dev)
+static void pcl725_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: pcl725: remove\n", dev->minor);
-
if (dev->iobase)
release_region(dev->iobase, PCL725_SIZE);
-
- return 0;
}
+static struct comedi_driver pcl725_driver = {
+ .driver_name = "pcl725",
+ .module = THIS_MODULE,
+ .attach = pcl725_attach,
+ .detach = pcl725_detach,
+};
+module_comedi_driver(pcl725_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
index 897cd808eeb7..d25c30c694e3 100644
--- a/drivers/staging/comedi/drivers/pcl726.c
+++ b/drivers/staging/comedi/drivers/pcl726.c
@@ -111,10 +111,6 @@ static const struct comedi_lrange *const rangelist_728[] = {
&range_4_20mA, &range_0_20mA
};
-static int pcl726_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcl726_detach(struct comedi_device *dev);
-
struct pcl726_board {
const char *name; /* driver name */
@@ -149,32 +145,8 @@ static const struct pcl726_board boardtypes[] = {
&rangelist_728[0],},
};
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl726_board))
#define this_board ((const struct pcl726_board *)dev->board_ptr)
-static struct comedi_driver driver_pcl726 = {
- .driver_name = "pcl726",
- .module = THIS_MODULE,
- .attach = pcl726_attach,
- .detach = pcl726_detach,
- .board_name = &boardtypes[0].name,
- .num_names = n_boardtypes,
- .offset = sizeof(struct pcl726_board),
-};
-
-static int __init driver_pcl726_init_module(void)
-{
- return comedi_driver_register(&driver_pcl726);
-}
-
-static void __exit driver_pcl726_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_pcl726);
-}
-
-module_init(driver_pcl726_init_module);
-module_exit(driver_pcl726_cleanup_module);
-
struct pcl726_private {
int bipolar[12];
@@ -378,21 +350,27 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int pcl726_detach(struct comedi_device *dev)
+static void pcl726_detach(struct comedi_device *dev)
{
-/* printk("comedi%d: pcl726: remove\n",dev->minor); */
-
#ifdef ACL6126_IRQ
if (dev->irq)
free_irq(dev->irq, dev);
#endif
-
if (dev->iobase)
release_region(dev->iobase, this_board->io_range);
-
- return 0;
}
+static struct comedi_driver pcl726_driver = {
+ .driver_name = "pcl726",
+ .module = THIS_MODULE,
+ .attach = pcl726_attach,
+ .detach = pcl726_detach,
+ .board_name = &boardtypes[0].name,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .offset = sizeof(struct pcl726_board),
+};
+module_comedi_driver(pcl726_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
index c9682d614e0e..e11704addedb 100644
--- a/drivers/staging/comedi/drivers/pcl730.c
+++ b/drivers/staging/comedi/drivers/pcl730.c
@@ -26,48 +26,14 @@ The ACL-7130 card have an 8254 timer/counter not supported by this driver.
#define PCL730_DIO_LO 2 /* TTL Digital I/O low byte (D0-D7) */
#define PCL730_DIO_HI 3 /* TTL Digital I/O high byte (D8-D15) */
-static int pcl730_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcl730_detach(struct comedi_device *dev);
-
struct pcl730_board {
const char *name; /* board name */
unsigned int io_range; /* len of I/O space */
};
-static const struct pcl730_board boardtypes[] = {
- {"pcl730", PCL730_SIZE,},
- {"iso730", PCL730_SIZE,},
- {"acl7130", ACL7130_SIZE,},
-};
-
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl730_board))
#define this_board ((const struct pcl730_board *)dev->board_ptr)
-static struct comedi_driver driver_pcl730 = {
- .driver_name = "pcl730",
- .module = THIS_MODULE,
- .attach = pcl730_attach,
- .detach = pcl730_detach,
- .board_name = &boardtypes[0].name,
- .num_names = n_boardtypes,
- .offset = sizeof(struct pcl730_board),
-};
-
-static int __init driver_pcl730_init_module(void)
-{
- return comedi_driver_register(&driver_pcl730);
-}
-
-static void __exit driver_pcl730_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_pcl730);
-}
-
-module_init(driver_pcl730_init_module);
-module_exit(driver_pcl730_cleanup_module);
-
static int pcl730_do_insn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
@@ -168,16 +134,29 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int pcl730_detach(struct comedi_device *dev)
+static void pcl730_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: pcl730: remove\n", dev->minor);
-
if (dev->iobase)
release_region(dev->iobase, this_board->io_range);
-
- return 0;
}
+static const struct pcl730_board boardtypes[] = {
+ { "pcl730", PCL730_SIZE, },
+ { "iso730", PCL730_SIZE, },
+ { "acl7130", ACL7130_SIZE, },
+};
+
+static struct comedi_driver pcl730_driver = {
+ .driver_name = "pcl730",
+ .module = THIS_MODULE,
+ .attach = pcl730_attach,
+ .detach = pcl730_detach,
+ .board_name = &boardtypes[0].name,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .offset = sizeof(struct pcl730_board),
+};
+module_comedi_driver(pcl730_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index 6fc74645af2c..51f4ca9f7927 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -316,10 +316,6 @@ static const struct comedi_lrange range_a821pgh_ai = { 4, {
}
};
-static int pcl812_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcl812_detach(struct comedi_device *dev);
-
struct pcl812_board {
const char *name; /* board name */
@@ -340,89 +336,8 @@ struct pcl812_board {
unsigned char haveMPC508; /* 1=board use MPC508A multiplexor */
};
-static const struct pcl812_board boardtypes[] = {
- {"pcl812", boardPCL812, 16, 0, 2, 16, 16, 0x0fff,
- 33000, 500, &range_bipolar10, &range_unipolar5,
- 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
- {"pcl812pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
- 33000, 500, &range_pcl812pg_ai, &range_unipolar5,
- 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
- {"acl8112pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
- 10000, 500, &range_pcl812pg_ai, &range_unipolar5,
- 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
- {"acl8112dg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
- 10000, 500, &range_acl8112dg_ai, &range_unipolar5,
- 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
- {"acl8112hg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
- 10000, 500, &range_acl8112hg_ai, &range_unipolar5,
- 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
- {"a821pgl", boardA821, 16, 8, 1, 16, 16, 0x0fff,
- 10000, 500, &range_pcl813b_ai, &range_unipolar5,
- 0x000c, 0x00, PCLx1x_IORANGE, 0},
- {"a821pglnda", boardA821, 16, 8, 0, 0, 0, 0x0fff,
- 10000, 500, &range_pcl813b_ai, NULL,
- 0x000c, 0x00, PCLx1x_IORANGE, 0},
- {"a821pgh", boardA821, 16, 8, 1, 16, 16, 0x0fff,
- 10000, 500, &range_a821pgh_ai, &range_unipolar5,
- 0x000c, 0x00, PCLx1x_IORANGE, 0},
- {"a822pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
- 10000, 500, &range_acl8112dg_ai, &range_unipolar5,
- 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
- {"a822pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
- 10000, 500, &range_acl8112hg_ai, &range_unipolar5,
- 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
- {"a823pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
- 8000, 500, &range_acl8112dg_ai, &range_unipolar5,
- 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
- {"a823pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
- 8000, 500, &range_acl8112hg_ai, &range_unipolar5,
- 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
- {"pcl813", boardPCL813, 32, 0, 0, 0, 0, 0x0fff,
- 0, 0, &range_pcl813b_ai, NULL,
- 0x0000, 0x00, PCLx1x_IORANGE, 0},
- {"pcl813b", boardPCL813B, 32, 0, 0, 0, 0, 0x0fff,
- 0, 0, &range_pcl813b_ai, NULL,
- 0x0000, 0x00, PCLx1x_IORANGE, 0},
- {"acl8113", boardACL8113, 32, 0, 0, 0, 0, 0x0fff,
- 0, 0, &range_acl8113_1_ai, NULL,
- 0x0000, 0x00, PCLx1x_IORANGE, 0},
- {"iso813", boardISO813, 32, 0, 0, 0, 0, 0x0fff,
- 0, 0, &range_iso813_1_ai, NULL,
- 0x0000, 0x00, PCLx1x_IORANGE, 0},
- {"acl8216", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
- 10000, 500, &range_pcl813b2_ai, &range_unipolar5,
- 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
- {"a826pg", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
- 10000, 500, &range_pcl813b2_ai, &range_unipolar5,
- 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
-};
-
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl812_board))
#define this_board ((const struct pcl812_board *)dev->board_ptr)
-static struct comedi_driver driver_pcl812 = {
- .driver_name = "pcl812",
- .module = THIS_MODULE,
- .attach = pcl812_attach,
- .detach = pcl812_detach,
- .board_name = &boardtypes[0].name,
- .num_names = n_boardtypes,
- .offset = sizeof(struct pcl812_board),
-};
-
-static int __init driver_pcl812_init_module(void)
-{
- return comedi_driver_register(&driver_pcl812);
-}
-
-static void __exit driver_pcl812_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_pcl812);
-}
-
-module_init(driver_pcl812_init_module);
-module_exit(driver_pcl812_cleanup_module);
-
struct pcl812_private {
unsigned char valid; /* =1 device is OK */
@@ -1356,9 +1271,6 @@ static void pcl812_reset(struct comedi_device *dev)
#endif
}
-/*
-==============================================================================
-*/
static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
int ret, subdev;
@@ -1702,19 +1614,79 @@ no_dma:
return 0;
}
-/*
-==============================================================================
- */
-static int pcl812_detach(struct comedi_device *dev)
+static void pcl812_detach(struct comedi_device *dev)
{
-
-#ifdef PCL812_EXTDEBUG
- printk(KERN_DEBUG "comedi%d: pcl812: remove\n", dev->minor);
-#endif
free_resources(dev);
- return 0;
}
+static const struct pcl812_board boardtypes[] = {
+ {"pcl812", boardPCL812, 16, 0, 2, 16, 16, 0x0fff,
+ 33000, 500, &range_bipolar10, &range_unipolar5,
+ 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
+ {"pcl812pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
+ 33000, 500, &range_pcl812pg_ai, &range_unipolar5,
+ 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
+ {"acl8112pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
+ 10000, 500, &range_pcl812pg_ai, &range_unipolar5,
+ 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
+ {"acl8112dg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
+ 10000, 500, &range_acl8112dg_ai, &range_unipolar5,
+ 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
+ {"acl8112hg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
+ 10000, 500, &range_acl8112hg_ai, &range_unipolar5,
+ 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
+ {"a821pgl", boardA821, 16, 8, 1, 16, 16, 0x0fff,
+ 10000, 500, &range_pcl813b_ai, &range_unipolar5,
+ 0x000c, 0x00, PCLx1x_IORANGE, 0},
+ {"a821pglnda", boardA821, 16, 8, 0, 0, 0, 0x0fff,
+ 10000, 500, &range_pcl813b_ai, NULL,
+ 0x000c, 0x00, PCLx1x_IORANGE, 0},
+ {"a821pgh", boardA821, 16, 8, 1, 16, 16, 0x0fff,
+ 10000, 500, &range_a821pgh_ai, &range_unipolar5,
+ 0x000c, 0x00, PCLx1x_IORANGE, 0},
+ {"a822pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
+ 10000, 500, &range_acl8112dg_ai, &range_unipolar5,
+ 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
+ {"a822pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
+ 10000, 500, &range_acl8112hg_ai, &range_unipolar5,
+ 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
+ {"a823pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
+ 8000, 500, &range_acl8112dg_ai, &range_unipolar5,
+ 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
+ {"a823pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
+ 8000, 500, &range_acl8112hg_ai, &range_unipolar5,
+ 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
+ {"pcl813", boardPCL813, 32, 0, 0, 0, 0, 0x0fff,
+ 0, 0, &range_pcl813b_ai, NULL,
+ 0x0000, 0x00, PCLx1x_IORANGE, 0},
+ {"pcl813b", boardPCL813B, 32, 0, 0, 0, 0, 0x0fff,
+ 0, 0, &range_pcl813b_ai, NULL,
+ 0x0000, 0x00, PCLx1x_IORANGE, 0},
+ {"acl8113", boardACL8113, 32, 0, 0, 0, 0, 0x0fff,
+ 0, 0, &range_acl8113_1_ai, NULL,
+ 0x0000, 0x00, PCLx1x_IORANGE, 0},
+ {"iso813", boardISO813, 32, 0, 0, 0, 0, 0x0fff,
+ 0, 0, &range_iso813_1_ai, NULL,
+ 0x0000, 0x00, PCLx1x_IORANGE, 0},
+ {"acl8216", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
+ 10000, 500, &range_pcl813b2_ai, &range_unipolar5,
+ 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
+ {"a826pg", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
+ 10000, 500, &range_pcl813b2_ai, &range_unipolar5,
+ 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
+};
+
+static struct comedi_driver pcl812_driver = {
+ .driver_name = "pcl812",
+ .module = THIS_MODULE,
+ .attach = pcl812_attach,
+ .detach = pcl812_detach,
+ .board_name = &boardtypes[0].name,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .offset = sizeof(struct pcl812_board),
+};
+module_comedi_driver(pcl812_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index 96cd7ec2ad53..cc67b6d46059 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -125,63 +125,14 @@ struct pcl816_board {
int i8254_osc_base; /* 1/frequency of on board oscilator in ns */
};
-static const struct pcl816_board boardtypes[] = {
- {"pcl816", 8, 16, 10000, 1, 16, 16, &range_pcl816,
- &range_pcl816, PCLx1x_RANGE,
- 0x00fc, /* IRQ mask */
- 0x0a, /* DMA mask */
- 0xffff, /* 16-bit card */
- 0xffff, /* D/A maxdata */
- 1024,
- 1, /* ao chan list */
- 100},
- {"pcl814b", 8, 16, 10000, 1, 16, 16, &range_pcl816,
- &range_pcl816, PCLx1x_RANGE,
- 0x00fc,
- 0x0a,
- 0x3fff, /* 14 bit card */
- 0x3fff,
- 1024,
- 1,
- 100},
-};
-
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl816_board))
#define devpriv ((struct pcl816_private *)dev->private)
#define this_board ((const struct pcl816_board *)dev->board_ptr)
-static int pcl816_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcl816_detach(struct comedi_device *dev);
-
#ifdef unused
static int RTC_lock; /* RTC lock */
static int RTC_timer_lock; /* RTC int lock */
#endif
-static struct comedi_driver driver_pcl816 = {
- .driver_name = "pcl816",
- .module = THIS_MODULE,
- .attach = pcl816_attach,
- .detach = pcl816_detach,
- .board_name = &boardtypes[0].name,
- .num_names = n_boardtypes,
- .offset = sizeof(struct pcl816_board),
-};
-
-static int __init driver_pcl816_init_module(void)
-{
- return comedi_driver_register(&driver_pcl816);
-}
-
-static void __exit driver_pcl816_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_pcl816);
-}
-
-module_init(driver_pcl816_init_module);
-module_exit(driver_pcl816_cleanup_module);
-
struct pcl816_private {
unsigned int dma; /* used DMA, 0=don't use DMA */
@@ -1075,46 +1026,6 @@ static int set_rtc_irq_bit(unsigned char bit)
}
#endif
-/*
-==============================================================================
- Free any resources that we have claimed
-*/
-static void free_resources(struct comedi_device *dev)
-{
- /* printk("free_resource()\n"); */
- if (dev->private) {
- pcl816_ai_cancel(dev, devpriv->sub_ai);
- pcl816_reset(dev);
- if (devpriv->dma)
- free_dma(devpriv->dma);
- if (devpriv->dmabuf[0])
- free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
- if (devpriv->dmabuf[1])
- free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
-#ifdef unused
- if (devpriv->rtc_irq)
- free_irq(devpriv->rtc_irq, dev);
- if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
- if (devpriv->rtc_iobase)
- release_region(devpriv->rtc_iobase,
- devpriv->rtc_iosize);
- }
-#endif
- }
-
- if (dev->irq)
- free_irq(dev->irq, dev);
- if (dev->iobase)
- release_region(dev->iobase, this_board->io_range);
- /* printk("free_resource() end\n"); */
-}
-
-/*
-==============================================================================
-
- Initialization
-
-*/
static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
int ret;
@@ -1340,21 +1251,69 @@ case COMEDI_SUBD_DO:
return 0;
}
-/*
-==============================================================================
- Removes device
- */
-static int pcl816_detach(struct comedi_device *dev)
+static void pcl816_detach(struct comedi_device *dev)
{
- DEBUG(printk(KERN_INFO "comedi%d: pcl816: remove\n", dev->minor);)
- free_resources(dev);
+ if (dev->private) {
+ pcl816_ai_cancel(dev, devpriv->sub_ai);
+ pcl816_reset(dev);
+ if (devpriv->dma)
+ free_dma(devpriv->dma);
+ if (devpriv->dmabuf[0])
+ free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
+ if (devpriv->dmabuf[1])
+ free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
+#ifdef unused
+ if (devpriv->rtc_irq)
+ free_irq(devpriv->rtc_irq, dev);
+ if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
+ if (devpriv->rtc_iobase)
+ release_region(devpriv->rtc_iobase,
+ devpriv->rtc_iosize);
+ }
+#endif
+ }
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ if (dev->iobase)
+ release_region(dev->iobase, this_board->io_range);
#ifdef unused
if (devpriv->dma_rtc)
RTC_lock--;
#endif
- return 0;
}
+static const struct pcl816_board boardtypes[] = {
+ {"pcl816", 8, 16, 10000, 1, 16, 16, &range_pcl816,
+ &range_pcl816, PCLx1x_RANGE,
+ 0x00fc, /* IRQ mask */
+ 0x0a, /* DMA mask */
+ 0xffff, /* 16-bit card */
+ 0xffff, /* D/A maxdata */
+ 1024,
+ 1, /* ao chan list */
+ 100},
+ {"pcl814b", 8, 16, 10000, 1, 16, 16, &range_pcl816,
+ &range_pcl816, PCLx1x_RANGE,
+ 0x00fc,
+ 0x0a,
+ 0x3fff, /* 14 bit card */
+ 0x3fff,
+ 1024,
+ 1,
+ 100},
+};
+
+static struct comedi_driver pcl816_driver = {
+ .driver_name = "pcl816",
+ .module = THIS_MODULE,
+ .attach = pcl816_attach,
+ .detach = pcl816_detach,
+ .board_name = &boardtypes[0].name,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .offset = sizeof(struct pcl816_board),
+};
+module_comedi_driver(pcl816_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index 7344a53a81c4..1406c9720f5d 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -247,10 +247,6 @@ static const struct comedi_lrange range718_bipolar0_5 =
static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
-static int pcl818_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcl818_detach(struct comedi_device *dev);
-
#ifdef unused
static int RTC_lock; /* RTC lock */
static int RTC_timer_lock; /* RTC int lock */
@@ -277,56 +273,6 @@ struct pcl818_board {
int is_818;
};
-static const struct pcl818_board boardtypes[] = {
- {"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai,
- &range_unipolar5, PCLx1x_RANGE, 0x00fc,
- 0x0a, 0xfff, 0xfff, 0, 1},
- {"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
- &range_unipolar5, PCLx1x_RANGE, 0x00fc,
- 0x0a, 0xfff, 0xfff, 0, 1},
- {"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
- &range_unipolar5, PCLx1x_RANGE, 0x00fc,
- 0x0a, 0xfff, 0xfff, 1, 1},
- {"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai,
- &range_unipolar5, PCLx1x_RANGE, 0x00fc,
- 0x0a, 0xfff, 0xfff, 1, 1},
- {"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai,
- &range_unipolar5, PCLx1x_RANGE, 0x00fc,
- 0x0a, 0xfff, 0xfff, 0, 1},
- {"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5,
- &range_unipolar5, PCLx1x_RANGE, 0x00fc,
- 0x0a, 0xfff, 0xfff, 0, 0},
- /* pcm3718 */
- {"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai,
- &range_unipolar5, PCLx1x_RANGE, 0x00fc,
- 0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ },
-};
-
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl818_board))
-
-static struct comedi_driver driver_pcl818 = {
- .driver_name = "pcl818",
- .module = THIS_MODULE,
- .attach = pcl818_attach,
- .detach = pcl818_detach,
- .board_name = &boardtypes[0].name,
- .num_names = n_boardtypes,
- .offset = sizeof(struct pcl818_board),
-};
-
-static int __init driver_pcl818_init_module(void)
-{
- return comedi_driver_register(&driver_pcl818);
-}
-
-static void __exit driver_pcl818_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_pcl818);
-}
-
-module_init(driver_pcl818_init_module);
-module_exit(driver_pcl818_cleanup_module);
-
struct pcl818_private {
unsigned int dma; /* used DMA, 0=don't use DMA */
@@ -1688,48 +1634,6 @@ static int rtc_setfreq_irq(int freq)
}
#endif
-/*
-==============================================================================
- Free any resources that we have claimed
-*/
-static void free_resources(struct comedi_device *dev)
-{
- /* printk("free_resource()\n"); */
- if (dev->private) {
- pcl818_ai_cancel(dev, devpriv->sub_ai);
- pcl818_reset(dev);
- if (devpriv->dma)
- free_dma(devpriv->dma);
- if (devpriv->dmabuf[0])
- free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
- if (devpriv->dmabuf[1])
- free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
-#ifdef unused
- if (devpriv->rtc_irq)
- free_irq(devpriv->rtc_irq, dev);
- if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
- if (devpriv->rtc_iobase)
- release_region(devpriv->rtc_iobase,
- devpriv->rtc_iosize);
- }
- if (devpriv->dma_rtc)
- RTC_lock--;
-#endif
- }
-
- if (dev->irq)
- free_irq(dev->irq, dev);
- if (dev->iobase)
- release_region(dev->iobase, devpriv->io_range);
- /* printk("free_resource() end\n"); */
-}
-
-/*
-==============================================================================
-
- Initialization
-
-*/
static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
int ret;
@@ -2020,17 +1924,71 @@ no_dma:
return 0;
}
-/*
-==============================================================================
- Removes device
- */
-static int pcl818_detach(struct comedi_device *dev)
+static void pcl818_detach(struct comedi_device *dev)
{
- /* printk("comedi%d: pcl818: remove\n", dev->minor); */
- free_resources(dev);
- return 0;
+ if (dev->private) {
+ pcl818_ai_cancel(dev, devpriv->sub_ai);
+ pcl818_reset(dev);
+ if (devpriv->dma)
+ free_dma(devpriv->dma);
+ if (devpriv->dmabuf[0])
+ free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
+ if (devpriv->dmabuf[1])
+ free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
+#ifdef unused
+ if (devpriv->rtc_irq)
+ free_irq(devpriv->rtc_irq, dev);
+ if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
+ if (devpriv->rtc_iobase)
+ release_region(devpriv->rtc_iobase,
+ devpriv->rtc_iosize);
+ }
+ if (devpriv->dma_rtc)
+ RTC_lock--;
+#endif
+ }
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ if (dev->iobase)
+ release_region(dev->iobase, devpriv->io_range);
}
+static const struct pcl818_board boardtypes[] = {
+ {"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai,
+ &range_unipolar5, PCLx1x_RANGE, 0x00fc,
+ 0x0a, 0xfff, 0xfff, 0, 1},
+ {"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
+ &range_unipolar5, PCLx1x_RANGE, 0x00fc,
+ 0x0a, 0xfff, 0xfff, 0, 1},
+ {"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
+ &range_unipolar5, PCLx1x_RANGE, 0x00fc,
+ 0x0a, 0xfff, 0xfff, 1, 1},
+ {"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai,
+ &range_unipolar5, PCLx1x_RANGE, 0x00fc,
+ 0x0a, 0xfff, 0xfff, 1, 1},
+ {"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai,
+ &range_unipolar5, PCLx1x_RANGE, 0x00fc,
+ 0x0a, 0xfff, 0xfff, 0, 1},
+ {"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5,
+ &range_unipolar5, PCLx1x_RANGE, 0x00fc,
+ 0x0a, 0xfff, 0xfff, 0, 0},
+ /* pcm3718 */
+ {"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai,
+ &range_unipolar5, PCLx1x_RANGE, 0x00fc,
+ 0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ },
+};
+
+static struct comedi_driver pcl818_driver = {
+ .driver_name = "pcl818",
+ .module = THIS_MODULE,
+ .attach = pcl818_attach,
+ .detach = pcl818_detach,
+ .board_name = &boardtypes[0].name,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .offset = sizeof(struct pcl818_board),
+};
+module_comedi_driver(pcl818_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
index f5c0bd17684c..7492b8f1d499 100644
--- a/drivers/staging/comedi/drivers/pcm3724.c
+++ b/drivers/staging/comedi/drivers/pcm3724.c
@@ -62,10 +62,6 @@ Copy/pasted/hacked from pcm724.c
#define CR_A_MODE(a) ((a)<<5)
#define CR_CW 0x80
-static int pcm3724_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcm3724_detach(struct comedi_device *dev);
-
struct pcm3724_board {
const char *name; /* driver name */
int dio; /* num of DIO */
@@ -80,36 +76,8 @@ struct priv_pcm3724 {
int dio_2;
};
-static const struct pcm3724_board boardtypes[] = {
- {"pcm3724", 48, 2, 0x00fc, PCM3724_SIZE,},
-};
-
-#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcm3724_board))
#define this_board ((const struct pcm3724_board *)dev->board_ptr)
-static struct comedi_driver driver_pcm3724 = {
- .driver_name = "pcm3724",
- .module = THIS_MODULE,
- .attach = pcm3724_attach,
- .detach = pcm3724_detach,
- .board_name = &boardtypes[0].name,
- .num_names = n_boardtypes,
- .offset = sizeof(struct pcm3724_board),
-};
-
-static int __init driver_pcm3724_init_module(void)
-{
- return comedi_driver_register(&driver_pcm3724);
-}
-
-static void __exit driver_pcm3724_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_pcm3724);
-}
-
-module_init(driver_pcm3724_init_module);
-module_exit(driver_pcm3724_cleanup_module);
-
/* (setq c-basic-offset 8) */
static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
@@ -305,7 +273,7 @@ static int pcm3724_attach(struct comedi_device *dev,
return 0;
}
-static int pcm3724_detach(struct comedi_device *dev)
+static void pcm3724_detach(struct comedi_device *dev)
{
int i;
@@ -315,10 +283,23 @@ static int pcm3724_detach(struct comedi_device *dev)
}
if (dev->iobase)
release_region(dev->iobase, this_board->io_range);
-
- return 0;
}
+static const struct pcm3724_board boardtypes[] = {
+ { "pcm3724", 48, 2, 0x00fc, PCM3724_SIZE, },
+};
+
+static struct comedi_driver pcm3724_driver = {
+ .driver_name = "pcm3724",
+ .module = THIS_MODULE,
+ .attach = pcm3724_attach,
+ .detach = pcm3724_detach,
+ .board_name = &boardtypes[0].name,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .offset = sizeof(struct pcm3724_board),
+};
+module_comedi_driver(pcm3724_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
index bada6b236ff1..f8d1c644daf8 100644
--- a/drivers/staging/comedi/drivers/pcm3730.c
+++ b/drivers/staging/comedi/drivers/pcm3730.c
@@ -28,29 +28,6 @@ Configuration options:
#define PCM3730_DIB 2
#define PCM3730_DIC 3
-static int pcm3730_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcm3730_detach(struct comedi_device *dev);
-static struct comedi_driver driver_pcm3730 = {
- .driver_name = "pcm3730",
- .module = THIS_MODULE,
- .attach = pcm3730_attach,
- .detach = pcm3730_detach,
-};
-
-static int __init driver_pcm3730_init_module(void)
-{
- return comedi_driver_register(&driver_pcm3730);
-}
-
-static void __exit driver_pcm3730_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_pcm3730);
-}
-
-module_init(driver_pcm3730_init_module);
-module_exit(driver_pcm3730_cleanup_module);
-
static int pcm3730_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -156,16 +133,20 @@ static int pcm3730_attach(struct comedi_device *dev,
return 0;
}
-static int pcm3730_detach(struct comedi_device *dev)
+static void pcm3730_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: pcm3730: remove\n", dev->minor);
-
if (dev->iobase)
release_region(dev->iobase, PCM3730_SIZE);
-
- return 0;
}
+static struct comedi_driver pcm3730_driver = {
+ .driver_name = "pcm3730",
+ .module = THIS_MODULE,
+ .attach = pcm3730_attach,
+ .detach = pcm3730_detach,
+};
+module_comedi_driver(pcm3730_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
index 23b3d777340c..1ec7d5cb346a 100644
--- a/drivers/staging/comedi/drivers/pcmad.c
+++ b/drivers/staging/comedi/drivers/pcmad.c
@@ -57,19 +57,8 @@ struct pcmad_board_struct {
const char *name;
int n_ai_bits;
};
-static const struct pcmad_board_struct pcmad_boards[] = {
- {
- .name = "pcmad12",
- .n_ai_bits = 12,
- },
- {
- .name = "pcmad16",
- .n_ai_bits = 16,
- },
-};
#define this_board ((const struct pcmad_board_struct *)(dev->board_ptr))
-#define n_pcmad_boards ARRAY_SIZE(pcmad_boards)
struct pcmad_priv_struct {
int differential;
@@ -77,31 +66,6 @@ struct pcmad_priv_struct {
};
#define devpriv ((struct pcmad_priv_struct *)dev->private)
-static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int pcmad_detach(struct comedi_device *dev);
-static struct comedi_driver driver_pcmad = {
- .driver_name = "pcmad",
- .module = THIS_MODULE,
- .attach = pcmad_attach,
- .detach = pcmad_detach,
- .board_name = &pcmad_boards[0].name,
- .num_names = n_pcmad_boards,
- .offset = sizeof(pcmad_boards[0]),
-};
-
-static int __init driver_pcmad_init_module(void)
-{
- return comedi_driver_register(&driver_pcmad);
-}
-
-static void __exit driver_pcmad_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_pcmad);
-}
-
-module_init(driver_pcmad_init_module);
-module_exit(driver_pcmad_cleanup_module);
-
#define TIMEOUT 100
static int pcmad_ai_insn_read(struct comedi_device *dev,
@@ -175,19 +139,34 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int pcmad_detach(struct comedi_device *dev)
+static void pcmad_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: pcmad: remove\n", dev->minor);
-
if (dev->irq)
free_irq(dev->irq, dev);
-
if (dev->iobase)
release_region(dev->iobase, PCMAD_SIZE);
-
- return 0;
}
+static const struct pcmad_board_struct pcmad_boards[] = {
+ {
+ .name = "pcmad12",
+ .n_ai_bits = 12,
+ }, {
+ .name = "pcmad16",
+ .n_ai_bits = 16,
+ },
+};
+static struct comedi_driver pcmad_driver = {
+ .driver_name = "pcmad",
+ .module = THIS_MODULE,
+ .attach = pcmad_attach,
+ .detach = pcmad_detach,
+ .board_name = &pcmad_boards[0].name,
+ .num_names = ARRAY_SIZE(pcmad_boards),
+ .offset = sizeof(pcmad_boards[0]),
+};
+module_comedi_driver(pcmad_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
index 0e9ffa28d745..4786148b4fd0 100644
--- a/drivers/staging/comedi/drivers/pcmda12.c
+++ b/drivers/staging/comedi/drivers/pcmda12.c
@@ -80,12 +80,6 @@ static const struct comedi_lrange pcmda12_ranges = {
}
};
-static const struct pcmda12_board pcmda12_boards[] = {
- {
- .name = "pcmda12",
- },
-};
-
/*
* Useful for shorthand access to the particular board structure
*/
@@ -99,137 +93,6 @@ struct pcmda12_private {
#define devpriv ((struct pcmda12_private *)(dev->private))
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int pcmda12_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcmda12_detach(struct comedi_device *dev);
-
-static void zero_chans(struct comedi_device *dev);
-
-static struct comedi_driver driver = {
- .driver_name = "pcmda12",
- .module = THIS_MODULE,
- .attach = pcmda12_attach,
- .detach = pcmda12_detach,
-/* It is not necessary to implement the following members if you are
- * writing a driver for a ISA PnP or PCI card */
- /* Most drivers will support multiple types of boards by
- * having an array of board structures. These were defined
- * in pcmda12_boards[] above. Note that the element 'name'
- * was first in the structure -- Comedi uses this fact to
- * extract the name of the board without knowing any details
- * about the structure except for its length.
- * When a device is attached (by comedi_config), the name
- * of the device is given to Comedi, and Comedi tries to
- * match it by going through the list of board names. If
- * there is a match, the address of the pointer is put
- * into dev->board_ptr and driver->attach() is called.
- *
- * Note that these are not necessary if you can determine
- * the type of board in software. ISA PnP, PCI, and PCMCIA
- * devices are such boards.
- */
- .board_name = &pcmda12_boards[0].name,
- .offset = sizeof(struct pcmda12_board),
- .num_names = ARRAY_SIZE(pcmda12_boards),
-};
-
-static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
-static int pcmda12_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- unsigned long iobase;
-
- iobase = it->options[0];
- printk(KERN_INFO
- "comedi%d: %s: io: %lx %s ", dev->minor, driver.driver_name,
- iobase, it->options[1] ? "simultaneous xfer mode enabled" : "");
-
- if (!request_region(iobase, IOSIZE, driver.driver_name)) {
- printk("I/O port conflict\n");
- return -EIO;
- }
- dev->iobase = iobase;
-
-/*
- * Initialize dev->board_name. Note that we can use the "thisboard"
- * macro now, since we just initialized it in the last line.
- */
- dev->board_name = thisboard->name;
-
-/*
- * Allocate the private structure area. alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
- if (alloc_private(dev, sizeof(struct pcmda12_private)) < 0) {
- printk(KERN_ERR "cannot allocate private data structure\n");
- return -ENOMEM;
- }
-
- devpriv->simultaneous_xfer_mode = it->options[1];
-
- /*
- * Allocate the subdevice structures. alloc_subdevice() is a
- * convenient macro defined in comedidev.h.
- *
- * Allocate 2 subdevs (32 + 16 DIO lines) or 3 32 DIO subdevs for the
- * 96-channel version of the board.
- */
- if (alloc_subdevices(dev, 1) < 0) {
- printk(KERN_ERR "cannot allocate subdevice data structures\n");
- return -ENOMEM;
- }
-
- s = dev->subdevices;
- s->private = NULL;
- s->maxdata = (0x1 << BITS) - 1;
- s->range_table = &pcmda12_ranges;
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = CHANS;
- s->insn_write = &ao_winsn;
- s->insn_read = &ao_rinsn;
-
- zero_chans(dev); /* clear out all the registers, basically */
-
- printk(KERN_INFO "attached\n");
-
- return 1;
-}
-
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int pcmda12_detach(struct comedi_device *dev)
-{
- printk(KERN_INFO
- "comedi%d: %s: remove\n", dev->minor, driver.driver_name);
- if (dev->iobase)
- release_region(dev->iobase, IOSIZE);
- return 0;
-}
-
static void zero_chans(struct comedi_device *dev)
{ /* sets up an
ASIC chip to defaults */
@@ -301,22 +164,91 @@ static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
return i;
}
+static int pcmda12_attach(struct comedi_device *dev,
+ struct comedi_devconfig *it)
+{
+ struct comedi_subdevice *s;
+ unsigned long iobase;
+
+ iobase = it->options[0];
+ printk(KERN_INFO
+ "comedi%d: %s: io: %lx %s ", dev->minor, dev->driver->driver_name,
+ iobase, it->options[1] ? "simultaneous xfer mode enabled" : "");
+
+ if (!request_region(iobase, IOSIZE, dev->driver->driver_name)) {
+ printk("I/O port conflict\n");
+ return -EIO;
+ }
+ dev->iobase = iobase;
+
/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
+ * Initialize dev->board_name. Note that we can use the "thisboard"
+ * macro now, since we just initialized it in the last line.
*/
-static int __init driver_init_module(void)
-{
- return comedi_driver_register(&driver);
+ dev->board_name = thisboard->name;
+
+/*
+ * Allocate the private structure area. alloc_private() is a
+ * convenient macro defined in comedidev.h.
+ */
+ if (alloc_private(dev, sizeof(struct pcmda12_private)) < 0) {
+ printk(KERN_ERR "cannot allocate private data structure\n");
+ return -ENOMEM;
+ }
+
+ devpriv->simultaneous_xfer_mode = it->options[1];
+
+ /*
+ * Allocate the subdevice structures. alloc_subdevice() is a
+ * convenient macro defined in comedidev.h.
+ *
+ * Allocate 2 subdevs (32 + 16 DIO lines) or 3 32 DIO subdevs for the
+ * 96-channel version of the board.
+ */
+ if (alloc_subdevices(dev, 1) < 0) {
+ printk(KERN_ERR "cannot allocate subdevice data structures\n");
+ return -ENOMEM;
+ }
+
+ s = dev->subdevices;
+ s->private = NULL;
+ s->maxdata = (0x1 << BITS) - 1;
+ s->range_table = &pcmda12_ranges;
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = CHANS;
+ s->insn_write = &ao_winsn;
+ s->insn_read = &ao_rinsn;
+
+ zero_chans(dev); /* clear out all the registers, basically */
+
+ printk(KERN_INFO "attached\n");
+
+ return 1;
}
-static void __exit driver_cleanup_module(void)
+static void pcmda12_detach(struct comedi_device *dev)
{
- comedi_driver_unregister(&driver);
+ if (dev->iobase)
+ release_region(dev->iobase, IOSIZE);
}
-module_init(driver_init_module);
-module_exit(driver_cleanup_module);
+static const struct pcmda12_board pcmda12_boards[] = {
+ {
+ .name = "pcmda12",
+ },
+};
+
+static struct comedi_driver pcmda12_driver = {
+ .driver_name = "pcmda12",
+ .module = THIS_MODULE,
+ .attach = pcmda12_attach,
+ .detach = pcmda12_detach,
+ .board_name = &pcmda12_boards[0].name,
+ .offset = sizeof(struct pcmda12_board),
+ .num_names = ARRAY_SIZE(pcmda12_boards),
+};
+module_comedi_driver(pcmda12_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index eddac00e4e29..efed168d2bac 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -145,13 +145,6 @@ Configuration Options:
#define PAGE_ENAB 2
#define PAGE_INT_ID 3
-static int ai_rinsn(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
-static int ao_rinsn(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
-static int ao_winsn(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
-
/*
* Board descriptions for two imaginary boards. Describing the
* boards in this way is optional, and completely driver-dependent.
@@ -190,23 +183,6 @@ static const struct comedi_lrange ranges_ao = {
RANGE(-2.5, 2.5), RANGE(-2.5, 7.5)}
};
-static const struct pcmmio_board pcmmio_boards[] = {
- {
- .name = "pcmmio",
- .dio_num_asics = 1,
- .dio_num_ports = 6,
- .total_iosize = 32,
- .ai_bits = 16,
- .ao_bits = 16,
- .n_ai_chans = 16,
- .n_ao_chans = 8,
- .ai_range_table = &ranges_ai,
- .ao_range_table = &ranges_ao,
- .ai_rinsn = ai_rinsn,
- .ao_rinsn = ao_rinsn,
- .ao_winsn = ao_winsn},
-};
-
/*
* Useful for shorthand access to the particular board structure
*/
@@ -293,312 +269,6 @@ struct pcmmio_private {
*/
#define devpriv ((struct pcmmio_private *)dev->private)
#define subpriv ((struct pcmmio_subdev_private *)s->private)
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int pcmmio_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcmmio_detach(struct comedi_device *dev);
-
-static struct comedi_driver driver = {
- .driver_name = "pcmmio",
- .module = THIS_MODULE,
- .attach = pcmmio_attach,
- .detach = pcmmio_detach,
-/* It is not necessary to implement the following members if you are
- * writing a driver for a ISA PnP or PCI card */
- /* Most drivers will support multiple types of boards by
- * having an array of board structures. These were defined
- * in pcmmio_boards[] above. Note that the element 'name'
- * was first in the structure -- Comedi uses this fact to
- * extract the name of the board without knowing any details
- * about the structure except for its length.
- * When a device is attached (by comedi_config), the name
- * of the device is given to Comedi, and Comedi tries to
- * match it by going through the list of board names. If
- * there is a match, the address of the pointer is put
- * into dev->board_ptr and driver->attach() is called.
- *
- * Note that these are not necessary if you can determine
- * the type of board in software. ISA PnP, PCI, and PCMCIA
- * devices are such boards.
- */
- .board_name = &pcmmio_boards[0].name,
- .offset = sizeof(struct pcmmio_board),
- .num_names = ARRAY_SIZE(pcmmio_boards),
-};
-
-static int pcmmio_dio_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int pcmmio_dio_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static irqreturn_t interrupt_pcmmio(int irq, void *d);
-static void pcmmio_stop_intr(struct comedi_device *, struct comedi_subdevice *);
-static int pcmmio_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
-static int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
-static int pcmmio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_cmd *cmd);
-
-/* some helper functions to deal with specifics of this device's registers */
-/* sets up/clears ASIC chips to defaults */
-static void init_asics(struct comedi_device *dev);
-static void switch_page(struct comedi_device *dev, int asic, int page);
-#ifdef notused
-static void lock_port(struct comedi_device *dev, int asic, int port);
-static void unlock_port(struct comedi_device *dev, int asic, int port);
-#endif
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
-static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic,
- thisasic_chanct = 0;
- unsigned long iobase;
- unsigned int irq[MAX_ASICS];
-
- iobase = it->options[0];
- irq[0] = it->options[1];
-
- printk(KERN_INFO "comedi%d: %s: io: %lx attaching...\n", dev->minor,
- driver.driver_name, iobase);
-
- dev->iobase = iobase;
-
- if (!iobase || !request_region(iobase,
- thisboard->total_iosize,
- driver.driver_name)) {
- printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor);
- return -EIO;
- }
-
-/*
- * Initialize dev->board_name. Note that we can use the "thisboard"
- * macro now, since we just initialized it in the last line.
- */
- dev->board_name = thisboard->name;
-
-/*
- * Allocate the private structure area. alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
- if (alloc_private(dev, sizeof(struct pcmmio_private)) < 0) {
- printk(KERN_ERR "comedi%d: cannot allocate private data structure\n",
- dev->minor);
- return -ENOMEM;
- }
-
- for (asic = 0; asic < MAX_ASICS; ++asic) {
- devpriv->asics[asic].num = asic;
- devpriv->asics[asic].iobase =
- dev->iobase + 16 + asic * ASIC_IOSIZE;
- /*
- * this gets actually set at the end of this function when we
- * request_irqs
- */
- devpriv->asics[asic].irq = 0;
- spin_lock_init(&devpriv->asics[asic].spinlock);
- }
-
- chans_left = CHANS_PER_ASIC * thisboard->dio_num_asics;
- n_dio_subdevs = CALC_N_DIO_SUBDEVS(chans_left);
- n_subdevs = n_dio_subdevs + 2;
- devpriv->sprivs =
- kcalloc(n_subdevs, sizeof(struct pcmmio_subdev_private),
- GFP_KERNEL);
- if (!devpriv->sprivs) {
- printk(KERN_ERR "comedi%d: cannot allocate subdevice private data structures\n",
- dev->minor);
- return -ENOMEM;
- }
- /*
- * Allocate the subdevice structures. alloc_subdevice() is a
- * convenient macro defined in comedidev.h.
- *
- * Allocate 1 AI + 1 AO + 2 DIO subdevs (24 lines per DIO)
- */
- if (alloc_subdevices(dev, n_subdevs) < 0) {
- printk(KERN_ERR "comedi%d: cannot allocate subdevice data structures\n",
- dev->minor);
- return -ENOMEM;
- }
-
- /* First, AI */
- sdev_no = 0;
- s = dev->subdevices + sdev_no;
- s->private = devpriv->sprivs + sdev_no;
- s->maxdata = (1 << thisboard->ai_bits) - 1;
- s->range_table = thisboard->ai_range_table;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
- s->type = COMEDI_SUBD_AI;
- s->n_chan = thisboard->n_ai_chans;
- s->len_chanlist = s->n_chan;
- s->insn_read = thisboard->ai_rinsn;
- subpriv->iobase = dev->iobase + 0;
- /* initialize the resource enable register by clearing it */
- outb(0, subpriv->iobase + 3);
- outb(0, subpriv->iobase + 4 + 3);
-
- /* Next, AO */
- ++sdev_no;
- s = dev->subdevices + sdev_no;
- s->private = devpriv->sprivs + sdev_no;
- s->maxdata = (1 << thisboard->ao_bits) - 1;
- s->range_table = thisboard->ao_range_table;
- s->subdev_flags = SDF_READABLE;
- s->type = COMEDI_SUBD_AO;
- s->n_chan = thisboard->n_ao_chans;
- s->len_chanlist = s->n_chan;
- s->insn_read = thisboard->ao_rinsn;
- s->insn_write = thisboard->ao_winsn;
- subpriv->iobase = dev->iobase + 8;
- /* initialize the resource enable register by clearing it */
- outb(0, subpriv->iobase + 3);
- outb(0, subpriv->iobase + 4 + 3);
-
- ++sdev_no;
- port = 0;
- asic = 0;
- for (; sdev_no < (int)dev->n_subdevices; ++sdev_no) {
- int byte_no;
-
- s = dev->subdevices + sdev_no;
- s->private = devpriv->sprivs + sdev_no;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->type = COMEDI_SUBD_DIO;
- s->insn_bits = pcmmio_dio_insn_bits;
- s->insn_config = pcmmio_dio_insn_config;
- s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV);
- subpriv->dio.intr.asic = -1;
- subpriv->dio.intr.first_chan = -1;
- subpriv->dio.intr.asic_chan = -1;
- subpriv->dio.intr.num_asic_chans = -1;
- subpriv->dio.intr.active = 0;
- s->len_chanlist = 1;
-
- /* save the ioport address for each 'port' of 8 channels in the
- subdevice */
- for (byte_no = 0; byte_no < PORTS_PER_SUBDEV; ++byte_no, ++port) {
- if (port >= PORTS_PER_ASIC) {
- port = 0;
- ++asic;
- thisasic_chanct = 0;
- }
- subpriv->iobases[byte_no] =
- devpriv->asics[asic].iobase + port;
-
- if (thisasic_chanct <
- CHANS_PER_PORT * INTR_PORTS_PER_ASIC
- && subpriv->dio.intr.asic < 0) {
- /*
- * this is an interrupt subdevice,
- * so setup the struct
- */
- subpriv->dio.intr.asic = asic;
- subpriv->dio.intr.active = 0;
- subpriv->dio.intr.stop_count = 0;
- subpriv->dio.intr.first_chan = byte_no * 8;
- subpriv->dio.intr.asic_chan = thisasic_chanct;
- subpriv->dio.intr.num_asic_chans =
- s->n_chan - subpriv->dio.intr.first_chan;
- s->cancel = pcmmio_cancel;
- s->do_cmd = pcmmio_cmd;
- s->do_cmdtest = pcmmio_cmdtest;
- s->len_chanlist =
- subpriv->dio.intr.num_asic_chans;
- }
- thisasic_chanct += CHANS_PER_PORT;
- }
- spin_lock_init(&subpriv->dio.intr.spinlock);
-
- chans_left -= s->n_chan;
-
- if (!chans_left) {
- /*
- * reset the asic to our first asic,
- * to do intr subdevs
- */
- asic = 0;
- port = 0;
- }
-
- }
-
- init_asics(dev); /* clear out all the registers, basically */
-
- for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) {
- if (irq[asic]
- && request_irq(irq[asic], interrupt_pcmmio,
- IRQF_SHARED, thisboard->name, dev)) {
- int i;
- /* unroll the allocated irqs.. */
- for (i = asic - 1; i >= 0; --i) {
- free_irq(irq[i], dev);
- devpriv->asics[i].irq = irq[i] = 0;
- }
- irq[asic] = 0;
- }
- devpriv->asics[asic].irq = irq[asic];
- }
-
- dev->irq = irq[0]; /*
- * grr.. wish comedi dev struct supported
- * multiple irqs..
- */
-
- if (irq[0]) {
- printk(KERN_DEBUG "comedi%d: irq: %u\n", dev->minor, irq[0]);
- if (thisboard->dio_num_asics == 2 && irq[1])
- printk(KERN_DEBUG "comedi%d: second ASIC irq: %u\n",
- dev->minor, irq[1]);
- } else {
- printk(KERN_INFO "comedi%d: (IRQ mode disabled)\n", dev->minor);
- }
-
- printk(KERN_INFO "comedi%d: attached\n", dev->minor);
-
- return 1;
-}
-
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int pcmmio_detach(struct comedi_device *dev)
-{
- int i;
-
- printk(KERN_INFO "comedi%d: %s: remove\n", dev->minor, driver.driver_name);
- if (dev->iobase)
- release_region(dev->iobase, thisboard->total_iosize);
-
- for (i = 0; i < MAX_ASICS; ++i) {
- if (devpriv && devpriv->asics[i].irq)
- free_irq(devpriv->asics[i].irq, dev);
- }
-
- if (devpriv && devpriv->sprivs)
- kfree(devpriv->sprivs);
-
- return 0;
-}
/* DIO devices are slightly special. Although it is possible to
* implement the insn_read/insn_write interface, it is much more
@@ -667,7 +337,7 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev,
}
#ifdef DAMMIT_ITS_BROKEN
/* DEBUG */
- printk("data_out_byte %02x\n", (unsigned)byte);
+ printk(KERN_DEBUG "data_out_byte %02x\n", (unsigned)byte);
#endif
/* save the digital input lines for this byte.. */
s->state |= ((unsigned int)byte) << offset;
@@ -751,6 +421,21 @@ static int pcmmio_dio_insn_config(struct comedi_device *dev,
return insn->n;
}
+static void switch_page(struct comedi_device *dev, int asic, int page)
+{
+ if (asic < 0 || asic >= thisboard->dio_num_asics)
+ return; /* paranoia */
+ if (page < 0 || page >= NUM_PAGES)
+ return; /* more paranoia */
+
+ devpriv->asics[asic].pagelock &= ~REG_PAGE_MASK;
+ devpriv->asics[asic].pagelock |= page << REG_PAGE_BITOFFSET;
+
+ /* now write out the shadow register */
+ outb(devpriv->asics[asic].pagelock,
+ devpriv->asics[asic].iobase + REG_PAGELOCK);
+}
+
static void init_asics(struct comedi_device *dev)
{ /* sets up an
ASIC chip to defaults */
@@ -788,21 +473,6 @@ static void init_asics(struct comedi_device *dev)
}
}
-static void switch_page(struct comedi_device *dev, int asic, int page)
-{
- if (asic < 0 || asic >= thisboard->dio_num_asics)
- return; /* paranoia */
- if (page < 0 || page >= NUM_PAGES)
- return; /* more paranoia */
-
- devpriv->asics[asic].pagelock &= ~REG_PAGE_MASK;
- devpriv->asics[asic].pagelock |= page << REG_PAGE_BITOFFSET;
-
- /* now write out the shadow register */
- outb(devpriv->asics[asic].pagelock,
- devpriv->asics[asic].iobase + REG_PAGELOCK);
-}
-
#ifdef notused
static void lock_port(struct comedi_device *dev, int asic, int port)
{
@@ -831,6 +501,27 @@ static void unlock_port(struct comedi_device *dev, int asic, int port)
}
#endif /* notused */
+static void pcmmio_stop_intr(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ int nports, firstport, asic, port;
+
+ asic = subpriv->dio.intr.asic;
+ if (asic < 0)
+ return; /* not an interrupt subdev */
+
+ subpriv->dio.intr.enabled_mask = 0;
+ subpriv->dio.intr.active = 0;
+ s->async->inttrig = 0;
+ nports = subpriv->dio.intr.num_asic_chans / CHANS_PER_PORT;
+ firstport = subpriv->dio.intr.asic_chan / CHANS_PER_PORT;
+ switch_page(dev, asic, PAGE_ENAB);
+ for (port = firstport; port < firstport + nports; ++port) {
+ /* disable all intrs for this subdev.. */
+ outb(0, devpriv->asics[asic].iobase + REG_ENAB0 + port);
+ }
+}
+
static irqreturn_t interrupt_pcmmio(int irq, void *d)
{
int asic, got1 = 0;
@@ -991,27 +682,6 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d)
return IRQ_HANDLED;
}
-static void pcmmio_stop_intr(struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- int nports, firstport, asic, port;
-
- asic = subpriv->dio.intr.asic;
- if (asic < 0)
- return; /* not an interrupt subdev */
-
- subpriv->dio.intr.enabled_mask = 0;
- subpriv->dio.intr.active = 0;
- s->async->inttrig = 0;
- nports = subpriv->dio.intr.num_asic_chans / CHANS_PER_PORT;
- firstport = subpriv->dio.intr.asic_chan / CHANS_PER_PORT;
- switch_page(dev, asic, PAGE_ENAB);
- for (port = firstport; port < firstport + nports; ++port) {
- /* disable all intrs for this subdev.. */
- outb(0, devpriv->asics[asic].iobase + REG_ENAB0 + port);
- }
-}
-
static int pcmmio_start_intr(struct comedi_device *dev,
struct comedi_subdevice *s)
{
@@ -1340,22 +1010,261 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
return n;
}
+static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+{
+ struct comedi_subdevice *s;
+ int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic,
+ thisasic_chanct = 0;
+ unsigned long iobase;
+ unsigned int irq[MAX_ASICS];
+
+ iobase = it->options[0];
+ irq[0] = it->options[1];
+
+ printk(KERN_INFO "comedi%d: %s: io: %lx attaching...\n", dev->minor,
+ dev->driver->driver_name, iobase);
+
+ dev->iobase = iobase;
+
+ if (!iobase || !request_region(iobase,
+ thisboard->total_iosize,
+ dev->driver->driver_name)) {
+ printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor);
+ return -EIO;
+ }
+
/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
+ * Initialize dev->board_name. Note that we can use the "thisboard"
+ * macro now, since we just initialized it in the last line.
*/
-static int __init driver_init_module(void)
-{
- return comedi_driver_register(&driver);
+ dev->board_name = thisboard->name;
+
+/*
+ * Allocate the private structure area. alloc_private() is a
+ * convenient macro defined in comedidev.h.
+ */
+ if (alloc_private(dev, sizeof(struct pcmmio_private)) < 0) {
+ printk(KERN_ERR "comedi%d: cannot allocate private data structure\n",
+ dev->minor);
+ return -ENOMEM;
+ }
+
+ for (asic = 0; asic < MAX_ASICS; ++asic) {
+ devpriv->asics[asic].num = asic;
+ devpriv->asics[asic].iobase =
+ dev->iobase + 16 + asic * ASIC_IOSIZE;
+ /*
+ * this gets actually set at the end of this function when we
+ * request_irqs
+ */
+ devpriv->asics[asic].irq = 0;
+ spin_lock_init(&devpriv->asics[asic].spinlock);
+ }
+
+ chans_left = CHANS_PER_ASIC * thisboard->dio_num_asics;
+ n_dio_subdevs = CALC_N_DIO_SUBDEVS(chans_left);
+ n_subdevs = n_dio_subdevs + 2;
+ devpriv->sprivs =
+ kcalloc(n_subdevs, sizeof(struct pcmmio_subdev_private),
+ GFP_KERNEL);
+ if (!devpriv->sprivs) {
+ printk(KERN_ERR "comedi%d: cannot allocate subdevice private data structures\n",
+ dev->minor);
+ return -ENOMEM;
+ }
+ /*
+ * Allocate the subdevice structures. alloc_subdevice() is a
+ * convenient macro defined in comedidev.h.
+ *
+ * Allocate 1 AI + 1 AO + 2 DIO subdevs (24 lines per DIO)
+ */
+ if (alloc_subdevices(dev, n_subdevs) < 0) {
+ printk(KERN_ERR "comedi%d: cannot allocate subdevice data structures\n",
+ dev->minor);
+ return -ENOMEM;
+ }
+
+ /* First, AI */
+ sdev_no = 0;
+ s = dev->subdevices + sdev_no;
+ s->private = devpriv->sprivs + sdev_no;
+ s->maxdata = (1 << thisboard->ai_bits) - 1;
+ s->range_table = thisboard->ai_range_table;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
+ s->type = COMEDI_SUBD_AI;
+ s->n_chan = thisboard->n_ai_chans;
+ s->len_chanlist = s->n_chan;
+ s->insn_read = thisboard->ai_rinsn;
+ subpriv->iobase = dev->iobase + 0;
+ /* initialize the resource enable register by clearing it */
+ outb(0, subpriv->iobase + 3);
+ outb(0, subpriv->iobase + 4 + 3);
+
+ /* Next, AO */
+ ++sdev_no;
+ s = dev->subdevices + sdev_no;
+ s->private = devpriv->sprivs + sdev_no;
+ s->maxdata = (1 << thisboard->ao_bits) - 1;
+ s->range_table = thisboard->ao_range_table;
+ s->subdev_flags = SDF_READABLE;
+ s->type = COMEDI_SUBD_AO;
+ s->n_chan = thisboard->n_ao_chans;
+ s->len_chanlist = s->n_chan;
+ s->insn_read = thisboard->ao_rinsn;
+ s->insn_write = thisboard->ao_winsn;
+ subpriv->iobase = dev->iobase + 8;
+ /* initialize the resource enable register by clearing it */
+ outb(0, subpriv->iobase + 3);
+ outb(0, subpriv->iobase + 4 + 3);
+
+ ++sdev_no;
+ port = 0;
+ asic = 0;
+ for (; sdev_no < (int)dev->n_subdevices; ++sdev_no) {
+ int byte_no;
+
+ s = dev->subdevices + sdev_no;
+ s->private = devpriv->sprivs + sdev_no;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->type = COMEDI_SUBD_DIO;
+ s->insn_bits = pcmmio_dio_insn_bits;
+ s->insn_config = pcmmio_dio_insn_config;
+ s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV);
+ subpriv->dio.intr.asic = -1;
+ subpriv->dio.intr.first_chan = -1;
+ subpriv->dio.intr.asic_chan = -1;
+ subpriv->dio.intr.num_asic_chans = -1;
+ subpriv->dio.intr.active = 0;
+ s->len_chanlist = 1;
+
+ /* save the ioport address for each 'port' of 8 channels in the
+ subdevice */
+ for (byte_no = 0; byte_no < PORTS_PER_SUBDEV; ++byte_no, ++port) {
+ if (port >= PORTS_PER_ASIC) {
+ port = 0;
+ ++asic;
+ thisasic_chanct = 0;
+ }
+ subpriv->iobases[byte_no] =
+ devpriv->asics[asic].iobase + port;
+
+ if (thisasic_chanct <
+ CHANS_PER_PORT * INTR_PORTS_PER_ASIC
+ && subpriv->dio.intr.asic < 0) {
+ /*
+ * this is an interrupt subdevice,
+ * so setup the struct
+ */
+ subpriv->dio.intr.asic = asic;
+ subpriv->dio.intr.active = 0;
+ subpriv->dio.intr.stop_count = 0;
+ subpriv->dio.intr.first_chan = byte_no * 8;
+ subpriv->dio.intr.asic_chan = thisasic_chanct;
+ subpriv->dio.intr.num_asic_chans =
+ s->n_chan - subpriv->dio.intr.first_chan;
+ s->cancel = pcmmio_cancel;
+ s->do_cmd = pcmmio_cmd;
+ s->do_cmdtest = pcmmio_cmdtest;
+ s->len_chanlist =
+ subpriv->dio.intr.num_asic_chans;
+ }
+ thisasic_chanct += CHANS_PER_PORT;
+ }
+ spin_lock_init(&subpriv->dio.intr.spinlock);
+
+ chans_left -= s->n_chan;
+
+ if (!chans_left) {
+ /*
+ * reset the asic to our first asic,
+ * to do intr subdevs
+ */
+ asic = 0;
+ port = 0;
+ }
+
+ }
+
+ init_asics(dev); /* clear out all the registers, basically */
+
+ for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) {
+ if (irq[asic]
+ && request_irq(irq[asic], interrupt_pcmmio,
+ IRQF_SHARED, thisboard->name, dev)) {
+ int i;
+ /* unroll the allocated irqs.. */
+ for (i = asic - 1; i >= 0; --i) {
+ free_irq(irq[i], dev);
+ devpriv->asics[i].irq = irq[i] = 0;
+ }
+ irq[asic] = 0;
+ }
+ devpriv->asics[asic].irq = irq[asic];
+ }
+
+ dev->irq = irq[0]; /*
+ * grr.. wish comedi dev struct supported
+ * multiple irqs..
+ */
+
+ if (irq[0]) {
+ printk(KERN_DEBUG "comedi%d: irq: %u\n", dev->minor, irq[0]);
+ if (thisboard->dio_num_asics == 2 && irq[1])
+ printk(KERN_DEBUG "comedi%d: second ASIC irq: %u\n",
+ dev->minor, irq[1]);
+ } else {
+ printk(KERN_INFO "comedi%d: (IRQ mode disabled)\n", dev->minor);
+ }
+
+ printk(KERN_INFO "comedi%d: attached\n", dev->minor);
+
+ return 1;
}
-static void __exit driver_cleanup_module(void)
+static void pcmmio_detach(struct comedi_device *dev)
{
- comedi_driver_unregister(&driver);
+ int i;
+
+ if (dev->iobase)
+ release_region(dev->iobase, thisboard->total_iosize);
+ for (i = 0; i < MAX_ASICS; ++i) {
+ if (devpriv && devpriv->asics[i].irq)
+ free_irq(devpriv->asics[i].irq, dev);
+ }
+ if (devpriv && devpriv->sprivs)
+ kfree(devpriv->sprivs);
}
-module_init(driver_init_module);
-module_exit(driver_cleanup_module);
+static const struct pcmmio_board pcmmio_boards[] = {
+ {
+ .name = "pcmmio",
+ .dio_num_asics = 1,
+ .dio_num_ports = 6,
+ .total_iosize = 32,
+ .ai_bits = 16,
+ .ao_bits = 16,
+ .n_ai_chans = 16,
+ .n_ao_chans = 8,
+ .ai_range_table = &ranges_ai,
+ .ao_range_table = &ranges_ao,
+ .ai_rinsn = ai_rinsn,
+ .ao_rinsn = ao_rinsn,
+ .ao_winsn = ao_winsn
+ },
+};
+
+static struct comedi_driver pcmmio_driver = {
+ .driver_name = "pcmmio",
+ .module = THIS_MODULE,
+ .attach = pcmmio_attach,
+ .detach = pcmmio_detach,
+ .board_name = &pcmmio_boards[0].name,
+ .offset = sizeof(struct pcmmio_board),
+ .num_names = ARRAY_SIZE(pcmmio_boards),
+};
+module_comedi_driver(pcmmio_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
index 661ba2e03892..623381d50dac 100644
--- a/drivers/staging/comedi/drivers/pcmuio.c
+++ b/drivers/staging/comedi/drivers/pcmuio.c
@@ -155,19 +155,6 @@ struct pcmuio_board {
const int num_ports;
};
-static const struct pcmuio_board pcmuio_boards[] = {
- {
- .name = "pcmuio48",
- .num_asics = 1,
- .num_ports = 6,
- },
- {
- .name = "pcmuio96",
- .num_asics = 2,
- .num_ports = 12,
- },
-};
-
/*
* Useful for shorthand access to the particular board structure
*/
@@ -218,262 +205,6 @@ struct pcmuio_private {
*/
#define devpriv ((struct pcmuio_private *)dev->private)
#define subpriv ((struct pcmuio_subdev_private *)s->private)
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int pcmuio_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int pcmuio_detach(struct comedi_device *dev);
-
-static struct comedi_driver driver = {
- .driver_name = "pcmuio",
- .module = THIS_MODULE,
- .attach = pcmuio_attach,
- .detach = pcmuio_detach,
-/* It is not necessary to implement the following members if you are
- * writing a driver for a ISA PnP or PCI card */
- /* Most drivers will support multiple types of boards by
- * having an array of board structures. These were defined
- * in pcmuio_boards[] above. Note that the element 'name'
- * was first in the structure -- Comedi uses this fact to
- * extract the name of the board without knowing any details
- * about the structure except for its length.
- * When a device is attached (by comedi_config), the name
- * of the device is given to Comedi, and Comedi tries to
- * match it by going through the list of board names. If
- * there is a match, the address of the pointer is put
- * into dev->board_ptr and driver->attach() is called.
- *
- * Note that these are not necessary if you can determine
- * the type of board in software. ISA PnP, PCI, and PCMCIA
- * devices are such boards.
- */
- .board_name = &pcmuio_boards[0].name,
- .offset = sizeof(struct pcmuio_board),
- .num_names = ARRAY_SIZE(pcmuio_boards),
-};
-
-static int pcmuio_dio_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int pcmuio_dio_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static irqreturn_t interrupt_pcmuio(int irq, void *d);
-static void pcmuio_stop_intr(struct comedi_device *, struct comedi_subdevice *);
-static int pcmuio_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
-static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
-static int pcmuio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_cmd *cmd);
-
-/* some helper functions to deal with specifics of this device's registers */
-static void init_asics(struct comedi_device *dev); /* sets up/clears ASIC chips to defaults */
-static void switch_page(struct comedi_device *dev, int asic, int page);
-#ifdef notused
-static void lock_port(struct comedi_device *dev, int asic, int port);
-static void unlock_port(struct comedi_device *dev, int asic, int port);
-#endif
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
-static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0;
- unsigned long iobase;
- unsigned int irq[MAX_ASICS];
-
- iobase = it->options[0];
- irq[0] = it->options[1];
- irq[1] = it->options[2];
-
- dev_dbg(dev->hw_dev, "comedi%d: %s: io: %lx attached\n", dev->minor,
- driver.driver_name, iobase);
-
- dev->iobase = iobase;
-
- if (!iobase || !request_region(iobase,
- thisboard->num_asics * ASIC_IOSIZE,
- driver.driver_name)) {
- dev_err(dev->hw_dev, "I/O port conflict\n");
- return -EIO;
- }
-
-/*
- * Initialize dev->board_name. Note that we can use the "thisboard"
- * macro now, since we just initialized it in the last line.
- */
- dev->board_name = thisboard->name;
-
-/*
- * Allocate the private structure area. alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
- if (alloc_private(dev, sizeof(struct pcmuio_private)) < 0) {
- dev_warn(dev->hw_dev, "cannot allocate private data structure\n");
- return -ENOMEM;
- }
-
- for (asic = 0; asic < MAX_ASICS; ++asic) {
- devpriv->asics[asic].num = asic;
- devpriv->asics[asic].iobase = dev->iobase + asic * ASIC_IOSIZE;
- devpriv->asics[asic].irq = 0; /* this gets actually set at the end of
- this function when we
- request_irqs */
- spin_lock_init(&devpriv->asics[asic].spinlock);
- }
-
- chans_left = CHANS_PER_ASIC * thisboard->num_asics;
- n_subdevs = CALC_N_SUBDEVS(chans_left);
- devpriv->sprivs =
- kcalloc(n_subdevs, sizeof(struct pcmuio_subdev_private),
- GFP_KERNEL);
- if (!devpriv->sprivs) {
- dev_warn(dev->hw_dev, "cannot allocate subdevice private data structures\n");
- return -ENOMEM;
- }
- /*
- * Allocate the subdevice structures. alloc_subdevice() is a
- * convenient macro defined in comedidev.h.
- *
- * Allocate 2 subdevs (32 + 16 DIO lines) or 3 32 DIO subdevs for the
- * 96-channel version of the board.
- */
- if (alloc_subdevices(dev, n_subdevs) < 0) {
- dev_dbg(dev->hw_dev, "cannot allocate subdevice data structures\n");
- return -ENOMEM;
- }
-
- port = 0;
- asic = 0;
- for (sdev_no = 0; sdev_no < (int)dev->n_subdevices; ++sdev_no) {
- int byte_no;
-
- s = dev->subdevices + sdev_no;
- s->private = devpriv->sprivs + sdev_no;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->type = COMEDI_SUBD_DIO;
- s->insn_bits = pcmuio_dio_insn_bits;
- s->insn_config = pcmuio_dio_insn_config;
- s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV);
- subpriv->intr.asic = -1;
- subpriv->intr.first_chan = -1;
- subpriv->intr.asic_chan = -1;
- subpriv->intr.num_asic_chans = -1;
- subpriv->intr.active = 0;
- s->len_chanlist = 1;
-
- /* save the ioport address for each 'port' of 8 channels in the
- subdevice */
- for (byte_no = 0; byte_no < PORTS_PER_SUBDEV; ++byte_no, ++port) {
- if (port >= PORTS_PER_ASIC) {
- port = 0;
- ++asic;
- thisasic_chanct = 0;
- }
- subpriv->iobases[byte_no] =
- devpriv->asics[asic].iobase + port;
-
- if (thisasic_chanct <
- CHANS_PER_PORT * INTR_PORTS_PER_ASIC
- && subpriv->intr.asic < 0) {
- /* this is an interrupt subdevice, so setup the struct */
- subpriv->intr.asic = asic;
- subpriv->intr.active = 0;
- subpriv->intr.stop_count = 0;
- subpriv->intr.first_chan = byte_no * 8;
- subpriv->intr.asic_chan = thisasic_chanct;
- subpriv->intr.num_asic_chans =
- s->n_chan - subpriv->intr.first_chan;
- dev->read_subdev = s;
- s->subdev_flags |= SDF_CMD_READ;
- s->cancel = pcmuio_cancel;
- s->do_cmd = pcmuio_cmd;
- s->do_cmdtest = pcmuio_cmdtest;
- s->len_chanlist = subpriv->intr.num_asic_chans;
- }
- thisasic_chanct += CHANS_PER_PORT;
- }
- spin_lock_init(&subpriv->intr.spinlock);
-
- chans_left -= s->n_chan;
-
- if (!chans_left) {
- asic = 0; /* reset the asic to our first asic, to do intr subdevs */
- port = 0;
- }
-
- }
-
- init_asics(dev); /* clear out all the registers, basically */
-
- for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) {
- if (irq[asic]
- && request_irq(irq[asic], interrupt_pcmuio,
- IRQF_SHARED, thisboard->name, dev)) {
- int i;
- /* unroll the allocated irqs.. */
- for (i = asic - 1; i >= 0; --i) {
- free_irq(irq[i], dev);
- devpriv->asics[i].irq = irq[i] = 0;
- }
- irq[asic] = 0;
- }
- devpriv->asics[asic].irq = irq[asic];
- }
-
- dev->irq = irq[0]; /* grr.. wish comedi dev struct supported multiple
- irqs.. */
-
- if (irq[0]) {
- dev_dbg(dev->hw_dev, "irq: %u\n", irq[0]);
- if (irq[1] && thisboard->num_asics == 2)
- dev_dbg(dev->hw_dev, "second ASIC irq: %u\n", irq[1]);
- } else {
- dev_dbg(dev->hw_dev, "(IRQ mode disabled)\n");
- }
-
-
- return 1;
-}
-
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int pcmuio_detach(struct comedi_device *dev)
-{
- int i;
-
- dev_dbg(dev->hw_dev, "comedi%d: %s: remove\n", dev->minor,
- driver.driver_name);
- if (dev->iobase)
- release_region(dev->iobase, ASIC_IOSIZE * thisboard->num_asics);
-
- for (i = 0; i < MAX_ASICS; ++i) {
- if (devpriv->asics[i].irq)
- free_irq(devpriv->asics[i].irq, dev);
- }
-
- if (devpriv && devpriv->sprivs)
- kfree(devpriv->sprivs);
-
- return 0;
-}
/* DIO devices are slightly special. Although it is possible to
* implement the insn_read/insn_write interface, it is much more
@@ -621,6 +352,21 @@ static int pcmuio_dio_insn_config(struct comedi_device *dev,
return insn->n;
}
+static void switch_page(struct comedi_device *dev, int asic, int page)
+{
+ if (asic < 0 || asic >= thisboard->num_asics)
+ return; /* paranoia */
+ if (page < 0 || page >= NUM_PAGES)
+ return; /* more paranoia */
+
+ devpriv->asics[asic].pagelock &= ~REG_PAGE_MASK;
+ devpriv->asics[asic].pagelock |= page << REG_PAGE_BITOFFSET;
+
+ /* now write out the shadow register */
+ outb(devpriv->asics[asic].pagelock,
+ dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK);
+}
+
static void init_asics(struct comedi_device *dev)
{ /* sets up an
ASIC chip to defaults */
@@ -658,21 +404,6 @@ static void init_asics(struct comedi_device *dev)
}
}
-static void switch_page(struct comedi_device *dev, int asic, int page)
-{
- if (asic < 0 || asic >= thisboard->num_asics)
- return; /* paranoia */
- if (page < 0 || page >= NUM_PAGES)
- return; /* more paranoia */
-
- devpriv->asics[asic].pagelock &= ~REG_PAGE_MASK;
- devpriv->asics[asic].pagelock |= page << REG_PAGE_BITOFFSET;
-
- /* now write out the shadow register */
- outb(devpriv->asics[asic].pagelock,
- dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK);
-}
-
#ifdef notused
static void lock_port(struct comedi_device *dev, int asic, int port)
{
@@ -700,6 +431,27 @@ static void unlock_port(struct comedi_device *dev, int asic, int port)
}
#endif /* notused */
+static void pcmuio_stop_intr(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ int nports, firstport, asic, port;
+
+ asic = subpriv->intr.asic;
+ if (asic < 0)
+ return; /* not an interrupt subdev */
+
+ subpriv->intr.enabled_mask = 0;
+ subpriv->intr.active = 0;
+ s->async->inttrig = 0;
+ nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT;
+ firstport = subpriv->intr.asic_chan / CHANS_PER_PORT;
+ switch_page(dev, asic, PAGE_ENAB);
+ for (port = firstport; port < firstport + nports; ++port) {
+ /* disable all intrs for this subdev.. */
+ outb(0, devpriv->asics[asic].iobase + REG_ENAB0 + port);
+ }
+}
+
static irqreturn_t interrupt_pcmuio(int irq, void *d)
{
int asic, got1 = 0;
@@ -852,27 +604,6 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d)
return IRQ_HANDLED;
}
-static void pcmuio_stop_intr(struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- int nports, firstport, asic, port;
-
- asic = subpriv->intr.asic;
- if (asic < 0)
- return; /* not an interrupt subdev */
-
- subpriv->intr.enabled_mask = 0;
- subpriv->intr.active = 0;
- s->async->inttrig = 0;
- nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT;
- firstport = subpriv->intr.asic_chan / CHANS_PER_PORT;
- switch_page(dev, asic, PAGE_ENAB);
- for (port = firstport; port < firstport + nports; ++port) {
- /* disable all intrs for this subdev.. */
- outb(0, devpriv->asics[asic].iobase + REG_ENAB0 + port);
- }
-}
-
static int pcmuio_start_intr(struct comedi_device *dev,
struct comedi_subdevice *s)
{
@@ -1014,22 +745,205 @@ pcmuio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
return comedi_pcm_cmdtest(dev, s, cmd);
}
+static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+{
+ struct comedi_subdevice *s;
+ int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0;
+ unsigned long iobase;
+ unsigned int irq[MAX_ASICS];
+
+ iobase = it->options[0];
+ irq[0] = it->options[1];
+ irq[1] = it->options[2];
+
+ dev_dbg(dev->hw_dev, "comedi%d: %s: io: %lx attached\n", dev->minor,
+ dev->driver->driver_name, iobase);
+
+ dev->iobase = iobase;
+
+ if (!iobase || !request_region(iobase,
+ thisboard->num_asics * ASIC_IOSIZE,
+ dev->driver->driver_name)) {
+ dev_err(dev->hw_dev, "I/O port conflict\n");
+ return -EIO;
+ }
+
/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
+ * Initialize dev->board_name. Note that we can use the "thisboard"
+ * macro now, since we just initialized it in the last line.
*/
-static int __init driver_init_module(void)
-{
- return comedi_driver_register(&driver);
+ dev->board_name = thisboard->name;
+
+/*
+ * Allocate the private structure area. alloc_private() is a
+ * convenient macro defined in comedidev.h.
+ */
+ if (alloc_private(dev, sizeof(struct pcmuio_private)) < 0) {
+ dev_warn(dev->hw_dev, "cannot allocate private data structure\n");
+ return -ENOMEM;
+ }
+
+ for (asic = 0; asic < MAX_ASICS; ++asic) {
+ devpriv->asics[asic].num = asic;
+ devpriv->asics[asic].iobase = dev->iobase + asic * ASIC_IOSIZE;
+ devpriv->asics[asic].irq = 0; /* this gets actually set at the end of
+ this function when we
+ request_irqs */
+ spin_lock_init(&devpriv->asics[asic].spinlock);
+ }
+
+ chans_left = CHANS_PER_ASIC * thisboard->num_asics;
+ n_subdevs = CALC_N_SUBDEVS(chans_left);
+ devpriv->sprivs =
+ kcalloc(n_subdevs, sizeof(struct pcmuio_subdev_private),
+ GFP_KERNEL);
+ if (!devpriv->sprivs) {
+ dev_warn(dev->hw_dev, "cannot allocate subdevice private data structures\n");
+ return -ENOMEM;
+ }
+ /*
+ * Allocate the subdevice structures. alloc_subdevice() is a
+ * convenient macro defined in comedidev.h.
+ *
+ * Allocate 2 subdevs (32 + 16 DIO lines) or 3 32 DIO subdevs for the
+ * 96-channel version of the board.
+ */
+ if (alloc_subdevices(dev, n_subdevs) < 0) {
+ dev_dbg(dev->hw_dev, "cannot allocate subdevice data structures\n");
+ return -ENOMEM;
+ }
+
+ port = 0;
+ asic = 0;
+ for (sdev_no = 0; sdev_no < (int)dev->n_subdevices; ++sdev_no) {
+ int byte_no;
+
+ s = dev->subdevices + sdev_no;
+ s->private = devpriv->sprivs + sdev_no;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->type = COMEDI_SUBD_DIO;
+ s->insn_bits = pcmuio_dio_insn_bits;
+ s->insn_config = pcmuio_dio_insn_config;
+ s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV);
+ subpriv->intr.asic = -1;
+ subpriv->intr.first_chan = -1;
+ subpriv->intr.asic_chan = -1;
+ subpriv->intr.num_asic_chans = -1;
+ subpriv->intr.active = 0;
+ s->len_chanlist = 1;
+
+ /* save the ioport address for each 'port' of 8 channels in the
+ subdevice */
+ for (byte_no = 0; byte_no < PORTS_PER_SUBDEV; ++byte_no, ++port) {
+ if (port >= PORTS_PER_ASIC) {
+ port = 0;
+ ++asic;
+ thisasic_chanct = 0;
+ }
+ subpriv->iobases[byte_no] =
+ devpriv->asics[asic].iobase + port;
+
+ if (thisasic_chanct <
+ CHANS_PER_PORT * INTR_PORTS_PER_ASIC
+ && subpriv->intr.asic < 0) {
+ /* this is an interrupt subdevice, so setup the struct */
+ subpriv->intr.asic = asic;
+ subpriv->intr.active = 0;
+ subpriv->intr.stop_count = 0;
+ subpriv->intr.first_chan = byte_no * 8;
+ subpriv->intr.asic_chan = thisasic_chanct;
+ subpriv->intr.num_asic_chans =
+ s->n_chan - subpriv->intr.first_chan;
+ dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
+ s->cancel = pcmuio_cancel;
+ s->do_cmd = pcmuio_cmd;
+ s->do_cmdtest = pcmuio_cmdtest;
+ s->len_chanlist = subpriv->intr.num_asic_chans;
+ }
+ thisasic_chanct += CHANS_PER_PORT;
+ }
+ spin_lock_init(&subpriv->intr.spinlock);
+
+ chans_left -= s->n_chan;
+
+ if (!chans_left) {
+ asic = 0; /* reset the asic to our first asic, to do intr subdevs */
+ port = 0;
+ }
+
+ }
+
+ init_asics(dev); /* clear out all the registers, basically */
+
+ for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) {
+ if (irq[asic]
+ && request_irq(irq[asic], interrupt_pcmuio,
+ IRQF_SHARED, thisboard->name, dev)) {
+ int i;
+ /* unroll the allocated irqs.. */
+ for (i = asic - 1; i >= 0; --i) {
+ free_irq(irq[i], dev);
+ devpriv->asics[i].irq = irq[i] = 0;
+ }
+ irq[asic] = 0;
+ }
+ devpriv->asics[asic].irq = irq[asic];
+ }
+
+ dev->irq = irq[0]; /* grr.. wish comedi dev struct supported multiple
+ irqs.. */
+
+ if (irq[0]) {
+ dev_dbg(dev->hw_dev, "irq: %u\n", irq[0]);
+ if (irq[1] && thisboard->num_asics == 2)
+ dev_dbg(dev->hw_dev, "second ASIC irq: %u\n", irq[1]);
+ } else {
+ dev_dbg(dev->hw_dev, "(IRQ mode disabled)\n");
+ }
+
+
+ return 1;
}
-static void __exit driver_cleanup_module(void)
+static void pcmuio_detach(struct comedi_device *dev)
{
- comedi_driver_unregister(&driver);
+ int i;
+
+ if (dev->iobase)
+ release_region(dev->iobase, ASIC_IOSIZE * thisboard->num_asics);
+ for (i = 0; i < MAX_ASICS; ++i) {
+ if (devpriv->asics[i].irq)
+ free_irq(devpriv->asics[i].irq, dev);
+ }
+ if (devpriv && devpriv->sprivs)
+ kfree(devpriv->sprivs);
}
-module_init(driver_init_module);
-module_exit(driver_cleanup_module);
+static const struct pcmuio_board pcmuio_boards[] = {
+ {
+ .name = "pcmuio48",
+ .num_asics = 1,
+ .num_ports = 6,
+ }, {
+ .name = "pcmuio96",
+ .num_asics = 2,
+ .num_ports = 12,
+ },
+};
+
+static struct comedi_driver pcmuio_driver = {
+ .driver_name = "pcmuio",
+ .module = THIS_MODULE,
+ .attach = pcmuio_attach,
+ .detach = pcmuio_detach,
+ .board_name = &pcmuio_boards[0].name,
+ .offset = sizeof(struct pcmuio_board),
+ .num_names = ARRAY_SIZE(pcmuio_boards),
+};
+module_comedi_driver(pcmuio_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
index 831a576c24aa..e7120480687b 100644
--- a/drivers/staging/comedi/drivers/poc.c
+++ b/drivers/staging/comedi/drivers/poc.c
@@ -41,20 +41,6 @@ Configuration options:
#include <linux/ioport.h>
-static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int poc_detach(struct comedi_device *dev);
-static int readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static int dac02_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int pcl733_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int pcl734_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
struct boarddef_struct {
const char *name;
unsigned int iosize;
@@ -70,108 +56,9 @@ struct boarddef_struct {
struct comedi_insn *, unsigned int *);
const struct comedi_lrange *range;
};
-static const struct boarddef_struct boards[] = {
- {
- .name = "dac02",
- .iosize = 8,
- /* .setup = dac02_setup, */
- .type = COMEDI_SUBD_AO,
- .n_chan = 2,
- .n_bits = 12,
- .winsn = dac02_ao_winsn,
- .rinsn = readback_insn,
- .range = &range_unknown,
- },
- {
- .name = "pcl733",
- .iosize = 4,
- .type = COMEDI_SUBD_DI,
- .n_chan = 32,
- .n_bits = 1,
- .insnbits = pcl733_insn_bits,
- .range = &range_digital,
- },
- {
- .name = "pcl734",
- .iosize = 4,
- .type = COMEDI_SUBD_DO,
- .n_chan = 32,
- .n_bits = 1,
- .insnbits = pcl734_insn_bits,
- .range = &range_digital,
- },
-};
-#define n_boards ARRAY_SIZE(boards)
#define this_board ((const struct boarddef_struct *)dev->board_ptr)
-static struct comedi_driver driver_poc = {
- .driver_name = "poc",
- .module = THIS_MODULE,
- .attach = poc_attach,
- .detach = poc_detach,
- .board_name = &boards[0].name,
- .num_names = n_boards,
- .offset = sizeof(boards[0]),
-};
-
-static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- unsigned long iobase;
- unsigned int iosize;
-
- iobase = it->options[0];
- printk(KERN_INFO "comedi%d: poc: using %s iobase 0x%lx\n", dev->minor,
- this_board->name, iobase);
-
- dev->board_name = this_board->name;
-
- if (iobase == 0) {
- printk(KERN_ERR "io base address required\n");
- return -EINVAL;
- }
-
- iosize = this_board->iosize;
- /* check if io addresses are available */
- if (!request_region(iobase, iosize, "dac02")) {
- printk(KERN_ERR "I/O port conflict: failed to allocate ports "
- "0x%lx to 0x%lx\n", iobase, iobase + iosize - 1);
- return -EIO;
- }
- dev->iobase = iobase;
-
- if (alloc_subdevices(dev, 1) < 0)
- return -ENOMEM;
- if (alloc_private(dev, sizeof(unsigned int) * this_board->n_chan) < 0)
- return -ENOMEM;
-
- /* analog output subdevice */
- s = dev->subdevices + 0;
- s->type = this_board->type;
- s->n_chan = this_board->n_chan;
- s->maxdata = (1 << this_board->n_bits) - 1;
- s->range_table = this_board->range;
- s->insn_write = this_board->winsn;
- s->insn_read = this_board->rinsn;
- s->insn_bits = this_board->insnbits;
- if (s->type == COMEDI_SUBD_AO || s->type == COMEDI_SUBD_DO)
- s->subdev_flags = SDF_WRITABLE;
-
- return 0;
-}
-
-static int poc_detach(struct comedi_device *dev)
-{
- /* only free stuff if it has been allocated by _attach */
- if (dev->iobase)
- release_region(dev->iobase, this_board->iosize);
-
- printk(KERN_INFO "comedi%d: dac02: remove\n", dev->minor);
-
- return 0;
-}
-
static int readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
@@ -248,18 +135,98 @@ static int pcl734_insn_bits(struct comedi_device *dev,
return 2;
}
-static int __init driver_poc_init_module(void)
+static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
- return comedi_driver_register(&driver_poc);
+ struct comedi_subdevice *s;
+ unsigned long iobase;
+ unsigned int iosize;
+
+ iobase = it->options[0];
+ printk(KERN_INFO "comedi%d: poc: using %s iobase 0x%lx\n", dev->minor,
+ this_board->name, iobase);
+
+ dev->board_name = this_board->name;
+
+ if (iobase == 0) {
+ printk(KERN_ERR "io base address required\n");
+ return -EINVAL;
+ }
+
+ iosize = this_board->iosize;
+ /* check if io addresses are available */
+ if (!request_region(iobase, iosize, "dac02")) {
+ printk(KERN_ERR "I/O port conflict: failed to allocate ports "
+ "0x%lx to 0x%lx\n", iobase, iobase + iosize - 1);
+ return -EIO;
+ }
+ dev->iobase = iobase;
+
+ if (alloc_subdevices(dev, 1) < 0)
+ return -ENOMEM;
+ if (alloc_private(dev, sizeof(unsigned int) * this_board->n_chan) < 0)
+ return -ENOMEM;
+
+ /* analog output subdevice */
+ s = dev->subdevices + 0;
+ s->type = this_board->type;
+ s->n_chan = this_board->n_chan;
+ s->maxdata = (1 << this_board->n_bits) - 1;
+ s->range_table = this_board->range;
+ s->insn_write = this_board->winsn;
+ s->insn_read = this_board->rinsn;
+ s->insn_bits = this_board->insnbits;
+ if (s->type == COMEDI_SUBD_AO || s->type == COMEDI_SUBD_DO)
+ s->subdev_flags = SDF_WRITABLE;
+
+ return 0;
}
-static void __exit driver_poc_cleanup_module(void)
+static void poc_detach(struct comedi_device *dev)
{
- comedi_driver_unregister(&driver_poc);
+ if (dev->iobase)
+ release_region(dev->iobase, this_board->iosize);
}
-module_init(driver_poc_init_module);
-module_exit(driver_poc_cleanup_module);
+static const struct boarddef_struct boards[] = {
+ {
+ .name = "dac02",
+ .iosize = 8,
+ /* .setup = dac02_setup, */
+ .type = COMEDI_SUBD_AO,
+ .n_chan = 2,
+ .n_bits = 12,
+ .winsn = dac02_ao_winsn,
+ .rinsn = readback_insn,
+ .range = &range_unknown,
+ }, {
+ .name = "pcl733",
+ .iosize = 4,
+ .type = COMEDI_SUBD_DI,
+ .n_chan = 32,
+ .n_bits = 1,
+ .insnbits = pcl733_insn_bits,
+ .range = &range_digital,
+ }, {
+ .name = "pcl734",
+ .iosize = 4,
+ .type = COMEDI_SUBD_DO,
+ .n_chan = 32,
+ .n_bits = 1,
+ .insnbits = pcl734_insn_bits,
+ .range = &range_digital,
+ },
+};
+
+static struct comedi_driver poc_driver = {
+ .driver_name = "poc",
+ .module = THIS_MODULE,
+ .attach = poc_attach,
+ .detach = poc_detach,
+ .board_name = &boards[0].name,
+ .num_names = ARRAY_SIZE(boards),
+ .offset = sizeof(boards[0]),
+};
+module_comedi_driver(poc_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index e0bb73445dd8..2f130b3095e9 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -181,7 +181,7 @@ static const struct comedi_lrange range_daqp_ao = { 1, {BIP_RANGE(5)} };
/* comedi interface code */
static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int daqp_detach(struct comedi_device *dev);
+static void daqp_detach(struct comedi_device *dev);
static struct comedi_driver driver_daqp = {
.driver_name = "quatech_daqp_cs",
.module = THIS_MODULE,
@@ -922,15 +922,9 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 1;
}
-/* daqp_detach (called from comedi_comdig) does nothing. If the PCMCIA
- * card is removed, daqp_cs_detach() is called by the pcmcia subsystem.
- */
-
-static int daqp_detach(struct comedi_device *dev)
+static void daqp_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: detaching daqp\n", dev->minor);
-
- return 0;
+ /* Nothing to cleanup */
}
/*====================================================================
@@ -1010,8 +1004,6 @@ static void daqp_cs_detach(struct pcmcia_device *link)
{
struct local_info_t *dev = link->priv;
- dev_dbg(&link->dev, "daqp_cs_detach\n");
-
dev->stop = 1;
daqp_cs_release(link);
@@ -1019,7 +1011,7 @@ static void daqp_cs_detach(struct pcmcia_device *link)
dev_table[dev->table_index] = NULL;
kfree(dev);
-} /* daqp_cs_detach */
+}
static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
{
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 138441960506..1678a0ccb8c1 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -328,14 +328,6 @@ static const struct rtdBoard rtd520Boards[] = {
},
};
-static DEFINE_PCI_DEVICE_TABLE(rtd520_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_RTD, 0x7520) },
- { PCI_DEVICE(PCI_VENDOR_ID_RTD, 0x4520) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, rtd520_pci_table);
-
/*
* Useful for shorthand access to the particular board structure
*/
@@ -347,13 +339,13 @@ MODULE_DEVICE_TABLE(pci, rtd520_pci_table);
*/
struct rtdPrivate {
/* memory mapped board structures */
- void *las0;
- void *las1;
- void *lcfg;
+ void __iomem *las0;
+ void __iomem *las1;
+ void __iomem *lcfg;
unsigned long intCount; /* interrupt count */
long aiCount; /* total transfer size (samples) */
- int transCount; /* # to tranfer data. 0->1/2FIFO */
+ int transCount; /* # to transfer data. 0->1/2FIFO */
int flags; /* flag event modes */
/* PCI device info */
@@ -377,8 +369,11 @@ struct rtdPrivate {
u8 utcCtrl[4]; /* crtl mode for 3 utc + read back */
u8 dioStatus; /* could be read back (dio0Ctrl) */
#ifdef USE_DMA
- /* Always DMA 1/2 FIFO. Buffer (dmaBuff?) is (at least) twice that size.
- After transferring, interrupt processes 1/2 FIFO and passes to comedi */
+ /*
+ * Always DMA 1/2 FIFO. Buffer (dmaBuff?) is (at least) twice that
+ * size. After transferring, interrupt processes 1/2 FIFO and
+ * passes to comedi
+ */
s16 dma0Offset; /* current processing offset (0, 1/2) */
uint16_t *dma0Buff[DMA_CHAIN_COUNT]; /* DMA buffers (for ADC) */
dma_addr_t dma0BuffPhysAddr[DMA_CHAIN_COUNT]; /* physical addresses */
@@ -581,7 +576,8 @@ struct rtdPrivate {
/* User output N source select (write only) */
#define RtdUsrOutSource(dev, n, v) \
- writel(v, devpriv->las0+((n <= 0) ? LAS0_UOUT0_SELECT : LAS0_UOUT1_SELECT))
+ writel(v, devpriv->las0+((n <= 0) ? LAS0_UOUT0_SELECT : \
+ LAS0_UOUT1_SELECT))
/* Digital IO */
#define RtdDio0Read(dev) \
@@ -608,7 +604,8 @@ struct rtdPrivate {
/* Write one data value (sign + 12bit + marker bits) */
/* Note: matches what DMA would put. Actual value << 3 */
#define RtdDacFifoPut(dev, n, v) \
- writew((v), devpriv->las1 + (((n) == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO))
+ writew((v), devpriv->las1 + (((n) == 0) ? LAS1_DAC1_FIFO : \
+ LAS1_DAC2_FIFO))
/* Start single DAC conversion */
#define RtdDacUpdate(dev, n) \
@@ -625,7 +622,8 @@ struct rtdPrivate {
/* Reset DAC FIFO */
#define RtdDacClearFifo(dev, n) \
- writel(0, devpriv->las0+(((n) == 0) ? LAS0_DAC1_RESET : LAS0_DAC2_RESET))
+ writel(0, devpriv->las0+(((n) == 0) ? LAS0_DAC1_RESET : \
+ LAS0_DAC2_RESET))
/* Set source for DMA 0 (write only, shadow?) */
#define RtdDma0Source(dev, n) \
@@ -705,22 +703,6 @@ struct rtdPrivate {
#define RtdDma1Status(dev) \
readb(devpriv->lcfg+LCFG_DMACSR1)
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attac/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int rtd_detach(struct comedi_device *dev);
-
-static struct comedi_driver rtd520Driver = {
- .driver_name = DRV_NAME,
- .module = THIS_MODULE,
- .attach = rtd_attach,
- .detach = rtd_detach,
-};
-
static int rtd_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
static int rtd_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
@@ -737,7 +719,10 @@ static int rtd_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_cmd *cmd);
static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
-/* static int rtd_ai_poll (struct comedi_device *dev,struct comedi_subdevice *s); */
+/*
+ * static int rtd_ai_poll(struct comedi_device *dev,
+ * struct comedi_subdevice *s);
+ */
static int rtd_ns_to_timer(unsigned int *ns, int roundMode);
static irqreturn_t rtd_interrupt(int irq, void *d);
static int rtd520_probe_fifo_depth(struct comedi_device *dev);
@@ -857,7 +842,9 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
DPRINTK("rtd520: PCI latency = %d\n", pci_latency);
}
- /* Undocumented EPLD version (doesn't match RTD driver results) */
+ /*
+ * Undocumented EPLD version (doesn't match RTD driver results)
+ */
/*DPRINTK ("rtd520: Reading epld from %p\n",
devpriv->las0+0);
epld_version = readl (devpriv->las0+0);
@@ -970,9 +957,11 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
#ifdef USE_DMA
if (dev->irq > 0) {
printk("( DMA buff=%d )\n", DMA_CHAIN_COUNT);
- /* The PLX9080 has 2 DMA controllers, but there could be 4 sources:
- ADC, digital, DAC1, and DAC2. Since only the ADC supports cmd mode
- right now, this isn't an issue (yet) */
+ /*
+ * The PLX9080 has 2 DMA controllers, but there could be
+ * 4 sources: ADC, digital, DAC1, and DAC2. Since only the
+ * ADC supports cmd mode right now, this isn't an issue (yet)
+ */
devpriv->dma0Offset = 0;
for (index = 0; index < DMA_CHAIN_COUNT; index++) {
@@ -988,10 +977,14 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
/*DPRINTK ("buff[%d] @ %p virtual, %x PCI\n",
index,
- devpriv->dma0Buff[index], devpriv->dma0BuffPhysAddr[index]); */
+ devpriv->dma0Buff[index],
+ devpriv->dma0BuffPhysAddr[index]); */
}
- /* setup DMA descriptor ring (use cpu_to_le32 for byte ordering?) */
+ /*
+ * setup DMA descriptor ring (use cpu_to_le32 for byte
+ * ordering?)
+ */
devpriv->dma0Chain =
pci_alloc_consistent(devpriv->pci_dev,
sizeof(struct plx_dma_desc) *
@@ -1088,30 +1081,12 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
#endif
}
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int rtd_detach(struct comedi_device *dev)
+static void rtd_detach(struct comedi_device *dev)
{
#ifdef USE_DMA
int index;
#endif
- DPRINTK("comedi%d: rtd520: removing (%ld ints)\n",
- dev->minor, (devpriv ? devpriv->intCount : 0L));
- if (devpriv && devpriv->lcfg) {
- DPRINTK
- ("(int status 0x%x, overrun status 0x%x, fifo status 0x%x)...\n",
- 0xffff & RtdInterruptStatus(dev),
- 0xffff & RtdInterruptOverrunStatus(dev),
- (0xffff & RtdFifoStatus(dev)) ^ 0x6666);
- }
-
if (devpriv) {
/* Shut down any board ops by resetting it */
#ifdef USE_DMA
@@ -1148,37 +1123,24 @@ static int rtd_detach(struct comedi_device *dev)
devpriv->dma0Chain = NULL;
}
#endif /* USE_DMA */
-
- /* release IRQ */
if (dev->irq) {
- /* disable interrupt controller */
RtdPlxInterruptWrite(dev, RtdPlxInterruptRead(dev)
& ~(ICS_PLIE | ICS_DMA0_E |
ICS_DMA1_E));
free_irq(dev->irq, dev);
}
-
- /* release all regions that were allocated */
if (devpriv->las0)
iounmap(devpriv->las0);
-
if (devpriv->las1)
iounmap(devpriv->las1);
-
if (devpriv->lcfg)
iounmap(devpriv->lcfg);
-
if (devpriv->pci_dev) {
if (devpriv->got_regions)
comedi_pci_disable(devpriv->pci_dev);
-
pci_dev_put(devpriv->pci_dev);
}
}
-
- printk(KERN_INFO "comedi%d: rtd520: removed.\n", dev->minor);
-
- return 0;
}
/*
@@ -1278,7 +1240,8 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev)
}
}
if (i == limit) {
- printk(KERN_INFO "\ncomedi: %s: failed to probe fifo size.\n", DRV_NAME);
+ printk(KERN_INFO "\ncomedi: %s: failed to probe fifo size.\n",
+ DRV_NAME);
return -EIO;
}
RtdAdcClearFifo(dev);
@@ -1378,9 +1341,10 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s,
d = RtdAdcFifoGet(dev); /* get 2s comp value */
d = d >> 3; /* low 3 bits are marker lines */
- if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan))
- sample = d + 2048; /* convert to comedi unsigned data */
- else
+ if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
+ /* convert to comedi unsigned data */
+ sample = d + 2048;
+ } else
sample = d;
if (!comedi_buf_put(s->async, sample))
@@ -1406,9 +1370,10 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s)
}
d = d >> 3; /* low 3 bits are marker lines */
- if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan))
- sample = d + 2048; /* convert to comedi unsigned data */
- else
+ if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
+ /* convert to comedi unsigned data */
+ sample = d + 2048;
+ } else
sample = d;
if (!comedi_buf_put(s->async, sample))
@@ -1525,7 +1490,9 @@ static int ai_process_dma(struct comedi_device *dev, struct comedi_subdevice *s)
comedi_buf_memcpy_to(s->async, 0, dp, n);
comedi_buf_write_free(s->async, n);
- /* always at least 1 scan -- 1/2 FIFO is larger than our max scan list */
+ /*
+ * always at least 1 scan -- 1/2 FIFO is larger than our max scan list
+ */
s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
if (++devpriv->dma0Offset >= DMA_CHAIN_COUNT) { /* next buffer */
@@ -1989,7 +1956,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
(TRANS_TARGET_PERIOD * cmd->chanlist_len) /
cmd->scan_begin_arg;
if (devpriv->transCount < cmd->chanlist_len) {
- /* tranfer after each scan (and avoid 0) */
+ /* transfer after each scan (and avoid 0) */
devpriv->transCount = cmd->chanlist_len;
} else { /* make a multiple of scan length */
devpriv->transCount =
@@ -2005,12 +1972,12 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->transCount = 0;
devpriv->flags &= ~SEND_EOS;
} else {
- /* interrupt for each tranfer */
+ /* interrupt for each transfer */
RtdAboutCounter(dev, devpriv->transCount - 1);
}
DPRINTK
- ("rtd520: scanLen=%d tranferCount=%d fifoLen=%d\n scanTime(ns)=%d flags=0x%x\n",
+ ("rtd520: scanLen=%d transferCount=%d fifoLen=%d\n scanTime(ns)=%d flags=0x%x\n",
cmd->chanlist_len, devpriv->transCount, devpriv->fifoLen,
cmd->scan_begin_arg, devpriv->flags);
} else { /* unknown timing, just use 1/2 FIFO */
@@ -2348,47 +2315,38 @@ static int rtd_dio_insn_config(struct comedi_device *dev,
return 1;
}
-/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
- */
-static int __devinit rtd520Driver_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static struct comedi_driver rtd520_driver = {
+ .driver_name = "rtd520",
+ .module = THIS_MODULE,
+ .attach = rtd_attach,
+ .detach = rtd_detach,
+};
+
+static int __devinit rtd520_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, rtd520Driver.driver_name);
+ return comedi_pci_auto_config(dev, &rtd520_driver);
}
-static void __devexit rtd520Driver_pci_remove(struct pci_dev *dev)
+static void __devexit rtd520_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver rtd520Driver_pci_driver = {
- .id_table = rtd520_pci_table,
- .probe = &rtd520Driver_pci_probe,
- .remove = __devexit_p(&rtd520Driver_pci_remove)
+static DEFINE_PCI_DEVICE_TABLE(rtd520_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_RTD, 0x7520) },
+ { PCI_DEVICE(PCI_VENDOR_ID_RTD, 0x4520) },
+ { 0 }
};
+MODULE_DEVICE_TABLE(pci, rtd520_pci_table);
-static int __init rtd520Driver_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&rtd520Driver);
- if (retval < 0)
- return retval;
-
- rtd520Driver_pci_driver.name = (char *)rtd520Driver.driver_name;
- return pci_register_driver(&rtd520Driver_pci_driver);
-}
-
-static void __exit rtd520Driver_cleanup_module(void)
-{
- pci_unregister_driver(&rtd520Driver_pci_driver);
- comedi_driver_unregister(&rtd520Driver);
-}
-
-module_init(rtd520Driver_init_module);
-module_exit(rtd520Driver_cleanup_module);
+static struct pci_driver rtd520_pci_driver = {
+ .name = "rtd520",
+ .id_table = rtd520_pci_table,
+ .probe = rtd520_pci_probe,
+ .remove = __devexit_p(rtd520_pci_remove),
+};
+module_comedi_pci_driver(rtd520_driver, rtd520_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
index 72042b818310..f0eb52a77881 100644
--- a/drivers/staging/comedi/drivers/rti800.c
+++ b/drivers/staging/comedi/drivers/rti800.c
@@ -138,39 +138,8 @@ struct rti800_board {
int has_ao;
};
-static const struct rti800_board boardtypes[] = {
- {"rti800", 0},
- {"rti815", 1},
-};
-
#define this_board ((const struct rti800_board *)dev->board_ptr)
-static int rti800_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int rti800_detach(struct comedi_device *dev);
-static struct comedi_driver driver_rti800 = {
- .driver_name = "rti800",
- .module = THIS_MODULE,
- .attach = rti800_attach,
- .detach = rti800_detach,
- .num_names = ARRAY_SIZE(boardtypes),
- .board_name = &boardtypes[0].name,
- .offset = sizeof(struct rti800_board),
-};
-
-static int __init driver_rti800_init_module(void)
-{
- return comedi_driver_register(&driver_rti800);
-}
-
-static void __exit driver_rti800_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_rti800);
-}
-
-module_init(driver_rti800_init_module);
-module_exit(driver_rti800_cleanup_module);
-
static irqreturn_t rti800_interrupt(int irq, void *dev);
struct rti800_private {
@@ -474,19 +443,30 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int rti800_detach(struct comedi_device *dev)
+static void rti800_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: rti800: remove\n", dev->minor);
-
if (dev->iobase)
release_region(dev->iobase, RTI800_SIZE);
-
if (dev->irq)
free_irq(dev->irq, dev);
-
- return 0;
}
+static const struct rti800_board boardtypes[] = {
+ { "rti800", 0 },
+ { "rti815", 1 },
+};
+
+static struct comedi_driver rti800_driver = {
+ .driver_name = "rti800",
+ .module = THIS_MODULE,
+ .attach = rti800_attach,
+ .detach = rti800_detach,
+ .num_names = ARRAY_SIZE(boardtypes),
+ .board_name = &boardtypes[0].name,
+ .offset = sizeof(struct rti800_board),
+};
+module_comedi_driver(rti800_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
index f59cb11590f6..09da5c21858c 100644
--- a/drivers/staging/comedi/drivers/rti802.c
+++ b/drivers/staging/comedi/drivers/rti802.c
@@ -47,29 +47,6 @@ Configuration Options:
#define RTI802_DATALOW 1
#define RTI802_DATAHIGH 2
-static int rti802_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int rti802_detach(struct comedi_device *dev);
-static struct comedi_driver driver_rti802 = {
- .driver_name = "rti802",
- .module = THIS_MODULE,
- .attach = rti802_attach,
- .detach = rti802_detach,
-};
-
-static int __init driver_rti802_init_module(void)
-{
- return comedi_driver_register(&driver_rti802);
-}
-
-static void __exit driver_rti802_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_rti802);
-}
-
-module_init(driver_rti802_init_module);
-module_exit(driver_rti802_cleanup_module);
-
struct rti802_private {
enum {
dac_2comp, dac_straight
@@ -152,16 +129,20 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static int rti802_detach(struct comedi_device *dev)
+static void rti802_detach(struct comedi_device *dev)
{
- printk(KERN_INFO "comedi%d: rti802: remove\n", dev->minor);
-
if (dev->iobase)
release_region(dev->iobase, RTI802_SIZE);
-
- return 0;
}
+static struct comedi_driver rti802_driver = {
+ .driver_name = "rti802",
+ .module = THIS_MODULE,
+ .attach = rti802_attach,
+ .detach = rti802_detach,
+};
+module_comedi_driver(rti802_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
index 2b34daedc3d7..7a56434eb224 100644
--- a/drivers/staging/comedi/drivers/s526.c
+++ b/drivers/staging/comedi/drivers/s526.c
@@ -230,287 +230,6 @@ struct s526_private {
*/
#define devpriv ((struct s526_private *)dev->private)
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int s526_detach(struct comedi_device *dev);
-static struct comedi_driver driver_s526 = {
- .driver_name = "s526",
- .module = THIS_MODULE,
- .attach = s526_attach,
- .detach = s526_detach,
-/* It is not necessary to implement the following members if you are
- * writing a driver for a ISA PnP or PCI card */
- /* Most drivers will support multiple types of boards by
- * having an array of board structures. These were defined
- * in s526_boards[] above. Note that the element 'name'
- * was first in the structure -- Comedi uses this fact to
- * extract the name of the board without knowing any details
- * about the structure except for its length.
- * When a device is attached (by comedi_config), the name
- * of the device is given to Comedi, and Comedi tries to
- * match it by going through the list of board names. If
- * there is a match, the address of the pointer is put
- * into dev->board_ptr and driver->attach() is called.
- *
- * Note that these are not necessary if you can determine
- * the type of board in software. ISA PnP, PCI, and PCMCIA
- * devices are such boards.
- */
- .board_name = &s526_boards[0].name,
- .offset = sizeof(struct s526_board),
- .num_names = ARRAY_SIZE(s526_boards),
-};
-
-static int s526_gpct_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data);
-static int s526_gpct_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int s526_gpct_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data);
-static int s526_ai_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int s526_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int s526_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int s526_dio_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int s526_dio_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
-static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- int iobase;
- int i, n;
-/* short value; */
-/* int subdev_channel = 0; */
- union cmReg cmReg;
-
- printk(KERN_INFO "comedi%d: s526: ", dev->minor);
-
- iobase = it->options[0];
- if (!iobase || !request_region(iobase, S526_IOSIZE, thisboard->name)) {
- comedi_error(dev, "I/O port conflict");
- return -EIO;
- }
- dev->iobase = iobase;
-
- printk("iobase=0x%lx\n", dev->iobase);
-
- /*** make it a little quieter, exw, 8/29/06
- for (i = 0; i < S526_NUM_PORTS; i++) {
- printk("0x%02x: 0x%04x\n", ADDR_REG(s526_ports[i]),
- inw(ADDR_REG(s526_ports[i])));
- }
- ***/
-
-/*
- * Initialize dev->board_name. Note that we can use the "thisboard"
- * macro now, since we just initialized it in the last line.
- */
- dev->board_ptr = &s526_boards[0];
-
- dev->board_name = thisboard->name;
-
-/*
- * Allocate the private structure area. alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
- if (alloc_private(dev, sizeof(struct s526_private)) < 0)
- return -ENOMEM;
-
-/*
- * Allocate the subdevice structures. alloc_subdevice() is a
- * convenient macro defined in comedidev.h.
- */
- dev->n_subdevices = 4;
- if (alloc_subdevices(dev, dev->n_subdevices) < 0)
- return -ENOMEM;
-
- s = dev->subdevices + 0;
- /* GENERAL-PURPOSE COUNTER/TIME (GPCT) */
- s->type = COMEDI_SUBD_COUNTER;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL;
- /* KG: What does SDF_LSAMPL (see multiq3.c) mean? */
- s->n_chan = thisboard->gpct_chans;
- s->maxdata = 0x00ffffff; /* 24 bit counter */
- s->insn_read = s526_gpct_rinsn;
- s->insn_config = s526_gpct_insn_config;
- s->insn_write = s526_gpct_winsn;
-
- /* Command are not implemented yet, however they are necessary to
- allocate the necessary memory for the comedi_async struct (used
- to trigger the GPCT in case of pulsegenerator function */
- /* s->do_cmd = s526_gpct_cmd; */
- /* s->do_cmdtest = s526_gpct_cmdtest; */
- /* s->cancel = s526_gpct_cancel; */
-
- s = dev->subdevices + 1;
- /* dev->read_subdev=s; */
- /* analog input subdevice */
- s->type = COMEDI_SUBD_AI;
- /* we support differential */
- s->subdev_flags = SDF_READABLE | SDF_DIFF;
- /* channels 0 to 7 are the regular differential inputs */
- /* channel 8 is "reference 0" (+10V), channel 9 is "reference 1" (0V) */
- s->n_chan = 10;
- s->maxdata = 0xffff;
- s->range_table = &range_bipolar10;
- s->len_chanlist = 16; /* This is the maximum chanlist length that
- the board can handle */
- s->insn_read = s526_ai_rinsn;
- s->insn_config = s526_ai_insn_config;
-
- s = dev->subdevices + 2;
- /* analog output subdevice */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = 4;
- s->maxdata = 0xffff;
- s->range_table = &range_bipolar10;
- s->insn_write = s526_ao_winsn;
- s->insn_read = s526_ao_rinsn;
-
- s = dev->subdevices + 3;
- /* digital i/o subdevice */
- if (thisboard->have_dio) {
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 8;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = s526_dio_insn_bits;
- s->insn_config = s526_dio_insn_config;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
-
- printk(KERN_INFO "attached\n");
-
- return 1;
-
-#if 0
- /* Example of Counter Application */
- /* One-shot (software trigger) */
- cmReg.reg.coutSource = 0; /* out RCAP */
- cmReg.reg.coutPolarity = 1; /* Polarity inverted */
- cmReg.reg.autoLoadResetRcap = 1;/* Auto load 0:disabled, 1:enabled */
- cmReg.reg.hwCtEnableSource = 3; /* NOT RCAP */
- cmReg.reg.ctEnableCtrl = 2; /* Hardware */
- cmReg.reg.clockSource = 2; /* Internal */
- cmReg.reg.countDir = 1; /* Down */
- cmReg.reg.countDirCtrl = 1; /* Software */
- cmReg.reg.outputRegLatchCtrl = 0; /* latch on read */
- cmReg.reg.preloadRegSel = 0; /* PR0 */
- cmReg.reg.reserved = 0;
-
- outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
-
- outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel));
- outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel));
-
- /* Reset the counter */
- outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
- /* Load the counter from PR0 */
- outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
- /* Reset RCAP (fires one-shot) */
- outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel));
-
-#else
-
- /* Set Counter Mode Register */
- cmReg.reg.coutSource = 0; /* out RCAP */
- cmReg.reg.coutPolarity = 0; /* Polarity inverted */
- cmReg.reg.autoLoadResetRcap = 0; /* Auto load disabled */
- cmReg.reg.hwCtEnableSource = 2; /* NOT RCAP */
- cmReg.reg.ctEnableCtrl = 1; /* 1: Software, >1 : Hardware */
- cmReg.reg.clockSource = 3; /* x4 */
- cmReg.reg.countDir = 0; /* up */
- cmReg.reg.countDirCtrl = 0; /* quadrature */
- cmReg.reg.outputRegLatchCtrl = 0; /* latch on read */
- cmReg.reg.preloadRegSel = 0; /* PR0 */
- cmReg.reg.reserved = 0;
-
- n = 0;
- printk(KERN_INFO "Mode reg=0x%04x, 0x%04lx\n",
- cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
- outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
- udelay(1000);
- printk(KERN_INFO "Read back mode reg=0x%04x\n",
- inw(ADDR_CHAN_REG(REG_C0M, n)));
-
- /* Load the pre-load register high word */
-/* value = (short) (0x55); */
-/* outw(value, ADDR_CHAN_REG(REG_C0H, n)); */
-
- /* Load the pre-load register low word */
-/* value = (short)(0xaa55); */
-/* outw(value, ADDR_CHAN_REG(REG_C0L, n)); */
-
- /* Write the Counter Control Register */
-/* outw(value, ADDR_CHAN_REG(REG_C0C, 0)); */
-
- /* Reset the counter if it is software preload */
- if (cmReg.reg.autoLoadResetRcap == 0) {
- /* Reset the counter */
- outw(0x8000, ADDR_CHAN_REG(REG_C0C, n));
- /* Load the counter from PR0 */
- outw(0x4000, ADDR_CHAN_REG(REG_C0C, n));
- }
-
- outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
- udelay(1000);
- printk(KERN_INFO "Read back mode reg=0x%04x\n",
- inw(ADDR_CHAN_REG(REG_C0M, n)));
-
-#endif
- printk(KERN_INFO "Current registres:\n");
-
- for (i = 0; i < S526_NUM_PORTS; i++) {
- printk(KERN_INFO "0x%02lx: 0x%04x\n",
- ADDR_REG(s526_ports[i]), inw(ADDR_REG(s526_ports[i])));
- }
- return 1;
-}
-
-/*
- * _detach is called to deconfigure a device. It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach(). dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static int s526_detach(struct comedi_device *dev)
-{
- printk(KERN_INFO "comedi%d: s526: remove\n", dev->minor);
-
- if (dev->iobase > 0)
- release_region(dev->iobase, S526_IOSIZE);
-
- return 0;
-}
-
static int s526_gpct_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn,
unsigned int *data)
@@ -1023,22 +742,218 @@ static int s526_dio_insn_config(struct comedi_device *dev,
return 1;
}
+static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+{
+ struct comedi_subdevice *s;
+ int iobase;
+ int i, n;
+/* short value; */
+/* int subdev_channel = 0; */
+ union cmReg cmReg;
+
+ printk(KERN_INFO "comedi%d: s526: ", dev->minor);
+
+ iobase = it->options[0];
+ if (!iobase || !request_region(iobase, S526_IOSIZE, thisboard->name)) {
+ comedi_error(dev, "I/O port conflict");
+ return -EIO;
+ }
+ dev->iobase = iobase;
+
+ printk("iobase=0x%lx\n", dev->iobase);
+
+ /*** make it a little quieter, exw, 8/29/06
+ for (i = 0; i < S526_NUM_PORTS; i++) {
+ printk("0x%02x: 0x%04x\n", ADDR_REG(s526_ports[i]),
+ inw(ADDR_REG(s526_ports[i])));
+ }
+ ***/
+
/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
+ * Initialize dev->board_name. Note that we can use the "thisboard"
+ * macro now, since we just initialized it in the last line.
*/
-static int __init driver_s526_init_module(void)
-{
- return comedi_driver_register(&driver_s526);
+ dev->board_ptr = &s526_boards[0];
+
+ dev->board_name = thisboard->name;
+
+/*
+ * Allocate the private structure area. alloc_private() is a
+ * convenient macro defined in comedidev.h.
+ */
+ if (alloc_private(dev, sizeof(struct s526_private)) < 0)
+ return -ENOMEM;
+
+/*
+ * Allocate the subdevice structures. alloc_subdevice() is a
+ * convenient macro defined in comedidev.h.
+ */
+ dev->n_subdevices = 4;
+ if (alloc_subdevices(dev, dev->n_subdevices) < 0)
+ return -ENOMEM;
+
+ s = dev->subdevices + 0;
+ /* GENERAL-PURPOSE COUNTER/TIME (GPCT) */
+ s->type = COMEDI_SUBD_COUNTER;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL;
+ /* KG: What does SDF_LSAMPL (see multiq3.c) mean? */
+ s->n_chan = thisboard->gpct_chans;
+ s->maxdata = 0x00ffffff; /* 24 bit counter */
+ s->insn_read = s526_gpct_rinsn;
+ s->insn_config = s526_gpct_insn_config;
+ s->insn_write = s526_gpct_winsn;
+
+ /* Command are not implemented yet, however they are necessary to
+ allocate the necessary memory for the comedi_async struct (used
+ to trigger the GPCT in case of pulsegenerator function */
+ /* s->do_cmd = s526_gpct_cmd; */
+ /* s->do_cmdtest = s526_gpct_cmdtest; */
+ /* s->cancel = s526_gpct_cancel; */
+
+ s = dev->subdevices + 1;
+ /* dev->read_subdev=s; */
+ /* analog input subdevice */
+ s->type = COMEDI_SUBD_AI;
+ /* we support differential */
+ s->subdev_flags = SDF_READABLE | SDF_DIFF;
+ /* channels 0 to 7 are the regular differential inputs */
+ /* channel 8 is "reference 0" (+10V), channel 9 is "reference 1" (0V) */
+ s->n_chan = 10;
+ s->maxdata = 0xffff;
+ s->range_table = &range_bipolar10;
+ s->len_chanlist = 16; /* This is the maximum chanlist length that
+ the board can handle */
+ s->insn_read = s526_ai_rinsn;
+ s->insn_config = s526_ai_insn_config;
+
+ s = dev->subdevices + 2;
+ /* analog output subdevice */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 4;
+ s->maxdata = 0xffff;
+ s->range_table = &range_bipolar10;
+ s->insn_write = s526_ao_winsn;
+ s->insn_read = s526_ao_rinsn;
+
+ s = dev->subdevices + 3;
+ /* digital i/o subdevice */
+ if (thisboard->have_dio) {
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = s526_dio_insn_bits;
+ s->insn_config = s526_dio_insn_config;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ printk(KERN_INFO "attached\n");
+
+ return 1;
+
+#if 0
+ /* Example of Counter Application */
+ /* One-shot (software trigger) */
+ cmReg.reg.coutSource = 0; /* out RCAP */
+ cmReg.reg.coutPolarity = 1; /* Polarity inverted */
+ cmReg.reg.autoLoadResetRcap = 1;/* Auto load 0:disabled, 1:enabled */
+ cmReg.reg.hwCtEnableSource = 3; /* NOT RCAP */
+ cmReg.reg.ctEnableCtrl = 2; /* Hardware */
+ cmReg.reg.clockSource = 2; /* Internal */
+ cmReg.reg.countDir = 1; /* Down */
+ cmReg.reg.countDirCtrl = 1; /* Software */
+ cmReg.reg.outputRegLatchCtrl = 0; /* latch on read */
+ cmReg.reg.preloadRegSel = 0; /* PR0 */
+ cmReg.reg.reserved = 0;
+
+ outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+
+ outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+
+ /* Reset the counter */
+ outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ /* Load the counter from PR0 */
+ outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ /* Reset RCAP (fires one-shot) */
+ outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+
+#else
+
+ /* Set Counter Mode Register */
+ cmReg.reg.coutSource = 0; /* out RCAP */
+ cmReg.reg.coutPolarity = 0; /* Polarity inverted */
+ cmReg.reg.autoLoadResetRcap = 0; /* Auto load disabled */
+ cmReg.reg.hwCtEnableSource = 2; /* NOT RCAP */
+ cmReg.reg.ctEnableCtrl = 1; /* 1: Software, >1 : Hardware */
+ cmReg.reg.clockSource = 3; /* x4 */
+ cmReg.reg.countDir = 0; /* up */
+ cmReg.reg.countDirCtrl = 0; /* quadrature */
+ cmReg.reg.outputRegLatchCtrl = 0; /* latch on read */
+ cmReg.reg.preloadRegSel = 0; /* PR0 */
+ cmReg.reg.reserved = 0;
+
+ n = 0;
+ printk(KERN_INFO "Mode reg=0x%04x, 0x%04lx\n",
+ cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
+ outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
+ udelay(1000);
+ printk(KERN_INFO "Read back mode reg=0x%04x\n",
+ inw(ADDR_CHAN_REG(REG_C0M, n)));
+
+ /* Load the pre-load register high word */
+/* value = (short) (0x55); */
+/* outw(value, ADDR_CHAN_REG(REG_C0H, n)); */
+
+ /* Load the pre-load register low word */
+/* value = (short)(0xaa55); */
+/* outw(value, ADDR_CHAN_REG(REG_C0L, n)); */
+
+ /* Write the Counter Control Register */
+/* outw(value, ADDR_CHAN_REG(REG_C0C, 0)); */
+
+ /* Reset the counter if it is software preload */
+ if (cmReg.reg.autoLoadResetRcap == 0) {
+ /* Reset the counter */
+ outw(0x8000, ADDR_CHAN_REG(REG_C0C, n));
+ /* Load the counter from PR0 */
+ outw(0x4000, ADDR_CHAN_REG(REG_C0C, n));
+ }
+
+ outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
+ udelay(1000);
+ printk(KERN_INFO "Read back mode reg=0x%04x\n",
+ inw(ADDR_CHAN_REG(REG_C0M, n)));
+
+#endif
+ printk(KERN_INFO "Current registres:\n");
+
+ for (i = 0; i < S526_NUM_PORTS; i++) {
+ printk(KERN_INFO "0x%02lx: 0x%04x\n",
+ ADDR_REG(s526_ports[i]), inw(ADDR_REG(s526_ports[i])));
+ }
+ return 1;
}
-static void __exit driver_s526_cleanup_module(void)
+static void s526_detach(struct comedi_device *dev)
{
- comedi_driver_unregister(&driver_s526);
+ if (dev->iobase > 0)
+ release_region(dev->iobase, S526_IOSIZE);
}
-module_init(driver_s526_init_module);
-module_exit(driver_s526_cleanup_module);
+static struct comedi_driver s526_driver = {
+ .driver_name = "s526",
+ .module = THIS_MODULE,
+ .attach = s526_attach,
+ .detach = s526_detach,
+ .board_name = &s526_boards[0].name,
+ .offset = sizeof(struct s526_board),
+ .num_names = ARRAY_SIZE(s526_boards),
+};
+module_comedi_driver(s526_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 23fc64b9988e..7beb8f6853af 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -79,12 +79,17 @@ INSN_CONFIG instructions:
#include "comedi_fc.h"
#include "s626.h"
-MODULE_AUTHOR("Gianluca Palli <gpalli@deis.unibo.it>");
-MODULE_DESCRIPTION("Sensoray 626 Comedi driver module");
-MODULE_LICENSE("GPL");
+#define PCI_VENDOR_ID_S626 0x1131
+#define PCI_DEVICE_ID_S626 0x7146
+#define PCI_SUBVENDOR_ID_S626 0x6000
+#define PCI_SUBDEVICE_ID_S626 0x0272
struct s626_board {
const char *name;
+ int vendor_id;
+ int device_id;
+ int subvendor_id;
+ int subdevice_id;
int ai_chans;
int ai_bits;
int ao_chans;
@@ -97,6 +102,10 @@ struct s626_board {
static const struct s626_board s626_boards[] = {
{
.name = "s626",
+ .vendor_id = PCI_VENDOR_ID_S626,
+ .device_id = PCI_DEVICE_ID_S626,
+ .subvendor_id = PCI_SUBVENDOR_ID_S626,
+ .subdevice_id = PCI_SUBDEVICE_ID_S626,
.ai_chans = S626_ADC_CHANNELS,
.ai_bits = 14,
.ao_chans = S626_DAC_CHANNELS,
@@ -108,30 +117,6 @@ static const struct s626_board s626_boards[] = {
};
#define thisboard ((const struct s626_board *)dev->board_ptr)
-#define PCI_VENDOR_ID_S626 0x1131
-#define PCI_DEVICE_ID_S626 0x7146
-
-/*
- * For devices with vendor:device id == 0x1131:0x7146 you must specify
- * also subvendor:subdevice ids, because otherwise it will conflict with
- * Philips SAA7146 media/dvb based cards.
- */
-static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = {
- {PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, 0x6000, 0x0272, 0, 0, 0},
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, s626_pci_table);
-
-static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int s626_detach(struct comedi_device *dev);
-
-static struct comedi_driver driver_s626 = {
- .driver_name = "s626",
- .module = THIS_MODULE,
- .attach = s626_attach,
- .detach = s626_detach,
-};
struct s626_private {
struct pci_dev *pdev;
@@ -224,44 +209,6 @@ static struct dio_private *dio_private_word[]={
#define devpriv ((struct s626_private *)dev->private)
#define diopriv ((struct dio_private *)s->private)
-static int __devinit driver_s626_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, driver_s626.driver_name);
-}
-
-static void __devexit driver_s626_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver driver_s626_pci_driver = {
- .id_table = s626_pci_table,
- .probe = &driver_s626_pci_probe,
- .remove = __devexit_p(&driver_s626_pci_remove)
-};
-
-static int __init driver_s626_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_s626);
- if (retval < 0)
- return retval;
-
- driver_s626_pci_driver.name = (char *)driver_s626.driver_name;
- return pci_register_driver(&driver_s626_pci_driver);
-}
-
-static void __exit driver_s626_cleanup_module(void)
-{
- pci_unregister_driver(&driver_s626_pci_driver);
- comedi_driver_unregister(&driver_s626);
-}
-
-module_init(driver_s626_init_module);
-module_exit(driver_s626_cleanup_module);
-
/* ioctl routines */
static int s626_ai_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
@@ -554,17 +501,17 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it)
resource_size_t resourceStart;
dma_addr_t appdma;
struct comedi_subdevice *s;
- const struct pci_device_id *ids;
struct pci_dev *pdev = NULL;
if (alloc_private(dev, sizeof(struct s626_private)) < 0)
return -ENOMEM;
- for (i = 0; i < (ARRAY_SIZE(s626_pci_table) - 1) && !pdev; i++) {
- ids = &s626_pci_table[i];
+ for (i = 0; i < ARRAY_SIZE(s626_boards) && !pdev; i++) {
do {
- pdev = pci_get_subsys(ids->vendor, ids->device,
- ids->subvendor, ids->subdevice,
+ pdev = pci_get_subsys(s626_boards[i].vendor_id,
+ s626_boards[i].device_id,
+ s626_boards[i].subvendor_id,
+ s626_boards[i].subdevice_id,
pdev);
if ((it->options[0] || it->options[1]) && pdev) {
@@ -1365,7 +1312,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d)
return IRQ_HANDLED;
}
-static int s626_detach(struct comedi_device *dev)
+static void s626_detach(struct comedi_device *dev)
{
if (devpriv) {
/* stop ai_command */
@@ -1389,20 +1336,14 @@ static int s626_detach(struct comedi_device *dev)
if (dev->irq)
free_irq(dev->irq, dev);
-
if (devpriv->base_addr)
iounmap(devpriv->base_addr);
-
if (devpriv->pdev) {
if (devpriv->got_regions)
comedi_pci_disable(devpriv->pdev);
pci_dev_put(devpriv->pdev);
}
}
-
- DEBUG("s626_detach: S626 detached!\n");
-
- return 0;
}
/*
@@ -3367,3 +3308,45 @@ static void CountersInit(struct comedi_device *dev)
DEBUG("CountersInit: counters initialized\n");
}
+
+static struct comedi_driver s626_driver = {
+ .driver_name = "s626",
+ .module = THIS_MODULE,
+ .attach = s626_attach,
+ .detach = s626_detach,
+};
+
+static int __devinit s626_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &s626_driver);
+}
+
+static void __devexit s626_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+/*
+ * For devices with vendor:device id == 0x1131:0x7146 you must specify
+ * also subvendor:subdevice ids, because otherwise it will conflict with
+ * Philips SAA7146 media/dvb based cards.
+ */
+static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = {
+ { PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626,
+ PCI_SUBVENDOR_ID_S626, PCI_SUBDEVICE_ID_S626, 0, 0, 0 },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, s626_pci_table);
+
+static struct pci_driver s626_pci_driver = {
+ .name = "s626",
+ .id_table = s626_pci_table,
+ .probe = s626_pci_probe,
+ .remove = __devexit_p(s626_pci_remove),
+};
+module_comedi_pci_driver(s626_driver, s626_pci_driver);
+
+MODULE_AUTHOR("Gianluca Palli <gpalli@deis.unibo.it>");
+MODULE_DESCRIPTION("Sensoray 626 Comedi driver module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index d880c2f6fbc1..6342bc5ddb3e 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -43,20 +43,10 @@ Status: in development
#include <linux/serial.h>
#include <linux/poll.h>
-/*
- * Board descriptions for two imaginary boards. Describing the
- * boards in this way is optional, and completely driver-dependent.
- * Some drivers use arrays such as this, other do not.
- */
struct serial2002_board {
const char *name;
};
-static const struct serial2002_board serial2002_boards[] = {
- {
- .name = "serial2002"}
-};
-
/*
* Useful for shorthand access to the particular board structure
*/
@@ -89,35 +79,6 @@ struct serial2002_private {
*/
#define devpriv ((struct serial2002_private *)dev->private)
-static int serial2002_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int serial2002_detach(struct comedi_device *dev);
-struct comedi_driver driver_serial2002 = {
- .driver_name = "serial2002",
- .module = THIS_MODULE,
- .attach = serial2002_attach,
- .detach = serial2002_detach,
- .board_name = &serial2002_boards[0].name,
- .offset = sizeof(struct serial2002_board),
- .num_names = ARRAY_SIZE(serial2002_boards),
-};
-
-static int serial2002_di_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int serial2002_do_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int serial2002_ai_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int serial2002_ao_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int serial2002_ao_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
struct serial_data {
enum { is_invalid, is_digital, is_channel } kind;
int index;
@@ -887,32 +848,34 @@ static int serial2002_attach(struct comedi_device *dev,
return 1;
}
-static int serial2002_detach(struct comedi_device *dev)
+static void serial2002_detach(struct comedi_device *dev)
{
struct comedi_subdevice *s;
int i;
- dev_dbg(dev->hw_dev, "comedi%d: remove\n", dev->minor);
for (i = 0; i < 5; i++) {
s = &dev->subdevices[i];
kfree(s->maxdata_list);
kfree(s->range_table_list);
}
- return 0;
-}
-
-static int __init driver_serial2002_init_module(void)
-{
- return comedi_driver_register(&driver_serial2002);
}
-static void __exit driver_serial2002_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_serial2002);
-}
+static const struct serial2002_board serial2002_boards[] = {
+ {
+ .name = "serial2002"
+ },
+};
-module_init(driver_serial2002_init_module);
-module_exit(driver_serial2002_cleanup_module);
+static struct comedi_driver serial2002_driver = {
+ .driver_name = "serial2002",
+ .module = THIS_MODULE,
+ .attach = serial2002_attach,
+ .detach = serial2002_detach,
+ .board_name = &serial2002_boards[0].name,
+ .offset = sizeof(struct serial2002_board),
+ .num_names = ARRAY_SIZE(serial2002_boards),
+};
+module_comedi_driver(serial2002_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
index ed69008f0d39..7d13ffa7f4f9 100644
--- a/drivers/staging/comedi/drivers/skel.c
+++ b/drivers/staging/comedi/drivers/skel.c
@@ -156,7 +156,7 @@ struct skel_private {
* the device code.
*/
static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int skel_detach(struct comedi_device *dev);
+static void skel_detach(struct comedi_device *dev);
static struct comedi_driver driver_skel = {
.driver_name = "dummy",
.module = THIS_MODULE,
@@ -295,11 +295,8 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it)
* allocated by _attach(). dev->private and dev->subdevices are
* deallocated automatically by the core.
*/
-static int skel_detach(struct comedi_device *dev)
+static void skel_detach(struct comedi_device *dev)
{
- pr_info("comedi%d: skel: remove\n", dev->minor);
-
- return 0;
}
/*
@@ -623,7 +620,7 @@ static int skel_dio_insn_config(struct comedi_device *dev,
static int __devinit driver_skel_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, driver_skel.driver_name);
+ return comedi_pci_auto_config(dev, &driver_skel);
}
static void __devexit driver_skel_pci_remove(struct pci_dev *dev)
diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
index 526de2efa125..16c4f5a757bb 100644
--- a/drivers/staging/comedi/drivers/ssv_dnp.c
+++ b/drivers/staging/comedi/drivers/ssv_dnp.c
@@ -59,16 +59,6 @@ struct dnp_board {
int have_dio;
};
-/* We only support one DNP 'board' variant at the moment */
-static const struct dnp_board dnp_boards[] = {
-{
- .name = "dnp-1486",
- .ai_chans = 16,
- .ai_bits = 12,
- .have_dio = 1,
- },
-};
-
/* Useful for shorthand access to the particular board structure ----------- */
#define thisboard ((const struct dnp_board *)dev->board_ptr)
@@ -81,136 +71,6 @@ struct dnp_private_data {
#define devpriv ((dnp_private *)dev->private)
/* ------------------------------------------------------------------------- */
-/* The struct comedi_driver structure tells the Comedi core module which */
-/* functions to call to configure/deconfigure (attach/detach) the board, and */
-/* also about the kernel module that contains the device code. */
-/* */
-/* In the following section we define the API of this driver. */
-/* ------------------------------------------------------------------------- */
-
-static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static int dnp_detach(struct comedi_device *dev);
-
-static struct comedi_driver driver_dnp = {
- .driver_name = "ssv_dnp",
- .module = THIS_MODULE,
- .attach = dnp_attach,
- .detach = dnp_detach,
- .board_name = &dnp_boards[0].name,
- /* only necessary for non-PnP devs */
- .offset = sizeof(struct dnp_board), /* like ISA-PnP, PCI or PCMCIA */
- .num_names = ARRAY_SIZE(dnp_boards),
-};
-
-static int __init driver_dnp_init_module(void)
-{
- return comedi_driver_register(&driver_dnp);
-}
-
-static void __exit driver_dnp_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_dnp);
-}
-
-module_init(driver_dnp_init_module);
-module_exit(driver_dnp_cleanup_module);
-
-static int dnp_dio_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static int dnp_dio_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-/* ------------------------------------------------------------------------- */
-/* Attach is called by comedi core to configure the driver for a particular */
-/* board. If you specified a board_name array in the driver structure, */
-/* dev->board_ptr contains that address. */
-/* ------------------------------------------------------------------------- */
-
-static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
-
- struct comedi_subdevice *s;
-
- printk(KERN_INFO "comedi%d: dnp: ", dev->minor);
-
- /* Autoprobing: this should find out which board we have. Currently */
- /* only the 1486 board is supported and autoprobing is not */
- /* implemented :-) */
- /* dev->board_ptr = dnp_probe(dev); */
-
- /* Initialize the name of the board. */
- /* We can use the "thisboard" macro now. */
- dev->board_name = thisboard->name;
-
- /* Allocate the private structure area. alloc_private() is a */
- /* convenient macro defined in comedidev.h. */
- if (alloc_private(dev, sizeof(struct dnp_private_data)) < 0)
- return -ENOMEM;
-
- /* Allocate the subdevice structures. alloc_subdevice() is a */
- /* convenient macro defined in comedidev.h. */
-
- if (alloc_subdevices(dev, 1) < 0)
- return -ENOMEM;
-
- s = dev->subdevices + 0;
- /* digital i/o subdevice */
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 20;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = dnp_dio_insn_bits;
- s->insn_config = dnp_dio_insn_config;
-
- printk("attached\n");
-
- /* We use the I/O ports 0x22,0x23 and 0xa3-0xa9, which are always
- * allocated for the primary 8259, so we don't need to allocate them
- * ourselves. */
-
- /* configure all ports as input (default) */
- outb(PAMR, CSCIR);
- outb(0x00, CSCDR);
- outb(PBMR, CSCIR);
- outb(0x00, CSCDR);
- outb(PCMR, CSCIR);
- outb((inb(CSCDR) & 0xAA), CSCDR);
-
- return 1;
-
-}
-
-/* ------------------------------------------------------------------------- */
-/* detach is called to deconfigure a device. It should deallocate the */
-/* resources. This function is also called when _attach() fails, so it */
-/* should be careful not to release resources that were not necessarily */
-/* allocated by _attach(). dev->private and dev->subdevices are */
-/* deallocated automatically by the core. */
-/* ------------------------------------------------------------------------- */
-
-static int dnp_detach(struct comedi_device *dev)
-{
-
- /* configure all ports as input (default) */
- outb(PAMR, CSCIR);
- outb(0x00, CSCDR);
- outb(PBMR, CSCIR);
- outb(0x00, CSCDR);
- outb(PCMR, CSCIR);
- outb((inb(CSCDR) & 0xAA), CSCDR);
-
- /* announce that we are finished */
- printk(KERN_INFO "comedi%d: dnp: remove\n", dev->minor);
-
- return 0;
-
-}
-
-/* ------------------------------------------------------------------------- */
/* The insn_bits interface allows packed reading/writing of DIO channels. */
/* The comedi core can convert between insn_bits and insn_read/write, so you */
/* are able to use these instructions as well. */
@@ -326,6 +186,89 @@ static int dnp_dio_insn_config(struct comedi_device *dev,
}
+static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+{
+ struct comedi_subdevice *s;
+
+ printk(KERN_INFO "comedi%d: dnp: ", dev->minor);
+
+ /* Autoprobing: this should find out which board we have. Currently */
+ /* only the 1486 board is supported and autoprobing is not */
+ /* implemented :-) */
+ /* dev->board_ptr = dnp_probe(dev); */
+
+ /* Initialize the name of the board. */
+ /* We can use the "thisboard" macro now. */
+ dev->board_name = thisboard->name;
+
+ /* Allocate the private structure area. alloc_private() is a */
+ /* convenient macro defined in comedidev.h. */
+ if (alloc_private(dev, sizeof(struct dnp_private_data)) < 0)
+ return -ENOMEM;
+
+ /* Allocate the subdevice structures. alloc_subdevice() is a */
+ /* convenient macro defined in comedidev.h. */
+
+ if (alloc_subdevices(dev, 1) < 0)
+ return -ENOMEM;
+
+ s = dev->subdevices + 0;
+ /* digital i/o subdevice */
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 20;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = dnp_dio_insn_bits;
+ s->insn_config = dnp_dio_insn_config;
+
+ printk("attached\n");
+
+ /* We use the I/O ports 0x22,0x23 and 0xa3-0xa9, which are always
+ * allocated for the primary 8259, so we don't need to allocate them
+ * ourselves. */
+
+ /* configure all ports as input (default) */
+ outb(PAMR, CSCIR);
+ outb(0x00, CSCDR);
+ outb(PBMR, CSCIR);
+ outb(0x00, CSCDR);
+ outb(PCMR, CSCIR);
+ outb((inb(CSCDR) & 0xAA), CSCDR);
+
+ return 1;
+}
+
+static void dnp_detach(struct comedi_device *dev)
+{
+ outb(PAMR, CSCIR);
+ outb(0x00, CSCDR);
+ outb(PBMR, CSCIR);
+ outb(0x00, CSCDR);
+ outb(PCMR, CSCIR);
+ outb((inb(CSCDR) & 0xAA), CSCDR);
+}
+
+static const struct dnp_board dnp_boards[] = {
+ {
+ .name = "dnp-1486",
+ .ai_chans = 16,
+ .ai_bits = 12,
+ .have_dio = 1,
+ },
+};
+
+static struct comedi_driver dnp_driver = {
+ .driver_name = "ssv_dnp",
+ .module = THIS_MODULE,
+ .attach = dnp_attach,
+ .detach = dnp_detach,
+ .board_name = &dnp_boards[0].name,
+ .offset = sizeof(struct dnp_board),
+ .num_names = ARRAY_SIZE(dnp_boards),
+};
+module_comedi_driver(dnp_driver);
+
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
index f45824f0d86b..d5f1f22aa708 100644
--- a/drivers/staging/comedi/drivers/unioxx5.c
+++ b/drivers/staging/comedi/drivers/unioxx5.c
@@ -83,96 +83,188 @@ struct unioxx5_subd_priv {
unsigned char usp_prev_cn_val[3]; /* previous channel value */
};
-static int unioxx5_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static int unioxx5_subdev_write(struct comedi_device *dev,
- struct comedi_subdevice *subdev,
- struct comedi_insn *insn, unsigned int *data);
-static int unioxx5_subdev_read(struct comedi_device *dev,
- struct comedi_subdevice *subdev,
- struct comedi_insn *insn, unsigned int *data);
-static int unioxx5_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *subdev,
- struct comedi_insn *insn, unsigned int *data);
-static int unioxx5_detach(struct comedi_device *dev);
-static int __unioxx5_subdev_init(struct comedi_subdevice *subdev,
- int subdev_iobase, int minor);
-static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp,
- unsigned int *data, int channel, int minor);
-static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp,
- unsigned int *data, int channel, int minor);
-/* static void __unioxx5_digital_config(struct unioxx5_subd_priv* usp, int mode); */
-static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp,
- unsigned int *data, int channel, int minor);
-static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp,
- unsigned int *data, int channel, int minor);
-static int __unioxx5_define_chan_offset(int chan_num);
-static void __unioxx5_analog_config(struct unioxx5_subd_priv *usp, int channel);
+static int __unioxx5_define_chan_offset(int chan_num)
+{
-static struct comedi_driver unioxx5_driver = {
- .driver_name = DRIVER_NAME,
- .module = THIS_MODULE,
- .attach = unioxx5_attach,
- .detach = unioxx5_detach
-};
+ if (chan_num < 0 || chan_num > 23)
+ return -1;
-static int __init unioxx5_driver_init_module(void)
+ return (chan_num >> 3) + 1;
+}
+
+#if 0 /* not used? */
+static void __unioxx5_digital_config(struct unioxx5_subd_priv *usp, int mode)
{
- return comedi_driver_register(&unioxx5_driver);
+ int i, mask;
+
+ mask = (mode == ALL_2_OUTPUT) ? 0xFF : 0x00;
+ printk("COMEDI: mode = %d\n", mask);
+
+ outb(1, usp->usp_iobase + 0);
+
+ for (i = 0; i < 3; i++)
+ outb(mask, usp->usp_iobase + i);
+
+ outb(0, usp->usp_iobase + 0);
}
+#endif
-static void __exit unioxx5_driver_cleanup_module(void)
+/* configure channels for analog i/o (even to output, odd to input) */
+static void __unioxx5_analog_config(struct unioxx5_subd_priv *usp, int channel)
{
- comedi_driver_unregister(&unioxx5_driver);
+ int chan_a, chan_b, conf, channel_offset;
+
+ channel_offset = __unioxx5_define_chan_offset(channel);
+ conf = usp->usp_prev_cn_val[channel_offset - 1];
+ chan_a = chan_b = 1;
+
+ /* setting channel A and channel B mask */
+ if (channel % 2 == 0) {
+ chan_a <<= channel & 0x07;
+ chan_b <<= (channel + 1) & 0x07;
+ } else {
+ chan_a <<= (channel - 1) & 0x07;
+ chan_b <<= channel & 0x07;
+ }
+
+ conf |= chan_a; /* even channel ot output */
+ conf &= ~chan_b; /* odd channel to input */
+
+ outb(1, usp->usp_iobase + 0);
+ outb(conf, usp->usp_iobase + channel_offset);
+ outb(0, usp->usp_iobase + 0);
+
+ usp->usp_prev_cn_val[channel_offset - 1] = conf;
}
-module_init(unioxx5_driver_init_module);
-module_exit(unioxx5_driver_cleanup_module);
+static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp,
+ unsigned int *data, int channel, int minor)
+{
+ int channel_offset, mask = 1 << (channel & 0x07);
-static int unioxx5_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+ channel_offset = __unioxx5_define_chan_offset(channel);
+ if (channel_offset < 0) {
+ printk(KERN_ERR
+ "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
+ minor, channel);
+ return 0;
+ }
+
+ *data = inb(usp->usp_iobase + channel_offset);
+ *data &= mask;
+
+ /* correct the read value to 0 or 1 */
+ if (channel_offset > 1)
+ channel -= 2 << channel_offset;
+ *data >>= channel;
+ return 1;
+}
+
+static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp,
+ unsigned int *data, int channel, int minor)
{
- int iobase, i, n_subd;
- int id, num, ba;
+ int module_no, read_ch;
+ char control;
- iobase = it->options[0];
+ module_no = channel / 2;
+ read_ch = channel % 2; /* depend on type of channel (A or B) */
- dev->board_name = DRIVER_NAME;
- dev->iobase = iobase;
- iobase += UNIOXX5_SUBDEV_BASE;
+ /* defining if given module can work on input */
+ if (usp->usp_module_type[module_no] & MODULE_OUTPUT_MASK) {
+ printk(KERN_ERR
+ "comedi%d: module in position %d with id 0x%02x is for output only",
+ minor, module_no, usp->usp_module_type[module_no]);
+ return 0;
+ }
- /* defining number of subdevices and getting they types (it must be 'g01') */
- for (i = n_subd = 0, ba = iobase; i < 4; i++, ba += UNIOXX5_SUBDEV_ODDS) {
- id = inb(ba + 0xE);
- num = inb(ba + 0xF);
+ __unioxx5_analog_config(usp, channel);
+ /* sends module number to card(1 .. 12) */
+ outb(module_no + 1, usp->usp_iobase + 5);
+ outb('V', usp->usp_iobase + 6); /* sends to module (V)erify command */
+ control = inb(usp->usp_iobase); /* get control register byte */
- if (id != 'g' || num != 1)
- continue;
+ /* waits while reading four bytes will be allowed */
+ while (!((control = inb(usp->usp_iobase + 0)) & Rx4CA))
+ ;
- n_subd++;
+ /* if four bytes readding error occurs - return 0(false) */
+ if ((control & Rx4CA_ERR_MASK)) {
+ printk("COMEDI: 4 bytes error\n");
+ return 0;
}
- /* unioxx5 can has from two to four subdevices */
- if (n_subd < 2) {
+ if (read_ch)
+ *data = inw(usp->usp_iobase + 6); /* channel B */
+ else
+ *data = inw(usp->usp_iobase + 4); /* channel A */
+
+ return 1;
+}
+
+static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp,
+ unsigned int *data, int channel, int minor)
+{
+ int channel_offset, val;
+ int mask = 1 << (channel & 0x07);
+
+ channel_offset = __unioxx5_define_chan_offset(channel);
+ if (channel_offset < 0) {
printk(KERN_ERR
- "your card must has at least 2 'g01' subdevices\n");
- return -1;
+ "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
+ minor, channel);
+ return 0;
}
- if (alloc_subdevices(dev, n_subd) < 0) {
- printk(KERN_ERR "out of memory\n");
- return -ENOMEM;
+ /* getting previous written value */
+ val = usp->usp_prev_wr_val[channel_offset - 1];
+
+ if (*data)
+ val |= mask;
+ else
+ val &= ~mask;
+
+ outb(val, usp->usp_iobase + channel_offset);
+ /* saving new written value */
+ usp->usp_prev_wr_val[channel_offset - 1] = val;
+
+ return 1;
+}
+
+static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp,
+ unsigned int *data, int channel, int minor)
+{
+ int module, i;
+
+ module = channel / 2; /* definig module number(0 .. 11) */
+ i = (channel % 2) << 1; /* depends on type of channel (A or B) */
+
+ /* defining if given module can work on output */
+ if (!(usp->usp_module_type[module] & MODULE_OUTPUT_MASK)) {
+ printk(KERN_ERR
+ "comedi%d: module in position %d with id 0x%0x is for input only!\n",
+ minor, module, usp->usp_module_type[module]);
+ return 0;
}
- /* initializing each of for same subdevices */
- for (i = 0; i < n_subd; i++, iobase += UNIOXX5_SUBDEV_ODDS) {
- if (__unioxx5_subdev_init(&dev->subdevices[i], iobase,
- dev->minor) < 0)
- return -1;
+ __unioxx5_analog_config(usp, channel);
+ /* saving minor byte */
+ usp->usp_extra_data[module][i++] = (unsigned char)(*data & 0x00FF);
+ /* saving major byte */
+ usp->usp_extra_data[module][i] = (unsigned char)((*data & 0xFF00) >> 8);
+
+ /* while(!((inb(usp->usp_iobase + 0)) & TxBE)); */
+ /* sending module number to card(1 .. 12) */
+ outb(module + 1, usp->usp_iobase + 5);
+ outb('W', usp->usp_iobase + 6); /* sends (W)rite command to module */
+
+ /* sending for bytes to module(one byte per cycle iteration) */
+ for (i = 0; i < 4; i++) {
+ while (!((inb(usp->usp_iobase + 0)) & TxBE))
+ ; /* waits while writting will be allowed */
+ outb(usp->usp_extra_data[module][i], usp->usp_iobase + 6);
}
- printk(KERN_INFO "attached\n");
- return 0;
+ return 1;
}
static int unioxx5_subdev_read(struct comedi_device *dev,
@@ -275,22 +367,6 @@ static int unioxx5_insn_config(struct comedi_device *dev,
return 0;
}
-static int unioxx5_detach(struct comedi_device *dev)
-{
- int i;
- struct comedi_subdevice *subdev;
- struct unioxx5_subd_priv *usp;
-
- for (i = 0; i < dev->n_subdevices; i++) {
- subdev = &dev->subdevices[i];
- usp = subdev->private;
- release_region(usp->usp_iobase, UNIOXX5_SIZE);
- kfree(subdev->private);
- }
-
- return 0;
-}
-
/* initializing subdevice with given address */
static int __unioxx5_subdev_init(struct comedi_subdevice *subdev,
int subdev_iobase, int minor)
@@ -362,196 +438,73 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev,
return 0;
}
-static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp,
- unsigned int *data, int channel, int minor)
+static int unioxx5_attach(struct comedi_device *dev,
+ struct comedi_devconfig *it)
{
- int channel_offset, val;
- int mask = 1 << (channel & 0x07);
-
- channel_offset = __unioxx5_define_chan_offset(channel);
- if (channel_offset < 0) {
- printk(KERN_ERR
- "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
- minor, channel);
- return 0;
- }
-
- /* getting previous written value */
- val = usp->usp_prev_wr_val[channel_offset - 1];
+ int iobase, i, n_subd;
+ int id, num, ba;
- if (*data)
- val |= mask;
- else
- val &= ~mask;
+ iobase = it->options[0];
- outb(val, usp->usp_iobase + channel_offset);
- /* saving new written value */
- usp->usp_prev_wr_val[channel_offset - 1] = val;
+ dev->board_name = DRIVER_NAME;
+ dev->iobase = iobase;
+ iobase += UNIOXX5_SUBDEV_BASE;
- return 1;
-}
+ /* defining number of subdevices and getting they types (it must be 'g01') */
+ for (i = n_subd = 0, ba = iobase; i < 4; i++, ba += UNIOXX5_SUBDEV_ODDS) {
+ id = inb(ba + 0xE);
+ num = inb(ba + 0xF);
-/* function for digital reading */
-static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp,
- unsigned int *data, int channel, int minor)
-{
- int channel_offset, mask = 1 << (channel & 0x07);
+ if (id != 'g' || num != 1)
+ continue;
- channel_offset = __unioxx5_define_chan_offset(channel);
- if (channel_offset < 0) {
- printk(KERN_ERR
- "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
- minor, channel);
- return 0;
+ n_subd++;
}
- *data = inb(usp->usp_iobase + channel_offset);
- *data &= mask;
-
- if (channel_offset > 1)
- channel -= 2 << channel_offset; /* this operation is created for correct readed value to 0 or 1 */
- *data >>= channel;
- return 1;
-}
-
-#if 0 /* not used? */
-static void __unioxx5_digital_config(struct unioxx5_subd_priv *usp, int mode)
-{
- int i, mask;
-
- mask = (mode == ALL_2_OUTPUT) ? 0xFF : 0x00;
- printk("COMEDI: mode = %d\n", mask);
-
- outb(1, usp->usp_iobase + 0);
-
- for (i = 0; i < 3; i++)
- outb(mask, usp->usp_iobase + i);
-
- outb(0, usp->usp_iobase + 0);
-}
-#endif
-
-static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp,
- unsigned int *data, int channel, int minor)
-{
- int module, i;
-
- module = channel / 2; /* definig module number(0 .. 11) */
- i = (channel % 2) << 1; /* depends on type of channel (A or B) */
-
- /* defining if given module can work on output */
- if (!(usp->usp_module_type[module] & MODULE_OUTPUT_MASK)) {
+ /* unioxx5 can has from two to four subdevices */
+ if (n_subd < 2) {
printk(KERN_ERR
- "comedi%d: module in position %d with id 0x%0x is for input only!\n",
- minor, module, usp->usp_module_type[module]);
- return 0;
- }
-
- __unioxx5_analog_config(usp, channel);
- /* saving minor byte */
- usp->usp_extra_data[module][i++] = (unsigned char)(*data & 0x00FF);
- /* saving major byte */
- usp->usp_extra_data[module][i] = (unsigned char)((*data & 0xFF00) >> 8);
-
- /* while(!((inb(usp->usp_iobase + 0)) & TxBE)); */
- /* sending module number to card(1 .. 12) */
- outb(module + 1, usp->usp_iobase + 5);
- outb('W', usp->usp_iobase + 6); /* sends (W)rite command to module */
-
- /* sending for bytes to module(one byte per cycle iteration) */
- for (i = 0; i < 4; i++) {
- while (!((inb(usp->usp_iobase + 0)) & TxBE))
- ; /* waits while writting will be allowed */
- outb(usp->usp_extra_data[module][i], usp->usp_iobase + 6);
+ "your card must has at least 2 'g01' subdevices\n");
+ return -1;
}
- return 1;
-}
-
-static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp,
- unsigned int *data, int channel, int minor)
-{
- int module_no, read_ch;
- char control;
-
- module_no = channel / 2;
- read_ch = channel % 2; /* depend on type of channel (A or B) */
-
- /* defining if given module can work on input */
- if (usp->usp_module_type[module_no] & MODULE_OUTPUT_MASK) {
- printk(KERN_ERR
- "comedi%d: module in position %d with id 0x%02x is for output only",
- minor, module_no, usp->usp_module_type[module_no]);
- return 0;
+ if (alloc_subdevices(dev, n_subd) < 0) {
+ printk(KERN_ERR "out of memory\n");
+ return -ENOMEM;
}
- __unioxx5_analog_config(usp, channel);
- /* sends module number to card(1 .. 12) */
- outb(module_no + 1, usp->usp_iobase + 5);
- outb('V', usp->usp_iobase + 6); /* sends to module (V)erify command */
- control = inb(usp->usp_iobase); /* get control register byte */
-
- /* waits while reading four bytes will be allowed */
- while (!((control = inb(usp->usp_iobase + 0)) & Rx4CA))
- ;
-
- /* if four bytes readding error occurs - return 0(false) */
- if ((control & Rx4CA_ERR_MASK)) {
- printk("COMEDI: 4 bytes error\n");
- return 0;
+ /* initializing each of for same subdevices */
+ for (i = 0; i < n_subd; i++, iobase += UNIOXX5_SUBDEV_ODDS) {
+ if (__unioxx5_subdev_init(&dev->subdevices[i], iobase,
+ dev->minor) < 0)
+ return -1;
}
- if (read_ch)
- *data = inw(usp->usp_iobase + 6); /* channel B */
- else
- *data = inw(usp->usp_iobase + 4); /* channel A */
-
- return 1;
+ printk(KERN_INFO "attached\n");
+ return 0;
}
-/* configure channels for analog i/o (even to output, odd to input) */
-static void __unioxx5_analog_config(struct unioxx5_subd_priv *usp, int channel)
+static void unioxx5_detach(struct comedi_device *dev)
{
- int chan_a, chan_b, conf, channel_offset;
-
- channel_offset = __unioxx5_define_chan_offset(channel);
- conf = usp->usp_prev_cn_val[channel_offset - 1];
- chan_a = chan_b = 1;
+ int i;
+ struct comedi_subdevice *subdev;
+ struct unioxx5_subd_priv *usp;
- /* setting channel A and channel B mask */
- if (channel % 2 == 0) {
- chan_a <<= channel & 0x07;
- chan_b <<= (channel + 1) & 0x07;
- } else {
- chan_a <<= (channel - 1) & 0x07;
- chan_b <<= channel & 0x07;
+ for (i = 0; i < dev->n_subdevices; i++) {
+ subdev = &dev->subdevices[i];
+ usp = subdev->private;
+ release_region(usp->usp_iobase, UNIOXX5_SIZE);
+ kfree(subdev->private);
}
-
- conf |= chan_a; /* even channel ot output */
- conf &= ~chan_b; /* odd channel to input */
-
- outb(1, usp->usp_iobase + 0);
- outb(conf, usp->usp_iobase + channel_offset);
- outb(0, usp->usp_iobase + 0);
-
- usp->usp_prev_cn_val[channel_offset - 1] = conf;
}
-/* *\
- * this function defines if the given channel number *
- * enters in default numeric interspace(from 0 to 23) *
- * and it returns address offset for usage needed *
- * channel. *
-\* */
-
-static int __unioxx5_define_chan_offset(int chan_num)
-{
-
- if (chan_num < 0 || chan_num > 23)
- return -1;
-
- return (chan_num >> 3) + 1;
-}
+static struct comedi_driver unioxx5_driver = {
+ .driver_name = DRIVER_NAME,
+ .module = THIS_MODULE,
+ .attach = unioxx5_attach,
+ .detach = unioxx5_detach,
+};
+module_comedi_driver(unioxx5_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index bf62e0dd6f69..13d9fd3efcfd 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -317,6 +317,8 @@ static struct usbduxsub usbduxsub[NUMUSBDUX];
static DEFINE_SEMAPHORE(start_stop_sem);
+static struct comedi_driver driver_usbdux; /* see below for initializer */
+
/*
* Stops the data acquision
* It should be safe to call this function from any context
@@ -2304,11 +2306,11 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
void *context)
{
struct usbduxsub *usbduxsub_tmp = context;
- struct usb_device *usbdev = usbduxsub_tmp->usbdev;
+ struct usb_interface *uinterf = usbduxsub_tmp->interface;
int ret;
if (fw == NULL) {
- dev_err(&usbdev->dev,
+ dev_err(&uinterf->dev,
"Firmware complete handler without firmware!\n");
return;
}
@@ -2320,11 +2322,11 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
ret = firmwareUpload(usbduxsub_tmp, fw->data, fw->size);
if (ret) {
- dev_err(&usbdev->dev,
+ dev_err(&uinterf->dev,
"Could not upload firmware (err=%d)\n", ret);
goto out;
}
- comedi_usb_auto_config(usbdev, BOARDNAME);
+ comedi_usb_auto_config(uinterf, &driver_usbdux);
out:
release_firmware(fw);
}
@@ -2606,7 +2608,7 @@ static void usbduxsub_disconnect(struct usb_interface *intf)
dev_err(&intf->dev, "comedi_: BUG! called with wrong ptr!!!\n");
return;
}
- comedi_usb_auto_unconfig(udev);
+ comedi_usb_auto_unconfig(intf);
down(&start_stop_sem);
down(&usbduxsub_tmp->sem);
tidy_up(usbduxsub_tmp);
@@ -2615,46 +2617,21 @@ static void usbduxsub_disconnect(struct usb_interface *intf)
dev_dbg(&intf->dev, "comedi_: disconnected from the usb\n");
}
-/* is called when comedi-config is called */
-static int usbdux_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+/* common part of attach and attach_usb */
+static int usbdux_attach_common(struct comedi_device *dev,
+ struct usbduxsub *udev,
+ void *aux_data, int aux_len)
{
int ret;
- int index;
- int i;
- struct usbduxsub *udev;
-
struct comedi_subdevice *s = NULL;
- dev->private = NULL;
-
- down(&start_stop_sem);
- /* find a valid device which has been detected by the probe function of
- * the usb */
- index = -1;
- for (i = 0; i < NUMUSBDUX; i++) {
- if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) {
- index = i;
- break;
- }
- }
- if (index < 0) {
- printk(KERN_ERR "comedi%d: usbdux: error: attach failed, no "
- "usbdux devs connected to the usb bus.\n", dev->minor);
- up(&start_stop_sem);
- return -ENODEV;
- }
-
- udev = &usbduxsub[index];
down(&udev->sem);
/* pointer back to the corresponding comedi device */
udev->comedidev = dev;
/* trying to upload the firmware into the chip */
- if (comedi_aux_data(it->options, 0) &&
- it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
- firmwareUpload(udev, comedi_aux_data(it->options, 0),
- it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]);
- }
+ if (aux_data)
+ firmwareUpload(udev, aux_data, aux_len);
dev->board_name = BOARDNAME;
@@ -2673,13 +2650,9 @@ static int usbdux_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev_err(&udev->interface->dev,
"comedi%d: error alloc space for subdev\n", dev->minor);
up(&udev->sem);
- up(&start_stop_sem);
return ret;
}
- dev_info(&udev->interface->dev,
- "comedi%d: usb-device %d is attached to comedi.\n",
- dev->minor, index);
/* private structure is also simply the usb-structure */
dev->private = udev;
@@ -2776,44 +2749,91 @@ static int usbdux_attach(struct comedi_device *dev, struct comedi_devconfig *it)
up(&udev->sem);
- up(&start_stop_sem);
-
dev_info(&udev->interface->dev, "comedi%d: attached to usbdux.\n",
dev->minor);
return 0;
}
-static int usbdux_detach(struct comedi_device *dev)
+/* is called when comedi-config is called */
+static int usbdux_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
- struct usbduxsub *usbduxsub_tmp;
+ int ret;
+ int index;
+ int i;
+ void *aux_data;
+ int aux_len;
- if (!dev) {
- printk(KERN_ERR
- "comedi?: usbdux: detach without dev variable...\n");
- return -EFAULT;
+ dev->private = NULL;
+
+ aux_data = comedi_aux_data(it->options, 0);
+ aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
+ if (aux_data == NULL)
+ aux_len = 0;
+ else if (aux_len == 0)
+ aux_data = NULL;
+
+ down(&start_stop_sem);
+ /* find a valid device which has been detected by the probe function of
+ * the usb */
+ index = -1;
+ for (i = 0; i < NUMUSBDUX; i++) {
+ if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) {
+ index = i;
+ break;
+ }
}
- usbduxsub_tmp = dev->private;
- if (!usbduxsub_tmp) {
+ if (index < 0) {
printk(KERN_ERR
- "comedi?: usbdux: detach without ptr to usbduxsub[]\n");
- return -EFAULT;
- }
+ "comedi%d: usbdux: error: attach failed, no usbdux devs connected to the usb bus.\n",
+ dev->minor);
+ ret = -ENODEV;
+ } else
+ ret = usbdux_attach_common(dev, &usbduxsub[index],
+ aux_data, aux_len);
+ up(&start_stop_sem);
+ return ret;
+}
- dev_dbg(&usbduxsub_tmp->interface->dev, "comedi%d: detach usb device\n",
- dev->minor);
+/* is called from comedi_usb_auto_config() */
+static int usbdux_attach_usb(struct comedi_device *dev,
+ struct usb_interface *uinterf)
+{
+ int ret;
+ struct usbduxsub *this_usbduxsub;
- down(&usbduxsub_tmp->sem);
- /* Don't allow detach to free the private structure */
- /* It's one entry of of usbduxsub[] */
dev->private = NULL;
- usbduxsub_tmp->attached = 0;
- usbduxsub_tmp->comedidev = NULL;
- dev_dbg(&usbduxsub_tmp->interface->dev,
- "comedi%d: detach: successfully removed\n", dev->minor);
- up(&usbduxsub_tmp->sem);
- return 0;
+
+ down(&start_stop_sem);
+ this_usbduxsub = usb_get_intfdata(uinterf);
+ if (!this_usbduxsub || !this_usbduxsub->probed) {
+ printk(KERN_ERR
+ "comedi%d: usbdux: error: attach_usb failed, not connected\n",
+ dev->minor);
+ ret = -ENODEV;
+ } else if (this_usbduxsub->attached) {
+ printk(KERN_ERR
+ "comedi%d: usbdux: error: attach_usb failed, already attached\n",
+ dev->minor);
+ ret = -ENODEV;
+ } else
+ ret = usbdux_attach_common(dev, this_usbduxsub, NULL, 0);
+ up(&start_stop_sem);
+ return ret;
+}
+
+static void usbdux_detach(struct comedi_device *dev)
+{
+ struct usbduxsub *usb = dev->private;
+
+ if (usb) {
+ down(&usb->sem);
+ dev->private = NULL;
+ usb->attached = 0;
+ usb->comedidev = NULL;
+ up(&usb->sem);
+ }
}
/* main driver struct */
@@ -2822,6 +2842,7 @@ static struct comedi_driver driver_usbdux = {
.module = THIS_MODULE,
.attach = usbdux_attach,
.detach = usbdux_detach,
+ .attach_usb = usbdux_attach_usb,
};
/* Table with the USB-devices: just now only testing IDs */
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
index 2a8e725b7859..7b1d21a6fc53 100644
--- a/drivers/staging/comedi/drivers/usbduxfast.c
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -201,6 +201,8 @@ static struct usbduxfastsub_s usbduxfastsub[NUMUSBDUXFAST];
static DEFINE_SEMAPHORE(start_stop_sem);
+static struct comedi_driver driver_usbduxfast; /* see below for initializer */
+
/*
* bulk transfers to usbduxfast
*/
@@ -453,14 +455,15 @@ static int usbduxfastsub_start(struct usbduxfastsub_s *udfs)
/* 7f92 to zero */
local_transfer_buffer[0] = 0;
/* bRequest, "Firmware" */
- ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), USBDUXFASTSUB_FIRMWARE,
- VENDOR_DIR_OUT, /* bmRequestType */
- USBDUXFASTSUB_CPUCS, /* Value */
- 0x0000, /* Index */
- /* address of the transfer buffer */
- local_transfer_buffer,
- 1, /* Length */
- EZTIMEOUT); /* Timeout */
+ ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0),
+ USBDUXFASTSUB_FIRMWARE,
+ VENDOR_DIR_OUT, /* bmRequestType */
+ USBDUXFASTSUB_CPUCS, /* Value */
+ 0x0000, /* Index */
+ /* address of the transfer buffer */
+ local_transfer_buffer,
+ 1, /* Length */
+ EZTIMEOUT); /* Timeout */
if (ret < 0) {
printk("comedi_: usbduxfast_: control msg failed (start)\n");
return ret;
@@ -477,7 +480,8 @@ static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs)
/* 7f92 to one */
local_transfer_buffer[0] = 1;
/* bRequest, "Firmware" */
- ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), USBDUXFASTSUB_FIRMWARE,
+ ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0),
+ USBDUXFASTSUB_FIRMWARE,
VENDOR_DIR_OUT, /* bmRequestType */
USBDUXFASTSUB_CPUCS, /* Value */
0x0000, /* Index */
@@ -504,14 +508,15 @@ static int usbduxfastsub_upload(struct usbduxfastsub_s *udfs,
startAddr, local_transfer_buffer[0]);
#endif
/* brequest, firmware */
- ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), USBDUXFASTSUB_FIRMWARE,
- VENDOR_DIR_OUT, /* bmRequestType */
- startAddr, /* value */
- 0x0000, /* index */
- /* our local safe buffer */
- local_transfer_buffer,
- len, /* length */
- EZTIMEOUT); /* timeout */
+ ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0),
+ USBDUXFASTSUB_FIRMWARE,
+ VENDOR_DIR_OUT, /* bmRequestType */
+ startAddr, /* value */
+ 0x0000, /* index */
+ /* our local safe buffer */
+ local_transfer_buffer,
+ len, /* length */
+ EZTIMEOUT); /* timeout */
#ifdef CONFIG_COMEDI_DEBUG
printk(KERN_DEBUG "comedi_: usbduxfast: result=%d\n", ret);
@@ -1440,7 +1445,7 @@ static void usbduxfast_firmware_request_complete_handler(const struct firmware
*fw, void *context)
{
struct usbduxfastsub_s *usbduxfastsub_tmp = context;
- struct usb_device *usbdev = usbduxfastsub_tmp->usbdev;
+ struct usb_interface *uinterf = usbduxfastsub_tmp->interface;
int ret;
if (fw == NULL)
@@ -1453,12 +1458,12 @@ static void usbduxfast_firmware_request_complete_handler(const struct firmware
ret = firmwareUpload(usbduxfastsub_tmp, fw->data, fw->size);
if (ret) {
- dev_err(&usbdev->dev,
+ dev_err(&uinterf->dev,
"Could not upload firmware (err=%d)\n", ret);
goto out;
}
- comedi_usb_auto_config(usbdev, BOARDNAME);
+ comedi_usb_auto_config(uinterf, &driver_usbduxfast);
out:
release_firmware(fw);
}
@@ -1606,7 +1611,7 @@ static void usbduxfastsub_disconnect(struct usb_interface *intf)
return;
}
- comedi_usb_auto_unconfig(udev);
+ comedi_usb_auto_unconfig(intf);
down(&start_stop_sem);
down(&udfs->sem);
@@ -1721,43 +1726,19 @@ static int usbduxfast_attach(struct comedi_device *dev,
return 0;
}
-static int usbduxfast_detach(struct comedi_device *dev)
+static void usbduxfast_detach(struct comedi_device *dev)
{
- struct usbduxfastsub_s *udfs;
-
- if (!dev) {
- printk(KERN_ERR "comedi?: usbduxfast: detach without dev "
- "variable...\n");
- return -EFAULT;
- }
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi%d: usbduxfast: detach usb device\n",
- dev->minor);
-#endif
-
- udfs = dev->private;
- if (!udfs) {
- printk(KERN_ERR "comedi?: usbduxfast: detach without ptr to "
- "usbduxfastsub[]\n");
- return -EFAULT;
+ struct usbduxfastsub_s *usb = dev->private;
+
+ if (usb) {
+ down(&usb->sem);
+ down(&start_stop_sem);
+ dev->private = NULL;
+ usb->attached = 0;
+ usb->comedidev = NULL;
+ up(&start_stop_sem);
+ up(&usb->sem);
}
-
- down(&udfs->sem);
- down(&start_stop_sem);
- /*
- * Don't allow detach to free the private structure
- * It's one entry of of usbduxfastsub[]
- */
- dev->private = NULL;
- udfs->attached = 0;
- udfs->comedidev = NULL;
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi%d: usbduxfast: detach: successfully "
- "removed\n", dev->minor);
-#endif
- up(&start_stop_sem);
- up(&udfs->sem);
- return 0;
}
/*
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c
index 63c9b6dbc317..465afbdf4069 100644
--- a/drivers/staging/comedi/drivers/usbduxsigma.c
+++ b/drivers/staging/comedi/drivers/usbduxsigma.c
@@ -267,6 +267,8 @@ static struct usbduxsub usbduxsub[NUMUSBDUX];
static DEFINE_SEMAPHORE(start_stop_sem);
+static struct comedi_driver driver_usbduxsigma; /* see below for initializer */
+
/*
* Stops the data acquision
* It should be safe to call this function from any context
@@ -2312,11 +2314,11 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
void *context)
{
struct usbduxsub *usbduxsub_tmp = context;
- struct usb_device *usbdev = usbduxsub_tmp->usbdev;
+ struct usb_interface *uinterf = usbduxsub_tmp->interface;
int ret;
if (fw == NULL) {
- dev_err(&usbdev->dev,
+ dev_err(&uinterf->dev,
"Firmware complete handler without firmware!\n");
return;
}
@@ -2328,11 +2330,11 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
ret = firmwareUpload(usbduxsub_tmp, fw->data, fw->size);
if (ret) {
- dev_err(&usbdev->dev,
+ dev_err(&uinterf->dev,
"Could not upload firmware (err=%d)\n", ret);
goto out;
}
- comedi_usb_auto_config(usbdev, BOARDNAME);
+ comedi_usb_auto_config(uinterf, &driver_usbduxsigma);
out:
release_firmware(fw);
}
@@ -2623,7 +2625,7 @@ static void usbduxsigma_disconnect(struct usb_interface *intf)
if (usbduxsub_tmp->ao_cmd_running)
/* we are still running a command */
usbdux_ao_stop(usbduxsub_tmp, 1);
- comedi_usb_auto_unconfig(udev);
+ comedi_usb_auto_unconfig(intf);
down(&start_stop_sem);
down(&usbduxsub_tmp->sem);
tidy_up(usbduxsub_tmp);
@@ -2799,37 +2801,17 @@ static int usbduxsigma_attach(struct comedi_device *dev,
return 0;
}
-static int usbduxsigma_detach(struct comedi_device *dev)
+static void usbduxsigma_detach(struct comedi_device *dev)
{
- struct usbduxsub *usbduxsub_tmp;
+ struct usbduxsub *usb = dev->private;
- if (!dev) {
- printk(KERN_ERR
- "comedi? usbduxsigma detach: dev=NULL\n");
- return -EFAULT;
+ if (usb) {
+ down(&usb->sem);
+ dev->private = NULL;
+ usb->attached = 0;
+ usb->comedidev = NULL;
+ up(&usb->sem);
}
-
- usbduxsub_tmp = dev->private;
- if (!usbduxsub_tmp) {
- printk(KERN_ERR
- "comedi?: usbduxsigma detach: private=NULL\n");
- return -EFAULT;
- }
-
- dev_dbg(&usbduxsub_tmp->interface->dev,
- "comedi%d: detach usb device\n",
- dev->minor);
-
- down(&usbduxsub_tmp->sem);
- /* Don't allow detach to free the private structure */
- /* It's one entry of of usbduxsub[] */
- dev->private = NULL;
- usbduxsub_tmp->attached = 0;
- usbduxsub_tmp->comedidev = NULL;
- dev_info(&usbduxsub_tmp->interface->dev,
- "comedi%d: successfully detached.\n", dev->minor);
- up(&usbduxsub_tmp->sem);
- return 0;
}
/* main driver struct */
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
index 3d13ca6e1670..baee8d767636 100644
--- a/drivers/staging/comedi/drivers/vmk80xx.c
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
@@ -151,27 +151,12 @@ MODULE_DEVICE_TABLE(usb, vmk80xx_id_table);
#define URB_RCV_FLAG (1 << 0)
#define URB_SND_FLAG (1 << 1)
-#define CONFIG_VMK80XX_DEBUG
-#undef CONFIG_VMK80XX_DEBUG
-
-#ifdef CONFIG_VMK80XX_DEBUG
-static int dbgvm = 1;
-#else
-static int dbgvm;
-#endif
-
#ifdef CONFIG_COMEDI_DEBUG
static int dbgcm = 1;
#else
static int dbgcm;
#endif
-#define dbgvm(fmt, arg...) \
-do { \
- if (dbgvm) \
- printk(KERN_DEBUG fmt, ##arg); \
-} while (0)
-
#define dbgcm(fmt, arg...) \
do { \
if (dbgcm) \
@@ -247,13 +232,13 @@ static struct vmk80xx_usb vmb[VMK80XX_MAX_BOARDS];
static DEFINE_MUTEX(glb_mutex);
+static struct comedi_driver driver_vmk80xx; /* see below for initializer */
+
static void vmk80xx_tx_callback(struct urb *urb)
{
struct vmk80xx_usb *dev = urb->context;
int stat = urb->status;
- dbgvm("vmk80xx: %s\n", __func__);
-
if (stat && !(stat == -ENOENT
|| stat == -ECONNRESET || stat == -ESHUTDOWN))
dbgcm("comedi#: vmk80xx: %s - nonzero urb status (%d)\n",
@@ -272,8 +257,6 @@ static void vmk80xx_rx_callback(struct urb *urb)
struct vmk80xx_usb *dev = urb->context;
int stat = urb->status;
- dbgvm("vmk80xx: %s\n", __func__);
-
switch (stat) {
case 0:
break;
@@ -295,7 +278,9 @@ resubmit:
if (!usb_submit_urb(urb, GFP_KERNEL))
goto exit;
- err("comedi#: vmk80xx: %s - submit urb failed\n", __func__);
+ dev_err(&urb->dev->dev,
+ "comedi#: vmk80xx: %s - submit urb failed\n",
+ __func__);
usb_unanchor_urb(urb);
}
@@ -312,8 +297,6 @@ static int vmk80xx_check_data_link(struct vmk80xx_usb *dev)
unsigned char tx[1];
unsigned char rx[2];
- dbgvm("vmk80xx: %s\n", __func__);
-
tx_pipe = usb_sndbulkpipe(dev->udev, 0x01);
rx_pipe = usb_rcvbulkpipe(dev->udev, 0x81);
@@ -338,8 +321,6 @@ static void vmk80xx_read_eeprom(struct vmk80xx_usb *dev, int flag)
unsigned char rx[64];
int cnt;
- dbgvm("vmk80xx: %s\n", __func__);
-
tx_pipe = usb_sndbulkpipe(dev->udev, 0x01);
rx_pipe = usb_rcvbulkpipe(dev->udev, 0x81);
@@ -367,8 +348,6 @@ static int vmk80xx_reset_device(struct vmk80xx_usb *dev)
int ival;
size_t size;
- dbgvm("vmk80xx: %s\n", __func__);
-
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return -ENOMEM;
@@ -406,8 +385,6 @@ static void vmk80xx_build_int_urb(struct urb *urb, int flag)
void (*callback) (struct urb *);
int ival;
- dbgvm("vmk80xx: %s\n", __func__);
-
if (flag & URB_RCV_FLAG) {
rx_addr = dev->ep_rx->bEndpointAddress;
pipe = usb_rcvintpipe(dev->udev, rx_addr);
@@ -435,8 +412,6 @@ static void vmk80xx_do_bulk_msg(struct vmk80xx_usb *dev)
unsigned int rx_pipe;
size_t size;
- dbgvm("vmk80xx: %s\n", __func__);
-
set_bit(TRANS_IN_BUSY, &dev->flags);
set_bit(TRANS_OUT_BUSY, &dev->flags);
@@ -464,8 +439,6 @@ static int vmk80xx_read_packet(struct vmk80xx_usb *dev)
struct urb *urb;
int retval;
- dbgvm("vmk80xx: %s\n", __func__);
-
if (!dev->intf)
return -ENODEV;
@@ -512,8 +485,6 @@ static int vmk80xx_write_packet(struct vmk80xx_usb *dev, int cmd)
struct urb *urb;
int retval;
- dbgvm("vmk80xx: %s\n", __func__);
-
if (!dev->intf)
return -ENODEV;
@@ -588,8 +559,6 @@ static int vmk80xx_ai_rinsn(struct comedi_device *cdev,
int reg[2];
int n;
- dbgvm("vmk80xx: %s\n", __func__);
-
n = rudimentary_check(dev, DIR_IN);
if (n)
return n;
@@ -641,8 +610,6 @@ static int vmk80xx_ao_winsn(struct comedi_device *cdev,
int reg;
int n;
- dbgvm("vmk80xx: %s\n", __func__);
-
n = rudimentary_check(dev, DIR_OUT);
if (n)
return n;
@@ -686,8 +653,6 @@ static int vmk80xx_ao_rinsn(struct comedi_device *cdev,
int reg;
int n;
- dbgvm("vmk80xx: %s\n", __func__);
-
n = rudimentary_check(dev, DIR_IN);
if (n)
return n;
@@ -720,8 +685,6 @@ static int vmk80xx_di_bits(struct comedi_device *cdev,
int reg;
int retval;
- dbgvm("vmk80xx: %s\n", __func__);
-
retval = rudimentary_check(dev, DIR_IN);
if (retval)
return retval;
@@ -766,8 +729,6 @@ static int vmk80xx_di_rinsn(struct comedi_device *cdev,
int inp;
int n;
- dbgvm("vmk80xx: %s\n", __func__);
-
n = rudimentary_check(dev, DIR_IN);
if (n)
return n;
@@ -813,8 +774,6 @@ static int vmk80xx_do_winsn(struct comedi_device *cdev,
int cmd;
int n;
- dbgvm("vmk80xx: %s\n", __func__);
-
n = rudimentary_check(dev, DIR_OUT);
if (n)
return n;
@@ -861,8 +820,6 @@ static int vmk80xx_do_rinsn(struct comedi_device *cdev,
int reg;
int n;
- dbgvm("vmk80xx: %s\n", __func__);
-
n = rudimentary_check(dev, DIR_IN);
if (n)
return n;
@@ -895,8 +852,6 @@ static int vmk80xx_do_bits(struct comedi_device *cdev,
int dir, reg, cmd;
int retval;
- dbgvm("vmk80xx: %s\n", __func__);
-
dir = 0;
if (data[0])
@@ -962,8 +917,6 @@ static int vmk80xx_cnt_rinsn(struct comedi_device *cdev,
int reg[2];
int n;
- dbgvm("vmk80xx: %s\n", __func__);
-
n = rudimentary_check(dev, DIR_IN);
if (n)
return n;
@@ -1012,18 +965,16 @@ static int vmk80xx_cnt_cinsn(struct comedi_device *cdev,
int reg;
int n;
- dbgvm("vmk80xx: %s\n", __func__);
-
n = rudimentary_check(dev, DIR_OUT);
if (n)
return n;
- down(&dev->limit_sem);
-
insn_cmd = data[0];
if (insn_cmd != INSN_CONFIG_RESET && insn_cmd != GPCT_RESET)
return -EINVAL;
+ down(&dev->limit_sem);
+
chan = CR_CHAN(insn->chanspec);
if (dev->board.model == VMK8055_MODEL) {
@@ -1060,8 +1011,6 @@ static int vmk80xx_cnt_winsn(struct comedi_device *cdev,
int cmd;
int n;
- dbgvm("vmk80xx: %s\n", __func__);
-
n = rudimentary_check(dev, DIR_OUT);
if (n)
return n;
@@ -1106,8 +1055,6 @@ static int vmk80xx_pwm_rinsn(struct comedi_device *cdev,
int reg[2];
int n;
- dbgvm("vmk80xx: %s\n", __func__);
-
n = rudimentary_check(dev, DIR_IN);
if (n)
return n;
@@ -1141,8 +1088,6 @@ static int vmk80xx_pwm_winsn(struct comedi_device *cdev,
int cmd;
int n;
- dbgvm("vmk80xx: %s\n", __func__);
-
n = rudimentary_check(dev, DIR_OUT);
if (n)
return n;
@@ -1191,8 +1136,6 @@ static int vmk80xx_attach(struct comedi_device *cdev,
struct comedi_subdevice *s;
int minor;
- dbgvm("vmk80xx: %s\n", __func__);
-
mutex_lock(&glb_mutex);
for (i = 0; i < VMK80XX_MAX_BOARDS; i++)
@@ -1307,34 +1250,16 @@ static int vmk80xx_attach(struct comedi_device *cdev,
return 0;
}
-static int vmk80xx_detach(struct comedi_device *cdev)
+static void vmk80xx_detach(struct comedi_device *dev)
{
- struct vmk80xx_usb *dev;
- int minor;
-
- dbgvm("vmk80xx: %s\n", __func__);
-
- if (!cdev)
- return -EFAULT;
-
- dev = cdev->private;
- if (!dev)
- return -EFAULT;
+ struct vmk80xx_usb *usb = dev->private;
- down(&dev->limit_sem);
-
- cdev->private = NULL;
- dev->attached = 0;
-
- minor = cdev->minor;
-
- printk(KERN_INFO
- "comedi%d: vmk80xx: board #%d [%s] detached from comedi\n",
- minor, dev->count, dev->board.name);
-
- up(&dev->limit_sem);
-
- return 0;
+ if (usb) {
+ down(&usb->limit_sem);
+ dev->private = NULL;
+ usb->attached = 0;
+ up(&usb->limit_sem);
+ }
}
static int vmk80xx_probe(struct usb_interface *intf,
@@ -1346,8 +1271,6 @@ static int vmk80xx_probe(struct usb_interface *intf,
struct usb_endpoint_descriptor *ep_desc;
size_t size;
- dbgvm("vmk80xx: %s\n", __func__);
-
mutex_lock(&glb_mutex);
for (i = 0; i < VMK80XX_MAX_BOARDS; i++)
@@ -1482,7 +1405,7 @@ static int vmk80xx_probe(struct usb_interface *intf,
mutex_unlock(&glb_mutex);
- comedi_usb_auto_config(dev->udev, BOARDNAME);
+ comedi_usb_auto_config(intf, &driver_vmk80xx);
return 0;
error:
@@ -1495,12 +1418,10 @@ static void vmk80xx_disconnect(struct usb_interface *intf)
{
struct vmk80xx_usb *dev = usb_get_intfdata(intf);
- dbgvm("vmk80xx: %s\n", __func__);
-
if (!dev)
return;
- comedi_usb_auto_unconfig(dev->udev);
+ comedi_usb_auto_unconfig(intf);
mutex_lock(&glb_mutex);
down(&dev->limit_sem);
diff --git a/drivers/staging/comedi/internal.h b/drivers/staging/comedi/internal.h
index 434ce3433368..7ed20a04eef5 100644
--- a/drivers/staging/comedi/internal.h
+++ b/drivers/staging/comedi/internal.h
@@ -1,5 +1,5 @@
/*
- * various internal comedi functions
+ * various internal comedi stuff
*/
int do_rangeinfo_ioctl(struct comedi_device *dev,
struct comedi_rangeinfo __user *arg);
@@ -7,6 +7,10 @@ int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
int comedi_alloc_board_minor(struct device *hardware_device);
void comedi_free_board_minor(unsigned minor);
+int comedi_find_board_minor(struct device *hardware_device);
void comedi_reset_async_buf(struct comedi_async *async);
int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned long new_size);
+
+extern unsigned int comedi_default_buf_size_kb;
+extern unsigned int comedi_default_buf_maxsize_kb;
diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c
index 886f5650444e..5b11c5e3622e 100644
--- a/drivers/staging/et131x/et131x.c
+++ b/drivers/staging/et131x/et131x.c
@@ -1710,7 +1710,8 @@ static int et131x_mdio_read(struct mii_bus *bus, int phy_addr, int reg)
return value;
}
-static int et131x_mdio_write(struct mii_bus *bus, int phy_addr, int reg, u16 value)
+static int et131x_mdio_write(struct mii_bus *bus, int phy_addr,
+ int reg, u16 value)
{
struct net_device *netdev = bus->priv;
struct et131x_adapter *adapter = netdev_priv(netdev);
@@ -4013,7 +4014,7 @@ static int et131x_pci_init(struct et131x_adapter *adapter,
dev_err(&pdev->dev, "Missing PCIe capabilities\n");
goto err_out;
}
-
+
/* Let's set up the PORT LOGIC Register. First we need to know what
* the max_payload_size is
*/
@@ -4060,7 +4061,7 @@ static int et131x_pci_init(struct et131x_adapter *adapter,
goto err_out;
}
- ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | ( 0x04 << 12);
+ ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | (0x04 << 12);
if (pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl)) {
dev_err(&pdev->dev,
@@ -4824,7 +4825,8 @@ static int et131x_open(struct net_device *netdev)
adapter->error_timer.data = (unsigned long)adapter;
add_timer(&adapter->error_timer);
- result = request_irq(irq, et131x_isr, IRQF_SHARED, netdev->name, netdev);
+ result = request_irq(irq, et131x_isr,
+ IRQF_SHARED, netdev->name, netdev);
if (result) {
dev_err(&pdev->dev, "could not register IRQ %d\n", irq);
return result;
diff --git a/drivers/staging/frontier/alphatrack.c b/drivers/staging/frontier/alphatrack.c
index 3bf0f40e97fd..acbb2cc510f9 100644
--- a/drivers/staging/frontier/alphatrack.c
+++ b/drivers/staging/frontier/alphatrack.c
@@ -333,8 +333,8 @@ static int usb_alphatrack_open(struct inode *inode, struct file *file)
interface = usb_find_interface(&usb_alphatrack_driver, subminor);
if (!interface) {
- err("%s - error, can't find device for minor %d\n",
- __func__, subminor);
+ printk(KERN_ERR "%s - error, can't find device for minor %d\n",
+ __func__, subminor);
retval = -ENODEV;
goto unlock_disconnect_exit;
}
@@ -494,7 +494,8 @@ static ssize_t usb_alphatrack_read(struct file *file, char __user *buffer,
/* verify that the device wasn't unplugged */
if (dev->intf == NULL) {
retval = -ENODEV;
- err("No device or device unplugged %d\n", retval);
+ printk(KERN_ERR "%s: No device or device unplugged %d\n",
+ __func__, retval);
goto unlock_exit;
}
@@ -564,7 +565,8 @@ static ssize_t usb_alphatrack_write(struct file *file,
/* verify that the device wasn't unplugged */
if (dev->intf == NULL) {
retval = -ENODEV;
- err("No device or device unplugged %d\n", retval);
+ printk(KERN_ERR "%s: No device or device unplugged %d\n",
+ __func__, retval);
goto unlock_exit;
}
@@ -599,7 +601,7 @@ static ssize_t usb_alphatrack_write(struct file *file,
}
if (dev->interrupt_out_endpoint == NULL) {
- err("Endpoint should not be be null!\n");
+ dev_err(&dev->intf->dev, "Endpoint should not be be null!\n");
goto unlock_exit;
}
@@ -619,7 +621,8 @@ static ssize_t usb_alphatrack_write(struct file *file,
retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
if (retval) {
dev->interrupt_out_busy = 0;
- err("Couldn't submit interrupt_out_urb %d\n", retval);
+ dev_err(&dev->intf->dev,
+ "Couldn't submit interrupt_out_urb %d\n", retval);
atomic_dec(&dev->writes_pending);
goto unlock_exit;
}
diff --git a/drivers/staging/frontier/tranzport.c b/drivers/staging/frontier/tranzport.c
index 29e99bbcae48..376706f1c712 100644
--- a/drivers/staging/frontier/tranzport.c
+++ b/drivers/staging/frontier/tranzport.c
@@ -353,7 +353,7 @@ static int usb_tranzport_open(struct inode *inode, struct file *file)
interface = usb_find_interface(&usb_tranzport_driver, subminor);
if (!interface) {
- err("%s - error, can't find device for minor %d\n",
+ printk(KERN_ERR "%s - error, can't find device for minor %d\n",
__func__, subminor);
retval = -ENODEV;
goto unlock_disconnect_exit;
@@ -517,9 +517,11 @@ static ssize_t usb_tranzport_read(struct file *file, char __user *buffer,
goto exit;
}
- /* verify that the device wasn't unplugged */ if (dev->intf == NULL) {
+ /* verify that the device wasn't unplugged */
+ if (dev->intf == NULL) {
retval = -ENODEV;
- err("No device or device unplugged %d\n", retval);
+ printk(KERN_ERR "%s: No device or device unplugged %d\n",
+ __func__, retval);
goto unlock_exit;
}
@@ -691,7 +693,8 @@ static ssize_t usb_tranzport_write(struct file *file,
/* verify that the device wasn't unplugged */
if (dev->intf == NULL) {
retval = -ENODEV;
- err("No device or device unplugged %d\n", retval);
+ printk(KERN_ERR "%s: No device or device unplugged %d\n",
+ __func__, retval);
goto unlock_exit;
}
@@ -726,7 +729,7 @@ static ssize_t usb_tranzport_write(struct file *file,
}
if (dev->interrupt_out_endpoint == NULL) {
- err("Endpoint should not be be null!\n");
+ dev_err(&dev->intf->dev, "Endpoint should not be be null!\n");
goto unlock_exit;
}
@@ -746,7 +749,8 @@ static ssize_t usb_tranzport_write(struct file *file,
retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
if (retval) {
dev->interrupt_out_busy = 0;
- err("Couldn't submit interrupt_out_urb %d\n", retval);
+ dev_err(&dev->intf->dev,
+ "Couldn't submit interrupt_out_urb %d\n", retval);
goto unlock_exit;
}
retval = bytes_to_write;
diff --git a/drivers/staging/gdm72xx/Kconfig b/drivers/staging/gdm72xx/Kconfig
new file mode 100644
index 000000000000..3c18efe31365
--- /dev/null
+++ b/drivers/staging/gdm72xx/Kconfig
@@ -0,0 +1,46 @@
+#
+# GCT GDM72xx WiMAX driver configuration
+#
+
+menuconfig WIMAX_GDM72XX
+ tristate "GCT GDM72xx WiMAX support"
+ depends on NET
+ help
+ Support for the GCT GDM72xx WiMAX chip
+
+if WIMAX_GDM72XX
+
+config WIMAX_GDM72XX_QOS
+ bool "Enable QoS support"
+ default n
+
+config WIMAX_GDM72XX_K_MODE
+ bool "Enable K mode"
+ default n
+
+config WIMAX_GDM72XX_WIMAX2
+ bool "Enable WIMAX2 support"
+ default n
+
+choice
+ prompt "Select interface"
+
+config WIMAX_GDM72XX_USB
+ bool "USB interface"
+ depends on USB
+
+config WIMAX_GDM72XX_SDIO
+ bool "SDIO interface"
+ depends on MMC
+
+endchoice
+
+if WIMAX_GDM72XX_USB
+
+config WIMAX_GDM72XX_USB_PM
+ bool "Enable power managerment support"
+ depends on USB_SUSPEND
+
+endif # WIMAX_GDM72XX_USB
+
+endif # WIMAX_GDM72XX
diff --git a/drivers/staging/gdm72xx/Makefile b/drivers/staging/gdm72xx/Makefile
new file mode 100644
index 000000000000..35da7b90b19b
--- /dev/null
+++ b/drivers/staging/gdm72xx/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_WIMAX_GDM72XX) := gdmwm.o
+
+gdmwm-y += gdm_wimax.o netlink_k.o
+gdmwm-$(CONFIG_WIMAX_GDM72XX_QOS) += gdm_qos.o
+gdmwm-$(CONFIG_WIMAX_GDM72XX_SDIO) += gdm_sdio.o sdio_boot.o
+gdmwm-$(CONFIG_WIMAX_GDM72XX_USB) += gdm_usb.o usb_boot.o
diff --git a/drivers/staging/gdm72xx/TODO b/drivers/staging/gdm72xx/TODO
new file mode 100644
index 000000000000..30ac01ab972f
--- /dev/null
+++ b/drivers/staging/gdm72xx/TODO
@@ -0,0 +1,5 @@
+TODO:
+- Replace kernel_thread with kthread in gdm_usb.c
+- Replace hard-coded firmware paths with request_firmware in
+ sdio_boot.c and usb_boot.c
+- Clean up coding style to meet kernel standard.
diff --git a/drivers/staging/gdm72xx/gdm_qos.c b/drivers/staging/gdm72xx/gdm_qos.c
new file mode 100644
index 000000000000..0217680ec545
--- /dev/null
+++ b/drivers/staging/gdm72xx/gdm_qos.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/version.h>
+#include <linux/etherdevice.h>
+#include <asm/byteorder.h>
+
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/if_ether.h>
+
+#include "gdm_wimax.h"
+#include "hci.h"
+#include "gdm_qos.h"
+
+#define B2H(x) __be16_to_cpu(x)
+
+#undef dprintk
+#define dprintk(fmt, args ...) printk(KERN_DEBUG "[QoS] " fmt, ## args)
+#undef wprintk
+#define wprintk(fmt, args ...) \
+ printk(KERN_WARNING "[QoS WARNING] " fmt, ## args)
+#undef eprintk
+#define eprintk(fmt, args ...) printk(KERN_ERR "[QoS ERROR] " fmt, ## args)
+
+
+#define MAX_FREE_LIST_CNT 32
+static struct {
+ struct list_head head;
+ int cnt;
+ spinlock_t lock;
+} qos_free_list;
+
+static void init_qos_entry_list(void)
+{
+ qos_free_list.cnt = 0;
+ INIT_LIST_HEAD(&qos_free_list.head);
+ spin_lock_init(&qos_free_list.lock);
+}
+
+static void *alloc_qos_entry(void)
+{
+ struct qos_entry_s *entry;
+ unsigned long flags;
+
+ spin_lock_irqsave(&qos_free_list.lock, flags);
+ if (qos_free_list.cnt) {
+ entry = list_entry(qos_free_list.head.prev, struct qos_entry_s,
+ list);
+ list_del(&entry->list);
+ qos_free_list.cnt--;
+ spin_unlock_irqrestore(&qos_free_list.lock, flags);
+ return entry;
+ }
+ spin_unlock_irqrestore(&qos_free_list.lock, flags);
+
+ entry = kmalloc(sizeof(struct qos_entry_s), GFP_ATOMIC);
+ return entry;
+}
+
+static void free_qos_entry(void *entry)
+{
+ struct qos_entry_s *qentry = (struct qos_entry_s *) entry;
+ unsigned long flags;
+
+ spin_lock_irqsave(&qos_free_list.lock, flags);
+ if (qos_free_list.cnt < MAX_FREE_LIST_CNT) {
+ list_add(&qentry->list, &qos_free_list.head);
+ qos_free_list.cnt++;
+ spin_unlock_irqrestore(&qos_free_list.lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&qos_free_list.lock, flags);
+
+ kfree(entry);
+}
+
+static void free_qos_entry_list(struct list_head *free_list)
+{
+ struct qos_entry_s *entry, *n;
+ int total_free = 0;
+
+ list_for_each_entry_safe(entry, n, free_list, list) {
+ list_del(&entry->list);
+ kfree(entry);
+ total_free++;
+ }
+
+ dprintk("%s: total_free_cnt=%d\n", __func__, total_free);
+}
+
+void gdm_qos_init(void *nic_ptr)
+{
+ struct nic *nic = nic_ptr;
+ struct qos_cb_s *qcb = &nic->qos;
+ int i;
+
+ for (i = 0 ; i < QOS_MAX; i++) {
+ INIT_LIST_HEAD(&qcb->qos_list[i]);
+ qcb->csr[i].QoSBufCount = 0;
+ qcb->csr[i].Enabled = 0;
+ }
+
+ qcb->qos_list_cnt = 0;
+ qcb->qos_null_idx = QOS_MAX-1;
+ qcb->qos_limit_size = 255;
+
+ spin_lock_init(&qcb->qos_lock);
+
+ init_qos_entry_list();
+}
+
+void gdm_qos_release_list(void *nic_ptr)
+{
+ struct nic *nic = nic_ptr;
+ struct qos_cb_s *qcb = &nic->qos;
+ unsigned long flags;
+ struct qos_entry_s *entry, *n;
+ struct list_head free_list;
+ int i;
+
+ INIT_LIST_HEAD(&free_list);
+
+ spin_lock_irqsave(&qcb->qos_lock, flags);
+
+ for (i = 0; i < QOS_MAX; i++) {
+ qcb->csr[i].QoSBufCount = 0;
+ qcb->csr[i].Enabled = 0;
+ }
+
+ qcb->qos_list_cnt = 0;
+ qcb->qos_null_idx = QOS_MAX-1;
+
+ for (i = 0; i < QOS_MAX; i++) {
+ list_for_each_entry_safe(entry, n, &qcb->qos_list[i], list) {
+ list_move_tail(&entry->list, &free_list);
+ }
+ }
+ spin_unlock_irqrestore(&qcb->qos_lock, flags);
+ free_qos_entry_list(&free_list);
+}
+
+static u32 chk_ipv4_rule(struct gdm_wimax_csr_s *csr, u8 *Stream, u8 *port)
+{
+ int i;
+
+ if (csr->ClassifierRuleEnable&IPTYPEOFSERVICE) {
+ if (((Stream[1] & csr->IPToSMask) < csr->IPToSLow) ||
+ ((Stream[1] & csr->IPToSMask) > csr->IPToSHigh))
+ return 1;
+ }
+
+ if (csr->ClassifierRuleEnable&PROTOCOL) {
+ if (Stream[9] != csr->Protocol)
+ return 1;
+ }
+
+ if (csr->ClassifierRuleEnable&IPMASKEDSRCADDRESS) {
+ for (i = 0; i < 4; i++) {
+ if ((Stream[12 + i] & csr->IPSrcAddrMask[i]) !=
+ (csr->IPSrcAddr[i] & csr->IPSrcAddrMask[i]))
+ return 1;
+ }
+ }
+
+ if (csr->ClassifierRuleEnable&IPMASKEDDSTADDRESS) {
+ for (i = 0; i < 4; i++) {
+ if ((Stream[16 + i] & csr->IPDstAddrMask[i]) !=
+ (csr->IPDstAddr[i] & csr->IPDstAddrMask[i]))
+ return 1;
+ }
+ }
+
+ if (csr->ClassifierRuleEnable&PROTOCOLSRCPORTRANGE) {
+ i = ((port[0]<<8)&0xff00)+port[1];
+ if ((i < csr->SrcPortLow) || (i > csr->SrcPortHigh))
+ return 1;
+ }
+
+ if (csr->ClassifierRuleEnable&PROTOCOLDSTPORTRANGE) {
+ i = ((port[2]<<8)&0xff00)+port[3];
+ if ((i < csr->DstPortLow) || (i > csr->DstPortHigh))
+ return 1;
+ }
+
+ return 0;
+}
+
+static u32 get_qos_index(struct nic *nic, u8* iph, u8* tcpudph)
+{
+ u32 IP_Ver, Header_Len, i;
+ struct qos_cb_s *qcb = &nic->qos;
+
+ if (iph == NULL || tcpudph == NULL)
+ return -1;
+
+ IP_Ver = (iph[0]>>4)&0xf;
+ Header_Len = iph[0]&0xf;
+
+ if (IP_Ver == 4) {
+ for (i = 0; i < QOS_MAX; i++) {
+ if (qcb->csr[i].Enabled) {
+ if (qcb->csr[i].ClassifierRuleEnable) {
+ if (chk_ipv4_rule(&qcb->csr[i], iph,
+ tcpudph) == 0)
+ return i;
+ }
+ }
+ }
+ }
+
+ return -1;
+}
+
+static u32 extract_qos_list(struct nic *nic, struct list_head *head)
+{
+ struct qos_cb_s *qcb = &nic->qos;
+ struct qos_entry_s *entry;
+ int i;
+
+ INIT_LIST_HEAD(head);
+
+ for (i = 0; i < QOS_MAX; i++) {
+ if (qcb->csr[i].Enabled) {
+ if (qcb->csr[i].QoSBufCount < qcb->qos_limit_size) {
+ if (!list_empty(&qcb->qos_list[i])) {
+ entry = list_entry(
+ qcb->qos_list[i].prev,
+ struct qos_entry_s, list);
+ list_move_tail(&entry->list, head);
+ qcb->csr[i].QoSBufCount++;
+
+ if (!list_empty(&qcb->qos_list[i]))
+ wprintk("QoS Index(%d) "
+ "is piled!!\n", i);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void send_qos_list(struct nic *nic, struct list_head *head)
+{
+ struct qos_entry_s *entry, *n;
+
+ list_for_each_entry_safe(entry, n, head, list) {
+ list_del(&entry->list);
+ free_qos_entry(entry);
+ gdm_wimax_send_tx(entry->skb, entry->dev);
+ }
+}
+
+int gdm_qos_send_hci_pkt(struct sk_buff *skb, struct net_device *dev)
+{
+ struct nic *nic = netdev_priv(dev);
+ int index;
+ struct qos_cb_s *qcb = &nic->qos;
+ unsigned long flags;
+ struct ethhdr *ethh = (struct ethhdr *) (skb->data + HCI_HEADER_SIZE);
+ struct iphdr *iph = (struct iphdr *) ((char *) ethh + ETH_HLEN);
+ struct tcphdr *tcph;
+ struct qos_entry_s *entry = NULL;
+ struct list_head send_list;
+ int ret = 0;
+
+ tcph = (struct tcphdr *) iph + iph->ihl*4;
+
+ if (B2H(ethh->h_proto) == ETH_P_IP) {
+ if (qcb->qos_list_cnt && !qos_free_list.cnt) {
+ entry = alloc_qos_entry();
+ entry->skb = skb;
+ entry->dev = dev;
+ dprintk("qcb->qos_list_cnt=%d\n", qcb->qos_list_cnt);
+ }
+
+ spin_lock_irqsave(&qcb->qos_lock, flags);
+ if (qcb->qos_list_cnt) {
+ index = get_qos_index(nic, (u8 *)iph, (u8 *) tcph);
+ if (index == -1)
+ index = qcb->qos_null_idx;
+
+ if (!entry) {
+ entry = alloc_qos_entry();
+ entry->skb = skb;
+ entry->dev = dev;
+ }
+
+ list_add_tail(&entry->list, &qcb->qos_list[index]);
+ extract_qos_list(nic, &send_list);
+ spin_unlock_irqrestore(&qcb->qos_lock, flags);
+ send_qos_list(nic, &send_list);
+ goto out;
+ }
+ spin_unlock_irqrestore(&qcb->qos_lock, flags);
+ if (entry)
+ free_qos_entry(entry);
+ }
+
+ ret = gdm_wimax_send_tx(skb, dev);
+out:
+ return ret;
+}
+
+static u32 get_csr(struct qos_cb_s *qcb, u32 SFID, int mode)
+{
+ int i;
+
+ for (i = 0; i < qcb->qos_list_cnt; i++) {
+ if (qcb->csr[i].SFID == SFID)
+ return i;
+ }
+
+ if (mode) {
+ for (i = 0; i < QOS_MAX; i++) {
+ if (qcb->csr[i].Enabled == 0) {
+ qcb->csr[i].Enabled = 1;
+ qcb->qos_list_cnt++;
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+#define QOS_CHANGE_DEL 0xFC
+#define QOS_ADD 0xFD
+#define QOS_REPORT 0xFE
+
+void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
+{
+ struct nic *nic = nic_ptr;
+ u32 i, SFID, index, pos;
+ u8 subCmdEvt;
+ u8 len;
+ struct qos_cb_s *qcb = &nic->qos;
+ struct qos_entry_s *entry, *n;
+ struct list_head send_list;
+ struct list_head free_list;
+ unsigned long flags;
+
+ subCmdEvt = (u8)buf[4];
+
+ if (subCmdEvt == QOS_REPORT) {
+ len = (u8)buf[5];
+
+ spin_lock_irqsave(&qcb->qos_lock, flags);
+ for (i = 0; i < qcb->qos_list_cnt; i++) {
+ SFID = ((buf[(i*5)+6]<<24)&0xff000000);
+ SFID += ((buf[(i*5)+7]<<16)&0xff0000);
+ SFID += ((buf[(i*5)+8]<<8)&0xff00);
+ SFID += (buf[(i*5)+9]);
+ index = get_csr(qcb, SFID, 0);
+ if (index == -1) {
+ spin_unlock_irqrestore(&qcb->qos_lock, flags);
+ eprintk("QoS ERROR: No SF\n");
+ return;
+ }
+ qcb->csr[index].QoSBufCount = buf[(i*5)+10];
+ }
+
+ extract_qos_list(nic, &send_list);
+ spin_unlock_irqrestore(&qcb->qos_lock, flags);
+ send_qos_list(nic, &send_list);
+ return;
+ } else if (subCmdEvt == QOS_ADD) {
+ pos = 5;
+ len = (u8)buf[pos++];
+
+ SFID = ((buf[pos++]<<24)&0xff000000);
+ SFID += ((buf[pos++]<<16)&0xff0000);
+ SFID += ((buf[pos++]<<8)&0xff00);
+ SFID += (buf[pos++]);
+
+ index = get_csr(qcb, SFID, 1);
+ if (index == -1) {
+ eprintk("QoS ERROR: csr Update Error\n");
+ return;
+ }
+
+ dprintk("QOS_ADD SFID = 0x%x, index=%d\n", SFID, index);
+
+ spin_lock_irqsave(&qcb->qos_lock, flags);
+ qcb->csr[index].SFID = SFID;
+ qcb->csr[index].ClassifierRuleEnable = ((buf[pos++]<<8)&0xff00);
+ qcb->csr[index].ClassifierRuleEnable += buf[pos++];
+ if (qcb->csr[index].ClassifierRuleEnable == 0)
+ qcb->qos_null_idx = index;
+ qcb->csr[index].IPToSMask = buf[pos++];
+ qcb->csr[index].IPToSLow = buf[pos++];
+ qcb->csr[index].IPToSHigh = buf[pos++];
+ qcb->csr[index].Protocol = buf[pos++];
+ qcb->csr[index].IPSrcAddrMask[0] = buf[pos++];
+ qcb->csr[index].IPSrcAddrMask[1] = buf[pos++];
+ qcb->csr[index].IPSrcAddrMask[2] = buf[pos++];
+ qcb->csr[index].IPSrcAddrMask[3] = buf[pos++];
+ qcb->csr[index].IPSrcAddr[0] = buf[pos++];
+ qcb->csr[index].IPSrcAddr[1] = buf[pos++];
+ qcb->csr[index].IPSrcAddr[2] = buf[pos++];
+ qcb->csr[index].IPSrcAddr[3] = buf[pos++];
+ qcb->csr[index].IPDstAddrMask[0] = buf[pos++];
+ qcb->csr[index].IPDstAddrMask[1] = buf[pos++];
+ qcb->csr[index].IPDstAddrMask[2] = buf[pos++];
+ qcb->csr[index].IPDstAddrMask[3] = buf[pos++];
+ qcb->csr[index].IPDstAddr[0] = buf[pos++];
+ qcb->csr[index].IPDstAddr[1] = buf[pos++];
+ qcb->csr[index].IPDstAddr[2] = buf[pos++];
+ qcb->csr[index].IPDstAddr[3] = buf[pos++];
+ qcb->csr[index].SrcPortLow = ((buf[pos++]<<8)&0xff00);
+ qcb->csr[index].SrcPortLow += buf[pos++];
+ qcb->csr[index].SrcPortHigh = ((buf[pos++]<<8)&0xff00);
+ qcb->csr[index].SrcPortHigh += buf[pos++];
+ qcb->csr[index].DstPortLow = ((buf[pos++]<<8)&0xff00);
+ qcb->csr[index].DstPortLow += buf[pos++];
+ qcb->csr[index].DstPortHigh = ((buf[pos++]<<8)&0xff00);
+ qcb->csr[index].DstPortHigh += buf[pos++];
+
+ qcb->qos_limit_size = 254/qcb->qos_list_cnt;
+ spin_unlock_irqrestore(&qcb->qos_lock, flags);
+ } else if (subCmdEvt == QOS_CHANGE_DEL) {
+ pos = 5;
+ len = (u8)buf[pos++];
+ SFID = ((buf[pos++]<<24)&0xff000000);
+ SFID += ((buf[pos++]<<16)&0xff0000);
+ SFID += ((buf[pos++]<<8)&0xff00);
+ SFID += (buf[pos++]);
+ index = get_csr(qcb, SFID, 1);
+ if (index == -1) {
+ eprintk("QoS ERROR: Wrong index(%d)\n", index);
+ return;
+ }
+
+ dprintk("QOS_CHANGE_DEL SFID = 0x%x, index=%d\n", SFID, index);
+
+ INIT_LIST_HEAD(&free_list);
+
+ spin_lock_irqsave(&qcb->qos_lock, flags);
+ qcb->csr[index].Enabled = 0;
+ qcb->qos_list_cnt--;
+ qcb->qos_limit_size = 254/qcb->qos_list_cnt;
+
+ list_for_each_entry_safe(entry, n, &qcb->qos_list[index],
+ list) {
+ list_move_tail(&entry->list, &free_list);
+ }
+ spin_unlock_irqrestore(&qcb->qos_lock, flags);
+ free_qos_entry_list(&free_list);
+ }
+}
diff --git a/drivers/staging/gdm72xx/gdm_qos.h b/drivers/staging/gdm72xx/gdm_qos.h
new file mode 100644
index 000000000000..33f2bd4cee32
--- /dev/null
+++ b/drivers/staging/gdm72xx/gdm_qos.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#if !defined(GDM_QOS_H_20090403)
+#define GDM_QOS_H_20090403
+
+#include <linux/types.h>
+#include <linux/usb.h>
+#include <linux/list.h>
+
+#define BOOLEAN u8
+
+#define QOS_MAX 16
+#define IPTYPEOFSERVICE 0x8000
+#define PROTOCOL 0x4000
+#define IPMASKEDSRCADDRESS 0x2000
+#define IPMASKEDDSTADDRESS 0x1000
+#define PROTOCOLSRCPORTRANGE 0x800
+#define PROTOCOLDSTPORTRANGE 0x400
+#define DSTMACADDR 0x200
+#define SRCMACADDR 0x100
+#define ETHERTYPE 0x80
+#define IEEE802_1DUSERPRIORITY 0x40
+#define IEEE802_1QVLANID 0x10
+
+struct gdm_wimax_csr_s {
+ /* union{
+ U16 all;
+ struct _CS_CLASSIFIER_RULE_ENABLE{
+ IPTypeOfService:1,
+ Protocol:1,
+ IPMaskedSrcAddress:1,
+ IPMaskedDstAddress:1,
+ ProtocolSrcPortRange:1,
+ ProtocolDstPortRange:1,
+ DstMacAddr:1,
+ SrcMacAddr:1,
+ Ethertype:1,
+ IEEE802_1DUserPriority:1,
+ IEEE802_1QVLANID:1,
+ Reserved:5;
+ } fields;
+ } */
+ BOOLEAN Enabled;
+ u32 SFID;
+ u8 QoSBufCount;
+ u16 ClassifierRuleEnable;
+ u8 IPToSLow;
+ u8 IPToSHigh;
+ u8 IPToSMask;
+ u8 Protocol;
+ u8 IPSrcAddr[16];
+ u8 IPSrcAddrMask[16];
+ u8 IPDstAddr[16];
+ u8 IPDstAddrMask[16];
+ u16 SrcPortLow;
+ u16 SrcPortHigh;
+ u16 DstPortLow;
+ u16 DstPortHigh;
+};
+
+struct qos_entry_s {
+ struct list_head list;
+ struct sk_buff *skb;
+ struct net_device *dev;
+
+};
+
+struct qos_cb_s {
+ struct list_head qos_list[QOS_MAX];
+ u32 qos_list_cnt;
+ u32 qos_null_idx;
+ struct gdm_wimax_csr_s csr[QOS_MAX];
+ spinlock_t qos_lock;
+ u32 qos_limit_size;
+};
+
+void gdm_qos_init(void *nic_ptr);
+void gdm_qos_release_list(void *nic_ptr);
+int gdm_qos_send_hci_pkt(struct sk_buff *skb, struct net_device *dev);
+void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size);
+
+#endif
diff --git a/drivers/staging/gdm72xx/gdm_sdio.c b/drivers/staging/gdm72xx/gdm_sdio.c
new file mode 100644
index 000000000000..e1a3dd2fc4af
--- /dev/null
+++ b/drivers/staging/gdm72xx/gdm_sdio.c
@@ -0,0 +1,754 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+
+#include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+
+#include "gdm_sdio.h"
+#include "gdm_wimax.h"
+#include "sdio_boot.h"
+#include "hci.h"
+
+#define TYPE_A_HEADER_SIZE 4
+#define TYPE_A_LOOKAHEAD_SIZE 16
+
+#define MAX_NR_RX_BUF 4
+
+#define SDU_TX_BUF_SIZE 2048
+#define TX_BUF_SIZE 2048
+#define TX_CHUNK_SIZE (2048 - TYPE_A_HEADER_SIZE)
+#define RX_BUF_SIZE (25*1024)
+
+#define TX_HZ 2000
+#define TX_INTERVAL (1000000/TX_HZ)
+
+/*#define DEBUG*/
+
+static int init_sdio(struct sdiowm_dev *sdev);
+static void release_sdio(struct sdiowm_dev *sdev);
+
+#ifdef DEBUG
+static void hexdump(char *title, u8 *data, int len)
+{
+ int i;
+
+ printk(KERN_DEBUG "%s: length = %d\n", title, len);
+ for (i = 0; i < len; i++) {
+ printk(KERN_DEBUG "%02x ", data[i]);
+ if ((i & 0xf) == 0xf)
+ printk(KERN_DEBUG "\n");
+ }
+ printk(KERN_DEBUG "\n");
+}
+#endif
+
+static struct sdio_tx *alloc_tx_struct(struct tx_cxt *tx)
+{
+ struct sdio_tx *t = NULL;
+
+ t = kmalloc(sizeof(*t), GFP_ATOMIC);
+ if (t == NULL)
+ goto out;
+
+ memset(t, 0, sizeof(*t));
+
+ t->buf = kmalloc(TX_BUF_SIZE, GFP_ATOMIC);
+ if (t->buf == NULL)
+ goto out;
+
+ t->tx_cxt = tx;
+
+ return t;
+out:
+ if (t) {
+ kfree(t->buf);
+ kfree(t);
+ }
+ return NULL;
+}
+
+static void free_tx_struct(struct sdio_tx *t)
+{
+ if (t) {
+ kfree(t->buf);
+ kfree(t);
+ }
+}
+
+static struct sdio_rx *alloc_rx_struct(struct rx_cxt *rx)
+{
+ struct sdio_rx *r = NULL;
+
+ r = kmalloc(sizeof(*r), GFP_ATOMIC);
+ if (r == NULL)
+ goto out;
+
+ memset(r, 0, sizeof(*r));
+
+ r->rx_cxt = rx;
+
+ return r;
+out:
+ kfree(r);
+ return NULL;
+}
+
+static void free_rx_struct(struct sdio_rx *r)
+{
+ kfree(r);
+}
+
+/* Before this function is called, spin lock should be locked. */
+static struct sdio_tx *get_tx_struct(struct tx_cxt *tx, int *no_spc)
+{
+ struct sdio_tx *t;
+
+ if (list_empty(&tx->free_list))
+ return NULL;
+
+ t = list_entry(tx->free_list.prev, struct sdio_tx, list);
+ list_del(&t->list);
+
+ *no_spc = list_empty(&tx->free_list) ? 1 : 0;
+
+ return t;
+}
+
+/* Before this function is called, spin lock should be locked. */
+static void put_tx_struct(struct tx_cxt *tx, struct sdio_tx *t)
+{
+ list_add_tail(&t->list, &tx->free_list);
+}
+
+/* Before this function is called, spin lock should be locked. */
+static struct sdio_rx *get_rx_struct(struct rx_cxt *rx)
+{
+ struct sdio_rx *r;
+
+ if (list_empty(&rx->free_list))
+ return NULL;
+
+ r = list_entry(rx->free_list.prev, struct sdio_rx, list);
+ list_del(&r->list);
+
+ return r;
+}
+
+/* Before this function is called, spin lock should be locked. */
+static void put_rx_struct(struct rx_cxt *rx, struct sdio_rx *r)
+{
+ list_add_tail(&r->list, &rx->free_list);
+}
+
+static int init_sdio(struct sdiowm_dev *sdev)
+{
+ int ret = 0, i;
+ struct tx_cxt *tx = &sdev->tx;
+ struct rx_cxt *rx = &sdev->rx;
+ struct sdio_tx *t;
+ struct sdio_rx *r;
+
+ INIT_LIST_HEAD(&tx->free_list);
+ INIT_LIST_HEAD(&tx->sdu_list);
+ INIT_LIST_HEAD(&tx->hci_list);
+
+ spin_lock_init(&tx->lock);
+
+ tx->sdu_buf = kmalloc(SDU_TX_BUF_SIZE, GFP_KERNEL);
+ if (tx->sdu_buf == NULL) {
+ printk(KERN_ERR "Failed to allocate SDU tx buffer.\n");
+ goto fail;
+ }
+
+ for (i = 0; i < MAX_NR_SDU_BUF; i++) {
+ t = alloc_tx_struct(tx);
+ if (t == NULL) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ list_add(&t->list, &tx->free_list);
+ }
+
+ INIT_LIST_HEAD(&rx->free_list);
+ INIT_LIST_HEAD(&rx->req_list);
+
+ spin_lock_init(&rx->lock);
+
+ for (i = 0; i < MAX_NR_RX_BUF; i++) {
+ r = alloc_rx_struct(rx);
+ if (r == NULL) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ list_add(&r->list, &rx->free_list);
+ }
+
+ rx->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
+ if (rx->rx_buf == NULL) {
+ printk(KERN_ERR "Failed to allocate rx buffer.\n");
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ release_sdio(sdev);
+ return ret;
+}
+
+static void release_sdio(struct sdiowm_dev *sdev)
+{
+ struct tx_cxt *tx = &sdev->tx;
+ struct rx_cxt *rx = &sdev->rx;
+ struct sdio_tx *t, *t_next;
+ struct sdio_rx *r, *r_next;
+
+ kfree(tx->sdu_buf);
+
+ list_for_each_entry_safe(t, t_next, &tx->free_list, list) {
+ list_del(&t->list);
+ free_tx_struct(t);
+ }
+
+ list_for_each_entry_safe(t, t_next, &tx->sdu_list, list) {
+ list_del(&t->list);
+ free_tx_struct(t);
+ }
+
+ list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
+ list_del(&t->list);
+ free_tx_struct(t);
+ }
+
+ kfree(rx->rx_buf);
+
+ list_for_each_entry_safe(r, r_next, &rx->free_list, list) {
+ list_del(&r->list);
+ free_rx_struct(r);
+ }
+
+ list_for_each_entry_safe(r, r_next, &rx->req_list, list) {
+ list_del(&r->list);
+ free_rx_struct(r);
+ }
+}
+
+static void send_sdio_pkt(struct sdio_func *func, u8 *data, int len)
+{
+ int n, blocks, ret, remain;
+
+ sdio_claim_host(func);
+
+ blocks = len / func->cur_blksize;
+ n = blocks * func->cur_blksize;
+ if (blocks) {
+ ret = sdio_memcpy_toio(func, 0, data, n);
+ if (ret < 0) {
+ if (ret != -ENOMEDIUM)
+ printk(KERN_ERR "gdmwms: %s error: ret = %d\n",
+ __func__, ret);
+ goto end_io;
+ }
+ }
+
+ remain = len - n;
+ remain = (remain + 3) & ~3;
+
+ if (remain) {
+ ret = sdio_memcpy_toio(func, 0, data + n, remain);
+ if (ret < 0) {
+ if (ret != -ENOMEDIUM)
+ printk(KERN_ERR "gdmwms: %s error: ret = %d\n",
+ __func__, ret);
+ goto end_io;
+ }
+ }
+
+end_io:
+ sdio_release_host(func);
+}
+
+static void send_sdu(struct sdio_func *func, struct tx_cxt *tx)
+{
+ struct list_head *l, *next;
+ struct hci_s *hci;
+ struct sdio_tx *t;
+ int pos, len, i, estlen, aggr_num = 0, aggr_len;
+ u8 *buf;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tx->lock, flags);
+
+ pos = TYPE_A_HEADER_SIZE + HCI_HEADER_SIZE;
+ list_for_each_entry(t, &tx->sdu_list, list) {
+ estlen = ((t->len + 3) & ~3) + 4;
+ if ((pos + estlen) > SDU_TX_BUF_SIZE)
+ break;
+
+ aggr_num++;
+ memcpy(tx->sdu_buf + pos, t->buf, t->len);
+ memset(tx->sdu_buf + pos + t->len, 0, estlen - t->len);
+ pos += estlen;
+ }
+ aggr_len = pos;
+
+ hci = (struct hci_s *)(tx->sdu_buf + TYPE_A_HEADER_SIZE);
+ hci->cmd_evt = H2B(WIMAX_TX_SDU_AGGR);
+ hci->length = H2B(aggr_len - TYPE_A_HEADER_SIZE - HCI_HEADER_SIZE);
+
+ spin_unlock_irqrestore(&tx->lock, flags);
+
+#ifdef DEBUG
+ hexdump("sdio_send", tx->sdu_buf + TYPE_A_HEADER_SIZE,
+ aggr_len - TYPE_A_HEADER_SIZE);
+#endif
+
+ for (pos = TYPE_A_HEADER_SIZE; pos < aggr_len; pos += TX_CHUNK_SIZE) {
+ len = aggr_len - pos;
+ len = len > TX_CHUNK_SIZE ? TX_CHUNK_SIZE : len;
+ buf = tx->sdu_buf + pos - TYPE_A_HEADER_SIZE;
+
+ buf[0] = len & 0xff;
+ buf[1] = (len >> 8) & 0xff;
+ buf[2] = (len >> 16) & 0xff;
+ buf[3] = (pos + len) >= aggr_len ? 0 : 1;
+ send_sdio_pkt(func, buf, len + TYPE_A_HEADER_SIZE);
+ }
+
+ spin_lock_irqsave(&tx->lock, flags);
+
+ for (l = tx->sdu_list.next, i = 0; i < aggr_num; i++, l = next) {
+ next = l->next;
+ t = list_entry(l, struct sdio_tx, list);
+ if (t->callback)
+ t->callback(t->cb_data);
+
+ list_del(l);
+ put_tx_struct(t->tx_cxt, t);
+ }
+
+ do_gettimeofday(&tx->sdu_stamp);
+ spin_unlock_irqrestore(&tx->lock, flags);
+}
+
+static void send_hci(struct sdio_func *func, struct tx_cxt *tx,
+ struct sdio_tx *t)
+{
+ unsigned long flags;
+
+#ifdef DEBUG
+ hexdump("sdio_send", t->buf + TYPE_A_HEADER_SIZE,
+ t->len - TYPE_A_HEADER_SIZE);
+#endif
+ send_sdio_pkt(func, t->buf, t->len);
+
+ spin_lock_irqsave(&tx->lock, flags);
+ if (t->callback)
+ t->callback(t->cb_data);
+ free_tx_struct(t);
+ spin_unlock_irqrestore(&tx->lock, flags);
+}
+
+static void do_tx(struct work_struct *work)
+{
+ struct sdiowm_dev *sdev = container_of(work, struct sdiowm_dev, ws);
+ struct sdio_func *func = sdev->func;
+ struct tx_cxt *tx = &sdev->tx;
+ struct sdio_tx *t = NULL;
+ struct timeval now, *before;
+ int is_sdu = 0;
+ long diff;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tx->lock, flags);
+ if (!tx->can_send) {
+ spin_unlock_irqrestore(&tx->lock, flags);
+ return;
+ }
+
+ if (!list_empty(&tx->hci_list)) {
+ t = list_entry(tx->hci_list.next, struct sdio_tx, list);
+ list_del(&t->list);
+ is_sdu = 0;
+ } else if (!tx->stop_sdu_tx && !list_empty(&tx->sdu_list)) {
+ do_gettimeofday(&now);
+ before = &tx->sdu_stamp;
+
+ diff = (now.tv_sec - before->tv_sec) * 1000000 +
+ (now.tv_usec - before->tv_usec);
+ if (diff >= 0 && diff < TX_INTERVAL) {
+ schedule_work(&sdev->ws);
+ spin_unlock_irqrestore(&tx->lock, flags);
+ return;
+ }
+ is_sdu = 1;
+ }
+
+ if (!is_sdu && t == NULL) {
+ spin_unlock_irqrestore(&tx->lock, flags);
+ return;
+ }
+
+ tx->can_send = 0;
+
+ spin_unlock_irqrestore(&tx->lock, flags);
+
+ if (is_sdu)
+ send_sdu(func, tx);
+ else
+ send_hci(func, tx, t);
+}
+
+static int gdm_sdio_send(void *priv_dev, void *data, int len,
+ void (*cb)(void *data), void *cb_data)
+{
+ struct sdiowm_dev *sdev = priv_dev;
+ struct tx_cxt *tx = &sdev->tx;
+ struct sdio_tx *t;
+ u8 *pkt = data;
+ int no_spc = 0;
+ u16 cmd_evt;
+ unsigned long flags;
+
+ BUG_ON(len > TX_BUF_SIZE - TYPE_A_HEADER_SIZE);
+
+ spin_lock_irqsave(&tx->lock, flags);
+
+ cmd_evt = (pkt[0] << 8) | pkt[1];
+ if (cmd_evt == WIMAX_TX_SDU) {
+ t = get_tx_struct(tx, &no_spc);
+ if (t == NULL) {
+ /* This case must not happen. */
+ spin_unlock_irqrestore(&tx->lock, flags);
+ return -ENOSPC;
+ }
+ list_add_tail(&t->list, &tx->sdu_list);
+
+ memcpy(t->buf, data, len);
+
+ t->len = len;
+ t->callback = cb;
+ t->cb_data = cb_data;
+ } else {
+ t = alloc_tx_struct(tx);
+ if (t == NULL) {
+ spin_unlock_irqrestore(&tx->lock, flags);
+ return -ENOMEM;
+ }
+ list_add_tail(&t->list, &tx->hci_list);
+
+ t->buf[0] = len & 0xff;
+ t->buf[1] = (len >> 8) & 0xff;
+ t->buf[2] = (len >> 16) & 0xff;
+ t->buf[3] = 2;
+ memcpy(t->buf + TYPE_A_HEADER_SIZE, data, len);
+
+ t->len = len + TYPE_A_HEADER_SIZE;
+ t->callback = cb;
+ t->cb_data = cb_data;
+ }
+
+ if (tx->can_send)
+ schedule_work(&sdev->ws);
+
+ spin_unlock_irqrestore(&tx->lock, flags);
+
+ if (no_spc)
+ return -ENOSPC;
+
+ return 0;
+}
+
+/*
+ * Handle the HCI, WIMAX_SDU_TX_FLOW.
+ */
+static int control_sdu_tx_flow(struct sdiowm_dev *sdev, u8 *hci_data, int len)
+{
+ struct tx_cxt *tx = &sdev->tx;
+ u16 cmd_evt;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tx->lock, flags);
+
+ cmd_evt = (hci_data[0] << 8) | (hci_data[1]);
+ if (cmd_evt != WIMAX_SDU_TX_FLOW)
+ goto out;
+
+ if (hci_data[4] == 0) {
+#ifdef DEBUG
+ printk(KERN_DEBUG "WIMAX ==> STOP SDU TX\n");
+#endif
+ tx->stop_sdu_tx = 1;
+ } else if (hci_data[4] == 1) {
+#ifdef DEBUG
+ printk(KERN_DEBUG "WIMAX ==> START SDU TX\n");
+#endif
+ tx->stop_sdu_tx = 0;
+ if (tx->can_send)
+ schedule_work(&sdev->ws);
+ /*
+ * If free buffer for sdu tx doesn't exist, then tx queue
+ * should not be woken. For this reason, don't pass the command,
+ * START_SDU_TX.
+ */
+ if (list_empty(&tx->free_list))
+ len = 0;
+ }
+
+out:
+ spin_unlock_irqrestore(&tx->lock, flags);
+ return len;
+}
+
+static void gdm_sdio_irq(struct sdio_func *func)
+{
+ struct phy_dev *phy_dev = sdio_get_drvdata(func);
+ struct sdiowm_dev *sdev = phy_dev->priv_dev;
+ struct tx_cxt *tx = &sdev->tx;
+ struct rx_cxt *rx = &sdev->rx;
+ struct sdio_rx *r;
+ unsigned long flags;
+ u8 val, hdr[TYPE_A_LOOKAHEAD_SIZE], *buf;
+ u32 len, blocks, n;
+ int ret, remain;
+
+ /* Check interrupt */
+ val = sdio_readb(func, 0x13, &ret);
+ if (val & 0x01)
+ sdio_writeb(func, 0x01, 0x13, &ret); /* clear interrupt */
+ else
+ return;
+
+ ret = sdio_memcpy_fromio(func, hdr, 0x0, TYPE_A_LOOKAHEAD_SIZE);
+ if (ret) {
+ printk(KERN_ERR "Cannot read from function %d\n", func->num);
+ goto done;
+ }
+
+ len = (hdr[2] << 16) | (hdr[1] << 8) | hdr[0];
+ if (len > (RX_BUF_SIZE - TYPE_A_HEADER_SIZE)) {
+ printk(KERN_ERR "Too big Type-A size: %d\n", len);
+ goto done;
+ }
+
+ if (hdr[3] == 1) { /* Ack */
+#ifdef DEBUG
+ u32 *ack_seq = (u32 *)&hdr[4];
+#endif
+ spin_lock_irqsave(&tx->lock, flags);
+ tx->can_send = 1;
+
+ if (!list_empty(&tx->sdu_list) || !list_empty(&tx->hci_list))
+ schedule_work(&sdev->ws);
+ spin_unlock_irqrestore(&tx->lock, flags);
+#ifdef DEBUG
+ printk(KERN_DEBUG "Ack... %0x\n", ntohl(*ack_seq));
+#endif
+ goto done;
+ }
+
+ memcpy(rx->rx_buf, hdr + TYPE_A_HEADER_SIZE,
+ TYPE_A_LOOKAHEAD_SIZE - TYPE_A_HEADER_SIZE);
+
+ buf = rx->rx_buf + TYPE_A_LOOKAHEAD_SIZE - TYPE_A_HEADER_SIZE;
+ remain = len - TYPE_A_LOOKAHEAD_SIZE + TYPE_A_HEADER_SIZE;
+ if (remain <= 0)
+ goto end_io;
+
+ blocks = remain / func->cur_blksize;
+
+ if (blocks) {
+ n = blocks * func->cur_blksize;
+ ret = sdio_memcpy_fromio(func, buf, 0x0, n);
+ if (ret) {
+ printk(KERN_ERR "Cannot read from function %d\n",
+ func->num);
+ goto done;
+ }
+ buf += n;
+ remain -= n;
+ }
+
+ if (remain) {
+ ret = sdio_memcpy_fromio(func, buf, 0x0, remain);
+ if (ret) {
+ printk(KERN_ERR "Cannot read from function %d\n",
+ func->num);
+ goto done;
+ }
+ }
+
+end_io:
+#ifdef DEBUG
+ hexdump("sdio_receive", rx->rx_buf, len);
+#endif
+ len = control_sdu_tx_flow(sdev, rx->rx_buf, len);
+
+ spin_lock_irqsave(&rx->lock, flags);
+
+ if (!list_empty(&rx->req_list)) {
+ r = list_entry(rx->req_list.next, struct sdio_rx, list);
+ spin_unlock_irqrestore(&rx->lock, flags);
+ if (r->callback)
+ r->callback(r->cb_data, rx->rx_buf, len);
+ spin_lock_irqsave(&rx->lock, flags);
+ list_del(&r->list);
+ put_rx_struct(rx, r);
+ }
+
+ spin_unlock_irqrestore(&rx->lock, flags);
+
+done:
+ sdio_writeb(func, 0x00, 0x10, &ret); /* PCRRT */
+ if (!phy_dev->netdev)
+ register_wimax_device(phy_dev, &func->dev);
+}
+
+static int gdm_sdio_receive(void *priv_dev,
+ void (*cb)(void *cb_data, void *data, int len),
+ void *cb_data)
+{
+ struct sdiowm_dev *sdev = priv_dev;
+ struct rx_cxt *rx = &sdev->rx;
+ struct sdio_rx *r;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rx->lock, flags);
+ r = get_rx_struct(rx);
+ if (r == NULL) {
+ spin_unlock_irqrestore(&rx->lock, flags);
+ return -ENOMEM;
+ }
+
+ r->callback = cb;
+ r->cb_data = cb_data;
+
+ list_add_tail(&r->list, &rx->req_list);
+ spin_unlock_irqrestore(&rx->lock, flags);
+
+ return 0;
+}
+
+static int sdio_wimax_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ int ret;
+ struct phy_dev *phy_dev = NULL;
+ struct sdiowm_dev *sdev = NULL;
+
+ printk(KERN_INFO "Found GDM SDIO VID = 0x%04x PID = 0x%04x...\n",
+ func->vendor, func->device);
+ printk(KERN_INFO "GCT WiMax driver version %s\n", DRIVER_VERSION);
+
+ sdio_claim_host(func);
+ sdio_enable_func(func);
+ sdio_claim_irq(func, gdm_sdio_irq);
+
+ ret = sdio_boot(func);
+ if (ret)
+ return ret;
+
+ phy_dev = kmalloc(sizeof(*phy_dev), GFP_KERNEL);
+ if (phy_dev == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ sdev = kmalloc(sizeof(*sdev), GFP_KERNEL);
+ if (sdev == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memset(phy_dev, 0, sizeof(*phy_dev));
+ memset(sdev, 0, sizeof(*sdev));
+
+ phy_dev->priv_dev = (void *)sdev;
+ phy_dev->send_func = gdm_sdio_send;
+ phy_dev->rcv_func = gdm_sdio_receive;
+
+ ret = init_sdio(sdev);
+ if (sdev < 0)
+ goto out;
+
+ sdev->func = func;
+
+ sdio_writeb(func, 1, 0x14, &ret); /* Enable interrupt */
+ sdio_release_host(func);
+
+ INIT_WORK(&sdev->ws, do_tx);
+
+ sdio_set_drvdata(func, phy_dev);
+out:
+ if (ret) {
+ kfree(phy_dev);
+ kfree(sdev);
+ }
+
+ return ret;
+}
+
+static void sdio_wimax_remove(struct sdio_func *func)
+{
+ struct phy_dev *phy_dev = sdio_get_drvdata(func);
+ struct sdiowm_dev *sdev = phy_dev->priv_dev;
+
+ if (phy_dev->netdev)
+ unregister_wimax_device(phy_dev);
+ sdio_claim_host(func);
+ sdio_release_irq(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+ release_sdio(sdev);
+
+ kfree(sdev);
+ kfree(phy_dev);
+}
+
+static const struct sdio_device_id sdio_wimax_ids[] = {
+ { SDIO_DEVICE(0x0296, 0x5347) },
+ {0}
+};
+
+MODULE_DEVICE_TABLE(sdio, sdio_wimax_ids);
+
+static struct sdio_driver sdio_wimax_driver = {
+ .probe = sdio_wimax_probe,
+ .remove = sdio_wimax_remove,
+ .name = "sdio_wimax",
+ .id_table = sdio_wimax_ids,
+};
+
+static int __init sdio_gdm_wimax_init(void)
+{
+ return sdio_register_driver(&sdio_wimax_driver);
+}
+
+static void __exit sdio_gdm_wimax_exit(void)
+{
+ sdio_unregister_driver(&sdio_wimax_driver);
+}
+
+module_init(sdio_gdm_wimax_init);
+module_exit(sdio_gdm_wimax_exit);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_DESCRIPTION("GCT WiMax SDIO Device Driver");
+MODULE_AUTHOR("Ethan Park");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gdm72xx/gdm_sdio.h b/drivers/staging/gdm72xx/gdm_sdio.h
new file mode 100644
index 000000000000..216e98f31bae
--- /dev/null
+++ b/drivers/staging/gdm72xx/gdm_sdio.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __GDM_SDIO_H__
+#define __GDM_SDIO_H__
+
+#include <linux/types.h>
+#include <linux/time.h>
+
+#define MAX_NR_SDU_BUF 64
+
+struct sdio_tx {
+ struct list_head list;
+ struct tx_cxt *tx_cxt;
+
+ u8 *buf;
+ int len;
+
+ void (*callback)(void *cb_data);
+ void *cb_data;
+};
+
+struct tx_cxt {
+ struct list_head free_list;
+ struct list_head sdu_list;
+ struct list_head hci_list;
+ struct timeval sdu_stamp;
+
+ u8 *sdu_buf;
+
+ spinlock_t lock;
+ int can_send;
+ int stop_sdu_tx;
+};
+
+struct sdio_rx {
+ struct list_head list;
+ struct rx_cxt *rx_cxt;
+
+ void (*callback)(void *cb_data, void *data, int len);
+ void *cb_data;
+};
+
+struct rx_cxt {
+ struct list_head free_list;
+ struct list_head req_list;
+
+ u8 *rx_buf;
+
+ spinlock_t lock;
+};
+
+struct sdiowm_dev {
+ struct sdio_func *func;
+
+ struct tx_cxt tx;
+ struct rx_cxt rx;
+
+ struct work_struct ws;
+};
+
+#endif /* __GDM_SDIO_H__ */
diff --git a/drivers/staging/gdm72xx/gdm_usb.c b/drivers/staging/gdm72xx/gdm_usb.c
new file mode 100644
index 000000000000..1e9dc0d90362
--- /dev/null
+++ b/drivers/staging/gdm72xx/gdm_usb.c
@@ -0,0 +1,798 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <asm/byteorder.h>
+
+#include "gdm_usb.h"
+#include "gdm_wimax.h"
+#include "usb_boot.h"
+#include "hci.h"
+
+#include "usb_ids.h"
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+#define TX_BUF_SIZE 2048
+#if defined(CONFIG_WIMAX_GDM72XX_WIMAX2)
+#define RX_BUF_SIZE (128*1024) /* For packet aggregation */
+#else
+#define RX_BUF_SIZE 2048
+#endif
+
+#define GDM7205_PADDING 256
+
+#define H2B(x) __cpu_to_be16(x)
+#define B2H(x) __be16_to_cpu(x)
+#define DB2H(x) __be32_to_cpu(x)
+
+#define DOWNLOAD_CONF_VALUE 0x21
+
+#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
+
+static DECLARE_WAIT_QUEUE_HEAD(k_wait);
+static LIST_HEAD(k_list);
+static DEFINE_SPINLOCK(k_lock);
+static int k_mode_stop;
+
+#define K_WAIT_TIME (2 * HZ / 100)
+
+#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
+
+static int init_usb(struct usbwm_dev *udev);
+static void release_usb(struct usbwm_dev *udev);
+
+/*#define DEBUG */
+#ifdef DEBUG
+static void hexdump(char *title, u8 *data, int len)
+{
+ int i;
+
+ printk(KERN_DEBUG "%s: length = %d\n", title, len);
+ for (i = 0; i < len; i++) {
+ printk(KERN_DEBUG "%02x ", data[i]);
+ if ((i & 0xf) == 0xf)
+ printk(KERN_DEBUG "\n");
+ }
+ printk(KERN_DEBUG "\n");
+}
+#endif
+
+static struct usb_tx *alloc_tx_struct(struct tx_cxt *tx)
+{
+ struct usb_tx *t = NULL;
+
+ t = kmalloc(sizeof(*t), GFP_ATOMIC);
+ if (t == NULL)
+ goto out;
+
+ memset(t, 0, sizeof(*t));
+
+ t->urb = usb_alloc_urb(0, GFP_ATOMIC);
+ t->buf = kmalloc(TX_BUF_SIZE, GFP_ATOMIC);
+ if (t->urb == NULL || t->buf == NULL)
+ goto out;
+
+ t->tx_cxt = tx;
+
+ return t;
+out:
+ if (t) {
+ usb_free_urb(t->urb);
+ kfree(t->buf);
+ kfree(t);
+ }
+ return NULL;
+}
+
+static void free_tx_struct(struct usb_tx *t)
+{
+ if (t) {
+ usb_free_urb(t->urb);
+ kfree(t->buf);
+ kfree(t);
+ }
+}
+
+static struct usb_rx *alloc_rx_struct(struct rx_cxt *rx)
+{
+ struct usb_rx *r = NULL;
+
+ r = kmalloc(sizeof(*r), GFP_ATOMIC);
+ if (r == NULL)
+ goto out;
+
+ memset(r, 0, sizeof(*r));
+
+ r->urb = usb_alloc_urb(0, GFP_ATOMIC);
+ r->buf = kmalloc(RX_BUF_SIZE, GFP_ATOMIC);
+ if (r->urb == NULL || r->buf == NULL)
+ goto out;
+
+ r->rx_cxt = rx;
+ return r;
+out:
+ if (r) {
+ usb_free_urb(r->urb);
+ kfree(r->buf);
+ kfree(r);
+ }
+ return NULL;
+}
+
+static void free_rx_struct(struct usb_rx *r)
+{
+ if (r) {
+ usb_free_urb(r->urb);
+ kfree(r->buf);
+ kfree(r);
+ }
+}
+
+/* Before this function is called, spin lock should be locked. */
+static struct usb_tx *get_tx_struct(struct tx_cxt *tx, int *no_spc)
+{
+ struct usb_tx *t;
+
+ if (list_empty(&tx->free_list)) {
+ *no_spc = 1;
+ return NULL;
+ }
+
+ t = list_entry(tx->free_list.next, struct usb_tx, list);
+ list_del(&t->list);
+
+ *no_spc = list_empty(&tx->free_list) ? 1 : 0;
+
+ return t;
+}
+
+/* Before this function is called, spin lock should be locked. */
+static void put_tx_struct(struct tx_cxt *tx, struct usb_tx *t)
+{
+ list_add_tail(&t->list, &tx->free_list);
+}
+
+/* Before this function is called, spin lock should be locked. */
+static struct usb_rx *get_rx_struct(struct rx_cxt *rx)
+{
+ struct usb_rx *r;
+
+ if (list_empty(&rx->free_list)) {
+ r = alloc_rx_struct(rx);
+ if (r == NULL)
+ return NULL;
+
+ list_add(&r->list, &rx->free_list);
+ }
+
+ r = list_entry(rx->free_list.next, struct usb_rx, list);
+ list_del(&r->list);
+ list_add_tail(&r->list, &rx->used_list);
+
+ return r;
+}
+
+/* Before this function is called, spin lock should be locked. */
+static void put_rx_struct(struct rx_cxt *rx, struct usb_rx *r)
+{
+ list_del(&r->list);
+ list_add(&r->list, &rx->free_list);
+}
+
+static int init_usb(struct usbwm_dev *udev)
+{
+ int ret = 0, i;
+ struct tx_cxt *tx = &udev->tx;
+ struct rx_cxt *rx = &udev->rx;
+ struct usb_tx *t;
+ struct usb_rx *r;
+
+ INIT_LIST_HEAD(&tx->free_list);
+ INIT_LIST_HEAD(&tx->sdu_list);
+ INIT_LIST_HEAD(&tx->hci_list);
+#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE)
+ INIT_LIST_HEAD(&tx->pending_list);
+#endif
+
+ INIT_LIST_HEAD(&rx->free_list);
+ INIT_LIST_HEAD(&rx->used_list);
+
+ spin_lock_init(&tx->lock);
+ spin_lock_init(&rx->lock);
+
+ for (i = 0; i < MAX_NR_SDU_BUF; i++) {
+ t = alloc_tx_struct(tx);
+ if (t == NULL) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ list_add(&t->list, &tx->free_list);
+ }
+
+ r = alloc_rx_struct(rx);
+ if (r == NULL) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ list_add(&r->list, &rx->free_list);
+ return ret;
+
+fail:
+ release_usb(udev);
+ return ret;
+}
+
+static void release_usb(struct usbwm_dev *udev)
+{
+ struct tx_cxt *tx = &udev->tx;
+ struct rx_cxt *rx = &udev->rx;
+ struct usb_tx *t, *t_next;
+ struct usb_rx *r, *r_next;
+
+ list_for_each_entry_safe(t, t_next, &tx->sdu_list, list) {
+ list_del(&t->list);
+ free_tx_struct(t);
+ }
+
+ list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
+ list_del(&t->list);
+ free_tx_struct(t);
+ }
+
+ list_for_each_entry_safe(t, t_next, &tx->free_list, list) {
+ list_del(&t->list);
+ free_tx_struct(t);
+ }
+
+ list_for_each_entry_safe(r, r_next, &rx->free_list, list) {
+ list_del(&r->list);
+ free_rx_struct(r);
+ }
+
+ list_for_each_entry_safe(r, r_next, &rx->used_list, list) {
+ list_del(&r->list);
+ free_rx_struct(r);
+ }
+}
+
+static void gdm_usb_send_complete(struct urb *urb)
+{
+ struct usb_tx *t = urb->context;
+ struct tx_cxt *tx = t->tx_cxt;
+ u8 *pkt = t->buf;
+ u16 cmd_evt;
+ unsigned long flags;
+
+ /* Completion by usb_unlink_urb */
+ if (urb->status == -ECONNRESET)
+ return;
+
+ spin_lock_irqsave(&tx->lock, flags);
+
+ if (t->callback)
+ t->callback(t->cb_data);
+
+ /* Delete from sdu list or hci list. */
+ list_del(&t->list);
+
+ cmd_evt = (pkt[0] << 8) | pkt[1];
+ if (cmd_evt == WIMAX_TX_SDU)
+ put_tx_struct(tx, t);
+ else
+ free_tx_struct(t);
+
+ spin_unlock_irqrestore(&tx->lock, flags);
+}
+
+static int gdm_usb_send(void *priv_dev, void *data, int len,
+ void (*cb)(void *data), void *cb_data)
+{
+ struct usbwm_dev *udev = priv_dev;
+ struct usb_device *usbdev = udev->usbdev;
+ struct tx_cxt *tx = &udev->tx;
+ struct usb_tx *t;
+ int padding = udev->padding;
+ int no_spc = 0, ret;
+ u8 *pkt = data;
+ u16 cmd_evt;
+ unsigned long flags;
+
+ if (!udev->usbdev) {
+ printk(KERN_ERR "%s: No such device\n", __func__);
+ return -ENODEV;
+ }
+
+ BUG_ON(len > TX_BUF_SIZE - padding - 1);
+
+ spin_lock_irqsave(&tx->lock, flags);
+
+ cmd_evt = (pkt[0] << 8) | pkt[1];
+ if (cmd_evt == WIMAX_TX_SDU) {
+ t = get_tx_struct(tx, &no_spc);
+ if (t == NULL) {
+ /* This case must not happen. */
+ spin_unlock_irqrestore(&tx->lock, flags);
+ return -ENOSPC;
+ }
+ list_add_tail(&t->list, &tx->sdu_list);
+ } else {
+ t = alloc_tx_struct(tx);
+ if (t == NULL) {
+ spin_unlock_irqrestore(&tx->lock, flags);
+ return -ENOMEM;
+ }
+ list_add_tail(&t->list, &tx->hci_list);
+ }
+
+ memcpy(t->buf + padding, data, len);
+ t->callback = cb;
+ t->cb_data = cb_data;
+
+ /*
+ * In some cases, USB Module of WiMax is blocked when data size is
+ * the multiple of 512. So, increment length by one in that case.
+ */
+ if ((len % 512) == 0)
+ len++;
+
+ usb_fill_bulk_urb(t->urb,
+ usbdev,
+ usb_sndbulkpipe(usbdev, 1),
+ t->buf,
+ len + padding,
+ gdm_usb_send_complete,
+ t);
+
+#ifdef DEBUG
+ hexdump("usb_send", t->buf, len + padding);
+#endif
+#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
+ if (usbdev->state & USB_STATE_SUSPENDED) {
+ list_add_tail(&t->p_list, &tx->pending_list);
+ schedule_work(&udev->pm_ws);
+ goto out;
+ }
+#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
+
+#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
+ if (udev->bw_switch) {
+ list_add_tail(&t->p_list, &tx->pending_list);
+ goto out;
+ } else if (cmd_evt == WIMAX_SCAN) {
+ struct rx_cxt *rx;
+ struct usb_rx *r;
+
+ rx = &udev->rx;
+
+ list_for_each_entry(r, &rx->used_list, list)
+ usb_unlink_urb(r->urb);
+ udev->bw_switch = 1;
+
+ spin_lock(&k_lock);
+ list_add_tail(&udev->list, &k_list);
+ spin_unlock(&k_lock);
+
+ wake_up(&k_wait);
+ }
+#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
+
+ ret = usb_submit_urb(t->urb, GFP_ATOMIC);
+ if (ret)
+ goto send_fail;
+
+#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
+ usb_mark_last_busy(usbdev);
+#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
+
+#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE)
+out:
+#endif
+ spin_unlock_irqrestore(&tx->lock, flags);
+
+ if (no_spc)
+ return -ENOSPC;
+
+ return 0;
+
+send_fail:
+ t->callback = NULL;
+ gdm_usb_send_complete(t->urb);
+ spin_unlock_irqrestore(&tx->lock, flags);
+ return ret;
+}
+
+static void gdm_usb_rcv_complete(struct urb *urb)
+{
+ struct usb_rx *r = urb->context;
+ struct rx_cxt *rx = r->rx_cxt;
+ struct usbwm_dev *udev = container_of(r->rx_cxt, struct usbwm_dev, rx);
+ struct tx_cxt *tx = &udev->tx;
+ struct usb_tx *t;
+ u16 cmd_evt;
+ unsigned long flags;
+
+#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
+ struct usb_device *dev = urb->dev;
+#endif
+
+ /* Completion by usb_unlink_urb */
+ if (urb->status == -ECONNRESET)
+ return;
+
+ spin_lock_irqsave(&tx->lock, flags);
+
+ if (!urb->status) {
+ cmd_evt = (r->buf[0] << 8) | (r->buf[1]);
+#ifdef DEBUG
+ hexdump("usb_receive", r->buf, urb->actual_length);
+#endif
+ if (cmd_evt == WIMAX_SDU_TX_FLOW) {
+ if (r->buf[4] == 0) {
+#ifdef DEBUG
+ printk(KERN_DEBUG "WIMAX ==> STOP SDU TX\n");
+#endif
+ list_for_each_entry(t, &tx->sdu_list, list)
+ usb_unlink_urb(t->urb);
+ } else if (r->buf[4] == 1) {
+#ifdef DEBUG
+ printk(KERN_DEBUG "WIMAX ==> START SDU TX\n");
+#endif
+ list_for_each_entry(t, &tx->sdu_list, list) {
+ usb_submit_urb(t->urb, GFP_ATOMIC);
+ }
+ /*
+ * If free buffer for sdu tx doesn't
+ * exist, then tx queue should not be
+ * woken. For this reason, don't pass
+ * the command, START_SDU_TX.
+ */
+ if (list_empty(&tx->free_list))
+ urb->actual_length = 0;
+ }
+ }
+ }
+
+ if (!urb->status && r->callback)
+ r->callback(r->cb_data, r->buf, urb->actual_length);
+
+ spin_lock(&rx->lock);
+ put_rx_struct(rx, r);
+ spin_unlock(&rx->lock);
+
+ spin_unlock_irqrestore(&tx->lock, flags);
+
+#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
+ usb_mark_last_busy(dev);
+#endif
+}
+
+static int gdm_usb_receive(void *priv_dev,
+ void (*cb)(void *cb_data, void *data, int len),
+ void *cb_data)
+{
+ struct usbwm_dev *udev = priv_dev;
+ struct usb_device *usbdev = udev->usbdev;
+ struct rx_cxt *rx = &udev->rx;
+ struct usb_rx *r;
+ unsigned long flags;
+
+ if (!udev->usbdev) {
+ printk(KERN_ERR "%s: No such device\n", __func__);
+ return -ENODEV;
+ }
+
+ spin_lock_irqsave(&rx->lock, flags);
+ r = get_rx_struct(rx);
+ spin_unlock_irqrestore(&rx->lock, flags);
+
+ if (r == NULL)
+ return -ENOMEM;
+
+ r->callback = cb;
+ r->cb_data = cb_data;
+
+ usb_fill_bulk_urb(r->urb,
+ usbdev,
+ usb_rcvbulkpipe(usbdev, 0x82),
+ r->buf,
+ RX_BUF_SIZE,
+ gdm_usb_rcv_complete,
+ r);
+
+ return usb_submit_urb(r->urb, GFP_ATOMIC);
+}
+
+#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
+static void do_pm_control(struct work_struct *work)
+{
+ struct usbwm_dev *udev = container_of(work, struct usbwm_dev, pm_ws);
+ struct tx_cxt *tx = &udev->tx;
+ int ret;
+ unsigned long flags;
+
+ ret = usb_autopm_get_interface(udev->intf);
+ if (!ret)
+ usb_autopm_put_interface(udev->intf);
+
+ spin_lock_irqsave(&tx->lock, flags);
+ if (!(udev->usbdev->state & USB_STATE_SUSPENDED)
+ && (!list_empty(&tx->hci_list) || !list_empty(&tx->sdu_list))) {
+ struct usb_tx *t, *temp;
+
+ list_for_each_entry_safe(t, temp, &tx->pending_list, p_list) {
+ list_del(&t->p_list);
+ ret = usb_submit_urb(t->urb, GFP_ATOMIC);
+
+ if (ret) {
+ t->callback = NULL;
+ gdm_usb_send_complete(t->urb);
+ }
+ }
+ }
+ spin_unlock_irqrestore(&tx->lock, flags);
+}
+#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
+
+static int gdm_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ int ret = 0;
+ u8 bConfigurationValue;
+ struct phy_dev *phy_dev = NULL;
+ struct usbwm_dev *udev = NULL;
+ u16 idVendor, idProduct, bcdDevice;
+
+ struct usb_device *usbdev = interface_to_usbdev(intf);
+
+ usb_get_dev(usbdev);
+ bConfigurationValue = usbdev->actconfig->desc.bConfigurationValue;
+
+ /*USB description is set up with Little-Endian*/
+ idVendor = L2H(usbdev->descriptor.idVendor);
+ idProduct = L2H(usbdev->descriptor.idProduct);
+ bcdDevice = L2H(usbdev->descriptor.bcdDevice);
+
+ printk(KERN_INFO "Found GDM USB VID = 0x%04x PID = 0x%04x...\n",
+ idVendor, idProduct);
+ printk(KERN_INFO "GCT WiMax driver version %s\n", DRIVER_VERSION);
+
+
+ if (idProduct == EMERGENCY_PID) {
+ ret = usb_emergency(usbdev);
+ goto out;
+ }
+
+ /* Support for EEPROM bootloader */
+ if (bConfigurationValue == DOWNLOAD_CONF_VALUE ||
+ idProduct & B_DOWNLOAD) {
+ ret = usb_boot(usbdev, bcdDevice);
+ goto out;
+ }
+
+ phy_dev = kmalloc(sizeof(*phy_dev), GFP_KERNEL);
+ if (phy_dev == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ udev = kmalloc(sizeof(*udev), GFP_KERNEL);
+ if (udev == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memset(phy_dev, 0, sizeof(*phy_dev));
+ memset(udev, 0, sizeof(*udev));
+
+ if (idProduct == 0x7205 || idProduct == 0x7206)
+ udev->padding = GDM7205_PADDING;
+ else
+ udev->padding = 0;
+
+ phy_dev->priv_dev = (void *)udev;
+ phy_dev->send_func = gdm_usb_send;
+ phy_dev->rcv_func = gdm_usb_receive;
+
+ ret = init_usb(udev);
+ if (ret < 0)
+ goto out;
+
+ udev->usbdev = usbdev;
+
+#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
+ udev->intf = intf;
+
+ intf->needs_remote_wakeup = 1;
+ device_init_wakeup(&intf->dev, 1);
+
+ pm_runtime_set_autosuspend_delay(&usbdev->dev, 10 * 1000); /* msec */
+
+ INIT_WORK(&udev->pm_ws, do_pm_control);
+#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
+
+ ret = register_wimax_device(phy_dev, &intf->dev);
+
+out:
+ if (ret) {
+ kfree(phy_dev);
+ kfree(udev);
+ }
+ usb_set_intfdata(intf, phy_dev);
+ return ret;
+}
+
+static void gdm_usb_disconnect(struct usb_interface *intf)
+{
+ u8 bConfigurationValue;
+ struct phy_dev *phy_dev;
+ struct usbwm_dev *udev;
+ u16 idProduct;
+ struct usb_device *usbdev = interface_to_usbdev(intf);
+
+ bConfigurationValue = usbdev->actconfig->desc.bConfigurationValue;
+ phy_dev = usb_get_intfdata(intf);
+
+ /*USB description is set up with Little-Endian*/
+ idProduct = L2H(usbdev->descriptor.idProduct);
+
+ if (idProduct != EMERGENCY_PID &&
+ bConfigurationValue != DOWNLOAD_CONF_VALUE &&
+ (idProduct & B_DOWNLOAD) == 0) {
+ udev = phy_dev->priv_dev;
+ udev->usbdev = NULL;
+
+ unregister_wimax_device(phy_dev);
+ release_usb(udev);
+ kfree(udev);
+ kfree(phy_dev);
+ }
+
+ usb_put_dev(usbdev);
+}
+
+#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
+static int gdm_suspend(struct usb_interface *intf, pm_message_t pm_msg)
+{
+ struct phy_dev *phy_dev;
+ struct usbwm_dev *udev;
+ struct rx_cxt *rx;
+ struct usb_rx *r;
+
+ phy_dev = usb_get_intfdata(intf);
+ udev = phy_dev->priv_dev;
+ rx = &udev->rx;
+
+ list_for_each_entry(r, &rx->used_list, list)
+ usb_unlink_urb(r->urb);
+
+ return 0;
+}
+
+static int gdm_resume(struct usb_interface *intf)
+{
+ struct phy_dev *phy_dev;
+ struct usbwm_dev *udev;
+ struct rx_cxt *rx;
+ struct usb_rx *r;
+
+ phy_dev = usb_get_intfdata(intf);
+ udev = phy_dev->priv_dev;
+ rx = &udev->rx;
+
+ list_for_each_entry(r, &rx->used_list, list)
+ usb_submit_urb(r->urb, GFP_ATOMIC);
+
+ return 0;
+}
+
+#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
+
+#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
+static int k_mode_thread(void *arg)
+{
+ struct usbwm_dev *udev;
+ struct tx_cxt *tx;
+ struct rx_cxt *rx;
+ struct usb_tx *t, *temp;
+ struct usb_rx *r;
+ unsigned long flags, flags2, expire;
+ int ret;
+
+ daemonize("k_mode_wimax");
+
+ while (!k_mode_stop) {
+
+ spin_lock_irqsave(&k_lock, flags2);
+ while (!list_empty(&k_list)) {
+
+ udev = list_entry(k_list.next, struct usbwm_dev, list);
+ tx = &udev->tx;
+ rx = &udev->rx;
+
+ list_del(&udev->list);
+ spin_unlock_irqrestore(&k_lock, flags2);
+
+ expire = jiffies + K_WAIT_TIME;
+ while (jiffies < expire)
+ schedule_timeout(K_WAIT_TIME);
+
+ list_for_each_entry(r, &rx->used_list, list)
+ usb_submit_urb(r->urb, GFP_ATOMIC);
+
+ spin_lock_irqsave(&tx->lock, flags);
+
+ list_for_each_entry_safe(t, temp, &tx->pending_list,
+ p_list) {
+ list_del(&t->p_list);
+ ret = usb_submit_urb(t->urb, GFP_ATOMIC);
+
+ if (ret) {
+ t->callback = NULL;
+ gdm_usb_send_complete(t->urb);
+ }
+ }
+
+ udev->bw_switch = 0;
+ spin_unlock_irqrestore(&tx->lock, flags);
+
+ spin_lock_irqsave(&k_lock, flags2);
+ }
+ spin_unlock_irqrestore(&k_lock, flags2);
+
+ interruptible_sleep_on(&k_wait);
+ }
+ return 0;
+}
+#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
+
+static struct usb_driver gdm_usb_driver = {
+ .name = "gdm_wimax",
+ .probe = gdm_usb_probe,
+ .disconnect = gdm_usb_disconnect,
+ .id_table = id_table,
+#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
+ .supports_autosuspend = 1,
+ .suspend = gdm_suspend,
+ .resume = gdm_resume,
+ .reset_resume = gdm_resume,
+#endif
+};
+
+static int __init usb_gdm_wimax_init(void)
+{
+#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
+ kernel_thread(k_mode_thread, NULL, CLONE_KERNEL);
+#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
+ return usb_register(&gdm_usb_driver);
+}
+
+static void __exit usb_gdm_wimax_exit(void)
+{
+#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
+ k_mode_stop = 1;
+ wake_up(&k_wait);
+#endif
+ usb_deregister(&gdm_usb_driver);
+}
+
+module_init(usb_gdm_wimax_init);
+module_exit(usb_gdm_wimax_exit);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_DESCRIPTION("GCT WiMax Device Driver");
+MODULE_AUTHOR("Ethan Park");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gdm72xx/gdm_usb.h b/drivers/staging/gdm72xx/gdm_usb.h
new file mode 100644
index 000000000000..ecb891f6a599
--- /dev/null
+++ b/drivers/staging/gdm72xx/gdm_usb.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __GDM_USB_H__
+#define __GDM_USB_H__
+
+#include <linux/types.h>
+#include <linux/usb.h>
+#include <linux/list.h>
+
+#define B_DIFF_DL_DRV (1<<4)
+#define B_DOWNLOAD (1 << 5)
+#define MAX_NR_SDU_BUF 64
+
+struct usb_tx {
+ struct list_head list;
+#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE)
+ struct list_head p_list;
+#endif
+ struct tx_cxt *tx_cxt;
+
+ struct urb *urb;
+ u8 *buf;
+
+ void (*callback)(void *cb_data);
+ void *cb_data;
+};
+
+struct tx_cxt {
+ struct list_head free_list;
+ struct list_head sdu_list;
+ struct list_head hci_list;
+#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE)
+ struct list_head pending_list;
+#endif
+
+ spinlock_t lock;
+};
+
+struct usb_rx {
+ struct list_head list;
+ struct rx_cxt *rx_cxt;
+
+ struct urb *urb;
+ u8 *buf;
+
+ void (*callback)(void *cb_data, void *data, int len);
+ void *cb_data;
+};
+
+struct rx_cxt {
+ struct list_head free_list;
+ struct list_head used_list;
+ spinlock_t lock;
+};
+
+struct usbwm_dev {
+ struct usb_device *usbdev;
+#ifdef CONFIG_WIMAX_GDM72XX_USB_PM
+ struct work_struct pm_ws;
+
+ struct usb_interface *intf;
+#endif
+#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
+ int bw_switch;
+ struct list_head list;
+#endif
+
+ struct tx_cxt tx;
+ struct rx_cxt rx;
+
+ int padding;
+};
+
+#endif /* __GDM_USB_H__ */
diff --git a/drivers/staging/gdm72xx/gdm_wimax.c b/drivers/staging/gdm72xx/gdm_wimax.c
new file mode 100644
index 000000000000..f1936b92533b
--- /dev/null
+++ b/drivers/staging/gdm72xx/gdm_wimax.c
@@ -0,0 +1,1026 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/version.h>
+#include <linux/etherdevice.h>
+#include <asm/byteorder.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include <linux/in.h>
+
+#include "gdm_wimax.h"
+#include "hci.h"
+#include "wm_ioctl.h"
+#include "netlink_k.h"
+
+#define gdm_wimax_send(n, d, l) \
+ (n->phy_dev->send_func)(n->phy_dev->priv_dev, d, l, NULL, NULL)
+#define gdm_wimax_send_with_cb(n, d, l, c, b) \
+ (n->phy_dev->send_func)(n->phy_dev->priv_dev, d, l, c, b)
+#define gdm_wimax_rcv_with_cb(n, c, b) \
+ (n->phy_dev->rcv_func)(n->phy_dev->priv_dev, c, b)
+
+#define EVT_MAX_SIZE 2048
+
+struct evt_entry {
+ struct list_head list;
+ struct net_device *dev;
+ char evt_data[EVT_MAX_SIZE];
+ int size;
+};
+
+static void __gdm_wimax_event_send(struct work_struct *work);
+static inline struct evt_entry *alloc_event_entry(void);
+static inline void free_event_entry(struct evt_entry *e);
+static struct evt_entry *get_event_entry(void);
+static void put_event_entry(struct evt_entry *e);
+
+static struct {
+ int ref_cnt;
+ struct sock *sock;
+ struct list_head evtq;
+ spinlock_t evt_lock;
+
+ struct list_head freeq;
+ struct work_struct ws;
+} wm_event;
+
+static u8 gdm_wimax_macaddr[6] = {0x00, 0x0a, 0x3b, 0xf0, 0x01, 0x30};
+
+static void gdm_wimax_ind_fsm_update(struct net_device *dev, struct fsm_s *fsm);
+static void gdm_wimax_ind_if_updown(struct net_device *dev, int if_up);
+
+#if defined(DEBUG_SDU)
+static void printk_hex(u8 *buf, u32 size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (i && i % 16 == 0)
+ printk(KERN_DEBUG "\n%02x ", *buf++);
+ else
+ printk(KERN_DEBUG "%02x ", *buf++);
+ }
+
+ printk(KERN_DEBUG "\n");
+}
+
+static const char *get_protocol_name(u16 protocol)
+{
+ static char buf[32];
+ const char *name = "-";
+
+ switch (protocol) {
+ case ETH_P_ARP:
+ name = "ARP";
+ break;
+ case ETH_P_IP:
+ name = "IP";
+ break;
+ case ETH_P_IPV6:
+ name = "IPv6";
+ break;
+ }
+
+ sprintf(buf, "0x%04x(%s)", protocol, name);
+ return buf;
+}
+
+static const char *get_ip_protocol_name(u8 ip_protocol)
+{
+ static char buf[32];
+ const char *name = "-";
+
+ switch (ip_protocol) {
+ case IPPROTO_TCP:
+ name = "TCP";
+ break;
+ case IPPROTO_UDP:
+ name = "UDP";
+ break;
+ case IPPROTO_ICMP:
+ name = "ICMP";
+ break;
+ }
+
+ sprintf(buf, "%u(%s)", ip_protocol, name);
+ return buf;
+}
+
+static const char *get_port_name(u16 port)
+{
+ static char buf[32];
+ const char *name = "-";
+
+ switch (port) {
+ case 67:
+ name = "DHCP-Server";
+ break;
+ case 68:
+ name = "DHCP-Client";
+ break;
+ case 69:
+ name = "TFTP";
+ break;
+ }
+
+ sprintf(buf, "%u(%s)", port, name);
+ return buf;
+}
+
+static void dump_eth_packet(const char *title, u8 *data, int len)
+{
+ struct iphdr *ih = NULL;
+ struct udphdr *uh = NULL;
+ u16 protocol = 0;
+ u8 ip_protocol = 0;
+ u16 port = 0;
+
+ protocol = (data[12]<<8) | data[13];
+ ih = (struct iphdr *) (data+ETH_HLEN);
+
+ if (protocol == ETH_P_IP) {
+ uh = (struct udphdr *) ((char *)ih + sizeof(struct iphdr));
+ ip_protocol = ih->protocol;
+ port = ntohs(uh->dest);
+ } else if (protocol == ETH_P_IPV6) {
+ struct ipv6hdr *i6h = (struct ipv6hdr *) data;
+ uh = (struct udphdr *) ((char *)i6h + sizeof(struct ipv6hdr));
+ ip_protocol = i6h->nexthdr;
+ port = ntohs(uh->dest);
+ }
+
+ printk(KERN_DEBUG "[%s] len=%d, %s, %s, %s\n",
+ title, len,
+ get_protocol_name(protocol),
+ get_ip_protocol_name(ip_protocol),
+ get_port_name(port));
+
+ #if 1
+ if (!(data[0] == 0xff && data[1] == 0xff)) {
+ if (protocol == ETH_P_IP) {
+ printk(KERN_DEBUG " src=%u.%u.%u.%u\n",
+ NIPQUAD(ih->saddr));
+ } else if (protocol == ETH_P_IPV6) {
+ #ifdef NIP6
+ printk(KERN_DEBUG " src=%x:%x:%x:%x:%x:%x:%x:%x\n",
+ NIP6(ih->saddr));
+ #else
+ printk(KERN_DEBUG " src=%pI6\n", &ih->saddr);
+ #endif
+ }
+ }
+ #endif
+
+ #if (DUMP_PACKET & DUMP_SDU_ALL)
+ printk_hex(data, len);
+ #else
+ #if (DUMP_PACKET & DUMP_SDU_ARP)
+ if (protocol == ETH_P_ARP)
+ printk_hex(data, len);
+ #endif
+ #if (DUMP_PACKET & DUMP_SDU_IP)
+ if (protocol == ETH_P_IP || protocol == ETH_P_IPV6)
+ printk_hex(data, len);
+ #else
+ #if (DUMP_PACKET & DUMP_SDU_IP_TCP)
+ if (ip_protocol == IPPROTO_TCP)
+ printk_hex(data, len);
+ #endif
+ #if (DUMP_PACKET & DUMP_SDU_IP_UDP)
+ if (ip_protocol == IPPROTO_UDP)
+ printk_hex(data, len);
+ #endif
+ #if (DUMP_PACKET & DUMP_SDU_IP_ICMP)
+ if (ip_protocol == IPPROTO_ICMP)
+ printk_hex(data, len);
+ #endif
+ #endif
+ #endif
+}
+#endif
+
+
+static inline int gdm_wimax_header(struct sk_buff **pskb)
+{
+ u16 buf[HCI_HEADER_SIZE / sizeof(u16)];
+ struct sk_buff *skb = *pskb;
+ int ret = 0;
+
+ if (unlikely(skb_headroom(skb) < HCI_HEADER_SIZE)) {
+ struct sk_buff *skb2;
+
+ skb2 = skb_realloc_headroom(skb, HCI_HEADER_SIZE);
+ if (skb2 == NULL)
+ return -ENOMEM;
+ if (skb->sk)
+ skb_set_owner_w(skb2, skb->sk);
+ kfree_skb(skb);
+ skb = skb2;
+ }
+
+ skb_push(skb, HCI_HEADER_SIZE);
+ buf[0] = H2B(WIMAX_TX_SDU);
+ buf[1] = H2B(skb->len - HCI_HEADER_SIZE);
+ memcpy(skb->data, buf, HCI_HEADER_SIZE);
+
+ *pskb = skb;
+ return ret;
+}
+
+static void gdm_wimax_event_rcv(struct net_device *dev, u16 type, void *msg,
+ int len)
+{
+ struct nic *nic = netdev_priv(dev);
+
+ #if defined(DEBUG_HCI)
+ u8 *buf = (u8 *) msg;
+ u16 hci_cmd = (buf[0]<<8) | buf[1];
+ u16 hci_len = (buf[2]<<8) | buf[3];
+ printk(KERN_DEBUG "H=>D: 0x%04x(%d)\n", hci_cmd, hci_len);
+ #endif
+
+ gdm_wimax_send(nic, msg, len);
+}
+
+static int gdm_wimax_event_init(void)
+{
+ if (wm_event.ref_cnt == 0) {
+ wm_event.sock = netlink_init(NETLINK_WIMAX,
+ gdm_wimax_event_rcv);
+ INIT_LIST_HEAD(&wm_event.evtq);
+ INIT_LIST_HEAD(&wm_event.freeq);
+ INIT_WORK(&wm_event.ws, __gdm_wimax_event_send);
+ spin_lock_init(&wm_event.evt_lock);
+ }
+
+ if (wm_event.sock) {
+ wm_event.ref_cnt++;
+ return 0;
+ }
+
+ printk(KERN_ERR "Creating WiMax Event netlink is failed\n");
+ return -1;
+}
+
+static void gdm_wimax_event_exit(void)
+{
+ if (wm_event.sock && --wm_event.ref_cnt == 0) {
+ struct evt_entry *e, *temp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&wm_event.evt_lock, flags);
+
+ list_for_each_entry_safe(e, temp, &wm_event.evtq, list) {
+ list_del(&e->list);
+ free_event_entry(e);
+ }
+ list_for_each_entry_safe(e, temp, &wm_event.freeq, list) {
+ list_del(&e->list);
+ free_event_entry(e);
+ }
+
+ spin_unlock_irqrestore(&wm_event.evt_lock, flags);
+ netlink_exit(wm_event.sock);
+ wm_event.sock = NULL;
+ }
+}
+
+static inline struct evt_entry *alloc_event_entry(void)
+{
+ return kmalloc(sizeof(struct evt_entry), GFP_ATOMIC);
+}
+
+static inline void free_event_entry(struct evt_entry *e)
+{
+ kfree(e);
+}
+
+static struct evt_entry *get_event_entry(void)
+{
+ struct evt_entry *e;
+
+ if (list_empty(&wm_event.freeq))
+ e = alloc_event_entry();
+ else {
+ e = list_entry(wm_event.freeq.next, struct evt_entry, list);
+ list_del(&e->list);
+ }
+
+ return e;
+}
+
+static void put_event_entry(struct evt_entry *e)
+{
+ BUG_ON(!e);
+
+ list_add_tail(&e->list, &wm_event.freeq);
+}
+
+static void __gdm_wimax_event_send(struct work_struct *work)
+{
+ int idx;
+ unsigned long flags;
+ struct evt_entry *e;
+
+ spin_lock_irqsave(&wm_event.evt_lock, flags);
+
+ while (!list_empty(&wm_event.evtq)) {
+ e = list_entry(wm_event.evtq.next, struct evt_entry, list);
+ spin_unlock_irqrestore(&wm_event.evt_lock, flags);
+
+ sscanf(e->dev->name, "wm%d", &idx);
+ netlink_send(wm_event.sock, idx, 0, e->evt_data, e->size);
+
+ spin_lock_irqsave(&wm_event.evt_lock, flags);
+ list_del(&e->list);
+ put_event_entry(e);
+ }
+
+ spin_unlock_irqrestore(&wm_event.evt_lock, flags);
+}
+
+static int gdm_wimax_event_send(struct net_device *dev, char *buf, int size)
+{
+ struct evt_entry *e;
+ unsigned long flags;
+
+ #if defined(DEBUG_HCI)
+ u16 hci_cmd = ((u8)buf[0]<<8) | (u8)buf[1];
+ u16 hci_len = ((u8)buf[2]<<8) | (u8)buf[3];
+ printk(KERN_DEBUG "D=>H: 0x%04x(%d)\n", hci_cmd, hci_len);
+ #endif
+
+ spin_lock_irqsave(&wm_event.evt_lock, flags);
+
+ e = get_event_entry();
+ if (!e) {
+ printk(KERN_ERR "%s: No memory for event\n", __func__);
+ spin_unlock_irqrestore(&wm_event.evt_lock, flags);
+ return -ENOMEM;
+ }
+
+ e->dev = dev;
+ e->size = size;
+ memcpy(e->evt_data, buf, size);
+
+ list_add_tail(&e->list, &wm_event.evtq);
+ spin_unlock_irqrestore(&wm_event.evt_lock, flags);
+
+ schedule_work(&wm_event.ws);
+
+ return 0;
+}
+
+static void tx_complete(void *arg)
+{
+ struct nic *nic = arg;
+
+ if (netif_queue_stopped(nic->netdev))
+ netif_wake_queue(nic->netdev);
+}
+
+int gdm_wimax_send_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ int ret = 0;
+ struct nic *nic = netdev_priv(dev);
+
+ ret = gdm_wimax_send_with_cb(nic, skb->data, skb->len, tx_complete,
+ nic);
+ if (ret == -ENOSPC) {
+ netif_stop_queue(dev);
+ ret = 0;
+ }
+
+ if (ret) {
+ skb_pull(skb, HCI_HEADER_SIZE);
+ return ret;
+ }
+
+ nic->stats.tx_packets++;
+ nic->stats.tx_bytes += skb->len - HCI_HEADER_SIZE;
+ kfree_skb(skb);
+ return ret;
+}
+
+static int gdm_wimax_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ int ret = 0;
+ struct nic *nic = netdev_priv(dev);
+ struct fsm_s *fsm = (struct fsm_s *) nic->sdk_data[SIOC_DATA_FSM].buf;
+
+ #if defined(DEBUG_SDU)
+ dump_eth_packet("TX", skb->data, skb->len);
+ #endif
+
+ ret = gdm_wimax_header(&skb);
+ if (ret < 0) {
+ skb_pull(skb, HCI_HEADER_SIZE);
+ return ret;
+ }
+
+ #if !defined(LOOPBACK_TEST)
+ if (!fsm)
+ printk(KERN_ERR "ASSERTION ERROR: fsm is NULL!!\n");
+ else if (fsm->m_status != M_CONNECTED) {
+ printk(KERN_EMERG "ASSERTION ERROR: Device is NOT ready. status=%d\n",
+ fsm->m_status);
+ kfree_skb(skb);
+ return 0;
+ }
+ #endif
+
+#if defined(CONFIG_WIMAX_GDM72XX_QOS)
+ ret = gdm_qos_send_hci_pkt(skb, dev);
+#else
+ ret = gdm_wimax_send_tx(skb, dev);
+#endif
+ return ret;
+}
+
+static int gdm_wimax_set_config(struct net_device *dev, struct ifmap *map)
+{
+ if (dev->flags & IFF_UP)
+ return -EBUSY;
+
+ return 0;
+}
+
+static void __gdm_wimax_set_mac_addr(struct net_device *dev, char *mac_addr)
+{
+ u16 hci_pkt_buf[32 / sizeof(u16)];
+ u8 *pkt = (u8 *) &hci_pkt_buf[0];
+ struct nic *nic = netdev_priv(dev);
+
+ /* Since dev is registered as a ethernet device,
+ * ether_setup has made dev->addr_len to be ETH_ALEN
+ */
+ memcpy(dev->dev_addr, mac_addr, dev->addr_len);
+
+ /* Let lower layer know of this change by sending
+ * SetInformation(MAC Address)
+ */
+ hci_pkt_buf[0] = H2B(WIMAX_SET_INFO); /* cmd_evt */
+ hci_pkt_buf[1] = H2B(8); /* size */
+ pkt[4] = 0; /* T */
+ pkt[5] = 6; /* L */
+ memcpy(pkt + 6, mac_addr, dev->addr_len); /* V */
+
+ gdm_wimax_send(nic, pkt, HCI_HEADER_SIZE + 8);
+}
+
+/* A driver function */
+static int gdm_wimax_set_mac_addr(struct net_device *dev, void *p)
+{
+ struct sockaddr *addr = p;
+
+ if (netif_running(dev))
+ return -EBUSY;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ __gdm_wimax_set_mac_addr(dev, addr->sa_data);
+
+ return 0;
+}
+
+static struct net_device_stats *gdm_wimax_stats(struct net_device *dev)
+{
+ struct nic *nic = netdev_priv(dev);
+
+ return &nic->stats;
+}
+
+static int gdm_wimax_open(struct net_device *dev)
+{
+ struct nic *nic = netdev_priv(dev);
+ struct fsm_s *fsm = (struct fsm_s *) nic->sdk_data[SIOC_DATA_FSM].buf;
+
+ netif_start_queue(dev);
+
+ if (fsm && fsm->m_status != M_INIT)
+ gdm_wimax_ind_if_updown(dev, 1);
+ return 0;
+}
+
+static int gdm_wimax_close(struct net_device *dev)
+{
+ struct nic *nic = netdev_priv(dev);
+ struct fsm_s *fsm = (struct fsm_s *) nic->sdk_data[SIOC_DATA_FSM].buf;
+
+ netif_stop_queue(dev);
+
+ if (fsm && fsm->m_status != M_INIT)
+ gdm_wimax_ind_if_updown(dev, 0);
+ return 0;
+}
+
+static void kdelete(void **buf)
+{
+ if (buf && *buf) {
+ kfree(*buf);
+ *buf = NULL;
+ }
+}
+
+static int gdm_wimax_ioctl_get_data(struct data_s *dst, struct data_s *src)
+{
+ int size;
+
+ size = dst->size < src->size ? dst->size : src->size;
+
+ dst->size = size;
+ if (src->size) {
+ if (!dst->buf)
+ return -EINVAL;
+ if (copy_to_user(dst->buf, src->buf, size))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int gdm_wimax_ioctl_set_data(struct data_s *dst, struct data_s *src)
+{
+ if (!src->size) {
+ dst->size = 0;
+ return 0;
+ }
+
+ if (!src->buf)
+ return -EINVAL;
+
+ if (!(dst->buf && dst->size == src->size)) {
+ kdelete(&dst->buf);
+ dst->buf = kmalloc(src->size, GFP_KERNEL);
+ if (dst->buf == NULL)
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(dst->buf, src->buf, src->size)) {
+ kdelete(&dst->buf);
+ return -EFAULT;
+ }
+ dst->size = src->size;
+ return 0;
+}
+
+static void gdm_wimax_cleanup_ioctl(struct net_device *dev)
+{
+ struct nic *nic = netdev_priv(dev);
+ int i;
+
+ for (i = 0; i < SIOC_DATA_MAX; i++)
+ kdelete(&nic->sdk_data[i].buf);
+}
+
+static void gdm_update_fsm(struct net_device *dev, struct fsm_s *new_fsm)
+{
+ struct nic *nic = netdev_priv(dev);
+ struct fsm_s *cur_fsm =
+ (struct fsm_s *) nic->sdk_data[SIOC_DATA_FSM].buf;
+
+ if (!cur_fsm)
+ return;
+
+ if (cur_fsm->m_status != new_fsm->m_status ||
+ cur_fsm->c_status != new_fsm->c_status) {
+ if (new_fsm->m_status == M_CONNECTED)
+ netif_carrier_on(dev);
+ else if (cur_fsm->m_status == M_CONNECTED) {
+ netif_carrier_off(dev);
+ #if defined(CONFIG_WIMAX_GDM72XX_QOS)
+ gdm_qos_release_list(nic);
+ #endif
+ }
+ gdm_wimax_ind_fsm_update(dev, new_fsm);
+ }
+}
+
+static int gdm_wimax_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct wm_req_s *req = (struct wm_req_s *) ifr;
+ struct nic *nic = netdev_priv(dev);
+ int ret;
+
+ if (cmd != SIOCWMIOCTL)
+ return -EOPNOTSUPP;
+
+ switch (req->cmd) {
+ case SIOCG_DATA:
+ case SIOCS_DATA:
+ if (req->data_id >= SIOC_DATA_MAX) {
+ printk(KERN_ERR
+ "%s error: data-index(%d) is invalid!!\n",
+ __func__, req->data_id);
+ return -EOPNOTSUPP;
+ }
+ if (req->cmd == SIOCG_DATA) {
+ ret = gdm_wimax_ioctl_get_data(&req->data,
+ &nic->sdk_data[req->data_id]);
+ if (ret < 0)
+ return ret;
+ } else if (req->cmd == SIOCS_DATA) {
+ if (req->data_id == SIOC_DATA_FSM) {
+ /*NOTE: gdm_update_fsm should be called
+ before gdm_wimax_ioctl_set_data is called*/
+ gdm_update_fsm(dev,
+ (struct fsm_s *) req->data.buf);
+ }
+ ret = gdm_wimax_ioctl_set_data(
+ &nic->sdk_data[req->data_id], &req->data);
+ if (ret < 0)
+ return ret;
+ }
+ break;
+ default:
+ printk(KERN_ERR "%s: %x unknown ioctl\n", __func__, cmd);
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static void gdm_wimax_prepare_device(struct net_device *dev)
+{
+ struct nic *nic = netdev_priv(dev);
+ u16 buf[32 / sizeof(u16)];
+ struct hci_s *hci = (struct hci_s *) buf;
+ u16 len = 0;
+ u32 val = 0;
+
+ #define BIT_MULTI_CS 0
+ #define BIT_WIMAX 1
+ #define BIT_QOS 2
+ #define BIT_AGGREGATION 3
+
+ /* GetInformation mac address */
+ len = 0;
+ hci->cmd_evt = H2B(WIMAX_GET_INFO);
+ hci->data[len++] = TLV_T(T_MAC_ADDRESS);
+ hci->length = H2B(len);
+ gdm_wimax_send(nic, hci, HCI_HEADER_SIZE+len);
+
+ val = (1<<BIT_WIMAX) | (1<<BIT_MULTI_CS);
+ #if defined(CONFIG_WIMAX_GDM72XX_QOS)
+ val |= (1<<BIT_QOS);
+ #endif
+ #if defined(CONFIG_WIMAX_GDM72XX_WIMAX2)
+ val |= (1<<BIT_AGGREGATION);
+ #endif
+
+ /* Set capability */
+ len = 0;
+ hci->cmd_evt = H2B(WIMAX_SET_INFO);
+ hci->data[len++] = TLV_T(T_CAPABILITY);
+ hci->data[len++] = TLV_L(T_CAPABILITY);
+ val = DH2B(val);
+ memcpy(&hci->data[len], &val, TLV_L(T_CAPABILITY));
+ len += TLV_L(T_CAPABILITY);
+ hci->length = H2B(len);
+ gdm_wimax_send(nic, hci, HCI_HEADER_SIZE+len);
+
+ printk(KERN_INFO "GDM WiMax Set CAPABILITY: 0x%08X\n", DB2H(val));
+}
+
+static int gdm_wimax_hci_get_tlv(u8 *buf, u8 *T, u16 *L, u8 **V)
+{
+ #define __U82U16(b) ((u16)((u8 *)(b))[0] | ((u16)((u8 *)(b))[1] << 8))
+ int next_pos;
+
+ *T = buf[0];
+ if (buf[1] == 0x82) {
+ *L = B2H(__U82U16(&buf[2]));
+ next_pos = 1/*type*/+3/*len*/;
+ } else {
+ *L = buf[1];
+ next_pos = 1/*type*/+1/*len*/;
+ }
+ *V = &buf[next_pos];
+
+ next_pos += *L/*length of val*/;
+ return next_pos;
+}
+
+static int gdm_wimax_get_prepared_info(struct net_device *dev, char *buf,
+ int len)
+{
+ u8 T, *V;
+ u16 L;
+ u16 cmd_evt, cmd_len;
+ int pos = HCI_HEADER_SIZE;
+
+ cmd_evt = B2H(*(u16 *)&buf[0]);
+ cmd_len = B2H(*(u16 *)&buf[2]);
+
+ if (len < cmd_len + HCI_HEADER_SIZE) {
+ printk(KERN_ERR "%s: invalid length [%d/%d]\n", __func__,
+ cmd_len + HCI_HEADER_SIZE, len);
+ return -1;
+ }
+
+ if (cmd_evt == WIMAX_GET_INFO_RESULT) {
+ if (cmd_len < 2) {
+ printk(KERN_ERR "%s: len is too short [%x/%d]\n",
+ __func__, cmd_evt, len);
+ return -1;
+ }
+
+ pos += gdm_wimax_hci_get_tlv(&buf[pos], &T, &L, &V);
+ if (T == TLV_T(T_MAC_ADDRESS)) {
+ if (L != dev->addr_len) {
+ printk(KERN_ERR
+ "%s Invalid inofrmation result T/L "
+ "[%x/%d]\n", __func__, T, L);
+ return -1;
+ }
+ printk(KERN_INFO
+ "MAC change [%02x:%02x:%02x:%02x:%02x:%02x]"
+ "->[%02x:%02x:%02x:%02x:%02x:%02x]\n",
+ dev->dev_addr[0], dev->dev_addr[1],
+ dev->dev_addr[2], dev->dev_addr[3],
+ dev->dev_addr[4], dev->dev_addr[5],
+ V[0], V[1], V[2], V[3], V[4], V[5]);
+ memcpy(dev->dev_addr, V, dev->addr_len);
+ return 1;
+ }
+ }
+
+ gdm_wimax_event_send(dev, buf, len);
+ return 0;
+}
+
+static void gdm_wimax_netif_rx(struct net_device *dev, char *buf, int len)
+{
+ struct nic *nic = netdev_priv(dev);
+ struct sk_buff *skb;
+ int ret;
+
+ #if defined(DEBUG_SDU)
+ dump_eth_packet("RX", buf, len);
+ #endif
+
+ skb = dev_alloc_skb(len + 2);
+ if (!skb) {
+ printk(KERN_ERR "%s: dev_alloc_skb failed!\n", __func__);
+ return;
+ }
+ skb_reserve(skb, 2);
+
+ nic->stats.rx_packets++;
+ nic->stats.rx_bytes += len;
+
+ memcpy(skb_put(skb, len), buf, len);
+
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev); /* what will happen? */
+
+ ret = in_interrupt() ? netif_rx(skb) : netif_rx_ni(skb);
+ if (ret == NET_RX_DROP)
+ printk(KERN_ERR "%s skb dropped\n", __func__);
+}
+
+static void gdm_wimax_transmit_aggr_pkt(struct net_device *dev, char *buf,
+ int len)
+{
+ #define HCI_PADDING_BYTE 4
+ #define HCI_RESERVED_BYTE 4
+ struct hci_s *hci;
+ int length;
+
+ while (len > 0) {
+ hci = (struct hci_s *) buf;
+
+ if (B2H(hci->cmd_evt) != WIMAX_RX_SDU) {
+ printk(KERN_ERR "Wrong cmd_evt(0x%04X)\n",
+ B2H(hci->cmd_evt));
+ break;
+ }
+
+ length = B2H(hci->length);
+ gdm_wimax_netif_rx(dev, hci->data, length);
+
+ if (length & 0x3) {
+ /* Add padding size */
+ length += HCI_PADDING_BYTE - (length & 0x3);
+ }
+
+ length += HCI_HEADER_SIZE + HCI_RESERVED_BYTE;
+ len -= length;
+ buf += length;
+ }
+}
+
+static void gdm_wimax_transmit_pkt(struct net_device *dev, char *buf, int len)
+{
+ #if defined(CONFIG_WIMAX_GDM72XX_QOS)
+ struct nic *nic = netdev_priv(dev);
+ #endif
+ u16 cmd_evt, cmd_len;
+
+ /* This code is added for certain rx packet to be ignored. */
+ if (len == 0)
+ return;
+
+ cmd_evt = B2H(*(u16 *)&buf[0]);
+ cmd_len = B2H(*(u16 *)&buf[2]);
+
+ if (len < cmd_len + HCI_HEADER_SIZE) {
+ if (len)
+ printk(KERN_ERR "%s: invalid length [%d/%d]\n",
+ __func__, cmd_len + HCI_HEADER_SIZE, len);
+ return;
+ }
+
+ switch (cmd_evt) {
+ case WIMAX_RX_SDU_AGGR:
+ gdm_wimax_transmit_aggr_pkt(dev, &buf[HCI_HEADER_SIZE],
+ cmd_len);
+ break;
+ case WIMAX_RX_SDU:
+ gdm_wimax_netif_rx(dev, &buf[HCI_HEADER_SIZE], cmd_len);
+ break;
+ #if defined(CONFIG_WIMAX_GDM72XX_QOS)
+ case WIMAX_EVT_MODEM_REPORT:
+ gdm_recv_qos_hci_packet(nic, buf, len);
+ break;
+ #endif
+ case WIMAX_SDU_TX_FLOW:
+ if (buf[4] == 0) {
+ if (!netif_queue_stopped(dev))
+ netif_stop_queue(dev);
+ } else if (buf[4] == 1) {
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+ }
+ break;
+ default:
+ gdm_wimax_event_send(dev, buf, len);
+ break;
+ }
+}
+
+static void gdm_wimax_ind_fsm_update(struct net_device *dev, struct fsm_s *fsm)
+{
+ u16 buf[32 / sizeof(u16)];
+ u8 *hci_pkt_buf = (u8 *)&buf[0];
+
+ /* Indicate updating fsm */
+ buf[0] = H2B(WIMAX_FSM_UPDATE);
+ buf[1] = H2B(sizeof(struct fsm_s));
+ memcpy(&hci_pkt_buf[HCI_HEADER_SIZE], fsm, sizeof(struct fsm_s));
+
+ gdm_wimax_event_send(dev, hci_pkt_buf,
+ HCI_HEADER_SIZE + sizeof(struct fsm_s));
+}
+
+static void gdm_wimax_ind_if_updown(struct net_device *dev, int if_up)
+{
+ u16 buf[32 / sizeof(u16)];
+ struct hci_s *hci = (struct hci_s *) buf;
+ unsigned char up_down;
+
+ up_down = if_up ? WIMAX_IF_UP : WIMAX_IF_DOWN;
+
+ /* Indicate updating fsm */
+ hci->cmd_evt = H2B(WIMAX_IF_UPDOWN);
+ hci->length = H2B(sizeof(up_down));
+ hci->data[0] = up_down;
+
+ gdm_wimax_event_send(dev, (char *)hci, HCI_HEADER_SIZE+sizeof(up_down));
+}
+
+static void rx_complete(void *arg, void *data, int len)
+{
+ struct nic *nic = arg;
+
+ gdm_wimax_transmit_pkt(nic->netdev, data, len);
+ gdm_wimax_rcv_with_cb(nic, rx_complete, nic);
+}
+
+static void prepare_rx_complete(void *arg, void *data, int len)
+{
+ struct nic *nic = arg;
+ int ret;
+
+ ret = gdm_wimax_get_prepared_info(nic->netdev, data, len);
+ if (ret == 1)
+ gdm_wimax_rcv_with_cb(nic, rx_complete, nic);
+ else {
+ if (ret < 0)
+ printk(KERN_ERR "get_prepared_info failed(%d)\n", ret);
+ gdm_wimax_rcv_with_cb(nic, prepare_rx_complete, nic);
+ #if 0
+ /* Re-prepare WiMax device */
+ gdm_wimax_prepare_device(nic->netdev);
+ #endif
+ }
+}
+
+static void start_rx_proc(struct nic *nic)
+{
+ gdm_wimax_rcv_with_cb(nic, prepare_rx_complete, nic);
+}
+
+static struct net_device_ops gdm_netdev_ops = {
+ .ndo_open = gdm_wimax_open,
+ .ndo_stop = gdm_wimax_close,
+ .ndo_set_config = gdm_wimax_set_config,
+ .ndo_start_xmit = gdm_wimax_tx,
+ .ndo_get_stats = gdm_wimax_stats,
+ .ndo_set_mac_address = gdm_wimax_set_mac_addr,
+ .ndo_do_ioctl = gdm_wimax_ioctl,
+};
+
+int register_wimax_device(struct phy_dev *phy_dev, struct device *pdev)
+{
+ struct nic *nic = NULL;
+ struct net_device *dev;
+ int ret;
+
+ dev = (struct net_device *)alloc_netdev(sizeof(*nic),
+ "wm%d", ether_setup);
+
+ if (dev == NULL) {
+ printk(KERN_ERR "alloc_etherdev failed\n");
+ return -ENOMEM;
+ }
+
+ SET_NETDEV_DEV(dev, pdev);
+ dev->mtu = 1400;
+ dev->netdev_ops = &gdm_netdev_ops;
+ dev->flags &= ~IFF_MULTICAST;
+ memcpy(dev->dev_addr, gdm_wimax_macaddr, sizeof(gdm_wimax_macaddr));
+
+ nic = netdev_priv(dev);
+ memset(nic, 0, sizeof(*nic));
+
+ nic->netdev = dev;
+ nic->phy_dev = phy_dev;
+ phy_dev->netdev = dev;
+
+ /* event socket init */
+ ret = gdm_wimax_event_init();
+ if (ret < 0) {
+ printk(KERN_ERR "Cannot create event.\n");
+ goto cleanup;
+ }
+
+ ret = register_netdev(dev);
+ if (ret)
+ goto cleanup;
+
+ #if defined(LOOPBACK_TEST)
+ netif_start_queue(dev);
+ netif_carrier_on(dev);
+ #else
+ netif_carrier_off(dev);
+ #endif
+
+#ifdef CONFIG_WIMAX_GDM72XX_QOS
+ gdm_qos_init(nic);
+#endif
+
+ start_rx_proc(nic);
+
+ /* Prepare WiMax device */
+ gdm_wimax_prepare_device(dev);
+
+ return 0;
+
+cleanup:
+ printk(KERN_ERR "register_netdev failed\n");
+ free_netdev(dev);
+ return ret;
+}
+
+void unregister_wimax_device(struct phy_dev *phy_dev)
+{
+ struct nic *nic = netdev_priv(phy_dev->netdev);
+ struct fsm_s *fsm = (struct fsm_s *) nic->sdk_data[SIOC_DATA_FSM].buf;
+
+ if (fsm)
+ fsm->m_status = M_INIT;
+ unregister_netdev(nic->netdev);
+
+ gdm_wimax_event_exit();
+
+#if defined(CONFIG_WIMAX_GDM72XX_QOS)
+ gdm_qos_release_list(nic);
+#endif
+
+ gdm_wimax_cleanup_ioctl(phy_dev->netdev);
+
+ free_netdev(nic->netdev);
+}
diff --git a/drivers/staging/gdm72xx/gdm_wimax.h b/drivers/staging/gdm72xx/gdm_wimax.h
new file mode 100644
index 000000000000..023e6492e33d
--- /dev/null
+++ b/drivers/staging/gdm72xx/gdm_wimax.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __GDM_WIMAX_H__
+#define __GDM_WIMAX_H__
+
+#include <linux/netdevice.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include "wm_ioctl.h"
+#if defined(CONFIG_WIMAX_GDM72XX_QOS)
+#include "gdm_qos.h"
+#endif
+
+#define DRIVER_VERSION "3.2.3"
+
+/*#define ETH_P_IP 0x0800 */
+/*#define ETH_P_ARP 0x0806 */
+/*#define ETH_P_IPV6 0x86DD */
+
+#define H2L(x) __cpu_to_le16(x)
+#define L2H(x) __le16_to_cpu(x)
+#define DH2L(x) __cpu_to_le32(x)
+#define DL2H(x) __le32_to_cpu(x)
+
+#define H2B(x) __cpu_to_be16(x)
+#define B2H(x) __be16_to_cpu(x)
+#define DH2B(x) __cpu_to_be32(x)
+#define DB2H(x) __be32_to_cpu(x)
+
+struct phy_dev {
+ void *priv_dev;
+ struct net_device *netdev;
+
+ int (*send_func)(void *priv_dev, void *data, int len,
+ void (*cb)(void *cb_data), void *cb_data);
+ int (*rcv_func)(void *priv_dev,
+ void (*cb)(void *cb_data, void *data, int len),
+ void *cb_data);
+};
+
+struct nic {
+ struct net_device *netdev;
+ struct phy_dev *phy_dev;
+
+ struct net_device_stats stats;
+
+ struct data_s sdk_data[SIOC_DATA_MAX];
+
+#if defined(CONFIG_WIMAX_GDM72XX_QOS)
+ struct qos_cb_s qos;
+#endif
+
+};
+
+
+#if 0
+#define dprintk(fmt, args ...) printk(KERN_DEBUG " [GDM] " fmt, ## args)
+#else
+#define dprintk(...)
+#endif
+
+/*#define DEBUG_SDU */
+#if defined(DEBUG_SDU)
+#define DUMP_SDU_ALL (1<<0)
+#define DUMP_SDU_ARP (1<<1)
+#define DUMP_SDU_IP (1<<2)
+#define DUMP_SDU_IP_TCP (1<<8)
+#define DUMP_SDU_IP_UDP (1<<9)
+#define DUMP_SDU_IP_ICMP (1<<10)
+#define DUMP_PACKET (DUMP_SDU_ALL)
+#endif
+
+/*#define DEBUG_HCI */
+
+/*#define LOOPBACK_TEST */
+
+extern int register_wimax_device(struct phy_dev *phy_dev, struct device *pdev);
+extern int gdm_wimax_send_tx(struct sk_buff *skb, struct net_device *dev);
+extern void unregister_wimax_device(struct phy_dev *phy_dev);
+
+#endif
diff --git a/drivers/staging/gdm72xx/hci.h b/drivers/staging/gdm72xx/hci.h
new file mode 100644
index 000000000000..0e0676622f1d
--- /dev/null
+++ b/drivers/staging/gdm72xx/hci.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef HCI_H_20080801
+#define HCI_H_20080801
+
+#define HCI_HEADER_SIZE 4
+#define HCI_VALUE_OFFS (HCI_HEADER_SIZE)
+#define HCI_MAX_PACKET 2048
+#define HCI_MAX_PARAM (HCI_MAX_PACKET-HCI_HEADER_SIZE)
+#define HCI_MAX_TLV 32
+
+/* CMD-EVT */
+
+/* Category 0 */
+#define WIMAX_RESET 0x0000
+#define WIMAX_SET_INFO 0x0001
+#define WIMAX_GET_INFO 0x0002
+#define WIMAX_GET_INFO_RESULT 0x8003
+#define WIMAX_RADIO_OFF 0x0004
+#define WIMAX_RADIO_ON 0x0006
+#define WIMAX_WIMAX_RESET 0x0007 /* Is this still here */
+
+/* Category 1 */
+#define WIMAX_NET_ENTRY 0x0100
+#define WIMAX_NET_DISCONN 0x0102
+#define WIMAX_ENTER_SLEEP 0x0103
+#define WIMAX_EXIT_SLEEP 0x0104
+#define WIMAX_ENTER_IDLE 0x0105
+#define WIMAX_EXIT_IDLE 0x0106
+#define WIMAX_MODE_CHANGE 0x8108
+#define WIMAX_HANDOVER 0x8109 /* obsolete */
+
+#define WIMAX_SCAN 0x010d
+#define WIMAX_SCAN_COMPLETE 0x810e
+#define WIMAX_SCAN_RESULT 0x810f
+
+#define WIMAX_CONNECT 0x0110
+#define WIMAX_CONNECT_START 0x8111
+#define WIMAX_CONNECT_COMPLETE 0x8112
+#define WIMAX_ASSOC_START 0x8113
+#define WIMAX_ASSOC_COMPLETE 0x8114
+#define WIMAX_DISCONN_IND 0x8115
+#define WIMAX_ENTRY_IND 0x8116
+#define WIMAX_HO_START 0x8117
+#define WIMAX_HO_COMPLETE 0x8118
+#define WIMAX_RADIO_STATE_IND 0x8119
+#define WIMAX_IP_RENEW_IND 0x811a
+
+#define WIMAX_DISCOVER_NSP 0x011d
+#define WIMAX_DISCOVER_NSP_RESULT 0x811e
+
+#define WIMAX_SDU_TX_FLOW 0x8125
+
+/* Category 2 */
+#define WIMAX_TX_EAP 0x0200
+#define WIMAX_RX_EAP 0x8201
+#define WIMAX_TX_SDU 0x0202
+#define WIMAX_RX_SDU 0x8203
+#define WIMAX_RX_SDU_AGGR 0x8204
+#define WIMAX_TX_SDU_AGGR 0x0205
+
+/* Category 3 */
+#define WIMAX_DM_CMD 0x030a
+#define WIMAX_DM_RSP 0x830b
+
+#define WIMAX_CLI_CMD 0x030c
+#define WIMAX_CLI_RSP 0x830d
+
+#define WIMAX_DL_IMAGE 0x0310
+#define WIMAX_DL_IMAGE_STATUS 0x8311
+#define WIMAX_UL_IMAGE 0x0312
+#define WIMAX_UL_IMAGE_RESULT 0x8313
+#define WIMAX_UL_IMAGE_STATUS 0x0314
+
+#define WIMAX_EVT_MODEM_REPORT 0x8325
+
+/* Category 0xF */
+#define WIMAX_FSM_UPDATE 0x8F01
+#define WIMAX_IF_UPDOWN 0x8F02
+ #define WIMAX_IF_UP 1
+ #define WIMAX_IF_DOWN 2
+
+/* WIMAX mode */
+#define W_NULL 0
+#define W_STANDBY 1
+#define W_OOZ 2
+#define W_AWAKE 3
+#define W_IDLE 4
+#define W_SLEEP 5
+#define W_WAIT 6
+
+#define W_NET_ENTRY_RNG 0x80
+#define W_NET_ENTRY_SBC 0x81
+#define W_NET_ENTRY_PKM 0x82
+#define W_NET_ENTRY_REG 0x83
+#define W_NET_ENTRY_DSX 0x84
+
+#define W_NET_ENTRY_RNG_FAIL 0x1100100
+#define W_NET_ENTRY_SBC_FAIL 0x1100200
+#define W_NET_ENTRY_PKM_FAIL 0x1102000
+#define W_NET_ENTRY_REG_FAIL 0x1103000
+#define W_NET_ENTRY_DSX_FAIL 0x1104000
+
+/* Scan Type */
+#define W_SCAN_ALL_CHANNEL 0
+#define W_SCAN_ALL_SUBSCRIPTION 1
+#define W_SCAN_SPECIFIED_SUBSCRIPTION 2
+
+/*
+ * TLV
+ *
+ * [31:31] indicates the type is composite.
+ * [30:16] is the length of the type. 0 length means length is variable.
+ * [15:0] is the actual type.
+ *
+ */
+#define TLV_L(x) (((x) >> 16) & 0xff)
+#define TLV_T(x) ((x) & 0xff)
+#define TLV_COMPOSITE(x) ((x) >> 31)
+
+/* GENERAL */
+#define T_MAC_ADDRESS (0x00 | (6 << 16))
+#define T_BSID (0x01 | (6 << 16))
+#define T_MSK (0x02 | (64 << 16))
+#define T_RSSI_THRSHLD (0x03 | (1 << 16))
+#define T_FREQUENCY (0x04 | (4 << 16))
+#define T_CONN_CS_TYPE (0x05 | (1 << 16))
+#define T_HOST_IP_VER (0x06 | (1 << 16))
+#define T_STBY_SCAN_INTERVAL (0x07 | (4 << 16))
+#define T_OOZ_SCAN_INTERVAL (0x08 | (4 << 16))
+#define T_IMEI (0x09 | (8 << 16))
+#define T_PID (0x0a | (12 << 16))
+
+#define T_CAPABILITY (0x1a | (4 << 16))
+#define T_RELEASE_NUMBER (0x1b | (4 << 16))
+#define T_DRIVER_REVISION (0x1c | (4 << 16))
+#define T_FW_REVISION (0x1d | (4 << 16))
+#define T_MAC_HW_REVISION (0x1e | (4 << 16))
+#define T_PHY_HW_REVISION (0x1f | (4 << 16))
+
+/* HANDOVER */
+#define T_SCAN_INTERVAL (0x20 | (1 << 16))
+
+#define T_RSC_RETAIN_TIME (0x2f | (2 << 16))
+
+/* SLEEP */
+#define T_TYPE1_ISW (0x40 | (1 << 16))
+
+#define T_SLP_START_TO (0x4a | (2 << 16))
+
+/* IDLE */
+#define T_IDLE_MODE_TO (0x50 | (2 << 16))
+
+#define T_IDLE_START_TO (0x54 | (2 << 16))
+
+/* MONITOR */
+#define T_RSSI (0x60 | (1 << 16))
+#define T_CINR (0x61 | (1 << 16))
+#define T_TX_POWER (0x6a | (1 << 16))
+#define T_CUR_FREQ (0x7f | (4 << 16))
+
+
+/* WIMAX */
+#define T_MAX_SUBSCRIPTION (0xa1 | (1 << 16))
+#define T_MAX_SF (0xa2 | (1 << 16))
+#define T_PHY_TYPE (0xa3 | (1 << 16))
+#define T_PKM (0xa4 | (1 << 16))
+#define T_AUTH_POLICY (0xa5 | (1 << 16))
+#define T_CS_TYPE (0xa6 | (2 << 16))
+#define T_VENDOR_NAME (0xa7 | (0 << 16))
+#define T_MOD_NAME (0xa8 | (0 << 16))
+#define T_PACKET_FILTER (0xa9 | (1 << 16))
+#define T_NSP_CHANGE_COUNT (0xaa | (4 << 16))
+#define T_RADIO_STATE (0xab | (1 << 16))
+#define T_URI_CONTACT_TYPE (0xac | (1 << 16))
+#define T_URI_TEXT (0xad | (0 << 16))
+#define T_URI (0xae | (0 << 16))
+#define T_ENABLE_AUTH (0xaf | (1 << 16))
+#define T_TIMEOUT (0xb0 | (2 << 16))
+#define T_RUN_MODE (0xb1 | (1 << 16))
+#define T_OMADMT_VER (0xb2 | (4 << 16))
+/* This is measured in seconds from 00:00:00 GMT January 1, 1970. */
+#define T_RTC_TIME (0xb3 | (4 << 16))
+#define T_CERT_STATUS (0xb4 | (4 << 16))
+#define T_CERT_MASK (0xb5 | (4 << 16))
+#define T_EMSK (0xb6 | (64 << 16))
+
+/* Subscription TLV */
+#define T_SUBSCRIPTION_LIST (0xd1 | (0 << 16) | (1 << 31))
+#define T_H_NSPID (0xd2 | (3 << 16))
+#define T_NSP_NAME (0xd3 | (0 << 16))
+#define T_SUBSCRIPTION_NAME (0xd4 | (0 << 16))
+#define T_SUBSCRIPTION_FLAG (0xd5 | (2 << 16))
+#define T_V_NSPID (0xd6 | (3 << 16))
+#define T_NAP_ID (0xd7 | (3 << 16))
+#define T_PREAMBLES (0xd8 | (15 << 16))
+#define T_BW (0xd9 | (4 << 16))
+#define T_FFTSIZE (0xda | (4 << 16))
+#define T_DUPLEX_MODE (0xdb | (4 << 16))
+
+struct hci_s {
+ unsigned short cmd_evt;
+ unsigned short length;
+ unsigned char data[0];
+} __packed;
+
+#endif
diff --git a/drivers/staging/gdm72xx/netlink_k.c b/drivers/staging/gdm72xx/netlink_k.c
new file mode 100644
index 000000000000..292af0f7f451
--- /dev/null
+++ b/drivers/staging/gdm72xx/netlink_k.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <linux/netlink.h>
+#include <asm/byteorder.h>
+#include <net/sock.h>
+
+#if !defined(NLMSG_HDRLEN)
+#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
+#endif
+
+#define ND_MAX_GROUP 30
+#define ND_IFINDEX_LEN sizeof(int)
+#define ND_NLMSG_SPACE(len) (NLMSG_SPACE(len) + ND_IFINDEX_LEN)
+#define ND_NLMSG_DATA(nlh) \
+ ((void *)((char *)NLMSG_DATA(nlh) + ND_IFINDEX_LEN))
+#define ND_NLMSG_S_LEN(len) (len+ND_IFINDEX_LEN)
+#define ND_NLMSG_R_LEN(nlh) (nlh->nlmsg_len-ND_IFINDEX_LEN)
+#define ND_NLMSG_IFIDX(nlh) NLMSG_DATA(nlh)
+#define ND_MAX_MSG_LEN 8096
+
+#if defined(DEFINE_MUTEX)
+static DEFINE_MUTEX(netlink_mutex);
+#else
+static struct semaphore netlink_mutex;
+#define mutex_lock(x) down(x)
+#define mutex_unlock(x) up(x)
+#endif
+
+static void (*rcv_cb)(struct net_device *dev, u16 type, void *msg, int len);
+
+static void netlink_rcv_cb(struct sk_buff *skb)
+{
+ struct nlmsghdr *nlh;
+ struct net_device *dev;
+ u32 mlen;
+ void *msg;
+ int ifindex;
+
+ if (skb->len >= NLMSG_SPACE(0)) {
+ nlh = (struct nlmsghdr *)skb->data;
+
+ if (skb->len < nlh->nlmsg_len ||
+ nlh->nlmsg_len > ND_MAX_MSG_LEN) {
+ printk(KERN_ERR "Invalid length (%d,%d)\n", skb->len,
+ nlh->nlmsg_len);
+ return;
+ }
+
+ memcpy(&ifindex, ND_NLMSG_IFIDX(nlh), ND_IFINDEX_LEN);
+ msg = ND_NLMSG_DATA(nlh);
+ mlen = ND_NLMSG_R_LEN(nlh);
+
+ if (rcv_cb) {
+ dev = dev_get_by_index(&init_net, ifindex);
+ if (dev) {
+ rcv_cb(dev, nlh->nlmsg_type, msg, mlen);
+ dev_put(dev);
+ } else
+ printk(KERN_ERR "dev_get_by_index(%d) "
+ "is not found.\n", ifindex);
+ } else
+ printk(KERN_ERR "Unregistered Callback\n");
+ }
+}
+
+static void netlink_rcv(struct sk_buff *skb)
+{
+ mutex_lock(&netlink_mutex);
+ netlink_rcv_cb(skb);
+ mutex_unlock(&netlink_mutex);
+}
+
+struct sock *netlink_init(int unit, void (*cb)(struct net_device *dev, u16 type,
+ void *msg, int len))
+{
+ struct sock *sock;
+
+#if !defined(DEFINE_MUTEX)
+ init_MUTEX(&netlink_mutex);
+#endif
+
+ sock = netlink_kernel_create(&init_net, unit, 0, netlink_rcv, NULL,
+ THIS_MODULE);
+
+ if (sock)
+ rcv_cb = cb;
+
+ return sock;
+}
+
+void netlink_exit(struct sock *sock)
+{
+ sock_release(sock->sk_socket);
+}
+
+int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len)
+{
+ static u32 seq;
+ struct sk_buff *skb = NULL;
+ struct nlmsghdr *nlh;
+ int ret = 0;
+
+ if (group > ND_MAX_GROUP) {
+ printk(KERN_ERR "Group %d is invalied.\n", group);
+ printk(KERN_ERR "Valid group is 0 ~ %d.\n", ND_MAX_GROUP);
+ return -EINVAL;
+ }
+
+ skb = alloc_skb(NLMSG_SPACE(len), GFP_ATOMIC);
+ if (!skb) {
+ printk(KERN_ERR "netlink_broadcast ret=%d\n", ret);
+ return -ENOMEM;
+ }
+
+ seq++;
+ nlh = NLMSG_PUT(skb, 0, seq, type, len);
+ memcpy(NLMSG_DATA(nlh), msg, len);
+
+ NETLINK_CB(skb).pid = 0;
+ NETLINK_CB(skb).dst_group = 0;
+
+ ret = netlink_broadcast(sock, skb, 0, group+1, GFP_ATOMIC);
+
+ if (!ret)
+ return len;
+ else {
+ if (ret != -ESRCH) {
+ printk(KERN_ERR "netlink_broadcast g=%d, t=%d, l=%d, r=%d\n",
+ group, type, len, ret);
+ }
+ ret = 0;
+ }
+
+nlmsg_failure:
+ return ret;
+}
diff --git a/drivers/staging/gdm72xx/netlink_k.h b/drivers/staging/gdm72xx/netlink_k.h
new file mode 100644
index 000000000000..1dffaa6156e4
--- /dev/null
+++ b/drivers/staging/gdm72xx/netlink_k.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#if !defined(NETLINK_H_20081202)
+#define NETLINK_H_20081202
+#include <linux/netdevice.h>
+#include <net/sock.h>
+
+struct sock *netlink_init(int unit,
+ void (*cb)(struct net_device *dev, u16 type, void *msg, int len));
+void netlink_exit(struct sock *sock);
+int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len);
+
+#endif
diff --git a/drivers/staging/gdm72xx/sdio_boot.c b/drivers/staging/gdm72xx/sdio_boot.c
new file mode 100644
index 000000000000..6ff4dc372522
--- /dev/null
+++ b/drivers/staging/gdm72xx/sdio_boot.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+
+#include "gdm_sdio.h"
+
+#define TYPE_A_HEADER_SIZE 4
+#define TYPE_A_LOOKAHEAD_SIZE 16
+#define YMEM0_SIZE 0x8000 /* 32kbytes */
+#define DOWNLOAD_SIZE (YMEM0_SIZE - TYPE_A_HEADER_SIZE)
+
+#define KRN_PATH "/lib/firmware/gdm72xx/gdmskrn.bin"
+#define RFS_PATH "/lib/firmware/gdm72xx/gdmsrfs.bin"
+
+static u8 *tx_buf;
+
+static int ack_ready(struct sdio_func *func)
+{
+ unsigned long start = jiffies;
+ u8 val;
+ int ret;
+
+ while ((jiffies - start) < HZ) {
+ val = sdio_readb(func, 0x13, &ret);
+ if (val & 0x01)
+ return 1;
+ schedule();
+ }
+
+ return 0;
+}
+
+static int download_image(struct sdio_func *func, char *img_name)
+{
+ int ret = 0, len, size, pno;
+ struct file *filp = NULL;
+ struct inode *inode = NULL;
+ u8 *buf = tx_buf;
+ loff_t pos = 0;
+
+ filp = filp_open(img_name, O_RDONLY | O_LARGEFILE, 0);
+ if (IS_ERR(filp)) {
+ printk(KERN_ERR "Can't find %s.\n", img_name);
+ return -ENOENT;
+ }
+
+ if (filp->f_dentry)
+ inode = filp->f_dentry->d_inode;
+ if (!inode || !S_ISREG(inode->i_mode)) {
+ printk(KERN_ERR "Invalid file type: %s\n", img_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ size = i_size_read(inode->i_mapping->host);
+ if (size <= 0) {
+ printk(KERN_ERR "Unable to find file size: %s\n", img_name);
+ ret = size;
+ goto out;
+ }
+
+ pno = 0;
+ while ((len = filp->f_op->read(filp, buf + TYPE_A_HEADER_SIZE,
+ DOWNLOAD_SIZE, &pos))) {
+ if (len < 0) {
+ ret = -1;
+ goto out;
+ }
+
+ buf[0] = len & 0xff;
+ buf[1] = (len >> 8) & 0xff;
+ buf[2] = (len >> 16) & 0xff;
+
+ if (pos >= size) /* The last packet */
+ buf[3] = 2;
+ else
+ buf[3] = 0;
+
+ ret = sdio_memcpy_toio(func, 0, buf, len + TYPE_A_HEADER_SIZE);
+ if (ret < 0) {
+ printk(KERN_ERR "gdmwm: send image error: "
+ "packet number = %d ret = %d\n", pno, ret);
+ goto out;
+ }
+ if (buf[3] == 2) /* The last packet */
+ break;
+ if (!ack_ready(func)) {
+ ret = -EIO;
+ printk(KERN_ERR "gdmwm: Ack is not ready.\n");
+ goto out;
+ }
+ ret = sdio_memcpy_fromio(func, buf, 0, TYPE_A_LOOKAHEAD_SIZE);
+ if (ret < 0) {
+ printk(KERN_ERR "gdmwm: receive ack error: "
+ "packet number = %d ret = %d\n", pno, ret);
+ goto out;
+ }
+ sdio_writeb(func, 0x01, 0x13, &ret);
+ sdio_writeb(func, 0x00, 0x10, &ret); /* PCRRT */
+
+ pno++;
+ }
+out:
+ filp_close(filp, current->files);
+ return ret;
+}
+
+int sdio_boot(struct sdio_func *func)
+{
+ static mm_segment_t fs;
+ int ret;
+
+ tx_buf = kmalloc(YMEM0_SIZE, GFP_KERNEL);
+ if (tx_buf == NULL) {
+ printk(KERN_ERR "Error: kmalloc: %s %d\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ fs = get_fs();
+ set_fs(get_ds());
+
+ ret = download_image(func, KRN_PATH);
+ if (ret)
+ goto restore_fs;
+ printk(KERN_INFO "GCT: Kernel download success.\n");
+
+ ret = download_image(func, RFS_PATH);
+ if (ret)
+ goto restore_fs;
+ printk(KERN_INFO "GCT: Filesystem download success.\n");
+
+restore_fs:
+ set_fs(fs);
+ kfree(tx_buf);
+ return ret;
+}
diff --git a/drivers/staging/gdm72xx/sdio_boot.h b/drivers/staging/gdm72xx/sdio_boot.h
new file mode 100644
index 000000000000..373ac28063c6
--- /dev/null
+++ b/drivers/staging/gdm72xx/sdio_boot.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SDIO_BOOT_H__
+#define __SDIO_BOOT_H__
+
+struct sdio_func;
+
+extern int sdio_boot(struct sdio_func *func);
+
+#endif /* __SDIO_BOOT_H__ */
diff --git a/drivers/staging/gdm72xx/usb_boot.c b/drivers/staging/gdm72xx/usb_boot.c
new file mode 100644
index 000000000000..5a0e030220dc
--- /dev/null
+++ b/drivers/staging/gdm72xx/usb_boot.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/usb.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+
+#include <asm/byteorder.h>
+#include "gdm_usb.h"
+#include "usb_boot.h"
+
+#define DN_KERNEL_MAGIC_NUMBER 0x10760001
+#define DN_ROOTFS_MAGIC_NUMBER 0x10760002
+
+#define DOWNLOAD_SIZE 1024
+
+#define DH2B(x) __cpu_to_be32(x)
+#define DL2H(x) __le32_to_cpu(x)
+
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+#define MAX_IMG_CNT 16
+#define UIMG_PATH "/lib/firmware/gdm72xx/gdmuimg.bin"
+#define KERN_PATH "/lib/firmware/gdm72xx/zImage"
+#define FS_PATH "/lib/firmware/gdm72xx/ramdisk.jffs2"
+
+struct dn_header {
+ u32 magic_num;
+ u32 file_size;
+};
+
+struct img_header {
+ u32 magic_code;
+ u32 count;
+ u32 len;
+ u32 offset[MAX_IMG_CNT];
+ char hostname[32];
+ char date[32];
+};
+
+struct fw_info {
+ u32 id;
+ u32 len;
+ u32 kernel_len;
+ u32 rootfs_len;
+ u32 kernel_offset;
+ u32 rootfs_offset;
+ u32 fw_ver;
+ u32 mac_ver;
+ char hostname[32];
+ char userid[16];
+ char date[32];
+ char user_desc[128];
+};
+
+static void array_le32_to_cpu(u32 *arr, int num)
+{
+ int i;
+ for (i = 0; i < num; i++, arr++)
+ *arr = DL2H(*arr);
+}
+
+static u8 *tx_buf;
+
+static int gdm_wibro_send(struct usb_device *usbdev, void *data, int len)
+{
+ int ret;
+ int actual;
+
+ ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), data, len,
+ &actual, 1000);
+
+ if (ret < 0) {
+ printk(KERN_ERR "Error : usb_bulk_msg ( result = %d )\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
+static int gdm_wibro_recv(struct usb_device *usbdev, void *data, int len)
+{
+ int ret;
+ int actual;
+
+ ret = usb_bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), data, len,
+ &actual, 5000);
+
+ if (ret < 0) {
+ printk(KERN_ERR "Error : usb_bulk_msg(recv) ( result = %d )\n",
+ ret);
+ return ret;
+ }
+ return 0;
+}
+
+static int download_image(struct usb_device *usbdev, struct file *filp,
+ loff_t *pos, u32 img_len, u32 magic_num)
+{
+ struct dn_header h;
+ int ret = 0;
+ u32 size;
+ int len, readn;
+
+ size = (img_len + DOWNLOAD_SIZE - 1) & ~(DOWNLOAD_SIZE - 1);
+ h.magic_num = DH2B(magic_num);
+ h.file_size = DH2B(size);
+
+ ret = gdm_wibro_send(usbdev, &h, sizeof(h));
+ if (ret < 0)
+ goto out;
+
+ readn = 0;
+ while ((len = filp->f_op->read(filp, tx_buf, DOWNLOAD_SIZE, pos))) {
+
+ if (len < 0) {
+ ret = -1;
+ goto out;
+ }
+ readn += len;
+
+ ret = gdm_wibro_send(usbdev, tx_buf, DOWNLOAD_SIZE);
+ if (ret < 0)
+ goto out;
+ if (readn >= img_len)
+ break;
+ }
+
+ if (readn < img_len) {
+ printk(KERN_ERR "gdmwm: Cannot read to the requested size. "
+ "Read = %d Requested = %d\n", readn, img_len);
+ ret = -EIO;
+ }
+out:
+
+ return ret;
+}
+
+int usb_boot(struct usb_device *usbdev, u16 pid)
+{
+ int i, ret = 0;
+ struct file *filp = NULL;
+ struct inode *inode = NULL;
+ static mm_segment_t fs;
+ struct img_header hdr;
+ struct fw_info fw_info;
+ loff_t pos = 0;
+ char *img_name = UIMG_PATH;
+ int len;
+
+ tx_buf = kmalloc(DOWNLOAD_SIZE, GFP_KERNEL);
+ if (tx_buf == NULL) {
+ printk(KERN_ERR "Error: kmalloc\n");
+ return -ENOMEM;
+ }
+
+ fs = get_fs();
+ set_fs(get_ds());
+
+ filp = filp_open(img_name, O_RDONLY | O_LARGEFILE, 0);
+ if (IS_ERR(filp)) {
+ printk(KERN_ERR "Can't find %s.\n", img_name);
+ set_fs(fs);
+ ret = -ENOENT;
+ goto restore_fs;
+ }
+
+ if (filp->f_dentry)
+ inode = filp->f_dentry->d_inode;
+ if (!inode || !S_ISREG(inode->i_mode)) {
+ printk(KERN_ERR "Invalid file type: %s\n", img_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ len = filp->f_op->read(filp, (u8 *)&hdr, sizeof(hdr), &pos);
+ if (len != sizeof(hdr)) {
+ printk(KERN_ERR "gdmwm: Cannot read the image info.\n");
+ ret = -EIO;
+ goto out;
+ }
+
+ array_le32_to_cpu((u32 *)&hdr, 19);
+#if 0
+ if (hdr.magic_code != 0x10767fff) {
+ printk(KERN_ERR "gdmwm: Invalid magic code 0x%08x\n",
+ hdr.magic_code);
+ ret = -EINVAL;
+ goto out;
+ }
+#endif
+ if (hdr.count > MAX_IMG_CNT) {
+ printk(KERN_ERR "gdmwm: Too many images. %d\n", hdr.count);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < hdr.count; i++) {
+ if (hdr.offset[i] > hdr.len) {
+ printk(KERN_ERR "gdmwm: Invalid offset. "
+ "Entry = %d Offset = 0x%08x "
+ "Image length = 0x%08x\n",
+ i, hdr.offset[i], hdr.len);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pos = hdr.offset[i];
+ len = filp->f_op->read(filp, (u8 *)&fw_info, sizeof(fw_info),
+ &pos);
+ if (len != sizeof(fw_info)) {
+ printk(KERN_ERR "gdmwm: Cannot read the FW info.\n");
+ ret = -EIO;
+ goto out;
+ }
+
+ array_le32_to_cpu((u32 *)&fw_info, 8);
+#if 0
+ if ((fw_info.id & 0xfffff000) != 0x10767000) {
+ printk(KERN_ERR "gdmwm: Invalid FW id. 0x%08x\n",
+ fw_info.id);
+ ret = -EIO;
+ goto out;
+ }
+#endif
+
+ if ((fw_info.id & 0xffff) != pid)
+ continue;
+
+ pos = hdr.offset[i] + fw_info.kernel_offset;
+ ret = download_image(usbdev, filp, &pos, fw_info.kernel_len,
+ DN_KERNEL_MAGIC_NUMBER);
+ if (ret < 0)
+ goto out;
+ printk(KERN_INFO "GCT: Kernel download success.\n");
+
+ pos = hdr.offset[i] + fw_info.rootfs_offset;
+ ret = download_image(usbdev, filp, &pos, fw_info.rootfs_len,
+ DN_ROOTFS_MAGIC_NUMBER);
+ if (ret < 0)
+ goto out;
+ printk(KERN_INFO "GCT: Filesystem download success.\n");
+
+ break;
+ }
+
+ if (i == hdr.count) {
+ printk(KERN_ERR "Firmware for gsk%x is not installed.\n", pid);
+ ret = -EINVAL;
+ }
+out:
+ filp_close(filp, current->files);
+
+restore_fs:
+ set_fs(fs);
+ kfree(tx_buf);
+ return ret;
+}
+
+/*#define GDM7205_PADDING 256 */
+#define DOWNLOAD_CHUCK 2048
+#define KERNEL_TYPE_STRING "linux"
+#define FS_TYPE_STRING "rootfs"
+
+static int em_wait_ack(struct usb_device *usbdev, int send_zlp)
+{
+ int ack;
+ int ret = -1;
+
+ if (send_zlp) {
+ /*Send ZLP*/
+ ret = gdm_wibro_send(usbdev, NULL, 0);
+ if (ret < 0)
+ goto out;
+ }
+
+ /*Wait for ACK*/
+ ret = gdm_wibro_recv(usbdev, &ack, sizeof(ack));
+ if (ret < 0)
+ goto out;
+out:
+ return ret;
+}
+
+static int em_download_image(struct usb_device *usbdev, char *path,
+ char *type_string)
+{
+ struct file *filp;
+ struct inode *inode;
+ static mm_segment_t fs;
+ char *buf = NULL;
+ loff_t pos = 0;
+ int ret = 0;
+ int len, readn = 0;
+ #if defined(GDM7205_PADDING)
+ const int pad_size = GDM7205_PADDING;
+ #else
+ const int pad_size = 0;
+ #endif
+
+ fs = get_fs();
+ set_fs(get_ds());
+
+ filp = filp_open(path, O_RDONLY | O_LARGEFILE, 0);
+ if (IS_ERR(filp)) {
+ printk(KERN_ERR "Can't find %s.\n", path);
+ set_fs(fs);
+ ret = -ENOENT;
+ goto restore_fs;
+ }
+
+ if (filp->f_dentry) {
+ inode = filp->f_dentry->d_inode;
+ if (!inode || !S_ISREG(inode->i_mode)) {
+ printk(KERN_ERR "Invalid file type: %s\n", path);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ buf = kmalloc(DOWNLOAD_CHUCK + pad_size, GFP_KERNEL);
+ if (buf == NULL) {
+ printk(KERN_ERR "Error: kmalloc\n");
+ return -ENOMEM;
+ }
+
+ strcpy(buf+pad_size, type_string);
+ ret = gdm_wibro_send(usbdev, buf, strlen(type_string)+pad_size);
+ if (ret < 0)
+ goto out;
+
+ while ((len = filp->f_op->read(filp, buf+pad_size, DOWNLOAD_CHUCK,
+ &pos))) {
+ if (len < 0) {
+ ret = -1;
+ goto out;
+ }
+ readn += len;
+
+ ret = gdm_wibro_send(usbdev, buf, len+pad_size);
+ if (ret < 0)
+ goto out;
+
+ ret = em_wait_ack(usbdev, ((len+pad_size) % 512 == 0));
+ if (ret < 0)
+ goto out;
+ }
+
+ ret = em_wait_ack(usbdev, 1);
+ if (ret < 0)
+ goto out;
+
+out:
+ filp_close(filp, current->files);
+
+restore_fs:
+ set_fs(fs);
+
+ kfree(buf);
+
+ return ret;
+}
+
+static int em_fw_reset(struct usb_device *usbdev)
+{
+ int ret;
+
+ /*Send ZLP*/
+ ret = gdm_wibro_send(usbdev, NULL, 0);
+ return ret;
+}
+
+int usb_emergency(struct usb_device *usbdev)
+{
+ int ret;
+
+ ret = em_download_image(usbdev, KERN_PATH, KERNEL_TYPE_STRING);
+ if (ret < 0)
+ goto out;
+ printk(KERN_INFO "GCT Emergency: Kernel download success.\n");
+
+ ret = em_download_image(usbdev, FS_PATH, FS_TYPE_STRING);
+ if (ret < 0)
+ goto out;
+ printk(KERN_INFO "GCT Emergency: Filesystem download success.\n");
+
+ ret = em_fw_reset(usbdev);
+out:
+ return ret;
+}
diff --git a/drivers/staging/gdm72xx/usb_boot.h b/drivers/staging/gdm72xx/usb_boot.h
new file mode 100644
index 000000000000..c715cd3cd300
--- /dev/null
+++ b/drivers/staging/gdm72xx/usb_boot.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __USB_BOOT_H__
+#define __USB_BOOT_H__
+
+struct usb_device;
+
+extern int usb_boot(struct usb_device *usbdev, u16 pid);
+extern int usb_emergency(struct usb_device *usbdev);
+
+#endif /* __USB_BOOT_H__ */
diff --git a/drivers/staging/gdm72xx/usb_ids.h b/drivers/staging/gdm72xx/usb_ids.h
new file mode 100644
index 000000000000..b34616b7203f
--- /dev/null
+++ b/drivers/staging/gdm72xx/usb_ids.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __USB_IDS_H__
+#define __USB_IDS_H__
+
+/*You can replace vendor-ID as yours.*/
+#define GCT_VID 0x1076
+
+/*You can replace product-ID as yours.*/
+#define GCT_PID1 0x7e00
+#define GCT_PID2 0x7f00
+
+#define USB_DEVICE_ID_MATCH_DEVICE_INTERFACE \
+ (USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_CLASS)
+
+#define USB_DEVICE_INTF(vend, prod, intf) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE_INTERFACE, \
+ .idVendor = (vend), .idProduct = (prod), .bInterfaceClass = (intf)
+
+#define EMERGENCY_PID 0x720f
+#define BL_PID_MASK 0xffc0
+
+#define USB_DEVICE_BOOTLOADER(vid, pid) \
+ {USB_DEVICE((vid), ((pid)&BL_PID_MASK)|B_DOWNLOAD)}, \
+ {USB_DEVICE((vid), ((pid)&BL_PID_MASK)|B_DOWNLOAD|B_DIFF_DL_DRV)}
+
+#define USB_DEVICE_CDC_DATA(vid, pid) \
+ {USB_DEVICE_INTF((vid), (pid), USB_CLASS_CDC_DATA)}
+
+static const struct usb_device_id id_table[] = {
+ USB_DEVICE_BOOTLOADER(GCT_VID, GCT_PID1),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x1),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x2),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x3),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x4),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x5),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x6),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x7),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x8),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x9),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xa),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xb),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xc),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xd),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xe),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xf),
+
+ USB_DEVICE_BOOTLOADER(GCT_VID, GCT_PID2),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x1),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x2),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x3),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x4),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x5),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x6),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x7),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x8),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x9),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xa),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xb),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xc),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xd),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xe),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xf),
+
+ {USB_DEVICE(GCT_VID, EMERGENCY_PID)},
+ { }
+};
+
+#endif /* __USB_IDS_H__ */
diff --git a/drivers/staging/gdm72xx/wm_ioctl.h b/drivers/staging/gdm72xx/wm_ioctl.h
new file mode 100644
index 000000000000..9f46e06f2303
--- /dev/null
+++ b/drivers/staging/gdm72xx/wm_ioctl.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#if !defined(WM_IOCTL_H_20080714)
+#define WM_IOCTL_H_20080714
+#if !defined(__KERNEL__)
+#include <net/if.h>
+#endif
+
+#define NETLINK_WIMAX 31
+
+#define SIOCWMIOCTL SIOCDEVPRIVATE
+
+#define SIOCG_DATA 0x8D10
+#define SIOCS_DATA 0x8D11
+
+enum {
+ SIOC_DATA_FSM,
+ SIOC_DATA_NETLIST,
+ SIOC_DATA_CONNNSP,
+ SIOC_DATA_CONNCOMP,
+ SIOC_DATA_PROFILEID,
+
+ SIOC_DATA_END
+};
+
+#define SIOC_DATA_MAX 16
+
+/* FSM */
+enum {
+ M_INIT = 0,
+ M_OPEN_OFF,
+ M_OPEN_ON,
+ M_SCAN,
+ M_CONNECTING,
+ M_CONNECTED,
+ M_FSM_END,
+
+ C_INIT = 0,
+ C_CONNSTART,
+ C_ASSOCSTART,
+ C_RNG,
+ C_SBC,
+ C_AUTH,
+ C_REG,
+ C_DSX,
+ C_ASSOCCOMPLETE,
+ C_CONNCOMPLETE,
+ C_FSM_END,
+
+ D_INIT = 0,
+ D_READY,
+ D_LISTEN,
+ D_IPACQUISITION,
+
+ END_FSM
+};
+
+struct fsm_s {
+ int m_status; /*main status*/
+ int c_status; /*connection status*/
+ int d_status; /*oma-dm status*/
+};
+
+struct data_s {
+ int size;
+ void *buf;
+};
+
+struct wm_req_s {
+ union {
+ char ifrn_name[IFNAMSIZ];
+ } ifr_ifrn;
+
+ unsigned short cmd;
+
+ unsigned short data_id;
+ struct data_s data;
+
+/* NOTE: sizeof(struct wm_req_s) must be less than sizeof(struct ifreq). */
+};
+
+#ifndef ifr_name
+#define ifr_name ifr_ifrn.ifrn_name
+#endif
+
+#endif
diff --git a/drivers/staging/iio/Documentation/device.txt b/drivers/staging/iio/Documentation/device.txt
index 8926f2448cc9..0338c7cd0a8b 100644
--- a/drivers/staging/iio/Documentation/device.txt
+++ b/drivers/staging/iio/Documentation/device.txt
@@ -8,7 +8,7 @@ The crucial structure for device drivers in iio is iio_dev.
First allocate one using:
-struct iio_dev *indio_dev = iio_allocate_device(sizeof(struct chip_state));
+struct iio_dev *indio_dev = iio_device_alloc(sizeof(struct chip_state));
where chip_state is a structure of local state data for this instance of
the chip.
@@ -78,4 +78,4 @@ be registered afterwards (otherwise the whole parentage of devices
gets confused)
On remove, iio_device_unregister(indio_dev) will remove the device from
-the core, and iio_free_device will clean up.
+the core, and iio_device_free will clean up.
diff --git a/drivers/staging/iio/Documentation/generic_buffer.c b/drivers/staging/iio/Documentation/generic_buffer.c
index 69a05b9456d6..bf553356fdad 100644
--- a/drivers/staging/iio/Documentation/generic_buffer.c
+++ b/drivers/staging/iio/Documentation/generic_buffer.c
@@ -60,9 +60,9 @@ void print2byte(int input, struct iio_channel_info *info)
/* First swap if incorrect endian */
if (info->be)
- input = be16toh((uint_16t)input);
+ input = be16toh((uint16_t)input);
else
- input = le16toh((uint_16t)input);
+ input = le16toh((uint16_t)input);
/* shift before conversion to avoid sign extension
of left aligned data */
diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c
index 0d21a277305f..22275845fb12 100644
--- a/drivers/staging/iio/Documentation/iio_event_monitor.c
+++ b/drivers/staging/iio/Documentation/iio_event_monitor.c
@@ -27,7 +27,7 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include "iio_utils.h"
-#include "../events.h"
+#include <linux/iio/events.h>
static const char * const iio_chan_type_name_spec[] = {
[IIO_VOLTAGE] = "voltage",
diff --git a/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2583 b/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2583
new file mode 100755
index 000000000000..470f7ad9c073
--- /dev/null
+++ b/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2583
@@ -0,0 +1,6 @@
+What: /sys/bus/iio/devices/device[n]/in_illuminance0_calibrate
+KernelVersion: 2.6.37
+Contact: linux-iio@vger.kernel.org
+Description:
+ This property causes an internal calibration of the als gain trim
+ value which is later used in calculating illuminance in lux.
diff --git a/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2x7x b/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2x7x
new file mode 100755
index 000000000000..b2798b258bf7
--- /dev/null
+++ b/drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2x7x
@@ -0,0 +1,13 @@
+What: /sys/bus/iio/devices/device[n]/in_illuminance0_calibrate
+KernelVersion: 3.3-rc1
+Contact: linux-iio@vger.kernel.org
+Description:
+ Causes an internal calibration of the als gain trim
+ value which is later used in calculating illuminance in lux.
+
+What: /sys/bus/iio/devices/device[n]/in_proximity0_calibrate
+KernelVersion: 3.3-rc1
+Contact: linux-iio@vger.kernel.org
+Description:
+ Causes a recalculation and adjustment to the
+ proximity_thresh_rising_value.
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-ad7192 b/drivers/staging/iio/Documentation/sysfs-bus-iio-ad7192
new file mode 100644
index 000000000000..1c35c507cc05
--- /dev/null
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-ad7192
@@ -0,0 +1,20 @@
+What: /sys/.../iio:deviceX/ac_excitation_en
+KernelVersion: 3.1.0
+Contact: linux-iio@vger.kernel.org
+Description:
+ This attribute, if available, is used to enable the AC
+ excitation mode found on some converters. In ac excitation mode,
+ the polarity of the excitation voltage is reversed on
+ alternate cycles, to eliminate DC errors.
+
+What: /sys/.../iio:deviceX/bridge_switch_en
+KernelVersion: 3.1.0
+Contact: linux-iio@vger.kernel.org
+Description:
+ This attribute, if available, is used to close or open the
+ bridge power down switch found on some converters.
+ In bridge applications, such as strain gauges and load cells,
+ the bridge itself consumes the majority of the current in the
+ system. To minimize the current consumption of the system,
+ the bridge can be disconnected (when it is not being used
+ using the bridge_switch_en attribute.
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-dds b/drivers/staging/iio/Documentation/sysfs-bus-iio-dds
index ffdd5478a35d..ee8c509c6733 100644
--- a/drivers/staging/iio/Documentation/sysfs-bus-iio-dds
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-dds
@@ -1,83 +1,86 @@
-What: /sys/bus/iio/devices/.../ddsX_freqY
+What: /sys/bus/iio/devices/.../out_altvoltageX_frequencyY
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
Stores frequency into tuning word Y.
- There will be more than one ddsX_freqY file, which allows for
- pin controlled FSK Frequency Shift Keying
- (ddsX_pincontrol_freq_en is active) or the user can control
- the desired active tuning word by writing Y to the
- ddsX_freqsymbol file.
+ There will be more than one out_altvoltageX_frequencyY file,
+ which allows for pin controlled FSK Frequency Shift Keying
+ (out_altvoltageX_pincontrol_frequency_en is active) or the user
+ can control the desired active tuning word by writing Y to the
+ out_altvoltageX_frequencysymbol file.
-What: /sys/bus/iio/devices/.../ddsX_freqY_scale
+What: /sys/bus/iio/devices/.../out_altvoltageX_frequencyY_scale
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
- Scale to be applied to ddsX_freqY in order to obtain the
- desired value in Hz. If shared across all frequency registers
- Y is not present. It is also possible X is not present if
- shared across all channels.
+ Scale to be applied to out_altvoltageX_frequencyY in order to
+ obtain the desired value in Hz. If shared across all frequency
+ registers Y is not present. It is also possible X is not present
+ if shared across all channels.
-What: /sys/bus/iio/devices/.../ddsX_freqsymbol
+What: /sys/bus/iio/devices/.../out_altvoltageX_frequencysymbol
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
Specifies the active output frequency tuning word. The value
- corresponds to the Y in ddsX_freqY. To exit this mode the user
- can write ddsX_pincontrol_freq_en or ddsX_out_enable file.
+ corresponds to the Y in out_altvoltageX_frequencyY.
+ To exit this mode the user can write
+ out_altvoltageX_pincontrol_frequency_en or
+ out_altvoltageX_out_enable file.
-What: /sys/bus/iio/devices/.../ddsX_phaseY
+What: /sys/bus/iio/devices/.../out_altvoltageX_phaseY
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
Stores phase into Y.
- There will be more than one ddsX_phaseY file, which allows for
- pin controlled PSK Phase Shift Keying
- (ddsX_pincontrol_phase_en is active) or the user can
+ There will be more than one out_altvoltageX_phaseY file, which
+ allows for pin controlled PSK Phase Shift Keying
+ (out_altvoltageX_pincontrol_phase_en is active) or the user can
control the desired phase Y which is added to the phase
- accumulator output by writing Y to the en_phase file.
+ accumulator output by writing Y to the phase_en file.
-What: /sys/bus/iio/devices/.../ddsX_phaseY_scale
+What: /sys/bus/iio/devices/.../out_altvoltageX_phaseY_scale
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
- Scale to be applied to ddsX_phaseY in order to obtain the
- desired value in rad. If shared across all phase registers
+ Scale to be applied to out_altvoltageX_phaseY in order to obtain
+ the desired value in rad. If shared across all phase registers
Y is not present. It is also possible X is not present if
shared across all channels.
-What: /sys/bus/iio/devices/.../ddsX_phasesymbol
+What: /sys/bus/iio/devices/.../out_altvoltageX_phasesymbol
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
Specifies the active phase Y which is added to the phase
accumulator output. The value corresponds to the Y in
- ddsX_phaseY. To exit this mode the user can write
- ddsX_pincontrol_phase_en or disable file.
+ out_altvoltageX_phaseY. To exit this mode the user can write
+ out_altvoltageX_pincontrol_phase_en or disable file.
-What: /sys/bus/iio/devices/.../ddsX_pincontrol_en
-What: /sys/bus/iio/devices/.../ddsX_pincontrol_freq_en
-What: /sys/bus/iio/devices/.../ddsX_pincontrol_phase_en
+What: /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_en
+What: /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_frequency_en
+What: /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_phase_en
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
- ddsX_pincontrol_en: Both, the active frequency and phase is
- controlled by the respective phase and frequency control inputs.
- In case the device in question allows to independent controls,
- then there are dedicated files (ddsX_pincontrol_freq_en,
- ddsX_pincontrol_phase_en).
+ out_altvoltageX_pincontrol_en: Both, the active frequency and
+ phase is controlled by the respective phase and frequency
+ control inputs. In case the device in features independent
+ controls, then there are dedicated files
+ (out_altvoltageX_pincontrol_frequency_en,
+ out_altvoltageX_pincontrol_phase_en).
-What: /sys/bus/iio/devices/.../ddsX_out_enable
-What: /sys/bus/iio/devices/.../ddsX_outY_enable
+What: /sys/bus/iio/devices/.../out_altvoltageX_out_enable
+What: /sys/bus/iio/devices/.../out_altvoltageX_outY_enable
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
- ddsX_outY_enable controls signal generation on output Y of
- channel X. Y may be suppressed if all channels are
+ out_altvoltageX_outY_enable controls signal generation on
+ output Y of channel X. Y may be suppressed if all channels are
controlled together.
-What: /sys/bus/iio/devices/.../ddsX_outY_wavetype
+What: /sys/bus/iio/devices/.../out_altvoltageX_outY_wavetype
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
@@ -86,7 +89,7 @@ Description:
For a list of available output waveform options read
available_output_modes.
-What: /sys/bus/iio/devices/.../ddsX_outY_wavetype_available
+What: /sys/bus/iio/devices/.../out_altvoltageX_outY_wavetype_available
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-light b/drivers/staging/iio/Documentation/sysfs-bus-iio-light
index edbf470e4e30..715c74dcb53a 100644
--- a/drivers/staging/iio/Documentation/sysfs-bus-iio-light
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-light
@@ -26,7 +26,7 @@ Description:
Hardware dependent list of possible values supported for the
adc_resolution of the given sensor.
-What: /sys/bus/iio/devices/device[n]/illuminance0[_input|_raw]
+What: /sys/bus/iio/devices/device[n]/in_illuminance0[_input|_raw]
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
@@ -45,7 +45,7 @@ Description:
do this calculation manually by reading the infrared sensor
value and doing the negation in sw.
-What: /sys/bus/iio/devices/device[n]/proximity[_input|_raw]
+What: /sys/bus/iio/devices/device[n]/in_proximity[_input|_raw]
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
@@ -63,23 +63,22 @@ Description:
and if expressed in SI units, should include _input. If this
value is not in SI units, then it should include _raw.
-What: /sys/bus/iio/devices/device[n]/illuminance0_target
+What: /sys/bus/iio/devices/device[n]/in_illuminance0_target
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
This property gets/sets the last known external
lux measurement used in/for calibration.
-What: /sys/bus/iio/devices/device[n]/illuminance0_integration_time
+What: /sys/bus/iio/devices/device[n]/in_illuminance0_integration_time
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
This property gets/sets the sensors ADC analog integration time.
-What: /sys/bus/iio/devices/device[n]/illuminance0_calibscale
+What: /sys/bus/iio/devices/device[n]/in_illuminance0_lux_table
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
- Hardware or software applied calibration scale factor assumed
- to account for attenuation due to industrial design (glass
- filters or aperture holes).
+ This property gets/sets the table of coefficients
+ used in calculating illuminance in lux.
diff --git a/drivers/staging/iio/Documentation/trigger.txt b/drivers/staging/iio/Documentation/trigger.txt
index fc2012ebc100..75cc37ff1ed0 100644
--- a/drivers/staging/iio/Documentation/trigger.txt
+++ b/drivers/staging/iio/Documentation/trigger.txt
@@ -5,7 +5,7 @@ an IIO device. Whilst this can create device specific complexities
such triggers are registered with the core in the same way as
stand-alone triggers.
-struct iio_trig *trig = iio_allocate_trigger("<trigger format string>", ...);
+struct iio_trig *trig = iio_trigger_alloc("<trigger format string>", ...);
allocates a trigger structure. The key elements to then fill in within
a driver are:
diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig
index fe1586718880..3c8e5ec26ac1 100644
--- a/drivers/staging/iio/Kconfig
+++ b/drivers/staging/iio/Kconfig
@@ -1,16 +1,9 @@
#
# Industrial I/O subsytem configuration
#
+menu "IIO staging drivers"
+ depends on IIO
-menuconfig IIO
- tristate "Industrial I/O support"
- depends on GENERIC_HARDIRQS
- help
- The industrial I/O subsystem provides a unified framework for
- drivers for many different types of embedded sensors using a
- number of different physical interfaces (i2c, spi, etc). See
- drivers/staging/iio/Documentation for more information.
-if IIO
config IIO_ST_HWMON
tristate "Hwmon driver that uses channels specified via iio maps"
depends on HWMON
@@ -19,12 +12,6 @@ config IIO_ST_HWMON
map allows IIO devices to provide basic hwmon functionality
for those channels specified in the map.
-config IIO_BUFFER
- bool "Enable buffer support within IIO"
- help
- Provide core support for various buffer based data
- acquisition methods.
-
if IIO_BUFFER
config IIO_SW_RING
@@ -36,39 +23,14 @@ config IIO_SW_RING
with the intention that some devices would be able to write
in interrupt context.
-config IIO_KFIFO_BUF
- select IIO_TRIGGER
- tristate "Industrial I/O buffering based on kfifo"
- help
- A simple fifo based on kfifo. Use this if you want a fifo
- rather than a ring buffer. Note that this currently provides
- no buffer events so it is up to userspace to work out how
- often to read from the buffer.
-
endif # IIO_BUFFER
-config IIO_TRIGGER
- boolean "Enable triggered sampling support"
- help
- Provides IIO core support for triggers. Currently these
- are used to initialize capture of samples to push into
- ring buffers. The triggers are effectively a 'capture
- data now' interrupt.
-
-config IIO_CONSUMERS_PER_TRIGGER
- int "Maximum number of consumers per trigger"
- depends on IIO_TRIGGER
- default "2"
- help
- This value controls the maximum number of consumers that a
- given trigger may handle. Default is 2.
-
source "drivers/staging/iio/accel/Kconfig"
source "drivers/staging/iio/adc/Kconfig"
source "drivers/staging/iio/addac/Kconfig"
source "drivers/staging/iio/cdc/Kconfig"
source "drivers/staging/iio/dac/Kconfig"
-source "drivers/staging/iio/dds/Kconfig"
+source "drivers/staging/iio/frequency/Kconfig"
source "drivers/staging/iio/gyro/Kconfig"
source "drivers/staging/iio/impedance-analyzer/Kconfig"
source "drivers/staging/iio/imu/Kconfig"
@@ -104,4 +66,4 @@ config IIO_SIMPLE_DUMMY_BUFFER
endif # IIO_SIMPLE_DUMMY
-endif # IIO
+endmenu
diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile
index 5075291dda7a..6a46d5afb380 100644
--- a/drivers/staging/iio/Makefile
+++ b/drivers/staging/iio/Makefile
@@ -2,13 +2,7 @@
# Makefile for the industrial I/O core.
#
-obj-$(CONFIG_IIO) += industrialio.o
-industrialio-y := industrialio-core.o industrialio-event.o inkern.o
-industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o
-industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
-
obj-$(CONFIG_IIO_SW_RING) += ring_sw.o
-obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
obj-$(CONFIG_IIO_SIMPLE_DUMMY) += iio_dummy.o
iio_dummy-y := iio_simple_dummy.o
@@ -24,7 +18,7 @@ obj-y += adc/
obj-y += addac/
obj-y += cdc/
obj-y += dac/
-obj-y += dds/
+obj-y += frequency/
obj-y += gyro/
obj-y += impedance-analyzer/
obj-y += imu/
diff --git a/drivers/staging/iio/TODO b/drivers/staging/iio/TODO
index d1ad35e24abb..cf3f9489b9da 100644
--- a/drivers/staging/iio/TODO
+++ b/drivers/staging/iio/TODO
@@ -67,7 +67,7 @@ e-mailing the normal IIO list (see below).
Documentation
1) Lots of cleanup and expansion.
-2) Some device require indvidual docs.
+2) Some device require individual docs.
Contact: Jonathan Cameron <jic23@cam.ac.uk>.
Mailing list: linux-iio@vger.kernel.org
diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
index d439e45d07fa..02b340919c0e 100644
--- a/drivers/staging/iio/accel/adis16201_core.c
+++ b/drivers/staging/iio/accel/adis16201_core.c
@@ -15,9 +15,9 @@
#include <linux/sysfs.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "adis16201.h"
@@ -171,7 +171,7 @@ static ssize_t adis16201_write_reset(struct device *dev,
ret = strtobool(buf, &res);
if (ret || !res)
return ret;
- return adis16201_reset(dev_get_drvdata(dev));
+ return adis16201_reset(dev_to_iio_dev(dev));
}
int adis16201_set_irq(struct iio_dev *indio_dev, bool enable)
@@ -298,7 +298,7 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
s16 val16;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
addr = adis16201_addresses[chan->address][0];
ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16);
@@ -406,39 +406,104 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
}
static struct iio_chan_spec adis16201_channels[] = {
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0,
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "supply",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- in_supply, ADIS16201_SCAN_SUPPLY,
- IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
+ .address = in_supply,
+ .scan_index = ADIS16201_SCAN_SUPPLY,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
- temp, ADIS16201_SCAN_TEMP,
- IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
+ .address = temp,
+ .scan_index = ADIS16201_SCAN_TEMP,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
- accel_x, ADIS16201_SCAN_ACC_X,
- IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
+ .address = accel_x,
+ .scan_index = ADIS16201_SCAN_ACC_X,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
- accel_y, ADIS16201_SCAN_ACC_Y,
- IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
+ .address = accel_y,
+ .scan_index = ADIS16201_SCAN_ACC_Y,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- in_aux, ADIS16201_SCAN_AUX_ADC,
- IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X,
+ .address = in_aux,
+ .scan_index = ADIS16201_SCAN_AUX_ADC,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_INCLI,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
- incli_x, ADIS16201_SCAN_INCLI_X,
- IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y,
+ .address = incli_x,
+ .scan_index = ADIS16201_SCAN_INCLI_X,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_INCLI,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
- incli_y, ADIS16201_SCAN_INCLI_Y,
- IIO_ST('s', 14, 16, 0), 0),
+ .address = incli_y,
+ .scan_index = ADIS16201_SCAN_INCLI_Y,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ },
IIO_CHAN_SOFT_TIMESTAMP(7)
};
@@ -467,7 +532,7 @@ static int __devinit adis16201_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -522,7 +587,7 @@ error_uninitialize_ring:
error_unreg_ring_funcs:
adis16201_unconfigure_ring(indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -535,7 +600,7 @@ static int adis16201_remove(struct spi_device *spi)
adis16201_remove_trigger(indio_dev);
iio_buffer_unregister(indio_dev);
adis16201_unconfigure_ring(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c
index 97f9e6b159d9..247602a8e54c 100644
--- a/drivers/staging/iio/accel/adis16201_ring.c
+++ b/drivers/staging/iio/accel/adis16201_ring.c
@@ -5,9 +5,9 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/trigger_consumer.h>
#include "adis16201.h"
@@ -66,9 +66,8 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p)
int i = 0;
s16 *data;
- size_t datasize = ring->access->get_bytes_per_datum(ring);
- data = kmalloc(datasize, GFP_KERNEL);
+ data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
return -ENOMEM;
@@ -81,7 +80,7 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p)
data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
- if (ring->scan_timestamp)
+ if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
ring->access->store_to(ring, (u8 *)data, pf->timestamp);
diff --git a/drivers/staging/iio/accel/adis16201_trigger.c b/drivers/staging/iio/accel/adis16201_trigger.c
index bce505e716d0..96fdabbac201 100644
--- a/drivers/staging/iio/accel/adis16201_trigger.c
+++ b/drivers/staging/iio/accel/adis16201_trigger.c
@@ -3,8 +3,8 @@
#include <linux/spi/spi.h>
#include <linux/export.h>
-#include "../iio.h"
-#include "../trigger.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
#include "adis16201.h"
/**
@@ -29,7 +29,7 @@ int adis16201_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct adis16201_state *st = iio_priv(indio_dev);
- st->trig = iio_allocate_trigger("adis16201-dev%d", indio_dev->id);
+ st->trig = iio_trigger_alloc("adis16201-dev%d", indio_dev->id);
if (st->trig == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -56,7 +56,7 @@ int adis16201_probe_trigger(struct iio_dev *indio_dev)
error_free_irq:
free_irq(st->us->irq, st->trig);
error_free_trig:
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
error_ret:
return ret;
}
@@ -67,5 +67,5 @@ void adis16201_remove_trigger(struct iio_dev *indio_dev)
iio_trigger_unregister(state->trig);
free_irq(state->us->irq, state->trig);
- iio_free_trigger(state->trig);
+ iio_trigger_free(state->trig);
}
diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
index 1a5140f9e3f4..15d46bfd1b42 100644
--- a/drivers/staging/iio/accel/adis16203_core.c
+++ b/drivers/staging/iio/accel/adis16203_core.c
@@ -15,9 +15,9 @@
#include <linux/sysfs.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "adis16203.h"
@@ -182,7 +182,7 @@ static ssize_t adis16203_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
if (len < 1)
return -EINVAL;
switch (buf[0]) {
@@ -305,7 +305,7 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
u8 addr;
s16 val16;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
addr = adis16203_addresses[chan->address][0];
ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16);
@@ -372,29 +372,75 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
}
static struct iio_chan_spec adis16203_channels[] = {
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- in_supply, ADIS16203_SCAN_SUPPLY,
- IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- in_aux, ADIS16203_SCAN_AUX_ADC,
- IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X,
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
- incli_x, ADIS16203_SCAN_INCLI_X,
- IIO_ST('s', 14, 16, 0), 0),
- /* Fixme: Not what it appears to be - see data sheet */
- IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- incli_y, ADIS16203_SCAN_INCLI_Y,
- IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
- IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
- temp, ADIS16203_SCAN_TEMP,
- IIO_ST('u', 12, 16, 0), 0),
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "supply",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .address = in_supply,
+ .scan_index = ADIS16203_SCAN_SUPPLY,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .address = in_aux,
+ .scan_index = ADIS16203_SCAN_AUX_ADC,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_INCLI,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+ .address = incli_x,
+ .scan_index = ADIS16203_SCAN_INCLI_X,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ }, { /* Fixme: Not what it appears to be - see data sheet */
+ .type = IIO_INCLI,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = incli_y,
+ .scan_index = ADIS16203_SCAN_INCLI_Y,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
+ .address = temp,
+ .scan_index = ADIS16203_SCAN_TEMP,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ },
IIO_CHAN_SOFT_TIMESTAMP(5),
};
@@ -423,7 +469,7 @@ static int __devinit adis16203_probe(struct spi_device *spi)
struct adis16203_state *st;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -477,7 +523,7 @@ error_uninitialize_ring:
error_unreg_ring_funcs:
adis16203_unconfigure_ring(indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -490,7 +536,7 @@ static int adis16203_remove(struct spi_device *spi)
adis16203_remove_trigger(indio_dev);
iio_buffer_unregister(indio_dev);
adis16203_unconfigure_ring(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c
index 6a8963db4f60..7bbd2c2bbd19 100644
--- a/drivers/staging/iio/accel/adis16203_ring.c
+++ b/drivers/staging/iio/accel/adis16203_ring.c
@@ -5,20 +5,19 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/trigger_consumer.h>
#include "adis16203.h"
/**
* adis16203_read_ring_data() read data registers which will be placed into ring
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @indio_dev: the IIO device
* @rx: somewhere to pass back the value read
**/
-static int adis16203_read_ring_data(struct device *dev, u8 *rx)
+static int adis16203_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16203_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[ADIS16203_OUTPUTS + 1];
int ret;
@@ -66,22 +65,21 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p)
int i = 0;
s16 *data;
- size_t datasize = ring->access->get_bytes_per_datum(ring);
- data = kmalloc(datasize, GFP_KERNEL);
+ data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
return -ENOMEM;
}
if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
- adis16203_read_ring_data(&indio_dev->dev, st->rx) >= 0)
+ adis16203_read_ring_data(indio_dev, st->rx) >= 0)
for (; i < bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength); i++)
data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
- if (ring->scan_timestamp)
+ if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
ring->access->store_to(ring,
diff --git a/drivers/staging/iio/accel/adis16203_trigger.c b/drivers/staging/iio/accel/adis16203_trigger.c
index 24bcb8e15c55..b8a04073d6d7 100644
--- a/drivers/staging/iio/accel/adis16203_trigger.c
+++ b/drivers/staging/iio/accel/adis16203_trigger.c
@@ -3,8 +3,8 @@
#include <linux/spi/spi.h>
#include <linux/export.h>
-#include "../iio.h"
-#include "../trigger.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
#include "adis16203.h"
/**
@@ -29,7 +29,7 @@ int adis16203_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct adis16203_state *st = iio_priv(indio_dev);
- st->trig = iio_allocate_trigger("adis16203-dev%d", indio_dev->id);
+ st->trig = iio_trigger_alloc("adis16203-dev%d", indio_dev->id);
if (st->trig == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -58,7 +58,7 @@ int adis16203_probe_trigger(struct iio_dev *indio_dev)
error_free_irq:
free_irq(st->us->irq, st->trig);
error_free_trig:
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
error_ret:
return ret;
}
@@ -69,5 +69,5 @@ void adis16203_remove_trigger(struct iio_dev *indio_dev)
iio_trigger_unregister(st->trig);
free_irq(st->us->irq, st->trig);
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
}
diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
index fa89364b841e..ac9d95e4ea47 100644
--- a/drivers/staging/iio/accel/adis16204_core.c
+++ b/drivers/staging/iio/accel/adis16204_core.c
@@ -18,9 +18,9 @@
#include <linux/list.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "adis16204.h"
@@ -173,7 +173,7 @@ static ssize_t adis16204_read_14bit_signed(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
s16 val = 0;
ssize_t ret;
@@ -211,7 +211,7 @@ static ssize_t adis16204_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
if (len < 1)
return -EINVAL;
@@ -342,7 +342,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
int addrind;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
addr = adis16204_addresses[chan->address][0];
ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
@@ -444,31 +444,78 @@ static int adis16204_write_raw(struct iio_dev *indio_dev,
}
static struct iio_chan_spec adis16204_channels[] = {
- IIO_CHAN(IIO_VOLTAGE, 0, 0, 0, "supply", 0, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- in_supply, ADIS16204_SCAN_SUPPLY,
- IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- in_aux, ADIS16204_SCAN_AUX_ADC,
- IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
- IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
- temp, ADIS16204_SCAN_TEMP,
- IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
- IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
- accel_x, ADIS16204_SCAN_ACC_X,
- IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
- IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
- accel_y, ADIS16204_SCAN_ACC_Y,
- IIO_ST('s', 14, 16, 0), 0),
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1, /* Note was not previously indexed */
+ .channel = 0,
+ .extend_name = "supply",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .address = in_supply,
+ .scan_index = ADIS16204_SCAN_SUPPLY,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .address = in_aux,
+ .scan_index = ADIS16204_SCAN_AUX_ADC,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
+ .address = temp,
+ .scan_index = ADIS16204_SCAN_TEMP,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
+ .address = accel_x,
+ .scan_index = ADIS16204_SCAN_ACC_X,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
+ .address = accel_y,
+ .scan_index = ADIS16204_SCAN_ACC_Y,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ },
IIO_CHAN_SOFT_TIMESTAMP(5),
};
@@ -498,7 +545,7 @@ static int __devinit adis16204_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -551,7 +598,7 @@ error_uninitialize_ring:
error_unreg_ring_funcs:
adis16204_unconfigure_ring(indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -564,7 +611,7 @@ static int adis16204_remove(struct spi_device *spi)
adis16204_remove_trigger(indio_dev);
iio_buffer_unregister(indio_dev);
adis16204_unconfigure_ring(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c
index 5c8ab7338864..f73518bc6587 100644
--- a/drivers/staging/iio/accel/adis16204_ring.c
+++ b/drivers/staging/iio/accel/adis16204_ring.c
@@ -5,20 +5,19 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/trigger_consumer.h>
#include "adis16204.h"
/**
* adis16204_read_ring_data() read data registers which will be placed into ring
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @indio_dev: the IIO device
* @rx: somewhere to pass back the value read
**/
-static int adis16204_read_ring_data(struct device *dev, u8 *rx)
+static int adis16204_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16204_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[ADIS16204_OUTPUTS + 1];
int ret;
@@ -63,22 +62,21 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p)
struct iio_buffer *ring = indio_dev->buffer;
int i = 0;
s16 *data;
- size_t datasize = ring->access->get_bytes_per_datum(ring);
- data = kmalloc(datasize, GFP_KERNEL);
+ data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
return -ENOMEM;
}
if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
- adis16204_read_ring_data(&indio_dev->dev, st->rx) >= 0)
+ adis16204_read_ring_data(indio_dev, st->rx) >= 0)
for (; i < bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength); i++)
data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
- if (ring->scan_timestamp)
+ if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
ring->access->store_to(ring, (u8 *)data, pf->timestamp);
diff --git a/drivers/staging/iio/accel/adis16204_trigger.c b/drivers/staging/iio/accel/adis16204_trigger.c
index 6e542af02c09..408a1682368e 100644
--- a/drivers/staging/iio/accel/adis16204_trigger.c
+++ b/drivers/staging/iio/accel/adis16204_trigger.c
@@ -3,8 +3,8 @@
#include <linux/spi/spi.h>
#include <linux/export.h>
-#include "../iio.h"
-#include "../trigger.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
#include "adis16204.h"
/**
@@ -29,7 +29,7 @@ int adis16204_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct adis16204_state *st = iio_priv(indio_dev);
- st->trig = iio_allocate_trigger("adis16204-dev%d", indio_dev->id);
+ st->trig = iio_trigger_alloc("adis16204-dev%d", indio_dev->id);
if (st->trig == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -58,7 +58,7 @@ int adis16204_probe_trigger(struct iio_dev *indio_dev)
error_free_irq:
free_irq(st->us->irq, st->trig);
error_free_trig:
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
error_ret:
return ret;
}
@@ -69,5 +69,5 @@ void adis16204_remove_trigger(struct iio_dev *indio_dev)
iio_trigger_unregister(state->trig);
free_irq(state->us->irq, state->trig);
- iio_free_trigger(state->trig);
+ iio_trigger_free(state->trig);
}
diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
index a98715f6bd6d..f6fd0d31d4f0 100644
--- a/drivers/staging/iio/accel/adis16209_core.c
+++ b/drivers/staging/iio/accel/adis16209_core.c
@@ -16,9 +16,9 @@
#include <linux/list.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "adis16209.h"
@@ -157,7 +157,7 @@ static ssize_t adis16209_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
if (len < 1)
return -EINVAL;
@@ -331,7 +331,7 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
s16 val16;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
addr = adis16209_addresses[chan->address][0];
ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16);
@@ -408,41 +408,114 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
}
static struct iio_chan_spec adis16209_channels[] = {
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- in_supply, ADIS16209_SCAN_SUPPLY,
- IIO_ST('u', 14, 16, 0), 0),
- IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
- IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
- temp, ADIS16209_SCAN_TEMP,
- IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
- accel_x, ADIS16209_SCAN_ACC_X,
- IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
- accel_y, ADIS16209_SCAN_ACC_Y,
- IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- in_aux, ADIS16209_SCAN_AUX_ADC,
- IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- incli_x, ADIS16209_SCAN_INCLI_X,
- IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- incli_y, ADIS16209_SCAN_INCLI_Y,
- IIO_ST('s', 14, 16, 0), 0),
- IIO_CHAN(IIO_ROT, 0, 1, 0, NULL, 0, IIO_MOD_X,
- 0,
- rot, ADIS16209_SCAN_ROT,
- IIO_ST('s', 14, 16, 0), 0),
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "supply",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .address = in_supply,
+ .scan_index = ADIS16209_SCAN_SUPPLY,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 0,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
+ .address = temp,
+ .scan_index = ADIS16209_SCAN_TEMP,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+ .address = accel_x,
+ .scan_index = ADIS16209_SCAN_ACC_X,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+ .address = accel_y,
+ .scan_index = ADIS16209_SCAN_ACC_Y,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .address = in_aux,
+ .scan_index = ADIS16209_SCAN_AUX_ADC,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_INCLI,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = incli_x,
+ .scan_index = ADIS16209_SCAN_INCLI_X,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_INCLI,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = incli_y,
+ .scan_index = ADIS16209_SCAN_INCLI_Y,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_ROT,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+ .address = rot,
+ .scan_index = ADIS16209_SCAN_ROT,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ },
IIO_CHAN_SOFT_TIMESTAMP(8)
};
@@ -471,7 +544,7 @@ static int __devinit adis16209_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -524,7 +597,7 @@ error_uninitialize_ring:
error_unreg_ring_funcs:
adis16209_unconfigure_ring(indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -539,7 +612,7 @@ static int adis16209_remove(struct spi_device *spi)
adis16209_remove_trigger(indio_dev);
iio_buffer_unregister(indio_dev);
adis16209_unconfigure_ring(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c
index 57254b6b38b7..090607504c93 100644
--- a/drivers/staging/iio/accel/adis16209_ring.c
+++ b/drivers/staging/iio/accel/adis16209_ring.c
@@ -5,20 +5,19 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/trigger_consumer.h>
#include "adis16209.h"
/**
* adis16209_read_ring_data() read data registers which will be placed into ring
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @indio_dev: the IIO device
* @rx: somewhere to pass back the value read
**/
-static int adis16209_read_ring_data(struct device *dev, u8 *rx)
+static int adis16209_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16209_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[ADIS16209_OUTPUTS + 1];
int ret;
@@ -61,25 +60,23 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct adis16209_state *st = iio_priv(indio_dev);
struct iio_buffer *ring = indio_dev->buffer;
-
int i = 0;
s16 *data;
- size_t datasize = ring->access->get_bytes_per_datum(ring);
- data = kmalloc(datasize , GFP_KERNEL);
+ data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
return -ENOMEM;
}
if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
- adis16209_read_ring_data(&indio_dev->dev, st->rx) >= 0)
+ adis16209_read_ring_data(indio_dev, st->rx) >= 0)
for (; i < bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength); i++)
data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
- if (ring->scan_timestamp)
+ if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
ring->access->store_to(ring, (u8 *)data, pf->timestamp);
diff --git a/drivers/staging/iio/accel/adis16209_trigger.c b/drivers/staging/iio/accel/adis16209_trigger.c
index c5d82c1a55d9..2ad93dcaf40d 100644
--- a/drivers/staging/iio/accel/adis16209_trigger.c
+++ b/drivers/staging/iio/accel/adis16209_trigger.c
@@ -3,8 +3,8 @@
#include <linux/spi/spi.h>
#include <linux/export.h>
-#include "../iio.h"
-#include "../trigger.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
#include "adis16209.h"
/**
@@ -38,7 +38,7 @@ int adis16209_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct adis16209_state *st = iio_priv(indio_dev);
- st->trig = iio_allocate_trigger("adis16209-dev%d", indio_dev->id);
+ st->trig = iio_trigger_alloc("adis16209-dev%d", indio_dev->id);
if (st->trig == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -66,7 +66,7 @@ int adis16209_probe_trigger(struct iio_dev *indio_dev)
error_free_irq:
free_irq(st->us->irq, st->trig);
error_free_trig:
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
error_ret:
return ret;
}
@@ -77,5 +77,5 @@ void adis16209_remove_trigger(struct iio_dev *indio_dev)
iio_trigger_unregister(st->trig);
free_irq(st->us->irq, st->trig);
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
}
diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
index 51a852d45482..6a9ac898cb01 100644
--- a/drivers/staging/iio/accel/adis16220_core.c
+++ b/drivers/staging/iio/accel/adis16220_core.c
@@ -15,8 +15,8 @@
#include <linux/sysfs.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "adis16220.h"
@@ -145,7 +145,7 @@ static ssize_t adis16220_read_16bit(struct device *dev,
char *buf)
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
ssize_t ret;
s16 val = 0;
@@ -164,7 +164,7 @@ static ssize_t adis16220_write_16bit(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
u16 val;
@@ -208,7 +208,7 @@ static ssize_t adis16220_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
bool val;
int ret;
@@ -228,7 +228,7 @@ static ssize_t adis16220_write_capture(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
bool val;
int ret;
@@ -393,7 +393,7 @@ static ssize_t adis16220_accel_bin_read(struct file *filp, struct kobject *kobj,
size_t count)
{
struct device *dev = container_of(kobj, struct device, kobj);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
return adis16220_capture_buffer_read(indio_dev, buf,
off, count,
@@ -415,7 +415,7 @@ static ssize_t adis16220_adc1_bin_read(struct file *filp, struct kobject *kobj,
size_t count)
{
struct device *dev = container_of(kobj, struct device, kobj);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
return adis16220_capture_buffer_read(indio_dev, buf,
off, count,
@@ -437,7 +437,7 @@ static ssize_t adis16220_adc2_bin_read(struct file *filp, struct kobject *kobj,
size_t count)
{
struct device *dev = container_of(kobj, struct device, kobj);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
return adis16220_capture_buffer_read(indio_dev, buf,
off, count,
@@ -507,7 +507,7 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
u8 bits;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
addrind = 0;
break;
case IIO_CHAN_INFO_OFFSET:
@@ -575,11 +575,13 @@ static const struct iio_chan_spec adis16220_channels[] = {
.indexed = 1,
.channel = 0,
.extend_name = "supply",
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_supply,
}, {
.type = IIO_ACCEL,
- .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
.address = accel,
@@ -587,20 +589,23 @@ static const struct iio_chan_spec adis16220_channels[] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = temp,
}, {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
- .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_1,
}, {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 2,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.address = in_2,
}
};
@@ -629,7 +634,7 @@ static int __devinit adis16220_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -680,7 +685,7 @@ error_rm_accel_bin:
error_unregister_dev:
iio_device_unregister(indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -695,7 +700,7 @@ static int adis16220_remove(struct spi_device *spi)
sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin);
sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin);
iio_device_unregister(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
index 17f77fef7f2b..8b15eaea3381 100644
--- a/drivers/staging/iio/accel/adis16240_core.c
+++ b/drivers/staging/iio/accel/adis16240_core.c
@@ -19,9 +19,9 @@
#include <linux/list.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "adis16240.h"
@@ -154,7 +154,7 @@ static ssize_t adis16240_spi_read_signed(struct device *dev,
char *buf,
unsigned bits)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
int ret;
s16 val = 0;
unsigned shift = 16 - bits;
@@ -177,7 +177,7 @@ static ssize_t adis16240_read_12bit_signed(struct device *dev,
char *buf)
{
ssize_t ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
/* Take the iio_dev status lock */
mutex_lock(&indio_dev->mlock);
@@ -203,7 +203,7 @@ static ssize_t adis16240_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
if (len < 1)
return -EINVAL;
@@ -365,7 +365,7 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
s16 val16;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
addr = adis16240_addresses[chan->address][0];
ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
@@ -468,33 +468,88 @@ static int adis16240_write_raw(struct iio_dev *indio_dev,
}
static struct iio_chan_spec adis16240_channels[] = {
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- in_supply, ADIS16240_SCAN_SUPPLY,
- IIO_ST('u', 10, 16, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
- 0,
- in_aux, ADIS16240_SCAN_AUX_ADC,
- IIO_ST('u', 10, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
- accel_x, ADIS16240_SCAN_ACC_X,
- IIO_ST('s', 10, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
- accel_y, ADIS16240_SCAN_ACC_Y,
- IIO_ST('s', 10, 16, 0), 0),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z,
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
- accel_z, ADIS16240_SCAN_ACC_Z,
- IIO_ST('s', 10, 16, 0), 0),
- IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- temp, ADIS16240_SCAN_TEMP,
- IIO_ST('u', 10, 16, 0), 0),
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "supply",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .address = in_supply,
+ .scan_index = ADIS16240_SCAN_SUPPLY,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 10,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+ .address = in_aux,
+ .scan_index = ADIS16240_SCAN_AUX_ADC,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 10,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+ .address = accel_x,
+ .scan_index = ADIS16240_SCAN_ACC_X,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 10,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+ .address = accel_y,
+ .scan_index = ADIS16240_SCAN_ACC_Y,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 10,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+ .address = accel_z,
+ .scan_index = ADIS16240_SCAN_ACC_Z,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 10,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .address = temp,
+ .scan_index = ADIS16240_SCAN_TEMP,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 10,
+ .storagebits = 16,
+ },
+ },
IIO_CHAN_SOFT_TIMESTAMP(6)
};
@@ -523,7 +578,7 @@ static int __devinit adis16240_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -576,7 +631,7 @@ error_uninitialize_ring:
error_unreg_ring_funcs:
adis16240_unconfigure_ring(indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -592,7 +647,7 @@ static int adis16240_remove(struct spi_device *spi)
adis16240_remove_trigger(indio_dev);
iio_buffer_unregister(indio_dev);
adis16240_unconfigure_ring(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c
index 43ba84e993ad..86a2a4757ea7 100644
--- a/drivers/staging/iio/accel/adis16240_ring.c
+++ b/drivers/staging/iio/accel/adis16240_ring.c
@@ -5,20 +5,19 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/trigger_consumer.h>
#include "adis16240.h"
/**
* adis16240_read_ring_data() read data registers which will be placed into ring
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @indio_dev: the IIO device
* @rx: somewhere to pass back the value read
**/
-static int adis16240_read_ring_data(struct device *dev, u8 *rx)
+static int adis16240_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16240_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[ADIS16240_OUTPUTS + 1];
int ret;
@@ -61,22 +60,21 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p)
int i = 0;
s16 *data;
- size_t datasize = ring->access->get_bytes_per_datum(ring);
- data = kmalloc(datasize, GFP_KERNEL);
+ data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
return -ENOMEM;
}
if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
- adis16240_read_ring_data(&indio_dev->dev, st->rx) >= 0)
+ adis16240_read_ring_data(indio_dev, st->rx) >= 0)
for (; i < bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength); i++)
data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
- if (ring->scan_timestamp)
+ if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
ring->access->store_to(ring, (u8 *)data, pf->timestamp);
diff --git a/drivers/staging/iio/accel/adis16240_trigger.c b/drivers/staging/iio/accel/adis16240_trigger.c
index 8e0ce568e64c..fa90a22b143e 100644
--- a/drivers/staging/iio/accel/adis16240_trigger.c
+++ b/drivers/staging/iio/accel/adis16240_trigger.c
@@ -3,8 +3,8 @@
#include <linux/spi/spi.h>
#include <linux/export.h>
-#include "../iio.h"
-#include "../trigger.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
#include "adis16240.h"
/**
@@ -38,7 +38,7 @@ int adis16240_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct adis16240_state *st = iio_priv(indio_dev);
- st->trig = iio_allocate_trigger("adis16240-dev%d", indio_dev->id);
+ st->trig = iio_trigger_alloc("adis16240-dev%d", indio_dev->id);
if (st->trig == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -67,7 +67,7 @@ int adis16240_probe_trigger(struct iio_dev *indio_dev)
error_free_irq:
free_irq(st->us->irq, st->trig);
error_free_trig:
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
error_ret:
return ret;
}
@@ -78,5 +78,5 @@ void adis16240_remove_trigger(struct iio_dev *indio_dev)
iio_trigger_unregister(st->trig);
free_irq(st->us->irq, st->trig);
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
}
diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c
index d13d7215ff6e..8cf7cd943c90 100644
--- a/drivers/staging/iio/accel/kxsd9.c
+++ b/drivers/staging/iio/accel/kxsd9.c
@@ -23,8 +23,8 @@
#include <linux/slab.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#define KXSD9_REG_X 0x00
#define KXSD9_REG_Y 0x02
@@ -158,7 +158,7 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev,
struct kxsd9_state *st = iio_priv(indio_dev);
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
ret = kxsd9_read(indio_dev, chan->address);
if (ret < 0)
goto error_ret;
@@ -181,7 +181,8 @@ error_ret:
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = KXSD9_REG_##axis, \
}
@@ -189,6 +190,7 @@ static struct iio_chan_spec kxsd9_channels[] = {
KXSD9_ACCEL_CHAN(X), KXSD9_ACCEL_CHAN(Y), KXSD9_ACCEL_CHAN(Z),
{
.type = IIO_VOLTAGE,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.indexed = 1,
.address = KXSD9_REG_AUX,
}
@@ -226,7 +228,7 @@ static int __devinit kxsd9_probe(struct spi_device *spi)
struct kxsd9_state *st;
int ret = 0;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -254,7 +256,7 @@ static int __devinit kxsd9_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -262,7 +264,7 @@ error_ret:
static int __devexit kxsd9_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_free_device(spi_get_drvdata(spi));
+ iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
index 376da5137967..9d263484fb86 100644
--- a/drivers/staging/iio/accel/lis3l02dq_core.c
+++ b/drivers/staging/iio/accel/lis3l02dq_core.c
@@ -23,10 +23,10 @@
#include <linux/sysfs.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../events.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+#include <linux/iio/buffer.h>
#include "lis3l02dq.h"
@@ -257,7 +257,7 @@ static int lis3l02dq_read_raw(struct iio_dev *indio_dev,
u8 reg;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
/* Take the iio_dev status lock */
mutex_lock(&indio_dev->mlock);
if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
@@ -297,7 +297,7 @@ static ssize_t lis3l02dq_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
int ret, len = 0;
s8 t;
ret = lis3l02dq_spi_read_reg_8(indio_dev,
@@ -328,7 +328,7 @@ static ssize_t lis3l02dq_write_frequency(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
unsigned long val;
int ret;
u8 t;
@@ -513,7 +513,8 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private)
}
#define LIS3L02DQ_INFO_MASK \
- (IIO_CHAN_INFO_SCALE_SHARED_BIT | \
+ (IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT | \
IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT)
@@ -521,13 +522,26 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private)
(IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
+#define LIS3L02DQ_CHAN(index, mod) \
+ { \
+ .type = IIO_ACCEL, \
+ .modified = 1, \
+ .channel2 = mod, \
+ .info_mask = LIS3L02DQ_INFO_MASK, \
+ .address = index, \
+ .scan_index = index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ }, \
+ .event_mask = LIS3L02DQ_EVENT_MASK, \
+ }
+
static struct iio_chan_spec lis3l02dq_channels[] = {
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, LIS3L02DQ_INFO_MASK,
- 0, 0, IIO_ST('s', 12, 16, 0), LIS3L02DQ_EVENT_MASK),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, LIS3L02DQ_INFO_MASK,
- 1, 1, IIO_ST('s', 12, 16, 0), LIS3L02DQ_EVENT_MASK),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, LIS3L02DQ_INFO_MASK,
- 2, 2, IIO_ST('s', 12, 16, 0), LIS3L02DQ_EVENT_MASK),
+ LIS3L02DQ_CHAN(0, IIO_MOD_X),
+ LIS3L02DQ_CHAN(1, IIO_MOD_Y),
+ LIS3L02DQ_CHAN(2, IIO_MOD_Z),
IIO_CHAN_SOFT_TIMESTAMP(3)
};
@@ -666,7 +680,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi)
struct lis3l02dq_state *st;
struct iio_dev *indio_dev;
- indio_dev = iio_allocate_device(sizeof *st);
+ indio_dev = iio_device_alloc(sizeof *st);
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -724,7 +738,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi)
return 0;
error_remove_trigger:
- if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
+ if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)))
lis3l02dq_remove_trigger(indio_dev);
error_free_interrupt:
if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
@@ -734,7 +748,7 @@ error_uninitialize_buffer:
error_unreg_buffer_funcs:
lis3l02dq_unconfigure_buffer(indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -789,7 +803,7 @@ static int lis3l02dq_remove(struct spi_device *spi)
iio_buffer_unregister(indio_dev);
lis3l02dq_unconfigure_buffer(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
err_ret:
return ret;
}
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index 0fc3973f32ae..51b00dfc0465 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -6,11 +6,11 @@
#include <linux/slab.h>
#include <linux/export.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#include "../ring_sw.h"
-#include "../kfifo_buf.h"
-#include "../trigger.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
#include "lis3l02dq.h"
/**
@@ -137,9 +137,9 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct iio_buffer *buffer = indio_dev->buffer;
int len = 0;
- size_t datasize = buffer->access->get_bytes_per_datum(buffer);
- char *data = kmalloc(datasize, GFP_KERNEL);
+ char *data;
+ data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL) {
dev_err(indio_dev->dev.parent,
"memory alloc failed in buffer bh");
@@ -150,7 +150,7 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p)
len = lis3l02dq_get_buffer_element(indio_dev, data);
/* Guaranteed to be aligned with 8 byte boundary */
- if (buffer->scan_timestamp)
+ if (indio_dev->scan_timestamp)
*(s64 *)(((phys_addr_t)data + len
+ sizeof(s64) - 1) & ~(sizeof(s64) - 1))
= pf->timestamp;
@@ -163,12 +163,11 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p)
/* Caller responsible for locking as necessary. */
static int
-__lis3l02dq_write_data_ready_config(struct device *dev, bool state)
+__lis3l02dq_write_data_ready_config(struct iio_dev *indio_dev, bool state)
{
int ret;
u8 valold;
bool currentlyset;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct lis3l02dq_state *st = iio_priv(indio_dev);
/* Get the current event mask register */
@@ -236,7 +235,7 @@ static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig,
int ret = 0;
u8 t;
- __lis3l02dq_write_data_ready_config(&indio_dev->dev, state);
+ __lis3l02dq_write_data_ready_config(indio_dev, state);
if (state == false) {
/*
* A possible quirk with the handler is currently worked around
@@ -286,7 +285,7 @@ int lis3l02dq_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct lis3l02dq_state *st = iio_priv(indio_dev);
- st->trig = iio_allocate_trigger("lis3l02dq-dev%d", indio_dev->id);
+ st->trig = iio_trigger_alloc("lis3l02dq-dev%d", indio_dev->id);
if (!st->trig) {
ret = -ENOMEM;
goto error_ret;
@@ -302,7 +301,7 @@ int lis3l02dq_probe_trigger(struct iio_dev *indio_dev)
return 0;
error_free_trig:
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
error_ret:
return ret;
}
@@ -312,7 +311,7 @@ void lis3l02dq_remove_trigger(struct iio_dev *indio_dev)
struct lis3l02dq_state *st = iio_priv(indio_dev);
iio_trigger_unregister(st->trig);
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
}
void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev)
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index 49764fb7181c..6ec5c204ff1d 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -18,10 +18,10 @@
#include <linux/spi/spi.h>
#include <linux/sysfs.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../events.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+#include <linux/iio/buffer.h>
#include "sca3000.h"
@@ -241,7 +241,7 @@ error_ret:
static int sca3000_check_status(struct device *dev)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
mutex_lock(&st->lock);
@@ -268,7 +268,7 @@ static ssize_t sca3000_show_rev(struct device *dev,
char *buf)
{
int len = 0, ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
mutex_lock(&st->lock);
@@ -296,7 +296,7 @@ sca3000_show_available_measurement_modes(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
int len = 0;
@@ -328,7 +328,7 @@ sca3000_show_measurement_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
int len = 0, ret;
@@ -379,7 +379,7 @@ sca3000_store_measurement_mode(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
int ret;
u8 mask = 0x03;
@@ -429,17 +429,31 @@ static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0);
#define SCA3000_INFO_MASK \
- IIO_CHAN_INFO_SCALE_SHARED_BIT
+ IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SHARED_BIT
#define SCA3000_EVENT_MASK \
(IIO_EV_BIT(IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING))
+#define SCA3000_CHAN(index, mod) \
+ { \
+ .type = IIO_ACCEL, \
+ .modified = 1, \
+ .channel2 = mod, \
+ .info_mask = SCA3000_INFO_MASK, \
+ .address = index, \
+ .scan_index = index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 11, \
+ .storagebits = 16, \
+ .shift = 5, \
+ }, \
+ .event_mask = SCA3000_EVENT_MASK, \
+ }
+
static struct iio_chan_spec sca3000_channels[] = {
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, SCA3000_INFO_MASK,
- 0, 0, IIO_ST('s', 11, 16, 5), SCA3000_EVENT_MASK),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, SCA3000_INFO_MASK,
- 1, 1, IIO_ST('s', 11, 16, 5), SCA3000_EVENT_MASK),
- IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, SCA3000_INFO_MASK,
- 2, 2, IIO_ST('s', 11, 16, 5), SCA3000_EVENT_MASK),
+ SCA3000_CHAN(0, IIO_MOD_X),
+ SCA3000_CHAN(1, IIO_MOD_Y),
+ SCA3000_CHAN(2, IIO_MOD_Z),
};
static u8 sca3000_addresses[3][3] = {
@@ -462,7 +476,7 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
u8 address;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&st->lock);
if (st->mo_det_use_count) {
mutex_unlock(&st->lock);
@@ -503,7 +517,7 @@ static ssize_t sca3000_read_av_freq(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
int len = 0, ret, val;
@@ -574,7 +588,7 @@ static ssize_t sca3000_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
int ret, len = 0, base_freq = 0, val;
@@ -616,7 +630,7 @@ static ssize_t sca3000_set_frequency(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
int ret, base_freq = 0;
int ctrlval;
@@ -676,7 +690,7 @@ static ssize_t sca3000_read_temp(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
int ret;
int val;
@@ -897,7 +911,7 @@ static ssize_t sca3000_query_free_fall_mode(struct device *dev,
char *buf)
{
int ret, len;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
int val;
@@ -925,7 +939,7 @@ static ssize_t sca3000_set_free_fall_mode(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
long val;
int ret;
@@ -1131,7 +1145,7 @@ static int __devinit sca3000_probe(struct spi_device *spi)
struct sca3000_state *st;
struct iio_dev *indio_dev;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -1195,7 +1209,7 @@ error_unregister_ring:
error_unregister_dev:
iio_device_unregister(indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
@@ -1233,7 +1247,7 @@ static int sca3000_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
iio_buffer_unregister(indio_dev);
sca3000_unconfigure_ring(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c
index 6b824a11f7f4..b7e1a002630a 100644
--- a/drivers/staging/iio/accel/sca3000_ring.c
+++ b/drivers/staging/iio/accel/sca3000_ring.c
@@ -18,9 +18,9 @@
#include <linux/sched.h>
#include <linux/poll.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "../ring_hw.h"
#include "sca3000.h"
@@ -157,7 +157,7 @@ static ssize_t sca3000_query_ring_int(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret, val;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
mutex_lock(&st->lock);
@@ -178,7 +178,7 @@ static ssize_t sca3000_set_ring_int(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
long val;
@@ -219,7 +219,7 @@ static ssize_t sca3000_show_buffer_scale(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
return sprintf(buf, "0.%06d\n", 4*st->info->scale);
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 592eabd85f36..2490dd25093b 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -25,7 +25,7 @@ config AD7606
depends on GPIOLIB
select IIO_BUFFER
select IIO_TRIGGER
- select IIO_SW_RING
+ select IIO_KFIFO_BUF
help
Say yes here to build support for Analog Devices:
ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC).
@@ -63,7 +63,7 @@ config AD799X_RING_BUFFER
bool "Analog Devices AD799x: use ring buffer"
depends on AD799X
select IIO_BUFFER
- select IIO_SW_RING
+ select IIO_KFIFO_BUF
help
Say yes here to include ring buffer support in the AD799X
ADC driver.
@@ -72,7 +72,7 @@ config AD7476
tristate "Analog Devices AD7475/6/7/8 AD7466/7/8 and AD7495 ADC driver"
depends on SPI
select IIO_BUFFER
- select IIO_SW_RING
+ select IIO_KFIFO_BUF
select IIO_TRIGGER
help
Say yes here to build support for Analog Devices
@@ -87,7 +87,7 @@ config AD7887
tristate "Analog Devices AD7887 ADC driver"
depends on SPI
select IIO_BUFFER
- select IIO_SW_RING
+ select IIO_KFIFO_BUF
select IIO_TRIGGER
help
Say yes here to build support for Analog Devices
@@ -113,7 +113,7 @@ config AD7793
tristate "Analog Devices AD7792 AD7793 ADC driver"
depends on SPI
select IIO_BUFFER
- select IIO_SW_RING
+ select IIO_KFIFO_BUF
select IIO_TRIGGER
help
Say yes here to build support for Analog Devices
@@ -135,7 +135,7 @@ config AD7192
tristate "Analog Devices AD7190 AD7192 AD7195 ADC driver"
depends on SPI
select IIO_BUFFER
- select IIO_SW_RING
+ select IIO_KFIFO_BUF
select IIO_TRIGGER
help
Say yes here to build support for Analog Devices AD7190,
@@ -195,11 +195,20 @@ config MAX1363_RING_BUFFER
config LPC32XX_ADC
tristate "NXP LPC32XX ADC"
- depends on ARCH_LPC32XX && !TOUCHSCREEN_LPC32XX
+ depends on ARCH_LPC32XX
help
Say yes here to build support for the integrated ADC inside the
LPC32XX SoC. Note that this feature uses the same hardware as the
- touchscreen driver, so you can only select one of the two drivers
- (lpc32xx_adc or lpc32xx_ts). Provides direct access via sysfs.
+ touchscreen driver, so you should either select only one of the two
+ drivers (lpc32xx_adc or lpc32xx_ts) or, in the OpenFirmware case,
+ activate only one via device tree selection. Provides direct access
+ via sysfs.
+
+config SPEAR_ADC
+ tristate "ST SPEAr ADC"
+ depends on PLAT_SPEAR
+ help
+ Say yes here to build support for the integrated ADC inside the
+ ST SPEAr SoC. Provides direct access via sysfs.
endmenu
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index f83ab9551d8e..14e98b62b70a 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -38,3 +38,4 @@ obj-$(CONFIG_ADT7310) += adt7310.o
obj-$(CONFIG_ADT7410) += adt7410.o
obj-$(CONFIG_AD7280) += ad7280a.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
+obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index 9fd6d63d2999..5eaeaf1f0ae8 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -1,7 +1,7 @@
/*
* AD7190 AD7192 AD7195 SPI ADC driver
*
- * Copyright 2011 Analog Devices Inc.
+ * Copyright 2011-2012 Analog Devices Inc.
*
* Licensed under the GPL-2.
*/
@@ -17,12 +17,12 @@
#include <linux/sched.h>
#include <linux/delay.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
-#include "../ring_sw.h"
-#include "../trigger.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
#include "ad7192.h"
@@ -456,31 +456,19 @@ out:
static int ad7192_ring_preenable(struct iio_dev *indio_dev)
{
struct ad7192_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
- size_t d_size;
unsigned channel;
+ int ret;
if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
return -EINVAL;
+ ret = iio_sw_buffer_preenable(indio_dev);
+ if (ret < 0)
+ return ret;
+
channel = find_first_bit(indio_dev->active_scan_mask,
indio_dev->masklength);
- d_size = bitmap_weight(indio_dev->active_scan_mask,
- indio_dev->masklength) *
- indio_dev->channels[0].scan_type.storagebits / 8;
-
- if (ring->scan_timestamp) {
- d_size += sizeof(s64);
-
- if (d_size % sizeof(s64))
- d_size += sizeof(s64) - (d_size % sizeof(s64));
- }
-
- if (indio_dev->buffer->access->set_bytes_per_datum)
- indio_dev->buffer->access->
- set_bytes_per_datum(indio_dev->buffer, d_size);
-
st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
AD7192_MODE_SEL(AD7192_MODE_CONT);
st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) |
@@ -533,7 +521,7 @@ static irqreturn_t ad7192_trigger_handler(int irq, void *p)
indio_dev->channels[0].scan_type.realbits/8);
/* Guaranteed to be aligned with 8 byte boundary */
- if (ring->scan_timestamp)
+ if (indio_dev->scan_timestamp)
dat64[1] = pf->timestamp;
ring->access->store_to(ring, (u8 *)dat64, pf->timestamp);
@@ -556,7 +544,7 @@ static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
int ret;
- indio_dev->buffer = iio_sw_rb_allocate(indio_dev);
+ indio_dev->buffer = iio_kfifo_allocate(indio_dev);
if (!indio_dev->buffer) {
ret = -ENOMEM;
goto error_ret;
@@ -569,7 +557,7 @@ static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->id);
if (indio_dev->pollfunc == NULL) {
ret = -ENOMEM;
- goto error_deallocate_sw_rb;
+ goto error_deallocate_kfifo;
}
/* Ring buffer functions - here trigger setup related */
@@ -579,8 +567,8 @@ static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
return 0;
-error_deallocate_sw_rb:
- iio_sw_rb_free(indio_dev->buffer);
+error_deallocate_kfifo:
+ iio_kfifo_free(indio_dev->buffer);
error_ret:
return ret;
}
@@ -588,7 +576,7 @@ error_ret:
static void ad7192_ring_cleanup(struct iio_dev *indio_dev)
{
iio_dealloc_pollfunc(indio_dev->pollfunc);
- iio_sw_rb_free(indio_dev->buffer);
+ iio_kfifo_free(indio_dev->buffer);
}
/**
@@ -616,7 +604,7 @@ static int ad7192_probe_trigger(struct iio_dev *indio_dev)
struct ad7192_state *st = iio_priv(indio_dev);
int ret;
- st->trig = iio_allocate_trigger("%s-dev%d",
+ st->trig = iio_trigger_alloc("%s-dev%d",
spi_get_device_id(st->spi)->name,
indio_dev->id);
if (st->trig == NULL) {
@@ -649,7 +637,7 @@ static int ad7192_probe_trigger(struct iio_dev *indio_dev)
error_free_irq:
free_irq(st->spi->irq, indio_dev);
error_free_trig:
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
error_ret:
return ret;
}
@@ -660,14 +648,14 @@ static void ad7192_remove_trigger(struct iio_dev *indio_dev)
iio_trigger_unregister(st->trig);
free_irq(st->spi->irq, indio_dev);
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
}
static ssize_t ad7192_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7192_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", st->mclk /
@@ -679,7 +667,7 @@ static ssize_t ad7192_write_frequency(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7192_state *st = iio_priv(indio_dev);
unsigned long lval;
int div, ret;
@@ -718,7 +706,7 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
static ssize_t ad7192_show_scale_available(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7192_state *st = iio_priv(indio_dev);
int i, len = 0;
@@ -742,7 +730,7 @@ static ssize_t ad7192_show_ac_excitation(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7192_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", !!(st->mode & AD7192_MODE_ACX));
@@ -752,7 +740,7 @@ static ssize_t ad7192_show_bridge_switch(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7192_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", !!(st->gpocon & AD7192_GPOCON_BPDSW));
@@ -763,7 +751,7 @@ static ssize_t ad7192_set(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7192_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
@@ -849,7 +837,7 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
bool unipolar = !!(st->conf & AD7192_CONF_UNIPOLAR);
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
ret = -EBUSY;
@@ -981,7 +969,8 @@ static const struct iio_info ad7195_info = {
.extend_name = _name, \
.channel = _chan, \
.channel2 = _chan2, \
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = _address, \
.scan_index = _si, \
.scan_type = IIO_ST('s', 24, 32, 0)}
@@ -990,7 +979,8 @@ static const struct iio_info ad7195_info = {
{ .type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = _chan, \
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = _address, \
.scan_index = _si, \
.scan_type = IIO_ST('s', 24, 32, 0)}
@@ -999,7 +989,8 @@ static const struct iio_info ad7195_info = {
{ .type = IIO_TEMP, \
.indexed = 1, \
.channel = _chan, \
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
.address = _address, \
.scan_index = _si, \
.scan_type = IIO_ST('s', 24, 32, 0)}
@@ -1033,7 +1024,7 @@ static int __devinit ad7192_probe(struct spi_device *spi)
return -ENODEV;
}
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -1114,7 +1105,7 @@ error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
index 7dbd6812c240..cfc39a703126 100644
--- a/drivers/staging/iio/adc/ad7280a.c
+++ b/drivers/staging/iio/adc/ad7280a.c
@@ -16,9 +16,9 @@
#include <linux/interrupt.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../events.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
#include "ad7280a.h"
@@ -384,7 +384,7 @@ static ssize_t ad7280_show_balance_sw(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7280_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -398,7 +398,7 @@ static ssize_t ad7280_store_balance_sw(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7280_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
bool readin;
@@ -429,7 +429,7 @@ static ssize_t ad7280_show_balance_timer(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7280_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
@@ -453,7 +453,7 @@ static ssize_t ad7280_store_balance_timer(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7280_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
unsigned long val;
@@ -508,6 +508,7 @@ static int ad7280_channel_init(struct ad7280_state *st)
}
st->channels[cnt].indexed = 1;
st->channels[cnt].info_mask =
+ IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT;
st->channels[cnt].address =
AD7280A_DEVADDR(dev) << 8 | ch;
@@ -524,7 +525,9 @@ static int ad7280_channel_init(struct ad7280_state *st)
st->channels[cnt].channel2 = dev * 6;
st->channels[cnt].address = AD7280A_ALL_CELLS;
st->channels[cnt].indexed = 1;
- st->channels[cnt].info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT;
+ st->channels[cnt].info_mask =
+ IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT;
st->channels[cnt].scan_index = cnt;
st->channels[cnt].scan_type.sign = 'u';
st->channels[cnt].scan_type.realbits = 32;
@@ -596,7 +599,7 @@ static ssize_t ad7280_read_channel_config(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7280_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
unsigned val;
@@ -626,7 +629,7 @@ static ssize_t ad7280_write_channel_config(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7280_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -788,7 +791,7 @@ static int ad7280_read_raw(struct iio_dev *indio_dev,
int ret;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
if (chan->address == AD7280A_ALL_CELLS)
ret = ad7280_read_all_channels(st, st->scan_cnt, NULL);
@@ -836,7 +839,7 @@ static int __devinit ad7280_probe(struct spi_device *spi)
int ret;
const unsigned short tACQ_ns[4] = {465, 1010, 1460, 1890};
const unsigned short nAVG[4] = {1, 2, 4, 8};
- struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+ struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -942,7 +945,7 @@ error_free_channels:
kfree(st->channels);
error_free_device:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
@@ -961,7 +964,7 @@ static int __devexit ad7280_remove(struct spi_device *spi)
kfree(st->channels);
kfree(st->iio_attr);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c
index 81d6b6128cb0..029b39c0ba60 100644
--- a/drivers/staging/iio/adc/ad7291.c
+++ b/drivers/staging/iio/adc/ad7291.c
@@ -17,9 +17,9 @@
#include <linux/regulator/consumer.h>
#include <linux/err.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../events.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
/*
* Simplified handling
@@ -132,7 +132,7 @@ static ssize_t ad7291_store_reset(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7291_chip_info *chip = iio_priv(indio_dev);
return ad7291_i2c_write(chip, AD7291_COMMAND,
@@ -214,7 +214,7 @@ static inline ssize_t ad7291_show_hyst(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7291_chip_info *chip = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
u16 data;
@@ -232,7 +232,7 @@ static inline ssize_t ad7291_set_hyst(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7291_chip_info *chip = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
u16 data;
@@ -461,7 +461,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
s16 signval;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
switch (chan->type) {
case IIO_VOLTAGE:
mutex_lock(&chip->state_lock);
@@ -536,7 +536,8 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
#define AD7291_VOLTAGE_CHAN(_chan) \
{ \
.type = IIO_VOLTAGE, \
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.indexed = 1, \
.channel = _chan, \
.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)|\
@@ -554,7 +555,8 @@ static const struct iio_chan_spec ad7291_channels[] = {
AD7291_VOLTAGE_CHAN(7),
{
.type = IIO_TEMP,
- .info_mask = IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.indexed = 1,
.channel = 0,
@@ -585,7 +587,7 @@ static int __devinit ad7291_probe(struct i2c_client *client,
struct iio_dev *indio_dev;
int ret = 0, voltage_uv = 0;
- indio_dev = iio_allocate_device(sizeof(*chip));
+ indio_dev = iio_device_alloc(sizeof(*chip));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -667,7 +669,7 @@ error_put_reg:
if (!IS_ERR(chip->reg))
regulator_put(chip->reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -687,7 +689,7 @@ static int __devexit ad7291_remove(struct i2c_client *client)
regulator_put(chip->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7298.h b/drivers/staging/iio/adc/ad7298.h
index a0e5dea415ef..5051a7e4d4fd 100644
--- a/drivers/staging/iio/adc/ad7298.h
+++ b/drivers/staging/iio/adc/ad7298.h
@@ -38,7 +38,6 @@ struct ad7298_platform_data {
struct ad7298_state {
struct spi_device *spi;
struct regulator *reg;
- size_t d_size;
u16 int_vref_mv;
unsigned ext_ref;
struct spi_transfer ring_xfer[10];
diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c
index 8dd6aa9cf928..c90f2b3e661f 100644
--- a/drivers/staging/iio/adc/ad7298_core.c
+++ b/drivers/staging/iio/adc/ad7298_core.c
@@ -16,40 +16,51 @@
#include <linux/delay.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "ad7298.h"
+#define AD7298_V_CHAN(index) \
+ { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = index, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .address = index, \
+ .scan_index = index, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ }, \
+ }
+
static struct iio_chan_spec ad7298_channels[] = {
- IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- 9, AD7298_CH_TEMP, IIO_ST('s', 32, 32, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 0, 0, IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 1, 1, IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 2, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 2, 2, IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 3, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 3, 3, IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 4, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 4, 4, IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 5, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 5, 5, IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 6, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 6, 6, IIO_ST('u', 12, 16, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 7, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 7, 7, IIO_ST('u', 12, 16, 0), 0),
+ {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .address = 9,
+ .scan_index = AD7298_CH_TEMP,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 32,
+ .storagebits = 32,
+ },
+ },
+ AD7298_V_CHAN(0),
+ AD7298_V_CHAN(1),
+ AD7298_V_CHAN(2),
+ AD7298_V_CHAN(3),
+ AD7298_V_CHAN(4),
+ AD7298_V_CHAN(5),
+ AD7298_V_CHAN(6),
+ AD7298_V_CHAN(7),
IIO_CHAN_SOFT_TIMESTAMP(8),
};
@@ -121,7 +132,7 @@ static int ad7298_read_raw(struct iio_dev *indio_dev,
unsigned int scale_uv;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
ret = -EBUSY;
@@ -168,7 +179,7 @@ static int __devinit ad7298_probe(struct spi_device *spi)
struct ad7298_platform_data *pdata = spi->dev.platform_data;
struct ad7298_state *st;
int ret;
- struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+ struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -241,7 +252,7 @@ error_disable_reg:
error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
@@ -258,7 +269,7 @@ static int __devexit ad7298_remove(struct spi_device *spi)
regulator_disable(st->reg);
regulator_put(st->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c
index feeb0eeba59a..908a3e5609df 100644
--- a/drivers/staging/iio/adc/ad7298_ring.c
+++ b/drivers/staging/iio/adc/ad7298_ring.c
@@ -1,7 +1,7 @@
/*
* AD7298 SPI ADC driver
*
- * Copyright 2011 Analog Devices Inc.
+ * Copyright 2011-2012 Analog Devices Inc.
*
* Licensed under the GPL-2.
*/
@@ -11,10 +11,10 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
-#include "../iio.h"
-#include "../buffer.h"
-#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger_consumer.h>
#include "ad7298.h"
@@ -28,25 +28,17 @@
static int ad7298_ring_preenable(struct iio_dev *indio_dev)
{
struct ad7298_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
- size_t d_size;
int i, m;
unsigned short command;
- int scan_count = bitmap_weight(indio_dev->active_scan_mask,
- indio_dev->masklength);
- d_size = scan_count * (AD7298_STORAGE_BITS / 8);
-
- if (ring->scan_timestamp) {
- d_size += sizeof(s64);
-
- if (d_size % sizeof(s64))
- d_size += sizeof(s64) - (d_size % sizeof(s64));
- }
+ int scan_count, ret;
- if (ring->access->set_bytes_per_datum)
- ring->access->set_bytes_per_datum(ring, d_size);
+ ret = iio_sw_buffer_preenable(indio_dev);
+ if (ret < 0)
+ return ret;
- st->d_size = d_size;
+ /* Now compute overall size */
+ scan_count = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength);
command = AD7298_WRITE | st->ext_ref;
@@ -100,9 +92,9 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p)
if (b_sent)
return b_sent;
- if (ring->scan_timestamp) {
+ if (indio_dev->scan_timestamp) {
time_ns = iio_get_time_ns();
- memcpy((u8 *)buf + st->d_size - sizeof(s64),
+ memcpy((u8 *)buf + indio_dev->scan_bytes - sizeof(s64),
&time_ns, sizeof(time_ns));
}
@@ -126,7 +118,7 @@ int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
int ret;
- indio_dev->buffer = iio_sw_rb_allocate(indio_dev);
+ indio_dev->buffer = iio_kfifo_allocate(indio_dev);
if (!indio_dev->buffer) {
ret = -ENOMEM;
goto error_ret;
@@ -140,7 +132,7 @@ int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev)
if (indio_dev->pollfunc == NULL) {
ret = -ENOMEM;
- goto error_deallocate_sw_rb;
+ goto error_deallocate_kfifo;
}
/* Ring buffer functions - here trigger setup related */
@@ -151,8 +143,8 @@ int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
return 0;
-error_deallocate_sw_rb:
- iio_sw_rb_free(indio_dev->buffer);
+error_deallocate_kfifo:
+ iio_kfifo_free(indio_dev->buffer);
error_ret:
return ret;
}
@@ -160,5 +152,5 @@ error_ret:
void ad7298_ring_cleanup(struct iio_dev *indio_dev)
{
iio_dealloc_pollfunc(indio_dev->pollfunc);
- iio_sw_rb_free(indio_dev->buffer);
+ iio_kfifo_free(indio_dev->buffer);
}
diff --git a/drivers/staging/iio/adc/ad7476.h b/drivers/staging/iio/adc/ad7476.h
index 27f696c75cc4..b1dd9317fe1f 100644
--- a/drivers/staging/iio/adc/ad7476.h
+++ b/drivers/staging/iio/adc/ad7476.h
@@ -27,7 +27,6 @@ struct ad7476_state {
struct spi_device *spi;
const struct ad7476_chip_info *chip_info;
struct regulator *reg;
- size_t d_size;
u16 int_vref_mv;
struct spi_transfer xfer;
struct spi_message msg;
diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c
index 0c064d1c3927..be1c260cf165 100644
--- a/drivers/staging/iio/adc/ad7476_core.c
+++ b/drivers/staging/iio/adc/ad7476_core.c
@@ -15,9 +15,9 @@
#include <linux/err.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "ad7476.h"
@@ -43,7 +43,7 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
unsigned int scale_uv;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
ret = -EBUSY;
@@ -66,53 +66,51 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
+#define AD7476_CHAN(bits) \
+ { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = bits, \
+ .storagebits = 16, \
+ .shift = 12 - bits, \
+ }, \
+}
+
static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
[ID_AD7466] = {
- .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 0, 0, IIO_ST('u', 12, 16, 0), 0),
+ .channel[0] = AD7476_CHAN(12),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7467] = {
- .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 0, 0, IIO_ST('u', 10, 16, 2), 0),
+ .channel[0] = AD7476_CHAN(10),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7468] = {
- .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1 , 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 0, 0, IIO_ST('u', 8, 16, 4), 0),
+ .channel[0] = AD7476_CHAN(8),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7475] = {
- .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 0, 0, IIO_ST('u', 12, 16, 0), 0),
+ .channel[0] = AD7476_CHAN(12),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7476] = {
- .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 0, 0, IIO_ST('u', 12, 16, 0), 0),
+ .channel[0] = AD7476_CHAN(12),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7477] = {
- .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 0, 0, IIO_ST('u', 10, 16, 2), 0),
+ .channel[0] = AD7476_CHAN(10),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7478] = {
- .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 0, 0, IIO_ST('u', 8, 16, 4), 0),
+ .channel[0] = AD7476_CHAN(8),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_AD7495] = {
- .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 0, 0, IIO_ST('u', 12, 16, 0), 0),
+ .channel[0] = AD7476_CHAN(12),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
.int_vref_mv = 2500,
},
@@ -130,7 +128,7 @@ static int __devinit ad7476_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
int ret, voltage_uv = 0;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -200,7 +198,7 @@ error_disable_reg:
error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
@@ -218,7 +216,7 @@ static int ad7476_remove(struct spi_device *spi)
regulator_disable(st->reg);
regulator_put(st->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c
index d6af6c05ce1c..383611b05764 100644
--- a/drivers/staging/iio/adc/ad7476_ring.c
+++ b/drivers/staging/iio/adc/ad7476_ring.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2010 Analog Devices Inc.
+ * Copyright 2010-2012 Analog Devices Inc.
* Copyright (C) 2008 Jonathan Cameron
*
* Licensed under the GPL-2 or later.
@@ -13,43 +13,13 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
-#include "../iio.h"
-#include "../buffer.h"
-#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger_consumer.h>
#include "ad7476.h"
-/**
- * ad7476_ring_preenable() setup the parameters of the ring before enabling
- *
- * The complex nature of the setting of the number of bytes per datum is due
- * to this driver currently ensuring that the timestamp is stored at an 8
- * byte boundary.
- **/
-static int ad7476_ring_preenable(struct iio_dev *indio_dev)
-{
- struct ad7476_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
-
- st->d_size = bitmap_weight(indio_dev->active_scan_mask,
- indio_dev->masklength) *
- st->chip_info->channel[0].scan_type.storagebits / 8;
-
- if (ring->scan_timestamp) {
- st->d_size += sizeof(s64);
-
- if (st->d_size % sizeof(s64))
- st->d_size += sizeof(s64) - (st->d_size % sizeof(s64));
- }
-
- if (indio_dev->buffer->access->set_bytes_per_datum)
- indio_dev->buffer->access->
- set_bytes_per_datum(indio_dev->buffer, st->d_size);
-
- return 0;
-}
-
static irqreturn_t ad7476_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
@@ -59,7 +29,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p)
__u8 *rxbuf;
int b_sent;
- rxbuf = kzalloc(st->d_size, GFP_KERNEL);
+ rxbuf = kzalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (rxbuf == NULL)
return -ENOMEM;
@@ -70,8 +40,8 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p)
time_ns = iio_get_time_ns();
- if (indio_dev->buffer->scan_timestamp)
- memcpy(rxbuf + st->d_size - sizeof(s64),
+ if (indio_dev->scan_timestamp)
+ memcpy(rxbuf + indio_dev->scan_bytes - sizeof(s64),
&time_ns, sizeof(time_ns));
indio_dev->buffer->access->store_to(indio_dev->buffer, rxbuf, time_ns);
@@ -83,7 +53,7 @@ done:
}
static const struct iio_buffer_setup_ops ad7476_ring_setup_ops = {
- .preenable = &ad7476_ring_preenable,
+ .preenable = &iio_sw_buffer_preenable,
.postenable = &iio_triggered_buffer_postenable,
.predisable = &iio_triggered_buffer_predisable,
};
@@ -93,7 +63,7 @@ int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev)
struct ad7476_state *st = iio_priv(indio_dev);
int ret = 0;
- indio_dev->buffer = iio_sw_rb_allocate(indio_dev);
+ indio_dev->buffer = iio_kfifo_allocate(indio_dev);
if (!indio_dev->buffer) {
ret = -ENOMEM;
goto error_ret;
@@ -108,7 +78,7 @@ int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->id);
if (indio_dev->pollfunc == NULL) {
ret = -ENOMEM;
- goto error_deallocate_sw_rb;
+ goto error_deallocate_kfifo;
}
/* Ring buffer functions - here trigger setup related */
@@ -119,8 +89,8 @@ int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
return 0;
-error_deallocate_sw_rb:
- iio_sw_rb_free(indio_dev->buffer);
+error_deallocate_kfifo:
+ iio_kfifo_free(indio_dev->buffer);
error_ret:
return ret;
}
@@ -128,5 +98,5 @@ error_ret:
void ad7476_ring_cleanup(struct iio_dev *indio_dev)
{
iio_dealloc_pollfunc(indio_dev->pollfunc);
- iio_sw_rb_free(indio_dev->buffer);
+ iio_kfifo_free(indio_dev->buffer);
}
diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c
index 97e8d3d4471e..10ab6dc823b9 100644
--- a/drivers/staging/iio/adc/ad7606_core.c
+++ b/drivers/staging/iio/adc/ad7606_core.c
@@ -18,9 +18,9 @@
#include <linux/sched.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "ad7606.h"
@@ -88,7 +88,7 @@ static int ad7606_read_raw(struct iio_dev *indio_dev,
unsigned int scale_uv;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
ret = -EBUSY;
@@ -113,7 +113,7 @@ static int ad7606_read_raw(struct iio_dev *indio_dev,
static ssize_t ad7606_show_range(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7606_state *st = iio_priv(indio_dev);
return sprintf(buf, "%u\n", st->range);
@@ -122,7 +122,7 @@ static ssize_t ad7606_show_range(struct device *dev,
static ssize_t ad7606_store_range(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7606_state *st = iio_priv(indio_dev);
unsigned long lval;
@@ -147,7 +147,7 @@ static IIO_CONST_ATTR(in_voltage_range_available, "5000 10000");
static ssize_t ad7606_show_oversampling_ratio(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7606_state *st = iio_priv(indio_dev);
return sprintf(buf, "%u\n", st->oversampling);
@@ -168,7 +168,7 @@ static int ad7606_oversampling_get_index(unsigned val)
static ssize_t ad7606_store_oversampling_ratio(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7606_state *st = iio_priv(indio_dev);
unsigned long lval;
int ret;
@@ -229,14 +229,15 @@ static const struct attribute_group ad7606_attribute_group_range = {
.attrs = ad7606_attributes_range,
};
-#define AD7606_CHANNEL(num) \
- { \
- .type = IIO_VOLTAGE, \
- .indexed = 1, \
- .channel = num, \
- .address = num, \
- .scan_index = num, \
- .scan_type = IIO_ST('s', 16, 16, 0), \
+#define AD7606_CHANNEL(num) \
+ { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = num, \
+ .address = num, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \
+ .scan_index = num, \
+ .scan_type = IIO_ST('s', 16, 16, 0), \
}
static struct iio_chan_spec ad7606_8_channels[] = {
@@ -460,7 +461,7 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq,
struct ad7606_platform_data *pdata = dev->platform_data;
struct ad7606_state *st;
int ret;
- struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+ struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
@@ -559,7 +560,7 @@ error_disable_reg:
error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ERR_PTR(ret);
}
@@ -579,7 +580,7 @@ int ad7606_remove(struct iio_dev *indio_dev, int irq)
}
ad7606_free_gpios(st);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c
index bb152a8e8c92..a53faafec070 100644
--- a/drivers/staging/iio/adc/ad7606_par.c
+++ b/drivers/staging/iio/adc/ad7606_par.c
@@ -12,7 +12,7 @@
#include <linux/err.h>
#include <linux/io.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#include "ad7606.h"
static int ad7606_par16_read_block(struct device *dev,
diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c
index 1ef9fbcaf2de..24ce8fc71646 100644
--- a/drivers/staging/iio/adc/ad7606_ring.c
+++ b/drivers/staging/iio/adc/ad7606_ring.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Analog Devices Inc.
+ * Copyright 2011-2012 Analog Devices Inc.
*
* Licensed under the GPL-2.
*
@@ -11,10 +11,10 @@
#include <linux/kernel.h>
#include <linux/slab.h>
-#include "../iio.h"
-#include "../buffer.h"
-#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger_consumer.h>
#include "ad7606.h"
@@ -51,8 +51,7 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
__u8 *buf;
int ret;
- buf = kzalloc(ring->access->get_bytes_per_datum(ring),
- GFP_KERNEL);
+ buf = kzalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (buf == NULL)
return;
@@ -82,9 +81,8 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
time_ns = iio_get_time_ns();
- if (ring->scan_timestamp)
- *((s64 *)(buf + ring->access->get_bytes_per_datum(ring) -
- sizeof(s64))) = time_ns;
+ if (indio_dev->scan_timestamp)
+ *((s64 *)(buf + indio_dev->scan_bytes - sizeof(s64))) = time_ns;
ring->access->store_to(indio_dev->buffer, buf, time_ns);
done:
@@ -104,7 +102,7 @@ int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev)
struct ad7606_state *st = iio_priv(indio_dev);
int ret;
- indio_dev->buffer = iio_sw_rb_allocate(indio_dev);
+ indio_dev->buffer = iio_kfifo_allocate(indio_dev);
if (!indio_dev->buffer) {
ret = -ENOMEM;
goto error_ret;
@@ -119,13 +117,13 @@ int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->id);
if (indio_dev->pollfunc == NULL) {
ret = -ENOMEM;
- goto error_deallocate_sw_rb;
+ goto error_deallocate_kfifo;
}
/* Ring buffer functions - here trigger setup related */
indio_dev->setup_ops = &ad7606_ring_setup_ops;
- indio_dev->buffer->scan_timestamp = true ;
+ indio_dev->buffer->scan_timestamp = true;
INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring);
@@ -133,8 +131,8 @@ int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
return 0;
-error_deallocate_sw_rb:
- iio_sw_rb_free(indio_dev->buffer);
+error_deallocate_kfifo:
+ iio_kfifo_free(indio_dev->buffer);
error_ret:
return ret;
}
@@ -142,5 +140,5 @@ error_ret:
void ad7606_ring_cleanup(struct iio_dev *indio_dev)
{
iio_dealloc_pollfunc(indio_dev->pollfunc);
- iio_sw_rb_free(indio_dev->buffer);
+ iio_kfifo_free(indio_dev->buffer);
}
diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c
index 237f1c44d296..099d347da52d 100644
--- a/drivers/staging/iio/adc/ad7606_spi.c
+++ b/drivers/staging/iio/adc/ad7606_spi.c
@@ -11,7 +11,7 @@
#include <linux/types.h>
#include <linux/err.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#include "ad7606.h"
#define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */
diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
index a13e58c814e6..1ece2ac8de56 100644
--- a/drivers/staging/iio/adc/ad7780.c
+++ b/drivers/staging/iio/adc/ad7780.c
@@ -18,8 +18,8 @@
#include <linux/gpio.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "ad7780.h"
@@ -94,7 +94,7 @@ static int ad7780_read_raw(struct iio_dev *indio_dev,
unsigned long scale_uv;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
ret = ad7780_read(st, &smpl);
mutex_unlock(&indio_dev->mlock);
@@ -126,14 +126,34 @@ static int ad7780_read_raw(struct iio_dev *indio_dev,
static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
[ID_AD7780] = {
- .channel = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 0, 0, IIO_ST('s', 24, 32, 8), 0),
+ .channel = {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ .shift = 8,
+ },
+ },
},
[ID_AD7781] = {
- .channel = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- 0, 0, IIO_ST('s', 20, 32, 12), 0),
+ .channel = {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 20,
+ .storagebits = 32,
+ .shift = 12,
+ },
+ },
},
};
@@ -167,7 +187,7 @@ static int __devinit ad7780_probe(struct spi_device *spi)
return -ENODEV;
}
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -245,7 +265,7 @@ error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
@@ -262,7 +282,7 @@ static int ad7780_remove(struct spi_device *spi)
regulator_disable(st->reg);
regulator_put(st->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index 84ecde1ad042..b36556fa2957 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -1,7 +1,7 @@
/*
* AD7792/AD7793 SPI ADC driver
*
- * Copyright 2011 Analog Devices Inc.
+ * Copyright 2011-2012 Analog Devices Inc.
*
* Licensed under the GPL-2.
*/
@@ -18,12 +18,12 @@
#include <linux/delay.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
-#include "../ring_sw.h"
-#include "../trigger.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
#include "ad7793.h"
@@ -319,31 +319,18 @@ out:
static int ad7793_ring_preenable(struct iio_dev *indio_dev)
{
struct ad7793_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
- size_t d_size;
unsigned channel;
+ int ret;
if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
return -EINVAL;
+ ret = iio_sw_buffer_preenable(indio_dev);
+ if (ret < 0)
+ return ret;
channel = find_first_bit(indio_dev->active_scan_mask,
indio_dev->masklength);
- d_size = bitmap_weight(indio_dev->active_scan_mask,
- indio_dev->masklength) *
- indio_dev->channels[0].scan_type.storagebits / 8;
-
- if (ring->scan_timestamp) {
- d_size += sizeof(s64);
-
- if (d_size % sizeof(s64))
- d_size += sizeof(s64) - (d_size % sizeof(s64));
- }
-
- if (indio_dev->buffer->access->set_bytes_per_datum)
- indio_dev->buffer->access->
- set_bytes_per_datum(indio_dev->buffer, d_size);
-
st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) |
AD7793_MODE_SEL(AD7793_MODE_CONT);
st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) |
@@ -399,7 +386,7 @@ static irqreturn_t ad7793_trigger_handler(int irq, void *p)
indio_dev->channels[0].scan_type.realbits/8);
/* Guaranteed to be aligned with 8 byte boundary */
- if (ring->scan_timestamp)
+ if (indio_dev->scan_timestamp)
dat64[1] = pf->timestamp;
ring->access->store_to(ring, (u8 *)dat64, pf->timestamp);
@@ -422,7 +409,7 @@ static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
int ret;
- indio_dev->buffer = iio_sw_rb_allocate(indio_dev);
+ indio_dev->buffer = iio_kfifo_allocate(indio_dev);
if (!indio_dev->buffer) {
ret = -ENOMEM;
goto error_ret;
@@ -435,7 +422,7 @@ static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->id);
if (indio_dev->pollfunc == NULL) {
ret = -ENOMEM;
- goto error_deallocate_sw_rb;
+ goto error_deallocate_kfifo;
}
/* Ring buffer functions - here trigger setup related */
@@ -445,8 +432,8 @@ static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
return 0;
-error_deallocate_sw_rb:
- iio_sw_rb_free(indio_dev->buffer);
+error_deallocate_kfifo:
+ iio_kfifo_free(indio_dev->buffer);
error_ret:
return ret;
}
@@ -454,7 +441,7 @@ error_ret:
static void ad7793_ring_cleanup(struct iio_dev *indio_dev)
{
iio_dealloc_pollfunc(indio_dev->pollfunc);
- iio_sw_rb_free(indio_dev->buffer);
+ iio_kfifo_free(indio_dev->buffer);
}
/**
@@ -482,7 +469,7 @@ static int ad7793_probe_trigger(struct iio_dev *indio_dev)
struct ad7793_state *st = iio_priv(indio_dev);
int ret;
- st->trig = iio_allocate_trigger("%s-dev%d",
+ st->trig = iio_trigger_alloc("%s-dev%d",
spi_get_device_id(st->spi)->name,
indio_dev->id);
if (st->trig == NULL) {
@@ -516,7 +503,7 @@ static int ad7793_probe_trigger(struct iio_dev *indio_dev)
error_free_irq:
free_irq(st->spi->irq, indio_dev);
error_free_trig:
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
error_ret:
return ret;
}
@@ -527,7 +514,7 @@ static void ad7793_remove_trigger(struct iio_dev *indio_dev)
iio_trigger_unregister(st->trig);
free_irq(st->spi->irq, indio_dev);
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
}
static const u16 sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39, 33, 19,
@@ -537,7 +524,7 @@ static ssize_t ad7793_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7793_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n",
@@ -549,7 +536,7 @@ static ssize_t ad7793_write_frequency(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7793_state *st = iio_priv(indio_dev);
long lval;
int i, ret;
@@ -591,7 +578,7 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
static ssize_t ad7793_show_scale_available(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7793_state *st = iio_priv(indio_dev);
int i, len = 0;
@@ -630,7 +617,7 @@ static int ad7793_read_raw(struct iio_dev *indio_dev,
bool unipolar = !!(st->conf & AD7793_CONF_UNIPOLAR);
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
ret = -EBUSY;
@@ -760,7 +747,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 0,
.channel2 = 0,
.address = AD7793_CH_AIN1P_AIN1M,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 0,
.scan_type = IIO_ST('s', 24, 32, 0)
},
@@ -771,7 +759,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 1,
.channel2 = 1,
.address = AD7793_CH_AIN2P_AIN2M,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 1,
.scan_type = IIO_ST('s', 24, 32, 0)
},
@@ -782,7 +771,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 2,
.channel2 = 2,
.address = AD7793_CH_AIN3P_AIN3M,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 2,
.scan_type = IIO_ST('s', 24, 32, 0)
},
@@ -794,7 +784,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 2,
.channel2 = 2,
.address = AD7793_CH_AIN1M_AIN1M,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 2,
.scan_type = IIO_ST('s', 24, 32, 0)
},
@@ -803,7 +794,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.indexed = 1,
.channel = 0,
.address = AD7793_CH_TEMP,
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 4,
.scan_type = IIO_ST('s', 24, 32, 0),
},
@@ -813,7 +805,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.indexed = 1,
.channel = 4,
.address = AD7793_CH_AVDD_MONITOR,
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 5,
.scan_type = IIO_ST('s', 24, 32, 0),
},
@@ -827,7 +820,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 0,
.channel2 = 0,
.address = AD7793_CH_AIN1P_AIN1M,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 0,
.scan_type = IIO_ST('s', 16, 32, 0)
},
@@ -838,7 +832,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 1,
.channel2 = 1,
.address = AD7793_CH_AIN2P_AIN2M,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 1,
.scan_type = IIO_ST('s', 16, 32, 0)
},
@@ -849,7 +844,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 2,
.channel2 = 2,
.address = AD7793_CH_AIN3P_AIN3M,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 2,
.scan_type = IIO_ST('s', 16, 32, 0)
},
@@ -861,7 +857,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 2,
.channel2 = 2,
.address = AD7793_CH_AIN1M_AIN1M,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 2,
.scan_type = IIO_ST('s', 16, 32, 0)
},
@@ -870,7 +867,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.indexed = 1,
.channel = 0,
.address = AD7793_CH_TEMP,
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 4,
.scan_type = IIO_ST('s', 16, 32, 0),
},
@@ -880,7 +878,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.indexed = 1,
.channel = 4,
.address = AD7793_CH_AVDD_MONITOR,
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 5,
.scan_type = IIO_ST('s', 16, 32, 0),
},
@@ -905,7 +904,7 @@ static int __devinit ad7793_probe(struct spi_device *spi)
return -ENODEV;
}
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -989,7 +988,7 @@ error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
@@ -1009,7 +1008,7 @@ static int ad7793_remove(struct spi_device *spi)
regulator_put(st->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
index 52b720e2b03a..5356b091b08f 100644
--- a/drivers/staging/iio/adc/ad7816.c
+++ b/drivers/staging/iio/adc/ad7816.c
@@ -16,9 +16,9 @@
#include <linux/spi/spi.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../events.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
/*
* AD7816 config masks
@@ -113,7 +113,7 @@ static ssize_t ad7816_show_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7816_chip_info *chip = iio_priv(indio_dev);
if (chip->mode)
@@ -127,7 +127,7 @@ static ssize_t ad7816_store_mode(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7816_chip_info *chip = iio_priv(indio_dev);
if (strcmp(buf, "full")) {
@@ -159,7 +159,7 @@ static ssize_t ad7816_show_channel(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7816_chip_info *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", chip->channel_id);
@@ -170,7 +170,7 @@ static ssize_t ad7816_store_channel(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7816_chip_info *chip = iio_priv(indio_dev);
unsigned long data;
int ret;
@@ -208,7 +208,7 @@ static ssize_t ad7816_show_value(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7816_chip_info *chip = iio_priv(indio_dev);
u16 data;
s8 value;
@@ -263,7 +263,7 @@ static ssize_t ad7816_show_oti(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7816_chip_info *chip = iio_priv(indio_dev);
int value;
@@ -284,7 +284,7 @@ static inline ssize_t ad7816_set_oti(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7816_chip_info *chip = iio_priv(indio_dev);
long value;
u8 data;
@@ -354,7 +354,7 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev)
return -EINVAL;
}
- indio_dev = iio_allocate_device(sizeof(*chip));
+ indio_dev = iio_device_alloc(sizeof(*chip));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -426,7 +426,7 @@ error_free_gpio_convert:
error_free_gpio_rdwr:
gpio_free(chip->rdwr_pin);
error_free_device:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -443,7 +443,7 @@ static int __devexit ad7816_remove(struct spi_device *spi_dev)
gpio_free(chip->busy_pin);
gpio_free(chip->convert_pin);
gpio_free(chip->rdwr_pin);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7887.h b/drivers/staging/iio/adc/ad7887.h
index bc53b6532121..2e09e54fc9c5 100644
--- a/drivers/staging/iio/adc/ad7887.h
+++ b/drivers/staging/iio/adc/ad7887.h
@@ -63,7 +63,6 @@ struct ad7887_state {
struct spi_device *spi;
const struct ad7887_chip_info *chip_info;
struct regulator *reg;
- size_t d_size;
u16 int_vref_mv;
struct spi_transfer xfer[4];
struct spi_message msg[3];
diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c
index e9bbc3eed15d..7186074deeb3 100644
--- a/drivers/staging/iio/adc/ad7887_core.c
+++ b/drivers/staging/iio/adc/ad7887_core.c
@@ -15,9 +15,9 @@
#include <linux/err.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "ad7887.h"
@@ -42,7 +42,7 @@ static int ad7887_read_raw(struct iio_dev *indio_dev,
unsigned int scale_uv;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
ret = -EBUSY;
@@ -75,7 +75,8 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = 1,
.scan_index = 1,
.scan_type = IIO_ST('u', 12, 16, 0),
@@ -84,7 +85,8 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = 0,
.scan_index = 0,
.scan_type = IIO_ST('u', 12, 16, 0),
@@ -104,7 +106,7 @@ static int __devinit ad7887_probe(struct spi_device *spi)
struct ad7887_platform_data *pdata = spi->dev.platform_data;
struct ad7887_state *st;
int ret, voltage_uv = 0;
- struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+ struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -220,7 +222,7 @@ error_disable_reg:
error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
@@ -237,7 +239,7 @@ static int ad7887_remove(struct spi_device *spi)
regulator_disable(st->reg);
regulator_put(st->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c
index d1809079b63d..fd91384db894 100644
--- a/drivers/staging/iio/adc/ad7887_ring.c
+++ b/drivers/staging/iio/adc/ad7887_ring.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2011 Analog Devices Inc.
+ * Copyright 2010-2012 Analog Devices Inc.
* Copyright (C) 2008 Jonathan Cameron
*
* Licensed under the GPL-2.
@@ -12,10 +12,10 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
-#include "../iio.h"
-#include "../buffer.h"
-#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger_consumer.h>
#include "ad7887.h"
@@ -29,22 +29,11 @@
static int ad7887_ring_preenable(struct iio_dev *indio_dev)
{
struct ad7887_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
-
- st->d_size = bitmap_weight(indio_dev->active_scan_mask,
- indio_dev->masklength) *
- st->chip_info->channel[0].scan_type.storagebits / 8;
-
- if (ring->scan_timestamp) {
- st->d_size += sizeof(s64);
-
- if (st->d_size % sizeof(s64))
- st->d_size += sizeof(s64) - (st->d_size % sizeof(s64));
- }
+ int ret;
- if (indio_dev->buffer->access->set_bytes_per_datum)
- indio_dev->buffer->access->
- set_bytes_per_datum(indio_dev->buffer, st->d_size);
+ ret = iio_sw_buffer_preenable(indio_dev);
+ if (ret < 0)
+ return ret;
/* We know this is a single long so can 'cheat' */
switch (*indio_dev->active_scan_mask) {
@@ -83,7 +72,6 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ad7887_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
s64 time_ns;
__u8 *buf;
int b_sent;
@@ -92,7 +80,7 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p)
indio_dev->masklength) *
st->chip_info->channel[0].scan_type.storagebits / 8;
- buf = kzalloc(st->d_size, GFP_KERNEL);
+ buf = kzalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
@@ -103,8 +91,8 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p)
time_ns = iio_get_time_ns();
memcpy(buf, st->data, bytes);
- if (ring->scan_timestamp)
- memcpy(buf + st->d_size - sizeof(s64),
+ if (indio_dev->scan_timestamp)
+ memcpy(buf + indio_dev->scan_bytes - sizeof(s64),
&time_ns, sizeof(time_ns));
indio_dev->buffer->access->store_to(indio_dev->buffer, buf, time_ns);
@@ -126,7 +114,7 @@ int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
int ret;
- indio_dev->buffer = iio_sw_rb_allocate(indio_dev);
+ indio_dev->buffer = iio_kfifo_allocate(indio_dev);
if (!indio_dev->buffer) {
ret = -ENOMEM;
goto error_ret;
@@ -139,7 +127,7 @@ int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->id);
if (indio_dev->pollfunc == NULL) {
ret = -ENOMEM;
- goto error_deallocate_sw_rb;
+ goto error_deallocate_kfifo;
}
/* Ring buffer functions - here trigger setup related */
indio_dev->setup_ops = &ad7887_ring_setup_ops;
@@ -148,8 +136,8 @@ int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
return 0;
-error_deallocate_sw_rb:
- iio_sw_rb_free(indio_dev->buffer);
+error_deallocate_kfifo:
+ iio_kfifo_free(indio_dev->buffer);
error_ret:
return ret;
}
@@ -157,5 +145,5 @@ error_ret:
void ad7887_ring_cleanup(struct iio_dev *indio_dev)
{
iio_dealloc_pollfunc(indio_dev->pollfunc);
- iio_sw_rb_free(indio_dev->buffer);
+ iio_kfifo_free(indio_dev->buffer);
}
diff --git a/drivers/staging/iio/adc/ad799x.h b/drivers/staging/iio/adc/ad799x.h
index 356f690a76fb..99f8abe9731b 100644
--- a/drivers/staging/iio/adc/ad799x.h
+++ b/drivers/staging/iio/adc/ad799x.h
@@ -104,7 +104,6 @@ struct ad799x_chip_info {
struct ad799x_state {
struct i2c_client *client;
const struct ad799x_chip_info *chip_info;
- size_t d_size;
struct iio_trigger *trig;
struct regulator *reg;
u16 int_vref_mv;
diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
index a8458669350f..80e0c6e25a9b 100644
--- a/drivers/staging/iio/adc/ad799x_core.c
+++ b/drivers/staging/iio/adc/ad799x_core.c
@@ -33,10 +33,10 @@
#include <linux/err.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../events.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+#include <linux/iio/buffer.h>
#include "ad799x.h"
@@ -148,7 +148,7 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
unsigned int scale_uv;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
ret = -EBUSY;
@@ -182,7 +182,7 @@ static ssize_t ad799x_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad799x_state *st = iio_priv(indio_dev);
int ret;
@@ -201,7 +201,7 @@ static ssize_t ad799x_write_frequency(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad799x_state *st = iio_priv(indio_dev);
long val;
@@ -294,7 +294,7 @@ static ssize_t ad799x_read_channel_config(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad799x_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -312,7 +312,7 @@ static ssize_t ad799x_write_channel_config(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad799x_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -454,6 +454,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 0,
.scan_type = IIO_ST('u', 12, 16, 0),
},
@@ -461,6 +462,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 1,
.scan_type = IIO_ST('u', 12, 16, 0),
},
@@ -468,6 +470,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 2,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 2,
.scan_type = IIO_ST('u', 12, 16, 0),
},
@@ -475,6 +478,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 3,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 3,
.scan_type = IIO_ST('u', 12, 16, 0),
},
@@ -490,6 +494,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 0,
.scan_type = IIO_ST('u', 10, 16, 2),
},
@@ -497,6 +502,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 1,
.scan_type = IIO_ST('u', 10, 16, 2),
},
@@ -504,6 +510,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 2,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 2,
.scan_type = IIO_ST('u', 10, 16, 2),
},
@@ -511,6 +518,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 3,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 3,
.scan_type = IIO_ST('u', 10, 16, 2),
},
@@ -526,6 +534,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 0,
.scan_type = IIO_ST('u', 8, 16, 4),
},
@@ -533,6 +542,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 1,
.scan_type = IIO_ST('u', 8, 16, 4),
},
@@ -540,6 +550,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 2,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 2,
.scan_type = IIO_ST('u', 8, 16, 4),
},
@@ -547,6 +558,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 3,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 3,
.scan_type = IIO_ST('u', 8, 16, 4),
},
@@ -562,6 +574,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 0,
.scan_type = IIO_ST('u', 12, 16, 0),
.event_mask = AD799X_EV_MASK,
@@ -570,6 +583,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 1,
.scan_type = IIO_ST('u', 12, 16, 0),
.event_mask = AD799X_EV_MASK,
@@ -587,6 +601,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 0,
.scan_type = IIO_ST('u', 10, 16, 2),
.event_mask = AD799X_EV_MASK,
@@ -596,6 +611,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.indexed = 1,
.channel = 1,
.scan_index = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_type = IIO_ST('u', 10, 16, 2),
.event_mask = AD799X_EV_MASK,
},
@@ -603,6 +619,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 2,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 2,
.scan_type = IIO_ST('u', 10, 16, 2),
.event_mask = AD799X_EV_MASK,
@@ -611,6 +628,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 3,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 3,
.scan_type = IIO_ST('u', 10, 16, 2),
.event_mask = AD799X_EV_MASK,
@@ -628,6 +646,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 0,
.scan_type = IIO_ST('u', 12, 16, 0),
.event_mask = AD799X_EV_MASK,
@@ -636,6 +655,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 1,
.scan_type = IIO_ST('u', 12, 16, 0),
.event_mask = AD799X_EV_MASK,
@@ -644,6 +664,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 2,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 2,
.scan_type = IIO_ST('u', 12, 16, 0),
.event_mask = AD799X_EV_MASK,
@@ -652,6 +673,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 3,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 3,
.scan_type = IIO_ST('u', 12, 16, 0),
.event_mask = AD799X_EV_MASK,
@@ -669,6 +691,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 0,
.scan_type = IIO_ST('u', 10, 16, 2),
.event_mask = AD799X_EV_MASK,
@@ -677,6 +700,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 1,
.scan_type = IIO_ST('u', 10, 16, 2),
.event_mask = AD799X_EV_MASK,
@@ -685,6 +709,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 2,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 2,
.scan_type = IIO_ST('u', 10, 16, 2),
.event_mask = AD799X_EV_MASK,
@@ -693,6 +718,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 3,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 3,
.scan_type = IIO_ST('u', 10, 16, 2),
.event_mask = AD799X_EV_MASK,
@@ -701,6 +727,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 4,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 4,
.scan_type = IIO_ST('u', 10, 16, 2),
},
@@ -708,6 +735,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 5,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 5,
.scan_type = IIO_ST('u', 10, 16, 2),
},
@@ -715,6 +743,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 6,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 6,
.scan_type = IIO_ST('u', 10, 16, 2),
},
@@ -722,6 +751,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 7,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 7,
.scan_type = IIO_ST('u', 10, 16, 2),
},
@@ -738,6 +768,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 0,
.scan_type = IIO_ST('u', 12, 16, 0),
.event_mask = AD799X_EV_MASK,
@@ -746,6 +777,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 1,
.scan_type = IIO_ST('u', 12, 16, 0),
.event_mask = AD799X_EV_MASK,
@@ -754,6 +786,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 2,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 2,
.scan_type = IIO_ST('u', 12, 16, 0),
.event_mask = AD799X_EV_MASK,
@@ -762,6 +795,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 3,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 3,
.scan_type = IIO_ST('u', 12, 16, 0),
.event_mask = AD799X_EV_MASK,
@@ -770,6 +804,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 4,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 4,
.scan_type = IIO_ST('u', 12, 16, 0),
},
@@ -777,6 +812,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 5,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 5,
.scan_type = IIO_ST('u', 12, 16, 0),
},
@@ -784,6 +820,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 6,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 6,
.scan_type = IIO_ST('u', 12, 16, 0),
},
@@ -791,6 +828,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 7,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.scan_index = 7,
.scan_type = IIO_ST('u', 12, 16, 0),
},
@@ -809,7 +847,7 @@ static int __devinit ad799x_probe(struct i2c_client *client,
int ret;
struct ad799x_platform_data *pdata = client->dev.platform_data;
struct ad799x_state *st;
- struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+ struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -882,7 +920,7 @@ error_disable_reg:
error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
@@ -902,7 +940,7 @@ static __devexit int ad799x_remove(struct i2c_client *client)
regulator_disable(st->reg);
regulator_put(st->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c
index 069765cab275..1c7ff4423db4 100644
--- a/drivers/staging/iio/adc/ad799x_ring.c
+++ b/drivers/staging/iio/adc/ad799x_ring.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc.
+ * Copyright (C) 2010-2012 Michael Hennerich, Analog Devices Inc.
* Copyright (C) 2008-2010 Jonathan Cameron
*
* This program is free software; you can redistribute it and/or modify
@@ -16,10 +16,10 @@
#include <linux/i2c.h>
#include <linux/bitops.h>
-#include "../iio.h"
-#include "../buffer.h"
-#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger_consumer.h>
#include "ad799x.h"
@@ -32,9 +32,7 @@
**/
static int ad799x_ring_preenable(struct iio_dev *indio_dev)
{
- struct iio_buffer *ring = indio_dev->buffer;
struct ad799x_state *st = iio_priv(indio_dev);
-
/*
* Need to figure out the current mode based upon the requested
* scan mask in iio_dev
@@ -43,21 +41,7 @@ static int ad799x_ring_preenable(struct iio_dev *indio_dev)
if (st->id == ad7997 || st->id == ad7998)
ad7997_8_set_scan_mode(st, *indio_dev->active_scan_mask);
- st->d_size = bitmap_weight(indio_dev->active_scan_mask,
- indio_dev->masklength) * 2;
-
- if (ring->scan_timestamp) {
- st->d_size += sizeof(s64);
-
- if (st->d_size % sizeof(s64))
- st->d_size += sizeof(s64) - (st->d_size % sizeof(s64));
- }
-
- if (indio_dev->buffer->access->set_bytes_per_datum)
- indio_dev->buffer->access->
- set_bytes_per_datum(indio_dev->buffer, st->d_size);
-
- return 0;
+ return iio_sw_buffer_preenable(indio_dev);
}
/**
@@ -78,7 +62,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
int b_sent;
u8 cmd;
- rxbuf = kmalloc(st->d_size, GFP_KERNEL);
+ rxbuf = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (rxbuf == NULL)
goto out;
@@ -111,8 +95,8 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
time_ns = iio_get_time_ns();
- if (ring->scan_timestamp)
- memcpy(rxbuf + st->d_size - sizeof(s64),
+ if (indio_dev->scan_timestamp)
+ memcpy(rxbuf + indio_dev->scan_bytes - sizeof(s64),
&time_ns, sizeof(time_ns));
ring->access->store_to(indio_dev->buffer, rxbuf, time_ns);
@@ -136,7 +120,7 @@ int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
int ret = 0;
- indio_dev->buffer = iio_sw_rb_allocate(indio_dev);
+ indio_dev->buffer = iio_kfifo_allocate(indio_dev);
if (!indio_dev->buffer) {
ret = -ENOMEM;
goto error_ret;
@@ -150,7 +134,7 @@ int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->id);
if (indio_dev->pollfunc == NULL) {
ret = -ENOMEM;
- goto error_deallocate_sw_rb;
+ goto error_deallocate_kfifo;
}
/* Ring buffer functions - here trigger setup related */
@@ -161,8 +145,8 @@ int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev)
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
return 0;
-error_deallocate_sw_rb:
- iio_sw_rb_free(indio_dev->buffer);
+error_deallocate_kfifo:
+ iio_kfifo_free(indio_dev->buffer);
error_ret:
return ret;
}
@@ -170,5 +154,5 @@ error_ret:
void ad799x_ring_cleanup(struct iio_dev *indio_dev)
{
iio_dealloc_pollfunc(indio_dev->pollfunc);
- iio_sw_rb_free(indio_dev->buffer);
+ iio_kfifo_free(indio_dev->buffer);
}
diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c
index caf57c1169b1..e5f1ed7f8696 100644
--- a/drivers/staging/iio/adc/adt7310.c
+++ b/drivers/staging/iio/adc/adt7310.c
@@ -15,9 +15,9 @@
#include <linux/spi/spi.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../events.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
/*
* ADT7310 registers definition
*/
@@ -175,7 +175,7 @@ static ssize_t adt7310_show_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
u8 config;
@@ -198,7 +198,7 @@ static ssize_t adt7310_store_mode(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
u16 config;
int ret;
@@ -242,7 +242,7 @@ static ssize_t adt7310_show_resolution(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
int ret;
int bits;
@@ -264,7 +264,7 @@ static ssize_t adt7310_store_resolution(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
unsigned long data;
u16 config;
@@ -300,7 +300,7 @@ static ssize_t adt7310_show_id(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
u8 id;
int ret;
@@ -350,7 +350,7 @@ static ssize_t adt7310_show_value(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
u8 status;
u16 data;
@@ -424,7 +424,7 @@ static ssize_t adt7310_show_event_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
int ret;
@@ -443,7 +443,7 @@ static ssize_t adt7310_set_event_mode(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
u16 config;
int ret;
@@ -476,7 +476,7 @@ static ssize_t adt7310_show_fault_queue(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
int ret;
@@ -492,7 +492,7 @@ static ssize_t adt7310_set_fault_queue(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
unsigned long data;
int ret;
@@ -522,7 +522,7 @@ static inline ssize_t adt7310_show_t_bound(struct device *dev,
u8 bound_reg,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
u16 data;
int ret;
@@ -540,7 +540,7 @@ static inline ssize_t adt7310_set_t_bound(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
long tmp1, tmp2;
u16 data;
@@ -660,7 +660,7 @@ static ssize_t adt7310_show_t_hyst(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
int ret;
u8 t_hyst;
@@ -677,7 +677,7 @@ static inline ssize_t adt7310_set_t_hyst(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7310_chip_info *chip = iio_priv(dev_info);
int ret;
unsigned long data;
@@ -753,7 +753,7 @@ static int __devinit adt7310_probe(struct spi_device *spi_dev)
unsigned long *adt7310_platform_data = spi_dev->dev.platform_data;
unsigned long irq_flags;
- indio_dev = iio_allocate_device(sizeof(*chip));
+ indio_dev = iio_device_alloc(sizeof(*chip));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -833,7 +833,7 @@ error_unreg_int_irq:
error_unreg_ct_irq:
free_irq(spi_dev->irq, indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -849,7 +849,7 @@ static int __devexit adt7310_remove(struct spi_device *spi_dev)
free_irq(adt7310_platform_data[0], indio_dev);
if (spi_dev->irq)
free_irq(spi_dev->irq, indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c
index dff3e8ca2d78..917b6921e24d 100644
--- a/drivers/staging/iio/adc/adt7410.c
+++ b/drivers/staging/iio/adc/adt7410.c
@@ -15,9 +15,9 @@
#include <linux/i2c.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../events.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
/*
* ADT7410 registers definition
@@ -144,7 +144,7 @@ static ssize_t adt7410_show_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
u8 config;
@@ -167,7 +167,7 @@ static ssize_t adt7410_store_mode(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
u16 config;
int ret;
@@ -211,7 +211,7 @@ static ssize_t adt7410_show_resolution(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
int ret;
int bits;
@@ -233,7 +233,7 @@ static ssize_t adt7410_store_resolution(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
unsigned long data;
u16 config;
@@ -269,7 +269,7 @@ static ssize_t adt7410_show_id(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
u8 id;
int ret;
@@ -319,7 +319,7 @@ static ssize_t adt7410_show_value(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
u8 status;
u16 data;
@@ -392,7 +392,7 @@ static ssize_t adt7410_show_event_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
int ret;
@@ -411,7 +411,7 @@ static ssize_t adt7410_set_event_mode(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
u16 config;
int ret;
@@ -444,7 +444,7 @@ static ssize_t adt7410_show_fault_queue(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
int ret;
@@ -460,7 +460,7 @@ static ssize_t adt7410_set_fault_queue(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
unsigned long data;
int ret;
@@ -490,7 +490,7 @@ static inline ssize_t adt7410_show_t_bound(struct device *dev,
u8 bound_reg,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
u16 data;
int ret;
@@ -508,7 +508,7 @@ static inline ssize_t adt7410_set_t_bound(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
long tmp1, tmp2;
u16 data;
@@ -628,7 +628,7 @@ static ssize_t adt7410_show_t_hyst(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
int ret;
u8 t_hyst;
@@ -645,7 +645,7 @@ static inline ssize_t adt7410_set_t_hyst(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7410_chip_info *chip = iio_priv(dev_info);
int ret;
unsigned long data;
@@ -721,7 +721,7 @@ static int __devinit adt7410_probe(struct i2c_client *client,
int ret = 0;
unsigned long *adt7410_platform_data = client->dev.platform_data;
- indio_dev = iio_allocate_device(sizeof(*chip));
+ indio_dev = iio_device_alloc(sizeof(*chip));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -797,7 +797,7 @@ error_unreg_int_irq:
error_unreg_ct_irq:
free_irq(client->irq, indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -812,7 +812,7 @@ static int __devexit adt7410_remove(struct i2c_client *client)
free_irq(adt7410_platform_data[0], indio_dev);
if (client->irq)
free_irq(client->irq, indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c
index dfc9033843a3..9690306d1f8f 100644
--- a/drivers/staging/iio/adc/lpc32xx_adc.c
+++ b/drivers/staging/iio/adc/lpc32xx_adc.c
@@ -30,9 +30,10 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/completion.h>
+#include <linux/of.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
/*
* LPC32XX registers definitions
@@ -73,7 +74,7 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
{
struct lpc32xx_adc_info *info = iio_priv(indio_dev);
- if (mask == 0) {
+ if (mask == IIO_CHAN_INFO_RAW) {
mutex_lock(&indio_dev->mlock);
clk_enable(info->clk);
/* Measurement setup */
@@ -98,12 +99,13 @@ static const struct iio_info lpc32xx_adc_iio_info = {
.driver_module = THIS_MODULE,
};
-#define LPC32XX_ADC_CHANNEL(_index) { \
- .type = IIO_VOLTAGE, \
- .indexed = 1, \
- .channel = _index, \
- .address = AD_IN * _index, \
- .scan_index = _index, \
+#define LPC32XX_ADC_CHANNEL(_index) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = _index, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \
+ .address = AD_IN * _index, \
+ .scan_index = _index, \
}
static struct iio_chan_spec lpc32xx_adc_iio_channels[] = {
@@ -139,7 +141,7 @@ static int __devinit lpc32xx_adc_probe(struct platform_device *pdev)
goto errout1;
}
- iodev = iio_allocate_device(sizeof(struct lpc32xx_adc_info));
+ iodev = iio_device_alloc(sizeof(struct lpc32xx_adc_info));
if (!iodev) {
dev_err(&pdev->dev, "failed allocating iio device\n");
retval = -ENOMEM;
@@ -200,7 +202,7 @@ errout4:
errout3:
iounmap(info->adc_base);
errout2:
- iio_free_device(iodev);
+ iio_device_free(iodev);
errout1:
return retval;
}
@@ -216,17 +218,26 @@ static int __devexit lpc32xx_adc_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
clk_put(info->clk);
iounmap(info->adc_base);
- iio_free_device(iodev);
+ iio_device_free(iodev);
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id lpc32xx_adc_match[] = {
+ { .compatible = "nxp,lpc3220-adc" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, lpc32xx_adc_match);
+#endif
+
static struct platform_driver lpc32xx_adc_driver = {
.probe = lpc32xx_adc_probe,
.remove = __devexit_p(lpc32xx_adc_remove),
.driver = {
.name = MOD_NAME,
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(lpc32xx_adc_match),
},
};
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index cf3e2ca7e314..6799ce23a395 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -32,10 +32,11 @@
#include <linux/err.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../events.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/driver.h>
#include "max1363.h"
@@ -248,7 +249,7 @@ static int max1363_read_raw(struct iio_dev *indio_dev,
struct max1363_state *st = iio_priv(indio_dev);
int ret;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
ret = max1363_read_single_chan(indio_dev, chan, val, m);
if (ret < 0)
return ret;
@@ -281,7 +282,8 @@ static const enum max1363_modes max1363_mode_list[] = {
#define MAX1363_EV_M \
(IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) \
| IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
-#define MAX1363_INFO_MASK IIO_CHAN_INFO_SCALE_SHARED_BIT
+#define MAX1363_INFO_MASK (IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT)
#define MAX1363_CHAN_U(num, addr, si, bits, evmask) \
{ \
.type = IIO_VOLTAGE, \
@@ -497,7 +499,7 @@ static ssize_t max1363_monitor_show_freq(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct max1363_state *st = iio_priv(dev_get_drvdata(dev));
+ struct max1363_state *st = iio_priv(dev_to_iio_dev(dev));
return sprintf(buf, "%d\n", max1363_monitor_speeds[st->monitor_speed]);
}
@@ -506,7 +508,7 @@ static ssize_t max1363_monitor_store_freq(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct max1363_state *st = iio_priv(indio_dev);
int i, ret;
unsigned long val;
@@ -830,6 +832,7 @@ static struct attribute_group max1363_event_attribute_group = {
static const struct iio_info max1238_info = {
.read_raw = &max1363_read_raw,
.driver_module = THIS_MODULE,
+ .update_scan_mode = &max1363_update_scan_mode,
};
static const struct iio_info max1363_info = {
@@ -1284,11 +1287,14 @@ static int __devinit max1363_probe(struct i2c_client *client,
if (ret)
goto error_put_reg;
- indio_dev = iio_allocate_device(sizeof(struct max1363_state));
+ indio_dev = iio_device_alloc(sizeof(struct max1363_state));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
}
+ ret = iio_map_array_register(indio_dev, client->dev.platform_data);
+ if (ret < 0)
+ goto error_free_device;
st = iio_priv(indio_dev);
st->reg = reg;
/* this is only used for device removal purposes */
@@ -1299,7 +1305,7 @@ static int __devinit max1363_probe(struct i2c_client *client,
ret = max1363_alloc_scan_masks(indio_dev);
if (ret)
- goto error_free_device;
+ goto error_unregister_map;
/* Estabilish that the iio_dev is a child of the i2c device */
indio_dev->dev.parent = &client->dev;
@@ -1349,8 +1355,10 @@ error_cleanup_ring:
max1363_ring_cleanup(indio_dev);
error_free_available_scan_masks:
kfree(indio_dev->available_scan_masks);
+error_unregister_map:
+ iio_map_array_unregister(indio_dev, client->dev.platform_data);
error_free_device:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_disable_reg:
regulator_disable(reg);
error_put_reg:
@@ -1375,7 +1383,8 @@ static int max1363_remove(struct i2c_client *client)
regulator_disable(reg);
regulator_put(reg);
}
- iio_free_device(indio_dev);
+ iio_map_array_unregister(indio_dev, client->dev.platform_data);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c
index d0a60a382930..b30201300121 100644
--- a/drivers/staging/iio/adc/max1363_ring.c
+++ b/drivers/staging/iio/adc/max1363_ring.c
@@ -14,10 +14,10 @@
#include <linux/i2c.h>
#include <linux/bitops.h>
-#include "../iio.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/trigger_consumer.h>
#include "max1363.h"
@@ -54,7 +54,7 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
d_size = numvals*2;
else
d_size = numvals;
- if (indio_dev->buffer->scan_timestamp) {
+ if (indio_dev->scan_timestamp) {
d_size += sizeof(s64);
if (d_size % sizeof(s64))
d_size += sizeof(s64) - (d_size % sizeof(s64));
@@ -78,7 +78,7 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
time_ns = iio_get_time_ns();
- if (indio_dev->buffer->scan_timestamp)
+ if (indio_dev->scan_timestamp)
memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
iio_push_to_buffer(indio_dev->buffer, rxbuf, time_ns);
diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
new file mode 100644
index 000000000000..64d630e6fe29
--- /dev/null
+++ b/drivers/staging/iio/adc/spear_adc.c
@@ -0,0 +1,448 @@
+/*
+ * ST SPEAr ADC driver
+ *
+ * Copyright 2012 Stefan Roese <sr@denx.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/completion.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+/*
+ * SPEAR registers definitions
+ */
+
+#define SCAN_RATE_LO(x) ((x) & 0xFFFF)
+#define SCAN_RATE_HI(x) (((x) >> 0x10) & 0xFFFF)
+#define CLK_LOW(x) (((x) & 0xf) << 0)
+#define CLK_HIGH(x) (((x) & 0xf) << 4)
+
+/* Bit definitions for SPEAR_ADC_STATUS */
+#define START_CONVERSION (1 << 0)
+#define CHANNEL_NUM(x) ((x) << 1)
+#define ADC_ENABLE (1 << 4)
+#define AVG_SAMPLE(x) ((x) << 5)
+#define VREF_INTERNAL (1 << 9)
+
+#define DATA_MASK 0x03ff
+#define DATA_BITS 10
+
+#define MOD_NAME "spear-adc"
+
+#define ADC_CHANNEL_NUM 8
+
+#define CLK_MIN 2500000
+#define CLK_MAX 20000000
+
+struct adc_regs_spear3xx {
+ u32 status;
+ u32 average;
+ u32 scan_rate;
+ u32 clk; /* Not avail for 1340 & 1310 */
+ u32 ch_ctrl[ADC_CHANNEL_NUM];
+ u32 ch_data[ADC_CHANNEL_NUM];
+};
+
+struct chan_data {
+ u32 lsb;
+ u32 msb;
+};
+
+struct adc_regs_spear6xx {
+ u32 status;
+ u32 pad[2];
+ u32 clk;
+ u32 ch_ctrl[ADC_CHANNEL_NUM];
+ struct chan_data ch_data[ADC_CHANNEL_NUM];
+ u32 scan_rate_lo;
+ u32 scan_rate_hi;
+ struct chan_data average;
+};
+
+struct spear_adc_info {
+ struct device_node *np;
+ struct adc_regs_spear3xx __iomem *adc_base_spear3xx;
+ struct adc_regs_spear6xx __iomem *adc_base_spear6xx;
+ struct clk *clk;
+ struct completion completion;
+ u32 current_clk;
+ u32 sampling_freq;
+ u32 avg_samples;
+ u32 vref_external;
+ u32 value;
+};
+
+/*
+ * Functions to access some SPEAr ADC register. Abstracted into
+ * static inline functions, because of different register offsets
+ * on different SoC variants (SPEAr300 vs SPEAr600 etc).
+ */
+static void spear_adc_set_status(struct spear_adc_info *info, u32 val)
+{
+ __raw_writel(val, &info->adc_base_spear6xx->status);
+}
+
+static void spear_adc_set_clk(struct spear_adc_info *info, u32 val)
+{
+ u32 clk_high, clk_low, count;
+ u32 apb_clk = clk_get_rate(info->clk);
+
+ count = (apb_clk + val - 1) / val;
+ clk_low = count / 2;
+ clk_high = count - clk_low;
+ info->current_clk = apb_clk / count;
+
+ __raw_writel(CLK_LOW(clk_low) | CLK_HIGH(clk_high),
+ &info->adc_base_spear6xx->clk);
+}
+
+static void spear_adc_set_ctrl(struct spear_adc_info *info, int n,
+ u32 val)
+{
+ __raw_writel(val, &info->adc_base_spear6xx->ch_ctrl[n]);
+}
+
+static u32 spear_adc_get_average(struct spear_adc_info *info)
+{
+ if (of_device_is_compatible(info->np, "st,spear600-adc")) {
+ return __raw_readl(&info->adc_base_spear6xx->average.msb) &
+ DATA_MASK;
+ } else {
+ return __raw_readl(&info->adc_base_spear3xx->average) &
+ DATA_MASK;
+ }
+}
+
+static void spear_adc_set_scanrate(struct spear_adc_info *info, u32 rate)
+{
+ if (of_device_is_compatible(info->np, "st,spear600-adc")) {
+ __raw_writel(SCAN_RATE_LO(rate),
+ &info->adc_base_spear6xx->scan_rate_lo);
+ __raw_writel(SCAN_RATE_HI(rate),
+ &info->adc_base_spear6xx->scan_rate_hi);
+ } else {
+ __raw_writel(rate, &info->adc_base_spear3xx->scan_rate);
+ }
+}
+
+static int spear_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long mask)
+{
+ struct spear_adc_info *info = iio_priv(indio_dev);
+ u32 scale_mv;
+ u32 status;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&indio_dev->mlock);
+
+ status = CHANNEL_NUM(chan->channel) |
+ AVG_SAMPLE(info->avg_samples) |
+ START_CONVERSION | ADC_ENABLE;
+ if (info->vref_external == 0)
+ status |= VREF_INTERNAL;
+
+ spear_adc_set_status(info, status);
+ wait_for_completion(&info->completion); /* set by ISR */
+ *val = info->value;
+
+ mutex_unlock(&indio_dev->mlock);
+
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ scale_mv = (info->vref_external * 1000) >> DATA_BITS;
+ *val = scale_mv / 1000;
+ *val2 = (scale_mv % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+
+ return -EINVAL;
+}
+
+#define SPEAR_ADC_CHAN(idx) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .channel = idx, \
+ .scan_type = { \
+ .sign = 'u', \
+ .storagebits = 16, \
+ }, \
+}
+
+static struct iio_chan_spec spear_adc_iio_channels[] = {
+ SPEAR_ADC_CHAN(0),
+ SPEAR_ADC_CHAN(1),
+ SPEAR_ADC_CHAN(2),
+ SPEAR_ADC_CHAN(3),
+ SPEAR_ADC_CHAN(4),
+ SPEAR_ADC_CHAN(5),
+ SPEAR_ADC_CHAN(6),
+ SPEAR_ADC_CHAN(7),
+};
+
+static irqreturn_t spear_adc_isr(int irq, void *dev_id)
+{
+ struct spear_adc_info *info = (struct spear_adc_info *)dev_id;
+
+ /* Read value to clear IRQ */
+ info->value = spear_adc_get_average(info);
+ complete(&info->completion);
+
+ return IRQ_HANDLED;
+}
+
+static int spear_adc_configure(struct spear_adc_info *info)
+{
+ int i;
+
+ /* Reset ADC core */
+ spear_adc_set_status(info, 0);
+ __raw_writel(0, &info->adc_base_spear6xx->clk);
+ for (i = 0; i < 8; i++)
+ spear_adc_set_ctrl(info, i, 0);
+ spear_adc_set_scanrate(info, 0);
+
+ spear_adc_set_clk(info, info->sampling_freq);
+
+ return 0;
+}
+
+static ssize_t spear_adc_read_frequency(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct spear_adc_info *info = iio_priv(indio_dev);
+
+ return sprintf(buf, "%d\n", info->current_clk);
+}
+
+static ssize_t spear_adc_write_frequency(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct spear_adc_info *info = iio_priv(indio_dev);
+ u32 clk_high, clk_low, count;
+ u32 apb_clk = clk_get_rate(info->clk);
+ unsigned long lval;
+ int ret;
+
+ ret = kstrtoul(buf, 10, &lval);
+ if (ret)
+ return ret;
+
+ mutex_lock(&indio_dev->mlock);
+
+ if ((lval < CLK_MIN) || (lval > CLK_MAX)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ count = (apb_clk + lval - 1) / lval;
+ clk_low = count / 2;
+ clk_high = count - clk_low;
+ info->current_clk = apb_clk / count;
+ spear_adc_set_clk(info, lval);
+
+out:
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret ? ret : len;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+ spear_adc_read_frequency,
+ spear_adc_write_frequency);
+
+static struct attribute *spear_attributes[] = {
+ &iio_dev_attr_sampling_frequency.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group spear_attribute_group = {
+ .attrs = spear_attributes,
+};
+
+static const struct iio_info spear_adc_iio_info = {
+ .read_raw = &spear_read_raw,
+ .attrs = &spear_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static int __devinit spear_adc_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ struct spear_adc_info *info;
+ struct iio_dev *iodev = NULL;
+ int ret = -ENODEV;
+ int irq;
+
+ iodev = iio_device_alloc(sizeof(struct spear_adc_info));
+ if (!iodev) {
+ dev_err(dev, "failed allocating iio device\n");
+ ret = -ENOMEM;
+ goto errout1;
+ }
+
+ info = iio_priv(iodev);
+ info->np = np;
+
+ /*
+ * SPEAr600 has a different register layout than other SPEAr SoC's
+ * (e.g. SPEAr3xx). Let's provide two register base addresses
+ * to support multi-arch kernels.
+ */
+ info->adc_base_spear6xx = of_iomap(np, 0);
+ if (!info->adc_base_spear6xx) {
+ dev_err(dev, "failed mapping memory\n");
+ ret = -ENOMEM;
+ goto errout2;
+ }
+ info->adc_base_spear3xx =
+ (struct adc_regs_spear3xx *)info->adc_base_spear6xx;
+
+ info->clk = clk_get(dev, NULL);
+ if (IS_ERR(info->clk)) {
+ dev_err(dev, "failed getting clock\n");
+ goto errout3;
+ }
+
+ ret = clk_prepare(info->clk);
+ if (ret) {
+ dev_err(dev, "failed preparing clock\n");
+ goto errout4;
+ }
+
+ ret = clk_enable(info->clk);
+ if (ret) {
+ dev_err(dev, "failed enabling clock\n");
+ goto errout5;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if ((irq < 0) || (irq >= NR_IRQS)) {
+ dev_err(dev, "failed getting interrupt resource\n");
+ ret = -EINVAL;
+ goto errout6;
+ }
+
+ ret = devm_request_irq(dev, irq, spear_adc_isr, 0, MOD_NAME, info);
+ if (ret < 0) {
+ dev_err(dev, "failed requesting interrupt\n");
+ goto errout6;
+ }
+
+ if (of_property_read_u32(np, "sampling-frequency",
+ &info->sampling_freq)) {
+ dev_err(dev, "sampling-frequency missing in DT\n");
+ ret = -EINVAL;
+ goto errout6;
+ }
+
+ /*
+ * Optional avg_samples defaults to 0, resulting in single data
+ * conversion
+ */
+ of_property_read_u32(np, "average-samples", &info->avg_samples);
+
+ /*
+ * Optional vref_external defaults to 0, resulting in internal vref
+ * selection
+ */
+ of_property_read_u32(np, "vref-external", &info->vref_external);
+
+ spear_adc_configure(info);
+
+ platform_set_drvdata(pdev, iodev);
+
+ init_completion(&info->completion);
+
+ iodev->name = MOD_NAME;
+ iodev->dev.parent = dev;
+ iodev->info = &spear_adc_iio_info;
+ iodev->modes = INDIO_DIRECT_MODE;
+ iodev->channels = spear_adc_iio_channels;
+ iodev->num_channels = ARRAY_SIZE(spear_adc_iio_channels);
+
+ ret = iio_device_register(iodev);
+ if (ret)
+ goto errout6;
+
+ dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n", irq);
+
+ return 0;
+
+errout6:
+ clk_disable(info->clk);
+errout5:
+ clk_unprepare(info->clk);
+errout4:
+ clk_put(info->clk);
+errout3:
+ iounmap(info->adc_base_spear6xx);
+errout2:
+ iio_device_free(iodev);
+errout1:
+ return ret;
+}
+
+static int __devexit spear_adc_remove(struct platform_device *pdev)
+{
+ struct iio_dev *iodev = platform_get_drvdata(pdev);
+ struct spear_adc_info *info = iio_priv(iodev);
+
+ iio_device_unregister(iodev);
+ platform_set_drvdata(pdev, NULL);
+ clk_disable(info->clk);
+ clk_unprepare(info->clk);
+ clk_put(info->clk);
+ iounmap(info->adc_base_spear6xx);
+ iio_device_free(iodev);
+
+ return 0;
+}
+
+static const struct of_device_id spear_adc_dt_ids[] = {
+ { .compatible = "st,spear600-adc", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, spear_adc_dt_ids);
+
+static struct platform_driver spear_adc_driver = {
+ .probe = spear_adc_probe,
+ .remove = __devexit_p(spear_adc_remove),
+ .driver = {
+ .name = MOD_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(spear_adc_dt_ids),
+ },
+};
+
+module_platform_driver(spear_adc_driver);
+
+MODULE_AUTHOR("Stefan Roese <sr@denx.de>");
+MODULE_DESCRIPTION("SPEAr ADC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c
index fd6a45444058..8fb014a046a2 100644
--- a/drivers/staging/iio/addac/adt7316.c
+++ b/drivers/staging/iio/addac/adt7316.c
@@ -19,9 +19,9 @@
#include <linux/rtc.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../events.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/events.h>
+#include <linux/iio/sysfs.h>
#include "adt7316.h"
/*
@@ -220,7 +220,7 @@ static ssize_t adt7316_show_enabled(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_EN));
@@ -252,7 +252,7 @@ static ssize_t adt7316_store_enabled(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
int enable;
@@ -276,7 +276,7 @@ static ssize_t adt7316_show_select_ex_temp(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX)
@@ -290,7 +290,7 @@ static ssize_t adt7316_store_select_ex_temp(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config1;
int ret;
@@ -320,7 +320,7 @@ static ssize_t adt7316_show_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
if (chip->config2 & ADT7316_AD_SINGLE_CH_MODE)
@@ -334,7 +334,7 @@ static ssize_t adt7316_store_mode(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config2;
int ret;
@@ -370,7 +370,7 @@ static ssize_t adt7316_show_ad_channel(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE))
@@ -409,7 +409,7 @@ static ssize_t adt7316_store_ad_channel(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config2;
unsigned long data = 0;
@@ -455,7 +455,7 @@ static ssize_t adt7316_show_all_ad_channels(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE))
@@ -477,7 +477,7 @@ static ssize_t adt7316_show_disable_averaging(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n",
@@ -489,7 +489,7 @@ static ssize_t adt7316_store_disable_averaging(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config2;
int ret;
@@ -516,7 +516,7 @@ static ssize_t adt7316_show_enable_smbus_timeout(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n",
@@ -528,7 +528,7 @@ static ssize_t adt7316_store_enable_smbus_timeout(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config2;
int ret;
@@ -557,7 +557,7 @@ static ssize_t adt7316_store_reset(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config2;
int ret;
@@ -580,7 +580,7 @@ static ssize_t adt7316_show_powerdown(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_PD));
@@ -591,7 +591,7 @@ static ssize_t adt7316_store_powerdown(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config1;
int ret;
@@ -618,7 +618,7 @@ static ssize_t adt7316_show_fast_ad_clock(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n", !!(chip->config3 & ADT7316_ADCLK_22_5));
@@ -629,7 +629,7 @@ static ssize_t adt7316_store_fast_ad_clock(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config3;
int ret;
@@ -656,7 +656,7 @@ static ssize_t adt7316_show_da_high_resolution(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
if (chip->config3 & ADT7316_DA_HIGH_RESOLUTION) {
@@ -674,7 +674,7 @@ static ssize_t adt7316_store_da_high_resolution(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config3;
int ret;
@@ -708,7 +708,7 @@ static ssize_t adt7316_show_AIN_internal_Vref(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX)
@@ -723,7 +723,7 @@ static ssize_t adt7316_store_AIN_internal_Vref(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config3;
int ret;
@@ -755,7 +755,7 @@ static ssize_t adt7316_show_enable_prop_DACA(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n",
@@ -767,7 +767,7 @@ static ssize_t adt7316_store_enable_prop_DACA(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config3;
int ret;
@@ -794,7 +794,7 @@ static ssize_t adt7316_show_enable_prop_DACB(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n",
@@ -806,7 +806,7 @@ static ssize_t adt7316_store_enable_prop_DACB(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config3;
int ret;
@@ -833,7 +833,7 @@ static ssize_t adt7316_show_DAC_2Vref_ch_mask(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "0x%x\n",
@@ -845,7 +845,7 @@ static ssize_t adt7316_store_DAC_2Vref_ch_mask(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 dac_config;
unsigned long data = 0;
@@ -876,7 +876,7 @@ static ssize_t adt7316_show_DAC_update_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA))
@@ -900,7 +900,7 @@ static ssize_t adt7316_store_DAC_update_mode(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 dac_config;
unsigned long data;
@@ -934,7 +934,7 @@ static ssize_t adt7316_show_all_DAC_update_modes(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA)
@@ -955,7 +955,7 @@ static ssize_t adt7316_store_update_DAC(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 ldac_config;
unsigned long data;
@@ -994,7 +994,7 @@ static ssize_t adt7316_show_DA_AB_Vref_bypass(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
@@ -1009,7 +1009,7 @@ static ssize_t adt7316_store_DA_AB_Vref_bypass(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 dac_config;
int ret;
@@ -1039,7 +1039,7 @@ static ssize_t adt7316_show_DA_CD_Vref_bypass(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
@@ -1054,7 +1054,7 @@ static ssize_t adt7316_store_DA_CD_Vref_bypass(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 dac_config;
int ret;
@@ -1084,7 +1084,7 @@ static ssize_t adt7316_show_DAC_internal_Vref(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
@@ -1101,7 +1101,7 @@ static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 ldac_config;
unsigned long data;
@@ -1220,7 +1220,7 @@ static ssize_t adt7316_show_VDD(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_VDD, buf);
@@ -1231,7 +1231,7 @@ static ssize_t adt7316_show_in_temp(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_IN, buf);
@@ -1243,7 +1243,7 @@ static ssize_t adt7316_show_ex_temp_AIN1(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_EX, buf);
@@ -1256,7 +1256,7 @@ static ssize_t adt7316_show_AIN2(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN2, buf);
@@ -1267,7 +1267,7 @@ static ssize_t adt7316_show_AIN3(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN3, buf);
@@ -1278,7 +1278,7 @@ static ssize_t adt7316_show_AIN4(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN4, buf);
@@ -1330,7 +1330,7 @@ static ssize_t adt7316_show_in_temp_offset(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_temp_offset(chip, ADT7316_IN_TEMP_OFFSET, buf);
@@ -1341,7 +1341,7 @@ static ssize_t adt7316_store_in_temp_offset(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_temp_offset(chip, ADT7316_IN_TEMP_OFFSET, buf, len);
@@ -1355,7 +1355,7 @@ static ssize_t adt7316_show_ex_temp_offset(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_temp_offset(chip, ADT7316_EX_TEMP_OFFSET, buf);
@@ -1366,7 +1366,7 @@ static ssize_t adt7316_store_ex_temp_offset(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_temp_offset(chip, ADT7316_EX_TEMP_OFFSET, buf, len);
@@ -1380,7 +1380,7 @@ static ssize_t adt7316_show_in_analog_temp_offset(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_temp_offset(chip,
@@ -1392,7 +1392,7 @@ static ssize_t adt7316_store_in_analog_temp_offset(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_temp_offset(chip,
@@ -1407,7 +1407,7 @@ static ssize_t adt7316_show_ex_analog_temp_offset(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_temp_offset(chip,
@@ -1419,7 +1419,7 @@ static ssize_t adt7316_store_ex_analog_temp_offset(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_temp_offset(chip,
@@ -1504,7 +1504,7 @@ static ssize_t adt7316_show_DAC_A(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_DAC(chip, 0, buf);
@@ -1515,7 +1515,7 @@ static ssize_t adt7316_store_DAC_A(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_DAC(chip, 0, buf, len);
@@ -1528,7 +1528,7 @@ static ssize_t adt7316_show_DAC_B(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_DAC(chip, 1, buf);
@@ -1539,7 +1539,7 @@ static ssize_t adt7316_store_DAC_B(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_DAC(chip, 1, buf, len);
@@ -1552,7 +1552,7 @@ static ssize_t adt7316_show_DAC_C(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_DAC(chip, 2, buf);
@@ -1563,7 +1563,7 @@ static ssize_t adt7316_store_DAC_C(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_DAC(chip, 2, buf, len);
@@ -1576,7 +1576,7 @@ static ssize_t adt7316_show_DAC_D(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_show_DAC(chip, 3, buf);
@@ -1587,7 +1587,7 @@ static ssize_t adt7316_store_DAC_D(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return adt7316_store_DAC(chip, 3, buf, len);
@@ -1600,7 +1600,7 @@ static ssize_t adt7316_show_device_id(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 id;
int ret;
@@ -1618,7 +1618,7 @@ static ssize_t adt7316_show_manufactorer_id(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 id;
int ret;
@@ -1637,7 +1637,7 @@ static ssize_t adt7316_show_device_rev(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 rev;
int ret;
@@ -1655,7 +1655,7 @@ static ssize_t adt7316_show_bus_type(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 stat;
int ret;
@@ -1841,7 +1841,7 @@ static ssize_t adt7316_show_int_mask(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "0x%x\n", chip->int_mask);
@@ -1855,7 +1855,7 @@ static ssize_t adt7316_set_int_mask(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
unsigned long data;
int ret;
@@ -1895,7 +1895,7 @@ static inline ssize_t adt7316_show_ad_bound(struct device *dev,
char *buf)
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 val;
int data;
@@ -1926,7 +1926,7 @@ static inline ssize_t adt7316_set_ad_bound(struct device *dev,
size_t len)
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
long data;
u8 val;
@@ -1965,7 +1965,7 @@ static ssize_t adt7316_show_int_enabled(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_INT_EN));
@@ -1976,7 +1976,7 @@ static ssize_t adt7316_set_int_enabled(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *dev_info = dev_get_drvdata(dev);
+ struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config1;
int ret;
@@ -2133,7 +2133,7 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
unsigned short *adt7316_platform_data = dev->platform_data;
int ret = 0;
- indio_dev = iio_allocate_device(sizeof(*chip));
+ indio_dev = iio_device_alloc(sizeof(*chip));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -2210,7 +2210,7 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
error_unreg_irq:
free_irq(chip->bus.irq, indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -2224,7 +2224,7 @@ int __devexit adt7316_remove(struct device *dev)
iio_device_unregister(indio_dev);
if (chip->bus.irq)
free_irq(chip->bus.irq, indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c
index e4a08dc9b6f5..a16d1a22db0a 100644
--- a/drivers/staging/iio/cdc/ad7150.c
+++ b/drivers/staging/iio/cdc/ad7150.c
@@ -13,9 +13,9 @@
#include <linux/i2c.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../events.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
/*
* AD7150 registers definition
*/
@@ -104,7 +104,7 @@ static int ad7150_read_raw(struct iio_dev *indio_dev,
struct ad7150_chip_info *chip = iio_priv(indio_dev);
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
ret = i2c_smbus_read_word_data(chip->client,
ad7150_addresses[chan->channel][0]);
if (ret < 0)
@@ -341,7 +341,7 @@ static ssize_t ad7150_show_timeout(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7150_chip_info *chip = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
u8 value;
@@ -370,7 +370,7 @@ static ssize_t ad7150_store_timeout(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7150_chip_info *chip = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int chan = IIO_EVENT_CODE_EXTRACT_CHAN(this_attr->address);
@@ -429,7 +429,8 @@ static const struct iio_chan_spec ad7150_channels[] = {
.type = IIO_CAPACITANCE,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT,
.event_mask =
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) |
@@ -441,7 +442,8 @@ static const struct iio_chan_spec ad7150_channels[] = {
.type = IIO_CAPACITANCE,
.indexed = 1,
.channel = 1,
- .info_mask = IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT,
.event_mask =
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) |
@@ -556,7 +558,7 @@ static int __devinit ad7150_probe(struct i2c_client *client,
struct ad7150_chip_info *chip;
struct iio_dev *indio_dev;
- indio_dev = iio_allocate_device(sizeof(*chip));
+ indio_dev = iio_device_alloc(sizeof(*chip));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -619,7 +621,7 @@ error_free_irq:
if (client->irq)
free_irq(client->irq, indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -635,7 +637,7 @@ static int __devexit ad7150_remove(struct i2c_client *client)
if (client->dev.platform_data)
free_irq(*(unsigned int *)client->dev.platform_data, indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c
index fdb83c35e6dd..98c3015116aa 100644
--- a/drivers/staging/iio/cdc/ad7152.c
+++ b/drivers/staging/iio/cdc/ad7152.c
@@ -15,8 +15,8 @@
#include <linux/module.h>
#include <linux/delay.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
/*
* TODO: Check compliance of calibbias with abi (units)
@@ -97,7 +97,7 @@ static inline ssize_t ad7152_start_calib(struct device *dev,
size_t len,
u8 regval)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7152_chip_info *chip = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
bool doit;
@@ -169,7 +169,7 @@ static ssize_t ad7152_show_filter_rate_setup(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7152_chip_info *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n",
@@ -181,7 +181,7 @@ static ssize_t ad7152_store_filter_rate_setup(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7152_chip_info *chip = iio_priv(indio_dev);
u8 data;
int ret, i;
@@ -329,7 +329,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock);
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
/* First set whether in differential mode */
regval = chip->setup[chan->channel];
@@ -436,7 +436,8 @@ static const struct iio_chan_spec ad7152_channels[] = {
.type = IIO_CAPACITANCE,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
}, {
@@ -445,14 +446,16 @@ static const struct iio_chan_spec ad7152_channels[] = {
.indexed = 1,
.channel = 0,
.channel2 = 2,
- .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
}, {
.type = IIO_CAPACITANCE,
.indexed = 1,
.channel = 1,
- .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
}, {
@@ -461,7 +464,8 @@ static const struct iio_chan_spec ad7152_channels[] = {
.indexed = 1,
.channel = 1,
.channel2 = 3,
- .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
}
@@ -477,7 +481,7 @@ static int __devinit ad7152_probe(struct i2c_client *client,
struct ad7152_chip_info *chip;
struct iio_dev *indio_dev;
- indio_dev = iio_allocate_device(sizeof(*chip));
+ indio_dev = iio_device_alloc(sizeof(*chip));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -509,7 +513,7 @@ static int __devinit ad7152_probe(struct i2c_client *client,
return 0;
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -519,7 +523,7 @@ static int __devexit ad7152_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c
index 40b8512cbc32..754e11e87193 100644
--- a/drivers/staging/iio/cdc/ad7746.c
+++ b/drivers/staging/iio/cdc/ad7746.c
@@ -16,8 +16,8 @@
#include <linux/module.h>
#include <linux/stat.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "ad7746.h"
@@ -123,7 +123,8 @@ static const struct iio_chan_spec ad7746_channels[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = AD7746_REG_VT_DATA_HIGH << 8 |
AD7746_VTSETUP_VTMD_EXT_VIN,
},
@@ -132,7 +133,8 @@ static const struct iio_chan_spec ad7746_channels[] = {
.indexed = 1,
.channel = 1,
.extend_name = "supply",
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = AD7746_REG_VT_DATA_HIGH << 8 |
AD7746_VTSETUP_VTMD_VDD_MON,
},
@@ -140,7 +142,7 @@ static const struct iio_chan_spec ad7746_channels[] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .processed_val = IIO_PROCESSED,
+ .info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT,
.address = AD7746_REG_VT_DATA_HIGH << 8 |
AD7746_VTSETUP_VTMD_INT_TEMP,
},
@@ -148,7 +150,7 @@ static const struct iio_chan_spec ad7746_channels[] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 1,
- .processed_val = IIO_PROCESSED,
+ .info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT,
.address = AD7746_REG_VT_DATA_HIGH << 8 |
AD7746_VTSETUP_VTMD_EXT_TEMP,
},
@@ -156,7 +158,8 @@ static const struct iio_chan_spec ad7746_channels[] = {
.type = IIO_CAPACITANCE,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
@@ -168,7 +171,8 @@ static const struct iio_chan_spec ad7746_channels[] = {
.indexed = 1,
.channel = 0,
.channel2 = 2,
- .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
@@ -179,7 +183,8 @@ static const struct iio_chan_spec ad7746_channels[] = {
.type = IIO_CAPACITANCE,
.indexed = 1,
.channel = 1,
- .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
@@ -192,7 +197,8 @@ static const struct iio_chan_spec ad7746_channels[] = {
.indexed = 1,
.channel = 1,
.channel2 = 3,
- .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
@@ -280,7 +286,7 @@ static inline ssize_t ad7746_start_calib(struct device *dev,
size_t len,
u8 regval)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7746_chip_info *chip = iio_priv(indio_dev);
bool doit;
int ret, timeout = 10;
@@ -319,7 +325,7 @@ static ssize_t ad7746_start_offset_calib(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
int ret = ad7746_select_channel(indio_dev,
&ad7746_channels[to_iio_dev_attr(attr)->address]);
if (ret < 0)
@@ -334,7 +340,7 @@ static ssize_t ad7746_start_gain_calib(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
int ret = ad7746_select_channel(indio_dev,
&ad7746_channels[to_iio_dev_attr(attr)->address]);
if (ret < 0)
@@ -359,7 +365,7 @@ static ssize_t ad7746_show_cap_filter_rate_setup(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7746_chip_info *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", ad7746_cap_filter_rate_table[
@@ -371,7 +377,7 @@ static ssize_t ad7746_store_cap_filter_rate_setup(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7746_chip_info *chip = iio_priv(indio_dev);
u8 data;
int ret, i;
@@ -399,7 +405,7 @@ static ssize_t ad7746_show_vt_filter_rate_setup(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7746_chip_info *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", ad7746_vt_filter_rate_table[
@@ -411,7 +417,7 @@ static ssize_t ad7746_store_vt_filter_rate_setup(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7746_chip_info *chip = iio_priv(indio_dev);
u8 data;
int ret, i;
@@ -572,7 +578,8 @@ static int ad7746_read_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock);
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_PROCESSED:
ret = ad7746_select_channel(indio_dev, chan);
if (ret < 0)
goto out;
@@ -696,7 +703,7 @@ static int __devinit ad7746_probe(struct i2c_client *client,
int ret = 0;
unsigned char regval = 0;
- indio_dev = iio_allocate_device(sizeof(*chip));
+ indio_dev = iio_device_alloc(sizeof(*chip));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -756,7 +763,7 @@ static int __devinit ad7746_probe(struct i2c_client *client,
return 0;
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -766,7 +773,7 @@ static int __devexit ad7746_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig
index a57803a5d1a7..a626f03871ec 100644
--- a/drivers/staging/iio/dac/Kconfig
+++ b/drivers/staging/iio/dac/Kconfig
@@ -56,12 +56,12 @@ config AD5624R_SPI
AD5664R converters (DAC). This driver uses the common SPI interface.
config AD5446
- tristate "Analog Devices AD5444/6, AD5620/40/60 and AD5542A/12A DAC SPI driver"
+ tristate "Analog Devices AD5446 and similar single channel DACs driver"
depends on SPI
help
Say yes here to build support for Analog Devices AD5444, AD5446,
- AD5512A, AD5542A, AD5543, AD5553, AD5601, AD5611, AD5620, AD5621,
- AD5640, AD5660, AD5662 DACs.
+ AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601, AD5611, AD5620,
+ AD5621, AD5640, AD5660, AD5662 DACs.
To compile this driver as a module, choose M here: the
module will be called ad5446.
diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c
index 06b162745a3e..047148aa66b2 100644
--- a/drivers/staging/iio/dac/ad5064.c
+++ b/drivers/staging/iio/dac/ad5064.c
@@ -16,8 +16,8 @@
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "dac.h"
#define AD5064_MAX_DAC_CHANNELS 8
@@ -144,14 +144,14 @@ static const char ad5064_powerdown_modes[][15] = {
};
static ssize_t ad5064_read_powerdown_mode_available(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan, char *buf)
+ uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
return sprintf(buf, "%s %s %s\n", ad5064_powerdown_modes[1],
ad5064_powerdown_modes[2], ad5064_powerdown_modes[3]);
}
static ssize_t ad5064_read_powerdown_mode(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan, char *buf)
+ uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
struct ad5064_state *st = iio_priv(indio_dev);
@@ -160,7 +160,8 @@ static ssize_t ad5064_read_powerdown_mode(struct iio_dev *indio_dev,
}
static ssize_t ad5064_write_powerdown_mode(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan, const char *buf, size_t len)
+ uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
+ size_t len)
{
struct ad5064_state *st = iio_priv(indio_dev);
unsigned int mode, i;
@@ -187,7 +188,7 @@ static ssize_t ad5064_write_powerdown_mode(struct iio_dev *indio_dev,
}
static ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan, char *buf)
+ uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
struct ad5064_state *st = iio_priv(indio_dev);
@@ -195,7 +196,8 @@ static ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev,
}
static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan, const char *buf, size_t len)
+ uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
+ size_t len)
{
struct ad5064_state *st = iio_priv(indio_dev);
bool pwr_down;
@@ -235,7 +237,7 @@ static int ad5064_read_raw(struct iio_dev *indio_dev,
int scale_uv;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
*val = st->dac_cache[chan->channel];
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
@@ -260,7 +262,7 @@ static int ad5064_write_raw(struct iio_dev *indio_dev,
int ret;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
if (val > (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
@@ -308,7 +310,8 @@ static struct iio_chan_spec_ext_info ad5064_ext_info[] = {
.indexed = 1, \
.output = 1, \
.channel = (chan), \
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
.address = AD5064_ADDR_DAC(chan), \
.scan_type = IIO_ST('u', (bits), 16, 20 - (bits)), \
.ext_info = ad5064_ext_info, \
@@ -442,7 +445,7 @@ static int __devinit ad5064_probe(struct spi_device *spi)
unsigned int i;
int ret;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -499,7 +502,7 @@ error_free_reg:
if (!st->use_internal_vref)
regulator_bulk_free(ad5064_num_vref(st), st->vref_reg);
error_free:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
@@ -517,7 +520,7 @@ static int __devexit ad5064_remove(struct spi_device *spi)
regulator_bulk_free(ad5064_num_vref(st), st->vref_reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/ad5360.c b/drivers/staging/iio/dac/ad5360.c
index cec3693b50a3..38660efca78a 100644
--- a/drivers/staging/iio/dac/ad5360.c
+++ b/drivers/staging/iio/dac/ad5360.c
@@ -16,8 +16,8 @@
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "dac.h"
#define AD5360_CMD(x) ((x) << 22)
@@ -103,7 +103,8 @@ enum ad5360_type {
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \
IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \
@@ -250,7 +251,7 @@ static ssize_t ad5360_read_dac_powerdown(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5360_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", (bool)(st->ctrl & AD5360_SF_CTRL_PWR_DOWN));
@@ -278,7 +279,7 @@ static int ad5360_update_ctrl(struct iio_dev *indio_dev, unsigned int set,
static ssize_t ad5360_write_dac_powerdown(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
bool pwr_down;
int ret;
@@ -319,7 +320,7 @@ static int ad5360_write_raw(struct iio_dev *indio_dev,
unsigned int ofs_index;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
if (val >= max_val || val < 0)
return -EINVAL;
@@ -376,7 +377,7 @@ static int ad5360_read_raw(struct iio_dev *indio_dev,
int ret;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
ret = ad5360_read(indio_dev, AD5360_READBACK_X1A,
chan->address);
if (ret < 0)
@@ -464,7 +465,7 @@ static int __devinit ad5360_probe(struct spi_device *spi)
unsigned int i;
int ret;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
dev_err(&spi->dev, "Failed to allocate iio device\n");
return -ENOMEM;
@@ -519,7 +520,7 @@ error_free_reg:
error_free_channels:
kfree(indio_dev->channels);
error_free:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
@@ -536,7 +537,7 @@ static int __devexit ad5360_remove(struct spi_device *spi)
regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg);
regulator_bulk_free(st->chip_info->num_vrefs, st->vref_reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/ad5380.c b/drivers/staging/iio/dac/ad5380.c
index 4c50716fa801..370d2842190e 100644
--- a/drivers/staging/iio/dac/ad5380.c
+++ b/drivers/staging/iio/dac/ad5380.c
@@ -18,8 +18,8 @@
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "dac.h"
@@ -85,7 +85,8 @@ enum ad5380_type {
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT | \
IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \
.scan_type = IIO_ST('u', (_bits), 16, 14 - (_bits)) \
@@ -167,7 +168,7 @@ static const struct ad5380_chip_info ad5380_chip_info_tbl[] = {
static ssize_t ad5380_read_dac_powerdown(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5380_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", st->pwr_down);
@@ -176,7 +177,7 @@ static ssize_t ad5380_read_dac_powerdown(struct device *dev,
static ssize_t ad5380_write_dac_powerdown(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5380_state *st = iio_priv(indio_dev);
bool pwr_down;
int ret;
@@ -212,7 +213,7 @@ static const char ad5380_powerdown_modes[][15] = {
static ssize_t ad5380_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5380_state *st = iio_priv(indio_dev);
unsigned int mode;
int ret;
@@ -229,7 +230,7 @@ static ssize_t ad5380_read_powerdown_mode(struct device *dev,
static ssize_t ad5380_write_powerdown_mode(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5380_state *st = iio_priv(indio_dev);
unsigned int i;
int ret;
@@ -292,7 +293,7 @@ static int ad5380_write_raw(struct iio_dev *indio_dev,
struct ad5380_state *st = iio_priv(indio_dev);
switch (info) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
case IIO_CHAN_INFO_CALIBSCALE:
if (val >= max_val || val < 0)
return -EINVAL;
@@ -322,7 +323,7 @@ static int ad5380_read_raw(struct iio_dev *indio_dev,
int ret;
switch (info) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
case IIO_CHAN_INFO_CALIBSCALE:
ret = regmap_read(st->regmap, ad5380_info_to_reg(chan, info),
val);
@@ -388,7 +389,7 @@ static int __devinit ad5380_probe(struct device *dev, struct regmap *regmap,
unsigned int ctrl = 0;
int ret;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
dev_err(dev, "Failed to allocate iio device\n");
ret = -ENOMEM;
@@ -454,7 +455,7 @@ error_free_reg:
kfree(indio_dev->channels);
error_free:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_regmap_exit:
regmap_exit(regmap);
@@ -476,7 +477,7 @@ static int __devexit ad5380_remove(struct device *dev)
}
regmap_exit(st->regmap);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/ad5421.c b/drivers/staging/iio/dac/ad5421.c
index 0b040b204697..ffbd4c234f57 100644
--- a/drivers/staging/iio/dac/ad5421.c
+++ b/drivers/staging/iio/dac/ad5421.c
@@ -16,9 +16,9 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../events.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
#include "dac.h"
#include "ad5421.h"
@@ -87,7 +87,8 @@ static const struct iio_chan_spec ad5421_channels[] = {
.indexed = 1,
.output = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_OFFSET_SHARED_BIT |
IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
@@ -304,7 +305,7 @@ static int ad5421_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA);
if (ret < 0)
return ret;
@@ -340,7 +341,7 @@ static int ad5421_write_raw(struct iio_dev *indio_dev,
const unsigned int max_val = 1 << 16;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
if (val >= max_val || val < 0)
return -EINVAL;
@@ -456,7 +457,7 @@ static int __devinit ad5421_probe(struct spi_device *spi)
struct ad5421_state *st;
int ret;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
dev_err(&spi->dev, "Failed to allocate iio device\n");
return -ENOMEM;
@@ -511,7 +512,7 @@ error_free_irq:
if (spi->irq)
free_irq(spi->irq, indio_dev);
error_free:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
@@ -523,7 +524,7 @@ static int __devexit ad5421_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
if (spi->irq)
free_irq(spi->irq, indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c
index 633ffbb21814..daa65b384c13 100644
--- a/drivers/staging/iio/dac/ad5446.c
+++ b/drivers/staging/iio/dac/ad5446.c
@@ -18,229 +18,212 @@
#include <linux/err.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "dac.h"
#include "ad5446.h"
-static void ad5446_store_sample(struct ad5446_state *st, unsigned val)
+static int ad5446_write(struct ad5446_state *st, unsigned val)
{
- st->data.d16 = cpu_to_be16(AD5446_LOAD | val);
+ __be16 data = cpu_to_be16(val);
+ return spi_write(st->spi, &data, sizeof(data));
}
-static void ad5542_store_sample(struct ad5446_state *st, unsigned val)
+static int ad5660_write(struct ad5446_state *st, unsigned val)
{
- st->data.d16 = cpu_to_be16(val);
-}
+ uint8_t data[3];
-static void ad5620_store_sample(struct ad5446_state *st, unsigned val)
-{
- st->data.d16 = cpu_to_be16(AD5620_LOAD | val);
-}
+ data[0] = (val >> 16) & 0xFF;
+ data[1] = (val >> 8) & 0xFF;
+ data[2] = val & 0xFF;
-static void ad5660_store_sample(struct ad5446_state *st, unsigned val)
-{
- val |= AD5660_LOAD;
- st->data.d24[0] = (val >> 16) & 0xFF;
- st->data.d24[1] = (val >> 8) & 0xFF;
- st->data.d24[2] = val & 0xFF;
+ return spi_write(st->spi, data, sizeof(data));
}
-static void ad5620_store_pwr_down(struct ad5446_state *st, unsigned mode)
-{
- st->data.d16 = cpu_to_be16(mode << 14);
-}
+static const char * const ad5446_powerdown_modes[] = {
+ "", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"
+};
-static void ad5660_store_pwr_down(struct ad5446_state *st, unsigned mode)
+static ssize_t ad5446_read_powerdown_mode_available(struct iio_dev *indio_dev,
+ uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
- unsigned val = mode << 16;
-
- st->data.d24[0] = (val >> 16) & 0xFF;
- st->data.d24[1] = (val >> 8) & 0xFF;
- st->data.d24[2] = val & 0xFF;
+ return sprintf(buf, "%s %s %s\n", ad5446_powerdown_modes[1],
+ ad5446_powerdown_modes[2], ad5446_powerdown_modes[3]);
}
-static ssize_t ad5446_write_powerdown_mode(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
+static ssize_t ad5446_write_powerdown_mode(struct iio_dev *indio_dev,
+ uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ad5446_state *st = iio_priv(indio_dev);
+ int i;
- if (sysfs_streq(buf, "1kohm_to_gnd"))
- st->pwr_down_mode = MODE_PWRDWN_1k;
- else if (sysfs_streq(buf, "100kohm_to_gnd"))
- st->pwr_down_mode = MODE_PWRDWN_100k;
- else if (sysfs_streq(buf, "three_state"))
- st->pwr_down_mode = MODE_PWRDWN_TRISTATE;
- else
+ for (i = 1; i < ARRAY_SIZE(ad5446_powerdown_modes); i++) {
+ if (sysfs_streq(buf, ad5446_powerdown_modes[i])) {
+ st->pwr_down_mode = i;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(ad5446_powerdown_modes))
return -EINVAL;
return len;
}
-static ssize_t ad5446_read_powerdown_mode(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t ad5446_read_powerdown_mode(struct iio_dev *indio_dev,
+ uintptr_t private,
+ const struct iio_chan_spec *chan,
+ char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ad5446_state *st = iio_priv(indio_dev);
- char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
-
- return sprintf(buf, "%s\n", mode[st->pwr_down_mode]);
+ return sprintf(buf, "%s\n", ad5446_powerdown_modes[st->pwr_down_mode]);
}
-static ssize_t ad5446_read_dac_powerdown(struct device *dev,
- struct device_attribute *attr,
+static ssize_t ad5446_read_dac_powerdown(struct iio_dev *indio_dev,
+ uintptr_t private,
+ const struct iio_chan_spec *chan,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ad5446_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", st->pwr_down);
}
-static ssize_t ad5446_write_dac_powerdown(struct device *dev,
- struct device_attribute *attr,
+static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev,
+ uintptr_t private,
+ const struct iio_chan_spec *chan,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ad5446_state *st = iio_priv(indio_dev);
- unsigned long readin;
+ unsigned int shift;
+ unsigned int val;
+ bool powerdown;
int ret;
- ret = strict_strtol(buf, 10, &readin);
+ ret = strtobool(buf, &powerdown);
if (ret)
return ret;
- if (readin > 1)
- ret = -EINVAL;
-
mutex_lock(&indio_dev->mlock);
- st->pwr_down = readin;
+ st->pwr_down = powerdown;
- if (st->pwr_down)
- st->chip_info->store_pwr_down(st, st->pwr_down_mode);
- else
- st->chip_info->store_sample(st, st->cached_val);
+ if (st->pwr_down) {
+ shift = chan->scan_type.realbits + chan->scan_type.shift;
+ val = st->pwr_down_mode << shift;
+ } else {
+ val = st->cached_val;
+ }
- ret = spi_sync(st->spi, &st->msg);
+ ret = st->chip_info->write(st, val);
mutex_unlock(&indio_dev->mlock);
return ret ? ret : len;
}
-static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO | S_IWUSR,
- ad5446_read_powerdown_mode,
- ad5446_write_powerdown_mode, 0);
-
-static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
- "1kohm_to_gnd 100kohm_to_gnd three_state");
-
-static IIO_DEVICE_ATTR(out_voltage0_powerdown, S_IRUGO | S_IWUSR,
- ad5446_read_dac_powerdown,
- ad5446_write_dac_powerdown, 0);
-
-static struct attribute *ad5446_attributes[] = {
- &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
- &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
- &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
- NULL,
-};
-
-static const struct attribute_group ad5446_attribute_group = {
- .attrs = ad5446_attributes,
+static const struct iio_chan_spec_ext_info ad5064_ext_info_powerdown[] = {
+ {
+ .name = "powerdown",
+ .read = ad5446_read_dac_powerdown,
+ .write = ad5446_write_dac_powerdown,
+ }, {
+ .name = "powerdown_mode",
+ .read = ad5446_read_powerdown_mode,
+ .write = ad5446_write_powerdown_mode,
+ }, {
+ .name = "powerdown_mode_available",
+ .shared = true,
+ .read = ad5446_read_powerdown_mode_available,
+ },
+ { },
};
-#define AD5446_CHANNEL(bits, storage, shift) { \
+#define _AD5446_CHANNEL(bits, storage, shift, ext) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = 0, \
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
- .scan_type = IIO_ST('u', (bits), (storage), (shift)) \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .scan_type = IIO_ST('u', (bits), (storage), (shift)), \
+ .ext_info = (ext), \
}
+#define AD5446_CHANNEL(bits, storage, shift) \
+ _AD5446_CHANNEL(bits, storage, shift, NULL)
+
+#define AD5446_CHANNEL_POWERDOWN(bits, storage, shift) \
+ _AD5446_CHANNEL(bits, storage, shift, ad5064_ext_info_powerdown)
+
static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
[ID_AD5444] = {
.channel = AD5446_CHANNEL(12, 16, 2),
- .store_sample = ad5446_store_sample,
+ .write = ad5446_write,
},
[ID_AD5446] = {
.channel = AD5446_CHANNEL(14, 16, 0),
- .store_sample = ad5446_store_sample,
+ .write = ad5446_write,
},
[ID_AD5541A] = {
.channel = AD5446_CHANNEL(16, 16, 0),
- .store_sample = ad5542_store_sample,
- },
- [ID_AD5542A] = {
- .channel = AD5446_CHANNEL(16, 16, 0),
- .store_sample = ad5542_store_sample,
- },
- [ID_AD5543] = {
- .channel = AD5446_CHANNEL(16, 16, 0),
- .store_sample = ad5542_store_sample,
+ .write = ad5446_write,
},
[ID_AD5512A] = {
.channel = AD5446_CHANNEL(12, 16, 4),
- .store_sample = ad5542_store_sample,
+ .write = ad5446_write,
},
[ID_AD5553] = {
.channel = AD5446_CHANNEL(14, 16, 0),
- .store_sample = ad5542_store_sample,
+ .write = ad5446_write,
},
[ID_AD5601] = {
- .channel = AD5446_CHANNEL(8, 16, 6),
- .store_sample = ad5542_store_sample,
- .store_pwr_down = ad5620_store_pwr_down,
+ .channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6),
+ .write = ad5446_write,
},
[ID_AD5611] = {
- .channel = AD5446_CHANNEL(10, 16, 4),
- .store_sample = ad5542_store_sample,
- .store_pwr_down = ad5620_store_pwr_down,
+ .channel = AD5446_CHANNEL_POWERDOWN(10, 16, 4),
+ .write = ad5446_write,
},
[ID_AD5621] = {
- .channel = AD5446_CHANNEL(12, 16, 2),
- .store_sample = ad5542_store_sample,
- .store_pwr_down = ad5620_store_pwr_down,
+ .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
+ .write = ad5446_write,
},
[ID_AD5620_2500] = {
- .channel = AD5446_CHANNEL(12, 16, 2),
+ .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
.int_vref_mv = 2500,
- .store_sample = ad5620_store_sample,
- .store_pwr_down = ad5620_store_pwr_down,
+ .write = ad5446_write,
},
[ID_AD5620_1250] = {
- .channel = AD5446_CHANNEL(12, 16, 2),
+ .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
.int_vref_mv = 1250,
- .store_sample = ad5620_store_sample,
- .store_pwr_down = ad5620_store_pwr_down,
+ .write = ad5446_write,
},
[ID_AD5640_2500] = {
- .channel = AD5446_CHANNEL(14, 16, 0),
+ .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
.int_vref_mv = 2500,
- .store_sample = ad5620_store_sample,
- .store_pwr_down = ad5620_store_pwr_down,
+ .write = ad5446_write,
},
[ID_AD5640_1250] = {
- .channel = AD5446_CHANNEL(14, 16, 0),
+ .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
.int_vref_mv = 1250,
- .store_sample = ad5620_store_sample,
- .store_pwr_down = ad5620_store_pwr_down,
+ .write = ad5446_write,
},
[ID_AD5660_2500] = {
- .channel = AD5446_CHANNEL(16, 16, 0),
+ .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
.int_vref_mv = 2500,
- .store_sample = ad5660_store_sample,
- .store_pwr_down = ad5660_store_pwr_down,
+ .write = ad5660_write,
},
[ID_AD5660_1250] = {
- .channel = AD5446_CHANNEL(16, 16, 0),
+ .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
.int_vref_mv = 1250,
- .store_sample = ad5660_store_sample,
- .store_pwr_down = ad5660_store_pwr_down,
+ .write = ad5660_write,
+ },
+ [ID_AD5662] = {
+ .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
+ .write = ad5660_write,
},
};
@@ -254,6 +237,9 @@ static int ad5446_read_raw(struct iio_dev *indio_dev,
unsigned long scale_uv;
switch (m) {
+ case IIO_CHAN_INFO_RAW:
+ *val = st->cached_val;
+ return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
*val = scale_uv / 1000;
@@ -271,18 +257,18 @@ static int ad5446_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct ad5446_state *st = iio_priv(indio_dev);
- int ret;
+ int ret = 0;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
if (val >= (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
val <<= chan->scan_type.shift;
mutex_lock(&indio_dev->mlock);
st->cached_val = val;
- st->chip_info->store_sample(st, val);
- ret = spi_sync(st->spi, &st->msg);
+ if (!st->pwr_down)
+ ret = st->chip_info->write(st, val);
mutex_unlock(&indio_dev->mlock);
break;
default:
@@ -295,13 +281,6 @@ static int ad5446_write_raw(struct iio_dev *indio_dev,
static const struct iio_info ad5446_info = {
.read_raw = ad5446_read_raw,
.write_raw = ad5446_write_raw,
- .attrs = &ad5446_attribute_group,
- .driver_module = THIS_MODULE,
-};
-
-static const struct iio_info ad5446_info_no_pwr_down = {
- .read_raw = ad5446_read_raw,
- .write_raw = ad5446_write_raw,
.driver_module = THIS_MODULE,
};
@@ -321,7 +300,7 @@ static int __devinit ad5446_probe(struct spi_device *spi)
voltage_uv = regulator_get_voltage(reg);
}
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
@@ -337,38 +316,17 @@ static int __devinit ad5446_probe(struct spi_device *spi)
/* Establish that the iio_dev is a child of the spi device */
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
- if (st->chip_info->store_pwr_down)
- indio_dev->info = &ad5446_info;
- else
- indio_dev->info = &ad5446_info_no_pwr_down;
+ indio_dev->info = &ad5446_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = &st->chip_info->channel;
indio_dev->num_channels = 1;
- /* Setup default message */
-
- st->xfer.tx_buf = &st->data;
- st->xfer.len = st->chip_info->channel.scan_type.storagebits / 8;
-
- spi_message_init(&st->msg);
- spi_message_add_tail(&st->xfer, &st->msg);
-
- switch (spi_get_device_id(spi)->driver_data) {
- case ID_AD5620_2500:
- case ID_AD5620_1250:
- case ID_AD5640_2500:
- case ID_AD5640_1250:
- case ID_AD5660_2500:
- case ID_AD5660_1250:
+ if (st->chip_info->int_vref_mv)
st->vref_mv = st->chip_info->int_vref_mv;
- break;
- default:
- if (voltage_uv)
- st->vref_mv = voltage_uv / 1000;
- else
- dev_warn(&spi->dev,
- "reference voltage unspecified\n");
- }
+ else if (voltage_uv)
+ st->vref_mv = voltage_uv / 1000;
+ else
+ dev_warn(&spi->dev, "reference voltage unspecified\n");
ret = iio_device_register(indio_dev);
if (ret)
@@ -377,7 +335,7 @@ static int __devinit ad5446_probe(struct spi_device *spi)
return 0;
error_free_device:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_disable_reg:
if (!IS_ERR(reg))
regulator_disable(reg);
@@ -398,7 +356,7 @@ static int ad5446_remove(struct spi_device *spi)
regulator_disable(st->reg);
regulator_put(st->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
@@ -408,8 +366,8 @@ static const struct spi_device_id ad5446_id[] = {
{"ad5446", ID_AD5446},
{"ad5512a", ID_AD5512A},
{"ad5541a", ID_AD5541A},
- {"ad5542a", ID_AD5542A},
- {"ad5543", ID_AD5543},
+ {"ad5542a", ID_AD5541A}, /* ad5541a and ad5542a are compatible */
+ {"ad5543", ID_AD5541A}, /* ad5541a and ad5543 are compatible */
{"ad5553", ID_AD5553},
{"ad5601", ID_AD5601},
{"ad5611", ID_AD5611},
@@ -420,6 +378,7 @@ static const struct spi_device_id ad5446_id[] = {
{"ad5640-1250", ID_AD5640_1250},
{"ad5660-2500", ID_AD5660_2500},
{"ad5660-1250", ID_AD5660_1250},
+ {"ad5662", ID_AD5662},
{}
};
MODULE_DEVICE_TABLE(spi, ad5446_id);
diff --git a/drivers/staging/iio/dac/ad5446.h b/drivers/staging/iio/dac/ad5446.h
index 4ea3476fb065..dfd68ce7427e 100644
--- a/drivers/staging/iio/dac/ad5446.h
+++ b/drivers/staging/iio/dac/ad5446.h
@@ -34,43 +34,30 @@
* @spi: spi_device
* @chip_info: chip model specific constants, available modes etc
* @reg: supply regulator
- * @poll_work: bottom half of polling interrupt handler
* @vref_mv: actual reference voltage used
- * @xfer: default spi transfer
- * @msg: default spi message
- * @data: spi transmit buffer
*/
struct ad5446_state {
struct spi_device *spi;
const struct ad5446_chip_info *chip_info;
struct regulator *reg;
- struct work_struct poll_work;
unsigned short vref_mv;
unsigned cached_val;
unsigned pwr_down_mode;
unsigned pwr_down;
- struct spi_transfer xfer;
- struct spi_message msg;
- union {
- unsigned short d16;
- unsigned char d24[3];
- } data;
};
/**
* struct ad5446_chip_info - chip specific information
* @channel: channel spec for the DAC
* @int_vref_mv: AD5620/40/60: the internal reference voltage
- * @store_sample: chip specific helper function to store the datum
- * @store_sample: chip specific helper function to store the powerpown cmd
+ * @write: chip specific helper function to write to the register
*/
struct ad5446_chip_info {
struct iio_chan_spec channel;
u16 int_vref_mv;
- void (*store_sample) (struct ad5446_state *st, unsigned val);
- void (*store_pwr_down) (struct ad5446_state *st, unsigned mode);
+ int (*write)(struct ad5446_state *st, unsigned val);
};
/**
@@ -85,8 +72,6 @@ enum ad5446_supported_device_ids {
ID_AD5444,
ID_AD5446,
ID_AD5541A,
- ID_AD5542A,
- ID_AD5543,
ID_AD5512A,
ID_AD5553,
ID_AD5601,
@@ -98,6 +83,7 @@ enum ad5446_supported_device_ids {
ID_AD5640_1250,
ID_AD5660_2500,
ID_AD5660_1250,
+ ID_AD5662,
};
#endif /* IIO_DAC_AD5446_H_ */
diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c
index bc17205fe722..019cf15cd24a 100644
--- a/drivers/staging/iio/dac/ad5504.c
+++ b/drivers/staging/iio/dac/ad5504.c
@@ -16,9 +16,9 @@
#include <linux/regulator/consumer.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../events.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
#include "dac.h"
#include "ad5504.h"
@@ -27,7 +27,8 @@
.indexed = 1, \
.output = 1, \
.channel = (_chan), \
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = AD5504_ADDR_DAC(_chan), \
.scan_type = IIO_ST('u', 12, 16, 0), \
}
@@ -81,7 +82,7 @@ static int ad5504_read_raw(struct iio_dev *indio_dev,
int ret;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
ret = ad5504_spi_read(st->spi, chan->address);
if (ret < 0)
return ret;
@@ -109,7 +110,7 @@ static int ad5504_write_raw(struct iio_dev *indio_dev,
int ret;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
if (val >= (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
@@ -124,7 +125,7 @@ static int ad5504_write_raw(struct iio_dev *indio_dev,
static ssize_t ad5504_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5504_state *st = iio_priv(indio_dev);
const char mode[][14] = {"20kohm_to_gnd", "three_state"};
@@ -136,7 +137,7 @@ static ssize_t ad5504_write_powerdown_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5504_state *st = iio_priv(indio_dev);
int ret;
@@ -154,7 +155,7 @@ static ssize_t ad5504_read_dac_powerdown(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5504_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -168,7 +169,7 @@ static ssize_t ad5504_write_dac_powerdown(struct device *dev,
{
long readin;
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5504_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -287,7 +288,7 @@ static int __devinit ad5504_probe(struct spi_device *spi)
struct regulator *reg;
int ret, voltage_uv = 0;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -350,7 +351,7 @@ error_put_reg:
if (!IS_ERR(reg))
regulator_put(reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -368,7 +369,7 @@ static int __devexit ad5504_remove(struct spi_device *spi)
regulator_disable(st->reg);
regulator_put(st->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c
index 10c7484366ef..42ff644ac43e 100644
--- a/drivers/staging/iio/dac/ad5624r_spi.c
+++ b/drivers/staging/iio/dac/ad5624r_spi.c
@@ -16,8 +16,8 @@
#include <linux/regulator/consumer.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "dac.h"
#include "ad5624r.h"
@@ -26,7 +26,8 @@
.indexed = 1, \
.output = 1, \
.channel = (_chan), \
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = (_chan), \
.scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \
}
@@ -122,7 +123,7 @@ static int ad5624r_write_raw(struct iio_dev *indio_dev,
int ret;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
if (val >= (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
@@ -140,7 +141,7 @@ static int ad5624r_write_raw(struct iio_dev *indio_dev,
static ssize_t ad5624r_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5624r_state *st = iio_priv(indio_dev);
char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
@@ -152,7 +153,7 @@ static ssize_t ad5624r_write_powerdown_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5624r_state *st = iio_priv(indio_dev);
int ret;
@@ -172,7 +173,7 @@ static ssize_t ad5624r_read_dac_powerdown(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5624r_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -186,7 +187,7 @@ static ssize_t ad5624r_write_dac_powerdown(struct device *dev,
{
long readin;
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5624r_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -255,7 +256,7 @@ static int __devinit ad5624r_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
int ret, voltage_uv = 0;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -305,7 +306,7 @@ error_disable_reg:
error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
@@ -321,7 +322,7 @@ static int __devexit ad5624r_remove(struct spi_device *spi)
regulator_disable(st->reg);
regulator_put(st->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c
index 2415a6e60c77..c1e903ebc7b9 100644
--- a/drivers/staging/iio/dac/ad5686.c
+++ b/drivers/staging/iio/dac/ad5686.c
@@ -16,8 +16,8 @@
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "dac.h"
#define AD5686_DAC_CHANNELS 4
@@ -98,7 +98,8 @@ enum ad5686_supported_device_ids {
.indexed = 1, \
.output = 1, \
.channel = chan, \
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = AD5686_ADDR_DAC(chan), \
.scan_type = IIO_ST('u', bits, 16, shift) \
}
@@ -172,7 +173,7 @@ static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
static ssize_t ad5686_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5686_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -186,7 +187,7 @@ static ssize_t ad5686_write_powerdown_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5686_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
unsigned mode;
@@ -210,7 +211,7 @@ static ssize_t ad5686_read_dac_powerdown(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5686_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -224,7 +225,7 @@ static ssize_t ad5686_write_dac_powerdown(struct device *dev,
{
bool readin;
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5686_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -296,7 +297,7 @@ static int ad5686_read_raw(struct iio_dev *indio_dev,
int ret;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
ret = ad5686_spi_read(st, chan->address);
mutex_unlock(&indio_dev->mlock);
@@ -326,7 +327,7 @@ static int ad5686_write_raw(struct iio_dev *indio_dev,
int ret;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
if (val > (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
@@ -358,7 +359,7 @@ static int __devinit ad5686_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
int ret, regdone = 0, voltage_uv = 0;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -410,7 +411,7 @@ error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
@@ -425,7 +426,7 @@ static int __devexit ad5686_remove(struct spi_device *spi)
regulator_disable(st->reg);
regulator_put(st->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/ad5764.c b/drivers/staging/iio/dac/ad5764.c
index f73a73079490..03dbd937b081 100644
--- a/drivers/staging/iio/dac/ad5764.c
+++ b/drivers/staging/iio/dac/ad5764.c
@@ -16,8 +16,8 @@
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "dac.h"
#define AD5764_REG_SF_NOP 0x0
@@ -79,7 +79,8 @@ enum ad5764_type {
.output = 1, \
.channel = (_chan), \
.address = (_chan), \
- .info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT | \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT | \
IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \
@@ -188,7 +189,7 @@ static int ad5764_write_raw(struct iio_dev *indio_dev,
unsigned int reg;
switch (info) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
if (val >= max_val || val < 0)
return -EINVAL;
val <<= chan->scan_type.shift;
@@ -228,7 +229,7 @@ static int ad5764_read_raw(struct iio_dev *indio_dev,
int ret;
switch (info) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
reg = AD5764_REG_DATA(chan->address);
ret = ad5764_read(indio_dev, reg, val);
if (ret < 0)
@@ -280,7 +281,7 @@ static int __devinit ad5764_probe(struct spi_device *spi)
struct ad5764_state *st;
int ret;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
dev_err(&spi->dev, "Failed to allocate iio device\n");
return -ENOMEM;
@@ -335,7 +336,7 @@ error_free_reg:
if (st->chip_info->int_vref == 0)
regulator_bulk_free(ARRAY_SIZE(st->vref_reg), st->vref_reg);
error_free:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
@@ -352,7 +353,7 @@ static int __devexit ad5764_remove(struct spi_device *spi)
regulator_bulk_free(ARRAY_SIZE(st->vref_reg), st->vref_reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c
index ac45636a8d72..13d8b5bb1cea 100644
--- a/drivers/staging/iio/dac/ad5791.c
+++ b/drivers/staging/iio/dac/ad5791.c
@@ -17,8 +17,8 @@
#include <linux/regulator/consumer.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "dac.h"
#include "ad5791.h"
@@ -78,7 +78,8 @@ static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val)
.indexed = 1, \
.address = AD5791_ADDR_DAC0, \
.channel = 0, \
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT | \
IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
.scan_type = IIO_ST('u', bits, 24, shift) \
}
@@ -93,7 +94,7 @@ static const struct iio_chan_spec ad5791_channels[] = {
static ssize_t ad5791_read_powerdown_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5791_state *st = iio_priv(indio_dev);
const char mode[][14] = {"6kohm_to_gnd", "three_state"};
@@ -105,7 +106,7 @@ static ssize_t ad5791_write_powerdown_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5791_state *st = iio_priv(indio_dev);
int ret;
@@ -123,7 +124,7 @@ static ssize_t ad5791_read_dac_powerdown(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5791_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", st->pwr_down);
@@ -135,7 +136,7 @@ static ssize_t ad5791_write_dac_powerdown(struct device *dev,
{
long readin;
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5791_state *st = iio_priv(indio_dev);
ret = strict_strtol(buf, 10, &readin);
@@ -231,7 +232,7 @@ static int ad5791_read_raw(struct iio_dev *indio_dev,
int ret;
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
ret = ad5791_spi_read(st->spi, chan->address, val);
if (ret)
return ret;
@@ -263,7 +264,7 @@ static int ad5791_write_raw(struct iio_dev *indio_dev,
struct ad5791_state *st = iio_priv(indio_dev);
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
val &= AD5791_RES_MASK(chan->scan_type.realbits);
val <<= chan->scan_type.shift;
@@ -288,7 +289,7 @@ static int __devinit ad5791_probe(struct spi_device *spi)
struct ad5791_state *st;
int ret, pos_voltage_uv = 0, neg_voltage_uv = 0;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -368,7 +369,7 @@ error_put_reg_neg:
error_put_reg_pos:
if (!IS_ERR(st->reg_vdd))
regulator_put(st->reg_vdd);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
@@ -389,7 +390,7 @@ static int __devexit ad5791_remove(struct spi_device *spi)
regulator_disable(st->reg_vss);
regulator_put(st->reg_vss);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dac/max517.c b/drivers/staging/iio/dac/max517.c
index 41483c72cec1..5287cad1f3a4 100644
--- a/drivers/staging/iio/dac/max517.c
+++ b/drivers/staging/iio/dac/max517.c
@@ -25,8 +25,8 @@
#include <linux/i2c.h>
#include <linux/err.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "dac.h"
#include "max517.h"
@@ -59,7 +59,7 @@ static ssize_t max517_set_value(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count, int channel)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct max517_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
u8 outbuf[4]; /* 1x or 2x command + value */
@@ -128,7 +128,7 @@ static ssize_t max517_show_scale(struct device *dev,
struct device_attribute *attr,
char *buf, int channel)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct max517_data *data = iio_priv(indio_dev);
/* Corresponds to Vref / 2^(bits) */
unsigned int scale_uv = (data->vref_mv[channel - 1] * 1000) >> 8;
@@ -218,7 +218,7 @@ static int max517_probe(struct i2c_client *client,
struct max517_platform_data *platform_data = client->dev.platform_data;
int err;
- indio_dev = iio_allocate_device(sizeof(*data));
+ indio_dev = iio_device_alloc(sizeof(*data));
if (indio_dev == NULL) {
err = -ENOMEM;
goto exit;
@@ -257,14 +257,15 @@ static int max517_probe(struct i2c_client *client,
return 0;
exit_free_device:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
exit:
return err;
}
static int max517_remove(struct i2c_client *client)
{
- iio_free_device(i2c_get_clientdata(client));
+ iio_device_unregister(i2c_get_clientdata(client));
+ iio_device_free(i2c_get_clientdata(client));
return 0;
}
diff --git a/drivers/staging/iio/dds/dds.h b/drivers/staging/iio/dds/dds.h
deleted file mode 100644
index d8ac3a93baf6..000000000000
--- a/drivers/staging/iio/dds/dds.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * dds.h - sysfs attributes associated with DDS devices
- *
- * Copyright (c) 2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-/**
- * /sys/bus/iio/devices/.../ddsX_freqY
- */
-
-#define IIO_DEV_ATTR_FREQ(_channel, _num, _mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(dds##_channel##_freq##_num, \
- _mode, _show, _store, _addr)
-
-/**
- * /sys/bus/iio/devices/.../ddsX_freqY_scale
- */
-
-#define IIO_CONST_ATTR_FREQ_SCALE(_channel, _string) \
- IIO_CONST_ATTR(dds##_channel##_freq_scale, _string)
-
-/**
- * /sys/bus/iio/devices/.../ddsX_freqsymbol
- */
-
-#define IIO_DEV_ATTR_FREQSYMBOL(_channel, _mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(dds##_channel##_freqsymbol, \
- _mode, _show, _store, _addr);
-
-/**
- * /sys/bus/iio/devices/.../ddsX_phaseY
- */
-
-#define IIO_DEV_ATTR_PHASE(_channel, _num, _mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(dds##_channel##_phase##_num, \
- _mode, _show, _store, _addr)
-
-/**
- * /sys/bus/iio/devices/.../ddsX_phaseY_scale
- */
-
-#define IIO_CONST_ATTR_PHASE_SCALE(_channel, _string) \
- IIO_CONST_ATTR(dds##_channel##_phase_scale, _string)
-
-/**
- * /sys/bus/iio/devices/.../ddsX_phasesymbol
- */
-
-#define IIO_DEV_ATTR_PHASESYMBOL(_channel, _mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(dds##_channel##_phasesymbol, \
- _mode, _show, _store, _addr);
-
-/**
- * /sys/bus/iio/devices/.../ddsX_pincontrol_en
- */
-
-#define IIO_DEV_ATTR_PINCONTROL_EN(_channel, _mode, _show, _store, _addr)\
- IIO_DEVICE_ATTR(dds##_channel##_pincontrol_en, \
- _mode, _show, _store, _addr);
-
-/**
- * /sys/bus/iio/devices/.../ddsX_pincontrol_freq_en
- */
-
-#define IIO_DEV_ATTR_PINCONTROL_FREQ_EN(_channel, _mode, _show, _store, _addr)\
- IIO_DEVICE_ATTR(dds##_channel##_pincontrol_freq_en, \
- _mode, _show, _store, _addr);
-
-/**
- * /sys/bus/iio/devices/.../ddsX_pincontrol_phase_en
- */
-
-#define IIO_DEV_ATTR_PINCONTROL_PHASE_EN(_channel, _mode, _show, _store, _addr)\
- IIO_DEVICE_ATTR(dds##_channel##_pincontrol_phase_en, \
- _mode, _show, _store, _addr);
-
-/**
- * /sys/bus/iio/devices/.../ddsX_out_enable
- */
-
-#define IIO_DEV_ATTR_OUT_ENABLE(_channel, _mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(dds##_channel##_out_enable, \
- _mode, _show, _store, _addr);
-
-/**
- * /sys/bus/iio/devices/.../ddsX_outY_enable
- */
-
-#define IIO_DEV_ATTR_OUTY_ENABLE(_channel, _output, \
- _mode, _show, _store, _addr) \
- IIO_DEVICE_ATTR(dds##_channel##_out##_output##_enable, \
- _mode, _show, _store, _addr);
-
-/**
- * /sys/bus/iio/devices/.../ddsX_outY_wavetype
- */
-
-#define IIO_DEV_ATTR_OUT_WAVETYPE(_channel, _output, _store, _addr) \
- IIO_DEVICE_ATTR(dds##_channel##_out##_output##_wavetype, \
- S_IWUSR, NULL, _store, _addr);
-
-/**
- * /sys/bus/iio/devices/.../ddsX_outY_wavetype_available
- */
-
-#define IIO_CONST_ATTR_OUT_WAVETYPES_AVAILABLE(_channel, _output, _modes)\
- IIO_CONST_ATTR(dds##_channel##_out##_output##_wavetype_available,\
- _modes);
diff --git a/drivers/staging/iio/dds/Kconfig b/drivers/staging/iio/frequency/Kconfig
index 93b7141b2c1f..93b7141b2c1f 100644
--- a/drivers/staging/iio/dds/Kconfig
+++ b/drivers/staging/iio/frequency/Kconfig
diff --git a/drivers/staging/iio/dds/Makefile b/drivers/staging/iio/frequency/Makefile
index 147746176b9b..147746176b9b 100644
--- a/drivers/staging/iio/dds/Makefile
+++ b/drivers/staging/iio/frequency/Makefile
diff --git a/drivers/staging/iio/dds/ad5930.c b/drivers/staging/iio/frequency/ad5930.c
index 9c32d1beae25..2d541d0eebef 100644
--- a/drivers/staging/iio/dds/ad5930.c
+++ b/drivers/staging/iio/frequency/ad5930.c
@@ -16,8 +16,8 @@
#include <linux/sysfs.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#define DRV_NAME "ad5930"
@@ -48,7 +48,7 @@ static ssize_t ad5930_set_parameter(struct device *dev,
struct spi_transfer xfer;
int ret;
struct ad5903_config *config = (struct ad5903_config *)buf;
- struct iio_dev *idev = dev_get_drvdata(dev);
+ struct iio_dev *idev = dev_to_iio_dev(dev);
struct ad5930_state *st = iio_priv(idev);
config->control = (config->control & ~value_mask);
@@ -97,7 +97,7 @@ static int __devinit ad5930_probe(struct spi_device *spi)
struct iio_dev *idev;
int ret = 0;
- idev = iio_allocate_device(sizeof(*st));
+ idev = iio_device_alloc(sizeof(*st));
if (idev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -122,7 +122,7 @@ static int __devinit ad5930_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(idev);
+ iio_device_free(idev);
error_ret:
return ret;
}
@@ -130,7 +130,7 @@ error_ret:
static int __devexit ad5930_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_free_device(spi_get_drvdata(spi));
+ iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/frequency/ad9832.c
index 2ccf25dd9289..fed39404e34a 100644
--- a/drivers/staging/iio/dds/ad9832.c
+++ b/drivers/staging/iio/frequency/ad9832.c
@@ -16,8 +16,8 @@
#include <linux/module.h>
#include <asm/div64.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "dds.h"
#include "ad9832.h"
@@ -77,7 +77,7 @@ static ssize_t ad9832_write(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad9832_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
@@ -177,18 +177,18 @@ static IIO_DEV_ATTR_OUT_ENABLE(0, S_IWUSR, NULL,
ad9832_write, AD9832_OUTPUT_EN);
static struct attribute *ad9832_attributes[] = {
- &iio_dev_attr_dds0_freq0.dev_attr.attr,
- &iio_dev_attr_dds0_freq1.dev_attr.attr,
- &iio_const_attr_dds0_freq_scale.dev_attr.attr,
- &iio_dev_attr_dds0_phase0.dev_attr.attr,
- &iio_dev_attr_dds0_phase1.dev_attr.attr,
- &iio_dev_attr_dds0_phase2.dev_attr.attr,
- &iio_dev_attr_dds0_phase3.dev_attr.attr,
- &iio_const_attr_dds0_phase_scale.dev_attr.attr,
- &iio_dev_attr_dds0_pincontrol_en.dev_attr.attr,
- &iio_dev_attr_dds0_freqsymbol.dev_attr.attr,
- &iio_dev_attr_dds0_phasesymbol.dev_attr.attr,
- &iio_dev_attr_dds0_out_enable.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_frequency0.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_frequency1.dev_attr.attr,
+ &iio_const_attr_out_altvoltage0_frequency_scale.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_phase0.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_phase1.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_phase2.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_phase3.dev_attr.attr,
+ &iio_const_attr_out_altvoltage0_phase_scale.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_pincontrol_en.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_frequencysymbol.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_phasesymbol.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_out_enable.dev_attr.attr,
NULL,
};
@@ -221,7 +221,7 @@ static int __devinit ad9832_probe(struct spi_device *spi)
goto error_put_reg;
}
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
@@ -313,7 +313,7 @@ static int __devinit ad9832_probe(struct spi_device *spi)
return 0;
error_free_device:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_disable_reg:
if (!IS_ERR(reg))
regulator_disable(reg);
@@ -334,7 +334,7 @@ static int __devexit ad9832_remove(struct spi_device *spi)
regulator_disable(st->reg);
regulator_put(st->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dds/ad9832.h b/drivers/staging/iio/frequency/ad9832.h
index c5b701f8aabb..c5b701f8aabb 100644
--- a/drivers/staging/iio/dds/ad9832.h
+++ b/drivers/staging/iio/frequency/ad9832.h
diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
index 38a2de08626f..1b2dc741d2ce 100644
--- a/drivers/staging/iio/dds/ad9834.c
+++ b/drivers/staging/iio/frequency/ad9834.c
@@ -19,8 +19,8 @@
#include <linux/module.h>
#include <asm/div64.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "dds.h"
#include "ad9834.h"
@@ -66,7 +66,7 @@ static ssize_t ad9834_write(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad9834_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
@@ -145,7 +145,7 @@ static ssize_t ad9834_store_wavetype(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad9834_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret = 0;
@@ -203,7 +203,7 @@ static ssize_t ad9834_show_out0_wavetype_available(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad9834_state *st = iio_priv(indio_dev);
char *str;
@@ -218,14 +218,14 @@ static ssize_t ad9834_show_out0_wavetype_available(struct device *dev,
}
-static IIO_DEVICE_ATTR(dds0_out0_wavetype_available, S_IRUGO,
+static IIO_DEVICE_ATTR(out_altvoltage0_out0_wavetype_available, S_IRUGO,
ad9834_show_out0_wavetype_available, NULL, 0);
static ssize_t ad9834_show_out1_wavetype_available(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad9834_state *st = iio_priv(indio_dev);
char *str;
@@ -237,7 +237,7 @@ static ssize_t ad9834_show_out1_wavetype_available(struct device *dev,
return sprintf(buf, "%s\n", str);
}
-static IIO_DEVICE_ATTR(dds0_out1_wavetype_available, S_IRUGO,
+static IIO_DEVICE_ATTR(out_altvoltage0_out1_wavetype_available, S_IRUGO,
ad9834_show_out1_wavetype_available, NULL, 0);
/**
@@ -263,36 +263,36 @@ static IIO_DEV_ATTR_OUT_WAVETYPE(0, 0, ad9834_store_wavetype, 0);
static IIO_DEV_ATTR_OUT_WAVETYPE(0, 1, ad9834_store_wavetype, 1);
static struct attribute *ad9834_attributes[] = {
- &iio_dev_attr_dds0_freq0.dev_attr.attr,
- &iio_dev_attr_dds0_freq1.dev_attr.attr,
- &iio_const_attr_dds0_freq_scale.dev_attr.attr,
- &iio_dev_attr_dds0_phase0.dev_attr.attr,
- &iio_dev_attr_dds0_phase1.dev_attr.attr,
- &iio_const_attr_dds0_phase_scale.dev_attr.attr,
- &iio_dev_attr_dds0_pincontrol_en.dev_attr.attr,
- &iio_dev_attr_dds0_freqsymbol.dev_attr.attr,
- &iio_dev_attr_dds0_phasesymbol.dev_attr.attr,
- &iio_dev_attr_dds0_out_enable.dev_attr.attr,
- &iio_dev_attr_dds0_out1_enable.dev_attr.attr,
- &iio_dev_attr_dds0_out0_wavetype.dev_attr.attr,
- &iio_dev_attr_dds0_out1_wavetype.dev_attr.attr,
- &iio_dev_attr_dds0_out0_wavetype_available.dev_attr.attr,
- &iio_dev_attr_dds0_out1_wavetype_available.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_frequency0.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_frequency1.dev_attr.attr,
+ &iio_const_attr_out_altvoltage0_frequency_scale.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_phase0.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_phase1.dev_attr.attr,
+ &iio_const_attr_out_altvoltage0_phase_scale.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_pincontrol_en.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_frequencysymbol.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_phasesymbol.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_out_enable.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_out1_enable.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_out0_wavetype.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_out1_wavetype.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_out0_wavetype_available.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_out1_wavetype_available.dev_attr.attr,
NULL,
};
static struct attribute *ad9833_attributes[] = {
- &iio_dev_attr_dds0_freq0.dev_attr.attr,
- &iio_dev_attr_dds0_freq1.dev_attr.attr,
- &iio_const_attr_dds0_freq_scale.dev_attr.attr,
- &iio_dev_attr_dds0_phase0.dev_attr.attr,
- &iio_dev_attr_dds0_phase1.dev_attr.attr,
- &iio_const_attr_dds0_phase_scale.dev_attr.attr,
- &iio_dev_attr_dds0_freqsymbol.dev_attr.attr,
- &iio_dev_attr_dds0_phasesymbol.dev_attr.attr,
- &iio_dev_attr_dds0_out_enable.dev_attr.attr,
- &iio_dev_attr_dds0_out0_wavetype.dev_attr.attr,
- &iio_dev_attr_dds0_out0_wavetype_available.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_frequency0.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_frequency1.dev_attr.attr,
+ &iio_const_attr_out_altvoltage0_frequency_scale.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_phase0.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_phase1.dev_attr.attr,
+ &iio_const_attr_out_altvoltage0_phase_scale.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_frequencysymbol.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_phasesymbol.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_out_enable.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_out0_wavetype.dev_attr.attr,
+ &iio_dev_attr_out_altvoltage0_out0_wavetype_available.dev_attr.attr,
NULL,
};
@@ -334,7 +334,7 @@ static int __devinit ad9834_probe(struct spi_device *spi)
goto error_put_reg;
}
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
@@ -414,7 +414,7 @@ static int __devinit ad9834_probe(struct spi_device *spi)
return 0;
error_free_device:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_disable_reg:
if (!IS_ERR(reg))
regulator_disable(reg);
@@ -434,7 +434,7 @@ static int __devexit ad9834_remove(struct spi_device *spi)
regulator_disable(st->reg);
regulator_put(st->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/dds/ad9834.h b/drivers/staging/iio/frequency/ad9834.h
index ed5ed8d0007f..ed5ed8d0007f 100644
--- a/drivers/staging/iio/dds/ad9834.h
+++ b/drivers/staging/iio/frequency/ad9834.h
diff --git a/drivers/staging/iio/dds/ad9850.c b/drivers/staging/iio/frequency/ad9850.c
index f4f731bb2191..74abee054ac0 100644
--- a/drivers/staging/iio/dds/ad9850.c
+++ b/drivers/staging/iio/frequency/ad9850.c
@@ -16,8 +16,8 @@
#include <linux/sysfs.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#define DRV_NAME "ad9850"
@@ -43,7 +43,7 @@ static ssize_t ad9850_set_parameter(struct device *dev,
struct spi_transfer xfer;
int ret;
struct ad9850_config *config = (struct ad9850_config *)buf;
- struct iio_dev *idev = dev_get_drvdata(dev);
+ struct iio_dev *idev = dev_to_iio_dev(dev);
struct ad9850_state *st = iio_priv(idev);
xfer.len = len;
@@ -83,7 +83,7 @@ static int __devinit ad9850_probe(struct spi_device *spi)
struct iio_dev *idev;
int ret = 0;
- idev = iio_allocate_device(sizeof(*st));
+ idev = iio_device_alloc(sizeof(*st));
if (idev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -108,7 +108,7 @@ static int __devinit ad9850_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(idev);
+ iio_device_free(idev);
error_ret:
return ret;
}
@@ -116,7 +116,7 @@ error_ret:
static int __devexit ad9850_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_free_device(spi_get_drvdata(spi));
+ iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/dds/ad9852.c b/drivers/staging/iio/frequency/ad9852.c
index 554266c615a8..fd9d14a413a5 100644
--- a/drivers/staging/iio/dds/ad9852.c
+++ b/drivers/staging/iio/frequency/ad9852.c
@@ -16,8 +16,8 @@
#include <linux/sysfs.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#define DRV_NAME "ad9852"
@@ -71,7 +71,7 @@ static ssize_t ad9852_set_parameter(struct device *dev,
struct spi_transfer xfer;
int ret;
struct ad9852_config *config = (struct ad9852_config *)buf;
- struct iio_dev *idev = dev_get_drvdata(dev);
+ struct iio_dev *idev = dev_to_iio_dev(dev);
struct ad9852_state *st = iio_priv(idev);
xfer.len = 3;
@@ -232,7 +232,7 @@ static int __devinit ad9852_probe(struct spi_device *spi)
struct iio_dev *idev;
int ret = 0;
- idev = iio_allocate_device(sizeof(*st));
+ idev = iio_device_alloc(sizeof(*st));
if (idev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -258,7 +258,7 @@ static int __devinit ad9852_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(idev);
+ iio_device_free(idev);
error_ret:
return ret;
@@ -267,7 +267,7 @@ error_ret:
static int __devexit ad9852_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_free_device(spi_get_drvdata(spi));
+ iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/dds/ad9910.c b/drivers/staging/iio/frequency/ad9910.c
index 3985766d6f87..5a7ba305b75a 100644
--- a/drivers/staging/iio/dds/ad9910.c
+++ b/drivers/staging/iio/frequency/ad9910.c
@@ -16,8 +16,8 @@
#include <linux/sysfs.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#define DRV_NAME "ad9910"
@@ -123,7 +123,7 @@ static ssize_t ad9910_set_parameter(struct device *dev,
struct spi_transfer xfer;
int ret;
struct ad9910_config *config = (struct ad9910_config *)buf;
- struct iio_dev *idev = dev_get_drvdata(dev);
+ struct iio_dev *idev = dev_to_iio_dev(dev);
struct ad9910_state *st = iio_priv(idev);
xfer.len = 5;
@@ -367,7 +367,7 @@ static int __devinit ad9910_probe(struct spi_device *spi)
struct iio_dev *idev;
int ret = 0;
- idev = iio_allocate_device(sizeof(*st));
+ idev = iio_device_alloc(sizeof(*st));
if (idev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -392,7 +392,7 @@ static int __devinit ad9910_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(idev);
+ iio_device_free(idev);
error_ret:
return ret;
}
@@ -400,7 +400,7 @@ error_ret:
static int __devexit ad9910_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_free_device(spi_get_drvdata(spi));
+ iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/dds/ad9951.c b/drivers/staging/iio/frequency/ad9951.c
index 4d150048002a..ba6f49ff09ae 100644
--- a/drivers/staging/iio/dds/ad9951.c
+++ b/drivers/staging/iio/frequency/ad9951.c
@@ -16,8 +16,8 @@
#include <linux/sysfs.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#define DRV_NAME "ad9951"
@@ -64,7 +64,7 @@ static ssize_t ad9951_set_parameter(struct device *dev,
struct spi_transfer xfer;
int ret;
struct ad9951_config *config = (struct ad9951_config *)buf;
- struct iio_dev *idev = dev_get_drvdata(dev);
+ struct iio_dev *idev = dev_to_iio_dev(dev);
struct ad9951_state *st = iio_priv(idev);
xfer.len = 3;
@@ -176,7 +176,7 @@ static int __devinit ad9951_probe(struct spi_device *spi)
struct iio_dev *idev;
int ret = 0;
- idev = iio_allocate_device(sizeof(*st));
+ idev = iio_device_alloc(sizeof(*st));
if (idev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -202,7 +202,7 @@ static int __devinit ad9951_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(idev);
+ iio_device_free(idev);
error_ret:
return ret;
@@ -211,7 +211,7 @@ error_ret:
static int __devexit ad9951_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_free_device(spi_get_drvdata(spi));
+ iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/frequency/dds.h b/drivers/staging/iio/frequency/dds.h
new file mode 100644
index 000000000000..c3342f6e052b
--- /dev/null
+++ b/drivers/staging/iio/frequency/dds.h
@@ -0,0 +1,110 @@
+/*
+ * dds.h - sysfs attributes associated with DDS devices
+ *
+ * Copyright (c) 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+/**
+ * /sys/bus/iio/devices/.../out_altvoltageX_frequencyY
+ */
+
+#define IIO_DEV_ATTR_FREQ(_channel, _num, _mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(out_altvoltage##_channel##_frequency##_num, \
+ _mode, _show, _store, _addr)
+
+/**
+ * /sys/bus/iio/devices/.../out_altvoltageX_frequencyY_scale
+ */
+
+#define IIO_CONST_ATTR_FREQ_SCALE(_channel, _string) \
+ IIO_CONST_ATTR(out_altvoltage##_channel##_frequency_scale, _string)
+
+/**
+ * /sys/bus/iio/devices/.../out_altvoltageX_frequencysymbol
+ */
+
+#define IIO_DEV_ATTR_FREQSYMBOL(_channel, _mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(out_altvoltage##_channel##_frequencysymbol, \
+ _mode, _show, _store, _addr);
+
+/**
+ * /sys/bus/iio/devices/.../out_altvoltageX_phaseY
+ */
+
+#define IIO_DEV_ATTR_PHASE(_channel, _num, _mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(out_altvoltage##_channel##_phase##_num, \
+ _mode, _show, _store, _addr)
+
+/**
+ * /sys/bus/iio/devices/.../out_altvoltageX_phaseY_scale
+ */
+
+#define IIO_CONST_ATTR_PHASE_SCALE(_channel, _string) \
+ IIO_CONST_ATTR(out_altvoltage##_channel##_phase_scale, _string)
+
+/**
+ * /sys/bus/iio/devices/.../out_altvoltageX_phasesymbol
+ */
+
+#define IIO_DEV_ATTR_PHASESYMBOL(_channel, _mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(out_altvoltage##_channel##_phasesymbol, \
+ _mode, _show, _store, _addr);
+
+/**
+ * /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_en
+ */
+
+#define IIO_DEV_ATTR_PINCONTROL_EN(_channel, _mode, _show, _store, _addr)\
+ IIO_DEVICE_ATTR(out_altvoltage##_channel##_pincontrol_en, \
+ _mode, _show, _store, _addr);
+
+/**
+ * /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_frequency_en
+ */
+
+#define IIO_DEV_ATTR_PINCONTROL_FREQ_EN(_channel, _mode, _show, _store, _addr)\
+ IIO_DEVICE_ATTR(out_altvoltage##_channel##_pincontrol_frequency_en,\
+ _mode, _show, _store, _addr);
+
+/**
+ * /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_phase_en
+ */
+
+#define IIO_DEV_ATTR_PINCONTROL_PHASE_EN(_channel, _mode, _show, _store, _addr)\
+ IIO_DEVICE_ATTR(out_altvoltage##_channel##_pincontrol_phase_en, \
+ _mode, _show, _store, _addr);
+
+/**
+ * /sys/bus/iio/devices/.../out_altvoltageX_out_enable
+ */
+
+#define IIO_DEV_ATTR_OUT_ENABLE(_channel, _mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(out_altvoltage##_channel##_out_enable, \
+ _mode, _show, _store, _addr);
+
+/**
+ * /sys/bus/iio/devices/.../out_altvoltageX_outY_enable
+ */
+
+#define IIO_DEV_ATTR_OUTY_ENABLE(_channel, _output, \
+ _mode, _show, _store, _addr) \
+ IIO_DEVICE_ATTR(out_altvoltage##_channel##_out##_output##_enable,\
+ _mode, _show, _store, _addr);
+
+/**
+ * /sys/bus/iio/devices/.../out_altvoltageX_outY_wavetype
+ */
+
+#define IIO_DEV_ATTR_OUT_WAVETYPE(_channel, _output, _store, _addr) \
+ IIO_DEVICE_ATTR(out_altvoltage##_channel##_out##_output##_wavetype,\
+ S_IWUSR, NULL, _store, _addr);
+
+/**
+ * /sys/bus/iio/devices/.../out_altvoltageX_outY_wavetype_available
+ */
+
+#define IIO_CONST_ATTR_OUT_WAVETYPES_AVAILABLE(_channel, _output, _modes)\
+ IIO_CONST_ATTR( \
+ out_altvoltage##_channel##_out##_output##_wavetype_available, _modes);
diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c
index 02cc23420b90..9931e2060e1f 100644
--- a/drivers/staging/iio/gyro/adis16060_core.c
+++ b/drivers/staging/iio/gyro/adis16060_core.c
@@ -15,8 +15,8 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#define ADIS16060_GYRO 0x20 /* Measure Angular Rate (Gyro) */
#define ADIS16060_TEMP_OUT 0x10 /* Measure Temperature */
@@ -85,7 +85,7 @@ static int adis16060_read_raw(struct iio_dev *indio_dev,
int ret;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
/* Take the iio_dev status lock */
mutex_lock(&indio_dev->mlock);
ret = adis16060_spi_write(indio_dev, chan->address);
@@ -120,22 +120,26 @@ static const struct iio_chan_spec adis16060_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.address = ADIS16060_GYRO,
}, {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.address = ADIS16060_AIN1,
}, {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.address = ADIS16060_AIN2,
}, {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = ADIS16060_TEMP_OUT,
}
@@ -148,7 +152,7 @@ static int __devinit adis16060_r_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -174,7 +178,7 @@ static int __devinit adis16060_r_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -183,7 +187,7 @@ error_ret:
static int adis16060_r_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_free_device(spi_get_drvdata(spi));
+ iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c
index 1815490db8b4..11f1dccd7a0d 100644
--- a/drivers/staging/iio/gyro/adis16080_core.c
+++ b/drivers/staging/iio/gyro/adis16080_core.c
@@ -14,8 +14,8 @@
#include <linux/sysfs.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#define ADIS16080_DIN_GYRO (0 << 10) /* Gyroscope output */
#define ADIS16080_DIN_TEMP (1 << 10) /* Temperature output */
@@ -87,7 +87,7 @@ static int adis16080_read_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock);
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
ret = adis16080_spi_write(indio_dev,
chan->address |
ADIS16080_DIN_WRITE);
@@ -110,21 +110,25 @@ static const struct iio_chan_spec adis16080_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.address = ADIS16080_DIN_GYRO,
}, {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.address = ADIS16080_DIN_AIN1,
}, {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.address = ADIS16080_DIN_AIN2,
}, {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.address = ADIS16080_DIN_TEMP,
}
};
@@ -141,7 +145,7 @@ static int __devinit adis16080_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -167,7 +171,7 @@ static int __devinit adis16080_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -176,7 +180,7 @@ error_ret:
static int adis16080_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_free_device(spi_get_drvdata(spi));
+ iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c
index 947eb86f05d8..bf61cd0b5bbc 100644
--- a/drivers/staging/iio/gyro/adis16130_core.c
+++ b/drivers/staging/iio/gyro/adis16130_core.c
@@ -16,8 +16,8 @@
#include <linux/list.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#define ADIS16130_CON 0x0
#define ADIS16130_CON_RD (1 << 6)
@@ -100,11 +100,13 @@ static const struct iio_chan_spec adis16130_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.address = ADIS16130_RATEDATA,
}, {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.address = ADIS16130_TEMPDATA,
}
};
@@ -121,7 +123,7 @@ static int __devinit adis16130_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -145,7 +147,7 @@ static int __devinit adis16130_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
@@ -155,7 +157,7 @@ error_ret:
static int adis16130_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_free_device(spi_get_drvdata(spi));
+ iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
index 8f6af47e9559..ec765f955f8d 100644
--- a/drivers/staging/iio/gyro/adis16260_core.c
+++ b/drivers/staging/iio/gyro/adis16260_core.c
@@ -18,9 +18,9 @@
#include <linux/list.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "adis16260.h"
@@ -149,7 +149,7 @@ static ssize_t adis16260_read_frequency_available(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct adis16260_state *st = iio_priv(indio_dev);
if (spi_get_device_id(st->us)->driver_data)
return sprintf(buf, "%s\n", "0.129 ~ 256");
@@ -161,7 +161,7 @@ static ssize_t adis16260_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct adis16260_state *st = iio_priv(indio_dev);
int ret, len = 0;
u16 t;
@@ -186,7 +186,7 @@ static ssize_t adis16260_write_frequency(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct adis16260_state *st = iio_priv(indio_dev);
long val;
int ret;
@@ -237,7 +237,7 @@ static ssize_t adis16260_write_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
if (len < 1)
return -EINVAL;
switch (buf[0]) {
@@ -389,30 +389,76 @@ enum adis16260_channel {
};
#define ADIS16260_GYRO_CHANNEL_SET(axis, mod) \
struct iio_chan_spec adis16260_channels_##axis[] = { \
- IIO_CHAN(IIO_ANGL_VEL, 1, 0, 0, NULL, 0, mod, \
- IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
- IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
- gyro, ADIS16260_SCAN_GYRO, \
- IIO_ST('s', 14, 16, 0), 0), \
- IIO_CHAN(IIO_ANGL, 1, 0, 0, NULL, 0, mod, \
- 0, \
- angle, ADIS16260_SCAN_ANGL, \
- IIO_ST('u', 14, 16, 0), 0), \
- IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, \
- IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
- temp, ADIS16260_SCAN_TEMP, \
- IIO_ST('u', 12, 16, 0), 0), \
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
- in_supply, ADIS16260_SCAN_SUPPLY, \
- IIO_ST('u', 12, 16, 0), 0), \
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
- in_aux, ADIS16260_SCAN_AUX_ADC, \
- IIO_ST('u', 12, 16, 0), 0), \
- IIO_CHAN_SOFT_TIMESTAMP(5) \
+ { \
+ .type = IIO_ANGL_VEL, \
+ .modified = 1, \
+ .channel2 = mod, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .address = gyro, \
+ .scan_index = ADIS16260_SCAN_GYRO, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 14, \
+ .storagebits = 16, \
+ }, \
+ }, { \
+ .type = IIO_ANGL, \
+ .modified = 1, \
+ .channel2 = mod, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \
+ .address = angle, \
+ .scan_index = ADIS16260_SCAN_ANGL, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 14, \
+ .storagebits = 16, \
+ }, \
+ }, { \
+ .type = IIO_TEMP, \
+ .indexed = 1, \
+ .channel = 0, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .address = temp, \
+ .scan_index = ADIS16260_SCAN_TEMP, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ }, \
+ }, { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = 0, \
+ .extend_name = "supply", \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .address = in_supply, \
+ .scan_index = ADIS16260_SCAN_SUPPLY, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ }, \
+ }, { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = 1, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .address = in_aux, \
+ .scan_index = ADIS16260_SCAN_AUX_ADC, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ }, \
+ }, \
+ IIO_CHAN_SOFT_TIMESTAMP(5), \
}
static const ADIS16260_GYRO_CHANNEL_SET(x, IIO_MOD_X);
@@ -440,7 +486,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
s16 val16;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
addr = adis16260_addresses[chan->address][0];
ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16);
@@ -581,7 +627,7 @@ static int __devinit adis16260_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -666,7 +712,7 @@ error_uninitialize_ring:
error_unreg_ring_funcs:
adis16260_unconfigure_ring(indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -687,7 +733,7 @@ static int adis16260_remove(struct spi_device *spi)
adis16260_remove_trigger(indio_dev);
iio_buffer_unregister(indio_dev);
adis16260_unconfigure_ring(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
err_ret:
return ret;
diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c
index 711f15122a08..0fe2d9dfb6cd 100644
--- a/drivers/staging/iio/gyro/adis16260_ring.c
+++ b/drivers/staging/iio/gyro/adis16260_ring.c
@@ -5,20 +5,19 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/trigger_consumer.h>
#include "adis16260.h"
/**
* adis16260_read_ring_data() read data registers which will be placed into ring
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @indio_dev: the IIO device
* @rx: somewhere to pass back the value read
**/
-static int adis16260_read_ring_data(struct device *dev, u8 *rx)
+static int adis16260_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16260_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[ADIS16260_OUTPUTS + 1];
int ret;
@@ -66,22 +65,21 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p)
struct iio_buffer *ring = indio_dev->buffer;
int i = 0;
s16 *data;
- size_t datasize = ring->access->get_bytes_per_datum(ring);
- data = kmalloc(datasize , GFP_KERNEL);
+ data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
return -ENOMEM;
}
if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
- adis16260_read_ring_data(&indio_dev->dev, st->rx) >= 0)
+ adis16260_read_ring_data(indio_dev, st->rx) >= 0)
for (; i < bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength); i++)
data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
/* Guaranteed to be aligned with 8 byte boundary */
- if (ring->scan_timestamp)
+ if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
ring->access->store_to(ring, (u8 *)data, pf->timestamp);
diff --git a/drivers/staging/iio/gyro/adis16260_trigger.c b/drivers/staging/iio/gyro/adis16260_trigger.c
index 8299cd18d705..034559e4d5b9 100644
--- a/drivers/staging/iio/gyro/adis16260_trigger.c
+++ b/drivers/staging/iio/gyro/adis16260_trigger.c
@@ -3,8 +3,8 @@
#include <linux/spi/spi.h>
#include <linux/export.h>
-#include "../iio.h"
-#include "../trigger.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
#include "adis16260.h"
/**
@@ -29,7 +29,7 @@ int adis16260_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct adis16260_state *st = iio_priv(indio_dev);
- st->trig = iio_allocate_trigger("%s-dev%d",
+ st->trig = iio_trigger_alloc("%s-dev%d",
spi_get_device_id(st->us)->name,
indio_dev->id);
if (st->trig == NULL) {
@@ -60,7 +60,7 @@ int adis16260_probe_trigger(struct iio_dev *indio_dev)
error_free_irq:
free_irq(st->us->irq, st->trig);
error_free_trig:
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
error_ret:
return ret;
}
@@ -71,5 +71,5 @@ void adis16260_remove_trigger(struct iio_dev *indio_dev)
iio_trigger_unregister(st->trig);
free_irq(st->us->irq, st->trig);
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
}
diff --git a/drivers/staging/iio/gyro/adxrs450.h b/drivers/staging/iio/gyro/adxrs450.h
index af0c870100b6..f8cf21f02943 100644
--- a/drivers/staging/iio/gyro/adxrs450.h
+++ b/drivers/staging/iio/gyro/adxrs450.h
@@ -49,7 +49,7 @@ enum {
* @us: actual spi_device
* @buf_lock: mutex to protect tx and rx
* @tx: transmit buffer
- * @rx: recieve buffer
+ * @rx: receive buffer
**/
struct adxrs450_state {
struct spi_device *us;
diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c
index 15e2496f70c8..6513119b1e90 100644
--- a/drivers/staging/iio/gyro/adxrs450_core.c
+++ b/drivers/staging/iio/gyro/adxrs450_core.c
@@ -18,8 +18,8 @@
#include <linux/list.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "adxrs450.h"
@@ -265,7 +265,7 @@ static int adxrs450_read_raw(struct iio_dev *indio_dev,
s16 t;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
switch (chan->type) {
case IIO_ANGL_VEL:
ret = adxrs450_spi_sensor_data(indio_dev, &t);
@@ -329,14 +329,16 @@ static const struct iio_chan_spec adxrs450_channels[2][2] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
}, {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
}
},
[ID_ADXRS453] = {
@@ -344,13 +346,15 @@ static const struct iio_chan_spec adxrs450_channels[2][2] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT,
}, {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
}
},
};
@@ -368,7 +372,7 @@ static int __devinit adxrs450_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -399,7 +403,7 @@ static int __devinit adxrs450_probe(struct spi_device *spi)
error_initial:
iio_device_unregister(indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
@@ -408,7 +412,7 @@ error_ret:
static int adxrs450_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_free_device(spi_get_drvdata(spi));
+ iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/iio_dummy_evgen.c b/drivers/staging/iio/iio_dummy_evgen.c
index f39f346bf04f..0cd4fe916bf9 100644
--- a/drivers/staging/iio/iio_dummy_evgen.c
+++ b/drivers/staging/iio/iio_dummy_evgen.c
@@ -22,8 +22,8 @@
#include <linux/sysfs.h>
#include "iio_dummy_evgen.h"
-#include "iio.h"
-#include "sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
/* Fiddly bit of faking and irq without hardware */
#define IIO_EVENTGEN_NO 10
diff --git a/drivers/staging/iio/iio_hwmon.c b/drivers/staging/iio/iio_hwmon.c
index a603a5f51f93..b03554fee443 100644
--- a/drivers/staging/iio/iio_hwmon.c
+++ b/drivers/staging/iio/iio_hwmon.c
@@ -14,8 +14,8 @@
#include <linux/platform_device.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
-#include "consumer.h"
-#include "types.h"
+#include <linux/iio/consumer.h>
+#include <linux/iio/types.h>
/**
* struct iio_hwmon_state - device instance state
diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c
index e3a94572bb40..310411911ed7 100644
--- a/drivers/staging/iio/iio_simple_dummy.c
+++ b/drivers/staging/iio/iio_simple_dummy.c
@@ -19,10 +19,10 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include "iio.h"
-#include "sysfs.h"
-#include "events.h"
-#include "buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+#include <linux/iio/buffer.h>
#include "iio_simple_dummy.h"
/*
@@ -73,6 +73,12 @@ static struct iio_chan_spec iio_dummy_channels[] = {
/* What other information is available? */
.info_mask =
/*
+ * in_voltage0_raw
+ * Raw (unscaled no bias removal etc) measurement
+ * from the device.
+ */
+ IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ /*
* in_voltage0_offset
* Offset for userspace to apply prior to scale
* when converting to standard units (microvolts)
@@ -114,6 +120,12 @@ static struct iio_chan_spec iio_dummy_channels[] = {
.channel2 = 2,
.info_mask =
/*
+ * in_voltage1-voltage2_raw
+ * Raw (unscaled no bias removal etc) measurement
+ * from the device.
+ */
+ IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ /*
* in_voltage-voltage_scale
* Shared version of scale - shared by differential
* input channels of type IIO_VOLTAGE.
@@ -135,6 +147,7 @@ static struct iio_chan_spec iio_dummy_channels[] = {
.channel = 3,
.channel2 = 4,
.info_mask =
+ IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = diffvoltage3m4,
.scan_type = {
@@ -154,6 +167,7 @@ static struct iio_chan_spec iio_dummy_channels[] = {
/* Channel 2 is use for modifiers */
.channel2 = IIO_MOD_X,
.info_mask =
+ IIO_CHAN_INFO_RAW_SEPARATE_BIT |
/*
* Internal bias correction value. Applied
* by the hardware or driver prior to userspace
@@ -177,6 +191,7 @@ static struct iio_chan_spec iio_dummy_channels[] = {
/* DAC channel out_voltage0_raw */
{
.type = IIO_VOLTAGE,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.output = 1,
.indexed = 1,
.channel = 0,
@@ -203,7 +218,7 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev,
mutex_lock(&st->lock);
switch (mask) {
- case 0: /* magic value - channel value read */
+ case IIO_CHAN_INFO_RAW: /* magic value - channel value read */
switch (chan->type) {
case IIO_VOLTAGE:
if (chan->output) {
@@ -290,7 +305,7 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev,
struct iio_dummy_state *st = iio_priv(indio_dev);
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
if (chan->output == 0)
return -EINVAL;
@@ -377,7 +392,7 @@ static int __devinit iio_dummy_probe(int index)
* It also has a region (accessed by iio_priv()
* for chip specific state information.
*/
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -455,9 +470,7 @@ error_unconfigure_buffer:
error_unregister_events:
iio_simple_dummy_events_unregister(indio_dev);
error_free_device:
- /* Note free device should only be called, before registration
- * has succeeded. */
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -494,7 +507,7 @@ static int iio_dummy_remove(int index)
goto error_ret;
/* Free all structures */
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c
index bb4daf744362..fdfc8739095a 100644
--- a/drivers/staging/iio/iio_simple_dummy_buffer.c
+++ b/drivers/staging/iio/iio_simple_dummy_buffer.c
@@ -18,9 +18,9 @@
#include <linux/irq.h>
#include <linux/bitmap.h>
-#include "iio.h"
-#include "trigger_consumer.h"
-#include "kfifo_buf.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/kfifo_buf.h>
#include "iio_simple_dummy.h"
@@ -37,7 +37,7 @@ static const s16 fakedata[] = {
* @irq: the interrupt number
* @p: private data - always a pointer to the poll func.
*
- * This is the guts of buffered capture. On a trigger event occuring,
+ * This is the guts of buffered capture. On a trigger event occurring,
* if the pollfunc is attached then this handler is called as a threaded
* interrupt (and hence may sleep). It is responsible for grabbing data
* from the device and pushing it into the associated buffer.
@@ -48,12 +48,9 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct iio_buffer *buffer = indio_dev->buffer;
int len = 0;
- /*
- * The datasize is obtained from the buffer. It was stored when
- * the preenable setup function was called.
- */
- size_t datasize = buffer->access->get_bytes_per_datum(buffer);
- u16 *data = kmalloc(datasize, GFP_KERNEL);
+ u16 *data;
+
+ data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
@@ -64,7 +61,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
* up a fast read. The capture will consist of all of them.
* Hence we just call the grab data function and fill the
* buffer without processing.
- * sofware scans: can be considered to be random access
+ * software scans: can be considered to be random access
* so efficient reading is just a case of minimal bus
* transactions.
* software culled hardware scans:
@@ -87,7 +84,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
}
}
/* Store a timestampe at an 8 byte boundary */
- if (buffer->scan_timestamp)
+ if (indio_dev->scan_timestamp)
*(s64 *)(((phys_addr_t)data + len
+ sizeof(s64) - 1) & ~(sizeof(s64) - 1))
= iio_get_time_ns();
diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c
index 449c7a5ece80..317b77465db4 100644
--- a/drivers/staging/iio/iio_simple_dummy_events.c
+++ b/drivers/staging/iio/iio_simple_dummy_events.c
@@ -12,9 +12,9 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include "iio.h"
-#include "sysfs.h"
-#include "events.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
#include "iio_simple_dummy.h"
/* Evgen 'fakes' interrupt events for this example */
@@ -122,7 +122,7 @@ int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev,
* @private: pointer to device instance state.
*
* This handler is responsible for querying the device to find out what
- * event occured and for then pushing that event towards userspace.
+ * event occurred and for then pushing that event towards userspace.
* Here only one event occurs so we push that directly on with locally
* grabbed timestamp.
*/
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index cd82b56d58af..a8e51bc04439 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -19,9 +19,9 @@
#include <linux/module.h>
#include <asm/div64.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "../ring_sw.h"
#include "ad5933.h"
@@ -109,15 +109,46 @@ static struct ad5933_platform_data ad5933_default_pdata = {
};
static struct iio_chan_spec ad5933_channels[] = {
- IIO_CHAN(IIO_TEMP, 0, 1, 1, NULL, 0, 0, 0,
- 0, AD5933_REG_TEMP_DATA, IIO_ST('s', 14, 16, 0), 0),
- /* Ring Channels */
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "real_raw", 0, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- AD5933_REG_REAL_DATA, 0, IIO_ST('s', 16, 16, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "imag_raw", 0, 0,
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- AD5933_REG_IMAG_DATA, 1, IIO_ST('s', 16, 16, 0), 0),
+ {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT,
+ .address = AD5933_REG_TEMP_DATA,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ },
+ }, { /* Ring Channels */
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "real_raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .address = AD5933_REG_REAL_DATA,
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ },
+ }, {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "imag_raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .address = AD5933_REG_IMAG_DATA,
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ },
+ },
};
static int ad5933_i2c_write(struct i2c_client *client,
@@ -260,7 +291,7 @@ static ssize_t ad5933_show_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5933_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
@@ -289,7 +320,7 @@ static ssize_t ad5933_store_frequency(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5933_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
long val;
@@ -323,7 +354,7 @@ static ssize_t ad5933_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5933_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret = 0, len = 0;
@@ -366,7 +397,7 @@ static ssize_t ad5933_store(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5933_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
long val;
@@ -495,7 +526,8 @@ static int ad5933_read_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock);
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_PROCESSED:
if (iio_buffer_enabled(indio_dev)) {
ret = -EBUSY;
goto out;
@@ -537,19 +569,14 @@ static const struct iio_info ad5933_info = {
static int ad5933_ring_preenable(struct iio_dev *indio_dev)
{
struct ad5933_state *st = iio_priv(indio_dev);
- size_t d_size;
int ret;
if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
return -EINVAL;
- d_size = bitmap_weight(indio_dev->active_scan_mask,
- indio_dev->masklength) *
- ad5933_channels[1].scan_type.storagebits / 8;
-
- if (indio_dev->buffer->access->set_bytes_per_datum)
- indio_dev->buffer->access->
- set_bytes_per_datum(indio_dev->buffer, d_size);
+ ret = iio_sw_buffer_preenable(indio_dev);
+ if (ret < 0)
+ return ret;
ret = ad5933_reset(st);
if (ret < 0)
@@ -678,7 +705,7 @@ static int __devinit ad5933_probe(struct i2c_client *client,
int ret, voltage_uv = 0;
struct ad5933_platform_data *pdata = client->dev.platform_data;
struct ad5933_state *st;
- struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+ struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -757,7 +784,7 @@ error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
@@ -774,7 +801,7 @@ static __devexit int ad5933_remove(struct i2c_client *client)
regulator_disable(st->reg);
regulator_put(st->reg);
}
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
index e73ad7818d85..1f6bd854e950 100644
--- a/drivers/staging/iio/imu/adis16400_core.c
+++ b/drivers/staging/iio/imu/adis16400_core.c
@@ -26,9 +26,9 @@
#include <linux/list.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "adis16400.h"
enum adis16400_chip_variant {
@@ -179,7 +179,7 @@ static ssize_t adis16400_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
int ret, len = 0;
ret = adis16400_get_freq(indio_dev);
if (ret < 0)
@@ -225,7 +225,7 @@ static ssize_t adis16400_write_frequency(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct adis16400_state *st = iio_priv(indio_dev);
long val;
int ret;
@@ -279,7 +279,7 @@ static ssize_t adis16400_write_reset(struct device *dev,
if (ret < 0)
return ret;
if (val) {
- ret = adis16400_reset(dev_get_drvdata(dev));
+ ret = adis16400_reset(dev_to_iio_dev(dev));
if (ret < 0)
return ret;
}
@@ -545,7 +545,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
s16 val16;
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
ret = adis16400_spi_read_reg_16(indio_dev,
adis16400_addresses[chan->address][0],
@@ -635,7 +635,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.indexed = 1,
.channel = 0,
.extend_name = "supply",
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_supply,
.scan_index = ADIS16400_SCAN_SUPPLY,
.scan_type = IIO_ST('u', 14, 16, 0)
@@ -643,7 +644,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_x,
@@ -653,7 +655,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_y,
@@ -663,7 +666,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_z,
@@ -673,7 +677,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_x,
@@ -683,7 +688,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_y,
@@ -693,7 +699,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_z,
@@ -703,7 +710,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_MAGN,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = magn_x,
.scan_index = ADIS16400_SCAN_MAGN_X,
@@ -712,7 +720,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_MAGN,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = magn_y,
.scan_index = ADIS16400_SCAN_MAGN_Y,
@@ -721,7 +730,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_MAGN,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = magn_z,
.scan_index = ADIS16400_SCAN_MAGN_Z,
@@ -730,7 +740,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = temp,
.scan_index = ADIS16400_SCAN_TEMP,
@@ -739,7 +750,8 @@ static struct iio_chan_spec adis16400_channels[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in1,
.scan_index = ADIS16400_SCAN_ADC_0,
.scan_type = IIO_ST('s', 12, 16, 0),
@@ -753,7 +765,8 @@ static struct iio_chan_spec adis16350_channels[] = {
.indexed = 1,
.channel = 0,
.extend_name = "supply",
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_supply,
.scan_index = ADIS16400_SCAN_SUPPLY,
.scan_type = IIO_ST('u', 12, 16, 0)
@@ -761,7 +774,8 @@ static struct iio_chan_spec adis16350_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_x,
@@ -771,7 +785,8 @@ static struct iio_chan_spec adis16350_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_y,
@@ -781,17 +796,19 @@ static struct iio_chan_spec adis16350_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_z,
.scan_index = ADIS16400_SCAN_GYRO_Z,
.scan_type = IIO_ST('s', 14, 16, 0),
}, {
- .type = IIO_ACCEL,
+ .type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_x,
@@ -801,7 +818,8 @@ static struct iio_chan_spec adis16350_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_y,
@@ -811,7 +829,8 @@ static struct iio_chan_spec adis16350_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_z,
@@ -822,7 +841,8 @@ static struct iio_chan_spec adis16350_channels[] = {
.indexed = 1,
.channel = 0,
.extend_name = "x",
- .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = temp0,
@@ -833,7 +853,8 @@ static struct iio_chan_spec adis16350_channels[] = {
.indexed = 1,
.channel = 1,
.extend_name = "y",
- .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = temp1,
@@ -844,7 +865,8 @@ static struct iio_chan_spec adis16350_channels[] = {
.indexed = 1,
.channel = 2,
.extend_name = "z",
- .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = temp2,
.scan_index = ADIS16350_SCAN_TEMP_Z,
@@ -853,7 +875,8 @@ static struct iio_chan_spec adis16350_channels[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in1,
.scan_index = ADIS16350_SCAN_ADC_0,
.scan_type = IIO_ST('s', 12, 16, 0),
@@ -867,7 +890,8 @@ static struct iio_chan_spec adis16300_channels[] = {
.indexed = 1,
.channel = 0,
.extend_name = "supply",
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_supply,
.scan_index = ADIS16400_SCAN_SUPPLY,
.scan_type = IIO_ST('u', 12, 16, 0)
@@ -875,7 +899,8 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_x,
@@ -885,7 +910,8 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_x,
@@ -895,7 +921,8 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_y,
@@ -905,7 +932,8 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_z,
@@ -915,7 +943,8 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = temp,
.scan_index = ADIS16400_SCAN_TEMP,
@@ -924,7 +953,8 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 1,
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in1,
.scan_index = ADIS16350_SCAN_ADC_0,
.scan_type = IIO_ST('s', 12, 16, 0),
@@ -932,7 +962,8 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_INCLI,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = incli_x,
.scan_index = ADIS16300_SCAN_INCLI_X,
.scan_type = IIO_ST('s', 13, 16, 0),
@@ -940,7 +971,8 @@ static struct iio_chan_spec adis16300_channels[] = {
.type = IIO_INCLI,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = incli_y,
.scan_index = ADIS16300_SCAN_INCLI_Y,
.scan_type = IIO_ST('s', 13, 16, 0),
@@ -953,7 +985,8 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_x,
@@ -963,7 +996,8 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_y,
@@ -973,7 +1007,8 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_z,
@@ -983,7 +1018,8 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_x,
@@ -993,7 +1029,8 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_y,
@@ -1003,7 +1040,8 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_ACCEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = accel_z,
@@ -1013,7 +1051,8 @@ static const struct iio_chan_spec adis16334_channels[] = {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
- .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
.address = accel_z,
.scan_index = ADIS16400_SCAN_ACC_Z,
@@ -1122,7 +1161,7 @@ static int __devinit adis16400_probe(struct spi_device *spi)
{
int ret;
struct adis16400_state *st;
- struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+ struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -1172,14 +1211,14 @@ static int __devinit adis16400_probe(struct spi_device *spi)
return 0;
error_remove_trigger:
- if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
+ if (spi->irq)
adis16400_remove_trigger(indio_dev);
error_uninitialize_ring:
iio_buffer_unregister(indio_dev);
error_unreg_ring_funcs:
adis16400_unconfigure_ring(indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -1198,7 +1237,7 @@ static int adis16400_remove(struct spi_device *spi)
adis16400_remove_trigger(indio_dev);
iio_buffer_unregister(indio_dev);
adis16400_unconfigure_ring(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c
index 8daa038b23e6..809e2c4270d1 100644
--- a/drivers/staging/iio/imu/adis16400_ring.c
+++ b/drivers/staging/iio/imu/adis16400_ring.c
@@ -6,20 +6,19 @@
#include <linux/bitops.h>
#include <linux/export.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/trigger_consumer.h>
#include "adis16400.h"
/**
* adis16400_spi_read_burst() - read all data registers
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @indio_dev: the IIO device
* @rx: somewhere to pass back the value read (min size is 24 bytes)
**/
-static int adis16400_spi_read_burst(struct device *dev, u8 *rx)
+static int adis16400_spi_read_burst(struct iio_dev *indio_dev, u8 *rx)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16400_state *st = iio_priv(indio_dev);
u32 old_speed_hz = st->us->max_speed_hz;
int ret;
@@ -71,9 +70,8 @@ static const u16 read_all_tx_array[] = {
cpu_to_be16(ADIS16400_READ_REG(ADIS16400_AUX_ADC)),
};
-static int adis16350_spi_read_all(struct device *dev, u8 *rx)
+static int adis16350_spi_read_all(struct iio_dev *indio_dev, u8 *rx)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adis16400_state *st = iio_priv(indio_dev);
struct spi_message msg;
@@ -119,12 +117,12 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
struct iio_buffer *ring = indio_dev->buffer;
int i = 0, j, ret = 0;
s16 *data;
- size_t datasize = ring->access->get_bytes_per_datum(ring);
+
/* Asumption that long is enough for maximum channels */
unsigned long mask = *indio_dev->active_scan_mask;
int scan_count = bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength);
- data = kmalloc(datasize , GFP_KERNEL);
+ data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL) {
dev_err(&st->us->dev, "memory alloc failed in ring bh");
return -ENOMEM;
@@ -132,13 +130,13 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
if (scan_count) {
if (st->variant->flags & ADIS16400_NO_BURST) {
- ret = adis16350_spi_read_all(&indio_dev->dev, st->rx);
+ ret = adis16350_spi_read_all(indio_dev, st->rx);
if (ret < 0)
goto err;
for (; i < scan_count; i++)
data[i] = *(s16 *)(st->rx + i*2);
} else {
- ret = adis16400_spi_read_burst(&indio_dev->dev, st->rx);
+ ret = adis16400_spi_read_burst(indio_dev, st->rx);
if (ret < 0)
goto err;
for (; i < scan_count; i++) {
diff --git a/drivers/staging/iio/imu/adis16400_trigger.c b/drivers/staging/iio/imu/adis16400_trigger.c
index 5bf000757522..42a678e92fc6 100644
--- a/drivers/staging/iio/imu/adis16400_trigger.c
+++ b/drivers/staging/iio/imu/adis16400_trigger.c
@@ -3,8 +3,8 @@
#include <linux/spi/spi.h>
#include <linux/export.h>
-#include "../iio.h"
-#include "../trigger.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
#include "adis16400.h"
/**
@@ -29,7 +29,7 @@ int adis16400_probe_trigger(struct iio_dev *indio_dev)
int ret;
struct adis16400_state *st = iio_priv(indio_dev);
- st->trig = iio_allocate_trigger("%s-dev%d",
+ st->trig = iio_trigger_alloc("%s-dev%d",
indio_dev->name,
indio_dev->id);
if (st->trig == NULL) {
@@ -59,7 +59,7 @@ int adis16400_probe_trigger(struct iio_dev *indio_dev)
error_free_irq:
free_irq(st->us->irq, st->trig);
error_free_trig:
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
error_ret:
return ret;
}
@@ -70,5 +70,5 @@ void adis16400_remove_trigger(struct iio_dev *indio_dev)
iio_trigger_unregister(st->trig);
free_irq(st->us->irq, st->trig);
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
}
diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig
index e7e9159d9895..4bed30eac3ed 100644
--- a/drivers/staging/iio/light/Kconfig
+++ b/drivers/staging/iio/light/Kconfig
@@ -4,15 +4,26 @@
menu "Light sensors"
config SENSORS_ISL29018
- tristate "ISL 29018 light and proximity sensor"
- depends on I2C
- default n
- help
- If you say yes here you get support for ambient light sensing and
- proximity infrared sensing from Intersil ISL29018.
- This driver will provide the measurements of ambient light intensity
- in lux, proximity infrared sensing and normal infrared sensing.
- Data from sensor is accessible via sysfs.
+ tristate "ISL 29018 light and proximity sensor"
+ depends on I2C
+ select REGMAP_I2C
+ default n
+ help
+ If you say yes here you get support for ambient light sensing and
+ proximity infrared sensing from Intersil ISL29018.
+ This driver will provide the measurements of ambient light intensity
+ in lux, proximity infrared sensing and normal infrared sensing.
+ Data from sensor is accessible via sysfs.
+
+config SENSORS_ISL29028
+ tristate "Intersil ISL29028 Concurrent Light and Proximity Sensor"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Provides driver for the Intersil's ISL29028 device.
+ This driver supports the sysfs interface to get the ALS, IR intensity,
+ Proximity value via iio. The ISL29028 provides the concurrent sensing
+ of ambient light and proximity.
config SENSORS_TSL2563
tristate "TAOS TSL2560, TSL2561, TSL2562 and TSL2563 ambient light sensors"
@@ -31,4 +42,12 @@ config TSL2583
Provides support for the TAOS tsl2580, tsl2581 and tsl2583 devices.
Access ALS data via iio, sysfs.
+config TSL2x7x
+ tristate "TAOS TSL/TMD2x71 and TSL/TMD2x72 Family of light and proximity sensors"
+ depends on I2C
+ help
+ Support for: tsl2571, tsl2671, tmd2671, tsl2771, tmd2771, tsl2572, tsl2672,
+ tmd2672, tsl2772, tmd2772 devices.
+ Provides iio_events and direct access via sysfs.
+
endmenu
diff --git a/drivers/staging/iio/light/Makefile b/drivers/staging/iio/light/Makefile
index 3011fbfa8dc2..141af1eb164c 100644
--- a/drivers/staging/iio/light/Makefile
+++ b/drivers/staging/iio/light/Makefile
@@ -4,4 +4,6 @@
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
obj-$(CONFIG_SENSORS_ISL29018) += isl29018.o
+obj-$(CONFIG_SENSORS_ISL29028) += isl29028.o
obj-$(CONFIG_TSL2583) += tsl2583.o
+obj-$(CONFIG_TSL2x7x) += tsl2x7x_core.o
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index 38ec52b65dfa..0abbf18d6103 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -26,9 +26,11 @@
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/delay.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
#define CONVERSION_TIME_MS 100
#define ISL29018_REG_ADD_COMMAND1 0x00
@@ -51,49 +53,22 @@
#define ISL29018_REG_ADD_DATA_LSB 0x02
#define ISL29018_REG_ADD_DATA_MSB 0x03
-#define ISL29018_MAX_REGS (ISL29018_REG_ADD_DATA_MSB+1)
#define ISL29018_REG_TEST 0x08
#define ISL29018_TEST_SHIFT 0
#define ISL29018_TEST_MASK (0xFF << ISL29018_TEST_SHIFT)
struct isl29018_chip {
- struct i2c_client *client;
+ struct device *dev;
+ struct regmap *regmap;
struct mutex lock;
unsigned int lux_scale;
unsigned int range;
unsigned int adc_bit;
int prox_scheme;
- u8 reg_cache[ISL29018_MAX_REGS];
};
-static int isl29018_write_data(struct i2c_client *client, u8 reg,
- u8 val, u8 mask, u8 shift)
-{
- u8 regval = val;
- int ret;
- struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client));
-
- /* don't cache or mask REG_TEST */
- if (reg < ISL29018_MAX_REGS) {
- regval = chip->reg_cache[reg];
- regval &= ~mask;
- regval |= val << shift;
- }
-
- ret = i2c_smbus_write_byte_data(client, reg, regval);
- if (ret) {
- dev_err(&client->dev, "Write to device fails status %x\n", ret);
- } else {
- /* don't update cache on err */
- if (reg < ISL29018_MAX_REGS)
- chip->reg_cache[reg] = regval;
- }
-
- return ret;
-}
-
-static int isl29018_set_range(struct i2c_client *client, unsigned long range,
+static int isl29018_set_range(struct isl29018_chip *chip, unsigned long range,
unsigned int *new_range)
{
static const unsigned long supp_ranges[] = {1000, 4000, 16000, 64000};
@@ -109,11 +84,11 @@ static int isl29018_set_range(struct i2c_client *client, unsigned long range,
if (i >= ARRAY_SIZE(supp_ranges))
return -EINVAL;
- return isl29018_write_data(client, ISL29018_REG_ADD_COMMANDII,
- i, COMMANDII_RANGE_MASK, COMMANDII_RANGE_SHIFT);
+ return regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII,
+ COMMANDII_RANGE_MASK, i << COMMANDII_RANGE_SHIFT);
}
-static int isl29018_set_resolution(struct i2c_client *client,
+static int isl29018_set_resolution(struct isl29018_chip *chip,
unsigned long adcbit, unsigned int *conf_adc_bit)
{
static const unsigned long supp_adcbit[] = {16, 12, 8, 4};
@@ -129,48 +104,49 @@ static int isl29018_set_resolution(struct i2c_client *client,
if (i >= ARRAY_SIZE(supp_adcbit))
return -EINVAL;
- return isl29018_write_data(client, ISL29018_REG_ADD_COMMANDII,
- i, COMMANDII_RESOLUTION_MASK,
- COMMANDII_RESOLUTION_SHIFT);
+ return regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII,
+ COMMANDII_RESOLUTION_MASK,
+ i << COMMANDII_RESOLUTION_SHIFT);
}
-static int isl29018_read_sensor_input(struct i2c_client *client, int mode)
+static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode)
{
int status;
- int lsb;
- int msb;
+ unsigned int lsb;
+ unsigned int msb;
/* Set mode */
- status = isl29018_write_data(client, ISL29018_REG_ADD_COMMAND1,
- mode, COMMMAND1_OPMODE_MASK, COMMMAND1_OPMODE_SHIFT);
+ status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1,
+ mode << COMMMAND1_OPMODE_SHIFT);
if (status) {
- dev_err(&client->dev, "Error in setting operating mode\n");
+ dev_err(chip->dev,
+ "Error in setting operating mode err %d\n", status);
return status;
}
msleep(CONVERSION_TIME_MS);
- lsb = i2c_smbus_read_byte_data(client, ISL29018_REG_ADD_DATA_LSB);
- if (lsb < 0) {
- dev_err(&client->dev, "Error in reading LSB DATA\n");
- return lsb;
+ status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_LSB, &lsb);
+ if (status < 0) {
+ dev_err(chip->dev,
+ "Error in reading LSB DATA with err %d\n", status);
+ return status;
}
- msb = i2c_smbus_read_byte_data(client, ISL29018_REG_ADD_DATA_MSB);
- if (msb < 0) {
- dev_err(&client->dev, "Error in reading MSB DATA\n");
- return msb;
+ status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_MSB, &msb);
+ if (status < 0) {
+ dev_err(chip->dev,
+ "Error in reading MSB DATA with error %d\n", status);
+ return status;
}
- dev_vdbg(&client->dev, "MSB 0x%x and LSB 0x%x\n", msb, lsb);
+ dev_vdbg(chip->dev, "MSB 0x%x and LSB 0x%x\n", msb, lsb);
return (msb << 8) | lsb;
}
-static int isl29018_read_lux(struct i2c_client *client, int *lux)
+static int isl29018_read_lux(struct isl29018_chip *chip, int *lux)
{
int lux_data;
- struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client));
- lux_data = isl29018_read_sensor_input(client,
- COMMMAND1_OPMODE_ALS_ONCE);
+ lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE);
if (lux_data < 0)
return lux_data;
@@ -180,11 +156,11 @@ static int isl29018_read_lux(struct i2c_client *client, int *lux)
return 0;
}
-static int isl29018_read_ir(struct i2c_client *client, int *ir)
+static int isl29018_read_ir(struct isl29018_chip *chip, int *ir)
{
int ir_data;
- ir_data = isl29018_read_sensor_input(client, COMMMAND1_OPMODE_IR_ONCE);
+ ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE);
if (ir_data < 0)
return ir_data;
@@ -194,7 +170,7 @@ static int isl29018_read_ir(struct i2c_client *client, int *ir)
return 0;
}
-static int isl29018_read_proximity_ir(struct i2c_client *client, int scheme,
+static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme,
int *near_ir)
{
int status;
@@ -202,14 +178,15 @@ static int isl29018_read_proximity_ir(struct i2c_client *client, int scheme,
int ir_data = -1;
/* Do proximity sensing with required scheme */
- status = isl29018_write_data(client, ISL29018_REG_ADD_COMMANDII,
- scheme, COMMANDII_SCHEME_MASK, COMMANDII_SCHEME_SHIFT);
+ status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII,
+ COMMANDII_SCHEME_MASK,
+ scheme << COMMANDII_SCHEME_SHIFT);
if (status) {
- dev_err(&client->dev, "Error in setting operating mode\n");
+ dev_err(chip->dev, "Error in setting operating mode\n");
return status;
}
- prox_data = isl29018_read_sensor_input(client,
+ prox_data = isl29018_read_sensor_input(chip,
COMMMAND1_OPMODE_PROX_ONCE);
if (prox_data < 0)
return prox_data;
@@ -219,8 +196,7 @@ static int isl29018_read_proximity_ir(struct i2c_client *client, int scheme,
return 0;
}
- ir_data = isl29018_read_sensor_input(client,
- COMMMAND1_OPMODE_IR_ONCE);
+ ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE);
if (ir_data < 0)
return ir_data;
@@ -238,7 +214,7 @@ static int isl29018_read_proximity_ir(struct i2c_client *client, int scheme,
static ssize_t show_range(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct isl29018_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%u\n", chip->range);
@@ -247,9 +223,8 @@ static ssize_t show_range(struct device *dev,
static ssize_t store_range(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct isl29018_chip *chip = iio_priv(indio_dev);
- struct i2c_client *client = chip->client;
int status;
unsigned long lval;
unsigned int new_range;
@@ -264,10 +239,11 @@ static ssize_t store_range(struct device *dev,
}
mutex_lock(&chip->lock);
- status = isl29018_set_range(client, lval, &new_range);
+ status = isl29018_set_range(chip, lval, &new_range);
if (status < 0) {
mutex_unlock(&chip->lock);
- dev_err(dev, "Error in setting max range\n");
+ dev_err(dev,
+ "Error in setting max range with err %d\n", status);
return status;
}
chip->range = new_range;
@@ -280,7 +256,7 @@ static ssize_t store_range(struct device *dev,
static ssize_t show_resolution(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct isl29018_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%u\n", chip->adc_bit);
@@ -289,9 +265,8 @@ static ssize_t show_resolution(struct device *dev,
static ssize_t store_resolution(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct isl29018_chip *chip = iio_priv(indio_dev);
- struct i2c_client *client = chip->client;
int status;
unsigned long lval;
unsigned int new_adc_bit;
@@ -304,7 +279,7 @@ static ssize_t store_resolution(struct device *dev,
}
mutex_lock(&chip->lock);
- status = isl29018_set_resolution(client, lval, &new_adc_bit);
+ status = isl29018_set_resolution(chip, lval, &new_adc_bit);
if (status < 0) {
mutex_unlock(&chip->lock);
dev_err(dev, "Error in setting resolution\n");
@@ -320,7 +295,7 @@ static ssize_t store_resolution(struct device *dev,
static ssize_t show_prox_infrared_supression(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct isl29018_chip *chip = iio_priv(indio_dev);
/* return the "proximity scheme" i.e. if the chip does on chip
@@ -331,7 +306,7 @@ static ssize_t show_prox_infrared_supression(struct device *dev,
static ssize_t store_prox_infrared_supression(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct isl29018_chip *chip = iio_priv(indio_dev);
unsigned long lval;
@@ -379,20 +354,20 @@ static int isl29018_read_raw(struct iio_dev *indio_dev,
{
int ret = -EINVAL;
struct isl29018_chip *chip = iio_priv(indio_dev);
- struct i2c_client *client = chip->client;
mutex_lock(&chip->lock);
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_PROCESSED:
switch (chan->type) {
case IIO_LIGHT:
- ret = isl29018_read_lux(client, val);
+ ret = isl29018_read_lux(chip, val);
break;
case IIO_INTENSITY:
- ret = isl29018_read_ir(client, val);
+ ret = isl29018_read_ir(chip, val);
break;
case IIO_PROXIMITY:
- ret = isl29018_read_proximity_ir(client,
+ ret = isl29018_read_proximity_ir(chip,
chip->prox_scheme, val);
break;
default:
@@ -419,15 +394,17 @@ static const struct iio_chan_spec isl29018_channels[] = {
.type = IIO_LIGHT,
.indexed = 1,
.channel = 0,
- .processed_val = IIO_PROCESSED,
- .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
}, {
.type = IIO_INTENSITY,
.modified = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
.channel2 = IIO_MOD_LIGHT_IR,
}, {
/* Unindexed in current ABI. But perhaps it should be. */
.type = IIO_PROXIMITY,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
}
};
@@ -456,15 +433,12 @@ static const struct attribute_group isl29108_group = {
.attrs = isl29018_attributes,
};
-static int isl29018_chip_init(struct i2c_client *client)
+static int isl29018_chip_init(struct isl29018_chip *chip)
{
- struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client));
int status;
int new_adc_bit;
unsigned int new_range;
- memset(chip->reg_cache, 0, sizeof(chip->reg_cache));
-
/* Code added per Intersil Application Note 1534:
* When VDD sinks to approximately 1.8V or below, some of
* the part's registers may change their state. When VDD
@@ -485,10 +459,9 @@ static int isl29018_chip_init(struct i2c_client *client)
* the same thing EXCEPT the data sheet asks for a 1ms delay after
* writing the CMD1 register.
*/
- status = isl29018_write_data(client, ISL29018_REG_TEST, 0,
- ISL29018_TEST_MASK, ISL29018_TEST_SHIFT);
+ status = regmap_write(chip->regmap, ISL29018_REG_TEST, 0x0);
if (status < 0) {
- dev_err(&client->dev, "Failed to clear isl29018 TEST reg."
+ dev_err(chip->dev, "Failed to clear isl29018 TEST reg."
"(%d)\n", status);
return status;
}
@@ -497,10 +470,9 @@ static int isl29018_chip_init(struct i2c_client *client)
* "Operating Mode" (COMMAND1) register is reprogrammed when
* data is read from the device.
*/
- status = isl29018_write_data(client, ISL29018_REG_ADD_COMMAND1, 0,
- 0xff, 0);
+ status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, 0);
if (status < 0) {
- dev_err(&client->dev, "Failed to clear isl29018 CMD1 reg."
+ dev_err(chip->dev, "Failed to clear isl29018 CMD1 reg."
"(%d)\n", status);
return status;
}
@@ -508,13 +480,13 @@ static int isl29018_chip_init(struct i2c_client *client)
msleep(1); /* per data sheet, page 10 */
/* set defaults */
- status = isl29018_set_range(client, chip->range, &new_range);
+ status = isl29018_set_range(chip, chip->range, &new_range);
if (status < 0) {
- dev_err(&client->dev, "Init of isl29018 fails\n");
+ dev_err(chip->dev, "Init of isl29018 fails\n");
return status;
}
- status = isl29018_set_resolution(client, chip->adc_bit,
+ status = isl29018_set_resolution(chip, chip->adc_bit,
&new_adc_bit);
return 0;
@@ -527,6 +499,32 @@ static const struct iio_info isl29108_info = {
.write_raw = &isl29018_write_raw,
};
+static bool is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ISL29018_REG_ADD_DATA_LSB:
+ case ISL29018_REG_ADD_DATA_MSB:
+ case ISL29018_REG_ADD_COMMAND1:
+ case ISL29018_REG_TEST:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/*
+ * isl29018_regmap_config: regmap configuration.
+ * Use RBTREE mechanism for caching.
+ */
+static const struct regmap_config isl29018_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_reg = is_volatile_reg,
+ .max_register = ISL29018_REG_TEST,
+ .num_reg_defaults_raw = ISL29018_REG_TEST + 1,
+ .cache_type = REGCACHE_RBTREE,
+};
+
static int __devinit isl29018_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -534,7 +532,7 @@ static int __devinit isl29018_probe(struct i2c_client *client,
struct iio_dev *indio_dev;
int err;
- indio_dev = iio_allocate_device(sizeof(*chip));
+ indio_dev = iio_device_alloc(sizeof(*chip));
if (indio_dev == NULL) {
dev_err(&client->dev, "iio allocation fails\n");
err = -ENOMEM;
@@ -543,7 +541,7 @@ static int __devinit isl29018_probe(struct i2c_client *client,
chip = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
- chip->client = client;
+ chip->dev = &client->dev;
mutex_init(&chip->lock);
@@ -551,7 +549,14 @@ static int __devinit isl29018_probe(struct i2c_client *client,
chip->range = 1000;
chip->adc_bit = 16;
- err = isl29018_chip_init(client);
+ chip->regmap = devm_regmap_init_i2c(client, &isl29018_regmap_config);
+ if (IS_ERR(chip->regmap)) {
+ err = PTR_ERR(chip->regmap);
+ dev_err(chip->dev, "regmap initialization failed: %d\n", err);
+ goto exit;
+ }
+
+ err = isl29018_chip_init(chip);
if (err)
goto exit_iio_free;
@@ -569,7 +574,7 @@ static int __devinit isl29018_probe(struct i2c_client *client,
return 0;
exit_iio_free:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
exit:
return err;
}
@@ -580,7 +585,7 @@ static int __devexit isl29018_remove(struct i2c_client *client)
dev_dbg(&client->dev, "%s()\n", __func__);
iio_device_unregister(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
@@ -593,7 +598,7 @@ static const struct i2c_device_id isl29018_id[] = {
MODULE_DEVICE_TABLE(i2c, isl29018_id);
static const struct of_device_id isl29018_of_match[] = {
- { .compatible = "invn,isl29018", },
+ { .compatible = "isil,isl29018", },
{ },
};
MODULE_DEVICE_TABLE(of, isl29018_of_match);
diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
new file mode 100644
index 000000000000..33a4c3f94a14
--- /dev/null
+++ b/drivers/staging/iio/light/isl29028.c
@@ -0,0 +1,566 @@
+/*
+ * IIO driver for the light sensor ISL29028.
+ * ISL29028 is Concurrent Ambient Light and Proximity Sensor
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define CONVERSION_TIME_MS 100
+
+#define ISL29028_REG_CONFIGURE 0x01
+
+#define CONFIGURE_ALS_IR_MODE_ALS 0
+#define CONFIGURE_ALS_IR_MODE_IR BIT(0)
+#define CONFIGURE_ALS_IR_MODE_MASK BIT(0)
+
+#define CONFIGURE_ALS_RANGE_LOW_LUX 0
+#define CONFIGURE_ALS_RANGE_HIGH_LUX BIT(1)
+#define CONFIGURE_ALS_RANGE_MASK BIT(1)
+
+#define CONFIGURE_ALS_DIS 0
+#define CONFIGURE_ALS_EN BIT(2)
+#define CONFIGURE_ALS_EN_MASK BIT(2)
+
+#define CONFIGURE_PROX_DRIVE BIT(3)
+
+#define CONFIGURE_PROX_SLP_SH 4
+#define CONFIGURE_PROX_SLP_MASK (7 << CONFIGURE_PROX_SLP_SH)
+
+#define CONFIGURE_PROX_EN BIT(7)
+#define CONFIGURE_PROX_EN_MASK BIT(7)
+
+#define ISL29028_REG_INTERRUPT 0x02
+
+#define ISL29028_REG_PROX_DATA 0x08
+#define ISL29028_REG_ALSIR_L 0x09
+#define ISL29028_REG_ALSIR_U 0x0A
+
+#define ISL29028_REG_TEST1_MODE 0x0E
+#define ISL29028_REG_TEST2_MODE 0x0F
+
+#define ISL29028_NUM_REGS (ISL29028_REG_TEST2_MODE + 1)
+
+enum als_ir_mode {
+ MODE_NONE = 0,
+ MODE_ALS,
+ MODE_IR
+};
+
+struct isl29028_chip {
+ struct device *dev;
+ struct mutex lock;
+ struct regmap *regmap;
+
+ unsigned int prox_sampling;
+ bool enable_prox;
+
+ int lux_scale;
+ int als_ir_mode;
+};
+
+static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
+ unsigned int sampling)
+{
+ static unsigned int prox_period[] = {800, 400, 200, 100, 75, 50, 12, 0};
+ int sel;
+ unsigned int period = DIV_ROUND_UP(1000, sampling);
+
+ for (sel = 0; sel < ARRAY_SIZE(prox_period); ++sel) {
+ if (period >= prox_period[sel])
+ break;
+ }
+ return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+ CONFIGURE_PROX_SLP_MASK, sel << CONFIGURE_PROX_SLP_SH);
+}
+
+static int isl29028_enable_proximity(struct isl29028_chip *chip, bool enable)
+{
+ int ret;
+ int val = 0;
+
+ if (enable)
+ val = CONFIGURE_PROX_EN;
+ ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+ CONFIGURE_PROX_EN_MASK, val);
+ if (ret < 0)
+ return ret;
+
+ /* Wait for conversion to be complete for first sample */
+ mdelay(DIV_ROUND_UP(1000, chip->prox_sampling));
+ return 0;
+}
+
+static int isl29028_set_als_scale(struct isl29028_chip *chip, int lux_scale)
+{
+ int val = (lux_scale == 2000) ? CONFIGURE_ALS_RANGE_HIGH_LUX :
+ CONFIGURE_ALS_RANGE_LOW_LUX;
+
+ return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+ CONFIGURE_ALS_RANGE_MASK, val);
+}
+
+static int isl29028_set_als_ir_mode(struct isl29028_chip *chip,
+ enum als_ir_mode mode)
+{
+ int ret = 0;
+
+ switch (mode) {
+ case MODE_ALS:
+ ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+ CONFIGURE_ALS_IR_MODE_MASK, CONFIGURE_ALS_IR_MODE_ALS);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+ CONFIGURE_ALS_RANGE_MASK, CONFIGURE_ALS_RANGE_HIGH_LUX);
+ break;
+
+ case MODE_IR:
+ ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+ CONFIGURE_ALS_IR_MODE_MASK, CONFIGURE_ALS_IR_MODE_IR);
+ break;
+
+ case MODE_NONE:
+ return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+ CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_DIS);
+ }
+
+ if (ret < 0)
+ return ret;
+
+ /* Enable the ALS/IR */
+ ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
+ CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_EN);
+ if (ret < 0)
+ return ret;
+
+ /* Need to wait for conversion time if ALS/IR mode enabled */
+ mdelay(CONVERSION_TIME_MS);
+ return 0;
+}
+
+static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir)
+{
+ unsigned int lsb;
+ unsigned int msb;
+ int ret;
+
+ ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_L, &lsb);
+ if (ret < 0) {
+ dev_err(chip->dev,
+ "Error in reading register ALSIR_L err %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_U, &msb);
+ if (ret < 0) {
+ dev_err(chip->dev,
+ "Error in reading register ALSIR_U err %d\n", ret);
+ return ret;
+ }
+
+ *als_ir = ((msb & 0xF) << 8) | (lsb & 0xFF);
+ return 0;
+}
+
+static int isl29028_read_proxim(struct isl29028_chip *chip, int *prox)
+{
+ unsigned int data;
+ int ret;
+
+ ret = regmap_read(chip->regmap, ISL29028_REG_PROX_DATA, &data);
+ if (ret < 0) {
+ dev_err(chip->dev, "Error in reading register %d, error %d\n",
+ ISL29028_REG_PROX_DATA, ret);
+ return ret;
+ }
+ *prox = data;
+ return 0;
+}
+
+static int isl29028_proxim_get(struct isl29028_chip *chip, int *prox_data)
+{
+ int ret;
+
+ if (!chip->enable_prox) {
+ ret = isl29028_enable_proximity(chip, true);
+ if (ret < 0)
+ return ret;
+ chip->enable_prox = true;
+ }
+ return isl29028_read_proxim(chip, prox_data);
+}
+
+static int isl29028_als_get(struct isl29028_chip *chip, int *als_data)
+{
+ int ret;
+ int als_ir_data;
+
+ if (chip->als_ir_mode != MODE_ALS) {
+ ret = isl29028_set_als_ir_mode(chip, MODE_ALS);
+ if (ret < 0) {
+ dev_err(chip->dev,
+ "Error in enabling ALS mode err %d\n", ret);
+ return ret;
+ }
+ chip->als_ir_mode = MODE_ALS;
+ }
+
+ ret = isl29028_read_als_ir(chip, &als_ir_data);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * convert als data count to lux.
+ * if lux_scale = 125, lux = count * 0.031
+ * if lux_scale = 2000, lux = count * 0.49
+ */
+ if (chip->lux_scale == 125)
+ als_ir_data = (als_ir_data * 31) / 1000;
+ else
+ als_ir_data = (als_ir_data * 49) / 100;
+
+ *als_data = als_ir_data;
+ return 0;
+}
+
+static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data)
+{
+ int ret;
+
+ if (chip->als_ir_mode != MODE_IR) {
+ ret = isl29028_set_als_ir_mode(chip, MODE_IR);
+ if (ret < 0) {
+ dev_err(chip->dev,
+ "Error in enabling IR mode err %d\n", ret);
+ return ret;
+ }
+ chip->als_ir_mode = MODE_IR;
+ }
+ return isl29028_read_als_ir(chip, ir_data);
+}
+
+/* Channel IO */
+static int isl29028_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+ struct isl29028_chip *chip = iio_priv(indio_dev);
+ int ret = -EINVAL;
+
+ mutex_lock(&chip->lock);
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ if (mask != IIO_CHAN_INFO_SAMP_FREQ) {
+ dev_err(chip->dev,
+ "proximity: mask value 0x%08lx not supported\n",
+ mask);
+ break;
+ }
+ if (val < 1 || val > 100) {
+ dev_err(chip->dev,
+ "Samp_freq %d is not in range[1:100]\n", val);
+ break;
+ }
+ ret = isl29028_set_proxim_sampling(chip, val);
+ if (ret < 0) {
+ dev_err(chip->dev,
+ "Setting proximity samp_freq fail, err %d\n",
+ ret);
+ break;
+ }
+ chip->prox_sampling = val;
+ break;
+
+ case IIO_LIGHT:
+ if (mask != IIO_CHAN_INFO_SCALE) {
+ dev_err(chip->dev,
+ "light: mask value 0x%08lx not supported\n",
+ mask);
+ break;
+ }
+ if ((val != 125) && (val != 2000)) {
+ dev_err(chip->dev,
+ "lux scale %d is invalid [125, 2000]\n", val);
+ break;
+ }
+ ret = isl29028_set_als_scale(chip, val);
+ if (ret < 0) {
+ dev_err(chip->dev,
+ "Setting lux scale fail with error %d\n", ret);
+ break;
+ }
+ chip->lux_scale = val;
+ break;
+
+ default:
+ dev_err(chip->dev, "Unsupported channel type\n");
+ break;
+ }
+ mutex_unlock(&chip->lock);
+ return ret;
+}
+
+static int isl29028_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val, int *val2, long mask)
+{
+ struct isl29028_chip *chip = iio_priv(indio_dev);
+ int ret = -EINVAL;
+
+ mutex_lock(&chip->lock);
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_PROCESSED:
+ switch (chan->type) {
+ case IIO_LIGHT:
+ ret = isl29028_als_get(chip, val);
+ break;
+ case IIO_INTENSITY:
+ ret = isl29028_ir_get(chip, val);
+ break;
+ case IIO_PROXIMITY:
+ ret = isl29028_proxim_get(chip, val);
+ break;
+ default:
+ break;
+ }
+ if (ret < 0)
+ break;
+ ret = IIO_VAL_INT;
+ break;
+
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (chan->type != IIO_PROXIMITY)
+ break;
+ *val = chip->prox_sampling;
+ ret = IIO_VAL_INT;
+ break;
+
+ case IIO_CHAN_INFO_SCALE:
+ if (chan->type != IIO_LIGHT)
+ break;
+ *val = chip->lux_scale;
+ ret = IIO_VAL_INT;
+ break;
+
+ default:
+ dev_err(chip->dev, "mask value 0x%08lx not supported\n", mask);
+ break;
+ }
+ mutex_unlock(&chip->lock);
+ return ret;
+}
+
+static IIO_CONST_ATTR(in_proximity_sampling_frequency_available,
+ "1, 3, 5, 10, 13, 20, 83, 100");
+static IIO_CONST_ATTR(in_illuminance_scale_available, "125, 2000");
+
+#define ISL29028_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
+#define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
+static struct attribute *isl29028_attributes[] = {
+ ISL29028_CONST_ATTR(in_proximity_sampling_frequency_available),
+ ISL29028_CONST_ATTR(in_illuminance_scale_available),
+ NULL,
+};
+
+static const struct attribute_group isl29108_group = {
+ .attrs = isl29028_attributes,
+};
+
+static const struct iio_chan_spec isl29028_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ }, {
+ .type = IIO_INTENSITY,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+ }, {
+ .type = IIO_PROXIMITY,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SAMP_FREQ_SEPARATE_BIT,
+ }
+};
+
+static const struct iio_info isl29028_info = {
+ .attrs = &isl29108_group,
+ .driver_module = THIS_MODULE,
+ .read_raw = &isl29028_read_raw,
+ .write_raw = &isl29028_write_raw,
+};
+
+static int isl29028_chip_init(struct isl29028_chip *chip)
+{
+ int ret;
+
+ chip->enable_prox = false;
+ chip->prox_sampling = 20;
+ chip->lux_scale = 2000;
+ chip->als_ir_mode = MODE_NONE;
+
+ ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
+ if (ret < 0) {
+ dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n",
+ __func__, ISL29028_REG_TEST1_MODE, ret);
+ return ret;
+ }
+ ret = regmap_write(chip->regmap, ISL29028_REG_TEST2_MODE, 0x0);
+ if (ret < 0) {
+ dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n",
+ __func__, ISL29028_REG_TEST2_MODE, ret);
+ return ret;
+ }
+
+ ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0);
+ if (ret < 0) {
+ dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n",
+ __func__, ISL29028_REG_CONFIGURE, ret);
+ return ret;
+ }
+
+ ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling);
+ if (ret < 0) {
+ dev_err(chip->dev, "%s(): setting the proximity, err = %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = isl29028_set_als_scale(chip, chip->lux_scale);
+ if (ret < 0)
+ dev_err(chip->dev, "%s(): setting als scale failed, err = %d\n",
+ __func__, ret);
+ return ret;
+}
+
+static bool is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ISL29028_REG_INTERRUPT:
+ case ISL29028_REG_PROX_DATA:
+ case ISL29028_REG_ALSIR_L:
+ case ISL29028_REG_ALSIR_U:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config isl29028_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_reg = is_volatile_reg,
+ .max_register = ISL29028_NUM_REGS - 1,
+ .num_reg_defaults_raw = ISL29028_NUM_REGS,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit isl29028_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct isl29028_chip *chip;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = iio_device_alloc(sizeof(*chip));
+ if (!indio_dev) {
+ dev_err(&client->dev, "iio allocation fails\n");
+ return -ENOMEM;
+ }
+
+ chip = iio_priv(indio_dev);
+
+ i2c_set_clientdata(client, indio_dev);
+ chip->dev = &client->dev;
+ mutex_init(&chip->lock);
+
+ chip->regmap = devm_regmap_init_i2c(client, &isl29028_regmap_config);
+ if (IS_ERR(chip->regmap)) {
+ ret = PTR_ERR(chip->regmap);
+ dev_err(chip->dev, "regmap initialization failed: %d\n", ret);
+ goto exit_iio_free;
+ }
+
+ ret = isl29028_chip_init(chip);
+ if (ret < 0) {
+ dev_err(chip->dev, "chip initialization failed: %d\n", ret);
+ goto exit_iio_free;
+ }
+
+ indio_dev->info = &isl29028_info;
+ indio_dev->channels = isl29028_channels;
+ indio_dev->num_channels = ARRAY_SIZE(isl29028_channels);
+ indio_dev->name = id->name;
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ ret = iio_device_register(indio_dev);
+ if (ret < 0) {
+ dev_err(chip->dev, "iio registration fails with error %d\n",
+ ret);
+ goto exit_iio_free;
+ }
+ return 0;
+
+exit_iio_free:
+ iio_device_free(indio_dev);
+ return ret;
+}
+
+static int __devexit isl29028_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+ iio_device_unregister(indio_dev);
+ iio_device_free(indio_dev);
+ return 0;
+}
+
+static const struct i2c_device_id isl29028_id[] = {
+ {"isl29028", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, isl29028_id);
+
+static const struct of_device_id isl29028_of_match[] = {
+ { .compatible = "isil,isl29028", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, isl29028_of_match);
+
+static struct i2c_driver isl29028_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "isl29028",
+ .owner = THIS_MODULE,
+ .of_match_table = isl29028_of_match,
+ },
+ .probe = isl29028_probe,
+ .remove = __devexit_p(isl29028_remove),
+ .id_table = isl29028_id,
+};
+
+module_i2c_driver(isl29028_driver);
+
+MODULE_DESCRIPTION("ISL29028 Ambient Light and Proximity Sensor driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
index 546c95a4ea9e..9d740be43a82 100644
--- a/drivers/staging/iio/light/tsl2563.c
+++ b/drivers/staging/iio/light/tsl2563.c
@@ -35,9 +35,9 @@
#include <linux/err.h>
#include <linux/slab.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../events.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
#include "tsl2563.h"
/* Use this many bits for fraction part. */
@@ -465,7 +465,7 @@ static int tsl2563_write_raw(struct iio_dev *indio_dev,
{
struct tsl2563_chip *chip = iio_priv(indio_dev);
- if (chan->channel == 0)
+ if (chan->channel == IIO_MOD_LIGHT_BOTH)
chip->calib0 = calib_from_sysfs(val);
else
chip->calib1 = calib_from_sysfs(val);
@@ -485,7 +485,8 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev,
mutex_lock(&chip->lock);
switch (m) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_PROCESSED:
switch (chan->type) {
case IIO_LIGHT:
ret = tsl2563_get_adc(chip);
@@ -534,12 +535,14 @@ static const struct iio_chan_spec tsl2563_channels[] = {
{
.type = IIO_LIGHT,
.indexed = 1,
+ .info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT,
.channel = 0,
}, {
.type = IIO_INTENSITY,
.modified = 1,
.channel2 = IIO_MOD_LIGHT_BOTH,
- .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
.event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING) |
IIO_EV_BIT(IIO_EV_TYPE_THRESH,
@@ -548,7 +551,8 @@ static const struct iio_chan_spec tsl2563_channels[] = {
.type = IIO_INTENSITY,
.modified = 1,
.channel2 = IIO_MOD_LIGHT_IR,
- .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
}
};
@@ -710,7 +714,7 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
int err = 0;
u8 id = 0;
- indio_dev = iio_allocate_device(sizeof(*chip));
+ indio_dev = iio_device_alloc(sizeof(*chip));
if (!indio_dev)
return -ENOMEM;
@@ -797,7 +801,7 @@ fail2:
if (client->irq)
free_irq(client->irq, indio_dev);
fail1:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return err;
}
@@ -818,7 +822,7 @@ static int tsl2563_remove(struct i2c_client *client)
if (client->irq)
free_irq(client->irq, indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c
index 8671d98e0448..5e23ad5a30d5 100644
--- a/drivers/staging/iio/light/tsl2583.c
+++ b/drivers/staging/iio/light/tsl2583.c
@@ -28,7 +28,7 @@
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#define TSL258X_MAX_DEVICE_REGS 32
@@ -483,7 +483,7 @@ static int taos_chip_off(struct iio_dev *indio_dev)
static ssize_t taos_power_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", chip->taos_chip_status);
@@ -492,7 +492,7 @@ static ssize_t taos_power_state_show(struct device *dev,
static ssize_t taos_power_state_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
unsigned long value;
if (strict_strtoul(buf, 0, &value))
@@ -509,7 +509,7 @@ static ssize_t taos_power_state_store(struct device *dev,
static ssize_t taos_gain_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
char gain[4] = {0};
@@ -534,7 +534,7 @@ static ssize_t taos_gain_show(struct device *dev,
static ssize_t taos_gain_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
unsigned long value;
@@ -571,7 +571,7 @@ static ssize_t taos_gain_available_show(struct device *dev,
static ssize_t taos_als_time_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", chip->taos_settings.als_time);
@@ -580,7 +580,7 @@ static ssize_t taos_als_time_show(struct device *dev,
static ssize_t taos_als_time_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
unsigned long value;
@@ -608,7 +608,7 @@ static ssize_t taos_als_time_available_show(struct device *dev,
static ssize_t taos_als_trim_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", chip->taos_settings.als_gain_trim);
@@ -617,7 +617,7 @@ static ssize_t taos_als_trim_show(struct device *dev,
static ssize_t taos_als_trim_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
unsigned long value;
@@ -633,7 +633,7 @@ static ssize_t taos_als_trim_store(struct device *dev,
static ssize_t taos_als_cal_target_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
return sprintf(buf, "%d\n", chip->taos_settings.als_cal_target);
@@ -642,7 +642,7 @@ static ssize_t taos_als_cal_target_show(struct device *dev,
static ssize_t taos_als_cal_target_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
unsigned long value;
@@ -660,7 +660,7 @@ static ssize_t taos_lux_show(struct device *dev, struct device_attribute *attr,
{
int ret;
- ret = taos_get_lux(dev_get_drvdata(dev));
+ ret = taos_get_lux(dev_to_iio_dev(dev));
if (ret < 0)
return ret;
@@ -670,7 +670,7 @@ static ssize_t taos_lux_show(struct device *dev, struct device_attribute *attr,
static ssize_t taos_do_calibrate(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
unsigned long value;
if (strict_strtoul(buf, 0, &value))
@@ -708,7 +708,7 @@ static ssize_t taos_luxtable_show(struct device *dev,
static ssize_t taos_luxtable_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
int value[ARRAY_SIZE(taos_device_lux)*3 + 1];
int n;
@@ -815,7 +815,7 @@ static int __devinit taos_probe(struct i2c_client *clientp,
return -EOPNOTSUPP;
}
- indio_dev = iio_allocate_device(sizeof(*chip));
+ indio_dev = iio_device_alloc(sizeof(*chip));
if (indio_dev == NULL) {
ret = -ENOMEM;
dev_err(&clientp->dev, "iio allocation failed\n");
@@ -879,7 +879,7 @@ static int __devinit taos_probe(struct i2c_client *clientp,
dev_info(&clientp->dev, "Light sensor found.\n");
return 0;
fail1:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
fail2:
return ret;
}
@@ -926,7 +926,7 @@ static SIMPLE_DEV_PM_OPS(taos_pm_ops, taos_suspend, taos_resume);
static int __devexit taos_remove(struct i2c_client *client)
{
iio_device_unregister(i2c_get_clientdata(client));
- iio_free_device(i2c_get_clientdata(client));
+ iio_device_free(i2c_get_clientdata(client));
return 0;
}
diff --git a/drivers/staging/iio/light/tsl2x7x.h b/drivers/staging/iio/light/tsl2x7x.h
new file mode 100755
index 000000000000..c4acf5ff1794
--- /dev/null
+++ b/drivers/staging/iio/light/tsl2x7x.h
@@ -0,0 +1,100 @@
+/*
+ * Device driver for monitoring ambient light intensity (lux)
+ * and proximity (prox) within the TAOS TSL2X7X family of devices.
+ *
+ * Copyright (c) 2012, TAOS Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __TSL2X7X_H
+#define __TSL2X7X_H
+#include <linux/pm.h>
+
+/* Max number of segments allowable in LUX table */
+#define TSL2X7X_MAX_LUX_TABLE_SIZE 9
+#define MAX_DEFAULT_TABLE_BYTES (sizeof(int) * TSL2X7X_MAX_LUX_TABLE_SIZE)
+
+struct iio_dev;
+
+struct tsl2x7x_lux {
+ unsigned int ratio;
+ unsigned int ch0;
+ unsigned int ch1;
+};
+
+/**
+ * struct tsl2x7x_default_settings - power on defaults unless
+ * overridden by platform data.
+ * @als_time: ALS Integration time - multiple of 50mS
+ * @als_gain: Index into the ALS gain table.
+ * @als_gain_trim: default gain trim to account for
+ * aperture effects.
+ * @wait_time: Time between PRX and ALS cycles
+ * in 2.7 periods
+ * @prx_time: 5.2ms prox integration time -
+ * decrease in 2.7ms periods
+ * @prx_gain: Proximity gain index
+ * @prox_config: Prox configuration filters.
+ * @als_cal_target: Known external ALS reading for
+ * calibration.
+ * @interrupts_en: Enable/Disable - 0x00 = none, 0x10 = als,
+ * 0x20 = prx, 0x30 = bth
+ * @persistence: H/W Filters, Number of 'out of limits'
+ * ADC readings PRX/ALS.
+ * @als_thresh_low: CH0 'low' count to trigger interrupt.
+ * @als_thresh_high: CH0 'high' count to trigger interrupt.
+ * @prox_thres_low: Low threshold proximity detection.
+ * @prox_thres_high: High threshold proximity detection
+ * @prox_pulse_count: Number if proximity emitter pulses
+ * @prox_max_samples_cal: Used for prox cal.
+ */
+struct tsl2x7x_settings {
+ int als_time;
+ int als_gain;
+ int als_gain_trim;
+ int wait_time;
+ int prx_time;
+ int prox_gain;
+ int prox_config;
+ int als_cal_target;
+ u8 interrupts_en;
+ u8 persistence;
+ int als_thresh_low;
+ int als_thresh_high;
+ int prox_thres_low;
+ int prox_thres_high;
+ int prox_pulse_count;
+ int prox_max_samples_cal;
+};
+
+/**
+ * struct tsl2X7X_platform_data - Platform callback, glass and defaults
+ * @platform_power: Suspend/resume platform callback
+ * @power_on: Power on callback
+ * @power_off: Power off callback
+ * @platform_lux_table: Device specific glass coefficents
+ * @platform_default_settings: Device specific power on defaults
+ *
+ */
+struct tsl2X7X_platform_data {
+ int (*platform_power)(struct device *dev, pm_message_t);
+ int (*power_on) (struct iio_dev *indio_dev);
+ int (*power_off) (struct i2c_client *dev);
+ struct tsl2x7x_lux platform_lux_table[TSL2X7X_MAX_LUX_TABLE_SIZE];
+ struct tsl2x7x_settings *platform_default_settings;
+};
+
+#endif /* __TSL2X7X_H */
diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c
new file mode 100755
index 000000000000..c3b05a1b3ea8
--- /dev/null
+++ b/drivers/staging/iio/light/tsl2x7x_core.c
@@ -0,0 +1,2082 @@
+/*
+ * Device driver for monitoring ambient light intensity in (lux)
+ * and proximity detection (prox) within the TAOS TSL2X7X family of devices.
+ *
+ * Copyright (c) 2012, TAOS Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/iio/events.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include "tsl2x7x.h"
+
+/* Cal defs*/
+#define PROX_STAT_CAL 0
+#define PROX_STAT_SAMP 1
+#define MAX_SAMPLES_CAL 200
+
+/* TSL2X7X Device ID */
+#define TRITON_ID 0x00
+#define SWORDFISH_ID 0x30
+#define HALIBUT_ID 0x20
+
+/* Lux calculation constants */
+#define TSL2X7X_LUX_CALC_OVER_FLOW 65535
+
+/* TAOS Register definitions - note:
+ * depending on device, some of these register are not used and the
+ * register address is benign.
+ */
+/* 2X7X register offsets */
+#define TSL2X7X_MAX_CONFIG_REG 16
+
+/* Device Registers and Masks */
+#define TSL2X7X_CNTRL 0x00
+#define TSL2X7X_ALS_TIME 0X01
+#define TSL2X7X_PRX_TIME 0x02
+#define TSL2X7X_WAIT_TIME 0x03
+#define TSL2X7X_ALS_MINTHRESHLO 0X04
+#define TSL2X7X_ALS_MINTHRESHHI 0X05
+#define TSL2X7X_ALS_MAXTHRESHLO 0X06
+#define TSL2X7X_ALS_MAXTHRESHHI 0X07
+#define TSL2X7X_PRX_MINTHRESHLO 0X08
+#define TSL2X7X_PRX_MINTHRESHHI 0X09
+#define TSL2X7X_PRX_MAXTHRESHLO 0X0A
+#define TSL2X7X_PRX_MAXTHRESHHI 0X0B
+#define TSL2X7X_PERSISTENCE 0x0C
+#define TSL2X7X_PRX_CONFIG 0x0D
+#define TSL2X7X_PRX_COUNT 0x0E
+#define TSL2X7X_GAIN 0x0F
+#define TSL2X7X_NOTUSED 0x10
+#define TSL2X7X_REVID 0x11
+#define TSL2X7X_CHIPID 0x12
+#define TSL2X7X_STATUS 0x13
+#define TSL2X7X_ALS_CHAN0LO 0x14
+#define TSL2X7X_ALS_CHAN0HI 0x15
+#define TSL2X7X_ALS_CHAN1LO 0x16
+#define TSL2X7X_ALS_CHAN1HI 0x17
+#define TSL2X7X_PRX_LO 0x18
+#define TSL2X7X_PRX_HI 0x19
+
+/* tsl2X7X cmd reg masks */
+#define TSL2X7X_CMD_REG 0x80
+#define TSL2X7X_CMD_SPL_FN 0x60
+
+#define TSL2X7X_CMD_PROX_INT_CLR 0X05
+#define TSL2X7X_CMD_ALS_INT_CLR 0x06
+#define TSL2X7X_CMD_PROXALS_INT_CLR 0X07
+
+/* tsl2X7X cntrl reg masks */
+#define TSL2X7X_CNTL_ADC_ENBL 0x02
+#define TSL2X7X_CNTL_PWR_ON 0x01
+
+/* tsl2X7X status reg masks */
+#define TSL2X7X_STA_ADC_VALID 0x01
+#define TSL2X7X_STA_PRX_VALID 0x02
+#define TSL2X7X_STA_ADC_PRX_VALID (TSL2X7X_STA_ADC_VALID |\
+ TSL2X7X_STA_PRX_VALID)
+#define TSL2X7X_STA_ALS_INTR 0x10
+#define TSL2X7X_STA_PRX_INTR 0x20
+
+/* tsl2X7X cntrl reg masks */
+#define TSL2X7X_CNTL_REG_CLEAR 0x00
+#define TSL2X7X_CNTL_PROX_INT_ENBL 0X20
+#define TSL2X7X_CNTL_ALS_INT_ENBL 0X10
+#define TSL2X7X_CNTL_WAIT_TMR_ENBL 0X08
+#define TSL2X7X_CNTL_PROX_DET_ENBL 0X04
+#define TSL2X7X_CNTL_PWRON 0x01
+#define TSL2X7X_CNTL_ALSPON_ENBL 0x03
+#define TSL2X7X_CNTL_INTALSPON_ENBL 0x13
+#define TSL2X7X_CNTL_PROXPON_ENBL 0x0F
+#define TSL2X7X_CNTL_INTPROXPON_ENBL 0x2F
+
+/*Prox diode to use */
+#define TSL2X7X_DIODE0 0x10
+#define TSL2X7X_DIODE1 0x20
+#define TSL2X7X_DIODE_BOTH 0x30
+
+/* LED Power */
+#define TSL2X7X_mA100 0x00
+#define TSL2X7X_mA50 0x40
+#define TSL2X7X_mA25 0x80
+#define TSL2X7X_mA13 0xD0
+#define TSL2X7X_MAX_TIMER_CNT (0xFF)
+
+/*Common device IIO EventMask */
+#define TSL2X7X_EVENT_MASK \
+ (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \
+ IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)),
+
+#define TSL2X7X_MIN_ITIME 3
+
+/* TAOS txx2x7x Device family members */
+enum {
+ tsl2571,
+ tsl2671,
+ tmd2671,
+ tsl2771,
+ tmd2771,
+ tsl2572,
+ tsl2672,
+ tmd2672,
+ tsl2772,
+ tmd2772
+};
+
+enum {
+ TSL2X7X_CHIP_UNKNOWN = 0,
+ TSL2X7X_CHIP_WORKING = 1,
+ TSL2X7X_CHIP_SUSPENDED = 2
+};
+
+struct tsl2x7x_parse_result {
+ int integer;
+ int fract;
+};
+
+/* Per-device data */
+struct tsl2x7x_als_info {
+ u16 als_ch0;
+ u16 als_ch1;
+ u16 lux;
+};
+
+struct tsl2x7x_prox_stat {
+ int min;
+ int max;
+ int mean;
+ unsigned long stddev;
+};
+
+struct tsl2x7x_chip_info {
+ int chan_table_elements;
+ struct iio_chan_spec channel[4];
+ const struct iio_info *info;
+};
+
+struct tsl2X7X_chip {
+ kernel_ulong_t id;
+ struct mutex prox_mutex;
+ struct mutex als_mutex;
+ struct i2c_client *client;
+ u16 prox_data;
+ struct tsl2x7x_als_info als_cur_info;
+ struct tsl2x7x_settings tsl2x7x_settings;
+ struct tsl2X7X_platform_data *pdata;
+ int als_time_scale;
+ int als_saturation;
+ int tsl2x7x_chip_status;
+ u8 tsl2x7x_config[TSL2X7X_MAX_CONFIG_REG];
+ const struct tsl2x7x_chip_info *chip_info;
+ const struct iio_info *info;
+ s64 event_timestamp;
+ /* This structure is intentionally large to accommodate
+ * updates via sysfs. */
+ /* Sized to 9 = max 8 segments + 1 termination segment */
+ struct tsl2x7x_lux tsl2x7x_device_lux[TSL2X7X_MAX_LUX_TABLE_SIZE];
+};
+
+/* Different devices require different coefficents */
+static const struct tsl2x7x_lux tsl2x71_lux_table[] = {
+ { 14461, 611, 1211 },
+ { 18540, 352, 623 },
+ { 0, 0, 0 },
+};
+
+static const struct tsl2x7x_lux tmd2x71_lux_table[] = {
+ { 11635, 115, 256 },
+ { 15536, 87, 179 },
+ { 0, 0, 0 },
+};
+
+static const struct tsl2x7x_lux tsl2x72_lux_table[] = {
+ { 14013, 466, 917 },
+ { 18222, 310, 552 },
+ { 0, 0, 0 },
+};
+
+static const struct tsl2x7x_lux tmd2x72_lux_table[] = {
+ { 13218, 130, 262 },
+ { 17592, 92, 169 },
+ { 0, 0, 0 },
+};
+
+static const struct tsl2x7x_lux *tsl2x7x_default_lux_table_group[] = {
+ [tsl2571] = tsl2x71_lux_table,
+ [tsl2671] = tsl2x71_lux_table,
+ [tmd2671] = tmd2x71_lux_table,
+ [tsl2771] = tsl2x71_lux_table,
+ [tmd2771] = tmd2x71_lux_table,
+ [tsl2572] = tsl2x72_lux_table,
+ [tsl2672] = tsl2x72_lux_table,
+ [tmd2672] = tmd2x72_lux_table,
+ [tsl2772] = tsl2x72_lux_table,
+ [tmd2772] = tmd2x72_lux_table,
+};
+
+static const struct tsl2x7x_settings tsl2x7x_default_settings = {
+ .als_time = 219, /* 101 ms */
+ .als_gain = 0,
+ .prx_time = 254, /* 5.4 ms */
+ .prox_gain = 1,
+ .wait_time = 245,
+ .prox_config = 0,
+ .als_gain_trim = 1000,
+ .als_cal_target = 150,
+ .als_thresh_low = 200,
+ .als_thresh_high = 256,
+ .persistence = 255,
+ .interrupts_en = 0,
+ .prox_thres_low = 0,
+ .prox_thres_high = 512,
+ .prox_max_samples_cal = 30,
+ .prox_pulse_count = 8
+};
+
+static const s16 tsl2X7X_als_gainadj[] = {
+ 1,
+ 8,
+ 16,
+ 120
+};
+
+static const s16 tsl2X7X_prx_gainadj[] = {
+ 1,
+ 2,
+ 4,
+ 8
+};
+
+/* Channel variations */
+enum {
+ ALS,
+ PRX,
+ ALSPRX,
+ PRX2,
+ ALSPRX2,
+};
+
+static const u8 device_channel_config[] = {
+ ALS,
+ PRX,
+ PRX,
+ ALSPRX,
+ ALSPRX,
+ ALS,
+ PRX2,
+ PRX2,
+ ALSPRX2,
+ ALSPRX2
+};
+
+/**
+ * tsl2x7x_parse_buffer() - parse a decimal result from a buffer.
+ * @*buf: pointer to char buffer to parse
+ * @*result: pointer to buffer to contain
+ * resulting interger / decimal as ints.
+ *
+ */
+static int
+tsl2x7x_parse_buffer(const char *buf, struct tsl2x7x_parse_result *result)
+{
+ int integer = 0, fract = 0, fract_mult = 100000;
+ bool integer_part = true, negative = false;
+
+ if (buf[0] == '-') {
+ negative = true;
+ buf++;
+ }
+
+ while (*buf) {
+ if ('0' <= *buf && *buf <= '9') {
+ if (integer_part)
+ integer = integer*10 + *buf - '0';
+ else {
+ fract += fract_mult*(*buf - '0');
+ if (fract_mult == 1)
+ break;
+ fract_mult /= 10;
+ }
+ } else if (*buf == '\n') {
+ if (*(buf + 1) == '\0')
+ break;
+ else
+ return -EINVAL;
+ } else if (*buf == '.') {
+ integer_part = false;
+ } else {
+ return -EINVAL;
+ }
+ buf++;
+ }
+ if (negative) {
+ if (integer)
+ integer = -integer;
+ else
+ fract = -fract;
+ }
+
+ result->integer = integer;
+ result->fract = fract;
+
+ return 0;
+}
+
+/**
+ * tsl2x7x_i2c_read() - Read a byte from a register.
+ * @client: i2c client
+ * @reg: device register to read from
+ * @*val: pointer to location to store register contents.
+ *
+ */
+static int
+tsl2x7x_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
+{
+ int ret = 0;
+
+ /* select register to write */
+ ret = i2c_smbus_write_byte(client, (TSL2X7X_CMD_REG | reg));
+ if (ret < 0) {
+ dev_err(&client->dev, "%s: failed to write register %x\n"
+ , __func__, reg);
+ return ret;
+ }
+
+ /* read the data */
+ ret = i2c_smbus_read_byte(client);
+ if (ret >= 0)
+ *val = (u8)ret;
+ else
+ dev_err(&client->dev, "%s: failed to read register %x\n"
+ , __func__, reg);
+
+ return ret;
+}
+
+/**
+ * tsl2x7x_get_lux() - Reads and calculates current lux value.
+ * @indio_dev: pointer to IIO device
+ *
+ * The raw ch0 and ch1 values of the ambient light sensed in the last
+ * integration cycle are read from the device.
+ * Time scale factor array values are adjusted based on the integration time.
+ * The raw values are multiplied by a scale factor, and device gain is obtained
+ * using gain index. Limit checks are done next, then the ratio of a multiple
+ * of ch1 value, to the ch0 value, is calculated. Array tsl2x7x_device_lux[]
+ * is then scanned to find the first ratio value that is just above the ratio
+ * we just calculated. The ch0 and ch1 multiplier constants in the array are
+ * then used along with the time scale factor array values, to calculate the
+ * lux.
+ */
+static int tsl2x7x_get_lux(struct iio_dev *indio_dev)
+{
+ u16 ch0, ch1; /* separated ch0/ch1 data from device */
+ u32 lux; /* raw lux calculated from device data */
+ u64 lux64;
+ u32 ratio;
+ u8 buf[4];
+ struct tsl2x7x_lux *p;
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ int i, ret;
+ u32 ch0lux = 0;
+ u32 ch1lux = 0;
+
+ if (mutex_trylock(&chip->als_mutex) == 0)
+ return chip->als_cur_info.lux; /* busy, so return LAST VALUE */
+
+ if (chip->tsl2x7x_chip_status != TSL2X7X_CHIP_WORKING) {
+ /* device is not enabled */
+ dev_err(&chip->client->dev, "%s: device is not enabled\n",
+ __func__);
+ ret = -EBUSY ;
+ goto out_unlock;
+ }
+
+ ret = tsl2x7x_i2c_read(chip->client,
+ (TSL2X7X_CMD_REG | TSL2X7X_STATUS), &buf[0]);
+ if (ret < 0) {
+ dev_err(&chip->client->dev,
+ "%s: Failed to read STATUS Reg\n", __func__);
+ goto out_unlock;
+ }
+ /* is data new & valid */
+ if (!(buf[0] & TSL2X7X_STA_ADC_VALID)) {
+ dev_err(&chip->client->dev,
+ "%s: data not valid yet\n", __func__);
+ ret = chip->als_cur_info.lux; /* return LAST VALUE */
+ goto out_unlock;
+ }
+
+ for (i = 0; i < 4; i++) {
+ ret = tsl2x7x_i2c_read(chip->client,
+ (TSL2X7X_CMD_REG | (TSL2X7X_ALS_CHAN0LO + i)),
+ &buf[i]);
+ if (ret < 0) {
+ dev_err(&chip->client->dev,
+ "%s: failed to read. err=%x\n", __func__, ret);
+ goto out_unlock;
+ }
+ }
+
+ /* clear any existing interrupt status */
+ ret = i2c_smbus_write_byte(chip->client,
+ (TSL2X7X_CMD_REG |
+ TSL2X7X_CMD_SPL_FN |
+ TSL2X7X_CMD_ALS_INT_CLR));
+ if (ret < 0) {
+ dev_err(&chip->client->dev,
+ "%s: i2c_write_command failed - err = %d\n",
+ __func__, ret);
+ goto out_unlock; /* have no data, so return failure */
+ }
+
+ /* extract ALS/lux data */
+ ch0 = le16_to_cpup((const __le16 *)&buf[0]);
+ ch1 = le16_to_cpup((const __le16 *)&buf[2]);
+
+ chip->als_cur_info.als_ch0 = ch0;
+ chip->als_cur_info.als_ch1 = ch1;
+
+ if ((ch0 >= chip->als_saturation) || (ch1 >= chip->als_saturation)) {
+ lux = TSL2X7X_LUX_CALC_OVER_FLOW;
+ goto return_max;
+ }
+
+ if (ch0 == 0) {
+ /* have no data, so return LAST VALUE */
+ ret = chip->als_cur_info.lux;
+ goto out_unlock;
+ }
+ /* calculate ratio */
+ ratio = (ch1 << 15) / ch0;
+ /* convert to unscaled lux using the pointer to the table */
+ p = (struct tsl2x7x_lux *) chip->tsl2x7x_device_lux;
+ while (p->ratio != 0 && p->ratio < ratio)
+ p++;
+
+ if (p->ratio == 0) {
+ lux = 0;
+ } else {
+ ch0lux = DIV_ROUND_UP((ch0 * p->ch0),
+ tsl2X7X_als_gainadj[chip->tsl2x7x_settings.als_gain]);
+ ch1lux = DIV_ROUND_UP((ch1 * p->ch1),
+ tsl2X7X_als_gainadj[chip->tsl2x7x_settings.als_gain]);
+ lux = ch0lux - ch1lux;
+ }
+
+ /* note: lux is 31 bit max at this point */
+ if (ch1lux > ch0lux) {
+ dev_dbg(&chip->client->dev, "ch1lux > ch0lux-return last value\n");
+ ret = chip->als_cur_info.lux;
+ goto out_unlock;
+ }
+
+ /* adjust for active time scale */
+ if (chip->als_time_scale == 0)
+ lux = 0;
+ else
+ lux = (lux + (chip->als_time_scale >> 1)) /
+ chip->als_time_scale;
+
+ /* adjust for active gain scale
+ * The tsl2x7x_device_lux tables have a factor of 256 built-in.
+ * User-specified gain provides a multiplier.
+ * Apply user-specified gain before shifting right to retain precision.
+ * Use 64 bits to avoid overflow on multiplication.
+ * Then go back to 32 bits before division to avoid using div_u64().
+ */
+
+ lux64 = lux;
+ lux64 = lux64 * chip->tsl2x7x_settings.als_gain_trim;
+ lux64 >>= 8;
+ lux = lux64;
+ lux = (lux + 500) / 1000;
+
+ if (lux > TSL2X7X_LUX_CALC_OVER_FLOW) /* check for overflow */
+ lux = TSL2X7X_LUX_CALC_OVER_FLOW;
+
+ /* Update the structure with the latest lux. */
+return_max:
+ chip->als_cur_info.lux = lux;
+ ret = lux;
+
+out_unlock:
+ mutex_unlock(&chip->als_mutex);
+
+ return ret;
+}
+
+/**
+ * tsl2x7x_get_prox() - Reads proximity data registers and updates
+ * chip->prox_data.
+ *
+ * @indio_dev: pointer to IIO device
+ */
+static int tsl2x7x_get_prox(struct iio_dev *indio_dev)
+{
+ int i;
+ int ret;
+ u8 status;
+ u8 chdata[2];
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+
+ if (mutex_trylock(&chip->prox_mutex) == 0) {
+ dev_err(&chip->client->dev,
+ "%s: Can't get prox mutex\n", __func__);
+ return -EBUSY;
+ }
+
+ ret = tsl2x7x_i2c_read(chip->client,
+ (TSL2X7X_CMD_REG | TSL2X7X_STATUS), &status);
+ if (ret < 0) {
+ dev_err(&chip->client->dev,
+ "%s: i2c err=%d\n", __func__, ret);
+ goto prox_poll_err;
+ }
+
+ switch (chip->id) {
+ case tsl2571:
+ case tsl2671:
+ case tmd2671:
+ case tsl2771:
+ case tmd2771:
+ if (!(status & TSL2X7X_STA_ADC_VALID))
+ goto prox_poll_err;
+ break;
+ case tsl2572:
+ case tsl2672:
+ case tmd2672:
+ case tsl2772:
+ case tmd2772:
+ if (!(status & TSL2X7X_STA_PRX_VALID))
+ goto prox_poll_err;
+ break;
+ }
+
+ for (i = 0; i < 2; i++) {
+ ret = tsl2x7x_i2c_read(chip->client,
+ (TSL2X7X_CMD_REG |
+ (TSL2X7X_PRX_LO + i)), &chdata[i]);
+ if (ret < 0)
+ goto prox_poll_err;
+ }
+
+ chip->prox_data =
+ le16_to_cpup((const __le16 *)&chdata[0]);
+
+prox_poll_err:
+
+ mutex_unlock(&chip->prox_mutex);
+
+ return chip->prox_data;
+}
+
+/**
+ * tsl2x7x_defaults() - Populates the device nominal operating parameters
+ * with those provided by a 'platform' data struct or
+ * with prefined defaults.
+ *
+ * @chip: pointer to device structure.
+ */
+static void tsl2x7x_defaults(struct tsl2X7X_chip *chip)
+{
+ /* If Operational settings defined elsewhere.. */
+ if (chip->pdata && chip->pdata->platform_default_settings != 0)
+ memcpy(&(chip->tsl2x7x_settings),
+ chip->pdata->platform_default_settings,
+ sizeof(tsl2x7x_default_settings));
+ else
+ memcpy(&(chip->tsl2x7x_settings),
+ &tsl2x7x_default_settings,
+ sizeof(tsl2x7x_default_settings));
+
+ /* Load up the proper lux table. */
+ if (chip->pdata && chip->pdata->platform_lux_table[0].ratio != 0)
+ memcpy(chip->tsl2x7x_device_lux,
+ chip->pdata->platform_lux_table,
+ sizeof(chip->pdata->platform_lux_table));
+ else
+ memcpy(chip->tsl2x7x_device_lux,
+ (struct tsl2x7x_lux *)tsl2x7x_default_lux_table_group[chip->id],
+ MAX_DEFAULT_TABLE_BYTES);
+}
+
+/**
+ * tsl2x7x_als_calibrate() - Obtain single reading and calculate
+ * the als_gain_trim.
+ *
+ * @indio_dev: pointer to IIO device
+ */
+static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev)
+{
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ u8 reg_val;
+ int gain_trim_val;
+ int ret;
+ int lux_val;
+
+ ret = i2c_smbus_write_byte(chip->client,
+ (TSL2X7X_CMD_REG | TSL2X7X_CNTRL));
+ if (ret < 0) {
+ dev_err(&chip->client->dev,
+ "%s: failed to write CNTRL register, ret=%d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ reg_val = i2c_smbus_read_byte(chip->client);
+ if ((reg_val & (TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PWR_ON))
+ != (TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PWR_ON)) {
+ dev_err(&chip->client->dev,
+ "%s: failed: ADC not enabled\n", __func__);
+ return -1;
+ }
+
+ ret = i2c_smbus_write_byte(chip->client,
+ (TSL2X7X_CMD_REG | TSL2X7X_CNTRL));
+ if (ret < 0) {
+ dev_err(&chip->client->dev,
+ "%s: failed to write ctrl reg: ret=%d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ reg_val = i2c_smbus_read_byte(chip->client);
+ if ((reg_val & TSL2X7X_STA_ADC_VALID) != TSL2X7X_STA_ADC_VALID) {
+ dev_err(&chip->client->dev,
+ "%s: failed: STATUS - ADC not valid.\n", __func__);
+ return -ENODATA;
+ }
+
+ lux_val = tsl2x7x_get_lux(indio_dev);
+ if (lux_val < 0) {
+ dev_err(&chip->client->dev,
+ "%s: failed to get lux\n", __func__);
+ return lux_val;
+ }
+
+ gain_trim_val = (((chip->tsl2x7x_settings.als_cal_target)
+ * chip->tsl2x7x_settings.als_gain_trim) / lux_val);
+ if ((gain_trim_val < 250) || (gain_trim_val > 4000))
+ return -ERANGE;
+
+ chip->tsl2x7x_settings.als_gain_trim = gain_trim_val;
+ dev_info(&chip->client->dev,
+ "%s als_calibrate completed\n", chip->client->name);
+
+ return (int) gain_trim_val;
+}
+
+static int tsl2x7x_chip_on(struct iio_dev *indio_dev)
+{
+ int i;
+ int ret = 0;
+ u8 *dev_reg;
+ u8 utmp;
+ int als_count;
+ int als_time;
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ u8 reg_val = 0;
+
+ if (chip->pdata && chip->pdata->power_on)
+ chip->pdata->power_on(indio_dev);
+
+ /* Non calculated parameters */
+ chip->tsl2x7x_config[TSL2X7X_PRX_TIME] =
+ chip->tsl2x7x_settings.prx_time;
+ chip->tsl2x7x_config[TSL2X7X_WAIT_TIME] =
+ chip->tsl2x7x_settings.wait_time;
+ chip->tsl2x7x_config[TSL2X7X_PRX_CONFIG] =
+ chip->tsl2x7x_settings.prox_config;
+
+ chip->tsl2x7x_config[TSL2X7X_ALS_MINTHRESHLO] =
+ (chip->tsl2x7x_settings.als_thresh_low) & 0xFF;
+ chip->tsl2x7x_config[TSL2X7X_ALS_MINTHRESHHI] =
+ (chip->tsl2x7x_settings.als_thresh_low >> 8) & 0xFF;
+ chip->tsl2x7x_config[TSL2X7X_ALS_MAXTHRESHLO] =
+ (chip->tsl2x7x_settings.als_thresh_high) & 0xFF;
+ chip->tsl2x7x_config[TSL2X7X_ALS_MAXTHRESHHI] =
+ (chip->tsl2x7x_settings.als_thresh_high >> 8) & 0xFF;
+ chip->tsl2x7x_config[TSL2X7X_PERSISTENCE] =
+ chip->tsl2x7x_settings.persistence;
+
+ chip->tsl2x7x_config[TSL2X7X_PRX_COUNT] =
+ chip->tsl2x7x_settings.prox_pulse_count;
+ chip->tsl2x7x_config[TSL2X7X_PRX_MINTHRESHLO] =
+ chip->tsl2x7x_settings.prox_thres_low;
+ chip->tsl2x7x_config[TSL2X7X_PRX_MAXTHRESHLO] =
+ chip->tsl2x7x_settings.prox_thres_high;
+
+ /* and make sure we're not already on */
+ if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING) {
+ /* if forcing a register update - turn off, then on */
+ dev_info(&chip->client->dev, "device is already enabled\n");
+ return -EINVAL;
+ }
+
+ /* determine als integration regster */
+ als_count = (chip->tsl2x7x_settings.als_time * 100 + 135) / 270;
+ if (als_count == 0)
+ als_count = 1; /* ensure at least one cycle */
+
+ /* convert back to time (encompasses overrides) */
+ als_time = (als_count * 27 + 5) / 10;
+ chip->tsl2x7x_config[TSL2X7X_ALS_TIME] = 256 - als_count;
+
+ /* Set the gain based on tsl2x7x_settings struct */
+ chip->tsl2x7x_config[TSL2X7X_GAIN] =
+ (chip->tsl2x7x_settings.als_gain |
+ (TSL2X7X_mA100 | TSL2X7X_DIODE1)
+ | ((chip->tsl2x7x_settings.prox_gain) << 2));
+
+ /* set chip struct re scaling and saturation */
+ chip->als_saturation = als_count * 922; /* 90% of full scale */
+ chip->als_time_scale = (als_time + 25) / 50;
+
+ /* TSL2X7X Specific power-on / adc enable sequence
+ * Power on the device 1st. */
+ utmp = TSL2X7X_CNTL_PWR_ON;
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL2X7X_CMD_REG | TSL2X7X_CNTRL, utmp);
+ if (ret < 0) {
+ dev_err(&chip->client->dev,
+ "%s: failed on CNTRL reg.\n", __func__);
+ return ret;
+ }
+
+ /* Use the following shadow copy for our delay before enabling ADC.
+ * Write all the registers. */
+ for (i = 0, dev_reg = chip->tsl2x7x_config;
+ i < TSL2X7X_MAX_CONFIG_REG; i++) {
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL2X7X_CMD_REG + i, *dev_reg++);
+ if (ret < 0) {
+ dev_err(&chip->client->dev,
+ "%s: failed on write to reg %d.\n", __func__, i);
+ return ret;
+ }
+ }
+
+ mdelay(3); /* Power-on settling time */
+
+ /* NOW enable the ADC
+ * initialize the desired mode of operation */
+ utmp = TSL2X7X_CNTL_PWR_ON |
+ TSL2X7X_CNTL_ADC_ENBL |
+ TSL2X7X_CNTL_PROX_DET_ENBL;
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL2X7X_CMD_REG | TSL2X7X_CNTRL, utmp);
+ if (ret < 0) {
+ dev_err(&chip->client->dev,
+ "%s: failed on 2nd CTRL reg.\n", __func__);
+ return ret;
+ }
+
+ chip->tsl2x7x_chip_status = TSL2X7X_CHIP_WORKING;
+
+ if (chip->tsl2x7x_settings.interrupts_en != 0) {
+ dev_info(&chip->client->dev, "Setting Up Interrupt(s)\n");
+
+ reg_val = TSL2X7X_CNTL_PWR_ON | TSL2X7X_CNTL_ADC_ENBL;
+ if ((chip->tsl2x7x_settings.interrupts_en == 0x20) ||
+ (chip->tsl2x7x_settings.interrupts_en == 0x30))
+ reg_val |= TSL2X7X_CNTL_PROX_DET_ENBL;
+
+ reg_val |= chip->tsl2x7x_settings.interrupts_en;
+ ret = i2c_smbus_write_byte_data(chip->client,
+ (TSL2X7X_CMD_REG | TSL2X7X_CNTRL), reg_val);
+ if (ret < 0)
+ dev_err(&chip->client->dev,
+ "%s: failed in tsl2x7x_IOCTL_INT_SET.\n",
+ __func__);
+
+ /* Clear out any initial interrupts */
+ ret = i2c_smbus_write_byte(chip->client,
+ TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN |
+ TSL2X7X_CMD_PROXALS_INT_CLR);
+ if (ret < 0) {
+ dev_err(&chip->client->dev,
+ "%s: Failed to clear Int status\n",
+ __func__);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int tsl2x7x_chip_off(struct iio_dev *indio_dev)
+{
+ int ret;
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+
+ /* turn device off */
+ chip->tsl2x7x_chip_status = TSL2X7X_CHIP_SUSPENDED;
+
+ ret = i2c_smbus_write_byte_data(chip->client,
+ TSL2X7X_CMD_REG | TSL2X7X_CNTRL, 0x00);
+
+ if (chip->pdata && chip->pdata->power_off)
+ chip->pdata->power_off(chip->client);
+
+ return ret;
+}
+
+/**
+ * tsl2x7x_invoke_change
+ * @indio_dev: pointer to IIO device
+ *
+ * Obtain and lock both ALS and PROX resources,
+ * determine and save device state (On/Off),
+ * cycle device to implement updated parameter,
+ * put device back into proper state, and unlock
+ * resource.
+ */
+static
+int tsl2x7x_invoke_change(struct iio_dev *indio_dev)
+{
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ int device_status = chip->tsl2x7x_chip_status;
+
+ mutex_lock(&chip->als_mutex);
+ mutex_lock(&chip->prox_mutex);
+
+ if (device_status == TSL2X7X_CHIP_WORKING)
+ tsl2x7x_chip_off(indio_dev);
+
+ tsl2x7x_chip_on(indio_dev);
+
+ if (device_status != TSL2X7X_CHIP_WORKING)
+ tsl2x7x_chip_off(indio_dev);
+
+ mutex_unlock(&chip->prox_mutex);
+ mutex_unlock(&chip->als_mutex);
+
+ return 0;
+}
+
+static
+void tsl2x7x_prox_calculate(int *data, int length,
+ struct tsl2x7x_prox_stat *statP)
+{
+ int i;
+ int sample_sum;
+ int tmp;
+
+ if (length == 0)
+ length = 1;
+
+ sample_sum = 0;
+ statP->min = INT_MAX;
+ statP->max = INT_MIN;
+ for (i = 0; i < length; i++) {
+ sample_sum += data[i];
+ statP->min = min(statP->min, data[i]);
+ statP->max = max(statP->max, data[i]);
+ }
+
+ statP->mean = sample_sum / length;
+ sample_sum = 0;
+ for (i = 0; i < length; i++) {
+ tmp = data[i] - statP->mean;
+ sample_sum += tmp * tmp;
+ }
+ statP->stddev = int_sqrt((long)sample_sum)/length;
+}
+
+/**
+ * tsl2x7x_prox_cal() - Calculates std. and sets thresholds.
+ * @indio_dev: pointer to IIO device
+ *
+ * Calculates a standard deviation based on the samples,
+ * and sets the threshold accordingly.
+ */
+static void tsl2x7x_prox_cal(struct iio_dev *indio_dev)
+{
+ int prox_history[MAX_SAMPLES_CAL + 1];
+ int i;
+ struct tsl2x7x_prox_stat prox_stat_data[2];
+ struct tsl2x7x_prox_stat *calP;
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ u8 tmp_irq_settings;
+ u8 current_state = chip->tsl2x7x_chip_status;
+
+ if (chip->tsl2x7x_settings.prox_max_samples_cal > MAX_SAMPLES_CAL) {
+ dev_err(&chip->client->dev,
+ "%s: max prox samples cal is too big: %d\n",
+ __func__, chip->tsl2x7x_settings.prox_max_samples_cal);
+ chip->tsl2x7x_settings.prox_max_samples_cal = MAX_SAMPLES_CAL;
+ }
+
+ /* have to stop to change settings */
+ tsl2x7x_chip_off(indio_dev);
+
+ /* Enable proximity detection save just in case prox not wanted yet*/
+ tmp_irq_settings = chip->tsl2x7x_settings.interrupts_en;
+ chip->tsl2x7x_settings.interrupts_en |= TSL2X7X_CNTL_PROX_INT_ENBL;
+
+ /*turn on device if not already on*/
+ tsl2x7x_chip_on(indio_dev);
+
+ /*gather the samples*/
+ for (i = 0; i < chip->tsl2x7x_settings.prox_max_samples_cal; i++) {
+ mdelay(15);
+ tsl2x7x_get_prox(indio_dev);
+ prox_history[i] = chip->prox_data;
+ dev_info(&chip->client->dev, "2 i=%d prox data= %d\n",
+ i, chip->prox_data);
+ }
+
+ tsl2x7x_chip_off(indio_dev);
+ calP = &prox_stat_data[PROX_STAT_CAL];
+ tsl2x7x_prox_calculate(prox_history,
+ chip->tsl2x7x_settings.prox_max_samples_cal, calP);
+ chip->tsl2x7x_settings.prox_thres_high = (calP->max << 1) - calP->mean;
+
+ dev_info(&chip->client->dev, " cal min=%d mean=%d max=%d\n",
+ calP->min, calP->mean, calP->max);
+ dev_info(&chip->client->dev,
+ "%s proximity threshold set to %d\n",
+ chip->client->name, chip->tsl2x7x_settings.prox_thres_high);
+
+ /* back to the way they were */
+ chip->tsl2x7x_settings.interrupts_en = tmp_irq_settings;
+ if (current_state == TSL2X7X_CHIP_WORKING)
+ tsl2x7x_chip_on(indio_dev);
+}
+
+static ssize_t tsl2x7x_power_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", chip->tsl2x7x_chip_status);
+}
+
+static ssize_t tsl2x7x_power_state_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ bool value;
+
+ if (strtobool(buf, &value))
+ return -EINVAL;
+
+ if (value)
+ tsl2x7x_chip_on(indio_dev);
+ else
+ tsl2x7x_chip_off(indio_dev);
+
+ return len;
+}
+
+static ssize_t tsl2x7x_gain_available_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
+
+ switch (chip->id) {
+ case tsl2571:
+ case tsl2671:
+ case tmd2671:
+ case tsl2771:
+ case tmd2771:
+ return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 128");
+ break;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 120");
+}
+
+static ssize_t tsl2x7x_prox_gain_available_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", "1 2 4 8");
+}
+
+static ssize_t tsl2x7x_als_time_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
+ int y, z;
+
+ y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.als_time) + 1;
+ z = y * TSL2X7X_MIN_ITIME;
+ y /= 1000;
+ z %= 1000;
+
+ return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z);
+}
+
+static ssize_t tsl2x7x_als_time_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ struct tsl2x7x_parse_result result;
+
+ result.integer = 0;
+ result.fract = 0;
+
+ tsl2x7x_parse_buffer(buf, &result);
+
+ result.fract /= 1000;
+ result.fract /= 3;
+ chip->tsl2x7x_settings.als_time =
+ (TSL2X7X_MAX_TIMER_CNT - (u8)result.fract);
+
+ dev_info(&chip->client->dev, "%s: als time = %d",
+ __func__, chip->tsl2x7x_settings.als_time);
+
+ tsl2x7x_invoke_change(indio_dev);
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static IIO_CONST_ATTR(in_illuminance0_integration_time_available,
+ ".00272 - .696");
+
+static ssize_t tsl2x7x_als_cal_target_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ chip->tsl2x7x_settings.als_cal_target);
+}
+
+static ssize_t tsl2x7x_als_cal_target_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ unsigned long value;
+
+ if (kstrtoul(buf, 0, &value))
+ return -EINVAL;
+
+ if (value)
+ chip->tsl2x7x_settings.als_cal_target = value;
+
+ tsl2x7x_invoke_change(indio_dev);
+
+ return len;
+}
+
+/* persistence settings */
+static ssize_t tsl2x7x_als_persistence_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
+ int y, z, filter_delay;
+
+ /* Determine integration time */
+ y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.als_time) + 1;
+ z = y * TSL2X7X_MIN_ITIME;
+ filter_delay = z * (chip->tsl2x7x_settings.persistence & 0x0F);
+ y = (filter_delay / 1000);
+ z = (filter_delay % 1000);
+
+ return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z);
+}
+
+static ssize_t tsl2x7x_als_persistence_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ struct tsl2x7x_parse_result result;
+ int y, z, filter_delay;
+
+ result.integer = 0;
+ result.fract = 0;
+ tsl2x7x_parse_buffer(buf, &result);
+
+ result.fract /= 1000;
+ y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.als_time) + 1;
+ z = y * TSL2X7X_MIN_ITIME;
+
+ filter_delay =
+ DIV_ROUND_UP(((result.integer * 1000) + result.fract), z);
+
+ chip->tsl2x7x_settings.persistence &= 0xF0;
+ chip->tsl2x7x_settings.persistence |= (filter_delay & 0x0F);
+
+ dev_info(&chip->client->dev, "%s: als persistence = %d",
+ __func__, filter_delay);
+
+ tsl2x7x_invoke_change(indio_dev);
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static ssize_t tsl2x7x_prox_persistence_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
+ int y, z, filter_delay;
+
+ /* Determine integration time */
+ y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.prx_time) + 1;
+ z = y * TSL2X7X_MIN_ITIME;
+ filter_delay = z * ((chip->tsl2x7x_settings.persistence & 0xF0) >> 4);
+ y = (filter_delay / 1000);
+ z = (filter_delay % 1000);
+
+ return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z);
+}
+
+static ssize_t tsl2x7x_prox_persistence_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ struct tsl2x7x_parse_result result;
+ int y, z, filter_delay;
+
+ result.integer = 0;
+ result.fract = 0;
+ tsl2x7x_parse_buffer(buf, &result);
+
+ result.fract /= 1000;
+ y = (TSL2X7X_MAX_TIMER_CNT - (u8)chip->tsl2x7x_settings.prx_time) + 1;
+ z = y * TSL2X7X_MIN_ITIME;
+
+ filter_delay =
+ DIV_ROUND_UP(((result.integer * 1000) + result.fract), z);
+
+ chip->tsl2x7x_settings.persistence &= 0x0F;
+ chip->tsl2x7x_settings.persistence |= ((filter_delay << 4) & 0xF0);
+
+ dev_info(&chip->client->dev, "%s: prox persistence = %d",
+ __func__, filter_delay);
+
+ tsl2x7x_invoke_change(indio_dev);
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static ssize_t tsl2x7x_do_calibrate(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ bool value;
+
+ if (strtobool(buf, &value))
+ return -EINVAL;
+
+ if (value)
+ tsl2x7x_als_calibrate(indio_dev);
+
+ tsl2x7x_invoke_change(indio_dev);
+
+ return len;
+}
+
+static ssize_t tsl2x7x_luxtable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev));
+ int i = 0;
+ int offset = 0;
+
+ while (i < (TSL2X7X_MAX_LUX_TABLE_SIZE * 3)) {
+ offset += snprintf(buf + offset, PAGE_SIZE, "%d,%d,%d,",
+ chip->tsl2x7x_device_lux[i].ratio,
+ chip->tsl2x7x_device_lux[i].ch0,
+ chip->tsl2x7x_device_lux[i].ch1);
+ if (chip->tsl2x7x_device_lux[i].ratio == 0) {
+ /* We just printed the first "0" entry.
+ * Now get rid of the extra "," and break. */
+ offset--;
+ break;
+ }
+ i++;
+ }
+
+ offset += snprintf(buf + offset, PAGE_SIZE, "\n");
+ return offset;
+}
+
+static ssize_t tsl2x7x_luxtable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ int value[ARRAY_SIZE(chip->tsl2x7x_device_lux)*3 + 1];
+ int n;
+
+ get_options(buf, ARRAY_SIZE(value), value);
+
+ /* We now have an array of ints starting at value[1], and
+ * enumerated by value[0].
+ * We expect each group of three ints is one table entry,
+ * and the last table entry is all 0.
+ */
+ n = value[0];
+ if ((n % 3) || n < 6 ||
+ n > ((ARRAY_SIZE(chip->tsl2x7x_device_lux) - 1) * 3)) {
+ dev_info(dev, "LUX TABLE INPUT ERROR 1 Value[0]=%d\n", n);
+ return -EINVAL;
+ }
+
+ if ((value[(n - 2)] | value[(n - 1)] | value[n]) != 0) {
+ dev_info(dev, "LUX TABLE INPUT ERROR 2 Value[0]=%d\n", n);
+ return -EINVAL;
+ }
+
+ if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING)
+ tsl2x7x_chip_off(indio_dev);
+
+ /* Zero out the table */
+ memset(chip->tsl2x7x_device_lux, 0, sizeof(chip->tsl2x7x_device_lux));
+ memcpy(chip->tsl2x7x_device_lux, &value[1], (value[0] * 4));
+
+ tsl2x7x_invoke_change(indio_dev);
+
+ return len;
+}
+
+static ssize_t tsl2x7x_do_prox_calibrate(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ bool value;
+
+ if (strtobool(buf, &value))
+ return -EINVAL;
+
+ if (value)
+ tsl2x7x_prox_cal(indio_dev);
+
+ tsl2x7x_invoke_change(indio_dev);
+
+ return len;
+}
+
+static int tsl2x7x_read_interrupt_config(struct iio_dev *indio_dev,
+ u64 event_code)
+{
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ int ret;
+
+ if (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code) == IIO_INTENSITY)
+ ret = !!(chip->tsl2x7x_settings.interrupts_en & 0x10);
+ else
+ ret = !!(chip->tsl2x7x_settings.interrupts_en & 0x20);
+
+ return ret;
+}
+
+static int tsl2x7x_write_interrupt_config(struct iio_dev *indio_dev,
+ u64 event_code,
+ int val)
+{
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+
+ if (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code) == IIO_INTENSITY) {
+ if (val)
+ chip->tsl2x7x_settings.interrupts_en |= 0x10;
+ else
+ chip->tsl2x7x_settings.interrupts_en &= 0x20;
+ } else {
+ if (val)
+ chip->tsl2x7x_settings.interrupts_en |= 0x20;
+ else
+ chip->tsl2x7x_settings.interrupts_en &= 0x10;
+ }
+
+ tsl2x7x_invoke_change(indio_dev);
+
+ return 0;
+}
+
+static int tsl2x7x_write_thresh(struct iio_dev *indio_dev,
+ u64 event_code,
+ int val)
+{
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+
+ if (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code) == IIO_INTENSITY) {
+ switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+ case IIO_EV_DIR_RISING:
+ chip->tsl2x7x_settings.als_thresh_high = val;
+ break;
+ case IIO_EV_DIR_FALLING:
+ chip->tsl2x7x_settings.als_thresh_low = val;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+ case IIO_EV_DIR_RISING:
+ chip->tsl2x7x_settings.prox_thres_high = val;
+ break;
+ case IIO_EV_DIR_FALLING:
+ chip->tsl2x7x_settings.prox_thres_low = val;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ tsl2x7x_invoke_change(indio_dev);
+
+ return 0;
+}
+
+static int tsl2x7x_read_thresh(struct iio_dev *indio_dev,
+ u64 event_code,
+ int *val)
+{
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+
+ if (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code) == IIO_INTENSITY) {
+ switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+ case IIO_EV_DIR_RISING:
+ *val = chip->tsl2x7x_settings.als_thresh_high;
+ break;
+ case IIO_EV_DIR_FALLING:
+ *val = chip->tsl2x7x_settings.als_thresh_low;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+ case IIO_EV_DIR_RISING:
+ *val = chip->tsl2x7x_settings.prox_thres_high;
+ break;
+ case IIO_EV_DIR_FALLING:
+ *val = chip->tsl2x7x_settings.prox_thres_low;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int tsl2x7x_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long mask)
+{
+ int ret = -EINVAL;
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ switch (chan->type) {
+ case IIO_LIGHT:
+ tsl2x7x_get_lux(indio_dev);
+ *val = chip->als_cur_info.lux;
+ ret = IIO_VAL_INT;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ break;
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_INTENSITY:
+ tsl2x7x_get_lux(indio_dev);
+ if (chan->channel == 0)
+ *val = chip->als_cur_info.als_ch0;
+ else
+ *val = chip->als_cur_info.als_ch1;
+ ret = IIO_VAL_INT;
+ break;
+ case IIO_PROXIMITY:
+ tsl2x7x_get_prox(indio_dev);
+ *val = chip->prox_data;
+ ret = IIO_VAL_INT;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ break;
+ case IIO_CHAN_INFO_CALIBSCALE:
+ if (chan->type == IIO_LIGHT)
+ *val =
+ tsl2X7X_als_gainadj[chip->tsl2x7x_settings.als_gain];
+ else
+ *val =
+ tsl2X7X_prx_gainadj[chip->tsl2x7x_settings.prox_gain];
+ ret = IIO_VAL_INT;
+ break;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ *val = chip->tsl2x7x_settings.als_gain_trim;
+ ret = IIO_VAL_INT;
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int tsl2x7x_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_CALIBSCALE:
+ if (chan->type == IIO_INTENSITY) {
+ switch (val) {
+ case 1:
+ chip->tsl2x7x_settings.als_gain = 0;
+ break;
+ case 8:
+ chip->tsl2x7x_settings.als_gain = 1;
+ break;
+ case 16:
+ chip->tsl2x7x_settings.als_gain = 2;
+ break;
+ case 120:
+ switch (chip->id) {
+ case tsl2572:
+ case tsl2672:
+ case tmd2672:
+ case tsl2772:
+ case tmd2772:
+ return -EINVAL;
+ break;
+ }
+ chip->tsl2x7x_settings.als_gain = 3;
+ break;
+ case 128:
+ switch (chip->id) {
+ case tsl2571:
+ case tsl2671:
+ case tmd2671:
+ case tsl2771:
+ case tmd2771:
+ return -EINVAL;
+ break;
+ }
+ chip->tsl2x7x_settings.als_gain = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ switch (val) {
+ case 1:
+ chip->tsl2x7x_settings.prox_gain = 0;
+ break;
+ case 2:
+ chip->tsl2x7x_settings.prox_gain = 1;
+ break;
+ case 4:
+ chip->tsl2x7x_settings.prox_gain = 2;
+ break;
+ case 8:
+ chip->tsl2x7x_settings.prox_gain = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ break;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ chip->tsl2x7x_settings.als_gain_trim = val;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ tsl2x7x_invoke_change(indio_dev);
+
+ return 0;
+}
+
+static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
+ tsl2x7x_power_state_show, tsl2x7x_power_state_store);
+
+static DEVICE_ATTR(in_proximity0_calibscale_available, S_IRUGO,
+ tsl2x7x_prox_gain_available_show, NULL);
+
+static DEVICE_ATTR(in_illuminance0_calibscale_available, S_IRUGO,
+ tsl2x7x_gain_available_show, NULL);
+
+static DEVICE_ATTR(in_illuminance0_integration_time, S_IRUGO | S_IWUSR,
+ tsl2x7x_als_time_show, tsl2x7x_als_time_store);
+
+static DEVICE_ATTR(in_illuminance0_target_input, S_IRUGO | S_IWUSR,
+ tsl2x7x_als_cal_target_show, tsl2x7x_als_cal_target_store);
+
+static DEVICE_ATTR(in_illuminance0_calibrate, S_IWUSR, NULL,
+ tsl2x7x_do_calibrate);
+
+static DEVICE_ATTR(in_proximity0_calibrate, S_IWUSR, NULL,
+ tsl2x7x_do_prox_calibrate);
+
+static DEVICE_ATTR(in_illuminance0_lux_table, S_IRUGO | S_IWUSR,
+ tsl2x7x_luxtable_show, tsl2x7x_luxtable_store);
+
+static DEVICE_ATTR(in_intensity0_thresh_period, S_IRUGO | S_IWUSR,
+ tsl2x7x_als_persistence_show, tsl2x7x_als_persistence_store);
+
+static DEVICE_ATTR(in_proximity0_thresh_period, S_IRUGO | S_IWUSR,
+ tsl2x7x_prox_persistence_show, tsl2x7x_prox_persistence_store);
+
+/* Use the default register values to identify the Taos device */
+static int tsl2x7x_device_id(unsigned char *id, int target)
+{
+ switch (target) {
+ case tsl2571:
+ case tsl2671:
+ case tsl2771:
+ return ((*id & 0xf0) == TRITON_ID);
+ break;
+ case tmd2671:
+ case tmd2771:
+ return ((*id & 0xf0) == HALIBUT_ID);
+ break;
+ case tsl2572:
+ case tsl2672:
+ case tmd2672:
+ case tsl2772:
+ case tmd2772:
+ return ((*id & 0xf0) == SWORDFISH_ID);
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static irqreturn_t tsl2x7x_event_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ s64 timestamp = iio_get_time_ns();
+ int ret;
+ u8 value;
+
+ value = i2c_smbus_read_byte_data(chip->client,
+ TSL2X7X_CMD_REG | TSL2X7X_STATUS);
+
+ /* What type of interrupt do we need to process */
+ if (value & TSL2X7X_STA_PRX_INTR) {
+ tsl2x7x_get_prox(indio_dev); /* freshen data for ABI */
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ timestamp);
+ }
+
+ if (value & TSL2X7X_STA_ALS_INTR) {
+ tsl2x7x_get_lux(indio_dev); /* freshen data for ABI */
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_LIGHT,
+ 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ timestamp);
+ }
+ /* Clear interrupt now that we have handled it. */
+ ret = i2c_smbus_write_byte(chip->client,
+ TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN |
+ TSL2X7X_CMD_PROXALS_INT_CLR);
+ if (ret < 0)
+ dev_err(&chip->client->dev,
+ "%s: Failed to clear irq from event handler. err = %d\n",
+ __func__, ret);
+
+ return IRQ_HANDLED;
+}
+
+static struct attribute *tsl2x7x_ALS_device_attrs[] = {
+ &dev_attr_power_state.attr,
+ &dev_attr_in_illuminance0_calibscale_available.attr,
+ &dev_attr_in_illuminance0_integration_time.attr,
+ &iio_const_attr_in_illuminance0_integration_time_available\
+ .dev_attr.attr,
+ &dev_attr_in_illuminance0_target_input.attr,
+ &dev_attr_in_illuminance0_calibrate.attr,
+ &dev_attr_in_illuminance0_lux_table.attr,
+ NULL
+};
+
+static struct attribute *tsl2x7x_PRX_device_attrs[] = {
+ &dev_attr_power_state.attr,
+ &dev_attr_in_proximity0_calibrate.attr,
+ NULL
+};
+
+static struct attribute *tsl2x7x_ALSPRX_device_attrs[] = {
+ &dev_attr_power_state.attr,
+ &dev_attr_in_illuminance0_calibscale_available.attr,
+ &dev_attr_in_illuminance0_integration_time.attr,
+ &iio_const_attr_in_illuminance0_integration_time_available\
+ .dev_attr.attr,
+ &dev_attr_in_illuminance0_target_input.attr,
+ &dev_attr_in_illuminance0_calibrate.attr,
+ &dev_attr_in_illuminance0_lux_table.attr,
+ &dev_attr_in_proximity0_calibrate.attr,
+ NULL
+};
+
+static struct attribute *tsl2x7x_PRX2_device_attrs[] = {
+ &dev_attr_power_state.attr,
+ &dev_attr_in_proximity0_calibrate.attr,
+ &dev_attr_in_proximity0_calibscale_available.attr,
+ NULL
+};
+
+static struct attribute *tsl2x7x_ALSPRX2_device_attrs[] = {
+ &dev_attr_power_state.attr,
+ &dev_attr_in_illuminance0_calibscale_available.attr,
+ &dev_attr_in_illuminance0_integration_time.attr,
+ &iio_const_attr_in_illuminance0_integration_time_available\
+ .dev_attr.attr,
+ &dev_attr_in_illuminance0_target_input.attr,
+ &dev_attr_in_illuminance0_calibrate.attr,
+ &dev_attr_in_illuminance0_lux_table.attr,
+ &dev_attr_in_proximity0_calibrate.attr,
+ &dev_attr_in_proximity0_calibscale_available.attr,
+ NULL
+};
+
+static struct attribute *tsl2X7X_ALS_event_attrs[] = {
+ &dev_attr_in_intensity0_thresh_period.attr,
+ NULL,
+};
+static struct attribute *tsl2X7X_PRX_event_attrs[] = {
+ &dev_attr_in_proximity0_thresh_period.attr,
+ NULL,
+};
+
+static struct attribute *tsl2X7X_ALSPRX_event_attrs[] = {
+ &dev_attr_in_intensity0_thresh_period.attr,
+ &dev_attr_in_proximity0_thresh_period.attr,
+ NULL,
+};
+
+static const struct attribute_group tsl2X7X_device_attr_group_tbl[] = {
+ [ALS] = {
+ .attrs = tsl2x7x_ALS_device_attrs,
+ },
+ [PRX] = {
+ .attrs = tsl2x7x_PRX_device_attrs,
+ },
+ [ALSPRX] = {
+ .attrs = tsl2x7x_ALSPRX_device_attrs,
+ },
+ [PRX2] = {
+ .attrs = tsl2x7x_PRX2_device_attrs,
+ },
+ [ALSPRX2] = {
+ .attrs = tsl2x7x_ALSPRX2_device_attrs,
+ },
+};
+
+static struct attribute_group tsl2X7X_event_attr_group_tbl[] = {
+ [ALS] = {
+ .attrs = tsl2X7X_ALS_event_attrs,
+ .name = "events",
+ },
+ [PRX] = {
+ .attrs = tsl2X7X_PRX_event_attrs,
+ .name = "events",
+ },
+ [ALSPRX] = {
+ .attrs = tsl2X7X_ALSPRX_event_attrs,
+ .name = "events",
+ },
+};
+
+static const struct iio_info tsl2X7X_device_info[] = {
+ [ALS] = {
+ .attrs = &tsl2X7X_device_attr_group_tbl[ALS],
+ .event_attrs = &tsl2X7X_event_attr_group_tbl[ALS],
+ .driver_module = THIS_MODULE,
+ .read_raw = &tsl2x7x_read_raw,
+ .write_raw = &tsl2x7x_write_raw,
+ .read_event_value = &tsl2x7x_read_thresh,
+ .write_event_value = &tsl2x7x_write_thresh,
+ .read_event_config = &tsl2x7x_read_interrupt_config,
+ .write_event_config = &tsl2x7x_write_interrupt_config,
+ },
+ [PRX] = {
+ .attrs = &tsl2X7X_device_attr_group_tbl[PRX],
+ .event_attrs = &tsl2X7X_event_attr_group_tbl[PRX],
+ .driver_module = THIS_MODULE,
+ .read_raw = &tsl2x7x_read_raw,
+ .write_raw = &tsl2x7x_write_raw,
+ .read_event_value = &tsl2x7x_read_thresh,
+ .write_event_value = &tsl2x7x_write_thresh,
+ .read_event_config = &tsl2x7x_read_interrupt_config,
+ .write_event_config = &tsl2x7x_write_interrupt_config,
+ },
+ [ALSPRX] = {
+ .attrs = &tsl2X7X_device_attr_group_tbl[ALSPRX],
+ .event_attrs = &tsl2X7X_event_attr_group_tbl[ALSPRX],
+ .driver_module = THIS_MODULE,
+ .read_raw = &tsl2x7x_read_raw,
+ .write_raw = &tsl2x7x_write_raw,
+ .read_event_value = &tsl2x7x_read_thresh,
+ .write_event_value = &tsl2x7x_write_thresh,
+ .read_event_config = &tsl2x7x_read_interrupt_config,
+ .write_event_config = &tsl2x7x_write_interrupt_config,
+ },
+ [PRX2] = {
+ .attrs = &tsl2X7X_device_attr_group_tbl[PRX2],
+ .event_attrs = &tsl2X7X_event_attr_group_tbl[PRX],
+ .driver_module = THIS_MODULE,
+ .read_raw = &tsl2x7x_read_raw,
+ .write_raw = &tsl2x7x_write_raw,
+ .read_event_value = &tsl2x7x_read_thresh,
+ .write_event_value = &tsl2x7x_write_thresh,
+ .read_event_config = &tsl2x7x_read_interrupt_config,
+ .write_event_config = &tsl2x7x_write_interrupt_config,
+ },
+ [ALSPRX2] = {
+ .attrs = &tsl2X7X_device_attr_group_tbl[ALSPRX2],
+ .event_attrs = &tsl2X7X_event_attr_group_tbl[ALSPRX],
+ .driver_module = THIS_MODULE,
+ .read_raw = &tsl2x7x_read_raw,
+ .write_raw = &tsl2x7x_write_raw,
+ .read_event_value = &tsl2x7x_read_thresh,
+ .write_event_value = &tsl2x7x_write_thresh,
+ .read_event_config = &tsl2x7x_read_interrupt_config,
+ .write_event_config = &tsl2x7x_write_interrupt_config,
+ },
+};
+
+static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = {
+ [ALS] = {
+ .channel = {
+ {
+ .type = IIO_LIGHT,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT,
+ }, {
+ .type = IIO_INTENSITY,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+ .event_mask = TSL2X7X_EVENT_MASK
+ }, {
+ .type = IIO_INTENSITY,
+ .indexed = 1,
+ .channel = 1,
+ },
+ },
+ .chan_table_elements = 3,
+ .info = &tsl2X7X_device_info[ALS],
+ },
+ [PRX] = {
+ .channel = {
+ {
+ .type = IIO_PROXIMITY,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+ .event_mask = TSL2X7X_EVENT_MASK
+ },
+ },
+ .chan_table_elements = 1,
+ .info = &tsl2X7X_device_info[PRX],
+ },
+ [ALSPRX] = {
+ .channel = {
+ {
+ .type = IIO_LIGHT,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT
+ }, {
+ .type = IIO_INTENSITY,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+ .event_mask = TSL2X7X_EVENT_MASK
+ }, {
+ .type = IIO_INTENSITY,
+ .indexed = 1,
+ .channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+ }, {
+ .type = IIO_PROXIMITY,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+ .event_mask = TSL2X7X_EVENT_MASK
+ },
+ },
+ .chan_table_elements = 4,
+ .info = &tsl2X7X_device_info[ALSPRX],
+ },
+ [PRX2] = {
+ .channel = {
+ {
+ .type = IIO_PROXIMITY,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
+ .event_mask = TSL2X7X_EVENT_MASK
+ },
+ },
+ .chan_table_elements = 1,
+ .info = &tsl2X7X_device_info[PRX2],
+ },
+ [ALSPRX2] = {
+ .channel = {
+ {
+ .type = IIO_LIGHT,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT,
+ }, {
+ .type = IIO_INTENSITY,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+ .event_mask = TSL2X7X_EVENT_MASK
+ }, {
+ .type = IIO_INTENSITY,
+ .indexed = 1,
+ .channel = 1,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+ }, {
+ .type = IIO_PROXIMITY,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
+ .event_mask = TSL2X7X_EVENT_MASK
+ },
+ },
+ .chan_table_elements = 4,
+ .info = &tsl2X7X_device_info[ALSPRX2],
+ },
+};
+
+static int __devinit tsl2x7x_probe(struct i2c_client *clientp,
+ const struct i2c_device_id *id)
+{
+ int ret;
+ unsigned char device_id;
+ struct iio_dev *indio_dev;
+ struct tsl2X7X_chip *chip;
+
+ indio_dev = iio_device_alloc(sizeof(*chip));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ chip = iio_priv(indio_dev);
+ chip->client = clientp;
+ i2c_set_clientdata(clientp, indio_dev);
+
+ ret = tsl2x7x_i2c_read(chip->client,
+ TSL2X7X_CHIPID, &device_id);
+ if (ret < 0)
+ goto fail1;
+
+ if ((!tsl2x7x_device_id(&device_id, id->driver_data)) ||
+ (tsl2x7x_device_id(&device_id, id->driver_data) == -EINVAL)) {
+ dev_info(&chip->client->dev,
+ "%s: i2c device found does not match expected id\n",
+ __func__);
+ goto fail1;
+ }
+
+ ret = i2c_smbus_write_byte(clientp, (TSL2X7X_CMD_REG | TSL2X7X_CNTRL));
+ if (ret < 0) {
+ dev_err(&clientp->dev, "%s: write to cmd reg failed. err = %d\n",
+ __func__, ret);
+ goto fail1;
+ }
+
+ /* ALS and PROX functions can be invoked via user space poll
+ * or H/W interrupt. If busy return last sample. */
+ mutex_init(&chip->als_mutex);
+ mutex_init(&chip->prox_mutex);
+
+ chip->tsl2x7x_chip_status = TSL2X7X_CHIP_UNKNOWN;
+ chip->pdata = clientp->dev.platform_data;
+ chip->id = id->driver_data;
+ chip->chip_info =
+ &tsl2x7x_chip_info_tbl[device_channel_config[id->driver_data]];
+
+ indio_dev->info = chip->chip_info->info;
+ indio_dev->dev.parent = &clientp->dev;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = chip->client->name;
+ indio_dev->channels = chip->chip_info->channel;
+ indio_dev->num_channels = chip->chip_info->chan_table_elements;
+
+ if (clientp->irq) {
+ ret = request_threaded_irq(clientp->irq,
+ NULL,
+ &tsl2x7x_event_handler,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "TSL2X7X_event",
+ indio_dev);
+ if (ret) {
+ dev_err(&clientp->dev,
+ "%s: irq request failed", __func__);
+ goto fail2;
+ }
+ }
+
+ /* Load up the defaults */
+ tsl2x7x_defaults(chip);
+ /* Make sure the chip is on */
+ tsl2x7x_chip_on(indio_dev);
+
+ ret = iio_device_register(indio_dev);
+ if (ret) {
+ dev_err(&clientp->dev,
+ "%s: iio registration failed\n", __func__);
+ goto fail1;
+ }
+
+ dev_info(&clientp->dev, "%s Light sensor found.\n", id->name);
+
+ return 0;
+
+fail1:
+ if (clientp->irq)
+ free_irq(clientp->irq, indio_dev);
+fail2:
+ iio_device_free(indio_dev);
+
+ return ret;
+}
+
+static int tsl2x7x_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ int ret = 0;
+
+ if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING) {
+ ret = tsl2x7x_chip_off(indio_dev);
+ chip->tsl2x7x_chip_status = TSL2X7X_CHIP_SUSPENDED;
+ }
+
+ if (chip->pdata && chip->pdata->platform_power) {
+ pm_message_t pmm = {PM_EVENT_SUSPEND};
+ chip->pdata->platform_power(dev, pmm);
+ }
+
+ return ret;
+}
+
+static int tsl2x7x_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct tsl2X7X_chip *chip = iio_priv(indio_dev);
+ int ret = 0;
+
+ if (chip->pdata && chip->pdata->platform_power) {
+ pm_message_t pmm = {PM_EVENT_RESUME};
+ chip->pdata->platform_power(dev, pmm);
+ }
+
+ if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_SUSPENDED)
+ ret = tsl2x7x_chip_on(indio_dev);
+
+ return ret;
+}
+
+static int __devexit tsl2x7x_remove(struct i2c_client *client)
+{
+ struct tsl2X7X_chip *chip = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = iio_priv_to_dev(chip);
+
+ tsl2x7x_chip_off(indio_dev);
+
+ iio_device_unregister(indio_dev);
+ if (client->irq)
+ free_irq(client->irq, chip->client->name);
+
+ iio_device_free(indio_dev);
+
+ return 0;
+}
+
+static struct i2c_device_id tsl2x7x_idtable[] = {
+ { "tsl2571", tsl2571 },
+ { "tsl2671", tsl2671 },
+ { "tmd2671", tmd2671 },
+ { "tsl2771", tsl2771 },
+ { "tmd2771", tmd2771 },
+ { "tsl2572", tsl2572 },
+ { "tsl2672", tsl2672 },
+ { "tmd2672", tmd2672 },
+ { "tsl2772", tsl2772 },
+ { "tmd2772", tmd2772 },
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, tsl2x7x_idtable);
+
+static const struct dev_pm_ops tsl2x7x_pm_ops = {
+ .suspend = tsl2x7x_suspend,
+ .resume = tsl2x7x_resume,
+};
+
+/* Driver definition */
+static struct i2c_driver tsl2x7x_driver = {
+ .driver = {
+ .name = "tsl2x7x",
+ .pm = &tsl2x7x_pm_ops,
+ },
+ .id_table = tsl2x7x_idtable,
+ .probe = tsl2x7x_probe,
+ .remove = __devexit_p(tsl2x7x_remove),
+};
+
+module_i2c_driver(tsl2x7x_driver);
+
+MODULE_AUTHOR("J. August Brenner<jbrenner@taosinc.com>");
+MODULE_DESCRIPTION("TAOS tsl2x7x ambient and proximity light sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio/magnetometer/Kconfig
index 722c4e13f713..b9d932595ba9 100644
--- a/drivers/staging/iio/magnetometer/Kconfig
+++ b/drivers/staging/iio/magnetometer/Kconfig
@@ -15,13 +15,13 @@ config SENSORS_AK8975
will be called ak8975.
config SENSORS_HMC5843
- tristate "Honeywell HMC5843 3-Axis Magnetometer"
+ tristate "Honeywell HMC5843/5883/5883L 3-Axis Magnetometer"
depends on I2C
help
- Say Y here to add support for the Honeywell HMC 5843 3-Axis
- Magnetometer (digital compass).
+ Say Y here to add support for the Honeywell HMC5843, HMC5883 and
+ HMC5883L 3-Axis Magnetometer (digital compass).
To compile this driver as a module, choose M here: the module
- will be called hmc5843
+ will be called hmc5843.
endmenu
diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c
index ebc2d0840caf..5834e4a70f8c 100644
--- a/drivers/staging/iio/magnetometer/ak8975.c
+++ b/drivers/staging/iio/magnetometer/ak8975.c
@@ -30,8 +30,8 @@
#include <linux/gpio.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
/*
* Register definitions, as well as various shifts and masks to get at the
* individual fields of the registers.
@@ -242,7 +242,7 @@ static int ak8975_setup(struct i2c_client *client)
static ssize_t show_mode(struct device *dev, struct device_attribute *devattr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ak8975_data *data = iio_priv(indio_dev);
return sprintf(buf, "%u\n", data->mode);
@@ -255,7 +255,7 @@ static ssize_t show_mode(struct device *dev, struct device_attribute *devattr,
static ssize_t store_mode(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ak8975_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
bool value;
@@ -431,7 +431,7 @@ static int ak8975_read_raw(struct iio_dev *indio_dev,
struct ak8975_data *data = iio_priv(indio_dev);
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
return ak8975_read_axis(indio_dev, chan->address, val);
case IIO_CHAN_INFO_SCALE:
*val = data->raw_to_gauss[chan->address];
@@ -445,7 +445,8 @@ static int ak8975_read_raw(struct iio_dev *indio_dev,
.type = IIO_MAGN, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
- .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
.address = index, \
}
@@ -505,7 +506,7 @@ static int ak8975_probe(struct i2c_client *client,
}
/* Register with IIO */
- indio_dev = iio_allocate_device(sizeof(*data));
+ indio_dev = iio_device_alloc(sizeof(*data));
if (indio_dev == NULL) {
err = -ENOMEM;
goto exit_gpio;
@@ -536,7 +537,7 @@ static int ak8975_probe(struct i2c_client *client,
return 0;
exit_free_iio:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
exit_gpio:
if (gpio_is_valid(eoc_gpio))
gpio_free(eoc_gpio);
@@ -554,7 +555,7 @@ static int ak8975_remove(struct i2c_client *client)
if (gpio_is_valid(data->eoc_gpio))
gpio_free(data->eoc_gpio);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index e00b416c4d33..c1fa09f07625 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -2,6 +2,8 @@
Author: Shubhrajyoti Datta <shubhrajyoti@ti.com>
Acknowledgement: Jonathan Cameron <jic23@cam.ac.uk> for valuable inputs.
+ Support for HMC5883 and HMC5883L by Peter Meerwald <pmeerw@pmeerw.net>.
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -22,10 +24,8 @@
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/types.h>
-#include "../iio.h"
-#include "../sysfs.h"
-
-#define HMC5843_I2C_ADDRESS 0x1E
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#define HMC5843_CONFIG_REG_A 0x00
#define HMC5843_CONFIG_REG_B 0x01
@@ -36,110 +36,185 @@
#define HMC5843_DATA_OUT_Y_LSB_REG 0x06
#define HMC5843_DATA_OUT_Z_MSB_REG 0x07
#define HMC5843_DATA_OUT_Z_LSB_REG 0x08
+/* Beware: Y and Z are exchanged on HMC5883 */
+#define HMC5883_DATA_OUT_Z_MSB_REG 0x05
+#define HMC5883_DATA_OUT_Z_LSB_REG 0x06
+#define HMC5883_DATA_OUT_Y_MSB_REG 0x07
+#define HMC5883_DATA_OUT_Y_LSB_REG 0x08
#define HMC5843_STATUS_REG 0x09
#define HMC5843_ID_REG_A 0x0A
#define HMC5843_ID_REG_B 0x0B
#define HMC5843_ID_REG_C 0x0C
+enum hmc5843_ids {
+ HMC5843_ID,
+ HMC5883_ID,
+ HMC5883L_ID,
+};
+
+/*
+ * Beware: identification of the HMC5883 is still "H43";
+ * I2C address is also unchanged
+ */
#define HMC5843_ID_REG_LENGTH 0x03
#define HMC5843_ID_STRING "H43"
+#define HMC5843_I2C_ADDRESS 0x1E
/*
- * Range settings in (+-)Ga
- * */
-#define RANGE_GAIN_OFFSET 0x05
-
-#define RANGE_0_7 0x00
-#define RANGE_1_0 0x01 /* default */
-#define RANGE_1_5 0x02
-#define RANGE_2_0 0x03
-#define RANGE_3_2 0x04
-#define RANGE_3_8 0x05
-#define RANGE_4_5 0x06
-#define RANGE_6_5 0x07 /* Not recommended */
+ * Range gain settings in (+-)Ga
+ * Beware: HMC5843 and HMC5883 have different recommended sensor field
+ * ranges; default corresponds to +-1.0 Ga and +-1.3 Ga, respectively
+ */
+#define HMC5843_RANGE_GAIN_OFFSET 0x05
+#define HMC5843_RANGE_GAIN_DEFAULT 0x01
+#define HMC5843_RANGE_GAIN_MAX 0x07
/*
* Device status
*/
-#define DATA_READY 0x01
-#define DATA_OUTPUT_LOCK 0x02
-#define VOLTAGE_REGULATOR_ENABLED 0x04
+#define HMC5843_DATA_READY 0x01
+#define HMC5843_DATA_OUTPUT_LOCK 0x02
+/* Does not exist on HMC5883, not used */
+#define HMC5843_VOLTAGE_REGULATOR_ENABLED 0x04
/*
* Mode register configuration
*/
-#define MODE_CONVERSION_CONTINUOUS 0x00
-#define MODE_CONVERSION_SINGLE 0x01
-#define MODE_IDLE 0x02
-#define MODE_SLEEP 0x03
-
-/* Minimum Data Output Rate in 1/10 Hz */
-#define RATE_OFFSET 0x02
-#define RATE_BITMASK 0x1C
-#define RATE_5 0x00
-#define RATE_10 0x01
-#define RATE_20 0x02
-#define RATE_50 0x03
-#define RATE_100 0x04
-#define RATE_200 0x05
-#define RATE_500 0x06
-#define RATE_NOT_USED 0x07
+#define HMC5843_MODE_CONVERSION_CONTINUOUS 0x00
+#define HMC5843_MODE_CONVERSION_SINGLE 0x01
+#define HMC5843_MODE_IDLE 0x02
+#define HMC5843_MODE_SLEEP 0x03
+#define HMC5843_MODE_MASK 0x03
+
+/*
+ * HMC5843: Minimum data output rate
+ * HMC5883: Typical data output rate
+ */
+#define HMC5843_RATE_OFFSET 0x02
+#define HMC5843_RATE_BITMASK 0x1C
+#define HMC5843_RATE_NOT_USED 0x07
/*
- * Device Configuration
+ * Device measurement configuration
*/
-#define CONF_NORMAL 0x00
-#define CONF_POSITIVE_BIAS 0x01
-#define CONF_NEGATIVE_BIAS 0x02
-#define CONF_NOT_USED 0x03
-#define MEAS_CONF_MASK 0x03
+#define HMC5843_MEAS_CONF_NORMAL 0x00
+#define HMC5843_MEAS_CONF_POSITIVE_BIAS 0x01
+#define HMC5843_MEAS_CONF_NEGATIVE_BIAS 0x02
+#define HMC5843_MEAS_CONF_NOT_USED 0x03
+#define HMC5843_MEAS_CONF_MASK 0x03
-static int hmc5843_regval_to_nanoscale[] = {
+/*
+ * Scaling factors: 10000000/Gain
+ */
+static const int hmc5843_regval_to_nanoscale[] = {
6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714
};
-static const int regval_to_input_field_mg[] = {
- 700,
- 1000,
- 1500,
- 2000,
- 3200,
- 3800,
- 4500,
- 6500
+static const int hmc5883_regval_to_nanoscale[] = {
+ 7812, 9766, 13021, 16287, 24096, 27701, 32573, 45662
};
-static const char * const regval_to_samp_freq[] = {
- "0.5",
- "1",
- "2",
- "5",
- "10",
- "20",
- "50",
+
+static const int hmc5883l_regval_to_nanoscale[] = {
+ 7299, 9174, 12195, 15152, 22727, 25641, 30303, 43478
+};
+
+/*
+ * From the HMC5843 datasheet:
+ * Value | Sensor input field range (Ga) | Gain (counts/milli-Gauss)
+ * 0 | (+-)0.7 | 1620
+ * 1 | (+-)1.0 | 1300
+ * 2 | (+-)1.5 | 970
+ * 3 | (+-)2.0 | 780
+ * 4 | (+-)3.2 | 530
+ * 5 | (+-)3.8 | 460
+ * 6 | (+-)4.5 | 390
+ * 7 | (+-)6.5 | 280
+ *
+ * From the HMC5883 datasheet:
+ * Value | Recommended sensor field range (Ga) | Gain (counts/Gauss)
+ * 0 | (+-)0.9 | 1280
+ * 1 | (+-)1.2 | 1024
+ * 2 | (+-)1.9 | 768
+ * 3 | (+-)2.5 | 614
+ * 4 | (+-)4.0 | 415
+ * 5 | (+-)4.6 | 361
+ * 6 | (+-)5.5 | 307
+ * 7 | (+-)7.9 | 219
+ *
+ * From the HMC5883L datasheet:
+ * Value | Recommended sensor field range (Ga) | Gain (LSB/Gauss)
+ * 0 | (+-)0.88 | 1370
+ * 1 | (+-)1.3 | 1090
+ * 2 | (+-)1.9 | 820
+ * 3 | (+-)2.5 | 660
+ * 4 | (+-)4.0 | 440
+ * 5 | (+-)4.7 | 390
+ * 6 | (+-)5.6 | 330
+ * 7 | (+-)8.1 | 230
+ */
+static const int hmc5843_regval_to_input_field_mga[] = {
+ 700, 1000, 1500, 2000, 3200, 3800, 4500, 6500
+};
+
+static const int hmc5883_regval_to_input_field_mga[] = {
+ 900, 1200, 1900, 2500, 4000, 4600, 5500, 7900
+};
+
+static const int hmc5883l_regval_to_input_field_mga[] = {
+ 880, 1300, 1900, 2500, 4000, 4700, 5600, 8100
+};
+
+/*
+ * From the datasheet:
+ * Value | HMC5843 | HMC5883/HMC5883L
+ * | Data output rate (Hz) | Data output rate (Hz)
+ * 0 | 0.5 | 0.75
+ * 1 | 1 | 1.5
+ * 2 | 2 | 3
+ * 3 | 5 | 7.5
+ * 4 | 10 (default) | 15
+ * 5 | 20 | 30
+ * 6 | 50 | 75
+ * 7 | Not used | Not used
+ */
+static const char * const hmc5843_regval_to_sample_freq[] = {
+ "0.5", "1", "2", "5", "10", "20", "50",
+};
+
+static const char * const hmc5883_regval_to_sample_freq[] = {
+ "0.75", "1.5", "3", "7.5", "15", "30", "75",
};
/* Addresses to scan: 0x1E */
static const unsigned short normal_i2c[] = { HMC5843_I2C_ADDRESS,
- I2C_CLIENT_END };
+ I2C_CLIENT_END };
+
+/* Describe chip variants */
+struct hmc5843_chip_info {
+ const struct iio_chan_spec *channels;
+ int num_channels;
+ const char * const *regval_to_sample_freq;
+ const int *regval_to_input_field_mga;
+ const int *regval_to_nanoscale;
+};
/* Each client has this additional data */
struct hmc5843_data {
struct mutex lock;
- u8 rate;
- u8 meas_conf;
- u8 operating_mode;
- u8 range;
+ u8 rate;
+ u8 meas_conf;
+ u8 operating_mode;
+ u8 range;
+ const struct hmc5843_chip_info *variant;
};
-static void hmc5843_init_client(struct i2c_client *client);
-
+/* The lower two bits contain the current conversion mode */
static s32 hmc5843_configure(struct i2c_client *client,
u8 operating_mode)
{
- /* The lower two bits contain the current conversion mode */
return i2c_smbus_write_byte_data(client,
HMC5843_MODE_REG,
- (operating_mode & 0x03));
+ operating_mode & HMC5843_MODE_MASK);
}
/* Return the measurement value from the specified channel */
@@ -153,7 +228,7 @@ static int hmc5843_read_measurement(struct iio_dev *indio_dev,
mutex_lock(&data->lock);
result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG);
- while (!(result & DATA_READY))
+ while (!(result & HMC5843_DATA_READY))
result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG);
result = i2c_smbus_read_word_data(client, address);
@@ -161,30 +236,29 @@ static int hmc5843_read_measurement(struct iio_dev *indio_dev,
if (result < 0)
return -EINVAL;
- *val = (s16)swab16((u16)result);
+ *val = (s16)swab16((u16)result);
return IIO_VAL_INT;
}
-
/*
- * From the datasheet
+ * From the datasheet:
* 0 - Continuous-Conversion Mode: In continuous-conversion mode, the
- * device continuously performs conversions and places the result in the
- * data register.
+ * device continuously performs conversions and places the result in
+ * the data register.
*
- * 1 - Single-Conversion Mode : device performs a single measurement,
- * sets RDY high and returned to sleep mode
+ * 1 - Single-Conversion Mode : Device performs a single measurement,
+ * sets RDY high and returns to sleep mode.
*
- * 2 - Idle Mode : Device is placed in idle mode.
+ * 2 - Idle Mode : Device is placed in idle mode.
*
- * 3 - Sleep Mode. Device is placed in sleep mode.
+ * 3 - Sleep Mode : Device is placed in sleep mode.
*
*/
static ssize_t hmc5843_show_operating_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct hmc5843_data *data = iio_priv(indio_dev);
return sprintf(buf, "%d\n", data->operating_mode);
}
@@ -194,21 +268,22 @@ static ssize_t hmc5843_set_operating_mode(struct device *dev,
const char *buf,
size_t count)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
struct hmc5843_data *data = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
unsigned long operating_mode = 0;
s32 status;
int error;
+
mutex_lock(&data->lock);
- error = strict_strtoul(buf, 10, &operating_mode);
+ error = kstrtoul(buf, 10, &operating_mode);
if (error) {
count = error;
goto exit;
}
- dev_dbg(dev, "set Conversion mode to %lu\n", operating_mode);
- if (operating_mode > MODE_SLEEP) {
+ dev_dbg(dev, "set conversion mode to %lu\n", operating_mode);
+ if (operating_mode > HMC5843_MODE_SLEEP) {
count = -EINVAL;
goto exit;
}
@@ -225,6 +300,7 @@ exit:
mutex_unlock(&data->lock);
return count;
}
+
static IIO_DEVICE_ATTR(operating_mode,
S_IWUSR | S_IRUGO,
hmc5843_show_operating_mode,
@@ -234,25 +310,29 @@ static IIO_DEVICE_ATTR(operating_mode,
/*
* API for setting the measurement configuration to
* Normal, Positive bias and Negative bias
- * From the datasheet
*
- * Normal measurement configuration (default): In normal measurement
- * configuration the device follows normal measurement flow. Pins BP and BN
- * are left floating and high impedance.
+ * From the datasheet:
+ * 0 - Normal measurement configuration (default): In normal measurement
+ * configuration the device follows normal measurement flow. Pins BP
+ * and BN are left floating and high impedance.
*
- * Positive bias configuration: In positive bias configuration, a positive
- * current is forced across the resistive load on pins BP and BN.
+ * 1 - Positive bias configuration: In positive bias configuration, a
+ * positive current is forced across the resistive load on pins BP
+ * and BN.
*
- * Negative bias configuration. In negative bias configuration, a negative
- * current is forced across the resistive load on pins BP and BN.
+ * 2 - Negative bias configuration. In negative bias configuration, a
+ * negative current is forced across the resistive load on pins BP
+ * and BN.
*
*/
static s32 hmc5843_set_meas_conf(struct i2c_client *client,
u8 meas_conf)
{
- struct hmc5843_data *data = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct hmc5843_data *data = iio_priv(indio_dev);
u8 reg_val;
- reg_val = (meas_conf & MEAS_CONF_MASK) | (data->rate << RATE_OFFSET);
+ reg_val = (meas_conf & HMC5843_MEAS_CONF_MASK) |
+ (data->rate << HMC5843_RATE_OFFSET);
return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val);
}
@@ -260,7 +340,7 @@ static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct hmc5843_data *data = iio_priv(indio_dev);
return sprintf(buf, "%d\n", data->meas_conf);
}
@@ -270,16 +350,20 @@ static ssize_t hmc5843_set_measurement_configuration(struct device *dev,
const char *buf,
size_t count)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
- struct hmc5843_data *data = i2c_get_clientdata(client);
+ struct hmc5843_data *data = iio_priv(indio_dev);
unsigned long meas_conf = 0;
- int error = strict_strtoul(buf, 10, &meas_conf);
+ int error;
+
+ error = kstrtoul(buf, 10, &meas_conf);
if (error)
return error;
- mutex_lock(&data->lock);
+ if (meas_conf >= HMC5843_MEAS_CONF_NOT_USED)
+ return -EINVAL;
- dev_dbg(dev, "set mode to %lu\n", meas_conf);
+ mutex_lock(&data->lock);
+ dev_dbg(dev, "set measurement configuration to %lu\n", meas_conf);
if (hmc5843_set_meas_conf(client, meas_conf)) {
count = -EINVAL;
goto exit;
@@ -290,71 +374,85 @@ exit:
mutex_unlock(&data->lock);
return count;
}
+
static IIO_DEVICE_ATTR(meas_conf,
S_IWUSR | S_IRUGO,
hmc5843_show_measurement_configuration,
hmc5843_set_measurement_configuration,
0);
-/*
- * From Datasheet
- * The table shows the minimum data output
- * Value | Minimum data output rate(Hz)
- * 0 | 0.5
- * 1 | 1
- * 2 | 2
- * 3 | 5
- * 4 | 10 (default)
- * 5 | 20
- * 6 | 50
- * 7 | Not used
- */
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("0.5 1 2 5 10 20 50");
+static ssize_t hmc5843_show_sampling_frequencies_available(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct hmc5843_data *data = iio_priv(indio_dev);
+ ssize_t total_n = 0;
+ int i;
+
+ for (i = 0; i < HMC5843_RATE_NOT_USED; i++) {
+ ssize_t n = sprintf(buf, "%s ", data->variant->regval_to_sample_freq[i]);
+ buf += n;
+ total_n += n;
+ }
+ /* replace trailing space by newline */
+ buf[-1] = '\n';
+
+ return total_n;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_sampling_frequencies_available);
static s32 hmc5843_set_rate(struct i2c_client *client,
u8 rate)
{
- struct hmc5843_data *data = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct hmc5843_data *data = iio_priv(indio_dev);
u8 reg_val;
- reg_val = (data->meas_conf) | (rate << RATE_OFFSET);
- if (rate >= RATE_NOT_USED) {
+ if (rate >= HMC5843_RATE_NOT_USED) {
dev_err(&client->dev,
- "This data output rate is not supported\n");
+ "data output rate is not supported\n");
return -EINVAL;
}
+
+ reg_val = data->meas_conf | (rate << HMC5843_RATE_OFFSET);
return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val);
}
-static ssize_t set_sampling_frequency(struct device *dev,
+static int hmc5843_check_sampling_frequency(struct hmc5843_data *data,
+ const char *buf)
+{
+ const char * const *samp_freq = data->variant->regval_to_sample_freq;
+ int i;
+
+ for (i = 0; i < HMC5843_RATE_NOT_USED; i++) {
+ if (sysfs_streq(buf, samp_freq[i]))
+ return i;
+ }
+
+ return -EINVAL;
+}
+
+static ssize_t hmc5843_set_sampling_frequency(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
struct hmc5843_data *data = iio_priv(indio_dev);
- unsigned long rate = 0;
-
- if (strncmp(buf, "0.5" , 3) == 0)
- rate = RATE_5;
- else if (strncmp(buf, "1" , 1) == 0)
- rate = RATE_10;
- else if (strncmp(buf, "2", 1) == 0)
- rate = RATE_20;
- else if (strncmp(buf, "5", 1) == 0)
- rate = RATE_50;
- else if (strncmp(buf, "10", 2) == 0)
- rate = RATE_100;
- else if (strncmp(buf, "20" , 2) == 0)
- rate = RATE_200;
- else if (strncmp(buf, "50" , 2) == 0)
- rate = RATE_500;
- else
- return -EINVAL;
+ int rate;
+
+ rate = hmc5843_check_sampling_frequency(data, buf);
+ if (rate < 0) {
+ dev_err(&client->dev,
+ "sampling frequency is not supported\n");
+ return rate;
+ }
mutex_lock(&data->lock);
- dev_dbg(dev, "set rate to %lu\n", rate);
+ dev_dbg(dev, "set rate to %d\n", rate);
if (hmc5843_set_rate(client, rate)) {
count = -EINVAL;
goto exit;
@@ -366,89 +464,79 @@ exit:
return count;
}
-static ssize_t show_sampling_frequency(struct device *dev,
+static ssize_t hmc5843_show_sampling_frequency(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ struct hmc5843_data *data = iio_priv(indio_dev);
s32 rate;
- rate = i2c_smbus_read_byte_data(client, this_attr->address);
+ rate = i2c_smbus_read_byte_data(client, this_attr->address);
if (rate < 0)
return rate;
- rate = (rate & RATE_BITMASK) >> RATE_OFFSET;
- return sprintf(buf, "%s\n", regval_to_samp_freq[rate]);
+ rate = (rate & HMC5843_RATE_BITMASK) >> HMC5843_RATE_OFFSET;
+ return sprintf(buf, "%s\n", data->variant->regval_to_sample_freq[rate]);
}
+
static IIO_DEVICE_ATTR(sampling_frequency,
S_IWUSR | S_IRUGO,
- show_sampling_frequency,
- set_sampling_frequency,
+ hmc5843_show_sampling_frequency,
+ hmc5843_set_sampling_frequency,
HMC5843_CONFIG_REG_A);
-/*
- * From Datasheet
- * Nominal gain settings
- * Value | Sensor Input Field Range(Ga) | Gain(counts/ milli-gauss)
- *0 |(+-)0.7 |1620
- *1 |(+-)1.0 |1300
- *2 |(+-)1.5 |970
- *3 |(+-)2.0 |780
- *4 |(+-)3.2 |530
- *5 |(+-)3.8 |460
- *6 |(+-)4.5 |390
- *7 |(+-)6.5 |280
- */
-static ssize_t show_range(struct device *dev,
+static ssize_t hmc5843_show_range_gain(struct device *dev,
struct device_attribute *attr,
char *buf)
{
u8 range;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct hmc5843_data *data = iio_priv(indio_dev);
range = data->range;
- return sprintf(buf, "%d\n", regval_to_input_field_mg[range]);
+ return sprintf(buf, "%d\n", data->variant->regval_to_input_field_mga[range]);
}
-static ssize_t set_range(struct device *dev,
+static ssize_t hmc5843_set_range_gain(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct hmc5843_data *data = iio_priv(indio_dev);
unsigned long range = 0;
int error;
+
mutex_lock(&data->lock);
- error = strict_strtoul(buf, 10, &range);
+ error = kstrtoul(buf, 10, &range);
if (error) {
count = error;
goto exit;
}
dev_dbg(dev, "set range to %lu\n", range);
- if (range > RANGE_6_5) {
+ if (range > HMC5843_RANGE_GAIN_MAX) {
count = -EINVAL;
goto exit;
}
data->range = range;
- range = range << RANGE_GAIN_OFFSET;
+ range = range << HMC5843_RANGE_GAIN_OFFSET;
if (i2c_smbus_write_byte_data(client, this_attr->address, range))
count = -EINVAL;
exit:
mutex_unlock(&data->lock);
return count;
-
}
+
static IIO_DEVICE_ATTR(in_magn_range,
S_IWUSR | S_IRUGO,
- show_range,
- set_range,
+ hmc5843_show_range_gain,
+ hmc5843_set_range_gain,
HMC5843_CONFIG_REG_B);
static int hmc5843_read_raw(struct iio_dev *indio_dev,
@@ -459,13 +547,13 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev,
struct hmc5843_data *data = iio_priv(indio_dev);
switch (mask) {
- case 0:
+ case IIO_CHAN_INFO_RAW:
return hmc5843_read_measurement(indio_dev,
chan->address,
val);
case IIO_CHAN_INFO_SCALE:
*val = 0;
- *val2 = hmc5843_regval_to_nanoscale[data->range];
+ *val2 = data->variant->regval_to_nanoscale[data->range];
return IIO_VAL_INT_PLUS_NANO;
};
return -EINVAL;
@@ -476,7 +564,8 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev,
.type = IIO_MAGN, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = add \
}
@@ -486,12 +575,18 @@ static const struct iio_chan_spec hmc5843_channels[] = {
HMC5843_CHANNEL(Z, HMC5843_DATA_OUT_Z_MSB_REG),
};
+static const struct iio_chan_spec hmc5883_channels[] = {
+ HMC5843_CHANNEL(X, HMC5843_DATA_OUT_X_MSB_REG),
+ HMC5843_CHANNEL(Y, HMC5883_DATA_OUT_Y_MSB_REG),
+ HMC5843_CHANNEL(Z, HMC5883_DATA_OUT_Z_MSB_REG),
+};
+
static struct attribute *hmc5843_attributes[] = {
&iio_dev_attr_meas_conf.dev_attr.attr,
&iio_dev_attr_operating_mode.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_dev_attr_in_magn_range.dev_attr.attr,
- &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
NULL
};
@@ -499,6 +594,33 @@ static const struct attribute_group hmc5843_group = {
.attrs = hmc5843_attributes,
};
+static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = {
+ [HMC5843_ID] = {
+ .channels = hmc5843_channels,
+ .num_channels = ARRAY_SIZE(hmc5843_channels),
+ .regval_to_sample_freq = hmc5843_regval_to_sample_freq,
+ .regval_to_input_field_mga =
+ hmc5843_regval_to_input_field_mga,
+ .regval_to_nanoscale = hmc5843_regval_to_nanoscale,
+ },
+ [HMC5883_ID] = {
+ .channels = hmc5883_channels,
+ .num_channels = ARRAY_SIZE(hmc5883_channels),
+ .regval_to_sample_freq = hmc5883_regval_to_sample_freq,
+ .regval_to_input_field_mga =
+ hmc5883_regval_to_input_field_mga,
+ .regval_to_nanoscale = hmc5883_regval_to_nanoscale,
+ },
+ [HMC5883L_ID] = {
+ .channels = hmc5883_channels,
+ .num_channels = ARRAY_SIZE(hmc5883_channels),
+ .regval_to_sample_freq = hmc5883_regval_to_sample_freq,
+ .regval_to_input_field_mga =
+ hmc5883l_regval_to_input_field_mga,
+ .regval_to_nanoscale = hmc5883l_regval_to_nanoscale,
+ },
+};
+
static int hmc5843_detect(struct i2c_client *client,
struct i2c_board_info *info)
{
@@ -518,18 +640,23 @@ static int hmc5843_detect(struct i2c_client *client,
return 0;
}
-/* Called when we have found a new HMC5843. */
-static void hmc5843_init_client(struct i2c_client *client)
+/* Called when we have found a new HMC58X3 */
+static void hmc5843_init_client(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct hmc5843_data *data = iio_priv(indio_dev);
+ data->variant = &hmc5843_chip_info_tbl[id->driver_data];
+ indio_dev->channels = data->variant->channels;
+ indio_dev->num_channels = data->variant->num_channels;
hmc5843_set_meas_conf(client, data->meas_conf);
hmc5843_set_rate(client, data->rate);
hmc5843_configure(client, data->operating_mode);
i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_B, data->range);
mutex_init(&data->lock);
- pr_info("HMC5843 initialized\n");
+
+ pr_info("%s initialized\n", id->name);
}
static const struct iio_info hmc5843_info = {
@@ -545,35 +672,34 @@ static int hmc5843_probe(struct i2c_client *client,
struct iio_dev *indio_dev;
int err = 0;
- indio_dev = iio_allocate_device(sizeof(*data));
+ indio_dev = iio_device_alloc(sizeof(*data));
if (indio_dev == NULL) {
err = -ENOMEM;
goto exit;
}
- data = iio_priv(indio_dev);
- /* default settings at probe */
- data->meas_conf = CONF_NORMAL;
- data->range = RANGE_1_0;
- data->operating_mode = MODE_CONVERSION_CONTINUOUS;
+ /* default settings at probe */
+ data = iio_priv(indio_dev);
+ data->meas_conf = HMC5843_MEAS_CONF_NORMAL;
+ data->range = HMC5843_RANGE_GAIN_DEFAULT;
+ data->operating_mode = HMC5843_MODE_CONVERSION_CONTINUOUS;
i2c_set_clientdata(client, indio_dev);
-
- /* Initialize the HMC5843 chip */
- hmc5843_init_client(client);
+ hmc5843_init_client(client, id);
indio_dev->info = &hmc5843_info;
indio_dev->name = id->name;
- indio_dev->channels = hmc5843_channels;
- indio_dev->num_channels = ARRAY_SIZE(hmc5843_channels);
indio_dev->dev.parent = &client->dev;
indio_dev->modes = INDIO_DIRECT_MODE;
+
err = iio_device_register(indio_dev);
if (err)
goto exit_free2;
+
return 0;
+
exit_free2:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
exit:
return err;
}
@@ -584,8 +710,8 @@ static int hmc5843_remove(struct i2c_client *client)
iio_device_unregister(indio_dev);
/* sleep mode to save power */
- hmc5843_configure(client, MODE_SLEEP);
- iio_free_device(indio_dev);
+ hmc5843_configure(client, HMC5843_MODE_SLEEP);
+ iio_device_free(indio_dev);
return 0;
}
@@ -593,14 +719,18 @@ static int hmc5843_remove(struct i2c_client *client)
#ifdef CONFIG_PM_SLEEP
static int hmc5843_suspend(struct device *dev)
{
- hmc5843_configure(to_i2c_client(dev), MODE_SLEEP);
+ hmc5843_configure(to_i2c_client(dev), HMC5843_MODE_SLEEP);
return 0;
}
static int hmc5843_resume(struct device *dev)
{
- struct hmc5843_data *data = i2c_get_clientdata(to_i2c_client(dev));
- hmc5843_configure(to_i2c_client(dev), data->operating_mode);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct hmc5843_data *data = iio_priv(indio_dev);
+
+ hmc5843_configure(client, data->operating_mode);
+
return 0;
}
@@ -611,7 +741,9 @@ static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops, hmc5843_suspend, hmc5843_resume);
#endif
static const struct i2c_device_id hmc5843_id[] = {
- { "hmc5843", 0 },
+ { "hmc5843", HMC5843_ID },
+ { "hmc5883", HMC5883_ID },
+ { "hmc5883l", HMC5883L_ID },
{ }
};
MODULE_DEVICE_TABLE(i2c, hmc5843_id);
@@ -630,5 +762,5 @@ static struct i2c_driver hmc5843_driver = {
module_i2c_driver(hmc5843_driver);
MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com");
-MODULE_DESCRIPTION("HMC5843 driver");
+MODULE_DESCRIPTION("HMC5843/5883/5883L driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
index 57baac6c0d40..f04ece7fbc2f 100644
--- a/drivers/staging/iio/meter/ade7753.c
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -18,8 +18,8 @@
#include <linux/list.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "meter.h"
#include "ade7753.h"
@@ -28,7 +28,7 @@ static int ade7753_spi_write_reg_8(struct device *dev,
u8 val)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7753_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -46,7 +46,7 @@ static int ade7753_spi_write_reg_16(struct device *dev,
u16 value)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7753_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -63,7 +63,7 @@ static int ade7753_spi_read_reg_8(struct device *dev,
u8 reg_address,
u8 *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7753_state *st = iio_priv(indio_dev);
ssize_t ret;
@@ -82,7 +82,7 @@ static int ade7753_spi_read_reg_16(struct device *dev,
u8 reg_address,
u16 *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7753_state *st = iio_priv(indio_dev);
ssize_t ret;
@@ -104,7 +104,7 @@ static int ade7753_spi_read_reg_24(struct device *dev,
u32 *val)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7753_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -416,7 +416,7 @@ static ssize_t ade7753_write_frequency(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7753_state *st = iio_priv(indio_dev);
unsigned long val;
int ret;
@@ -517,7 +517,7 @@ static int __devinit ade7753_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -546,7 +546,7 @@ static int __devinit ade7753_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
@@ -564,7 +564,7 @@ static int ade7753_remove(struct spi_device *spi)
if (ret)
goto err_ret;
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
err_ret:
return ret;
}
diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
index 8d81c92007e9..6cee28a5e877 100644
--- a/drivers/staging/iio/meter/ade7754.c
+++ b/drivers/staging/iio/meter/ade7754.c
@@ -18,8 +18,8 @@
#include <linux/list.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "meter.h"
#include "ade7754.h"
@@ -28,7 +28,7 @@ static int ade7754_spi_write_reg_8(struct device *dev,
u8 val)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7754_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -46,7 +46,7 @@ static int ade7754_spi_write_reg_16(struct device *dev,
u16 value)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7754_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -63,7 +63,7 @@ static int ade7754_spi_read_reg_8(struct device *dev,
u8 reg_address,
u8 *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7754_state *st = iio_priv(indio_dev);
int ret;
@@ -82,7 +82,7 @@ static int ade7754_spi_read_reg_16(struct device *dev,
u8 reg_address,
u16 *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7754_state *st = iio_priv(indio_dev);
int ret;
@@ -104,7 +104,7 @@ static int ade7754_spi_read_reg_24(struct device *dev,
u32 *val)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7754_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -436,7 +436,7 @@ static ssize_t ade7754_write_frequency(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7754_state *st = iio_priv(indio_dev);
unsigned long val;
int ret;
@@ -540,7 +540,7 @@ static int __devinit ade7754_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -568,7 +568,7 @@ static int __devinit ade7754_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
@@ -585,7 +585,7 @@ static int ade7754_remove(struct spi_device *spi)
if (ret)
goto err_ret;
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
err_ret:
return ret;
diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
index dcb20294dfe8..96d6114a31aa 100644
--- a/drivers/staging/iio/meter/ade7758_core.c
+++ b/drivers/staging/iio/meter/ade7758_core.c
@@ -18,9 +18,9 @@
#include <linux/list.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
#include "meter.h"
#include "ade7758.h"
@@ -29,7 +29,7 @@ int ade7758_spi_write_reg_8(struct device *dev,
u8 val)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7758_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -48,7 +48,7 @@ static int ade7758_spi_write_reg_16(struct device *dev,
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7758_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[] = {
{
@@ -77,7 +77,7 @@ static int ade7758_spi_write_reg_24(struct device *dev,
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7758_state *st = iio_priv(indio_dev);
struct spi_transfer xfers[] = {
{
@@ -106,7 +106,7 @@ int ade7758_spi_read_reg_8(struct device *dev,
u8 *val)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7758_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -149,7 +149,7 @@ static int ade7758_spi_read_reg_16(struct device *dev,
u16 *val)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7758_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -195,7 +195,7 @@ static int ade7758_spi_read_reg_24(struct device *dev,
u32 *val)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7758_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -534,7 +534,7 @@ static ssize_t ade7758_write_frequency(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
unsigned long val;
int ret;
u8 reg, t;
@@ -662,66 +662,217 @@ static const struct attribute_group ade7758_attribute_group = {
};
static struct iio_chan_spec ade7758_channels[] = {
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE),
- 0, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT),
- 1, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR),
- 2, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR),
- 3, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 0, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR),
- 4, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 1, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE),
- 5, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 1, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT),
- 6, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 1, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR),
- 7, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 1, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR),
- 8, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 1, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR),
- 9, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 2, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE),
- 10, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 2, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT),
- 11, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 2, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR),
- 12, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 2, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR),
- 13, IIO_ST('s', 24, 32, 0), 0),
- IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 2, 0,
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
- AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR),
- 14, IIO_ST('s', 24, 32, 0), 0),
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_CURRENT,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT),
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_POWER,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "apparent_raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR),
+ .scan_index = 2,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_POWER,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "active_raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR),
+ .scan_index = 3,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_POWER,
+ .indexed = 1,
+ .channel = 0,
+ .extend_name = "reactive_raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR),
+ .scan_index = 4,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 1,
+ .extend_name = "raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE),
+ .scan_index = 5,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_CURRENT,
+ .indexed = 1,
+ .channel = 1,
+ .extend_name = "raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT),
+ .scan_index = 6,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_POWER,
+ .indexed = 1,
+ .channel = 1,
+ .extend_name = "apparent_raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR),
+ .scan_index = 7,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_POWER,
+ .indexed = 1,
+ .channel = 1,
+ .extend_name = "active_raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR),
+ .scan_index = 8,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_POWER,
+ .indexed = 1,
+ .channel = 1,
+ .extend_name = "reactive_raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR),
+ .scan_index = 9,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 2,
+ .extend_name = "raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE),
+ .scan_index = 10,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_CURRENT,
+ .indexed = 1,
+ .channel = 2,
+ .extend_name = "raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT),
+ .scan_index = 11,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_POWER,
+ .indexed = 1,
+ .channel = 2,
+ .extend_name = "apparent_raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR),
+ .scan_index = 12,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_POWER,
+ .indexed = 1,
+ .channel = 2,
+ .extend_name = "active_raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR),
+ .scan_index = 13,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ }, {
+ .type = IIO_POWER,
+ .indexed = 1,
+ .channel = 2,
+ .extend_name = "reactive_raw",
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+ IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ .address = AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR),
+ .scan_index = 14,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+ },
IIO_CHAN_SOFT_TIMESTAMP(15),
};
@@ -734,7 +885,7 @@ static int __devinit ade7758_probe(struct spi_device *spi)
{
int i, ret;
struct ade7758_state *st;
- struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
+ struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
@@ -800,7 +951,7 @@ static int __devinit ade7758_probe(struct spi_device *spi)
return 0;
error_remove_trigger:
- if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
+ if (spi->irq)
ade7758_remove_trigger(indio_dev);
error_uninitialize_ring:
ade7758_uninitialize_ring(indio_dev);
@@ -811,7 +962,7 @@ error_free_tx:
error_free_rx:
kfree(st->rx);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -833,7 +984,7 @@ static int ade7758_remove(struct spi_device *spi)
kfree(st->tx);
kfree(st->rx);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
err_ret:
return ret;
diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c
index c45b23bb1229..92159f208d14 100644
--- a/drivers/staging/iio/meter/ade7758_ring.c
+++ b/drivers/staging/iio/meter/ade7758_ring.c
@@ -12,18 +12,17 @@
#include <linux/slab.h>
#include <asm/unaligned.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#include "../ring_sw.h"
-#include "../trigger_consumer.h"
+#include <linux/iio/trigger_consumer.h>
#include "ade7758.h"
/**
* ade7758_spi_read_burst() - read data registers
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @indio_dev: the IIO device
**/
-static int ade7758_spi_read_burst(struct device *dev)
+static int ade7758_spi_read_burst(struct iio_dev *indio_dev)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ade7758_state *st = iio_priv(indio_dev);
int ret;
@@ -68,11 +67,11 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p)
u32 *dat32 = (u32 *)dat64;
if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
- if (ade7758_spi_read_burst(&indio_dev->dev) >= 0)
+ if (ade7758_spi_read_burst(indio_dev) >= 0)
*dat32 = get_unaligned_be32(&st->rx_buf[5]) & 0xFFFFFF;
/* Guaranteed to be aligned with 8 byte boundary */
- if (ring->scan_timestamp)
+ if (indio_dev->scan_timestamp)
dat64[1] = pf->timestamp;
ring->access->store_to(ring, (u8 *)dat64, pf->timestamp);
@@ -92,29 +91,19 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p)
static int ade7758_ring_preenable(struct iio_dev *indio_dev)
{
struct ade7758_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
- size_t d_size;
unsigned channel;
+ int ret;
if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
return -EINVAL;
+ ret = iio_sw_buffer_preenable(indio_dev);
+ if (ret < 0)
+ return ret;
+
channel = find_first_bit(indio_dev->active_scan_mask,
indio_dev->masklength);
- d_size = st->ade7758_ring_channels[channel].scan_type.storagebits / 8;
-
- if (ring->scan_timestamp) {
- d_size += sizeof(s64);
-
- if (d_size % sizeof(s64))
- d_size += sizeof(s64) - (d_size % sizeof(s64));
- }
-
- if (indio_dev->buffer->access->set_bytes_per_datum)
- indio_dev->buffer->access->
- set_bytes_per_datum(indio_dev->buffer, d_size);
-
ade7758_write_waveform_type(&indio_dev->dev,
st->ade7758_ring_channels[channel].address);
diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c
index b6569c706651..f9c6a340092b 100644
--- a/drivers/staging/iio/meter/ade7758_trigger.c
+++ b/drivers/staging/iio/meter/ade7758_trigger.c
@@ -11,8 +11,8 @@
#include <linux/spi/spi.h>
#include <linux/export.h>
-#include "../iio.h"
-#include "../trigger.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
#include "ade7758.h"
/**
@@ -63,7 +63,7 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev)
struct ade7758_state *st = iio_priv(indio_dev);
int ret;
- st->trig = iio_allocate_trigger("%s-dev%d",
+ st->trig = iio_trigger_alloc("%s-dev%d",
spi_get_device_id(st->us)->name,
indio_dev->id);
if (st->trig == NULL) {
@@ -94,7 +94,7 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev)
error_free_irq:
free_irq(st->us->irq, st->trig);
error_free_trig:
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
error_ret:
return ret;
}
@@ -105,5 +105,5 @@ void ade7758_remove_trigger(struct iio_dev *indio_dev)
iio_trigger_unregister(st->trig);
free_irq(st->us->irq, st->trig);
- iio_free_trigger(st->trig);
+ iio_trigger_free(st->trig);
}
diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
index 0beab478dcd9..b3f7e0fa9612 100644
--- a/drivers/staging/iio/meter/ade7759.c
+++ b/drivers/staging/iio/meter/ade7759.c
@@ -18,8 +18,8 @@
#include <linux/list.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "meter.h"
#include "ade7759.h"
@@ -28,7 +28,7 @@ static int ade7759_spi_write_reg_8(struct device *dev,
u8 val)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7759_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -46,7 +46,7 @@ static int ade7759_spi_write_reg_16(struct device *dev,
u16 value)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7759_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -63,7 +63,7 @@ static int ade7759_spi_read_reg_8(struct device *dev,
u8 reg_address,
u8 *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7759_state *st = iio_priv(indio_dev);
int ret;
@@ -82,7 +82,7 @@ static int ade7759_spi_read_reg_16(struct device *dev,
u8 reg_address,
u16 *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7759_state *st = iio_priv(indio_dev);
int ret;
@@ -104,7 +104,7 @@ static int ade7759_spi_read_reg_40(struct device *dev,
u64 *val)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7759_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -376,7 +376,7 @@ static ssize_t ade7759_write_frequency(struct device *dev,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7759_state *st = iio_priv(indio_dev);
unsigned long val;
int ret;
@@ -463,7 +463,7 @@ static int __devinit ade7759_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -491,7 +491,7 @@ static int __devinit ade7759_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -507,7 +507,7 @@ static int ade7759_remove(struct spi_device *spi)
if (ret)
goto err_ret;
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
err_ret:
return ret;
diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c
index 1e1faa0479d3..06090465fa5f 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -12,7 +12,7 @@
#include <linux/slab.h>
#include <linux/module.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#include "ade7854.h"
static int ade7854_i2c_write_reg_8(struct device *dev,
@@ -20,7 +20,7 @@ static int ade7854_i2c_write_reg_8(struct device *dev,
u8 value)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -39,7 +39,7 @@ static int ade7854_i2c_write_reg_16(struct device *dev,
u16 value)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -59,7 +59,7 @@ static int ade7854_i2c_write_reg_24(struct device *dev,
u32 value)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -80,7 +80,7 @@ static int ade7854_i2c_write_reg_32(struct device *dev,
u32 value)
{
int ret;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
mutex_lock(&st->buf_lock);
@@ -101,7 +101,7 @@ static int ade7854_i2c_read_reg_8(struct device *dev,
u16 reg_address,
u8 *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
@@ -127,7 +127,7 @@ static int ade7854_i2c_read_reg_16(struct device *dev,
u16 reg_address,
u16 *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
@@ -153,7 +153,7 @@ static int ade7854_i2c_read_reg_24(struct device *dev,
u16 reg_address,
u32 *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
@@ -179,7 +179,7 @@ static int ade7854_i2c_read_reg_32(struct device *dev,
u16 reg_address,
u32 *val)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
@@ -208,7 +208,7 @@ static int __devinit ade7854_i2c_probe(struct i2c_client *client,
struct ade7854_state *st;
struct iio_dev *indio_dev;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
@@ -226,7 +226,7 @@ static int __devinit ade7854_i2c_probe(struct i2c_client *client,
ret = ade7854_probe(indio_dev, &client->dev);
if (ret)
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
index 81121862c1bd..9fb2f8bfca81 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -12,7 +12,7 @@
#include <linux/slab.h>
#include <linux/module.h>
-#include "../iio.h"
+#include <linux/iio/iio.h>
#include "ade7854.h"
static int ade7854_spi_write_reg_8(struct device *dev,
@@ -21,7 +21,7 @@ static int ade7854_spi_write_reg_8(struct device *dev,
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
struct spi_transfer xfer = {
.tx_buf = st->tx,
@@ -49,7 +49,7 @@ static int ade7854_spi_write_reg_16(struct device *dev,
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
struct spi_transfer xfer = {
.tx_buf = st->tx,
@@ -78,7 +78,7 @@ static int ade7854_spi_write_reg_24(struct device *dev,
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
struct spi_transfer xfer = {
.tx_buf = st->tx,
@@ -108,7 +108,7 @@ static int ade7854_spi_write_reg_32(struct device *dev,
{
int ret;
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
struct spi_transfer xfer = {
.tx_buf = st->tx,
@@ -138,7 +138,7 @@ static int ade7854_spi_read_reg_8(struct device *dev,
u8 *val)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -180,7 +180,7 @@ static int ade7854_spi_read_reg_16(struct device *dev,
u16 *val)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -221,7 +221,7 @@ static int ade7854_spi_read_reg_24(struct device *dev,
u32 *val)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -263,7 +263,7 @@ static int ade7854_spi_read_reg_32(struct device *dev,
u32 *val)
{
struct spi_message msg;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
@@ -306,7 +306,7 @@ static int __devinit ade7854_spi_probe(struct spi_device *spi)
struct ade7854_state *st;
struct iio_dev *indio_dev;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
@@ -325,7 +325,7 @@ static int __devinit ade7854_spi_probe(struct spi_device *spi)
ret = ade7854_probe(indio_dev, &spi->dev);
if (ret)
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c
index 49c01c5c1b59..c642da84842a 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -17,8 +17,8 @@
#include <linux/list.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "meter.h"
#include "ade7854.h"
@@ -28,7 +28,7 @@ static ssize_t ade7854_read_8bit(struct device *dev,
{
int ret;
u8 val = 0;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -45,7 +45,7 @@ static ssize_t ade7854_read_16bit(struct device *dev,
{
int ret;
u16 val = 0;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -62,7 +62,7 @@ static ssize_t ade7854_read_24bit(struct device *dev,
{
int ret;
u32 val;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -80,7 +80,7 @@ static ssize_t ade7854_read_32bit(struct device *dev,
int ret;
u32 val = 0;
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
ret = st->read_reg_32(dev, this_attr->address, &val);
@@ -96,7 +96,7 @@ static ssize_t ade7854_write_8bit(struct device *dev,
size_t len)
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
@@ -117,7 +117,7 @@ static ssize_t ade7854_write_16bit(struct device *dev,
size_t len)
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
@@ -138,7 +138,7 @@ static ssize_t ade7854_write_24bit(struct device *dev,
size_t len)
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
@@ -159,7 +159,7 @@ static ssize_t ade7854_write_32bit(struct device *dev,
size_t len)
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
@@ -176,7 +176,7 @@ error_ret:
static int ade7854_reset(struct device *dev)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
u16 val;
@@ -425,7 +425,7 @@ static IIO_DEV_ATTR_CVAHR(ade7854_read_32bit,
static int ade7854_set_irq(struct device *dev, bool enable)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
@@ -581,7 +581,7 @@ int ade7854_probe(struct iio_dev *indio_dev, struct device *dev)
error_unreg_dev:
iio_device_unregister(indio_dev);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return ret;
}
@@ -590,7 +590,7 @@ EXPORT_SYMBOL(ade7854_probe);
int ade7854_remove(struct iio_dev *indio_dev)
{
iio_device_unregister(indio_dev);
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/meter/meter.h b/drivers/staging/iio/meter/meter.h
index 6a3db1423631..23e1b5f480a9 100644
--- a/drivers/staging/iio/meter/meter.h
+++ b/drivers/staging/iio/meter/meter.h
@@ -1,4 +1,4 @@
-#include "../sysfs.h"
+#include <linux/iio/sysfs.h>
/* metering ic types of attribute */
diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c
index d8ce854c1897..8b71eb0e16f5 100644
--- a/drivers/staging/iio/resolver/ad2s1200.c
+++ b/drivers/staging/iio/resolver/ad2s1200.c
@@ -19,8 +19,8 @@
#include <linux/gpio.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#define DRV_NAME "ad2s1200"
@@ -85,10 +85,12 @@ static const struct iio_chan_spec ad2s1200_channels[] = {
.type = IIO_ANGL,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
}, {
.type = IIO_ANGL_VEL,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
}
};
@@ -110,7 +112,7 @@ static int __devinit ad2s1200_probe(struct spi_device *spi)
DRV_NAME, pins[pn]);
goto error_ret;
}
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -140,7 +142,7 @@ static int __devinit ad2s1200_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
for (--pn; pn >= 0; pn--)
gpio_free(pins[pn]);
@@ -150,7 +152,7 @@ error_ret:
static int __devexit ad2s1200_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_free_device(spi_get_drvdata(spi));
+ iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
index c439fcf72be7..f313859476c1 100644
--- a/drivers/staging/iio/resolver/ad2s1210.c
+++ b/drivers/staging/iio/resolver/ad2s1210.c
@@ -18,8 +18,8 @@
#include <linux/gpio.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
#include "ad2s1210.h"
#define DRV_NAME "ad2s1210"
@@ -200,7 +200,7 @@ static ssize_t ad2s1210_store_softreset(struct device *dev,
const char *buf,
size_t len)
{
- struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+ struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
int ret;
mutex_lock(&st->lock);
@@ -214,7 +214,7 @@ static ssize_t ad2s1210_show_fclkin(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+ struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
return sprintf(buf, "%d\n", st->fclkin);
}
@@ -223,7 +223,7 @@ static ssize_t ad2s1210_store_fclkin(struct device *dev,
const char *buf,
size_t len)
{
- struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+ struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
unsigned long fclkin;
int ret;
@@ -252,7 +252,7 @@ static ssize_t ad2s1210_show_fexcit(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+ struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
return sprintf(buf, "%d\n", st->fexcit);
}
@@ -260,7 +260,7 @@ static ssize_t ad2s1210_store_fexcit(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+ struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
unsigned long fexcit;
int ret;
@@ -287,7 +287,7 @@ static ssize_t ad2s1210_show_control(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+ struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
int ret;
mutex_lock(&st->lock);
ret = ad2s1210_config_read(st, AD2S1210_REG_CONTROL);
@@ -299,7 +299,7 @@ static ssize_t ad2s1210_store_control(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+ struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
unsigned long udata;
unsigned char data;
int ret;
@@ -345,7 +345,7 @@ error_ret:
static ssize_t ad2s1210_show_resolution(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+ struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
return sprintf(buf, "%d\n", st->resolution);
}
@@ -353,7 +353,7 @@ static ssize_t ad2s1210_store_resolution(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+ struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
unsigned char data;
unsigned long udata;
int ret;
@@ -403,7 +403,7 @@ error_ret:
static ssize_t ad2s1210_show_fault(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+ struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
int ret;
mutex_lock(&st->lock);
@@ -418,7 +418,7 @@ static ssize_t ad2s1210_clear_fault(struct device *dev,
const char *buf,
size_t len)
{
- struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+ struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
int ret;
mutex_lock(&st->lock);
@@ -441,7 +441,7 @@ static ssize_t ad2s1210_show_reg(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+ struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
struct iio_dev_attr *iattr = to_iio_dev_attr(attr);
int ret;
@@ -455,7 +455,7 @@ static ssize_t ad2s1210_show_reg(struct device *dev,
static ssize_t ad2s1210_store_reg(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
- struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+ struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
unsigned long data;
int ret;
struct iio_dev_attr *iattr = to_iio_dev_attr(attr);
@@ -580,10 +580,12 @@ static struct iio_chan_spec ad2s1210_channels[] = {
.type = IIO_ANGL,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
}, {
.type = IIO_ANGL_VEL,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
}
};
@@ -688,7 +690,7 @@ static int __devinit ad2s1210_probe(struct spi_device *spi)
if (spi->dev.platform_data == NULL)
return -EINVAL;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -729,7 +731,7 @@ static int __devinit ad2s1210_probe(struct spi_device *spi)
error_free_gpios:
ad2s1210_free_gpios(st);
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -740,7 +742,7 @@ static int __devexit ad2s1210_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
ad2s1210_free_gpios(iio_priv(indio_dev));
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
index 2a86f582ddf1..a8057228dca1 100644
--- a/drivers/staging/iio/resolver/ad2s90.c
+++ b/drivers/staging/iio/resolver/ad2s90.c
@@ -16,8 +16,8 @@
#include <linux/sysfs.h>
#include <linux/module.h>
-#include "../iio.h"
-#include "../sysfs.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
struct ad2s90_state {
struct mutex lock;
@@ -55,6 +55,7 @@ static const struct iio_chan_spec ad2s90_chan = {
.type = IIO_ANGL,
.indexed = 1,
.channel = 0,
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
};
static int __devinit ad2s90_probe(struct spi_device *spi)
@@ -63,7 +64,7 @@ static int __devinit ad2s90_probe(struct spi_device *spi)
struct ad2s90_state *st;
int ret = 0;
- indio_dev = iio_allocate_device(sizeof(*st));
+ indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_ret;
@@ -92,7 +93,7 @@ static int __devinit ad2s90_probe(struct spi_device *spi)
return 0;
error_free_dev:
- iio_free_device(indio_dev);
+ iio_device_free(indio_dev);
error_ret:
return ret;
}
@@ -100,7 +101,7 @@ error_ret:
static int __devexit ad2s90_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_free_device(spi_get_drvdata(spi));
+ iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c
index b9945ec44faa..9358c6cb1c72 100644
--- a/drivers/staging/iio/ring_sw.c
+++ b/drivers/staging/iio/ring_sw.c
@@ -15,7 +15,7 @@
#include <linux/sched.h>
#include <linux/poll.h>
#include "ring_sw.h"
-#include "trigger.h"
+#include <linux/iio/trigger.h>
/**
* struct iio_sw_ring_buffer - software ring buffer
diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h
index 7556e2122367..a5857aa7aefa 100644
--- a/drivers/staging/iio/ring_sw.h
+++ b/drivers/staging/iio/ring_sw.h
@@ -23,7 +23,7 @@
#ifndef _IIO_RING_SW_H_
#define _IIO_RING_SW_H_
-#include "buffer.h"
+#include <linux/iio/buffer.h>
struct iio_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev);
void iio_sw_rb_free(struct iio_buffer *ring);
diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
index 665653d79f02..f85734d212bb 100644
--- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
@@ -15,8 +15,8 @@
#include <asm/gptimers.h>
-#include "../iio.h"
-#include "../trigger.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
struct bfin_timer {
unsigned short id, bit;
@@ -172,7 +172,7 @@ static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
st->timer_num = ret;
st->t = &iio_bfin_timer_code[st->timer_num];
- st->trig = iio_allocate_trigger("bfintmr%d", st->timer_num);
+ st->trig = iio_trigger_alloc("bfintmr%d", st->timer_num);
if (!st->trig) {
ret = -ENOMEM;
goto out1;
@@ -203,7 +203,7 @@ static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
out4:
iio_trigger_unregister(st->trig);
out2:
- iio_put_trigger(st->trig);
+ iio_trigger_put(st->trig);
out1:
kfree(st);
out:
@@ -217,7 +217,7 @@ static int __devexit iio_bfin_tmr_trigger_remove(struct platform_device *pdev)
disable_gptimers(st->t->bit);
free_irq(st->irq, st);
iio_trigger_unregister(st->trig);
- iio_put_trigger(st->trig);
+ iio_trigger_put(st->trig);
kfree(st);
return 0;
diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c
index a3465947235e..90b26846fc6b 100644
--- a/drivers/staging/iio/trigger/iio-trig-gpio.c
+++ b/drivers/staging/iio/trigger/iio-trig-gpio.c
@@ -22,8 +22,8 @@
#include <linux/gpio.h>
#include <linux/slab.h>
-#include "../iio.h"
-#include "../trigger.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
static LIST_HEAD(iio_gpio_trigger_list);
static DEFINE_MUTEX(iio_gpio_trigger_list_lock);
@@ -72,7 +72,7 @@ static int iio_gpio_trigger_probe(struct platform_device *pdev)
for (irq = irq_res->start; irq <= irq_res->end; irq++) {
- trig = iio_allocate_trigger("irqtrig%d", irq);
+ trig = iio_trigger_alloc("irqtrig%d", irq);
if (!trig) {
ret = -ENOMEM;
goto error_free_completed_registrations;
@@ -114,7 +114,7 @@ error_release_irq:
error_free_trig_info:
kfree(trig_info);
error_put_trigger:
- iio_put_trigger(trig);
+ iio_trigger_put(trig);
error_free_completed_registrations:
/* The rest should have been added to the iio_gpio_trigger_list */
list_for_each_entry_safe(trig,
@@ -144,7 +144,7 @@ static int iio_gpio_trigger_remove(struct platform_device *pdev)
iio_trigger_unregister(trig);
free_irq(trig_info->irq, trig);
kfree(trig_info);
- iio_put_trigger(trig);
+ iio_trigger_put(trig);
}
mutex_unlock(&iio_gpio_trigger_list_lock);
diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
index a80cf67bf84d..9f2d055524a3 100644
--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
@@ -16,8 +16,8 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/rtc.h>
-#include "../iio.h"
-#include "../trigger.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
static LIST_HEAD(iio_prtc_trigger_list);
static DEFINE_MUTEX(iio_prtc_trigger_list_lock);
@@ -112,7 +112,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev)
for (i = 0;; i++) {
if (pdata[i] == NULL)
break;
- trig = iio_allocate_trigger("periodic%s", pdata[i]);
+ trig = iio_trigger_alloc("periodic%s", pdata[i]);
if (!trig) {
ret = -ENOMEM;
goto error_free_completed_registrations;
@@ -152,7 +152,7 @@ error_free_trig_info:
kfree(trig_info);
error_put_trigger_and_remove_from_list:
list_del(&trig->alloc_list);
- iio_put_trigger(trig);
+ iio_trigger_put(trig);
error_free_completed_registrations:
list_for_each_entry_safe(trig,
trig2,
diff --git a/drivers/staging/iio/trigger/iio-trig-sysfs.c b/drivers/staging/iio/trigger/iio-trig-sysfs.c
index 174dc65709d5..552763bb3d4c 100644
--- a/drivers/staging/iio/trigger/iio-trig-sysfs.c
+++ b/drivers/staging/iio/trigger/iio-trig-sysfs.c
@@ -11,8 +11,8 @@
#include <linux/slab.h>
#include <linux/list.h>
-#include "../iio.h"
-#include "../trigger.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
struct iio_sysfs_trig {
struct iio_trigger *trig;
@@ -139,7 +139,7 @@ static int iio_sysfs_trigger_probe(int id)
goto out1;
}
t->id = id;
- t->trig = iio_allocate_trigger("sysfstrig%d", id);
+ t->trig = iio_trigger_alloc("sysfstrig%d", id);
if (!t->trig) {
ret = -ENOMEM;
goto free_t;
@@ -158,7 +158,7 @@ static int iio_sysfs_trigger_probe(int id)
return 0;
out2:
- iio_put_trigger(t->trig);
+ iio_trigger_put(t->trig);
free_t:
kfree(t);
out1:
@@ -182,7 +182,7 @@ static int iio_sysfs_trigger_remove(int id)
}
iio_trigger_unregister(t->trig);
- iio_free_trigger(t->trig);
+ iio_trigger_free(t->trig);
list_del(&t->l);
kfree(t);
diff --git a/drivers/staging/ipack/Kconfig b/drivers/staging/ipack/Kconfig
new file mode 100644
index 000000000000..af321789dddb
--- /dev/null
+++ b/drivers/staging/ipack/Kconfig
@@ -0,0 +1,20 @@
+#
+# IPACK configuration.
+#
+
+menuconfig IPACK_BUS
+ tristate "IndustryPack bus support"
+ ---help---
+ If you say Y here you get support for the IndustryPack Framework
+ for drivers for many types of boards that support this industrial
+ bus. The IndustryPack Framework is a virtual bus allowing to
+ communicate between carrier and mezzanine cards connected through
+ this bus.
+
+if IPACK_BUS
+
+source "drivers/staging/ipack/bridges/Kconfig"
+
+source "drivers/staging/ipack/devices/Kconfig"
+
+endif # IPACK
diff --git a/drivers/staging/ipack/Makefile b/drivers/staging/ipack/Makefile
new file mode 100644
index 000000000000..85ff223616fd
--- /dev/null
+++ b/drivers/staging/ipack/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the IPACK bridge device drivers.
+#
+obj-$(CONFIG_IPACK_BUS) += ipack.o
+obj-y += devices/
+obj-y += bridges/
diff --git a/drivers/staging/ipack/TODO b/drivers/staging/ipack/TODO
new file mode 100644
index 000000000000..3a45a53afd88
--- /dev/null
+++ b/drivers/staging/ipack/TODO
@@ -0,0 +1,46 @@
+ TODO
+ ====
+Introduction
+============
+
+These drivers add support for IndustryPack devices: carrier and mezzanine
+boards.
+
+The ipack driver is just an abstraction of the bus providing the common
+operations between the two kind of boards.
+
+TODO
+====
+
+TPCI-200
+--------
+
+* It receives the name of the mezzanine plugged in each slot by SYSFS.
+ No autodetection supported yet, because the mezzanine driver could not be
+ loaded at the time that the tpci200 driver loads.
+
+* It has a linked list with the tpci200 devices it is managing. Get rid of it
+ and use driver_for_each_device() instead.
+
+IP-OCTAL
+--------
+
+* It has a linked list which saves the devices it is currently
+ managing. It should use the driver_for_each_device() function. It is not there
+ due to the impossibility of using container_of macro to recover the
+ corresponding "struct ipoctal" because the attribute "struct ipack_device" is
+ a pointer. This code should be refactored.
+
+Ipack
+-----
+
+* The structures and API exported can be improved a lot. For example, the
+ way to unregistering mezzanine devices, doing the mezzanine driver a call to
+ remove_device() to notify the carrier driver, or the opposite with the call to
+ the ipack_driver_ops' remove() function could be improved.
+
+
+Contact
+=======
+
+Contact: Samuel Iglesias Gonsalvez <siglesias@igalia.com> \ No newline at end of file
diff --git a/drivers/staging/ipack/bridges/Kconfig b/drivers/staging/ipack/bridges/Kconfig
new file mode 100644
index 000000000000..97c837ea7a03
--- /dev/null
+++ b/drivers/staging/ipack/bridges/Kconfig
@@ -0,0 +1,8 @@
+config BOARD_TPCI200
+ tristate "TEWS TPCI-200 support for IndustryPack bus"
+ depends on IPACK_BUS
+ depends on PCI
+ help
+ This driver supports the TEWS TPCI200 device for the IndustryPack bus.
+ default n
+
diff --git a/drivers/staging/ipack/bridges/Makefile b/drivers/staging/ipack/bridges/Makefile
new file mode 100644
index 000000000000..d8b76459300f
--- /dev/null
+++ b/drivers/staging/ipack/bridges/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_BOARD_TPCI200) += tpci200.o
diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c
new file mode 100644
index 000000000000..ad2870750235
--- /dev/null
+++ b/drivers/staging/ipack/bridges/tpci200.c
@@ -0,0 +1,1141 @@
+/**
+ * tpci200.c
+ *
+ * driver for the TEWS TPCI-200 device
+ * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
+ * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
+ * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include "tpci200.h"
+
+static struct ipack_bus_ops tpci200_bus_ops;
+
+/* TPCI200 controls registers */
+static int control_reg[] = {
+ TPCI200_CONTROL_A_REG,
+ TPCI200_CONTROL_B_REG,
+ TPCI200_CONTROL_C_REG,
+ TPCI200_CONTROL_D_REG
+};
+
+/* Linked list to save the registered devices */
+static LIST_HEAD(tpci200_list);
+
+static int tpci200_slot_unregister(struct ipack_device *dev);
+
+static struct tpci200_board *check_slot(struct ipack_device *dev)
+{
+ struct tpci200_board *tpci200;
+ int found = 0;
+
+ if (dev == NULL) {
+ pr_info("Slot doesn't exist.\n");
+ return NULL;
+ }
+
+ list_for_each_entry(tpci200, &tpci200_list, list) {
+ if (tpci200->number == dev->bus_nr) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ pr_err("Carrier not found\n");
+ return NULL;
+ }
+
+ if (dev->slot >= TPCI200_NB_SLOT) {
+ pr_info("Slot [%d:%d] doesn't exist! Last tpci200 slot is %d.\n",
+ dev->bus_nr, dev->slot, TPCI200_NB_SLOT-1);
+ return NULL;
+ }
+
+ BUG_ON(tpci200->slots == NULL);
+ if (tpci200->slots[dev->slot].dev == NULL) {
+ pr_info("Slot [%d:%d] is not registered !\n", dev->bus_nr,
+ dev->slot);
+ return NULL;
+ }
+
+ return tpci200;
+}
+
+static inline unsigned char __tpci200_read8(void __iomem *address,
+ unsigned long offset)
+{
+ return ioread8(address + (offset^1));
+}
+
+static inline unsigned short __tpci200_read16(void __iomem *address,
+ unsigned long offset)
+{
+ return ioread16(address + offset);
+}
+
+static inline unsigned int __tpci200_read32(void __iomem *address,
+ unsigned long offset)
+{
+ return swahw32(ioread32(address + offset));
+}
+
+static inline void __tpci200_write8(unsigned char value,
+ void __iomem *address, unsigned long offset)
+{
+ iowrite8(value, address+(offset^1));
+}
+
+static inline void __tpci200_write16(unsigned short value,
+ void __iomem *address,
+ unsigned long offset)
+{
+ iowrite16(value, address+offset);
+}
+
+static inline void __tpci200_write32(unsigned int value,
+ void __iomem *address,
+ unsigned long offset)
+{
+ iowrite32(swahw32(value), address+offset);
+}
+
+static struct ipack_addr_space *get_slot_address_space(struct ipack_device *dev,
+ int space)
+{
+ struct ipack_addr_space *addr;
+
+ switch (space) {
+ case IPACK_IO_SPACE:
+ addr = &dev->io_space;
+ break;
+ case IPACK_ID_SPACE:
+ addr = &dev->id_space;
+ break;
+ case IPACK_MEM_SPACE:
+ addr = &dev->mem_space;
+ break;
+ default:
+ pr_err("Slot [%d:%d] space number %d doesn't exist !\n",
+ dev->bus_nr, dev->slot, space);
+ return NULL;
+ break;
+ }
+
+ if ((addr->size == 0) || (addr->address == NULL)) {
+ pr_err("Error, slot space not mapped !\n");
+ return NULL;
+ }
+
+ return addr;
+}
+
+static int tpci200_read8(struct ipack_device *dev, int space,
+ unsigned long offset, unsigned char *value)
+{
+ struct ipack_addr_space *addr;
+ struct tpci200_board *tpci200;
+
+ tpci200 = check_slot(dev);
+ if (tpci200 == NULL)
+ return -EINVAL;
+
+ addr = get_slot_address_space(dev, space);
+ if (addr == NULL)
+ return -EINVAL;
+
+ if (offset >= addr->size) {
+ pr_err("Error, slot space offset error !\n");
+ return -EFAULT;
+ }
+
+ *value = __tpci200_read8(addr->address, offset);
+
+ return 0;
+}
+
+static int tpci200_read16(struct ipack_device *dev, int space,
+ unsigned long offset, unsigned short *value)
+{
+ struct ipack_addr_space *addr;
+ struct tpci200_board *tpci200;
+
+ tpci200 = check_slot(dev);
+ if (tpci200 == NULL)
+ return -EINVAL;
+
+ addr = get_slot_address_space(dev, space);
+ if (addr == NULL)
+ return -EINVAL;
+
+ if ((offset+2) >= addr->size) {
+ pr_err("Error, slot space offset error !\n");
+ return -EFAULT;
+ }
+ *value = __tpci200_read16(addr->address, offset);
+
+ return 0;
+}
+
+static int tpci200_read32(struct ipack_device *dev, int space,
+ unsigned long offset, unsigned int *value)
+{
+ struct ipack_addr_space *addr;
+ struct tpci200_board *tpci200;
+
+ tpci200 = check_slot(dev);
+ if (tpci200 == NULL)
+ return -EINVAL;
+
+ addr = get_slot_address_space(dev, space);
+ if (addr == NULL)
+ return -EINVAL;
+
+ if ((offset+4) >= addr->size) {
+ pr_err("Error, slot space offset error !\n");
+ return -EFAULT;
+ }
+
+ *value = __tpci200_read32(addr->address, offset);
+
+ return 0;
+}
+
+static int tpci200_write8(struct ipack_device *dev, int space,
+ unsigned long offset, unsigned char value)
+{
+ struct ipack_addr_space *addr;
+ struct tpci200_board *tpci200;
+
+ tpci200 = check_slot(dev);
+ if (tpci200 == NULL)
+ return -EINVAL;
+
+ addr = get_slot_address_space(dev, space);
+ if (addr == NULL)
+ return -EINVAL;
+
+ if (offset >= addr->size) {
+ pr_err("Error, slot space offset error !\n");
+ return -EFAULT;
+ }
+
+ __tpci200_write8(value, addr->address, offset);
+
+ return 0;
+}
+
+static int tpci200_write16(struct ipack_device *dev, int space,
+ unsigned long offset, unsigned short value)
+{
+ struct ipack_addr_space *addr;
+ struct tpci200_board *tpci200;
+
+ tpci200 = check_slot(dev);
+ if (tpci200 == NULL)
+ return -EINVAL;
+
+ addr = get_slot_address_space(dev, space);
+ if (addr == NULL)
+ return -EINVAL;
+
+ if ((offset+2) >= addr->size) {
+ pr_err("Error, slot space offset error !\n");
+ return -EFAULT;
+ }
+
+ __tpci200_write16(value, addr->address, offset);
+
+ return 0;
+}
+
+static int tpci200_write32(struct ipack_device *dev, int space,
+ unsigned long offset, unsigned int value)
+{
+ struct ipack_addr_space *addr;
+ struct tpci200_board *tpci200;
+
+ tpci200 = check_slot(dev);
+ if (tpci200 == NULL)
+ return -EINVAL;
+
+ addr = get_slot_address_space(dev, space);
+ if (addr == NULL)
+ return -EINVAL;
+
+ if ((offset+4) >= addr->size) {
+ pr_err("Error, slot space offset error !\n");
+ return -EFAULT;
+ }
+
+ __tpci200_write32(value, addr->address, offset);
+
+ return 0;
+}
+
+static void tpci200_unregister(struct tpci200_board *tpci200)
+{
+ int i;
+
+ free_irq(tpci200->info->pdev->irq, (void *) tpci200);
+
+ pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
+ pci_iounmap(tpci200->info->pdev, tpci200->info->ioidint_space);
+ pci_iounmap(tpci200->info->pdev, tpci200->info->mem8_space);
+
+ pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
+ pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
+ pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
+
+ pci_disable_device(tpci200->info->pdev);
+ pci_dev_put(tpci200->info->pdev);
+
+ kfree(tpci200->info);
+
+ for (i = 0; i < TPCI200_NB_SLOT; i++) {
+ tpci200->slots[i].io_phys.address = NULL;
+ tpci200->slots[i].io_phys.size = 0;
+ tpci200->slots[i].id_phys.address = NULL;
+ tpci200->slots[i].id_phys.size = 0;
+ tpci200->slots[i].mem_phys.address = NULL;
+ tpci200->slots[i].mem_phys.size = 0;
+ }
+}
+
+static irqreturn_t tpci200_interrupt(int irq, void *dev_id)
+{
+ struct tpci200_board *tpci200 = (struct tpci200_board *) dev_id;
+ int i;
+ unsigned long flags;
+ unsigned short status_reg, reg_value;
+ unsigned short unhandled_ints = 0;
+ irqreturn_t ret = IRQ_NONE;
+
+ spin_lock_irqsave(&tpci200->info->access_lock, flags);
+
+ /* Read status register */
+ status_reg = readw(tpci200->info->interface_regs +
+ TPCI200_STATUS_REG);
+
+ if (status_reg & TPCI200_SLOT_INT_MASK) {
+ unhandled_ints = status_reg & TPCI200_SLOT_INT_MASK;
+ /* callback to the IRQ handler for the corresponding slot */
+ for (i = 0; i < TPCI200_NB_SLOT; i++) {
+ if ((tpci200->slots[i].irq != NULL) &&
+ (status_reg & ((TPCI200_A_INT0 | TPCI200_A_INT1) << (2*i)))) {
+
+ ret = tpci200->slots[i].irq->handler(tpci200->slots[i].irq->arg);
+
+ /* Dummy reads */
+ readw(tpci200->slots[i].dev->io_space.address +
+ 0xC0);
+ readw(tpci200->slots[i].dev->io_space.address +
+ 0xC2);
+
+ unhandled_ints &= ~(((TPCI200_A_INT0 | TPCI200_A_INT1) << (2*i)));
+ }
+ }
+ }
+ /* Interrupt not handled are disabled */
+ if (unhandled_ints) {
+ for (i = 0; i < TPCI200_NB_SLOT; i++) {
+ if (unhandled_ints & ((TPCI200_INT0_EN | TPCI200_INT1_EN) << (2*i))) {
+ pr_info("No registered ISR for slot [%d:%d]!. IRQ will be disabled.\n",
+ tpci200->number, i);
+ reg_value = readw(
+ tpci200->info->interface_regs +
+ control_reg[i]);
+ reg_value &=
+ ~(TPCI200_INT0_EN | TPCI200_INT1_EN);
+ writew(reg_value,
+ (tpci200->info->interface_regs +
+ control_reg[i]));
+ }
+ }
+ }
+
+ spin_unlock_irqrestore(&tpci200->info->access_lock, flags);
+ return ret;
+}
+
+#ifdef CONFIG_SYSFS
+
+static struct ipack_device *tpci200_slot_register(unsigned int tpci200_number,
+ unsigned int slot_position)
+{
+ int found = 0;
+ struct ipack_device *dev;
+ struct tpci200_board *tpci200;
+
+ list_for_each_entry(tpci200, &tpci200_list, list) {
+ if (tpci200->number == tpci200_number) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ pr_err("carrier board not found for the device\n");
+ return NULL;
+ }
+
+ if (slot_position >= TPCI200_NB_SLOT) {
+ pr_info("Slot [%d:%d] doesn't exist!\n", tpci200_number,
+ slot_position);
+ return NULL;
+ }
+
+ if (mutex_lock_interruptible(&tpci200->mutex))
+ return NULL;
+
+ if (tpci200->slots[slot_position].dev != NULL) {
+ pr_err("Slot [%d:%d] already installed !\n", tpci200_number,
+ slot_position);
+ goto err_unlock;
+ }
+
+ /*
+ * Give the same IRQ number as the slot number.
+ * The TPCI200 has assigned his own two IRQ by PCI bus driver
+ */
+ dev = ipack_device_register(tpci200->info->ipack_bus,
+ slot_position, slot_position);
+ if (dev == NULL) {
+ pr_info("Slot [%d:%d] Unable to register an ipack device\n",
+ tpci200_number, slot_position);
+ goto err_unlock;
+ }
+
+ tpci200->slots[slot_position].dev = dev;
+ mutex_unlock(&tpci200->mutex);
+ return dev;
+
+err_unlock:
+ mutex_unlock(&tpci200->mutex);
+ return NULL;
+}
+
+static ssize_t tpci200_store_board(struct device *pdev, const char *buf,
+ size_t count, int slot)
+{
+ struct tpci200_board *card = dev_get_drvdata(pdev);
+ struct ipack_device *dev = card->slots[slot].dev;
+
+ if (dev != NULL)
+ return -EBUSY;
+
+ dev = tpci200_slot_register(card->number, slot);
+ if (dev == NULL)
+ return -ENODEV;
+
+ return count;
+}
+
+static ssize_t tpci200_show_board(struct device *pdev, char *buf, int slot)
+{
+ struct tpci200_board *card = dev_get_drvdata(pdev);
+ struct ipack_device *dev = card->slots[slot].dev;
+
+ if (dev != NULL)
+ return snprintf(buf, PAGE_SIZE, "%s\n", dev_name(&dev->dev));
+ else
+ return snprintf(buf, PAGE_SIZE, "none\n");
+}
+
+static ssize_t tpci200_show_description(struct device *pdev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE,
+ "TEWS tpci200 carrier PCI for Industry-pack mezzanines.\n");
+}
+
+static ssize_t tpci200_show_board_slot0(struct device *pdev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return tpci200_show_board(pdev, buf, 0);
+}
+
+static ssize_t tpci200_store_board_slot0(struct device *pdev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return tpci200_store_board(pdev, buf, count, 0);
+}
+
+static ssize_t tpci200_show_board_slot1(struct device *pdev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return tpci200_show_board(pdev, buf, 1);
+}
+
+static ssize_t tpci200_store_board_slot1(struct device *pdev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return tpci200_store_board(pdev, buf, count, 1);
+}
+
+static ssize_t tpci200_show_board_slot2(struct device *pdev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return tpci200_show_board(pdev, buf, 2);
+}
+
+static ssize_t tpci200_store_board_slot2(struct device *pdev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return tpci200_store_board(pdev, buf, count, 2);
+}
+
+
+static ssize_t tpci200_show_board_slot3(struct device *pdev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return tpci200_show_board(pdev, buf, 3);
+}
+
+static ssize_t tpci200_store_board_slot3(struct device *pdev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return tpci200_store_board(pdev, buf, count, 3);
+}
+
+/* Declaration of the device attributes for the TPCI200 */
+static DEVICE_ATTR(description, S_IRUGO,
+ tpci200_show_description, NULL);
+static DEVICE_ATTR(board_slot0, S_IRUGO | S_IWUSR,
+ tpci200_show_board_slot0, tpci200_store_board_slot0);
+static DEVICE_ATTR(board_slot1, S_IRUGO | S_IWUSR,
+ tpci200_show_board_slot1, tpci200_store_board_slot1);
+static DEVICE_ATTR(board_slot2, S_IRUGO | S_IWUSR,
+ tpci200_show_board_slot2, tpci200_store_board_slot2);
+static DEVICE_ATTR(board_slot3, S_IRUGO | S_IWUSR,
+ tpci200_show_board_slot3, tpci200_store_board_slot3);
+
+static struct attribute *tpci200_attrs[] = {
+ &dev_attr_description.attr,
+ &dev_attr_board_slot0.attr,
+ &dev_attr_board_slot1.attr,
+ &dev_attr_board_slot2.attr,
+ &dev_attr_board_slot3.attr,
+ NULL,
+};
+
+static struct attribute_group tpci200_attr_group = {
+ .attrs = tpci200_attrs,
+};
+
+static int tpci200_create_sysfs_files(struct tpci200_board *card)
+{
+ return sysfs_create_group(&card->info->pdev->dev.kobj,
+ &tpci200_attr_group);
+}
+
+static void tpci200_remove_sysfs_files(struct tpci200_board *card)
+{
+ sysfs_remove_group(&card->info->pdev->dev.kobj, &tpci200_attr_group);
+}
+
+#else
+
+static int tpci200_create_sysfs_files(struct tpci200_board *card)
+{
+ return 0;
+}
+
+static void tpci200_remove_sysfs_files(struct tpci200_board *card)
+{
+}
+
+#endif /* CONFIG_SYSFS */
+
+static int tpci200_register(struct tpci200_board *tpci200)
+{
+ int i;
+ int res;
+ unsigned long ioidint_base;
+ unsigned long mem_base;
+ unsigned short slot_ctrl;
+
+ if (pci_enable_device(tpci200->info->pdev) < 0)
+ return -ENODEV;
+
+ if (tpci200_create_sysfs_files(tpci200) < 0) {
+ pr_err("failed creating sysfs files\n");
+ res = -EFAULT;
+ goto out_disable_pci;
+ }
+
+ /* Request IP interface register (Bar 2) */
+ res = pci_request_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR,
+ "Carrier IP interface registers");
+ if (res) {
+ pr_err("(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !",
+ tpci200->info->pdev->bus->number,
+ tpci200->info->pdev->devfn);
+ goto out_remove_sysfs;
+ }
+
+ /* Request IO ID INT space (Bar 3) */
+ res = pci_request_region(tpci200->info->pdev,
+ TPCI200_IO_ID_INT_SPACES_BAR,
+ "Carrier IO ID INT space");
+ if (res) {
+ pr_err("(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !",
+ tpci200->info->pdev->bus->number,
+ tpci200->info->pdev->devfn);
+ goto out_release_ip_space;
+ }
+
+ /* Request MEM space (Bar 4) */
+ res = pci_request_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR,
+ "Carrier MEM space");
+ if (res) {
+ pr_err("(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!",
+ tpci200->info->pdev->bus->number,
+ tpci200->info->pdev->devfn);
+ goto out_release_ioid_int_space;
+ }
+
+ /* Map internal tpci200 driver user space */
+ tpci200->info->interface_regs =
+ ioremap(pci_resource_start(tpci200->info->pdev,
+ TPCI200_IP_INTERFACE_BAR),
+ TPCI200_IFACE_SIZE);
+ tpci200->info->ioidint_space =
+ ioremap(pci_resource_start(tpci200->info->pdev,
+ TPCI200_IO_ID_INT_SPACES_BAR),
+ TPCI200_IOIDINT_SIZE);
+ tpci200->info->mem8_space =
+ ioremap(pci_resource_start(tpci200->info->pdev,
+ TPCI200_MEM8_SPACE_BAR),
+ TPCI200_MEM8_SIZE);
+
+ spin_lock_init(&tpci200->info->access_lock);
+ ioidint_base = pci_resource_start(tpci200->info->pdev,
+ TPCI200_IO_ID_INT_SPACES_BAR);
+ mem_base = pci_resource_start(tpci200->info->pdev,
+ TPCI200_MEM8_SPACE_BAR);
+
+ /* Set the default parameters of the slot
+ * INT0 disabled, level sensitive
+ * INT1 disabled, level sensitive
+ * error interrupt disabled
+ * timeout interrupt disabled
+ * recover time disabled
+ * clock rate 8 MHz
+ */
+ slot_ctrl = 0;
+
+ /* Set all slot physical address space */
+ for (i = 0; i < TPCI200_NB_SLOT; i++) {
+ tpci200->slots[i].io_phys.address =
+ (void __iomem *)ioidint_base +
+ TPCI200_IO_SPACE_OFF + TPCI200_IO_SPACE_GAP*i;
+ tpci200->slots[i].io_phys.size = TPCI200_IO_SPACE_SIZE;
+
+ tpci200->slots[i].id_phys.address =
+ (void __iomem *)ioidint_base +
+ TPCI200_ID_SPACE_OFF + TPCI200_ID_SPACE_GAP*i;
+ tpci200->slots[i].id_phys.size = TPCI200_ID_SPACE_SIZE;
+
+ tpci200->slots[i].mem_phys.address =
+ (void __iomem *)mem_base + TPCI200_MEM8_GAP*i;
+ tpci200->slots[i].mem_phys.size = TPCI200_MEM8_SIZE;
+
+ writew(slot_ctrl, (tpci200->info->interface_regs +
+ control_reg[i]));
+ }
+
+ res = request_irq(tpci200->info->pdev->irq,
+ tpci200_interrupt, IRQF_SHARED,
+ KBUILD_MODNAME, (void *) tpci200);
+ if (res) {
+ pr_err("(bn 0x%X, sn 0x%X) unable to register IRQ !",
+ tpci200->info->pdev->bus->number,
+ tpci200->info->pdev->devfn);
+ tpci200_unregister(tpci200);
+ goto out_err;
+ }
+
+ return 0;
+
+out_release_ioid_int_space:
+ pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
+out_release_ip_space:
+ pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
+out_remove_sysfs:
+ tpci200_remove_sysfs_files(tpci200);
+out_disable_pci:
+ pci_disable_device(tpci200->info->pdev);
+out_err:
+ return res;
+}
+
+static int __tpci200_request_irq(struct tpci200_board *tpci200,
+ struct ipack_device *dev)
+{
+ unsigned short slot_ctrl;
+
+ /* Set the default parameters of the slot
+ * INT0 enabled, level sensitive
+ * INT1 enabled, level sensitive
+ * error interrupt disabled
+ * timeout interrupt disabled
+ * recover time disabled
+ * clock rate 8 MHz
+ */
+ slot_ctrl = TPCI200_INT0_EN | TPCI200_INT1_EN;
+ writew(slot_ctrl, (tpci200->info->interface_regs +
+ control_reg[dev->slot]));
+
+ return 0;
+}
+
+static void __tpci200_free_irq(struct tpci200_board *tpci200,
+ struct ipack_device *dev)
+{
+ unsigned short slot_ctrl;
+
+ /* Set the default parameters of the slot
+ * INT0 disabled, level sensitive
+ * INT1 disabled, level sensitive
+ * error interrupt disabled
+ * timeout interrupt disabled
+ * recover time disabled
+ * clock rate 8 MHz
+ */
+ slot_ctrl = 0;
+ writew(slot_ctrl, (tpci200->info->interface_regs +
+ control_reg[dev->slot]));
+}
+
+static int tpci200_free_irq(struct ipack_device *dev)
+{
+ int res;
+ struct slot_irq *slot_irq;
+ struct tpci200_board *tpci200;
+
+ tpci200 = check_slot(dev);
+ if (tpci200 == NULL) {
+ res = -EINVAL;
+ goto out;
+ }
+
+ if (mutex_lock_interruptible(&tpci200->mutex)) {
+ res = -ERESTARTSYS;
+ goto out;
+ }
+
+ if (tpci200->slots[dev->slot].irq == NULL) {
+ res = -EINVAL;
+ goto out_unlock;
+ }
+
+ __tpci200_free_irq(tpci200, dev);
+ slot_irq = tpci200->slots[dev->slot].irq;
+ tpci200->slots[dev->slot].irq = NULL;
+ kfree(slot_irq);
+
+out_unlock:
+ mutex_unlock(&tpci200->mutex);
+out:
+ return res;
+}
+
+static int tpci200_slot_unmap_space(struct ipack_device *dev, int space)
+{
+ int res;
+ struct ipack_addr_space *virt_addr_space;
+ struct tpci200_board *tpci200;
+
+ tpci200 = check_slot(dev);
+ if (tpci200 == NULL) {
+ res = -EINVAL;
+ goto out;
+ }
+
+ if (mutex_lock_interruptible(&tpci200->mutex)) {
+ res = -ERESTARTSYS;
+ goto out;
+ }
+
+ switch (space) {
+ case IPACK_IO_SPACE:
+ if (dev->io_space.address == NULL) {
+ pr_info("Slot [%d:%d] IO space not mapped !\n",
+ dev->bus_nr, dev->slot);
+ goto out_unlock;
+ }
+ virt_addr_space = &dev->io_space;
+ break;
+ case IPACK_ID_SPACE:
+ if (dev->id_space.address == NULL) {
+ pr_info("Slot [%d:%d] ID space not mapped !\n",
+ dev->bus_nr, dev->slot);
+ goto out_unlock;
+ }
+ virt_addr_space = &dev->id_space;
+ break;
+ case IPACK_MEM_SPACE:
+ if (dev->mem_space.address == NULL) {
+ pr_info("Slot [%d:%d] MEM space not mapped !\n",
+ dev->bus_nr, dev->slot);
+ goto out_unlock;
+ }
+ virt_addr_space = &dev->mem_space;
+ break;
+ default:
+ pr_err("Slot [%d:%d] space number %d doesn't exist !\n",
+ dev->bus_nr, dev->slot, space);
+ res = -EINVAL;
+ goto out_unlock;
+ break;
+ }
+
+ iounmap(virt_addr_space->address);
+
+ virt_addr_space->address = NULL;
+ virt_addr_space->size = 0;
+out_unlock:
+ mutex_unlock(&tpci200->mutex);
+out:
+ return res;
+}
+
+static int tpci200_slot_unregister(struct ipack_device *dev)
+{
+ struct tpci200_board *tpci200;
+
+ if (dev == NULL)
+ return -ENODEV;
+
+ tpci200 = check_slot(dev);
+ if (tpci200 == NULL)
+ return -EINVAL;
+
+ tpci200_free_irq(dev);
+
+ if (mutex_lock_interruptible(&tpci200->mutex))
+ return -ERESTARTSYS;
+
+ ipack_device_unregister(dev);
+ tpci200->slots[dev->slot].dev = NULL;
+ mutex_unlock(&tpci200->mutex);
+
+ return 0;
+}
+
+static int tpci200_slot_map_space(struct ipack_device *dev,
+ unsigned int memory_size, int space)
+{
+ int res;
+ unsigned int size_to_map;
+ void __iomem *phys_address;
+ struct ipack_addr_space *virt_addr_space;
+ struct tpci200_board *tpci200;
+
+ tpci200 = check_slot(dev);
+ if (tpci200 == NULL) {
+ res = -EINVAL;
+ goto out;
+ }
+
+ if (mutex_lock_interruptible(&tpci200->mutex)) {
+ res = -ERESTARTSYS;
+ goto out;
+ }
+
+ switch (space) {
+ case IPACK_IO_SPACE:
+ if (dev->io_space.address != NULL) {
+ pr_err("Slot [%d:%d] IO space already mapped !\n",
+ tpci200->number, dev->slot);
+ res = -EINVAL;
+ goto out_unlock;
+ }
+ virt_addr_space = &dev->io_space;
+
+ phys_address = tpci200->slots[dev->slot].io_phys.address;
+ size_to_map = tpci200->slots[dev->slot].io_phys.size;
+ break;
+ case IPACK_ID_SPACE:
+ if (dev->id_space.address != NULL) {
+ pr_err("Slot [%d:%d] ID space already mapped !\n",
+ tpci200->number, dev->slot);
+ res = -EINVAL;
+ goto out_unlock;
+ }
+ virt_addr_space = &dev->id_space;
+
+ phys_address = tpci200->slots[dev->slot].id_phys.address;
+ size_to_map = tpci200->slots[dev->slot].id_phys.size;
+ break;
+ case IPACK_MEM_SPACE:
+ if (dev->mem_space.address != NULL) {
+ pr_err("Slot [%d:%d] MEM space already mapped !\n",
+ tpci200->number, dev->slot);
+ res = -EINVAL;
+ goto out_unlock;
+ }
+ virt_addr_space = &dev->mem_space;
+
+ if (memory_size > tpci200->slots[dev->slot].mem_phys.size) {
+ pr_err("Slot [%d:%d] request is 0x%X memory, only 0x%X available !\n",
+ dev->bus_nr, dev->slot, memory_size,
+ tpci200->slots[dev->slot].mem_phys.size);
+ res = -EINVAL;
+ goto out_unlock;
+ }
+
+ phys_address = tpci200->slots[dev->slot].mem_phys.address;
+ size_to_map = memory_size;
+ break;
+ default:
+ pr_err("Slot [%d:%d] space %d doesn't exist !\n",
+ tpci200->number, dev->slot, space);
+ res = -EINVAL;
+ goto out_unlock;
+ break;
+ }
+
+ virt_addr_space->size = size_to_map;
+ virt_addr_space->address =
+ ioremap((unsigned long)phys_address, size_to_map);
+
+out_unlock:
+ mutex_unlock(&tpci200->mutex);
+out:
+ return res;
+}
+
+static int tpci200_request_irq(struct ipack_device *dev, int vector,
+ int (*handler)(void *), void *arg)
+{
+ int res;
+ struct slot_irq *slot_irq;
+ struct tpci200_board *tpci200;
+
+ tpci200 = check_slot(dev);
+ if (tpci200 == NULL) {
+ res = -EINVAL;
+ goto out;
+ }
+
+ if (mutex_lock_interruptible(&tpci200->mutex)) {
+ res = -ERESTARTSYS;
+ goto out;
+ }
+
+ if (tpci200->slots[dev->slot].irq != NULL) {
+ pr_err("Slot [%d:%d] IRQ already registered !\n", dev->bus_nr,
+ dev->slot);
+ res = -EINVAL;
+ goto out_unlock;
+ }
+
+ slot_irq = kzalloc(sizeof(struct slot_irq), GFP_KERNEL);
+ if (slot_irq == NULL) {
+ pr_err("Slot [%d:%d] unable to allocate memory for IRQ !\n",
+ dev->bus_nr, dev->slot);
+ res = -ENOMEM;
+ goto out_unlock;
+ }
+
+ /*
+ * WARNING: Setup Interrupt Vector in the IndustryPack device
+ * before an IRQ request.
+ * Read the User Manual of your IndustryPack device to know
+ * where to write the vector in memory.
+ */
+ slot_irq->vector = vector;
+ slot_irq->handler = handler;
+ slot_irq->arg = arg;
+ slot_irq->name = dev_name(&dev->dev);
+
+ tpci200->slots[dev->slot].irq = slot_irq;
+ res = __tpci200_request_irq(tpci200, dev);
+
+out_unlock:
+ mutex_unlock(&tpci200->mutex);
+out:
+ return res;
+}
+
+static void tpci200_slot_remove(struct tpci200_slot *slot)
+{
+ if ((slot->dev == NULL) ||
+ (slot->dev->driver->ops->remove == NULL))
+ return;
+
+ slot->dev->driver->ops->remove(slot->dev);
+}
+
+static void tpci200_uninstall(struct tpci200_board *tpci200)
+{
+ int i;
+
+ for (i = 0; i < TPCI200_NB_SLOT; i++)
+ tpci200_slot_remove(&tpci200->slots[i]);
+
+ tpci200_unregister(tpci200);
+ kfree(tpci200->slots);
+}
+
+static struct ipack_bus_ops tpci200_bus_ops = {
+ .map_space = tpci200_slot_map_space,
+ .unmap_space = tpci200_slot_unmap_space,
+ .request_irq = tpci200_request_irq,
+ .free_irq = tpci200_free_irq,
+ .read8 = tpci200_read8,
+ .read16 = tpci200_read16,
+ .read32 = tpci200_read32,
+ .write8 = tpci200_write8,
+ .write16 = tpci200_write16,
+ .write32 = tpci200_write32,
+ .remove_device = tpci200_slot_unregister,
+};
+
+static int tpci200_install(struct tpci200_board *tpci200)
+{
+ int res;
+
+ tpci200->slots = kzalloc(
+ TPCI200_NB_SLOT * sizeof(struct tpci200_slot), GFP_KERNEL);
+ if (tpci200->slots == NULL) {
+ res = -ENOMEM;
+ goto out_err;
+ }
+
+ res = tpci200_register(tpci200);
+ if (res)
+ goto out_free;
+
+ mutex_init(&tpci200->mutex);
+ return 0;
+
+out_free:
+ kfree(tpci200->slots);
+ tpci200->slots = NULL;
+out_err:
+ return res;
+}
+
+static int tpci200_pciprobe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int ret;
+ struct tpci200_board *tpci200;
+
+ tpci200 = kzalloc(sizeof(struct tpci200_board), GFP_KERNEL);
+ if (!tpci200)
+ return -ENOMEM;
+
+ tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL);
+ if (!tpci200->info) {
+ kfree(tpci200);
+ return -ENOMEM;
+ }
+
+ /* Save struct pci_dev pointer */
+ tpci200->info->pdev = pdev;
+ tpci200->info->id_table = (struct pci_device_id *)id;
+
+ /* register the device and initialize it */
+ ret = tpci200_install(tpci200);
+ if (ret) {
+ pr_err("Error during tpci200 install !\n");
+ kfree(tpci200->info);
+ kfree(tpci200);
+ return -ENODEV;
+ }
+
+ /* Register the carrier in the industry pack bus driver */
+ tpci200->info->ipack_bus = ipack_bus_register(&pdev->dev,
+ TPCI200_NB_SLOT,
+ &tpci200_bus_ops);
+ if (!tpci200->info->ipack_bus) {
+ pr_err("error registering the carrier on ipack driver\n");
+ tpci200_uninstall(tpci200);
+ kfree(tpci200->info);
+ kfree(tpci200);
+ return -EFAULT;
+ }
+
+ /* save the bus number given by ipack to logging purpose */
+ tpci200->number = tpci200->info->ipack_bus->bus_nr;
+ dev_set_drvdata(&pdev->dev, tpci200);
+ /* add the registered device in an internal linked list */
+ list_add_tail(&tpci200->list, &tpci200_list);
+ return ret;
+}
+
+static void __tpci200_pci_remove(struct tpci200_board *tpci200)
+{
+ tpci200_uninstall(tpci200);
+ tpci200_remove_sysfs_files(tpci200);
+ list_del(&tpci200->list);
+ ipack_bus_unregister(tpci200->info->ipack_bus);
+ kfree(tpci200->info);
+ kfree(tpci200);
+}
+
+static void __devexit tpci200_pci_remove(struct pci_dev *dev)
+{
+ struct tpci200_board *tpci200, *next;
+
+ /* Search the registered device to uninstall it */
+ list_for_each_entry_safe(tpci200, next, &tpci200_list, list) {
+ if (tpci200->info->pdev == dev) {
+ __tpci200_pci_remove(tpci200);
+ break;
+ }
+ }
+}
+
+static struct pci_device_id tpci200_idtable[2] = {
+ { TPCI200_VENDOR_ID, TPCI200_DEVICE_ID, TPCI200_SUBVENDOR_ID,
+ TPCI200_SUBDEVICE_ID },
+ { 0, },
+};
+
+static struct pci_driver tpci200_pci_drv = {
+ .name = "tpci200",
+ .id_table = tpci200_idtable,
+ .probe = tpci200_pciprobe,
+ .remove = __devexit_p(tpci200_pci_remove),
+};
+
+static int __init tpci200_drvr_init_module(void)
+{
+ return pci_register_driver(&tpci200_pci_drv);
+}
+
+static void __exit tpci200_drvr_exit_module(void)
+{
+ struct tpci200_board *tpci200, *next;
+
+ list_for_each_entry_safe(tpci200, next, &tpci200_list, list)
+ __tpci200_pci_remove(tpci200);
+
+ pci_unregister_driver(&tpci200_pci_drv);
+}
+
+MODULE_DESCRIPTION("TEWS TPCI-200 device driver");
+MODULE_LICENSE("GPL");
+module_init(tpci200_drvr_init_module);
+module_exit(tpci200_drvr_exit_module);
diff --git a/drivers/staging/ipack/bridges/tpci200.h b/drivers/staging/ipack/bridges/tpci200.h
new file mode 100644
index 000000000000..0b547eedddc2
--- /dev/null
+++ b/drivers/staging/ipack/bridges/tpci200.h
@@ -0,0 +1,162 @@
+/**
+ * tpci200.h
+ *
+ * driver for the carrier TEWS TPCI-200
+ * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
+ * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
+ * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ */
+
+#ifndef _TPCI200_H_
+#define _TPCI200_H_
+
+#include <linux/version.h>
+#include <linux/limits.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/swab.h>
+#include <linux/io.h>
+
+#include "../ipack.h"
+
+#define TPCI200_NB_SLOT 0x4
+#define TPCI200_NB_BAR 0x6
+
+#define TPCI200_VENDOR_ID 0x1498
+#define TPCI200_DEVICE_ID 0x30C8
+#define TPCI200_SUBVENDOR_ID 0x1498
+#define TPCI200_SUBDEVICE_ID 0x300A
+
+#define TPCI200_IP_INTERFACE_BAR 2
+#define TPCI200_IO_ID_INT_SPACES_BAR 3
+#define TPCI200_MEM16_SPACE_BAR 4
+#define TPCI200_MEM8_SPACE_BAR 5
+
+#define TPCI200_REVISION_REG 0x00
+#define TPCI200_CONTROL_A_REG 0x02
+#define TPCI200_CONTROL_B_REG 0x04
+#define TPCI200_CONTROL_C_REG 0x06
+#define TPCI200_CONTROL_D_REG 0x08
+#define TPCI200_RESET_REG 0x0A
+#define TPCI200_STATUS_REG 0x0C
+
+#define TPCI200_IFACE_SIZE 0x100
+
+#define TPCI200_IO_SPACE_OFF 0x0000
+#define TPCI200_IO_SPACE_GAP 0x0100
+#define TPCI200_IO_SPACE_SIZE 0x0080
+#define TPCI200_ID_SPACE_OFF 0x0080
+#define TPCI200_ID_SPACE_GAP 0x0100
+#define TPCI200_ID_SPACE_SIZE 0x0040
+#define TPCI200_INT_SPACE_OFF 0x00C0
+#define TPCI200_INT_SPACE_GAP 0x0100
+#define TPCI200_INT_SPACE_SIZE 0x0040
+#define TPCI200_IOIDINT_SIZE 0x0400
+
+#define TPCI200_MEM8_GAP 0x00400000
+#define TPCI200_MEM8_SIZE 0x00400000
+#define TPCI200_MEM16_GAP 0x00800000
+#define TPCI200_MEM16_SIZE 0x00800000
+
+#define TPCI200_INT0_EN 0x0040
+#define TPCI200_INT1_EN 0x0080
+#define TPCI200_INT0_EDGE 0x0010
+#define TPCI200_INT1_EDGE 0x0020
+#define TPCI200_ERR_INT_EN 0x0008
+#define TPCI200_TIME_INT_EN 0x0004
+#define TPCI200_RECOVER_EN 0x0002
+#define TPCI200_CLK32 0x0001
+
+#define TPCI200_A_RESET 0x0001
+#define TPCI200_B_RESET 0x0002
+#define TPCI200_C_RESET 0x0004
+#define TPCI200_D_RESET 0x0008
+
+#define TPCI200_A_TIMEOUT 0x1000
+#define TPCI200_B_TIMEOUT 0x2000
+#define TPCI200_C_TIMEOUT 0x4000
+#define TPCI200_D_TIMEOUT 0x8000
+
+#define TPCI200_A_ERROR 0x0100
+#define TPCI200_B_ERROR 0x0200
+#define TPCI200_C_ERROR 0x0400
+#define TPCI200_D_ERROR 0x0800
+
+#define TPCI200_A_INT0 0x0001
+#define TPCI200_A_INT1 0x0002
+#define TPCI200_B_INT0 0x0004
+#define TPCI200_B_INT1 0x0008
+#define TPCI200_C_INT0 0x0010
+#define TPCI200_C_INT1 0x0020
+#define TPCI200_D_INT0 0x0040
+#define TPCI200_D_INT1 0x0080
+
+#define TPCI200_SLOT_INT_MASK 0x00FF
+
+#define VME_IOID_SPACE "IOID"
+#define VME_MEM_SPACE "MEM"
+
+/**
+ * struct slot_irq - slot IRQ definition.
+ * @vector Vector number
+ * @handler Handler called when IRQ arrives
+ * @arg Handler argument
+ * @name IRQ name
+ *
+ */
+struct slot_irq {
+ int vector;
+ int (*handler)(void *);
+ void *arg;
+ const char *name;
+};
+
+/**
+ * struct tpci200_slot - data specific to the tpci200 slot.
+ * @slot_id Slot identification gived to external interface
+ * @irq Slot IRQ infos
+ * @io_phys IO physical base address register of the slot
+ * @id_phys ID physical base address register of the slot
+ * @mem_phys MEM physical base address register of the slot
+ *
+ */
+struct tpci200_slot {
+ struct ipack_device *dev;
+ struct slot_irq *irq;
+ struct ipack_addr_space io_phys;
+ struct ipack_addr_space id_phys;
+ struct ipack_addr_space mem_phys;
+};
+
+/**
+ * struct tpci200_infos - informations specific of the TPCI200 tpci200.
+ * @pci_dev PCI device
+ * @interface_regs Pointer to IP interface space (Bar 2)
+ * @ioidint_space Pointer to IP ID, IO and INT space (Bar 3)
+ * @mem8_space Pointer to MEM space (Bar 4)
+ * @access_lock Mutex lock for simultaneous access
+ *
+ */
+struct tpci200_infos {
+ struct pci_dev *pdev;
+ struct pci_device_id *id_table;
+ void __iomem *interface_regs;
+ void __iomem *ioidint_space;
+ void __iomem *mem8_space;
+ spinlock_t access_lock;
+ struct ipack_bus_device *ipack_bus;
+};
+struct tpci200_board {
+ struct list_head list;
+ unsigned int number;
+ struct mutex mutex;
+ struct tpci200_slot *slots;
+ struct tpci200_infos *info;
+};
+
+#endif /* _TPCI200_H_ */
diff --git a/drivers/staging/ipack/devices/Kconfig b/drivers/staging/ipack/devices/Kconfig
new file mode 100644
index 000000000000..39f71888a584
--- /dev/null
+++ b/drivers/staging/ipack/devices/Kconfig
@@ -0,0 +1,7 @@
+config SERIAL_IPOCTAL
+ tristate "IndustryPack IP-OCTAL uart support"
+ depends on IPACK_BUS
+ help
+ This driver supports the IPOCTAL serial port device for the IndustryPack bus.
+ default n
+
diff --git a/drivers/staging/ipack/devices/Makefile b/drivers/staging/ipack/devices/Makefile
new file mode 100644
index 000000000000..6de18bda4a9a
--- /dev/null
+++ b/drivers/staging/ipack/devices/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SERIAL_IPOCTAL) += ipoctal.o
diff --git a/drivers/staging/ipack/devices/ipoctal.c b/drivers/staging/ipack/devices/ipoctal.c
new file mode 100644
index 000000000000..29f6fa841d23
--- /dev/null
+++ b/drivers/staging/ipack/devices/ipoctal.c
@@ -0,0 +1,901 @@
+/**
+ * ipoctal.c
+ *
+ * driver for the GE IP-OCTAL boards
+ * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
+ * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
+ * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/tty_flip.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
+#include "../ipack.h"
+#include "ipoctal.h"
+#include "scc2698.h"
+
+#define IP_OCTAL_MANUFACTURER_ID 0xF0
+#define IP_OCTAL_232_ID 0x22
+#define IP_OCTAL_422_ID 0x2A
+#define IP_OCTAL_485_ID 0x48
+
+#define IP_OCTAL_ID_SPACE_VECTOR 0x41
+#define IP_OCTAL_NB_BLOCKS 4
+
+static struct ipack_driver driver;
+static const struct tty_operations ipoctal_fops;
+
+struct ipoctal {
+ struct list_head list;
+ struct ipack_device *dev;
+ unsigned int board_id;
+ struct scc2698_channel *chan_regs;
+ struct scc2698_block *block_regs;
+ struct ipoctal_stats chan_stats[NR_CHANNELS];
+ char *buffer[NR_CHANNELS];
+ unsigned int nb_bytes[NR_CHANNELS];
+ unsigned int count_wr[NR_CHANNELS];
+ struct ipoctal_config chan_config[NR_CHANNELS];
+ wait_queue_head_t queue[NR_CHANNELS];
+ unsigned short error_flag[NR_CHANNELS];
+ spinlock_t lock[NR_CHANNELS];
+ unsigned int pointer_read[NR_CHANNELS];
+ unsigned int pointer_write[NR_CHANNELS];
+ atomic_t open[NR_CHANNELS];
+ unsigned char write;
+ struct tty_port tty_port[NR_CHANNELS];
+ struct tty_driver *tty_drv;
+};
+
+/* Linked list to save the registered devices */
+static LIST_HEAD(ipoctal_list);
+
+static inline void ipoctal_write_io_reg(struct ipoctal *ipoctal,
+ unsigned char *dest,
+ unsigned char value)
+{
+ unsigned long offset;
+
+ offset = ((void __iomem *) dest) - ipoctal->dev->io_space.address;
+ ipoctal->dev->bus->ops->write8(ipoctal->dev, IPACK_IO_SPACE, offset,
+ value);
+}
+
+static inline void ipoctal_write_cr_cmd(struct ipoctal *ipoctal,
+ unsigned char *dest,
+ unsigned char value)
+{
+ ipoctal_write_io_reg(ipoctal, dest, value);
+}
+
+static inline unsigned char ipoctal_read_io_reg(struct ipoctal *ipoctal,
+ unsigned char *src)
+{
+ unsigned long offset;
+ unsigned char value;
+
+ offset = ((void __iomem *) src) - ipoctal->dev->io_space.address;
+ ipoctal->dev->bus->ops->read8(ipoctal->dev, IPACK_IO_SPACE, offset,
+ &value);
+ return value;
+}
+
+static struct ipoctal *ipoctal_find_board(struct tty_struct *tty)
+{
+ struct ipoctal *p;
+
+ list_for_each_entry(p, &ipoctal_list, list) {
+ if (tty->driver->major == p->tty_drv->major)
+ return p;
+ }
+
+ return NULL;
+}
+
+static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty)
+{
+ struct ipoctal *ipoctal;
+ int channel = tty->index;
+
+ ipoctal = ipoctal_find_board(tty);
+
+ if (ipoctal == NULL) {
+ pr_err("Device not found. Major %d\n", tty->driver->major);
+ return -ENODEV;
+ }
+
+ ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
+ CR_ENABLE_RX);
+ tty->driver_data = ipoctal;
+
+ return 0;
+}
+
+static int ipoctal_open(struct tty_struct *tty, struct file *file)
+{
+ int channel = tty->index;
+ int res;
+ struct ipoctal *ipoctal;
+
+ ipoctal = ipoctal_find_board(tty);
+
+ if (ipoctal == NULL) {
+ pr_err("Device not found. Major %d\n", tty->driver->major);
+ return -ENODEV;
+ }
+
+ if (atomic_read(&ipoctal->open[channel]))
+ return -EBUSY;
+
+ res = tty_port_open(&ipoctal->tty_port[channel], tty, file);
+ if (res)
+ return res;
+
+ atomic_inc(&ipoctal->open[channel]);
+ return 0;
+}
+
+static void ipoctal_reset_stats(struct ipoctal_stats *stats)
+{
+ stats->tx = 0;
+ stats->rx = 0;
+ stats->rcv_break = 0;
+ stats->framing_err = 0;
+ stats->overrun_err = 0;
+ stats->parity_err = 0;
+}
+
+static void ipoctal_free_channel(struct tty_struct *tty)
+{
+ int channel = tty->index;
+ struct ipoctal *ipoctal = tty->driver_data;
+
+ if (ipoctal == NULL)
+ return;
+
+ ipoctal_reset_stats(&ipoctal->chan_stats[channel]);
+ ipoctal->pointer_read[channel] = 0;
+ ipoctal->pointer_write[channel] = 0;
+ ipoctal->nb_bytes[channel] = 0;
+}
+
+static void ipoctal_close(struct tty_struct *tty, struct file *filp)
+{
+ int channel = tty->index;
+ struct ipoctal *ipoctal = tty->driver_data;
+
+ tty_port_close(&ipoctal->tty_port[channel], tty, filp);
+
+ if (atomic_dec_and_test(&ipoctal->open[channel]))
+ ipoctal_free_channel(tty);
+}
+
+static int ipoctal_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+{
+ struct ipoctal *ipoctal = tty->driver_data;
+ int channel = tty->index;
+
+ icount->cts = 0;
+ icount->dsr = 0;
+ icount->rng = 0;
+ icount->dcd = 0;
+ icount->rx = ipoctal->chan_stats[channel].rx;
+ icount->tx = ipoctal->chan_stats[channel].tx;
+ icount->frame = ipoctal->chan_stats[channel].framing_err;
+ icount->parity = ipoctal->chan_stats[channel].parity_err;
+ icount->brk = ipoctal->chan_stats[channel].rcv_break;
+ return 0;
+}
+
+static int ipoctal_irq_handler(void *arg)
+{
+ unsigned int channel;
+ unsigned int block;
+ unsigned char isr;
+ unsigned char sr;
+ unsigned char isr_tx_rdy, isr_rx_rdy;
+ unsigned char value;
+ unsigned char flag;
+ struct tty_struct *tty;
+ struct ipoctal *ipoctal = (struct ipoctal *) arg;
+
+ /* Check all channels */
+ for (channel = 0; channel < NR_CHANNELS; channel++) {
+ /* If there is no client, skip the check */
+ if (!atomic_read(&ipoctal->open[channel]))
+ continue;
+
+ tty = tty_port_tty_get(&ipoctal->tty_port[channel]);
+ if (!tty)
+ continue;
+
+ /*
+ * The HW is organized in pair of channels.
+ * See which register we need to read from
+ */
+ block = channel / 2;
+ isr = ipoctal_read_io_reg(ipoctal,
+ &ipoctal->block_regs[block].u.r.isr);
+ sr = ipoctal_read_io_reg(ipoctal,
+ &ipoctal->chan_regs[channel].u.r.sr);
+
+ if ((channel % 2) == 1) {
+ isr_tx_rdy = isr & ISR_TxRDY_B;
+ isr_rx_rdy = isr & ISR_RxRDY_FFULL_B;
+ } else {
+ isr_tx_rdy = isr & ISR_TxRDY_A;
+ isr_rx_rdy = isr & ISR_RxRDY_FFULL_A;
+ }
+
+ /* In case of RS-485, change from TX to RX when finishing TX.
+ * Half-duplex.
+ */
+ if ((ipoctal->board_id == IP_OCTAL_485_ID) &&
+ (sr & SR_TX_EMPTY) &&
+ (ipoctal->nb_bytes[channel] == 0)) {
+ ipoctal_write_io_reg(ipoctal,
+ &ipoctal->chan_regs[channel].u.w.cr,
+ CR_DISABLE_TX);
+ ipoctal_write_cr_cmd(ipoctal,
+ &ipoctal->chan_regs[channel].u.w.cr,
+ CR_CMD_NEGATE_RTSN);
+ ipoctal_write_io_reg(ipoctal,
+ &ipoctal->chan_regs[channel].u.w.cr,
+ CR_ENABLE_RX);
+ ipoctal->write = 1;
+ wake_up_interruptible(&ipoctal->queue[channel]);
+ }
+
+ /* RX data */
+ if (isr_rx_rdy && (sr & SR_RX_READY)) {
+ value = ipoctal_read_io_reg(ipoctal,
+ &ipoctal->chan_regs[channel].u.r.rhr);
+ flag = TTY_NORMAL;
+
+ /* Error: count statistics */
+ if (sr & SR_ERROR) {
+ ipoctal_write_cr_cmd(ipoctal,
+ &ipoctal->chan_regs[channel].u.w.cr,
+ CR_CMD_RESET_ERR_STATUS);
+
+ if (sr & SR_OVERRUN_ERROR) {
+ ipoctal->error_flag[channel] |= UART_OVERRUN;
+ ipoctal->chan_stats[channel].overrun_err++;
+ /* Overrun doesn't affect the current character*/
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ }
+ if (sr & SR_PARITY_ERROR) {
+ ipoctal->error_flag[channel] |= UART_PARITY;
+ ipoctal->chan_stats[channel].parity_err++;
+ flag = TTY_PARITY;
+ }
+ if (sr & SR_FRAMING_ERROR) {
+ ipoctal->error_flag[channel] |= UART_FRAMING;
+ ipoctal->chan_stats[channel].framing_err++;
+ flag = TTY_FRAME;
+ }
+ if (sr & SR_RECEIVED_BREAK) {
+ ipoctal->error_flag[channel] |= UART_BREAK;
+ ipoctal->chan_stats[channel].rcv_break++;
+ flag = TTY_BREAK;
+ }
+ }
+
+ tty_insert_flip_char(tty, value, flag);
+ }
+
+ /* TX of each character */
+ if (isr_tx_rdy && (sr & SR_TX_READY)) {
+ unsigned int *pointer_write =
+ &ipoctal->pointer_write[channel];
+
+ if (ipoctal->nb_bytes[channel] <= 0) {
+ ipoctal->nb_bytes[channel] = 0;
+ continue;
+ }
+ spin_lock(&ipoctal->lock[channel]);
+ value = ipoctal->buffer[channel][*pointer_write];
+ ipoctal_write_io_reg(ipoctal,
+ &ipoctal->chan_regs[channel].u.w.thr,
+ value);
+ ipoctal->chan_stats[channel].tx++;
+ ipoctal->count_wr[channel]++;
+ (*pointer_write)++;
+ *pointer_write = *pointer_write % PAGE_SIZE;
+ ipoctal->nb_bytes[channel]--;
+ spin_unlock(&ipoctal->lock[channel]);
+
+ if ((ipoctal->nb_bytes[channel] == 0) &&
+ (waitqueue_active(&ipoctal->queue[channel]))) {
+
+ if (ipoctal->board_id != IP_OCTAL_485_ID) {
+ ipoctal->write = 1;
+ wake_up_interruptible(&ipoctal->queue[channel]);
+ }
+ }
+ }
+
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+ }
+ return IRQ_HANDLED;
+}
+
+static int ipoctal_check_model(struct ipack_device *dev, unsigned char *id)
+{
+ unsigned char manufacturerID;
+ unsigned char board_id;
+
+ dev->bus->ops->read8(dev, IPACK_ID_SPACE,
+ IPACK_IDPROM_OFFSET_MANUFACTURER_ID, &manufacturerID);
+ if (manufacturerID != IP_OCTAL_MANUFACTURER_ID)
+ return -ENODEV;
+
+ dev->bus->ops->read8(dev, IPACK_ID_SPACE,
+ IPACK_IDPROM_OFFSET_MODEL, (unsigned char *)&board_id);
+
+ switch (board_id) {
+ case IP_OCTAL_232_ID:
+ case IP_OCTAL_422_ID:
+ case IP_OCTAL_485_ID:
+ *id = board_id;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static const struct tty_port_operations ipoctal_tty_port_ops = {
+ .dtr_rts = NULL,
+ .activate = ipoctal_port_activate,
+};
+
+static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
+ unsigned int slot, unsigned int vector)
+{
+ int res = 0;
+ int i;
+ struct tty_driver *tty;
+ char name[20];
+ unsigned char board_id;
+
+ res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0,
+ IPACK_ID_SPACE);
+ if (res) {
+ pr_err("Unable to map slot [%d:%d] ID space!\n", bus_nr, slot);
+ return res;
+ }
+
+ res = ipoctal_check_model(ipoctal->dev, &board_id);
+ if (res) {
+ ipoctal->dev->bus->ops->unmap_space(ipoctal->dev,
+ IPACK_ID_SPACE);
+ goto out_unregister_id_space;
+ }
+ ipoctal->board_id = board_id;
+
+ res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0,
+ IPACK_IO_SPACE);
+ if (res) {
+ pr_err("Unable to map slot [%d:%d] IO space!\n", bus_nr, slot);
+ goto out_unregister_id_space;
+ }
+
+ res = ipoctal->dev->bus->ops->map_space(ipoctal->dev,
+ 0x8000, IPACK_MEM_SPACE);
+ if (res) {
+ pr_err("Unable to map slot [%d:%d] MEM space!\n", bus_nr, slot);
+ goto out_unregister_io_space;
+ }
+
+ /* Save the virtual address to access the registers easily */
+ ipoctal->chan_regs =
+ (struct scc2698_channel *) ipoctal->dev->io_space.address;
+ ipoctal->block_regs =
+ (struct scc2698_block *) ipoctal->dev->io_space.address;
+
+ /* Disable RX and TX before touching anything */
+ for (i = 0; i < NR_CHANNELS ; i++) {
+ ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[i].u.w.cr,
+ CR_DISABLE_RX | CR_DISABLE_TX);
+ }
+
+ for (i = 0; i < IP_OCTAL_NB_BLOCKS; i++) {
+ ipoctal_write_io_reg(ipoctal,
+ &ipoctal->block_regs[i].u.w.acr,
+ ACR_BRG_SET2);
+ ipoctal_write_io_reg(ipoctal,
+ &ipoctal->block_regs[i].u.w.opcr,
+ OPCR_MPP_OUTPUT | OPCR_MPOa_RTSN |
+ OPCR_MPOb_RTSN);
+ ipoctal_write_io_reg(ipoctal,
+ &ipoctal->block_regs[i].u.w.imr,
+ IMR_TxRDY_A | IMR_RxRDY_FFULL_A |
+ IMR_DELTA_BREAK_A | IMR_TxRDY_B |
+ IMR_RxRDY_FFULL_B | IMR_DELTA_BREAK_B);
+ }
+
+ /*
+ * IP-OCTAL has different addresses to copy its IRQ vector.
+ * Depending of the carrier these addresses are accesible or not.
+ * More info in the datasheet.
+ */
+ ipoctal->dev->bus->ops->request_irq(ipoctal->dev, vector,
+ ipoctal_irq_handler, ipoctal);
+ ipoctal->dev->bus->ops->write8(ipoctal->dev, IPACK_ID_SPACE, 0, vector);
+
+ /* Register the TTY device */
+
+ /* Each IP-OCTAL channel is a TTY port */
+ tty = alloc_tty_driver(NR_CHANNELS);
+
+ if (!tty) {
+ res = -ENOMEM;
+ goto out_unregister_slot_unmap;
+ }
+
+ /* Fill struct tty_driver with ipoctal data */
+ tty->owner = THIS_MODULE;
+ tty->driver_name = "ipoctal";
+ sprintf(name, "ipoctal.%d.%d.", bus_nr, slot);
+ tty->name = name;
+ tty->major = 0;
+
+ tty->minor_start = 0;
+ tty->type = TTY_DRIVER_TYPE_SERIAL;
+ tty->subtype = SERIAL_TYPE_NORMAL;
+ tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ tty->init_termios = tty_std_termios;
+ tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->init_termios.c_ispeed = 9600;
+ tty->init_termios.c_ospeed = 9600;
+
+ tty_set_operations(tty, &ipoctal_fops);
+ res = tty_register_driver(tty);
+ if (res) {
+ pr_err("Can't register tty driver.\n");
+ put_tty_driver(tty);
+ goto out_unregister_slot_unmap;
+ }
+
+ /* Save struct tty_driver for use it when uninstalling the device */
+ ipoctal->tty_drv = tty;
+
+ for (i = 0; i < NR_CHANNELS; i++) {
+ tty_port_init(&ipoctal->tty_port[i]);
+ tty_port_alloc_xmit_buf(&ipoctal->tty_port[i]);
+ ipoctal->tty_port[i].ops = &ipoctal_tty_port_ops;
+
+ ipoctal_reset_stats(&ipoctal->chan_stats[i]);
+ ipoctal->nb_bytes[i] = 0;
+ init_waitqueue_head(&ipoctal->queue[i]);
+ ipoctal->error_flag[i] = UART_NOERROR;
+
+ spin_lock_init(&ipoctal->lock[i]);
+ ipoctal->pointer_read[i] = 0;
+ ipoctal->pointer_write[i] = 0;
+ ipoctal->nb_bytes[i] = 0;
+ tty_register_device(tty, i, NULL);
+
+ /*
+ * Enable again the RX. TX will be enabled when
+ * there is something to send
+ */
+ ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[i].u.w.cr,
+ CR_ENABLE_RX);
+ }
+
+ return 0;
+
+out_unregister_slot_unmap:
+ ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_ID_SPACE);
+out_unregister_io_space:
+ ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_IO_SPACE);
+out_unregister_id_space:
+ ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_MEM_SPACE);
+ return res;
+}
+
+static inline int ipoctal_copy_write_buffer(struct ipoctal *ipoctal,
+ unsigned int channel,
+ const unsigned char *buf,
+ int count)
+{
+ unsigned long flags;
+ int i;
+ unsigned int *pointer_read = &ipoctal->pointer_read[channel];
+
+ /* Copy the bytes from the user buffer to the internal one */
+ for (i = 0; i < count; i++) {
+ if (i <= (PAGE_SIZE - ipoctal->nb_bytes[channel])) {
+ spin_lock_irqsave(&ipoctal->lock[channel], flags);
+ ipoctal->tty_port[channel].xmit_buf[*pointer_read] = buf[i];
+ *pointer_read = (*pointer_read + 1) % PAGE_SIZE;
+ ipoctal->nb_bytes[channel]++;
+ spin_unlock_irqrestore(&ipoctal->lock[channel], flags);
+ } else {
+ break;
+ }
+ }
+ return i;
+}
+
+static int ipoctal_write(struct ipoctal *ipoctal, unsigned int channel,
+ const unsigned char *buf, int count)
+{
+ ipoctal->nb_bytes[channel] = 0;
+ ipoctal->count_wr[channel] = 0;
+
+ ipoctal_copy_write_buffer(ipoctal, channel, buf, count);
+
+ ipoctal->error_flag[channel] = UART_NOERROR;
+
+ /* As the IP-OCTAL 485 only supports half duplex, do it manually */
+ if (ipoctal->board_id == IP_OCTAL_485_ID) {
+ ipoctal_write_io_reg(ipoctal,
+ &ipoctal->chan_regs[channel].u.w.cr,
+ CR_DISABLE_RX);
+ ipoctal_write_cr_cmd(ipoctal,
+ &ipoctal->chan_regs[channel].u.w.cr,
+ CR_CMD_ASSERT_RTSN);
+ }
+
+ /*
+ * Send a packet and then disable TX to avoid failure after several send
+ * operations
+ */
+ ipoctal_write_io_reg(ipoctal,
+ &ipoctal->chan_regs[channel].u.w.cr,
+ CR_ENABLE_TX);
+ wait_event_interruptible(ipoctal->queue[channel], ipoctal->write);
+ ipoctal_write_io_reg(ipoctal,
+ &ipoctal->chan_regs[channel].u.w.cr,
+ CR_DISABLE_TX);
+
+ ipoctal->write = 0;
+ return ipoctal->count_wr[channel];
+}
+
+static int ipoctal_write_tty(struct tty_struct *tty,
+ const unsigned char *buf, int count)
+{
+ unsigned int channel = tty->index;
+ struct ipoctal *ipoctal = tty->driver_data;
+
+ return ipoctal_write(ipoctal, channel, buf, count);
+}
+
+static int ipoctal_write_room(struct tty_struct *tty)
+{
+ int channel = tty->index;
+ struct ipoctal *ipoctal = tty->driver_data;
+
+ return PAGE_SIZE - ipoctal->nb_bytes[channel];
+}
+
+static int ipoctal_chars_in_buffer(struct tty_struct *tty)
+{
+ int channel = tty->index;
+ struct ipoctal *ipoctal = tty->driver_data;
+
+ return ipoctal->nb_bytes[channel];
+}
+
+static void ipoctal_set_termios(struct tty_struct *tty,
+ struct ktermios *old_termios)
+{
+ unsigned int cflag;
+ unsigned char mr1 = 0;
+ unsigned char mr2 = 0;
+ unsigned char csr = 0;
+ unsigned int channel = tty->index;
+ struct ipoctal *ipoctal = tty->driver_data;
+ speed_t baud;
+
+ cflag = tty->termios->c_cflag;
+
+ /* Disable and reset everything before change the setup */
+ ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
+ CR_DISABLE_RX | CR_DISABLE_TX);
+ ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
+ CR_CMD_RESET_RX);
+ ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
+ CR_CMD_RESET_TX);
+ ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
+ CR_CMD_RESET_ERR_STATUS);
+ ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
+ CR_CMD_RESET_MR);
+
+ /* Set Bits per chars */
+ switch (cflag & CSIZE) {
+ case CS6:
+ mr1 |= MR1_CHRL_6_BITS;
+ break;
+ case CS7:
+ mr1 |= MR1_CHRL_7_BITS;
+ break;
+ case CS8:
+ default:
+ mr1 |= MR1_CHRL_8_BITS;
+ /* By default, select CS8 */
+ tty->termios->c_cflag = (cflag & ~CSIZE) | CS8;
+ break;
+ }
+
+ /* Set Parity */
+ if (cflag & PARENB)
+ if (cflag & PARODD)
+ mr1 |= MR1_PARITY_ON | MR1_PARITY_ODD;
+ else
+ mr1 |= MR1_PARITY_ON | MR1_PARITY_EVEN;
+ else
+ mr1 |= MR1_PARITY_OFF;
+
+ /* Mark or space parity is not supported */
+ tty->termios->c_cflag &= ~CMSPAR;
+
+ /* Set stop bits */
+ if (cflag & CSTOPB)
+ mr2 |= MR2_STOP_BITS_LENGTH_2;
+ else
+ mr2 |= MR2_STOP_BITS_LENGTH_1;
+
+ /* Set the flow control */
+ switch (ipoctal->board_id) {
+ case IP_OCTAL_232_ID:
+ if (cflag & CRTSCTS) {
+ mr1 |= MR1_RxRTS_CONTROL_ON;
+ mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_ON;
+ ipoctal->chan_config[channel].flow_control = 1;
+ } else {
+ mr1 |= MR1_RxRTS_CONTROL_OFF;
+ mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF;
+ ipoctal->chan_config[channel].flow_control = 0;
+ }
+ break;
+ case IP_OCTAL_422_ID:
+ mr1 |= MR1_RxRTS_CONTROL_OFF;
+ mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF;
+ ipoctal->chan_config[channel].flow_control = 0;
+ break;
+ case IP_OCTAL_485_ID:
+ mr1 |= MR1_RxRTS_CONTROL_OFF;
+ mr2 |= MR2_TxRTS_CONTROL_ON | MR2_CTS_ENABLE_TX_OFF;
+ ipoctal->chan_config[channel].flow_control = 0;
+ break;
+ default:
+ return;
+ break;
+ }
+
+ baud = tty_get_baud_rate(tty);
+ tty_termios_encode_baud_rate(tty->termios, baud, baud);
+
+ /* Set baud rate */
+ switch (tty->termios->c_ospeed) {
+ case 75:
+ csr |= TX_CLK_75 | RX_CLK_75;
+ break;
+ case 110:
+ csr |= TX_CLK_110 | RX_CLK_110;
+ break;
+ case 150:
+ csr |= TX_CLK_150 | RX_CLK_150;
+ break;
+ case 300:
+ csr |= TX_CLK_300 | RX_CLK_300;
+ break;
+ case 600:
+ csr |= TX_CLK_600 | RX_CLK_600;
+ break;
+ case 1200:
+ csr |= TX_CLK_1200 | RX_CLK_1200;
+ break;
+ case 1800:
+ csr |= TX_CLK_1800 | RX_CLK_1800;
+ break;
+ case 2000:
+ csr |= TX_CLK_2000 | RX_CLK_2000;
+ break;
+ case 2400:
+ csr |= TX_CLK_2400 | RX_CLK_2400;
+ break;
+ case 4800:
+ csr |= TX_CLK_4800 | RX_CLK_4800;
+ break;
+ case 9600:
+ csr |= TX_CLK_9600 | RX_CLK_9600;
+ break;
+ case 19200:
+ csr |= TX_CLK_19200 | RX_CLK_19200;
+ break;
+ case 38400:
+ default:
+ csr |= TX_CLK_38400 | RX_CLK_38400;
+ /* In case of default, we establish 38400 bps */
+ tty_termios_encode_baud_rate(tty->termios, 38400, 38400);
+ break;
+ }
+
+ mr1 |= MR1_ERROR_CHAR;
+ mr1 |= MR1_RxINT_RxRDY;
+
+ /* Write the control registers */
+ ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.mr, mr1);
+ ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.mr, mr2);
+ ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.csr, csr);
+
+ /* save the setup in the structure */
+ ipoctal->chan_config[channel].baud = tty_get_baud_rate(tty);
+ ipoctal->chan_config[channel].bits_per_char = cflag & CSIZE;
+ ipoctal->chan_config[channel].parity = cflag & PARENB;
+ ipoctal->chan_config[channel].stop_bits = cflag & CSTOPB;
+
+ /* Enable again the RX */
+ ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
+ CR_ENABLE_RX);
+}
+
+static void ipoctal_hangup(struct tty_struct *tty)
+{
+ unsigned long flags;
+ int channel = tty->index;
+ struct ipoctal *ipoctal = tty->driver_data;
+
+ if (ipoctal == NULL)
+ return;
+
+ spin_lock_irqsave(&ipoctal->lock[channel], flags);
+ ipoctal->nb_bytes[channel] = 0;
+ ipoctal->pointer_read[channel] = 0;
+ ipoctal->pointer_write[channel] = 0;
+ spin_unlock_irqrestore(&ipoctal->lock[channel], flags);
+
+ tty_port_hangup(&ipoctal->tty_port[channel]);
+
+ ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
+ CR_DISABLE_RX | CR_DISABLE_TX);
+ ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
+ CR_CMD_RESET_RX);
+ ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
+ CR_CMD_RESET_TX);
+ ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
+ CR_CMD_RESET_ERR_STATUS);
+ ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].u.w.cr,
+ CR_CMD_RESET_MR);
+
+ clear_bit(ASYNCB_INITIALIZED, &ipoctal->tty_port[channel].flags);
+ wake_up_interruptible(&ipoctal->tty_port[channel].open_wait);
+}
+
+static const struct tty_operations ipoctal_fops = {
+ .ioctl = NULL,
+ .open = ipoctal_open,
+ .close = ipoctal_close,
+ .write = ipoctal_write_tty,
+ .set_termios = ipoctal_set_termios,
+ .write_room = ipoctal_write_room,
+ .chars_in_buffer = ipoctal_chars_in_buffer,
+ .get_icount = ipoctal_get_icount,
+ .hangup = ipoctal_hangup,
+};
+
+static int ipoctal_match(struct ipack_device *dev)
+{
+ int res;
+ unsigned char board_id;
+
+ if ((!dev->bus->ops) || (!dev->bus->ops->map_space) ||
+ (!dev->bus->ops->unmap_space))
+ return 0;
+
+ res = dev->bus->ops->map_space(dev, 0, IPACK_ID_SPACE);
+ if (res)
+ return 0;
+
+ res = ipoctal_check_model(dev, &board_id);
+ dev->bus->ops->unmap_space(dev, IPACK_ID_SPACE);
+ if (!res)
+ return 1;
+
+ return 0;
+}
+
+static int ipoctal_probe(struct ipack_device *dev)
+{
+ int res;
+ struct ipoctal *ipoctal;
+
+ ipoctal = kzalloc(sizeof(struct ipoctal), GFP_KERNEL);
+ if (ipoctal == NULL)
+ return -ENOMEM;
+
+ ipoctal->dev = dev;
+ res = ipoctal_inst_slot(ipoctal, dev->bus_nr, dev->slot, dev->irq);
+ if (res)
+ goto out_uninst;
+
+ list_add_tail(&ipoctal->list, &ipoctal_list);
+ return 0;
+
+out_uninst:
+ kfree(ipoctal);
+ return res;
+}
+
+static void __ipoctal_remove(struct ipoctal *ipoctal)
+{
+ int i;
+
+ for (i = 0; i < NR_CHANNELS; i++) {
+ tty_unregister_device(ipoctal->tty_drv, i);
+ tty_port_free_xmit_buf(&ipoctal->tty_port[i]);
+ }
+
+ tty_unregister_driver(ipoctal->tty_drv);
+ put_tty_driver(ipoctal->tty_drv);
+
+ /* Tell the carrier board to free all the resources for this device */
+ if (ipoctal->dev->bus->ops->remove_device != NULL)
+ ipoctal->dev->bus->ops->remove_device(ipoctal->dev);
+
+ list_del(&ipoctal->list);
+ kfree(ipoctal);
+}
+
+static void ipoctal_remove(struct ipack_device *device)
+{
+ struct ipoctal *ipoctal, *next;
+
+ list_for_each_entry_safe(ipoctal, next, &ipoctal_list, list) {
+ if (ipoctal->dev == device)
+ __ipoctal_remove(ipoctal);
+ }
+}
+
+static struct ipack_driver_ops ipoctal_drv_ops = {
+ .match = ipoctal_match,
+ .probe = ipoctal_probe,
+ .remove = ipoctal_remove,
+};
+
+static int __init ipoctal_init(void)
+{
+ driver.ops = &ipoctal_drv_ops;
+ return ipack_driver_register(&driver, THIS_MODULE, KBUILD_MODNAME);
+}
+
+static void __exit ipoctal_exit(void)
+{
+ struct ipoctal *p, *next;
+
+ list_for_each_entry_safe(p, next, &ipoctal_list, list)
+ __ipoctal_remove(p);
+
+ ipack_driver_unregister(&driver);
+}
+
+MODULE_DESCRIPTION("IP-Octal 232, 422 and 485 device driver");
+MODULE_LICENSE("GPL");
+
+module_init(ipoctal_init);
+module_exit(ipoctal_exit);
diff --git a/drivers/staging/ipack/devices/ipoctal.h b/drivers/staging/ipack/devices/ipoctal.h
new file mode 100644
index 000000000000..266f3617069d
--- /dev/null
+++ b/drivers/staging/ipack/devices/ipoctal.h
@@ -0,0 +1,80 @@
+/**
+ * ipoctal.h
+ *
+ * driver for the IPOCTAL boards
+ * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
+ * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
+ * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ */
+
+#ifndef _IPOCTAL_H
+#define _IPOCTAL_H_
+
+#define NR_CHANNELS 8
+#define IPOCTAL_MAX_BOARDS 16
+#define MAX_DEVICES (NR_CHANNELS * IPOCTAL_MAX_BOARDS)
+#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+/**
+ * enum uart_parity_e - UART supported parity.
+ */
+enum uart_parity_e {
+ UART_NONE = 0,
+ UART_ODD = 1,
+ UART_EVEN = 2,
+};
+
+/**
+ * enum uart_error - UART error type
+ *
+ */
+enum uart_error {
+ UART_NOERROR = 0, /* No error during transmission */
+ UART_TIMEOUT = 1 << 0, /* Timeout error */
+ UART_OVERRUN = 1 << 1, /* Overrun error */
+ UART_PARITY = 1 << 2, /* Parity error */
+ UART_FRAMING = 1 << 3, /* Framing error */
+ UART_BREAK = 1 << 4, /* Received break */
+};
+
+/**
+ * struct ipoctal_config - Serial configuration
+ *
+ * @baud: Baud rate
+ * @stop_bits: Stop bits (1 or 2)
+ * @bits_per_char: data size in bits
+ * @parity
+ * @flow_control: Flow control management (RTS/CTS) (0 disabled, 1 enabled)
+ */
+struct ipoctal_config {
+ unsigned int baud;
+ unsigned int stop_bits;
+ unsigned int bits_per_char;
+ unsigned short parity;
+ unsigned int flow_control;
+};
+
+/**
+ * struct ipoctal_stats -- Stats since last reset
+ *
+ * @tx: Number of transmitted bytes
+ * @rx: Number of received bytes
+ * @overrun: Number of overrun errors
+ * @parity_err: Number of parity errors
+ * @framing_err: Number of framing errors
+ * @rcv_break: Number of break received
+ */
+struct ipoctal_stats {
+ unsigned long tx;
+ unsigned long rx;
+ unsigned long overrun_err;
+ unsigned long parity_err;
+ unsigned long framing_err;
+ unsigned long rcv_break;
+};
+
+#endif /* _IPOCTAL_H_ */
diff --git a/drivers/staging/ipack/devices/scc2698.h b/drivers/staging/ipack/devices/scc2698.h
new file mode 100644
index 000000000000..47f6269985fd
--- /dev/null
+++ b/drivers/staging/ipack/devices/scc2698.h
@@ -0,0 +1,228 @@
+/*
+ * scc2698.h
+ *
+ * driver for the IPOCTAL boards
+ * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
+ * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
+ * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ */
+
+#ifndef SCC2698_H_
+#define SCC2698_H_
+
+/*
+ * struct scc2698_channel - Channel access to scc2698 IO
+ *
+ * dn value are only spacer.
+ *
+ */
+struct scc2698_channel {
+ union {
+ struct {
+ unsigned char d0, mr; /* Mode register 1/2*/
+ unsigned char d1, sr; /* Status register */
+ unsigned char d2, r1; /* reserved */
+ unsigned char d3, rhr; /* Receive holding register (R) */
+ unsigned char junk[8]; /* other crap for block control */
+ } r; /* Read access */
+ struct {
+ unsigned char d0, mr; /* Mode register 1/2 */
+ unsigned char d1, csr; /* Clock select register */
+ unsigned char d2, cr; /* Command register */
+ unsigned char d3, thr; /* Transmit holding register */
+ unsigned char junk[8]; /* other crap for block control */
+ } w; /* Write access */
+ } u;
+};
+
+/*
+ * struct scc2698_block - Block access to scc2698 IO
+ *
+ * The scc2698 contain 4 block.
+ * Each block containt two channel a and b.
+ * dn value are only spacer.
+ *
+ */
+struct scc2698_block {
+ union {
+ struct {
+ unsigned char d0, mra; /* Mode register 1/2 (a) */
+ unsigned char d1, sra; /* Status register (a) */
+ unsigned char d2, r1; /* reserved */
+ unsigned char d3, rhra; /* Receive holding register (a) */
+ unsigned char d4, ipcr; /* Input port change register of block */
+ unsigned char d5, isr; /* Interrupt status register of block */
+ unsigned char d6, ctur; /* Counter timer upper register of block */
+ unsigned char d7, ctlr; /* Counter timer lower register of block */
+ unsigned char d8, mrb; /* Mode register 1/2 (b) */
+ unsigned char d9, srb; /* Status register (b) */
+ unsigned char da, r2; /* reserved */
+ unsigned char db, rhrb; /* Receive holding register (b) */
+ unsigned char dc, r3; /* reserved */
+ unsigned char dd, ip; /* Input port register of block */
+ unsigned char de, ctg; /* Start counter timer of block */
+ unsigned char df, cts; /* Stop counter timer of block */
+ } r; /* Read access */
+ struct {
+ unsigned char d0, mra; /* Mode register 1/2 (a) */
+ unsigned char d1, csra; /* Clock select register (a) */
+ unsigned char d2, cra; /* Command register (a) */
+ unsigned char d3, thra; /* Transmit holding register (a) */
+ unsigned char d4, acr; /* Auxiliary control register of block */
+ unsigned char d5, imr; /* Interrupt mask register of block */
+ unsigned char d6, ctu; /* Counter timer upper register of block */
+ unsigned char d7, ctl; /* Counter timer lower register of block */
+ unsigned char d8, mrb; /* Mode register 1/2 (b) */
+ unsigned char d9, csrb; /* Clock select register (a) */
+ unsigned char da, crb; /* Command register (b) */
+ unsigned char db, thrb; /* Transmit holding register (b) */
+ unsigned char dc, r1; /* reserved */
+ unsigned char dd, opcr; /* Output port configuration register of block */
+ unsigned char de, r2; /* reserved */
+ unsigned char df, r3; /* reserved */
+ } w; /* Write access */
+ } u;
+} ;
+
+#define MR1_CHRL_5_BITS (0x0 << 0)
+#define MR1_CHRL_6_BITS (0x1 << 0)
+#define MR1_CHRL_7_BITS (0x2 << 0)
+#define MR1_CHRL_8_BITS (0x3 << 0)
+#define MR1_PARITY_EVEN (0x1 << 2)
+#define MR1_PARITY_ODD (0x0 << 2)
+#define MR1_PARITY_ON (0x0 << 3)
+#define MR1_PARITY_FORCE (0x1 << 3)
+#define MR1_PARITY_OFF (0x2 << 3)
+#define MR1_PARITY_SPECIAL (0x3 << 3)
+#define MR1_ERROR_CHAR (0x0 << 5)
+#define MR1_ERROR_BLOCK (0x1 << 5)
+#define MR1_RxINT_RxRDY (0x0 << 6)
+#define MR1_RxINT_FFULL (0x1 << 6)
+#define MR1_RxRTS_CONTROL_ON (0x1 << 7)
+#define MR1_RxRTS_CONTROL_OFF (0x0 << 7)
+
+#define MR2_STOP_BITS_LENGTH_1 (0x7 << 0)
+#define MR2_STOP_BITS_LENGTH_2 (0xF << 0)
+#define MR2_CTS_ENABLE_TX_ON (0x1 << 4)
+#define MR2_CTS_ENABLE_TX_OFF (0x0 << 4)
+#define MR2_TxRTS_CONTROL_ON (0x1 << 5)
+#define MR2_TxRTS_CONTROL_OFF (0x0 << 5)
+#define MR2_CH_MODE_NORMAL (0x0 << 6)
+#define MR2_CH_MODE_ECHO (0x1 << 6)
+#define MR2_CH_MODE_LOCAL (0x2 << 6)
+#define MR2_CH_MODE_REMOTE (0x3 << 6)
+
+#define CR_ENABLE_RX (0x1 << 0)
+#define CR_DISABLE_RX (0x1 << 1)
+#define CR_ENABLE_TX (0x1 << 2)
+#define CR_DISABLE_TX (0x1 << 3)
+#define CR_CMD_RESET_MR (0x1 << 4)
+#define CR_CMD_RESET_RX (0x2 << 4)
+#define CR_CMD_RESET_TX (0x3 << 4)
+#define CR_CMD_RESET_ERR_STATUS (0x4 << 4)
+#define CR_CMD_RESET_BREAK_CHANGE (0x5 << 4)
+#define CR_CMD_START_BREAK (0x6 << 4)
+#define CR_CMD_STOP_BREAK (0x7 << 4)
+#define CR_CMD_ASSERT_RTSN (0x8 << 4)
+#define CR_CMD_NEGATE_RTSN (0x9 << 4)
+#define CR_CMD_SET_TIMEOUT_MODE (0xA << 4)
+#define CR_CMD_DISABLE_TIMEOUT_MODE (0xC << 4)
+
+#define SR_RX_READY (0x1 << 0)
+#define SR_FIFO_FULL (0x1 << 1)
+#define SR_TX_READY (0x1 << 2)
+#define SR_TX_EMPTY (0x1 << 3)
+#define SR_OVERRUN_ERROR (0x1 << 4)
+#define SR_PARITY_ERROR (0x1 << 5)
+#define SR_FRAMING_ERROR (0x1 << 6)
+#define SR_RECEIVED_BREAK (0x1 << 7)
+
+#define SR_ERROR (0xF0)
+
+#define ACR_DELTA_IP0_IRQ_EN (0x1 << 0)
+#define ACR_DELTA_IP1_IRQ_EN (0x1 << 1)
+#define ACR_DELTA_IP2_IRQ_EN (0x1 << 2)
+#define ACR_DELTA_IP3_IRQ_EN (0x1 << 3)
+#define ACR_CT_Mask (0x7 << 4)
+#define ACR_CExt (0x0 << 4)
+#define ACR_CTxCA (0x1 << 4)
+#define ACR_CTxCB (0x2 << 4)
+#define ACR_CClk16 (0x3 << 4)
+#define ACR_TExt (0x4 << 4)
+#define ACR_TExt16 (0x5 << 4)
+#define ACR_TClk (0x6 << 4)
+#define ACR_TClk16 (0x7 << 4)
+#define ACR_BRG_SET1 (0x0 << 7)
+#define ACR_BRG_SET2 (0x1 << 7)
+
+#define TX_CLK_75 (0x0 << 0)
+#define TX_CLK_110 (0x1 << 0)
+#define TX_CLK_38400 (0x2 << 0)
+#define TX_CLK_150 (0x3 << 0)
+#define TX_CLK_300 (0x4 << 0)
+#define TX_CLK_600 (0x5 << 0)
+#define TX_CLK_1200 (0x6 << 0)
+#define TX_CLK_2000 (0x7 << 0)
+#define TX_CLK_2400 (0x8 << 0)
+#define TX_CLK_4800 (0x9 << 0)
+#define TX_CLK_1800 (0xA << 0)
+#define TX_CLK_9600 (0xB << 0)
+#define TX_CLK_19200 (0xC << 0)
+#define RX_CLK_75 (0x0 << 4)
+#define RX_CLK_110 (0x1 << 4)
+#define RX_CLK_38400 (0x2 << 4)
+#define RX_CLK_150 (0x3 << 4)
+#define RX_CLK_300 (0x4 << 4)
+#define RX_CLK_600 (0x5 << 4)
+#define RX_CLK_1200 (0x6 << 4)
+#define RX_CLK_2000 (0x7 << 4)
+#define RX_CLK_2400 (0x8 << 4)
+#define RX_CLK_4800 (0x9 << 4)
+#define RX_CLK_1800 (0xA << 4)
+#define RX_CLK_9600 (0xB << 4)
+#define RX_CLK_19200 (0xC << 4)
+
+#define OPCR_MPOa_RTSN (0x0 << 0)
+#define OPCR_MPOa_C_TO (0x1 << 0)
+#define OPCR_MPOa_TxC1X (0x2 << 0)
+#define OPCR_MPOa_TxC16X (0x3 << 0)
+#define OPCR_MPOa_RxC1X (0x4 << 0)
+#define OPCR_MPOa_RxC16X (0x5 << 0)
+#define OPCR_MPOa_TxRDY (0x6 << 0)
+#define OPCR_MPOa_RxRDY_FF (0x7 << 0)
+
+#define OPCR_MPOb_RTSN (0x0 << 4)
+#define OPCR_MPOb_C_TO (0x1 << 4)
+#define OPCR_MPOb_TxC1X (0x2 << 4)
+#define OPCR_MPOb_TxC16X (0x3 << 4)
+#define OPCR_MPOb_RxC1X (0x4 << 4)
+#define OPCR_MPOb_RxC16X (0x5 << 4)
+#define OPCR_MPOb_TxRDY (0x6 << 4)
+#define OPCR_MPOb_RxRDY_FF (0x7 << 4)
+
+#define OPCR_MPP_INPUT (0x0 << 7)
+#define OPCR_MPP_OUTPUT (0x1 << 7)
+
+#define IMR_TxRDY_A (0x1 << 0)
+#define IMR_RxRDY_FFULL_A (0x1 << 1)
+#define IMR_DELTA_BREAK_A (0x1 << 2)
+#define IMR_COUNTER_READY (0x1 << 3)
+#define IMR_TxRDY_B (0x1 << 4)
+#define IMR_RxRDY_FFULL_B (0x1 << 5)
+#define IMR_DELTA_BREAK_B (0x1 << 6)
+#define IMR_INPUT_PORT_CHANGE (0x1 << 7)
+
+#define ISR_TxRDY_A (0x1 << 0)
+#define ISR_RxRDY_FFULL_A (0x1 << 1)
+#define ISR_DELTA_BREAK_A (0x1 << 2)
+#define ISR_COUNTER_READY (0x1 << 3)
+#define ISR_TxRDY_B (0x1 << 4)
+#define ISR_RxRDY_FFULL_B (0x1 << 5)
+#define ISR_DELTA_BREAK_B (0x1 << 6)
+#define ISR_INPUT_PORT_CHANGE (0x1 << 7)
+
+#endif /* SCC2698_H_ */
diff --git a/drivers/staging/ipack/ipack.c b/drivers/staging/ipack/ipack.c
new file mode 100644
index 000000000000..2b4fa51bf167
--- /dev/null
+++ b/drivers/staging/ipack/ipack.c
@@ -0,0 +1,205 @@
+/*
+ * Industry-pack bus support functions.
+ *
+ * (C) 2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
+ * (C) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include "ipack.h"
+
+#define to_ipack_dev(device) container_of(device, struct ipack_device, dev)
+#define to_ipack_driver(drv) container_of(drv, struct ipack_driver, driver)
+
+/* used when allocating bus numbers */
+#define IPACK_MAXBUS 64
+
+static DEFINE_MUTEX(ipack_mutex);
+
+struct ipack_busmap {
+ unsigned long busmap[IPACK_MAXBUS / (8*sizeof(unsigned long))];
+};
+static struct ipack_busmap busmap;
+
+static void ipack_device_release(struct device *dev)
+{
+ struct ipack_device *device = to_ipack_dev(dev);
+ kfree(device);
+}
+
+static int ipack_bus_match(struct device *device, struct device_driver *driver)
+{
+ int ret;
+ struct ipack_device *dev = to_ipack_dev(device);
+ struct ipack_driver *drv = to_ipack_driver(driver);
+
+ if ((!drv->ops) || (!drv->ops->match))
+ return -EINVAL;
+
+ ret = drv->ops->match(dev);
+ if (ret)
+ dev->driver = drv;
+
+ return 0;
+}
+
+static int ipack_bus_probe(struct device *device)
+{
+ struct ipack_device *dev = to_ipack_dev(device);
+
+ if (!dev->driver->ops->probe)
+ return -EINVAL;
+
+ return dev->driver->ops->probe(dev);
+}
+
+static int ipack_bus_remove(struct device *device)
+{
+ struct ipack_device *dev = to_ipack_dev(device);
+
+ if (!dev->driver->ops->remove)
+ return -EINVAL;
+
+ dev->driver->ops->remove(dev);
+ return 0;
+}
+
+static struct bus_type ipack_bus_type = {
+ .name = "ipack",
+ .probe = ipack_bus_probe,
+ .match = ipack_bus_match,
+ .remove = ipack_bus_remove,
+};
+
+static int ipack_assign_bus_number(void)
+{
+ int busnum;
+
+ mutex_lock(&ipack_mutex);
+ busnum = find_next_zero_bit(busmap.busmap, IPACK_MAXBUS, 1);
+
+ if (busnum >= IPACK_MAXBUS) {
+ pr_err("too many buses\n");
+ busnum = -1;
+ goto error_find_busnum;
+ }
+
+ set_bit(busnum, busmap.busmap);
+
+error_find_busnum:
+ mutex_unlock(&ipack_mutex);
+ return busnum;
+}
+
+struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
+ struct ipack_bus_ops *ops)
+{
+ int bus_nr;
+ struct ipack_bus_device *bus;
+
+ bus = kzalloc(sizeof(struct ipack_bus_device), GFP_KERNEL);
+ if (!bus)
+ return NULL;
+
+ bus_nr = ipack_assign_bus_number();
+ if (bus_nr < 0) {
+ kfree(bus);
+ return NULL;
+ }
+
+ bus->bus_nr = bus_nr;
+ bus->parent = parent;
+ bus->slots = slots;
+ bus->ops = ops;
+ return bus;
+}
+EXPORT_SYMBOL_GPL(ipack_bus_register);
+
+int ipack_bus_unregister(struct ipack_bus_device *bus)
+{
+ mutex_lock(&ipack_mutex);
+ clear_bit(bus->bus_nr, busmap.busmap);
+ mutex_unlock(&ipack_mutex);
+ kfree(bus);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipack_bus_unregister);
+
+int ipack_driver_register(struct ipack_driver *edrv, struct module *owner,
+ char *name)
+{
+ edrv->driver.owner = owner;
+ edrv->driver.name = name;
+ edrv->driver.bus = &ipack_bus_type;
+ return driver_register(&edrv->driver);
+}
+EXPORT_SYMBOL_GPL(ipack_driver_register);
+
+void ipack_driver_unregister(struct ipack_driver *edrv)
+{
+ driver_unregister(&edrv->driver);
+}
+EXPORT_SYMBOL_GPL(ipack_driver_unregister);
+
+struct ipack_device *ipack_device_register(struct ipack_bus_device *bus,
+ int slot, int irqv)
+{
+ int ret;
+ struct ipack_device *dev;
+
+ dev = kzalloc(sizeof(struct ipack_device), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ dev->dev.bus = &ipack_bus_type;
+ dev->dev.release = ipack_device_release;
+ dev->dev.parent = bus->parent;
+ dev->slot = slot;
+ dev->bus_nr = bus->bus_nr;
+ dev->irq = irqv;
+ dev->bus = bus;
+ dev_set_name(&dev->dev,
+ "ipack-dev.%u.%u", dev->bus_nr, dev->slot);
+
+ ret = device_register(&dev->dev);
+ if (ret < 0) {
+ pr_err("error registering the device.\n");
+ dev->driver->ops->remove(dev);
+ kfree(dev);
+ return NULL;
+ }
+
+ return dev;
+}
+EXPORT_SYMBOL_GPL(ipack_device_register);
+
+void ipack_device_unregister(struct ipack_device *dev)
+{
+ device_unregister(&dev->dev);
+}
+EXPORT_SYMBOL_GPL(ipack_device_unregister);
+
+static int __init ipack_init(void)
+{
+ return bus_register(&ipack_bus_type);
+}
+
+static void __exit ipack_exit(void)
+{
+ bus_unregister(&ipack_bus_type);
+}
+
+module_init(ipack_init);
+module_exit(ipack_exit);
+
+MODULE_AUTHOR("Samuel Iglesias Gonsalvez <siglesias@igalia.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Industry-pack bus core");
diff --git a/drivers/staging/ipack/ipack.h b/drivers/staging/ipack/ipack.h
new file mode 100644
index 000000000000..8bc001e3ca4e
--- /dev/null
+++ b/drivers/staging/ipack/ipack.h
@@ -0,0 +1,183 @@
+/*
+ * Industry-pack bus.
+ *
+ * (C) 2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
+ * (C) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ */
+
+#include <linux/device.h>
+
+#define IPACK_IDPROM_OFFSET_I 0x01
+#define IPACK_IDPROM_OFFSET_P 0x03
+#define IPACK_IDPROM_OFFSET_A 0x05
+#define IPACK_IDPROM_OFFSET_C 0x07
+#define IPACK_IDPROM_OFFSET_MANUFACTURER_ID 0x09
+#define IPACK_IDPROM_OFFSET_MODEL 0x0B
+#define IPACK_IDPROM_OFFSET_REVISION 0x0D
+#define IPACK_IDPROM_OFFSET_RESERVED 0x0F
+#define IPACK_IDPROM_OFFSET_DRIVER_ID_L 0x11
+#define IPACK_IDPROM_OFFSET_DRIVER_ID_H 0x13
+#define IPACK_IDPROM_OFFSET_NUM_BYTES 0x15
+#define IPACK_IDPROM_OFFSET_CRC 0x17
+
+struct ipack_bus_ops;
+struct ipack_driver;
+
+enum ipack_space {
+ IPACK_IO_SPACE = 0,
+ IPACK_ID_SPACE = 1,
+ IPACK_MEM_SPACE = 2,
+};
+
+/**
+ * struct ipack_addr_space - Virtual address space mapped for a specified type.
+ *
+ * @address: virtual address
+ * @size: size of the mapped space
+ */
+struct ipack_addr_space {
+ void __iomem *address;
+ unsigned int size;
+};
+
+/**
+ * struct ipack_device
+ *
+ * @bus_nr: IP bus number where the device is plugged
+ * @slot: Slot where the device is plugged in the carrier board
+ * @irq: IRQ vector
+ * @driver: Pointer to the ipack_driver that manages the device
+ * @bus: ipack_bus_device where the device is plugged to.
+ * @id_space: Virtual address to ID space.
+ * @io_space: Virtual address to IO space.
+ * @mem_space: Virtual address to MEM space.
+ * @dev: device in kernel representation.
+ *
+ * Warning: Direct access to mapped memory is possible but the endianness
+ * is not the same with PCI carrier or VME carrier. The endianness is managed
+ * by the carrier board throught bus->ops.
+ */
+struct ipack_device {
+ unsigned int bus_nr;
+ unsigned int slot;
+ unsigned int irq;
+ struct ipack_driver *driver;
+ struct ipack_bus_device *bus;
+ struct ipack_addr_space id_space;
+ struct ipack_addr_space io_space;
+ struct ipack_addr_space mem_space;
+ struct device dev;
+};
+
+/**
+ * struct ipack_driver_ops -- callbacks to mezzanine driver for installing/removing one device
+ *
+ * @match: Match function
+ * @probe: Probe function
+ * @remove: tell the driver that the carrier board wants to remove one device
+ */
+
+struct ipack_driver_ops {
+ int (*match) (struct ipack_device *dev);
+ int (*probe) (struct ipack_device *dev);
+ void (*remove) (struct ipack_device *dev);
+};
+
+/**
+ * struct ipack_driver -- Specific data to each ipack board driver
+ *
+ * @driver: Device driver kernel representation
+ * @ops: Mezzanine driver operations specific for the ipack bus.
+ */
+struct ipack_driver {
+ struct device_driver driver;
+ struct ipack_driver_ops *ops;
+};
+
+/**
+ * struct ipack_bus_ops - available operations on a bridge module
+ *
+ * @map_space: map IP address space
+ * @unmap_space: unmap IP address space
+ * @request_irq: request IRQ
+ * @free_irq: free IRQ
+ * @read8: read unsigned char
+ * @read16: read unsigned short
+ * @read32: read unsigned int
+ * @write8: read unsigned char
+ * @write16: read unsigned short
+ * @write32: read unsigned int
+ * @remove_device: tell the bridge module that the device has been removed
+ */
+struct ipack_bus_ops {
+ int (*map_space) (struct ipack_device *dev, unsigned int memory_size, int space);
+ int (*unmap_space) (struct ipack_device *dev, int space);
+ int (*request_irq) (struct ipack_device *dev, int vector, int (*handler)(void *), void *arg);
+ int (*free_irq) (struct ipack_device *dev);
+ int (*read8) (struct ipack_device *dev, int space, unsigned long offset, unsigned char *value);
+ int (*read16) (struct ipack_device *dev, int space, unsigned long offset, unsigned short *value);
+ int (*read32) (struct ipack_device *dev, int space, unsigned long offset, unsigned int *value);
+ int (*write8) (struct ipack_device *dev, int space, unsigned long offset, unsigned char value);
+ int (*write16) (struct ipack_device *dev, int space, unsigned long offset, unsigned short value);
+ int (*write32) (struct ipack_device *dev, int space, unsigned long offset, unsigned int value);
+ int (*remove_device) (struct ipack_device *dev);
+};
+
+/**
+ * struct ipack_bus_device
+ *
+ * @dev: pointer to carrier device
+ * @slots: number of slots available
+ * @bus_nr: ipack bus number
+ * @ops: bus operations for the mezzanine drivers
+ */
+struct ipack_bus_device {
+ struct device *parent;
+ int slots;
+ int bus_nr;
+ struct ipack_bus_ops *ops;
+};
+
+/**
+ * ipack_bus_register -- register a new ipack bus
+ *
+ * @parent: pointer to the parent device, if any.
+ * @slots: number of slots available in the bus device.
+ * @ops: bus operations for the mezzanine drivers.
+ *
+ * The carrier board device should call this function to register itself as
+ * available bus device in ipack.
+ */
+struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
+ struct ipack_bus_ops *ops);
+
+/**
+ * ipack_bus_unregister -- unregister an ipack bus
+ */
+int ipack_bus_unregister(struct ipack_bus_device *bus);
+
+/**
+ * ipack_driver_register -- Register a new driver
+ *
+ * Called by a ipack driver to register itself as a driver
+ * that can manage ipack devices.
+ */
+int ipack_driver_register(struct ipack_driver *edrv, struct module *owner, char *name);
+void ipack_driver_unregister(struct ipack_driver *edrv);
+
+/**
+ * ipack_device_register -- register a new mezzanine device
+ *
+ * @bus: ipack bus device it is plugged to.
+ * @slot: slot position in the bus device.
+ * @irqv: IRQ vector for the mezzanine.
+ *
+ * Register a new ipack device (mezzanine device). The call is done by
+ * the carrier device driver.
+ */
+struct ipack_device *ipack_device_register(struct ipack_bus_device *bus, int slot, int irqv);
+void ipack_device_unregister(struct ipack_device *dev);
diff --git a/drivers/staging/line6/config.h b/drivers/staging/line6/config.h
deleted file mode 100644
index f8a5149e3dad..000000000000
--- a/drivers/staging/line6/config.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.8.0
- *
- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#ifndef CONFIG_H
-#define CONFIG_H
-
-
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG 1
-#endif
-
-
-/*
- * Development tools.
- */
-#define DO_DEBUG_MESSAGES 0
-#define DO_DUMP_URB_SEND DO_DEBUG_MESSAGES
-#define DO_DUMP_URB_RECEIVE DO_DEBUG_MESSAGES
-#define DO_DUMP_PCM_SEND 0
-#define DO_DUMP_PCM_RECEIVE 0
-#define DO_DUMP_MIDI_SEND DO_DEBUG_MESSAGES
-#define DO_DUMP_MIDI_RECEIVE DO_DEBUG_MESSAGES
-#define DO_DUMP_ANY (DO_DUMP_URB_SEND || DO_DUMP_URB_RECEIVE || \
- DO_DUMP_PCM_SEND || DO_DUMP_PCM_RECEIVE || \
- DO_DUMP_MIDI_SEND || DO_DUMP_MIDI_RECEIVE)
-#define CREATE_RAW_FILE 0
-
-#if DO_DEBUG_MESSAGES
-#define CHECKPOINT printk(KERN_INFO "line6usb: %s (%s:%d)\n", \
- __func__, __FILE__, __LINE__)
-#endif
-
-#if DO_DEBUG_MESSAGES
-#define DEBUG_MESSAGES(x) (x)
-#else
-#define DEBUG_MESSAGES(x)
-#endif
-
-
-#endif
diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c
index e8023afd3656..4513f78f1127 100644
--- a/drivers/staging/line6/driver.c
+++ b/drivers/staging/line6/driver.c
@@ -92,15 +92,10 @@ const unsigned char line6_midi_id[] = {
Code to request version of POD, Variax interface
(and maybe other devices).
*/
-static const char line6_request_version0[] = {
+static const char line6_request_version[] = {
0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7
};
-/*
- Copy of version request code with GFP_KERNEL flag for use in URB.
-*/
-static const char *line6_request_version;
-
struct usb_line6 *line6_devices[LINE6_MAX_DEVICES];
/**
@@ -336,8 +331,21 @@ int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer,
*/
int line6_version_request_async(struct usb_line6 *line6)
{
- return line6_send_raw_message_async(line6, line6_request_version,
- sizeof(line6_request_version0));
+ char *buffer;
+ int retval;
+
+ buffer = kmalloc(sizeof(line6_request_version), GFP_ATOMIC);
+ if (buffer == NULL) {
+ dev_err(line6->ifcdev, "Out of memory");
+ return -ENOMEM;
+ }
+
+ memcpy(buffer, line6_request_version, sizeof(line6_request_version));
+
+ retval = line6_send_raw_message_async(line6, buffer,
+ sizeof(line6_request_version));
+ kfree(buffer);
+ return retval;
}
/*
@@ -1292,69 +1300,7 @@ static struct usb_driver line6_driver = {
.id_table = line6_id_table,
};
-/*
- Module initialization.
-*/
-static int __init line6_init(void)
-{
- int i, retval;
-
- printk(KERN_INFO "%s driver version %s\n", DRIVER_NAME, DRIVER_VERSION);
-
- for (i = LINE6_MAX_DEVICES; i--;)
- line6_devices[i] = NULL;
-
- retval = usb_register(&line6_driver);
-
- if (retval) {
- err("usb_register failed. Error number %d", retval);
- return retval;
- }
-
- line6_request_version = kmalloc(sizeof(line6_request_version0),
- GFP_KERNEL);
-
- if (line6_request_version == NULL) {
- err("Out of memory");
- return -ENOMEM;
- }
-
- memcpy((char *)line6_request_version, line6_request_version0,
- sizeof(line6_request_version0));
-
- return retval;
-}
-
-/*
- Module cleanup.
-*/
-static void __exit line6_exit(void)
-{
- int i;
- struct usb_line6 *line6;
- struct snd_line6_pcm *line6pcm;
-
- /* stop all PCM channels */
- for (i = LINE6_MAX_DEVICES; i--;) {
- line6 = line6_devices[i];
-
- if (line6 == NULL)
- continue;
-
- line6pcm = line6->line6pcm;
-
- if (line6pcm == NULL)
- continue;
-
- line6_pcm_release(line6pcm, ~0);
- }
-
- usb_deregister(&line6_driver);
- kfree(line6_request_version);
-}
-
-module_init(line6_init);
-module_exit(line6_exit);
+module_usb_driver(line6_driver);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c
index 13d02939c3cb..50407294fbd4 100644
--- a/drivers/staging/line6/midi.c
+++ b/drivers/staging/line6/midi.c
@@ -406,7 +406,7 @@ int line6_init_midi(struct usb_line6 *line6)
line6midi->line6 = line6;
- switch(line6->product) {
+ switch (line6->product) {
case LINE6_DEVID_PODHD300:
case LINE6_DEVID_PODHD500:
line6midi->midi_mask_transmit = 1;
diff --git a/drivers/staging/line6/midibuf.c b/drivers/staging/line6/midibuf.c
index 7b532e5ce8b4..836e8c847c52 100644
--- a/drivers/staging/line6/midibuf.c
+++ b/drivers/staging/line6/midibuf.c
@@ -64,7 +64,7 @@ int line6_midibuf_init(struct MidiBuffer *this, int size, int split)
void line6_midibuf_status(struct MidiBuffer *this)
{
- printk(KERN_DEBUG "midibuf size=%d split=%d pos_read=%d pos_write=%d "
+ pr_debug("midibuf size=%d split=%d pos_read=%d pos_write=%d "
"full=%d command_prev=%02x\n", this->size, this->split,
this->pos_read, this->pos_write, this->full, this->command_prev);
}
diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c
index 90d2d4475cb4..5e319e3ce685 100644
--- a/drivers/staging/line6/pcm.c
+++ b/drivers/staging/line6/pcm.c
@@ -99,7 +99,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels)
unsigned long flags_new = flags_old | channels;
unsigned long flags_final = flags_old;
int err = 0;
-
+
line6pcm->prev_fbuf = NULL;
if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_BUFFER)) {
diff --git a/drivers/staging/line6/toneport.c b/drivers/staging/line6/toneport.c
index b754f69a29c4..31b624b63425 100644
--- a/drivers/staging/line6/toneport.c
+++ b/drivers/staging/line6/toneport.c
@@ -168,7 +168,7 @@ static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ);
if (ret < 0) {
- err("send failed (error %d)\n", ret);
+ dev_err(&usbdev->dev, "send failed (error %d)\n", ret);
return ret;
}
diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c
index ea4f992de235..ac92eaf6c74b 100644
--- a/drivers/staging/media/as102/as102_drv.c
+++ b/drivers/staging/media/as102/as102_drv.c
@@ -279,40 +279,8 @@ void as102_dvb_unregister(struct as102_dev_t *as102_dev)
pr_info("Unregistered device %s", as102_dev->name);
}
-static int __init as102_driver_init(void)
-{
- int ret;
-
- /* register this driver with the low level subsystem */
- ret = usb_register(&as102_usb_driver);
- if (ret)
- err("usb_register failed (ret = %d)", ret);
-
- return ret;
-}
-
-/*
- * Mandatory function : Adds a special section to the module indicating
- * where initialisation function is defined
- */
-module_init(as102_driver_init);
-
-/**
- * as102_driver_exit - as102 driver exit point
- *
- * This function is called when device has to be removed.
- */
-static void __exit as102_driver_exit(void)
-{
- /* deregister this driver with the low level bus subsystem */
- usb_deregister(&as102_usb_driver);
-}
+module_usb_driver(as102_usb_driver);
-/*
- * required function for unload: Adds a special section to the module
- * indicating where unload function is defined
- */
-module_exit(as102_driver_exit);
/* modinfo details */
MODULE_DESCRIPTION(DRIVER_FULL_NAME);
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/media/as102/as102_fe.c b/drivers/staging/media/as102/as102_fe.c
index 5917657b9d0f..9ce8c9daa2e7 100644
--- a/drivers/staging/media/as102/as102_fe.c
+++ b/drivers/staging/media/as102/as102_fe.c
@@ -17,8 +17,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/version.h>
-
#include "as102_drv.h"
#include "as10x_types.h"
#include "as10x_cmd.h"
diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c
index 1075fb1df0d9..b9670ee41b4e 100644
--- a/drivers/staging/media/as102/as102_fw.c
+++ b/drivers/staging/media/as102/as102_fw.c
@@ -230,11 +230,8 @@ int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap)
pr_info("%s: firmware: %s loaded with success\n",
DRIVER_NAME, fw2);
error:
- /* free data buffer */
kfree(cmd_buf);
- /* release firmware if needed */
- if (firmware != NULL)
- release_firmware(firmware);
+ release_firmware(firmware);
LEAVE();
return errno;
diff --git a/drivers/staging/media/as102/as102_usb_drv.c b/drivers/staging/media/as102/as102_usb_drv.c
index 0f6bfe7eccba..aaf1bc2ad1b2 100644
--- a/drivers/staging/media/as102/as102_usb_drv.c
+++ b/drivers/staging/media/as102/as102_usb_drv.c
@@ -367,7 +367,7 @@ static int as102_usb_probe(struct usb_interface *intf,
ENTER();
/* This should never actually happen */
- if ((sizeof(as102_usb_id_table) / sizeof(struct usb_device_id)) !=
+ if (ARRAY_SIZE(as102_usb_id_table) !=
(sizeof(as102_device_names) / sizeof(const char *))) {
pr_err("Device names table invalid size");
return -EINVAL;
@@ -375,13 +375,12 @@ static int as102_usb_probe(struct usb_interface *intf,
as102_dev = kzalloc(sizeof(struct as102_dev_t), GFP_KERNEL);
if (as102_dev == NULL) {
- err("%s: kzalloc failed", __func__);
+ dev_err(&intf->dev, "%s: kzalloc failed\n", __func__);
return -ENOMEM;
}
/* Assign the user-friendly device name */
- for (i = 0; i < (sizeof(as102_usb_id_table) /
- sizeof(struct usb_device_id)); i++) {
+ for (i = 0; i < ARRAY_SIZE(as102_usb_id_table); i++) {
if (id == &as102_usb_id_table[i]) {
as102_dev->name = as102_device_names[i];
as102_dev->elna_cfg = as102_elna_cfg[i];
@@ -411,8 +410,9 @@ static int as102_usb_probe(struct usb_interface *intf,
ret = usb_register_dev(intf, &as102_usb_class_driver);
if (ret < 0) {
/* something prevented us from registering this driver */
- err("%s: usb_register_dev() failed (errno = %d)",
- __func__, ret);
+ dev_err(&intf->dev,
+ "%s: usb_register_dev() failed (errno = %d)\n",
+ __func__, ret);
goto failed;
}
diff --git a/drivers/staging/media/as102/as102_usb_drv.h b/drivers/staging/media/as102/as102_usb_drv.h
index fc2884ab02a2..1ad1ec52b11e 100644
--- a/drivers/staging/media/as102/as102_usb_drv.h
+++ b/drivers/staging/media/as102/as102_usb_drv.h
@@ -17,8 +17,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/version.h>
-
#ifndef _AS102_USB_DRV_H_
#define _AS102_USB_DRV_H_
diff --git a/drivers/staging/media/easycap/easycap_ioctl.c b/drivers/staging/media/easycap/easycap_ioctl.c
index 9413b37490c2..3cee3cd986d2 100644
--- a/drivers/staging/media/easycap/easycap_ioctl.c
+++ b/drivers/staging/media/easycap/easycap_ioctl.c
@@ -26,6 +26,7 @@
/*****************************************************************************/
#include "easycap.h"
+#include <linux/version.h>
/*--------------------------------------------------------------------------*/
/*
diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c
index d0fe34afc2e5..6f83d362ab0d 100644
--- a/drivers/staging/media/easycap/easycap_main.c
+++ b/drivers/staging/media/easycap/easycap_main.c
@@ -3578,7 +3578,8 @@ static int easycap_usb_probe(struct usb_interface *intf,
if (0 != (video_register_device(&(peasycap->video_device),
VFL_TYPE_GRABBER, -1))) {
- err("Not able to register with videodev");
+ dev_err(&intf->dev,
+ "Not able to register with videodev\n");
videodev_release(&(peasycap->video_device));
return -ENODEV;
}
@@ -3822,7 +3823,8 @@ static int easycap_usb_probe(struct usb_interface *intf,
rc = easycap_alsa_probe(peasycap);
if (rc) {
- err("easycap_alsa_probe() rc = %i\n", rc);
+ dev_err(&intf->dev, "easycap_alsa_probe() rc = %i\n",
+ rc);
return -ENODEV;
}
diff --git a/drivers/staging/media/go7007/README b/drivers/staging/media/go7007/README
index 48f447637817..aeba1324a9c5 100644
--- a/drivers/staging/media/go7007/README
+++ b/drivers/staging/media/go7007/README
@@ -6,6 +6,6 @@ Todo:
- testing?
- handle churn in v4l layer.
-Please send patchs to Greg Kroah-Hartman <greg@kroah.com> and Cc: Ross
+Please send patches to Greg Kroah-Hartman <greg@linuxfoundation.org> and Cc: Ross
Cohen <rcohen@snurgle.org> as well.
diff --git a/drivers/staging/media/go7007/go7007.txt b/drivers/staging/media/go7007/go7007.txt
index 9db1f3952fd2..fcb3e235abbf 100644
--- a/drivers/staging/media/go7007/go7007.txt
+++ b/drivers/staging/media/go7007/go7007.txt
@@ -87,7 +87,6 @@ kernel as built-in or modules:
CONFIG_SOUND - Sound card support
CONFIG_SND - Advanced Linux Sound Architecture
CONFIG_USB - Support for Host-side USB
- CONFIG_USB_DEVICEFS - USB device filesystem
CONFIG_USB_EHCI_HCD - EHCI HCD (USB 2.0) support
Additionally, to use the example application, the following options need to
diff --git a/drivers/staging/media/go7007/s2250-loader.c b/drivers/staging/media/go7007/s2250-loader.c
index 4e132519e253..7c5af4f289b6 100644
--- a/drivers/staging/media/go7007/s2250-loader.c
+++ b/drivers/staging/media/go7007/s2250-loader.c
@@ -160,31 +160,7 @@ static struct usb_driver s2250loader_driver = {
.id_table = s2250loader_ids,
};
-static int __init s2250loader_init(void)
-{
- int r;
- unsigned i = 0;
-
- for (i = 0; i < MAX_DEVICES; i++)
- s2250_dev_table[i] = NULL;
-
- r = usb_register(&s2250loader_driver);
- if (r) {
- printk(KERN_ERR "usb_register failed. Error number %d\n", r);
- return -1;
- }
-
- printk(KERN_INFO "s2250loader_init: driver registered\n");
- return 0;
-}
-module_init(s2250loader_init);
-
-static void __exit s2250loader_cleanup(void)
-{
- printk(KERN_INFO "s2250loader_cleanup\n");
- usb_deregister(&s2250loader_driver);
-}
-module_exit(s2250loader_cleanup);
+module_usb_driver(s2250loader_driver);
MODULE_AUTHOR("");
MODULE_DESCRIPTION("firmware loader for Sensoray 2250/2251");
diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c
index 5f7f8cd3a661..d7cf5ef076a5 100644
--- a/drivers/staging/media/lirc/lirc_imon.c
+++ b/drivers/staging/media/lirc/lirc_imon.c
@@ -209,8 +209,9 @@ static void deregister_from_lirc(struct imon_context *context)
retval = lirc_unregister_driver(minor);
if (retval)
- err("%s: unable to deregister from lirc(%d)",
- __func__, retval);
+ printk(KERN_ERR KBUILD_MODNAME
+ ": %s: unable to deregister from lirc(%d)",
+ __func__, retval);
else
printk(KERN_INFO MOD_NAME ": Deregistered iMON driver "
"(minor:%d)\n", minor);
@@ -234,16 +235,18 @@ static int display_open(struct inode *inode, struct file *file)
subminor = iminor(inode);
interface = usb_find_interface(&imon_driver, subminor);
if (!interface) {
- err("%s: could not find interface for minor %d",
- __func__, subminor);
+ printk(KERN_ERR KBUILD_MODNAME
+ ": %s: could not find interface for minor %d\n",
+ __func__, subminor);
retval = -ENODEV;
goto exit;
}
context = usb_get_intfdata(interface);
if (!context) {
- err("%s: no context found for minor %d",
- __func__, subminor);
+ dev_err(&interface->dev,
+ "%s: no context found for minor %d\n",
+ __func__, subminor);
retval = -ENODEV;
goto exit;
}
@@ -251,10 +254,12 @@ static int display_open(struct inode *inode, struct file *file)
mutex_lock(&context->ctx_lock);
if (!context->display) {
- err("%s: display not supported by device", __func__);
+ dev_err(&interface->dev,
+ "%s: display not supported by device\n", __func__);
retval = -ENODEV;
} else if (context->display_isopen) {
- err("%s: display port is already open", __func__);
+ dev_err(&interface->dev,
+ "%s: display port is already open\n", __func__);
retval = -EBUSY;
} else {
context->display_isopen = 1;
@@ -281,17 +286,20 @@ static int display_close(struct inode *inode, struct file *file)
context = file->private_data;
if (!context) {
- err("%s: no context for device", __func__);
+ printk(KERN_ERR KBUILD_MODNAME
+ "%s: no context for device\n", __func__);
return -ENODEV;
}
mutex_lock(&context->ctx_lock);
if (!context->display) {
- err("%s: display not supported by device", __func__);
+ dev_err(&context->usbdev->dev,
+ "%s: display not supported by device\n", __func__);
retval = -ENODEV;
} else if (!context->display_isopen) {
- err("%s: display is not open", __func__);
+ dev_err(&context->usbdev->dev,
+ "%s: display is not open\n", __func__);
retval = -EIO;
} else {
context->display_isopen = 0;
@@ -340,19 +348,23 @@ static int send_packet(struct imon_context *context)
retval = usb_submit_urb(context->tx_urb, GFP_KERNEL);
if (retval) {
atomic_set(&(context->tx.busy), 0);
- err("%s: error submitting urb(%d)", __func__, retval);
+ dev_err(&context->usbdev->dev,
+ "%s: error submitting urb(%d)\n", __func__, retval);
} else {
/* Wait for transmission to complete (or abort) */
mutex_unlock(&context->ctx_lock);
retval = wait_for_completion_interruptible(
&context->tx.finished);
if (retval)
- err("%s: task interrupted", __func__);
+ dev_err(&context->usbdev->dev,
+ "%s: task interrupted\n", __func__);
mutex_lock(&context->ctx_lock);
retval = context->tx.status;
if (retval)
- err("%s: packet tx failed (%d)", __func__, retval);
+ dev_err(&context->usbdev->dev,
+ "%s: packet tx failed (%d)\n",
+ __func__, retval);
}
return retval;
@@ -383,20 +395,23 @@ static ssize_t vfd_write(struct file *file, const char __user *buf,
context = file->private_data;
if (!context) {
- err("%s: no context for device", __func__);
+ printk(KERN_ERR KBUILD_MODNAME
+ "%s: no context for device\n", __func__);
return -ENODEV;
}
mutex_lock(&context->ctx_lock);
if (!context->dev_present) {
- err("%s: no iMON device present", __func__);
+ dev_err(&context->usbdev->dev,
+ "%s: no iMON device present\n", __func__);
retval = -ENODEV;
goto exit;
}
if (n_bytes <= 0 || n_bytes > IMON_DATA_BUF_SZ - 3) {
- err("%s: invalid payload size", __func__);
+ dev_err(&context->usbdev->dev,
+ "%s: invalid payload size\n", __func__);
retval = -EINVAL;
goto exit;
}
@@ -425,8 +440,9 @@ static ssize_t vfd_write(struct file *file, const char __user *buf,
retval = send_packet(context);
if (retval) {
- err("%s: send packet failed for packet #%d",
- __func__, seq/2);
+ dev_err(&context->usbdev->dev,
+ "%s: send packet failed for packet #%d\n",
+ __func__, seq/2);
goto exit;
} else {
seq += 2;
@@ -441,7 +457,8 @@ static ssize_t vfd_write(struct file *file, const char __user *buf,
context->usb_tx_buf[7] = (unsigned char) seq;
retval = send_packet(context);
if (retval)
- err("%s: send packet failed for packet #%d",
+ dev_err(&context->usbdev->dev,
+ "%s: send packet failed for packet #%d\n",
__func__, seq/2);
}
@@ -508,7 +525,8 @@ static void ir_close(void *data)
context = (struct imon_context *)data;
if (!context) {
- err("%s: no context for device", __func__);
+ printk(KERN_ERR KBUILD_MODNAME
+ "%s: no context for device\n", __func__);
return;
}
@@ -732,7 +750,7 @@ static int imon_probe(struct usb_interface *interface,
context = kzalloc(sizeof(struct imon_context), GFP_KERNEL);
if (!context) {
- err("%s: kzalloc failed for context", __func__);
+ dev_err(dev, "%s: kzalloc failed for context\n", __func__);
alloc_status = 1;
goto alloc_status_switch;
}
@@ -797,7 +815,7 @@ static int imon_probe(struct usb_interface *interface,
/* Input endpoint is mandatory */
if (!ir_ep_found) {
- err("%s: no valid input (IR) endpoint found.", __func__);
+ dev_err(dev, "%s: no valid input (IR) endpoint found.\n", __func__);
retval = -ENODEV;
alloc_status = 2;
goto alloc_status_switch;
@@ -814,30 +832,30 @@ static int imon_probe(struct usb_interface *interface,
driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
if (!driver) {
- err("%s: kzalloc failed for lirc_driver", __func__);
+ dev_err(dev, "%s: kzalloc failed for lirc_driver\n", __func__);
alloc_status = 2;
goto alloc_status_switch;
}
rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
if (!rbuf) {
- err("%s: kmalloc failed for lirc_buffer", __func__);
+ dev_err(dev, "%s: kmalloc failed for lirc_buffer\n", __func__);
alloc_status = 3;
goto alloc_status_switch;
}
if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) {
- err("%s: lirc_buffer_init failed", __func__);
+ dev_err(dev, "%s: lirc_buffer_init failed\n", __func__);
alloc_status = 4;
goto alloc_status_switch;
}
rx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!rx_urb) {
- err("%s: usb_alloc_urb failed for IR urb", __func__);
+ dev_err(dev, "%s: usb_alloc_urb failed for IR urb\n", __func__);
alloc_status = 5;
goto alloc_status_switch;
}
tx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!tx_urb) {
- err("%s: usb_alloc_urb failed for display urb",
+ dev_err(dev, "%s: usb_alloc_urb failed for display urb\n",
__func__);
alloc_status = 6;
goto alloc_status_switch;
@@ -865,7 +883,7 @@ static int imon_probe(struct usb_interface *interface,
lirc_minor = lirc_register_driver(driver);
if (lirc_minor < 0) {
- err("%s: lirc_register_driver failed", __func__);
+ dev_err(dev, "%s: lirc_register_driver failed\n", __func__);
alloc_status = 7;
goto unlock;
} else
@@ -900,8 +918,8 @@ static int imon_probe(struct usb_interface *interface,
retval = usb_submit_urb(context->rx_urb, GFP_KERNEL);
if (retval) {
- err("%s: usb_submit_urb failed for intf0 (%d)",
- __func__, retval);
+ dev_err(dev, "%s: usb_submit_urb failed for intf0 (%d)\n",
+ __func__, retval);
mutex_unlock(&context->ctx_lock);
goto exit;
}
diff --git a/drivers/staging/media/lirc/lirc_sasem.c b/drivers/staging/media/lirc/lirc_sasem.c
index 74421043b954..352a20229ca2 100644
--- a/drivers/staging/media/lirc/lirc_sasem.c
+++ b/drivers/staging/media/lirc/lirc_sasem.c
@@ -185,7 +185,7 @@ static void deregister_from_lirc(struct sasem_context *context)
retval = lirc_unregister_driver(minor);
if (retval)
- err("%s: unable to deregister from lirc (%d)",
+ printk(KERN_ERR "%s: unable to deregister from lirc (%d)\n",
__func__, retval);
else
printk(KERN_INFO "Deregistered Sasem driver (minor:%d)\n",
@@ -210,16 +210,18 @@ static int vfd_open(struct inode *inode, struct file *file)
subminor = iminor(inode);
interface = usb_find_interface(&sasem_driver, subminor);
if (!interface) {
- err("%s: could not find interface for minor %d",
- __func__, subminor);
+ printk(KERN_ERR KBUILD_MODNAME
+ ": %s: could not find interface for minor %d\n",
+ __func__, subminor);
retval = -ENODEV;
goto exit;
}
context = usb_get_intfdata(interface);
if (!context) {
- err("%s: no context found for minor %d",
- __func__, subminor);
+ dev_err(&interface->dev,
+ "%s: no context found for minor %d\n",
+ __func__, subminor);
retval = -ENODEV;
goto exit;
}
@@ -227,12 +229,13 @@ static int vfd_open(struct inode *inode, struct file *file)
mutex_lock(&context->ctx_lock);
if (context->vfd_isopen) {
- err("%s: VFD port is already open", __func__);
+ dev_err(&interface->dev,
+ "%s: VFD port is already open", __func__);
retval = -EBUSY;
} else {
context->vfd_isopen = 1;
file->private_data = context;
- printk(KERN_INFO "VFD port opened\n");
+ dev_info(&interface->dev, "VFD port opened\n");
}
mutex_unlock(&context->ctx_lock);
@@ -253,7 +256,8 @@ static long vfd_ioctl(struct file *file, unsigned cmd, unsigned long arg)
context = (struct sasem_context *) file->private_data;
if (!context) {
- err("%s: no context for device", __func__);
+ printk(KERN_ERR KBUILD_MODNAME
+ ": %s: no context for device\n", __func__);
return -ENODEV;
}
@@ -287,14 +291,15 @@ static int vfd_close(struct inode *inode, struct file *file)
context = (struct sasem_context *) file->private_data;
if (!context) {
- err("%s: no context for device", __func__);
+ printk(KERN_ERR KBUILD_MODNAME
+ ": %s: no context for device\n", __func__);
return -ENODEV;
}
mutex_lock(&context->ctx_lock);
if (!context->vfd_isopen) {
- err("%s: VFD is not open", __func__);
+ dev_err(&context->dev->dev, "%s: VFD is not open\n", __func__);
retval = -EIO;
} else {
context->vfd_isopen = 0;
@@ -339,7 +344,8 @@ static int send_packet(struct sasem_context *context)
retval = usb_submit_urb(context->tx_urb, GFP_KERNEL);
if (retval) {
atomic_set(&(context->tx.busy), 0);
- err("%s: error submitting urb (%d)", __func__, retval);
+ dev_err(&context->dev->dev, "%s: error submitting urb (%d)\n",
+ __func__, retval);
} else {
/* Wait for transmission to complete (or abort) */
mutex_unlock(&context->ctx_lock);
@@ -348,7 +354,9 @@ static int send_packet(struct sasem_context *context)
retval = context->tx.status;
if (retval)
- err("%s: packet tx failed (%d)", __func__, retval);
+ dev_err(&context->dev->dev,
+ "%s: packet tx failed (%d)\n",
+ __func__, retval);
}
return retval;
@@ -369,20 +377,23 @@ static ssize_t vfd_write(struct file *file, const char *buf,
context = (struct sasem_context *) file->private_data;
if (!context) {
- err("%s: no context for device", __func__);
+ printk(KERN_ERR KBUILD_MODNAME
+ ": %s: no context for device\n", __func__);
return -ENODEV;
}
mutex_lock(&context->ctx_lock);
if (!context->dev_present) {
- err("%s: no Sasem device present", __func__);
+ printk(KERN_ERR KBUILD_MODNAME
+ ": %s: no Sasem device present\n", __func__);
retval = -ENODEV;
goto exit;
}
if (n_bytes <= 0 || n_bytes > SASEM_DATA_BUF_SZ) {
- err("%s: invalid payload size", __func__);
+ dev_err(&context->dev->dev, "%s: invalid payload size\n",
+ __func__);
retval = -EINVAL;
goto exit;
}
@@ -440,9 +451,9 @@ static ssize_t vfd_write(struct file *file, const char *buf,
}
retval = send_packet(context);
if (retval) {
-
- err("%s: send packet failed for packet #%d",
- __func__, i);
+ dev_err(&context->dev->dev,
+ "%s: send packet failed for packet #%d\n",
+ __func__, i);
goto exit;
}
}
@@ -492,7 +503,8 @@ static int ir_open(void *data)
mutex_lock(&context->ctx_lock);
if (context->ir_isopen) {
- err("%s: IR port is already open", __func__);
+ dev_err(&context->dev->dev, "%s: IR port is already open\n",
+ __func__);
retval = -EBUSY;
goto exit;
}
@@ -506,8 +518,9 @@ static int ir_open(void *data)
retval = usb_submit_urb(context->rx_urb, GFP_KERNEL);
if (retval)
- err("%s: usb_submit_urb failed for ir_open (%d)",
- __func__, retval);
+ dev_err(&context->dev->dev,
+ "%s: usb_submit_urb failed for ir_open (%d)\n",
+ __func__, retval);
else {
context->ir_isopen = 1;
printk(KERN_INFO "IR port opened\n");
@@ -529,7 +542,8 @@ static void ir_close(void *data)
context = (struct sasem_context *)data;
if (!context) {
- err("%s: no context for device", __func__);
+ printk(KERN_ERR KBUILD_MODNAME
+ ": %s: no context for device\n", __func__);
return;
}
@@ -687,7 +701,7 @@ static int sasem_probe(struct usb_interface *interface,
struct sasem_context *context = NULL;
int i;
- printk(KERN_INFO "%s: found Sasem device\n", __func__);
+ dev_info(&interface->dev, "%s: found Sasem device\n", __func__);
dev = usb_get_dev(interface_to_usbdev(interface));
@@ -719,8 +733,8 @@ static int sasem_probe(struct usb_interface *interface,
rx_endpoint = ep;
ir_ep_found = 1;
if (debug)
- printk(KERN_INFO "%s: found IR endpoint\n",
- __func__);
+ dev_info(&interface->dev,
+ "%s: found IR endpoint\n", __func__);
} else if (!vfd_ep_found &&
ep_dir == USB_DIR_OUT &&
@@ -729,22 +743,23 @@ static int sasem_probe(struct usb_interface *interface,
tx_endpoint = ep;
vfd_ep_found = 1;
if (debug)
- printk(KERN_INFO "%s: found VFD endpoint\n",
- __func__);
+ dev_info(&interface->dev,
+ "%s: found VFD endpoint\n", __func__);
}
}
/* Input endpoint is mandatory */
if (!ir_ep_found) {
-
- err("%s: no valid input (IR) endpoint found.", __func__);
+ dev_err(&interface->dev,
+ "%s: no valid input (IR) endpoint found.\n", __func__);
retval = -ENODEV;
goto exit;
}
if (!vfd_ep_found)
- printk(KERN_INFO "%s: no valid output (VFD) endpoint found.\n",
- __func__);
+ dev_info(&interface->dev,
+ "%s: no valid output (VFD) endpoint found.\n",
+ __func__);
/* Allocate memory */
@@ -752,38 +767,44 @@ static int sasem_probe(struct usb_interface *interface,
context = kzalloc(sizeof(struct sasem_context), GFP_KERNEL);
if (!context) {
- err("%s: kzalloc failed for context", __func__);
+ dev_err(&interface->dev,
+ "%s: kzalloc failed for context\n", __func__);
alloc_status = 1;
goto alloc_status_switch;
}
driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
if (!driver) {
- err("%s: kzalloc failed for lirc_driver", __func__);
+ dev_err(&interface->dev,
+ "%s: kzalloc failed for lirc_driver\n", __func__);
alloc_status = 2;
goto alloc_status_switch;
}
rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
if (!rbuf) {
- err("%s: kmalloc failed for lirc_buffer", __func__);
+ dev_err(&interface->dev,
+ "%s: kmalloc failed for lirc_buffer\n", __func__);
alloc_status = 3;
goto alloc_status_switch;
}
if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) {
- err("%s: lirc_buffer_init failed", __func__);
+ dev_err(&interface->dev,
+ "%s: lirc_buffer_init failed\n", __func__);
alloc_status = 4;
goto alloc_status_switch;
}
rx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!rx_urb) {
- err("%s: usb_alloc_urb failed for IR urb", __func__);
+ dev_err(&interface->dev,
+ "%s: usb_alloc_urb failed for IR urb\n", __func__);
alloc_status = 5;
goto alloc_status_switch;
}
if (vfd_ep_found) {
tx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!tx_urb) {
- err("%s: usb_alloc_urb failed for VFD urb",
- __func__);
+ dev_err(&interface->dev,
+ "%s: usb_alloc_urb failed for VFD urb",
+ __func__);
alloc_status = 6;
goto alloc_status_switch;
}
@@ -807,7 +828,8 @@ static int sasem_probe(struct usb_interface *interface,
lirc_minor = lirc_register_driver(driver);
if (lirc_minor < 0) {
- err("%s: lirc_register_driver failed", __func__);
+ dev_err(&interface->dev,
+ "%s: lirc_register_driver failed\n", __func__);
alloc_status = 7;
retval = lirc_minor;
goto unlock;
diff --git a/drivers/staging/media/lirc/lirc_ttusbir.c b/drivers/staging/media/lirc/lirc_ttusbir.c
index 7950887ff113..3bb865c02173 100644
--- a/drivers/staging/media/lirc/lirc_ttusbir.c
+++ b/drivers/staging/media/lirc/lirc_ttusbir.c
@@ -113,8 +113,9 @@ static int set_use_inc(void *data)
for (i = 0; i < num_urbs; i++) {
retval = usb_submit_urb(ttusbir->urb[i], GFP_KERNEL);
if (retval) {
- err("%s: usb_submit_urb failed on urb %d",
- __func__, i);
+ dev_err(&ttusbir->interf->dev,
+ "%s: usb_submit_urb failed on urb %d\n",
+ __func__, i);
return retval;
}
}
@@ -278,7 +279,7 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
if (ttusbir->alt_setting != -1)
DPRINTK("alt setting: %d\n", ttusbir->alt_setting);
else {
- err("Could not find alternate setting\n");
+ dev_err(&intf->dev, "Could not find alternate setting\n");
kfree(ttusbir);
return -EINVAL;
}
@@ -291,7 +292,7 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
/* Register as a LIRC driver */
if (lirc_buffer_init(&ttusbir->rbuf, sizeof(int), 256) < 0) {
- err("Could not get memory for LIRC data buffer\n");
+ dev_err(&intf->dev, "Could not get memory for LIRC data buffer\n");
usb_set_intfdata(intf, NULL);
kfree(ttusbir);
return -ENOMEM;
@@ -310,7 +311,7 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
ttusbir->driver.features = LIRC_CAN_REC_MODE2;
ttusbir->minor = lirc_register_driver(&ttusbir->driver);
if (ttusbir->minor < 0) {
- err("Error registering as LIRC driver\n");
+ dev_err(&intf->dev, "Error registering as LIRC driver\n");
usb_set_intfdata(intf, NULL);
lirc_buffer_free(&ttusbir->rbuf);
kfree(ttusbir);
@@ -321,7 +322,7 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
for (i = 0; i < num_urbs; i++) {
ttusbir->urb[i] = usb_alloc_urb(8, GFP_KERNEL);
if (!ttusbir->urb[i]) {
- err("Could not allocate memory for the URB\n");
+ dev_err(&intf->dev, "Could not allocate memory for the URB\n");
for (j = i - 1; j >= 0; j--)
kfree(ttusbir->urb[j]);
lirc_buffer_free(&ttusbir->rbuf);
diff --git a/drivers/staging/mei/TODO b/drivers/staging/mei/TODO
deleted file mode 100644
index fc266018355e..000000000000
--- a/drivers/staging/mei/TODO
+++ /dev/null
@@ -1,10 +0,0 @@
-TODO:
- - Cleanup and split the timer function
-Upon Unstaging:
- - move mei.h to include/linux/mei.h
- - Documentation/ioctl/ioctl-number.txt
- - move mei.txt under Documentation/mei/
- - move mei-amt-version.c under Documentation/mei
- - add hostprogs-y for mei-amt-version.c
- - drop mei_version.h
- - Updated MAINTAINERS
diff --git a/drivers/staging/net/Kconfig b/drivers/staging/net/Kconfig
new file mode 100644
index 000000000000..a64e56b1898a
--- /dev/null
+++ b/drivers/staging/net/Kconfig
@@ -0,0 +1,38 @@
+if NETDEVICES
+
+if WAN
+
+config PC300
+ tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)"
+ depends on HDLC && PCI && BROKEN
+ ---help---
+ This driver is broken because of struct tty_driver change.
+
+ Driver for the Cyclades-PC300 synchronous communication boards.
+
+ These boards provide synchronous serial interfaces to your
+ Linux box (interfaces currently available are RS-232/V.35, X.21 and
+ T1/E1). If you wish to support Multilink PPP, please select the
+ option later and read the file README.mlppp provided by PC300
+ package.
+
+ To compile this as a module, choose M here: the module
+ will be called pc300.
+
+ If unsure, say N.
+
+config PC300_MLPPP
+ bool "Cyclades-PC300 MLPPP support"
+ depends on PC300 && PPP_MULTILINK && PPP_SYNC_TTY && HDLC_PPP
+ help
+ Multilink PPP over the PC300 synchronous communication boards.
+
+comment "Cyclades-PC300 MLPPP support is disabled."
+ depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP)
+
+comment "Refer to the file README.mlppp, provided by PC300 package."
+ depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP)
+
+endif # WAN
+
+endif # NETDEVICES
diff --git a/drivers/staging/net/Makefile b/drivers/staging/net/Makefile
new file mode 100644
index 000000000000..0799c43d5114
--- /dev/null
+++ b/drivers/staging/net/Makefile
@@ -0,0 +1,5 @@
+pc300-y := pc300_drv.o
+pc300-$(CONFIG_PC300_MLPPP) += pc300_tty.o
+pc300-objs := $(pc300-y)
+
+obj-$(CONFIG_PC300) += pc300.o
diff --git a/drivers/staging/net/TODO b/drivers/staging/net/TODO
new file mode 100644
index 000000000000..e3446f2ad7c7
--- /dev/null
+++ b/drivers/staging/net/TODO
@@ -0,0 +1,5 @@
+PC300
+The driver is very broken and cannot work with the current TTY layer. It is
+inevitable to convert it to the new TTY API.
+
+If no one steps in to adopt the driver, it will be removed in the 3.7 release.
diff --git a/drivers/net/wan/pc300-falc-lh.h b/drivers/staging/net/pc300-falc-lh.h
index 01ed23ca76c7..01ed23ca76c7 100644
--- a/drivers/net/wan/pc300-falc-lh.h
+++ b/drivers/staging/net/pc300-falc-lh.h
diff --git a/drivers/net/wan/pc300.h b/drivers/staging/net/pc300.h
index 2e4f84f6cad4..2e4f84f6cad4 100644
--- a/drivers/net/wan/pc300.h
+++ b/drivers/staging/net/pc300.h
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/staging/net/pc300_drv.c
index cb0f8d932b0c..cb0f8d932b0c 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/staging/net/pc300_drv.c
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/staging/net/pc300_tty.c
index 4709f4228561..4709f4228561 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/staging/net/pc300_tty.c
diff --git a/drivers/staging/nvec/nvec.h b/drivers/staging/nvec/nvec.h
index a4c17b0e10cf..ba6ed8f4e8a3 100644
--- a/drivers/staging/nvec/nvec.h
+++ b/drivers/staging/nvec/nvec.h
@@ -42,7 +42,7 @@
* enum nvec_event_size - The size of an event message
* @NVEC_2BYTES: The message has one command byte and one data byte
* @NVEC_3BYTES: The message has one command byte and two data bytes
- * @NVEC_VAR_SIZE: The message has one command byte, one count byte, and as
+ * @NVEC_VAR_SIZE: The message has one command byte, one count byte, and has
* up to as many bytes as the number in the count byte. The
* maximum is 32
*
diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c
index d91751f9ffe8..34afc16bc493 100644
--- a/drivers/staging/octeon/ethernet-rx.c
+++ b/drivers/staging/octeon/ethernet-rx.c
@@ -163,7 +163,7 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
/*
* We received a packet with either an alignment error
* or a FCS error. This may be signalling that we are
- * running 10Mbps with GMXX_RXX_FRM_CTL[PRE_CHK}
+ * running 10Mbps with GMXX_RXX_FRM_CTL[PRE_CHK]
* off. If this is the case we need to parse the
* packet to determine if we can remove a non spec
* preamble and generate a correct packet.
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index 5877b2c64e2a..5631dd9f8201 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -62,7 +62,7 @@
* You can define GET_SKBUFF_QOS() to override how the skbuff output
* function determines which output queue is used. The default
* implementation always uses the base queue for the port. If, for
- * example, you wanted to use the skb->priority fieid, define
+ * example, you wanted to use the skb->priority field, define
* GET_SKBUFF_QOS as: #define GET_SKBUFF_QOS(skb) ((skb)->priority)
*/
#ifndef GET_SKBUFF_QOS
@@ -165,8 +165,8 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
#endif
/*
- * Prefetch the private data structure. It is larger that one
- * cache line.
+ * Prefetch the private data structure. It is larger than the
+ * one cache line.
*/
prefetch(priv);
@@ -291,8 +291,8 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
* See if we can put this skb in the FPA pool. Any strange
* behavior from the Linux networking stack will most likely
* be caused by a bug in the following code. If some field is
- * in use by the network stack and get carried over when a
- * buffer is reused, bad thing may happen. If in doubt and
+ * in use by the network stack and gets carried over when a
+ * buffer is reused, bad things may happen. If in doubt and
* you dont need the absolute best performance, disable the
* define REUSE_SKBUFFS_WITHOUT_FREE. The reuse of buffers has
* shown a 25% increase in performance under some loads.
diff --git a/drivers/staging/octeon/ethernet-util.h b/drivers/staging/octeon/ethernet-util.h
index 144fb99bf50c..2da5ce17ead0 100644
--- a/drivers/staging/octeon/ethernet-util.h
+++ b/drivers/staging/octeon/ethernet-util.h
@@ -38,7 +38,7 @@ static inline void *cvm_oct_get_buffer_ptr(union cvmx_buf_ptr packet_ptr)
}
/**
- * INTERFACE - convert IPD port to locgical interface
+ * INTERFACE - convert IPD port to logical interface
* @ipd_port: Port to check
*
* Returns Logical interface
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index 60cba8194de3..18f7a790f73d 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -357,7 +357,7 @@ static void cvm_oct_common_set_multicast_list(struct net_device *dev)
/* Force accept multicast packets */
control.s.mcst = 2;
else
- /* Force reject multicat packets */
+ /* Force reject multicast packets */
control.s.mcst = 1;
if (dev->flags & IFF_PROMISC)
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
index 3d9199320d86..992275c0d87c 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon.c
@@ -71,8 +71,8 @@ static int dcon_hw_init(struct dcon_priv *dcon, int is_init)
ver = dcon_read(dcon, DCON_REG_ID);
if ((ver >> 8) != 0xDC) {
- printk(KERN_ERR "olpc-dcon: DCON ID not 0xDCxx: 0x%04x "
- "instead.\n", ver);
+ printk(KERN_ERR "olpc-dcon: DCON ID not 0xDCxx: 0x%04x instead.\n",
+ ver);
rc = -ENXIO;
goto err;
}
@@ -134,10 +134,10 @@ static int dcon_bus_stabilize(struct dcon_priv *dcon, int is_powered_down)
power_up:
if (is_powered_down) {
x = 1;
- x = olpc_ec_cmd(0x26, (unsigned char *) &x, 1, NULL, 0);
+ x = olpc_ec_cmd(0x26, (unsigned char *)&x, 1, NULL, 0);
if (x) {
- printk(KERN_WARNING "olpc-dcon: unable to force dcon "
- "to power up: %d!\n", x);
+ printk(KERN_WARNING "olpc-dcon: unable to force dcon to power up: %d!\n",
+ x);
return x;
}
msleep(10); /* we'll be conservative */
@@ -150,11 +150,10 @@ power_up:
x = dcon_read(dcon, DCON_REG_ID);
}
if (x < 0) {
- printk(KERN_ERR "olpc-dcon: unable to stabilize dcon's "
- "smbus, reasserting power and praying.\n");
+ printk(KERN_ERR "olpc-dcon: unable to stabilize dcon's smbus, reasserting power and praying.\n");
BUG_ON(olpc_board_at_least(olpc_board(0xc2)));
x = 0;
- olpc_ec_cmd(0x26, (unsigned char *) &x, 1, NULL, 0);
+ olpc_ec_cmd(0x26, (unsigned char *)&x, 1, NULL, 0);
msleep(100);
is_powered_down = 1;
goto power_up; /* argh, stupid hardware.. */
@@ -220,10 +219,10 @@ static void dcon_sleep(struct dcon_priv *dcon, bool sleep)
if (sleep) {
x = 0;
- x = olpc_ec_cmd(0x26, (unsigned char *) &x, 1, NULL, 0);
+ x = olpc_ec_cmd(0x26, (unsigned char *)&x, 1, NULL, 0);
if (x)
- printk(KERN_WARNING "olpc-dcon: unable to force dcon "
- "to power down: %d!\n", x);
+ printk(KERN_WARNING "olpc-dcon: unable to force dcon to power down: %d!\n",
+ x);
else
dcon->asleep = sleep;
} else {
@@ -232,8 +231,8 @@ static void dcon_sleep(struct dcon_priv *dcon, bool sleep)
dcon->disp_mode |= MODE_BL_ENABLE;
x = dcon_bus_stabilize(dcon, 1);
if (x)
- printk(KERN_WARNING "olpc-dcon: unable to reinit dcon"
- " hardware: %d!\n", x);
+ printk(KERN_WARNING "olpc-dcon: unable to reinit dcon hardware: %d!\n",
+ x);
else
dcon->asleep = sleep;
@@ -304,7 +303,7 @@ static void dcon_source_switch(struct work_struct *work)
switch (source) {
case DCON_SOURCE_CPU:
- printk("dcon_source_switch to CPU\n");
+ printk(KERN_INFO "dcon_source_switch to CPU\n");
/* Enable the scanline interrupt bit */
if (dcon_write(dcon, DCON_REG_MODE,
dcon->disp_mode | MODE_SCAN_INT))
@@ -599,7 +598,7 @@ static int dcon_fb_notifier(struct notifier_block *self,
struct fb_event *evdata = data;
struct dcon_priv *dcon = container_of(self, struct dcon_priv,
fbevent_nb);
- int *blank = (int *) evdata->data;
+ int *blank = (int *)evdata->data;
if (((event != FB_EVENT_BLANK) && (event != FB_EVENT_CONBLANK)) ||
dcon->ignore_fb_events)
return 0;
diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
index cb6ce0cf92a0..c87fdfac4855 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
@@ -116,7 +116,7 @@ static int dcon_init_xo_1(struct dcon_priv *dcon)
cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS);
cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_STS);
- /* FIXME: Clear the posiitive status as well, just to be sure */
+ /* FIXME: Clear the positive status as well, just to be sure */
cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_POSITIVE_EDGE_STS);
cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_POSITIVE_EDGE_STS);
diff --git a/drivers/staging/omapdrm/Makefile b/drivers/staging/omapdrm/Makefile
index d9cdc120d122..1ca0e0016de4 100644
--- a/drivers/staging/omapdrm/Makefile
+++ b/drivers/staging/omapdrm/Makefile
@@ -13,6 +13,7 @@ omapdrm-y := omap_drv.o \
omap_fb.o \
omap_fbdev.o \
omap_gem.o \
+ omap_gem_dmabuf.o \
omap_dmm_tiler.o \
tcm-sita.o
diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c
index 1ecb6a73d790..9d83060e753a 100644
--- a/drivers/staging/omapdrm/omap_dmm_tiler.c
+++ b/drivers/staging/omapdrm/omap_dmm_tiler.c
@@ -347,7 +347,7 @@ struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w,
ret = tcm_reserve_2d(containers[fmt], w, h, align, &block->area);
if (ret) {
kfree(block);
- return 0;
+ return ERR_PTR(-ENOMEM);
}
/* add to allocation list */
@@ -371,7 +371,7 @@ struct tiler_block *tiler_reserve_1d(size_t size)
if (tcm_reserve_1d(containers[TILFMT_PAGE], num_pages,
&block->area)) {
kfree(block);
- return 0;
+ return ERR_PTR(-ENOMEM);
}
spin_lock(&omap_dmm->list_lock);
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c
index 620b8d54223d..0d2acca376ca 100644
--- a/drivers/staging/omapdrm/omap_drv.c
+++ b/drivers/staging/omapdrm/omap_drv.c
@@ -746,7 +746,7 @@ static const struct file_operations omapdriver_fops = {
static struct drm_driver omap_drm_driver = {
.driver_features =
- DRIVER_HAVE_IRQ | DRIVER_MODESET | DRIVER_GEM,
+ DRIVER_HAVE_IRQ | DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
.load = dev_load,
.unload = dev_unload,
.open = dev_open,
@@ -766,6 +766,10 @@ static struct drm_driver omap_drm_driver = {
.debugfs_init = omap_debugfs_init,
.debugfs_cleanup = omap_debugfs_cleanup,
#endif
+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+ .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+ .gem_prime_export = omap_gem_prime_export,
+ .gem_prime_import = omap_gem_prime_import,
.gem_init_object = omap_gem_init_object,
.gem_free_object = omap_gem_free_object,
.gem_vm_ops = &omap_gem_vm_ops,
diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h
index b7e0f0773003..f238d574da0c 100644
--- a/drivers/staging/omapdrm/omap_drv.h
+++ b/drivers/staging/omapdrm/omap_drv.h
@@ -138,6 +138,8 @@ int omap_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
int omap_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
struct drm_mode_create_dumb *args);
int omap_gem_mmap(struct file *filp, struct vm_area_struct *vma);
+int omap_gem_mmap_obj(struct drm_gem_object *obj,
+ struct vm_area_struct *vma);
int omap_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
int omap_gem_op_start(struct drm_gem_object *obj, enum omap_gem_op op);
int omap_gem_op_finish(struct drm_gem_object *obj, enum omap_gem_op op);
@@ -145,12 +147,24 @@ int omap_gem_op_sync(struct drm_gem_object *obj, enum omap_gem_op op);
int omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op,
void (*fxn)(void *arg), void *arg);
int omap_gem_roll(struct drm_gem_object *obj, uint32_t roll);
+void omap_gem_cpu_sync(struct drm_gem_object *obj, int pgoff);
+void omap_gem_dma_sync(struct drm_gem_object *obj,
+ enum dma_data_direction dir);
int omap_gem_get_paddr(struct drm_gem_object *obj,
dma_addr_t *paddr, bool remap);
int omap_gem_put_paddr(struct drm_gem_object *obj);
+int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages,
+ bool remap);
+int omap_gem_put_pages(struct drm_gem_object *obj);
+uint32_t omap_gem_flags(struct drm_gem_object *obj);
uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj);
size_t omap_gem_mmap_size(struct drm_gem_object *obj);
+struct dma_buf * omap_gem_prime_export(struct drm_device *dev,
+ struct drm_gem_object *obj, int flags);
+struct drm_gem_object * omap_gem_prime_import(struct drm_device *dev,
+ struct dma_buf *buffer);
+
static inline int align_pitch(int pitch, int width, int bpp)
{
int bytespp = (bpp + 7) / 8;
diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c
index 04b235b6724a..74260f043ab1 100644
--- a/drivers/staging/omapdrm/omap_fb.c
+++ b/drivers/staging/omapdrm/omap_fb.c
@@ -167,7 +167,7 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
}
/* Call for unpin 'a' (if not NULL), and pin 'b' (if not NULL). Although
- * buffers to unpin are just just pushed to the unpin fifo so that the
+ * buffers to unpin are just pushed to the unpin fifo so that the
* caller can defer unpin until vblank.
*
* Note if this fails (ie. something went very wrong!), all buffers are
@@ -197,8 +197,11 @@ int omap_framebuffer_replace(struct drm_framebuffer *a,
pa->paddr = 0;
}
- if (pb && !ret)
+ if (pb && !ret) {
ret = omap_gem_get_paddr(pb->bo, &pb->paddr, true);
+ if (!ret)
+ omap_gem_dma_sync(pb->bo, DMA_TO_DEVICE);
+ }
}
if (ret) {
diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c
index 921f058cc6a4..3a0d035a9e03 100644
--- a/drivers/staging/omapdrm/omap_gem.c
+++ b/drivers/staging/omapdrm/omap_gem.c
@@ -207,13 +207,27 @@ static inline bool is_shmem(struct drm_gem_object *obj)
return obj->filp != NULL;
}
+/**
+ * shmem buffers that are mapped cached can simulate coherency via using
+ * page faulting to keep track of dirty pages
+ */
+static inline bool is_cached_coherent(struct drm_gem_object *obj)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ return is_shmem(obj) &&
+ ((omap_obj->flags & OMAP_BO_CACHE_MASK) == OMAP_BO_CACHED);
+}
+
static DEFINE_SPINLOCK(sync_lock);
/** ensure backing pages are allocated */
static int omap_gem_attach_pages(struct drm_gem_object *obj)
{
+ struct drm_device *dev = obj->dev;
struct omap_gem_object *omap_obj = to_omap_bo(obj);
struct page **pages;
+ int i, npages = obj->size >> PAGE_SHIFT;
+ dma_addr_t *addrs;
WARN_ON(omap_obj->pages);
@@ -231,16 +245,18 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
* DSS, GPU, etc. are not cache coherent:
*/
if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) {
- int i, npages = obj->size >> PAGE_SHIFT;
- dma_addr_t *addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL);
+ addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL);
for (i = 0; i < npages; i++) {
- addrs[i] = dma_map_page(obj->dev->dev, pages[i],
+ addrs[i] = dma_map_page(dev->dev, pages[i],
0, PAGE_SIZE, DMA_BIDIRECTIONAL);
}
- omap_obj->addrs = addrs;
+ } else {
+ addrs = kzalloc(npages * sizeof(addrs), GFP_KERNEL);
}
+ omap_obj->addrs = addrs;
omap_obj->pages = pages;
+
return 0;
}
@@ -258,14 +274,21 @@ static void omap_gem_detach_pages(struct drm_gem_object *obj)
dma_unmap_page(obj->dev->dev, omap_obj->addrs[i],
PAGE_SIZE, DMA_BIDIRECTIONAL);
}
- kfree(omap_obj->addrs);
- omap_obj->addrs = NULL;
}
+ kfree(omap_obj->addrs);
+ omap_obj->addrs = NULL;
+
_drm_gem_put_pages(obj, omap_obj->pages, true, false);
omap_obj->pages = NULL;
}
+/* get buffer flags */
+uint32_t omap_gem_flags(struct drm_gem_object *obj)
+{
+ return to_omap_bo(obj)->flags;
+}
+
/** get mmap offset */
static uint64_t mmap_offset(struct drm_gem_object *obj)
{
@@ -330,6 +353,7 @@ static int fault_1d(struct drm_gem_object *obj,
vma->vm_start) >> PAGE_SHIFT;
if (omap_obj->pages) {
+ omap_gem_cpu_sync(obj, pgoff);
pfn = page_to_pfn(omap_obj->pages[pgoff]);
} else {
BUG_ON(!(omap_obj->flags & OMAP_BO_DMA));
@@ -504,7 +528,6 @@ fail:
/** We override mainly to fix up some of the vm mapping flags.. */
int omap_gem_mmap(struct file *filp, struct vm_area_struct *vma)
{
- struct omap_gem_object *omap_obj;
int ret;
ret = drm_gem_mmap(filp, vma);
@@ -513,8 +536,13 @@ int omap_gem_mmap(struct file *filp, struct vm_area_struct *vma)
return ret;
}
- /* after drm_gem_mmap(), it is safe to access the obj */
- omap_obj = to_omap_bo(vma->vm_private_data);
+ return omap_gem_mmap_obj(vma->vm_private_data, vma);
+}
+
+int omap_gem_mmap_obj(struct drm_gem_object *obj,
+ struct vm_area_struct *vma)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
vma->vm_flags &= ~VM_PFNMAP;
vma->vm_flags |= VM_MIXEDMAP;
@@ -524,12 +552,31 @@ int omap_gem_mmap(struct file *filp, struct vm_area_struct *vma)
} else if (omap_obj->flags & OMAP_BO_UNCACHED) {
vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags));
} else {
+ /*
+ * We do have some private objects, at least for scanout buffers
+ * on hardware without DMM/TILER. But these are allocated write-
+ * combine
+ */
+ if (WARN_ON(!obj->filp))
+ return -EINVAL;
+
+ /*
+ * Shunt off cached objs to shmem file so they have their own
+ * address_space (so unmap_mapping_range does what we want,
+ * in particular in the case of mmap'd dmabufs)
+ */
+ fput(vma->vm_file);
+ get_file(obj->filp);
+ vma->vm_pgoff = 0;
+ vma->vm_file = obj->filp;
+
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
}
- return ret;
+ return 0;
}
+
/**
* omap_gem_dumb_create - create a dumb buffer
* @drm_file: our client file
@@ -639,6 +686,48 @@ fail:
return ret;
}
+/* Sync the buffer for CPU access.. note pages should already be
+ * attached, ie. omap_gem_get_pages()
+ */
+void omap_gem_cpu_sync(struct drm_gem_object *obj, int pgoff)
+{
+ struct drm_device *dev = obj->dev;
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+
+ if (is_cached_coherent(obj) && omap_obj->addrs[pgoff]) {
+ dma_unmap_page(dev->dev, omap_obj->addrs[pgoff],
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+ omap_obj->addrs[pgoff] = 0;
+ }
+}
+
+/* sync the buffer for DMA access */
+void omap_gem_dma_sync(struct drm_gem_object *obj,
+ enum dma_data_direction dir)
+{
+ struct drm_device *dev = obj->dev;
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+
+ if (is_cached_coherent(obj)) {
+ int i, npages = obj->size >> PAGE_SHIFT;
+ struct page **pages = omap_obj->pages;
+ bool dirty = false;
+
+ for (i = 0; i < npages; i++) {
+ if (!omap_obj->addrs[i]) {
+ omap_obj->addrs[i] = dma_map_page(dev->dev, pages[i], 0,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+ dirty = true;
+ }
+ }
+
+ if (dirty) {
+ unmap_mapping_range(obj->filp->f_mapping, 0,
+ omap_gem_mmap_size(obj), 1);
+ }
+ }
+}
+
/* Get physical address for DMA.. if 'remap' is true, and the buffer is not
* already contiguous, remap it to pin in physically contiguous memory.. (ie.
* map in TILER)
@@ -703,6 +792,7 @@ int omap_gem_get_paddr(struct drm_gem_object *obj,
*paddr = omap_obj->paddr;
} else {
ret = -EINVAL;
+ goto fail;
}
fail:
@@ -764,9 +854,27 @@ static int get_pages(struct drm_gem_object *obj, struct page ***pages)
return 0;
}
-int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages)
+/* if !remap, and we don't have pages backing, then fail, rather than
+ * increasing the pin count (which we don't really do yet anyways,
+ * because we don't support swapping pages back out). And 'remap'
+ * might not be quite the right name, but I wanted to keep it working
+ * similarly to omap_gem_get_paddr(). Note though that mutex is not
+ * aquired if !remap (because this can be called in atomic ctxt),
+ * but probably omap_gem_get_paddr() should be changed to work in the
+ * same way. If !remap, a matching omap_gem_put_pages() call is not
+ * required (and should not be made).
+ */
+int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages,
+ bool remap)
{
int ret;
+ if (!remap) {
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ if (!omap_obj->pages)
+ return -ENOMEM;
+ *pages = omap_obj->pages;
+ return 0;
+ }
mutex_lock(&obj->dev->struct_mutex);
ret = get_pages(obj, pages);
mutex_unlock(&obj->dev->struct_mutex);
diff --git a/drivers/staging/omapdrm/omap_gem_dmabuf.c b/drivers/staging/omapdrm/omap_gem_dmabuf.c
new file mode 100644
index 000000000000..42728e0cc194
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_gem_dmabuf.c
@@ -0,0 +1,220 @@
+/*
+ * drivers/staging/omapdrm/omap_gem_dmabuf.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob.clark@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "omap_drv.h"
+
+#include <linux/dma-buf.h>
+
+static struct sg_table *omap_gem_map_dma_buf(
+ struct dma_buf_attachment *attachment,
+ enum dma_data_direction dir)
+{
+ struct drm_gem_object *obj = attachment->dmabuf->priv;
+ struct sg_table *sg;
+ dma_addr_t paddr;
+ int ret;
+
+ sg = kzalloc(sizeof(*sg), GFP_KERNEL);
+ if (!sg)
+ return ERR_PTR(-ENOMEM);
+
+ /* camera, etc, need physically contiguous.. but we need a
+ * better way to know this..
+ */
+ ret = omap_gem_get_paddr(obj, &paddr, true);
+ if (ret)
+ goto out;
+
+ ret = sg_alloc_table(sg, 1, GFP_KERNEL);
+ if (ret)
+ goto out;
+
+ sg_init_table(sg->sgl, 1);
+ sg_dma_len(sg->sgl) = obj->size;
+ sg_set_page(sg->sgl, pfn_to_page(PFN_DOWN(paddr)), obj->size, 0);
+ sg_dma_address(sg->sgl) = paddr;
+
+ /* this should be after _get_paddr() to ensure we have pages attached */
+ omap_gem_dma_sync(obj, dir);
+
+out:
+ if (ret)
+ return ERR_PTR(ret);
+ return sg;
+}
+
+static void omap_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
+ struct sg_table *sg, enum dma_data_direction dir)
+{
+ struct drm_gem_object *obj = attachment->dmabuf->priv;
+ omap_gem_put_paddr(obj);
+ sg_free_table(sg);
+ kfree(sg);
+}
+
+static void omap_gem_dmabuf_release(struct dma_buf *buffer)
+{
+ struct drm_gem_object *obj = buffer->priv;
+ /* release reference that was taken when dmabuf was exported
+ * in omap_gem_prime_set()..
+ */
+ drm_gem_object_unreference_unlocked(obj);
+}
+
+
+static int omap_gem_dmabuf_begin_cpu_access(struct dma_buf *buffer,
+ size_t start, size_t len, enum dma_data_direction dir)
+{
+ struct drm_gem_object *obj = buffer->priv;
+ struct page **pages;
+ if (omap_gem_flags(obj) & OMAP_BO_TILED) {
+ /* TODO we would need to pin at least part of the buffer to
+ * get de-tiled view. For now just reject it.
+ */
+ return -ENOMEM;
+ }
+ /* make sure we have the pages: */
+ return omap_gem_get_pages(obj, &pages, true);
+}
+
+static void omap_gem_dmabuf_end_cpu_access(struct dma_buf *buffer,
+ size_t start, size_t len, enum dma_data_direction dir)
+{
+ struct drm_gem_object *obj = buffer->priv;
+ omap_gem_put_pages(obj);
+}
+
+
+static void *omap_gem_dmabuf_kmap_atomic(struct dma_buf *buffer,
+ unsigned long page_num)
+{
+ struct drm_gem_object *obj = buffer->priv;
+ struct page **pages;
+ omap_gem_get_pages(obj, &pages, false);
+ omap_gem_cpu_sync(obj, page_num);
+ return kmap_atomic(pages[page_num]);
+}
+
+static void omap_gem_dmabuf_kunmap_atomic(struct dma_buf *buffer,
+ unsigned long page_num, void *addr)
+{
+ kunmap_atomic(addr);
+}
+
+static void *omap_gem_dmabuf_kmap(struct dma_buf *buffer,
+ unsigned long page_num)
+{
+ struct drm_gem_object *obj = buffer->priv;
+ struct page **pages;
+ omap_gem_get_pages(obj, &pages, false);
+ omap_gem_cpu_sync(obj, page_num);
+ return kmap(pages[page_num]);
+}
+
+static void omap_gem_dmabuf_kunmap(struct dma_buf *buffer,
+ unsigned long page_num, void *addr)
+{
+ struct drm_gem_object *obj = buffer->priv;
+ struct page **pages;
+ omap_gem_get_pages(obj, &pages, false);
+ kunmap(pages[page_num]);
+}
+
+/*
+ * TODO maybe we can split up drm_gem_mmap to avoid duplicating
+ * some here.. or at least have a drm_dmabuf_mmap helper.
+ */
+static int omap_gem_dmabuf_mmap(struct dma_buf *buffer,
+ struct vm_area_struct *vma)
+{
+ struct drm_gem_object *obj = buffer->priv;
+ int ret = 0;
+
+ if (WARN_ON(!obj->filp))
+ return -EINVAL;
+
+ /* Check for valid size. */
+ if (omap_gem_mmap_size(obj) < vma->vm_end - vma->vm_start) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ if (!obj->dev->driver->gem_vm_ops) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND;
+ vma->vm_ops = obj->dev->driver->gem_vm_ops;
+ vma->vm_private_data = obj;
+ vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
+
+ /* Take a ref for this mapping of the object, so that the fault
+ * handler can dereference the mmap offset's pointer to the object.
+ * This reference is cleaned up by the corresponding vm_close
+ * (which should happen whether the vma was created by this call, or
+ * by a vm_open due to mremap or partial unmap or whatever).
+ */
+ vma->vm_ops->open(vma);
+
+out_unlock:
+
+ return omap_gem_mmap_obj(obj, vma);
+}
+
+struct dma_buf_ops omap_dmabuf_ops = {
+ .map_dma_buf = omap_gem_map_dma_buf,
+ .unmap_dma_buf = omap_gem_unmap_dma_buf,
+ .release = omap_gem_dmabuf_release,
+ .begin_cpu_access = omap_gem_dmabuf_begin_cpu_access,
+ .end_cpu_access = omap_gem_dmabuf_end_cpu_access,
+ .kmap_atomic = omap_gem_dmabuf_kmap_atomic,
+ .kunmap_atomic = omap_gem_dmabuf_kunmap_atomic,
+ .kmap = omap_gem_dmabuf_kmap,
+ .kunmap = omap_gem_dmabuf_kunmap,
+ .mmap = omap_gem_dmabuf_mmap,
+};
+
+struct dma_buf * omap_gem_prime_export(struct drm_device *dev,
+ struct drm_gem_object *obj, int flags)
+{
+ return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, 0600);
+}
+
+struct drm_gem_object * omap_gem_prime_import(struct drm_device *dev,
+ struct dma_buf *buffer)
+{
+ struct drm_gem_object *obj;
+
+ /* is this one of own objects? */
+ if (buffer->ops == &omap_dmabuf_ops) {
+ obj = buffer->priv;
+ /* is it from our device? */
+ if (obj->dev == dev) {
+ drm_gem_object_reference(obj);
+ return obj;
+ }
+ }
+
+ /*
+ * TODO add support for importing buffers from other devices..
+ * for now we don't need this but would be nice to add eventually
+ */
+ return ERR_PTR(-EINVAL);
+}
diff --git a/drivers/staging/omapdrm/tcm-sita.c b/drivers/staging/omapdrm/tcm-sita.c
index 10d5ac3dae4b..efb609510540 100644
--- a/drivers/staging/omapdrm/tcm-sita.c
+++ b/drivers/staging/omapdrm/tcm-sita.c
@@ -200,7 +200,7 @@ static s32 sita_reserve_1d(struct tcm *tcm, u32 num_slots,
*
* @param w width
* @param h height
- * @param area pointer to the area that will be populated with the reesrved
+ * @param area pointer to the area that will be populated with the reserved
* area
*
* @return 0 on success, non-0 error value on failure.
diff --git a/drivers/staging/ozwpan/README b/drivers/staging/ozwpan/README
index bb1a69b94541..7c055ec99544 100644
--- a/drivers/staging/ozwpan/README
+++ b/drivers/staging/ozwpan/README
@@ -9,7 +9,7 @@ technology.
To operate the driver must be bound to a suitable network interface. This can
be done when the module is loaded (specifying the name of the network interface
-as a paramter - e.g. 'insmod ozwpan g_net_dev=go0') or can be bound after
+as a parameter - e.g. 'insmod ozwpan g_net_dev=go0') or can be bound after
loading using an ioctl call. See the ozappif.h file and the ioctls
OZ_IOCTL_ADD_BINDING and OZ_IOCTL_REMOVE_BINDING.
diff --git a/drivers/staging/ozwpan/ozappif.h b/drivers/staging/ozwpan/ozappif.h
index af0273293872..1b59b0748c6b 100644
--- a/drivers/staging/ozwpan/ozappif.h
+++ b/drivers/staging/ozwpan/ozappif.h
@@ -11,13 +11,13 @@
#define OZ_IOCTL_MAGIC 0xf4
struct oz_mac_addr {
- unsigned char a[6];
+ __u8 a[6];
};
#define OZ_MAX_PDS 8
struct oz_pd_list {
- int count;
+ __u32 count;
struct oz_mac_addr addr[OZ_MAX_PDS];
};
@@ -27,18 +27,10 @@ struct oz_binding_info {
char name[OZ_MAX_BINDING_LEN];
};
-struct oz_test {
- int action;
-};
-
#define OZ_IOCTL_GET_PD_LIST _IOR(OZ_IOCTL_MAGIC, 0, struct oz_pd_list)
#define OZ_IOCTL_SET_ACTIVE_PD _IOW(OZ_IOCTL_MAGIC, 1, struct oz_mac_addr)
#define OZ_IOCTL_GET_ACTIVE_PD _IOR(OZ_IOCTL_MAGIC, 2, struct oz_mac_addr)
-#define OZ_IOCTL_CLEAR_EVENTS _IO(OZ_IOCTL_MAGIC, 3)
-#define OZ_IOCTL_GET_EVENTS _IOR(OZ_IOCTL_MAGIC, 4, struct oz_evtlist)
#define OZ_IOCTL_ADD_BINDING _IOW(OZ_IOCTL_MAGIC, 5, struct oz_binding_info)
-#define OZ_IOCTL_TEST _IOWR(OZ_IOCTL_MAGIC, 6, struct oz_test)
-#define OZ_IOCTL_SET_EVENT_MASK _IOW(OZ_IOCTL_MAGIC, 7, unsigned long)
#define OZ_IOCTL_REMOVE_BINDING _IOW(OZ_IOCTL_MAGIC, 8, struct oz_binding_info)
#define OZ_IOCTL_MAX 9
diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c
index 1c380d687963..27325f74ecdc 100644
--- a/drivers/staging/ozwpan/ozcdev.c
+++ b/drivers/staging/ozwpan/ozcdev.c
@@ -41,9 +41,6 @@ struct oz_serial_ctx {
};
/*------------------------------------------------------------------------------
*/
-int g_taction;
-/*------------------------------------------------------------------------------
- */
static struct oz_cdev g_cdev;
/*------------------------------------------------------------------------------
* Context: process and softirq
@@ -276,20 +273,6 @@ long oz_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -EFAULT;
}
break;
-#ifdef WANT_EVENT_TRACE
- case OZ_IOCTL_CLEAR_EVENTS:
- oz_events_clear();
- break;
- case OZ_IOCTL_GET_EVENTS:
- rc = oz_events_copy((void __user *)arg);
- break;
- case OZ_IOCTL_SET_EVENT_MASK:
- if (copy_from_user(&g_evt_mask, (void __user *)arg,
- sizeof(unsigned long))) {
- return -EFAULT;
- }
- break;
-#endif /* WANT_EVENT_TRACE */
case OZ_IOCTL_ADD_BINDING:
case OZ_IOCTL_REMOVE_BINDING: {
struct oz_binding_info b;
diff --git a/drivers/staging/ozwpan/ozevent.c b/drivers/staging/ozwpan/ozevent.c
index 73703d3e96bd..7f66b4f19b01 100644
--- a/drivers/staging/ozwpan/ozevent.c
+++ b/drivers/staging/ozwpan/ozevent.c
@@ -5,29 +5,46 @@
*/
#include "ozconfig.h"
#ifdef WANT_EVENT_TRACE
+#include <linux/module.h>
+#include <linux/debugfs.h>
#include <linux/jiffies.h>
#include <linux/uaccess.h>
#include "oztrace.h"
#include "ozevent.h"
+#include "ozappif.h"
/*------------------------------------------------------------------------------
+ * Although the event mask is logically part of the oz_evtdev structure, it is
+ * needed outside of this file so define it seperately to avoid the need to
+ * export definition of struct oz_evtdev.
*/
-unsigned long g_evt_mask = 0xffffffff;
+u32 g_evt_mask;
/*------------------------------------------------------------------------------
*/
#define OZ_MAX_EVTS 2048 /* Must be power of 2 */
-DEFINE_SPINLOCK(g_eventlock);
-static int g_evt_in;
-static int g_evt_out;
-static int g_missed_events;
-static struct oz_event g_events[OZ_MAX_EVTS];
+struct oz_evtdev {
+ struct dentry *root_dir;
+ int evt_in;
+ int evt_out;
+ int missed_events;
+ int present;
+ atomic_t users;
+ spinlock_t lock;
+ struct oz_event evts[OZ_MAX_EVTS];
+};
+
+static struct oz_evtdev g_evtdev;
+
/*------------------------------------------------------------------------------
* Context: process
*/
void oz_event_init(void)
{
+ /* Because g_evtdev is static external all fields initally zero so no
+ * need to reinitialised those.
+ */
oz_trace("Event tracing initialized\n");
- g_evt_in = g_evt_out = 0;
- g_missed_events = 0;
+ spin_lock_init(&g_evtdev.lock);
+ atomic_set(&g_evtdev.users, 0);
}
/*------------------------------------------------------------------------------
* Context: process
@@ -43,74 +60,136 @@ void oz_event_log2(u8 evt, u8 ctx1, u16 ctx2, void *ctx3, unsigned ctx4)
{
unsigned long irqstate;
int ix;
- spin_lock_irqsave(&g_eventlock, irqstate);
- ix = (g_evt_in + 1) & (OZ_MAX_EVTS - 1);
- if (ix != g_evt_out) {
- struct oz_event *e = &g_events[g_evt_in];
+ spin_lock_irqsave(&g_evtdev.lock, irqstate);
+ ix = (g_evtdev.evt_in + 1) & (OZ_MAX_EVTS - 1);
+ if (ix != g_evtdev.evt_out) {
+ struct oz_event *e = &g_evtdev.evts[g_evtdev.evt_in];
e->jiffies = jiffies;
e->evt = evt;
e->ctx1 = ctx1;
e->ctx2 = ctx2;
- e->ctx3 = ctx3;
+ e->ctx3 = (__u32)(unsigned long)ctx3;
e->ctx4 = ctx4;
- g_evt_in = ix;
+ g_evtdev.evt_in = ix;
} else {
- g_missed_events++;
+ g_evtdev.missed_events++;
}
- spin_unlock_irqrestore(&g_eventlock, irqstate);
+ spin_unlock_irqrestore(&g_evtdev.lock, irqstate);
}
/*------------------------------------------------------------------------------
* Context: process
*/
-int oz_events_copy(struct oz_evtlist __user *lst)
+static void oz_events_clear(struct oz_evtdev *dev)
{
- int first;
- int ix;
- struct hdr {
- int count;
- int missed;
- } hdr;
- ix = g_evt_out;
- hdr.count = g_evt_in - ix;
- if (hdr.count < 0)
- hdr.count += OZ_MAX_EVTS;
- if (hdr.count > OZ_EVT_LIST_SZ)
- hdr.count = OZ_EVT_LIST_SZ;
- hdr.missed = g_missed_events;
- g_missed_events = 0;
- if (copy_to_user((void __user *)lst, &hdr, sizeof(hdr)))
- return -EFAULT;
- first = OZ_MAX_EVTS - ix;
- if (first > hdr.count)
- first = hdr.count;
- if (first) {
- int sz = first*sizeof(struct oz_event);
- void __user *p = (void __user *)lst->evts;
- if (copy_to_user(p, &g_events[ix], sz))
- return -EFAULT;
- if (hdr.count > first) {
- p = (void __user *)&lst->evts[first];
- sz = (hdr.count-first)*sizeof(struct oz_event);
- if (copy_to_user(p, g_events, sz))
- return -EFAULT;
- }
+ unsigned long irqstate;
+ oz_trace("Clearing events\n");
+ spin_lock_irqsave(&dev->lock, irqstate);
+ dev->evt_in = dev->evt_out = 0;
+ dev->missed_events = 0;
+ spin_unlock_irqrestore(&dev->lock, irqstate);
+}
+#ifdef CONFIG_DEBUG_FS
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+int oz_events_open(struct inode *inode, struct file *filp)
+{
+ oz_trace("oz_evt_open()\n");
+ oz_trace("Open flags: 0x%x\n", filp->f_flags);
+ if (atomic_add_return(1, &g_evtdev.users) == 1) {
+ oz_events_clear(&g_evtdev);
+ return nonseekable_open(inode, filp);
+ } else {
+ atomic_dec(&g_evtdev.users);
+ return -EBUSY;
}
- ix += hdr.count;
- if (ix >= OZ_MAX_EVTS)
- ix -= OZ_MAX_EVTS;
- g_evt_out = ix;
+}
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+int oz_events_release(struct inode *inode, struct file *filp)
+{
+ oz_events_clear(&g_evtdev);
+ atomic_dec(&g_evtdev.users);
+ g_evt_mask = 0;
+ oz_trace("oz_evt_release()\n");
return 0;
}
/*------------------------------------------------------------------------------
* Context: process
*/
-void oz_events_clear(void)
+ssize_t oz_events_read(struct file *filp, char __user *buf, size_t count,
+ loff_t *fpos)
{
- unsigned long irqstate;
- spin_lock_irqsave(&g_eventlock, irqstate);
- g_evt_in = g_evt_out = 0;
- g_missed_events = 0;
- spin_unlock_irqrestore(&g_eventlock, irqstate);
+ struct oz_evtdev *dev = &g_evtdev;
+ int rc = 0;
+ int nb_evts = count / sizeof(struct oz_event);
+ int n;
+ int sz;
+
+ n = dev->evt_in - dev->evt_out;
+ if (n < 0)
+ n += OZ_MAX_EVTS;
+ if (nb_evts > n)
+ nb_evts = n;
+ if (nb_evts == 0)
+ goto out;
+ n = OZ_MAX_EVTS - dev->evt_out;
+ if (n > nb_evts)
+ n = nb_evts;
+ sz = n * sizeof(struct oz_event);
+ if (copy_to_user(buf, &dev->evts[dev->evt_out], sz)) {
+ rc = -EFAULT;
+ goto out;
+ }
+ if (n == nb_evts)
+ goto out2;
+ n = nb_evts - n;
+ if (copy_to_user(buf + sz, dev->evts, n * sizeof(struct oz_event))) {
+ rc = -EFAULT;
+ goto out;
+ }
+out2:
+ dev->evt_out = (dev->evt_out + nb_evts) & (OZ_MAX_EVTS - 1);
+ rc = nb_evts * sizeof(struct oz_event);
+out:
+ return rc;
}
-#endif /* WANT_EVENT_TRACE */
+/*------------------------------------------------------------------------------
+ */
+const struct file_operations oz_events_fops = {
+ .owner = THIS_MODULE,
+ .open = oz_events_open,
+ .release = oz_events_release,
+ .read = oz_events_read,
+};
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+void oz_debugfs_init(void)
+{
+ struct dentry *parent;
+ parent = debugfs_create_dir("ozwpan", NULL);
+ if (parent == NULL) {
+ oz_trace("Failed to create debugfs directory ozmo\n");
+ return;
+ } else {
+ g_evtdev.root_dir = parent;
+ if (debugfs_create_file("events", S_IRUSR, parent, NULL,
+ &oz_events_fops) == NULL)
+ oz_trace("Failed to create file ozmo/events\n");
+ if (debugfs_create_x32("event_mask", S_IRUSR | S_IWUSR, parent,
+ &g_evt_mask) == NULL)
+ oz_trace("Failed to create file ozmo/event_mask\n");
+ }
+}
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+void oz_debugfs_remove(void)
+{
+ debugfs_remove_recursive(g_evtdev.root_dir);
+}
+#endif /* CONFIG_DEBUG_FS */
+#endif /* WANT_EVENT_TRACE */
diff --git a/drivers/staging/ozwpan/ozevent.h b/drivers/staging/ozwpan/ozevent.h
index f033d014c6f3..32f6f9859c41 100644
--- a/drivers/staging/ozwpan/ozevent.h
+++ b/drivers/staging/ozwpan/ozevent.h
@@ -9,23 +9,24 @@
#include "ozeventdef.h"
#ifdef WANT_EVENT_TRACE
-extern unsigned long g_evt_mask;
+extern u32 g_evt_mask;
void oz_event_init(void);
void oz_event_term(void);
void oz_event_log2(u8 evt, u8 ctx1, u16 ctx2, void *ctx3, unsigned ctx4);
+void oz_debugfs_init(void);
+void oz_debugfs_remove(void);
#define oz_event_log(__evt, __ctx1, __ctx2, __ctx3, __ctx4) \
do { \
if ((1<<(__evt)) & g_evt_mask) \
oz_event_log2(__evt, __ctx1, __ctx2, __ctx3, __ctx4); \
} while (0)
-int oz_events_copy(struct oz_evtlist __user *lst);
-void oz_events_clear(void);
+
#else
#define oz_event_init()
#define oz_event_term()
#define oz_event_log(__evt, __ctx1, __ctx2, __ctx3, __ctx4)
-#define oz_events_copy(__lst)
-#define oz_events_clear()
+#define oz_debugfs_init()
+#define oz_debugfs_remove()
#endif /* WANT_EVENT_TRACE */
#endif /* _OZEVENT_H */
diff --git a/drivers/staging/ozwpan/ozeventdef.h b/drivers/staging/ozwpan/ozeventdef.h
index a880288bab11..4b938981671a 100644
--- a/drivers/staging/ozwpan/ozeventdef.h
+++ b/drivers/staging/ozwpan/ozeventdef.h
@@ -29,19 +29,12 @@
#define OZ_EVT_DEBUG 20
struct oz_event {
- unsigned long jiffies;
- unsigned char evt;
- unsigned char ctx1;
- unsigned short ctx2;
- void *ctx3;
- unsigned ctx4;
-};
-
-#define OZ_EVT_LIST_SZ 64
-struct oz_evtlist {
- int count;
- int missed;
- struct oz_event evts[OZ_EVT_LIST_SZ];
+ __u32 jiffies;
+ __u8 evt;
+ __u8 ctx1;
+ __u16 ctx2;
+ __u32 ctx3;
+ __u32 ctx4;
};
#endif /* _OZEVENTDEF_H */
diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c
index 750b14eb505e..251f07c39a6b 100644
--- a/drivers/staging/ozwpan/ozhcd.c
+++ b/drivers/staging/ozwpan/ozhcd.c
@@ -1416,7 +1416,7 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
oz_trace("USB_REQ_SET_CONFIGURATION - req\n");
break;
case USB_REQ_GET_CONFIGURATION:
- /* We short curcuit this case and reply directly since
+ /* We short circuit this case and reply directly since
* we have the selected configuration number cached.
*/
oz_event_log(OZ_EVT_CTRL_LOCAL, setup->bRequest, 0, 0,
@@ -1432,7 +1432,7 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
}
break;
case USB_REQ_GET_INTERFACE:
- /* We short curcuit this case and reply directly since
+ /* We short circuit this case and reply directly since
* we have the selected interface alternative cached.
*/
oz_event_log(OZ_EVT_CTRL_LOCAL, setup->bRequest, 0, 0,
@@ -1463,7 +1463,7 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
rc = -ENOMEM;
} else {
/* Note: we are queuing the request after we have
- * submitted it to be tranmitted. If the request were
+ * submitted it to be transmitted. If the request were
* to complete before we queued it then it would not
* be found in the queue. It seems impossible for
* this to happen but if it did the request would
diff --git a/drivers/staging/ozwpan/ozmain.c b/drivers/staging/ozwpan/ozmain.c
index aaf2ccc0bcfb..7579645d642a 100644
--- a/drivers/staging/ozwpan/ozmain.c
+++ b/drivers/staging/ozwpan/ozmain.c
@@ -33,6 +33,9 @@ static int __init ozwpan_init(void)
oz_protocol_init(g_net_dev);
oz_app_enable(OZ_APPID_USB, 1);
oz_apps_init();
+#ifdef CONFIG_DEBUG_FS
+ oz_debugfs_init();
+#endif
return 0;
}
/*------------------------------------------------------------------------------
@@ -44,6 +47,9 @@ static void __exit ozwpan_exit(void)
oz_apps_term();
oz_cdev_deregister();
oz_event_term();
+#ifdef CONFIG_DEBUG_FS
+ oz_debugfs_remove();
+#endif
}
/*------------------------------------------------------------------------------
*/
@@ -53,6 +59,6 @@ module_exit(ozwpan_exit);
MODULE_AUTHOR("Chris Kelly");
MODULE_DESCRIPTION("Ozmo Devices USB over WiFi hcd driver");
-MODULE_VERSION("1.0.8");
+MODULE_VERSION("1.0.9");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/ozwpan/ozusbsvc.c b/drivers/staging/ozwpan/ozusbsvc.c
index 9e74f9602384..8fa7f256ad8c 100644
--- a/drivers/staging/ozwpan/ozusbsvc.c
+++ b/drivers/staging/ozwpan/ozusbsvc.c
@@ -7,7 +7,7 @@
* The implementation of this service is split into two parts the first of which
* is protocol independent and the second contains protocol specific details.
* This split is to allow alternative protocols to be defined.
- * The implemenation of this service uses ozhcd.c to implement a USB HCD.
+ * The implementation of this service uses ozhcd.c to implement a USB HCD.
* -----------------------------------------------------------------------------
*/
#include <linux/init.h>
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index 6183573f112f..7365089a33e8 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -754,7 +754,7 @@ static void lcd_backlight(int on)
if (lcd_bl_pin == PIN_NONE)
return;
- /* The backlight is activated by seting the AUTOFEED line to +5V */
+ /* The backlight is activated by setting the AUTOFEED line to +5V */
spin_lock(&pprt_lock);
bits.bl = on;
panel_set_bits();
diff --git a/drivers/staging/quatech_usb2/Kconfig b/drivers/staging/quatech_usb2/Kconfig
deleted file mode 100644
index 1494f42f3da0..000000000000
--- a/drivers/staging/quatech_usb2/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-config USB_SERIAL_QUATECH_USB2
- tristate "USB Quatech xSU2-[14]00 USB Serial Driver"
- depends on USB_SERIAL
- help
- Say Y here if you want to use a Quatech USB2.0 to serial adaptor. This
- driver supports the SSU2-100, DSU2-100, DSU2-400, QSU2-100, QSU2-400,
- ESU2-400 and ESU2-100 USB2.0 to RS232 / 485 / 422 serial adaptors.
-
- Some hardware has an incorrect product string and announces itself as
- ESU-100 (which uses the serqt driver) even though it is an ESU2-100.
- Check the label on the bottom of your device.
-
- To compile this driver as a module, choose M here: the module will be
- called quatech_usb2 .
-
diff --git a/drivers/staging/quatech_usb2/Makefile b/drivers/staging/quatech_usb2/Makefile
deleted file mode 100644
index bcd1f890d163..000000000000
--- a/drivers/staging/quatech_usb2/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2.o
diff --git a/drivers/staging/quatech_usb2/TODO b/drivers/staging/quatech_usb2/TODO
deleted file mode 100644
index 67f61dbe14ac..000000000000
--- a/drivers/staging/quatech_usb2/TODO
+++ /dev/null
@@ -1,8 +0,0 @@
-Incomplete list of things that this driver does not yet implement completely or
-at all. some of these may not be possible to implement because the hardware
-support does not exist. Others may be possible, but the magic control codes to
-make them happen are unknown, and some may just need the driver support to
-implement them writing.
-
-* Mark/Space parity is not implemented (reported back correctly)
-* IXANY flow control mode is not implemented (flag ignored completely)
diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c
deleted file mode 100644
index bb977e00cc86..000000000000
--- a/drivers/staging/quatech_usb2/quatech_usb2.c
+++ /dev/null
@@ -1,1976 +0,0 @@
-/*
- * Driver for Quatech Inc USB2.0 to serial adaptors. Largely unrelated to the
- * serqt_usb driver, based on a re-write of the vendor supplied serqt_usb2 code,
- * which is unrelated to the serqt_usb2 in the staging kernel
- */
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/module.h>
-#include <linux/serial.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-#include <linux/uaccess.h>
-
-static bool debug;
-
-/* Version Information */
-#define DRIVER_VERSION "v2.00"
-#define DRIVER_AUTHOR "Tim Gobeli, Quatech, Inc"
-#define DRIVER_DESC "Quatech USB 2.0 to Serial Driver"
-
-/* vendor and device IDs */
-#define USB_VENDOR_ID_QUATECH 0x061d /* Quatech VID */
-#define QUATECH_SSU2_100 0xC120 /* RS232 single port */
-#define QUATECH_DSU2_100 0xC140 /* RS232 dual port */
-#define QUATECH_DSU2_400 0xC150 /* RS232/422/485 dual port */
-#define QUATECH_QSU2_100 0xC160 /* RS232 four port */
-#define QUATECH_QSU2_400 0xC170 /* RS232/422/485 four port */
-#define QUATECH_ESU2_100 0xC1A0 /* RS232 eight port */
-#define QUATECH_ESU2_400 0xC180 /* RS232/422/485 eight port */
-
-/* magic numbers go here, when we find out which ones are needed */
-
-#define QU2BOXPWRON 0x8000 /* magic number to turn FPGA power on */
-#define QU2BOX232 0x40 /* RS232 mode on MEI devices */
-#define QU2BOXSPD9600 0x60 /* set speed to 9600 baud */
-#define QT2_FIFO_DEPTH 1024 /* size of hardware fifos */
-#define QT2_TX_HEADER_LENGTH 5
-/* length of the header sent to the box with each write URB */
-
-/* directions for USB transfers */
-#define USBD_TRANSFER_DIRECTION_IN 0xc0
-#define USBD_TRANSFER_DIRECTION_OUT 0x40
-
-/* special Quatech command IDs. These are pushed down the
- USB control pipe to get the box on the end to do things */
-#define QT_SET_GET_DEVICE 0xc2
-#define QT_OPEN_CLOSE_CHANNEL 0xca
-/*#define QT_GET_SET_PREBUF_TRIG_LVL 0xcc
-#define QT_SET_ATF 0xcd*/
-#define QT2_GET_SET_REGISTER 0xc0
-#define QT2_GET_SET_UART 0xc1
-#define QT2_HW_FLOW_CONTROL_MASK 0xc5
-#define QT2_SW_FLOW_CONTROL_MASK 0xc6
-#define QT2_SW_FLOW_CONTROL_DISABLE 0xc7
-#define QT2_BREAK_CONTROL 0xc8
-#define QT2_STOP_RECEIVE 0xe0
-#define QT2_FLUSH_DEVICE 0xc4
-#define QT2_GET_SET_QMCR 0xe1
-
-/* sorts of flush we can do on */
-#define QT2_FLUSH_RX 0x00
-#define QT2_FLUSH_TX 0x01
-
-/* port setting constants, used to set up serial port speeds, flow
- * control and so on */
-#define QT2_SERIAL_MCR_DTR 0x01
-#define QT2_SERIAL_MCR_RTS 0x02
-#define QT2_SERIAL_MCR_LOOP 0x10
-
-#define QT2_SERIAL_MSR_CTS 0x10
-#define QT2_SERIAL_MSR_CD 0x80
-#define QT2_SERIAL_MSR_RI 0x40
-#define QT2_SERIAL_MSR_DSR 0x20
-#define QT2_SERIAL_MSR_MASK 0xf0
-
-#define QT2_SERIAL_8_DATA 0x03
-#define QT2_SERIAL_7_DATA 0x02
-#define QT2_SERIAL_6_DATA 0x01
-#define QT2_SERIAL_5_DATA 0x00
-
-#define QT2_SERIAL_ODD_PARITY 0x08
-#define QT2_SERIAL_EVEN_PARITY 0x18
-#define QT2_SERIAL_TWO_STOPB 0x04
-#define QT2_SERIAL_ONE_STOPB 0x00
-
-#define QT2_MAX_BAUD_RATE 921600
-#define QT2_MAX_BAUD_REMAINDER 4608
-
-#define QT2_SERIAL_LSR_OE 0x02
-#define QT2_SERIAL_LSR_PE 0x04
-#define QT2_SERIAL_LSR_FE 0x08
-#define QT2_SERIAL_LSR_BI 0x10
-
-/* value of Line Status Register when UART has completed
- * emptying data out on the line */
-#define QT2_LSR_TEMT 0x40
-
-/* register numbers on each UART, for use with qt2_box_[get|set]_register*/
-#define QT2_XMT_HOLD_REGISTER 0x00
-#define QT2_XVR_BUFFER_REGISTER 0x00
-#define QT2_FIFO_CONTROL_REGISTER 0x02
-#define QT2_LINE_CONTROL_REGISTER 0x03
-#define QT2_MODEM_CONTROL_REGISTER 0x04
-#define QT2_LINE_STATUS_REGISTER 0x05
-#define QT2_MODEM_STATUS_REGISTER 0x06
-
-/* handy macros for doing escape sequence parsing on data reads */
-#define THISCHAR ((unsigned char *)(urb->transfer_buffer))[i]
-#define NEXTCHAR ((unsigned char *)(urb->transfer_buffer))[i + 1]
-#define THIRDCHAR ((unsigned char *)(urb->transfer_buffer))[i + 2]
-#define FOURTHCHAR ((unsigned char *)(urb->transfer_buffer))[i + 3]
-#define FIFTHCHAR ((unsigned char *)(urb->transfer_buffer))[i + 4]
-
-static const struct usb_device_id quausb2_id_table[] = {
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU2_100)},
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU2_100)},
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU2_400)},
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU2_100)},
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU2_400)},
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU2_100)},
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU2_400)},
- {} /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, quausb2_id_table);
-
-/* custom structures we need go here */
-static struct usb_driver quausb2_usb_driver = {
- .name = "quatech-usb2-serial",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = quausb2_id_table,
-};
-
-/**
- * quatech2_port: Structure in which to keep all the messy stuff that this
- * driver needs alongside the usb_serial_port structure
- * @read_urb_busy: Flag indicating that port->read_urb is in use
- * @close_pending: flag indicating that this port is in the process of
- * being closed (and so no new reads / writes should be started).
- * @shadowLSR: Last received state of the line status register, holds the
- * value of the line status flags from the port
- * @shadowMSR: Last received state of the modem status register, holds
- * the value of the modem status received from the port
- * @rcv_flush: Flag indicating that a receive flush has occurred on
- * the hardware.
- * @xmit_flush: Flag indicating that a transmit flush has been processed by
- * the hardware.
- * @tx_pending_bytes: Number of bytes waiting to be sent. This total
- * includes the size (excluding header) of URBs that have been submitted but
- * have not yet been sent to to the device, and bytes that have been sent out
- * of the port but not yet reported sent by the "xmit_empty" messages (which
- * indicate the number of bytes sent each time they are received, despite the
- * misleading name).
- * - Starts at zero when port is initialised.
- * - is incremented by the size of the data to be written (no headers)
- * each time a write urb is dispatched.
- * - is decremented each time a "transmit empty" message is received
- * by the driver in the data stream.
- * @lock: Mutex to lock access to this structure when we need to ensure that
- * races don't occur to access bits of it.
- * @open_count: The number of uses of the port currently having
- * it open, i.e. the reference count.
- */
-struct quatech2_port {
- int magic;
- bool read_urb_busy;
- bool close_pending;
- __u8 shadowLSR;
- __u8 shadowMSR;
- bool rcv_flush;
- bool xmit_flush;
- int tx_pending_bytes;
- struct mutex modelock;
- int open_count;
-
- char active; /* someone has this device open */
- unsigned char *xfer_to_tty_buffer;
- wait_queue_head_t wait;
- __u8 shadowLCR; /* last LCR value received */
- __u8 shadowMCR; /* last MCR value received */
- char RxHolding;
- struct semaphore pend_xmit_sem; /* locks this structure */
- spinlock_t lock;
-};
-
-/**
- * Structure to hold device-wide internal status information
- * @param ReadBulkStopped The last bulk read attempt ended in tears
- * @param open_ports The number of serial ports currently in use on the box
- * @param current_port Pointer to the serial port structure of the port which
- * the read stream is currently directed to. Escape sequences in the read
- * stream will change this around as data arrives from different ports on the
- * box
- * @buffer_size: The max size buffer each URB can take, used to set the size of
- * the buffers allocated for writing to each port on the device (we need to
- * store this because it is known only to the endpoint, but used each time a
- * port is opened and a new buffer is allocated.
- */
-struct quatech2_dev {
- bool ReadBulkStopped;
- char open_ports;
- struct usb_serial_port *current_port;
- int buffer_size;
-};
-
-/* structure which holds line and modem status flags */
-struct qt2_status_data {
- __u8 line_status;
- __u8 modem_status;
-};
-
-/* Function prototypes */
-static int qt2_boxpoweron(struct usb_serial *serial);
-static int qt2_boxsetQMCR(struct usb_serial *serial, __u16 Uart_Number,
- __u8 QMCR_Value);
-static int port_paranoia_check(struct usb_serial_port *port,
- const char *function);
-static int serial_paranoia_check(struct usb_serial *serial,
- const char *function);
-static inline struct quatech2_port *qt2_get_port_private(struct usb_serial_port
- *port);
-static inline void qt2_set_port_private(struct usb_serial_port *port,
- struct quatech2_port *data);
-static inline struct quatech2_dev *qt2_get_dev_private(struct usb_serial
- *serial);
-static inline void qt2_set_dev_private(struct usb_serial *serial,
- struct quatech2_dev *data);
-static int qt2_openboxchannel(struct usb_serial *serial, __u16
- Uart_Number, struct qt2_status_data *pDeviceData);
-static int qt2_closeboxchannel(struct usb_serial *serial, __u16
- Uart_Number);
-static int qt2_conf_uart(struct usb_serial *serial, unsigned short Uart_Number,
- unsigned short divisor, unsigned char LCR);
-static void qt2_read_bulk_callback(struct urb *urb);
-static void qt2_write_bulk_callback(struct urb *urb);
-static void qt2_process_line_status(struct usb_serial_port *port,
- unsigned char LineStatus);
-static void qt2_process_modem_status(struct usb_serial_port *port,
- unsigned char ModemStatus);
-static void qt2_process_xmit_empty(struct usb_serial_port *port,
- unsigned char fourth_char, unsigned char fifth_char);
-static void qt2_process_port_change(struct usb_serial_port *port,
- unsigned char New_Current_Port);
-static void qt2_process_rcv_flush(struct usb_serial_port *port);
-static void qt2_process_xmit_flush(struct usb_serial_port *port);
-static void qt2_process_rx_char(struct usb_serial_port *port,
- unsigned char data);
-static int qt2_box_get_register(struct usb_serial *serial,
- unsigned char uart_number, unsigned short register_num,
- __u8 *pValue);
-static int qt2_box_set_register(struct usb_serial *serial,
- unsigned short Uart_Number, unsigned short Register_Num,
- unsigned short Value);
-static int qt2_boxsetuart(struct usb_serial *serial, unsigned short Uart_Number,
- unsigned short default_divisor, unsigned char default_LCR);
-static int qt2_boxsethw_flowctl(struct usb_serial *serial,
- unsigned int UartNumber, bool bSet);
-static int qt2_boxsetsw_flowctl(struct usb_serial *serial, __u16 UartNumber,
- unsigned char stop_char, unsigned char start_char);
-static int qt2_boxunsetsw_flowctl(struct usb_serial *serial, __u16 UartNumber);
-static int qt2_boxstoprx(struct usb_serial *serial, unsigned short uart_number,
- unsigned short stop);
-
-/* implementation functions, roughly in order of use, are here */
-static int qt2_calc_num_ports(struct usb_serial *serial)
-{
- int num_ports;
- int flag_as_400;
- switch (serial->dev->descriptor.idProduct) {
- case QUATECH_SSU2_100:
- num_ports = 1;
- break;
-
- case QUATECH_DSU2_400:
- flag_as_400 = true;
- case QUATECH_DSU2_100:
- num_ports = 2;
- break;
-
- case QUATECH_QSU2_400:
- flag_as_400 = true;
- case QUATECH_QSU2_100:
- num_ports = 4;
- break;
-
- case QUATECH_ESU2_400:
- flag_as_400 = true;
- case QUATECH_ESU2_100:
- num_ports = 8;
- break;
- default:
- num_ports = 1;
- break;
- }
- return num_ports;
-}
-
-static int qt2_attach(struct usb_serial *serial)
-{
- struct usb_serial_port *port;
- struct quatech2_port *qt2_port; /* port-specific private data pointer */
- struct quatech2_dev *qt2_dev; /* dev-specific private data pointer */
- int i;
- /* stuff for storing endpoint addresses now */
- struct usb_endpoint_descriptor *endpoint;
- struct usb_host_interface *iface_desc;
- struct usb_serial_port *port0; /* first port structure on device */
-
- /* check how many endpoints there are on the device, for
- * sanity's sake */
- dbg("%s(): Endpoints: %d bulk in, %d bulk out, %d interrupt in",
- __func__, serial->num_bulk_in,
- serial->num_bulk_out, serial->num_interrupt_in);
- if ((serial->num_bulk_in != 1) || (serial->num_bulk_out != 1)) {
- dbg("Device has wrong number of bulk endpoints!");
- return -ENODEV;
- }
- iface_desc = serial->interface->cur_altsetting;
-
- /* Set up per-device private data, storing extra data alongside
- * struct usb_serial */
- qt2_dev = kzalloc(sizeof(*qt2_dev), GFP_KERNEL);
- if (!qt2_dev) {
- dbg("%s: kmalloc for quatech2_dev failed!",
- __func__);
- return -ENOMEM;
- }
- qt2_dev->open_ports = 0; /* no ports open */
- qt2_set_dev_private(serial, qt2_dev); /* store private data */
-
- /* Now setup per port private data, which replaces all the things
- * that quatech added to standard kernel structures in their driver */
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- qt2_port = kzalloc(sizeof(*qt2_port), GFP_KERNEL);
- if (!qt2_port) {
- dbg("%s: kmalloc for quatech2_port (%d) failed!.",
- __func__, i);
- return -ENOMEM;
- }
- /* initialise stuff in the structure */
- qt2_port->open_count = 0; /* port is not open */
- spin_lock_init(&qt2_port->lock);
- mutex_init(&qt2_port->modelock);
- qt2_set_port_private(port, qt2_port);
- }
-
- /* gain access to port[0]'s structure because we want to store
- * device-level stuff in it */
- if (serial_paranoia_check(serial, __func__))
- return -ENODEV;
- port0 = serial->port[0]; /* get the first port's device structure */
-
- /* print endpoint addresses so we can check them later
- * by hand */
- for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
- endpoint = &iface_desc->endpoint[i].desc;
- if ((endpoint->bEndpointAddress & 0x80) &&
- ((endpoint->bmAttributes & 3) == 0x02)) {
- /* we found a bulk in endpoint */
- dbg("found bulk in at %#.2x",
- endpoint->bEndpointAddress);
- }
-
- if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
- ((endpoint->bmAttributes & 3) == 0x02)) {
- /* we found a bulk out endpoint */
- dbg("found bulk out at %#.2x",
- endpoint->bEndpointAddress);
- qt2_dev->buffer_size = endpoint->wMaxPacketSize;
- /* max size of URB needs recording for the device */
- }
- } /* end printing endpoint addresses */
-
- /* switch on power to the hardware */
- if (qt2_boxpoweron(serial) < 0) {
- dbg("qt2_boxpoweron() failed");
- goto startup_error;
- }
- /* set all ports to RS232 mode */
- for (i = 0; i < serial->num_ports; ++i) {
- if (qt2_boxsetQMCR(serial, i, QU2BOX232) < 0) {
- dbg("qt2_boxsetQMCR() on port %d failed",
- i);
- goto startup_error;
- }
- }
-
- return 0;
-
-startup_error:
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- qt2_port = qt2_get_port_private(port);
- kfree(qt2_port);
- qt2_set_port_private(port, NULL);
- }
- qt2_dev = qt2_get_dev_private(serial);
- kfree(qt2_dev);
- qt2_set_dev_private(serial, NULL);
-
- dbg("Exit fail %s\n", __func__);
- return -EIO;
-}
-
-static void qt2_release(struct usb_serial *serial)
-{
- struct usb_serial_port *port;
- struct quatech2_port *qt_port;
- int i;
-
- dbg("enterting %s", __func__);
-
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- if (!port)
- continue;
-
- qt_port = usb_get_serial_port_data(port);
- kfree(qt_port);
- usb_set_serial_port_data(port, NULL);
- }
-}
-/* This function is called once per serial port on the device, when
- * that port is opened by a userspace application.
- * The tty_struct and the usb_serial_port belong to this port,
- * i.e. there are multiple ones for a multi-port device.
- * However the usb_serial_port structure has a back-pointer
- * to the parent usb_serial structure which belongs to the device,
- * so we can access either the device-wide information or
- * any other port's information (because there are also forward
- * pointers) via that pointer.
- * This is most helpful if the device shares resources (e.g. end
- * points) between different ports
- */
-int qt2_open(struct tty_struct *tty, struct usb_serial_port *port)
-{
- struct usb_serial *serial; /* device structure */
- struct usb_serial_port *port0; /* first port structure on device */
- struct quatech2_port *port_extra; /* extra data for this port */
- struct quatech2_port *port0_extra; /* extra data for first port */
- struct quatech2_dev *dev_extra; /* extra data for the device */
- struct qt2_status_data ChannelData;
- unsigned short default_divisor = QU2BOXSPD9600;
- unsigned char default_LCR = QT2_SERIAL_8_DATA;
- int status;
- int result;
-
- if (port_paranoia_check(port, __func__))
- return -ENODEV;
-
- dbg("%s(): port %d", __func__, port->number);
-
- serial = port->serial; /* get the parent device structure */
- if (serial_paranoia_check(serial, __func__)) {
- dbg("usb_serial struct failed sanity check");
- return -ENODEV;
- }
- dev_extra = qt2_get_dev_private(serial);
- /* get the device private data */
- if (dev_extra == NULL) {
- dbg("device extra data pointer is null");
- return -ENODEV;
- }
- port0 = serial->port[0]; /* get the first port's device structure */
- if (port_paranoia_check(port0, __func__)) {
- dbg("port0 usb_serial_port struct failed sanity check");
- return -ENODEV;
- }
-
- port_extra = qt2_get_port_private(port);
- port0_extra = qt2_get_port_private(port0);
- if (port_extra == NULL || port0_extra == NULL) {
- dbg("failed to get private data for port or port0");
- return -ENODEV;
- }
-
- /* FIXME: are these needed? Does it even do anything useful? */
- /* get the modem and line status values from the UART */
- status = qt2_openboxchannel(serial, port->number,
- &ChannelData);
- if (status < 0) {
- dbg("qt2_openboxchannel on channel %d failed",
- port->number);
- return status;
- }
- port_extra->shadowLSR = ChannelData.line_status &
- (QT2_SERIAL_LSR_OE | QT2_SERIAL_LSR_PE |
- QT2_SERIAL_LSR_FE | QT2_SERIAL_LSR_BI);
- port_extra->shadowMSR = ChannelData.modem_status &
- (QT2_SERIAL_MSR_CTS | QT2_SERIAL_MSR_DSR |
- QT2_SERIAL_MSR_RI | QT2_SERIAL_MSR_CD);
-
-/* port_extra->fifo_empty_flag = true;*/
- dbg("qt2_openboxchannel on channel %d completed.",
- port->number);
-
- /* Set Baud rate to default and turn off flow control here */
- status = qt2_conf_uart(serial, port->number, default_divisor,
- default_LCR);
- if (status < 0) {
- dbg("qt2_conf_uart() failed on channel %d",
- port->number);
- return status;
- }
- dbg("qt2_conf_uart() completed on channel %d",
- port->number);
-
- /*
- * At this point we will need some end points to make further progress.
- * Handlily, the correct endpoint addresses have been filled out into
- * the usb_serial_port structure for us by the driver core, so we
- * already have access to them.
- * As there is only one bulk in and one bulk out end-point, these are in
- * port[0]'s structure, and the rest are uninitialised. Handily,
- * when we do a write to a port, we will use the same endpoint
- * regardless of the port, with a 5-byte header added on to
- * tell the box which port it should eventually come out of, so we only
- * need the one set of endpoints. We will have one URB per port for
- * writing, so that multiple ports can be writing at once.
- * Finally we need a bulk in URB to use for background reads from the
- * device, which will deal with uplink data from the box to host.
- */
- dbg("port0 bulk in endpoint is %#.2x", port0->bulk_in_endpointAddress);
- dbg("port0 bulk out endpoint is %#.2x",
- port0->bulk_out_endpointAddress);
-
- /* set up write_urb for bulk out transfers on this port. The USB
- * serial framework will have allocated a blank URB, buffer etc for
- * port0 when it put the endpoints there, but not for any of the other
- * ports on the device because there are no more endpoints. Thus we
- * have to allocate our own URBs for ports 1-7
- */
- if (port->write_urb == NULL) {
- dbg("port->write_urb == NULL, allocating one");
- port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->write_urb) {
- err("Allocating write URB failed");
- return -ENOMEM;
- }
- /* buffer same size as port0 */
- port->bulk_out_size = dev_extra->buffer_size;
- port->bulk_out_buffer = kmalloc(port->bulk_out_size,
- GFP_KERNEL);
- if (!port->bulk_out_buffer) {
- err("Couldn't allocate bulk_out_buffer");
- return -ENOMEM;
- }
- }
- if (serial->dev == NULL)
- dbg("serial->dev == NULL");
- dbg("port->bulk_out_size is %d", port->bulk_out_size);
-
- usb_fill_bulk_urb(port->write_urb, serial->dev,
- usb_sndbulkpipe(serial->dev,
- port0->bulk_out_endpointAddress),
- port->bulk_out_buffer,
- port->bulk_out_size,
- qt2_write_bulk_callback,
- port);
- port_extra->tx_pending_bytes = 0;
-
- if (dev_extra->open_ports == 0) {
- /* this is first port to be opened, so need the read URB
- * initialised for bulk in transfers (this is shared amongst
- * all the ports on the device) */
- usb_fill_bulk_urb(port0->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev,
- port0->bulk_in_endpointAddress),
- port0->bulk_in_buffer,
- port0->bulk_in_size,
- qt2_read_bulk_callback, serial);
- dbg("port0 bulk in URB initialised");
-
- /* submit URB, i.e. start reading from device (async) */
- dev_extra->ReadBulkStopped = false;
- port_extra->read_urb_busy = true;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
- if (result) {
- dev_err(&port->dev,
- "%s(): Error %d submitting bulk in urb",
- __func__, result);
- port_extra->read_urb_busy = false;
- dev_extra->ReadBulkStopped = true;
- }
-
- /* When the first port is opened, initialise the value of
- * current_port in dev_extra to this port, so it is set
- * to something. Once the box sends data it will send the
- * relevant escape sequences to get it to the right port anyway
- */
- dev_extra->current_port = port;
- }
-
- /* initialize our wait queues */
- init_waitqueue_head(&port_extra->wait);
- /* increment the count of openings of this port by one */
- port_extra->open_count++;
-
- /* remember to store dev_extra, port_extra and port0_extra back again at
- * end !*/
- qt2_set_port_private(port, port_extra);
- qt2_set_port_private(serial->port[0], port0_extra);
- qt2_set_dev_private(serial, dev_extra);
-
- dev_extra->open_ports++; /* one more port opened */
-
- return 0;
-}
-
-/* called when a port is closed by userspace. It won't be called, however,
- * until calls to chars_in_buffer() reveal that the port has completed
- * sending buffered data, and there is nothing else to do. Thus we don't have
- * to rely on forcing data through in this function. */
-/* Setting close_pending should keep new data from being written out,
- * once all the data in the enpoint buffers is moved out we won't get
- * any more. */
-/* BoxStopReceive would keep any more data from coming from a given
- * port, but isn't called by the vendor driver, although their comments
- * mention it. Should it be used here to stop the inbound data
- * flow?
- */
-static void qt2_close(struct usb_serial_port *port)
-{
- /* time out value for flush loops */
- unsigned long jift;
- struct quatech2_port *port_extra; /* extra data for this port */
- struct usb_serial *serial; /* device structure */
- struct quatech2_dev *dev_extra; /* extra data for the device */
- __u8 lsr_value = 0; /* value of Line Status Register */
- int status; /* result of last USB comms function */
-
- dbg("%s(): port %d", __func__, port->number);
- serial = port->serial; /* get the parent device structure */
- dev_extra = qt2_get_dev_private(serial);
- /* get the device private data */
- port_extra = qt2_get_port_private(port); /* port private data */
-
- /* we can now (and only now) stop reading data */
- port_extra->close_pending = true;
- dbg("%s(): port_extra->close_pending = true", __func__);
- /* although the USB side is now empty, the UART itself may
- * still be pushing characters out over the line, so we have to
- * wait testing the actual line status until the lines change
- * indicating that the data is done transferring. */
- /* FIXME: slow this polling down so it doesn't run the USB bus flat out
- * if it actually has to spend any time in this loop (which it normally
- * doesn't because the buffer is nearly empty) */
- jift = jiffies + (10 * HZ); /* 10 sec timeout */
- do {
- status = qt2_box_get_register(serial, port->number,
- QT2_LINE_STATUS_REGISTER, &lsr_value);
- if (status < 0) {
- dbg("%s(): qt2_box_get_register failed", __func__);
- break;
- }
- if ((lsr_value & QT2_LSR_TEMT)) {
- dbg("UART done sending");
- break;
- }
- schedule();
- } while (jiffies <= jift);
-
- status = qt2_closeboxchannel(serial, port->number);
- if (status < 0)
- dbg("%s(): port %d qt2_box_open_close_channel failed",
- __func__, port->number);
- /* to avoid leaking URBs, we should now free the write_urb for this
- * port and set the pointer to null so that next time the port is opened
- * a new URB is allocated. This avoids leaking URBs when the device is
- * removed */
- usb_free_urb(port->write_urb);
- kfree(port->bulk_out_buffer);
- port->bulk_out_buffer = NULL;
- port->bulk_out_size = 0;
-
- /* decrement the count of openings of this port by one */
- port_extra->open_count--;
- /* one less overall open as well */
- dev_extra->open_ports--;
- dbg("%s(): Exit, dev_extra->open_ports = %d", __func__,
- dev_extra->open_ports);
-}
-
-/**
- * qt2_write - write bytes from the tty layer out to the USB device.
- * @buf: The data to be written, size at least count.
- * @count: The number of bytes requested for transmission.
- * @return The number of bytes actually accepted for transmission to the device.
- */
-static int qt2_write(struct tty_struct *tty, struct usb_serial_port *port,
- const unsigned char *buf, int count)
-{
- struct usb_serial *serial; /* parent device struct */
- __u8 header_array[5]; /* header used to direct writes to the correct
- port on the device */
- struct quatech2_port *port_extra; /* extra data for this port */
- int result;
-
- serial = port->serial; /* get the parent device of the port */
- port_extra = qt2_get_port_private(port); /* port extra info */
- if (serial == NULL)
- return -ENODEV;
- dbg("%s(): port %d, requested to write %d bytes, %d already pending",
- __func__, port->number, count, port_extra->tx_pending_bytes);
-
- if (count <= 0) {
- dbg("%s(): write request of <= 0 bytes", __func__);
- return 0; /* no bytes written */
- }
-
- /* check if the write urb is already in use, i.e. data already being
- * sent to this port */
- if ((port->write_urb->status == -EINPROGRESS)) {
- /* Fifo hasn't been emptied since last write to this port */
- dbg("%s(): already writing, port->write_urb->status == "
- "-EINPROGRESS", __func__);
- /* schedule_work(&port->work); commented in vendor driver */
- return 0;
- } else if (port_extra->tx_pending_bytes >= QT2_FIFO_DEPTH) {
- /* buffer is full (==). > should not occur, but would indicate
- * that an overflow had occurred */
- dbg("%s(): port transmit buffer is full!", __func__);
- /* schedule_work(&port->work); commented in vendor driver */
- return 0;
- }
-
- /* We must fill the first 5 bytes of anything we sent with a transmit
- * header which directes the data to the correct port. The maximum
- * size we can send out in one URB is port->bulk_out_size, which caps
- * the number of bytes of real data we can send in each write. As the
- * semantics of write allow us to write less than we were give, we cap
- * the maximum we will ever write to the device as 5 bytes less than
- * one URB's worth, by reducing the value of the count argument
- * appropriately*/
- if (count > port->bulk_out_size - QT2_TX_HEADER_LENGTH) {
- count = port->bulk_out_size - QT2_TX_HEADER_LENGTH;
- dbg("%s(): write request bigger than urb, only accepting "
- "%d bytes", __func__, count);
- }
- /* we must also ensure that the FIFO at the other end can cope with the
- * URB we send it, otherwise it will have problems. As above, we can
- * restrict the write size by just shrinking count.*/
- if (count > (QT2_FIFO_DEPTH - port_extra->tx_pending_bytes)) {
- count = QT2_FIFO_DEPTH - port_extra->tx_pending_bytes;
- dbg("%s(): not enough room in buffer, only accepting %d bytes",
- __func__, count);
- }
- /* now build the header for transmission */
- header_array[0] = 0x1b;
- header_array[1] = 0x1b;
- header_array[2] = (__u8)port->number;
- header_array[3] = (__u8)count;
- header_array[4] = (__u8)count >> 8;
- /* copy header into URB */
- memcpy(port->write_urb->transfer_buffer, header_array,
- QT2_TX_HEADER_LENGTH);
- /* and actual data to write */
- memcpy(port->write_urb->transfer_buffer + 5, buf, count);
-
- dbg("%s(): first data byte to send = %#.2x", __func__, *buf);
-
- /* set up our urb */
- usb_fill_bulk_urb(port->write_urb, serial->dev,
- usb_sndbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
- port->write_urb->transfer_buffer, count + 5,
- (qt2_write_bulk_callback), port);
- /* send the data out the bulk port */
- result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
- if (result) {
- /* error couldn't submit urb */
- result = 0; /* return 0 as nothing got written */
- dbg("%s(): failed submitting write urb, error %d",
- __func__, result);
- } else {
- port_extra->tx_pending_bytes += count;
- result = count; /* return number of bytes written, i.e. count */
- dbg("%s(): submitted write urb, wrote %d bytes, "
- "total pending bytes %d",
- __func__, result, port_extra->tx_pending_bytes);
- }
- return result;
-}
-
-/* This is used by the next layer up to know how much space is available
- * in the buffer on the device. It is used on a device closure to avoid
- * calling close() until the buffer is reported to be empty.
- * The returned value must never go down by more than the number of bytes
- * written for correct behaviour further up the driver stack, i.e. if I call
- * it, then write 6 bytes, then call again I should get 6 less, or possibly
- * only 5 less if one was written in the meantime, etc. I should never get 7
- * less (or any bigger number) because I only wrote 6 bytes.
- */
-static int qt2_write_room(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- /* parent usb_serial_port pointer */
- struct quatech2_port *port_extra; /* extra data for this port */
- int room = 0;
- port_extra = qt2_get_port_private(port);
-
- if (port_extra->close_pending == true) {
- dbg("%s(): port_extra->close_pending == true", __func__);
- return -ENODEV;
- }
- /* Q: how many bytes would a write() call actually succeed in writing
- * if it happened now?
- * A: one QT2_FIFO_DEPTH, less the number of bytes waiting to be sent
- * out of the port, unless this is more than the size of the
- * write_urb output buffer less the header, which is the maximum
- * size write we can do.
-
- * Most of the implementation of this is done when writes to the device
- * are started or terminate. When we send a write to the device, we
- * reduce the free space count by the size of the dispatched write.
- * When a "transmit empty" message comes back up the USB read stream,
- * we decrement the count by the number of bytes reported sent, thus
- * keeping track of the difference between sent and received bytes.
- */
-
- room = (QT2_FIFO_DEPTH - port_extra->tx_pending_bytes);
- /* space in FIFO */
- if (room > port->bulk_out_size - QT2_TX_HEADER_LENGTH)
- room = port->bulk_out_size - QT2_TX_HEADER_LENGTH;
- /* if more than the URB can hold, then cap to that limit */
-
- dbg("%s(): port %d: write room is %d", __func__, port->number, room);
- return room;
-}
-
-static int qt2_chars_in_buffer(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- /* parent usb_serial_port pointer */
- struct quatech2_port *port_extra; /* extra data for this port */
- port_extra = qt2_get_port_private(port);
-
- dbg("%s(): port %d: chars_in_buffer = %d", __func__,
- port->number, port_extra->tx_pending_bytes);
- return port_extra->tx_pending_bytes;
-}
-
-/* called when userspace does an ioctl() on the device. Note that
- * TIOCMGET and TIOCMSET are filtered off to their own methods before they get
- * here, so we don't have to handle them.
- */
-static int qt2_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct usb_serial *serial = port->serial;
- __u8 mcr_value; /* Modem Control Register value */
- __u8 msr_value; /* Modem Status Register value */
- unsigned short prev_msr_value; /* Previous value of Modem Status
- * Register used to implement waiting for a line status change to
- * occur */
- struct quatech2_port *port_extra; /* extra data for this port */
- DECLARE_WAITQUEUE(wait, current);
- /* Declare a wait queue named "wait" */
-
- unsigned int value;
- unsigned int UartNumber;
-
- if (serial == NULL)
- return -ENODEV;
- UartNumber = tty->index - serial->minor;
- port_extra = qt2_get_port_private(port);
-
- dbg("%s(): port %d, UartNumber %d, tty =0x%p", __func__,
- port->number, UartNumber, tty);
-
- if (cmd == TIOCMBIS || cmd == TIOCMBIC) {
- if (qt2_box_get_register(port->serial, UartNumber,
- QT2_MODEM_CONTROL_REGISTER, &mcr_value) < 0)
- return -ESPIPE;
- if (copy_from_user(&value, (unsigned int *)arg,
- sizeof(value)))
- return -EFAULT;
-
- switch (cmd) {
- case TIOCMBIS:
- if (value & TIOCM_RTS)
- mcr_value |= QT2_SERIAL_MCR_RTS;
- if (value & TIOCM_DTR)
- mcr_value |= QT2_SERIAL_MCR_DTR;
- if (value & TIOCM_LOOP)
- mcr_value |= QT2_SERIAL_MCR_LOOP;
- break;
- case TIOCMBIC:
- if (value & TIOCM_RTS)
- mcr_value &= ~QT2_SERIAL_MCR_RTS;
- if (value & TIOCM_DTR)
- mcr_value &= ~QT2_SERIAL_MCR_DTR;
- if (value & TIOCM_LOOP)
- mcr_value &= ~QT2_SERIAL_MCR_LOOP;
- break;
- default:
- break;
- } /* end of local switch on cmd */
- if (qt2_box_set_register(port->serial, UartNumber,
- QT2_MODEM_CONTROL_REGISTER, mcr_value) < 0) {
- return -ESPIPE;
- } else {
- port_extra->shadowMCR = mcr_value;
- return 0;
- }
- } else if (cmd == TIOCMIWAIT) {
- dbg("%s() port %d, cmd == TIOCMIWAIT enter",
- __func__, port->number);
- prev_msr_value = port_extra->shadowMSR & QT2_SERIAL_MSR_MASK;
- barrier();
- __set_current_state(TASK_INTERRUPTIBLE);
- while (1) {
- add_wait_queue(&port_extra->wait, &wait);
- schedule();
- dbg("%s(): port %d, cmd == TIOCMIWAIT here\n",
- __func__, port->number);
- remove_wait_queue(&port_extra->wait, &wait);
- /* see if a signal woke us up */
- if (signal_pending(current))
- return -ERESTARTSYS;
- set_current_state(TASK_INTERRUPTIBLE);
- msr_value = port_extra->shadowMSR & QT2_SERIAL_MSR_MASK;
- if (msr_value == prev_msr_value) {
- __set_current_state(TASK_RUNNING);
- return -EIO; /* no change - error */
- }
- if ((arg & TIOCM_RNG &&
- ((prev_msr_value & QT2_SERIAL_MSR_RI) ==
- (msr_value & QT2_SERIAL_MSR_RI))) ||
- (arg & TIOCM_DSR &&
- ((prev_msr_value & QT2_SERIAL_MSR_DSR) ==
- (msr_value & QT2_SERIAL_MSR_DSR))) ||
- (arg & TIOCM_CD &&
- ((prev_msr_value & QT2_SERIAL_MSR_CD) ==
- (msr_value & QT2_SERIAL_MSR_CD))) ||
- (arg & TIOCM_CTS &&
- ((prev_msr_value & QT2_SERIAL_MSR_CTS) ==
- (msr_value & QT2_SERIAL_MSR_CTS)))) {
- __set_current_state(TASK_RUNNING);
- return 0;
- }
- } /* end inifinite while */
- /* FIXME: This while loop needs a way to break out if the device
- * is disconnected while a process is waiting for the MSR to
- * change, because once it's disconnected, it isn't going to
- * change state ... */
- } else {
- /* any other ioctls we don't know about come here */
- dbg("%s(): No ioctl for that one. port = %d", __func__,
- port->number);
- return -ENOIOCTLCMD;
- }
-}
-
-/* Called when the user wishes to change the port settings using the termios
- * userspace interface */
-static void qt2_set_termios(struct tty_struct *tty,
- struct usb_serial_port *port, struct ktermios *old_termios)
-{
- struct usb_serial *serial; /* parent serial device */
- int baud, divisor, remainder;
- unsigned char LCR_change_to = 0;
- int status;
- __u16 UartNumber;
-
- dbg("%s(): port %d", __func__, port->number);
-
- serial = port->serial;
-
- UartNumber = port->number;
-
- if (old_termios && !tty_termios_hw_change(old_termios, tty->termios))
- return;
-
- switch (tty->termios->c_cflag) {
- case CS5:
- LCR_change_to |= QT2_SERIAL_5_DATA;
- break;
- case CS6:
- LCR_change_to |= QT2_SERIAL_6_DATA;
- break;
- case CS7:
- LCR_change_to |= QT2_SERIAL_7_DATA;
- break;
- default:
- case CS8:
- LCR_change_to |= QT2_SERIAL_8_DATA;
- break;
- }
-
- /* Parity stuff */
- if (tty->termios->c_cflag & PARENB) {
- if (tty->termios->c_cflag & PARODD)
- LCR_change_to |= QT2_SERIAL_ODD_PARITY;
- else
- LCR_change_to |= QT2_SERIAL_EVEN_PARITY;
- }
- /* Because LCR_change_to is initialised to zero, we don't have to worry
- * about the case where PARENB is not set or clearing bits, because by
- * default all of them are cleared, turning parity off.
- * as we don't support mark/space parity, we should clear the
- * mark/space parity bit in c_cflag, so the caller can tell we have
- * ignored the request */
- tty->termios->c_cflag &= ~CMSPAR;
-
- if (tty->termios->c_cflag & CSTOPB)
- LCR_change_to |= QT2_SERIAL_TWO_STOPB;
- else
- LCR_change_to |= QT2_SERIAL_ONE_STOPB;
-
- /* Thats the LCR stuff, next we need to work out the divisor as the
- * LCR and the divisor are set together */
- baud = tty_get_baud_rate(tty);
- if (!baud) {
- /* pick a default, any default... */
- baud = 9600;
- }
- dbg("%s(): got baud = %d", __func__, baud);
-
- divisor = QT2_MAX_BAUD_RATE / baud;
- remainder = QT2_MAX_BAUD_RATE % baud;
- /* Round to nearest divisor */
- if (((remainder * 2) >= baud) && (baud != 110))
- divisor++;
- dbg("%s(): setting divisor = %d, QT2_MAX_BAUD_RATE = %d , LCR = %#.2x",
- __func__, divisor, QT2_MAX_BAUD_RATE, LCR_change_to);
-
- status = qt2_boxsetuart(serial, UartNumber, (unsigned short) divisor,
- LCR_change_to);
- if (status < 0) {
- dbg("qt2_boxsetuart() failed");
- return;
- } else {
- /* now encode the baud rate we actually set, which may be
- * different to the request */
- baud = QT2_MAX_BAUD_RATE / divisor;
- tty_encode_baud_rate(tty, baud, baud);
- }
-
- /* Now determine flow control */
- if (tty->termios->c_cflag & CRTSCTS) {
- dbg("%s(): Enabling HW flow control port %d", __func__,
- port->number);
- /* Enable RTS/CTS flow control */
- status = qt2_boxsethw_flowctl(serial, UartNumber, true);
- if (status < 0) {
- dbg("qt2_boxsethw_flowctl() failed");
- return;
- }
- } else {
- /* Disable RTS/CTS flow control */
- dbg("%s(): disabling HW flow control port %d", __func__,
- port->number);
- status = qt2_boxsethw_flowctl(serial, UartNumber, false);
- if (status < 0) {
- dbg("qt2_boxsethw_flowctl failed");
- return;
- }
- }
- /* if we are implementing XON/XOFF, set the start and stop character
- * in the device */
- if (I_IXOFF(tty) || I_IXON(tty)) {
- unsigned char stop_char = STOP_CHAR(tty);
- unsigned char start_char = START_CHAR(tty);
- status = qt2_boxsetsw_flowctl(serial, UartNumber, stop_char,
- start_char);
- if (status < 0)
- dbg("qt2_boxsetsw_flowctl (enabled) failed");
- } else {
- /* disable SW flow control */
- status = qt2_boxunsetsw_flowctl(serial, UartNumber);
- if (status < 0)
- dbg("qt2_boxunsetsw_flowctl (disabling) failed");
- }
-}
-
-static int qt2_tiocmget(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct usb_serial *serial = port->serial;
-
- __u8 mcr_value; /* Modem Control Register value */
- __u8 msr_value; /* Modem Status Register value */
- unsigned int result = 0;
- int status;
- unsigned int UartNumber;
-
- if (serial == NULL)
- return -ENODEV;
-
- dbg("%s(): port %d, tty =0x%p", __func__, port->number, tty);
- UartNumber = tty->index - serial->minor;
- dbg("UartNumber is %d", UartNumber);
-
- status = qt2_box_get_register(port->serial, UartNumber,
- QT2_MODEM_CONTROL_REGISTER, &mcr_value);
- if (status >= 0) {
- status = qt2_box_get_register(port->serial, UartNumber,
- QT2_MODEM_STATUS_REGISTER, &msr_value);
- }
- if (status >= 0) {
- result = ((mcr_value & QT2_SERIAL_MCR_DTR) ? TIOCM_DTR : 0)
- /*DTR set */
- | ((mcr_value & QT2_SERIAL_MCR_RTS) ? TIOCM_RTS : 0)
- /*RTS set */
- | ((msr_value & QT2_SERIAL_MSR_CTS) ? TIOCM_CTS : 0)
- /* CTS set */
- | ((msr_value & QT2_SERIAL_MSR_CD) ? TIOCM_CAR : 0)
- /*Carrier detect set */
- | ((msr_value & QT2_SERIAL_MSR_RI) ? TIOCM_RI : 0)
- /* Ring indicator set */
- | ((msr_value & QT2_SERIAL_MSR_DSR) ? TIOCM_DSR : 0);
- /* DSR set */
- return result;
- } else {
- return -ESPIPE;
- }
-}
-
-static int qt2_tiocmset(struct tty_struct *tty,
- unsigned int set, unsigned int clear)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct usb_serial *serial = port->serial;
- __u8 mcr_value; /* Modem Control Register value */
- int status;
- unsigned int UartNumber;
-
- if (serial == NULL)
- return -ENODEV;
-
- UartNumber = tty->index - serial->minor;
- dbg("%s(): port %d, UartNumber %d", __func__, port->number, UartNumber);
-
- status = qt2_box_get_register(port->serial, UartNumber,
- QT2_MODEM_CONTROL_REGISTER, &mcr_value);
- if (status < 0)
- return -ESPIPE;
-
- /* Turn off RTS, DTR and loopback, then only turn on what was asked
- * for */
- mcr_value &= ~(QT2_SERIAL_MCR_RTS | QT2_SERIAL_MCR_DTR |
- QT2_SERIAL_MCR_LOOP);
- if (set & TIOCM_RTS)
- mcr_value |= QT2_SERIAL_MCR_RTS;
- if (set & TIOCM_DTR)
- mcr_value |= QT2_SERIAL_MCR_DTR;
- if (set & TIOCM_LOOP)
- mcr_value |= QT2_SERIAL_MCR_LOOP;
-
- status = qt2_box_set_register(port->serial, UartNumber,
- QT2_MODEM_CONTROL_REGISTER, mcr_value);
- if (status < 0)
- return -ESPIPE;
- else
- return 0;
-}
-
-/** qt2_break - Turn BREAK on and off on the UARTs
- */
-static void qt2_break(struct tty_struct *tty, int break_state)
-{
- struct usb_serial_port *port = tty->driver_data; /* parent port */
- struct usb_serial *serial = port->serial; /* parent device */
- struct quatech2_port *port_extra; /* extra data for this port */
- __u16 break_value;
- unsigned int result;
-
- port_extra = qt2_get_port_private(port);
- if (!serial) {
- dbg("%s(): port %d: no serial object", __func__, port->number);
- return;
- }
-
- if (break_state == -1)
- break_value = 1;
- else
- break_value = 0;
- dbg("%s(): port %d, break_value %d", __func__, port->number,
- break_value);
-
- mutex_lock(&port_extra->modelock);
- if (!port_extra->open_count) {
- dbg("%s(): port not open", __func__);
- goto exit;
- }
-
- result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- QT2_BREAK_CONTROL, 0x40, break_value,
- port->number, NULL, 0, 300);
-exit:
- mutex_unlock(&port_extra->modelock);
- dbg("%s(): exit port %d", __func__, port->number);
-
-}
-/**
- * qt2_throttle: - stop reading new data from the port
- */
-static void qt2_throttle(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct usb_serial *serial = port->serial;
- struct quatech2_port *port_extra; /* extra data for this port */
- dbg("%s(): port %d", __func__, port->number);
-
- port_extra = qt2_get_port_private(port);
- if (!serial) {
- dbg("%s(): enter port %d no serial object", __func__,
- port->number);
- return;
- }
-
- mutex_lock(&port_extra->modelock); /* lock structure */
- if (!port_extra->open_count) {
- dbg("%s(): port not open", __func__);
- goto exit;
- }
- /* Send command to box to stop receiving stuff. This will stop this
- * particular UART from filling the endpoint - in the multiport case the
- * FPGA UART will handle any flow control implemented, but for the single
- * port it's handed differently and we just quit submitting urbs
- */
- if (serial->dev->descriptor.idProduct != QUATECH_SSU2_100)
- qt2_boxstoprx(serial, port->number, 1);
-
- port->throttled = 1;
-exit:
- mutex_unlock(&port_extra->modelock);
- dbg("%s(): port %d: setting port->throttled", __func__, port->number);
- return;
-}
-
-/**
- * qt2_unthrottle: - start receiving data through the port again after being
- * throttled
- */
-static void qt2_unthrottle(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct usb_serial *serial = port->serial;
- struct quatech2_port *port_extra; /* extra data for this port */
- struct usb_serial_port *port0; /* first port structure on device */
- struct quatech2_dev *dev_extra; /* extra data for the device */
-
- if (!serial) {
- dbg("%s() enter port %d no serial object!", __func__,
- port->number);
- return;
- }
- dbg("%s(): enter port %d", __func__, port->number);
- dev_extra = qt2_get_dev_private(serial);
- port_extra = qt2_get_port_private(port);
- port0 = serial->port[0]; /* get the first port's device structure */
-
- mutex_lock(&port_extra->modelock);
- if (!port_extra->open_count) {
- dbg("%s(): port %d not open", __func__, port->number);
- goto exit;
- }
-
- if (port->throttled != 0) {
- dbg("%s(): port %d: unsetting port->throttled", __func__,
- port->number);
- port->throttled = 0;
- /* Send command to box to start receiving stuff */
- if (serial->dev->descriptor.idProduct != QUATECH_SSU2_100) {
- qt2_boxstoprx(serial, port->number, 0);
- } else if (dev_extra->ReadBulkStopped == true) {
- usb_fill_bulk_urb(port0->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev,
- port0->bulk_in_endpointAddress),
- port0->bulk_in_buffer,
- port0->bulk_in_size,
- qt2_read_bulk_callback,
- serial);
- }
- }
-exit:
- mutex_unlock(&port_extra->modelock);
- dbg("%s(): exit port %d", __func__, port->number);
- return;
-}
-
-/* internal, private helper functions for the driver */
-
-/* Power up the FPGA in the box to get it working */
-static int qt2_boxpoweron(struct usb_serial *serial)
-{
- int result;
- __u8 Direcion;
- unsigned int pipe;
- Direcion = USBD_TRANSFER_DIRECTION_OUT;
- pipe = usb_rcvctrlpipe(serial->dev, 0);
- result = usb_control_msg(serial->dev, pipe, QT_SET_GET_DEVICE,
- Direcion, QU2BOXPWRON, 0x00, NULL, 0x00,
- 5000);
- return result;
-}
-
-/*
- * qt2_boxsetQMCR Issue a QT2_GET_SET_QMCR vendor-spcific request on the
- * default control pipe. If successful return the number of bytes written,
- * otherwise return a negative error number of the problem.
- */
-static int qt2_boxsetQMCR(struct usb_serial *serial, __u16 Uart_Number,
- __u8 QMCR_Value)
-{
- int result;
- __u16 PortSettings;
-
- PortSettings = (__u16)(QMCR_Value);
-
- dbg("%s(): Port = %d, PortSettings = 0x%x", __func__,
- Uart_Number, PortSettings);
-
- result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- QT2_GET_SET_QMCR, 0x40, PortSettings,
- (__u16)Uart_Number, NULL, 0, 5000);
- return result;
-}
-
-static int port_paranoia_check(struct usb_serial_port *port,
- const char *function)
-{
- if (!port) {
- dbg("%s - port == NULL", function);
- return -1;
- }
- if (!port->serial) {
- dbg("%s - port->serial == NULL\n", function);
- return -1;
- }
- return 0;
-}
-
-static int serial_paranoia_check(struct usb_serial *serial,
- const char *function)
-{
- if (!serial) {
- dbg("%s - serial == NULL\n", function);
- return -1;
- }
-
- if (!serial->type) {
- dbg("%s - serial->type == NULL!", function);
- return -1;
- }
-
- return 0;
-}
-
-static inline struct quatech2_port *qt2_get_port_private(struct usb_serial_port
- *port)
-{
- return (struct quatech2_port *)usb_get_serial_port_data(port);
-}
-
-static inline void qt2_set_port_private(struct usb_serial_port *port,
- struct quatech2_port *data)
-{
- usb_set_serial_port_data(port, (void *)data);
-}
-
-static inline struct quatech2_dev *qt2_get_dev_private(struct usb_serial
- *serial)
-{
- return (struct quatech2_dev *)usb_get_serial_data(serial);
-}
-static inline void qt2_set_dev_private(struct usb_serial *serial,
- struct quatech2_dev *data)
-{
- usb_set_serial_data(serial, (void *)data);
-}
-
-static int qt2_openboxchannel(struct usb_serial *serial, __u16
- Uart_Number, struct qt2_status_data *status)
-{
- int result;
- __u16 length;
- __u8 Direcion;
- unsigned int pipe;
- length = sizeof(struct qt2_status_data);
- Direcion = USBD_TRANSFER_DIRECTION_IN;
- pipe = usb_rcvctrlpipe(serial->dev, 0);
- result = usb_control_msg(serial->dev, pipe, QT_OPEN_CLOSE_CHANNEL,
- Direcion, 0x00, Uart_Number, status, length, 5000);
- return result;
-}
-static int qt2_closeboxchannel(struct usb_serial *serial, __u16 Uart_Number)
-{
- int result;
- __u8 direcion;
- unsigned int pipe;
- direcion = USBD_TRANSFER_DIRECTION_OUT;
- pipe = usb_sndctrlpipe(serial->dev, 0);
- result = usb_control_msg(serial->dev, pipe, QT_OPEN_CLOSE_CHANNEL,
- direcion, 0, Uart_Number, NULL, 0, 5000);
- return result;
-}
-
-/* qt2_conf_uart Issue a SET_UART vendor-spcific request on the default
- * control pipe. If successful sets baud rate divisor and LCR value
- */
-static int qt2_conf_uart(struct usb_serial *serial, unsigned short Uart_Number,
- unsigned short divisor, unsigned char LCR)
-{
- int result;
- unsigned short UartNumandLCR;
-
- UartNumandLCR = (LCR << 8) + Uart_Number;
-
- result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- QT2_GET_SET_UART, 0x40, divisor, UartNumandLCR,
- NULL, 0, 300);
- return result;
-}
-
-/** @brief Callback for asynchronous submission of read URBs on bulk in
- * endpoints
- *
- * Registered in qt2_open_port(), used to deal with incomming data
- * from the box.
- */
-static void qt2_read_bulk_callback(struct urb *urb)
-{
- /* Get the device pointer (struct usb_serial) back out of the URB */
- struct usb_serial *serial = urb->context;
- /* get the extra struct for the device */
- struct quatech2_dev *dev_extra = qt2_get_dev_private(serial);
- /* Get first port structure from the device */
- struct usb_serial_port *port0 = serial->port[0];
- /* Get the currently active port structure from serial struct */
- struct usb_serial_port *active = dev_extra->current_port;
- /* get the extra struct for port 0 */
- struct quatech2_port *port0_extra = qt2_get_port_private(port0);
- /* and for the currently active port */
- struct quatech2_port *active_extra = qt2_get_port_private(active);
- /* When we finally get to doing some tty stuff, we will need this */
- struct tty_struct *tty_st;
- unsigned int RxCount; /* the length of the data to process */
- unsigned int i; /* loop counter over the data to process */
- int result; /* return value cache variable */
- bool escapeflag; /* flag set to true if this loop iteration is
- * parsing an escape sequence, rather than
- * ordinary data */
- dbg("%s(): callback running, active port is %d", __func__,
- active->number);
-
- if (urb->status) {
- /* read didn't go well */
- dev_extra->ReadBulkStopped = true;
- dbg("%s(): nonzero bulk read status received: %d",
- __func__, urb->status);
- return;
- }
-
- /* inline port_sofrint() here */
- if (port_paranoia_check(port0, __func__) != 0) {
- dbg("%s - port_paranoia_check on port0 failed, exiting\n",
-__func__);
- return;
- }
- if (port_paranoia_check(active, __func__) != 0) {
- dbg("%s - port_paranoia_check on current_port "
- "failed, exiting", __func__);
- return;
- }
-
-/* This single callback function has to do for all the ports on
- * the device. Data being read up the USB can contain certain
- * escape sequences which are used to communicate out-of-band
- * information from the serial port in-band over the USB.
- * These escapes include sending modem and flow control line
- * status, and switching the port. The concept of a "Current Port"
- * is used, which is where data is going until a port change
- * escape seqence is received. This Current Port is kept between
- * callbacks so that when this function enters we know which the
- * currently active port is and can get to work right away without
- * the box having to send repeat escape sequences (anyway, how
- * would it know to do so?).
- */
-
- if (active_extra->close_pending == true) {
- /* We are closing , stop reading */
- dbg("%s - (active->close_pending == true", __func__);
- if (dev_extra->open_ports <= 0) {
- /* If this is the only port left open - stop the
- * bulk read */
- dev_extra->ReadBulkStopped = true;
- dbg("%s - (ReadBulkStopped == true;", __func__);
- return;
- }
- }
-
- /*
- * RxHolding is asserted by throttle, if we assert it, we're not
- * receiving any more characters and let the box handle the flow
- * control
- */
- if ((port0_extra->RxHolding == true) &&
- (serial->dev->descriptor.idProduct == QUATECH_SSU2_100)) {
- /* single port device, input is already stopped, so we don't
- * need any more input data */
- dev_extra->ReadBulkStopped = true;
- return;
- }
- /* finally, we are in a situation where we might consider the data
- * that is contained within the URB, and what to do about it.
- * This is likely to involved communicating up to the TTY layer, so
- * we will need to get hold of the tty for the port we are currently
- * dealing with */
-
- /* active is a usb_serial_port. It has a member port which is a
- * tty_port. From this we get a tty_struct pointer which is what we
- * actually wanted, and keep it on tty_st */
- tty_st = tty_port_tty_get(&active->port);
- if (!tty_st) {
- dbg("%s - bad tty pointer - exiting", __func__);
- return;
- }
- RxCount = urb->actual_length; /* grab length of data handy */
-
- if (RxCount) {
- /* skip all this if no data to process */
- for (i = 0; i < RxCount ; ++i) {
- /* Look ahead code here -works on several bytes at onc*/
- if ((i <= (RxCount - 3)) && (THISCHAR == 0x1b)
- && (NEXTCHAR == 0x1b)) {
- /* we are in an escape sequence, type
- * determined by the 3rd char */
- escapeflag = false;
- switch (THIRDCHAR) {
- case 0x00:
- /* Line status change 4th byte must
- * follow */
- if (i > (RxCount - 4)) {
- dbg("Illegal escape sequences "
- "in received data");
- break;
- }
- qt2_process_line_status(active,
- FOURTHCHAR);
- i += 3;
- escapeflag = true;
- break;
- case 0x01:
- /* Modem status status change 4th byte
- * must follow */
- if (i > (RxCount - 4)) {
- dbg("Illegal escape sequences "
- "in received data");
- break;
- }
- qt2_process_modem_status(active,
- FOURTHCHAR);
- i += 3;
- escapeflag = true;
- break;
- case 0x02:
- /* xmit hold empty 4th byte
- * must follow */
- if (i > (RxCount - 4)) {
- dbg("Illegal escape sequences "
- "in received data");
- break;
- }
- qt2_process_xmit_empty(active,
- FOURTHCHAR, FIFTHCHAR);
- i += 4;
- escapeflag = true;
- break;
- case 0x03:
- /* Port number change 4th byte
- * must follow */
- if (i > (RxCount - 4)) {
- dbg("Illegal escape sequences "
- "in received data");
- break;
- }
- /* Port change. If port open push
- * current data up to tty layer */
- if (active_extra->open_count > 0)
- tty_flip_buffer_push(tty_st);
-
- dbg("Port Change: new port = %d",
- FOURTHCHAR);
- qt2_process_port_change(active,
- FOURTHCHAR);
- i += 3;
- escapeflag = true;
- /* having changed port, the pointers for
- * the currently active port are all out
- * of date and need updating */
- active = dev_extra->current_port;
- active_extra =
- qt2_get_port_private(active);
- tty_st = tty_port_tty_get(
- &active->port);
- break;
- case 0x04:
- /* Recv flush 3rd byte must
- * follow */
- if (i > (RxCount - 3)) {
- dbg("Illegal escape sequences "
- "in received data");
- break;
- }
- qt2_process_rcv_flush(active);
- i += 2;
- escapeflag = true;
- break;
- case 0x05:
- /* xmit flush 3rd byte must follow */
- if (i > (RxCount - 3)) {
- dbg("Illegal escape sequences "
- "in received data");
- break;
- }
- qt2_process_xmit_flush(active);
- i += 2;
- escapeflag = true;
- break;
- case 0xff:
- dbg("No status sequence");
- qt2_process_rx_char(active, THISCHAR);
- qt2_process_rx_char(active, NEXTCHAR);
- i += 2;
- break;
- default:
- qt2_process_rx_char(active, THISCHAR);
- i += 1;
- break;
- } /*end switch*/
- if (escapeflag == true)
- continue;
- /* if we did an escape char, we don't need
- * to mess around pushing data through the
- * tty layer, and can go round again */
- } /*endif*/
- if (tty_st && urb->actual_length) {
- tty_buffer_request_room(tty_st, 1);
- tty_insert_flip_string(tty_st, &(
- (unsigned char *)
- (urb->transfer_buffer)
- )[i], 1);
- }
- } /*endfor*/
- tty_flip_buffer_push(tty_st);
- } /*endif*/
-
- /* at this point we have complete dealing with the data for this
- * callback. All we have to do now is to start the async read process
- * back off again. */
-
- usb_fill_bulk_urb(port0->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port0->bulk_in_endpointAddress),
- port0->bulk_in_buffer, port0->bulk_in_size,
- qt2_read_bulk_callback, serial);
- result = usb_submit_urb(port0->read_urb, GFP_ATOMIC);
- if (result) {
- dbg("%s(): failed resubmitting read urb, error %d",
- __func__, result);
- } else {
- dbg("%s() successfully resubmitted read urb", __func__);
- if (tty_st && RxCount) {
- /* if some inbound data was processed, then
- * we need to push that through the tty layer
- */
- tty_flip_buffer_push(tty_st);
- tty_schedule_flip(tty_st);
- }
- }
-
- /* cribbed from serqt_usb2 driver, but not sure which work needs
- * scheduling - port0 or currently active port? */
- /* schedule_work(&port->work); */
- dbg("%s() completed", __func__);
- return;
-}
-
-/** @brief Callback for asynchronous submission of write URBs on bulk in
- * endpoints
- *
- * Registered in qt2_write(), used to deal with outgoing data
- * to the box.
- */
-static void qt2_write_bulk_callback(struct urb *urb)
-{
- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
- struct usb_serial *serial = port->serial;
- dbg("%s(): port %d", __func__, port->number);
- if (!serial) {
- dbg("%s(): bad serial pointer, exiting", __func__);
- return;
- }
- if (urb->status) {
- dbg("%s(): nonzero write bulk status received: %d",
- __func__, urb->status);
- return;
- }
- /* FIXME What is supposed to be going on here?
- * does this actually do anything useful, and should it?
- */
- /*port_softint((void *) serial); commented in vendor driver */
- schedule_work(&port->work);
- dbg("%s(): port %d exit", __func__, port->number);
- return;
-}
-
-static void qt2_process_line_status(struct usb_serial_port *port,
- unsigned char LineStatus)
-{
- /* obtain the private structure for the port */
- struct quatech2_port *port_extra = qt2_get_port_private(port);
- port_extra->shadowLSR = LineStatus & (QT2_SERIAL_LSR_OE |
- QT2_SERIAL_LSR_PE | QT2_SERIAL_LSR_FE | QT2_SERIAL_LSR_BI);
-}
-static void qt2_process_modem_status(struct usb_serial_port *port,
- unsigned char ModemStatus)
-{
- /* obtain the private structure for the port */
- struct quatech2_port *port_extra = qt2_get_port_private(port);
- port_extra->shadowMSR = ModemStatus;
- wake_up_interruptible(&port_extra->wait);
- /* this wakes up the otherwise indefinitely waiting code for
- * the TIOCMIWAIT ioctl, so that it can notice that
- * port_extra->shadowMSR has changed and the ioctl needs to return.
- */
-}
-
-static void qt2_process_xmit_empty(struct usb_serial_port *port,
- unsigned char fourth_char, unsigned char fifth_char)
-{
- int byte_count;
- /* obtain the private structure for the port */
- struct quatech2_port *port_extra = qt2_get_port_private(port);
-
- byte_count = (int)(fifth_char * 16);
- byte_count += (int)fourth_char;
- /* byte_count indicates how many bytes the device has written out. This
- * message appears to occur regularly, and is used in the vendor driver
- * to keep track of the fill state of the port transmit buffer */
- port_extra->tx_pending_bytes -= byte_count;
- /* reduce the stored data queue length by the known number of bytes
- * sent */
- dbg("port %d: %d bytes reported sent, %d still pending", port->number,
- byte_count, port_extra->tx_pending_bytes);
-
- /*port_extra->xmit_fifo_room_bytes = FIFO_DEPTH; ???*/
-}
-
-static void qt2_process_port_change(struct usb_serial_port *port,
- unsigned char New_Current_Port)
-{
- /* obtain the parent usb serial device structure */
- struct usb_serial *serial = port->serial;
- /* obtain the private structure for the device */
- struct quatech2_dev *dev_extra = qt2_get_dev_private(serial);
- dev_extra->current_port = serial->port[New_Current_Port];
- /* what should I do with this? commented out in upstream
- * driver */
- /*schedule_work(&port->work);*/
-}
-
-static void qt2_process_rcv_flush(struct usb_serial_port *port)
-{
- /* obtain the private structure for the port */
- struct quatech2_port *port_extra = qt2_get_port_private(port);
- port_extra->rcv_flush = true;
-}
-static void qt2_process_xmit_flush(struct usb_serial_port *port)
-{
- /* obtain the private structure for the port */
- struct quatech2_port *port_extra = qt2_get_port_private(port);
- port_extra->xmit_flush = true;
-}
-
-static void qt2_process_rx_char(struct usb_serial_port *port,
- unsigned char data)
-{
- /* get the tty_struct for this port */
- struct tty_struct *tty = tty_port_tty_get(&(port->port));
- /* get the URB with the data in to push */
- struct urb *urb = port->serial->port[0]->read_urb;
-
- if (tty && urb->actual_length) {
- tty_buffer_request_room(tty, 1);
- tty_insert_flip_string(tty, &data, 1);
- /* should this be commented out here? */
- /*tty_flip_buffer_push(tty);*/
- }
-}
-
-/** @brief Retrieve the value of a register from the device
- *
- * Issues a GET_REGISTER vendor-spcific request over the USB control
- * pipe to obtain a value back from a specific register on a specific
- * UART
- * @param serial Serial device handle to access the device through
- * @param uart_number Which UART the value is wanted from
- * @param register_num Which register to read the value from
- * @param pValue Pointer to somewhere to put the retrieved value
- */
-static int qt2_box_get_register(struct usb_serial *serial,
- unsigned char uart_number, unsigned short register_num,
- __u8 *pValue)
-{
- int result;
- result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- QT2_GET_SET_REGISTER, 0xC0, register_num,
- uart_number, (void *)pValue, sizeof(*pValue), 300);
- return result;
-}
-
-/** qt2_box_set_register
- * Issue a SET_REGISTER vendor-specific request on the default control pipe
- */
-static int qt2_box_set_register(struct usb_serial *serial,
- unsigned short Uart_Number, unsigned short Register_Num,
- unsigned short Value)
-{
- int result;
- unsigned short reg_and_byte;
-
- reg_and_byte = Value;
- reg_and_byte = reg_and_byte << 8;
- reg_and_byte = reg_and_byte + Register_Num;
-
- result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- QT2_GET_SET_REGISTER, 0x40, reg_and_byte,
- Uart_Number, NULL, 0, 300);
- return result;
-}
-
-/** qt2_boxsetuart - Issue a SET_UART vendor-spcific request on the default
- * control pipe. If successful sets baud rate divisor and LCR value.
- */
-static int qt2_boxsetuart(struct usb_serial *serial, unsigned short Uart_Number,
- unsigned short default_divisor, unsigned char default_LCR)
-{
- unsigned short UartNumandLCR;
-
- UartNumandLCR = (default_LCR << 8) + Uart_Number;
-
- return usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- QT2_GET_SET_UART, 0x40, default_divisor, UartNumandLCR,
- NULL, 0, 300);
-}
-
-/** qt2_boxsethw_flowctl - Turn hardware (RTS/CTS) flow control on and off for
- * a hardware UART.
- */
-static int qt2_boxsethw_flowctl(struct usb_serial *serial,
- unsigned int UartNumber, bool bSet)
-{
- __u8 MCR_Value = 0;
- __u8 MSR_Value = 0;
- __u16 MOUT_Value = 0;
-
- if (bSet == true) {
- MCR_Value = QT2_SERIAL_MCR_RTS;
- /* flow control, box will clear RTS line to prevent remote
- * device from transmitting more chars */
- } else {
- /* no flow control to remote device */
- MCR_Value = 0;
- }
- MOUT_Value = MCR_Value << 8;
-
- if (bSet == true) {
- MSR_Value = QT2_SERIAL_MSR_CTS;
- /* flow control on, box will inhibit tx data if CTS line is
- * asserted */
- } else {
- /* Box will not inhibit tx data due to CTS line */
- MSR_Value = 0;
- }
- MOUT_Value |= MSR_Value;
- return usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- QT2_HW_FLOW_CONTROL_MASK, 0x40, MOUT_Value, UartNumber,
- NULL, 0, 300);
-}
-
-/** qt2_boxsetsw_flowctl - Turn software (XON/XOFF) flow control on for
- * a hardware UART, and set the XON and XOFF characters.
- */
-static int qt2_boxsetsw_flowctl(struct usb_serial *serial, __u16 UartNumber,
- unsigned char stop_char, unsigned char start_char)
-{
- __u16 nSWflowout;
-
- nSWflowout = start_char << 8;
- nSWflowout = (unsigned short)stop_char;
- return usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- QT2_SW_FLOW_CONTROL_MASK, 0x40, nSWflowout, UartNumber,
- NULL, 0, 300);
-}
-
-/** qt2_boxunsetsw_flowctl - Turn software (XON/XOFF) flow control off for
- * a hardware UART.
- */
-static int qt2_boxunsetsw_flowctl(struct usb_serial *serial, __u16 UartNumber)
-{
- return usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- QT2_SW_FLOW_CONTROL_DISABLE, 0x40, 0, UartNumber, NULL,
- 0, 300);
-}
-
-/**
- * qt2_boxstoprx - Start and stop reception of data by the FPGA UART in
- * response to requests from the tty layer
- * @serial: pointer to the usb_serial structure for the parent device
- * @uart_number: which UART on the device we are addressing
- * @stop: Whether to start or stop data reception. Set to 1 to stop data being
- * received, and to 0 to start it being received.
- */
-static int qt2_boxstoprx(struct usb_serial *serial, unsigned short uart_number,
- unsigned short stop)
-{
- return usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- QT2_STOP_RECEIVE, 0x40, stop, uart_number, NULL, 0, 300);
-}
-
-
-/*
- * last things in file: stuff to register this driver into the generic
- * USB serial framework.
- */
-
-static struct usb_serial_driver quatech2_device = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "quatech_usb2",
- },
- .description = DRIVER_DESC,
- .id_table = quausb2_id_table,
- .num_ports = 8,
- .open = qt2_open,
- .close = qt2_close,
- .write = qt2_write,
- .write_room = qt2_write_room,
- .chars_in_buffer = qt2_chars_in_buffer,
- .throttle = qt2_throttle,
- .unthrottle = qt2_unthrottle,
- .calc_num_ports = qt2_calc_num_ports,
- .ioctl = qt2_ioctl,
- .set_termios = qt2_set_termios,
- .break_ctl = qt2_break,
- .tiocmget = qt2_tiocmget,
- .tiocmset = qt2_tiocmset,
- .attach = qt2_attach,
- .release = qt2_release,
- .read_bulk_callback = qt2_read_bulk_callback,
- .write_bulk_callback = qt2_write_bulk_callback,
-};
-
-static struct usb_serial_driver * const serial_drivers[] = {
- &quatech2_device, NULL
-};
-
-module_usb_serial_driver(quausb2_usb_driver, serial_drivers);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/staging/ramster/Kconfig b/drivers/staging/ramster/Kconfig
index 4af1f8d4b953..8349887827dc 100644
--- a/drivers/staging/ramster/Kconfig
+++ b/drivers/staging/ramster/Kconfig
@@ -1,6 +1,6 @@
config RAMSTER
bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem"
- depends on (CLEANCACHE || FRONTSWAP) && CONFIGFS_FS=y && !ZCACHE && !XVMALLOC && !HIGHMEM
+ depends on (CLEANCACHE || FRONTSWAP) && CONFIGFS_FS=y && !ZCACHE && !XVMALLOC && !HIGHMEM && NET
select LZO_COMPRESS
select LZO_DECOMPRESS
default n
diff --git a/drivers/staging/ramster/cluster/tcp.c b/drivers/staging/ramster/cluster/tcp.c
index b9721c1055b1..d0a07d722b61 100644
--- a/drivers/staging/ramster/cluster/tcp.c
+++ b/drivers/staging/ramster/cluster/tcp.c
@@ -111,7 +111,7 @@ static struct socket *r2net_listen_sock;
* r2net_wq. teardown detaches the callbacks before destroying the workqueue.
* quorum work is queued as sock containers are shutdown.. stop_listening
* tears down all the node's sock containers, preventing future shutdowns
- * and queued quroum work, before canceling delayed quorum work and
+ * and queued quorum work, before canceling delayed quorum work and
* destroying the work queue.
*/
static struct workqueue_struct *r2net_wq;
@@ -660,7 +660,7 @@ out:
/*
* we register callbacks so we can queue work on events before calling
- * the original callbacks. our callbacks our careful to test user_data
+ * the original callbacks. our callbacks are careful to test user_data
* to discover when they've reaced with r2net_unregister_callbacks().
*/
static void r2net_register_callbacks(struct sock *sk,
diff --git a/drivers/staging/ramster/xvmalloc.c b/drivers/staging/ramster/xvmalloc.c
index 93ba8e9407aa..44ceb0b823a9 100644
--- a/drivers/staging/ramster/xvmalloc.c
+++ b/drivers/staging/ramster/xvmalloc.c
@@ -132,7 +132,7 @@ static u32 find_block(struct xv_pool *pool, u32 size,
if (!pool->flbitmap)
return 0;
- /* Get freelist index correspoding to this size */
+ /* Get freelist index corresponding to this size */
slindex = get_index(size);
slbitmap = pool->slbitmap[slindex / BITS_PER_LONG];
slbitstart = slindex % BITS_PER_LONG;
diff --git a/drivers/staging/ramster/zcache-main.c b/drivers/staging/ramster/zcache-main.c
index 68b2e053a0e6..4e7ef0e6b79c 100644
--- a/drivers/staging/ramster/zcache-main.c
+++ b/drivers/staging/ramster/zcache-main.c
@@ -1331,7 +1331,7 @@ static ssize_t zv_max_mean_zsize_store(struct kobject *kobj,
* when that limit is reached, further puts will be rejected (until
* some pages have been flushed). Note that, due to compression,
* this number may exceed 100; it defaults to 75 and we set an
- * arbitary limit of 150. A poor choice will almost certainly result
+ * arbitrary limit of 150. A poor choice will almost certainly result
* in OOM's, so this value should only be changed prudently.
*/
static ssize_t zv_page_count_policy_percent_show(struct kobject *kobj,
@@ -2004,7 +2004,7 @@ int zcache_pampd_replace_in_obj(void *new_pampd, struct tmem_obj *obj)
* Called by the message handler after a (still compressed) page has been
* fetched from the remote machine in response to an "is_remote" tmem_get
* or persistent tmem_localify. For a tmem_get, "extra" is the address of
- * the page that is to be filled to succesfully resolve the tmem_get; for
+ * the page that is to be filled to successfully resolve the tmem_get; for
* a (persistent) tmem_localify, "extra" is NULL (as the data is placed only
* in the local zcache). "data" points to "size" bytes of (compressed) data
* passed in the message. In the case of a persistent remote get, if
@@ -2095,7 +2095,7 @@ out:
/*
* Called on a remote persistent tmem_get to attempt to preallocate
* local storage for the data contained in the remote persistent page.
- * If succesfully preallocated, returns the pampd, marked as remote and
+ * If successfully preallocated, returns the pampd, marked as remote and
* in_transit. Else returns NULL. Note that the appropriate tmem data
* structure must be locked.
*/
diff --git a/drivers/staging/rtl8187se/Makefile b/drivers/staging/rtl8187se/Makefile
index 72db504b23b4..91d1aa2830c9 100644
--- a/drivers/staging/rtl8187se/Makefile
+++ b/drivers/staging/rtl8187se/Makefile
@@ -10,7 +10,7 @@ ccflags-y += -DHIGH_POWER
ccflags-y += -DSW_DIG
ccflags-y += -DRATE_ADAPT
-#enable it for legacy power save, disable it for leisure power save
+#enable it for legacy power save, disable it for leisure power save
ccflags-y += -DENABLE_LPS
diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c
index 309bb8bf287e..0e93eb0735a7 100644
--- a/drivers/staging/rtl8187se/ieee80211/dot11d.c
+++ b/drivers/staging/rtl8187se/ieee80211/dot11d.c
@@ -55,7 +55,7 @@ Dot11d_Reset(struct ieee80211_device *ieee)
//
// Description:
-// Update country IE from Beacon or Probe Resopnse
+// Update country IE from Beacon or Probe Response
// and configure PHY for operation in the regulatory domain.
//
// TODO:
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
index 40dd715d9df7..b94c48b29302 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
@@ -834,7 +834,7 @@ enum ieee80211_state {
/* the association procedure is sending AUTH request*/
IEEE80211_ASSOCIATING_AUTHENTICATING,
- /* the association procedure has successfully authentcated
+ /* the association procedure has successfully authenticated
* and is sending association request
*/
IEEE80211_ASSOCIATING_AUTHENTICATED,
@@ -934,7 +934,7 @@ struct ieee80211_device {
* with RX of broad/multicast frames */
/* Fragmentation structures */
- // each streaming contain a entry
+ /* each stream contains an entry */
struct ieee80211_frag_entry frag_cache[17][IEEE80211_FRAG_CACHE_LEN];
unsigned int frag_next_idx[17];
u16 fts; /* Fragmentation Threshold */
@@ -972,7 +972,7 @@ struct ieee80211_device {
int rate; /* current rate */
int basic_rate;
- //FIXME: pleace callback, see if redundant with softmac_features
+ //FIXME: please callback, see if redundant with softmac_features
short active_scan;
/* this contains flags for selectively enable softmac support */
@@ -1106,7 +1106,7 @@ struct ieee80211_device {
/* used instead of hard_start_xmit (not softmac_hard_start_xmit)
* if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data
- * frames. I the option IEEE_SOFTMAC_SINGLE_QUEUE is also set
+ * frames. If the option IEEE_SOFTMAC_SINGLE_QUEUE is also set
* then also management frames are sent via this callback.
* This function can't sleep.
*/
@@ -1124,7 +1124,7 @@ struct ieee80211_device {
/* ask to the driver to retune the radio .
* This function can sleep. the driver should ensure
- * the radio has been swithced before return.
+ * the radio has been switched before return.
*/
void (*set_chan)(struct net_device *dev,short ch);
@@ -1135,7 +1135,7 @@ struct ieee80211_device {
* The syncro version is similar to the start_scan but
* does not return until all channels has been scanned.
* this is called in user context and should sleep,
- * it is called in a work_queue when swithcing to ad-hoc mode
+ * it is called in a work_queue when switching to ad-hoc mode
* or in behalf of iwlist scan when the card is associated
* and root user ask for a scan.
* the function stop_scan should stop both the syncro and
@@ -1196,7 +1196,7 @@ struct ieee80211_device {
/* Generate probe requests */
#define IEEE_SOFTMAC_PROBERQ (1<<4)
-/* Generate respones to probe requests */
+/* Generate response to probe requests */
#define IEEE_SOFTMAC_PROBERS (1<<5)
/* The ieee802.11 stack will manages the netif queue
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
index 26bacb96d247..8173240dcf7a 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
@@ -42,7 +42,7 @@ short ieee80211_is_shortslot(const struct ieee80211_network *net)
return net->capability & WLAN_CAPABILITY_SHORT_SLOT;
}
-/* returns the total length needed for pleacing the RATE MFIE
+/* returns the total length needed for placing the RATE MFIE
* tag and the EXTENDED RATE MFIE tag if needed.
* It encludes two bytes per tag for the tag itself and its len
*/
@@ -60,7 +60,7 @@ unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
return rate_len;
}
-/* pleace the MFIE rate, tag to the memory (double) poined.
+/* place the MFIE rate, tag to the memory (double) poised.
* Then it updates the pointer so that
* it points after the new MFIE tag added.
*/
@@ -467,7 +467,7 @@ void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
* So we switch to IEEE80211_LINKED_SCANNING to remember
* that we are still logically linked (not interested in
* new network events, despite for updating the net list,
- * but we are temporarly 'unlinked' as the driver shall
+ * but we are temporarily 'unlinked' as the driver shall
* not filter RX frames and the channel is changing.
* So the only situation in witch are interested is to check
* if the state become LINKED because of the #1 situation
@@ -530,7 +530,7 @@ void ieee80211_softmac_ips_scan_syncro(struct ieee80211_device *ieee)
* So we switch to IEEE80211_LINKED_SCANNING to remember
* that we are still logically linked (not interested in
* new network events, despite for updating the net list,
- * but we are temporarly 'unlinked' as the driver shall
+ * but we are temporarily 'unlinked' as the driver shall
* not filter RX frames and the channel is changing.
* So the only situation in witch are interested is to check
* if the state become LINKED because of the #1 situation
@@ -1140,7 +1140,7 @@ void ieee80211_associate_abort(struct ieee80211_device *ieee)
ieee->associate_seq++;
- /* don't scan, and avoid to have the RX path possibily
+ /* don't scan, and avoid to have the RX path possibly
* try again to associate. Even do not react to AUTH or
* ASSOC response. Just wait for the retry wq to be scheduled.
* Here we will check if there are good nets to associate
@@ -1346,14 +1346,14 @@ inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee
//printk("apset=%d apmatch=%d ssidset=%d ssidbroad=%d ssidmatch=%d\n",apset,apmatch,ssidset,ssidbroad,ssidmatch);
if ( /* if the user set the AP check if match.
- * if the network does not broadcast essid we check the user supplyed ANY essid
+ * if the network does not broadcast essid we check the user supplied ANY essid
* if the network does broadcast and the user does not set essid it is OK
* if the network does broadcast and the user did set essid chech if essid match
*/
( apset && apmatch &&
((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
/* if the ap is not set, check that the user set the bssid
- * and the network does bradcast and that those two bssid matches
+ * and the network does broadcast and that those two bssid matches
*/
(!apset && ssidset && ssidbroad && ssidmatch)
){
@@ -1821,7 +1821,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
while (left >= sizeof(struct ieee80211_info_element_hdr)) {
if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) {
- printk(KERN_WARNING "[re]associate reeponse error!");
+ printk(KERN_WARNING "[re]associate response error!");
return 1;
}
switch (info_element->id) {
@@ -1905,7 +1905,7 @@ associate_complete:
}
}else{
ieee->softmac_stats.rx_auth_rs_err++;
- IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
+ IEEE80211_DEBUG_MGMT("Authentication response status code 0x%x",errcode);
ieee80211_associate_abort(ieee);
}
@@ -2184,15 +2184,15 @@ void ieee80211_start_ibss_wq(struct work_struct *work)
if(ieee->state == IEEE80211_NOLINK)
ieee->current_network.channel = 10;
- /* if not then the state is not linked. Maybe the user swithced to
+ /* if not then the state is not linked. Maybe the user switched to
* ad-hoc mode just after being in monitor mode, or just after
* being very few time in managed mode (so the card have had no
* time to scan all the chans..) or we have just run up the iface
* after setting ad-hoc mode. So we have to give another try..
* Here, in ibss mode, should be safe to do this without extra care
- * (in bss mode we had to make sure no-one tryed to associate when
+ * (in bss mode we had to make sure no-one tried to associate when
* we had just checked the ieee->state and we was going to start the
- * scan) beacause in ibss mode the ieee80211_new_net function, when
+ * scan) because in ibss mode the ieee80211_new_net function, when
* finds a good net, just set the ieee->state to IEEE80211_LINKED,
* so, at worst, we waste a bit of time to initiate an unneeded syncro
* scan, that will stop at the first round because it sees the state
@@ -2342,7 +2342,7 @@ void ieee80211_associate_retry_wq(struct work_struct *work)
goto exit;
/* until we do not set the state to IEEE80211_NOLINK
* there are no possibility to have someone else trying
- * to start an association procdure (we get here with
+ * to start an association procedure (we get here with
* ieee->state = IEEE80211_ASSOCIATING).
* When we set the state to IEEE80211_NOLINK it is possible
* that the RX path run an attempt to associate, but
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
index e46ff2ffa09b..5d204906baf7 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
@@ -362,7 +362,7 @@ int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
ieee80211_stop_protocol(ieee);
/* this is just to be sure that the GET wx callback
- * has consisten infos. not needed otherwise
+ * has consistent infos. not needed otherwise
*/
spin_lock_irqsave(&ieee->lock, flags);
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
index 552115cd760e..89ed86ef0d15 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
@@ -328,7 +328,7 @@ int ieee80211_rtl_xmit(struct sk_buff *skb,
//printk(KERN_WARNING "upper layer packet!\n");
spin_lock_irqsave(&ieee->lock, flags);
- /* If there is no driver handler to take the TXB, dont' bother
+ /* If there is no driver handler to take the TXB, don't bother
* creating it... */
if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))||
((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
@@ -413,10 +413,7 @@ int ieee80211_rtl_xmit(struct sk_buff *skb,
/* Determine fragmentation size based on destination (multicast
* and broadcast are not fragmented) */
-// if (is_multicast_ether_addr(dest) ||
-// is_broadcast_ether_addr(dest)) {
- if (is_multicast_ether_addr(header.addr1) ||
- is_broadcast_ether_addr(header.addr1)) {
+ if (is_multicast_ether_addr(header.addr1)) {
frag_size = MAX_FRAG_THRESHOLD;
qos_ctl = QOS_CTL_NOTCONTAIN_ACK;
}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
index ca414a915a4e..c7917b24425c 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
@@ -363,7 +363,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
(*crypt)->priv);
sec.flags |= (1 << key);
/* This ensures a key will be activated if no key is
- * explicitely set */
+ * explicitly set */
if (key == sec.active_key)
sec.flags |= SEC_ACTIVE_KEY;
ieee->tx_keyidx = key;//by wb 080312
diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h
index a2c46ae4a400..2682afbac4ff 100644
--- a/drivers/staging/rtl8187se/r8180.h
+++ b/drivers/staging/rtl8187se/r8180.h
@@ -11,7 +11,7 @@
Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
- We want to tanks the Authors of those projects and the Ndiswrapper
+ We want to thanks the Authors of those projects and the Ndiswrapper
project Authors.
*/
@@ -514,12 +514,12 @@ typedef struct r8180_priv
bool bDefaultAntenna1;
u8 SignalStrength;
long Stats_SignalStrength;
- long LastSignalStrengthInPercent; // In percentange, used for smoothing, e.g. Moving Average.
+ long LastSignalStrengthInPercent; // In percentage, used for smoothing, e.g. Moving Average.
u8 SignalQuality; // in 0-100 index.
long Stats_SignalQuality;
long RecvSignalPower; // in dBm.
long Stats_RecvSignalPower;
- u8 LastRxPktAntenna; // +by amy 080312 Antenn which received the lasted packet. 0: Aux, 1:Main. Added by Roger, 2008.01.25.
+ u8 LastRxPktAntenna; // +by amy 080312 Antenna which received the lasted packet. 0: Aux, 1:Main. Added by Roger, 2008.01.25.
u32 AdRxOkCnt;
long AdRxSignalStrength;
u8 CurrAntennaIndex; // Index to current Antenna (both Tx and Rx).
@@ -530,7 +530,7 @@ typedef struct r8180_priv
long AdRxSsThreshold; // Signal strength threshold to switch antenna.
long AdMaxRxSsThreshold; // Max value of AdRxSsThreshold.
bool bAdSwitchedChecking; // TRUE if we shall shall check Rx signal strength for last time switching antenna.
- long AdRxSsBeforeSwitched; // Rx signal strength before we swithed antenna.
+ long AdRxSsBeforeSwitched; // Rx signal strength before we switched antenna.
struct timer_list SwAntennaDiversityTimer;
//by amy for antenna
//{by amy 080312
@@ -553,7 +553,7 @@ typedef struct r8180_priv
bool bDigMechanism; // TRUE if DIG is enabled, FALSE ow.
bool bRegHighPowerMechanism; // For High Power Mechanism. 061010, by rcnjko.
u32 FalseAlarmRegValue;
- u8 RegDigOfdmFaUpTh; // Upper threhold of OFDM false alarm, which is used in DIG.
+ u8 RegDigOfdmFaUpTh; // Upper threshold of OFDM false alarm, which is used in DIG.
u8 DIG_NumberFallbackVote;
u8 DIG_NumberUpgradeVote;
// For HW antenna diversity, added by Roger, 2008.01.30.
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 4fe52f6b0034..fd22b75aea4f 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -1329,7 +1329,7 @@ u16 N_DBPSOfRate(u16 DataRate)
}
/*
- * For Netgear case, they want good-looking singal strength.
+ * For Netgear case, they want good-looking signal strength.
*/
long NetgearSignalStrengthTranslate(long LastSS, long CurrSS)
{
@@ -1380,7 +1380,7 @@ long TranslateToDbm8185(u8 SignalStrengthIndex)
/*
* Perform signal smoothing for dynamic mechanism.
- * This is different with PerformSignalSmoothing8185 in smoothing fomula.
+ * This is different with PerformSignalSmoothing8185 in smoothing formula.
* No dramatic adjustion is apply because dynamic mechanism need some degree
* of correctness. Ported from 8187B.
*/
@@ -1535,7 +1535,7 @@ void rtl8180_rx(struct net_device *dev)
/* HW is probably passing several buggy frames
* without FD or LD flag set.
* Throw this garbage away to prevent skb
- * memory exausting
+ * memory exhausting
*/
if (!priv->rx_skb_complete)
dev_kfree_skb_any(priv->rx_skb);
@@ -1648,14 +1648,14 @@ void rtl8180_rx(struct net_device *dev)
priv->Stats_SignalQuality = (long)(priv->Stats_SignalQuality * 5 + (long)priv->SignalQuality + 5) / 6;
priv->Stats_RecvSignalPower = (long)(priv->Stats_RecvSignalPower * 5 + priv->RecvSignalPower - 1) / 6;
- /* Figure out which antenna that received the lasted packet. */
+ /* Figure out which antenna that received the last packet. */
priv->LastRxPktAntenna = Antenna ? 1 : 0; /* 0: aux, 1: main. */
SwAntennaDiversityRxOk8185(dev, priv->SignalStrength);
}
if (first) {
if (!priv->rx_skb_complete) {
- /* seems that HW sometimes fails to reiceve and
+ /* seems that HW sometimes fails to receive and
doesn't provide the last descriptor */
dev_kfree_skb_any(priv->rx_skb);
priv->stats.rxnolast++;
@@ -1672,7 +1672,7 @@ void rtl8180_rx(struct net_device *dev)
priv->rx_skb_complete = 0;
priv->rx_skb->dev = dev;
} else {
- /* if we are here we should have already RXed
+ /* if we are here we should have already RXed
* the first frame.
* If we get here and the skb is not allocated then
* we have just throw out garbage (skb not allocated)
@@ -1821,15 +1821,15 @@ rate) {
/*
* This is a rough attempt to TX a frame
* This is called by the ieee 80211 stack to TX management frames.
- * If the ring is full packet are dropped (for data frame the queue
+ * If the ring is full packets are dropped (for data frame the queue
* is stopped before this can happen). For this reason it is better
* if the descriptors are larger than the largest management frame
- * we intend to TX: i'm unsure what the HW does if it will not found
+ * we intend to TX: i'm unsure what the HW does if it will not find
* the last fragment of a frame because it has been dropped...
* Since queues for Management and Data frames are different we
* might use a different lock than tx_lock (for example mgmt_tx_lock)
*/
-/* these function may loops if invoked with 0 descriptors or 0 len buffer */
+/* these function may loop if invoked with 0 descriptors or 0 len buffer */
int rtl8180_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
@@ -2003,8 +2003,7 @@ short rtl8180_tx(struct net_device *dev, u8* txbuf, int len, int priority,
}
memcpy(&dest, frag_hdr->addr1, ETH_ALEN);
- if (is_multicast_ether_addr(dest) ||
- is_broadcast_ether_addr(dest)) {
+ if (is_multicast_ether_addr(dest)) {
Duration = 0;
RtsDur = 0;
bRTSEnable = 0;
@@ -2378,7 +2377,7 @@ void rtl8180_wmm_param_update(struct work_struct *work)
u8 u1bAIFS;
u32 u4bAcParam;
pAcParam = (PAC_PARAM)(&AcParam);
- /* Retrive paramters to udpate. */
+ /* Retrieve paramters to update. */
u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * (((mode&IEEE_G) == IEEE_G) ? 9 : 20) + aSifsTime;
u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit))<<AC_PARAM_TXOP_LIMIT_OFFSET)|
(((u32)(pAcParam->f.Ecw.f.ECWmax))<<AC_PARAM_ECW_MAX_OFFSET)|
@@ -2414,7 +2413,7 @@ void rtl8180_wmm_param_update(struct work_struct *work)
u8 u1bAIFS;
u32 u4bAcParam;
- /* Retrive paramters to udpate. */
+ /* Retrieve paramters to update. */
eACI = pAcParam->f.AciAifsn.f.ACI;
/* Mode G/A: slotTimeTimer = 9; Mode B: 20 */
u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * (((mode&IEEE_G) == IEEE_G) ? 9 : 20) + aSifsTime;
@@ -2700,7 +2699,7 @@ short rtl8180_init(struct net_device *dev)
priv->bTxPowerTrack = false;
priv->ThermalMeter = 0;
priv->FalseAlarmRegValue = 0;
- priv->RegDigOfdmFaUpTh = 0xc; /* Upper threhold of OFDM false alarm, which is used in DIG. */
+ priv->RegDigOfdmFaUpTh = 0xc; /* Upper threshold of OFDM false alarm, which is used in DIG. */
priv->DIG_NumberFallbackVote = 0;
priv->DIG_NumberUpgradeVote = 0;
priv->LastSignalStrengthInPercent = 0;
@@ -2896,7 +2895,7 @@ short rtl8180_init(struct net_device *dev)
priv->chtxpwr_ofdm[i+1] = (word & 0xff00) >> 8;
}
- /* 3Read crystal calibtration and thermal meter indication on 87SE. */
+ /* 3Read crystal calibration and thermal meter indication on 87SE. */
eeprom_93cx6_read(&eeprom, EEPROM_RSV>>1, &tmpu16);
/* Crystal calibration for Xin and Xout resp. */
@@ -3140,7 +3139,7 @@ void rtl8180_adapter_start(struct net_device *dev)
/*
* The following is very strange. seems to be that 1 means test mode,
- * but we need to acknolwledges the nic when a packet is ready
+ * but we need to acknowledges the nic when a packet is ready
* although we set it to 0
*/
@@ -3971,7 +3970,7 @@ irqreturn_t rtl8180_interrupt(int irq, void *netdev, struct pt_regs *regs)
}
if (inta == 0xffff) {
- /* HW disappared */
+ /* HW disappeared */
spin_unlock_irqrestore(&priv->irq_th_lock, flags);
return IRQ_HANDLED;
}
diff --git a/drivers/staging/rtl8187se/r8180_dm.c b/drivers/staging/rtl8187se/r8180_dm.c
index 4d7a5951486e..b8f2ba010a04 100644
--- a/drivers/staging/rtl8187se/r8180_dm.c
+++ b/drivers/staging/rtl8187se/r8180_dm.c
@@ -2,7 +2,7 @@
#include "r8180_hw.h"
#include "r8180_93cx6.h"
- /* Return TRUE if we shall perform High Power Mecahnism, FALSE otherwise. */
+ /* Return TRUE if we shall perform High Power Mechanism, FALSE otherwise. */
#define RATE_ADAPTIVE_TIMER_PERIOD 300
bool CheckHighPower(struct net_device *dev)
@@ -105,7 +105,7 @@ void rtl8180_tx_pw_wq(struct work_struct *work)
/*
- * Return TRUE if we shall perform DIG Mecahnism, FALSE otherwise.
+ * Return TRUE if we shall perform DIG Mechanism, FALSE otherwise.
*/
bool CheckDig(struct net_device *dev)
{
@@ -507,7 +507,7 @@ void StaRateAdaptive87SE(struct net_device *dev)
* and retry rate.
* (3) Remove all Initial Gain Updates over OFDM rate. To avoid the complicated
* situation, Initial Gain Update is upon on DIG mechanism except CCK rate.
- * (4) Add the mehanism of trying to upgrade tx rate.
+ * (4) Add the mechanism of trying to upgrade tx rate.
* (5) Record the information of upping tx rate to avoid trying upping tx rate constantly.
*
*/
@@ -528,7 +528,7 @@ void StaRateAdaptive87SE(struct net_device *dev)
if (priv->bTryuping == true) {
/* 2 For Test Upgrading mechanism
* Note:
- * Sometimes the throughput is upon on the capability bwtween the AP and NIC,
+ * Sometimes the throughput is upon on the capability between the AP and NIC,
* thus the low data rate does not improve the performance.
* We randomly upgrade the data rate and check if the retry rate is improved.
*/
@@ -704,7 +704,7 @@ void StaRateAdaptive87SE(struct net_device *dev)
/*
* The difference in throughput between 48Mbps and 36Mbps is 8M.
- * So, we must be carefully in this rate scale. Isaiah 2008-02-15.
+ * So, we must be careful in this rate scale. Isaiah 2008-02-15.
*/
if (((priv->CurrentOperaRate == 72) || (priv->CurrentOperaRate == 48) || (priv->CurrentOperaRate == 36)) &&
(priv->FailTxRateCount > 2))
@@ -1009,7 +1009,7 @@ void SwAntennaDiversity(struct net_device *dev)
if (priv->AdCheckPeriod > priv->AdMaxCheckPeriod)
priv->AdCheckPeriod = priv->AdMaxCheckPeriod;
- /* Wrong deceision => switch back. */
+ /* Wrong decision => switch back. */
SwitchAntenna(dev);
} else {
/* Rx Signal Strength is improved. */
@@ -1057,7 +1057,7 @@ void SwAntennaDiversity(struct net_device *dev)
}
/*
* <Roger_Notes> We evaluate Rx signal strength ONLY when default antenna
- * didn't changed by HW evaluation.
+ * didn't change by HW evaluation.
* 2008.02.27.
*
* [TRC Dell Lab] SignalStrength is inaccuracy. Isaiah 2008-03-05
@@ -1098,7 +1098,7 @@ void SwAntennaDiversity(struct net_device *dev)
priv->AdAuxAntennaRxOkCnt = 0;
}
- /* Return TRUE if we shall perform Tx Power Tracking Mecahnism, FALSE otherwise. */
+ /* Return TRUE if we shall perform Tx Power Tracking Mechanism, FALSE otherwise. */
bool CheckTxPwrTracking(struct net_device *dev)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
diff --git a/drivers/staging/rtl8187se/r8180_rtl8225z2.c b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
index ee5b867fd0d4..d28c1d996084 100644
--- a/drivers/staging/rtl8187se/r8180_rtl8225z2.c
+++ b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
@@ -190,7 +190,7 @@ static void rtl8225_SetTXPowerLevel(struct net_device *dev, short ch)
write_phy_cck(dev, 0x44 + i, power);
}
- /* FIXME Is this delay really needeed ? */
+ /* FIXME Is this delay really needed ? */
force_pci_posting(dev);
mdelay(1);
@@ -479,7 +479,7 @@ s8 DbmToTxPwrIdx(struct r8180_priv *priv, WIRELESS_MODE WirelessMode,
/*
* TRUE if we want to use a default implementation.
- * We shall set it to FALSE when we have exact translation formular
+ * We shall set it to FALSE when we have exact translation formula
* for target IC. 070622, by rcnjko.
*/
if (bUseDefault) {
diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c
index 303ec691262a..46ee6f47f525 100644
--- a/drivers/staging/rtl8187se/r8180_wx.c
+++ b/drivers/staging/rtl8187se/r8180_wx.c
@@ -13,7 +13,7 @@
Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
- We want to tanks the Authors of those projects and the Ndiswrapper
+ We want to thanks the Authors of those projects and the Ndiswrapper
project Authors.
*/
@@ -1181,7 +1181,7 @@ static iw_handler r8180_wx_handlers[] = {
r8180_wx_set_wap, /* SIOCSIWAP */
r8180_wx_get_wap, /* SIOCGIWAP */
r8180_wx_set_mlme, /* SIOCSIWMLME*/
- dummy, /* SIOCGIWAPLIST -- depricated */
+ dummy, /* SIOCGIWAPLIST -- deprecated */
r8180_wx_set_scan, /* SIOCSIWSCAN */
r8180_wx_get_scan, /* SIOCGIWSCAN */
r8180_wx_set_essid, /* SIOCSIWESSID */
@@ -1369,7 +1369,7 @@ static inline int is_same_network(struct ieee80211_network *src,
(dst->capability & WLAN_CAPABILITY_BSS)));
}
-/* WB modefied to show signal to GUI on 18-01-2008 */
+/* WB modified to show signal to GUI on 18-01-2008 */
static struct iw_statistics *r8180_get_wireless_stats(struct net_device *dev)
{
struct r8180_priv *priv = ieee80211_priv(dev);
diff --git a/drivers/staging/rtl8187se/r8180_wx.h b/drivers/staging/rtl8187se/r8180_wx.h
index 735d03dceed3..408191403112 100644
--- a/drivers/staging/rtl8187se/r8180_wx.h
+++ b/drivers/staging/rtl8187se/r8180_wx.h
@@ -7,7 +7,7 @@
Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
- We want to tanks the Authors of such projects and the Ndiswrapper project Authors.
+ We want to thanks the Authors of such projects and the Ndiswrapper project Authors.
*/
/* this file (will) contains wireless extension handlers*/
diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c
index 4b0b830f9ab6..914495783c06 100644
--- a/drivers/staging/rtl8187se/r8185b_init.c
+++ b/drivers/staging/rtl8187se/r8185b_init.c
@@ -1,22 +1,22 @@
-/*++
-Copyright (c) Realtek Semiconductor Corp. All rights reserved.
-
-Module Name:
- r8185b_init.c
-
-Abstract:
- Hardware Initialization and Hardware IO for RTL8185B
-
-Major Change History:
- When Who What
- ---------- --------------- -------------------------------
- 2006-11-15 Xiong Created
-
-Notes:
- This file is ported from RTL8185B Windows driver.
-
-
---*/
+/*
+ * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
+ *
+ * Module Name:
+ * r8185b_init.c
+ *
+ * Abstract:
+ * Hardware Initialization and Hardware IO for RTL8185B
+ *
+ * Major Change History:
+ * When Who What
+ * ---------- --------------- -------------------------------
+ * 2006-11-15 Xiong Created
+ *
+ * Notes:
+ * This file is ported from RTL8185B Windows driver.
+ *
+ *
+ */
/*--------------------------Include File------------------------------------*/
#include <linux/spinlock.h>
@@ -25,155 +25,134 @@ Notes:
#include "r8180_rtl8225.h" /* RTL8225 Radio frontend */
#include "r8180_93cx6.h" /* Card EEPROM */
#include "r8180_wx.h"
-
#include "ieee80211/dot11d.h"
-
-
/* #define CONFIG_RTL8180_IO_MAP */
-
#define TC_3W_POLL_MAX_TRY_CNT 5
+
static u8 MAC_REG_TABLE[][2] = {
- /*PAGA 0: */
- /* 0x34(BRSR), 0xBE(RATE_FALLBACK_CTL), 0x1E0(ARFR) would set in HwConfigureRTL8185() */
- /* 0x272(RFSW_CTRL), 0x1CE(AESMSK_QC) set in InitializeAdapter8185(). */
- /* 0x1F0~0x1F8 set in MacConfig_85BASIC() */
- {0x08, 0xae}, {0x0a, 0x72}, {0x5b, 0x42},
- {0x84, 0x88}, {0x85, 0x24}, {0x88, 0x54}, {0x8b, 0xb8}, {0x8c, 0x03},
- {0x8d, 0x40}, {0x8e, 0x00}, {0x8f, 0x00}, {0x5b, 0x18}, {0x91, 0x03},
- {0x94, 0x0F}, {0x95, 0x32},
- {0x96, 0x00}, {0x97, 0x07}, {0xb4, 0x22}, {0xdb, 0x00},
- {0xf0, 0x32}, {0xf1, 0x32}, {0xf2, 0x00}, {0xf3, 0x00}, {0xf4, 0x32},
- {0xf5, 0x43}, {0xf6, 0x00}, {0xf7, 0x00}, {0xf8, 0x46}, {0xf9, 0xa4},
- {0xfa, 0x00}, {0xfb, 0x00}, {0xfc, 0x96}, {0xfd, 0xa4}, {0xfe, 0x00},
- {0xff, 0x00},
-
- /*PAGE 1: */
- /* For Flextronics system Logo PCIHCT failure: */
- /* 0x1C4~0x1CD set no-zero value to avoid PCI configuration space 0x45[7]=1 */
- {0x5e, 0x01},
- {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x04}, {0x5b, 0x00}, {0x60, 0x24},
- {0x61, 0x97}, {0x62, 0xF0}, {0x63, 0x09}, {0x80, 0x0F}, {0x81, 0xFF},
- {0x82, 0xFF}, {0x83, 0x03},
- {0xC4, 0x22}, {0xC5, 0x22}, {0xC6, 0x22}, {0xC7, 0x22}, {0xC8, 0x22}, /* lzm add 080826 */
- {0xC9, 0x22}, {0xCA, 0x22}, {0xCB, 0x22}, {0xCC, 0x22}, {0xCD, 0x22},/* lzm add 080826 */
- {0xe2, 0x00},
-
-
- /* PAGE 2: */
- {0x5e, 0x02},
- {0x0c, 0x04}, {0x4c, 0x30}, {0x4d, 0x08}, {0x50, 0x05}, {0x51, 0xf5},
- {0x52, 0x04}, {0x53, 0xa0}, {0x54, 0xff}, {0x55, 0xff}, {0x56, 0xff},
- {0x57, 0xff}, {0x58, 0x08}, {0x59, 0x08}, {0x5a, 0x08}, {0x5b, 0x08},
- {0x60, 0x08}, {0x61, 0x08}, {0x62, 0x08}, {0x63, 0x08}, {0x64, 0x2f},
- {0x8c, 0x3f}, {0x8d, 0x3f}, {0x8e, 0x3f},
- {0x8f, 0x3f}, {0xc4, 0xff}, {0xc5, 0xff}, {0xc6, 0xff}, {0xc7, 0xff},
- {0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x80}, {0xcb, 0x00},
-
- /* PAGA 0: */
- {0x5e, 0x00}, {0x9f, 0x03}
- };
-
-
-static u8 ZEBRA_AGC[] = {
- 0,
- 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72,
- 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62,
- 0x48, 0x47, 0x46, 0x45, 0x44, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07,
- 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16,
- 0x17, 0x17, 0x18, 0x18, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e,
- 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x24,
- 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F
- };
-
-static u32 ZEBRA_RF_RX_GAIN_TABLE[] = {
- 0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6,
- 0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057,
- 0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3,
- 0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3,
- 0x0183, 0x0163, 0x0143, 0x0123, 0x0103
+ /*PAGA 0: */
+ /* 0x34(BRSR), 0xBE(RATE_FALLBACK_CTL), 0x1E0(ARFR) would set in HwConfigureRTL8185() */
+ /* 0x272(RFSW_CTRL), 0x1CE(AESMSK_QC) set in InitializeAdapter8185(). */
+ /* 0x1F0~0x1F8 set in MacConfig_85BASIC() */
+ {0x08, 0xae}, {0x0a, 0x72}, {0x5b, 0x42},
+ {0x84, 0x88}, {0x85, 0x24}, {0x88, 0x54}, {0x8b, 0xb8}, {0x8c, 0x03},
+ {0x8d, 0x40}, {0x8e, 0x00}, {0x8f, 0x00}, {0x5b, 0x18}, {0x91, 0x03},
+ {0x94, 0x0F}, {0x95, 0x32},
+ {0x96, 0x00}, {0x97, 0x07}, {0xb4, 0x22}, {0xdb, 0x00},
+ {0xf0, 0x32}, {0xf1, 0x32}, {0xf2, 0x00}, {0xf3, 0x00}, {0xf4, 0x32},
+ {0xf5, 0x43}, {0xf6, 0x00}, {0xf7, 0x00}, {0xf8, 0x46}, {0xf9, 0xa4},
+ {0xfa, 0x00}, {0xfb, 0x00}, {0xfc, 0x96}, {0xfd, 0xa4}, {0xfe, 0x00},
+ {0xff, 0x00},
+
+ /*PAGE 1: */
+ /* For Flextronics system Logo PCIHCT failure: */
+ /* 0x1C4~0x1CD set no-zero value to avoid PCI configuration space 0x45[7]=1 */
+ {0x5e, 0x01},
+ {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x04}, {0x5b, 0x00}, {0x60, 0x24},
+ {0x61, 0x97}, {0x62, 0xF0}, {0x63, 0x09}, {0x80, 0x0F}, {0x81, 0xFF},
+ {0x82, 0xFF}, {0x83, 0x03},
+ {0xC4, 0x22}, {0xC5, 0x22}, {0xC6, 0x22}, {0xC7, 0x22}, {0xC8, 0x22}, /* lzm add 080826 */
+ {0xC9, 0x22}, {0xCA, 0x22}, {0xCB, 0x22}, {0xCC, 0x22}, {0xCD, 0x22}, /* lzm add 080826 */
+ {0xe2, 0x00},
+
+
+ /* PAGE 2: */
+ {0x5e, 0x02},
+ {0x0c, 0x04}, {0x4c, 0x30}, {0x4d, 0x08}, {0x50, 0x05}, {0x51, 0xf5},
+ {0x52, 0x04}, {0x53, 0xa0}, {0x54, 0xff}, {0x55, 0xff}, {0x56, 0xff},
+ {0x57, 0xff}, {0x58, 0x08}, {0x59, 0x08}, {0x5a, 0x08}, {0x5b, 0x08},
+ {0x60, 0x08}, {0x61, 0x08}, {0x62, 0x08}, {0x63, 0x08}, {0x64, 0x2f},
+ {0x8c, 0x3f}, {0x8d, 0x3f}, {0x8e, 0x3f},
+ {0x8f, 0x3f}, {0xc4, 0xff}, {0xc5, 0xff}, {0xc6, 0xff}, {0xc7, 0xff},
+ {0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x80}, {0xcb, 0x00},
+
+ /* PAGA 0: */
+ {0x5e, 0x00}, {0x9f, 0x03}
+ };
+
+
+static u8 ZEBRA_AGC[] = {
+ 0,
+ 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72,
+ 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62,
+ 0x48, 0x47, 0x46, 0x45, 0x44, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07,
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16,
+ 0x17, 0x17, 0x18, 0x18, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e,
+ 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x24,
+ 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F
+ };
+
+static u32 ZEBRA_RF_RX_GAIN_TABLE[] = {
+ 0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6,
+ 0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057,
+ 0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3,
+ 0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3,
+ 0x0183, 0x0163, 0x0143, 0x0123, 0x0103
};
-static u8 OFDM_CONFIG[] = {
- /* OFDM reg0x06[7:0]=0xFF: Enable power saving mode in RX */
- /* OFDM reg0x3C[4]=1'b1: Enable RX power saving mode */
- /* ofdm 0x3a = 0x7b ,(original : 0xfb) For ECS shielding room TP test */
-
- /* 0x00 */
- 0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50,
- 0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00,
- /* 0x10 */
- 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26,
- 0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB,
- /* 0x20 */
- 0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00,
- 0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00,
- /* 0x30 */
- 0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e,
- 0xD8, 0x3C, 0x7B, 0x10, 0x10
- };
-
-/* ---------------------------------------------------------------
- * Hardware IO
- * the code is ported from Windows source code
- ----------------------------------------------------------------*/
-
-void
-PlatformIOWrite1Byte(
- struct net_device *dev,
- u32 offset,
- u8 data
- )
+static u8 OFDM_CONFIG[] = {
+ /* OFDM reg0x06[7:0]=0xFF: Enable power saving mode in RX */
+ /* OFDM reg0x3C[4]=1'b1: Enable RX power saving mode */
+ /* ofdm 0x3a = 0x7b ,(original : 0xfb) For ECS shielding room TP test */
+ /* 0x00 */
+ 0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50,
+ 0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00,
+ /* 0x10 */
+ 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26,
+ 0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB,
+ /* 0x20 */
+ 0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00,
+ 0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00,
+ /* 0x30 */
+ 0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e,
+ 0xD8, 0x3C, 0x7B, 0x10, 0x10
+ };
+
+ /*---------------------------------------------------------------
+ * Hardware IO
+ * the code is ported from Windows source code
+ *---------------------------------------------------------------
+ */
+
+void PlatformIOWrite1Byte(struct net_device *dev, u32 offset, u8 data)
{
write_nic_byte(dev, offset, data);
- read_nic_byte(dev, offset); /* To make sure write operation is completed, 2005.11.09, by rcnjko. */
-
+ read_nic_byte(dev, offset); /* To make sure write operation is completed, 2005.11.09, by rcnjko. */
}
-void
-PlatformIOWrite2Byte(
- struct net_device *dev,
- u32 offset,
- u16 data
- )
+void PlatformIOWrite2Byte(struct net_device *dev, u32 offset, u16 data)
{
write_nic_word(dev, offset, data);
read_nic_word(dev, offset); /* To make sure write operation is completed, 2005.11.09, by rcnjko. */
-
-
}
+
u8 PlatformIORead1Byte(struct net_device *dev, u32 offset);
-void
-PlatformIOWrite4Byte(
- struct net_device *dev,
- u32 offset,
- u32 data
- )
+void PlatformIOWrite4Byte(struct net_device *dev, u32 offset, u32 data)
{
-/* {by amy 080312 */
-if (offset == PhyAddr) {
-/* For Base Band configuration. */
+ if (offset == PhyAddr) {
+ /* For Base Band configuration. */
unsigned char cmdByte;
unsigned long dataBytes;
unsigned char idx;
- u8 u1bTmp;
+ u8 u1bTmp;
cmdByte = (u8)(data & 0x000000ff);
dataBytes = data>>8;
/*
- 071010, rcnjko:
- The critical section is only BB read/write race condition.
- Assumption:
- 1. We assume NO one will access BB at DIRQL, otherwise, system will crash for
- acquiring the spinlock in such context.
- 2. PlatformIOWrite4Byte() MUST NOT be recursive.
- */
-/* NdisAcquireSpinLock( &(pDevice->IoSpinLock) ); */
-
- for (idx = 0; idx < 30; idx++) {
- /* Make sure command bit is clear before access it. */
+ * 071010, rcnjko:
+ * The critical section is only BB read/write race condition.
+ * Assumption:
+ * 1. We assume NO one will access BB at DIRQL, otherwise, system will crash for
+ * acquiring the spinlock in such context.
+ * 2. PlatformIOWrite4Byte() MUST NOT be recursive.
+ */
+ /* NdisAcquireSpinLock( &(pDevice->IoSpinLock) ); */
+
+ for (idx = 0; idx < 30; idx++) {
+ /* Make sure command bit is clear before access it. */
u1bTmp = PlatformIORead1Byte(dev, PhyAddr);
if ((u1bTmp & BIT7) == 0)
break;
@@ -186,20 +165,14 @@ if (offset == PhyAddr) {
write_nic_byte(dev, offset, cmdByte);
-/* NdisReleaseSpinLock( &(pDevice->IoSpinLock) ); */
- }
-/* by amy 080312} */
- else {
+ /* NdisReleaseSpinLock( &(pDevice->IoSpinLock) ); */
+ } else {
write_nic_dword(dev, offset, data);
read_nic_dword(dev, offset); /* To make sure write operation is completed, 2005.11.09, by rcnjko. */
}
}
-u8
-PlatformIORead1Byte(
- struct net_device *dev,
- u32 offset
- )
+u8 PlatformIORead1Byte(struct net_device *dev, u32 offset)
{
u8 data = 0;
@@ -209,11 +182,7 @@ PlatformIORead1Byte(
return data;
}
-u16
-PlatformIORead2Byte(
- struct net_device *dev,
- u32 offset
- )
+u16 PlatformIORead2Byte(struct net_device *dev, u32 offset)
{
u16 data = 0;
@@ -223,11 +192,7 @@ PlatformIORead2Byte(
return data;
}
-u32
-PlatformIORead4Byte(
- struct net_device *dev,
- u32 offset
- )
+u32 PlatformIORead4Byte(struct net_device *dev, u32 offset)
{
u32 data = 0;
@@ -242,22 +207,19 @@ void SetOutputEnableOfRfPins(struct net_device *dev)
write_nic_word(dev, RFPinsEnable, 0x1bff);
}
-static int
-HwHSSIThreeWire(
- struct net_device *dev,
- u8 *pDataBuf,
- u8 nDataBufBitCnt,
- int bSI,
- int bWrite
- )
+static int HwHSSIThreeWire(struct net_device *dev,
+ u8 *pDataBuf,
+ u8 nDataBufBitCnt,
+ int bSI,
+ int bWrite)
{
int bResult = 1;
u8 TryCnt;
u8 u1bTmp;
- do {
+ do {
/* Check if WE and RE are cleared. */
- for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
+ for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
if ((u1bTmp & (SW_3W_CMD1_RE|SW_3W_CMD1_WE)) == 0)
break;
@@ -275,15 +237,15 @@ HwHSSIThreeWire(
u1bTmp = read_nic_byte(dev, RF_SW_CONFIG);
if (bSI)
- u1bTmp |= RF_SW_CFG_SI; /* reg08[1]=1 Serial Interface(SI) */
+ u1bTmp |= RF_SW_CFG_SI; /* reg08[1]=1 Serial Interface(SI) */
else
- u1bTmp &= ~RF_SW_CFG_SI; /* reg08[1]=0 Parallel Interface(PI) */
+ u1bTmp &= ~RF_SW_CFG_SI; /* reg08[1]=0 Parallel Interface(PI) */
write_nic_byte(dev, RF_SW_CONFIG, u1bTmp);
- if (bSI) {
+ if (bSI) {
/* jong: HW SI read must set reg84[3]=0. */
u1bTmp = read_nic_byte(dev, RFPinsSelect);
u1bTmp &= ~BIT3;
@@ -291,14 +253,14 @@ HwHSSIThreeWire(
}
/* Fill up data buffer for write operation. */
- if (bWrite) {
- if (nDataBufBitCnt == 16) {
+ if (bWrite) {
+ if (nDataBufBitCnt == 16) {
write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
- } else if (nDataBufBitCnt == 64) {
+ } else if (nDataBufBitCnt == 64) {
/* RTL8187S shouldn't enter this case */
write_nic_dword(dev, SW_3W_DB0, *((u32 *)pDataBuf));
write_nic_dword(dev, SW_3W_DB1, *((u32 *)(pDataBuf + 4)));
- } else {
+ } else {
int idx;
int ByteCnt = nDataBufBitCnt / 8;
/* printk("%d\n",nDataBufBitCnt); */
@@ -324,11 +286,11 @@ HwHSSIThreeWire(
write_nic_byte(dev, (SW_3W_DB0+idx), *(pDataBuf+idx));
}
- } else { /* read */
- if (bSI) {
- /* SI - reg274[3:0] : RF register's Address */
+ } else { /* read */
+ if (bSI) {
+ /* SI - reg274[3:0] : RF register's Address */
write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
- } else {
+ } else {
/* PI - reg274[15:12] : RF register's Address */
write_nic_word(dev, SW_3W_DB0, (*((u16 *)pDataBuf)) << 12);
}
@@ -343,7 +305,7 @@ HwHSSIThreeWire(
/* Check if DONE is set. */
- for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
+ for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
if ((u1bTmp & SW_3W_CMD1_DONE) != 0)
break;
@@ -353,12 +315,12 @@ HwHSSIThreeWire(
write_nic_byte(dev, SW_3W_CMD1, 0);
- /* Read back data for read operation. */
- if (bWrite == 0) {
- if (bSI) {
+ /* Read back data for read operation. */
+ if (bWrite == 0) {
+ if (bSI) {
/* Serial Interface : reg363_362[11:0] */
*((u16 *)pDataBuf) = read_nic_word(dev, SI_DATA_READ) ;
- } else {
+ } else {
/* Parallel Interface : reg361_360[11:0] */
*((u16 *)pDataBuf) = read_nic_word(dev, PI_DATA_READ);
}
@@ -366,13 +328,12 @@ HwHSSIThreeWire(
*((u16 *)pDataBuf) &= 0x0FFF;
}
- } while (0);
+ } while (0);
return bResult;
}
-void
-RF_WriteReg(struct net_device *dev, u8 offset, u32 data)
+void RF_WriteReg(struct net_device *dev, u8 offset, u32 data)
{
u32 data2Write;
u8 len;
@@ -400,11 +361,7 @@ u32 RF_ReadReg(struct net_device *dev, u8 offset)
/* by Owen on 04/07/14 for writing BB register successfully */
-void
-WriteBBPortUchar(
- struct net_device *dev,
- u32 Data
- )
+void WriteBBPortUchar(struct net_device *dev, u32 Data)
{
/* u8 TimeoutCounter; */
u8 RegisterContent;
@@ -421,11 +378,7 @@ WriteBBPortUchar(
}
}
-u8
-ReadBBPortUchar(
- struct net_device *dev,
- u32 addr
- )
+u8 ReadBBPortUchar(struct net_device *dev, u32 addr)
{
/*u8 TimeoutCounter; */
u8 RegisterContent;
@@ -435,66 +388,62 @@ ReadBBPortUchar(
return RegisterContent;
}
-/* {by amy 080312 */
/*
- Description:
- Perform Antenna settings with antenna diversity on 87SE.
- Created by Roger, 2008.01.25.
-*/
-bool
-SetAntennaConfig87SE(
- struct net_device *dev,
- u8 DefaultAnt, /* 0: Main, 1: Aux. */
- bool bAntDiversity /* 1:Enable, 0: Disable. */
-)
+ * Description:
+ * Perform Antenna settings with antenna diversity on 87SE.
+ * Created by Roger, 2008.01.25.
+ */
+bool SetAntennaConfig87SE(struct net_device *dev,
+ u8 DefaultAnt, /* 0: Main, 1: Aux. */
+ bool bAntDiversity) /* 1:Enable, 0: Disable. */
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
bool bAntennaSwitched = true;
/* printk("SetAntennaConfig87SE(): DefaultAnt(%d), bAntDiversity(%d)\n", DefaultAnt, bAntDiversity); */
- /* Threshold for antenna diversity. */
+ /* Threshold for antenna diversity. */
write_phy_cck(dev, 0x0c, 0x09); /* Reg0c : 09 */
- if (bAntDiversity) { /* Enable Antenna Diversity. */
- if (DefaultAnt == 1) { /* aux antenna */
+ if (bAntDiversity) { /* Enable Antenna Diversity. */
+ if (DefaultAnt == 1) { /* aux antenna */
- /* Mac register, aux antenna */
+ /* Mac register, aux antenna */
write_nic_byte(dev, ANTSEL, 0x00);
- /* Config CCK RX antenna. */
+ /* Config CCK RX antenna. */
write_phy_cck(dev, 0x11, 0xbb); /* Reg11 : bb */
write_phy_cck(dev, 0x01, 0xc7); /* Reg01 : c7 */
- /* Config OFDM RX antenna. */
- write_phy_ofdm(dev, 0x0D, 0x54); /* Reg0d : 54 */
- write_phy_ofdm(dev, 0x18, 0xb2); /* Reg18 : b2 */
- } else { /* use main antenna */
- /* Mac register, main antenna */
+ /* Config OFDM RX antenna. */
+ write_phy_ofdm(dev, 0x0D, 0x54); /* Reg0d : 54 */
+ write_phy_ofdm(dev, 0x18, 0xb2); /* Reg18 : b2 */
+ } else { /* use main antenna */
+ /* Mac register, main antenna */
write_nic_byte(dev, ANTSEL, 0x03);
- /* base band */
- /* Config CCK RX antenna. */
- write_phy_cck(dev, 0x11, 0x9b); /* Reg11 : 9b */
- write_phy_cck(dev, 0x01, 0xc7); /* Reg01 : c7 */
+ /* base band */
+ /* Config CCK RX antenna. */
+ write_phy_cck(dev, 0x11, 0x9b); /* Reg11 : 9b */
+ write_phy_cck(dev, 0x01, 0xc7); /* Reg01 : c7 */
/* Config OFDM RX antenna. */
write_phy_ofdm(dev, 0x0d, 0x5c); /* Reg0d : 5c */
write_phy_ofdm(dev, 0x18, 0xb2); /* Reg18 : b2 */
}
- } else {
+ } else {
/* Disable Antenna Diversity. */
- if (DefaultAnt == 1) { /* aux Antenna */
+ if (DefaultAnt == 1) { /* aux Antenna */
/* Mac register, aux antenna */
write_nic_byte(dev, ANTSEL, 0x00);
/* Config CCK RX antenna. */
- write_phy_cck(dev, 0x11, 0xbb); /* Reg11 : bb */
- write_phy_cck(dev, 0x01, 0x47); /* Reg01 : 47 */
+ write_phy_cck(dev, 0x11, 0xbb); /* Reg11 : bb */
+ write_phy_cck(dev, 0x01, 0x47); /* Reg01 : 47 */
/* Config OFDM RX antenna. */
- write_phy_ofdm(dev, 0x0D, 0x54); /* Reg0d : 54 */
- write_phy_ofdm(dev, 0x18, 0x32); /* Reg18 : 32 */
- } else { /* main Antenna */
+ write_phy_ofdm(dev, 0x0D, 0x54); /* Reg0d : 54 */
+ write_phy_ofdm(dev, 0x18, 0x32); /* Reg18 : 32 */
+ } else { /* main Antenna */
/* Mac register, main antenna */
write_nic_byte(dev, ANTSEL, 0x03);
@@ -502,25 +451,22 @@ SetAntennaConfig87SE(
write_phy_cck(dev, 0x11, 0x9b); /* Reg11 : 9b */
write_phy_cck(dev, 0x01, 0x47); /* Reg01 : 47 */
- /* Config OFDM RX antenna. */
- write_phy_ofdm(dev, 0x0D, 0x5c); /* Reg0d : 5c */
- write_phy_ofdm(dev, 0x18, 0x32); /*Reg18 : 32 */
+ /* Config OFDM RX antenna. */
+ write_phy_ofdm(dev, 0x0D, 0x5c); /* Reg0d : 5c */
+ write_phy_ofdm(dev, 0x18, 0x32); /*Reg18 : 32 */
}
}
priv->CurrAntennaIndex = DefaultAnt; /* Update default settings. */
return bAntennaSwitched;
}
-/* by amy 080312 */
/*
----------------------------------------------------------------
- * Hardware Initialization.
- * the code is ported from Windows source code
-----------------------------------------------------------------*/
-
-void
-ZEBRA_Config_85BASIC_HardCode(
- struct net_device *dev
- )
+ *--------------------------------------------------------------
+ * Hardware Initialization.
+ * the code is ported from Windows source code
+ *--------------------------------------------------------------
+ */
+
+void ZEBRA_Config_85BASIC_HardCode(struct net_device *dev)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
@@ -532,163 +478,151 @@ ZEBRA_Config_85BASIC_HardCode(
/*
-=============================================================================
- 87S_PCIE :: RADIOCFG.TXT
-=============================================================================
-*/
+ *===========================================================================
+ * 87S_PCIE :: RADIOCFG.TXT
+ *===========================================================================
+ */
/* Page1 : reg16-reg30 */
- RF_WriteReg(dev, 0x00, 0x013f); mdelay(1); /* switch to page1 */
- u4bRF23 = RF_ReadReg(dev, 0x08); mdelay(1);
- u4bRF24 = RF_ReadReg(dev, 0x09); mdelay(1);
+ RF_WriteReg(dev, 0x00, 0x013f); mdelay(1); /* switch to page1 */
+ u4bRF23 = RF_ReadReg(dev, 0x08); mdelay(1);
+ u4bRF24 = RF_ReadReg(dev, 0x09); mdelay(1);
if (u4bRF23 == 0x818 && u4bRF24 == 0x70C) {
d_cut = 1;
printk(KERN_INFO "rtl8187se: card type changed from C- to D-cut\n");
}
- /* Page0 : reg0-reg15 */
-
- RF_WriteReg(dev, 0x00, 0x009f); mdelay(1);/* 1 */
-
- RF_WriteReg(dev, 0x01, 0x06e0); mdelay(1);
-
- RF_WriteReg(dev, 0x02, 0x004d); mdelay(1);/* 2 */
-
- RF_WriteReg(dev, 0x03, 0x07f1); mdelay(1);/* 3 */
-
- RF_WriteReg(dev, 0x04, 0x0975); mdelay(1);
- RF_WriteReg(dev, 0x05, 0x0c72); mdelay(1);
- RF_WriteReg(dev, 0x06, 0x0ae6); mdelay(1);
- RF_WriteReg(dev, 0x07, 0x00ca); mdelay(1);
- RF_WriteReg(dev, 0x08, 0x0e1c); mdelay(1);
- RF_WriteReg(dev, 0x09, 0x02f0); mdelay(1);
- RF_WriteReg(dev, 0x0a, 0x09d0); mdelay(1);
- RF_WriteReg(dev, 0x0b, 0x01ba); mdelay(1);
- RF_WriteReg(dev, 0x0c, 0x0640); mdelay(1);
- RF_WriteReg(dev, 0x0d, 0x08df); mdelay(1);
- RF_WriteReg(dev, 0x0e, 0x0020); mdelay(1);
- RF_WriteReg(dev, 0x0f, 0x0990); mdelay(1);
-
+ /* Page0 : reg0-reg15 */
+
+ RF_WriteReg(dev, 0x00, 0x009f); mdelay(1);/* 1 */
+ RF_WriteReg(dev, 0x01, 0x06e0); mdelay(1);
+ RF_WriteReg(dev, 0x02, 0x004d); mdelay(1);/* 2 */
+ RF_WriteReg(dev, 0x03, 0x07f1); mdelay(1);/* 3 */
+ RF_WriteReg(dev, 0x04, 0x0975); mdelay(1);
+ RF_WriteReg(dev, 0x05, 0x0c72); mdelay(1);
+ RF_WriteReg(dev, 0x06, 0x0ae6); mdelay(1);
+ RF_WriteReg(dev, 0x07, 0x00ca); mdelay(1);
+ RF_WriteReg(dev, 0x08, 0x0e1c); mdelay(1);
+ RF_WriteReg(dev, 0x09, 0x02f0); mdelay(1);
+ RF_WriteReg(dev, 0x0a, 0x09d0); mdelay(1);
+ RF_WriteReg(dev, 0x0b, 0x01ba); mdelay(1);
+ RF_WriteReg(dev, 0x0c, 0x0640); mdelay(1);
+ RF_WriteReg(dev, 0x0d, 0x08df); mdelay(1);
+ RF_WriteReg(dev, 0x0e, 0x0020); mdelay(1);
+ RF_WriteReg(dev, 0x0f, 0x0990); mdelay(1);
/* Page1 : reg16-reg30 */
- RF_WriteReg(dev, 0x00, 0x013f); mdelay(1);
-
- RF_WriteReg(dev, 0x03, 0x0806); mdelay(1);
-
- RF_WriteReg(dev, 0x04, 0x03a7); mdelay(1);
- RF_WriteReg(dev, 0x05, 0x059b); mdelay(1);
- RF_WriteReg(dev, 0x06, 0x0081); mdelay(1);
-
-
- RF_WriteReg(dev, 0x07, 0x01A0); mdelay(1);
+ RF_WriteReg(dev, 0x00, 0x013f); mdelay(1);
+ RF_WriteReg(dev, 0x03, 0x0806); mdelay(1);
+ RF_WriteReg(dev, 0x04, 0x03a7); mdelay(1);
+ RF_WriteReg(dev, 0x05, 0x059b); mdelay(1);
+ RF_WriteReg(dev, 0x06, 0x0081); mdelay(1);
+ RF_WriteReg(dev, 0x07, 0x01A0); mdelay(1);
/* Don't write RF23/RF24 to make a difference between 87S C cut and D cut. asked by SD3 stevenl. */
- RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1);
- RF_WriteReg(dev, 0x0b, 0x0418); mdelay(1);
+ RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1);
+ RF_WriteReg(dev, 0x0b, 0x0418); mdelay(1);
if (d_cut) {
- RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1);
- RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1);
- RF_WriteReg(dev, 0x0e, 0x0807); mdelay(1); /* RX LO buffer */
- } else {
- RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1);
- RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1);
- RF_WriteReg(dev, 0x0e, 0x0806); mdelay(1); /* RX LO buffer */
+ RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1);
+ RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1);
+ RF_WriteReg(dev, 0x0e, 0x0807); mdelay(1); /* RX LO buffer */
+ } else {
+ RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1);
+ RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1);
+ RF_WriteReg(dev, 0x0e, 0x0806); mdelay(1); /* RX LO buffer */
}
- RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1);
-
- RF_WriteReg(dev, 0x00, 0x01d7); mdelay(1); /* 6 */
+ RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1);
+ RF_WriteReg(dev, 0x00, 0x01d7); mdelay(1); /* 6 */
+ RF_WriteReg(dev, 0x03, 0x0e00); mdelay(1);
+ RF_WriteReg(dev, 0x04, 0x0e50); mdelay(1);
- RF_WriteReg(dev, 0x03, 0x0e00); mdelay(1);
- RF_WriteReg(dev, 0x04, 0x0e50); mdelay(1);
- for (i = 0; i <= 36; i++) {
- RF_WriteReg(dev, 0x01, i); mdelay(1);
+ for (i = 0; i <= 36; i++) {
+ RF_WriteReg(dev, 0x01, i); mdelay(1);
RF_WriteReg(dev, 0x02, ZEBRA_RF_RX_GAIN_TABLE[i]); mdelay(1);
}
- RF_WriteReg(dev, 0x05, 0x0203); mdelay(1); /* 203, 343 */
- RF_WriteReg(dev, 0x06, 0x0200); mdelay(1); /* 400 */
+ RF_WriteReg(dev, 0x05, 0x0203); mdelay(1); /* 203, 343 */
+ RF_WriteReg(dev, 0x06, 0x0200); mdelay(1); /* 400 */
+ RF_WriteReg(dev, 0x00, 0x0137); mdelay(1); /* switch to reg16-reg30, and HSSI disable 137 */
+ mdelay(10); /* Deay 10 ms. */ /* 0xfd */
- RF_WriteReg(dev, 0x00, 0x0137); mdelay(1); /* switch to reg16-reg30, and HSSI disable 137 */
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
+ RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1); /* Z4 synthesizer loop filter setting, 392 */
+ mdelay(10); /* Deay 10 ms. */ /* 0xfd */
- RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1); /* Z4 synthesizer loop filter setting, 392 */
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
+ RF_WriteReg(dev, 0x00, 0x0037); mdelay(1); /* switch to reg0-reg15, and HSSI disable */
+ mdelay(10); /* Deay 10 ms. */ /* 0xfd */
- RF_WriteReg(dev, 0x00, 0x0037); mdelay(1); /* switch to reg0-reg15, and HSSI disable */
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
+ RF_WriteReg(dev, 0x04, 0x0160); mdelay(1); /* CBC on, Tx Rx disable, High gain */
+ mdelay(10); /* Deay 10 ms. */ /* 0xfd */
- RF_WriteReg(dev, 0x04, 0x0160); mdelay(1); /* CBC on, Tx Rx disable, High gain */
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
+ RF_WriteReg(dev, 0x07, 0x0080); mdelay(1); /* Z4 setted channel 1 */
+ mdelay(10); /* Deay 10 ms. */ /* 0xfd */
- RF_WriteReg(dev, 0x07, 0x0080); mdelay(1); /* Z4 setted channel 1 */
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
+ RF_WriteReg(dev, 0x02, 0x088D); mdelay(1); /* LC calibration */
+ mdelay(200); /* Deay 200 ms. */ /* 0xfd */
+ mdelay(10); /* Deay 10 ms. */ /* 0xfd */
+ mdelay(10); /* Deay 10 ms. */ /* 0xfd */
- RF_WriteReg(dev, 0x02, 0x088D); mdelay(1); /* LC calibration */
- mdelay(200); /* Deay 200 ms. */ /* 0xfd */
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
+ RF_WriteReg(dev, 0x00, 0x0137); mdelay(1); /* switch to reg16-reg30 137, and HSSI disable 137 */
+ mdelay(10); /* Deay 10 ms. */ /* 0xfd */
- RF_WriteReg(dev, 0x00, 0x0137); mdelay(1); /* switch to reg16-reg30 137, and HSSI disable 137 */
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
-
- RF_WriteReg(dev, 0x07, 0x0000); mdelay(1);
- RF_WriteReg(dev, 0x07, 0x0180); mdelay(1);
- RF_WriteReg(dev, 0x07, 0x0220); mdelay(1);
- RF_WriteReg(dev, 0x07, 0x03E0); mdelay(1);
+ RF_WriteReg(dev, 0x07, 0x0000); mdelay(1);
+ RF_WriteReg(dev, 0x07, 0x0180); mdelay(1);
+ RF_WriteReg(dev, 0x07, 0x0220); mdelay(1);
+ RF_WriteReg(dev, 0x07, 0x03E0); mdelay(1);
/* DAC calibration off 20070702 */
- RF_WriteReg(dev, 0x06, 0x00c1); mdelay(1);
- RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1);
-/* {by amy 080312 */
+ RF_WriteReg(dev, 0x06, 0x00c1); mdelay(1);
+ RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1);
/* For crystal calibration, added by Roger, 2007.12.11. */
- if (priv->bXtalCalibration) { /* reg 30. */
- /* enable crystal calibration.
- RF Reg[30], (1)Xin:[12:9], Xout:[8:5], addr[4:0].
- (2)PA Pwr delay timer[15:14], default: 2.4us, set BIT15=0
- (3)RF signal on/off when calibration[13], default: on, set BIT13=0.
- So we should minus 4 BITs offset. */
- RF_WriteReg(dev, 0x0f, (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) | BIT11 | BIT9); mdelay(1);
+ if (priv->bXtalCalibration) { /* reg 30. */
+ /*
+ * enable crystal calibration.
+ * RF Reg[30], (1)Xin:[12:9], Xout:[8:5], addr[4:0].
+ * (2)PA Pwr delay timer[15:14], default: 2.4us, set BIT15=0
+ * (3)RF signal on/off when calibration[13], default: on, set BIT13=0.
+ * So we should minus 4 BITs offset.
+ */
+ RF_WriteReg(dev, 0x0f, (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) | BIT11 | BIT9); mdelay(1);
printk("ZEBRA_Config_85BASIC_HardCode(): (%02x)\n",
- (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) | BIT11 | BIT9);
- } else {
+ (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) | BIT11 | BIT9);
+ } else {
/* using default value. Xin=6, Xout=6. */
- RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1);
+ RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1);
}
-/* by amy 080312 */
- RF_WriteReg(dev, 0x00, 0x00bf); mdelay(1); /* switch to reg0-reg15, and HSSI enable */
- RF_WriteReg(dev, 0x0d, 0x08df); mdelay(1); /* Rx BB start calibration, 00c//+edward */
- RF_WriteReg(dev, 0x02, 0x004d); mdelay(1); /* temperature meter off */
- RF_WriteReg(dev, 0x04, 0x0975); mdelay(1); /* Rx mode */
+ RF_WriteReg(dev, 0x00, 0x00bf); mdelay(1); /* switch to reg0-reg15, and HSSI enable */
+ RF_WriteReg(dev, 0x0d, 0x08df); mdelay(1); /* Rx BB start calibration, 00c//+edward */
+ RF_WriteReg(dev, 0x02, 0x004d); mdelay(1); /* temperature meter off */
+ RF_WriteReg(dev, 0x04, 0x0975); mdelay(1); /* Rx mode */
mdelay(10); /* Deay 10 ms.*/ /* 0xfe */
mdelay(10); /* Deay 10 ms.*/ /* 0xfe */
mdelay(10); /* Deay 10 ms.*/ /* 0xfe */
- RF_WriteReg(dev, 0x00, 0x0197); mdelay(1); /* Rx mode*/ /*+edward */
- RF_WriteReg(dev, 0x05, 0x05ab); mdelay(1); /* Rx mode*/ /*+edward */
- RF_WriteReg(dev, 0x00, 0x009f); mdelay(1); /* Rx mode*/ /*+edward */
-
- RF_WriteReg(dev, 0x01, 0x0000); mdelay(1); /* Rx mode*/ /*+edward */
- RF_WriteReg(dev, 0x02, 0x0000); mdelay(1); /* Rx mode*/ /*+edward */
- /* power save parameters. */
+ RF_WriteReg(dev, 0x00, 0x0197); mdelay(1); /* Rx mode*/ /*+edward */
+ RF_WriteReg(dev, 0x05, 0x05ab); mdelay(1); /* Rx mode*/ /*+edward */
+ RF_WriteReg(dev, 0x00, 0x009f); mdelay(1); /* Rx mode*/ /*+edward */
+ RF_WriteReg(dev, 0x01, 0x0000); mdelay(1); /* Rx mode*/ /*+edward */
+ RF_WriteReg(dev, 0x02, 0x0000); mdelay(1); /* Rx mode*/ /*+edward */
+ /* power save parameters. */
u1b24E = read_nic_byte(dev, 0x24E);
write_nic_byte(dev, 0x24E, (u1b24E & (~(BIT5|BIT6))));
/*=============================================================================
-
- =============================================================================
- CCKCONF.TXT
- =============================================================================
- */
- /* [POWER SAVE] Power Saving Parameters by jong. 2007-11-27
- CCK reg0x00[7]=1'b1 :power saving for TX (default)
- CCK reg0x00[6]=1'b1: power saving for RX (default)
- CCK reg0x06[4]=1'b1: turn off channel estimation related circuits if not doing channel estimation.
- CCK reg0x06[3]=1'b1: turn off unused circuits before cca = 1
- CCK reg0x06[2]=1'b1: turn off cck's circuit if macrst =0
- */
+ *
+ *===========================================================================
+ * CCKCONF.TXT
+ *===========================================================================
+ *
+ * [POWER SAVE] Power Saving Parameters by jong. 2007-11-27
+ * CCK reg0x00[7]=1'b1 :power saving for TX (default)
+ * CCK reg0x00[6]=1'b1: power saving for RX (default)
+ * CCK reg0x06[4]=1'b1: turn off channel estimation related circuits if not doing channel estimation.
+ * CCK reg0x06[3]=1'b1: turn off unused circuits before cca = 1
+ * CCK reg0x06[2]=1'b1: turn off cck's circuit if macrst =0
+ */
write_phy_cck(dev, 0x00, 0xc8);
write_phy_cck(dev, 0x06, 0x1c);
@@ -697,7 +631,7 @@ ZEBRA_Config_85BASIC_HardCode(
write_phy_cck(dev, 0x2f, 0x06);
write_phy_cck(dev, 0x01, 0x46);
- /* power control */
+ /* power control */
write_nic_byte(dev, CCK_TXAGC, 0x10);
write_nic_byte(dev, OFDM_TXAGC, 0x1B);
write_nic_byte(dev, ANTSEL, 0x03);
@@ -705,14 +639,14 @@ ZEBRA_Config_85BASIC_HardCode(
/*
- =============================================================================
- AGC.txt
- =============================================================================
- */
+ *===========================================================================
+ * AGC.txt
+ *===========================================================================
+ */
write_phy_ofdm(dev, 0x00, 0x12);
- for (i = 0; i < 128; i++) {
+ for (i = 0; i < 128; i++) {
data = ZEBRA_AGC[i+1];
data = data << 8;
@@ -730,49 +664,43 @@ ZEBRA_Config_85BASIC_HardCode(
PlatformIOWrite4Byte(dev, PhyAddr, 0x00001080); /* Annie, 2006-05-05 */
/*
- =============================================================================
-
- =============================================================================
- OFDMCONF.TXT
- =============================================================================
- */
-
- for (i = 0; i < 60; i++) {
+ *===========================================================================
+ *
+ *===========================================================================
+ * OFDMCONF.TXT
+ *===========================================================================
+ */
+
+ for (i = 0; i < 60; i++) {
u4bRegOffset = i;
u4bRegValue = OFDM_CONFIG[i];
WriteBBPortUchar(dev,
- (0x00000080 |
- (u4bRegOffset & 0x7f) |
- ((u4bRegValue & 0xff) << 8)));
+ (0x00000080 |
+ (u4bRegOffset & 0x7f) |
+ ((u4bRegValue & 0xff) << 8)));
}
/*
- =============================================================================
- by amy for antenna
- =============================================================================
- */
-/* {by amy 080312 */
+ *===========================================================================
+ * by amy for antenna
+ *===========================================================================
+ */
/* Config Sw/Hw Combinational Antenna Diversity. Added by Roger, 2008.02.26. */
SetAntennaConfig87SE(dev, priv->bDefaultAntenna1, priv->bSwAntennaDiverity);
-/* by amy 080312} */
-/* by amy for antenna */
}
-void
-UpdateInitialGain(
- struct net_device *dev
- )
+void UpdateInitialGain(struct net_device *dev)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
/* lzm add 080826 */
- if (priv->eRFPowerState != eRfOn) {
+ if (priv->eRFPowerState != eRfOn) {
/* Don't access BB/RF under disable PLL situation.
- RT_TRACE(COMP_DIG, DBG_LOUD, ("UpdateInitialGain - pHalData->eRFPowerState!=eRfOn\n"));
- Back to the original state
- */
+ * RT_TRACE(COMP_DIG, DBG_LOUD, ("UpdateInitialGain - pHalData->eRFPowerState!=eRfOn\n"));
+ * Back to the original state
+ */
priv->InitialGain = priv->InitialGainBackUp;
return;
}
@@ -826,7 +754,7 @@ UpdateInitialGain(
write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1);
break;
- default: /* MP */
+ default: /* MP */
write_phy_ofdm(dev, 0x17, 0x26); mdelay(1);
write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1);
@@ -834,14 +762,11 @@ UpdateInitialGain(
}
}
/*
- Description:
- Tx Power tracking mechanism routine on 87SE.
- Created by Roger, 2007.12.11.
-*/
-void
-InitTxPwrTracking87SE(
- struct net_device *dev
-)
+ * Description:
+ * Tx Power tracking mechanism routine on 87SE.
+ * Created by Roger, 2007.12.11.
+ */
+void InitTxPwrTracking87SE(struct net_device *dev)
{
u32 u4bRfReg;
@@ -851,49 +776,41 @@ InitTxPwrTracking87SE(
RF_WriteReg(dev, 0x02, u4bRfReg|PWR_METER_EN); mdelay(1);
}
-void
-PhyConfig8185(
- struct net_device *dev
- )
+void PhyConfig8185(struct net_device *dev)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
write_nic_dword(dev, RCR, priv->ReceiveConfig);
priv->RFProgType = read_nic_byte(dev, CONFIG4) & 0x03;
/* RF config */
ZEBRA_Config_85BASIC_HardCode(dev);
-/* {by amy 080312 */
/* Set default initial gain state to 4, approved by SD3 DZ, by Bruce, 2007-06-06. */
- if (priv->bDigMechanism) {
+ if (priv->bDigMechanism) {
if (priv->InitialGain == 0)
priv->InitialGain = 4;
}
/*
- Enable thermal meter indication to implement TxPower tracking on 87SE.
- We initialize thermal meter here to avoid unsuccessful configuration.
- Added by Roger, 2007.12.11.
- */
+ * Enable thermal meter indication to implement TxPower tracking on 87SE.
+ * We initialize thermal meter here to avoid unsuccessful configuration.
+ * Added by Roger, 2007.12.11.
+ */
if (priv->bTxPowerTrack)
InitTxPwrTracking87SE(dev);
-/* by amy 080312} */
priv->InitialGainBackUp = priv->InitialGain;
UpdateInitialGain(dev);
return;
}
-void
-HwConfigureRTL8185(
- struct net_device *dev
- )
+void HwConfigureRTL8185(struct net_device *dev)
{
/* RTL8185_TODO: Determine Retrylimit, TxAGC, AutoRateFallback control. */
- u8 bUNIVERSAL_CONTROL_RL = 0;
- u8 bUNIVERSAL_CONTROL_AGC = 1;
- u8 bUNIVERSAL_CONTROL_ANT = 1;
- u8 bAUTO_RATE_FALLBACK_CTL = 1;
- u8 val8;
+ u8 bUNIVERSAL_CONTROL_RL = 0;
+ u8 bUNIVERSAL_CONTROL_AGC = 1;
+ u8 bUNIVERSAL_CONTROL_ANT = 1;
+ u8 bAUTO_RATE_FALLBACK_CTL = 1;
+ u8 val8;
write_nic_word(dev, BRSR, 0x0fff);
/* Retry limit */
val8 = read_nic_byte(dev, CW_CONF);
@@ -907,24 +824,24 @@ HwConfigureRTL8185(
/* Tx AGC */
val8 = read_nic_byte(dev, TXAGC_CTL);
- if (bUNIVERSAL_CONTROL_AGC) {
+ if (bUNIVERSAL_CONTROL_AGC) {
write_nic_byte(dev, CCK_TXAGC, 128);
write_nic_byte(dev, OFDM_TXAGC, 128);
val8 = val8 & 0xfe;
- } else {
+ } else {
val8 = val8 | 0x01 ;
}
write_nic_byte(dev, TXAGC_CTL, val8);
- /* Tx Antenna including Feedback control */
+ /* Tx Antenna including Feedback control */
val8 = read_nic_byte(dev, TXAGC_CTL);
- if (bUNIVERSAL_CONTROL_ANT) {
+ if (bUNIVERSAL_CONTROL_ANT) {
write_nic_byte(dev, ANTSEL, 0x00);
val8 = val8 & 0xfd;
- } else {
+ } else {
val8 = val8 & (val8|0x02); /* xiong-2006-11-15 */
}
@@ -933,7 +850,7 @@ HwConfigureRTL8185(
/* Auto Rate fallback control */
val8 = read_nic_byte(dev, RATE_FALLBACK);
val8 &= 0x7c;
- if (bAUTO_RATE_FALLBACK_CTL) {
+ if (bAUTO_RATE_FALLBACK_CTL) {
val8 |= RATE_FALLBACK_CTL_ENABLE | RATE_FALLBACK_CTL_AUTO_STEP1;
/* <RJ_TODO_8185B> We shall set up the ARFR according to user's setting. */
@@ -942,40 +859,34 @@ HwConfigureRTL8185(
write_nic_byte(dev, RATE_FALLBACK, val8);
}
-static void
-MacConfig_85BASIC_HardCode(
- struct net_device *dev)
+static void MacConfig_85BASIC_HardCode(struct net_device *dev)
{
/*
- ============================================================================
- MACREG.TXT
- ============================================================================
- */
- int nLinesRead = 0;
-
- u32 u4bRegOffset, u4bRegValue, u4bPageIndex = 0;
- int i;
+ *==========================================================================
+ * MACREG.TXT
+ *==========================================================================
+ */
+ int nLinesRead = 0;
+ u32 u4bRegOffset, u4bRegValue, u4bPageIndex = 0;
+ int i;
nLinesRead = sizeof(MAC_REG_TABLE)/2;
- for (i = 0; i < nLinesRead; i++) { /* nLinesRead=101 */
+ for (i = 0; i < nLinesRead; i++) { /* nLinesRead=101 */
u4bRegOffset = MAC_REG_TABLE[i][0];
u4bRegValue = MAC_REG_TABLE[i][1];
if (u4bRegOffset == 0x5e)
u4bPageIndex = u4bRegValue;
-
else
- u4bRegOffset |= (u4bPageIndex << 8);
+ u4bRegOffset |= (u4bPageIndex << 8);
write_nic_byte(dev, u4bRegOffset, (u8)u4bRegValue);
}
/* ============================================================================ */
}
-static void
-MacConfig_85BASIC(
- struct net_device *dev)
+static void MacConfig_85BASIC(struct net_device *dev)
{
u8 u1DA;
@@ -994,18 +905,18 @@ MacConfig_85BASIC(
PlatformIOWrite4Byte(dev, 0x1F4, 0x00000000);
PlatformIOWrite1Byte(dev, 0x1F8, 0x00);
- /* Asked for by SD3 CM Lin, 2006.06.27, by rcnjko. */
- /* power save parameter based on "87SE power save parameters 20071127.doc", as follow. */
+ /* Asked for by SD3 CM Lin, 2006.06.27, by rcnjko. */
+ /* power save parameter based on "87SE power save parameters 20071127.doc", as follow. */
/* Enable DA10 TX power saving */
u1DA = read_nic_byte(dev, PHYPR);
write_nic_byte(dev, PHYPR, (u1DA | BIT2));
- /* POWER: */
+ /* POWER: */
write_nic_word(dev, 0x360, 0x1000);
write_nic_word(dev, 0x362, 0x1000);
- /* AFE. */
+ /* AFE. */
write_nic_word(dev, 0x370, 0x0560);
write_nic_word(dev, 0x372, 0x0560);
write_nic_word(dev, 0x374, 0x0DA4);
@@ -1013,54 +924,48 @@ MacConfig_85BASIC(
write_nic_word(dev, 0x378, 0x0560);
write_nic_word(dev, 0x37A, 0x0560);
write_nic_word(dev, 0x37C, 0x00EC);
- write_nic_word(dev, 0x37E, 0x00EC); /*+edward */
+ write_nic_word(dev, 0x37E, 0x00EC); /* +edward */
write_nic_byte(dev, 0x24E, 0x01);
}
-u8
-GetSupportedWirelessMode8185(
- struct net_device *dev
-)
+u8 GetSupportedWirelessMode8185(struct net_device *dev)
{
- u8 btSupportedWirelessMode = 0;
+ u8 btSupportedWirelessMode = 0;
btSupportedWirelessMode = (WIRELESS_MODE_B | WIRELESS_MODE_G);
return btSupportedWirelessMode;
}
-void
-ActUpdateChannelAccessSetting(
- struct net_device *dev,
- WIRELESS_MODE WirelessMode,
- PCHANNEL_ACCESS_SETTING ChnlAccessSetting
- )
+void ActUpdateChannelAccessSetting(struct net_device *dev,
+ WIRELESS_MODE WirelessMode,
+ PCHANNEL_ACCESS_SETTING ChnlAccessSetting)
{
- struct r8180_priv *priv = ieee80211_priv(dev);
- struct ieee80211_device *ieee = priv->ieee80211;
+ struct r8180_priv *priv = ieee80211_priv(dev);
+ struct ieee80211_device *ieee = priv->ieee80211;
AC_CODING eACI;
AC_PARAM AcParam;
- u8 bFollowLegacySetting = 0;
- u8 u1bAIFS;
+ u8 bFollowLegacySetting = 0;
+ u8 u1bAIFS;
/*
- <RJ_TODO_8185B>
- TODO: We still don't know how to set up these registers, just follow WMAC to
- verify 8185B FPAG.
-
- <RJ_TODO_8185B>
- Jong said CWmin/CWmax register are not functional in 8185B,
- so we shall fill channel access realted register into AC parameter registers,
- even in nQBss.
- */
+ * <RJ_TODO_8185B>
+ * TODO: We still don't know how to set up these registers, just follow WMAC to
+ * verify 8185B FPAG.
+ *
+ * <RJ_TODO_8185B>
+ * Jong said CWmin/CWmax register are not functional in 8185B,
+ * so we shall fill channel access realted register into AC parameter registers,
+ * even in nQBss.
+ */
ChnlAccessSetting->SIFS_Timer = 0x22; /* Suggested by Jong, 2005.12.08. */
- ChnlAccessSetting->DIFS_Timer = 0x1C; /* 2006.06.02, by rcnjko. */
- ChnlAccessSetting->SlotTimeTimer = 9; /* 2006.06.02, by rcnjko. */
- ChnlAccessSetting->EIFS_Timer = 0x5B; /* Suggested by wcchu, it is the default value of EIFS register, 2005.12.08. */
- ChnlAccessSetting->CWminIndex = 3; /* 2006.06.02, by rcnjko. */
- ChnlAccessSetting->CWmaxIndex = 7; /* 2006.06.02, by rcnjko. */
+ ChnlAccessSetting->DIFS_Timer = 0x1C; /* 2006.06.02, by rcnjko. */
+ ChnlAccessSetting->SlotTimeTimer = 9; /* 2006.06.02, by rcnjko. */
+ ChnlAccessSetting->EIFS_Timer = 0x5B; /* Suggested by wcchu, it is the default value of EIFS register, 2005.12.08. */
+ ChnlAccessSetting->CWminIndex = 3; /* 2006.06.02, by rcnjko. */
+ ChnlAccessSetting->CWmaxIndex = 7; /* 2006.06.02, by rcnjko. */
write_nic_byte(dev, SIFS, ChnlAccessSetting->SIFS_Timer);
- write_nic_byte(dev, SLOT, ChnlAccessSetting->SlotTimeTimer); /* Rewrited from directly use PlatformEFIOWrite1Byte(), by Annie, 2006-03-29. */
+ write_nic_byte(dev, SLOT, ChnlAccessSetting->SlotTimeTimer); /* Rewrited from directly use PlatformEFIOWrite1Byte(), by Annie, 2006-03-29. */
u1bAIFS = aSifsTime + (2 * ChnlAccessSetting->SlotTimeTimer);
@@ -1074,17 +979,17 @@ ActUpdateChannelAccessSetting(
}
/* this setting is copied from rtl8187B. xiong-2006-11-13 */
- if (bFollowLegacySetting) {
+ if (bFollowLegacySetting) {
/*
- Follow 802.11 seeting to AC parameter, all AC shall use the same parameter.
- 2005.12.01, by rcnjko.
- */
+ * Follow 802.11 seeting to AC parameter, all AC shall use the same parameter.
+ * 2005.12.01, by rcnjko.
+ */
AcParam.longData = 0;
AcParam.f.AciAifsn.f.AIFSN = 2; /* Follow 802.11 DIFS. */
AcParam.f.AciAifsn.f.ACM = 0;
- AcParam.f.Ecw.f.ECWmin = ChnlAccessSetting->CWminIndex; /* Follow 802.11 CWmin. */
- AcParam.f.Ecw.f.ECWmax = ChnlAccessSetting->CWmaxIndex; /* Follow 802.11 CWmax. */
+ AcParam.f.Ecw.f.ECWmin = ChnlAccessSetting->CWminIndex; /* Follow 802.11 CWmin. */
+ AcParam.f.Ecw.f.ECWmax = ChnlAccessSetting->CWmaxIndex; /* Follow 802.11 CWmax. */
AcParam.f.TXOPLimit = 0;
/* lzm reserved 080826 */
@@ -1095,7 +1000,7 @@ ActUpdateChannelAccessSetting(
if (ieee->iw_mode == IW_MODE_ADHOC)
AcParam.f.TXOPLimit = 0x0020;
- for (eACI = 0; eACI < AC_MAX; eACI++) {
+ for (eACI = 0; eACI < AC_MAX; eACI++) {
AcParam.f.AciAifsn.f.ACI = (u8)eACI;
{
PAC_PARAM pAcParam = (PAC_PARAM)(&AcParam);
@@ -1103,7 +1008,7 @@ ActUpdateChannelAccessSetting(
u8 u1bAIFS;
u32 u4bAcParam;
- /* Retrive paramters to udpate. */
+ /* Retrieve paramters to update. */
eACI = pAcParam->f.AciAifsn.f.ACI;
u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * ChnlAccessSetting->SlotTimeTimer + aSifsTime;
u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit)) << AC_PARAM_TXOP_LIMIT_OFFSET) |
@@ -1111,7 +1016,7 @@ ActUpdateChannelAccessSetting(
(((u32)(pAcParam->f.Ecw.f.ECWmin)) << AC_PARAM_ECW_MIN_OFFSET) |
(((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET));
- switch (eACI) {
+ switch (eACI) {
case AC1_BK:
/* write_nic_dword(dev, AC_BK_PARAM, u4bAcParam); */
break;
@@ -1133,47 +1038,46 @@ ActUpdateChannelAccessSetting(
break;
}
- /* Cehck ACM bit. */
+ /* Cehck ACM bit. */
/* If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13. */
{
PACI_AIFSN pAciAifsn = (PACI_AIFSN)(&pAcParam->f.AciAifsn);
AC_CODING eACI = pAciAifsn->f.ACI;
- /*modified Joseph */
- /*for 8187B AsynIORead issue */
+ /*for 8187B AsynIORead issue */
u8 AcmCtrl = 0;
- if (pAciAifsn->f.ACM) {
+ if (pAciAifsn->f.ACM) {
/* ACM bit is 1. */
- switch (eACI) {
+ switch (eACI) {
case AC0_BE:
- AcmCtrl |= (BEQ_ACM_EN|BEQ_ACM_CTL|ACM_HW_EN); /* or 0x21 */
+ AcmCtrl |= (BEQ_ACM_EN|BEQ_ACM_CTL|ACM_HW_EN); /* or 0x21 */
break;
case AC2_VI:
- AcmCtrl |= (VIQ_ACM_EN|VIQ_ACM_CTL|ACM_HW_EN); /* or 0x42 */
+ AcmCtrl |= (VIQ_ACM_EN|VIQ_ACM_CTL|ACM_HW_EN); /* or 0x42 */
break;
case AC3_VO:
- AcmCtrl |= (VOQ_ACM_EN|VOQ_ACM_CTL|ACM_HW_EN); /* or 0x84 */
+ AcmCtrl |= (VOQ_ACM_EN|VOQ_ACM_CTL|ACM_HW_EN); /* or 0x84 */
break;
default:
DMESGW("SetHwReg8185(): [HW_VAR_ACM_CTRL] ACM set failed: eACI is %d\n", eACI);
break;
}
- } else {
+ } else {
/* ACM bit is 0. */
- switch (eACI) {
+ switch (eACI) {
case AC0_BE:
- AcmCtrl &= ((~BEQ_ACM_EN) & (~BEQ_ACM_CTL) & (~ACM_HW_EN)); /* and 0xDE */
+ AcmCtrl &= ((~BEQ_ACM_EN) & (~BEQ_ACM_CTL) & (~ACM_HW_EN)); /* and 0xDE */
break;
case AC2_VI:
- AcmCtrl &= ((~VIQ_ACM_EN) & (~VIQ_ACM_CTL) & (~ACM_HW_EN)); /* and 0xBD */
+ AcmCtrl &= ((~VIQ_ACM_EN) & (~VIQ_ACM_CTL) & (~ACM_HW_EN)); /* and 0xBD */
break;
case AC3_VO:
- AcmCtrl &= ((~VOQ_ACM_EN) & (~VOQ_ACM_CTL) & (~ACM_HW_EN)); /* and 0x7B */
+ AcmCtrl &= ((~VOQ_ACM_EN) & (~VOQ_ACM_CTL) & (~ACM_HW_EN)); /* and 0x7B */
break;
default:
@@ -1187,53 +1091,51 @@ ActUpdateChannelAccessSetting(
}
}
-void
-ActSetWirelessMode8185(
- struct net_device *dev,
- u8 btWirelessMode
- )
+void ActSetWirelessMode8185(struct net_device *dev, u8 btWirelessMode)
{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- struct ieee80211_device *ieee = priv->ieee80211;
+ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
+ struct ieee80211_device *ieee = priv->ieee80211;
u8 btSupportedWirelessMode = GetSupportedWirelessMode8185(dev);
if ((btWirelessMode & btSupportedWirelessMode) == 0) {
- /* Don't switch to unsupported wireless mode, 2006.02.15, by rcnjko. */
+ /* Don't switch to unsupported wireless mode, 2006.02.15, by rcnjko. */
DMESGW("ActSetWirelessMode8185(): WirelessMode(%d) is not supported (%d)!\n",
btWirelessMode, btSupportedWirelessMode);
return;
}
- /* 1. Assign wireless mode to swtich if necessary. */
- if (btWirelessMode == WIRELESS_MODE_AUTO) {
- if ((btSupportedWirelessMode & WIRELESS_MODE_A)) {
+ /* 1. Assign wireless mode to switch if necessary. */
+ if (btWirelessMode == WIRELESS_MODE_AUTO) {
+ if ((btSupportedWirelessMode & WIRELESS_MODE_A)) {
btWirelessMode = WIRELESS_MODE_A;
- } else if (btSupportedWirelessMode & WIRELESS_MODE_G) {
+ } else if (btSupportedWirelessMode & WIRELESS_MODE_G) {
btWirelessMode = WIRELESS_MODE_G;
- } else if ((btSupportedWirelessMode & WIRELESS_MODE_B)) {
- btWirelessMode = WIRELESS_MODE_B;
- } else {
- DMESGW("ActSetWirelessMode8185(): No valid wireless mode supported, btSupportedWirelessMode(%x)!!!\n",
- btSupportedWirelessMode);
+ } else if ((btSupportedWirelessMode & WIRELESS_MODE_B)) {
btWirelessMode = WIRELESS_MODE_B;
+ } else {
+ DMESGW("ActSetWirelessMode8185(): No valid wireless mode supported, btSupportedWirelessMode(%x)!!!\n",
+ btSupportedWirelessMode);
+ btWirelessMode = WIRELESS_MODE_B;
}
}
- /* 2. Swtich band: RF or BB specific actions,
+ /*
+ * 2. Swtich band: RF or BB specific actions,
* for example, refresh tables in omc8255, or change initial gain if necessary.
* Nothing to do for Zebra to switch band.
- * Update current wireless mode if we swtich to specified band successfully. */
+ * Update current wireless mode if we switch to specified band successfully.
+ */
ieee->mode = (WIRELESS_MODE)btWirelessMode;
- /* 3. Change related setting. */
- if( ieee->mode == WIRELESS_MODE_A ) {
+ /* 3. Change related setting. */
+ if( ieee->mode == WIRELESS_MODE_A ) {
DMESG("WIRELESS_MODE_A\n");
- } else if( ieee->mode == WIRELESS_MODE_B ) {
- DMESG("WIRELESS_MODE_B\n");
- } else if( ieee->mode == WIRELESS_MODE_G ) {
- DMESG("WIRELESS_MODE_G\n");
+ } else if( ieee->mode == WIRELESS_MODE_B ) {
+ DMESG("WIRELESS_MODE_B\n");
+ } else if( ieee->mode == WIRELESS_MODE_G ) {
+ DMESG("WIRELESS_MODE_G\n");
}
ActUpdateChannelAccessSetting( dev, ieee->mode, &priv->ChannelAccessSetting);
}
@@ -1245,22 +1147,16 @@ void rtl8185b_irq_enable(struct net_device *dev)
priv->irq_enabled = 1;
write_nic_dword(dev, IMR, priv->IntrMask);
}
-/* by amy for power save */
-void
-DrvIFIndicateDisassociation(
- struct net_device *dev,
- u16 reason
- )
+
+void DrvIFIndicateDisassociation(struct net_device *dev, u16 reason)
{
/* nothing is needed after disassociation request. */
- }
-void
-MgntDisconnectIBSS(
- struct net_device *dev
-)
+}
+
+void MgntDisconnectIBSS(struct net_device *dev)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- u8 i;
+ u8 i;
DrvIFIndicateDisassociation(dev, unspec_reason);
@@ -1271,166 +1167,143 @@ MgntDisconnectIBSS(
priv->ieee80211->state = IEEE80211_NOLINK;
/*
- Stop Beacon.
-
- Vista add a Adhoc profile, HW radio off until OID_DOT11_RESET_REQUEST
- Driver would set MSR=NO_LINK, then HW Radio ON, MgntQueue Stuck.
- Because Bcn DMA isn't complete, mgnt queue would stuck until Bcn packet send.
-
- Disable Beacon Queue Own bit, suggested by jong */
+ * Stop Beacon.
+ *
+ * Vista add a Adhoc profile, HW radio off until OID_DOT11_RESET_REQUEST
+ * Driver would set MSR=NO_LINK, then HW Radio ON, MgntQueue Stuck.
+ * Because Bcn DMA isn't complete, mgnt queue would stuck until Bcn packet send.
+ *
+ * Disable Beacon Queue Own bit, suggested by jong
+ */
ieee80211_stop_send_beacons(priv->ieee80211);
priv->ieee80211->link_change(dev);
notify_wx_assoc_event(priv->ieee80211);
}
-void
-MlmeDisassociateRequest(
- struct net_device *dev,
- u8 *asSta,
- u8 asRsn
- )
+
+void MlmeDisassociateRequest(struct net_device *dev, u8 *asSta, u8 asRsn)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
u8 i;
SendDisassociation(priv->ieee80211, asSta, asRsn);
- if (memcmp(priv->ieee80211->current_network.bssid, asSta, 6) == 0) {
- /*ShuChen TODO: change media status. */
- /*ShuChen TODO: What to do when disassociate. */
+ if (memcmp(priv->ieee80211->current_network.bssid, asSta, 6) == 0) {
+ /* ShuChen TODO: change media status. */
+ /* ShuChen TODO: What to do when disassociate. */
DrvIFIndicateDisassociation(dev, unspec_reason);
-
-
for (i = 0; i < 6; i++)
priv->ieee80211->current_network.bssid[i] = 0x22;
ieee80211_disassociate(priv->ieee80211);
}
-
}
-void
-MgntDisconnectAP(
- struct net_device *dev,
- u8 asRsn
-)
+void MgntDisconnectAP(struct net_device *dev, u8 asRsn)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
/*
- Commented out by rcnjko, 2005.01.27:
- I move SecClearAllKeys() to MgntActSet_802_11_DISASSOCIATE().
-
- 2004/09/15, kcwu, the key should be cleared, or the new handshaking will not success
-
- In WPA WPA2 need to Clear all key ... because new key will set after new handshaking.
- 2004.10.11, by rcnjko. */
+ * Commented out by rcnjko, 2005.01.27:
+ * I move SecClearAllKeys() to MgntActSet_802_11_DISASSOCIATE().
+ *
+ * 2004/09/15, kcwu, the key should be cleared, or the new handshaking will not success
+ *
+ * In WPA WPA2 need to Clear all key ... because new key will set after new handshaking.
+ * 2004.10.11, by rcnjko.
+ */
MlmeDisassociateRequest(dev, priv->ieee80211->current_network.bssid, asRsn);
priv->ieee80211->state = IEEE80211_NOLINK;
}
-bool
-MgntDisconnect(
- struct net_device *dev,
- u8 asRsn
-)
+
+bool MgntDisconnect(struct net_device *dev, u8 asRsn)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
/*
- Schedule an workitem to wake up for ps mode, 070109, by rcnjko.
- */
+ * Schedule an workitem to wake up for ps mode, 070109, by rcnjko.
+ */
if (IS_DOT11D_ENABLE(priv->ieee80211))
Dot11d_Reset(priv->ieee80211);
- /* In adhoc mode, update beacon frame. */
+ /* In adhoc mode, update beacon frame. */
if (priv->ieee80211->state == IEEE80211_LINKED) {
if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
MgntDisconnectIBSS(dev);
- if (priv->ieee80211->iw_mode == IW_MODE_INFRA) {
- /* We clear key here instead of MgntDisconnectAP() because that
- MgntActSet_802_11_DISASSOCIATE() is an interface called by OS,
- e.g. OID_802_11_DISASSOCIATE in Windows while as MgntDisconnectAP() is
- used to handle disassociation related things to AP, e.g. send Disassoc
- frame to AP. 2005.01.27, by rcnjko. */
+ if (priv->ieee80211->iw_mode == IW_MODE_INFRA) {
+ /*
+ * We clear key here instead of MgntDisconnectAP() because that
+ * MgntActSet_802_11_DISASSOCIATE() is an interface called by OS,
+ * e.g. OID_802_11_DISASSOCIATE in Windows while as MgntDisconnectAP() is
+ * used to handle disassociation related things to AP, e.g. send Disassoc
+ * frame to AP. 2005.01.27, by rcnjko.
+ */
MgntDisconnectAP(dev, asRsn);
}
- /* Inidicate Disconnect, 2005.02.23, by rcnjko. */
+ /* Indicate Disconnect, 2005.02.23, by rcnjko. */
}
return true;
}
/*
- Description:
- Chang RF Power State.
- Note that, only MgntActSet_RF_State() is allowed to set HW_VAR_RF_STATE.
-
- Assumption:
- PASSIVE LEVEL.
-*/
-bool
-SetRFPowerState(
- struct net_device *dev,
- RT_RF_POWER_STATE eRFPowerState
- )
+ * Description:
+ * Chang RF Power State.
+ * Note that, only MgntActSet_RF_State() is allowed to set HW_VAR_RF_STATE.
+ *
+ * Assumption:
+ * PASSIVE LEVEL.
+ */
+bool SetRFPowerState(struct net_device *dev, RT_RF_POWER_STATE eRFPowerState)
{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- bool bResult = false;
+ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
+ bool bResult = false;
if (eRFPowerState == priv->eRFPowerState)
return bResult;
- bResult = SetZebraRFPowerState8185(dev, eRFPowerState);
+ bResult = SetZebraRFPowerState8185(dev, eRFPowerState);
return bResult;
}
-void
-HalEnableRx8185Dummy(
- struct net_device *dev
- )
+
+void HalEnableRx8185Dummy(struct net_device *dev)
{
}
-void
-HalDisableRx8185Dummy(
- struct net_device *dev
- )
+
+void HalDisableRx8185Dummy(struct net_device *dev)
{
}
-bool
-MgntActSet_RF_State(
- struct net_device *dev,
- RT_RF_POWER_STATE StateToSet,
- u32 ChangeSource
- )
+bool MgntActSet_RF_State(struct net_device *dev, RT_RF_POWER_STATE StateToSet, u32 ChangeSource)
{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- bool bActionAllowed = false;
- bool bConnectBySSID = false;
- RT_RF_POWER_STATE rtState;
- u16 RFWaitCounter = 0;
+ struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
+ bool bActionAllowed = false;
+ bool bConnectBySSID = false;
+ RT_RF_POWER_STATE rtState;
+ u16 RFWaitCounter = 0;
unsigned long flag;
/*
- Prevent the race condition of RF state change. By Bruce, 2007-11-28.
- Only one thread can change the RF state at one time, and others should wait to be executed.
- */
- while (true) {
+ * Prevent the race condition of RF state change. By Bruce, 2007-11-28.
+ * Only one thread can change the RF state at one time, and others should wait to be executed.
+ */
+ while (true) {
spin_lock_irqsave(&priv->rf_ps_lock, flag);
- if (priv->RFChangeInProgress) {
+ if (priv->RFChangeInProgress) {
spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
/* Set RF after the previous action is done. */
- while (priv->RFChangeInProgress) {
+ while (priv->RFChangeInProgress) {
RFWaitCounter++;
udelay(1000); /* 1 ms */
- /* Wait too long, return FALSE to avoid to be stuck here. */
- if (RFWaitCounter > 1000) { /* 1sec */
+ /* Wait too long, return FALSE to avoid to be stuck here. */
+ if (RFWaitCounter > 1000) { /* 1sec */
printk("MgntActSet_RF_State(): Wait too long to set RF\n");
- /* TODO: Reset RF state? */
+ /* TODO: Reset RF state? */
return false;
}
}
- } else {
+ } else {
priv->RFChangeInProgress = true;
spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
break;
@@ -1438,12 +1311,12 @@ MgntActSet_RF_State(
}
rtState = priv->eRFPowerState;
- switch (StateToSet) {
+ switch (StateToSet) {
case eRfOn:
/*
- Turn On RF no matter the IPS setting because we need to update the RF state to Ndis under Vista, or
- the Windows does not allow the driver to perform site survey any more. By Bruce, 2007-10-02.
- */
+ * Turn On RF no matter the IPS setting because we need to update the RF state to Ndis under Vista, or
+ * the Windows does not allow the driver to perform site survey any more. By Bruce, 2007-10-02.
+ */
priv->RfOffReason &= (~ChangeSource);
if (!priv->RfOffReason) {
@@ -1453,25 +1326,24 @@ MgntActSet_RF_State(
if (rtState == eRfOff && ChangeSource >= RF_CHANGE_BY_HW && !priv->bInHctTest)
bConnectBySSID = true;
- } else
- ;
+ } else
+ ;
break;
case eRfOff:
- /* 070125, rcnjko: we always keep connected in AP mode. */
-
- if (priv->RfOffReason > RF_CHANGE_BY_IPS) {
- /*
- 060808, Annie:
- Disconnect to current BSS when radio off. Asked by QuanTa.
-
- Calling MgntDisconnect() instead of MgntActSet_802_11_DISASSOCIATE(),
- because we do NOT need to set ssid to dummy ones.
- */
- MgntDisconnect(dev, disas_lv_ss);
-
- /* Clear content of bssDesc[] and bssDesc4Query[] to avoid reporting old bss to UI. */
- }
+ /* 070125, rcnjko: we always keep connected in AP mode. */
+
+ if (priv->RfOffReason > RF_CHANGE_BY_IPS) {
+ /*
+ * 060808, Annie:
+ * Disconnect to current BSS when radio off. Asked by QuanTa.
+ *
+ * Calling MgntDisconnect() instead of MgntActSet_802_11_DISASSOCIATE(),
+ * because we do NOT need to set ssid to dummy ones.
+ */
+ MgntDisconnect(dev, disas_lv_ss);
+ /* Clear content of bssDesc[] and bssDesc4Query[] to avoid reporting old bss to UI. */
+ }
priv->RfOffReason |= ChangeSource;
bActionAllowed = true;
@@ -1484,14 +1356,14 @@ MgntActSet_RF_State(
break;
}
- if (bActionAllowed) {
- /* Config HW to the specified mode. */
+ if (bActionAllowed) {
+ /* Config HW to the specified mode. */
SetRFPowerState(dev, StateToSet);
/* Turn on RF. */
- if (StateToSet == eRfOn) {
+ if (StateToSet == eRfOn) {
HalEnableRx8185Dummy(dev);
- if (bConnectBySSID) {
+ if (bConnectBySSID) {
/* by amy not supported */
}
}
@@ -1507,69 +1379,61 @@ MgntActSet_RF_State(
spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
return bActionAllowed;
}
-void
-InactivePowerSave(
- struct net_device *dev
- )
+
+void InactivePowerSave(struct net_device *dev)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
/*
- This flag "bSwRfProcessing", indicates the status of IPS procedure, should be set if the IPS workitem
- is really scheduled.
- The old code, sets this flag before scheduling the IPS workitem and however, at the same time the
- previous IPS workitem did not end yet, fails to schedule the current workitem. Thus, bSwRfProcessing
- blocks the IPS procedure of switching RF.
- */
+ * This flag "bSwRfProcessing", indicates the status of IPS procedure, should be set if the IPS workitem
+ * is really scheduled.
+ * The old code, sets this flag before scheduling the IPS workitem and however, at the same time the
+ * previous IPS workitem did not end yet, fails to schedule the current workitem. Thus, bSwRfProcessing
+ * blocks the IPS procedure of switching RF.
+ */
priv->bSwRfProcessing = true;
MgntActSet_RF_State(dev, priv->eInactivePowerState, RF_CHANGE_BY_IPS);
/*
- To solve CAM values miss in RF OFF, rewrite CAM values after RF ON. By Bruce, 2007-09-20.
- */
+ * To solve CAM values miss in RF OFF, rewrite CAM values after RF ON. By Bruce, 2007-09-20.
+ */
priv->bSwRfProcessing = false;
}
/*
- Description:
- Enter the inactive power save mode. RF will be off
-*/
-void
-IPSEnter(
- struct net_device *dev
- )
+ * Description:
+ * Enter the inactive power save mode. RF will be off
+ */
+void IPSEnter(struct net_device *dev)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
RT_RF_POWER_STATE rtState;
- if (priv->bInactivePs) {
+ if (priv->bInactivePs) {
rtState = priv->eRFPowerState;
/*
- Do not enter IPS in the following conditions:
- (1) RF is already OFF or Sleep
- (2) bSwRfProcessing (indicates the IPS is still under going)
- (3) Connectted (only disconnected can trigger IPS)
- (4) IBSS (send Beacon)
- (5) AP mode (send Beacon)
- */
+ * Do not enter IPS in the following conditions:
+ * (1) RF is already OFF or Sleep
+ * (2) bSwRfProcessing (indicates the IPS is still under going)
+ * (3) Connected (only disconnected can trigger IPS)
+ * (4) IBSS (send Beacon)
+ * (5) AP mode (send Beacon)
+ */
if (rtState == eRfOn && !priv->bSwRfProcessing
- && (priv->ieee80211->state != IEEE80211_LINKED)) {
+ && (priv->ieee80211->state != IEEE80211_LINKED)) {
priv->eInactivePowerState = eRfOff;
InactivePowerSave(dev);
}
}
}
-void
-IPSLeave(
- struct net_device *dev
- )
+void IPSLeave(struct net_device *dev)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
RT_RF_POWER_STATE rtState;
- if (priv->bInactivePs) {
+ if (priv->bInactivePs) {
rtState = priv->eRFPowerState;
- if ((rtState == eRfOff || rtState == eRfSleep) && (!priv->bSwRfProcessing) && priv->RfOffReason <= RF_CHANGE_BY_IPS) {
+ if ((rtState == eRfOff || rtState == eRfSleep) && (!priv->bSwRfProcessing) && priv->RfOffReason <= RF_CHANGE_BY_IPS) {
priv->eInactivePowerState = eRfOn;
InactivePowerSave(dev);
}
@@ -1582,8 +1446,8 @@ void rtl8185b_adapter_start(struct net_device *dev)
struct ieee80211_device *ieee = priv->ieee80211;
u8 SupportedWirelessMode;
- u8 InitWirelessMode;
- u8 bInvalidWirelessMode = 0;
+ u8 InitWirelessMode;
+ u8 bInvalidWirelessMode = 0;
u8 tmpu8;
u8 btCR9346;
u8 TmpU1b;
@@ -1598,89 +1462,89 @@ void rtl8185b_adapter_start(struct net_device *dev)
HwConfigureRTL8185(dev);
write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
write_nic_word(dev, MAC4, ((u32 *)dev->dev_addr)[1] & 0xffff);
- write_nic_byte(dev, MSR, read_nic_byte(dev, MSR) & 0xf3); /* default network type to 'No Link' */
+ write_nic_byte(dev, MSR, read_nic_byte(dev, MSR) & 0xf3); /* default network type to 'No Link' */
write_nic_word(dev, BcnItv, 100);
write_nic_word(dev, AtimWnd, 2);
PlatformIOWrite2Byte(dev, FEMR, 0xFFFF);
write_nic_byte(dev, WPA_CONFIG, 0);
MacConfig_85BASIC(dev);
- /* Override the RFSW_CTRL (MAC offset 0x272-0x273), 2006.06.07, by rcnjko. */
- /* BT_DEMO_BOARD type */
+ /* Override the RFSW_CTRL (MAC offset 0x272-0x273), 2006.06.07, by rcnjko. */
+ /* BT_DEMO_BOARD type */
PlatformIOWrite2Byte(dev, RFSW_CTRL, 0x569a);
/*
- -----------------------------------------------------------------------------
- Set up PHY related.
- -----------------------------------------------------------------------------
- */
- /* Enable Config3.PARAM_En to revise AnaaParm. */
- write_nic_byte(dev, CR9346, 0xc0); /* enable config register write */
+ *---------------------------------------------------------------------------
+ * Set up PHY related.
+ *---------------------------------------------------------------------------
+ */
+ /* Enable Config3.PARAM_En to revise AnaaParm. */
+ write_nic_byte(dev, CR9346, 0xc0); /* enable config register write */
tmpu8 = read_nic_byte(dev, CONFIG3);
write_nic_byte(dev, CONFIG3, (tmpu8 | CONFIG3_PARM_En));
- /* Turn on Analog power. */
- /* Asked for by William, otherwise, MAC 3-wire can't work, 2006.06.27, by rcnjko. */
+ /* Turn on Analog power. */
+ /* Asked for by William, otherwise, MAC 3-wire can't work, 2006.06.27, by rcnjko. */
write_nic_dword(dev, ANAPARAM2, ANAPARM2_ASIC_ON);
write_nic_dword(dev, ANAPARAM, ANAPARM_ASIC_ON);
write_nic_word(dev, ANAPARAM3, 0x0010);
write_nic_byte(dev, CONFIG3, tmpu8);
write_nic_byte(dev, CR9346, 0x00);
- /* enable EEM0 and EEM1 in 9346CR */
+ /* enable EEM0 and EEM1 in 9346CR */
btCR9346 = read_nic_byte(dev, CR9346);
write_nic_byte(dev, CR9346, (btCR9346 | 0xC0));
- /* B cut use LED1 to control HW RF on/off */
+ /* B cut use LED1 to control HW RF on/off */
TmpU1b = read_nic_byte(dev, CONFIG5);
TmpU1b = TmpU1b & ~BIT3;
write_nic_byte(dev, CONFIG5, TmpU1b);
- /* disable EEM0 and EEM1 in 9346CR */
+ /* disable EEM0 and EEM1 in 9346CR */
btCR9346 &= ~(0xC0);
write_nic_byte(dev, CR9346, btCR9346);
- /* Enable Led (suggested by Jong) */
- /* B-cut RF Radio on/off 5e[3]=0 */
+ /* Enable Led (suggested by Jong) */
+ /* B-cut RF Radio on/off 5e[3]=0 */
btPSR = read_nic_byte(dev, PSR);
write_nic_byte(dev, PSR, (btPSR | BIT3));
- /* setup initial timing for RFE. */
+ /* setup initial timing for RFE. */
write_nic_word(dev, RFPinsOutput, 0x0480);
SetOutputEnableOfRfPins(dev);
write_nic_word(dev, RFPinsSelect, 0x2488);
- /* PHY config. */
+ /* PHY config. */
PhyConfig8185(dev);
/*
- We assume RegWirelessMode has already been initialized before,
- however, we has to validate the wireless mode here and provide a
- reasonable initialized value if necessary. 2005.01.13, by rcnjko.
- */
+ * We assume RegWirelessMode has already been initialized before,
+ * however, we has to validate the wireless mode here and provide a
+ * reasonable initialized value if necessary. 2005.01.13, by rcnjko.
+ */
SupportedWirelessMode = GetSupportedWirelessMode8185(dev);
if ((ieee->mode != WIRELESS_MODE_B) &&
(ieee->mode != WIRELESS_MODE_G) &&
(ieee->mode != WIRELESS_MODE_A) &&
- (ieee->mode != WIRELESS_MODE_AUTO)) {
- /* It should be one of B, G, A, or AUTO. */
+ (ieee->mode != WIRELESS_MODE_AUTO)) {
+ /* It should be one of B, G, A, or AUTO. */
bInvalidWirelessMode = 1;
- } else {
- /* One of B, G, A, or AUTO. */
- /* Check if the wireless mode is supported by RF. */
+ } else {
+ /* One of B, G, A, or AUTO. */
+ /* Check if the wireless mode is supported by RF. */
if ((ieee->mode != WIRELESS_MODE_AUTO) &&
- (ieee->mode & SupportedWirelessMode) == 0) {
+ (ieee->mode & SupportedWirelessMode) == 0) {
bInvalidWirelessMode = 1;
}
}
- if (bInvalidWirelessMode || ieee->mode == WIRELESS_MODE_AUTO) {
- /* Auto or other invalid value. */
- /* Assigne a wireless mode to initialize. */
- if ((SupportedWirelessMode & WIRELESS_MODE_A)) {
+ if (bInvalidWirelessMode || ieee->mode == WIRELESS_MODE_AUTO) {
+ /* Auto or other invalid value. */
+ /* Assigne a wireless mode to initialize. */
+ if ((SupportedWirelessMode & WIRELESS_MODE_A)) {
InitWirelessMode = WIRELESS_MODE_A;
- } else if ((SupportedWirelessMode & WIRELESS_MODE_G)) {
+ } else if ((SupportedWirelessMode & WIRELESS_MODE_G)) {
InitWirelessMode = WIRELESS_MODE_G;
- } else if ((SupportedWirelessMode & WIRELESS_MODE_B)) {
+ } else if ((SupportedWirelessMode & WIRELESS_MODE_B)) {
InitWirelessMode = WIRELESS_MODE_B;
- } else {
+ } else {
DMESGW("InitializeAdapter8185(): No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n",
SupportedWirelessMode);
InitWirelessMode = WIRELESS_MODE_B;
@@ -1690,24 +1554,21 @@ void rtl8185b_adapter_start(struct net_device *dev)
if (bInvalidWirelessMode)
ieee->mode = (WIRELESS_MODE)InitWirelessMode;
- } else {
- /* One of B, G, A. */
+ } else {
+ /* One of B, G, A. */
InitWirelessMode = ieee->mode;
}
-/* by amy for power save */
priv->eRFPowerState = eRfOff;
priv->RfOffReason = 0;
{
MgntActSet_RF_State(dev, eRfOn, 0);
}
/*
- If inactive power mode is enabled, disable rf while in disconnected state.
- */
+ * If inactive power mode is enabled, disable rf while in disconnected state.
+ */
if (priv->bInactivePs)
MgntActSet_RF_State(dev , eRfOff, RF_CHANGE_BY_IPS);
-/* by amy for power save */
-
ActSetWirelessMode8185(dev, (u8)(InitWirelessMode));
/* ----------------------------------------------------------------------------- */
@@ -1715,7 +1576,7 @@ void rtl8185b_adapter_start(struct net_device *dev)
rtl8185b_irq_enable(dev);
netif_start_queue(dev);
- }
+}
void rtl8185b_rx_enable(struct net_device *dev)
{
@@ -1728,7 +1589,7 @@ void rtl8185b_rx_enable(struct net_device *dev)
DMESG("NIC in promisc mode");
if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || \
- dev->flags & IFF_PROMISC) {
+ dev->flags & IFF_PROMISC) {
priv->ReceiveConfig = priv->ReceiveConfig & (~RCR_APM);
priv->ReceiveConfig = priv->ReceiveConfig | RCR_AAP;
}
diff --git a/drivers/staging/rtl8192e/Kconfig b/drivers/staging/rtl8192e/Kconfig
index f87e21101857..4602a47cdb4a 100644
--- a/drivers/staging/rtl8192e/Kconfig
+++ b/drivers/staging/rtl8192e/Kconfig
@@ -14,6 +14,7 @@ if RTLLIB
config RTLLIB_CRYPTO_CCMP
tristate "Support for rtllib CCMP crypto"
depends on RTLLIB
+ select CRYPTO_AES
default y
---help---
CCMP crypto driver for rtllib.
@@ -23,6 +24,8 @@ config RTLLIB_CRYPTO_CCMP
config RTLLIB_CRYPTO_TKIP
tristate "Support for rtllib TKIP crypto"
depends on RTLLIB
+ select CRYPTO_ARC4
+ select CRYPTO_MICHAEL_MIC
default y
---help---
TKIP crypto driver for rtllib.
@@ -31,6 +34,7 @@ config RTLLIB_CRYPTO_TKIP
config RTLLIB_CRYPTO_WEP
tristate "Support for rtllib WEP crypto"
+ select CRYPTO_ARC4
depends on RTLLIB
default y
---help---
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
index 58d044ea5524..ea91744f7ccf 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
@@ -342,7 +342,6 @@ static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg)
u32 cmpk_message_handle_rx(struct net_device *dev,
struct rtllib_rx_stats *pstats)
{
- struct r8192_priv *priv = rtllib_priv(dev);
int total_length;
u8 cmd_length, exe_cnt = 0;
u8 element_id;
@@ -409,8 +408,6 @@ u32 cmpk_message_handle_rx(struct net_device *dev,
return 1;
}
- priv->stats.rxcmdpkt[element_id]++;
-
total_length -= cmd_length;
pcmd_buff += cmd_length;
}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
index 37719859bdae..b526fa428679 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
@@ -216,7 +216,7 @@ static bool firmware_check_ready(struct net_device *dev,
break;
default:
rt_status = false;
- RT_TRACE(COMP_FIRMWARE, "Unknown firware status");
+ RT_TRACE(COMP_FIRMWARE, "Unknown firmware status");
break;
}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
index 3e705efaaf22..9676c591c859 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
@@ -689,7 +689,7 @@ void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel)
case RF_8258:
break;
default:
- RT_TRACE(COMP_ERR, "unknown rf chip in funtion %s()\n",
+ RT_TRACE(COMP_ERR, "unknown rf chip in function %s()\n",
__func__);
break;
}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r819xE_phyreg.h b/drivers/staging/rtl8192e/rtl8192e/r819xE_phyreg.h
index d5de279f6644..970298b07af7 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r819xE_phyreg.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r819xE_phyreg.h
@@ -306,7 +306,7 @@
#define bRFStart 0x0000f000
#define bBBStart 0x000000f0
#define bBBCCKStart 0x0000000f
-/* Reg)x814 */
+/* Reg x814 */
#define bPAEnd 0xf
#define bTREnd 0x0f000000
#define bRFEnd 0x000f0000
@@ -844,7 +844,7 @@
#define bRTL8258_RxLPFBW 0xc00
#define bRTL8258_RSSILPFBW 0xc0
-/* byte endable for sb_write */
+/* byte enable for sb_write */
#define bByte0 0x1
#define bByte1 0x2
#define bByte2 0x4
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index 71adb6b3344d..4f602b227b50 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -1025,7 +1025,7 @@ static int rtl8192_sta_down(struct net_device *dev, bool shutdownrf)
break;
}
RT_TRACE(COMP_DBG, "===>%s():RF is in progress, need to wait "
- "until rf chang is done.\n", __func__);
+ "until rf change is done.\n", __func__);
mdelay(1);
RFInProgressTimeOut++;
spin_lock_irqsave(&priv->rf_ps_lock, flags);
@@ -1211,7 +1211,7 @@ static void rtl8192_init_priv_variable(struct net_device *dev)
priv->AcmControl = 0;
priv->pFirmware = vzalloc(sizeof(struct rt_firmware));
if (!priv->pFirmware)
- printk(KERN_ERR "rtl8193e: Unable to allocate space "
+ printk(KERN_ERR "rtl8192e: Unable to allocate space "
"for firmware\n");
skb_queue_head_init(&priv->rx_queue);
@@ -2024,10 +2024,10 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
stype = WLAN_FC_GET_STYPE(fc);
pda_addr = header->addr1;
- if (is_multicast_ether_addr(pda_addr))
- multi_addr = true;
- else if (is_broadcast_ether_addr(pda_addr))
+ if (is_broadcast_ether_addr(pda_addr))
broad_addr = true;
+ else if (is_multicast_ether_addr(pda_addr))
+ multi_addr = true;
else
uni_addr = true;
@@ -2358,8 +2358,7 @@ static void rtl8192_rx_normal(struct net_device *dev)
stats.RxBufShift);
skb_trim(skb, skb->len - 4/*sCrcLng*/);
rtllib_hdr = (struct rtllib_hdr_1addr *)skb->data;
- if (!is_broadcast_ether_addr(rtllib_hdr->addr1) &&
- !is_multicast_ether_addr(rtllib_hdr->addr1)) {
+ if (!is_multicast_ether_addr(rtllib_hdr->addr1)) {
/* unicast packet */
unicast_packet = true;
}
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
index 2a2519cc284d..320d5fc026b4 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
@@ -353,7 +353,6 @@ struct rt_stats {
unsigned long rxrdu;
unsigned long rxok;
unsigned long rxframgment;
- unsigned long rxcmdpkt[8];
unsigned long rxurberr;
unsigned long rxstaterr;
unsigned long rxdatacrcerr;
@@ -944,7 +943,7 @@ struct r8192_priv {
bool bfsync_processing;
u32 rate_record;
u32 rateCountDiffRecord;
- u32 ContiuneDiffCount;
+ u32 ContinueDiffCount;
bool bswitch_fsync;
u8 framesync;
u32 framesyncC34;
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
index f026b7171f62..481b1e4d4913 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
@@ -493,7 +493,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
if (priv->bResetInProgress) {
RT_TRACE(COMP_POWER_TRACKING,
- "we are in slient reset progress, so return\n");
+ "we are in silent reset progress, so return\n");
write_nic_byte(dev, Pw_Track_Flag, 0);
write_nic_byte(dev, FW_Busy_Flag, 0);
return;
@@ -2615,22 +2615,22 @@ void dm_fsync_timer_callback(unsigned long data)
rate_count_diff;
if (DiffNum >=
priv->rtllib->fsync_seconddiff_ratethreshold)
- priv->ContiuneDiffCount++;
+ priv->ContinueDiffCount++;
else
- priv->ContiuneDiffCount = 0;
+ priv->ContinueDiffCount = 0;
- if (priv->ContiuneDiffCount >= 2) {
+ if (priv->ContinueDiffCount >= 2) {
bSwitchFromCountDiff = true;
- priv->ContiuneDiffCount = 0;
+ priv->ContinueDiffCount = 0;
}
} else {
- priv->ContiuneDiffCount = 0;
+ priv->ContinueDiffCount = 0;
}
if (rate_count_diff <=
priv->rtllib->fsync_firstdiff_ratethreshold) {
bSwitchFromCountDiff = true;
- priv->ContiuneDiffCount = 0;
+ priv->ContinueDiffCount = 0;
}
priv->rate_record = rate_count;
priv->rateCountDiffRecord = rate_count_diff;
@@ -2677,10 +2677,10 @@ void dm_fsync_timer_callback(unsigned long data)
write_nic_byte(dev, 0xC36, 0x5c);
write_nic_byte(dev, 0xC3e, 0x96);
}
- priv->ContiuneDiffCount = 0;
+ priv->ContinueDiffCount = 0;
write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
}
- RT_TRACE(COMP_HALDM, "ContiuneDiffCount %d\n", priv->ContiuneDiffCount);
+ RT_TRACE(COMP_HALDM, "ContinueDiffCount %d\n", priv->ContinueDiffCount);
RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d "
"bSwitchFsync %d\n", priv->rate_record, rate_count,
rate_count_diff, priv->bswitch_fsync);
@@ -2723,7 +2723,7 @@ static void dm_EndSWFsync(struct net_device *dev)
write_nic_byte(dev, 0xC3e, 0x96);
}
- priv->ContiuneDiffCount = 0;
+ priv->ContinueDiffCount = 0;
write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
}
@@ -2735,7 +2735,7 @@ static void dm_StartSWFsync(struct net_device *dev)
RT_TRACE(COMP_HALDM, "%s\n", __func__);
priv->rate_record = 0;
- priv->ContiuneDiffCount = 0;
+ priv->ContinueDiffCount = 0;
priv->rateCountDiffRecord = 0;
priv->bswitch_fsync = false;
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
index 4e93669210af..778d7baf8e08 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
@@ -1322,9 +1322,9 @@ static struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
struct iw_handler_def r8192_wx_handlers_def = {
.standard = r8192_wx_handlers,
- .num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler),
+ .num_standard = ARRAY_SIZE(r8192_wx_handlers),
.private = r8192_private_handler,
- .num_private = sizeof(r8192_private_handler) / sizeof(iw_handler),
+ .num_private = ARRAY_SIZE(r8192_private_handler),
.num_private_args = sizeof(r8192_private_args) /
sizeof(struct iw_priv_args),
.get_wireless_stats = r8192_get_wireless_stats,
diff --git a/drivers/staging/rtl8192e/rtl819x_TSProc.c b/drivers/staging/rtl8192e/rtl819x_TSProc.c
index 711a096be7a7..658e875232aa 100644
--- a/drivers/staging/rtl8192e/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192e/rtl819x_TSProc.c
@@ -310,7 +310,7 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
u8 *Addr, u8 TID, enum tr_select TxRxSelect, bool bAddNewTs)
{
u8 UP = 0;
- if (is_broadcast_ether_addr(Addr) || is_multicast_ether_addr(Addr)) {
+ if (is_multicast_ether_addr(Addr)) {
RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR! get TS for Broadcast or "
"Multicast\n");
return false;
diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h
index e26aec86a5c8..d7460ae3a765 100644
--- a/drivers/staging/rtl8192e/rtllib.h
+++ b/drivers/staging/rtl8192e/rtllib.h
@@ -169,7 +169,7 @@ struct cb_desc {
u8 nStuckCount;
- /* Tx Firmware Relaged flags (10-11)*/
+ /* Tx Firmware Related flags (10-11)*/
u8 bCTSEnable:1;
u8 bRTSEnable:1;
u8 bUseShortGI:1;
@@ -1690,7 +1690,7 @@ enum rtllib_state {
/* the association procedure is sending AUTH request*/
RTLLIB_ASSOCIATING_AUTHENTICATING,
- /* the association procedure has successfully authentcated
+ /* the association procedure has successfully authenticated
* and is sending association request
*/
RTLLIB_ASSOCIATING_AUTHENTICATED,
@@ -2409,7 +2409,7 @@ struct rtllib_device {
/* used instead of hard_start_xmit (not softmac_hard_start_xmit)
* if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data
- * frames. I the option IEEE_SOFTMAC_SINGLE_QUEUE is also set
+ * frames. If the option IEEE_SOFTMAC_SINGLE_QUEUE is also set
* then also management frames are sent via this callback.
* This function can't sleep.
*/
@@ -2422,12 +2422,12 @@ struct rtllib_device {
*/
void (*data_hard_stop)(struct net_device *dev);
- /* OK this is complementar to data_poll_hard_stop */
+ /* OK this is complementing to data_poll_hard_stop */
void (*data_hard_resume)(struct net_device *dev);
/* ask to the driver to retune the radio .
* This function can sleep. the driver should ensure
- * the radio has been swithced before return.
+ * the radio has been switched before return.
*/
void (*set_chan)(struct net_device *dev, short ch);
@@ -2438,7 +2438,7 @@ struct rtllib_device {
* The syncro version is similar to the start_scan but
* does not return until all channels has been scanned.
* this is called in user context and should sleep,
- * it is called in a work_queue when swithcing to ad-hoc mode
+ * it is called in a work_queue when switching to ad-hoc mode
* or in behalf of iwlist scan when the card is associated
* and root user ask for a scan.
* the fucntion stop_scan should stop both the syncro and
@@ -2481,7 +2481,7 @@ struct rtllib_device {
struct rtllib_network *network);
- /* check whether Tx hw resouce available */
+ /* check whether Tx hw resource available */
short (*check_nic_enough_desc)(struct net_device *dev, int queue_index);
short (*get_nic_desc_num)(struct net_device *dev, int queue_index);
void (*SetBWModeHandler)(struct net_device *dev,
@@ -2543,10 +2543,10 @@ struct rtllib_device {
/* Generate probe requests */
#define IEEE_SOFTMAC_PROBERQ (1<<4)
-/* Generate respones to probe requests */
+/* Generate response to probe requests */
#define IEEE_SOFTMAC_PROBERS (1<<5)
-/* The ieee802.11 stack will manages the netif queue
+/* The ieee802.11 stack will manage the netif queue
* wake/stop for the driver, taking care of 802.11
* fragmentation. See softmac.c for details. */
#define IEEE_SOFTMAC_TX_QUEUE (1<<7)
diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
index 13979b5ea32a..8b8a5c661a26 100644
--- a/drivers/staging/rtl8192e/rtllib_rx.c
+++ b/drivers/staging/rtl8192e/rtllib_rx.c
@@ -496,7 +496,7 @@ void rtllib_indicate_packets(struct rtllib_device *ieee, struct rtllib_rxb **prx
memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
}
- /* Indicat the packets to upper layer */
+ /* Indicate the packets to upper layer */
if (sub_skb) {
stats->rx_packets++;
stats->rx_bytes += sub_skb->len;
@@ -1000,7 +1000,7 @@ static int rtllib_rx_data_filter(struct rtllib_device *ieee, u16 fc,
return -1;
/* {broad,multi}cast packets to our BSS go through */
- if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst)) {
+ if (is_multicast_ether_addr(dst)) {
if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN))
return -1;
}
@@ -1233,7 +1233,7 @@ static void rtllib_rx_indicate_pkt_legacy(struct rtllib_device *ieee,
if (is_multicast_ether_addr(dst))
ieee->stats.multicast++;
- /* Indicat the packets to upper layer */
+ /* Indicate the packets to upper layer */
memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
sub_skb->protocol = eth_type_trans(sub_skb, dev);
sub_skb->dev = dev;
@@ -1269,7 +1269,7 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb,
sc = le16_to_cpu(hdr->seq_ctl);
/*Filter pkt not to me*/
- multicast = is_multicast_ether_addr(hdr->addr1)|is_broadcast_ether_addr(hdr->addr1);
+ multicast = is_multicast_ether_addr(hdr->addr1);
unicast = !multicast;
if (unicast && (compare_ether_addr(dev->dev_addr, hdr->addr1) != 0)) {
if (ieee->bNetPromiscuousMode)
@@ -1350,7 +1350,7 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb,
/* Get TS for Rx Reorder */
hdr = (struct rtllib_hdr_4addr *) skb->data;
if (ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data)
- && !is_multicast_ether_addr(hdr->addr1) && !is_broadcast_ether_addr(hdr->addr1)
+ && !is_multicast_ether_addr(hdr->addr1)
&& (!bToOtherSTA)) {
TID = Frame_QoSTID(skb->data);
SeqNum = WLAN_GET_SEQ_SEQ(sc);
diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c
index c5a15dba1bf5..a21b4d91a596 100644
--- a/drivers/staging/rtl8192e/rtllib_softmac.c
+++ b/drivers/staging/rtl8192e/rtllib_softmac.c
@@ -31,7 +31,7 @@ short rtllib_is_shortslot(const struct rtllib_network *net)
return net->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME;
}
-/* returns the total length needed for pleacing the RATE MFIE
+/* returns the total length needed for placing the RATE MFIE
* tag and the EXTENDED RATE MFIE tag if needed.
* It encludes two bytes per tag for the tag itself and its len
*/
@@ -49,7 +49,7 @@ static unsigned int rtllib_MFIE_rate_len(struct rtllib_device *ieee)
return rate_len;
}
-/* pleace the MFIE rate, tag to the memory (double) poined.
+/* place the MFIE rate, tag to the memory (double) pointed.
* Then it updates the pointer so that
* it points after the new MFIE tag added.
*/
@@ -557,7 +557,7 @@ void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
* new network events, despite for updating the net list,
* but we are temporarly 'unlinked' as the driver shall
* not filter RX frames and the channel is changing.
- * So the only situation in witch are interested is to check
+ * So the only situation in which are interested is to check
* if the state become LINKED because of the #1 situation
*/
@@ -1681,7 +1681,7 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee,
/* if the user set the AP check if match.
* if the network does not broadcast essid we check the
- * user supplyed ANY essid
+ * user supplied ANY essid
* if the network does broadcast and the user does not set
* essid it is OK
* if the network does broadcast and the user did set essid
@@ -2444,16 +2444,16 @@ inline int rtllib_rx_frame_softmac(struct rtllib_device *ieee,
/* following are for a simplier TX queue management.
* Instead of using netif_[stop/wake]_queue the driver
- * will uses these two function (plus a reset one), that
- * will internally uses the kernel netif_* and takes
+ * will use these two functions (plus a reset one), that
+ * will internally use the kernel netif_* and takes
* care of the ieee802.11 fragmentation.
* So the driver receives a fragment per time and might
- * call the stop function when it want without take care
- * to have enought room to TX an entire packet.
- * This might be useful if each fragment need it's own
+ * call the stop function when it wants to not
+ * have enough room to TX an entire packet.
+ * This might be useful if each fragment needs it's own
* descriptor, thus just keep a total free memory > than
- * the max fragmentation treshold is not enought.. If the
- * ieee802.11 stack passed a TXB struct then you needed
+ * the max fragmentation threshold is not enough.. If the
+ * ieee802.11 stack passed a TXB struct then you need
* to keep N free descriptors where
* N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
* In this way you need just one and the 802.11 stack
@@ -2696,15 +2696,15 @@ static void rtllib_start_ibss_wq(void *data)
rtllib_softmac_check_all_nets(ieee);
- /* if not then the state is not linked. Maybe the user swithced to
+ /* if not then the state is not linked. Maybe the user switched to
* ad-hoc mode just after being in monitor mode, or just after
* being very few time in managed mode (so the card have had no
* time to scan all the chans..) or we have just run up the iface
* after setting ad-hoc mode. So we have to give another try..
* Here, in ibss mode, should be safe to do this without extra care
- * (in bss mode we had to make sure no-one tryed to associate when
+ * (in bss mode we had to make sure no-one tried to associate when
* we had just checked the ieee->state and we was going to start the
- * scan) beacause in ibss mode the rtllib_new_net function, when
+ * scan) because in ibss mode the rtllib_new_net function, when
* finds a good net, just set the ieee->state to RTLLIB_LINKED,
* so, at worst, we waste a bit of time to initiate an unneeded syncro
* scan, that will stop at the first round because it sees the state
@@ -2819,7 +2819,7 @@ void rtllib_start_bss(struct rtllib_device *ieee)
/* ensure no-one start an associating process (thus setting
* the ieee->state to rtllib_ASSOCIATING) while we
- * have just cheked it and we are going to enable scan.
+ * have just checked it and we are going to enable scan.
* The rtllib_new_net function is always called with
* lock held (from both rtllib_softmac_check_all_nets and
* the rx path), so we cannot be in the middle of such function
@@ -2872,7 +2872,7 @@ static void rtllib_associate_retry_wq(void *data)
/* until we do not set the state to RTLLIB_NOLINK
* there are no possibility to have someone else trying
- * to start an association procdure (we get here with
+ * to start an association procedure (we get here with
* ieee->state = RTLLIB_ASSOCIATING).
* When we set the state to RTLLIB_NOLINK it is possible
* that the RX path run an attempt to associate, but
@@ -3679,8 +3679,7 @@ void rtllib_MlmeDisassociateRequest(struct rtllib_device *rtllib, u8 *asSta,
RemovePeerTS(rtllib, asSta);
-
- if (memcpy(rtllib->current_network.bssid, asSta, 6) == NULL) {
+ if (memcmp(rtllib->current_network.bssid, asSta, 6) == 0) {
rtllib->state = RTLLIB_NOLINK;
for (i = 0; i < 6; i++)
diff --git a/drivers/staging/rtl8192e/rtllib_softmac_wx.c b/drivers/staging/rtl8192e/rtllib_softmac_wx.c
index 1523bc7a2105..1bb6b52e0f24 100644
--- a/drivers/staging/rtl8192e/rtllib_softmac_wx.c
+++ b/drivers/staging/rtl8192e/rtllib_softmac_wx.c
@@ -479,7 +479,7 @@ int rtllib_wx_set_essid(struct rtllib_device *ieee,
/* this is just to be sure that the GET wx callback
- * has consisten infos. not needed otherwise
+ * has consistent infos. not needed otherwise
*/
spin_lock_irqsave(&ieee->lock, flags);
@@ -575,7 +575,7 @@ int rtllib_wx_set_power(struct rtllib_device *ieee,
if ((!ieee->sta_wake_up) ||
(!ieee->enter_sleep_state) ||
(!ieee->ps_is_queue_empty)) {
- RTLLIB_DEBUG(RTLLIB_DL_ERR, "%s(): PS mode is tryied to be use "
+ RTLLIB_DEBUG(RTLLIB_DL_ERR, "%s(): PS mode is tried to be use "
"but driver missed a callback\n\n", __func__);
return -1;
}
diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c
index f451bfc27a86..42900ee4825b 100644
--- a/drivers/staging/rtl8192e/rtllib_tx.c
+++ b/drivers/staging/rtl8192e/rtllib_tx.c
@@ -59,7 +59,7 @@
802.11 Data Frame
-802.11 frame_contorl for data frames - 2 bytes
+802.11 frame_control for data frames - 2 bytes
,-----------------------------------------------------------------------------------------.
bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e |
|----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
@@ -296,8 +296,7 @@ static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee,
return;
if (!IsQoSDataFrame(skb->data))
return;
- if (is_multicast_ether_addr(hdr->addr1) ||
- is_broadcast_ether_addr(hdr->addr1))
+ if (is_multicast_ether_addr(hdr->addr1))
return;
if (tcb_desc->bdhcp || ieee->CntAfterLink < 2)
@@ -515,7 +514,7 @@ u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb,
{
u16 seqnum = 0;
- if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst))
+ if (is_multicast_ether_addr(dst))
return 0;
if (IsQoSDataFrame(skb->data)) {
struct tx_ts_record *pTS = NULL;
@@ -576,7 +575,7 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave(&ieee->lock, flags);
- /* If there is no driver handler to take the TXB, dont' bother
+ /* If there is no driver handler to take the TXB, don't bother
* creating it... */
if ((!ieee->hard_start_xmit && !(ieee->softmac_features &
IEEE_SOFTMAC_TX_QUEUE)) ||
@@ -698,8 +697,7 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
ETH_ALEN);
}
- bIsMulticast = is_broadcast_ether_addr(header.addr1) ||
- is_multicast_ether_addr(header.addr1);
+ bIsMulticast = is_multicast_ether_addr(header.addr1);
header.frame_ctl = cpu_to_le16(fc);
@@ -738,7 +736,7 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
(CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
bytes_per_frag -= RTLLIB_FCS_LEN;
- /* Each fragment may need to have room for encryptiong
+ /* Each fragment may need to have room for encrypting
* pre/postfix */
if (encrypt) {
bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c
index c27ff7edbaf2..c7e8d4d8ec2b 100644
--- a/drivers/staging/rtl8192e/rtllib_wx.c
+++ b/drivers/staging/rtl8192e/rtllib_wx.c
@@ -88,7 +88,7 @@ static inline char *rtl819x_translate_scan(struct rtllib_device *ieee,
}
/* Add the protocol name */
iwe.cmd = SIOCGIWNAME;
- for (i = 0; i < (sizeof(rtllib_modes)/sizeof(rtllib_modes[0])); i++) {
+ for (i = 0; i < ARRAY_SIZE(rtllib_modes); i++) {
if (network->mode&(1<<i)) {
sprintf(pname, rtllib_modes[i].mode_string,
rtllib_modes[i].mode_size);
@@ -408,7 +408,7 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
(*crypt)->priv);
sec.flags |= (1 << key);
/* This ensures a key will be activated if no key is
- * explicitely set */
+ * explicitly set */
if (key == sec.active_key)
sec.flags |= SEC_ACTIVE_KEY;
ieee->crypt_info.tx_keyidx = key;
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
index e3d47bcf4cab..82d4bf6a86a5 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
@@ -161,7 +161,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
if (ieee->pHTInfo == NULL)
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for HTInfo\n");
- return NULL;
+ goto failed;
}
HTUpdateDefaultSetting(ieee);
HTInitializeHTInfo(ieee); //may move to other place.
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index be2a28cf8edd..e3cf7a45b900 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -671,7 +671,7 @@ void RxReorderIndicatePacket( struct ieee80211_device *ieee,
index = 1;
} else {
/* Current packet is going to be inserted into pending list.*/
- //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): We RX no ordered packed, insert to orderd list\n",__FUNCTION__);
+ //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): We RX no ordered packed, insert to ordered list\n",__FUNCTION__);
if(!list_empty(&ieee->RxReorder_Unused_List)) {
pReorderEntry = (PRX_REORDER_ENTRY)list_entry(ieee->RxReorder_Unused_List.next,RX_REORDER_ENTRY,List);
list_del_init(&pReorderEntry->List);
@@ -1285,7 +1285,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
*/
//added by amy for reorder
if(ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data)
- && !is_multicast_ether_addr(hdr->addr1) && !is_broadcast_ether_addr(hdr->addr1))
+ && !is_multicast_ether_addr(hdr->addr1))
{
TID = Frame_QoSTID(skb->data);
SeqNum = WLAN_GET_SEQ_SEQ(sc);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
index c2ab5fa15465..f6ff8cff313a 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
@@ -2062,7 +2062,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
}
}else{
ieee->softmac_stats.rx_auth_rs_err++;
- IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
+ IEEE80211_DEBUG_MGMT("Authentication response status code 0x%x",errcode);
ieee80211_associate_abort(ieee);
}
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
index 59c45a510efb..3f5ceeb88b6c 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
@@ -314,7 +314,7 @@ void ieee80211_tx_query_agg_cap(struct ieee80211_device* ieee, struct sk_buff* s
if (!IsQoSDataFrame(skb->data))
return;
- if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1))
+ if (is_multicast_ether_addr(hdr->addr1))
return;
//check packet and mode later
#ifdef TO_DO_LIST
@@ -575,7 +575,7 @@ void ieee80211_txrate_selectmode(struct ieee80211_device* ieee, cb_desc* tcb_des
void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u8* dst)
{
- if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst))
+ if (is_multicast_ether_addr(dst))
return;
if (IsQoSDataFrame(skb->data)) //we deal qos data only
{
@@ -693,8 +693,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
/* Determine fragmentation size based on destination (multicast
* and broadcast are not fragmented) */
- if (is_multicast_ether_addr(header.addr1) ||
- is_broadcast_ether_addr(header.addr1)) {
+ if (is_multicast_ether_addr(header.addr1)) {
frag_size = MAX_FRAG_THRESHOLD;
qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
}
diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
index 957ce4ef48b5..06a9824bbff1 100644
--- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
@@ -350,7 +350,7 @@ bool GetTs(
// We do not build any TS for Broadcast or Multicast stream.
// So reject these kinds of search here.
//
- if(is_broadcast_ether_addr(Addr) || is_multicast_ether_addr(Addr))
+ if (is_multicast_ether_addr(Addr))
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "get TS for Broadcast or Multicast\n");
return false;
diff --git a/drivers/staging/rtl8192u/r8180_93cx6.c b/drivers/staging/rtl8192u/r8180_93cx6.c
index 8878cfeb0fbb..3c515b7bc542 100644
--- a/drivers/staging/rtl8192u/r8180_93cx6.c
+++ b/drivers/staging/rtl8192u/r8180_93cx6.c
@@ -14,7 +14,7 @@
Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
- We want to tanks the Authors of those projects and the Ndiswrapper
+ We want to thank the Authors of those projects and the Ndiswrapper
project Authors.
*/
diff --git a/drivers/staging/rtl8192u/r8180_93cx6.h b/drivers/staging/rtl8192u/r8180_93cx6.h
index fb3ac9766ea5..5cea51e1142e 100644
--- a/drivers/staging/rtl8192u/r8180_93cx6.h
+++ b/drivers/staging/rtl8192u/r8180_93cx6.h
@@ -7,7 +7,7 @@
Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
- We want to tanks the Authors of such projects and the Ndiswrapper project Authors.
+ We want to thank the Authors of such projects and the Ndiswrapper project Authors.
*/
/*This files contains card eeprom (93c46 or 93c56) programming routines*/
diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h
index 9b81f26d40fe..57e3383cc935 100644
--- a/drivers/staging/rtl8192u/r8192U.h
+++ b/drivers/staging/rtl8192u/r8192U.h
@@ -11,7 +11,7 @@
Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
- We want to tanks the Authors of those projects and the Ndiswrapper
+ We want to thank the Authors of those projects and the Ndiswrapper
project Authors.
*/
@@ -98,7 +98,7 @@ do { if(rt_global_debug_component & component) \
#define COMP_INIT BIT2 // during driver initialization / halt / reset.
-#define COMP_RECV BIT3 // Reveive part data path.
+#define COMP_RECV BIT3 // Receive data path.
#define COMP_SEND BIT4 // Send part path.
#define COMP_IO BIT5 // I/O Related. Added by Annie, 2006-03-02.
#define COMP_POWER BIT6 // 802.11 Power Save mode or System/Device Power state related.
@@ -322,7 +322,7 @@ typedef struct _tx_fwinfo_819x_usb {
u8 TxSubCarrier:2; // This is used for legacy OFDM rate only.
u8 STBC:2;
u8 AllowAggregation:1;
- u8 RtsHT:1; //Interpre RtsRate field as high throughput data rate
+ u8 RtsHT:1; //Interpret RtsRate field as high throughput data rate
u8 RtsShort:1; //Short PLCP for CCK, or short GI for 11n MCS
u8 RtsBandwidth:1; // This is used for HT MCS rate only.
u8 RtsSubcarrier:2; // This is used for legacy OFDM rate only.
@@ -610,7 +610,6 @@ typedef struct Stats
// unsigned long rxnopointer;
unsigned long rxok;
unsigned long rxframgment;
- unsigned long rxcmdpkt[4]; //08/05/08 amy rx cmd element txfeedback/bcn report/cfg set/query
unsigned long rxurberr;
unsigned long rxstaterr;
unsigned long received_rate_histogram[4][32]; //0: Total, 1:OK, 2:CRC, 3:ICV, 2007 07 03 cosa
@@ -1117,7 +1116,7 @@ typedef struct r8192_priv
bool bfsync_processing; // 500ms Fsync timer is active or not
u32 rate_record;
u32 rateCountDiffRecord;
- u32 ContiuneDiffCount;
+ u32 ContinueDiffCount;
bool bswitch_fsync;
u8 framesync;
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index 9c00865f302a..5981d6658320 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -203,7 +203,7 @@ static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv* priv)
{
Dot11d_Init(ieee);
ieee->bGlobalDomain = false;
- //acturally 8225 & 8256 rf chip only support B,G,24N mode
+ //actually 8225 & 8256 rf chips only support B,G,24N mode
if ((priv->rf_chip == RF_8225) || (priv->rf_chip == RF_8256))
{
min_chan = 1;
@@ -1103,7 +1103,7 @@ inline u16 rtl8192_rate2rate(short rate)
}
-/* The protype of rx_isr has changed since one verion of Linux Kernel */
+/* The prototype of rx_isr has changed since one version of Linux Kernel */
static void rtl8192_rx_isr(struct urb *urb)
{
struct sk_buff *skb = (struct sk_buff *) urb->context;
@@ -1476,7 +1476,7 @@ static void rtl8192_tx_isr(struct urb *tx_urb)
if(tcb_desc->queue_index != TXCMD_QUEUE) {
if(tx_urb->status == 0) {
dev->trans_start = jiffies;
- // As act as station mode, destion shall be unicast address.
+ // Act as station mode, destination shall be unicast address.
//priv->ieee80211->stats.tx_bytes+=(skb->len - priv->ieee80211->tx_headroom);
//priv->ieee80211->stats.tx_packets++;
priv->stats.txoktotal++;
@@ -1522,13 +1522,13 @@ static void rtl8192_tx_isr(struct urb *tx_urb)
else if ((skb_queue_len(&priv->ieee80211->skb_drv_aggQ[queue_index])!= 0)&&\
(!(priv->ieee80211->queue_stop))) {
// Tx Driver Aggregation process
- /* The driver will aggregation the packets according to the following stets
+ /* The driver will aggregation the packets according to the following stats
* 1. check whether there's tx irq available, for it's a completion return
* function, it should contain enough tx irq;
- * 2. check pakcet type;
+ * 2. check packet type;
* 3. initialize sendlist, check whether the to-be send packet no greater than 1
- * 4. aggregation the packets, and fill firmware info and tx desc to it, etc.
- * 5. check whehter the packet could be sent, otherwise just insert to wait head
+ * 4. aggregates the packets, and fill firmware info and tx desc into it, etc.
+ * 5. check whether the packet could be sent, otherwise just insert into wait head
* */
skb = skb_dequeue(&priv->ieee80211->skb_drv_aggQ[queue_index]);
if(!check_nic_enough_desc(dev, queue_index)) {
@@ -2447,7 +2447,7 @@ static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
return 0;
}
-/* handle manage frame frame beacon and probe response */
+/* handle and manage frame from beacon and probe response */
static int rtl8192_handle_beacon(struct net_device * dev,
struct ieee80211_beacon * beacon,
struct ieee80211_network * network)
@@ -2625,7 +2625,7 @@ bool GetHalfNmodeSupportByAPs819xUsb(struct net_device* dev)
void rtl8192_refresh_supportrate(struct r8192_priv* priv)
{
struct ieee80211_device* ieee = priv->ieee80211;
- //we donot consider set support rate for ABG mode, only HT MCS rate is set here.
+ //we do not consider set support rate for ABG mode, only HT MCS rate is set here.
if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
{
memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
@@ -2780,10 +2780,10 @@ static void rtl8192_init_priv_variable(struct net_device* dev)
priv->TransmitConfig =
// TCR_DurProcMode | //for RTL8185B, duration setting by HW
//? TCR_DISReqQsize |
- (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reservied.
+ (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reserved.
(priv->ShortRetryLimit<<TCR_SRL_OFFSET)| // Short retry limit
(priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
- (false ? TCR_SAT: 0); // FALSE: HW provies PLCP length and LENGEXT, TURE: SW proiveds them
+ (false ? TCR_SAT: 0); // FALSE: HW provides PLCP length and LENGEXT, TRUE: SW provides them
#ifdef TO_DO_LIST
if(Adapter->bInHctTest)
pHalData->ReceiveConfig = pHalData->CSMethod |
@@ -3437,7 +3437,7 @@ if(Adapter->ResetProgress == RESET_TYPE_NORESET)
{ // User disable RF via registry.
RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
- // Those action will be discard in MgntActSet_RF_State because off the same state
+ // Those actions will be discard in MgntActSet_RF_State because of the same state
for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
}
@@ -3458,7 +3458,7 @@ if(Adapter->ResetProgress == RESET_TYPE_NORESET)
if(pHalData->eRFPowerState == eRfOff)
{
MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
- // Those action will be discard in MgntActSet_RF_State because off the same state
+ // Those actions will be discard in MgntActSet_RF_State because of the same state
for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
}
@@ -3586,7 +3586,7 @@ TxCheckStuck(struct net_device *dev)
//unsigned long flags;
//
- // Decide Stuch threshold according to current power save mode
+ // Decide such threshold according to current power save mode
//
// RT_TRACE(COMP_RESET, " ==> TxCheckStuck()\n");
@@ -3745,7 +3745,7 @@ rtl819x_ifcheck_resetornot(struct net_device *dev)
// Driver should not check RX stuck in IBSS mode because it is required to
// set Check BSSID in order to send beacon, however, if check BSSID is
- // set, STA cannot hear any packet a all. Emily, 2008.04.12
+ // set, STA cannot hear any packet at all. Emily, 2008.04.12
RxResetType = RxCheckStuck(dev);
}
if(TxResetType==RESET_TYPE_NORMAL || RxResetType==RESET_TYPE_NORMAL)
@@ -3962,7 +3962,7 @@ RESET_START:
up(&priv->wx_sem);
RT_TRACE(COMP_RESET,"%s():<==========down process is finished\n",__FUNCTION__);
//rtl8192_irq_disable(dev);
- RT_TRACE(COMP_RESET,"%s():===========>start to up the driver\n",__FUNCTION__);
+ RT_TRACE(COMP_RESET,"%s():===========>start up the driver\n",__FUNCTION__);
reset_status = _rtl8192_up(dev);
RT_TRACE(COMP_RESET,"%s():<===========up process is finished\n",__FUNCTION__);
@@ -4155,7 +4155,7 @@ extern void rtl819x_watchdog_wqcallback(struct work_struct *work)
void watch_dog_timer_callback(unsigned long data)
{
struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
- //printk("===============>watch_dog timer\n");
+ //printk("===============>watch_dog timer\n");
queue_delayed_work(priv->priv_wq,&priv->watch_dog_wq, 0);
mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
}
@@ -4170,7 +4170,7 @@ int _rtl8192_up(struct net_device *dev)
init_status = rtl8192_adapter_start(dev);
if(!init_status)
{
- RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n", __FUNCTION__);
+ RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization failed!\n", __FUNCTION__);
priv->up=priv->ieee80211->ieee_up = 0;
return -EAGAIN;
}
@@ -4256,7 +4256,7 @@ int rtl8192_down(struct net_device *dev)
skb_queue_purge(&priv->ieee80211->skb_drv_aggQ [i]);
}
- //as cancel_delayed_work will del work->timer, so if work is not definedas struct delayed_work, it will corrupt
+ //as cancel_delayed_work will del work->timer, so if work is not defined as struct delayed_work, it will corrupt
// flush_scheduled_work();
rtl8192_cancel_deferred_work(priv);
deinit_hal_dm(dev);
@@ -4516,7 +4516,7 @@ u8 HwRateToMRate90(bool bIsHT, u8 rate)
/**
* Function: UpdateRxPktTimeStamp
- * Overview: Recored down the TSF time stamp when receiving a packet
+ * Overview: Record the TSF time stamp when receiving a packet
*
* Input:
* PADAPTER Adapter
@@ -4556,10 +4556,10 @@ long rtl819x_translate_todbm(u8 signal_strength_index )// 0-100 index.
}
-/* 2008/01/22 MH We can not delcare RSSI/EVM total value of sliding window to
+/* 2008/01/22 MH We can not declare RSSI/EVM total value of sliding window to
be a local static. Otherwise, it may increase when we return from S3/S4. The
- value will be kept in memory or disk. We must delcare the value in adapter
- and it will be reinitialized when return from S3/S4. */
+ value will be kept in memory or disk. Declare the value in the adaptor
+ and it will be reinitialized when returned from S3/S4. */
void rtl8192_process_phyinfo(struct r8192_priv * priv,u8* buffer, struct ieee80211_rx_stats * pprevious_stats, struct ieee80211_rx_stats * pcurrent_stats)
{
bool bcheck = false;
@@ -5091,8 +5091,8 @@ static void rtl8192_query_rxphystatus(
tmp_rxevm = pofdm_buf->rxevm_X[i];
rx_evmX = (char)(tmp_rxevm);
- // Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment
- // fill most significant bit to "zero" when doing shifting operation which may change a negative
+ // Do not use shift operation like "rx_evmX >>= 1" because the compiler of free build environment
+ // will set the most significant bit to "zero" when doing shifting operation which may change a negative
// value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
rx_evmX /= 2; //dbm
@@ -5171,7 +5171,7 @@ void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
- /* Check if the received packet is acceptabe. */
+ /* Check if the received packet is acceptable. */
bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
(eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS )? hdr->addr2 : hdr->addr3))
&& (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV));
@@ -5211,7 +5211,7 @@ void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
/**
* Function: UpdateReceivedRateHistogramStatistics
-* Overview: Recored down the received data rate
+* Overview: Record the received data rate
*
* Input:
* struct net_device *dev
@@ -5401,7 +5401,7 @@ void query_rxdesc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats,
}
#ifdef USB_RX_AGGREGATION_SUPPORT
- /* for the rx aggregated sub frame, the redundant space truelly contained in the packet */
+ /* for the rx aggregated sub frame, the redundant space truly contained in the packet */
if(bIsRxAggrSubframe) {
skb_pull(skb, 8);
}
@@ -5480,7 +5480,7 @@ void rtl8192_rx_nomal(struct sk_buff* skb)
PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false);
}
#endif
- /* Process the MPDU recevied */
+ /* Process the MPDU received */
skb_trim(skb, skb->len - 4/*sCrcLng*/);
rx_pkt_len = skb->len;
@@ -5538,7 +5538,7 @@ void rtl8192_rx_nomal(struct sk_buff* skb)
if(PacketLength > agg_skb->len) {
break;
}
- /* Process the MPDU recevied */
+ /* Process the MPDU received */
skb = dev_alloc_skb(PacketLength);
memcpy(skb_put(skb,PacketLength),agg_skb->data, PacketLength);
skb_trim(skb, skb->len - 4/*sCrcLng*/);
diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c
index 2dde9fa5c21e..cd8dc85e9c0f 100644
--- a/drivers/staging/rtl8192u/r8192U_dm.c
+++ b/drivers/staging/rtl8192u/r8192U_dm.c
@@ -38,7 +38,7 @@ static u32 edca_setting_UL[HT_IOT_PEER_MAX] =
/*------------------------Define global variable-----------------------------*/
// Debug variable ?
dig_t dm_digtable;
-// Store current shoftware write register content for MAC PHY.
+// Store current software write register content for MAC PHY.
u8 dm_shadow[16][256] = {{0}};
// For Dynamic Rx Path Selection by Signal Strength
DRxPathSel DM_RxPathSelTable;
@@ -119,7 +119,7 @@ static void dm_pd_th(struct net_device *dev);
static void dm_cs_ratio(struct net_device *dev);
static void dm_init_ctstoself(struct net_device *dev);
-// DM --> EDCA turboe mode control
+// DM --> EDCA turbo mode control
static void dm_check_edca_turbo(struct net_device *dev);
// DM --> HW RF control
@@ -348,7 +348,7 @@ extern void init_rate_adaptive(struct net_device * dev)
*
* Revised History:
* When Who Remark
- * 05/26/08 amy Create version 0 proting from windows code.
+ * 05/26/08 amy Create version 0 porting from windows code.
*
*---------------------------------------------------------------------------*/
static void dm_check_rate_adaptive(struct net_device * dev)
@@ -543,7 +543,7 @@ static u32 OFDMSwingTable[OFDM_Table_Length] = {
0x5a400169, // 3, +3db
0x50800142, // 4, +2db
0x47c0011f, // 5, +1db
- 0x40000100, // 6, +0db ===> default, upper for higher temprature, lower for low temprature
+ 0x40000100, // 6, +0db ===> default, upper for higher temperature, lower for low temperature
0x390000e4, // 7, -1db
0x32c000cb, // 8, -2db
0x2d4000b5, // 9, -3db
@@ -678,7 +678,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
{
write_nic_byte(dev, 0x1ba, 0);
viviflag = FALSE;
- RT_TRACE(COMP_POWER_TRACKING, "we filted this data\n");
+ RT_TRACE(COMP_POWER_TRACKING, "we filtered the data\n");
for(k = 0;k < 5; k++)
tmp_report[k] = 0;
break;
@@ -864,14 +864,14 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev)
RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d \n", tmpRegA);
if(tmpRegA < 3 || tmpRegA > 13)
return;
- if(tmpRegA >= 12) // if over 12, TP will be bad when high temprature
+ if(tmpRegA >= 12) // if over 12, TP will be bad when high temperature
tmpRegA = 12;
RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d \n", tmpRegA);
priv->ThermalMeter[0] = ThermalMeterVal; //We use fixed value by Bryant's suggestion
priv->ThermalMeter[1] = ThermalMeterVal; //We use fixed value by Bryant's suggestion
- //Get current RF-A temprature index
- if(priv->ThermalMeter[0] >= (u8)tmpRegA) //lower temprature
+ //Get current RF-A temperature index
+ if(priv->ThermalMeter[0] >= (u8)tmpRegA) //lower temperature
{
tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0]-(u8)tmpRegA);
tmpCCK40Mindex = tmpCCK20Mindex - 6;
@@ -885,7 +885,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev)
else
{
tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]);
- if(tmpval >= 6) // higher temprature
+ if(tmpval >= 6) // higher temperature
tmpOFDMindex = tmpCCK20Mindex = 0; // max to +6dB
else
tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval;
@@ -1457,9 +1457,9 @@ static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
- // Tx Power tracking by Theremal Meter require Firmware R/W 3-wire. This mechanism
+ // Tx Power tracking by Thermal Meter requires Firmware R/W 3-wire. This mechanism
// can be enabled only when Firmware R/W 3-wire is enabled. Otherwise, frequent r/w
- // 3-wire by driver cause RF goes into wrong state.
+ // 3-wire by driver causes RF to go into a wrong state.
if(priv->ieee80211->FwRWRF)
priv->btxpower_tracking = TRUE;
else
@@ -1520,7 +1520,7 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev)
if(!TM_Trigger)
{
- //Attention!! You have to wirte all 12bits data to RF, or it may cause RF to crash
+ //Attention!! You have to write all 12bits of data to RF, or it may cause RF to crash
//actually write reg0x02 bit1=0, then bit1=1.
//DbgPrint("Trigger ThermalMeter, write RF reg0x2 = 0x4d to 0x4f\n");
rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
@@ -1744,7 +1744,7 @@ extern void dm_restore_dynamic_mechanism_state(struct net_device *dev)
write_nic_dword(dev, RATR0, ratr_value);
write_nic_byte(dev, UFWP, 1);
}
- //Resore TX Power Tracking Index
+ //Restore TX Power Tracking Index
if(priv->btxpower_trackingInit && priv->btxpower_tracking){
dm_txpower_reset_recovery(dev);
}
@@ -2031,7 +2031,7 @@ static void dm_dig_init(struct net_device *dev)
dm_digtable.dbg_mode = DM_DBG_OFF; //off=by real rssi value, on=by DM_DigTable.Rssi_val for new dig
dm_digtable.dig_algorithm_switch = 0;
- /* 2007/10/04 MH Define init gain threshol. */
+ /* 2007/10/04 MH Define init gain threshold. */
dm_digtable.dig_state = DM_STA_DIG_MAX;
dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX;
dm_digtable.initialgain_lowerbound_state = false;
@@ -2097,7 +2097,7 @@ static void dm_ctrl_initgain_byrssi_by_driverrssi(
return;
//DbgPrint("Dig by Sw Rssi \n");
- if(dm_digtable.dig_algorithm_switch) // if swithed algorithm, we have to disable FW Dig.
+ if(dm_digtable.dig_algorithm_switch) // if switched algorithm, we have to disable FW Dig.
fw_dig = 0;
if(fw_dig <= 3) // execute several times to make sure the FW Dig is disabled
{// FW DIG Off
@@ -2160,8 +2160,8 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
/*DbgPrint("DIG Check\n\r RSSI=%d LOW=%d HIGH=%d STATE=%d",
pHalData->UndecoratedSmoothedPWDB, DM_DigTable.RssiLowThresh,
DM_DigTable.RssiHighThresh, DM_DigTable.Dig_State);*/
- /* 1. When RSSI decrease, We have to judge if it is smaller than a treshold
- and then execute below step. */
+ /* 1. When RSSI decrease, We have to judge if it is smaller than a threshold
+ and then execute the step below. */
if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh))
{
/* 2008/02/05 MH When we execute silent reset, the DIG PHY parameters
@@ -2220,8 +2220,8 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
}
- /* 2. When RSSI increase, We have to judge if it is larger than a treshold
- and then execute below step. */
+ /* 2. When RSSI increase, We have to judge if it is larger than a threshold
+ and then execute the step below. */
if ((priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) )
{
u8 reset_flag = 0;
@@ -2329,7 +2329,7 @@ static void dm_ctrl_initgain_byrssi_highpwr(
}
/* 3. When RSSI >75% or <70%, it is a high power issue. We have to judge if
- it is larger than a treshold and then execute below step. */
+ it is larger than a threshold and then execute the step below. */
// 2008/02/05 MH SD3-Jerry Modify PD_TH for high power issue.
if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh)
{
@@ -2841,8 +2841,8 @@ static void dm_check_rfctrl_gpio(struct net_device * dev)
{
//struct r8192_priv *priv = ieee80211_priv(dev);
- // Walk around for DTM test, we will not enable HW - radio on/off because r/w
- // page 1 register before Lextra bus is enabled cause system fails when resuming
+ // Work around for DTM test, we will not enable HW - radio on/off because r/w
+ // page 1 register before extra bus is enabled causing system failures when resuming
// from S4. 20080218, Emily
// Stop to execute workitem to prevent S3/S4 bug.
@@ -3377,30 +3377,30 @@ extern void dm_fsync_timer_callback(unsigned long data)
{
u32 DiffNum = priv->rateCountDiffRecord - rate_count_diff;
- // Contiune count
+ // Continue count
if(DiffNum >= priv->ieee80211->fsync_seconddiff_ratethreshold)
- priv->ContiuneDiffCount++;
+ priv->ContinueDiffCount++;
else
- priv->ContiuneDiffCount = 0;
+ priv->ContinueDiffCount = 0;
- // Contiune count over
- if(priv->ContiuneDiffCount >=2)
+ // Continue count over
+ if(priv->ContinueDiffCount >=2)
{
bSwitchFromCountDiff = true;
- priv->ContiuneDiffCount = 0;
+ priv->ContinueDiffCount = 0;
}
}
else
{
- // Stop contiune count
- priv->ContiuneDiffCount = 0;
+ // Stop the continued count
+ priv->ContinueDiffCount = 0;
}
//If Count diff <= FsyncRateCountThreshold
if(rate_count_diff <= priv->ieee80211->fsync_firstdiff_ratethreshold)
{
bSwitchFromCountDiff = true;
- priv->ContiuneDiffCount = 0;
+ priv->ContinueDiffCount = 0;
}
priv->rate_record = rate_count;
priv->rateCountDiffRecord = rate_count_diff;
@@ -3468,14 +3468,14 @@ extern void dm_fsync_timer_callback(unsigned long data)
#endif
write_nic_byte(dev, 0xC3e, 0x96);
}
- priv->ContiuneDiffCount = 0;
+ priv->ContinueDiffCount = 0;
#ifdef RTL8190P
write_nic_dword(dev, rOFDM0_RxDetector2, 0x164052cd);
#else
write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
#endif
}
- RT_TRACE(COMP_HALDM, "ContiuneDiffCount %d\n", priv->ContiuneDiffCount);
+ RT_TRACE(COMP_HALDM, "ContinueDiffCount %d\n", priv->ContinueDiffCount);
RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync);
}
@@ -3507,7 +3507,7 @@ static void dm_EndSWFsync(struct net_device *dev)
write_nic_byte(dev, 0xC3e, 0x96);
}
- priv->ContiuneDiffCount = 0;
+ priv->ContinueDiffCount = 0;
#ifndef RTL8190P
write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
#endif
@@ -3523,8 +3523,8 @@ static void dm_StartSWFsync(struct net_device *dev)
RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__);
// Initial rate record to zero, start to record.
priv->rate_record = 0;
- // Initial contiune diff count to zero, start to record.
- priv->ContiuneDiffCount = 0;
+ // Initialize continue diff count to zero, start to record.
+ priv->ContinueDiffCount = 0;
priv->rateCountDiffRecord = 0;
priv->bswitch_fsync = false;
@@ -3875,7 +3875,7 @@ static void dm_send_rssi_tofw(struct net_device *dev)
// If we test chariot, we should stop the TX command ?
// Because 92E will always silent reset when we send tx command. We use register
- // 0x1e0(byte) to botify driver.
+ // 0x1e0(byte) to notify driver.
write_nic_byte(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb);
return;
tx_cmd.Op = TXCMD_SET_RX_RSSI;
diff --git a/drivers/staging/rtl8192u/r8192U_hw.h b/drivers/staging/rtl8192u/r8192U_hw.h
index e89aaf70143b..1bfe871dcfb2 100644
--- a/drivers/staging/rtl8192u/r8192U_hw.h
+++ b/drivers/staging/rtl8192u/r8192U_hw.h
@@ -10,7 +10,7 @@
Parts of this driver are based on the Intel Pro Wireless
2100 GPL driver.
- We want to tanks the Authors of those projects
+ We want to thank the Authors of those projects
and the Ndiswrapper project Authors.
*/
diff --git a/drivers/staging/rtl8192u/r8192U_wx.c b/drivers/staging/rtl8192u/r8192U_wx.c
index f6408f98ede6..71f2d2349c38 100644
--- a/drivers/staging/rtl8192u/r8192U_wx.c
+++ b/drivers/staging/rtl8192u/r8192U_wx.c
@@ -13,7 +13,7 @@
Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
- We want to tanks the Authors of those projects and the Ndiswrapper
+ We want to thank the Authors of those projects and the Ndiswrapper
project Authors.
*/
@@ -256,7 +256,7 @@ static int r8192_wx_get_ap_status(struct net_device *dev,
//count the length of input ssid
for(name_len=0 ; ((char*)wrqu->data.pointer)[name_len]!='\0' ; name_len++);
- //search for the correspoding info which is received
+ //search for the corresponding info which is received
list_for_each_entry(target, &ieee->network_list, list) {
if ( (target->ssid_len == name_len) &&
(strncmp(target->ssid, (char*)wrqu->data.pointer, name_len)==0)){
@@ -419,7 +419,7 @@ static int rtl8180_wx_get_range(struct net_device *dev,
range->max_qual.updated = 7; /* Updated all three */
range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
- /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
+ /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
range->avg_qual.level = 20 + -98;
range->avg_qual.noise = 0;
range->avg_qual.updated = 7; /* Updated all three */
@@ -1047,7 +1047,7 @@ static iw_handler r8192_wx_handlers[] =
#else
NULL,
#endif
- dummy, /* SIOCGIWAPLIST -- depricated */
+ dummy, /* SIOCGIWAPLIST -- deprecated */
r8192_wx_set_scan, /* SIOCSIWSCAN */
r8192_wx_get_scan, /* SIOCGIWSCAN */
r8192_wx_set_essid, /* SIOCSIWESSID */
@@ -1211,9 +1211,9 @@ struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
struct iw_handler_def r8192_wx_handlers_def={
.standard = r8192_wx_handlers,
- .num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler),
+ .num_standard = ARRAY_SIZE(r8192_wx_handlers),
.private = r8192_private_handler,
- .num_private = sizeof(r8192_private_handler) / sizeof(iw_handler),
+ .num_private = ARRAY_SIZE(r8192_private_handler),
.num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
#if WIRELESS_EXT >= 17
.get_wireless_stats = r8192_get_wireless_stats,
diff --git a/drivers/staging/rtl8192u/r8192U_wx.h b/drivers/staging/rtl8192u/r8192U_wx.h
index f4cf2801136a..9f6b10505426 100644
--- a/drivers/staging/rtl8192u/r8192U_wx.h
+++ b/drivers/staging/rtl8192u/r8192U_wx.h
@@ -7,7 +7,7 @@
Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
- We want to tanks the Authors of such projects and the Ndiswrapper project Authors.
+ We want to thank the Authors of such projects and the Ndiswrapper project Authors.
*/
/* this file (will) contains wireless extension handlers*/
diff --git a/drivers/staging/rtl8192u/r819xU_HTType.h b/drivers/staging/rtl8192u/r819xU_HTType.h
index 2ac421626e7c..e07f8b17a0d6 100644
--- a/drivers/staging/rtl8192u/r819xU_HTType.h
+++ b/drivers/staging/rtl8192u/r819xU_HTType.h
@@ -211,7 +211,7 @@ typedef struct _RT_HIGH_THROUGHPUT{
u8 bEnableHT;
u8 bCurrentHTSupport;
- u8 bRegBW40MHz; // Tx 40MHz channel capablity
+ u8 bRegBW40MHz; // Tx 40MHz channel capability
u8 bCurBW40MHz; // Tx 40MHz channel capability
u8 bRegShortGI40MHz; // Tx Short GI for 40Mhz
diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c
index 0cb28c776c49..a8a6dc2c365f 100644
--- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c
+++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c
@@ -157,7 +157,7 @@ SendTxCommandPacket(
seg_ptr = skb_put(skb, buffer_len);
/*
* Transform from little endian to big endian
- * and pending zero
+ * and pending zero
*/
memcpy(seg_ptr,codevirtualaddress,buffer_len);
tcb_desc->txbuf_size= (u16)buffer_len;
@@ -697,7 +697,6 @@ cmpk_message_handle_rx(
struct ieee80211_rx_stats *pstats)
{
// u32 debug_level = DBG_LOUD;
- struct r8192_priv *priv = ieee80211_priv(dev);
int total_length;
u8 cmd_length, exe_cnt = 0;
u8 element_id;
@@ -719,15 +718,15 @@ cmpk_message_handle_rx(
/* 2. Read virtual address from RFD. */
pcmd_buff = pstats->virtual_address;
- /* 3. Read command pakcet element id and length. */
+ /* 3. Read command packet element id and length. */
element_id = pcmd_buff[0];
/*RT_TRACE(COMP_SEND, DebugLevel,
("\n\r[CMPK]-->element ID=%d Len=%d", element_id, total_length));*/
- /* 4. Check every received command packet conent according to different
+ /* 4. Check every received command packet content according to different
element type. Because FW may aggregate RX command packet to minimize
transmit time between DRV and FW.*/
- // Add a counter to prevent to locked in the loop too long
+ // Add a counter to prevent the lock in the loop from being held too long
while (total_length > 0 || exe_cnt++ >100)
{
/* 2007/01/17 MH We support aggregation of different cmd in the same packet. */
@@ -779,9 +778,6 @@ cmpk_message_handle_rx(
// 2007/01/22 MH Add to display tx statistic.
//cmpk_DisplayTxStatistic(pAdapter);
- /* 2007/03/09 MH Collect sidderent cmd element pkt num. */
- priv->stats.rxcmdpkt[element_id]++;
-
total_length -= cmd_length;
pcmd_buff += cmd_length;
} /* while (total_length > 0) */
diff --git a/drivers/staging/rtl8192u/r819xU_firmware.c b/drivers/staging/rtl8192u/r819xU_firmware.c
index 4bb5fffca5b9..b12d19079798 100644
--- a/drivers/staging/rtl8192u/r819xU_firmware.c
+++ b/drivers/staging/rtl8192u/r819xU_firmware.c
@@ -275,11 +275,11 @@ bool init_firmware(struct net_device *dev)
/*
* Download boot, main, and data image for System reset.
- * Download data image for firmware reseta
+ * Download data image for firmware reset
*/
for(init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; init_step++) {
/*
- * Open Image file, and map file to contineous memory if open file success.
+ * Open image file, and map file to continuous memory if open file success.
* or read image file from array. Default load from IMG file
*/
if(rst_opt == OPT_SYSTEM_RESET) {
diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c
index c4586b0817d1..dd1954daea2d 100644
--- a/drivers/staging/rtl8192u/r819xU_phy.c
+++ b/drivers/staging/rtl8192u/r819xU_phy.c
@@ -40,7 +40,7 @@ static u32 RF_CHANNEL_TABLE_ZEBRA[] = {
* and do register read/write
* input: u32 dwBitMask //taget bit pos in the addr to be modified
* output: none
- * return: u32 return the shift bit bit position of the mask
+ * return: u32 return the shift bit position of the mask
* ****************************************************************************/
u32 rtl8192_CalculateBitShift(u32 dwBitMask)
{
@@ -176,7 +176,7 @@ u32 rtl8192_phy_RFSerialRead(struct net_device* dev, RF90_RADIO_PATH_E eRFPath,
rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x1);
- // TODO: we should not delay such a long time. Ask help from SD3
+ // TODO: we should not delay such a long time. Ask for help from SD3
msleep(1);
ret = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBack, bLSSIReadBackData);
@@ -252,7 +252,7 @@ void rtl8192_phy_RFSerialWrite(struct net_device* dev, RF90_RADIO_PATH_E eRFPath
NewOffset = Offset;
}
- // Put write addr in [5:0] and write data in [31:16]
+ // Put write addr in [5:0] and write data in [31:16]
DataAndAddr = (Data<<16) | (NewOffset&0x3f);
// Write Operation
@@ -525,7 +525,7 @@ void rtl8192_phy_configmac(struct net_device* dev)
}
/******************************************************************************
- *function: This function do dirty work
+ *function: This function does dirty work
* input: dev
* output: none
* return: none
@@ -578,7 +578,7 @@ void rtl8192_phyConfigBB(struct net_device* dev, u8 ConfigType)
void rtl8192_InitBBRFRegDef(struct net_device* dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
-// RF Interface Sowrtware Control
+// RF Interface Software Control
priv->PHYRegDef[RF90_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; // 16 LSBs if read 32-bit from 0x870
priv->PHYRegDef[RF90_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; // 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872)
priv->PHYRegDef[RF90_PATH_C].rfintfs = rFPGA0_XCD_RFInterfaceSW;// 16 LSBs if read 32-bit from 0x874
@@ -602,7 +602,7 @@ void rtl8192_InitBBRFRegDef(struct net_device* dev)
priv->PHYRegDef[RF90_PATH_C].rfintfe = rFPGA0_XC_RFInterfaceOE;// 16 MSBs if read 32-bit from 0x86A (16-bit for 0x86A)
priv->PHYRegDef[RF90_PATH_D].rfintfe = rFPGA0_XD_RFInterfaceOE;// 16 MSBs if read 32-bit from 0x86C (16-bit for 0x86E)
- //Addr of LSSI. Wirte RF register by driver
+ //Addr of LSSI. Write RF register by driver
priv->PHYRegDef[RF90_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; //LSSI Parameter
priv->PHYRegDef[RF90_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter;
priv->PHYRegDef[RF90_PATH_C].rf3wireOffset = rFPGA0_XC_LSSIParameter;
@@ -1384,7 +1384,7 @@ u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, u8* stage, u
}
/******************************************************************************
- *function: This function does acturally set channel work
+ *function: This function does actually set channel work
* input: struct net_device *dev
* u8 channel
* output: none
@@ -1425,7 +1425,7 @@ void rtl8192_SwChnl_WorkItem(struct net_device *dev)
}
/******************************************************************************
- *function: This function scheduled actural workitem to set channel
+ *function: This function scheduled actual work item to set channel
* input: net_device dev
* u8 channel //channel to set
* output: none
diff --git a/drivers/staging/rtl8192u/r819xU_phyreg.h b/drivers/staging/rtl8192u/r819xU_phyreg.h
index 06b0b539e1bc..50f24dce8b16 100644
--- a/drivers/staging/rtl8192u/r819xU_phyreg.h
+++ b/drivers/staging/rtl8192u/r819xU_phyreg.h
@@ -443,7 +443,7 @@
#define bCCKRxIG 0x7f00
#define bCCKLNAPolarity 0x800000
#define bCCKRx1stGain 0x7f0000
-#define bCCKRFExtend 0x20000000 //CCK Rx Iinital gain polarity
+#define bCCKRFExtend 0x20000000 //CCK Rx inital gain polarity
#define bCCKRxAGCSatLevel 0x1f000000
#define bCCKRxAGCSatCount 0xe0
#define bCCKRxRFSettle 0x1f //AGCsamp_dly
diff --git a/drivers/staging/rtl8712/big_endian.h b/drivers/staging/rtl8712/big_endian.h
deleted file mode 100644
index b16f8ecf99c6..000000000000
--- a/drivers/staging/rtl8712/big_endian.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _LINUX_BYTEORDER_BIG_ENDIAN_H
-#define _LINUX_BYTEORDER_BIG_ENDIAN_H
-
-#ifndef __BIG_ENDIAN
-#define __BIG_ENDIAN 4321
-#endif
-#ifndef __BIG_ENDIAN_BITFIELD
-#define __BIG_ENDIAN_BITFIELD
-#endif
-
-#include "swab.h"
-
-#define __constant_htonl(x) ((__u32)(x))
-#define __constant_ntohl(x) ((__u32)(x))
-#define __constant_htons(x) ((__u16)(x))
-#define __constant_ntohs(x) ((__u16)(x))
-#define __constant_cpu_to_le64(x) ___constant_swab64((x))
-#define __constant_le64_to_cpu(x) ___constant_swab64((x))
-#define __constant_cpu_to_le32(x) ___constant_swab32((x))
-#define __constant_le32_to_cpu(x) ___constant_swab32((x))
-#define __constant_cpu_to_le16(x) ___constant_swab16((x))
-#define __constant_le16_to_cpu(x) ___constant_swab16((x))
-#define __constant_cpu_to_be64(x) ((__u64)(x))
-#define __constant_be64_to_cpu(x) ((__u64)(x))
-#define __constant_cpu_to_be32(x) ((__u32)(x))
-#define __constant_be32_to_cpu(x) ((__u32)(x))
-#define __constant_cpu_to_be16(x) ((__u16)(x))
-#define __constant_be16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_le64(x) __swab64((x))
-#define __le64_to_cpu(x) __swab64((x))
-#define __cpu_to_le32(x) __swab32((x))
-#define __le32_to_cpu(x) __swab32((x))
-#define __cpu_to_le16(x) __swab16((x))
-#define __le16_to_cpu(x) __swab16((x))
-#define __cpu_to_be64(x) ((__u64)(x))
-#define __be64_to_cpu(x) ((__u64)(x))
-#define __cpu_to_be32(x) ((__u32)(x))
-#define __be32_to_cpu(x) ((__u32)(x))
-#define __cpu_to_be16(x) ((__u16)(x))
-#define __be16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_le64p(x) __swab64p((x))
-#define __le64_to_cpup(x) __swab64p((x))
-#define __cpu_to_le32p(x) __swab32p((x))
-#define __le32_to_cpup(x) __swab32p((x))
-#define __cpu_to_le16p(x) __swab16p((x))
-#define __le16_to_cpup(x) __swab16p((x))
-#define __cpu_to_be64p(x) (*(__u64 *)(x))
-#define __be64_to_cpup(x) (*(__u64 *)(x))
-#define __cpu_to_be32p(x) (*(__u32 *)(x))
-#define __be32_to_cpup(x) (*(__u32 *)(x))
-#define __cpu_to_be16p(x) (*(__u16 *)(x))
-#define __be16_to_cpup(x) (*(__u16 *)(x))
-#define __cpu_to_le64s(x) __swab64s((x))
-#define __le64_to_cpus(x) __swab64s((x))
-#define __cpu_to_le32s(x) __swab32s((x))
-#define __le32_to_cpus(x) __swab32s((x))
-#define __cpu_to_le16s(x) __swab16s((x))
-#define __le16_to_cpus(x) __swab16s((x))
-#define __cpu_to_be64s(x) do {} while (0)
-#define __be64_to_cpus(x) do {} while (0)
-#define __cpu_to_be32s(x) do {} while (0)
-#define __be32_to_cpus(x) do {} while (0)
-#define __cpu_to_be16s(x) do {} while (0)
-#define __be16_to_cpus(x) do {} while (0)
-
-#include "generic.h"
-
-#endif /* _LINUX_BYTEORDER_BIG_ENDIAN_H */
-
diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h
index e83665d06020..62b55663c63a 100644
--- a/drivers/staging/rtl8712/drv_types.h
+++ b/drivers/staging/rtl8712/drv_types.h
@@ -146,7 +146,7 @@ struct dvobj_priv {
/**
* struct _adapter - the main adapter structure for this device.
*
- * bup: True indicates that the interface is Up.
+ * bup: True indicates that the interface is up.
*/
struct _adapter {
struct dvobj_priv dvobjpriv;
diff --git a/drivers/staging/rtl8712/generic.h b/drivers/staging/rtl8712/generic.h
deleted file mode 100644
index 8868c9f4adf8..000000000000
--- a/drivers/staging/rtl8712/generic.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _LINUX_BYTEORDER_GENERIC_H
-#define _LINUX_BYTEORDER_GENERIC_H
-
-/*
- * linux/byteorder_generic.h
- * Generic Byte-reordering support
- *
- * Francois-Rene Rideau <fare@tunes.org> 19970707
- * gathered all the good ideas from all asm-foo/byteorder.h into one file,
- * cleaned them up.
- * I hope it is compliant with non-GCC compilers.
- * I decided to put __BYTEORDER_HAS_U64__ in byteorder.h,
- * because I wasn't sure it would be ok to put it in types.h
- * Upgraded it to 2.1.43
- * Francois-Rene Rideau <fare@tunes.org> 19971012
- * Upgraded it to 2.1.57
- * to please Linus T., replaced huge #ifdef's between little/big endian
- * by nestedly #include'd files.
- * Francois-Rene Rideau <fare@tunes.org> 19971205
- * Made it to 2.1.71; now a facelift:
- * Put files under include/linux/byteorder/
- * Split swab from generic support.
- *
- * TODO:
- * = Regular kernel maintainers could also replace all these manual
- * byteswap macros that remain, disseminated among drivers,
- * after some grep or the sources...
- * = Linus might want to rename all these macros and files to fit his taste,
- * to fit his personal naming scheme.
- * = it seems that a few drivers would also appreciate
- * nybble swapping support...
- * = every architecture could add their byteswap macro in asm/byteorder.h
- * see how some architectures already do (i386, alpha, ppc, etc)
- * = cpu_to_beXX and beXX_to_cpu might some day need to be well
- * distinguished throughout the kernel. This is not the case currently,
- * since little endian, big endian, and pdp endian machines needn't it.
- * But this might be the case for, say, a port of Linux to 20/21 bit
- * architectures (and F21 Linux addict around?).
- */
-
-/*
- * The following macros are to be defined by <asm/byteorder.h>:
- *
- * Conversion of long and short int between network and host format
- * ntohl(__u32 x)
- * ntohs(__u16 x)
- * htonl(__u32 x)
- * htons(__u16 x)
- * It seems that some programs (which? where? or perhaps a standard? POSIX?)
- * might like the above to be functions, not macros (why?).
- * if that's true, then detect them, and take measures.
- * Anyway, the measure is: define only ___ntohl as a macro instead,
- * and in a separate file, have
- * unsigned long inline ntohl(x){return ___ntohl(x);}
- *
- * The same for constant arguments
- * __constant_ntohl(__u32 x)
- * __constant_ntohs(__u16 x)
- * __constant_htonl(__u32 x)
- * __constant_htons(__u16 x)
- *
- * Conversion of XX-bit integers (16- 32- or 64-)
- * between native CPU format and little/big endian format
- * 64-bit stuff only defined for proper architectures
- * cpu_to_[bl]eXX(__uXX x)
- * [bl]eXX_to_cpu(__uXX x)
- *
- * The same, but takes a pointer to the value to convert
- * cpu_to_[bl]eXXp(__uXX x)
- * [bl]eXX_to_cpup(__uXX x)
- *
- * The same, but change in situ
- * cpu_to_[bl]eXXs(__uXX x)
- * [bl]eXX_to_cpus(__uXX x)
- *
- * See asm-foo/byteorder.h for examples of how to provide
- * architecture-optimized versions
- *
- */
-
-
-/*
- * inside the kernel, we can use nicknames;
- * outside of it, we must avoid POSIX namespace pollution...
- */
-#define cpu_to_le64 __cpu_to_le64
-#define le64_to_cpu __le64_to_cpu
-#define cpu_to_le32 __cpu_to_le32
-#define le32_to_cpu __le32_to_cpu
-#define cpu_to_le16 __cpu_to_le16
-#define le16_to_cpu __le16_to_cpu
-#define cpu_to_be64 __cpu_to_be64
-#define be64_to_cpu __be64_to_cpu
-#define cpu_to_be32 __cpu_to_be32
-#define be32_to_cpu __be32_to_cpu
-#define cpu_to_be16 __cpu_to_be16
-#define be16_to_cpu __be16_to_cpu
-#define cpu_to_le64p __cpu_to_le64p
-#define le64_to_cpup __le64_to_cpup
-#define cpu_to_le32p __cpu_to_le32p
-#define le32_to_cpup __le32_to_cpup
-#define cpu_to_le16p __cpu_to_le16p
-#define le16_to_cpup __le16_to_cpup
-#define cpu_to_be64p __cpu_to_be64p
-#define be64_to_cpup __be64_to_cpup
-#define cpu_to_be32p __cpu_to_be32p
-#define be32_to_cpup __be32_to_cpup
-#define cpu_to_be16p __cpu_to_be16p
-#define be16_to_cpup __be16_to_cpup
-#define cpu_to_le64s __cpu_to_le64s
-#define le64_to_cpus __le64_to_cpus
-#define cpu_to_le32s __cpu_to_le32s
-#define le32_to_cpus __le32_to_cpus
-#define cpu_to_le16s __cpu_to_le16s
-#define le16_to_cpus __le16_to_cpus
-#define cpu_to_be64s __cpu_to_be64s
-#define be64_to_cpus __be64_to_cpus
-#define cpu_to_be32s __cpu_to_be32s
-#define be32_to_cpus __be32_to_cpus
-#define cpu_to_be16s __cpu_to_be16s
-#define be16_to_cpus __be16_to_cpus
-
-
-/*
- * Handle ntohl and suches. These have various compatibility
- * issues - like we want to give the prototype even though we
- * also have a macro for them in case some strange program
- * wants to take the address of the thing or something..
- *
- * Note that these used to return a "long" in libc5, even though
- * long is often 64-bit these days.. Thus the casts.
- *
- * They have to be macros in order to do the constant folding
- * correctly - if the argument passed into a inline function
- * it is no longer constant according to gcc..
- */
-
-#undef ntohl
-#undef ntohs
-#undef htonl
-#undef htons
-
-/*
- * Do the prototypes. Somebody might want to take the
- * address or some such sick thing..
- */
-extern __u32 ntohl(__u32);
-extern __u32 htonl(__u32);
-extern unsigned short int ntohs(unsigned short int);
-extern unsigned short int htons(unsigned short int);
-
-#endif /* _LINUX_BYTEORDER_GENERIC_H */
-
diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c
index cc893c0f5ad3..cb9d4cfe8fe4 100644
--- a/drivers/staging/rtl8712/hal_init.c
+++ b/drivers/staging/rtl8712/hal_init.c
@@ -36,7 +36,6 @@
#include "osdep_service.h"
#include "drv_types.h"
-#include "rtl871x_byteorder.h"
#include "usb_osintf.h"
#define FWBUFF_ALIGN_SZ 512
diff --git a/drivers/staging/rtl8712/ieee80211.h b/drivers/staging/rtl8712/ieee80211.h
index 3c0092b7de09..21515c31b373 100644
--- a/drivers/staging/rtl8712/ieee80211.h
+++ b/drivers/staging/rtl8712/ieee80211.h
@@ -705,7 +705,7 @@ enum ieee80211_state {
IEEE80211_ASSOCIATING_RETRY,
/* the association procedure is sending AUTH request*/
IEEE80211_ASSOCIATING_AUTHENTICATING,
- /* the association procedure has successfully authentcated
+ /* the association procedure has successfully authenticated
* and is sending association request
*/
IEEE80211_ASSOCIATING_AUTHENTICATED,
diff --git a/drivers/staging/rtl8712/if_ether.h b/drivers/staging/rtl8712/if_ether.h
deleted file mode 100644
index 2bbe527bcd5c..000000000000
--- a/drivers/staging/rtl8712/if_ether.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Global definitions for the Ethernet IEEE 802.3 interface.
- *
- * Version: @(#)if_ether.h 1.0.1a 02/08/94
- *
- * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Donald Becker, <becker@super.org>
- * Alan Cox, <alan@redhat.com>
- * Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef _LINUX_IF_ETHER_H
-#define _LINUX_IF_ETHER_H
-
-/*
- * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble
- * and FCS/CRC (frame check sequence).
- */
-
-#define ETH_ALEN 6 /* Octets in one ethernet addr */
-#define ETH_HLEN 14 /* Total octets in header. */
-#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
-#define ETH_DATA_LEN 1500 /* Max. octets in payload */
-#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
-
-/*
- * These are the defined Ethernet Protocol ID's.
- */
-
-#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */
-#define ETH_P_PUP 0x0200 /* Xerox PUP packet */
-#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */
-#define ETH_P_IP 0x0800 /* Internet Protocol packet */
-#define ETH_P_X25 0x0805 /* CCITT X.25 */
-#define ETH_P_ARP 0x0806 /* Address Resolution packet */
-#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet
- * [ NOT AN OFFICIAL ID ] */
-#define ETH_P_IEEEPUP 0x0a00 /* Xerox IEEE802.3 PUP packet */
-#define ETH_P_IEEEPUPAT 0x0a01 /* Xerox IEEE802.3 PUP Addr
- * Trans packet */
-#define ETH_P_DEC 0x6000 /* DEC Assigned proto */
-#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */
-#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */
-#define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */
-#define ETH_P_LAT 0x6004 /* DEC LAT */
-#define ETH_P_DIAG 0x6005 /* DEC Diagnostics */
-#define ETH_P_CUST 0x6006 /* DEC Customer use */
-#define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */
-#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */
-#define ETH_P_ATALK 0x809B /* Appletalk DDP */
-#define ETH_P_AARP 0x80F3 /* Appletalk AARP */
-#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */
-#define ETH_P_IPX 0x8137 /* IPX over DIX */
-#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */
-#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */
-#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */
-#define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */
-#define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport
- * over Ethernet
- */
-
-/*
- * Non DIX types. Won't clash for 1500 types.
- */
-
-#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */
-#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */
-#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */
-#define ETH_P_802_2 0x0004 /* 802.2 frames */
-#define ETH_P_SNAP 0x0005 /* Internal only */
-#define ETH_P_DDCMP 0x0006 /* DEC DDCMP: Internal only */
-#define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/
-#define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */
-#define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */
-#define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/
-#define ETH_P_TR_802_2 0x0011i /* 802.2 frames */
-#define ETH_P_MOBITEX 0x0015 /* Mobitex (kaz@cafe.net) */
-#define ETH_P_CONTROL 0x0016 /* Card specific control frames */
-#define ETH_P_IRDA 0x0017 /* Linux-IrDA */
-#define ETH_P_ECONET 0x0018 /* Acorn Econet */
-
-/*
- * This is an Ethernet frame header.
- */
-
-struct ethhdr {
- unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
- unsigned char h_source[ETH_ALEN]; /* source ether addr */
- unsigned short h_proto; /* packet type ID field */
-};
-
-struct _vlan {
- unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID*/
- unsigned short h_vlan_encapsulated_proto;
-};
-
-
-
-#define get_vlan_id(pvlan) ((ntohs((unsigned short)pvlan->h_vlan_TCI)) & 0xfff)
-#define get_vlan_priority(pvlan) ((ntohs((unsigned short)\
- pvlan->h_vlan_TCI)) >> 13)
-#define get_vlan_encap_proto(pvlan) (ntohs((unsigned short)\
- pvlan->h_vlan_encapsulated_proto))
-
-
-#endif /* _LINUX_IF_ETHER_H */
-
diff --git a/drivers/staging/rtl8712/ip.h b/drivers/staging/rtl8712/ip.h
deleted file mode 100644
index f37b0f8d14d4..000000000000
--- a/drivers/staging/rtl8712/ip.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the IP protocol.
- *
- * Version: @(#)ip.h 1.0.2 04/28/93
- *
- * Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.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.
- */
-#ifndef _LINUX_IP_H
-#define _LINUX_IP_H
-
-#include "rtl871x_byteorder.h"
-
-/* SOL_IP socket options */
-
-#define IPTOS_TOS_MASK 0x1E
-#define IPTOS_TOS(tos) ((tos)&IPTOS_TOS_MASK)
-#define IPTOS_LOWDELAY 0x10
-#define IPTOS_THROUGHPUT 0x08
-#define IPTOS_RELIABILITY 0x04
-#define IPTOS_MINCOST 0x02
-
-#define IPTOS_PREC_MASK 0xE0
-#define IPTOS_PREC(tos) ((tos)&IPTOS_PREC_MASK)
-#define IPTOS_PREC_NETCONTROL 0xe0
-#define IPTOS_PREC_INTERNETCONTROL 0xc0
-#define IPTOS_PREC_CRITIC_ECP 0xa0
-#define IPTOS_PREC_FLASHOVERRIDE 0x80
-#define IPTOS_PREC_FLASH 0x60
-#define IPTOS_PREC_IMMEDIATE 0x40
-#define IPTOS_PREC_PRIORITY 0x20
-#define IPTOS_PREC_ROUTINE 0x00
-
-/* IP options */
-#define IPOPT_COPY 0x80
-#define IPOPT_CLASS_MASK 0x60
-#define IPOPT_NUMBER_MASK 0x1f
-
-#define IPOPT_COPIED(o) ((o)&IPOPT_COPY)
-#define IPOPT_CLASS(o) ((o)&IPOPT_CLASS_MASK)
-#define IPOPT_NUMBER(o) ((o)&IPOPT_NUMBER_MASK)
-
-#define IPOPT_CONTROL 0x00
-#define IPOPT_RESERVED1 0x20
-#define IPOPT_MEASUREMENT 0x40
-#define IPOPT_RESERVED2 0x60
-
-#define IPOPT_END (0 | IPOPT_CONTROL)
-#define IPOPT_NOOP (1 | IPOPT_CONTROL)
-#define IPOPT_SEC (2 | IPOPT_CONTROL|IPOPT_COPY)
-#define IPOPT_LSRR (3 | IPOPT_CONTROL|IPOPT_COPY)
-#define IPOPT_TIMESTAMP (4 | IPOPT_MEASUREMENT)
-#define IPOPT_RR (7 | IPOPT_CONTROL)
-#define IPOPT_SID (8 | IPOPT_CONTROL | IPOPT_COPY)
-#define IPOPT_SSRR (9 | IPOPT_CONTROL | IPOPT_COPY)
-#define IPOPT_RA (20 | IPOPT_CONTROL | IPOPT_COPY)
-
-#define IPVERSION 4
-#define MAXTTL 255
-#define IPDEFTTL 64
-
-/* struct timestamp, struct route and MAX_ROUTES are removed.
- *
- * REASONS: it is clear that nobody used them because:
- * - MAX_ROUTES value was wrong.
- * - "struct route" was wrong.
- * - "struct timestamp" had fatally misaligned bitfields and was completely
- * unusable.
- */
-
-#define IPOPT_OPTVAL 0
-#define IPOPT_OLEN 1
-#define IPOPT_OFFSET 2
-#define IPOPT_MINOFF 4
-#define MAX_IPOPTLEN 40
-#define IPOPT_NOP IPOPT_NOOP
-#define IPOPT_EOL IPOPT_END
-#define IPOPT_TS IPOPT_TIMESTAMP
-
-#define IPOPT_TS_TSONLY 0 /* timestamps only */
-#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
-#define IPOPT_TS_PRESPEC 3 /* specified modules only */
-
-struct ip_options {
- __u32 faddr; /* Saved first hop address */
- unsigned char optlen;
- unsigned char srr;
- unsigned char rr;
- unsigned char ts;
- unsigned char is_setbyuser:1, /* Set by setsockopt? */
- is_data:1, /* Options in __data, rather than skb */
- is_strictroute:1, /* Strict source route */
- srr_is_hit:1, /* Packet destination addr was our one*/
- is_changed:1, /* IP checksum more not valid */
- rr_needaddr:1, /* Need to record addr of outgoing dev*/
- ts_needtime:1, /* Need to record timestamp */
- ts_needaddr:1; /* Need to record addr of outgoing dev*/
- unsigned char router_alert;
- unsigned char __pad1;
- unsigned char __pad2;
- unsigned char __data[0];
-};
-
-#define optlength(opt) (sizeof(struct ip_options) + opt->optlen)
-
-struct iphdr {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- __u8 ihl:4,
- version:4;
-#elif defined(__BIG_ENDIAN_BITFIELD)
- __u8 version:4,
- ihl:4;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
- __u8 tos;
- __u16 tot_len;
- __u16 id;
- __u16 frag_off;
- __u8 ttl;
- __u8 protocol;
- __u16 check;
- __u32 saddr;
- __u32 daddr;
- /*The options start here. */
-};
-
-#endif /* _LINUX_IP_H */
-
diff --git a/drivers/staging/rtl8712/little_endian.h b/drivers/staging/rtl8712/little_endian.h
deleted file mode 100644
index cd57d6c2850f..000000000000
--- a/drivers/staging/rtl8712/little_endian.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _LINUX_BYTEORDER_LITTLE_ENDIAN_H
-#define _LINUX_BYTEORDER_LITTLE_ENDIAN_H
-
-#ifndef __LITTLE_ENDIAN
-#define __LITTLE_ENDIAN 1234
-#endif
-#ifndef __LITTLE_ENDIAN_BITFIELD
-#define __LITTLE_ENDIAN_BITFIELD
-#endif
-
-#include "swab.h"
-
-#define __constant_htonl(x) ___constant_swab32((x))
-#define __constant_ntohl(x) ___constant_swab32((x))
-#define __constant_htons(x) ___constant_swab16((x))
-#define __constant_ntohs(x) ___constant_swab16((x))
-#define __constant_cpu_to_le64(x) ((__u64)(x))
-#define __constant_le64_to_cpu(x) ((__u64)(x))
-#define __constant_cpu_to_le32(x) ((__u32)(x))
-#define __constant_le32_to_cpu(x) ((__u32)(x))
-#define __constant_cpu_to_le16(x) ((__u16)(x))
-#define __constant_le16_to_cpu(x) ((__u16)(x))
-#define __constant_cpu_to_be64(x) ___constant_swab64((x))
-#define __constant_be64_to_cpu(x) ___constant_swab64((x))
-#define __constant_cpu_to_be32(x) ___constant_swab32((x))
-#define __constant_be32_to_cpu(x) ___constant_swab32((x))
-#define __constant_cpu_to_be16(x) ___constant_swab16((x))
-#define __constant_be16_to_cpu(x) ___constant_swab16((x))
-#define __cpu_to_le64(x) ((__u64)(x))
-#define __le64_to_cpu(x) ((__u64)(x))
-#define __cpu_to_le32(x) ((__u32)(x))
-#define __le32_to_cpu(x) ((__u32)(x))
-#define __cpu_to_le16(x) ((__u16)(x))
-#define __le16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_be64(x) __swab64((x))
-#define __be64_to_cpu(x) __swab64((x))
-#define __cpu_to_be32(x) __swab32((x))
-#define __be32_to_cpu(x) __swab32((x))
-#define __cpu_to_be16(x) __swab16((x))
-#define __be16_to_cpu(x) __swab16((x))
-#define __cpu_to_le64p(x) (*(__u64 *)(x))
-#define __le64_to_cpup(x) (*(__u64 *)(x))
-#define __cpu_to_le32p(x) (*(__u32 *)(x))
-#define __le32_to_cpup(x) (*(__u32 *)(x))
-#define __cpu_to_le16p(x) (*(__u16 *)(x))
-#define __le16_to_cpup(x) (*(__u16 *)(x))
-#define __cpu_to_be64p(x) __swab64p((x))
-#define __be64_to_cpup(x) __swab64p((x))
-#define __cpu_to_be32p(x) __swab32p((x))
-#define __be32_to_cpup(x) __swab32p((x))
-#define __cpu_to_be16p(x) __swab16p((x))
-#define __be16_to_cpup(x) __swab16p((x))
-#define __cpu_to_le64s(x) do {} while (0)
-#define __le64_to_cpus(x) do {} while (0)
-#define __cpu_to_le32s(x) do {} while (0)
-#define __le32_to_cpus(x) do {} while (0)
-#define __cpu_to_le16s(x) do {} while (0)
-#define __le16_to_cpus(x) do {} while (0)
-#define __cpu_to_be64s(x) __swab64s((x))
-#define __be64_to_cpus(x) __swab64s((x))
-#define __cpu_to_be32s(x) __swab32s((x))
-#define __be32_to_cpus(x) __swab32s((x))
-#define __cpu_to_be16s(x) __swab16s((x))
-#define __be16_to_cpus(x) __swab16s((x))
-
-#include "generic.h"
-
-#endif /* _LINUX_BYTEORDER_LITTLE_ENDIAN_H */
-
diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c
index 7bbd53a410e3..448f00dd68fe 100644
--- a/drivers/staging/rtl8712/os_intfs.c
+++ b/drivers/staging/rtl8712/os_intfs.c
@@ -52,7 +52,7 @@ static int lbkmode = RTL8712_AIR_TRX;
static int hci = RTL8712_USB;
static int ampdu_enable = 1;/*for enable tx_ampdu*/
-/* The video_mode variable is for vedio mode.*/
+/* The video_mode variable is for video mode.*/
/* It may be specify when inserting module with video_mode=1 parameter.*/
static int video_mode = 1; /* enable video mode*/
@@ -248,7 +248,7 @@ static u32 start_drv_threads(struct _adapter *padapter)
void r8712_stop_drv_threads(struct _adapter *padapter)
{
- /*Below is to termindate r8712_cmd_thread & event_thread...*/
+ /*Below is to terminate r8712_cmd_thread & event_thread...*/
up(&padapter->cmdpriv.cmd_queue_sema);
if (padapter->cmdThread)
_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema);
diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h
index 9ba603310fdc..f1ccc7ebbda7 100644
--- a/drivers/staging/rtl8712/osdep_service.h
+++ b/drivers/staging/rtl8712/osdep_service.h
@@ -29,7 +29,6 @@
#define _SUCCESS 1
#define _FAIL 0
-#include <linux/version.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
@@ -107,8 +106,6 @@ static inline void _set_workitem(_workitem *pwork)
schedule_work(pwork);
}
-#include "rtl871x_byteorder.h"
-
#ifndef BIT
#define BIT(x) (1 << (x))
#endif
diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c
index 9f6ebc419b0b..088647cdca99 100644
--- a/drivers/staging/rtl8712/rtl8712_cmd.c
+++ b/drivers/staging/rtl8712/rtl8712_cmd.c
@@ -50,7 +50,6 @@
#include "drv_types.h"
#include "recv_osdep.h"
#include "mlme_osdep.h"
-#include "rtl871x_byteorder.h"
#include "rtl871x_ioctl_set.h"
static void check_hw_pbc(struct _adapter *padapter)
@@ -69,7 +68,7 @@ static void check_hw_pbc(struct _adapter *padapter)
* After trigger PBC, the variable will be set to false */
DBG_8712("CheckPbcGPIO - PBC is pressed !!!!\n");
/* 0 is the default value and it means the application monitors
- * the HW PBC doesn't privde its pid to driver. */
+ * the HW PBC doesn't provide its pid to driver. */
if (padapter->pid == 0)
return;
kill_pid(find_vpid(padapter->pid), SIGUSR1, 1);
@@ -382,7 +381,7 @@ _next:
*pcmdbuf = cpu_to_le32((cmdsz & 0x0000ffff) |
(pcmd->cmdcode << 16) |
(pcmdpriv->cmd_seq << 24));
- pcmdbuf += 2 ; /* 8 bytes aligment */
+ pcmdbuf += 2 ; /* 8 bytes alignment */
memcpy((u8 *)pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
while (check_cmd_fifo(padapter, wr_sz) == _FAIL) {
if ((padapter->bDriverStopped == true) ||
@@ -471,7 +470,7 @@ void r8712_event_handle(struct _adapter *padapter, uint *peventbuf)
pevt_priv->event_seq++; /* update evt_seq */
if (pevt_priv->event_seq > 127)
pevt_priv->event_seq = 0;
- peventbuf = peventbuf + 2; /* move to event content, 8 bytes aligment */
+ peventbuf = peventbuf + 2; /* move to event content, 8 bytes alignment */
if (peventbuf) {
event_callback = wlanevents[evt_code].event_callback;
if (event_callback)
diff --git a/drivers/staging/rtl8712/rtl8712_cmd.h b/drivers/staging/rtl8712/rtl8712_cmd.h
index 766a6463266a..039ab3e97172 100644
--- a/drivers/staging/rtl8712/rtl8712_cmd.h
+++ b/drivers/staging/rtl8712/rtl8712_cmd.h
@@ -121,7 +121,7 @@ enum rtl8712_h2c_cmd {
GEN_CMD_CODE(_GetCurDataRate) ,
GEN_CMD_CODE(_GetTxRetrycnt), /* to record times that Tx retry to
- * transmmit packet after association
+ * transmit packet after association
*/
GEN_CMD_CODE(_GetRxRetrycnt), /* to record total number of the
* received frame with ReTry bit set in
diff --git a/drivers/staging/rtl8712/rtl8712_efuse.c b/drivers/staging/rtl8712/rtl8712_efuse.c
index b08e9a25c9c5..377fca905801 100644
--- a/drivers/staging/rtl8712/rtl8712_efuse.c
+++ b/drivers/staging/rtl8712/rtl8712_efuse.c
@@ -417,7 +417,7 @@ u8 r8712_efuse_pg_packet_write(struct _adapter *padapter, const u8 offset,
} else { /* write header fail */
bResult = false;
if (0xFF == efuse_data)
- return bResult; /* not thing damaged. */
+ return bResult; /* nothing damaged. */
/* call rescue procedure */
if (fix_header(padapter, efuse_data, efuse_addr) ==
false)
diff --git a/drivers/staging/rtl8712/rtl8712_gp_bitdef.h b/drivers/staging/rtl8712/rtl8712_gp_bitdef.h
index 884a8212176d..138ea453d9df 100644
--- a/drivers/staging/rtl8712/rtl8712_gp_bitdef.h
+++ b/drivers/staging/rtl8712/rtl8712_gp_bitdef.h
@@ -70,7 +70,7 @@
#define GPIOSEL_BT 2 /* BT_coex*/
#define GPIOSEL_WLANDBG 3 /* WLANDBG*/
#define GPIOSEL_GPIO_MASK (~(BIT(0)|BIT(1)))
-/* HW Readio OFF switch (GPIO BIT) */
+/* HW Radio OFF switch (GPIO BIT) */
#define HAL_8192S_HW_GPIO_OFF_BIT BIT(3)
#define HAL_8192S_HW_GPIO_OFF_MASK 0xF7
#define HAL_8192S_HW_GPIO_WPS_BIT BIT(4)
diff --git a/drivers/staging/rtl8712/rtl8712_hal.h b/drivers/staging/rtl8712/rtl8712_hal.h
index d19865a5a50c..4c51fa373b54 100644
--- a/drivers/staging/rtl8712/rtl8712_hal.h
+++ b/drivers/staging/rtl8712/rtl8712_hal.h
@@ -83,7 +83,7 @@ struct fw_priv { /*8-bytes alignment required*/
unsigned char rfintfs; /* 0:SWSI, 1:HWSI, 2:HWPI*/
unsigned char def_nettype;
unsigned char turboMode;
- unsigned char lowPowerMode;/* 0: noral mode, 1: low power mode*/
+ unsigned char lowPowerMode;/* 0: normal mode, 1: low power mode*/
/*--- long word 2 ----*/
unsigned char lbk_mode; /*0x00: normal, 0x03: MACLBK, 0x01: PHYLBK*/
unsigned char mp_mode; /* 1: for MP use, 0: for normal driver */
@@ -123,7 +123,7 @@ struct fw_priv { /*8-bytes alignment required*/
unsigned char rsvd053;
};
-struct fw_hdr {/*8-byte alinment required*/
+struct fw_hdr {/*8-byte alignment required*/
unsigned short signature;
unsigned short version; /*0x8000 ~ 0x8FFF for FPGA version,
*0x0000 ~ 0x7FFF for ASIC version,*/
diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c
index bac56e5caf12..c9eb4b74799b 100644
--- a/drivers/staging/rtl8712/rtl8712_led.c
+++ b/drivers/staging/rtl8712/rtl8712_led.c
@@ -60,7 +60,7 @@ enum _LED_STATE_871x {
* the # of times to blink is depend on time
* for scanning. */
LED_NO_LINK_BLINK = 7, /* LED is blinking during no link state. */
- LED_BLINK_StartToBlink = 8,/* Customzied for Sercomm Printer
+ LED_BLINK_StartToBlink = 8,/* Customized for Sercomm Printer
* Server case */
LED_BLINK_WPS = 9, /* LED is blinkg during WPS communication */
LED_TXRX_BLINK = 10,
@@ -826,7 +826,7 @@ static void BlinkTimerCallback(unsigned long data)
{
struct LED_871x *pLed = (struct LED_871x *)data;
- /* This fixed the crash problem on Fedora 12 when trying to do thei
+ /* This fixed the crash problem on Fedora 12 when trying to do the
* insmod;ifconfig up;rmmod commands. */
if ((pLed->padapter->bSurpriseRemoved == true) ||
(pLed->padapter->bDriverStopped == true))
@@ -836,7 +836,7 @@ static void BlinkTimerCallback(unsigned long data)
/* Description:
* Callback function of LED BlinkWorkItem.
- * We dispatch acture LED blink action according to LedStrategy.
+ * We dispatch actual LED blink action according to LedStrategy.
*/
static void BlinkWorkItemCallback(struct work_struct *work)
{
diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c
index fa6dc9c09b3f..8e82ce2fee38 100644
--- a/drivers/staging/rtl8712/rtl8712_recv.c
+++ b/drivers/staging/rtl8712/rtl8712_recv.c
@@ -28,12 +28,13 @@
#define _RTL8712_RECV_C_
+#include <linux/if_ether.h>
+#include <linux/ip.h>
+
#include "osdep_service.h"
#include "drv_types.h"
#include "recv_osdep.h"
#include "mlme_osdep.h"
-#include "ip.h"
-#include "if_ether.h"
#include "ethernet.h"
#include "usb_ops.h"
#include "wifi.h"
@@ -459,7 +460,7 @@ void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf)
cmd_seq = (u8)((le32_to_cpu(voffset) >> 24) & 0x7f);
eid = (u8)((le32_to_cpu(voffset) >> 16) & 0xff);
r8712_event_handle(padapter, (uint *)poffset);
- poffset += (cmd_len + 8);/*8 bytes aligment*/
+ poffset += (cmd_len + 8);/*8 bytes alignment*/
} while (le32_to_cpu(voffset) & BIT(31));
}
@@ -603,7 +604,7 @@ static int recv_indicatepkt_reorder(struct _adapter *padapter,
}
}
spin_lock_irqsave(&ppending_recvframe_queue->lock, irql);
- /*s2. check if winstart_b(indicate_seq) needs to been updated*/
+ /*s2. check if winstart_b(indicate_seq) needs to be updated*/
if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num))
goto _err_exit;
/*s3. Insert all packet into Reorder Queue to maintain its ordering.*/
diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c
index 693331955d67..3d23514c0222 100644
--- a/drivers/staging/rtl8712/rtl8712_xmit.c
+++ b/drivers/staging/rtl8712/rtl8712_xmit.c
@@ -30,7 +30,6 @@
#include "osdep_service.h"
#include "drv_types.h"
-#include "rtl871x_byteorder.h"
#include "wifi.h"
#include "osdep_intf.h"
#include "usb_ops.h"
diff --git a/drivers/staging/rtl8712/rtl871x_byteorder.h b/drivers/staging/rtl8712/rtl871x_byteorder.h
deleted file mode 100644
index bd3703b98bce..000000000000
--- a/drivers/staging/rtl8712/rtl871x_byteorder.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#ifndef _RTL871X_BYTEORDER_H_
-#define _RTL871X_BYTEORDER_H_
-
-#if defined(__LITTLE_ENDIAN)
-# include "little_endian.h"
-#elif defined(__BIG_ENDIAN)
-# include "big_endian.h"
-#else
-# error "Must be LITTLE/BIG Endian Host"
-#endif
-
-#endif /* _RTL871X_BYTEORDER_H_ */
-
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c
index d77388bdba7b..659683e022b9 100644
--- a/drivers/staging/rtl8712/rtl871x_cmd.c
+++ b/drivers/staging/rtl8712/rtl871x_cmd.c
@@ -50,7 +50,6 @@
#include "drv_types.h"
#include "recv_osdep.h"
#include "mlme_osdep.h"
-#include "rtl871x_byteorder.h"
/*
Caller and the r8712_cmd_thread can protect cmd_q by spin_lock.
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.h b/drivers/staging/rtl8712/rtl871x_cmd.h
index 757ebf77e9d6..9d93189d8700 100644
--- a/drivers/staging/rtl8712/rtl871x_cmd.h
+++ b/drivers/staging/rtl8712/rtl871x_cmd.h
@@ -720,7 +720,7 @@ struct DisconnectCtrlEx_param {
* Result:
* 0x00: success
* 0x01: success, and check Response.
- * 0x02: cmd ignored due to duplicated sequcne number
+ * 0x02: cmd ignored due to duplicated sequence number
* 0x03: cmd dropped due to invalid cmd code
* 0x04: reserved.
*/
diff --git a/drivers/staging/rtl8712/rtl871x_io.h b/drivers/staging/rtl8712/rtl871x_io.h
index d3d8727c2ec5..dc23395fec3b 100644
--- a/drivers/staging/rtl8712/rtl871x_io.h
+++ b/drivers/staging/rtl8712/rtl871x_io.h
@@ -117,7 +117,7 @@ struct io_req {
u32 command;
u32 status;
u8 *pbuf;
- void (*_async_io_callback)(struct _adapter *padater,
+ void (*_async_io_callback)(struct _adapter *padapter,
struct io_req *pio_req, u8 *cnxt);
u8 *cnxt;
};
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
index ef35bc29a3fa..35e781fca4a0 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
@@ -43,7 +43,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/io.h>
#include <linux/semaphore.h>
#include <net/iw_handler.h>
@@ -242,7 +241,7 @@ static inline char *translate_scan(struct _adapter *padapter,
/* Add frequency/channel */
iwe.cmd = SIOCGIWFREQ;
{
- /* check legel index */
+ /* check legal index */
u8 dsconfig = pnetwork->network.Configuration.DSConfig;
if (dsconfig >= 1 && dsconfig <= sizeof(
ieee80211_wlan_frequencies) / sizeof(long))
@@ -810,11 +809,11 @@ static int r871x_wx_set_pmkid(struct net_device *dev,
/*
There are the BSSID information in the bssid.sa_data array.
- If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear
- all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
- wpa_supplicant wants to add a PMKID/BSSID to driver.
+ If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
+ all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
+ wpa_supplicant wants to add a PMKID/BSSID to driver.
If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
- remove a PMKID/BSSID from driver.
+ remove a PMKID/BSSID from driver.
*/
if (pPMK == NULL)
return -EINVAL;
@@ -924,7 +923,7 @@ static int r8711_wx_get_range(struct net_device *dev,
range->max_qual.noise = 100;
range->max_qual.updated = 7; /* Updated all three */
range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
- /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
+ /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
range->avg_qual.level = 20 + -98;
range->avg_qual.noise = 0;
range->avg_qual.updated = 7; /* Updated all three */
@@ -1071,7 +1070,7 @@ FREE_EXT:
* MAC# of a preferred Access Point.
* Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
*
- * For this operation to succeed, there is no need for the interface to be Up.
+ * For this operation to succeed, there is no need for the interface to be up.
*
*/
static int r8711_wx_set_wap(struct net_device *dev,
@@ -2389,10 +2388,10 @@ static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
struct iw_handler_def r871x_handlers_def = {
.standard = r8711_handlers,
- .num_standard = sizeof(r8711_handlers) / sizeof(iw_handler),
+ .num_standard = ARRAY_SIZE(r8711_handlers),
.private = r8711_private_handler,
.private_args = (struct iw_priv_args *)r8711_private_args,
- .num_private = sizeof(r8711_private_handler) / sizeof(iw_handler),
+ .num_private = ARRAY_SIZE(r8711_private_handler),
.num_private_args = sizeof(r8711_private_args) /
sizeof(struct iw_priv_args),
.get_wireless_stats = r871x_get_wireless_stats
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c
index fb29b423752f..f352b32355a0 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c
@@ -264,7 +264,7 @@ void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter,
(*pold_state == Ndis802_11Infrastructure) ||
(*pold_state == Ndis802_11IBSS)) {
/* will clr Linked_state before this function,
- * we must have chked whether issue dis-assoc_cmd or
+ * we must have checked whether issue dis-assoc_cmd or
* not */
r8712_ind_disconnect(padapter);
}
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c
index 4277d0304b7a..dc7adc132d12 100644
--- a/drivers/staging/rtl8712/rtl871x_mlme.c
+++ b/drivers/staging/rtl8712/rtl871x_mlme.c
@@ -137,7 +137,7 @@ static void _free_network_nolock(struct mlme_priv *pmlmepriv,
/*
return the wlan_network with the matching addr
- Shall be calle under atomic context...
+ Shall be called under atomic context...
to avoid possible racing condition...
*/
static struct wlan_network *_r8712_find_network(struct __queue *scanned_queue,
@@ -255,7 +255,7 @@ void r8712_free_network_queue(struct _adapter *dev)
/*
return the wlan_network with the matching addr
- Shall be calle under atomic context...
+ Shall be called under atomic context...
to avoid possible racing condition...
*/
static struct wlan_network *r8712_find_network(struct __queue *scanned_queue,
@@ -1037,7 +1037,7 @@ void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf)
* and the WiFi client will drop the data with seq number 0.
* So, the 8712 firmware has to inform driver with receiving the
* ADDBA-Req frame so that the driver can reset the
- * sequence value of Rx reorder contorl.
+ * sequence value of Rx reorder control.
*/
void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf)
{
@@ -1775,7 +1775,7 @@ static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
}
/* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
- * if A-MPDU Rx is enabled, reseting rx_ordering_ctrl
+ * if A-MPDU Rx is enabled, resetting rx_ordering_ctrl
* wstart_b(indicate_seq) to default value=0xffff
* todo: check if AP can send A-MPDU packets
*/
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h
index 71ca01350b5e..42bd0bf8a816 100644
--- a/drivers/staging/rtl8712/rtl871x_mlme.h
+++ b/drivers/staging/rtl8712/rtl871x_mlme.h
@@ -69,8 +69,8 @@ since mlme_priv is a shared resource between many threads,
like ISR/Call-Back functions, the OID handlers, and even timer functions.
Each _queue has its own locks, already.
Other items are protected by mlme_priv.lock.
-To avoid possible dead lock, any thread trying to modifiying mlme_priv
-SHALL not lock up more than one locks at a time!
+To avoid possible dead lock, any thread trying to modify mlme_priv
+SHALL not lock up more than one lock at a time!
*/
#define traffic_threshold 10
@@ -132,7 +132,7 @@ static inline sint get_fwstate(struct mlme_priv *pmlmepriv)
* therefore set it to be the critical section...
*
* ### NOTE:#### (!!!!)
- * TAKE CARE THAT BEFORE CALLING THIS FUNC, LOCK pmlmepriv->lock
+ * TAKE CARE BEFORE CALLING THIS FUNC, LOCK pmlmepriv->lock
*/
static inline void set_fwstate(struct mlme_priv *pmlmepriv, sint state)
{
diff --git a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h b/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h
index 23532a793859..8e2586231ffd 100644
--- a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h
+++ b/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h
@@ -184,7 +184,7 @@
/*RxIQ DC offset, Rx digital filter, DC notch filter */
#define rOFDM0_XARxAFE 0xc10
-#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imblance matrix */
+#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imbalance matrix */
#define rOFDM0_XBRxAFE 0xc18
#define rOFDM0_XBRxIQImbalance 0xc1c
#define rOFDM0_XCRxAFE 0xc20
@@ -603,7 +603,7 @@
#define bCCKRxIG 0x7f00
#define bCCKLNAPolarity 0x800000
#define bCCKRx1stGain 0x7f0000
-#define bCCKRFExtend 0x20000000 /* CCK Rx Iinital gain polarity */
+#define bCCKRFExtend 0x20000000 /* CCK Rx inital gain polarity */
#define bCCKRxAGCSatLevel 0x1f000000
#define bCCKRxAGCSatCount 0xe0
#define bCCKRxRFSettle 0x1f /* AGCsamp_dly */
diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c
index 5b03b405883e..c9d1743e5c5d 100644
--- a/drivers/staging/rtl8712/rtl871x_recv.c
+++ b/drivers/staging/rtl8712/rtl871x_recv.c
@@ -28,15 +28,15 @@
#define _RTL871X_RECV_C_
+#include <linux/ip.h>
#include <linux/slab.h>
+#include <linux/if_ether.h>
#include <linux/kmemleak.h>
#include "osdep_service.h"
#include "drv_types.h"
#include "recv_osdep.h"
#include "mlme_osdep.h"
-#include "ip.h"
-#include "if_ether.h"
#include "ethernet.h"
#include "usb_ops.h"
#include "wifi.h"
diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c
index aa57e7754f04..78f570b571a7 100644
--- a/drivers/staging/rtl8712/rtl871x_xmit.c
+++ b/drivers/staging/rtl8712/rtl871x_xmit.c
@@ -30,7 +30,6 @@
#include "osdep_service.h"
#include "drv_types.h"
-#include "rtl871x_byteorder.h"
#include "wifi.h"
#include "osdep_intf.h"
#include "usb_ops.h"
@@ -72,7 +71,7 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv));
spin_lock_init(&pxmitpriv->lock);
/*
- Please insert all the queue initializaiton using _init_queue below
+ Please insert all the queue initialization using _init_queue below
*/
pxmitpriv->adapter = padapter;
_init_queue(&pxmitpriv->be_pending);
diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h
index 638b79b4c5a8..ee906987735a 100644
--- a/drivers/staging/rtl8712/rtl871x_xmit.h
+++ b/drivers/staging/rtl8712/rtl871x_xmit.h
@@ -119,7 +119,7 @@ struct pkt_attrib {
u8 priority;
u8 encrypt; /* when 0 indicate no encrypt. when non-zero,
- * indicate the encrypt algorith*/
+ * indicate the encrypt algorithm*/
u8 iv_len;
u8 icv_len;
unsigned char iv[8];
diff --git a/drivers/staging/rtl8712/swab.h b/drivers/staging/rtl8712/swab.h
deleted file mode 100644
index f12781829c1b..000000000000
--- a/drivers/staging/rtl8712/swab.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _LINUX_BYTEORDER_SWAB_H
-#define _LINUX_BYTEORDER_SWAB_H
-
-#ifndef __u16
- #define __u16 unsigned short
-#endif
-
-#ifndef __u32
- #define __u32 unsigned int
-#endif
-
-#ifndef __u8
- #define __u8 unsigned char
-#endif
-
-#ifndef __u64
- #define __u64 unsigned long long
-#endif
-
-
-static inline __u16 ___swab16(__u16 x)
-{
- __u16 __x = x;
- return (__u16)(
- (((__u16)(__x) & (__u16)0x00ffU) << 8) |
- (((__u16)(__x) & (__u16)0xff00U) >> 8));
-
-}
-
-static inline __u32 ___swab32(__u32 x)
-{
- __u32 __x = (x);
- return (__u32)(
- (((__u32)(__x) & (__u32)0x000000ffUL) << 24) |
- (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) |
- (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) |
- (((__u32)(__x) & (__u32)0xff000000UL) >> 24));
-}
-
-static inline __u64 ___swab64(__u64 x)
-{
- __u64 __x = (x);
-
- return (__u64)( \
- (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \
- (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \
- (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \
- (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \
- (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \
- (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
- (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \
- (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56));
-}
-
-#ifndef __arch__swab16
-static inline __u16 __arch__swab16(__u16 x)
-{
- return ___swab16(x);
-}
-
-#endif
-
-#ifndef __arch__swab32
-static inline __u32 __arch__swab32(__u32 x)
-{
- __u32 __tmp = (x) ;
- return ___swab32(__tmp);
-}
-#endif
-
-#ifndef __arch__swab64
-
-static inline __u64 __arch__swab64(__u64 x)
-{
- __u64 __tmp = (x) ;
- return ___swab64(__tmp);
-}
-
-
-#endif
-
-#define __swab16(x) __fswab16(x)
-#define __swab32(x) __fswab32(x)
-#define __swab64(x) __fswab64(x)
-
-static inline const __u16 __fswab16(__u16 x)
-{
- return __arch__swab16(x);
-}
-static inline const __u32 __fswab32(__u32 x)
-{
- return __arch__swab32(x);
-}
-
-#define swab16 __swab16
-#define swab32 __swab32
-#define swab64 __swab64
-#define swab16p __swab16p
-#define swab32p __swab32p
-#define swab64p __swab64p
-#define swab16s __swab16s
-#define swab32s __swab32s
-#define swab64s __swab64s
-
-#endif /* _LINUX_BYTEORDER_SWAB_H */
-
diff --git a/drivers/staging/rtl8712/usb_halinit.c b/drivers/staging/rtl8712/usb_halinit.c
index 46287c17a417..b4ae11a78b46 100644
--- a/drivers/staging/rtl8712/usb_halinit.c
+++ b/drivers/staging/rtl8712/usb_halinit.c
@@ -141,7 +141,7 @@ u8 r8712_usb_hal_bus_init(struct _adapter *padapter)
/* Enable AFE PLL Macro Block */
val8 = r8712_read8(padapter, AFE_PLL_CTRL);
r8712_write8(padapter, AFE_PLL_CTRL, (val8 | 0x11));
- /* Attatch AFE PLL to MACTOP/BB/PCIe Digital */
+ /* Attach AFE PLL to MACTOP/BB/PCIe Digital */
val8 = r8712_read8(padapter, SYS_ISO_CTRL);
r8712_write8(padapter, SYS_ISO_CTRL, (val8 & 0xEE));
/* Switch to 40M clock */
@@ -234,7 +234,7 @@ u8 r8712_usb_hal_bus_init(struct _adapter *padapter)
udelay(500);
r8712_write8(padapter, AFE_PLL_CTRL, (val8 | 0x11));
udelay(500);
- /* Attatch AFE PLL to MACTOP/BB/PCIe Digital */
+ /* Attach AFE PLL to MACTOP/BB/PCIe Digital */
val8 = r8712_read8(padapter, SYS_ISO_CTRL);
r8712_write8(padapter, SYS_ISO_CTRL, (val8 & 0xEE));
/* Switch to 40M clock */
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
index e419b4fd82b9..9bd18e2d0513 100644
--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -621,30 +621,28 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)
struct usb_device *udev = interface_to_usbdev(pusb_intf);
usb_set_intfdata(pusb_intf, NULL);
- if (padapter) {
- if (padapter->fw_found)
- release_firmware(padapter->fw);
- /* never exit with a firmware callback pending */
- wait_for_completion(&padapter->rtl8712_fw_ready);
- if (drvpriv.drv_registered == true)
- padapter->bSurpriseRemoved = true;
- if (pnetdev != NULL) {
- /* will call netdev_close() */
- unregister_netdev(pnetdev);
- }
- flush_scheduled_work();
- udelay(1);
- /*Stop driver mlme relation timer */
- if (padapter->fw_found)
- r8712_stop_drv_timers(padapter);
- r871x_dev_unload(padapter);
- r8712_free_drv_sw(padapter);
+ if (padapter->fw_found)
+ release_firmware(padapter->fw);
+ /* never exit with a firmware callback pending */
+ wait_for_completion(&padapter->rtl8712_fw_ready);
+ if (drvpriv.drv_registered == true)
+ padapter->bSurpriseRemoved = true;
+ if (pnetdev != NULL) {
+ /* will call netdev_close() */
+ unregister_netdev(pnetdev);
}
+ flush_scheduled_work();
+ udelay(1);
+ /*Stop driver mlme relation timer */
+ if (padapter->fw_found)
+ r8712_stop_drv_timers(padapter);
+ r871x_dev_unload(padapter);
+ r8712_free_drv_sw(padapter);
usb_set_intfdata(pusb_intf, NULL);
/* decrease the reference count of the usb device structure
* when disconnect */
usb_put_dev(udev);
- /* If we didn't unplug usb dongle and remove/insert modlue, driver
+ /* If we didn't unplug usb dongle and remove/insert module, driver
* fails on sitesurvey for the first time when device is up.
* Reset usb port for sitesurvey fail issue. */
if (udev->state != USB_STATE_NOTATTACHED)
diff --git a/drivers/staging/rtl8712/usb_ops.c b/drivers/staging/rtl8712/usb_ops.c
index 5a8b0ebd0b79..c03508d935f2 100644
--- a/drivers/staging/rtl8712/usb_ops.c
+++ b/drivers/staging/rtl8712/usb_ops.c
@@ -33,7 +33,6 @@
#include "osdep_intf.h"
#include "usb_ops.h"
#include "recv_osdep.h"
-#include "rtl871x_byteorder.h"
static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
{
diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h
index 277398cff0a7..793443e758ac 100644
--- a/drivers/staging/rtl8712/wifi.h
+++ b/drivers/staging/rtl8712/wifi.h
@@ -26,7 +26,6 @@
#ifndef _WIFI_H_
#define _WIFI_H_
-#include "rtl871x_byteorder.h"
#include <linux/compiler.h>
#ifdef BIT
diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c
index c9703627c8f5..65542cb7168f 100644
--- a/drivers/staging/rtl8712/xmit_linux.c
+++ b/drivers/staging/rtl8712/xmit_linux.c
@@ -29,14 +29,12 @@
#define _XMIT_OSDEP_C_
#include <linux/usb.h>
+#include <linux/ip.h>
+#include <linux/if_ether.h>
#include "osdep_service.h"
#include "drv_types.h"
-
-#include "if_ether.h"
-#include "ip.h"
-#include "rtl871x_byteorder.h"
#include "wifi.h"
#include "mlme_osdep.h"
#include "xmit_osdep.h"
diff --git a/drivers/staging/rts5139/ms.c b/drivers/staging/rts5139/ms.c
index b0e9071c8e52..6eef33b03f55 100644
--- a/drivers/staging/rts5139/ms.c
+++ b/drivers/staging/rts5139/ms.c
@@ -2680,7 +2680,7 @@ static int mspro_set_rw_cmd(struct rts51x_chip *chip, u32 start_sec,
return STATUS_SUCCESS;
}
-void mspro_stop_seq_mode(struct rts51x_chip *chip)
+static void mspro_stop_seq_mode(struct rts51x_chip *chip)
{
struct ms_info *ms_card = &(chip->ms_card);
int retval;
@@ -3149,7 +3149,7 @@ Fail:
TRACE_RET(chip, STATUS_FAIL);
sec_cnt = chip->rsp_buf[0];
- RTS51X_DEBUGP("%d pages need be trasferred, %d pages remained\n",
+ RTS51X_DEBUGP("%d pages need be transferred, %d pages remained\n",
(int)page_cnt, (int)sec_cnt);
page_addr = start_page + (page_cnt - sec_cnt);
@@ -3864,7 +3864,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
log_blk = (u16) (start_sector >> ms_card->block_shift);
start_page = (u8) (start_sector & ms_card->page_off);
- for (seg_no = 0; seg_no < sizeof(ms_start_idx) / 2; seg_no++) {
+ for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1; seg_no++) {
if (log_blk < ms_start_idx[seg_no + 1])
break;
}
@@ -4020,7 +4020,8 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
log_blk++;
- for (seg_no = 0; seg_no < sizeof(ms_start_idx) / 2; seg_no++) {
+ for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1;
+ seg_no++) {
if (log_blk < ms_start_idx[seg_no + 1])
break;
}
@@ -4134,7 +4135,7 @@ void ms_cleanup_work(struct rts51x_chip *chip)
}
}
-int ms_power_off_card3v3(struct rts51x_chip *chip)
+static int ms_power_off_card3v3(struct rts51x_chip *chip)
{
int retval;
diff --git a/drivers/staging/rts5139/ms.h b/drivers/staging/rts5139/ms.h
index 3ce1dc90f19d..0321d06e776d 100644
--- a/drivers/staging/rts5139/ms.h
+++ b/drivers/staging/rts5139/ms.h
@@ -234,7 +234,6 @@
void mspro_polling_format_status(struct rts51x_chip *chip);
void mspro_format_sense(struct rts51x_chip *chip, unsigned int lun);
-void mspro_stop_seq_mode(struct rts51x_chip *chip);
int reset_ms_card(struct rts51x_chip *chip);
int ms_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
u16 sector_cnt);
@@ -242,7 +241,6 @@ int mspro_format(struct scsi_cmnd *srb, struct rts51x_chip *chip,
int short_data_len, int quick_format);
void ms_free_l2p_tbl(struct rts51x_chip *chip);
void ms_cleanup_work(struct rts51x_chip *chip);
-int ms_power_off_card3v3(struct rts51x_chip *chip);
int release_ms_card(struct rts51x_chip *chip);
int ms_delay_write(struct rts51x_chip *chip);
diff --git a/drivers/staging/rts5139/ms_mg.c b/drivers/staging/rts5139/ms_mg.c
index 154b5230aa5e..057d96c1a937 100644
--- a/drivers/staging/rts5139/ms_mg.c
+++ b/drivers/staging/rts5139/ms_mg.c
@@ -38,7 +38,7 @@
#ifdef SUPPORT_MAGIC_GATE
-int mg_check_int_error(struct rts51x_chip *chip)
+static int mg_check_int_error(struct rts51x_chip *chip)
{
u8 value;
@@ -444,7 +444,7 @@ int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
*
* Since the extra 4 bytes data is just only a prefix to original data
* that read from medium, so that the 4-byte data pushed into Ring buffer
- * precedes data tramsinssion from medium to Ring buffer by DMA mechanisim
+ * precedes data transmission from medium to Ring buffer by DMA mechanism
* in order to get maximum performance and minimum code size simultaneously.
*/
int mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
diff --git a/drivers/staging/rts5139/rts51x.c b/drivers/staging/rts5139/rts51x.c
index 2b9f785954df..c3fe7dda1f4e 100644
--- a/drivers/staging/rts5139/rts51x.c
+++ b/drivers/staging/rts5139/rts51x.c
@@ -56,12 +56,6 @@ MODULE_DESCRIPTION(RTS51X_DESC);
MODULE_LICENSE("GPL");
MODULE_VERSION(DRIVER_VERSION);
-#ifdef SCSI_SCAN_DELAY
-static unsigned int delay_use = 5;
-module_param(delay_use, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
-#endif
-
static int auto_delink_en;
module_param(auto_delink_en, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(auto_delink_en, "enable auto delink");
@@ -114,7 +108,7 @@ static inline void usb_autopm_disable(struct usb_interface *intf)
usb_autopm_get_interface(intf);
}
-void rts51x_try_to_enter_ss(struct rts51x_chip *chip)
+static void rts51x_try_to_enter_ss(struct rts51x_chip *chip)
{
RTS51X_DEBUGP("Ready to enter SS state\n");
usb_autopm_enable(chip->usb->pusb_intf);
@@ -207,7 +201,7 @@ int rts51x_reset_resume(struct usb_interface *iface)
#else /* CONFIG_PM */
-void rts51x_try_to_enter_ss(struct rts51x_chip *chip)
+static void rts51x_try_to_enter_ss(struct rts51x_chip *chip)
{
}
@@ -364,11 +358,6 @@ static int rts51x_polling_thread(void *__chip)
{
struct rts51x_chip *chip = (struct rts51x_chip *)__chip;
-#ifdef SCSI_SCAN_DELAY
- /* Wait until SCSI scan finished */
- wait_timeout((delay_use + 5) * HZ);
-#endif
-
for (;;) {
wait_timeout(POLLING_INTERVAL);
@@ -432,38 +421,6 @@ static int rts51x_polling_thread(void *__chip)
return 0;
}
-#ifdef SCSI_SCAN_DELAY
-/* Thread to carry out delayed SCSI-device scanning */
-static int rts51x_scan_thread(void *__chip)
-{
- struct rts51x_chip *chip = (struct rts51x_chip *)__chip;
-
- printk(KERN_DEBUG
- "rts51x: device found at %d\n", chip->usb->pusb_dev->devnum);
-
- set_freezable();
- /* Wait for the timeout to expire or for a disconnect */
- if (delay_use > 0) {
- printk(KERN_DEBUG "rts51x: waiting for device "
- "to settle before scanning\n");
- wait_event_freezable_timeout(chip->usb->delay_wait,
- test_bit(FLIDX_DONT_SCAN,
- &chip->usb->dflags),
- delay_use * HZ);
- }
-
- /* If the device is still connected, perform the scanning */
- if (!test_bit(FLIDX_DONT_SCAN, &chip->usb->dflags)) {
- scsi_scan_host(rts51x_to_host(chip));
- printk(KERN_DEBUG "rts51x: device scan complete\n");
-
- /* Should we unbind if no devices were detected? */
- }
-
- complete_and_exit(&chip->usb->scanning_done, 0);
-}
-#endif
-
/* Associate our private data with the USB device */
static int associate_dev(struct rts51x_chip *chip, struct usb_interface *intf)
{
@@ -521,7 +478,6 @@ static void rts51x_init_options(struct rts51x_chip *chip)
{
struct rts51x_option *option = &(chip->option);
- option->led_blink_speed = 7;
option->mspro_formatter_enable = 1;
option->fpga_sd_sdr104_clk = CLK_100;
@@ -549,7 +505,6 @@ static void rts51x_init_options(struct rts51x_chip *chip)
option->ss_en = ss_en;
option->ss_delay = ss_delay;
- option->needs_remote_wakeup = needs_remote_wakeup;
option->auto_delink_en = auto_delink_en;
@@ -561,10 +516,7 @@ static void rts51x_init_options(struct rts51x_chip *chip)
option->rts5129_D3318_off_enable = 0;
option->sd20_pad_drive = 0;
option->reset_or_rw_fail_set_pad_drive = 1;
- option->rcc_fail_flag = 0;
- option->rcc_bug_fix_en = 1;
option->debounce_num = 2;
- option->polling_time = 100;
option->led_toggle_interval = 6;
option->xd_rwn_step = 0;
option->sd_send_status_en = 0;
@@ -737,15 +689,6 @@ static void quiesce_and_remove_host(struct rts51x_chip *chip)
if (rts51x->pusb_dev->state == USB_STATE_NOTATTACHED)
set_bit(FLIDX_DISCONNECTING, &rts51x->dflags);
-#ifdef SCSI_SCAN_DELAY
- /* Prevent SCSI-scanning (if it hasn't started yet)
- * and wait for the SCSI-scanning thread to stop.
- */
- set_bit(FLIDX_DONT_SCAN, &rts51x->dflags);
- wake_up(&rts51x->delay_wait);
- wait_for_completion(&rts51x->scanning_done);
-#endif
-
/* Removing the host will perform an orderly shutdown: caches
* synchronized, disks spun down, etc.
*/
@@ -757,9 +700,6 @@ static void quiesce_and_remove_host(struct rts51x_chip *chip)
scsi_lock(host);
set_bit(FLIDX_DISCONNECTING, &rts51x->dflags);
scsi_unlock(host);
-#ifdef SCSI_SCAN_DELAY
- wake_up(&rts51x->delay_wait);
-#endif
}
/* Second stage of disconnect processing: deallocate all resources */
@@ -818,10 +758,6 @@ static int rts51x_probe(struct usb_interface *intf,
init_completion(&rts51x->control_exit);
init_completion(&rts51x->polling_exit);
init_completion(&(rts51x->notify));
-#ifdef SCSI_SCAN_DELAY
- init_waitqueue_head(&rts51x->delay_wait);
- init_completion(&rts51x->scanning_done);
-#endif
chip->usb = rts51x;
@@ -855,22 +791,7 @@ static int rts51x_probe(struct usb_interface *intf,
printk(KERN_WARNING RTS51X_TIP "Unable to add the scsi host\n");
goto BadDevice;
}
-#ifdef SCSI_SCAN_DELAY
- /* Start up the thread for delayed SCSI-device scanning */
- th = kthread_create(rts51x_scan_thread, chip, RTS51X_SCAN_THREAD);
- if (IS_ERR(th)) {
- printk(KERN_WARNING RTS51X_TIP
- "Unable to start the device-scanning thread\n");
- complete(&rts51x->scanning_done);
- quiesce_and_remove_host(chip);
- result = PTR_ERR(th);
- goto BadDevice;
- }
-
- wake_up_process(th);
-#else
scsi_scan_host(rts51x_to_host(chip));
-#endif
/* Start up our polling thread */
th = kthread_run(rts51x_polling_thread, chip, RTS51X_POLLING_THREAD);
diff --git a/drivers/staging/rts5139/rts51x.h b/drivers/staging/rts5139/rts51x.h
index b2c58390bfc5..ecc0109a5b1a 100644
--- a/drivers/staging/rts5139/rts51x.h
+++ b/drivers/staging/rts5139/rts51x.h
@@ -47,11 +47,9 @@
#define RTS51X_DESC "Realtek RTS5139/29 USB card reader driver"
#define RTS51X_NAME "rts5139"
#define RTS51X_CTL_THREAD "rts5139-control"
-#define RTS51X_SCAN_THREAD "rts5139-scan"
#define RTS51X_POLLING_THREAD "rts5139-polling"
#define POLLING_IN_THREAD
-/* #define SCSI_SCAN_DELAY */
#define SUPPORT_FILE_OP
#define wait_timeout_x(task_state, msecs) \
@@ -66,8 +64,6 @@ do { \
/* Size of the DMA-mapped I/O buffer */
#define RTS51X_IOBUF_SIZE 1024
-/* Size of the autosense data buffer */
-#define RTS51X_SENSE_SIZE 18
/* Dynamic bitflag definitions (dflags): used in set_bit() etc. */
#define FLIDX_URB_ACTIVE 0 /* current_urb is in use */
@@ -76,7 +72,6 @@ do { \
#define FLIDX_DISCONNECTING 3 /* disconnect in progress */
#define FLIDX_RESETTING 4 /* device reset in progress */
#define FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */
-#define FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */
struct rts51x_chip;
@@ -116,10 +111,6 @@ struct rts51x_usb {
struct completion control_exit; /* control thread exit */
struct completion polling_exit; /* polling thread exit */
struct completion notify; /* thread begin/end */
-#ifdef SCSI_SCAN_DELAY
- wait_queue_head_t delay_wait; /* wait during scan, reset */
- struct completion scanning_done; /* wait for scan thread */
-#endif
};
extern struct usb_driver rts51x_driver;
@@ -188,7 +179,6 @@ enum xfer_buf_dir { TO_XFER_BUF, FROM_XFER_BUF };
/* General routines provided by the usb-storage standard core */
#ifdef CONFIG_PM
-void rts51x_try_to_enter_ss(struct rts51x_chip *chip);
void rts51x_try_to_exit_ss(struct rts51x_chip *chip);
int rts51x_suspend(struct usb_interface *iface, pm_message_t message);
int rts51x_resume(struct usb_interface *iface);
diff --git a/drivers/staging/rts5139/rts51x_card.c b/drivers/staging/rts5139/rts51x_card.c
index 424a84581b86..4192c3bac12f 100644
--- a/drivers/staging/rts5139/rts51x_card.c
+++ b/drivers/staging/rts5139/rts51x_card.c
@@ -37,7 +37,6 @@
#include "rts51x_chip.h"
#include "rts51x_card.h"
#include "rts51x_transport.h"
-#include "rts51x_sys.h"
#include "xd.h"
#include "sd.h"
#include "ms.h"
@@ -94,7 +93,7 @@ void do_remaining_work(struct rts51x_chip *chip)
ms_cleanup_work(chip);
}
-void do_reset_xd_card(struct rts51x_chip *chip)
+static void do_reset_xd_card(struct rts51x_chip *chip)
{
int retval;
@@ -148,7 +147,7 @@ void do_reset_sd_card(struct rts51x_chip *chip)
}
}
-void do_reset_ms_card(struct rts51x_chip *chip)
+static void do_reset_ms_card(struct rts51x_chip *chip)
{
int retval;
@@ -175,7 +174,7 @@ void do_reset_ms_card(struct rts51x_chip *chip)
}
}
-void card_cd_debounce(struct rts51x_chip *chip, u8 *need_reset,
+static void card_cd_debounce(struct rts51x_chip *chip, u8 *need_reset,
u8 *need_release)
{
int retval;
@@ -191,7 +190,6 @@ void card_cd_debounce(struct rts51x_chip *chip, u8 *need_reset,
goto Exit_Debounce;
if (chip->card_exist) {
- rts51x_clear_start_time(chip);
retval = rts51x_read_register(chip, CARD_INT_PEND, &value);
if (retval != STATUS_SUCCESS) {
rts51x_ep0_write_register(chip, MC_FIFO_CTL, FIFO_FLUSH,
@@ -214,17 +212,11 @@ void card_cd_debounce(struct rts51x_chip *chip, u8 *need_reset,
}
} else {
if (chip->card_status & XD_CD) {
- rts51x_clear_start_time(chip);
reset_map |= XD_CARD;
} else if (chip->card_status & SD_CD) {
- rts51x_clear_start_time(chip);
reset_map |= SD_CARD;
} else if (chip->card_status & MS_CD) {
- rts51x_clear_start_time(chip);
reset_map |= MS_CARD;
- } else {
- if (rts51x_check_start_time(chip))
- rts51x_set_start_time(chip);
}
}
@@ -709,7 +701,7 @@ u8 get_lun_card(struct rts51x_chip *chip, unsigned int lun)
return 0;
}
-int card_share_mode(struct rts51x_chip *chip, int card)
+static int card_share_mode(struct rts51x_chip *chip, int card)
{
u8 value;
@@ -823,22 +815,6 @@ int enable_card_clock(struct rts51x_chip *chip, u8 card)
return STATUS_SUCCESS;
}
-int disable_card_clock(struct rts51x_chip *chip, u8 card)
-{
- u8 clk_en = 0;
-
- if (card & XD_CARD)
- clk_en |= XD_CLK_EN;
- if (card & SD_CARD)
- clk_en |= SD_CLK_EN;
- if (card & MS_CARD)
- clk_en |= MS_CLK_EN;
-
- RTS51X_WRITE_REG(chip, CARD_CLK_EN, clk_en, 0);
-
- return STATUS_SUCCESS;
-}
-
int card_power_on(struct rts51x_chip *chip, u8 card)
{
u8 mask, val1, val2;
@@ -851,16 +827,7 @@ int card_power_on(struct rts51x_chip *chip, u8 card)
if ((card == SD_CARD) || (card == XD_CARD)) {
RTS51X_WRITE_REG(chip, CARD_PWR_CTL, mask | LDO3318_PWR_MASK,
val1 | LDO_SUSPEND);
- /* RTS51X_WRITE_REG(chip, CARD_PWR_CTL,
- LDO3318_PWR_MASK, LDO_SUSPEND); */
}
- /* else if(card==XD_CARD)
- {
- RTS51X_WRITE_REG(chip, CARD_PWR_CTL,
- mask|LDO3318_PWR_MASK, val1|LDO_SUSPEND);
- //RTS51X_WRITE_REG(chip, CARD_PWR_CTL,
- // LDO3318_PWR_MASK, LDO_SUSPEND);
- } */
else {
#endif
RTS51X_WRITE_REG(chip, CARD_PWR_CTL, mask, val1);
@@ -879,17 +846,6 @@ int card_power_on(struct rts51x_chip *chip, u8 card)
return STATUS_SUCCESS;
}
-int card_power_off(struct rts51x_chip *chip, u8 card)
-{
- u8 mask, val;
-
- mask = POWER_MASK;
- val = POWER_OFF;
- RTS51X_WRITE_REG(chip, CARD_PWR_CTL, mask, val);
-
- return STATUS_SUCCESS;
-}
-
int monitor_card_cd(struct rts51x_chip *chip, u8 card)
{
int retval;
diff --git a/drivers/staging/rts5139/rts51x_card.h b/drivers/staging/rts5139/rts51x_card.h
index ac3c1e741ab9..c5c03cce98bd 100644
--- a/drivers/staging/rts5139/rts51x_card.h
+++ b/drivers/staging/rts5139/rts51x_card.h
@@ -204,13 +204,7 @@
/* LDO_POWER_CFG */
#define TUNE_SD18_MASK 0x1C
-#define TUNE_SD18_1V7 0x00
#define TUNE_SD18_1V8 (0x01 << 2)
-#define TUNE_SD18_1V9 (0x02 << 2)
-#define TUNE_SD18_2V0 (0x03 << 2)
-#define TUNE_SD18_2V7 (0x04 << 2)
-#define TUNE_SD18_2V8 (0x05 << 2)
-#define TUNE_SD18_2V9 (0x06 << 2)
#define TUNE_SD18_3V3 (0x07 << 2)
/* XD_CP_WAITTIME */
@@ -744,9 +738,7 @@
int monitor_card_cd(struct rts51x_chip *chip, u8 card);
void do_remaining_work(struct rts51x_chip *chip);
-void do_reset_xd_card(struct rts51x_chip *chip);
void do_reset_sd_card(struct rts51x_chip *chip);
-void do_reset_ms_card(struct rts51x_chip *chip);
void rts51x_init_cards(struct rts51x_chip *chip);
void rts51x_release_cards(struct rts51x_chip *chip);
int switch_ssc_clock(struct rts51x_chip *chip, int clk);
@@ -754,15 +746,12 @@ int switch_normal_clock(struct rts51x_chip *chip, int clk);
int card_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 sec_addr,
u16 sec_cnt);
u8 get_lun_card(struct rts51x_chip *chip, unsigned int lun);
-int card_share_mode(struct rts51x_chip *chip, int card);
int rts51x_select_card(struct rts51x_chip *chip, int card);
void eject_card(struct rts51x_chip *chip, unsigned int lun);
void trans_dma_enable(enum dma_data_direction dir, struct rts51x_chip *chip,
u32 byte_cnt, u8 pack_size);
int enable_card_clock(struct rts51x_chip *chip, u8 card);
-int disable_card_clock(struct rts51x_chip *chip, u8 card);
int card_power_on(struct rts51x_chip *chip, u8 card);
-int card_power_off(struct rts51x_chip *chip, u8 card);
int toggle_gpio(struct rts51x_chip *chip, u8 gpio);
int turn_on_led(struct rts51x_chip *chip, u8 gpio);
int turn_off_led(struct rts51x_chip *chip, u8 gpio);
diff --git a/drivers/staging/rts5139/rts51x_chip.c b/drivers/staging/rts5139/rts51x_chip.c
index b3e0bb22b0ff..db88d7a194b8 100644
--- a/drivers/staging/rts5139/rts51x_chip.c
+++ b/drivers/staging/rts5139/rts51x_chip.c
@@ -34,7 +34,6 @@
#include "rts51x_chip.h"
#include "rts51x_card.h"
#include "rts51x_transport.h"
-#include "rts51x_sys.h"
#include "xd.h"
#include "ms.h"
#include "sd.h"
@@ -79,20 +78,18 @@ int rts51x_reset_chip(struct rts51x_chip *chip)
chip->option.sd20_pad_drive);
if (chip->rts5179)
rts51x_write_register(chip, CARD_PULL_CTL5, 0x03, 0x01);
- if (!chip->option.ww_enable) {
- if (CHECK_PKG(chip, LQFP48)) {
- rts51x_write_register(chip, CARD_PULL_CTL3,
- 0x80, 0x80);
- rts51x_write_register(chip, CARD_PULL_CTL6,
- 0xf0, 0xA0);
- } else {
- rts51x_write_register(chip, CARD_PULL_CTL1,
- 0x30, 0x20);
- rts51x_write_register(chip, CARD_PULL_CTL3,
- 0x80, 0x80);
- rts51x_write_register(chip, CARD_PULL_CTL6,
- 0x0c, 0x08);
- }
+ if (CHECK_PKG(chip, LQFP48)) {
+ rts51x_write_register(chip, CARD_PULL_CTL3,
+ 0x80, 0x80);
+ rts51x_write_register(chip, CARD_PULL_CTL6,
+ 0xf0, 0xA0);
+ } else {
+ rts51x_write_register(chip, CARD_PULL_CTL1,
+ 0x30, 0x20);
+ rts51x_write_register(chip, CARD_PULL_CTL3,
+ 0x80, 0x80);
+ rts51x_write_register(chip, CARD_PULL_CTL6,
+ 0x0c, 0x08);
}
}
if (chip->option.sd_ctl & SUPPORT_UHS50_MMC44) {
@@ -121,12 +118,6 @@ int rts51x_reset_chip(struct rts51x_chip *chip)
/* GPIO OE */
rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO, GPIO_OE, GPIO_OE);
-#ifdef LED_AUTO_BLINK
- /* LED autoblink */
- rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_AUTO_BLINK,
- BLINK_ENABLE | BLINK_SPEED_MASK,
- BLINK_ENABLE | chip->option.led_blink_speed);
-#endif
rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DMA1_CTL,
EXTEND_DMA1_ASYNC_SIGNAL, EXTEND_DMA1_ASYNC_SIGNAL);
@@ -144,7 +135,6 @@ int rts51x_reset_chip(struct rts51x_chip *chip)
card_power_on(chip, SD_CARD | MS_CARD | XD_CARD);
wait_timeout(10);
}
- rts51x_clear_start_time(chip);
return STATUS_SUCCESS;
}
@@ -164,12 +154,6 @@ int rts51x_init_chip(struct rts51x_chip *chip)
chip->card_ejected = 0;
chip->lun2card[0] = XD_CARD | SD_CARD | MS_CARD;
-#if 0
- chip->option.sdr50_tx_phase = 0x01;
- chip->option.sdr50_rx_phase = 0x05;
- chip->option.ddr50_tx_phase = 0x09;
- chip->option.ddr50_rx_phase = 0x06; /* add for debug */
-#endif
#ifdef CLOSE_SSC_POWER
rts51x_write_register(chip, FPDCTL, SSC_POWER_MASK, SSC_POWER_ON);
udelay(100);
@@ -178,9 +162,6 @@ int rts51x_init_chip(struct rts51x_chip *chip)
RTS51X_SET_STAT(chip, STAT_RUN);
RTS51X_READ_REG(chip, HW_VERSION, &val);
- if ((val & 0x0f) >= 2)
- chip->option.rcc_bug_fix_en = 0;
- RTS51X_DEBUGP("rcc bug fix enable:%d\n", chip->option.rcc_bug_fix_en);
RTS51X_DEBUGP("HW_VERSION: 0x%x\n", val);
if (val & FPGA_VER) {
chip->asic_code = 0;
@@ -237,7 +218,6 @@ int rts51x_release_chip(struct rts51x_chip *chip)
return STATUS_SUCCESS;
}
-#ifndef LED_AUTO_BLINK
static inline void rts51x_blink_led(struct rts51x_chip *chip)
{
/* Read/Write */
@@ -251,20 +231,6 @@ static inline void rts51x_blink_led(struct rts51x_chip *chip)
}
}
}
-#endif
-
-int rts51x_check_start_time(struct rts51x_chip *chip)
-{
- return 0;
-}
-
-void rts51x_set_start_time(struct rts51x_chip *chip)
-{
-}
-
-void rts51x_clear_start_time(struct rts51x_chip *chip)
-{
-}
static void rts51x_auto_delink_cmd(struct rts51x_chip *chip)
{
@@ -287,7 +253,6 @@ static void rts51x_auto_delink_polling_cycle(struct rts51x_chip *chip)
chip->option.delink_delay * 2) {
if (chip->auto_delink_counter ==
chip->option.delink_delay) {
- clear_first_install_mark(chip);
if (chip->card_exist) {
/* False card */
if (!chip->card_ejected) {
@@ -321,91 +286,13 @@ static void rts51x_auto_delink(struct rts51x_chip *chip)
}
#else
/* some of called funcs are not implemented, so comment it out */
-#if 0
-/* using precise time as delink time */
-static void rts51x_auto_delink_precise_time(struct rts51x_chip *chip)
-{
- int retvalue = 0;
-
- retvalue = rts51x_get_card_status(chip, &chip->card_status);
- /* get card CD status success and card CD not exist,
- * then check whether delink */
- if ((retvalue == STATUS_SUCCESS)
- && (!(chip->card_status & (SD_CD | MS_CD | XD_CD)))) {
- if (rts51x_count_delink_time(chip) >=
- chip->option.delink_delay) {
- clear_first_install_mark(chip);
- RTS51X_DEBUGP("No card inserted, do delink\n");
- /* sangdy2010-05-17:disable because there is error
- * after SSC clock closed and card power
- * has been closed before */
- /* rts51x_write_register(chip, CARD_PWR_CTL,
- DV3318_AUTO_PWR_OFF, 0); */
- rts51x_auto_delink_cmd(chip);
- }
- /* card CD exist and not ready, then do force delink */
- if ((retvalue == STATUS_SUCCESS)
- && (chip->card_status & (SD_CD | MS_CD | XD_CD))) {
- /* if card is not ejected or safely remove,
- * then do force delink */
- if (!chip->card_ejected) {
- /* sangdy2010-11-16:polling at least 2 cycles
- * then do force delink for card may force delink
- * if card is extracted and insert quickly
- * after ready. */
- if (chip->auto_delink_counter > 1) {
- if (rts51x_count_delink_time(chip) >
- chip->option.delink_delay * 2) {
- RTS51X_DEBUGP("Try to do force"
- "delink\n");
- rts51x_auto_delink_force_cmd(chip);
- }
- }
- }
- }
- chip->auto_delink_counter++;
-}
-#else
-static void rts51x_auto_delink_precise_time(struct rts51x_chip *chip)
-{
-}
-#endif
-
static void rts51x_auto_delink(struct rts51x_chip *chip)
{
- rts51x_auto_delink_precise_time(chip);
}
#endif
void rts51x_polling_func(struct rts51x_chip *chip)
{
-#ifdef SUPPORT_SD_LOCK
- struct sd_info *sd_card = &(chip->sd_card);
-
- if (sd_card->sd_erase_status) {
- if (chip->card_exist & SD_CARD) {
- u8 val;
- rts51x_read_register(chip, SD_BUS_STAT, &val);
- if (val & SD_DAT0_STATUS) {
- /* Erase completed */
- sd_card->sd_erase_status = SD_NOT_ERASE;
- sd_card->sd_lock_notify = 1;
-
- /* SD card should be reinited,
- * so we release it here. */
- sd_cleanup_work(chip);
- release_sd_card(chip);
- chip->card_ready &= ~SD_CARD;
- chip->card_exist &= ~SD_CARD;
- chip->rw_card[chip->card2lun[SD_CARD]] = NULL;
- clear_bit(chip->card2lun[SD_CARD],
- &(chip->lun_mc));
- }
- } else {
- sd_card->sd_erase_status = SD_NOT_ERASE;
- }
- }
-#endif
rts51x_init_cards(chip);
@@ -431,9 +318,7 @@ void rts51x_polling_func(struct rts51x_chip *chip)
if (!RTS51X_CHK_STAT(chip, STAT_IDLE)) {
RTS51X_DEBUGP("Idle state!\n");
RTS51X_SET_STAT(chip, STAT_IDLE);
-#ifndef LED_AUTO_BLINK
chip->led_toggle_counter = 0;
-#endif
/* Idle state, turn off LED
* to reduce power consumption */
if (chip->option.led_always_on
@@ -467,9 +352,7 @@ void rts51x_polling_func(struct rts51x_chip *chip)
switch (RTS51X_GET_STAT(chip)) {
case STAT_RUN:
-#ifndef LED_AUTO_BLINK
rts51x_blink_led(chip);
-#endif
do_remaining_work(chip);
break;
@@ -484,7 +367,6 @@ void rts51x_polling_func(struct rts51x_chip *chip)
rts51x_auto_delink(chip);
} else {
chip->auto_delink_counter = 0;
- rts51x_clear_start_time(chip);
}
}
@@ -831,7 +713,7 @@ void rts51x_do_before_power_down(struct rts51x_chip *chip)
chip->cur_clk = 0;
chip->card_exist = 0;
chip->cur_card = 0;
- if (chip->asic_code && !chip->option.ww_enable) {
+ if (chip->asic_code) {
if (CHECK_PKG(chip, LQFP48)) {
rts51x_write_register(chip, CARD_PULL_CTL3, 0x80, 0x00);
rts51x_write_register(chip, CARD_PULL_CTL6, 0xf0, 0x50);
@@ -863,16 +745,6 @@ void rts51x_prepare_run(struct rts51x_chip *chip)
rts51x_write_register(chip, CLK_DIV, CLK_CHANGE, 0x00);
}
#endif
-#if 0
- if (chip->option.ss_en && RTS51X_CHK_STAT(chip, STAT_SS)) {
- rts51x_try_to_exit_ss(chip);
- wait_timeout(100);
- rts51x_init_chip(chip);
- rts51x_init_cards(chip);
- }
-
- RTS51X_SET_STAT(chip, STAT_RUN);
-#endif
}
#ifdef _MSG_TRACE
@@ -1017,24 +889,6 @@ void rts51x_pp_status(struct rts51x_chip *chip, unsigned int lun, u8 *status,
status[0x0F] = 0x00;
}
}
-#ifdef SUPPORT_SD_LOCK
- /* SD Lock/Unlock */
- if (card == SD_CARD) {
- status[0x17] = 0x80;
- if (sd_card->sd_erase_status)
- status[0x17] |= 0x01; /* Under erasing */
- if (sd_card->sd_lock_status & SD_LOCKED) {
- status[0x17] |= 0x02; /* Locked */
- status[0x07] |= 0x40; /* Read protected */
- }
- if (sd_card->sd_lock_status & SD_PWD_EXIST)
- status[0x17] |= 0x04; /* Contain PWD */
- } else {
- status[0x17] = 0x00;
- }
-
- RTS51X_DEBUGP("status[0x17] = 0x%x\n", status[0x17]);
-#endif
/* Function 0
* Support Magic Gate, CPRM and PhyRegister R/W */
@@ -1044,12 +898,6 @@ void rts51x_pp_status(struct rts51x_chip *chip, unsigned int lun, u8 *status,
* Support OC LUN status & WP LUN status */
status[0x1A] = 0x28;
- /* Function 7 */
-#ifdef SUPPORT_SD_LOCK
- /* Support SD Lock/Unlock */
- status[0x1F] = 0x01;
-#endif
-
/* Function 2
* Support OC LUN status & WP LUN status */
status[0x1A] = 0x28;
diff --git a/drivers/staging/rts5139/rts51x_chip.h b/drivers/staging/rts5139/rts51x_chip.h
index 13fc2a410d90..6d395b6533a8 100644
--- a/drivers/staging/rts5139/rts51x_chip.h
+++ b/drivers/staging/rts5139/rts51x_chip.h
@@ -39,12 +39,7 @@
#define SUPPORT_CPRM
#define SUPPORT_MAGIC_GATE
#define SUPPORT_MSXC
-/* #define LED_AUTO_BLINK */
-
-/* { wwang, 2010-07-26
- * Add support for SD lock/unlock */
-/* #define SUPPORT_SD_LOCK */
-/* } wwang, 2010-07-26 */
+#define USING_POLLING_CYCLE_DELINK
#ifdef SUPPORT_MAGIC_GA
/* Using NORMAL_WRITE instead of AUTO_WRITE to set ICVTE */
@@ -63,7 +58,6 @@
#define SUPPORT_OCP
#define MS_SPEEDUP
-/* #define XD_SPEEDUP */
#define SD_XD_IO_FOLLOW_PWR
@@ -81,7 +75,6 @@
#define MAX_ALLOWED_LUN_CNT 8
#define CMD_BUF_LEN 1024
-#define RSP_BUF_LEN 1024
#define POLLING_INTERVAL 50 /* 50ms */
#define XD_FREE_TABLE_CNT 1200
@@ -128,8 +121,6 @@
#endif
#define STATUS_FAIL 1
-#define STATUS_READ_FAIL 2
-#define STATUS_WRITE_FAIL 3
#define STATUS_TIMEDOUT 4
#define STATUS_NOMEM 5
#define STATUS_TRANS_SHORT 6
@@ -139,8 +130,6 @@
#define IDLE_MAX_COUNT 10
#define POLLING_WAIT_CNT 1
-#define DELINK_DELAY 100
-#define LED_TOGGLE_INTERVAL 6
#define LED_GPIO 0
/* package */
@@ -157,8 +146,6 @@
#define TRANSPORT_GOOD 0
/* Transport good, command failed */
#define TRANSPORT_FAILED 1
-/* Command failed, no auto-sense */
-#define TRANSPORT_NO_SENSE 2
/* Transport bad (i.e. device dead) */
#define TRANSPORT_ERROR 3
@@ -195,7 +182,6 @@ struct trace_msg_t {
#define SENSE_TYPE_MEDIA_INVALID_CMD_FIELD 6
#define SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR 7
#define SENSE_TYPE_MEDIA_WRITE_ERR 8
-#define SENSE_TYPE_FORMAT_IN_PROGRESS 9
#define SENSE_TYPE_FORMAT_CMD_FAILED 10
#ifdef SUPPORT_MAGIC_GATE
/* COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT ESTABLISHED */
@@ -207,83 +193,27 @@ struct trace_msg_t {
/* WRITE ERROR */
#define SENSE_TYPE_MG_WRITE_ERR 0x0e
#endif
-#ifdef SUPPORT_SD_LOCK
-/* FOR Locked SD card */
-#define SENSE_TYPE_MEDIA_READ_FORBIDDEN 0x10
-#endif
/*---- sense key ----*/
-#define ILI 0x20 /* ILI bit is on */
-
-#define NO_SENSE 0x00 /* not exist sense key */
-#define RECOVER_ERR 0x01 /* Target/Logical unit is recoverd */
-#define NOT_READY 0x02 /* Logical unit is not ready */
-#define MEDIA_ERR 0x03 /* medium/data error */
-#define HARDWARE_ERR 0x04 /* hardware error */
#define ILGAL_REQ 0x05 /* CDB/parameter/identify msg error */
-#define UNIT_ATTENTION 0x06 /* unit attention condition occur */
-#define DAT_PRTCT 0x07 /* read/write is desable */
-#define BLNC_CHK 0x08 /* find blank/DOF in read */
- /* write to unblank area */
-#define CPY_ABRT 0x0a /* Copy/Compare/Copy&Verify illgal */
-#define ABRT_CMD 0x0b /* Target make the command in error */
-#define EQUAL 0x0c /* Search Data end with Equal */
-#define VLM_OVRFLW 0x0d /* Some data are left in buffer */
-#define MISCMP 0x0e /* find inequality */
/*-----------------------------------
SENSE_DATA
-----------------------------------*/
-/*---- valid ----*/
-#define SENSE_VALID 0x80 /* Sense data is valid as SCSI2 */
-#define SENSE_INVALID 0x00 /* Sense data is invalid as SCSI2 */
/*---- error code ----*/
#define CUR_ERR 0x70 /* current error */
-#define DEF_ERR 0x71 /* specific command error */
/*---- sense key Infomation ----*/
-#define SNSKEYINFO_LEN 3 /* length of sense key infomation */
#define SKSV 0x80
#define CDB_ILLEGAL 0x40
-#define DAT_ILLEGAL 0x00
-#define BPV 0x08
-#define BIT_ILLEGAL0 0 /* bit0 is illegal */
-#define BIT_ILLEGAL1 1 /* bit1 is illegal */
-#define BIT_ILLEGAL2 2 /* bit2 is illegal */
-#define BIT_ILLEGAL3 3 /* bit3 is illegal */
-#define BIT_ILLEGAL4 4 /* bit4 is illegal */
-#define BIT_ILLEGAL5 5 /* bit5 is illegal */
-#define BIT_ILLEGAL6 6 /* bit6 is illegal */
-#define BIT_ILLEGAL7 7 /* bit7 is illegal */
/*---- ASC ----*/
-#define ASC_NO_INFO 0x00
-#define ASC_MISCMP 0x1d
#define ASC_INVLD_CDB 0x24
-#define ASC_INVLD_PARA 0x26
-#define ASC_LU_NOT_READY 0x04
-#define ASC_WRITE_ERR 0x0c
-#define ASC_READ_ERR 0x11
-#define ASC_LOAD_EJCT_ERR 0x53
-#define ASC_MEDIA_NOT_PRESENT 0x3A
-#define ASC_MEDIA_CHANGED 0x28
-#define ASC_MEDIA_IN_PROCESS 0x04
-#define ASC_WRITE_PROTECT 0x27
-#define ASC_LUN_NOT_SUPPORTED 0x25
/*---- ASQC ----*/
-#define ASCQ_NO_INFO 0x00
-#define ASCQ_MEDIA_IN_PROCESS 0x01
-#define ASCQ_MISCMP 0x00
#define ASCQ_INVLD_CDB 0x00
-#define ASCQ_INVLD_PARA 0x02
-#define ASCQ_LU_NOT_READY 0x02
-#define ASCQ_WRITE_ERR 0x02
-#define ASCQ_READ_ERR 0x00
-#define ASCQ_LOAD_EJCT_ERR 0x00
-#define ASCQ_WRITE_PROTECT 0x00
struct sense_data_t {
unsigned char err_code; /* error code */
@@ -296,13 +226,13 @@ struct sense_data_t {
unsigned char seg_no; /* segment No. */
unsigned char sense_key; /* byte5 : ILI */
/* bit3-0 : sense key */
- unsigned char info[4]; /* infomation */
+ unsigned char info[4]; /* information */
unsigned char ad_sense_len; /* additional sense data length */
- unsigned char cmd_info[4]; /* command specific infomation */
+ unsigned char cmd_info[4]; /* command specific information */
unsigned char asc; /* ASC */
unsigned char ascq; /* ASCQ */
unsigned char rfu; /* FRU */
- unsigned char sns_key_info[3]; /* sense key specific infomation */
+ unsigned char sns_key_info[3]; /* sense key specific information */
};
/* sd_ctl bit map */
@@ -323,8 +253,6 @@ struct sense_data_t {
#define SUPPORT_UHS50_MMC44 0x40
struct rts51x_option {
- u8 led_blink_speed;
-
int mspro_formatter_enable;
/* card clock expected by user for fpga platform */
@@ -368,8 +296,6 @@ struct rts51x_option {
int ss_en;
/* Interval to enter SS from IDLE state (second) */
int ss_delay;
- int needs_remote_wakeup;
- u8 ww_enable; /* sangdy2010-08-03:add for remote wakeup */
/* Enable SSC clock */
int ssc_en;
@@ -392,10 +318,7 @@ struct rts51x_option {
/*if reset or rw fail,then set SD20 pad drive again */
u8 reset_or_rw_fail_set_pad_drive;
- u8 rcc_fail_flag; /* add to indicate whether rcc bug happen */
- u8 rcc_bug_fix_en; /* if set,then support fixing rcc bug */
u8 debounce_num; /* debounce number */
- int polling_time; /* polling delay time */
u8 led_toggle_interval; /* used to control led toggle speed */
int xd_rwn_step;
u8 sd_send_status_en;
@@ -405,7 +328,7 @@ struct rts51x_option {
u8 ddr50_rx_phase;
u8 sdr50_tx_phase;
u8 sdr50_rx_phase;
- /* used to enable select sdr50 tx phase according to proportion. */
+ /* used to enable select sdr50 tx phase according to proportion. */
u8 sdr50_phase_sel;
u8 ms_errreg_fix;
u8 reset_mmc_first;
@@ -614,11 +537,6 @@ struct sd_info {
u8 sd_reset_fail; /* sangdy2010-07-01 */
u8 sd_send_status_en;
-#ifdef SUPPORT_SD_LOCK
- u8 sd_lock_status;
- u8 sd_erase_status;
- u8 sd_lock_notify;
-#endif
};
#define MODE_512_SEQ 0x01
@@ -720,9 +638,8 @@ struct rts51x_chip {
struct scsi_cmnd *srb;
struct sense_data_t sense_buffer[MAX_ALLOWED_LUN_CNT];
-#ifndef LED_AUTO_BLINK
int led_toggle_counter;
-#endif
+
int ss_counter;
int idle_counter;
int auto_delink_counter;
diff --git a/drivers/staging/rts5139/rts51x_fop.c b/drivers/staging/rts5139/rts51x_fop.c
index 6eaebb6223c9..ef893c8cdec6 100644
--- a/drivers/staging/rts5139/rts51x_fop.c
+++ b/drivers/staging/rts5139/rts51x_fop.c
@@ -234,12 +234,7 @@ ssize_t rts51x_write(struct file *filp, const char __user *buf, size_t count,
return 0;
}
-#if 0 /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) */
-int rts51x_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-#else
long rts51x_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-#endif
{
struct rts51x_chip *chip;
struct sd_direct_cmnd cmnd;
diff --git a/drivers/staging/rts5139/rts51x_fop.h b/drivers/staging/rts5139/rts51x_fop.h
index 94d75f08d255..eb45acf50d1a 100644
--- a/drivers/staging/rts5139/rts51x_fop.h
+++ b/drivers/staging/rts5139/rts51x_fop.h
@@ -50,12 +50,7 @@ ssize_t rts51x_read(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos);
ssize_t rts51x_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos);
-#if 0 /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) */
-int rts51x_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg);
-#else
long rts51x_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-#endif
#endif
diff --git a/drivers/staging/rts5139/rts51x_scsi.c b/drivers/staging/rts5139/rts51x_scsi.c
index 87c9cdc8bd29..e07a1f4f58cf 100644
--- a/drivers/staging/rts5139/rts51x_scsi.c
+++ b/drivers/staging/rts5139/rts51x_scsi.c
@@ -40,7 +40,6 @@
#include "rts51x_scsi.h"
#include "rts51x_card.h"
#include "rts51x_transport.h"
-#include "rts51x_sys.h"
#include "sd_cprm.h"
#include "ms_mg.h"
#include "trace.h"
@@ -370,10 +369,6 @@ void set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type)
ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1);
break;
- case SENSE_TYPE_FORMAT_IN_PROGRESS:
- set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, 0, 0);
- break;
-
case SENSE_TYPE_FORMAT_CMD_FAILED:
set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0);
break;
@@ -396,12 +391,6 @@ void set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type)
break;
#endif
-#ifdef SUPPORT_SD_LOCK
- case SENSE_TYPE_MEDIA_READ_FORBIDDEN:
- set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x11, 0x13, 0, 0);
- break;
-#endif
-
case SENSE_TYPE_NO_SENSE:
default:
set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0);
@@ -448,20 +437,6 @@ static int test_unit_ready(struct scsi_cmnd *srb, struct rts51x_chip *chip)
set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
return TRANSPORT_FAILED;
}
-#ifdef SUPPORT_SD_LOCK
- if (get_lun_card(chip, SCSI_LUN(srb)) == SD_CARD) {
- struct sd_info *sd_card = &(chip->sd_card);
- if (sd_card->sd_lock_notify) {
- sd_card->sd_lock_notify = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- } else if (sd_card->sd_lock_status & SD_LOCKED) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_READ_FORBIDDEN);
- return TRANSPORT_FAILED;
- }
- }
-#endif
return TRANSPORT_GOOD;
}
@@ -797,9 +772,6 @@ static int request_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip)
static int read_write(struct scsi_cmnd *srb, struct rts51x_chip *chip)
{
-#ifdef SUPPORT_SD_LOCK
- struct sd_info *sd_card = &(chip->sd_card);
-#endif
unsigned int lun = SCSI_LUN(srb);
int retval;
u32 start_sec;
@@ -819,25 +791,6 @@ static int read_write(struct scsi_cmnd *srb, struct rts51x_chip *chip)
rts51x_prepare_run(chip);
RTS51X_SET_STAT(chip, STAT_RUN);
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_erase_status) {
- /* Accessing to any card is forbidden
- * until the erase procedure of SD is completed */
- RTS51X_DEBUGP("SD card being erased!\n");
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
- TRACE_RET(chip, TRANSPORT_FAILED);
- }
-
- if (get_lun_card(chip, lun) == SD_CARD) {
- if (sd_card->sd_lock_status & SD_LOCKED) {
- RTS51X_DEBUGP("SD card locked!\n");
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_READ_FORBIDDEN);
- TRACE_RET(chip, TRANSPORT_FAILED);
- }
- }
-#endif
-
if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) {
start_sec =
((u32) srb->cmnd[2] << 24) |
@@ -883,20 +836,12 @@ static int read_write(struct scsi_cmnd *srb, struct rts51x_chip *chip)
retval = card_rw(srb, chip, start_sec, sec_cnt);
if (retval != STATUS_SUCCESS) {
-#if 0
- if (chip->need_release & chip->lun2card[lun]) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- } else {
-#endif
if (srb->sc_data_direction == DMA_FROM_DEVICE) {
set_sense_type(chip, lun,
SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
} else {
set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
}
-#if 0
- }
-#endif
TRACE_RET(chip, TRANSPORT_FAILED);
}
@@ -1516,7 +1461,7 @@ static int ms_format_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
}
#ifdef SUPPORT_PCGL_1P18
-int get_ms_information(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+static int get_ms_information(struct scsi_cmnd *srb, struct rts51x_chip *chip)
{
struct ms_info *ms_card = &(chip->ms_card);
unsigned int lun = SCSI_LUN(srb);
@@ -1677,7 +1622,7 @@ static int sd_extention_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
#endif
#ifdef SUPPORT_MAGIC_GATE
-int mg_report_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+static int mg_report_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
{
struct ms_info *ms_card = &(chip->ms_card);
unsigned int lun = SCSI_LUN(srb);
@@ -1764,7 +1709,7 @@ int mg_report_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
return TRANSPORT_GOOD;
}
-int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+static int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
{
struct ms_info *ms_card = &(chip->ms_card);
unsigned int lun = SCSI_LUN(srb);
@@ -1871,30 +1816,10 @@ int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
int rts51x_scsi_handler(struct scsi_cmnd *srb, struct rts51x_chip *chip)
{
-#ifdef SUPPORT_SD_LOCK
- struct sd_info *sd_card = &(chip->sd_card);
-#endif
struct ms_info *ms_card = &(chip->ms_card);
unsigned int lun = SCSI_LUN(srb);
int result = TRANSPORT_GOOD;
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_erase_status) {
- /* Block all SCSI command except for REQUEST_SENSE
- * and rs_ppstatus */
- if (!
- ((srb->cmnd[0] == VENDOR_CMND)
- && (srb->cmnd[1] == SCSI_APP_CMD)
- && (srb->cmnd[2] == GET_DEV_STATUS))
- && (srb->cmnd[0] != REQUEST_SENSE)) {
- /* Logical Unit Not Ready Format in Progress */
- set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
- 0, 0);
- TRACE_RET(chip, TRANSPORT_FAILED);
- }
- }
-#endif
-
if ((get_lun_card(chip, lun) == MS_CARD) &&
(ms_card->format_status == FORMAT_IN_PROGRESS)) {
if ((srb->cmnd[0] != REQUEST_SENSE)
@@ -1994,11 +1919,6 @@ int rts51x_scsi_handler(struct scsi_cmnd *srb, struct rts51x_chip *chip)
* Host functions
***********************************************************************/
-const char *host_info(struct Scsi_Host *host)
-{
- return "SCSI emulation for RTS51xx USB driver-based card reader";
-}
-
int slave_alloc(struct scsi_device *sdev)
{
/*
@@ -2111,14 +2031,7 @@ int queuecommand_lck(struct scsi_cmnd *srb, void (*done) (struct scsi_cmnd *))
return 0;
}
-#if 0 /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) */
-int queuecommand(struct scsi_cmnd *srb, void (*done) (struct scsi_cmnd *))
-{
- return queuecommand_lck(srb, done);
-}
-#else
DEF_SCSI_QCMD(queuecommand)
-#endif
/***********************************************************************
* Error handling functions
***********************************************************************/
diff --git a/drivers/staging/rts5139/rts51x_scsi.h b/drivers/staging/rts5139/rts51x_scsi.h
index 3a8ca069b278..060d2c2e77ec 100644
--- a/drivers/staging/rts5139/rts51x_scsi.h
+++ b/drivers/staging/rts5139/rts51x_scsi.h
@@ -145,16 +145,11 @@ struct Scsi_Host;
struct scsi_device;
struct scsi_cmnd;
-const char *host_info(struct Scsi_Host *host);
int slave_alloc(struct scsi_device *sdev);
int slave_configure(struct scsi_device *sdev);
int proc_info(struct Scsi_Host *host, char *buffer,
char **start, off_t offset, int length, int inout);
-#if 0 /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) */
-int queuecommand(struct scsi_cmnd *srb, void (*done) (struct scsi_cmnd *));
-#else
int queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
-#endif
int command_abort(struct scsi_cmnd *srb);
int device_reset(struct scsi_cmnd *srb);
int bus_reset(struct scsi_cmnd *srb);
diff --git a/drivers/staging/rts5139/rts51x_sys.h b/drivers/staging/rts5139/rts51x_sys.h
deleted file mode 100644
index b09cd34a6c02..000000000000
--- a/drivers/staging/rts5139/rts51x_sys.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Driver for Realtek USB RTS51xx card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- * wwang (wei_wang@realsil.com.cn)
- * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- * Maintainer:
- * Edwin Rong (edwin_rong@realsil.com.cn)
- * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __RTS51X_SYS_H
-#define __RTS51X_SYS_H
-
-#include "rts51x.h"
-#include "rts51x_chip.h"
-#include "rts51x_card.h"
-
-#define USING_POLLING_CYCLE_DELINK
-
-extern int rts51x_check_start_time(struct rts51x_chip *chip);
-extern void rts51x_set_start_time(struct rts51x_chip *chip);
-extern void rts51x_clear_start_time(struct rts51x_chip *chip);
-
-/* typedef dma_addr_t ULONG_PTR; */
-
-static inline void rts51x_reset_detected_cards(struct rts51x_chip *chip)
-{
-/* rts51x_reset_cards(chip); */
-}
-
-static inline void clear_first_install_mark(struct rts51x_chip *chip)
-{
-}
-
-void rts51x_enter_ss(struct rts51x_chip *chip);
-void rts51x_exit_ss(struct rts51x_chip *chip);
-
-#endif /* __RTS51X_SYS_H */
diff --git a/drivers/staging/rts5139/rts51x_transport.c b/drivers/staging/rts5139/rts51x_transport.c
index da9c83b49426..89e4d805a345 100644
--- a/drivers/staging/rts5139/rts51x_transport.c
+++ b/drivers/staging/rts5139/rts51x_transport.c
@@ -120,7 +120,7 @@ unsigned int rts51x_access_sglist(unsigned char *buffer,
return cnt;
}
-unsigned int rts51x_access_xfer_buf(unsigned char *buffer,
+static unsigned int rts51x_access_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb,
struct scatterlist **sgptr,
unsigned int *offset, enum xfer_buf_dir dir)
@@ -252,6 +252,8 @@ static int rts51x_msg_common(struct rts51x_chip *chip, struct urb *urb,
return status;
}
+static int rts51x_clear_halt(struct rts51x_chip *chip, unsigned int pipe);
+
/*
* Interpret the results of a URB transfer
*/
@@ -359,7 +361,7 @@ int rts51x_ctrl_transfer(struct rts51x_chip *chip, unsigned int pipe,
rts51x->current_urb->actual_length);
}
-int rts51x_clear_halt(struct rts51x_chip *chip, unsigned int pipe)
+static int rts51x_clear_halt(struct rts51x_chip *chip, unsigned int pipe)
{
int result;
int endp = usb_pipeendpoint(pipe);
@@ -378,11 +380,6 @@ int rts51x_clear_halt(struct rts51x_chip *chip, unsigned int pipe)
return STATUS_SUCCESS;
}
-int rts51x_reset_pipe(struct rts51x_chip *chip, char pipe)
-{
- return rts51x_clear_halt(chip, pipe);
-}
-
static void rts51x_sg_clean(struct usb_sg_request *io)
{
if (io->urbs) {
@@ -391,226 +388,17 @@ static void rts51x_sg_clean(struct usb_sg_request *io)
kfree(io->urbs);
io->urbs = NULL;
}
-#if 0 /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) */
- if (io->dev->dev.dma_mask != NULL)
- usb_buffer_unmap_sg(io->dev, usb_pipein(io->pipe),
- io->sg, io->nents);
-#endif
io->dev = NULL;
}
-#if 0
-static void rts51x_sg_complete(struct urb *urb)
-{
- struct usb_sg_request *io = urb->context;
- int status = urb->status;
-
- spin_lock(&io->lock);
-
- /* In 2.5 we require hcds' endpoint queues not to progress after fault
- * reports, until the completion callback (this!) returns. That lets
- * device driver code (like this routine) unlink queued urbs first,
- * if it needs to, since the HC won't work on them at all. So it's
- * not possible for page N+1 to overwrite page N, and so on.
- *
- * That's only for "hard" faults; "soft" faults (unlinks) sometimes
- * complete before the HCD can get requests away from hardware,
- * though never during cleanup after a hard fault.
- */
- if (io->status
- && (io->status != -ECONNRESET
- || status != -ECONNRESET)
- && urb->actual_length) {
- dev_err(io->dev->bus->controller,
- "dev %s ep%d%s scatterlist error %d/%d\n",
- io->dev->devpath,
- usb_endpoint_num(&urb->ep->desc),
- usb_urb_dir_in(urb) ? "in" : "out",
- status, io->status);
- /* BUG (); */
- }
-
- if (io->status == 0 && status && status != -ECONNRESET) {
- int i, found, retval;
-
- io->status = status;
-
- /* the previous urbs, and this one, completed already.
- * unlink pending urbs so they won't rx/tx bad data.
- * careful: unlink can sometimes be synchronous...
- */
- spin_unlock(&io->lock);
- for (i = 0, found = 0; i < io->entries; i++) {
- if (!io->urbs[i] || !io->urbs[i]->dev)
- continue;
- if (found) {
- retval = usb_unlink_urb(io->urbs[i]);
- if (retval != -EINPROGRESS &&
- retval != -ENODEV &&
- retval != -EBUSY)
- dev_err(&io->dev->dev,
- "%s, unlink --> %d\n",
- __func__, retval);
- } else if (urb == io->urbs[i])
- found = 1;
- }
- spin_lock(&io->lock);
- }
- urb->dev = NULL;
-
- /* on the last completion, signal usb_sg_wait() */
- io->bytes += urb->actual_length;
- io->count--;
- if (!io->count)
- complete(&io->complete);
-
- spin_unlock(&io->lock);
-}
-
-/* This function is ported from usb_sg_init, which can transfer
- * sg list partially */
-int rts51x_sg_init_partial(struct usb_sg_request *io, struct usb_device *dev,
- unsigned pipe, unsigned period, void *buf, struct scatterlist **sgptr,
- unsigned int *offset, int nents, size_t length, gfp_t mem_flags)
-{
- int i;
- int urb_flags;
- int dma;
- struct scatterlist *sg = *sgptr, *first_sg;
-
- first_sg = (struct scatterlist *)buf;
- if (!sg)
- sg = first_sg;
-
- if (!io || !dev || !sg
- || usb_pipecontrol(pipe)
- || usb_pipeisoc(pipe)
- || (nents <= 0))
- return -EINVAL;
-
- spin_lock_init(&io->lock);
- io->dev = dev;
- io->pipe = pipe;
- io->sg = first_sg; /* used by unmap */
- io->nents = nents;
-
- RTS51X_DEBUGP("Before map, sg address: 0x%x\n", (unsigned int)sg);
- RTS51X_DEBUGP("Before map, dev address: 0x%x\n", (unsigned int)dev);
-
- /* not all host controllers use DMA (like the mainstream pci ones);
- * they can use PIO (sl811) or be software over another transport.
- */
- dma = (dev->dev.dma_mask != NULL);
- if (dma) {
- /* map the whole sg list, because here we only know the
- * total nents */
- io->entries = usb_buffer_map_sg(dev, usb_pipein(pipe),
- first_sg, nents);
- } else {
- io->entries = nents;
- }
-
- /* initialize all the urbs we'll use */
- if (io->entries <= 0)
- return io->entries;
-
- io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags);
- if (!io->urbs)
- goto nomem;
-
- urb_flags = URB_NO_INTERRUPT;
- if (dma)
- urb_flags |= URB_NO_TRANSFER_DMA_MAP;
- if (usb_pipein(pipe))
- urb_flags |= URB_SHORT_NOT_OK;
-
- RTS51X_DEBUGP("io->entries = %d\n", io->entries);
-
- for (i = 0; (sg != NULL) && (length > 0); i++) {
- unsigned len;
-
- RTS51X_DEBUGP("sg address: 0x%x\n", (unsigned int)sg);
- RTS51X_DEBUGP("length = %d, *offset = %d\n", length, *offset);
-
- io->urbs[i] = usb_alloc_urb(0, mem_flags);
- if (!io->urbs[i]) {
- io->entries = i;
- goto nomem;
- }
-
- io->urbs[i]->dev = NULL;
- io->urbs[i]->pipe = pipe;
- io->urbs[i]->interval = period;
- io->urbs[i]->transfer_flags = urb_flags;
-
- io->urbs[i]->complete = rts51x_sg_complete;
- io->urbs[i]->context = io;
-
- if (dma) {
- io->urbs[i]->transfer_dma =
- sg_dma_address(sg) + *offset;
- len = sg_dma_len(sg) - *offset;
- io->urbs[i]->transfer_buffer = NULL;
- RTS51X_DEBUGP(" -- sg entry dma length = %d\n",
- sg_dma_len(sg));
- } else {
- /* hc may use _only_ transfer_buffer */
- io->urbs[i]->transfer_buffer = sg_virt(sg) + *offset;
- len = sg->length - *offset;
- RTS51X_DEBUGP(" -- sg entry length = %d\n",
- sg->length);
- }
-
- if (length >= len) {
- *offset = 0;
- io->urbs[i]->transfer_buffer_length = len;
- length -= len;
- sg = sg_next(sg);
- } else {
- *offset += length;
- io->urbs[i]->transfer_buffer_length = length;
- length = 0;
- }
- if (length == 0)
- io->entries = i + 1;
-#if 0
- if (length) {
- len = min_t(unsigned, len, length);
- length -= len;
- if (length == 0) {
- io->entries = i + 1;
- *offset += len;
- } else {
- *offset = 0;
- }
- }
-#endif
- }
- RTS51X_DEBUGP("In %s, urb count: %d\n", __func__, i);
- io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
-
- RTS51X_DEBUGP("sg address stored in sgptr: 0x%x\n", (unsigned int)sg);
- *sgptr = sg;
-
- /* transaction state */
- io->count = io->entries;
- io->status = 0;
- io->bytes = 0;
- init_completion(&io->complete);
- return 0;
-nomem:
- rts51x_sg_clean(io);
- return -ENOMEM;
-}
-#endif
-int rts51x_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+static int rts51x_sg_init(struct usb_sg_request *io, struct usb_device *dev,
unsigned pipe, unsigned period, struct scatterlist *sg,
int nents, size_t length, gfp_t mem_flags)
{
return usb_sg_init(io, dev, pipe, period, sg, nents, length, mem_flags);
}
-int rts51x_sg_wait(struct usb_sg_request *io, int timeout)
+static int rts51x_sg_wait(struct usb_sg_request *io, int timeout)
{
long timeleft;
int i;
@@ -630,7 +418,7 @@ int rts51x_sg_wait(struct usb_sg_request *io, int timeout)
*/
spin_unlock_irq(&io->lock);
switch (retval) {
- /* maybe we retrying will recover */
+ /* maybe the retry will recover */
case -ENXIO: /* hc didn't queue this one */
case -EAGAIN:
case -ENOMEM:
@@ -740,56 +528,9 @@ static int rts51x_bulk_transfer_sglist(struct rts51x_chip *chip,
return interpret_urb_result(chip, pipe, length, result,
chip->usb->current_sg.bytes);
}
-#if 0
-static int rts51x_bulk_transfer_sglist_partial(struct rts51x_chip *chip,
- unsigned int pipe, void *buf, struct scatterlist **sgptr,
- unsigned int *offset, int num_sg, unsigned int length,
- unsigned int *act_len, int timeout)
-{
- int result;
-
- /* don't submit s-g requests during abort processing */
- if (test_bit(FLIDX_ABORTING, &chip->usb->dflags))
- TRACE_RET(chip, STATUS_ERROR);
- /* initialize the scatter-gather request block */
- RTS51X_DEBUGP("%s: xfer %u bytes, %d entries\n", __func__,
- length, num_sg);
- result = rts51x_sg_init_partial(&chip->usb->current_sg,
- chip->usb->pusb_dev, pipe, 0, buf, sgptr, offset,
- num_sg, length, GFP_NOIO);
- if (result) {
- RTS51X_DEBUGP("rts51x_sg_init_partial returned %d\n", result);
- TRACE_RET(chip, STATUS_ERROR);
- }
-
- /* since the block has been initialized successfully, it's now
- * okay to cancel it */
- set_bit(FLIDX_SG_ACTIVE, &chip->usb->dflags);
-
- /* did an abort occur during the submission? */
- if (test_bit(FLIDX_ABORTING, &chip->usb->dflags)) {
-
- /* cancel the request, if it hasn't been cancelled already */
- if (test_and_clear_bit(FLIDX_SG_ACTIVE, &chip->usb->dflags)) {
- RTS51X_DEBUGP("-- cancelling sg request\n");
- usb_sg_cancel(&chip->usb->current_sg);
- }
- }
-
- /* wait for the completion of the transfer */
- result = rts51x_sg_wait(&chip->usb->current_sg, timeout);
-
- clear_bit(FLIDX_SG_ACTIVE, &chip->usb->dflags);
-
- /* result = us->current_sg.status; */
- if (act_len)
- *act_len = chip->usb->current_sg.bytes;
- return interpret_urb_result(chip, pipe, length, result,
- chip->usb->current_sg.bytes);
-}
-#endif
-int rts51x_bulk_transfer_buf(struct rts51x_chip *chip, unsigned int pipe,
+static int rts51x_bulk_transfer_buf(struct rts51x_chip *chip,
+ unsigned int pipe,
void *buf, unsigned int length,
unsigned int *act_len, int timeout)
{
@@ -860,11 +601,6 @@ int rts51x_transfer_data_partial(struct rts51x_chip *chip, unsigned int pipe,
}
kfree(tmp_buf);
-#if 0
- result = rts51x_bulk_transfer_sglist_partial(chip, pipe, buf,
- (struct scatterlist **)ptr, offset,
- use_sg, len, act_len, timeout);
-#endif
} else {
unsigned int step = 0;
if (offset)
diff --git a/drivers/staging/rts5139/rts51x_transport.h b/drivers/staging/rts5139/rts51x_transport.h
index 9dd556ea9c08..024f115540a6 100644
--- a/drivers/staging/rts5139/rts51x_transport.h
+++ b/drivers/staging/rts5139/rts51x_transport.h
@@ -40,11 +40,6 @@ unsigned int rts51x_access_sglist(unsigned char *buffer,
unsigned int buflen, void *sglist,
void **sgptr, unsigned int *offset,
enum xfer_buf_dir dir);
-unsigned int rts51x_access_xfer_buf(unsigned char *buffer, unsigned int buflen,
- struct scsi_cmnd *srb,
- struct scatterlist **sgptr,
- unsigned int *offset,
- enum xfer_buf_dir dir);
void rts51x_set_xfer_buf(unsigned char *buffer, unsigned int buflen,
struct scsi_cmnd *srb);
void rts51x_get_xfer_buf(unsigned char *buffer, unsigned int buflen,
@@ -53,7 +48,6 @@ void rts51x_get_xfer_buf(unsigned char *buffer, unsigned int buflen,
int rts51x_ctrl_transfer(struct rts51x_chip *chip, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size, int timeout);
-int rts51x_clear_halt(struct rts51x_chip *chip, unsigned int pipe);
int rts51x_transfer_data(struct rts51x_chip *chip, unsigned int pipe,
void *buf, unsigned int len, int use_sg,
unsigned int *act_len, int timeout);
@@ -62,12 +56,6 @@ int rts51x_transfer_data_partial(struct rts51x_chip *chip, unsigned int pipe,
unsigned int len, int use_sg,
unsigned int *act_len, int timeout);
-/* whichPipe:
- * 0: bulk in pipe
- * 1: bulk out pipe
- * 2: intr in pipe */
-int rts51x_reset_pipe(struct rts51x_chip *chip, char pipe);
-
#ifndef POLLING_IN_THREAD
int rts51x_start_epc_transfer(struct rts51x_chip *chip);
void rts51x_cancel_epc_transfer(struct rts51x_chip *chip);
diff --git a/drivers/staging/rts5139/sd.c b/drivers/staging/rts5139/sd.c
index d5dd2f926d1d..b739f26f78cc 100644
--- a/drivers/staging/rts5139/sd.c
+++ b/drivers/staging/rts5139/sd.c
@@ -246,12 +246,7 @@ RTY_SEND_CMD:
if (buf[1] & 0x80)
TRACE_RET(chip, STATUS_FAIL);
}
-#ifdef SUPPORT_SD_LOCK
- /* exclude bit25 CARD_IS_LOCKED */
- if (buf[1] & 0x7D) {
-#else
if (buf[1] & 0x7F) {
-#endif
RTS51X_DEBUGP("buf[1]: 0x%02x\n", buf[1]);
TRACE_RET(chip, STATUS_FAIL);
}
@@ -709,37 +704,7 @@ int sd_select_card(struct rts51x_chip *chip, int select)
return STATUS_SUCCESS;
}
-#ifdef SUPPORT_SD_LOCK
-int sd_update_lock_status(struct rts51x_chip *chip)
-{
- struct sd_info *sd_card = &(chip->sd_card);
- int retval;
- u8 rsp[5];
-
- retval =
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, rsp, 5);
- if (retval != STATUS_SUCCESS)
- TRACE_RET(chip, STATUS_FAIL);
-
- if (rsp[1] & 0x02)
- sd_card->sd_lock_status |= SD_LOCKED;
- else
- sd_card->sd_lock_status &= ~SD_LOCKED;
-
- RTS51X_DEBUGP("sd_card->sd_lock_status = 0x%x\n",
- sd_card->sd_lock_status);
-
- if (rsp[1] & 0x01) {
- /* LOCK_UNLOCK_FAILED */
- TRACE_RET(chip, STATUS_FAIL);
- }
-
- return STATUS_SUCCESS;
-}
-#endif
-
-int sd_wait_currentstate_dataready(struct rts51x_chip *chip, u8 statechk,
+static int sd_wait_currentstate_dataready(struct rts51x_chip *chip, u8 statechk,
u8 rdychk, u16 pollingcnt)
{
struct sd_info *sd_card = &(chip->sd_card);
@@ -1197,15 +1162,6 @@ static int sd_switch_function(struct rts51x_chip *chip, u8 bus_width)
RTS51X_DEBUGP("SD_FUNC_GROUP_1: func_to_switch = 0x%02x",
func_to_switch);
-#ifdef SUPPORT_SD_LOCK
- if ((sd_card->sd_lock_status & SD_SDR_RST)
- && (DDR50_SUPPORT == func_to_switch)
- && (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) {
- func_to_switch = SDR50_SUPPORT;
- RTS51X_DEBUGP("Using SDR50 instead of DDR50 for SD Lock\n");
- }
-#endif
-
if (func_to_switch) {
retval =
sd_check_switch(chip, SD_FUNC_GROUP_1, func_to_switch,
@@ -1562,7 +1518,7 @@ static u8 sd_search_final_phase(struct rts51x_chip *chip, u32 phase_map,
}
Search_Finish:
- RTS51X_DEBUGP("Final choosen phase: %d\n", final_phase);
+ RTS51X_DEBUGP("Final chosen phase: %d\n", final_phase);
return final_phase;
}
@@ -2024,10 +1980,6 @@ Switch_Fail:
k = 0;
hi_cap_flow = 0;
support_1v8 = 0;
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
- goto SD_UNLOCK_ENTRY;
-#endif
retval = sd_prepare_reset(chip);
if (retval != STATUS_SUCCESS)
@@ -2182,7 +2134,7 @@ RTY_CMD55:
sd_card->sd_addr += (u32) rsp[2] << 16;
/* Get CSD register for Calculating Timing,Capacity,
- * Check CSD to determaine as if this is the SD ROM card */
+ * Check CSD to determine as if this is the SD ROM card */
retval = sd_check_csd(chip, 1);
if (retval != STATUS_SUCCESS)
TRACE_RET(chip, retval);
@@ -2190,20 +2142,6 @@ RTY_CMD55:
retval = sd_select_card(chip, 1);
if (retval != STATUS_SUCCESS)
TRACE_RET(chip, retval);
-#ifdef SUPPORT_SD_LOCK
-SD_UNLOCK_ENTRY:
- /* Get SD lock status */
- retval = sd_update_lock_status(chip);
- if (retval != STATUS_SUCCESS)
- TRACE_RET(chip, STATUS_FAIL);
-
- if (sd_card->sd_lock_status & SD_LOCKED) {
- sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST);
- return STATUS_SUCCESS;
- } else if (!(sd_card->sd_lock_status & SD_UNLOCK_POW_ON)) {
- sd_card->sd_lock_status &= ~SD_PWD_EXIST;
- }
-#endif
/* ACMD42 */
retval =
@@ -2294,10 +2232,6 @@ SD_UNLOCK_ENTRY:
if (retval != STATUS_SUCCESS)
TRACE_RET(chip, retval);
}
-#ifdef SUPPORT_SD_LOCK
- /* clear 1 bit mode status */
- sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
-#endif
if (CHK_SD30_SPEED(sd_card)) {
rts51x_write_register(chip, SD30_DRIVE_SEL, SD30_DRIVE_MASK,
@@ -2380,19 +2314,6 @@ SD_UNLOCK_ENTRY:
chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
- rts51x_init_cmd(chip);
-
- rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0x02);
- rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 0x00);
-
- retval = rts51x_send_cmd(chip, MODE_C, 100);
- if (retval != STATUS_SUCCESS)
- TRACE_RET(chip, retval);
- }
-#endif
-
return STATUS_SUCCESS;
}
@@ -2587,17 +2508,10 @@ static int mmc_switch_timing_bus(struct rts51x_chip *chip)
sd_card->capacity =
((u32) buf[5] << 24) | ((u32) buf[4] << 16) |
((u32) buf[3] << 8) | ((u32) buf[2]);
-#ifdef SUPPORT_SD_LOCK
- if (!(sd_card->sd_lock_status & SD_SDR_RST) && CHECK_UHS50(chip))
- card_type_mask = 0x07;
- else
- card_type_mask = 0x03;
-#else
if (CHECK_UHS50(chip))
card_type_mask = 0x07;
else
card_type_mask = 0x03;
-#endif
card_type = buf[1] & card_type_mask;
if (card_type) {
@@ -2626,15 +2540,9 @@ static int mmc_switch_timing_bus(struct rts51x_chip *chip)
if (mmc_test_switch_bus(chip, MMC_8BIT_BUS) == STATUS_SUCCESS) {
SET_MMC_8BIT(sd_card);
chip->card_bus_width[chip->card2lun[SD_CARD]] = 8;
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
-#endif
} else if (mmc_test_switch_bus(chip, MMC_4BIT_BUS) == STATUS_SUCCESS) {
SET_MMC_4BIT(sd_card);
chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
-#endif
} else {
CLR_MMC_8BIT(sd_card);
CLR_MMC_4BIT(sd_card);
@@ -2652,11 +2560,6 @@ static int reset_mmc(struct rts51x_chip *chip)
u8 change_to_ddr52 = 1;
u8 cmd[5];
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
- goto MMC_UNLOCK_ENTRY;
-#endif
-
MMC_DDR_FAIL:
retval = sd_prepare_reset(chip);
@@ -2745,7 +2648,7 @@ RTY_MMC_RST:
TRACE_RET(chip, retval);
/* Get CSD register for Calculating Timing,Capacity
- * Check CSD to determaine as if this is the SD ROM card */
+ * Check CSD to determine as if this is the SD ROM card */
retval = sd_check_csd(chip, 1);
if (retval != STATUS_SUCCESS)
TRACE_RET(chip, retval);
@@ -2763,13 +2666,6 @@ RTY_MMC_RST:
0);
if (retval != STATUS_SUCCESS)
TRACE_RET(chip, retval);
-#ifdef SUPPORT_SD_LOCK
-MMC_UNLOCK_ENTRY:
- /* Get SD lock status */
- retval = sd_update_lock_status(chip);
- if (retval != STATUS_SUCCESS)
- TRACE_RET(chip, STATUS_FAIL);
-#endif
RTS51X_WRITE_REG(chip, SD_CFG1, SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0);
@@ -2842,18 +2738,6 @@ MMC_UNLOCK_ENTRY:
}
}
}
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
- rts51x_init_cmd(chip);
-
- rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0x02);
- rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 0x00);
-
- retval = rts51x_send_cmd(chip, MODE_C, 100);
- if (retval != STATUS_SUCCESS)
- TRACE_RET(chip, retval);
- }
-#endif
retval = rts51x_get_card_status(chip, &(chip->card_status));
if (retval != STATUS_SUCCESS)
@@ -2879,11 +2763,6 @@ int reset_sd_card(struct rts51x_chip *chip)
sd_card->capacity = 0;
sd_card->sd_switch_fail = 0;
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status = 0;
- sd_card->sd_erase_status = 0;
-#endif
-
sd_clear_reset_fail(chip);
enable_card_clock(chip, SD_CARD);
@@ -3006,7 +2885,7 @@ static int wait_data_buf_ready(struct rts51x_chip *chip)
TRACE_RET(chip, STATUS_FAIL);
}
-void sd_stop_seq_mode(struct rts51x_chip *chip)
+static void sd_stop_seq_mode(struct rts51x_chip *chip)
{
struct sd_info *sd_card = &(chip->sd_card);
int retval;
@@ -3300,7 +3179,7 @@ void sd_cleanup_work(struct rts51x_chip *chip)
}
}
-inline void sd_fill_power_off_card3v3(struct rts51x_chip *chip)
+static inline void sd_fill_power_off_card3v3(struct rts51x_chip *chip)
{
rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0);
@@ -3322,7 +3201,7 @@ inline void sd_fill_power_off_card3v3(struct rts51x_chip *chip)
}
}
-int sd_power_off_card3v3(struct rts51x_chip *chip)
+static int sd_power_off_card3v3(struct rts51x_chip *chip)
{
int retval;
@@ -3346,17 +3225,12 @@ int release_sd_card(struct rts51x_chip *chip)
struct sd_info *sd_card = &(chip->sd_card);
int retval;
- RTS51X_DEBUGP("elease_sd_card\n");
+ RTS51X_DEBUGP("release_sd_card\n");
chip->card_ready &= ~SD_CARD;
chip->card_fail &= ~SD_CARD;
chip->card_wp &= ~SD_CARD;
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status = 0;
- sd_card->sd_erase_status = 0;
-#endif
-
memset(sd_card->raw_csd, 0, 16);
memset(sd_card->raw_scr, 0, 8);
diff --git a/drivers/staging/rts5139/sd.h b/drivers/staging/rts5139/sd.h
index 0805edcaea86..de155d8e682d 100644
--- a/drivers/staging/rts5139/sd.h
+++ b/drivers/staging/rts5139/sd.h
@@ -141,29 +141,6 @@
#define SWITCH_MODE_ERR 0x06
#define SWITCH_PASS 0x07
-#ifdef SUPPORT_SD_LOCK
-/* CMD42 Parameter */
-#define SD_ERASE 0x08
-#define SD_LOCK 0x04
-#define SD_UNLOCK 0x00
-#define SD_CLR_PWD 0x02
-#define SD_SET_PWD 0x01
-
-#define SD_PWD_LEN 0x10
-
-/* SD lock unlock Status */
-#define SD_LOCKED 0x80 /* Global lock status */
-#define SD_LOCK_1BIT_MODE 0x40 /**/
-#define SD_PWD_EXIST 0x20
-#define SD_UNLOCK_POW_ON 0x01 /**/
-#define SD_SDR_RST 0x02 /* Reset SD30 card with current DDR mode to SDR mode. */
-/* g_bySDEraseStatus */
-#define SD_NOT_ERASE 0x00
-#define SD_UNDER_ERASING 0x01
-#define SD_COMPLETE_ERASE 0x02
-/* SD_RW FAIL status */
-#define SD_RW_FORBIDDEN 0x0F /* read/write is forbidden (SD card) */
-#endif
/* Function Group Definition */
/* Function Group 1 */
#define HS_SUPPORT 0x01
@@ -282,17 +259,11 @@ struct timing_phase_path {
int sd_select_card(struct rts51x_chip *chip, int select);
int reset_sd_card(struct rts51x_chip *chip);
int sd_switch_clock(struct rts51x_chip *chip);
-void sd_stop_seq_mode(struct rts51x_chip *chip);
int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
u16 sector_cnt);
void sd_cleanup_work(struct rts51x_chip *chip);
-int sd_power_off_card3v3(struct rts51x_chip *chip);
int release_sd_card(struct rts51x_chip *chip);
-#ifdef SUPPORT_SD_LOCK
-int sd_update_lock_status(struct rts51x_chip *chip);
-#endif
-
#ifdef SUPPORT_CPRM
extern int reset_sd(struct rts51x_chip *chip);
extern int sd_check_data0_status(struct rts51x_chip *chip);
diff --git a/drivers/staging/rts5139/sd_cprm.c b/drivers/staging/rts5139/sd_cprm.c
index d5969d992d84..f8c60711f710 100644
--- a/drivers/staging/rts5139/sd_cprm.c
+++ b/drivers/staging/rts5139/sd_cprm.c
@@ -77,12 +77,7 @@ static inline int get_rsp_type(u8 rsp_code, u8 *rsp_type, int *rsp_len)
return STATUS_SUCCESS;
}
-int soft_reset_sd_card(struct rts51x_chip *chip)
-{
- return reset_sd(chip);
-}
-
-int ext_sd_send_cmd_get_rsp(struct rts51x_chip *chip, u8 cmd_idx,
+static int ext_sd_send_cmd_get_rsp(struct rts51x_chip *chip, u8 cmd_idx,
u32 arg, u8 rsp_type, u8 *rsp, int rsp_len,
int special_check)
{
@@ -206,11 +201,7 @@ RTY_SEND_CMD:
if (buf[1] & 0x80)
TRACE_RET(chip, STATUS_FAIL);
}
-#ifdef SUPPORT_SD_LOCK
- if (buf[1] & 0x7D) {
-#else
if (buf[1] & 0x7F) {
-#endif
TRACE_RET(chip, STATUS_FAIL);
}
if (buf[2] & 0xF8)
@@ -233,7 +224,7 @@ RTY_SEND_CMD:
return STATUS_SUCCESS;
}
-int ext_sd_get_rsp(struct rts51x_chip *chip, int len, u8 *rsp, u8 rsp_type)
+static int ext_sd_get_rsp(struct rts51x_chip *chip, int len, u8 *rsp, u8 rsp_type)
{
int retval, rsp_len;
u16 reg_addr;
@@ -305,26 +296,8 @@ int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
retval = sd_switch_clock(chip);
if (retval != STATUS_SUCCESS)
TRACE_RET(chip, TRANSPORT_FAILED);
-#ifdef SUPPORT_SD_LOCK
- if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
- if (CHK_MMC_8BIT(sd_card)) {
- retval =
- rts51x_write_register(chip, SD_CFG1, 0x03,
- SD_BUS_WIDTH_8);
- if (retval != STATUS_SUCCESS)
- TRACE_RET(chip, TRANSPORT_FAILED);
- } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
- retval =
- rts51x_write_register(chip, SD_CFG1, 0x03,
- SD_BUS_WIDTH_4);
- if (retval != STATUS_SUCCESS)
- TRACE_RET(chip, TRANSPORT_FAILED);
- }
- }
-#else
/* Set H/W SD/MMC Bus Width */
rts51x_write_register(chip, SD_CFG1, 0x03, SD_BUS_WIDTH_4);
-#endif
if (standby) {
retval = sd_select_card(chip, 0);
@@ -350,12 +323,6 @@ int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
if (retval != STATUS_SUCCESS)
TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
}
-#ifdef SUPPORT_SD_LOCK
- /* Get SD lock status */
- retval = sd_update_lock_status(chip);
- if (retval != STATUS_SUCCESS)
- TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
-#endif
return TRANSPORT_GOOD;
@@ -399,21 +366,7 @@ int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
retval = sd_switch_clock(chip);
if (retval != STATUS_SUCCESS)
TRACE_RET(chip, TRANSPORT_FAILED);
-#ifdef SUPPORT_SD_LOCK
- if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
- if (CHK_MMC_8BIT(sd_card))
- bus_width = SD_BUS_WIDTH_8;
- else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card))
- bus_width = SD_BUS_WIDTH_4;
- else
- bus_width = SD_BUS_WIDTH_1;
- } else {
- bus_width = SD_BUS_WIDTH_4;
- }
- RTS51X_DEBUGP("bus_width = %d\n", bus_width);
-#else
bus_width = SD_BUS_WIDTH_4;
-#endif
if (data_len < 512) {
retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
@@ -599,11 +552,6 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
int cmd13_checkbit = 0, write_err = 0;
u8 rsp_type;
u32 i;
-#ifdef SUPPORT_SD_LOCK
- int lock_cmd_fail = 0;
- u8 sd_lock_state = 0;
- u8 lock_cmd_type = 0;
-#endif
if (sd_card->pre_cmd_err) {
sd_card->pre_cmd_err = 0;
@@ -614,12 +562,6 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
retval = sd_switch_clock(chip);
if (retval != STATUS_SUCCESS)
TRACE_RET(chip, STATUS_FAIL);
-#ifdef SUPPORT_SD_LOCK
- if (cmd_idx == LOCK_UNLOCK) {
- sd_lock_state = sd_card->sd_lock_status;
- sd_lock_state &= SD_LOCKED;
- }
-#endif
retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len);
if (retval != STATUS_SUCCESS) {
@@ -631,25 +573,7 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
retval = sd_switch_clock(chip);
if (retval != STATUS_SUCCESS)
TRACE_RET(chip, TRANSPORT_FAILED);
-#ifdef SUPPORT_SD_LOCK
- if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
- if (CHK_MMC_8BIT(sd_card)) {
- retval =
- rts51x_write_register(chip, SD_CFG1, 0x03,
- SD_BUS_WIDTH_8);
- if (retval != STATUS_SUCCESS)
- TRACE_RET(chip, TRANSPORT_FAILED);
- } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
- retval =
- rts51x_write_register(chip, SD_CFG1, 0x03,
- SD_BUS_WIDTH_4);
- if (retval != STATUS_SUCCESS)
- TRACE_RET(chip, TRANSPORT_FAILED);
- }
- }
-#else
rts51x_write_register(chip, SD_CFG1, 0x03, SD_BUS_WIDTH_4);
-#endif
if (data_len < 512) {
retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
@@ -692,10 +616,6 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
else
memcpy(buf, data_buf, data_len);
-#ifdef SUPPORT_SD_LOCK
- if (cmd_idx == LOCK_UNLOCK)
- lock_cmd_type = buf[0] & 0x0F;
-#endif
if (data_len > 256) {
rts51x_init_cmd(chip);
@@ -802,29 +722,6 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
SD_STOP | SD_CLR_ERR);
TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
}
-#ifdef SUPPORT_SD_LOCK
- if (cmd_idx == LOCK_UNLOCK) {
- if (lock_cmd_type == SD_ERASE) {
- sd_card->sd_erase_status = SD_UNDER_ERASING;
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
- }
-
- rts51x_init_cmd(chip);
- rts51x_add_cmd(chip, CHECK_REG_CMD, SD_BUS_STAT, SD_DAT0_STATUS,
- SD_DAT0_STATUS);
- retval = rts51x_send_cmd(chip, MODE_CR, 250);
- if (retval != STATUS_SUCCESS)
- TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
- rts51x_get_rsp(chip, 1, 200); /* Don't care return value */
-
- retval = sd_update_lock_status(chip);
- if (retval != STATUS_SUCCESS) {
- RTS51X_DEBUGP("Lock command fail!\n");
- lock_cmd_fail = 1;
- }
- }
-#endif /* SUPPORT_SD_LOCK */
if (standby) {
retval = sd_select_card(chip, 1);
@@ -865,51 +762,6 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
}
if (retval != STATUS_SUCCESS)
TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-#ifdef SUPPORT_SD_LOCK
- if (cmd_idx == LOCK_UNLOCK) {
- if (!lock_cmd_fail) {
- RTS51X_DEBUGP("lock_cmd_type = 0x%x\n",
- lock_cmd_type);
- if (lock_cmd_type & SD_CLR_PWD)
- sd_card->sd_lock_status &= ~SD_PWD_EXIST;
- if (lock_cmd_type & SD_SET_PWD)
- sd_card->sd_lock_status |= SD_PWD_EXIST;
- }
-
- RTS51X_DEBUGP("sd_lock_state = 0x%x,"
- "sd_card->sd_lock_status = 0x%x\n",
- sd_lock_state, sd_card->sd_lock_status);
- if (sd_lock_state ^ (sd_card->sd_lock_status & SD_LOCKED)) {
- sd_card->sd_lock_notify = 1;
- if (sd_lock_state) {
- if (sd_card->sd_lock_status &
- SD_LOCK_1BIT_MODE) {
- sd_card->sd_lock_status |=
- (SD_UNLOCK_POW_ON | SD_SDR_RST);
- if (CHK_SD(sd_card)) {
- retval = reset_sd(chip);
- if (retval != STATUS_SUCCESS) {
- sd_card->sd_lock_status
- &= ~(SD_UNLOCK_POW_ON |
- SD_SDR_RST);
- TRACE_GOTO(chip,
- SD_Execute_Write_Cmd_Failed);
- }
- }
-
- sd_card->sd_lock_status &=
- ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
- }
- }
- }
- }
-
- if (lock_cmd_fail) {
- scsi_set_resid(srb, 0);
- set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
- TRACE_RET(chip, TRANSPORT_FAILED);
- }
-#endif /* SUPPORT_SD_LOCK */
return TRANSPORT_GOOD;
@@ -1173,30 +1025,18 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip)
switch (srb->cmnd[1] & 0x0F) {
case 0:
/* SD Card Power Off -> ON and Initialization */
-#ifdef SUPPORT_SD_LOCK
- if (0x64 == srb->cmnd[9]) {
- /* Command Mode */
- sd_card->sd_lock_status |= SD_SDR_RST;
- }
-#endif /* SUPPORT_SD_LOCK */
retval = reset_sd_card(chip);
if (retval != STATUS_SUCCESS) {
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_SDR_RST;
-#endif
set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
sd_card->pre_cmd_err = 1;
TRACE_RET(chip, TRANSPORT_FAILED);
}
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_SDR_RST;
-#endif
break;
case 1:
/* reset CMD(CMD0) and Initialization
* (without SD Card Power Off -> ON) */
- retval = soft_reset_sd_card(chip);
+ retval = reset_sd(chip);
if (retval != STATUS_SUCCESS) {
set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
sd_card->pre_cmd_err = 1;
diff --git a/drivers/staging/rts5139/xd.c b/drivers/staging/rts5139/xd.c
index 5820605d1806..58f8ba24caed 100644
--- a/drivers/staging/rts5139/xd.c
+++ b/drivers/staging/rts5139/xd.c
@@ -47,13 +47,6 @@ static inline void xd_set_err_code(struct rts51x_chip *chip, u8 err_code)
xd_card->err_code = err_code;
}
-static inline int xd_check_err_code(struct rts51x_chip *chip, u8 err_code)
-{
- struct xd_info *xd_card = &(chip->xd_card);
-
- return (xd_card->err_code == err_code);
-}
-
static int xd_set_init_para(struct rts51x_chip *chip)
{
struct xd_info *xd_card = &(chip->xd_card);
@@ -862,6 +855,8 @@ static void xd_set_l2p_tbl(struct rts51x_chip *chip, int zone_no, u16 log_off,
zone->l2p_table[log_off] = phy_off;
}
+static int xd_delay_write(struct rts51x_chip *chip);
+
static u32 xd_get_l2p_tbl(struct rts51x_chip *chip, int zone_no, u16 log_off)
{
struct xd_info *xd_card = &(chip->xd_card);
@@ -1182,91 +1177,6 @@ static int xd_copy_page(struct rts51x_chip *chip,
return STATUS_SUCCESS;
}
-#ifdef XD_SPEEDUP
-static int xd_auto_copy_page(struct rts51x_chip *chip,
- u32 old_blk, u32 new_blk,
- u8 start_page, u8 end_page)
-{
- struct xd_info *xd_card = &(chip->xd_card);
- u32 old_page, new_page;
- int retval;
- u8 page_count;
-
- RTS51X_DEBUGP("Auto copy page from block 0x%x to block 0x%x\n",
- old_blk, new_blk);
-
- if (start_page > end_page)
- TRACE_RET(chip, STATUS_FAIL);
-
- page_count = end_page - start_page;
-
- if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND))
- TRACE_RET(chip, STATUS_FAIL);
-
- old_page = (old_blk << xd_card->block_shift) + start_page;
- new_page = (new_blk << xd_card->block_shift) + start_page;
-
- XD_CLR_BAD_NEWBLK(xd_card);
-
- rts51x_init_cmd(chip);
-
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WAITTIME, 0x03, WAIT_FF);
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_PAGELEN, 0xFF, page_count);
-
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR0, 0xFF, 0);
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR1, 0xFF,
- (u8) old_page);
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR2, 0xFF,
- (u8) (old_page >> 8));
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR3, 0xFF,
- (u8) (old_page >> 16));
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR4, 0xFF, 0);
-
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR0, 0xFF, 0);
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR1, 0xFF,
- (u8) new_page);
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR2, 0xFF,
- (u8) (new_page >> 8));
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR3, 0xFF,
- (u8) (new_page >> 16));
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR4, 0xFF, 0);
-
- rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
- PINGPONG_BUFFER);
-
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG,
- XD_BA_TRANSFORM | XD_ADDR_MASK, 0 | xd_card->addr_cycle);
-
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
- XD_AUTO_CHK_DATA_STATUS, 0);
- rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_COPY_PAGES);
- rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END,
- XD_TRANSFER_END);
-
- retval = rts51x_send_cmd(chip, MODE_CR, 100);
- if (retval != STATUS_SUCCESS) {
- rts51x_clear_xd_error(chip);
- TRACE_GOTO(chip, Copy_Fail);
- }
-
- retval = rts51x_get_rsp(chip, 1, 800);
- if (retval != STATUS_SUCCESS) {
- rts51x_clear_xd_error(chip);
- TRACE_GOTO(chip, Copy_Fail);
- }
-
- return STATUS_SUCCESS;
-
-Copy_Fail:
- retval = xd_copy_page(chip, old_blk, new_blk, start_page, end_page);
- if (retval != STATUS_SUCCESS)
- TRACE_RET(chip, retval);
-
- return STATUS_SUCCESS;
-}
-#endif
-
static int xd_reset_cmd(struct rts51x_chip *chip)
{
int retval;
@@ -1686,15 +1596,9 @@ Fail:
XD_CLR_BAD_OLDBLK(xd_card);
TRACE_RET(chip, STATUS_FAIL);
}
-#ifdef XD_SPEEDUP
- retval =
- xd_auto_copy_page(chip, phy_blk, new_blk, 0,
- xd_card->page_off + 1);
-#else
retval =
xd_copy_page(chip, phy_blk, new_blk, 0,
xd_card->page_off + 1);
-#endif
if (retval != STATUS_SUCCESS) {
if (!XD_CHK_BAD_NEWBLK(xd_card)) {
retval = xd_erase_block(chip, new_blk);
@@ -1741,13 +1645,8 @@ static int xd_finish_write(struct rts51x_chip *chip,
TRACE_RET(chip, STATUS_FAIL);
}
} else {
-#ifdef XD_SPEEDUP
- retval = xd_auto_copy_page(chip, old_blk, new_blk,
- page_off, xd_card->page_off + 1);
-#else
retval = xd_copy_page(chip, old_blk, new_blk,
page_off, xd_card->page_off + 1);
-#endif
if (retval != STATUS_SUCCESS) {
if (!XD_CHK_BAD_NEWBLK(xd_card)) {
retval = xd_erase_block(chip, new_blk);
@@ -1789,11 +1688,7 @@ static int xd_prepare_write(struct rts51x_chip *chip,
old_blk, new_blk, log_blk, (int)page_off);
if (page_off) {
-#ifdef XD_SPEEDUP
- retval = xd_auto_copy_page(chip, old_blk, new_blk, 0, page_off);
-#else
retval = xd_copy_page(chip, old_blk, new_blk, 0, page_off);
-#endif
if (retval != STATUS_SUCCESS)
TRACE_RET(chip, retval);
}
@@ -1922,7 +1817,7 @@ Fail:
TRACE_RET(chip, STATUS_FAIL);
}
-int xd_delay_write(struct rts51x_chip *chip)
+static int xd_delay_write(struct rts51x_chip *chip)
{
struct xd_info *xd_card = &(chip->xd_card);
struct xd_delay_write_tag *delay_write = &(xd_card->delay_write);
@@ -1999,18 +1894,11 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
(start_page > delay_write->pageoff)) {
delay_write->delay_write_flag = 0;
if (delay_write->old_phyblock != BLK_NOT_FOUND) {
-#ifdef XD_SPEEDUP
- retval = xd_auto_copy_page(chip,
- delay_write->old_phyblock,
- delay_write->new_phyblock,
- delay_write->pageoff, start_page);
-#else
retval = xd_copy_page(chip,
delay_write->old_phyblock,
delay_write->new_phyblock,
delay_write->pageoff,
start_page);
-#endif
if (retval != STATUS_SUCCESS) {
set_sense_type(chip, lun,
SENSE_TYPE_MEDIA_WRITE_ERR);
@@ -2198,7 +2086,7 @@ void xd_cleanup_work(struct rts51x_chip *chip)
}
}
-int xd_power_off_card3v3(struct rts51x_chip *chip)
+static int xd_power_off_card3v3(struct rts51x_chip *chip)
{
int retval;
@@ -2232,7 +2120,7 @@ int release_xd_card(struct rts51x_chip *chip)
struct xd_info *xd_card = &(chip->xd_card);
int retval;
- RTS51X_DEBUGP("elease_xd_card\n");
+ RTS51X_DEBUGP("release_xd_card\n");
chip->card_ready &= ~XD_CARD;
chip->card_fail &= ~XD_CARD;
diff --git a/drivers/staging/rts5139/xd.h b/drivers/staging/rts5139/xd.h
index fa695903ba65..55e4205e23fa 100644
--- a/drivers/staging/rts5139/xd.h
+++ b/drivers/staging/rts5139/xd.h
@@ -182,12 +182,10 @@
#define CIS1_9 (256 + 9)
int reset_xd_card(struct rts51x_chip *chip);
-int xd_delay_write(struct rts51x_chip *chip);
int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
u16 sector_cnt);
void xd_free_l2p_tbl(struct rts51x_chip *chip);
void xd_cleanup_work(struct rts51x_chip *chip);
-int xd_power_off_card3v3(struct rts51x_chip *chip);
int release_xd_card(struct rts51x_chip *chip);
#endif /* __RTS51X_XD_H */
diff --git a/drivers/staging/rts_pstor/ms.c b/drivers/staging/rts_pstor/ms.c
index f9a4498984cc..0bf6d95b3fab 100644
--- a/drivers/staging/rts_pstor/ms.c
+++ b/drivers/staging/rts_pstor/ms.c
@@ -4136,7 +4136,7 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
#else
retval = ms_transfer_data(chip, MS_TM_AUTO_WRITE, PRO_WRITE_LONG_DATA,
2, WAIT_INT, 0, 0, buf + 4, 1024);
- if ((retval != STATUS_SUCCESS) || check_ms_err(chip) {
+ if ((retval != STATUS_SUCCESS) || check_ms_err(chip)) {
rtsx_clear_ms_error(chip);
if (ms_card->mg_auth == 0) {
if ((buf[5] & 0xC0) != 0) {
diff --git a/drivers/staging/rts_pstor/rtsx_transport.c b/drivers/staging/rts_pstor/rtsx_transport.c
index 9b2e5c99870f..54a474235f26 100644
--- a/drivers/staging/rts_pstor/rtsx_transport.c
+++ b/drivers/staging/rts_pstor/rtsx_transport.c
@@ -130,7 +130,7 @@ unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer,
/* Store the contents of buffer into srb's transfer buffer and set the
* SCSI residue. */
void rtsx_stor_set_xfer_buf(unsigned char *buffer,
- unsigned int buflen, struct scsi_cmnd *srb)
+ unsigned int buflen, struct scsi_cmnd *srb)
{
unsigned int index = 0, offset = 0;
@@ -141,7 +141,7 @@ void rtsx_stor_set_xfer_buf(unsigned char *buffer,
}
void rtsx_stor_get_xfer_buf(unsigned char *buffer,
- unsigned int buflen, struct scsi_cmnd *srb)
+ unsigned int buflen, struct scsi_cmnd *srb)
{
unsigned int index = 0, offset = 0;
diff --git a/drivers/staging/sep/sep_driver_config.h b/drivers/staging/sep/sep_driver_config.h
index fa7c0d09bfa5..9d9fc7c94a6e 100644
--- a/drivers/staging/sep/sep_driver_config.h
+++ b/drivers/staging/sep/sep_driver_config.h
@@ -68,11 +68,11 @@
#define SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE 16
/* flag that signifies tah the lock is
-currently held by the proccess (struct file) */
+currently held by the process (struct file) */
#define SEP_DRIVER_OWN_LOCK_FLAG 1
/* flag that signifies tah the lock is currently NOT
-held by the proccess (struct file) */
+held by the process (struct file) */
#define SEP_DRIVER_DISOWN_LOCK_FLAG 0
/* indicates whether driver has mapped/unmapped shared area */
@@ -280,7 +280,7 @@ held by the proccess (struct file) */
/*
* Used to limit number of concurrent processes
- * allowed to allocte dynamic buffers in fastcall
+ * allowed to allocate dynamic buffers in fastcall
* interface.
*/
#define SEP_DOUBLEBUF_USERS_LIMIT 3
diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c
index f1701bc6e312..df1d13e96fcd 100644
--- a/drivers/staging/sep/sep_main.c
+++ b/drivers/staging/sep/sep_main.c
@@ -786,7 +786,7 @@ static unsigned int sep_poll(struct file *filp, poll_table *wait)
"[PID%d] poll: send_ct is %lx reply ct is %lx\n",
current->pid, sep->send_ct, sep->reply_ct);
- /* Check if error occured during poll */
+ /* Check if error occurred during poll */
retval2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
if ((retval2 != 0x0) && (retval2 != 0x8)) {
dev_dbg(&sep->pdev->dev, "[PID%d] poll; poll error %x\n",
@@ -1160,7 +1160,7 @@ static int sep_lock_kernel_pages(struct sep_device *sep,
/* Put mapped kernel sg into kernel resource array */
- /* Set output params acording to the in_out flag */
+ /* Set output params according to the in_out flag */
if (in_out_flag == SEP_DRIVER_IN_FLAG) {
*lli_array_ptr = lli_array;
dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages =
@@ -1358,7 +1358,7 @@ static int sep_lock_user_pages(struct sep_device *sep,
lli_array[num_pages - 1].block_size);
}
- /* Set output params acording to the in_out flag */
+ /* Set output params according to the in_out flag */
if (in_out_flag == SEP_DRIVER_IN_FLAG) {
*lli_array_ptr = lli_array;
dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages =
@@ -2038,7 +2038,7 @@ static int sep_prepare_input_dma_table(struct sep_device *sep,
/*
* If this is not the last table -
- * then allign it to the block size
+ * then align it to the block size
*/
if (!last_table_flag)
table_data_size =
@@ -3033,7 +3033,7 @@ static int sep_free_dcb_handler(struct sep_device *sep,
* @cmd: command
* @arg: pointer to argument structure
*
- * Implement the ioctl methods availble on the SEP device.
+ * Implement the ioctl methods available on the SEP device.
*/
static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
@@ -4460,7 +4460,7 @@ static int sep_pm_runtime_suspend(struct device *dev)
* @sep_pm_runtime_resume: resume- no communication with cpu & main memory
* @sep_pm_runtime_suspend: suspend- no communication with cpu & main memory
* @sep_pci_suspend: suspend - main memory is still ON
- * @sep_pci_resume: resume - main meory is still ON
+ * @sep_pci_resume: resume - main memory is still ON
*/
static const struct dev_pm_ops sep_pm = {
.runtime_resume = sep_pm_runtime_resume,
diff --git a/drivers/staging/serial/68360serial.c b/drivers/staging/serial/68360serial.c
deleted file mode 100644
index daf0b1d0dc28..000000000000
--- a/drivers/staging/serial/68360serial.c
+++ /dev/null
@@ -1,2979 +0,0 @@
-/*
- * UART driver for 68360 CPM SCC or SMC
- * Copyright (c) 2000 D. Jeff Dionne <jeff@uclinux.org>,
- * Copyright (c) 2000 Michael Leslie <mleslie@lineo.ca>
- * Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
- *
- * I used the serial.c driver as the framework for this driver.
- * Give credit to those guys.
- * The original code was written for the MBX860 board. I tried to make
- * it generic, but there may be some assumptions in the structures that
- * have to be fixed later.
- * To save porting time, I did not bother to change any object names
- * that are not accessed outside of this file.
- * It still needs lots of work........When it was easy, I included code
- * to support the SCCs, but this has never been tested, nor is it complete.
- * Only the SCCs support modem control, so that is not complete either.
- *
- * This module exports the following rs232 io functions:
- *
- * int rs_360_init(void);
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <asm/irq.h>
-#include <asm/m68360.h>
-#include <asm/commproc.h>
-
-
-#ifdef CONFIG_KGDB
-extern void breakpoint(void);
-extern void set_debug_traps(void);
-extern int kgdb_output_string (const char* s, unsigned int count);
-#endif
-
-
-/* #ifdef CONFIG_SERIAL_CONSOLE */ /* This seems to be a post 2.0 thing - mles */
-#include <linux/console.h>
-#include <linux/jiffies.h>
-
-/* this defines the index into rs_table for the port to use
- */
-#ifndef CONFIG_SERIAL_CONSOLE_PORT
-#define CONFIG_SERIAL_CONSOLE_PORT 1 /* ie SMC2 - note USE_SMC2 must be defined */
-#endif
-/* #endif */
-
-#if 0
-/* SCC2 for console
- */
-#undef CONFIG_SERIAL_CONSOLE_PORT
-#define CONFIG_SERIAL_CONSOLE_PORT 2
-#endif
-
-
-#define TX_WAKEUP ASYNC_SHARE_IRQ
-
-static char *serial_name = "CPM UART driver";
-static char *serial_version = "0.03";
-
-static struct tty_driver *serial_driver;
-int serial_console_setup(struct console *co, char *options);
-
-/*
- * Serial driver configuration section. Here are the various options:
- */
-#define SERIAL_PARANOIA_CHECK
-#define CONFIG_SERIAL_NOPAUSE_IO
-#define SERIAL_DO_RESTART
-
-/* Set of debugging defines */
-
-#undef SERIAL_DEBUG_INTR
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
-#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-
-#define _INLINE_ inline
-
-#define DBG_CNT(s)
-
-/* We overload some of the items in the data structure to meet our
- * needs. For example, the port address is the CPM parameter ram
- * offset for the SCC or SMC. The maximum number of ports is 4 SCCs and
- * 2 SMCs. The "hub6" field is used to indicate the channel number, with
- * a flag indicating SCC or SMC, and the number is used as an index into
- * the CPM parameter area for this device.
- * The "type" field is currently set to 0, for PORT_UNKNOWN. It is
- * not currently used. I should probably use it to indicate the port
- * type of SMC or SCC.
- * The SMCs do not support any modem control signals.
- */
-#define smc_scc_num hub6
-#define NUM_IS_SCC ((int)0x00010000)
-#define PORT_NUM(P) ((P) & 0x0000ffff)
-
-
-#if defined (CONFIG_UCQUICC)
-
-volatile extern void *_periph_base;
-/* sipex transceiver
- * mode bits for are on pins
- *
- * SCC2 d16..19
- * SCC3 d20..23
- * SCC4 d24..27
- */
-#define SIPEX_MODE(n,m) ((m & 0x0f)<<(16+4*(n-1)))
-
-static uint sipex_mode_bits = 0x00000000;
-
-#endif
-
-/* There is no `serial_state' defined back here in 2.0.
- * Try to get by with serial_struct
- */
-/* #define serial_state serial_struct */
-
-/* 2.4 -> 2.0 portability problem: async_icount in 2.4 has a few
- * extras: */
-
-#if 0
-struct async_icount_24 {
- __u32 cts, dsr, rng, dcd, tx, rx;
- __u32 frame, parity, overrun, brk;
- __u32 buf_overrun;
-} icount;
-#endif
-
-#if 0
-
-struct serial_state {
- int magic;
- int baud_base;
- unsigned long port;
- int irq;
- int flags;
- int hub6;
- int type;
- int line;
- int revision; /* Chip revision (950) */
- int xmit_fifo_size;
- int custom_divisor;
- int count;
- u8 *iomem_base;
- u16 iomem_reg_shift;
- unsigned short close_delay;
- unsigned short closing_wait; /* time to wait before closing */
- struct async_icount_24 icount;
- int io_type;
- struct async_struct *info;
-};
-#endif
-
-#define SSTATE_MAGIC 0x5302
-
-
-
-/* SMC2 is sometimes used for low performance TDM interfaces. Define
- * this as 1 if you want SMC2 as a serial port UART managed by this driver.
- * Define this as 0 if you wish to use SMC2 for something else.
- */
-#define USE_SMC2 1
-
-#if 0
-/* Define SCC to ttySx mapping. */
-#define SCC_NUM_BASE (USE_SMC2 + 1) /* SCC base tty "number" */
-
-/* Define which SCC is the first one to use for a serial port. These
- * are 0-based numbers, i.e. this assumes the first SCC (SCC1) is used
- * for Ethernet, and the first available SCC for serial UART is SCC2.
- * NOTE: IF YOU CHANGE THIS, you have to change the PROFF_xxx and
- * interrupt vectors in the table below to match.
- */
-#define SCC_IDX_BASE 1 /* table index */
-#endif
-
-
-/* Processors other than the 860 only get SMCs configured by default.
- * Either they don't have SCCs or they are allocated somewhere else.
- * Of course, there are now 860s without some SCCs, so we will need to
- * address that someday.
- * The Embedded Planet Multimedia I/O cards use TDM interfaces to the
- * stereo codec parts, and we use SMC2 to help support that.
- */
-static struct serial_state rs_table[] = {
-/* type line PORT IRQ FLAGS smc_scc_num (F.K.A. hub6) */
- { 0, 0, PRSLOT_SMC1, CPMVEC_SMC1, 0, 0 } /* SMC1 ttyS0 */
-#if USE_SMC2
- ,{ 0, 0, PRSLOT_SMC2, CPMVEC_SMC2, 0, 1 } /* SMC2 ttyS1 */
-#endif
-
-#if defined(CONFIG_SERIAL_68360_SCC)
- ,{ 0, 0, PRSLOT_SCC2, CPMVEC_SCC2, 0, (NUM_IS_SCC | 1) } /* SCC2 ttyS2 */
- ,{ 0, 0, PRSLOT_SCC3, CPMVEC_SCC3, 0, (NUM_IS_SCC | 2) } /* SCC3 ttyS3 */
- ,{ 0, 0, PRSLOT_SCC4, CPMVEC_SCC4, 0, (NUM_IS_SCC | 3) } /* SCC4 ttyS4 */
-#endif
-};
-
-#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state))
-
-/* The number of buffer descriptors and their sizes.
- */
-#define RX_NUM_FIFO 4
-#define RX_BUF_SIZE 32
-#define TX_NUM_FIFO 4
-#define TX_BUF_SIZE 32
-
-#define CONSOLE_NUM_FIFO 2
-#define CONSOLE_BUF_SIZE 4
-
-char *console_fifos[CONSOLE_NUM_FIFO * CONSOLE_BUF_SIZE];
-
-/* The async_struct in serial.h does not really give us what we
- * need, so define our own here.
- */
-typedef struct serial_info {
- int magic;
- int flags;
-
- struct serial_state *state;
- /* struct serial_struct *state; */
- /* struct async_struct *state; */
-
- struct tty_struct *tty;
- int read_status_mask;
- int ignore_status_mask;
- int timeout;
- int line;
- int x_char; /* xon/xoff character */
- int close_delay;
- unsigned short closing_wait;
- unsigned short closing_wait2;
- unsigned long event;
- unsigned long last_active;
- int blocked_open; /* # of blocked opens */
- struct work_struct tqueue;
- struct work_struct tqueue_hangup;
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
-
-
-/* CPM Buffer Descriptor pointers.
- */
- QUICC_BD *rx_bd_base;
- QUICC_BD *rx_cur;
- QUICC_BD *tx_bd_base;
- QUICC_BD *tx_cur;
-} ser_info_t;
-
-
-/* since kmalloc_init() does not get called until much after this initialization: */
-static ser_info_t quicc_ser_info[NR_PORTS];
-static char rx_buf_pool[NR_PORTS * RX_NUM_FIFO * RX_BUF_SIZE];
-static char tx_buf_pool[NR_PORTS * TX_NUM_FIFO * TX_BUF_SIZE];
-
-static void change_speed(ser_info_t *info);
-static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout);
-
-static inline int serial_paranoia_check(ser_info_t *info,
- char *name, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
- static const char *badmagic =
- "Warning: bad magic number for serial struct (%s) in %s\n";
- static const char *badinfo =
- "Warning: null async_struct for (%s) in %s\n";
-
- if (!info) {
- printk(badinfo, name, routine);
- return 1;
- }
- if (info->magic != SERIAL_MAGIC) {
- printk(badmagic, name, routine);
- return 1;
- }
-#endif
- return 0;
-}
-
-/*
- * This is used to figure out the divisor speeds and the timeouts,
- * indexed by the termio value. The generic CPM functions are responsible
- * for setting and assigning baud rate generators for us.
- */
-static int baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
-
-/* This sucks. There is a better way: */
-#if defined(CONFIG_CONSOLE_9600)
- #define CONSOLE_BAUDRATE 9600
-#elif defined(CONFIG_CONSOLE_19200)
- #define CONSOLE_BAUDRATE 19200
-#elif defined(CONFIG_CONSOLE_115200)
- #define CONSOLE_BAUDRATE 115200
-#else
- #warning "console baud rate undefined"
- #define CONSOLE_BAUDRATE 9600
-#endif
-
-/*
- * ------------------------------------------------------------
- * rs_stop() and rs_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void rs_360_stop(struct tty_struct *tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- int idx;
- unsigned long flags;
- volatile struct scc_regs *sccp;
- volatile struct smc_regs *smcp;
-
- if (serial_paranoia_check(info, tty->name, "rs_stop"))
- return;
-
- local_irq_save(flags);
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- sccp->scc_sccm &= ~UART_SCCM_TX;
- } else {
- /* smcp = &cpmp->cp_smc[idx]; */
- smcp = &pquicc->smc_regs[idx];
- smcp->smc_smcm &= ~SMCM_TX;
- }
- local_irq_restore(flags);
-}
-
-
-static void rs_360_start(struct tty_struct *tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- int idx;
- unsigned long flags;
- volatile struct scc_regs *sccp;
- volatile struct smc_regs *smcp;
-
- if (serial_paranoia_check(info, tty->name, "rs_stop"))
- return;
-
- local_irq_save(flags);
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- sccp->scc_sccm |= UART_SCCM_TX;
- } else {
- smcp = &pquicc->smc_regs[idx];
- smcp->smc_smcm |= SMCM_TX;
- }
- local_irq_restore(flags);
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * Here starts the interrupt handling routines. All of the following
- * subroutines are declared as inline and are folded into
- * rs_interrupt(). They were separated out for readability's sake.
- *
- * Note: rs_interrupt() is a "fast" interrupt, which means that it
- * runs with interrupts turned off. People who may want to modify
- * rs_interrupt() should try to keep the interrupt handler as fast as
- * possible. After you are done making modifications, it is not a bad
- * idea to do:
- *
- * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
- *
- * and look at the resulting assemble code in serial.s.
- *
- * - Ted Ts'o (tytso@mit.edu), 7-Mar-93
- * -----------------------------------------------------------------------
- */
-
-static _INLINE_ void receive_chars(ser_info_t *info)
-{
- struct tty_struct *tty = info->port.tty;
- unsigned char ch, flag, *cp;
- /*int ignored = 0;*/
- int i;
- ushort status;
- struct async_icount *icount;
- /* struct async_icount_24 *icount; */
- volatile QUICC_BD *bdp;
-
- icount = &info->state->icount;
-
- /* Just loop through the closed BDs and copy the characters into
- * the buffer.
- */
- bdp = info->rx_cur;
- for (;;) {
- if (bdp->status & BD_SC_EMPTY) /* If this one is empty */
- break; /* we are all done */
-
- /* The read status mask tell us what we should do with
- * incoming characters, especially if errors occur.
- * One special case is the use of BD_SC_EMPTY. If
- * this is not set, we are supposed to be ignoring
- * inputs. In this case, just mark the buffer empty and
- * continue.
- */
- if (!(info->read_status_mask & BD_SC_EMPTY)) {
- bdp->status |= BD_SC_EMPTY;
- bdp->status &=
- ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
-
- if (bdp->status & BD_SC_WRAP)
- bdp = info->rx_bd_base;
- else
- bdp++;
- continue;
- }
-
- /* Get the number of characters and the buffer pointer.
- */
- i = bdp->length;
- /* cp = (unsigned char *)__va(bdp->buf); */
- cp = (char *)bdp->buf;
- status = bdp->status;
-
- while (i-- > 0) {
- ch = *cp++;
- icount->rx++;
-
-#ifdef SERIAL_DEBUG_INTR
- printk("DR%02x:%02x...", ch, status);
-#endif
- flag = TTY_NORMAL;
-
- if (status & (BD_SC_BR | BD_SC_FR |
- BD_SC_PR | BD_SC_OV)) {
- /*
- * For statistics only
- */
- if (status & BD_SC_BR)
- icount->brk++;
- else if (status & BD_SC_PR)
- icount->parity++;
- else if (status & BD_SC_FR)
- icount->frame++;
- if (status & BD_SC_OV)
- icount->overrun++;
-
- /*
- * Now check to see if character should be
- * ignored, and mask off conditions which
- * should be ignored.
- if (status & info->ignore_status_mask) {
- if (++ignored > 100)
- break;
- continue;
- }
- */
- status &= info->read_status_mask;
-
- if (status & (BD_SC_BR)) {
-#ifdef SERIAL_DEBUG_INTR
- printk("handling break....");
-#endif
- *tty->flip.flag_buf_ptr = TTY_BREAK;
- if (info->flags & ASYNC_SAK)
- do_SAK(tty);
- } else if (status & BD_SC_PR)
- flag = TTY_PARITY;
- else if (status & BD_SC_FR)
- flag = TTY_FRAME;
- }
- tty_insert_flip_char(tty, ch, flag);
- if (status & BD_SC_OV)
- /*
- * Overrun is special, since it's
- * reported immediately, and doesn't
- * affect the current character
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
-
- /* This BD is ready to be used again. Clear status.
- * Get next BD.
- */
- bdp->status |= BD_SC_EMPTY;
- bdp->status &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
-
- if (bdp->status & BD_SC_WRAP)
- bdp = info->rx_bd_base;
- else
- bdp++;
- }
-
- info->rx_cur = (QUICC_BD *)bdp;
-
- tty_schedule_flip(tty);
-}
-
-static _INLINE_ void receive_break(ser_info_t *info)
-{
- struct tty_struct *tty = info->port.tty;
-
- info->state->icount.brk++;
- /* Check to see if there is room in the tty buffer for
- * the break. If not, we exit now, losing the break. FIXME
- */
- tty_insert_flip_char(tty, 0, TTY_BREAK);
- tty_schedule_flip(tty);
-}
-
-static _INLINE_ void transmit_chars(ser_info_t *info)
-{
-
- if ((info->flags & TX_WAKEUP) ||
- (info->port.tty->flags & (1 << TTY_DO_WRITE_WAKEUP))) {
- schedule_work(&info->tqueue);
- }
-
-#ifdef SERIAL_DEBUG_INTR
- printk("THRE...");
-#endif
-}
-
-#ifdef notdef
- /* I need to do this for the SCCs, so it is left as a reminder.
- */
-static _INLINE_ void check_modem_status(struct async_struct *info)
-{
- int status;
- /* struct async_icount *icount; */
- struct async_icount_24 *icount;
-
- status = serial_in(info, UART_MSR);
-
- if (status & UART_MSR_ANY_DELTA) {
- icount = &info->state->icount;
- /* update input line counters */
- if (status & UART_MSR_TERI)
- icount->rng++;
- if (status & UART_MSR_DDSR)
- icount->dsr++;
- if (status & UART_MSR_DDCD) {
- icount->dcd++;
-#ifdef CONFIG_HARD_PPS
- if ((info->flags & ASYNC_HARDPPS_CD) &&
- (status & UART_MSR_DCD))
- hardpps();
-#endif
- }
- if (status & UART_MSR_DCTS)
- icount->cts++;
- wake_up_interruptible(&info->delta_msr_wait);
- }
-
- if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
-#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
- printk("ttys%d CD now %s...", info->line,
- (status & UART_MSR_DCD) ? "on" : "off");
-#endif
- if (status & UART_MSR_DCD)
- wake_up_interruptible(&info->open_wait);
- else {
-#ifdef SERIAL_DEBUG_OPEN
- printk("scheduling hangup...");
-#endif
- queue_task(&info->tqueue_hangup,
- &tq_scheduler);
- }
- }
- if (info->flags & ASYNC_CTS_FLOW) {
- if (info->port.tty->hw_stopped) {
- if (status & UART_MSR_CTS) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
- printk("CTS tx start...");
-#endif
- info->port.tty->hw_stopped = 0;
- info->IER |= UART_IER_THRI;
- serial_out(info, UART_IER, info->IER);
- rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
- return;
- }
- } else {
- if (!(status & UART_MSR_CTS)) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
- printk("CTS tx stop...");
-#endif
- info->port.tty->hw_stopped = 1;
- info->IER &= ~UART_IER_THRI;
- serial_out(info, UART_IER, info->IER);
- }
- }
- }
-}
-#endif
-
-/*
- * This is the serial driver's interrupt routine for a single port
- */
-/* static void rs_360_interrupt(void *dev_id) */ /* until and if we start servicing irqs here */
-static void rs_360_interrupt(int vec, void *dev_id)
-{
- u_char events;
- int idx;
- ser_info_t *info;
- volatile struct smc_regs *smcp;
- volatile struct scc_regs *sccp;
-
- info = dev_id;
-
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- events = sccp->scc_scce;
- if (events & SCCM_RX)
- receive_chars(info);
- if (events & SCCM_TX)
- transmit_chars(info);
- sccp->scc_scce = events;
- } else {
- smcp = &pquicc->smc_regs[idx];
- events = smcp->smc_smce;
- if (events & SMCM_BRKE)
- receive_break(info);
- if (events & SMCM_RX)
- receive_chars(info);
- if (events & SMCM_TX)
- transmit_chars(info);
- smcp->smc_smce = events;
- }
-
-#ifdef SERIAL_DEBUG_INTR
- printk("rs_interrupt_single(%d, %x)...",
- info->state->smc_scc_num, events);
-#endif
-#ifdef modem_control
- check_modem_status(info);
-#endif
- info->last_active = jiffies;
-#ifdef SERIAL_DEBUG_INTR
- printk("end.\n");
-#endif
-}
-
-
-/*
- * -------------------------------------------------------------------
- * Here ends the serial interrupt routines.
- * -------------------------------------------------------------------
- */
-
-
-static void do_softint(void *private_)
-{
- ser_info_t *info = (ser_info_t *) private_;
- struct tty_struct *tty;
-
- tty = info->port.tty;
- if (!tty)
- return;
-
- if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
- tty_wakeup(tty);
-}
-
-
-/*
- * This routine is called from the scheduler tqueue when the interrupt
- * routine has signalled that a hangup has occurred. The path of
- * hangup processing is:
- *
- * serial interrupt routine -> (scheduler tqueue) ->
- * do_serial_hangup() -> tty->hangup() -> rs_hangup()
- *
- */
-static void do_serial_hangup(void *private_)
-{
- struct async_struct *info = (struct async_struct *) private_;
- struct tty_struct *tty;
-
- tty = info->port.tty;
- if (!tty)
- return;
-
- tty_hangup(tty);
-}
-
-
-static int startup(ser_info_t *info)
-{
- unsigned long flags;
- int retval=0;
- int idx;
- /*struct serial_state *state = info->state;*/
- volatile struct smc_regs *smcp;
- volatile struct scc_regs *sccp;
- volatile struct smc_uart_pram *up;
- volatile struct uart_pram *scup;
-
-
- local_irq_save(flags);
-
- if (info->flags & ASYNC_INITIALIZED) {
- goto errout;
- }
-
-#ifdef maybe
- if (!state->port || !state->type) {
- if (info->port.tty)
- set_bit(TTY_IO_ERROR, &info->port.tty->flags);
- goto errout;
- }
-#endif
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("starting up ttys%d (irq %d)...", info->line, state->irq);
-#endif
-
-
-#ifdef modem_control
- info->MCR = 0;
- if (info->port.tty->termios->c_cflag & CBAUD)
- info->MCR = UART_MCR_DTR | UART_MCR_RTS;
-#endif
-
- if (info->port.tty)
- clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
- /*
- * and set the speed of the serial port
- */
- change_speed(info);
-
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- scup = &pquicc->pram[info->state->port].scc.pscc.u;
-
- scup->mrblr = RX_BUF_SIZE;
- scup->max_idl = RX_BUF_SIZE;
-
- sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX);
- sccp->scc_gsmr.w.low |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-
- } else {
- smcp = &pquicc->smc_regs[idx];
-
- /* Enable interrupts and I/O.
- */
- smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
- smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
-
- /* We can tune the buffer length and idle characters
- * to take advantage of the entire incoming buffer size.
- * If mrblr is something other than 1, maxidl has to be
- * non-zero or we never get an interrupt. The maxidl
- * is the number of character times we wait after reception
- * of the last character before we decide no more characters
- * are coming.
- */
- /* up = (smc_uart_t *)&pquicc->cp_dparam[state->port]; */
- /* holy unionized structures, Batman: */
- up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u;
-
- up->mrblr = RX_BUF_SIZE;
- up->max_idl = RX_BUF_SIZE;
-
- up->brkcr = 1; /* number of break chars */
- }
-
- info->flags |= ASYNC_INITIALIZED;
- local_irq_restore(flags);
- return 0;
-
-errout:
- local_irq_restore(flags);
- return retval;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(ser_info_t *info)
-{
- unsigned long flags;
- struct serial_state *state;
- int idx;
- volatile struct smc_regs *smcp;
- volatile struct scc_regs *sccp;
-
- if (!(info->flags & ASYNC_INITIALIZED))
- return;
-
- state = info->state;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("Shutting down serial port %d (irq %d)....", info->line,
- state->irq);
-#endif
-
- local_irq_save(flags);
-
- idx = PORT_NUM(state->smc_scc_num);
- if (state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- sccp->scc_gsmr.w.low &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-#ifdef CONFIG_SERIAL_CONSOLE
- /* We can't disable the transmitter if this is the
- * system console.
- */
- if ((state - rs_table) != CONFIG_SERIAL_CONSOLE_PORT)
-#endif
- sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
- } else {
- smcp = &pquicc->smc_regs[idx];
-
- /* Disable interrupts and I/O.
- */
- smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
-#ifdef CONFIG_SERIAL_CONSOLE
- /* We can't disable the transmitter if this is the
- * system console.
- */
- if ((state - rs_table) != CONFIG_SERIAL_CONSOLE_PORT)
-#endif
- smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
- }
-
- if (info->port.tty)
- set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
- info->flags &= ~ASYNC_INITIALIZED;
- local_irq_restore(flags);
-}
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static void change_speed(ser_info_t *info)
-{
- int baud_rate;
- unsigned cflag, cval, scval, prev_mode;
- int i, bits, sbits, idx;
- unsigned long flags;
- struct serial_state *state;
- volatile struct smc_regs *smcp;
- volatile struct scc_regs *sccp;
-
- if (!info->port.tty || !info->port.tty->termios)
- return;
- cflag = info->port.tty->termios->c_cflag;
-
- state = info->state;
-
- /* Character length programmed into the mode register is the
- * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
- * 1 or 2 stop bits, minus 1.
- * The value 'bits' counts this for us.
- */
- cval = 0;
- scval = 0;
-
- /* byte size and parity */
- switch (cflag & CSIZE) {
- case CS5: bits = 5; break;
- case CS6: bits = 6; break;
- case CS7: bits = 7; break;
- case CS8: bits = 8; break;
- /* Never happens, but GCC is too dumb to figure it out */
- default: bits = 8; break;
- }
- sbits = bits - 5;
-
- if (cflag & CSTOPB) {
- cval |= SMCMR_SL; /* Two stops */
- scval |= SCU_PMSR_SL;
- bits++;
- }
- if (cflag & PARENB) {
- cval |= SMCMR_PEN;
- scval |= SCU_PMSR_PEN;
- bits++;
- }
- if (!(cflag & PARODD)) {
- cval |= SMCMR_PM_EVEN;
- scval |= (SCU_PMSR_REVP | SCU_PMSR_TEVP);
- }
-
- /* Determine divisor based on baud rate */
- i = cflag & CBAUD;
- if (i >= (sizeof(baud_table)/sizeof(int)))
- baud_rate = 9600;
- else
- baud_rate = baud_table[i];
-
- info->timeout = (TX_BUF_SIZE*HZ*bits);
- info->timeout += HZ/50; /* Add .02 seconds of slop */
-
-#ifdef modem_control
- /* CTS flow control flag and modem status interrupts */
- info->IER &= ~UART_IER_MSI;
- if (info->flags & ASYNC_HARDPPS_CD)
- info->IER |= UART_IER_MSI;
- if (cflag & CRTSCTS) {
- info->flags |= ASYNC_CTS_FLOW;
- info->IER |= UART_IER_MSI;
- } else
- info->flags &= ~ASYNC_CTS_FLOW;
- if (cflag & CLOCAL)
- info->flags &= ~ASYNC_CHECK_CD;
- else {
- info->flags |= ASYNC_CHECK_CD;
- info->IER |= UART_IER_MSI;
- }
- serial_out(info, UART_IER, info->IER);
-#endif
-
- /*
- * Set up parity check flag
- */
- info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
- if (I_INPCK(info->port.tty))
- info->read_status_mask |= BD_SC_FR | BD_SC_PR;
- if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
- info->read_status_mask |= BD_SC_BR;
-
- /*
- * Characters to ignore
- */
- info->ignore_status_mask = 0;
- if (I_IGNPAR(info->port.tty))
- info->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
- if (I_IGNBRK(info->port.tty)) {
- info->ignore_status_mask |= BD_SC_BR;
- /*
- * If we're ignore parity and break indicators, ignore
- * overruns too. (For real raw support).
- */
- if (I_IGNPAR(info->port.tty))
- info->ignore_status_mask |= BD_SC_OV;
- }
- /*
- * !!! ignore all characters if CREAD is not set
- */
- if ((cflag & CREAD) == 0)
- info->read_status_mask &= ~BD_SC_EMPTY;
- local_irq_save(flags);
-
- /* Start bit has not been added (so don't, because we would just
- * subtract it later), and we need to add one for the number of
- * stops bits (there is always at least one).
- */
- bits++;
- idx = PORT_NUM(state->smc_scc_num);
- if (state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- sccp->scc_psmr = (sbits << 12) | scval;
- } else {
- smcp = &pquicc->smc_regs[idx];
-
- /* Set the mode register. We want to keep a copy of the
- * enables, because we want to put them back if they were
- * present.
- */
- prev_mode = smcp->smc_smcmr;
- smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART;
- smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN));
- }
-
- m360_cpm_setbrg((state - rs_table), baud_rate);
-
- local_irq_restore(flags);
-}
-
-static void rs_360_put_char(struct tty_struct *tty, unsigned char ch)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- volatile QUICC_BD *bdp;
-
- if (serial_paranoia_check(info, tty->name, "rs_put_char"))
- return 0;
-
- if (!tty)
- return 0;
-
- bdp = info->tx_cur;
- while (bdp->status & BD_SC_READY);
-
- /* *((char *)__va(bdp->buf)) = ch; */
- *((char *)bdp->buf) = ch;
- bdp->length = 1;
- bdp->status |= BD_SC_READY;
-
- /* Get next BD.
- */
- if (bdp->status & BD_SC_WRAP)
- bdp = info->tx_bd_base;
- else
- bdp++;
-
- info->tx_cur = (QUICC_BD *)bdp;
- return 1;
-
-}
-
-static int rs_360_write(struct tty_struct * tty,
- const unsigned char *buf, int count)
-{
- int c, ret = 0;
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- volatile QUICC_BD *bdp;
-
-#ifdef CONFIG_KGDB
- /* Try to let stub handle output. Returns true if it did. */
- if (kgdb_output_string(buf, count))
- return ret;
-#endif
-
- if (serial_paranoia_check(info, tty->name, "rs_write"))
- return 0;
-
- if (!tty)
- return 0;
-
- bdp = info->tx_cur;
-
- while (1) {
- c = min(count, TX_BUF_SIZE);
-
- if (c <= 0)
- break;
-
- if (bdp->status & BD_SC_READY) {
- info->flags |= TX_WAKEUP;
- break;
- }
-
- /* memcpy(__va(bdp->buf), buf, c); */
- memcpy((void *)bdp->buf, buf, c);
-
- bdp->length = c;
- bdp->status |= BD_SC_READY;
-
- buf += c;
- count -= c;
- ret += c;
-
- /* Get next BD.
- */
- if (bdp->status & BD_SC_WRAP)
- bdp = info->tx_bd_base;
- else
- bdp++;
- info->tx_cur = (QUICC_BD *)bdp;
- }
- return ret;
-}
-
-static int rs_360_write_room(struct tty_struct *tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- int ret;
-
- if (serial_paranoia_check(info, tty->name, "rs_write_room"))
- return 0;
-
- if ((info->tx_cur->status & BD_SC_READY) == 0) {
- info->flags &= ~TX_WAKEUP;
- ret = TX_BUF_SIZE;
- }
- else {
- info->flags |= TX_WAKEUP;
- ret = 0;
- }
- return ret;
-}
-
-/* I could track this with transmit counters....maybe later.
-*/
-static int rs_360_chars_in_buffer(struct tty_struct *tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
- return 0;
- return 0;
-}
-
-static void rs_360_flush_buffer(struct tty_struct *tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
- return;
-
- /* There is nothing to "flush", whatever we gave the CPM
- * is on its way out.
- */
- tty_wakeup(tty);
- info->flags &= ~TX_WAKEUP;
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void rs_360_send_xchar(struct tty_struct *tty, char ch)
-{
- volatile QUICC_BD *bdp;
-
- ser_info_t *info = (ser_info_t *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "rs_send_char"))
- return;
-
- bdp = info->tx_cur;
- while (bdp->status & BD_SC_READY);
-
- /* *((char *)__va(bdp->buf)) = ch; */
- *((char *)bdp->buf) = ch;
- bdp->length = 1;
- bdp->status |= BD_SC_READY;
-
- /* Get next BD.
- */
- if (bdp->status & BD_SC_WRAP)
- bdp = info->tx_bd_base;
- else
- bdp++;
-
- info->tx_cur = (QUICC_BD *)bdp;
-}
-
-/*
- * ------------------------------------------------------------
- * rs_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void rs_360_throttle(struct tty_struct * tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
- char buf[64];
-
- printk("throttle %s: %d....\n", _tty_name(tty, buf),
- tty->ldisc.chars_in_buffer(tty));
-#endif
-
- if (serial_paranoia_check(info, tty->name, "rs_throttle"))
- return;
-
- if (I_IXOFF(tty))
- rs_360_send_xchar(tty, STOP_CHAR(tty));
-
-#ifdef modem_control
- if (tty->termios->c_cflag & CRTSCTS)
- info->MCR &= ~UART_MCR_RTS;
-
- local_irq_disable();
- serial_out(info, UART_MCR, info->MCR);
- local_irq_enable();
-#endif
-}
-
-static void rs_360_unthrottle(struct tty_struct * tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
- char buf[64];
-
- printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
- tty->ldisc.chars_in_buffer(tty));
-#endif
-
- if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
- return;
-
- if (I_IXOFF(tty)) {
- if (info->x_char)
- info->x_char = 0;
- else
- rs_360_send_xchar(tty, START_CHAR(tty));
- }
-#ifdef modem_control
- if (tty->termios->c_cflag & CRTSCTS)
- info->MCR |= UART_MCR_RTS;
- local_irq_disable();
- serial_out(info, UART_MCR, info->MCR);
- local_irq_enable();
-#endif
-}
-
-/*
- * ------------------------------------------------------------
- * rs_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-#ifdef maybe
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * is emptied. On bus types like RS485, the transmitter must
- * release the bus after transmitting. This must be done when
- * the transmit shift register is empty, not be done when the
- * transmit holding register is empty. This functionality
- * allows an RS485 driver to be written in user space.
- */
-static int get_lsr_info(struct async_struct * info, unsigned int *value)
-{
- unsigned char status;
- unsigned int result;
-
- local_irq_disable();
- status = serial_in(info, UART_LSR);
- local_irq_enable();
- result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
- return put_user(result,value);
-}
-#endif
-
-static int rs_360_tiocmget(struct tty_struct *tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- unsigned int result = 0;
-#ifdef modem_control
- unsigned char control, status;
-
- if (serial_paranoia_check(info, tty->name, __func__))
- return -ENODEV;
-
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
-
- control = info->MCR;
- local_irq_disable();
- status = serial_in(info, UART_MSR);
- local_irq_enable();
- result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
- | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
-#ifdef TIOCM_OUT1
- | ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0)
- | ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0)
-#endif
- | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
- | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
- | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
- | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-#endif
- return result;
-}
-
-static int rs_360_tiocmset(struct tty_struct *tty,
- unsigned int set, unsigned int clear)
-{
-#ifdef modem_control
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- unsigned int arg;
-
- if (serial_paranoia_check(info, tty->name, __func__))
- return -ENODEV;
-
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
- /* FIXME: locking on info->mcr */
- if (set & TIOCM_RTS)
- info->mcr |= UART_MCR_RTS;
- if (set & TIOCM_DTR)
- info->mcr |= UART_MCR_DTR;
- if (clear & TIOCM_RTS)
- info->MCR &= ~UART_MCR_RTS;
- if (clear & TIOCM_DTR)
- info->MCR &= ~UART_MCR_DTR;
-
-#ifdef TIOCM_OUT1
- if (set & TIOCM_OUT1)
- info->MCR |= UART_MCR_OUT1;
- if (set & TIOCM_OUT2)
- info->MCR |= UART_MCR_OUT2;
- if (clear & TIOCM_OUT1)
- info->MCR &= ~UART_MCR_OUT1;
- if (clear & TIOCM_OUT2)
- info->MCR &= ~UART_MCR_OUT2;
-#endif
-
- local_irq_disable();
- serial_out(info, UART_MCR, info->MCR);
- local_irq_enable();
-#endif
- return 0;
-}
-
-/* Sending a break is a two step process on the SMC/SCC. It is accomplished
- * by sending a STOP TRANSMIT command followed by a RESTART TRANSMIT
- * command. We take advantage of the begin/end functions to make this
- * happen.
- */
-static ushort smc_chan_map[] = {
- CPM_CR_CH_SMC1,
- CPM_CR_CH_SMC2
-};
-
-static ushort scc_chan_map[] = {
- CPM_CR_CH_SCC1,
- CPM_CR_CH_SCC2,
- CPM_CR_CH_SCC3,
- CPM_CR_CH_SCC4
-};
-
-static void begin_break(ser_info_t *info)
-{
- volatile QUICC *cp;
- ushort chan;
- int idx;
-
- cp = pquicc;
-
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC)
- chan = scc_chan_map[idx];
- else
- chan = smc_chan_map[idx];
-
- cp->cp_cr = mk_cr_cmd(chan, CPM_CR_STOP_TX) | CPM_CR_FLG;
- while (cp->cp_cr & CPM_CR_FLG);
-}
-
-static void end_break(ser_info_t *info)
-{
- volatile QUICC *cp;
- ushort chan;
- int idx;
-
- cp = pquicc;
-
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC)
- chan = scc_chan_map[idx];
- else
- chan = smc_chan_map[idx];
-
- cp->cp_cr = mk_cr_cmd(chan, CPM_CR_RESTART_TX) | CPM_CR_FLG;
- while (cp->cp_cr & CPM_CR_FLG);
-}
-
-/*
- * This routine sends a break character out the serial port.
- */
-static void send_break(ser_info_t *info, unsigned int duration)
-{
-#ifdef SERIAL_DEBUG_SEND_BREAK
- printk("rs_send_break(%d) jiff=%lu...", duration, jiffies);
-#endif
- begin_break(info);
- msleep_interruptible(duration);
- end_break(info);
-#ifdef SERIAL_DEBUG_SEND_BREAK
- printk("done jiffies=%lu\n", jiffies);
-#endif
-}
-
-
-/*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
-static int rs_360_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- struct async_icount cnow;
-
- local_irq_disable();
- cnow = info->state->icount;
- local_irq_enable();
-
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
-
- return 0;
-}
-
-static int rs_360_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg)
-{
- int error;
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- int retval;
- struct async_icount cnow;
- /* struct async_icount_24 cnow;*/ /* kernel counter temps */
- struct serial_icounter_struct *p_cuser; /* user space */
-
- if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
- return -ENODEV;
-
- if (cmd != TIOCMIWAIT) {
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
- }
-
- switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (signal_pending(current))
- return -EINTR;
- if (!arg) {
- send_break(info, 250); /* 1/4 second */
- if (signal_pending(current))
- return -EINTR;
- }
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (signal_pending(current))
- return -EINTR;
- send_break(info, arg ? arg*100 : 250);
- if (signal_pending(current))
- return -EINTR;
- return 0;
- case TIOCSBRK:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- begin_break(info);
- return 0;
- case TIOCCBRK:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- end_break(info);
- return 0;
-#ifdef maybe
- case TIOCSERGETLSR: /* Get line status register */
- return get_lsr_info(info, (unsigned int *) arg);
-#endif
- /*
- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
- * - mask passed in arg for lines of interest
- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
- * Caller should use TIOCGICOUNT to see which one it was
- */
- case TIOCMIWAIT:
-#ifdef modem_control
- local_irq_disable();
- /* note the counters on entry */
- cprev = info->state->icount;
- local_irq_enable();
- while (1) {
- interruptible_sleep_on(&info->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- local_irq_disable();
- cnow = info->state->icount; /* atomic copy */
- local_irq_enable();
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
- return 0;
- }
- cprev = cnow;
- }
- /* NOTREACHED */
-#else
- return 0;
-#endif
-
-
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
-}
-
-/* FIX UP modem control here someday......
-*/
-static void rs_360_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
-
- change_speed(info);
-
-#ifdef modem_control
- /* Handle transition to B0 status */
- if ((old_termios->c_cflag & CBAUD) &&
- !(tty->termios->c_cflag & CBAUD)) {
- info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
- local_irq_disable();
- serial_out(info, UART_MCR, info->MCR);
- local_irq_enable();
- }
-
- /* Handle transition away from B0 status */
- if (!(old_termios->c_cflag & CBAUD) &&
- (tty->termios->c_cflag & CBAUD)) {
- info->MCR |= UART_MCR_DTR;
- if (!tty->hw_stopped ||
- !(tty->termios->c_cflag & CRTSCTS)) {
- info->MCR |= UART_MCR_RTS;
- }
- local_irq_disable();
- serial_out(info, UART_MCR, info->MCR);
- local_irq_enable();
- }
-
- /* Handle turning off CRTSCTS */
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- rs_360_start(tty);
- }
-#endif
-
-#if 0
- /*
- * No need to wake up processes in open wait, since they
- * sample the CLOCAL flag once, and don't recheck it.
- * XXX It's not clear whether the current behavior is correct
- * or not. Hence, this may change.....
- */
- if (!(old_termios->c_cflag & CLOCAL) &&
- (tty->termios->c_cflag & CLOCAL))
- wake_up_interruptible(&info->open_wait);
-#endif
-}
-
-/*
- * ------------------------------------------------------------
- * rs_close()
- *
- * This routine is called when the serial port gets closed. First, we
- * wait for the last remaining data to be sent. Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
-static void rs_360_close(struct tty_struct *tty, struct file * filp)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- /* struct async_state *state; */
- struct serial_state *state;
- unsigned long flags;
- int idx;
- volatile struct smc_regs *smcp;
- volatile struct scc_regs *sccp;
-
- if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
- return;
-
- state = info->state;
-
- local_irq_save(flags);
-
- if (tty_hung_up_p(filp)) {
- DBG_CNT("before DEC-hung");
- local_irq_restore(flags);
- return;
- }
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_close ttys%d, count = %d\n", info->line, state->count);
-#endif
- if ((tty->count == 1) && (state->count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. state->count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- printk("rs_close: bad serial port count; tty->count is 1, "
- "state->count is %d\n", state->count);
- state->count = 1;
- }
- if (--state->count < 0) {
- printk("rs_close: bad serial port count for ttys%d: %d\n",
- info->line, state->count);
- state->count = 0;
- }
- if (state->count) {
- DBG_CNT("before DEC-2");
- local_irq_restore(flags);
- return;
- }
- info->flags |= ASYNC_CLOSING;
- /*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters.
- */
- tty->closing = 1;
- if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, info->closing_wait);
- /*
- * At this point we stop accepting input. To do this, we
- * disable the receive line status interrupts, and tell the
- * interrupt driver to stop checking the data ready bit in the
- * line status register.
- */
- info->read_status_mask &= ~BD_SC_EMPTY;
- if (info->flags & ASYNC_INITIALIZED) {
-
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
- sccp = &pquicc->scc_regs[idx];
- sccp->scc_sccm &= ~UART_SCCM_RX;
- sccp->scc_gsmr.w.low &= ~SCC_GSMRL_ENR;
- } else {
- smcp = &pquicc->smc_regs[idx];
- smcp->smc_smcm &= ~SMCM_RX;
- smcp->smc_smcmr &= ~SMCMR_REN;
- }
- /*
- * Before we drop DTR, make sure the UART transmitter
- * has completely drained; this is especially
- * important if there is a transmit FIFO!
- */
- rs_360_wait_until_sent(tty, info->timeout);
- }
- shutdown(info);
- rs_360_flush_buffer(tty);
- tty_ldisc_flush(tty);
- tty->closing = 0;
- info->event = 0;
- info->port.tty = NULL;
- if (info->blocked_open) {
- if (info->close_delay) {
- msleep_interruptible(jiffies_to_msecs(info->close_delay));
- }
- wake_up_interruptible(&info->open_wait);
- }
- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&info->close_wait);
- local_irq_restore(flags);
-}
-
-/*
- * rs_wait_until_sent() --- wait until the transmitter is empty
- */
-static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- unsigned long orig_jiffies, char_time;
- /*int lsr;*/
- volatile QUICC_BD *bdp;
-
- if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent"))
- return;
-
-#ifdef maybe
- if (info->state->type == PORT_UNKNOWN)
- return;
-#endif
-
- orig_jiffies = jiffies;
- /*
- * Set the check interval to be 1/5 of the estimated time to
- * send a single character, and make it at least 1. The check
- * interval should also be less than the timeout.
- *
- * Note: we have to use pretty tight timings here to satisfy
- * the NIST-PCTS.
- */
- char_time = 1;
- if (timeout)
- char_time = min(char_time, (unsigned long)timeout);
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
- printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
- printk("jiff=%lu...", jiffies);
-#endif
-
- /* We go through the loop at least once because we can't tell
- * exactly when the last character exits the shifter. There can
- * be at least two characters waiting to be sent after the buffers
- * are empty.
- */
- do {
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
- printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
-#endif
-/* current->counter = 0; make us low-priority */
- msleep_interruptible(jiffies_to_msecs(char_time));
- if (signal_pending(current))
- break;
- if (timeout && (time_after(jiffies, orig_jiffies + timeout)))
- break;
- /* The 'tx_cur' is really the next buffer to send. We
- * have to back up to the previous BD and wait for it
- * to go. This isn't perfect, because all this indicates
- * is the buffer is available. There are still characters
- * in the CPM FIFO.
- */
- bdp = info->tx_cur;
- if (bdp == info->tx_bd_base)
- bdp += (TX_NUM_FIFO-1);
- else
- bdp--;
- } while (bdp->status & BD_SC_READY);
- current->state = TASK_RUNNING;
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
- printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
-#endif
-}
-
-/*
- * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void rs_360_hangup(struct tty_struct *tty)
-{
- ser_info_t *info = (ser_info_t *)tty->driver_data;
- struct serial_state *state = info->state;
-
- if (serial_paranoia_check(info, tty->name, "rs_hangup"))
- return;
-
- state = info->state;
-
- rs_360_flush_buffer(tty);
- shutdown(info);
- info->event = 0;
- state->count = 0;
- info->flags &= ~ASYNC_NORMAL_ACTIVE;
- info->port.tty = NULL;
- wake_up_interruptible(&info->open_wait);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_open() and friends
- * ------------------------------------------------------------
- */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
- ser_info_t *info)
-{
-#ifdef DO_THIS_LATER
- DECLARE_WAITQUEUE(wait, current);
-#endif
- struct serial_state *state = info->state;
- int retval;
- int do_clocal = 0;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (tty_hung_up_p(filp) ||
- (info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
- if (info->flags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
-#else
- return -EAGAIN;
-#endif
- }
-
- /*
- * If non-blocking mode is set, or the port is not enabled,
- * then make the check up front and then exit.
- * If this is an SMC port, we don't have modem control to wait
- * for, so just get out here.
- */
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR)) ||
- !(info->state->smc_scc_num & NUM_IS_SCC)) {
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
-
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
-
- /*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, state->count is dropped by one, so that
- * rs_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
- retval = 0;
-#ifdef DO_THIS_LATER
- add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready before block: ttys%d, count = %d\n",
- state->line, state->count);
-#endif
- local_irq_disable();
- if (!tty_hung_up_p(filp))
- state->count--;
- local_irq_enable();
- info->blocked_open++;
- while (1) {
- local_irq_disable();
- if (tty->termios->c_cflag & CBAUD)
- serial_out(info, UART_MCR,
- serial_inp(info, UART_MCR) |
- (UART_MCR_DTR | UART_MCR_RTS));
- local_irq_enable();
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) ||
- !(info->flags & ASYNC_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
- if (info->flags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
-#else
- retval = -EAGAIN;
-#endif
- break;
- }
- if (!(info->flags & ASYNC_CLOSING) &&
- (do_clocal || (serial_in(info, UART_MSR) &
- UART_MSR_DCD)))
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready blocking: ttys%d, count = %d\n",
- info->line, state->count);
-#endif
- tty_unlock();
- schedule();
- tty_lock();
- }
- current->state = TASK_RUNNING;
- remove_wait_queue(&info->open_wait, &wait);
- if (!tty_hung_up_p(filp))
- state->count++;
- info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready after blocking: ttys%d, count = %d\n",
- info->line, state->count);
-#endif
-#endif /* DO_THIS_LATER */
- if (retval)
- return retval;
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
-}
-
-static int get_async_struct(int line, ser_info_t **ret_info)
-{
- struct serial_state *sstate;
-
- sstate = rs_table + line;
- if (sstate->info) {
- sstate->count++;
- *ret_info = (ser_info_t *)sstate->info;
- return 0;
- }
- else {
- return -ENOMEM;
- }
-}
-
-/*
- * This routine is called whenever a serial port is opened. It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain. It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int rs_360_open(struct tty_struct *tty, struct file * filp)
-{
- ser_info_t *info;
- int retval, line;
-
- line = tty->index;
- if ((line < 0) || (line >= NR_PORTS))
- return -ENODEV;
- retval = get_async_struct(line, &info);
- if (retval)
- return retval;
- if (serial_paranoia_check(info, tty->name, "rs_open"))
- return -ENODEV;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_open %s, count = %d\n", tty->name, info->state->count);
-#endif
- tty->driver_data = info;
- info->port.tty = tty;
-
- /*
- * Start up serial port
- */
- retval = startup(info);
- if (retval)
- return retval;
-
- retval = block_til_ready(tty, filp, info);
- if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_open returning after block_til_ready with %d\n",
- retval);
-#endif
- return retval;
- }
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_open %s successful...", tty->name);
-#endif
- return 0;
-}
-
-/*
- * /proc fs routines....
- */
-
-static inline int line_info(char *buf, struct serial_state *state)
-{
-#ifdef notdef
- struct async_struct *info = state->info, scr_info;
- char stat_buf[30], control, status;
-#endif
- int ret;
-
- ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
- state->line,
- (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC",
- (unsigned int)(state->port), state->irq);
-
- if (!state->port || (state->type == PORT_UNKNOWN)) {
- ret += sprintf(buf+ret, "\n");
- return ret;
- }
-
-#ifdef notdef
- /*
- * Figure out the current RS-232 lines
- */
- if (!info) {
- info = &scr_info; /* This is just for serial_{in,out} */
-
- info->magic = SERIAL_MAGIC;
- info->port = state->port;
- info->flags = state->flags;
- info->quot = 0;
- info->port.tty = NULL;
- }
- local_irq_disable();
- status = serial_in(info, UART_MSR);
- control = info ? info->MCR : serial_in(info, UART_MCR);
- local_irq_enable();
-
- stat_buf[0] = 0;
- stat_buf[1] = 0;
- if (control & UART_MCR_RTS)
- strcat(stat_buf, "|RTS");
- if (status & UART_MSR_CTS)
- strcat(stat_buf, "|CTS");
- if (control & UART_MCR_DTR)
- strcat(stat_buf, "|DTR");
- if (status & UART_MSR_DSR)
- strcat(stat_buf, "|DSR");
- if (status & UART_MSR_DCD)
- strcat(stat_buf, "|CD");
- if (status & UART_MSR_RI)
- strcat(stat_buf, "|RI");
-
- if (info->quot) {
- ret += sprintf(buf+ret, " baud:%d",
- state->baud_base / info->quot);
- }
-
- ret += sprintf(buf+ret, " tx:%d rx:%d",
- state->icount.tx, state->icount.rx);
-
- if (state->icount.frame)
- ret += sprintf(buf+ret, " fe:%d", state->icount.frame);
-
- if (state->icount.parity)
- ret += sprintf(buf+ret, " pe:%d", state->icount.parity);
-
- if (state->icount.brk)
- ret += sprintf(buf+ret, " brk:%d", state->icount.brk);
-
- if (state->icount.overrun)
- ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);
-
- /*
- * Last thing is the RS-232 status lines
- */
- ret += sprintf(buf+ret, " %s\n", stat_buf+1);
-#endif
- return ret;
-}
-
-int rs_360_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- int i, len = 0;
- off_t begin = 0;
-
- len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
- for (i = 0; i < NR_PORTS && len < 4000; i++) {
- len += line_info(page + len, &rs_table[i]);
- if (len+begin > off+count)
- goto done;
- if (len+begin < off) {
- begin += len;
- len = 0;
- }
- }
- *eof = 1;
-done:
- if (off >= len+begin)
- return 0;
- *start = page + (begin-off);
- return ((count < begin+len-off) ? count : begin+len-off);
-}
-
-/*
- * ---------------------------------------------------------------------
- * rs_init() and friends
- *
- * rs_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-/*
- * This routine prints out the appropriate serial driver version
- * number, and identifies which options were configured into this
- * driver.
- */
-static _INLINE_ void show_serial_version(void)
-{
- printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
-}
-
-
-/*
- * The serial console driver used during boot. Note that these names
- * clash with those found in "serial.c", so we currently can't support
- * the 16xxx uarts and these at the same time. I will fix this to become
- * an indirect function call from tty_io.c (or something).
- */
-
-#ifdef CONFIG_SERIAL_CONSOLE
-
-/*
- * Print a string to the serial port trying not to disturb any possible
- * real use of the port...
- */
-static void my_console_write(int idx, const char *s,
- unsigned count)
-{
- struct serial_state *ser;
- ser_info_t *info;
- unsigned i;
- QUICC_BD *bdp, *bdbase;
- volatile struct smc_uart_pram *up;
- volatile u_char *cp;
-
- ser = rs_table + idx;
-
-
- /* If the port has been initialized for general use, we have
- * to use the buffer descriptors allocated there. Otherwise,
- * we simply use the single buffer allocated.
- */
- if ((info = (ser_info_t *)ser->info) != NULL) {
- bdp = info->tx_cur;
- bdbase = info->tx_bd_base;
- }
- else {
- /* Pointer to UART in parameter ram.
- */
- /* up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; */
- up = &pquicc->pram[ser->port].scc.pothers.idma_smc.psmc.u;
-
- /* Get the address of the host memory buffer.
- */
- bdp = bdbase = (QUICC_BD *)((uint)pquicc + (uint)up->tbase);
- }
-
- /*
- * We need to gracefully shut down the transmitter, disable
- * interrupts, then send our bytes out.
- */
-
- /*
- * Now, do each character. This is not as bad as it looks
- * since this is a holding FIFO and not a transmitting FIFO.
- * We could add the complexity of filling the entire transmit
- * buffer, but we would just wait longer between accesses......
- */
- for (i = 0; i < count; i++, s++) {
- /* Wait for transmitter fifo to empty.
- * Ready indicates output is ready, and xmt is doing
- * that, not that it is ready for us to send.
- */
- while (bdp->status & BD_SC_READY);
-
- /* Send the character out.
- */
- cp = bdp->buf;
- *cp = *s;
-
- bdp->length = 1;
- bdp->status |= BD_SC_READY;
-
- if (bdp->status & BD_SC_WRAP)
- bdp = bdbase;
- else
- bdp++;
-
- /* if a LF, also do CR... */
- if (*s == 10) {
- while (bdp->status & BD_SC_READY);
- /* cp = __va(bdp->buf); */
- cp = bdp->buf;
- *cp = 13;
- bdp->length = 1;
- bdp->status |= BD_SC_READY;
-
- if (bdp->status & BD_SC_WRAP) {
- bdp = bdbase;
- }
- else {
- bdp++;
- }
- }
- }
-
- /*
- * Finally, Wait for transmitter & holding register to empty
- * and restore the IER
- */
- while (bdp->status & BD_SC_READY);
-
- if (info)
- info->tx_cur = (QUICC_BD *)bdp;
-}
-
-static void serial_console_write(struct console *c, const char *s,
- unsigned count)
-{
-#ifdef CONFIG_KGDB
- /* Try to let stub handle output. Returns true if it did. */
- if (kgdb_output_string(s, count))
- return;
-#endif
- my_console_write(c->index, s, count);
-}
-
-
-
-/*void console_print_68360(const char *p)
-{
- const char *cp = p;
- int i;
-
- for (i=0;cp[i]!=0;i++);
-
- serial_console_write (p, i);
-
- //Comment this if you want to have a strict interrupt-driven output
- //rs_fair_output();
-
- return;
-}*/
-
-
-
-
-
-
-#ifdef CONFIG_XMON
-int
-xmon_360_write(const char *s, unsigned count)
-{
- my_console_write(0, s, count);
- return(count);
-}
-#endif
-
-#ifdef CONFIG_KGDB
-void
-putDebugChar(char ch)
-{
- my_console_write(0, &ch, 1);
-}
-#endif
-
-/*
- * Receive character from the serial port. This only works well
- * before the port is initialized for real use.
- */
-static int my_console_wait_key(int idx, int xmon, char *obuf)
-{
- struct serial_state *ser;
- u_char c, *cp;
- ser_info_t *info;
- QUICC_BD *bdp;
- volatile struct smc_uart_pram *up;
- int i;
-
- ser = rs_table + idx;
-
- /* Get the address of the host memory buffer.
- * If the port has been initialized for general use, we must
- * use information from the port structure.
- */
- if ((info = (ser_info_t *)ser->info))
- bdp = info->rx_cur;
- else
- /* bdp = (QUICC_BD *)&cpmp->cp_dpmem[up->smc_rbase]; */
- bdp = (QUICC_BD *)((uint)pquicc + (uint)up->tbase);
-
- /* Pointer to UART in parameter ram.
- */
- /* up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; */
- up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u;
-
- /*
- * We need to gracefully shut down the receiver, disable
- * interrupts, then read the input.
- * XMON just wants a poll. If no character, return -1, else
- * return the character.
- */
- if (!xmon) {
- while (bdp->status & BD_SC_EMPTY);
- }
- else {
- if (bdp->status & BD_SC_EMPTY)
- return -1;
- }
-
- cp = (char *)bdp->buf;
-
- if (obuf) {
- i = c = bdp->length;
- while (i-- > 0)
- *obuf++ = *cp++;
- }
- else {
- c = *cp;
- }
- bdp->status |= BD_SC_EMPTY;
-
- if (info) {
- if (bdp->status & BD_SC_WRAP) {
- bdp = info->rx_bd_base;
- }
- else {
- bdp++;
- }
- info->rx_cur = (QUICC_BD *)bdp;
- }
-
- return((int)c);
-}
-
-static int serial_console_wait_key(struct console *co)
-{
- return(my_console_wait_key(co->index, 0, NULL));
-}
-
-#ifdef CONFIG_XMON
-int
-xmon_360_read_poll(void)
-{
- return(my_console_wait_key(0, 1, NULL));
-}
-
-int
-xmon_360_read_char(void)
-{
- return(my_console_wait_key(0, 0, NULL));
-}
-#endif
-
-#ifdef CONFIG_KGDB
-static char kgdb_buf[RX_BUF_SIZE], *kgdp;
-static int kgdb_chars;
-
-unsigned char
-getDebugChar(void)
-{
- if (kgdb_chars <= 0) {
- kgdb_chars = my_console_wait_key(0, 0, kgdb_buf);
- kgdp = kgdb_buf;
- }
- kgdb_chars--;
-
- return(*kgdp++);
-}
-
-void kgdb_interruptible(int state)
-{
-}
-void kgdb_map_scc(void)
-{
- struct serial_state *ser;
- uint mem_addr;
- volatile QUICC_BD *bdp;
- volatile smc_uart_t *up;
-
- cpmp = (cpm360_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
-
- /* To avoid data cache CPM DMA coherency problems, allocate a
- * buffer in the CPM DPRAM. This will work until the CPM and
- * serial ports are initialized. At that time a memory buffer
- * will be allocated.
- * The port is already initialized from the boot procedure, all
- * we do here is give it a different buffer and make it a FIFO.
- */
-
- ser = rs_table;
-
- /* Right now, assume we are using SMCs.
- */
- up = (smc_uart_t *)&cpmp->cp_dparam[ser->port];
-
- /* Allocate space for an input FIFO, plus a few bytes for output.
- * Allocate bytes to maintain word alignment.
- */
- mem_addr = (uint)(&cpmp->cp_dpmem[0x1000]);
-
- /* Set the physical address of the host memory buffers in
- * the buffer descriptors.
- */
- bdp = (QUICC_BD *)&cpmp->cp_dpmem[up->smc_rbase];
- bdp->buf = mem_addr;
-
- bdp = (QUICC_BD *)&cpmp->cp_dpmem[up->smc_tbase];
- bdp->buf = mem_addr+RX_BUF_SIZE;
-
- up->smc_mrblr = RX_BUF_SIZE; /* receive buffer length */
- up->smc_maxidl = RX_BUF_SIZE;
-}
-#endif
-
-static struct tty_struct *serial_console_device(struct console *c, int *index)
-{
- *index = c->index;
- return serial_driver;
-}
-
-
-struct console sercons = {
- .name = "ttyS",
- .write = serial_console_write,
- .device = serial_console_device,
- .wait_key = serial_console_wait_key,
- .setup = serial_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = CONFIG_SERIAL_CONSOLE_PORT,
-};
-
-
-
-/*
- * Register console.
- */
-long console_360_init(long kmem_start, long kmem_end)
-{
- register_console(&sercons);
- /*register_console (console_print_68360); - 2.0.38 only required a write
- function pointer. */
- return kmem_start;
-}
-
-#endif
-
-/* Index in baud rate table of the default console baud rate.
-*/
-static int baud_idx;
-
-static const struct tty_operations rs_360_ops = {
- .owner = THIS_MODULE,
- .open = rs_360_open,
- .close = rs_360_close,
- .write = rs_360_write,
- .put_char = rs_360_put_char,
- .write_room = rs_360_write_room,
- .chars_in_buffer = rs_360_chars_in_buffer,
- .flush_buffer = rs_360_flush_buffer,
- .ioctl = rs_360_ioctl,
- .throttle = rs_360_throttle,
- .unthrottle = rs_360_unthrottle,
- /* .send_xchar = rs_360_send_xchar, */
- .set_termios = rs_360_set_termios,
- .stop = rs_360_stop,
- .start = rs_360_start,
- .hangup = rs_360_hangup,
- /* .wait_until_sent = rs_360_wait_until_sent, */
- /* .read_proc = rs_360_read_proc, */
- .tiocmget = rs_360_tiocmget,
- .tiocmset = rs_360_tiocmset,
- .get_icount = rs_360_get_icount,
-};
-
-static int __init rs_360_init(void)
-{
- struct serial_state * state;
- ser_info_t *info;
- void *mem_addr;
- uint dp_addr, iobits;
- int i, j, idx;
- ushort chan;
- QUICC_BD *bdp;
- volatile QUICC *cp;
- volatile struct smc_regs *sp;
- volatile struct smc_uart_pram *up;
- volatile struct scc_regs *scp;
- volatile struct uart_pram *sup;
- /* volatile immap_t *immap; */
-
- serial_driver = alloc_tty_driver(NR_PORTS);
- if (!serial_driver)
- return -1;
-
- show_serial_version();
-
- serial_driver->name = "ttyS";
- serial_driver->major = TTY_MAJOR;
- serial_driver->minor_start = 64;
- serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
- serial_driver->subtype = SERIAL_TYPE_NORMAL;
- serial_driver->init_termios = tty_std_termios;
- serial_driver->init_termios.c_cflag =
- baud_idx | CS8 | CREAD | HUPCL | CLOCAL;
- serial_driver->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(serial_driver, &rs_360_ops);
-
- if (tty_register_driver(serial_driver))
- panic("Couldn't register serial driver\n");
-
- cp = pquicc; /* Get pointer to Communication Processor */
- /* immap = (immap_t *)IMAP_ADDR; */ /* and to internal registers */
-
-
- /* Configure SCC2, SCC3, and SCC4 instead of port A parallel I/O.
- */
- /* The "standard" configuration through the 860.
- */
-/* immap->im_ioport.iop_papar |= 0x00fc; */
-/* immap->im_ioport.iop_padir &= ~0x00fc; */
-/* immap->im_ioport.iop_paodr &= ~0x00fc; */
- cp->pio_papar |= 0x00fc;
- cp->pio_padir &= ~0x00fc;
- /* cp->pio_paodr &= ~0x00fc; */
-
-
- /* Since we don't yet do modem control, connect the port C pins
- * as general purpose I/O. This will assert CTS and CD for the
- * SCC ports.
- */
- /* FIXME: see 360um p.7-365 and 860um p.34-12
- * I can't make sense of these bits - mleslie*/
-/* immap->im_ioport.iop_pcdir |= 0x03c6; */
-/* immap->im_ioport.iop_pcpar &= ~0x03c6; */
-
-/* cp->pio_pcdir |= 0x03c6; */
-/* cp->pio_pcpar &= ~0x03c6; */
-
-
-
- /* Connect SCC2 and SCC3 to NMSI. Connect BRG3 to SCC2 and
- * BRG4 to SCC3.
- */
- cp->si_sicr &= ~0x00ffff00;
- cp->si_sicr |= 0x001b1200;
-
-#ifdef CONFIG_PP04
- /* Frequentis PP04 forced to RS-232 until we know better.
- * Port C 12 and 13 low enables RS-232 on SCC3 and SCC4.
- */
- immap->im_ioport.iop_pcdir |= 0x000c;
- immap->im_ioport.iop_pcpar &= ~0x000c;
- immap->im_ioport.iop_pcdat &= ~0x000c;
-
- /* This enables the TX driver.
- */
- cp->cp_pbpar &= ~0x6000;
- cp->cp_pbdat &= ~0x6000;
-#endif
-
- for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
- state->magic = SSTATE_MAGIC;
- state->line = i;
- state->type = PORT_UNKNOWN;
- state->custom_divisor = 0;
- state->close_delay = 5*HZ/10;
- state->closing_wait = 30*HZ;
- state->icount.cts = state->icount.dsr =
- state->icount.rng = state->icount.dcd = 0;
- state->icount.rx = state->icount.tx = 0;
- state->icount.frame = state->icount.parity = 0;
- state->icount.overrun = state->icount.brk = 0;
- printk(KERN_INFO "ttyS%d at irq 0x%02x is an %s\n",
- i, (unsigned int)(state->irq),
- (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC");
-
-#ifdef CONFIG_SERIAL_CONSOLE
- /* If we just printed the message on the console port, and
- * we are about to initialize it for general use, we have
- * to wait a couple of character times for the CR/NL to
- * make it out of the transmit buffer.
- */
- if (i == CONFIG_SERIAL_CONSOLE_PORT)
- mdelay(8);
-
-
-/* idx = PORT_NUM(info->state->smc_scc_num); */
-/* if (info->state->smc_scc_num & NUM_IS_SCC) */
-/* chan = scc_chan_map[idx]; */
-/* else */
-/* chan = smc_chan_map[idx]; */
-
-/* cp->cp_cr = mk_cr_cmd(chan, CPM_CR_STOP_TX) | CPM_CR_FLG; */
-/* while (cp->cp_cr & CPM_CR_FLG); */
-
-#endif
- /* info = kmalloc(sizeof(ser_info_t), GFP_KERNEL); */
- info = &quicc_ser_info[i];
- if (info) {
- memset (info, 0, sizeof(ser_info_t));
- info->magic = SERIAL_MAGIC;
- info->line = i;
- info->flags = state->flags;
- INIT_WORK(&info->tqueue, do_softint, info);
- INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info);
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
- info->state = state;
- state->info = (struct async_struct *)info;
-
- /* We need to allocate a transmit and receive buffer
- * descriptors from dual port ram, and a character
- * buffer area from host mem.
- */
- dp_addr = m360_cpm_dpalloc(sizeof(QUICC_BD) * RX_NUM_FIFO);
-
- /* Allocate space for FIFOs in the host memory.
- * (for now this is from a static array of buffers :(
- */
- /* mem_addr = m360_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE); */
- /* mem_addr = kmalloc (RX_NUM_FIFO * RX_BUF_SIZE, GFP_BUFFER); */
- mem_addr = &rx_buf_pool[i * RX_NUM_FIFO * RX_BUF_SIZE];
-
- /* Set the physical address of the host memory
- * buffers in the buffer descriptors, and the
- * virtual address for us to work with.
- */
- bdp = (QUICC_BD *)((uint)pquicc + dp_addr);
- info->rx_cur = info->rx_bd_base = bdp;
-
- /* initialize rx buffer descriptors */
- for (j=0; j<(RX_NUM_FIFO-1); j++) {
- bdp->buf = &rx_buf_pool[(i * RX_NUM_FIFO + j ) * RX_BUF_SIZE];
- bdp->status = BD_SC_EMPTY | BD_SC_INTRPT;
- mem_addr += RX_BUF_SIZE;
- bdp++;
- }
- bdp->buf = &rx_buf_pool[(i * RX_NUM_FIFO + j ) * RX_BUF_SIZE];
- bdp->status = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
-
-
- idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
-
-#if defined (CONFIG_UCQUICC) && 1
- /* set the transceiver mode to RS232 */
- sipex_mode_bits &= ~(uint)SIPEX_MODE(idx,0x0f); /* clear current mode */
- sipex_mode_bits |= (uint)SIPEX_MODE(idx,0x02);
- *(uint *)_periph_base = sipex_mode_bits;
- /* printk ("sipex bits = 0x%08x\n", sipex_mode_bits); */
-#endif
- }
-
- dp_addr = m360_cpm_dpalloc(sizeof(QUICC_BD) * TX_NUM_FIFO);
-
- /* Allocate space for FIFOs in the host memory.
- */
- /* mem_addr = m360_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE); */
- /* mem_addr = kmalloc (TX_NUM_FIFO * TX_BUF_SIZE, GFP_BUFFER); */
- mem_addr = &tx_buf_pool[i * TX_NUM_FIFO * TX_BUF_SIZE];
-
- /* Set the physical address of the host memory
- * buffers in the buffer descriptors, and the
- * virtual address for us to work with.
- */
- /* bdp = (QUICC_BD *)&cp->cp_dpmem[dp_addr]; */
- bdp = (QUICC_BD *)((uint)pquicc + dp_addr);
- info->tx_cur = info->tx_bd_base = (QUICC_BD *)bdp;
-
- /* initialize tx buffer descriptors */
- for (j=0; j<(TX_NUM_FIFO-1); j++) {
- bdp->buf = &tx_buf_pool[(i * TX_NUM_FIFO + j ) * TX_BUF_SIZE];
- bdp->status = BD_SC_INTRPT;
- mem_addr += TX_BUF_SIZE;
- bdp++;
- }
- bdp->buf = &tx_buf_pool[(i * TX_NUM_FIFO + j ) * TX_BUF_SIZE];
- bdp->status = (BD_SC_WRAP | BD_SC_INTRPT);
-
- if (info->state->smc_scc_num & NUM_IS_SCC) {
- scp = &pquicc->scc_regs[idx];
- sup = &pquicc->pram[info->state->port].scc.pscc.u;
- sup->rbase = dp_addr;
- sup->tbase = dp_addr;
-
- /* Set up the uart parameters in the
- * parameter ram.
- */
- sup->rfcr = SMC_EB;
- sup->tfcr = SMC_EB;
-
- /* Set this to 1 for now, so we get single
- * character interrupts. Using idle character
- * time requires some additional tuning.
- */
- sup->mrblr = 1;
- sup->max_idl = 0;
- sup->brkcr = 1;
- sup->parec = 0;
- sup->frmer = 0;
- sup->nosec = 0;
- sup->brkec = 0;
- sup->uaddr1 = 0;
- sup->uaddr2 = 0;
- sup->toseq = 0;
- {
- int i;
- for (i=0;i<8;i++)
- sup->cc[i] = 0x8000;
- }
- sup->rccm = 0xc0ff;
-
- /* Send the CPM an initialize command.
- */
- chan = scc_chan_map[idx];
-
- /* execute the INIT RX & TX PARAMS command for this channel. */
- cp->cp_cr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG;
- while (cp->cp_cr & CPM_CR_FLG);
-
- /* Set UART mode, 8 bit, no parity, one stop.
- * Enable receive and transmit.
- */
- scp->scc_gsmr.w.high = 0;
- scp->scc_gsmr.w.low =
- (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
-
- /* Disable all interrupts and clear all pending
- * events.
- */
- scp->scc_sccm = 0;
- scp->scc_scce = 0xffff;
- scp->scc_dsr = 0x7e7e;
- scp->scc_psmr = 0x3000;
-
- /* If the port is the console, enable Rx and Tx.
- */
-#ifdef CONFIG_SERIAL_CONSOLE
- if (i == CONFIG_SERIAL_CONSOLE_PORT)
- scp->scc_gsmr.w.low |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-#endif
- }
- else {
- /* Configure SMCs Tx/Rx instead of port B
- * parallel I/O.
- */
- up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u;
- up->rbase = dp_addr;
-
- iobits = 0xc0 << (idx * 4);
- cp->pip_pbpar |= iobits;
- cp->pip_pbdir &= ~iobits;
- cp->pip_pbodr &= ~iobits;
-
-
- /* Connect the baud rate generator to the
- * SMC based upon index in rs_table. Also
- * make sure it is connected to NMSI.
- */
- cp->si_simode &= ~(0xffff << (idx * 16));
- cp->si_simode |= (i << ((idx * 16) + 12));
-
- up->tbase = dp_addr;
-
- /* Set up the uart parameters in the
- * parameter ram.
- */
- up->rfcr = SMC_EB;
- up->tfcr = SMC_EB;
-
- /* Set this to 1 for now, so we get single
- * character interrupts. Using idle character
- * time requires some additional tuning.
- */
- up->mrblr = 1;
- up->max_idl = 0;
- up->brkcr = 1;
-
- /* Send the CPM an initialize command.
- */
- chan = smc_chan_map[idx];
-
- cp->cp_cr = mk_cr_cmd(chan,
- CPM_CR_INIT_TRX) | CPM_CR_FLG;
-#ifdef CONFIG_SERIAL_CONSOLE
- if (i == CONFIG_SERIAL_CONSOLE_PORT)
- printk("");
-#endif
- while (cp->cp_cr & CPM_CR_FLG);
-
- /* Set UART mode, 8 bit, no parity, one stop.
- * Enable receive and transmit.
- */
- sp = &cp->smc_regs[idx];
- sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
-
- /* Disable all interrupts and clear all pending
- * events.
- */
- sp->smc_smcm = 0;
- sp->smc_smce = 0xff;
-
- /* If the port is the console, enable Rx and Tx.
- */
-#ifdef CONFIG_SERIAL_CONSOLE
- if (i == CONFIG_SERIAL_CONSOLE_PORT)
- sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
-#endif
- }
-
- /* Install interrupt handler.
- */
- /* cpm_install_handler(IRQ_MACHSPEC | state->irq, rs_360_interrupt, info); */
- /*request_irq(IRQ_MACHSPEC | state->irq, rs_360_interrupt, */
- request_irq(state->irq, rs_360_interrupt, 0, "ttyS",
- (void *)info);
-
- /* Set up the baud rate generator.
- */
- m360_cpm_setbrg(i, baud_table[baud_idx]);
-
- }
- }
-
- return 0;
-}
-module_init(rs_360_init);
-
-/* This must always be called before the rs_360_init() function, otherwise
- * it blows away the port control information.
- */
-//static int __init serial_console_setup( struct console *co, char *options)
-int serial_console_setup( struct console *co, char *options)
-{
- struct serial_state *ser;
- uint mem_addr, dp_addr, bidx, idx, iobits;
- ushort chan;
- QUICC_BD *bdp;
- volatile QUICC *cp;
- volatile struct smc_regs *sp;
- volatile struct scc_regs *scp;
- volatile struct smc_uart_pram *up;
- volatile struct uart_pram *sup;
-
-/* mleslie TODO:
- * add something to the 68k bootloader to store a desired initial console baud rate */
-
-/* bd_t *bd; */ /* a board info struct used by EPPC-bug */
-/* bd = (bd_t *)__res; */
-
- for (bidx = 0; bidx < (sizeof(baud_table) / sizeof(int)); bidx++)
- /* if (bd->bi_baudrate == baud_table[bidx]) */
- if (CONSOLE_BAUDRATE == baud_table[bidx])
- break;
-
- /* co->cflag = CREAD|CLOCAL|bidx|CS8; */
- baud_idx = bidx;
-
- ser = rs_table + CONFIG_SERIAL_CONSOLE_PORT;
-
- cp = pquicc; /* Get pointer to Communication Processor */
-
- idx = PORT_NUM(ser->smc_scc_num);
- if (ser->smc_scc_num & NUM_IS_SCC) {
-
- /* TODO: need to set up SCC pin assignment etc. here */
-
- }
- else {
- iobits = 0xc0 << (idx * 4);
- cp->pip_pbpar |= iobits;
- cp->pip_pbdir &= ~iobits;
- cp->pip_pbodr &= ~iobits;
-
- /* Connect the baud rate generator to the
- * SMC based upon index in rs_table. Also
- * make sure it is connected to NMSI.
- */
- cp->si_simode &= ~(0xffff << (idx * 16));
- cp->si_simode |= (idx << ((idx * 16) + 12));
- }
-
- /* When we get here, the CPM has been reset, so we need
- * to configure the port.
- * We need to allocate a transmit and receive buffer descriptor
- * from dual port ram, and a character buffer area from host mem.
- */
-
- /* Allocate space for two buffer descriptors in the DP ram.
- */
- dp_addr = m360_cpm_dpalloc(sizeof(QUICC_BD) * CONSOLE_NUM_FIFO);
-
- /* Allocate space for two 2 byte FIFOs in the host memory.
- */
- /* mem_addr = m360_cpm_hostalloc(8); */
- mem_addr = (uint)console_fifos;
-
-
- /* Set the physical address of the host memory buffers in
- * the buffer descriptors.
- */
- /* bdp = (QUICC_BD *)&cp->cp_dpmem[dp_addr]; */
- bdp = (QUICC_BD *)((uint)pquicc + dp_addr);
- bdp->buf = (char *)mem_addr;
- (bdp+1)->buf = (char *)(mem_addr+4);
-
- /* For the receive, set empty and wrap.
- * For transmit, set wrap.
- */
- bdp->status = BD_SC_EMPTY | BD_SC_WRAP;
- (bdp+1)->status = BD_SC_WRAP;
-
- /* Set up the uart parameters in the parameter ram.
- */
- if (ser->smc_scc_num & NUM_IS_SCC) {
- scp = &cp->scc_regs[idx];
- /* sup = (scc_uart_t *)&cp->cp_dparam[ser->port]; */
- sup = &pquicc->pram[ser->port].scc.pscc.u;
-
- sup->rbase = dp_addr;
- sup->tbase = dp_addr + sizeof(QUICC_BD);
-
- /* Set up the uart parameters in the
- * parameter ram.
- */
- sup->rfcr = SMC_EB;
- sup->tfcr = SMC_EB;
-
- /* Set this to 1 for now, so we get single
- * character interrupts. Using idle character
- * time requires some additional tuning.
- */
- sup->mrblr = 1;
- sup->max_idl = 0;
- sup->brkcr = 1;
- sup->parec = 0;
- sup->frmer = 0;
- sup->nosec = 0;
- sup->brkec = 0;
- sup->uaddr1 = 0;
- sup->uaddr2 = 0;
- sup->toseq = 0;
- {
- int i;
- for (i=0;i<8;i++)
- sup->cc[i] = 0x8000;
- }
- sup->rccm = 0xc0ff;
-
- /* Send the CPM an initialize command.
- */
- chan = scc_chan_map[idx];
-
- cp->cp_cr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG;
- while (cp->cp_cr & CPM_CR_FLG);
-
- /* Set UART mode, 8 bit, no parity, one stop.
- * Enable receive and transmit.
- */
- scp->scc_gsmr.w.high = 0;
- scp->scc_gsmr.w.low =
- (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
-
- /* Disable all interrupts and clear all pending
- * events.
- */
- scp->scc_sccm = 0;
- scp->scc_scce = 0xffff;
- scp->scc_dsr = 0x7e7e;
- scp->scc_psmr = 0x3000;
-
- scp->scc_gsmr.w.low |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-
- }
- else {
- /* up = (smc_uart_t *)&cp->cp_dparam[ser->port]; */
- up = &pquicc->pram[ser->port].scc.pothers.idma_smc.psmc.u;
-
- up->rbase = dp_addr; /* Base of receive buffer desc. */
- up->tbase = dp_addr+sizeof(QUICC_BD); /* Base of xmt buffer desc. */
- up->rfcr = SMC_EB;
- up->tfcr = SMC_EB;
-
- /* Set this to 1 for now, so we get single character interrupts.
- */
- up->mrblr = 1; /* receive buffer length */
- up->max_idl = 0; /* wait forever for next char */
-
- /* Send the CPM an initialize command.
- */
- chan = smc_chan_map[idx];
- cp->cp_cr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG;
- while (cp->cp_cr & CPM_CR_FLG);
-
- /* Set UART mode, 8 bit, no parity, one stop.
- * Enable receive and transmit.
- */
- sp = &cp->smc_regs[idx];
- sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
-
- /* And finally, enable Rx and Tx.
- */
- sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
- }
-
- /* Set up the baud rate generator.
- */
- /* m360_cpm_setbrg((ser - rs_table), bd->bi_baudrate); */
- m360_cpm_setbrg((ser - rs_table), CONSOLE_BAUDRATE);
-
- return 0;
-}
-
-/*
- * Local variables:
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/drivers/staging/serial/Kconfig b/drivers/staging/serial/Kconfig
deleted file mode 100644
index 9489688397e0..000000000000
--- a/drivers/staging/serial/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-config SERIAL_68360_SMC
- bool "68360 SMC uart support"
- depends on M68360
- help
- This driver supports the SMC serial ports of the Motorola 68360 CPU.
-
-config SERIAL_68360_SCC
- bool "68360 SCC uart support"
- depends on M68360
- help
- This driver supports the SCC serial ports of the Motorola 68360 CPU.
-
-config SERIAL_68360
- bool
- depends on SERIAL_68360_SMC || SERIAL_68360_SCC
- default y
diff --git a/drivers/staging/serial/Makefile b/drivers/staging/serial/Makefile
deleted file mode 100644
index 37a6a0b35fba..000000000000
--- a/drivers/staging/serial/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_SERIAL_68360) += 68360serial.o
diff --git a/drivers/staging/serial/TODO b/drivers/staging/serial/TODO
deleted file mode 100644
index a19cda81dab4..000000000000
--- a/drivers/staging/serial/TODO
+++ /dev/null
@@ -1,6 +0,0 @@
-These are a few serial drivers that either do not build, or do not work if they
-do build, or if they seem to work, are for obsolete hardware, or are full of
-unfixable races and no one uses them anymore.
-
-If no one steps up to adopt any of these drivers, they will be removed
-in the 3.4 release.
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
index ae1d815e2a53..43045db982d4 100644
--- a/drivers/staging/serqt_usb2/serqt_usb2.c
+++ b/drivers/staging/serqt_usb2/serqt_usb2.c
@@ -41,13 +41,6 @@ static bool debug;
#define QUATECH_HSU200B 0xC0B1 /* HSU200B */
#define QUATECH_HSU200C 0xC0B2 /* HSU200C */
#define QUATECH_HSU200D 0xC0B3 /* HSU200D */
-#define QUATECH_SSU100_2 0xC120 /* SSU100_2 */
-#define QUATECH_DSU100_2 0xC140 /* DSU100_2 */
-#define QUATECH_DSU400_2 0xC150 /* DSU400_2 */
-#define QUATECH_QSU100_2 0xC160 /* QSU100_2 */
-#define QUATECH_QSU400_2 0xC170 /* QSU400_2 */
-#define QUATECH_ESU400_2 0xC180 /* ESU400_2 */
-#define QUATECH_ESU100_2 0xC1A0 /* ESU100_2 */
#define QT_SET_GET_DEVICE 0xc2
#define QT_OPEN_CLOSE_CHANNEL 0xca
@@ -125,7 +118,7 @@ static bool debug;
#define MODEM_CTRL 0x40
#define RS232_MODE 0x00
-static const struct usb_device_id serqt_id_table[] = {
+static const struct usb_device_id id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU200)},
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100)},
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU200)},
@@ -143,17 +136,9 @@ static const struct usb_device_id serqt_id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200B)},
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200C)},
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200D)},
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100_2)},
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100_2)},
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU400_2)},
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU100_2)},
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU400_2)},
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU400_2)},
- {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100_2)},
{} /* Terminating entry */
};
-
-MODULE_DEVICE_TABLE(usb, serqt_id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
struct qt_get_device_data {
__u8 porta;
@@ -195,13 +180,6 @@ struct quatech_port {
char closePending;
};
-static struct usb_driver serqt_usb_driver = {
- .name = "quatech-usb-serial",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = serqt_id_table,
-};
-
static int port_paranoia_check(struct usb_serial_port *port,
const char *function)
{
@@ -304,8 +282,6 @@ static void qt_write_bulk_callback(struct urb *urb)
quatech_port = urb->context;
- dbg("%s - port %d\n", __func__, quatech_port->port_num);
-
tty = tty_port_tty_get(&quatech_port->port->port);
if (tty)
@@ -351,7 +327,6 @@ static void qt_read_bulk_callback(struct urb *urb)
/* index = MINOR(port->tty->device) - serial->minor; */
index = tty->index - serial->minor;
- dbg("%s - port %d\n", __func__, port->number);
dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding);
if (port_paranoia_check(port, __func__) != 0) {
@@ -726,8 +701,6 @@ static int qt_startup(struct usb_serial *serial)
int i;
int status;
- dbg("enterting %s", __func__);
-
/* Now setup per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
@@ -855,8 +828,6 @@ static void qt_release(struct usb_serial *serial)
struct quatech_port *qt_port;
int i;
- dbg("enterting %s", __func__);
-
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
if (!port)
@@ -882,8 +853,6 @@ static int qt_open(struct tty_struct *tty,
if (port_paranoia_check(port, __func__))
return -ENODEV;
- dbg("%s - port %d\n", __func__, port->number);
-
serial = port->serial;
if (serial_paranoia_check(serial, __func__))
@@ -1006,8 +975,6 @@ static int qt_chars_in_buffer(struct tty_struct *tty)
serial = get_usb_serial(port, __func__);
- dbg("%s - port %d\n", __func__, port->number);
-
if (serial->num_bulk_out) {
if (port->write_urb->status == -EINPROGRESS)
chars = port->write_urb->transfer_buffer_length;
@@ -1054,8 +1021,6 @@ static void qt_close(struct usb_serial_port *port)
unsigned int index;
status = 0;
- dbg("%s - port %d\n", __func__, port->number);
-
tty = tty_port_tty_get(&port->port);
index = tty->index - serial->minor;
@@ -1109,8 +1074,6 @@ static int qt_write(struct tty_struct *tty, struct usb_serial_port *port,
if (serial == NULL)
return -ENODEV;
- dbg("%s - port %d\n", __func__, port->number);
-
if (count == 0) {
dbg("%s - write request of 0 bytes\n", __func__);
return 0;
@@ -1173,8 +1136,6 @@ static int qt_write_room(struct tty_struct *tty)
mutex_lock(&qt_port->lock);
- dbg("%s - port %d\n", __func__, port->number);
-
if (serial->num_bulk_out) {
if (port->write_urb->status != -EINPROGRESS)
retval = port->bulk_out_size;
@@ -1241,8 +1202,6 @@ static void qt_set_termios(struct tty_struct *tty,
int baud, divisor, remainder;
int status;
- dbg("%s", __func__);
-
index = tty->index - port->serial->minor;
switch (cflag) {
@@ -1365,8 +1324,6 @@ static void qt_break(struct tty_struct *tty, int break_state)
mutex_lock(&qt_port->lock);
- dbg("%s - port %d\n", __func__, port->number);
-
result =
usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
QT_BREAK_CONTROL, 0x40, onoff, index, NULL, 0, 300);
@@ -1385,8 +1342,6 @@ static inline int qt_real_tiocmget(struct tty_struct *tty,
int status;
unsigned int index;
- dbg("%s - port %d, tty =0x%p\n", __func__, port->number, tty);
-
index = tty->index - serial->minor;
status =
BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr);
@@ -1426,8 +1381,6 @@ static inline int qt_real_tiocmset(struct tty_struct *tty,
int status;
unsigned int index;
- dbg("%s - port %d\n", __func__, port->number);
-
index = tty->index - serial->minor;
status =
BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr);
@@ -1461,18 +1414,11 @@ static int qt_tiocmget(struct tty_struct *tty)
struct quatech_port *qt_port = qt_get_port_private(port);
int retval = -ENODEV;
- dbg("In %s\n", __func__);
-
if (!serial)
return -ENODEV;
mutex_lock(&qt_port->lock);
-
- dbg("%s - port %d\n", __func__, port->number);
- dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding);
-
retval = qt_real_tiocmget(tty, port, serial);
-
mutex_unlock(&qt_port->lock);
return retval;
}
@@ -1486,18 +1432,11 @@ static int qt_tiocmset(struct tty_struct *tty,
struct quatech_port *qt_port = qt_get_port_private(port);
int retval = -ENODEV;
- dbg("In %s\n", __func__);
-
if (!serial)
return -ENODEV;
mutex_lock(&qt_port->lock);
-
- dbg("%s - port %d\n", __func__, port->number);
- dbg("%s - qt_port->RxHolding = %d\n", __func__, qt_port->RxHolding);
-
retval = qt_real_tiocmset(tty, port, serial, set);
-
mutex_unlock(&qt_port->lock);
return retval;
}
@@ -1508,8 +1447,6 @@ static void qt_throttle(struct tty_struct *tty)
struct usb_serial *serial = get_usb_serial(port, __func__);
struct quatech_port *qt_port;
- dbg("%s - port %d\n", __func__, port->number);
-
if (!serial)
return;
@@ -1519,7 +1456,6 @@ static void qt_throttle(struct tty_struct *tty)
/* pass on to the driver specific version of this function */
qt_port->RxHolding = 1;
- dbg("%s - port->RxHolding = 1\n", __func__);
mutex_unlock(&qt_port->lock);
return;
@@ -1539,8 +1475,6 @@ static void qt_unthrottle(struct tty_struct *tty)
mutex_lock(&qt_port->lock);
- dbg("%s - port %d\n", __func__, port->number);
-
if (qt_port->RxHolding == 1) {
dbg("%s -qt_port->RxHolding == 1\n", __func__);
@@ -1559,8 +1493,9 @@ static void qt_unthrottle(struct tty_struct *tty)
qt_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed restarting read urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed restarting read urb, error %d\n",
+ __func__, result);
}
}
mutex_unlock(&qt_port->lock);
@@ -1589,7 +1524,7 @@ static struct usb_serial_driver quatech_device = {
.name = "serqt",
},
.description = DRIVER_DESC,
- .id_table = serqt_id_table,
+ .id_table = id_table,
.num_ports = 8,
.open = qt_open,
.close = qt_close,
@@ -1612,7 +1547,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&quatech_device, NULL
};
-module_usb_serial_driver(serqt_usb_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/staging/sm7xx/smtcfb.c b/drivers/staging/sm7xx/smtcfb.c
index 83c582ed12e5..746c4cd5d30e 100644
--- a/drivers/staging/sm7xx/smtcfb.c
+++ b/drivers/staging/sm7xx/smtcfb.c
@@ -2,31 +2,19 @@
* Silicon Motion SM7XX frame buffer device
*
* Copyright (C) 2006 Silicon Motion Technology Corp.
- * Authors: Ge Wang, gewang@siliconmotion.com
- * Boyod boyod.yang@siliconmotion.com.cn
+ * Authors: Ge Wang, gewang@siliconmotion.com
+ * Boyod boyod.yang@siliconmotion.com.cn
*
* Copyright (C) 2009 Lemote, Inc.
- * Author: Wu Zhangjin, wuzhangjin@gmail.com
+ * Author: Wu Zhangjin, wuzhangjin@gmail.com
*
* Copyright (C) 2011 Igalia, S.L.
- * Author: Javier M. Mellid <jmunhoz@igalia.com>
+ * Author: Javier M. Mellid <jmunhoz@igalia.com>
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
*
- * Version 0.10.26192.21.01
- * - Add PowerPC/Big endian support
- * - Verified on 2.6.19.2
- * Boyod.yang <boyod.yang@siliconmotion.com.cn>
- *
- * Version 0.09.2621.00.01
- * - Only support Linux Kernel's version 2.6.21
- * Boyod.yang <boyod.yang@siliconmotion.com.cn>
- *
- * Version 0.09
- * - Only support Linux Kernel's version 2.6.12
- * Boyod.yang <boyod.yang@siliconmotion.com.cn>
*/
#include <linux/io.h>
@@ -45,40 +33,19 @@
#include "smtcfb.h"
-#ifdef DEBUG
-#define smdbg(format, arg...) printk(KERN_DEBUG format , ## arg)
-#else
-#define smdbg(format, arg...)
-#endif
-
struct screen_info smtc_screen_info;
/*
* Private structure
*/
struct smtcfb_info {
- /*
- * The following is a pointer to be passed into the
- * functions below. The modules outside the main
- * voyager.c driver have no knowledge as to what
- * is within this structure.
- */
struct fb_info fb;
- struct display_switch *dispsw;
- struct pci_dev *dev;
- signed int currcon;
-
+ struct pci_dev *pdev;
struct {
u8 red, green, blue;
} palette[NR_RGB];
-
u_int palette_size;
-};
-struct par_info {
- /*
- * Hardware
- */
u16 chipID;
unsigned char __iomem *m_pMMIO;
char __iomem *m_pLFB;
@@ -121,15 +88,6 @@ char __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */
char __iomem *smtc_VRAMBaseAddress; /* video memory starting address */
static u32 colreg[17];
-static struct par_info hw; /* hardware information */
-
-u16 smtc_ChipIDs[] = {
- 0x710,
- 0x712,
- 0x720
-};
-
-#define numSMTCchipIDs ARRAY_SIZE(smtc_ChipIDs)
static struct fb_var_screeninfo smtcfb_var = {
.xres = 1024,
@@ -154,30 +112,29 @@ static struct fb_fix_screeninfo smtcfb_fix = {
.accel = FB_ACCEL_SMI_LYNX,
};
-static void sm712_set_timing(struct smtcfb_info *sfb,
- struct par_info *ppar_info)
+static void sm712_set_timing(struct smtcfb_info *sfb)
{
int i = 0, j = 0;
u32 m_nScreenStride;
- smdbg("\nppar_info->width = %d ppar_info->height = %d"
- "sfb->fb.var.bits_per_pixel = %d ppar_info->hz = %d\n",
- ppar_info->width, ppar_info->height,
- sfb->fb.var.bits_per_pixel, ppar_info->hz);
+ dev_dbg(&sfb->pdev->dev,
+ "sfb->width=%d sfb->height=%d "
+ "sfb->fb.var.bits_per_pixel=%d sfb->hz=%d\n",
+ sfb->width, sfb->height, sfb->fb.var.bits_per_pixel, sfb->hz);
for (j = 0; j < numVGAModes; j++) {
- if (VGAMode[j].mmSizeX == ppar_info->width &&
- VGAMode[j].mmSizeY == ppar_info->height &&
+ if (VGAMode[j].mmSizeX == sfb->width &&
+ VGAMode[j].mmSizeY == sfb->height &&
VGAMode[j].bpp == sfb->fb.var.bits_per_pixel &&
- VGAMode[j].hz == ppar_info->hz) {
+ VGAMode[j].hz == sfb->hz) {
- smdbg("\nVGAMode[j].mmSizeX = %d VGAMode[j].mmSizeY ="
- "%d VGAMode[j].bpp = %d"
- "VGAMode[j].hz=%d\n",
- VGAMode[j].mmSizeX, VGAMode[j].mmSizeY,
- VGAMode[j].bpp, VGAMode[j].hz);
+ dev_dbg(&sfb->pdev->dev,
+ "VGAMode[j].mmSizeX=%d VGAMode[j].mmSizeY=%d "
+ "VGAMode[j].bpp=%d VGAMode[j].hz=%d\n",
+ VGAMode[j].mmSizeX, VGAMode[j].mmSizeY,
+ VGAMode[j].bpp, VGAMode[j].hz);
- smdbg("VGAMode index=%d\n", j);
+ dev_dbg(&sfb->pdev->dev, "VGAMode index=%d\n", j);
smtc_mmiowb(0x0, 0x3c6);
@@ -238,37 +195,37 @@ static void sm712_set_timing(struct smtcfb_info *sfb,
smtc_mmiowb(0x67, 0x3c2);
/* set VPR registers */
- writel(0x0, ppar_info->m_pVPR + 0x0C);
- writel(0x0, ppar_info->m_pVPR + 0x40);
+ writel(0x0, sfb->m_pVPR + 0x0C);
+ writel(0x0, sfb->m_pVPR + 0x40);
/* set data width */
m_nScreenStride =
- (ppar_info->width * sfb->fb.var.bits_per_pixel) / 64;
+ (sfb->width * sfb->fb.var.bits_per_pixel) / 64;
switch (sfb->fb.var.bits_per_pixel) {
case 8:
- writel(0x0, ppar_info->m_pVPR + 0x0);
+ writel(0x0, sfb->m_pVPR + 0x0);
break;
case 16:
- writel(0x00020000, ppar_info->m_pVPR + 0x0);
+ writel(0x00020000, sfb->m_pVPR + 0x0);
break;
case 24:
- writel(0x00040000, ppar_info->m_pVPR + 0x0);
+ writel(0x00040000, sfb->m_pVPR + 0x0);
break;
case 32:
- writel(0x00030000, ppar_info->m_pVPR + 0x0);
+ writel(0x00030000, sfb->m_pVPR + 0x0);
break;
}
writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride),
- ppar_info->m_pVPR + 0x10);
+ sfb->m_pVPR + 0x10);
}
static void sm712_setpalette(int regno, unsigned red, unsigned green,
unsigned blue, struct fb_info *info)
{
- struct par_info *cur_par = (struct par_info *)info->par;
+ struct smtcfb_info *sfb = info->par;
- if (cur_par->BaseAddressInVRAM)
+ if (sfb->BaseAddressInVRAM)
/*
* second display palette for dual head. Enable CRT RAM, 6-bit
* RAM
@@ -283,14 +240,13 @@ static void sm712_setpalette(int regno, unsigned red, unsigned green,
smtc_mmiowb(blue >> 10, dac_val);
}
-static void smtc_set_timing(struct smtcfb_info *sfb, struct par_info
- *ppar_info)
+static void smtc_set_timing(struct smtcfb_info *sfb)
{
- switch (ppar_info->chipID) {
+ switch (sfb->chipID) {
case 0x710:
case 0x712:
case 0x720:
- sm712_set_timing(sfb, ppar_info);
+ sm712_set_timing(sfb);
break;
}
}
@@ -310,7 +266,7 @@ static inline unsigned int chan_to_field(unsigned int chan,
return chan << bf->offset;
}
-static int cfb_blank(int blank_mode, struct fb_info *info)
+static int smtc_blank(int blank_mode, struct fb_info *info)
{
/* clear DPMS setting */
switch (blank_mode) {
@@ -660,10 +616,10 @@ void smtcfb_setmode(struct smtcfb_info *sfb)
break;
}
- hw.width = sfb->fb.var.xres;
- hw.height = sfb->fb.var.yres;
- hw.hz = 60;
- smtc_set_timing(sfb, &hw);
+ sfb->width = sfb->fb.var.xres;
+ sfb->height = sfb->fb.var.yres;
+ sfb->hz = 60;
+ smtc_set_timing(sfb);
}
static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
@@ -697,7 +653,7 @@ static struct fb_ops smtcfb_ops = {
.fb_check_var = smtc_check_var,
.fb_set_par = smtc_set_par,
.fb_setcolreg = smtc_setcolreg,
- .fb_blank = cfb_blank,
+ .fb_blank = smtc_blank,
.fb_fillrect = cfb_fillrect,
.fb_imageblit = cfb_imageblit,
.fb_copyarea = cfb_copyarea,
@@ -710,8 +666,7 @@ static struct fb_ops smtcfb_ops = {
/*
* Alloc struct smtcfb_info and assign the default value
*/
-static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *dev,
- char *name)
+static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *pdev, char *name)
{
struct smtcfb_info *sfb;
@@ -720,8 +675,7 @@ static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *dev,
if (!sfb)
return NULL;
- sfb->currcon = -1;
- sfb->dev = dev;
+ sfb->pdev = pdev;
/*** Init sfb->fb with default value ***/
sfb->fb.flags = FBINFO_FLAG_DEFAULT;
@@ -745,7 +699,9 @@ static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *dev,
/* text mode acceleration */
sfb->fb.var.accel_flags = FB_ACCELF_TEXT;
sfb->fb.var.vmode = FB_VMODE_NONINTERLACED;
- sfb->fb.par = &hw;
+
+ sfb->fb.par = sfb;
+
sfb->fb.pseudo_palette = colreg;
return sfb;
@@ -766,17 +722,17 @@ static void smtc_unmap_mmio(struct smtcfb_info *sfb)
*/
static int smtc_map_smem(struct smtcfb_info *sfb,
- struct pci_dev *dev, u_long smem_len)
+ struct pci_dev *pdev, u_long smem_len)
{
if (sfb->fb.var.bits_per_pixel == 32) {
#ifdef __BIG_ENDIAN
- sfb->fb.fix.smem_start = pci_resource_start(dev, 0)
+ sfb->fb.fix.smem_start = pci_resource_start(pdev, 0)
+ 0x800000;
#else
- sfb->fb.fix.smem_start = pci_resource_start(dev, 0);
+ sfb->fb.fix.smem_start = pci_resource_start(pdev, 0);
#endif
} else {
- sfb->fb.fix.smem_start = pci_resource_start(dev, 0);
+ sfb->fb.fix.smem_start = pci_resource_start(pdev, 0);
}
sfb->fb.fix.smem_len = smem_len;
@@ -784,8 +740,8 @@ static int smtc_map_smem(struct smtcfb_info *sfb,
sfb->fb.screen_base = smtc_VRAMBaseAddress;
if (!sfb->fb.screen_base) {
- printk(KERN_ERR "%s: unable to map screen memory\n",
- sfb->fb.fix.id);
+ dev_err(&pdev->dev,
+ "%s: unable to map screen memory\n", sfb->fb.fix.id);
return -ENOMEM;
}
@@ -831,16 +787,14 @@ static int __init sm712vga_setup(char *options)
{
int index;
- if (!options || !*options) {
- smdbg("\n No vga parameter\n");
+ if (!options || !*options)
return -EINVAL;
- }
smtc_screen_info.lfb_width = 0;
smtc_screen_info.lfb_height = 0;
smtc_screen_info.lfb_depth = 0;
- smdbg("\nsm712vga_setup = %s\n", options);
+ pr_debug("sm712vga_setup = %s\n", options);
for (index = 0;
index < ARRAY_SIZE(vesa_mode);
@@ -858,10 +812,6 @@ static int __init sm712vga_setup(char *options)
}
__setup("vga=", sm712vga_setup);
-/* Jason (08/13/2009)
- * Original init function changed to probe method to be used by pci_drv
- * process used to detect chips replaced with kernel process in pci_drv
- */
static int __devinit smtcfb_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -871,23 +821,20 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev,
int err;
unsigned long pFramebufferPhysical;
- printk(KERN_INFO
- "Silicon Motion display driver " SMTC_LINUX_FB_VERSION "\n");
+ dev_info(&pdev->dev, "Silicon Motion display driver.");
err = pci_enable_device(pdev); /* enable SMTC chip */
if (err)
return err;
- hw.chipID = ent->device;
- sprintf(name, "sm%Xfb", hw.chipID);
-
sfb = smtc_alloc_fb_info(pdev, name);
if (!sfb)
goto failed_free;
- /* Jason (08/13/2009)
- * Store fb_info to be further used when suspending and resuming
- */
+
+ sfb->chipID = ent->device;
+ sprintf(name, "sm%Xfb", sfb->chipID);
+
pci_set_drvdata(pdev, sfb);
sm7xx_init_hw();
@@ -910,37 +857,37 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev,
#endif
/* Map address and memory detection */
pFramebufferPhysical = pci_resource_start(pdev, 0);
- pci_read_config_byte(pdev, PCI_REVISION_ID, &hw.chipRevID);
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chipRevID);
- switch (hw.chipID) {
+ switch (sfb->chipID) {
case 0x710:
case 0x712:
sfb->fb.fix.mmio_start = pFramebufferPhysical + 0x00400000;
sfb->fb.fix.mmio_len = 0x00400000;
smem_size = SM712_VIDEOMEMORYSIZE;
#ifdef __BIG_ENDIAN
- hw.m_pLFB = (smtc_VRAMBaseAddress =
+ sfb->m_pLFB = (smtc_VRAMBaseAddress =
ioremap(pFramebufferPhysical, 0x00c00000));
#else
- hw.m_pLFB = (smtc_VRAMBaseAddress =
+ sfb->m_pLFB = (smtc_VRAMBaseAddress =
ioremap(pFramebufferPhysical, 0x00800000));
#endif
- hw.m_pMMIO = (smtc_RegBaseAddress =
+ sfb->m_pMMIO = (smtc_RegBaseAddress =
smtc_VRAMBaseAddress + 0x00700000);
- hw.m_pDPR = smtc_VRAMBaseAddress + 0x00408000;
- hw.m_pVPR = hw.m_pLFB + 0x0040c000;
+ sfb->m_pDPR = smtc_VRAMBaseAddress + 0x00408000;
+ sfb->m_pVPR = sfb->m_pLFB + 0x0040c000;
#ifdef __BIG_ENDIAN
if (sfb->fb.var.bits_per_pixel == 32) {
smtc_VRAMBaseAddress += 0x800000;
- hw.m_pLFB += 0x800000;
- printk(KERN_INFO
- "\nsmtc_VRAMBaseAddress=%p hw.m_pLFB=%p\n",
- smtc_VRAMBaseAddress, hw.m_pLFB);
+ sfb->m_pLFB += 0x800000;
+ dev_info(&pdev->dev,
+ "smtc_VRAMBaseAddress=%p sfb->m_pLFB=%p",
+ smtc_VRAMBaseAddress, sfb->m_pLFB);
}
#endif
if (!smtc_RegBaseAddress) {
- printk(KERN_ERR
- "%s: unable to map memory mapped IO\n",
+ dev_err(&pdev->dev,
+ "%s: unable to map memory mapped IO!",
sfb->fb.fix.id);
err = -ENOMEM;
goto failed_fb;
@@ -962,20 +909,20 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev,
sfb->fb.fix.mmio_start = pFramebufferPhysical;
sfb->fb.fix.mmio_len = 0x00200000;
smem_size = SM722_VIDEOMEMORYSIZE;
- hw.m_pDPR = ioremap(pFramebufferPhysical, 0x00a00000);
- hw.m_pLFB = (smtc_VRAMBaseAddress =
- hw.m_pDPR + 0x00200000);
- hw.m_pMMIO = (smtc_RegBaseAddress =
- hw.m_pDPR + 0x000c0000);
- hw.m_pVPR = hw.m_pDPR + 0x800;
+ sfb->m_pDPR = ioremap(pFramebufferPhysical, 0x00a00000);
+ sfb->m_pLFB = (smtc_VRAMBaseAddress =
+ sfb->m_pDPR + 0x00200000);
+ sfb->m_pMMIO = (smtc_RegBaseAddress =
+ sfb->m_pDPR + 0x000c0000);
+ sfb->m_pVPR = sfb->m_pDPR + 0x800;
smtc_seqw(0x62, 0xff);
smtc_seqw(0x6a, 0x0d);
smtc_seqw(0x6b, 0x02);
break;
default:
- printk(KERN_ERR
- "No valid Silicon Motion display chip was detected!\n");
+ dev_err(&pdev->dev,
+ "No valid Silicon Motion display chip was detected!");
goto failed_fb;
}
@@ -992,22 +939,21 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev,
smtcfb_setmode(sfb);
/* Primary display starting from 0 position */
- hw.BaseAddressInVRAM = 0;
- sfb->fb.par = &hw;
+ sfb->BaseAddressInVRAM = 0;
err = register_framebuffer(&sfb->fb);
if (err < 0)
goto failed;
- printk(KERN_INFO "Silicon Motion SM%X Rev%X primary display mode"
- "%dx%d-%d Init Complete.\n", hw.chipID, hw.chipRevID,
- sfb->fb.var.xres, sfb->fb.var.yres,
- sfb->fb.var.bits_per_pixel);
+ dev_info(&pdev->dev,
+ "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.",
+ sfb->chipID, sfb->chipRevID, sfb->fb.var.xres,
+ sfb->fb.var.yres, sfb->fb.var.bits_per_pixel);
return 0;
failed:
- printk(KERN_ERR "Silicon Motion, Inc. primary display init fail\n");
+ dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail.");
smtc_unmap_smem(sfb);
smtc_unmap_mmio(sfb);
@@ -1021,7 +967,6 @@ failed_free:
}
-/* Jason (08/11/2009) PCI_DRV wrapper essential structs */
static DEFINE_PCI_DEVICE_TABLE(smtcfb_pci_table) = {
{ PCI_DEVICE(0x126f, 0x710), },
{ PCI_DEVICE(0x126f, 0x712), },
@@ -1030,9 +975,6 @@ static DEFINE_PCI_DEVICE_TABLE(smtcfb_pci_table) = {
};
-/* Jason (08/14/2009)
- * do some clean up when the driver module is removed
- */
static void __devexit smtcfb_pci_remove(struct pci_dev *pdev)
{
struct smtcfb_info *sfb;
@@ -1078,7 +1020,7 @@ static int smtcfb_pci_resume(struct device *device)
/* reinit hardware */
sm7xx_init_hw();
- switch (hw.chipID) {
+ switch (sfb->chipID) {
case 0x710:
case 0x712:
/* set MCLK = 14.31818 * (0x16 / 0x2) */
diff --git a/drivers/staging/sm7xx/smtcfb.h b/drivers/staging/sm7xx/smtcfb.h
index ab95af2b9c07..43d86f873410 100644
--- a/drivers/staging/sm7xx/smtcfb.h
+++ b/drivers/staging/sm7xx/smtcfb.h
@@ -13,19 +13,11 @@
* more details.
*/
-#define SMTC_LINUX_FB_VERSION "version 0.11.2619.21.01 July 27, 2008"
-
#define NR_PALETTE 256
#define NR_RGB 2
#define FB_ACCEL_SMI_LYNX 88
-#ifdef __BIG_ENDIAN
-#define PC_VGA 0
-#else
-#define PC_VGA 1
-#endif
-
#define SCREEN_X_RES 1024
#define SCREEN_Y_RES 600
#define SCREEN_BPP 16
diff --git a/drivers/staging/telephony/ixj.c b/drivers/staging/telephony/ixj.c
index f96027921f60..fd7757ad7fa3 100644
--- a/drivers/staging/telephony/ixj.c
+++ b/drivers/staging/telephony/ixj.c
@@ -19,20 +19,20 @@
* David W. Erhart, <derhart@quicknet.net>
* John Sellers, <jsellers@quicknet.net>
* Mike Preston, <mpreston@quicknet.net>
- *
+ *
* Fixes: David Huggins-Daines, <dhd@cepstral.com>
* Fabio Ferrari, <fabio.ferrari@digitro.com.br>
* Artis Kugevics, <artis@mt.lv>
* Daniele Bellucci, <bellucda@tiscali.it>
*
- * More information about the hardware related to this driver can be found
+ * More information about the hardware related to this driver can be found
* at our website: http://www.quicknet.net
*
* IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET
* TECHNOLOGIES, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
@@ -317,7 +317,7 @@ static IXJ *ixj[IXJMAX];
/*
* Allocate a free IXJ device
*/
-
+
static IXJ *ixj_alloc()
{
for(cnt=0; cnt<IXJMAX; cnt++)
@@ -366,7 +366,7 @@ static IXJ ixj[IXJMAX];
/*
* Allocate a free IXJ device
*/
-
+
static IXJ *ixj_alloc(void)
{
int cnt;
@@ -1084,7 +1084,7 @@ static void ixj_pstn_state(IXJ *j)
printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board,
j->cadence_f[4].on3, j->cadence_f[4].on3min, j->cadence_f[4].on3dot, j->cadence_f[4].on3max);
break;
- case 6:
+ case 6:
printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board,
j->cadence_f[4].off3, j->cadence_f[4].off3min, j->cadence_f[4].off3dot, j->cadence_f[4].off3max);
break;
@@ -1109,7 +1109,7 @@ static void ixj_pstn_state(IXJ *j)
}
j->pstn_ring_stop = j->pstn_ring_int = 0;
daa_set_mode(j, SOP_PU_SLEEP);
- }
+ }
outb_p(j->pld_scrw.byte, j->XILINXbase);
if (j->pstn_cid_intr && time_after(jiffies, j->pstn_cid_received + hertz)) {
ixj_daa_cid_read(j);
@@ -1133,7 +1133,7 @@ static void ixj_pstn_state(IXJ *j)
printk("IXJ DAA possible wink /dev/phone%d %ld\n", j->board, jiffies);
}
j->pstn_winkstart = jiffies;
- }
+ }
} else {
if (j->pstn_winkstart) {
if(ixjdebug & 0x0008) {
@@ -1524,7 +1524,7 @@ static inline void LED_SetState(int state, IXJ *j)
/*********************************************************************
* GPIO Pins are configured as follows on the Quicknet Internet
* PhoneJACK Telephony Cards
-*
+*
* POTS Select GPIO_6=0 GPIO_7=0
* Mic/Speaker Select GPIO_6=0 GPIO_7=1
* Handset Select GPIO_6=1 GPIO_7=0
@@ -1932,7 +1932,7 @@ static int ixj_hookstate(IXJ *j)
if(fOffHook != j->p_hook) {
if(!j->checkwait) {
j->checkwait = jiffies;
- }
+ }
if(time_before(jiffies, j->checkwait + 2)) {
fOffHook ^= 1;
} else {
@@ -2342,8 +2342,8 @@ static int ixj_release(struct inode *inode, struct file *file_p)
j->ixj_signals[cnt] = SIGIO;
/* Set the excetion signal enable flags */
- j->ex_sig.bits.dtmf_ready = j->ex_sig.bits.hookstate = j->ex_sig.bits.flash = j->ex_sig.bits.pstn_ring =
- j->ex_sig.bits.caller_id = j->ex_sig.bits.pstn_wink = j->ex_sig.bits.f0 = j->ex_sig.bits.f1 = j->ex_sig.bits.f2 =
+ j->ex_sig.bits.dtmf_ready = j->ex_sig.bits.hookstate = j->ex_sig.bits.flash = j->ex_sig.bits.pstn_ring =
+ j->ex_sig.bits.caller_id = j->ex_sig.bits.pstn_wink = j->ex_sig.bits.f0 = j->ex_sig.bits.f1 = j->ex_sig.bits.f2 =
j->ex_sig.bits.f3 = j->ex_sig.bits.fc0 = j->ex_sig.bits.fc1 = j->ex_sig.bits.fc2 = j->ex_sig.bits.fc3 = 1;
file_p->private_data = NULL;
@@ -2506,7 +2506,7 @@ static int read_filters(IXJ *j)
j->cadence_f[cnt].on1, j->cadence_f[cnt].on1min, j->cadence_f[cnt].on1dot, j->cadence_f[cnt].on1max);
break;
case 2:
- printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off1min,
+ printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off1min,
j->cadence_f[cnt].off1max);
break;
case 3:
@@ -2521,12 +2521,12 @@ static int read_filters(IXJ *j)
printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].on3min,
j->cadence_f[cnt].on3max);
break;
- case 6:
+ case 6:
printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off3min,
j->cadence_f[cnt].off3max);
break;
}
- }
+ }
}
if (j->cadence_f[cnt].state == 7) {
j->cadence_f[cnt].state = 0;
@@ -2656,37 +2656,37 @@ static void ulaw2alaw(unsigned char *buff, unsigned long len)
{
static unsigned char table_ulaw2alaw[] =
{
- 0x2A, 0x2B, 0x28, 0x29, 0x2E, 0x2F, 0x2C, 0x2D,
- 0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25,
- 0x3A, 0x3B, 0x38, 0x39, 0x3E, 0x3F, 0x3C, 0x3D,
- 0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35,
- 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D, 0x02,
- 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x1A,
- 0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D, 0x12,
- 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x6B,
- 0x68, 0x69, 0x6E, 0x6F, 0x6C, 0x6D, 0x62, 0x63,
- 0x60, 0x61, 0x66, 0x67, 0x64, 0x65, 0x7B, 0x79,
- 0x7E, 0x7F, 0x7C, 0x7D, 0x72, 0x73, 0x70, 0x71,
- 0x76, 0x77, 0x74, 0x75, 0x4B, 0x49, 0x4F, 0x4D,
- 0x42, 0x43, 0x40, 0x41, 0x46, 0x47, 0x44, 0x45,
- 0x5A, 0x5B, 0x58, 0x59, 0x5E, 0x5F, 0x5C, 0x5D,
- 0x52, 0x52, 0x53, 0x53, 0x50, 0x50, 0x51, 0x51,
- 0x56, 0x56, 0x57, 0x57, 0x54, 0x54, 0x55, 0xD5,
- 0xAA, 0xAB, 0xA8, 0xA9, 0xAE, 0xAF, 0xAC, 0xAD,
- 0xA2, 0xA3, 0xA0, 0xA1, 0xA6, 0xA7, 0xA4, 0xA5,
- 0xBA, 0xBB, 0xB8, 0xB9, 0xBE, 0xBF, 0xBC, 0xBD,
- 0xB2, 0xB3, 0xB0, 0xB1, 0xB6, 0xB7, 0xB4, 0xB5,
- 0x8B, 0x88, 0x89, 0x8E, 0x8F, 0x8C, 0x8D, 0x82,
- 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85, 0x9A,
- 0x9B, 0x98, 0x99, 0x9E, 0x9F, 0x9C, 0x9D, 0x92,
- 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, 0xEB,
- 0xE8, 0xE9, 0xEE, 0xEF, 0xEC, 0xED, 0xE2, 0xE3,
- 0xE0, 0xE1, 0xE6, 0xE7, 0xE4, 0xE5, 0xFB, 0xF9,
- 0xFE, 0xFF, 0xFC, 0xFD, 0xF2, 0xF3, 0xF0, 0xF1,
- 0xF6, 0xF7, 0xF4, 0xF5, 0xCB, 0xC9, 0xCF, 0xCD,
- 0xC2, 0xC3, 0xC0, 0xC1, 0xC6, 0xC7, 0xC4, 0xC5,
- 0xDA, 0xDB, 0xD8, 0xD9, 0xDE, 0xDF, 0xDC, 0xDD,
- 0xD2, 0xD2, 0xD3, 0xD3, 0xD0, 0xD0, 0xD1, 0xD1,
+ 0x2A, 0x2B, 0x28, 0x29, 0x2E, 0x2F, 0x2C, 0x2D,
+ 0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25,
+ 0x3A, 0x3B, 0x38, 0x39, 0x3E, 0x3F, 0x3C, 0x3D,
+ 0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35,
+ 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D, 0x02,
+ 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x1A,
+ 0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D, 0x12,
+ 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x6B,
+ 0x68, 0x69, 0x6E, 0x6F, 0x6C, 0x6D, 0x62, 0x63,
+ 0x60, 0x61, 0x66, 0x67, 0x64, 0x65, 0x7B, 0x79,
+ 0x7E, 0x7F, 0x7C, 0x7D, 0x72, 0x73, 0x70, 0x71,
+ 0x76, 0x77, 0x74, 0x75, 0x4B, 0x49, 0x4F, 0x4D,
+ 0x42, 0x43, 0x40, 0x41, 0x46, 0x47, 0x44, 0x45,
+ 0x5A, 0x5B, 0x58, 0x59, 0x5E, 0x5F, 0x5C, 0x5D,
+ 0x52, 0x52, 0x53, 0x53, 0x50, 0x50, 0x51, 0x51,
+ 0x56, 0x56, 0x57, 0x57, 0x54, 0x54, 0x55, 0xD5,
+ 0xAA, 0xAB, 0xA8, 0xA9, 0xAE, 0xAF, 0xAC, 0xAD,
+ 0xA2, 0xA3, 0xA0, 0xA1, 0xA6, 0xA7, 0xA4, 0xA5,
+ 0xBA, 0xBB, 0xB8, 0xB9, 0xBE, 0xBF, 0xBC, 0xBD,
+ 0xB2, 0xB3, 0xB0, 0xB1, 0xB6, 0xB7, 0xB4, 0xB5,
+ 0x8B, 0x88, 0x89, 0x8E, 0x8F, 0x8C, 0x8D, 0x82,
+ 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85, 0x9A,
+ 0x9B, 0x98, 0x99, 0x9E, 0x9F, 0x9C, 0x9D, 0x92,
+ 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, 0xEB,
+ 0xE8, 0xE9, 0xEE, 0xEF, 0xEC, 0xED, 0xE2, 0xE3,
+ 0xE0, 0xE1, 0xE6, 0xE7, 0xE4, 0xE5, 0xFB, 0xF9,
+ 0xFE, 0xFF, 0xFC, 0xFD, 0xF2, 0xF3, 0xF0, 0xF1,
+ 0xF6, 0xF7, 0xF4, 0xF5, 0xCB, 0xC9, 0xCF, 0xCD,
+ 0xC2, 0xC3, 0xC0, 0xC1, 0xC6, 0xC7, 0xC4, 0xC5,
+ 0xDA, 0xDB, 0xD8, 0xD9, 0xDE, 0xDF, 0xDC, 0xDD,
+ 0xD2, 0xD2, 0xD3, 0xD3, 0xD0, 0xD0, 0xD1, 0xD1,
0xD6, 0xD6, 0xD7, 0xD7, 0xD4, 0xD4, 0xD5, 0xD5
};
@@ -2701,37 +2701,37 @@ static void alaw2ulaw(unsigned char *buff, unsigned long len)
{
static unsigned char table_alaw2ulaw[] =
{
- 0x29, 0x2A, 0x27, 0x28, 0x2D, 0x2E, 0x2B, 0x2C,
- 0x21, 0x22, 0x1F, 0x20, 0x25, 0x26, 0x23, 0x24,
- 0x39, 0x3A, 0x37, 0x38, 0x3D, 0x3E, 0x3B, 0x3C,
- 0x31, 0x32, 0x2F, 0x30, 0x35, 0x36, 0x33, 0x34,
- 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D,
- 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
- 0x1A, 0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D,
- 0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15,
- 0x62, 0x63, 0x60, 0x61, 0x66, 0x67, 0x64, 0x65,
- 0x5D, 0x5D, 0x5C, 0x5C, 0x5F, 0x5F, 0x5E, 0x5E,
- 0x74, 0x76, 0x70, 0x72, 0x7C, 0x7E, 0x78, 0x7A,
- 0x6A, 0x6B, 0x68, 0x69, 0x6E, 0x6F, 0x6C, 0x6D,
- 0x48, 0x49, 0x46, 0x47, 0x4C, 0x4D, 0x4A, 0x4B,
- 0x40, 0x41, 0x3F, 0x3F, 0x44, 0x45, 0x42, 0x43,
- 0x56, 0x57, 0x54, 0x55, 0x5A, 0x5B, 0x58, 0x59,
- 0x4F, 0x4F, 0x4E, 0x4E, 0x52, 0x53, 0x50, 0x51,
- 0xA9, 0xAA, 0xA7, 0xA8, 0xAD, 0xAE, 0xAB, 0xAC,
- 0xA1, 0xA2, 0x9F, 0xA0, 0xA5, 0xA6, 0xA3, 0xA4,
- 0xB9, 0xBA, 0xB7, 0xB8, 0xBD, 0xBE, 0xBB, 0xBC,
- 0xB1, 0xB2, 0xAF, 0xB0, 0xB5, 0xB6, 0xB3, 0xB4,
- 0x8A, 0x8B, 0x88, 0x89, 0x8E, 0x8F, 0x8C, 0x8D,
- 0x82, 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85,
- 0x9A, 0x9B, 0x98, 0x99, 0x9E, 0x9F, 0x9C, 0x9D,
- 0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95,
- 0xE2, 0xE3, 0xE0, 0xE1, 0xE6, 0xE7, 0xE4, 0xE5,
- 0xDD, 0xDD, 0xDC, 0xDC, 0xDF, 0xDF, 0xDE, 0xDE,
- 0xF4, 0xF6, 0xF0, 0xF2, 0xFC, 0xFE, 0xF8, 0xFA,
- 0xEA, 0xEB, 0xE8, 0xE9, 0xEE, 0xEF, 0xEC, 0xED,
- 0xC8, 0xC9, 0xC6, 0xC7, 0xCC, 0xCD, 0xCA, 0xCB,
- 0xC0, 0xC1, 0xBF, 0xBF, 0xC4, 0xC5, 0xC2, 0xC3,
- 0xD6, 0xD7, 0xD4, 0xD5, 0xDA, 0xDB, 0xD8, 0xD9,
+ 0x29, 0x2A, 0x27, 0x28, 0x2D, 0x2E, 0x2B, 0x2C,
+ 0x21, 0x22, 0x1F, 0x20, 0x25, 0x26, 0x23, 0x24,
+ 0x39, 0x3A, 0x37, 0x38, 0x3D, 0x3E, 0x3B, 0x3C,
+ 0x31, 0x32, 0x2F, 0x30, 0x35, 0x36, 0x33, 0x34,
+ 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D,
+ 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
+ 0x1A, 0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D,
+ 0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15,
+ 0x62, 0x63, 0x60, 0x61, 0x66, 0x67, 0x64, 0x65,
+ 0x5D, 0x5D, 0x5C, 0x5C, 0x5F, 0x5F, 0x5E, 0x5E,
+ 0x74, 0x76, 0x70, 0x72, 0x7C, 0x7E, 0x78, 0x7A,
+ 0x6A, 0x6B, 0x68, 0x69, 0x6E, 0x6F, 0x6C, 0x6D,
+ 0x48, 0x49, 0x46, 0x47, 0x4C, 0x4D, 0x4A, 0x4B,
+ 0x40, 0x41, 0x3F, 0x3F, 0x44, 0x45, 0x42, 0x43,
+ 0x56, 0x57, 0x54, 0x55, 0x5A, 0x5B, 0x58, 0x59,
+ 0x4F, 0x4F, 0x4E, 0x4E, 0x52, 0x53, 0x50, 0x51,
+ 0xA9, 0xAA, 0xA7, 0xA8, 0xAD, 0xAE, 0xAB, 0xAC,
+ 0xA1, 0xA2, 0x9F, 0xA0, 0xA5, 0xA6, 0xA3, 0xA4,
+ 0xB9, 0xBA, 0xB7, 0xB8, 0xBD, 0xBE, 0xBB, 0xBC,
+ 0xB1, 0xB2, 0xAF, 0xB0, 0xB5, 0xB6, 0xB3, 0xB4,
+ 0x8A, 0x8B, 0x88, 0x89, 0x8E, 0x8F, 0x8C, 0x8D,
+ 0x82, 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85,
+ 0x9A, 0x9B, 0x98, 0x99, 0x9E, 0x9F, 0x9C, 0x9D,
+ 0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95,
+ 0xE2, 0xE3, 0xE0, 0xE1, 0xE6, 0xE7, 0xE4, 0xE5,
+ 0xDD, 0xDD, 0xDC, 0xDC, 0xDF, 0xDF, 0xDE, 0xDE,
+ 0xF4, 0xF6, 0xF0, 0xF2, 0xFC, 0xFE, 0xF8, 0xFA,
+ 0xEA, 0xEB, 0xE8, 0xE9, 0xEE, 0xEF, 0xEC, 0xED,
+ 0xC8, 0xC9, 0xC6, 0xC7, 0xCC, 0xCD, 0xCA, 0xCB,
+ 0xC0, 0xC1, 0xBF, 0xBF, 0xC4, 0xC5, 0xC2, 0xC3,
+ 0xD6, 0xD7, 0xD4, 0xD5, 0xDA, 0xDB, 0xD8, 0xD9,
0xCF, 0xCF, 0xCE, 0xCE, 0xD2, 0xD3, 0xD0, 0xD1
};
@@ -3090,7 +3090,7 @@ static int ixj_write_cid_string(IXJ *j, char *s, int checksum)
static void ixj_pad_fsk(IXJ *j, int pad)
{
- int cnt;
+ int cnt;
for (cnt = 0; cnt < pad; cnt++) {
if(j->fskdcnt < (j->fsksize - 1))
@@ -3474,7 +3474,7 @@ static void ixj_write_frame(IXJ *j)
ixj_post_cid(j);
}
/* This may seem rude, but if we just played one frame of FSK data for CallerID
- and there is real audio data in the buffer, we need to throw it away because
+ and there is real audio data in the buffer, we need to throw it away because
we just used it's time slot */
if (j->write_buffer_rp > j->write_buffer_wp) {
j->write_buffer_rp += j->cid_play_frame_size * 2;
@@ -3486,7 +3486,7 @@ static void ixj_write_frame(IXJ *j)
wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */
}
- } else if (j->write_buffer && j->write_buffers_empty < 1) {
+ } else if (j->write_buffer && j->write_buffers_empty < 1) {
if (j->write_buffer_wp > j->write_buffer_rp) {
frame_count =
(j->write_buffer_wp - j->write_buffer_rp) / (j->play_frame_size * 2);
@@ -4150,7 +4150,7 @@ static void ixj_aec_start(IXJ *j, int level)
ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */
ixj_WriteDSPCommand(0x0000, j); /* to off */
-
+
break;
case AEC_MED:
@@ -4161,7 +4161,7 @@ static void ixj_aec_start(IXJ *j, int level)
ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */
ixj_WriteDSPCommand(0x0000, j); /* to off */
-
+
break;
case AEC_HIGH:
@@ -4172,7 +4172,7 @@ static void ixj_aec_start(IXJ *j, int level)
ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */
ixj_WriteDSPCommand(0x0000, j); /* to off */
-
+
break;
case AEC_AGC:
@@ -4197,28 +4197,28 @@ static void ixj_aec_start(IXJ *j, int level)
/* Now we can set the AGC initial parameters and turn it on */
ixj_WriteDSPCommand(0xCF90, j); /* Set AGC Minimum gain */
ixj_WriteDSPCommand(0x0020, j); /* to 0.125 (-18dB) */
-
+
ixj_WriteDSPCommand(0xCF91, j); /* Set AGC Maximum gain */
ixj_WriteDSPCommand(0x1000, j); /* to 16 (24dB) */
-
+
ixj_WriteDSPCommand(0xCF92, j); /* Set AGC start gain */
ixj_WriteDSPCommand(0x0800, j); /* to 8 (+18dB) */
-
+
ixj_WriteDSPCommand(0xCF93, j); /* Set AGC hold time */
ixj_WriteDSPCommand(0x1F40, j); /* to 2 seconds (units are 250us) */
-
+
ixj_WriteDSPCommand(0xCF94, j); /* Set AGC Attack Time Constant */
ixj_WriteDSPCommand(0x0005, j); /* to 8ms */
-
+
ixj_WriteDSPCommand(0xCF95, j); /* Set AGC Decay Time Constant */
ixj_WriteDSPCommand(0x000D, j); /* to 4096ms */
-
+
ixj_WriteDSPCommand(0xCF96, j); /* Set AGC Attack Threshold */
ixj_WriteDSPCommand(0x1200, j); /* to 25% */
-
+
ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */
ixj_WriteDSPCommand(0x0001, j); /* to on */
-
+
break;
case AEC_AUTO:
@@ -4495,7 +4495,7 @@ static int ixj_play_start(IXJ *j)
return -ENOMEM;
}
/* j->write_buffers_empty = 2; */
- j->write_buffers_empty = 1;
+ j->write_buffers_empty = 1;
j->write_buffer_size = j->play_frame_size * 2;
j->write_buffer_end = j->write_buffer + j->play_frame_size * 2;
j->write_buffer_rp = j->write_buffer_wp = j->write_buffer;
@@ -6465,9 +6465,9 @@ static long do_ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long ar
ixj_ringback(j);
break;
case PHONE_WINK:
- if(j->cardtype == QTI_PHONEJACK)
+ if(j->cardtype == QTI_PHONEJACK)
retval = -1;
- else
+ else
retval = ixj_wink(j);
break;
case PHONE_CPT_STOP:
@@ -6553,7 +6553,7 @@ static long do_ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long ar
ixj_write_vmwi(j, arg);
break;
case IXJCTL_CID:
- if (copy_to_user(argp, &j->cid, sizeof(PHONE_CID)))
+ if (copy_to_user(argp, &j->cid, sizeof(PHONE_CID)))
retval = -EFAULT;
j->ex.bits.caller_id = 0;
break;
@@ -6575,13 +6575,13 @@ static long do_ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long ar
break;
case PHONE_CAPABILITIES_LIST:
add_caps(j);
- if (copy_to_user(argp, j->caplist, sizeof(struct phone_capability) * j->caps))
+ if (copy_to_user(argp, j->caplist, sizeof(struct phone_capability) * j->caps))
retval = -EFAULT;
break;
case PHONE_CAPABILITIES_CHECK:
{
struct phone_capability cap;
- if (copy_from_user(&cap, argp, sizeof(cap)))
+ if (copy_from_user(&cap, argp, sizeof(cap)))
retval = -EFAULT;
else {
add_caps(j);
@@ -6597,13 +6597,13 @@ static long do_ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long ar
j->ex.bits.pstn_ring = 0;
break;
case IXJCTL_SET_FILTER:
- if (copy_from_user(&jf, argp, sizeof(jf)))
+ if (copy_from_user(&jf, argp, sizeof(jf)))
retval = -EFAULT;
else
retval = ixj_init_filter(j, &jf);
break;
case IXJCTL_SET_FILTER_RAW:
- if (copy_from_user(&jfr, argp, sizeof(jfr)))
+ if (copy_from_user(&jfr, argp, sizeof(jfr)))
retval = -EFAULT;
else
retval = ixj_init_filter_raw(j, &jfr);
@@ -6638,9 +6638,9 @@ static long do_ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long ar
raise *= 2;
}
if(j->sigdef.signal)
- j->ex_sig.bytes |= raise;
+ j->ex_sig.bytes |= raise;
else
- j->ex_sig.bytes &= (raise^0xffff);
+ j->ex_sig.bytes &= (raise^0xffff);
}
break;
case IXJCTL_INTERCOM_STOP:
@@ -7040,9 +7040,9 @@ static int ixj_selfprobe(IXJ *j)
/* initialise the DTMF prescale to a sensible value */
if (j->cardtype == QTI_LINEJACK) {
- set_dtmf_prescale(j, 0x10);
+ set_dtmf_prescale(j, 0x10);
} else {
- set_dtmf_prescale(j, 0x40);
+ set_dtmf_prescale(j, 0x40);
}
set_play_volume(j, 0x100);
set_rec_volume(j, 0x100);
@@ -7095,15 +7095,15 @@ static int ixj_selfprobe(IXJ *j)
j->ixj_signals[cnt] = SIGIO;
/* Set the excetion signal enable flags */
- j->ex_sig.bits.dtmf_ready = j->ex_sig.bits.hookstate = j->ex_sig.bits.flash = j->ex_sig.bits.pstn_ring =
- j->ex_sig.bits.caller_id = j->ex_sig.bits.pstn_wink = j->ex_sig.bits.f0 = j->ex_sig.bits.f1 = j->ex_sig.bits.f2 =
+ j->ex_sig.bits.dtmf_ready = j->ex_sig.bits.hookstate = j->ex_sig.bits.flash = j->ex_sig.bits.pstn_ring =
+ j->ex_sig.bits.caller_id = j->ex_sig.bits.pstn_wink = j->ex_sig.bits.f0 = j->ex_sig.bits.f1 = j->ex_sig.bits.f2 =
j->ex_sig.bits.f3 = j->ex_sig.bits.fc0 = j->ex_sig.bits.fc1 = j->ex_sig.bits.fc2 = j->ex_sig.bits.fc3 = 1;
#ifdef IXJ_DYN_ALLOC
j->fskdata = NULL;
#endif
j->fskdcnt = 0;
j->cidcw_wait = 0;
-
+
/* Register with the Telephony for Linux subsystem */
j->p.f_op = &ixj_fops;
j->p.open = ixj_open;
@@ -7118,7 +7118,7 @@ static int ixj_selfprobe(IXJ *j)
/*
* Exported service for pcmcia card handling
*/
-
+
IXJ *ixj_pcmcia_probe(unsigned long dsp, unsigned long xilinx)
{
IXJ *j = ixj_alloc();
@@ -7320,7 +7320,7 @@ static int ixj_get_status_proc(char *buf)
len += sprintf(buf + len, "\nRec volume 0x%x", get_rec_volume(j));
len += sprintf(buf + len, "\nPlay volume 0x%x", get_play_volume(j));
len += sprintf(buf + len, "\nDTMF prescale 0x%x", get_dtmf_prescale(j));
-
+
len += sprintf(buf + len, "\nHook state %d", j->hookstate); /* j->r_hook); */
if (j->cardtype == QTI_LINEJACK) {
@@ -7417,7 +7417,7 @@ static int ixj_get_status_proc(char *buf)
len += sprintf(buf + len, "\nPControl Wait Fails %ld", j->pcontrolwaitfail);
len += sprintf(buf + len, "\nIs Control Ready Checks %ld", j->iscontrolready);
len += sprintf(buf + len, "\nIs Control Ready Check failures %ld", j->iscontrolreadyfail);
-
+
#endif
len += sprintf(buf + len, "\n");
}
@@ -7608,7 +7608,7 @@ static IXJ *new_ixj(unsigned long port)
}
static int __init ixj_probe_isapnp(int *cnt)
-{
+{
int probe = 0;
int func = 0x110;
struct pnp_dev *dev = NULL, *old_dev = NULL;
@@ -7686,7 +7686,7 @@ static int __init ixj_probe_isapnp(int *cnt)
}
return probe;
}
-
+
static int __init ixj_probe_isa(int *cnt)
{
int i, probe;
@@ -7713,7 +7713,7 @@ static int __init ixj_probe_isa(int *cnt)
static int __init ixj_probe_pci(int *cnt)
{
- struct pci_dev *pci = NULL;
+ struct pci_dev *pci = NULL;
int i, probe = 0;
IXJ *j = NULL;
@@ -7745,7 +7745,7 @@ static int __init ixj_probe_pci(int *cnt)
static int __init ixj_init(void)
{
int cnt = 0;
- int probe = 0;
+ int probe = 0;
cnt = 0;
@@ -7887,7 +7887,7 @@ static void DAA_Coeff_US(IXJ *j)
/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x2D; */
/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0x62; */
/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x2D; */
- /* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */
+ /* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */
/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x2D; */
/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x62; */
/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; */
diff --git a/drivers/staging/tidspbridge/core/io_sm.c b/drivers/staging/tidspbridge/core/io_sm.c
index 9b50b5bd4edb..c51f651dfd1b 100644
--- a/drivers/staging/tidspbridge/core/io_sm.c
+++ b/drivers/staging/tidspbridge/core/io_sm.c
@@ -2212,7 +2212,7 @@ void dump_dl_modules(struct bridge_dev_context *bridge_context)
if (status) {
pr_debug(
- "%s: Failed to read dll_module stuct for 0x%x.\n",
+ "%s: Failed to read dll_module struct for 0x%x.\n",
__func__, module_dsp_addr);
break;
}
diff --git a/drivers/staging/tidspbridge/core/ue_deh.c b/drivers/staging/tidspbridge/core/ue_deh.c
index 006ffd752895..3d28b2345fbd 100644
--- a/drivers/staging/tidspbridge/core/ue_deh.c
+++ b/drivers/staging/tidspbridge/core/ue_deh.c
@@ -215,7 +215,7 @@ static inline const char *event_to_string(int event)
case DSP_MMUFAULT: return "DSP_MMUFAULT"; break;
case DSP_PWRERROR: return "DSP_PWRERROR"; break;
case DSP_WDTOVERFLOW: return "DSP_WDTOVERFLOW"; break;
- default: return "unkown event"; break;
+ default: return "unknown event"; break;
}
}
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
index fa870e3f7f6a..92ced35e6b7f 100644
--- a/drivers/staging/usbip/stub_dev.c
+++ b/drivers/staging/usbip/stub_dev.c
@@ -113,8 +113,8 @@ static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr,
spin_unlock(&sdev->ud.lock);
- sdev->ud.tcp_rx = kthread_run(stub_rx_loop, &sdev->ud, "stub_rx");
- sdev->ud.tcp_tx = kthread_run(stub_tx_loop, &sdev->ud, "stub_tx");
+ sdev->ud.tcp_rx = kthread_get_run(stub_rx_loop, &sdev->ud, "stub_rx");
+ sdev->ud.tcp_tx = kthread_get_run(stub_tx_loop, &sdev->ud, "stub_tx");
spin_lock(&sdev->ud.lock);
sdev->ud.status = SDEV_ST_USED;
@@ -187,10 +187,10 @@ static void stub_shutdown_connection(struct usbip_device *ud)
}
/* 1. stop threads */
- if (ud->tcp_rx && !task_is_dead(ud->tcp_rx))
- kthread_stop(ud->tcp_rx);
- if (ud->tcp_tx && !task_is_dead(ud->tcp_tx))
- kthread_stop(ud->tcp_tx);
+ if (ud->tcp_rx)
+ kthread_stop_put(ud->tcp_rx);
+ if (ud->tcp_tx)
+ kthread_stop_put(ud->tcp_tx);
/*
* 2. close the socket
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
index c7b888ca54f5..5d89c0fd6f7b 100644
--- a/drivers/staging/usbip/usbip_common.h
+++ b/drivers/staging/usbip/usbip_common.h
@@ -292,6 +292,23 @@ struct usbip_device {
} eh_ops;
};
+#define kthread_get_run(threadfn, data, namefmt, ...) \
+({ \
+ struct task_struct *__k \
+ = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
+ if (!IS_ERR(__k)) { \
+ get_task_struct(__k); \
+ wake_up_process(__k); \
+ } \
+ __k; \
+})
+
+#define kthread_stop_put(k) \
+ do { \
+ kthread_stop(k); \
+ put_task_struct(k); \
+ } while (0)
+
/* usbip_common.c */
void usbip_dump_urb(struct urb *purb);
void usbip_dump_header(struct usbip_header *pdu);
diff --git a/drivers/staging/usbip/usbip_protocol.txt b/drivers/staging/usbip/usbip_protocol.txt
index 0f102081e86c..16b6fe27284c 100644
--- a/drivers/staging/usbip/usbip_protocol.txt
+++ b/drivers/staging/usbip/usbip_protocol.txt
@@ -27,7 +27,7 @@ Once the client knows the list of exported USB devices it may decide to use one
of them. First the client opens a TCP/IP connection towards the server and
sends an OP_REQ_IMPORT packet. The server replies with OP_REP_IMPORT. If the
import was successful the TCP/IP connection remains open and will be used
-to trasfer the URB traffic between the client and the server. The client may
+to transfer the URB traffic between the client and the server. The client may
send two types of packets: the USBIP_CMD_SUBMIT to submit an URB, and
USBIP_CMD_UNLINK to unlink a previously submitted URB. The answers of the
server may be USBIP_RET_SUBMIT and USBIP_RET_UNLINK respectively.
diff --git a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
index 269787751b20..0958ba53e94a 100644
--- a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
+++ b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
@@ -59,7 +59,10 @@ static int parse_status(char *value)
/* skip a header line */
- c = strchr(value, '\n') + 1;
+ c = strchr(value, '\n');
+ if (!c)
+ return -1;
+ c++;
while (*c != '\0') {
int port, status, speed, devid;
@@ -109,7 +112,10 @@ static int parse_status(char *value)
/* go to the next line */
- c = strchr(c, '\n') + 1;
+ c = strchr(c, '\n');
+ if (!c)
+ break;
+ c++;
}
dbg("exit");
@@ -264,11 +270,17 @@ static int get_nports(void)
attr_status->method, attr_status->value);
/* skip a header line */
- c = strchr(attr_status->value, '\n') + 1;
+ c = strchr(attr_status->value, '\n');
+ if (!c)
+ return 0;
+ c++;
while (*c != '\0') {
/* go to the next line */
- c = strchr(c, '\n') + 1;
+ c = strchr(c, '\n');
+ if (!c)
+ return nports;
+ c++;
nports += 1;
}
diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
index dca9bf11f0c2..f708cbaee16b 100644
--- a/drivers/staging/usbip/vhci_hcd.c
+++ b/drivers/staging/usbip/vhci_hcd.c
@@ -821,10 +821,10 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
}
/* kill threads related to this sdev, if v.c. exists */
- if (vdev->ud.tcp_rx && !task_is_dead(vdev->ud.tcp_rx))
- kthread_stop(vdev->ud.tcp_rx);
- if (vdev->ud.tcp_tx && !task_is_dead(vdev->ud.tcp_tx))
- kthread_stop(vdev->ud.tcp_tx);
+ if (vdev->ud.tcp_rx)
+ kthread_stop_put(vdev->ud.tcp_rx);
+ if (vdev->ud.tcp_tx)
+ kthread_stop_put(vdev->ud.tcp_tx);
pr_info("stop threads\n");
diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c
index f5fba7320c5a..f0eaf04fa25b 100644
--- a/drivers/staging/usbip/vhci_rx.c
+++ b/drivers/staging/usbip/vhci_rx.c
@@ -162,7 +162,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
* already received the result of its submit result and gave
* back the URB.
*/
- pr_info("the urb (seqnum %d) was already given backed\n",
+ pr_info("the urb (seqnum %d) was already given back\n",
pdu->base.seqnum);
} else {
usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c
index 0cd039bb5fd6..7ce9c2f7e442 100644
--- a/drivers/staging/usbip/vhci_sysfs.c
+++ b/drivers/staging/usbip/vhci_sysfs.c
@@ -222,8 +222,8 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
spin_unlock(&the_controller->lock);
/* end the lock */
- vdev->ud.tcp_rx = kthread_run(vhci_rx_loop, &vdev->ud, "vhci_rx");
- vdev->ud.tcp_tx = kthread_run(vhci_tx_loop, &vdev->ud, "vhci_tx");
+ vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx");
+ vdev->ud.tcp_tx = kthread_get_run(vhci_tx_loop, &vdev->ud, "vhci_tx");
rh_port_connect(rhport, speed);
diff --git a/drivers/staging/vme/Makefile b/drivers/staging/vme/Makefile
index b4ea3f8d0a50..accdb72e39e2 100644
--- a/drivers/staging/vme/Makefile
+++ b/drivers/staging/vme/Makefile
@@ -1,8 +1 @@
-#
-# Makefile for the VME bridge device drivers.
-#
-obj-$(CONFIG_VME_BUS) += vme.o
-
-obj-y += bridges/
obj-y += devices/
-obj-y += boards/
diff --git a/drivers/staging/vme/TODO b/drivers/staging/vme/TODO
deleted file mode 100644
index 79f00333e7ef..000000000000
--- a/drivers/staging/vme/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
- TODO
- ====
-
-- Add one or more device drivers which use the VME framework.
-
diff --git a/drivers/staging/vme/devices/Kconfig b/drivers/staging/vme/devices/Kconfig
index 55ec30cb1fa2..d0cab1766190 100644
--- a/drivers/staging/vme/devices/Kconfig
+++ b/drivers/staging/vme/devices/Kconfig
@@ -2,6 +2,7 @@ comment "VME Device Drivers"
config VME_USER
tristate "VME user space access driver"
+ depends on STAGING
help
If you say Y here you want to be able to access a limited number of
VME windows in a manner at least semi-compatible with the interface
@@ -9,7 +10,7 @@ config VME_USER
config VME_PIO2
tristate "GE PIO2 VME"
- depends on GPIOLIB
+ depends on STAGING && GPIOLIB
help
Say Y here to include support for the GE PIO2. The PIO2 is a 6U VME
slave card, implementing 32 solid-state relay switched IO lines, in
diff --git a/drivers/staging/vme/devices/vme_pio2_cntr.c b/drivers/staging/vme/devices/vme_pio2_cntr.c
index 08e0d59806ca..6335471faa36 100644
--- a/drivers/staging/vme/devices/vme_pio2_cntr.c
+++ b/drivers/staging/vme/devices/vme_pio2_cntr.c
@@ -17,8 +17,8 @@
#include <linux/device.h>
#include <linux/types.h>
#include <linux/gpio.h>
+#include <linux/vme.h>
-#include "../vme.h"
#include "vme_pio2.h"
static int pio2_cntr_irq_set(struct pio2_card *card, int id)
diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c
index 573c80003f0c..4bf8e05ac312 100644
--- a/drivers/staging/vme/devices/vme_pio2_core.c
+++ b/drivers/staging/vme/devices/vme_pio2_core.c
@@ -10,7 +10,6 @@
* option) any later version.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
@@ -20,8 +19,8 @@
#include <linux/ctype.h>
#include <linux/gpio.h>
#include <linux/slab.h>
+#include <linux/vme.h>
-#include "../vme.h"
#include "vme_pio2.h"
diff --git a/drivers/staging/vme/devices/vme_pio2_gpio.c b/drivers/staging/vme/devices/vme_pio2_gpio.c
index 858484915f08..ad76a477825b 100644
--- a/drivers/staging/vme/devices/vme_pio2_gpio.c
+++ b/drivers/staging/vme/devices/vme_pio2_gpio.c
@@ -10,7 +10,6 @@
* option) any later version.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
@@ -21,8 +20,8 @@
#include <linux/ctype.h>
#include <linux/gpio.h>
#include <linux/slab.h>
+#include <linux/vme.h>
-#include "../vme.h"
#include "vme_pio2.h"
static const char driver_name[] = "pio2_gpio";
@@ -79,7 +78,7 @@ static void pio2_gpio_set(struct gpio_chip *chip, unsigned int offset,
if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) |
(card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
- dev_err(&card->vdev->dev, "Channel not availabe as output\n");
+ dev_err(&card->vdev->dev, "Channel not available as output\n");
return;
}
diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
index 7dcd1622b5f5..e24a6f95db12 100644
--- a/drivers/staging/vme/devices/vme_user.c
+++ b/drivers/staging/vme/devices/vme_user.c
@@ -27,7 +27,7 @@
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/pci.h>
-#include <linux/semaphore.h>
+#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/syscalls.h>
@@ -36,8 +36,8 @@
#include <linux/io.h>
#include <linux/uaccess.h>
+#include <linux/vme.h>
-#include "../vme.h"
#include "vme_user.h"
static DEFINE_MUTEX(vme_user_mutex);
@@ -95,7 +95,7 @@ struct image_desc {
void *kern_buf; /* Buffer address in kernel space */
dma_addr_t pci_buf; /* Buffer address in PCI address space */
unsigned long long size_buf; /* Buffer size */
- struct semaphore sem; /* Semaphore for locking image */
+ struct mutex mutex; /* Mutex for locking image */
struct device *device; /* Sysfs device */
struct vme_resource *resource; /* VME resource */
int users; /* Number of current users */
@@ -168,7 +168,7 @@ static int vme_user_open(struct inode *inode, struct file *file)
int err;
unsigned int minor = MINOR(inode->i_rdev);
- down(&image[minor].sem);
+ mutex_lock(&image[minor].mutex);
/* Allow device to be opened if a resource is needed and allocated. */
if (minor < CONTROL_MINOR && image[minor].resource == NULL) {
printk(KERN_ERR "No resources allocated for device\n");
@@ -179,12 +179,12 @@ static int vme_user_open(struct inode *inode, struct file *file)
/* Increment user count */
image[minor].users++;
- up(&image[minor].sem);
+ mutex_unlock(&image[minor].mutex);
return 0;
err_res:
- up(&image[minor].sem);
+ mutex_unlock(&image[minor].mutex);
return err;
}
@@ -193,12 +193,12 @@ static int vme_user_release(struct inode *inode, struct file *file)
{
unsigned int minor = MINOR(inode->i_rdev);
- down(&image[minor].sem);
+ mutex_lock(&image[minor].mutex);
/* Decrement user count */
image[minor].users--;
- up(&image[minor].sem);
+ mutex_unlock(&image[minor].mutex);
return 0;
}
@@ -325,14 +325,14 @@ static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,
if (minor == CONTROL_MINOR)
return 0;
- down(&image[minor].sem);
+ mutex_lock(&image[minor].mutex);
/* XXX Do we *really* want this helper - we can use vme_*_get ? */
image_size = vme_get_size(image[minor].resource);
/* Ensure we are starting at a valid location */
if ((*ppos < 0) || (*ppos > (image_size - 1))) {
- up(&image[minor].sem);
+ mutex_unlock(&image[minor].mutex);
return 0;
}
@@ -353,8 +353,7 @@ static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,
retval = -EINVAL;
}
- up(&image[minor].sem);
-
+ mutex_unlock(&image[minor].mutex);
if (retval > 0)
*ppos += retval;
@@ -372,13 +371,13 @@ static ssize_t vme_user_write(struct file *file, const char __user *buf,
if (minor == CONTROL_MINOR)
return 0;
- down(&image[minor].sem);
+ mutex_lock(&image[minor].mutex);
image_size = vme_get_size(image[minor].resource);
/* Ensure we are starting at a valid location */
if ((*ppos < 0) || (*ppos > (image_size - 1))) {
- up(&image[minor].sem);
+ mutex_unlock(&image[minor].mutex);
return 0;
}
@@ -398,8 +397,8 @@ static ssize_t vme_user_write(struct file *file, const char __user *buf,
default:
retval = -EINVAL;
}
-
- up(&image[minor].sem);
+
+ mutex_unlock(&image[minor].mutex);
if (retval > 0)
*ppos += retval;
@@ -416,7 +415,7 @@ static loff_t vme_user_llseek(struct file *file, loff_t off, int whence)
if (minor == CONTROL_MINOR)
return -EINVAL;
- down(&image[minor].sem);
+ mutex_lock(&image[minor].mutex);
image_size = vme_get_size(image[minor].resource);
switch (whence) {
@@ -430,19 +429,19 @@ static loff_t vme_user_llseek(struct file *file, loff_t off, int whence)
absolute = image_size + off;
break;
default:
- up(&image[minor].sem);
+ mutex_unlock(&image[minor].mutex);
return -EINVAL;
break;
}
if ((absolute < 0) || (absolute >= image_size)) {
- up(&image[minor].sem);
+ mutex_unlock(&image[minor].mutex);
return -EINVAL;
}
file->f_pos = absolute;
- up(&image[minor].sem);
+ mutex_unlock(&image[minor].mutex);
return absolute;
}
@@ -696,7 +695,7 @@ static int __devinit vme_user_probe(struct vme_dev *vdev)
for (i = 0; i < VME_DEVS; i++) {
image[i].kern_buf = NULL;
image[i].pci_buf = 0;
- sema_init(&image[i].sem, 1);
+ mutex_init(&image[i].mutex);
image[i].device = NULL;
image[i].resource = NULL;
image[i].users = 0;
@@ -858,8 +857,10 @@ static int __devexit vme_user_remove(struct vme_dev *dev)
int i;
/* Remove sysfs Entries */
- for (i = 0; i < VME_DEVS; i++)
+ for (i = 0; i < VME_DEVS; i++) {
+ mutex_destroy(&image[i].mutex);
device_destroy(vme_user_sysfs_class, MKDEV(VME_MAJOR, i));
+ }
class_destroy(vme_user_sysfs_class);
for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++) {
diff --git a/drivers/staging/vt6655/wpa.c b/drivers/staging/vt6655/wpa.c
index 61ac46fa505e..0afb9fe0379a 100644
--- a/drivers/staging/vt6655/wpa.c
+++ b/drivers/staging/vt6655/wpa.c
@@ -148,7 +148,7 @@ WPA_ParseRSN (
{
j = 0;
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d, sizeof(pBSSList->abyPKType): %zu\n", pRSN->wPKCount, sizeof(pBSSList->abyPKType));
- for(i = 0; (i < pRSN->wPKCount) && (j < sizeof(pBSSList->abyPKType)/sizeof(unsigned char)); i++) {
+ for(i = 0; (i < pRSN->wPKCount) && (j < ARRAY_SIZE(pBSSList->abyPKType)); i++) {
if(pRSN->len >= 12+i*4+4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*i)
if ( !memcmp(pRSN->PKSList[i].abyOUI, abyOUI00, 4))
pBSSList->abyPKType[j++] = WPA_NONE;
@@ -180,7 +180,7 @@ WPA_ParseRSN (
j = 0;
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d, sizeof(pBSSList->abyAuthType): %zu\n",
pIE_RSN_Auth->wAuthCount, sizeof(pBSSList->abyAuthType));
- for(i = 0; (i < pIE_RSN_Auth->wAuthCount) && (j < sizeof(pBSSList->abyAuthType)/sizeof(unsigned char)); i++) {
+ for(i = 0; (i < pIE_RSN_Auth->wAuthCount) && (j < ARRAY_SIZE(pBSSList->abyAuthType)); i++) {
if(pRSN->len >= 14+4+(m+i)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*i)
if ( !memcmp(pIE_RSN_Auth->AuthKSList[i].abyOUI, abyOUI01, 4))
pBSSList->abyAuthType[j++] = WPA_AUTH_IEEE802_1X;
diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c
index c0edf97535dc..e4bdf2a2b582 100644
--- a/drivers/staging/vt6656/dpc.c
+++ b/drivers/staging/vt6656/dpc.c
@@ -452,7 +452,7 @@ RXbBulkInProcessData (
}
}
- if (!is_multicast_ether_addr(pMACHeader->abyAddr1) && !is_broadcast_ether_addr(pMACHeader->abyAddr1)) {
+ if (!is_multicast_ether_addr(pMACHeader->abyAddr1)) {
if ( WCTLbIsDuplicate(&(pDevice->sDupRxCache), (PS802_11Header) pbyFrame) ) {
pDevice->s802_11Counter.FrameDuplicateCount++;
return FALSE;
diff --git a/drivers/staging/vt6656/ioctl.c b/drivers/staging/vt6656/ioctl.c
index d59456c29df1..5b9a84f95185 100644
--- a/drivers/staging/vt6656/ioctl.c
+++ b/drivers/staging/vt6656/ioctl.c
@@ -90,18 +90,17 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
spin_lock_irq(&pDevice->lock);
if (memcmp(pMgmt->abyCurrBSSID, &abyNullAddr[0], 6) == 0)
- BSSvClearBSSList((void *)pDevice, FALSE);
+ BSSvClearBSSList(pDevice, FALSE);
else
- BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
+ BSSvClearBSSList(pDevice, pDevice->bLinkPass);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_BSS_SCAN..begin\n");
if (pItemSSID->len != 0)
- bScheduleCommand((void *)pDevice,
- WLAN_CMD_BSSID_SCAN,
+ bScheduleCommand(pDevice, WLAN_CMD_BSSID_SCAN,
abyScanSSID);
else
- bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
+ bScheduleCommand(pDevice, WLAN_CMD_BSSID_SCAN, NULL);
spin_unlock_irq(&pDevice->lock);
break;
@@ -150,6 +149,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
}
}
break;
+
case WLAN_CMD_BSS_JOIN:
if (copy_from_user(&sJoinCmd, pReq->data, sizeof(SCmdBSSJoin))) {
result = -EFAULT;
@@ -190,10 +190,9 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
netif_stop_queue(pDevice->dev);
spin_lock_irq(&pDevice->lock);
pMgmt->eCurrState = WMAC_STATE_IDLE;
- bScheduleCommand((void *) pDevice,
- WLAN_CMD_BSSID_SCAN,
+ bScheduleCommand(pDevice, WLAN_CMD_BSSID_SCAN,
pMgmt->abyDesireSSID);
- bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL);
+ bScheduleCommand(pDevice, WLAN_CMD_SSID, NULL);
spin_unlock_irq(&pDevice->lock);
break;
@@ -299,7 +298,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
result = -EINVAL;
break;
}
- pList = (PSBSSIDList)kmalloc(sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)), (int)GFP_ATOMIC);
+ pList = kmalloc(sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)), GFP_ATOMIC);
if (pList == NULL) {
result = -ENOMEM;
break;
@@ -313,7 +312,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
pList->sBSSIDList[ii].wBeaconInterval = pBSS->wBeaconInterval;
pList->sBSSIDList[ii].wCapInfo = pBSS->wCapInfo;
RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm);
- pList->sBSSIDList[ii].uRSSI = (unsigned int) ldBm;
+ pList->sBSSIDList[ii].uRSSI = (unsigned int)ldBm;
/* pList->sBSSIDList[ii].uRSSI = pBSS->uRSSI; */
memcpy(pList->sBSSIDList[ii].abyBSSID, pBSS->abyBSSID, WLAN_BSSID_LEN);
pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
@@ -356,6 +355,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
break;
}
break;
+
case WLAN_CMD_STOP_MAC:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_STOP_MAC\n");
/* Todo xxxxxx */
@@ -534,7 +534,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
netif_stop_queue(pDevice->dev);
spin_lock_irq(&pDevice->lock);
- bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL);
+ bScheduleCommand(pDevice, WLAN_CMD_RUN_AP, NULL);
spin_unlock_irq(&pDevice->lock);
break;
@@ -565,7 +565,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
result = -ENOMEM;
break;
}
- pNodeList = kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC);
+ pNodeList = kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), GFP_ATOMIC);
if (pNodeList == NULL) {
result = -ENOMEM;
break;
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 763e028a5cc5..ee5261a36886 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -1257,9 +1257,7 @@ static void __devexit vt6656_disconnect(struct usb_interface *intf)
}
device_release_WPADEV(device);
-
- if (device->firmware)
- release_firmware(device->firmware);
+ release_firmware(device->firmware);
usb_set_intfdata(intf, NULL);
usb_put_dev(interface_to_usbdev(intf));
diff --git a/drivers/staging/vt6656/wpa.c b/drivers/staging/vt6656/wpa.c
index 7dde3d6941ab..b16d4ddc117b 100644
--- a/drivers/staging/vt6656/wpa.c
+++ b/drivers/staging/vt6656/wpa.c
@@ -149,7 +149,7 @@ WPA_ParseRSN(
j = 0;
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d, sizeof(pBSSList->abyPKType): %zu\n", pRSN->wPKCount, sizeof(pBSSList->abyPKType));
for (i = 0; (i < pRSN->wPKCount) &&
- (j < sizeof(pBSSList->abyPKType)/sizeof(BYTE)); i++) {
+ (j < ARRAY_SIZE(pBSSList->abyPKType)); i++) {
if(pRSN->len >= 12+i*4+4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*i)
if ( !memcmp(pRSN->PKSList[i].abyOUI, abyOUI00, 4))
pBSSList->abyPKType[j++] = WPA_NONE;
@@ -182,7 +182,7 @@ WPA_ParseRSN(
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d, sizeof(pBSSList->abyAuthType): %zu\n",
pIE_RSN_Auth->wAuthCount, sizeof(pBSSList->abyAuthType));
for (i = 0; (i < pIE_RSN_Auth->wAuthCount) &&
- (j < sizeof(pBSSList->abyAuthType)/sizeof(BYTE)); i++) {
+ (j < ARRAY_SIZE(pBSSList->abyAuthType)); i++) {
if(pRSN->len >= 14+4+(m+i)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*i)
if ( !memcmp(pIE_RSN_Auth->AuthKSList[i].abyOUI, abyOUI01, 4))
pBSSList->abyAuthType[j++] = WPA_AUTH_IEEE802_1X;
diff --git a/drivers/staging/wlags49_h2/README.ubuntu b/drivers/staging/wlags49_h2/README.ubuntu
index edee8b9385be..5f1cfb8fd427 100644
--- a/drivers/staging/wlags49_h2/README.ubuntu
+++ b/drivers/staging/wlags49_h2/README.ubuntu
@@ -87,7 +87,7 @@ The linux driver files (wl_xxxx.c) are changed in the following ways:
-- Recovery actions added
The major problem was the order in which calls can be made. The original
-looks like a traditonal UNIX driver. To call an "ioctl" function you
+looks like a traditional UNIX driver. To call an "ioctl" function you
have to "open" the device first to get a handle and after "close" no
"ioctl" function can be called anymore. With the 2.6 driver this all
changed; the former ioctl functions are now called before "open" and
diff --git a/drivers/staging/wlags49_h2/hcf.c b/drivers/staging/wlags49_h2/hcf.c
index 5957c3a439ac..366e4a4b75c5 100644
--- a/drivers/staging/wlags49_h2/hcf.c
+++ b/drivers/staging/wlags49_h2/hcf.c
@@ -2871,8 +2871,8 @@ or
* The Assert validates the HCF assumption about Hermes implementation upon which the range of
* Pseudo-RIDs is based.
* Then the control fields up to the start of the 802.3 frame are read from the NIC into the lookahead buffer.
-* The status field is converted to native Endianess.
-* The length is, after implicit Endianess conversion if needed, and adjustment for the 14 bytes of the
+* The status field is converted to native Endianness.
+* The length is, after implicit Endianness conversion if needed, and adjustment for the 14 bytes of the
* 802.3 MAC header, stored in IFB_RxLen.
* In MAC Monitor mode, 802.11 control frames with a TOTAL length of 14 are received, so without this
* length adjustment, IFB_RxLen could not be used to distinguish these frames from "no frame".
@@ -2894,7 +2894,7 @@ or
* - the Hermes reported Tunnel encapsulation or
* - the Hermes reported 1042 Encapsulation and hcf_encap reports that the HCF would not have used
* 1042 as the encapsulation mechanism
-* Note that the first field of the RxFS in bufp has Native Endianess due to the conversion done by the
+* Note that the first field of the RxFS in bufp has Native Endianness due to the conversion done by the
* BE_PAR in get_frag.
*36: The Type field is the only word kept (after moving) of the just read 8 bytes, it is moved to the
* L-field. The original L-field and 6 byte SNAP header are discarded, so IFB_RxLen and buf_addr must
@@ -3831,7 +3831,7 @@ get_fid( IFBP ifbp )
*.DESCRIPTION
* process the single byte (if applicable) read by the previous get_frag and copy len (or len-1) bytes from
* NIC to bufp.
- * On a Big Endian platform, the parameter word_len controls the number of leading bytes whose endianess is
+ * On a Big Endian platform, the parameter word_len controls the number of leading bytes whose endianness is
* converted (i.e. byte swapped)
*
*
@@ -3980,7 +3980,7 @@ get_frag( IFBP ifbp, wci_bufp bufp, int len BE_PAR( int word_len ) )
* appropriate means on H-I: always
* and on H-II if F/W supplier reflects a primary (i.e. only after an Hermes Reset or Init
* command).
- * QUESTION ;? !!!!!! should, For each of the above RIDs the Endianess is converted to native Endianess.
+ * QUESTION ;? !!!!!! should, For each of the above RIDs the Endianness is converted to native Endianness.
* Only the return code of the first hcf_get_info is used. All hcf_get_info calls are made, regardless of
* the success or failure of the 1st hcf_get_info. The assumptions are:
* - if any call fails, they all fail, so remembering the result of the 1st call is adequate
diff --git a/drivers/staging/wlags49_h2/hcf.h b/drivers/staging/wlags49_h2/hcf.h
index 95527b5cf863..68e23303b5e8 100644
--- a/drivers/staging/wlags49_h2/hcf.h
+++ b/drivers/staging/wlags49_h2/hcf.h
@@ -90,7 +90,7 @@
#define LOF(x) (sizeof(x)/sizeof(hcf_16)-1)
-/* Endianess
+/* Endianness
* Little Endian (a.k.a. Intel), least significant byte first
* Big Endian (a.k.a. Motorola), most significant byte first
*
@@ -101,7 +101,7 @@
*/
/* To increase portability, use unsigned char and unsigned char * when accessing parts of larger
- * types to convert their Endianess
+ * types to convert their Endianness
*/
#define CNV_END_SHORT(w) (hcf_16)( ((hcf_16)(w) & 0x00FF) << 8 | ((hcf_16)(w) & 0xFF00) >> 8 )
@@ -109,14 +109,14 @@
#if HCF_BIG_ENDIAN
//******************************************** B I G E N D I A N *******************************************
-#define CNV_LITTLE_TO_SHORT(w) CNV_END_SHORT(w) // endianess conversion needed
-#define CNV_BIG_TO_SHORT(w) (w) // no endianess conversion needed
+#define CNV_LITTLE_TO_SHORT(w) CNV_END_SHORT(w) // endianness conversion needed
+#define CNV_BIG_TO_SHORT(w) (w) // no endianness conversion needed
#define CNV_LITTLE_TO_LONG(dw) CNV_END_LONG(dw)
#define CNV_LONG_TO_LITTLE(dw) CNV_END_LONG(dw)
#else
//****************************************** L I T T L E E N D I A N ****************************************
-#define CNV_LITTLE_TO_SHORT(w) (w) // no endianess conversion needed
-#define CNV_BIG_TO_SHORT(w) CNV_END_SHORT(w) // endianess conversion needed
+#define CNV_LITTLE_TO_SHORT(w) (w) // no endianness conversion needed
+#define CNV_BIG_TO_SHORT(w) CNV_END_SHORT(w) // endianness conversion needed
#define CNV_LITTLE_TO_LONG(dw) (dw)
#define CNV_LONG_TO_LITTLE(dw) (dw)
diff --git a/drivers/staging/wlags49_h2/mmd.c b/drivers/staging/wlags49_h2/mmd.c
index c8f52107e6ca..7204a373bc51 100644
--- a/drivers/staging/wlags49_h2/mmd.c
+++ b/drivers/staging/wlags49_h2/mmd.c
@@ -101,10 +101,10 @@
* supp address of the supplier specification
*
* Description: mmd_check_comp is a support routine to check the compatibility between an actor and a
-* supplier. mmd_check_comp is independent of the endianess of the actp and supp structures. This is
+* supplier. mmd_check_comp is independent of the endianness of the actp and supp structures. This is
* achieved by checking the "bottom" or "role" fields of these structures. Since these fields are restricted
* to a limited range, comparing the contents to a value with a known endian-ess gives a clue to their actual
-* endianess.
+* endianness.
*
*.DIAGRAM
*1a: The role-field of the actor structure has a known non-zero, not "byte symmetric" value (namely
@@ -114,16 +114,16 @@
* for a supplier. A supplier has always exactly 1 variant,top,bottom record with (officially, but see the
* note below) each of these 3 values in the range 1 through 99, so one byte of the word value of variant,
* top and bottom words is 0x00 and the other byte is non-zero. Whether the lowest address byte or the
-* highest address byte is non-zero depends on the Endianess of the LTV. If and only if the word value of
+* highest address byte is non-zero depends on the Endianness of the LTV. If and only if the word value of
* bottom is less than 0x0100, the supplier is Native Endian.
* NOTE: the variant field of the supplier structure can not be used for the Endian Detection Algorithm,
* because a a zero-valued variant has been used as Controlled Deployment indication in the past.
* Note: An actor may have multiple sets of variant,top,bottom records, including dummy sets with variant,
-* top and bottom fields with a zero-value. As a consequence the endianess of the actor can not be determined
+* top and bottom fields with a zero-value. As a consequence the endianness of the actor can not be determined
* based on its variant,top,bottom values.
*
* Note: the L and T field of the structures are always in Native Endian format, so you can not draw
-* conclusions concerning the Endianess of the structure based on these two fields.
+* conclusions concerning the Endianness of the structure based on these two fields.
*
*1b/2b
* The only purpose of the CFG_RANGE_SPEC_BYTE_STRCT is to give easy access to the non-zero byte of the word
@@ -149,7 +149,7 @@
*
* This is implemented as:
* #if HCF_BIG_ENDIAN == 0 //platform is LE
-* sup/act_endian becomes reverse of structure-endianess as determined in 1a/1b
+* sup/act_endian becomes reverse of structure-endianness as determined in 1a/1b
* #endif
*6: Each of the actor variant-bottom-top records is checked against the (single) supplier variant-bottom-top
* range till either an acceptable match is found or all actor records are tried. As explained above, due to
diff --git a/drivers/staging/wlags49_h2/wl_cs.c b/drivers/staging/wlags49_h2/wl_cs.c
index 7084f414846e..7c7c77f9c862 100644
--- a/drivers/staging/wlags49_h2/wl_cs.c
+++ b/drivers/staging/wlags49_h2/wl_cs.c
@@ -177,10 +177,9 @@ static void wl_adapter_detach(struct pcmcia_device *link)
if (dev) {
unregister_wlags_sysfs(dev);
unregister_netdev(dev);
+ wl_device_dealloc(dev);
}
- wl_device_dealloc(dev);
-
DBG_LEAVE(DbgInfo);
} /* wl_adapter_detach */
/*============================================================================*/
diff --git a/drivers/staging/wlags49_h2/wl_netdev.c b/drivers/staging/wlags49_h2/wl_netdev.c
index 90820ff1aced..824b85232353 100644
--- a/drivers/staging/wlags49_h2/wl_netdev.c
+++ b/drivers/staging/wlags49_h2/wl_netdev.c
@@ -1063,7 +1063,7 @@ void wl_multicast( struct net_device *dev )
#if DBG
if( DBG_FLAGS( DbgInfo ) & DBG_PARAM_ON ) {
DBG_PRINT(" flags: %s%s%s\n",
- ( dev->flags & IFF_PROMISC ) ? "Promiscous " : "",
+ ( dev->flags & IFF_PROMISC ) ? "Promiscuous " : "",
( dev->flags & IFF_MULTICAST ) ? "Multicast " : "",
( dev->flags & IFF_ALLMULTI ) ? "All-Multicast" : "" );
@@ -1510,8 +1510,11 @@ void wl_wds_device_alloc( struct wl_private *lp )
for( count = 0; count < NUM_WDS_PORTS; count++ ) {
struct net_device *dev_wds = NULL;
- dev_wds = kmalloc( sizeof( struct net_device ), GFP_KERNEL );
- memset( dev_wds, 0, sizeof( struct net_device ));
+ dev_wds = kzalloc(sizeof(struct net_device), GFP_KERNEL);
+ if (!dev_wds) {
+ DBG_LEAVE(DbgInfo);
+ return;
+ }
ether_setup( dev_wds );
diff --git a/drivers/staging/wlags49_h2/wl_pci.c b/drivers/staging/wlags49_h2/wl_pci.c
index 3df990c7306a..0b31b01bd490 100644
--- a/drivers/staging/wlags49_h2/wl_pci.c
+++ b/drivers/staging/wlags49_h2/wl_pci.c
@@ -524,6 +524,7 @@ int wl_pci_setup( struct pci_dev *pdev )
/* Make sure that space was allocated for our private adapter struct */
if( dev->priv == NULL ) {
DBG_ERROR( DbgInfo, "Private adapter struct was not allocated!!!\n" );
+ wl_device_dealloc(dev);
DBG_LEAVE( DbgInfo );
return -ENOMEM;
}
@@ -532,6 +533,7 @@ int wl_pci_setup( struct pci_dev *pdev )
/* Allocate DMA Descriptors */
if( wl_pci_dma_alloc( pdev, dev->priv ) < 0 ) {
DBG_ERROR( DbgInfo, "Could not allocate DMA descriptor memory!!!\n" );
+ wl_device_dealloc(dev);
DBG_LEAVE( DbgInfo );
return -ENOMEM;
}
@@ -561,6 +563,8 @@ int wl_pci_setup( struct pci_dev *pdev )
result = request_irq(dev->irq, wl_isr, SA_SHIRQ, dev->name, dev);
if( result ) {
DBG_WARNING( DbgInfo, "Could not register ISR!!!\n" );
+ wl_remove(dev);
+ wl_device_dealloc(dev);
DBG_LEAVE( DbgInfo );
return result;
}
diff --git a/drivers/staging/wlags49_h2/wl_profile.c b/drivers/staging/wlags49_h2/wl_profile.c
index b8c96cf18de5..0e49272bc7a8 100644
--- a/drivers/staging/wlags49_h2/wl_profile.c
+++ b/drivers/staging/wlags49_h2/wl_profile.c
@@ -401,7 +401,7 @@ void translate_option(char *buffer, struct wl_private *lp)
if ((value_convert >= PARM_MIN_BRSC) || (value_convert <= PARM_MAX_BRSC))
lp->brsc[0] = value_convert;
else
- DBG_WARNING(DbgInfo, "%s invaid; will be ignored\n", PARM_NAME_BRSC_2GHZ);
+ DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_BRSC_2GHZ);
} else if (strcmp(key, PARM_NAME_BRSC_5GHZ) == 0) {
DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_BRSC_5GHZ, value);
@@ -409,7 +409,7 @@ void translate_option(char *buffer, struct wl_private *lp)
if ((value_convert >= PARM_MIN_BRSC) || (value_convert <= PARM_MAX_BRSC))
lp->brsc[1] = value_convert;
else
- DBG_WARNING(DbgInfo, "%s invaid; will be ignored\n", PARM_NAME_BRSC_5GHZ);
+ DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_BRSC_5GHZ);
} else if ((strcmp(key, PARM_NAME_DESIRED_SSID) == 0) || (strcmp(key, PARM_NAME_OWN_SSID) == 0)) {
DBG_TRACE(DbgInfo, "SSID, value: %s\n", value);
@@ -556,7 +556,7 @@ void translate_option(char *buffer, struct wl_private *lp)
if ((value_convert >= PARM_MIN_SRSC) || (value_convert <= PARM_MAX_SRSC))
lp->srsc[0] = value_convert;
else
- DBG_WARNING(DbgInfo, "%s invaid; will be ignored\n", PARM_NAME_SRSC_2GHZ);
+ DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_SRSC_2GHZ);
} else if (strcmp(key, PARM_NAME_SRSC_5GHZ) == 0) {
DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_SRSC_5GHZ, value);
@@ -564,7 +564,7 @@ void translate_option(char *buffer, struct wl_private *lp)
if ((value_convert >= PARM_MIN_SRSC) || (value_convert <= PARM_MAX_SRSC))
lp->srsc[1] = value_convert;
else
- DBG_WARNING(DbgInfo, "%s invaid; will be ignored\n", PARM_NAME_SRSC_5GHZ);
+ DBG_WARNING(DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_SRSC_5GHZ);
} else if (strcmp(key, PARM_NAME_SYSTEM_SCALE) == 0) {
DBG_TRACE(DbgInfo, "%s, value: %s\n", PARM_NAME_SYSTEM_SCALE, value);
diff --git a/drivers/staging/wlags49_h2/wl_util.c b/drivers/staging/wlags49_h2/wl_util.c
index f104e6f1e980..404ec7da0348 100644
--- a/drivers/staging/wlags49_h2/wl_util.c
+++ b/drivers/staging/wlags49_h2/wl_util.c
@@ -98,8 +98,7 @@
******************************************************************************/
/* A matrix which maps channels to frequencies */
-#define MAX_CHAN_FREQ_MAP_ENTRIES 50
-static const long chan_freq_list[][MAX_CHAN_FREQ_MAP_ENTRIES] =
+static const long chan_freq_list[][2] =
{
{1,2412},
{2,2417},
@@ -846,7 +845,7 @@ int wl_is_a_valid_chan( int channel )
}
/* Iterate through the matrix and retrieve the frequency */
- for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
+ for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
if( chan_freq_list[i][0] == channel ) {
return 1;
}
@@ -884,7 +883,7 @@ int wl_is_a_valid_freq( long frequency )
/* Iterate through the matrix and retrieve the channel */
- for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
+ for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
if( chan_freq_list[i][1] == frequency ) {
return 1;
}
@@ -927,7 +926,7 @@ long wl_get_freq_from_chan( int channel )
}
/* Iterate through the matrix and retrieve the frequency */
- for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
+ for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
if( chan_freq_list[i][0] == channel ) {
return chan_freq_list[i][1];
}
@@ -965,7 +964,7 @@ int wl_get_chan_from_freq( long frequency )
/* Iterate through the matrix and retrieve the channel */
- for( i = 0; i < MAX_CHAN_FREQ_MAP_ENTRIES; i++ ) {
+ for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
if( chan_freq_list[i][1] == frequency ) {
return chan_freq_list[i][0];
}
diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c
index 4cd3ba5d5646..8bc562b8c4d9 100644
--- a/drivers/staging/wlan-ng/cfg80211.c
+++ b/drivers/staging/wlan-ng/cfg80211.c
@@ -332,6 +332,7 @@ int prism2_scan(struct wiphy *wiphy, struct net_device *dev,
wlandevice_t *wlandev = dev->ml_priv;
struct p80211msg_dot11req_scan msg1;
struct p80211msg_dot11req_scan_results msg2;
+ struct cfg80211_bss *bss;
int result;
int err = 0;
int numbss = 0;
@@ -401,7 +402,7 @@ int prism2_scan(struct wiphy *wiphy, struct net_device *dev,
ie_buf[1] = msg2.ssid.data.len;
ie_len = ie_buf[1] + 2;
memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len);
- cfg80211_inform_bss(wiphy,
+ bss = cfg80211_inform_bss(wiphy,
ieee80211_get_channel(wiphy, ieee80211_dsss_chan_to_freq(msg2.dschannel.data)),
(const u8 *) &(msg2.bssid.data.data),
msg2.timestamp.data, msg2.capinfo.data,
@@ -411,6 +412,13 @@ int prism2_scan(struct wiphy *wiphy, struct net_device *dev,
(msg2.signal.data - 65536) * 100, /* Conversion to signed type */
GFP_KERNEL
);
+
+ if (!bss) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ cfg80211_put_bss(bss);
}
if (result)
diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c
index c3bb05dd744f..4efa9bc0fcf0 100644
--- a/drivers/staging/wlan-ng/prism2mgmt.c
+++ b/drivers/staging/wlan-ng/prism2mgmt.c
@@ -380,8 +380,8 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
}
count = (hw->scanresults->framelen - 3) / 32;
- if (count > 32)
- count = 32;
+ if (count > HFA384x_SCANRESULT_MAX)
+ count = HFA384x_SCANRESULT_MAX;
if (req->bssindex.data >= count) {
pr_debug("requested index (%d) out of range (%d)\n",
diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h
index e828fd403c35..9c62aeb9ede9 100644
--- a/drivers/staging/xgifb/XGI_main.h
+++ b/drivers/staging/xgifb/XGI_main.h
@@ -12,9 +12,6 @@
#define XGIFAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
-#ifndef PCI_DEVICE_ID_XGI_41
-#define PCI_DEVICE_ID_XGI_41 0x041
-#endif
#ifndef PCI_DEVICE_ID_XGI_42
#define PCI_DEVICE_ID_XGI_42 0x042
#endif
@@ -82,177 +79,79 @@ static int XGIfb_tvplug = -1;
/* TW: For ioctl XGIFB_GET_INFO */
/* XGIfb_info XGIfbinfo; */
-#define MD_XGI300 1
-#define MD_XGI315 2
+#define MD_XGI315 1
/* mode table */
static const struct _XGIbios_mode {
- char name[15];
u8 mode_no;
u16 vesa_mode_no_1; /* "XGI defined" VESA mode number */
u16 vesa_mode_no_2; /* Real VESA mode numbers */
u16 xres;
u16 yres;
u16 bpp;
- u16 rate_idx;
- u16 cols;
- u16 rows;
u8 chipset;
} XGIbios_mode[] = {
- {"320x240x16", 0x56, 0x0000, 0x0000, 320, 240, 16, 1, 40, 15,
- MD_XGI315},
- {"320x480x8", 0x5A, 0x0000, 0x0000, 320, 480, 8, 1, 40, 30,
- MD_XGI315}, /* TW: FSTN */
- {"320x480x16", 0x5B, 0x0000, 0x0000, 320, 480, 16, 1, 40, 30,
- MD_XGI315}, /* TW: FSTN */
- {"640x480x8", 0x2E, 0x0101, 0x0101, 640, 480, 8, 1, 80, 30,
- MD_XGI300|MD_XGI315},
- {"640x480x16", 0x44, 0x0111, 0x0111, 640, 480, 16, 1, 80, 30,
- MD_XGI300|MD_XGI315},
- {"640x480x24", 0x62, 0x013a, 0x0112, 640, 480, 32, 1, 80, 30,
- MD_XGI300|MD_XGI315}, /* TW: That's for people who mix up color-
- and fb depth */
- {"640x480x32", 0x62, 0x013a, 0x0112, 640, 480, 32, 1, 80, 30,
- MD_XGI300|MD_XGI315},
- {"720x480x8", 0x31, 0x0000, 0x0000, 720, 480, 8, 1, 90, 30,
- MD_XGI300|MD_XGI315},
- {"720x480x16", 0x33, 0x0000, 0x0000, 720, 480, 16, 1, 90, 30,
- MD_XGI300|MD_XGI315},
- {"720x480x24", 0x35, 0x0000, 0x0000, 720, 480, 32, 1, 90, 30,
- MD_XGI300|MD_XGI315},
- {"720x480x32", 0x35, 0x0000, 0x0000, 720, 480, 32, 1, 90, 30,
- MD_XGI300|MD_XGI315},
- {"720x576x8", 0x32, 0x0000, 0x0000, 720, 576, 8, 1, 90, 36,
- MD_XGI300|MD_XGI315},
- {"720x576x16", 0x34, 0x0000, 0x0000, 720, 576, 16, 1, 90, 36,
- MD_XGI300|MD_XGI315},
- {"720x576x24", 0x36, 0x0000, 0x0000, 720, 576, 32, 1, 90, 36,
- MD_XGI300|MD_XGI315},
- {"720x576x32", 0x36, 0x0000, 0x0000, 720, 576, 32, 1, 90, 36,
- MD_XGI300|MD_XGI315},
- {"800x480x8", 0x70, 0x0000, 0x0000, 800, 480, 8, 1, 100, 30,
- MD_XGI300|MD_XGI315},
- {"800x480x16", 0x7a, 0x0000, 0x0000, 800, 480, 16, 1, 100, 30,
- MD_XGI300|MD_XGI315},
- {"800x480x24", 0x76, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30,
- MD_XGI300|MD_XGI315},
- {"800x480x32", 0x76, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30,
- MD_XGI300|MD_XGI315},
- {"800x600x8", 0x30, 0x0103, 0x0103, 800, 600, 8, 1, 100, 37,
- MD_XGI300|MD_XGI315},
-#define DEFAULT_MODE 20 /* index for 800x600x16 */
- {"800x600x16", 0x47, 0x0114, 0x0114, 800, 600, 16, 1, 100, 37,
- MD_XGI300|MD_XGI315},
- {"800x600x24", 0x63, 0x013b, 0x0115, 800, 600, 32, 1, 100, 37,
- MD_XGI300|MD_XGI315},
- {"800x600x32", 0x63, 0x013b, 0x0115, 800, 600, 32, 1, 100, 37,
- MD_XGI300|MD_XGI315},
- {"1024x576x8", 0x71, 0x0000, 0x0000, 1024, 576, 8, 1, 128, 36,
- MD_XGI300|MD_XGI315},
- {"1024x576x16", 0x74, 0x0000, 0x0000, 1024, 576, 16, 1, 128, 36,
- MD_XGI300|MD_XGI315},
- {"1024x576x24", 0x77, 0x0000, 0x0000, 1024, 576, 32, 1, 128, 36,
- MD_XGI300|MD_XGI315},
- {"1024x576x32", 0x77, 0x0000, 0x0000, 1024, 576, 32, 1, 128, 36,
- MD_XGI300|MD_XGI315},
- {"1024x600x8", 0x20, 0x0000, 0x0000, 1024, 600, 8, 1, 128, 37,
- MD_XGI300 }, /* TW: 300 series only */
- {"1024x600x16", 0x21, 0x0000, 0x0000, 1024, 600, 16, 1, 128, 37,
- MD_XGI300 },
- {"1024x600x24", 0x22, 0x0000, 0x0000, 1024, 600, 32, 1, 128, 37,
- MD_XGI300 },
- {"1024x600x32", 0x22, 0x0000, 0x0000, 1024, 600, 32, 1, 128, 37,
- MD_XGI300 },
- {"1024x768x8", 0x38, 0x0105, 0x0105, 1024, 768, 8, 1, 128, 48,
- MD_XGI300|MD_XGI315},
- {"1024x768x16", 0x4A, 0x0117, 0x0117, 1024, 768, 16, 1, 128, 48,
- MD_XGI300|MD_XGI315},
- {"1024x768x24", 0x64, 0x013c, 0x0118, 1024, 768, 32, 1, 128, 48,
- MD_XGI300|MD_XGI315},
- {"1024x768x32", 0x64, 0x013c, 0x0118, 1024, 768, 32, 1, 128, 48,
- MD_XGI300|MD_XGI315},
- {"1152x768x8", 0x23, 0x0000, 0x0000, 1152, 768, 8, 1, 144, 48,
- MD_XGI300 }, /* TW: 300 series only */
- {"1152x768x16", 0x24, 0x0000, 0x0000, 1152, 768, 16, 1, 144, 48,
- MD_XGI300 },
- {"1152x768x24", 0x25, 0x0000, 0x0000, 1152, 768, 32, 1, 144, 48,
- MD_XGI300 },
- {"1152x768x32", 0x25, 0x0000, 0x0000, 1152, 768, 32, 1, 144, 48,
- MD_XGI300 },
- {"1280x720x8", 0x79, 0x0000, 0x0000, 1280, 720, 8, 1, 160, 45,
- MD_XGI300|MD_XGI315},
- {"1280x720x16", 0x75, 0x0000, 0x0000, 1280, 720, 16, 1, 160, 45,
- MD_XGI300|MD_XGI315},
- {"1280x720x24", 0x78, 0x0000, 0x0000, 1280, 720, 32, 1, 160, 45,
- MD_XGI300|MD_XGI315},
- {"1280x720x32", 0x78, 0x0000, 0x0000, 1280, 720, 32, 1, 160, 45,
- MD_XGI300|MD_XGI315},
- {"1280x768x8", 0x23, 0x0000, 0x0000, 1280, 768, 8, 1, 160, 48,
- MD_XGI315}, /* TW: 310/325 series only */
- {"1280x768x16", 0x24, 0x0000, 0x0000, 1280, 768, 16, 1, 160, 48,
- MD_XGI315},
- {"1280x768x24", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48,
- MD_XGI315},
- {"1280x768x32", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48,
- MD_XGI315},
- {"1280x960x8", 0x7C, 0x0000, 0x0000, 1280, 960, 8, 1, 160, 60,
- MD_XGI300|MD_XGI315},
- {"1280x960x16", 0x7D, 0x0000, 0x0000, 1280, 960, 16, 1, 160, 60,
- MD_XGI300|MD_XGI315},
- {"1280x960x24", 0x7E, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60,
- MD_XGI300|MD_XGI315},
- {"1280x960x32", 0x7E, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60,
- MD_XGI300|MD_XGI315},
- {"1280x1024x8", 0x3A, 0x0107, 0x0107, 1280, 1024, 8, 1, 160, 64,
- MD_XGI300|MD_XGI315},
- {"1280x1024x16", 0x4D, 0x011a, 0x011a, 1280, 1024, 16, 1, 160, 64,
- MD_XGI300|MD_XGI315},
- {"1280x1024x24", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 1, 160, 64,
- MD_XGI300|MD_XGI315},
- {"1280x1024x32", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 1, 160, 64,
- MD_XGI300|MD_XGI315},
- {"1400x1050x8", 0x26, 0x0000, 0x0000, 1400, 1050, 8, 1, 175, 65,
- MD_XGI315}, /* TW: 310/325 series only */
- {"1400x1050x16", 0x27, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65,
- MD_XGI315},
- {"1400x1050x24", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,
- MD_XGI315},
- {"1400x1050x32", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,
- MD_XGI315},
- {"1600x1200x8", 0x3C, 0x0130, 0x011c, 1600, 1200, 8, 1, 200, 75,
- MD_XGI300|MD_XGI315},
- {"1600x1200x16", 0x3D, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75,
- MD_XGI300|MD_XGI315},
- {"1600x1200x24", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75,
- MD_XGI300|MD_XGI315},
- {"1600x1200x32", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75,
- MD_XGI300|MD_XGI315},
- {"1920x1440x8", 0x68, 0x013f, 0x0000, 1920, 1440, 8, 1, 240, 75,
- MD_XGI300|MD_XGI315},
- {"1920x1440x16", 0x69, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75,
- MD_XGI300|MD_XGI315},
- {"1920x1440x24", 0x6B, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75,
- MD_XGI300|MD_XGI315},
- {"1920x1440x32", 0x6B, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75,
- MD_XGI300|MD_XGI315},
- {"2048x1536x8", 0x6c, 0x0000, 0x0000, 2048, 1536, 8, 1, 256, 96,
- MD_XGI315}, /* TW: 310/325 series only */
- {"2048x1536x16", 0x6d, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96,
- MD_XGI315},
- {"2048x1536x24", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,
- MD_XGI315},
- {"2048x1536x32", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,
- MD_XGI315},
- {"\0", 0x00, 0, 0, 0, 0, 0, 0, 0}
+ { 0x56, 0x0000, 0x0000, 320, 240, 16, MD_XGI315 },
+ { 0x5A, 0x0000, 0x0000, 320, 480, 8, MD_XGI315 },
+ { 0x5B, 0x0000, 0x0000, 320, 480, 16, MD_XGI315 },
+ { 0x2E, 0x0101, 0x0101, 640, 480, 8, MD_XGI315 },
+ { 0x44, 0x0111, 0x0111, 640, 480, 16, MD_XGI315 },
+ { 0x62, 0x013a, 0x0112, 640, 480, 32, MD_XGI315 },
+ { 0x31, 0x0000, 0x0000, 720, 480, 8, MD_XGI315 },
+ { 0x33, 0x0000, 0x0000, 720, 480, 16, MD_XGI315 },
+ { 0x35, 0x0000, 0x0000, 720, 480, 32, MD_XGI315 },
+ { 0x32, 0x0000, 0x0000, 720, 576, 8, MD_XGI315 },
+ { 0x34, 0x0000, 0x0000, 720, 576, 16, MD_XGI315 },
+ { 0x36, 0x0000, 0x0000, 720, 576, 32, MD_XGI315 },
+ { 0x36, 0x0000, 0x0000, 720, 576, 32, MD_XGI315 },
+ { 0x70, 0x0000, 0x0000, 800, 480, 8, MD_XGI315 },
+ { 0x7a, 0x0000, 0x0000, 800, 480, 16, MD_XGI315 },
+ { 0x76, 0x0000, 0x0000, 800, 480, 32, MD_XGI315 },
+ { 0x30, 0x0103, 0x0103, 800, 600, 8, MD_XGI315 },
+#define DEFAULT_MODE 17 /* index for 800x600x16 */
+ { 0x47, 0x0114, 0x0114, 800, 600, 16, MD_XGI315 },
+ { 0x63, 0x013b, 0x0115, 800, 600, 32, MD_XGI315 },
+ { 0x71, 0x0000, 0x0000, 1024, 576, 8, MD_XGI315 },
+ { 0x74, 0x0000, 0x0000, 1024, 576, 16, MD_XGI315 },
+ { 0x77, 0x0000, 0x0000, 1024, 576, 32, MD_XGI315 },
+ { 0x77, 0x0000, 0x0000, 1024, 576, 32, MD_XGI315 },
+ { 0x20, 0x0000, 0x0000, 1024, 600, 8, },
+ { 0x21, 0x0000, 0x0000, 1024, 600, 16, },
+ { 0x22, 0x0000, 0x0000, 1024, 600, 32, },
+ { 0x38, 0x0105, 0x0105, 1024, 768, 8, MD_XGI315 },
+ { 0x4A, 0x0117, 0x0117, 1024, 768, 16, MD_XGI315 },
+ { 0x64, 0x013c, 0x0118, 1024, 768, 32, MD_XGI315 },
+ { 0x64, 0x013c, 0x0118, 1024, 768, 32, MD_XGI315 },
+ { 0x23, 0x0000, 0x0000, 1152, 768, 8, },
+ { 0x24, 0x0000, 0x0000, 1152, 768, 16, },
+ { 0x25, 0x0000, 0x0000, 1152, 768, 32, },
+ { 0x79, 0x0000, 0x0000, 1280, 720, 8, MD_XGI315 },
+ { 0x75, 0x0000, 0x0000, 1280, 720, 16, MD_XGI315 },
+ { 0x78, 0x0000, 0x0000, 1280, 720, 32, MD_XGI315 },
+ { 0x23, 0x0000, 0x0000, 1280, 768, 8, MD_XGI315 },
+ { 0x24, 0x0000, 0x0000, 1280, 768, 16, MD_XGI315 },
+ { 0x25, 0x0000, 0x0000, 1280, 768, 32, MD_XGI315 },
+ { 0x7C, 0x0000, 0x0000, 1280, 960, 8, MD_XGI315 },
+ { 0x7D, 0x0000, 0x0000, 1280, 960, 16, MD_XGI315 },
+ { 0x7E, 0x0000, 0x0000, 1280, 960, 32, MD_XGI315 },
+ { 0x3A, 0x0107, 0x0107, 1280, 1024, 8, MD_XGI315 },
+ { 0x4D, 0x011a, 0x011a, 1280, 1024, 16, MD_XGI315 },
+ { 0x65, 0x013d, 0x011b, 1280, 1024, 32, MD_XGI315 },
+ { 0x26, 0x0000, 0x0000, 1400, 1050, 8, MD_XGI315 },
+ { 0x27, 0x0000, 0x0000, 1400, 1050, 16, MD_XGI315 },
+ { 0x28, 0x0000, 0x0000, 1400, 1050, 32, MD_XGI315 },
+ { 0x3C, 0x0130, 0x011c, 1600, 1200, 8, MD_XGI315 },
+ { 0x3D, 0x0131, 0x011e, 1600, 1200, 16, MD_XGI315 },
+ { 0x66, 0x013e, 0x011f, 1600, 1200, 32, MD_XGI315 },
+ { 0x68, 0x013f, 0x0000, 1920, 1440, 8, MD_XGI315 },
+ { 0x69, 0x0140, 0x0000, 1920, 1440, 16, MD_XGI315 },
+ { 0x6B, 0x0141, 0x0000, 1920, 1440, 32, MD_XGI315 },
+ { 0x6c, 0x0000, 0x0000, 2048, 1536, 8, MD_XGI315 },
+ { 0x6d, 0x0000, 0x0000, 2048, 1536, 16, MD_XGI315 },
+ { 0x6e, 0x0000, 0x0000, 2048, 1536, 32, MD_XGI315 },
+ { 0 },
};
-/* TW: CR36 evaluation */
-static const unsigned short XGI300paneltype[] = {
- LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
- LCD_1280x960, LCD_640x480, LCD_1024x600, LCD_1152x768,
- LCD_1024x768, LCD_1024x768, LCD_1024x768,
- LCD_1024x768, LCD_1024x768, LCD_1024x768, LCD_1024x768};
-
static const unsigned short XGI310paneltype[] = {
LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
index 21c037827de4..85dbf32b1f66 100644
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -156,25 +156,14 @@ static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
unsigned short ModeNo = modeno;
unsigned short ModeIdIndex = 0, ClockIndex = 0;
unsigned short RefreshRateTableIndex = 0;
-
- /* unsigned long temp = 0; */
int Clock;
InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
+ XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
+
RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
ModeIdIndex, XGI_Pr);
- /*
- temp = XGI_SearchModeID(ModeNo , &ModeIdIndex, XGI_Pr) ;
- if (!temp) {
- printk(KERN_ERR "Could not find mode %x\n", ModeNo);
- return 65000;
- }
-
- RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
- RefreshRateTableIndex += (rateindex - 1);
-
- */
ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
@@ -190,7 +179,7 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
u32 *vmode)
{
unsigned short ModeNo = modeno;
- unsigned short ModeIdIndex = 0, index = 0;
+ unsigned short ModeIdIndex, index = 0;
unsigned short RefreshRateTableIndex = 0;
unsigned short VRE, VBE, VRS, VBS, VDE, VT;
@@ -199,16 +188,10 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
unsigned long cr_data3;
int A, B, C, D, E, F, temp, j;
InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
+ if (!XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr))
+ return 0;
RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
ModeIdIndex, XGI_Pr);
- /*
- temp = XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
- if (!temp)
- return 0;
-
- RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
- RefreshRateTableIndex += (rateindex - 1);
- */
index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
@@ -219,12 +202,6 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
HT = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8);
A = HT + 5;
- /*
- cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
-
- Horizontal display enable end
- HDE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x0C) << 6);
- */
HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) - 1;
E = HDE + 1;
@@ -358,7 +335,6 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
{
- XGI_Pr->RelIO = BaseAddr;
XGI_Pr->P3c4 = BaseAddr + 0x14;
XGI_Pr->P3d4 = BaseAddr + 0x24;
XGI_Pr->P3c0 = BaseAddr + 0x10;
@@ -414,19 +390,26 @@ static int XGIfb_GetXG21DefaultLVDSModeIdx(struct xgifb_video_info *xgifb_info)
static void XGIfb_search_mode(struct xgifb_video_info *xgifb_info,
const char *name)
{
- int i = 0, j = 0, l;
+ unsigned int xres;
+ unsigned int yres;
+ unsigned int bpp;
+ int i;
- while (XGIbios_mode[i].mode_no != 0) {
- l = min(strlen(name), strlen(XGIbios_mode[i].name));
- if (!strncmp(name, XGIbios_mode[i].name, l)) {
+ if (sscanf(name, "%ux%ux%u", &xres, &yres, &bpp) != 3)
+ goto invalid_mode;
+
+ if (bpp == 24)
+ bpp = 32; /* That's for people who mix up color and fb depth. */
+
+ for (i = 0; XGIbios_mode[i].mode_no != 0; i++)
+ if (XGIbios_mode[i].xres == xres &&
+ XGIbios_mode[i].yres == yres &&
+ XGIbios_mode[i].bpp == bpp) {
xgifb_info->mode_idx = i;
- j = 1;
- break;
+ return;
}
- i++;
- }
- if (!j)
- pr_info("Invalid mode '%s'\n", name);
+invalid_mode:
+ pr_info("Invalid mode '%s'\n", name);
}
static void XGIfb_search_vesamode(struct xgifb_video_info *xgifb_info,
@@ -1088,7 +1071,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
+ var->vsync_len;
#if defined(__powerpc__)
- u8 sr_data, cr_data;
+ u8 cr_data;
#endif
unsigned int drate = 0, hrate = 0;
int found_mode = 0;
@@ -1162,8 +1145,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
if (XGIfb_search_refresh_rate(xgifb_info,
xgifb_info->refresh_rate) == 0) {
- xgifb_info->rate_idx =
- XGIbios_mode[xgifb_info->mode_idx].rate_idx;
+ xgifb_info->rate_idx = 1;
xgifb_info->refresh_rate = 60;
}
@@ -1680,17 +1662,6 @@ static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info)
ChannelNum = 1;
break;
- case XG45:
- if (tmp == 1)
- ChannelNum = 2;
- else if (tmp == 2)
- ChannelNum = 3;
- else if (tmp == 3)
- ChannelNum = 4;
- else
- ChannelNum = 1;
- break;
-
case XG40:
default:
if (tmp == 2)
@@ -1911,11 +1882,9 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
xgifb_info->mmio_base = pci_resource_start(pdev, 1);
xgifb_info->mmio_size = pci_resource_len(pdev, 1);
xgifb_info->vga_base = pci_resource_start(pdev, 2) + 0x30;
- hw_info->pjIOAddress = (unsigned char *)xgifb_info->vga_base;
- /* XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
- pr_info("Relocate IO address: %lx [%08lx]\n",
- (unsigned long)pci_resource_start(pdev, 2),
- xgifb_info->dev_info.RelIO);
+ pr_info("Relocate IO address: %Lx [%08lx]\n",
+ (u64) pci_resource_start(pdev, 2),
+ xgifb_info->vga_base);
if (pci_enable_device(pdev)) {
ret = -EIO;
@@ -1927,7 +1896,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
xgifb_info->display2_force = true;
}
- XGIRegInit(&xgifb_info->dev_info, (unsigned long)hw_info->pjIOAddress);
+ XGIRegInit(&xgifb_info->dev_info, xgifb_info->vga_base);
xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
reg1 = xgifb_reg_get(XGISR, IND_SIS_PASSWORD);
@@ -1950,9 +1919,6 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
case PCI_DEVICE_ID_XGI_40:
xgifb_info->chip = XG40;
break;
- case PCI_DEVICE_ID_XGI_41:
- xgifb_info->chip = XG41;
- break;
case PCI_DEVICE_ID_XGI_42:
xgifb_info->chip = XG42;
break;
@@ -2006,13 +1972,13 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
xgifb_info->mmio_vbase = ioremap(xgifb_info->mmio_base,
xgifb_info->mmio_size);
- pr_info("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
- xgifb_info->video_base,
+ pr_info("Framebuffer at 0x%Lx, mapped to 0x%p, size %dk\n",
+ (u64) xgifb_info->video_base,
xgifb_info->video_vbase,
xgifb_info->video_size / 1024);
- pr_info("MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
- xgifb_info->mmio_base, xgifb_info->mmio_vbase,
+ pr_info("MMIO at 0x%Lx, mapped to 0x%p, size %ldk\n",
+ (u64) xgifb_info->mmio_base, xgifb_info->mmio_vbase,
xgifb_info->mmio_size / 1024);
pci_set_drvdata(pdev, xgifb_info);
@@ -2174,8 +2140,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
xgifb_info->refresh_rate = 60;
if (XGIfb_search_refresh_rate(xgifb_info,
xgifb_info->refresh_rate) == 0) {
- xgifb_info->rate_idx =
- XGIbios_mode[xgifb_info->mode_idx].rate_idx;
+ xgifb_info->rate_idx = 1;
xgifb_info->refresh_rate = 60;
}
diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h
index 37bb730de047..9068c5ad76ec 100644
--- a/drivers/staging/xgifb/XGIfb.h
+++ b/drivers/staging/xgifb/XGIfb.h
@@ -23,9 +23,7 @@ enum xgifb_display_type {
enum XGI_CHIP_TYPE {
XG40 = 32,
- XG41,
XG42,
- XG45,
XG20 = 48,
XG21,
XG27,
@@ -66,9 +64,9 @@ struct xgifb_video_info {
int chip_id;
unsigned int video_size;
- unsigned long video_base;
+ phys_addr_t video_base;
void __iomem *video_vbase;
- unsigned long mmio_base;
+ phys_addr_t mmio_base;
unsigned long mmio_size;
void __iomem *mmio_vbase;
unsigned long vga_base;
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
index 3650bbff7686..c222d611431d 100644
--- a/drivers/staging/xgifb/vb_init.c
+++ b/drivers/staging/xgifb/vb_init.c
@@ -353,7 +353,6 @@ static void XGINew_DDR1x_DefaultRegister(
XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo);
switch (HwDeviceExtension->jChipType) {
- case XG41:
case XG42:
/* CR82 */
xgifb_reg_set(P3d4,
@@ -556,8 +555,7 @@ static void XGINew_SetDRAMDefaultRegister340(
xgifb_reg_set(P3d4, (0x8A + j),
pVBInfo->CR40[1 + j][pVBInfo->ram_type]);
- if ((HwDeviceExtension->jChipType == XG41) ||
- (HwDeviceExtension->jChipType == XG42))
+ if (HwDeviceExtension->jChipType == XG42)
xgifb_reg_set(P3d4, 0x8C, 0x87);
xgifb_reg_set(P3d4,
@@ -854,78 +852,6 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
pVBInfo->ram_channel = 1; /* Single channel */
xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x51); /* 32Mx16 bit*/
break;
- case XG41:
- if (XGINew_CheckFrequence(pVBInfo) == 1) {
- pVBInfo->ram_bus = 32; /* 32 bits */
- pVBInfo->ram_channel = 3; /* Quad Channel */
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x4C);
-
- if (XGINew_ReadWriteRest(25, 23, pVBInfo) == 1)
- return;
-
- pVBInfo->ram_channel = 2; /* Dual channels */
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x48);
-
- if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
- return;
-
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x49);
-
- if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
- return;
-
- pVBInfo->ram_channel = 3;
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x3C);
-
- if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
- return;
-
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x38);
-
- if (XGINew_ReadWriteRest(8, 4, pVBInfo) == 1)
- return;
- else
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x39);
- } else { /* DDR */
- pVBInfo->ram_bus = 64; /* 64 bits */
- pVBInfo->ram_channel = 2; /* Dual channels */
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x5A);
-
- if (XGINew_ReadWriteRest(25, 24, pVBInfo) == 1)
- return;
-
- pVBInfo->ram_channel = 1; /* Single channels */
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x52);
-
- if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
- return;
-
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x53);
-
- if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
- return;
-
- pVBInfo->ram_channel = 2; /* Dual channels */
- xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x4A);
-
- if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
- return;
-
- pVBInfo->ram_channel = 1; /* Single channels */
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x42);
-
- if (XGINew_ReadWriteRest(8, 4, pVBInfo) == 1)
- return;
- else
- xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x43);
- }
-
- break;
-
case XG42:
/*
XG42 SR14 D[3] Reserve
@@ -1478,7 +1404,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
- pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
+ pVBInfo->BaseAddr = xgifb_info->vga_base;
/* Newdebugcode(0x99); */
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
index 60d4adf99923..b2f4338b1109 100644
--- a/drivers/staging/xgifb/vb_setmode.c
+++ b/drivers/staging/xgifb/vb_setmode.c
@@ -16,36 +16,6 @@
#define IndexMask 0xff
-static const unsigned short XGINew_MDA_DAC[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F};
-
-static const unsigned short XGINew_CGA_DAC[] = {
- 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
- 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
- 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
- 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
- 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
- 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
- 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
- 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F};
-
-static const unsigned short XGINew_EGA_DAC[] = {
- 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15,
- 0x20, 0x30, 0x24, 0x34, 0x21, 0x31, 0x25, 0x35,
- 0x08, 0x18, 0x0C, 0x1C, 0x09, 0x19, 0x0D, 0x1D,
- 0x28, 0x38, 0x2C, 0x3C, 0x29, 0x39, 0x2D, 0x3D,
- 0x02, 0x12, 0x06, 0x16, 0x03, 0x13, 0x07, 0x17,
- 0x22, 0x32, 0x26, 0x36, 0x23, 0x33, 0x27, 0x37,
- 0x0A, 0x1A, 0x0E, 0x1E, 0x0B, 0x1B, 0x0F, 0x1F,
- 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F};
-
static const unsigned short XGINew_VGA_DAC[] = {
0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
@@ -60,8 +30,7 @@ static const unsigned short XGINew_VGA_DAC[] = {
void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
{
- pVBInfo->SModeIDTable = (struct XGI_StStruct *) XGI330_SModeIDTable;
- pVBInfo->StandTable = (struct SiS_StandTable_S *) XGI330_StandTable;
+ pVBInfo->StandTable = (struct SiS_StandTable_S *) &XGI330_StandTable;
pVBInfo->EModeIDTable = (struct XGI_ExtStruct *) XGI330_EModeIDTable;
pVBInfo->RefIndex = (struct XGI_Ext2Struct *) XGI330_RefIndex;
pVBInfo->XGINEWUB_CRT1Table
@@ -182,38 +151,17 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
}
-static unsigned char XGI_GetModePtr(unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct vb_device_info *pVBInfo)
-{
- unsigned char index;
-
- if (ModeNo <= 0x13)
- index = pVBInfo->SModeIDTable[ModeIdIndex].St_StTableIndex;
- else {
- if (pVBInfo->ModeType <= 0x02)
- index = 0x1B; /* 02 -> ModeEGA */
- else
- index = 0x0F;
- }
- return index; /* Get pVBInfo->StandTable index */
-}
-
static void XGI_SetSeqRegs(unsigned short ModeNo,
- unsigned short StandTableIndex,
unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
unsigned char tempah, SRdata;
unsigned short i, modeflag;
- if (ModeNo <= 0x13)
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
xgifb_reg_set(pVBInfo->P3c4, 0x00, 0x03); /* Set SR0 */
- tempah = pVBInfo->StandTable[StandTableIndex].SR[0];
+ tempah = pVBInfo->StandTable->SR[0];
i = XGI_SetCRT2ToLCDA;
if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
@@ -230,13 +178,12 @@ static void XGI_SetSeqRegs(unsigned short ModeNo,
for (i = 02; i <= 04; i++) {
/* Get SR2,3,4 from file */
- SRdata = pVBInfo->StandTable[StandTableIndex].SR[i - 1];
+ SRdata = pVBInfo->StandTable->SR[i - 1];
xgifb_reg_set(pVBInfo->P3c4, i, SRdata); /* Set SR2 3 4 */
}
}
static void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension,
- unsigned short StandTableIndex,
struct vb_device_info *pVBInfo)
{
unsigned char CRTCdata;
@@ -248,26 +195,22 @@ static void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension,
for (i = 0; i <= 0x18; i++) {
/* Get CRTC from file */
- CRTCdata = pVBInfo->StandTable[StandTableIndex].CRTC[i];
+ CRTCdata = pVBInfo->StandTable->CRTC[i];
xgifb_reg_set(pVBInfo->P3d4, i, CRTCdata); /* Set CRTC(3d4) */
}
}
static void XGI_SetATTRegs(unsigned short ModeNo,
- unsigned short StandTableIndex,
unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
unsigned char ARdata;
unsigned short i, modeflag;
- if (ModeNo <= 0x13)
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
for (i = 0; i <= 0x13; i++) {
- ARdata = pVBInfo->StandTable[StandTableIndex].ATTR[i];
+ ARdata = pVBInfo->StandTable->ATTR[i];
if (modeflag & Charx8Dot) { /* ifndef Dot9 */
if (i == 0x13) {
if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
@@ -295,15 +238,14 @@ static void XGI_SetATTRegs(unsigned short ModeNo,
outb(0x20, pVBInfo->P3c0);
}
-static void XGI_SetGRCRegs(unsigned short StandTableIndex,
- struct vb_device_info *pVBInfo)
+static void XGI_SetGRCRegs(struct vb_device_info *pVBInfo)
{
unsigned char GRdata;
unsigned short i;
for (i = 0; i <= 0x08; i++) {
/* Get GR from file */
- GRdata = pVBInfo->StandTable[StandTableIndex].GRC[i];
+ GRdata = pVBInfo->StandTable->GRC[i];
xgifb_reg_set(pVBInfo->P3ce, i, GRdata); /* Set GR(3ce) */
}
@@ -344,12 +286,7 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo,
{
unsigned short tempax, tempbx, resinfo, modeflag, infoflag;
- if (ModeNo <= 0x13)
- /* si+St_ModeFlag */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
tempbx = pVBInfo->RefIndex[RefreshRateTableIndex + (*i)].ModeID;
tempax = 0;
@@ -584,11 +521,7 @@ static void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
data &= 0x80;
data = data >> 2;
- if (ModeNo <= 0x13)
- i = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- i = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
+ i = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
i &= DoubleScanMode;
if (i)
data |= 0x80;
@@ -641,158 +574,97 @@ static void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
unsigned short RefreshRateTableIndex,
struct vb_device_info *pVBInfo)
{
- unsigned char StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx;
+ unsigned char index, Tempax, Tempbx, Tempcx, Tempdx;
unsigned short Temp1, Temp2, Temp3;
- if (ModeNo <= 0x13) {
- StandTableIndex = XGI_GetModePtr(ModeNo, ModeIdIndex, pVBInfo);
- /* CR04 HRS */
- Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[4];
- /* SR2E [7:0]->HRS */
- xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax);
- /* Tempbx: CR05 HRE */
- Tempbx = pVBInfo->StandTable[StandTableIndex].CRTC[5];
- Tempbx &= 0x1F; /* Tempbx: HRE[4:0] */
- Tempcx = Tempax;
- Tempcx &= 0xE0; /* Tempcx: HRS[7:5] */
- Tempdx = Tempcx | Tempbx; /* Tempdx(HRE): HRS[7:5]HRE[4:0] */
- if (Tempbx < (Tempax & 0x1F)) /* IF HRE < HRS */
- Tempdx |= 0x20; /* Tempdx: HRE = HRE + 0x20 */
- Tempdx <<= 2; /* Tempdx << 2 */
- /* SR2F [7:2]->HRE */
- xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempdx);
- xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
-
- /* Tempax: CR16 VRS */
- Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[16];
- Tempbx = Tempax; /* Tempbx=Tempax */
- Tempax &= 0x01; /* Tempax: VRS[0] */
- xgifb_reg_or(pVBInfo->P3c4, 0x33, Tempax); /* SR33[0]->VRS */
-
- /* Tempax: CR7 VRS */
- Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[7];
- Tempdx = Tempbx >> 1; /* Tempdx: VRS[7:1] */
- Tempcx = Tempax & 0x04; /* Tempcx: CR7[2] */
- Tempcx <<= 5; /* Tempcx[7]: VRS[8] */
- Tempdx |= Tempcx; /* Tempdx: VRS[8:1] */
- /* SR34[7:0]: VRS[8:1] */
- xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempdx);
-
- /* Temp1[8]: VRS[8] unsigned char -> unsigned short */
- Temp1 = Tempcx << 1;
- Temp1 |= Tempbx; /* Temp1[8:0]: VRS[8:0] */
- Tempax &= 0x80; /* Tempax[7]: CR7[7] */
- Temp2 = Tempax << 2; /* Temp2[9]: VRS[9] */
- Temp1 |= Temp2; /* Temp1[9:0]: VRS[9:0] */
-
- /* CR16 VRE */
- Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[17];
- Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
- Temp2 = Temp1 & 0x3F0; /* Temp2[9:4]: VRS[9:4] */
- Temp2 |= Tempax; /* Temp2[9:0]: VRE[9:0] */
- Temp3 = Temp1 & 0x0F; /* Temp3[3:0]: VRS[3:0] */
- if (Tempax < Temp3) /* VRE[3:0]<VRS[3:0] */
- Temp2 |= 0x10; /* Temp2: VRE + 0x10 */
- Temp2 &= 0xFF; /* Temp2[7:0]: VRE[7:0] */
- Tempax = (unsigned char) Temp2; /* Tempax[7:0]: VRE[7:0] */
- Tempax <<= 2; /* Tempax << 2: VRE[5:0] */
- Temp1 &= 0x600; /* Temp1[10:9]: VRS[10:9] */
- Temp1 >>= 9; /* [10:9]->[1:0] */
- Tempbx = (unsigned char) Temp1; /* Tempbx[1:0]: VRS[10:9] */
- Tempax |= Tempbx; /* VRE[5:0]VRS[10:9] */
- Tempax &= 0x7F;
- /* SR3F D[7:2]->VRE D[1:0]->VRS */
- xgifb_reg_set(pVBInfo->P3c4, 0x3F, Tempax);
- } else {
- index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
- /* Tempax: CR4 HRS */
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3];
- Tempcx = Tempax; /* Tempcx: HRS */
- /* SR2E[7:0]->HRS */
- xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax);
-
- Tempdx = pVBInfo->XGINEWUB_CRT1Table[index].CR[5]; /* SRB */
- Tempdx &= 0xC0; /* Tempdx[7:6]: SRB[7:6] */
- Temp1 = Tempdx; /* Temp1[7:6]: HRS[9:8] */
- Temp1 <<= 2; /* Temp1[9:8]: HRS[9:8] */
- Temp1 |= Tempax; /* Temp1[9:0]: HRS[9:0] */
-
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[4]; /* CR5 HRE */
- Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
-
- Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[6]; /* SRC */
- Tempbx &= 0x04; /* Tempbx[2]: HRE[5] */
- Tempbx <<= 3; /* Tempbx[5]: HRE[5] */
- Tempax |= Tempbx; /* Tempax[5:0]: HRE[5:0] */
-
- Temp2 = Temp1 & 0x3C0; /* Temp2[9:6]: HRS[9:6] */
- Temp2 |= Tempax; /* Temp2[9:0]: HRE[9:0] */
-
- Tempcx &= 0x3F; /* Tempcx[5:0]: HRS[5:0] */
- if (Tempax < Tempcx) /* HRE < HRS */
- Temp2 |= 0x40; /* Temp2 + 0x40 */
-
- Temp2 &= 0xFF;
- Tempax = (unsigned char) Temp2; /* Tempax: HRE[7:0] */
- Tempax <<= 2; /* Tempax[7:2]: HRE[5:0] */
- Tempdx >>= 6; /* Tempdx[7:6]->[1:0] HRS[9:8] */
- Tempax |= Tempdx; /* HRE[5:0]HRS[9:8] */
- /* SR2F D[7:2]->HRE, D[1:0]->HRS */
- xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempax);
- xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
-
- /* CR10 VRS */
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[10];
- Tempbx = Tempax; /* Tempbx: VRS */
- Tempax &= 0x01; /* Tempax[0]: VRS[0] */
- xgifb_reg_or(pVBInfo->P3c4, 0x33, Tempax); /* SR33[0]->VRS[0] */
- /* CR7[2][7] VRE */
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[9];
- Tempcx = Tempbx >> 1; /* Tempcx[6:0]: VRS[7:1] */
- Tempdx = Tempax & 0x04; /* Tempdx[2]: CR7[2] */
- Tempdx <<= 5; /* Tempdx[7]: VRS[8] */
- Tempcx |= Tempdx; /* Tempcx[7:0]: VRS[8:1] */
- xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempcx); /* SR34[8:1]->VRS */
-
- Temp1 = Tempdx; /* Temp1[7]: Tempdx[7] */
- Temp1 <<= 1; /* Temp1[8]: VRS[8] */
- Temp1 |= Tempbx; /* Temp1[8:0]: VRS[8:0] */
- Tempax &= 0x80;
- Temp2 = Tempax << 2; /* Temp2[9]: VRS[9] */
- Temp1 |= Temp2; /* Temp1[9:0]: VRS[9:0] */
- /* Tempax: SRA */
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[14];
- Tempax &= 0x08; /* Tempax[3]: VRS[3] */
- Temp2 = Tempax;
- Temp2 <<= 7; /* Temp2[10]: VRS[10] */
- Temp1 |= Temp2; /* Temp1[10:0]: VRS[10:0] */
-
- /* Tempax: CR11 VRE */
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[11];
- Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
- /* Tempbx: SRA */
- Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[14];
- Tempbx &= 0x20; /* Tempbx[5]: VRE[5] */
- Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
- Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
- Temp2 = Temp1 & 0x7E0; /* Temp2[10:5]: VRS[10:5] */
- Temp2 |= Tempax; /* Temp2[10:5]: VRE[10:5] */
-
- Temp3 = Temp1 & 0x1F; /* Temp3[4:0]: VRS[4:0] */
- if (Tempax < Temp3) /* VRE < VRS */
- Temp2 |= 0x20; /* VRE + 0x20 */
-
- Temp2 &= 0xFF;
- Tempax = (unsigned char) Temp2; /* Tempax: VRE[7:0] */
- Tempax <<= 2; /* Tempax[7:0]; VRE[5:0]00 */
- Temp1 &= 0x600; /* Temp1[10:9]: VRS[10:9] */
- Temp1 >>= 9; /* Temp1[1:0]: VRS[10:9] */
- Tempbx = (unsigned char) Temp1;
- Tempax |= Tempbx; /* Tempax[7:0]: VRE[5:0]VRS[10:9] */
- Tempax &= 0x7F;
- /* SR3F D[7:2]->VRE D[1:0]->VRS */
- xgifb_reg_set(pVBInfo->P3c4, 0x3F, Tempax);
- }
+ index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+ /* Tempax: CR4 HRS */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3];
+ Tempcx = Tempax; /* Tempcx: HRS */
+ /* SR2E[7:0]->HRS */
+ xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax);
+
+ Tempdx = pVBInfo->XGINEWUB_CRT1Table[index].CR[5]; /* SRB */
+ Tempdx &= 0xC0; /* Tempdx[7:6]: SRB[7:6] */
+ Temp1 = Tempdx; /* Temp1[7:6]: HRS[9:8] */
+ Temp1 <<= 2; /* Temp1[9:8]: HRS[9:8] */
+ Temp1 |= Tempax; /* Temp1[9:0]: HRS[9:0] */
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[4]; /* CR5 HRE */
+ Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
+
+ Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[6]; /* SRC */
+ Tempbx &= 0x04; /* Tempbx[2]: HRE[5] */
+ Tempbx <<= 3; /* Tempbx[5]: HRE[5] */
+ Tempax |= Tempbx; /* Tempax[5:0]: HRE[5:0] */
+
+ Temp2 = Temp1 & 0x3C0; /* Temp2[9:6]: HRS[9:6] */
+ Temp2 |= Tempax; /* Temp2[9:0]: HRE[9:0] */
+
+ Tempcx &= 0x3F; /* Tempcx[5:0]: HRS[5:0] */
+ if (Tempax < Tempcx) /* HRE < HRS */
+ Temp2 |= 0x40; /* Temp2 + 0x40 */
+
+ Temp2 &= 0xFF;
+ Tempax = (unsigned char) Temp2; /* Tempax: HRE[7:0] */
+ Tempax <<= 2; /* Tempax[7:2]: HRE[5:0] */
+ Tempdx >>= 6; /* Tempdx[7:6]->[1:0] HRS[9:8] */
+ Tempax |= Tempdx; /* HRE[5:0]HRS[9:8] */
+ /* SR2F D[7:2]->HRE, D[1:0]->HRS */
+ xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempax);
+ xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
+
+ /* CR10 VRS */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[10];
+ Tempbx = Tempax; /* Tempbx: VRS */
+ Tempax &= 0x01; /* Tempax[0]: VRS[0] */
+ xgifb_reg_or(pVBInfo->P3c4, 0x33, Tempax); /* SR33[0]->VRS[0] */
+ /* CR7[2][7] VRE */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[9];
+ Tempcx = Tempbx >> 1; /* Tempcx[6:0]: VRS[7:1] */
+ Tempdx = Tempax & 0x04; /* Tempdx[2]: CR7[2] */
+ Tempdx <<= 5; /* Tempdx[7]: VRS[8] */
+ Tempcx |= Tempdx; /* Tempcx[7:0]: VRS[8:1] */
+ xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempcx); /* SR34[8:1]->VRS */
+
+ Temp1 = Tempdx; /* Temp1[7]: Tempdx[7] */
+ Temp1 <<= 1; /* Temp1[8]: VRS[8] */
+ Temp1 |= Tempbx; /* Temp1[8:0]: VRS[8:0] */
+ Tempax &= 0x80;
+ Temp2 = Tempax << 2; /* Temp2[9]: VRS[9] */
+ Temp1 |= Temp2; /* Temp1[9:0]: VRS[9:0] */
+ /* Tempax: SRA */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[14];
+ Tempax &= 0x08; /* Tempax[3]: VRS[3] */
+ Temp2 = Tempax;
+ Temp2 <<= 7; /* Temp2[10]: VRS[10] */
+ Temp1 |= Temp2; /* Temp1[10:0]: VRS[10:0] */
+
+ /* Tempax: CR11 VRE */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[11];
+ Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
+ /* Tempbx: SRA */
+ Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[14];
+ Tempbx &= 0x20; /* Tempbx[5]: VRE[5] */
+ Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
+ Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
+ Temp2 = Temp1 & 0x7E0; /* Temp2[10:5]: VRS[10:5] */
+ Temp2 |= Tempax; /* Temp2[10:5]: VRE[10:5] */
+
+ Temp3 = Temp1 & 0x1F; /* Temp3[4:0]: VRS[4:0] */
+ if (Tempax < Temp3) /* VRE < VRS */
+ Temp2 |= 0x20; /* VRE + 0x20 */
+
+ Temp2 &= 0xFF;
+ Tempax = (unsigned char) Temp2; /* Tempax: VRE[7:0] */
+ Tempax <<= 2; /* Tempax[7:0]; VRE[5:0]00 */
+ Temp1 &= 0x600; /* Temp1[10:9]: VRS[10:9] */
+ Temp1 >>= 9; /* Temp1[1:0]: VRS[10:9] */
+ Tempbx = (unsigned char) Temp1;
+ Tempax |= Tempbx; /* Tempax[7:0]: VRE[5:0]VRS[10:9] */
+ Tempax &= 0x7F;
+ /* SR3F D[7:2]->VRE D[1:0]->VRS */
+ xgifb_reg_set(pVBInfo->P3c4, 0x3F, Tempax);
}
static void XGI_SetXG27CRTC(unsigned short ModeNo,
@@ -800,139 +672,88 @@ static void XGI_SetXG27CRTC(unsigned short ModeNo,
unsigned short RefreshRateTableIndex,
struct vb_device_info *pVBInfo)
{
- unsigned short StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx;
-
- if (ModeNo <= 0x13) {
- StandTableIndex = XGI_GetModePtr(ModeNo, ModeIdIndex, pVBInfo);
- /* CR04 HRS */
- Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[4];
- /* SR2E [7:0]->HRS */
- xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax);
- /* Tempbx: CR05 HRE */
- Tempbx = pVBInfo->StandTable[StandTableIndex].CRTC[5];
- Tempbx &= 0x1F; /* Tempbx: HRE[4:0] */
- Tempcx = Tempax;
- Tempcx &= 0xE0; /* Tempcx: HRS[7:5] */
- Tempdx = Tempcx | Tempbx; /* Tempdx(HRE): HRS[7:5]HRE[4:0] */
- if (Tempbx < (Tempax & 0x1F)) /* IF HRE < HRS */
- Tempdx |= 0x20; /* Tempdx: HRE = HRE + 0x20 */
- Tempdx <<= 2; /* Tempdx << 2 */
- /* SR2F [7:2]->HRE */
- xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempdx);
- xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
-
- /* Tempax: CR10 VRS */
- Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[16];
- xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempax); /* SR34[7:0]->VRS */
- Tempcx = Tempax; /* Tempcx=Tempax=VRS[7:0] */
- /* Tempax[7][2]: CR7[7][2] VRS[9][8] */
- Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[7];
- Tempbx = Tempax; /* Tempbx=CR07 */
- Tempax &= 0x04; /* Tempax[2]: CR07[2] VRS[8] */
- Tempax >>= 2;
- /* SR35 D[0]->VRS D[8] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x01, Tempax);
- Tempcx |= (Tempax << 8); /* Tempcx[8] |= VRS[8] */
- Tempcx |= (Tempbx & 0x80) << 2; /* Tempcx[9] |= VRS[9] */
-
- /* CR11 VRE */
- Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[17];
- Tempax &= 0x0F; /* Tempax: VRE[3:0] */
- Tempbx = Tempcx; /* Tempbx=Tempcx=VRS[9:0] */
- Tempbx &= 0x3F0; /* Tempbx[9:4]: VRS[9:4] */
- Tempbx |= Tempax; /* Tempbx[9:0]: VRE[9:0] */
- if (Tempax <= (Tempcx & 0x0F)) /* VRE[3:0]<=VRS[3:0] */
- Tempbx |= 0x10; /* Tempbx: VRE + 0x10 */
- /* Tempax[7:0]: VRE[7:0] */
- Tempax = (unsigned char) Tempbx & 0xFF;
- Tempax <<= 2; /* Tempax << 2: VRE[5:0] */
- Tempcx = (Tempcx & 0x600) >> 8; /* Tempcx VRS[10:9] */
- /* SR3F D[7:2]->VRE D[5:0] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC, Tempax);
- /* SR35 D[2:1]->VRS[10:9] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x06, Tempcx);
- } else {
- index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
- /* Tempax: CR4 HRS */
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3];
- Tempbx = Tempax; /* Tempbx: HRS[7:0] */
- /* SR2E[7:0]->HRS */
- xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax);
-
- /* SR0B */
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[5];
- Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
- Tempbx |= (Tempax << 2); /* Tempbx: HRS[9:0] */
-
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[4]; /* CR5 HRE */
- Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
- Tempcx = Tempax; /* Tempcx: HRE[4:0] */
-
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[6]; /* SRC */
- Tempax &= 0x04; /* Tempax[2]: HRE[5] */
- Tempax <<= 3; /* Tempax[5]: HRE[5] */
- Tempcx |= Tempax; /* Tempcx[5:0]: HRE[5:0] */
-
- Tempbx = Tempbx & 0x3C0; /* Tempbx[9:6]: HRS[9:6] */
- Tempbx |= Tempcx; /* Tempbx: HRS[9:6]HRE[5:0] */
-
- /* Tempax: CR4 HRS */
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3];
- Tempax &= 0x3F; /* Tempax: HRS[5:0] */
- if (Tempcx <= Tempax) /* HRE[5:0] < HRS[5:0] */
- Tempbx += 0x40; /* Tempbx= Tempbx + 0x40 : HRE[9:0]*/
-
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[5]; /* SR0B */
- Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
- Tempax >>= 6; /* Tempax[1:0]: HRS[9:8]*/
- Tempax |= ((Tempbx << 2) & 0xFF); /* Tempax[7:2]: HRE[5:0] */
- /* SR2F [7:2][1:0]: HRE[5:0]HRS[9:8] */
- xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempax);
- xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
-
- /* CR10 VRS */
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[10];
- /* SR34[7:0]->VRS[7:0] */
- xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempax);
-
- Tempcx = Tempax; /* Tempcx <= VRS[7:0] */
- /* CR7[7][2] VRS[9][8] */
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[9];
- Tempbx = Tempax; /* Tempbx <= CR07[7:0] */
- Tempax = Tempax & 0x04; /* Tempax[2]: CR7[2]: VRS[8] */
- Tempax >>= 2; /* Tempax[0]: VRS[8] */
- /* SR35[0]: VRS[8] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x01, Tempax);
- Tempcx |= (Tempax << 8); /* Tempcx <= VRS[8:0] */
- Tempcx |= ((Tempbx & 0x80) << 2); /* Tempcx <= VRS[9:0] */
- /* Tempax: SR0A */
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[14];
- Tempax &= 0x08; /* SR0A[3] VRS[10] */
- Tempcx |= (Tempax << 7); /* Tempcx <= VRS[10:0] */
-
- /* Tempax: CR11 VRE */
- Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[11];
- Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
- /* Tempbx: SR0A */
- Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[14];
- Tempbx &= 0x20; /* Tempbx[5]: SR0A[5]: VRE[4] */
- Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
- Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
- Tempbx = Tempcx; /* Tempbx: VRS[10:0] */
- Tempbx &= 0x7E0; /* Tempbx[10:5]: VRS[10:5] */
- Tempbx |= Tempax; /* Tempbx: VRS[10:5]VRE[4:0] */
-
- if (Tempbx <= Tempcx) /* VRE <= VRS */
- Tempbx |= 0x20; /* VRE + 0x20 */
-
- /* Tempax: Tempax[7:0]; VRE[5:0]00 */
- Tempax = (Tempbx << 2) & 0xFF;
- /* SR3F[7:2]:VRE[5:0] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC, Tempax);
- Tempax = Tempcx >> 8;
- /* SR35[2:0]:VRS[10:8] */
- xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x07, Tempax);
- }
+ unsigned short index, Tempax, Tempbx, Tempcx;
+
+ index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+ /* Tempax: CR4 HRS */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3];
+ Tempbx = Tempax; /* Tempbx: HRS[7:0] */
+ /* SR2E[7:0]->HRS */
+ xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax);
+
+ /* SR0B */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[5];
+ Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
+ Tempbx |= (Tempax << 2); /* Tempbx: HRS[9:0] */
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[4]; /* CR5 HRE */
+ Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
+ Tempcx = Tempax; /* Tempcx: HRE[4:0] */
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[6]; /* SRC */
+ Tempax &= 0x04; /* Tempax[2]: HRE[5] */
+ Tempax <<= 3; /* Tempax[5]: HRE[5] */
+ Tempcx |= Tempax; /* Tempcx[5:0]: HRE[5:0] */
+
+ Tempbx = Tempbx & 0x3C0; /* Tempbx[9:6]: HRS[9:6] */
+ Tempbx |= Tempcx; /* Tempbx: HRS[9:6]HRE[5:0] */
+
+ /* Tempax: CR4 HRS */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3];
+ Tempax &= 0x3F; /* Tempax: HRS[5:0] */
+ if (Tempcx <= Tempax) /* HRE[5:0] < HRS[5:0] */
+ Tempbx += 0x40; /* Tempbx= Tempbx + 0x40 : HRE[9:0]*/
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[5]; /* SR0B */
+ Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
+ Tempax >>= 6; /* Tempax[1:0]: HRS[9:8]*/
+ Tempax |= ((Tempbx << 2) & 0xFF); /* Tempax[7:2]: HRE[5:0] */
+ /* SR2F [7:2][1:0]: HRE[5:0]HRS[9:8] */
+ xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempax);
+ xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
+
+ /* CR10 VRS */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[10];
+ /* SR34[7:0]->VRS[7:0] */
+ xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempax);
+
+ Tempcx = Tempax; /* Tempcx <= VRS[7:0] */
+ /* CR7[7][2] VRS[9][8] */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[9];
+ Tempbx = Tempax; /* Tempbx <= CR07[7:0] */
+ Tempax = Tempax & 0x04; /* Tempax[2]: CR7[2]: VRS[8] */
+ Tempax >>= 2; /* Tempax[0]: VRS[8] */
+ /* SR35[0]: VRS[8] */
+ xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x01, Tempax);
+ Tempcx |= (Tempax << 8); /* Tempcx <= VRS[8:0] */
+ Tempcx |= ((Tempbx & 0x80) << 2); /* Tempcx <= VRS[9:0] */
+ /* Tempax: SR0A */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[14];
+ Tempax &= 0x08; /* SR0A[3] VRS[10] */
+ Tempcx |= (Tempax << 7); /* Tempcx <= VRS[10:0] */
+
+ /* Tempax: CR11 VRE */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[11];
+ Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
+ /* Tempbx: SR0A */
+ Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[14];
+ Tempbx &= 0x20; /* Tempbx[5]: SR0A[5]: VRE[4] */
+ Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
+ Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
+ Tempbx = Tempcx; /* Tempbx: VRS[10:0] */
+ Tempbx &= 0x7E0; /* Tempbx[10:5]: VRS[10:5] */
+ Tempbx |= Tempax; /* Tempbx: VRS[10:5]VRE[4:0] */
+
+ if (Tempbx <= Tempcx) /* VRE <= VRS */
+ Tempbx |= 0x20; /* VRE + 0x20 */
+
+ /* Tempax: Tempax[7:0]; VRE[5:0]00 */
+ Tempax = (Tempbx << 2) & 0xFF;
+ /* SR3F[7:2]:VRE[5:0] */
+ xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC, Tempax);
+ Tempax = Tempcx >> 8;
+ /* SR35[2:0]:VRS[10:8] */
+ xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x07, Tempax);
}
static void XGI_SetXG27FPBits(struct vb_device_info *pVBInfo)
@@ -954,7 +775,7 @@ static void xgifb_set_lcd(int chip_id,
unsigned short RefreshRateTableIndex,
unsigned short ModeNo)
{
- unsigned short Data, Temp, b3CC;
+ unsigned short Data, Temp;
unsigned short XGI_P3cc;
XGI_P3cc = pVBInfo->P3cc;
@@ -995,23 +816,13 @@ static void xgifb_set_lcd(int chip_id,
xgifb_reg_and(pVBInfo->P3c4, 0x30, ~0x20); /* Hsync polarity */
xgifb_reg_and(pVBInfo->P3c4, 0x35, ~0x80); /* Vsync polarity */
- if (ModeNo <= 0x13) {
- b3CC = (unsigned char) inb(XGI_P3cc);
- if (b3CC & 0x40)
- /* Hsync polarity */
- xgifb_reg_or(pVBInfo->P3c4, 0x30, 0x20);
- if (b3CC & 0x80)
- /* Vsync polarity */
- xgifb_reg_or(pVBInfo->P3c4, 0x35, 0x80);
- } else {
- Data = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
- if (Data & 0x4000)
- /* Hsync polarity */
- xgifb_reg_or(pVBInfo->P3c4, 0x30, 0x20);
- if (Data & 0x8000)
- /* Vsync polarity */
- xgifb_reg_or(pVBInfo->P3c4, 0x35, 0x80);
- }
+ Data = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+ if (Data & 0x4000)
+ /* Hsync polarity */
+ xgifb_reg_or(pVBInfo->P3c4, 0x30, 0x20);
+ if (Data & 0x8000)
+ /* Vsync polarity */
+ xgifb_reg_or(pVBInfo->P3c4, 0x35, 0x80);
}
/* --------------------------------------------------------------------- */
@@ -1024,30 +835,22 @@ static void XGI_UpdateXG21CRTC(unsigned short ModeNo,
struct vb_device_info *pVBInfo,
unsigned short RefreshRateTableIndex)
{
- int i, index = -1;
+ int index = -1;
xgifb_reg_and(pVBInfo->P3d4, 0x11, 0x7F); /* Unlock CR0~7 */
- if (ModeNo <= 0x13) {
- for (i = 0; i < 12; i++) {
- if (ModeNo == pVBInfo->UpdateCRT1[i].ModeID)
- index = i;
- }
- } else {
- if (ModeNo == 0x2E &&
- (pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC ==
- RES640x480x60))
- index = 12;
- else if (ModeNo == 0x2E &&
- (pVBInfo->RefIndex[RefreshRateTableIndex].
+ if (ModeNo == 0x2E &&
+ (pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC ==
+ RES640x480x60))
+ index = 12;
+ else if (ModeNo == 0x2E && (pVBInfo->RefIndex[RefreshRateTableIndex].
Ext_CRT1CRTC == RES640x480x72))
- index = 13;
- else if (ModeNo == 0x2F)
- index = 14;
- else if (ModeNo == 0x50)
- index = 15;
- else if (ModeNo == 0x59)
- index = 16;
- }
+ index = 13;
+ else if (ModeNo == 0x2F)
+ index = 14;
+ else if (ModeNo == 0x50)
+ index = 15;
+ else if (ModeNo == 0x59)
+ index = 16;
if (index != -1) {
xgifb_reg_set(pVBInfo->P3d4, 0x02,
@@ -1061,20 +864,6 @@ static void XGI_UpdateXG21CRTC(unsigned short ModeNo,
}
}
-static unsigned short XGI_GetResInfo(unsigned short ModeNo,
- unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
-{
- unsigned short resindex;
-
- if (ModeNo <= 0x13)
- /* si+St_ResInfo */
- resindex = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
- else
- /* si+Ext_ResInfo */
- resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- return resindex;
-}
-
static void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension,
unsigned short ModeNo, unsigned short ModeIdIndex,
unsigned short RefreshRateTableIndex,
@@ -1084,33 +873,25 @@ static void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension,
unsigned char data;
- resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
+ resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- if (ModeNo <= 0x13) {
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- tempax = pVBInfo->StResInfo[resindex].HTotal;
- tempbx = pVBInfo->StResInfo[resindex].VTotal;
- } else {
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- tempax = pVBInfo->ModeResInfo[resindex].HTotal;
- tempbx = pVBInfo->ModeResInfo[resindex].VTotal;
- }
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ tempax = pVBInfo->ModeResInfo[resindex].HTotal;
+ tempbx = pVBInfo->ModeResInfo[resindex].VTotal;
if (modeflag & HalfDCLK)
tempax = tempax >> 1;
- if (ModeNo > 0x13) {
- if (modeflag & HalfDCLK)
- tempax = tempax << 1;
+ if (modeflag & HalfDCLK)
+ tempax = tempax << 1;
- temp = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+ temp = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
- if (temp & InterlaceMode)
- tempbx = tempbx >> 1;
+ if (temp & InterlaceMode)
+ tempbx = tempbx >> 1;
- if (modeflag & DoubleScanMode)
- tempbx = tempbx << 1;
- }
+ if (modeflag & DoubleScanMode)
+ tempbx = tempbx << 1;
tempcx = 8;
@@ -1258,18 +1039,10 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
unsigned short CRT2Index, VCLKIndex;
unsigned short modeflag, resinfo;
- if (ModeNo <= 0x13) {
- /* si+St_ResInfo */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
- CRT2Index = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- } else {
- /* si+Ext_ResInfo */
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- CRT2Index = pVBInfo->RefIndex[RefreshRateTableIndex].
- Ext_CRT2CRTC;
- }
+ /* si+Ext_ResInfo */
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ CRT2Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
if (pVBInfo->IF_DEF_LVDS == 0) {
CRT2Index = CRT2Index >> 6; /* for LCD */
@@ -1318,23 +1091,13 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
VCLKIndex += 25;
}
} else { /* for CRT2 */
- /* Port 3cch */
- VCLKIndex = (unsigned char) inb((pVBInfo->P3ca + 0x02));
- VCLKIndex = ((VCLKIndex >> 2) & 0x03);
- if (ModeNo > 0x13) {
- /* di+Ext_CRTVCLK */
- VCLKIndex = pVBInfo->RefIndex[
- RefreshRateTableIndex].
+ /* di+Ext_CRTVCLK */
+ VCLKIndex = pVBInfo->RefIndex[RefreshRateTableIndex].
Ext_CRTVCLK;
- VCLKIndex &= IndexMask;
- }
+ VCLKIndex &= IndexMask;
}
} else { /* LVDS */
- if (ModeNo <= 0x13)
- VCLKIndex = CRT2Index;
- else
- VCLKIndex = CRT2Index;
-
+ VCLKIndex = CRT2Index;
VCLKIndex = VCLKIndex >> 6;
if ((pVBInfo->LCDResInfo == Panel_800x600) ||
(pVBInfo->LCDResInfo == Panel_320x480))
@@ -1431,27 +1194,13 @@ static void XGI_SetCRT1FIFO(unsigned short ModeNo,
data &= 0xfe;
xgifb_reg_set(pVBInfo->P3c4, 0x3D, data); /* diable auto-threshold */
- if (ModeNo > 0x13) {
- xgifb_reg_set(pVBInfo->P3c4, 0x08, 0x34);
- data = xgifb_reg_get(pVBInfo->P3c4, 0x09);
- data &= 0xC0;
- xgifb_reg_set(pVBInfo->P3c4, 0x09, data | 0x30);
- data = xgifb_reg_get(pVBInfo->P3c4, 0x3D);
- data |= 0x01;
- xgifb_reg_set(pVBInfo->P3c4, 0x3D, data);
- } else {
- if (HwDeviceExtension->jChipType == XG27) {
- xgifb_reg_set(pVBInfo->P3c4, 0x08, 0x0E);
- data = xgifb_reg_get(pVBInfo->P3c4, 0x09);
- data &= 0xC0;
- xgifb_reg_set(pVBInfo->P3c4, 0x09, data | 0x20);
- } else {
- xgifb_reg_set(pVBInfo->P3c4, 0x08, 0xAE);
- data = xgifb_reg_get(pVBInfo->P3c4, 0x09);
- data &= 0xF0;
- xgifb_reg_set(pVBInfo->P3c4, 0x09, data);
- }
- }
+ xgifb_reg_set(pVBInfo->P3c4, 0x08, 0x34);
+ data = xgifb_reg_get(pVBInfo->P3c4, 0x09);
+ data &= 0xC0;
+ xgifb_reg_set(pVBInfo->P3c4, 0x09, data | 0x30);
+ data = xgifb_reg_get(pVBInfo->P3c4, 0x3D);
+ data |= 0x01;
+ xgifb_reg_set(pVBInfo->P3c4, 0x3D, data);
if (HwDeviceExtension->jChipType == XG21)
XGI_SetXG21FPBits(pVBInfo); /* Fix SR9[7:6] can't read back */
@@ -1466,13 +1215,9 @@ static void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension,
unsigned char index;
- if (ModeNo <= 0x13)
- VCLK = 0;
- else {
- index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
- index &= IndexMask;
- VCLK = pVBInfo->VCLKData[index].CLOCK;
- }
+ index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+ index &= IndexMask;
+ VCLK = pVBInfo->VCLKData[index].CLOCK;
data = xgifb_reg_get(pVBInfo->P3c4, 0x32);
data &= 0xf3;
@@ -1508,44 +1253,26 @@ static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
unsigned short data, data2, data3, infoflag = 0, modeflag, resindex,
xres;
- if (ModeNo > 0x13) {
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- infoflag = pVBInfo->RefIndex[RefreshRateTableIndex].
- Ext_InfoFlag;
- } else
- /* si+St_ModeFlag */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ infoflag = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
if (xgifb_reg_get(pVBInfo->P3d4, 0x31) & 0x01)
xgifb_reg_and_or(pVBInfo->P3c4, 0x1F, 0x3F, 0x00);
- if (ModeNo > 0x13)
- data = infoflag;
- else
- data = 0;
-
+ data = infoflag;
data2 = 0;
-
- if (ModeNo > 0x13) {
- if (pVBInfo->ModeType > 0x02) {
- data2 |= 0x02;
- data3 = pVBInfo->ModeType - ModeVGA;
- data3 = data3 << 2;
- data2 |= data3;
- }
- }
-
+ data2 |= 0x02;
+ data3 = pVBInfo->ModeType - ModeVGA;
+ data3 = data3 << 2;
+ data2 |= data3;
data &= InterlaceMode;
if (data)
data2 |= 0x20;
xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0x3F, data2);
- resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
- if (ModeNo <= 0x13)
- xres = pVBInfo->StResInfo[resindex].HTotal;
- else
- xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
+ resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
data = 0x0000;
if (infoflag & InterlaceMode) {
@@ -1568,18 +1295,10 @@ static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
if (modeflag & LineCompareOff)
data2 |= 0x08;
- if (ModeNo > 0x13) {
- if (pVBInfo->ModeType == ModeEGA)
- data2 |= 0x40;
- }
-
xgifb_reg_and_or(pVBInfo->P3c4, 0x0F, ~0x48, data2);
data = 0x60;
- if (pVBInfo->ModeType != ModeText) {
- data = data ^ 0x60;
- if (pVBInfo->ModeType != ModeEGA)
- data = data ^ 0xA0;
- }
+ data = data ^ 0x60;
+ data = data ^ 0xA0;
xgifb_reg_and_or(pVBInfo->P3c4, 0x21, 0x1F, data);
XGI_SetVCLKState(HwDeviceExtension, ModeNo, RefreshRateTableIndex,
@@ -1644,38 +1363,13 @@ static void XGI_WriteDAC(unsigned short dl,
static void XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
- unsigned short data, data2, time, i, j, k, m, n, o, si, di, bx, dl, al,
- ah, dh;
- const unsigned short *table = NULL;
-
- if (ModeNo <= 0x13)
- data = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- data = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
- data &= DACInfoFlag;
- time = 64;
-
- if (data == 0x00)
- table = XGINew_MDA_DAC;
- else if (data == 0x08)
- table = XGINew_CGA_DAC;
- else if (data == 0x10)
- table = XGINew_EGA_DAC;
- else if (data == 0x18) {
- time = 256;
- table = XGINew_VGA_DAC;
- }
-
- if (time == 256)
- j = 16;
- else
- j = time;
+ unsigned short data, data2, i, k, m, n, o, si, di, bx, dl, al, ah, dh;
+ const unsigned short *table = XGINew_VGA_DAC;
outb(0xFF, pVBInfo->P3c6);
outb(0x00, pVBInfo->P3c8);
- for (i = 0; i < j; i++) {
+ for (i = 0; i < 16; i++) {
data = table[i];
for (k = 0; k < 3; k++) {
@@ -1692,45 +1386,43 @@ static void XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,
}
}
- if (time == 256) {
- for (i = 16; i < 32; i++) {
- data = table[i];
-
- for (k = 0; k < 3; k++)
- outb(data, pVBInfo->P3c9);
- }
+ for (i = 16; i < 32; i++) {
+ data = table[i];
- si = 32;
+ for (k = 0; k < 3; k++)
+ outb(data, pVBInfo->P3c9);
+ }
- for (m = 0; m < 9; m++) {
- di = si;
- bx = si + 0x04;
- dl = 0;
+ si = 32;
- for (n = 0; n < 3; n++) {
- for (o = 0; o < 5; o++) {
- dh = table[si];
- ah = table[di];
- al = table[bx];
- si++;
- XGI_WriteDAC(dl, ah, al, dh, pVBInfo);
- }
+ for (m = 0; m < 9; m++) {
+ di = si;
+ bx = si + 0x04;
+ dl = 0;
- si -= 2;
+ for (n = 0; n < 3; n++) {
+ for (o = 0; o < 5; o++) {
+ dh = table[si];
+ ah = table[di];
+ al = table[bx];
+ si++;
+ XGI_WriteDAC(dl, ah, al, dh, pVBInfo);
+ }
- for (o = 0; o < 3; o++) {
- dh = table[bx];
- ah = table[di];
- al = table[si];
- si--;
- XGI_WriteDAC(dl, ah, al, dh, pVBInfo);
- }
+ si -= 2;
- dl++;
+ for (o = 0; o < 3; o++) {
+ dh = table[bx];
+ ah = table[di];
+ al = table[si];
+ si--;
+ XGI_WriteDAC(dl, ah, al, dh, pVBInfo);
}
- si += 5;
+ dl++;
}
+
+ si += 5;
}
}
@@ -1740,34 +1432,20 @@ static void XGI_GetLVDSResInfo(unsigned short ModeNo,
{
unsigned short resindex, xres, yres, modeflag;
- if (ModeNo <= 0x13)
- /* si+St_ResInfo */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
- else
- /* si+Ext_ResInfo */
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ /* si+Ext_ResInfo */
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- if (ModeNo <= 0x13)
- /* si+St_ResInfo */
- resindex = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
- else
- /* si+Ext_ResInfo */
- resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ /* si+Ext_ResInfo */
+ resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- if (ModeNo <= 0x13) {
- xres = pVBInfo->StResInfo[resindex].HTotal;
- yres = pVBInfo->StResInfo[resindex].VTotal;
- } else {
- xres = pVBInfo->ModeResInfo[resindex].HTotal;
- yres = pVBInfo->ModeResInfo[resindex].VTotal;
- }
- if (ModeNo > 0x13) {
- if (modeflag & HalfDCLK)
- xres = xres << 1;
+ xres = pVBInfo->ModeResInfo[resindex].HTotal;
+ yres = pVBInfo->ModeResInfo[resindex].VTotal;
- if (modeflag & DoubleScanMode)
- yres = yres << 1;
- }
+ if (modeflag & HalfDCLK)
+ xres = xres << 1;
+
+ if (modeflag & DoubleScanMode)
+ yres = yres << 1;
if (xres == 720)
xres = 640;
@@ -1789,32 +1467,16 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo,
tempbx = BX;
- if (ModeNo <= 0x13) {
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- } else {
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
- }
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
tempal = tempal & 0x0f;
if (tempbx <= 1) { /* ExpLink */
- if (ModeNo <= 0x13) {
- /* find no Ext_CRT2CRTC2 */
- tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- } else {
- tempal = pVBInfo->RefIndex[RefreshRateTableIndex].
- Ext_CRT2CRTC;
- }
+ tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
- if (ModeNo <= 0x13)
- tempal = pVBInfo->SModeIDTable[ModeIdIndex].
- St_CRT2CRTC2;
- else
- tempal = pVBInfo->RefIndex[
- RefreshRateTableIndex].
+ tempal = pVBInfo->RefIndex[RefreshRateTableIndex].
Ext_CRT2CRTC2;
}
@@ -1882,9 +1544,6 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo,
tempbx = tempdi[i].MASK;
tempdx = pVBInfo->LCDInfo;
- if (ModeNo <= 0x13) /* alan 09/10/2003 */
- tempdx |= SetLCDStdMode;
-
if (modeflag & HalfDCLK)
tempdx |= SetLCDLowResolution;
@@ -2238,15 +1897,8 @@ static void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo,
struct XGI330_TVDataTablStruct *tempdi = NULL;
tempbx = BX;
-
- if (ModeNo <= 0x13) {
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- } else {
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
- }
-
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
tempal = tempal & 0x3f;
table = tempbx;
@@ -2413,11 +2065,7 @@ static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
struct XGI_LVDSCRT1HDataStruct *LCDPtr = NULL;
struct XGI_LVDSCRT1VDataStruct *LCDPtr1 = NULL;
- if (ModeNo <= 0x13)
- index = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- else
- index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
+ index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
index = index & IndexMask;
tempbx = 0;
@@ -2530,14 +2178,10 @@ static void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
{
unsigned short tempbx, tempax, tempcx, tempdx, push1, push2, modeflag;
unsigned long temp, temp1, temp2, temp3, push3;
- struct XGI330_LCDDataDesStruct *LCDPtr = NULL;
+ struct XGI_LCDDesStruct *LCDPtr = NULL;
struct XGI330_LCDDataDesStruct2 *LCDPtr1 = NULL;
- if (ModeNo > 0x13)
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- else
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
tempbx = 3;
if (pVBInfo->LCDInfo & EnableScalingLCD)
LCDPtr1 =
@@ -2550,7 +2194,7 @@ static void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
pVBInfo);
else
LCDPtr =
- (struct XGI330_LCDDataDesStruct *)
+ (struct XGI_LCDDesStruct *)
XGI_GetLcdPtr(
tempbx,
ModeNo,
@@ -2829,12 +2473,8 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
unsigned short index, modeflag;
unsigned char tempal;
- if (ModeNo <= 0x13)
- /* si+St_ResInfo */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- /* si+Ext_ResInfo */
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ /* si+Ext_ResInfo */
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
if ((pVBInfo->SetFlag & ProgrammingCRT2) &&
(!(pVBInfo->LCDInfo & EnableScalingLCD))) { /* {LCDA/LCDB} */
@@ -2895,9 +2535,6 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
if ((pVBInfo->LCDInfo & EnableScalingLCD) && (modeflag & Charx8Dot))
tempal = tempal ^ tempal; /* ; set to VCLK25MHz always */
- if (ModeNo <= 0x13)
- return tempal;
-
tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
return tempal;
}
@@ -3079,11 +2716,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
{
unsigned short tempax, push, tempbx, temp, modeflag;
- if (ModeNo <= 0x13)
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
pVBInfo->SetFlag = 0;
pVBInfo->ModeType = modeflag & ModeTypeMask;
tempbx = 0;
@@ -3283,17 +2916,8 @@ static void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
resinfo = 0;
if (pVBInfo->VBInfo & SetCRT2ToTV) {
- if (ModeNo <= 0x13) {
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].
- St_ModeFlag; /* si+St_ModeFlag */
- resinfo = pVBInfo->SModeIDTable[ModeIdIndex].
- St_ResInfo; /* si+St_ResInfo */
- } else {
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].
- Ext_ModeFlag;
- resinfo = pVBInfo->EModeIDTable[ModeIdIndex].
- Ext_RESINFO; /* si+Ext_ResInfo */
- }
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
if (pVBInfo->VBInfo & SetCRT2ToTV) {
temp = xgifb_reg_get(pVBInfo->P3d4, 0x35);
@@ -3380,15 +3004,9 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo,
pVBInfo->LCDTypeInfo = 0;
pVBInfo->LCDInfo = 0;
- if (ModeNo <= 0x13) {
- /* si+St_ModeFlag // */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else {
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- /* si+Ext_ResInfo // */
- resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- }
-
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ /* si+Ext_ResInfo // */
+ resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
temp = xgifb_reg_get(pVBInfo->P3d4, 0x36); /* Get LCD Res.Info */
tempbx = temp & 0x0F;
@@ -3442,8 +3060,8 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo,
if (pVBInfo->IF_DEF_LVDS == 0) {
if ((pVBInfo->LCDResInfo == Panel_1400x1050) && (pVBInfo->VBInfo
- & SetCRT2ToLCD) && (ModeNo > 0x13) && (resinfo
- == 9) && (!(tempbx & EnableScalingLCD)))
+ & SetCRT2ToLCD) && (resinfo == 9) &&
+ (!(tempbx & EnableScalingLCD)))
/* set to center in 1280x1024 LCDB for Panel_1400x1050 */
tempbx |= SetLCDtoNonExpanding;
}
@@ -3453,12 +3071,9 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo,
if (!(tempbx & SetLCDtoNonExpanding)) {
tempbx |= XGI_EnableLVDSDDA;
} else {
- if (ModeNo > 0x13) {
- if (pVBInfo->LCDResInfo
- == Panel_1024x768) {
- if (resinfo == 4) {/* 512x384 */
- tempbx |= XGI_EnableLVDSDDA;
- }
+ if (pVBInfo->LCDResInfo == Panel_1024x768) {
+ if (resinfo == 4) {/* 512x384 */
+ tempbx |= XGI_EnableLVDSDDA;
}
}
}
@@ -3474,56 +3089,17 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo,
pVBInfo->LCDInfo = tempbx;
- if (pVBInfo->IF_DEF_LVDS == 0) {
- if (tempax & (LockLCDBToA | StLCDBToA)) {
- if (pVBInfo->VBInfo & SetInSlaveMode) {
- if (!(tempax & LockLCDBToA)) {
- if (ModeNo <= 0x13) {
- pVBInfo->VBInfo &=
- ~(SetSimuScanMode |
- SetInSlaveMode |
- SetCRT2ToLCD);
- pVBInfo->VBInfo |=
- XGI_SetCRT2ToLCDA |
- SetCRT2ToDualEdge;
- }
- }
- }
- }
- }
-
return 1;
}
unsigned char XGI_SearchModeID(unsigned short ModeNo,
unsigned short *ModeIdIndex, struct vb_device_info *pVBInfo)
{
- if (ModeNo <= 5)
- ModeNo |= 1;
- if (ModeNo <= 0x13) {
- for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
- if (pVBInfo->SModeIDTable[*ModeIdIndex].St_ModeID ==
- ModeNo)
- break;
- if (pVBInfo->SModeIDTable[*ModeIdIndex].St_ModeID ==
- 0xFF)
- return 0;
- }
-
- if (ModeNo == 0x07)
- (*ModeIdIndex)++; /* 400 lines */
- if (ModeNo <= 3)
- (*ModeIdIndex) += 2; /* 400 lines */
- /* else 350 lines */
- } else {
- for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
- if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID ==
- ModeNo)
- break;
- if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID ==
- 0xFF)
- return 0;
- }
+ for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
+ if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID == ModeNo)
+ break;
+ if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
+ return 0;
}
return 1;
@@ -3789,22 +3365,17 @@ static void XGI_GetCRT2ResInfo(unsigned short ModeNo,
{
unsigned short xres, yres, modeflag, resindex;
- resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
- if (ModeNo <= 0x13) {
- xres = pVBInfo->StResInfo[resindex].HTotal;
- yres = pVBInfo->StResInfo[resindex].VTotal;
- } else {
- xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
- yres = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
- /* si+St_ModeFlag */
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
+ yres = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
+ /* si+St_ModeFlag */
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- if (modeflag & HalfDCLK)
- xres *= 2;
+ if (modeflag & HalfDCLK)
+ xres *= 2;
- if (modeflag & DoubleScanMode)
- yres *= 2;
- }
+ if (modeflag & DoubleScanMode)
+ yres *= 2;
if (pVBInfo->VBInfo & SetCRT2ToLCD) {
if (pVBInfo->IF_DEF_LVDS == 0) {
@@ -3868,37 +3439,23 @@ static void XGI_GetRAMDAC2DATA(unsigned short ModeNo,
struct vb_device_info *pVBInfo)
{
unsigned short tempax, tempbx, temp1, temp2, modeflag = 0, tempcx,
- StandTableIndex, CRT1Index;
+ CRT1Index;
pVBInfo->RVBHCMAX = 1;
pVBInfo->RVBHCFACT = 1;
-
- if (ModeNo <= 0x13) {
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- StandTableIndex = XGI_GetModePtr(ModeNo, ModeIdIndex, pVBInfo);
- tempax = pVBInfo->StandTable[StandTableIndex].CRTC[0];
- tempbx = pVBInfo->StandTable[StandTableIndex].CRTC[6];
- temp1 = pVBInfo->StandTable[StandTableIndex].CRTC[7];
- } else {
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].
- Ext_CRT1CRTC;
- CRT1Index &= IndexMask;
- temp1 = (unsigned short) pVBInfo->
- XGINEWUB_CRT1Table[CRT1Index].CR[0];
- temp2 = (unsigned short) pVBInfo->
- XGINEWUB_CRT1Table[CRT1Index].CR[5];
- tempax = (temp1 & 0xFF) | ((temp2 & 0x03) << 8);
- tempbx = (unsigned short) pVBInfo->
- XGINEWUB_CRT1Table[CRT1Index].CR[8];
- tempcx = (unsigned short) pVBInfo->
- XGINEWUB_CRT1Table[CRT1Index].CR[14] << 8;
- tempcx &= 0x0100;
- tempcx = tempcx << 2;
- tempbx |= tempcx;
- temp1 = (unsigned short) pVBInfo->
- XGINEWUB_CRT1Table[CRT1Index].CR[9];
- }
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+ CRT1Index &= IndexMask;
+ temp1 = (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[0];
+ temp2 = (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[5];
+ tempax = (temp1 & 0xFF) | ((temp2 & 0x03) << 8);
+ tempbx = (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[8];
+ tempcx = (unsigned short)
+ pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[14] << 8;
+ tempcx &= 0x0100;
+ tempcx = tempcx << 2;
+ tempbx |= tempcx;
+ temp1 = (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[9];
if (temp1 & 0x01)
tempbx |= 0x0100;
@@ -3928,16 +3485,9 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex,
struct SiS_LCDData *LCDPtr = NULL;
struct SiS_TVData *TVPtr = NULL;
- if (ModeNo <= 0x13) {
- /* si+St_ResInfo */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
- } else {
- /* si+Ext_ResInfo */
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- }
-
+ /* si+Ext_ResInfo */
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
pVBInfo->NewFlickerMode = 0;
pVBInfo->RVBHRS = 50;
@@ -4141,11 +3691,7 @@ static unsigned short XGI_GetColorDepth(unsigned short ModeNo,
short index;
unsigned short modeflag;
- if (ModeNo <= 0x13)
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
index = (modeflag & ModeTypeMask) - ModeEGA;
if (index < 0)
@@ -4164,11 +3710,7 @@ static unsigned short XGI_GetOffset(unsigned short ModeNo,
ColorDepth[] = { 0x01, 0x02, 0x04 };
modeinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeInfo;
- if (ModeNo <= 0x14)
- infoflag = 0;
- else
- infoflag = pVBInfo->
- RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+ infoflag = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
index = (modeinfo >> 8) & 0xFF;
@@ -4228,12 +3770,9 @@ static void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
{
unsigned short tempcx = 0, CRT1Index = 0, resinfo = 0;
- if (ModeNo > 0x13) {
- CRT1Index = pVBInfo->
- RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
- CRT1Index &= IndexMask;
- resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- }
+ CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+ CRT1Index &= IndexMask;
+ resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
XGI_SetCRT2Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
HwDeviceExtension, pVBInfo);
@@ -4254,17 +3793,10 @@ static void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
unsigned short temp = 0, tempax = 0, tempbx = 0, tempcx = 0,
pushbx = 0, CRT1Index = 0, modeflag, resinfo = 0;
- if (ModeNo > 0x13) {
- CRT1Index = pVBInfo->
- RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
- CRT1Index &= IndexMask;
- resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- }
-
- if (ModeNo <= 0x13)
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+ CRT1Index &= IndexMask;
+ resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
/* bainy change table name */
if (modeflag & HalfDCLK) {
@@ -4422,18 +3954,11 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
unsigned short push1, push2, tempax, tempbx = 0, tempcx, temp, resinfo,
modeflag, CRT1Index;
- if (ModeNo <= 0x13) {
- /* si+St_ResInfo */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
- } else {
- /* si+Ext_ResInfo */
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- CRT1Index = pVBInfo->
- RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
- CRT1Index &= IndexMask;
- }
+ /* si+Ext_ResInfo */
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+ CRT1Index &= IndexMask;
if (!(pVBInfo->VBInfo & SetInSlaveMode))
return;
@@ -4500,8 +4025,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
temp -= 6;
if (pVBInfo->TVInfo & TVSimuMode) {
temp -= 4;
- if (ModeNo > 0x13)
- temp -= 10;
+ temp -= 10;
}
}
} else {
@@ -4523,14 +4047,6 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
if (pVBInfo->LCDResInfo != Panel_1280x960 &&
pVBInfo->VGAHDE >= 800) {
temp -= 7;
- if (pVBInfo->ModeType == ModeEGA &&
- pVBInfo->VGAVDE == 1024) {
- temp += 15;
- if (pVBInfo->LCDResInfo !=
- Panel_1280x1024)
- temp += 7;
- }
-
if (pVBInfo->VGAHDE >= 1280 &&
pVBInfo->LCDResInfo != Panel_1280x960 &&
(pVBInfo->LCDInfo & LCDNonExpanding))
@@ -4546,48 +4062,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
if (pVBInfo->VBInfo & SetCRT2ToTV) {
if (pVBInfo->TVInfo & TVSimuMode) {
- if ((ModeNo == 0x06) || (ModeNo == 0x10) || (ModeNo
- == 0x11) || (ModeNo == 0x13) || (ModeNo
- == 0x0F)) {
- xgifb_reg_set(pVBInfo->Part1Port, 0x07, 0x5b);
- xgifb_reg_set(pVBInfo->Part1Port, 0x08, 0x03);
- }
-
- if ((ModeNo == 0x00) || (ModeNo == 0x01)) {
- if (pVBInfo->TVInfo & SetNTSCTV) {
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x07, 0x2A);
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x08, 0x61);
- } else {
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x07, 0x2A);
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x08, 0x41);
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x0C, 0xF0);
- }
- }
-
- if ((ModeNo == 0x02) || (ModeNo == 0x03) || (ModeNo
- == 0x07)) {
- if (pVBInfo->TVInfo & SetNTSCTV) {
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x07, 0x54);
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x08, 0x00);
- } else {
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x07, 0x55);
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x08, 0x00);
- xgifb_reg_set(pVBInfo->Part1Port,
- 0x0C, 0xF0);
- }
- }
-
- if ((ModeNo == 0x04) || (ModeNo == 0x05) || (ModeNo
- == 0x0D) || (ModeNo == 0x50)) {
+ if (ModeNo == 0x50) {
if (pVBInfo->TVInfo & SetNTSCTV) {
xgifb_reg_set(pVBInfo->Part1Port,
0x07, 0x30);
@@ -4796,18 +4271,10 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
unsigned long longtemp, tempeax, tempebx, temp2, tempecx;
- if (ModeNo <= 0x13) {
- /* si+St_ResInfo */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
- crt2crtc = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- } else {
- /* si+Ext_ResInfo */
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- crt2crtc = pVBInfo->RefIndex[RefreshRateTableIndex].
- Ext_CRT2CRTC;
- }
+ /* si+Ext_ResInfo */
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ crt2crtc = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
tempax = 0;
@@ -5245,18 +4712,11 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
struct XGI_LCDDesStruct *LCDBDesPtr = NULL;
- if (ModeNo <= 0x13) {
- /* si+St_ResInfo */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
- } else {
- /* si+Ext_ResInfo */
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
- CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].
- Ext_CRT1CRTC;
- CRT1Index &= IndexMask;
- }
+ /* si+Ext_ResInfo */
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+ CRT1Index &= IndexMask;
if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
return;
@@ -5274,16 +4734,6 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
xgifb_reg_and_or(pVBInfo->Part2Port, 0x2B, 0x0F, temp);
temp = 0x01;
- if (pVBInfo->LCDResInfo == Panel_1280x1024) {
- if (pVBInfo->ModeType == ModeEGA) {
- if (pVBInfo->VGAHDE >= 1024) {
- temp = 0x02;
- if (pVBInfo->LCDInfo & XGI_LCDVESATiming)
- temp = 0x01;
- }
- }
- }
-
xgifb_reg_set(pVBInfo->Part2Port, 0x0B, temp);
tempbx = pVBInfo->VDE; /* RTVACTEO=(VDE-1)&0xFF */
push1 = tempbx;
@@ -5542,12 +4992,8 @@ static void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex,
unsigned char *tempdi;
unsigned short modeflag;
- if (ModeNo <= 0x13)
- /* si+St_ResInfo */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- /* si+Ext_ResInfo */
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ /* si+Ext_ResInfo */
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
xgifb_reg_set(pVBInfo->Part3Port, 0x00, 0x00);
if (pVBInfo->TVInfo & TVSetPAL) {
@@ -5605,13 +5051,8 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex,
unsigned long tempebx, tempeax, templong;
- if (ModeNo <= 0x13)
- /* si+St_ResInfo */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- /* si+Ext_ResInfo */
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
+ /* si+Ext_ResInfo */
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
temp = pVBInfo->RVBHCFACT;
xgifb_reg_set(pVBInfo->Part4Port, 0x13, temp);
@@ -5818,32 +5259,22 @@ static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info,
{
unsigned short xres, yres, colordepth, modeflag, resindex;
- resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
- if (ModeNo <= 0x13) {
- xres = pVBInfo->StResInfo[resindex].HTotal;
- yres = pVBInfo->StResInfo[resindex].VTotal;
- /* si+St_ResInfo */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else {
- xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
- yres = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
- /* si+St_ModeFlag */
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
+ resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
+ yres = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
+ /* si+St_ModeFlag */
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
if (!(modeflag & Charx8Dot)) {
xres /= 9;
xres *= 8;
}
- if (ModeNo > 0x13) {
- if ((ModeNo > 0x13) && (modeflag & HalfDCLK))
- xres *= 2;
-
- if ((ModeNo > 0x13) && (modeflag & DoubleScanMode))
- yres *= 2;
+ if ((ModeNo > 0x13) && (modeflag & HalfDCLK))
+ xres *= 2;
- }
+ if ((ModeNo > 0x13) && (modeflag & DoubleScanMode))
+ yres *= 2;
if (xres > xgifb_info->lvds_data.LVDSHDE)
return 0;
@@ -5851,16 +5282,11 @@ static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info,
if (yres > xgifb_info->lvds_data.LVDSVDE)
return 0;
- if (ModeNo > 0x13) {
- if (xres != xgifb_info->lvds_data.LVDSHDE ||
- yres != xgifb_info->lvds_data.LVDSVDE) {
- colordepth = XGI_GetColorDepth(ModeNo,
- ModeIdIndex,
- pVBInfo);
- if (colordepth > 2)
- return 0;
-
- }
+ if (xres != xgifb_info->lvds_data.LVDSHDE ||
+ yres != xgifb_info->lvds_data.LVDSVDE) {
+ colordepth = XGI_GetColorDepth(ModeNo, ModeIdIndex, pVBInfo);
+ if (colordepth > 2)
+ return 0;
}
return 1;
}
@@ -5895,18 +5321,11 @@ static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info,
else
XGI_SetXG21FPBits(pVBInfo);
- resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
- if (ModeNo <= 0x13) {
- xres = pVBInfo->StResInfo[resindex].HTotal;
- yres = pVBInfo->StResInfo[resindex].VTotal;
- /* si+St_ResInfo */
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else {
- xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
- yres = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
- /* si+St_ModeFlag */
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
+ resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
+ yres = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
+ /* si+St_ModeFlag */
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
if (!(modeflag & Charx8Dot))
xres = xres * 8 / 9;
@@ -5914,8 +5333,6 @@ static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info,
LVDSHT = xgifb_info->lvds_data.LVDSHT;
LVDSHBS = xres + (xgifb_info->lvds_data.LVDSHDE - xres) / 2;
- if ((ModeNo <= 0x13) && (modeflag & HalfDCLK))
- LVDSHBS -= xres / 4;
if (LVDSHBS > LVDSHT)
LVDSHBS -= LVDSHT;
@@ -5933,7 +5350,7 @@ static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info,
LVDSVT = xgifb_info->lvds_data.LVDSVT;
LVDSVBS = yres + (xgifb_info->lvds_data.LVDSVDE - yres) / 2;
- if ((ModeNo > 0x13) && (modeflag & DoubleScanMode))
+ if (modeflag & DoubleScanMode)
LVDSVBS += yres / 2;
if (LVDSVBS > LVDSVT)
@@ -6527,7 +5944,7 @@ static void XGI_SetAntiFlicker(unsigned short ModeNo,
unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
- unsigned short tempbx, index;
+ unsigned short tempbx;
unsigned char tempah;
@@ -6536,13 +5953,6 @@ static void XGI_SetAntiFlicker(unsigned short ModeNo,
tempbx = XGI_GetTVPtrIndex(pVBInfo);
tempbx &= 0xFE;
-
- if (ModeNo <= 0x13)
- index = pVBInfo->SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
- else
- index = pVBInfo->EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
-
- tempbx += index;
tempah = TVAntiFlickList[tempbx];
tempah = tempah << 4;
@@ -6553,19 +5963,12 @@ static void XGI_SetEdgeEnhance(unsigned short ModeNo,
unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
- unsigned short tempbx, index;
+ unsigned short tempbx;
unsigned char tempah;
tempbx = XGI_GetTVPtrIndex(pVBInfo);
tempbx &= 0xFE;
-
- if (ModeNo <= 0x13)
- index = pVBInfo->SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
- else
- index = pVBInfo->EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
-
- tempbx += index;
tempah = TVEdgeList[tempbx];
tempah = tempah << 5;
@@ -6631,13 +6034,7 @@ static void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex,
return;
}
- if (ModeNo <= 0x13)
- tempal = pVBInfo->SModeIDTable[ModeIdIndex].
- VB_StTVYFilterIndex;
- else
- tempal = pVBInfo->EModeIDTable[ModeIdIndex].
- VB_ExtTVYFilterIndex;
-
+ tempal = pVBInfo->EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
if (tempcl == 0)
index = tempal * 4;
else
@@ -6712,16 +6109,14 @@ static void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV
| SetCRT2ToLCD)) {
tempah = 0x40; /* BTDRAM */
- if (ModeNo > 0x13) {
- tempcl = pVBInfo->ModeType;
- tempcl -= ModeVGA;
- if (tempcl >= 0) {
- /* BT Color */
- tempah = (0x008 >> tempcl);
- if (tempah == 0)
- tempah = 1;
- tempah |= 0x040;
- }
+ tempcl = pVBInfo->ModeType;
+ tempcl -= ModeVGA;
+ if (tempcl >= 0) {
+ /* BT Color */
+ tempah = (0x008 >> tempcl);
+ if (tempah == 0)
+ tempah = 1;
+ tempah |= 0x040;
}
if (pVBInfo->VBInfo & SetInSlaveMode)
tempah ^= 0x50; /* BTDAC */
@@ -6797,10 +6192,8 @@ static void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
if (pVBInfo->VBInfo & SetCRT2ToTV) {
tempah |= 0x020;
- if (ModeNo > 0x13) {
- if (pVBInfo->VBInfo & DriverMode)
- tempah = tempah ^ 0x20;
- }
+ if (pVBInfo->VBInfo & DriverMode)
+ tempah = tempah ^ 0x20;
}
xgifb_reg_and_or(pVBInfo->Part4Port, 0x0D, ~0x0BF, tempah);
@@ -6925,13 +6318,7 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
unsigned short RefreshRateTableIndex, i, modeflag, index, temp;
- if (ModeNo <= 0x13)
- modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
- if (ModeNo < 0x14)
- return 0xFFFF;
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
index = xgifb_reg_get(pVBInfo->P3d4, 0x33);
index = index >> pVBInfo->SelectCRT2Rate;
@@ -7297,16 +6684,13 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info,
unsigned short ModeNo, unsigned short ModeIdIndex,
struct vb_device_info *pVBInfo)
{
- unsigned short StandTableIndex, RefreshRateTableIndex, b3CC, temp;
+ unsigned short RefreshRateTableIndex, temp;
- unsigned short XGINew_P3cc = pVBInfo->P3cc;
-
- StandTableIndex = XGI_GetModePtr(ModeNo, ModeIdIndex, pVBInfo);
- XGI_SetSeqRegs(ModeNo, StandTableIndex, ModeIdIndex, pVBInfo);
- outb(pVBInfo->StandTable[StandTableIndex].MISC, pVBInfo->P3c2);
- XGI_SetCRTCRegs(HwDeviceExtension, StandTableIndex, pVBInfo);
- XGI_SetATTRegs(ModeNo, StandTableIndex, ModeIdIndex, pVBInfo);
- XGI_SetGRCRegs(StandTableIndex, pVBInfo);
+ XGI_SetSeqRegs(ModeNo, ModeIdIndex, pVBInfo);
+ outb(pVBInfo->StandTable->MISC, pVBInfo->P3c2);
+ XGI_SetCRTCRegs(HwDeviceExtension, pVBInfo);
+ XGI_SetATTRegs(ModeNo, ModeIdIndex, pVBInfo);
+ XGI_SetGRCRegs(pVBInfo);
XGI_ClearExt1Regs(pVBInfo);
if (HwDeviceExtension->jChipType == XG27) {
@@ -7340,22 +6724,6 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info,
RefreshRateTableIndex, pVBInfo);
}
- if ((HwDeviceExtension->jChipType >= XG20) &&
- (HwDeviceExtension->jChipType < XG27)) { /* fix H/W DCLK/2 bug */
- if ((ModeNo == 0x00) | (ModeNo == 0x01)) {
- xgifb_reg_set(pVBInfo->P3c4, 0x2B, 0x4E);
- xgifb_reg_set(pVBInfo->P3c4, 0x2C, 0xE9);
- b3CC = (unsigned char) inb(XGINew_P3cc);
- outb((b3CC |= 0x0C), XGINew_P3cc);
- } else if ((ModeNo == 0x04) | (ModeNo == 0x05) | (ModeNo
- == 0x0D)) {
- xgifb_reg_set(pVBInfo->P3c4, 0x2B, 0x1B);
- xgifb_reg_set(pVBInfo->P3c4, 0x2C, 0xE3);
- b3CC = (unsigned char) inb(XGINew_P3cc);
- outb((b3CC |= 0x0C), XGINew_P3cc);
- }
- }
-
if (HwDeviceExtension->jChipType >= XG21) {
temp = xgifb_reg_get(pVBInfo->P3d4, 0x38);
if (temp & 0xA0) {
@@ -7394,7 +6762,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
unsigned short ModeIdIndex;
struct vb_device_info VBINF;
struct vb_device_info *pVBInfo = &VBINF;
- pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
+ pVBInfo->BaseAddr = xgifb_info->vga_base;
pVBInfo->IF_DEF_LVDS = 0;
pVBInfo->IF_DEF_LCDA = 1;
@@ -7509,13 +6877,8 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
pVBInfo))
return 0;
- if (ModeNo <= 0x13) {
- pVBInfo->ModeType = pVBInfo->SModeIDTable[ModeIdIndex].
- St_ModeFlag & ModeTypeMask;
- } else {
- pVBInfo->ModeType = pVBInfo->EModeIDTable[ModeIdIndex].
+ pVBInfo->ModeType = pVBInfo->EModeIDTable[ModeIdIndex].
Ext_ModeFlag & ModeTypeMask;
- }
pVBInfo->SetFlag = 0;
pVBInfo->VBInfo = DisableCRT2Display;
diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
index a5bd56af92b1..38f47ffc69c4 100644
--- a/drivers/staging/xgifb/vb_struct.h
+++ b/drivers/staging/xgifb/vb_struct.h
@@ -10,28 +10,11 @@ struct XGI_LVDSCRT1VDataStruct {
unsigned char Reg[7];
};
-struct XGI_StStruct {
- unsigned char St_ModeID;
- unsigned short St_ModeFlag;
- unsigned char St_StTableIndex;
- unsigned char St_CRT2CRTC;
- unsigned char St_CRT2CRTC2;
- unsigned char St_ResInfo;
- unsigned char VB_StTVFlickerIndex;
- unsigned char VB_StTVEdgeIndex;
- unsigned char VB_StTVYFilterIndex;
-};
-
struct XGI_ExtStruct {
unsigned char Ext_ModeID;
unsigned short Ext_ModeFlag;
unsigned short Ext_ModeInfo;
- unsigned short Ext_Point;
- unsigned short Ext_VESAID;
- unsigned char Ext_VESAMEMSize;
unsigned char Ext_RESINFO;
- unsigned char VB_ExtTVFlickerIndex;
- unsigned char VB_ExtTVEdgeIndex;
unsigned char VB_ExtTVYFilterIndex;
unsigned char REFindex;
};
@@ -68,14 +51,6 @@ struct XGI_LCDDataTablStruct {
unsigned short DATAPTR;
};
-struct XGI330_LCDDataDesStruct {
- unsigned short LCDHDES;
- unsigned short LCDHRS;
- unsigned short LCDVDES;
- unsigned short LCDVRS;
-};
-
-
struct XGI330_LVDSDataStruct {
unsigned short VGAHT;
unsigned short VGAVT;
@@ -236,7 +211,6 @@ struct vb_device_info {
void __iomem *FBAddr;
unsigned long BaseAddr;
- unsigned long RelIO;
unsigned char (*CR6B)[4];
unsigned char (*CR6E)[4];
@@ -314,7 +288,6 @@ struct vb_device_info {
struct XGI_TimingHStruct *TimingH;
struct XGI_TimingVStruct *TimingV;
- struct XGI_StStruct *SModeIDTable;
struct SiS_StandTable_S *StandTable;
struct XGI_ExtStruct *EModeIDTable;
struct XGI_Ext2Struct *RefIndex;
diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
index e8d6f674b274..d22e599cb305 100644
--- a/drivers/staging/xgifb/vb_table.h
+++ b/drivers/staging/xgifb/vb_table.h
@@ -135,609 +135,92 @@ static unsigned char XGI330_SR33;
static unsigned char XG40_CRCF = 0x13;
static unsigned char XG40_DRAMTypeDefinition = 0xFF ;
-static struct XGI_StStruct XGI330_SModeIDTable[] = {
- {0x01, 0x9208, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00},
- {0x01, 0x1210, 0x14, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00},
- {0x01, 0x1010, 0x17, 0x02, 0x11, 0x00, 0x00, 0x01, 0x01},
- {0x03, 0x8208, 0x03, 0x00, 0x14, 0x00, 0x00, 0x01, 0x02},
- {0x03, 0x0210, 0x16, 0x01, 0x04, 0x01, 0x00, 0x01, 0x02},
- {0x03, 0x0010, 0x18, 0x02, 0x15, 0x00, 0x00, 0x01, 0x03},
- {0x05, 0x9209, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04},
- {0x06, 0x8209, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05},
- {0x07, 0x0000, 0x07, 0x03, 0x05, 0x03, 0x00, 0x01, 0x03},
- {0x07, 0x0000, 0x19, 0x02, 0x15, 0x02, 0x00, 0x01, 0x03},
- {0x0d, 0x920a, 0x0d, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04},
- {0x0e, 0x820a, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05},
- {0x0f, 0x0202, 0x11, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05},
- {0x10, 0x0212, 0x12, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05},
- {0x11, 0x0212, 0x1a, 0x04, 0x24, 0x04, 0x00, 0x00, 0x05},
- {0x12, 0x0212, 0x1b, 0x04, 0x24, 0x04, 0x00, 0x00, 0x05},
- {0x13, 0x021b, 0x1c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04},
- {0x12, 0x0010, 0x18, 0x02, 0x24, 0x02, 0x00, 0x00, 0x05},/* St_CRT2CRTC2
- not sure */
- {0x12, 0x0210, 0x18, 0x01, 0x24, 0x01, 0x00, 0x00, 0x05},/* St_CRT2CRTC2
- not sure */
- {0xff, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
-};
-
-
static struct XGI_ExtStruct XGI330_EModeIDTable[] = {
- {0x6a, 0x2212, 0x0407, 0x3a81, 0x0102, 0x08,
- 0x07, 0x00, 0x00, 0x07, 0x0e},
- {0x2e, 0x0a1b, 0x0306, 0x3a57, 0x0101, 0x08,
- 0x06, 0x00, 0x00, 0x05, 0x06},
- {0x2f, 0x0a1b, 0x0305, 0x3a50, 0x0100, 0x08,
- 0x05, 0x00, 0x00, 0x05, 0x05},
- {0x30, 0x2a1b, 0x0407, 0x3a81, 0x0103, 0x08,
- 0x07, 0x00, 0x00, 0x07, 0x0e},
- {0x31, 0x0a1b, 0x030d, 0x3b85, 0x0000, 0x08,
- 0x0d, 0x00, 0x00, 0x06, 0x3d},
- {0x32, 0x0a1b, 0x0a0e, 0x3b8c, 0x0000, 0x08,
- 0x0e, 0x00, 0x00, 0x06, 0x3e},
- {0x33, 0x0a1d, 0x0a0d, 0x3b85, 0x0000, 0x08,
- 0x0d, 0x00, 0x00, 0x06, 0x3d},
- {0x34, 0x2a1d, 0x0a0e, 0x3b8c, 0x0000, 0x08,
- 0x0e, 0x00, 0x00, 0x06, 0x3e},
- {0x35, 0x0a1f, 0x0a0d, 0x3b85, 0x0000, 0x08,
- 0x0d, 0x00, 0x00, 0x06, 0x3d},
- {0x36, 0x2a1f, 0x0a0e, 0x3b8c, 0x0000, 0x08,
- 0x0e, 0x00, 0x00, 0x06, 0x3e},
- {0x37, 0x0212, 0x0508, 0x3aab, 0x0104, 0x08,
- 0x08, 0x00, 0x00, 0x00, 0x16},
- {0x38, 0x0a1b, 0x0508, 0x3aab, 0x0105, 0x08,
- 0x08, 0x00, 0x00, 0x00, 0x16},
- {0x3a, 0x0e3b, 0x0609, 0x3adc, 0x0107, 0x08,
- 0x09, 0x00, 0x00, 0x00, 0x1e},
- {0x3c, 0x0e3b, 0x070a, 0x3af2, 0x0130, 0x08,
- 0x0a, 0x00, 0x00, 0x00, 0x22}, /* mode 1600x1200
+ {0x2e, 0x0a1b, 0x0306, 0x06, 0x05, 0x06},
+ {0x2f, 0x0a1b, 0x0305, 0x05, 0x05, 0x05},
+ {0x30, 0x2a1b, 0x0407, 0x07, 0x07, 0x0e},
+ {0x31, 0x0a1b, 0x030d, 0x0d, 0x06, 0x3d},
+ {0x32, 0x0a1b, 0x0a0e, 0x0e, 0x06, 0x3e},
+ {0x33, 0x0a1d, 0x0a0d, 0x0d, 0x06, 0x3d},
+ {0x34, 0x2a1d, 0x0a0e, 0x0e, 0x06, 0x3e},
+ {0x35, 0x0a1f, 0x0a0d, 0x0d, 0x06, 0x3d},
+ {0x36, 0x2a1f, 0x0a0e, 0x0e, 0x06, 0x3e},
+ {0x38, 0x0a1b, 0x0508, 0x08, 0x00, 0x16},
+ {0x3a, 0x0e3b, 0x0609, 0x09, 0x00, 0x1e},
+ {0x3c, 0x0e3b, 0x070a, 0x0a, 0x00, 0x22}, /* mode 1600x1200
add CRT2MODE [2003/10/07] */
- {0x3d, 0x0e7d, 0x070a, 0x3af2, 0x0131, 0x08,
- 0x0a, 0x00, 0x00, 0x00, 0x22}, /* mode 1600x1200
+ {0x3d, 0x0e7d, 0x070a, 0x0a, 0x00, 0x22}, /* mode 1600x1200
add CRT2MODE */
- {0x40, 0x9a1c, 0x0000, 0x3a34, 0x010d, 0x08,
- 0x00, 0x00, 0x00, 0x04, 0x00},
- {0x41, 0x9a1d, 0x0000, 0x3a34, 0x010e, 0x08,
- 0x00, 0x00, 0x00, 0x04, 0x00}, /* ModeIdIndex = 0x10 */
- {0x43, 0x0a1c, 0x0306, 0x3a57, 0x0110, 0x08,
- 0x06, 0x00, 0x00, 0x05, 0x06},
- {0x44, 0x0a1d, 0x0306, 0x3a57, 0x0111, 0x08,
- 0x06, 0x00, 0x00, 0x05, 0x06},
- {0x46, 0x2a1c, 0x0407, 0x3a81, 0x0113, 0x08,
- 0x07, 0x00, 0x00, 0x07, 0x0e},
- {0x47, 0x2a1d, 0x0407, 0x3a81, 0x0114, 0x08,
- 0x07, 0x00, 0x00, 0x07, 0x0e},
- {0x49, 0x0a3c, 0x0508, 0x3aab, 0x0116, 0x08,
- 0x08, 0x00, 0x00, 0x00, 0x16},
- {0x4a, 0x0a3d, 0x0508, 0x3aab, 0x0117, 0x08,
- 0x08, 0x00, 0x00, 0x00, 0x16},
- {0x4c, 0x0e7c, 0x0609, 0x3adc, 0x0119, 0x08,
- 0x09, 0x00, 0x00, 0x00, 0x1e},
- {0x4d, 0x0e7d, 0x0609, 0x3adc, 0x011a, 0x08,
- 0x09, 0x00, 0x00, 0x00, 0x1e},
- {0x50, 0x9a1b, 0x0001, 0x3a3b, 0x0132, 0x08,
- 0x01, 0x00, 0x00, 0x04, 0x02},
- {0x51, 0xba1b, 0x0103, 0x3a42, 0x0133, 0x08,
- 0x03, 0x00, 0x00, 0x07, 0x03},
- {0x52, 0x9a1b, 0x0204, 0x3a49, 0x0134, 0x08,
- 0x04, 0x00, 0x00, 0x00, 0x04},
- {0x56, 0x9a1d, 0x0001, 0x3a3b, 0x0135, 0x08,
- 0x01, 0x00, 0x00, 0x04, 0x02},
- {0x57, 0xba1d, 0x0103, 0x3a42, 0x0136, 0x08,
- 0x03, 0x00, 0x00, 0x07, 0x03},
- {0x58, 0x9a1d, 0x0204, 0x3a49, 0x0137, 0x08,
- 0x04, 0x00, 0x00, 0x00, 0x04},
- {0x59, 0x9a1b, 0x0000, 0x3a34, 0x0138, 0x08,
- 0x00, 0x00, 0x00, 0x04, 0x00},
- {0x5A, 0x021b, 0x0014, 0x3b83, 0x0138, 0x08,
- 0x01, 0x00, 0x00, 0x04, 0x3f}, /* ModeIdIndex = 0x20 */
- {0x5B, 0x0a1d, 0x0014, 0x3b83, 0x0135, 0x08,
- 0x01, 0x00, 0x00, 0x04, 0x3f},
- {0x5d, 0x0a1d, 0x0305, 0x3a50, 0x0139, 0x08,
- 0x05, 0x00, 0x00, 0x07, 0x05},
- {0x62, 0x0a3f, 0x0306, 0x3a57, 0x013a, 0x08,
- 0x06, 0x00, 0x00, 0x05, 0x06},
- {0x63, 0x2a3f, 0x0407, 0x3a81, 0x013b, 0x08,
- 0x07, 0x00, 0x00, 0x07, 0x0e},
- {0x64, 0x0a7f, 0x0508, 0x3aab, 0x013c, 0x08,
- 0x08, 0x00, 0x00, 0x00, 0x16},
- {0x65, 0x0eff, 0x0609, 0x3adc, 0x013d, 0x08,
- 0x09, 0x00, 0x00, 0x00, 0x1e},
- {0x66, 0x0eff, 0x070a, 0x3af2, 0x013e, 0x08,
- 0x0a, 0x00, 0x00, 0x00, 0x22}, /* mode 1600x1200
+ {0x40, 0x9a1c, 0x0000, 0x00, 0x04, 0x00},
+ {0x41, 0x9a1d, 0x0000, 0x00, 0x04, 0x00},
+ {0x43, 0x0a1c, 0x0306, 0x06, 0x05, 0x06},
+ {0x44, 0x0a1d, 0x0306, 0x06, 0x05, 0x06},
+ {0x46, 0x2a1c, 0x0407, 0x07, 0x07, 0x0e},
+ {0x47, 0x2a1d, 0x0407, 0x07, 0x07, 0x0e},
+ {0x49, 0x0a3c, 0x0508, 0x08, 0x00, 0x16},
+ {0x4a, 0x0a3d, 0x0508, 0x08, 0x00, 0x16},
+ {0x4c, 0x0e7c, 0x0609, 0x09, 0x00, 0x1e},
+ {0x4d, 0x0e7d, 0x0609, 0x09, 0x00, 0x1e},
+ {0x50, 0x9a1b, 0x0001, 0x01, 0x04, 0x02},
+ {0x51, 0xba1b, 0x0103, 0x03, 0x07, 0x03},
+ {0x52, 0x9a1b, 0x0204, 0x04, 0x00, 0x04},
+ {0x56, 0x9a1d, 0x0001, 0x01, 0x04, 0x02},
+ {0x57, 0xba1d, 0x0103, 0x03, 0x07, 0x03},
+ {0x58, 0x9a1d, 0x0204, 0x04, 0x00, 0x04},
+ {0x59, 0x9a1b, 0x0000, 0x00, 0x04, 0x00},
+ {0x5A, 0x021b, 0x0014, 0x01, 0x04, 0x3f},
+ {0x5B, 0x0a1d, 0x0014, 0x01, 0x04, 0x3f},
+ {0x5d, 0x0a1d, 0x0305, 0x05, 0x07, 0x05},
+ {0x62, 0x0a3f, 0x0306, 0x06, 0x05, 0x06},
+ {0x63, 0x2a3f, 0x0407, 0x07, 0x07, 0x0e},
+ {0x64, 0x0a7f, 0x0508, 0x08, 0x00, 0x16},
+ {0x65, 0x0eff, 0x0609, 0x09, 0x00, 0x1e},
+ {0x66, 0x0eff, 0x070a, 0x0a, 0x00, 0x22}, /* mode 1600x1200
add CRT2MODE */
- {0x68, 0x067b, 0x080b, 0x3b17, 0x013f, 0x08,
- 0x0b, 0x00, 0x00, 0x00, 0x29},
- {0x69, 0x06fd, 0x080b, 0x3b17, 0x0140, 0x08,
- 0x0b, 0x00, 0x00, 0x00, 0x29},
- {0x6b, 0x07ff, 0x080b, 0x3b17, 0x0141, 0x10,
- 0x0b, 0x00, 0x00, 0x00, 0x29},
- {0x6c, 0x067b, 0x090c, 0x3b37, 0x0000, 0x08,
- 0x0c, 0x00, 0x00, 0x00, 0x2f},
- {0x6d, 0x06fd, 0x090c, 0x3b37, 0x0000, 0x10,
- 0x0c, 0x00, 0x00, 0x00, 0x2f},
- {0x6e, 0x07ff, 0x090c, 0x3b37, 0x0000, 0x10,
- 0x0c, 0x00, 0x00, 0x00, 0x2f},
- {0x70, 0x2a1b, 0x0410, 0x3b52, 0x0000, 0x08,
- 0x10, 0x00, 0x00, 0x07, 0x34},
- {0x71, 0x0a1b, 0x0511, 0x3b63, 0x0000, 0x08,
- 0x11, 0x00, 0x00, 0x00, 0x37},
- {0x74, 0x0a1d, 0x0511, 0x3b63, 0x0000, 0x08,
- 0x11, 0x00, 0x00, 0x00, 0x37}, /* ModeIdIndex = 0x30 */
- {0x75, 0x0a3d, 0x0612, 0x3b74, 0x0000, 0x08,
- 0x12, 0x00, 0x00, 0x00, 0x3a},
- {0x76, 0x2a1f, 0x0410, 0x3b52, 0x0000, 0x08,
- 0x10, 0x00, 0x00, 0x07, 0x34},
- {0x77, 0x0a1f, 0x0511, 0x3b63, 0x0000, 0x08,
- 0x11, 0x00, 0x00, 0x00, 0x37},
- {0x78, 0x0a3f, 0x0612, 0x3b74, 0x0000, 0x08,
- 0x12, 0x00, 0x00, 0x00, 0x3a},
- {0x79, 0x0a3b, 0x0612, 0x3b74, 0x0000, 0x08,
- 0x12, 0x00, 0x00, 0x00, 0x3a},
- {0x7a, 0x2a1d, 0x0410, 0x3b52, 0x0000, 0x08,
- 0x10, 0x00, 0x00, 0x07, 0x34},
- {0x7b, 0x0e3b, 0x060f, 0x3ad0, 0x0000, 0x08,
- 0x0f, 0x00, 0x00, 0x00, 0x1d},
- {0x7c, 0x0e7d, 0x060f, 0x3ad0, 0x0000, 0x08,
- 0x0f, 0x00, 0x00, 0x00, 0x1d},
- {0x7d, 0x0eff, 0x060f, 0x3ad0, 0x0000, 0x08,
- 0x0f, 0x00, 0x00, 0x00, 0x1d},
- {0x20, 0x0e3b, 0x0D16, 0x49e0, 0x0000, 0x08,
- 0x16, 0x00, 0x00, 0x00, 0x43},
- {0x21, 0x0e7d, 0x0D16, 0x49e0, 0x0000, 0x08,
- 0x16, 0x00, 0x00, 0x00, 0x43},
- {0x22, 0x0eff, 0x0D16, 0x49e0, 0x0000, 0x08,
- 0x16, 0x00, 0x00, 0x00, 0x43},
- {0x23, 0x0e3b, 0x0614, 0x49d5, 0x0000, 0x08,
- 0x14, 0x00, 0x00, 0x00, 0x41},
- {0x24, 0x0e7d, 0x0614, 0x49d5, 0x0000, 0x08,
- 0x14, 0x00, 0x00, 0x00, 0x41},
- {0x25, 0x0eff, 0x0614, 0x49d5, 0x0000, 0x08,
- 0x14, 0x00, 0x00, 0x00, 0x41},
- {0x26, 0x063b, 0x0c15, 0x49dc, 0x0000, 0x08,
- 0x15, 0x00, 0x00, 0x00, 0x42}, /* ModeIdIndex = 0x40 */
- {0x27, 0x067d, 0x0c15, 0x49dc, 0x0000, 0x08,
- 0x15, 0x00, 0x00, 0x00, 0x42},
- {0x28, 0x06ff, 0x0c15, 0x49dc, 0x0000, 0x08,
- 0x15, 0x00, 0x00, 0x00, 0x42},
- {0xff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}
-};
-
-static struct SiS_StandTable_S XGI330_StandTable[] = {
-/* MD_0_200 */
- {
- 0x28, 0x18, 0x08, 0x0800,
- {0x09, 0x03, 0x00, 0x02},
- 0x63,
- {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
- 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
- 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x08, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
- 0xff}
- },
-/* MD_1_200 */
- {
- 0x28, 0x18, 0x08, 0x0800,
- {0x09, 0x03, 0x00, 0x02},
- 0x63,
- {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
- 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
- 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x08, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
- 0xff}
- },
-/* MD_2_200 */
- {
- 0x50, 0x18, 0x08, 0x1000,
- {0x01, 0x03, 0x00, 0x02},
- 0x63,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
- 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
- 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x08, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
- 0xff}
- },
-/* MD_3_200 */
- {
- 0x50, 0x18, 0x08, 0x1000,
- {0x01, 0x03, 0x00, 0x02},
- 0x63,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
- 0x00, 0xc7, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
- 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x08, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
- 0xff}
- },
-/* MD_4 */
- {
- 0x28, 0x18, 0x08, 0x4000,
- {0x09, 0x03, 0x00, 0x02},
- 0x63,
- {0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0xbf, 0x1f,
- 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2,
- 0xff},
- {0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x01, 0x00, 0x03, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x00,
- 0xff}
- },
-/* MD_5 */
- {
- 0x28, 0x18, 0x08, 0x4000,
- {0x09, 0x03, 0x00, 0x02},
- 0x63,
- {0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0xbf, 0x1f,
- 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2,
- 0xff},
- {0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x01, 0x00, 0x03, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x00,
- 0xff}
- },
-/* MD_6 */
- {
- 0x50, 0x18, 0x08, 0x4000,
- {0x01, 0x01, 0x00, 0x06},
- 0x63,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
- 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xc2,
- 0xff},
- {0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
- 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
- 0x01, 0x00, 0x01, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00,
- 0xff}
- },
-/* MD_7 */
- {
- 0x50, 0x18, 0x0e, 0x1000,
- {0x00, 0x03, 0x00, 0x03},
- 0xa6,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
- 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
- 0x83, 0x85, 0x5d, 0x28, 0x0d, 0x63, 0xba, 0xa3,
- 0xff},
- {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
- 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x0e, 0x00, 0x0f, 0x08},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x00,
- 0xff}
- },
-/* MDA_DAC */
- {
- 0x00, 0x00, 0x00, 0x0000,
- {0x00, 0x00, 0x00, 0x15},
- 0x15,
- {0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3f, 0x3f,
- 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00,
- 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15},
- {0x15, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
- 0x3f}
- },
-/* CGA_DAC */
- {
- 0x00, 0x10, 0x04, 0x0114,
- {0x11, 0x09, 0x15, 0x00},
- 0x10,
- {0x04, 0x14, 0x01, 0x11, 0x09, 0x15, 0x2a, 0x3a,
- 0x2e, 0x3e, 0x2b, 0x3b, 0x2f, 0x3f, 0x2a, 0x3a,
- 0x2e, 0x3e, 0x2b, 0x3b, 0x2f, 0x3f, 0x00, 0x10,
- 0x04},
- {0x14, 0x01, 0x11, 0x09, 0x15, 0x00, 0x10, 0x04,
- 0x14, 0x01, 0x11, 0x09, 0x15, 0x2a, 0x3a, 0x2e,
- 0x3e, 0x2b, 0x3b, 0x2f},
- {0x3f, 0x2a, 0x3a, 0x2e, 0x3e, 0x2b, 0x3b, 0x2f,
- 0x3f}
- },
-/* EGA_DAC */
- {
- 0x00, 0x10, 0x04, 0x0114,
- {0x11, 0x05, 0x15, 0x20},
- 0x30,
- {0x24, 0x34, 0x21, 0x31, 0x25, 0x35, 0x08, 0x18,
- 0x0c, 0x1c, 0x09, 0x19, 0x0d, 0x1d, 0x28, 0x38,
- 0x2c, 0x3c, 0x29, 0x39, 0x2d, 0x3d, 0x02, 0x12,
- 0x06},
- {0x16, 0x03, 0x13, 0x07, 0x17, 0x22, 0x32, 0x26,
- 0x36, 0x23, 0x33, 0x27, 0x37, 0x0a, 0x1a, 0x0e,
- 0x1e, 0x0b, 0x1b, 0x0f},
- {0x1f, 0x2a, 0x3a, 0x2e, 0x3e, 0x2b, 0x3b, 0x2f,
- 0x3f}
- },
-/* VGA_DAC */
- {
- 0x00, 0x10, 0x04, 0x0114,
- {0x11, 0x09, 0x15, 0x2a},
- 0x3a,
- {0x2e, 0x3e, 0x2b, 0x3b, 0x2f, 0x3f, 0x00, 0x05,
- 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x18, 0x1c, 0x20,
- 0x24, 0x28, 0x2d, 0x32, 0x38, 0x3f, 0x00, 0x10,
- 0x1f},
- {0x2f, 0x3f, 0x1f, 0x27, 0x2f, 0x37, 0x3f, 0x2d,
- 0x31, 0x36, 0x3a, 0x3f, 0x00, 0x07, 0x0e, 0x15,
- 0x1c, 0x0e, 0x11, 0x15},
- {0x18, 0x1c, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x00,
- 0x04}
- },
- {
- 0x08, 0x0c, 0x10, 0x0a08,
- {0x0c, 0x0e, 0x10, 0x0b},
- 0x0c,
- {0x0d, 0x0f, 0x10, 0x10, 0x01, 0x08, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x01, 0x00,
- 0x04, 0x04, 0x01, 0x00, 0x05, 0x02, 0x05, 0x00,
- 0x06},
- {0x01, 0x06, 0x05, 0x06, 0x00, 0x08, 0x01, 0x08,
- 0x00, 0x07, 0x02, 0x07, 0x06, 0x07, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00}
- },
-/* MD_D */
- {
- 0x28, 0x18, 0x08, 0x2000,
- {0x09, 0x0f, 0x00, 0x06},
- 0x63,
- {0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0xbf, 0x1f,
- 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xe3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x01, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
- 0xff}
- },
-/* MD_E */
- {
- 0x50, 0x18, 0x08, 0x4000,
- {0x01, 0x0f, 0x00, 0x06},
- 0x63,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
- 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xe3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x01, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
- 0xff}
- },
+ {0x68, 0x067b, 0x080b, 0x0b, 0x00, 0x29},
+ {0x69, 0x06fd, 0x080b, 0x0b, 0x00, 0x29},
+ {0x6b, 0x07ff, 0x080b, 0x0b, 0x00, 0x29},
+ {0x6c, 0x067b, 0x090c, 0x0c, 0x00, 0x2f},
+ {0x6d, 0x06fd, 0x090c, 0x0c, 0x00, 0x2f},
+ {0x6e, 0x07ff, 0x090c, 0x0c, 0x00, 0x2f},
+ {0x70, 0x2a1b, 0x0410, 0x10, 0x07, 0x34},
+ {0x71, 0x0a1b, 0x0511, 0x11, 0x00, 0x37},
+ {0x74, 0x0a1d, 0x0511, 0x11, 0x00, 0x37},
+ {0x75, 0x0a3d, 0x0612, 0x12, 0x00, 0x3a},
+ {0x76, 0x2a1f, 0x0410, 0x10, 0x07, 0x34},
+ {0x77, 0x0a1f, 0x0511, 0x11, 0x00, 0x37},
+ {0x78, 0x0a3f, 0x0612, 0x12, 0x00, 0x3a},
+ {0x79, 0x0a3b, 0x0612, 0x12, 0x00, 0x3a},
+ {0x7a, 0x2a1d, 0x0410, 0x10, 0x07, 0x34},
+ {0x7b, 0x0e3b, 0x060f, 0x0f, 0x00, 0x1d},
+ {0x7c, 0x0e7d, 0x060f, 0x0f, 0x00, 0x1d},
+ {0x7d, 0x0eff, 0x060f, 0x0f, 0x00, 0x1d},
+ {0x20, 0x0e3b, 0x0D16, 0x16, 0x00, 0x43},
+ {0x21, 0x0e7d, 0x0D16, 0x16, 0x00, 0x43},
+ {0x22, 0x0eff, 0x0D16, 0x16, 0x00, 0x43},
+ {0x23, 0x0e3b, 0x0614, 0x14, 0x00, 0x41},
+ {0x24, 0x0e7d, 0x0614, 0x14, 0x00, 0x41},
+ {0x25, 0x0eff, 0x0614, 0x14, 0x00, 0x41},
+ {0x26, 0x063b, 0x0c15, 0x15, 0x00, 0x42},
+ {0x27, 0x067d, 0x0c15, 0x15, 0x00, 0x42},
+ {0x28, 0x06ff, 0x0c15, 0x15, 0x00, 0x42},
+ {0xff, 0x0000, 0x0000, 0x00, 0x00, 0x00}
+};
+
+static struct SiS_StandTable_S XGI330_StandTable = {
/* ExtVGATable */
- {
- 0x00, 0x00, 0x00, 0x0000,
- {0x01, 0x0f, 0x00, 0x0e},
- 0x23,
- {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
- 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x01, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
- 0xff}
- },
-/* ROM_SAVEPTR */
- {
- 0x9f, 0x3b, 0x00, 0x00c0,
- {0x00, 0x00, 0x00, 0x00},
- 0x00,
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x3f,
- 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x1a, 0x00, 0xac, 0x3e, 0x00, 0xc0,
- 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00}
- },
-/* MD_F */
- {
- 0x50, 0x18, 0x0e, 0x8000,
- {0x01, 0x0f, 0x00, 0x06},
- 0xa2,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
- 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x82, 0x84, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3,
- 0xff},
- {0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
- 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
- 0x0b, 0x00, 0x05, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05,
- 0xff}
- },
-/* MD_10 */
- {
- 0x50, 0x18, 0x0e, 0x8000,
- {0x01, 0x0f, 0x00, 0x06},
- 0xa3,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
- 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x82, 0x84, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- 0x01, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
- 0xff}
- },
-/* MD_0_350 */
- {
- 0x28, 0x18, 0x0e, 0x0800,
- {0x09, 0x03, 0x00, 0x02},
- 0xa3,
- {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xb1, 0xbf, 0x1f,
- 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
- 0x83, 0x85, 0x5d, 0x14, 0x1f, 0x63, 0xba, 0xa3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- 0x08, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
- 0xff}
- },
-/* MD_1_350 */
- {
- 0x28, 0x18, 0x0e, 0x0800,
- {0x09, 0x03, 0x00, 0x02},
- 0xa3,
- {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
- 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
- 0x83, 0x85, 0x5d, 0x14, 0x1f, 0x63, 0xba, 0xa3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- 0x08, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
- 0xff}
- },
-/* MD_2_350 */
- {
- 0x50, 0x18, 0x0e, 0x1000,
- {0x01, 0x03, 0x00, 0x02},
- 0xa3,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
- 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
- 0x83, 0x85, 0x5d, 0x28, 0x1f, 0x63, 0xba, 0xa3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- 0x08, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
- 0xff}
- },
-/* MD_3_350 */
- {
- 0x50, 0x18, 0x0e, 0x1000,
- {0x01, 0x03, 0x00, 0x02},
- 0xa3,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
- 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
- 0x83, 0x85, 0x5d, 0x28, 0x1f, 0x63, 0xba, 0xa3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- 0x08, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
- 0xff}
- },
-/* MD_0_1_400 */
- {
- 0x28, 0x18, 0x10, 0x0800,
- {0x08, 0x03, 0x00, 0x02},
- 0x67,
- {0x2d, 0x27, 0x28, 0x90, 0x2b, 0xb1, 0xbf, 0x1f,
- 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
- 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- 0x0c, 0x00, 0x0f, 0x08},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
- 0xff}
- },
-/* MD_2_3_400 */
- {
- 0x50, 0x18, 0x10, 0x1000,
- {0x00, 0x03, 0x00, 0x02},
- 0x67,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
- 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
- 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- 0x0c, 0x00, 0x0f, 0x08},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
- 0xff}
- },
-/* MD_7_400 */
- {
- 0x50, 0x18, 0x10, 0x1000,
- {0x00, 0x03, 0x00, 0x02},
- 0x66,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
- 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
- 0x9c, 0x8e, 0x8f, 0x28, 0x0f, 0x96, 0xb9, 0xa3,
- 0xff},
- {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
- 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x0e, 0x00, 0x0f, 0x08},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x00,
- 0xff}
- },
-/* MD_11 */
- {
- 0x50, 0x1d, 0x10, 0xa000,
- {0x01, 0x0f, 0x00, 0x06},
- 0xe3,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e,
- 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xe9, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xc3,
- 0xff},
- {0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
- 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
- 0x01, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01,
- 0xff}
- },
-/* ExtEGATable */
- {
- 0x50, 0x1d, 0x10, 0xa000,
- {0x01, 0x0f, 0x00, 0x06},
- 0xe3,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e,
- 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xe9, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- 0x01, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
- 0xff}
- },
-/* MD_13 */
- {
- 0x28, 0x18, 0x08, 0x2000,
- {0x01, 0x0f, 0x00, 0x0e},
- 0x63,
- {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
- 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3,
- 0xff},
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x41, 0x00, 0x0f, 0x00},
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
- 0xff}
- }
+ 0x00, 0x00, 0x00, 0x0000,
+ {0x01, 0x0f, 0x00, 0x0e},
+ 0x23,
+ {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
+ 0xff},
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x01, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
+ 0xff}
};
static struct XGI_TimingHStruct XGI_TimingH[1];
@@ -1143,7 +626,7 @@ static struct XGI330_LCDDataStruct XGI_NoScalingDatax75[] = {
{1, 1, 1688, 806, 1688, 806} /* ; 0A (1280x768x75Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_ExtLCDDes1024x768Data[] = {
+static struct XGI_LCDDesStruct XGI_ExtLCDDes1024x768Data[] = {
{9, 1057, 0, 771}, /* ; 00 (320x200,320x400,640x200,640x400) */
{9, 1057, 0, 771}, /* ; 01 (320x350,640x350) */
{9, 1057, 0, 771}, /* ; 02 (360x400,720x400) */
@@ -1153,7 +636,7 @@ static struct XGI330_LCDDataDesStruct XGI_ExtLCDDes1024x768Data[] = {
{9, 1057, 805, 770} /* ; 06 (1024x768x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_StLCDDes1024x768Data[] = {
+static struct XGI_LCDDesStruct XGI_StLCDDes1024x768Data[] = {
{9, 1057, 737, 703}, /* ; 00 (320x200,320x400,640x200,640x400) */
{9, 1057, 686, 651}, /* ; 01 (320x350,640x350) */
{9, 1057, 737, 703}, /* ; 02 (360x400,720x400) */
@@ -1163,7 +646,7 @@ static struct XGI330_LCDDataDesStruct XGI_StLCDDes1024x768Data[] = {
{9, 1057, 805, 770} /* ; 06 (1024x768x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_CetLCDDes1024x768Data[] = {
+static struct XGI_LCDDesStruct XGI_CetLCDDes1024x768Data[] = {
{1152, 856, 622, 587}, /* ; 00 (320x200,320x400,640x200,640x400) */
{1152, 856, 597, 562}, /* ; 01 (320x350,640x350) */
{1152, 856, 622, 587}, /* ; 02 (360x400,720x400) */
@@ -1173,7 +656,7 @@ static struct XGI330_LCDDataDesStruct XGI_CetLCDDes1024x768Data[] = {
{0, 1048, 805, 770} /* ; 06 (1024x768x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1280x1024Data[] = {
+static struct XGI_LCDDesStruct XGI_ExtLCDDLDes1280x1024Data[] = {
{18, 1346, 981, 940}, /* 00 (320x200,320x400,640x200,640x400) */
{18, 1346, 926, 865}, /* 01 (320x350,640x350) */
{18, 1346, 981, 940}, /* 02 (360x400,720x400) */
@@ -1184,7 +667,7 @@ static struct XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1280x1024Data[] = {
{18, 1346, 1065, 1024} /* 07 (1280x1024x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_StLCDDLDes1280x1024Data[] = {
+static struct XGI_LCDDesStruct XGI_StLCDDLDes1280x1024Data[] = {
{18, 1346, 970, 907}, /* 00 (320x200,320x400,640x200,640x400) */
{18, 1346, 917, 854}, /* 01 (320x350,640x350) */
{18, 1346, 970, 907}, /* 02 (360x400,720x400) */
@@ -1195,7 +678,7 @@ static struct XGI330_LCDDataDesStruct XGI_StLCDDLDes1280x1024Data[] = {
{18, 1346, 1065, 1024} /* 07 (1280x1024x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_CetLCDDLDes1280x1024Data[] = {
+static struct XGI_LCDDesStruct XGI_CetLCDDLDes1280x1024Data[] = {
{1368, 1008, 752, 711}, /* 00 (320x200,320x400,640x200,640x400) */
{1368, 1008, 729, 688}, /* 01 (320x350,640x350) */
{1368, 1008, 752, 711}, /* 02 (360x400,720x400) */
@@ -1206,7 +689,7 @@ static struct XGI330_LCDDataDesStruct XGI_CetLCDDLDes1280x1024Data[] = {
{18, 1346, 1065, 1024} /* 07 (1280x1024x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_ExtLCDDes1280x1024Data[] = {
+static struct XGI_LCDDesStruct XGI_ExtLCDDes1280x1024Data[] = {
{9, 1337, 981, 940}, /* ; 00 (320x200,320x400,640x200,640x400) */
{9, 1337, 926, 884}, /* ; 01 (320x350,640x350) alan, 2003/09/30 */
{9, 1337, 981, 940}, /* ; 02 (360x400,720x400) */
@@ -1217,7 +700,7 @@ static struct XGI330_LCDDataDesStruct XGI_ExtLCDDes1280x1024Data[] = {
{9, 1337, 1065, 1024} /* ; 07 (1280x1024x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_StLCDDes1280x1024Data[] = {
+static struct XGI_LCDDesStruct XGI_StLCDDes1280x1024Data[] = {
{9, 1337, 970, 907}, /* ; 00 (320x200,320x400,640x200,640x400) */
{9, 1337, 917, 854}, /* ; 01 (320x350,640x350) */
{9, 1337, 970, 907}, /* ; 02 (360x400,720x400) */
@@ -1228,7 +711,7 @@ static struct XGI330_LCDDataDesStruct XGI_StLCDDes1280x1024Data[] = {
{9, 1337, 1065, 1024} /* ; 07 (1280x1024x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_CetLCDDes1280x1024Data[] = {
+static struct XGI_LCDDesStruct XGI_CetLCDDes1280x1024Data[] = {
{1368, 1008, 752, 711}, /* 00 (320x200,320x400,640x200,640x400) */
{1368, 1008, 729, 688}, /* 01 (320x350,640x350) */
{1368, 1008, 752, 711}, /* 02 (360x400,720x400) */
@@ -1239,7 +722,7 @@ static struct XGI330_LCDDataDesStruct XGI_CetLCDDes1280x1024Data[] = {
{9, 1337, 1065, 1024} /* 07 (1280x1024x60Hz) */
};
-static struct XGI330_LCDDataDesStruct xgifb_lcddldes_1400x1050[] = {
+static struct XGI_LCDDesStruct xgifb_lcddldes_1400x1050[] = {
{18, 1464, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */
{18, 1464, 0, 1051}, /* 01 (320x350,640x350) */
{18, 1464, 0, 1051}, /* 02 (360x400,720x400) */
@@ -1251,7 +734,7 @@ static struct XGI330_LCDDataDesStruct xgifb_lcddldes_1400x1050[] = {
{18, 1464, 0, 1051} /* 08 (1400x1050x60Hz) */
};
-static struct XGI330_LCDDataDesStruct xgifb_lcddes_1400x1050[] = {
+static struct XGI_LCDDesStruct xgifb_lcddes_1400x1050[] = {
{9, 1455, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */
{9, 1455, 0, 1051}, /* 01 (320x350,640x350) */
{9, 1455, 0, 1051}, /* 02 (360x400,720x400) */
@@ -1263,7 +746,7 @@ static struct XGI330_LCDDataDesStruct xgifb_lcddes_1400x1050[] = {
{9, 1455, 0, 1051} /* 08 (1400x1050x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_CetLCDDes1400x1050Data[] = {
+static struct XGI_LCDDesStruct XGI_CetLCDDes1400x1050Data[] = {
{1308, 1068, 781, 766}, /* 00 (320x200,320x400,640x200,640x400) */
{1308, 1068, 781, 766}, /* 01 (320x350,640x350) */
{1308, 1068, 781, 766}, /* 02 (360x400,720x400) */
@@ -1275,7 +758,7 @@ static struct XGI330_LCDDataDesStruct XGI_CetLCDDes1400x1050Data[] = {
{18, 1464, 0, 1051} /* 08 (1400x1050x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_CetLCDDes1400x1050Data2[] = {
+static struct XGI_LCDDesStruct XGI_CetLCDDes1400x1050Data2[] = {
{0, 1448, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */
{0, 1448, 0, 1051}, /* 01 (320x350,640x350) */
{0, 1448, 0, 1051}, /* 02 (360x400,720x400) */
@@ -1283,7 +766,7 @@ static struct XGI330_LCDDataDesStruct XGI_CetLCDDes1400x1050Data2[] = {
{0, 1448, 0, 1051} /* 04 (640x480x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1600x1200Data[] = {
+static struct XGI_LCDDesStruct XGI_ExtLCDDLDes1600x1200Data[] = {
{18, 1682, 0, 1201}, /* 00 (320x200,320x400,640x200,640x400) */
{18, 1682, 0, 1201}, /* 01 (320x350,640x350) */
{18, 1682, 0, 1201}, /* 02 (360x400,720x400) */
@@ -1296,7 +779,7 @@ static struct XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1600x1200Data[] = {
{18, 1682, 0, 1201} /* 09 (1600x1200x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_StLCDDLDes1600x1200Data[] = {
+static struct XGI_LCDDesStruct XGI_StLCDDLDes1600x1200Data[] = {
{18, 1682, 1150, 1101}, /* 00 (320x200,320x400,640x200,640x400) */
{18, 1682, 1083, 1034}, /* 01 (320x350,640x350) */
{18, 1682, 1150, 1101}, /* 02 (360x400,720x400) */
@@ -1309,7 +792,7 @@ static struct XGI330_LCDDataDesStruct XGI_StLCDDLDes1600x1200Data[] = {
{18, 1682, 0, 1201} /* 09 (1600x1200x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_ExtLCDDes1600x1200Data[] = {
+static struct XGI_LCDDesStruct XGI_ExtLCDDes1600x1200Data[] = {
{9, 1673, 0, 1201}, /* 00 (320x200,320x400,640x200,640x400) */
{9, 1673, 0, 1201}, /* 01 (320x350,640x350) */
{9, 1673, 0, 1201}, /* 02 (360x400,720x400) */
@@ -1322,7 +805,7 @@ static struct XGI330_LCDDataDesStruct XGI_ExtLCDDes1600x1200Data[] = {
{9, 1673, 0, 1201} /* 09 (1600x1200x60Hz) */
};
-static struct XGI330_LCDDataDesStruct XGI_StLCDDes1600x1200Data[] = {
+static struct XGI_LCDDesStruct XGI_StLCDDes1600x1200Data[] = {
{9, 1673, 1150, 1101}, /* 00 (320x200,320x400,640x200,640x400) */
{9, 1673, 1083, 1034}, /* 01 (320x350,640x350) */
{9, 1673, 1150, 1101}, /* 02 (360x400,720x400) */
@@ -1352,7 +835,7 @@ static struct XGI330_LCDDataDesStruct2 XGI_NoScalingDesData[] = {
};
/* ;;1024x768x75Hz */
-static struct XGI330_LCDDataDesStruct xgifb_lcddes_1024x768x75[] = {
+static struct XGI_LCDDesStruct xgifb_lcddes_1024x768x75[] = {
{9, 1049, 0, 769}, /* ; 00 (320x200,320x400,640x200,640x400) */
{9, 1049, 0, 769}, /* ; 01 (320x350,640x350) */
{9, 1049, 0, 769}, /* ; 02 (360x400,720x400) */
@@ -1363,7 +846,7 @@ static struct XGI330_LCDDataDesStruct xgifb_lcddes_1024x768x75[] = {
};
/* ;;1024x768x75Hz */
-static struct XGI330_LCDDataDesStruct XGI_CetLCDDes1024x768x75Data[] = {
+static struct XGI_LCDDesStruct XGI_CetLCDDes1024x768x75Data[] = {
{1152, 856, 622, 587}, /* ; 00 (320x200,320x400,640x200,640x400) */
{1152, 856, 597, 562}, /* ; 01 (320x350,640x350) */
{1192, 896, 622, 587}, /* ; 02 (360x400,720x400) */
@@ -1374,7 +857,7 @@ static struct XGI330_LCDDataDesStruct XGI_CetLCDDes1024x768x75Data[] = {
};
/* ;;1280x1024x75Hz */
-static struct XGI330_LCDDataDesStruct xgifb_lcddldes_1280x1024x75[] = {
+static struct XGI_LCDDesStruct xgifb_lcddldes_1280x1024x75[] = {
{18, 1314, 0, 1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
{18, 1314, 0, 1025}, /* ; 01 (320x350,640x350) */
{18, 1314, 0, 1025}, /* ; 02 (360x400,720x400) */
@@ -1386,7 +869,7 @@ static struct XGI330_LCDDataDesStruct xgifb_lcddldes_1280x1024x75[] = {
};
/* 1280x1024x75Hz */
-static struct XGI330_LCDDataDesStruct XGI_CetLCDDLDes1280x1024x75Data[] = {
+static struct XGI_LCDDesStruct XGI_CetLCDDLDes1280x1024x75Data[] = {
{1368, 1008, 752, 711}, /* ; 00 (320x200,320x400,640x200,640x400) */
{1368, 1008, 729, 688}, /* ; 01 (320x350,640x350) */
{1408, 1048, 752, 711}, /* ; 02 (360x400,720x400) */
@@ -1398,7 +881,7 @@ static struct XGI330_LCDDataDesStruct XGI_CetLCDDLDes1280x1024x75Data[] = {
};
/* ;;1280x1024x75Hz */
-static struct XGI330_LCDDataDesStruct xgifb_lcddes_1280x1024x75[] = {
+static struct XGI_LCDDesStruct xgifb_lcddes_1280x1024x75[] = {
{9, 1305, 0, 1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
{9, 1305, 0, 1025}, /* ; 01 (320x350,640x350) */
{9, 1305, 0, 1025}, /* ; 02 (360x400,720x400) */
@@ -1410,7 +893,7 @@ static struct XGI330_LCDDataDesStruct xgifb_lcddes_1280x1024x75[] = {
};
/* 1280x1024x75Hz */
-static struct XGI330_LCDDataDesStruct XGI_CetLCDDes1280x1024x75Data[] = {
+static struct XGI_LCDDesStruct XGI_CetLCDDes1280x1024x75Data[] = {
{1368, 1008, 752, 711}, /* ; 00 (320x200,320x400,640x200,640x400) */
{1368, 1008, 729, 688}, /* ; 01 (320x350,640x350) */
{1408, 1048, 752, 711}, /* ; 02 (360x400,720x400) */
diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
index a7208e315815..30cdd1af81f1 100644
--- a/drivers/staging/xgifb/vgatypes.h
+++ b/drivers/staging/xgifb/vgatypes.h
@@ -66,8 +66,6 @@ struct xgi_hw_device_info {
unsigned long ulVideoMemorySize; /* size, in bytes, of the
memory on the board */
- unsigned char *pjIOAddress; /* base I/O address of VGA ports (0x3B0) */
-
unsigned char jChipType; /* Used to Identify Graphics Chip */
/* defined in the data structure type */
/* "XGI_CHIP_TYPE" */
diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c
index 917461c66014..449673773286 100644
--- a/drivers/staging/zsmalloc/zsmalloc-main.c
+++ b/drivers/staging/zsmalloc/zsmalloc-main.c
@@ -45,12 +45,12 @@ static DEFINE_PER_CPU(struct mapping_area, zs_map_area);
static int is_first_page(struct page *page)
{
- return test_bit(PG_private, &page->flags);
+ return PagePrivate(page);
}
static int is_last_page(struct page *page)
{
- return test_bit(PG_private_2, &page->flags);
+ return PagePrivate2(page);
}
static void get_zspage_mapping(struct page *page, unsigned int *class_idx,
@@ -180,7 +180,7 @@ out:
* link together 3 PAGE_SIZE sized pages to form a zspage
* since then we can perfectly fit in 8 such objects.
*/
-static int get_zspage_order(int class_size)
+static int get_pages_per_zspage(int class_size)
{
int i, max_usedpc = 0;
/* zspage order which gives maximum used size per KB */
@@ -368,7 +368,7 @@ static struct page *alloc_zspage(struct size_class *class, gfp_t flags)
* identify the last page.
*/
error = -ENOMEM;
- for (i = 0; i < class->zspage_order; i++) {
+ for (i = 0; i < class->pages_per_zspage; i++) {
struct page *page, *prev_page;
page = alloc_page(flags);
@@ -377,7 +377,7 @@ static struct page *alloc_zspage(struct size_class *class, gfp_t flags)
INIT_LIST_HEAD(&page->lru);
if (i == 0) { /* first page */
- set_bit(PG_private, &page->flags);
+ SetPagePrivate(page);
set_page_private(page, 0);
first_page = page;
first_page->inuse = 0;
@@ -388,9 +388,8 @@ static struct page *alloc_zspage(struct size_class *class, gfp_t flags)
page->first_page = first_page;
if (i >= 2)
list_add(&page->lru, &prev_page->lru);
- if (i == class->zspage_order - 1) /* last page */
- set_bit(PG_private_2, &page->flags);
-
+ if (i == class->pages_per_zspage - 1) /* last page */
+ SetPagePrivate2(page);
prev_page = page;
}
@@ -398,7 +397,7 @@ static struct page *alloc_zspage(struct size_class *class, gfp_t flags)
first_page->freelist = obj_location_to_handle(first_page, 0);
/* Maximum number of objects we can store in this zspage */
- first_page->objects = class->zspage_order * PAGE_SIZE / class->size;
+ first_page->objects = class->pages_per_zspage * PAGE_SIZE / class->size;
error = 0; /* Success */
@@ -513,7 +512,7 @@ struct zs_pool *zs_create_pool(const char *name, gfp_t flags)
class->size = size;
class->index = i;
spin_lock_init(&class->lock);
- class->zspage_order = get_zspage_order(size);
+ class->pages_per_zspage = get_pages_per_zspage(size);
}
@@ -567,13 +566,9 @@ EXPORT_SYMBOL_GPL(zs_destroy_pool);
* zs_malloc - Allocate block of given size from pool.
* @pool: pool to allocate from
* @size: size of block to allocate
- * @page: page no. that holds the object
- * @offset: location of object within page
- *
- * On success, <page, offset> identifies block allocated
- * and 0 is returned. On failure, <page, offset> is set to
- * 0 and -ENOMEM is returned.
*
+ * On success, handle to the allocated object is returned,
+ * otherwise NULL.
* Allocation requests with size > ZS_MAX_ALLOC_SIZE will fail.
*/
void *zs_malloc(struct zs_pool *pool, size_t size)
@@ -604,7 +599,7 @@ void *zs_malloc(struct zs_pool *pool, size_t size)
set_zspage_mapping(first_page, class->index, ZS_EMPTY);
spin_lock(&class->lock);
- class->pages_allocated += class->zspage_order;
+ class->pages_allocated += class->pages_per_zspage;
}
obj = first_page->freelist;
@@ -659,7 +654,7 @@ void zs_free(struct zs_pool *pool, void *obj)
fullness = fix_fullness_group(pool, first_page);
if (fullness == ZS_EMPTY)
- class->pages_allocated -= class->zspage_order;
+ class->pages_allocated -= class->pages_per_zspage;
spin_unlock(&class->lock);
@@ -668,6 +663,15 @@ void zs_free(struct zs_pool *pool, void *obj)
}
EXPORT_SYMBOL_GPL(zs_free);
+/**
+ * zs_map_object - get address of allocated object from handle.
+ * @pool: pool from which the object was allocated
+ * @handle: handle returned from zs_malloc
+ *
+ * Before using an object allocated from zs_malloc, it must be mapped using
+ * this function. When done with the object, it must be unmapped using
+ * zs_unmap_object
+*/
void *zs_map_object(struct zs_pool *pool, void *handle)
{
struct page *page;
diff --git a/drivers/staging/zsmalloc/zsmalloc_int.h b/drivers/staging/zsmalloc/zsmalloc_int.h
index 92eefc663afc..6fd32a9e0315 100644
--- a/drivers/staging/zsmalloc/zsmalloc_int.h
+++ b/drivers/staging/zsmalloc/zsmalloc_int.h
@@ -124,7 +124,7 @@ struct size_class {
unsigned int index;
/* Number of PAGE_SIZE sized pages to combine to form a 'zspage' */
- int zspage_order;
+ int pages_per_zspage;
spinlock_t lock;
diff --git a/drivers/target/Kconfig b/drivers/target/Kconfig
index b28794b72125..18303686eb58 100644
--- a/drivers/target/Kconfig
+++ b/drivers/target/Kconfig
@@ -32,5 +32,6 @@ config TCM_PSCSI
source "drivers/target/loopback/Kconfig"
source "drivers/target/tcm_fc/Kconfig"
source "drivers/target/iscsi/Kconfig"
+source "drivers/target/sbp/Kconfig"
endif
diff --git a/drivers/target/Makefile b/drivers/target/Makefile
index 62e54053bcd8..61648d84fbb6 100644
--- a/drivers/target/Makefile
+++ b/drivers/target/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_TCM_PSCSI) += target_core_pscsi.o
obj-$(CONFIG_LOOPBACK_TARGET) += loopback/
obj-$(CONFIG_TCM_FC) += tcm_fc/
obj-$(CONFIG_ISCSI_TARGET) += iscsi/
+obj-$(CONFIG_SBP_TARGET) += sbp/
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 8b1d5e62ed40..d57d10cb2e47 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -27,8 +27,10 @@
#include <asm/unaligned.h>
#include <scsi/scsi_device.h>
#include <scsi/iscsi_proto.h>
+#include <scsi/scsi_tcq.h>
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
+#include <target/target_core_configfs.h>
#include "iscsi_target_core.h"
#include "iscsi_target_parameters.h"
@@ -593,7 +595,7 @@ static void __exit iscsi_target_cleanup_module(void)
kfree(iscsit_global);
}
-int iscsit_add_reject(
+static int iscsit_add_reject(
u8 reason,
int fail_conn,
unsigned char *buf,
@@ -622,7 +624,7 @@ int iscsit_add_reject(
}
spin_lock_bh(&conn->cmd_lock);
- list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+ list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock);
cmd->i_state = ISTATE_SEND_REJECT;
@@ -669,7 +671,7 @@ int iscsit_add_reject_from_cmd(
if (add_to_conn) {
spin_lock_bh(&conn->cmd_lock);
- list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+ list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock);
}
@@ -685,9 +687,7 @@ int iscsit_add_reject_from_cmd(
/*
* Map some portion of the allocated scatterlist to an iovec, suitable for
- * kernel sockets to copy data in/out. This handles both pages and slab-allocated
- * buffers, since we have been tricky and mapped t_mem_sg to the buffer in
- * either case (see iscsit_alloc_buffs)
+ * kernel sockets to copy data in/out.
*/
static int iscsit_map_iovec(
struct iscsi_cmd *cmd,
@@ -700,10 +700,9 @@ static int iscsit_map_iovec(
unsigned int page_off;
/*
- * We have a private mapping of the allocated pages in t_mem_sg.
- * At this point, we also know each contains a page.
+ * We know each entry in t_data_sg contains a page.
*/
- sg = &cmd->t_mem_sg[data_offset / PAGE_SIZE];
+ sg = &cmd->se_cmd.t_data_sg[data_offset / PAGE_SIZE];
page_off = (data_offset % PAGE_SIZE);
cmd->first_data_sg = sg;
@@ -744,7 +743,7 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
conn->exp_statsn = exp_statsn;
spin_lock_bh(&conn->cmd_lock);
- list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
+ list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
spin_lock(&cmd->istate_lock);
if ((cmd->i_state == ISTATE_SENT_STATUS) &&
(cmd->stat_sn < exp_statsn)) {
@@ -761,8 +760,7 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
{
- u32 iov_count = (cmd->se_cmd.t_data_nents == 0) ? 1 :
- cmd->se_cmd.t_data_nents;
+ u32 iov_count = max(1UL, DIV_ROUND_UP(cmd->se_cmd.data_length, PAGE_SIZE));
iov_count += ISCSI_IOV_DATA_BUFFER;
@@ -776,64 +774,6 @@ static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
return 0;
}
-static int iscsit_alloc_buffs(struct iscsi_cmd *cmd)
-{
- struct scatterlist *sgl;
- u32 length = cmd->se_cmd.data_length;
- int nents = DIV_ROUND_UP(length, PAGE_SIZE);
- int i = 0, j = 0, ret;
- /*
- * If no SCSI payload is present, allocate the default iovecs used for
- * iSCSI PDU Header
- */
- if (!length)
- return iscsit_allocate_iovecs(cmd);
-
- sgl = kzalloc(sizeof(*sgl) * nents, GFP_KERNEL);
- if (!sgl)
- return -ENOMEM;
-
- sg_init_table(sgl, nents);
-
- while (length) {
- int buf_size = min_t(int, length, PAGE_SIZE);
- struct page *page;
-
- page = alloc_page(GFP_KERNEL | __GFP_ZERO);
- if (!page)
- goto page_alloc_failed;
-
- sg_set_page(&sgl[i], page, buf_size, 0);
-
- length -= buf_size;
- i++;
- }
-
- cmd->t_mem_sg = sgl;
- cmd->t_mem_sg_nents = nents;
-
- /* BIDI ops not supported */
-
- /* Tell the core about our preallocated memory */
- transport_generic_map_mem_to_cmd(&cmd->se_cmd, sgl, nents, NULL, 0);
- /*
- * Allocate iovecs for SCSI payload after transport_generic_map_mem_to_cmd
- * so that cmd->se_cmd.t_tasks_se_num has been set.
- */
- ret = iscsit_allocate_iovecs(cmd);
- if (ret < 0)
- return -ENOMEM;
-
- return 0;
-
-page_alloc_failed:
- while (j < i)
- __free_page(sg_page(&sgl[j++]));
-
- kfree(sgl);
- return -ENOMEM;
-}
-
static int iscsit_handle_scsi_cmd(
struct iscsi_conn *conn,
unsigned char *buf)
@@ -842,6 +782,8 @@ static int iscsit_handle_scsi_cmd(
int dump_immediate_data = 0, send_check_condition = 0, payload_length;
struct iscsi_cmd *cmd = NULL;
struct iscsi_scsi_req *hdr;
+ int iscsi_task_attr;
+ int sam_task_attr;
spin_lock_bh(&conn->sess->session_stats_lock);
conn->sess->cmd_pdus++;
@@ -958,15 +900,30 @@ done:
(hdr->flags & ISCSI_FLAG_CMD_READ) ? DMA_FROM_DEVICE :
DMA_NONE;
- cmd = iscsit_allocate_se_cmd(conn, hdr->data_length, data_direction,
- (hdr->flags & ISCSI_FLAG_CMD_ATTR_MASK));
+ cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
if (!cmd)
return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1,
- buf, conn);
+ buf, conn);
- pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x,"
- " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,
- hdr->cmdsn, hdr->data_length, payload_length, conn->cid);
+ cmd->data_direction = data_direction;
+ iscsi_task_attr = hdr->flags & ISCSI_FLAG_CMD_ATTR_MASK;
+ /*
+ * Figure out the SAM Task Attribute for the incoming SCSI CDB
+ */
+ if ((iscsi_task_attr == ISCSI_ATTR_UNTAGGED) ||
+ (iscsi_task_attr == ISCSI_ATTR_SIMPLE))
+ sam_task_attr = MSG_SIMPLE_TAG;
+ else if (iscsi_task_attr == ISCSI_ATTR_ORDERED)
+ sam_task_attr = MSG_ORDERED_TAG;
+ else if (iscsi_task_attr == ISCSI_ATTR_HEAD_OF_QUEUE)
+ sam_task_attr = MSG_HEAD_TAG;
+ else if (iscsi_task_attr == ISCSI_ATTR_ACA)
+ sam_task_attr = MSG_ACA_TAG;
+ else {
+ pr_debug("Unknown iSCSI Task Attribute: 0x%02x, using"
+ " MSG_SIMPLE_TAG\n", iscsi_task_attr);
+ sam_task_attr = MSG_SIMPLE_TAG;
+ }
cmd->iscsi_opcode = ISCSI_OP_SCSI_CMD;
cmd->i_state = ISTATE_NEW_CMD;
@@ -1003,6 +960,17 @@ done:
}
/*
+ * Initialize struct se_cmd descriptor from target_core_mod infrastructure
+ */
+ transport_init_se_cmd(&cmd->se_cmd, &lio_target_fabric_configfs->tf_ops,
+ conn->sess->se_sess, hdr->data_length, cmd->data_direction,
+ sam_task_attr, &cmd->sense_buffer[0]);
+
+ pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x,"
+ " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,
+ hdr->cmdsn, hdr->data_length, payload_length, conn->cid);
+
+ /*
* The CDB is going to an se_device_t.
*/
ret = transport_lookup_cmd_lun(&cmd->se_cmd,
@@ -1016,13 +984,8 @@ done:
send_check_condition = 1;
goto attach_cmd;
}
- /*
- * The Initiator Node has access to the LUN (the addressing method
- * is handled inside of iscsit_get_lun_for_cmd()). Now it's time to
- * allocate 1->N transport tasks (depending on sector count and
- * maximum request size the physical HBA(s) can handle.
- */
- transport_ret = transport_generic_allocate_tasks(&cmd->se_cmd, hdr->cdb);
+
+ transport_ret = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb);
if (transport_ret == -ENOMEM) {
return iscsit_add_reject_from_cmd(
ISCSI_REASON_BOOKMARK_NO_RESOURCES,
@@ -1035,9 +998,7 @@ done:
*/
send_check_condition = 1;
} else {
- cmd->data_length = cmd->se_cmd.data_length;
-
- if (iscsit_decide_list_to_build(cmd, payload_length) < 0)
+ if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0)
return iscsit_add_reject_from_cmd(
ISCSI_REASON_BOOKMARK_NO_RESOURCES,
1, 1, buf, cmd);
@@ -1045,18 +1006,15 @@ done:
attach_cmd:
spin_lock_bh(&conn->cmd_lock);
- list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+ list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock);
/*
* Check if we need to delay processing because of ALUA
* Active/NonOptimized primary access state..
*/
core_alua_check_nonop_delay(&cmd->se_cmd);
- /*
- * Allocate and setup SGL used with transport_generic_map_mem_to_cmd().
- * also call iscsit_allocate_iovecs()
- */
- ret = iscsit_alloc_buffs(cmd);
+
+ ret = iscsit_allocate_iovecs(cmd);
if (ret < 0)
return iscsit_add_reject_from_cmd(
ISCSI_REASON_BOOKMARK_NO_RESOURCES,
@@ -1303,10 +1261,10 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
se_cmd = &cmd->se_cmd;
iscsit_mod_dataout_timer(cmd);
- if ((hdr->offset + payload_length) > cmd->data_length) {
+ if ((hdr->offset + payload_length) > cmd->se_cmd.data_length) {
pr_err("DataOut Offset: %u, Length %u greater than"
" iSCSI Command EDTL %u, protocol error.\n",
- hdr->offset, payload_length, cmd->data_length);
+ hdr->offset, payload_length, cmd->se_cmd.data_length);
return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
1, 0, buf, cmd);
}
@@ -1442,7 +1400,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
return 0;
else if (ret == DATAOUT_SEND_R2T) {
iscsit_set_dataout_sequence_values(cmd);
- iscsit_build_r2ts_for_cmd(cmd, conn, 0);
+ iscsit_build_r2ts_for_cmd(cmd, conn, false);
} else if (ret == DATAOUT_SEND_TO_TRANSPORT) {
/*
* Handle extra special case for out of order
@@ -1617,7 +1575,7 @@ static int iscsit_handle_nop_out(
* Initiator is expecting a NopIN ping reply,
*/
spin_lock_bh(&conn->cmd_lock);
- list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+ list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock);
iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
@@ -1723,10 +1681,75 @@ static int iscsit_handle_task_mgt_cmd(
(hdr->refcmdsn != ISCSI_RESERVED_TAG))
hdr->refcmdsn = ISCSI_RESERVED_TAG;
- cmd = iscsit_allocate_se_cmd_for_tmr(conn, function);
+ cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
if (!cmd)
return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
- 1, buf, conn);
+ 1, buf, conn);
+
+ cmd->data_direction = DMA_NONE;
+
+ cmd->tmr_req = kzalloc(sizeof(struct iscsi_tmr_req), GFP_KERNEL);
+ if (!cmd->tmr_req) {
+ pr_err("Unable to allocate memory for"
+ " Task Management command!\n");
+ return iscsit_add_reject_from_cmd(
+ ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+ 1, 1, buf, cmd);
+ }
+
+ /*
+ * TASK_REASSIGN for ERL=2 / connection stays inside of
+ * LIO-Target $FABRIC_MOD
+ */
+ if (function != ISCSI_TM_FUNC_TASK_REASSIGN) {
+
+ u8 tcm_function;
+ int ret;
+
+ transport_init_se_cmd(&cmd->se_cmd,
+ &lio_target_fabric_configfs->tf_ops,
+ conn->sess->se_sess, 0, DMA_NONE,
+ MSG_SIMPLE_TAG, &cmd->sense_buffer[0]);
+
+ switch (function) {
+ case ISCSI_TM_FUNC_ABORT_TASK:
+ tcm_function = TMR_ABORT_TASK;
+ break;
+ case ISCSI_TM_FUNC_ABORT_TASK_SET:
+ tcm_function = TMR_ABORT_TASK_SET;
+ break;
+ case ISCSI_TM_FUNC_CLEAR_ACA:
+ tcm_function = TMR_CLEAR_ACA;
+ break;
+ case ISCSI_TM_FUNC_CLEAR_TASK_SET:
+ tcm_function = TMR_CLEAR_TASK_SET;
+ break;
+ case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
+ tcm_function = TMR_LUN_RESET;
+ break;
+ case ISCSI_TM_FUNC_TARGET_WARM_RESET:
+ tcm_function = TMR_TARGET_WARM_RESET;
+ break;
+ case ISCSI_TM_FUNC_TARGET_COLD_RESET:
+ tcm_function = TMR_TARGET_COLD_RESET;
+ break;
+ default:
+ pr_err("Unknown iSCSI TMR Function:"
+ " 0x%02x\n", function);
+ return iscsit_add_reject_from_cmd(
+ ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+ 1, 1, buf, cmd);
+ }
+
+ ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req,
+ tcm_function, GFP_KERNEL);
+ if (ret < 0)
+ return iscsit_add_reject_from_cmd(
+ ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+ 1, 1, buf, cmd);
+
+ cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req;
+ }
cmd->iscsi_opcode = ISCSI_OP_SCSI_TMFUNC;
cmd->i_state = ISTATE_SEND_TASKMGTRSP;
@@ -1804,7 +1827,7 @@ static int iscsit_handle_task_mgt_cmd(
se_tmr->call_transport = 1;
attach:
spin_lock_bh(&conn->cmd_lock);
- list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+ list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock);
if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
@@ -1980,7 +2003,7 @@ static int iscsit_handle_text_cmd(
cmd->data_direction = DMA_NONE;
spin_lock_bh(&conn->cmd_lock);
- list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+ list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock);
iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
@@ -2168,7 +2191,7 @@ static int iscsit_handle_logout_cmd(
logout_remove = 1;
spin_lock_bh(&conn->cmd_lock);
- list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+ list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock);
if (reason_code != ISCSI_LOGOUT_REASON_RECOVERY)
@@ -2178,7 +2201,7 @@ static int iscsit_handle_logout_cmd(
* Immediate commands are executed, well, immediately.
* Non-Immediate Logout Commands are executed in CmdSN order.
*/
- if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
+ if (cmd->immediate_cmd) {
int ret = iscsit_execute_cmd(cmd, 0);
if (ret < 0)
@@ -2336,7 +2359,7 @@ static int iscsit_handle_immediate_data(
cmd->write_data_done += length;
- if (cmd->write_data_done == cmd->data_length) {
+ if (cmd->write_data_done == cmd->se_cmd.data_length) {
spin_lock_bh(&cmd->istate_lock);
cmd->cmd_flags |= ICF_GOT_LAST_DATAOUT;
cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT;
@@ -2381,7 +2404,7 @@ static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn)
cmd->i_state = ISTATE_SEND_ASYNCMSG;
spin_lock_bh(&conn_p->cmd_lock);
- list_add_tail(&cmd->i_list, &conn_p->conn_cmd_list);
+ list_add_tail(&cmd->i_conn_node, &conn_p->conn_cmd_list);
spin_unlock_bh(&conn_p->cmd_lock);
iscsit_add_cmd_to_response_queue(cmd, conn_p, cmd->i_state);
@@ -2434,10 +2457,19 @@ static int iscsit_send_conn_drop_async_message(
return 0;
}
+static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *conn)
+{
+ if ((conn->sock->sk->sk_shutdown & SEND_SHUTDOWN) ||
+ (conn->sock->sk->sk_shutdown & RCV_SHUTDOWN)) {
+ wait_for_completion_interruptible_timeout(
+ &conn->tx_half_close_comp,
+ ISCSI_TX_THREAD_TCP_TIMEOUT * HZ);
+ }
+}
+
static int iscsit_send_data_in(
struct iscsi_cmd *cmd,
- struct iscsi_conn *conn,
- int *eodr)
+ struct iscsi_conn *conn)
{
int iov_ret = 0, set_statsn = 0;
u32 iov_count = 0, tx_size = 0;
@@ -2445,6 +2477,8 @@ static int iscsit_send_data_in(
struct iscsi_datain_req *dr;
struct iscsi_data_rsp *hdr;
struct kvec *iov;
+ int eodr = 0;
+ int ret;
memset(&datain, 0, sizeof(struct iscsi_datain));
dr = iscsit_get_datain_values(cmd, &datain);
@@ -2457,11 +2491,11 @@ static int iscsit_send_data_in(
/*
* Be paranoid and double check the logic for now.
*/
- if ((datain.offset + datain.length) > cmd->data_length) {
+ if ((datain.offset + datain.length) > cmd->se_cmd.data_length) {
pr_err("Command ITT: 0x%08x, datain.offset: %u and"
" datain.length: %u exceeds cmd->data_length: %u\n",
cmd->init_task_tag, datain.offset, datain.length,
- cmd->data_length);
+ cmd->se_cmd.data_length);
return -1;
}
@@ -2577,13 +2611,26 @@ static int iscsit_send_data_in(
cmd->init_task_tag, ntohl(hdr->statsn), ntohl(hdr->datasn),
ntohl(hdr->offset), datain.length, conn->cid);
+ /* sendpage is preferred but can't insert markers */
+ if (!conn->conn_ops->IFMarker)
+ ret = iscsit_fe_sendpage_sg(cmd, conn);
+ else
+ ret = iscsit_send_tx_data(cmd, conn, 0);
+
+ iscsit_unmap_iovec(cmd);
+
+ if (ret < 0) {
+ iscsit_tx_thread_wait_for_tcp(conn);
+ return ret;
+ }
+
if (dr->dr_complete) {
- *eodr = (cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ?
+ eodr = (cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ?
2 : 1;
iscsit_free_datain_req(cmd, dr);
}
- return 0;
+ return eodr;
}
static int iscsit_send_logout_response(
@@ -2715,6 +2762,7 @@ static int iscsit_send_unsolicited_nopin(
{
int tx_size = ISCSI_HDR_LEN;
struct iscsi_nopin *hdr;
+ int ret;
hdr = (struct iscsi_nopin *) cmd->pdu;
memset(hdr, 0, ISCSI_HDR_LEN);
@@ -2747,6 +2795,17 @@ static int iscsit_send_unsolicited_nopin(
pr_debug("Sending Unsolicited NOPIN TTT: 0x%08x StatSN:"
" 0x%08x CID: %hu\n", hdr->ttt, cmd->stat_sn, conn->cid);
+ ret = iscsit_send_tx_data(cmd, conn, 1);
+ if (ret < 0) {
+ iscsit_tx_thread_wait_for_tcp(conn);
+ return ret;
+ }
+
+ spin_lock_bh(&cmd->istate_lock);
+ cmd->i_state = want_response ?
+ ISTATE_SENT_NOPIN_WANT_RESPONSE : ISTATE_SENT_STATUS;
+ spin_unlock_bh(&cmd->istate_lock);
+
return 0;
}
@@ -2837,13 +2896,14 @@ static int iscsit_send_nopin_response(
return 0;
}
-int iscsit_send_r2t(
+static int iscsit_send_r2t(
struct iscsi_cmd *cmd,
struct iscsi_conn *conn)
{
int tx_size = 0;
struct iscsi_r2t *r2t;
struct iscsi_r2t_rsp *hdr;
+ int ret;
r2t = iscsit_get_r2t_from_list(cmd);
if (!r2t)
@@ -2899,19 +2959,27 @@ int iscsit_send_r2t(
r2t->sent_r2t = 1;
spin_unlock_bh(&cmd->r2t_lock);
+ ret = iscsit_send_tx_data(cmd, conn, 1);
+ if (ret < 0) {
+ iscsit_tx_thread_wait_for_tcp(conn);
+ return ret;
+ }
+
+ spin_lock_bh(&cmd->dataout_timeout_lock);
+ iscsit_start_dataout_timer(cmd, conn);
+ spin_unlock_bh(&cmd->dataout_timeout_lock);
+
return 0;
}
/*
- * type 0: Normal Operation.
- * type 1: Called from Storage Transport.
- * type 2: Called from iscsi_task_reassign_complete_write() for
- * connection recovery.
+ * @recovery: If called from iscsi_task_reassign_complete_write() for
+ * connection recovery.
*/
int iscsit_build_r2ts_for_cmd(
struct iscsi_cmd *cmd,
struct iscsi_conn *conn,
- int type)
+ bool recovery)
{
int first_r2t = 1;
u32 offset = 0, xfer_len = 0;
@@ -2922,32 +2990,37 @@ int iscsit_build_r2ts_for_cmd(
return 0;
}
- if (conn->sess->sess_ops->DataSequenceInOrder && (type != 2))
- if (cmd->r2t_offset < cmd->write_data_done)
- cmd->r2t_offset = cmd->write_data_done;
+ if (conn->sess->sess_ops->DataSequenceInOrder &&
+ !recovery)
+ cmd->r2t_offset = max(cmd->r2t_offset, cmd->write_data_done);
while (cmd->outstanding_r2ts < conn->sess->sess_ops->MaxOutstandingR2T) {
if (conn->sess->sess_ops->DataSequenceInOrder) {
offset = cmd->r2t_offset;
- if (first_r2t && (type == 2)) {
- xfer_len = ((offset +
- (conn->sess->sess_ops->MaxBurstLength -
- cmd->next_burst_len) >
- cmd->data_length) ?
- (cmd->data_length - offset) :
- (conn->sess->sess_ops->MaxBurstLength -
- cmd->next_burst_len));
+ if (first_r2t && recovery) {
+ int new_data_end = offset +
+ conn->sess->sess_ops->MaxBurstLength -
+ cmd->next_burst_len;
+
+ if (new_data_end > cmd->se_cmd.data_length)
+ xfer_len = cmd->se_cmd.data_length - offset;
+ else
+ xfer_len =
+ conn->sess->sess_ops->MaxBurstLength -
+ cmd->next_burst_len;
} else {
- xfer_len = ((offset +
- conn->sess->sess_ops->MaxBurstLength) >
- cmd->data_length) ?
- (cmd->data_length - offset) :
- conn->sess->sess_ops->MaxBurstLength;
+ int new_data_end = offset +
+ conn->sess->sess_ops->MaxBurstLength;
+
+ if (new_data_end > cmd->se_cmd.data_length)
+ xfer_len = cmd->se_cmd.data_length - offset;
+ else
+ xfer_len = conn->sess->sess_ops->MaxBurstLength;
}
cmd->r2t_offset += xfer_len;
- if (cmd->r2t_offset == cmd->data_length)
+ if (cmd->r2t_offset == cmd->se_cmd.data_length)
cmd->cmd_flags |= ICF_SENT_LAST_R2T;
} else {
struct iscsi_seq *seq;
@@ -3179,6 +3252,8 @@ static bool iscsit_check_inaddr_any(struct iscsi_np *np)
return ret;
}
+#define SENDTARGETS_BUF_LIMIT 32768U
+
static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
{
char *payload = NULL;
@@ -3187,12 +3262,10 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
struct iscsi_tiqn *tiqn;
struct iscsi_tpg_np *tpg_np;
int buffer_len, end_of_buf = 0, len = 0, payload_len = 0;
- unsigned char buf[256];
+ unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */
- buffer_len = (conn->conn_ops->MaxRecvDataSegmentLength > 32768) ?
- 32768 : conn->conn_ops->MaxRecvDataSegmentLength;
-
- memset(buf, 0, 256);
+ buffer_len = max(conn->conn_ops->MaxRecvDataSegmentLength,
+ SENDTARGETS_BUF_LIMIT);
payload = kzalloc(buffer_len, GFP_KERNEL);
if (!payload) {
@@ -3408,18 +3481,6 @@ static int iscsit_send_reject(
return 0;
}
-static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *conn)
-{
- if ((conn->sock->sk->sk_shutdown & SEND_SHUTDOWN) ||
- (conn->sock->sk->sk_shutdown & RCV_SHUTDOWN)) {
- wait_for_completion_interruptible_timeout(
- &conn->tx_half_close_comp,
- ISCSI_TX_THREAD_TCP_TIMEOUT * HZ);
- }
-}
-
-#ifdef CONFIG_SMP
-
void iscsit_thread_get_cpumask(struct iscsi_conn *conn)
{
struct iscsi_thread_set *ts = conn->thread_set;
@@ -3433,10 +3494,6 @@ void iscsit_thread_get_cpumask(struct iscsi_conn *conn)
* execute upon.
*/
ord = ts->thread_id % cpumask_weight(cpu_online_mask);
-#if 0
- pr_debug(">>>>>>>>>>>>>>>>>>>> Generated ord: %d from"
- " thread_id: %d\n", ord, ts->thread_id);
-#endif
for_each_online_cpu(cpu) {
if (ord-- == 0) {
cpumask_set_cpu(cpu, conn->conn_cpumask);
@@ -3476,34 +3533,196 @@ static inline void iscsit_thread_check_cpumask(
*/
memset(buf, 0, 128);
cpumask_scnprintf(buf, 128, conn->conn_cpumask);
-#if 0
- pr_debug(">>>>>>>>>>>>>> Calling set_cpus_allowed_ptr():"
- " %s for %s\n", buf, p->comm);
-#endif
set_cpus_allowed_ptr(p, conn->conn_cpumask);
}
-#else
-
-void iscsit_thread_get_cpumask(struct iscsi_conn *conn)
+static int handle_immediate_queue(struct iscsi_conn *conn)
{
- return;
+ struct iscsi_queue_req *qr;
+ struct iscsi_cmd *cmd;
+ u8 state;
+ int ret;
+
+ while ((qr = iscsit_get_cmd_from_immediate_queue(conn))) {
+ atomic_set(&conn->check_immediate_queue, 0);
+ cmd = qr->cmd;
+ state = qr->state;
+ kmem_cache_free(lio_qr_cache, qr);
+
+ switch (state) {
+ case ISTATE_SEND_R2T:
+ ret = iscsit_send_r2t(cmd, conn);
+ if (ret < 0)
+ goto err;
+ break;
+ case ISTATE_REMOVE:
+ if (cmd->data_direction == DMA_TO_DEVICE)
+ iscsit_stop_dataout_timer(cmd);
+
+ spin_lock_bh(&conn->cmd_lock);
+ list_del(&cmd->i_conn_node);
+ spin_unlock_bh(&conn->cmd_lock);
+
+ iscsit_free_cmd(cmd);
+ continue;
+ case ISTATE_SEND_NOPIN_WANT_RESPONSE:
+ iscsit_mod_nopin_response_timer(conn);
+ ret = iscsit_send_unsolicited_nopin(cmd,
+ conn, 1);
+ if (ret < 0)
+ goto err;
+ break;
+ case ISTATE_SEND_NOPIN_NO_RESPONSE:
+ ret = iscsit_send_unsolicited_nopin(cmd,
+ conn, 0);
+ if (ret < 0)
+ goto err;
+ break;
+ default:
+ pr_err("Unknown Opcode: 0x%02x ITT:"
+ " 0x%08x, i_state: %d on CID: %hu\n",
+ cmd->iscsi_opcode, cmd->init_task_tag, state,
+ conn->cid);
+ goto err;
+ }
+ }
+
+ return 0;
+
+err:
+ return -1;
}
-#define iscsit_thread_check_cpumask(X, Y, Z) ({})
-#endif /* CONFIG_SMP */
+static int handle_response_queue(struct iscsi_conn *conn)
+{
+ struct iscsi_queue_req *qr;
+ struct iscsi_cmd *cmd;
+ u8 state;
+ int ret;
+
+ while ((qr = iscsit_get_cmd_from_response_queue(conn))) {
+ cmd = qr->cmd;
+ state = qr->state;
+ kmem_cache_free(lio_qr_cache, qr);
+
+check_rsp_state:
+ switch (state) {
+ case ISTATE_SEND_DATAIN:
+ ret = iscsit_send_data_in(cmd, conn);
+ if (ret < 0)
+ goto err;
+ else if (!ret)
+ /* more drs */
+ goto check_rsp_state;
+ else if (ret == 1) {
+ /* all done */
+ spin_lock_bh(&cmd->istate_lock);
+ cmd->i_state = ISTATE_SENT_STATUS;
+ spin_unlock_bh(&cmd->istate_lock);
+ continue;
+ } else if (ret == 2) {
+ /* Still must send status,
+ SCF_TRANSPORT_TASK_SENSE was set */
+ spin_lock_bh(&cmd->istate_lock);
+ cmd->i_state = ISTATE_SEND_STATUS;
+ spin_unlock_bh(&cmd->istate_lock);
+ state = ISTATE_SEND_STATUS;
+ goto check_rsp_state;
+ }
+
+ break;
+ case ISTATE_SEND_STATUS:
+ case ISTATE_SEND_STATUS_RECOVERY:
+ ret = iscsit_send_status(cmd, conn);
+ break;
+ case ISTATE_SEND_LOGOUTRSP:
+ ret = iscsit_send_logout_response(cmd, conn);
+ break;
+ case ISTATE_SEND_ASYNCMSG:
+ ret = iscsit_send_conn_drop_async_message(
+ cmd, conn);
+ break;
+ case ISTATE_SEND_NOPIN:
+ ret = iscsit_send_nopin_response(cmd, conn);
+ break;
+ case ISTATE_SEND_REJECT:
+ ret = iscsit_send_reject(cmd, conn);
+ break;
+ case ISTATE_SEND_TASKMGTRSP:
+ ret = iscsit_send_task_mgt_rsp(cmd, conn);
+ if (ret != 0)
+ break;
+ ret = iscsit_tmr_post_handler(cmd, conn);
+ if (ret != 0)
+ iscsit_fall_back_to_erl0(conn->sess);
+ break;
+ case ISTATE_SEND_TEXTRSP:
+ ret = iscsit_send_text_rsp(cmd, conn);
+ break;
+ default:
+ pr_err("Unknown Opcode: 0x%02x ITT:"
+ " 0x%08x, i_state: %d on CID: %hu\n",
+ cmd->iscsi_opcode, cmd->init_task_tag,
+ state, conn->cid);
+ goto err;
+ }
+ if (ret < 0)
+ goto err;
+
+ if (iscsit_send_tx_data(cmd, conn, 1) < 0) {
+ iscsit_tx_thread_wait_for_tcp(conn);
+ iscsit_unmap_iovec(cmd);
+ goto err;
+ }
+ iscsit_unmap_iovec(cmd);
+
+ switch (state) {
+ case ISTATE_SEND_LOGOUTRSP:
+ if (!iscsit_logout_post_handler(cmd, conn))
+ goto restart;
+ /* fall through */
+ case ISTATE_SEND_STATUS:
+ case ISTATE_SEND_ASYNCMSG:
+ case ISTATE_SEND_NOPIN:
+ case ISTATE_SEND_STATUS_RECOVERY:
+ case ISTATE_SEND_TEXTRSP:
+ case ISTATE_SEND_TASKMGTRSP:
+ spin_lock_bh(&cmd->istate_lock);
+ cmd->i_state = ISTATE_SENT_STATUS;
+ spin_unlock_bh(&cmd->istate_lock);
+ break;
+ case ISTATE_SEND_REJECT:
+ if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) {
+ cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN;
+ complete(&cmd->reject_comp);
+ goto err;
+ }
+ complete(&cmd->reject_comp);
+ break;
+ default:
+ pr_err("Unknown Opcode: 0x%02x ITT:"
+ " 0x%08x, i_state: %d on CID: %hu\n",
+ cmd->iscsi_opcode, cmd->init_task_tag,
+ cmd->i_state, conn->cid);
+ goto err;
+ }
+
+ if (atomic_read(&conn->check_immediate_queue))
+ break;
+ }
+
+ return 0;
+
+err:
+ return -1;
+restart:
+ return -EAGAIN;
+}
int iscsi_target_tx_thread(void *arg)
{
- u8 state;
- int eodr = 0;
int ret = 0;
- int sent_status = 0;
- int use_misc = 0;
- int map_sg = 0;
- struct iscsi_cmd *cmd = NULL;
struct iscsi_conn *conn;
- struct iscsi_queue_req *qr = NULL;
struct iscsi_thread_set *ts = arg;
/*
* Allow ourselves to be interrupted by SIGINT so that a
@@ -3516,7 +3735,7 @@ restart:
if (!conn)
goto out;
- eodr = map_sg = ret = sent_status = use_misc = 0;
+ ret = 0;
while (!kthread_should_stop()) {
/*
@@ -3531,251 +3750,15 @@ restart:
signal_pending(current))
goto transport_err;
-get_immediate:
- qr = iscsit_get_cmd_from_immediate_queue(conn);
- if (qr) {
- atomic_set(&conn->check_immediate_queue, 0);
- cmd = qr->cmd;
- state = qr->state;
- kmem_cache_free(lio_qr_cache, qr);
-
- spin_lock_bh(&cmd->istate_lock);
- switch (state) {
- case ISTATE_SEND_R2T:
- spin_unlock_bh(&cmd->istate_lock);
- ret = iscsit_send_r2t(cmd, conn);
- break;
- case ISTATE_REMOVE:
- spin_unlock_bh(&cmd->istate_lock);
-
- if (cmd->data_direction == DMA_TO_DEVICE)
- iscsit_stop_dataout_timer(cmd);
-
- spin_lock_bh(&conn->cmd_lock);
- list_del(&cmd->i_list);
- spin_unlock_bh(&conn->cmd_lock);
-
- iscsit_free_cmd(cmd);
- goto get_immediate;
- case ISTATE_SEND_NOPIN_WANT_RESPONSE:
- spin_unlock_bh(&cmd->istate_lock);
- iscsit_mod_nopin_response_timer(conn);
- ret = iscsit_send_unsolicited_nopin(cmd,
- conn, 1);
- break;
- case ISTATE_SEND_NOPIN_NO_RESPONSE:
- spin_unlock_bh(&cmd->istate_lock);
- ret = iscsit_send_unsolicited_nopin(cmd,
- conn, 0);
- break;
- default:
- pr_err("Unknown Opcode: 0x%02x ITT:"
- " 0x%08x, i_state: %d on CID: %hu\n",
- cmd->iscsi_opcode, cmd->init_task_tag, state,
- conn->cid);
- spin_unlock_bh(&cmd->istate_lock);
- goto transport_err;
- }
- if (ret < 0) {
- conn->tx_immediate_queue = 0;
- goto transport_err;
- }
-
- if (iscsit_send_tx_data(cmd, conn, 1) < 0) {
- conn->tx_immediate_queue = 0;
- iscsit_tx_thread_wait_for_tcp(conn);
- goto transport_err;
- }
-
- spin_lock_bh(&cmd->istate_lock);
- switch (state) {
- case ISTATE_SEND_R2T:
- spin_unlock_bh(&cmd->istate_lock);
- spin_lock_bh(&cmd->dataout_timeout_lock);
- iscsit_start_dataout_timer(cmd, conn);
- spin_unlock_bh(&cmd->dataout_timeout_lock);
- break;
- case ISTATE_SEND_NOPIN_WANT_RESPONSE:
- cmd->i_state = ISTATE_SENT_NOPIN_WANT_RESPONSE;
- spin_unlock_bh(&cmd->istate_lock);
- break;
- case ISTATE_SEND_NOPIN_NO_RESPONSE:
- cmd->i_state = ISTATE_SENT_STATUS;
- spin_unlock_bh(&cmd->istate_lock);
- break;
- default:
- pr_err("Unknown Opcode: 0x%02x ITT:"
- " 0x%08x, i_state: %d on CID: %hu\n",
- cmd->iscsi_opcode, cmd->init_task_tag,
- state, conn->cid);
- spin_unlock_bh(&cmd->istate_lock);
- goto transport_err;
- }
- goto get_immediate;
- } else
- conn->tx_immediate_queue = 0;
-
-get_response:
- qr = iscsit_get_cmd_from_response_queue(conn);
- if (qr) {
- cmd = qr->cmd;
- state = qr->state;
- kmem_cache_free(lio_qr_cache, qr);
-
- spin_lock_bh(&cmd->istate_lock);
-check_rsp_state:
- switch (state) {
- case ISTATE_SEND_DATAIN:
- spin_unlock_bh(&cmd->istate_lock);
- ret = iscsit_send_data_in(cmd, conn,
- &eodr);
- map_sg = 1;
- break;
- case ISTATE_SEND_STATUS:
- case ISTATE_SEND_STATUS_RECOVERY:
- spin_unlock_bh(&cmd->istate_lock);
- use_misc = 1;
- ret = iscsit_send_status(cmd, conn);
- break;
- case ISTATE_SEND_LOGOUTRSP:
- spin_unlock_bh(&cmd->istate_lock);
- use_misc = 1;
- ret = iscsit_send_logout_response(cmd, conn);
- break;
- case ISTATE_SEND_ASYNCMSG:
- spin_unlock_bh(&cmd->istate_lock);
- use_misc = 1;
- ret = iscsit_send_conn_drop_async_message(
- cmd, conn);
- break;
- case ISTATE_SEND_NOPIN:
- spin_unlock_bh(&cmd->istate_lock);
- use_misc = 1;
- ret = iscsit_send_nopin_response(cmd, conn);
- break;
- case ISTATE_SEND_REJECT:
- spin_unlock_bh(&cmd->istate_lock);
- use_misc = 1;
- ret = iscsit_send_reject(cmd, conn);
- break;
- case ISTATE_SEND_TASKMGTRSP:
- spin_unlock_bh(&cmd->istate_lock);
- use_misc = 1;
- ret = iscsit_send_task_mgt_rsp(cmd, conn);
- if (ret != 0)
- break;
- ret = iscsit_tmr_post_handler(cmd, conn);
- if (ret != 0)
- iscsit_fall_back_to_erl0(conn->sess);
- break;
- case ISTATE_SEND_TEXTRSP:
- spin_unlock_bh(&cmd->istate_lock);
- use_misc = 1;
- ret = iscsit_send_text_rsp(cmd, conn);
- break;
- default:
- pr_err("Unknown Opcode: 0x%02x ITT:"
- " 0x%08x, i_state: %d on CID: %hu\n",
- cmd->iscsi_opcode, cmd->init_task_tag,
- state, conn->cid);
- spin_unlock_bh(&cmd->istate_lock);
- goto transport_err;
- }
- if (ret < 0) {
- conn->tx_response_queue = 0;
- goto transport_err;
- }
-
- if (map_sg && !conn->conn_ops->IFMarker) {
- if (iscsit_fe_sendpage_sg(cmd, conn) < 0) {
- conn->tx_response_queue = 0;
- iscsit_tx_thread_wait_for_tcp(conn);
- iscsit_unmap_iovec(cmd);
- goto transport_err;
- }
- } else {
- if (iscsit_send_tx_data(cmd, conn, use_misc) < 0) {
- conn->tx_response_queue = 0;
- iscsit_tx_thread_wait_for_tcp(conn);
- iscsit_unmap_iovec(cmd);
- goto transport_err;
- }
- }
- map_sg = 0;
- iscsit_unmap_iovec(cmd);
-
- spin_lock_bh(&cmd->istate_lock);
- switch (state) {
- case ISTATE_SEND_DATAIN:
- if (!eodr)
- goto check_rsp_state;
-
- if (eodr == 1) {
- cmd->i_state = ISTATE_SENT_LAST_DATAIN;
- sent_status = 1;
- eodr = use_misc = 0;
- } else if (eodr == 2) {
- cmd->i_state = state =
- ISTATE_SEND_STATUS;
- sent_status = 0;
- eodr = use_misc = 0;
- goto check_rsp_state;
- }
- break;
- case ISTATE_SEND_STATUS:
- use_misc = 0;
- sent_status = 1;
- break;
- case ISTATE_SEND_ASYNCMSG:
- case ISTATE_SEND_NOPIN:
- case ISTATE_SEND_STATUS_RECOVERY:
- case ISTATE_SEND_TEXTRSP:
- use_misc = 0;
- sent_status = 1;
- break;
- case ISTATE_SEND_REJECT:
- use_misc = 0;
- if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) {
- cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN;
- spin_unlock_bh(&cmd->istate_lock);
- complete(&cmd->reject_comp);
- goto transport_err;
- }
- complete(&cmd->reject_comp);
- break;
- case ISTATE_SEND_TASKMGTRSP:
- use_misc = 0;
- sent_status = 1;
- break;
- case ISTATE_SEND_LOGOUTRSP:
- spin_unlock_bh(&cmd->istate_lock);
- if (!iscsit_logout_post_handler(cmd, conn))
- goto restart;
- spin_lock_bh(&cmd->istate_lock);
- use_misc = 0;
- sent_status = 1;
- break;
- default:
- pr_err("Unknown Opcode: 0x%02x ITT:"
- " 0x%08x, i_state: %d on CID: %hu\n",
- cmd->iscsi_opcode, cmd->init_task_tag,
- cmd->i_state, conn->cid);
- spin_unlock_bh(&cmd->istate_lock);
- goto transport_err;
- }
-
- if (sent_status) {
- cmd->i_state = ISTATE_SENT_STATUS;
- sent_status = 0;
- }
- spin_unlock_bh(&cmd->istate_lock);
-
- if (atomic_read(&conn->check_immediate_queue))
- goto get_immediate;
+ ret = handle_immediate_queue(conn);
+ if (ret < 0)
+ goto transport_err;
- goto get_response;
- } else
- conn->tx_response_queue = 0;
+ ret = handle_response_queue(conn);
+ if (ret == -EAGAIN)
+ goto restart;
+ else if (ret < 0)
+ goto transport_err;
}
transport_err:
@@ -3952,9 +3935,9 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
* has been reset -> returned sleeping pre-handler state.
*/
spin_lock_bh(&conn->cmd_lock);
- list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_list) {
+ list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) {
- list_del(&cmd->i_list);
+ list_del(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);
iscsit_increment_maxcmdsn(cmd, sess);
@@ -3972,7 +3955,7 @@ static void iscsit_stop_timers_for_cmds(
struct iscsi_cmd *cmd;
spin_lock_bh(&conn->cmd_lock);
- list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
+ list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
if (cmd->data_direction == DMA_TO_DEVICE)
iscsit_stop_dataout_timer(cmd);
}
diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h
index 5db2ddeed5eb..12abb4c9e34e 100644
--- a/drivers/target/iscsi/iscsi_target.h
+++ b/drivers/target/iscsi/iscsi_target.h
@@ -18,8 +18,7 @@ extern int iscsit_logout_closesession(struct iscsi_cmd *, struct iscsi_conn *);
extern int iscsit_logout_closeconnection(struct iscsi_cmd *, struct iscsi_conn *);
extern int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *, struct iscsi_conn *);
extern int iscsit_send_async_msg(struct iscsi_conn *, u16, u8, u8);
-extern int iscsit_send_r2t(struct iscsi_cmd *, struct iscsi_conn *);
-extern int iscsit_build_r2ts_for_cmd(struct iscsi_cmd *, struct iscsi_conn *, int);
+extern int iscsit_build_r2ts_for_cmd(struct iscsi_cmd *, struct iscsi_conn *, bool recovery);
extern void iscsit_thread_get_cpumask(struct iscsi_conn *);
extern int iscsi_target_tx_thread(void *);
extern int iscsi_target_rx_thread(void *);
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index 00c58cc82c85..69dc8e35c03a 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -1538,7 +1538,7 @@ static int lio_write_pending(struct se_cmd *se_cmd)
struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
if (!cmd->immediate_data && !cmd->unsolicited_data)
- return iscsit_build_r2ts_for_cmd(cmd, cmd->conn, 1);
+ return iscsit_build_r2ts_for_cmd(cmd, cmd->conn, false);
return 0;
}
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h
index 2aaee7efa683..1c70144cdaf1 100644
--- a/drivers/target/iscsi/iscsi_target_core.h
+++ b/drivers/target/iscsi/iscsi_target_core.h
@@ -296,12 +296,11 @@ struct iscsi_datain_req {
u32 runlength;
u32 data_length;
u32 data_offset;
- u32 data_offset_end;
u32 data_sn;
u32 next_burst_len;
u32 read_data_done;
u32 seq_send_order;
- struct list_head dr_list;
+ struct list_head cmd_datain_node;
} ____cacheline_aligned;
struct iscsi_ooo_cmdsn {
@@ -381,8 +380,6 @@ struct iscsi_cmd {
u32 buf_ptr_size;
/* Used to store DataDigest */
u32 data_crc;
- /* Total size in bytes associated with command */
- u32 data_length;
/* Counter for MaxOutstandingR2T */
u32 outstanding_r2ts;
/* Next R2T Offset when DataSequenceInOrder=Yes */
@@ -464,16 +461,13 @@ struct iscsi_cmd {
/* Session the command is part of, used for connection recovery */
struct iscsi_session *sess;
/* list_head for connection list */
- struct list_head i_list;
+ struct list_head i_conn_node;
/* The TCM I/O descriptor that is accessed via container_of() */
struct se_cmd se_cmd;
/* Sense buffer that will be mapped into outgoing status */
#define ISCSI_SENSE_BUFFER_LEN (TRANSPORT_SENSE_BUFFER + 2)
unsigned char sense_buffer[ISCSI_SENSE_BUFFER_LEN];
- struct scatterlist *t_mem_sg;
- u32 t_mem_sg_nents;
-
u32 padding;
u8 pad_bytes[4];
@@ -500,8 +494,6 @@ struct iscsi_conn {
u8 network_transport;
enum iscsi_timer_flags_table nopin_timer_flags;
enum iscsi_timer_flags_table nopin_response_timer_flags;
- u8 tx_immediate_queue;
- u8 tx_response_queue;
/* Used to know what thread encountered a transport failure */
u8 which_thread;
/* connection id assigned by the Initiator */
diff --git a/drivers/target/iscsi/iscsi_target_datain_values.c b/drivers/target/iscsi/iscsi_target_datain_values.c
index 8c0495129513..848fee768948 100644
--- a/drivers/target/iscsi/iscsi_target_datain_values.c
+++ b/drivers/target/iscsi/iscsi_target_datain_values.c
@@ -37,7 +37,7 @@ struct iscsi_datain_req *iscsit_allocate_datain_req(void)
" struct iscsi_datain_req\n");
return NULL;
}
- INIT_LIST_HEAD(&dr->dr_list);
+ INIT_LIST_HEAD(&dr->cmd_datain_node);
return dr;
}
@@ -45,14 +45,14 @@ struct iscsi_datain_req *iscsit_allocate_datain_req(void)
void iscsit_attach_datain_req(struct iscsi_cmd *cmd, struct iscsi_datain_req *dr)
{
spin_lock(&cmd->datain_lock);
- list_add_tail(&dr->dr_list, &cmd->datain_list);
+ list_add_tail(&dr->cmd_datain_node, &cmd->datain_list);
spin_unlock(&cmd->datain_lock);
}
void iscsit_free_datain_req(struct iscsi_cmd *cmd, struct iscsi_datain_req *dr)
{
spin_lock(&cmd->datain_lock);
- list_del(&dr->dr_list);
+ list_del(&dr->cmd_datain_node);
spin_unlock(&cmd->datain_lock);
kmem_cache_free(lio_dr_cache, dr);
@@ -63,8 +63,8 @@ void iscsit_free_all_datain_reqs(struct iscsi_cmd *cmd)
struct iscsi_datain_req *dr, *dr_tmp;
spin_lock(&cmd->datain_lock);
- list_for_each_entry_safe(dr, dr_tmp, &cmd->datain_list, dr_list) {
- list_del(&dr->dr_list);
+ list_for_each_entry_safe(dr, dr_tmp, &cmd->datain_list, cmd_datain_node) {
+ list_del(&dr->cmd_datain_node);
kmem_cache_free(lio_dr_cache, dr);
}
spin_unlock(&cmd->datain_lock);
@@ -72,17 +72,14 @@ void iscsit_free_all_datain_reqs(struct iscsi_cmd *cmd)
struct iscsi_datain_req *iscsit_get_datain_req(struct iscsi_cmd *cmd)
{
- struct iscsi_datain_req *dr;
-
if (list_empty(&cmd->datain_list)) {
pr_err("cmd->datain_list is empty for ITT:"
" 0x%08x\n", cmd->init_task_tag);
return NULL;
}
- list_for_each_entry(dr, &cmd->datain_list, dr_list)
- break;
- return dr;
+ return list_first_entry(&cmd->datain_list, struct iscsi_datain_req,
+ cmd_datain_node);
}
/*
@@ -113,7 +110,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_yes(
read_data_done = (!dr->recovery) ?
cmd->read_data_done : dr->read_data_done;
- read_data_left = (cmd->data_length - read_data_done);
+ read_data_left = (cmd->se_cmd.data_length - read_data_done);
if (!read_data_left) {
pr_err("ITT: 0x%08x read_data_left is zero!\n",
cmd->init_task_tag);
@@ -212,7 +209,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_no_and_yes(
seq_send_order = (!dr->recovery) ?
cmd->seq_send_order : dr->seq_send_order;
- read_data_left = (cmd->data_length - read_data_done);
+ read_data_left = (cmd->se_cmd.data_length - read_data_done);
if (!read_data_left) {
pr_err("ITT: 0x%08x read_data_left is zero!\n",
cmd->init_task_tag);
@@ -231,8 +228,8 @@ static struct iscsi_datain_req *iscsit_set_datain_values_no_and_yes(
offset = (seq->offset + seq->next_burst_len);
if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
- cmd->data_length) {
- datain->length = (cmd->data_length - offset);
+ cmd->se_cmd.data_length) {
+ datain->length = (cmd->se_cmd.data_length - offset);
datain->offset = offset;
datain->flags |= ISCSI_FLAG_CMD_FINAL;
@@ -264,7 +261,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_no_and_yes(
}
}
- if ((read_data_done + datain->length) == cmd->data_length)
+ if ((read_data_done + datain->length) == cmd->se_cmd.data_length)
datain->flags |= ISCSI_FLAG_DATA_STATUS;
datain->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
@@ -333,7 +330,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_no(
read_data_done = (!dr->recovery) ?
cmd->read_data_done : dr->read_data_done;
- read_data_left = (cmd->data_length - read_data_done);
+ read_data_left = (cmd->se_cmd.data_length - read_data_done);
if (!read_data_left) {
pr_err("ITT: 0x%08x read_data_left is zero!\n",
cmd->init_task_tag);
@@ -344,7 +341,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_no(
if (!pdu)
return dr;
- if ((read_data_done + pdu->length) == cmd->data_length) {
+ if ((read_data_done + pdu->length) == cmd->se_cmd.data_length) {
pdu->flags |= (ISCSI_FLAG_CMD_FINAL | ISCSI_FLAG_DATA_STATUS);
if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
pdu->flags |= ISCSI_FLAG_DATA_ACK;
@@ -433,7 +430,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_no_and_no(
seq_send_order = (!dr->recovery) ?
cmd->seq_send_order : dr->seq_send_order;
- read_data_left = (cmd->data_length - read_data_done);
+ read_data_left = (cmd->se_cmd.data_length - read_data_done);
if (!read_data_left) {
pr_err("ITT: 0x%08x read_data_left is zero!\n",
cmd->init_task_tag);
@@ -463,7 +460,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_no_and_no(
} else
seq->next_burst_len += pdu->length;
- if ((read_data_done + pdu->length) == cmd->data_length)
+ if ((read_data_done + pdu->length) == cmd->se_cmd.data_length)
pdu->flags |= ISCSI_FLAG_DATA_STATUS;
pdu->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c
index 1ab0560b0924..1a02016ecdab 100644
--- a/drivers/target/iscsi/iscsi_target_erl0.c
+++ b/drivers/target/iscsi/iscsi_target_erl0.c
@@ -48,9 +48,9 @@ void iscsit_set_dataout_sequence_values(
if (cmd->unsolicited_data) {
cmd->seq_start_offset = cmd->write_data_done;
cmd->seq_end_offset = (cmd->write_data_done +
- (cmd->data_length >
+ (cmd->se_cmd.data_length >
conn->sess->sess_ops->FirstBurstLength) ?
- conn->sess->sess_ops->FirstBurstLength : cmd->data_length);
+ conn->sess->sess_ops->FirstBurstLength : cmd->se_cmd.data_length);
return;
}
@@ -59,15 +59,15 @@ void iscsit_set_dataout_sequence_values(
if (!cmd->seq_start_offset && !cmd->seq_end_offset) {
cmd->seq_start_offset = cmd->write_data_done;
- cmd->seq_end_offset = (cmd->data_length >
+ cmd->seq_end_offset = (cmd->se_cmd.data_length >
conn->sess->sess_ops->MaxBurstLength) ?
(cmd->write_data_done +
- conn->sess->sess_ops->MaxBurstLength) : cmd->data_length;
+ conn->sess->sess_ops->MaxBurstLength) : cmd->se_cmd.data_length;
} else {
cmd->seq_start_offset = cmd->seq_end_offset;
cmd->seq_end_offset = ((cmd->seq_end_offset +
conn->sess->sess_ops->MaxBurstLength) >=
- cmd->data_length) ? cmd->data_length :
+ cmd->se_cmd.data_length) ? cmd->se_cmd.data_length :
(cmd->seq_end_offset +
conn->sess->sess_ops->MaxBurstLength);
}
@@ -182,13 +182,13 @@ static int iscsit_dataout_check_unsolicited_sequence(
if (!conn->sess->sess_ops->DataPDUInOrder)
goto out;
- if ((first_burst_len != cmd->data_length) &&
+ if ((first_burst_len != cmd->se_cmd.data_length) &&
(first_burst_len != conn->sess->sess_ops->FirstBurstLength)) {
pr_err("Unsolicited non-immediate data"
" received %u does not equal FirstBurstLength: %u, and"
" does not equal ExpXferLen %u.\n", first_burst_len,
conn->sess->sess_ops->FirstBurstLength,
- cmd->data_length);
+ cmd->se_cmd.data_length);
transport_send_check_condition_and_sense(&cmd->se_cmd,
TCM_INCORRECT_AMOUNT_OF_DATA, 0);
return DATAOUT_CANNOT_RECOVER;
@@ -201,10 +201,10 @@ static int iscsit_dataout_check_unsolicited_sequence(
conn->sess->sess_ops->FirstBurstLength);
return DATAOUT_CANNOT_RECOVER;
}
- if (first_burst_len == cmd->data_length) {
+ if (first_burst_len == cmd->se_cmd.data_length) {
pr_err("Command ITT: 0x%08x reached"
" ExpXferLen: %u, but ISCSI_FLAG_CMD_FINAL is not set. protocol"
- " error.\n", cmd->init_task_tag, cmd->data_length);
+ " error.\n", cmd->init_task_tag, cmd->se_cmd.data_length);
return DATAOUT_CANNOT_RECOVER;
}
}
@@ -294,7 +294,7 @@ static int iscsit_dataout_check_sequence(
if ((next_burst_len <
conn->sess->sess_ops->MaxBurstLength) &&
((cmd->write_data_done + payload_length) <
- cmd->data_length)) {
+ cmd->se_cmd.data_length)) {
pr_err("Command ITT: 0x%08x set ISCSI_FLAG_CMD_FINAL"
" before end of DataOUT sequence, protocol"
" error.\n", cmd->init_task_tag);
@@ -319,7 +319,7 @@ static int iscsit_dataout_check_sequence(
return DATAOUT_CANNOT_RECOVER;
}
if ((cmd->write_data_done + payload_length) ==
- cmd->data_length) {
+ cmd->se_cmd.data_length) {
pr_err("Command ITT: 0x%08x reached"
" last DataOUT PDU in sequence but ISCSI_FLAG_"
"CMD_FINAL is not set, protocol error.\n",
@@ -640,9 +640,12 @@ static int iscsit_dataout_post_crc_passed(
cmd->write_data_done += payload_length;
- return (cmd->write_data_done == cmd->data_length) ?
- DATAOUT_SEND_TO_TRANSPORT : (send_r2t) ?
- DATAOUT_SEND_R2T : DATAOUT_NORMAL;
+ if (cmd->write_data_done == cmd->se_cmd.data_length)
+ return DATAOUT_SEND_TO_TRANSPORT;
+ else if (send_r2t)
+ return DATAOUT_SEND_R2T;
+ else
+ return DATAOUT_NORMAL;
}
static int iscsit_dataout_post_crc_failed(
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c
index 006f605edb08..ecdd46deedda 100644
--- a/drivers/target/iscsi/iscsi_target_erl1.c
+++ b/drivers/target/iscsi/iscsi_target_erl1.c
@@ -279,11 +279,9 @@ int iscsit_create_recovery_datain_values_datasequenceinorder_no(
* seq->first_datasn and seq->last_datasn have not been set.
*/
if (!seq->sent) {
-#if 0
pr_err("Ignoring non-sent sequence 0x%08x ->"
" 0x%08x\n\n", seq->first_datasn,
seq->last_datasn);
-#endif
continue;
}
@@ -294,11 +292,10 @@ int iscsit_create_recovery_datain_values_datasequenceinorder_no(
*/
if ((seq->first_datasn < begrun) &&
(seq->last_datasn < begrun)) {
-#if 0
pr_err("Pre BegRun sequence 0x%08x ->"
" 0x%08x\n", seq->first_datasn,
seq->last_datasn);
-#endif
+
read_data_done += cmd->seq_list[i].xfer_len;
seq->next_burst_len = seq->pdu_send_order = 0;
continue;
@@ -309,11 +306,10 @@ int iscsit_create_recovery_datain_values_datasequenceinorder_no(
*/
if ((seq->first_datasn <= begrun) &&
(seq->last_datasn >= begrun)) {
-#if 0
pr_err("Found sequence begrun: 0x%08x in"
" 0x%08x -> 0x%08x\n", begrun,
seq->first_datasn, seq->last_datasn);
-#endif
+
seq_send_order = seq->seq_send_order;
data_sn = seq->first_datasn;
seq->next_burst_len = seq->pdu_send_order = 0;
@@ -369,10 +365,9 @@ int iscsit_create_recovery_datain_values_datasequenceinorder_no(
*/
if ((seq->first_datasn > begrun) ||
(seq->last_datasn > begrun)) {
-#if 0
pr_err("Post BegRun sequence 0x%08x -> 0x%08x\n",
seq->first_datasn, seq->last_datasn);
-#endif
+
seq->next_burst_len = seq->pdu_send_order = 0;
continue;
}
@@ -526,7 +521,7 @@ int iscsit_handle_status_snack(
found_cmd = 0;
spin_lock_bh(&conn->cmd_lock);
- list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
+ list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
if (cmd->stat_sn == begrun) {
found_cmd = 1;
break;
@@ -987,7 +982,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
return 0;
iscsit_set_dataout_sequence_values(cmd);
- iscsit_build_r2ts_for_cmd(cmd, cmd->conn, 0);
+ iscsit_build_r2ts_for_cmd(cmd, cmd->conn, false);
}
return 0;
}
@@ -1121,8 +1116,8 @@ static int iscsit_set_dataout_timeout_values(
if (cmd->unsolicited_data) {
*offset = 0;
*length = (conn->sess->sess_ops->FirstBurstLength >
- cmd->data_length) ?
- cmd->data_length :
+ cmd->se_cmd.data_length) ?
+ cmd->se_cmd.data_length :
conn->sess->sess_ops->FirstBurstLength;
return 0;
}
@@ -1193,8 +1188,8 @@ static void iscsit_handle_dataout_timeout(unsigned long data)
if (conn->sess->sess_ops->DataPDUInOrder) {
pdu_offset = cmd->write_data_done;
if ((pdu_offset + (conn->sess->sess_ops->MaxBurstLength -
- cmd->next_burst_len)) > cmd->data_length)
- pdu_length = (cmd->data_length -
+ cmd->next_burst_len)) > cmd->se_cmd.data_length)
+ pdu_length = (cmd->se_cmd.data_length -
cmd->write_data_done);
else
pdu_length = (conn->sess->sess_ops->MaxBurstLength -
diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c
index 1af1f21af21f..65aac14fd831 100644
--- a/drivers/target/iscsi/iscsi_target_erl2.c
+++ b/drivers/target/iscsi/iscsi_target_erl2.c
@@ -138,9 +138,9 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
spin_lock(&cr->conn_recovery_cmd_lock);
list_for_each_entry_safe(cmd, cmd_tmp,
- &cr->conn_recovery_cmd_list, i_list) {
+ &cr->conn_recovery_cmd_list, i_conn_node) {
- list_del(&cmd->i_list);
+ list_del(&cmd->i_conn_node);
cmd->conn = NULL;
spin_unlock(&cr->conn_recovery_cmd_lock);
iscsit_free_cmd(cmd);
@@ -160,9 +160,9 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
spin_lock(&cr->conn_recovery_cmd_lock);
list_for_each_entry_safe(cmd, cmd_tmp,
- &cr->conn_recovery_cmd_list, i_list) {
+ &cr->conn_recovery_cmd_list, i_conn_node) {
- list_del(&cmd->i_list);
+ list_del(&cmd->i_conn_node);
cmd->conn = NULL;
spin_unlock(&cr->conn_recovery_cmd_lock);
iscsit_free_cmd(cmd);
@@ -220,7 +220,7 @@ int iscsit_remove_cmd_from_connection_recovery(
}
cr = cmd->cr;
- list_del(&cmd->i_list);
+ list_del(&cmd->i_conn_node);
return --cr->cmd_count;
}
@@ -234,7 +234,7 @@ void iscsit_discard_cr_cmds_by_expstatsn(
spin_lock(&cr->conn_recovery_cmd_lock);
list_for_each_entry_safe(cmd, cmd_tmp,
- &cr->conn_recovery_cmd_list, i_list) {
+ &cr->conn_recovery_cmd_list, i_conn_node) {
if (((cmd->deferred_i_state != ISTATE_SENT_STATUS) &&
(cmd->deferred_i_state != ISTATE_REMOVE)) ||
@@ -297,11 +297,11 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn)
mutex_unlock(&sess->cmdsn_mutex);
spin_lock_bh(&conn->cmd_lock);
- list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_list) {
+ list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) {
if (!(cmd->cmd_flags & ICF_OOO_CMDSN))
continue;
- list_del(&cmd->i_list);
+ list_del(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);
iscsit_free_cmd(cmd);
@@ -339,14 +339,14 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
/*
* Only perform connection recovery on ISCSI_OP_SCSI_CMD or
* ISCSI_OP_NOOP_OUT opcodes. For all other opcodes call
- * list_del(&cmd->i_list); to release the command to the
+ * list_del(&cmd->i_conn_node); to release the command to the
* session pool and remove it from the connection's list.
*
* Also stop the DataOUT timer, which will be restarted after
* sending the TMR response.
*/
spin_lock_bh(&conn->cmd_lock);
- list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_list) {
+ list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) {
if ((cmd->iscsi_opcode != ISCSI_OP_SCSI_CMD) &&
(cmd->iscsi_opcode != ISCSI_OP_NOOP_OUT)) {
@@ -355,7 +355,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
" CID: %hu\n", cmd->iscsi_opcode,
cmd->init_task_tag, cmd->cmd_sn, conn->cid);
- list_del(&cmd->i_list);
+ list_del(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);
iscsit_free_cmd(cmd);
spin_lock_bh(&conn->cmd_lock);
@@ -375,7 +375,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
*/
if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd &&
(cmd->cmd_sn >= conn->sess->exp_cmd_sn)) {
- list_del(&cmd->i_list);
+ list_del(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);
iscsit_free_cmd(cmd);
spin_lock_bh(&conn->cmd_lock);
@@ -397,7 +397,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
cmd->sess = conn->sess;
- list_del(&cmd->i_list);
+ list_del(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);
iscsit_free_all_datain_reqs(cmd);
@@ -407,7 +407,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
* Add the struct iscsi_cmd to the connection recovery cmd list
*/
spin_lock(&cr->conn_recovery_cmd_lock);
- list_add_tail(&cmd->i_list, &cr->conn_recovery_cmd_list);
+ list_add_tail(&cmd->i_conn_node, &cr->conn_recovery_cmd_list);
spin_unlock(&cr->conn_recovery_cmd_lock);
spin_lock_bh(&conn->cmd_lock);
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index eb05c9d751ea..ed5241e7f12a 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -803,14 +803,6 @@ static int iscsi_check_numerical_value(struct iscsi_param *param, char *value_pt
value = simple_strtoul(value_ptr, &tmpptr, 0);
-/* #warning FIXME: Fix this */
-#if 0
- if (strspn(endptr, WHITE_SPACE) != strlen(endptr)) {
- pr_err("Illegal value \"%s\" for \"%s\".\n",
- value, param->name);
- return -1;
- }
-#endif
if (IS_TYPERANGE_0_TO_2(param)) {
if ((value < 0) || (value > 2)) {
pr_err("Illegal value for \"%s\", must be"
@@ -1045,13 +1037,6 @@ static char *iscsi_check_valuelist_for_support(
tmp2 = strchr(acceptor_values, ',');
if (tmp2)
*tmp2 = '\0';
- if (!acceptor_values || !proposer_values) {
- if (tmp1)
- *tmp1 = ',';
- if (tmp2)
- *tmp2 = ',';
- return NULL;
- }
if (!strcmp(acceptor_values, proposer_values)) {
if (tmp2)
*tmp2 = ',';
@@ -1061,8 +1046,6 @@ static char *iscsi_check_valuelist_for_support(
*tmp2++ = ',';
acceptor_values = tmp2;
- if (!acceptor_values)
- break;
} while (acceptor_values);
if (tmp1)
*tmp1++ = ',';
diff --git a/drivers/target/iscsi/iscsi_target_seq_pdu_list.c b/drivers/target/iscsi/iscsi_target_seq_pdu_list.c
index fc694082bfc0..85a306e067ba 100644
--- a/drivers/target/iscsi/iscsi_target_seq_pdu_list.c
+++ b/drivers/target/iscsi/iscsi_target_seq_pdu_list.c
@@ -24,11 +24,13 @@
#include "iscsi_target_core.h"
#include "iscsi_target_util.h"
+#include "iscsi_target_tpg.h"
#include "iscsi_target_seq_pdu_list.h"
#define OFFLOAD_BUF_SIZE 32768
-void iscsit_dump_seq_list(struct iscsi_cmd *cmd)
+#ifdef DEBUG
+static void iscsit_dump_seq_list(struct iscsi_cmd *cmd)
{
int i;
struct iscsi_seq *seq;
@@ -46,7 +48,7 @@ void iscsit_dump_seq_list(struct iscsi_cmd *cmd)
}
}
-void iscsit_dump_pdu_list(struct iscsi_cmd *cmd)
+static void iscsit_dump_pdu_list(struct iscsi_cmd *cmd)
{
int i;
struct iscsi_pdu *pdu;
@@ -61,6 +63,10 @@ void iscsit_dump_pdu_list(struct iscsi_cmd *cmd)
pdu->length, pdu->pdu_send_order, pdu->seq_no);
}
}
+#else
+static void iscsit_dump_seq_list(struct iscsi_cmd *cmd) {}
+static void iscsit_dump_pdu_list(struct iscsi_cmd *cmd) {}
+#endif
static void iscsit_ordered_seq_lists(
struct iscsi_cmd *cmd,
@@ -135,11 +141,11 @@ redo:
seq_count++;
continue;
}
- array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
+ array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
if (!array) {
pr_err("Unable to allocate memory"
" for random array.\n");
- return -1;
+ return -ENOMEM;
}
iscsit_create_random_array(array, seq_count);
@@ -155,11 +161,11 @@ redo:
}
if (seq_count) {
- array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
+ array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
if (!array) {
pr_err("Unable to allocate memory for"
" random array.\n");
- return -1;
+ return -ENOMEM;
}
iscsit_create_random_array(array, seq_count);
@@ -187,10 +193,10 @@ static int iscsit_randomize_seq_lists(
if (!seq_count)
return 0;
- array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
+ array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
if (!array) {
pr_err("Unable to allocate memory for random array.\n");
- return -1;
+ return -ENOMEM;
}
iscsit_create_random_array(array, seq_count);
@@ -221,11 +227,10 @@ static void iscsit_determine_counts_for_list(
if ((bl->type == PDULIST_UNSOLICITED) ||
(bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
- unsolicited_data_length = (cmd->data_length >
- conn->sess->sess_ops->FirstBurstLength) ?
- conn->sess->sess_ops->FirstBurstLength : cmd->data_length;
+ unsolicited_data_length = min(cmd->se_cmd.data_length,
+ conn->sess->sess_ops->FirstBurstLength);
- while (offset < cmd->data_length) {
+ while (offset < cmd->se_cmd.data_length) {
*pdu_count += 1;
if (check_immediate) {
@@ -239,10 +244,10 @@ static void iscsit_determine_counts_for_list(
}
if (unsolicited_data_length > 0) {
if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
- >= cmd->data_length) {
+ >= cmd->se_cmd.data_length) {
unsolicited_data_length -=
- (cmd->data_length - offset);
- offset += (cmd->data_length - offset);
+ (cmd->se_cmd.data_length - offset);
+ offset += (cmd->se_cmd.data_length - offset);
continue;
}
if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
@@ -263,8 +268,8 @@ static void iscsit_determine_counts_for_list(
continue;
}
if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
- cmd->data_length) {
- offset += (cmd->data_length - offset);
+ cmd->se_cmd.data_length) {
+ offset += (cmd->se_cmd.data_length - offset);
continue;
}
if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
@@ -283,10 +288,10 @@ static void iscsit_determine_counts_for_list(
/*
- * Builds PDU and/or Sequence list, called while DataSequenceInOrder=No
- * and DataPDUInOrder=No.
+ * Builds PDU and/or Sequence list, called while DataSequenceInOrder=No
+ * or DataPDUInOrder=No.
*/
-static int iscsit_build_pdu_and_seq_list(
+static int iscsit_do_build_pdu_and_seq_lists(
struct iscsi_cmd *cmd,
struct iscsi_build_list *bl)
{
@@ -306,11 +311,10 @@ static int iscsit_build_pdu_and_seq_list(
if ((bl->type == PDULIST_UNSOLICITED) ||
(bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
- unsolicited_data_length = (cmd->data_length >
- conn->sess->sess_ops->FirstBurstLength) ?
- conn->sess->sess_ops->FirstBurstLength : cmd->data_length;
+ unsolicited_data_length = min(cmd->se_cmd.data_length,
+ conn->sess->sess_ops->FirstBurstLength);
- while (offset < cmd->data_length) {
+ while (offset < cmd->se_cmd.data_length) {
pdu_count++;
if (!datapduinorder) {
pdu[i].offset = offset;
@@ -346,21 +350,21 @@ static int iscsit_build_pdu_and_seq_list(
if (unsolicited_data_length > 0) {
if ((offset +
conn->conn_ops->MaxRecvDataSegmentLength) >=
- cmd->data_length) {
+ cmd->se_cmd.data_length) {
if (!datapduinorder) {
pdu[i].type = PDUTYPE_UNSOLICITED;
pdu[i].length =
- (cmd->data_length - offset);
+ (cmd->se_cmd.data_length - offset);
}
if (!datasequenceinorder) {
seq[seq_no].type = SEQTYPE_UNSOLICITED;
seq[seq_no].pdu_count = pdu_count;
seq[seq_no].xfer_len = (burstlength +
- (cmd->data_length - offset));
+ (cmd->se_cmd.data_length - offset));
}
unsolicited_data_length -=
- (cmd->data_length - offset);
- offset += (cmd->data_length - offset);
+ (cmd->se_cmd.data_length - offset);
+ offset += (cmd->se_cmd.data_length - offset);
continue;
}
if ((offset +
@@ -402,18 +406,18 @@ static int iscsit_build_pdu_and_seq_list(
continue;
}
if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
- cmd->data_length) {
+ cmd->se_cmd.data_length) {
if (!datapduinorder) {
pdu[i].type = PDUTYPE_NORMAL;
- pdu[i].length = (cmd->data_length - offset);
+ pdu[i].length = (cmd->se_cmd.data_length - offset);
}
if (!datasequenceinorder) {
seq[seq_no].type = SEQTYPE_NORMAL;
seq[seq_no].pdu_count = pdu_count;
seq[seq_no].xfer_len = (burstlength +
- (cmd->data_length - offset));
+ (cmd->se_cmd.data_length - offset));
}
- offset += (cmd->data_length - offset);
+ offset += (cmd->se_cmd.data_length - offset);
continue;
}
if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
@@ -464,9 +468,8 @@ static int iscsit_build_pdu_and_seq_list(
} else
iscsit_ordered_seq_lists(cmd, bl->type);
}
-#if 0
+
iscsit_dump_seq_list(cmd);
-#endif
}
if (!datapduinorder) {
if (bl->data_direction & ISCSI_PDU_WRITE) {
@@ -484,50 +487,86 @@ static int iscsit_build_pdu_and_seq_list(
} else
iscsit_ordered_pdu_lists(cmd, bl->type);
}
-#if 0
+
iscsit_dump_pdu_list(cmd);
-#endif
}
return 0;
}
-/*
- * Only called while DataSequenceInOrder=No or DataPDUInOrder=No.
- */
-int iscsit_do_build_list(
+int iscsit_build_pdu_and_seq_lists(
struct iscsi_cmd *cmd,
- struct iscsi_build_list *bl)
+ u32 immediate_data_length)
{
+ struct iscsi_build_list bl;
u32 pdu_count = 0, seq_count = 1;
struct iscsi_conn *conn = cmd->conn;
struct iscsi_pdu *pdu = NULL;
struct iscsi_seq *seq = NULL;
- iscsit_determine_counts_for_list(cmd, bl, &seq_count, &pdu_count);
+ struct iscsi_session *sess = conn->sess;
+ struct iscsi_node_attrib *na;
+
+ /*
+ * Do nothing if no OOO shenanigans
+ */
+ if (sess->sess_ops->DataSequenceInOrder &&
+ sess->sess_ops->DataPDUInOrder)
+ return 0;
+
+ if (cmd->data_direction == DMA_NONE)
+ return 0;
+
+ na = iscsit_tpg_get_node_attrib(sess);
+ memset(&bl, 0, sizeof(struct iscsi_build_list));
+
+ if (cmd->data_direction == DMA_FROM_DEVICE) {
+ bl.data_direction = ISCSI_PDU_READ;
+ bl.type = PDULIST_NORMAL;
+ if (na->random_datain_pdu_offsets)
+ bl.randomize |= RANDOM_DATAIN_PDU_OFFSETS;
+ if (na->random_datain_seq_offsets)
+ bl.randomize |= RANDOM_DATAIN_SEQ_OFFSETS;
+ } else {
+ bl.data_direction = ISCSI_PDU_WRITE;
+ bl.immediate_data_length = immediate_data_length;
+ if (na->random_r2t_offsets)
+ bl.randomize |= RANDOM_R2T_OFFSETS;
+
+ if (!cmd->immediate_data && !cmd->unsolicited_data)
+ bl.type = PDULIST_NORMAL;
+ else if (cmd->immediate_data && !cmd->unsolicited_data)
+ bl.type = PDULIST_IMMEDIATE;
+ else if (!cmd->immediate_data && cmd->unsolicited_data)
+ bl.type = PDULIST_UNSOLICITED;
+ else if (cmd->immediate_data && cmd->unsolicited_data)
+ bl.type = PDULIST_IMMEDIATE_AND_UNSOLICITED;
+ }
+
+ iscsit_determine_counts_for_list(cmd, &bl, &seq_count, &pdu_count);
if (!conn->sess->sess_ops->DataSequenceInOrder) {
- seq = kzalloc(seq_count * sizeof(struct iscsi_seq), GFP_ATOMIC);
+ seq = kcalloc(seq_count, sizeof(struct iscsi_seq), GFP_ATOMIC);
if (!seq) {
pr_err("Unable to allocate struct iscsi_seq list\n");
- return -1;
+ return -ENOMEM;
}
cmd->seq_list = seq;
cmd->seq_count = seq_count;
}
if (!conn->sess->sess_ops->DataPDUInOrder) {
- pdu = kzalloc(pdu_count * sizeof(struct iscsi_pdu), GFP_ATOMIC);
+ pdu = kcalloc(pdu_count, sizeof(struct iscsi_pdu), GFP_ATOMIC);
if (!pdu) {
pr_err("Unable to allocate struct iscsi_pdu list.\n");
kfree(seq);
- return -1;
+ return -ENOMEM;
}
cmd->pdu_list = pdu;
cmd->pdu_count = pdu_count;
}
- return iscsit_build_pdu_and_seq_list(cmd, bl);
+ return iscsit_do_build_pdu_and_seq_lists(cmd, &bl);
}
struct iscsi_pdu *iscsit_get_pdu_holder(
@@ -572,13 +611,12 @@ redo:
pdu = &cmd->pdu_list[cmd->pdu_start];
for (i = 0; pdu[i].seq_no != cmd->seq_no; i++) {
-#if 0
pr_debug("pdu[i].seq_no: %d, pdu[i].pdu"
"_send_order: %d, pdu[i].offset: %d,"
" pdu[i].length: %d\n", pdu[i].seq_no,
pdu[i].pdu_send_order, pdu[i].offset,
pdu[i].length);
-#endif
+
if (pdu[i].pdu_send_order == cmd->pdu_send_order) {
cmd->pdu_send_order++;
return &pdu[i];
@@ -601,11 +639,11 @@ redo:
pr_err("struct iscsi_seq is NULL!\n");
return NULL;
}
-#if 0
+
pr_debug("seq->pdu_start: %d, seq->pdu_count: %d,"
" seq->seq_no: %d\n", seq->pdu_start, seq->pdu_count,
seq->seq_no);
-#endif
+
pdu = &cmd->pdu_list[seq->pdu_start];
if (seq->pdu_send_order == seq->pdu_count) {
@@ -645,12 +683,11 @@ struct iscsi_seq *iscsit_get_seq_holder(
}
for (i = 0; i < cmd->seq_count; i++) {
-#if 0
pr_debug("seq_list[i].orig_offset: %d, seq_list[i]."
"xfer_len: %d, seq_list[i].seq_no %u\n",
cmd->seq_list[i].orig_offset, cmd->seq_list[i].xfer_len,
cmd->seq_list[i].seq_no);
-#endif
+
if ((cmd->seq_list[i].orig_offset +
cmd->seq_list[i].xfer_len) >=
(offset + length))
diff --git a/drivers/target/iscsi/iscsi_target_seq_pdu_list.h b/drivers/target/iscsi/iscsi_target_seq_pdu_list.h
index 0d52a10e3069..d5b153751a8d 100644
--- a/drivers/target/iscsi/iscsi_target_seq_pdu_list.h
+++ b/drivers/target/iscsi/iscsi_target_seq_pdu_list.h
@@ -78,7 +78,7 @@ struct iscsi_seq {
u32 xfer_len;
} ____cacheline_aligned;
-extern int iscsit_do_build_list(struct iscsi_cmd *, struct iscsi_build_list *);
+extern int iscsit_build_pdu_and_seq_lists(struct iscsi_cmd *, u32);
extern struct iscsi_pdu *iscsit_get_pdu_holder(struct iscsi_cmd *, u32, u32);
extern struct iscsi_pdu *iscsit_get_pdu_holder_for_seq(struct iscsi_cmd *, struct iscsi_seq *);
extern struct iscsi_seq *iscsit_get_seq_holder(struct iscsi_cmd *, u32, u32);
diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c
index e01da9d2b37e..f4e640b51fd1 100644
--- a/drivers/target/iscsi/iscsi_target_tmr.c
+++ b/drivers/target/iscsi/iscsi_target_tmr.c
@@ -78,10 +78,7 @@ int iscsit_tmr_task_warm_reset(
{
struct iscsi_session *sess = conn->sess;
struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
-#if 0
- struct iscsi_init_task_mgt_cmnd *hdr =
- (struct iscsi_init_task_mgt_cmnd *) buf;
-#endif
+
if (!na->tmr_warm_reset) {
pr_err("TMR Opcode TARGET_WARM_RESET authorization"
" failed for Initiator Node: %s\n",
@@ -216,7 +213,7 @@ static int iscsit_task_reassign_complete_nop_out(
iscsit_task_reassign_remove_cmd(cmd, cr, conn->sess);
spin_lock_bh(&conn->cmd_lock);
- list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+ list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock);
cmd->i_state = ISTATE_SEND_NOPIN;
@@ -272,9 +269,9 @@ static int iscsit_task_reassign_complete_write(
offset = cmd->next_burst_len = cmd->write_data_done;
if ((conn->sess->sess_ops->FirstBurstLength - offset) >=
- cmd->data_length) {
+ cmd->se_cmd.data_length) {
no_build_r2ts = 1;
- length = (cmd->data_length - offset);
+ length = (cmd->se_cmd.data_length - offset);
} else
length = (conn->sess->sess_ops->FirstBurstLength - offset);
@@ -292,7 +289,7 @@ static int iscsit_task_reassign_complete_write(
/*
* iscsit_build_r2ts_for_cmd() can handle the rest from here.
*/
- return iscsit_build_r2ts_for_cmd(cmd, conn, 2);
+ return iscsit_build_r2ts_for_cmd(cmd, conn, true);
}
static int iscsit_task_reassign_complete_read(
@@ -385,7 +382,7 @@ static int iscsit_task_reassign_complete_scsi_cmnd(
iscsit_task_reassign_remove_cmd(cmd, cr, conn->sess);
spin_lock_bh(&conn->cmd_lock);
- list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+ list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock);
if (se_cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 4eba86d2bd82..b42cdeb153df 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -163,7 +163,7 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)
}
cmd->conn = conn;
- INIT_LIST_HEAD(&cmd->i_list);
+ INIT_LIST_HEAD(&cmd->i_conn_node);
INIT_LIST_HEAD(&cmd->datain_list);
INIT_LIST_HEAD(&cmd->cmd_r2t_list);
init_completion(&cmd->reject_comp);
@@ -176,174 +176,6 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)
return cmd;
}
-/*
- * Called from iscsi_handle_scsi_cmd()
- */
-struct iscsi_cmd *iscsit_allocate_se_cmd(
- struct iscsi_conn *conn,
- u32 data_length,
- int data_direction,
- int iscsi_task_attr)
-{
- struct iscsi_cmd *cmd;
- struct se_cmd *se_cmd;
- int sam_task_attr;
-
- cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
- if (!cmd)
- return NULL;
-
- cmd->data_direction = data_direction;
- cmd->data_length = data_length;
- /*
- * Figure out the SAM Task Attribute for the incoming SCSI CDB
- */
- if ((iscsi_task_attr == ISCSI_ATTR_UNTAGGED) ||
- (iscsi_task_attr == ISCSI_ATTR_SIMPLE))
- sam_task_attr = MSG_SIMPLE_TAG;
- else if (iscsi_task_attr == ISCSI_ATTR_ORDERED)
- sam_task_attr = MSG_ORDERED_TAG;
- else if (iscsi_task_attr == ISCSI_ATTR_HEAD_OF_QUEUE)
- sam_task_attr = MSG_HEAD_TAG;
- else if (iscsi_task_attr == ISCSI_ATTR_ACA)
- sam_task_attr = MSG_ACA_TAG;
- else {
- pr_debug("Unknown iSCSI Task Attribute: 0x%02x, using"
- " MSG_SIMPLE_TAG\n", iscsi_task_attr);
- sam_task_attr = MSG_SIMPLE_TAG;
- }
-
- se_cmd = &cmd->se_cmd;
- /*
- * Initialize struct se_cmd descriptor from target_core_mod infrastructure
- */
- transport_init_se_cmd(se_cmd, &lio_target_fabric_configfs->tf_ops,
- conn->sess->se_sess, data_length, data_direction,
- sam_task_attr, &cmd->sense_buffer[0]);
- return cmd;
-}
-
-struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr(
- struct iscsi_conn *conn,
- u8 function)
-{
- struct iscsi_cmd *cmd;
- struct se_cmd *se_cmd;
- int rc;
- u8 tcm_function;
-
- cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
- if (!cmd)
- return NULL;
-
- cmd->data_direction = DMA_NONE;
-
- cmd->tmr_req = kzalloc(sizeof(struct iscsi_tmr_req), GFP_KERNEL);
- if (!cmd->tmr_req) {
- pr_err("Unable to allocate memory for"
- " Task Management command!\n");
- goto out;
- }
- /*
- * TASK_REASSIGN for ERL=2 / connection stays inside of
- * LIO-Target $FABRIC_MOD
- */
- if (function == ISCSI_TM_FUNC_TASK_REASSIGN)
- return cmd;
-
- se_cmd = &cmd->se_cmd;
- /*
- * Initialize struct se_cmd descriptor from target_core_mod infrastructure
- */
- transport_init_se_cmd(se_cmd, &lio_target_fabric_configfs->tf_ops,
- conn->sess->se_sess, 0, DMA_NONE,
- MSG_SIMPLE_TAG, &cmd->sense_buffer[0]);
-
- switch (function) {
- case ISCSI_TM_FUNC_ABORT_TASK:
- tcm_function = TMR_ABORT_TASK;
- break;
- case ISCSI_TM_FUNC_ABORT_TASK_SET:
- tcm_function = TMR_ABORT_TASK_SET;
- break;
- case ISCSI_TM_FUNC_CLEAR_ACA:
- tcm_function = TMR_CLEAR_ACA;
- break;
- case ISCSI_TM_FUNC_CLEAR_TASK_SET:
- tcm_function = TMR_CLEAR_TASK_SET;
- break;
- case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
- tcm_function = TMR_LUN_RESET;
- break;
- case ISCSI_TM_FUNC_TARGET_WARM_RESET:
- tcm_function = TMR_TARGET_WARM_RESET;
- break;
- case ISCSI_TM_FUNC_TARGET_COLD_RESET:
- tcm_function = TMR_TARGET_COLD_RESET;
- break;
- default:
- pr_err("Unknown iSCSI TMR Function:"
- " 0x%02x\n", function);
- goto out;
- }
-
- rc = core_tmr_alloc_req(se_cmd, cmd->tmr_req, tcm_function, GFP_KERNEL);
- if (rc < 0)
- goto out;
-
- cmd->tmr_req->se_tmr_req = se_cmd->se_tmr_req;
-
- return cmd;
-out:
- iscsit_release_cmd(cmd);
- return NULL;
-}
-
-int iscsit_decide_list_to_build(
- struct iscsi_cmd *cmd,
- u32 immediate_data_length)
-{
- struct iscsi_build_list bl;
- struct iscsi_conn *conn = cmd->conn;
- struct iscsi_session *sess = conn->sess;
- struct iscsi_node_attrib *na;
-
- if (sess->sess_ops->DataSequenceInOrder &&
- sess->sess_ops->DataPDUInOrder)
- return 0;
-
- if (cmd->data_direction == DMA_NONE)
- return 0;
-
- na = iscsit_tpg_get_node_attrib(sess);
- memset(&bl, 0, sizeof(struct iscsi_build_list));
-
- if (cmd->data_direction == DMA_FROM_DEVICE) {
- bl.data_direction = ISCSI_PDU_READ;
- bl.type = PDULIST_NORMAL;
- if (na->random_datain_pdu_offsets)
- bl.randomize |= RANDOM_DATAIN_PDU_OFFSETS;
- if (na->random_datain_seq_offsets)
- bl.randomize |= RANDOM_DATAIN_SEQ_OFFSETS;
- } else {
- bl.data_direction = ISCSI_PDU_WRITE;
- bl.immediate_data_length = immediate_data_length;
- if (na->random_r2t_offsets)
- bl.randomize |= RANDOM_R2T_OFFSETS;
-
- if (!cmd->immediate_data && !cmd->unsolicited_data)
- bl.type = PDULIST_NORMAL;
- else if (cmd->immediate_data && !cmd->unsolicited_data)
- bl.type = PDULIST_IMMEDIATE;
- else if (!cmd->immediate_data && cmd->unsolicited_data)
- bl.type = PDULIST_UNSOLICITED;
- else if (cmd->immediate_data && cmd->unsolicited_data)
- bl.type = PDULIST_IMMEDIATE_AND_UNSOLICITED;
- }
-
- return iscsit_do_build_list(cmd, &bl);
-}
-
struct iscsi_seq *iscsit_get_seq_holder_for_datain(
struct iscsi_cmd *cmd,
u32 seq_send_order)
@@ -502,14 +334,14 @@ int iscsit_check_unsolicited_dataout(struct iscsi_cmd *cmd, unsigned char *buf)
if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))
return 0;
- if (((cmd->first_burst_len + payload_length) != cmd->data_length) &&
+ if (((cmd->first_burst_len + payload_length) != cmd->se_cmd.data_length) &&
((cmd->first_burst_len + payload_length) !=
conn->sess->sess_ops->FirstBurstLength)) {
pr_err("Unsolicited non-immediate data received %u"
" does not equal FirstBurstLength: %u, and does"
" not equal ExpXferLen %u.\n",
(cmd->first_burst_len + payload_length),
- conn->sess->sess_ops->FirstBurstLength, cmd->data_length);
+ conn->sess->sess_ops->FirstBurstLength, cmd->se_cmd.data_length);
transport_send_check_condition_and_sense(se_cmd,
TCM_INCORRECT_AMOUNT_OF_DATA, 0);
return -1;
@@ -524,7 +356,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_itt(
struct iscsi_cmd *cmd;
spin_lock_bh(&conn->cmd_lock);
- list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
+ list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
if (cmd->init_task_tag == init_task_tag) {
spin_unlock_bh(&conn->cmd_lock);
return cmd;
@@ -545,7 +377,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(
struct iscsi_cmd *cmd;
spin_lock_bh(&conn->cmd_lock);
- list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
+ list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
if (cmd->init_task_tag == init_task_tag) {
spin_unlock_bh(&conn->cmd_lock);
return cmd;
@@ -568,7 +400,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_ttt(
struct iscsi_cmd *cmd = NULL;
spin_lock_bh(&conn->cmd_lock);
- list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
+ list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
if (cmd->targ_xfer_tag == targ_xfer_tag) {
spin_unlock_bh(&conn->cmd_lock);
return cmd;
@@ -596,7 +428,7 @@ int iscsit_find_cmd_for_recovery(
spin_lock(&sess->cr_i_lock);
list_for_each_entry(cr, &sess->cr_inactive_list, cr_list) {
spin_lock(&cr->conn_recovery_cmd_lock);
- list_for_each_entry(cmd, &cr->conn_recovery_cmd_list, i_list) {
+ list_for_each_entry(cmd, &cr->conn_recovery_cmd_list, i_conn_node) {
if (cmd->init_task_tag == init_task_tag) {
spin_unlock(&cr->conn_recovery_cmd_lock);
spin_unlock(&sess->cr_i_lock);
@@ -616,7 +448,7 @@ int iscsit_find_cmd_for_recovery(
spin_lock(&sess->cr_a_lock);
list_for_each_entry(cr, &sess->cr_active_list, cr_list) {
spin_lock(&cr->conn_recovery_cmd_lock);
- list_for_each_entry(cmd, &cr->conn_recovery_cmd_list, i_list) {
+ list_for_each_entry(cmd, &cr->conn_recovery_cmd_list, i_conn_node) {
if (cmd->init_task_tag == init_task_tag) {
spin_unlock(&cr->conn_recovery_cmd_lock);
spin_unlock(&sess->cr_a_lock);
@@ -813,7 +645,6 @@ void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
void iscsit_release_cmd(struct iscsi_cmd *cmd)
{
struct iscsi_conn *conn = cmd->conn;
- int i;
iscsit_free_r2ts_from_list(cmd);
iscsit_free_all_datain_reqs(cmd);
@@ -824,11 +655,6 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd)
kfree(cmd->tmr_req);
kfree(cmd->iov_data);
- for (i = 0; i < cmd->t_mem_sg_nents; i++)
- __free_page(sg_page(&cmd->t_mem_sg[i]));
-
- kfree(cmd->t_mem_sg);
-
if (conn) {
iscsit_remove_cmd_from_immediate_queue(cmd, conn);
iscsit_remove_cmd_from_response_queue(cmd, conn);
@@ -1038,7 +864,7 @@ static int iscsit_add_nopin(struct iscsi_conn *conn, int want_response)
spin_unlock_bh(&conn->sess->ttt_lock);
spin_lock_bh(&conn->cmd_lock);
- list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+ list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock);
if (want_response)
diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h
index 835bf7de0281..e1c729b8a1c5 100644
--- a/drivers/target/iscsi/iscsi_target_util.h
+++ b/drivers/target/iscsi/iscsi_target_util.h
@@ -9,9 +9,6 @@ extern struct iscsi_r2t *iscsit_get_r2t_from_list(struct iscsi_cmd *);
extern void iscsit_free_r2t(struct iscsi_r2t *, struct iscsi_cmd *);
extern void iscsit_free_r2ts_from_list(struct iscsi_cmd *);
extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t);
-extern struct iscsi_cmd *iscsit_allocate_se_cmd(struct iscsi_conn *, u32, int, int);
-extern struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr(struct iscsi_conn *, u8);
-extern int iscsit_decide_list_to_build(struct iscsi_cmd *, u32);
extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsi_cmd *, u32);
extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *);
extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32);
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index a9b4eeefe9fc..38dfac2b0a1c 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -213,7 +213,7 @@ static void tcm_loop_submission_work(struct work_struct *work)
* associated read buffers, go ahead and do that here for type
* SCF_SCSI_CONTROL_SG_IO_CDB. Also note that this is currently
* guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB
- * by target core in transport_generic_allocate_tasks() ->
+ * by target core in target_setup_cmd_from_cdb() ->
* transport_generic_cmd_sequencer().
*/
if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB &&
@@ -227,7 +227,7 @@ static void tcm_loop_submission_work(struct work_struct *work)
}
}
- ret = transport_generic_allocate_tasks(se_cmd, sc->cmnd);
+ ret = target_setup_cmd_from_cdb(se_cmd, sc->cmnd);
if (ret == -ENOMEM) {
transport_send_check_condition_and_sense(se_cmd,
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
diff --git a/drivers/target/sbp/Kconfig b/drivers/target/sbp/Kconfig
new file mode 100644
index 000000000000..132da544eafc
--- /dev/null
+++ b/drivers/target/sbp/Kconfig
@@ -0,0 +1,11 @@
+config SBP_TARGET
+ tristate "FireWire SBP-2 fabric module"
+ depends on FIREWIRE && EXPERIMENTAL
+ help
+ Say Y or M here to enable SCSI target functionality over FireWire.
+ This enables you to expose SCSI devices to other nodes on the FireWire
+ bus, for example hard disks. Similar to FireWire Target Disk mode on
+ many Apple computers.
+
+ To compile this driver as a module, say M here: The module will be
+ called sbp-target.
diff --git a/drivers/target/sbp/Makefile b/drivers/target/sbp/Makefile
new file mode 100644
index 000000000000..27747ad054c4
--- /dev/null
+++ b/drivers/target/sbp/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SBP_TARGET) += sbp_target.o
diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
new file mode 100644
index 000000000000..37c609898f84
--- /dev/null
+++ b/drivers/target/sbp/sbp_target.c
@@ -0,0 +1,2621 @@
+/*
+ * SBP2 target driver (SCSI over IEEE1394 in target mode)
+ *
+ * Copyright (C) 2011 Chris Boot <bootc@bootc.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define KMSG_COMPONENT "sbp_target"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/configfs.h>
+#include <linux/ctype.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_tcq.h>
+#include <target/target_core_base.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
+#include <target/target_core_fabric_configfs.h>
+#include <target/target_core_configfs.h>
+#include <target/configfs_macros.h>
+#include <asm/unaligned.h>
+
+#include "sbp_target.h"
+
+/* Local pointer to allocated TCM configfs fabric module */
+static struct target_fabric_configfs *sbp_fabric_configfs;
+
+/* FireWire address region for management and command block address handlers */
+static const struct fw_address_region sbp_register_region = {
+ .start = CSR_REGISTER_BASE + 0x10000,
+ .end = 0x1000000000000ULL,
+};
+
+static const u32 sbp_unit_directory_template[] = {
+ 0x1200609e, /* unit_specifier_id: NCITS/T10 */
+ 0x13010483, /* unit_sw_version: 1155D Rev 4 */
+ 0x3800609e, /* command_set_specifier_id: NCITS/T10 */
+ 0x390104d8, /* command_set: SPC-2 */
+ 0x3b000000, /* command_set_revision: 0 */
+ 0x3c000001, /* firmware_revision: 1 */
+};
+
+#define SESSION_MAINTENANCE_INTERVAL HZ
+
+static atomic_t login_id = ATOMIC_INIT(0);
+
+static void session_maintenance_work(struct work_struct *);
+static int sbp_run_transaction(struct fw_card *, int, int, int, int,
+ unsigned long long, void *, size_t);
+
+static int read_peer_guid(u64 *guid, const struct sbp_management_request *req)
+{
+ int ret;
+ __be32 high, low;
+
+ ret = sbp_run_transaction(req->card, TCODE_READ_QUADLET_REQUEST,
+ req->node_addr, req->generation, req->speed,
+ (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + 3 * 4,
+ &high, sizeof(high));
+ if (ret != RCODE_COMPLETE)
+ return ret;
+
+ ret = sbp_run_transaction(req->card, TCODE_READ_QUADLET_REQUEST,
+ req->node_addr, req->generation, req->speed,
+ (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + 4 * 4,
+ &low, sizeof(low));
+ if (ret != RCODE_COMPLETE)
+ return ret;
+
+ *guid = (u64)be32_to_cpu(high) << 32 | be32_to_cpu(low);
+
+ return RCODE_COMPLETE;
+}
+
+static struct sbp_session *sbp_session_find_by_guid(
+ struct sbp_tpg *tpg, u64 guid)
+{
+ struct se_session *se_sess;
+ struct sbp_session *sess, *found = NULL;
+
+ spin_lock_bh(&tpg->se_tpg.session_lock);
+ list_for_each_entry(se_sess, &tpg->se_tpg.tpg_sess_list, sess_list) {
+ sess = se_sess->fabric_sess_ptr;
+ if (sess->guid == guid)
+ found = sess;
+ }
+ spin_unlock_bh(&tpg->se_tpg.session_lock);
+
+ return found;
+}
+
+static struct sbp_login_descriptor *sbp_login_find_by_lun(
+ struct sbp_session *session, struct se_lun *lun)
+{
+ struct sbp_login_descriptor *login, *found = NULL;
+
+ spin_lock_bh(&session->lock);
+ list_for_each_entry(login, &session->login_list, link) {
+ if (login->lun == lun)
+ found = login;
+ }
+ spin_unlock_bh(&session->lock);
+
+ return found;
+}
+
+static int sbp_login_count_all_by_lun(
+ struct sbp_tpg *tpg,
+ struct se_lun *lun,
+ int exclusive)
+{
+ struct se_session *se_sess;
+ struct sbp_session *sess;
+ struct sbp_login_descriptor *login;
+ int count = 0;
+
+ spin_lock_bh(&tpg->se_tpg.session_lock);
+ list_for_each_entry(se_sess, &tpg->se_tpg.tpg_sess_list, sess_list) {
+ sess = se_sess->fabric_sess_ptr;
+
+ spin_lock_bh(&sess->lock);
+ list_for_each_entry(login, &sess->login_list, link) {
+ if (login->lun != lun)
+ continue;
+
+ if (!exclusive || login->exclusive)
+ count++;
+ }
+ spin_unlock_bh(&sess->lock);
+ }
+ spin_unlock_bh(&tpg->se_tpg.session_lock);
+
+ return count;
+}
+
+static struct sbp_login_descriptor *sbp_login_find_by_id(
+ struct sbp_tpg *tpg, int login_id)
+{
+ struct se_session *se_sess;
+ struct sbp_session *sess;
+ struct sbp_login_descriptor *login, *found = NULL;
+
+ spin_lock_bh(&tpg->se_tpg.session_lock);
+ list_for_each_entry(se_sess, &tpg->se_tpg.tpg_sess_list, sess_list) {
+ sess = se_sess->fabric_sess_ptr;
+
+ spin_lock_bh(&sess->lock);
+ list_for_each_entry(login, &sess->login_list, link) {
+ if (login->login_id == login_id)
+ found = login;
+ }
+ spin_unlock_bh(&sess->lock);
+ }
+ spin_unlock_bh(&tpg->se_tpg.session_lock);
+
+ return found;
+}
+
+static struct se_lun *sbp_get_lun_from_tpg(struct sbp_tpg *tpg, int lun)
+{
+ struct se_portal_group *se_tpg = &tpg->se_tpg;
+ struct se_lun *se_lun;
+
+ if (lun >= TRANSPORT_MAX_LUNS_PER_TPG)
+ return ERR_PTR(-EINVAL);
+
+ spin_lock(&se_tpg->tpg_lun_lock);
+ se_lun = se_tpg->tpg_lun_list[lun];
+
+ if (se_lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE)
+ se_lun = ERR_PTR(-ENODEV);
+
+ spin_unlock(&se_tpg->tpg_lun_lock);
+
+ return se_lun;
+}
+
+static struct sbp_session *sbp_session_create(
+ struct sbp_tpg *tpg,
+ u64 guid)
+{
+ struct sbp_session *sess;
+ int ret;
+ char guid_str[17];
+ struct se_node_acl *se_nacl;
+
+ sess = kmalloc(sizeof(*sess), GFP_KERNEL);
+ if (!sess) {
+ pr_err("failed to allocate session descriptor\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ sess->se_sess = transport_init_session();
+ if (IS_ERR(sess->se_sess)) {
+ pr_err("failed to init se_session\n");
+
+ ret = PTR_ERR(sess->se_sess);
+ kfree(sess);
+ return ERR_PTR(ret);
+ }
+
+ snprintf(guid_str, sizeof(guid_str), "%016llx", guid);
+
+ se_nacl = core_tpg_check_initiator_node_acl(&tpg->se_tpg, guid_str);
+ if (!se_nacl) {
+ pr_warn("Node ACL not found for %s\n", guid_str);
+
+ transport_free_session(sess->se_sess);
+ kfree(sess);
+
+ return ERR_PTR(-EPERM);
+ }
+
+ sess->se_sess->se_node_acl = se_nacl;
+
+ spin_lock_init(&sess->lock);
+ INIT_LIST_HEAD(&sess->login_list);
+ INIT_DELAYED_WORK(&sess->maint_work, session_maintenance_work);
+
+ sess->guid = guid;
+
+ transport_register_session(&tpg->se_tpg, se_nacl, sess->se_sess, sess);
+
+ return sess;
+}
+
+static void sbp_session_release(struct sbp_session *sess, bool cancel_work)
+{
+ spin_lock_bh(&sess->lock);
+ if (!list_empty(&sess->login_list)) {
+ spin_unlock_bh(&sess->lock);
+ return;
+ }
+ spin_unlock_bh(&sess->lock);
+
+ if (cancel_work)
+ cancel_delayed_work_sync(&sess->maint_work);
+
+ transport_deregister_session_configfs(sess->se_sess);
+ transport_deregister_session(sess->se_sess);
+
+ if (sess->card)
+ fw_card_put(sess->card);
+
+ kfree(sess);
+}
+
+static void sbp_target_agent_unregister(struct sbp_target_agent *);
+
+static void sbp_login_release(struct sbp_login_descriptor *login,
+ bool cancel_work)
+{
+ struct sbp_session *sess = login->sess;
+
+ /* FIXME: abort/wait on tasks */
+
+ sbp_target_agent_unregister(login->tgt_agt);
+
+ if (sess) {
+ spin_lock_bh(&sess->lock);
+ list_del(&login->link);
+ spin_unlock_bh(&sess->lock);
+
+ sbp_session_release(sess, cancel_work);
+ }
+
+ kfree(login);
+}
+
+static struct sbp_target_agent *sbp_target_agent_register(
+ struct sbp_login_descriptor *);
+
+static void sbp_management_request_login(
+ struct sbp_management_agent *agent, struct sbp_management_request *req,
+ int *status_data_size)
+{
+ struct sbp_tport *tport = agent->tport;
+ struct sbp_tpg *tpg = tport->tpg;
+ struct se_lun *se_lun;
+ int ret;
+ u64 guid;
+ struct sbp_session *sess;
+ struct sbp_login_descriptor *login;
+ struct sbp_login_response_block *response;
+ int login_response_len;
+
+ se_lun = sbp_get_lun_from_tpg(tpg,
+ LOGIN_ORB_LUN(be32_to_cpu(req->orb.misc)));
+ if (IS_ERR(se_lun)) {
+ pr_notice("login to unknown LUN: %d\n",
+ LOGIN_ORB_LUN(be32_to_cpu(req->orb.misc)));
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_LUN_NOTSUPP));
+ return;
+ }
+
+ ret = read_peer_guid(&guid, req);
+ if (ret != RCODE_COMPLETE) {
+ pr_warn("failed to read peer GUID: %d\n", ret);
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_TRANSPORT_FAILURE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
+ return;
+ }
+
+ pr_notice("mgt_agent LOGIN to LUN %d from %016llx\n",
+ se_lun->unpacked_lun, guid);
+
+ sess = sbp_session_find_by_guid(tpg, guid);
+ if (sess) {
+ login = sbp_login_find_by_lun(sess, se_lun);
+ if (login) {
+ pr_notice("initiator already logged-in\n");
+
+ /*
+ * SBP-2 R4 says we should return access denied, but
+ * that can confuse initiators. Instead we need to
+ * treat this like a reconnect, but send the login
+ * response block like a fresh login.
+ *
+ * This is required particularly in the case of Apple
+ * devices booting off the FireWire target, where
+ * the firmware has an active login to the target. When
+ * the OS takes control of the session it issues its own
+ * LOGIN rather than a RECONNECT. To avoid the machine
+ * waiting until the reconnect_hold expires, we can skip
+ * the ACCESS_DENIED errors to speed things up.
+ */
+
+ goto already_logged_in;
+ }
+ }
+
+ /*
+ * check exclusive bit in login request
+ * reject with access_denied if any logins present
+ */
+ if (LOGIN_ORB_EXCLUSIVE(be32_to_cpu(req->orb.misc)) &&
+ sbp_login_count_all_by_lun(tpg, se_lun, 0)) {
+ pr_warn("refusing exclusive login with other active logins\n");
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_ACCESS_DENIED));
+ return;
+ }
+
+ /*
+ * check exclusive bit in any existing login descriptor
+ * reject with access_denied if any exclusive logins present
+ */
+ if (sbp_login_count_all_by_lun(tpg, se_lun, 1)) {
+ pr_warn("refusing login while another exclusive login present\n");
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_ACCESS_DENIED));
+ return;
+ }
+
+ /*
+ * check we haven't exceeded the number of allowed logins
+ * reject with resources_unavailable if we have
+ */
+ if (sbp_login_count_all_by_lun(tpg, se_lun, 0) >=
+ tport->max_logins_per_lun) {
+ pr_warn("max number of logins reached\n");
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_RESOURCES_UNAVAIL));
+ return;
+ }
+
+ if (!sess) {
+ sess = sbp_session_create(tpg, guid);
+ if (IS_ERR(sess)) {
+ switch (PTR_ERR(sess)) {
+ case -EPERM:
+ ret = SBP_STATUS_ACCESS_DENIED;
+ break;
+ default:
+ ret = SBP_STATUS_RESOURCES_UNAVAIL;
+ break;
+ }
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(
+ STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(ret));
+ return;
+ }
+
+ sess->node_id = req->node_addr;
+ sess->card = fw_card_get(req->card);
+ sess->generation = req->generation;
+ sess->speed = req->speed;
+
+ schedule_delayed_work(&sess->maint_work,
+ SESSION_MAINTENANCE_INTERVAL);
+ }
+
+ /* only take the latest reconnect_hold into account */
+ sess->reconnect_hold = min(
+ 1 << LOGIN_ORB_RECONNECT(be32_to_cpu(req->orb.misc)),
+ tport->max_reconnect_timeout) - 1;
+
+ login = kmalloc(sizeof(*login), GFP_KERNEL);
+ if (!login) {
+ pr_err("failed to allocate login descriptor\n");
+
+ sbp_session_release(sess, true);
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_RESOURCES_UNAVAIL));
+ return;
+ }
+
+ login->sess = sess;
+ login->lun = se_lun;
+ login->status_fifo_addr = sbp2_pointer_to_addr(&req->orb.status_fifo);
+ login->exclusive = LOGIN_ORB_EXCLUSIVE(be32_to_cpu(req->orb.misc));
+ login->login_id = atomic_inc_return(&login_id);
+
+ login->tgt_agt = sbp_target_agent_register(login);
+ if (IS_ERR(login->tgt_agt)) {
+ ret = PTR_ERR(login->tgt_agt);
+ pr_err("failed to map command block handler: %d\n", ret);
+
+ sbp_session_release(sess, true);
+ kfree(login);
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_RESOURCES_UNAVAIL));
+ return;
+ }
+
+ spin_lock_bh(&sess->lock);
+ list_add_tail(&login->link, &sess->login_list);
+ spin_unlock_bh(&sess->lock);
+
+already_logged_in:
+ response = kzalloc(sizeof(*response), GFP_KERNEL);
+ if (!response) {
+ pr_err("failed to allocate login response block\n");
+
+ sbp_login_release(login, true);
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_RESOURCES_UNAVAIL));
+ return;
+ }
+
+ login_response_len = clamp_val(
+ LOGIN_ORB_RESPONSE_LENGTH(be32_to_cpu(req->orb.length)),
+ 12, sizeof(*response));
+ response->misc = cpu_to_be32(
+ ((login_response_len & 0xffff) << 16) |
+ (login->login_id & 0xffff));
+ response->reconnect_hold = cpu_to_be32(sess->reconnect_hold & 0xffff);
+ addr_to_sbp2_pointer(login->tgt_agt->handler.offset,
+ &response->command_block_agent);
+
+ ret = sbp_run_transaction(sess->card, TCODE_WRITE_BLOCK_REQUEST,
+ sess->node_id, sess->generation, sess->speed,
+ sbp2_pointer_to_addr(&req->orb.ptr2), response,
+ login_response_len);
+ if (ret != RCODE_COMPLETE) {
+ pr_debug("failed to write login response block: %x\n", ret);
+
+ kfree(response);
+ sbp_login_release(login, true);
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_TRANSPORT_FAILURE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
+ return;
+ }
+
+ kfree(response);
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_OK));
+}
+
+static void sbp_management_request_query_logins(
+ struct sbp_management_agent *agent, struct sbp_management_request *req,
+ int *status_data_size)
+{
+ pr_notice("QUERY LOGINS not implemented\n");
+ /* FIXME: implement */
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQ_TYPE_NOTSUPP));
+}
+
+static void sbp_management_request_reconnect(
+ struct sbp_management_agent *agent, struct sbp_management_request *req,
+ int *status_data_size)
+{
+ struct sbp_tport *tport = agent->tport;
+ struct sbp_tpg *tpg = tport->tpg;
+ int ret;
+ u64 guid;
+ struct sbp_login_descriptor *login;
+
+ ret = read_peer_guid(&guid, req);
+ if (ret != RCODE_COMPLETE) {
+ pr_warn("failed to read peer GUID: %d\n", ret);
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_TRANSPORT_FAILURE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
+ return;
+ }
+
+ pr_notice("mgt_agent RECONNECT from %016llx\n", guid);
+
+ login = sbp_login_find_by_id(tpg,
+ RECONNECT_ORB_LOGIN_ID(be32_to_cpu(req->orb.misc)));
+
+ if (!login) {
+ pr_err("mgt_agent RECONNECT unknown login ID\n");
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_ACCESS_DENIED));
+ return;
+ }
+
+ if (login->sess->guid != guid) {
+ pr_err("mgt_agent RECONNECT login GUID doesn't match\n");
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_ACCESS_DENIED));
+ return;
+ }
+
+ spin_lock_bh(&login->sess->lock);
+ if (login->sess->card)
+ fw_card_put(login->sess->card);
+
+ /* update the node details */
+ login->sess->generation = req->generation;
+ login->sess->node_id = req->node_addr;
+ login->sess->card = fw_card_get(req->card);
+ login->sess->speed = req->speed;
+ spin_unlock_bh(&login->sess->lock);
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_OK));
+}
+
+static void sbp_management_request_logout(
+ struct sbp_management_agent *agent, struct sbp_management_request *req,
+ int *status_data_size)
+{
+ struct sbp_tport *tport = agent->tport;
+ struct sbp_tpg *tpg = tport->tpg;
+ int login_id;
+ struct sbp_login_descriptor *login;
+
+ login_id = LOGOUT_ORB_LOGIN_ID(be32_to_cpu(req->orb.misc));
+
+ login = sbp_login_find_by_id(tpg, login_id);
+ if (!login) {
+ pr_warn("cannot find login: %d\n", login_id);
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_LOGIN_ID_UNKNOWN));
+ return;
+ }
+
+ pr_info("mgt_agent LOGOUT from LUN %d session %d\n",
+ login->lun->unpacked_lun, login->login_id);
+
+ if (req->node_addr != login->sess->node_id) {
+ pr_warn("logout from different node ID\n");
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_ACCESS_DENIED));
+ return;
+ }
+
+ sbp_login_release(login, true);
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_OK));
+}
+
+static void session_check_for_reset(struct sbp_session *sess)
+{
+ bool card_valid = false;
+
+ spin_lock_bh(&sess->lock);
+
+ if (sess->card) {
+ spin_lock_irq(&sess->card->lock);
+ card_valid = (sess->card->local_node != NULL);
+ spin_unlock_irq(&sess->card->lock);
+
+ if (!card_valid) {
+ fw_card_put(sess->card);
+ sess->card = NULL;
+ }
+ }
+
+ if (!card_valid || (sess->generation != sess->card->generation)) {
+ pr_info("Waiting for reconnect from node: %016llx\n",
+ sess->guid);
+
+ sess->node_id = -1;
+ sess->reconnect_expires = get_jiffies_64() +
+ ((sess->reconnect_hold + 1) * HZ);
+ }
+
+ spin_unlock_bh(&sess->lock);
+}
+
+static void session_reconnect_expired(struct sbp_session *sess)
+{
+ struct sbp_login_descriptor *login, *temp;
+ LIST_HEAD(login_list);
+
+ pr_info("Reconnect timer expired for node: %016llx\n", sess->guid);
+
+ spin_lock_bh(&sess->lock);
+ list_for_each_entry_safe(login, temp, &sess->login_list, link) {
+ login->sess = NULL;
+ list_del(&login->link);
+ list_add_tail(&login->link, &login_list);
+ }
+ spin_unlock_bh(&sess->lock);
+
+ list_for_each_entry_safe(login, temp, &login_list, link) {
+ list_del(&login->link);
+ sbp_login_release(login, false);
+ }
+
+ sbp_session_release(sess, false);
+}
+
+static void session_maintenance_work(struct work_struct *work)
+{
+ struct sbp_session *sess = container_of(work, struct sbp_session,
+ maint_work.work);
+
+ /* could be called while tearing down the session */
+ spin_lock_bh(&sess->lock);
+ if (list_empty(&sess->login_list)) {
+ spin_unlock_bh(&sess->lock);
+ return;
+ }
+ spin_unlock_bh(&sess->lock);
+
+ if (sess->node_id != -1) {
+ /* check for bus reset and make node_id invalid */
+ session_check_for_reset(sess);
+
+ schedule_delayed_work(&sess->maint_work,
+ SESSION_MAINTENANCE_INTERVAL);
+ } else if (!time_after64(get_jiffies_64(), sess->reconnect_expires)) {
+ /* still waiting for reconnect */
+ schedule_delayed_work(&sess->maint_work,
+ SESSION_MAINTENANCE_INTERVAL);
+ } else {
+ /* reconnect timeout has expired */
+ session_reconnect_expired(sess);
+ }
+}
+
+static int tgt_agent_rw_agent_state(struct fw_card *card, int tcode, void *data,
+ struct sbp_target_agent *agent)
+{
+ __be32 state;
+
+ switch (tcode) {
+ case TCODE_READ_QUADLET_REQUEST:
+ pr_debug("tgt_agent AGENT_STATE READ\n");
+
+ spin_lock_bh(&agent->lock);
+ state = cpu_to_be32(agent->state);
+ spin_unlock_bh(&agent->lock);
+ memcpy(data, &state, sizeof(state));
+
+ return RCODE_COMPLETE;
+
+ case TCODE_WRITE_QUADLET_REQUEST:
+ /* ignored */
+ return RCODE_COMPLETE;
+
+ default:
+ return RCODE_TYPE_ERROR;
+ }
+}
+
+static int tgt_agent_rw_agent_reset(struct fw_card *card, int tcode, void *data,
+ struct sbp_target_agent *agent)
+{
+ switch (tcode) {
+ case TCODE_WRITE_QUADLET_REQUEST:
+ pr_debug("tgt_agent AGENT_RESET\n");
+ spin_lock_bh(&agent->lock);
+ agent->state = AGENT_STATE_RESET;
+ spin_unlock_bh(&agent->lock);
+ return RCODE_COMPLETE;
+
+ default:
+ return RCODE_TYPE_ERROR;
+ }
+}
+
+static int tgt_agent_rw_orb_pointer(struct fw_card *card, int tcode, void *data,
+ struct sbp_target_agent *agent)
+{
+ struct sbp2_pointer *ptr = data;
+
+ switch (tcode) {
+ case TCODE_WRITE_BLOCK_REQUEST:
+ spin_lock_bh(&agent->lock);
+ if (agent->state != AGENT_STATE_SUSPENDED &&
+ agent->state != AGENT_STATE_RESET) {
+ spin_unlock_bh(&agent->lock);
+ pr_notice("Ignoring ORB_POINTER write while active.\n");
+ return RCODE_CONFLICT_ERROR;
+ }
+ agent->state = AGENT_STATE_ACTIVE;
+ spin_unlock_bh(&agent->lock);
+
+ agent->orb_pointer = sbp2_pointer_to_addr(ptr);
+ agent->doorbell = false;
+
+ pr_debug("tgt_agent ORB_POINTER write: 0x%llx\n",
+ agent->orb_pointer);
+
+ queue_work(system_unbound_wq, &agent->work);
+
+ return RCODE_COMPLETE;
+
+ case TCODE_READ_BLOCK_REQUEST:
+ pr_debug("tgt_agent ORB_POINTER READ\n");
+ spin_lock_bh(&agent->lock);
+ addr_to_sbp2_pointer(agent->orb_pointer, ptr);
+ spin_unlock_bh(&agent->lock);
+ return RCODE_COMPLETE;
+
+ default:
+ return RCODE_TYPE_ERROR;
+ }
+}
+
+static int tgt_agent_rw_doorbell(struct fw_card *card, int tcode, void *data,
+ struct sbp_target_agent *agent)
+{
+ switch (tcode) {
+ case TCODE_WRITE_QUADLET_REQUEST:
+ spin_lock_bh(&agent->lock);
+ if (agent->state != AGENT_STATE_SUSPENDED) {
+ spin_unlock_bh(&agent->lock);
+ pr_debug("Ignoring DOORBELL while active.\n");
+ return RCODE_CONFLICT_ERROR;
+ }
+ agent->state = AGENT_STATE_ACTIVE;
+ spin_unlock_bh(&agent->lock);
+
+ agent->doorbell = true;
+
+ pr_debug("tgt_agent DOORBELL\n");
+
+ queue_work(system_unbound_wq, &agent->work);
+
+ return RCODE_COMPLETE;
+
+ case TCODE_READ_QUADLET_REQUEST:
+ return RCODE_COMPLETE;
+
+ default:
+ return RCODE_TYPE_ERROR;
+ }
+}
+
+static int tgt_agent_rw_unsolicited_status_enable(struct fw_card *card,
+ int tcode, void *data, struct sbp_target_agent *agent)
+{
+ switch (tcode) {
+ case TCODE_WRITE_QUADLET_REQUEST:
+ pr_debug("tgt_agent UNSOLICITED_STATUS_ENABLE\n");
+ /* ignored as we don't send unsolicited status */
+ return RCODE_COMPLETE;
+
+ case TCODE_READ_QUADLET_REQUEST:
+ return RCODE_COMPLETE;
+
+ default:
+ return RCODE_TYPE_ERROR;
+ }
+}
+
+static void tgt_agent_rw(struct fw_card *card, struct fw_request *request,
+ int tcode, int destination, int source, int generation,
+ unsigned long long offset, void *data, size_t length,
+ void *callback_data)
+{
+ struct sbp_target_agent *agent = callback_data;
+ struct sbp_session *sess = agent->login->sess;
+ int sess_gen, sess_node, rcode;
+
+ spin_lock_bh(&sess->lock);
+ sess_gen = sess->generation;
+ sess_node = sess->node_id;
+ spin_unlock_bh(&sess->lock);
+
+ if (generation != sess_gen) {
+ pr_notice("ignoring request with wrong generation\n");
+ rcode = RCODE_TYPE_ERROR;
+ goto out;
+ }
+
+ if (source != sess_node) {
+ pr_notice("ignoring request from foreign node (%x != %x)\n",
+ source, sess_node);
+ rcode = RCODE_TYPE_ERROR;
+ goto out;
+ }
+
+ /* turn offset into the offset from the start of the block */
+ offset -= agent->handler.offset;
+
+ if (offset == 0x00 && length == 4) {
+ /* AGENT_STATE */
+ rcode = tgt_agent_rw_agent_state(card, tcode, data, agent);
+ } else if (offset == 0x04 && length == 4) {
+ /* AGENT_RESET */
+ rcode = tgt_agent_rw_agent_reset(card, tcode, data, agent);
+ } else if (offset == 0x08 && length == 8) {
+ /* ORB_POINTER */
+ rcode = tgt_agent_rw_orb_pointer(card, tcode, data, agent);
+ } else if (offset == 0x10 && length == 4) {
+ /* DOORBELL */
+ rcode = tgt_agent_rw_doorbell(card, tcode, data, agent);
+ } else if (offset == 0x14 && length == 4) {
+ /* UNSOLICITED_STATUS_ENABLE */
+ rcode = tgt_agent_rw_unsolicited_status_enable(card, tcode,
+ data, agent);
+ } else {
+ rcode = RCODE_ADDRESS_ERROR;
+ }
+
+out:
+ fw_send_response(card, request, rcode);
+}
+
+static void sbp_handle_command(struct sbp_target_request *);
+static int sbp_send_status(struct sbp_target_request *);
+static void sbp_free_request(struct sbp_target_request *);
+
+static void tgt_agent_process_work(struct work_struct *work)
+{
+ struct sbp_target_request *req =
+ container_of(work, struct sbp_target_request, work);
+
+ pr_debug("tgt_orb ptr:0x%llx next_ORB:0x%llx data_descriptor:0x%llx misc:0x%x\n",
+ req->orb_pointer,
+ sbp2_pointer_to_addr(&req->orb.next_orb),
+ sbp2_pointer_to_addr(&req->orb.data_descriptor),
+ be32_to_cpu(req->orb.misc));
+
+ if (req->orb_pointer >> 32)
+ pr_debug("ORB with high bits set\n");
+
+ switch (ORB_REQUEST_FORMAT(be32_to_cpu(req->orb.misc))) {
+ case 0:/* Format specified by this standard */
+ sbp_handle_command(req);
+ return;
+ case 1: /* Reserved for future standardization */
+ case 2: /* Vendor-dependent */
+ req->status.status |= cpu_to_be32(
+ STATUS_BLOCK_RESP(
+ STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_DEAD(0) |
+ STATUS_BLOCK_LEN(1) |
+ STATUS_BLOCK_SBP_STATUS(
+ SBP_STATUS_REQ_TYPE_NOTSUPP));
+ sbp_send_status(req);
+ sbp_free_request(req);
+ return;
+ case 3: /* Dummy ORB */
+ req->status.status |= cpu_to_be32(
+ STATUS_BLOCK_RESP(
+ STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_DEAD(0) |
+ STATUS_BLOCK_LEN(1) |
+ STATUS_BLOCK_SBP_STATUS(
+ SBP_STATUS_DUMMY_ORB_COMPLETE));
+ sbp_send_status(req);
+ sbp_free_request(req);
+ return;
+ default:
+ BUG();
+ }
+}
+
+/* used to double-check we haven't been issued an AGENT_RESET */
+static inline bool tgt_agent_check_active(struct sbp_target_agent *agent)
+{
+ bool active;
+
+ spin_lock_bh(&agent->lock);
+ active = (agent->state == AGENT_STATE_ACTIVE);
+ spin_unlock_bh(&agent->lock);
+
+ return active;
+}
+
+static void tgt_agent_fetch_work(struct work_struct *work)
+{
+ struct sbp_target_agent *agent =
+ container_of(work, struct sbp_target_agent, work);
+ struct sbp_session *sess = agent->login->sess;
+ struct sbp_target_request *req;
+ int ret;
+ bool doorbell = agent->doorbell;
+ u64 next_orb = agent->orb_pointer;
+
+ while (next_orb && tgt_agent_check_active(agent)) {
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req) {
+ spin_lock_bh(&agent->lock);
+ agent->state = AGENT_STATE_DEAD;
+ spin_unlock_bh(&agent->lock);
+ return;
+ }
+
+ req->login = agent->login;
+ req->orb_pointer = next_orb;
+
+ req->status.status = cpu_to_be32(STATUS_BLOCK_ORB_OFFSET_HIGH(
+ req->orb_pointer >> 32));
+ req->status.orb_low = cpu_to_be32(
+ req->orb_pointer & 0xfffffffc);
+
+ /* read in the ORB */
+ ret = sbp_run_transaction(sess->card, TCODE_READ_BLOCK_REQUEST,
+ sess->node_id, sess->generation, sess->speed,
+ req->orb_pointer, &req->orb, sizeof(req->orb));
+ if (ret != RCODE_COMPLETE) {
+ pr_debug("tgt_orb fetch failed: %x\n", ret);
+ req->status.status |= cpu_to_be32(
+ STATUS_BLOCK_SRC(
+ STATUS_SRC_ORB_FINISHED) |
+ STATUS_BLOCK_RESP(
+ STATUS_RESP_TRANSPORT_FAILURE) |
+ STATUS_BLOCK_DEAD(1) |
+ STATUS_BLOCK_LEN(1) |
+ STATUS_BLOCK_SBP_STATUS(
+ SBP_STATUS_UNSPECIFIED_ERROR));
+ spin_lock_bh(&agent->lock);
+ agent->state = AGENT_STATE_DEAD;
+ spin_unlock_bh(&agent->lock);
+
+ sbp_send_status(req);
+ sbp_free_request(req);
+ return;
+ }
+
+ /* check the next_ORB field */
+ if (be32_to_cpu(req->orb.next_orb.high) & 0x80000000) {
+ next_orb = 0;
+ req->status.status |= cpu_to_be32(STATUS_BLOCK_SRC(
+ STATUS_SRC_ORB_FINISHED));
+ } else {
+ next_orb = sbp2_pointer_to_addr(&req->orb.next_orb);
+ req->status.status |= cpu_to_be32(STATUS_BLOCK_SRC(
+ STATUS_SRC_ORB_CONTINUING));
+ }
+
+ if (tgt_agent_check_active(agent) && !doorbell) {
+ INIT_WORK(&req->work, tgt_agent_process_work);
+ queue_work(system_unbound_wq, &req->work);
+ } else {
+ /* don't process this request, just check next_ORB */
+ sbp_free_request(req);
+ }
+
+ spin_lock_bh(&agent->lock);
+ doorbell = agent->doorbell = false;
+
+ /* check if we should carry on processing */
+ if (next_orb)
+ agent->orb_pointer = next_orb;
+ else
+ agent->state = AGENT_STATE_SUSPENDED;
+
+ spin_unlock_bh(&agent->lock);
+ };
+}
+
+static struct sbp_target_agent *sbp_target_agent_register(
+ struct sbp_login_descriptor *login)
+{
+ struct sbp_target_agent *agent;
+ int ret;
+
+ agent = kmalloc(sizeof(*agent), GFP_KERNEL);
+ if (!agent)
+ return ERR_PTR(-ENOMEM);
+
+ spin_lock_init(&agent->lock);
+
+ agent->handler.length = 0x20;
+ agent->handler.address_callback = tgt_agent_rw;
+ agent->handler.callback_data = agent;
+
+ agent->login = login;
+ agent->state = AGENT_STATE_RESET;
+ INIT_WORK(&agent->work, tgt_agent_fetch_work);
+ agent->orb_pointer = 0;
+ agent->doorbell = false;
+
+ ret = fw_core_add_address_handler(&agent->handler,
+ &sbp_register_region);
+ if (ret < 0) {
+ kfree(agent);
+ return ERR_PTR(ret);
+ }
+
+ return agent;
+}
+
+static void sbp_target_agent_unregister(struct sbp_target_agent *agent)
+{
+ fw_core_remove_address_handler(&agent->handler);
+ cancel_work_sync(&agent->work);
+ kfree(agent);
+}
+
+/*
+ * Simple wrapper around fw_run_transaction that retries the transaction several
+ * times in case of failure, with an exponential backoff.
+ */
+static int sbp_run_transaction(struct fw_card *card, int tcode, int destination_id,
+ int generation, int speed, unsigned long long offset,
+ void *payload, size_t length)
+{
+ int attempt, ret, delay;
+
+ for (attempt = 1; attempt <= 5; attempt++) {
+ ret = fw_run_transaction(card, tcode, destination_id,
+ generation, speed, offset, payload, length);
+
+ switch (ret) {
+ case RCODE_COMPLETE:
+ case RCODE_TYPE_ERROR:
+ case RCODE_ADDRESS_ERROR:
+ case RCODE_GENERATION:
+ return ret;
+
+ default:
+ delay = 5 * attempt * attempt;
+ usleep_range(delay, delay * 2);
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Wrapper around sbp_run_transaction that gets the card, destination,
+ * generation and speed out of the request's session.
+ */
+static int sbp_run_request_transaction(struct sbp_target_request *req,
+ int tcode, unsigned long long offset, void *payload,
+ size_t length)
+{
+ struct sbp_login_descriptor *login = req->login;
+ struct sbp_session *sess = login->sess;
+ struct fw_card *card;
+ int node_id, generation, speed, ret;
+
+ spin_lock_bh(&sess->lock);
+ card = fw_card_get(sess->card);
+ node_id = sess->node_id;
+ generation = sess->generation;
+ speed = sess->speed;
+ spin_unlock_bh(&sess->lock);
+
+ ret = sbp_run_transaction(card, tcode, node_id, generation, speed,
+ offset, payload, length);
+
+ fw_card_put(card);
+
+ return ret;
+}
+
+static int sbp_fetch_command(struct sbp_target_request *req)
+{
+ int ret, cmd_len, copy_len;
+
+ cmd_len = scsi_command_size(req->orb.command_block);
+
+ req->cmd_buf = kmalloc(cmd_len, GFP_KERNEL);
+ if (!req->cmd_buf)
+ return -ENOMEM;
+
+ memcpy(req->cmd_buf, req->orb.command_block,
+ min_t(int, cmd_len, sizeof(req->orb.command_block)));
+
+ if (cmd_len > sizeof(req->orb.command_block)) {
+ pr_debug("sbp_fetch_command: filling in long command\n");
+ copy_len = cmd_len - sizeof(req->orb.command_block);
+
+ ret = sbp_run_request_transaction(req,
+ TCODE_READ_BLOCK_REQUEST,
+ req->orb_pointer + sizeof(req->orb),
+ req->cmd_buf + sizeof(req->orb.command_block),
+ copy_len);
+ if (ret != RCODE_COMPLETE)
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int sbp_fetch_page_table(struct sbp_target_request *req)
+{
+ int pg_tbl_sz, ret;
+ struct sbp_page_table_entry *pg_tbl;
+
+ if (!CMDBLK_ORB_PG_TBL_PRESENT(be32_to_cpu(req->orb.misc)))
+ return 0;
+
+ pg_tbl_sz = CMDBLK_ORB_DATA_SIZE(be32_to_cpu(req->orb.misc)) *
+ sizeof(struct sbp_page_table_entry);
+
+ pg_tbl = kmalloc(pg_tbl_sz, GFP_KERNEL);
+ if (!pg_tbl)
+ return -ENOMEM;
+
+ ret = sbp_run_request_transaction(req, TCODE_READ_BLOCK_REQUEST,
+ sbp2_pointer_to_addr(&req->orb.data_descriptor),
+ pg_tbl, pg_tbl_sz);
+ if (ret != RCODE_COMPLETE) {
+ kfree(pg_tbl);
+ return -EIO;
+ }
+
+ req->pg_tbl = pg_tbl;
+ return 0;
+}
+
+static void sbp_calc_data_length_direction(struct sbp_target_request *req,
+ u32 *data_len, enum dma_data_direction *data_dir)
+{
+ int data_size, direction, idx;
+
+ data_size = CMDBLK_ORB_DATA_SIZE(be32_to_cpu(req->orb.misc));
+ direction = CMDBLK_ORB_DIRECTION(be32_to_cpu(req->orb.misc));
+
+ if (!data_size) {
+ *data_len = 0;
+ *data_dir = DMA_NONE;
+ return;
+ }
+
+ *data_dir = direction ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+ if (req->pg_tbl) {
+ *data_len = 0;
+ for (idx = 0; idx < data_size; idx++) {
+ *data_len += be16_to_cpu(
+ req->pg_tbl[idx].segment_length);
+ }
+ } else {
+ *data_len = data_size;
+ }
+}
+
+static void sbp_handle_command(struct sbp_target_request *req)
+{
+ struct sbp_login_descriptor *login = req->login;
+ struct sbp_session *sess = login->sess;
+ int ret, unpacked_lun;
+ u32 data_length;
+ enum dma_data_direction data_dir;
+
+ ret = sbp_fetch_command(req);
+ if (ret) {
+ pr_debug("sbp_handle_command: fetch command failed: %d\n", ret);
+ req->status.status |= cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_TRANSPORT_FAILURE) |
+ STATUS_BLOCK_DEAD(0) |
+ STATUS_BLOCK_LEN(1) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
+ sbp_send_status(req);
+ sbp_free_request(req);
+ return;
+ }
+
+ ret = sbp_fetch_page_table(req);
+ if (ret) {
+ pr_debug("sbp_handle_command: fetch page table failed: %d\n",
+ ret);
+ req->status.status |= cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_TRANSPORT_FAILURE) |
+ STATUS_BLOCK_DEAD(0) |
+ STATUS_BLOCK_LEN(1) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
+ sbp_send_status(req);
+ sbp_free_request(req);
+ return;
+ }
+
+ unpacked_lun = req->login->lun->unpacked_lun;
+ sbp_calc_data_length_direction(req, &data_length, &data_dir);
+
+ pr_debug("sbp_handle_command ORB:0x%llx unpacked_lun:%d data_len:%d data_dir:%d\n",
+ req->orb_pointer, unpacked_lun, data_length, data_dir);
+
+ target_submit_cmd(&req->se_cmd, sess->se_sess, req->cmd_buf,
+ req->sense_buf, unpacked_lun, data_length,
+ MSG_SIMPLE_TAG, data_dir, 0);
+}
+
+/*
+ * DMA_TO_DEVICE = read from initiator (SCSI WRITE)
+ * DMA_FROM_DEVICE = write to initiator (SCSI READ)
+ */
+static int sbp_rw_data(struct sbp_target_request *req)
+{
+ struct sbp_session *sess = req->login->sess;
+ int tcode, sg_miter_flags, max_payload, pg_size, speed, node_id,
+ generation, num_pte, length, tfr_length,
+ rcode = RCODE_COMPLETE;
+ struct sbp_page_table_entry *pte;
+ unsigned long long offset;
+ struct fw_card *card;
+ struct sg_mapping_iter iter;
+
+ if (req->se_cmd.data_direction == DMA_FROM_DEVICE) {
+ tcode = TCODE_WRITE_BLOCK_REQUEST;
+ sg_miter_flags = SG_MITER_FROM_SG;
+ } else {
+ tcode = TCODE_READ_BLOCK_REQUEST;
+ sg_miter_flags = SG_MITER_TO_SG;
+ }
+
+ max_payload = 4 << CMDBLK_ORB_MAX_PAYLOAD(be32_to_cpu(req->orb.misc));
+ speed = CMDBLK_ORB_SPEED(be32_to_cpu(req->orb.misc));
+
+ pg_size = CMDBLK_ORB_PG_SIZE(be32_to_cpu(req->orb.misc));
+ if (pg_size) {
+ pr_err("sbp_run_transaction: page size ignored\n");
+ pg_size = 0x100 << pg_size;
+ }
+
+ spin_lock_bh(&sess->lock);
+ card = fw_card_get(sess->card);
+ node_id = sess->node_id;
+ generation = sess->generation;
+ spin_unlock_bh(&sess->lock);
+
+ if (req->pg_tbl) {
+ pte = req->pg_tbl;
+ num_pte = CMDBLK_ORB_DATA_SIZE(be32_to_cpu(req->orb.misc));
+
+ offset = 0;
+ length = 0;
+ } else {
+ pte = NULL;
+ num_pte = 0;
+
+ offset = sbp2_pointer_to_addr(&req->orb.data_descriptor);
+ length = req->se_cmd.data_length;
+ }
+
+ sg_miter_start(&iter, req->se_cmd.t_data_sg, req->se_cmd.t_data_nents,
+ sg_miter_flags);
+
+ while (length || num_pte) {
+ if (!length) {
+ offset = (u64)be16_to_cpu(pte->segment_base_hi) << 32 |
+ be32_to_cpu(pte->segment_base_lo);
+ length = be16_to_cpu(pte->segment_length);
+
+ pte++;
+ num_pte--;
+ }
+
+ sg_miter_next(&iter);
+
+ tfr_length = min3(length, max_payload, (int)iter.length);
+
+ /* FIXME: take page_size into account */
+
+ rcode = sbp_run_transaction(card, tcode, node_id,
+ generation, speed,
+ offset, iter.addr, tfr_length);
+
+ if (rcode != RCODE_COMPLETE)
+ break;
+
+ length -= tfr_length;
+ offset += tfr_length;
+ iter.consumed = tfr_length;
+ }
+
+ sg_miter_stop(&iter);
+ fw_card_put(card);
+
+ if (rcode == RCODE_COMPLETE) {
+ WARN_ON(length != 0);
+ return 0;
+ } else {
+ return -EIO;
+ }
+}
+
+static int sbp_send_status(struct sbp_target_request *req)
+{
+ int ret, length;
+ struct sbp_login_descriptor *login = req->login;
+
+ length = (((be32_to_cpu(req->status.status) >> 24) & 0x07) + 1) * 4;
+
+ ret = sbp_run_request_transaction(req, TCODE_WRITE_BLOCK_REQUEST,
+ login->status_fifo_addr, &req->status, length);
+ if (ret != RCODE_COMPLETE) {
+ pr_debug("sbp_send_status: write failed: 0x%x\n", ret);
+ return -EIO;
+ }
+
+ pr_debug("sbp_send_status: status write complete for ORB: 0x%llx\n",
+ req->orb_pointer);
+
+ return 0;
+}
+
+static void sbp_sense_mangle(struct sbp_target_request *req)
+{
+ struct se_cmd *se_cmd = &req->se_cmd;
+ u8 *sense = req->sense_buf;
+ u8 *status = req->status.data;
+
+ WARN_ON(se_cmd->scsi_sense_length < 18);
+
+ switch (sense[0] & 0x7f) { /* sfmt */
+ case 0x70: /* current, fixed */
+ status[0] = 0 << 6;
+ break;
+ case 0x71: /* deferred, fixed */
+ status[0] = 1 << 6;
+ break;
+ case 0x72: /* current, descriptor */
+ case 0x73: /* deferred, descriptor */
+ default:
+ /*
+ * TODO: SBP-3 specifies what we should do with descriptor
+ * format sense data
+ */
+ pr_err("sbp_send_sense: unknown sense format: 0x%x\n",
+ sense[0]);
+ req->status.status |= cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_DEAD(0) |
+ STATUS_BLOCK_LEN(1) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQUEST_ABORTED));
+ return;
+ }
+
+ status[0] |= se_cmd->scsi_status & 0x3f;/* status */
+ status[1] =
+ (sense[0] & 0x80) | /* valid */
+ ((sense[2] & 0xe0) >> 1) | /* mark, eom, ili */
+ (sense[2] & 0x0f); /* sense_key */
+ status[2] = se_cmd->scsi_asc; /* sense_code */
+ status[3] = se_cmd->scsi_ascq; /* sense_qualifier */
+
+ /* information */
+ status[4] = sense[3];
+ status[5] = sense[4];
+ status[6] = sense[5];
+ status[7] = sense[6];
+
+ /* CDB-dependent */
+ status[8] = sense[8];
+ status[9] = sense[9];
+ status[10] = sense[10];
+ status[11] = sense[11];
+
+ /* fru */
+ status[12] = sense[14];
+
+ /* sense_key-dependent */
+ status[13] = sense[15];
+ status[14] = sense[16];
+ status[15] = sense[17];
+
+ req->status.status |= cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_DEAD(0) |
+ STATUS_BLOCK_LEN(5) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_OK));
+}
+
+static int sbp_send_sense(struct sbp_target_request *req)
+{
+ struct se_cmd *se_cmd = &req->se_cmd;
+
+ if (se_cmd->scsi_sense_length) {
+ sbp_sense_mangle(req);
+ } else {
+ req->status.status |= cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_DEAD(0) |
+ STATUS_BLOCK_LEN(1) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_OK));
+ }
+
+ return sbp_send_status(req);
+}
+
+static void sbp_free_request(struct sbp_target_request *req)
+{
+ kfree(req->pg_tbl);
+ kfree(req->cmd_buf);
+ kfree(req);
+}
+
+static void sbp_mgt_agent_process(struct work_struct *work)
+{
+ struct sbp_management_agent *agent =
+ container_of(work, struct sbp_management_agent, work);
+ struct sbp_management_request *req = agent->request;
+ int ret;
+ int status_data_len = 0;
+
+ /* fetch the ORB from the initiator */
+ ret = sbp_run_transaction(req->card, TCODE_READ_BLOCK_REQUEST,
+ req->node_addr, req->generation, req->speed,
+ agent->orb_offset, &req->orb, sizeof(req->orb));
+ if (ret != RCODE_COMPLETE) {
+ pr_debug("mgt_orb fetch failed: %x\n", ret);
+ goto out;
+ }
+
+ pr_debug("mgt_orb ptr1:0x%llx ptr2:0x%llx misc:0x%x len:0x%x status_fifo:0x%llx\n",
+ sbp2_pointer_to_addr(&req->orb.ptr1),
+ sbp2_pointer_to_addr(&req->orb.ptr2),
+ be32_to_cpu(req->orb.misc), be32_to_cpu(req->orb.length),
+ sbp2_pointer_to_addr(&req->orb.status_fifo));
+
+ if (!ORB_NOTIFY(be32_to_cpu(req->orb.misc)) ||
+ ORB_REQUEST_FORMAT(be32_to_cpu(req->orb.misc)) != 0) {
+ pr_err("mgt_orb bad request\n");
+ goto out;
+ }
+
+ switch (MANAGEMENT_ORB_FUNCTION(be32_to_cpu(req->orb.misc))) {
+ case MANAGEMENT_ORB_FUNCTION_LOGIN:
+ sbp_management_request_login(agent, req, &status_data_len);
+ break;
+
+ case MANAGEMENT_ORB_FUNCTION_QUERY_LOGINS:
+ sbp_management_request_query_logins(agent, req,
+ &status_data_len);
+ break;
+
+ case MANAGEMENT_ORB_FUNCTION_RECONNECT:
+ sbp_management_request_reconnect(agent, req, &status_data_len);
+ break;
+
+ case MANAGEMENT_ORB_FUNCTION_SET_PASSWORD:
+ pr_notice("SET PASSWORD not implemented\n");
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQ_TYPE_NOTSUPP));
+
+ break;
+
+ case MANAGEMENT_ORB_FUNCTION_LOGOUT:
+ sbp_management_request_logout(agent, req, &status_data_len);
+ break;
+
+ case MANAGEMENT_ORB_FUNCTION_ABORT_TASK:
+ pr_notice("ABORT TASK not implemented\n");
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQ_TYPE_NOTSUPP));
+
+ break;
+
+ case MANAGEMENT_ORB_FUNCTION_ABORT_TASK_SET:
+ pr_notice("ABORT TASK SET not implemented\n");
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQ_TYPE_NOTSUPP));
+
+ break;
+
+ case MANAGEMENT_ORB_FUNCTION_LOGICAL_UNIT_RESET:
+ pr_notice("LOGICAL UNIT RESET not implemented\n");
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQ_TYPE_NOTSUPP));
+
+ break;
+
+ case MANAGEMENT_ORB_FUNCTION_TARGET_RESET:
+ pr_notice("TARGET RESET not implemented\n");
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQ_TYPE_NOTSUPP));
+
+ break;
+
+ default:
+ pr_notice("unknown management function 0x%x\n",
+ MANAGEMENT_ORB_FUNCTION(be32_to_cpu(req->orb.misc)));
+
+ req->status.status = cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQ_TYPE_NOTSUPP));
+
+ break;
+ }
+
+ req->status.status |= cpu_to_be32(
+ STATUS_BLOCK_SRC(1) | /* Response to ORB, next_ORB absent */
+ STATUS_BLOCK_LEN(DIV_ROUND_UP(status_data_len, 4) + 1) |
+ STATUS_BLOCK_ORB_OFFSET_HIGH(agent->orb_offset >> 32));
+ req->status.orb_low = cpu_to_be32(agent->orb_offset);
+
+ /* write the status block back to the initiator */
+ ret = sbp_run_transaction(req->card, TCODE_WRITE_BLOCK_REQUEST,
+ req->node_addr, req->generation, req->speed,
+ sbp2_pointer_to_addr(&req->orb.status_fifo),
+ &req->status, 8 + status_data_len);
+ if (ret != RCODE_COMPLETE) {
+ pr_debug("mgt_orb status write failed: %x\n", ret);
+ goto out;
+ }
+
+out:
+ fw_card_put(req->card);
+ kfree(req);
+
+ spin_lock_bh(&agent->lock);
+ agent->state = MANAGEMENT_AGENT_STATE_IDLE;
+ spin_unlock_bh(&agent->lock);
+}
+
+static void sbp_mgt_agent_rw(struct fw_card *card,
+ struct fw_request *request, int tcode, int destination, int source,
+ int generation, unsigned long long offset, void *data, size_t length,
+ void *callback_data)
+{
+ struct sbp_management_agent *agent = callback_data;
+ struct sbp2_pointer *ptr = data;
+ int rcode = RCODE_ADDRESS_ERROR;
+
+ if (!agent->tport->enable)
+ goto out;
+
+ if ((offset != agent->handler.offset) || (length != 8))
+ goto out;
+
+ if (tcode == TCODE_WRITE_BLOCK_REQUEST) {
+ struct sbp_management_request *req;
+ int prev_state;
+
+ spin_lock_bh(&agent->lock);
+ prev_state = agent->state;
+ agent->state = MANAGEMENT_AGENT_STATE_BUSY;
+ spin_unlock_bh(&agent->lock);
+
+ if (prev_state == MANAGEMENT_AGENT_STATE_BUSY) {
+ pr_notice("ignoring management request while busy\n");
+ rcode = RCODE_CONFLICT_ERROR;
+ goto out;
+ }
+
+ req = kzalloc(sizeof(*req), GFP_ATOMIC);
+ if (!req) {
+ rcode = RCODE_CONFLICT_ERROR;
+ goto out;
+ }
+
+ req->card = fw_card_get(card);
+ req->generation = generation;
+ req->node_addr = source;
+ req->speed = fw_get_request_speed(request);
+
+ agent->orb_offset = sbp2_pointer_to_addr(ptr);
+ agent->request = req;
+
+ queue_work(system_unbound_wq, &agent->work);
+ rcode = RCODE_COMPLETE;
+ } else if (tcode == TCODE_READ_BLOCK_REQUEST) {
+ addr_to_sbp2_pointer(agent->orb_offset, ptr);
+ rcode = RCODE_COMPLETE;
+ } else {
+ rcode = RCODE_TYPE_ERROR;
+ }
+
+out:
+ fw_send_response(card, request, rcode);
+}
+
+static struct sbp_management_agent *sbp_management_agent_register(
+ struct sbp_tport *tport)
+{
+ int ret;
+ struct sbp_management_agent *agent;
+
+ agent = kmalloc(sizeof(*agent), GFP_KERNEL);
+ if (!agent)
+ return ERR_PTR(-ENOMEM);
+
+ spin_lock_init(&agent->lock);
+ agent->tport = tport;
+ agent->handler.length = 0x08;
+ agent->handler.address_callback = sbp_mgt_agent_rw;
+ agent->handler.callback_data = agent;
+ agent->state = MANAGEMENT_AGENT_STATE_IDLE;
+ INIT_WORK(&agent->work, sbp_mgt_agent_process);
+ agent->orb_offset = 0;
+ agent->request = NULL;
+
+ ret = fw_core_add_address_handler(&agent->handler,
+ &sbp_register_region);
+ if (ret < 0) {
+ kfree(agent);
+ return ERR_PTR(ret);
+ }
+
+ return agent;
+}
+
+static void sbp_management_agent_unregister(struct sbp_management_agent *agent)
+{
+ fw_core_remove_address_handler(&agent->handler);
+ cancel_work_sync(&agent->work);
+ kfree(agent);
+}
+
+static int sbp_check_true(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static int sbp_check_false(struct se_portal_group *se_tpg)
+{
+ return 0;
+}
+
+static char *sbp_get_fabric_name(void)
+{
+ return "sbp";
+}
+
+static char *sbp_get_fabric_wwn(struct se_portal_group *se_tpg)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ struct sbp_tport *tport = tpg->tport;
+
+ return &tport->tport_name[0];
+}
+
+static u16 sbp_get_tag(struct se_portal_group *se_tpg)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ return tpg->tport_tpgt;
+}
+
+static u32 sbp_get_default_depth(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static struct se_node_acl *sbp_alloc_fabric_acl(struct se_portal_group *se_tpg)
+{
+ struct sbp_nacl *nacl;
+
+ nacl = kzalloc(sizeof(struct sbp_nacl), GFP_KERNEL);
+ if (!nacl) {
+ pr_err("Unable to alocate struct sbp_nacl\n");
+ return NULL;
+ }
+
+ return &nacl->se_node_acl;
+}
+
+static void sbp_release_fabric_acl(
+ struct se_portal_group *se_tpg,
+ struct se_node_acl *se_nacl)
+{
+ struct sbp_nacl *nacl =
+ container_of(se_nacl, struct sbp_nacl, se_node_acl);
+ kfree(nacl);
+}
+
+static u32 sbp_tpg_get_inst_index(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static void sbp_release_cmd(struct se_cmd *se_cmd)
+{
+ struct sbp_target_request *req = container_of(se_cmd,
+ struct sbp_target_request, se_cmd);
+
+ sbp_free_request(req);
+}
+
+static int sbp_shutdown_session(struct se_session *se_sess)
+{
+ return 0;
+}
+
+static void sbp_close_session(struct se_session *se_sess)
+{
+ return;
+}
+
+static u32 sbp_sess_get_index(struct se_session *se_sess)
+{
+ return 0;
+}
+
+static int sbp_write_pending(struct se_cmd *se_cmd)
+{
+ struct sbp_target_request *req = container_of(se_cmd,
+ struct sbp_target_request, se_cmd);
+ int ret;
+
+ ret = sbp_rw_data(req);
+ if (ret) {
+ req->status.status |= cpu_to_be32(
+ STATUS_BLOCK_RESP(
+ STATUS_RESP_TRANSPORT_FAILURE) |
+ STATUS_BLOCK_DEAD(0) |
+ STATUS_BLOCK_LEN(1) |
+ STATUS_BLOCK_SBP_STATUS(
+ SBP_STATUS_UNSPECIFIED_ERROR));
+ sbp_send_status(req);
+ return ret;
+ }
+
+ transport_generic_process_write(se_cmd);
+
+ return 0;
+}
+
+static int sbp_write_pending_status(struct se_cmd *se_cmd)
+{
+ return 0;
+}
+
+static void sbp_set_default_node_attrs(struct se_node_acl *nacl)
+{
+ return;
+}
+
+static u32 sbp_get_task_tag(struct se_cmd *se_cmd)
+{
+ struct sbp_target_request *req = container_of(se_cmd,
+ struct sbp_target_request, se_cmd);
+
+ /* only used for printk until we do TMRs */
+ return (u32)req->orb_pointer;
+}
+
+static int sbp_get_cmd_state(struct se_cmd *se_cmd)
+{
+ return 0;
+}
+
+static int sbp_queue_data_in(struct se_cmd *se_cmd)
+{
+ struct sbp_target_request *req = container_of(se_cmd,
+ struct sbp_target_request, se_cmd);
+ int ret;
+
+ ret = sbp_rw_data(req);
+ if (ret) {
+ req->status.status |= cpu_to_be32(
+ STATUS_BLOCK_RESP(STATUS_RESP_TRANSPORT_FAILURE) |
+ STATUS_BLOCK_DEAD(0) |
+ STATUS_BLOCK_LEN(1) |
+ STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
+ sbp_send_status(req);
+ return ret;
+ }
+
+ return sbp_send_sense(req);
+}
+
+/*
+ * Called after command (no data transfer) or after the write (to device)
+ * operation is completed
+ */
+static int sbp_queue_status(struct se_cmd *se_cmd)
+{
+ struct sbp_target_request *req = container_of(se_cmd,
+ struct sbp_target_request, se_cmd);
+
+ return sbp_send_sense(req);
+}
+
+static int sbp_queue_tm_rsp(struct se_cmd *se_cmd)
+{
+ return 0;
+}
+
+static u16 sbp_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_length)
+{
+ return 0;
+}
+
+static u16 sbp_get_fabric_sense_len(void)
+{
+ return 0;
+}
+
+static int sbp_check_stop_free(struct se_cmd *se_cmd)
+{
+ struct sbp_target_request *req = container_of(se_cmd,
+ struct sbp_target_request, se_cmd);
+
+ transport_generic_free_cmd(&req->se_cmd, 0);
+ return 1;
+}
+
+/*
+ * Handlers for Serial Bus Protocol 2/3 (SBP-2 / SBP-3)
+ */
+static u8 sbp_get_fabric_proto_ident(struct se_portal_group *se_tpg)
+{
+ /*
+ * Return a IEEE 1394 SCSI Protocol identifier for loopback operations
+ * This is defined in section 7.5.1 Table 362 in spc4r17
+ */
+ return SCSI_PROTOCOL_SBP;
+}
+
+static u32 sbp_get_pr_transport_id(
+ struct se_portal_group *se_tpg,
+ struct se_node_acl *se_nacl,
+ struct t10_pr_registration *pr_reg,
+ int *format_code,
+ unsigned char *buf)
+{
+ int ret;
+
+ /*
+ * Set PROTOCOL IDENTIFIER to 3h for SBP
+ */
+ buf[0] = SCSI_PROTOCOL_SBP;
+ /*
+ * From spc4r17, 7.5.4.4 TransportID for initiator ports using SCSI
+ * over IEEE 1394
+ */
+ ret = hex2bin(&buf[8], se_nacl->initiatorname, 8);
+ if (ret < 0)
+ pr_debug("sbp transport_id: invalid hex string\n");
+
+ /*
+ * The IEEE 1394 Transport ID is a hardcoded 24-byte length
+ */
+ return 24;
+}
+
+static u32 sbp_get_pr_transport_id_len(
+ struct se_portal_group *se_tpg,
+ struct se_node_acl *se_nacl,
+ struct t10_pr_registration *pr_reg,
+ int *format_code)
+{
+ *format_code = 0;
+ /*
+ * From spc4r17, 7.5.4.4 TransportID for initiator ports using SCSI
+ * over IEEE 1394
+ *
+ * The SBP Transport ID is a hardcoded 24-byte length
+ */
+ return 24;
+}
+
+/*
+ * Used for handling SCSI fabric dependent TransportIDs in SPC-3 and above
+ * Persistent Reservation SPEC_I_PT=1 and PROUT REGISTER_AND_MOVE operations.
+ */
+static char *sbp_parse_pr_out_transport_id(
+ struct se_portal_group *se_tpg,
+ const char *buf,
+ u32 *out_tid_len,
+ char **port_nexus_ptr)
+{
+ /*
+ * Assume the FORMAT CODE 00b from spc4r17, 7.5.4.4 TransportID
+ * for initiator ports using SCSI over SBP Serial SCSI Protocol
+ *
+ * The TransportID for a IEEE 1394 Initiator Port is of fixed size of
+ * 24 bytes, and IEEE 1394 does not contain a I_T nexus identifier,
+ * so we return the **port_nexus_ptr set to NULL.
+ */
+ *port_nexus_ptr = NULL;
+ *out_tid_len = 24;
+
+ return (char *)&buf[8];
+}
+
+static int sbp_count_se_tpg_luns(struct se_portal_group *tpg)
+{
+ int i, count = 0;
+
+ spin_lock(&tpg->tpg_lun_lock);
+ for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
+ struct se_lun *se_lun = tpg->tpg_lun_list[i];
+
+ if (se_lun->lun_status == TRANSPORT_LUN_STATUS_FREE)
+ continue;
+
+ count++;
+ }
+ spin_unlock(&tpg->tpg_lun_lock);
+
+ return count;
+}
+
+static int sbp_update_unit_directory(struct sbp_tport *tport)
+{
+ int num_luns, num_entries, idx = 0, mgt_agt_addr, ret, i;
+ u32 *data;
+
+ if (tport->unit_directory.data) {
+ fw_core_remove_descriptor(&tport->unit_directory);
+ kfree(tport->unit_directory.data);
+ tport->unit_directory.data = NULL;
+ }
+
+ if (!tport->enable || !tport->tpg)
+ return 0;
+
+ num_luns = sbp_count_se_tpg_luns(&tport->tpg->se_tpg);
+
+ /*
+ * Number of entries in the final unit directory:
+ * - all of those in the template
+ * - management_agent
+ * - unit_characteristics
+ * - reconnect_timeout
+ * - unit unique ID
+ * - one for each LUN
+ *
+ * MUST NOT include leaf or sub-directory entries
+ */
+ num_entries = ARRAY_SIZE(sbp_unit_directory_template) + 4 + num_luns;
+
+ if (tport->directory_id != -1)
+ num_entries++;
+
+ /* allocate num_entries + 4 for the header and unique ID leaf */
+ data = kcalloc((num_entries + 4), sizeof(u32), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /* directory_length */
+ data[idx++] = num_entries << 16;
+
+ /* directory_id */
+ if (tport->directory_id != -1)
+ data[idx++] = (CSR_DIRECTORY_ID << 24) | tport->directory_id;
+
+ /* unit directory template */
+ memcpy(&data[idx], sbp_unit_directory_template,
+ sizeof(sbp_unit_directory_template));
+ idx += ARRAY_SIZE(sbp_unit_directory_template);
+
+ /* management_agent */
+ mgt_agt_addr = (tport->mgt_agt->handler.offset - CSR_REGISTER_BASE) / 4;
+ data[idx++] = 0x54000000 | (mgt_agt_addr & 0x00ffffff);
+
+ /* unit_characteristics */
+ data[idx++] = 0x3a000000 |
+ (((tport->mgt_orb_timeout * 2) << 8) & 0xff00) |
+ SBP_ORB_FETCH_SIZE;
+
+ /* reconnect_timeout */
+ data[idx++] = 0x3d000000 | (tport->max_reconnect_timeout & 0xffff);
+
+ /* unit unique ID (leaf is just after LUNs) */
+ data[idx++] = 0x8d000000 | (num_luns + 1);
+
+ spin_lock(&tport->tpg->se_tpg.tpg_lun_lock);
+ for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
+ struct se_lun *se_lun = tport->tpg->se_tpg.tpg_lun_list[i];
+ struct se_device *dev;
+ int type;
+
+ if (se_lun->lun_status == TRANSPORT_LUN_STATUS_FREE)
+ continue;
+
+ spin_unlock(&tport->tpg->se_tpg.tpg_lun_lock);
+
+ dev = se_lun->lun_se_dev;
+ type = dev->transport->get_device_type(dev);
+
+ /* logical_unit_number */
+ data[idx++] = 0x14000000 |
+ ((type << 16) & 0x1f0000) |
+ (se_lun->unpacked_lun & 0xffff);
+
+ spin_lock(&tport->tpg->se_tpg.tpg_lun_lock);
+ }
+ spin_unlock(&tport->tpg->se_tpg.tpg_lun_lock);
+
+ /* unit unique ID leaf */
+ data[idx++] = 2 << 16;
+ data[idx++] = tport->guid >> 32;
+ data[idx++] = tport->guid;
+
+ tport->unit_directory.length = idx;
+ tport->unit_directory.key = (CSR_DIRECTORY | CSR_UNIT) << 24;
+ tport->unit_directory.data = data;
+
+ ret = fw_core_add_descriptor(&tport->unit_directory);
+ if (ret < 0) {
+ kfree(tport->unit_directory.data);
+ tport->unit_directory.data = NULL;
+ }
+
+ return ret;
+}
+
+static ssize_t sbp_parse_wwn(const char *name, u64 *wwn, int strict)
+{
+ const char *cp;
+ char c, nibble;
+ int pos = 0, err;
+
+ *wwn = 0;
+ for (cp = name; cp < &name[SBP_NAMELEN - 1]; cp++) {
+ c = *cp;
+ if (c == '\n' && cp[1] == '\0')
+ continue;
+ if (c == '\0') {
+ err = 2;
+ if (pos != 16)
+ goto fail;
+ return cp - name;
+ }
+ err = 3;
+ if (isdigit(c))
+ nibble = c - '0';
+ else if (isxdigit(c) && (islower(c) || !strict))
+ nibble = tolower(c) - 'a' + 10;
+ else
+ goto fail;
+ *wwn = (*wwn << 4) | nibble;
+ pos++;
+ }
+ err = 4;
+fail:
+ printk(KERN_INFO "err %u len %zu pos %u\n",
+ err, cp - name, pos);
+ return -1;
+}
+
+static ssize_t sbp_format_wwn(char *buf, size_t len, u64 wwn)
+{
+ return snprintf(buf, len, "%016llx", wwn);
+}
+
+static struct se_node_acl *sbp_make_nodeacl(
+ struct se_portal_group *se_tpg,
+ struct config_group *group,
+ const char *name)
+{
+ struct se_node_acl *se_nacl, *se_nacl_new;
+ struct sbp_nacl *nacl;
+ u64 guid = 0;
+ u32 nexus_depth = 1;
+
+ if (sbp_parse_wwn(name, &guid, 1) < 0)
+ return ERR_PTR(-EINVAL);
+
+ se_nacl_new = sbp_alloc_fabric_acl(se_tpg);
+ if (!se_nacl_new)
+ return ERR_PTR(-ENOMEM);
+
+ /*
+ * se_nacl_new may be released by core_tpg_add_initiator_node_acl()
+ * when converting a NodeACL from demo mode -> explict
+ */
+ se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new,
+ name, nexus_depth);
+ if (IS_ERR(se_nacl)) {
+ sbp_release_fabric_acl(se_tpg, se_nacl_new);
+ return se_nacl;
+ }
+
+ nacl = container_of(se_nacl, struct sbp_nacl, se_node_acl);
+ nacl->guid = guid;
+ sbp_format_wwn(nacl->iport_name, SBP_NAMELEN, guid);
+
+ return se_nacl;
+}
+
+static void sbp_drop_nodeacl(struct se_node_acl *se_acl)
+{
+ struct sbp_nacl *nacl =
+ container_of(se_acl, struct sbp_nacl, se_node_acl);
+
+ core_tpg_del_initiator_node_acl(se_acl->se_tpg, se_acl, 1);
+ kfree(nacl);
+}
+
+static int sbp_post_link_lun(
+ struct se_portal_group *se_tpg,
+ struct se_lun *se_lun)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+
+ return sbp_update_unit_directory(tpg->tport);
+}
+
+static void sbp_pre_unlink_lun(
+ struct se_portal_group *se_tpg,
+ struct se_lun *se_lun)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ struct sbp_tport *tport = tpg->tport;
+ int ret;
+
+ if (sbp_count_se_tpg_luns(&tpg->se_tpg) == 0)
+ tport->enable = 0;
+
+ ret = sbp_update_unit_directory(tport);
+ if (ret < 0)
+ pr_err("unlink LUN: failed to update unit directory\n");
+}
+
+static struct se_portal_group *sbp_make_tpg(
+ struct se_wwn *wwn,
+ struct config_group *group,
+ const char *name)
+{
+ struct sbp_tport *tport =
+ container_of(wwn, struct sbp_tport, tport_wwn);
+
+ struct sbp_tpg *tpg;
+ unsigned long tpgt;
+ int ret;
+
+ if (strstr(name, "tpgt_") != name)
+ return ERR_PTR(-EINVAL);
+ if (kstrtoul(name + 5, 10, &tpgt) || tpgt > UINT_MAX)
+ return ERR_PTR(-EINVAL);
+
+ if (tport->tpg) {
+ pr_err("Only one TPG per Unit is possible.\n");
+ return ERR_PTR(-EBUSY);
+ }
+
+ tpg = kzalloc(sizeof(*tpg), GFP_KERNEL);
+ if (!tpg) {
+ pr_err("Unable to allocate struct sbp_tpg\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ tpg->tport = tport;
+ tpg->tport_tpgt = tpgt;
+ tport->tpg = tpg;
+
+ /* default attribute values */
+ tport->enable = 0;
+ tport->directory_id = -1;
+ tport->mgt_orb_timeout = 15;
+ tport->max_reconnect_timeout = 5;
+ tport->max_logins_per_lun = 1;
+
+ tport->mgt_agt = sbp_management_agent_register(tport);
+ if (IS_ERR(tport->mgt_agt)) {
+ ret = PTR_ERR(tport->mgt_agt);
+ kfree(tpg);
+ return ERR_PTR(ret);
+ }
+
+ ret = core_tpg_register(&sbp_fabric_configfs->tf_ops, wwn,
+ &tpg->se_tpg, (void *)tpg,
+ TRANSPORT_TPG_TYPE_NORMAL);
+ if (ret < 0) {
+ sbp_management_agent_unregister(tport->mgt_agt);
+ kfree(tpg);
+ return ERR_PTR(ret);
+ }
+
+ return &tpg->se_tpg;
+}
+
+static void sbp_drop_tpg(struct se_portal_group *se_tpg)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ struct sbp_tport *tport = tpg->tport;
+
+ core_tpg_deregister(se_tpg);
+ sbp_management_agent_unregister(tport->mgt_agt);
+ tport->tpg = NULL;
+ kfree(tpg);
+}
+
+static struct se_wwn *sbp_make_tport(
+ struct target_fabric_configfs *tf,
+ struct config_group *group,
+ const char *name)
+{
+ struct sbp_tport *tport;
+ u64 guid = 0;
+
+ if (sbp_parse_wwn(name, &guid, 1) < 0)
+ return ERR_PTR(-EINVAL);
+
+ tport = kzalloc(sizeof(*tport), GFP_KERNEL);
+ if (!tport) {
+ pr_err("Unable to allocate struct sbp_tport\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ tport->guid = guid;
+ sbp_format_wwn(tport->tport_name, SBP_NAMELEN, guid);
+
+ return &tport->tport_wwn;
+}
+
+static void sbp_drop_tport(struct se_wwn *wwn)
+{
+ struct sbp_tport *tport =
+ container_of(wwn, struct sbp_tport, tport_wwn);
+
+ kfree(tport);
+}
+
+static ssize_t sbp_wwn_show_attr_version(
+ struct target_fabric_configfs *tf,
+ char *page)
+{
+ return sprintf(page, "FireWire SBP fabric module %s\n", SBP_VERSION);
+}
+
+TF_WWN_ATTR_RO(sbp, version);
+
+static struct configfs_attribute *sbp_wwn_attrs[] = {
+ &sbp_wwn_version.attr,
+ NULL,
+};
+
+static ssize_t sbp_tpg_show_directory_id(
+ struct se_portal_group *se_tpg,
+ char *page)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ struct sbp_tport *tport = tpg->tport;
+
+ if (tport->directory_id == -1)
+ return sprintf(page, "implicit\n");
+ else
+ return sprintf(page, "%06x\n", tport->directory_id);
+}
+
+static ssize_t sbp_tpg_store_directory_id(
+ struct se_portal_group *se_tpg,
+ const char *page,
+ size_t count)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ struct sbp_tport *tport = tpg->tport;
+ unsigned long val;
+
+ if (tport->enable) {
+ pr_err("Cannot change the directory_id on an active target.\n");
+ return -EBUSY;
+ }
+
+ if (strstr(page, "implicit") == page) {
+ tport->directory_id = -1;
+ } else {
+ if (kstrtoul(page, 16, &val) < 0)
+ return -EINVAL;
+ if (val > 0xffffff)
+ return -EINVAL;
+
+ tport->directory_id = val;
+ }
+
+ return count;
+}
+
+static ssize_t sbp_tpg_show_enable(
+ struct se_portal_group *se_tpg,
+ char *page)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ struct sbp_tport *tport = tpg->tport;
+ return sprintf(page, "%d\n", tport->enable);
+}
+
+static ssize_t sbp_tpg_store_enable(
+ struct se_portal_group *se_tpg,
+ const char *page,
+ size_t count)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ struct sbp_tport *tport = tpg->tport;
+ unsigned long val;
+ int ret;
+
+ if (kstrtoul(page, 0, &val) < 0)
+ return -EINVAL;
+ if ((val != 0) && (val != 1))
+ return -EINVAL;
+
+ if (tport->enable == val)
+ return count;
+
+ if (val) {
+ if (sbp_count_se_tpg_luns(&tpg->se_tpg) == 0) {
+ pr_err("Cannot enable a target with no LUNs!\n");
+ return -EINVAL;
+ }
+ } else {
+ /* XXX: force-shutdown sessions instead? */
+ spin_lock_bh(&se_tpg->session_lock);
+ if (!list_empty(&se_tpg->tpg_sess_list)) {
+ spin_unlock_bh(&se_tpg->session_lock);
+ return -EBUSY;
+ }
+ spin_unlock_bh(&se_tpg->session_lock);
+ }
+
+ tport->enable = val;
+
+ ret = sbp_update_unit_directory(tport);
+ if (ret < 0) {
+ pr_err("Could not update Config ROM\n");
+ return ret;
+ }
+
+ return count;
+}
+
+TF_TPG_BASE_ATTR(sbp, directory_id, S_IRUGO | S_IWUSR);
+TF_TPG_BASE_ATTR(sbp, enable, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *sbp_tpg_base_attrs[] = {
+ &sbp_tpg_directory_id.attr,
+ &sbp_tpg_enable.attr,
+ NULL,
+};
+
+static ssize_t sbp_tpg_attrib_show_mgt_orb_timeout(
+ struct se_portal_group *se_tpg,
+ char *page)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ struct sbp_tport *tport = tpg->tport;
+ return sprintf(page, "%d\n", tport->mgt_orb_timeout);
+}
+
+static ssize_t sbp_tpg_attrib_store_mgt_orb_timeout(
+ struct se_portal_group *se_tpg,
+ const char *page,
+ size_t count)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ struct sbp_tport *tport = tpg->tport;
+ unsigned long val;
+ int ret;
+
+ if (kstrtoul(page, 0, &val) < 0)
+ return -EINVAL;
+ if ((val < 1) || (val > 127))
+ return -EINVAL;
+
+ if (tport->mgt_orb_timeout == val)
+ return count;
+
+ tport->mgt_orb_timeout = val;
+
+ ret = sbp_update_unit_directory(tport);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static ssize_t sbp_tpg_attrib_show_max_reconnect_timeout(
+ struct se_portal_group *se_tpg,
+ char *page)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ struct sbp_tport *tport = tpg->tport;
+ return sprintf(page, "%d\n", tport->max_reconnect_timeout);
+}
+
+static ssize_t sbp_tpg_attrib_store_max_reconnect_timeout(
+ struct se_portal_group *se_tpg,
+ const char *page,
+ size_t count)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ struct sbp_tport *tport = tpg->tport;
+ unsigned long val;
+ int ret;
+
+ if (kstrtoul(page, 0, &val) < 0)
+ return -EINVAL;
+ if ((val < 1) || (val > 32767))
+ return -EINVAL;
+
+ if (tport->max_reconnect_timeout == val)
+ return count;
+
+ tport->max_reconnect_timeout = val;
+
+ ret = sbp_update_unit_directory(tport);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static ssize_t sbp_tpg_attrib_show_max_logins_per_lun(
+ struct se_portal_group *se_tpg,
+ char *page)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ struct sbp_tport *tport = tpg->tport;
+ return sprintf(page, "%d\n", tport->max_logins_per_lun);
+}
+
+static ssize_t sbp_tpg_attrib_store_max_logins_per_lun(
+ struct se_portal_group *se_tpg,
+ const char *page,
+ size_t count)
+{
+ struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
+ struct sbp_tport *tport = tpg->tport;
+ unsigned long val;
+
+ if (kstrtoul(page, 0, &val) < 0)
+ return -EINVAL;
+ if ((val < 1) || (val > 127))
+ return -EINVAL;
+
+ /* XXX: also check against current count? */
+
+ tport->max_logins_per_lun = val;
+
+ return count;
+}
+
+TF_TPG_ATTRIB_ATTR(sbp, mgt_orb_timeout, S_IRUGO | S_IWUSR);
+TF_TPG_ATTRIB_ATTR(sbp, max_reconnect_timeout, S_IRUGO | S_IWUSR);
+TF_TPG_ATTRIB_ATTR(sbp, max_logins_per_lun, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *sbp_tpg_attrib_attrs[] = {
+ &sbp_tpg_attrib_mgt_orb_timeout.attr,
+ &sbp_tpg_attrib_max_reconnect_timeout.attr,
+ &sbp_tpg_attrib_max_logins_per_lun.attr,
+ NULL,
+};
+
+static struct target_core_fabric_ops sbp_ops = {
+ .get_fabric_name = sbp_get_fabric_name,
+ .get_fabric_proto_ident = sbp_get_fabric_proto_ident,
+ .tpg_get_wwn = sbp_get_fabric_wwn,
+ .tpg_get_tag = sbp_get_tag,
+ .tpg_get_default_depth = sbp_get_default_depth,
+ .tpg_get_pr_transport_id = sbp_get_pr_transport_id,
+ .tpg_get_pr_transport_id_len = sbp_get_pr_transport_id_len,
+ .tpg_parse_pr_out_transport_id = sbp_parse_pr_out_transport_id,
+ .tpg_check_demo_mode = sbp_check_true,
+ .tpg_check_demo_mode_cache = sbp_check_true,
+ .tpg_check_demo_mode_write_protect = sbp_check_false,
+ .tpg_check_prod_mode_write_protect = sbp_check_false,
+ .tpg_alloc_fabric_acl = sbp_alloc_fabric_acl,
+ .tpg_release_fabric_acl = sbp_release_fabric_acl,
+ .tpg_get_inst_index = sbp_tpg_get_inst_index,
+ .release_cmd = sbp_release_cmd,
+ .shutdown_session = sbp_shutdown_session,
+ .close_session = sbp_close_session,
+ .sess_get_index = sbp_sess_get_index,
+ .write_pending = sbp_write_pending,
+ .write_pending_status = sbp_write_pending_status,
+ .set_default_node_attributes = sbp_set_default_node_attrs,
+ .get_task_tag = sbp_get_task_tag,
+ .get_cmd_state = sbp_get_cmd_state,
+ .queue_data_in = sbp_queue_data_in,
+ .queue_status = sbp_queue_status,
+ .queue_tm_rsp = sbp_queue_tm_rsp,
+ .get_fabric_sense_len = sbp_get_fabric_sense_len,
+ .set_fabric_sense_len = sbp_set_fabric_sense_len,
+ .check_stop_free = sbp_check_stop_free,
+
+ .fabric_make_wwn = sbp_make_tport,
+ .fabric_drop_wwn = sbp_drop_tport,
+ .fabric_make_tpg = sbp_make_tpg,
+ .fabric_drop_tpg = sbp_drop_tpg,
+ .fabric_post_link = sbp_post_link_lun,
+ .fabric_pre_unlink = sbp_pre_unlink_lun,
+ .fabric_make_np = NULL,
+ .fabric_drop_np = NULL,
+ .fabric_make_nodeacl = sbp_make_nodeacl,
+ .fabric_drop_nodeacl = sbp_drop_nodeacl,
+};
+
+static int sbp_register_configfs(void)
+{
+ struct target_fabric_configfs *fabric;
+ int ret;
+
+ fabric = target_fabric_configfs_init(THIS_MODULE, "sbp");
+ if (!fabric) {
+ pr_err("target_fabric_configfs_init() failed\n");
+ return -ENOMEM;
+ }
+
+ fabric->tf_ops = sbp_ops;
+
+ /*
+ * Setup default attribute lists for various fabric->tf_cit_tmpl
+ */
+ TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = sbp_wwn_attrs;
+ TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = sbp_tpg_base_attrs;
+ TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = sbp_tpg_attrib_attrs;
+ TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL;
+
+ ret = target_fabric_configfs_register(fabric);
+ if (ret < 0) {
+ pr_err("target_fabric_configfs_register() failed for SBP\n");
+ return ret;
+ }
+
+ sbp_fabric_configfs = fabric;
+
+ return 0;
+};
+
+static void sbp_deregister_configfs(void)
+{
+ if (!sbp_fabric_configfs)
+ return;
+
+ target_fabric_configfs_deregister(sbp_fabric_configfs);
+ sbp_fabric_configfs = NULL;
+};
+
+static int __init sbp_init(void)
+{
+ int ret;
+
+ ret = sbp_register_configfs();
+ if (ret < 0)
+ return ret;
+
+ return 0;
+};
+
+static void sbp_exit(void)
+{
+ sbp_deregister_configfs();
+};
+
+MODULE_DESCRIPTION("FireWire SBP fabric driver");
+MODULE_LICENSE("GPL");
+module_init(sbp_init);
+module_exit(sbp_exit);
diff --git a/drivers/target/sbp/sbp_target.h b/drivers/target/sbp/sbp_target.h
new file mode 100644
index 000000000000..6d0d74a2c545
--- /dev/null
+++ b/drivers/target/sbp/sbp_target.h
@@ -0,0 +1,251 @@
+#ifndef _SBP_BASE_H
+#define _SBP_BASE_H
+
+#include <linux/firewire.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+#include <target/target_core_base.h>
+
+#define SBP_VERSION "v0.1"
+#define SBP_NAMELEN 32
+
+#define SBP_ORB_FETCH_SIZE 8
+
+#define MANAGEMENT_AGENT_STATE_IDLE 0
+#define MANAGEMENT_AGENT_STATE_BUSY 1
+
+#define ORB_NOTIFY(v) (((v) >> 31) & 0x01)
+#define ORB_REQUEST_FORMAT(v) (((v) >> 29) & 0x03)
+
+#define MANAGEMENT_ORB_FUNCTION(v) (((v) >> 16) & 0x0f)
+
+#define MANAGEMENT_ORB_FUNCTION_LOGIN 0x0
+#define MANAGEMENT_ORB_FUNCTION_QUERY_LOGINS 0x1
+#define MANAGEMENT_ORB_FUNCTION_RECONNECT 0x3
+#define MANAGEMENT_ORB_FUNCTION_SET_PASSWORD 0x4
+#define MANAGEMENT_ORB_FUNCTION_LOGOUT 0x7
+#define MANAGEMENT_ORB_FUNCTION_ABORT_TASK 0xb
+#define MANAGEMENT_ORB_FUNCTION_ABORT_TASK_SET 0xc
+#define MANAGEMENT_ORB_FUNCTION_LOGICAL_UNIT_RESET 0xe
+#define MANAGEMENT_ORB_FUNCTION_TARGET_RESET 0xf
+
+#define LOGIN_ORB_EXCLUSIVE(v) (((v) >> 28) & 0x01)
+#define LOGIN_ORB_RESERVED(v) (((v) >> 24) & 0x0f)
+#define LOGIN_ORB_RECONNECT(v) (((v) >> 20) & 0x0f)
+#define LOGIN_ORB_LUN(v) (((v) >> 0) & 0xffff)
+#define LOGIN_ORB_PASSWORD_LENGTH(v) (((v) >> 16) & 0xffff)
+#define LOGIN_ORB_RESPONSE_LENGTH(v) (((v) >> 0) & 0xffff)
+
+#define RECONNECT_ORB_LOGIN_ID(v) (((v) >> 0) & 0xffff)
+#define LOGOUT_ORB_LOGIN_ID(v) (((v) >> 0) & 0xffff)
+
+#define CMDBLK_ORB_DIRECTION(v) (((v) >> 27) & 0x01)
+#define CMDBLK_ORB_SPEED(v) (((v) >> 24) & 0x07)
+#define CMDBLK_ORB_MAX_PAYLOAD(v) (((v) >> 20) & 0x0f)
+#define CMDBLK_ORB_PG_TBL_PRESENT(v) (((v) >> 19) & 0x01)
+#define CMDBLK_ORB_PG_SIZE(v) (((v) >> 16) & 0x07)
+#define CMDBLK_ORB_DATA_SIZE(v) (((v) >> 0) & 0xffff)
+
+#define STATUS_BLOCK_SRC(v) (((v) & 0x03) << 30)
+#define STATUS_BLOCK_RESP(v) (((v) & 0x03) << 28)
+#define STATUS_BLOCK_DEAD(v) (((v) ? 1 : 0) << 27)
+#define STATUS_BLOCK_LEN(v) (((v) & 0x07) << 24)
+#define STATUS_BLOCK_SBP_STATUS(v) (((v) & 0xff) << 16)
+#define STATUS_BLOCK_ORB_OFFSET_HIGH(v) (((v) & 0xffff) << 0)
+
+#define STATUS_SRC_ORB_CONTINUING 0
+#define STATUS_SRC_ORB_FINISHED 1
+#define STATUS_SRC_UNSOLICITED 2
+
+#define STATUS_RESP_REQUEST_COMPLETE 0
+#define STATUS_RESP_TRANSPORT_FAILURE 1
+#define STATUS_RESP_ILLEGAL_REQUEST 2
+#define STATUS_RESP_VENDOR_DEPENDENT 3
+
+#define SBP_STATUS_OK 0
+#define SBP_STATUS_REQ_TYPE_NOTSUPP 1
+#define SBP_STATUS_SPEED_NOTSUPP 2
+#define SBP_STATUS_PAGE_SIZE_NOTSUPP 3
+#define SBP_STATUS_ACCESS_DENIED 4
+#define SBP_STATUS_LUN_NOTSUPP 5
+#define SBP_STATUS_PAYLOAD_TOO_SMALL 6
+/* 7 is reserved */
+#define SBP_STATUS_RESOURCES_UNAVAIL 8
+#define SBP_STATUS_FUNCTION_REJECTED 9
+#define SBP_STATUS_LOGIN_ID_UNKNOWN 10
+#define SBP_STATUS_DUMMY_ORB_COMPLETE 11
+#define SBP_STATUS_REQUEST_ABORTED 12
+#define SBP_STATUS_UNSPECIFIED_ERROR 0xff
+
+#define AGENT_STATE_RESET 0
+#define AGENT_STATE_ACTIVE 1
+#define AGENT_STATE_SUSPENDED 2
+#define AGENT_STATE_DEAD 3
+
+struct sbp2_pointer {
+ __be32 high;
+ __be32 low;
+};
+
+struct sbp_command_block_orb {
+ struct sbp2_pointer next_orb;
+ struct sbp2_pointer data_descriptor;
+ __be32 misc;
+ u8 command_block[12];
+};
+
+struct sbp_page_table_entry {
+ __be16 segment_length;
+ __be16 segment_base_hi;
+ __be32 segment_base_lo;
+};
+
+struct sbp_management_orb {
+ struct sbp2_pointer ptr1;
+ struct sbp2_pointer ptr2;
+ __be32 misc;
+ __be32 length;
+ struct sbp2_pointer status_fifo;
+};
+
+struct sbp_status_block {
+ __be32 status;
+ __be32 orb_low;
+ u8 data[24];
+};
+
+struct sbp_login_response_block {
+ __be32 misc;
+ struct sbp2_pointer command_block_agent;
+ __be32 reconnect_hold;
+};
+
+struct sbp_login_descriptor {
+ struct sbp_session *sess;
+ struct list_head link;
+
+ struct se_lun *lun;
+
+ u64 status_fifo_addr;
+ int exclusive;
+ u16 login_id;
+
+ struct sbp_target_agent *tgt_agt;
+};
+
+struct sbp_session {
+ spinlock_t lock;
+ struct se_session *se_sess;
+ struct list_head login_list;
+ struct delayed_work maint_work;
+
+ u64 guid; /* login_owner_EUI_64 */
+ int node_id; /* login_owner_ID */
+
+ struct fw_card *card;
+ int generation;
+ int speed;
+
+ int reconnect_hold;
+ u64 reconnect_expires;
+};
+
+struct sbp_nacl {
+ /* Initiator EUI-64 */
+ u64 guid;
+ /* ASCII formatted GUID for SBP Initiator port */
+ char iport_name[SBP_NAMELEN];
+ /* Returned by sbp_make_nodeacl() */
+ struct se_node_acl se_node_acl;
+};
+
+struct sbp_tpg {
+ /* Target portal group tag for TCM */
+ u16 tport_tpgt;
+ /* Pointer back to sbp_tport */
+ struct sbp_tport *tport;
+ /* Returned by sbp_make_tpg() */
+ struct se_portal_group se_tpg;
+};
+
+struct sbp_tport {
+ /* Target Unit Identifier (EUI-64) */
+ u64 guid;
+ /* Target port name */
+ char tport_name[SBP_NAMELEN];
+ /* Returned by sbp_make_tport() */
+ struct se_wwn tport_wwn;
+
+ struct sbp_tpg *tpg;
+
+ /* FireWire unit directory */
+ struct fw_descriptor unit_directory;
+
+ /* SBP Management Agent */
+ struct sbp_management_agent *mgt_agt;
+
+ /* Parameters */
+ int enable;
+ s32 directory_id;
+ int mgt_orb_timeout;
+ int max_reconnect_timeout;
+ int max_logins_per_lun;
+};
+
+static inline u64 sbp2_pointer_to_addr(const struct sbp2_pointer *ptr)
+{
+ return (u64)(be32_to_cpu(ptr->high) & 0x0000ffff) << 32 |
+ (be32_to_cpu(ptr->low) & 0xfffffffc);
+}
+
+static inline void addr_to_sbp2_pointer(u64 addr, struct sbp2_pointer *ptr)
+{
+ ptr->high = cpu_to_be32(addr >> 32);
+ ptr->low = cpu_to_be32(addr);
+}
+
+struct sbp_target_agent {
+ spinlock_t lock;
+ struct fw_address_handler handler;
+ struct sbp_login_descriptor *login;
+ int state;
+ struct work_struct work;
+ u64 orb_pointer;
+ bool doorbell;
+};
+
+struct sbp_target_request {
+ struct sbp_login_descriptor *login;
+ u64 orb_pointer;
+ struct sbp_command_block_orb orb;
+ struct sbp_status_block status;
+ struct work_struct work;
+
+ struct se_cmd se_cmd;
+ struct sbp_page_table_entry *pg_tbl;
+ void *cmd_buf;
+
+ unsigned char sense_buf[TRANSPORT_SENSE_BUFFER];
+};
+
+struct sbp_management_agent {
+ spinlock_t lock;
+ struct sbp_tport *tport;
+ struct fw_address_handler handler;
+ int state;
+ struct work_struct work;
+ u64 orb_offset;
+ struct sbp_management_request *request;
+};
+
+struct sbp_management_request {
+ struct sbp_management_orb orb;
+ struct sbp_status_block status;
+ struct fw_card *card;
+ int generation;
+ int node_addr;
+ int speed;
+};
+
+#endif
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index c7746a3339d4..e624b836469c 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -59,26 +59,31 @@ struct t10_alua_lu_gp *default_lu_gp;
*
* See spc4r17 section 6.27
*/
-int target_emulate_report_target_port_groups(struct se_task *task)
+int target_emulate_report_target_port_groups(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
struct se_port *port;
struct t10_alua_tg_pt_gp *tg_pt_gp;
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
unsigned char *buf;
- u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first
- Target port group descriptor */
+ u32 rd_len = 0, off;
+ int ext_hdr = (cmd->t_task_cdb[1] & 0x20);
/*
- * Need at least 4 bytes of response data or else we can't
- * even fit the return data length.
+ * Skip over RESERVED area to first Target port group descriptor
+ * depending on the PARAMETER DATA FORMAT type..
*/
- if (cmd->data_length < 4) {
- pr_warn("REPORT TARGET PORT GROUPS allocation length %u"
- " too small\n", cmd->data_length);
+ if (ext_hdr != 0)
+ off = 8;
+ else
+ off = 4;
+
+ if (cmd->data_length < off) {
+ pr_warn("REPORT TARGET PORT GROUPS allocation length %u too"
+ " small for %s header\n", cmd->data_length,
+ (ext_hdr) ? "extended" : "normal");
+ cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
return -EINVAL;
}
-
buf = transport_kmap_data_sg(cmd);
spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
@@ -159,15 +164,34 @@ int target_emulate_report_target_port_groups(struct se_task *task)
/*
* Set the RETURN DATA LENGTH set in the header of the DataIN Payload
*/
- buf[0] = ((rd_len >> 24) & 0xff);
- buf[1] = ((rd_len >> 16) & 0xff);
- buf[2] = ((rd_len >> 8) & 0xff);
- buf[3] = (rd_len & 0xff);
+ put_unaligned_be32(rd_len, &buf[0]);
+ /*
+ * Fill in the Extended header parameter data format if requested
+ */
+ if (ext_hdr != 0) {
+ buf[4] = 0x10;
+ /*
+ * Set the implict transition time (in seconds) for the application
+ * client to use as a base for it's transition timeout value.
+ *
+ * Use the current tg_pt_gp_mem -> tg_pt_gp membership from the LUN
+ * this CDB was received upon to determine this value individually
+ * for ALUA target port group.
+ */
+ port = cmd->se_lun->lun_sep;
+ tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
+ if (tg_pt_gp_mem) {
+ spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
+ tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
+ if (tg_pt_gp)
+ buf[5] = tg_pt_gp->tg_pt_gp_implict_trans_secs;
+ spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
+ }
+ }
transport_kunmap_data_sg(cmd);
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
+ target_complete_cmd(cmd, GOOD);
return 0;
}
@@ -176,9 +200,8 @@ int target_emulate_report_target_port_groups(struct se_task *task)
*
* See spc4r17 section 6.35
*/
-int target_emulate_set_target_port_groups(struct se_task *task)
+int target_emulate_set_target_port_groups(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
struct se_subsystem_dev *su_dev = dev->se_sub_dev;
struct se_port *port, *l_port = cmd->se_lun->lun_sep;
@@ -351,8 +374,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
out:
transport_kunmap_data_sg(cmd);
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
+ target_complete_cmd(cmd, GOOD);
return 0;
}
@@ -391,7 +413,7 @@ static inline int core_alua_state_standby(
case RECEIVE_DIAGNOSTIC:
case SEND_DIAGNOSTIC:
case MAINTENANCE_IN:
- switch (cdb[1]) {
+ switch (cdb[1] & 0x1f) {
case MI_REPORT_TARGET_PGS:
return 0;
default:
@@ -433,7 +455,7 @@ static inline int core_alua_state_unavailable(
case INQUIRY:
case REPORT_LUNS:
case MAINTENANCE_IN:
- switch (cdb[1]) {
+ switch (cdb[1] & 0x1f) {
case MI_REPORT_TARGET_PGS:
return 0;
default:
@@ -473,7 +495,7 @@ static inline int core_alua_state_transition(
case INQUIRY:
case REPORT_LUNS:
case MAINTENANCE_IN:
- switch (cdb[1]) {
+ switch (cdb[1] & 0x1f) {
case MI_REPORT_TARGET_PGS:
return 0;
default:
@@ -1359,6 +1381,7 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(
*/
tg_pt_gp->tg_pt_gp_nonop_delay_msecs = ALUA_DEFAULT_NONOP_DELAY_MSECS;
tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS;
+ tg_pt_gp->tg_pt_gp_implict_trans_secs = ALUA_DEFAULT_IMPLICT_TRANS_SECS;
if (def_group) {
spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
@@ -1855,6 +1878,37 @@ ssize_t core_alua_store_trans_delay_msecs(
return count;
}
+ssize_t core_alua_show_implict_trans_secs(
+ struct t10_alua_tg_pt_gp *tg_pt_gp,
+ char *page)
+{
+ return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_implict_trans_secs);
+}
+
+ssize_t core_alua_store_implict_trans_secs(
+ struct t10_alua_tg_pt_gp *tg_pt_gp,
+ const char *page,
+ size_t count)
+{
+ unsigned long tmp;
+ int ret;
+
+ ret = strict_strtoul(page, 0, &tmp);
+ if (ret < 0) {
+ pr_err("Unable to extract implict_trans_secs\n");
+ return -EINVAL;
+ }
+ if (tmp > ALUA_MAX_IMPLICT_TRANS_SECS) {
+ pr_err("Passed implict_trans_secs: %lu, exceeds"
+ " ALUA_MAX_IMPLICT_TRANS_SECS: %d\n", tmp,
+ ALUA_MAX_IMPLICT_TRANS_SECS);
+ return -EINVAL;
+ }
+ tg_pt_gp->tg_pt_gp_implict_trans_secs = (int)tmp;
+
+ return count;
+}
+
ssize_t core_alua_show_preferred_bit(
struct t10_alua_tg_pt_gp *tg_pt_gp,
char *page)
diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h
index c5b4ecd3e745..f920c170d47b 100644
--- a/drivers/target/target_core_alua.h
+++ b/drivers/target/target_core_alua.h
@@ -52,6 +52,12 @@
#define ALUA_DEFAULT_TRANS_DELAY_MSECS 0
#define ALUA_MAX_TRANS_DELAY_MSECS 30000 /* 30 seconds */
/*
+ * Used for the recommended application client implict transition timeout
+ * in seconds, returned by the REPORT_TARGET_PORT_GROUPS w/ extended header.
+ */
+#define ALUA_DEFAULT_IMPLICT_TRANS_SECS 0
+#define ALUA_MAX_IMPLICT_TRANS_SECS 255
+/*
* Used by core_alua_update_tpg_primary_metadata() and
* core_alua_update_tpg_secondary_metadata()
*/
@@ -66,8 +72,8 @@ extern struct kmem_cache *t10_alua_lu_gp_mem_cache;
extern struct kmem_cache *t10_alua_tg_pt_gp_cache;
extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
-extern int target_emulate_report_target_port_groups(struct se_task *);
-extern int target_emulate_set_target_port_groups(struct se_task *);
+extern int target_emulate_report_target_port_groups(struct se_cmd *);
+extern int target_emulate_set_target_port_groups(struct se_cmd *);
extern int core_alua_check_nonop_delay(struct se_cmd *);
extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *,
struct se_device *, struct se_port *,
@@ -107,6 +113,10 @@ extern ssize_t core_alua_show_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
char *);
extern ssize_t core_alua_store_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
const char *, size_t);
+extern ssize_t core_alua_show_implict_trans_secs(struct t10_alua_tg_pt_gp *,
+ char *);
+extern ssize_t core_alua_store_implict_trans_secs(struct t10_alua_tg_pt_gp *,
+ const char *, size_t);
extern ssize_t core_alua_show_preferred_bit(struct t10_alua_tg_pt_gp *,
char *);
extern ssize_t core_alua_store_preferred_bit(struct t10_alua_tg_pt_gp *,
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c
index 30a67707036f..9888693a18fe 100644
--- a/drivers/target/target_core_cdb.c
+++ b/drivers/target/target_core_cdb.c
@@ -432,6 +432,7 @@ static int
target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
{
struct se_device *dev = cmd->se_dev;
+ u32 max_sectors;
int have_tp = 0;
/*
@@ -456,7 +457,9 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
/*
* Set MAXIMUM TRANSFER LENGTH
*/
- put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.fabric_max_sectors, &buf[8]);
+ max_sectors = min(dev->se_sub_dev->se_dev_attrib.fabric_max_sectors,
+ dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
+ put_unaligned_be32(max_sectors, &buf[8]);
/*
* Set OPTIMAL TRANSFER LENGTH
@@ -598,9 +601,8 @@ target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
return 0;
}
-int target_emulate_inquiry(struct se_task *task)
+int target_emulate_inquiry(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg;
unsigned char *buf, *map_buf;
@@ -664,16 +666,13 @@ out:
}
transport_kunmap_data_sg(cmd);
- if (!ret) {
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
- }
+ if (!ret)
+ target_complete_cmd(cmd, GOOD);
return ret;
}
-int target_emulate_readcapacity(struct se_task *task)
+int target_emulate_readcapacity(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
unsigned char *buf;
unsigned long long blocks_long = dev->transport->get_blocks(dev);
@@ -697,14 +696,12 @@ int target_emulate_readcapacity(struct se_task *task)
transport_kunmap_data_sg(cmd);
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
+ target_complete_cmd(cmd, GOOD);
return 0;
}
-int target_emulate_readcapacity_16(struct se_task *task)
+int target_emulate_readcapacity_16(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
unsigned char *buf;
unsigned long long blocks = dev->transport->get_blocks(dev);
@@ -732,8 +729,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
transport_kunmap_data_sg(cmd);
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
+ target_complete_cmd(cmd, GOOD);
return 0;
}
@@ -872,9 +868,8 @@ target_modesense_dpofua(unsigned char *buf, int type)
}
}
-int target_emulate_modesense(struct se_task *task)
+int target_emulate_modesense(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
char *cdb = cmd->t_task_cdb;
unsigned char *rbuf;
@@ -947,14 +942,12 @@ int target_emulate_modesense(struct se_task *task)
memcpy(rbuf, buf, offset);
transport_kunmap_data_sg(cmd);
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
+ target_complete_cmd(cmd, GOOD);
return 0;
}
-int target_emulate_request_sense(struct se_task *task)
+int target_emulate_request_sense(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
unsigned char *cdb = cmd->t_task_cdb;
unsigned char *buf;
u8 ua_asc = 0, ua_ascq = 0;
@@ -1008,8 +1001,7 @@ int target_emulate_request_sense(struct se_task *task)
end:
transport_kunmap_data_sg(cmd);
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
+ target_complete_cmd(cmd, GOOD);
return 0;
}
@@ -1017,9 +1009,8 @@ end:
* Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
* Note this is not used for TCM/pSCSI passthrough
*/
-int target_emulate_unmap(struct se_task *task)
+int target_emulate_unmap(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
unsigned char *buf, *ptr = NULL;
unsigned char *cdb = &cmd->t_task_cdb[0];
@@ -1066,10 +1057,8 @@ int target_emulate_unmap(struct se_task *task)
err:
transport_kunmap_data_sg(cmd);
- if (!ret) {
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
- }
+ if (!ret)
+ target_complete_cmd(cmd, GOOD);
return ret;
}
@@ -1077,9 +1066,8 @@ err:
* Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
* Note this is not used for TCM/pSCSI passthrough
*/
-int target_emulate_write_same(struct se_task *task)
+int target_emulate_write_same(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
sector_t range;
sector_t lba = cmd->t_task_lba;
@@ -1118,79 +1106,25 @@ int target_emulate_write_same(struct se_task *task)
return ret;
}
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
+ target_complete_cmd(cmd, GOOD);
return 0;
}
-int target_emulate_synchronize_cache(struct se_task *task)
+int target_emulate_synchronize_cache(struct se_cmd *cmd)
{
- struct se_device *dev = task->task_se_cmd->se_dev;
- struct se_cmd *cmd = task->task_se_cmd;
-
- if (!dev->transport->do_sync_cache) {
+ if (!cmd->se_dev->transport->do_sync_cache) {
pr_err("SYNCHRONIZE_CACHE emulation not supported"
- " for: %s\n", dev->transport->name);
+ " for: %s\n", cmd->se_dev->transport->name);
cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
return -ENOSYS;
}
- dev->transport->do_sync_cache(task);
+ cmd->se_dev->transport->do_sync_cache(cmd);
return 0;
}
-int target_emulate_noop(struct se_task *task)
+int target_emulate_noop(struct se_cmd *cmd)
{
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
+ target_complete_cmd(cmd, GOOD);
return 0;
}
-
-/*
- * Write a CDB into @cdb that is based on the one the intiator sent us,
- * but updated to only cover the sectors that the current task handles.
- */
-void target_get_task_cdb(struct se_task *task, unsigned char *cdb)
-{
- struct se_cmd *cmd = task->task_se_cmd;
- unsigned int cdb_len = scsi_command_size(cmd->t_task_cdb);
-
- memcpy(cdb, cmd->t_task_cdb, cdb_len);
- if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
- unsigned long long lba = task->task_lba;
- u32 sectors = task->task_sectors;
-
- switch (cdb_len) {
- case 6:
- /* 21-bit LBA and 8-bit sectors */
- cdb[1] = (lba >> 16) & 0x1f;
- cdb[2] = (lba >> 8) & 0xff;
- cdb[3] = lba & 0xff;
- cdb[4] = sectors & 0xff;
- break;
- case 10:
- /* 32-bit LBA and 16-bit sectors */
- put_unaligned_be32(lba, &cdb[2]);
- put_unaligned_be16(sectors, &cdb[7]);
- break;
- case 12:
- /* 32-bit LBA and 32-bit sectors */
- put_unaligned_be32(lba, &cdb[2]);
- put_unaligned_be32(sectors, &cdb[6]);
- break;
- case 16:
- /* 64-bit LBA and 32-bit sectors */
- put_unaligned_be64(lba, &cdb[2]);
- put_unaligned_be32(sectors, &cdb[10]);
- break;
- case 32:
- /* 64-bit LBA and 32-bit sectors, extended CDB */
- put_unaligned_be64(lba, &cdb[12]);
- put_unaligned_be32(sectors, &cdb[28]);
- break;
- default:
- BUG();
- }
- }
-}
-EXPORT_SYMBOL(target_get_task_cdb);
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index cbb66537d230..801efa892046 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -683,9 +683,6 @@ SE_DEV_ATTR(block_size, S_IRUGO | S_IWUSR);
DEF_DEV_ATTRIB_RO(hw_max_sectors);
SE_DEV_ATTR_RO(hw_max_sectors);
-DEF_DEV_ATTRIB(max_sectors);
-SE_DEV_ATTR(max_sectors, S_IRUGO | S_IWUSR);
-
DEF_DEV_ATTRIB(fabric_max_sectors);
SE_DEV_ATTR(fabric_max_sectors, S_IRUGO | S_IWUSR);
@@ -727,7 +724,6 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
&target_core_dev_attrib_hw_block_size.attr,
&target_core_dev_attrib_block_size.attr,
&target_core_dev_attrib_hw_max_sectors.attr,
- &target_core_dev_attrib_max_sectors.attr,
&target_core_dev_attrib_fabric_max_sectors.attr,
&target_core_dev_attrib_optimal_sectors.attr,
&target_core_dev_attrib_hw_queue_depth.attr,
@@ -2451,6 +2447,26 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_trans_delay_msecs(
SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR);
/*
+ * implict_trans_secs
+ */
+static ssize_t target_core_alua_tg_pt_gp_show_attr_implict_trans_secs(
+ struct t10_alua_tg_pt_gp *tg_pt_gp,
+ char *page)
+{
+ return core_alua_show_implict_trans_secs(tg_pt_gp, page);
+}
+
+static ssize_t target_core_alua_tg_pt_gp_store_attr_implict_trans_secs(
+ struct t10_alua_tg_pt_gp *tg_pt_gp,
+ const char *page,
+ size_t count)
+{
+ return core_alua_store_implict_trans_secs(tg_pt_gp, page, count);
+}
+
+SE_DEV_ALUA_TG_PT_ATTR(implict_trans_secs, S_IRUGO | S_IWUSR);
+
+/*
* preferred
*/
@@ -2574,6 +2590,7 @@ static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = {
&target_core_alua_tg_pt_gp_alua_write_metadata.attr,
&target_core_alua_tg_pt_gp_nonop_delay_msecs.attr,
&target_core_alua_tg_pt_gp_trans_delay_msecs.attr,
+ &target_core_alua_tg_pt_gp_implict_trans_secs.attr,
&target_core_alua_tg_pt_gp_preferred.attr,
&target_core_alua_tg_pt_gp_tg_pt_gp_id.attr,
&target_core_alua_tg_pt_gp_members.attr,
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index aa6267746383..5ad972856a8d 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -643,9 +643,8 @@ void core_dev_unexport(
lun->lun_se_dev = NULL;
}
-int target_report_luns(struct se_task *se_task)
+int target_report_luns(struct se_cmd *se_cmd)
{
- struct se_cmd *se_cmd = se_task->task_se_cmd;
struct se_dev_entry *deve;
struct se_session *se_sess = se_cmd->se_sess;
unsigned char *buf;
@@ -696,8 +695,7 @@ done:
buf[3] = (lun_count & 0xff);
transport_kunmap_data_sg(se_cmd);
- se_task->task_scsi_status = GOOD;
- transport_complete_task(se_task, 1);
+ target_complete_cmd(se_cmd, GOOD);
return 0;
}
@@ -878,15 +876,12 @@ void se_dev_set_default_attribs(
dev->se_sub_dev->se_dev_attrib.hw_block_size = limits->logical_block_size;
dev->se_sub_dev->se_dev_attrib.block_size = limits->logical_block_size;
/*
- * max_sectors is based on subsystem plugin dependent requirements.
+ * Align max_hw_sectors down to PAGE_SIZE I/O transfers
*/
- dev->se_sub_dev->se_dev_attrib.hw_max_sectors = limits->max_hw_sectors;
- /*
- * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks()
- */
- limits->max_sectors = se_dev_align_max_sectors(limits->max_sectors,
+ limits->max_hw_sectors = se_dev_align_max_sectors(limits->max_hw_sectors,
limits->logical_block_size);
- dev->se_sub_dev->se_dev_attrib.max_sectors = limits->max_sectors;
+ dev->se_sub_dev->se_dev_attrib.hw_max_sectors = limits->max_hw_sectors;
+
/*
* Set fabric_max_sectors, which is reported in block limits
* VPD page (B0h).
@@ -1170,64 +1165,6 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth)
return 0;
}
-int se_dev_set_max_sectors(struct se_device *dev, u32 max_sectors)
-{
- int force = 0; /* Force setting for VDEVS */
-
- if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
- pr_err("dev[%p]: Unable to change SE Device"
- " max_sectors while dev_export_obj: %d count exists\n",
- dev, atomic_read(&dev->dev_export_obj.obj_access_count));
- return -EINVAL;
- }
- if (!max_sectors) {
- pr_err("dev[%p]: Illegal ZERO value for"
- " max_sectors\n", dev);
- return -EINVAL;
- }
- if (max_sectors < DA_STATUS_MAX_SECTORS_MIN) {
- pr_err("dev[%p]: Passed max_sectors: %u less than"
- " DA_STATUS_MAX_SECTORS_MIN: %u\n", dev, max_sectors,
- DA_STATUS_MAX_SECTORS_MIN);
- return -EINVAL;
- }
- if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
- if (max_sectors > dev->se_sub_dev->se_dev_attrib.hw_max_sectors) {
- pr_err("dev[%p]: Passed max_sectors: %u"
- " greater than TCM/SE_Device max_sectors:"
- " %u\n", dev, max_sectors,
- dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
- return -EINVAL;
- }
- } else {
- if (!force && (max_sectors >
- dev->se_sub_dev->se_dev_attrib.hw_max_sectors)) {
- pr_err("dev[%p]: Passed max_sectors: %u"
- " greater than TCM/SE_Device max_sectors"
- ": %u, use force=1 to override.\n", dev,
- max_sectors, dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
- return -EINVAL;
- }
- if (max_sectors > DA_STATUS_MAX_SECTORS_MAX) {
- pr_err("dev[%p]: Passed max_sectors: %u"
- " greater than DA_STATUS_MAX_SECTORS_MAX:"
- " %u\n", dev, max_sectors,
- DA_STATUS_MAX_SECTORS_MAX);
- return -EINVAL;
- }
- }
- /*
- * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks()
- */
- max_sectors = se_dev_align_max_sectors(max_sectors,
- dev->se_sub_dev->se_dev_attrib.block_size);
-
- dev->se_sub_dev->se_dev_attrib.max_sectors = max_sectors;
- pr_debug("dev[%p]: SE Device max_sectors changed to %u\n",
- dev, max_sectors);
- return 0;
-}
-
int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)
{
if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
@@ -1341,7 +1278,6 @@ struct se_lun *core_dev_add_lun(
u32 lun)
{
struct se_lun *lun_p;
- u32 lun_access = 0;
int rc;
if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) {
@@ -1354,12 +1290,8 @@ struct se_lun *core_dev_add_lun(
if (IS_ERR(lun_p))
return lun_p;
- if (dev->dev_flags & DF_READ_ONLY)
- lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
- else
- lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
-
- rc = core_tpg_post_addlun(tpg, lun_p, lun_access, dev);
+ rc = core_tpg_post_addlun(tpg, lun_p,
+ TRANSPORT_LUNFLAGS_READ_WRITE, dev);
if (rc < 0)
return ERR_PTR(rc);
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 7ed58e2df791..686dba189f8e 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -133,15 +133,10 @@ static struct se_device *fd_create_virtdevice(
ret = PTR_ERR(dev_p);
goto fail;
}
-#if 0
- if (di->no_create_file)
- flags = O_RDWR | O_LARGEFILE;
- else
- flags = O_RDWR | O_CREAT | O_LARGEFILE;
-#else
+
+ /* O_DIRECT too? */
flags = O_RDWR | O_CREAT | O_LARGEFILE;
-#endif
-/* flags |= O_DIRECT; */
+
/*
* If fd_buffered_io=1 has not been set explicitly (the default),
* use O_SYNC to force FILEIO writes to disk.
@@ -169,6 +164,7 @@ static struct se_device *fd_create_virtdevice(
inode = file->f_mapping->host;
if (S_ISBLK(inode->i_mode)) {
struct request_queue *q;
+ unsigned long long dev_size;
/*
* Setup the local scope queue_limits from struct request_queue->limits
* to pass into transport_add_device_to_core_hba() as struct se_dev_limits.
@@ -183,13 +179,12 @@ static struct se_device *fd_create_virtdevice(
* one (1) logical sector from underlying struct block_device
*/
fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev);
- fd_dev->fd_dev_size = (i_size_read(file->f_mapping->host) -
+ dev_size = (i_size_read(file->f_mapping->host) -
fd_dev->fd_block_size);
pr_debug("FILEIO: Using size: %llu bytes from struct"
" block_device blocks: %llu logical_block_size: %d\n",
- fd_dev->fd_dev_size,
- div_u64(fd_dev->fd_dev_size, fd_dev->fd_block_size),
+ dev_size, div_u64(dev_size, fd_dev->fd_block_size),
fd_dev->fd_block_size);
} else {
if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) {
@@ -249,53 +244,33 @@ static void fd_free_device(void *p)
kfree(fd_dev);
}
-static inline struct fd_request *FILE_REQ(struct se_task *task)
+static int fd_do_readv(struct se_cmd *cmd, struct scatterlist *sgl,
+ u32 sgl_nents)
{
- return container_of(task, struct fd_request, fd_task);
-}
-
-
-static struct se_task *
-fd_alloc_task(unsigned char *cdb)
-{
- struct fd_request *fd_req;
-
- fd_req = kzalloc(sizeof(struct fd_request), GFP_KERNEL);
- if (!fd_req) {
- pr_err("Unable to allocate struct fd_request\n");
- return NULL;
- }
-
- return &fd_req->fd_task;
-}
-
-static int fd_do_readv(struct se_task *task)
-{
- struct fd_request *req = FILE_REQ(task);
- struct se_device *se_dev = req->fd_task.task_se_cmd->se_dev;
+ struct se_device *se_dev = cmd->se_dev;
struct fd_dev *dev = se_dev->dev_ptr;
struct file *fd = dev->fd_file;
- struct scatterlist *sg = task->task_sg;
+ struct scatterlist *sg;
struct iovec *iov;
mm_segment_t old_fs;
- loff_t pos = (task->task_lba *
+ loff_t pos = (cmd->t_task_lba *
se_dev->se_sub_dev->se_dev_attrib.block_size);
int ret = 0, i;
- iov = kzalloc(sizeof(struct iovec) * task->task_sg_nents, GFP_KERNEL);
+ iov = kzalloc(sizeof(struct iovec) * sgl_nents, GFP_KERNEL);
if (!iov) {
pr_err("Unable to allocate fd_do_readv iov[]\n");
return -ENOMEM;
}
- for_each_sg(task->task_sg, sg, task->task_sg_nents, i) {
+ for_each_sg(sgl, sg, sgl_nents, i) {
iov[i].iov_len = sg->length;
iov[i].iov_base = sg_virt(sg);
}
old_fs = get_fs();
set_fs(get_ds());
- ret = vfs_readv(fd, &iov[0], task->task_sg_nents, &pos);
+ ret = vfs_readv(fd, &iov[0], sgl_nents, &pos);
set_fs(old_fs);
kfree(iov);
@@ -305,10 +280,10 @@ static int fd_do_readv(struct se_task *task)
* block_device.
*/
if (S_ISBLK(fd->f_dentry->d_inode->i_mode)) {
- if (ret < 0 || ret != task->task_size) {
+ if (ret < 0 || ret != cmd->data_length) {
pr_err("vfs_readv() returned %d,"
" expecting %d for S_ISBLK\n", ret,
- (int)task->task_size);
+ (int)cmd->data_length);
return (ret < 0 ? ret : -EINVAL);
}
} else {
@@ -322,38 +297,38 @@ static int fd_do_readv(struct se_task *task)
return 1;
}
-static int fd_do_writev(struct se_task *task)
+static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl,
+ u32 sgl_nents)
{
- struct fd_request *req = FILE_REQ(task);
- struct se_device *se_dev = req->fd_task.task_se_cmd->se_dev;
+ struct se_device *se_dev = cmd->se_dev;
struct fd_dev *dev = se_dev->dev_ptr;
struct file *fd = dev->fd_file;
- struct scatterlist *sg = task->task_sg;
+ struct scatterlist *sg;
struct iovec *iov;
mm_segment_t old_fs;
- loff_t pos = (task->task_lba *
+ loff_t pos = (cmd->t_task_lba *
se_dev->se_sub_dev->se_dev_attrib.block_size);
int ret, i = 0;
- iov = kzalloc(sizeof(struct iovec) * task->task_sg_nents, GFP_KERNEL);
+ iov = kzalloc(sizeof(struct iovec) * sgl_nents, GFP_KERNEL);
if (!iov) {
pr_err("Unable to allocate fd_do_writev iov[]\n");
return -ENOMEM;
}
- for_each_sg(task->task_sg, sg, task->task_sg_nents, i) {
+ for_each_sg(sgl, sg, sgl_nents, i) {
iov[i].iov_len = sg->length;
iov[i].iov_base = sg_virt(sg);
}
old_fs = get_fs();
set_fs(get_ds());
- ret = vfs_writev(fd, &iov[0], task->task_sg_nents, &pos);
+ ret = vfs_writev(fd, &iov[0], sgl_nents, &pos);
set_fs(old_fs);
kfree(iov);
- if (ret < 0 || ret != task->task_size) {
+ if (ret < 0 || ret != cmd->data_length) {
pr_err("vfs_writev() returned %d\n", ret);
return (ret < 0 ? ret : -EINVAL);
}
@@ -361,9 +336,8 @@ static int fd_do_writev(struct se_task *task)
return 1;
}
-static void fd_emulate_sync_cache(struct se_task *task)
+static void fd_emulate_sync_cache(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
struct fd_dev *fd_dev = dev->dev_ptr;
int immed = (cmd->t_task_cdb[1] & 0x2);
@@ -375,7 +349,7 @@ static void fd_emulate_sync_cache(struct se_task *task)
* for this SYNCHRONIZE_CACHE op
*/
if (immed)
- transport_complete_sync_cache(cmd, 1);
+ target_complete_cmd(cmd, SAM_STAT_GOOD);
/*
* Determine if we will be flushing the entire device.
@@ -395,33 +369,37 @@ static void fd_emulate_sync_cache(struct se_task *task)
if (ret != 0)
pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret);
- if (!immed)
- transport_complete_sync_cache(cmd, ret == 0);
+ if (immed)
+ return;
+
+ if (ret) {
+ cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
+ } else {
+ target_complete_cmd(cmd, SAM_STAT_GOOD);
+ }
}
-/*
- * WRITE Force Unit Access (FUA) emulation on a per struct se_task
- * LBA range basis..
- */
-static void fd_emulate_write_fua(struct se_cmd *cmd, struct se_task *task)
+static void fd_emulate_write_fua(struct se_cmd *cmd)
{
struct se_device *dev = cmd->se_dev;
struct fd_dev *fd_dev = dev->dev_ptr;
- loff_t start = task->task_lba * dev->se_sub_dev->se_dev_attrib.block_size;
- loff_t end = start + task->task_size;
+ loff_t start = cmd->t_task_lba *
+ dev->se_sub_dev->se_dev_attrib.block_size;
+ loff_t end = start + cmd->data_length;
int ret;
pr_debug("FILEIO: FUA WRITE LBA: %llu, bytes: %u\n",
- task->task_lba, task->task_size);
+ cmd->t_task_lba, cmd->data_length);
ret = vfs_fsync_range(fd_dev->fd_file, start, end, 1);
if (ret != 0)
pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret);
}
-static int fd_do_task(struct se_task *task)
+static int fd_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
+ u32 sgl_nents, enum dma_data_direction data_direction)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
int ret = 0;
@@ -429,10 +407,10 @@ static int fd_do_task(struct se_task *task)
* Call vectorized fileio functions to map struct scatterlist
* physical memory addresses to struct iovec virtual memory.
*/
- if (task->task_data_direction == DMA_FROM_DEVICE) {
- ret = fd_do_readv(task);
+ if (data_direction == DMA_FROM_DEVICE) {
+ ret = fd_do_readv(cmd, sgl, sgl_nents);
} else {
- ret = fd_do_writev(task);
+ ret = fd_do_writev(cmd, sgl, sgl_nents);
if (ret > 0 &&
dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0 &&
@@ -443,7 +421,7 @@ static int fd_do_task(struct se_task *task)
* and return some sense data to let the initiator
* know the FUA WRITE cache sync failed..?
*/
- fd_emulate_write_fua(cmd, task);
+ fd_emulate_write_fua(cmd);
}
}
@@ -452,24 +430,11 @@ static int fd_do_task(struct se_task *task)
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return ret;
}
- if (ret) {
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
- }
+ if (ret)
+ target_complete_cmd(cmd, SAM_STAT_GOOD);
return 0;
}
-/* fd_free_task(): (Part of se_subsystem_api_t template)
- *
- *
- */
-static void fd_free_task(struct se_task *task)
-{
- struct fd_request *req = FILE_REQ(task);
-
- kfree(req);
-}
-
enum {
Opt_fd_dev_name, Opt_fd_dev_size, Opt_fd_buffered_io, Opt_err
};
@@ -605,10 +570,20 @@ static u32 fd_get_device_type(struct se_device *dev)
static sector_t fd_get_blocks(struct se_device *dev)
{
struct fd_dev *fd_dev = dev->dev_ptr;
- unsigned long long blocks_long = div_u64(fd_dev->fd_dev_size,
- dev->se_sub_dev->se_dev_attrib.block_size);
+ struct file *f = fd_dev->fd_file;
+ struct inode *i = f->f_mapping->host;
+ unsigned long long dev_size;
+ /*
+ * When using a file that references an underlying struct block_device,
+ * ensure dev_size is always based on the current inode size in order
+ * to handle underlying block_device resize operations.
+ */
+ if (S_ISBLK(i->i_mode))
+ dev_size = (i_size_read(i) - fd_dev->fd_block_size);
+ else
+ dev_size = fd_dev->fd_dev_size;
- return blocks_long;
+ return div_u64(dev_size, dev->se_sub_dev->se_dev_attrib.block_size);
}
static struct se_subsystem_api fileio_template = {
@@ -622,10 +597,8 @@ static struct se_subsystem_api fileio_template = {
.allocate_virtdevice = fd_allocate_virtdevice,
.create_virtdevice = fd_create_virtdevice,
.free_device = fd_free_device,
- .alloc_task = fd_alloc_task,
- .do_task = fd_do_task,
+ .execute_cmd = fd_execute_cmd,
.do_sync_cache = fd_emulate_sync_cache,
- .free_task = fd_free_task,
.check_configfs_dev_params = fd_check_configfs_dev_params,
.set_configfs_dev_params = fd_set_configfs_dev_params,
.show_configfs_dev_params = fd_show_configfs_dev_params,
diff --git a/drivers/target/target_core_file.h b/drivers/target/target_core_file.h
index 59e6e73106c2..fbd59ef7d8be 100644
--- a/drivers/target/target_core_file.h
+++ b/drivers/target/target_core_file.h
@@ -12,10 +12,6 @@
#define RRF_EMULATE_CDB 0x01
#define RRF_GOT_LBA 0x02
-struct fd_request {
- struct se_task fd_task;
-};
-
#define FBDF_HAS_PATH 0x01
#define FBDF_HAS_SIZE 0x02
#define FDBD_USE_BUFFERED_IO 0x04
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 2ec299e8a73e..fd47950727b4 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -189,26 +189,6 @@ static void iblock_free_device(void *p)
kfree(ib_dev);
}
-static inline struct iblock_req *IBLOCK_REQ(struct se_task *task)
-{
- return container_of(task, struct iblock_req, ib_task);
-}
-
-static struct se_task *
-iblock_alloc_task(unsigned char *cdb)
-{
- struct iblock_req *ib_req;
-
- ib_req = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
- if (!ib_req) {
- pr_err("Unable to allocate memory for struct iblock_req\n");
- return NULL;
- }
-
- atomic_set(&ib_req->pending, 1);
- return &ib_req->ib_task;
-}
-
static unsigned long long iblock_emulate_read_cap_with_block_size(
struct se_device *dev,
struct block_device *bd,
@@ -295,8 +275,16 @@ static void iblock_end_io_flush(struct bio *bio, int err)
if (err)
pr_err("IBLOCK: cache flush failed: %d\n", err);
- if (cmd)
- transport_complete_sync_cache(cmd, err == 0);
+ if (cmd) {
+ if (err) {
+ cmd->scsi_sense_reason =
+ TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
+ } else {
+ target_complete_cmd(cmd, SAM_STAT_GOOD);
+ }
+ }
+
bio_put(bio);
}
@@ -304,9 +292,8 @@ static void iblock_end_io_flush(struct bio *bio, int err)
* Implement SYCHRONIZE CACHE. Note that we can't handle lba ranges and must
* always flush the whole cache.
*/
-static void iblock_emulate_sync_cache(struct se_task *task)
+static void iblock_emulate_sync_cache(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
int immed = (cmd->t_task_cdb[1] & 0x2);
struct bio *bio;
@@ -316,7 +303,7 @@ static void iblock_emulate_sync_cache(struct se_task *task)
* for this SYNCHRONIZE_CACHE op.
*/
if (immed)
- transport_complete_sync_cache(cmd, 1);
+ target_complete_cmd(cmd, SAM_STAT_GOOD);
bio = bio_alloc(GFP_KERNEL, 0);
bio->bi_end_io = iblock_end_io_flush;
@@ -335,11 +322,6 @@ static int iblock_do_discard(struct se_device *dev, sector_t lba, u32 range)
return blkdev_issue_discard(bd, lba, range, GFP_KERNEL, barrier);
}
-static void iblock_free_task(struct se_task *task)
-{
- kfree(IBLOCK_REQ(task));
-}
-
enum {
Opt_udev_path, Opt_force, Opt_err
};
@@ -448,19 +430,35 @@ static ssize_t iblock_show_configfs_dev_params(
return bl;
}
+static void iblock_complete_cmd(struct se_cmd *cmd)
+{
+ struct iblock_req *ibr = cmd->priv;
+ u8 status;
+
+ if (!atomic_dec_and_test(&ibr->pending))
+ return;
+
+ if (atomic_read(&ibr->ib_bio_err_cnt))
+ status = SAM_STAT_CHECK_CONDITION;
+ else
+ status = SAM_STAT_GOOD;
+
+ target_complete_cmd(cmd, status);
+ kfree(ibr);
+}
+
static void iblock_bio_destructor(struct bio *bio)
{
- struct se_task *task = bio->bi_private;
- struct iblock_dev *ib_dev = task->task_se_cmd->se_dev->dev_ptr;
+ struct se_cmd *cmd = bio->bi_private;
+ struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
bio_free(bio, ib_dev->ibd_bio_set);
}
static struct bio *
-iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num)
+iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num)
{
- struct iblock_dev *ib_dev = task->task_se_cmd->se_dev->dev_ptr;
- struct iblock_req *ib_req = IBLOCK_REQ(task);
+ struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
struct bio *bio;
/*
@@ -476,19 +474,11 @@ iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num)
return NULL;
}
- pr_debug("Allocated bio: %p task_sg_nents: %u using ibd_bio_set:"
- " %p\n", bio, task->task_sg_nents, ib_dev->ibd_bio_set);
- pr_debug("Allocated bio: %p task_size: %u\n", bio, task->task_size);
-
bio->bi_bdev = ib_dev->ibd_bd;
- bio->bi_private = task;
+ bio->bi_private = cmd;
bio->bi_destructor = iblock_bio_destructor;
bio->bi_end_io = &iblock_bio_done;
bio->bi_sector = lba;
- atomic_inc(&ib_req->pending);
-
- pr_debug("Set bio->bi_sector: %llu\n", (unsigned long long)bio->bi_sector);
- pr_debug("Set ib_req->pending: %d\n", atomic_read(&ib_req->pending));
return bio;
}
@@ -503,20 +493,21 @@ static void iblock_submit_bios(struct bio_list *list, int rw)
blk_finish_plug(&plug);
}
-static int iblock_do_task(struct se_task *task)
+static int iblock_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
+ u32 sgl_nents, enum dma_data_direction data_direction)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
- struct iblock_req *ibr = IBLOCK_REQ(task);
+ struct iblock_req *ibr;
struct bio *bio;
struct bio_list list;
struct scatterlist *sg;
- u32 i, sg_num = task->task_sg_nents;
+ u32 sg_num = sgl_nents;
sector_t block_lba;
unsigned bio_cnt;
int rw;
+ int i;
- if (task->task_data_direction == DMA_TO_DEVICE) {
+ if (data_direction == DMA_TO_DEVICE) {
/*
* Force data to disk if we pretend to not have a volatile
* write cache, or the initiator set the Force Unit Access bit.
@@ -532,17 +523,17 @@ static int iblock_do_task(struct se_task *task)
}
/*
- * Do starting conversion up from non 512-byte blocksize with
- * struct se_task SCSI blocksize into Linux/Block 512 units for BIO.
+ * Convert the blocksize advertised to the initiator to the 512 byte
+ * units unconditionally used by the Linux block layer.
*/
if (dev->se_sub_dev->se_dev_attrib.block_size == 4096)
- block_lba = (task->task_lba << 3);
+ block_lba = (cmd->t_task_lba << 3);
else if (dev->se_sub_dev->se_dev_attrib.block_size == 2048)
- block_lba = (task->task_lba << 2);
+ block_lba = (cmd->t_task_lba << 2);
else if (dev->se_sub_dev->se_dev_attrib.block_size == 1024)
- block_lba = (task->task_lba << 1);
+ block_lba = (cmd->t_task_lba << 1);
else if (dev->se_sub_dev->se_dev_attrib.block_size == 512)
- block_lba = task->task_lba;
+ block_lba = cmd->t_task_lba;
else {
pr_err("Unsupported SCSI -> BLOCK LBA conversion:"
" %u\n", dev->se_sub_dev->se_dev_attrib.block_size);
@@ -550,17 +541,22 @@ static int iblock_do_task(struct se_task *task)
return -ENOSYS;
}
- bio = iblock_get_bio(task, block_lba, sg_num);
- if (!bio) {
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
- return -ENOMEM;
- }
+ ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
+ if (!ibr)
+ goto fail;
+ cmd->priv = ibr;
+
+ bio = iblock_get_bio(cmd, block_lba, sgl_nents);
+ if (!bio)
+ goto fail_free_ibr;
bio_list_init(&list);
bio_list_add(&list, bio);
+
+ atomic_set(&ibr->pending, 2);
bio_cnt = 1;
- for_each_sg(task->task_sg, sg, task->task_sg_nents, i) {
+ for_each_sg(sgl, sg, sgl_nents, i) {
/*
* XXX: if the length the device accepts is shorter than the
* length of the S/G list entry this will cause and
@@ -573,9 +569,11 @@ static int iblock_do_task(struct se_task *task)
bio_cnt = 0;
}
- bio = iblock_get_bio(task, block_lba, sg_num);
+ bio = iblock_get_bio(cmd, block_lba, sg_num);
if (!bio)
- goto fail;
+ goto fail_put_bios;
+
+ atomic_inc(&ibr->pending);
bio_list_add(&list, bio);
bio_cnt++;
}
@@ -586,17 +584,16 @@ static int iblock_do_task(struct se_task *task)
}
iblock_submit_bios(&list, rw);
-
- if (atomic_dec_and_test(&ibr->pending)) {
- transport_complete_task(task,
- !atomic_read(&ibr->ib_bio_err_cnt));
- }
+ iblock_complete_cmd(cmd);
return 0;
-fail:
+fail_put_bios:
while ((bio = bio_list_pop(&list)))
bio_put(bio);
+fail_free_ibr:
+ kfree(ibr);
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+fail:
return -ENOMEM;
}
@@ -621,8 +618,8 @@ static sector_t iblock_get_blocks(struct se_device *dev)
static void iblock_bio_done(struct bio *bio, int err)
{
- struct se_task *task = bio->bi_private;
- struct iblock_req *ibr = IBLOCK_REQ(task);
+ struct se_cmd *cmd = bio->bi_private;
+ struct iblock_req *ibr = cmd->priv;
/*
* Set -EIO if !BIO_UPTODATE and the passed is still err=0
@@ -642,14 +639,7 @@ static void iblock_bio_done(struct bio *bio, int err)
bio_put(bio);
- if (!atomic_dec_and_test(&ibr->pending))
- return;
-
- pr_debug("done[%p] bio: %p task_lba: %llu bio_lba: %llu err=%d\n",
- task, bio, task->task_lba,
- (unsigned long long)bio->bi_sector, err);
-
- transport_complete_task(task, !atomic_read(&ibr->ib_bio_err_cnt));
+ iblock_complete_cmd(cmd);
}
static struct se_subsystem_api iblock_template = {
@@ -663,11 +653,9 @@ static struct se_subsystem_api iblock_template = {
.allocate_virtdevice = iblock_allocate_virtdevice,
.create_virtdevice = iblock_create_virtdevice,
.free_device = iblock_free_device,
- .alloc_task = iblock_alloc_task,
- .do_task = iblock_do_task,
+ .execute_cmd = iblock_execute_cmd,
.do_discard = iblock_do_discard,
.do_sync_cache = iblock_emulate_sync_cache,
- .free_task = iblock_free_task,
.check_configfs_dev_params = iblock_check_configfs_dev_params,
.set_configfs_dev_params = iblock_set_configfs_dev_params,
.show_configfs_dev_params = iblock_show_configfs_dev_params,
diff --git a/drivers/target/target_core_iblock.h b/drivers/target/target_core_iblock.h
index e929370b6fd3..66cf7b9e205e 100644
--- a/drivers/target/target_core_iblock.h
+++ b/drivers/target/target_core_iblock.h
@@ -7,7 +7,6 @@
#define IBLOCK_LBA_SHIFT 9
struct iblock_req {
- struct se_task ib_task;
atomic_t pending;
atomic_t ib_bio_err_cnt;
} ____cacheline_aligned;
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
index 21c05638f158..165e82429687 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -5,15 +5,15 @@
extern struct t10_alua_lu_gp *default_lu_gp;
/* target_core_cdb.c */
-int target_emulate_inquiry(struct se_task *task);
-int target_emulate_readcapacity(struct se_task *task);
-int target_emulate_readcapacity_16(struct se_task *task);
-int target_emulate_modesense(struct se_task *task);
-int target_emulate_request_sense(struct se_task *task);
-int target_emulate_unmap(struct se_task *task);
-int target_emulate_write_same(struct se_task *task);
-int target_emulate_synchronize_cache(struct se_task *task);
-int target_emulate_noop(struct se_task *task);
+int target_emulate_inquiry(struct se_cmd *cmd);
+int target_emulate_readcapacity(struct se_cmd *cmd);
+int target_emulate_readcapacity_16(struct se_cmd *cmd);
+int target_emulate_modesense(struct se_cmd *cmd);
+int target_emulate_request_sense(struct se_cmd *cmd);
+int target_emulate_unmap(struct se_cmd *cmd);
+int target_emulate_write_same(struct se_cmd *cmd);
+int target_emulate_synchronize_cache(struct se_cmd *cmd);
+int target_emulate_noop(struct se_cmd *cmd);
/* target_core_device.c */
struct se_dev_entry *core_get_se_deve_from_rtpi(struct se_node_acl *, u16);
@@ -28,7 +28,7 @@ int core_dev_export(struct se_device *, struct se_portal_group *,
struct se_lun *);
void core_dev_unexport(struct se_device *, struct se_portal_group *,
struct se_lun *);
-int target_report_luns(struct se_task *);
+int target_report_luns(struct se_cmd *);
void se_release_device_for_hba(struct se_device *);
void se_release_vpd_for_dev(struct se_device *);
int se_free_virtual_device(struct se_device *, struct se_hba *);
@@ -104,8 +104,7 @@ void release_se_kmem_caches(void);
u32 scsi_get_new_index(scsi_index_t);
void transport_subsystem_check_init(void);
void transport_cmd_finish_abort(struct se_cmd *, int);
-void __transport_remove_task_from_execute_queue(struct se_task *,
- struct se_device *);
+void __target_remove_from_execute_list(struct se_cmd *);
unsigned char *transport_dump_cmd_direction(struct se_cmd *);
void transport_dump_dev_state(struct se_device *, char *, int *);
void transport_dump_dev_info(struct se_device *, struct se_lun *,
@@ -114,7 +113,7 @@ void transport_dump_vpd_proto_id(struct t10_vpd *, unsigned char *, int);
int transport_dump_vpd_assoc(struct t10_vpd *, unsigned char *, int);
int transport_dump_vpd_ident_type(struct t10_vpd *, unsigned char *, int);
int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int);
-bool target_stop_task(struct se_task *task, unsigned long *flags);
+bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags);
int transport_clear_lun_from_sessions(struct se_lun *);
void transport_send_task_abort(struct se_cmd *);
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index 86f0c3b5d500..85564998500a 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -193,9 +193,8 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd)
return 0;
}
-int target_scsi2_reservation_release(struct se_task *task)
+int target_scsi2_reservation_release(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
struct se_session *sess = cmd->se_sess;
struct se_portal_group *tpg = sess->se_tpg;
@@ -220,6 +219,9 @@ int target_scsi2_reservation_release(struct se_task *task)
if (dev->dev_reserved_node_acl != sess->se_node_acl)
goto out_unlock;
+ if (dev->dev_res_bin_isid != sess->sess_bin_isid)
+ goto out_unlock;
+
dev->dev_reserved_node_acl = NULL;
dev->dev_flags &= ~DF_SPC2_RESERVATIONS;
if (dev->dev_flags & DF_SPC2_RESERVATIONS_WITH_ISID) {
@@ -234,16 +236,13 @@ int target_scsi2_reservation_release(struct se_task *task)
out_unlock:
spin_unlock(&dev->dev_reservation_lock);
out:
- if (!ret) {
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
- }
+ if (!ret)
+ target_complete_cmd(cmd, GOOD);
return ret;
}
-int target_scsi2_reservation_reserve(struct se_task *task)
+int target_scsi2_reservation_reserve(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
struct se_session *sess = cmd->se_sess;
struct se_portal_group *tpg = sess->se_tpg;
@@ -304,10 +303,8 @@ int target_scsi2_reservation_reserve(struct se_task *task)
out_unlock:
spin_unlock(&dev->dev_reservation_lock);
out:
- if (!ret) {
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
- }
+ if (!ret)
+ target_complete_cmd(cmd, GOOD);
return ret;
}
@@ -500,11 +497,10 @@ static int core_scsi3_pr_seq_non_holder(
* statement.
*/
if (!ret && !other_cdb) {
-#if 0
pr_debug("Allowing explict CDB: 0x%02x for %s"
" reservation holder\n", cdb[0],
core_scsi3_pr_dump_type(pr_reg_type));
-#endif
+
return ret;
}
/*
@@ -532,14 +528,14 @@ static int core_scsi3_pr_seq_non_holder(
* as we expect registered non-reservation holding
* nexuses to issue CDBs.
*/
-#if 0
+
if (!registered_nexus) {
pr_debug("Allowing implict CDB: 0x%02x"
" for %s reservation on unregistered"
" nexus\n", cdb[0],
core_scsi3_pr_dump_type(pr_reg_type));
}
-#endif
+
return 0;
}
} else if ((reg_only) || (all_reg)) {
@@ -548,11 +544,11 @@ static int core_scsi3_pr_seq_non_holder(
* For PR_*_REG_ONLY and PR_*_ALL_REG reservations,
* allow commands from registered nexuses.
*/
-#if 0
+
pr_debug("Allowing implict CDB: 0x%02x for %s"
" reservation\n", cdb[0],
core_scsi3_pr_dump_type(pr_reg_type));
-#endif
+
return 0;
}
}
@@ -1666,12 +1662,12 @@ static int core_scsi3_decode_spec_i_port(
ret = -EINVAL;
goto out;
}
-#if 0
+
pr_debug("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u"
" tid_len: %d for %s + %s\n",
dest_tpg->se_tpg_tfo->get_fabric_name(), cmd->data_length,
tpdl, tid_len, i_str, iport_ptr);
-#endif
+
if (tid_len > tpdl) {
pr_err("SPC-3 PR SPEC_I_PT: Illegal tid_len:"
" %u for Transport ID: %s\n", tid_len, ptr);
@@ -1714,12 +1710,12 @@ static int core_scsi3_decode_spec_i_port(
ret = -EINVAL;
goto out;
}
-#if 0
+
pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s"
" dest_se_deve mapped_lun: %u\n",
dest_tpg->se_tpg_tfo->get_fabric_name(),
dest_node_acl->initiatorname, dest_se_deve->mapped_lun);
-#endif
+
/*
* Skip any TransportIDs that already have a registration for
* this target port.
@@ -3473,10 +3469,10 @@ static int core_scsi3_emulate_pro_register_and_move(
buf = transport_kmap_data_sg(cmd);
proto_ident = (buf[24] & 0x0f);
-#if 0
+
pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
" 0x%02x\n", proto_ident);
-#endif
+
if (proto_ident != dest_tf_ops->get_fabric_proto_ident(dest_se_tpg)) {
pr_err("SPC-3 PR REGISTER_AND_MOVE: Received"
" proto_ident: 0x%02x does not match ident: 0x%02x"
@@ -3575,11 +3571,11 @@ after_iport_check:
ret = -EINVAL;
goto out;
}
-#if 0
+
pr_debug("SPC-3 PR REGISTER_AND_MOVE: Found %s dest_node_acl:"
" %s from TransportID\n", dest_tf_ops->get_fabric_name(),
dest_node_acl->initiatorname);
-#endif
+
/*
* Locate the struct se_dev_entry pointer for the matching RELATIVE TARGET
* PORT IDENTIFIER.
@@ -3603,12 +3599,12 @@ after_iport_check:
ret = -EINVAL;
goto out;
}
-#if 0
+
pr_debug("SPC-3 PR REGISTER_AND_MOVE: Located %s node %s LUN"
" ACL for dest_se_deve->mapped_lun: %u\n",
dest_tf_ops->get_fabric_name(), dest_node_acl->initiatorname,
dest_se_deve->mapped_lun);
-#endif
+
/*
* A persistent reservation needs to already existing in order to
* successfully complete the REGISTER_AND_MOVE service action..
@@ -3799,9 +3795,8 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb)
/*
* See spc4r17 section 6.14 Table 170
*/
-int target_scsi3_emulate_pr_out(struct se_task *task)
+int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
unsigned char *cdb = &cmd->t_task_cdb[0];
unsigned char *buf;
u64 res_key, sa_res_key;
@@ -3941,10 +3936,8 @@ int target_scsi3_emulate_pr_out(struct se_task *task)
}
out:
- if (!ret) {
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
- }
+ if (!ret)
+ target_complete_cmd(cmd, GOOD);
return ret;
}
@@ -4299,9 +4292,8 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
return 0;
}
-int target_scsi3_emulate_pr_in(struct se_task *task)
+int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
{
- struct se_cmd *cmd = task->task_se_cmd;
int ret;
/*
@@ -4342,10 +4334,8 @@ int target_scsi3_emulate_pr_in(struct se_task *task)
break;
}
- if (!ret) {
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
- }
+ if (!ret)
+ target_complete_cmd(cmd, GOOD);
return ret;
}
diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h
index 7a233feb7e99..af6c460d886d 100644
--- a/drivers/target/target_core_pr.h
+++ b/drivers/target/target_core_pr.h
@@ -47,8 +47,8 @@ extern struct kmem_cache *t10_pr_reg_cache;
extern int core_pr_dump_initiator_port(struct t10_pr_registration *,
char *, u32);
-extern int target_scsi2_reservation_release(struct se_task *task);
-extern int target_scsi2_reservation_reserve(struct se_task *task);
+extern int target_scsi2_reservation_release(struct se_cmd *);
+extern int target_scsi2_reservation_reserve(struct se_cmd *);
extern int core_scsi3_alloc_aptpl_registration(
struct t10_reservation *, u64,
unsigned char *, unsigned char *, u32,
@@ -61,8 +61,8 @@ extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *,
extern void core_scsi3_free_all_registrations(struct se_device *);
extern unsigned char *core_scsi3_pr_dump_type(int);
-extern int target_scsi3_emulate_pr_in(struct se_task *task);
-extern int target_scsi3_emulate_pr_out(struct se_task *task);
+extern int target_scsi3_emulate_pr_in(struct se_cmd *);
+extern int target_scsi3_emulate_pr_out(struct se_cmd *);
extern int core_setup_reservations(struct se_device *, int);
#endif /* TARGET_CORE_PR_H */
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index 94c905fcbceb..4ce2cf642fce 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -663,22 +663,12 @@ static void pscsi_free_device(void *p)
kfree(pdv);
}
-static inline struct pscsi_plugin_task *PSCSI_TASK(struct se_task *task)
+static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)
{
- return container_of(task, struct pscsi_plugin_task, pscsi_task);
-}
-
-
-/* pscsi_transport_complete():
- *
- *
- */
-static int pscsi_transport_complete(struct se_task *task)
-{
- struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr;
+ struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;
struct scsi_device *sd = pdv->pdv_sd;
int result;
- struct pscsi_plugin_task *pt = PSCSI_TASK(task);
+ struct pscsi_plugin_task *pt = cmd->priv;
unsigned char *cdb = &pt->pscsi_cdb[0];
result = pt->pscsi_result;
@@ -688,12 +678,11 @@ static int pscsi_transport_complete(struct se_task *task)
*/
if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) &&
(status_byte(result) << 1) == SAM_STAT_GOOD) {
- if (!task->task_se_cmd->se_deve)
+ if (!cmd->se_deve)
goto after_mode_sense;
- if (task->task_se_cmd->se_deve->lun_flags &
- TRANSPORT_LUNFLAGS_READ_ONLY) {
- unsigned char *buf = transport_kmap_data_sg(task->task_se_cmd);
+ if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) {
+ unsigned char *buf = transport_kmap_data_sg(cmd);
if (cdb[0] == MODE_SENSE_10) {
if (!(buf[3] & 0x80))
@@ -703,7 +692,7 @@ static int pscsi_transport_complete(struct se_task *task)
buf[2] |= 0x80;
}
- transport_kunmap_data_sg(task->task_se_cmd);
+ transport_kunmap_data_sg(cmd);
}
}
after_mode_sense:
@@ -722,7 +711,6 @@ after_mode_sense:
if (((cdb[0] == MODE_SELECT) || (cdb[0] == MODE_SELECT_10)) &&
(status_byte(result) << 1) == SAM_STAT_GOOD) {
unsigned char *buf;
- struct scatterlist *sg = task->task_sg;
u16 bdl;
u32 blocksize;
@@ -757,35 +745,6 @@ after_mode_select:
return 0;
}
-static struct se_task *
-pscsi_alloc_task(unsigned char *cdb)
-{
- struct pscsi_plugin_task *pt;
-
- /*
- * Dynamically alloc cdb space, since it may be larger than
- * TCM_MAX_COMMAND_SIZE
- */
- pt = kzalloc(sizeof(*pt) + scsi_command_size(cdb), GFP_KERNEL);
- if (!pt) {
- pr_err("Unable to allocate struct pscsi_plugin_task\n");
- return NULL;
- }
-
- return &pt->pscsi_task;
-}
-
-static void pscsi_free_task(struct se_task *task)
-{
- struct pscsi_plugin_task *pt = PSCSI_TASK(task);
-
- /*
- * We do not release the bio(s) here associated with this task, as
- * this is handled by bio_put() and pscsi_bi_endio().
- */
- kfree(pt);
-}
-
enum {
Opt_scsi_host_id, Opt_scsi_channel_id, Opt_scsi_target_id,
Opt_scsi_lun_id, Opt_err
@@ -958,26 +917,25 @@ static inline struct bio *pscsi_get_bio(int sg_num)
return bio;
}
-static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg,
+static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl,
+ u32 sgl_nents, enum dma_data_direction data_direction,
struct bio **hbio)
{
- struct se_cmd *cmd = task->task_se_cmd;
- struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr;
- u32 task_sg_num = task->task_sg_nents;
+ struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;
struct bio *bio = NULL, *tbio = NULL;
struct page *page;
struct scatterlist *sg;
- u32 data_len = task->task_size, i, len, bytes, off;
- int nr_pages = (task->task_size + task_sg[0].offset +
+ u32 data_len = cmd->data_length, i, len, bytes, off;
+ int nr_pages = (cmd->data_length + sgl[0].offset +
PAGE_SIZE - 1) >> PAGE_SHIFT;
int nr_vecs = 0, rc;
- int rw = (task->task_data_direction == DMA_TO_DEVICE);
+ int rw = (data_direction == DMA_TO_DEVICE);
*hbio = NULL;
pr_debug("PSCSI: nr_pages: %d\n", nr_pages);
- for_each_sg(task_sg, sg, task_sg_num, i) {
+ for_each_sg(sgl, sg, sgl_nents, i) {
page = sg_page(sg);
off = sg->offset;
len = sg->length;
@@ -1009,7 +967,7 @@ static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg,
* Set *hbio pointer to handle the case:
* nr_pages > BIO_MAX_PAGES, where additional
* bios need to be added to complete a given
- * struct se_task
+ * command.
*/
if (!*hbio)
*hbio = tbio = bio;
@@ -1049,7 +1007,7 @@ static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg,
}
}
- return task->task_sg_nents;
+ return sgl_nents;
fail:
while (*hbio) {
bio = *hbio;
@@ -1061,52 +1019,61 @@ fail:
return -ENOMEM;
}
-static int pscsi_do_task(struct se_task *task)
+static int pscsi_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
+ u32 sgl_nents, enum dma_data_direction data_direction)
{
- struct se_cmd *cmd = task->task_se_cmd;
- struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr;
- struct pscsi_plugin_task *pt = PSCSI_TASK(task);
+ struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;
+ struct pscsi_plugin_task *pt;
struct request *req;
struct bio *hbio;
int ret;
- target_get_task_cdb(task, pt->pscsi_cdb);
+ /*
+ * Dynamically alloc cdb space, since it may be larger than
+ * TCM_MAX_COMMAND_SIZE
+ */
+ pt = kzalloc(sizeof(*pt) + scsi_command_size(cmd->t_task_cdb), GFP_KERNEL);
+ if (!pt) {
+ cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ return -ENOMEM;
+ }
+ cmd->priv = pt;
+
+ memcpy(pt->pscsi_cdb, cmd->t_task_cdb,
+ scsi_command_size(cmd->t_task_cdb));
- if (task->task_se_cmd->se_cmd_flags & SCF_SCSI_NON_DATA_CDB) {
+ if (cmd->se_cmd_flags & SCF_SCSI_NON_DATA_CDB) {
req = blk_get_request(pdv->pdv_sd->request_queue,
- (task->task_data_direction == DMA_TO_DEVICE),
+ (data_direction == DMA_TO_DEVICE),
GFP_KERNEL);
if (!req || IS_ERR(req)) {
pr_err("PSCSI: blk_get_request() failed: %ld\n",
req ? IS_ERR(req) : -ENOMEM);
cmd->scsi_sense_reason =
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
- return -ENODEV;
+ goto fail;
}
} else {
- BUG_ON(!task->task_size);
+ BUG_ON(!cmd->data_length);
- /*
- * Setup the main struct request for the task->task_sg[] payload
- */
- ret = pscsi_map_sg(task, task->task_sg, &hbio);
+ ret = pscsi_map_sg(cmd, sgl, sgl_nents, data_direction, &hbio);
if (ret < 0) {
cmd->scsi_sense_reason =
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
- return ret;
+ goto fail;
}
req = blk_make_request(pdv->pdv_sd->request_queue, hbio,
GFP_KERNEL);
if (IS_ERR(req)) {
pr_err("pSCSI: blk_make_request() failed\n");
- goto fail;
+ goto fail_free_bio;
}
}
req->cmd_type = REQ_TYPE_BLOCK_PC;
req->end_io = pscsi_req_done;
- req->end_io_data = task;
+ req->end_io_data = cmd;
req->cmd_len = scsi_command_size(pt->pscsi_cdb);
req->cmd = &pt->pscsi_cdb[0];
req->sense = &pt->pscsi_sense[0];
@@ -1118,12 +1085,12 @@ static int pscsi_do_task(struct se_task *task)
req->retries = PS_RETRY;
blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, req,
- (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG),
+ (cmd->sam_task_attr == MSG_HEAD_TAG),
pscsi_req_done);
return 0;
-fail:
+fail_free_bio:
while (hbio) {
struct bio *bio = hbio;
hbio = hbio->bi_next;
@@ -1131,16 +1098,14 @@ fail:
bio_endio(bio, 0); /* XXX: should be error */
}
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+fail:
+ kfree(pt);
return -ENOMEM;
}
-/* pscsi_get_sense_buffer():
- *
- *
- */
-static unsigned char *pscsi_get_sense_buffer(struct se_task *task)
+static unsigned char *pscsi_get_sense_buffer(struct se_cmd *cmd)
{
- struct pscsi_plugin_task *pt = PSCSI_TASK(task);
+ struct pscsi_plugin_task *pt = cmd->priv;
return pt->pscsi_sense;
}
@@ -1180,48 +1145,36 @@ static sector_t pscsi_get_blocks(struct se_device *dev)
return 0;
}
-/* pscsi_handle_SAM_STATUS_failures():
- *
- *
- */
-static inline void pscsi_process_SAM_status(
- struct se_task *task,
- struct pscsi_plugin_task *pt)
+static void pscsi_req_done(struct request *req, int uptodate)
{
- task->task_scsi_status = status_byte(pt->pscsi_result);
- if (task->task_scsi_status) {
- task->task_scsi_status <<= 1;
- pr_debug("PSCSI Status Byte exception at task: %p CDB:"
- " 0x%02x Result: 0x%08x\n", task, pt->pscsi_cdb[0],
+ struct se_cmd *cmd = req->end_io_data;
+ struct pscsi_plugin_task *pt = cmd->priv;
+
+ pt->pscsi_result = req->errors;
+ pt->pscsi_resid = req->resid_len;
+
+ cmd->scsi_status = status_byte(pt->pscsi_result) << 1;
+ if (cmd->scsi_status) {
+ pr_debug("PSCSI Status Byte exception at cmd: %p CDB:"
+ " 0x%02x Result: 0x%08x\n", cmd, pt->pscsi_cdb[0],
pt->pscsi_result);
}
switch (host_byte(pt->pscsi_result)) {
case DID_OK:
- transport_complete_task(task, (!task->task_scsi_status));
+ target_complete_cmd(cmd, cmd->scsi_status);
break;
default:
- pr_debug("PSCSI Host Byte exception at task: %p CDB:"
- " 0x%02x Result: 0x%08x\n", task, pt->pscsi_cdb[0],
+ pr_debug("PSCSI Host Byte exception at cmd: %p CDB:"
+ " 0x%02x Result: 0x%08x\n", cmd, pt->pscsi_cdb[0],
pt->pscsi_result);
- task->task_scsi_status = SAM_STAT_CHECK_CONDITION;
- task->task_se_cmd->scsi_sense_reason =
- TCM_UNSUPPORTED_SCSI_OPCODE;
- transport_complete_task(task, 0);
+ cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
+ target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
break;
}
-}
-static void pscsi_req_done(struct request *req, int uptodate)
-{
- struct se_task *task = req->end_io_data;
- struct pscsi_plugin_task *pt = PSCSI_TASK(task);
-
- pt->pscsi_result = req->errors;
- pt->pscsi_resid = req->resid_len;
-
- pscsi_process_SAM_status(task, pt);
__blk_put_request(req->q, req);
+ kfree(pt);
}
static struct se_subsystem_api pscsi_template = {
@@ -1235,9 +1188,7 @@ static struct se_subsystem_api pscsi_template = {
.create_virtdevice = pscsi_create_virtdevice,
.free_device = pscsi_free_device,
.transport_complete = pscsi_transport_complete,
- .alloc_task = pscsi_alloc_task,
- .do_task = pscsi_do_task,
- .free_task = pscsi_free_task,
+ .execute_cmd = pscsi_execute_cmd,
.check_configfs_dev_params = pscsi_check_configfs_dev_params,
.set_configfs_dev_params = pscsi_set_configfs_dev_params,
.show_configfs_dev_params = pscsi_show_configfs_dev_params,
diff --git a/drivers/target/target_core_pscsi.h b/drivers/target/target_core_pscsi.h
index 43f1c419e8e5..bc1e5e11eca0 100644
--- a/drivers/target/target_core_pscsi.h
+++ b/drivers/target/target_core_pscsi.h
@@ -22,7 +22,6 @@
#include <linux/kobject.h>
struct pscsi_plugin_task {
- struct se_task pscsi_task;
unsigned char pscsi_sense[SCSI_SENSE_BUFFERSIZE];
int pscsi_direction;
int pscsi_result;
diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c
index 8b68f7b82631..d0ceb873c0e5 100644
--- a/drivers/target/target_core_rd.c
+++ b/drivers/target/target_core_rd.c
@@ -64,9 +64,6 @@ static int rd_attach_hba(struct se_hba *hba, u32 host_id)
pr_debug("CORE_HBA[%d] - TCM Ramdisk HBA Driver %s on"
" Generic Target Core Stack %s\n", hba->hba_id,
RD_HBA_VERSION, TARGET_CORE_MOD_VERSION);
- pr_debug("CORE_HBA[%d] - Attached Ramdisk HBA: %u to Generic"
- " MaxSectors: %u\n", hba->hba_id,
- rd_host->rd_host_id, RD_MAX_SECTORS);
return 0;
}
@@ -199,10 +196,7 @@ static int rd_build_device_space(struct rd_dev *rd_dev)
return 0;
}
-static void *rd_allocate_virtdevice(
- struct se_hba *hba,
- const char *name,
- int rd_direct)
+static void *rd_allocate_virtdevice(struct se_hba *hba, const char *name)
{
struct rd_dev *rd_dev;
struct rd_host *rd_host = hba->hba_ptr;
@@ -214,25 +208,12 @@ static void *rd_allocate_virtdevice(
}
rd_dev->rd_host = rd_host;
- rd_dev->rd_direct = rd_direct;
return rd_dev;
}
-static void *rd_MEMCPY_allocate_virtdevice(struct se_hba *hba, const char *name)
-{
- return rd_allocate_virtdevice(hba, name, 0);
-}
-
-/* rd_create_virtdevice():
- *
- *
- */
-static struct se_device *rd_create_virtdevice(
- struct se_hba *hba,
- struct se_subsystem_dev *se_dev,
- void *p,
- int rd_direct)
+static struct se_device *rd_create_virtdevice(struct se_hba *hba,
+ struct se_subsystem_dev *se_dev, void *p)
{
struct se_device *dev;
struct se_dev_limits dev_limits;
@@ -247,13 +228,12 @@ static struct se_device *rd_create_virtdevice(
if (ret < 0)
goto fail;
- snprintf(prod, 16, "RAMDISK-%s", (rd_dev->rd_direct) ? "DR" : "MCP");
- snprintf(rev, 4, "%s", (rd_dev->rd_direct) ? RD_DR_VERSION :
- RD_MCP_VERSION);
+ snprintf(prod, 16, "RAMDISK-MCP");
+ snprintf(rev, 4, "%s", RD_MCP_VERSION);
dev_limits.limits.logical_block_size = RD_BLOCKSIZE;
- dev_limits.limits.max_hw_sectors = RD_MAX_SECTORS;
- dev_limits.limits.max_sectors = RD_MAX_SECTORS;
+ dev_limits.limits.max_hw_sectors = UINT_MAX;
+ dev_limits.limits.max_sectors = UINT_MAX;
dev_limits.hw_queue_depth = RD_MAX_DEVICE_QUEUE_DEPTH;
dev_limits.queue_depth = RD_DEVICE_QUEUE_DEPTH;
@@ -264,12 +244,10 @@ static struct se_device *rd_create_virtdevice(
goto fail;
rd_dev->rd_dev_id = rd_host->rd_host_dev_id_count++;
- rd_dev->rd_queue_depth = dev->queue_depth;
- pr_debug("CORE_RD[%u] - Added TCM %s Ramdisk Device ID: %u of"
+ pr_debug("CORE_RD[%u] - Added TCM MEMCPY Ramdisk Device ID: %u of"
" %u pages in %u tables, %lu total bytes\n",
- rd_host->rd_host_id, (!rd_dev->rd_direct) ? "MEMCPY" :
- "DIRECT", rd_dev->rd_dev_id, rd_dev->rd_page_count,
+ rd_host->rd_host_id, rd_dev->rd_dev_id, rd_dev->rd_page_count,
rd_dev->sg_table_count,
(unsigned long)(rd_dev->rd_page_count * PAGE_SIZE));
@@ -280,18 +258,6 @@ fail:
return ERR_PTR(ret);
}
-static struct se_device *rd_MEMCPY_create_virtdevice(
- struct se_hba *hba,
- struct se_subsystem_dev *se_dev,
- void *p)
-{
- return rd_create_virtdevice(hba, se_dev, p, 0);
-}
-
-/* rd_free_device(): (Part of se_subsystem_api_t template)
- *
- *
- */
static void rd_free_device(void *p)
{
struct rd_dev *rd_dev = p;
@@ -300,29 +266,6 @@ static void rd_free_device(void *p)
kfree(rd_dev);
}
-static inline struct rd_request *RD_REQ(struct se_task *task)
-{
- return container_of(task, struct rd_request, rd_task);
-}
-
-static struct se_task *
-rd_alloc_task(unsigned char *cdb)
-{
- struct rd_request *rd_req;
-
- rd_req = kzalloc(sizeof(struct rd_request), GFP_KERNEL);
- if (!rd_req) {
- pr_err("Unable to allocate struct rd_request\n");
- return NULL;
- }
-
- return &rd_req->rd_task;
-}
-
-/* rd_get_sg_table():
- *
- *
- */
static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
{
u32 i;
@@ -341,31 +284,41 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
return NULL;
}
-static int rd_MEMCPY(struct rd_request *req, u32 read_rd)
+static int rd_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
+ u32 sgl_nents, enum dma_data_direction data_direction)
{
- struct se_task *task = &req->rd_task;
- struct rd_dev *dev = req->rd_task.task_se_cmd->se_dev->dev_ptr;
+ struct se_device *se_dev = cmd->se_dev;
+ struct rd_dev *dev = se_dev->dev_ptr;
struct rd_dev_sg_table *table;
struct scatterlist *rd_sg;
struct sg_mapping_iter m;
- u32 rd_offset = req->rd_offset;
+ u32 rd_offset;
+ u32 rd_size;
+ u32 rd_page;
u32 src_len;
+ u64 tmp;
+
+ tmp = cmd->t_task_lba * se_dev->se_sub_dev->se_dev_attrib.block_size;
+ rd_offset = do_div(tmp, PAGE_SIZE);
+ rd_page = tmp;
+ rd_size = cmd->data_length;
- table = rd_get_sg_table(dev, req->rd_page);
+ table = rd_get_sg_table(dev, rd_page);
if (!table)
return -EINVAL;
- rd_sg = &table->sg_table[req->rd_page - table->page_start_offset];
+ rd_sg = &table->sg_table[rd_page - table->page_start_offset];
pr_debug("RD[%u]: %s LBA: %llu, Size: %u Page: %u, Offset: %u\n",
- dev->rd_dev_id, read_rd ? "Read" : "Write",
- task->task_lba, req->rd_size, req->rd_page,
- rd_offset);
+ dev->rd_dev_id,
+ data_direction == DMA_FROM_DEVICE ? "Read" : "Write",
+ cmd->t_task_lba, rd_size, rd_page, rd_offset);
src_len = PAGE_SIZE - rd_offset;
- sg_miter_start(&m, task->task_sg, task->task_sg_nents,
- read_rd ? SG_MITER_TO_SG : SG_MITER_FROM_SG);
- while (req->rd_size) {
+ sg_miter_start(&m, sgl, sgl_nents,
+ data_direction == DMA_FROM_DEVICE ?
+ SG_MITER_TO_SG : SG_MITER_FROM_SG);
+ while (rd_size) {
u32 len;
void *rd_addr;
@@ -375,13 +328,13 @@ static int rd_MEMCPY(struct rd_request *req, u32 read_rd)
rd_addr = sg_virt(rd_sg) + rd_offset;
- if (read_rd)
+ if (data_direction == DMA_FROM_DEVICE)
memcpy(m.addr, rd_addr, len);
else
memcpy(rd_addr, m.addr, len);
- req->rd_size -= len;
- if (!req->rd_size)
+ rd_size -= len;
+ if (!rd_size)
continue;
src_len -= len;
@@ -391,15 +344,15 @@ static int rd_MEMCPY(struct rd_request *req, u32 read_rd)
}
/* rd page completed, next one please */
- req->rd_page++;
+ rd_page++;
rd_offset = 0;
src_len = PAGE_SIZE;
- if (req->rd_page <= table->page_end_offset) {
+ if (rd_page <= table->page_end_offset) {
rd_sg++;
continue;
}
- table = rd_get_sg_table(dev, req->rd_page);
+ table = rd_get_sg_table(dev, rd_page);
if (!table) {
sg_miter_stop(&m);
return -EINVAL;
@@ -409,43 +362,11 @@ static int rd_MEMCPY(struct rd_request *req, u32 read_rd)
rd_sg = table->sg_table;
}
sg_miter_stop(&m);
- return 0;
-}
-/* rd_MEMCPY_do_task(): (Part of se_subsystem_api_t template)
- *
- *
- */
-static int rd_MEMCPY_do_task(struct se_task *task)
-{
- struct se_device *dev = task->task_se_cmd->se_dev;
- struct rd_request *req = RD_REQ(task);
- u64 tmp;
- int ret;
-
- tmp = task->task_lba * dev->se_sub_dev->se_dev_attrib.block_size;
- req->rd_offset = do_div(tmp, PAGE_SIZE);
- req->rd_page = tmp;
- req->rd_size = task->task_size;
-
- ret = rd_MEMCPY(req, task->task_data_direction == DMA_FROM_DEVICE);
- if (ret != 0)
- return ret;
-
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
+ target_complete_cmd(cmd, SAM_STAT_GOOD);
return 0;
}
-/* rd_free_task(): (Part of se_subsystem_api_t template)
- *
- *
- */
-static void rd_free_task(struct se_task *task)
-{
- kfree(RD_REQ(task));
-}
-
enum {
Opt_rd_pages, Opt_err
};
@@ -512,9 +433,8 @@ static ssize_t rd_show_configfs_dev_params(
char *b)
{
struct rd_dev *rd_dev = se_dev->se_dev_su_ptr;
- ssize_t bl = sprintf(b, "TCM RamDisk ID: %u RamDisk Makeup: %s\n",
- rd_dev->rd_dev_id, (rd_dev->rd_direct) ?
- "rd_direct" : "rd_mcp");
+ ssize_t bl = sprintf(b, "TCM RamDisk ID: %u RamDisk Makeup: rd_mcp\n",
+ rd_dev->rd_dev_id);
bl += sprintf(b + bl, " PAGES/PAGE_SIZE: %u*%lu"
" SG_table_count: %u\n", rd_dev->rd_page_count,
PAGE_SIZE, rd_dev->sg_table_count);
@@ -545,12 +465,10 @@ static struct se_subsystem_api rd_mcp_template = {
.transport_type = TRANSPORT_PLUGIN_VHBA_VDEV,
.attach_hba = rd_attach_hba,
.detach_hba = rd_detach_hba,
- .allocate_virtdevice = rd_MEMCPY_allocate_virtdevice,
- .create_virtdevice = rd_MEMCPY_create_virtdevice,
+ .allocate_virtdevice = rd_allocate_virtdevice,
+ .create_virtdevice = rd_create_virtdevice,
.free_device = rd_free_device,
- .alloc_task = rd_alloc_task,
- .do_task = rd_MEMCPY_do_task,
- .free_task = rd_free_task,
+ .execute_cmd = rd_execute_cmd,
.check_configfs_dev_params = rd_check_configfs_dev_params,
.set_configfs_dev_params = rd_set_configfs_dev_params,
.show_configfs_dev_params = rd_show_configfs_dev_params,
diff --git a/drivers/target/target_core_rd.h b/drivers/target/target_core_rd.h
index 784e56a04100..21458125fe51 100644
--- a/drivers/target/target_core_rd.h
+++ b/drivers/target/target_core_rd.h
@@ -2,7 +2,6 @@
#define TARGET_CORE_RD_H
#define RD_HBA_VERSION "v4.0"
-#define RD_DR_VERSION "4.0"
#define RD_MCP_VERSION "4.0"
/* Largest piece of memory kmalloc can allocate */
@@ -10,28 +9,11 @@
#define RD_DEVICE_QUEUE_DEPTH 32
#define RD_MAX_DEVICE_QUEUE_DEPTH 128
#define RD_BLOCKSIZE 512
-#define RD_MAX_SECTORS 1024
/* Used in target_core_init_configfs() for virtual LUN 0 access */
int __init rd_module_init(void);
void rd_module_exit(void);
-#define RRF_EMULATE_CDB 0x01
-#define RRF_GOT_LBA 0x02
-
-struct rd_request {
- struct se_task rd_task;
-
- /* Offset from start of page */
- u32 rd_offset;
- /* Starting page in Ramdisk for request */
- u32 rd_page;
- /* Total number of pages needed for request */
- u32 rd_page_count;
- /* Scatterlist count */
- u32 rd_size;
-} ____cacheline_aligned;
-
struct rd_dev_sg_table {
u32 page_start_offset;
u32 page_end_offset;
@@ -42,7 +24,6 @@ struct rd_dev_sg_table {
#define RDF_HAS_PAGE_COUNT 0x01
struct rd_dev {
- int rd_direct;
u32 rd_flags;
/* Unique Ramdisk Device ID in Ramdisk HBA */
u32 rd_dev_id;
@@ -50,7 +31,6 @@ struct rd_dev {
u32 rd_page_count;
/* Number of SG tables in sg_table_array */
u32 sg_table_count;
- u32 rd_queue_depth;
/* Array of rd_dev_sg_table_t containing scatterlists */
struct rd_dev_sg_table *sg_table_array;
/* Ramdisk HBA device is connected to */
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c
index f015839aef89..84caf1bed9a3 100644
--- a/drivers/target/target_core_tmr.c
+++ b/drivers/target/target_core_tmr.c
@@ -244,7 +244,7 @@ static void core_tmr_drain_tmr_list(
}
}
-static void core_tmr_drain_task_list(
+static void core_tmr_drain_state_list(
struct se_device *dev,
struct se_cmd *prout_cmd,
struct se_node_acl *tmr_nacl,
@@ -252,12 +252,13 @@ static void core_tmr_drain_task_list(
struct list_head *preempt_and_abort_list)
{
LIST_HEAD(drain_task_list);
- struct se_cmd *cmd;
- struct se_task *task, *task_tmp;
+ struct se_cmd *cmd, *next;
unsigned long flags;
int fe_count;
+
/*
- * Complete outstanding struct se_task CDBs with TASK_ABORTED SAM status.
+ * Complete outstanding commands with TASK_ABORTED SAM status.
+ *
* This is following sam4r17, section 5.6 Aborting commands, Table 38
* for TMR LUN_RESET:
*
@@ -278,56 +279,43 @@ static void core_tmr_drain_task_list(
* in the Control Mode Page.
*/
spin_lock_irqsave(&dev->execute_task_lock, flags);
- list_for_each_entry_safe(task, task_tmp, &dev->state_task_list,
- t_state_list) {
- if (!task->task_se_cmd) {
- pr_err("task->task_se_cmd is NULL!\n");
- continue;
- }
- cmd = task->task_se_cmd;
-
+ list_for_each_entry_safe(cmd, next, &dev->state_list, state_list) {
/*
* For PREEMPT_AND_ABORT usage, only process commands
* with a matching reservation key.
*/
if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd))
continue;
+
/*
* Not aborting PROUT PREEMPT_AND_ABORT CDB..
*/
if (prout_cmd == cmd)
continue;
- list_move_tail(&task->t_state_list, &drain_task_list);
- task->t_state_active = false;
- /*
- * Remove from task execute list before processing drain_task_list
- */
- if (!list_empty(&task->t_execute_list))
- __transport_remove_task_from_execute_queue(task, dev);
+ list_move_tail(&cmd->state_list, &drain_task_list);
+ cmd->state_active = false;
+
+ if (!list_empty(&cmd->execute_list))
+ __target_remove_from_execute_list(cmd);
}
spin_unlock_irqrestore(&dev->execute_task_lock, flags);
while (!list_empty(&drain_task_list)) {
- task = list_entry(drain_task_list.next, struct se_task, t_state_list);
- list_del(&task->t_state_list);
- cmd = task->task_se_cmd;
+ cmd = list_entry(drain_task_list.next, struct se_cmd, state_list);
+ list_del(&cmd->state_list);
- pr_debug("LUN_RESET: %s cmd: %p task: %p"
+ pr_debug("LUN_RESET: %s cmd: %p"
" ITT/CmdSN: 0x%08x/0x%08x, i_state: %d, t_state: %d"
"cdb: 0x%02x\n",
- (preempt_and_abort_list) ? "Preempt" : "", cmd, task,
+ (preempt_and_abort_list) ? "Preempt" : "", cmd,
cmd->se_tfo->get_task_tag(cmd), 0,
cmd->se_tfo->get_cmd_state(cmd), cmd->t_state,
cmd->t_task_cdb[0]);
pr_debug("LUN_RESET: ITT[0x%08x] - pr_res_key: 0x%016Lx"
- " t_task_cdbs: %d t_task_cdbs_left: %d"
- " t_task_cdbs_sent: %d -- CMD_T_ACTIVE: %d"
+ " -- CMD_T_ACTIVE: %d"
" CMD_T_STOP: %d CMD_T_SENT: %d\n",
cmd->se_tfo->get_task_tag(cmd), cmd->pr_res_key,
- cmd->t_task_list_num,
- atomic_read(&cmd->t_task_cdbs_left),
- atomic_read(&cmd->t_task_cdbs_sent),
(cmd->transport_state & CMD_T_ACTIVE) != 0,
(cmd->transport_state & CMD_T_STOP) != 0,
(cmd->transport_state & CMD_T_SENT) != 0);
@@ -343,20 +331,13 @@ static void core_tmr_drain_task_list(
cancel_work_sync(&cmd->work);
spin_lock_irqsave(&cmd->t_state_lock, flags);
- target_stop_task(task, &flags);
+ target_stop_cmd(cmd, &flags);
- if (!atomic_dec_and_test(&cmd->t_task_cdbs_ex_left)) {
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- pr_debug("LUN_RESET: Skipping task: %p, dev: %p for"
- " t_task_cdbs_ex_left: %d\n", task, dev,
- atomic_read(&cmd->t_task_cdbs_ex_left));
- continue;
- }
fe_count = atomic_read(&cmd->t_fe_count);
if (!(cmd->transport_state & CMD_T_ACTIVE)) {
pr_debug("LUN_RESET: got CMD_T_ACTIVE for"
- " task: %p, t_fe_count: %d dev: %p\n", task,
+ " cdb: %p, t_fe_count: %d dev: %p\n", cmd,
fe_count, dev);
cmd->transport_state |= CMD_T_ABORTED;
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
@@ -364,8 +345,8 @@ static void core_tmr_drain_task_list(
core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
continue;
}
- pr_debug("LUN_RESET: Got !CMD_T_ACTIVE for task: %p,"
- " t_fe_count: %d dev: %p\n", task, fe_count, dev);
+ pr_debug("LUN_RESET: Got !CMD_T_ACTIVE for cdb: %p,"
+ " t_fe_count: %d dev: %p\n", cmd, fe_count, dev);
cmd->transport_state |= CMD_T_ABORTED;
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
@@ -384,13 +365,11 @@ static void core_tmr_drain_cmd_list(
struct se_queue_obj *qobj = &dev->dev_queue_obj;
struct se_cmd *cmd, *tcmd;
unsigned long flags;
+
/*
- * Release all commands remaining in the struct se_device cmd queue.
+ * Release all commands remaining in the per-device command queue.
*
- * This follows the same logic as above for the struct se_device
- * struct se_task state list, where commands are returned with
- * TASK_ABORTED status, if there is an outstanding $FABRIC_MOD
- * reference, otherwise the struct se_cmd is released.
+ * This follows the same logic as above for the state list.
*/
spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
list_for_each_entry_safe(cmd, tcmd, &qobj->qobj_list, se_queue_node) {
@@ -466,7 +445,7 @@ int core_tmr_lun_reset(
dev->transport->name, tas);
core_tmr_drain_tmr_list(dev, tmr, preempt_and_abort_list);
- core_tmr_drain_task_list(dev, prout_cmd, tmr_nacl, tas,
+ core_tmr_drain_state_list(dev, prout_cmd, tmr_nacl, tas,
preempt_and_abort_list);
core_tmr_drain_cmd_list(dev, prout_cmd, tmr_nacl, tas,
preempt_and_abort_list);
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index e320ec24aa1b..8bd58e284185 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -153,10 +153,7 @@ void core_tpg_add_node_to_devs(
* demo_mode_write_protect is ON, or READ_ONLY;
*/
if (!tpg->se_tpg_tfo->tpg_check_demo_mode_write_protect(tpg)) {
- if (dev->dev_flags & DF_READ_ONLY)
- lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
- else
- lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
+ lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
} else {
/*
* Allow only optical drives to issue R/W in default RO
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 443704f84fd5..b05fdc0c05d3 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -72,7 +72,6 @@ static int __transport_execute_tasks(struct se_device *dev, struct se_cmd *);
static void transport_complete_task_attr(struct se_cmd *cmd);
static void transport_handle_queue_full(struct se_cmd *cmd,
struct se_device *dev);
-static void transport_free_dev_tasks(struct se_cmd *cmd);
static int transport_generic_get_mem(struct se_cmd *cmd);
static void transport_put_cmd(struct se_cmd *cmd);
static void transport_remove_cmd_from_queue(struct se_cmd *cmd);
@@ -331,9 +330,9 @@ void target_get_session(struct se_session *se_sess)
}
EXPORT_SYMBOL(target_get_session);
-int target_put_session(struct se_session *se_sess)
+void target_put_session(struct se_session *se_sess)
{
- return kref_put(&se_sess->sess_kref, target_release_session);
+ kref_put(&se_sess->sess_kref, target_release_session);
}
EXPORT_SYMBOL(target_put_session);
@@ -444,31 +443,23 @@ EXPORT_SYMBOL(transport_deregister_session);
/*
* Called with cmd->t_state_lock held.
*/
-static void transport_all_task_dev_remove_state(struct se_cmd *cmd)
+static void target_remove_from_state_list(struct se_cmd *cmd)
{
struct se_device *dev = cmd->se_dev;
- struct se_task *task;
unsigned long flags;
if (!dev)
return;
- list_for_each_entry(task, &cmd->t_task_list, t_list) {
- if (task->task_flags & TF_ACTIVE)
- continue;
-
- spin_lock_irqsave(&dev->execute_task_lock, flags);
- if (task->t_state_active) {
- pr_debug("Removed ITT: 0x%08x dev: %p task[%p]\n",
- cmd->se_tfo->get_task_tag(cmd), dev, task);
+ if (cmd->transport_state & CMD_T_BUSY)
+ return;
- list_del(&task->t_state_list);
- atomic_dec(&cmd->t_task_cdbs_ex_left);
- task->t_state_active = false;
- }
- spin_unlock_irqrestore(&dev->execute_task_lock, flags);
+ spin_lock_irqsave(&dev->execute_task_lock, flags);
+ if (cmd->state_active) {
+ list_del(&cmd->state_list);
+ cmd->state_active = false;
}
-
+ spin_unlock_irqrestore(&dev->execute_task_lock, flags);
}
/* transport_cmd_check_stop():
@@ -497,7 +488,7 @@ static int transport_cmd_check_stop(
cmd->transport_state &= ~CMD_T_ACTIVE;
if (transport_off == 2)
- transport_all_task_dev_remove_state(cmd);
+ target_remove_from_state_list(cmd);
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
complete(&cmd->transport_lun_stop_comp);
@@ -513,7 +504,7 @@ static int transport_cmd_check_stop(
cmd->se_tfo->get_task_tag(cmd));
if (transport_off == 2)
- transport_all_task_dev_remove_state(cmd);
+ target_remove_from_state_list(cmd);
/*
* Clear struct se_cmd->se_lun before the transport_off == 2 handoff
@@ -529,7 +520,7 @@ static int transport_cmd_check_stop(
if (transport_off) {
cmd->transport_state &= ~CMD_T_ACTIVE;
if (transport_off == 2) {
- transport_all_task_dev_remove_state(cmd);
+ target_remove_from_state_list(cmd);
/*
* Clear struct se_cmd->se_lun before the transport_off == 2
* handoff to fabric module.
@@ -577,7 +568,7 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd)
spin_lock_irqsave(&cmd->t_state_lock, flags);
if (cmd->transport_state & CMD_T_DEV_ACTIVE) {
cmd->transport_state &= ~CMD_T_DEV_ACTIVE;
- transport_all_task_dev_remove_state(cmd);
+ target_remove_from_state_list(cmd);
}
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
@@ -669,29 +660,6 @@ static void transport_remove_cmd_from_queue(struct se_cmd *cmd)
spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
}
-/*
- * Completion function used by TCM subsystem plugins (such as FILEIO)
- * for queueing up response from struct se_subsystem_api->do_task()
- */
-void transport_complete_sync_cache(struct se_cmd *cmd, int good)
-{
- struct se_task *task = list_entry(cmd->t_task_list.next,
- struct se_task, t_list);
-
- if (good) {
- cmd->scsi_status = SAM_STAT_GOOD;
- task->task_scsi_status = GOOD;
- } else {
- task->task_scsi_status = SAM_STAT_CHECK_CONDITION;
- task->task_se_cmd->scsi_sense_reason =
- TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-
- }
-
- transport_complete_task(task, good);
-}
-EXPORT_SYMBOL(transport_complete_sync_cache);
-
static void target_complete_failure_work(struct work_struct *work)
{
struct se_cmd *cmd = container_of(work, struct se_cmd, work);
@@ -699,40 +667,32 @@ static void target_complete_failure_work(struct work_struct *work)
transport_generic_request_failure(cmd);
}
-/* transport_complete_task():
- *
- * Called from interrupt and non interrupt context depending
- * on the transport plugin.
- */
-void transport_complete_task(struct se_task *task, int success)
+void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
{
- struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
+ int success = scsi_status == GOOD;
unsigned long flags;
+ cmd->scsi_status = scsi_status;
+
+
spin_lock_irqsave(&cmd->t_state_lock, flags);
- task->task_flags &= ~TF_ACTIVE;
+ cmd->transport_state &= ~CMD_T_BUSY;
- /*
- * See if any sense data exists, if so set the TASK_SENSE flag.
- * Also check for any other post completion work that needs to be
- * done by the plugins.
- */
if (dev && dev->transport->transport_complete) {
- if (dev->transport->transport_complete(task) != 0) {
+ if (dev->transport->transport_complete(cmd,
+ cmd->t_data_sg) != 0) {
cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE;
- task->task_flags |= TF_HAS_SENSE;
success = 1;
}
}
/*
- * See if we are waiting for outstanding struct se_task
- * to complete for an exception condition
+ * See if we are waiting to complete for an exception condition.
*/
- if (task->task_flags & TF_REQUEST_STOP) {
+ if (cmd->transport_state & CMD_T_REQUEST_STOP) {
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- complete(&task->task_stop_comp);
+ complete(&cmd->task_stop_comp);
return;
}
@@ -740,15 +700,6 @@ void transport_complete_task(struct se_task *task, int success)
cmd->transport_state |= CMD_T_FAILED;
/*
- * Decrement the outstanding t_task_cdbs_left count. The last
- * struct se_task from struct se_cmd will complete itself into the
- * device queue depending upon int success.
- */
- if (!atomic_dec_and_test(&cmd->t_task_cdbs_left)) {
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- return;
- }
- /*
* Check for case where an explict ABORT_TASK has been received
* and transport_wait_for_tasks() will be waiting for completion..
*/
@@ -770,157 +721,77 @@ void transport_complete_task(struct se_task *task, int success)
queue_work(target_completion_wq, &cmd->work);
}
-EXPORT_SYMBOL(transport_complete_task);
-
-/*
- * Called by transport_add_tasks_from_cmd() once a struct se_cmd's
- * struct se_task list are ready to be added to the active execution list
- * struct se_device
+EXPORT_SYMBOL(target_complete_cmd);
- * Called with se_dev_t->execute_task_lock called.
- */
-static inline int transport_add_task_check_sam_attr(
- struct se_task *task,
- struct se_task *task_prev,
- struct se_device *dev)
+static void target_add_to_state_list(struct se_cmd *cmd)
{
- /*
- * No SAM Task attribute emulation enabled, add to tail of
- * execution queue
- */
- if (dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED) {
- list_add_tail(&task->t_execute_list, &dev->execute_task_list);
- return 0;
- }
- /*
- * HEAD_OF_QUEUE attribute for received CDB, which means
- * the first task that is associated with a struct se_cmd goes to
- * head of the struct se_device->execute_task_list, and task_prev
- * after that for each subsequent task
- */
- if (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG) {
- list_add(&task->t_execute_list,
- (task_prev != NULL) ?
- &task_prev->t_execute_list :
- &dev->execute_task_list);
-
- pr_debug("Set HEAD_OF_QUEUE for task CDB: 0x%02x"
- " in execution queue\n",
- task->task_se_cmd->t_task_cdb[0]);
- return 1;
+ struct se_device *dev = cmd->se_dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->execute_task_lock, flags);
+ if (!cmd->state_active) {
+ list_add_tail(&cmd->state_list, &dev->state_list);
+ cmd->state_active = true;
}
- /*
- * For ORDERED, SIMPLE or UNTAGGED attribute tasks once they have been
- * transitioned from Dermant -> Active state, and are added to the end
- * of the struct se_device->execute_task_list
- */
- list_add_tail(&task->t_execute_list, &dev->execute_task_list);
- return 0;
+ spin_unlock_irqrestore(&dev->execute_task_lock, flags);
}
-/* __transport_add_task_to_execute_queue():
- *
- * Called with se_dev_t->execute_task_lock called.
- */
-static void __transport_add_task_to_execute_queue(
- struct se_task *task,
- struct se_task *task_prev,
- struct se_device *dev)
+static void __target_add_to_execute_list(struct se_cmd *cmd)
{
- int head_of_queue;
-
- head_of_queue = transport_add_task_check_sam_attr(task, task_prev, dev);
- atomic_inc(&dev->execute_tasks);
+ struct se_device *dev = cmd->se_dev;
+ bool head_of_queue = false;
- if (task->t_state_active)
+ if (!list_empty(&cmd->execute_list))
return;
- /*
- * Determine if this task needs to go to HEAD_OF_QUEUE for the
- * state list as well. Running with SAM Task Attribute emulation
- * will always return head_of_queue == 0 here
- */
- if (head_of_queue)
- list_add(&task->t_state_list, (task_prev) ?
- &task_prev->t_state_list :
- &dev->state_task_list);
- else
- list_add_tail(&task->t_state_list, &dev->state_task_list);
- task->t_state_active = true;
+ if (dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED &&
+ cmd->sam_task_attr == MSG_HEAD_TAG)
+ head_of_queue = true;
- pr_debug("Added ITT: 0x%08x task[%p] to dev: %p\n",
- task->task_se_cmd->se_tfo->get_task_tag(task->task_se_cmd),
- task, dev);
-}
+ if (head_of_queue)
+ list_add(&cmd->execute_list, &dev->execute_list);
+ else
+ list_add_tail(&cmd->execute_list, &dev->execute_list);
-static void transport_add_tasks_to_state_queue(struct se_cmd *cmd)
-{
- struct se_device *dev = cmd->se_dev;
- struct se_task *task;
- unsigned long flags;
+ atomic_inc(&dev->execute_tasks);
- spin_lock_irqsave(&cmd->t_state_lock, flags);
- list_for_each_entry(task, &cmd->t_task_list, t_list) {
- spin_lock(&dev->execute_task_lock);
- if (!task->t_state_active) {
- list_add_tail(&task->t_state_list,
- &dev->state_task_list);
- task->t_state_active = true;
-
- pr_debug("Added ITT: 0x%08x task[%p] to dev: %p\n",
- task->task_se_cmd->se_tfo->get_task_tag(
- task->task_se_cmd), task, dev);
- }
- spin_unlock(&dev->execute_task_lock);
- }
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-}
+ if (cmd->state_active)
+ return;
-static void __transport_add_tasks_from_cmd(struct se_cmd *cmd)
-{
- struct se_device *dev = cmd->se_dev;
- struct se_task *task, *task_prev = NULL;
+ if (head_of_queue)
+ list_add(&cmd->state_list, &dev->state_list);
+ else
+ list_add_tail(&cmd->state_list, &dev->state_list);
- list_for_each_entry(task, &cmd->t_task_list, t_list) {
- if (!list_empty(&task->t_execute_list))
- continue;
- /*
- * __transport_add_task_to_execute_queue() handles the
- * SAM Task Attribute emulation if enabled
- */
- __transport_add_task_to_execute_queue(task, task_prev, dev);
- task_prev = task;
- }
+ cmd->state_active = true;
}
-static void transport_add_tasks_from_cmd(struct se_cmd *cmd)
+static void target_add_to_execute_list(struct se_cmd *cmd)
{
unsigned long flags;
struct se_device *dev = cmd->se_dev;
spin_lock_irqsave(&dev->execute_task_lock, flags);
- __transport_add_tasks_from_cmd(cmd);
+ __target_add_to_execute_list(cmd);
spin_unlock_irqrestore(&dev->execute_task_lock, flags);
}
-void __transport_remove_task_from_execute_queue(struct se_task *task,
- struct se_device *dev)
+void __target_remove_from_execute_list(struct se_cmd *cmd)
{
- list_del_init(&task->t_execute_list);
- atomic_dec(&dev->execute_tasks);
+ list_del_init(&cmd->execute_list);
+ atomic_dec(&cmd->se_dev->execute_tasks);
}
-static void transport_remove_task_from_execute_queue(
- struct se_task *task,
- struct se_device *dev)
+static void target_remove_from_execute_list(struct se_cmd *cmd)
{
+ struct se_device *dev = cmd->se_dev;
unsigned long flags;
- if (WARN_ON(list_empty(&task->t_execute_list)))
+ if (WARN_ON(list_empty(&cmd->execute_list)))
return;
spin_lock_irqsave(&dev->execute_task_lock, flags);
- __transport_remove_task_from_execute_queue(task, dev);
+ __target_remove_from_execute_list(cmd);
spin_unlock_irqrestore(&dev->execute_task_lock, flags);
}
@@ -999,8 +870,9 @@ void transport_dump_dev_state(
*bl += sprintf(b + *bl, " Execute/Max Queue Depth: %d/%d",
atomic_read(&dev->execute_tasks), dev->queue_depth);
- *bl += sprintf(b + *bl, " SectorSize: %u MaxSectors: %u\n",
- dev->se_sub_dev->se_dev_attrib.block_size, dev->se_sub_dev->se_dev_attrib.max_sectors);
+ *bl += sprintf(b + *bl, " SectorSize: %u HwMaxSectors: %u\n",
+ dev->se_sub_dev->se_dev_attrib.block_size,
+ dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
*bl += sprintf(b + *bl, " ");
}
@@ -1344,9 +1216,9 @@ struct se_device *transport_add_device_to_core_hba(
INIT_LIST_HEAD(&dev->dev_list);
INIT_LIST_HEAD(&dev->dev_sep_list);
INIT_LIST_HEAD(&dev->dev_tmr_list);
- INIT_LIST_HEAD(&dev->execute_task_list);
+ INIT_LIST_HEAD(&dev->execute_list);
INIT_LIST_HEAD(&dev->delayed_cmd_list);
- INIT_LIST_HEAD(&dev->state_task_list);
+ INIT_LIST_HEAD(&dev->state_list);
INIT_LIST_HEAD(&dev->qf_cmd_list);
spin_lock_init(&dev->execute_task_lock);
spin_lock_init(&dev->delayed_cmd_lock);
@@ -1457,6 +1329,7 @@ static inline void transport_generic_prepare_cdb(
case VERIFY_16: /* SBC - VRProtect */
case WRITE_VERIFY: /* SBC - VRProtect */
case WRITE_VERIFY_12: /* SBC - VRProtect */
+ case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */
break;
default:
cdb[1] &= 0x1f; /* clear logical unit number */
@@ -1464,29 +1337,6 @@ static inline void transport_generic_prepare_cdb(
}
}
-static struct se_task *
-transport_generic_get_task(struct se_cmd *cmd,
- enum dma_data_direction data_direction)
-{
- struct se_task *task;
- struct se_device *dev = cmd->se_dev;
-
- task = dev->transport->alloc_task(cmd->t_task_cdb);
- if (!task) {
- pr_err("Unable to allocate struct se_task\n");
- return NULL;
- }
-
- INIT_LIST_HEAD(&task->t_list);
- INIT_LIST_HEAD(&task->t_execute_list);
- INIT_LIST_HEAD(&task->t_state_list);
- init_completion(&task->task_stop_comp);
- task->task_se_cmd = cmd;
- task->task_data_direction = data_direction;
-
- return task;
-}
-
static int transport_generic_cmd_sequencer(struct se_cmd *, unsigned char *);
/*
@@ -1507,11 +1357,13 @@ void transport_init_se_cmd(
INIT_LIST_HEAD(&cmd->se_qf_node);
INIT_LIST_HEAD(&cmd->se_queue_node);
INIT_LIST_HEAD(&cmd->se_cmd_list);
- INIT_LIST_HEAD(&cmd->t_task_list);
+ INIT_LIST_HEAD(&cmd->execute_list);
+ INIT_LIST_HEAD(&cmd->state_list);
init_completion(&cmd->transport_lun_fe_stop_comp);
init_completion(&cmd->transport_lun_stop_comp);
init_completion(&cmd->t_transport_stop_comp);
init_completion(&cmd->cmd_wait_comp);
+ init_completion(&cmd->task_stop_comp);
spin_lock_init(&cmd->t_state_lock);
cmd->transport_state = CMD_T_DEV_ACTIVE;
@@ -1521,6 +1373,8 @@ void transport_init_se_cmd(
cmd->data_direction = data_direction;
cmd->sam_task_attr = task_attr;
cmd->sense_buffer = sense_buffer;
+
+ cmd->state_active = false;
}
EXPORT_SYMBOL(transport_init_se_cmd);
@@ -1550,11 +1404,11 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd)
return 0;
}
-/* transport_generic_allocate_tasks():
+/* target_setup_cmd_from_cdb():
*
* Called from fabric RX Thread.
*/
-int transport_generic_allocate_tasks(
+int target_setup_cmd_from_cdb(
struct se_cmd *cmd,
unsigned char *cdb)
{
@@ -1620,7 +1474,7 @@ int transport_generic_allocate_tasks(
spin_unlock(&cmd->se_lun->lun_sep_lock);
return 0;
}
-EXPORT_SYMBOL(transport_generic_allocate_tasks);
+EXPORT_SYMBOL(target_setup_cmd_from_cdb);
/*
* Used by fabric module frontends to queue tasks directly.
@@ -1701,6 +1555,8 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
*/
transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess,
data_length, data_dir, task_attr, sense);
+ if (flags & TARGET_SCF_UNKNOWN_SIZE)
+ se_cmd->unknown_data_length = 1;
/*
* Obtain struct se_cmd->cmd_kref reference and add new cmd to
* se_sess->sess_cmd_list. A second kref_get here is necessary
@@ -1726,11 +1582,18 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
* Sanitize CDBs via transport_generic_cmd_sequencer() and
* allocate the necessary tasks to complete the received CDB+data
*/
- rc = transport_generic_allocate_tasks(se_cmd, cdb);
+ rc = target_setup_cmd_from_cdb(se_cmd, cdb);
if (rc != 0) {
transport_generic_request_failure(se_cmd);
return;
}
+
+ /*
+ * Check if we need to delay processing because of ALUA
+ * Active/NonOptimized primary access state..
+ */
+ core_alua_check_nonop_delay(se_cmd);
+
/*
* Dispatch se_cmd descriptor to se_lun->lun_se_dev backend
* for immediate execution of READs, otherwise wait for
@@ -1872,72 +1735,30 @@ int transport_generic_handle_tmr(
EXPORT_SYMBOL(transport_generic_handle_tmr);
/*
- * If the task is active, request it to be stopped and sleep until it
+ * If the cmd is active, request it to be stopped and sleep until it
* has completed.
*/
-bool target_stop_task(struct se_task *task, unsigned long *flags)
+bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags)
{
- struct se_cmd *cmd = task->task_se_cmd;
bool was_active = false;
- if (task->task_flags & TF_ACTIVE) {
- task->task_flags |= TF_REQUEST_STOP;
+ if (cmd->transport_state & CMD_T_BUSY) {
+ cmd->transport_state |= CMD_T_REQUEST_STOP;
spin_unlock_irqrestore(&cmd->t_state_lock, *flags);
- pr_debug("Task %p waiting to complete\n", task);
- wait_for_completion(&task->task_stop_comp);
- pr_debug("Task %p stopped successfully\n", task);
+ pr_debug("cmd %p waiting to complete\n", cmd);
+ wait_for_completion(&cmd->task_stop_comp);
+ pr_debug("cmd %p stopped successfully\n", cmd);
spin_lock_irqsave(&cmd->t_state_lock, *flags);
- atomic_dec(&cmd->t_task_cdbs_left);
- task->task_flags &= ~(TF_ACTIVE | TF_REQUEST_STOP);
+ cmd->transport_state &= ~CMD_T_REQUEST_STOP;
+ cmd->transport_state &= ~CMD_T_BUSY;
was_active = true;
}
return was_active;
}
-static int transport_stop_tasks_for_cmd(struct se_cmd *cmd)
-{
- struct se_task *task, *task_tmp;
- unsigned long flags;
- int ret = 0;
-
- pr_debug("ITT[0x%08x] - Stopping tasks\n",
- cmd->se_tfo->get_task_tag(cmd));
-
- /*
- * No tasks remain in the execution queue
- */
- spin_lock_irqsave(&cmd->t_state_lock, flags);
- list_for_each_entry_safe(task, task_tmp,
- &cmd->t_task_list, t_list) {
- pr_debug("Processing task %p\n", task);
- /*
- * If the struct se_task has not been sent and is not active,
- * remove the struct se_task from the execution queue.
- */
- if (!(task->task_flags & (TF_ACTIVE | TF_SENT))) {
- spin_unlock_irqrestore(&cmd->t_state_lock,
- flags);
- transport_remove_task_from_execute_queue(task,
- cmd->se_dev);
-
- pr_debug("Task %p removed from execute queue\n", task);
- spin_lock_irqsave(&cmd->t_state_lock, flags);
- continue;
- }
-
- if (!target_stop_task(task, &flags)) {
- pr_debug("Task %p - did nothing\n", task);
- ret++;
- }
- }
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
- return ret;
-}
-
/*
* Handle SAM-esque emulation for generic transport request failures.
*/
@@ -1951,13 +1772,7 @@ void transport_generic_request_failure(struct se_cmd *cmd)
pr_debug("-----[ i_state: %d t_state: %d scsi_sense_reason: %d\n",
cmd->se_tfo->get_cmd_state(cmd),
cmd->t_state, cmd->scsi_sense_reason);
- pr_debug("-----[ t_tasks: %d t_task_cdbs_left: %d"
- " t_task_cdbs_sent: %d t_task_cdbs_ex_left: %d --"
- " CMD_T_ACTIVE: %d CMD_T_STOP: %d CMD_T_SENT: %d\n",
- cmd->t_task_list_num,
- atomic_read(&cmd->t_task_cdbs_left),
- atomic_read(&cmd->t_task_cdbs_sent),
- atomic_read(&cmd->t_task_cdbs_ex_left),
+ pr_debug("-----[ CMD_T_ACTIVE: %d CMD_T_STOP: %d CMD_T_SENT: %d\n",
(cmd->transport_state & CMD_T_ACTIVE) != 0,
(cmd->transport_state & CMD_T_STOP) != 0,
(cmd->transport_state & CMD_T_SENT) != 0);
@@ -2156,7 +1971,7 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd)
* Called from fabric module context in transport_generic_new_cmd() and
* transport_generic_process_write()
*/
-static int transport_execute_tasks(struct se_cmd *cmd)
+static void transport_execute_tasks(struct se_cmd *cmd)
{
int add_tasks;
struct se_device *se_dev = cmd->se_dev;
@@ -2170,71 +1985,52 @@ static int transport_execute_tasks(struct se_cmd *cmd)
* attribute for the tasks of the received struct se_cmd CDB
*/
add_tasks = transport_execute_task_attr(cmd);
- if (!add_tasks)
- goto execute_tasks;
- /*
- * __transport_execute_tasks() -> __transport_add_tasks_from_cmd()
- * adds associated se_tasks while holding dev->execute_task_lock
- * before I/O dispath to avoid a double spinlock access.
- */
- __transport_execute_tasks(se_dev, cmd);
- return 0;
+ if (add_tasks) {
+ __transport_execute_tasks(se_dev, cmd);
+ return;
+ }
}
-
-execute_tasks:
__transport_execute_tasks(se_dev, NULL);
- return 0;
}
-/*
- * Called to check struct se_device tcq depth window, and once open pull struct se_task
- * from struct se_device->execute_task_list and
- *
- * Called from transport_processing_thread()
- */
static int __transport_execute_tasks(struct se_device *dev, struct se_cmd *new_cmd)
{
int error;
struct se_cmd *cmd = NULL;
- struct se_task *task = NULL;
unsigned long flags;
check_depth:
spin_lock_irq(&dev->execute_task_lock);
if (new_cmd != NULL)
- __transport_add_tasks_from_cmd(new_cmd);
+ __target_add_to_execute_list(new_cmd);
- if (list_empty(&dev->execute_task_list)) {
+ if (list_empty(&dev->execute_list)) {
spin_unlock_irq(&dev->execute_task_lock);
return 0;
}
- task = list_first_entry(&dev->execute_task_list,
- struct se_task, t_execute_list);
- __transport_remove_task_from_execute_queue(task, dev);
+ cmd = list_first_entry(&dev->execute_list, struct se_cmd, execute_list);
+ __target_remove_from_execute_list(cmd);
spin_unlock_irq(&dev->execute_task_lock);
- cmd = task->task_se_cmd;
spin_lock_irqsave(&cmd->t_state_lock, flags);
- task->task_flags |= (TF_ACTIVE | TF_SENT);
- atomic_inc(&cmd->t_task_cdbs_sent);
-
- if (atomic_read(&cmd->t_task_cdbs_sent) ==
- cmd->t_task_list_num)
- cmd->transport_state |= CMD_T_SENT;
+ cmd->transport_state |= CMD_T_BUSY;
+ cmd->transport_state |= CMD_T_SENT;
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- if (cmd->execute_task)
- error = cmd->execute_task(task);
- else
- error = dev->transport->do_task(task);
+ if (cmd->execute_cmd)
+ error = cmd->execute_cmd(cmd);
+ else {
+ error = dev->transport->execute_cmd(cmd, cmd->t_data_sg,
+ cmd->t_data_nents, cmd->data_direction);
+ }
+
if (error != 0) {
spin_lock_irqsave(&cmd->t_state_lock, flags);
- task->task_flags &= ~TF_ACTIVE;
+ cmd->transport_state &= ~CMD_T_BUSY;
cmd->transport_state &= ~CMD_T_SENT;
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- transport_stop_tasks_for_cmd(cmd);
transport_generic_request_failure(cmd);
}
@@ -2392,12 +2188,12 @@ static inline u32 transport_get_size(
} else /* bytes */
return sectors;
}
-#if 0
+
pr_debug("Returning block_size: %u, sectors: %u == %u for"
- " %s object\n", dev->se_sub_dev->se_dev_attrib.block_size, sectors,
- dev->se_sub_dev->se_dev_attrib.block_size * sectors,
- dev->transport->name);
-#endif
+ " %s object\n", dev->se_sub_dev->se_dev_attrib.block_size,
+ sectors, dev->se_sub_dev->se_dev_attrib.block_size * sectors,
+ dev->transport->name);
+
return dev->se_sub_dev->se_dev_attrib.block_size * sectors;
}
@@ -2462,7 +2258,6 @@ static int transport_get_sense_data(struct se_cmd *cmd)
{
unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL;
struct se_device *dev = cmd->se_dev;
- struct se_task *task = NULL, *task_tmp;
unsigned long flags;
u32 offset = 0;
@@ -2477,44 +2272,37 @@ static int transport_get_sense_data(struct se_cmd *cmd)
return 0;
}
- list_for_each_entry_safe(task, task_tmp,
- &cmd->t_task_list, t_list) {
- if (!(task->task_flags & TF_HAS_SENSE))
- continue;
-
- if (!dev->transport->get_sense_buffer) {
- pr_err("dev->transport->get_sense_buffer"
- " is NULL\n");
- continue;
- }
-
- sense_buffer = dev->transport->get_sense_buffer(task);
- if (!sense_buffer) {
- pr_err("ITT[0x%08x]_TASK[%p]: Unable to locate"
- " sense buffer for task with sense\n",
- cmd->se_tfo->get_task_tag(cmd), task);
- continue;
- }
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+ if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE))
+ goto out;
- offset = cmd->se_tfo->set_fabric_sense_len(cmd,
- TRANSPORT_SENSE_BUFFER);
+ if (!dev->transport->get_sense_buffer) {
+ pr_err("dev->transport->get_sense_buffer is NULL\n");
+ goto out;
+ }
- memcpy(&buffer[offset], sense_buffer,
- TRANSPORT_SENSE_BUFFER);
- cmd->scsi_status = task->task_scsi_status;
- /* Automatically padded */
- cmd->scsi_sense_length =
- (TRANSPORT_SENSE_BUFFER + offset);
-
- pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x"
- " and sense\n",
- dev->se_hba->hba_id, dev->transport->name,
- cmd->scsi_status);
- return 0;
+ sense_buffer = dev->transport->get_sense_buffer(cmd);
+ if (!sense_buffer) {
+ pr_err("ITT 0x%08x cmd %p: Unable to locate"
+ " sense buffer for task with sense\n",
+ cmd->se_tfo->get_task_tag(cmd), cmd);
+ goto out;
}
+
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+ offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER);
+
+ memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER);
+
+ /* Automatically padded */
+ cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset;
+
+ pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n",
+ dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status);
+ return 0;
+
+out:
+ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
return -1;
}
@@ -2581,7 +2369,7 @@ static int target_check_write_same_discard(unsigned char *flags, struct se_devic
* Generic Command Sequencer that should work for most DAS transport
* drivers.
*
- * Called from transport_generic_allocate_tasks() in the $FABRIC_MOD
+ * Called from target_setup_cmd_from_cdb() in the $FABRIC_MOD
* RX Thread.
*
* FIXME: Need to support other SCSI OPCODES where as well.
@@ -2615,11 +2403,10 @@ static int transport_generic_cmd_sequencer(
* by the ALUA primary or secondary access state..
*/
if (ret > 0) {
-#if 0
pr_debug("[%s]: ALUA TG Port not available,"
" SenseKey: NOT_READY, ASC/ASCQ: 0x04/0x%02x\n",
cmd->se_tfo->get_fabric_name(), alua_ascq);
-#endif
+
transport_set_sense_codes(cmd, 0x04, alua_ascq);
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY;
@@ -2695,6 +2482,7 @@ static int transport_generic_cmd_sequencer(
cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
break;
case WRITE_10:
+ case WRITE_VERIFY:
sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
if (sector_ret)
goto out_unsupported_cdb;
@@ -2796,7 +2584,7 @@ static int transport_generic_cmd_sequencer(
if (target_check_write_same_discard(&cdb[10], dev) < 0)
goto out_unsupported_cdb;
if (!passthrough)
- cmd->execute_task = target_emulate_write_same;
+ cmd->execute_cmd = target_emulate_write_same;
break;
default:
pr_err("VARIABLE_LENGTH_CMD service action"
@@ -2810,9 +2598,9 @@ static int transport_generic_cmd_sequencer(
/*
* Check for emulated MI_REPORT_TARGET_PGS.
*/
- if (cdb[1] == MI_REPORT_TARGET_PGS &&
+ if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS &&
su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
- cmd->execute_task =
+ cmd->execute_cmd =
target_emulate_report_target_port_groups;
}
size = (cdb[6] << 24) | (cdb[7] << 16) |
@@ -2835,13 +2623,13 @@ static int transport_generic_cmd_sequencer(
size = cdb[4];
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
if (!passthrough)
- cmd->execute_task = target_emulate_modesense;
+ cmd->execute_cmd = target_emulate_modesense;
break;
case MODE_SENSE_10:
size = (cdb[7] << 8) + cdb[8];
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
if (!passthrough)
- cmd->execute_task = target_emulate_modesense;
+ cmd->execute_cmd = target_emulate_modesense;
break;
case GPCMD_READ_BUFFER_CAPACITY:
case GPCMD_SEND_OPC:
@@ -2863,13 +2651,13 @@ static int transport_generic_cmd_sequencer(
break;
case PERSISTENT_RESERVE_IN:
if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
- cmd->execute_task = target_scsi3_emulate_pr_in;
+ cmd->execute_cmd = target_scsi3_emulate_pr_in;
size = (cdb[7] << 8) + cdb[8];
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
break;
case PERSISTENT_RESERVE_OUT:
if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
- cmd->execute_task = target_scsi3_emulate_pr_out;
+ cmd->execute_cmd = target_scsi3_emulate_pr_out;
size = (cdb[7] << 8) + cdb[8];
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
break;
@@ -2890,7 +2678,7 @@ static int transport_generic_cmd_sequencer(
*/
if (cdb[1] == MO_SET_TARGET_PGS &&
su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
- cmd->execute_task =
+ cmd->execute_cmd =
target_emulate_set_target_port_groups;
}
@@ -2912,7 +2700,7 @@ static int transport_generic_cmd_sequencer(
cmd->sam_task_attr = MSG_HEAD_TAG;
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
if (!passthrough)
- cmd->execute_task = target_emulate_inquiry;
+ cmd->execute_cmd = target_emulate_inquiry;
break;
case READ_BUFFER:
size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
@@ -2922,7 +2710,7 @@ static int transport_generic_cmd_sequencer(
size = READ_CAP_LEN;
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
if (!passthrough)
- cmd->execute_task = target_emulate_readcapacity;
+ cmd->execute_cmd = target_emulate_readcapacity;
break;
case READ_MEDIA_SERIAL_NUMBER:
case SECURITY_PROTOCOL_IN:
@@ -2934,7 +2722,7 @@ static int transport_generic_cmd_sequencer(
switch (cmd->t_task_cdb[1] & 0x1f) {
case SAI_READ_CAPACITY_16:
if (!passthrough)
- cmd->execute_task =
+ cmd->execute_cmd =
target_emulate_readcapacity_16;
break;
default:
@@ -2977,7 +2765,7 @@ static int transport_generic_cmd_sequencer(
size = cdb[4];
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
if (!passthrough)
- cmd->execute_task = target_emulate_request_sense;
+ cmd->execute_cmd = target_emulate_request_sense;
break;
case READ_ELEMENT_STATUS:
size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9];
@@ -3006,7 +2794,7 @@ static int transport_generic_cmd_sequencer(
* emulation disabled.
*/
if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
- cmd->execute_task = target_scsi2_reservation_reserve;
+ cmd->execute_cmd = target_scsi2_reservation_reserve;
cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
break;
case RELEASE:
@@ -3021,7 +2809,7 @@ static int transport_generic_cmd_sequencer(
size = cmd->data_length;
if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
- cmd->execute_task = target_scsi2_reservation_release;
+ cmd->execute_cmd = target_scsi2_reservation_release;
cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
break;
case SYNCHRONIZE_CACHE:
@@ -3053,13 +2841,13 @@ static int transport_generic_cmd_sequencer(
if (transport_cmd_get_valid_sectors(cmd) < 0)
goto out_invalid_cdb_field;
}
- cmd->execute_task = target_emulate_synchronize_cache;
+ cmd->execute_cmd = target_emulate_synchronize_cache;
break;
case UNMAP:
size = get_unaligned_be16(&cdb[7]);
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
if (!passthrough)
- cmd->execute_task = target_emulate_unmap;
+ cmd->execute_cmd = target_emulate_unmap;
break;
case WRITE_SAME_16:
sectors = transport_get_sectors_16(cdb, cmd, &sector_ret);
@@ -3079,7 +2867,7 @@ static int transport_generic_cmd_sequencer(
if (target_check_write_same_discard(&cdb[1], dev) < 0)
goto out_unsupported_cdb;
if (!passthrough)
- cmd->execute_task = target_emulate_write_same;
+ cmd->execute_cmd = target_emulate_write_same;
break;
case WRITE_SAME:
sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
@@ -3102,7 +2890,7 @@ static int transport_generic_cmd_sequencer(
if (target_check_write_same_discard(&cdb[1], dev) < 0)
goto out_unsupported_cdb;
if (!passthrough)
- cmd->execute_task = target_emulate_write_same;
+ cmd->execute_cmd = target_emulate_write_same;
break;
case ALLOW_MEDIUM_REMOVAL:
case ERASE:
@@ -3115,7 +2903,7 @@ static int transport_generic_cmd_sequencer(
case WRITE_FILEMARKS:
cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
if (!passthrough)
- cmd->execute_task = target_emulate_noop;
+ cmd->execute_cmd = target_emulate_noop;
break;
case GPCMD_CLOSE_TRACK:
case INITIALIZE_ELEMENT_STATUS:
@@ -3125,7 +2913,7 @@ static int transport_generic_cmd_sequencer(
cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
break;
case REPORT_LUNS:
- cmd->execute_task = target_report_luns;
+ cmd->execute_cmd = target_report_luns;
size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
/*
* Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
@@ -3135,6 +2923,42 @@ static int transport_generic_cmd_sequencer(
cmd->sam_task_attr = MSG_HEAD_TAG;
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
break;
+ case GET_EVENT_STATUS_NOTIFICATION:
+ size = (cdb[7] << 8) | cdb[8];
+ cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
+ break;
+ case ATA_16:
+ /* Only support ATA passthrough to pSCSI backends.. */
+ if (!passthrough)
+ goto out_unsupported_cdb;
+
+ /* T_LENGTH */
+ switch (cdb[2] & 0x3) {
+ case 0x0:
+ sectors = 0;
+ break;
+ case 0x1:
+ sectors = (((cdb[1] & 0x1) ? cdb[3] : 0) << 8) | cdb[4];
+ break;
+ case 0x2:
+ sectors = (((cdb[1] & 0x1) ? cdb[5] : 0) << 8) | cdb[6];
+ break;
+ case 0x3:
+ pr_err("T_LENGTH=0x3 not supported for ATA_16\n");
+ goto out_invalid_cdb_field;
+ }
+
+ /* BYTE_BLOCK */
+ if (cdb[2] & 0x4) {
+ /* BLOCK T_TYPE: 512 or sector */
+ size = sectors * ((cdb[2] & 0x10) ?
+ dev->se_sub_dev->se_dev_attrib.block_size : 512);
+ } else {
+ /* BYTE */
+ size = sectors;
+ }
+ cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
+ break;
default:
pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode"
" 0x%02x, sending CHECK_CONDITION.\n",
@@ -3142,6 +2966,9 @@ static int transport_generic_cmd_sequencer(
goto out_unsupported_cdb;
}
+ if (cmd->unknown_data_length)
+ cmd->data_length = size;
+
if (size != cmd->data_length) {
pr_warn("TARGET_CORE[%s]: Expected Transfer Length:"
" %u does not match SCSI CDB Length: %u for SAM Opcode:"
@@ -3177,15 +3004,25 @@ static int transport_generic_cmd_sequencer(
cmd->data_length = size;
}
- if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB &&
- sectors > dev->se_sub_dev->se_dev_attrib.fabric_max_sectors) {
- printk_ratelimited(KERN_ERR "SCSI OP %02xh with too big sectors %u\n",
- cdb[0], sectors);
- goto out_invalid_cdb_field;
+ if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
+ if (sectors > su_dev->se_dev_attrib.fabric_max_sectors) {
+ printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
+ " big sectors %u exceeds fabric_max_sectors:"
+ " %u\n", cdb[0], sectors,
+ su_dev->se_dev_attrib.fabric_max_sectors);
+ goto out_invalid_cdb_field;
+ }
+ if (sectors > su_dev->se_dev_attrib.hw_max_sectors) {
+ printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
+ " big sectors %u exceeds backend hw_max_sectors:"
+ " %u\n", cdb[0], sectors,
+ su_dev->se_dev_attrib.hw_max_sectors);
+ goto out_invalid_cdb_field;
+ }
}
/* reject any command that we don't have a handler for */
- if (!(passthrough || cmd->execute_task ||
+ if (!(passthrough || cmd->execute_cmd ||
(cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)))
goto out_unsupported_cdb;
@@ -3250,7 +3087,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
cmd_p->t_task_cdb[0],
cmd_p->sam_task_attr, cmd_p->se_ordered_id);
- transport_add_tasks_from_cmd(cmd_p);
+ target_add_to_execute_list(cmd_p);
new_active_tasks++;
spin_lock(&dev->delayed_cmd_lock);
@@ -3346,10 +3183,6 @@ static void target_complete_ok_work(struct work_struct *work)
if (transport_get_sense_data(cmd) < 0)
reason = TCM_NON_EXISTENT_LUN;
- /*
- * Only set when an struct se_task->task_scsi_status returned
- * a non GOOD status.
- */
if (cmd->scsi_status) {
ret = transport_send_check_condition_and_sense(
cmd, reason, 1);
@@ -3424,33 +3257,6 @@ queue_full:
transport_handle_queue_full(cmd, cmd->se_dev);
}
-static void transport_free_dev_tasks(struct se_cmd *cmd)
-{
- struct se_task *task, *task_tmp;
- unsigned long flags;
- LIST_HEAD(dispose_list);
-
- spin_lock_irqsave(&cmd->t_state_lock, flags);
- list_for_each_entry_safe(task, task_tmp,
- &cmd->t_task_list, t_list) {
- if (!(task->task_flags & TF_ACTIVE))
- list_move_tail(&task->t_list, &dispose_list);
- }
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
- while (!list_empty(&dispose_list)) {
- task = list_first_entry(&dispose_list, struct se_task, t_list);
-
- if (task->task_sg != cmd->t_data_sg &&
- task->task_sg != cmd->t_bidi_data_sg)
- kfree(task->task_sg);
-
- list_del(&task->t_list);
-
- cmd->se_dev->transport->free_task(task);
- }
-}
-
static inline void transport_free_sgl(struct scatterlist *sgl, int nents)
{
struct scatterlist *sg;
@@ -3511,7 +3317,6 @@ static void transport_release_cmd(struct se_cmd *cmd)
static void transport_put_cmd(struct se_cmd *cmd)
{
unsigned long flags;
- int free_tasks = 0;
spin_lock_irqsave(&cmd->t_state_lock, flags);
if (atomic_read(&cmd->t_fe_count)) {
@@ -3519,21 +3324,12 @@ static void transport_put_cmd(struct se_cmd *cmd)
goto out_busy;
}
- if (atomic_read(&cmd->t_se_count)) {
- if (!atomic_dec_and_test(&cmd->t_se_count))
- goto out_busy;
- }
-
if (cmd->transport_state & CMD_T_DEV_ACTIVE) {
cmd->transport_state &= ~CMD_T_DEV_ACTIVE;
- transport_all_task_dev_remove_state(cmd);
- free_tasks = 1;
+ target_remove_from_state_list(cmd);
}
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- if (free_tasks != 0)
- transport_free_dev_tasks(cmd);
-
transport_free_pages(cmd);
transport_release_cmd(cmd);
return;
@@ -3683,245 +3479,14 @@ out:
return -ENOMEM;
}
-/* Reduce sectors if they are too long for the device */
-static inline sector_t transport_limit_task_sectors(
- struct se_device *dev,
- unsigned long long lba,
- sector_t sectors)
-{
- sectors = min_t(sector_t, sectors, dev->se_sub_dev->se_dev_attrib.max_sectors);
-
- if (dev->transport->get_device_type(dev) == TYPE_DISK)
- if ((lba + sectors) > transport_dev_end_lba(dev))
- sectors = ((transport_dev_end_lba(dev) - lba) + 1);
-
- return sectors;
-}
-
-
-/*
- * This function can be used by HW target mode drivers to create a linked
- * scatterlist from all contiguously allocated struct se_task->task_sg[].
- * This is intended to be called during the completion path by TCM Core
- * when struct target_core_fabric_ops->check_task_sg_chaining is enabled.
- */
-void transport_do_task_sg_chain(struct se_cmd *cmd)
-{
- struct scatterlist *sg_first = NULL;
- struct scatterlist *sg_prev = NULL;
- int sg_prev_nents = 0;
- struct scatterlist *sg;
- struct se_task *task;
- u32 chained_nents = 0;
- int i;
-
- BUG_ON(!cmd->se_tfo->task_sg_chaining);
-
- /*
- * Walk the struct se_task list and setup scatterlist chains
- * for each contiguously allocated struct se_task->task_sg[].
- */
- list_for_each_entry(task, &cmd->t_task_list, t_list) {
- if (!task->task_sg)
- continue;
-
- if (!sg_first) {
- sg_first = task->task_sg;
- chained_nents = task->task_sg_nents;
- } else {
- sg_chain(sg_prev, sg_prev_nents, task->task_sg);
- chained_nents += task->task_sg_nents;
- }
- /*
- * For the padded tasks, use the extra SGL vector allocated
- * in transport_allocate_data_tasks() for the sg_prev_nents
- * offset into sg_chain() above.
- *
- * We do not need the padding for the last task (or a single
- * task), but in that case we will never use the sg_prev_nents
- * value below which would be incorrect.
- */
- sg_prev_nents = (task->task_sg_nents + 1);
- sg_prev = task->task_sg;
- }
- /*
- * Setup the starting pointer and total t_tasks_sg_linked_no including
- * padding SGs for linking and to mark the end.
- */
- cmd->t_tasks_sg_chained = sg_first;
- cmd->t_tasks_sg_chained_no = chained_nents;
-
- pr_debug("Setup cmd: %p cmd->t_tasks_sg_chained: %p and"
- " t_tasks_sg_chained_no: %u\n", cmd, cmd->t_tasks_sg_chained,
- cmd->t_tasks_sg_chained_no);
-
- for_each_sg(cmd->t_tasks_sg_chained, sg,
- cmd->t_tasks_sg_chained_no, i) {
-
- pr_debug("SG[%d]: %p page: %p length: %d offset: %d\n",
- i, sg, sg_page(sg), sg->length, sg->offset);
- if (sg_is_chain(sg))
- pr_debug("SG: %p sg_is_chain=1\n", sg);
- if (sg_is_last(sg))
- pr_debug("SG: %p sg_is_last=1\n", sg);
- }
-}
-EXPORT_SYMBOL(transport_do_task_sg_chain);
-
-/*
- * Break up cmd into chunks transport can handle
- */
-static int
-transport_allocate_data_tasks(struct se_cmd *cmd,
- enum dma_data_direction data_direction,
- struct scatterlist *cmd_sg, unsigned int sgl_nents)
-{
- struct se_device *dev = cmd->se_dev;
- int task_count, i;
- unsigned long long lba;
- sector_t sectors, dev_max_sectors;
- u32 sector_size;
-
- if (transport_cmd_get_valid_sectors(cmd) < 0)
- return -EINVAL;
-
- dev_max_sectors = dev->se_sub_dev->se_dev_attrib.max_sectors;
- sector_size = dev->se_sub_dev->se_dev_attrib.block_size;
-
- WARN_ON(cmd->data_length % sector_size);
-
- lba = cmd->t_task_lba;
- sectors = DIV_ROUND_UP(cmd->data_length, sector_size);
- task_count = DIV_ROUND_UP_SECTOR_T(sectors, dev_max_sectors);
-
- /*
- * If we need just a single task reuse the SG list in the command
- * and avoid a lot of work.
- */
- if (task_count == 1) {
- struct se_task *task;
- unsigned long flags;
-
- task = transport_generic_get_task(cmd, data_direction);
- if (!task)
- return -ENOMEM;
-
- task->task_sg = cmd_sg;
- task->task_sg_nents = sgl_nents;
-
- task->task_lba = lba;
- task->task_sectors = sectors;
- task->task_size = task->task_sectors * sector_size;
-
- spin_lock_irqsave(&cmd->t_state_lock, flags);
- list_add_tail(&task->t_list, &cmd->t_task_list);
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
- return task_count;
- }
-
- for (i = 0; i < task_count; i++) {
- struct se_task *task;
- unsigned int task_size, task_sg_nents_padded;
- struct scatterlist *sg;
- unsigned long flags;
- int count;
-
- task = transport_generic_get_task(cmd, data_direction);
- if (!task)
- return -ENOMEM;
-
- task->task_lba = lba;
- task->task_sectors = min(sectors, dev_max_sectors);
- task->task_size = task->task_sectors * sector_size;
-
- /*
- * This now assumes that passed sg_ents are in PAGE_SIZE chunks
- * in order to calculate the number per task SGL entries
- */
- task->task_sg_nents = DIV_ROUND_UP(task->task_size, PAGE_SIZE);
- /*
- * Check if the fabric module driver is requesting that all
- * struct se_task->task_sg[] be chained together.. If so,
- * then allocate an extra padding SG entry for linking and
- * marking the end of the chained SGL for every task except
- * the last one for (task_count > 1) operation, or skipping
- * the extra padding for the (task_count == 1) case.
- */
- if (cmd->se_tfo->task_sg_chaining && (i < (task_count - 1))) {
- task_sg_nents_padded = (task->task_sg_nents + 1);
- } else
- task_sg_nents_padded = task->task_sg_nents;
-
- task->task_sg = kmalloc(sizeof(struct scatterlist) *
- task_sg_nents_padded, GFP_KERNEL);
- if (!task->task_sg) {
- cmd->se_dev->transport->free_task(task);
- return -ENOMEM;
- }
-
- sg_init_table(task->task_sg, task_sg_nents_padded);
-
- task_size = task->task_size;
-
- /* Build new sgl, only up to task_size */
- for_each_sg(task->task_sg, sg, task->task_sg_nents, count) {
- if (cmd_sg->length > task_size)
- break;
-
- *sg = *cmd_sg;
- task_size -= cmd_sg->length;
- cmd_sg = sg_next(cmd_sg);
- }
-
- lba += task->task_sectors;
- sectors -= task->task_sectors;
-
- spin_lock_irqsave(&cmd->t_state_lock, flags);
- list_add_tail(&task->t_list, &cmd->t_task_list);
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- }
-
- return task_count;
-}
-
-static int
-transport_allocate_control_task(struct se_cmd *cmd)
-{
- struct se_task *task;
- unsigned long flags;
-
- /* Workaround for handling zero-length control CDBs */
- if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
- !cmd->data_length)
- return 0;
-
- task = transport_generic_get_task(cmd, cmd->data_direction);
- if (!task)
- return -ENOMEM;
-
- task->task_sg = cmd->t_data_sg;
- task->task_size = cmd->data_length;
- task->task_sg_nents = cmd->t_data_nents;
-
- spin_lock_irqsave(&cmd->t_state_lock, flags);
- list_add_tail(&task->t_list, &cmd->t_task_list);
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
- /* Success! Return number of tasks allocated */
- return 1;
-}
-
/*
- * Allocate any required ressources to execute the command, and either place
- * it on the execution queue if possible. For writes we might not have the
- * payload yet, thus notify the fabric via a call to ->write_pending instead.
+ * Allocate any required resources to execute the command. For writes we
+ * might not have the payload yet, so notify the fabric via a call to
+ * ->write_pending instead. Otherwise place it on the execution queue.
*/
int transport_generic_new_cmd(struct se_cmd *cmd)
{
struct se_device *dev = cmd->se_dev;
- int task_cdbs, task_cdbs_bidi = 0;
- int set_counts = 1;
int ret = 0;
/*
@@ -3936,35 +3501,9 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
goto out_fail;
}
- /*
- * For BIDI command set up the read tasks first.
- */
- if (cmd->t_bidi_data_sg &&
- dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) {
- BUG_ON(!(cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB));
-
- task_cdbs_bidi = transport_allocate_data_tasks(cmd,
- DMA_FROM_DEVICE, cmd->t_bidi_data_sg,
- cmd->t_bidi_data_nents);
- if (task_cdbs_bidi <= 0)
- goto out_fail;
-
- atomic_inc(&cmd->t_fe_count);
- atomic_inc(&cmd->t_se_count);
- set_counts = 0;
- }
-
- if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
- task_cdbs = transport_allocate_data_tasks(cmd,
- cmd->data_direction, cmd->t_data_sg,
- cmd->t_data_nents);
- } else {
- task_cdbs = transport_allocate_control_task(cmd);
- }
-
- if (task_cdbs < 0)
- goto out_fail;
- else if (!task_cdbs && (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)) {
+ /* Workaround for handling zero-length control CDBs */
+ if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
+ !cmd->data_length) {
spin_lock_irq(&cmd->t_state_lock);
cmd->t_state = TRANSPORT_COMPLETE;
cmd->transport_state |= CMD_T_ACTIVE;
@@ -3982,29 +3521,31 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
return 0;
}
- if (set_counts) {
- atomic_inc(&cmd->t_fe_count);
- atomic_inc(&cmd->t_se_count);
+ if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
+ struct se_dev_attrib *attr = &dev->se_sub_dev->se_dev_attrib;
+
+ if (transport_cmd_get_valid_sectors(cmd) < 0)
+ return -EINVAL;
+
+ BUG_ON(cmd->data_length % attr->block_size);
+ BUG_ON(DIV_ROUND_UP(cmd->data_length, attr->block_size) >
+ attr->hw_max_sectors);
}
- cmd->t_task_list_num = (task_cdbs + task_cdbs_bidi);
- atomic_set(&cmd->t_task_cdbs_left, cmd->t_task_list_num);
- atomic_set(&cmd->t_task_cdbs_ex_left, cmd->t_task_list_num);
+ atomic_inc(&cmd->t_fe_count);
/*
- * For WRITEs, let the fabric know its buffer is ready..
- * This WRITE struct se_cmd (and all of its associated struct se_task's)
- * will be added to the struct se_device execution queue after its WRITE
- * data has arrived. (ie: It gets handled by the transport processing
- * thread a second time)
+ * For WRITEs, let the fabric know its buffer is ready.
+ *
+ * The command will be added to the execution queue after its write
+ * data has arrived.
*/
if (cmd->data_direction == DMA_TO_DEVICE) {
- transport_add_tasks_to_state_queue(cmd);
+ target_add_to_state_list(cmd);
return transport_generic_write_pending(cmd);
}
/*
- * Everything else but a WRITE, add the struct se_cmd's struct se_task's
- * to the execution queue.
+ * Everything else but a WRITE, add the command to the execution queue.
*/
transport_execute_tasks(cmd);
return 0;
@@ -4091,8 +3632,6 @@ void transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
if (cmd->se_lun)
transport_lun_remove_cmd(cmd);
- transport_free_dev_tasks(cmd);
-
transport_put_cmd(cmd);
}
}
@@ -4233,7 +3772,8 @@ EXPORT_SYMBOL(target_wait_for_sess_cmds);
static int transport_lun_wait_for_tasks(struct se_cmd *cmd, struct se_lun *lun)
{
unsigned long flags;
- int ret;
+ int ret = 0;
+
/*
* If the frontend has already requested this struct se_cmd to
* be stopped, we can safely ignore this struct se_cmd.
@@ -4253,10 +3793,21 @@ static int transport_lun_wait_for_tasks(struct se_cmd *cmd, struct se_lun *lun)
wake_up_interruptible(&cmd->se_dev->dev_queue_obj.thread_wq);
- ret = transport_stop_tasks_for_cmd(cmd);
+ // XXX: audit task_flags checks.
+ spin_lock_irqsave(&cmd->t_state_lock, flags);
+ if ((cmd->transport_state & CMD_T_BUSY) &&
+ (cmd->transport_state & CMD_T_SENT)) {
+ if (!target_stop_cmd(cmd, &flags))
+ ret++;
+ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+ } else {
+ spin_unlock_irqrestore(&cmd->t_state_lock,
+ flags);
+ target_remove_from_execute_list(cmd);
+ }
- pr_debug("ConfigFS: cmd: %p t_tasks: %d stop tasks ret:"
- " %d\n", cmd, cmd->t_task_list_num, ret);
+ pr_debug("ConfigFS: cmd: %p stop tasks ret:"
+ " %d\n", cmd, ret);
if (!ret) {
pr_debug("ConfigFS: ITT[0x%08x] - stopping cmd....\n",
cmd->se_tfo->get_task_tag(cmd));
@@ -4328,10 +3879,9 @@ static void __transport_clear_lun_from_sessions(struct se_lun *lun)
goto check_cond;
}
cmd->transport_state &= ~CMD_T_DEV_ACTIVE;
- transport_all_task_dev_remove_state(cmd);
+ target_remove_from_state_list(cmd);
spin_unlock_irqrestore(&cmd->t_state_lock, cmd_flags);
- transport_free_dev_tasks(cmd);
/*
* The Storage engine stopped this struct se_cmd before it was
* send to the fabric frontend for delivery back to the
@@ -4444,7 +3994,7 @@ bool transport_wait_for_tasks(struct se_cmd *cmd)
wait_for_completion(&cmd->transport_lun_fe_stop_comp);
spin_lock_irqsave(&cmd->t_state_lock, flags);
- transport_all_task_dev_remove_state(cmd);
+ target_remove_from_state_list(cmd);
/*
* At this point, the frontend who was the originator of this
* struct se_cmd, now owns the structure and can be released through
@@ -4710,12 +4260,12 @@ int transport_check_aborted_status(struct se_cmd *cmd, int send_status)
if (!send_status ||
(cmd->se_cmd_flags & SCF_SENT_DELAYED_TAS))
return 1;
-#if 0
+
pr_debug("Sending delayed SAM_STAT_TASK_ABORTED"
" status for CDB: 0x%02x ITT: 0x%08x\n",
cmd->t_task_cdb[0],
cmd->se_tfo->get_task_tag(cmd));
-#endif
+
cmd->se_cmd_flags |= SCF_SENT_DELAYED_TAS;
cmd->se_tfo->queue_status(cmd);
ret = 1;
@@ -4748,11 +4298,11 @@ void transport_send_task_abort(struct se_cmd *cmd)
}
}
cmd->scsi_status = SAM_STAT_TASK_ABORTED;
-#if 0
+
pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x,"
" ITT: 0x%08x\n", cmd->t_task_cdb[0],
cmd->se_tfo->get_task_tag(cmd));
-#endif
+
cmd->se_tfo->queue_status(cmd);
}
@@ -4865,7 +4415,7 @@ get_cmd:
}
out:
- WARN_ON(!list_empty(&dev->state_task_list));
+ WARN_ON(!list_empty(&dev->state_list));
WARN_ON(!list_empty(&dev->dev_queue_obj.qobj_list));
dev->process_thread = NULL;
return 0;
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index a375f257aabc..f03fb9730f5b 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -215,20 +215,10 @@ int ft_write_pending(struct se_cmd *se_cmd)
*/
if ((ep->xid <= lport->lro_xid) &&
(fh->fh_r_ctl == FC_RCTL_DD_DATA_DESC)) {
- if (se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
- /*
- * cmd may have been broken up into multiple
- * tasks. Link their sgs together so we can
- * operate on them all at once.
- */
- transport_do_task_sg_chain(se_cmd);
- cmd->sg = se_cmd->t_tasks_sg_chained;
- cmd->sg_cnt =
- se_cmd->t_tasks_sg_chained_no;
- }
- if (cmd->sg && lport->tt.ddp_target(lport, ep->xid,
- cmd->sg,
- cmd->sg_cnt))
+ if ((se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) &&
+ lport->tt.ddp_target(lport, ep->xid,
+ se_cmd->t_data_sg,
+ se_cmd->t_data_nents))
cmd->was_ddp_setup = 1;
}
}
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c
index 2948dc944619..9501844fae2d 100644
--- a/drivers/target/tcm_fc/tfc_conf.c
+++ b/drivers/target/tcm_fc/tfc_conf.c
@@ -576,9 +576,6 @@ int ft_register_configfs(void)
}
fabric->tf_ops = ft_fabric_ops;
- /* Allowing support for task_sg_chaining */
- fabric->tf_ops.task_sg_chaining = 1;
-
/*
* Setup default attribute lists for various fabric->tf_cit_tmpl
*/
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c
index dc7c0db26e20..071a505f98fc 100644
--- a/drivers/target/tcm_fc/tfc_io.c
+++ b/drivers/target/tcm_fc/tfc_io.c
@@ -228,7 +228,7 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
"payload, Frame will be dropped if"
"'Sequence Initiative' bit in f_ctl is"
"not set\n", __func__, ep->xid, f_ctl,
- cmd->sg, cmd->sg_cnt);
+ se_cmd->t_data_sg, se_cmd->t_data_nents);
/*
* Invalidate HW DDP context if it was setup for respective
* command. Invalidation of HW DDP context is requited in both
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 6cc4358f68c1..35819e312624 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1033,7 +1033,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
- tty_lock();
+ tty_lock(tty);
tmp.line = tty->index;
tmp.port = state->port;
tmp.flags = state->tport.flags;
@@ -1042,7 +1042,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
tmp.close_delay = state->tport.close_delay;
tmp.closing_wait = state->tport.closing_wait;
tmp.custom_divisor = state->custom_divisor;
- tty_unlock();
+ tty_unlock(tty);
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
return -EFAULT;
return 0;
@@ -1059,12 +1059,12 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
return -EFAULT;
- tty_lock();
+ tty_lock(tty);
change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) ||
new_serial.custom_divisor != state->custom_divisor;
if (new_serial.irq || new_serial.port != state->port ||
new_serial.xmit_fifo_size != state->xmit_fifo_size) {
- tty_unlock();
+ tty_unlock(tty);
return -EINVAL;
}
@@ -1074,7 +1074,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
(new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
((new_serial.flags & ~ASYNC_USR_MASK) !=
(port->flags & ~ASYNC_USR_MASK))) {
- tty_unlock();
+ tty_unlock(tty);
return -EPERM;
}
port->flags = ((port->flags & ~ASYNC_USR_MASK) |
@@ -1084,7 +1084,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
}
if (new_serial.baud_base < 9600) {
- tty_unlock();
+ tty_unlock(tty);
return -EINVAL;
}
@@ -1116,7 +1116,7 @@ check_and_exit:
}
} else
retval = startup(tty, state);
- tty_unlock();
+ tty_unlock(tty);
return retval;
}
diff --git a/drivers/tty/bfin_jtag_comm.c b/drivers/tty/bfin_jtag_comm.c
index 946f799861f5..61fc74fe1747 100644
--- a/drivers/tty/bfin_jtag_comm.c
+++ b/drivers/tty/bfin_jtag_comm.c
@@ -62,9 +62,7 @@ static inline uint32_t bfin_write_emudat_chars(char a, char b, char c, char d)
static struct tty_driver *bfin_jc_driver;
static struct task_struct *bfin_jc_kthread;
-static struct tty_struct * volatile bfin_jc_tty;
-static unsigned long bfin_jc_count;
-static DEFINE_MUTEX(bfin_jc_tty_mutex);
+static struct tty_port port;
static volatile struct circ_buf bfin_jc_write_buf;
static int
@@ -73,18 +71,21 @@ bfin_jc_emudat_manager(void *arg)
uint32_t inbound_len = 0, outbound_len = 0;
while (!kthread_should_stop()) {
+ struct tty_struct *tty = tty_port_tty_get(&port);
/* no one left to give data to, so sleep */
- if (bfin_jc_tty == NULL && circ_empty(&bfin_jc_write_buf)) {
+ if (tty == NULL && circ_empty(&bfin_jc_write_buf)) {
pr_debug("waiting for readers\n");
__set_current_state(TASK_UNINTERRUPTIBLE);
schedule();
__set_current_state(TASK_RUNNING);
+ continue;
}
/* no data available, so just chill */
if (!(bfin_read_DBGSTAT() & EMUDIF) && circ_empty(&bfin_jc_write_buf)) {
pr_debug("waiting for data (in_len = %i) (circ: %i %i)\n",
inbound_len, bfin_jc_write_buf.tail, bfin_jc_write_buf.head);
+ tty_kref_put(tty);
if (inbound_len)
schedule();
else
@@ -94,9 +95,6 @@ bfin_jc_emudat_manager(void *arg)
/* if incoming data is ready, eat it */
if (bfin_read_DBGSTAT() & EMUDIF) {
- struct tty_struct *tty;
- mutex_lock(&bfin_jc_tty_mutex);
- tty = (struct tty_struct *)bfin_jc_tty;
if (tty != NULL) {
uint32_t emudat = bfin_read_emudat();
if (inbound_len == 0) {
@@ -110,7 +108,6 @@ bfin_jc_emudat_manager(void *arg)
tty_flip_buffer_push(tty);
}
}
- mutex_unlock(&bfin_jc_tty_mutex);
}
/* if outgoing data is ready, post it */
@@ -120,7 +117,6 @@ bfin_jc_emudat_manager(void *arg)
bfin_write_emudat(outbound_len);
pr_debug("outgoing length: 0x%08x\n", outbound_len);
} else {
- struct tty_struct *tty;
int tail = bfin_jc_write_buf.tail;
size_t ate = (4 <= outbound_len ? 4 : outbound_len);
uint32_t emudat =
@@ -132,14 +128,12 @@ bfin_jc_emudat_manager(void *arg)
);
bfin_jc_write_buf.tail += ate;
outbound_len -= ate;
- mutex_lock(&bfin_jc_tty_mutex);
- tty = (struct tty_struct *)bfin_jc_tty;
if (tty)
tty_wakeup(tty);
- mutex_unlock(&bfin_jc_tty_mutex);
pr_debug(" outgoing data: 0x%08x (pushing %zu)\n", emudat, ate);
}
}
+ tty_kref_put(tty);
}
__set_current_state(TASK_RUNNING);
@@ -149,24 +143,28 @@ bfin_jc_emudat_manager(void *arg)
static int
bfin_jc_open(struct tty_struct *tty, struct file *filp)
{
- mutex_lock(&bfin_jc_tty_mutex);
- pr_debug("open %lu\n", bfin_jc_count);
- ++bfin_jc_count;
- bfin_jc_tty = tty;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port.lock, flags);
+ port.count++;
+ spin_unlock_irqrestore(&port.lock, flags);
+ tty_port_tty_set(&port, tty);
wake_up_process(bfin_jc_kthread);
- mutex_unlock(&bfin_jc_tty_mutex);
return 0;
}
static void
bfin_jc_close(struct tty_struct *tty, struct file *filp)
{
- mutex_lock(&bfin_jc_tty_mutex);
- pr_debug("close %lu\n", bfin_jc_count);
- if (--bfin_jc_count == 0)
- bfin_jc_tty = NULL;
+ unsigned long flags;
+ bool last;
+
+ spin_lock_irqsave(&port.lock, flags);
+ last = --port.count == 0;
+ spin_unlock_irqrestore(&port.lock, flags);
+ if (last)
+ tty_port_tty_set(&port, NULL);
wake_up_process(bfin_jc_kthread);
- mutex_unlock(&bfin_jc_tty_mutex);
}
/* XXX: we dont handle the put_char() case where we must handle count = 1 */
@@ -242,6 +240,8 @@ static int __init bfin_jc_init(void)
{
int ret;
+ tty_port_init(&port);
+
bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME);
if (IS_ERR(bfin_jc_kthread))
return PTR_ERR(bfin_jc_kthread);
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index e61cabdd69df..6984e1a2686a 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -1599,7 +1599,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
* If the port is the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->port.close_wait,
+ wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
}
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 8880adf5fc6f..2d691eb7c40a 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -107,7 +107,7 @@ static struct hvc_struct *hvc_get_by_index(int index)
list_for_each_entry(hp, &hvc_structs, next) {
spin_lock_irqsave(&hp->lock, flags);
if (hp->index == index) {
- kref_get(&hp->kref);
+ tty_port_get(&hp->port);
spin_unlock_irqrestore(&hp->lock, flags);
spin_unlock(&hvc_structs_lock);
return hp;
@@ -229,9 +229,9 @@ static int __init hvc_console_init(void)
console_initcall(hvc_console_init);
/* callback when the kboject ref count reaches zero. */
-static void destroy_hvc_struct(struct kref *kref)
+static void hvc_port_destruct(struct tty_port *port)
{
- struct hvc_struct *hp = container_of(kref, struct hvc_struct, kref);
+ struct hvc_struct *hp = container_of(port, struct hvc_struct, port);
unsigned long flags;
spin_lock(&hvc_structs_lock);
@@ -264,7 +264,7 @@ int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops)
/* make sure no no tty has been registered in this index */
hp = hvc_get_by_index(index);
if (hp) {
- kref_put(&hp->kref, destroy_hvc_struct);
+ tty_port_put(&hp->port);
return -1;
}
@@ -313,20 +313,17 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
if (!(hp = hvc_get_by_index(tty->index)))
return -ENODEV;
- spin_lock_irqsave(&hp->lock, flags);
+ spin_lock_irqsave(&hp->port.lock, flags);
/* Check and then increment for fast path open. */
- if (hp->count++ > 0) {
- tty_kref_get(tty);
- spin_unlock_irqrestore(&hp->lock, flags);
+ if (hp->port.count++ > 0) {
+ spin_unlock_irqrestore(&hp->port.lock, flags);
hvc_kick();
return 0;
} /* else count == 0 */
+ spin_unlock_irqrestore(&hp->port.lock, flags);
tty->driver_data = hp;
-
- hp->tty = tty_kref_get(tty);
-
- spin_unlock_irqrestore(&hp->lock, flags);
+ tty_port_tty_set(&hp->port, tty);
if (hp->ops->notifier_add)
rc = hp->ops->notifier_add(hp, hp->data);
@@ -338,12 +335,9 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
* tty fields and return the kref reference.
*/
if (rc) {
- spin_lock_irqsave(&hp->lock, flags);
- hp->tty = NULL;
- spin_unlock_irqrestore(&hp->lock, flags);
- tty_kref_put(tty);
+ tty_port_tty_set(&hp->port, NULL);
tty->driver_data = NULL;
- kref_put(&hp->kref, destroy_hvc_struct);
+ tty_port_put(&hp->port);
printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
}
/* Force wakeup of the polling thread */
@@ -370,12 +364,12 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
hp = tty->driver_data;
- spin_lock_irqsave(&hp->lock, flags);
+ spin_lock_irqsave(&hp->port.lock, flags);
- if (--hp->count == 0) {
+ if (--hp->port.count == 0) {
+ spin_unlock_irqrestore(&hp->port.lock, flags);
/* We are done with the tty pointer now. */
- hp->tty = NULL;
- spin_unlock_irqrestore(&hp->lock, flags);
+ tty_port_tty_set(&hp->port, NULL);
if (hp->ops->notifier_del)
hp->ops->notifier_del(hp, hp->data);
@@ -390,14 +384,13 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
*/
tty_wait_until_sent_from_close(tty, HVC_CLOSE_WAIT);
} else {
- if (hp->count < 0)
+ if (hp->port.count < 0)
printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
- hp->vtermno, hp->count);
- spin_unlock_irqrestore(&hp->lock, flags);
+ hp->vtermno, hp->port.count);
+ spin_unlock_irqrestore(&hp->port.lock, flags);
}
- tty_kref_put(tty);
- kref_put(&hp->kref, destroy_hvc_struct);
+ tty_port_put(&hp->port);
}
static void hvc_hangup(struct tty_struct *tty)
@@ -412,32 +405,31 @@ static void hvc_hangup(struct tty_struct *tty)
/* cancel pending tty resize work */
cancel_work_sync(&hp->tty_resize);
- spin_lock_irqsave(&hp->lock, flags);
+ spin_lock_irqsave(&hp->port.lock, flags);
/*
* The N_TTY line discipline has problems such that in a close vs
* open->hangup case this can be called after the final close so prevent
* that from happening for now.
*/
- if (hp->count <= 0) {
- spin_unlock_irqrestore(&hp->lock, flags);
+ if (hp->port.count <= 0) {
+ spin_unlock_irqrestore(&hp->port.lock, flags);
return;
}
- temp_open_count = hp->count;
- hp->count = 0;
- hp->n_outbuf = 0;
- hp->tty = NULL;
+ temp_open_count = hp->port.count;
+ hp->port.count = 0;
+ spin_unlock_irqrestore(&hp->port.lock, flags);
+ tty_port_tty_set(&hp->port, NULL);
- spin_unlock_irqrestore(&hp->lock, flags);
+ hp->n_outbuf = 0;
if (hp->ops->notifier_hangup)
hp->ops->notifier_hangup(hp, hp->data);
while(temp_open_count) {
--temp_open_count;
- tty_kref_put(tty);
- kref_put(&hp->kref, destroy_hvc_struct);
+ tty_port_put(&hp->port);
}
}
@@ -478,7 +470,8 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count
if (!hp)
return -EPIPE;
- if (hp->count <= 0)
+ /* FIXME what's this (unprotected) check for? */
+ if (hp->port.count <= 0)
return -EIO;
spin_lock_irqsave(&hp->lock, flags);
@@ -526,13 +519,12 @@ static void hvc_set_winsz(struct work_struct *work)
hp = container_of(work, struct hvc_struct, tty_resize);
- spin_lock_irqsave(&hp->lock, hvc_flags);
- if (!hp->tty) {
- spin_unlock_irqrestore(&hp->lock, hvc_flags);
+ tty = tty_port_tty_get(&hp->port);
+ if (!tty)
return;
- }
- ws = hp->ws;
- tty = tty_kref_get(hp->tty);
+
+ spin_lock_irqsave(&hp->lock, hvc_flags);
+ ws = hp->ws;
spin_unlock_irqrestore(&hp->lock, hvc_flags);
tty_do_resize(tty, &ws);
@@ -601,7 +593,7 @@ int hvc_poll(struct hvc_struct *hp)
}
/* No tty attached, just skip */
- tty = tty_kref_get(hp->tty);
+ tty = tty_port_tty_get(&hp->port);
if (tty == NULL)
goto bail;
@@ -681,8 +673,7 @@ int hvc_poll(struct hvc_struct *hp)
tty_flip_buffer_push(tty);
}
- if (tty)
- tty_kref_put(tty);
+ tty_kref_put(tty);
return poll_mask;
}
@@ -817,6 +808,10 @@ static const struct tty_operations hvc_ops = {
#endif
};
+static const struct tty_port_operations hvc_port_ops = {
+ .destruct = hvc_port_destruct,
+};
+
struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
const struct hv_ops *ops,
int outbuf_size)
@@ -842,7 +837,8 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
hp->outbuf_size = outbuf_size;
hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))];
- kref_init(&hp->kref);
+ tty_port_init(&hp->port);
+ hp->port.ops = &hvc_port_ops;
INIT_WORK(&hp->tty_resize, hvc_set_winsz);
spin_lock_init(&hp->lock);
@@ -875,9 +871,9 @@ int hvc_remove(struct hvc_struct *hp)
unsigned long flags;
struct tty_struct *tty;
- spin_lock_irqsave(&hp->lock, flags);
- tty = tty_kref_get(hp->tty);
+ tty = tty_port_tty_get(&hp->port);
+ spin_lock_irqsave(&hp->lock, flags);
if (hp->index < MAX_NR_HVC_CONSOLES)
vtermnos[hp->index] = -1;
@@ -891,7 +887,7 @@ int hvc_remove(struct hvc_struct *hp)
* kref cause it to be removed, which will probably be the tty_vhangup
* below.
*/
- kref_put(&hp->kref, destroy_hvc_struct);
+ tty_port_put(&hp->port);
/*
* This function call will auto chain call hvc_hangup.
diff --git a/drivers/tty/hvc/hvc_console.h b/drivers/tty/hvc/hvc_console.h
index c335a1492a54..674d23cb919a 100644
--- a/drivers/tty/hvc/hvc_console.h
+++ b/drivers/tty/hvc/hvc_console.h
@@ -46,10 +46,9 @@
#define HVC_ALLOC_TTY_ADAPTERS 8
struct hvc_struct {
+ struct tty_port port;
spinlock_t lock;
int index;
- struct tty_struct *tty;
- int count;
int do_wakeup;
char *outbuf;
int outbuf_size;
@@ -61,7 +60,6 @@ struct hvc_struct {
struct winsize ws;
struct work_struct tty_resize;
struct list_head next;
- struct kref kref; /* ref count & hvc_struct lifetime */
};
/* implemented by a low level driver */
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index 83d5c88e7165..d3d91dae065c 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -430,9 +430,9 @@ static int __devinit xencons_probe(struct xenbus_device *dev,
if (devid == 0)
return -ENODEV;
- info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL | __GFP_ZERO);
+ info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
if (!info)
- goto error_nomem;
+ return -ENOMEM;
dev_set_drvdata(&dev->dev, info);
info->xbdev = dev;
info->vtermno = xenbus_devid_to_vtermno(devid);
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index 3436436fe2d7..d56788c83974 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -261,6 +261,7 @@ static DEFINE_SPINLOCK(hvcs_pi_lock);
/* One vty-server per hvcs_struct */
struct hvcs_struct {
+ struct tty_port port;
spinlock_t lock;
/*
@@ -269,9 +270,6 @@ struct hvcs_struct {
*/
unsigned int index;
- struct tty_struct *tty;
- int open_count;
-
/*
* Used to tell the driver kernel_thread what operations need to take
* place upon this hvcs_struct instance.
@@ -290,12 +288,11 @@ struct hvcs_struct {
int chars_in_buffer;
/*
- * Any variable below the kref is valid before a tty is connected and
+ * Any variable below is valid before a tty is connected and
* stays valid after the tty is disconnected. These shouldn't be
* whacked until the kobject refcount reaches zero though some entries
* may be changed via sysfs initiatives.
*/
- struct kref kref; /* ref count & hvcs_struct lifetime */
int connected; /* is the vty-server currently connected to a vty? */
uint32_t p_unit_address; /* partner unit address */
uint32_t p_partition_ID; /* partner partition ID */
@@ -304,9 +301,6 @@ struct hvcs_struct {
struct vio_dev *vdev;
};
-/* Required to back map a kref to its containing object */
-#define from_kref(k) container_of(k, struct hvcs_struct, kref)
-
static LIST_HEAD(hvcs_structs);
static DEFINE_SPINLOCK(hvcs_structs_lock);
static DEFINE_MUTEX(hvcs_init_mutex);
@@ -422,7 +416,7 @@ static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribut
spin_lock_irqsave(&hvcsd->lock, flags);
- if (hvcsd->open_count > 0) {
+ if (hvcsd->port.count > 0) {
spin_unlock_irqrestore(&hvcsd->lock, flags);
printk(KERN_INFO "HVCS: vterm state unchanged. "
"The hvcs device node is still in use.\n");
@@ -564,7 +558,7 @@ static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance)
static void hvcs_try_write(struct hvcs_struct *hvcsd)
{
uint32_t unit_address = hvcsd->vdev->unit_address;
- struct tty_struct *tty = hvcsd->tty;
+ struct tty_struct *tty = hvcsd->port.tty;
int sent;
if (hvcsd->todo_mask & HVCS_TRY_WRITE) {
@@ -602,7 +596,7 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
spin_lock_irqsave(&hvcsd->lock, flags);
unit_address = hvcsd->vdev->unit_address;
- tty = hvcsd->tty;
+ tty = hvcsd->port.tty;
hvcs_try_write(hvcsd);
@@ -701,10 +695,9 @@ static void hvcs_return_index(int index)
hvcs_index_list[index] = -1;
}
-/* callback when the kref ref count reaches zero */
-static void destroy_hvcs_struct(struct kref *kref)
+static void hvcs_destruct_port(struct tty_port *p)
{
- struct hvcs_struct *hvcsd = from_kref(kref);
+ struct hvcs_struct *hvcsd = container_of(p, struct hvcs_struct, port);
struct vio_dev *vdev;
unsigned long flags;
@@ -741,6 +734,10 @@ static void destroy_hvcs_struct(struct kref *kref)
kfree(hvcsd);
}
+static const struct tty_port_operations hvcs_port_ops = {
+ .destruct = hvcs_destruct_port,
+};
+
static int hvcs_get_index(void)
{
int i;
@@ -789,10 +786,9 @@ static int __devinit hvcs_probe(
if (!hvcsd)
return -ENODEV;
-
+ tty_port_init(&hvcsd->port);
+ hvcsd->port.ops = &hvcs_port_ops;
spin_lock_init(&hvcsd->lock);
- /* Automatically incs the refcount the first time */
- kref_init(&hvcsd->kref);
hvcsd->vdev = dev;
dev_set_drvdata(&dev->dev, hvcsd);
@@ -852,7 +848,7 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
spin_lock_irqsave(&hvcsd->lock, flags);
- tty = hvcsd->tty;
+ tty = hvcsd->port.tty;
spin_unlock_irqrestore(&hvcsd->lock, flags);
@@ -860,7 +856,7 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
* Let the last holder of this object cause it to be removed, which
* would probably be tty_hangup below.
*/
- kref_put(&hvcsd->kref, destroy_hvcs_struct);
+ tty_port_put(&hvcsd->port);
/*
* The hangup is a scheduled function which will auto chain call
@@ -1094,7 +1090,7 @@ static struct hvcs_struct *hvcs_get_by_index(int index)
list_for_each_entry(hvcsd, &hvcs_structs, next) {
spin_lock_irqsave(&hvcsd->lock, flags);
if (hvcsd->index == index) {
- kref_get(&hvcsd->kref);
+ tty_port_get(&hvcsd->port);
spin_unlock_irqrestore(&hvcsd->lock, flags);
spin_unlock(&hvcs_structs_lock);
return hvcsd;
@@ -1138,8 +1134,8 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
if ((retval = hvcs_partner_connect(hvcsd)))
goto error_release;
- hvcsd->open_count = 1;
- hvcsd->tty = tty;
+ hvcsd->port.count = 1;
+ hvcsd->port.tty = tty;
tty->driver_data = hvcsd;
memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
@@ -1160,7 +1156,7 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
* and will grab the spinlock and free the connection if it fails.
*/
if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
- kref_put(&hvcsd->kref, destroy_hvcs_struct);
+ tty_port_put(&hvcsd->port);
printk(KERN_WARNING "HVCS: enable device failed.\n");
return rc;
}
@@ -1171,8 +1167,8 @@ fast_open:
hvcsd = tty->driver_data;
spin_lock_irqsave(&hvcsd->lock, flags);
- kref_get(&hvcsd->kref);
- hvcsd->open_count++;
+ tty_port_get(&hvcsd->port);
+ hvcsd->port.count++;
hvcsd->todo_mask |= HVCS_SCHED_READ;
spin_unlock_irqrestore(&hvcsd->lock, flags);
@@ -1186,7 +1182,7 @@ open_success:
error_release:
spin_unlock_irqrestore(&hvcsd->lock, flags);
- kref_put(&hvcsd->kref, destroy_hvcs_struct);
+ tty_port_put(&hvcsd->port);
printk(KERN_WARNING "HVCS: partner connect failed.\n");
return retval;
@@ -1216,7 +1212,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
hvcsd = tty->driver_data;
spin_lock_irqsave(&hvcsd->lock, flags);
- if (--hvcsd->open_count == 0) {
+ if (--hvcsd->port.count == 0) {
vio_disable_interrupts(hvcsd->vdev);
@@ -1225,7 +1221,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
* execute any operations on the TTY even though it is obligated
* to deliver any pending I/O to the hypervisor.
*/
- hvcsd->tty = NULL;
+ hvcsd->port.tty = NULL;
irq = hvcsd->vdev->irq;
spin_unlock_irqrestore(&hvcsd->lock, flags);
@@ -1240,16 +1236,16 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
tty->driver_data = NULL;
free_irq(irq, hvcsd);
- kref_put(&hvcsd->kref, destroy_hvcs_struct);
+ tty_port_put(&hvcsd->port);
return;
- } else if (hvcsd->open_count < 0) {
+ } else if (hvcsd->port.count < 0) {
printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
" is missmanaged.\n",
- hvcsd->vdev->unit_address, hvcsd->open_count);
+ hvcsd->vdev->unit_address, hvcsd->port.count);
}
spin_unlock_irqrestore(&hvcsd->lock, flags);
- kref_put(&hvcsd->kref, destroy_hvcs_struct);
+ tty_port_put(&hvcsd->port);
}
static void hvcs_hangup(struct tty_struct * tty)
@@ -1261,7 +1257,7 @@ static void hvcs_hangup(struct tty_struct * tty)
spin_lock_irqsave(&hvcsd->lock, flags);
/* Preserve this so that we know how many kref refs to put */
- temp_open_count = hvcsd->open_count;
+ temp_open_count = hvcsd->port.count;
/*
* Don't kref put inside the spinlock because the destruction
@@ -1273,10 +1269,10 @@ static void hvcs_hangup(struct tty_struct * tty)
hvcsd->todo_mask = 0;
/* I don't think the tty needs the hvcs_struct pointer after a hangup */
- hvcsd->tty->driver_data = NULL;
- hvcsd->tty = NULL;
+ tty->driver_data = NULL;
+ hvcsd->port.tty = NULL;
- hvcsd->open_count = 0;
+ hvcsd->port.count = 0;
/* This will drop any buffered data on the floor which is OK in a hangup
* scenario. */
@@ -1301,7 +1297,7 @@ static void hvcs_hangup(struct tty_struct * tty)
* NOTE: If this hangup was signaled from user space then the
* final put will never happen.
*/
- kref_put(&hvcsd->kref, destroy_hvcs_struct);
+ tty_port_put(&hvcsd->port);
}
}
@@ -1347,7 +1343,7 @@ static int hvcs_write(struct tty_struct *tty,
* the middle of a write operation? This is a crummy place to do this
* but we want to keep it all in the spinlock.
*/
- if (hvcsd->open_count <= 0) {
+ if (hvcsd->port.count <= 0) {
spin_unlock_irqrestore(&hvcsd->lock, flags);
return -ENODEV;
}
@@ -1421,7 +1417,7 @@ static int hvcs_write_room(struct tty_struct *tty)
{
struct hvcs_struct *hvcsd = tty->driver_data;
- if (!hvcsd || hvcsd->open_count <= 0)
+ if (!hvcsd || hvcsd->port.count <= 0)
return 0;
return HVCS_BUFF_LEN - hvcsd->chars_in_buffer;
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c
index a7488b748647..6f5bc49c441f 100644
--- a/drivers/tty/hvc/hvsi.c
+++ b/drivers/tty/hvc/hvsi.c
@@ -69,14 +69,13 @@
#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
struct hvsi_struct {
+ struct tty_port port;
struct delayed_work writer;
struct work_struct handshaker;
wait_queue_head_t emptyq; /* woken when outbuf is emptied */
wait_queue_head_t stateq; /* woken when HVSI state changes */
spinlock_t lock;
int index;
- struct tty_struct *tty;
- int count;
uint8_t throttle_buf[128];
uint8_t outbuf[N_OUTBUF]; /* to implement write_room and chars_in_buffer */
/* inbuf is for packet reassembly. leave a little room for leftovers. */
@@ -237,7 +236,7 @@ static int hvsi_read(struct hvsi_struct *hp, char *buf, int count)
}
static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet,
- struct tty_struct **to_hangup, struct hvsi_struct **to_handshake)
+ struct tty_struct *tty, struct hvsi_struct **to_handshake)
{
struct hvsi_control *header = (struct hvsi_control *)packet;
@@ -247,9 +246,8 @@ static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet,
/* CD went away; no more connection */
pr_debug("hvsi%i: CD dropped\n", hp->index);
hp->mctrl &= TIOCM_CD;
- /* If userland hasn't done an open(2) yet, hp->tty is NULL. */
- if (hp->tty && !(hp->tty->flags & CLOCAL))
- *to_hangup = hp->tty;
+ if (tty && !C_CLOCAL(tty))
+ tty_hangup(tty);
}
break;
case VSV_CLOSE_PROTOCOL:
@@ -331,7 +329,8 @@ static void hvsi_recv_query(struct hvsi_struct *hp, uint8_t *packet)
}
}
-static void hvsi_insert_chars(struct hvsi_struct *hp, const char *buf, int len)
+static void hvsi_insert_chars(struct hvsi_struct *hp, struct tty_struct *tty,
+ const char *buf, int len)
{
int i;
@@ -347,7 +346,7 @@ static void hvsi_insert_chars(struct hvsi_struct *hp, const char *buf, int len)
continue;
}
#endif /* CONFIG_MAGIC_SYSRQ */
- tty_insert_flip_char(hp->tty, c, 0);
+ tty_insert_flip_char(tty, c, 0);
}
}
@@ -360,7 +359,7 @@ static void hvsi_insert_chars(struct hvsi_struct *hp, const char *buf, int len)
* revisited.
*/
#define TTY_THRESHOLD_THROTTLE 128
-static struct tty_struct *hvsi_recv_data(struct hvsi_struct *hp,
+static bool hvsi_recv_data(struct hvsi_struct *hp, struct tty_struct *tty,
const uint8_t *packet)
{
const struct hvsi_header *header = (const struct hvsi_header *)packet;
@@ -371,14 +370,14 @@ static struct tty_struct *hvsi_recv_data(struct hvsi_struct *hp,
pr_debug("queueing %i chars '%.*s'\n", datalen, datalen, data);
if (datalen == 0)
- return NULL;
+ return false;
if (overflow > 0) {
pr_debug("%s: got >TTY_THRESHOLD_THROTTLE bytes\n", __func__);
datalen = TTY_THRESHOLD_THROTTLE;
}
- hvsi_insert_chars(hp, data, datalen);
+ hvsi_insert_chars(hp, tty, data, datalen);
if (overflow > 0) {
/*
@@ -390,7 +389,7 @@ static struct tty_struct *hvsi_recv_data(struct hvsi_struct *hp,
hp->n_throttle = overflow;
}
- return hp->tty;
+ return true;
}
/*
@@ -399,14 +398,13 @@ static struct tty_struct *hvsi_recv_data(struct hvsi_struct *hp,
* machine during console handshaking (in which case tty = NULL and we ignore
* incoming data).
*/
-static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
- struct tty_struct **hangup, struct hvsi_struct **handshake)
+static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct *tty,
+ struct hvsi_struct **handshake)
{
uint8_t *packet = hp->inbuf;
int chunklen;
+ bool flip = false;
- *flip = NULL;
- *hangup = NULL;
*handshake = NULL;
chunklen = hvsi_read(hp, hp->inbuf_end, HVSI_MAX_READ);
@@ -440,12 +438,12 @@ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
case VS_DATA_PACKET_HEADER:
if (!is_open(hp))
break;
- if (hp->tty == NULL)
+ if (tty == NULL)
break; /* no tty buffer to put data in */
- *flip = hvsi_recv_data(hp, packet);
+ flip = hvsi_recv_data(hp, tty, packet);
break;
case VS_CONTROL_PACKET_HEADER:
- hvsi_recv_control(hp, packet, hangup, handshake);
+ hvsi_recv_control(hp, packet, tty, handshake);
break;
case VS_QUERY_RESPONSE_PACKET_HEADER:
hvsi_recv_response(hp, packet);
@@ -462,28 +460,26 @@ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
packet += len_packet(packet);
- if (*hangup || *handshake) {
- pr_debug("%s: hangup or handshake\n", __func__);
- /*
- * we need to send the hangup now before receiving any more data.
- * If we get "data, hangup, data", we can't deliver the second
- * data before the hangup.
- */
+ if (*handshake) {
+ pr_debug("%s: handshake\n", __func__);
break;
}
}
compact_inbuf(hp, packet);
+ if (flip)
+ tty_flip_buffer_push(tty);
+
return 1;
}
-static void hvsi_send_overflow(struct hvsi_struct *hp)
+static void hvsi_send_overflow(struct hvsi_struct *hp, struct tty_struct *tty)
{
pr_debug("%s: delivering %i bytes overflow\n", __func__,
hp->n_throttle);
- hvsi_insert_chars(hp, hp->throttle_buf, hp->n_throttle);
+ hvsi_insert_chars(hp, tty, hp->throttle_buf, hp->n_throttle);
hp->n_throttle = 0;
}
@@ -494,35 +490,20 @@ static void hvsi_send_overflow(struct hvsi_struct *hp)
static irqreturn_t hvsi_interrupt(int irq, void *arg)
{
struct hvsi_struct *hp = (struct hvsi_struct *)arg;
- struct tty_struct *flip;
- struct tty_struct *hangup;
struct hvsi_struct *handshake;
+ struct tty_struct *tty;
unsigned long flags;
int again = 1;
pr_debug("%s\n", __func__);
+ tty = tty_port_tty_get(&hp->port);
+
while (again) {
spin_lock_irqsave(&hp->lock, flags);
- again = hvsi_load_chunk(hp, &flip, &hangup, &handshake);
+ again = hvsi_load_chunk(hp, tty, &handshake);
spin_unlock_irqrestore(&hp->lock, flags);
- /*
- * we have to call tty_flip_buffer_push() and tty_hangup() outside our
- * spinlock. But we also have to keep going until we've read all the
- * available data.
- */
-
- if (flip) {
- /* there was data put in the tty flip buffer */
- tty_flip_buffer_push(flip);
- flip = NULL;
- }
-
- if (hangup) {
- tty_hangup(hangup);
- }
-
if (handshake) {
pr_debug("hvsi%i: attempting re-handshake\n", handshake->index);
schedule_work(&handshake->handshaker);
@@ -530,18 +511,15 @@ static irqreturn_t hvsi_interrupt(int irq, void *arg)
}
spin_lock_irqsave(&hp->lock, flags);
- if (hp->tty && hp->n_throttle
- && (!test_bit(TTY_THROTTLED, &hp->tty->flags))) {
- /* we weren't hung up and we weren't throttled, so we can deliver the
- * rest now */
- flip = hp->tty;
- hvsi_send_overflow(hp);
+ if (tty && hp->n_throttle && !test_bit(TTY_THROTTLED, &tty->flags)) {
+ /* we weren't hung up and we weren't throttled, so we can
+ * deliver the rest now */
+ hvsi_send_overflow(hp, tty);
+ tty_flip_buffer_push(tty);
}
spin_unlock_irqrestore(&hp->lock, flags);
- if (flip) {
- tty_flip_buffer_push(flip);
- }
+ tty_kref_put(tty);
return IRQ_HANDLED;
}
@@ -749,9 +727,9 @@ static int hvsi_open(struct tty_struct *tty, struct file *filp)
if (hp->state == HVSI_FSP_DIED)
return -EIO;
+ tty_port_tty_set(&hp->port, tty);
spin_lock_irqsave(&hp->lock, flags);
- hp->tty = tty;
- hp->count++;
+ hp->port.count++;
atomic_set(&hp->seqno, 0);
h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE);
spin_unlock_irqrestore(&hp->lock, flags);
@@ -808,8 +786,8 @@ static void hvsi_close(struct tty_struct *tty, struct file *filp)
spin_lock_irqsave(&hp->lock, flags);
- if (--hp->count == 0) {
- hp->tty = NULL;
+ if (--hp->port.count == 0) {
+ tty_port_tty_set(&hp->port, NULL);
hp->inbuf_end = hp->inbuf; /* discard remaining partial packets */
/* only close down connection if it is not the console */
@@ -841,9 +819,9 @@ static void hvsi_close(struct tty_struct *tty, struct file *filp)
spin_lock_irqsave(&hp->lock, flags);
}
- } else if (hp->count < 0)
+ } else if (hp->port.count < 0)
printk(KERN_ERR "hvsi_close %lu: oops, count is %d\n",
- hp - hvsi_ports, hp->count);
+ hp - hvsi_ports, hp->port.count);
spin_unlock_irqrestore(&hp->lock, flags);
}
@@ -855,12 +833,11 @@ static void hvsi_hangup(struct tty_struct *tty)
pr_debug("%s\n", __func__);
- spin_lock_irqsave(&hp->lock, flags);
+ tty_port_tty_set(&hp->port, NULL);
- hp->count = 0;
+ spin_lock_irqsave(&hp->lock, flags);
+ hp->port.count = 0;
hp->n_outbuf = 0;
- hp->tty = NULL;
-
spin_unlock_irqrestore(&hp->lock, flags);
}
@@ -888,6 +865,7 @@ static void hvsi_write_worker(struct work_struct *work)
{
struct hvsi_struct *hp =
container_of(work, struct hvsi_struct, writer.work);
+ struct tty_struct *tty;
unsigned long flags;
#ifdef DEBUG
static long start_j = 0;
@@ -921,7 +899,11 @@ static void hvsi_write_worker(struct work_struct *work)
start_j = 0;
#endif /* DEBUG */
wake_up_all(&hp->emptyq);
- tty_wakeup(hp->tty);
+ tty = tty_port_tty_get(&hp->port);
+ if (tty) {
+ tty_wakeup(tty);
+ tty_kref_put(tty);
+ }
}
out:
@@ -966,8 +948,8 @@ static int hvsi_write(struct tty_struct *tty,
* and hvsi_write_worker will be scheduled. subsequent hvsi_write() calls
* will see there is no room in outbuf and return.
*/
- while ((count > 0) && (hvsi_write_room(hp->tty) > 0)) {
- int chunksize = min(count, hvsi_write_room(hp->tty));
+ while ((count > 0) && (hvsi_write_room(tty) > 0)) {
+ int chunksize = min(count, hvsi_write_room(tty));
BUG_ON(hp->n_outbuf < 0);
memcpy(hp->outbuf + hp->n_outbuf, source, chunksize);
@@ -1014,19 +996,16 @@ static void hvsi_unthrottle(struct tty_struct *tty)
{
struct hvsi_struct *hp = tty->driver_data;
unsigned long flags;
- int shouldflip = 0;
pr_debug("%s\n", __func__);
spin_lock_irqsave(&hp->lock, flags);
if (hp->n_throttle) {
- hvsi_send_overflow(hp);
- shouldflip = 1;
+ hvsi_send_overflow(hp, tty);
+ tty_flip_buffer_push(tty);
}
spin_unlock_irqrestore(&hp->lock, flags);
- if (shouldflip)
- tty_flip_buffer_push(hp->tty);
h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE);
}
@@ -1228,6 +1207,7 @@ static int __init hvsi_console_init(void)
init_waitqueue_head(&hp->emptyq);
init_waitqueue_head(&hp->stateq);
spin_lock_init(&hp->lock);
+ tty_port_init(&hp->port);
hp->index = hvsi_count;
hp->inbuf_end = hp->inbuf;
hp->state = HVSI_CLOSED;
diff --git a/drivers/tty/hvc/hvsi_lib.c b/drivers/tty/hvc/hvsi_lib.c
index 6f4dd83d8695..59c135dd5d20 100644
--- a/drivers/tty/hvc/hvsi_lib.c
+++ b/drivers/tty/hvc/hvsi_lib.c
@@ -377,7 +377,7 @@ int hvsilib_open(struct hvsi_priv *pv, struct hvc_struct *hp)
pr_devel("HVSI@%x: open !\n", pv->termno);
/* Keep track of the tty data structure */
- pv->tty = tty_kref_get(hp->tty);
+ pv->tty = tty_port_tty_get(&hp->port);
hvsilib_establish(pv);
diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c
index 4daf962f7055..f8b5fa0093a3 100644
--- a/drivers/tty/ipwireless/tty.c
+++ b/drivers/tty/ipwireless/tty.c
@@ -44,14 +44,13 @@
#define TTYTYPE_RAS_RAW (2)
struct ipw_tty {
+ struct tty_port port;
int index;
struct ipw_hardware *hardware;
unsigned int channel_idx;
unsigned int secondary_channel_idx;
int tty_type;
struct ipw_network *network;
- struct tty_struct *linux_tty;
- int open_count;
unsigned int control_lines;
struct mutex ipw_tty_mutex;
int tx_bytes_queued;
@@ -73,23 +72,6 @@ static char *tty_type_name(int tty_type)
return channel_names[tty_type];
}
-static void report_registering(struct ipw_tty *tty)
-{
- char *iftype = tty_type_name(tty->tty_type);
-
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": registering %s device ttyIPWp%d\n", iftype, tty->index);
-}
-
-static void report_deregistering(struct ipw_tty *tty)
-{
- char *iftype = tty_type_name(tty->tty_type);
-
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": deregistering %s device ttyIPWp%d\n", iftype,
- tty->index);
-}
-
static struct ipw_tty *get_tty(int index)
{
/*
@@ -117,12 +99,12 @@ static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
mutex_unlock(&tty->ipw_tty_mutex);
return -ENODEV;
}
- if (tty->open_count == 0)
+ if (tty->port.count == 0)
tty->tx_bytes_queued = 0;
- tty->open_count++;
+ tty->port.count++;
- tty->linux_tty = linux_tty;
+ tty->port.tty = linux_tty;
linux_tty->driver_data = tty;
linux_tty->low_latency = 1;
@@ -136,13 +118,13 @@ static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
static void do_ipw_close(struct ipw_tty *tty)
{
- tty->open_count--;
+ tty->port.count--;
- if (tty->open_count == 0) {
- struct tty_struct *linux_tty = tty->linux_tty;
+ if (tty->port.count == 0) {
+ struct tty_struct *linux_tty = tty->port.tty;
if (linux_tty != NULL) {
- tty->linux_tty = NULL;
+ tty->port.tty = NULL;
linux_tty->driver_data = NULL;
if (tty->tty_type == TTYTYPE_MODEM)
@@ -159,7 +141,7 @@ static void ipw_hangup(struct tty_struct *linux_tty)
return;
mutex_lock(&tty->ipw_tty_mutex);
- if (tty->open_count == 0) {
+ if (tty->port.count == 0) {
mutex_unlock(&tty->ipw_tty_mutex);
return;
}
@@ -182,13 +164,13 @@ void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
int work = 0;
mutex_lock(&tty->ipw_tty_mutex);
- linux_tty = tty->linux_tty;
+ linux_tty = tty->port.tty;
if (linux_tty == NULL) {
mutex_unlock(&tty->ipw_tty_mutex);
return;
}
- if (!tty->open_count) {
+ if (!tty->port.count) {
mutex_unlock(&tty->ipw_tty_mutex);
return;
}
@@ -230,7 +212,7 @@ static int ipw_write(struct tty_struct *linux_tty,
return -ENODEV;
mutex_lock(&tty->ipw_tty_mutex);
- if (!tty->open_count) {
+ if (!tty->port.count) {
mutex_unlock(&tty->ipw_tty_mutex);
return -EINVAL;
}
@@ -270,7 +252,7 @@ static int ipw_write_room(struct tty_struct *linux_tty)
if (!tty)
return -ENODEV;
- if (!tty->open_count)
+ if (!tty->port.count)
return -EINVAL;
room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
@@ -312,7 +294,7 @@ static int ipw_chars_in_buffer(struct tty_struct *linux_tty)
if (!tty)
return 0;
- if (!tty->open_count)
+ if (!tty->port.count)
return 0;
return tty->tx_bytes_queued;
@@ -393,7 +375,7 @@ static int ipw_tiocmget(struct tty_struct *linux_tty)
if (!tty)
return -ENODEV;
- if (!tty->open_count)
+ if (!tty->port.count)
return -EINVAL;
return get_control_lines(tty);
@@ -409,7 +391,7 @@ ipw_tiocmset(struct tty_struct *linux_tty,
if (!tty)
return -ENODEV;
- if (!tty->open_count)
+ if (!tty->port.count)
return -EINVAL;
return set_control_lines(tty, set, clear);
@@ -423,7 +405,7 @@ static int ipw_ioctl(struct tty_struct *linux_tty,
if (!tty)
return -ENODEV;
- if (!tty->open_count)
+ if (!tty->port.count)
return -EINVAL;
/* FIXME: Exactly how is the tty object locked here .. */
@@ -492,6 +474,7 @@ static int add_tty(int j,
ttys[j]->network = network;
ttys[j]->tty_type = tty_type;
mutex_init(&ttys[j]->ipw_tty_mutex);
+ tty_port_init(&ttys[j]->port);
tty_register_device(ipw_tty_driver, j, NULL);
ipwireless_associate_network_tty(network, channel_idx, ttys[j]);
@@ -500,8 +483,12 @@ static int add_tty(int j,
ipwireless_associate_network_tty(network,
secondary_channel_idx,
ttys[j]);
- if (get_tty(j) == ttys[j])
- report_registering(ttys[j]);
+ /* check if we provide raw device (if loopback is enabled) */
+ if (get_tty(j))
+ printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+ ": registering %s device ttyIPWp%d\n",
+ tty_type_name(tty_type), j);
+
return 0;
}
@@ -560,19 +547,21 @@ void ipwireless_tty_free(struct ipw_tty *tty)
if (ttyj) {
mutex_lock(&ttyj->ipw_tty_mutex);
- if (get_tty(j) == ttyj)
- report_deregistering(ttyj);
+ if (get_tty(j))
+ printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+ ": deregistering %s device ttyIPWp%d\n",
+ tty_type_name(ttyj->tty_type), j);
ttyj->closing = 1;
- if (ttyj->linux_tty != NULL) {
+ if (ttyj->port.tty != NULL) {
mutex_unlock(&ttyj->ipw_tty_mutex);
- tty_hangup(ttyj->linux_tty);
- /* Wait till the tty_hangup has completed */
- flush_work_sync(&ttyj->linux_tty->hangup_work);
+ tty_vhangup(ttyj->port.tty);
/* FIXME: Exactly how is the tty object locked here
against a parallel ioctl etc */
+ /* FIXME2: hangup does not mean all processes
+ * are gone */
mutex_lock(&ttyj->ipw_tty_mutex);
}
- while (ttyj->open_count)
+ while (ttyj->port.count)
do_ipw_close(ttyj);
ipwireless_disassociate_network_ttys(network,
ttyj->channel_idx);
@@ -661,8 +650,8 @@ ipwireless_tty_notify_control_line_change(struct ipw_tty *tty,
*/
if ((old_control_lines & IPW_CONTROL_LINE_DCD)
&& !(tty->control_lines & IPW_CONTROL_LINE_DCD)
- && tty->linux_tty) {
- tty_hangup(tty->linux_tty);
+ && tty->port.tty) {
+ tty_hangup(tty->port.tty);
}
}
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index c6f372dd5623..90cc680c4f0e 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -2326,7 +2326,7 @@ static const struct tty_operations mxser_ops = {
.get_icount = mxser_get_icount,
};
-struct tty_port_operations mxser_port_ops = {
+static struct tty_port_operations mxser_port_ops = {
.carrier_raised = mxser_carrier_raised,
.dtr_rts = mxser_dtr_rts,
.activate = mxser_activate,
diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c
index 5c6c31459a2f..656ad93bbc96 100644
--- a/drivers/tty/n_r3964.c
+++ b/drivers/tty/n_r3964.c
@@ -1065,7 +1065,8 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
TRACE_L("read()");
- tty_lock();
+ /* FIXME: should use a private lock */
+ tty_lock(tty);
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
@@ -1077,7 +1078,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
goto unlock;
}
/* block until there is a message: */
- wait_event_interruptible_tty(pInfo->read_wait,
+ wait_event_interruptible_tty(tty, pInfo->read_wait,
(pMsg = remove_msg(pInfo, pClient)));
}
@@ -1107,7 +1108,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
}
ret = -EPERM;
unlock:
- tty_unlock();
+ tty_unlock(tty);
return ret;
}
@@ -1156,7 +1157,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
pHeader->locks = 0;
pHeader->owner = NULL;
- tty_lock();
+ tty_lock(tty);
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
@@ -1175,7 +1176,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
add_tx_queue(pInfo, pHeader);
trigger_transmit(pInfo);
- tty_unlock();
+ tty_unlock(tty);
return 0;
}
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 94b6eda87afd..ee1c268f5f9d 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -1630,6 +1630,7 @@ static int copy_from_read_buf(struct tty_struct *tty,
int retval;
size_t n;
unsigned long flags;
+ bool is_eof;
retval = 0;
spin_lock_irqsave(&tty->read_lock, flags);
@@ -1639,15 +1640,15 @@ static int copy_from_read_buf(struct tty_struct *tty,
if (n) {
retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
n -= retval;
+ is_eof = n == 1 &&
+ tty->read_buf[tty->read_tail] == EOF_CHAR(tty);
tty_audit_add_data(tty, &tty->read_buf[tty->read_tail], n);
spin_lock_irqsave(&tty->read_lock, flags);
tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
tty->read_cnt -= n;
/* Turn single EOF into zero-length read */
- if (L_EXTPROC(tty) && tty->icanon && n == 1) {
- if (!tty->read_cnt && (*b)[n-1] == EOF_CHAR(tty))
- n--;
- }
+ if (L_EXTPROC(tty) && tty->icanon && is_eof && !tty->read_cnt)
+ n = 0;
spin_unlock_irqrestore(&tty->read_lock, flags);
*b += n;
*nr -= n;
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index eeae7fafe9a7..59af3945ea85 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -26,11 +26,13 @@
#include <linux/bitops.h>
#include <linux/devpts_fs.h>
#include <linux/slab.h>
+#include <linux/mutex.h>
#ifdef CONFIG_UNIX98_PTYS
static struct tty_driver *ptm_driver;
static struct tty_driver *pts_driver;
+static DEFINE_MUTEX(devpts_mutex);
#endif
static void pty_close(struct tty_struct *tty, struct file *filp)
@@ -45,6 +47,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
wake_up_interruptible(&tty->read_wait);
wake_up_interruptible(&tty->write_wait);
tty->packet = 0;
+ /* Review - krefs on tty_link ?? */
if (!tty->link)
return;
tty->link->packet = 0;
@@ -54,12 +57,15 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
if (tty->driver->subtype == PTY_TYPE_MASTER) {
set_bit(TTY_OTHER_CLOSED, &tty->flags);
#ifdef CONFIG_UNIX98_PTYS
- if (tty->driver == ptm_driver)
+ if (tty->driver == ptm_driver) {
+ mutex_lock(&devpts_mutex);
devpts_pty_kill(tty->link);
+ mutex_unlock(&devpts_mutex);
+ }
#endif
- tty_unlock();
+ tty_unlock(tty);
tty_vhangup(tty->link);
- tty_lock();
+ tty_lock(tty);
}
}
@@ -475,13 +481,17 @@ static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
* @idx: tty index
*
* Look up a pty master device. Called under the tty_mutex for now.
- * This provides our locking.
+ * This provides our locking for the tty pointer.
*/
static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
struct inode *pts_inode, int idx)
{
- struct tty_struct *tty = devpts_get_tty(pts_inode, idx);
+ struct tty_struct *tty;
+
+ mutex_lock(&devpts_mutex);
+ tty = devpts_get_tty(pts_inode, idx);
+ mutex_unlock(&devpts_mutex);
/* Master must be open before slave */
if (!tty)
return ERR_PTR(-EIO);
@@ -613,24 +623,29 @@ static int ptmx_open(struct inode *inode, struct file *filp)
return retval;
/* find a device that is not in use. */
- tty_lock();
+ mutex_lock(&devpts_mutex);
index = devpts_new_index(inode);
- tty_unlock();
if (index < 0) {
retval = index;
goto err_file;
}
+ mutex_unlock(&devpts_mutex);
+
mutex_lock(&tty_mutex);
- tty_lock();
+ mutex_lock(&devpts_mutex);
tty = tty_init_dev(ptm_driver, index);
- mutex_unlock(&tty_mutex);
if (IS_ERR(tty)) {
retval = PTR_ERR(tty);
goto out;
}
+ /* The tty returned here is locked so we can safely
+ drop the mutex */
+ mutex_unlock(&devpts_mutex);
+ mutex_unlock(&tty_mutex);
+
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
tty_add_file(tty, filp);
@@ -643,16 +658,17 @@ static int ptmx_open(struct inode *inode, struct file *filp)
if (retval)
goto err_release;
- tty_unlock();
+ tty_unlock(tty);
return 0;
err_release:
- tty_unlock();
+ tty_unlock(tty);
tty_release(inode, filp);
return retval;
out:
+ mutex_unlock(&tty_mutex);
devpts_kill_index(inode, index);
- tty_unlock();
err_file:
+ mutex_unlock(&devpts_mutex);
tty_free_file(filp);
return retval;
}
diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c
index 5ce782529d65..3ed20e435e59 100644
--- a/drivers/tty/serial/68328serial.c
+++ b/drivers/tty/serial/68328serial.c
@@ -17,6 +17,7 @@
#include <asm/dbg.h>
#include <linux/module.h>
#include <linux/errno.h>
+#include <linux/serial.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/timer.h>
@@ -56,8 +57,6 @@
#endif /* CONFIG_M68VZ328 */
#endif /* CONFIG_M68EZ328 */
-#include "68328serial.h"
-
/* Turn off usage of real serial interrupt code, to "support" Copilot */
#ifdef CONFIG_XCOPILOT_BUGS
#undef USE_INTS
@@ -65,33 +64,82 @@
#define USE_INTS
#endif
-static struct m68k_serial m68k_soft[NR_PORTS];
+/*
+ * I believe this is the optimal setting that reduces the number of interrupts.
+ * At high speeds the output might become a little "bursted" (use USTCNT_TXHE
+ * if that bothers you), but in most cases it will not, since we try to
+ * transmit characters every time rs_interrupt is called. Thus, quite often
+ * you'll see that a receive interrupt occures before the transmit one.
+ * -- Vladimir Gurevich
+ */
+#define USTCNT_TX_INTR_MASK (USTCNT_TXEE)
-static unsigned int uart_irqs[NR_PORTS] = UART_IRQ_DEFNS;
+/*
+ * 68328 and 68EZ328 UARTS are a little bit different. EZ328 has special
+ * "Old data interrupt" which occures whenever the data stay in the FIFO
+ * longer than 30 bits time. This allows us to use FIFO without compromising
+ * latency. '328 does not have this feature and without the real 328-based
+ * board I would assume that RXRE is the safest setting.
+ *
+ * For EZ328 I use RXHE (Half empty) interrupt to reduce the number of
+ * interrupts. RXFE (receive queue full) causes the system to lose data
+ * at least at 115200 baud
+ *
+ * If your board is busy doing other stuff, you might consider to use
+ * RXRE (data ready intrrupt) instead.
+ *
+ * The other option is to make these INTR masks run-time configurable, so
+ * that people can dynamically adapt them according to the current usage.
+ * -- Vladimir Gurevich
+ */
-/* multiple ports are contiguous in memory */
-m68328_uart *uart_addr = (m68328_uart *)USTCNT_ADDR;
+/* (es) */
+#if defined(CONFIG_M68EZ328) || defined(CONFIG_M68VZ328)
+#define USTCNT_RX_INTR_MASK (USTCNT_RXHE | USTCNT_ODEN)
+#elif defined(CONFIG_M68328)
+#define USTCNT_RX_INTR_MASK (USTCNT_RXRE)
+#else
+#error Please, define the Rx interrupt events for your CPU
+#endif
+/* (/es) */
-struct tty_struct m68k_ttys;
-struct m68k_serial *m68k_consinfo = 0;
+/*
+ * This is our internal structure for each serial port's state.
+ */
+struct m68k_serial {
+ struct tty_port tport;
+ char is_cons; /* Is this our console. */
+ int magic;
+ int baud_base;
+ int port;
+ int irq;
+ int type; /* UART type */
+ int custom_divisor;
+ int x_char; /* xon/xoff character */
+ int line;
+ unsigned char *xmit_buf;
+ int xmit_head;
+ int xmit_tail;
+ int xmit_cnt;
+};
-#define M68K_CLOCK (16667000) /* FIXME: 16MHz is likely wrong */
+#define SERIAL_MAGIC 0x5301
-struct tty_driver *serial_driver;
+/*
+ * Define the number of ports supported and their irqs.
+ */
+#define NR_PORTS 1
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
+static struct m68k_serial m68k_soft[NR_PORTS];
-/* Debugging... DEBUG_INTR is bad to use when one of the zs
- * lines is your console ;(
- */
-#undef SERIAL_DEBUG_INTR
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
+static unsigned int uart_irqs[NR_PORTS] = { UART_IRQ_NUM };
-#define RS_ISR_PASS_LIMIT 256
+/* multiple ports are contiguous in memory */
+m68328_uart *uart_addr = (m68328_uart *)USTCNT_ADDR;
+
+struct tty_driver *serial_driver;
-static void change_speed(struct m68k_serial *info);
+static void change_speed(struct m68k_serial *info, struct tty_struct *tty);
/*
* Setup for console. Argument comes from the boot command line.
@@ -143,17 +191,6 @@ static int baud_table[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
9600, 19200, 38400, 57600, 115200, 0 };
-/* Sets or clears DTR/RTS on the requested line */
-static inline void m68k_rtsdtr(struct m68k_serial *ss, int set)
-{
- if (set) {
- /* set the RTS/CTS line */
- } else {
- /* clear it */
- }
- return;
-}
-
/* Utility routines */
static inline int get_baud(struct m68k_serial *ss)
{
@@ -189,7 +226,8 @@ static void rs_stop(struct tty_struct *tty)
static int rs_put_char(char ch)
{
- int flags, loops = 0;
+ unsigned long flags;
+ int loops = 0;
local_irq_save(flags);
@@ -224,28 +262,9 @@ static void rs_start(struct tty_struct *tty)
local_irq_restore(flags);
}
-/* Drop into either the boot monitor or kadb upon receiving a break
- * from keyboard/console input.
- */
-static void batten_down_hatches(void)
-{
- /* Drop into the debugger */
-}
-
-static void status_handle(struct m68k_serial *info, unsigned short status)
+static void receive_chars(struct m68k_serial *info, struct tty_struct *tty,
+ unsigned short rx)
{
- /* If this is console input and this is a
- * 'break asserted' status change interrupt
- * see if we can drop into the debugger
- */
- if((status & URX_BREAK) && info->break_abort)
- batten_down_hatches();
- return;
-}
-
-static void receive_chars(struct m68k_serial *info, unsigned short rx)
-{
- struct tty_struct *tty = info->tty;
m68328_uart *uart = &uart_addr[info->line];
unsigned char ch, flag;
@@ -259,7 +278,6 @@ static void receive_chars(struct m68k_serial *info, unsigned short rx)
if(info->is_cons) {
if(URX_BREAK & rx) { /* whee, break received */
- status_handle(info, rx);
return;
#ifdef CONFIG_MAGIC_SYSRQ
} else if (ch == 0x10) { /* ^P */
@@ -280,16 +298,13 @@ static void receive_chars(struct m68k_serial *info, unsigned short rx)
flag = TTY_NORMAL;
- if(rx & URX_PARITY_ERROR) {
+ if (rx & URX_PARITY_ERROR)
flag = TTY_PARITY;
- status_handle(info, rx);
- } else if(rx & URX_OVRUN) {
+ else if (rx & URX_OVRUN)
flag = TTY_OVERRUN;
- status_handle(info, rx);
- } else if(rx & URX_FRAME_ERROR) {
+ else if (rx & URX_FRAME_ERROR)
flag = TTY_FRAME;
- status_handle(info, rx);
- }
+
tty_insert_flip_char(tty, ch, flag);
#ifndef CONFIG_XCOPILOT_BUGS
} while((rx = uart->urx.w) & URX_DATA_READY);
@@ -301,7 +316,7 @@ clear_and_exit:
return;
}
-static void transmit_chars(struct m68k_serial *info)
+static void transmit_chars(struct m68k_serial *info, struct tty_struct *tty)
{
m68328_uart *uart = &uart_addr[info->line];
@@ -312,7 +327,7 @@ static void transmit_chars(struct m68k_serial *info)
goto clear_and_return;
}
- if((info->xmit_cnt <= 0) || info->tty->stopped) {
+ if ((info->xmit_cnt <= 0) || !tty || tty->stopped) {
/* That's peculiar... TX ints off */
uart->ustcnt &= ~USTCNT_TX_INTR_MASK;
goto clear_and_return;
@@ -340,6 +355,7 @@ clear_and_return:
irqreturn_t rs_interrupt(int irq, void *dev_id)
{
struct m68k_serial *info = dev_id;
+ struct tty_struct *tty = tty_port_tty_get(&info->tport);
m68328_uart *uart;
unsigned short rx;
unsigned short tx;
@@ -350,20 +366,24 @@ irqreturn_t rs_interrupt(int irq, void *dev_id)
#ifdef USE_INTS
tx = uart->utx.w;
- if (rx & URX_DATA_READY) receive_chars(info, rx);
- if (tx & UTX_TX_AVAIL) transmit_chars(info);
+ if (rx & URX_DATA_READY)
+ receive_chars(info, tty, rx);
+ if (tx & UTX_TX_AVAIL)
+ transmit_chars(info, tty);
#else
- receive_chars(info, rx);
+ receive_chars(info, tty, rx);
#endif
+ tty_kref_put(tty);
+
return IRQ_HANDLED;
}
-static int startup(struct m68k_serial * info)
+static int startup(struct m68k_serial *info, struct tty_struct *tty)
{
m68328_uart *uart = &uart_addr[info->line];
unsigned long flags;
- if (info->flags & S_INITIALIZED)
+ if (info->tport.flags & ASYNC_INITIALIZED)
return 0;
if (!info->xmit_buf) {
@@ -380,7 +400,6 @@ static int startup(struct m68k_serial * info)
*/
uart->ustcnt = USTCNT_UEN;
- info->xmit_fifo_size = 1;
uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_TXEN;
(void)uart->urx.w;
@@ -394,17 +413,17 @@ static int startup(struct m68k_serial * info)
uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_RX_INTR_MASK;
#endif
- if (info->tty)
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ if (tty)
+ clear_bit(TTY_IO_ERROR, &tty->flags);
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
/*
* and set the speed of the serial port
*/
- change_speed(info);
+ change_speed(info, tty);
- info->flags |= S_INITIALIZED;
+ info->tport.flags |= ASYNC_INITIALIZED;
local_irq_restore(flags);
return 0;
}
@@ -413,13 +432,13 @@ static int startup(struct m68k_serial * info)
* This routine will shutdown a serial port; interrupts are disabled, and
* DTR is dropped if the hangup on close termio flag is on.
*/
-static void shutdown(struct m68k_serial * info)
+static void shutdown(struct m68k_serial *info, struct tty_struct *tty)
{
m68328_uart *uart = &uart_addr[info->line];
unsigned long flags;
uart->ustcnt = 0; /* All off! */
- if (!(info->flags & S_INITIALIZED))
+ if (!(info->tport.flags & ASYNC_INITIALIZED))
return;
local_irq_save(flags);
@@ -429,10 +448,10 @@ static void shutdown(struct m68k_serial * info)
info->xmit_buf = 0;
}
- if (info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
+ if (tty)
+ set_bit(TTY_IO_ERROR, &tty->flags);
- info->flags &= ~S_INITIALIZED;
+ info->tport.flags &= ~ASYNC_INITIALIZED;
local_irq_restore(flags);
}
@@ -488,7 +507,7 @@ struct {
* This routine is called to set the UART divisor registers to match
* the specified baud rate for a serial port.
*/
-static void change_speed(struct m68k_serial *info)
+static void change_speed(struct m68k_serial *info, struct tty_struct *tty)
{
m68328_uart *uart = &uart_addr[info->line];
unsigned short port;
@@ -496,9 +515,7 @@ static void change_speed(struct m68k_serial *info)
unsigned cflag;
int i;
- if (!info->tty || !info->tty->termios)
- return;
- cflag = info->tty->termios->c_cflag;
+ cflag = tty->termios->c_cflag;
if (!(port = info->port))
return;
@@ -510,7 +527,6 @@ static void change_speed(struct m68k_serial *info)
i = (i & ~CBAUDEX) + B38400;
}
- info->baud = baud_table[i];
uart->ubaud = PUT_FIELD(UBAUD_DIVIDE, hw_baud_table[i].divisor) |
PUT_FIELD(UBAUD_PRESCALER, hw_baud_table[i].prescale);
@@ -807,10 +823,10 @@ static int get_serial_info(struct m68k_serial * info,
tmp.line = info->line;
tmp.port = info->port;
tmp.irq = info->irq;
- tmp.flags = info->flags;
+ tmp.flags = info->tport.flags;
tmp.baud_base = info->baud_base;
- tmp.close_delay = info->close_delay;
- tmp.closing_wait = info->closing_wait;
+ tmp.close_delay = info->tport.close_delay;
+ tmp.closing_wait = info->tport.closing_wait;
tmp.custom_divisor = info->custom_divisor;
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;
@@ -818,9 +834,10 @@ static int get_serial_info(struct m68k_serial * info,
return 0;
}
-static int set_serial_info(struct m68k_serial * info,
+static int set_serial_info(struct m68k_serial *info, struct tty_struct *tty,
struct serial_struct * new_info)
{
+ struct tty_port *port = &info->tport;
struct serial_struct new_serial;
struct m68k_serial old_info;
int retval = 0;
@@ -834,17 +851,17 @@ static int set_serial_info(struct m68k_serial * info,
if (!capable(CAP_SYS_ADMIN)) {
if ((new_serial.baud_base != info->baud_base) ||
(new_serial.type != info->type) ||
- (new_serial.close_delay != info->close_delay) ||
- ((new_serial.flags & ~S_USR_MASK) !=
- (info->flags & ~S_USR_MASK)))
+ (new_serial.close_delay != port->close_delay) ||
+ ((new_serial.flags & ~ASYNC_USR_MASK) !=
+ (port->flags & ~ASYNC_USR_MASK)))
return -EPERM;
- info->flags = ((info->flags & ~S_USR_MASK) |
- (new_serial.flags & S_USR_MASK));
+ port->flags = ((port->flags & ~ASYNC_USR_MASK) |
+ (new_serial.flags & ASYNC_USR_MASK));
info->custom_divisor = new_serial.custom_divisor;
goto check_and_exit;
}
- if (info->count > 1)
+ if (port->count > 1)
return -EBUSY;
/*
@@ -853,14 +870,14 @@ static int set_serial_info(struct m68k_serial * info,
*/
info->baud_base = new_serial.baud_base;
- info->flags = ((info->flags & ~S_FLAGS) |
- (new_serial.flags & S_FLAGS));
+ port->flags = ((port->flags & ~ASYNC_FLAGS) |
+ (new_serial.flags & ASYNC_FLAGS));
info->type = new_serial.type;
- info->close_delay = new_serial.close_delay;
- info->closing_wait = new_serial.closing_wait;
+ port->close_delay = new_serial.close_delay;
+ port->closing_wait = new_serial.closing_wait;
check_and_exit:
- retval = startup(info);
+ retval = startup(info, tty);
return retval;
}
@@ -946,7 +963,7 @@ static int rs_ioctl(struct tty_struct *tty,
return get_serial_info(info,
(struct serial_struct *) arg);
case TIOCSSERIAL:
- return set_serial_info(info,
+ return set_serial_info(info, tty,
(struct serial_struct *) arg);
case TIOCSERGETLSR: /* Get line status register */
return get_lsr_info(info, (unsigned int *) arg);
@@ -965,7 +982,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
- change_speed(info);
+ change_speed(info, tty);
if ((old_termios->c_cflag & CRTSCTS) &&
!(tty->termios->c_cflag & CRTSCTS)) {
@@ -988,6 +1005,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
static void rs_close(struct tty_struct *tty, struct file * filp)
{
struct m68k_serial * info = (struct m68k_serial *)tty->driver_data;
+ struct tty_port *port = &info->tport;
m68328_uart *uart = &uart_addr[info->line];
unsigned long flags;
@@ -1001,7 +1019,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
return;
}
- if ((tty->count == 1) && (info->count != 1)) {
+ if ((tty->count == 1) && (port->count != 1)) {
/*
* Uh, oh. tty->count is 1, which means that the tty
* structure will be freed. Info->count should always
@@ -1010,26 +1028,26 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
* serial port won't be shutdown.
*/
printk("rs_close: bad serial port count; tty->count is 1, "
- "info->count is %d\n", info->count);
- info->count = 1;
+ "port->count is %d\n", port->count);
+ port->count = 1;
}
- if (--info->count < 0) {
+ if (--port->count < 0) {
printk("rs_close: bad serial port count for ttyS%d: %d\n",
- info->line, info->count);
- info->count = 0;
+ info->line, port->count);
+ port->count = 0;
}
- if (info->count) {
+ if (port->count) {
local_irq_restore(flags);
return;
}
- info->flags |= S_CLOSING;
+ port->flags |= ASYNC_CLOSING;
/*
* Now we wait for the transmit buffer to clear; and we notify
* the line discipline to only process XON/XOFF characters.
*/
tty->closing = 1;
- if (info->closing_wait != S_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, info->closing_wait);
+ if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ tty_wait_until_sent(tty, port->closing_wait);
/*
* At this point we stop accepting input. To do this, we
* disable the receive line status interrupts, and tell the
@@ -1040,13 +1058,12 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
uart->ustcnt &= ~USTCNT_RXEN;
uart->ustcnt &= ~(USTCNT_RXEN | USTCNT_RX_INTR_MASK);
- shutdown(info);
+ shutdown(info, tty);
rs_flush_buffer(tty);
tty_ldisc_flush(tty);
tty->closing = 0;
- info->event = 0;
- info->tty = NULL;
+ tty_port_tty_set(&info->tport, NULL);
#warning "This is not and has never been valid so fix it"
#if 0
if (tty->ldisc.num != ldiscs[N_TTY].num) {
@@ -1058,14 +1075,13 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
(tty->ldisc.open)(tty);
}
#endif
- if (info->blocked_open) {
- if (info->close_delay) {
- msleep_interruptible(jiffies_to_msecs(info->close_delay));
- }
- wake_up_interruptible(&info->open_wait);
+ if (port->blocked_open) {
+ if (port->close_delay)
+ msleep_interruptible(jiffies_to_msecs(port->close_delay));
+ wake_up_interruptible(&port->open_wait);
}
- info->flags &= ~(S_NORMAL_ACTIVE|S_CLOSING);
- wake_up_interruptible(&info->close_wait);
+ port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+ wake_up_interruptible(&port->close_wait);
local_irq_restore(flags);
}
@@ -1080,107 +1096,14 @@ void rs_hangup(struct tty_struct *tty)
return;
rs_flush_buffer(tty);
- shutdown(info);
- info->event = 0;
- info->count = 0;
- info->flags &= ~S_NORMAL_ACTIVE;
- info->tty = NULL;
- wake_up_interruptible(&info->open_wait);
+ shutdown(info, tty);
+ info->tport.count = 0;
+ info->tport.flags &= ~ASYNC_NORMAL_ACTIVE;
+ tty_port_tty_set(&info->tport, NULL);
+ wake_up_interruptible(&info->tport.open_wait);
}
/*
- * ------------------------------------------------------------
- * rs_open() and friends
- * ------------------------------------------------------------
- */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
- struct m68k_serial *info)
-{
- DECLARE_WAITQUEUE(wait, current);
- int retval;
- int do_clocal = 0;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (info->flags & S_CLOSING) {
- interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
- if (info->flags & S_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
-#else
- return -EAGAIN;
-#endif
- }
-
- /*
- * If non-blocking mode is set, or the port is not enabled,
- * then make the check up front and then exit.
- */
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR))) {
- info->flags |= S_NORMAL_ACTIVE;
- return 0;
- }
-
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
-
- /*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, info->count is dropped by one, so that
- * rs_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
- retval = 0;
- add_wait_queue(&info->open_wait, &wait);
-
- info->count--;
- info->blocked_open++;
- while (1) {
- local_irq_disable();
- m68k_rtsdtr(info, 1);
- local_irq_enable();
- current->state = TASK_INTERRUPTIBLE;
- if (tty_hung_up_p(filp) ||
- !(info->flags & S_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
- if (info->flags & S_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
-#else
- retval = -EAGAIN;
-#endif
- break;
- }
- if (!(info->flags & S_CLOSING) && do_clocal)
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- tty_unlock();
- schedule();
- tty_lock();
- }
- current->state = TASK_RUNNING;
- remove_wait_queue(&info->open_wait, &wait);
- if (!tty_hung_up_p(filp))
- info->count++;
- info->blocked_open--;
-
- if (retval)
- return retval;
- info->flags |= S_NORMAL_ACTIVE;
- return 0;
-}
-
-/*
* This routine is called whenever a serial port is opened. It
* enables interrupts for a serial port, linking in its S structure into
* the IRQ chain. It also performs the serial-specific
@@ -1196,18 +1119,18 @@ int rs_open(struct tty_struct *tty, struct file * filp)
if (serial_paranoia_check(info, tty->name, "rs_open"))
return -ENODEV;
- info->count++;
+ info->tport.count++;
tty->driver_data = info;
- info->tty = tty;
+ tty_port_tty_set(&info->tport, tty);
/*
* Start up serial port
*/
- retval = startup(info);
+ retval = startup(info, tty);
if (retval)
return retval;
- return block_til_ready(tty, filp, info);
+ return tty_port_block_til_ready(&info->tport, tty, filp);
}
/* Finally, routines used to initialize the serial driver. */
@@ -1235,11 +1158,15 @@ static const struct tty_operations rs_ops = {
.set_ldisc = rs_set_ldisc,
};
+static const struct tty_port_operations rs_port_ops = {
+};
+
/* rs_init inits the driver */
static int __init
rs68328_init(void)
{
- int flags, i;
+ unsigned long flags;
+ int i;
struct m68k_serial *info;
serial_driver = alloc_tty_driver(NR_PORTS);
@@ -1273,19 +1200,13 @@ rs68328_init(void)
for(i=0;i<NR_PORTS;i++) {
info = &m68k_soft[i];
+ tty_port_init(&info->tport);
+ info->tport.ops = &rs_port_ops;
info->magic = SERIAL_MAGIC;
info->port = (int) &uart_addr[i];
- info->tty = NULL;
info->irq = uart_irqs[i];
info->custom_divisor = 16;
- info->close_delay = 50;
- info->closing_wait = 3000;
info->x_char = 0;
- info->event = 0;
- info->count = 0;
- info->blocked_open = 0;
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
info->line = i;
info->is_cons = 1; /* Means shortcuts work */
diff --git a/drivers/tty/serial/68328serial.h b/drivers/tty/serial/68328serial.h
deleted file mode 100644
index 3d2faabd766f..000000000000
--- a/drivers/tty/serial/68328serial.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* 68328serial.h: Definitions for the mc68328 serial driver.
- *
- * Copyright (C) 1995 David S. Miller <davem@caip.rutgers.edu>
- * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
- * Copyright (C) 1998, 1999 D. Jeff Dionne <jeff@uclinux.org>
- * Copyright (C) 1999 Vladimir Gurevich <vgurevic@cisco.com>
- *
- * VZ Support/Fixes Evan Stawnyczy <e@lineo.ca>
- */
-
-#ifndef _MC683XX_SERIAL_H
-#define _MC683XX_SERIAL_H
-
-
-struct serial_struct {
- int type;
- int line;
- int port;
- int irq;
- int flags;
- int xmit_fifo_size;
- int custom_divisor;
- int baud_base;
- unsigned short close_delay;
- char reserved_char[2];
- int hub6; /* FIXME: We don't have AT&T Hub6 boards! */
- unsigned short closing_wait; /* time to wait before closing */
- unsigned short closing_wait2; /* no longer used... */
- int reserved[4];
-};
-
-/*
- * For the close wait times, 0 means wait forever for serial port to
- * flush its output. 65535 means don't wait at all.
- */
-#define S_CLOSING_WAIT_INF 0
-#define S_CLOSING_WAIT_NONE 65535
-
-/*
- * Definitions for S_struct (and serial_struct) flags field
- */
-#define S_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes
- on the callout port */
-#define S_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */
-#define S_SAK 0x0004 /* Secure Attention Key (Orange book) */
-#define S_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
-
-#define S_SPD_MASK 0x0030
-#define S_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */
-
-#define S_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */
-#define S_SPD_CUST 0x0030 /* Use user-specified divisor */
-
-#define S_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */
-#define S_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */
-#define S_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
-#define S_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */
-#define S_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */
-
-#define S_FLAGS 0x0FFF /* Possible legal S flags */
-#define S_USR_MASK 0x0430 /* Legal flags that non-privileged
- * users can set or reset */
-
-/* Internal flags used only by kernel/chr_drv/serial.c */
-#define S_INITIALIZED 0x80000000 /* Serial port was initialized */
-#define S_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */
-#define S_NORMAL_ACTIVE 0x20000000 /* Normal device is active */
-#define S_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */
-#define S_CLOSING 0x08000000 /* Serial port is closing */
-#define S_CTS_FLOW 0x04000000 /* Do CTS flow control */
-#define S_CHECK_CD 0x02000000 /* i.e., CLOCAL */
-
-/* Software state per channel */
-
-#ifdef __KERNEL__
-
-/*
- * I believe this is the optimal setting that reduces the number of interrupts.
- * At high speeds the output might become a little "bursted" (use USTCNT_TXHE
- * if that bothers you), but in most cases it will not, since we try to
- * transmit characters every time rs_interrupt is called. Thus, quite often
- * you'll see that a receive interrupt occures before the transmit one.
- * -- Vladimir Gurevich
- */
-#define USTCNT_TX_INTR_MASK (USTCNT_TXEE)
-
-/*
- * 68328 and 68EZ328 UARTS are a little bit different. EZ328 has special
- * "Old data interrupt" which occures whenever the data stay in the FIFO
- * longer than 30 bits time. This allows us to use FIFO without compromising
- * latency. '328 does not have this feature and without the real 328-based
- * board I would assume that RXRE is the safest setting.
- *
- * For EZ328 I use RXHE (Half empty) interrupt to reduce the number of
- * interrupts. RXFE (receive queue full) causes the system to lose data
- * at least at 115200 baud
- *
- * If your board is busy doing other stuff, you might consider to use
- * RXRE (data ready intrrupt) instead.
- *
- * The other option is to make these INTR masks run-time configurable, so
- * that people can dynamically adapt them according to the current usage.
- * -- Vladimir Gurevich
- */
-
-/* (es) */
-#if defined(CONFIG_M68EZ328) || defined(CONFIG_M68VZ328)
-#define USTCNT_RX_INTR_MASK (USTCNT_RXHE | USTCNT_ODEN)
-#elif defined(CONFIG_M68328)
-#define USTCNT_RX_INTR_MASK (USTCNT_RXRE)
-#else
-#error Please, define the Rx interrupt events for your CPU
-#endif
-/* (/es) */
-
-/*
- * This is our internal structure for each serial port's state.
- *
- * Many fields are paralleled by the structure used by the serial_struct
- * structure.
- *
- * For definitions of the flags field, see tty.h
- */
-
-struct m68k_serial {
- char soft_carrier; /* Use soft carrier on this channel */
- char break_abort; /* Is serial console in, so process brk/abrt */
- char is_cons; /* Is this our console. */
-
- /* We need to know the current clock divisor
- * to read the bps rate the chip has currently
- * loaded.
- */
- unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */
- int baud;
- int magic;
- int baud_base;
- int port;
- int irq;
- int flags; /* defined in tty.h */
- int type; /* UART type */
- struct tty_struct *tty;
- int read_status_mask;
- int ignore_status_mask;
- int timeout;
- int xmit_fifo_size;
- int custom_divisor;
- int x_char; /* xon/xoff character */
- int close_delay;
- unsigned short closing_wait;
- unsigned short closing_wait2;
- unsigned long event;
- unsigned long last_active;
- int line;
- int count; /* # of fd on device */
- int blocked_open; /* # of blocked opens */
- unsigned char *xmit_buf;
- int xmit_head;
- int xmit_tail;
- int xmit_cnt;
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
-};
-
-
-#define SERIAL_MAGIC 0x5301
-
-/*
- * The size of the serial xmit buffer is 1 page, or 4096 bytes
- */
-#define SERIAL_XMIT_SIZE 4096
-
-/*
- * Events are used to schedule things to happen at timer-interrupt
- * time, instead of at rs interrupt time.
- */
-#define RS_EVENT_WRITE_WAKEUP 0
-
-/*
- * Define the number of ports supported and their irqs.
- */
-#define NR_PORTS 1
-#define UART_IRQ_DEFNS {UART_IRQ_NUM}
-
-#endif /* __KERNEL__ */
-#endif /* !(_MC683XX_SERIAL_H) */
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 5c27f7e6c9f1..47d061b9ad4d 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -284,7 +284,20 @@ static const struct serial8250_config uart_config[] = {
},
};
-#if defined(CONFIG_MIPS_ALCHEMY)
+/* Uart divisor latch read */
+static int default_serial_dl_read(struct uart_8250_port *up)
+{
+ return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
+}
+
+/* Uart divisor latch write */
+static void default_serial_dl_write(struct uart_8250_port *up, int value)
+{
+ serial_out(up, UART_DLL, value & 0xff);
+ serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+#ifdef CONFIG_MIPS_ALCHEMY
/* Au1x00 UART hardware has a weird register layout */
static const u8 au_io_in_map[] = {
@@ -305,22 +318,32 @@ static const u8 au_io_out_map[] = {
[UART_MCR] = 6,
};
-/* sane hardware needs no mapping */
-static inline int map_8250_in_reg(struct uart_port *p, int offset)
+static unsigned int au_serial_in(struct uart_port *p, int offset)
+{
+ offset = au_io_in_map[offset] << p->regshift;
+ return __raw_readl(p->membase + offset);
+}
+
+static void au_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = au_io_out_map[offset] << p->regshift;
+ __raw_writel(value, p->membase + offset);
+}
+
+/* Au1x00 haven't got a standard divisor latch */
+static int au_serial_dl_read(struct uart_8250_port *up)
{
- if (p->iotype != UPIO_AU)
- return offset;
- return au_io_in_map[offset];
+ return __raw_readl(up->port.membase + 0x28);
}
-static inline int map_8250_out_reg(struct uart_port *p, int offset)
+static void au_serial_dl_write(struct uart_8250_port *up, int value)
{
- if (p->iotype != UPIO_AU)
- return offset;
- return au_io_out_map[offset];
+ __raw_writel(value, up->port.membase + 0x28);
}
-#elif defined(CONFIG_SERIAL_8250_RM9K)
+#endif
+
+#ifdef CONFIG_SERIAL_8250_RM9K
static const u8
regmap_in[8] = {
@@ -344,87 +367,79 @@ static const u8
[UART_SCR] = 0x2c
};
-static inline int map_8250_in_reg(struct uart_port *p, int offset)
+static unsigned int rm9k_serial_in(struct uart_port *p, int offset)
{
- if (p->iotype != UPIO_RM9000)
- return offset;
- return regmap_in[offset];
+ offset = regmap_in[offset] << p->regshift;
+ return readl(p->membase + offset);
}
-static inline int map_8250_out_reg(struct uart_port *p, int offset)
+static void rm9k_serial_out(struct uart_port *p, int offset, int value)
{
- if (p->iotype != UPIO_RM9000)
- return offset;
- return regmap_out[offset];
+ offset = regmap_out[offset] << p->regshift;
+ writel(value, p->membase + offset);
}
-#else
+static int rm9k_serial_dl_read(struct uart_8250_port *up)
+{
+ return ((__raw_readl(up->port.membase + 0x10) << 8) |
+ (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff;
+}
-/* sane hardware needs no mapping */
-#define map_8250_in_reg(up, offset) (offset)
-#define map_8250_out_reg(up, offset) (offset)
+static void rm9k_serial_dl_write(struct uart_8250_port *up, int value)
+{
+ __raw_writel(value, up->port.membase + 0x08);
+ __raw_writel(value >> 8, up->port.membase + 0x10);
+}
#endif
static unsigned int hub6_serial_in(struct uart_port *p, int offset)
{
- offset = map_8250_in_reg(p, offset) << p->regshift;
+ offset = offset << p->regshift;
outb(p->hub6 - 1 + offset, p->iobase);
return inb(p->iobase + 1);
}
static void hub6_serial_out(struct uart_port *p, int offset, int value)
{
- offset = map_8250_out_reg(p, offset) << p->regshift;
+ offset = offset << p->regshift;
outb(p->hub6 - 1 + offset, p->iobase);
outb(value, p->iobase + 1);
}
static unsigned int mem_serial_in(struct uart_port *p, int offset)
{
- offset = map_8250_in_reg(p, offset) << p->regshift;
+ offset = offset << p->regshift;
return readb(p->membase + offset);
}
static void mem_serial_out(struct uart_port *p, int offset, int value)
{
- offset = map_8250_out_reg(p, offset) << p->regshift;
+ offset = offset << p->regshift;
writeb(value, p->membase + offset);
}
static void mem32_serial_out(struct uart_port *p, int offset, int value)
{
- offset = map_8250_out_reg(p, offset) << p->regshift;
+ offset = offset << p->regshift;
writel(value, p->membase + offset);
}
static unsigned int mem32_serial_in(struct uart_port *p, int offset)
{
- offset = map_8250_in_reg(p, offset) << p->regshift;
+ offset = offset << p->regshift;
return readl(p->membase + offset);
}
-static unsigned int au_serial_in(struct uart_port *p, int offset)
-{
- offset = map_8250_in_reg(p, offset) << p->regshift;
- return __raw_readl(p->membase + offset);
-}
-
-static void au_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = map_8250_out_reg(p, offset) << p->regshift;
- __raw_writel(value, p->membase + offset);
-}
-
static unsigned int io_serial_in(struct uart_port *p, int offset)
{
- offset = map_8250_in_reg(p, offset) << p->regshift;
+ offset = offset << p->regshift;
return inb(p->iobase + offset);
}
static void io_serial_out(struct uart_port *p, int offset, int value)
{
- offset = map_8250_out_reg(p, offset) << p->regshift;
+ offset = offset << p->regshift;
outb(value, p->iobase + offset);
}
@@ -434,6 +449,10 @@ static void set_io_from_upio(struct uart_port *p)
{
struct uart_8250_port *up =
container_of(p, struct uart_8250_port, port);
+
+ up->dl_read = default_serial_dl_read;
+ up->dl_write = default_serial_dl_write;
+
switch (p->iotype) {
case UPIO_HUB6:
p->serial_in = hub6_serial_in;
@@ -445,16 +464,28 @@ static void set_io_from_upio(struct uart_port *p)
p->serial_out = mem_serial_out;
break;
- case UPIO_RM9000:
case UPIO_MEM32:
p->serial_in = mem32_serial_in;
p->serial_out = mem32_serial_out;
break;
+#ifdef CONFIG_SERIAL_8250_RM9K
+ case UPIO_RM9000:
+ p->serial_in = rm9k_serial_in;
+ p->serial_out = rm9k_serial_out;
+ up->dl_read = rm9k_serial_dl_read;
+ up->dl_write = rm9k_serial_dl_write;
+ break;
+#endif
+
+#ifdef CONFIG_MIPS_ALCHEMY
case UPIO_AU:
p->serial_in = au_serial_in;
p->serial_out = au_serial_out;
+ up->dl_read = au_serial_dl_read;
+ up->dl_write = au_serial_dl_write;
break;
+#endif
default:
p->serial_in = io_serial_in;
@@ -481,59 +512,6 @@ serial_port_out_sync(struct uart_port *p, int offset, int value)
}
}
-/* Uart divisor latch read */
-static inline int _serial_dl_read(struct uart_8250_port *up)
-{
- return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
-}
-
-/* Uart divisor latch write */
-static inline void _serial_dl_write(struct uart_8250_port *up, int value)
-{
- serial_out(up, UART_DLL, value & 0xff);
- serial_out(up, UART_DLM, value >> 8 & 0xff);
-}
-
-#if defined(CONFIG_MIPS_ALCHEMY)
-/* Au1x00 haven't got a standard divisor latch */
-static int serial_dl_read(struct uart_8250_port *up)
-{
- if (up->port.iotype == UPIO_AU)
- return __raw_readl(up->port.membase + 0x28);
- else
- return _serial_dl_read(up);
-}
-
-static void serial_dl_write(struct uart_8250_port *up, int value)
-{
- if (up->port.iotype == UPIO_AU)
- __raw_writel(value, up->port.membase + 0x28);
- else
- _serial_dl_write(up, value);
-}
-#elif defined(CONFIG_SERIAL_8250_RM9K)
-static int serial_dl_read(struct uart_8250_port *up)
-{
- return (up->port.iotype == UPIO_RM9000) ?
- (((__raw_readl(up->port.membase + 0x10) << 8) |
- (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
- _serial_dl_read(up);
-}
-
-static void serial_dl_write(struct uart_8250_port *up, int value)
-{
- if (up->port.iotype == UPIO_RM9000) {
- __raw_writel(value, up->port.membase + 0x08);
- __raw_writel(value >> 8, up->port.membase + 0x10);
- } else {
- _serial_dl_write(up, value);
- }
-}
-#else
-#define serial_dl_read(up) _serial_dl_read(up)
-#define serial_dl_write(up, value) _serial_dl_write(up, value)
-#endif
-
/*
* For the 16C950
*/
@@ -568,6 +546,16 @@ static void serial8250_clear_fifos(struct uart_8250_port *p)
}
}
+void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
+{
+ unsigned char fcr;
+
+ serial8250_clear_fifos(p);
+ fcr = uart_config[p->port.type].fcr;
+ serial_out(p, UART_FCR, fcr);
+}
+EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
+
/*
* IER sleep support. UARTs which have EFRs need the "extended
* capability" bit enabled. Note that on XR16C850s, we need to
@@ -1332,27 +1320,6 @@ static void serial8250_enable_ms(struct uart_port *port)
}
/*
- * Clear the Tegra rx fifo after a break
- *
- * FIXME: This needs to become a port specific callback once we have a
- * framework for this
- */
-static void clear_rx_fifo(struct uart_8250_port *up)
-{
- unsigned int status, tmout = 10000;
- do {
- status = serial_in(up, UART_LSR);
- if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
- status = serial_in(up, UART_RX);
- else
- break;
- if (--tmout == 0)
- break;
- udelay(1);
- } while (1);
-}
-
-/*
* serial8250_rx_chars: processes according to the passed in LSR
* value, and returns the remaining LSR bits not handled
* by this Rx routine.
@@ -1386,20 +1353,10 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
up->lsr_saved_flags = 0;
if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
- /*
- * For statistics only
- */
if (lsr & UART_LSR_BI) {
lsr &= ~(UART_LSR_FE | UART_LSR_PE);
port->icount.brk++;
/*
- * If tegra port then clear the rx fifo to
- * accept another break/character.
- */
- if (port->type == PORT_TEGRA)
- clear_rx_fifo(up);
-
- /*
* We do the SysRQ and SAK checking
* here because otherwise the break
* may get masked by ignore_status_mask
@@ -2280,10 +2237,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
quot++;
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
- if (baud < 2400)
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
- else
- fcr = uart_config[port->type].fcr;
+ fcr = uart_config[port->type].fcr;
+ if (baud < 2400) {
+ fcr &= ~UART_FCR_TRIGGER_MASK;
+ fcr |= UART_FCR_TRIGGER_1;
+ }
}
/*
@@ -3037,6 +2995,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
port.serial_in = p->serial_in;
port.serial_out = p->serial_out;
port.handle_irq = p->handle_irq;
+ port.handle_break = p->handle_break;
port.set_termios = p->set_termios;
port.pm = p->pm;
port.dev = &dev->dev;
@@ -3153,7 +3112,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
}
/**
- * serial8250_register_port - register a serial port
+ * serial8250_register_8250_port - register a serial port
* @port: serial port template
*
* Configure the serial port specified by the request. If the
@@ -3165,50 +3124,56 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
*
* On success the port is ready to use and the line number is returned.
*/
-int serial8250_register_port(struct uart_port *port)
+int serial8250_register_8250_port(struct uart_8250_port *up)
{
struct uart_8250_port *uart;
int ret = -ENOSPC;
- if (port->uartclk == 0)
+ if (up->port.uartclk == 0)
return -EINVAL;
mutex_lock(&serial_mutex);
- uart = serial8250_find_match_or_unused(port);
+ uart = serial8250_find_match_or_unused(&up->port);
if (uart) {
uart_remove_one_port(&serial8250_reg, &uart->port);
- uart->port.iobase = port->iobase;
- uart->port.membase = port->membase;
- uart->port.irq = port->irq;
- uart->port.irqflags = port->irqflags;
- uart->port.uartclk = port->uartclk;
- uart->port.fifosize = port->fifosize;
- uart->port.regshift = port->regshift;
- uart->port.iotype = port->iotype;
- uart->port.flags = port->flags | UPF_BOOT_AUTOCONF;
- uart->port.mapbase = port->mapbase;
- uart->port.private_data = port->private_data;
- if (port->dev)
- uart->port.dev = port->dev;
-
- if (port->flags & UPF_FIXED_TYPE)
- serial8250_init_fixed_type_port(uart, port->type);
+ uart->port.iobase = up->port.iobase;
+ uart->port.membase = up->port.membase;
+ uart->port.irq = up->port.irq;
+ uart->port.irqflags = up->port.irqflags;
+ uart->port.uartclk = up->port.uartclk;
+ uart->port.fifosize = up->port.fifosize;
+ uart->port.regshift = up->port.regshift;
+ uart->port.iotype = up->port.iotype;
+ uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF;
+ uart->port.mapbase = up->port.mapbase;
+ uart->port.private_data = up->port.private_data;
+ if (up->port.dev)
+ uart->port.dev = up->port.dev;
+
+ if (up->port.flags & UPF_FIXED_TYPE)
+ serial8250_init_fixed_type_port(uart, up->port.type);
set_io_from_upio(&uart->port);
/* Possibly override default I/O functions. */
- if (port->serial_in)
- uart->port.serial_in = port->serial_in;
- if (port->serial_out)
- uart->port.serial_out = port->serial_out;
- if (port->handle_irq)
- uart->port.handle_irq = port->handle_irq;
+ if (up->port.serial_in)
+ uart->port.serial_in = up->port.serial_in;
+ if (up->port.serial_out)
+ uart->port.serial_out = up->port.serial_out;
+ if (up->port.handle_irq)
+ uart->port.handle_irq = up->port.handle_irq;
/* Possibly override set_termios call */
- if (port->set_termios)
- uart->port.set_termios = port->set_termios;
- if (port->pm)
- uart->port.pm = port->pm;
+ if (up->port.set_termios)
+ uart->port.set_termios = up->port.set_termios;
+ if (up->port.pm)
+ uart->port.pm = up->port.pm;
+ if (up->port.handle_break)
+ uart->port.handle_break = up->port.handle_break;
+ if (up->dl_read)
+ uart->dl_read = up->dl_read;
+ if (up->dl_write)
+ uart->dl_write = up->dl_write;
if (serial8250_isa_config != NULL)
serial8250_isa_config(0, &uart->port,
@@ -3222,6 +3187,29 @@ int serial8250_register_port(struct uart_port *port)
return ret;
}
+EXPORT_SYMBOL(serial8250_register_8250_port);
+
+/**
+ * serial8250_register_port - register a serial port
+ * @port: serial port template
+ *
+ * Configure the serial port specified by the request. If the
+ * port exists and is in use, it is hung up and unregistered
+ * first.
+ *
+ * The port is then probed and if necessary the IRQ is autodetected
+ * If this fails an error is returned.
+ *
+ * On success the port is ready to use and the line number is returned.
+ */
+int serial8250_register_port(struct uart_port *port)
+{
+ struct uart_8250_port up;
+
+ memset(&up, 0, sizeof(up));
+ memcpy(&up.port, port, sizeof(*port));
+ return serial8250_register_8250_port(&up);
+}
EXPORT_SYMBOL(serial8250_register_port);
/**
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 2868a1da254d..f9719d167c8d 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -37,6 +37,10 @@ struct uart_8250_port {
unsigned char lsr_saved_flags;
#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
unsigned char msr_saved_flags;
+
+ /* 8250 specific callbacks */
+ int (*dl_read)(struct uart_8250_port *);
+ void (*dl_write)(struct uart_8250_port *, int);
};
struct old_serial_port {
@@ -96,6 +100,18 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value)
up->port.serial_out(&up->port, offset, value);
}
+void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p);
+
+static inline int serial_dl_read(struct uart_8250_port *up)
+{
+ return up->dl_read(up);
+}
+
+static inline void serial_dl_write(struct uart_8250_port *up, int value)
+{
+ up->dl_write(up, value);
+}
+
#if defined(__alpha__) && !defined(CONFIG_PCI)
/*
* Digital did something really horribly wrong with the OUT1 and OUT2
diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
new file mode 100644
index 000000000000..3a0363e7f3a7
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_em.c
@@ -0,0 +1,186 @@
+/*
+ * Renesas Emma Mobile 8250 driver
+ *
+ * Copyright (C) 2012 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+
+#include "8250.h"
+
+#define UART_DLL_EM 9
+#define UART_DLM_EM 10
+
+struct serial8250_em_priv {
+ struct clk *sclk;
+ int line;
+};
+
+static void serial8250_em_serial_out(struct uart_port *p, int offset, int value)
+{
+ switch (offset) {
+ case UART_TX: /* TX @ 0x00 */
+ writeb(value, p->membase);
+ break;
+ case UART_FCR: /* FCR @ 0x0c (+1) */
+ case UART_LCR: /* LCR @ 0x10 (+1) */
+ case UART_MCR: /* MCR @ 0x14 (+1) */
+ case UART_SCR: /* SCR @ 0x20 (+1) */
+ writel(value, p->membase + ((offset + 1) << 2));
+ break;
+ case UART_IER: /* IER @ 0x04 */
+ value &= 0x0f; /* only 4 valid bits - not Xscale */
+ /* fall-through */
+ case UART_DLL_EM: /* DLL @ 0x24 (+9) */
+ case UART_DLM_EM: /* DLM @ 0x28 (+9) */
+ writel(value, p->membase + (offset << 2));
+ }
+}
+
+static unsigned int serial8250_em_serial_in(struct uart_port *p, int offset)
+{
+ switch (offset) {
+ case UART_RX: /* RX @ 0x00 */
+ return readb(p->membase);
+ case UART_MCR: /* MCR @ 0x14 (+1) */
+ case UART_LSR: /* LSR @ 0x18 (+1) */
+ case UART_MSR: /* MSR @ 0x1c (+1) */
+ case UART_SCR: /* SCR @ 0x20 (+1) */
+ return readl(p->membase + ((offset + 1) << 2));
+ case UART_IER: /* IER @ 0x04 */
+ case UART_IIR: /* IIR @ 0x08 */
+ case UART_DLL_EM: /* DLL @ 0x24 (+9) */
+ case UART_DLM_EM: /* DLM @ 0x28 (+9) */
+ return readl(p->membase + (offset << 2));
+ }
+ return 0;
+}
+
+static int serial8250_em_serial_dl_read(struct uart_8250_port *up)
+{
+ return serial_in(up, UART_DLL_EM) | serial_in(up, UART_DLM_EM) << 8;
+}
+
+static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value)
+{
+ serial_out(up, UART_DLL_EM, value & 0xff);
+ serial_out(up, UART_DLM_EM, value >> 8 & 0xff);
+}
+
+static int __devinit serial8250_em_probe(struct platform_device *pdev)
+{
+ struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ struct serial8250_em_priv *priv;
+ struct uart_8250_port up;
+ int ret = -EINVAL;
+
+ if (!regs || !irq) {
+ dev_err(&pdev->dev, "missing registers or irq\n");
+ goto err0;
+ }
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(&pdev->dev, "unable to allocate private data\n");
+ ret = -ENOMEM;
+ goto err0;
+ }
+
+ priv->sclk = clk_get(&pdev->dev, "sclk");
+ if (IS_ERR(priv->sclk)) {
+ dev_err(&pdev->dev, "unable to get clock\n");
+ ret = PTR_ERR(priv->sclk);
+ goto err1;
+ }
+
+ memset(&up, 0, sizeof(up));
+ up.port.mapbase = regs->start;
+ up.port.irq = irq->start;
+ up.port.type = PORT_UNKNOWN;
+ up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;
+ up.port.dev = &pdev->dev;
+ up.port.private_data = priv;
+
+ clk_enable(priv->sclk);
+ up.port.uartclk = clk_get_rate(priv->sclk);
+
+ up.port.iotype = UPIO_MEM32;
+ up.port.serial_in = serial8250_em_serial_in;
+ up.port.serial_out = serial8250_em_serial_out;
+ up.dl_read = serial8250_em_serial_dl_read;
+ up.dl_write = serial8250_em_serial_dl_write;
+
+ ret = serial8250_register_8250_port(&up);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "unable to register 8250 port\n");
+ goto err2;
+ }
+
+ priv->line = ret;
+ platform_set_drvdata(pdev, priv);
+ return 0;
+
+ err2:
+ clk_disable(priv->sclk);
+ clk_put(priv->sclk);
+ err1:
+ kfree(priv);
+ err0:
+ return ret;
+}
+
+static int __devexit serial8250_em_remove(struct platform_device *pdev)
+{
+ struct serial8250_em_priv *priv = platform_get_drvdata(pdev);
+
+ serial8250_unregister_port(priv->line);
+ clk_disable(priv->sclk);
+ clk_put(priv->sclk);
+ kfree(priv);
+ return 0;
+}
+
+static const struct of_device_id serial8250_em_dt_ids[] __devinitconst = {
+ { .compatible = "renesas,em-uart", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, serial8250_em_dt_ids);
+
+static struct platform_driver serial8250_em_platform_driver = {
+ .driver = {
+ .name = "serial8250-em",
+ .of_match_table = serial8250_em_dt_ids,
+ .owner = THIS_MODULE,
+ },
+ .probe = serial8250_em_probe,
+ .remove = __devexit_p(serial8250_em_remove),
+};
+
+module_platform_driver(serial8250_em_platform_driver);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("Renesas Emma Mobile 8250 Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 858dca865d6a..28e7c7cce893 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/tty.h>
+#include <linux/serial_reg.h>
#include <linux/serial_core.h>
#include <linux/8250_pci.h>
#include <linux/bitops.h>
@@ -1092,11 +1093,49 @@ static int skip_tx_en_setup(struct serial_private *priv,
return pci_default_setup(priv, board, port, idx);
}
+static void kt_handle_break(struct uart_port *p)
+{
+ struct uart_8250_port *up =
+ container_of(p, struct uart_8250_port, port);
+ /*
+ * On receipt of a BI, serial device in Intel ME (Intel
+ * management engine) needs to have its fifos cleared for sane
+ * SOL (Serial Over Lan) output.
+ */
+ serial8250_clear_and_reinit_fifos(up);
+}
+
+static unsigned int kt_serial_in(struct uart_port *p, int offset)
+{
+ struct uart_8250_port *up =
+ container_of(p, struct uart_8250_port, port);
+ unsigned int val;
+
+ /*
+ * When the Intel ME (management engine) gets reset its serial
+ * port registers could return 0 momentarily. Functions like
+ * serial8250_console_write, read and save the IER, perform
+ * some operation and then restore it. In order to avoid
+ * setting IER register inadvertently to 0, if the value read
+ * is 0, double check with ier value in uart_8250_port and use
+ * that instead. up->ier should be the same value as what is
+ * currently configured.
+ */
+ val = inb(p->iobase + offset);
+ if (offset == UART_IER) {
+ if (val == 0)
+ val = up->ier;
+ }
+ return val;
+}
+
static int kt_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_port *port, int idx)
{
port->flags |= UPF_BUG_THRE;
+ port->serial_in = kt_serial_in;
+ port->handle_break = kt_handle_break;
return skip_tx_en_setup(priv, board, port, idx);
}
@@ -1609,54 +1648,72 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x8811,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x8812,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x8813,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x8814,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x8027,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x8028,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x8029,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x800C,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x800D,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
.init = pci_eg20t_init,
.setup = pci_default_setup,
},
@@ -2775,6 +2832,12 @@ void pciserial_suspend_ports(struct serial_private *priv)
for (i = 0; i < priv->nr; i++)
if (priv->line[i] >= 0)
serial8250_suspend_port(priv->line[i]);
+
+ /*
+ * Ensure that every init quirk is properly torn down
+ */
+ if (priv->quirk->exit)
+ priv->quirk->exit(priv->dev);
}
EXPORT_SYMBOL_GPL(pciserial_suspend_ports);
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 175c2041847f..a27dd0569bd7 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -269,3 +269,11 @@ config SERIAL_8250_DW
help
Selecting this option will enable handling of the extra features
present in the Synopsys DesignWare APB UART.
+
+config SERIAL_8250_EM
+ tristate "Support for Emma Mobile intergrated serial port"
+ depends on SERIAL_8250 && ARM && HAVE_CLK
+ help
+ Selecting this option will add support for the integrated serial
+ port hardware found on the Emma Mobile line of processors.
+ If unsure, say N.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 464320f52dab..d7533c7d2c1a 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o
obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o
+obj-$(CONFIG_SERIAL_8250_EM) += 8250_em.o
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 3d569cd68f58..4ad721fb8405 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -52,6 +52,7 @@
#include <linux/scatterlist.h>
#include <linux/delay.h>
#include <linux/types.h>
+#include <linux/pinctrl/consumer.h>
#include <asm/io.h>
#include <asm/sizes.h>
@@ -67,30 +68,6 @@
#define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE)
#define UART_DUMMY_DR_RX (1 << 16)
-
-#define UART_WA_SAVE_NR 14
-
-static void pl011_lockup_wa(unsigned long data);
-static const u32 uart_wa_reg[UART_WA_SAVE_NR] = {
- ST_UART011_DMAWM,
- ST_UART011_TIMEOUT,
- ST_UART011_LCRH_RX,
- UART011_IBRD,
- UART011_FBRD,
- ST_UART011_LCRH_TX,
- UART011_IFLS,
- ST_UART011_XFCR,
- ST_UART011_XON1,
- ST_UART011_XON2,
- ST_UART011_XOFF1,
- ST_UART011_XOFF2,
- UART011_CR,
- UART011_IMSC
-};
-
-static u32 uart_wa_regdata[UART_WA_SAVE_NR];
-static DECLARE_TASKLET(pl011_lockup_tlet, pl011_lockup_wa, 0);
-
/* There is by now at least one vendor with differing details, so handle it */
struct vendor_data {
unsigned int ifls;
@@ -100,6 +77,7 @@ struct vendor_data {
bool oversampling;
bool interrupt_may_hang; /* vendor-specific */
bool dma_threshold;
+ bool cts_event_workaround;
};
static struct vendor_data vendor_arm = {
@@ -109,6 +87,7 @@ static struct vendor_data vendor_arm = {
.lcrh_rx = UART011_LCRH,
.oversampling = false,
.dma_threshold = false,
+ .cts_event_workaround = false,
};
static struct vendor_data vendor_st = {
@@ -119,6 +98,7 @@ static struct vendor_data vendor_st = {
.oversampling = true,
.interrupt_may_hang = true,
.dma_threshold = true,
+ .cts_event_workaround = true,
};
static struct uart_amba_port *amba_ports[UART_NR];
@@ -1054,69 +1034,6 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
#define pl011_dma_flush_buffer NULL
#endif
-
-/*
- * pl011_lockup_wa
- * This workaround aims to break the deadlock situation
- * when after long transfer over uart in hardware flow
- * control, uart interrupt registers cannot be cleared.
- * Hence uart transfer gets blocked.
- *
- * It is seen that during such deadlock condition ICR
- * don't get cleared even on multiple write. This leads
- * pass_counter to decrease and finally reach zero. This
- * can be taken as trigger point to run this UART_BT_WA.
- *
- */
-static void pl011_lockup_wa(unsigned long data)
-{
- struct uart_amba_port *uap = amba_ports[0];
- void __iomem *base = uap->port.membase;
- struct circ_buf *xmit = &uap->port.state->xmit;
- struct tty_struct *tty = uap->port.state->port.tty;
- int buf_empty_retries = 200;
- int loop;
-
- /* Stop HCI layer from submitting data for tx */
- tty->hw_stopped = 1;
- while (!uart_circ_empty(xmit)) {
- if (buf_empty_retries-- == 0)
- break;
- udelay(100);
- }
-
- /* Backup registers */
- for (loop = 0; loop < UART_WA_SAVE_NR; loop++)
- uart_wa_regdata[loop] = readl(base + uart_wa_reg[loop]);
-
- /* Disable UART so that FIFO data is flushed out */
- writew(0x00, uap->port.membase + UART011_CR);
-
- /* Soft reset UART module */
- if (uap->port.dev->platform_data) {
- struct amba_pl011_data *plat;
-
- plat = uap->port.dev->platform_data;
- if (plat->reset)
- plat->reset();
- }
-
- /* Restore registers */
- for (loop = 0; loop < UART_WA_SAVE_NR; loop++)
- writew(uart_wa_regdata[loop] ,
- uap->port.membase + uart_wa_reg[loop]);
-
- /* Initialise the old status of the modem signals */
- uap->old_status = readw(uap->port.membase + UART01x_FR) &
- UART01x_FR_MODEM_ANY;
-
- if (readl(base + UART011_MIS) & 0x2)
- printk(KERN_EMERG "UART_BT_WA: ***FAILED***\n");
-
- /* Start Tx/Rx */
- tty->hw_stopped = 0;
-}
-
static void pl011_stop_tx(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
@@ -1245,12 +1162,26 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
unsigned long flags;
unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
int handled = 0;
+ unsigned int dummy_read;
spin_lock_irqsave(&uap->port.lock, flags);
status = readw(uap->port.membase + UART011_MIS);
if (status) {
do {
+ if (uap->vendor->cts_event_workaround) {
+ /* workaround to make sure that all bits are unlocked.. */
+ writew(0x00, uap->port.membase + UART011_ICR);
+
+ /*
+ * WA: introduce 26ns(1 uart clk) delay before W1C;
+ * single apb access will incur 2 pclk(133.12Mhz) delay,
+ * so add 2 dummy reads
+ */
+ dummy_read = readw(uap->port.membase + UART011_ICR);
+ dummy_read = readw(uap->port.membase + UART011_ICR);
+ }
+
writew(status & ~(UART011_TXIS|UART011_RTIS|
UART011_RXIS),
uap->port.membase + UART011_ICR);
@@ -1267,11 +1198,8 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
if (status & UART011_TXIS)
pl011_tx_chars(uap);
- if (pass_counter-- == 0) {
- if (uap->interrupt_may_hang)
- tasklet_schedule(&pl011_lockup_tlet);
+ if (pass_counter-- == 0)
break;
- }
status = readw(uap->port.membase + UART011_MIS);
} while (status != 0);
@@ -1916,6 +1844,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
{
struct uart_amba_port *uap;
struct vendor_data *vendor = id->data;
+ struct pinctrl *pinctrl;
void __iomem *base;
int i, ret;
@@ -1940,6 +1869,12 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
goto free;
}
+ pinctrl = devm_pinctrl_get_select_default(&dev->dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ goto unmap;
+ }
+
uap->clk = clk_get(&dev->dev, NULL);
if (IS_ERR(uap->clk)) {
ret = PTR_ERR(uap->clk);
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index 5832fdef11e9..bd97db23985b 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -1,7 +1,7 @@
/*
* Blackfin On-Chip Serial Driver
*
- * Copyright 2006-2010 Analog Devices Inc.
+ * Copyright 2006-2011 Analog Devices Inc.
*
* Enter bugs at http://blackfin.uclinux.org/
*
@@ -35,10 +35,6 @@
#include <asm/portmux.h>
#include <asm/cacheflush.h>
#include <asm/dma.h>
-
-#define port_membase(uart) (((struct bfin_serial_port *)(uart))->port.membase)
-#define get_lsr_cache(uart) (((struct bfin_serial_port *)(uart))->lsr)
-#define put_lsr_cache(uart, v) (((struct bfin_serial_port *)(uart))->lsr = (v))
#include <asm/bfin_serial.h>
#ifdef CONFIG_SERIAL_BFIN_MODULE
@@ -166,7 +162,7 @@ static void bfin_serial_stop_tx(struct uart_port *port)
uart->tx_count = 0;
uart->tx_done = 1;
#else
-#ifdef CONFIG_BF54x
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
/* Clear TFI bit */
UART_PUT_LSR(uart, TFI);
#endif
@@ -337,7 +333,7 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
struct circ_buf *xmit = &uart->port.state->xmit;
if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
-#ifdef CONFIG_BF54x
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
/* Clear TFI bit */
UART_PUT_LSR(uart, TFI);
#endif
@@ -536,7 +532,7 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
*/
UART_CLEAR_IER(uart, ETBEI);
uart->port.icount.tx += uart->tx_count;
- if (!uart_circ_empty(xmit)) {
+ if (!(xmit->tail == 0 && xmit->head == 0)) {
xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
@@ -553,7 +549,7 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
{
struct bfin_serial_port *uart = dev_id;
- unsigned short irqstat;
+ unsigned int irqstat;
int x_pos, pos;
spin_lock(&uart->rx_lock);
@@ -586,7 +582,7 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
static unsigned int bfin_serial_tx_empty(struct uart_port *port)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- unsigned short lsr;
+ unsigned int lsr;
lsr = UART_GET_LSR(uart);
if (lsr & TEMT)
@@ -598,7 +594,7 @@ static unsigned int bfin_serial_tx_empty(struct uart_port *port)
static void bfin_serial_break_ctl(struct uart_port *port, int break_state)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- u16 lcr = UART_GET_LCR(uart);
+ u32 lcr = UART_GET_LCR(uart);
if (break_state)
lcr |= SB;
else
@@ -745,7 +741,7 @@ static int bfin_serial_startup(struct uart_port *port)
}
/* CTS RTS PINs are negative assertive. */
- UART_PUT_MCR(uart, ACTS);
+ UART_PUT_MCR(uart, UART_GET_MCR(uart) | ACTS);
UART_SET_IER(uart, EDSSI);
}
#endif
@@ -803,7 +799,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
unsigned long flags;
unsigned int baud, quot;
- unsigned short val, ier, lcr = 0;
+ unsigned int ier, lcr = 0;
switch (termios->c_cflag & CSIZE) {
case CS8:
@@ -875,26 +871,23 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
/* Disable UART */
ier = UART_GET_IER(uart);
+ UART_PUT_GCTL(uart, UART_GET_GCTL(uart) & ~UCEN);
UART_DISABLE_INTS(uart);
- /* Set DLAB in LCR to Access DLL and DLH */
+ /* Set DLAB in LCR to Access CLK */
UART_SET_DLAB(uart);
- UART_PUT_DLL(uart, quot & 0xFF);
- UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
+ UART_PUT_CLK(uart, quot);
SSYNC();
/* Clear DLAB in LCR to Access THR RBR IER */
UART_CLEAR_DLAB(uart);
- UART_PUT_LCR(uart, lcr);
+ UART_PUT_LCR(uart, (UART_GET_LCR(uart) & ~LCR_MASK) | lcr);
/* Enable UART */
UART_ENABLE_INTS(uart, ier);
-
- val = UART_GET_GCTL(uart);
- val |= UCEN;
- UART_PUT_GCTL(uart, val);
+ UART_PUT_GCTL(uart, UART_GET_GCTL(uart) | UCEN);
/* Port speed changed, update the per-port timeout. */
uart_update_timeout(port, termios->c_cflag, baud);
@@ -954,17 +947,17 @@ bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
static void bfin_serial_set_ldisc(struct uart_port *port, int ld)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- unsigned short val;
+ unsigned int val;
switch (ld) {
case N_IRDA:
val = UART_GET_GCTL(uart);
- val |= (IREN | RPOLC);
+ val |= (UMOD_IRDA | RPOLC);
UART_PUT_GCTL(uart, val);
break;
default:
val = UART_GET_GCTL(uart);
- val &= ~(IREN | RPOLC);
+ val &= ~(UMOD_MASK | RPOLC);
UART_PUT_GCTL(uart, val);
}
}
@@ -972,13 +965,13 @@ static void bfin_serial_set_ldisc(struct uart_port *port, int ld)
static void bfin_serial_reset_irda(struct uart_port *port)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- unsigned short val;
+ unsigned int val;
val = UART_GET_GCTL(uart);
- val &= ~(IREN | RPOLC);
+ val &= ~(UMOD_MASK | RPOLC);
UART_PUT_GCTL(uart, val);
SSYNC();
- val |= (IREN | RPOLC);
+ val |= (UMOD_IRDA | RPOLC);
UART_PUT_GCTL(uart, val);
SSYNC();
}
@@ -1070,12 +1063,12 @@ static void __init
bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
int *parity, int *bits)
{
- unsigned short status;
+ unsigned int status;
status = UART_GET_IER(uart) & (ERBFI | ETBEI);
if (status == (ERBFI | ETBEI)) {
/* ok, the port was enabled */
- u16 lcr, dlh, dll;
+ u32 lcr, clk;
lcr = UART_GET_LCR(uart);
@@ -1086,30 +1079,17 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
else
*parity = 'o';
}
- switch (lcr & 0x03) {
- case 0:
- *bits = 5;
- break;
- case 1:
- *bits = 6;
- break;
- case 2:
- *bits = 7;
- break;
- case 3:
- *bits = 8;
- break;
- }
- /* Set DLAB in LCR to Access DLL and DLH */
+ *bits = ((lcr & WLS_MASK) >> WLS_OFFSET) + 5;
+
+ /* Set DLAB in LCR to Access CLK */
UART_SET_DLAB(uart);
- dll = UART_GET_DLL(uart);
- dlh = UART_GET_DLH(uart);
+ clk = UART_GET_CLK(uart);
/* Clear DLAB in LCR to Access THR RBR IER */
UART_CLEAR_DLAB(uart);
- *baud = get_sclk() / (16*(dll | dlh << 8));
+ *baud = get_sclk() / (16*clk);
}
pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __func__, *baud, *parity, *bits);
}
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index 836fe2731234..d0f719fafc84 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -40,7 +40,6 @@
#include <mach/hardware.h>
#include <asm/irq.h>
-#include <asm/hardware/clps7111.h>
#define UART_NR 2
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c
index 5b07c0c3a10c..7264d4d26717 100644
--- a/drivers/tty/serial/crisv10.c
+++ b/drivers/tty/serial/crisv10.c
@@ -952,19 +952,6 @@ static const struct control_pins e100_modem_pins[NR_PORTS] =
/* Input */
#define E100_DSR_GET(info) ((*e100_modem_pins[(info)->line].dsr_port) & e100_modem_pins[(info)->line].dsr_mask)
-
-/*
- * tmp_buf is used as a temporary buffer by serial_write. We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char *tmp_buf;
-static DEFINE_MUTEX(tmp_buf_mutex);
-
/* Calculate the chartime depending on baudrate, numbor of bits etc. */
static void update_char_time(struct e100_serial * info)
{
@@ -3150,7 +3137,7 @@ static int rs_raw_write(struct tty_struct *tty,
/* first some sanity checks */
- if (!tty || !info->xmit.buf || !tmp_buf)
+ if (!tty || !info->xmit.buf)
return 0;
#ifdef SERIAL_DEBUG_DATA
@@ -3989,7 +3976,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->close_wait,
+ wait_event_interruptible_tty(tty, info->close_wait,
!(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
if (info->flags & ASYNC_HUP_NOTIFY)
@@ -4065,9 +4052,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
printk("block_til_ready blocking: ttyS%d, count = %d\n",
info->line, info->count);
#endif
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&info->open_wait, &wait);
@@ -4106,7 +4093,6 @@ rs_open(struct tty_struct *tty, struct file * filp)
{
struct e100_serial *info;
int retval;
- unsigned long page;
int allocated_resources = 0;
info = rs_table + tty->index;
@@ -4124,23 +4110,12 @@ rs_open(struct tty_struct *tty, struct file * filp)
tty->low_latency = !!(info->flags & ASYNC_LOW_LATENCY);
- if (!tmp_buf) {
- page = get_zeroed_page(GFP_KERNEL);
- if (!page) {
- return -ENOMEM;
- }
- if (tmp_buf)
- free_page(page);
- else
- tmp_buf = (unsigned char *) page;
- }
-
/*
* If the port is in the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->close_wait,
+ wait_event_interruptible_tty(tty, info->close_wait,
!(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
return ((info->flags & ASYNC_HUP_NOTIFY) ?
@@ -4487,6 +4462,7 @@ static int __init rs_init(void)
info->enabled = 0;
}
}
+ tty_port_init(&info->port);
info->uses_dma_in = 0;
info->uses_dma_out = 0;
info->line = i;
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index e7feceeebc2f..ec206732f68c 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -47,6 +47,7 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -1464,6 +1465,7 @@ static int serial_imx_probe(struct platform_device *pdev)
void __iomem *base;
int ret = 0;
struct resource *res;
+ struct pinctrl *pinctrl;
sport = kzalloc(sizeof(*sport), GFP_KERNEL);
if (!sport)
@@ -1503,6 +1505,12 @@ static int serial_imx_probe(struct platform_device *pdev)
sport->timer.function = imx_timeout;
sport->timer.data = (unsigned long)sport;
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ goto unmap;
+ }
+
sport->clk = clk_get(&pdev->dev, "uart");
if (IS_ERR(sport->clk)) {
ret = PTR_ERR(sport->clk);
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 55fd362b9879..ec56d8397aae 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -32,6 +32,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/pinctrl/consumer.h>
#include <asm/cacheflush.h>
@@ -369,6 +370,8 @@ static void mxs_auart_settermios(struct uart_port *u,
writel(ctrl, u->membase + AUART_LINECTRL);
writel(ctrl2, u->membase + AUART_CTRL2);
+
+ uart_update_timeout(u, termios->c_cflag, baud);
}
static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
@@ -678,6 +681,7 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
u32 version;
int ret = 0;
struct resource *r;
+ struct pinctrl *pinctrl;
s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL);
if (!s) {
@@ -685,6 +689,12 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
goto out;
}
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ goto out_free;
+ }
+
s->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(s->clk)) {
ret = PTR_ERR(s->clk);
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index e8c9cee07d00..5410c0637266 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -12,10 +12,13 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/delay.h>
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
+#include <linux/serial_reg.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/of_serial.h>
#include <linux/of_platform.h>
#include <linux/nwpserial.h>
@@ -24,6 +27,26 @@ struct of_serial_info {
int line;
};
+#ifdef CONFIG_ARCH_TEGRA
+void tegra_serial_handle_break(struct uart_port *p)
+{
+ unsigned int status, tmout = 10000;
+
+ do {
+ status = p->serial_in(p, UART_LSR);
+ if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
+ status = p->serial_in(p, UART_RX);
+ else
+ break;
+ if (--tmout == 0)
+ break;
+ udelay(1);
+ } while (1);
+}
+/* FIXME remove this export when tegra finishes conversion to open firmware */
+EXPORT_SYMBOL_GPL(tegra_serial_handle_break);
+#endif
+
/*
* Fill a struct uart_port for a given device node
*/
@@ -84,6 +107,9 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
| UPF_FIXED_PORT | UPF_FIXED_TYPE;
port->dev = &ofdev->dev;
+ if (type == PORT_TEGRA)
+ port->handle_break = tegra_serial_handle_break;
+
return 0;
}
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index d00b38eb268e..d3cda0cb2df0 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -44,6 +44,13 @@
#include <plat/dmtimer.h>
#include <plat/omap-serial.h>
+#define UART_BUILD_REVISION(x, y) (((x) << 8) | (y))
+
+#define OMAP_UART_REV_42 0x0402
+#define OMAP_UART_REV_46 0x0406
+#define OMAP_UART_REV_52 0x0502
+#define OMAP_UART_REV_63 0x0603
+
#define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/
/* SCR register bitmasks */
@@ -53,6 +60,17 @@
#define OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT 6
#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6)
+/* MVR register bitmasks */
+#define OMAP_UART_MVR_SCHEME_SHIFT 30
+
+#define OMAP_UART_LEGACY_MVR_MAJ_MASK 0xf0
+#define OMAP_UART_LEGACY_MVR_MAJ_SHIFT 4
+#define OMAP_UART_LEGACY_MVR_MIN_MASK 0x0f
+
+#define OMAP_UART_MVR_MAJ_MASK 0x700
+#define OMAP_UART_MVR_MAJ_SHIFT 8
+#define OMAP_UART_MVR_MIN_MASK 0x3f
+
static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
/* Forward declaration of functions */
@@ -1346,6 +1364,59 @@ static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)
return;
}
+static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
+{
+ u32 mvr, scheme;
+ u16 revision, major, minor;
+
+ mvr = serial_in(up, UART_OMAP_MVER);
+
+ /* Check revision register scheme */
+ scheme = mvr >> OMAP_UART_MVR_SCHEME_SHIFT;
+
+ switch (scheme) {
+ case 0: /* Legacy Scheme: OMAP2/3 */
+ /* MINOR_REV[0:4], MAJOR_REV[4:7] */
+ major = (mvr & OMAP_UART_LEGACY_MVR_MAJ_MASK) >>
+ OMAP_UART_LEGACY_MVR_MAJ_SHIFT;
+ minor = (mvr & OMAP_UART_LEGACY_MVR_MIN_MASK);
+ break;
+ case 1:
+ /* New Scheme: OMAP4+ */
+ /* MINOR_REV[0:5], MAJOR_REV[8:10] */
+ major = (mvr & OMAP_UART_MVR_MAJ_MASK) >>
+ OMAP_UART_MVR_MAJ_SHIFT;
+ minor = (mvr & OMAP_UART_MVR_MIN_MASK);
+ break;
+ default:
+ dev_warn(&up->pdev->dev,
+ "Unknown %s revision, defaulting to highest\n",
+ up->name);
+ /* highest possible revision */
+ major = 0xff;
+ minor = 0xff;
+ }
+
+ /* normalize revision for the driver */
+ revision = UART_BUILD_REVISION(major, minor);
+
+ switch (revision) {
+ case OMAP_UART_REV_46:
+ up->errata |= (UART_ERRATA_i202_MDR1_ACCESS |
+ UART_ERRATA_i291_DMA_FORCEIDLE);
+ break;
+ case OMAP_UART_REV_52:
+ up->errata |= (UART_ERRATA_i202_MDR1_ACCESS |
+ UART_ERRATA_i291_DMA_FORCEIDLE);
+ break;
+ case OMAP_UART_REV_63:
+ up->errata |= UART_ERRATA_i202_MDR1_ACCESS;
+ break;
+ default:
+ break;
+ }
+}
+
static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
{
struct omap_uart_port_info *omap_up_info;
@@ -1439,7 +1510,6 @@ static int serial_omap_probe(struct platform_device *pdev)
"%d\n", DEFAULT_CLK_SPEED);
}
up->uart_dma.uart_base = mem->start;
- up->errata = omap_up_info->errata;
if (omap_up_info->dma_enabled) {
up->uart_dma.uart_dma_tx = dma_tx->start;
@@ -1469,6 +1539,8 @@ static int serial_omap_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
+ omap_serial_fill_features_erratas(up);
+
ui[up->port.line] = up;
serial_omap_add_console_port(up);
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index c2816f494807..4fdec6a6b758 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -39,6 +39,7 @@ enum {
PCH_UART_HANDLED_RX_ERR_INT_SHIFT,
PCH_UART_HANDLED_RX_TRG_INT_SHIFT,
PCH_UART_HANDLED_MS_INT_SHIFT,
+ PCH_UART_HANDLED_LS_INT_SHIFT,
};
enum {
@@ -63,6 +64,8 @@ enum {
PCH_UART_HANDLED_RX_TRG_INT_SHIFT)<<1))
#define PCH_UART_HANDLED_MS_INT (1<<((PCH_UART_HANDLED_MS_INT_SHIFT)<<1))
+#define PCH_UART_HANDLED_LS_INT (1<<((PCH_UART_HANDLED_LS_INT_SHIFT)<<1))
+
#define PCH_UART_RBR 0x00
#define PCH_UART_THR 0x00
@@ -229,7 +232,6 @@ struct eg20t_port {
int start_tx;
int start_rx;
int tx_empty;
- int int_dis_flag;
int trigger;
int trigger_level;
struct pch_uart_buffer rxbuf;
@@ -237,7 +239,6 @@ struct eg20t_port {
unsigned int fcr;
unsigned int mcr;
unsigned int use_dma;
- unsigned int use_dma_flag;
struct dma_async_tx_descriptor *desc_tx;
struct dma_async_tx_descriptor *desc_rx;
struct pch_dma_slave param_tx;
@@ -560,14 +561,10 @@ static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf,
return i;
}
-static unsigned int pch_uart_hal_get_iid(struct eg20t_port *priv)
+static unsigned char pch_uart_hal_get_iid(struct eg20t_port *priv)
{
- unsigned int iir;
- int ret;
-
- iir = ioread8(priv->membase + UART_IIR);
- ret = (iir & (PCH_UART_IIR_IID | PCH_UART_IIR_TOI | PCH_UART_IIR_IP));
- return ret;
+ return ioread8(priv->membase + UART_IIR) &\
+ (PCH_UART_IIR_IID | PCH_UART_IIR_TOI | PCH_UART_IIR_IP);
}
static u8 pch_uart_hal_get_line_status(struct eg20t_port *priv)
@@ -666,10 +663,13 @@ static void pch_free_dma(struct uart_port *port)
dma_release_channel(priv->chan_rx);
priv->chan_rx = NULL;
}
- if (sg_dma_address(&priv->sg_rx))
- dma_free_coherent(port->dev, port->fifosize,
- sg_virt(&priv->sg_rx),
- sg_dma_address(&priv->sg_rx));
+
+ if (priv->rx_buf_dma) {
+ dma_free_coherent(port->dev, port->fifosize, priv->rx_buf_virt,
+ priv->rx_buf_dma);
+ priv->rx_buf_virt = NULL;
+ priv->rx_buf_dma = 0;
+ }
return;
}
@@ -1053,12 +1053,17 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
unsigned int handled;
u8 lsr;
int ret = 0;
- unsigned int iid;
+ unsigned char iid;
unsigned long flags;
+ int next = 1;
+ u8 msr;
spin_lock_irqsave(&priv->port.lock, flags);
handled = 0;
- while ((iid = pch_uart_hal_get_iid(priv)) > 1) {
+ while (next) {
+ iid = pch_uart_hal_get_iid(priv);
+ if (iid & PCH_UART_IIR_IP) /* No Interrupt */
+ break;
switch (iid) {
case PCH_UART_IID_RLS: /* Receiver Line Status */
lsr = pch_uart_hal_get_line_status(priv);
@@ -1066,6 +1071,8 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
UART_LSR_PE | UART_LSR_OE)) {
pch_uart_err_ir(priv, lsr);
ret = PCH_UART_HANDLED_RX_ERR_INT;
+ } else {
+ ret = PCH_UART_HANDLED_LS_INT;
}
break;
case PCH_UART_IID_RDR: /* Received Data Ready */
@@ -1092,20 +1099,22 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
ret = handle_tx(priv);
break;
case PCH_UART_IID_MS: /* Modem Status */
- ret = PCH_UART_HANDLED_MS_INT;
+ msr = pch_uart_hal_get_modem(priv);
+ next = 0; /* MS ir prioirty is the lowest. So, MS ir
+ means final interrupt */
+ if ((msr & UART_MSR_ANY_DELTA) == 0)
+ break;
+ ret |= PCH_UART_HANDLED_MS_INT;
break;
default: /* Never junp to this label */
- dev_err(priv->port.dev, "%s:iid=%d (%lu)\n", __func__,
+ dev_err(priv->port.dev, "%s:iid=%02x (%lu)\n", __func__,
iid, jiffies);
ret = -1;
+ next = 0;
break;
}
handled |= (unsigned int)ret;
}
- if (handled == 0 && iid <= 1) {
- if (priv->int_dis_flag)
- priv->int_dis_flag = 0;
- }
spin_unlock_irqrestore(&priv->port.lock, flags);
return IRQ_RETVAL(handled);
@@ -1200,7 +1209,6 @@ static void pch_uart_stop_rx(struct uart_port *port)
priv = container_of(port, struct eg20t_port, port);
priv->start_rx = 0;
pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT);
- priv->int_dis_flag = 1;
}
/* Enable the modem status interrupts. */
@@ -1447,7 +1455,6 @@ static int pch_uart_verify_port(struct uart_port *port,
__func__);
return -EOPNOTSUPP;
#endif
- priv->use_dma_flag = 1;
dev_info(priv->port.dev, "PCH UART : Use DMA Mode\n");
if (!priv->use_dma)
pch_request_dma(port);
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 9c4c05b2825b..246b823c1b27 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2282,6 +2282,7 @@ void uart_unregister_driver(struct uart_driver *drv)
tty_unregister_driver(p);
put_tty_driver(p);
kfree(drv->state);
+ drv->state = NULL;
drv->tty_driver = NULL;
}
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 3158e17b665c..4604153b7954 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1052,9 +1052,17 @@ static int sci_request_irq(struct sci_port *port)
if (SCIx_IRQ_IS_MUXED(port)) {
i = SCIx_MUX_IRQ;
irq = up->irq;
- } else
+ } else {
irq = port->cfg->irqs[i];
+ /*
+ * Certain port types won't support all of the
+ * available interrupt sources.
+ */
+ if (unlikely(!irq))
+ continue;
+ }
+
desc = sci_irq_desc + i;
port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
dev_name(up->dev), desc->desc);
@@ -1094,6 +1102,15 @@ static void sci_free_irq(struct sci_port *port)
* IRQ first.
*/
for (i = 0; i < SCIx_NR_IRQS; i++) {
+ unsigned int irq = port->cfg->irqs[i];
+
+ /*
+ * Certain port types won't support all of the available
+ * interrupt sources.
+ */
+ if (unlikely(!irq))
+ continue;
+
free_irq(port->cfg->irqs[i], port);
kfree(port->irqstr[i]);
@@ -1564,10 +1581,32 @@ static void sci_enable_ms(struct uart_port *port)
static void sci_break_ctl(struct uart_port *port, int break_state)
{
- /*
- * Not supported by hardware. Most parts couple break and rx
- * interrupts together, with break detection always enabled.
- */
+ struct sci_port *s = to_sci_port(port);
+ struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
+ unsigned short scscr, scsptr;
+
+ /* check wheter the port has SCSPTR */
+ if (!reg->size) {
+ /*
+ * Not supported by hardware. Most parts couple break and rx
+ * interrupts together, with break detection always enabled.
+ */
+ return;
+ }
+
+ scsptr = serial_port_in(port, SCSPTR);
+ scscr = serial_port_in(port, SCSCR);
+
+ if (break_state == -1) {
+ scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT;
+ scscr &= ~SCSCR_TE;
+ } else {
+ scsptr = (scsptr | SCSPTR_SPB2DT) & ~SCSPTR_SPB2IO;
+ scscr |= SCSCR_TE;
+ }
+
+ serial_port_out(port, SCSPTR, scsptr);
+ serial_port_out(port, SCSCR, scscr);
}
#ifdef CONFIG_SERIAL_SH_SCI_DMA
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index 593d40ad0a6b..5ed0daae6564 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -3338,9 +3338,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
printk("%s(%d):block_til_ready blocking on %s count=%d\n",
__FILE__,__LINE__, tty->driver->name, port->count );
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index aa1debf97cc7..45b43f11ca39 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -3336,9 +3336,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
}
DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
index a3dddc12d2fe..4a1e4f07765b 100644
--- a/drivers/tty/synclinkmp.c
+++ b/drivers/tty/synclinkmp.c
@@ -3357,9 +3357,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
printk("%s(%d):%s block_til_ready() count=%d\n",
__FILE__,__LINE__, tty->driver->name, port->count );
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 6c9b7cd6778a..91e326ffe7db 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -185,25 +185,19 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
/* Should possibly check if this fails for the largest buffer we
have queued and recycle that ? */
}
-
/**
- * tty_buffer_request_room - grow tty buffer if needed
+ * __tty_buffer_request_room - grow tty buffer if needed
* @tty: tty structure
* @size: size desired
*
* Make at least size bytes of linear space available for the tty
* buffer. If we fail return the size we managed to find.
- *
- * Locking: Takes tty->buf.lock
+ * Locking: Caller must hold tty->buf.lock
*/
-int tty_buffer_request_room(struct tty_struct *tty, size_t size)
+static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
{
struct tty_buffer *b, *n;
int left;
- unsigned long flags;
-
- spin_lock_irqsave(&tty->buf.lock, flags);
-
/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
remove this conditional if its worth it. This would be invisible
to the callers */
@@ -225,9 +219,30 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size)
size = left;
}
- spin_unlock_irqrestore(&tty->buf.lock, flags);
return size;
}
+
+
+/**
+ * tty_buffer_request_room - grow tty buffer if needed
+ * @tty: tty structure
+ * @size: size desired
+ *
+ * Make at least size bytes of linear space available for the tty
+ * buffer. If we fail return the size we managed to find.
+ *
+ * Locking: Takes tty->buf.lock
+ */
+int tty_buffer_request_room(struct tty_struct *tty, size_t size)
+{
+ unsigned long flags;
+ int length;
+
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ length = __tty_buffer_request_room(tty, size);
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+ return length;
+}
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
/**
@@ -249,14 +264,22 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
int copied = 0;
do {
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
- int space = tty_buffer_request_room(tty, goal);
- struct tty_buffer *tb = tty->buf.tail;
+ int space;
+ unsigned long flags;
+ struct tty_buffer *tb;
+
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ space = __tty_buffer_request_room(tty, goal);
+ tb = tty->buf.tail;
/* If there is no space then tb may be NULL */
- if (unlikely(space == 0))
+ if (unlikely(space == 0)) {
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
break;
+ }
memcpy(tb->char_buf_ptr + tb->used, chars, space);
memset(tb->flag_buf_ptr + tb->used, flag, space);
tb->used += space;
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
copied += space;
chars += space;
/* There is a small chance that we need to split the data over
@@ -286,14 +309,22 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
int copied = 0;
do {
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
- int space = tty_buffer_request_room(tty, goal);
- struct tty_buffer *tb = tty->buf.tail;
+ int space;
+ unsigned long __flags;
+ struct tty_buffer *tb;
+
+ spin_lock_irqsave(&tty->buf.lock, __flags);
+ space = __tty_buffer_request_room(tty, goal);
+ tb = tty->buf.tail;
/* If there is no space then tb may be NULL */
- if (unlikely(space == 0))
+ if (unlikely(space == 0)) {
+ spin_unlock_irqrestore(&tty->buf.lock, __flags);
break;
+ }
memcpy(tb->char_buf_ptr + tb->used, chars, space);
memcpy(tb->flag_buf_ptr + tb->used, flags, space);
tb->used += space;
+ spin_unlock_irqrestore(&tty->buf.lock, __flags);
copied += space;
chars += space;
flags += space;
@@ -344,13 +375,20 @@ EXPORT_SYMBOL(tty_schedule_flip);
int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
size_t size)
{
- int space = tty_buffer_request_room(tty, size);
+ int space;
+ unsigned long flags;
+ struct tty_buffer *tb;
+
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ space = __tty_buffer_request_room(tty, size);
+
+ tb = tty->buf.tail;
if (likely(space)) {
- struct tty_buffer *tb = tty->buf.tail;
*chars = tb->char_buf_ptr + tb->used;
memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
tb->used += space;
}
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
return space;
}
EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
@@ -374,13 +412,20 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
int tty_prepare_flip_string_flags(struct tty_struct *tty,
unsigned char **chars, char **flags, size_t size)
{
- int space = tty_buffer_request_room(tty, size);
+ int space;
+ unsigned long __flags;
+ struct tty_buffer *tb;
+
+ spin_lock_irqsave(&tty->buf.lock, __flags);
+ space = __tty_buffer_request_room(tty, size);
+
+ tb = tty->buf.tail;
if (likely(space)) {
- struct tty_buffer *tb = tty->buf.tail;
*chars = tb->char_buf_ptr + tb->used;
*flags = tb->flag_buf_ptr + tb->used;
tb->used += space;
}
+ spin_unlock_irqrestore(&tty->buf.lock, __flags);
return space;
}
EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index d939bd705c71..9e930c009bf2 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -185,6 +185,7 @@ void free_tty_struct(struct tty_struct *tty)
put_device(tty->dev);
kfree(tty->write_buf);
tty_buffer_free_all(tty);
+ tty->magic = 0xDEADDEAD;
kfree(tty);
}
@@ -573,7 +574,7 @@ void __tty_hangup(struct tty_struct *tty)
}
spin_unlock(&redirect_lock);
- tty_lock();
+ tty_lock(tty);
/* some functions below drop BTM, so we need this bit */
set_bit(TTY_HUPPING, &tty->flags);
@@ -666,7 +667,7 @@ void __tty_hangup(struct tty_struct *tty)
clear_bit(TTY_HUPPING, &tty->flags);
tty_ldisc_enable(tty);
- tty_unlock();
+ tty_unlock(tty);
if (f)
fput(f);
@@ -855,10 +856,11 @@ void disassociate_ctty(int on_exit)
*/
void no_tty(void)
{
+ /* FIXME: Review locking here. The tty_lock never covered any race
+ between a new association and proc_clear_tty but possible we need
+ to protect against this anyway */
struct task_struct *tsk = current;
- tty_lock();
disassociate_ctty(0);
- tty_unlock();
proc_clear_tty(tsk);
}
@@ -1102,12 +1104,12 @@ void tty_write_message(struct tty_struct *tty, char *msg)
{
if (tty) {
mutex_lock(&tty->atomic_write_lock);
- tty_lock();
+ tty_lock(tty);
if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
- tty_unlock();
+ tty_unlock(tty);
tty->ops->write(tty, msg, strlen(msg));
} else
- tty_unlock();
+ tty_unlock(tty);
tty_write_unlock(tty);
}
return;
@@ -1402,6 +1404,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
}
initialize_tty_struct(tty, driver, idx);
+ tty_lock(tty);
retval = tty_driver_install_tty(driver, tty);
if (retval < 0)
goto err_deinit_tty;
@@ -1414,9 +1417,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
retval = tty_ldisc_setup(tty, tty->link);
if (retval)
goto err_release_tty;
+ /* Return the tty locked so that it cannot vanish under the caller */
return tty;
err_deinit_tty:
+ tty_unlock(tty);
deinitialize_tty_struct(tty);
free_tty_struct(tty);
err_module_put:
@@ -1425,6 +1430,7 @@ err_module_put:
/* call the tty release_tty routine to clean out this slot */
err_release_tty:
+ tty_unlock(tty);
printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, "
"clearing slot %d\n", idx);
release_tty(tty, idx);
@@ -1627,7 +1633,7 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty_paranoia_check(tty, inode, __func__))
return 0;
- tty_lock();
+ tty_lock(tty);
check_tty_count(tty, __func__);
__tty_fasync(-1, filp, 0);
@@ -1636,10 +1642,11 @@ int tty_release(struct inode *inode, struct file *filp)
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER);
devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
+ /* Review: parallel close */
o_tty = tty->link;
if (tty_release_checks(tty, o_tty, idx)) {
- tty_unlock();
+ tty_unlock(tty);
return 0;
}
@@ -1651,7 +1658,7 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty->ops->close)
tty->ops->close(tty, filp);
- tty_unlock();
+ tty_unlock(tty);
/*
* Sanity check: if tty->count is going to zero, there shouldn't be
* any waiters on tty->read_wait or tty->write_wait. We test the
@@ -1674,7 +1681,7 @@ int tty_release(struct inode *inode, struct file *filp)
opens on /dev/tty */
mutex_lock(&tty_mutex);
- tty_lock();
+ tty_lock_pair(tty, o_tty);
tty_closing = tty->count <= 1;
o_tty_closing = o_tty &&
(o_tty->count <= (pty_master ? 1 : 0));
@@ -1705,7 +1712,7 @@ int tty_release(struct inode *inode, struct file *filp)
printk(KERN_WARNING "%s: %s: read/write wait queue active!\n",
__func__, tty_name(tty, buf));
- tty_unlock();
+ tty_unlock_pair(tty, o_tty);
mutex_unlock(&tty_mutex);
schedule();
}
@@ -1768,7 +1775,7 @@ int tty_release(struct inode *inode, struct file *filp)
/* check whether both sides are closing ... */
if (!tty_closing || (o_tty && !o_tty_closing)) {
- tty_unlock();
+ tty_unlock_pair(tty, o_tty);
return 0;
}
@@ -1781,14 +1788,16 @@ int tty_release(struct inode *inode, struct file *filp)
tty_ldisc_release(tty, o_tty);
/*
* The release_tty function takes care of the details of clearing
- * the slots and preserving the termios structure.
+ * the slots and preserving the termios structure. The tty_unlock_pair
+ * should be safe as we keep a kref while the tty is locked (so the
+ * unlock never unlocks a freed tty).
*/
release_tty(tty, idx);
+ tty_unlock_pair(tty, o_tty);
/* Make this pty number available for reallocation */
if (devpts)
devpts_kill_index(inode, idx);
- tty_unlock();
return 0;
}
@@ -1800,6 +1809,9 @@ int tty_release(struct inode *inode, struct file *filp)
*
* We cannot return driver and index like for the other nodes because
* devpts will not work then. It expects inodes to be from devpts FS.
+ *
+ * We need to move to returning a refcounted object from all the lookup
+ * paths including this one.
*/
static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp)
{
@@ -1816,6 +1828,7 @@ static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp)
/* noctty = 1; */
tty_kref_put(tty);
/* FIXME: we put a reference and return a TTY! */
+ /* This is only safe because the caller holds tty_mutex */
return tty;
}
@@ -1888,6 +1901,9 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,
* Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev.
* tty->count should protect the rest.
* ->siglock protects ->signal/->sighand
+ *
+ * Note: the tty_unlock/lock cases without a ref are only safe due to
+ * tty_mutex
*/
static int tty_open(struct inode *inode, struct file *filp)
@@ -1911,8 +1927,7 @@ retry_open:
retval = 0;
mutex_lock(&tty_mutex);
- tty_lock();
-
+ /* This is protected by the tty_mutex */
tty = tty_open_current_tty(device, filp);
if (IS_ERR(tty)) {
retval = PTR_ERR(tty);
@@ -1933,17 +1948,19 @@ retry_open:
}
if (tty) {
+ tty_lock(tty);
retval = tty_reopen(tty);
- if (retval)
+ if (retval < 0) {
+ tty_unlock(tty);
tty = ERR_PTR(retval);
- } else
+ }
+ } else /* Returns with the tty_lock held for now */
tty = tty_init_dev(driver, index);
mutex_unlock(&tty_mutex);
if (driver)
tty_driver_kref_put(driver);
if (IS_ERR(tty)) {
- tty_unlock();
retval = PTR_ERR(tty);
goto err_file;
}
@@ -1972,7 +1989,7 @@ retry_open:
printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__,
retval, tty->name);
#endif
- tty_unlock(); /* need to call tty_release without BTM */
+ tty_unlock(tty); /* need to call tty_release without BTM */
tty_release(inode, filp);
if (retval != -ERESTARTSYS)
return retval;
@@ -1984,17 +2001,15 @@ retry_open:
/*
* Need to reset f_op in case a hangup happened.
*/
- tty_lock();
if (filp->f_op == &hung_up_tty_fops)
filp->f_op = &tty_fops;
- tty_unlock();
goto retry_open;
}
- tty_unlock();
+ tty_unlock(tty);
mutex_lock(&tty_mutex);
- tty_lock();
+ tty_lock(tty);
spin_lock_irq(&current->sighand->siglock);
if (!noctty &&
current->signal->leader &&
@@ -2002,11 +2017,10 @@ retry_open:
tty->session == NULL)
__proc_set_tty(current, tty);
spin_unlock_irq(&current->sighand->siglock);
- tty_unlock();
+ tty_unlock(tty);
mutex_unlock(&tty_mutex);
return 0;
err_unlock:
- tty_unlock();
mutex_unlock(&tty_mutex);
/* after locks to avoid deadlock */
if (!IS_ERR_OR_NULL(driver))
@@ -2089,10 +2103,13 @@ out:
static int tty_fasync(int fd, struct file *filp, int on)
{
+ struct tty_struct *tty = file_tty(filp);
int retval;
- tty_lock();
+
+ tty_lock(tty);
retval = __tty_fasync(fd, filp, on);
- tty_unlock();
+ tty_unlock(tty);
+
return retval;
}
@@ -2929,6 +2946,7 @@ void initialize_tty_struct(struct tty_struct *tty,
tty->pgrp = NULL;
tty->overrun_time = jiffies;
tty_buffer_init(tty);
+ mutex_init(&tty->legacy_mutex);
mutex_init(&tty->termios_mutex);
mutex_init(&tty->ldisc_mutex);
init_waitqueue_head(&tty->write_wait);
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 24b95db75d84..173a9000a6cb 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -28,7 +28,6 @@
static DEFINE_SPINLOCK(tty_ldisc_lock);
static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
-static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_idle);
/* Line disc dispatch table */
static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
@@ -65,7 +64,7 @@ static void put_ldisc(struct tty_ldisc *ld)
return;
}
local_irq_restore(flags);
- wake_up(&tty_ldisc_idle);
+ wake_up(&ld->wq_idle);
}
/**
@@ -200,6 +199,8 @@ static struct tty_ldisc *tty_ldisc_get(int disc)
ld->ops = ldops;
atomic_set(&ld->users, 1);
+ init_waitqueue_head(&ld->wq_idle);
+
return ld;
}
@@ -538,7 +539,7 @@ static void tty_ldisc_flush_works(struct tty_struct *tty)
static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
{
long ret;
- ret = wait_event_timeout(tty_ldisc_idle,
+ ret = wait_event_timeout(tty->ldisc->wq_idle,
atomic_read(&tty->ldisc->users) == 1, timeout);
return ret > 0 ? 0 : -EBUSY;
}
@@ -567,7 +568,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
if (IS_ERR(new_ldisc))
return PTR_ERR(new_ldisc);
- tty_lock();
+ tty_lock(tty);
/*
* We need to look at the tty locking here for pty/tty pairs
* when both sides try to change in parallel.
@@ -581,12 +582,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
*/
if (tty->ldisc->ops->num == ldisc) {
- tty_unlock();
+ tty_unlock(tty);
tty_ldisc_put(new_ldisc);
return 0;
}
- tty_unlock();
+ tty_unlock(tty);
/*
* Problem: What do we do if this blocks ?
* We could deadlock here
@@ -594,7 +595,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
tty_wait_until_sent(tty, 0);
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/*
@@ -604,10 +605,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
mutex_unlock(&tty->ldisc_mutex);
- tty_unlock();
+ tty_unlock(tty);
wait_event(tty_ldisc_wait,
test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
}
@@ -622,7 +623,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
o_ldisc = tty->ldisc;
- tty_unlock();
+ tty_unlock(tty);
/*
* Make sure we don't change while someone holds a
* reference to the line discipline. The TTY_LDISC bit
@@ -649,7 +650,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
retval = tty_ldisc_wait_idle(tty, 5 * HZ);
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/* handle wait idle failure locked */
@@ -664,7 +665,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
clear_bit(TTY_LDISC_CHANGING, &tty->flags);
mutex_unlock(&tty->ldisc_mutex);
tty_ldisc_put(new_ldisc);
- tty_unlock();
+ tty_unlock(tty);
return -EIO;
}
@@ -707,7 +708,7 @@ enable:
if (o_work)
schedule_work(&o_tty->buf.work);
mutex_unlock(&tty->ldisc_mutex);
- tty_unlock();
+ tty_unlock(tty);
return retval;
}
@@ -815,11 +816,11 @@ void tty_ldisc_hangup(struct tty_struct *tty)
* need to wait for another function taking the BTM
*/
clear_bit(TTY_LDISC, &tty->flags);
- tty_unlock();
+ tty_unlock(tty);
cancel_work_sync(&tty->buf.work);
mutex_unlock(&tty->ldisc_mutex);
retry:
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/* At this point we have a closed ldisc and we want to
@@ -830,7 +831,7 @@ retry:
if (atomic_read(&tty->ldisc->users) != 1) {
char cur_n[TASK_COMM_LEN], tty_n[64];
long timeout = 3 * HZ;
- tty_unlock();
+ tty_unlock(tty);
while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
timeout = MAX_SCHEDULE_TIMEOUT;
@@ -911,10 +912,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
* race with the set_ldisc code path.
*/
- tty_unlock();
+ tty_unlock(tty);
tty_ldisc_halt(tty);
tty_ldisc_flush_works(tty);
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/*
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
index 9ff986c32a21..69adc80c98cd 100644
--- a/drivers/tty/tty_mutex.c
+++ b/drivers/tty/tty_mutex.c
@@ -4,29 +4,59 @@
#include <linux/semaphore.h>
#include <linux/sched.h>
-/*
- * The 'big tty mutex'
- *
- * This mutex is taken and released by tty_lock() and tty_unlock(),
- * replacing the older big kernel lock.
- * It can no longer be taken recursively, and does not get
- * released implicitly while sleeping.
- *
- * Don't use in new code.
- */
-static DEFINE_MUTEX(big_tty_mutex);
+/* Legacy tty mutex glue */
/*
* Getting the big tty mutex.
*/
-void __lockfunc tty_lock(void)
+
+void __lockfunc tty_lock(struct tty_struct *tty)
{
- mutex_lock(&big_tty_mutex);
+ if (tty->magic != TTY_MAGIC) {
+ printk(KERN_ERR "L Bad %p\n", tty);
+ WARN_ON(1);
+ return;
+ }
+ tty_kref_get(tty);
+ mutex_lock(&tty->legacy_mutex);
}
EXPORT_SYMBOL(tty_lock);
-void __lockfunc tty_unlock(void)
+void __lockfunc tty_unlock(struct tty_struct *tty)
{
- mutex_unlock(&big_tty_mutex);
+ if (tty->magic != TTY_MAGIC) {
+ printk(KERN_ERR "U Bad %p\n", tty);
+ WARN_ON(1);
+ return;
+ }
+ mutex_unlock(&tty->legacy_mutex);
+ tty_kref_put(tty);
}
EXPORT_SYMBOL(tty_unlock);
+
+/*
+ * Getting the big tty mutex for a pair of ttys with lock ordering
+ * On a non pty/tty pair tty2 can be NULL which is just fine.
+ */
+void __lockfunc tty_lock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2)
+{
+ if (tty < tty2) {
+ tty_lock(tty);
+ tty_lock(tty2);
+ } else {
+ if (tty2 && tty2 != tty)
+ tty_lock(tty2);
+ tty_lock(tty);
+ }
+}
+EXPORT_SYMBOL(tty_lock_pair);
+
+void __lockfunc tty_unlock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2)
+{
+ tty_unlock(tty);
+ if (tty2 && tty2 != tty)
+ tty_unlock(tty2);
+}
+EXPORT_SYMBOL(tty_unlock_pair);
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index bf6e238146ae..d9cca95a5452 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -230,7 +230,7 @@ int tty_port_block_til_ready(struct tty_port *port,
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
- wait_event_interruptible_tty(port->close_wait,
+ wait_event_interruptible_tty(tty, port->close_wait,
!(port->flags & ASYNC_CLOSING));
if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
@@ -296,9 +296,9 @@ int tty_port_block_til_ready(struct tty_port *port,
retval = -ERESTARTSYS;
break;
}
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
finish_wait(&port->open_wait, &wait);
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
index 8308fc7cdc26..2aaa0c228409 100644
--- a/drivers/tty/vt/consolemap.c
+++ b/drivers/tty/vt/consolemap.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/tty.h>
#include <asm/uaccess.h>
+#include <linux/console.h>
#include <linux/consolemap.h>
#include <linux/vt_kern.h>
@@ -312,6 +313,7 @@ int con_set_trans_old(unsigned char __user * arg)
if (!access_ok(VERIFY_READ, arg, E_TABSZ))
return -EFAULT;
+ console_lock();
for (i=0; i<E_TABSZ ; i++) {
unsigned char uc;
__get_user(uc, arg+i);
@@ -319,6 +321,7 @@ int con_set_trans_old(unsigned char __user * arg)
}
update_user_maps();
+ console_unlock();
return 0;
}
@@ -330,11 +333,13 @@ int con_get_trans_old(unsigned char __user * arg)
if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
return -EFAULT;
+ console_lock();
for (i=0; i<E_TABSZ ; i++)
- {
- ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
- __put_user((ch & ~0xff) ? 0 : ch, arg+i);
- }
+ {
+ ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
+ __put_user((ch & ~0xff) ? 0 : ch, arg+i);
+ }
+ console_unlock();
return 0;
}
@@ -346,6 +351,7 @@ int con_set_trans_new(ushort __user * arg)
if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
return -EFAULT;
+ console_lock();
for (i=0; i<E_TABSZ ; i++) {
unsigned short us;
__get_user(us, arg+i);
@@ -353,6 +359,7 @@ int con_set_trans_new(ushort __user * arg)
}
update_user_maps();
+ console_unlock();
return 0;
}
@@ -364,8 +371,10 @@ int con_get_trans_new(ushort __user * arg)
if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
return -EFAULT;
+ console_lock();
for (i=0; i<E_TABSZ ; i++)
__put_user(p[i], arg+i);
+ console_unlock();
return 0;
}
@@ -407,6 +416,7 @@ static void con_release_unimap(struct uni_pagedir *p)
}
}
+/* Caller must hold the console lock */
void con_free_unimap(struct vc_data *vc)
{
struct uni_pagedir *p;
@@ -487,17 +497,21 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
return 0;
}
-/* ui is a leftover from using a hashtable, but might be used again */
-int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
+/* ui is a leftover from using a hashtable, but might be used again
+ Caller must hold the lock */
+static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
{
struct uni_pagedir *p, *q;
-
+
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
- if (p && p->readonly) return -EIO;
+ if (p && p->readonly)
+ return -EIO;
+
if (!p || --p->refcount) {
q = kzalloc(sizeof(*p), GFP_KERNEL);
if (!q) {
- if (p) p->refcount++;
+ if (p)
+ p->refcount++;
return -ENOMEM;
}
q->refcount=1;
@@ -511,23 +525,43 @@ int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
return 0;
}
+int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
+{
+ int ret;
+ console_lock();
+ ret = con_do_clear_unimap(vc, ui);
+ console_unlock();
+ return ret;
+}
+
int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
{
int err = 0, err1, i;
struct uni_pagedir *p, *q;
+ console_lock();
+
/* Save original vc_unipagdir_loc in case we allocate a new one */
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
- if (p->readonly) return -EIO;
+ if (p->readonly) {
+ console_unlock();
+ return -EIO;
+ }
- if (!ct) return 0;
+ if (!ct) {
+ console_unlock();
+ return 0;
+ }
if (p->refcount > 1) {
int j, k;
u16 **p1, *p2, l;
- err1 = con_clear_unimap(vc, NULL);
- if (err1) return err1;
+ err1 = con_do_clear_unimap(vc, NULL);
+ if (err1) {
+ console_unlock();
+ return err1;
+ }
/*
* Since refcount was > 1, con_clear_unimap() allocated a
@@ -558,7 +592,8 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
*vc->vc_uni_pagedir_loc = (unsigned long)p;
con_release_unimap(q);
kfree(q);
- return err1;
+ console_unlock();
+ return err1;
}
}
} else {
@@ -592,21 +627,30 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
/*
* Merge with fontmaps of any other virtual consoles.
*/
- if (con_unify_unimap(vc, p))
+ if (con_unify_unimap(vc, p)) {
+ console_unlock();
return err;
+ }
for (i = 0; i <= 3; i++)
set_inverse_transl(vc, p, i); /* Update inverse translations */
set_inverse_trans_unicode(vc, p);
-
+
+ console_unlock();
return err;
}
-/* Loads the unimap for the hardware font, as defined in uni_hash.tbl.
- The representation used was the most compact I could come up
- with. This routine is executed at sys_setup time, and when the
- PIO_FONTRESET ioctl is called. */
-
+/**
+ * con_set_default_unimap - set default unicode map
+ * @vc: the console we are updating
+ *
+ * Loads the unimap for the hardware font, as defined in uni_hash.tbl.
+ * The representation used was the most compact I could come up
+ * with. This routine is executed at video setup, and when the
+ * PIO_FONTRESET ioctl is called.
+ *
+ * The caller must hold the console lock
+ */
int con_set_default_unimap(struct vc_data *vc)
{
int i, j, err = 0, err1;
@@ -617,6 +661,7 @@ int con_set_default_unimap(struct vc_data *vc)
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
if (p == dflt)
return 0;
+
dflt->refcount++;
*vc->vc_uni_pagedir_loc = (unsigned long)dflt;
if (p && !--p->refcount) {
@@ -628,8 +673,9 @@ int con_set_default_unimap(struct vc_data *vc)
/* The default font is always 256 characters */
- err = con_clear_unimap(vc, NULL);
- if (err) return err;
+ err = con_do_clear_unimap(vc, NULL);
+ if (err)
+ return err;
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
q = dfont_unitable;
@@ -654,6 +700,13 @@ int con_set_default_unimap(struct vc_data *vc)
}
EXPORT_SYMBOL(con_set_default_unimap);
+/**
+ * con_copy_unimap - copy unimap between two vts
+ * @dst_vc: target
+ * @src_vt: source
+ *
+ * The caller must hold the console lock when invoking this method
+ */
int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
{
struct uni_pagedir *q;
@@ -668,13 +721,23 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
*dst_vc->vc_uni_pagedir_loc = (long)q;
return 0;
}
+EXPORT_SYMBOL(con_copy_unimap);
+/**
+ * con_get_unimap - get the unicode map
+ * @vc: the console to read from
+ *
+ * Read the console unicode data for this console. Called from the ioctl
+ * handlers.
+ */
int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
{
int i, j, k, ect;
u16 **p1, *p2;
struct uni_pagedir *p;
+ console_lock();
+
ect = 0;
if (*vc->vc_uni_pagedir_loc) {
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
@@ -694,22 +757,19 @@ int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct uni
}
}
__put_user(ect, uct);
+ console_unlock();
return ((ect <= ct) ? 0 : -ENOMEM);
}
-void con_protect_unimap(struct vc_data *vc, int rdonly)
-{
- struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
-
- if (p)
- p->readonly = rdonly;
-}
-
/*
* Always use USER_MAP. These functions are used by the keyboard,
* which shouldn't be affected by G0/G1 switching, etc.
* If the user map still contains default values, i.e. the
* direct-to-font mapping, then assume user is using Latin1.
+ *
+ * FIXME: at some point we need to decide if we want to lock the table
+ * update element itself via the keyboard_event_lock for consistency with the
+ * keyboard driver as well as the consoles
*/
/* may be called during an interrupt */
u32 conv_8bit_to_uni(unsigned char c)
@@ -777,4 +837,3 @@ console_map_init(void)
con_set_default_unimap(vc_cons[i].d);
}
-EXPORT_SYMBOL(con_copy_unimap);
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 3b0c4e32ed7b..48cc6f25cfd3 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -53,17 +53,13 @@ extern void ctrl_alt_del(void);
#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
-/*
- * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
- * This seems a good reason to start with NumLock off. On HIL keyboards
- * of PARISC machines however there is no NumLock key and everyone expects the
- * keypad to be used for numbers.
- */
-
-#if defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD))
-#define KBD_DEFLEDS (1 << VC_NUMLOCK)
+#if defined(CONFIG_X86) || defined(CONFIG_PARISC)
+#include <asm/kbdleds.h>
#else
-#define KBD_DEFLEDS 0
+static inline int kbd_defleds(void)
+{
+ return 0;
+}
#endif
#define KBD_DEFLOCK 0
@@ -1524,8 +1520,8 @@ int __init kbd_init(void)
int error;
for (i = 0; i < MAX_NR_CONSOLES; i++) {
- kbd_table[i].ledflagstate = KBD_DEFLEDS;
- kbd_table[i].default_ledflagstate = KBD_DEFLEDS;
+ kbd_table[i].ledflagstate = kbd_defleds();
+ kbd_table[i].default_ledflagstate = kbd_defleds();
kbd_table[i].ledmode = LED_SHOW_FLAGS;
kbd_table[i].lockstate = KBD_DEFLOCK;
kbd_table[i].slockstate = 0;
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 2156188db4a6..84cbf298c094 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -3892,36 +3892,6 @@ static void set_palette(struct vc_data *vc)
vc->vc_sw->con_set_palette(vc, color_table);
}
-static int set_get_cmap(unsigned char __user *arg, int set)
-{
- int i, j, k;
-
- WARN_CONSOLE_UNLOCKED();
-
- for (i = 0; i < 16; i++)
- if (set) {
- get_user(default_red[i], arg++);
- get_user(default_grn[i], arg++);
- get_user(default_blu[i], arg++);
- } else {
- put_user(default_red[i], arg++);
- put_user(default_grn[i], arg++);
- put_user(default_blu[i], arg++);
- }
- if (set) {
- for (i = 0; i < MAX_NR_CONSOLES; i++)
- if (vc_cons_allocated(i)) {
- for (j = k = 0; j < 16; j++) {
- vc_cons[i].d->vc_palette[k++] = default_red[j];
- vc_cons[i].d->vc_palette[k++] = default_grn[j];
- vc_cons[i].d->vc_palette[k++] = default_blu[j];
- }
- set_palette(vc_cons[i].d);
- }
- }
- return 0;
-}
-
/*
* Load palette into the DAC registers. arg points to a colour
* map, 3 bytes per colour, 16 colours, range from 0 to 255.
@@ -3929,24 +3899,50 @@ static int set_get_cmap(unsigned char __user *arg, int set)
int con_set_cmap(unsigned char __user *arg)
{
- int rc;
+ int i, j, k;
+ unsigned char colormap[3*16];
+
+ if (copy_from_user(colormap, arg, sizeof(colormap)))
+ return -EFAULT;
console_lock();
- rc = set_get_cmap (arg,1);
+ for (i = k = 0; i < 16; i++) {
+ default_red[i] = colormap[k++];
+ default_grn[i] = colormap[k++];
+ default_blu[i] = colormap[k++];
+ }
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ if (!vc_cons_allocated(i))
+ continue;
+ for (j = k = 0; j < 16; j++) {
+ vc_cons[i].d->vc_palette[k++] = default_red[j];
+ vc_cons[i].d->vc_palette[k++] = default_grn[j];
+ vc_cons[i].d->vc_palette[k++] = default_blu[j];
+ }
+ set_palette(vc_cons[i].d);
+ }
console_unlock();
- return rc;
+ return 0;
}
int con_get_cmap(unsigned char __user *arg)
{
- int rc;
+ int i, k;
+ unsigned char colormap[3*16];
console_lock();
- rc = set_get_cmap (arg,0);
+ for (i = k = 0; i < 16; i++) {
+ colormap[k++] = default_red[i];
+ colormap[k++] = default_grn[i];
+ colormap[k++] = default_blu[i];
+ }
console_unlock();
- return rc;
+ if (copy_to_user(arg, colormap, sizeof(colormap)))
+ return -EFAULT;
+
+ return 0;
}
void reset_palette(struct vc_data *vc)
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index ede2ef18d2fb..64618547be11 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -910,7 +910,9 @@ int vt_ioctl(struct tty_struct *tty,
ret = con_font_op(vc_cons[fg_console].d, &op);
if (ret)
break;
+ console_lock();
con_set_default_unimap(vc_cons[fg_console].d);
+ console_unlock();
break;
}
#endif
@@ -934,33 +936,23 @@ int vt_ioctl(struct tty_struct *tty,
case PIO_SCRNMAP:
if (!perm)
ret = -EPERM;
- else {
- tty_lock();
+ else
ret = con_set_trans_old(up);
- tty_unlock();
- }
break;
case GIO_SCRNMAP:
- tty_lock();
ret = con_get_trans_old(up);
- tty_unlock();
break;
case PIO_UNISCRNMAP:
if (!perm)
ret = -EPERM;
- else {
- tty_lock();
+ else
ret = con_set_trans_new(up);
- tty_unlock();
- }
break;
case GIO_UNISCRNMAP:
- tty_lock();
ret = con_get_trans_new(up);
- tty_unlock();
break;
case PIO_UNIMAPCLR:
@@ -970,19 +962,14 @@ int vt_ioctl(struct tty_struct *tty,
ret = copy_from_user(&ui, up, sizeof(struct unimapinit));
if (ret)
ret = -EFAULT;
- else {
- tty_lock();
+ else
con_clear_unimap(vc, &ui);
- tty_unlock();
- }
break;
}
case PIO_UNIMAP:
case GIO_UNIMAP:
- tty_lock();
ret = do_unimap_ioctl(cmd, up, perm, vc);
- tty_unlock();
break;
case VT_LOCKSWITCH:
@@ -1196,9 +1183,7 @@ long vt_compat_ioctl(struct tty_struct *tty,
case PIO_UNIMAP:
case GIO_UNIMAP:
- tty_lock();
ret = compat_unimap_ioctl(cmd, up, perm, vc);
- tty_unlock();
break;
/*
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
index b98371d93a92..42202cd83158 100644
--- a/drivers/uio/uio_pdrv_genirq.c
+++ b/drivers/uio/uio_pdrv_genirq.c
@@ -146,6 +146,14 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
priv->flags = 0; /* interrupt is enabled to begin with */
priv->pdev = pdev;
+ if (!uioinfo->irq) {
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to get IRQ\n");
+ goto bad0;
+ }
+ uioinfo->irq = ret;
+ }
uiomem = &uioinfo->mem[0];
for (i = 0; i < pdev->num_resources; ++i) {
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 76316a33061b..a7773a3e02b1 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -133,6 +133,8 @@ source "drivers/usb/host/Kconfig"
source "drivers/usb/musb/Kconfig"
+source "drivers/usb/chipidea/Kconfig"
+
source "drivers/usb/renesas_usbhs/Kconfig"
source "drivers/usb/class/Kconfig"
@@ -177,6 +179,8 @@ source "drivers/usb/serial/Kconfig"
source "drivers/usb/misc/Kconfig"
+source "drivers/usb/phy/Kconfig"
+
source "drivers/usb/atm/Kconfig"
source "drivers/usb/gadget/Kconfig"
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 53a7bc07dd8d..c691eea51537 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -46,12 +46,14 @@ obj-$(CONFIG_USB_MICROTEK) += image/
obj-$(CONFIG_USB_SERIAL) += serial/
obj-$(CONFIG_USB) += misc/
+obj-$(CONFIG_USB) += phy/
obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/
obj-$(CONFIG_USB_ATM) += atm/
obj-$(CONFIG_USB_SPEEDTOUCH) += atm/
obj-$(CONFIG_USB_MUSB_HDRC) += musb/
+obj-$(CONFIG_USB_CHIPIDEA) += chipidea/
obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs/
obj-$(CONFIG_USB_GADGET) += gadget/
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 98b89fe19867..b7eb86ad6bf2 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -674,7 +674,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,
}
ret = offd;
- dbg("cm %#x", cm);
+ usb_dbg(instance->usbatm, "cm %#x\n", cm);
fail:
mutex_unlock(&instance->cm_serialize);
err:
@@ -733,7 +733,7 @@ static int cxacru_card_status(struct cxacru_data *instance)
{
int ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
if (ret < 0) { /* firmware not loaded */
- dbg("cxacru_adsl_start: CARD_GET_STATUS returned %d", ret);
+ usb_dbg(instance->usbatm, "cxacru_adsl_start: CARD_GET_STATUS returned %d\n", ret);
return ret;
}
return 0;
@@ -758,7 +758,7 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
int ret;
int start_polling = 1;
- dbg("cxacru_atm_start");
+ dev_dbg(&intf->dev, "%s\n", __func__);
/* Read MAC address */
ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_MAC_ADDRESS, NULL, 0,
@@ -962,13 +962,13 @@ static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw,
ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD),
buf, offb, NULL, CMD_TIMEOUT);
if (ret < 0) {
- dbg("sending fw %#x failed", fw);
+ dev_dbg(&usb_dev->dev, "sending fw %#x failed\n", fw);
goto cleanup;
}
offb = 0;
}
} while (offd < size);
- dbg("sent fw %#x", fw);
+ dev_dbg(&usb_dev->dev, "sent fw %#x\n", fw);
ret = 0;
@@ -988,7 +988,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
usb_dev->descriptor.idProduct };
__le32 val;
- dbg("cxacru_upload_firmware");
+ usb_dbg(usbatm, "%s\n", __func__);
/* FirmwarePllFClkValue */
val = cpu_to_le32(instance->modem_type->pll_f_clk);
@@ -1074,7 +1074,7 @@ static int cxacru_find_firmware(struct cxacru_data *instance,
char buf[16];
sprintf(buf, "cxacru-%s.bin", phase);
- dbg("cxacru_find_firmware: looking for %s", buf);
+ usb_dbg(usbatm, "cxacru_find_firmware: looking for %s\n", buf);
if (request_firmware(fw_p, buf, dev)) {
usb_dbg(usbatm, "no stage %s firmware found\n", phase);
@@ -1115,9 +1115,9 @@ static int cxacru_heavy_init(struct usbatm_data *usbatm_instance,
ret = cxacru_card_status(instance);
if (ret)
- dbg("modem initialisation failed");
+ usb_dbg(usbatm_instance, "modem initialisation failed\n");
else
- dbg("done setting up the modem");
+ usb_dbg(usbatm_instance, "done setting up the modem\n");
return ret;
}
@@ -1133,7 +1133,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
/* instance init */
instance = kzalloc(sizeof(*instance), GFP_KERNEL);
if (!instance) {
- dbg("cxacru_bind: no memory for instance data");
+ usb_dbg(usbatm_instance, "cxacru_bind: no memory for instance data\n");
return -ENOMEM;
}
@@ -1149,31 +1149,31 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
instance->rcv_buf = (u8 *) __get_free_page(GFP_KERNEL);
if (!instance->rcv_buf) {
- dbg("cxacru_bind: no memory for rcv_buf");
+ usb_dbg(usbatm_instance, "cxacru_bind: no memory for rcv_buf\n");
ret = -ENOMEM;
goto fail;
}
instance->snd_buf = (u8 *) __get_free_page(GFP_KERNEL);
if (!instance->snd_buf) {
- dbg("cxacru_bind: no memory for snd_buf");
+ usb_dbg(usbatm_instance, "cxacru_bind: no memory for snd_buf\n");
ret = -ENOMEM;
goto fail;
}
instance->rcv_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!instance->rcv_urb) {
- dbg("cxacru_bind: no memory for rcv_urb");
+ usb_dbg(usbatm_instance, "cxacru_bind: no memory for rcv_urb\n");
ret = -ENOMEM;
goto fail;
}
instance->snd_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!instance->snd_urb) {
- dbg("cxacru_bind: no memory for snd_urb");
+ usb_dbg(usbatm_instance, "cxacru_bind: no memory for snd_urb\n");
ret = -ENOMEM;
goto fail;
}
if (!cmd_ep) {
- dbg("cxacru_bind: no command endpoint");
+ usb_dbg(usbatm_instance, "cxacru_bind: no command endpoint\n");
ret = -ENODEV;
goto fail;
}
@@ -1227,10 +1227,10 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance,
struct cxacru_data *instance = usbatm_instance->driver_data;
int is_polling = 1;
- dbg("cxacru_unbind entered");
+ usb_dbg(usbatm_instance, "cxacru_unbind entered\n");
if (!instance) {
- dbg("cxacru_unbind: NULL instance!");
+ usb_dbg(usbatm_instance, "cxacru_unbind: NULL instance!\n");
return;
}
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 98dd9e49b684..975e9c6691d6 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -170,7 +170,7 @@ static void speedtch_set_swbuff(struct speedtch_instance_data *instance, int sta
"%sabling SW buffering: usb_control_msg returned %d\n",
state ? "En" : "Dis", ret);
else
- dbg("speedtch_set_swbuff: %sbled SW buffering", state ? "En" : "Dis");
+ usb_dbg(usbatm, "speedtch_set_swbuff: %sbled SW buffering\n", state ? "En" : "Dis");
}
static void speedtch_test_sequence(struct speedtch_instance_data *instance)
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 01ea5d7421d4..d7e422dc0ef7 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -1357,10 +1357,8 @@ static int uea_stat_e1(struct uea_softc *sc)
/* release the dsp firmware as it is not needed until
* the next failure
*/
- if (sc->dsp_firm) {
- release_firmware(sc->dsp_firm);
- sc->dsp_firm = NULL;
- }
+ release_firmware(sc->dsp_firm);
+ sc->dsp_firm = NULL;
}
/* always update it as atm layer could not be init when we switch to
@@ -1496,10 +1494,8 @@ static int uea_stat_e4(struct uea_softc *sc)
/* release the dsp firmware as it is not needed until
* the next failure
*/
- if (sc->dsp_firm) {
- release_firmware(sc->dsp_firm);
- sc->dsp_firm = NULL;
- }
+ release_firmware(sc->dsp_firm);
+ sc->dsp_firm = NULL;
}
/* always update it as atm layer could not be init when we switch to
@@ -2240,8 +2236,7 @@ static void uea_stop(struct uea_softc *sc)
/* flush the work item, when no one can schedule it */
flush_work_sync(&sc->task);
- if (sc->dsp_firm)
- release_firmware(sc->dsp_firm);
+ release_firmware(sc->dsp_firm);
uea_leaves(INS_TO_USBDEV(sc));
}
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index d3448ca110ce..ee62b3576f94 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -86,7 +86,7 @@
#ifdef VERBOSE_DEBUG
static int usbatm_print_packet(const unsigned char *data, int len);
#define PACKETDEBUG(arg...) usbatm_print_packet(arg)
-#define vdbg(arg...) dbg(arg)
+#define vdbg(arg...) dev_dbg(arg)
#else
#define PACKETDEBUG(arg...)
#define vdbg(arg...)
@@ -714,7 +714,7 @@ static void usbatm_destroy_instance(struct kref *kref)
{
struct usbatm_data *instance = container_of(kref, struct usbatm_data, refcount);
- dbg("%s", __func__);
+ usb_dbg(instance, "%s\n", __func__);
tasklet_kill(&instance->rx_channel.tasklet);
tasklet_kill(&instance->tx_channel.tasklet);
@@ -724,14 +724,14 @@ static void usbatm_destroy_instance(struct kref *kref)
static void usbatm_get_instance(struct usbatm_data *instance)
{
- dbg("%s", __func__);
+ usb_dbg(instance, "%s\n", __func__);
kref_get(&instance->refcount);
}
static void usbatm_put_instance(struct usbatm_data *instance)
{
- dbg("%s", __func__);
+ usb_dbg(instance, "%s\n", __func__);
kref_put(&instance->refcount, usbatm_destroy_instance);
}
@@ -745,11 +745,10 @@ static void usbatm_atm_dev_close(struct atm_dev *atm_dev)
{
struct usbatm_data *instance = atm_dev->dev_data;
- dbg("%s", __func__);
-
if (!instance)
return;
+ usb_dbg(instance, "%s\n", __func__);
atm_dev->dev_data = NULL; /* catch bugs */
usbatm_put_instance(instance); /* taken in usbatm_atm_init */
}
@@ -759,10 +758,8 @@ static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *pag
struct usbatm_data *instance = atm_dev->dev_data;
int left = *pos;
- if (!instance) {
- dbg("%s: NULL instance!", __func__);
+ if (!instance)
return -ENODEV;
- }
if (!left--)
return sprintf(page, "%s\n", instance->description);
@@ -804,10 +801,8 @@ static int usbatm_atm_open(struct atm_vcc *vcc)
int vci = vcc->vci;
short vpi = vcc->vpi;
- if (!instance) {
- dbg("%s: NULL data!", __func__);
+ if (!instance)
return -ENODEV;
- }
atm_dbg(instance, "%s: vpi %hd, vci %d\n", __func__, vpi, vci);
@@ -884,10 +879,8 @@ static void usbatm_atm_close(struct atm_vcc *vcc)
struct usbatm_data *instance = vcc->dev->dev_data;
struct usbatm_vcc_data *vcc_data = vcc->dev_data;
- if (!instance || !vcc_data) {
- dbg("%s: NULL data!", __func__);
+ if (!instance || !vcc_data)
return;
- }
atm_dbg(instance, "%s entered\n", __func__);
@@ -929,10 +922,8 @@ static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd,
{
struct usbatm_data *instance = atm_dev->dev_data;
- if (!instance || instance->disconnected) {
- dbg("%s: %s!", __func__, instance ? "disconnected" : "NULL instance");
+ if (!instance || instance->disconnected)
return -ENODEV;
- }
switch (cmd) {
case ATM_QUERYLOOP:
@@ -1336,8 +1327,6 @@ EXPORT_SYMBOL_GPL(usbatm_usb_disconnect);
static int __init usbatm_usb_init(void)
{
- dbg("%s: driver version %s", __func__, DRIVER_VERSION);
-
if (sizeof(struct usbatm_control) > FIELD_SIZEOF(struct sk_buff, cb)) {
printk(KERN_ERR "%s unusable with this kernel!\n", usbatm_driver_name);
return -EIO;
@@ -1357,7 +1346,6 @@ module_init(usbatm_usb_init);
static void __exit usbatm_usb_exit(void)
{
- dbg("%s", __func__);
}
module_exit(usbatm_usb_exit);
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c
index 48ee0c5ff282..14ec9f0c5924 100644
--- a/drivers/usb/atm/xusbatm.c
+++ b/drivers/usb/atm/xusbatm.c
@@ -187,8 +187,6 @@ static int __init xusbatm_init(void)
{
int i;
- dbg("xusbatm_init");
-
if (!num_vendor ||
num_vendor != num_product ||
num_vendor != num_rx_endpoint ||
@@ -221,8 +219,6 @@ module_init(xusbatm_init);
static void __exit xusbatm_exit(void)
{
- dbg("xusbatm_exit entered");
-
usb_deregister(&xusbatm_usb_driver);
}
module_exit(xusbatm_exit);
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
new file mode 100644
index 000000000000..fd36dc8b889b
--- /dev/null
+++ b/drivers/usb/chipidea/Kconfig
@@ -0,0 +1,32 @@
+config USB_CHIPIDEA
+ tristate "ChipIdea Highspeed Dual Role Controller"
+ depends on USB
+ help
+ Say Y here if your system has a dual role high speed USB
+ controller based on ChipIdea silicon IP. Currently, only the
+ peripheral mode is supported.
+
+ When compiled dynamically, the module will be called ci-hdrc.ko.
+
+if USB_CHIPIDEA
+
+config USB_CHIPIDEA_UDC
+ bool "ChipIdea device controller"
+ depends on USB_GADGET
+ select USB_GADGET_DUALSPEED
+ help
+ Say Y here to enable device controller functionality of the
+ ChipIdea driver.
+
+config USB_CHIPIDEA_HOST
+ bool "ChipIdea host controller"
+ help
+ Say Y here to enable host controller functionality of the
+ ChipIdea driver.
+
+config USB_CHIPIDEA_DEBUG
+ bool "ChipIdea driver debug"
+ help
+ Say Y here to enable debugging output of the ChipIdea driver.
+
+endif
diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile
new file mode 100644
index 000000000000..cc3493769724
--- /dev/null
+++ b/drivers/usb/chipidea/Makefile
@@ -0,0 +1,14 @@
+obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc.o
+
+ci_hdrc-y := core.o
+ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o
+ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o
+ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o
+
+ifneq ($(CONFIG_PCI),)
+ obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_pci.o
+endif
+
+ifneq ($(CONFIG_ARCH_MSM),)
+ obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o
+endif
diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
new file mode 100644
index 000000000000..050de8562a04
--- /dev/null
+++ b/drivers/usb/chipidea/bits.h
@@ -0,0 +1,90 @@
+/*
+ * bits.h - register bits of the ChipIdea USB IP core
+ *
+ * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
+ *
+ * Author: David Lopo
+ *
+ * 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 __DRIVERS_USB_CHIPIDEA_BITS_H
+#define __DRIVERS_USB_CHIPIDEA_BITS_H
+
+#include <linux/usb/ehci_def.h>
+
+/* HCCPARAMS */
+#define HCCPARAMS_LEN BIT(17)
+
+/* DCCPARAMS */
+#define DCCPARAMS_DEN (0x1F << 0)
+#define DCCPARAMS_DC BIT(7)
+#define DCCPARAMS_HC BIT(8)
+
+/* TESTMODE */
+#define TESTMODE_FORCE BIT(0)
+
+/* USBCMD */
+#define USBCMD_RS BIT(0)
+#define USBCMD_RST BIT(1)
+#define USBCMD_SUTW BIT(13)
+#define USBCMD_ATDTW BIT(14)
+
+/* USBSTS & USBINTR */
+#define USBi_UI BIT(0)
+#define USBi_UEI BIT(1)
+#define USBi_PCI BIT(2)
+#define USBi_URI BIT(6)
+#define USBi_SLI BIT(8)
+
+/* DEVICEADDR */
+#define DEVICEADDR_USBADRA BIT(24)
+#define DEVICEADDR_USBADR (0x7FUL << 25)
+
+/* PORTSC */
+#define PORTSC_FPR BIT(6)
+#define PORTSC_SUSP BIT(7)
+#define PORTSC_HSP BIT(9)
+#define PORTSC_PTC (0x0FUL << 16)
+
+/* DEVLC */
+#define DEVLC_PSPD (0x03UL << 25)
+#define DEVLC_PSPD_HS (0x02UL << 25)
+
+/* OTGSC */
+#define OTGSC_IDPU BIT(5)
+#define OTGSC_ID BIT(8)
+#define OTGSC_AVV BIT(9)
+#define OTGSC_ASV BIT(10)
+#define OTGSC_BSV BIT(11)
+#define OTGSC_BSE BIT(12)
+#define OTGSC_IDIS BIT(16)
+#define OTGSC_AVVIS BIT(17)
+#define OTGSC_ASVIS BIT(18)
+#define OTGSC_BSVIS BIT(19)
+#define OTGSC_BSEIS BIT(20)
+#define OTGSC_IDIE BIT(24)
+#define OTGSC_AVVIE BIT(25)
+#define OTGSC_ASVIE BIT(26)
+#define OTGSC_BSVIE BIT(27)
+#define OTGSC_BSEIE BIT(28)
+
+/* USBMODE */
+#define USBMODE_CM (0x03UL << 0)
+#define USBMODE_CM_DC (0x02UL << 0)
+#define USBMODE_SLOM BIT(3)
+#define USBMODE_CI_SDIS BIT(4)
+
+/* ENDPTCTRL */
+#define ENDPTCTRL_RXS BIT(0)
+#define ENDPTCTRL_RXT (0x03UL << 2)
+#define ENDPTCTRL_RXR BIT(6) /* reserved for port 0 */
+#define ENDPTCTRL_RXE BIT(7)
+#define ENDPTCTRL_TXS BIT(16)
+#define ENDPTCTRL_TXT (0x03UL << 18)
+#define ENDPTCTRL_TXR BIT(22) /* reserved for port 0 */
+#define ENDPTCTRL_TXE BIT(23)
+
+#endif /* __DRIVERS_USB_CHIPIDEA_BITS_H */
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
new file mode 100644
index 000000000000..50911f8490d4
--- /dev/null
+++ b/drivers/usb/chipidea/ci.h
@@ -0,0 +1,313 @@
+/*
+ * ci.h - common structures, functions, and macros of the ChipIdea driver
+ *
+ * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
+ *
+ * Author: David Lopo
+ *
+ * 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 __DRIVERS_USB_CHIPIDEA_CI_H
+#define __DRIVERS_USB_CHIPIDEA_CI_H
+
+#include <linux/list.h>
+#include <linux/irqreturn.h>
+#include <linux/usb.h>
+#include <linux/usb/gadget.h>
+
+/******************************************************************************
+ * DEFINE
+ *****************************************************************************/
+#define CI13XXX_PAGE_SIZE 4096ul /* page size for TD's */
+#define ENDPT_MAX 32
+
+/******************************************************************************
+ * STRUCTURES
+ *****************************************************************************/
+/**
+ * struct ci13xxx_ep - endpoint representation
+ * @ep: endpoint structure for gadget drivers
+ * @dir: endpoint direction (TX/RX)
+ * @num: endpoint number
+ * @type: endpoint type
+ * @name: string description of the endpoint
+ * @qh: queue head for this endpoint
+ * @wedge: is the endpoint wedged
+ * @udc: pointer to the controller
+ * @lock: pointer to controller's spinlock
+ * @td_pool: pointer to controller's TD pool
+ */
+struct ci13xxx_ep {
+ struct usb_ep ep;
+ u8 dir;
+ u8 num;
+ u8 type;
+ char name[16];
+ struct {
+ struct list_head queue;
+ struct ci13xxx_qh *ptr;
+ dma_addr_t dma;
+ } qh;
+ int wedge;
+
+ /* global resources */
+ struct ci13xxx *udc;
+ spinlock_t *lock;
+ struct dma_pool *td_pool;
+};
+
+enum ci_role {
+ CI_ROLE_HOST = 0,
+ CI_ROLE_GADGET,
+ CI_ROLE_END,
+};
+
+/**
+ * struct ci_role_driver - host/gadget role driver
+ * start: start this role
+ * stop: stop this role
+ * irq: irq handler for this role
+ * name: role name string (host/gadget)
+ */
+struct ci_role_driver {
+ int (*start)(struct ci13xxx *);
+ void (*stop)(struct ci13xxx *);
+ irqreturn_t (*irq)(struct ci13xxx *);
+ const char *name;
+};
+
+/**
+ * struct hw_bank - hardware register mapping representation
+ * @lpm: set if the device is LPM capable
+ * @phys: physical address of the controller's registers
+ * @abs: absolute address of the beginning of register window
+ * @cap: capability registers
+ * @op: operational registers
+ * @size: size of the register window
+ * @regmap: register lookup table
+ */
+struct hw_bank {
+ unsigned lpm;
+ resource_size_t phys;
+ void __iomem *abs;
+ void __iomem *cap;
+ void __iomem *op;
+ size_t size;
+ void __iomem **regmap;
+};
+
+/**
+ * struct ci13xxx - chipidea device representation
+ * @dev: pointer to parent device
+ * @lock: access synchronization
+ * @hw_bank: hardware register mapping
+ * @irq: IRQ number
+ * @roles: array of supported roles for this controller
+ * @role: current role
+ * @is_otg: if the device is otg-capable
+ * @work: work for role changing
+ * @wq: workqueue thread
+ * @qh_pool: allocation pool for queue heads
+ * @td_pool: allocation pool for transfer descriptors
+ * @gadget: device side representation for peripheral controller
+ * @driver: gadget driver
+ * @hw_ep_max: total number of endpoints supported by hardware
+ * @ci13xxx_ep: array of endpoints
+ * @ep0_dir: ep0 direction
+ * @ep0out: pointer to ep0 OUT endpoint
+ * @ep0in: pointer to ep0 IN endpoint
+ * @status: ep0 status request
+ * @setaddr: if we should set the address on status completion
+ * @address: usb address received from the host
+ * @remote_wakeup: host-enabled remote wakeup
+ * @suspended: suspended by host
+ * @test_mode: the selected test mode
+ * @udc_driver: platform specific information supplied by parent device
+ * @vbus_active: is VBUS active
+ * @transceiver: pointer to USB PHY, if any
+ * @hcd: pointer to usb_hcd for ehci host driver
+ */
+struct ci13xxx {
+ struct device *dev;
+ spinlock_t lock;
+ struct hw_bank hw_bank;
+ int irq;
+ struct ci_role_driver *roles[CI_ROLE_END];
+ enum ci_role role;
+ bool is_otg;
+ struct work_struct work;
+ struct workqueue_struct *wq;
+
+ struct dma_pool *qh_pool;
+ struct dma_pool *td_pool;
+
+ struct usb_gadget gadget;
+ struct usb_gadget_driver *driver;
+ unsigned hw_ep_max;
+ struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX];
+ u32 ep0_dir;
+ struct ci13xxx_ep *ep0out, *ep0in;
+
+ struct usb_request *status;
+ bool setaddr;
+ u8 address;
+ u8 remote_wakeup;
+ u8 suspended;
+ u8 test_mode;
+
+ struct ci13xxx_udc_driver *udc_driver;
+ int vbus_active;
+ struct usb_phy *transceiver;
+ struct usb_hcd *hcd;
+};
+
+static inline struct ci_role_driver *ci_role(struct ci13xxx *ci)
+{
+ BUG_ON(ci->role >= CI_ROLE_END || !ci->roles[ci->role]);
+ return ci->roles[ci->role];
+}
+
+static inline int ci_role_start(struct ci13xxx *ci, enum ci_role role)
+{
+ int ret;
+
+ if (role >= CI_ROLE_END)
+ return -EINVAL;
+
+ if (!ci->roles[role])
+ return -ENXIO;
+
+ ret = ci->roles[role]->start(ci);
+ if (!ret)
+ ci->role = role;
+ return ret;
+}
+
+static inline void ci_role_stop(struct ci13xxx *ci)
+{
+ enum ci_role role = ci->role;
+
+ if (role == CI_ROLE_END)
+ return;
+
+ ci->role = CI_ROLE_END;
+
+ ci->roles[role]->stop(ci);
+}
+
+/******************************************************************************
+ * REGISTERS
+ *****************************************************************************/
+/* register size */
+#define REG_BITS (32)
+
+/* register indices */
+enum ci13xxx_regs {
+ CAP_CAPLENGTH,
+ CAP_HCCPARAMS,
+ CAP_DCCPARAMS,
+ CAP_TESTMODE,
+ CAP_LAST = CAP_TESTMODE,
+ OP_USBCMD,
+ OP_USBSTS,
+ OP_USBINTR,
+ OP_DEVICEADDR,
+ OP_ENDPTLISTADDR,
+ OP_PORTSC,
+ OP_DEVLC,
+ OP_OTGSC,
+ OP_USBMODE,
+ OP_ENDPTSETUPSTAT,
+ OP_ENDPTPRIME,
+ OP_ENDPTFLUSH,
+ OP_ENDPTSTAT,
+ OP_ENDPTCOMPLETE,
+ OP_ENDPTCTRL,
+ /* endptctrl1..15 follow */
+ OP_LAST = OP_ENDPTCTRL + ENDPT_MAX / 2,
+};
+
+/**
+ * ffs_nr: find first (least significant) bit set
+ * @x: the word to search
+ *
+ * This function returns bit number (instead of position)
+ */
+static inline int ffs_nr(u32 x)
+{
+ int n = ffs(x);
+
+ return n ? n-1 : 32;
+}
+
+/**
+ * hw_read: reads from a hw register
+ * @reg: register index
+ * @mask: bitfield mask
+ *
+ * This function returns register contents
+ */
+static inline u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask)
+{
+ return ioread32(udc->hw_bank.regmap[reg]) & mask;
+}
+
+/**
+ * hw_write: writes to a hw register
+ * @reg: register index
+ * @mask: bitfield mask
+ * @data: new value
+ */
+static inline void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
+ u32 mask, u32 data)
+{
+ if (~mask)
+ data = (ioread32(udc->hw_bank.regmap[reg]) & ~mask)
+ | (data & mask);
+
+ iowrite32(data, udc->hw_bank.regmap[reg]);
+}
+
+/**
+ * hw_test_and_clear: tests & clears a hw register
+ * @reg: register index
+ * @mask: bitfield mask
+ *
+ * This function returns register contents
+ */
+static inline u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg,
+ u32 mask)
+{
+ u32 val = ioread32(udc->hw_bank.regmap[reg]) & mask;
+
+ iowrite32(val, udc->hw_bank.regmap[reg]);
+ return val;
+}
+
+/**
+ * hw_test_and_write: tests & writes a hw register
+ * @reg: register index
+ * @mask: bitfield mask
+ * @data: new value
+ *
+ * This function returns register contents
+ */
+static inline u32 hw_test_and_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
+ u32 mask, u32 data)
+{
+ u32 val = hw_read(udc, reg, ~0);
+
+ hw_write(udc, reg, mask, data);
+ return (val & mask) >> ffs_nr(mask);
+}
+
+int hw_device_reset(struct ci13xxx *ci, u32 mode);
+
+int hw_port_test_set(struct ci13xxx *ci, u8 mode);
+
+u8 hw_port_test_get(struct ci13xxx *ci);
+
+#endif /* __DRIVERS_USB_CHIPIDEA_CI_H */
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/chipidea/ci13xxx_msm.c
index d07e44c05e9b..958069ef95e3 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/chipidea/ci13xxx_msm.c
@@ -10,15 +10,12 @@
#include <linux/pm_runtime.h>
#include <linux/usb/msm_hsusb_hw.h>
#include <linux/usb/ulpi.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/chipidea.h>
-#include "ci13xxx_udc.c"
+#include "ci.h"
-#define MSM_USB_BASE (udc->regs)
-
-static irqreturn_t msm_udc_irq(int irq, void *data)
-{
- return udc_irq();
-}
+#define MSM_USB_BASE (udc->hw_bank.abs)
static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
{
@@ -60,53 +57,40 @@ static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
static int ci13xxx_msm_probe(struct platform_device *pdev)
{
- struct resource *res;
- void __iomem *regs;
- int irq;
+ struct platform_device *plat_ci;
int ret;
dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "failed to get platform resource mem\n");
- return -ENXIO;
- }
-
- regs = ioremap(res->start, resource_size(res));
- if (!regs) {
- dev_err(&pdev->dev, "ioremap failed\n");
+ plat_ci = platform_device_alloc("ci_hdrc", -1);
+ if (!plat_ci) {
+ dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n");
return -ENOMEM;
}
- ret = udc_probe(&ci13xxx_msm_udc_driver, &pdev->dev, regs);
- if (ret < 0) {
- dev_err(&pdev->dev, "udc_probe failed\n");
- goto iounmap;
+ ret = platform_device_add_resources(plat_ci, pdev->resource,
+ pdev->num_resources);
+ if (ret) {
+ dev_err(&pdev->dev, "can't add resources to platform device\n");
+ goto put_platform;
}
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "IRQ not found\n");
- ret = -ENXIO;
- goto udc_remove;
- }
+ ret = platform_device_add_data(plat_ci, &ci13xxx_msm_udc_driver,
+ sizeof(ci13xxx_msm_udc_driver));
+ if (ret)
+ goto put_platform;
- ret = request_irq(irq, msm_udc_irq, IRQF_SHARED, pdev->name, pdev);
- if (ret < 0) {
- dev_err(&pdev->dev, "request_irq failed\n");
- goto udc_remove;
- }
+ ret = platform_device_add(plat_ci);
+ if (ret)
+ goto put_platform;
pm_runtime_no_callbacks(&pdev->dev);
pm_runtime_enable(&pdev->dev);
return 0;
-udc_remove:
- udc_remove();
-iounmap:
- iounmap(regs);
+put_platform:
+ platform_device_put(plat_ci);
return ret;
}
diff --git a/drivers/usb/gadget/ci13xxx_pci.c b/drivers/usb/chipidea/ci13xxx_pci.c
index 883ab5e832d1..e3dab27f5c75 100644
--- a/drivers/usb/gadget/ci13xxx_pci.c
+++ b/drivers/usb/chipidea/ci13xxx_pci.c
@@ -10,10 +10,12 @@
* published by the Free Software Foundation.
*/
+#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/pci.h>
-
-#include "ci13xxx_udc.c"
+#include <linux/interrupt.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/chipidea.h>
/* driver name */
#define UDC_DRIVER_NAME "ci13xxx_pci"
@@ -21,25 +23,20 @@
/******************************************************************************
* PCI block
*****************************************************************************/
-/**
- * ci13xxx_pci_irq: interrut handler
- * @irq: irq number
- * @pdev: USB Device Controller interrupt source
- *
- * This function returns IRQ_HANDLED if the IRQ has been handled
- * This is an ISR don't trace, use attribute interface instead
- */
-static irqreturn_t ci13xxx_pci_irq(int irq, void *pdev)
-{
- if (irq == 0) {
- dev_err(&((struct pci_dev *)pdev)->dev, "Invalid IRQ0 usage!");
- return IRQ_HANDLED;
- }
- return udc_irq();
-}
+struct ci13xxx_udc_driver pci_driver = {
+ .name = UDC_DRIVER_NAME,
+ .capoffset = DEF_CAPOFFSET,
+};
-static struct ci13xxx_udc_driver ci13xxx_pci_udc_driver = {
+struct ci13xxx_udc_driver langwell_pci_driver = {
.name = UDC_DRIVER_NAME,
+ .capoffset = 0,
+};
+
+struct ci13xxx_udc_driver penwell_pci_driver = {
+ .name = UDC_DRIVER_NAME,
+ .capoffset = 0,
+ .power_budget = 200,
};
/**
@@ -54,11 +51,15 @@ static struct ci13xxx_udc_driver ci13xxx_pci_udc_driver = {
static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
- void __iomem *regs = NULL;
- int retval = 0;
-
- if (id == NULL)
- return -EINVAL;
+ struct ci13xxx_udc_driver *driver = (void *)id->driver_data;
+ struct platform_device *plat_ci;
+ struct resource res[3];
+ int retval = 0, nres = 2;
+
+ if (!driver) {
+ dev_err(&pdev->dev, "device doesn't provide driver data\n");
+ return -ENODEV;
+ }
retval = pci_enable_device(pdev);
if (retval)
@@ -70,41 +71,50 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
goto disable_device;
}
- retval = pci_request_regions(pdev, UDC_DRIVER_NAME);
- if (retval)
- goto disable_device;
+ pci_set_power_state(pdev, PCI_D0);
+ pci_set_master(pdev);
+ pci_try_set_mwi(pdev);
- /* BAR 0 holds all the registers */
- regs = pci_iomap(pdev, 0, 0);
- if (!regs) {
- dev_err(&pdev->dev, "Error mapping memory!");
- retval = -EFAULT;
- goto release_regions;
+ plat_ci = platform_device_alloc("ci_hdrc", -1);
+ if (!plat_ci) {
+ dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n");
+ retval = -ENOMEM;
+ goto disable_device;
}
- pci_set_drvdata(pdev, (__force void *)regs);
- pci_set_master(pdev);
- pci_try_set_mwi(pdev);
+ memset(res, 0, sizeof(res));
+ res[0].start = pci_resource_start(pdev, 0);
+ res[0].end = pci_resource_end(pdev, 0);
+ res[0].flags = IORESOURCE_MEM;
+ res[1].start = pdev->irq;
+ res[1].flags = IORESOURCE_IRQ;
+
+ retval = platform_device_add_resources(plat_ci, res, nres);
+ if (retval) {
+ dev_err(&pdev->dev, "can't add resources to platform device\n");
+ goto put_platform;
+ }
- retval = udc_probe(&ci13xxx_pci_udc_driver, &pdev->dev, regs);
+ retval = platform_device_add_data(plat_ci, driver, sizeof(*driver));
if (retval)
- goto iounmap;
+ goto put_platform;
+
+ dma_set_coherent_mask(&plat_ci->dev, pdev->dev.coherent_dma_mask);
+ plat_ci->dev.dma_mask = pdev->dev.dma_mask;
+ plat_ci->dev.dma_parms = pdev->dev.dma_parms;
+ plat_ci->dev.parent = &pdev->dev;
- /* our device does not have MSI capability */
+ pci_set_drvdata(pdev, plat_ci);
- retval = request_irq(pdev->irq, ci13xxx_pci_irq, IRQF_SHARED,
- UDC_DRIVER_NAME, pdev);
+ retval = platform_device_add(plat_ci);
if (retval)
- goto gadget_remove;
+ goto put_platform;
return 0;
- gadget_remove:
- udc_remove();
- iounmap:
- pci_iounmap(pdev, regs);
- release_regions:
- pci_release_regions(pdev);
+ put_platform:
+ pci_set_drvdata(pdev, NULL);
+ platform_device_put(plat_ci);
disable_device:
pci_disable_device(pdev);
done:
@@ -121,10 +131,10 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
*/
static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
{
- free_irq(pdev->irq, pdev);
- udc_remove();
- pci_iounmap(pdev, (__force void __iomem *)pci_get_drvdata(pdev));
- pci_release_regions(pdev);
+ struct platform_device *plat_ci = pci_get_drvdata(pdev);
+
+ platform_device_unregister(plat_ci);
+ pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
}
@@ -135,8 +145,22 @@ static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
* Check "pci.h" for details
*/
static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
- { PCI_DEVICE(0x153F, 0x1004) },
- { PCI_DEVICE(0x153F, 0x1006) },
+ {
+ PCI_DEVICE(0x153F, 0x1004),
+ .driver_data = (kernel_ulong_t)&pci_driver,
+ },
+ {
+ PCI_DEVICE(0x153F, 0x1006),
+ .driver_data = (kernel_ulong_t)&pci_driver,
+ },
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811),
+ .driver_data = (kernel_ulong_t)&langwell_pci_driver,
+ },
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829),
+ .driver_data = (kernel_ulong_t)&penwell_pci_driver,
+ },
{ 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table);
@@ -148,27 +172,7 @@ static struct pci_driver ci13xxx_pci_driver = {
.remove = __devexit_p(ci13xxx_pci_remove),
};
-/**
- * ci13xxx_pci_init: module init
- *
- * Driver load
- */
-static int __init ci13xxx_pci_init(void)
-{
- return pci_register_driver(&ci13xxx_pci_driver);
-}
-module_init(ci13xxx_pci_init);
-
-/**
- * ci13xxx_pci_exit: module exit
- *
- * Driver unload
- */
-static void __exit ci13xxx_pci_exit(void)
-{
- pci_unregister_driver(&ci13xxx_pci_driver);
-}
-module_exit(ci13xxx_pci_exit);
+module_pci_driver(ci13xxx_pci_driver);
MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
new file mode 100644
index 000000000000..15e03b308f8a
--- /dev/null
+++ b/drivers/usb/chipidea/core.c
@@ -0,0 +1,474 @@
+/*
+ * core.c - ChipIdea USB IP core family device controller
+ *
+ * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
+ *
+ * Author: David Lopo
+ *
+ * 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.
+ */
+
+/*
+ * Description: ChipIdea USB IP core family device controller
+ *
+ * This driver is composed of several blocks:
+ * - HW: hardware interface
+ * - DBG: debug facilities (optional)
+ * - UTIL: utilities
+ * - ISR: interrupts handling
+ * - ENDPT: endpoint operations (Gadget API)
+ * - GADGET: gadget operations (Gadget API)
+ * - BUS: bus glue code, bus abstraction layer
+ *
+ * Compile Options
+ * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities
+ * - STALL_IN: non-empty bulk-in pipes cannot be halted
+ * if defined mass storage compliance succeeds but with warnings
+ * => case 4: Hi > Dn
+ * => case 5: Hi > Di
+ * => case 8: Hi <> Do
+ * if undefined usbtest 13 fails
+ * - TRACE: enable function tracing (depends on DEBUG)
+ *
+ * Main Features
+ * - Chapter 9 & Mass Storage Compliance with Gadget File Storage
+ * - Chapter 9 Compliance with Gadget Zero (STALL_IN undefined)
+ * - Normal & LPM support
+ *
+ * USBTEST Report
+ * - OK: 0-12, 13 (STALL_IN defined) & 14
+ * - Not Supported: 15 & 16 (ISO)
+ *
+ * TODO List
+ * - OTG
+ * - Isochronous & Interrupt Traffic
+ * - Handle requests which spawns into several TDs
+ * - GET_STATUS(device) - always reports 0
+ * - Gadget API (majority of optional features)
+ * - Suspend & Remote Wakeup
+ */
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dmapool.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/chipidea.h>
+
+#include "ci.h"
+#include "udc.h"
+#include "bits.h"
+#include "host.h"
+#include "debug.h"
+
+/* Controller register map */
+static uintptr_t ci_regs_nolpm[] = {
+ [CAP_CAPLENGTH] = 0x000UL,
+ [CAP_HCCPARAMS] = 0x008UL,
+ [CAP_DCCPARAMS] = 0x024UL,
+ [CAP_TESTMODE] = 0x038UL,
+ [OP_USBCMD] = 0x000UL,
+ [OP_USBSTS] = 0x004UL,
+ [OP_USBINTR] = 0x008UL,
+ [OP_DEVICEADDR] = 0x014UL,
+ [OP_ENDPTLISTADDR] = 0x018UL,
+ [OP_PORTSC] = 0x044UL,
+ [OP_DEVLC] = 0x084UL,
+ [OP_OTGSC] = 0x064UL,
+ [OP_USBMODE] = 0x068UL,
+ [OP_ENDPTSETUPSTAT] = 0x06CUL,
+ [OP_ENDPTPRIME] = 0x070UL,
+ [OP_ENDPTFLUSH] = 0x074UL,
+ [OP_ENDPTSTAT] = 0x078UL,
+ [OP_ENDPTCOMPLETE] = 0x07CUL,
+ [OP_ENDPTCTRL] = 0x080UL,
+};
+
+static uintptr_t ci_regs_lpm[] = {
+ [CAP_CAPLENGTH] = 0x000UL,
+ [CAP_HCCPARAMS] = 0x008UL,
+ [CAP_DCCPARAMS] = 0x024UL,
+ [CAP_TESTMODE] = 0x0FCUL,
+ [OP_USBCMD] = 0x000UL,
+ [OP_USBSTS] = 0x004UL,
+ [OP_USBINTR] = 0x008UL,
+ [OP_DEVICEADDR] = 0x014UL,
+ [OP_ENDPTLISTADDR] = 0x018UL,
+ [OP_PORTSC] = 0x044UL,
+ [OP_DEVLC] = 0x084UL,
+ [OP_OTGSC] = 0x0C4UL,
+ [OP_USBMODE] = 0x0C8UL,
+ [OP_ENDPTSETUPSTAT] = 0x0D8UL,
+ [OP_ENDPTPRIME] = 0x0DCUL,
+ [OP_ENDPTFLUSH] = 0x0E0UL,
+ [OP_ENDPTSTAT] = 0x0E4UL,
+ [OP_ENDPTCOMPLETE] = 0x0E8UL,
+ [OP_ENDPTCTRL] = 0x0ECUL,
+};
+
+static int hw_alloc_regmap(struct ci13xxx *ci, bool is_lpm)
+{
+ int i;
+
+ kfree(ci->hw_bank.regmap);
+
+ ci->hw_bank.regmap = kzalloc((OP_LAST + 1) * sizeof(void *),
+ GFP_KERNEL);
+ if (!ci->hw_bank.regmap)
+ return -ENOMEM;
+
+ for (i = 0; i < OP_ENDPTCTRL; i++)
+ ci->hw_bank.regmap[i] =
+ (i <= CAP_LAST ? ci->hw_bank.cap : ci->hw_bank.op) +
+ (is_lpm ? ci_regs_lpm[i] : ci_regs_nolpm[i]);
+
+ for (; i <= OP_LAST; i++)
+ ci->hw_bank.regmap[i] = ci->hw_bank.op +
+ 4 * (i - OP_ENDPTCTRL) +
+ (is_lpm
+ ? ci_regs_lpm[OP_ENDPTCTRL]
+ : ci_regs_nolpm[OP_ENDPTCTRL]);
+
+ return 0;
+}
+
+/**
+ * hw_port_test_set: writes port test mode (execute without interruption)
+ * @mode: new value
+ *
+ * This function returns an error code
+ */
+int hw_port_test_set(struct ci13xxx *ci, u8 mode)
+{
+ const u8 TEST_MODE_MAX = 7;
+
+ if (mode > TEST_MODE_MAX)
+ return -EINVAL;
+
+ hw_write(ci, OP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC));
+ return 0;
+}
+
+/**
+ * hw_port_test_get: reads port test mode value
+ *
+ * This function returns port test mode value
+ */
+u8 hw_port_test_get(struct ci13xxx *ci)
+{
+ return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC);
+}
+
+static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
+{
+ u32 reg;
+
+ /* bank is a module variable */
+ ci->hw_bank.abs = base;
+
+ ci->hw_bank.cap = ci->hw_bank.abs;
+ ci->hw_bank.cap += ci->udc_driver->capoffset;
+ ci->hw_bank.op = ci->hw_bank.cap + ioread8(ci->hw_bank.cap);
+
+ hw_alloc_regmap(ci, false);
+ reg = hw_read(ci, CAP_HCCPARAMS, HCCPARAMS_LEN) >>
+ ffs_nr(HCCPARAMS_LEN);
+ ci->hw_bank.lpm = reg;
+ hw_alloc_regmap(ci, !!reg);
+ ci->hw_bank.size = ci->hw_bank.op - ci->hw_bank.abs;
+ ci->hw_bank.size += OP_LAST;
+ ci->hw_bank.size /= sizeof(u32);
+
+ reg = hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DEN) >>
+ ffs_nr(DCCPARAMS_DEN);
+ ci->hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */
+
+ if (ci->hw_ep_max > ENDPT_MAX)
+ return -ENODEV;
+
+ dev_dbg(ci->dev, "ChipIdea HDRC found, lpm: %d; cap: %p op: %p\n",
+ ci->hw_bank.lpm, ci->hw_bank.cap, ci->hw_bank.op);
+
+ /* setup lock mode ? */
+
+ /* ENDPTSETUPSTAT is '0' by default */
+
+ /* HCSPARAMS.bf.ppc SHOULD BE zero for device */
+
+ return 0;
+}
+
+/**
+ * hw_device_reset: resets chip (execute without interruption)
+ * @ci: the controller
+ *
+ * This function returns an error code
+ */
+int hw_device_reset(struct ci13xxx *ci, u32 mode)
+{
+ /* should flush & stop before reset */
+ hw_write(ci, OP_ENDPTFLUSH, ~0, ~0);
+ hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
+
+ hw_write(ci, OP_USBCMD, USBCMD_RST, USBCMD_RST);
+ while (hw_read(ci, OP_USBCMD, USBCMD_RST))
+ udelay(10); /* not RTOS friendly */
+
+
+ if (ci->udc_driver->notify_event)
+ ci->udc_driver->notify_event(ci,
+ CI13XXX_CONTROLLER_RESET_EVENT);
+
+ if (ci->udc_driver->flags & CI13XXX_DISABLE_STREAMING)
+ hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
+
+ /* USBMODE should be configured step by step */
+ hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
+ hw_write(ci, OP_USBMODE, USBMODE_CM, mode);
+ /* HW >= 2.3 */
+ hw_write(ci, OP_USBMODE, USBMODE_SLOM, USBMODE_SLOM);
+
+ if (hw_read(ci, OP_USBMODE, USBMODE_CM) != mode) {
+ pr_err("cannot enter in %s mode", ci_role(ci)->name);
+ pr_err("lpm = %i", ci->hw_bank.lpm);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/**
+ * ci_otg_role - pick role based on ID pin state
+ * @ci: the controller
+ */
+static enum ci_role ci_otg_role(struct ci13xxx *ci)
+{
+ u32 sts = hw_read(ci, OP_OTGSC, ~0);
+ enum ci_role role = sts & OTGSC_ID
+ ? CI_ROLE_GADGET
+ : CI_ROLE_HOST;
+
+ return role;
+}
+
+/**
+ * ci_role_work - perform role changing based on ID pin
+ * @work: work struct
+ */
+static void ci_role_work(struct work_struct *work)
+{
+ struct ci13xxx *ci = container_of(work, struct ci13xxx, work);
+ enum ci_role role = ci_otg_role(ci);
+
+ hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS);
+
+ if (role != ci->role) {
+ dev_dbg(ci->dev, "switching from %s to %s\n",
+ ci_role(ci)->name, ci->roles[role]->name);
+
+ ci_role_stop(ci);
+ ci_role_start(ci, role);
+ }
+}
+
+static ssize_t show_role(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct ci13xxx *ci = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", ci_role(ci)->name);
+}
+
+static ssize_t store_role(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ci13xxx *ci = dev_get_drvdata(dev);
+ enum ci_role role;
+ int ret;
+
+ for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++)
+ if (ci->roles[role] && !strcmp(buf, ci->roles[role]->name))
+ break;
+
+ if (role == CI_ROLE_END || role == ci->role)
+ return -EINVAL;
+
+ ci_role_stop(ci);
+ ret = ci_role_start(ci, role);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(role, S_IRUSR | S_IWUSR, show_role, store_role);
+
+static irqreturn_t ci_irq(int irq, void *data)
+{
+ struct ci13xxx *ci = data;
+ irqreturn_t ret = IRQ_NONE;
+
+ if (ci->is_otg) {
+ u32 sts = hw_read(ci, OP_OTGSC, ~0);
+
+ if (sts & OTGSC_IDIS) {
+ queue_work(ci->wq, &ci->work);
+ ret = IRQ_HANDLED;
+ }
+ }
+
+ return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci);
+}
+
+static int __devinit ci_hdrc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ci13xxx *ci;
+ struct resource *res;
+ void __iomem *base;
+ int ret;
+
+ if (!dev->platform_data) {
+ dev_err(dev, "platform data missing\n");
+ return -ENODEV;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "missing resource\n");
+ return -ENODEV;
+ }
+
+ base = devm_request_and_ioremap(dev, res);
+ if (!res) {
+ dev_err(dev, "can't request and ioremap resource\n");
+ return -ENOMEM;
+ }
+
+ ci = devm_kzalloc(dev, sizeof(*ci), GFP_KERNEL);
+ if (!ci) {
+ dev_err(dev, "can't allocate device\n");
+ return -ENOMEM;
+ }
+
+ ci->dev = dev;
+ ci->udc_driver = dev->platform_data;
+
+ ret = hw_device_init(ci, base);
+ if (ret < 0) {
+ dev_err(dev, "can't initialize hardware\n");
+ return -ENODEV;
+ }
+
+ ci->hw_bank.phys = res->start;
+
+ ci->irq = platform_get_irq(pdev, 0);
+ if (ci->irq < 0) {
+ dev_err(dev, "missing IRQ\n");
+ return -ENODEV;
+ }
+
+ INIT_WORK(&ci->work, ci_role_work);
+ ci->wq = create_singlethread_workqueue("ci_otg");
+ if (!ci->wq) {
+ dev_err(dev, "can't create workqueue\n");
+ return -ENODEV;
+ }
+
+ /* initialize role(s) before the interrupt is requested */
+ ret = ci_hdrc_host_init(ci);
+ if (ret)
+ dev_info(dev, "doesn't support host\n");
+
+ ret = ci_hdrc_gadget_init(ci);
+ if (ret)
+ dev_info(dev, "doesn't support gadget\n");
+
+ if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) {
+ dev_err(dev, "no supported roles\n");
+ ret = -ENODEV;
+ goto rm_wq;
+ }
+
+ if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) {
+ ci->is_otg = true;
+ ci->role = ci_otg_role(ci);
+ } else {
+ ci->role = ci->roles[CI_ROLE_HOST]
+ ? CI_ROLE_HOST
+ : CI_ROLE_GADGET;
+ }
+
+ ret = ci_role_start(ci, ci->role);
+ if (ret) {
+ dev_err(dev, "can't start %s role\n", ci_role(ci)->name);
+ ret = -ENODEV;
+ goto rm_wq;
+ }
+
+ platform_set_drvdata(pdev, ci);
+ ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->udc_driver->name,
+ ci);
+ if (ret)
+ goto stop;
+
+ ret = device_create_file(dev, &dev_attr_role);
+ if (ret)
+ goto rm_attr;
+
+ if (ci->is_otg)
+ hw_write(ci, OP_OTGSC, OTGSC_IDIE, OTGSC_IDIE);
+
+ return ret;
+
+rm_attr:
+ device_remove_file(dev, &dev_attr_role);
+stop:
+ ci_role_stop(ci);
+rm_wq:
+ flush_workqueue(ci->wq);
+ destroy_workqueue(ci->wq);
+
+ return ret;
+}
+
+static int __devexit ci_hdrc_remove(struct platform_device *pdev)
+{
+ struct ci13xxx *ci = platform_get_drvdata(pdev);
+
+ flush_workqueue(ci->wq);
+ destroy_workqueue(ci->wq);
+ device_remove_file(ci->dev, &dev_attr_role);
+ free_irq(ci->irq, ci);
+ ci_role_stop(ci);
+
+ return 0;
+}
+
+static struct platform_driver ci_hdrc_driver = {
+ .probe = ci_hdrc_probe,
+ .remove = __devexit_p(ci_hdrc_remove),
+ .driver = {
+ .name = "ci_hdrc",
+ },
+};
+
+module_platform_driver(ci_hdrc_driver);
+
+MODULE_ALIAS("platform:ci_hdrc");
+MODULE_ALIAS("platform:ci13xxx");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("David Lopo <dlopo@chipidea.mips.com>");
+MODULE_DESCRIPTION("ChipIdea HDRC Driver");
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
new file mode 100644
index 000000000000..c4b3e15532db
--- /dev/null
+++ b/drivers/usb/chipidea/debug.c
@@ -0,0 +1,804 @@
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dmapool.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/chipidea.h>
+
+#include "ci.h"
+#include "udc.h"
+#include "bits.h"
+#include "debug.h"
+
+/* Interrupt statistics */
+#define ISR_MASK 0x1F
+static struct isr_statistics {
+ u32 test;
+ u32 ui;
+ u32 uei;
+ u32 pci;
+ u32 uri;
+ u32 sli;
+ u32 none;
+ struct {
+ u32 cnt;
+ u32 buf[ISR_MASK+1];
+ u32 idx;
+ } hndl;
+} isr_statistics;
+
+void dbg_interrupt(u32 intmask)
+{
+ if (!intmask) {
+ isr_statistics.none++;
+ return;
+ }
+
+ isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intmask;
+ isr_statistics.hndl.idx &= ISR_MASK;
+ isr_statistics.hndl.cnt++;
+
+ if (USBi_URI & intmask)
+ isr_statistics.uri++;
+ if (USBi_PCI & intmask)
+ isr_statistics.pci++;
+ if (USBi_UEI & intmask)
+ isr_statistics.uei++;
+ if (USBi_UI & intmask)
+ isr_statistics.ui++;
+ if (USBi_SLI & intmask)
+ isr_statistics.sli++;
+}
+
+/**
+ * hw_register_read: reads all device registers (execute without interruption)
+ * @buf: destination buffer
+ * @size: buffer size
+ *
+ * This function returns number of registers read
+ */
+static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size)
+{
+ unsigned i;
+
+ if (size > udc->hw_bank.size)
+ size = udc->hw_bank.size;
+
+ for (i = 0; i < size; i++)
+ buf[i] = hw_read(udc, i * sizeof(u32), ~0);
+
+ return size;
+}
+
+/**
+ * hw_register_write: writes to register
+ * @addr: register address
+ * @data: register value
+ *
+ * This function returns an error code
+ */
+static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data)
+{
+ /* align */
+ addr /= sizeof(u32);
+
+ if (addr >= udc->hw_bank.size)
+ return -EINVAL;
+
+ /* align */
+ addr *= sizeof(u32);
+
+ hw_write(udc, addr, ~0, data);
+ return 0;
+}
+
+/**
+ * hw_intr_clear: disables interrupt & clears interrupt status (execute without
+ * interruption)
+ * @n: interrupt bit
+ *
+ * This function returns an error code
+ */
+static int hw_intr_clear(struct ci13xxx *udc, int n)
+{
+ if (n >= REG_BITS)
+ return -EINVAL;
+
+ hw_write(udc, OP_USBINTR, BIT(n), 0);
+ hw_write(udc, OP_USBSTS, BIT(n), BIT(n));
+ return 0;
+}
+
+/**
+ * hw_intr_force: enables interrupt & forces interrupt status (execute without
+ * interruption)
+ * @n: interrupt bit
+ *
+ * This function returns an error code
+ */
+static int hw_intr_force(struct ci13xxx *udc, int n)
+{
+ if (n >= REG_BITS)
+ return -EINVAL;
+
+ hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
+ hw_write(udc, OP_USBINTR, BIT(n), BIT(n));
+ hw_write(udc, OP_USBSTS, BIT(n), BIT(n));
+ hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, 0);
+ return 0;
+}
+
+/**
+ * show_device: prints information about device capabilities and status
+ *
+ * Check "device.h" for details
+ */
+static ssize_t show_device(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ struct usb_gadget *gadget = &udc->gadget;
+ int n = 0;
+
+ if (attr == NULL || buf == NULL) {
+ dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+ return 0;
+ }
+
+ n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
+ gadget->speed);
+ n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
+ gadget->max_speed);
+ /* TODO: Scheduled for removal in 3.8. */
+ n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
+ gadget_is_dualspeed(gadget));
+ n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
+ gadget->is_otg);
+ n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
+ gadget->is_a_peripheral);
+ n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n",
+ gadget->b_hnp_enable);
+ n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n",
+ gadget->a_hnp_support);
+ n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
+ gadget->a_alt_hnp_support);
+ n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n",
+ (gadget->name ? gadget->name : ""));
+
+ return n;
+}
+static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
+
+/**
+ * show_driver: prints information about attached gadget (if any)
+ *
+ * Check "device.h" for details
+ */
+static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ struct usb_gadget_driver *driver = udc->driver;
+ int n = 0;
+
+ if (attr == NULL || buf == NULL) {
+ dev_err(dev, "[%s] EINVAL\n", __func__);
+ return 0;
+ }
+
+ if (driver == NULL)
+ return scnprintf(buf, PAGE_SIZE,
+ "There is no gadget attached!\n");
+
+ n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
+ (driver->function ? driver->function : ""));
+ n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
+ driver->max_speed);
+
+ return n;
+}
+static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
+
+/* Maximum event message length */
+#define DBG_DATA_MSG 64UL
+
+/* Maximum event messages */
+#define DBG_DATA_MAX 128UL
+
+/* Event buffer descriptor */
+static struct {
+ char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
+ unsigned idx; /* index */
+ unsigned tty; /* print to console? */
+ rwlock_t lck; /* lock */
+} dbg_data = {
+ .idx = 0,
+ .tty = 0,
+ .lck = __RW_LOCK_UNLOCKED(lck)
+};
+
+/**
+ * dbg_dec: decrements debug event index
+ * @idx: buffer index
+ */
+static void dbg_dec(unsigned *idx)
+{
+ *idx = (*idx - 1) & (DBG_DATA_MAX-1);
+}
+
+/**
+ * dbg_inc: increments debug event index
+ * @idx: buffer index
+ */
+static void dbg_inc(unsigned *idx)
+{
+ *idx = (*idx + 1) & (DBG_DATA_MAX-1);
+}
+
+/**
+ * dbg_print: prints the common part of the event
+ * @addr: endpoint address
+ * @name: event name
+ * @status: status
+ * @extra: extra information
+ */
+static void dbg_print(u8 addr, const char *name, int status, const char *extra)
+{
+ struct timeval tval;
+ unsigned int stamp;
+ unsigned long flags;
+
+ write_lock_irqsave(&dbg_data.lck, flags);
+
+ do_gettimeofday(&tval);
+ stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
+ stamp = stamp * 1000000 + tval.tv_usec;
+
+ scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
+ "%04X\t? %02X %-7.7s %4i ?\t%s\n",
+ stamp, addr, name, status, extra);
+
+ dbg_inc(&dbg_data.idx);
+
+ write_unlock_irqrestore(&dbg_data.lck, flags);
+
+ if (dbg_data.tty != 0)
+ pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
+ stamp, addr, name, status, extra);
+}
+
+/**
+ * dbg_done: prints a DONE event
+ * @addr: endpoint address
+ * @td: transfer descriptor
+ * @status: status
+ */
+void dbg_done(u8 addr, const u32 token, int status)
+{
+ char msg[DBG_DATA_MSG];
+
+ scnprintf(msg, sizeof(msg), "%d %02X",
+ (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
+ (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
+ dbg_print(addr, "DONE", status, msg);
+}
+
+/**
+ * dbg_event: prints a generic event
+ * @addr: endpoint address
+ * @name: event name
+ * @status: status
+ */
+void dbg_event(u8 addr, const char *name, int status)
+{
+ if (name != NULL)
+ dbg_print(addr, name, status, "");
+}
+
+/*
+ * dbg_queue: prints a QUEUE event
+ * @addr: endpoint address
+ * @req: USB request
+ * @status: status
+ */
+void dbg_queue(u8 addr, const struct usb_request *req, int status)
+{
+ char msg[DBG_DATA_MSG];
+
+ if (req != NULL) {
+ scnprintf(msg, sizeof(msg),
+ "%d %d", !req->no_interrupt, req->length);
+ dbg_print(addr, "QUEUE", status, msg);
+ }
+}
+
+/**
+ * dbg_setup: prints a SETUP event
+ * @addr: endpoint address
+ * @req: setup request
+ */
+void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
+{
+ char msg[DBG_DATA_MSG];
+
+ if (req != NULL) {
+ scnprintf(msg, sizeof(msg),
+ "%02X %02X %04X %04X %d", req->bRequestType,
+ req->bRequest, le16_to_cpu(req->wValue),
+ le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
+ dbg_print(addr, "SETUP", 0, msg);
+ }
+}
+
+/**
+ * show_events: displays the event buffer
+ *
+ * Check "device.h" for details
+ */
+static ssize_t show_events(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long flags;
+ unsigned i, j, n = 0;
+
+ if (attr == NULL || buf == NULL) {
+ dev_err(dev->parent, "[%s] EINVAL\n", __func__);
+ return 0;
+ }
+
+ read_lock_irqsave(&dbg_data.lck, flags);
+
+ i = dbg_data.idx;
+ for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
+ n += strlen(dbg_data.buf[i]);
+ if (n >= PAGE_SIZE) {
+ n -= strlen(dbg_data.buf[i]);
+ break;
+ }
+ }
+ for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
+ j += scnprintf(buf + j, PAGE_SIZE - j,
+ "%s", dbg_data.buf[i]);
+
+ read_unlock_irqrestore(&dbg_data.lck, flags);
+
+ return n;
+}
+
+/**
+ * store_events: configure if events are going to be also printed to console
+ *
+ * Check "device.h" for details
+ */
+static ssize_t store_events(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned tty;
+
+ if (attr == NULL || buf == NULL) {
+ dev_err(dev, "[%s] EINVAL\n", __func__);
+ goto done;
+ }
+
+ if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
+ dev_err(dev, "<1|0>: enable|disable console log\n");
+ goto done;
+ }
+
+ dbg_data.tty = tty;
+ dev_info(dev, "tty = %u", dbg_data.tty);
+
+ done:
+ return count;
+}
+static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
+
+/**
+ * show_inters: interrupt status, enable status and historic
+ *
+ * Check "device.h" for details
+ */
+static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ unsigned long flags;
+ u32 intr;
+ unsigned i, j, n = 0;
+
+ if (attr == NULL || buf == NULL) {
+ dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+ return 0;
+ }
+
+ spin_lock_irqsave(&udc->lock, flags);
+
+ /*n += scnprintf(buf + n, PAGE_SIZE - n,
+ "status = %08x\n", hw_read_intr_status(udc));
+ n += scnprintf(buf + n, PAGE_SIZE - n,
+ "enable = %08x\n", hw_read_intr_enable(udc));*/
+
+ n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
+ isr_statistics.test);
+ n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n",
+ isr_statistics.ui);
+ n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
+ isr_statistics.uei);
+ n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
+ isr_statistics.pci);
+ n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
+ isr_statistics.uri);
+ n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
+ isr_statistics.sli);
+ n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
+ isr_statistics.none);
+ n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
+ isr_statistics.hndl.cnt);
+
+ for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
+ i &= ISR_MASK;
+ intr = isr_statistics.hndl.buf[i];
+
+ if (USBi_UI & intr)
+ n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
+ intr &= ~USBi_UI;
+ if (USBi_UEI & intr)
+ n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
+ intr &= ~USBi_UEI;
+ if (USBi_PCI & intr)
+ n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
+ intr &= ~USBi_PCI;
+ if (USBi_URI & intr)
+ n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
+ intr &= ~USBi_URI;
+ if (USBi_SLI & intr)
+ n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
+ intr &= ~USBi_SLI;
+ if (intr)
+ n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
+ if (isr_statistics.hndl.buf[i])
+ n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
+ }
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ return n;
+}
+
+/**
+ * store_inters: enable & force or disable an individual interrutps
+ * (to be used for test purposes only)
+ *
+ * Check "device.h" for details
+ */
+static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ unsigned long flags;
+ unsigned en, bit;
+
+ if (attr == NULL || buf == NULL) {
+ dev_err(udc->dev, "EINVAL\n");
+ goto done;
+ }
+
+ if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
+ dev_err(udc->dev, "<1|0> <bit>: enable|disable interrupt\n");
+ goto done;
+ }
+
+ spin_lock_irqsave(&udc->lock, flags);
+ if (en) {
+ if (hw_intr_force(udc, bit))
+ dev_err(dev, "invalid bit number\n");
+ else
+ isr_statistics.test++;
+ } else {
+ if (hw_intr_clear(udc, bit))
+ dev_err(dev, "invalid bit number\n");
+ }
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ done:
+ return count;
+}
+static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
+
+/**
+ * show_port_test: reads port test mode
+ *
+ * Check "device.h" for details
+ */
+static ssize_t show_port_test(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ unsigned long flags;
+ unsigned mode;
+
+ if (attr == NULL || buf == NULL) {
+ dev_err(udc->dev, "EINVAL\n");
+ return 0;
+ }
+
+ spin_lock_irqsave(&udc->lock, flags);
+ mode = hw_port_test_get(udc);
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
+}
+
+/**
+ * store_port_test: writes port test mode
+ *
+ * Check "device.h" for details
+ */
+static ssize_t store_port_test(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ unsigned long flags;
+ unsigned mode;
+
+ if (attr == NULL || buf == NULL) {
+ dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+ goto done;
+ }
+
+ if (sscanf(buf, "%u", &mode) != 1) {
+ dev_err(udc->dev, "<mode>: set port test mode");
+ goto done;
+ }
+
+ spin_lock_irqsave(&udc->lock, flags);
+ if (hw_port_test_set(udc, mode))
+ dev_err(udc->dev, "invalid mode\n");
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ done:
+ return count;
+}
+static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
+ show_port_test, store_port_test);
+
+/**
+ * show_qheads: DMA contents of all queue heads
+ *
+ * Check "device.h" for details
+ */
+static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ unsigned long flags;
+ unsigned i, j, n = 0;
+
+ if (attr == NULL || buf == NULL) {
+ dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+ return 0;
+ }
+
+ spin_lock_irqsave(&udc->lock, flags);
+ for (i = 0; i < udc->hw_ep_max/2; i++) {
+ struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
+ struct ci13xxx_ep *mEpTx =
+ &udc->ci13xxx_ep[i + udc->hw_ep_max/2];
+ n += scnprintf(buf + n, PAGE_SIZE - n,
+ "EP=%02i: RX=%08X TX=%08X\n",
+ i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
+ for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
+ n += scnprintf(buf + n, PAGE_SIZE - n,
+ " %04X: %08X %08X\n", j,
+ *((u32 *)mEpRx->qh.ptr + j),
+ *((u32 *)mEpTx->qh.ptr + j));
+ }
+ }
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ return n;
+}
+static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
+
+/**
+ * show_registers: dumps all registers
+ *
+ * Check "device.h" for details
+ */
+#define DUMP_ENTRIES 512
+static ssize_t show_registers(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ unsigned long flags;
+ u32 *dump;
+ unsigned i, k, n = 0;
+
+ if (attr == NULL || buf == NULL) {
+ dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+ return 0;
+ }
+
+ dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
+ if (!dump) {
+ dev_err(udc->dev, "%s: out of memory\n", __func__);
+ return 0;
+ }
+
+ spin_lock_irqsave(&udc->lock, flags);
+ k = hw_register_read(udc, dump, DUMP_ENTRIES);
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ for (i = 0; i < k; i++) {
+ n += scnprintf(buf + n, PAGE_SIZE - n,
+ "reg[0x%04X] = 0x%08X\n",
+ i * (unsigned)sizeof(u32), dump[i]);
+ }
+ kfree(dump);
+
+ return n;
+}
+
+/**
+ * store_registers: writes value to register address
+ *
+ * Check "device.h" for details
+ */
+static ssize_t store_registers(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ unsigned long addr, data, flags;
+
+ if (attr == NULL || buf == NULL) {
+ dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+ goto done;
+ }
+
+ if (sscanf(buf, "%li %li", &addr, &data) != 2) {
+ dev_err(udc->dev,
+ "<addr> <data>: write data to register address\n");
+ goto done;
+ }
+
+ spin_lock_irqsave(&udc->lock, flags);
+ if (hw_register_write(udc, addr, data))
+ dev_err(udc->dev, "invalid address range\n");
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ done:
+ return count;
+}
+static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
+ show_registers, store_registers);
+
+/**
+ * show_requests: DMA contents of all requests currently queued (all endpts)
+ *
+ * Check "device.h" for details
+ */
+static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ unsigned long flags;
+ struct list_head *ptr = NULL;
+ struct ci13xxx_req *req = NULL;
+ unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
+
+ if (attr == NULL || buf == NULL) {
+ dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+ return 0;
+ }
+
+ spin_lock_irqsave(&udc->lock, flags);
+ for (i = 0; i < udc->hw_ep_max; i++)
+ list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
+ {
+ req = list_entry(ptr, struct ci13xxx_req, queue);
+
+ n += scnprintf(buf + n, PAGE_SIZE - n,
+ "EP=%02i: TD=%08X %s\n",
+ i % udc->hw_ep_max/2, (u32)req->dma,
+ ((i < udc->hw_ep_max/2) ? "RX" : "TX"));
+
+ for (j = 0; j < qSize; j++)
+ n += scnprintf(buf + n, PAGE_SIZE - n,
+ " %04X: %08X\n", j,
+ *((u32 *)req->ptr + j));
+ }
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ return n;
+}
+static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
+
+/**
+ * dbg_create_files: initializes the attribute interface
+ * @dev: device
+ *
+ * This function returns an error code
+ */
+int dbg_create_files(struct device *dev)
+{
+ int retval = 0;
+
+ if (dev == NULL)
+ return -EINVAL;
+ retval = device_create_file(dev, &dev_attr_device);
+ if (retval)
+ goto done;
+ retval = device_create_file(dev, &dev_attr_driver);
+ if (retval)
+ goto rm_device;
+ retval = device_create_file(dev, &dev_attr_events);
+ if (retval)
+ goto rm_driver;
+ retval = device_create_file(dev, &dev_attr_inters);
+ if (retval)
+ goto rm_events;
+ retval = device_create_file(dev, &dev_attr_port_test);
+ if (retval)
+ goto rm_inters;
+ retval = device_create_file(dev, &dev_attr_qheads);
+ if (retval)
+ goto rm_port_test;
+ retval = device_create_file(dev, &dev_attr_registers);
+ if (retval)
+ goto rm_qheads;
+ retval = device_create_file(dev, &dev_attr_requests);
+ if (retval)
+ goto rm_registers;
+ return 0;
+
+ rm_registers:
+ device_remove_file(dev, &dev_attr_registers);
+ rm_qheads:
+ device_remove_file(dev, &dev_attr_qheads);
+ rm_port_test:
+ device_remove_file(dev, &dev_attr_port_test);
+ rm_inters:
+ device_remove_file(dev, &dev_attr_inters);
+ rm_events:
+ device_remove_file(dev, &dev_attr_events);
+ rm_driver:
+ device_remove_file(dev, &dev_attr_driver);
+ rm_device:
+ device_remove_file(dev, &dev_attr_device);
+ done:
+ return retval;
+}
+
+/**
+ * dbg_remove_files: destroys the attribute interface
+ * @dev: device
+ *
+ * This function returns an error code
+ */
+int dbg_remove_files(struct device *dev)
+{
+ if (dev == NULL)
+ return -EINVAL;
+ device_remove_file(dev, &dev_attr_requests);
+ device_remove_file(dev, &dev_attr_registers);
+ device_remove_file(dev, &dev_attr_qheads);
+ device_remove_file(dev, &dev_attr_port_test);
+ device_remove_file(dev, &dev_attr_inters);
+ device_remove_file(dev, &dev_attr_events);
+ device_remove_file(dev, &dev_attr_driver);
+ device_remove_file(dev, &dev_attr_device);
+ return 0;
+}
diff --git a/drivers/usb/chipidea/debug.h b/drivers/usb/chipidea/debug.h
new file mode 100644
index 000000000000..80d96865775c
--- /dev/null
+++ b/drivers/usb/chipidea/debug.h
@@ -0,0 +1,56 @@
+/*
+ * debug.h - ChipIdea USB driver debug interfaces
+ *
+ * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
+ *
+ * Author: David Lopo
+ *
+ * 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 __DRIVERS_USB_CHIPIDEA_DEBUG_H
+#define __DRIVERS_USB_CHIPIDEA_DEBUG_H
+
+#ifdef CONFIG_USB_CHIPIDEA_DEBUG
+void dbg_interrupt(u32 intmask);
+void dbg_done(u8 addr, const u32 token, int status);
+void dbg_event(u8 addr, const char *name, int status);
+void dbg_queue(u8 addr, const struct usb_request *req, int status);
+void dbg_setup(u8 addr, const struct usb_ctrlrequest *req);
+int dbg_create_files(struct device *dev);
+int dbg_remove_files(struct device *dev);
+#else
+static inline void dbg_interrupt(u32 intmask)
+{
+}
+
+static inline void dbg_done(u8 addr, const u32 token, int status)
+{
+}
+
+static inline void dbg_event(u8 addr, const char *name, int status)
+{
+}
+
+static inline void dbg_queue(u8 addr, const struct usb_request *req, int status)
+{
+}
+
+static inline void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
+{
+}
+
+static inline int dbg_create_files(struct device *dev)
+{
+ return 0;
+}
+
+static inline int dbg_remove_files(struct device *dev)
+{
+ return 0;
+}
+#endif
+
+#endif /* __DRIVERS_USB_CHIPIDEA_DEBUG_H */
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
new file mode 100644
index 000000000000..9eacd21c0cd9
--- /dev/null
+++ b/drivers/usb/chipidea/host.c
@@ -0,0 +1,160 @@
+/*
+ * host.c - ChipIdea USB host controller driver
+ *
+ * Copyright (c) 2012 Intel Corporation
+ *
+ * Author: Alexander Shishkin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/chipidea.h>
+
+#define CHIPIDEA_EHCI
+#include "../host/ehci-hcd.c"
+
+#include "ci.h"
+#include "bits.h"
+#include "host.h"
+
+static int ci_ehci_setup(struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ int ret;
+
+ hcd->has_tt = 1;
+
+ ret = ehci_setup(hcd);
+ if (ret)
+ return ret;
+
+ ehci_port_power(ehci, 0);
+
+ return ret;
+}
+
+static const struct hc_driver ci_ehci_hc_driver = {
+ .description = "ehci_hcd",
+ .product_desc = "ChipIdea HDRC EHCI",
+ .hcd_priv_size = sizeof(struct ehci_hcd),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = ehci_irq,
+ .flags = HCD_MEMORY | HCD_USB2,
+
+ /*
+ * basic lifecycle operations
+ */
+ .reset = ci_ehci_setup,
+ .start = ehci_run,
+ .stop = ehci_stop,
+ .shutdown = ehci_shutdown,
+
+ /*
+ * managing i/o requests and associated device resources
+ */
+ .urb_enqueue = ehci_urb_enqueue,
+ .urb_dequeue = ehci_urb_dequeue,
+ .endpoint_disable = ehci_endpoint_disable,
+ .endpoint_reset = ehci_endpoint_reset,
+
+ /*
+ * scheduling support
+ */
+ .get_frame_number = ehci_get_frame,
+
+ /*
+ * root hub support
+ */
+ .hub_status_data = ehci_hub_status_data,
+ .hub_control = ehci_hub_control,
+ .bus_suspend = ehci_bus_suspend,
+ .bus_resume = ehci_bus_resume,
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
+
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+};
+
+static irqreturn_t host_irq(struct ci13xxx *ci)
+{
+ return usb_hcd_irq(ci->irq, ci->hcd);
+}
+
+static int host_start(struct ci13xxx *ci)
+{
+ struct usb_hcd *hcd;
+ struct ehci_hcd *ehci;
+ int ret;
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ hcd = usb_create_hcd(&ci_ehci_hc_driver, ci->dev, dev_name(ci->dev));
+ if (!hcd)
+ return -ENOMEM;
+
+ dev_set_drvdata(ci->dev, ci);
+ hcd->rsrc_start = ci->hw_bank.phys;
+ hcd->rsrc_len = ci->hw_bank.size;
+ hcd->regs = ci->hw_bank.abs;
+ hcd->has_tt = 1;
+
+ hcd->power_budget = ci->udc_driver->power_budget;
+
+ ehci = hcd_to_ehci(hcd);
+ ehci->caps = ci->hw_bank.cap;
+ ehci->has_hostpc = ci->hw_bank.lpm;
+
+ ret = usb_add_hcd(hcd, 0, 0);
+ if (ret)
+ usb_put_hcd(hcd);
+ else
+ ci->hcd = hcd;
+
+ return ret;
+}
+
+static void host_stop(struct ci13xxx *ci)
+{
+ struct usb_hcd *hcd = ci->hcd;
+
+ usb_remove_hcd(hcd);
+ usb_put_hcd(hcd);
+}
+
+int ci_hdrc_host_init(struct ci13xxx *ci)
+{
+ struct ci_role_driver *rdrv;
+
+ if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_HC))
+ return -ENXIO;
+
+ rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL);
+ if (!rdrv)
+ return -ENOMEM;
+
+ rdrv->start = host_start;
+ rdrv->stop = host_stop;
+ rdrv->irq = host_irq;
+ rdrv->name = "host";
+ ci->roles[CI_ROLE_HOST] = rdrv;
+
+ return 0;
+}
diff --git a/drivers/usb/chipidea/host.h b/drivers/usb/chipidea/host.h
new file mode 100644
index 000000000000..761fb1fd6d99
--- /dev/null
+++ b/drivers/usb/chipidea/host.h
@@ -0,0 +1,17 @@
+#ifndef __DRIVERS_USB_CHIPIDEA_HOST_H
+#define __DRIVERS_USB_CHIPIDEA_HOST_H
+
+#ifdef CONFIG_USB_CHIPIDEA_HOST
+
+int ci_hdrc_host_init(struct ci13xxx *ci);
+
+#else
+
+static inline int ci_hdrc_host_init(struct ci13xxx *ci)
+{
+ return -ENXIO;
+}
+
+#endif
+
+#endif /* __DRIVERS_USB_CHIPIDEA_HOST_H */
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
new file mode 100644
index 000000000000..51f96942dc5e
--- /dev/null
+++ b/drivers/usb/chipidea/udc.c
@@ -0,0 +1,1809 @@
+/*
+ * udc.c - ChipIdea UDC driver
+ *
+ * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
+ *
+ * Author: David Lopo
+ *
+ * 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/delay.h>
+#include <linux/device.h>
+#include <linux/dmapool.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/chipidea.h>
+
+#include "ci.h"
+#include "udc.h"
+#include "bits.h"
+#include "debug.h"
+
+/* control endpoint description */
+static const struct usb_endpoint_descriptor
+ctrl_endpt_out_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
+ .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
+};
+
+static const struct usb_endpoint_descriptor
+ctrl_endpt_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
+ .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
+};
+
+/**
+ * hw_ep_bit: calculates the bit number
+ * @num: endpoint number
+ * @dir: endpoint direction
+ *
+ * This function returns bit number
+ */
+static inline int hw_ep_bit(int num, int dir)
+{
+ return num + (dir ? 16 : 0);
+}
+
+static inline int ep_to_bit(struct ci13xxx *udc, int n)
+{
+ int fill = 16 - udc->hw_ep_max / 2;
+
+ if (n >= udc->hw_ep_max / 2)
+ n += fill;
+
+ return n;
+}
+
+/**
+ * hw_device_state: enables/disables interrupts & starts/stops device (execute
+ * without interruption)
+ * @dma: 0 => disable, !0 => enable and set dma engine
+ *
+ * This function returns an error code
+ */
+static int hw_device_state(struct ci13xxx *udc, u32 dma)
+{
+ if (dma) {
+ hw_write(udc, OP_ENDPTLISTADDR, ~0, dma);
+ /* interrupt, error, port change, reset, sleep/suspend */
+ hw_write(udc, OP_USBINTR, ~0,
+ USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
+ hw_write(udc, OP_USBCMD, USBCMD_RS, USBCMD_RS);
+ } else {
+ hw_write(udc, OP_USBCMD, USBCMD_RS, 0);
+ hw_write(udc, OP_USBINTR, ~0, 0);
+ }
+ return 0;
+}
+
+/**
+ * hw_ep_flush: flush endpoint fifo (execute without interruption)
+ * @num: endpoint number
+ * @dir: endpoint direction
+ *
+ * This function returns an error code
+ */
+static int hw_ep_flush(struct ci13xxx *udc, int num, int dir)
+{
+ int n = hw_ep_bit(num, dir);
+
+ do {
+ /* flush any pending transfer */
+ hw_write(udc, OP_ENDPTFLUSH, BIT(n), BIT(n));
+ while (hw_read(udc, OP_ENDPTFLUSH, BIT(n)))
+ cpu_relax();
+ } while (hw_read(udc, OP_ENDPTSTAT, BIT(n)));
+
+ return 0;
+}
+
+/**
+ * hw_ep_disable: disables endpoint (execute without interruption)
+ * @num: endpoint number
+ * @dir: endpoint direction
+ *
+ * This function returns an error code
+ */
+static int hw_ep_disable(struct ci13xxx *udc, int num, int dir)
+{
+ hw_ep_flush(udc, num, dir);
+ hw_write(udc, OP_ENDPTCTRL + num,
+ dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0);
+ return 0;
+}
+
+/**
+ * hw_ep_enable: enables endpoint (execute without interruption)
+ * @num: endpoint number
+ * @dir: endpoint direction
+ * @type: endpoint type
+ *
+ * This function returns an error code
+ */
+static int hw_ep_enable(struct ci13xxx *udc, int num, int dir, int type)
+{
+ u32 mask, data;
+
+ if (dir) {
+ mask = ENDPTCTRL_TXT; /* type */
+ data = type << ffs_nr(mask);
+
+ mask |= ENDPTCTRL_TXS; /* unstall */
+ mask |= ENDPTCTRL_TXR; /* reset data toggle */
+ data |= ENDPTCTRL_TXR;
+ mask |= ENDPTCTRL_TXE; /* enable */
+ data |= ENDPTCTRL_TXE;
+ } else {
+ mask = ENDPTCTRL_RXT; /* type */
+ data = type << ffs_nr(mask);
+
+ mask |= ENDPTCTRL_RXS; /* unstall */
+ mask |= ENDPTCTRL_RXR; /* reset data toggle */
+ data |= ENDPTCTRL_RXR;
+ mask |= ENDPTCTRL_RXE; /* enable */
+ data |= ENDPTCTRL_RXE;
+ }
+ hw_write(udc, OP_ENDPTCTRL + num, mask, data);
+ return 0;
+}
+
+/**
+ * hw_ep_get_halt: return endpoint halt status
+ * @num: endpoint number
+ * @dir: endpoint direction
+ *
+ * This function returns 1 if endpoint halted
+ */
+static int hw_ep_get_halt(struct ci13xxx *udc, int num, int dir)
+{
+ u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
+
+ return hw_read(udc, OP_ENDPTCTRL + num, mask) ? 1 : 0;
+}
+
+/**
+ * hw_test_and_clear_setup_status: test & clear setup status (execute without
+ * interruption)
+ * @n: endpoint number
+ *
+ * This function returns setup status
+ */
+static int hw_test_and_clear_setup_status(struct ci13xxx *udc, int n)
+{
+ n = ep_to_bit(udc, n);
+ return hw_test_and_clear(udc, OP_ENDPTSETUPSTAT, BIT(n));
+}
+
+/**
+ * hw_ep_prime: primes endpoint (execute without interruption)
+ * @num: endpoint number
+ * @dir: endpoint direction
+ * @is_ctrl: true if control endpoint
+ *
+ * This function returns an error code
+ */
+static int hw_ep_prime(struct ci13xxx *udc, int num, int dir, int is_ctrl)
+{
+ int n = hw_ep_bit(num, dir);
+
+ if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num)))
+ return -EAGAIN;
+
+ hw_write(udc, OP_ENDPTPRIME, BIT(n), BIT(n));
+
+ while (hw_read(udc, OP_ENDPTPRIME, BIT(n)))
+ cpu_relax();
+ if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num)))
+ return -EAGAIN;
+
+ /* status shoult be tested according with manual but it doesn't work */
+ return 0;
+}
+
+/**
+ * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute
+ * without interruption)
+ * @num: endpoint number
+ * @dir: endpoint direction
+ * @value: true => stall, false => unstall
+ *
+ * This function returns an error code
+ */
+static int hw_ep_set_halt(struct ci13xxx *udc, int num, int dir, int value)
+{
+ if (value != 0 && value != 1)
+ return -EINVAL;
+
+ do {
+ enum ci13xxx_regs reg = OP_ENDPTCTRL + num;
+ u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
+ u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR;
+
+ /* data toggle - reserved for EP0 but it's in ESS */
+ hw_write(udc, reg, mask_xs|mask_xr,
+ value ? mask_xs : mask_xr);
+ } while (value != hw_ep_get_halt(udc, num, dir));
+
+ return 0;
+}
+
+/**
+ * hw_is_port_high_speed: test if port is high speed
+ *
+ * This function returns true if high speed port
+ */
+static int hw_port_is_high_speed(struct ci13xxx *udc)
+{
+ return udc->hw_bank.lpm ? hw_read(udc, OP_DEVLC, DEVLC_PSPD) :
+ hw_read(udc, OP_PORTSC, PORTSC_HSP);
+}
+
+/**
+ * hw_read_intr_enable: returns interrupt enable register
+ *
+ * This function returns register data
+ */
+static u32 hw_read_intr_enable(struct ci13xxx *udc)
+{
+ return hw_read(udc, OP_USBINTR, ~0);
+}
+
+/**
+ * hw_read_intr_status: returns interrupt status register
+ *
+ * This function returns register data
+ */
+static u32 hw_read_intr_status(struct ci13xxx *udc)
+{
+ return hw_read(udc, OP_USBSTS, ~0);
+}
+
+/**
+ * hw_test_and_clear_complete: test & clear complete status (execute without
+ * interruption)
+ * @n: endpoint number
+ *
+ * This function returns complete status
+ */
+static int hw_test_and_clear_complete(struct ci13xxx *udc, int n)
+{
+ n = ep_to_bit(udc, n);
+ return hw_test_and_clear(udc, OP_ENDPTCOMPLETE, BIT(n));
+}
+
+/**
+ * hw_test_and_clear_intr_active: test & clear active interrupts (execute
+ * without interruption)
+ *
+ * This function returns active interrutps
+ */
+static u32 hw_test_and_clear_intr_active(struct ci13xxx *udc)
+{
+ u32 reg = hw_read_intr_status(udc) & hw_read_intr_enable(udc);
+
+ hw_write(udc, OP_USBSTS, ~0, reg);
+ return reg;
+}
+
+/**
+ * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
+ * interruption)
+ *
+ * This function returns guard value
+ */
+static int hw_test_and_clear_setup_guard(struct ci13xxx *udc)
+{
+ return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, 0);
+}
+
+/**
+ * hw_test_and_set_setup_guard: test & set setup guard (execute without
+ * interruption)
+ *
+ * This function returns guard value
+ */
+static int hw_test_and_set_setup_guard(struct ci13xxx *udc)
+{
+ return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW);
+}
+
+/**
+ * hw_usb_set_address: configures USB address (execute without interruption)
+ * @value: new USB address
+ *
+ * This function explicitly sets the address, without the "USBADRA" (advance)
+ * feature, which is not supported by older versions of the controller.
+ */
+static void hw_usb_set_address(struct ci13xxx *udc, u8 value)
+{
+ hw_write(udc, OP_DEVICEADDR, DEVICEADDR_USBADR,
+ value << ffs_nr(DEVICEADDR_USBADR));
+}
+
+/**
+ * hw_usb_reset: restart device after a bus reset (execute without
+ * interruption)
+ *
+ * This function returns an error code
+ */
+static int hw_usb_reset(struct ci13xxx *udc)
+{
+ hw_usb_set_address(udc, 0);
+
+ /* ESS flushes only at end?!? */
+ hw_write(udc, OP_ENDPTFLUSH, ~0, ~0);
+
+ /* clear setup token semaphores */
+ hw_write(udc, OP_ENDPTSETUPSTAT, 0, 0);
+
+ /* clear complete status */
+ hw_write(udc, OP_ENDPTCOMPLETE, 0, 0);
+
+ /* wait until all bits cleared */
+ while (hw_read(udc, OP_ENDPTPRIME, ~0))
+ udelay(10); /* not RTOS friendly */
+
+ /* reset all endpoints ? */
+
+ /* reset internal status and wait for further instructions
+ no need to verify the port reset status (ESS does it) */
+
+ return 0;
+}
+
+/******************************************************************************
+ * UTIL block
+ *****************************************************************************/
+/**
+ * _usb_addr: calculates endpoint address from direction & number
+ * @ep: endpoint
+ */
+static inline u8 _usb_addr(struct ci13xxx_ep *ep)
+{
+ return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num;
+}
+
+/**
+ * _hardware_queue: configures a request at hardware level
+ * @gadget: gadget
+ * @mEp: endpoint
+ *
+ * This function returns an error code
+ */
+static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
+{
+ struct ci13xxx *udc = mEp->udc;
+ unsigned i;
+ int ret = 0;
+ unsigned length = mReq->req.length;
+
+ /* don't queue twice */
+ if (mReq->req.status == -EALREADY)
+ return -EALREADY;
+
+ mReq->req.status = -EALREADY;
+
+ if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
+ mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
+ &mReq->zdma);
+ if (mReq->zptr == NULL)
+ return -ENOMEM;
+
+ memset(mReq->zptr, 0, sizeof(*mReq->zptr));
+ mReq->zptr->next = TD_TERMINATE;
+ mReq->zptr->token = TD_STATUS_ACTIVE;
+ if (!mReq->req.no_interrupt)
+ mReq->zptr->token |= TD_IOC;
+ }
+ ret = usb_gadget_map_request(&udc->gadget, &mReq->req, mEp->dir);
+ if (ret)
+ return ret;
+
+ /*
+ * TD configuration
+ * TODO - handle requests which spawns into several TDs
+ */
+ memset(mReq->ptr, 0, sizeof(*mReq->ptr));
+ mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
+ mReq->ptr->token &= TD_TOTAL_BYTES;
+ mReq->ptr->token |= TD_STATUS_ACTIVE;
+ if (mReq->zptr) {
+ mReq->ptr->next = mReq->zdma;
+ } else {
+ mReq->ptr->next = TD_TERMINATE;
+ if (!mReq->req.no_interrupt)
+ mReq->ptr->token |= TD_IOC;
+ }
+ mReq->ptr->page[0] = mReq->req.dma;
+ for (i = 1; i < 5; i++)
+ mReq->ptr->page[i] =
+ (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
+
+ if (!list_empty(&mEp->qh.queue)) {
+ struct ci13xxx_req *mReqPrev;
+ int n = hw_ep_bit(mEp->num, mEp->dir);
+ int tmp_stat;
+
+ mReqPrev = list_entry(mEp->qh.queue.prev,
+ struct ci13xxx_req, queue);
+ if (mReqPrev->zptr)
+ mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
+ else
+ mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
+ wmb();
+ if (hw_read(udc, OP_ENDPTPRIME, BIT(n)))
+ goto done;
+ do {
+ hw_write(udc, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
+ tmp_stat = hw_read(udc, OP_ENDPTSTAT, BIT(n));
+ } while (!hw_read(udc, OP_USBCMD, USBCMD_ATDTW));
+ hw_write(udc, OP_USBCMD, USBCMD_ATDTW, 0);
+ if (tmp_stat)
+ goto done;
+ }
+
+ /* QH configuration */
+ mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
+ mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
+ mEp->qh.ptr->cap |= QH_ZLT;
+
+ wmb(); /* synchronize before ep prime */
+
+ ret = hw_ep_prime(udc, mEp->num, mEp->dir,
+ mEp->type == USB_ENDPOINT_XFER_CONTROL);
+done:
+ return ret;
+}
+
+/**
+ * _hardware_dequeue: handles a request at hardware level
+ * @gadget: gadget
+ * @mEp: endpoint
+ *
+ * This function returns an error code
+ */
+static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
+{
+ if (mReq->req.status != -EALREADY)
+ return -EINVAL;
+
+ if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
+ return -EBUSY;
+
+ if (mReq->zptr) {
+ if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
+ return -EBUSY;
+ dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
+ mReq->zptr = NULL;
+ }
+
+ mReq->req.status = 0;
+
+ usb_gadget_unmap_request(&mEp->udc->gadget, &mReq->req, mEp->dir);
+
+ mReq->req.status = mReq->ptr->token & TD_STATUS;
+ if ((TD_STATUS_HALTED & mReq->req.status) != 0)
+ mReq->req.status = -1;
+ else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
+ mReq->req.status = -1;
+ else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
+ mReq->req.status = -1;
+
+ mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
+ mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
+ mReq->req.actual = mReq->req.length - mReq->req.actual;
+ mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
+
+ return mReq->req.actual;
+}
+
+/**
+ * _ep_nuke: dequeues all endpoint requests
+ * @mEp: endpoint
+ *
+ * This function returns an error code
+ * Caller must hold lock
+ */
+static int _ep_nuke(struct ci13xxx_ep *mEp)
+__releases(mEp->lock)
+__acquires(mEp->lock)
+{
+ if (mEp == NULL)
+ return -EINVAL;
+
+ hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
+
+ while (!list_empty(&mEp->qh.queue)) {
+
+ /* pop oldest request */
+ struct ci13xxx_req *mReq = \
+ list_entry(mEp->qh.queue.next,
+ struct ci13xxx_req, queue);
+ list_del_init(&mReq->queue);
+ mReq->req.status = -ESHUTDOWN;
+
+ if (mReq->req.complete != NULL) {
+ spin_unlock(mEp->lock);
+ mReq->req.complete(&mEp->ep, &mReq->req);
+ spin_lock(mEp->lock);
+ }
+ }
+ return 0;
+}
+
+/**
+ * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
+ * @gadget: gadget
+ *
+ * This function returns an error code
+ */
+static int _gadget_stop_activity(struct usb_gadget *gadget)
+{
+ struct usb_ep *ep;
+ struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
+ unsigned long flags;
+
+ spin_lock_irqsave(&udc->lock, flags);
+ udc->gadget.speed = USB_SPEED_UNKNOWN;
+ udc->remote_wakeup = 0;
+ udc->suspended = 0;
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ /* flush all endpoints */
+ gadget_for_each_ep(ep, gadget) {
+ usb_ep_fifo_flush(ep);
+ }
+ usb_ep_fifo_flush(&udc->ep0out->ep);
+ usb_ep_fifo_flush(&udc->ep0in->ep);
+
+ if (udc->driver)
+ udc->driver->disconnect(gadget);
+
+ /* make sure to disable all endpoints */
+ gadget_for_each_ep(ep, gadget) {
+ usb_ep_disable(ep);
+ }
+
+ if (udc->status != NULL) {
+ usb_ep_free_request(&udc->ep0in->ep, udc->status);
+ udc->status = NULL;
+ }
+
+ return 0;
+}
+
+/******************************************************************************
+ * ISR block
+ *****************************************************************************/
+/**
+ * isr_reset_handler: USB reset interrupt handler
+ * @udc: UDC device
+ *
+ * This function resets USB engine after a bus reset occurred
+ */
+static void isr_reset_handler(struct ci13xxx *udc)
+__releases(udc->lock)
+__acquires(udc->lock)
+{
+ int retval;
+
+ dbg_event(0xFF, "BUS RST", 0);
+
+ spin_unlock(&udc->lock);
+ retval = _gadget_stop_activity(&udc->gadget);
+ if (retval)
+ goto done;
+
+ retval = hw_usb_reset(udc);
+ if (retval)
+ goto done;
+
+ udc->status = usb_ep_alloc_request(&udc->ep0in->ep, GFP_ATOMIC);
+ if (udc->status == NULL)
+ retval = -ENOMEM;
+
+done:
+ spin_lock(&udc->lock);
+
+ if (retval)
+ dev_err(udc->dev, "error: %i\n", retval);
+}
+
+/**
+ * isr_get_status_complete: get_status request complete function
+ * @ep: endpoint
+ * @req: request handled
+ *
+ * Caller must release lock
+ */
+static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ if (ep == NULL || req == NULL)
+ return;
+
+ kfree(req->buf);
+ usb_ep_free_request(ep, req);
+}
+
+/**
+ * isr_get_status_response: get_status request response
+ * @udc: udc struct
+ * @setup: setup request packet
+ *
+ * This function returns an error code
+ */
+static int isr_get_status_response(struct ci13xxx *udc,
+ struct usb_ctrlrequest *setup)
+__releases(mEp->lock)
+__acquires(mEp->lock)
+{
+ struct ci13xxx_ep *mEp = udc->ep0in;
+ struct usb_request *req = NULL;
+ gfp_t gfp_flags = GFP_ATOMIC;
+ int dir, num, retval;
+
+ if (mEp == NULL || setup == NULL)
+ return -EINVAL;
+
+ spin_unlock(mEp->lock);
+ req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
+ spin_lock(mEp->lock);
+ if (req == NULL)
+ return -ENOMEM;
+
+ req->complete = isr_get_status_complete;
+ req->length = 2;
+ req->buf = kzalloc(req->length, gfp_flags);
+ if (req->buf == NULL) {
+ retval = -ENOMEM;
+ goto err_free_req;
+ }
+
+ if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
+ /* Assume that device is bus powered for now. */
+ *(u16 *)req->buf = udc->remote_wakeup << 1;
+ retval = 0;
+ } else if ((setup->bRequestType & USB_RECIP_MASK) \
+ == USB_RECIP_ENDPOINT) {
+ dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
+ TX : RX;
+ num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
+ *(u16 *)req->buf = hw_ep_get_halt(udc, num, dir);
+ }
+ /* else do nothing; reserved for future use */
+
+ spin_unlock(mEp->lock);
+ retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
+ spin_lock(mEp->lock);
+ if (retval)
+ goto err_free_buf;
+
+ return 0;
+
+ err_free_buf:
+ kfree(req->buf);
+ err_free_req:
+ spin_unlock(mEp->lock);
+ usb_ep_free_request(&mEp->ep, req);
+ spin_lock(mEp->lock);
+ return retval;
+}
+
+/**
+ * isr_setup_status_complete: setup_status request complete function
+ * @ep: endpoint
+ * @req: request handled
+ *
+ * Caller must release lock. Put the port in test mode if test mode
+ * feature is selected.
+ */
+static void
+isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct ci13xxx *udc = req->context;
+ unsigned long flags;
+
+ if (udc->setaddr) {
+ hw_usb_set_address(udc, udc->address);
+ udc->setaddr = false;
+ }
+
+ spin_lock_irqsave(&udc->lock, flags);
+ if (udc->test_mode)
+ hw_port_test_set(udc, udc->test_mode);
+ spin_unlock_irqrestore(&udc->lock, flags);
+}
+
+/**
+ * isr_setup_status_phase: queues the status phase of a setup transation
+ * @udc: udc struct
+ *
+ * This function returns an error code
+ */
+static int isr_setup_status_phase(struct ci13xxx *udc)
+__releases(mEp->lock)
+__acquires(mEp->lock)
+{
+ int retval;
+ struct ci13xxx_ep *mEp;
+
+ mEp = (udc->ep0_dir == TX) ? udc->ep0out : udc->ep0in;
+ udc->status->context = udc;
+ udc->status->complete = isr_setup_status_complete;
+
+ spin_unlock(mEp->lock);
+ retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
+ spin_lock(mEp->lock);
+
+ return retval;
+}
+
+/**
+ * isr_tr_complete_low: transaction complete low level handler
+ * @mEp: endpoint
+ *
+ * This function returns an error code
+ * Caller must hold lock
+ */
+static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
+__releases(mEp->lock)
+__acquires(mEp->lock)
+{
+ struct ci13xxx_req *mReq, *mReqTemp;
+ struct ci13xxx_ep *mEpTemp = mEp;
+ int uninitialized_var(retval);
+
+ if (list_empty(&mEp->qh.queue))
+ return -EINVAL;
+
+ list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
+ queue) {
+ retval = _hardware_dequeue(mEp, mReq);
+ if (retval < 0)
+ break;
+ list_del_init(&mReq->queue);
+ dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
+ if (mReq->req.complete != NULL) {
+ spin_unlock(mEp->lock);
+ if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
+ mReq->req.length)
+ mEpTemp = mEp->udc->ep0in;
+ mReq->req.complete(&mEpTemp->ep, &mReq->req);
+ spin_lock(mEp->lock);
+ }
+ }
+
+ if (retval == -EBUSY)
+ retval = 0;
+ if (retval < 0)
+ dbg_event(_usb_addr(mEp), "DONE", retval);
+
+ return retval;
+}
+
+/**
+ * isr_tr_complete_handler: transaction complete interrupt handler
+ * @udc: UDC descriptor
+ *
+ * This function handles traffic events
+ */
+static void isr_tr_complete_handler(struct ci13xxx *udc)
+__releases(udc->lock)
+__acquires(udc->lock)
+{
+ unsigned i;
+ u8 tmode = 0;
+
+ for (i = 0; i < udc->hw_ep_max; i++) {
+ struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
+ int type, num, dir, err = -EINVAL;
+ struct usb_ctrlrequest req;
+
+ if (mEp->ep.desc == NULL)
+ continue; /* not configured */
+
+ if (hw_test_and_clear_complete(udc, i)) {
+ err = isr_tr_complete_low(mEp);
+ if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
+ if (err > 0) /* needs status phase */
+ err = isr_setup_status_phase(udc);
+ if (err < 0) {
+ dbg_event(_usb_addr(mEp),
+ "ERROR", err);
+ spin_unlock(&udc->lock);
+ if (usb_ep_set_halt(&mEp->ep))
+ dev_err(udc->dev,
+ "error: ep_set_halt\n");
+ spin_lock(&udc->lock);
+ }
+ }
+ }
+
+ if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
+ !hw_test_and_clear_setup_status(udc, i))
+ continue;
+
+ if (i != 0) {
+ dev_warn(udc->dev, "ctrl traffic at endpoint %d\n", i);
+ continue;
+ }
+
+ /*
+ * Flush data and handshake transactions of previous
+ * setup packet.
+ */
+ _ep_nuke(udc->ep0out);
+ _ep_nuke(udc->ep0in);
+
+ /* read_setup_packet */
+ do {
+ hw_test_and_set_setup_guard(udc);
+ memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
+ } while (!hw_test_and_clear_setup_guard(udc));
+
+ type = req.bRequestType;
+
+ udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
+
+ dbg_setup(_usb_addr(mEp), &req);
+
+ switch (req.bRequest) {
+ case USB_REQ_CLEAR_FEATURE:
+ if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
+ le16_to_cpu(req.wValue) ==
+ USB_ENDPOINT_HALT) {
+ if (req.wLength != 0)
+ break;
+ num = le16_to_cpu(req.wIndex);
+ dir = num & USB_ENDPOINT_DIR_MASK;
+ num &= USB_ENDPOINT_NUMBER_MASK;
+ if (dir) /* TX */
+ num += udc->hw_ep_max/2;
+ if (!udc->ci13xxx_ep[num].wedge) {
+ spin_unlock(&udc->lock);
+ err = usb_ep_clear_halt(
+ &udc->ci13xxx_ep[num].ep);
+ spin_lock(&udc->lock);
+ if (err)
+ break;
+ }
+ err = isr_setup_status_phase(udc);
+ } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
+ le16_to_cpu(req.wValue) ==
+ USB_DEVICE_REMOTE_WAKEUP) {
+ if (req.wLength != 0)
+ break;
+ udc->remote_wakeup = 0;
+ err = isr_setup_status_phase(udc);
+ } else {
+ goto delegate;
+ }
+ break;
+ case USB_REQ_GET_STATUS:
+ if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
+ type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
+ type != (USB_DIR_IN|USB_RECIP_INTERFACE))
+ goto delegate;
+ if (le16_to_cpu(req.wLength) != 2 ||
+ le16_to_cpu(req.wValue) != 0)
+ break;
+ err = isr_get_status_response(udc, &req);
+ break;
+ case USB_REQ_SET_ADDRESS:
+ if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
+ goto delegate;
+ if (le16_to_cpu(req.wLength) != 0 ||
+ le16_to_cpu(req.wIndex) != 0)
+ break;
+ udc->address = (u8)le16_to_cpu(req.wValue);
+ udc->setaddr = true;
+ err = isr_setup_status_phase(udc);
+ break;
+ case USB_REQ_SET_FEATURE:
+ if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
+ le16_to_cpu(req.wValue) ==
+ USB_ENDPOINT_HALT) {
+ if (req.wLength != 0)
+ break;
+ num = le16_to_cpu(req.wIndex);
+ dir = num & USB_ENDPOINT_DIR_MASK;
+ num &= USB_ENDPOINT_NUMBER_MASK;
+ if (dir) /* TX */
+ num += udc->hw_ep_max/2;
+
+ spin_unlock(&udc->lock);
+ err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
+ spin_lock(&udc->lock);
+ if (!err)
+ isr_setup_status_phase(udc);
+ } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
+ if (req.wLength != 0)
+ break;
+ switch (le16_to_cpu(req.wValue)) {
+ case USB_DEVICE_REMOTE_WAKEUP:
+ udc->remote_wakeup = 1;
+ err = isr_setup_status_phase(udc);
+ break;
+ case USB_DEVICE_TEST_MODE:
+ tmode = le16_to_cpu(req.wIndex) >> 8;
+ switch (tmode) {
+ case TEST_J:
+ case TEST_K:
+ case TEST_SE0_NAK:
+ case TEST_PACKET:
+ case TEST_FORCE_EN:
+ udc->test_mode = tmode;
+ err = isr_setup_status_phase(
+ udc);
+ break;
+ default:
+ break;
+ }
+ default:
+ goto delegate;
+ }
+ } else {
+ goto delegate;
+ }
+ break;
+ default:
+delegate:
+ if (req.wLength == 0) /* no data phase */
+ udc->ep0_dir = TX;
+
+ spin_unlock(&udc->lock);
+ err = udc->driver->setup(&udc->gadget, &req);
+ spin_lock(&udc->lock);
+ break;
+ }
+
+ if (err < 0) {
+ dbg_event(_usb_addr(mEp), "ERROR", err);
+
+ spin_unlock(&udc->lock);
+ if (usb_ep_set_halt(&mEp->ep))
+ dev_err(udc->dev, "error: ep_set_halt\n");
+ spin_lock(&udc->lock);
+ }
+ }
+}
+
+/******************************************************************************
+ * ENDPT block
+ *****************************************************************************/
+/**
+ * ep_enable: configure endpoint, making it usable
+ *
+ * Check usb_ep_enable() at "usb_gadget.h" for details
+ */
+static int ep_enable(struct usb_ep *ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
+ int retval = 0;
+ unsigned long flags;
+
+ if (ep == NULL || desc == NULL)
+ return -EINVAL;
+
+ spin_lock_irqsave(mEp->lock, flags);
+
+ /* only internal SW should enable ctrl endpts */
+
+ mEp->ep.desc = desc;
+
+ if (!list_empty(&mEp->qh.queue))
+ dev_warn(mEp->udc->dev, "enabling a non-empty endpoint!\n");
+
+ mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
+ mEp->num = usb_endpoint_num(desc);
+ mEp->type = usb_endpoint_type(desc);
+
+ mEp->ep.maxpacket = usb_endpoint_maxp(desc);
+
+ dbg_event(_usb_addr(mEp), "ENABLE", 0);
+
+ mEp->qh.ptr->cap = 0;
+
+ if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
+ mEp->qh.ptr->cap |= QH_IOS;
+ else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
+ mEp->qh.ptr->cap &= ~QH_MULT;
+ else
+ mEp->qh.ptr->cap &= ~QH_ZLT;
+
+ mEp->qh.ptr->cap |=
+ (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
+ mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
+
+ /*
+ * Enable endpoints in the HW other than ep0 as ep0
+ * is always enabled
+ */
+ if (mEp->num)
+ retval |= hw_ep_enable(mEp->udc, mEp->num, mEp->dir, mEp->type);
+
+ spin_unlock_irqrestore(mEp->lock, flags);
+ return retval;
+}
+
+/**
+ * ep_disable: endpoint is no longer usable
+ *
+ * Check usb_ep_disable() at "usb_gadget.h" for details
+ */
+static int ep_disable(struct usb_ep *ep)
+{
+ struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
+ int direction, retval = 0;
+ unsigned long flags;
+
+ if (ep == NULL)
+ return -EINVAL;
+ else if (mEp->ep.desc == NULL)
+ return -EBUSY;
+
+ spin_lock_irqsave(mEp->lock, flags);
+
+ /* only internal SW should disable ctrl endpts */
+
+ direction = mEp->dir;
+ do {
+ dbg_event(_usb_addr(mEp), "DISABLE", 0);
+
+ retval |= _ep_nuke(mEp);
+ retval |= hw_ep_disable(mEp->udc, mEp->num, mEp->dir);
+
+ if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
+ mEp->dir = (mEp->dir == TX) ? RX : TX;
+
+ } while (mEp->dir != direction);
+
+ mEp->ep.desc = NULL;
+
+ spin_unlock_irqrestore(mEp->lock, flags);
+ return retval;
+}
+
+/**
+ * ep_alloc_request: allocate a request object to use with this endpoint
+ *
+ * Check usb_ep_alloc_request() at "usb_gadget.h" for details
+ */
+static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
+{
+ struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
+ struct ci13xxx_req *mReq = NULL;
+
+ if (ep == NULL)
+ return NULL;
+
+ mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
+ if (mReq != NULL) {
+ INIT_LIST_HEAD(&mReq->queue);
+
+ mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
+ &mReq->dma);
+ if (mReq->ptr == NULL) {
+ kfree(mReq);
+ mReq = NULL;
+ }
+ }
+
+ dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
+
+ return (mReq == NULL) ? NULL : &mReq->req;
+}
+
+/**
+ * ep_free_request: frees a request object
+ *
+ * Check usb_ep_free_request() at "usb_gadget.h" for details
+ */
+static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
+{
+ struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
+ struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
+ unsigned long flags;
+
+ if (ep == NULL || req == NULL) {
+ return;
+ } else if (!list_empty(&mReq->queue)) {
+ dev_err(mEp->udc->dev, "freeing queued request\n");
+ return;
+ }
+
+ spin_lock_irqsave(mEp->lock, flags);
+
+ if (mReq->ptr)
+ dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
+ kfree(mReq);
+
+ dbg_event(_usb_addr(mEp), "FREE", 0);
+
+ spin_unlock_irqrestore(mEp->lock, flags);
+}
+
+/**
+ * ep_queue: queues (submits) an I/O request to an endpoint
+ *
+ * Check usb_ep_queue()* at usb_gadget.h" for details
+ */
+static int ep_queue(struct usb_ep *ep, struct usb_request *req,
+ gfp_t __maybe_unused gfp_flags)
+{
+ struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
+ struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
+ struct ci13xxx *udc = mEp->udc;
+ int retval = 0;
+ unsigned long flags;
+
+ if (ep == NULL || req == NULL || mEp->ep.desc == NULL)
+ return -EINVAL;
+
+ spin_lock_irqsave(mEp->lock, flags);
+
+ if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
+ if (req->length)
+ mEp = (udc->ep0_dir == RX) ?
+ udc->ep0out : udc->ep0in;
+ if (!list_empty(&mEp->qh.queue)) {
+ _ep_nuke(mEp);
+ retval = -EOVERFLOW;
+ dev_warn(mEp->udc->dev, "endpoint ctrl %X nuked\n",
+ _usb_addr(mEp));
+ }
+ }
+
+ /* first nuke then test link, e.g. previous status has not sent */
+ if (!list_empty(&mReq->queue)) {
+ retval = -EBUSY;
+ dev_err(mEp->udc->dev, "request already in queue\n");
+ goto done;
+ }
+
+ if (req->length > 4 * CI13XXX_PAGE_SIZE) {
+ req->length = 4 * CI13XXX_PAGE_SIZE;
+ retval = -EMSGSIZE;
+ dev_warn(mEp->udc->dev, "request length truncated\n");
+ }
+
+ dbg_queue(_usb_addr(mEp), req, retval);
+
+ /* push request */
+ mReq->req.status = -EINPROGRESS;
+ mReq->req.actual = 0;
+
+ retval = _hardware_enqueue(mEp, mReq);
+
+ if (retval == -EALREADY) {
+ dbg_event(_usb_addr(mEp), "QUEUE", retval);
+ retval = 0;
+ }
+ if (!retval)
+ list_add_tail(&mReq->queue, &mEp->qh.queue);
+
+ done:
+ spin_unlock_irqrestore(mEp->lock, flags);
+ return retval;
+}
+
+/**
+ * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
+ *
+ * Check usb_ep_dequeue() at "usb_gadget.h" for details
+ */
+static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
+{
+ struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
+ struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
+ unsigned long flags;
+
+ if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
+ mEp->ep.desc == NULL || list_empty(&mReq->queue) ||
+ list_empty(&mEp->qh.queue))
+ return -EINVAL;
+
+ spin_lock_irqsave(mEp->lock, flags);
+
+ dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
+
+ hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
+
+ /* pop request */
+ list_del_init(&mReq->queue);
+
+ usb_gadget_unmap_request(&mEp->udc->gadget, req, mEp->dir);
+
+ req->status = -ECONNRESET;
+
+ if (mReq->req.complete != NULL) {
+ spin_unlock(mEp->lock);
+ mReq->req.complete(&mEp->ep, &mReq->req);
+ spin_lock(mEp->lock);
+ }
+
+ spin_unlock_irqrestore(mEp->lock, flags);
+ return 0;
+}
+
+/**
+ * ep_set_halt: sets the endpoint halt feature
+ *
+ * Check usb_ep_set_halt() at "usb_gadget.h" for details
+ */
+static int ep_set_halt(struct usb_ep *ep, int value)
+{
+ struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
+ int direction, retval = 0;
+ unsigned long flags;
+
+ if (ep == NULL || mEp->ep.desc == NULL)
+ return -EINVAL;
+
+ spin_lock_irqsave(mEp->lock, flags);
+
+#ifndef STALL_IN
+ /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
+ if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
+ !list_empty(&mEp->qh.queue)) {
+ spin_unlock_irqrestore(mEp->lock, flags);
+ return -EAGAIN;
+ }
+#endif
+
+ direction = mEp->dir;
+ do {
+ dbg_event(_usb_addr(mEp), "HALT", value);
+ retval |= hw_ep_set_halt(mEp->udc, mEp->num, mEp->dir, value);
+
+ if (!value)
+ mEp->wedge = 0;
+
+ if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
+ mEp->dir = (mEp->dir == TX) ? RX : TX;
+
+ } while (mEp->dir != direction);
+
+ spin_unlock_irqrestore(mEp->lock, flags);
+ return retval;
+}
+
+/**
+ * ep_set_wedge: sets the halt feature and ignores clear requests
+ *
+ * Check usb_ep_set_wedge() at "usb_gadget.h" for details
+ */
+static int ep_set_wedge(struct usb_ep *ep)
+{
+ struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
+ unsigned long flags;
+
+ if (ep == NULL || mEp->ep.desc == NULL)
+ return -EINVAL;
+
+ spin_lock_irqsave(mEp->lock, flags);
+
+ dbg_event(_usb_addr(mEp), "WEDGE", 0);
+ mEp->wedge = 1;
+
+ spin_unlock_irqrestore(mEp->lock, flags);
+
+ return usb_ep_set_halt(ep);
+}
+
+/**
+ * ep_fifo_flush: flushes contents of a fifo
+ *
+ * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
+ */
+static void ep_fifo_flush(struct usb_ep *ep)
+{
+ struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
+ unsigned long flags;
+
+ if (ep == NULL) {
+ dev_err(mEp->udc->dev, "%02X: -EINVAL\n", _usb_addr(mEp));
+ return;
+ }
+
+ spin_lock_irqsave(mEp->lock, flags);
+
+ dbg_event(_usb_addr(mEp), "FFLUSH", 0);
+ hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
+
+ spin_unlock_irqrestore(mEp->lock, flags);
+}
+
+/**
+ * Endpoint-specific part of the API to the USB controller hardware
+ * Check "usb_gadget.h" for details
+ */
+static const struct usb_ep_ops usb_ep_ops = {
+ .enable = ep_enable,
+ .disable = ep_disable,
+ .alloc_request = ep_alloc_request,
+ .free_request = ep_free_request,
+ .queue = ep_queue,
+ .dequeue = ep_dequeue,
+ .set_halt = ep_set_halt,
+ .set_wedge = ep_set_wedge,
+ .fifo_flush = ep_fifo_flush,
+};
+
+/******************************************************************************
+ * GADGET block
+ *****************************************************************************/
+static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
+{
+ struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+ unsigned long flags;
+ int gadget_ready = 0;
+
+ if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
+ return -EOPNOTSUPP;
+
+ spin_lock_irqsave(&udc->lock, flags);
+ udc->vbus_active = is_active;
+ if (udc->driver)
+ gadget_ready = 1;
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ if (gadget_ready) {
+ if (is_active) {
+ pm_runtime_get_sync(&_gadget->dev);
+ hw_device_reset(udc, USBMODE_CM_DC);
+ hw_device_state(udc, udc->ep0out->qh.dma);
+ } else {
+ hw_device_state(udc, 0);
+ if (udc->udc_driver->notify_event)
+ udc->udc_driver->notify_event(udc,
+ CI13XXX_CONTROLLER_STOPPED_EVENT);
+ _gadget_stop_activity(&udc->gadget);
+ pm_runtime_put_sync(&_gadget->dev);
+ }
+ }
+
+ return 0;
+}
+
+static int ci13xxx_wakeup(struct usb_gadget *_gadget)
+{
+ struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&udc->lock, flags);
+ if (!udc->remote_wakeup) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+ if (!hw_read(udc, OP_PORTSC, PORTSC_SUSP)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ hw_write(udc, OP_PORTSC, PORTSC_FPR, PORTSC_FPR);
+out:
+ spin_unlock_irqrestore(&udc->lock, flags);
+ return ret;
+}
+
+static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
+{
+ struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+
+ if (udc->transceiver)
+ return usb_phy_set_power(udc->transceiver, mA);
+ return -ENOTSUPP;
+}
+
+static int ci13xxx_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver);
+static int ci13xxx_stop(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver);
+/**
+ * Device operations part of the API to the USB controller hardware,
+ * which don't involve endpoints (or i/o)
+ * Check "usb_gadget.h" for details
+ */
+static const struct usb_gadget_ops usb_gadget_ops = {
+ .vbus_session = ci13xxx_vbus_session,
+ .wakeup = ci13xxx_wakeup,
+ .vbus_draw = ci13xxx_vbus_draw,
+ .udc_start = ci13xxx_start,
+ .udc_stop = ci13xxx_stop,
+};
+
+static int init_eps(struct ci13xxx *udc)
+{
+ int retval = 0, i, j;
+
+ for (i = 0; i < udc->hw_ep_max/2; i++)
+ for (j = RX; j <= TX; j++) {
+ int k = i + j * udc->hw_ep_max/2;
+ struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
+
+ scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
+ (j == TX) ? "in" : "out");
+
+ mEp->udc = udc;
+ mEp->lock = &udc->lock;
+ mEp->td_pool = udc->td_pool;
+
+ mEp->ep.name = mEp->name;
+ mEp->ep.ops = &usb_ep_ops;
+ mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
+
+ INIT_LIST_HEAD(&mEp->qh.queue);
+ mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
+ &mEp->qh.dma);
+ if (mEp->qh.ptr == NULL)
+ retval = -ENOMEM;
+ else
+ memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
+
+ /*
+ * set up shorthands for ep0 out and in endpoints,
+ * don't add to gadget's ep_list
+ */
+ if (i == 0) {
+ if (j == RX)
+ udc->ep0out = mEp;
+ else
+ udc->ep0in = mEp;
+
+ continue;
+ }
+
+ list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
+ }
+
+ return retval;
+}
+
+/**
+ * ci13xxx_start: register a gadget driver
+ * @gadget: our gadget
+ * @driver: the driver being registered
+ *
+ * Interrupts are enabled here.
+ */
+static int ci13xxx_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
+{
+ struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
+ unsigned long flags;
+ int retval = -ENOMEM;
+
+ if (driver->disconnect == NULL)
+ return -EINVAL;
+
+
+ udc->ep0out->ep.desc = &ctrl_endpt_out_desc;
+ retval = usb_ep_enable(&udc->ep0out->ep);
+ if (retval)
+ return retval;
+
+ udc->ep0in->ep.desc = &ctrl_endpt_in_desc;
+ retval = usb_ep_enable(&udc->ep0in->ep);
+ if (retval)
+ return retval;
+ spin_lock_irqsave(&udc->lock, flags);
+
+ udc->driver = driver;
+ pm_runtime_get_sync(&udc->gadget.dev);
+ if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
+ if (udc->vbus_active) {
+ if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
+ hw_device_reset(udc, USBMODE_CM_DC);
+ } else {
+ pm_runtime_put_sync(&udc->gadget.dev);
+ goto done;
+ }
+ }
+
+ retval = hw_device_state(udc, udc->ep0out->qh.dma);
+ if (retval)
+ pm_runtime_put_sync(&udc->gadget.dev);
+
+ done:
+ spin_unlock_irqrestore(&udc->lock, flags);
+ return retval;
+}
+
+/**
+ * ci13xxx_stop: unregister a gadget driver
+ */
+static int ci13xxx_stop(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
+{
+ struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
+ unsigned long flags;
+
+ spin_lock_irqsave(&udc->lock, flags);
+
+ if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
+ udc->vbus_active) {
+ hw_device_state(udc, 0);
+ if (udc->udc_driver->notify_event)
+ udc->udc_driver->notify_event(udc,
+ CI13XXX_CONTROLLER_STOPPED_EVENT);
+ udc->driver = NULL;
+ spin_unlock_irqrestore(&udc->lock, flags);
+ _gadget_stop_activity(&udc->gadget);
+ spin_lock_irqsave(&udc->lock, flags);
+ pm_runtime_put(&udc->gadget.dev);
+ }
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ return 0;
+}
+
+/******************************************************************************
+ * BUS block
+ *****************************************************************************/
+/**
+ * udc_irq: udc interrupt handler
+ *
+ * This function returns IRQ_HANDLED if the IRQ has been handled
+ * It locks access to registers
+ */
+static irqreturn_t udc_irq(struct ci13xxx *udc)
+{
+ irqreturn_t retval;
+ u32 intr;
+
+ if (udc == NULL)
+ return IRQ_HANDLED;
+
+ spin_lock(&udc->lock);
+
+ if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
+ if (hw_read(udc, OP_USBMODE, USBMODE_CM) !=
+ USBMODE_CM_DC) {
+ spin_unlock(&udc->lock);
+ return IRQ_NONE;
+ }
+ }
+ intr = hw_test_and_clear_intr_active(udc);
+ dbg_interrupt(intr);
+
+ if (intr) {
+ /* order defines priority - do NOT change it */
+ if (USBi_URI & intr)
+ isr_reset_handler(udc);
+
+ if (USBi_PCI & intr) {
+ udc->gadget.speed = hw_port_is_high_speed(udc) ?
+ USB_SPEED_HIGH : USB_SPEED_FULL;
+ if (udc->suspended && udc->driver->resume) {
+ spin_unlock(&udc->lock);
+ udc->driver->resume(&udc->gadget);
+ spin_lock(&udc->lock);
+ udc->suspended = 0;
+ }
+ }
+
+ if (USBi_UI & intr)
+ isr_tr_complete_handler(udc);
+
+ if (USBi_SLI & intr) {
+ if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
+ udc->driver->suspend) {
+ udc->suspended = 1;
+ spin_unlock(&udc->lock);
+ udc->driver->suspend(&udc->gadget);
+ spin_lock(&udc->lock);
+ }
+ }
+ retval = IRQ_HANDLED;
+ } else {
+ retval = IRQ_NONE;
+ }
+ spin_unlock(&udc->lock);
+
+ return retval;
+}
+
+/**
+ * udc_release: driver release function
+ * @dev: device
+ *
+ * Currently does nothing
+ */
+static void udc_release(struct device *dev)
+{
+}
+
+/**
+ * udc_start: initialize gadget role
+ * @udc: chipidea controller
+ */
+static int udc_start(struct ci13xxx *udc)
+{
+ struct device *dev = udc->dev;
+ int retval = 0;
+
+ if (!udc)
+ return -EINVAL;
+
+ spin_lock_init(&udc->lock);
+
+ udc->gadget.ops = &usb_gadget_ops;
+ udc->gadget.speed = USB_SPEED_UNKNOWN;
+ udc->gadget.max_speed = USB_SPEED_HIGH;
+ udc->gadget.is_otg = 0;
+ udc->gadget.name = udc->udc_driver->name;
+
+ INIT_LIST_HEAD(&udc->gadget.ep_list);
+
+ dev_set_name(&udc->gadget.dev, "gadget");
+ udc->gadget.dev.dma_mask = dev->dma_mask;
+ udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
+ udc->gadget.dev.parent = dev;
+ udc->gadget.dev.release = udc_release;
+
+ /* alloc resources */
+ udc->qh_pool = dma_pool_create("ci13xxx_qh", dev,
+ sizeof(struct ci13xxx_qh),
+ 64, CI13XXX_PAGE_SIZE);
+ if (udc->qh_pool == NULL)
+ return -ENOMEM;
+
+ udc->td_pool = dma_pool_create("ci13xxx_td", dev,
+ sizeof(struct ci13xxx_td),
+ 64, CI13XXX_PAGE_SIZE);
+ if (udc->td_pool == NULL) {
+ retval = -ENOMEM;
+ goto free_qh_pool;
+ }
+
+ retval = init_eps(udc);
+ if (retval)
+ goto free_pools;
+
+ udc->gadget.ep0 = &udc->ep0in->ep;
+
+ udc->transceiver = usb_get_transceiver();
+
+ if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
+ if (udc->transceiver == NULL) {
+ retval = -ENODEV;
+ goto free_pools;
+ }
+ }
+
+ if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
+ retval = hw_device_reset(udc, USBMODE_CM_DC);
+ if (retval)
+ goto put_transceiver;
+ }
+
+ retval = device_register(&udc->gadget.dev);
+ if (retval) {
+ put_device(&udc->gadget.dev);
+ goto put_transceiver;
+ }
+
+ retval = dbg_create_files(&udc->gadget.dev);
+ if (retval)
+ goto unreg_device;
+
+ if (udc->transceiver) {
+ retval = otg_set_peripheral(udc->transceiver->otg,
+ &udc->gadget);
+ if (retval)
+ goto remove_dbg;
+ }
+
+ retval = usb_add_gadget_udc(dev, &udc->gadget);
+ if (retval)
+ goto remove_trans;
+
+ pm_runtime_no_callbacks(&udc->gadget.dev);
+ pm_runtime_enable(&udc->gadget.dev);
+
+ return retval;
+
+remove_trans:
+ if (udc->transceiver) {
+ otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
+ usb_put_transceiver(udc->transceiver);
+ }
+
+ dev_err(dev, "error = %i\n", retval);
+remove_dbg:
+ dbg_remove_files(&udc->gadget.dev);
+unreg_device:
+ device_unregister(&udc->gadget.dev);
+put_transceiver:
+ if (udc->transceiver)
+ usb_put_transceiver(udc->transceiver);
+free_pools:
+ dma_pool_destroy(udc->td_pool);
+free_qh_pool:
+ dma_pool_destroy(udc->qh_pool);
+ return retval;
+}
+
+/**
+ * udc_remove: parent remove must call this to remove UDC
+ *
+ * No interrupts active, the IRQ has been released
+ */
+static void udc_stop(struct ci13xxx *udc)
+{
+ int i;
+
+ if (udc == NULL)
+ return;
+
+ usb_del_gadget_udc(&udc->gadget);
+
+ for (i = 0; i < udc->hw_ep_max; i++) {
+ struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
+
+ dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
+ }
+
+ dma_pool_destroy(udc->td_pool);
+ dma_pool_destroy(udc->qh_pool);
+
+ if (udc->transceiver) {
+ otg_set_peripheral(udc->transceiver->otg, NULL);
+ usb_put_transceiver(udc->transceiver);
+ }
+ dbg_remove_files(&udc->gadget.dev);
+ device_unregister(&udc->gadget.dev);
+ /* my kobject is dynamic, I swear! */
+ memset(&udc->gadget, 0, sizeof(udc->gadget));
+}
+
+/**
+ * ci_hdrc_gadget_init - initialize device related bits
+ * ci: the controller
+ *
+ * This function enables the gadget role, if the device is "device capable".
+ */
+int ci_hdrc_gadget_init(struct ci13xxx *ci)
+{
+ struct ci_role_driver *rdrv;
+
+ if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DC))
+ return -ENXIO;
+
+ rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL);
+ if (!rdrv)
+ return -ENOMEM;
+
+ rdrv->start = udc_start;
+ rdrv->stop = udc_stop;
+ rdrv->irq = udc_irq;
+ rdrv->name = "gadget";
+ ci->roles[CI_ROLE_GADGET] = rdrv;
+
+ return 0;
+}
diff --git a/drivers/usb/chipidea/udc.h b/drivers/usb/chipidea/udc.h
new file mode 100644
index 000000000000..4ff2384d7ca8
--- /dev/null
+++ b/drivers/usb/chipidea/udc.h
@@ -0,0 +1,93 @@
+/*
+ * udc.h - ChipIdea UDC structures
+ *
+ * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
+ *
+ * Author: David Lopo
+ *
+ * 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 __DRIVERS_USB_CHIPIDEA_UDC_H
+#define __DRIVERS_USB_CHIPIDEA_UDC_H
+
+#include <linux/list.h>
+
+#define CTRL_PAYLOAD_MAX 64
+#define RX 0 /* similar to USB_DIR_OUT but can be used as an index */
+#define TX 1 /* similar to USB_DIR_IN but can be used as an index */
+
+/* DMA layout of transfer descriptors */
+struct ci13xxx_td {
+ /* 0 */
+ u32 next;
+#define TD_TERMINATE BIT(0)
+#define TD_ADDR_MASK (0xFFFFFFEUL << 5)
+ /* 1 */
+ u32 token;
+#define TD_STATUS (0x00FFUL << 0)
+#define TD_STATUS_TR_ERR BIT(3)
+#define TD_STATUS_DT_ERR BIT(5)
+#define TD_STATUS_HALTED BIT(6)
+#define TD_STATUS_ACTIVE BIT(7)
+#define TD_MULTO (0x0003UL << 10)
+#define TD_IOC BIT(15)
+#define TD_TOTAL_BYTES (0x7FFFUL << 16)
+ /* 2 */
+ u32 page[5];
+#define TD_CURR_OFFSET (0x0FFFUL << 0)
+#define TD_FRAME_NUM (0x07FFUL << 0)
+#define TD_RESERVED_MASK (0x0FFFUL << 0)
+} __attribute__ ((packed));
+
+/* DMA layout of queue heads */
+struct ci13xxx_qh {
+ /* 0 */
+ u32 cap;
+#define QH_IOS BIT(15)
+#define QH_MAX_PKT (0x07FFUL << 16)
+#define QH_ZLT BIT(29)
+#define QH_MULT (0x0003UL << 30)
+ /* 1 */
+ u32 curr;
+ /* 2 - 8 */
+ struct ci13xxx_td td;
+ /* 9 */
+ u32 RESERVED;
+ struct usb_ctrlrequest setup;
+} __attribute__ ((packed));
+
+/**
+ * struct ci13xxx_req - usb request representation
+ * @req: request structure for gadget drivers
+ * @queue: link to QH list
+ * @ptr: transfer descriptor for this request
+ * @dma: dma address for the transfer descriptor
+ * @zptr: transfer descriptor for the zero packet
+ * @zdma: dma address of the zero packet's transfer descriptor
+ */
+struct ci13xxx_req {
+ struct usb_request req;
+ struct list_head queue;
+ struct ci13xxx_td *ptr;
+ dma_addr_t dma;
+ struct ci13xxx_td *zptr;
+ dma_addr_t zdma;
+};
+
+#ifdef CONFIG_USB_CHIPIDEA_UDC
+
+int ci_hdrc_gadget_init(struct ci13xxx *ci);
+
+#else
+
+static inline int ci_hdrc_gadget_init(struct ci13xxx *ci)
+{
+ return -ENXIO;
+}
+
+#endif
+
+#endif /* __DRIVERS_USB_CHIPIDEA_UDC_H */
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index b32ccb461019..f2a120eea9d4 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1664,6 +1664,7 @@ static struct usb_driver acm_driver = {
#ifdef CONFIG_PM
.supports_autosuspend = 1,
#endif
+ .disable_hub_initiated_lpm = 1,
};
/*
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 0bb2b3248dad..ea8b304f0e85 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -309,9 +309,6 @@ static void free_urbs(struct wdm_device *desc)
static void cleanup(struct wdm_device *desc)
{
- spin_lock(&wdm_device_list_lock);
- list_del(&desc->device_list);
- spin_unlock(&wdm_device_list_lock);
kfree(desc->sbuf);
kfree(desc->inbuf);
kfree(desc->orq);
@@ -369,6 +366,7 @@ static ssize_t wdm_write
r = usb_autopm_get_interface(desc->intf);
if (r < 0) {
kfree(buf);
+ rv = usb_translate_errors(r);
goto outnp;
}
@@ -384,6 +382,7 @@ static ssize_t wdm_write
if (r < 0) {
kfree(buf);
+ rv = r;
goto out;
}
@@ -415,6 +414,7 @@ static ssize_t wdm_write
desc->outbuf = NULL;
clear_bit(WDM_IN_USE, &desc->flags);
dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv);
+ rv = usb_translate_errors(rv);
} else {
dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d",
req->wIndex);
@@ -530,11 +530,13 @@ static int wdm_flush(struct file *file, fl_owner_t id)
struct wdm_device *desc = file->private_data;
wait_event(desc->wait, !test_bit(WDM_IN_USE, &desc->flags));
- if (desc->werr < 0)
+
+ /* cannot dereference desc->intf if WDM_DISCONNECTING */
+ if (desc->werr < 0 && !test_bit(WDM_DISCONNECTING, &desc->flags))
dev_err(&desc->intf->dev, "Error in flush path: %d\n",
desc->werr);
- return desc->werr;
+ return usb_translate_errors(desc->werr);
}
static unsigned int wdm_poll(struct file *file, struct poll_table_struct *wait)
@@ -545,7 +547,7 @@ static unsigned int wdm_poll(struct file *file, struct poll_table_struct *wait)
spin_lock_irqsave(&desc->iuspin, flags);
if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
- mask = POLLERR;
+ mask = POLLHUP | POLLERR;
spin_unlock_irqrestore(&desc->iuspin, flags);
goto desc_out;
}
@@ -596,6 +598,7 @@ static int wdm_open(struct inode *inode, struct file *file)
desc->count--;
dev_err(&desc->intf->dev,
"Error submitting int urb - %d\n", rv);
+ rv = usb_translate_errors(rv);
}
} else {
rv = 0;
@@ -621,10 +624,15 @@ static int wdm_release(struct inode *inode, struct file *file)
mutex_unlock(&desc->wlock);
if (!desc->count) {
- dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
- kill_urbs(desc);
- if (!test_bit(WDM_DISCONNECTING, &desc->flags))
+ if (!test_bit(WDM_DISCONNECTING, &desc->flags)) {
+ dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
+ kill_urbs(desc);
desc->manage_power(desc->intf, 0);
+ } else {
+ /* must avoid dev_printk here as desc->intf is invalid */
+ pr_debug(KBUILD_MODNAME " %s: device gone - cleaning up\n", __func__);
+ cleanup(desc);
+ }
}
mutex_unlock(&wdm_mutex);
return 0;
@@ -771,6 +779,9 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor
out:
return rv;
err:
+ spin_lock(&wdm_device_list_lock);
+ list_del(&desc->device_list);
+ spin_unlock(&wdm_device_list_lock);
cleanup(desc);
return rv;
}
@@ -896,8 +907,16 @@ static void wdm_disconnect(struct usb_interface *intf)
cancel_work_sync(&desc->rxwork);
mutex_unlock(&desc->wlock);
mutex_unlock(&desc->rlock);
+
+ /* the desc->intf pointer used as list key is now invalid */
+ spin_lock(&wdm_device_list_lock);
+ list_del(&desc->device_list);
+ spin_unlock(&wdm_device_list_lock);
+
if (!desc->count)
cleanup(desc);
+ else
+ dev_dbg(&intf->dev, "%s: %d open files - postponing cleanup\n", __func__, desc->count);
mutex_unlock(&wdm_mutex);
}
@@ -1015,6 +1034,7 @@ static struct usb_driver wdm_driver = {
.post_reset = wdm_post_reset,
.id_table = wdm_ids,
.supports_autosuspend = 1,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(wdm_driver);
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index a68c1a63dc65..d4c47d5d7625 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -172,27 +172,31 @@ struct usblp {
#ifdef DEBUG
static void usblp_dump(struct usblp *usblp)
{
+ struct device *dev = &usblp->intf->dev;
int p;
- dbg("usblp=0x%p", usblp);
- dbg("dev=0x%p", usblp->dev);
- dbg("present=%d", usblp->present);
- dbg("readbuf=0x%p", usblp->readbuf);
- dbg("readcount=%d", usblp->readcount);
- dbg("ifnum=%d", usblp->ifnum);
- for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
- dbg("protocol[%d].alt_setting=%d", p, usblp->protocol[p].alt_setting);
- dbg("protocol[%d].epwrite=%p", p, usblp->protocol[p].epwrite);
- dbg("protocol[%d].epread=%p", p, usblp->protocol[p].epread);
- }
- dbg("current_protocol=%d", usblp->current_protocol);
- dbg("minor=%d", usblp->minor);
- dbg("wstatus=%d", usblp->wstatus);
- dbg("rstatus=%d", usblp->rstatus);
- dbg("quirks=%d", usblp->quirks);
- dbg("used=%d", usblp->used);
- dbg("bidir=%d", usblp->bidir);
- dbg("device_id_string=\"%s\"",
+ dev_dbg(dev, "usblp=0x%p\n", usblp);
+ dev_dbg(dev, "dev=0x%p\n", usblp->dev);
+ dev_dbg(dev, "present=%d\n", usblp->present);
+ dev_dbg(dev, "readbuf=0x%p\n", usblp->readbuf);
+ dev_dbg(dev, "readcount=%d\n", usblp->readcount);
+ dev_dbg(dev, "ifnum=%d\n", usblp->ifnum);
+ for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
+ dev_dbg(dev, "protocol[%d].alt_setting=%d\n", p,
+ usblp->protocol[p].alt_setting);
+ dev_dbg(dev, "protocol[%d].epwrite=%p\n", p,
+ usblp->protocol[p].epwrite);
+ dev_dbg(dev, "protocol[%d].epread=%p\n", p,
+ usblp->protocol[p].epread);
+ }
+ dev_dbg(dev, "current_protocol=%d\n", usblp->current_protocol);
+ dev_dbg(dev, "minor=%d\n", usblp->minor);
+ dev_dbg(dev, "wstatus=%d\n", usblp->wstatus);
+ dev_dbg(dev, "rstatus=%d\n", usblp->rstatus);
+ dev_dbg(dev, "quirks=%d\n", usblp->quirks);
+ dev_dbg(dev, "used=%d\n", usblp->used);
+ dev_dbg(dev, "bidir=%d\n", usblp->bidir);
+ dev_dbg(dev, "device_id_string=\"%s\"\n",
usblp->device_id_string ?
usblp->device_id_string + 2 :
(unsigned char *)"(null)");
@@ -262,7 +266,8 @@ static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, i
retval = usb_control_msg(usblp->dev,
dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
request, type | dir | recip, value, index, buf, len, USBLP_CTL_TIMEOUT);
- dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d idx: %d len: %#x result: %d",
+ dev_dbg(&usblp->intf->dev,
+ "usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d idx: %d len: %#x result: %d\n",
request, !!dir, recip, value, index, len, retval);
return retval < 0 ? retval : 0;
}
@@ -500,8 +505,9 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto done;
}
- dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd),
- _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd));
+ dev_dbg(&usblp->intf->dev,
+ "usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)\n", cmd,
+ _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd));
if (_IOC_TYPE(cmd) == 'P') /* new-style ioctl number */
@@ -594,7 +600,8 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto done;
}
- dbg("usblp%d requested/got HP channel %ld/%d",
+ dev_dbg(&usblp->intf->dev,
+ "usblp%d requested/got HP channel %ld/%d\n",
usblp->minor, arg, newChannel);
break;
@@ -614,7 +621,8 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto done;
}
- dbg("usblp%d is bus=%d, device=%d",
+ dev_dbg(&usblp->intf->dev,
+ "usblp%d is bus=%d, device=%d\n",
usblp->minor, twoints[0], twoints[1]);
break;
@@ -634,7 +642,8 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto done;
}
- dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
+ dev_dbg(&usblp->intf->dev,
+ "usblp%d is VID=0x%4.4X, PID=0x%4.4X\n",
usblp->minor, twoints[0], twoints[1]);
break;
@@ -987,7 +996,7 @@ static int usblp_submit_read(struct usblp *usblp)
usblp->rcomplete = 0;
spin_unlock_irqrestore(&usblp->lock, flags);
if ((rc = usb_submit_urb(urb, GFP_KERNEL)) < 0) {
- dbg("error submitting urb (%d)", rc);
+ dev_dbg(&usblp->intf->dev, "error submitting urb (%d)\n", rc);
spin_lock_irqsave(&usblp->lock, flags);
usblp->rstatus = rc;
usblp->rcomplete = 1;
@@ -1129,7 +1138,8 @@ static int usblp_probe(struct usb_interface *intf,
/* Analyze and pick initial alternate settings and endpoints. */
protocol = usblp_select_alts(usblp);
if (protocol < 0) {
- dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
+ dev_dbg(&intf->dev,
+ "incompatible printer-class device 0x%4.4X/0x%4.4X\n",
le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
retval = -ENODEV;
@@ -1158,14 +1168,14 @@ static int usblp_probe(struct usb_interface *intf,
retval = usb_register_dev(intf, &usblp_class);
if (retval) {
- printk(KERN_ERR "usblp: Not able to get a minor"
- " (base %u, slice default): %d\n",
- USBLP_MINOR_BASE, retval);
+ dev_err(&intf->dev,
+ "usblp: Not able to get a minor (base %u, slice default): %d\n",
+ USBLP_MINOR_BASE, retval);
goto abort_intfdata;
}
usblp->minor = intf->minor;
- printk(KERN_INFO "usblp%d: USB %sdirectional printer dev %d "
- "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X\n",
+ dev_info(&intf->dev,
+ "usblp%d: USB %sdirectional printer dev %d if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X\n",
usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
usblp->ifnum,
usblp->protocol[usblp->current_protocol].alt_setting,
@@ -1302,7 +1312,8 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol)
usblp->bidir = (usblp->protocol[protocol].epread != NULL);
usblp->current_protocol = protocol;
- dbg("usblp%d set protocol %d", usblp->minor, protocol);
+ dev_dbg(&usblp->intf->dev, "usblp%d set protocol %d\n",
+ usblp->minor, protocol);
return 0;
}
@@ -1315,7 +1326,8 @@ static int usblp_cache_device_id_string(struct usblp *usblp)
err = usblp_get_id(usblp, 0, usblp->device_id_string, USBLP_DEVICE_ID_SIZE - 1);
if (err < 0) {
- dbg("usblp%d: error = %d reading IEEE-1284 Device ID string",
+ dev_dbg(&usblp->intf->dev,
+ "usblp%d: error = %d reading IEEE-1284 Device ID string\n",
usblp->minor, err);
usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
return -EIO;
@@ -1331,7 +1343,7 @@ static int usblp_cache_device_id_string(struct usblp *usblp)
length = USBLP_DEVICE_ID_SIZE - 1;
usblp->device_id_string[length] = '\0';
- dbg("usblp%d Device ID string [len=%d]=\"%s\"",
+ dev_dbg(&usblp->intf->dev, "usblp%d Device ID string [len=%d]=\"%s\"\n",
usblp->minor, length, &usblp->device_id_string[2]);
return length;
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 18d02e32a3d5..9981984b365b 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -27,58 +27,6 @@ config USB_ANNOUNCE_NEW_DEVICES
comment "Miscellaneous USB options"
depends on USB
-config USB_DEVICEFS
- bool "USB device filesystem (DEPRECATED)"
- depends on USB
- ---help---
- If you say Y here (and to "/proc file system support" in the "File
- systems" section, above), you will get a file /proc/bus/usb/devices
- which lists the devices currently connected to your USB bus or
- busses, and for every connected device a file named
- "/proc/bus/usb/xxx/yyy", where xxx is the bus number and yyy the
- device number; the latter files can be used by user space programs
- to talk directly to the device. These files are "virtual", meaning
- they are generated on the fly and not stored on the hard drive.
-
- You may need to mount the usbfs file system to see the files, use
- mount -t usbfs none /proc/bus/usb
-
- For the format of the various /proc/bus/usb/ files, please read
- <file:Documentation/usb/proc_usb_info.txt>.
-
- Modern Linux systems do not use this.
-
- Usbfs entries are files and not character devices; usbfs can't
- handle Access Control Lists (ACL) which are the default way to
- grant access to USB devices for untrusted users of a desktop
- system.
-
- The usbfs functionality is replaced by real device-nodes managed by
- udev. These nodes lived in /dev/bus/usb and are used by libusb.
-
-config USB_DEVICE_CLASS
- bool "USB device class-devices (DEPRECATED)"
- depends on USB
- default y
- ---help---
- Userspace access to USB devices is granted by device-nodes exported
- directly from the usbdev in sysfs. Old versions of the driver
- core and udev needed additional class devices to export device nodes.
-
- These additional devices are difficult to handle in userspace, if
- information about USB interfaces must be available. One device
- contains the device node, the other device contains the interface
- data. Both devices are at the same level in sysfs (siblings) and one
- can't access the other. The device node created directly by the
- usb device is the parent device of the interface and therefore
- easily accessible from the interface event.
-
- This option provides backward compatibility for libusb device
- nodes (lsusb) when usbfs is not used, and the following udev rule
- doesn't exist:
- SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", \
- NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644"
-
config USB_DYNAMIC_MINORS
bool "Dynamic USB minor allocation"
depends on USB
@@ -125,7 +73,6 @@ config USB_OTG_WHITELIST
bool "Rely on OTG Targeted Peripherals List"
depends on USB_OTG || EXPERT
default y if USB_OTG
- default n if EXPERT
help
If you say Y here, the "otg_whitelist.h" file will be used as a
product whitelist, so USB peripherals not listed there will be
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 507a4e1b6360..26059b93dbf4 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -9,6 +9,6 @@ usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
usbcore-y += devio.o notify.o generic.o quirks.o devices.o
usbcore-$(CONFIG_PCI) += hcd-pci.o
-usbcore-$(CONFIG_USB_DEVICEFS) += inode.o
+usbcore-$(CONFIG_ACPI) += usb-acpi.o
obj-$(CONFIG_USB) += usbcore.o
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 8df4b76465ac..e0f107948eba 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -333,17 +333,14 @@ static struct async *async_getcompleted(struct dev_state *ps)
static struct async *async_getpending(struct dev_state *ps,
void __user *userurb)
{
- unsigned long flags;
struct async *as;
- spin_lock_irqsave(&ps->lock, flags);
list_for_each_entry(as, &ps->async_pending, asynclist)
if (as->userurb == userurb) {
list_del_init(&as->asynclist);
- spin_unlock_irqrestore(&ps->lock, flags);
return as;
}
- spin_unlock_irqrestore(&ps->lock, flags);
+
return NULL;
}
@@ -398,6 +395,7 @@ static void cancel_bulk_urbs(struct dev_state *ps, unsigned bulk_addr)
__releases(ps->lock)
__acquires(ps->lock)
{
+ struct urb *urb;
struct async *as;
/* Mark all the pending URBs that match bulk_addr, up to but not
@@ -420,8 +418,11 @@ __acquires(ps->lock)
list_for_each_entry(as, &ps->async_pending, asynclist) {
if (as->bulk_status == AS_UNLINK) {
as->bulk_status = 0; /* Only once */
+ urb = as->urb;
+ usb_get_urb(urb);
spin_unlock(&ps->lock); /* Allow completions */
- usb_unlink_urb(as->urb);
+ usb_unlink_urb(urb);
+ usb_put_urb(urb);
spin_lock(&ps->lock);
goto rescan;
}
@@ -472,6 +473,7 @@ static void async_completed(struct urb *urb)
static void destroy_async(struct dev_state *ps, struct list_head *list)
{
+ struct urb *urb;
struct async *as;
unsigned long flags;
@@ -479,10 +481,13 @@ static void destroy_async(struct dev_state *ps, struct list_head *list)
while (!list_empty(list)) {
as = list_entry(list->next, struct async, asynclist);
list_del_init(&as->asynclist);
+ urb = as->urb;
+ usb_get_urb(urb);
/* drop the spinlock so the completion handler can run */
spin_unlock_irqrestore(&ps->lock, flags);
- usb_kill_urb(as->urb);
+ usb_kill_urb(urb);
+ usb_put_urb(urb);
spin_lock_irqsave(&ps->lock, flags);
}
spin_unlock_irqrestore(&ps->lock, flags);
@@ -727,17 +732,6 @@ static int usbdev_open(struct inode *inode, struct file *file)
if (imajor(inode) == USB_DEVICE_MAJOR)
dev = usbdev_lookup_by_devt(inode->i_rdev);
-#ifdef CONFIG_USB_DEVICEFS
- /* procfs file */
- if (!dev) {
- dev = inode->i_private;
- if (dev && dev->usbfs_dentry &&
- dev->usbfs_dentry->d_inode == inode)
- usb_get_dev(dev);
- else
- dev = NULL;
- }
-#endif
mutex_unlock(&usbfs_mutex);
if (!dev)
@@ -1410,12 +1404,24 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
static int proc_unlinkurb(struct dev_state *ps, void __user *arg)
{
+ struct urb *urb;
struct async *as;
+ unsigned long flags;
+ spin_lock_irqsave(&ps->lock, flags);
as = async_getpending(ps, arg);
- if (!as)
+ if (!as) {
+ spin_unlock_irqrestore(&ps->lock, flags);
return -EINVAL;
- usb_kill_urb(as->urb);
+ }
+
+ urb = as->urb;
+ usb_get_urb(urb);
+ spin_unlock_irqrestore(&ps->lock, flags);
+
+ usb_kill_urb(urb);
+ usb_put_urb(urb);
+
return 0;
}
@@ -2062,44 +2068,13 @@ static void usbdev_remove(struct usb_device *udev)
}
}
-#ifdef CONFIG_USB_DEVICE_CLASS
-static struct class *usb_classdev_class;
-
-static int usb_classdev_add(struct usb_device *dev)
-{
- struct device *cldev;
-
- cldev = device_create(usb_classdev_class, &dev->dev, dev->dev.devt,
- NULL, "usbdev%d.%d", dev->bus->busnum,
- dev->devnum);
- if (IS_ERR(cldev))
- return PTR_ERR(cldev);
- dev->usb_classdev = cldev;
- return 0;
-}
-
-static void usb_classdev_remove(struct usb_device *dev)
-{
- if (dev->usb_classdev)
- device_unregister(dev->usb_classdev);
-}
-
-#else
-#define usb_classdev_add(dev) 0
-#define usb_classdev_remove(dev) do {} while (0)
-
-#endif
-
static int usbdev_notify(struct notifier_block *self,
unsigned long action, void *dev)
{
switch (action) {
case USB_DEVICE_ADD:
- if (usb_classdev_add(dev))
- return NOTIFY_BAD;
break;
case USB_DEVICE_REMOVE:
- usb_classdev_remove(dev);
usbdev_remove(dev);
break;
}
@@ -2129,21 +2104,6 @@ int __init usb_devio_init(void)
USB_DEVICE_MAJOR);
goto error_cdev;
}
-#ifdef CONFIG_USB_DEVICE_CLASS
- usb_classdev_class = class_create(THIS_MODULE, "usb_device");
- if (IS_ERR(usb_classdev_class)) {
- printk(KERN_ERR "Unable to register usb_device class\n");
- retval = PTR_ERR(usb_classdev_class);
- cdev_del(&usb_device_cdev);
- usb_classdev_class = NULL;
- goto out;
- }
- /* devices of this class shadow the major:minor of their parent
- * device, so clear ->dev_kobj to prevent adding duplicate entries
- * to /sys/dev
- */
- usb_classdev_class->dev_kobj = NULL;
-#endif
usb_register_notify(&usbdev_nb);
out:
return retval;
@@ -2156,9 +2116,6 @@ error_cdev:
void usb_devio_cleanup(void)
{
usb_unregister_notify(&usbdev_nb);
-#ifdef CONFIG_USB_DEVICE_CLASS
- class_destroy(usb_classdev_class);
-#endif
cdev_del(&usb_device_cdev);
unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
}
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 9a56635dc19c..f536aebc958e 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -79,6 +79,30 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
}
EXPORT_SYMBOL_GPL(usb_store_new_id);
+ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf)
+{
+ struct usb_dynid *dynid;
+ size_t count = 0;
+
+ list_for_each_entry(dynid, &dynids->list, node)
+ if (dynid->id.bInterfaceClass != 0)
+ count += scnprintf(&buf[count], PAGE_SIZE - count, "%04x %04x %02x\n",
+ dynid->id.idVendor, dynid->id.idProduct,
+ dynid->id.bInterfaceClass);
+ else
+ count += scnprintf(&buf[count], PAGE_SIZE - count, "%04x %04x\n",
+ dynid->id.idVendor, dynid->id.idProduct);
+ return count;
+}
+EXPORT_SYMBOL_GPL(usb_show_dynids);
+
+static ssize_t show_dynids(struct device_driver *driver, char *buf)
+{
+ struct usb_driver *usb_drv = to_usb_driver(driver);
+
+ return usb_show_dynids(&usb_drv->dynids, buf);
+}
+
static ssize_t store_new_id(struct device_driver *driver,
const char *buf, size_t count)
{
@@ -86,7 +110,7 @@ static ssize_t store_new_id(struct device_driver *driver,
return usb_store_new_id(&usb_drv->dynids, driver, buf, count);
}
-static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
+static DRIVER_ATTR(new_id, S_IRUGO | S_IWUSR, show_dynids, store_new_id);
/**
* store_remove_id - remove a USB device ID from this driver
@@ -127,7 +151,7 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count)
return retval;
return count;
}
-static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id);
+static DRIVER_ATTR(remove_id, S_IRUGO | S_IWUSR, show_dynids, store_remove_id);
static int usb_create_newid_files(struct usb_driver *usb_drv)
{
@@ -264,6 +288,7 @@ static int usb_probe_interface(struct device *dev)
struct usb_device *udev = interface_to_usbdev(intf);
const struct usb_device_id *id;
int error = -ENODEV;
+ int lpm_disable_error;
dev_dbg(dev, "%s\n", __func__);
@@ -300,6 +325,25 @@ static int usb_probe_interface(struct device *dev)
if (driver->supports_autosuspend)
pm_runtime_enable(dev);
+ /* If the new driver doesn't allow hub-initiated LPM, and we can't
+ * disable hub-initiated LPM, then fail the probe.
+ *
+ * Otherwise, leaving LPM enabled should be harmless, because the
+ * endpoint intervals should remain the same, and the U1/U2 timeouts
+ * should remain the same.
+ *
+ * If we need to install alt setting 0 before probe, or another alt
+ * setting during probe, that should also be fine. usb_set_interface()
+ * will attempt to disable LPM, and fail if it can't disable it.
+ */
+ lpm_disable_error = usb_unlocked_disable_lpm(udev);
+ if (lpm_disable_error && driver->disable_hub_initiated_lpm) {
+ dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n.",
+ __func__, driver->name);
+ error = lpm_disable_error;
+ goto err;
+ }
+
/* Carry out a deferred switch to altsetting 0 */
if (intf->needs_altsetting0) {
error = usb_set_interface(udev, intf->altsetting[0].
@@ -314,6 +358,11 @@ static int usb_probe_interface(struct device *dev)
goto err;
intf->condition = USB_INTERFACE_BOUND;
+
+ /* If the LPM disable succeeded, balance the ref counts. */
+ if (!lpm_disable_error)
+ usb_unlocked_enable_lpm(udev);
+
usb_autosuspend_device(udev);
return error;
@@ -337,7 +386,7 @@ static int usb_unbind_interface(struct device *dev)
struct usb_driver *driver = to_usb_driver(dev->driver);
struct usb_interface *intf = to_usb_interface(dev);
struct usb_device *udev;
- int error, r;
+ int error, r, lpm_disable_error;
intf->condition = USB_INTERFACE_UNBINDING;
@@ -345,6 +394,13 @@ static int usb_unbind_interface(struct device *dev)
udev = interface_to_usbdev(intf);
error = usb_autoresume_device(udev);
+ /* Hub-initiated LPM policy may change, so attempt to disable LPM until
+ * the driver is unbound. If LPM isn't disabled, that's fine because it
+ * wouldn't be enabled unless all the bound interfaces supported
+ * hub-initiated LPM.
+ */
+ lpm_disable_error = usb_unlocked_disable_lpm(udev);
+
/* Terminate all URBs for this interface unless the driver
* supports "soft" unbinding.
*/
@@ -378,6 +434,10 @@ static int usb_unbind_interface(struct device *dev)
intf->condition = USB_INTERFACE_UNBOUND;
intf->needs_remote_wakeup = 0;
+ /* Attempt to re-enable USB3 LPM, if the disable succeeded. */
+ if (!lpm_disable_error)
+ usb_unlocked_enable_lpm(udev);
+
/* Unbound interfaces are always runtime-PM-disabled and -suspended */
if (driver->supports_autosuspend)
pm_runtime_disable(dev);
@@ -418,17 +478,29 @@ int usb_driver_claim_interface(struct usb_driver *driver,
struct usb_interface *iface, void *priv)
{
struct device *dev = &iface->dev;
+ struct usb_device *udev;
int retval = 0;
+ int lpm_disable_error;
if (dev->driver)
return -EBUSY;
+ udev = interface_to_usbdev(iface);
+
dev->driver = &driver->drvwrap.driver;
usb_set_intfdata(iface, priv);
iface->needs_binding = 0;
iface->condition = USB_INTERFACE_BOUND;
+ /* Disable LPM until this driver is bound. */
+ lpm_disable_error = usb_unlocked_disable_lpm(udev);
+ if (lpm_disable_error && driver->disable_hub_initiated_lpm) {
+ dev_err(&iface->dev, "%s Failed to disable LPM for driver %s\n.",
+ __func__, driver->name);
+ return -ENOMEM;
+ }
+
/* Claimed interfaces are initially inactive (suspended) and
* runtime-PM-enabled, but only if the driver has autosuspend
* support. Otherwise they are marked active, to prevent the
@@ -447,6 +519,10 @@ int usb_driver_claim_interface(struct usb_driver *driver,
if (device_is_registered(dev))
retval = device_bind_driver(dev);
+ /* Attempt to re-enable USB3 LPM, if the disable was successful. */
+ if (!lpm_disable_error)
+ usb_unlocked_enable_lpm(udev);
+
return retval;
}
EXPORT_SYMBOL_GPL(usb_driver_claim_interface);
@@ -726,16 +802,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
return -ENODEV;
}
-#ifdef CONFIG_USB_DEVICEFS
- /* If this is available, userspace programs can directly read
- * all the device descriptors we don't tell them about. Or
- * act as usermode drivers.
- */
- if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d",
- usb_dev->bus->busnum, usb_dev->devnum))
- return -ENOMEM;
-#endif
-
/* per-device configurations are common */
if (add_uevent_var(env, "PRODUCT=%x/%x/%x",
le16_to_cpu(usb_dev->descriptor.idVendor),
@@ -788,15 +854,13 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver,
retval = driver_register(&new_udriver->drvwrap.driver);
- if (!retval) {
+ if (!retval)
pr_info("%s: registered new device driver %s\n",
usbcore_name, new_udriver->name);
- usbfs_update_special();
- } else {
+ else
printk(KERN_ERR "%s: error %d registering device "
" driver %s\n",
usbcore_name, retval, new_udriver->name);
- }
return retval;
}
@@ -815,7 +879,6 @@ void usb_deregister_device_driver(struct usb_device_driver *udriver)
usbcore_name, udriver->name);
driver_unregister(&udriver->drvwrap.driver);
- usbfs_update_special();
}
EXPORT_SYMBOL_GPL(usb_deregister_device_driver);
@@ -856,8 +919,6 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
if (retval)
goto out;
- usbfs_update_special();
-
retval = usb_create_newid_files(new_driver);
if (retval)
goto out_newid;
@@ -897,8 +958,6 @@ void usb_deregister(struct usb_driver *driver)
usb_remove_newid_files(driver);
driver_unregister(&driver->drvwrap.driver);
usb_free_dynids(driver);
-
- usbfs_update_special();
}
EXPORT_SYMBOL_GPL(usb_deregister);
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index d95760de9e8b..e673b26e598f 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -183,7 +183,7 @@ int usb_register_dev(struct usb_interface *intf,
if (retval)
return retval;
- dev_dbg(&intf->dev, "looking for a minor, starting at %d", minor_base);
+ dev_dbg(&intf->dev, "looking for a minor, starting at %d\n", minor_base);
down_write(&minor_rwsem);
for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
@@ -239,7 +239,7 @@ void usb_deregister_dev(struct usb_interface *intf,
if (intf->minor == -1)
return;
- dbg ("removing %d minor", intf->minor);
+ dev_dbg(&intf->dev, "removing %d minor\n", intf->minor);
down_write(&minor_rwsem);
usb_minors[intf->minor] = NULL;
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 140d3e11f212..190b1ec7bdcb 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -138,7 +138,7 @@ static const u8 usb3_rh_dev_descriptor[18] = {
0x03, /* __u8 bDeviceProtocol; USB 3.0 hub */
0x09, /* __u8 bMaxPacketSize0; 2^9 = 512 Bytes */
- 0x6b, 0x1d, /* __le16 idVendor; Linux Foundation */
+ 0x6b, 0x1d, /* __le16 idVendor; Linux Foundation 0x1d6b */
0x03, 0x00, /* __le16 idProduct; device 0x0003 */
KERNEL_VER, KERNEL_REL, /* __le16 bcdDevice */
@@ -159,7 +159,7 @@ static const u8 usb2_rh_dev_descriptor [18] = {
0x00, /* __u8 bDeviceProtocol; [ usb 2.0 no TT ] */
0x40, /* __u8 bMaxPacketSize0; 64 Bytes */
- 0x6b, 0x1d, /* __le16 idVendor; Linux Foundation */
+ 0x6b, 0x1d, /* __le16 idVendor; Linux Foundation 0x1d6b */
0x02, 0x00, /* __le16 idProduct; device 0x0002 */
KERNEL_VER, KERNEL_REL, /* __le16 bcdDevice */
@@ -182,7 +182,7 @@ static const u8 usb11_rh_dev_descriptor [18] = {
0x00, /* __u8 bDeviceProtocol; [ low/full speeds only ] */
0x40, /* __u8 bMaxPacketSize0; 64 Bytes */
- 0x6b, 0x1d, /* __le16 idVendor; Linux Foundation */
+ 0x6b, 0x1d, /* __le16 idVendor; Linux Foundation 0x1d6b */
0x01, 0x00, /* __le16 idProduct; device 0x0001 */
KERNEL_VER, KERNEL_REL, /* __le16 bcdDevice */
@@ -997,6 +997,15 @@ static int register_root_hub(struct usb_hcd *hcd)
dev_name(&usb_dev->dev), retval);
return (retval < 0) ? retval : -EMSGSIZE;
}
+ if (usb_dev->speed == USB_SPEED_SUPER) {
+ retval = usb_get_bos_descriptor(usb_dev);
+ if (retval < 0) {
+ mutex_unlock(&usb_bus_list_lock);
+ dev_dbg(parent_dev, "can't read %s bos descriptor %d\n",
+ dev_name(&usb_dev->dev), retval);
+ return retval;
+ }
+ }
retval = usb_new_device (usb_dev);
if (retval) {
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index ec6c97dadbe4..04fb834c3fa1 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -177,6 +177,228 @@ static struct usb_hub *hdev_to_hub(struct usb_device *hdev)
return usb_get_intfdata(hdev->actconfig->interface[0]);
}
+static int usb_device_supports_lpm(struct usb_device *udev)
+{
+ /* USB 2.1 (and greater) devices indicate LPM support through
+ * their USB 2.0 Extended Capabilities BOS descriptor.
+ */
+ if (udev->speed == USB_SPEED_HIGH) {
+ if (udev->bos->ext_cap &&
+ (USB_LPM_SUPPORT &
+ le32_to_cpu(udev->bos->ext_cap->bmAttributes)))
+ return 1;
+ return 0;
+ }
+
+ /* All USB 3.0 must support LPM, but we need their max exit latency
+ * information from the SuperSpeed Extended Capabilities BOS descriptor.
+ */
+ if (!udev->bos->ss_cap) {
+ dev_warn(&udev->dev, "No LPM exit latency info found. "
+ "Power management will be impacted.\n");
+ return 0;
+ }
+ if (udev->parent->lpm_capable)
+ return 1;
+
+ dev_warn(&udev->dev, "Parent hub missing LPM exit latency info. "
+ "Power management will be impacted.\n");
+ return 0;
+}
+
+/*
+ * Set the Maximum Exit Latency (MEL) for the host to initiate a transition from
+ * either U1 or U2.
+ */
+static void usb_set_lpm_mel(struct usb_device *udev,
+ struct usb3_lpm_parameters *udev_lpm_params,
+ unsigned int udev_exit_latency,
+ struct usb_hub *hub,
+ struct usb3_lpm_parameters *hub_lpm_params,
+ unsigned int hub_exit_latency)
+{
+ unsigned int total_mel;
+ unsigned int device_mel;
+ unsigned int hub_mel;
+
+ /*
+ * Calculate the time it takes to transition all links from the roothub
+ * to the parent hub into U0. The parent hub must then decode the
+ * packet (hub header decode latency) to figure out which port it was
+ * bound for.
+ *
+ * The Hub Header decode latency is expressed in 0.1us intervals (0x1
+ * means 0.1us). Multiply that by 100 to get nanoseconds.
+ */
+ total_mel = hub_lpm_params->mel +
+ (hub->descriptor->u.ss.bHubHdrDecLat * 100);
+
+ /*
+ * How long will it take to transition the downstream hub's port into
+ * U0? The greater of either the hub exit latency or the device exit
+ * latency.
+ *
+ * The BOS U1/U2 exit latencies are expressed in 1us intervals.
+ * Multiply that by 1000 to get nanoseconds.
+ */
+ device_mel = udev_exit_latency * 1000;
+ hub_mel = hub_exit_latency * 1000;
+ if (device_mel > hub_mel)
+ total_mel += device_mel;
+ else
+ total_mel += hub_mel;
+
+ udev_lpm_params->mel = total_mel;
+}
+
+/*
+ * Set the maximum Device to Host Exit Latency (PEL) for the device to initiate
+ * a transition from either U1 or U2.
+ */
+static void usb_set_lpm_pel(struct usb_device *udev,
+ struct usb3_lpm_parameters *udev_lpm_params,
+ unsigned int udev_exit_latency,
+ struct usb_hub *hub,
+ struct usb3_lpm_parameters *hub_lpm_params,
+ unsigned int hub_exit_latency,
+ unsigned int port_to_port_exit_latency)
+{
+ unsigned int first_link_pel;
+ unsigned int hub_pel;
+
+ /*
+ * First, the device sends an LFPS to transition the link between the
+ * device and the parent hub into U0. The exit latency is the bigger of
+ * the device exit latency or the hub exit latency.
+ */
+ if (udev_exit_latency > hub_exit_latency)
+ first_link_pel = udev_exit_latency * 1000;
+ else
+ first_link_pel = hub_exit_latency * 1000;
+
+ /*
+ * When the hub starts to receive the LFPS, there is a slight delay for
+ * it to figure out that one of the ports is sending an LFPS. Then it
+ * will forward the LFPS to its upstream link. The exit latency is the
+ * delay, plus the PEL that we calculated for this hub.
+ */
+ hub_pel = port_to_port_exit_latency * 1000 + hub_lpm_params->pel;
+
+ /*
+ * According to figure C-7 in the USB 3.0 spec, the PEL for this device
+ * is the greater of the two exit latencies.
+ */
+ if (first_link_pel > hub_pel)
+ udev_lpm_params->pel = first_link_pel;
+ else
+ udev_lpm_params->pel = hub_pel;
+}
+
+/*
+ * Set the System Exit Latency (SEL) to indicate the total worst-case time from
+ * when a device initiates a transition to U0, until when it will receive the
+ * first packet from the host controller.
+ *
+ * Section C.1.5.1 describes the four components to this:
+ * - t1: device PEL
+ * - t2: time for the ERDY to make it from the device to the host.
+ * - t3: a host-specific delay to process the ERDY.
+ * - t4: time for the packet to make it from the host to the device.
+ *
+ * t3 is specific to both the xHCI host and the platform the host is integrated
+ * into. The Intel HW folks have said it's negligible, FIXME if a different
+ * vendor says otherwise.
+ */
+static void usb_set_lpm_sel(struct usb_device *udev,
+ struct usb3_lpm_parameters *udev_lpm_params)
+{
+ struct usb_device *parent;
+ unsigned int num_hubs;
+ unsigned int total_sel;
+
+ /* t1 = device PEL */
+ total_sel = udev_lpm_params->pel;
+ /* How many external hubs are in between the device & the root port. */
+ for (parent = udev->parent, num_hubs = 0; parent->parent;
+ parent = parent->parent)
+ num_hubs++;
+ /* t2 = 2.1us + 250ns * (num_hubs - 1) */
+ if (num_hubs > 0)
+ total_sel += 2100 + 250 * (num_hubs - 1);
+
+ /* t4 = 250ns * num_hubs */
+ total_sel += 250 * num_hubs;
+
+ udev_lpm_params->sel = total_sel;
+}
+
+static void usb_set_lpm_parameters(struct usb_device *udev)
+{
+ struct usb_hub *hub;
+ unsigned int port_to_port_delay;
+ unsigned int udev_u1_del;
+ unsigned int udev_u2_del;
+ unsigned int hub_u1_del;
+ unsigned int hub_u2_del;
+
+ if (!udev->lpm_capable || udev->speed != USB_SPEED_SUPER)
+ return;
+
+ hub = hdev_to_hub(udev->parent);
+ /* It doesn't take time to transition the roothub into U0, since it
+ * doesn't have an upstream link.
+ */
+ if (!hub)
+ return;
+
+ udev_u1_del = udev->bos->ss_cap->bU1devExitLat;
+ udev_u2_del = udev->bos->ss_cap->bU2DevExitLat;
+ hub_u1_del = udev->parent->bos->ss_cap->bU1devExitLat;
+ hub_u2_del = udev->parent->bos->ss_cap->bU2DevExitLat;
+
+ usb_set_lpm_mel(udev, &udev->u1_params, udev_u1_del,
+ hub, &udev->parent->u1_params, hub_u1_del);
+
+ usb_set_lpm_mel(udev, &udev->u2_params, udev_u2_del,
+ hub, &udev->parent->u2_params, hub_u2_del);
+
+ /*
+ * Appendix C, section C.2.2.2, says that there is a slight delay from
+ * when the parent hub notices the downstream port is trying to
+ * transition to U0 to when the hub initiates a U0 transition on its
+ * upstream port. The section says the delays are tPort2PortU1EL and
+ * tPort2PortU2EL, but it doesn't define what they are.
+ *
+ * The hub chapter, sections 10.4.2.4 and 10.4.2.5 seem to be talking
+ * about the same delays. Use the maximum delay calculations from those
+ * sections. For U1, it's tHubPort2PortExitLat, which is 1us max. For
+ * U2, it's tHubPort2PortExitLat + U2DevExitLat - U1DevExitLat. I
+ * assume the device exit latencies they are talking about are the hub
+ * exit latencies.
+ *
+ * What do we do if the U2 exit latency is less than the U1 exit
+ * latency? It's possible, although not likely...
+ */
+ port_to_port_delay = 1;
+
+ usb_set_lpm_pel(udev, &udev->u1_params, udev_u1_del,
+ hub, &udev->parent->u1_params, hub_u1_del,
+ port_to_port_delay);
+
+ if (hub_u2_del > hub_u1_del)
+ port_to_port_delay = 1 + hub_u2_del - hub_u1_del;
+ else
+ port_to_port_delay = 1 + hub_u1_del;
+
+ usb_set_lpm_pel(udev, &udev->u2_params, udev_u2_del,
+ hub, &udev->parent->u2_params, hub_u2_del,
+ port_to_port_delay);
+
+ /* Now that we've got PEL, calculate SEL. */
+ usb_set_lpm_sel(udev, &udev->u1_params);
+ usb_set_lpm_sel(udev, &udev->u2_params);
+}
+
/* USB 2.0 spec Section 11.24.4.5 */
static int get_hub_descriptor(struct usb_device *hdev, void *data)
{
@@ -2480,6 +2702,12 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
if (udev->usb2_hw_lpm_enabled == 1)
usb_set_usb2_hardware_lpm(udev, 0);
+ if (usb_unlocked_disable_lpm(udev)) {
+ dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.",
+ __func__);
+ return -ENOMEM;
+ }
+
/* see 7.1.7.6 */
if (hub_is_superspeed(hub->hdev))
status = set_port_feature(hub->hdev,
@@ -2499,6 +2727,13 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
NULL, 0,
USB_CTRL_SET_TIMEOUT);
+ /* Try to enable USB2 hardware LPM again */
+ if (udev->usb2_hw_lpm_capable == 1)
+ usb_set_usb2_hardware_lpm(udev, 1);
+
+ /* Try to enable USB3 LPM again */
+ usb_unlocked_enable_lpm(udev);
+
/* System sleep transitions should never fail */
if (!PMSG_IS_AUTO(msg))
status = 0;
@@ -2696,6 +2931,9 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
/* Try to enable USB2 hardware LPM */
if (udev->usb2_hw_lpm_capable == 1)
usb_set_usb2_hardware_lpm(udev, 1);
+
+ /* Try to enable USB3 LPM */
+ usb_unlocked_enable_lpm(udev);
}
return status;
@@ -2824,11 +3062,429 @@ void usb_root_hub_lost_power(struct usb_device *rhdev)
}
EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
+static const char * const usb3_lpm_names[] = {
+ "U0",
+ "U1",
+ "U2",
+ "U3",
+};
+
+/*
+ * Send a Set SEL control transfer to the device, prior to enabling
+ * device-initiated U1 or U2. This lets the device know the exit latencies from
+ * the time the device initiates a U1 or U2 exit, to the time it will receive a
+ * packet from the host.
+ *
+ * This function will fail if the SEL or PEL values for udev are greater than
+ * the maximum allowed values for the link state to be enabled.
+ */
+static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)
+{
+ struct usb_set_sel_req *sel_values;
+ unsigned long long u1_sel;
+ unsigned long long u1_pel;
+ unsigned long long u2_sel;
+ unsigned long long u2_pel;
+ int ret;
+
+ /* Convert SEL and PEL stored in ns to us */
+ u1_sel = DIV_ROUND_UP(udev->u1_params.sel, 1000);
+ u1_pel = DIV_ROUND_UP(udev->u1_params.pel, 1000);
+ u2_sel = DIV_ROUND_UP(udev->u2_params.sel, 1000);
+ u2_pel = DIV_ROUND_UP(udev->u2_params.pel, 1000);
+
+ /*
+ * Make sure that the calculated SEL and PEL values for the link
+ * state we're enabling aren't bigger than the max SEL/PEL
+ * value that will fit in the SET SEL control transfer.
+ * Otherwise the device would get an incorrect idea of the exit
+ * latency for the link state, and could start a device-initiated
+ * U1/U2 when the exit latencies are too high.
+ */
+ if ((state == USB3_LPM_U1 &&
+ (u1_sel > USB3_LPM_MAX_U1_SEL_PEL ||
+ u1_pel > USB3_LPM_MAX_U1_SEL_PEL)) ||
+ (state == USB3_LPM_U2 &&
+ (u2_sel > USB3_LPM_MAX_U2_SEL_PEL ||
+ u2_pel > USB3_LPM_MAX_U2_SEL_PEL))) {
+ dev_dbg(&udev->dev, "Device-initiated %s disabled due "
+ "to long SEL %llu ms or PEL %llu ms\n",
+ usb3_lpm_names[state], u1_sel, u1_pel);
+ return -EINVAL;
+ }
+
+ /*
+ * If we're enabling device-initiated LPM for one link state,
+ * but the other link state has a too high SEL or PEL value,
+ * just set those values to the max in the Set SEL request.
+ */
+ if (u1_sel > USB3_LPM_MAX_U1_SEL_PEL)
+ u1_sel = USB3_LPM_MAX_U1_SEL_PEL;
+
+ if (u1_pel > USB3_LPM_MAX_U1_SEL_PEL)
+ u1_pel = USB3_LPM_MAX_U1_SEL_PEL;
+
+ if (u2_sel > USB3_LPM_MAX_U2_SEL_PEL)
+ u2_sel = USB3_LPM_MAX_U2_SEL_PEL;
+
+ if (u2_pel > USB3_LPM_MAX_U2_SEL_PEL)
+ u2_pel = USB3_LPM_MAX_U2_SEL_PEL;
+
+ /*
+ * usb_enable_lpm() can be called as part of a failed device reset,
+ * which may be initiated by an error path of a mass storage driver.
+ * Therefore, use GFP_NOIO.
+ */
+ sel_values = kmalloc(sizeof *(sel_values), GFP_NOIO);
+ if (!sel_values)
+ return -ENOMEM;
+
+ sel_values->u1_sel = u1_sel;
+ sel_values->u1_pel = u1_pel;
+ sel_values->u2_sel = cpu_to_le16(u2_sel);
+ sel_values->u2_pel = cpu_to_le16(u2_pel);
+
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ USB_REQ_SET_SEL,
+ USB_RECIP_DEVICE,
+ 0, 0,
+ sel_values, sizeof *(sel_values),
+ USB_CTRL_SET_TIMEOUT);
+ kfree(sel_values);
+ return ret;
+}
+
+/*
+ * Enable or disable device-initiated U1 or U2 transitions.
+ */
+static int usb_set_device_initiated_lpm(struct usb_device *udev,
+ enum usb3_link_state state, bool enable)
+{
+ int ret;
+ int feature;
+
+ switch (state) {
+ case USB3_LPM_U1:
+ feature = USB_DEVICE_U1_ENABLE;
+ break;
+ case USB3_LPM_U2:
+ feature = USB_DEVICE_U2_ENABLE;
+ break;
+ default:
+ dev_warn(&udev->dev, "%s: Can't %s non-U1 or U2 state.\n",
+ __func__, enable ? "enable" : "disable");
+ return -EINVAL;
+ }
+
+ if (udev->state != USB_STATE_CONFIGURED) {
+ dev_dbg(&udev->dev, "%s: Can't %s %s state "
+ "for unconfigured device.\n",
+ __func__, enable ? "enable" : "disable",
+ usb3_lpm_names[state]);
+ return 0;
+ }
+
+ if (enable) {
+ /*
+ * First, let the device know about the exit latencies
+ * associated with the link state we're about to enable.
+ */
+ ret = usb_req_set_sel(udev, state);
+ if (ret < 0) {
+ dev_warn(&udev->dev, "Set SEL for device-initiated "
+ "%s failed.\n", usb3_lpm_names[state]);
+ return -EBUSY;
+ }
+ /*
+ * Now send the control transfer to enable device-initiated LPM
+ * for either U1 or U2.
+ */
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ USB_REQ_SET_FEATURE,
+ USB_RECIP_DEVICE,
+ feature,
+ 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ } else {
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ USB_REQ_CLEAR_FEATURE,
+ USB_RECIP_DEVICE,
+ feature,
+ 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ }
+ if (ret < 0) {
+ dev_warn(&udev->dev, "%s of device-initiated %s failed.\n",
+ enable ? "Enable" : "Disable",
+ usb3_lpm_names[state]);
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static int usb_set_lpm_timeout(struct usb_device *udev,
+ enum usb3_link_state state, int timeout)
+{
+ int ret;
+ int feature;
+
+ switch (state) {
+ case USB3_LPM_U1:
+ feature = USB_PORT_FEAT_U1_TIMEOUT;
+ break;
+ case USB3_LPM_U2:
+ feature = USB_PORT_FEAT_U2_TIMEOUT;
+ break;
+ default:
+ dev_warn(&udev->dev, "%s: Can't set timeout for non-U1 or U2 state.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (state == USB3_LPM_U1 && timeout > USB3_LPM_U1_MAX_TIMEOUT &&
+ timeout != USB3_LPM_DEVICE_INITIATED) {
+ dev_warn(&udev->dev, "Failed to set %s timeout to 0x%x, "
+ "which is a reserved value.\n",
+ usb3_lpm_names[state], timeout);
+ return -EINVAL;
+ }
+
+ ret = set_port_feature(udev->parent,
+ USB_PORT_LPM_TIMEOUT(timeout) | udev->portnum,
+ feature);
+ if (ret < 0) {
+ dev_warn(&udev->dev, "Failed to set %s timeout to 0x%x,"
+ "error code %i\n", usb3_lpm_names[state],
+ timeout, ret);
+ return -EBUSY;
+ }
+ if (state == USB3_LPM_U1)
+ udev->u1_params.timeout = timeout;
+ else
+ udev->u2_params.timeout = timeout;
+ return 0;
+}
+
+/*
+ * Enable the hub-initiated U1/U2 idle timeouts, and enable device-initiated
+ * U1/U2 entry.
+ *
+ * We will attempt to enable U1 or U2, but there are no guarantees that the
+ * control transfers to set the hub timeout or enable device-initiated U1/U2
+ * will be successful.
+ *
+ * If we cannot set the parent hub U1/U2 timeout, we attempt to let the xHCI
+ * driver know about it. If that call fails, it should be harmless, and just
+ * take up more slightly more bus bandwidth for unnecessary U1/U2 exit latency.
+ */
+static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
+ enum usb3_link_state state)
+{
+ int timeout;
+
+ /* We allow the host controller to set the U1/U2 timeout internally
+ * first, so that it can change its schedule to account for the
+ * additional latency to send data to a device in a lower power
+ * link state.
+ */
+ timeout = hcd->driver->enable_usb3_lpm_timeout(hcd, udev, state);
+
+ /* xHCI host controller doesn't want to enable this LPM state. */
+ if (timeout == 0)
+ return;
+
+ if (timeout < 0) {
+ dev_warn(&udev->dev, "Could not enable %s link state, "
+ "xHCI error %i.\n", usb3_lpm_names[state],
+ timeout);
+ return;
+ }
+
+ if (usb_set_lpm_timeout(udev, state, timeout))
+ /* If we can't set the parent hub U1/U2 timeout,
+ * device-initiated LPM won't be allowed either, so let the xHCI
+ * host know that this link state won't be enabled.
+ */
+ hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state);
+
+ /* Only a configured device will accept the Set Feature U1/U2_ENABLE */
+ else if (udev->actconfig)
+ usb_set_device_initiated_lpm(udev, state, true);
+
+}
+
+/*
+ * Disable the hub-initiated U1/U2 idle timeouts, and disable device-initiated
+ * U1/U2 entry.
+ *
+ * If this function returns -EBUSY, the parent hub will still allow U1/U2 entry.
+ * If zero is returned, the parent will not allow the link to go into U1/U2.
+ *
+ * If zero is returned, device-initiated U1/U2 entry may still be enabled, but
+ * it won't have an effect on the bus link state because the parent hub will
+ * still disallow device-initiated U1/U2 entry.
+ *
+ * If zero is returned, the xHCI host controller may still think U1/U2 entry is
+ * possible. The result will be slightly more bus bandwidth will be taken up
+ * (to account for U1/U2 exit latency), but it should be harmless.
+ */
+static int usb_disable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
+ enum usb3_link_state state)
+{
+ int feature;
+
+ switch (state) {
+ case USB3_LPM_U1:
+ feature = USB_PORT_FEAT_U1_TIMEOUT;
+ break;
+ case USB3_LPM_U2:
+ feature = USB_PORT_FEAT_U2_TIMEOUT;
+ break;
+ default:
+ dev_warn(&udev->dev, "%s: Can't disable non-U1 or U2 state.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (usb_set_lpm_timeout(udev, state, 0))
+ return -EBUSY;
+
+ usb_set_device_initiated_lpm(udev, state, false);
+
+ if (hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state))
+ dev_warn(&udev->dev, "Could not disable xHCI %s timeout, "
+ "bus schedule bandwidth may be impacted.\n",
+ usb3_lpm_names[state]);
+ return 0;
+}
+
+/*
+ * Disable hub-initiated and device-initiated U1 and U2 entry.
+ * Caller must own the bandwidth_mutex.
+ *
+ * This will call usb_enable_lpm() on failure, which will decrement
+ * lpm_disable_count, and will re-enable LPM if lpm_disable_count reaches zero.
+ */
+int usb_disable_lpm(struct usb_device *udev)
+{
+ struct usb_hcd *hcd;
+
+ if (!udev || !udev->parent ||
+ udev->speed != USB_SPEED_SUPER ||
+ !udev->lpm_capable)
+ return 0;
+
+ hcd = bus_to_hcd(udev->bus);
+ if (!hcd || !hcd->driver->disable_usb3_lpm_timeout)
+ return 0;
+
+ udev->lpm_disable_count++;
+ if ((udev->u1_params.timeout == 0 && udev->u1_params.timeout == 0))
+ return 0;
+
+ /* If LPM is enabled, attempt to disable it. */
+ if (usb_disable_link_state(hcd, udev, USB3_LPM_U1))
+ goto enable_lpm;
+ if (usb_disable_link_state(hcd, udev, USB3_LPM_U2))
+ goto enable_lpm;
+
+ return 0;
+
+enable_lpm:
+ usb_enable_lpm(udev);
+ return -EBUSY;
+}
+EXPORT_SYMBOL_GPL(usb_disable_lpm);
+
+/* Grab the bandwidth_mutex before calling usb_disable_lpm() */
+int usb_unlocked_disable_lpm(struct usb_device *udev)
+{
+ struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+ int ret;
+
+ if (!hcd)
+ return -EINVAL;
+
+ mutex_lock(hcd->bandwidth_mutex);
+ ret = usb_disable_lpm(udev);
+ mutex_unlock(hcd->bandwidth_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(usb_unlocked_disable_lpm);
+
+/*
+ * Attempt to enable device-initiated and hub-initiated U1 and U2 entry. The
+ * xHCI host policy may prevent U1 or U2 from being enabled.
+ *
+ * Other callers may have disabled link PM, so U1 and U2 entry will be disabled
+ * until the lpm_disable_count drops to zero. Caller must own the
+ * bandwidth_mutex.
+ */
+void usb_enable_lpm(struct usb_device *udev)
+{
+ struct usb_hcd *hcd;
+
+ if (!udev || !udev->parent ||
+ udev->speed != USB_SPEED_SUPER ||
+ !udev->lpm_capable)
+ return;
+
+ udev->lpm_disable_count--;
+ hcd = bus_to_hcd(udev->bus);
+ /* Double check that we can both enable and disable LPM.
+ * Device must be configured to accept set feature U1/U2 timeout.
+ */
+ if (!hcd || !hcd->driver->enable_usb3_lpm_timeout ||
+ !hcd->driver->disable_usb3_lpm_timeout)
+ return;
+
+ if (udev->lpm_disable_count > 0)
+ return;
+
+ usb_enable_link_state(hcd, udev, USB3_LPM_U1);
+ usb_enable_link_state(hcd, udev, USB3_LPM_U2);
+}
+EXPORT_SYMBOL_GPL(usb_enable_lpm);
+
+/* Grab the bandwidth_mutex before calling usb_enable_lpm() */
+void usb_unlocked_enable_lpm(struct usb_device *udev)
+{
+ struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
+ if (!hcd)
+ return;
+
+ mutex_lock(hcd->bandwidth_mutex);
+ usb_enable_lpm(udev);
+ mutex_unlock(hcd->bandwidth_mutex);
+}
+EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm);
+
+
#else /* CONFIG_PM */
#define hub_suspend NULL
#define hub_resume NULL
#define hub_reset_resume NULL
+
+int usb_disable_lpm(struct usb_device *udev)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_disable_lpm);
+
+void usb_enable_lpm(struct usb_device *udev) { }
+EXPORT_SYMBOL_GPL(usb_enable_lpm);
+
+int usb_unlocked_disable_lpm(struct usb_device *udev)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_unlocked_disable_lpm);
+
+void usb_unlocked_enable_lpm(struct usb_device *udev) { }
+EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm);
#endif
@@ -3208,9 +3864,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) {
retval = usb_get_bos_descriptor(udev);
if (!retval) {
- if (udev->bos->ext_cap && (USB_LPM_SUPPORT &
- le32_to_cpu(udev->bos->ext_cap->bmAttributes)))
- udev->lpm_capable = 1;
+ udev->lpm_capable = usb_device_supports_lpm(udev);
+ usb_set_lpm_parameters(udev);
}
}
@@ -4042,11 +4697,22 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
goto done;
mutex_lock(hcd->bandwidth_mutex);
+ /* Disable LPM while we reset the device and reinstall the alt settings.
+ * Device-initiated LPM settings, and system exit latency settings are
+ * cleared when the device is reset, so we have to set them up again.
+ */
+ ret = usb_disable_lpm(udev);
+ if (ret) {
+ dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__);
+ mutex_unlock(hcd->bandwidth_mutex);
+ goto done;
+ }
ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL);
if (ret < 0) {
dev_warn(&udev->dev,
"Busted HC? Not enough HCD resources for "
"old configuration.\n");
+ usb_enable_lpm(udev);
mutex_unlock(hcd->bandwidth_mutex);
goto re_enumerate;
}
@@ -4058,6 +4724,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
dev_err(&udev->dev,
"can't restore configuration #%d (error=%d)\n",
udev->actconfig->desc.bConfigurationValue, ret);
+ usb_enable_lpm(udev);
mutex_unlock(hcd->bandwidth_mutex);
goto re_enumerate;
}
@@ -4096,10 +4763,13 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
desc->bInterfaceNumber,
desc->bAlternateSetting,
ret);
+ usb_unlocked_enable_lpm(udev);
goto re_enumerate;
}
}
+ /* Now that the alt settings are re-installed, enable LPM. */
+ usb_unlocked_enable_lpm(udev);
done:
return 0;
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
deleted file mode 100644
index d2b9af59cba9..000000000000
--- a/drivers/usb/core/inode.c
+++ /dev/null
@@ -1,748 +0,0 @@
-/*****************************************************************************/
-
-/*
- * inode.c -- Inode/Dentry functions for the USB device file system.
- *
- * Copyright (C) 2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
- * Copyright (C) 2001,2002,2004 Greg Kroah-Hartman (greg@kroah.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * History:
- * 0.1 04.01.2000 Created
- * 0.2 10.12.2001 converted to use the vfs layer better
- */
-
-/*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/mount.h>
-#include <linux/pagemap.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/usb.h>
-#include <linux/namei.h>
-#include <linux/usbdevice_fs.h>
-#include <linux/parser.h>
-#include <linux/notifier.h>
-#include <linux/seq_file.h>
-#include <linux/usb/hcd.h>
-#include <asm/byteorder.h>
-#include "usb.h"
-
-#define USBFS_DEFAULT_DEVMODE (S_IWUSR | S_IRUGO)
-#define USBFS_DEFAULT_BUSMODE (S_IXUGO | S_IRUGO)
-#define USBFS_DEFAULT_LISTMODE S_IRUGO
-
-static const struct file_operations default_file_operations;
-static struct vfsmount *usbfs_mount;
-static int usbfs_mount_count; /* = 0 */
-
-static struct dentry *devices_usbfs_dentry;
-static int num_buses; /* = 0 */
-
-static uid_t devuid; /* = 0 */
-static uid_t busuid; /* = 0 */
-static uid_t listuid; /* = 0 */
-static gid_t devgid; /* = 0 */
-static gid_t busgid; /* = 0 */
-static gid_t listgid; /* = 0 */
-static umode_t devmode = USBFS_DEFAULT_DEVMODE;
-static umode_t busmode = USBFS_DEFAULT_BUSMODE;
-static umode_t listmode = USBFS_DEFAULT_LISTMODE;
-
-static int usbfs_show_options(struct seq_file *seq, struct dentry *root)
-{
- if (devuid != 0)
- seq_printf(seq, ",devuid=%u", devuid);
- if (devgid != 0)
- seq_printf(seq, ",devgid=%u", devgid);
- if (devmode != USBFS_DEFAULT_DEVMODE)
- seq_printf(seq, ",devmode=%o", devmode);
- if (busuid != 0)
- seq_printf(seq, ",busuid=%u", busuid);
- if (busgid != 0)
- seq_printf(seq, ",busgid=%u", busgid);
- if (busmode != USBFS_DEFAULT_BUSMODE)
- seq_printf(seq, ",busmode=%o", busmode);
- if (listuid != 0)
- seq_printf(seq, ",listuid=%u", listuid);
- if (listgid != 0)
- seq_printf(seq, ",listgid=%u", listgid);
- if (listmode != USBFS_DEFAULT_LISTMODE)
- seq_printf(seq, ",listmode=%o", listmode);
-
- return 0;
-}
-
-enum {
- Opt_devuid, Opt_devgid, Opt_devmode,
- Opt_busuid, Opt_busgid, Opt_busmode,
- Opt_listuid, Opt_listgid, Opt_listmode,
- Opt_err,
-};
-
-static const match_table_t tokens = {
- {Opt_devuid, "devuid=%u"},
- {Opt_devgid, "devgid=%u"},
- {Opt_devmode, "devmode=%o"},
- {Opt_busuid, "busuid=%u"},
- {Opt_busgid, "busgid=%u"},
- {Opt_busmode, "busmode=%o"},
- {Opt_listuid, "listuid=%u"},
- {Opt_listgid, "listgid=%u"},
- {Opt_listmode, "listmode=%o"},
- {Opt_err, NULL}
-};
-
-static int parse_options(struct super_block *s, char *data)
-{
- char *p;
- int option;
-
- /* (re)set to defaults. */
- devuid = 0;
- busuid = 0;
- listuid = 0;
- devgid = 0;
- busgid = 0;
- listgid = 0;
- devmode = USBFS_DEFAULT_DEVMODE;
- busmode = USBFS_DEFAULT_BUSMODE;
- listmode = USBFS_DEFAULT_LISTMODE;
-
- while ((p = strsep(&data, ",")) != NULL) {
- substring_t args[MAX_OPT_ARGS];
- int token;
- if (!*p)
- continue;
-
- token = match_token(p, tokens, args);
- switch (token) {
- case Opt_devuid:
- if (match_int(&args[0], &option))
- return -EINVAL;
- devuid = option;
- break;
- case Opt_devgid:
- if (match_int(&args[0], &option))
- return -EINVAL;
- devgid = option;
- break;
- case Opt_devmode:
- if (match_octal(&args[0], &option))
- return -EINVAL;
- devmode = option & S_IRWXUGO;
- break;
- case Opt_busuid:
- if (match_int(&args[0], &option))
- return -EINVAL;
- busuid = option;
- break;
- case Opt_busgid:
- if (match_int(&args[0], &option))
- return -EINVAL;
- busgid = option;
- break;
- case Opt_busmode:
- if (match_octal(&args[0], &option))
- return -EINVAL;
- busmode = option & S_IRWXUGO;
- break;
- case Opt_listuid:
- if (match_int(&args[0], &option))
- return -EINVAL;
- listuid = option;
- break;
- case Opt_listgid:
- if (match_int(&args[0], &option))
- return -EINVAL;
- listgid = option;
- break;
- case Opt_listmode:
- if (match_octal(&args[0], &option))
- return -EINVAL;
- listmode = option & S_IRWXUGO;
- break;
- default:
- printk(KERN_ERR "usbfs: unrecognised mount option "
- "\"%s\" or missing value\n", p);
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static void update_special(struct dentry *special)
-{
- special->d_inode->i_uid = listuid;
- special->d_inode->i_gid = listgid;
- special->d_inode->i_mode = S_IFREG | listmode;
-}
-
-static void update_dev(struct dentry *dev)
-{
- dev->d_inode->i_uid = devuid;
- dev->d_inode->i_gid = devgid;
- dev->d_inode->i_mode = S_IFREG | devmode;
-}
-
-static void update_bus(struct dentry *bus)
-{
- struct dentry *dev = NULL;
-
- bus->d_inode->i_uid = busuid;
- bus->d_inode->i_gid = busgid;
- bus->d_inode->i_mode = S_IFDIR | busmode;
-
- mutex_lock(&bus->d_inode->i_mutex);
-
- list_for_each_entry(dev, &bus->d_subdirs, d_u.d_child)
- if (dev->d_inode)
- update_dev(dev);
-
- mutex_unlock(&bus->d_inode->i_mutex);
-}
-
-static void update_sb(struct super_block *sb)
-{
- struct dentry *root = sb->s_root;
- struct dentry *bus = NULL;
-
- if (!root)
- return;
-
- mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_PARENT);
-
- list_for_each_entry(bus, &root->d_subdirs, d_u.d_child) {
- if (bus->d_inode) {
- switch (S_IFMT & bus->d_inode->i_mode) {
- case S_IFDIR:
- update_bus(bus);
- break;
- case S_IFREG:
- update_special(bus);
- break;
- default:
- printk(KERN_WARNING "usbfs: Unknown node %s "
- "mode %x found on remount!\n",
- bus->d_name.name, bus->d_inode->i_mode);
- break;
- }
- }
- }
-
- mutex_unlock(&root->d_inode->i_mutex);
-}
-
-static int remount(struct super_block *sb, int *flags, char *data)
-{
- /* If this is not a real mount,
- * i.e. it's a simple_pin_fs from create_special_files,
- * then ignore it.
- */
- if (*flags & MS_KERNMOUNT)
- return 0;
-
- if (parse_options(sb, data)) {
- printk(KERN_WARNING "usbfs: mount parameter error.\n");
- return -EINVAL;
- }
-
- if (usbfs_mount)
- update_sb(usbfs_mount->mnt_sb);
-
- return 0;
-}
-
-static struct inode *usbfs_get_inode (struct super_block *sb, umode_t mode, dev_t dev)
-{
- struct inode *inode = new_inode(sb);
-
- if (inode) {
- inode->i_ino = get_next_ino();
- inode_init_owner(inode, NULL, mode);
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- switch (mode & S_IFMT) {
- default:
- init_special_inode(inode, mode, dev);
- break;
- case S_IFREG:
- inode->i_fop = &default_file_operations;
- break;
- case S_IFDIR:
- inode->i_op = &simple_dir_inode_operations;
- inode->i_fop = &simple_dir_operations;
-
- /* directory inodes start off with i_nlink == 2 (for "." entry) */
- inc_nlink(inode);
- break;
- }
- }
- return inode;
-}
-
-/* SMP-safe */
-static int usbfs_mknod (struct inode *dir, struct dentry *dentry, umode_t mode,
- dev_t dev)
-{
- struct inode *inode = usbfs_get_inode(dir->i_sb, mode, dev);
- int error = -EPERM;
-
- if (dentry->d_inode)
- return -EEXIST;
-
- if (inode) {
- d_instantiate(dentry, inode);
- dget(dentry);
- error = 0;
- }
- return error;
-}
-
-static int usbfs_mkdir (struct inode *dir, struct dentry *dentry, umode_t mode)
-{
- int res;
-
- mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
- res = usbfs_mknod (dir, dentry, mode, 0);
- if (!res)
- inc_nlink(dir);
- return res;
-}
-
-static int usbfs_create (struct inode *dir, struct dentry *dentry, umode_t mode)
-{
- mode = (mode & S_IALLUGO) | S_IFREG;
- return usbfs_mknod (dir, dentry, mode, 0);
-}
-
-static inline int usbfs_positive (struct dentry *dentry)
-{
- return dentry->d_inode && !d_unhashed(dentry);
-}
-
-static int usbfs_empty (struct dentry *dentry)
-{
- struct list_head *list;
-
- spin_lock(&dentry->d_lock);
- list_for_each(list, &dentry->d_subdirs) {
- struct dentry *de = list_entry(list, struct dentry, d_u.d_child);
-
- spin_lock_nested(&de->d_lock, DENTRY_D_LOCK_NESTED);
- if (usbfs_positive(de)) {
- spin_unlock(&de->d_lock);
- spin_unlock(&dentry->d_lock);
- return 0;
- }
- spin_unlock(&de->d_lock);
- }
- spin_unlock(&dentry->d_lock);
- return 1;
-}
-
-static int usbfs_unlink (struct inode *dir, struct dentry *dentry)
-{
- struct inode *inode = dentry->d_inode;
- mutex_lock(&inode->i_mutex);
- drop_nlink(dentry->d_inode);
- dput(dentry);
- mutex_unlock(&inode->i_mutex);
- d_delete(dentry);
- return 0;
-}
-
-static int usbfs_rmdir(struct inode *dir, struct dentry *dentry)
-{
- int error = -ENOTEMPTY;
- struct inode * inode = dentry->d_inode;
-
- mutex_lock(&inode->i_mutex);
- dentry_unhash(dentry);
- if (usbfs_empty(dentry)) {
- dont_mount(dentry);
- drop_nlink(dentry->d_inode);
- drop_nlink(dentry->d_inode);
- dput(dentry);
- inode->i_flags |= S_DEAD;
- drop_nlink(dir);
- error = 0;
- }
- mutex_unlock(&inode->i_mutex);
- if (!error)
- d_delete(dentry);
- return error;
-}
-
-
-/* default file operations */
-static ssize_t default_read_file (struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- return 0;
-}
-
-static ssize_t default_write_file (struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- return count;
-}
-
-static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
-{
- loff_t retval = -EINVAL;
-
- mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
- switch(orig) {
- case 0:
- if (offset > 0) {
- file->f_pos = offset;
- retval = file->f_pos;
- }
- break;
- case 1:
- if ((offset + file->f_pos) > 0) {
- file->f_pos += offset;
- retval = file->f_pos;
- }
- break;
- default:
- break;
- }
- mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
- return retval;
-}
-
-static const struct file_operations default_file_operations = {
- .read = default_read_file,
- .write = default_write_file,
- .open = simple_open,
- .llseek = default_file_lseek,
-};
-
-static const struct super_operations usbfs_ops = {
- .statfs = simple_statfs,
- .drop_inode = generic_delete_inode,
- .remount_fs = remount,
- .show_options = usbfs_show_options,
-};
-
-static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
-{
- struct inode *inode;
-
- sb->s_blocksize = PAGE_CACHE_SIZE;
- sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
- sb->s_magic = USBDEVICE_SUPER_MAGIC;
- sb->s_op = &usbfs_ops;
- sb->s_time_gran = 1;
- inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0);
- sb->s_root = d_make_root(inode);
- if (!sb->s_root) {
- dbg("%s: could not get root dentry!",__func__);
- return -ENOMEM;
- }
- return 0;
-}
-
-/*
- * fs_create_by_name - create a file, given a name
- * @name: name of file
- * @mode: type of file
- * @parent: dentry of directory to create it in
- * @dentry: resulting dentry of file
- *
- * This function handles both regular files and directories.
- */
-static int fs_create_by_name (const char *name, umode_t mode,
- struct dentry *parent, struct dentry **dentry)
-{
- int error = 0;
-
- /* If the parent is not specified, we create it in the root.
- * We need the root dentry to do this, which is in the super
- * block. A pointer to that is in the struct vfsmount that we
- * have around.
- */
- if (!parent ) {
- if (usbfs_mount)
- parent = usbfs_mount->mnt_root;
- }
-
- if (!parent) {
- dbg("Ah! can not find a parent!");
- return -EFAULT;
- }
-
- *dentry = NULL;
- mutex_lock(&parent->d_inode->i_mutex);
- *dentry = lookup_one_len(name, parent, strlen(name));
- if (!IS_ERR(*dentry)) {
- if (S_ISDIR(mode))
- error = usbfs_mkdir (parent->d_inode, *dentry, mode);
- else
- error = usbfs_create (parent->d_inode, *dentry, mode);
- } else
- error = PTR_ERR(*dentry);
- mutex_unlock(&parent->d_inode->i_mutex);
-
- return error;
-}
-
-static struct dentry *fs_create_file (const char *name, umode_t mode,
- struct dentry *parent, void *data,
- const struct file_operations *fops,
- uid_t uid, gid_t gid)
-{
- struct dentry *dentry;
- int error;
-
- dbg("creating file '%s'",name);
-
- error = fs_create_by_name (name, mode, parent, &dentry);
- if (error) {
- dentry = NULL;
- } else {
- if (dentry->d_inode) {
- if (data)
- dentry->d_inode->i_private = data;
- if (fops)
- dentry->d_inode->i_fop = fops;
- dentry->d_inode->i_uid = uid;
- dentry->d_inode->i_gid = gid;
- }
- }
-
- return dentry;
-}
-
-static void fs_remove_file (struct dentry *dentry)
-{
- struct dentry *parent = dentry->d_parent;
-
- if (!parent || !parent->d_inode)
- return;
-
- mutex_lock_nested(&parent->d_inode->i_mutex, I_MUTEX_PARENT);
- if (usbfs_positive(dentry)) {
- if (dentry->d_inode) {
- if (S_ISDIR(dentry->d_inode->i_mode))
- usbfs_rmdir(parent->d_inode, dentry);
- else
- usbfs_unlink(parent->d_inode, dentry);
- dput(dentry);
- }
- }
- mutex_unlock(&parent->d_inode->i_mutex);
-}
-
-/* --------------------------------------------------------------------- */
-
-static struct dentry *usb_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
-{
- return mount_single(fs_type, flags, data, usbfs_fill_super);
-}
-
-static struct file_system_type usb_fs_type = {
- .owner = THIS_MODULE,
- .name = "usbfs",
- .mount = usb_mount,
- .kill_sb = kill_litter_super,
-};
-
-/* --------------------------------------------------------------------- */
-
-static int create_special_files (void)
-{
- struct dentry *parent;
- int retval;
-
- /* create the devices special file */
- retval = simple_pin_fs(&usb_fs_type, &usbfs_mount, &usbfs_mount_count);
- if (retval) {
- printk(KERN_ERR "Unable to get usbfs mount\n");
- goto exit;
- }
-
- parent = usbfs_mount->mnt_root;
- devices_usbfs_dentry = fs_create_file ("devices",
- listmode | S_IFREG, parent,
- NULL, &usbfs_devices_fops,
- listuid, listgid);
- if (devices_usbfs_dentry == NULL) {
- printk(KERN_ERR "Unable to create devices usbfs file\n");
- retval = -ENODEV;
- goto error_clean_mounts;
- }
-
- goto exit;
-
-error_clean_mounts:
- simple_release_fs(&usbfs_mount, &usbfs_mount_count);
-exit:
- return retval;
-}
-
-static void remove_special_files (void)
-{
- if (devices_usbfs_dentry)
- fs_remove_file (devices_usbfs_dentry);
- devices_usbfs_dentry = NULL;
- simple_release_fs(&usbfs_mount, &usbfs_mount_count);
-}
-
-void usbfs_update_special (void)
-{
- struct inode *inode;
-
- if (devices_usbfs_dentry) {
- inode = devices_usbfs_dentry->d_inode;
- if (inode)
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- }
-}
-
-static void usbfs_add_bus(struct usb_bus *bus)
-{
- struct dentry *parent;
- char name[8];
- int retval;
-
- /* create the special files if this is the first bus added */
- if (num_buses == 0) {
- retval = create_special_files();
- if (retval)
- return;
- }
- ++num_buses;
-
- sprintf (name, "%03d", bus->busnum);
-
- parent = usbfs_mount->mnt_root;
- bus->usbfs_dentry = fs_create_file (name, busmode | S_IFDIR, parent,
- bus, NULL, busuid, busgid);
- if (bus->usbfs_dentry == NULL) {
- printk(KERN_ERR "Error creating usbfs bus entry\n");
- return;
- }
-}
-
-static void usbfs_remove_bus(struct usb_bus *bus)
-{
- if (bus->usbfs_dentry) {
- fs_remove_file (bus->usbfs_dentry);
- bus->usbfs_dentry = NULL;
- }
-
- --num_buses;
- if (num_buses <= 0) {
- remove_special_files();
- num_buses = 0;
- }
-}
-
-static void usbfs_add_device(struct usb_device *dev)
-{
- char name[8];
- int i;
- int i_size;
-
- sprintf (name, "%03d", dev->devnum);
- dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG,
- dev->bus->usbfs_dentry, dev,
- &usbdev_file_operations,
- devuid, devgid);
- if (dev->usbfs_dentry == NULL) {
- printk(KERN_ERR "Error creating usbfs device entry\n");
- return;
- }
-
- /* Set the size of the device's file to be
- * equal to the size of the device descriptors. */
- i_size = sizeof (struct usb_device_descriptor);
- for (i = 0; i < dev->descriptor.bNumConfigurations; ++i) {
- struct usb_config_descriptor *config =
- (struct usb_config_descriptor *)dev->rawdescriptors[i];
- i_size += le16_to_cpu(config->wTotalLength);
- }
- if (dev->usbfs_dentry->d_inode)
- dev->usbfs_dentry->d_inode->i_size = i_size;
-}
-
-static void usbfs_remove_device(struct usb_device *dev)
-{
- if (dev->usbfs_dentry) {
- fs_remove_file (dev->usbfs_dentry);
- dev->usbfs_dentry = NULL;
- }
-}
-
-static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev)
-{
- switch (action) {
- case USB_DEVICE_ADD:
- usbfs_add_device(dev);
- break;
- case USB_DEVICE_REMOVE:
- usbfs_remove_device(dev);
- break;
- case USB_BUS_ADD:
- usbfs_add_bus(dev);
- break;
- case USB_BUS_REMOVE:
- usbfs_remove_bus(dev);
- }
-
- usbfs_update_special();
- usbfs_conn_disc_event();
- return NOTIFY_OK;
-}
-
-static struct notifier_block usbfs_nb = {
- .notifier_call = usbfs_notify,
-};
-
-/* --------------------------------------------------------------------- */
-
-static struct proc_dir_entry *usbdir = NULL;
-
-int __init usbfs_init(void)
-{
- int retval;
-
- retval = register_filesystem(&usb_fs_type);
- if (retval)
- return retval;
-
- usb_register_notify(&usbfs_nb);
-
- /* create mount point for usbfs */
- usbdir = proc_mkdir("bus/usb", NULL);
-
- return 0;
-}
-
-void usbfs_cleanup(void)
-{
- usb_unregister_notify(&usbfs_nb);
- unregister_filesystem(&usb_fs_type);
- if (usbdir)
- remove_proc_entry("bus/usb", NULL);
-}
-
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index ca717da3be95..b548cf1dbc62 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1308,10 +1308,19 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
* Remove the current alt setting and add the new alt setting.
*/
mutex_lock(hcd->bandwidth_mutex);
+ /* Disable LPM, and re-enable it once the new alt setting is installed,
+ * so that the xHCI driver can recalculate the U1/U2 timeouts.
+ */
+ if (usb_disable_lpm(dev)) {
+ dev_err(&iface->dev, "%s Failed to disable LPM\n.", __func__);
+ mutex_unlock(hcd->bandwidth_mutex);
+ return -ENOMEM;
+ }
ret = usb_hcd_alloc_bandwidth(dev, NULL, iface->cur_altsetting, alt);
if (ret < 0) {
dev_info(&dev->dev, "Not enough bandwidth for altsetting %d\n",
alternate);
+ usb_enable_lpm(dev);
mutex_unlock(hcd->bandwidth_mutex);
return ret;
}
@@ -1334,6 +1343,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
} else if (ret < 0) {
/* Re-instate the old alt setting */
usb_hcd_alloc_bandwidth(dev, NULL, alt, iface->cur_altsetting);
+ usb_enable_lpm(dev);
mutex_unlock(hcd->bandwidth_mutex);
return ret;
}
@@ -1354,6 +1364,9 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
iface->cur_altsetting = alt;
+ /* Now that the interface is installed, re-enable LPM. */
+ usb_unlocked_enable_lpm(dev);
+
/* If the interface only has one altsetting and the device didn't
* accept the request, we attempt to carry out the equivalent action
* by manually clearing the HALT feature for each endpoint in the
@@ -1437,6 +1450,14 @@ int usb_reset_configuration(struct usb_device *dev)
config = dev->actconfig;
retval = 0;
mutex_lock(hcd->bandwidth_mutex);
+ /* Disable LPM, and re-enable it once the configuration is reset, so
+ * that the xHCI driver can recalculate the U1/U2 timeouts.
+ */
+ if (usb_disable_lpm(dev)) {
+ dev_err(&dev->dev, "%s Failed to disable LPM\n.", __func__);
+ mutex_unlock(hcd->bandwidth_mutex);
+ return -ENOMEM;
+ }
/* Make sure we have enough bandwidth for each alternate setting 0 */
for (i = 0; i < config->desc.bNumInterfaces; i++) {
struct usb_interface *intf = config->interface[i];
@@ -1465,6 +1486,7 @@ reset_old_alts:
usb_hcd_alloc_bandwidth(dev, NULL,
alt, intf->cur_altsetting);
}
+ usb_enable_lpm(dev);
mutex_unlock(hcd->bandwidth_mutex);
return retval;
}
@@ -1502,6 +1524,8 @@ reset_old_alts:
create_intf_ep_devs(intf);
}
}
+ /* Now that the interfaces are installed, re-enable LPM. */
+ usb_unlocked_enable_lpm(dev);
return 0;
}
EXPORT_SYMBOL_GPL(usb_reset_configuration);
@@ -1763,8 +1787,18 @@ free_interfaces:
* this call fails, the device state is unchanged.
*/
mutex_lock(hcd->bandwidth_mutex);
+ /* Disable LPM, and re-enable it once the new configuration is
+ * installed, so that the xHCI driver can recalculate the U1/U2
+ * timeouts.
+ */
+ if (usb_disable_lpm(dev)) {
+ dev_err(&dev->dev, "%s Failed to disable LPM\n.", __func__);
+ mutex_unlock(hcd->bandwidth_mutex);
+ return -ENOMEM;
+ }
ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
if (ret < 0) {
+ usb_enable_lpm(dev);
mutex_unlock(hcd->bandwidth_mutex);
usb_autosuspend_device(dev);
goto free_interfaces;
@@ -1784,6 +1818,7 @@ free_interfaces:
if (!cp) {
usb_set_device_state(dev, USB_STATE_ADDRESS);
usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
+ usb_enable_lpm(dev);
mutex_unlock(hcd->bandwidth_mutex);
usb_autosuspend_device(dev);
goto free_interfaces;
@@ -1838,6 +1873,9 @@ free_interfaces:
!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
+ /* Now that the interfaces are installed, re-enable LPM. */
+ usb_unlocked_enable_lpm(dev);
+
/* Now that all the interfaces are set up, register them
* to trigger binding of drivers to interfaces. probe()
* routines may install different altsettings and may
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 4c65eb6a867a..32d3adc315f5 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -123,6 +123,9 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Guillemot Webcam Hercules Dualpix Exchange*/
{ USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* Midiman M-Audio Keystation 88es */
+ { USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME },
+
/* M-Systems Flash Disk Pioneers */
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 566d9f94f735..9a56e3adf476 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -73,7 +73,7 @@ set_bConfigurationValue(struct device *dev, struct device_attribute *attr,
return (value < 0) ? value : count;
}
-static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR,
+static DEVICE_ATTR_IGNORE_LOCKDEP(bConfigurationValue, S_IRUGO | S_IWUSR,
show_bConfigurationValue, set_bConfigurationValue);
/* String fields */
@@ -595,7 +595,7 @@ static ssize_t usb_dev_authorized_store(struct device *dev,
return result < 0? result : size;
}
-static DEVICE_ATTR(authorized, 0644,
+static DEVICE_ATTR_IGNORE_LOCKDEP(authorized, 0644,
usb_dev_authorized_show, usb_dev_authorized_store);
/* "Safely remove a device" */
@@ -618,7 +618,7 @@ static ssize_t usb_remove_store(struct device *dev,
usb_unlock_device(udev);
return rc;
}
-static DEVICE_ATTR(remove, 0200, NULL, usb_remove_store);
+static DEVICE_ATTR_IGNORE_LOCKDEP(remove, 0200, NULL, usb_remove_store);
static struct attribute *dev_attrs[] = {
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index cd9b3a2cd8a7..9d912bfdcffe 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -681,6 +681,27 @@ void usb_unpoison_urb(struct urb *urb)
EXPORT_SYMBOL_GPL(usb_unpoison_urb);
/**
+ * usb_block_urb - reliably prevent further use of an URB
+ * @urb: pointer to URB to be blocked, may be NULL
+ *
+ * After the routine has run, attempts to resubmit the URB will fail
+ * with error -EPERM. Thus even if the URB's completion handler always
+ * tries to resubmit, it will not succeed and the URB will become idle.
+ *
+ * The URB must not be deallocated while this routine is running. In
+ * particular, when a driver calls this routine, it must insure that the
+ * completion handler cannot deallocate the URB.
+ */
+void usb_block_urb(struct urb *urb)
+{
+ if (!urb)
+ return;
+
+ atomic_inc(&urb->reject);
+}
+EXPORT_SYMBOL_GPL(usb_block_urb);
+
+/**
* usb_kill_anchored_urbs - cancel transfer requests en masse
* @anchor: anchor the requests are bound to
*
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c
new file mode 100644
index 000000000000..8947b203d5a4
--- /dev/null
+++ b/drivers/usb/core/usb-acpi.c
@@ -0,0 +1,117 @@
+/*
+ * USB-ACPI glue code
+ *
+ * Copyright 2012 Red Hat <mjg@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, version 2.
+ *
+ */
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/acpi.h>
+#include <linux/pci.h>
+#include <acpi/acpi_bus.h>
+
+#include "usb.h"
+
+static int usb_acpi_check_upc(struct usb_device *udev, acpi_handle handle)
+{
+ acpi_status status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *upc;
+ int ret = 0;
+
+ status = acpi_evaluate_object(handle, "_UPC", NULL, &buffer);
+
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ upc = buffer.pointer;
+
+ if (!upc || (upc->type != ACPI_TYPE_PACKAGE)
+ || upc->package.count != 4) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (upc->package.elements[0].integer.value)
+ udev->removable = USB_DEVICE_REMOVABLE;
+ else
+ udev->removable = USB_DEVICE_FIXED;
+
+out:
+ kfree(upc);
+ return ret;
+}
+
+static int usb_acpi_check_pld(struct usb_device *udev, acpi_handle handle)
+{
+ acpi_status status;
+ struct acpi_pld pld;
+
+ status = acpi_get_physical_device_location(handle, &pld);
+
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ if (pld.user_visible)
+ udev->removable = USB_DEVICE_REMOVABLE;
+ else
+ udev->removable = USB_DEVICE_FIXED;
+
+ return 0;
+}
+
+static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
+{
+ struct usb_device *udev;
+ struct device *parent;
+ acpi_handle *parent_handle;
+
+ if (!is_usb_device(dev))
+ return -ENODEV;
+
+ udev = to_usb_device(dev);
+ parent = dev->parent;
+ parent_handle = DEVICE_ACPI_HANDLE(parent);
+
+ if (!parent_handle)
+ return -ENODEV;
+
+ *handle = acpi_get_child(parent_handle, udev->portnum);
+
+ if (!*handle)
+ return -ENODEV;
+
+ /*
+ * PLD will tell us whether a port is removable to the user or
+ * not. If we don't get an answer from PLD (it's not present
+ * or it's malformed) then try to infer it from UPC. If a
+ * device isn't connectable then it's probably not removable.
+ */
+ if (usb_acpi_check_pld(udev, *handle) != 0)
+ usb_acpi_check_upc(udev, *handle);
+
+ return 0;
+}
+
+static struct acpi_bus_type usb_acpi_bus = {
+ .bus = &usb_bus_type,
+ .find_bridge = NULL,
+ .find_device = usb_acpi_find_device,
+};
+
+int usb_acpi_register(void)
+{
+ return register_acpi_bus_type(&usb_acpi_bus);
+}
+
+void usb_acpi_unregister(void)
+{
+ unregister_acpi_bus_type(&usb_acpi_bus);
+}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index c74ba7bbc748..25d0c61c3f8a 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -1015,6 +1015,7 @@ static int __init usb_init(void)
if (retval)
goto out;
+ usb_acpi_register();
retval = bus_register(&usb_bus_type);
if (retval)
goto bus_register_failed;
@@ -1030,9 +1031,6 @@ static int __init usb_init(void)
retval = usb_devio_init();
if (retval)
goto usb_devio_init_failed;
- retval = usbfs_init();
- if (retval)
- goto fs_init_failed;
retval = usb_hub_init();
if (retval)
goto hub_init_failed;
@@ -1042,8 +1040,6 @@ static int __init usb_init(void)
usb_hub_cleanup();
hub_init_failed:
- usbfs_cleanup();
-fs_init_failed:
usb_devio_cleanup();
usb_devio_init_failed:
usb_deregister(&usbfs_driver);
@@ -1054,6 +1050,7 @@ major_init_failed:
bus_notifier_failed:
bus_unregister(&usb_bus_type);
bus_register_failed:
+ usb_acpi_unregister();
usb_debugfs_cleanup();
out:
return retval;
@@ -1070,12 +1067,12 @@ static void __exit usb_exit(void)
usb_deregister_device_driver(&usb_generic_driver);
usb_major_cleanup();
- usbfs_cleanup();
usb_deregister(&usbfs_driver);
usb_devio_cleanup();
usb_hub_cleanup();
bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
bus_unregister(&usb_bus_type);
+ usb_acpi_unregister();
usb_debugfs_cleanup();
}
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 71648dcbe438..5c5c538ea73d 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -156,3 +156,10 @@ extern void usb_notify_remove_device(struct usb_device *udev);
extern void usb_notify_add_bus(struct usb_bus *ubus);
extern void usb_notify_remove_bus(struct usb_bus *ubus);
+#ifdef CONFIG_ACPI
+extern int usb_acpi_register(void);
+extern void usb_acpi_unregister(void);
+#else
+static inline int usb_acpi_register(void) { return 0; };
+static inline void usb_acpi_unregister(void) { };
+#endif
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index d8f741f9e56e..d13c60f42139 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -4,7 +4,7 @@ config USB_DWC3
select USB_OTG_UTILS
select USB_GADGET_DUALSPEED
select USB_GADGET_SUPERSPEED
- select USB_XHCI_PLATFORM
+ select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
help
Say Y or M here if your system has a Dual Role SuperSpeed
USB controller based on the DesignWare USB3 IP Core.
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 99b58d84553a..1040bdb8dc88 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -410,7 +410,6 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
int ret = -ENOMEM;
- int irq;
void __iomem *regs;
void *mem;
@@ -425,15 +424,28 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
dwc->mem = mem;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
- dev_err(dev, "missing resource\n");
+ dev_err(dev, "missing IRQ\n");
return -ENODEV;
}
+ dwc->xhci_resources[1] = *res;
- dwc->res = res;
-
- res = devm_request_mem_region(dev, res->start, resource_size(res),
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "missing memory resource\n");
+ return -ENODEV;
+ }
+ dwc->xhci_resources[0] = *res;
+ dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
+ DWC3_XHCI_REGS_END;
+
+ /*
+ * Request memory region but exclude xHCI regs,
+ * since it will be requested by the xhci-plat driver.
+ */
+ res = devm_request_mem_region(dev, res->start + DWC3_GLOBALS_REGS_START,
+ resource_size(res) - DWC3_GLOBALS_REGS_START,
dev_name(dev));
if (!res) {
dev_err(dev, "can't request mem region\n");
@@ -446,19 +458,12 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
return -ENOMEM;
}
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "missing IRQ\n");
- return -ENODEV;
- }
-
spin_lock_init(&dwc->lock);
platform_set_drvdata(pdev, dwc);
dwc->regs = regs;
dwc->regs_size = resource_size(res);
dwc->dev = dev;
- dwc->irq = irq;
if (!strncmp("super", maximum_speed, 5))
dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 6c7945b4cad3..f69c877add09 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -51,7 +51,9 @@
#include <linux/usb/gadget.h>
/* Global constants */
+#define DWC3_EP0_BOUNCE_SIZE 512
#define DWC3_ENDPOINTS_NUM 32
+#define DWC3_XHCI_RESOURCES_NUM 2
#define DWC3_EVENT_BUFFERS_SIZE PAGE_SIZE
#define DWC3_EVENT_TYPE_MASK 0xfe
@@ -75,6 +77,16 @@
#define DWC3_GSNPSID_MASK 0xffff0000
#define DWC3_GSNPSREV_MASK 0xffff
+/* DWC3 registers memory space boundries */
+#define DWC3_XHCI_REGS_START 0x0
+#define DWC3_XHCI_REGS_END 0x7fff
+#define DWC3_GLOBALS_REGS_START 0xc100
+#define DWC3_GLOBALS_REGS_END 0xc6ff
+#define DWC3_DEVICE_REGS_START 0xc700
+#define DWC3_DEVICE_REGS_END 0xcbff
+#define DWC3_OTG_REGS_START 0xcc00
+#define DWC3_OTG_REGS_END 0xccff
+
/* Global Registers */
#define DWC3_GSBUSCFG0 0xc100
#define DWC3_GSBUSCFG1 0xc104
@@ -183,6 +195,7 @@
#define DWC3_GHWPARAMS1_EN_PWROPT_CLK 1
/* Device Configuration Register */
+#define DWC3_DCFG_LPM_CAP (1 << 22)
#define DWC3_DCFG_DEVADDR(addr) ((addr) << 3)
#define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f)
@@ -272,12 +285,14 @@
#define DWC3_DGCMD_SET_ENDPOINT_NRDY 0x0c
#define DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK 0x10
+#define DWC3_DGCMD_STATUS(n) (((n) >> 15) & 1)
+#define DWC3_DGCMD_CMDACT (1 << 10)
+
/* Device Endpoint Command Register */
#define DWC3_DEPCMD_PARAM_SHIFT 16
#define DWC3_DEPCMD_PARAM(x) ((x) << DWC3_DEPCMD_PARAM_SHIFT)
#define DWC3_DEPCMD_GET_RSC_IDX(x) (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f)
-#define DWC3_DEPCMD_STATUS_MASK (0x0f << 12)
-#define DWC3_DEPCMD_STATUS(x) (((x) & DWC3_DEPCMD_STATUS_MASK) >> 12)
+#define DWC3_DEPCMD_STATUS(x) (((x) >> 15) & 1)
#define DWC3_DEPCMD_HIPRI_FORCERM (1 << 11)
#define DWC3_DEPCMD_CMDACT (1 << 10)
#define DWC3_DEPCMD_CMDIOC (1 << 8)
@@ -361,7 +376,6 @@ struct dwc3_ep {
dma_addr_t trb_pool_dma;
u32 free_slot;
u32 busy_slot;
- const struct usb_endpoint_descriptor *desc;
const struct usb_ss_ep_comp_descriptor *comp_desc;
struct dwc3 *dwc;
@@ -561,6 +575,11 @@ struct dwc3_request {
* @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
* @needs_fifo_resize: not all users might want fifo resizing, flag it
* @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes.
+ * @isoch_delay: wValue from Set Isochronous Delay request;
+ * @u2sel: parameter from Set SEL request.
+ * @u2pel: parameter from Set SEL request.
+ * @u1sel: parameter from Set SEL request.
+ * @u1pel: parameter from Set SEL request.
* @ep0_next_event: hold the next expected event
* @ep0state: state of endpoint zero
* @link_state: link state
@@ -583,7 +602,7 @@ struct dwc3 {
struct device *dev;
struct platform_device *xhci;
- struct resource *res;
+ struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM];
struct dwc3_event_buffer **ev_buffs;
struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM];
@@ -594,8 +613,6 @@ struct dwc3 {
void __iomem *regs;
size_t regs_size;
- int irq;
-
u32 num_event_buffers;
u32 u1u2;
u32 maximum_speed;
@@ -609,6 +626,10 @@ struct dwc3 {
#define DWC3_REVISION_185A 0x5533185a
#define DWC3_REVISION_188A 0x5533188a
#define DWC3_REVISION_190A 0x5533190a
+#define DWC3_REVISION_200A 0x5533200a
+#define DWC3_REVISION_202A 0x5533202a
+#define DWC3_REVISION_210A 0x5533210a
+#define DWC3_REVISION_220A 0x5533220a
unsigned is_selfpowered:1;
unsigned three_stage_setup:1;
@@ -625,7 +646,14 @@ struct dwc3 {
enum dwc3_link_state link_state;
enum dwc3_device_state dev_state;
+ u16 isoch_delay;
+ u16 u2sel;
+ u16 u2pel;
+ u8 u1sel;
+ u8 u1pel;
+
u8 speed;
+
void *mem;
struct dwc3_hwparams hwparams;
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index d7d9c0ec9515..479dc047da3a 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -49,7 +49,6 @@
#include <linux/of.h>
#include "core.h"
-#include "io.h"
/*
* All these registers belong to OMAP's Wrapper around the
@@ -143,6 +142,17 @@ struct dwc3_omap {
u32 dma_status:1;
};
+static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
+{
+ return readl(base + offset);
+}
+
+static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
+{
+ writel(value, base + offset);
+}
+
+
static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
{
struct dwc3_omap *omap = _omap;
@@ -150,7 +160,7 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
spin_lock(&omap->lock);
- reg = dwc3_readl(omap->base, USBOTGSS_IRQSTATUS_1);
+ reg = dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_1);
if (reg & USBOTGSS_IRQ1_DMADISABLECLR) {
dev_dbg(omap->dev, "DMA Disable was Cleared\n");
@@ -184,10 +194,10 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
if (reg & USBOTGSS_IRQ1_IDPULLUP_FALL)
dev_dbg(omap->dev, "IDPULLUP Fall\n");
- dwc3_writel(omap->base, USBOTGSS_IRQSTATUS_1, reg);
+ dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_1, reg);
- reg = dwc3_readl(omap->base, USBOTGSS_IRQSTATUS_0);
- dwc3_writel(omap->base, USBOTGSS_IRQSTATUS_0, reg);
+ reg = dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_0);
+ dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_0, reg);
spin_unlock(&omap->lock);
@@ -270,7 +280,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
omap->base = base;
omap->dwc3 = dwc3;
- reg = dwc3_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
+ reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
utmi_mode = of_get_property(node, "utmi-mode", &size);
if (utmi_mode && size == sizeof(*utmi_mode)) {
@@ -293,10 +303,10 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
}
}
- dwc3_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
+ dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
/* check the DMA Status */
- reg = dwc3_readl(omap->base, USBOTGSS_SYSCONFIG);
+ reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE);
/* Set No-Idle and No-Standby */
@@ -306,7 +316,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
reg |= (USBOTGSS_SYSCONFIG_STANDBYMODE(USBOTGSS_STANDBYMODE_NO_STANDBY)
| USBOTGSS_SYSCONFIG_IDLEMODE(USBOTGSS_IDLEMODE_NO_IDLE));
- dwc3_writel(omap->base, USBOTGSS_SYSCONFIG, reg);
+ dwc3_omap_writel(omap->base, USBOTGSS_SYSCONFIG, reg);
ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0,
"dwc3-omap", omap);
@@ -318,7 +328,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
/* enable all IRQs */
reg = USBOTGSS_IRQO_COREIRQ_ST;
- dwc3_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
+ dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
reg = (USBOTGSS_IRQ1_OEVT |
USBOTGSS_IRQ1_DRVVBUS_RISE |
@@ -330,7 +340,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
USBOTGSS_IRQ1_DISCHRGVBUS_FALL |
USBOTGSS_IRQ1_IDPULLUP_FALL);
- dwc3_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
+ dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
ret = platform_device_add_resources(dwc3, pdev->resource,
pdev->num_resources);
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 3584a169886f..9e8a3dce69fd 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -179,7 +179,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
int ret;
spin_lock_irqsave(&dwc->lock, flags);
- if (!dep->desc) {
+ if (!dep->endpoint.desc) {
dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n",
request, dep->name);
ret = -ESHUTDOWN;
@@ -261,6 +261,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
{
struct dwc3_ep *dep;
u32 recip;
+ u32 reg;
u16 usb_status = 0;
__le16 *response_pkt;
@@ -268,10 +269,18 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
switch (recip) {
case USB_RECIP_DEVICE:
/*
- * We are self-powered. U1/U2/LTM will be set later
- * once we handle this states. RemoteWakeup is 0 on SS
+ * LTM will be set once we know how to set this in HW.
*/
usb_status |= dwc->is_selfpowered << USB_DEVICE_SELF_POWERED;
+
+ if (dwc->speed == DWC3_DSTS_SUPERSPEED) {
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ if (reg & DWC3_DCTL_INITU1ENA)
+ usb_status |= 1 << USB_DEV_STAT_U1_ENABLED;
+ if (reg & DWC3_DCTL_INITU2ENA)
+ usb_status |= 1 << USB_DEV_STAT_U2_ENABLED;
+ }
+
break;
case USB_RECIP_INTERFACE:
@@ -312,6 +321,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
u32 recip;
u32 wValue;
u32 wIndex;
+ u32 reg;
int ret;
wValue = le16_to_cpu(ctrl->wValue);
@@ -320,29 +330,43 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
switch (recip) {
case USB_RECIP_DEVICE:
+ switch (wValue) {
+ case USB_DEVICE_REMOTE_WAKEUP:
+ break;
/*
* 9.4.1 says only only for SS, in AddressState only for
* default control pipe
*/
- switch (wValue) {
case USB_DEVICE_U1_ENABLE:
- case USB_DEVICE_U2_ENABLE:
- case USB_DEVICE_LTM_ENABLE:
if (dwc->dev_state != DWC3_CONFIGURED_STATE)
return -EINVAL;
if (dwc->speed != DWC3_DSTS_SUPERSPEED)
return -EINVAL;
- }
- /* XXX add U[12] & LTM */
- switch (wValue) {
- case USB_DEVICE_REMOTE_WAKEUP:
- break;
- case USB_DEVICE_U1_ENABLE:
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ if (set)
+ reg |= DWC3_DCTL_INITU1ENA;
+ else
+ reg &= ~DWC3_DCTL_INITU1ENA;
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
break;
+
case USB_DEVICE_U2_ENABLE:
+ if (dwc->dev_state != DWC3_CONFIGURED_STATE)
+ return -EINVAL;
+ if (dwc->speed != DWC3_DSTS_SUPERSPEED)
+ return -EINVAL;
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ if (set)
+ reg |= DWC3_DCTL_INITU2ENA;
+ else
+ reg &= ~DWC3_DCTL_INITU2ENA;
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
break;
+
case USB_DEVICE_LTM_ENABLE:
+ return -EINVAL;
break;
case USB_DEVICE_TEST_MODE:
@@ -469,6 +493,107 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
return ret;
}
+static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req)
+{
+ struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+
+ u32 param = 0;
+ u32 reg;
+
+ struct timing {
+ u8 u1sel;
+ u8 u1pel;
+ u16 u2sel;
+ u16 u2pel;
+ } __packed timing;
+
+ int ret;
+
+ memcpy(&timing, req->buf, sizeof(timing));
+
+ dwc->u1sel = timing.u1sel;
+ dwc->u1pel = timing.u1pel;
+ dwc->u2sel = timing.u2sel;
+ dwc->u2pel = timing.u2pel;
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ if (reg & DWC3_DCTL_INITU2ENA)
+ param = dwc->u2pel;
+ if (reg & DWC3_DCTL_INITU1ENA)
+ param = dwc->u1pel;
+
+ /*
+ * According to Synopsys Databook, if parameter is
+ * greater than 125, a value of zero should be
+ * programmed in the register.
+ */
+ if (param > 125)
+ param = 0;
+
+ /* now that we have the time, issue DGCMD Set Sel */
+ ret = dwc3_send_gadget_generic_command(dwc,
+ DWC3_DGCMD_SET_PERIODIC_PAR, param);
+ WARN_ON(ret < 0);
+}
+
+static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
+{
+ struct dwc3_ep *dep;
+ u16 wLength;
+ u16 wValue;
+
+ if (dwc->dev_state == DWC3_DEFAULT_STATE)
+ return -EINVAL;
+
+ wValue = le16_to_cpu(ctrl->wValue);
+ wLength = le16_to_cpu(ctrl->wLength);
+
+ if (wLength != 6) {
+ dev_err(dwc->dev, "Set SEL should be 6 bytes, got %d\n",
+ wLength);
+ return -EINVAL;
+ }
+
+ /*
+ * To handle Set SEL we need to receive 6 bytes from Host. So let's
+ * queue a usb_request for 6 bytes.
+ *
+ * Remember, though, this controller can't handle non-wMaxPacketSize
+ * aligned transfers on the OUT direction, so we queue a request for
+ * wMaxPacketSize instead.
+ */
+ dep = dwc->eps[0];
+ dwc->ep0_usb_req.dep = dep;
+ dwc->ep0_usb_req.request.length = dep->endpoint.maxpacket;
+ dwc->ep0_usb_req.request.buf = dwc->setup_buf;
+ dwc->ep0_usb_req.request.complete = dwc3_ep0_set_sel_cmpl;
+
+ return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
+}
+
+static int dwc3_ep0_set_isoch_delay(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
+{
+ u16 wLength;
+ u16 wValue;
+ u16 wIndex;
+
+ wValue = le16_to_cpu(ctrl->wValue);
+ wLength = le16_to_cpu(ctrl->wLength);
+ wIndex = le16_to_cpu(ctrl->wIndex);
+
+ if (wIndex || wLength)
+ return -EINVAL;
+
+ /*
+ * REVISIT It's unclear from Databook what to do with this
+ * value. For now, just cache it.
+ */
+ dwc->isoch_delay = wValue;
+
+ return 0;
+}
+
static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
int ret;
@@ -494,6 +619,14 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dev_vdbg(dwc->dev, "USB_REQ_SET_CONFIGURATION\n");
ret = dwc3_ep0_set_config(dwc, ctrl);
break;
+ case USB_REQ_SET_SEL:
+ dev_vdbg(dwc->dev, "USB_REQ_SET_SEL\n");
+ ret = dwc3_ep0_set_sel(dwc, ctrl);
+ break;
+ case USB_REQ_SET_ISOCH_DELAY:
+ dev_vdbg(dwc->dev, "USB_REQ_SET_ISOCH_DELAY\n");
+ ret = dwc3_ep0_set_isoch_delay(dwc, ctrl);
+ break;
default:
dev_vdbg(dwc->dev, "Forwarding to gadget driver\n");
ret = dwc3_ep0_delegate_req(dwc, ctrl);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 5255fe975ea1..3df1a1973b05 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -178,8 +178,8 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc)
if (!(dep->flags & DWC3_EP_ENABLED))
continue;
- if (usb_endpoint_xfer_bulk(dep->desc)
- || usb_endpoint_xfer_isoc(dep->desc))
+ if (usb_endpoint_xfer_bulk(dep->endpoint.desc)
+ || usb_endpoint_xfer_isoc(dep->endpoint.desc))
mult = 3;
/*
@@ -229,7 +229,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
* completed (not the LINK TRB).
*/
if (((dep->busy_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
- usb_endpoint_xfer_isoc(dep->desc))
+ usb_endpoint_xfer_isoc(dep->endpoint.desc))
dep->busy_slot++;
}
list_del(&req->list);
@@ -276,6 +276,33 @@ static const char *dwc3_gadget_ep_cmd_string(u8 cmd)
}
}
+int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param)
+{
+ u32 timeout = 500;
+ u32 reg;
+
+ dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param);
+ dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT);
+
+ do {
+ reg = dwc3_readl(dwc->regs, DWC3_DGCMD);
+ if (!(reg & DWC3_DGCMD_CMDACT)) {
+ dev_vdbg(dwc->dev, "Command Complete --> %d\n",
+ DWC3_DGCMD_STATUS(reg));
+ return 0;
+ }
+
+ /*
+ * We can't sleep here, because it's also called from
+ * interrupt context.
+ */
+ timeout--;
+ if (!timeout)
+ return -ETIMEDOUT;
+ udelay(1);
+ } while (1);
+}
+
int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
unsigned cmd, struct dwc3_gadget_ep_cmd_params *params)
{
@@ -470,7 +497,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
if (ret)
return ret;
- dep->desc = desc;
+ dep->endpoint.desc = desc;
dep->comp_desc = comp_desc;
dep->type = usb_endpoint_type(desc);
dep->flags |= DWC3_EP_ENABLED;
@@ -533,7 +560,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
dep->stream_capable = false;
- dep->desc = NULL;
dep->endpoint.desc = NULL;
dep->comp_desc = NULL;
dep->type = 0;
@@ -694,7 +720,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
/* Skip the LINK-TRB on ISOC */
if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
- usb_endpoint_xfer_isoc(dep->desc))
+ usb_endpoint_xfer_isoc(dep->endpoint.desc))
return;
if (!req->trb) {
@@ -707,7 +733,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
trb->bpl = lower_32_bits(dma);
trb->bph = upper_32_bits(dma);
- switch (usb_endpoint_type(dep->desc)) {
+ switch (usb_endpoint_type(dep->endpoint.desc)) {
case USB_ENDPOINT_XFER_CONTROL:
trb->ctrl = DWC3_TRBCTL_CONTROL_SETUP;
break;
@@ -732,7 +758,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
BUG();
}
- if (usb_endpoint_xfer_isoc(dep->desc)) {
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
trb->ctrl |= DWC3_TRB_CTRL_CSP;
} else {
@@ -743,7 +769,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
trb->ctrl |= DWC3_TRB_CTRL_LST;
}
- if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable)
+ if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable)
trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id);
trb->ctrl |= DWC3_TRB_CTRL_HWO;
@@ -771,7 +797,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK;
/* Can't wrap around on a non-isoc EP since there's no link TRB */
- if (!usb_endpoint_xfer_isoc(dep->desc)) {
+ if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
max = DWC3_TRB_NUM - (dep->free_slot & DWC3_TRB_MASK);
if (trbs_left > max)
trbs_left = max;
@@ -797,7 +823,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
* processed from the first TRB until the last one. Since we
* don't wrap around we have to start at the beginning.
*/
- if (usb_endpoint_xfer_isoc(dep->desc)) {
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
dep->busy_slot = 1;
dep->free_slot = 1;
} else {
@@ -807,7 +833,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
}
/* The last TRB is a link TRB, not used for xfer */
- if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->desc))
+ if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->endpoint.desc))
return;
list_for_each_entry_safe(req, n, &dep->request_list, list) {
@@ -930,10 +956,12 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
}
dep->flags |= DWC3_EP_BUSY;
- dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc,
- dep->number);
- WARN_ON_ONCE(!dep->res_trans_idx);
+ if (start_new) {
+ dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc,
+ dep->number);
+ WARN_ON_ONCE(!dep->res_trans_idx);
+ }
return 0;
}
@@ -967,28 +995,37 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
list_add_tail(&req->list, &dep->request_list);
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && (dep->flags & DWC3_EP_BUSY))
+ dep->flags |= DWC3_EP_PENDING_REQUEST;
+
/*
- * There is one special case: XferNotReady with
- * empty list of requests. We need to kick the
- * transfer here in that situation, otherwise
- * we will be NAKing forever.
+ * There are two special cases:
+ *
+ * 1. XferNotReady with empty list of requests. We need to kick the
+ * transfer here in that situation, otherwise we will be NAKing
+ * forever. If we get XferNotReady before gadget driver has a
+ * chance to queue a request, we will ACK the IRQ but won't be
+ * able to receive the data until the next request is queued.
+ * The following code is handling exactly that.
*
- * If we get XferNotReady before gadget driver
- * has a chance to queue a request, we will ACK
- * the IRQ but won't be able to receive the data
- * until the next request is queued. The following
- * code is handling exactly that.
+ * 2. XferInProgress on Isoc EP with an active transfer. We need to
+ * kick the transfer here after queuing a request, otherwise the
+ * core may not see the modified TRB(s).
*/
if (dep->flags & DWC3_EP_PENDING_REQUEST) {
- int ret;
- int start_trans;
+ int ret;
+ int start_trans = 1;
+ u8 trans_idx = dep->res_trans_idx;
- start_trans = 1;
- if (usb_endpoint_xfer_isoc(dep->desc) &&
- (dep->flags & DWC3_EP_BUSY))
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+ (dep->flags & DWC3_EP_BUSY)) {
start_trans = 0;
+ WARN_ON_ONCE(!trans_idx);
+ } else {
+ trans_idx = 0;
+ }
- ret = __dwc3_gadget_kick_transfer(dep, 0, start_trans);
+ ret = __dwc3_gadget_kick_transfer(dep, trans_idx, start_trans);
if (ret && ret != -EBUSY) {
struct dwc3 *dwc = dep->dwc;
@@ -1011,7 +1048,7 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
int ret;
- if (!dep->desc) {
+ if (!dep->endpoint.desc) {
dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n",
request, ep->name);
return -ESHUTDOWN;
@@ -1125,7 +1162,7 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value)
spin_lock_irqsave(&dwc->lock, flags);
- if (usb_endpoint_xfer_isoc(dep->desc)) {
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name);
ret = -EINVAL;
goto out;
@@ -1356,7 +1393,24 @@ static int dwc3_gadget_start(struct usb_gadget *g,
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
reg &= ~(DWC3_DCFG_SPEED_MASK);
- reg |= dwc->maximum_speed;
+
+ /**
+ * WORKAROUND: DWC3 revision < 2.20a have an issue
+ * which would cause metastability state on Run/Stop
+ * bit if we try to force the IP to USB2-only mode.
+ *
+ * Because of that, we cannot configure the IP to any
+ * speed other than the SuperSpeed
+ *
+ * Refers to:
+ *
+ * STAR#9000525659: Clock Domain Crossing on DCTL in
+ * USB 2.0 Mode
+ */
+ if (dwc->revision < DWC3_REVISION_220A)
+ reg |= DWC3_DCFG_SUPERSPEED;
+ else
+ reg |= dwc->maximum_speed;
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
dwc->start_config_issued = false;
@@ -1681,7 +1735,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
case DWC3_DEPEVT_XFERCOMPLETE:
dep->res_trans_idx = 0;
- if (usb_endpoint_xfer_isoc(dep->desc)) {
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
dev_dbg(dwc->dev, "%s is an Isochronous endpoint\n",
dep->name);
return;
@@ -1690,7 +1744,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
dwc3_endpoint_transfer_complete(dwc, dep, event, 1);
break;
case DWC3_DEPEVT_XFERINPROGRESS:
- if (!usb_endpoint_xfer_isoc(dep->desc)) {
+ if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
dev_dbg(dwc->dev, "%s is not an Isochronous endpoint\n",
dep->name);
return;
@@ -1699,7 +1753,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
dwc3_endpoint_transfer_complete(dwc, dep, event, 0);
break;
case DWC3_DEPEVT_XFERNOTREADY:
- if (usb_endpoint_xfer_isoc(dep->desc)) {
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
dwc3_gadget_start_isoc(dwc, dep, event);
} else {
int ret;
@@ -1720,7 +1774,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
break;
case DWC3_DEPEVT_STREAMEVT:
- if (!usb_endpoint_xfer_bulk(dep->desc)) {
+ if (!usb_endpoint_xfer_bulk(dep->endpoint.desc)) {
dev_err(dwc->dev, "Stream event for non-Bulk %s\n",
dep->name);
return;
@@ -1916,6 +1970,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg &= ~DWC3_DCTL_TSTCTRL_MASK;
+ reg &= ~(DWC3_DCTL_INITU1ENA | DWC3_DCTL_INITU2ENA);
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
dwc->test_mode = false;
@@ -2263,8 +2318,7 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
goto err1;
}
- dwc->setup_buf = kzalloc(sizeof(*dwc->setup_buf) * 2,
- GFP_KERNEL);
+ dwc->setup_buf = kzalloc(DWC3_EP0_BOUNCE_SIZE, GFP_KERNEL);
if (!dwc->setup_buf) {
dev_err(dwc->dev, "failed to allocate setup buffer\n");
ret = -ENOMEM;
@@ -2272,7 +2326,8 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
}
dwc->ep0_bounce = dma_alloc_coherent(dwc->dev,
- 512, &dwc->ep0_bounce_addr, GFP_KERNEL);
+ DWC3_EP0_BOUNCE_SIZE, &dwc->ep0_bounce_addr,
+ GFP_KERNEL);
if (!dwc->ep0_bounce) {
dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n");
ret = -ENOMEM;
@@ -2313,6 +2368,14 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
goto err5;
}
+ reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+ reg |= DWC3_DCFG_LPM_CAP;
+ dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ reg |= DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA;
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
/* Enable all but Start and End of Frame IRQs */
reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
DWC3_DEVTEN_EVNTOVERFLOWEN |
@@ -2351,8 +2414,8 @@ err5:
dwc3_gadget_free_endpoints(dwc);
err4:
- dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce,
- dwc->ep0_bounce_addr);
+ dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
+ dwc->ep0_bounce, dwc->ep0_bounce_addr);
err3:
kfree(dwc->setup_buf);
@@ -2381,8 +2444,8 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
dwc3_gadget_free_endpoints(dwc);
- dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce,
- dwc->ep0_bounce_addr);
+ dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
+ dwc->ep0_bounce, dwc->ep0_bounce_addr);
kfree(dwc->setup_buf);
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index a8600084348c..95ef6a2f7764 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -111,6 +111,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value);
int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
unsigned cmd, struct dwc3_gadget_ep_cmd_params *params);
+int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param);
/**
* dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index b108d18fd40d..56a62342884d 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -39,15 +39,6 @@
#include "core.h"
-static struct resource generic_resources[] = {
- {
- .flags = IORESOURCE_IRQ,
- },
- {
- .flags = IORESOURCE_MEM,
- },
-};
-
int dwc3_host_init(struct dwc3 *dwc)
{
struct platform_device *xhci;
@@ -68,14 +59,8 @@ int dwc3_host_init(struct dwc3 *dwc)
dwc->xhci = xhci;
- /* setup resources */
- generic_resources[0].start = dwc->irq;
-
- generic_resources[1].start = dwc->res->start;
- generic_resources[1].end = dwc->res->start + 0x7fff;
-
- ret = platform_device_add_resources(xhci, generic_resources,
- ARRAY_SIZE(generic_resources));
+ ret = platform_device_add_resources(xhci, dwc->xhci_resources,
+ DWC3_XHCI_RESOURCES_NUM);
if (ret) {
dev_err(dwc->dev, "couldn't add resources to xHCI device\n");
goto err1;
diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index 071d561f3e68..a50f76b9d19b 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -41,14 +41,26 @@
#include <linux/io.h>
+#include "core.h"
+
static inline u32 dwc3_readl(void __iomem *base, u32 offset)
{
- return readl(base + offset);
+ /*
+ * We requested the mem region starting from the Globals address
+ * space, see dwc3_probe in core.c.
+ * However, the offsets are given starting from xHCI address space.
+ */
+ return readl(base + (offset - DWC3_GLOBALS_REGS_START));
}
static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value)
{
- writel(value, base + offset);
+ /*
+ * We requested the mem region starting from the Globals address
+ * space, see dwc3_probe in core.c.
+ * However, the offsets are given starting from xHCI address space.
+ */
+ writel(value, base + (offset - DWC3_GLOBALS_REGS_START));
}
#endif /* __DRIVERS_USB_DWC3_IO_H */
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 2633f7595116..bddc8fd9a7be 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -123,13 +123,7 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
# - discrete ones (including all PCI-only controllers)
# - debug/dummy gadget+hcd is last.
#
-choice
- prompt "USB Peripheral Controller"
- help
- A USB device uses a controller to talk to its host.
- Systems should have only one such upstream link.
- Many controller drivers are platform-specific; these
- often need board-specific hooks.
+menu "USB Peripheral Controller"
#
# Integrated controllers
@@ -147,6 +141,17 @@ config USB_AT91
dynamically linked module called "at91_udc" and force all
gadget drivers to also be dynamically linked.
+config USB_LPC32XX
+ tristate "LPC32XX USB Peripheral Controller"
+ depends on ARCH_LPC32XX
+ select USB_ISP1301
+ help
+ This option selects the USB device controller in the LPC32xx SoC.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "lpc32xx_udc" and force all
+ gadget drivers to also be dynamically linked.
+
config USB_ATMEL_USBA
tristate "Atmel USBA"
select USB_GADGET_DUALSPEED
@@ -161,7 +166,7 @@ config USB_FSL_USB2
select USB_GADGET_DUALSPEED
select USB_FSL_MPH_DR_OF if OF
help
- Some of Freescale PowerPC processors have a High Speed
+ Some of Freescale PowerPC and i.MX processors have a High Speed
Dual-Role(DR) USB controller, which supports device mode.
The number of programmable endpoints is different through
@@ -373,18 +378,6 @@ config USB_FSL_QE
Set CONFIG_USB_GADGET to "m" to build this driver as a
dynamically linked module called "fsl_qe_udc".
-config USB_CI13XXX_PCI
- tristate "MIPS USB CI13xxx PCI UDC"
- depends on PCI
- select USB_GADGET_DUALSPEED
- help
- MIPS USB IP core family device controller
- Currently it only supports IP part number CI13412
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "ci13xxx_udc" and force all
- gadget drivers to also be dynamically linked.
-
config USB_NET2272
tristate "PLX NET2272"
select USB_GADGET_DUALSPEED
@@ -438,22 +431,6 @@ config USB_GOKU
dynamically linked module called "goku_udc" and to force all
gadget drivers to also be dynamically linked.
-config USB_LANGWELL
- tristate "Intel Langwell USB Device Controller"
- depends on PCI
- depends on !PHYS_ADDR_T_64BIT
- select USB_GADGET_DUALSPEED
- help
- Intel Langwell USB Device Controller is a High-Speed USB
- On-The-Go device controller.
-
- The number of programmable endpoints is different through
- controller revision.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "langwell_udc" and force all
- gadget drivers to also be dynamically linked.
-
config USB_EG20T
tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
depends on PCI
@@ -477,23 +454,6 @@ config USB_EG20T
ML7213/ML7831 is companion chip for Intel Atom E6xx series.
ML7213/ML7831 is completely compatible for Intel EG20T PCH.
-config USB_CI13XXX_MSM
- tristate "MIPS USB CI13xxx for MSM"
- depends on ARCH_MSM
- select USB_GADGET_DUALSPEED
- select USB_MSM_OTG
- help
- MSM SoC has chipidea USB controller. This driver uses
- ci13xxx_udc core.
- This driver depends on OTG driver for PHY initialization,
- clock management, powering up VBUS, and power management.
- This driver is not supported on boards like trout which
- has an external PHY.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "ci13xxx_msm" and force all
- gadget drivers to also be dynamically linked.
-
#
# LAST -- dummy/emulated controller
#
@@ -525,7 +485,7 @@ config USB_DUMMY_HCD
# NOTE: Please keep dummy_hcd LAST so that "real hardware" appears
# first and will be selected by default.
-endchoice
+endmenu
# Selected by UDC drivers that support high-speed operation.
config USB_GADGET_DUALSPEED
@@ -798,6 +758,16 @@ config USB_MASS_STORAGE
Say "y" to link the driver statically, or "m" to build
a dynamically linked module called "g_mass_storage".
+config USB_GADGET_TARGET
+ tristate "USB Gadget Target Fabric Module"
+ depends on TARGET_CORE
+ help
+ This fabric is an USB gadget. Two USB protocols are supported that is
+ BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is
+ advertised on alternative interface 0 (primary) and UAS is on
+ alternative interface 1. Both protocols can work on USB2.0 and USB3.0.
+ UAS utilizes the USB 3.0 feature called streams support.
+
config USB_G_SERIAL
tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
help
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index b7f6eefc3927..1811513f1c27 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -22,14 +22,12 @@ fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o
obj-$(CONFIG_USB_M66592) += m66592-udc.o
obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o
obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o
-obj-$(CONFIG_USB_CI13XXX_PCI) += ci13xxx_pci.o
obj-$(CONFIG_USB_S3C_HSOTG) += s3c-hsotg.o
obj-$(CONFIG_USB_S3C_HSUDC) += s3c-hsudc.o
-obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o
+obj-$(CONFIG_USB_LPC32XX) += lpc32xx_udc.o
obj-$(CONFIG_USB_EG20T) += pch_udc.o
obj-$(CONFIG_USB_MV_UDC) += mv_udc.o
mv_udc-y := mv_udc_core.o
-obj-$(CONFIG_USB_CI13XXX_MSM) += ci13xxx_msm.o
obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o
#
@@ -52,6 +50,7 @@ g_nokia-y := nokia.o
g_webcam-y := webcam.o
g_ncm-y := ncm.o
g_acm_ms-y := acm_ms.o
+g_tcm_usb_gadget-y := tcm_usb_gadget.o
obj-$(CONFIG_USB_ZERO) += g_zero.o
obj-$(CONFIG_USB_AUDIO) += g_audio.o
@@ -71,3 +70,4 @@ obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o
obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o
obj-$(CONFIG_USB_G_NCM) += g_ncm.o
obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o
+obj-$(CONFIG_USB_GADGET_TARGET) += tcm_usb_gadget.o
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 77779271f487..187d21181cd5 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -333,7 +333,7 @@ udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)
return -ESHUTDOWN;
spin_lock_irqsave(&dev->lock, iflags);
- ep->desc = desc;
+ ep->ep.desc = desc;
ep->halted = 0;
@@ -442,7 +442,6 @@ static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep)
u32 tmp;
VDBG(ep->dev, "ep-%d reset\n", ep->num);
- ep->desc = NULL;
ep->ep.desc = NULL;
ep->ep.ops = &udc_ep_ops;
INIT_LIST_HEAD(&ep->queue);
@@ -489,7 +488,7 @@ static int udc_ep_disable(struct usb_ep *usbep)
return -EINVAL;
ep = container_of(usbep, struct udc_ep, ep);
- if (usbep->name == ep0_string || !ep->desc)
+ if (usbep->name == ep0_string || !ep->ep.desc)
return -EINVAL;
DBG(ep->dev, "Disable ep-%d\n", ep->num);
@@ -1066,7 +1065,7 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
return -EINVAL;
ep = container_of(usbep, struct udc_ep, ep);
- if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
+ if (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
return -EINVAL;
VDBG(ep->dev, "udc_queue(): ep%d-in=%d\n", ep->num, ep->in);
@@ -1257,7 +1256,7 @@ static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq)
unsigned long iflags;
ep = container_of(usbep, struct udc_ep, ep);
- if (!usbep || !usbreq || (!ep->desc && (ep->num != 0
+ if (!usbep || !usbreq || (!ep->ep.desc && (ep->num != 0
&& ep->num != UDC_EP0OUT_IX)))
return -EINVAL;
@@ -1317,7 +1316,7 @@ udc_set_halt(struct usb_ep *usbep, int halt)
pr_debug("set_halt %s: halt=%d\n", usbep->name, halt);
ep = container_of(usbep, struct udc_ep, ep);
- if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
+ if (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
return -EINVAL;
if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
return -ESHUTDOWN;
@@ -1539,7 +1538,7 @@ static void udc_setup_endpoints(struct udc *dev)
* disabling ep interrupts when ENUM interrupt occurs but ep is
* not enabled by gadget driver
*/
- if (!ep->desc)
+ if (!ep->ep.desc)
ep_init(dev->regs, ep);
if (use_dma) {
@@ -3402,19 +3401,7 @@ static struct pci_driver udc_pci_driver = {
.remove = udc_pci_remove,
};
-/* Inits driver */
-static int __init init(void)
-{
- return pci_register_driver(&udc_pci_driver);
-}
-module_init(init);
-
-/* Cleans driver */
-static void __exit cleanup(void)
-{
- pci_unregister_driver(&udc_pci_driver);
-}
-module_exit(cleanup);
+module_pci_driver(udc_pci_driver);
MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION);
MODULE_AUTHOR("Thomas Dahlmann");
diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/amd5536udc.h
index f87e29c65325..14af87d65caa 100644
--- a/drivers/usb/gadget/amd5536udc.h
+++ b/drivers/usb/gadget/amd5536udc.h
@@ -512,7 +512,6 @@ struct udc_ep {
/* queue for requests */
struct list_head queue;
- const struct usb_endpoint_descriptor *desc;
unsigned halted;
unsigned cancel_transfer;
unsigned num : 5,
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 9d7bcd910074..1a4430f315c3 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -212,7 +212,7 @@ static int proc_udc_show(struct seq_file *s, void *unused)
if (udc->enabled && udc->vbus) {
proc_ep_show(s, &udc->ep[0]);
list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) {
- if (ep->desc)
+ if (ep->ep.desc)
proc_ep_show(s, ep);
}
}
@@ -475,7 +475,7 @@ static int at91_ep_enable(struct usb_ep *_ep,
unsigned long flags;
if (!_ep || !ep
- || !desc || ep->desc
+ || !desc || ep->ep.desc
|| _ep->name == ep0name
|| desc->bDescriptorType != USB_DT_ENDPOINT
|| (maxpacket = usb_endpoint_maxp(desc)) == 0
@@ -530,7 +530,7 @@ ok:
tmp |= AT91_UDP_EPEDS;
__raw_writel(tmp, ep->creg);
- ep->desc = desc;
+ ep->ep.desc = desc;
ep->ep.maxpacket = maxpacket;
/*
@@ -558,7 +558,6 @@ static int at91_ep_disable (struct usb_ep * _ep)
nuke(ep, -ESHUTDOWN);
/* restore the endpoint's pristine config */
- ep->desc = NULL;
ep->ep.desc = NULL;
ep->ep.maxpacket = ep->maxpacket;
@@ -618,7 +617,7 @@ static int at91_ep_queue(struct usb_ep *_ep,
return -EINVAL;
}
- if (!_ep || (!ep->desc && ep->ep.name != ep0name)) {
+ if (!_ep || (!ep->ep.desc && ep->ep.name != ep0name)) {
DBG("invalid ep\n");
return -EINVAL;
}
@@ -833,7 +832,7 @@ static void udc_reinit(struct at91_udc *udc)
if (i != 0)
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
- ep->desc = NULL;
+ ep->ep.desc = NULL;
ep->stopped = 0;
ep->fifo_bank = 0;
ep->ep.maxpacket = ep->maxpacket;
@@ -978,18 +977,18 @@ static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on)
return 0;
}
-static int at91_start(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *));
-static int at91_stop(struct usb_gadget_driver *driver);
-
+static int at91_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver);
+static int at91_stop(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver);
static const struct usb_gadget_ops at91_udc_ops = {
.get_frame = at91_get_frame,
.wakeup = at91_wakeup,
.set_selfpowered = at91_set_selfpowered,
.vbus_session = at91_vbus_session,
.pullup = at91_pullup,
- .start = at91_start,
- .stop = at91_stop,
+ .udc_start = at91_start,
+ .udc_stop = at91_stop,
/*
* VBUS-powered devices may also also want to support bigger
@@ -1172,7 +1171,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
| USB_REQ_GET_STATUS:
tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
ep = &udc->ep[tmp];
- if (tmp >= NUM_ENDPOINTS || (tmp && !ep->desc))
+ if (tmp >= NUM_ENDPOINTS || (tmp && !ep->ep.desc))
goto stall;
if (tmp) {
@@ -1197,7 +1196,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
ep = &udc->ep[tmp];
if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
goto stall;
- if (!ep->desc || ep->is_iso)
+ if (!ep->ep.desc || ep->is_iso)
goto stall;
if ((w_index & USB_DIR_IN)) {
if (!ep->is_in)
@@ -1218,7 +1217,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
goto stall;
if (tmp == 0)
goto succeed;
- if (!ep->desc || ep->is_iso)
+ if (!ep->ep.desc || ep->is_iso)
goto stall;
if ((w_index & USB_DIR_IN)) {
if (!ep->is_in)
@@ -1627,66 +1626,34 @@ static void at91_vbus_timer(unsigned long data)
schedule_work(&udc->vbus_timer_work);
}
-static int at91_start(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *))
+static int at91_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
{
- struct at91_udc *udc = &controller;
- int retval;
- unsigned long flags;
-
- if (!driver
- || driver->max_speed < USB_SPEED_FULL
- || !bind
- || !driver->setup) {
- DBG("bad parameter.\n");
- return -EINVAL;
- }
-
- if (udc->driver) {
- DBG("UDC already has a gadget driver\n");
- return -EBUSY;
- }
+ struct at91_udc *udc;
+ udc = container_of(gadget, struct at91_udc, gadget);
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
dev_set_drvdata(&udc->gadget.dev, &driver->driver);
udc->enabled = 1;
udc->selfpowered = 1;
- retval = bind(&udc->gadget);
- if (retval) {
- DBG("bind() returned %d\n", retval);
- udc->driver = NULL;
- udc->gadget.dev.driver = NULL;
- dev_set_drvdata(&udc->gadget.dev, NULL);
- udc->enabled = 0;
- udc->selfpowered = 0;
- return retval;
- }
-
- spin_lock_irqsave(&udc->lock, flags);
- pullup(udc, 1);
- spin_unlock_irqrestore(&udc->lock, flags);
-
DBG("bound to %s\n", driver->driver.name);
return 0;
}
-static int at91_stop(struct usb_gadget_driver *driver)
+static int at91_stop(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
{
- struct at91_udc *udc = &controller;
+ struct at91_udc *udc;
unsigned long flags;
- if (!driver || driver != udc->driver || !driver->unbind)
- return -EINVAL;
-
+ udc = container_of(gadget, struct at91_udc, gadget);
spin_lock_irqsave(&udc->lock, flags);
udc->enabled = 0;
at91_udp_write(udc, AT91_UDP_IDR, ~0);
- pullup(udc, 0);
spin_unlock_irqrestore(&udc->lock, flags);
- driver->unbind(&udc->gadget);
udc->gadget.dev.driver = NULL;
dev_set_drvdata(&udc->gadget.dev, NULL);
udc->driver = NULL;
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index 3c0315b86ace..e647d1c2ada4 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/at91_udc.h
@@ -105,9 +105,6 @@ struct at91_ep {
unsigned is_in:1;
unsigned is_iso:1;
unsigned fifo_bank:1;
-
- const struct usb_endpoint_descriptor
- *desc;
};
/*
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 9f98508966d1..e23bf7984aaf 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -599,13 +599,13 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
spin_lock_irqsave(&ep->udc->lock, flags);
- if (ep->desc) {
+ if (ep->ep.desc) {
spin_unlock_irqrestore(&ep->udc->lock, flags);
DBG(DBG_ERR, "ep%d already enabled\n", ep->index);
return -EBUSY;
}
- ep->desc = desc;
+ ep->ep.desc = desc;
ep->ep.maxpacket = maxpacket;
usba_ep_writel(ep, CFG, ept_cfg);
@@ -647,7 +647,7 @@ static int usba_ep_disable(struct usb_ep *_ep)
spin_lock_irqsave(&udc->lock, flags);
- if (!ep->desc) {
+ if (!ep->ep.desc) {
spin_unlock_irqrestore(&udc->lock, flags);
/* REVISIT because this driver disables endpoints in
* reset_all_endpoints() before calling disconnect(),
@@ -658,7 +658,6 @@ static int usba_ep_disable(struct usb_ep *_ep)
ep->ep.name);
return -EINVAL;
}
- ep->desc = NULL;
ep->ep.desc = NULL;
list_splice_init(&ep->queue, &req_list);
@@ -752,7 +751,7 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
*/
ret = -ESHUTDOWN;
spin_lock_irqsave(&udc->lock, flags);
- if (ep->desc) {
+ if (ep->ep.desc) {
if (list_empty(&ep->queue))
submit_request(ep, req);
@@ -776,7 +775,8 @@ usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
DBG(DBG_GADGET | DBG_QUEUE | DBG_REQ, "%s: queue req %p, len %u\n",
ep->ep.name, req, _req->length);
- if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN || !ep->desc)
+ if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN ||
+ !ep->ep.desc)
return -ESHUTDOWN;
req->submitted = 0;
@@ -792,7 +792,7 @@ usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
/* May have received a reset since last time we checked */
ret = -ESHUTDOWN;
spin_lock_irqsave(&udc->lock, flags);
- if (ep->desc) {
+ if (ep->ep.desc) {
list_add_tail(&req->queue, &ep->queue);
if ((!ep_is_control(ep) && ep->is_in) ||
@@ -905,7 +905,7 @@ static int usba_ep_set_halt(struct usb_ep *_ep, int value)
DBG(DBG_GADGET, "endpoint %s: %s HALT\n", ep->ep.name,
value ? "set" : "clear");
- if (!ep->desc) {
+ if (!ep->ep.desc) {
DBG(DBG_ERR, "Attempted to halt uninitialized ep %s\n",
ep->ep.name);
return -ENODEV;
@@ -1008,16 +1008,16 @@ usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
return 0;
}
-static int atmel_usba_start(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *));
-static int atmel_usba_stop(struct usb_gadget_driver *driver);
-
+static int atmel_usba_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver);
+static int atmel_usba_stop(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver);
static const struct usb_gadget_ops usba_udc_ops = {
.get_frame = usba_udc_get_frame,
.wakeup = usba_udc_wakeup,
.set_selfpowered = usba_udc_set_selfpowered,
- .start = atmel_usba_start,
- .stop = atmel_usba_stop,
+ .udc_start = atmel_usba_start,
+ .udc_stop = atmel_usba_stop,
};
static struct usb_endpoint_descriptor usba_ep0_desc = {
@@ -1071,7 +1071,7 @@ static void reset_all_endpoints(struct usba_udc *udc)
* FIXME remove this code ... and retest thoroughly.
*/
list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
- if (ep->desc) {
+ if (ep->ep.desc) {
spin_unlock(&udc->lock);
usba_ep_disable(&ep->ep);
spin_lock(&udc->lock);
@@ -1089,9 +1089,9 @@ static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex)
list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) {
u8 bEndpointAddress;
- if (!ep->desc)
+ if (!ep->ep.desc)
continue;
- bEndpointAddress = ep->desc->bEndpointAddress;
+ bEndpointAddress = ep->ep.desc->bEndpointAddress;
if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
continue;
if ((bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)
@@ -1727,7 +1727,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
usb_speed_string(udc->gadget.speed));
ep0 = &usba_ep[0];
- ep0->desc = &usba_ep0_desc;
+ ep0->ep.desc = &usba_ep0_desc;
ep0->state = WAIT_FOR_SETUP;
usba_ep_writel(ep0, CFG,
(USBA_BF(EPT_SIZE, EP0_EPT_SIZE)
@@ -1795,21 +1795,13 @@ out:
return IRQ_HANDLED;
}
-static int atmel_usba_start(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *))
+static int atmel_usba_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
{
- struct usba_udc *udc = &the_udc;
+ struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
unsigned long flags;
- int ret;
-
- if (!udc->pdev)
- return -ENODEV;
spin_lock_irqsave(&udc->lock, flags);
- if (udc->driver) {
- spin_unlock_irqrestore(&udc->lock, flags);
- return -EBUSY;
- }
udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
udc->driver = driver;
@@ -1819,13 +1811,6 @@ static int atmel_usba_start(struct usb_gadget_driver *driver,
clk_enable(udc->pclk);
clk_enable(udc->hclk);
- ret = bind(&udc->gadget);
- if (ret) {
- DBG(DBG_ERR, "Could not bind to driver %s: error %d\n",
- driver->driver.name, ret);
- goto err_driver_bind;
- }
-
DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name);
udc->vbus_prev = 0;
@@ -1842,23 +1827,14 @@ static int atmel_usba_start(struct usb_gadget_driver *driver,
spin_unlock_irqrestore(&udc->lock, flags);
return 0;
-
-err_driver_bind:
- udc->driver = NULL;
- udc->gadget.dev.driver = NULL;
- return ret;
}
-static int atmel_usba_stop(struct usb_gadget_driver *driver)
+static int atmel_usba_stop(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
{
- struct usba_udc *udc = &the_udc;
+ struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
unsigned long flags;
- if (!udc->pdev)
- return -ENODEV;
- if (driver != udc->driver || !driver->unbind)
- return -EINVAL;
-
if (gpio_is_valid(udc->vbus_pin))
disable_irq(gpio_to_irq(udc->vbus_pin));
@@ -1871,10 +1847,6 @@ static int atmel_usba_stop(struct usb_gadget_driver *driver)
toggle_bias(0);
usba_writel(udc, CTRL, USBA_DISABLE_MASK);
- if (udc->driver->disconnect)
- udc->driver->disconnect(&udc->gadget);
-
- driver->unbind(&udc->gadget);
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
index 88a2e07a11a8..9791259cbda7 100644
--- a/drivers/usb/gadget/atmel_usba_udc.h
+++ b/drivers/usb/gadget/atmel_usba_udc.h
@@ -280,7 +280,6 @@ struct usba_ep {
struct usba_udc *udc;
struct list_head queue;
- const struct usb_endpoint_descriptor *desc;
u16 fifo_size;
u8 nr_banks;
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
deleted file mode 100644
index 243ef1adf969..000000000000
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ /dev/null
@@ -1,2996 +0,0 @@
-/*
- * ci13xxx_udc.c - MIPS USB IP core family device controller
- *
- * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
- *
- * Author: David Lopo
- *
- * 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.
- */
-
-/*
- * Description: MIPS USB IP core family device controller
- * Currently it only supports IP part number CI13412
- *
- * This driver is composed of several blocks:
- * - HW: hardware interface
- * - DBG: debug facilities (optional)
- * - UTIL: utilities
- * - ISR: interrupts handling
- * - ENDPT: endpoint operations (Gadget API)
- * - GADGET: gadget operations (Gadget API)
- * - BUS: bus glue code, bus abstraction layer
- *
- * Compile Options
- * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities
- * - STALL_IN: non-empty bulk-in pipes cannot be halted
- * if defined mass storage compliance succeeds but with warnings
- * => case 4: Hi > Dn
- * => case 5: Hi > Di
- * => case 8: Hi <> Do
- * if undefined usbtest 13 fails
- * - TRACE: enable function tracing (depends on DEBUG)
- *
- * Main Features
- * - Chapter 9 & Mass Storage Compliance with Gadget File Storage
- * - Chapter 9 Compliance with Gadget Zero (STALL_IN undefined)
- * - Normal & LPM support
- *
- * USBTEST Report
- * - OK: 0-12, 13 (STALL_IN defined) & 14
- * - Not Supported: 15 & 16 (ISO)
- *
- * TODO List
- * - OTG
- * - Isochronous & Interrupt Traffic
- * - Handle requests which spawns into several TDs
- * - GET_STATUS(device) - always reports 0
- * - Gadget API (majority of optional features)
- * - Suspend & Remote Wakeup
- */
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dmapool.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
-
-#include "ci13xxx_udc.h"
-
-
-/******************************************************************************
- * DEFINE
- *****************************************************************************/
-
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
-
-/* ctrl register bank access */
-static DEFINE_SPINLOCK(udc_lock);
-
-/* control endpoint description */
-static const struct usb_endpoint_descriptor
-ctrl_endpt_out_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
- .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
-};
-
-static const struct usb_endpoint_descriptor
-ctrl_endpt_in_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
- .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
-};
-
-/* UDC descriptor */
-static struct ci13xxx *_udc;
-
-/* Interrupt statistics */
-#define ISR_MASK 0x1F
-static struct {
- u32 test;
- u32 ui;
- u32 uei;
- u32 pci;
- u32 uri;
- u32 sli;
- u32 none;
- struct {
- u32 cnt;
- u32 buf[ISR_MASK+1];
- u32 idx;
- } hndl;
-} isr_statistics;
-
-/**
- * ffs_nr: find first (least significant) bit set
- * @x: the word to search
- *
- * This function returns bit number (instead of position)
- */
-static int ffs_nr(u32 x)
-{
- int n = ffs(x);
-
- return n ? n-1 : 32;
-}
-
-/******************************************************************************
- * HW block
- *****************************************************************************/
-/* register bank descriptor */
-static struct {
- unsigned lpm; /* is LPM? */
- void __iomem *abs; /* bus map offset */
- void __iomem *cap; /* bus map offset + CAP offset + CAP data */
- size_t size; /* bank size */
-} hw_bank;
-
-/* MSM specific */
-#define ABS_AHBBURST (0x0090UL)
-#define ABS_AHBMODE (0x0098UL)
-/* UDC register map */
-#define ABS_CAPLENGTH (0x100UL)
-#define ABS_HCCPARAMS (0x108UL)
-#define ABS_DCCPARAMS (0x124UL)
-#define ABS_TESTMODE (hw_bank.lpm ? 0x0FCUL : 0x138UL)
-/* offset to CAPLENTGH (addr + data) */
-#define CAP_USBCMD (0x000UL)
-#define CAP_USBSTS (0x004UL)
-#define CAP_USBINTR (0x008UL)
-#define CAP_DEVICEADDR (0x014UL)
-#define CAP_ENDPTLISTADDR (0x018UL)
-#define CAP_PORTSC (0x044UL)
-#define CAP_DEVLC (0x084UL)
-#define CAP_USBMODE (hw_bank.lpm ? 0x0C8UL : 0x068UL)
-#define CAP_ENDPTSETUPSTAT (hw_bank.lpm ? 0x0D8UL : 0x06CUL)
-#define CAP_ENDPTPRIME (hw_bank.lpm ? 0x0DCUL : 0x070UL)
-#define CAP_ENDPTFLUSH (hw_bank.lpm ? 0x0E0UL : 0x074UL)
-#define CAP_ENDPTSTAT (hw_bank.lpm ? 0x0E4UL : 0x078UL)
-#define CAP_ENDPTCOMPLETE (hw_bank.lpm ? 0x0E8UL : 0x07CUL)
-#define CAP_ENDPTCTRL (hw_bank.lpm ? 0x0ECUL : 0x080UL)
-#define CAP_LAST (hw_bank.lpm ? 0x12CUL : 0x0C0UL)
-
-/* maximum number of enpoints: valid only after hw_device_reset() */
-static unsigned hw_ep_max;
-
-/**
- * hw_ep_bit: calculates the bit number
- * @num: endpoint number
- * @dir: endpoint direction
- *
- * This function returns bit number
- */
-static inline int hw_ep_bit(int num, int dir)
-{
- return num + (dir ? 16 : 0);
-}
-
-static int ep_to_bit(int n)
-{
- int fill = 16 - hw_ep_max / 2;
-
- if (n >= hw_ep_max / 2)
- n += fill;
-
- return n;
-}
-
-/**
- * hw_aread: reads from register bitfield
- * @addr: address relative to bus map
- * @mask: bitfield mask
- *
- * This function returns register bitfield data
- */
-static u32 hw_aread(u32 addr, u32 mask)
-{
- return ioread32(addr + hw_bank.abs) & mask;
-}
-
-/**
- * hw_awrite: writes to register bitfield
- * @addr: address relative to bus map
- * @mask: bitfield mask
- * @data: new data
- */
-static void hw_awrite(u32 addr, u32 mask, u32 data)
-{
- iowrite32(hw_aread(addr, ~mask) | (data & mask),
- addr + hw_bank.abs);
-}
-
-/**
- * hw_cread: reads from register bitfield
- * @addr: address relative to CAP offset plus content
- * @mask: bitfield mask
- *
- * This function returns register bitfield data
- */
-static u32 hw_cread(u32 addr, u32 mask)
-{
- return ioread32(addr + hw_bank.cap) & mask;
-}
-
-/**
- * hw_cwrite: writes to register bitfield
- * @addr: address relative to CAP offset plus content
- * @mask: bitfield mask
- * @data: new data
- */
-static void hw_cwrite(u32 addr, u32 mask, u32 data)
-{
- iowrite32(hw_cread(addr, ~mask) | (data & mask),
- addr + hw_bank.cap);
-}
-
-/**
- * hw_ctest_and_clear: tests & clears register bitfield
- * @addr: address relative to CAP offset plus content
- * @mask: bitfield mask
- *
- * This function returns register bitfield data
- */
-static u32 hw_ctest_and_clear(u32 addr, u32 mask)
-{
- u32 reg = hw_cread(addr, mask);
-
- iowrite32(reg, addr + hw_bank.cap);
- return reg;
-}
-
-/**
- * hw_ctest_and_write: tests & writes register bitfield
- * @addr: address relative to CAP offset plus content
- * @mask: bitfield mask
- * @data: new data
- *
- * This function returns register bitfield data
- */
-static u32 hw_ctest_and_write(u32 addr, u32 mask, u32 data)
-{
- u32 reg = hw_cread(addr, ~0);
-
- iowrite32((reg & ~mask) | (data & mask), addr + hw_bank.cap);
- return (reg & mask) >> ffs_nr(mask);
-}
-
-static int hw_device_init(void __iomem *base)
-{
- u32 reg;
-
- /* bank is a module variable */
- hw_bank.abs = base;
-
- hw_bank.cap = hw_bank.abs;
- hw_bank.cap += ABS_CAPLENGTH;
- hw_bank.cap += ioread8(hw_bank.cap);
-
- reg = hw_aread(ABS_HCCPARAMS, HCCPARAMS_LEN) >> ffs_nr(HCCPARAMS_LEN);
- hw_bank.lpm = reg;
- hw_bank.size = hw_bank.cap - hw_bank.abs;
- hw_bank.size += CAP_LAST;
- hw_bank.size /= sizeof(u32);
-
- reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN);
- hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */
-
- if (hw_ep_max == 0 || hw_ep_max > ENDPT_MAX)
- return -ENODEV;
-
- /* setup lock mode ? */
-
- /* ENDPTSETUPSTAT is '0' by default */
-
- /* HCSPARAMS.bf.ppc SHOULD BE zero for device */
-
- return 0;
-}
-/**
- * hw_device_reset: resets chip (execute without interruption)
- * @base: register base address
- *
- * This function returns an error code
- */
-static int hw_device_reset(struct ci13xxx *udc)
-{
- /* should flush & stop before reset */
- hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0);
- hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
-
- hw_cwrite(CAP_USBCMD, USBCMD_RST, USBCMD_RST);
- while (hw_cread(CAP_USBCMD, USBCMD_RST))
- udelay(10); /* not RTOS friendly */
-
-
- if (udc->udc_driver->notify_event)
- udc->udc_driver->notify_event(udc,
- CI13XXX_CONTROLLER_RESET_EVENT);
-
- if (udc->udc_driver->flags & CI13XXX_DISABLE_STREAMING)
- hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
-
- /* USBMODE should be configured step by step */
- hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
- hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
- hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW >= 2.3 */
-
- if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
- pr_err("cannot enter in device mode");
- pr_err("lpm = %i", hw_bank.lpm);
- return -ENODEV;
- }
-
- return 0;
-}
-
-/**
- * hw_device_state: enables/disables interrupts & starts/stops device (execute
- * without interruption)
- * @dma: 0 => disable, !0 => enable and set dma engine
- *
- * This function returns an error code
- */
-static int hw_device_state(u32 dma)
-{
- if (dma) {
- hw_cwrite(CAP_ENDPTLISTADDR, ~0, dma);
- /* interrupt, error, port change, reset, sleep/suspend */
- hw_cwrite(CAP_USBINTR, ~0,
- USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
- hw_cwrite(CAP_USBCMD, USBCMD_RS, USBCMD_RS);
- } else {
- hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
- hw_cwrite(CAP_USBINTR, ~0, 0);
- }
- return 0;
-}
-
-/**
- * hw_ep_flush: flush endpoint fifo (execute without interruption)
- * @num: endpoint number
- * @dir: endpoint direction
- *
- * This function returns an error code
- */
-static int hw_ep_flush(int num, int dir)
-{
- int n = hw_ep_bit(num, dir);
-
- do {
- /* flush any pending transfer */
- hw_cwrite(CAP_ENDPTFLUSH, BIT(n), BIT(n));
- while (hw_cread(CAP_ENDPTFLUSH, BIT(n)))
- cpu_relax();
- } while (hw_cread(CAP_ENDPTSTAT, BIT(n)));
-
- return 0;
-}
-
-/**
- * hw_ep_disable: disables endpoint (execute without interruption)
- * @num: endpoint number
- * @dir: endpoint direction
- *
- * This function returns an error code
- */
-static int hw_ep_disable(int num, int dir)
-{
- hw_ep_flush(num, dir);
- hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32),
- dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0);
- return 0;
-}
-
-/**
- * hw_ep_enable: enables endpoint (execute without interruption)
- * @num: endpoint number
- * @dir: endpoint direction
- * @type: endpoint type
- *
- * This function returns an error code
- */
-static int hw_ep_enable(int num, int dir, int type)
-{
- u32 mask, data;
-
- if (dir) {
- mask = ENDPTCTRL_TXT; /* type */
- data = type << ffs_nr(mask);
-
- mask |= ENDPTCTRL_TXS; /* unstall */
- mask |= ENDPTCTRL_TXR; /* reset data toggle */
- data |= ENDPTCTRL_TXR;
- mask |= ENDPTCTRL_TXE; /* enable */
- data |= ENDPTCTRL_TXE;
- } else {
- mask = ENDPTCTRL_RXT; /* type */
- data = type << ffs_nr(mask);
-
- mask |= ENDPTCTRL_RXS; /* unstall */
- mask |= ENDPTCTRL_RXR; /* reset data toggle */
- data |= ENDPTCTRL_RXR;
- mask |= ENDPTCTRL_RXE; /* enable */
- data |= ENDPTCTRL_RXE;
- }
- hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32), mask, data);
- return 0;
-}
-
-/**
- * hw_ep_get_halt: return endpoint halt status
- * @num: endpoint number
- * @dir: endpoint direction
- *
- * This function returns 1 if endpoint halted
- */
-static int hw_ep_get_halt(int num, int dir)
-{
- u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
-
- return hw_cread(CAP_ENDPTCTRL + num * sizeof(u32), mask) ? 1 : 0;
-}
-
-/**
- * hw_test_and_clear_setup_status: test & clear setup status (execute without
- * interruption)
- * @n: endpoint number
- *
- * This function returns setup status
- */
-static int hw_test_and_clear_setup_status(int n)
-{
- n = ep_to_bit(n);
- return hw_ctest_and_clear(CAP_ENDPTSETUPSTAT, BIT(n));
-}
-
-/**
- * hw_ep_prime: primes endpoint (execute without interruption)
- * @num: endpoint number
- * @dir: endpoint direction
- * @is_ctrl: true if control endpoint
- *
- * This function returns an error code
- */
-static int hw_ep_prime(int num, int dir, int is_ctrl)
-{
- int n = hw_ep_bit(num, dir);
-
- if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
- return -EAGAIN;
-
- hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n));
-
- while (hw_cread(CAP_ENDPTPRIME, BIT(n)))
- cpu_relax();
- if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
- return -EAGAIN;
-
- /* status shoult be tested according with manual but it doesn't work */
- return 0;
-}
-
-/**
- * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute
- * without interruption)
- * @num: endpoint number
- * @dir: endpoint direction
- * @value: true => stall, false => unstall
- *
- * This function returns an error code
- */
-static int hw_ep_set_halt(int num, int dir, int value)
-{
- if (value != 0 && value != 1)
- return -EINVAL;
-
- do {
- u32 addr = CAP_ENDPTCTRL + num * sizeof(u32);
- u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
- u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR;
-
- /* data toggle - reserved for EP0 but it's in ESS */
- hw_cwrite(addr, mask_xs|mask_xr, value ? mask_xs : mask_xr);
-
- } while (value != hw_ep_get_halt(num, dir));
-
- return 0;
-}
-
-/**
- * hw_intr_clear: disables interrupt & clears interrupt status (execute without
- * interruption)
- * @n: interrupt bit
- *
- * This function returns an error code
- */
-static int hw_intr_clear(int n)
-{
- if (n >= REG_BITS)
- return -EINVAL;
-
- hw_cwrite(CAP_USBINTR, BIT(n), 0);
- hw_cwrite(CAP_USBSTS, BIT(n), BIT(n));
- return 0;
-}
-
-/**
- * hw_intr_force: enables interrupt & forces interrupt status (execute without
- * interruption)
- * @n: interrupt bit
- *
- * This function returns an error code
- */
-static int hw_intr_force(int n)
-{
- if (n >= REG_BITS)
- return -EINVAL;
-
- hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
- hw_cwrite(CAP_USBINTR, BIT(n), BIT(n));
- hw_cwrite(CAP_USBSTS, BIT(n), BIT(n));
- hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, 0);
- return 0;
-}
-
-/**
- * hw_is_port_high_speed: test if port is high speed
- *
- * This function returns true if high speed port
- */
-static int hw_port_is_high_speed(void)
-{
- return hw_bank.lpm ? hw_cread(CAP_DEVLC, DEVLC_PSPD) :
- hw_cread(CAP_PORTSC, PORTSC_HSP);
-}
-
-/**
- * hw_port_test_get: reads port test mode value
- *
- * This function returns port test mode value
- */
-static u8 hw_port_test_get(void)
-{
- return hw_cread(CAP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC);
-}
-
-/**
- * hw_port_test_set: writes port test mode (execute without interruption)
- * @mode: new value
- *
- * This function returns an error code
- */
-static int hw_port_test_set(u8 mode)
-{
- const u8 TEST_MODE_MAX = 7;
-
- if (mode > TEST_MODE_MAX)
- return -EINVAL;
-
- hw_cwrite(CAP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC));
- return 0;
-}
-
-/**
- * hw_read_intr_enable: returns interrupt enable register
- *
- * This function returns register data
- */
-static u32 hw_read_intr_enable(void)
-{
- return hw_cread(CAP_USBINTR, ~0);
-}
-
-/**
- * hw_read_intr_status: returns interrupt status register
- *
- * This function returns register data
- */
-static u32 hw_read_intr_status(void)
-{
- return hw_cread(CAP_USBSTS, ~0);
-}
-
-/**
- * hw_register_read: reads all device registers (execute without interruption)
- * @buf: destination buffer
- * @size: buffer size
- *
- * This function returns number of registers read
- */
-static size_t hw_register_read(u32 *buf, size_t size)
-{
- unsigned i;
-
- if (size > hw_bank.size)
- size = hw_bank.size;
-
- for (i = 0; i < size; i++)
- buf[i] = hw_aread(i * sizeof(u32), ~0);
-
- return size;
-}
-
-/**
- * hw_register_write: writes to register
- * @addr: register address
- * @data: register value
- *
- * This function returns an error code
- */
-static int hw_register_write(u16 addr, u32 data)
-{
- /* align */
- addr /= sizeof(u32);
-
- if (addr >= hw_bank.size)
- return -EINVAL;
-
- /* align */
- addr *= sizeof(u32);
-
- hw_awrite(addr, ~0, data);
- return 0;
-}
-
-/**
- * hw_test_and_clear_complete: test & clear complete status (execute without
- * interruption)
- * @n: endpoint number
- *
- * This function returns complete status
- */
-static int hw_test_and_clear_complete(int n)
-{
- n = ep_to_bit(n);
- return hw_ctest_and_clear(CAP_ENDPTCOMPLETE, BIT(n));
-}
-
-/**
- * hw_test_and_clear_intr_active: test & clear active interrupts (execute
- * without interruption)
- *
- * This function returns active interrutps
- */
-static u32 hw_test_and_clear_intr_active(void)
-{
- u32 reg = hw_read_intr_status() & hw_read_intr_enable();
-
- hw_cwrite(CAP_USBSTS, ~0, reg);
- return reg;
-}
-
-/**
- * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
- * interruption)
- *
- * This function returns guard value
- */
-static int hw_test_and_clear_setup_guard(void)
-{
- return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, 0);
-}
-
-/**
- * hw_test_and_set_setup_guard: test & set setup guard (execute without
- * interruption)
- *
- * This function returns guard value
- */
-static int hw_test_and_set_setup_guard(void)
-{
- return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, USBCMD_SUTW);
-}
-
-/**
- * hw_usb_set_address: configures USB address (execute without interruption)
- * @value: new USB address
- *
- * This function returns an error code
- */
-static int hw_usb_set_address(u8 value)
-{
- /* advance */
- hw_cwrite(CAP_DEVICEADDR, DEVICEADDR_USBADR | DEVICEADDR_USBADRA,
- value << ffs_nr(DEVICEADDR_USBADR) | DEVICEADDR_USBADRA);
- return 0;
-}
-
-/**
- * hw_usb_reset: restart device after a bus reset (execute without
- * interruption)
- *
- * This function returns an error code
- */
-static int hw_usb_reset(void)
-{
- hw_usb_set_address(0);
-
- /* ESS flushes only at end?!? */
- hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); /* flush all EPs */
-
- /* clear setup token semaphores */
- hw_cwrite(CAP_ENDPTSETUPSTAT, 0, 0); /* writes its content */
-
- /* clear complete status */
- hw_cwrite(CAP_ENDPTCOMPLETE, 0, 0); /* writes its content */
-
- /* wait until all bits cleared */
- while (hw_cread(CAP_ENDPTPRIME, ~0))
- udelay(10); /* not RTOS friendly */
-
- /* reset all endpoints ? */
-
- /* reset internal status and wait for further instructions
- no need to verify the port reset status (ESS does it) */
-
- return 0;
-}
-
-/******************************************************************************
- * DBG block
- *****************************************************************************/
-/**
- * show_device: prints information about device capabilities and status
- *
- * Check "device.h" for details
- */
-static ssize_t show_device(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
- struct usb_gadget *gadget = &udc->gadget;
- int n = 0;
-
- dbg_trace("[%s] %p\n", __func__, buf);
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- return 0;
- }
-
- n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
- gadget->speed);
- n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
- gadget->max_speed);
- /* TODO: Scheduled for removal in 3.8. */
- n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
- gadget_is_dualspeed(gadget));
- n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
- gadget->is_otg);
- n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
- gadget->is_a_peripheral);
- n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n",
- gadget->b_hnp_enable);
- n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n",
- gadget->a_hnp_support);
- n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
- gadget->a_alt_hnp_support);
- n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n",
- (gadget->name ? gadget->name : ""));
-
- return n;
-}
-static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
-
-/**
- * show_driver: prints information about attached gadget (if any)
- *
- * Check "device.h" for details
- */
-static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
- struct usb_gadget_driver *driver = udc->driver;
- int n = 0;
-
- dbg_trace("[%s] %p\n", __func__, buf);
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- return 0;
- }
-
- if (driver == NULL)
- return scnprintf(buf, PAGE_SIZE,
- "There is no gadget attached!\n");
-
- n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
- (driver->function ? driver->function : ""));
- n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
- driver->max_speed);
-
- return n;
-}
-static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
-
-/* Maximum event message length */
-#define DBG_DATA_MSG 64UL
-
-/* Maximum event messages */
-#define DBG_DATA_MAX 128UL
-
-/* Event buffer descriptor */
-static struct {
- char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
- unsigned idx; /* index */
- unsigned tty; /* print to console? */
- rwlock_t lck; /* lock */
-} dbg_data = {
- .idx = 0,
- .tty = 0,
- .lck = __RW_LOCK_UNLOCKED(lck)
-};
-
-/**
- * dbg_dec: decrements debug event index
- * @idx: buffer index
- */
-static void dbg_dec(unsigned *idx)
-{
- *idx = (*idx - 1) & (DBG_DATA_MAX-1);
-}
-
-/**
- * dbg_inc: increments debug event index
- * @idx: buffer index
- */
-static void dbg_inc(unsigned *idx)
-{
- *idx = (*idx + 1) & (DBG_DATA_MAX-1);
-}
-
-/**
- * dbg_print: prints the common part of the event
- * @addr: endpoint address
- * @name: event name
- * @status: status
- * @extra: extra information
- */
-static void dbg_print(u8 addr, const char *name, int status, const char *extra)
-{
- struct timeval tval;
- unsigned int stamp;
- unsigned long flags;
-
- write_lock_irqsave(&dbg_data.lck, flags);
-
- do_gettimeofday(&tval);
- stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
- stamp = stamp * 1000000 + tval.tv_usec;
-
- scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
- "%04X\t? %02X %-7.7s %4i ?\t%s\n",
- stamp, addr, name, status, extra);
-
- dbg_inc(&dbg_data.idx);
-
- write_unlock_irqrestore(&dbg_data.lck, flags);
-
- if (dbg_data.tty != 0)
- pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
- stamp, addr, name, status, extra);
-}
-
-/**
- * dbg_done: prints a DONE event
- * @addr: endpoint address
- * @td: transfer descriptor
- * @status: status
- */
-static void dbg_done(u8 addr, const u32 token, int status)
-{
- char msg[DBG_DATA_MSG];
-
- scnprintf(msg, sizeof(msg), "%d %02X",
- (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
- (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
- dbg_print(addr, "DONE", status, msg);
-}
-
-/**
- * dbg_event: prints a generic event
- * @addr: endpoint address
- * @name: event name
- * @status: status
- */
-static void dbg_event(u8 addr, const char *name, int status)
-{
- if (name != NULL)
- dbg_print(addr, name, status, "");
-}
-
-/*
- * dbg_queue: prints a QUEUE event
- * @addr: endpoint address
- * @req: USB request
- * @status: status
- */
-static void dbg_queue(u8 addr, const struct usb_request *req, int status)
-{
- char msg[DBG_DATA_MSG];
-
- if (req != NULL) {
- scnprintf(msg, sizeof(msg),
- "%d %d", !req->no_interrupt, req->length);
- dbg_print(addr, "QUEUE", status, msg);
- }
-}
-
-/**
- * dbg_setup: prints a SETUP event
- * @addr: endpoint address
- * @req: setup request
- */
-static void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
-{
- char msg[DBG_DATA_MSG];
-
- if (req != NULL) {
- scnprintf(msg, sizeof(msg),
- "%02X %02X %04X %04X %d", req->bRequestType,
- req->bRequest, le16_to_cpu(req->wValue),
- le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
- dbg_print(addr, "SETUP", 0, msg);
- }
-}
-
-/**
- * show_events: displays the event buffer
- *
- * Check "device.h" for details
- */
-static ssize_t show_events(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- unsigned long flags;
- unsigned i, j, n = 0;
-
- dbg_trace("[%s] %p\n", __func__, buf);
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- return 0;
- }
-
- read_lock_irqsave(&dbg_data.lck, flags);
-
- i = dbg_data.idx;
- for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
- n += strlen(dbg_data.buf[i]);
- if (n >= PAGE_SIZE) {
- n -= strlen(dbg_data.buf[i]);
- break;
- }
- }
- for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
- j += scnprintf(buf + j, PAGE_SIZE - j,
- "%s", dbg_data.buf[i]);
-
- read_unlock_irqrestore(&dbg_data.lck, flags);
-
- return n;
-}
-
-/**
- * store_events: configure if events are going to be also printed to console
- *
- * Check "device.h" for details
- */
-static ssize_t store_events(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned tty;
-
- dbg_trace("[%s] %p, %d\n", __func__, buf, count);
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- goto done;
- }
-
- if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
- dev_err(dev, "<1|0>: enable|disable console log\n");
- goto done;
- }
-
- dbg_data.tty = tty;
- dev_info(dev, "tty = %u", dbg_data.tty);
-
- done:
- return count;
-}
-static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
-
-/**
- * show_inters: interrupt status, enable status and historic
- *
- * Check "device.h" for details
- */
-static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
- unsigned long flags;
- u32 intr;
- unsigned i, j, n = 0;
-
- dbg_trace("[%s] %p\n", __func__, buf);
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- return 0;
- }
-
- spin_lock_irqsave(udc->lock, flags);
-
- n += scnprintf(buf + n, PAGE_SIZE - n,
- "status = %08x\n", hw_read_intr_status());
- n += scnprintf(buf + n, PAGE_SIZE - n,
- "enable = %08x\n", hw_read_intr_enable());
-
- n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
- isr_statistics.test);
- n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n",
- isr_statistics.ui);
- n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
- isr_statistics.uei);
- n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
- isr_statistics.pci);
- n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
- isr_statistics.uri);
- n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
- isr_statistics.sli);
- n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
- isr_statistics.none);
- n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
- isr_statistics.hndl.cnt);
-
- for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
- i &= ISR_MASK;
- intr = isr_statistics.hndl.buf[i];
-
- if (USBi_UI & intr)
- n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
- intr &= ~USBi_UI;
- if (USBi_UEI & intr)
- n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
- intr &= ~USBi_UEI;
- if (USBi_PCI & intr)
- n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
- intr &= ~USBi_PCI;
- if (USBi_URI & intr)
- n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
- intr &= ~USBi_URI;
- if (USBi_SLI & intr)
- n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
- intr &= ~USBi_SLI;
- if (intr)
- n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
- if (isr_statistics.hndl.buf[i])
- n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
- }
-
- spin_unlock_irqrestore(udc->lock, flags);
-
- return n;
-}
-
-/**
- * store_inters: enable & force or disable an individual interrutps
- * (to be used for test purposes only)
- *
- * Check "device.h" for details
- */
-static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
- unsigned long flags;
- unsigned en, bit;
-
- dbg_trace("[%s] %p, %d\n", __func__, buf, count);
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- goto done;
- }
-
- if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
- dev_err(dev, "<1|0> <bit>: enable|disable interrupt");
- goto done;
- }
-
- spin_lock_irqsave(udc->lock, flags);
- if (en) {
- if (hw_intr_force(bit))
- dev_err(dev, "invalid bit number\n");
- else
- isr_statistics.test++;
- } else {
- if (hw_intr_clear(bit))
- dev_err(dev, "invalid bit number\n");
- }
- spin_unlock_irqrestore(udc->lock, flags);
-
- done:
- return count;
-}
-static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
-
-/**
- * show_port_test: reads port test mode
- *
- * Check "device.h" for details
- */
-static ssize_t show_port_test(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
- unsigned long flags;
- unsigned mode;
-
- dbg_trace("[%s] %p\n", __func__, buf);
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- return 0;
- }
-
- spin_lock_irqsave(udc->lock, flags);
- mode = hw_port_test_get();
- spin_unlock_irqrestore(udc->lock, flags);
-
- return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
-}
-
-/**
- * store_port_test: writes port test mode
- *
- * Check "device.h" for details
- */
-static ssize_t store_port_test(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
- unsigned long flags;
- unsigned mode;
-
- dbg_trace("[%s] %p, %d\n", __func__, buf, count);
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- goto done;
- }
-
- if (sscanf(buf, "%u", &mode) != 1) {
- dev_err(dev, "<mode>: set port test mode");
- goto done;
- }
-
- spin_lock_irqsave(udc->lock, flags);
- if (hw_port_test_set(mode))
- dev_err(dev, "invalid mode\n");
- spin_unlock_irqrestore(udc->lock, flags);
-
- done:
- return count;
-}
-static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
- show_port_test, store_port_test);
-
-/**
- * show_qheads: DMA contents of all queue heads
- *
- * Check "device.h" for details
- */
-static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
- unsigned long flags;
- unsigned i, j, n = 0;
-
- dbg_trace("[%s] %p\n", __func__, buf);
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- return 0;
- }
-
- spin_lock_irqsave(udc->lock, flags);
- for (i = 0; i < hw_ep_max/2; i++) {
- struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
- struct ci13xxx_ep *mEpTx = &udc->ci13xxx_ep[i + hw_ep_max/2];
- n += scnprintf(buf + n, PAGE_SIZE - n,
- "EP=%02i: RX=%08X TX=%08X\n",
- i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
- for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
- n += scnprintf(buf + n, PAGE_SIZE - n,
- " %04X: %08X %08X\n", j,
- *((u32 *)mEpRx->qh.ptr + j),
- *((u32 *)mEpTx->qh.ptr + j));
- }
- }
- spin_unlock_irqrestore(udc->lock, flags);
-
- return n;
-}
-static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
-
-/**
- * show_registers: dumps all registers
- *
- * Check "device.h" for details
- */
-#define DUMP_ENTRIES 512
-static ssize_t show_registers(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
- unsigned long flags;
- u32 *dump;
- unsigned i, k, n = 0;
-
- dbg_trace("[%s] %p\n", __func__, buf);
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- return 0;
- }
-
- dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
- if (!dump) {
- dev_err(dev, "%s: out of memory\n", __func__);
- return 0;
- }
-
- spin_lock_irqsave(udc->lock, flags);
- k = hw_register_read(dump, DUMP_ENTRIES);
- spin_unlock_irqrestore(udc->lock, flags);
-
- for (i = 0; i < k; i++) {
- n += scnprintf(buf + n, PAGE_SIZE - n,
- "reg[0x%04X] = 0x%08X\n",
- i * (unsigned)sizeof(u32), dump[i]);
- }
- kfree(dump);
-
- return n;
-}
-
-/**
- * store_registers: writes value to register address
- *
- * Check "device.h" for details
- */
-static ssize_t store_registers(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
- unsigned long addr, data, flags;
-
- dbg_trace("[%s] %p, %d\n", __func__, buf, count);
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- goto done;
- }
-
- if (sscanf(buf, "%li %li", &addr, &data) != 2) {
- dev_err(dev, "<addr> <data>: write data to register address");
- goto done;
- }
-
- spin_lock_irqsave(udc->lock, flags);
- if (hw_register_write(addr, data))
- dev_err(dev, "invalid address range\n");
- spin_unlock_irqrestore(udc->lock, flags);
-
- done:
- return count;
-}
-static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
- show_registers, store_registers);
-
-/**
- * show_requests: DMA contents of all requests currently queued (all endpts)
- *
- * Check "device.h" for details
- */
-static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
- unsigned long flags;
- struct list_head *ptr = NULL;
- struct ci13xxx_req *req = NULL;
- unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
-
- dbg_trace("[%s] %p\n", __func__, buf);
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- return 0;
- }
-
- spin_lock_irqsave(udc->lock, flags);
- for (i = 0; i < hw_ep_max; i++)
- list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
- {
- req = list_entry(ptr, struct ci13xxx_req, queue);
-
- n += scnprintf(buf + n, PAGE_SIZE - n,
- "EP=%02i: TD=%08X %s\n",
- i % hw_ep_max/2, (u32)req->dma,
- ((i < hw_ep_max/2) ? "RX" : "TX"));
-
- for (j = 0; j < qSize; j++)
- n += scnprintf(buf + n, PAGE_SIZE - n,
- " %04X: %08X\n", j,
- *((u32 *)req->ptr + j));
- }
- spin_unlock_irqrestore(udc->lock, flags);
-
- return n;
-}
-static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
-
-/**
- * dbg_create_files: initializes the attribute interface
- * @dev: device
- *
- * This function returns an error code
- */
-__maybe_unused static int dbg_create_files(struct device *dev)
-{
- int retval = 0;
-
- if (dev == NULL)
- return -EINVAL;
- retval = device_create_file(dev, &dev_attr_device);
- if (retval)
- goto done;
- retval = device_create_file(dev, &dev_attr_driver);
- if (retval)
- goto rm_device;
- retval = device_create_file(dev, &dev_attr_events);
- if (retval)
- goto rm_driver;
- retval = device_create_file(dev, &dev_attr_inters);
- if (retval)
- goto rm_events;
- retval = device_create_file(dev, &dev_attr_port_test);
- if (retval)
- goto rm_inters;
- retval = device_create_file(dev, &dev_attr_qheads);
- if (retval)
- goto rm_port_test;
- retval = device_create_file(dev, &dev_attr_registers);
- if (retval)
- goto rm_qheads;
- retval = device_create_file(dev, &dev_attr_requests);
- if (retval)
- goto rm_registers;
- return 0;
-
- rm_registers:
- device_remove_file(dev, &dev_attr_registers);
- rm_qheads:
- device_remove_file(dev, &dev_attr_qheads);
- rm_port_test:
- device_remove_file(dev, &dev_attr_port_test);
- rm_inters:
- device_remove_file(dev, &dev_attr_inters);
- rm_events:
- device_remove_file(dev, &dev_attr_events);
- rm_driver:
- device_remove_file(dev, &dev_attr_driver);
- rm_device:
- device_remove_file(dev, &dev_attr_device);
- done:
- return retval;
-}
-
-/**
- * dbg_remove_files: destroys the attribute interface
- * @dev: device
- *
- * This function returns an error code
- */
-__maybe_unused static int dbg_remove_files(struct device *dev)
-{
- if (dev == NULL)
- return -EINVAL;
- device_remove_file(dev, &dev_attr_requests);
- device_remove_file(dev, &dev_attr_registers);
- device_remove_file(dev, &dev_attr_qheads);
- device_remove_file(dev, &dev_attr_port_test);
- device_remove_file(dev, &dev_attr_inters);
- device_remove_file(dev, &dev_attr_events);
- device_remove_file(dev, &dev_attr_driver);
- device_remove_file(dev, &dev_attr_device);
- return 0;
-}
-
-/******************************************************************************
- * UTIL block
- *****************************************************************************/
-/**
- * _usb_addr: calculates endpoint address from direction & number
- * @ep: endpoint
- */
-static inline u8 _usb_addr(struct ci13xxx_ep *ep)
-{
- return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num;
-}
-
-/**
- * _hardware_queue: configures a request at hardware level
- * @gadget: gadget
- * @mEp: endpoint
- *
- * This function returns an error code
- */
-static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
-{
- unsigned i;
- int ret = 0;
- unsigned length = mReq->req.length;
-
- trace("%p, %p", mEp, mReq);
-
- /* don't queue twice */
- if (mReq->req.status == -EALREADY)
- return -EALREADY;
-
- mReq->req.status = -EALREADY;
- if (length && mReq->req.dma == DMA_ADDR_INVALID) {
- mReq->req.dma = \
- dma_map_single(mEp->device, mReq->req.buf,
- length, mEp->dir ? DMA_TO_DEVICE :
- DMA_FROM_DEVICE);
- if (mReq->req.dma == 0)
- return -ENOMEM;
-
- mReq->map = 1;
- }
-
- if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
- mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
- &mReq->zdma);
- if (mReq->zptr == NULL) {
- if (mReq->map) {
- dma_unmap_single(mEp->device, mReq->req.dma,
- length, mEp->dir ? DMA_TO_DEVICE :
- DMA_FROM_DEVICE);
- mReq->req.dma = DMA_ADDR_INVALID;
- mReq->map = 0;
- }
- return -ENOMEM;
- }
- memset(mReq->zptr, 0, sizeof(*mReq->zptr));
- mReq->zptr->next = TD_TERMINATE;
- mReq->zptr->token = TD_STATUS_ACTIVE;
- if (!mReq->req.no_interrupt)
- mReq->zptr->token |= TD_IOC;
- }
- /*
- * TD configuration
- * TODO - handle requests which spawns into several TDs
- */
- memset(mReq->ptr, 0, sizeof(*mReq->ptr));
- mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
- mReq->ptr->token &= TD_TOTAL_BYTES;
- mReq->ptr->token |= TD_STATUS_ACTIVE;
- if (mReq->zptr) {
- mReq->ptr->next = mReq->zdma;
- } else {
- mReq->ptr->next = TD_TERMINATE;
- if (!mReq->req.no_interrupt)
- mReq->ptr->token |= TD_IOC;
- }
- mReq->ptr->page[0] = mReq->req.dma;
- for (i = 1; i < 5; i++)
- mReq->ptr->page[i] =
- (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
-
- if (!list_empty(&mEp->qh.queue)) {
- struct ci13xxx_req *mReqPrev;
- int n = hw_ep_bit(mEp->num, mEp->dir);
- int tmp_stat;
-
- mReqPrev = list_entry(mEp->qh.queue.prev,
- struct ci13xxx_req, queue);
- if (mReqPrev->zptr)
- mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
- else
- mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
- wmb();
- if (hw_cread(CAP_ENDPTPRIME, BIT(n)))
- goto done;
- do {
- hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
- tmp_stat = hw_cread(CAP_ENDPTSTAT, BIT(n));
- } while (!hw_cread(CAP_USBCMD, USBCMD_ATDTW));
- hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, 0);
- if (tmp_stat)
- goto done;
- }
-
- /* QH configuration */
- mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
- mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
- mEp->qh.ptr->cap |= QH_ZLT;
-
- wmb(); /* synchronize before ep prime */
-
- ret = hw_ep_prime(mEp->num, mEp->dir,
- mEp->type == USB_ENDPOINT_XFER_CONTROL);
-done:
- return ret;
-}
-
-/**
- * _hardware_dequeue: handles a request at hardware level
- * @gadget: gadget
- * @mEp: endpoint
- *
- * This function returns an error code
- */
-static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
-{
- trace("%p, %p", mEp, mReq);
-
- if (mReq->req.status != -EALREADY)
- return -EINVAL;
-
- if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
- return -EBUSY;
-
- if (mReq->zptr) {
- if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
- return -EBUSY;
- dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
- mReq->zptr = NULL;
- }
-
- mReq->req.status = 0;
-
- if (mReq->map) {
- dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
- mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- mReq->req.dma = DMA_ADDR_INVALID;
- mReq->map = 0;
- }
-
- mReq->req.status = mReq->ptr->token & TD_STATUS;
- if ((TD_STATUS_HALTED & mReq->req.status) != 0)
- mReq->req.status = -1;
- else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
- mReq->req.status = -1;
- else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
- mReq->req.status = -1;
-
- mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
- mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
- mReq->req.actual = mReq->req.length - mReq->req.actual;
- mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
-
- return mReq->req.actual;
-}
-
-/**
- * _ep_nuke: dequeues all endpoint requests
- * @mEp: endpoint
- *
- * This function returns an error code
- * Caller must hold lock
- */
-static int _ep_nuke(struct ci13xxx_ep *mEp)
-__releases(mEp->lock)
-__acquires(mEp->lock)
-{
- trace("%p", mEp);
-
- if (mEp == NULL)
- return -EINVAL;
-
- hw_ep_flush(mEp->num, mEp->dir);
-
- while (!list_empty(&mEp->qh.queue)) {
-
- /* pop oldest request */
- struct ci13xxx_req *mReq = \
- list_entry(mEp->qh.queue.next,
- struct ci13xxx_req, queue);
- list_del_init(&mReq->queue);
- mReq->req.status = -ESHUTDOWN;
-
- if (mReq->req.complete != NULL) {
- spin_unlock(mEp->lock);
- mReq->req.complete(&mEp->ep, &mReq->req);
- spin_lock(mEp->lock);
- }
- }
- return 0;
-}
-
-/**
- * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
- * @gadget: gadget
- *
- * This function returns an error code
- */
-static int _gadget_stop_activity(struct usb_gadget *gadget)
-{
- struct usb_ep *ep;
- struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
- unsigned long flags;
-
- trace("%p", gadget);
-
- if (gadget == NULL)
- return -EINVAL;
-
- spin_lock_irqsave(udc->lock, flags);
- udc->gadget.speed = USB_SPEED_UNKNOWN;
- udc->remote_wakeup = 0;
- udc->suspended = 0;
- spin_unlock_irqrestore(udc->lock, flags);
-
- /* flush all endpoints */
- gadget_for_each_ep(ep, gadget) {
- usb_ep_fifo_flush(ep);
- }
- usb_ep_fifo_flush(&udc->ep0out.ep);
- usb_ep_fifo_flush(&udc->ep0in.ep);
-
- udc->driver->disconnect(gadget);
-
- /* make sure to disable all endpoints */
- gadget_for_each_ep(ep, gadget) {
- usb_ep_disable(ep);
- }
-
- if (udc->status != NULL) {
- usb_ep_free_request(&udc->ep0in.ep, udc->status);
- udc->status = NULL;
- }
-
- return 0;
-}
-
-/******************************************************************************
- * ISR block
- *****************************************************************************/
-/**
- * isr_reset_handler: USB reset interrupt handler
- * @udc: UDC device
- *
- * This function resets USB engine after a bus reset occurred
- */
-static void isr_reset_handler(struct ci13xxx *udc)
-__releases(udc->lock)
-__acquires(udc->lock)
-{
- int retval;
-
- trace("%p", udc);
-
- if (udc == NULL) {
- err("EINVAL");
- return;
- }
-
- dbg_event(0xFF, "BUS RST", 0);
-
- spin_unlock(udc->lock);
- retval = _gadget_stop_activity(&udc->gadget);
- if (retval)
- goto done;
-
- retval = hw_usb_reset();
- if (retval)
- goto done;
-
- udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC);
- if (udc->status == NULL)
- retval = -ENOMEM;
-
- spin_lock(udc->lock);
-
- done:
- if (retval)
- err("error: %i", retval);
-}
-
-/**
- * isr_get_status_complete: get_status request complete function
- * @ep: endpoint
- * @req: request handled
- *
- * Caller must release lock
- */
-static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
-{
- trace("%p, %p", ep, req);
-
- if (ep == NULL || req == NULL) {
- err("EINVAL");
- return;
- }
-
- kfree(req->buf);
- usb_ep_free_request(ep, req);
-}
-
-/**
- * isr_get_status_response: get_status request response
- * @udc: udc struct
- * @setup: setup request packet
- *
- * This function returns an error code
- */
-static int isr_get_status_response(struct ci13xxx *udc,
- struct usb_ctrlrequest *setup)
-__releases(mEp->lock)
-__acquires(mEp->lock)
-{
- struct ci13xxx_ep *mEp = &udc->ep0in;
- struct usb_request *req = NULL;
- gfp_t gfp_flags = GFP_ATOMIC;
- int dir, num, retval;
-
- trace("%p, %p", mEp, setup);
-
- if (mEp == NULL || setup == NULL)
- return -EINVAL;
-
- spin_unlock(mEp->lock);
- req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
- spin_lock(mEp->lock);
- if (req == NULL)
- return -ENOMEM;
-
- req->complete = isr_get_status_complete;
- req->length = 2;
- req->buf = kzalloc(req->length, gfp_flags);
- if (req->buf == NULL) {
- retval = -ENOMEM;
- goto err_free_req;
- }
-
- if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
- /* Assume that device is bus powered for now. */
- *((u16 *)req->buf) = _udc->remote_wakeup << 1;
- retval = 0;
- } else if ((setup->bRequestType & USB_RECIP_MASK) \
- == USB_RECIP_ENDPOINT) {
- dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
- TX : RX;
- num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
- *((u16 *)req->buf) = hw_ep_get_halt(num, dir);
- }
- /* else do nothing; reserved for future use */
-
- spin_unlock(mEp->lock);
- retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
- spin_lock(mEp->lock);
- if (retval)
- goto err_free_buf;
-
- return 0;
-
- err_free_buf:
- kfree(req->buf);
- err_free_req:
- spin_unlock(mEp->lock);
- usb_ep_free_request(&mEp->ep, req);
- spin_lock(mEp->lock);
- return retval;
-}
-
-/**
- * isr_setup_status_complete: setup_status request complete function
- * @ep: endpoint
- * @req: request handled
- *
- * Caller must release lock. Put the port in test mode if test mode
- * feature is selected.
- */
-static void
-isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct ci13xxx *udc = req->context;
- unsigned long flags;
-
- trace("%p, %p", ep, req);
-
- spin_lock_irqsave(udc->lock, flags);
- if (udc->test_mode)
- hw_port_test_set(udc->test_mode);
- spin_unlock_irqrestore(udc->lock, flags);
-}
-
-/**
- * isr_setup_status_phase: queues the status phase of a setup transation
- * @udc: udc struct
- *
- * This function returns an error code
- */
-static int isr_setup_status_phase(struct ci13xxx *udc)
-__releases(mEp->lock)
-__acquires(mEp->lock)
-{
- int retval;
- struct ci13xxx_ep *mEp;
-
- trace("%p", udc);
-
- mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in;
- udc->status->context = udc;
- udc->status->complete = isr_setup_status_complete;
-
- spin_unlock(mEp->lock);
- retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
- spin_lock(mEp->lock);
-
- return retval;
-}
-
-/**
- * isr_tr_complete_low: transaction complete low level handler
- * @mEp: endpoint
- *
- * This function returns an error code
- * Caller must hold lock
- */
-static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
-__releases(mEp->lock)
-__acquires(mEp->lock)
-{
- struct ci13xxx_req *mReq, *mReqTemp;
- struct ci13xxx_ep *mEpTemp = mEp;
- int uninitialized_var(retval);
-
- trace("%p", mEp);
-
- if (list_empty(&mEp->qh.queue))
- return -EINVAL;
-
- list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
- queue) {
- retval = _hardware_dequeue(mEp, mReq);
- if (retval < 0)
- break;
- list_del_init(&mReq->queue);
- dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
- if (mReq->req.complete != NULL) {
- spin_unlock(mEp->lock);
- if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
- mReq->req.length)
- mEpTemp = &_udc->ep0in;
- mReq->req.complete(&mEpTemp->ep, &mReq->req);
- spin_lock(mEp->lock);
- }
- }
-
- if (retval == -EBUSY)
- retval = 0;
- if (retval < 0)
- dbg_event(_usb_addr(mEp), "DONE", retval);
-
- return retval;
-}
-
-/**
- * isr_tr_complete_handler: transaction complete interrupt handler
- * @udc: UDC descriptor
- *
- * This function handles traffic events
- */
-static void isr_tr_complete_handler(struct ci13xxx *udc)
-__releases(udc->lock)
-__acquires(udc->lock)
-{
- unsigned i;
- u8 tmode = 0;
-
- trace("%p", udc);
-
- if (udc == NULL) {
- err("EINVAL");
- return;
- }
-
- for (i = 0; i < hw_ep_max; i++) {
- struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
- int type, num, dir, err = -EINVAL;
- struct usb_ctrlrequest req;
-
- if (mEp->desc == NULL)
- continue; /* not configured */
-
- if (hw_test_and_clear_complete(i)) {
- err = isr_tr_complete_low(mEp);
- if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
- if (err > 0) /* needs status phase */
- err = isr_setup_status_phase(udc);
- if (err < 0) {
- dbg_event(_usb_addr(mEp),
- "ERROR", err);
- spin_unlock(udc->lock);
- if (usb_ep_set_halt(&mEp->ep))
- err("error: ep_set_halt");
- spin_lock(udc->lock);
- }
- }
- }
-
- if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
- !hw_test_and_clear_setup_status(i))
- continue;
-
- if (i != 0) {
- warn("ctrl traffic received at endpoint");
- continue;
- }
-
- /*
- * Flush data and handshake transactions of previous
- * setup packet.
- */
- _ep_nuke(&udc->ep0out);
- _ep_nuke(&udc->ep0in);
-
- /* read_setup_packet */
- do {
- hw_test_and_set_setup_guard();
- memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
- } while (!hw_test_and_clear_setup_guard());
-
- type = req.bRequestType;
-
- udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
-
- dbg_setup(_usb_addr(mEp), &req);
-
- switch (req.bRequest) {
- case USB_REQ_CLEAR_FEATURE:
- if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
- le16_to_cpu(req.wValue) ==
- USB_ENDPOINT_HALT) {
- if (req.wLength != 0)
- break;
- num = le16_to_cpu(req.wIndex);
- dir = num & USB_ENDPOINT_DIR_MASK;
- num &= USB_ENDPOINT_NUMBER_MASK;
- if (dir) /* TX */
- num += hw_ep_max/2;
- if (!udc->ci13xxx_ep[num].wedge) {
- spin_unlock(udc->lock);
- err = usb_ep_clear_halt(
- &udc->ci13xxx_ep[num].ep);
- spin_lock(udc->lock);
- if (err)
- break;
- }
- err = isr_setup_status_phase(udc);
- } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
- le16_to_cpu(req.wValue) ==
- USB_DEVICE_REMOTE_WAKEUP) {
- if (req.wLength != 0)
- break;
- udc->remote_wakeup = 0;
- err = isr_setup_status_phase(udc);
- } else {
- goto delegate;
- }
- break;
- case USB_REQ_GET_STATUS:
- if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
- type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
- type != (USB_DIR_IN|USB_RECIP_INTERFACE))
- goto delegate;
- if (le16_to_cpu(req.wLength) != 2 ||
- le16_to_cpu(req.wValue) != 0)
- break;
- err = isr_get_status_response(udc, &req);
- break;
- case USB_REQ_SET_ADDRESS:
- if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
- goto delegate;
- if (le16_to_cpu(req.wLength) != 0 ||
- le16_to_cpu(req.wIndex) != 0)
- break;
- err = hw_usb_set_address((u8)le16_to_cpu(req.wValue));
- if (err)
- break;
- err = isr_setup_status_phase(udc);
- break;
- case USB_REQ_SET_FEATURE:
- if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
- le16_to_cpu(req.wValue) ==
- USB_ENDPOINT_HALT) {
- if (req.wLength != 0)
- break;
- num = le16_to_cpu(req.wIndex);
- dir = num & USB_ENDPOINT_DIR_MASK;
- num &= USB_ENDPOINT_NUMBER_MASK;
- if (dir) /* TX */
- num += hw_ep_max/2;
-
- spin_unlock(udc->lock);
- err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
- spin_lock(udc->lock);
- if (!err)
- isr_setup_status_phase(udc);
- } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
- if (req.wLength != 0)
- break;
- switch (le16_to_cpu(req.wValue)) {
- case USB_DEVICE_REMOTE_WAKEUP:
- udc->remote_wakeup = 1;
- err = isr_setup_status_phase(udc);
- break;
- case USB_DEVICE_TEST_MODE:
- tmode = le16_to_cpu(req.wIndex) >> 8;
- switch (tmode) {
- case TEST_J:
- case TEST_K:
- case TEST_SE0_NAK:
- case TEST_PACKET:
- case TEST_FORCE_EN:
- udc->test_mode = tmode;
- err = isr_setup_status_phase(
- udc);
- break;
- default:
- break;
- }
- default:
- goto delegate;
- }
- } else {
- goto delegate;
- }
- break;
- default:
-delegate:
- if (req.wLength == 0) /* no data phase */
- udc->ep0_dir = TX;
-
- spin_unlock(udc->lock);
- err = udc->driver->setup(&udc->gadget, &req);
- spin_lock(udc->lock);
- break;
- }
-
- if (err < 0) {
- dbg_event(_usb_addr(mEp), "ERROR", err);
-
- spin_unlock(udc->lock);
- if (usb_ep_set_halt(&mEp->ep))
- err("error: ep_set_halt");
- spin_lock(udc->lock);
- }
- }
-}
-
-/******************************************************************************
- * ENDPT block
- *****************************************************************************/
-/**
- * ep_enable: configure endpoint, making it usable
- *
- * Check usb_ep_enable() at "usb_gadget.h" for details
- */
-static int ep_enable(struct usb_ep *ep,
- const struct usb_endpoint_descriptor *desc)
-{
- struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
- int retval = 0;
- unsigned long flags;
-
- trace("%p, %p", ep, desc);
-
- if (ep == NULL || desc == NULL)
- return -EINVAL;
-
- spin_lock_irqsave(mEp->lock, flags);
-
- /* only internal SW should enable ctrl endpts */
-
- mEp->desc = desc;
-
- if (!list_empty(&mEp->qh.queue))
- warn("enabling a non-empty endpoint!");
-
- mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
- mEp->num = usb_endpoint_num(desc);
- mEp->type = usb_endpoint_type(desc);
-
- mEp->ep.maxpacket = usb_endpoint_maxp(desc);
-
- dbg_event(_usb_addr(mEp), "ENABLE", 0);
-
- mEp->qh.ptr->cap = 0;
-
- if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
- mEp->qh.ptr->cap |= QH_IOS;
- else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
- mEp->qh.ptr->cap &= ~QH_MULT;
- else
- mEp->qh.ptr->cap &= ~QH_ZLT;
-
- mEp->qh.ptr->cap |=
- (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
- mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
-
- /*
- * Enable endpoints in the HW other than ep0 as ep0
- * is always enabled
- */
- if (mEp->num)
- retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type);
-
- spin_unlock_irqrestore(mEp->lock, flags);
- return retval;
-}
-
-/**
- * ep_disable: endpoint is no longer usable
- *
- * Check usb_ep_disable() at "usb_gadget.h" for details
- */
-static int ep_disable(struct usb_ep *ep)
-{
- struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
- int direction, retval = 0;
- unsigned long flags;
-
- trace("%p", ep);
-
- if (ep == NULL)
- return -EINVAL;
- else if (mEp->desc == NULL)
- return -EBUSY;
-
- spin_lock_irqsave(mEp->lock, flags);
-
- /* only internal SW should disable ctrl endpts */
-
- direction = mEp->dir;
- do {
- dbg_event(_usb_addr(mEp), "DISABLE", 0);
-
- retval |= _ep_nuke(mEp);
- retval |= hw_ep_disable(mEp->num, mEp->dir);
-
- if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
- mEp->dir = (mEp->dir == TX) ? RX : TX;
-
- } while (mEp->dir != direction);
-
- mEp->desc = NULL;
- mEp->ep.desc = NULL;
-
- spin_unlock_irqrestore(mEp->lock, flags);
- return retval;
-}
-
-/**
- * ep_alloc_request: allocate a request object to use with this endpoint
- *
- * Check usb_ep_alloc_request() at "usb_gadget.h" for details
- */
-static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
-{
- struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
- struct ci13xxx_req *mReq = NULL;
-
- trace("%p, %i", ep, gfp_flags);
-
- if (ep == NULL) {
- err("EINVAL");
- return NULL;
- }
-
- mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
- if (mReq != NULL) {
- INIT_LIST_HEAD(&mReq->queue);
- mReq->req.dma = DMA_ADDR_INVALID;
-
- mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
- &mReq->dma);
- if (mReq->ptr == NULL) {
- kfree(mReq);
- mReq = NULL;
- }
- }
-
- dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
-
- return (mReq == NULL) ? NULL : &mReq->req;
-}
-
-/**
- * ep_free_request: frees a request object
- *
- * Check usb_ep_free_request() at "usb_gadget.h" for details
- */
-static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
-{
- struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
- struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
- unsigned long flags;
-
- trace("%p, %p", ep, req);
-
- if (ep == NULL || req == NULL) {
- err("EINVAL");
- return;
- } else if (!list_empty(&mReq->queue)) {
- err("EBUSY");
- return;
- }
-
- spin_lock_irqsave(mEp->lock, flags);
-
- if (mReq->ptr)
- dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
- kfree(mReq);
-
- dbg_event(_usb_addr(mEp), "FREE", 0);
-
- spin_unlock_irqrestore(mEp->lock, flags);
-}
-
-/**
- * ep_queue: queues (submits) an I/O request to an endpoint
- *
- * Check usb_ep_queue()* at usb_gadget.h" for details
- */
-static int ep_queue(struct usb_ep *ep, struct usb_request *req,
- gfp_t __maybe_unused gfp_flags)
-{
- struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
- struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
- int retval = 0;
- unsigned long flags;
-
- trace("%p, %p, %X", ep, req, gfp_flags);
-
- if (ep == NULL || req == NULL || mEp->desc == NULL)
- return -EINVAL;
-
- spin_lock_irqsave(mEp->lock, flags);
-
- if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
- if (req->length)
- mEp = (_udc->ep0_dir == RX) ?
- &_udc->ep0out : &_udc->ep0in;
- if (!list_empty(&mEp->qh.queue)) {
- _ep_nuke(mEp);
- retval = -EOVERFLOW;
- warn("endpoint ctrl %X nuked", _usb_addr(mEp));
- }
- }
-
- /* first nuke then test link, e.g. previous status has not sent */
- if (!list_empty(&mReq->queue)) {
- retval = -EBUSY;
- err("request already in queue");
- goto done;
- }
-
- if (req->length > (4 * CI13XXX_PAGE_SIZE)) {
- req->length = (4 * CI13XXX_PAGE_SIZE);
- retval = -EMSGSIZE;
- warn("request length truncated");
- }
-
- dbg_queue(_usb_addr(mEp), req, retval);
-
- /* push request */
- mReq->req.status = -EINPROGRESS;
- mReq->req.actual = 0;
-
- retval = _hardware_enqueue(mEp, mReq);
-
- if (retval == -EALREADY) {
- dbg_event(_usb_addr(mEp), "QUEUE", retval);
- retval = 0;
- }
- if (!retval)
- list_add_tail(&mReq->queue, &mEp->qh.queue);
-
- done:
- spin_unlock_irqrestore(mEp->lock, flags);
- return retval;
-}
-
-/**
- * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
- *
- * Check usb_ep_dequeue() at "usb_gadget.h" for details
- */
-static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
-{
- struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
- struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
- unsigned long flags;
-
- trace("%p, %p", ep, req);
-
- if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
- mEp->desc == NULL || list_empty(&mReq->queue) ||
- list_empty(&mEp->qh.queue))
- return -EINVAL;
-
- spin_lock_irqsave(mEp->lock, flags);
-
- dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
-
- hw_ep_flush(mEp->num, mEp->dir);
-
- /* pop request */
- list_del_init(&mReq->queue);
- if (mReq->map) {
- dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
- mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- mReq->req.dma = DMA_ADDR_INVALID;
- mReq->map = 0;
- }
- req->status = -ECONNRESET;
-
- if (mReq->req.complete != NULL) {
- spin_unlock(mEp->lock);
- mReq->req.complete(&mEp->ep, &mReq->req);
- spin_lock(mEp->lock);
- }
-
- spin_unlock_irqrestore(mEp->lock, flags);
- return 0;
-}
-
-/**
- * ep_set_halt: sets the endpoint halt feature
- *
- * Check usb_ep_set_halt() at "usb_gadget.h" for details
- */
-static int ep_set_halt(struct usb_ep *ep, int value)
-{
- struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
- int direction, retval = 0;
- unsigned long flags;
-
- trace("%p, %i", ep, value);
-
- if (ep == NULL || mEp->desc == NULL)
- return -EINVAL;
-
- spin_lock_irqsave(mEp->lock, flags);
-
-#ifndef STALL_IN
- /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
- if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
- !list_empty(&mEp->qh.queue)) {
- spin_unlock_irqrestore(mEp->lock, flags);
- return -EAGAIN;
- }
-#endif
-
- direction = mEp->dir;
- do {
- dbg_event(_usb_addr(mEp), "HALT", value);
- retval |= hw_ep_set_halt(mEp->num, mEp->dir, value);
-
- if (!value)
- mEp->wedge = 0;
-
- if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
- mEp->dir = (mEp->dir == TX) ? RX : TX;
-
- } while (mEp->dir != direction);
-
- spin_unlock_irqrestore(mEp->lock, flags);
- return retval;
-}
-
-/**
- * ep_set_wedge: sets the halt feature and ignores clear requests
- *
- * Check usb_ep_set_wedge() at "usb_gadget.h" for details
- */
-static int ep_set_wedge(struct usb_ep *ep)
-{
- struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
- unsigned long flags;
-
- trace("%p", ep);
-
- if (ep == NULL || mEp->desc == NULL)
- return -EINVAL;
-
- spin_lock_irqsave(mEp->lock, flags);
-
- dbg_event(_usb_addr(mEp), "WEDGE", 0);
- mEp->wedge = 1;
-
- spin_unlock_irqrestore(mEp->lock, flags);
-
- return usb_ep_set_halt(ep);
-}
-
-/**
- * ep_fifo_flush: flushes contents of a fifo
- *
- * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
- */
-static void ep_fifo_flush(struct usb_ep *ep)
-{
- struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
- unsigned long flags;
-
- trace("%p", ep);
-
- if (ep == NULL) {
- err("%02X: -EINVAL", _usb_addr(mEp));
- return;
- }
-
- spin_lock_irqsave(mEp->lock, flags);
-
- dbg_event(_usb_addr(mEp), "FFLUSH", 0);
- hw_ep_flush(mEp->num, mEp->dir);
-
- spin_unlock_irqrestore(mEp->lock, flags);
-}
-
-/**
- * Endpoint-specific part of the API to the USB controller hardware
- * Check "usb_gadget.h" for details
- */
-static const struct usb_ep_ops usb_ep_ops = {
- .enable = ep_enable,
- .disable = ep_disable,
- .alloc_request = ep_alloc_request,
- .free_request = ep_free_request,
- .queue = ep_queue,
- .dequeue = ep_dequeue,
- .set_halt = ep_set_halt,
- .set_wedge = ep_set_wedge,
- .fifo_flush = ep_fifo_flush,
-};
-
-/******************************************************************************
- * GADGET block
- *****************************************************************************/
-static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
-{
- struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
- unsigned long flags;
- int gadget_ready = 0;
-
- if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
- return -EOPNOTSUPP;
-
- spin_lock_irqsave(udc->lock, flags);
- udc->vbus_active = is_active;
- if (udc->driver)
- gadget_ready = 1;
- spin_unlock_irqrestore(udc->lock, flags);
-
- if (gadget_ready) {
- if (is_active) {
- pm_runtime_get_sync(&_gadget->dev);
- hw_device_reset(udc);
- hw_device_state(udc->ep0out.qh.dma);
- } else {
- hw_device_state(0);
- if (udc->udc_driver->notify_event)
- udc->udc_driver->notify_event(udc,
- CI13XXX_CONTROLLER_STOPPED_EVENT);
- _gadget_stop_activity(&udc->gadget);
- pm_runtime_put_sync(&_gadget->dev);
- }
- }
-
- return 0;
-}
-
-static int ci13xxx_wakeup(struct usb_gadget *_gadget)
-{
- struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
- unsigned long flags;
- int ret = 0;
-
- trace();
-
- spin_lock_irqsave(udc->lock, flags);
- if (!udc->remote_wakeup) {
- ret = -EOPNOTSUPP;
- trace("remote wakeup feature is not enabled\n");
- goto out;
- }
- if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
- ret = -EINVAL;
- trace("port is not suspended\n");
- goto out;
- }
- hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR);
-out:
- spin_unlock_irqrestore(udc->lock, flags);
- return ret;
-}
-
-static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
-{
- struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
-
- if (udc->transceiver)
- return usb_phy_set_power(udc->transceiver, mA);
- return -ENOTSUPP;
-}
-
-static int ci13xxx_start(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *));
-static int ci13xxx_stop(struct usb_gadget_driver *driver);
-/**
- * Device operations part of the API to the USB controller hardware,
- * which don't involve endpoints (or i/o)
- * Check "usb_gadget.h" for details
- */
-static const struct usb_gadget_ops usb_gadget_ops = {
- .vbus_session = ci13xxx_vbus_session,
- .wakeup = ci13xxx_wakeup,
- .vbus_draw = ci13xxx_vbus_draw,
- .start = ci13xxx_start,
- .stop = ci13xxx_stop,
-};
-
-/**
- * ci13xxx_start: register a gadget driver
- * @driver: the driver being registered
- * @bind: the driver's bind callback
- *
- * Check ci13xxx_start() at <linux/usb/gadget.h> for details.
- * Interrupts are enabled here.
- */
-static int ci13xxx_start(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *))
-{
- struct ci13xxx *udc = _udc;
- unsigned long flags;
- int i, j;
- int retval = -ENOMEM;
-
- trace("%p", driver);
-
- if (driver == NULL ||
- bind == NULL ||
- driver->setup == NULL ||
- driver->disconnect == NULL)
- return -EINVAL;
- else if (udc == NULL)
- return -ENODEV;
- else if (udc->driver != NULL)
- return -EBUSY;
-
- /* alloc resources */
- udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev,
- sizeof(struct ci13xxx_qh),
- 64, CI13XXX_PAGE_SIZE);
- if (udc->qh_pool == NULL)
- return -ENOMEM;
-
- udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev,
- sizeof(struct ci13xxx_td),
- 64, CI13XXX_PAGE_SIZE);
- if (udc->td_pool == NULL) {
- dma_pool_destroy(udc->qh_pool);
- udc->qh_pool = NULL;
- return -ENOMEM;
- }
-
- spin_lock_irqsave(udc->lock, flags);
-
- info("hw_ep_max = %d", hw_ep_max);
-
- udc->gadget.dev.driver = NULL;
-
- retval = 0;
- for (i = 0; i < hw_ep_max/2; i++) {
- for (j = RX; j <= TX; j++) {
- int k = i + j * hw_ep_max/2;
- struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
-
- scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
- (j == TX) ? "in" : "out");
-
- mEp->lock = udc->lock;
- mEp->device = &udc->gadget.dev;
- mEp->td_pool = udc->td_pool;
-
- mEp->ep.name = mEp->name;
- mEp->ep.ops = &usb_ep_ops;
- mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
-
- INIT_LIST_HEAD(&mEp->qh.queue);
- spin_unlock_irqrestore(udc->lock, flags);
- mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
- &mEp->qh.dma);
- spin_lock_irqsave(udc->lock, flags);
- if (mEp->qh.ptr == NULL)
- retval = -ENOMEM;
- else
- memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
-
- /* skip ep0 out and in endpoints */
- if (i == 0)
- continue;
-
- list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
- }
- }
- if (retval)
- goto done;
- spin_unlock_irqrestore(udc->lock, flags);
- udc->ep0out.ep.desc = &ctrl_endpt_out_desc;
- retval = usb_ep_enable(&udc->ep0out.ep);
- if (retval)
- return retval;
-
- udc->ep0in.ep.desc = &ctrl_endpt_in_desc;
- retval = usb_ep_enable(&udc->ep0in.ep);
- if (retval)
- return retval;
- spin_lock_irqsave(udc->lock, flags);
-
- udc->gadget.ep0 = &udc->ep0in.ep;
- /* bind gadget */
- driver->driver.bus = NULL;
- udc->gadget.dev.driver = &driver->driver;
-
- spin_unlock_irqrestore(udc->lock, flags);
- retval = bind(&udc->gadget); /* MAY SLEEP */
- spin_lock_irqsave(udc->lock, flags);
-
- if (retval) {
- udc->gadget.dev.driver = NULL;
- goto done;
- }
-
- udc->driver = driver;
- pm_runtime_get_sync(&udc->gadget.dev);
- if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
- if (udc->vbus_active) {
- if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
- hw_device_reset(udc);
- } else {
- pm_runtime_put_sync(&udc->gadget.dev);
- goto done;
- }
- }
-
- retval = hw_device_state(udc->ep0out.qh.dma);
- if (retval)
- pm_runtime_put_sync(&udc->gadget.dev);
-
- done:
- spin_unlock_irqrestore(udc->lock, flags);
- return retval;
-}
-
-/**
- * ci13xxx_stop: unregister a gadget driver
- *
- * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
- */
-static int ci13xxx_stop(struct usb_gadget_driver *driver)
-{
- struct ci13xxx *udc = _udc;
- unsigned long i, flags;
-
- trace("%p", driver);
-
- if (driver == NULL ||
- driver->unbind == NULL ||
- driver->setup == NULL ||
- driver->disconnect == NULL ||
- driver != udc->driver)
- return -EINVAL;
-
- spin_lock_irqsave(udc->lock, flags);
-
- if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
- udc->vbus_active) {
- hw_device_state(0);
- if (udc->udc_driver->notify_event)
- udc->udc_driver->notify_event(udc,
- CI13XXX_CONTROLLER_STOPPED_EVENT);
- spin_unlock_irqrestore(udc->lock, flags);
- _gadget_stop_activity(&udc->gadget);
- spin_lock_irqsave(udc->lock, flags);
- pm_runtime_put(&udc->gadget.dev);
- }
-
- /* unbind gadget */
- spin_unlock_irqrestore(udc->lock, flags);
- driver->unbind(&udc->gadget); /* MAY SLEEP */
- spin_lock_irqsave(udc->lock, flags);
-
- udc->gadget.dev.driver = NULL;
-
- /* free resources */
- for (i = 0; i < hw_ep_max; i++) {
- struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
-
- if (!list_empty(&mEp->ep.ep_list))
- list_del_init(&mEp->ep.ep_list);
-
- if (mEp->qh.ptr != NULL)
- dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
- }
-
- udc->gadget.ep0 = NULL;
- udc->driver = NULL;
-
- spin_unlock_irqrestore(udc->lock, flags);
-
- if (udc->td_pool != NULL) {
- dma_pool_destroy(udc->td_pool);
- udc->td_pool = NULL;
- }
- if (udc->qh_pool != NULL) {
- dma_pool_destroy(udc->qh_pool);
- udc->qh_pool = NULL;
- }
-
- return 0;
-}
-
-/******************************************************************************
- * BUS block
- *****************************************************************************/
-/**
- * udc_irq: global interrupt handler
- *
- * This function returns IRQ_HANDLED if the IRQ has been handled
- * It locks access to registers
- */
-static irqreturn_t udc_irq(void)
-{
- struct ci13xxx *udc = _udc;
- irqreturn_t retval;
- u32 intr;
-
- trace();
-
- if (udc == NULL) {
- err("ENODEV");
- return IRQ_HANDLED;
- }
-
- spin_lock(udc->lock);
-
- if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
- if (hw_cread(CAP_USBMODE, USBMODE_CM) !=
- USBMODE_CM_DEVICE) {
- spin_unlock(udc->lock);
- return IRQ_NONE;
- }
- }
- intr = hw_test_and_clear_intr_active();
- if (intr) {
- isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr;
- isr_statistics.hndl.idx &= ISR_MASK;
- isr_statistics.hndl.cnt++;
-
- /* order defines priority - do NOT change it */
- if (USBi_URI & intr) {
- isr_statistics.uri++;
- isr_reset_handler(udc);
- }
- if (USBi_PCI & intr) {
- isr_statistics.pci++;
- udc->gadget.speed = hw_port_is_high_speed() ?
- USB_SPEED_HIGH : USB_SPEED_FULL;
- if (udc->suspended && udc->driver->resume) {
- spin_unlock(udc->lock);
- udc->driver->resume(&udc->gadget);
- spin_lock(udc->lock);
- udc->suspended = 0;
- }
- }
- if (USBi_UEI & intr)
- isr_statistics.uei++;
- if (USBi_UI & intr) {
- isr_statistics.ui++;
- isr_tr_complete_handler(udc);
- }
- if (USBi_SLI & intr) {
- if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
- udc->driver->suspend) {
- udc->suspended = 1;
- spin_unlock(udc->lock);
- udc->driver->suspend(&udc->gadget);
- spin_lock(udc->lock);
- }
- isr_statistics.sli++;
- }
- retval = IRQ_HANDLED;
- } else {
- isr_statistics.none++;
- retval = IRQ_NONE;
- }
- spin_unlock(udc->lock);
-
- return retval;
-}
-
-/**
- * udc_release: driver release function
- * @dev: device
- *
- * Currently does nothing
- */
-static void udc_release(struct device *dev)
-{
- trace("%p", dev);
-
- if (dev == NULL)
- err("EINVAL");
-}
-
-/**
- * udc_probe: parent probe must call this to initialize UDC
- * @dev: parent device
- * @regs: registers base address
- * @name: driver name
- *
- * This function returns an error code
- * No interrupts active, the IRQ has not been requested yet
- * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask
- */
-static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
- void __iomem *regs)
-{
- struct ci13xxx *udc;
- int retval = 0;
-
- trace("%p, %p, %p", dev, regs, driver->name);
-
- if (dev == NULL || regs == NULL || driver == NULL ||
- driver->name == NULL)
- return -EINVAL;
-
- udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL);
- if (udc == NULL)
- return -ENOMEM;
-
- udc->lock = &udc_lock;
- udc->regs = regs;
- udc->udc_driver = driver;
-
- udc->gadget.ops = &usb_gadget_ops;
- udc->gadget.speed = USB_SPEED_UNKNOWN;
- udc->gadget.max_speed = USB_SPEED_HIGH;
- udc->gadget.is_otg = 0;
- udc->gadget.name = driver->name;
-
- INIT_LIST_HEAD(&udc->gadget.ep_list);
- udc->gadget.ep0 = NULL;
-
- dev_set_name(&udc->gadget.dev, "gadget");
- udc->gadget.dev.dma_mask = dev->dma_mask;
- udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
- udc->gadget.dev.parent = dev;
- udc->gadget.dev.release = udc_release;
-
- retval = hw_device_init(regs);
- if (retval < 0)
- goto free_udc;
-
- udc->transceiver = usb_get_transceiver();
-
- if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
- if (udc->transceiver == NULL) {
- retval = -ENODEV;
- goto free_udc;
- }
- }
-
- if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
- retval = hw_device_reset(udc);
- if (retval)
- goto put_transceiver;
- }
-
- retval = device_register(&udc->gadget.dev);
- if (retval) {
- put_device(&udc->gadget.dev);
- goto put_transceiver;
- }
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
- retval = dbg_create_files(&udc->gadget.dev);
-#endif
- if (retval)
- goto unreg_device;
-
- if (udc->transceiver) {
- retval = otg_set_peripheral(udc->transceiver->otg,
- &udc->gadget);
- if (retval)
- goto remove_dbg;
- }
-
- retval = usb_add_gadget_udc(dev, &udc->gadget);
- if (retval)
- goto remove_trans;
-
- pm_runtime_no_callbacks(&udc->gadget.dev);
- pm_runtime_enable(&udc->gadget.dev);
-
- _udc = udc;
- return retval;
-
-remove_trans:
- if (udc->transceiver) {
- otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
- usb_put_transceiver(udc->transceiver);
- }
-
- err("error = %i", retval);
-remove_dbg:
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
- dbg_remove_files(&udc->gadget.dev);
-#endif
-unreg_device:
- device_unregister(&udc->gadget.dev);
-put_transceiver:
- if (udc->transceiver)
- usb_put_transceiver(udc->transceiver);
-free_udc:
- kfree(udc);
- _udc = NULL;
- return retval;
-}
-
-/**
- * udc_remove: parent remove must call this to remove UDC
- *
- * No interrupts active, the IRQ has been released
- */
-static void udc_remove(void)
-{
- struct ci13xxx *udc = _udc;
-
- if (udc == NULL) {
- err("EINVAL");
- return;
- }
- usb_del_gadget_udc(&udc->gadget);
-
- if (udc->transceiver) {
- otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
- usb_put_transceiver(udc->transceiver);
- }
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
- dbg_remove_files(&udc->gadget.dev);
-#endif
- device_unregister(&udc->gadget.dev);
-
- kfree(udc);
- _udc = NULL;
-}
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
deleted file mode 100644
index 0d31af56c989..000000000000
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * ci13xxx_udc.h - structures, registers, and macros MIPS USB IP core
- *
- * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
- *
- * Author: David Lopo
- *
- * 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.
- *
- * Description: MIPS USB IP core family device controller
- * Structures, registers and logging macros
- */
-
-#ifndef _CI13XXX_h_
-#define _CI13XXX_h_
-
-/******************************************************************************
- * DEFINE
- *****************************************************************************/
-#define CI13XXX_PAGE_SIZE 4096ul /* page size for TD's */
-#define ENDPT_MAX (32)
-#define CTRL_PAYLOAD_MAX (64)
-#define RX (0) /* similar to USB_DIR_OUT but can be used as an index */
-#define TX (1) /* similar to USB_DIR_IN but can be used as an index */
-
-/******************************************************************************
- * STRUCTURES
- *****************************************************************************/
-/* DMA layout of transfer descriptors */
-struct ci13xxx_td {
- /* 0 */
- u32 next;
-#define TD_TERMINATE BIT(0)
-#define TD_ADDR_MASK (0xFFFFFFEUL << 5)
- /* 1 */
- u32 token;
-#define TD_STATUS (0x00FFUL << 0)
-#define TD_STATUS_TR_ERR BIT(3)
-#define TD_STATUS_DT_ERR BIT(5)
-#define TD_STATUS_HALTED BIT(6)
-#define TD_STATUS_ACTIVE BIT(7)
-#define TD_MULTO (0x0003UL << 10)
-#define TD_IOC BIT(15)
-#define TD_TOTAL_BYTES (0x7FFFUL << 16)
- /* 2 */
- u32 page[5];
-#define TD_CURR_OFFSET (0x0FFFUL << 0)
-#define TD_FRAME_NUM (0x07FFUL << 0)
-#define TD_RESERVED_MASK (0x0FFFUL << 0)
-} __attribute__ ((packed));
-
-/* DMA layout of queue heads */
-struct ci13xxx_qh {
- /* 0 */
- u32 cap;
-#define QH_IOS BIT(15)
-#define QH_MAX_PKT (0x07FFUL << 16)
-#define QH_ZLT BIT(29)
-#define QH_MULT (0x0003UL << 30)
- /* 1 */
- u32 curr;
- /* 2 - 8 */
- struct ci13xxx_td td;
- /* 9 */
- u32 RESERVED;
- struct usb_ctrlrequest setup;
-} __attribute__ ((packed));
-
-/* Extension of usb_request */
-struct ci13xxx_req {
- struct usb_request req;
- unsigned map;
- struct list_head queue;
- struct ci13xxx_td *ptr;
- dma_addr_t dma;
- struct ci13xxx_td *zptr;
- dma_addr_t zdma;
-};
-
-/* Extension of usb_ep */
-struct ci13xxx_ep {
- struct usb_ep ep;
- const struct usb_endpoint_descriptor *desc;
- u8 dir;
- u8 num;
- u8 type;
- char name[16];
- struct {
- struct list_head queue;
- struct ci13xxx_qh *ptr;
- dma_addr_t dma;
- } qh;
- int wedge;
-
- /* global resources */
- spinlock_t *lock;
- struct device *device;
- struct dma_pool *td_pool;
-};
-
-struct ci13xxx;
-struct ci13xxx_udc_driver {
- const char *name;
- unsigned long flags;
-#define CI13XXX_REGS_SHARED BIT(0)
-#define CI13XXX_REQUIRE_TRANSCEIVER BIT(1)
-#define CI13XXX_PULLUP_ON_VBUS BIT(2)
-#define CI13XXX_DISABLE_STREAMING BIT(3)
-
-#define CI13XXX_CONTROLLER_RESET_EVENT 0
-#define CI13XXX_CONTROLLER_STOPPED_EVENT 1
- void (*notify_event) (struct ci13xxx *udc, unsigned event);
-};
-
-/* CI13XXX UDC descriptor & global resources */
-struct ci13xxx {
- spinlock_t *lock; /* ctrl register bank access */
- void __iomem *regs; /* registers address space */
-
- struct dma_pool *qh_pool; /* DMA pool for queue heads */
- struct dma_pool *td_pool; /* DMA pool for transfer descs */
- struct usb_request *status; /* ep0 status request */
-
- struct usb_gadget gadget; /* USB slave device */
- struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; /* extended endpts */
- u32 ep0_dir; /* ep0 direction */
-#define ep0out ci13xxx_ep[0]
-#define ep0in ci13xxx_ep[hw_ep_max / 2]
- u8 remote_wakeup; /* Is remote wakeup feature
- enabled by the host? */
- u8 suspended; /* suspended by the host */
- u8 test_mode; /* the selected test mode */
-
- struct usb_gadget_driver *driver; /* 3rd party gadget driver */
- struct ci13xxx_udc_driver *udc_driver; /* device controller driver */
- int vbus_active; /* is VBUS active */
- struct usb_phy *transceiver; /* Transceiver struct */
-};
-
-/******************************************************************************
- * REGISTERS
- *****************************************************************************/
-/* register size */
-#define REG_BITS (32)
-
-/* HCCPARAMS */
-#define HCCPARAMS_LEN BIT(17)
-
-/* DCCPARAMS */
-#define DCCPARAMS_DEN (0x1F << 0)
-#define DCCPARAMS_DC BIT(7)
-
-/* TESTMODE */
-#define TESTMODE_FORCE BIT(0)
-
-/* USBCMD */
-#define USBCMD_RS BIT(0)
-#define USBCMD_RST BIT(1)
-#define USBCMD_SUTW BIT(13)
-#define USBCMD_ATDTW BIT(14)
-
-/* USBSTS & USBINTR */
-#define USBi_UI BIT(0)
-#define USBi_UEI BIT(1)
-#define USBi_PCI BIT(2)
-#define USBi_URI BIT(6)
-#define USBi_SLI BIT(8)
-
-/* DEVICEADDR */
-#define DEVICEADDR_USBADRA BIT(24)
-#define DEVICEADDR_USBADR (0x7FUL << 25)
-
-/* PORTSC */
-#define PORTSC_FPR BIT(6)
-#define PORTSC_SUSP BIT(7)
-#define PORTSC_HSP BIT(9)
-#define PORTSC_PTC (0x0FUL << 16)
-
-/* DEVLC */
-#define DEVLC_PSPD (0x03UL << 25)
-#define DEVLC_PSPD_HS (0x02UL << 25)
-
-/* USBMODE */
-#define USBMODE_CM (0x03UL << 0)
-#define USBMODE_CM_IDLE (0x00UL << 0)
-#define USBMODE_CM_DEVICE (0x02UL << 0)
-#define USBMODE_CM_HOST (0x03UL << 0)
-#define USBMODE_SLOM BIT(3)
-#define USBMODE_SDIS BIT(4)
-
-/* ENDPTCTRL */
-#define ENDPTCTRL_RXS BIT(0)
-#define ENDPTCTRL_RXT (0x03UL << 2)
-#define ENDPTCTRL_RXR BIT(6) /* reserved for port 0 */
-#define ENDPTCTRL_RXE BIT(7)
-#define ENDPTCTRL_TXS BIT(16)
-#define ENDPTCTRL_TXT (0x03UL << 18)
-#define ENDPTCTRL_TXR BIT(22) /* reserved for port 0 */
-#define ENDPTCTRL_TXE BIT(23)
-
-/******************************************************************************
- * LOGGING
- *****************************************************************************/
-#define ci13xxx_printk(level, format, args...) \
-do { \
- if (_udc == NULL) \
- printk(level "[%s] " format "\n", __func__, ## args); \
- else \
- dev_printk(level, _udc->gadget.dev.parent, \
- "[%s] " format "\n", __func__, ## args); \
-} while (0)
-
-#define err(format, args...) ci13xxx_printk(KERN_ERR, format, ## args)
-#define warn(format, args...) ci13xxx_printk(KERN_WARNING, format, ## args)
-#define info(format, args...) ci13xxx_printk(KERN_INFO, format, ## args)
-
-#ifdef TRACE
-#define trace(format, args...) ci13xxx_printk(KERN_DEBUG, format, ## args)
-#define dbg_trace(format, args...) dev_dbg(dev, format, ##args)
-#else
-#define trace(format, args...) do {} while (0)
-#define dbg_trace(format, args...) do {} while (0)
-#endif
-
-#endif /* _CI13XXX_h_ */
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index baaebf2830fc..390749bbb0c3 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -40,27 +40,27 @@ static int (*composite_gadget_bind)(struct usb_composite_dev *cdev);
*/
static ushort idVendor;
-module_param(idVendor, ushort, 0);
+module_param(idVendor, ushort, 0644);
MODULE_PARM_DESC(idVendor, "USB Vendor ID");
static ushort idProduct;
-module_param(idProduct, ushort, 0);
+module_param(idProduct, ushort, 0644);
MODULE_PARM_DESC(idProduct, "USB Product ID");
static ushort bcdDevice;
-module_param(bcdDevice, ushort, 0);
+module_param(bcdDevice, ushort, 0644);
MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
static char *iManufacturer;
-module_param(iManufacturer, charp, 0);
+module_param(iManufacturer, charp, 0644);
MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
static char *iProduct;
-module_param(iProduct, charp, 0);
+module_param(iProduct, charp, 0644);
MODULE_PARM_DESC(iProduct, "USB Product string");
static char *iSerialNumber;
-module_param(iSerialNumber, charp, 0);
+module_param(iSerialNumber, charp, 0644);
MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
static char composite_manufacturer[50];
@@ -734,9 +734,23 @@ int usb_add_config(struct usb_composite_dev *cdev,
INIT_LIST_HEAD(&config->functions);
config->next_interface_id = 0;
+ memset(config->interface, 0, sizeof(config->interface));
status = bind(config);
if (status < 0) {
+ while (!list_empty(&config->functions)) {
+ struct usb_function *f;
+
+ f = list_first_entry(&config->functions,
+ struct usb_function, list);
+ list_del(&f->list);
+ if (f->unbind) {
+ DBG(cdev, "unbind function '%s'/%p\n",
+ f->name, f);
+ f->unbind(config, f);
+ /* may free memory for "f" */
+ }
+ }
list_del(&config->list);
config->cdev = NULL;
} else {
@@ -774,6 +788,53 @@ done:
return status;
}
+static void remove_config(struct usb_composite_dev *cdev,
+ struct usb_configuration *config)
+{
+ while (!list_empty(&config->functions)) {
+ struct usb_function *f;
+
+ f = list_first_entry(&config->functions,
+ struct usb_function, list);
+ list_del(&f->list);
+ if (f->unbind) {
+ DBG(cdev, "unbind function '%s'/%p\n", f->name, f);
+ f->unbind(config, f);
+ /* may free memory for "f" */
+ }
+ }
+ list_del(&config->list);
+ if (config->unbind) {
+ DBG(cdev, "unbind config '%s'/%p\n", config->label, config);
+ config->unbind(config);
+ /* may free memory for "c" */
+ }
+}
+
+/**
+ * usb_remove_config() - remove a configuration from a device.
+ * @cdev: wraps the USB gadget
+ * @config: the configuration
+ *
+ * Drivers must call usb_gadget_disconnect before calling this function
+ * to disconnect the device from the host and make sure the host will not
+ * try to enumerate the device while we are changing the config list.
+ */
+void usb_remove_config(struct usb_composite_dev *cdev,
+ struct usb_configuration *config)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cdev->lock, flags);
+
+ if (cdev->config == config)
+ reset_config(cdev);
+
+ spin_unlock_irqrestore(&cdev->lock, flags);
+
+ remove_config(cdev, config);
+}
+
/*-------------------------------------------------------------------------*/
/* We support strings in multiple languages ... string descriptor zero
@@ -785,7 +846,7 @@ done:
static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf)
{
const struct usb_gadget_strings *s;
- u16 language;
+ __le16 language;
__le16 *tmp;
while (*sp) {
@@ -877,7 +938,7 @@ static int get_string(struct usb_composite_dev *cdev,
else if (cdev->product_override == id)
str = iProduct ?: composite->iProduct;
else if (cdev->serial_override == id)
- str = iSerialNumber;
+ str = iSerialNumber ?: composite->iSerialNumber;
else
str = NULL;
if (str) {
@@ -1328,28 +1389,9 @@ composite_unbind(struct usb_gadget *gadget)
while (!list_empty(&cdev->configs)) {
struct usb_configuration *c;
-
c = list_first_entry(&cdev->configs,
struct usb_configuration, list);
- while (!list_empty(&c->functions)) {
- struct usb_function *f;
-
- f = list_first_entry(&c->functions,
- struct usb_function, list);
- list_del(&f->list);
- if (f->unbind) {
- DBG(cdev, "unbind function '%s'/%p\n",
- f->name, f);
- f->unbind(c, f);
- /* may free memory for "f" */
- }
- }
- list_del(&c->list);
- if (c->unbind) {
- DBG(cdev, "unbind config '%s'/%p\n", c->label, c);
- c->unbind(c);
- /* may free memory for "c" */
- }
+ remove_config(cdev, c);
}
if (composite->unbind)
composite->unbind(cdev);
@@ -1431,10 +1473,16 @@ static int composite_bind(struct usb_gadget *gadget)
/* standardized runtime overrides for device ID data */
if (idVendor)
cdev->desc.idVendor = cpu_to_le16(idVendor);
+ else
+ idVendor = le16_to_cpu(cdev->desc.idVendor);
if (idProduct)
cdev->desc.idProduct = cpu_to_le16(idProduct);
+ else
+ idProduct = le16_to_cpu(cdev->desc.idProduct);
if (bcdDevice)
cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
+ else
+ bcdDevice = le16_to_cpu(cdev->desc.bcdDevice);
/* string overrides */
if (iManufacturer || !cdev->desc.iManufacturer) {
@@ -1455,7 +1503,8 @@ static int composite_bind(struct usb_gadget *gadget)
cdev->product_override =
override_id(cdev, &cdev->desc.iProduct);
- if (iSerialNumber)
+ if (iSerialNumber ||
+ (!cdev->desc.iSerialNumber && composite->iSerialNumber))
cdev->serial_override =
override_id(cdev, &cdev->desc.iSerialNumber);
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 170cbe89d9f8..b799106027ad 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -595,14 +595,12 @@ static struct usb_request *dummy_alloc_request(struct usb_ep *_ep,
static void dummy_free_request(struct usb_ep *_ep, struct usb_request *_req)
{
- struct dummy_ep *ep;
struct dummy_request *req;
- if (!_ep || !_req)
- return;
- ep = usb_ep_to_dummy_ep(_ep);
- if (!ep->desc && _ep->name != ep0name)
+ if (!_ep || !_req) {
+ WARN_ON(1);
return;
+ }
req = usb_request_to_dummy_request(_req);
WARN_ON(!list_empty(&req->queue));
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index f52cb1ae45d9..dcd1c7fbb016 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -1031,6 +1031,12 @@ struct ffs_sb_fill_data {
struct ffs_file_perms perms;
umode_t root_mode;
const char *dev_name;
+ union {
+ /* set by ffs_fs_mount(), read by ffs_sb_fill() */
+ void *private_data;
+ /* set by ffs_sb_fill(), read by ffs_fs_mount */
+ struct ffs_data *ffs_data;
+ };
};
static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
@@ -1047,8 +1053,14 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
goto Enomem;
ffs->sb = sb;
- ffs->dev_name = data->dev_name;
+ ffs->dev_name = kstrdup(data->dev_name, GFP_KERNEL);
+ if (unlikely(!ffs->dev_name))
+ goto Enomem;
ffs->file_perms = data->perms;
+ ffs->private_data = data->private_data;
+
+ /* used by the caller of this function */
+ data->ffs_data = ffs;
sb->s_fs_info = ffs;
sb->s_blocksize = PAGE_CACHE_SIZE;
@@ -1167,20 +1179,29 @@ ffs_fs_mount(struct file_system_type *t, int flags,
},
.root_mode = S_IFDIR | 0500,
};
+ struct dentry *rv;
int ret;
+ void *ffs_dev;
ENTER();
- ret = functionfs_check_dev_callback(dev_name);
- if (unlikely(ret < 0))
- return ERR_PTR(ret);
-
ret = ffs_fs_parse_opts(&data, opts);
if (unlikely(ret < 0))
return ERR_PTR(ret);
+ ffs_dev = functionfs_acquire_dev_callback(dev_name);
+ if (IS_ERR(ffs_dev))
+ return ffs_dev;
+
data.dev_name = dev_name;
- return mount_single(t, flags, &data, ffs_sb_fill);
+ data.private_data = ffs_dev;
+ rv = mount_nodev(t, flags, &data, ffs_sb_fill);
+
+ /* data.ffs_data is set by ffs_sb_fill */
+ if (IS_ERR(rv))
+ functionfs_release_dev_callback(data.ffs_data);
+
+ return rv;
}
static void
@@ -1189,8 +1210,10 @@ ffs_fs_kill_sb(struct super_block *sb)
ENTER();
kill_litter_super(sb);
- if (sb->s_fs_info)
+ if (sb->s_fs_info) {
+ functionfs_release_dev_callback(sb->s_fs_info);
ffs_data_put(sb->s_fs_info);
+ }
}
static struct file_system_type ffs_fs_type = {
@@ -1256,6 +1279,7 @@ static void ffs_data_put(struct ffs_data *ffs)
ffs_data_clear(ffs);
BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
waitqueue_active(&ffs->ep0req_completion.wait));
+ kfree(ffs->dev_name);
kfree(ffs);
}
}
@@ -1473,8 +1497,22 @@ static int functionfs_bind_config(struct usb_composite_dev *cdev,
static void ffs_func_free(struct ffs_function *func)
{
+ struct ffs_ep *ep = func->eps;
+ unsigned count = func->ffs->eps_count;
+ unsigned long flags;
+
ENTER();
+ /* cleanup after autoconfig */
+ spin_lock_irqsave(&func->ffs->eps_lock, flags);
+ do {
+ if (ep->ep && ep->req)
+ usb_ep_free_request(ep->ep, ep->req);
+ ep->req = NULL;
+ ++ep;
+ } while (--count);
+ spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
+
ffs_data_put(func->ffs);
kfree(func->eps);
diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c
index b2113420b806..3b3932c55361 100644
--- a/drivers/usb/gadget/f_hid.c
+++ b/drivers/usb/gadget/f_hid.c
@@ -374,7 +374,7 @@ static int hidg_setup(struct usb_function *f,
break;
default:
- VDBG(cdev, "Unknown decriptor request 0x%x\n",
+ VDBG(cdev, "Unknown descriptor request 0x%x\n",
value >> 8);
goto stall;
break;
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index 2c0cd824c667..7275706caeb0 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -286,7 +286,7 @@ static void disable_loopback(struct f_loopback *loop)
struct usb_composite_dev *cdev;
cdev = loop->function.config->cdev;
- disable_endpoints(cdev, loop->in_ep, loop->out_ep);
+ disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL);
VDBG(cdev, "%s disabled\n", loop->function.name);
}
@@ -329,7 +329,7 @@ fail0:
* than 'buflen' bytes each.
*/
for (i = 0; i < qlen && result == 0; i++) {
- req = alloc_ep_req(ep);
+ req = alloc_ep_req(ep, 0);
if (req) {
req->complete = loopback_complete;
result = usb_ep_queue(ep, req, GFP_ATOMIC);
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index cb8c162cae5a..f67b453740bd 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -3110,13 +3110,6 @@ static int fsg_bind_config(struct usb_composite_dev *cdev,
return rc;
}
-static inline int __deprecated __maybe_unused
-fsg_add(struct usb_composite_dev *cdev, struct usb_configuration *c,
- struct fsg_common *common)
-{
- return fsg_bind_config(cdev, c, common);
-}
-
/************************* Module parameters *************************/
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index d4f823f463e9..b1681e45aca7 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -71,6 +71,8 @@ struct f_rndis {
struct gether port;
u8 ctrl_id, data_id;
u8 ethaddr[ETH_ALEN];
+ u32 vendorID;
+ const char *manufacturer;
int config;
struct usb_ep *notify;
@@ -768,12 +770,10 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0);
rndis_set_host_mac(rndis->config, rndis->ethaddr);
-#if 0
-// FIXME
- if (rndis_set_param_vendor(rndis->config, vendorID,
- manufacturer))
- goto fail0;
-#endif
+ if (rndis->manufacturer && rndis->vendorID &&
+ rndis_set_param_vendor(rndis->config, rndis->vendorID,
+ rndis->manufacturer))
+ goto fail;
/* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code
@@ -820,6 +820,7 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f)
rndis_deregister(rndis->config);
rndis_exit();
+ rndis_string_defs[0].id = 0;
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
@@ -840,20 +841,9 @@ static inline bool can_support_rndis(struct usb_configuration *c)
return true;
}
-/**
- * rndis_bind_config - add RNDIS network link to a configuration
- * @c: the configuration to support the network link
- * @ethaddr: a buffer in which the ethernet address of the host side
- * side of the link was recorded
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- *
- * Caller must have called @gether_setup(). Caller is also responsible
- * for calling @gether_cleanup() before module unload.
- */
int
-rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ u32 vendorID, const char *manufacturer)
{
struct f_rndis *rndis;
int status;
@@ -898,6 +888,8 @@ rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
goto fail;
memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);
+ rndis->vendorID = vendorID;
+ rndis->manufacturer = manufacturer;
/* RNDIS activates when the host changes this filter */
rndis->port.cdc_filter = 0;
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index 7aa7ac82c02c..5c1b68b63c98 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -51,6 +51,9 @@ struct f_sourcesink {
struct usb_ep *in_ep;
struct usb_ep *out_ep;
+ struct usb_ep *iso_in_ep;
+ struct usb_ep *iso_out_ep;
+ int cur_alt;
};
static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
@@ -59,18 +62,45 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
}
static unsigned pattern;
-module_param(pattern, uint, 0);
-MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 ");
+module_param(pattern, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63, 2 = none");
+
+static unsigned isoc_interval = 4;
+module_param(isoc_interval, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(isoc_interval, "1 - 16");
+
+static unsigned isoc_maxpacket = 1024;
+module_param(isoc_maxpacket, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(isoc_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
+
+static unsigned isoc_mult;
+module_param(isoc_mult, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(isoc_mult, "0 - 2 (hs/ss only)");
+
+static unsigned isoc_maxburst;
+module_param(isoc_maxburst, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)");
/*-------------------------------------------------------------------------*/
-static struct usb_interface_descriptor source_sink_intf = {
- .bLength = sizeof source_sink_intf,
+static struct usb_interface_descriptor source_sink_intf_alt0 = {
+ .bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
+ .bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
- /* .iInterface = DYNAMIC */
+ /* .iInterface = DYNAMIC */
+};
+
+static struct usb_interface_descriptor source_sink_intf_alt1 = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 4,
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+ /* .iInterface = DYNAMIC */
};
/* full speed support: */
@@ -91,10 +121,36 @@ static struct usb_endpoint_descriptor fs_sink_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
+static struct usb_endpoint_descriptor fs_iso_source_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = cpu_to_le16(1023),
+ .bInterval = 4,
+};
+
+static struct usb_endpoint_descriptor fs_iso_sink_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = cpu_to_le16(1023),
+ .bInterval = 4,
+};
+
static struct usb_descriptor_header *fs_source_sink_descs[] = {
- (struct usb_descriptor_header *) &source_sink_intf,
+ (struct usb_descriptor_header *) &source_sink_intf_alt0,
(struct usb_descriptor_header *) &fs_sink_desc,
(struct usb_descriptor_header *) &fs_source_desc,
+ (struct usb_descriptor_header *) &source_sink_intf_alt1,
+#define FS_ALT_IFC_1_OFFSET 3
+ (struct usb_descriptor_header *) &fs_sink_desc,
+ (struct usb_descriptor_header *) &fs_source_desc,
+ (struct usb_descriptor_header *) &fs_iso_sink_desc,
+ (struct usb_descriptor_header *) &fs_iso_source_desc,
NULL,
};
@@ -116,10 +172,34 @@ static struct usb_endpoint_descriptor hs_sink_desc = {
.wMaxPacketSize = cpu_to_le16(512),
};
+static struct usb_endpoint_descriptor hs_iso_source_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = cpu_to_le16(1024),
+ .bInterval = 4,
+};
+
+static struct usb_endpoint_descriptor hs_iso_sink_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = cpu_to_le16(1024),
+ .bInterval = 4,
+};
+
static struct usb_descriptor_header *hs_source_sink_descs[] = {
- (struct usb_descriptor_header *) &source_sink_intf,
+ (struct usb_descriptor_header *) &source_sink_intf_alt0,
(struct usb_descriptor_header *) &hs_source_desc,
(struct usb_descriptor_header *) &hs_sink_desc,
+ (struct usb_descriptor_header *) &source_sink_intf_alt1,
+#define HS_ALT_IFC_1_OFFSET 3
+ (struct usb_descriptor_header *) &hs_source_desc,
+ (struct usb_descriptor_header *) &hs_sink_desc,
+ (struct usb_descriptor_header *) &hs_iso_source_desc,
+ (struct usb_descriptor_header *) &hs_iso_sink_desc,
NULL,
};
@@ -136,6 +216,7 @@ static struct usb_endpoint_descriptor ss_source_desc = {
struct usb_ss_ep_comp_descriptor ss_source_comp_desc = {
.bLength = USB_DT_SS_EP_COMP_SIZE,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
.bMaxBurst = 0,
.bmAttributes = 0,
.wBytesPerInterval = 0,
@@ -152,17 +233,64 @@ static struct usb_endpoint_descriptor ss_sink_desc = {
struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = {
.bLength = USB_DT_SS_EP_COMP_SIZE,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
.bMaxBurst = 0,
.bmAttributes = 0,
.wBytesPerInterval = 0,
};
+static struct usb_endpoint_descriptor ss_iso_source_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = cpu_to_le16(1024),
+ .bInterval = 4,
+};
+
+struct usb_ss_ep_comp_descriptor ss_iso_source_comp_desc = {
+ .bLength = USB_DT_SS_EP_COMP_SIZE,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ .bMaxBurst = 0,
+ .bmAttributes = 0,
+ .wBytesPerInterval = cpu_to_le16(1024),
+};
+
+static struct usb_endpoint_descriptor ss_iso_sink_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = cpu_to_le16(1024),
+ .bInterval = 4,
+};
+
+struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = {
+ .bLength = USB_DT_SS_EP_COMP_SIZE,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ .bMaxBurst = 0,
+ .bmAttributes = 0,
+ .wBytesPerInterval = cpu_to_le16(1024),
+};
+
static struct usb_descriptor_header *ss_source_sink_descs[] = {
- (struct usb_descriptor_header *) &source_sink_intf,
+ (struct usb_descriptor_header *) &source_sink_intf_alt0,
(struct usb_descriptor_header *) &ss_source_desc,
(struct usb_descriptor_header *) &ss_source_comp_desc,
(struct usb_descriptor_header *) &ss_sink_desc,
(struct usb_descriptor_header *) &ss_sink_comp_desc,
+ (struct usb_descriptor_header *) &source_sink_intf_alt1,
+#define SS_ALT_IFC_1_OFFSET 5
+ (struct usb_descriptor_header *) &ss_source_desc,
+ (struct usb_descriptor_header *) &ss_source_comp_desc,
+ (struct usb_descriptor_header *) &ss_sink_desc,
+ (struct usb_descriptor_header *) &ss_sink_comp_desc,
+ (struct usb_descriptor_header *) &ss_iso_source_desc,
+ (struct usb_descriptor_header *) &ss_iso_source_comp_desc,
+ (struct usb_descriptor_header *) &ss_iso_sink_desc,
+ (struct usb_descriptor_header *) &ss_iso_sink_comp_desc,
NULL,
};
@@ -196,9 +324,10 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
id = usb_interface_id(c, f);
if (id < 0)
return id;
- source_sink_intf.bInterfaceNumber = id;
+ source_sink_intf_alt0.bInterfaceNumber = id;
+ source_sink_intf_alt1.bInterfaceNumber = id;
- /* allocate endpoints */
+ /* allocate bulk endpoints */
ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
if (!ss->in_ep) {
autoconf_fail:
@@ -213,12 +342,74 @@ autoconf_fail:
goto autoconf_fail;
ss->out_ep->driver_data = cdev; /* claim */
+ /* sanity check the isoc module parameters */
+ if (isoc_interval < 1)
+ isoc_interval = 1;
+ if (isoc_interval > 16)
+ isoc_interval = 16;
+ if (isoc_mult > 2)
+ isoc_mult = 2;
+ if (isoc_maxburst > 15)
+ isoc_maxburst = 15;
+
+ /* fill in the FS isoc descriptors from the module parameters */
+ fs_iso_source_desc.wMaxPacketSize = isoc_maxpacket > 1023 ?
+ 1023 : isoc_maxpacket;
+ fs_iso_source_desc.bInterval = isoc_interval;
+ fs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket > 1023 ?
+ 1023 : isoc_maxpacket;
+ fs_iso_sink_desc.bInterval = isoc_interval;
+
+ /* allocate iso endpoints */
+ ss->iso_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_source_desc);
+ if (!ss->iso_in_ep)
+ goto no_iso;
+ ss->iso_in_ep->driver_data = cdev; /* claim */
+
+ ss->iso_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_sink_desc);
+ if (ss->iso_out_ep) {
+ ss->iso_out_ep->driver_data = cdev; /* claim */
+ } else {
+ ss->iso_in_ep->driver_data = NULL;
+ ss->iso_in_ep = NULL;
+no_iso:
+ /*
+ * We still want to work even if the UDC doesn't have isoc
+ * endpoints, so null out the alt interface that contains
+ * them and continue.
+ */
+ fs_source_sink_descs[FS_ALT_IFC_1_OFFSET] = NULL;
+ hs_source_sink_descs[HS_ALT_IFC_1_OFFSET] = NULL;
+ ss_source_sink_descs[SS_ALT_IFC_1_OFFSET] = NULL;
+ }
+
+ if (isoc_maxpacket > 1024)
+ isoc_maxpacket = 1024;
+
/* support high speed hardware */
if (gadget_is_dualspeed(c->cdev->gadget)) {
hs_source_desc.bEndpointAddress =
fs_source_desc.bEndpointAddress;
hs_sink_desc.bEndpointAddress =
fs_sink_desc.bEndpointAddress;
+
+ /*
+ * Fill in the HS isoc descriptors from the module parameters.
+ * We assume that the user knows what they are doing and won't
+ * give parameters that their UDC doesn't support.
+ */
+ hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
+ hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
+ hs_iso_source_desc.bInterval = isoc_interval;
+ hs_iso_source_desc.bEndpointAddress =
+ fs_iso_source_desc.bEndpointAddress;
+
+ hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
+ hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
+ hs_iso_sink_desc.bInterval = isoc_interval;
+ hs_iso_sink_desc.bEndpointAddress =
+ fs_iso_sink_desc.bEndpointAddress;
+
f->hs_descriptors = hs_source_sink_descs;
}
@@ -228,13 +419,39 @@ autoconf_fail:
fs_source_desc.bEndpointAddress;
ss_sink_desc.bEndpointAddress =
fs_sink_desc.bEndpointAddress;
+
+ /*
+ * Fill in the SS isoc descriptors from the module parameters.
+ * We assume that the user knows what they are doing and won't
+ * give parameters that their UDC doesn't support.
+ */
+ ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
+ ss_iso_source_desc.bInterval = isoc_interval;
+ ss_iso_source_comp_desc.bmAttributes = isoc_mult;
+ ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst;
+ ss_iso_source_comp_desc.wBytesPerInterval =
+ isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+ ss_iso_source_desc.bEndpointAddress =
+ fs_iso_source_desc.bEndpointAddress;
+
+ ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
+ ss_iso_sink_desc.bInterval = isoc_interval;
+ ss_iso_sink_comp_desc.bmAttributes = isoc_mult;
+ ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
+ ss_iso_sink_comp_desc.wBytesPerInterval =
+ isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+ ss_iso_sink_desc.bEndpointAddress =
+ fs_iso_sink_desc.bEndpointAddress;
+
f->ss_descriptors = ss_source_sink_descs;
}
- DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
+ DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n",
(gadget_is_superspeed(c->cdev->gadget) ? "super" :
(gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")),
- f->name, ss->in_ep->name, ss->out_ep->name);
+ f->name, ss->in_ep->name, ss->out_ep->name,
+ ss->iso_in_ep ? ss->iso_in_ep->name : "<none>",
+ ss->iso_out_ep ? ss->iso_out_ep->name : "<none>");
return 0;
}
@@ -251,6 +468,9 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req)
u8 *buf = req->buf;
struct usb_composite_dev *cdev = ss->function.config->cdev;
+ if (pattern == 2)
+ return 0;
+
for (i = 0; i < req->actual; i++, buf++) {
switch (pattern) {
@@ -265,7 +485,7 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req)
* each usb transfer request should be. Resync is done
* with set_interface or set_config. (We *WANT* it to
* get quickly out of sync if controllers or their drivers
- * stutter for any reason, including buffer duplcation...)
+ * stutter for any reason, including buffer duplication...)
*/
case 1:
if (*buf == (u8)(i % 63))
@@ -292,21 +512,30 @@ static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
for (i = 0; i < req->length; i++)
*buf++ = (u8) (i % 63);
break;
+ case 2:
+ break;
}
}
static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
{
- struct f_sourcesink *ss = ep->driver_data;
- struct usb_composite_dev *cdev = ss->function.config->cdev;
- int status = req->status;
+ struct usb_composite_dev *cdev;
+ struct f_sourcesink *ss = ep->driver_data;
+ int status = req->status;
+
+ /* driver_data will be null if ep has been disabled */
+ if (!ss)
+ return;
+
+ cdev = ss->function.config->cdev;
switch (status) {
case 0: /* normal completion? */
if (ep == ss->out_ep) {
check_read_data(ss, req);
- memset(req->buf, 0x55, req->length);
+ if (pattern != 2)
+ memset(req->buf, 0x55, req->length);
} else
reinit_write_data(ep, req);
break;
@@ -344,32 +573,57 @@ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
}
}
-static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in)
+static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
+ bool is_iso, int speed)
{
struct usb_ep *ep;
struct usb_request *req;
- int status;
+ int i, size, status;
+
+ for (i = 0; i < 8; i++) {
+ if (is_iso) {
+ switch (speed) {
+ case USB_SPEED_SUPER:
+ size = isoc_maxpacket * (isoc_mult + 1) *
+ (isoc_maxburst + 1);
+ break;
+ case USB_SPEED_HIGH:
+ size = isoc_maxpacket * (isoc_mult + 1);
+ break;
+ default:
+ size = isoc_maxpacket > 1023 ?
+ 1023 : isoc_maxpacket;
+ break;
+ }
+ ep = is_in ? ss->iso_in_ep : ss->iso_out_ep;
+ req = alloc_ep_req(ep, size);
+ } else {
+ ep = is_in ? ss->in_ep : ss->out_ep;
+ req = alloc_ep_req(ep, 0);
+ }
- ep = is_in ? ss->in_ep : ss->out_ep;
- req = alloc_ep_req(ep);
- if (!req)
- return -ENOMEM;
+ if (!req)
+ return -ENOMEM;
- req->complete = source_sink_complete;
- if (is_in)
- reinit_write_data(ep, req);
- else
- memset(req->buf, 0x55, req->length);
+ req->complete = source_sink_complete;
+ if (is_in)
+ reinit_write_data(ep, req);
+ else if (pattern != 2)
+ memset(req->buf, 0x55, req->length);
- status = usb_ep_queue(ep, req, GFP_ATOMIC);
- if (status) {
- struct usb_composite_dev *cdev;
+ status = usb_ep_queue(ep, req, GFP_ATOMIC);
+ if (status) {
+ struct usb_composite_dev *cdev;
- cdev = ss->function.config->cdev;
- ERROR(cdev, "start %s %s --> %d\n",
- is_in ? "IN" : "OUT",
- ep->name, status);
- free_ep_req(ep, req);
+ cdev = ss->function.config->cdev;
+ ERROR(cdev, "start %s%s %s --> %d\n",
+ is_iso ? "ISO-" : "", is_in ? "IN" : "OUT",
+ ep->name, status);
+ free_ep_req(ep, req);
+ }
+
+ if (!is_iso)
+ break;
}
return status;
@@ -380,17 +634,20 @@ static void disable_source_sink(struct f_sourcesink *ss)
struct usb_composite_dev *cdev;
cdev = ss->function.config->cdev;
- disable_endpoints(cdev, ss->in_ep, ss->out_ep);
+ disable_endpoints(cdev, ss->in_ep, ss->out_ep, ss->iso_in_ep,
+ ss->iso_out_ep);
VDBG(cdev, "%s disabled\n", ss->function.name);
}
static int
-enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss)
+enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
+ int alt)
{
int result = 0;
+ int speed = cdev->gadget->speed;
struct usb_ep *ep;
- /* one endpoint writes (sources) zeroes IN (to the host) */
+ /* one bulk endpoint writes (sources) zeroes IN (to the host) */
ep = ss->in_ep;
result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
if (result)
@@ -400,7 +657,7 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss)
return result;
ep->driver_data = ss;
- result = source_sink_start_ep(ss, true);
+ result = source_sink_start_ep(ss, true, false, speed);
if (result < 0) {
fail:
ep = ss->in_ep;
@@ -409,7 +666,7 @@ fail:
return result;
}
- /* one endpoint reads (sinks) anything OUT (from the host) */
+ /* one bulk endpoint reads (sinks) anything OUT (from the host) */
ep = ss->out_ep;
result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
if (result)
@@ -419,27 +676,82 @@ fail:
goto fail;
ep->driver_data = ss;
- result = source_sink_start_ep(ss, false);
+ result = source_sink_start_ep(ss, false, false, speed);
if (result < 0) {
+fail2:
+ ep = ss->out_ep;
usb_ep_disable(ep);
ep->driver_data = NULL;
goto fail;
}
- DBG(cdev, "%s enabled\n", ss->function.name);
+ if (alt == 0)
+ goto out;
+
+ /* one iso endpoint writes (sources) zeroes IN (to the host) */
+ ep = ss->iso_in_ep;
+ if (ep) {
+ result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
+ if (result)
+ goto fail2;
+ result = usb_ep_enable(ep);
+ if (result < 0)
+ goto fail2;
+ ep->driver_data = ss;
+
+ result = source_sink_start_ep(ss, true, true, speed);
+ if (result < 0) {
+fail3:
+ ep = ss->iso_in_ep;
+ if (ep) {
+ usb_ep_disable(ep);
+ ep->driver_data = NULL;
+ }
+ goto fail2;
+ }
+ }
+
+ /* one iso endpoint reads (sinks) anything OUT (from the host) */
+ ep = ss->iso_out_ep;
+ if (ep) {
+ result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
+ if (result)
+ goto fail3;
+ result = usb_ep_enable(ep);
+ if (result < 0)
+ goto fail3;
+ ep->driver_data = ss;
+
+ result = source_sink_start_ep(ss, false, true, speed);
+ if (result < 0) {
+ usb_ep_disable(ep);
+ ep->driver_data = NULL;
+ goto fail3;
+ }
+ }
+out:
+ ss->cur_alt = alt;
+
+ DBG(cdev, "%s enabled, alt intf %d\n", ss->function.name, alt);
return result;
}
static int sourcesink_set_alt(struct usb_function *f,
unsigned intf, unsigned alt)
{
- struct f_sourcesink *ss = func_to_ss(f);
- struct usb_composite_dev *cdev = f->config->cdev;
+ struct f_sourcesink *ss = func_to_ss(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
- /* we know alt is zero */
if (ss->in_ep->driver_data)
disable_source_sink(ss);
- return enable_source_sink(cdev, ss);
+ return enable_source_sink(cdev, ss, alt);
+}
+
+static int sourcesink_get_alt(struct usb_function *f, unsigned intf)
+{
+ struct f_sourcesink *ss = func_to_ss(f);
+
+ return ss->cur_alt;
}
static void sourcesink_disable(struct usb_function *f)
@@ -465,6 +777,7 @@ static int __init sourcesink_bind_config(struct usb_configuration *c)
ss->function.bind = sourcesink_bind;
ss->function.unbind = sourcesink_unbind;
ss->function.set_alt = sourcesink_set_alt;
+ ss->function.get_alt = sourcesink_get_alt;
ss->function.disable = sourcesink_disable;
status = usb_add_function(c, &ss->function);
@@ -536,7 +849,7 @@ unknown:
req->length = value;
value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC);
if (value < 0)
- ERROR(c->cdev, "source/sinkc response, err %d\n",
+ ERROR(c->cdev, "source/sink response, err %d\n",
value);
}
@@ -545,12 +858,12 @@ unknown:
}
static struct usb_configuration sourcesink_driver = {
- .label = "source/sink",
- .strings = sourcesink_strings,
- .setup = sourcesink_setup,
- .bConfigurationValue = 3,
- .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
- /* .iConfiguration = DYNAMIC */
+ .label = "source/sink",
+ .strings = sourcesink_strings,
+ .setup = sourcesink_setup,
+ .bConfigurationValue = 3,
+ .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
+ /* .iConfiguration = DYNAMIC */
};
/**
@@ -567,7 +880,8 @@ int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume)
return id;
strings_sourcesink[0].id = id;
- source_sink_intf.iInterface = id;
+ source_sink_intf_alt0.iInterface = id;
+ source_sink_intf_alt1.iInterface = id;
sourcesink_driver.iConfiguration = id;
/* support autoresume for remote wakeup testing */
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index 877a2c46672b..51881f3bd07a 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -71,9 +71,6 @@ static struct usb_endpoint_descriptor qe_ep0_desc = {
.wMaxPacketSize = USB_MAX_CTRL_PAYLOAD,
};
-/* it is initialized in probe() */
-static struct qe_udc *udc_controller;
-
/********************************************************************
* Internal Used Function Start
********************************************************************/
@@ -188,8 +185,8 @@ static int qe_ep0_stall(struct qe_udc *udc)
{
qe_eptx_stall_change(&udc->eps[0], 1);
qe_eprx_stall_change(&udc->eps[0], 1);
- udc_controller->ep0_state = WAIT_FOR_SETUP;
- udc_controller->ep0_dir = 0;
+ udc->ep0_state = WAIT_FOR_SETUP;
+ udc->ep0_dir = 0;
return 0;
}
@@ -450,13 +447,13 @@ static int qe_ep_rxbd_update(struct qe_ep *ep)
ep->rxbuf_d = virt_to_phys((void *)ep->rxbuffer);
if (ep->rxbuf_d == DMA_ADDR_INVALID) {
- ep->rxbuf_d = dma_map_single(udc_controller->gadget.dev.parent,
+ ep->rxbuf_d = dma_map_single(ep->udc->gadget.dev.parent,
ep->rxbuffer,
size,
DMA_FROM_DEVICE);
ep->rxbufmap = 1;
} else {
- dma_sync_single_for_device(udc_controller->gadget.dev.parent,
+ dma_sync_single_for_device(ep->udc->gadget.dev.parent,
ep->rxbuf_d, size,
DMA_FROM_DEVICE);
ep->rxbufmap = 0;
@@ -489,10 +486,10 @@ static int qe_ep_register_init(struct qe_udc *udc, unsigned char pipe_num)
epparam = udc->ep_param[pipe_num];
usep = 0;
- logepnum = (ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+ logepnum = (ep->ep.desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
usep |= (logepnum << USB_EPNUM_SHIFT);
- switch (ep->desc->bmAttributes & 0x03) {
+ switch (ep->ep.desc->bmAttributes & 0x03) {
case USB_ENDPOINT_XFER_BULK:
usep |= USB_TRANS_BULK;
break;
@@ -644,7 +641,7 @@ static int qe_ep_init(struct qe_udc *udc,
/* initialize ep structure */
ep->ep.maxpacket = max;
ep->tm = (u8)(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
- ep->desc = desc;
+ ep->ep.desc = desc;
ep->stopped = 0;
ep->init = 1;
@@ -698,14 +695,14 @@ en_done:
return -ENODEV;
}
-static inline void qe_usb_enable(void)
+static inline void qe_usb_enable(struct qe_udc *udc)
{
- setbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN);
+ setbits8(&udc->usb_regs->usb_usmod, USB_MODE_EN);
}
-static inline void qe_usb_disable(void)
+static inline void qe_usb_disable(struct qe_udc *udc)
{
- clrbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN);
+ clrbits8(&udc->usb_regs->usb_usmod, USB_MODE_EN);
}
/*----------------------------------------------------------------------------*
@@ -1599,7 +1596,7 @@ static int qe_ep_enable(struct usb_ep *_ep,
ep = container_of(_ep, struct qe_ep, ep);
/* catch various bogus parameters */
- if (!_ep || !desc || ep->desc || _ep->name == ep_name[0] ||
+ if (!_ep || !desc || ep->ep.desc || _ep->name == ep_name[0] ||
(desc->bDescriptorType != USB_DT_ENDPOINT))
return -EINVAL;
@@ -1629,7 +1626,7 @@ static int qe_ep_disable(struct usb_ep *_ep)
ep = container_of(_ep, struct qe_ep, ep);
udc = ep->udc;
- if (!_ep || !ep->desc) {
+ if (!_ep || !ep->ep.desc) {
dev_dbg(udc->dev, "%s not enabled\n", _ep ? ep->ep.name : NULL);
return -EINVAL;
}
@@ -1637,7 +1634,6 @@ static int qe_ep_disable(struct usb_ep *_ep)
spin_lock_irqsave(&udc->lock, flags);
/* Nuke all pending requests (does flush) */
nuke(ep, -ESHUTDOWN);
- ep->desc = NULL;
ep->ep.desc = NULL;
ep->stopped = 1;
ep->tx_req = NULL;
@@ -1656,13 +1652,13 @@ static int qe_ep_disable(struct usb_ep *_ep)
if (ep->dir != USB_DIR_IN) {
kfree(ep->rxframe);
if (ep->rxbufmap) {
- dma_unmap_single(udc_controller->gadget.dev.parent,
+ dma_unmap_single(udc->gadget.dev.parent,
ep->rxbuf_d, size,
DMA_FROM_DEVICE);
ep->rxbuf_d = DMA_ADDR_INVALID;
} else {
dma_sync_single_for_cpu(
- udc_controller->gadget.dev.parent,
+ udc->gadget.dev.parent,
ep->rxbuf_d, size,
DMA_FROM_DEVICE);
}
@@ -1715,7 +1711,7 @@ static int __qe_ep_queue(struct usb_ep *_ep, struct usb_request *_req)
dev_dbg(udc->dev, "bad params\n");
return -EINVAL;
}
- if (!_ep || (!ep->desc && ep_index(ep))) {
+ if (!_ep || (!ep->ep.desc && ep_index(ep))) {
dev_dbg(udc->dev, "bad ep\n");
return -EINVAL;
}
@@ -1826,7 +1822,7 @@ static int qe_ep_set_halt(struct usb_ep *_ep, int value)
struct qe_udc *udc;
ep = container_of(_ep, struct qe_ep, ep);
- if (!_ep || !ep->desc) {
+ if (!_ep || !ep->ep.desc) {
status = -EINVAL;
goto out;
}
@@ -1880,9 +1876,10 @@ static struct usb_ep_ops qe_ep_ops = {
/* Get the current frame number */
static int qe_get_frame(struct usb_gadget *gadget)
{
+ struct qe_udc *udc = container_of(gadget, struct qe_udc, gadget);
u16 tmp;
- tmp = in_be16(&udc_controller->usb_param->frame_n);
+ tmp = in_be16(&udc->usb_param->frame_n);
if (tmp & 0x8000)
tmp = tmp & 0x07ff;
else
@@ -1891,57 +1888,16 @@ static int qe_get_frame(struct usb_gadget *gadget)
return (int)tmp;
}
-/* Tries to wake up the host connected to this gadget
- *
- * Return : 0-success
- * Negative-this feature not enabled by host or not supported by device hw
- */
-static int qe_wakeup(struct usb_gadget *gadget)
-{
- return -ENOTSUPP;
-}
-
-/* Notify controller that VBUS is powered, Called by whatever
- detects VBUS sessions */
-static int qe_vbus_session(struct usb_gadget *gadget, int is_active)
-{
- return -ENOTSUPP;
-}
-
-/* constrain controller's VBUS power usage
- * This call is used by gadget drivers during SET_CONFIGURATION calls,
- * reporting how much power the device may consume. For example, this
- * could affect how quickly batteries are recharged.
- *
- * Returns zero on success, else negative errno.
- */
-static int qe_vbus_draw(struct usb_gadget *gadget, unsigned mA)
-{
- return -ENOTSUPP;
-}
-
-/* Change Data+ pullup status
- * this func is used by usb_gadget_connect/disconnect
- */
-static int qe_pullup(struct usb_gadget *gadget, int is_on)
-{
- return -ENOTSUPP;
-}
-
-static int fsl_qe_start(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *));
-static int fsl_qe_stop(struct usb_gadget_driver *driver);
+static int fsl_qe_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver);
+static int fsl_qe_stop(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver);
/* defined in usb_gadget.h */
static struct usb_gadget_ops qe_gadget_ops = {
.get_frame = qe_get_frame,
- .wakeup = qe_wakeup,
-/* .set_selfpowered = qe_set_selfpowered,*/ /* always selfpowered */
- .vbus_session = qe_vbus_session,
- .vbus_draw = qe_vbus_draw,
- .pullup = qe_pullup,
- .start = fsl_qe_start,
- .stop = fsl_qe_stop,
+ .udc_start = fsl_qe_start,
+ .udc_stop = fsl_qe_stop,
};
/*-------------------------------------------------------------------------
@@ -2015,7 +1971,7 @@ static void ch9getstatus(struct qe_udc *udc, u8 request_type, u16 value,
u16 usep;
/* stall if endpoint doesn't exist */
- if (!target_ep->desc)
+ if (!target_ep->ep.desc)
goto stall;
usep = in_be16(&udc->usb_regs->usb_usep[pipe]);
@@ -2190,7 +2146,7 @@ static int reset_irq(struct qe_udc *udc)
if (udc->usb_state == USB_STATE_DEFAULT)
return 0;
- qe_usb_disable();
+ qe_usb_disable(udc);
out_8(&udc->usb_regs->usb_usadr, 0);
for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
@@ -2202,7 +2158,7 @@ static int reset_irq(struct qe_udc *udc)
udc->usb_state = USB_STATE_DEFAULT;
udc->ep0_state = WAIT_FOR_SETUP;
udc->ep0_dir = USB_DIR_OUT;
- qe_usb_enable();
+ qe_usb_enable(udc);
return 0;
}
@@ -2327,92 +2283,65 @@ static irqreturn_t qe_udc_irq(int irq, void *_udc)
/*-------------------------------------------------------------------------
Gadget driver probe and unregister.
--------------------------------------------------------------------------*/
-static int fsl_qe_start(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *))
+static int fsl_qe_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
{
- int retval;
- unsigned long flags = 0;
-
- /* standard operations */
- if (!udc_controller)
- return -ENODEV;
-
- if (!driver || driver->max_speed < USB_SPEED_FULL
- || !bind || !driver->disconnect || !driver->setup)
- return -EINVAL;
-
- if (udc_controller->driver)
- return -EBUSY;
+ struct qe_udc *udc;
+ unsigned long flags;
+ udc = container_of(gadget, struct qe_udc, gadget);
/* lock is needed but whether should use this lock or another */
- spin_lock_irqsave(&udc_controller->lock, flags);
+ spin_lock_irqsave(&udc->lock, flags);
driver->driver.bus = NULL;
/* hook up the driver */
- udc_controller->driver = driver;
- udc_controller->gadget.dev.driver = &driver->driver;
- udc_controller->gadget.speed = driver->max_speed;
- spin_unlock_irqrestore(&udc_controller->lock, flags);
-
- retval = bind(&udc_controller->gadget);
- if (retval) {
- dev_err(udc_controller->dev, "bind to %s --> %d",
- driver->driver.name, retval);
- udc_controller->gadget.dev.driver = NULL;
- udc_controller->driver = NULL;
- return retval;
- }
+ udc->driver = driver;
+ udc->gadget.dev.driver = &driver->driver;
+ udc->gadget.speed = driver->max_speed;
/* Enable IRQ reg and Set usbcmd reg EN bit */
- qe_usb_enable();
-
- out_be16(&udc_controller->usb_regs->usb_usber, 0xffff);
- out_be16(&udc_controller->usb_regs->usb_usbmr, USB_E_DEFAULT_DEVICE);
- udc_controller->usb_state = USB_STATE_ATTACHED;
- udc_controller->ep0_state = WAIT_FOR_SETUP;
- udc_controller->ep0_dir = USB_DIR_OUT;
- dev_info(udc_controller->dev, "%s bind to driver %s \n",
- udc_controller->gadget.name, driver->driver.name);
+ qe_usb_enable(udc);
+
+ out_be16(&udc->usb_regs->usb_usber, 0xffff);
+ out_be16(&udc->usb_regs->usb_usbmr, USB_E_DEFAULT_DEVICE);
+ udc->usb_state = USB_STATE_ATTACHED;
+ udc->ep0_state = WAIT_FOR_SETUP;
+ udc->ep0_dir = USB_DIR_OUT;
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ dev_info(udc->dev, "%s bind to driver %s\n", udc->gadget.name,
+ driver->driver.name);
return 0;
}
-static int fsl_qe_stop(struct usb_gadget_driver *driver)
+static int fsl_qe_stop(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
{
+ struct qe_udc *udc;
struct qe_ep *loop_ep;
unsigned long flags;
- if (!udc_controller)
- return -ENODEV;
-
- if (!driver || driver != udc_controller->driver)
- return -EINVAL;
-
+ udc = container_of(gadget, struct qe_udc, gadget);
/* stop usb controller, disable intr */
- qe_usb_disable();
+ qe_usb_disable(udc);
/* in fact, no needed */
- udc_controller->usb_state = USB_STATE_ATTACHED;
- udc_controller->ep0_state = WAIT_FOR_SETUP;
- udc_controller->ep0_dir = 0;
+ udc->usb_state = USB_STATE_ATTACHED;
+ udc->ep0_state = WAIT_FOR_SETUP;
+ udc->ep0_dir = 0;
/* stand operation */
- spin_lock_irqsave(&udc_controller->lock, flags);
- udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
- nuke(&udc_controller->eps[0], -ESHUTDOWN);
- list_for_each_entry(loop_ep, &udc_controller->gadget.ep_list,
- ep.ep_list)
+ spin_lock_irqsave(&udc->lock, flags);
+ udc->gadget.speed = USB_SPEED_UNKNOWN;
+ nuke(&udc->eps[0], -ESHUTDOWN);
+ list_for_each_entry(loop_ep, &udc->gadget.ep_list, ep.ep_list)
nuke(loop_ep, -ESHUTDOWN);
- spin_unlock_irqrestore(&udc_controller->lock, flags);
-
- /* report disconnect; the controller is already quiesced */
- driver->disconnect(&udc_controller->gadget);
+ spin_unlock_irqrestore(&udc->lock, flags);
- /* unbind gadget and unhook driver. */
- driver->unbind(&udc_controller->gadget);
- udc_controller->gadget.dev.driver = NULL;
- udc_controller->driver = NULL;
+ udc->gadget.dev.driver = NULL;
+ udc->driver = NULL;
- dev_info(udc_controller->dev, "unregistered gadget driver '%s'\r\n",
+ dev_info(udc->dev, "unregistered gadget driver '%s'\r\n",
driver->driver.name);
return 0;
}
@@ -2502,7 +2431,7 @@ static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
ep->ep.ops = &qe_ep_ops;
ep->stopped = 1;
ep->ep.maxpacket = (unsigned short) ~0;
- ep->desc = NULL;
+ ep->ep.desc = NULL;
ep->dir = 0xff;
ep->epnum = (u8)pipe_num;
ep->sent = 0;
@@ -2531,21 +2460,22 @@ static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
*----------------------------------------------------------------------*/
static void qe_udc_release(struct device *dev)
{
- int i = 0;
+ struct qe_udc *udc = container_of(dev, struct qe_udc, gadget.dev);
+ int i;
- complete(udc_controller->done);
- cpm_muram_free(cpm_muram_offset(udc_controller->ep_param[0]));
+ complete(udc->done);
+ cpm_muram_free(cpm_muram_offset(udc->ep_param[0]));
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
- udc_controller->ep_param[i] = NULL;
+ udc->ep_param[i] = NULL;
- kfree(udc_controller);
- udc_controller = NULL;
+ kfree(udc);
}
/* Driver probe functions */
static const struct of_device_id qe_udc_match[];
static int __devinit qe_udc_probe(struct platform_device *ofdev)
{
+ struct qe_udc *udc;
const struct of_device_id *match;
struct device_node *np = ofdev->dev.of_node;
struct qe_ep *ep;
@@ -2562,44 +2492,44 @@ static int __devinit qe_udc_probe(struct platform_device *ofdev)
return -ENODEV;
/* Initialize the udc structure including QH member and other member */
- udc_controller = qe_udc_config(ofdev);
- if (!udc_controller) {
+ udc = qe_udc_config(ofdev);
+ if (!udc) {
dev_err(&ofdev->dev, "failed to initialize\n");
return -ENOMEM;
}
- udc_controller->soc_type = (unsigned long)match->data;
- udc_controller->usb_regs = of_iomap(np, 0);
- if (!udc_controller->usb_regs) {
+ udc->soc_type = (unsigned long)match->data;
+ udc->usb_regs = of_iomap(np, 0);
+ if (!udc->usb_regs) {
ret = -ENOMEM;
goto err1;
}
/* initialize usb hw reg except for regs for EP,
* leave usbintr reg untouched*/
- qe_udc_reg_init(udc_controller);
+ qe_udc_reg_init(udc);
/* here comes the stand operations for probe
* set the qe_udc->gadget.xxx */
- udc_controller->gadget.ops = &qe_gadget_ops;
+ udc->gadget.ops = &qe_gadget_ops;
/* gadget.ep0 is a pointer */
- udc_controller->gadget.ep0 = &udc_controller->eps[0].ep;
+ udc->gadget.ep0 = &udc->eps[0].ep;
- INIT_LIST_HEAD(&udc_controller->gadget.ep_list);
+ INIT_LIST_HEAD(&udc->gadget.ep_list);
/* modify in register gadget process */
- udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
+ udc->gadget.speed = USB_SPEED_UNKNOWN;
/* name: Identifies the controller hardware type. */
- udc_controller->gadget.name = driver_name;
+ udc->gadget.name = driver_name;
- device_initialize(&udc_controller->gadget.dev);
+ device_initialize(&udc->gadget.dev);
- dev_set_name(&udc_controller->gadget.dev, "gadget");
+ dev_set_name(&udc->gadget.dev, "gadget");
- udc_controller->gadget.dev.release = qe_udc_release;
- udc_controller->gadget.dev.parent = &ofdev->dev;
+ udc->gadget.dev.release = qe_udc_release;
+ udc->gadget.dev.parent = &ofdev->dev;
/* initialize qe_ep struct */
for (i = 0; i < USB_MAX_ENDPOINTS ; i++) {
@@ -2608,104 +2538,104 @@ static int __devinit qe_udc_probe(struct platform_device *ofdev)
/* setup the qe_ep struct and link ep.ep.list
* into gadget.ep_list */
- qe_ep_config(udc_controller, (unsigned char)i);
+ qe_ep_config(udc, (unsigned char)i);
}
/* ep0 initialization in here */
- ret = qe_ep_init(udc_controller, 0, &qe_ep0_desc);
+ ret = qe_ep_init(udc, 0, &qe_ep0_desc);
if (ret)
goto err2;
/* create a buf for ZLP send, need to remain zeroed */
- udc_controller->nullbuf = kzalloc(256, GFP_KERNEL);
- if (udc_controller->nullbuf == NULL) {
- dev_err(udc_controller->dev, "cannot alloc nullbuf\n");
+ udc->nullbuf = kzalloc(256, GFP_KERNEL);
+ if (udc->nullbuf == NULL) {
+ dev_err(udc->dev, "cannot alloc nullbuf\n");
ret = -ENOMEM;
goto err3;
}
/* buffer for data of get_status request */
- udc_controller->statusbuf = kzalloc(2, GFP_KERNEL);
- if (udc_controller->statusbuf == NULL) {
+ udc->statusbuf = kzalloc(2, GFP_KERNEL);
+ if (udc->statusbuf == NULL) {
ret = -ENOMEM;
goto err4;
}
- udc_controller->nullp = virt_to_phys((void *)udc_controller->nullbuf);
- if (udc_controller->nullp == DMA_ADDR_INVALID) {
- udc_controller->nullp = dma_map_single(
- udc_controller->gadget.dev.parent,
- udc_controller->nullbuf,
+ udc->nullp = virt_to_phys((void *)udc->nullbuf);
+ if (udc->nullp == DMA_ADDR_INVALID) {
+ udc->nullp = dma_map_single(
+ udc->gadget.dev.parent,
+ udc->nullbuf,
256,
DMA_TO_DEVICE);
- udc_controller->nullmap = 1;
+ udc->nullmap = 1;
} else {
- dma_sync_single_for_device(udc_controller->gadget.dev.parent,
- udc_controller->nullp, 256,
+ dma_sync_single_for_device(udc->gadget.dev.parent,
+ udc->nullp, 256,
DMA_TO_DEVICE);
}
- tasklet_init(&udc_controller->rx_tasklet, ep_rx_tasklet,
- (unsigned long)udc_controller);
+ tasklet_init(&udc->rx_tasklet, ep_rx_tasklet,
+ (unsigned long)udc);
/* request irq and disable DR */
- udc_controller->usb_irq = irq_of_parse_and_map(np, 0);
- if (!udc_controller->usb_irq) {
+ udc->usb_irq = irq_of_parse_and_map(np, 0);
+ if (!udc->usb_irq) {
ret = -EINVAL;
goto err_noirq;
}
- ret = request_irq(udc_controller->usb_irq, qe_udc_irq, 0,
- driver_name, udc_controller);
+ ret = request_irq(udc->usb_irq, qe_udc_irq, 0,
+ driver_name, udc);
if (ret) {
- dev_err(udc_controller->dev, "cannot request irq %d err %d \n",
- udc_controller->usb_irq, ret);
+ dev_err(udc->dev, "cannot request irq %d err %d\n",
+ udc->usb_irq, ret);
goto err5;
}
- ret = device_add(&udc_controller->gadget.dev);
+ ret = device_add(&udc->gadget.dev);
if (ret)
goto err6;
- ret = usb_add_gadget_udc(&ofdev->dev, &udc_controller->gadget);
+ ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget);
if (ret)
goto err7;
- dev_info(udc_controller->dev,
+ dev_set_drvdata(&ofdev->dev, udc);
+ dev_info(udc->dev,
"%s USB controller initialized as device\n",
- (udc_controller->soc_type == PORT_QE) ? "QE" : "CPM");
+ (udc->soc_type == PORT_QE) ? "QE" : "CPM");
return 0;
err7:
- device_unregister(&udc_controller->gadget.dev);
+ device_unregister(&udc->gadget.dev);
err6:
- free_irq(udc_controller->usb_irq, udc_controller);
+ free_irq(udc->usb_irq, udc);
err5:
- irq_dispose_mapping(udc_controller->usb_irq);
+ irq_dispose_mapping(udc->usb_irq);
err_noirq:
- if (udc_controller->nullmap) {
- dma_unmap_single(udc_controller->gadget.dev.parent,
- udc_controller->nullp, 256,
+ if (udc->nullmap) {
+ dma_unmap_single(udc->gadget.dev.parent,
+ udc->nullp, 256,
DMA_TO_DEVICE);
- udc_controller->nullp = DMA_ADDR_INVALID;
+ udc->nullp = DMA_ADDR_INVALID;
} else {
- dma_sync_single_for_cpu(udc_controller->gadget.dev.parent,
- udc_controller->nullp, 256,
+ dma_sync_single_for_cpu(udc->gadget.dev.parent,
+ udc->nullp, 256,
DMA_TO_DEVICE);
}
- kfree(udc_controller->statusbuf);
+ kfree(udc->statusbuf);
err4:
- kfree(udc_controller->nullbuf);
+ kfree(udc->nullbuf);
err3:
- ep = &udc_controller->eps[0];
+ ep = &udc->eps[0];
cpm_muram_free(cpm_muram_offset(ep->rxbase));
kfree(ep->rxframe);
kfree(ep->rxbuffer);
kfree(ep->txframe);
err2:
- iounmap(udc_controller->usb_regs);
+ iounmap(udc->usb_regs);
err1:
- kfree(udc_controller);
- udc_controller = NULL;
+ kfree(udc);
return ret;
}
@@ -2723,44 +2653,41 @@ static int qe_udc_resume(struct platform_device *dev)
static int __devexit qe_udc_remove(struct platform_device *ofdev)
{
+ struct qe_udc *udc = dev_get_drvdata(&ofdev->dev);
struct qe_ep *ep;
unsigned int size;
-
DECLARE_COMPLETION(done);
- if (!udc_controller)
- return -ENODEV;
-
- usb_del_gadget_udc(&udc_controller->gadget);
+ usb_del_gadget_udc(&udc->gadget);
- udc_controller->done = &done;
- tasklet_disable(&udc_controller->rx_tasklet);
+ udc->done = &done;
+ tasklet_disable(&udc->rx_tasklet);
- if (udc_controller->nullmap) {
- dma_unmap_single(udc_controller->gadget.dev.parent,
- udc_controller->nullp, 256,
+ if (udc->nullmap) {
+ dma_unmap_single(udc->gadget.dev.parent,
+ udc->nullp, 256,
DMA_TO_DEVICE);
- udc_controller->nullp = DMA_ADDR_INVALID;
+ udc->nullp = DMA_ADDR_INVALID;
} else {
- dma_sync_single_for_cpu(udc_controller->gadget.dev.parent,
- udc_controller->nullp, 256,
+ dma_sync_single_for_cpu(udc->gadget.dev.parent,
+ udc->nullp, 256,
DMA_TO_DEVICE);
}
- kfree(udc_controller->statusbuf);
- kfree(udc_controller->nullbuf);
+ kfree(udc->statusbuf);
+ kfree(udc->nullbuf);
- ep = &udc_controller->eps[0];
+ ep = &udc->eps[0];
cpm_muram_free(cpm_muram_offset(ep->rxbase));
size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (USB_BDRING_LEN + 1);
kfree(ep->rxframe);
if (ep->rxbufmap) {
- dma_unmap_single(udc_controller->gadget.dev.parent,
+ dma_unmap_single(udc->gadget.dev.parent,
ep->rxbuf_d, size,
DMA_FROM_DEVICE);
ep->rxbuf_d = DMA_ADDR_INVALID;
} else {
- dma_sync_single_for_cpu(udc_controller->gadget.dev.parent,
+ dma_sync_single_for_cpu(udc->gadget.dev.parent,
ep->rxbuf_d, size,
DMA_FROM_DEVICE);
}
@@ -2768,14 +2695,14 @@ static int __devexit qe_udc_remove(struct platform_device *ofdev)
kfree(ep->rxbuffer);
kfree(ep->txframe);
- free_irq(udc_controller->usb_irq, udc_controller);
- irq_dispose_mapping(udc_controller->usb_irq);
+ free_irq(udc->usb_irq, udc);
+ irq_dispose_mapping(udc->usb_irq);
- tasklet_kill(&udc_controller->rx_tasklet);
+ tasklet_kill(&udc->rx_tasklet);
- iounmap(udc_controller->usb_regs);
+ iounmap(udc->usb_regs);
- device_unregister(&udc_controller->gadget.dev);
+ device_unregister(&udc->gadget.dev);
/* wait for release() of gadget.dev to free udc */
wait_for_completion(&done);
diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h
index 1da5fb03d218..4c07ca9cebf3 100644
--- a/drivers/usb/gadget/fsl_qe_udc.h
+++ b/drivers/usb/gadget/fsl_qe_udc.h
@@ -266,7 +266,6 @@ struct qe_ep {
struct usb_ep ep;
struct list_head queue;
struct qe_udc *udc;
- const struct usb_endpoint_descriptor *desc;
struct usb_gadget *gadget;
u8 state;
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 55abfb6bd612..28316858208b 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007,2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2004-2007,2011-2012 Freescale Semiconductor, Inc.
* All rights reserved.
*
* Author: Li Yang <leoli@freescale.com>
@@ -58,9 +58,8 @@ static const char driver_name[] = "fsl-usb2-udc";
static const char driver_desc[] = DRIVER_DESC;
static struct usb_dr_device *dr_regs;
-#ifndef CONFIG_ARCH_MXC
+
static struct usb_sys_interface *usb_sys_regs;
-#endif
/* it is initialized in probe() */
static struct fsl_udc *udc_controller = NULL;
@@ -244,10 +243,9 @@ static int dr_controller_setup(struct fsl_udc *udc)
{
unsigned int tmp, portctrl, ep_num;
unsigned int max_no_of_ep;
-#ifndef CONFIG_ARCH_MXC
unsigned int ctrl;
-#endif
unsigned long timeout;
+
#define FSL_UDC_RESET_TIMEOUT 1000
/* Config PHY interface */
@@ -255,12 +253,32 @@ static int dr_controller_setup(struct fsl_udc *udc)
portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH);
switch (udc->phy_mode) {
case FSL_USB2_PHY_ULPI:
+ if (udc->pdata->have_sysif_regs) {
+ if (udc->pdata->controller_ver) {
+ /* controller version 1.6 or above */
+ ctrl = __raw_readl(&usb_sys_regs->control);
+ ctrl &= ~USB_CTRL_UTMI_PHY_EN;
+ ctrl |= USB_CTRL_USB_EN;
+ __raw_writel(ctrl, &usb_sys_regs->control);
+ }
+ }
portctrl |= PORTSCX_PTS_ULPI;
break;
case FSL_USB2_PHY_UTMI_WIDE:
portctrl |= PORTSCX_PTW_16BIT;
/* fall through */
case FSL_USB2_PHY_UTMI:
+ if (udc->pdata->have_sysif_regs) {
+ if (udc->pdata->controller_ver) {
+ /* controller version 1.6 or above */
+ ctrl = __raw_readl(&usb_sys_regs->control);
+ ctrl |= (USB_CTRL_UTMI_PHY_EN |
+ USB_CTRL_USB_EN);
+ __raw_writel(ctrl, &usb_sys_regs->control);
+ mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI
+ PHY CLK to become stable - 10ms*/
+ }
+ }
portctrl |= PORTSCX_PTS_UTMI;
break;
case FSL_USB2_PHY_SERIAL:
@@ -549,7 +567,7 @@ static int fsl_ep_enable(struct usb_ep *_ep,
ep = container_of(_ep, struct fsl_ep, ep);
/* catch various bogus parameters */
- if (!_ep || !desc || ep->desc
+ if (!_ep || !desc || ep->ep.desc
|| (desc->bDescriptorType != USB_DT_ENDPOINT))
return -EINVAL;
@@ -590,7 +608,7 @@ static int fsl_ep_enable(struct usb_ep *_ep,
spin_lock_irqsave(&udc->lock, flags);
ep->ep.maxpacket = max;
- ep->desc = desc;
+ ep->ep.desc = desc;
ep->stopped = 0;
/* Controller related setup */
@@ -614,7 +632,7 @@ static int fsl_ep_enable(struct usb_ep *_ep,
retval = 0;
VDBG("enabled %s (ep%d%s) maxpacket %d",ep->ep.name,
- ep->desc->bEndpointAddress & 0x0f,
+ ep->ep.desc->bEndpointAddress & 0x0f,
(desc->bEndpointAddress & USB_DIR_IN)
? "in" : "out", max);
en_done:
@@ -634,7 +652,7 @@ static int fsl_ep_disable(struct usb_ep *_ep)
int ep_num;
ep = container_of(_ep, struct fsl_ep, ep);
- if (!_ep || !ep->desc) {
+ if (!_ep || !ep->ep.desc) {
VDBG("%s not enabled", _ep ? ep->ep.name : NULL);
return -EINVAL;
}
@@ -657,7 +675,6 @@ static int fsl_ep_disable(struct usb_ep *_ep)
/* nuke all pending requests (does flush) */
nuke(ep, -ESHUTDOWN);
- ep->desc = NULL;
ep->ep.desc = NULL;
ep->stopped = 1;
spin_unlock_irqrestore(&udc->lock, flags);
@@ -736,6 +753,8 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
lastreq = list_entry(ep->queue.prev, struct fsl_req, queue);
lastreq->tail->next_td_ptr =
cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK);
+ /* Ensure dTD's next dtd pointer to be updated */
+ wmb();
/* Read prime bit, if 1 goto done */
if (fsl_readl(&dr_regs->endpointprime) & bitmask)
return;
@@ -874,11 +893,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
VDBG("%s, bad params", __func__);
return -EINVAL;
}
- if (unlikely(!_ep || !ep->desc)) {
+ if (unlikely(!_ep || !ep->ep.desc)) {
VDBG("%s, bad ep", __func__);
return -EINVAL;
}
- if (usb_endpoint_xfer_isoc(ep->desc)) {
+ if (usb_endpoint_xfer_isoc(ep->ep.desc)) {
if (req->req.length > ep->ep.maxpacket)
return -EMSGSIZE;
}
@@ -1017,12 +1036,12 @@ static int fsl_ep_set_halt(struct usb_ep *_ep, int value)
ep = container_of(_ep, struct fsl_ep, ep);
udc = ep->udc;
- if (!_ep || !ep->desc) {
+ if (!_ep || !ep->ep.desc) {
status = -EINVAL;
goto out;
}
- if (usb_endpoint_xfer_isoc(ep->desc)) {
+ if (usb_endpoint_xfer_isoc(ep->ep.desc)) {
status = -EOPNOTSUPP;
goto out;
}
@@ -1061,7 +1080,7 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep)
struct ep_queue_head *qh;
ep = container_of(_ep, struct fsl_ep, ep);
- if (!_ep || (!ep->desc && ep_index(ep) != 0))
+ if (!_ep || (!ep->ep.desc && ep_index(ep) != 0))
return -ENODEV;
udc = (struct fsl_udc *)ep->udc;
@@ -1094,7 +1113,7 @@ static void fsl_ep_fifo_flush(struct usb_ep *_ep)
return;
} else {
ep = container_of(_ep, struct fsl_ep, ep);
- if (!ep->desc)
+ if (!ep->ep.desc)
return;
}
ep_num = ep_index(ep);
@@ -1349,7 +1368,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
target_ep = get_ep_by_pipe(udc, get_pipe_by_windex(index));
/* stall if endpoint doesn't exist */
- if (!target_ep->desc)
+ if (!target_ep->ep.desc)
goto stall;
tmp = dr_ep_get_stall(ep_index(target_ep), ep_is_in(target_ep))
<< USB_ENDPOINT_HALT;
@@ -2259,7 +2278,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
}
/* other gadget->eplist ep */
list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
- if (ep->desc) {
+ if (ep->ep.desc) {
t = scnprintf(next, size,
"\nFor %s Maxpkt is 0x%x "
"index is 0x%x\n",
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index e651469fd39b..5cd7b7e7ddb4 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -1,4 +1,12 @@
/*
+ * Copyright (C) 2004,2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
* Freescale USB device/endpoint management registers
*/
#ifndef __FSL_USB2_UDC_H
@@ -348,6 +356,9 @@ struct usb_sys_interface {
/* control Register Bit Masks */
#define USB_CTRL_IOENB 0x00000004
#define USB_CTRL_ULPI_INT0EN 0x00000001
+#define USB_CTRL_UTMI_PHY_EN 0x00000200
+#define USB_CTRL_USB_EN 0x00000004
+#define USB_CTRL_ULPI_PHY_CLK_SEL 0x00000400
/* Endpoint Queue Head data struct
* Rem: all the variables of qh are LittleEndian Mode
@@ -450,7 +461,6 @@ struct fsl_ep {
struct list_head queue;
struct fsl_udc *udc;
struct ep_queue_head *qh;
- const struct usb_endpoint_descriptor *desc;
struct usb_gadget *gadget;
char name[14];
diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c
index 5831cb4a0b35..cdd94540e1cd 100644
--- a/drivers/usb/gadget/fusb300_udc.c
+++ b/drivers/usb/gadget/fusb300_udc.c
@@ -203,7 +203,7 @@ static int config_ep(struct fusb300_ep *ep,
struct fusb300 *fusb300 = ep->fusb300;
struct fusb300_ep_info info;
- ep->desc = desc;
+ ep->ep.desc = desc;
info.interval = 0;
info.addrofs = 0;
@@ -443,7 +443,7 @@ static int fusb300_queue(struct usb_ep *_ep, struct usb_request *_req,
req->req.actual = 0;
req->req.status = -EINPROGRESS;
- if (ep->desc == NULL) /* ep0 */
+ if (ep->ep.desc == NULL) /* ep0 */
ep0_queue(ep, req);
else if (request && !ep->stall)
enable_fifo_int(ep);
diff --git a/drivers/usb/gadget/fusb300_udc.h b/drivers/usb/gadget/fusb300_udc.h
index 92745bd03064..542cd83cc806 100644
--- a/drivers/usb/gadget/fusb300_udc.h
+++ b/drivers/usb/gadget/fusb300_udc.h
@@ -650,7 +650,6 @@ struct fusb300_ep {
unsigned char epnum;
unsigned char type;
- const struct usb_endpoint_descriptor *desc;
};
struct fusb300 {
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index a85eaf40b948..d3ace9002a6a 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -67,6 +67,15 @@ MODULE_LICENSE("GPL");
#define GFS_VENDOR_ID 0x1d6b /* Linux Foundation */
#define GFS_PRODUCT_ID 0x0105 /* FunctionFS Gadget */
+#define GFS_MAX_DEVS 10
+
+struct gfs_ffs_obj {
+ const char *name;
+ bool mounted;
+ bool desc_ready;
+ struct ffs_data *ffs_data;
+};
+
static struct usb_device_descriptor gfs_dev_desc = {
.bLength = sizeof gfs_dev_desc,
.bDescriptorType = USB_DT_DEVICE,
@@ -78,12 +87,17 @@ static struct usb_device_descriptor gfs_dev_desc = {
.idProduct = cpu_to_le16(GFS_PRODUCT_ID),
};
+static char *func_names[GFS_MAX_DEVS];
+static unsigned int func_num;
+
module_param_named(bDeviceClass, gfs_dev_desc.bDeviceClass, byte, 0644);
MODULE_PARM_DESC(bDeviceClass, "USB Device class");
module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte, 0644);
MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass");
module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte, 0644);
MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
+module_param_array_named(functions, func_names, charp, &func_num, 0);
+MODULE_PARM_DESC(functions, "USB Functions list");
static const struct usb_descriptor_header *gfs_otg_desc[] = {
(const struct usb_descriptor_header *)
@@ -158,13 +172,34 @@ static struct usb_composite_driver gfs_driver = {
.iProduct = DRIVER_DESC,
};
-static struct ffs_data *gfs_ffs_data;
-static unsigned long gfs_registered;
+static DEFINE_MUTEX(gfs_lock);
+static unsigned int missing_funcs;
+static bool gfs_ether_setup;
+static bool gfs_registered;
+static bool gfs_single_func;
+static struct gfs_ffs_obj *ffs_tab;
static int __init gfs_init(void)
{
+ int i;
+
ENTER();
+ if (!func_num) {
+ gfs_single_func = true;
+ func_num = 1;
+ }
+
+ ffs_tab = kcalloc(func_num, sizeof *ffs_tab, GFP_KERNEL);
+ if (!ffs_tab)
+ return -ENOMEM;
+
+ if (!gfs_single_func)
+ for (i = 0; i < func_num; i++)
+ ffs_tab[i].name = func_names[i];
+
+ missing_funcs = func_num;
+
return functionfs_init();
}
module_init(gfs_init);
@@ -172,63 +207,165 @@ module_init(gfs_init);
static void __exit gfs_exit(void)
{
ENTER();
+ mutex_lock(&gfs_lock);
- if (test_and_clear_bit(0, &gfs_registered))
+ if (gfs_registered)
usb_composite_unregister(&gfs_driver);
+ gfs_registered = false;
functionfs_cleanup();
+
+ mutex_unlock(&gfs_lock);
+ kfree(ffs_tab);
}
module_exit(gfs_exit);
+static struct gfs_ffs_obj *gfs_find_dev(const char *dev_name)
+{
+ int i;
+
+ ENTER();
+
+ if (gfs_single_func)
+ return &ffs_tab[0];
+
+ for (i = 0; i < func_num; i++)
+ if (strcmp(ffs_tab[i].name, dev_name) == 0)
+ return &ffs_tab[i];
+
+ return NULL;
+}
+
static int functionfs_ready_callback(struct ffs_data *ffs)
{
+ struct gfs_ffs_obj *ffs_obj;
int ret;
ENTER();
+ mutex_lock(&gfs_lock);
+
+ ffs_obj = ffs->private_data;
+ if (!ffs_obj) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (WARN_ON(ffs_obj->desc_ready)) {
+ ret = -EBUSY;
+ goto done;
+ }
+ ffs_obj->desc_ready = true;
+ ffs_obj->ffs_data = ffs;
- if (WARN_ON(test_and_set_bit(0, &gfs_registered)))
- return -EBUSY;
+ if (--missing_funcs) {
+ ret = 0;
+ goto done;
+ }
+
+ if (gfs_registered) {
+ ret = -EBUSY;
+ goto done;
+ }
+ gfs_registered = true;
- gfs_ffs_data = ffs;
ret = usb_composite_probe(&gfs_driver, gfs_bind);
if (unlikely(ret < 0))
- clear_bit(0, &gfs_registered);
+ gfs_registered = false;
+
+done:
+ mutex_unlock(&gfs_lock);
return ret;
}
static void functionfs_closed_callback(struct ffs_data *ffs)
{
+ struct gfs_ffs_obj *ffs_obj;
+
ENTER();
+ mutex_lock(&gfs_lock);
- if (test_and_clear_bit(0, &gfs_registered))
+ ffs_obj = ffs->private_data;
+ if (!ffs_obj)
+ goto done;
+
+ ffs_obj->desc_ready = false;
+ missing_funcs++;
+
+ if (gfs_registered)
usb_composite_unregister(&gfs_driver);
+ gfs_registered = false;
+
+done:
+ mutex_unlock(&gfs_lock);
}
-static int functionfs_check_dev_callback(const char *dev_name)
+static void *functionfs_acquire_dev_callback(const char *dev_name)
{
- return 0;
+ struct gfs_ffs_obj *ffs_dev;
+
+ ENTER();
+ mutex_lock(&gfs_lock);
+
+ ffs_dev = gfs_find_dev(dev_name);
+ if (!ffs_dev) {
+ ffs_dev = ERR_PTR(-ENODEV);
+ goto done;
+ }
+
+ if (ffs_dev->mounted) {
+ ffs_dev = ERR_PTR(-EBUSY);
+ goto done;
+ }
+ ffs_dev->mounted = true;
+
+done:
+ mutex_unlock(&gfs_lock);
+ return ffs_dev;
}
+static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
+{
+ struct gfs_ffs_obj *ffs_dev;
+
+ ENTER();
+ mutex_lock(&gfs_lock);
+
+ ffs_dev = ffs_data->private_data;
+ if (ffs_dev)
+ ffs_dev->mounted = false;
+
+ mutex_unlock(&gfs_lock);
+}
+
+/*
+ * It is assumed that gfs_bind is called from a context where gfs_lock is held
+ */
static int gfs_bind(struct usb_composite_dev *cdev)
{
int ret, i;
ENTER();
- if (WARN_ON(!gfs_ffs_data))
+ if (missing_funcs)
return -ENODEV;
ret = gether_setup(cdev->gadget, gfs_hostaddr);
if (unlikely(ret < 0))
goto error_quick;
+ gfs_ether_setup = true;
ret = usb_string_ids_tab(cdev, gfs_strings);
if (unlikely(ret < 0))
goto error;
- ret = functionfs_bind(gfs_ffs_data, cdev);
- if (unlikely(ret < 0))
- goto error;
+ for (i = func_num; --i; ) {
+ ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);
+ if (unlikely(ret < 0)) {
+ while (++i < func_num)
+ functionfs_unbind(ffs_tab[i].ffs_data);
+ goto error;
+ }
+ }
for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
struct gfs_configuration *c = gfs_configurations + i;
@@ -246,16 +383,22 @@ static int gfs_bind(struct usb_composite_dev *cdev)
return 0;
error_unbind:
- functionfs_unbind(gfs_ffs_data);
+ for (i = 0; i < func_num; i++)
+ functionfs_unbind(ffs_tab[i].ffs_data);
error:
gether_cleanup();
error_quick:
- gfs_ffs_data = NULL;
+ gfs_ether_setup = false;
return ret;
}
+/*
+ * It is assumed that gfs_unbind is called from a context where gfs_lock is held
+ */
static int gfs_unbind(struct usb_composite_dev *cdev)
{
+ int i;
+
ENTER();
/*
@@ -266,22 +409,29 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
* from composite on orror recovery, but what you're gonna
* do...?
*/
- if (gfs_ffs_data) {
+ if (gfs_ether_setup)
gether_cleanup();
- functionfs_unbind(gfs_ffs_data);
- gfs_ffs_data = NULL;
- }
+ gfs_ether_setup = false;
+
+ for (i = func_num; --i; )
+ if (ffs_tab[i].ffs_data)
+ functionfs_unbind(ffs_tab[i].ffs_data);
return 0;
}
+/*
+ * It is assumed that gfs_do_config is called from a context where
+ * gfs_lock is held
+ */
static int gfs_do_config(struct usb_configuration *c)
{
struct gfs_configuration *gc =
container_of(c, struct gfs_configuration, c);
+ int i;
int ret;
- if (WARN_ON(!gfs_ffs_data))
+ if (missing_funcs)
return -ENODEV;
if (gadget_is_otg(c->cdev->gadget)) {
@@ -295,9 +445,11 @@ static int gfs_do_config(struct usb_configuration *c)
return ret;
}
- ret = functionfs_bind_config(c->cdev, c, gfs_ffs_data);
- if (unlikely(ret < 0))
- return ret;
+ for (i = 0; i < func_num; i++) {
+ ret = functionfs_bind_config(c->cdev, c, ffs_tab[i].ffs_data);
+ if (unlikely(ret < 0))
+ return ret;
+ }
/*
* After previous do_configs there may be some invalid
diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h
index e84b3c47ed3c..71ca193358b8 100644
--- a/drivers/usb/gadget/g_zero.h
+++ b/drivers/usb/gadget/g_zero.h
@@ -13,10 +13,11 @@ extern unsigned buflen;
extern const struct usb_descriptor_header *otg_desc[];
/* common utilities */
-struct usb_request *alloc_ep_req(struct usb_ep *ep);
+struct usb_request *alloc_ep_req(struct usb_ep *ep, int len);
void free_ep_req(struct usb_ep *ep, struct usb_request *req);
void disable_endpoints(struct usb_composite_dev *cdev,
- struct usb_ep *in, struct usb_ep *out);
+ struct usb_ep *in, struct usb_ep *out,
+ struct usb_ep *iso_in, struct usb_ep *iso_out);
/* configuration-specific linkup */
int sourcesink_add(struct usb_composite_dev *cdev, bool autoresume);
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index a8855d0b7f3b..b8b3a3411218 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -37,6 +37,7 @@
#define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name))
#define gadget_is_imx(g) (!strcmp("imx_udc", (g)->name))
#define gadget_is_langwell(g) (!strcmp("langwell_udc", (g)->name))
+#define gadget_is_lpc32xx(g) (!strcmp("lpc32xx_udc", (g)->name))
#define gadget_is_m66592(g) (!strcmp("m66592_udc", (g)->name))
#define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name))
#define gadget_is_net2272(g) (!strcmp("net2272", (g)->name))
@@ -118,6 +119,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x31;
else if (gadget_is_dwc3(gadget))
return 0x32;
+ else if (gadget_is_lpc32xx(gadget))
+ return 0x33;
return -ENOENT;
}
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index e151d6b87dee..b241e6c6a7f2 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -102,7 +102,7 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
unsigned long flags;
ep = container_of(_ep, struct goku_ep, ep);
- if (!_ep || !desc || ep->desc
+ if (!_ep || !desc || ep->ep.desc
|| desc->bDescriptorType != USB_DT_ENDPOINT)
return -EINVAL;
dev = ep->dev;
@@ -176,7 +176,7 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
command(ep->dev->regs, COMMAND_RESET, ep->num);
ep->ep.maxpacket = max;
ep->stopped = 0;
- ep->desc = desc;
+ ep->ep.desc = desc;
spin_unlock_irqrestore(&ep->dev->lock, flags);
DBG(dev, "enable %s %s %s maxpacket %u\n", ep->ep.name,
@@ -233,7 +233,6 @@ static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep)
}
ep->ep.maxpacket = MAX_FIFO_SIZE;
- ep->desc = NULL;
ep->ep.desc = NULL;
ep->stopped = 1;
ep->irqs = 0;
@@ -247,7 +246,7 @@ static int goku_ep_disable(struct usb_ep *_ep)
unsigned long flags;
ep = container_of(_ep, struct goku_ep, ep);
- if (!_ep || !ep->desc)
+ if (!_ep || !ep->ep.desc)
return -ENODEV;
dev = ep->dev;
if (dev->ep0state == EP0_SUSPEND)
@@ -722,7 +721,7 @@ goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
|| !_req->buf || !list_empty(&req->queue)))
return -EINVAL;
ep = container_of(_ep, struct goku_ep, ep);
- if (unlikely(!_ep || (!ep->desc && ep->num != 0)))
+ if (unlikely(!_ep || (!ep->ep.desc && ep->num != 0)))
return -EINVAL;
dev = ep->dev;
if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))
@@ -815,7 +814,7 @@ static int goku_dequeue(struct usb_ep *_ep, struct usb_request *_req)
unsigned long flags;
ep = container_of(_ep, struct goku_ep, ep);
- if (!_ep || !_req || (!ep->desc && ep->num != 0))
+ if (!_ep || !_req || (!ep->ep.desc && ep->num != 0))
return -EINVAL;
dev = ep->dev;
if (!dev->driver)
@@ -896,7 +895,7 @@ static int goku_set_halt(struct usb_ep *_ep, int value)
return -EINVAL;
/* don't change EPxSTATUS_EP_INVALID to READY */
- } else if (!ep->desc) {
+ } else if (!ep->ep.desc) {
DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
return -EINVAL;
}
@@ -955,7 +954,7 @@ static void goku_fifo_flush(struct usb_ep *_ep)
VDBG(ep->dev, "%s %s\n", __func__, ep->ep.name);
/* don't change EPxSTATUS_EP_INVALID to READY */
- if (!ep->desc && ep->num != 0) {
+ if (!ep->ep.desc && ep->num != 0) {
DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
return;
}
@@ -1152,7 +1151,7 @@ udc_proc_read(char *buffer, char **start, off_t off, int count,
struct goku_ep *ep = &dev->ep [i];
struct goku_request *req;
- if (i && !ep->desc)
+ if (i && !ep->ep.desc)
continue;
tmp = readl(ep->reg_status);
@@ -1473,7 +1472,8 @@ static void ep0_setup(struct goku_udc *dev)
case USB_RECIP_ENDPOINT:
tmp = le16_to_cpu(ctrl.wIndex) & 0x0f;
/* active endpoint */
- if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0))
+ if (tmp > 3 ||
+ (!dev->ep[tmp].ep.desc && tmp != 0))
goto stall;
if (ctrl.wIndex & cpu_to_le16(
USB_DIR_IN)) {
@@ -1895,14 +1895,4 @@ static struct pci_driver goku_pci_driver = {
/* FIXME add power management support */
};
-static int __init init (void)
-{
- return pci_register_driver (&goku_pci_driver);
-}
-module_init (init);
-
-static void __exit cleanup (void)
-{
- pci_unregister_driver (&goku_pci_driver);
-}
-module_exit (cleanup);
+module_pci_driver(goku_pci_driver);
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h
index e7e0c69d3b1f..85cdce0d1901 100644
--- a/drivers/usb/gadget/goku_udc.h
+++ b/drivers/usb/gadget/goku_udc.h
@@ -216,7 +216,6 @@ struct goku_ep {
/* analogous to a host-side qh */
struct list_head queue;
- const struct usb_endpoint_descriptor *desc;
u32 __iomem *reg_fifo;
u32 __iomem *reg_mode;
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
index 8d1c75abd73d..54034f84f992 100644
--- a/drivers/usb/gadget/imx_udc.c
+++ b/drivers/usb/gadget/imx_udc.c
@@ -1237,14 +1237,15 @@ irq_handler_t intr_handler(int i)
*******************************************************************************
*/
-static int imx_udc_start(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *));
-static int imx_udc_stop(struct usb_gadget_driver *driver);
+static int imx_udc_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver);
+static int imx_udc_stop(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver);
static const struct usb_gadget_ops imx_udc_ops = {
- .get_frame = imx_udc_get_frame,
- .wakeup = imx_udc_wakeup,
- .start = imx_udc_start,
- .stop = imx_udc_stop,
+ .get_frame = imx_udc_get_frame,
+ .wakeup = imx_udc_wakeup,
+ .udc_start = imx_udc_start,
+ .udc_stop = imx_udc_stop,
};
static struct imx_udc_struct controller = {
@@ -1329,23 +1330,13 @@ static struct imx_udc_struct controller = {
* USB gadget driver functions
*******************************************************************************
*/
-static int imx_udc_start(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *))
+static int imx_udc_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
{
- struct imx_udc_struct *imx_usb = &controller;
+ struct imx_udc_struct *imx_usb;
int retval;
- if (!driver
- || driver->max_speed < USB_SPEED_FULL
- || !bind
- || !driver->disconnect
- || !driver->setup)
- return -EINVAL;
- if (!imx_usb)
- return -ENODEV;
- if (imx_usb->driver)
- return -EBUSY;
-
+ imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
/* first hook up the driver ... */
imx_usb->driver = driver;
imx_usb->gadget.dev.driver = &driver->driver;
@@ -1353,14 +1344,6 @@ static int imx_udc_start(struct usb_gadget_driver *driver,
retval = device_add(&imx_usb->gadget.dev);
if (retval)
goto fail;
- retval = bind(&imx_usb->gadget);
- if (retval) {
- D_ERR(imx_usb->dev, "<%s> bind to driver %s --> error %d\n",
- __func__, driver->driver.name, retval);
- device_del(&imx_usb->gadget.dev);
-
- goto fail;
- }
D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
__func__, driver->driver.name);
@@ -1374,20 +1357,16 @@ fail:
return retval;
}
-static int imx_udc_stop(struct usb_gadget_driver *driver)
+static int imx_udc_stop(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
{
- struct imx_udc_struct *imx_usb = &controller;
-
- if (!imx_usb)
- return -ENODEV;
- if (!driver || driver != imx_usb->driver || !driver->unbind)
- return -EINVAL;
+ struct imx_udc_struct *imx_usb = container_of(gadget,
+ struct imx_udc_struct, gadget);
udc_stop_activity(imx_usb, driver);
imx_udc_disable(imx_usb);
del_timer(&imx_usb->timer);
- driver->unbind(&imx_usb->gadget);
imx_usb->gadget.dev.driver = NULL;
imx_usb->driver = NULL;
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
deleted file mode 100644
index f9cedd52cf20..000000000000
--- a/drivers/usb/gadget/langwell_udc.c
+++ /dev/null
@@ -1,3434 +0,0 @@
-/*
- * Intel Langwell USB Device Controller driver
- * Copyright (C) 2008-2009, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- */
-
-
-/* #undef DEBUG */
-/* #undef VERBOSE_DEBUG */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
-#include <linux/pm.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <asm/unaligned.h>
-
-#include "langwell_udc.h"
-
-
-#define DRIVER_DESC "Intel Langwell USB Device Controller driver"
-#define DRIVER_VERSION "16 May 2009"
-
-static const char driver_name[] = "langwell_udc";
-static const char driver_desc[] = DRIVER_DESC;
-
-
-/* for endpoint 0 operations */
-static const struct usb_endpoint_descriptor
-langwell_ep0_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 0,
- .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
- .wMaxPacketSize = EP0_MAX_PKT_SIZE,
-};
-
-
-/*-------------------------------------------------------------------------*/
-/* debugging */
-
-#ifdef VERBOSE_DEBUG
-static inline void print_all_registers(struct langwell_udc *dev)
-{
- int i;
-
- /* Capability Registers */
- dev_dbg(&dev->pdev->dev,
- "Capability Registers (offset: 0x%04x, length: 0x%08x)\n",
- CAP_REG_OFFSET, (u32)sizeof(struct langwell_cap_regs));
- dev_dbg(&dev->pdev->dev, "caplength=0x%02x\n",
- readb(&dev->cap_regs->caplength));
- dev_dbg(&dev->pdev->dev, "hciversion=0x%04x\n",
- readw(&dev->cap_regs->hciversion));
- dev_dbg(&dev->pdev->dev, "hcsparams=0x%08x\n",
- readl(&dev->cap_regs->hcsparams));
- dev_dbg(&dev->pdev->dev, "hccparams=0x%08x\n",
- readl(&dev->cap_regs->hccparams));
- dev_dbg(&dev->pdev->dev, "dciversion=0x%04x\n",
- readw(&dev->cap_regs->dciversion));
- dev_dbg(&dev->pdev->dev, "dccparams=0x%08x\n",
- readl(&dev->cap_regs->dccparams));
-
- /* Operational Registers */
- dev_dbg(&dev->pdev->dev,
- "Operational Registers (offset: 0x%04x, length: 0x%08x)\n",
- OP_REG_OFFSET, (u32)sizeof(struct langwell_op_regs));
- dev_dbg(&dev->pdev->dev, "extsts=0x%08x\n",
- readl(&dev->op_regs->extsts));
- dev_dbg(&dev->pdev->dev, "extintr=0x%08x\n",
- readl(&dev->op_regs->extintr));
- dev_dbg(&dev->pdev->dev, "usbcmd=0x%08x\n",
- readl(&dev->op_regs->usbcmd));
- dev_dbg(&dev->pdev->dev, "usbsts=0x%08x\n",
- readl(&dev->op_regs->usbsts));
- dev_dbg(&dev->pdev->dev, "usbintr=0x%08x\n",
- readl(&dev->op_regs->usbintr));
- dev_dbg(&dev->pdev->dev, "frindex=0x%08x\n",
- readl(&dev->op_regs->frindex));
- dev_dbg(&dev->pdev->dev, "ctrldssegment=0x%08x\n",
- readl(&dev->op_regs->ctrldssegment));
- dev_dbg(&dev->pdev->dev, "deviceaddr=0x%08x\n",
- readl(&dev->op_regs->deviceaddr));
- dev_dbg(&dev->pdev->dev, "endpointlistaddr=0x%08x\n",
- readl(&dev->op_regs->endpointlistaddr));
- dev_dbg(&dev->pdev->dev, "ttctrl=0x%08x\n",
- readl(&dev->op_regs->ttctrl));
- dev_dbg(&dev->pdev->dev, "burstsize=0x%08x\n",
- readl(&dev->op_regs->burstsize));
- dev_dbg(&dev->pdev->dev, "txfilltuning=0x%08x\n",
- readl(&dev->op_regs->txfilltuning));
- dev_dbg(&dev->pdev->dev, "txttfilltuning=0x%08x\n",
- readl(&dev->op_regs->txttfilltuning));
- dev_dbg(&dev->pdev->dev, "ic_usb=0x%08x\n",
- readl(&dev->op_regs->ic_usb));
- dev_dbg(&dev->pdev->dev, "ulpi_viewport=0x%08x\n",
- readl(&dev->op_regs->ulpi_viewport));
- dev_dbg(&dev->pdev->dev, "configflag=0x%08x\n",
- readl(&dev->op_regs->configflag));
- dev_dbg(&dev->pdev->dev, "portsc1=0x%08x\n",
- readl(&dev->op_regs->portsc1));
- dev_dbg(&dev->pdev->dev, "devlc=0x%08x\n",
- readl(&dev->op_regs->devlc));
- dev_dbg(&dev->pdev->dev, "otgsc=0x%08x\n",
- readl(&dev->op_regs->otgsc));
- dev_dbg(&dev->pdev->dev, "usbmode=0x%08x\n",
- readl(&dev->op_regs->usbmode));
- dev_dbg(&dev->pdev->dev, "endptnak=0x%08x\n",
- readl(&dev->op_regs->endptnak));
- dev_dbg(&dev->pdev->dev, "endptnaken=0x%08x\n",
- readl(&dev->op_regs->endptnaken));
- dev_dbg(&dev->pdev->dev, "endptsetupstat=0x%08x\n",
- readl(&dev->op_regs->endptsetupstat));
- dev_dbg(&dev->pdev->dev, "endptprime=0x%08x\n",
- readl(&dev->op_regs->endptprime));
- dev_dbg(&dev->pdev->dev, "endptflush=0x%08x\n",
- readl(&dev->op_regs->endptflush));
- dev_dbg(&dev->pdev->dev, "endptstat=0x%08x\n",
- readl(&dev->op_regs->endptstat));
- dev_dbg(&dev->pdev->dev, "endptcomplete=0x%08x\n",
- readl(&dev->op_regs->endptcomplete));
-
- for (i = 0; i < dev->ep_max / 2; i++) {
- dev_dbg(&dev->pdev->dev, "endptctrl[%d]=0x%08x\n",
- i, readl(&dev->op_regs->endptctrl[i]));
- }
-}
-#else
-
-#define print_all_registers(dev) do { } while (0)
-
-#endif /* VERBOSE_DEBUG */
-
-
-/*-------------------------------------------------------------------------*/
-
-#define is_in(ep) (((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir == \
- USB_DIR_IN) : (usb_endpoint_dir_in((ep)->desc)))
-
-#define DIR_STRING(ep) (is_in(ep) ? "in" : "out")
-
-
-static char *type_string(const struct usb_endpoint_descriptor *desc)
-{
- switch (usb_endpoint_type(desc)) {
- case USB_ENDPOINT_XFER_BULK:
- return "bulk";
- case USB_ENDPOINT_XFER_ISOC:
- return "iso";
- case USB_ENDPOINT_XFER_INT:
- return "int";
- };
-
- return "control";
-}
-
-
-/* configure endpoint control registers */
-static void ep_reset(struct langwell_ep *ep, unsigned char ep_num,
- unsigned char is_in, unsigned char ep_type)
-{
- struct langwell_udc *dev;
- u32 endptctrl;
-
- dev = ep->dev;
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
- if (is_in) { /* TX */
- if (ep_num)
- endptctrl |= EPCTRL_TXR;
- endptctrl |= EPCTRL_TXE;
- endptctrl |= ep_type << EPCTRL_TXT_SHIFT;
- } else { /* RX */
- if (ep_num)
- endptctrl |= EPCTRL_RXR;
- endptctrl |= EPCTRL_RXE;
- endptctrl |= ep_type << EPCTRL_RXT_SHIFT;
- }
-
- writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* reset ep0 dQH and endptctrl */
-static void ep0_reset(struct langwell_udc *dev)
-{
- struct langwell_ep *ep;
- int i;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* ep0 in and out */
- for (i = 0; i < 2; i++) {
- ep = &dev->ep[i];
- ep->dev = dev;
-
- /* ep0 dQH */
- ep->dqh = &dev->ep_dqh[i];
-
- /* configure ep0 endpoint capabilities in dQH */
- ep->dqh->dqh_ios = 1;
- ep->dqh->dqh_mpl = EP0_MAX_PKT_SIZE;
-
- /* enable ep0-in HW zero length termination select */
- if (is_in(ep))
- ep->dqh->dqh_zlt = 0;
- ep->dqh->dqh_mult = 0;
-
- ep->dqh->dtd_next = DTD_TERM;
-
- /* configure ep0 control registers */
- ep_reset(&dev->ep[0], 0, i, USB_ENDPOINT_XFER_CONTROL);
- }
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* endpoints operations */
-
-/* configure endpoint, making it usable */
-static int langwell_ep_enable(struct usb_ep *_ep,
- const struct usb_endpoint_descriptor *desc)
-{
- struct langwell_udc *dev;
- struct langwell_ep *ep;
- u16 max = 0;
- unsigned long flags;
- int i, retval = 0;
- unsigned char zlt, ios = 0, mult = 0;
-
- ep = container_of(_ep, struct langwell_ep, ep);
- dev = ep->dev;
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if (!_ep || !desc || ep->desc
- || desc->bDescriptorType != USB_DT_ENDPOINT)
- return -EINVAL;
-
- if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
- return -ESHUTDOWN;
-
- max = usb_endpoint_maxp(desc);
-
- /*
- * disable HW zero length termination select
- * driver handles zero length packet through req->req.zero
- */
- zlt = 1;
-
- /*
- * sanity check type, direction, address, and then
- * initialize the endpoint capabilities fields in dQH
- */
- switch (usb_endpoint_type(desc)) {
- case USB_ENDPOINT_XFER_CONTROL:
- ios = 1;
- break;
- case USB_ENDPOINT_XFER_BULK:
- if ((dev->gadget.speed == USB_SPEED_HIGH
- && max != 512)
- || (dev->gadget.speed == USB_SPEED_FULL
- && max > 64)) {
- goto done;
- }
- break;
- case USB_ENDPOINT_XFER_INT:
- if (strstr(ep->ep.name, "-iso")) /* bulk is ok */
- goto done;
-
- switch (dev->gadget.speed) {
- case USB_SPEED_HIGH:
- if (max <= 1024)
- break;
- case USB_SPEED_FULL:
- if (max <= 64)
- break;
- default:
- if (max <= 8)
- break;
- goto done;
- }
- break;
- case USB_ENDPOINT_XFER_ISOC:
- if (strstr(ep->ep.name, "-bulk")
- || strstr(ep->ep.name, "-int"))
- goto done;
-
- switch (dev->gadget.speed) {
- case USB_SPEED_HIGH:
- if (max <= 1024)
- break;
- case USB_SPEED_FULL:
- if (max <= 1023)
- break;
- default:
- goto done;
- }
- /*
- * FIXME:
- * calculate transactions needed for high bandwidth iso
- */
- mult = (unsigned char)(1 + ((max >> 11) & 0x03));
- max = max & 0x8ff; /* bit 0~10 */
- /* 3 transactions at most */
- if (mult > 3)
- goto done;
- break;
- default:
- goto done;
- }
-
- spin_lock_irqsave(&dev->lock, flags);
-
- ep->ep.maxpacket = max;
- ep->desc = desc;
- ep->stopped = 0;
- ep->ep_num = usb_endpoint_num(desc);
-
- /* ep_type */
- ep->ep_type = usb_endpoint_type(desc);
-
- /* configure endpoint control registers */
- ep_reset(ep, ep->ep_num, is_in(ep), ep->ep_type);
-
- /* configure endpoint capabilities in dQH */
- i = ep->ep_num * 2 + is_in(ep);
- ep->dqh = &dev->ep_dqh[i];
- ep->dqh->dqh_ios = ios;
- ep->dqh->dqh_mpl = cpu_to_le16(max);
- ep->dqh->dqh_zlt = zlt;
- ep->dqh->dqh_mult = mult;
- ep->dqh->dtd_next = DTD_TERM;
-
- dev_dbg(&dev->pdev->dev, "enabled %s (ep%d%s-%s), max %04x\n",
- _ep->name,
- ep->ep_num,
- DIR_STRING(ep),
- type_string(desc),
- max);
-
- spin_unlock_irqrestore(&dev->lock, flags);
-done:
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return retval;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* retire a request */
-static void done(struct langwell_ep *ep, struct langwell_request *req,
- int status)
-{
- struct langwell_udc *dev = ep->dev;
- unsigned stopped = ep->stopped;
- struct langwell_dtd *curr_dtd, *next_dtd;
- int i;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* remove the req from ep->queue */
- list_del_init(&req->queue);
-
- if (req->req.status == -EINPROGRESS)
- req->req.status = status;
- else
- status = req->req.status;
-
- /* free dTD for the request */
- next_dtd = req->head;
- for (i = 0; i < req->dtd_count; i++) {
- curr_dtd = next_dtd;
- if (i != req->dtd_count - 1)
- next_dtd = curr_dtd->next_dtd_virt;
- dma_pool_free(dev->dtd_pool, curr_dtd, curr_dtd->dtd_dma);
- }
-
- usb_gadget_unmap_request(&dev->gadget, &req->req, is_in(ep));
-
- if (status != -ESHUTDOWN)
- dev_dbg(&dev->pdev->dev,
- "complete %s, req %p, stat %d, len %u/%u\n",
- ep->ep.name, &req->req, status,
- req->req.actual, req->req.length);
-
- /* don't modify queue heads during completion callback */
- ep->stopped = 1;
-
- spin_unlock(&dev->lock);
- /* complete routine from gadget driver */
- if (req->req.complete)
- req->req.complete(&ep->ep, &req->req);
-
- spin_lock(&dev->lock);
- ep->stopped = stopped;
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-static void langwell_ep_fifo_flush(struct usb_ep *_ep);
-
-/* delete all endpoint requests, called with spinlock held */
-static void nuke(struct langwell_ep *ep, int status)
-{
- /* called with spinlock held */
- ep->stopped = 1;
-
- /* endpoint fifo flush */
- if (&ep->ep && ep->desc)
- langwell_ep_fifo_flush(&ep->ep);
-
- while (!list_empty(&ep->queue)) {
- struct langwell_request *req = NULL;
- req = list_entry(ep->queue.next, struct langwell_request,
- queue);
- done(ep, req, status);
- }
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* endpoint is no longer usable */
-static int langwell_ep_disable(struct usb_ep *_ep)
-{
- struct langwell_ep *ep;
- unsigned long flags;
- struct langwell_udc *dev;
- int ep_num;
- u32 endptctrl;
-
- ep = container_of(_ep, struct langwell_ep, ep);
- dev = ep->dev;
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if (!_ep || !ep->desc)
- return -EINVAL;
-
- spin_lock_irqsave(&dev->lock, flags);
-
- /* disable endpoint control register */
- ep_num = ep->ep_num;
- endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
- if (is_in(ep))
- endptctrl &= ~EPCTRL_TXE;
- else
- endptctrl &= ~EPCTRL_RXE;
- writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
-
- /* nuke all pending requests (does flush) */
- nuke(ep, -ESHUTDOWN);
-
- ep->desc = NULL;
- ep->ep.desc = NULL;
- ep->stopped = 1;
-
- spin_unlock_irqrestore(&dev->lock, flags);
-
- dev_dbg(&dev->pdev->dev, "disabled %s\n", _ep->name);
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-
- return 0;
-}
-
-
-/* allocate a request object to use with this endpoint */
-static struct usb_request *langwell_alloc_request(struct usb_ep *_ep,
- gfp_t gfp_flags)
-{
- struct langwell_ep *ep;
- struct langwell_udc *dev;
- struct langwell_request *req = NULL;
-
- if (!_ep)
- return NULL;
-
- ep = container_of(_ep, struct langwell_ep, ep);
- dev = ep->dev;
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- req = kzalloc(sizeof(*req), gfp_flags);
- if (!req)
- return NULL;
-
- req->req.dma = DMA_ADDR_INVALID;
- INIT_LIST_HEAD(&req->queue);
-
- dev_vdbg(&dev->pdev->dev, "alloc request for %s\n", _ep->name);
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return &req->req;
-}
-
-
-/* free a request object */
-static void langwell_free_request(struct usb_ep *_ep,
- struct usb_request *_req)
-{
- struct langwell_ep *ep;
- struct langwell_udc *dev;
- struct langwell_request *req = NULL;
-
- ep = container_of(_ep, struct langwell_ep, ep);
- dev = ep->dev;
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if (!_ep || !_req)
- return;
-
- req = container_of(_req, struct langwell_request, req);
- WARN_ON(!list_empty(&req->queue));
-
- if (_req)
- kfree(req);
-
- dev_vdbg(&dev->pdev->dev, "free request for %s\n", _ep->name);
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* queue dTD and PRIME endpoint */
-static int queue_dtd(struct langwell_ep *ep, struct langwell_request *req)
-{
- u32 bit_mask, usbcmd, endptstat, dtd_dma;
- u8 dtd_status;
- int i;
- struct langwell_dqh *dqh;
- struct langwell_udc *dev;
-
- dev = ep->dev;
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- i = ep->ep_num * 2 + is_in(ep);
- dqh = &dev->ep_dqh[i];
-
- if (ep->ep_num)
- dev_vdbg(&dev->pdev->dev, "%s\n", ep->name);
- else
- /* ep0 */
- dev_vdbg(&dev->pdev->dev, "%s-%s\n", ep->name, DIR_STRING(ep));
-
- dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%p\n",
- i, &(dev->ep_dqh[i]));
-
- bit_mask = is_in(ep) ?
- (1 << (ep->ep_num + 16)) : (1 << (ep->ep_num));
-
- dev_vdbg(&dev->pdev->dev, "bit_mask = 0x%08x\n", bit_mask);
-
- /* check if the pipe is empty */
- if (!(list_empty(&ep->queue))) {
- /* add dTD to the end of linked list */
- struct langwell_request *lastreq;
- lastreq = list_entry(ep->queue.prev,
- struct langwell_request, queue);
-
- lastreq->tail->dtd_next =
- cpu_to_le32(req->head->dtd_dma & DTD_NEXT_MASK);
-
- /* read prime bit, if 1 goto out */
- if (readl(&dev->op_regs->endptprime) & bit_mask)
- goto out;
-
- do {
- /* set ATDTW bit in USBCMD */
- usbcmd = readl(&dev->op_regs->usbcmd);
- writel(usbcmd | CMD_ATDTW, &dev->op_regs->usbcmd);
-
- /* read correct status bit */
- endptstat = readl(&dev->op_regs->endptstat) & bit_mask;
-
- } while (!(readl(&dev->op_regs->usbcmd) & CMD_ATDTW));
-
- /* write ATDTW bit to 0 */
- usbcmd = readl(&dev->op_regs->usbcmd);
- writel(usbcmd & ~CMD_ATDTW, &dev->op_regs->usbcmd);
-
- if (endptstat)
- goto out;
- }
-
- /* write dQH next pointer and terminate bit to 0 */
- dtd_dma = req->head->dtd_dma & DTD_NEXT_MASK;
- dqh->dtd_next = cpu_to_le32(dtd_dma);
-
- /* clear active and halt bit */
- dtd_status = (u8) ~(DTD_STS_ACTIVE | DTD_STS_HALTED);
- dqh->dtd_status &= dtd_status;
- dev_vdbg(&dev->pdev->dev, "dqh->dtd_status = 0x%x\n", dqh->dtd_status);
-
- /* ensure that updates to the dQH will occur before priming */
- wmb();
-
- /* write 1 to endptprime register to PRIME endpoint */
- bit_mask = is_in(ep) ? (1 << (ep->ep_num + 16)) : (1 << ep->ep_num);
- dev_vdbg(&dev->pdev->dev, "endprime bit_mask = 0x%08x\n", bit_mask);
- writel(bit_mask, &dev->op_regs->endptprime);
-out:
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return 0;
-}
-
-
-/* fill in the dTD structure to build a transfer descriptor */
-static struct langwell_dtd *build_dtd(struct langwell_request *req,
- unsigned *length, dma_addr_t *dma, int *is_last)
-{
- u32 buf_ptr;
- struct langwell_dtd *dtd;
- struct langwell_udc *dev;
- int i;
-
- dev = req->ep->dev;
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* the maximum transfer length, up to 16k bytes */
- *length = min(req->req.length - req->req.actual,
- (unsigned)DTD_MAX_TRANSFER_LENGTH);
-
- /* create dTD dma_pool resource */
- dtd = dma_pool_alloc(dev->dtd_pool, GFP_KERNEL, dma);
- if (dtd == NULL)
- return dtd;
- dtd->dtd_dma = *dma;
-
- /* initialize buffer page pointers */
- buf_ptr = (u32)(req->req.dma + req->req.actual);
- for (i = 0; i < 5; i++)
- dtd->dtd_buf[i] = cpu_to_le32(buf_ptr + i * PAGE_SIZE);
-
- req->req.actual += *length;
-
- /* fill in total bytes with transfer size */
- dtd->dtd_total = cpu_to_le16(*length);
- dev_vdbg(&dev->pdev->dev, "dtd->dtd_total = %d\n", dtd->dtd_total);
-
- /* set is_last flag if req->req.zero is set or not */
- if (req->req.zero) {
- if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0)
- *is_last = 1;
- else
- *is_last = 0;
- } else if (req->req.length == req->req.actual) {
- *is_last = 1;
- } else
- *is_last = 0;
-
- if (*is_last == 0)
- dev_vdbg(&dev->pdev->dev, "multi-dtd request!\n");
-
- /* set interrupt on complete bit for the last dTD */
- if (*is_last && !req->req.no_interrupt)
- dtd->dtd_ioc = 1;
-
- /* set multiplier override 0 for non-ISO and non-TX endpoint */
- dtd->dtd_multo = 0;
-
- /* set the active bit of status field to 1 */
- dtd->dtd_status = DTD_STS_ACTIVE;
- dev_vdbg(&dev->pdev->dev, "dtd->dtd_status = 0x%02x\n",
- dtd->dtd_status);
-
- dev_vdbg(&dev->pdev->dev, "length = %d, dma addr= 0x%08x\n",
- *length, (int)*dma);
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return dtd;
-}
-
-
-/* generate dTD linked list for a request */
-static int req_to_dtd(struct langwell_request *req)
-{
- unsigned count;
- int is_last, is_first = 1;
- struct langwell_dtd *dtd, *last_dtd = NULL;
- struct langwell_udc *dev;
- dma_addr_t dma;
-
- dev = req->ep->dev;
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
- do {
- dtd = build_dtd(req, &count, &dma, &is_last);
- if (dtd == NULL)
- return -ENOMEM;
-
- if (is_first) {
- is_first = 0;
- req->head = dtd;
- } else {
- last_dtd->dtd_next = cpu_to_le32(dma);
- last_dtd->next_dtd_virt = dtd;
- }
- last_dtd = dtd;
- req->dtd_count++;
- } while (!is_last);
-
- /* set terminate bit to 1 for the last dTD */
- dtd->dtd_next = DTD_TERM;
-
- req->tail = dtd;
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* queue (submits) an I/O requests to an endpoint */
-static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
- gfp_t gfp_flags)
-{
- struct langwell_request *req;
- struct langwell_ep *ep;
- struct langwell_udc *dev;
- unsigned long flags;
- int is_iso = 0;
- int ret;
-
- /* always require a cpu-view buffer */
- req = container_of(_req, struct langwell_request, req);
- ep = container_of(_ep, struct langwell_ep, ep);
-
- if (!_req || !_req->complete || !_req->buf
- || !list_empty(&req->queue)) {
- return -EINVAL;
- }
-
- if (unlikely(!_ep || !ep->desc))
- return -EINVAL;
-
- dev = ep->dev;
- req->ep = ep;
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if (usb_endpoint_xfer_isoc(ep->desc)) {
- if (req->req.length > ep->ep.maxpacket)
- return -EMSGSIZE;
- is_iso = 1;
- }
-
- if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))
- return -ESHUTDOWN;
-
- /* set up dma mapping */
- ret = usb_gadget_map_request(&dev->gadget, &req->req, is_in(ep));
- if (ret)
- return ret;
-
- dev_dbg(&dev->pdev->dev,
- "%s queue req %p, len %u, buf %p, dma 0x%08x\n",
- _ep->name,
- _req, _req->length, _req->buf, (int)_req->dma);
-
- _req->status = -EINPROGRESS;
- _req->actual = 0;
- req->dtd_count = 0;
-
- spin_lock_irqsave(&dev->lock, flags);
-
- /* build and put dTDs to endpoint queue */
- if (!req_to_dtd(req)) {
- queue_dtd(ep, req);
- } else {
- spin_unlock_irqrestore(&dev->lock, flags);
- return -ENOMEM;
- }
-
- /* update ep0 state */
- if (ep->ep_num == 0)
- dev->ep0_state = DATA_STATE_XMIT;
-
- if (likely(req != NULL)) {
- list_add_tail(&req->queue, &ep->queue);
- dev_vdbg(&dev->pdev->dev, "list_add_tail()\n");
- }
-
- spin_unlock_irqrestore(&dev->lock, flags);
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return 0;
-}
-
-
-/* dequeue (cancels, unlinks) an I/O request from an endpoint */
-static int langwell_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
- struct langwell_ep *ep;
- struct langwell_udc *dev;
- struct langwell_request *req;
- unsigned long flags;
- int stopped, ep_num, retval = 0;
- u32 endptctrl;
-
- ep = container_of(_ep, struct langwell_ep, ep);
- dev = ep->dev;
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if (!_ep || !ep->desc || !_req)
- return -EINVAL;
-
- if (!dev->driver)
- return -ESHUTDOWN;
-
- spin_lock_irqsave(&dev->lock, flags);
- stopped = ep->stopped;
-
- /* quiesce dma while we patch the queue */
- ep->stopped = 1;
- ep_num = ep->ep_num;
-
- /* disable endpoint control register */
- endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
- if (is_in(ep))
- endptctrl &= ~EPCTRL_TXE;
- else
- endptctrl &= ~EPCTRL_RXE;
- writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
-
- /* make sure it's still queued on this endpoint */
- list_for_each_entry(req, &ep->queue, queue) {
- if (&req->req == _req)
- break;
- }
-
- if (&req->req != _req) {
- retval = -EINVAL;
- goto done;
- }
-
- /* queue head may be partially complete. */
- if (ep->queue.next == &req->queue) {
- dev_dbg(&dev->pdev->dev, "unlink (%s) dma\n", _ep->name);
- _req->status = -ECONNRESET;
- langwell_ep_fifo_flush(&ep->ep);
-
- /* not the last request in endpoint queue */
- if (likely(ep->queue.next == &req->queue)) {
- struct langwell_dqh *dqh;
- struct langwell_request *next_req;
-
- dqh = ep->dqh;
- next_req = list_entry(req->queue.next,
- struct langwell_request, queue);
-
- /* point the dQH to the first dTD of next request */
- writel((u32) next_req->head, &dqh->dqh_current);
- }
- } else {
- struct langwell_request *prev_req;
-
- prev_req = list_entry(req->queue.prev,
- struct langwell_request, queue);
- writel(readl(&req->tail->dtd_next),
- &prev_req->tail->dtd_next);
- }
-
- done(ep, req, -ECONNRESET);
-
-done:
- /* enable endpoint again */
- endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
- if (is_in(ep))
- endptctrl |= EPCTRL_TXE;
- else
- endptctrl |= EPCTRL_RXE;
- writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
-
- ep->stopped = stopped;
- spin_unlock_irqrestore(&dev->lock, flags);
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return retval;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* endpoint set/clear halt */
-static void ep_set_halt(struct langwell_ep *ep, int value)
-{
- u32 endptctrl = 0;
- int ep_num;
- struct langwell_udc *dev = ep->dev;
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- ep_num = ep->ep_num;
- endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
-
- /* value: 1 - set halt, 0 - clear halt */
- if (value) {
- /* set the stall bit */
- if (is_in(ep))
- endptctrl |= EPCTRL_TXS;
- else
- endptctrl |= EPCTRL_RXS;
- } else {
- /* clear the stall bit and reset data toggle */
- if (is_in(ep)) {
- endptctrl &= ~EPCTRL_TXS;
- endptctrl |= EPCTRL_TXR;
- } else {
- endptctrl &= ~EPCTRL_RXS;
- endptctrl |= EPCTRL_RXR;
- }
- }
-
- writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* set the endpoint halt feature */
-static int langwell_ep_set_halt(struct usb_ep *_ep, int value)
-{
- struct langwell_ep *ep;
- struct langwell_udc *dev;
- unsigned long flags;
- int retval = 0;
-
- ep = container_of(_ep, struct langwell_ep, ep);
- dev = ep->dev;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if (!_ep || !ep->desc)
- return -EINVAL;
-
- if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
- return -ESHUTDOWN;
-
- if (usb_endpoint_xfer_isoc(ep->desc))
- return -EOPNOTSUPP;
-
- spin_lock_irqsave(&dev->lock, flags);
-
- /*
- * attempt to halt IN ep will fail if any transfer requests
- * are still queue
- */
- if (!list_empty(&ep->queue) && is_in(ep) && value) {
- /* IN endpoint FIFO holds bytes */
- dev_dbg(&dev->pdev->dev, "%s FIFO holds bytes\n", _ep->name);
- retval = -EAGAIN;
- goto done;
- }
-
- /* endpoint set/clear halt */
- if (ep->ep_num) {
- ep_set_halt(ep, value);
- } else { /* endpoint 0 */
- dev->ep0_state = WAIT_FOR_SETUP;
- dev->ep0_dir = USB_DIR_OUT;
- }
-done:
- spin_unlock_irqrestore(&dev->lock, flags);
- dev_dbg(&dev->pdev->dev, "%s %s halt\n",
- _ep->name, value ? "set" : "clear");
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return retval;
-}
-
-
-/* set the halt feature and ignores clear requests */
-static int langwell_ep_set_wedge(struct usb_ep *_ep)
-{
- struct langwell_ep *ep;
- struct langwell_udc *dev;
-
- ep = container_of(_ep, struct langwell_ep, ep);
- dev = ep->dev;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if (!_ep || !ep->desc)
- return -EINVAL;
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return usb_ep_set_halt(_ep);
-}
-
-
-/* flush contents of a fifo */
-static void langwell_ep_fifo_flush(struct usb_ep *_ep)
-{
- struct langwell_ep *ep;
- struct langwell_udc *dev;
- u32 flush_bit;
- unsigned long timeout;
-
- ep = container_of(_ep, struct langwell_ep, ep);
- dev = ep->dev;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if (!_ep || !ep->desc) {
- dev_vdbg(&dev->pdev->dev, "ep or ep->desc is NULL\n");
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return;
- }
-
- dev_vdbg(&dev->pdev->dev, "%s-%s fifo flush\n",
- _ep->name, DIR_STRING(ep));
-
- /* flush endpoint buffer */
- if (ep->ep_num == 0)
- flush_bit = (1 << 16) | 1;
- else if (is_in(ep))
- flush_bit = 1 << (ep->ep_num + 16); /* TX */
- else
- flush_bit = 1 << ep->ep_num; /* RX */
-
- /* wait until flush complete */
- timeout = jiffies + FLUSH_TIMEOUT;
- do {
- writel(flush_bit, &dev->op_regs->endptflush);
- while (readl(&dev->op_regs->endptflush)) {
- if (time_after(jiffies, timeout)) {
- dev_err(&dev->pdev->dev, "ep flush timeout\n");
- goto done;
- }
- cpu_relax();
- }
- } while (readl(&dev->op_regs->endptstat) & flush_bit);
-done:
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* endpoints operations structure */
-static const struct usb_ep_ops langwell_ep_ops = {
-
- /* configure endpoint, making it usable */
- .enable = langwell_ep_enable,
-
- /* endpoint is no longer usable */
- .disable = langwell_ep_disable,
-
- /* allocate a request object to use with this endpoint */
- .alloc_request = langwell_alloc_request,
-
- /* free a request object */
- .free_request = langwell_free_request,
-
- /* queue (submits) an I/O requests to an endpoint */
- .queue = langwell_ep_queue,
-
- /* dequeue (cancels, unlinks) an I/O request from an endpoint */
- .dequeue = langwell_ep_dequeue,
-
- /* set the endpoint halt feature */
- .set_halt = langwell_ep_set_halt,
-
- /* set the halt feature and ignores clear requests */
- .set_wedge = langwell_ep_set_wedge,
-
- /* flush contents of a fifo */
- .fifo_flush = langwell_ep_fifo_flush,
-};
-
-
-/*-------------------------------------------------------------------------*/
-
-/* device controller usb_gadget_ops structure */
-
-/* returns the current frame number */
-static int langwell_get_frame(struct usb_gadget *_gadget)
-{
- struct langwell_udc *dev;
- u16 retval;
-
- if (!_gadget)
- return -ENODEV;
-
- dev = container_of(_gadget, struct langwell_udc, gadget);
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- retval = readl(&dev->op_regs->frindex) & FRINDEX_MASK;
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return retval;
-}
-
-
-/* enter or exit PHY low power state */
-static void langwell_phy_low_power(struct langwell_udc *dev, bool flag)
-{
- u32 devlc;
- u8 devlc_byte2;
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- devlc = readl(&dev->op_regs->devlc);
- dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc);
-
- if (flag)
- devlc |= LPM_PHCD;
- else
- devlc &= ~LPM_PHCD;
-
- /* FIXME: workaround for Langwell A1/A2/A3 sighting */
- devlc_byte2 = (devlc >> 16) & 0xff;
- writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2);
-
- devlc = readl(&dev->op_regs->devlc);
- dev_vdbg(&dev->pdev->dev,
- "%s PHY low power suspend, devlc = 0x%08x\n",
- flag ? "enter" : "exit", devlc);
-}
-
-
-/* tries to wake up the host connected to this gadget */
-static int langwell_wakeup(struct usb_gadget *_gadget)
-{
- struct langwell_udc *dev;
- u32 portsc1;
- unsigned long flags;
-
- if (!_gadget)
- return 0;
-
- dev = container_of(_gadget, struct langwell_udc, gadget);
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* remote wakeup feature not enabled by host */
- if (!dev->remote_wakeup) {
- dev_info(&dev->pdev->dev, "remote wakeup is disabled\n");
- return -ENOTSUPP;
- }
-
- spin_lock_irqsave(&dev->lock, flags);
-
- portsc1 = readl(&dev->op_regs->portsc1);
- if (!(portsc1 & PORTS_SUSP)) {
- spin_unlock_irqrestore(&dev->lock, flags);
- return 0;
- }
-
- /* LPM L1 to L0 or legacy remote wakeup */
- if (dev->lpm && dev->lpm_state == LPM_L1)
- dev_info(&dev->pdev->dev, "LPM L1 to L0 remote wakeup\n");
- else
- dev_info(&dev->pdev->dev, "device remote wakeup\n");
-
- /* exit PHY low power suspend */
- if (dev->pdev->device != 0x0829)
- langwell_phy_low_power(dev, 0);
-
- /* force port resume */
- portsc1 |= PORTS_FPR;
- writel(portsc1, &dev->op_regs->portsc1);
-
- spin_unlock_irqrestore(&dev->lock, flags);
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return 0;
-}
-
-
-/* notify controller that VBUS is powered or not */
-static int langwell_vbus_session(struct usb_gadget *_gadget, int is_active)
-{
- struct langwell_udc *dev;
- unsigned long flags;
- u32 usbcmd;
-
- if (!_gadget)
- return -ENODEV;
-
- dev = container_of(_gadget, struct langwell_udc, gadget);
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- spin_lock_irqsave(&dev->lock, flags);
- dev_vdbg(&dev->pdev->dev, "VBUS status: %s\n",
- is_active ? "on" : "off");
-
- dev->vbus_active = (is_active != 0);
- if (dev->driver && dev->softconnected && dev->vbus_active) {
- usbcmd = readl(&dev->op_regs->usbcmd);
- usbcmd |= CMD_RUNSTOP;
- writel(usbcmd, &dev->op_regs->usbcmd);
- } else {
- usbcmd = readl(&dev->op_regs->usbcmd);
- usbcmd &= ~CMD_RUNSTOP;
- writel(usbcmd, &dev->op_regs->usbcmd);
- }
-
- spin_unlock_irqrestore(&dev->lock, flags);
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return 0;
-}
-
-
-/* constrain controller's VBUS power usage */
-static int langwell_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
-{
- struct langwell_udc *dev;
-
- if (!_gadget)
- return -ENODEV;
-
- dev = container_of(_gadget, struct langwell_udc, gadget);
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if (dev->transceiver) {
- dev_vdbg(&dev->pdev->dev, "usb_phy_set_power\n");
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return usb_phy_set_power(dev->transceiver, mA);
- }
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return -ENOTSUPP;
-}
-
-
-/* D+ pullup, software-controlled connect/disconnect to USB host */
-static int langwell_pullup(struct usb_gadget *_gadget, int is_on)
-{
- struct langwell_udc *dev;
- u32 usbcmd;
- unsigned long flags;
-
- if (!_gadget)
- return -ENODEV;
-
- dev = container_of(_gadget, struct langwell_udc, gadget);
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- spin_lock_irqsave(&dev->lock, flags);
- dev->softconnected = (is_on != 0);
-
- if (dev->driver && dev->softconnected && dev->vbus_active) {
- usbcmd = readl(&dev->op_regs->usbcmd);
- usbcmd |= CMD_RUNSTOP;
- writel(usbcmd, &dev->op_regs->usbcmd);
- } else {
- usbcmd = readl(&dev->op_regs->usbcmd);
- usbcmd &= ~CMD_RUNSTOP;
- writel(usbcmd, &dev->op_regs->usbcmd);
- }
- spin_unlock_irqrestore(&dev->lock, flags);
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return 0;
-}
-
-static int langwell_start(struct usb_gadget *g,
- struct usb_gadget_driver *driver);
-
-static int langwell_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver);
-
-/* device controller usb_gadget_ops structure */
-static const struct usb_gadget_ops langwell_ops = {
-
- /* returns the current frame number */
- .get_frame = langwell_get_frame,
-
- /* tries to wake up the host connected to this gadget */
- .wakeup = langwell_wakeup,
-
- /* set the device selfpowered feature, always selfpowered */
- /* .set_selfpowered = langwell_set_selfpowered, */
-
- /* notify controller that VBUS is powered or not */
- .vbus_session = langwell_vbus_session,
-
- /* constrain controller's VBUS power usage */
- .vbus_draw = langwell_vbus_draw,
-
- /* D+ pullup, software-controlled connect/disconnect to USB host */
- .pullup = langwell_pullup,
-
- .udc_start = langwell_start,
- .udc_stop = langwell_stop,
-};
-
-
-/*-------------------------------------------------------------------------*/
-
-/* device controller operations */
-
-/* reset device controller */
-static int langwell_udc_reset(struct langwell_udc *dev)
-{
- u32 usbcmd, usbmode, devlc, endpointlistaddr;
- u8 devlc_byte0, devlc_byte2;
- unsigned long timeout;
-
- if (!dev)
- return -EINVAL;
-
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* set controller to stop state */
- usbcmd = readl(&dev->op_regs->usbcmd);
- usbcmd &= ~CMD_RUNSTOP;
- writel(usbcmd, &dev->op_regs->usbcmd);
-
- /* reset device controller */
- usbcmd = readl(&dev->op_regs->usbcmd);
- usbcmd |= CMD_RST;
- writel(usbcmd, &dev->op_regs->usbcmd);
-
- /* wait for reset to complete */
- timeout = jiffies + RESET_TIMEOUT;
- while (readl(&dev->op_regs->usbcmd) & CMD_RST) {
- if (time_after(jiffies, timeout)) {
- dev_err(&dev->pdev->dev, "device reset timeout\n");
- return -ETIMEDOUT;
- }
- cpu_relax();
- }
-
- /* set controller to device mode */
- usbmode = readl(&dev->op_regs->usbmode);
- usbmode |= MODE_DEVICE;
-
- /* turn setup lockout off, require setup tripwire in usbcmd */
- usbmode |= MODE_SLOM;
-
- writel(usbmode, &dev->op_regs->usbmode);
- usbmode = readl(&dev->op_regs->usbmode);
- dev_vdbg(&dev->pdev->dev, "usbmode=0x%08x\n", usbmode);
-
- /* Write-Clear setup status */
- writel(0, &dev->op_regs->usbsts);
-
- /* if support USB LPM, ACK all LPM token */
- if (dev->lpm) {
- devlc = readl(&dev->op_regs->devlc);
- dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc);
- /* FIXME: workaround for Langwell A1/A2/A3 sighting */
- devlc &= ~LPM_STL; /* don't STALL LPM token */
- devlc &= ~LPM_NYT_ACK; /* ACK LPM token */
- devlc_byte0 = devlc & 0xff;
- devlc_byte2 = (devlc >> 16) & 0xff;
- writeb(devlc_byte0, (u8 *)&dev->op_regs->devlc);
- writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2);
- devlc = readl(&dev->op_regs->devlc);
- dev_vdbg(&dev->pdev->dev,
- "ACK LPM token, devlc = 0x%08x\n", devlc);
- }
-
- /* fill endpointlistaddr register */
- endpointlistaddr = dev->ep_dqh_dma;
- endpointlistaddr &= ENDPOINTLISTADDR_MASK;
- writel(endpointlistaddr, &dev->op_regs->endpointlistaddr);
-
- dev_vdbg(&dev->pdev->dev,
- "dQH base (vir: %p, phy: 0x%08x), endpointlistaddr=0x%08x\n",
- dev->ep_dqh, endpointlistaddr,
- readl(&dev->op_regs->endpointlistaddr));
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return 0;
-}
-
-
-/* reinitialize device controller endpoints */
-static int eps_reinit(struct langwell_udc *dev)
-{
- struct langwell_ep *ep;
- char name[14];
- int i;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* initialize ep0 */
- ep = &dev->ep[0];
- ep->dev = dev;
- strncpy(ep->name, "ep0", sizeof(ep->name));
- ep->ep.name = ep->name;
- ep->ep.ops = &langwell_ep_ops;
- ep->stopped = 0;
- ep->ep.maxpacket = EP0_MAX_PKT_SIZE;
- ep->ep_num = 0;
- ep->desc = &langwell_ep0_desc;
- INIT_LIST_HEAD(&ep->queue);
-
- ep->ep_type = USB_ENDPOINT_XFER_CONTROL;
-
- /* initialize other endpoints */
- for (i = 2; i < dev->ep_max; i++) {
- ep = &dev->ep[i];
- if (i % 2)
- snprintf(name, sizeof(name), "ep%din", i / 2);
- else
- snprintf(name, sizeof(name), "ep%dout", i / 2);
- ep->dev = dev;
- strncpy(ep->name, name, sizeof(ep->name));
- ep->ep.name = ep->name;
-
- ep->ep.ops = &langwell_ep_ops;
- ep->stopped = 0;
- ep->ep.maxpacket = (unsigned short) ~0;
- ep->ep_num = i / 2;
-
- INIT_LIST_HEAD(&ep->queue);
- list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
- }
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return 0;
-}
-
-
-/* enable interrupt and set controller to run state */
-static void langwell_udc_start(struct langwell_udc *dev)
-{
- u32 usbintr, usbcmd;
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* enable interrupts */
- usbintr = INTR_ULPIE /* ULPI */
- | INTR_SLE /* suspend */
- /* | INTR_SRE SOF received */
- | INTR_URE /* USB reset */
- | INTR_AAE /* async advance */
- | INTR_SEE /* system error */
- | INTR_FRE /* frame list rollover */
- | INTR_PCE /* port change detect */
- | INTR_UEE /* USB error interrupt */
- | INTR_UE; /* USB interrupt */
- writel(usbintr, &dev->op_regs->usbintr);
-
- /* clear stopped bit */
- dev->stopped = 0;
-
- /* set controller to run */
- usbcmd = readl(&dev->op_regs->usbcmd);
- usbcmd |= CMD_RUNSTOP;
- writel(usbcmd, &dev->op_regs->usbcmd);
-
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* disable interrupt and set controller to stop state */
-static void langwell_udc_stop(struct langwell_udc *dev)
-{
- u32 usbcmd;
-
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* disable all interrupts */
- writel(0, &dev->op_regs->usbintr);
-
- /* set stopped bit */
- dev->stopped = 1;
-
- /* set controller to stop state */
- usbcmd = readl(&dev->op_regs->usbcmd);
- usbcmd &= ~CMD_RUNSTOP;
- writel(usbcmd, &dev->op_regs->usbcmd);
-
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* stop all USB activities */
-static void stop_activity(struct langwell_udc *dev)
-{
- struct langwell_ep *ep;
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- nuke(&dev->ep[0], -ESHUTDOWN);
-
- list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
- nuke(ep, -ESHUTDOWN);
- }
-
- /* report disconnect; the driver is already quiesced */
- if (dev->driver) {
- spin_unlock(&dev->lock);
- dev->driver->disconnect(&dev->gadget);
- spin_lock(&dev->lock);
- }
-
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* device "function" sysfs attribute file */
-static ssize_t show_function(struct device *_dev,
- struct device_attribute *attr, char *buf)
-{
- struct langwell_udc *dev = dev_get_drvdata(_dev);
-
- if (!dev->driver || !dev->driver->function
- || strlen(dev->driver->function) > PAGE_SIZE)
- return 0;
-
- return scnprintf(buf, PAGE_SIZE, "%s\n", dev->driver->function);
-}
-static DEVICE_ATTR(function, S_IRUGO, show_function, NULL);
-
-
-static inline enum usb_device_speed lpm_device_speed(u32 reg)
-{
- switch (LPM_PSPD(reg)) {
- case LPM_SPEED_HIGH:
- return USB_SPEED_HIGH;
- case LPM_SPEED_FULL:
- return USB_SPEED_FULL;
- case LPM_SPEED_LOW:
- return USB_SPEED_LOW;
- default:
- return USB_SPEED_UNKNOWN;
- }
-}
-
-/* device "langwell_udc" sysfs attribute file */
-static ssize_t show_langwell_udc(struct device *_dev,
- struct device_attribute *attr, char *buf)
-{
- struct langwell_udc *dev = dev_get_drvdata(_dev);
- struct langwell_request *req;
- struct langwell_ep *ep = NULL;
- char *next;
- unsigned size;
- unsigned t;
- unsigned i;
- unsigned long flags;
- u32 tmp_reg;
-
- next = buf;
- size = PAGE_SIZE;
- spin_lock_irqsave(&dev->lock, flags);
-
- /* driver basic information */
- t = scnprintf(next, size,
- DRIVER_DESC "\n"
- "%s version: %s\n"
- "Gadget driver: %s\n\n",
- driver_name, DRIVER_VERSION,
- dev->driver ? dev->driver->driver.name : "(none)");
- size -= t;
- next += t;
-
- /* device registers */
- tmp_reg = readl(&dev->op_regs->usbcmd);
- t = scnprintf(next, size,
- "USBCMD reg:\n"
- "SetupTW: %d\n"
- "Run/Stop: %s\n\n",
- (tmp_reg & CMD_SUTW) ? 1 : 0,
- (tmp_reg & CMD_RUNSTOP) ? "Run" : "Stop");
- size -= t;
- next += t;
-
- tmp_reg = readl(&dev->op_regs->usbsts);
- t = scnprintf(next, size,
- "USB Status Reg:\n"
- "Device Suspend: %d\n"
- "Reset Received: %d\n"
- "System Error: %s\n"
- "USB Error Interrupt: %s\n\n",
- (tmp_reg & STS_SLI) ? 1 : 0,
- (tmp_reg & STS_URI) ? 1 : 0,
- (tmp_reg & STS_SEI) ? "Error" : "No error",
- (tmp_reg & STS_UEI) ? "Error detected" : "No error");
- size -= t;
- next += t;
-
- tmp_reg = readl(&dev->op_regs->usbintr);
- t = scnprintf(next, size,
- "USB Intrrupt Enable Reg:\n"
- "Sleep Enable: %d\n"
- "SOF Received Enable: %d\n"
- "Reset Enable: %d\n"
- "System Error Enable: %d\n"
- "Port Change Dectected Enable: %d\n"
- "USB Error Intr Enable: %d\n"
- "USB Intr Enable: %d\n\n",
- (tmp_reg & INTR_SLE) ? 1 : 0,
- (tmp_reg & INTR_SRE) ? 1 : 0,
- (tmp_reg & INTR_URE) ? 1 : 0,
- (tmp_reg & INTR_SEE) ? 1 : 0,
- (tmp_reg & INTR_PCE) ? 1 : 0,
- (tmp_reg & INTR_UEE) ? 1 : 0,
- (tmp_reg & INTR_UE) ? 1 : 0);
- size -= t;
- next += t;
-
- tmp_reg = readl(&dev->op_regs->frindex);
- t = scnprintf(next, size,
- "USB Frame Index Reg:\n"
- "Frame Number is 0x%08x\n\n",
- (tmp_reg & FRINDEX_MASK));
- size -= t;
- next += t;
-
- tmp_reg = readl(&dev->op_regs->deviceaddr);
- t = scnprintf(next, size,
- "USB Device Address Reg:\n"
- "Device Addr is 0x%x\n\n",
- USBADR(tmp_reg));
- size -= t;
- next += t;
-
- tmp_reg = readl(&dev->op_regs->endpointlistaddr);
- t = scnprintf(next, size,
- "USB Endpoint List Address Reg:\n"
- "Endpoint List Pointer is 0x%x\n\n",
- EPBASE(tmp_reg));
- size -= t;
- next += t;
-
- tmp_reg = readl(&dev->op_regs->portsc1);
- t = scnprintf(next, size,
- "USB Port Status & Control Reg:\n"
- "Port Reset: %s\n"
- "Port Suspend Mode: %s\n"
- "Over-current Change: %s\n"
- "Port Enable/Disable Change: %s\n"
- "Port Enabled/Disabled: %s\n"
- "Current Connect Status: %s\n"
- "LPM Suspend Status: %s\n\n",
- (tmp_reg & PORTS_PR) ? "Reset" : "Not Reset",
- (tmp_reg & PORTS_SUSP) ? "Suspend " : "Not Suspend",
- (tmp_reg & PORTS_OCC) ? "Detected" : "No",
- (tmp_reg & PORTS_PEC) ? "Changed" : "Not Changed",
- (tmp_reg & PORTS_PE) ? "Enable" : "Not Correct",
- (tmp_reg & PORTS_CCS) ? "Attached" : "Not Attached",
- (tmp_reg & PORTS_SLP) ? "LPM L1" : "LPM L0");
- size -= t;
- next += t;
-
- tmp_reg = readl(&dev->op_regs->devlc);
- t = scnprintf(next, size,
- "Device LPM Control Reg:\n"
- "Parallel Transceiver : %d\n"
- "Serial Transceiver : %d\n"
- "Port Speed: %s\n"
- "Port Force Full Speed Connenct: %s\n"
- "PHY Low Power Suspend Clock: %s\n"
- "BmAttributes: %d\n\n",
- LPM_PTS(tmp_reg),
- (tmp_reg & LPM_STS) ? 1 : 0,
- usb_speed_string(lpm_device_speed(tmp_reg)),
- (tmp_reg & LPM_PFSC) ? "Force Full Speed" : "Not Force",
- (tmp_reg & LPM_PHCD) ? "Disabled" : "Enabled",
- LPM_BA(tmp_reg));
- size -= t;
- next += t;
-
- tmp_reg = readl(&dev->op_regs->usbmode);
- t = scnprintf(next, size,
- "USB Mode Reg:\n"
- "Controller Mode is : %s\n\n", ({
- char *s;
- switch (MODE_CM(tmp_reg)) {
- case MODE_IDLE:
- s = "Idle"; break;
- case MODE_DEVICE:
- s = "Device Controller"; break;
- case MODE_HOST:
- s = "Host Controller"; break;
- default:
- s = "None"; break;
- }
- s;
- }));
- size -= t;
- next += t;
-
- tmp_reg = readl(&dev->op_regs->endptsetupstat);
- t = scnprintf(next, size,
- "Endpoint Setup Status Reg:\n"
- "SETUP on ep 0x%04x\n\n",
- tmp_reg & SETUPSTAT_MASK);
- size -= t;
- next += t;
-
- for (i = 0; i < dev->ep_max / 2; i++) {
- tmp_reg = readl(&dev->op_regs->endptctrl[i]);
- t = scnprintf(next, size, "EP Ctrl Reg [%d]: 0x%08x\n",
- i, tmp_reg);
- size -= t;
- next += t;
- }
- tmp_reg = readl(&dev->op_regs->endptprime);
- t = scnprintf(next, size, "EP Prime Reg: 0x%08x\n\n", tmp_reg);
- size -= t;
- next += t;
-
- /* langwell_udc, langwell_ep, langwell_request structure information */
- ep = &dev->ep[0];
- t = scnprintf(next, size, "%s MaxPacketSize: 0x%x, ep_num: %d\n",
- ep->ep.name, ep->ep.maxpacket, ep->ep_num);
- size -= t;
- next += t;
-
- if (list_empty(&ep->queue)) {
- t = scnprintf(next, size, "its req queue is empty\n\n");
- size -= t;
- next += t;
- } else {
- list_for_each_entry(req, &ep->queue, queue) {
- t = scnprintf(next, size,
- "req %p actual 0x%x length 0x%x buf %p\n",
- &req->req, req->req.actual,
- req->req.length, req->req.buf);
- size -= t;
- next += t;
- }
- }
- /* other gadget->eplist ep */
- list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
- if (ep->desc) {
- t = scnprintf(next, size,
- "\n%s MaxPacketSize: 0x%x, "
- "ep_num: %d\n",
- ep->ep.name, ep->ep.maxpacket,
- ep->ep_num);
- size -= t;
- next += t;
-
- if (list_empty(&ep->queue)) {
- t = scnprintf(next, size,
- "its req queue is empty\n\n");
- size -= t;
- next += t;
- } else {
- list_for_each_entry(req, &ep->queue, queue) {
- t = scnprintf(next, size,
- "req %p actual 0x%x length "
- "0x%x buf %p\n",
- &req->req, req->req.actual,
- req->req.length, req->req.buf);
- size -= t;
- next += t;
- }
- }
- }
- }
-
- spin_unlock_irqrestore(&dev->lock, flags);
- return PAGE_SIZE - size;
-}
-static DEVICE_ATTR(langwell_udc, S_IRUGO, show_langwell_udc, NULL);
-
-
-/* device "remote_wakeup" sysfs attribute file */
-static ssize_t store_remote_wakeup(struct device *_dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct langwell_udc *dev = dev_get_drvdata(_dev);
- unsigned long flags;
- ssize_t rc = count;
-
- if (count > 2)
- return -EINVAL;
-
- if (count > 0 && buf[count-1] == '\n')
- ((char *) buf)[count-1] = 0;
-
- if (buf[0] != '1')
- return -EINVAL;
-
- /* force remote wakeup enabled in case gadget driver doesn't support */
- spin_lock_irqsave(&dev->lock, flags);
- dev->remote_wakeup = 1;
- dev->dev_status |= (1 << USB_DEVICE_REMOTE_WAKEUP);
- spin_unlock_irqrestore(&dev->lock, flags);
-
- langwell_wakeup(&dev->gadget);
-
- return rc;
-}
-static DEVICE_ATTR(remote_wakeup, S_IWUSR, NULL, store_remote_wakeup);
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * when a driver is successfully registered, it will receive
- * control requests including set_configuration(), which enables
- * non-control requests. then usb traffic follows until a
- * disconnect is reported. then a host may connect again, or
- * the driver might get unbound.
- */
-
-static int langwell_start(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
-{
- struct langwell_udc *dev = gadget_to_langwell(g);
- unsigned long flags;
- int retval;
-
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- spin_lock_irqsave(&dev->lock, flags);
-
- /* hook up the driver ... */
- driver->driver.bus = NULL;
- dev->driver = driver;
- dev->gadget.dev.driver = &driver->driver;
-
- spin_unlock_irqrestore(&dev->lock, flags);
-
- retval = device_create_file(&dev->pdev->dev, &dev_attr_function);
- if (retval)
- goto err;
-
- dev->usb_state = USB_STATE_ATTACHED;
- dev->ep0_state = WAIT_FOR_SETUP;
- dev->ep0_dir = USB_DIR_OUT;
-
- /* enable interrupt and set controller to run state */
- if (dev->got_irq)
- langwell_udc_start(dev);
-
- dev_vdbg(&dev->pdev->dev,
- "After langwell_udc_start(), print all registers:\n");
- print_all_registers(dev);
-
- dev_info(&dev->pdev->dev, "register driver: %s\n",
- driver->driver.name);
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-
- return 0;
-
-err:
- dev->gadget.dev.driver = NULL;
- dev->driver = NULL;
-
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-
- return retval;
-}
-
-/* unregister gadget driver */
-static int langwell_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
-{
- struct langwell_udc *dev = gadget_to_langwell(g);
- unsigned long flags;
-
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* exit PHY low power suspend */
- if (dev->pdev->device != 0x0829)
- langwell_phy_low_power(dev, 0);
-
- /* unbind OTG transceiver */
- if (dev->transceiver)
- (void)otg_set_peripheral(dev->transceiver->otg, 0);
-
- /* disable interrupt and set controller to stop state */
- langwell_udc_stop(dev);
-
- dev->usb_state = USB_STATE_ATTACHED;
- dev->ep0_state = WAIT_FOR_SETUP;
- dev->ep0_dir = USB_DIR_OUT;
-
- spin_lock_irqsave(&dev->lock, flags);
-
- /* stop all usb activities */
- dev->gadget.speed = USB_SPEED_UNKNOWN;
- dev->gadget.dev.driver = NULL;
- dev->driver = NULL;
- stop_activity(dev);
- spin_unlock_irqrestore(&dev->lock, flags);
-
- device_remove_file(&dev->pdev->dev, &dev_attr_function);
-
- dev_info(&dev->pdev->dev, "unregistered driver '%s'\n",
- driver->driver.name);
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * setup tripwire is used as a semaphore to ensure that the setup data
- * payload is extracted from a dQH without being corrupted
- */
-static void setup_tripwire(struct langwell_udc *dev)
-{
- u32 usbcmd,
- endptsetupstat;
- unsigned long timeout;
- struct langwell_dqh *dqh;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* ep0 OUT dQH */
- dqh = &dev->ep_dqh[EP_DIR_OUT];
-
- /* Write-Clear endptsetupstat */
- endptsetupstat = readl(&dev->op_regs->endptsetupstat);
- writel(endptsetupstat, &dev->op_regs->endptsetupstat);
-
- /* wait until endptsetupstat is cleared */
- timeout = jiffies + SETUPSTAT_TIMEOUT;
- while (readl(&dev->op_regs->endptsetupstat)) {
- if (time_after(jiffies, timeout)) {
- dev_err(&dev->pdev->dev, "setup_tripwire timeout\n");
- break;
- }
- cpu_relax();
- }
-
- /* while a hazard exists when setup packet arrives */
- do {
- /* set setup tripwire bit */
- usbcmd = readl(&dev->op_regs->usbcmd);
- writel(usbcmd | CMD_SUTW, &dev->op_regs->usbcmd);
-
- /* copy the setup packet to local buffer */
- memcpy(&dev->local_setup_buff, &dqh->dqh_setup, 8);
- } while (!(readl(&dev->op_regs->usbcmd) & CMD_SUTW));
-
- /* Write-Clear setup tripwire bit */
- usbcmd = readl(&dev->op_regs->usbcmd);
- writel(usbcmd & ~CMD_SUTW, &dev->op_regs->usbcmd);
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* protocol ep0 stall, will automatically be cleared on new transaction */
-static void ep0_stall(struct langwell_udc *dev)
-{
- u32 endptctrl;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* set TX and RX to stall */
- endptctrl = readl(&dev->op_regs->endptctrl[0]);
- endptctrl |= EPCTRL_TXS | EPCTRL_RXS;
- writel(endptctrl, &dev->op_regs->endptctrl[0]);
-
- /* update ep0 state */
- dev->ep0_state = WAIT_FOR_SETUP;
- dev->ep0_dir = USB_DIR_OUT;
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* PRIME a status phase for ep0 */
-static int prime_status_phase(struct langwell_udc *dev, int dir)
-{
- struct langwell_request *req;
- struct langwell_ep *ep;
- int status = 0;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if (dir == EP_DIR_IN)
- dev->ep0_dir = USB_DIR_IN;
- else
- dev->ep0_dir = USB_DIR_OUT;
-
- ep = &dev->ep[0];
- dev->ep0_state = WAIT_FOR_OUT_STATUS;
-
- req = dev->status_req;
-
- req->ep = ep;
- req->req.length = 0;
- req->req.status = -EINPROGRESS;
- req->req.actual = 0;
- req->req.complete = NULL;
- req->dtd_count = 0;
-
- if (!req_to_dtd(req))
- status = queue_dtd(ep, req);
- else
- return -ENOMEM;
-
- if (status)
- dev_err(&dev->pdev->dev, "can't queue ep0 status request\n");
-
- list_add_tail(&req->queue, &ep->queue);
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return status;
-}
-
-
-/* SET_ADDRESS request routine */
-static void set_address(struct langwell_udc *dev, u16 value,
- u16 index, u16 length)
-{
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* save the new address to device struct */
- dev->dev_addr = (u8) value;
- dev_vdbg(&dev->pdev->dev, "dev->dev_addr = %d\n", dev->dev_addr);
-
- /* update usb state */
- dev->usb_state = USB_STATE_ADDRESS;
-
- /* STATUS phase */
- if (prime_status_phase(dev, EP_DIR_IN))
- ep0_stall(dev);
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* return endpoint by windex */
-static struct langwell_ep *get_ep_by_windex(struct langwell_udc *dev,
- u16 wIndex)
-{
- struct langwell_ep *ep;
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
- return &dev->ep[0];
-
- list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
- u8 bEndpointAddress;
- if (!ep->desc)
- continue;
-
- bEndpointAddress = ep->desc->bEndpointAddress;
- if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
- continue;
-
- if ((wIndex & USB_ENDPOINT_NUMBER_MASK)
- == (bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))
- return ep;
- }
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return NULL;
-}
-
-
-/* return whether endpoint is stalled, 0: not stalled; 1: stalled */
-static int ep_is_stall(struct langwell_ep *ep)
-{
- struct langwell_udc *dev = ep->dev;
- u32 endptctrl;
- int retval;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- endptctrl = readl(&dev->op_regs->endptctrl[ep->ep_num]);
- if (is_in(ep))
- retval = endptctrl & EPCTRL_TXS ? 1 : 0;
- else
- retval = endptctrl & EPCTRL_RXS ? 1 : 0;
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return retval;
-}
-
-
-/* GET_STATUS request routine */
-static void get_status(struct langwell_udc *dev, u8 request_type, u16 value,
- u16 index, u16 length)
-{
- struct langwell_request *req;
- struct langwell_ep *ep;
- u16 status_data = 0; /* 16 bits cpu view status data */
- int status = 0;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- ep = &dev->ep[0];
-
- if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
- /* get device status */
- status_data = dev->dev_status;
- } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) {
- /* get interface status */
- status_data = 0;
- } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) {
- /* get endpoint status */
- struct langwell_ep *epn;
- epn = get_ep_by_windex(dev, index);
- /* stall if endpoint doesn't exist */
- if (!epn)
- goto stall;
-
- status_data = ep_is_stall(epn) << USB_ENDPOINT_HALT;
- }
-
- dev_dbg(&dev->pdev->dev, "get status data: 0x%04x\n", status_data);
-
- dev->ep0_dir = USB_DIR_IN;
-
- /* borrow the per device status_req */
- req = dev->status_req;
-
- /* fill in the reqest structure */
- *((u16 *) req->req.buf) = cpu_to_le16(status_data);
- req->ep = ep;
- req->req.length = 2;
- req->req.status = -EINPROGRESS;
- req->req.actual = 0;
- req->req.complete = NULL;
- req->dtd_count = 0;
-
- /* prime the data phase */
- if (!req_to_dtd(req))
- status = queue_dtd(ep, req);
- else /* no mem */
- goto stall;
-
- if (status) {
- dev_err(&dev->pdev->dev,
- "response error on GET_STATUS request\n");
- goto stall;
- }
-
- list_add_tail(&req->queue, &ep->queue);
- dev->ep0_state = DATA_STATE_XMIT;
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return;
-stall:
- ep0_stall(dev);
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* setup packet interrupt handler */
-static void handle_setup_packet(struct langwell_udc *dev,
- struct usb_ctrlrequest *setup)
-{
- u16 wValue = le16_to_cpu(setup->wValue);
- u16 wIndex = le16_to_cpu(setup->wIndex);
- u16 wLength = le16_to_cpu(setup->wLength);
- u32 portsc1;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* ep0 fifo flush */
- nuke(&dev->ep[0], -ESHUTDOWN);
-
- dev_dbg(&dev->pdev->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
- setup->bRequestType, setup->bRequest,
- wValue, wIndex, wLength);
-
- /* RNDIS gadget delegate */
- if ((setup->bRequestType == 0x21) && (setup->bRequest == 0x00)) {
- /* USB_CDC_SEND_ENCAPSULATED_COMMAND */
- goto delegate;
- }
-
- /* USB_CDC_GET_ENCAPSULATED_RESPONSE */
- if ((setup->bRequestType == 0xa1) && (setup->bRequest == 0x01)) {
- /* USB_CDC_GET_ENCAPSULATED_RESPONSE */
- goto delegate;
- }
-
- /* We process some stardard setup requests here */
- switch (setup->bRequest) {
- case USB_REQ_GET_STATUS:
- dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_GET_STATUS\n");
- /* get status, DATA and STATUS phase */
- if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
- != (USB_DIR_IN | USB_TYPE_STANDARD))
- break;
- get_status(dev, setup->bRequestType, wValue, wIndex, wLength);
- goto end;
-
- case USB_REQ_SET_ADDRESS:
- dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_SET_ADDRESS\n");
- /* STATUS phase */
- if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD
- | USB_RECIP_DEVICE))
- break;
- set_address(dev, wValue, wIndex, wLength);
- goto end;
-
- case USB_REQ_CLEAR_FEATURE:
- case USB_REQ_SET_FEATURE:
- /* STATUS phase */
- {
- int rc = -EOPNOTSUPP;
- if (setup->bRequest == USB_REQ_SET_FEATURE)
- dev_dbg(&dev->pdev->dev,
- "SETUP: USB_REQ_SET_FEATURE\n");
- else if (setup->bRequest == USB_REQ_CLEAR_FEATURE)
- dev_dbg(&dev->pdev->dev,
- "SETUP: USB_REQ_CLEAR_FEATURE\n");
-
- if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK))
- == (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) {
- struct langwell_ep *epn;
- epn = get_ep_by_windex(dev, wIndex);
- /* stall if endpoint doesn't exist */
- if (!epn) {
- ep0_stall(dev);
- goto end;
- }
-
- if (wValue != 0 || wLength != 0
- || epn->ep_num > dev->ep_max)
- break;
-
- spin_unlock(&dev->lock);
- rc = langwell_ep_set_halt(&epn->ep,
- (setup->bRequest == USB_REQ_SET_FEATURE)
- ? 1 : 0);
- spin_lock(&dev->lock);
-
- } else if ((setup->bRequestType & (USB_RECIP_MASK
- | USB_TYPE_MASK)) == (USB_RECIP_DEVICE
- | USB_TYPE_STANDARD)) {
- rc = 0;
- switch (wValue) {
- case USB_DEVICE_REMOTE_WAKEUP:
- if (setup->bRequest == USB_REQ_SET_FEATURE) {
- dev->remote_wakeup = 1;
- dev->dev_status |= (1 << wValue);
- } else {
- dev->remote_wakeup = 0;
- dev->dev_status &= ~(1 << wValue);
- }
- break;
- case USB_DEVICE_TEST_MODE:
- dev_dbg(&dev->pdev->dev, "SETUP: TEST MODE\n");
- if ((wIndex & 0xff) ||
- (dev->gadget.speed != USB_SPEED_HIGH))
- ep0_stall(dev);
-
- switch (wIndex >> 8) {
- case TEST_J:
- case TEST_K:
- case TEST_SE0_NAK:
- case TEST_PACKET:
- case TEST_FORCE_EN:
- if (prime_status_phase(dev, EP_DIR_IN))
- ep0_stall(dev);
- portsc1 = readl(&dev->op_regs->portsc1);
- portsc1 |= (wIndex & 0xf00) << 8;
- writel(portsc1, &dev->op_regs->portsc1);
- goto end;
- default:
- rc = -EOPNOTSUPP;
- }
- break;
- default:
- rc = -EOPNOTSUPP;
- break;
- }
-
- if (!gadget_is_otg(&dev->gadget))
- break;
- else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE)
- dev->gadget.b_hnp_enable = 1;
- else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT)
- dev->gadget.a_hnp_support = 1;
- else if (setup->bRequest ==
- USB_DEVICE_A_ALT_HNP_SUPPORT)
- dev->gadget.a_alt_hnp_support = 1;
- else
- break;
- } else
- break;
-
- if (rc == 0) {
- if (prime_status_phase(dev, EP_DIR_IN))
- ep0_stall(dev);
- }
- goto end;
- }
-
- case USB_REQ_GET_DESCRIPTOR:
- dev_dbg(&dev->pdev->dev,
- "SETUP: USB_REQ_GET_DESCRIPTOR\n");
- goto delegate;
-
- case USB_REQ_SET_DESCRIPTOR:
- dev_dbg(&dev->pdev->dev,
- "SETUP: USB_REQ_SET_DESCRIPTOR unsupported\n");
- goto delegate;
-
- case USB_REQ_GET_CONFIGURATION:
- dev_dbg(&dev->pdev->dev,
- "SETUP: USB_REQ_GET_CONFIGURATION\n");
- goto delegate;
-
- case USB_REQ_SET_CONFIGURATION:
- dev_dbg(&dev->pdev->dev,
- "SETUP: USB_REQ_SET_CONFIGURATION\n");
- goto delegate;
-
- case USB_REQ_GET_INTERFACE:
- dev_dbg(&dev->pdev->dev,
- "SETUP: USB_REQ_GET_INTERFACE\n");
- goto delegate;
-
- case USB_REQ_SET_INTERFACE:
- dev_dbg(&dev->pdev->dev,
- "SETUP: USB_REQ_SET_INTERFACE\n");
- goto delegate;
-
- case USB_REQ_SYNCH_FRAME:
- dev_dbg(&dev->pdev->dev,
- "SETUP: USB_REQ_SYNCH_FRAME unsupported\n");
- goto delegate;
-
- default:
- /* delegate USB standard requests to the gadget driver */
- goto delegate;
-delegate:
- /* USB requests handled by gadget */
- if (wLength) {
- /* DATA phase from gadget, STATUS phase from udc */
- dev->ep0_dir = (setup->bRequestType & USB_DIR_IN)
- ? USB_DIR_IN : USB_DIR_OUT;
- dev_vdbg(&dev->pdev->dev,
- "dev->ep0_dir = 0x%x, wLength = %d\n",
- dev->ep0_dir, wLength);
- spin_unlock(&dev->lock);
- if (dev->driver->setup(&dev->gadget,
- &dev->local_setup_buff) < 0)
- ep0_stall(dev);
- spin_lock(&dev->lock);
- dev->ep0_state = (setup->bRequestType & USB_DIR_IN)
- ? DATA_STATE_XMIT : DATA_STATE_RECV;
- } else {
- /* no DATA phase, IN STATUS phase from gadget */
- dev->ep0_dir = USB_DIR_IN;
- dev_vdbg(&dev->pdev->dev,
- "dev->ep0_dir = 0x%x, wLength = %d\n",
- dev->ep0_dir, wLength);
- spin_unlock(&dev->lock);
- if (dev->driver->setup(&dev->gadget,
- &dev->local_setup_buff) < 0)
- ep0_stall(dev);
- spin_lock(&dev->lock);
- dev->ep0_state = WAIT_FOR_OUT_STATUS;
- }
- break;
- }
-end:
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* transfer completion, process endpoint request and free the completed dTDs
- * for this request
- */
-static int process_ep_req(struct langwell_udc *dev, int index,
- struct langwell_request *curr_req)
-{
- struct langwell_dtd *curr_dtd;
- struct langwell_dqh *curr_dqh;
- int td_complete, actual, remaining_length;
- int i, dir;
- u8 dtd_status = 0;
- int retval = 0;
-
- curr_dqh = &dev->ep_dqh[index];
- dir = index % 2;
-
- curr_dtd = curr_req->head;
- td_complete = 0;
- actual = curr_req->req.length;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- for (i = 0; i < curr_req->dtd_count; i++) {
-
- /* command execution states by dTD */
- dtd_status = curr_dtd->dtd_status;
-
- barrier();
- remaining_length = le16_to_cpu(curr_dtd->dtd_total);
- actual -= remaining_length;
-
- if (!dtd_status) {
- /* transfers completed successfully */
- if (!remaining_length) {
- td_complete++;
- dev_vdbg(&dev->pdev->dev,
- "dTD transmitted successfully\n");
- } else {
- if (dir) {
- dev_vdbg(&dev->pdev->dev,
- "TX dTD remains data\n");
- retval = -EPROTO;
- break;
-
- } else {
- td_complete++;
- break;
- }
- }
- } else {
- /* transfers completed with errors */
- if (dtd_status & DTD_STS_ACTIVE) {
- dev_dbg(&dev->pdev->dev,
- "dTD status ACTIVE dQH[%d]\n", index);
- retval = 1;
- return retval;
- } else if (dtd_status & DTD_STS_HALTED) {
- dev_err(&dev->pdev->dev,
- "dTD error %08x dQH[%d]\n",
- dtd_status, index);
- /* clear the errors and halt condition */
- curr_dqh->dtd_status = 0;
- retval = -EPIPE;
- break;
- } else if (dtd_status & DTD_STS_DBE) {
- dev_dbg(&dev->pdev->dev,
- "data buffer (overflow) error\n");
- retval = -EPROTO;
- break;
- } else if (dtd_status & DTD_STS_TRE) {
- dev_dbg(&dev->pdev->dev,
- "transaction(ISO) error\n");
- retval = -EILSEQ;
- break;
- } else
- dev_err(&dev->pdev->dev,
- "unknown error (0x%x)!\n",
- dtd_status);
- }
-
- if (i != curr_req->dtd_count - 1)
- curr_dtd = (struct langwell_dtd *)
- curr_dtd->next_dtd_virt;
- }
-
- if (retval)
- return retval;
-
- curr_req->req.actual = actual;
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return 0;
-}
-
-
-/* complete DATA or STATUS phase of ep0 prime status phase if needed */
-static void ep0_req_complete(struct langwell_udc *dev,
- struct langwell_ep *ep0, struct langwell_request *req)
-{
- u32 new_addr;
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if (dev->usb_state == USB_STATE_ADDRESS) {
- /* set the new address */
- new_addr = (u32)dev->dev_addr;
- writel(new_addr << USBADR_SHIFT, &dev->op_regs->deviceaddr);
-
- new_addr = USBADR(readl(&dev->op_regs->deviceaddr));
- dev_vdbg(&dev->pdev->dev, "new_addr = %d\n", new_addr);
- }
-
- done(ep0, req, 0);
-
- switch (dev->ep0_state) {
- case DATA_STATE_XMIT:
- /* receive status phase */
- if (prime_status_phase(dev, EP_DIR_OUT))
- ep0_stall(dev);
- break;
- case DATA_STATE_RECV:
- /* send status phase */
- if (prime_status_phase(dev, EP_DIR_IN))
- ep0_stall(dev);
- break;
- case WAIT_FOR_OUT_STATUS:
- dev->ep0_state = WAIT_FOR_SETUP;
- break;
- case WAIT_FOR_SETUP:
- dev_err(&dev->pdev->dev, "unexpect ep0 packets\n");
- break;
- default:
- ep0_stall(dev);
- break;
- }
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* USB transfer completion interrupt */
-static void handle_trans_complete(struct langwell_udc *dev)
-{
- u32 complete_bits;
- int i, ep_num, dir, bit_mask, status;
- struct langwell_ep *epn;
- struct langwell_request *curr_req, *temp_req;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- complete_bits = readl(&dev->op_regs->endptcomplete);
- dev_vdbg(&dev->pdev->dev, "endptcomplete register: 0x%08x\n",
- complete_bits);
-
- /* Write-Clear the bits in endptcomplete register */
- writel(complete_bits, &dev->op_regs->endptcomplete);
-
- if (!complete_bits) {
- dev_dbg(&dev->pdev->dev, "complete_bits = 0\n");
- goto done;
- }
-
- for (i = 0; i < dev->ep_max; i++) {
- ep_num = i / 2;
- dir = i % 2;
-
- bit_mask = 1 << (ep_num + 16 * dir);
-
- if (!(complete_bits & bit_mask))
- continue;
-
- /* ep0 */
- if (i == 1)
- epn = &dev->ep[0];
- else
- epn = &dev->ep[i];
-
- if (epn->name == NULL) {
- dev_warn(&dev->pdev->dev, "invalid endpoint\n");
- continue;
- }
-
- if (i < 2)
- /* ep0 in and out */
- dev_dbg(&dev->pdev->dev, "%s-%s transfer completed\n",
- epn->name,
- is_in(epn) ? "in" : "out");
- else
- dev_dbg(&dev->pdev->dev, "%s transfer completed\n",
- epn->name);
-
- /* process the req queue until an uncomplete request */
- list_for_each_entry_safe(curr_req, temp_req,
- &epn->queue, queue) {
- status = process_ep_req(dev, i, curr_req);
- dev_vdbg(&dev->pdev->dev, "%s req status: %d\n",
- epn->name, status);
-
- if (status)
- break;
-
- /* write back status to req */
- curr_req->req.status = status;
-
- /* ep0 request completion */
- if (ep_num == 0) {
- ep0_req_complete(dev, epn, curr_req);
- break;
- } else {
- done(epn, curr_req, status);
- }
- }
- }
-done:
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-/* port change detect interrupt handler */
-static void handle_port_change(struct langwell_udc *dev)
-{
- u32 portsc1, devlc;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if (dev->bus_reset)
- dev->bus_reset = 0;
-
- portsc1 = readl(&dev->op_regs->portsc1);
- devlc = readl(&dev->op_regs->devlc);
- dev_vdbg(&dev->pdev->dev, "portsc1 = 0x%08x, devlc = 0x%08x\n",
- portsc1, devlc);
-
- /* bus reset is finished */
- if (!(portsc1 & PORTS_PR)) {
- /* get the speed */
- dev->gadget.speed = lpm_device_speed(devlc);
- dev_vdbg(&dev->pdev->dev, "dev->gadget.speed = %d\n",
- dev->gadget.speed);
- }
-
- /* LPM L0 to L1 */
- if (dev->lpm && dev->lpm_state == LPM_L0)
- if (portsc1 & PORTS_SUSP && portsc1 & PORTS_SLP) {
- dev_info(&dev->pdev->dev, "LPM L0 to L1\n");
- dev->lpm_state = LPM_L1;
- }
-
- /* LPM L1 to L0, force resume or remote wakeup finished */
- if (dev->lpm && dev->lpm_state == LPM_L1)
- if (!(portsc1 & PORTS_SUSP)) {
- dev_info(&dev->pdev->dev, "LPM L1 to L0\n");
- dev->lpm_state = LPM_L0;
- }
-
- /* update USB state */
- if (!dev->resume_state)
- dev->usb_state = USB_STATE_DEFAULT;
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* USB reset interrupt handler */
-static void handle_usb_reset(struct langwell_udc *dev)
-{
- u32 deviceaddr,
- endptsetupstat,
- endptcomplete;
- unsigned long timeout;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* Write-Clear the device address */
- deviceaddr = readl(&dev->op_regs->deviceaddr);
- writel(deviceaddr & ~USBADR_MASK, &dev->op_regs->deviceaddr);
-
- dev->dev_addr = 0;
-
- /* clear usb state */
- dev->resume_state = 0;
-
- /* LPM L1 to L0, reset */
- if (dev->lpm)
- dev->lpm_state = LPM_L0;
-
- dev->ep0_dir = USB_DIR_OUT;
- dev->ep0_state = WAIT_FOR_SETUP;
-
- /* remote wakeup reset to 0 when the device is reset */
- dev->remote_wakeup = 0;
- dev->dev_status = 1 << USB_DEVICE_SELF_POWERED;
- dev->gadget.b_hnp_enable = 0;
- dev->gadget.a_hnp_support = 0;
- dev->gadget.a_alt_hnp_support = 0;
-
- /* Write-Clear all the setup token semaphores */
- endptsetupstat = readl(&dev->op_regs->endptsetupstat);
- writel(endptsetupstat, &dev->op_regs->endptsetupstat);
-
- /* Write-Clear all the endpoint complete status bits */
- endptcomplete = readl(&dev->op_regs->endptcomplete);
- writel(endptcomplete, &dev->op_regs->endptcomplete);
-
- /* wait until all endptprime bits cleared */
- timeout = jiffies + PRIME_TIMEOUT;
- while (readl(&dev->op_regs->endptprime)) {
- if (time_after(jiffies, timeout)) {
- dev_err(&dev->pdev->dev, "USB reset timeout\n");
- break;
- }
- cpu_relax();
- }
-
- /* write 1s to endptflush register to clear any primed buffers */
- writel((u32) ~0, &dev->op_regs->endptflush);
-
- if (readl(&dev->op_regs->portsc1) & PORTS_PR) {
- dev_vdbg(&dev->pdev->dev, "USB bus reset\n");
- /* bus is reseting */
- dev->bus_reset = 1;
-
- /* reset all the queues, stop all USB activities */
- stop_activity(dev);
- dev->usb_state = USB_STATE_DEFAULT;
- } else {
- dev_vdbg(&dev->pdev->dev, "device controller reset\n");
- /* controller reset */
- langwell_udc_reset(dev);
-
- /* reset all the queues, stop all USB activities */
- stop_activity(dev);
-
- /* reset ep0 dQH and endptctrl */
- ep0_reset(dev);
-
- /* enable interrupt and set controller to run state */
- langwell_udc_start(dev);
-
- dev->usb_state = USB_STATE_ATTACHED;
- }
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* USB bus suspend/resume interrupt */
-static void handle_bus_suspend(struct langwell_udc *dev)
-{
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- dev->resume_state = dev->usb_state;
- dev->usb_state = USB_STATE_SUSPENDED;
-
- /* report suspend to the driver */
- if (dev->driver) {
- if (dev->driver->suspend) {
- spin_unlock(&dev->lock);
- dev->driver->suspend(&dev->gadget);
- spin_lock(&dev->lock);
- dev_dbg(&dev->pdev->dev, "suspend %s\n",
- dev->driver->driver.name);
- }
- }
-
- /* enter PHY low power suspend */
- if (dev->pdev->device != 0x0829)
- langwell_phy_low_power(dev, 0);
-
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-static void handle_bus_resume(struct langwell_udc *dev)
-{
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- dev->usb_state = dev->resume_state;
- dev->resume_state = 0;
-
- /* exit PHY low power suspend */
- if (dev->pdev->device != 0x0829)
- langwell_phy_low_power(dev, 0);
-
- /* report resume to the driver */
- if (dev->driver) {
- if (dev->driver->resume) {
- spin_unlock(&dev->lock);
- dev->driver->resume(&dev->gadget);
- spin_lock(&dev->lock);
- dev_dbg(&dev->pdev->dev, "resume %s\n",
- dev->driver->driver.name);
- }
- }
-
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* USB device controller interrupt handler */
-static irqreturn_t langwell_irq(int irq, void *_dev)
-{
- struct langwell_udc *dev = _dev;
- u32 usbsts,
- usbintr,
- irq_sts,
- portsc1;
-
- dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- if (dev->stopped) {
- dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n");
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return IRQ_NONE;
- }
-
- spin_lock(&dev->lock);
-
- /* USB status */
- usbsts = readl(&dev->op_regs->usbsts);
-
- /* USB interrupt enable */
- usbintr = readl(&dev->op_regs->usbintr);
-
- irq_sts = usbsts & usbintr;
- dev_vdbg(&dev->pdev->dev,
- "usbsts = 0x%08x, usbintr = 0x%08x, irq_sts = 0x%08x\n",
- usbsts, usbintr, irq_sts);
-
- if (!irq_sts) {
- dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n");
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- spin_unlock(&dev->lock);
- return IRQ_NONE;
- }
-
- /* Write-Clear interrupt status bits */
- writel(irq_sts, &dev->op_regs->usbsts);
-
- /* resume from suspend */
- portsc1 = readl(&dev->op_regs->portsc1);
- if (dev->usb_state == USB_STATE_SUSPENDED)
- if (!(portsc1 & PORTS_SUSP))
- handle_bus_resume(dev);
-
- /* USB interrupt */
- if (irq_sts & STS_UI) {
- dev_vdbg(&dev->pdev->dev, "USB interrupt\n");
-
- /* setup packet received from ep0 */
- if (readl(&dev->op_regs->endptsetupstat)
- & EP0SETUPSTAT_MASK) {
- dev_vdbg(&dev->pdev->dev,
- "USB SETUP packet received interrupt\n");
- /* setup tripwire semaphone */
- setup_tripwire(dev);
- handle_setup_packet(dev, &dev->local_setup_buff);
- }
-
- /* USB transfer completion */
- if (readl(&dev->op_regs->endptcomplete)) {
- dev_vdbg(&dev->pdev->dev,
- "USB transfer completion interrupt\n");
- handle_trans_complete(dev);
- }
- }
-
- /* SOF received interrupt (for ISO transfer) */
- if (irq_sts & STS_SRI) {
- /* FIXME */
- /* dev_vdbg(&dev->pdev->dev, "SOF received interrupt\n"); */
- }
-
- /* port change detect interrupt */
- if (irq_sts & STS_PCI) {
- dev_vdbg(&dev->pdev->dev, "port change detect interrupt\n");
- handle_port_change(dev);
- }
-
- /* suspend interrupt */
- if (irq_sts & STS_SLI) {
- dev_vdbg(&dev->pdev->dev, "suspend interrupt\n");
- handle_bus_suspend(dev);
- }
-
- /* USB reset interrupt */
- if (irq_sts & STS_URI) {
- dev_vdbg(&dev->pdev->dev, "USB reset interrupt\n");
- handle_usb_reset(dev);
- }
-
- /* USB error or system error interrupt */
- if (irq_sts & (STS_UEI | STS_SEI)) {
- /* FIXME */
- dev_warn(&dev->pdev->dev, "error IRQ, irq_sts: %x\n", irq_sts);
- }
-
- spin_unlock(&dev->lock);
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return IRQ_HANDLED;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* release device structure */
-static void gadget_release(struct device *_dev)
-{
- struct langwell_udc *dev = dev_get_drvdata(_dev);
-
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- complete(dev->done);
-
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- kfree(dev);
-}
-
-
-/* enable SRAM caching if SRAM detected */
-static void sram_init(struct langwell_udc *dev)
-{
- struct pci_dev *pdev = dev->pdev;
-
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- dev->sram_addr = pci_resource_start(pdev, 1);
- dev->sram_size = pci_resource_len(pdev, 1);
- dev_info(&dev->pdev->dev, "Found private SRAM at %x size:%x\n",
- dev->sram_addr, dev->sram_size);
- dev->got_sram = 1;
-
- if (pci_request_region(pdev, 1, kobject_name(&pdev->dev.kobj))) {
- dev_warn(&dev->pdev->dev, "SRAM request failed\n");
- dev->got_sram = 0;
- } else if (!dma_declare_coherent_memory(&pdev->dev, dev->sram_addr,
- dev->sram_addr, dev->sram_size, DMA_MEMORY_MAP)) {
- dev_warn(&dev->pdev->dev, "SRAM DMA declare failed\n");
- pci_release_region(pdev, 1);
- dev->got_sram = 0;
- }
-
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* release SRAM caching */
-static void sram_deinit(struct langwell_udc *dev)
-{
- struct pci_dev *pdev = dev->pdev;
-
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- dma_release_declared_memory(&pdev->dev);
- pci_release_region(pdev, 1);
-
- dev->got_sram = 0;
-
- dev_info(&dev->pdev->dev, "release SRAM caching\n");
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-
-/* tear down the binding between this driver and the pci device */
-static void langwell_udc_remove(struct pci_dev *pdev)
-{
- struct langwell_udc *dev = pci_get_drvdata(pdev);
-
- DECLARE_COMPLETION(done);
-
- BUG_ON(dev->driver);
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- dev->done = &done;
-
- /* free dTD dma_pool and dQH */
- if (dev->dtd_pool)
- dma_pool_destroy(dev->dtd_pool);
-
- if (dev->ep_dqh)
- dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
- dev->ep_dqh, dev->ep_dqh_dma);
-
- /* release SRAM caching */
- if (dev->has_sram && dev->got_sram)
- sram_deinit(dev);
-
- if (dev->status_req) {
- kfree(dev->status_req->req.buf);
- kfree(dev->status_req);
- }
-
- kfree(dev->ep);
-
- /* disable IRQ handler */
- if (dev->got_irq)
- free_irq(pdev->irq, dev);
-
- if (dev->cap_regs)
- iounmap(dev->cap_regs);
-
- if (dev->region)
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
-
- if (dev->enabled)
- pci_disable_device(pdev);
-
- dev->cap_regs = NULL;
-
- dev_info(&dev->pdev->dev, "unbind\n");
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-
- device_unregister(&dev->gadget.dev);
- device_remove_file(&pdev->dev, &dev_attr_langwell_udc);
- device_remove_file(&pdev->dev, &dev_attr_remote_wakeup);
-
- pci_set_drvdata(pdev, NULL);
-
- /* free dev, wait for the release() finished */
- wait_for_completion(&done);
-}
-
-
-/*
- * wrap this driver around the specified device, but
- * don't respond over USB until a gadget driver binds to us.
- */
-static int langwell_udc_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- struct langwell_udc *dev;
- unsigned long resource, len;
- void __iomem *base = NULL;
- size_t size;
- int retval;
-
- /* alloc, and start init */
- dev = kzalloc(sizeof *dev, GFP_KERNEL);
- if (dev == NULL) {
- retval = -ENOMEM;
- goto error;
- }
-
- /* initialize device spinlock */
- spin_lock_init(&dev->lock);
-
- dev->pdev = pdev;
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- pci_set_drvdata(pdev, dev);
-
- /* now all the pci goodies ... */
- if (pci_enable_device(pdev) < 0) {
- retval = -ENODEV;
- goto error;
- }
- dev->enabled = 1;
-
- /* control register: BAR 0 */
- resource = pci_resource_start(pdev, 0);
- len = pci_resource_len(pdev, 0);
- if (!request_mem_region(resource, len, driver_name)) {
- dev_err(&dev->pdev->dev, "controller already in use\n");
- retval = -EBUSY;
- goto error;
- }
- dev->region = 1;
-
- base = ioremap_nocache(resource, len);
- if (base == NULL) {
- dev_err(&dev->pdev->dev, "can't map memory\n");
- retval = -EFAULT;
- goto error;
- }
-
- dev->cap_regs = (struct langwell_cap_regs __iomem *) base;
- dev_vdbg(&dev->pdev->dev, "dev->cap_regs: %p\n", dev->cap_regs);
- dev->op_regs = (struct langwell_op_regs __iomem *)
- (base + OP_REG_OFFSET);
- dev_vdbg(&dev->pdev->dev, "dev->op_regs: %p\n", dev->op_regs);
-
- /* irq setup after old hardware is cleaned up */
- if (!pdev->irq) {
- dev_err(&dev->pdev->dev, "No IRQ. Check PCI setup!\n");
- retval = -ENODEV;
- goto error;
- }
-
- dev->has_sram = 1;
- dev->got_sram = 0;
- dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram);
-
- /* enable SRAM caching if detected */
- if (dev->has_sram && !dev->got_sram)
- sram_init(dev);
-
- dev_info(&dev->pdev->dev,
- "irq %d, io mem: 0x%08lx, len: 0x%08lx, pci mem 0x%p\n",
- pdev->irq, resource, len, base);
- /* enables bus-mastering for device dev */
- pci_set_master(pdev);
-
- if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED,
- driver_name, dev) != 0) {
- dev_err(&dev->pdev->dev,
- "request interrupt %d failed\n", pdev->irq);
- retval = -EBUSY;
- goto error;
- }
- dev->got_irq = 1;
-
- /* set stopped bit */
- dev->stopped = 1;
-
- /* capabilities and endpoint number */
- dev->lpm = (readl(&dev->cap_regs->hccparams) & HCC_LEN) ? 1 : 0;
- dev->dciversion = readw(&dev->cap_regs->dciversion);
- dev->devcap = (readl(&dev->cap_regs->dccparams) & DEVCAP) ? 1 : 0;
- dev_vdbg(&dev->pdev->dev, "dev->lpm: %d\n", dev->lpm);
- dev_vdbg(&dev->pdev->dev, "dev->dciversion: 0x%04x\n",
- dev->dciversion);
- dev_vdbg(&dev->pdev->dev, "dccparams: 0x%08x\n",
- readl(&dev->cap_regs->dccparams));
- dev_vdbg(&dev->pdev->dev, "dev->devcap: %d\n", dev->devcap);
- if (!dev->devcap) {
- dev_err(&dev->pdev->dev, "can't support device mode\n");
- retval = -ENODEV;
- goto error;
- }
-
- /* a pair of endpoints (out/in) for each address */
- dev->ep_max = DEN(readl(&dev->cap_regs->dccparams)) * 2;
- dev_vdbg(&dev->pdev->dev, "dev->ep_max: %d\n", dev->ep_max);
-
- /* allocate endpoints memory */
- dev->ep = kzalloc(sizeof(struct langwell_ep) * dev->ep_max,
- GFP_KERNEL);
- if (!dev->ep) {
- dev_err(&dev->pdev->dev, "allocate endpoints memory failed\n");
- retval = -ENOMEM;
- goto error;
- }
-
- /* allocate device dQH memory */
- size = dev->ep_max * sizeof(struct langwell_dqh);
- dev_vdbg(&dev->pdev->dev, "orig size = %zd\n", size);
- if (size < DQH_ALIGNMENT)
- size = DQH_ALIGNMENT;
- else if ((size % DQH_ALIGNMENT) != 0) {
- size += DQH_ALIGNMENT + 1;
- size &= ~(DQH_ALIGNMENT - 1);
- }
- dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size,
- &dev->ep_dqh_dma, GFP_KERNEL);
- if (!dev->ep_dqh) {
- dev_err(&dev->pdev->dev, "allocate dQH memory failed\n");
- retval = -ENOMEM;
- goto error;
- }
- dev->ep_dqh_size = size;
- dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %zd\n", dev->ep_dqh_size);
-
- /* initialize ep0 status request structure */
- dev->status_req = kzalloc(sizeof(struct langwell_request), GFP_KERNEL);
- if (!dev->status_req) {
- dev_err(&dev->pdev->dev,
- "allocate status_req memory failed\n");
- retval = -ENOMEM;
- goto error;
- }
- INIT_LIST_HEAD(&dev->status_req->queue);
-
- /* allocate a small amount of memory to get valid address */
- dev->status_req->req.buf = kmalloc(8, GFP_KERNEL);
- dev->status_req->req.dma = virt_to_phys(dev->status_req->req.buf);
-
- dev->resume_state = USB_STATE_NOTATTACHED;
- dev->usb_state = USB_STATE_POWERED;
- dev->ep0_dir = USB_DIR_OUT;
-
- /* remote wakeup reset to 0 when the device is reset */
- dev->remote_wakeup = 0;
- dev->dev_status = 1 << USB_DEVICE_SELF_POWERED;
-
- /* reset device controller */
- langwell_udc_reset(dev);
-
- /* initialize gadget structure */
- dev->gadget.ops = &langwell_ops; /* usb_gadget_ops */
- dev->gadget.ep0 = &dev->ep[0].ep; /* gadget ep0 */
- INIT_LIST_HEAD(&dev->gadget.ep_list); /* ep_list */
- dev->gadget.speed = USB_SPEED_UNKNOWN; /* speed */
- dev->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */
-
- /* the "gadget" abstracts/virtualizes the controller */
- dev_set_name(&dev->gadget.dev, "gadget");
- dev->gadget.dev.parent = &pdev->dev;
- dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
- dev->gadget.dev.release = gadget_release;
- dev->gadget.name = driver_name; /* gadget name */
-
- /* controller endpoints reinit */
- eps_reinit(dev);
-
- /* reset ep0 dQH and endptctrl */
- ep0_reset(dev);
-
- /* create dTD dma_pool resource */
- dev->dtd_pool = dma_pool_create("langwell_dtd",
- &dev->pdev->dev,
- sizeof(struct langwell_dtd),
- DTD_ALIGNMENT,
- DMA_BOUNDARY);
-
- if (!dev->dtd_pool) {
- retval = -ENOMEM;
- goto error;
- }
-
- /* done */
- dev_info(&dev->pdev->dev, "%s\n", driver_desc);
- dev_info(&dev->pdev->dev, "irq %d, pci mem %p\n", pdev->irq, base);
- dev_info(&dev->pdev->dev, "Driver version: " DRIVER_VERSION "\n");
- dev_info(&dev->pdev->dev, "Support (max) %d endpoints\n", dev->ep_max);
- dev_info(&dev->pdev->dev, "Device interface version: 0x%04x\n",
- dev->dciversion);
- dev_info(&dev->pdev->dev, "Controller mode: %s\n",
- dev->devcap ? "Device" : "Host");
- dev_info(&dev->pdev->dev, "Support USB LPM: %s\n",
- dev->lpm ? "Yes" : "No");
-
- dev_vdbg(&dev->pdev->dev,
- "After langwell_udc_probe(), print all registers:\n");
- print_all_registers(dev);
-
- retval = device_register(&dev->gadget.dev);
- if (retval)
- goto error;
-
- retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
- if (retval)
- goto error;
-
- retval = device_create_file(&pdev->dev, &dev_attr_langwell_udc);
- if (retval)
- goto error;
-
- retval = device_create_file(&pdev->dev, &dev_attr_remote_wakeup);
- if (retval)
- goto error_attr1;
-
- dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return 0;
-
-error_attr1:
- device_remove_file(&pdev->dev, &dev_attr_langwell_udc);
-error:
- if (dev) {
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- langwell_udc_remove(pdev);
- }
-
- return retval;
-}
-
-
-/* device controller suspend */
-static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct langwell_udc *dev = pci_get_drvdata(pdev);
-
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- usb_del_gadget_udc(&dev->gadget);
- /* disable interrupt and set controller to stop state */
- langwell_udc_stop(dev);
-
- /* disable IRQ handler */
- if (dev->got_irq)
- free_irq(pdev->irq, dev);
- dev->got_irq = 0;
-
- /* save PCI state */
- pci_save_state(pdev);
-
- spin_lock_irq(&dev->lock);
- /* stop all usb activities */
- stop_activity(dev);
- spin_unlock_irq(&dev->lock);
-
- /* free dTD dma_pool and dQH */
- if (dev->dtd_pool)
- dma_pool_destroy(dev->dtd_pool);
-
- if (dev->ep_dqh)
- dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
- dev->ep_dqh, dev->ep_dqh_dma);
-
- /* release SRAM caching */
- if (dev->has_sram && dev->got_sram)
- sram_deinit(dev);
-
- /* set device power state */
- pci_set_power_state(pdev, PCI_D3hot);
-
- /* enter PHY low power suspend */
- if (dev->pdev->device != 0x0829)
- langwell_phy_low_power(dev, 1);
-
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return 0;
-}
-
-
-/* device controller resume */
-static int langwell_udc_resume(struct pci_dev *pdev)
-{
- struct langwell_udc *dev = pci_get_drvdata(pdev);
- size_t size;
-
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* exit PHY low power suspend */
- if (dev->pdev->device != 0x0829)
- langwell_phy_low_power(dev, 0);
-
- /* set device D0 power state */
- pci_set_power_state(pdev, PCI_D0);
-
- /* enable SRAM caching if detected */
- if (dev->has_sram && !dev->got_sram)
- sram_init(dev);
-
- /* allocate device dQH memory */
- size = dev->ep_max * sizeof(struct langwell_dqh);
- dev_vdbg(&dev->pdev->dev, "orig size = %zd\n", size);
- if (size < DQH_ALIGNMENT)
- size = DQH_ALIGNMENT;
- else if ((size % DQH_ALIGNMENT) != 0) {
- size += DQH_ALIGNMENT + 1;
- size &= ~(DQH_ALIGNMENT - 1);
- }
- dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size,
- &dev->ep_dqh_dma, GFP_KERNEL);
- if (!dev->ep_dqh) {
- dev_err(&dev->pdev->dev, "allocate dQH memory failed\n");
- return -ENOMEM;
- }
- dev->ep_dqh_size = size;
- dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %zd\n", dev->ep_dqh_size);
-
- /* create dTD dma_pool resource */
- dev->dtd_pool = dma_pool_create("langwell_dtd",
- &dev->pdev->dev,
- sizeof(struct langwell_dtd),
- DTD_ALIGNMENT,
- DMA_BOUNDARY);
-
- if (!dev->dtd_pool)
- return -ENOMEM;
-
- /* restore PCI state */
- pci_restore_state(pdev);
-
- /* enable IRQ handler */
- if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED,
- driver_name, dev) != 0) {
- dev_err(&dev->pdev->dev, "request interrupt %d failed\n",
- pdev->irq);
- return -EBUSY;
- }
- dev->got_irq = 1;
-
- /* reset and start controller to run state */
- if (dev->stopped) {
- /* reset device controller */
- langwell_udc_reset(dev);
-
- /* reset ep0 dQH and endptctrl */
- ep0_reset(dev);
-
- /* start device if gadget is loaded */
- if (dev->driver)
- langwell_udc_start(dev);
- }
-
- /* reset USB status */
- dev->usb_state = USB_STATE_ATTACHED;
- dev->ep0_state = WAIT_FOR_SETUP;
- dev->ep0_dir = USB_DIR_OUT;
-
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
- return 0;
-}
-
-
-/* pci driver shutdown */
-static void langwell_udc_shutdown(struct pci_dev *pdev)
-{
- struct langwell_udc *dev = pci_get_drvdata(pdev);
- u32 usbmode;
-
- dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-
- /* reset controller mode to IDLE */
- usbmode = readl(&dev->op_regs->usbmode);
- dev_dbg(&dev->pdev->dev, "usbmode = 0x%08x\n", usbmode);
- usbmode &= (~3 | MODE_IDLE);
- writel(usbmode, &dev->op_regs->usbmode);
-
- dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static const struct pci_device_id pci_ids[] = { {
- .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
- .class_mask = ~0,
- .vendor = 0x8086,
- .device = 0x0811,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
-}, { /* end: all zeroes */ }
-};
-
-MODULE_DEVICE_TABLE(pci, pci_ids);
-
-
-static struct pci_driver langwell_pci_driver = {
- .name = (char *) driver_name,
- .id_table = pci_ids,
-
- .probe = langwell_udc_probe,
- .remove = langwell_udc_remove,
-
- /* device controller suspend/resume */
- .suspend = langwell_udc_suspend,
- .resume = langwell_udc_resume,
-
- .shutdown = langwell_udc_shutdown,
-};
-
-
-static int __init init(void)
-{
- return pci_register_driver(&langwell_pci_driver);
-}
-module_init(init);
-
-
-static void __exit cleanup(void)
-{
- pci_unregister_driver(&langwell_pci_driver);
-}
-module_exit(cleanup);
-
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Xiaochen Shen <xiaochen.shen@intel.com>");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h
deleted file mode 100644
index 8c8087abb481..000000000000
--- a/drivers/usb/gadget/langwell_udc.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Intel Langwell USB Device Controller driver
- * Copyright (C) 2008-2009, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- */
-
-#include <linux/usb/langwell_udc.h>
-
-/*-------------------------------------------------------------------------*/
-
-/* driver data structures and utilities */
-
-/*
- * dTD: Device Endpoint Transfer Descriptor
- * describe to the device controller the location and quantity of
- * data to be send/received for given transfer
- */
-struct langwell_dtd {
- u32 dtd_next;
-/* bits 31:5, next transfer element pointer */
-#define DTD_NEXT(d) (((d)>>5)&0x7ffffff)
-#define DTD_NEXT_MASK (0x7ffffff << 5)
-/* terminate */
-#define DTD_TERM BIT(0)
- /* bits 7:0, execution back states */
- u32 dtd_status:8;
-#define DTD_STATUS(d) (((d)>>0)&0xff)
-#define DTD_STS_ACTIVE BIT(7) /* active */
-#define DTD_STS_HALTED BIT(6) /* halted */
-#define DTD_STS_DBE BIT(5) /* data buffer error */
-#define DTD_STS_TRE BIT(3) /* transaction error */
- /* bits 9:8 */
- u32 dtd_res0:2;
- /* bits 11:10, multipier override */
- u32 dtd_multo:2;
-#define DTD_MULTO (BIT(11) | BIT(10))
- /* bits 14:12 */
- u32 dtd_res1:3;
- /* bit 15, interrupt on complete */
- u32 dtd_ioc:1;
-#define DTD_IOC BIT(15)
- /* bits 30:16, total bytes */
- u32 dtd_total:15;
-#define DTD_TOTAL(d) (((d)>>16)&0x7fff)
-#define DTD_MAX_TRANSFER_LENGTH 0x4000
- /* bit 31 */
- u32 dtd_res2:1;
- /* dTD buffer pointer page 0 to 4 */
- u32 dtd_buf[5];
-#define DTD_OFFSET_MASK 0xfff
-/* bits 31:12, buffer pointer */
-#define DTD_BUFFER(d) (((d)>>12)&0x3ff)
-/* bits 11:0, current offset */
-#define DTD_C_OFFSET(d) (((d)>>0)&0xfff)
-/* bits 10:0, frame number */
-#define DTD_FRAME(d) (((d)>>0)&0x7ff)
-
- /* driver-private parts */
-
- /* dtd dma address */
- dma_addr_t dtd_dma;
- /* next dtd virtual address */
- struct langwell_dtd *next_dtd_virt;
-};
-
-
-/*
- * dQH: Device Endpoint Queue Head
- * describe where all transfers are managed
- * 48-byte data structure, aligned on 64-byte boundary
- *
- * These are associated with dTD structure
- */
-struct langwell_dqh {
- /* endpoint capabilities and characteristics */
- u32 dqh_res0:15; /* bits 14:0 */
- u32 dqh_ios:1; /* bit 15, interrupt on setup */
-#define DQH_IOS BIT(15)
- u32 dqh_mpl:11; /* bits 26:16, maximum packet length */
-#define DQH_MPL (0x7ff << 16)
- u32 dqh_res1:2; /* bits 28:27 */
- u32 dqh_zlt:1; /* bit 29, zero length termination */
-#define DQH_ZLT BIT(29)
- u32 dqh_mult:2; /* bits 31:30 */
-#define DQH_MULT (BIT(30) | BIT(31))
-
- /* current dTD pointer */
- u32 dqh_current; /* locate the transfer in progress */
-#define DQH_C_DTD(e) \
- (((e)>>5)&0x7ffffff) /* bits 31:5, current dTD pointer */
-
- /* transfer overlay, hardware parts of a struct langwell_dtd */
- u32 dtd_next;
- u32 dtd_status:8; /* bits 7:0, execution back states */
- u32 dtd_res0:2; /* bits 9:8 */
- u32 dtd_multo:2; /* bits 11:10, multipier override */
- u32 dtd_res1:3; /* bits 14:12 */
- u32 dtd_ioc:1; /* bit 15, interrupt on complete */
- u32 dtd_total:15; /* bits 30:16, total bytes */
- u32 dtd_res2:1; /* bit 31 */
- u32 dtd_buf[5]; /* dTD buffer pointer page 0 to 4 */
-
- u32 dqh_res2;
- struct usb_ctrlrequest dqh_setup; /* setup packet buffer */
-} __attribute__ ((aligned(64)));
-
-
-/* endpoint data structure */
-struct langwell_ep {
- struct usb_ep ep;
- dma_addr_t dma;
- struct langwell_udc *dev;
- unsigned long irqs;
- struct list_head queue;
- struct langwell_dqh *dqh;
- const struct usb_endpoint_descriptor *desc;
- char name[14];
- unsigned stopped:1,
- ep_type:2,
- ep_num:8;
-};
-
-
-/* request data structure */
-struct langwell_request {
- struct usb_request req;
- struct langwell_dtd *dtd, *head, *tail;
- struct langwell_ep *ep;
- dma_addr_t dtd_dma;
- struct list_head queue;
- unsigned dtd_count;
- unsigned mapped:1;
-};
-
-
-/* ep0 transfer state */
-enum ep0_state {
- WAIT_FOR_SETUP,
- DATA_STATE_XMIT,
- DATA_STATE_NEED_ZLP,
- WAIT_FOR_OUT_STATUS,
- DATA_STATE_RECV,
-};
-
-
-/* device suspend state */
-enum lpm_state {
- LPM_L0, /* on */
- LPM_L1, /* LPM L1 sleep */
- LPM_L2, /* suspend */
- LPM_L3, /* off */
-};
-
-
-/* device data structure */
-struct langwell_udc {
- /* each pci device provides one gadget, several endpoints */
- struct usb_gadget gadget;
- spinlock_t lock; /* device lock */
- struct langwell_ep *ep;
- struct usb_gadget_driver *driver;
- struct usb_phy *transceiver;
- u8 dev_addr;
- u32 usb_state;
- u32 resume_state;
- u32 bus_reset;
- enum lpm_state lpm_state;
- enum ep0_state ep0_state;
- u32 ep0_dir;
- u16 dciversion;
- unsigned ep_max;
- unsigned devcap:1,
- enabled:1,
- region:1,
- got_irq:1,
- powered:1,
- remote_wakeup:1,
- rate:1,
- is_reset:1,
- softconnected:1,
- vbus_active:1,
- suspended:1,
- stopped:1,
- lpm:1, /* LPM capability */
- has_sram:1, /* SRAM caching */
- got_sram:1;
-
- /* pci state used to access those endpoints */
- struct pci_dev *pdev;
-
- /* Langwell otg transceiver */
- struct langwell_otg *lotg;
-
- /* control registers */
- struct langwell_cap_regs __iomem *cap_regs;
- struct langwell_op_regs __iomem *op_regs;
-
- struct usb_ctrlrequest local_setup_buff;
- struct langwell_dqh *ep_dqh;
- size_t ep_dqh_size;
- dma_addr_t ep_dqh_dma;
-
- /* ep0 status request */
- struct langwell_request *status_req;
-
- /* dma pool */
- struct dma_pool *dtd_pool;
-
- /* make sure release() is done */
- struct completion *done;
-
- /* for private SRAM caching */
- unsigned int sram_addr;
- unsigned int sram_size;
-
- /* device status data for get_status request */
- u16 dev_status;
-};
-
-#define gadget_to_langwell(g) container_of((g), struct langwell_udc, gadget)
-
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c
new file mode 100644
index 000000000000..262acfd53e32
--- /dev/null
+++ b/drivers/usb/gadget/lpc32xx_udc.c
@@ -0,0 +1,3538 @@
+/*
+ * USB Gadget driver for LPC32xx
+ *
+ * Authors:
+ * Kevin Wells <kevin.wells@nxp.com>
+ * Mike James
+ * Roland Stigge <stigge@antcom.de>
+ *
+ * Copyright (C) 2006 Philips Semiconductors
+ * Copyright (C) 2009 NXP Semiconductors
+ * Copyright (C) 2012 Roland Stigge
+ *
+ * Note: This driver is based on original work done by Mike James for
+ * the LPC3180.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/clk.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/i2c.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/workqueue.h>
+#include <linux/of.h>
+#include <linux/usb/isp1301.h>
+
+#include <asm/byteorder.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include <mach/platform.h>
+#include <mach/irqs.h>
+#include <mach/board.h>
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+#include <linux/seq_file.h>
+#endif
+
+/*
+ * USB device configuration structure
+ */
+typedef void (*usc_chg_event)(int);
+struct lpc32xx_usbd_cfg {
+ int vbus_drv_pol; /* 0=active low drive for VBUS via ISP1301 */
+ usc_chg_event conn_chgb; /* Connection change event (optional) */
+ usc_chg_event susp_chgb; /* Suspend/resume event (optional) */
+ usc_chg_event rmwk_chgb; /* Enable/disable remote wakeup */
+};
+
+/*
+ * controller driver data structures
+ */
+
+/* 16 endpoints (not to be confused with 32 hardware endpoints) */
+#define NUM_ENDPOINTS 16
+
+/*
+ * IRQ indices make reading the code a little easier
+ */
+#define IRQ_USB_LP 0
+#define IRQ_USB_HP 1
+#define IRQ_USB_DEVDMA 2
+#define IRQ_USB_ATX 3
+
+#define EP_OUT 0 /* RX (from host) */
+#define EP_IN 1 /* TX (to host) */
+
+/* Returns the interrupt mask for the selected hardware endpoint */
+#define EP_MASK_SEL(ep, dir) (1 << (((ep) * 2) + dir))
+
+#define EP_INT_TYPE 0
+#define EP_ISO_TYPE 1
+#define EP_BLK_TYPE 2
+#define EP_CTL_TYPE 3
+
+/* EP0 states */
+#define WAIT_FOR_SETUP 0 /* Wait for setup packet */
+#define DATA_IN 1 /* Expect dev->host transfer */
+#define DATA_OUT 2 /* Expect host->dev transfer */
+
+/* DD (DMA Descriptor) structure, requires word alignment, this is already
+ * defined in the LPC32XX USB device header file, but this version is slightly
+ * modified to tag some work data with each DMA descriptor. */
+struct lpc32xx_usbd_dd_gad {
+ u32 dd_next_phy;
+ u32 dd_setup;
+ u32 dd_buffer_addr;
+ u32 dd_status;
+ u32 dd_iso_ps_mem_addr;
+ u32 this_dma;
+ u32 iso_status[6]; /* 5 spare */
+ u32 dd_next_v;
+};
+
+/*
+ * Logical endpoint structure
+ */
+struct lpc32xx_ep {
+ struct usb_ep ep;
+ struct list_head queue;
+ struct lpc32xx_udc *udc;
+
+ u32 hwep_num_base; /* Physical hardware EP */
+ u32 hwep_num; /* Maps to hardware endpoint */
+ u32 maxpacket;
+ u32 lep;
+
+ bool is_in;
+ bool req_pending;
+ u32 eptype;
+
+ u32 totalints;
+
+ bool wedge;
+
+ const struct usb_endpoint_descriptor *desc;
+};
+
+/*
+ * Common UDC structure
+ */
+struct lpc32xx_udc {
+ struct usb_gadget gadget;
+ struct usb_gadget_driver *driver;
+ struct platform_device *pdev;
+ struct device *dev;
+ struct dentry *pde;
+ spinlock_t lock;
+ struct i2c_client *isp1301_i2c_client;
+
+ /* Board and device specific */
+ struct lpc32xx_usbd_cfg *board;
+ u32 io_p_start;
+ u32 io_p_size;
+ void __iomem *udp_baseaddr;
+ int udp_irq[4];
+ struct clk *usb_pll_clk;
+ struct clk *usb_slv_clk;
+
+ /* DMA support */
+ u32 *udca_v_base;
+ u32 udca_p_base;
+ struct dma_pool *dd_cache;
+
+ /* Common EP and control data */
+ u32 enabled_devints;
+ u32 enabled_hwepints;
+ u32 dev_status;
+ u32 realized_eps;
+
+ /* VBUS detection, pullup, and power flags */
+ u8 vbus;
+ u8 last_vbus;
+ int pullup;
+ int poweron;
+
+ /* Work queues related to I2C support */
+ struct work_struct pullup_job;
+ struct work_struct vbus_job;
+ struct work_struct power_job;
+
+ /* USB device peripheral - various */
+ struct lpc32xx_ep ep[NUM_ENDPOINTS];
+ bool enabled;
+ bool clocked;
+ bool suspended;
+ bool selfpowered;
+ int ep0state;
+ atomic_t enabled_ep_cnt;
+ wait_queue_head_t ep_disable_wait_queue;
+};
+
+/*
+ * Endpoint request
+ */
+struct lpc32xx_request {
+ struct usb_request req;
+ struct list_head queue;
+ struct lpc32xx_usbd_dd_gad *dd_desc_ptr;
+ bool mapped;
+ bool send_zlp;
+};
+
+static inline struct lpc32xx_udc *to_udc(struct usb_gadget *g)
+{
+ return container_of(g, struct lpc32xx_udc, gadget);
+}
+
+#define ep_dbg(epp, fmt, arg...) \
+ dev_dbg(epp->udc->dev, "%s: " fmt, __func__, ## arg)
+#define ep_err(epp, fmt, arg...) \
+ dev_err(epp->udc->dev, "%s: " fmt, __func__, ## arg)
+#define ep_info(epp, fmt, arg...) \
+ dev_info(epp->udc->dev, "%s: " fmt, __func__, ## arg)
+#define ep_warn(epp, fmt, arg...) \
+ dev_warn(epp->udc->dev, "%s:" fmt, __func__, ## arg)
+
+#define UDCA_BUFF_SIZE (128)
+
+/* TODO: When the clock framework is introduced in LPC32xx, IO_ADDRESS will
+ * be replaced with an inremap()ed pointer, see USB_OTG_CLK_CTRL()
+ * */
+#define USB_CTRL IO_ADDRESS(LPC32XX_CLK_PM_BASE + 0x64)
+#define USB_CLOCK_MASK (AHB_M_CLOCK_ON | OTG_CLOCK_ON | \
+ DEV_CLOCK_ON | I2C_CLOCK_ON)
+
+/* USB_CTRL bit defines */
+#define USB_SLAVE_HCLK_EN (1 << 24)
+#define USB_HOST_NEED_CLK_EN (1 << 21)
+#define USB_DEV_NEED_CLK_EN (1 << 22)
+
+#define USB_OTG_CLK_CTRL(udc) ((udc)->udp_baseaddr + 0xFF4)
+#define USB_OTG_CLK_STAT(udc) ((udc)->udp_baseaddr + 0xFF8)
+
+/* USB_OTG_CLK_CTRL bit defines */
+#define AHB_M_CLOCK_ON (1 << 4)
+#define OTG_CLOCK_ON (1 << 3)
+#define I2C_CLOCK_ON (1 << 2)
+#define DEV_CLOCK_ON (1 << 1)
+#define HOST_CLOCK_ON (1 << 0)
+
+#define USB_OTG_STAT_CONTROL(udc) (udc->udp_baseaddr + 0x110)
+
+/* USB_OTG_STAT_CONTROL bit defines */
+#define TRANSPARENT_I2C_EN (1 << 7)
+#define HOST_EN (1 << 0)
+
+/**********************************************************************
+ * USB device controller register offsets
+ **********************************************************************/
+
+#define USBD_DEVINTST(x) ((x) + 0x200)
+#define USBD_DEVINTEN(x) ((x) + 0x204)
+#define USBD_DEVINTCLR(x) ((x) + 0x208)
+#define USBD_DEVINTSET(x) ((x) + 0x20C)
+#define USBD_CMDCODE(x) ((x) + 0x210)
+#define USBD_CMDDATA(x) ((x) + 0x214)
+#define USBD_RXDATA(x) ((x) + 0x218)
+#define USBD_TXDATA(x) ((x) + 0x21C)
+#define USBD_RXPLEN(x) ((x) + 0x220)
+#define USBD_TXPLEN(x) ((x) + 0x224)
+#define USBD_CTRL(x) ((x) + 0x228)
+#define USBD_DEVINTPRI(x) ((x) + 0x22C)
+#define USBD_EPINTST(x) ((x) + 0x230)
+#define USBD_EPINTEN(x) ((x) + 0x234)
+#define USBD_EPINTCLR(x) ((x) + 0x238)
+#define USBD_EPINTSET(x) ((x) + 0x23C)
+#define USBD_EPINTPRI(x) ((x) + 0x240)
+#define USBD_REEP(x) ((x) + 0x244)
+#define USBD_EPIND(x) ((x) + 0x248)
+#define USBD_EPMAXPSIZE(x) ((x) + 0x24C)
+/* DMA support registers only below */
+/* Set, clear, or get enabled state of the DMA request status. If
+ * enabled, an IN or OUT token will start a DMA transfer for the EP */
+#define USBD_DMARST(x) ((x) + 0x250)
+#define USBD_DMARCLR(x) ((x) + 0x254)
+#define USBD_DMARSET(x) ((x) + 0x258)
+/* DMA UDCA head pointer */
+#define USBD_UDCAH(x) ((x) + 0x280)
+/* EP DMA status, enable, and disable. This is used to specifically
+ * enabled or disable DMA for a specific EP */
+#define USBD_EPDMAST(x) ((x) + 0x284)
+#define USBD_EPDMAEN(x) ((x) + 0x288)
+#define USBD_EPDMADIS(x) ((x) + 0x28C)
+/* DMA master interrupts enable and pending interrupts */
+#define USBD_DMAINTST(x) ((x) + 0x290)
+#define USBD_DMAINTEN(x) ((x) + 0x294)
+/* DMA end of transfer interrupt enable, disable, status */
+#define USBD_EOTINTST(x) ((x) + 0x2A0)
+#define USBD_EOTINTCLR(x) ((x) + 0x2A4)
+#define USBD_EOTINTSET(x) ((x) + 0x2A8)
+/* New DD request interrupt enable, disable, status */
+#define USBD_NDDRTINTST(x) ((x) + 0x2AC)
+#define USBD_NDDRTINTCLR(x) ((x) + 0x2B0)
+#define USBD_NDDRTINTSET(x) ((x) + 0x2B4)
+/* DMA error interrupt enable, disable, status */
+#define USBD_SYSERRTINTST(x) ((x) + 0x2B8)
+#define USBD_SYSERRTINTCLR(x) ((x) + 0x2BC)
+#define USBD_SYSERRTINTSET(x) ((x) + 0x2C0)
+
+/**********************************************************************
+ * USBD_DEVINTST/USBD_DEVINTEN/USBD_DEVINTCLR/USBD_DEVINTSET/
+ * USBD_DEVINTPRI register definitions
+ **********************************************************************/
+#define USBD_ERR_INT (1 << 9)
+#define USBD_EP_RLZED (1 << 8)
+#define USBD_TXENDPKT (1 << 7)
+#define USBD_RXENDPKT (1 << 6)
+#define USBD_CDFULL (1 << 5)
+#define USBD_CCEMPTY (1 << 4)
+#define USBD_DEV_STAT (1 << 3)
+#define USBD_EP_SLOW (1 << 2)
+#define USBD_EP_FAST (1 << 1)
+#define USBD_FRAME (1 << 0)
+
+/**********************************************************************
+ * USBD_EPINTST/USBD_EPINTEN/USBD_EPINTCLR/USBD_EPINTSET/
+ * USBD_EPINTPRI register definitions
+ **********************************************************************/
+/* End point selection macro (RX) */
+#define USBD_RX_EP_SEL(e) (1 << ((e) << 1))
+
+/* End point selection macro (TX) */
+#define USBD_TX_EP_SEL(e) (1 << (((e) << 1) + 1))
+
+/**********************************************************************
+ * USBD_REEP/USBD_DMARST/USBD_DMARCLR/USBD_DMARSET/USBD_EPDMAST/
+ * USBD_EPDMAEN/USBD_EPDMADIS/
+ * USBD_NDDRTINTST/USBD_NDDRTINTCLR/USBD_NDDRTINTSET/
+ * USBD_EOTINTST/USBD_EOTINTCLR/USBD_EOTINTSET/
+ * USBD_SYSERRTINTST/USBD_SYSERRTINTCLR/USBD_SYSERRTINTSET
+ * register definitions
+ **********************************************************************/
+/* Endpoint selection macro */
+#define USBD_EP_SEL(e) (1 << (e))
+
+/**********************************************************************
+ * SBD_DMAINTST/USBD_DMAINTEN
+ **********************************************************************/
+#define USBD_SYS_ERR_INT (1 << 2)
+#define USBD_NEW_DD_INT (1 << 1)
+#define USBD_EOT_INT (1 << 0)
+
+/**********************************************************************
+ * USBD_RXPLEN register definitions
+ **********************************************************************/
+#define USBD_PKT_RDY (1 << 11)
+#define USBD_DV (1 << 10)
+#define USBD_PK_LEN_MASK 0x3FF
+
+/**********************************************************************
+ * USBD_CTRL register definitions
+ **********************************************************************/
+#define USBD_LOG_ENDPOINT(e) ((e) << 2)
+#define USBD_WR_EN (1 << 1)
+#define USBD_RD_EN (1 << 0)
+
+/**********************************************************************
+ * USBD_CMDCODE register definitions
+ **********************************************************************/
+#define USBD_CMD_CODE(c) ((c) << 16)
+#define USBD_CMD_PHASE(p) ((p) << 8)
+
+/**********************************************************************
+ * USBD_DMARST/USBD_DMARCLR/USBD_DMARSET register definitions
+ **********************************************************************/
+#define USBD_DMAEP(e) (1 << (e))
+
+/* DD (DMA Descriptor) structure, requires word alignment */
+struct lpc32xx_usbd_dd {
+ u32 *dd_next;
+ u32 dd_setup;
+ u32 dd_buffer_addr;
+ u32 dd_status;
+ u32 dd_iso_ps_mem_addr;
+};
+
+/* dd_setup bit defines */
+#define DD_SETUP_ATLE_DMA_MODE 0x01
+#define DD_SETUP_NEXT_DD_VALID 0x04
+#define DD_SETUP_ISO_EP 0x10
+#define DD_SETUP_PACKETLEN(n) (((n) & 0x7FF) << 5)
+#define DD_SETUP_DMALENBYTES(n) (((n) & 0xFFFF) << 16)
+
+/* dd_status bit defines */
+#define DD_STATUS_DD_RETIRED 0x01
+#define DD_STATUS_STS_MASK 0x1E
+#define DD_STATUS_STS_NS 0x00 /* Not serviced */
+#define DD_STATUS_STS_BS 0x02 /* Being serviced */
+#define DD_STATUS_STS_NC 0x04 /* Normal completion */
+#define DD_STATUS_STS_DUR 0x06 /* Data underrun (short packet) */
+#define DD_STATUS_STS_DOR 0x08 /* Data overrun */
+#define DD_STATUS_STS_SE 0x12 /* System error */
+#define DD_STATUS_PKT_VAL 0x20 /* Packet valid */
+#define DD_STATUS_LSB_EX 0x40 /* LS byte extracted (ATLE) */
+#define DD_STATUS_MSB_EX 0x80 /* MS byte extracted (ATLE) */
+#define DD_STATUS_MLEN(n) (((n) >> 8) & 0x3F)
+#define DD_STATUS_CURDMACNT(n) (((n) >> 16) & 0xFFFF)
+
+/*
+ *
+ * Protocol engine bits below
+ *
+ */
+/* Device Interrupt Bit Definitions */
+#define FRAME_INT 0x00000001
+#define EP_FAST_INT 0x00000002
+#define EP_SLOW_INT 0x00000004
+#define DEV_STAT_INT 0x00000008
+#define CCEMTY_INT 0x00000010
+#define CDFULL_INT 0x00000020
+#define RxENDPKT_INT 0x00000040
+#define TxENDPKT_INT 0x00000080
+#define EP_RLZED_INT 0x00000100
+#define ERR_INT 0x00000200
+
+/* Rx & Tx Packet Length Definitions */
+#define PKT_LNGTH_MASK 0x000003FF
+#define PKT_DV 0x00000400
+#define PKT_RDY 0x00000800
+
+/* USB Control Definitions */
+#define CTRL_RD_EN 0x00000001
+#define CTRL_WR_EN 0x00000002
+
+/* Command Codes */
+#define CMD_SET_ADDR 0x00D00500
+#define CMD_CFG_DEV 0x00D80500
+#define CMD_SET_MODE 0x00F30500
+#define CMD_RD_FRAME 0x00F50500
+#define DAT_RD_FRAME 0x00F50200
+#define CMD_RD_TEST 0x00FD0500
+#define DAT_RD_TEST 0x00FD0200
+#define CMD_SET_DEV_STAT 0x00FE0500
+#define CMD_GET_DEV_STAT 0x00FE0500
+#define DAT_GET_DEV_STAT 0x00FE0200
+#define CMD_GET_ERR_CODE 0x00FF0500
+#define DAT_GET_ERR_CODE 0x00FF0200
+#define CMD_RD_ERR_STAT 0x00FB0500
+#define DAT_RD_ERR_STAT 0x00FB0200
+#define DAT_WR_BYTE(x) (0x00000100 | ((x) << 16))
+#define CMD_SEL_EP(x) (0x00000500 | ((x) << 16))
+#define DAT_SEL_EP(x) (0x00000200 | ((x) << 16))
+#define CMD_SEL_EP_CLRI(x) (0x00400500 | ((x) << 16))
+#define DAT_SEL_EP_CLRI(x) (0x00400200 | ((x) << 16))
+#define CMD_SET_EP_STAT(x) (0x00400500 | ((x) << 16))
+#define CMD_CLR_BUF 0x00F20500
+#define DAT_CLR_BUF 0x00F20200
+#define CMD_VALID_BUF 0x00FA0500
+
+/* Device Address Register Definitions */
+#define DEV_ADDR_MASK 0x7F
+#define DEV_EN 0x80
+
+/* Device Configure Register Definitions */
+#define CONF_DVICE 0x01
+
+/* Device Mode Register Definitions */
+#define AP_CLK 0x01
+#define INAK_CI 0x02
+#define INAK_CO 0x04
+#define INAK_II 0x08
+#define INAK_IO 0x10
+#define INAK_BI 0x20
+#define INAK_BO 0x40
+
+/* Device Status Register Definitions */
+#define DEV_CON 0x01
+#define DEV_CON_CH 0x02
+#define DEV_SUS 0x04
+#define DEV_SUS_CH 0x08
+#define DEV_RST 0x10
+
+/* Error Code Register Definitions */
+#define ERR_EC_MASK 0x0F
+#define ERR_EA 0x10
+
+/* Error Status Register Definitions */
+#define ERR_PID 0x01
+#define ERR_UEPKT 0x02
+#define ERR_DCRC 0x04
+#define ERR_TIMOUT 0x08
+#define ERR_EOP 0x10
+#define ERR_B_OVRN 0x20
+#define ERR_BTSTF 0x40
+#define ERR_TGL 0x80
+
+/* Endpoint Select Register Definitions */
+#define EP_SEL_F 0x01
+#define EP_SEL_ST 0x02
+#define EP_SEL_STP 0x04
+#define EP_SEL_PO 0x08
+#define EP_SEL_EPN 0x10
+#define EP_SEL_B_1_FULL 0x20
+#define EP_SEL_B_2_FULL 0x40
+
+/* Endpoint Status Register Definitions */
+#define EP_STAT_ST 0x01
+#define EP_STAT_DA 0x20
+#define EP_STAT_RF_MO 0x40
+#define EP_STAT_CND_ST 0x80
+
+/* Clear Buffer Register Definitions */
+#define CLR_BUF_PO 0x01
+
+/* DMA Interrupt Bit Definitions */
+#define EOT_INT 0x01
+#define NDD_REQ_INT 0x02
+#define SYS_ERR_INT 0x04
+
+#define DRIVER_VERSION "1.03"
+static const char driver_name[] = "lpc32xx_udc";
+
+/*
+ *
+ * proc interface support
+ *
+ */
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+static char *epnames[] = {"INT", "ISO", "BULK", "CTRL"};
+static const char debug_filename[] = "driver/udc";
+
+static void proc_ep_show(struct seq_file *s, struct lpc32xx_ep *ep)
+{
+ struct lpc32xx_request *req;
+
+ seq_printf(s, "\n");
+ seq_printf(s, "%12s, maxpacket %4d %3s",
+ ep->ep.name, ep->ep.maxpacket,
+ ep->is_in ? "in" : "out");
+ seq_printf(s, " type %4s", epnames[ep->eptype]);
+ seq_printf(s, " ints: %12d", ep->totalints);
+
+ if (list_empty(&ep->queue))
+ seq_printf(s, "\t(queue empty)\n");
+ else {
+ list_for_each_entry(req, &ep->queue, queue) {
+ u32 length = req->req.actual;
+
+ seq_printf(s, "\treq %p len %d/%d buf %p\n",
+ &req->req, length,
+ req->req.length, req->req.buf);
+ }
+ }
+}
+
+static int proc_udc_show(struct seq_file *s, void *unused)
+{
+ struct lpc32xx_udc *udc = s->private;
+ struct lpc32xx_ep *ep;
+ unsigned long flags;
+
+ seq_printf(s, "%s: version %s\n", driver_name, DRIVER_VERSION);
+
+ spin_lock_irqsave(&udc->lock, flags);
+
+ seq_printf(s, "vbus %s, pullup %s, %s powered%s, gadget %s\n\n",
+ udc->vbus ? "present" : "off",
+ udc->enabled ? (udc->vbus ? "active" : "enabled") :
+ "disabled",
+ udc->selfpowered ? "self" : "VBUS",
+ udc->suspended ? ", suspended" : "",
+ udc->driver ? udc->driver->driver.name : "(none)");
+
+ if (udc->enabled && udc->vbus) {
+ proc_ep_show(s, &udc->ep[0]);
+ list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
+ if (ep->desc)
+ proc_ep_show(s, ep);
+ }
+ }
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ return 0;
+}
+
+static int proc_udc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_udc_show, PDE(inode)->data);
+}
+
+static const struct file_operations proc_ops = {
+ .owner = THIS_MODULE,
+ .open = proc_udc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void create_debug_file(struct lpc32xx_udc *udc)
+{
+ udc->pde = debugfs_create_file(debug_filename, 0, NULL, udc, &proc_ops);
+}
+
+static void remove_debug_file(struct lpc32xx_udc *udc)
+{
+ if (udc->pde)
+ debugfs_remove(udc->pde);
+}
+
+#else
+static inline void create_debug_file(struct lpc32xx_udc *udc) {}
+static inline void remove_debug_file(struct lpc32xx_udc *udc) {}
+#endif
+
+/* Primary initialization sequence for the ISP1301 transceiver */
+static void isp1301_udc_configure(struct lpc32xx_udc *udc)
+{
+ /* LPC32XX only supports DAT_SE0 USB mode */
+ /* This sequence is important */
+
+ /* Disable transparent UART mode first */
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ (ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR),
+ MC1_UART_EN);
+
+ /* Set full speed and SE0 mode */
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ (ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_MODE_CONTROL_1, (MC1_SPEED_REG | MC1_DAT_SE0));
+
+ /*
+ * The PSW_OE enable bit state is reversed in the ISP1301 User's Guide
+ */
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ (ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_SPD_SUSP_CTRL));
+
+ /* Driver VBUS_DRV high or low depending on board setup */
+ if (udc->board->vbus_drv_pol != 0)
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV);
+ else
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
+ OTG1_VBUS_DRV);
+
+ /* Bi-directional mode with suspend control
+ * Enable both pulldowns for now - the pullup will be enable when VBUS
+ * is detected */
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ (ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_OTG_CONTROL_1,
+ (0 | OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));
+
+ /* Discharge VBUS (just in case) */
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DISCHRG);
+ msleep(1);
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ (ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR),
+ OTG1_VBUS_DISCHRG);
+
+ /* Clear and enable VBUS high edge interrupt */
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_INTERRUPT_FALLING, INT_VBUS_VLD);
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_INTERRUPT_RISING, INT_VBUS_VLD);
+
+ /* Enable usb_need_clk clock after transceiver is initialized */
+ writel((readl(USB_CTRL) | (1 << 22)), USB_CTRL);
+
+ dev_info(udc->dev, "ISP1301 Vendor ID : 0x%04x\n",
+ i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00));
+ dev_info(udc->dev, "ISP1301 Product ID : 0x%04x\n",
+ i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x02));
+ dev_info(udc->dev, "ISP1301 Version ID : 0x%04x\n",
+ i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x14));
+}
+
+/* Enables or disables the USB device pullup via the ISP1301 transceiver */
+static void isp1301_pullup_set(struct lpc32xx_udc *udc)
+{
+ if (udc->pullup)
+ /* Enable pullup for bus signalling */
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_OTG_CONTROL_1, OTG1_DP_PULLUP);
+ else
+ /* Enable pullup for bus signalling */
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
+ OTG1_DP_PULLUP);
+}
+
+static void pullup_work(struct work_struct *work)
+{
+ struct lpc32xx_udc *udc =
+ container_of(work, struct lpc32xx_udc, pullup_job);
+
+ isp1301_pullup_set(udc);
+}
+
+static void isp1301_pullup_enable(struct lpc32xx_udc *udc, int en_pullup,
+ int block)
+{
+ if (en_pullup == udc->pullup)
+ return;
+
+ udc->pullup = en_pullup;
+ if (block)
+ isp1301_pullup_set(udc);
+ else
+ /* defer slow i2c pull up setting */
+ schedule_work(&udc->pullup_job);
+}
+
+#ifdef CONFIG_PM
+/* Powers up or down the ISP1301 transceiver */
+static void isp1301_set_powerstate(struct lpc32xx_udc *udc, int enable)
+{
+ if (enable != 0)
+ /* Power up ISP1301 - this ISP1301 will automatically wakeup
+ when VBUS is detected */
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR,
+ MC2_GLOBAL_PWR_DN);
+ else
+ /* Power down ISP1301 */
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
+}
+
+static void power_work(struct work_struct *work)
+{
+ struct lpc32xx_udc *udc =
+ container_of(work, struct lpc32xx_udc, power_job);
+
+ isp1301_set_powerstate(udc, udc->poweron);
+}
+#endif
+
+/*
+ *
+ * USB protocol engine command/data read/write helper functions
+ *
+ */
+/* Issues a single command to the USB device state machine */
+static void udc_protocol_cmd_w(struct lpc32xx_udc *udc, u32 cmd)
+{
+ u32 pass = 0;
+ int to;
+
+ /* EP may lock on CLRI if this read isn't done */
+ u32 tmp = readl(USBD_DEVINTST(udc->udp_baseaddr));
+ (void) tmp;
+
+ while (pass == 0) {
+ writel(USBD_CCEMPTY, USBD_DEVINTCLR(udc->udp_baseaddr));
+
+ /* Write command code */
+ writel(cmd, USBD_CMDCODE(udc->udp_baseaddr));
+ to = 10000;
+ while (((readl(USBD_DEVINTST(udc->udp_baseaddr)) &
+ USBD_CCEMPTY) == 0) && (to > 0)) {
+ to--;
+ }
+
+ if (to > 0)
+ pass = 1;
+
+ cpu_relax();
+ }
+}
+
+/* Issues 2 commands (or command and data) to the USB device state machine */
+static inline void udc_protocol_cmd_data_w(struct lpc32xx_udc *udc, u32 cmd,
+ u32 data)
+{
+ udc_protocol_cmd_w(udc, cmd);
+ udc_protocol_cmd_w(udc, data);
+}
+
+/* Issues a single command to the USB device state machine and reads
+ * response data */
+static u32 udc_protocol_cmd_r(struct lpc32xx_udc *udc, u32 cmd)
+{
+ u32 tmp;
+ int to = 1000;
+
+ /* Write a command and read data from the protocol engine */
+ writel((USBD_CDFULL | USBD_CCEMPTY),
+ USBD_DEVINTCLR(udc->udp_baseaddr));
+
+ /* Write command code */
+ udc_protocol_cmd_w(udc, cmd);
+
+ tmp = readl(USBD_DEVINTST(udc->udp_baseaddr));
+ while ((!(readl(USBD_DEVINTST(udc->udp_baseaddr)) & USBD_CDFULL))
+ && (to > 0))
+ to--;
+ if (!to)
+ dev_dbg(udc->dev,
+ "Protocol engine didn't receive response (CDFULL)\n");
+
+ return readl(USBD_CMDDATA(udc->udp_baseaddr));
+}
+
+/*
+ *
+ * USB device interrupt mask support functions
+ *
+ */
+/* Enable one or more USB device interrupts */
+static inline void uda_enable_devint(struct lpc32xx_udc *udc, u32 devmask)
+{
+ udc->enabled_devints |= devmask;
+ writel(udc->enabled_devints, USBD_DEVINTEN(udc->udp_baseaddr));
+}
+
+/* Disable one or more USB device interrupts */
+static inline void uda_disable_devint(struct lpc32xx_udc *udc, u32 mask)
+{
+ udc->enabled_devints &= ~mask;
+ writel(udc->enabled_devints, USBD_DEVINTEN(udc->udp_baseaddr));
+}
+
+/* Clear one or more USB device interrupts */
+static inline void uda_clear_devint(struct lpc32xx_udc *udc, u32 mask)
+{
+ writel(mask, USBD_DEVINTCLR(udc->udp_baseaddr));
+}
+
+/*
+ *
+ * Endpoint interrupt disable/enable functions
+ *
+ */
+/* Enable one or more USB endpoint interrupts */
+static void uda_enable_hwepint(struct lpc32xx_udc *udc, u32 hwep)
+{
+ udc->enabled_hwepints |= (1 << hwep);
+ writel(udc->enabled_hwepints, USBD_EPINTEN(udc->udp_baseaddr));
+}
+
+/* Disable one or more USB endpoint interrupts */
+static void uda_disable_hwepint(struct lpc32xx_udc *udc, u32 hwep)
+{
+ udc->enabled_hwepints &= ~(1 << hwep);
+ writel(udc->enabled_hwepints, USBD_EPINTEN(udc->udp_baseaddr));
+}
+
+/* Clear one or more USB endpoint interrupts */
+static inline void uda_clear_hwepint(struct lpc32xx_udc *udc, u32 hwep)
+{
+ writel((1 << hwep), USBD_EPINTCLR(udc->udp_baseaddr));
+}
+
+/* Enable DMA for the HW channel */
+static inline void udc_ep_dma_enable(struct lpc32xx_udc *udc, u32 hwep)
+{
+ writel((1 << hwep), USBD_EPDMAEN(udc->udp_baseaddr));
+}
+
+/* Disable DMA for the HW channel */
+static inline void udc_ep_dma_disable(struct lpc32xx_udc *udc, u32 hwep)
+{
+ writel((1 << hwep), USBD_EPDMADIS(udc->udp_baseaddr));
+}
+
+/*
+ *
+ * Endpoint realize/unrealize functions
+ *
+ */
+/* Before an endpoint can be used, it needs to be realized
+ * in the USB protocol engine - this realizes the endpoint.
+ * The interrupt (FIFO or DMA) is not enabled with this function */
+static void udc_realize_hwep(struct lpc32xx_udc *udc, u32 hwep,
+ u32 maxpacket)
+{
+ int to = 1000;
+
+ writel(USBD_EP_RLZED, USBD_DEVINTCLR(udc->udp_baseaddr));
+ writel(hwep, USBD_EPIND(udc->udp_baseaddr));
+ udc->realized_eps |= (1 << hwep);
+ writel(udc->realized_eps, USBD_REEP(udc->udp_baseaddr));
+ writel(maxpacket, USBD_EPMAXPSIZE(udc->udp_baseaddr));
+
+ /* Wait until endpoint is realized in hardware */
+ while ((!(readl(USBD_DEVINTST(udc->udp_baseaddr)) &
+ USBD_EP_RLZED)) && (to > 0))
+ to--;
+ if (!to)
+ dev_dbg(udc->dev, "EP not correctly realized in hardware\n");
+
+ writel(USBD_EP_RLZED, USBD_DEVINTCLR(udc->udp_baseaddr));
+}
+
+/* Unrealize an EP */
+static void udc_unrealize_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+ udc->realized_eps &= ~(1 << hwep);
+ writel(udc->realized_eps, USBD_REEP(udc->udp_baseaddr));
+}
+
+/*
+ *
+ * Endpoint support functions
+ *
+ */
+/* Select and clear endpoint interrupt */
+static u32 udc_selep_clrint(struct lpc32xx_udc *udc, u32 hwep)
+{
+ udc_protocol_cmd_w(udc, CMD_SEL_EP_CLRI(hwep));
+ return udc_protocol_cmd_r(udc, DAT_SEL_EP_CLRI(hwep));
+}
+
+/* Disables the endpoint in the USB protocol engine */
+static void udc_disable_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+ udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep),
+ DAT_WR_BYTE(EP_STAT_DA));
+}
+
+/* Stalls the endpoint - endpoint will return STALL */
+static void udc_stall_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+ udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep),
+ DAT_WR_BYTE(EP_STAT_ST));
+}
+
+/* Clear stall or reset endpoint */
+static void udc_clrstall_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+ udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep),
+ DAT_WR_BYTE(0));
+}
+
+/* Select an endpoint for endpoint status, clear, validate */
+static void udc_select_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+ udc_protocol_cmd_w(udc, CMD_SEL_EP(hwep));
+}
+
+/*
+ *
+ * Endpoint buffer management functions
+ *
+ */
+/* Clear the current endpoint's buffer */
+static void udc_clr_buffer_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+ udc_select_hwep(udc, hwep);
+ udc_protocol_cmd_w(udc, CMD_CLR_BUF);
+}
+
+/* Validate the current endpoint's buffer */
+static void udc_val_buffer_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+ udc_select_hwep(udc, hwep);
+ udc_protocol_cmd_w(udc, CMD_VALID_BUF);
+}
+
+static inline u32 udc_clearep_getsts(struct lpc32xx_udc *udc, u32 hwep)
+{
+ /* Clear EP interrupt */
+ uda_clear_hwepint(udc, hwep);
+ return udc_selep_clrint(udc, hwep);
+}
+
+/*
+ *
+ * USB EP DMA support
+ *
+ */
+/* Allocate a DMA Descriptor */
+static struct lpc32xx_usbd_dd_gad *udc_dd_alloc(struct lpc32xx_udc *udc)
+{
+ dma_addr_t dma;
+ struct lpc32xx_usbd_dd_gad *dd;
+
+ dd = (struct lpc32xx_usbd_dd_gad *) dma_pool_alloc(
+ udc->dd_cache, (GFP_KERNEL | GFP_DMA), &dma);
+ if (dd)
+ dd->this_dma = dma;
+
+ return dd;
+}
+
+/* Free a DMA Descriptor */
+static void udc_dd_free(struct lpc32xx_udc *udc, struct lpc32xx_usbd_dd_gad *dd)
+{
+ dma_pool_free(udc->dd_cache, dd, dd->this_dma);
+}
+
+/*
+ *
+ * USB setup and shutdown functions
+ *
+ */
+/* Enables or disables most of the USB system clocks when low power mode is
+ * needed. Clocks are typically started on a connection event, and disabled
+ * when a cable is disconnected */
+#define OTGOFF_CLK_MASK (AHB_M_CLOCK_ON | I2C_CLOCK_ON)
+static void udc_clk_set(struct lpc32xx_udc *udc, int enable)
+{
+ int to = 1000;
+
+ if (enable != 0) {
+ if (udc->clocked)
+ return;
+
+ udc->clocked = 1;
+
+ /* 48MHz PLL up */
+ clk_enable(udc->usb_pll_clk);
+
+ /* Enable the USB device clock */
+ writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN,
+ USB_CTRL);
+
+ /* Set to enable all needed USB OTG clocks */
+ writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL(udc));
+
+ while (((readl(USB_OTG_CLK_STAT(udc)) & USB_CLOCK_MASK) !=
+ USB_CLOCK_MASK) && (to > 0))
+ to--;
+ if (!to)
+ dev_dbg(udc->dev, "Cannot enable USB OTG clocking\n");
+ } else {
+ if (!udc->clocked)
+ return;
+
+ udc->clocked = 0;
+
+ /* Never disable the USB_HCLK during normal operation */
+
+ /* 48MHz PLL dpwn */
+ clk_disable(udc->usb_pll_clk);
+
+ /* Enable the USB device clock */
+ writel(readl(USB_CTRL) & ~USB_DEV_NEED_CLK_EN,
+ USB_CTRL);
+
+ /* Set to enable all needed USB OTG clocks */
+ writel(OTGOFF_CLK_MASK, USB_OTG_CLK_CTRL(udc));
+
+ while (((readl(USB_OTG_CLK_STAT(udc)) &
+ OTGOFF_CLK_MASK) !=
+ OTGOFF_CLK_MASK) && (to > 0))
+ to--;
+ if (!to)
+ dev_dbg(udc->dev, "Cannot disable USB OTG clocking\n");
+ }
+}
+
+/* Set/reset USB device address */
+static void udc_set_address(struct lpc32xx_udc *udc, u32 addr)
+{
+ /* Address will be latched at the end of the status phase, or
+ latched immediately if function is called twice */
+ udc_protocol_cmd_data_w(udc, CMD_SET_ADDR,
+ DAT_WR_BYTE(DEV_EN | addr));
+}
+
+/* Setup up a IN request for DMA transfer - this consists of determining the
+ * list of DMA addresses for the transfer, allocating DMA Descriptors,
+ * installing the DD into the UDCA, and then enabling the DMA for that EP */
+static int udc_ep_in_req_dma(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
+{
+ struct lpc32xx_request *req;
+ u32 hwep = ep->hwep_num;
+
+ ep->req_pending = 1;
+
+ /* There will always be a request waiting here */
+ req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
+
+ /* Place the DD Descriptor into the UDCA */
+ udc->udca_v_base[hwep] = req->dd_desc_ptr->this_dma;
+
+ /* Enable DMA and interrupt for the HW EP */
+ udc_ep_dma_enable(udc, hwep);
+
+ /* Clear ZLP if last packet is not of MAXP size */
+ if (req->req.length % ep->ep.maxpacket)
+ req->send_zlp = 0;
+
+ return 0;
+}
+
+/* Setup up a OUT request for DMA transfer - this consists of determining the
+ * list of DMA addresses for the transfer, allocating DMA Descriptors,
+ * installing the DD into the UDCA, and then enabling the DMA for that EP */
+static int udc_ep_out_req_dma(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
+{
+ struct lpc32xx_request *req;
+ u32 hwep = ep->hwep_num;
+
+ ep->req_pending = 1;
+
+ /* There will always be a request waiting here */
+ req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
+
+ /* Place the DD Descriptor into the UDCA */
+ udc->udca_v_base[hwep] = req->dd_desc_ptr->this_dma;
+
+ /* Enable DMA and interrupt for the HW EP */
+ udc_ep_dma_enable(udc, hwep);
+ return 0;
+}
+
+static void udc_disable(struct lpc32xx_udc *udc)
+{
+ u32 i;
+
+ /* Disable device */
+ udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(0));
+ udc_protocol_cmd_data_w(udc, CMD_SET_DEV_STAT, DAT_WR_BYTE(0));
+
+ /* Disable all device interrupts (including EP0) */
+ uda_disable_devint(udc, 0x3FF);
+
+ /* Disable and reset all endpoint interrupts */
+ for (i = 0; i < 32; i++) {
+ uda_disable_hwepint(udc, i);
+ uda_clear_hwepint(udc, i);
+ udc_disable_hwep(udc, i);
+ udc_unrealize_hwep(udc, i);
+ udc->udca_v_base[i] = 0;
+
+ /* Disable and clear all interrupts and DMA */
+ udc_ep_dma_disable(udc, i);
+ writel((1 << i), USBD_EOTINTCLR(udc->udp_baseaddr));
+ writel((1 << i), USBD_NDDRTINTCLR(udc->udp_baseaddr));
+ writel((1 << i), USBD_SYSERRTINTCLR(udc->udp_baseaddr));
+ writel((1 << i), USBD_DMARCLR(udc->udp_baseaddr));
+ }
+
+ /* Disable DMA interrupts */
+ writel(0, USBD_DMAINTEN(udc->udp_baseaddr));
+
+ writel(0, USBD_UDCAH(udc->udp_baseaddr));
+}
+
+static void udc_enable(struct lpc32xx_udc *udc)
+{
+ u32 i;
+ struct lpc32xx_ep *ep = &udc->ep[0];
+
+ /* Start with known state */
+ udc_disable(udc);
+
+ /* Enable device */
+ udc_protocol_cmd_data_w(udc, CMD_SET_DEV_STAT, DAT_WR_BYTE(DEV_CON));
+
+ /* EP interrupts on high priority, FRAME interrupt on low priority */
+ writel(USBD_EP_FAST, USBD_DEVINTPRI(udc->udp_baseaddr));
+ writel(0xFFFF, USBD_EPINTPRI(udc->udp_baseaddr));
+
+ /* Clear any pending device interrupts */
+ writel(0x3FF, USBD_DEVINTCLR(udc->udp_baseaddr));
+
+ /* Setup UDCA - not yet used (DMA) */
+ writel(udc->udca_p_base, USBD_UDCAH(udc->udp_baseaddr));
+
+ /* Only enable EP0 in and out for now, EP0 only works in FIFO mode */
+ for (i = 0; i <= 1; i++) {
+ udc_realize_hwep(udc, i, ep->ep.maxpacket);
+ uda_enable_hwepint(udc, i);
+ udc_select_hwep(udc, i);
+ udc_clrstall_hwep(udc, i);
+ udc_clr_buffer_hwep(udc, i);
+ }
+
+ /* Device interrupt setup */
+ uda_clear_devint(udc, (USBD_ERR_INT | USBD_DEV_STAT | USBD_EP_SLOW |
+ USBD_EP_FAST));
+ uda_enable_devint(udc, (USBD_ERR_INT | USBD_DEV_STAT | USBD_EP_SLOW |
+ USBD_EP_FAST));
+
+ /* Set device address to 0 - called twice to force a latch in the USB
+ engine without the need of a setup packet status closure */
+ udc_set_address(udc, 0);
+ udc_set_address(udc, 0);
+
+ /* Enable master DMA interrupts */
+ writel((USBD_SYS_ERR_INT | USBD_EOT_INT),
+ USBD_DMAINTEN(udc->udp_baseaddr));
+
+ udc->dev_status = 0;
+}
+
+/*
+ *
+ * USB device board specific events handled via callbacks
+ *
+ */
+/* Connection change event - notify board function of change */
+static void uda_power_event(struct lpc32xx_udc *udc, u32 conn)
+{
+ /* Just notify of a connection change event (optional) */
+ if (udc->board->conn_chgb != NULL)
+ udc->board->conn_chgb(conn);
+}
+
+/* Suspend/resume event - notify board function of change */
+static void uda_resm_susp_event(struct lpc32xx_udc *udc, u32 conn)
+{
+ /* Just notify of a Suspend/resume change event (optional) */
+ if (udc->board->susp_chgb != NULL)
+ udc->board->susp_chgb(conn);
+
+ if (conn)
+ udc->suspended = 0;
+ else
+ udc->suspended = 1;
+}
+
+/* Remote wakeup enable/disable - notify board function of change */
+static void uda_remwkp_cgh(struct lpc32xx_udc *udc)
+{
+ if (udc->board->rmwk_chgb != NULL)
+ udc->board->rmwk_chgb(udc->dev_status &
+ (1 << USB_DEVICE_REMOTE_WAKEUP));
+}
+
+/* Reads data from FIFO, adjusts for alignment and data size */
+static void udc_pop_fifo(struct lpc32xx_udc *udc, u8 *data, u32 bytes)
+{
+ int n, i, bl;
+ u16 *p16;
+ u32 *p32, tmp, cbytes;
+
+ /* Use optimal data transfer method based on source address and size */
+ switch (((u32) data) & 0x3) {
+ case 0: /* 32-bit aligned */
+ p32 = (u32 *) data;
+ cbytes = (bytes & ~0x3);
+
+ /* Copy 32-bit aligned data first */
+ for (n = 0; n < cbytes; n += 4)
+ *p32++ = readl(USBD_RXDATA(udc->udp_baseaddr));
+
+ /* Handle any remaining bytes */
+ bl = bytes - cbytes;
+ if (bl) {
+ tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
+ for (n = 0; n < bl; n++)
+ data[cbytes + n] = ((tmp >> (n * 8)) & 0xFF);
+
+ }
+ break;
+
+ case 1: /* 8-bit aligned */
+ case 3:
+ /* Each byte has to be handled independently */
+ for (n = 0; n < bytes; n += 4) {
+ tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
+
+ bl = bytes - n;
+ if (bl > 3)
+ bl = 3;
+
+ for (i = 0; i < bl; i++)
+ data[n + i] = (u8) ((tmp >> (n * 8)) & 0xFF);
+ }
+ break;
+
+ case 2: /* 16-bit aligned */
+ p16 = (u16 *) data;
+ cbytes = (bytes & ~0x3);
+
+ /* Copy 32-bit sized objects first with 16-bit alignment */
+ for (n = 0; n < cbytes; n += 4) {
+ tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
+ *p16++ = (u16)(tmp & 0xFFFF);
+ *p16++ = (u16)((tmp >> 16) & 0xFFFF);
+ }
+
+ /* Handle any remaining bytes */
+ bl = bytes - cbytes;
+ if (bl) {
+ tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
+ for (n = 0; n < bl; n++)
+ data[cbytes + n] = ((tmp >> (n * 8)) & 0xFF);
+ }
+ break;
+ }
+}
+
+/* Read data from the FIFO for an endpoint. This function is for endpoints (such
+ * as EP0) that don't use DMA. This function should only be called if a packet
+ * is known to be ready to read for the endpoint. Note that the endpoint must
+ * be selected in the protocol engine prior to this call. */
+static u32 udc_read_hwep(struct lpc32xx_udc *udc, u32 hwep, u32 *data,
+ u32 bytes)
+{
+ u32 tmpv;
+ int to = 1000;
+ u32 tmp, hwrep = ((hwep & 0x1E) << 1) | CTRL_RD_EN;
+
+ /* Setup read of endpoint */
+ writel(hwrep, USBD_CTRL(udc->udp_baseaddr));
+
+ /* Wait until packet is ready */
+ while ((((tmpv = readl(USBD_RXPLEN(udc->udp_baseaddr))) &
+ PKT_RDY) == 0) && (to > 0))
+ to--;
+ if (!to)
+ dev_dbg(udc->dev, "No packet ready on FIFO EP read\n");
+
+ /* Mask out count */
+ tmp = tmpv & PKT_LNGTH_MASK;
+ if (bytes < tmp)
+ tmp = bytes;
+
+ if ((tmp > 0) && (data != NULL))
+ udc_pop_fifo(udc, (u8 *) data, tmp);
+
+ writel(((hwep & 0x1E) << 1), USBD_CTRL(udc->udp_baseaddr));
+
+ /* Clear the buffer */
+ udc_clr_buffer_hwep(udc, hwep);
+
+ return tmp;
+}
+
+/* Stuffs data into the FIFO, adjusts for alignment and data size */
+static void udc_stuff_fifo(struct lpc32xx_udc *udc, u8 *data, u32 bytes)
+{
+ int n, i, bl;
+ u16 *p16;
+ u32 *p32, tmp, cbytes;
+
+ /* Use optimal data transfer method based on source address and size */
+ switch (((u32) data) & 0x3) {
+ case 0: /* 32-bit aligned */
+ p32 = (u32 *) data;
+ cbytes = (bytes & ~0x3);
+
+ /* Copy 32-bit aligned data first */
+ for (n = 0; n < cbytes; n += 4)
+ writel(*p32++, USBD_TXDATA(udc->udp_baseaddr));
+
+ /* Handle any remaining bytes */
+ bl = bytes - cbytes;
+ if (bl) {
+ tmp = 0;
+ for (n = 0; n < bl; n++)
+ tmp |= data[cbytes + n] << (n * 8);
+
+ writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
+ }
+ break;
+
+ case 1: /* 8-bit aligned */
+ case 3:
+ /* Each byte has to be handled independently */
+ for (n = 0; n < bytes; n += 4) {
+ bl = bytes - n;
+ if (bl > 4)
+ bl = 4;
+
+ tmp = 0;
+ for (i = 0; i < bl; i++)
+ tmp |= data[n + i] << (i * 8);
+
+ writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
+ }
+ break;
+
+ case 2: /* 16-bit aligned */
+ p16 = (u16 *) data;
+ cbytes = (bytes & ~0x3);
+
+ /* Copy 32-bit aligned data first */
+ for (n = 0; n < cbytes; n += 4) {
+ tmp = *p16++ & 0xFFFF;
+ tmp |= (*p16++ & 0xFFFF) << 16;
+ writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
+ }
+
+ /* Handle any remaining bytes */
+ bl = bytes - cbytes;
+ if (bl) {
+ tmp = 0;
+ for (n = 0; n < bl; n++)
+ tmp |= data[cbytes + n] << (n * 8);
+
+ writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
+ }
+ break;
+ }
+}
+
+/* Write data to the FIFO for an endpoint. This function is for endpoints (such
+ * as EP0) that don't use DMA. Note that the endpoint must be selected in the
+ * protocol engine prior to this call. */
+static void udc_write_hwep(struct lpc32xx_udc *udc, u32 hwep, u32 *data,
+ u32 bytes)
+{
+ u32 hwwep = ((hwep & 0x1E) << 1) | CTRL_WR_EN;
+
+ if ((bytes > 0) && (data == NULL))
+ return;
+
+ /* Setup write of endpoint */
+ writel(hwwep, USBD_CTRL(udc->udp_baseaddr));
+
+ writel(bytes, USBD_TXPLEN(udc->udp_baseaddr));
+
+ /* Need at least 1 byte to trigger TX */
+ if (bytes == 0)
+ writel(0, USBD_TXDATA(udc->udp_baseaddr));
+ else
+ udc_stuff_fifo(udc, (u8 *) data, bytes);
+
+ writel(((hwep & 0x1E) << 1), USBD_CTRL(udc->udp_baseaddr));
+
+ udc_val_buffer_hwep(udc, hwep);
+}
+
+/* USB device reset - resets USB to a default state with just EP0
+ enabled */
+static void uda_usb_reset(struct lpc32xx_udc *udc)
+{
+ u32 i = 0;
+ /* Re-init device controller and EP0 */
+ udc_enable(udc);
+ udc->gadget.speed = USB_SPEED_FULL;
+
+ for (i = 1; i < NUM_ENDPOINTS; i++) {
+ struct lpc32xx_ep *ep = &udc->ep[i];
+ ep->req_pending = 0;
+ }
+}
+
+/* Send a ZLP on EP0 */
+static void udc_ep0_send_zlp(struct lpc32xx_udc *udc)
+{
+ udc_write_hwep(udc, EP_IN, NULL, 0);
+}
+
+/* Get current frame number */
+static u16 udc_get_current_frame(struct lpc32xx_udc *udc)
+{
+ u16 flo, fhi;
+
+ udc_protocol_cmd_w(udc, CMD_RD_FRAME);
+ flo = (u16) udc_protocol_cmd_r(udc, DAT_RD_FRAME);
+ fhi = (u16) udc_protocol_cmd_r(udc, DAT_RD_FRAME);
+
+ return (fhi << 8) | flo;
+}
+
+/* Set the device as configured - enables all endpoints */
+static inline void udc_set_device_configured(struct lpc32xx_udc *udc)
+{
+ udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(CONF_DVICE));
+}
+
+/* Set the device as unconfigured - disables all endpoints */
+static inline void udc_set_device_unconfigured(struct lpc32xx_udc *udc)
+{
+ udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(0));
+}
+
+/* reinit == restore initial software state */
+static void udc_reinit(struct lpc32xx_udc *udc)
+{
+ u32 i;
+
+ INIT_LIST_HEAD(&udc->gadget.ep_list);
+ INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
+
+ for (i = 0; i < NUM_ENDPOINTS; i++) {
+ struct lpc32xx_ep *ep = &udc->ep[i];
+
+ if (i != 0)
+ list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+ ep->desc = NULL;
+ ep->ep.maxpacket = ep->maxpacket;
+ INIT_LIST_HEAD(&ep->queue);
+ ep->req_pending = 0;
+ }
+
+ udc->ep0state = WAIT_FOR_SETUP;
+}
+
+/* Must be called with lock */
+static void done(struct lpc32xx_ep *ep, struct lpc32xx_request *req, int status)
+{
+ struct lpc32xx_udc *udc = ep->udc;
+
+ list_del_init(&req->queue);
+ if (req->req.status == -EINPROGRESS)
+ req->req.status = status;
+ else
+ status = req->req.status;
+
+ if (ep->lep) {
+ enum dma_data_direction direction;
+
+ if (ep->is_in)
+ direction = DMA_TO_DEVICE;
+ else
+ direction = DMA_FROM_DEVICE;
+
+ if (req->mapped) {
+ dma_unmap_single(ep->udc->gadget.dev.parent,
+ req->req.dma, req->req.length,
+ direction);
+ req->req.dma = 0;
+ req->mapped = 0;
+ } else
+ dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
+ req->req.dma, req->req.length,
+ direction);
+
+ /* Free DDs */
+ udc_dd_free(udc, req->dd_desc_ptr);
+ }
+
+ if (status && status != -ESHUTDOWN)
+ ep_dbg(ep, "%s done %p, status %d\n", ep->ep.name, req, status);
+
+ ep->req_pending = 0;
+ spin_unlock(&udc->lock);
+ req->req.complete(&ep->ep, &req->req);
+ spin_lock(&udc->lock);
+}
+
+/* Must be called with lock */
+static void nuke(struct lpc32xx_ep *ep, int status)
+{
+ struct lpc32xx_request *req;
+
+ while (!list_empty(&ep->queue)) {
+ req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
+ done(ep, req, status);
+ }
+
+ if (ep->desc && status == -ESHUTDOWN) {
+ uda_disable_hwepint(ep->udc, ep->hwep_num);
+ udc_disable_hwep(ep->udc, ep->hwep_num);
+ }
+}
+
+/* IN endpoint 0 transfer */
+static int udc_ep0_in_req(struct lpc32xx_udc *udc)
+{
+ struct lpc32xx_request *req;
+ struct lpc32xx_ep *ep0 = &udc->ep[0];
+ u32 tsend, ts = 0;
+
+ if (list_empty(&ep0->queue))
+ /* Nothing to send */
+ return 0;
+ else
+ req = list_entry(ep0->queue.next, struct lpc32xx_request,
+ queue);
+
+ tsend = ts = req->req.length - req->req.actual;
+ if (ts == 0) {
+ /* Send a ZLP */
+ udc_ep0_send_zlp(udc);
+ done(ep0, req, 0);
+ return 1;
+ } else if (ts > ep0->ep.maxpacket)
+ ts = ep0->ep.maxpacket; /* Just send what we can */
+
+ /* Write data to the EP0 FIFO and start transfer */
+ udc_write_hwep(udc, EP_IN, (req->req.buf + req->req.actual), ts);
+
+ /* Increment data pointer */
+ req->req.actual += ts;
+
+ if (tsend >= ep0->ep.maxpacket)
+ return 0; /* Stay in data transfer state */
+
+ /* Transfer request is complete */
+ udc->ep0state = WAIT_FOR_SETUP;
+ done(ep0, req, 0);
+ return 1;
+}
+
+/* OUT endpoint 0 transfer */
+static int udc_ep0_out_req(struct lpc32xx_udc *udc)
+{
+ struct lpc32xx_request *req;
+ struct lpc32xx_ep *ep0 = &udc->ep[0];
+ u32 tr, bufferspace;
+
+ if (list_empty(&ep0->queue))
+ return 0;
+ else
+ req = list_entry(ep0->queue.next, struct lpc32xx_request,
+ queue);
+
+ if (req) {
+ if (req->req.length == 0) {
+ /* Just dequeue request */
+ done(ep0, req, 0);
+ udc->ep0state = WAIT_FOR_SETUP;
+ return 1;
+ }
+
+ /* Get data from FIFO */
+ bufferspace = req->req.length - req->req.actual;
+ if (bufferspace > ep0->ep.maxpacket)
+ bufferspace = ep0->ep.maxpacket;
+
+ /* Copy data to buffer */
+ prefetchw(req->req.buf + req->req.actual);
+ tr = udc_read_hwep(udc, EP_OUT, req->req.buf + req->req.actual,
+ bufferspace);
+ req->req.actual += bufferspace;
+
+ if (tr < ep0->ep.maxpacket) {
+ /* This is the last packet */
+ done(ep0, req, 0);
+ udc->ep0state = WAIT_FOR_SETUP;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Must be called with lock */
+static void stop_activity(struct lpc32xx_udc *udc)
+{
+ struct usb_gadget_driver *driver = udc->driver;
+ int i;
+
+ if (udc->gadget.speed == USB_SPEED_UNKNOWN)
+ driver = NULL;
+
+ udc->gadget.speed = USB_SPEED_UNKNOWN;
+ udc->suspended = 0;
+
+ for (i = 0; i < NUM_ENDPOINTS; i++) {
+ struct lpc32xx_ep *ep = &udc->ep[i];
+ nuke(ep, -ESHUTDOWN);
+ }
+ if (driver) {
+ spin_unlock(&udc->lock);
+ driver->disconnect(&udc->gadget);
+ spin_lock(&udc->lock);
+ }
+
+ isp1301_pullup_enable(udc, 0, 0);
+ udc_disable(udc);
+ udc_reinit(udc);
+}
+
+/*
+ * Activate or kill host pullup
+ * Can be called with or without lock
+ */
+static void pullup(struct lpc32xx_udc *udc, int is_on)
+{
+ if (!udc->clocked)
+ return;
+
+ if (!udc->enabled || !udc->vbus)
+ is_on = 0;
+
+ if (is_on != udc->pullup)
+ isp1301_pullup_enable(udc, is_on, 0);
+}
+
+/* Must be called without lock */
+static int lpc32xx_ep_disable(struct usb_ep *_ep)
+{
+ struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
+ struct lpc32xx_udc *udc = ep->udc;
+ unsigned long flags;
+
+ if ((ep->hwep_num_base == 0) || (ep->hwep_num == 0))
+ return -EINVAL;
+ spin_lock_irqsave(&udc->lock, flags);
+
+ nuke(ep, -ESHUTDOWN);
+
+ /* restore the endpoint's pristine config */
+ ep->desc = NULL;
+
+ /* Clear all DMA statuses for this EP */
+ udc_ep_dma_disable(udc, ep->hwep_num);
+ writel(1 << ep->hwep_num, USBD_EOTINTCLR(udc->udp_baseaddr));
+ writel(1 << ep->hwep_num, USBD_NDDRTINTCLR(udc->udp_baseaddr));
+ writel(1 << ep->hwep_num, USBD_SYSERRTINTCLR(udc->udp_baseaddr));
+ writel(1 << ep->hwep_num, USBD_DMARCLR(udc->udp_baseaddr));
+
+ /* Remove the DD pointer in the UDCA */
+ udc->udca_v_base[ep->hwep_num] = 0;
+
+ /* Disable and reset endpoint and interrupt */
+ uda_clear_hwepint(udc, ep->hwep_num);
+ udc_unrealize_hwep(udc, ep->hwep_num);
+
+ ep->hwep_num = 0;
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ atomic_dec(&udc->enabled_ep_cnt);
+ wake_up(&udc->ep_disable_wait_queue);
+
+ return 0;
+}
+
+/* Must be called without lock */
+static int lpc32xx_ep_enable(struct usb_ep *_ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
+ struct lpc32xx_udc *udc = ep->udc;
+ u16 maxpacket;
+ u32 tmp;
+ unsigned long flags;
+
+ /* Verify EP data */
+ if ((!_ep) || (!ep) || (!desc) || (ep->desc) ||
+ (desc->bDescriptorType != USB_DT_ENDPOINT)) {
+ dev_dbg(udc->dev, "bad ep or descriptor\n");
+ return -EINVAL;
+ }
+ maxpacket = usb_endpoint_maxp(desc);
+ if ((maxpacket == 0) || (maxpacket > ep->maxpacket)) {
+ dev_dbg(udc->dev, "bad ep descriptor's packet size\n");
+ return -EINVAL;
+ }
+
+ /* Don't touch EP0 */
+ if (ep->hwep_num_base == 0) {
+ dev_dbg(udc->dev, "Can't re-enable EP0!!!\n");
+ return -EINVAL;
+ }
+
+ /* Is driver ready? */
+ if ((!udc->driver) || (udc->gadget.speed == USB_SPEED_UNKNOWN)) {
+ dev_dbg(udc->dev, "bogus device state\n");
+ return -ESHUTDOWN;
+ }
+
+ tmp = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+ switch (tmp) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ return -EINVAL;
+
+ case USB_ENDPOINT_XFER_INT:
+ if (maxpacket > ep->maxpacket) {
+ dev_dbg(udc->dev,
+ "Bad INT endpoint maxpacket %d\n", maxpacket);
+ return -EINVAL;
+ }
+ break;
+
+ case USB_ENDPOINT_XFER_BULK:
+ switch (maxpacket) {
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ break;
+
+ default:
+ dev_dbg(udc->dev,
+ "Bad BULK endpoint maxpacket %d\n", maxpacket);
+ return -EINVAL;
+ }
+ break;
+
+ case USB_ENDPOINT_XFER_ISOC:
+ break;
+ }
+ spin_lock_irqsave(&udc->lock, flags);
+
+ /* Initialize endpoint to match the selected descriptor */
+ ep->is_in = (desc->bEndpointAddress & USB_DIR_IN) != 0;
+ ep->desc = desc;
+ ep->ep.maxpacket = maxpacket;
+
+ /* Map hardware endpoint from base and direction */
+ if (ep->is_in)
+ /* IN endpoints are offset 1 from the OUT endpoint */
+ ep->hwep_num = ep->hwep_num_base + EP_IN;
+ else
+ ep->hwep_num = ep->hwep_num_base;
+
+ ep_dbg(ep, "EP enabled: %s, HW:%d, MP:%d IN:%d\n", ep->ep.name,
+ ep->hwep_num, maxpacket, (ep->is_in == 1));
+
+ /* Realize the endpoint, interrupt is enabled later when
+ * buffers are queued, IN EPs will NAK until buffers are ready */
+ udc_realize_hwep(udc, ep->hwep_num, ep->ep.maxpacket);
+ udc_clr_buffer_hwep(udc, ep->hwep_num);
+ uda_disable_hwepint(udc, ep->hwep_num);
+ udc_clrstall_hwep(udc, ep->hwep_num);
+
+ /* Clear all DMA statuses for this EP */
+ udc_ep_dma_disable(udc, ep->hwep_num);
+ writel(1 << ep->hwep_num, USBD_EOTINTCLR(udc->udp_baseaddr));
+ writel(1 << ep->hwep_num, USBD_NDDRTINTCLR(udc->udp_baseaddr));
+ writel(1 << ep->hwep_num, USBD_SYSERRTINTCLR(udc->udp_baseaddr));
+ writel(1 << ep->hwep_num, USBD_DMARCLR(udc->udp_baseaddr));
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ atomic_inc(&udc->enabled_ep_cnt);
+ return 0;
+}
+
+/*
+ * Allocate a USB request list
+ * Can be called with or without lock
+ */
+static struct usb_request *lpc32xx_ep_alloc_request(struct usb_ep *_ep,
+ gfp_t gfp_flags)
+{
+ struct lpc32xx_request *req;
+
+ req = kzalloc(sizeof(struct lpc32xx_request), gfp_flags);
+ if (!req)
+ return NULL;
+
+ INIT_LIST_HEAD(&req->queue);
+ return &req->req;
+}
+
+/*
+ * De-allocate a USB request list
+ * Can be called with or without lock
+ */
+static void lpc32xx_ep_free_request(struct usb_ep *_ep,
+ struct usb_request *_req)
+{
+ struct lpc32xx_request *req;
+
+ req = container_of(_req, struct lpc32xx_request, req);
+ BUG_ON(!list_empty(&req->queue));
+ kfree(req);
+}
+
+/* Must be called without lock */
+static int lpc32xx_ep_queue(struct usb_ep *_ep,
+ struct usb_request *_req, gfp_t gfp_flags)
+{
+ struct lpc32xx_request *req;
+ struct lpc32xx_ep *ep;
+ struct lpc32xx_udc *udc;
+ unsigned long flags;
+ int status = 0;
+
+ req = container_of(_req, struct lpc32xx_request, req);
+ ep = container_of(_ep, struct lpc32xx_ep, ep);
+
+ if (!_req || !_req->complete || !_req->buf ||
+ !list_empty(&req->queue))
+ return -EINVAL;
+
+ udc = ep->udc;
+
+ if (!_ep || (!ep->desc && ep->hwep_num_base != 0)) {
+ dev_dbg(udc->dev, "invalid ep\n");
+ return -EINVAL;
+ }
+
+
+ if ((!udc) || (!udc->driver) ||
+ (udc->gadget.speed == USB_SPEED_UNKNOWN)) {
+ dev_dbg(udc->dev, "invalid device\n");
+ return -EINVAL;
+ }
+
+ if (ep->lep) {
+ enum dma_data_direction direction;
+ struct lpc32xx_usbd_dd_gad *dd;
+
+ /* Map DMA pointer */
+ if (ep->is_in)
+ direction = DMA_TO_DEVICE;
+ else
+ direction = DMA_FROM_DEVICE;
+
+ if (req->req.dma == 0) {
+ req->req.dma = dma_map_single(
+ ep->udc->gadget.dev.parent,
+ req->req.buf, req->req.length, direction);
+ req->mapped = 1;
+ } else {
+ dma_sync_single_for_device(
+ ep->udc->gadget.dev.parent, req->req.dma,
+ req->req.length, direction);
+ req->mapped = 0;
+ }
+
+ /* For the request, build a list of DDs */
+ dd = udc_dd_alloc(udc);
+ if (!dd) {
+ /* Error allocating DD */
+ return -ENOMEM;
+ }
+ req->dd_desc_ptr = dd;
+
+ /* Setup the DMA descriptor */
+ dd->dd_next_phy = dd->dd_next_v = 0;
+ dd->dd_buffer_addr = req->req.dma;
+ dd->dd_status = 0;
+
+ /* Special handling for ISO EPs */
+ if (ep->eptype == EP_ISO_TYPE) {
+ dd->dd_setup = DD_SETUP_ISO_EP |
+ DD_SETUP_PACKETLEN(0) |
+ DD_SETUP_DMALENBYTES(1);
+ dd->dd_iso_ps_mem_addr = dd->this_dma + 24;
+ if (ep->is_in)
+ dd->iso_status[0] = req->req.length;
+ else
+ dd->iso_status[0] = 0;
+ } else
+ dd->dd_setup = DD_SETUP_PACKETLEN(ep->ep.maxpacket) |
+ DD_SETUP_DMALENBYTES(req->req.length);
+ }
+
+ ep_dbg(ep, "%s queue req %p len %d buf %p (in=%d) z=%d\n", _ep->name,
+ _req, _req->length, _req->buf, ep->is_in, _req->zero);
+
+ spin_lock_irqsave(&udc->lock, flags);
+
+ _req->status = -EINPROGRESS;
+ _req->actual = 0;
+ req->send_zlp = _req->zero;
+
+ /* Kickstart empty queues */
+ if (list_empty(&ep->queue)) {
+ list_add_tail(&req->queue, &ep->queue);
+
+ if (ep->hwep_num_base == 0) {
+ /* Handle expected data direction */
+ if (ep->is_in) {
+ /* IN packet to host */
+ udc->ep0state = DATA_IN;
+ status = udc_ep0_in_req(udc);
+ } else {
+ /* OUT packet from host */
+ udc->ep0state = DATA_OUT;
+ status = udc_ep0_out_req(udc);
+ }
+ } else if (ep->is_in) {
+ /* IN packet to host and kick off transfer */
+ if (!ep->req_pending)
+ udc_ep_in_req_dma(udc, ep);
+ } else
+ /* OUT packet from host and kick off list */
+ if (!ep->req_pending)
+ udc_ep_out_req_dma(udc, ep);
+ } else
+ list_add_tail(&req->queue, &ep->queue);
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ return (status < 0) ? status : 0;
+}
+
+/* Must be called without lock */
+static int lpc32xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct lpc32xx_ep *ep;
+ struct lpc32xx_request *req;
+ unsigned long flags;
+
+ ep = container_of(_ep, struct lpc32xx_ep, ep);
+ if (!_ep || ep->hwep_num_base == 0)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ep->udc->lock, flags);
+
+ /* make sure it's actually queued on this endpoint */
+ list_for_each_entry(req, &ep->queue, queue) {
+ if (&req->req == _req)
+ break;
+ }
+ if (&req->req != _req) {
+ spin_unlock_irqrestore(&ep->udc->lock, flags);
+ return -EINVAL;
+ }
+
+ done(ep, req, -ECONNRESET);
+
+ spin_unlock_irqrestore(&ep->udc->lock, flags);
+
+ return 0;
+}
+
+/* Must be called without lock */
+static int lpc32xx_ep_set_halt(struct usb_ep *_ep, int value)
+{
+ struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
+ struct lpc32xx_udc *udc = ep->udc;
+ unsigned long flags;
+
+ if ((!ep) || (ep->desc == NULL) || (ep->hwep_num <= 1))
+ return -EINVAL;
+
+ /* Don't halt an IN EP */
+ if (ep->is_in)
+ return -EAGAIN;
+
+ spin_lock_irqsave(&udc->lock, flags);
+
+ if (value == 1) {
+ /* stall */
+ udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(ep->hwep_num),
+ DAT_WR_BYTE(EP_STAT_ST));
+ } else {
+ /* End stall */
+ ep->wedge = 0;
+ udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(ep->hwep_num),
+ DAT_WR_BYTE(0));
+ }
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ return 0;
+}
+
+/* set the halt feature and ignores clear requests */
+static int lpc32xx_ep_set_wedge(struct usb_ep *_ep)
+{
+ struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
+
+ if (!_ep || !ep->udc)
+ return -EINVAL;
+
+ ep->wedge = 1;
+
+ return usb_ep_set_halt(_ep);
+}
+
+static const struct usb_ep_ops lpc32xx_ep_ops = {
+ .enable = lpc32xx_ep_enable,
+ .disable = lpc32xx_ep_disable,
+ .alloc_request = lpc32xx_ep_alloc_request,
+ .free_request = lpc32xx_ep_free_request,
+ .queue = lpc32xx_ep_queue,
+ .dequeue = lpc32xx_ep_dequeue,
+ .set_halt = lpc32xx_ep_set_halt,
+ .set_wedge = lpc32xx_ep_set_wedge,
+};
+
+/* Send a ZLP on a non-0 IN EP */
+void udc_send_in_zlp(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
+{
+ /* Clear EP status */
+ udc_clearep_getsts(udc, ep->hwep_num);
+
+ /* Send ZLP via FIFO mechanism */
+ udc_write_hwep(udc, ep->hwep_num, NULL, 0);
+}
+
+/*
+ * Handle EP completion for ZLP
+ * This function will only be called when a delayed ZLP needs to be sent out
+ * after a DMA transfer has filled both buffers.
+ */
+void udc_handle_eps(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
+{
+ u32 epstatus;
+ struct lpc32xx_request *req;
+
+ if (ep->hwep_num <= 0)
+ return;
+
+ uda_clear_hwepint(udc, ep->hwep_num);
+
+ /* If this interrupt isn't enabled, return now */
+ if (!(udc->enabled_hwepints & (1 << ep->hwep_num)))
+ return;
+
+ /* Get endpoint status */
+ epstatus = udc_clearep_getsts(udc, ep->hwep_num);
+
+ /*
+ * This should never happen, but protect against writing to the
+ * buffer when full.
+ */
+ if (epstatus & EP_SEL_F)
+ return;
+
+ if (ep->is_in) {
+ udc_send_in_zlp(udc, ep);
+ uda_disable_hwepint(udc, ep->hwep_num);
+ } else
+ return;
+
+ /* If there isn't a request waiting, something went wrong */
+ req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
+ if (req) {
+ done(ep, req, 0);
+
+ /* Start another request if ready */
+ if (!list_empty(&ep->queue)) {
+ if (ep->is_in)
+ udc_ep_in_req_dma(udc, ep);
+ else
+ udc_ep_out_req_dma(udc, ep);
+ } else
+ ep->req_pending = 0;
+ }
+}
+
+
+/* DMA end of transfer completion */
+static void udc_handle_dma_ep(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
+{
+ u32 status, epstatus;
+ struct lpc32xx_request *req;
+ struct lpc32xx_usbd_dd_gad *dd;
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+ ep->totalints++;
+#endif
+
+ req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
+ if (!req) {
+ ep_err(ep, "DMA interrupt on no req!\n");
+ return;
+ }
+ dd = req->dd_desc_ptr;
+
+ /* DMA descriptor should always be retired for this call */
+ if (!(dd->dd_status & DD_STATUS_DD_RETIRED))
+ ep_warn(ep, "DMA descriptor did not retire\n");
+
+ /* Disable DMA */
+ udc_ep_dma_disable(udc, ep->hwep_num);
+ writel((1 << ep->hwep_num), USBD_EOTINTCLR(udc->udp_baseaddr));
+ writel((1 << ep->hwep_num), USBD_NDDRTINTCLR(udc->udp_baseaddr));
+
+ /* System error? */
+ if (readl(USBD_SYSERRTINTST(udc->udp_baseaddr)) &
+ (1 << ep->hwep_num)) {
+ writel((1 << ep->hwep_num),
+ USBD_SYSERRTINTCLR(udc->udp_baseaddr));
+ ep_err(ep, "AHB critical error!\n");
+ ep->req_pending = 0;
+
+ /* The error could have occurred on a packet of a multipacket
+ * transfer, so recovering the transfer is not possible. Close
+ * the request with an error */
+ done(ep, req, -ECONNABORTED);
+ return;
+ }
+
+ /* Handle the current DD's status */
+ status = dd->dd_status;
+ switch (status & DD_STATUS_STS_MASK) {
+ case DD_STATUS_STS_NS:
+ /* DD not serviced? This shouldn't happen! */
+ ep->req_pending = 0;
+ ep_err(ep, "DMA critical EP error: DD not serviced (0x%x)!\n",
+ status);
+
+ done(ep, req, -ECONNABORTED);
+ return;
+
+ case DD_STATUS_STS_BS:
+ /* Interrupt only fires on EOT - This shouldn't happen! */
+ ep->req_pending = 0;
+ ep_err(ep, "DMA critical EP error: EOT prior to service completion (0x%x)!\n",
+ status);
+ done(ep, req, -ECONNABORTED);
+ return;
+
+ case DD_STATUS_STS_NC:
+ case DD_STATUS_STS_DUR:
+ /* Really just a short packet, not an underrun */
+ /* This is a good status and what we expect */
+ break;
+
+ default:
+ /* Data overrun, system error, or unknown */
+ ep->req_pending = 0;
+ ep_err(ep, "DMA critical EP error: System error (0x%x)!\n",
+ status);
+ done(ep, req, -ECONNABORTED);
+ return;
+ }
+
+ /* ISO endpoints are handled differently */
+ if (ep->eptype == EP_ISO_TYPE) {
+ if (ep->is_in)
+ req->req.actual = req->req.length;
+ else
+ req->req.actual = dd->iso_status[0] & 0xFFFF;
+ } else
+ req->req.actual += DD_STATUS_CURDMACNT(status);
+
+ /* Send a ZLP if necessary. This will be done for non-int
+ * packets which have a size that is a divisor of MAXP */
+ if (req->send_zlp) {
+ /*
+ * If at least 1 buffer is available, send the ZLP now.
+ * Otherwise, the ZLP send needs to be deferred until a
+ * buffer is available.
+ */
+ if (udc_clearep_getsts(udc, ep->hwep_num) & EP_SEL_F) {
+ udc_clearep_getsts(udc, ep->hwep_num);
+ uda_enable_hwepint(udc, ep->hwep_num);
+ epstatus = udc_clearep_getsts(udc, ep->hwep_num);
+
+ /* Let the EP interrupt handle the ZLP */
+ return;
+ } else
+ udc_send_in_zlp(udc, ep);
+ }
+
+ /* Transfer request is complete */
+ done(ep, req, 0);
+
+ /* Start another request if ready */
+ udc_clearep_getsts(udc, ep->hwep_num);
+ if (!list_empty((&ep->queue))) {
+ if (ep->is_in)
+ udc_ep_in_req_dma(udc, ep);
+ else
+ udc_ep_out_req_dma(udc, ep);
+ } else
+ ep->req_pending = 0;
+
+}
+
+/*
+ *
+ * Endpoint 0 functions
+ *
+ */
+static void udc_handle_dev(struct lpc32xx_udc *udc)
+{
+ u32 tmp;
+
+ udc_protocol_cmd_w(udc, CMD_GET_DEV_STAT);
+ tmp = udc_protocol_cmd_r(udc, DAT_GET_DEV_STAT);
+
+ if (tmp & DEV_RST)
+ uda_usb_reset(udc);
+ else if (tmp & DEV_CON_CH)
+ uda_power_event(udc, (tmp & DEV_CON));
+ else if (tmp & DEV_SUS_CH) {
+ if (tmp & DEV_SUS) {
+ if (udc->vbus == 0)
+ stop_activity(udc);
+ else if ((udc->gadget.speed != USB_SPEED_UNKNOWN) &&
+ udc->driver) {
+ /* Power down transceiver */
+ udc->poweron = 0;
+ schedule_work(&udc->pullup_job);
+ uda_resm_susp_event(udc, 1);
+ }
+ } else if ((udc->gadget.speed != USB_SPEED_UNKNOWN) &&
+ udc->driver && udc->vbus) {
+ uda_resm_susp_event(udc, 0);
+ /* Power up transceiver */
+ udc->poweron = 1;
+ schedule_work(&udc->pullup_job);
+ }
+ }
+}
+
+static int udc_get_status(struct lpc32xx_udc *udc, u16 reqtype, u16 wIndex)
+{
+ struct lpc32xx_ep *ep;
+ u32 ep0buff = 0, tmp;
+
+ switch (reqtype & USB_RECIP_MASK) {
+ case USB_RECIP_INTERFACE:
+ break; /* Not supported */
+
+ case USB_RECIP_DEVICE:
+ ep0buff = (udc->selfpowered << USB_DEVICE_SELF_POWERED);
+ if (udc->dev_status & (1 << USB_DEVICE_REMOTE_WAKEUP))
+ ep0buff |= (1 << USB_DEVICE_REMOTE_WAKEUP);
+ break;
+
+ case USB_RECIP_ENDPOINT:
+ tmp = wIndex & USB_ENDPOINT_NUMBER_MASK;
+ ep = &udc->ep[tmp];
+ if ((tmp == 0) || (tmp >= NUM_ENDPOINTS) || (tmp && !ep->desc))
+ return -EOPNOTSUPP;
+
+ if (wIndex & USB_DIR_IN) {
+ if (!ep->is_in)
+ return -EOPNOTSUPP; /* Something's wrong */
+ } else if (ep->is_in)
+ return -EOPNOTSUPP; /* Not an IN endpoint */
+
+ /* Get status of the endpoint */
+ udc_protocol_cmd_w(udc, CMD_SEL_EP(ep->hwep_num));
+ tmp = udc_protocol_cmd_r(udc, DAT_SEL_EP(ep->hwep_num));
+
+ if (tmp & EP_SEL_ST)
+ ep0buff = (1 << USB_ENDPOINT_HALT);
+ else
+ ep0buff = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Return data */
+ udc_write_hwep(udc, EP_IN, &ep0buff, 2);
+
+ return 0;
+}
+
+static void udc_handle_ep0_setup(struct lpc32xx_udc *udc)
+{
+ struct lpc32xx_ep *ep, *ep0 = &udc->ep[0];
+ struct usb_ctrlrequest ctrlpkt;
+ int i, bytes;
+ u16 wIndex, wValue, wLength, reqtype, req, tmp;
+
+ /* Nuke previous transfers */
+ nuke(ep0, -EPROTO);
+
+ /* Get setup packet */
+ bytes = udc_read_hwep(udc, EP_OUT, (u32 *) &ctrlpkt, 8);
+ if (bytes != 8) {
+ ep_warn(ep0, "Incorrectly sized setup packet (s/b 8, is %d)!\n",
+ bytes);
+ return;
+ }
+
+ /* Native endianness */
+ wIndex = le16_to_cpu(ctrlpkt.wIndex);
+ wValue = le16_to_cpu(ctrlpkt.wValue);
+ wLength = le16_to_cpu(ctrlpkt.wLength);
+ reqtype = le16_to_cpu(ctrlpkt.bRequestType);
+
+ /* Set direction of EP0 */
+ if (likely(reqtype & USB_DIR_IN))
+ ep0->is_in = 1;
+ else
+ ep0->is_in = 0;
+
+ /* Handle SETUP packet */
+ req = le16_to_cpu(ctrlpkt.bRequest);
+ switch (req) {
+ case USB_REQ_CLEAR_FEATURE:
+ case USB_REQ_SET_FEATURE:
+ switch (reqtype) {
+ case (USB_TYPE_STANDARD | USB_RECIP_DEVICE):
+ if (wValue != USB_DEVICE_REMOTE_WAKEUP)
+ goto stall; /* Nothing else handled */
+
+ /* Tell board about event */
+ if (req == USB_REQ_CLEAR_FEATURE)
+ udc->dev_status &=
+ ~(1 << USB_DEVICE_REMOTE_WAKEUP);
+ else
+ udc->dev_status |=
+ (1 << USB_DEVICE_REMOTE_WAKEUP);
+ uda_remwkp_cgh(udc);
+ goto zlp_send;
+
+ case (USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
+ tmp = wIndex & USB_ENDPOINT_NUMBER_MASK;
+ if ((wValue != USB_ENDPOINT_HALT) ||
+ (tmp >= NUM_ENDPOINTS))
+ break;
+
+ /* Find hardware endpoint from logical endpoint */
+ ep = &udc->ep[tmp];
+ tmp = ep->hwep_num;
+ if (tmp == 0)
+ break;
+
+ if (req == USB_REQ_SET_FEATURE)
+ udc_stall_hwep(udc, tmp);
+ else if (!ep->wedge)
+ udc_clrstall_hwep(udc, tmp);
+
+ goto zlp_send;
+
+ default:
+ break;
+ }
+
+
+ case USB_REQ_SET_ADDRESS:
+ if (reqtype == (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) {
+ udc_set_address(udc, wValue);
+ goto zlp_send;
+ }
+ break;
+
+ case USB_REQ_GET_STATUS:
+ udc_get_status(udc, reqtype, wIndex);
+ return;
+
+ default:
+ break; /* Let GadgetFS handle the descriptor instead */
+ }
+
+ if (likely(udc->driver)) {
+ /* device-2-host (IN) or no data setup command, process
+ * immediately */
+ spin_unlock(&udc->lock);
+ i = udc->driver->setup(&udc->gadget, &ctrlpkt);
+
+ spin_lock(&udc->lock);
+ if (req == USB_REQ_SET_CONFIGURATION) {
+ /* Configuration is set after endpoints are realized */
+ if (wValue) {
+ /* Set configuration */
+ udc_set_device_configured(udc);
+
+ udc_protocol_cmd_data_w(udc, CMD_SET_MODE,
+ DAT_WR_BYTE(AP_CLK |
+ INAK_BI | INAK_II));
+ } else {
+ /* Clear configuration */
+ udc_set_device_unconfigured(udc);
+
+ /* Disable NAK interrupts */
+ udc_protocol_cmd_data_w(udc, CMD_SET_MODE,
+ DAT_WR_BYTE(AP_CLK));
+ }
+ }
+
+ if (i < 0) {
+ /* setup processing failed, force stall */
+ dev_err(udc->dev,
+ "req %02x.%02x protocol STALL; stat %d\n",
+ reqtype, req, i);
+ udc->ep0state = WAIT_FOR_SETUP;
+ goto stall;
+ }
+ }
+
+ if (!ep0->is_in)
+ udc_ep0_send_zlp(udc); /* ZLP IN packet on data phase */
+
+ return;
+
+stall:
+ udc_stall_hwep(udc, EP_IN);
+ return;
+
+zlp_send:
+ udc_ep0_send_zlp(udc);
+ return;
+}
+
+/* IN endpoint 0 transfer */
+static void udc_handle_ep0_in(struct lpc32xx_udc *udc)
+{
+ struct lpc32xx_ep *ep0 = &udc->ep[0];
+ u32 epstatus;
+
+ /* Clear EP interrupt */
+ epstatus = udc_clearep_getsts(udc, EP_IN);
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+ ep0->totalints++;
+#endif
+
+ /* Stalled? Clear stall and reset buffers */
+ if (epstatus & EP_SEL_ST) {
+ udc_clrstall_hwep(udc, EP_IN);
+ nuke(ep0, -ECONNABORTED);
+ udc->ep0state = WAIT_FOR_SETUP;
+ return;
+ }
+
+ /* Is a buffer available? */
+ if (!(epstatus & EP_SEL_F)) {
+ /* Handle based on current state */
+ if (udc->ep0state == DATA_IN)
+ udc_ep0_in_req(udc);
+ else {
+ /* Unknown state for EP0 oe end of DATA IN phase */
+ nuke(ep0, -ECONNABORTED);
+ udc->ep0state = WAIT_FOR_SETUP;
+ }
+ }
+}
+
+/* OUT endpoint 0 transfer */
+static void udc_handle_ep0_out(struct lpc32xx_udc *udc)
+{
+ struct lpc32xx_ep *ep0 = &udc->ep[0];
+ u32 epstatus;
+
+ /* Clear EP interrupt */
+ epstatus = udc_clearep_getsts(udc, EP_OUT);
+
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+ ep0->totalints++;
+#endif
+
+ /* Stalled? */
+ if (epstatus & EP_SEL_ST) {
+ udc_clrstall_hwep(udc, EP_OUT);
+ nuke(ep0, -ECONNABORTED);
+ udc->ep0state = WAIT_FOR_SETUP;
+ return;
+ }
+
+ /* A NAK may occur if a packet couldn't be received yet */
+ if (epstatus & EP_SEL_EPN)
+ return;
+ /* Setup packet incoming? */
+ if (epstatus & EP_SEL_STP) {
+ nuke(ep0, 0);
+ udc->ep0state = WAIT_FOR_SETUP;
+ }
+
+ /* Data available? */
+ if (epstatus & EP_SEL_F)
+ /* Handle based on current state */
+ switch (udc->ep0state) {
+ case WAIT_FOR_SETUP:
+ udc_handle_ep0_setup(udc);
+ break;
+
+ case DATA_OUT:
+ udc_ep0_out_req(udc);
+ break;
+
+ default:
+ /* Unknown state for EP0 */
+ nuke(ep0, -ECONNABORTED);
+ udc->ep0state = WAIT_FOR_SETUP;
+ }
+}
+
+/* Must be called without lock */
+static int lpc32xx_get_frame(struct usb_gadget *gadget)
+{
+ int frame;
+ unsigned long flags;
+ struct lpc32xx_udc *udc = to_udc(gadget);
+
+ if (!udc->clocked)
+ return -EINVAL;
+
+ spin_lock_irqsave(&udc->lock, flags);
+
+ frame = (int) udc_get_current_frame(udc);
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ return frame;
+}
+
+static int lpc32xx_wakeup(struct usb_gadget *gadget)
+{
+ return -ENOTSUPP;
+}
+
+static int lpc32xx_set_selfpowered(struct usb_gadget *gadget, int is_on)
+{
+ struct lpc32xx_udc *udc = to_udc(gadget);
+
+ /* Always self-powered */
+ udc->selfpowered = (is_on != 0);
+
+ return 0;
+}
+
+/*
+ * vbus is here! turn everything on that's ready
+ * Must be called without lock
+ */
+static int lpc32xx_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+ unsigned long flags;
+ struct lpc32xx_udc *udc = to_udc(gadget);
+
+ spin_lock_irqsave(&udc->lock, flags);
+
+ /* Doesn't need lock */
+ if (udc->driver) {
+ udc_clk_set(udc, 1);
+ udc_enable(udc);
+ pullup(udc, is_active);
+ } else {
+ stop_activity(udc);
+ pullup(udc, 0);
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+ /*
+ * Wait for all the endpoints to disable,
+ * before disabling clocks. Don't wait if
+ * endpoints are not enabled.
+ */
+ if (atomic_read(&udc->enabled_ep_cnt))
+ wait_event_interruptible(udc->ep_disable_wait_queue,
+ (atomic_read(&udc->enabled_ep_cnt) == 0));
+
+ spin_lock_irqsave(&udc->lock, flags);
+
+ udc_clk_set(udc, 0);
+ }
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ return 0;
+}
+
+/* Can be called with or without lock */
+static int lpc32xx_pullup(struct usb_gadget *gadget, int is_on)
+{
+ struct lpc32xx_udc *udc = to_udc(gadget);
+
+ /* Doesn't need lock */
+ pullup(udc, is_on);
+
+ return 0;
+}
+
+static int lpc32xx_start(struct usb_gadget_driver *driver,
+ int (*bind)(struct usb_gadget *));
+static int lpc32xx_stop(struct usb_gadget_driver *driver);
+
+static const struct usb_gadget_ops lpc32xx_udc_ops = {
+ .get_frame = lpc32xx_get_frame,
+ .wakeup = lpc32xx_wakeup,
+ .set_selfpowered = lpc32xx_set_selfpowered,
+ .vbus_session = lpc32xx_vbus_session,
+ .pullup = lpc32xx_pullup,
+ .start = lpc32xx_start,
+ .stop = lpc32xx_stop,
+};
+
+static void nop_release(struct device *dev)
+{
+ /* nothing to free */
+}
+
+static struct lpc32xx_udc controller = {
+ .gadget = {
+ .ops = &lpc32xx_udc_ops,
+ .ep0 = &controller.ep[0].ep,
+ .name = driver_name,
+ .dev = {
+ .init_name = "gadget",
+ .release = nop_release,
+ }
+ },
+ .ep[0] = {
+ .ep = {
+ .name = "ep0",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 64,
+ .hwep_num_base = 0,
+ .hwep_num = 0, /* Can be 0 or 1, has special handling */
+ .lep = 0,
+ .eptype = EP_CTL_TYPE,
+ },
+ .ep[1] = {
+ .ep = {
+ .name = "ep1-int",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 64,
+ .hwep_num_base = 2,
+ .hwep_num = 0, /* 2 or 3, will be set later */
+ .lep = 1,
+ .eptype = EP_INT_TYPE,
+ },
+ .ep[2] = {
+ .ep = {
+ .name = "ep2-bulk",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 64,
+ .hwep_num_base = 4,
+ .hwep_num = 0, /* 4 or 5, will be set later */
+ .lep = 2,
+ .eptype = EP_BLK_TYPE,
+ },
+ .ep[3] = {
+ .ep = {
+ .name = "ep3-iso",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 1023,
+ .hwep_num_base = 6,
+ .hwep_num = 0, /* 6 or 7, will be set later */
+ .lep = 3,
+ .eptype = EP_ISO_TYPE,
+ },
+ .ep[4] = {
+ .ep = {
+ .name = "ep4-int",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 64,
+ .hwep_num_base = 8,
+ .hwep_num = 0, /* 8 or 9, will be set later */
+ .lep = 4,
+ .eptype = EP_INT_TYPE,
+ },
+ .ep[5] = {
+ .ep = {
+ .name = "ep5-bulk",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 64,
+ .hwep_num_base = 10,
+ .hwep_num = 0, /* 10 or 11, will be set later */
+ .lep = 5,
+ .eptype = EP_BLK_TYPE,
+ },
+ .ep[6] = {
+ .ep = {
+ .name = "ep6-iso",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 1023,
+ .hwep_num_base = 12,
+ .hwep_num = 0, /* 12 or 13, will be set later */
+ .lep = 6,
+ .eptype = EP_ISO_TYPE,
+ },
+ .ep[7] = {
+ .ep = {
+ .name = "ep7-int",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 64,
+ .hwep_num_base = 14,
+ .hwep_num = 0,
+ .lep = 7,
+ .eptype = EP_INT_TYPE,
+ },
+ .ep[8] = {
+ .ep = {
+ .name = "ep8-bulk",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 64,
+ .hwep_num_base = 16,
+ .hwep_num = 0,
+ .lep = 8,
+ .eptype = EP_BLK_TYPE,
+ },
+ .ep[9] = {
+ .ep = {
+ .name = "ep9-iso",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 1023,
+ .hwep_num_base = 18,
+ .hwep_num = 0,
+ .lep = 9,
+ .eptype = EP_ISO_TYPE,
+ },
+ .ep[10] = {
+ .ep = {
+ .name = "ep10-int",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 64,
+ .hwep_num_base = 20,
+ .hwep_num = 0,
+ .lep = 10,
+ .eptype = EP_INT_TYPE,
+ },
+ .ep[11] = {
+ .ep = {
+ .name = "ep11-bulk",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 64,
+ .hwep_num_base = 22,
+ .hwep_num = 0,
+ .lep = 11,
+ .eptype = EP_BLK_TYPE,
+ },
+ .ep[12] = {
+ .ep = {
+ .name = "ep12-iso",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 1023,
+ .hwep_num_base = 24,
+ .hwep_num = 0,
+ .lep = 12,
+ .eptype = EP_ISO_TYPE,
+ },
+ .ep[13] = {
+ .ep = {
+ .name = "ep13-int",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 64,
+ .hwep_num_base = 26,
+ .hwep_num = 0,
+ .lep = 13,
+ .eptype = EP_INT_TYPE,
+ },
+ .ep[14] = {
+ .ep = {
+ .name = "ep14-bulk",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 64,
+ .hwep_num_base = 28,
+ .hwep_num = 0,
+ .lep = 14,
+ .eptype = EP_BLK_TYPE,
+ },
+ .ep[15] = {
+ .ep = {
+ .name = "ep15-bulk",
+ .ops = &lpc32xx_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 1023,
+ .hwep_num_base = 30,
+ .hwep_num = 0,
+ .lep = 15,
+ .eptype = EP_BLK_TYPE,
+ },
+};
+
+/* ISO and status interrupts */
+static irqreturn_t lpc32xx_usb_lp_irq(int irq, void *_udc)
+{
+ u32 tmp, devstat;
+ struct lpc32xx_udc *udc = _udc;
+
+ spin_lock(&udc->lock);
+
+ /* Read the device status register */
+ devstat = readl(USBD_DEVINTST(udc->udp_baseaddr));
+
+ devstat &= ~USBD_EP_FAST;
+ writel(devstat, USBD_DEVINTCLR(udc->udp_baseaddr));
+ devstat = devstat & udc->enabled_devints;
+
+ /* Device specific handling needed? */
+ if (devstat & USBD_DEV_STAT)
+ udc_handle_dev(udc);
+
+ /* Start of frame? (devstat & FRAME_INT):
+ * The frame interrupt isn't really needed for ISO support,
+ * as the driver will queue the necessary packets */
+
+ /* Error? */
+ if (devstat & ERR_INT) {
+ /* All types of errors, from cable removal during transfer to
+ * misc protocol and bit errors. These are mostly for just info,
+ * as the USB hardware will work around these. If these errors
+ * happen alot, something is wrong. */
+ udc_protocol_cmd_w(udc, CMD_RD_ERR_STAT);
+ tmp = udc_protocol_cmd_r(udc, DAT_RD_ERR_STAT);
+ dev_dbg(udc->dev, "Device error (0x%x)!\n", tmp);
+ }
+
+ spin_unlock(&udc->lock);
+
+ return IRQ_HANDLED;
+}
+
+/* EP interrupts */
+static irqreturn_t lpc32xx_usb_hp_irq(int irq, void *_udc)
+{
+ u32 tmp;
+ struct lpc32xx_udc *udc = _udc;
+
+ spin_lock(&udc->lock);
+
+ /* Read the device status register */
+ writel(USBD_EP_FAST, USBD_DEVINTCLR(udc->udp_baseaddr));
+
+ /* Endpoints */
+ tmp = readl(USBD_EPINTST(udc->udp_baseaddr));
+
+ /* Special handling for EP0 */
+ if (tmp & (EP_MASK_SEL(0, EP_OUT) | EP_MASK_SEL(0, EP_IN))) {
+ /* Handle EP0 IN */
+ if (tmp & (EP_MASK_SEL(0, EP_IN)))
+ udc_handle_ep0_in(udc);
+
+ /* Handle EP0 OUT */
+ if (tmp & (EP_MASK_SEL(0, EP_OUT)))
+ udc_handle_ep0_out(udc);
+ }
+
+ /* All other EPs */
+ if (tmp & ~(EP_MASK_SEL(0, EP_OUT) | EP_MASK_SEL(0, EP_IN))) {
+ int i;
+
+ /* Handle other EP interrupts */
+ for (i = 1; i < NUM_ENDPOINTS; i++) {
+ if (tmp & (1 << udc->ep[i].hwep_num))
+ udc_handle_eps(udc, &udc->ep[i]);
+ }
+ }
+
+ spin_unlock(&udc->lock);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t lpc32xx_usb_devdma_irq(int irq, void *_udc)
+{
+ struct lpc32xx_udc *udc = _udc;
+
+ int i;
+ u32 tmp;
+
+ spin_lock(&udc->lock);
+
+ /* Handle EP DMA EOT interrupts */
+ tmp = readl(USBD_EOTINTST(udc->udp_baseaddr)) |
+ (readl(USBD_EPDMAST(udc->udp_baseaddr)) &
+ readl(USBD_NDDRTINTST(udc->udp_baseaddr))) |
+ readl(USBD_SYSERRTINTST(udc->udp_baseaddr));
+ for (i = 1; i < NUM_ENDPOINTS; i++) {
+ if (tmp & (1 << udc->ep[i].hwep_num))
+ udc_handle_dma_ep(udc, &udc->ep[i]);
+ }
+
+ spin_unlock(&udc->lock);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ *
+ * VBUS detection, pullup handler, and Gadget cable state notification
+ *
+ */
+static void vbus_work(struct work_struct *work)
+{
+ u8 value;
+ struct lpc32xx_udc *udc = container_of(work, struct lpc32xx_udc,
+ vbus_job);
+
+ if (udc->enabled != 0) {
+ /* Discharge VBUS real quick */
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DISCHRG);
+
+ /* Give VBUS some time (100mS) to discharge */
+ msleep(100);
+
+ /* Disable VBUS discharge resistor */
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
+ OTG1_VBUS_DISCHRG);
+
+ /* Clear interrupt */
+ i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_INTERRUPT_LATCH |
+ ISP1301_I2C_REG_CLEAR_ADDR, ~0);
+
+ /* Get the VBUS status from the transceiver */
+ value = i2c_smbus_read_byte_data(udc->isp1301_i2c_client,
+ ISP1301_I2C_OTG_CONTROL_2);
+
+ /* VBUS on or off? */
+ if (value & OTG_B_SESS_VLD)
+ udc->vbus = 1;
+ else
+ udc->vbus = 0;
+
+ /* VBUS changed? */
+ if (udc->last_vbus != udc->vbus) {
+ udc->last_vbus = udc->vbus;
+ lpc32xx_vbus_session(&udc->gadget, udc->vbus);
+ }
+ }
+
+ /* Re-enable after completion */
+ enable_irq(udc->udp_irq[IRQ_USB_ATX]);
+}
+
+static irqreturn_t lpc32xx_usb_vbus_irq(int irq, void *_udc)
+{
+ struct lpc32xx_udc *udc = _udc;
+
+ /* Defer handling of VBUS IRQ to work queue */
+ disable_irq_nosync(udc->udp_irq[IRQ_USB_ATX]);
+ schedule_work(&udc->vbus_job);
+
+ return IRQ_HANDLED;
+}
+
+static int lpc32xx_start(struct usb_gadget_driver *driver,
+ int (*bind)(struct usb_gadget *))
+{
+ struct lpc32xx_udc *udc = &controller;
+ int retval, i;
+
+ if (!driver || driver->max_speed < USB_SPEED_FULL ||
+ !bind || !driver->setup) {
+ dev_err(udc->dev, "bad parameter.\n");
+ return -EINVAL;
+ }
+
+ if (udc->driver) {
+ dev_err(udc->dev, "UDC already has a gadget driver\n");
+ return -EBUSY;
+ }
+
+ udc->driver = driver;
+ udc->gadget.dev.driver = &driver->driver;
+ udc->enabled = 1;
+ udc->selfpowered = 1;
+ udc->vbus = 0;
+
+ retval = bind(&udc->gadget);
+ if (retval) {
+ dev_err(udc->dev, "bind() returned %d\n", retval);
+ udc->enabled = 0;
+ udc->selfpowered = 0;
+ udc->driver = NULL;
+ udc->gadget.dev.driver = NULL;
+ return retval;
+ }
+
+ dev_dbg(udc->dev, "bound to %s\n", driver->driver.name);
+
+ /* Force VBUS process once to check for cable insertion */
+ udc->last_vbus = udc->vbus = 0;
+ schedule_work(&udc->vbus_job);
+
+ /* Do not re-enable ATX IRQ (3) */
+ for (i = IRQ_USB_LP; i < IRQ_USB_ATX; i++)
+ enable_irq(udc->udp_irq[i]);
+
+ return 0;
+}
+
+static int lpc32xx_stop(struct usb_gadget_driver *driver)
+{
+ int i;
+ struct lpc32xx_udc *udc = &controller;
+
+ if (!driver || driver != udc->driver || !driver->unbind)
+ return -EINVAL;
+
+ /* Disable USB pullup */
+ isp1301_pullup_enable(udc, 0, 1);
+
+ for (i = IRQ_USB_LP; i <= IRQ_USB_ATX; i++)
+ disable_irq(udc->udp_irq[i]);
+
+ if (udc->clocked) {
+
+ spin_lock(&udc->lock);
+ stop_activity(udc);
+ spin_unlock(&udc->lock);
+
+ /*
+ * Wait for all the endpoints to disable,
+ * before disabling clocks. Don't wait if
+ * endpoints are not enabled.
+ */
+ if (atomic_read(&udc->enabled_ep_cnt))
+ wait_event_interruptible(udc->ep_disable_wait_queue,
+ (atomic_read(&udc->enabled_ep_cnt) == 0));
+
+ spin_lock(&udc->lock);
+ udc_clk_set(udc, 0);
+ spin_unlock(&udc->lock);
+ }
+
+ udc->enabled = 0;
+ pullup(udc, 0);
+
+ driver->unbind(&udc->gadget);
+ udc->gadget.dev.driver = NULL;
+ udc->driver = NULL;
+
+ dev_dbg(udc->dev, "unbound from %s\n", driver->driver.name);
+ return 0;
+}
+
+static void lpc32xx_udc_shutdown(struct platform_device *dev)
+{
+ /* Force disconnect on reboot */
+ struct lpc32xx_udc *udc = &controller;
+
+ pullup(udc, 0);
+}
+
+/*
+ * Callbacks to be overridden by options passed via OF (TODO)
+ */
+
+static void lpc32xx_usbd_conn_chg(int conn)
+{
+ /* Do nothing, it might be nice to enable an LED
+ * based on conn state being !0 */
+}
+
+static void lpc32xx_usbd_susp_chg(int susp)
+{
+ /* Device suspend if susp != 0 */
+}
+
+static void lpc32xx_rmwkup_chg(int remote_wakup_enable)
+{
+ /* Enable or disable USB remote wakeup */
+}
+
+struct lpc32xx_usbd_cfg lpc32xx_usbddata = {
+ .vbus_drv_pol = 0,
+ .conn_chgb = &lpc32xx_usbd_conn_chg,
+ .susp_chgb = &lpc32xx_usbd_susp_chg,
+ .rmwk_chgb = &lpc32xx_rmwkup_chg,
+};
+
+
+static u64 lpc32xx_usbd_dmamask = ~(u32) 0x7F;
+
+static int __init lpc32xx_udc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct lpc32xx_udc *udc = &controller;
+ int retval, i;
+ struct resource *res;
+ dma_addr_t dma_handle;
+ struct device_node *isp1301_node;
+
+ /* init software state */
+ udc->gadget.dev.parent = dev;
+ udc->pdev = pdev;
+ udc->dev = &pdev->dev;
+ udc->enabled = 0;
+
+ if (pdev->dev.of_node) {
+ isp1301_node = of_parse_phandle(pdev->dev.of_node,
+ "transceiver", 0);
+ } else {
+ isp1301_node = NULL;
+ }
+
+ udc->isp1301_i2c_client = isp1301_get_client(isp1301_node);
+ if (!udc->isp1301_i2c_client)
+ return -EPROBE_DEFER;
+
+ dev_info(udc->dev, "ISP1301 I2C device at address 0x%x\n",
+ udc->isp1301_i2c_client->addr);
+
+ pdev->dev.dma_mask = &lpc32xx_usbd_dmamask;
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+ udc->board = &lpc32xx_usbddata;
+
+ /*
+ * Resources are mapped as follows:
+ * IORESOURCE_MEM, base address and size of USB space
+ * IORESOURCE_IRQ, USB device low priority interrupt number
+ * IORESOURCE_IRQ, USB device high priority interrupt number
+ * IORESOURCE_IRQ, USB device interrupt number
+ * IORESOURCE_IRQ, USB transceiver interrupt number
+ */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENXIO;
+
+ spin_lock_init(&udc->lock);
+
+ /* Get IRQs */
+ for (i = 0; i < 4; i++) {
+ udc->udp_irq[i] = platform_get_irq(pdev, i);
+ if (udc->udp_irq[i] < 0) {
+ dev_err(udc->dev,
+ "irq resource %d not available!\n", i);
+ return udc->udp_irq[i];
+ }
+ }
+
+ udc->io_p_start = res->start;
+ udc->io_p_size = resource_size(res);
+ if (!request_mem_region(udc->io_p_start, udc->io_p_size, driver_name)) {
+ dev_err(udc->dev, "someone's using UDC memory\n");
+ return -EBUSY;
+ }
+
+ udc->udp_baseaddr = ioremap(udc->io_p_start, udc->io_p_size);
+ if (!udc->udp_baseaddr) {
+ retval = -ENOMEM;
+ dev_err(udc->dev, "IO map failure\n");
+ goto io_map_fail;
+ }
+
+ /* Enable AHB slave USB clock, needed for further USB clock control */
+ writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL);
+
+ /* Get required clocks */
+ udc->usb_pll_clk = clk_get(&pdev->dev, "ck_pll5");
+ if (IS_ERR(udc->usb_pll_clk)) {
+ dev_err(udc->dev, "failed to acquire USB PLL\n");
+ retval = PTR_ERR(udc->usb_pll_clk);
+ goto pll_get_fail;
+ }
+ udc->usb_slv_clk = clk_get(&pdev->dev, "ck_usbd");
+ if (IS_ERR(udc->usb_slv_clk)) {
+ dev_err(udc->dev, "failed to acquire USB device clock\n");
+ retval = PTR_ERR(udc->usb_slv_clk);
+ goto usb_clk_get_fail;
+ }
+
+ /* Setup PLL clock to 48MHz */
+ retval = clk_enable(udc->usb_pll_clk);
+ if (retval < 0) {
+ dev_err(udc->dev, "failed to start USB PLL\n");
+ goto pll_enable_fail;
+ }
+
+ retval = clk_set_rate(udc->usb_pll_clk, 48000);
+ if (retval < 0) {
+ dev_err(udc->dev, "failed to set USB clock rate\n");
+ goto pll_set_fail;
+ }
+
+ writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN, USB_CTRL);
+
+ /* Enable USB device clock */
+ retval = clk_enable(udc->usb_slv_clk);
+ if (retval < 0) {
+ dev_err(udc->dev, "failed to start USB device clock\n");
+ goto usb_clk_enable_fail;
+ }
+
+ /* Set to enable all needed USB OTG clocks */
+ writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL(udc));
+
+ i = 1000;
+ while (((readl(USB_OTG_CLK_STAT(udc)) & USB_CLOCK_MASK) !=
+ USB_CLOCK_MASK) && (i > 0))
+ i--;
+ if (!i)
+ dev_dbg(udc->dev, "USB OTG clocks not correctly enabled\n");
+
+ /* Setup deferred workqueue data */
+ udc->poweron = udc->pullup = 0;
+ INIT_WORK(&udc->pullup_job, pullup_work);
+ INIT_WORK(&udc->vbus_job, vbus_work);
+#ifdef CONFIG_PM
+ INIT_WORK(&udc->power_job, power_work);
+#endif
+
+ /* All clocks are now on */
+ udc->clocked = 1;
+
+ isp1301_udc_configure(udc);
+ /* Allocate memory for the UDCA */
+ udc->udca_v_base = dma_alloc_coherent(&pdev->dev, UDCA_BUFF_SIZE,
+ &dma_handle,
+ (GFP_KERNEL | GFP_DMA));
+ if (!udc->udca_v_base) {
+ dev_err(udc->dev, "error getting UDCA region\n");
+ retval = -ENOMEM;
+ goto i2c_fail;
+ }
+ udc->udca_p_base = dma_handle;
+ dev_dbg(udc->dev, "DMA buffer(0x%x bytes), P:0x%08x, V:0x%p\n",
+ UDCA_BUFF_SIZE, udc->udca_p_base, udc->udca_v_base);
+
+ /* Setup the DD DMA memory pool */
+ udc->dd_cache = dma_pool_create("udc_dd", udc->dev,
+ sizeof(struct lpc32xx_usbd_dd_gad),
+ sizeof(u32), 0);
+ if (!udc->dd_cache) {
+ dev_err(udc->dev, "error getting DD DMA region\n");
+ retval = -ENOMEM;
+ goto dma_alloc_fail;
+ }
+
+ /* Clear USB peripheral and initialize gadget endpoints */
+ udc_disable(udc);
+ udc_reinit(udc);
+
+ retval = device_register(&udc->gadget.dev);
+ if (retval < 0) {
+ dev_err(udc->dev, "Device registration failure\n");
+ goto dev_register_fail;
+ }
+
+ /* Request IRQs - low and high priority USB device IRQs are routed to
+ * the same handler, while the DMA interrupt is routed elsewhere */
+ retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq,
+ 0, "udc_lp", udc);
+ if (retval < 0) {
+ dev_err(udc->dev, "LP request irq %d failed\n",
+ udc->udp_irq[IRQ_USB_LP]);
+ goto irq_lp_fail;
+ }
+ retval = request_irq(udc->udp_irq[IRQ_USB_HP], lpc32xx_usb_hp_irq,
+ 0, "udc_hp", udc);
+ if (retval < 0) {
+ dev_err(udc->dev, "HP request irq %d failed\n",
+ udc->udp_irq[IRQ_USB_HP]);
+ goto irq_hp_fail;
+ }
+
+ retval = request_irq(udc->udp_irq[IRQ_USB_DEVDMA],
+ lpc32xx_usb_devdma_irq, 0, "udc_dma", udc);
+ if (retval < 0) {
+ dev_err(udc->dev, "DEV request irq %d failed\n",
+ udc->udp_irq[IRQ_USB_DEVDMA]);
+ goto irq_dev_fail;
+ }
+
+ /* The transceiver interrupt is used for VBUS detection and will
+ kick off the VBUS handler function */
+ retval = request_irq(udc->udp_irq[IRQ_USB_ATX], lpc32xx_usb_vbus_irq,
+ 0, "udc_otg", udc);
+ if (retval < 0) {
+ dev_err(udc->dev, "VBUS request irq %d failed\n",
+ udc->udp_irq[IRQ_USB_ATX]);
+ goto irq_xcvr_fail;
+ }
+
+ /* Initialize wait queue */
+ init_waitqueue_head(&udc->ep_disable_wait_queue);
+ atomic_set(&udc->enabled_ep_cnt, 0);
+
+ /* Keep all IRQs disabled until GadgetFS starts up */
+ for (i = IRQ_USB_LP; i <= IRQ_USB_ATX; i++)
+ disable_irq(udc->udp_irq[i]);
+
+ retval = usb_add_gadget_udc(dev, &udc->gadget);
+ if (retval < 0)
+ goto add_gadget_fail;
+
+ dev_set_drvdata(dev, udc);
+ device_init_wakeup(dev, 1);
+ create_debug_file(udc);
+
+ /* Disable clocks for now */
+ udc_clk_set(udc, 0);
+
+ dev_info(udc->dev, "%s version %s\n", driver_name, DRIVER_VERSION);
+ return 0;
+
+add_gadget_fail:
+ free_irq(udc->udp_irq[IRQ_USB_ATX], udc);
+irq_xcvr_fail:
+ free_irq(udc->udp_irq[IRQ_USB_DEVDMA], udc);
+irq_dev_fail:
+ free_irq(udc->udp_irq[IRQ_USB_HP], udc);
+irq_hp_fail:
+ free_irq(udc->udp_irq[IRQ_USB_LP], udc);
+irq_lp_fail:
+ device_unregister(&udc->gadget.dev);
+dev_register_fail:
+ dma_pool_destroy(udc->dd_cache);
+dma_alloc_fail:
+ dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
+ udc->udca_v_base, udc->udca_p_base);
+i2c_fail:
+ clk_disable(udc->usb_slv_clk);
+usb_clk_enable_fail:
+pll_set_fail:
+ clk_disable(udc->usb_pll_clk);
+pll_enable_fail:
+ clk_put(udc->usb_slv_clk);
+usb_clk_get_fail:
+ clk_put(udc->usb_pll_clk);
+pll_get_fail:
+ iounmap(udc->udp_baseaddr);
+io_map_fail:
+ release_mem_region(udc->io_p_start, udc->io_p_size);
+ dev_err(udc->dev, "%s probe failed, %d\n", driver_name, retval);
+
+ return retval;
+}
+
+static int __devexit lpc32xx_udc_remove(struct platform_device *pdev)
+{
+ struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
+
+ usb_del_gadget_udc(&udc->gadget);
+ if (udc->driver)
+ return -EBUSY;
+
+ udc_clk_set(udc, 1);
+ udc_disable(udc);
+ pullup(udc, 0);
+
+ free_irq(udc->udp_irq[IRQ_USB_ATX], udc);
+
+ device_init_wakeup(&pdev->dev, 0);
+ remove_debug_file(udc);
+
+ dma_pool_destroy(udc->dd_cache);
+ dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
+ udc->udca_v_base, udc->udca_p_base);
+ free_irq(udc->udp_irq[IRQ_USB_DEVDMA], udc);
+ free_irq(udc->udp_irq[IRQ_USB_HP], udc);
+ free_irq(udc->udp_irq[IRQ_USB_LP], udc);
+
+ device_unregister(&udc->gadget.dev);
+
+ clk_disable(udc->usb_slv_clk);
+ clk_put(udc->usb_slv_clk);
+ clk_disable(udc->usb_pll_clk);
+ clk_put(udc->usb_pll_clk);
+ iounmap(udc->udp_baseaddr);
+ release_mem_region(udc->io_p_start, udc->io_p_size);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int lpc32xx_udc_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+ int to = 1000;
+ struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
+
+ if (udc->clocked) {
+ /* Power down ISP */
+ udc->poweron = 0;
+ isp1301_set_powerstate(udc, 0);
+
+ /* Disable clocking */
+ udc_clk_set(udc, 0);
+
+ /* Keep clock flag on, so we know to re-enable clocks
+ on resume */
+ udc->clocked = 1;
+
+ /* Kill OTG and I2C clocks */
+ writel(0, USB_OTG_CLK_CTRL(udc));
+ while (((readl(USB_OTG_CLK_STAT(udc)) & OTGOFF_CLK_MASK) !=
+ OTGOFF_CLK_MASK) && (to > 0))
+ to--;
+ if (!to)
+ dev_dbg(udc->dev,
+ "USB OTG clocks not correctly enabled\n");
+
+ /* Kill global USB clock */
+ clk_disable(udc->usb_slv_clk);
+ }
+
+ return 0;
+}
+
+static int lpc32xx_udc_resume(struct platform_device *pdev)
+{
+ struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
+
+ if (udc->clocked) {
+ /* Enable global USB clock */
+ clk_enable(udc->usb_slv_clk);
+
+ /* Enable clocking */
+ udc_clk_set(udc, 1);
+
+ /* ISP back to normal power mode */
+ udc->poweron = 1;
+ isp1301_set_powerstate(udc, 1);
+ }
+
+ return 0;
+}
+#else
+#define lpc32xx_udc_suspend NULL
+#define lpc32xx_udc_resume NULL
+#endif
+
+#ifdef CONFIG_OF
+static struct of_device_id lpc32xx_udc_of_match[] = {
+ { .compatible = "nxp,lpc3220-udc", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, lpc32xx_udc_of_match);
+#endif
+
+static struct platform_driver lpc32xx_udc_driver = {
+ .remove = __devexit_p(lpc32xx_udc_remove),
+ .shutdown = lpc32xx_udc_shutdown,
+ .suspend = lpc32xx_udc_suspend,
+ .resume = lpc32xx_udc_resume,
+ .driver = {
+ .name = (char *) driver_name,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(lpc32xx_udc_of_match),
+ },
+};
+
+static int __init udc_init_module(void)
+{
+ return platform_driver_probe(&lpc32xx_udc_driver, lpc32xx_udc_probe);
+}
+module_init(udc_init_module);
+
+static void __exit udc_exit_module(void)
+{
+ platform_driver_unregister(&lpc32xx_udc_driver);
+}
+module_exit(udc_exit_module);
+
+MODULE_DESCRIPTION("LPC32XX udc driver");
+MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lpc32xx_udc");
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index 3608b3bd5732..8981fbb5748c 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -390,7 +390,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
int *counter;
int ret;
- ep->desc = desc;
+ ep->ep.desc = desc;
BUG_ON(ep->pipenum);
@@ -558,7 +558,7 @@ static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
static void start_packet(struct m66592_ep *ep, struct m66592_request *req)
{
- if (ep->desc->bEndpointAddress & USB_DIR_IN)
+ if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
start_packet_write(ep, req);
else
start_packet_read(ep, req);
@@ -734,7 +734,7 @@ __acquires(m66592->lock)
if (restart) {
req = list_entry(ep->queue.next, struct m66592_request, queue);
- if (ep->desc)
+ if (ep->ep.desc)
start_packet(ep, req);
}
}
@@ -917,7 +917,7 @@ static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb)
ep = m66592->pipenum2ep[pipenum];
req = list_entry(ep->queue.next,
struct m66592_request, queue);
- if (ep->desc->bEndpointAddress & USB_DIR_IN)
+ if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
irq_packet_write(ep, req);
else
irq_packet_read(ep, req);
@@ -1377,7 +1377,7 @@ static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
req->req.actual = 0;
req->req.status = -EINPROGRESS;
- if (ep->desc == NULL) /* control */
+ if (ep->ep.desc == NULL) /* control */
start_ep0(ep, req);
else {
if (request && !ep->busy)
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
index 9d9f7e39f037..88c85b4116a2 100644
--- a/drivers/usb/gadget/m66592-udc.h
+++ b/drivers/usb/gadget/m66592-udc.h
@@ -456,7 +456,7 @@ struct m66592_ep {
unsigned use_dma:1;
u16 pipenum;
u16 type;
- const struct usb_endpoint_descriptor *desc;
+
/* register address */
unsigned long fifoaddr;
unsigned long fifosel;
diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h
index e2be9519abbe..9073436d8b24 100644
--- a/drivers/usb/gadget/mv_udc.h
+++ b/drivers/usb/gadget/mv_udc.h
@@ -232,7 +232,6 @@ struct mv_ep {
struct mv_udc *udc;
struct list_head queue;
struct mv_dqh *dqh;
- const struct usb_endpoint_descriptor *desc;
u32 direction;
char name[14];
unsigned stopped:1,
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index a73cf406e2a4..dbcd1329495e 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -464,7 +464,7 @@ static int mv_ep_enable(struct usb_ep *_ep,
ep = container_of(_ep, struct mv_ep, ep);
udc = ep->udc;
- if (!_ep || !desc || ep->desc
+ if (!_ep || !desc || ep->ep.desc
|| desc->bDescriptorType != USB_DT_ENDPOINT)
return -EINVAL;
@@ -528,7 +528,7 @@ static int mv_ep_enable(struct usb_ep *_ep,
dqh->size_ioc_int_sts = 0;
ep->ep.maxpacket = max;
- ep->desc = desc;
+ ep->ep.desc = desc;
ep->stopped = 0;
/* Enable the endpoint for Rx or Tx and set the endpoint type */
@@ -580,7 +580,7 @@ static int mv_ep_disable(struct usb_ep *_ep)
unsigned long flags;
ep = container_of(_ep, struct mv_ep, ep);
- if ((_ep == NULL) || !ep->desc)
+ if ((_ep == NULL) || !ep->ep.desc)
return -EINVAL;
udc = ep->udc;
@@ -606,7 +606,6 @@ static int mv_ep_disable(struct usb_ep *_ep)
/* nuke all pending requests (does flush) */
nuke(ep, -ESHUTDOWN);
- ep->desc = NULL;
ep->ep.desc = NULL;
ep->stopped = 1;
@@ -651,7 +650,7 @@ static void mv_ep_fifo_flush(struct usb_ep *_ep)
return;
ep = container_of(_ep, struct mv_ep, ep);
- if (!ep->desc)
+ if (!ep->ep.desc)
return;
udc = ep->udc;
@@ -715,11 +714,11 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
dev_err(&udc->dev->dev, "%s, bad params", __func__);
return -EINVAL;
}
- if (unlikely(!_ep || !ep->desc)) {
+ if (unlikely(!_ep || !ep->ep.desc)) {
dev_err(&udc->dev->dev, "%s, bad ep", __func__);
return -EINVAL;
}
- if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+ if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
if (req->req.length > ep->ep.maxpacket)
return -EMSGSIZE;
}
@@ -925,12 +924,12 @@ static int mv_ep_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge)
ep = container_of(_ep, struct mv_ep, ep);
udc = ep->udc;
- if (!_ep || !ep->desc) {
+ if (!_ep || !ep->ep.desc) {
status = -EINVAL;
goto out;
}
- if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+ if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
status = -EOPNOTSUPP;
goto out;
}
@@ -1279,7 +1278,7 @@ static int eps_init(struct mv_udc *udc)
ep->stopped = 0;
ep->ep.maxpacket = EP0_MAX_PKT_SIZE;
ep->ep_num = 0;
- ep->desc = &mv_ep0_desc;
+ ep->ep.desc = &mv_ep0_desc;
INIT_LIST_HEAD(&ep->queue);
ep->ep_type = USB_ENDPOINT_XFER_CONTROL;
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 3b4b6dd0f95a..7ba32469c5bd 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -153,7 +153,7 @@ static int omap_ep_enable(struct usb_ep *_ep,
u16 maxp;
/* catch various bogus parameters */
- if (!_ep || !desc || ep->desc
+ if (!_ep || !desc || ep->ep.desc
|| desc->bDescriptorType != USB_DT_ENDPOINT
|| ep->bEndpointAddress != desc->bEndpointAddress
|| ep->maxpacket < usb_endpoint_maxp(desc)) {
@@ -200,7 +200,7 @@ static int omap_ep_enable(struct usb_ep *_ep,
spin_lock_irqsave(&udc->lock, flags);
- ep->desc = desc;
+ ep->ep.desc = desc;
ep->irqs = 0;
ep->stopped = 0;
ep->ep.maxpacket = maxp;
@@ -242,14 +242,13 @@ static int omap_ep_disable(struct usb_ep *_ep)
struct omap_ep *ep = container_of(_ep, struct omap_ep, ep);
unsigned long flags;
- if (!_ep || !ep->desc) {
+ if (!_ep || !ep->ep.desc) {
DBG("%s, %s not enabled\n", __func__,
_ep ? ep->ep.name : NULL);
return -EINVAL;
}
spin_lock_irqsave(&ep->udc->lock, flags);
- ep->desc = NULL;
ep->ep.desc = NULL;
nuke (ep, -ESHUTDOWN);
ep->ep.maxpacket = ep->maxpacket;
@@ -917,7 +916,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
DBG("%s, bad params\n", __func__);
return -EINVAL;
}
- if (!_ep || (!ep->desc && ep->bEndpointAddress)) {
+ if (!_ep || (!ep->ep.desc && ep->bEndpointAddress)) {
DBG("%s, bad ep\n", __func__);
return -EINVAL;
}
@@ -1121,7 +1120,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value)
status = 0;
/* otherwise, all active non-ISO endpoints can halt */
- } else if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC && ep->desc) {
+ } else if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC && ep->ep.desc) {
/* IN endpoints must already be idle */
if ((ep->bEndpointAddress & USB_DIR_IN)
@@ -1625,7 +1624,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
if (w_index & USB_DIR_IN)
ep += 16;
if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
- || !ep->desc)
+ || !ep->ep.desc)
goto do_stall;
use_ep(ep, 0);
omap_writew(udc->clr_halt, UDC_CTRL);
@@ -1653,7 +1652,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
if (w_index & USB_DIR_IN)
ep += 16;
if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
- || ep == ep0 || !ep->desc)
+ || ep == ep0 || !ep->ep.desc)
goto do_stall;
if (use_dma && ep->has_dma) {
/* this has rude side-effects (aborts) and
@@ -1688,7 +1687,7 @@ ep0out_status_stage:
ep = &udc->ep[w_index & 0xf];
if (w_index & USB_DIR_IN)
ep += 16;
- if (!ep->desc)
+ if (!ep->ep.desc)
goto do_stall;
/* iso never stalls */
@@ -2509,7 +2508,7 @@ static int proc_udc_show(struct seq_file *s, void *_)
if (tmp & UDC_ADD) {
list_for_each_entry (ep, &udc->gadget.ep_list,
ep.ep_list) {
- if (ep->desc)
+ if (ep->ep.desc)
proc_ep_show(s, ep);
}
}
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
index 59d3b2213cb1..cfadeb5fc5de 100644
--- a/drivers/usb/gadget/omap_udc.h
+++ b/drivers/usb/gadget/omap_udc.h
@@ -140,7 +140,6 @@ struct omap_ep {
struct list_head queue;
unsigned long irqs;
struct list_head iso;
- const struct usb_endpoint_descriptor *desc;
char name[14];
u16 maxpacket;
u8 bEndpointAddress;
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 65307064a6fd..1cfcc9ecbfbc 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -295,7 +295,6 @@ struct pch_udc_ep {
struct pch_udc_data_dma_desc *td_data;
struct pch_udc_dev *dev;
unsigned long offset_addr;
- const struct usb_endpoint_descriptor *desc;
struct list_head queue;
unsigned num:5,
in:1,
@@ -1705,7 +1704,7 @@ static int pch_udc_pcd_ep_enable(struct usb_ep *usbep,
if (!dev->driver || (dev->gadget.speed == USB_SPEED_UNKNOWN))
return -ESHUTDOWN;
spin_lock_irqsave(&dev->lock, iflags);
- ep->desc = desc;
+ ep->ep.desc = desc;
ep->halted = 0;
pch_udc_ep_enable(ep, &ep->dev->cfg_data, desc);
ep->ep.maxpacket = usb_endpoint_maxp(desc);
@@ -1734,7 +1733,7 @@ static int pch_udc_pcd_ep_disable(struct usb_ep *usbep)
ep = container_of(usbep, struct pch_udc_ep, ep);
dev = ep->dev;
- if ((usbep->name == ep0_string) || !ep->desc)
+ if ((usbep->name == ep0_string) || !ep->ep.desc)
return -EINVAL;
spin_lock_irqsave(&ep->dev->lock, iflags);
@@ -1742,7 +1741,6 @@ static int pch_udc_pcd_ep_disable(struct usb_ep *usbep)
ep->halted = 1;
pch_udc_ep_disable(ep);
pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
- ep->desc = NULL;
ep->ep.desc = NULL;
INIT_LIST_HEAD(&ep->queue);
spin_unlock_irqrestore(&ep->dev->lock, iflags);
@@ -1849,7 +1847,7 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
return -EINVAL;
ep = container_of(usbep, struct pch_udc_ep, ep);
dev = ep->dev;
- if (!ep->desc && ep->num)
+ if (!ep->ep.desc && ep->num)
return -EINVAL;
req = container_of(usbreq, struct pch_udc_request, req);
if (!list_empty(&req->queue))
@@ -1949,7 +1947,7 @@ static int pch_udc_pcd_dequeue(struct usb_ep *usbep,
ep = container_of(usbep, struct pch_udc_ep, ep);
dev = ep->dev;
- if (!usbep || !usbreq || (!ep->desc && ep->num))
+ if (!usbep || !usbreq || (!ep->ep.desc && ep->num))
return ret;
req = container_of(usbreq, struct pch_udc_request, req);
spin_lock_irqsave(&ep->dev->lock, flags);
@@ -1988,7 +1986,7 @@ static int pch_udc_pcd_set_halt(struct usb_ep *usbep, int halt)
return -EINVAL;
ep = container_of(usbep, struct pch_udc_ep, ep);
dev = ep->dev;
- if (!ep->desc && !ep->num)
+ if (!ep->ep.desc && !ep->num)
return -EINVAL;
if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN))
return -ESHUTDOWN;
@@ -2033,7 +2031,7 @@ static int pch_udc_pcd_set_wedge(struct usb_ep *usbep)
return -EINVAL;
ep = container_of(usbep, struct pch_udc_ep, ep);
dev = ep->dev;
- if (!ep->desc && !ep->num)
+ if (!ep->ep.desc && !ep->num)
return -EINVAL;
if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN))
return -ESHUTDOWN;
@@ -2065,7 +2063,7 @@ static void pch_udc_pcd_fifo_flush(struct usb_ep *usbep)
return;
ep = container_of(usbep, struct pch_udc_ep, ep);
- if (ep->desc || !ep->num)
+ if (ep->ep.desc || !ep->num)
pch_udc_ep_fifo_flush(ep, ep->in);
}
@@ -3282,7 +3280,6 @@ static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = {
MODULE_DEVICE_TABLE(pci, pch_udc_pcidev_id);
-
static struct pci_driver pch_udc_driver = {
.name = KBUILD_MODNAME,
.id_table = pch_udc_pcidev_id,
@@ -3293,17 +3290,7 @@ static struct pci_driver pch_udc_driver = {
.shutdown = pch_udc_shutdown,
};
-static int __init pch_udc_pci_init(void)
-{
- return pci_register_driver(&pch_udc_driver);
-}
-module_init(pch_udc_pci_init);
-
-static void __exit pch_udc_pci_exit(void)
-{
- pci_unregister_driver(&pch_udc_driver);
-}
-module_exit(pch_udc_pci_exit);
+module_pci_driver(pch_udc_driver);
MODULE_DESCRIPTION("Intel EG20T USB Device Controller");
MODULE_AUTHOR("LAPIS Semiconductor, <tomoya-linux@dsn.lapis-semi.com>");
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 4e4dc1f5f388..f1f9290a2f47 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -51,6 +51,7 @@
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
+#include "composite.c"
#include "usbstring.c"
#include "config.c"
#include "epautoconf.c"
@@ -75,8 +76,6 @@ struct printer_dev {
/* lock buffer lists during read/write calls */
struct mutex lock_printer_io;
struct usb_gadget *gadget;
- struct usb_request *req; /* for control responses */
- u8 config;
s8 interface;
struct usb_ep *in_ep, *out_ep;
@@ -100,6 +99,7 @@ struct printer_dev {
struct device *pdev;
u8 printer_cdev_open;
wait_queue_head_t wait;
+ struct usb_function function;
};
static struct printer_dev usb_printer_gadget;
@@ -120,26 +120,6 @@ static struct printer_dev usb_printer_gadget;
* parameters are in UTF-8 (superset of ASCII's 7 bit characters).
*/
-static ushort idVendor;
-module_param(idVendor, ushort, S_IRUGO);
-MODULE_PARM_DESC(idVendor, "USB Vendor ID");
-
-static ushort idProduct;
-module_param(idProduct, ushort, S_IRUGO);
-MODULE_PARM_DESC(idProduct, "USB Product ID");
-
-static ushort bcdDevice;
-module_param(bcdDevice, ushort, S_IRUGO);
-MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
-
-static char *iManufacturer;
-module_param(iManufacturer, charp, S_IRUGO);
-MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
-
-static char *iProduct;
-module_param(iProduct, charp, S_IRUGO);
-MODULE_PARM_DESC(iProduct, "USB Product string");
-
static char *iSerialNum;
module_param(iSerialNum, charp, S_IRUGO);
MODULE_PARM_DESC(iSerialNum, "1");
@@ -154,47 +134,8 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR);
#define QLEN qlen
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-#define DEVSPEED USB_SPEED_HIGH
-#else /* full speed (low speed doesn't do bulk) */
-#define DEVSPEED USB_SPEED_FULL
-#endif
-
/*-------------------------------------------------------------------------*/
-#define xprintk(d, level, fmt, args...) \
- printk(level "%s: " fmt, DRIVER_DESC, ## args)
-
-#ifdef DEBUG
-#define DBG(dev, fmt, args...) \
- xprintk(dev, KERN_DEBUG, fmt, ## args)
-#else
-#define DBG(dev, fmt, args...) \
- do { } while (0)
-#endif /* DEBUG */
-
-#ifdef VERBOSE
-#define VDBG(dev, fmt, args...) \
- xprintk(dev, KERN_DEBUG, fmt, ## args)
-#else
-#define VDBG(dev, fmt, args...) \
- do { } while (0)
-#endif /* VERBOSE */
-
-#define ERROR(dev, fmt, args...) \
- xprintk(dev, KERN_ERR, fmt, ## args)
-#define WARNING(dev, fmt, args...) \
- xprintk(dev, KERN_WARNING, fmt, ## args)
-#define INFO(dev, fmt, args...) \
- xprintk(dev, KERN_INFO, fmt, ## args)
-
-/*-------------------------------------------------------------------------*/
-
-/* USB DRIVER HOOKUP (to the hardware driver, below us), mostly
- * ep0 implementation: descriptors, config management, setup().
- * also optional class-specific notification interrupt transfer.
- */
-
/*
* DESCRIPTORS ... most are static, but strings and (full) configuration
* descriptors are built on demand.
@@ -227,24 +168,6 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1
};
-static struct usb_otg_descriptor otg_desc = {
- .bLength = sizeof otg_desc,
- .bDescriptorType = USB_DT_OTG,
- .bmAttributes = USB_OTG_SRP
-};
-
-static struct usb_config_descriptor config_desc = {
- .bLength = sizeof config_desc,
- .bDescriptorType = USB_DT_CONFIG,
-
- /* compute wTotalLength on the fly */
- .bNumInterfaces = 1,
- .bConfigurationValue = DEV_CONFIG_VALUE,
- .iConfiguration = 0,
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2,
-};
-
static struct usb_interface_descriptor intf_desc = {
.bLength = sizeof intf_desc,
.bDescriptorType = USB_DT_INTERFACE,
@@ -270,16 +193,13 @@ static struct usb_endpoint_descriptor fs_ep_out_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK
};
-static const struct usb_descriptor_header *fs_printer_function [11] = {
- (struct usb_descriptor_header *) &otg_desc,
+static struct usb_descriptor_header *fs_printer_function[] = {
(struct usb_descriptor_header *) &intf_desc,
(struct usb_descriptor_header *) &fs_ep_in_desc,
(struct usb_descriptor_header *) &fs_ep_out_desc,
NULL
};
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-
/*
* usb 2.0 devices need to expose both high speed and full speed
* descriptors, unless they only run at full speed.
@@ -307,23 +227,26 @@ static struct usb_qualifier_descriptor dev_qualifier = {
.bNumConfigurations = 1
};
-static const struct usb_descriptor_header *hs_printer_function [11] = {
- (struct usb_descriptor_header *) &otg_desc,
+static struct usb_descriptor_header *hs_printer_function[] = {
(struct usb_descriptor_header *) &intf_desc,
(struct usb_descriptor_header *) &hs_ep_in_desc,
(struct usb_descriptor_header *) &hs_ep_out_desc,
NULL
};
-/* maxpacket and other transfer characteristics vary by speed. */
-#define ep_desc(g, hs, fs) (((g)->speed == USB_SPEED_HIGH)?(hs):(fs))
-
-#else
+static struct usb_otg_descriptor otg_descriptor = {
+ .bLength = sizeof otg_descriptor,
+ .bDescriptorType = USB_DT_OTG,
+ .bmAttributes = USB_OTG_SRP,
+};
-/* if there's no high speed support, maxpacket doesn't change. */
-#define ep_desc(g, hs, fs) (((void)(g)), (fs))
+static const struct usb_descriptor_header *otg_desc[] = {
+ (struct usb_descriptor_header *) &otg_descriptor,
+ NULL,
+};
-#endif /* !CONFIG_USB_GADGET_DUALSPEED */
+/* maxpacket and other transfer characteristics vary by speed. */
+#define ep_desc(g, hs, fs) (((g)->speed == USB_SPEED_HIGH)?(hs):(fs))
/*-------------------------------------------------------------------------*/
@@ -343,11 +266,16 @@ static struct usb_string strings [] = {
{ } /* end of list */
};
-static struct usb_gadget_strings stringtab = {
+static struct usb_gadget_strings stringtab_dev = {
.language = 0x0409, /* en-us */
.strings = strings,
};
+static struct usb_gadget_strings *dev_strings[] = {
+ &stringtab_dev,
+ NULL,
+};
+
/*-------------------------------------------------------------------------*/
static struct usb_request *
@@ -937,82 +865,8 @@ static void printer_reset_interface(struct printer_dev *dev)
dev->interface = -1;
}
-/* change our operational config. must agree with the code
- * that returns config descriptors, and altsetting code.
- */
-static int
-printer_set_config(struct printer_dev *dev, unsigned number)
-{
- int result = 0;
- struct usb_gadget *gadget = dev->gadget;
-
- switch (number) {
- case DEV_CONFIG_VALUE:
- result = 0;
- break;
- default:
- result = -EINVAL;
- /* FALL THROUGH */
- case 0:
- break;
- }
-
- if (result) {
- usb_gadget_vbus_draw(dev->gadget,
- dev->gadget->is_otg ? 8 : 100);
- } else {
- unsigned power;
-
- power = 2 * config_desc.bMaxPower;
- usb_gadget_vbus_draw(dev->gadget, power);
-
- dev->config = number;
- INFO(dev, "%s config #%d: %d mA, %s\n",
- usb_speed_string(gadget->speed),
- number, power, driver_desc);
- }
- return result;
-}
-
-static int
-config_buf(enum usb_device_speed speed, u8 *buf, u8 type, unsigned index,
- int is_otg)
-{
- int len;
- const struct usb_descriptor_header **function;
-#ifdef CONFIG_USB_GADGET_DUALSPEED
- int hs = (speed == USB_SPEED_HIGH);
-
- if (type == USB_DT_OTHER_SPEED_CONFIG)
- hs = !hs;
-
- if (hs) {
- function = hs_printer_function;
- } else {
- function = fs_printer_function;
- }
-#else
- function = fs_printer_function;
-#endif
-
- if (index >= device_desc.bNumConfigurations)
- return -EINVAL;
-
- /* for now, don't advertise srp-only devices */
- if (!is_otg)
- function++;
-
- len = usb_gadget_config_buf(&config_desc, buf, USB_DESC_BUFSIZE,
- function);
- if (len < 0)
- return len;
- ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
- return len;
-}
-
/* Change our operational Interface. */
-static int
-set_interface(struct printer_dev *dev, unsigned number)
+static int set_interface(struct printer_dev *dev, unsigned number)
{
int result = 0;
@@ -1043,14 +897,6 @@ set_interface(struct printer_dev *dev, unsigned number)
return result;
}
-static void printer_setup_complete(struct usb_ep *ep, struct usb_request *req)
-{
- if (req->status || req->actual != req->length)
- DBG((struct printer_dev *) ep->driver_data,
- "setup complete --> %d, %d/%d\n",
- req->status, req->actual, req->length);
-}
-
static void printer_soft_reset(struct printer_dev *dev)
{
struct usb_request *req;
@@ -1107,11 +953,12 @@ static void printer_soft_reset(struct printer_dev *dev)
* The setup() callback implements all the ep0 functionality that's not
* handled lower down.
*/
-static int
-printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+static int printer_func_setup(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
{
- struct printer_dev *dev = get_gadget_data(gadget);
- struct usb_request *req = dev->req;
+ struct printer_dev *dev = container_of(f, struct printer_dev, function);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
int value = -EOPNOTSUPP;
u16 wIndex = le16_to_cpu(ctrl->wIndex);
u16 wValue = le16_to_cpu(ctrl->wValue);
@@ -1120,102 +967,7 @@ printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
DBG(dev, "ctrl req%02x.%02x v%04x i%04x l%d\n",
ctrl->bRequestType, ctrl->bRequest, wValue, wIndex, wLength);
- req->complete = printer_setup_complete;
-
switch (ctrl->bRequestType&USB_TYPE_MASK) {
-
- case USB_TYPE_STANDARD:
- switch (ctrl->bRequest) {
-
- case USB_REQ_GET_DESCRIPTOR:
- if (ctrl->bRequestType != USB_DIR_IN)
- break;
- switch (wValue >> 8) {
-
- case USB_DT_DEVICE:
- device_desc.bMaxPacketSize0 =
- gadget->ep0->maxpacket;
- value = min(wLength, (u16) sizeof device_desc);
- memcpy(req->buf, &device_desc, value);
- break;
-#ifdef CONFIG_USB_GADGET_DUALSPEED
- case USB_DT_DEVICE_QUALIFIER:
- if (!gadget_is_dualspeed(gadget))
- break;
- /*
- * assumes ep0 uses the same value for both
- * speeds
- */
- dev_qualifier.bMaxPacketSize0 =
- gadget->ep0->maxpacket;
- value = min(wLength,
- (u16) sizeof dev_qualifier);
- memcpy(req->buf, &dev_qualifier, value);
- break;
-
- case USB_DT_OTHER_SPEED_CONFIG:
- if (!gadget_is_dualspeed(gadget))
- break;
- /* FALLTHROUGH */
-#endif /* CONFIG_USB_GADGET_DUALSPEED */
- case USB_DT_CONFIG:
- value = config_buf(gadget->speed, req->buf,
- wValue >> 8,
- wValue & 0xff,
- gadget->is_otg);
- if (value >= 0)
- value = min(wLength, (u16) value);
- break;
-
- case USB_DT_STRING:
- value = usb_gadget_get_string(&stringtab,
- wValue & 0xff, req->buf);
- if (value >= 0)
- value = min(wLength, (u16) value);
- break;
- }
- break;
-
- case USB_REQ_SET_CONFIGURATION:
- if (ctrl->bRequestType != 0)
- break;
- if (gadget->a_hnp_support)
- DBG(dev, "HNP available\n");
- else if (gadget->a_alt_hnp_support)
- DBG(dev, "HNP needs a different root port\n");
- value = printer_set_config(dev, wValue);
- if (!value)
- value = set_interface(dev, PRINTER_INTERFACE);
- break;
- case USB_REQ_GET_CONFIGURATION:
- if (ctrl->bRequestType != USB_DIR_IN)
- break;
- *(u8 *)req->buf = dev->config;
- value = min(wLength, (u16) 1);
- break;
-
- case USB_REQ_SET_INTERFACE:
- if (ctrl->bRequestType != USB_RECIP_INTERFACE ||
- !dev->config)
- break;
-
- value = set_interface(dev, PRINTER_INTERFACE);
- break;
- case USB_REQ_GET_INTERFACE:
- if (ctrl->bRequestType !=
- (USB_DIR_IN|USB_RECIP_INTERFACE)
- || !dev->config)
- break;
-
- *(u8 *)req->buf = dev->interface;
- value = min(wLength, (u16) 1);
- break;
-
- default:
- goto unknown;
- }
- break;
-
case USB_TYPE_CLASS:
switch (ctrl->bRequest) {
case 0: /* Get the IEEE-1284 PNP String */
@@ -1261,44 +1013,50 @@ unknown:
wValue, wIndex, wLength);
break;
}
-
- /* respond with data transfer before status phase? */
- if (value >= 0) {
- req->length = value;
- req->zero = value < wLength;
- value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
- if (value < 0) {
- DBG(dev, "ep_queue --> %d\n", value);
- req->status = 0;
- printer_setup_complete(gadget->ep0, req);
- }
- }
-
/* host either stalls (value < 0) or reports success */
return value;
}
-static void
-printer_disconnect(struct usb_gadget *gadget)
+static int __init printer_func_bind(struct usb_configuration *c,
+ struct usb_function *f)
{
- struct printer_dev *dev = get_gadget_data(gadget);
+ return 0;
+}
+
+static void printer_func_unbind(struct usb_configuration *c,
+ struct usb_function *f)
+{
+}
+
+static int printer_func_set_alt(struct usb_function *f,
+ unsigned intf, unsigned alt)
+{
+ struct printer_dev *dev = container_of(f, struct printer_dev, function);
+ int ret = -ENOTSUPP;
+
+ if (!alt)
+ ret = set_interface(dev, PRINTER_INTERFACE);
+ return ret;
+}
+
+static void printer_func_disable(struct usb_function *f)
+{
+ struct printer_dev *dev = container_of(f, struct printer_dev, function);
unsigned long flags;
DBG(dev, "%s\n", __func__);
spin_lock_irqsave(&dev->lock, flags);
-
printer_reset_interface(dev);
-
spin_unlock_irqrestore(&dev->lock, flags);
}
-static void
-printer_unbind(struct usb_gadget *gadget)
+static void printer_cfg_unbind(struct usb_configuration *c)
{
- struct printer_dev *dev = get_gadget_data(gadget);
+ struct printer_dev *dev;
struct usb_request *req;
+ dev = &usb_printer_gadget;
DBG(dev, "%s\n", __func__);
@@ -1336,18 +1094,18 @@ printer_unbind(struct usb_gadget *gadget)
list_del(&req->list);
printer_req_free(dev->out_ep, req);
}
-
- if (dev->req) {
- printer_req_free(gadget->ep0, dev->req);
- dev->req = NULL;
- }
-
- set_gadget_data(gadget, NULL);
}
-static int __init
-printer_bind(struct usb_gadget *gadget)
+static struct usb_configuration printer_cfg_driver = {
+ .label = "printer",
+ .unbind = printer_cfg_unbind,
+ .bConfigurationValue = 1,
+ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+};
+
+static int __init printer_bind_config(struct usb_configuration *c)
{
+ struct usb_gadget *gadget = c->cdev->gadget;
struct printer_dev *dev;
struct usb_ep *in_ep, *out_ep;
int status = -ENOMEM;
@@ -1358,6 +1116,14 @@ printer_bind(struct usb_gadget *gadget)
dev = &usb_printer_gadget;
+ dev->function.name = shortname;
+ dev->function.descriptors = fs_printer_function;
+ dev->function.hs_descriptors = hs_printer_function;
+ dev->function.bind = printer_func_bind;
+ dev->function.setup = printer_func_setup;
+ dev->function.unbind = printer_func_unbind;
+ dev->function.set_alt = printer_func_set_alt;
+ dev->function.disable = printer_func_disable;
/* Setup the sysfs files for the printer gadget. */
dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
@@ -1393,29 +1159,6 @@ printer_bind(struct usb_gadget *gadget)
init_utsname()->sysname, init_utsname()->release,
gadget->name);
- device_desc.idVendor =
- cpu_to_le16(PRINTER_VENDOR_NUM);
- device_desc.idProduct =
- cpu_to_le16(PRINTER_PRODUCT_NUM);
-
- /* support optional vendor/distro customization */
- if (idVendor) {
- if (!idProduct) {
- dev_err(&gadget->dev, "idVendor needs idProduct!\n");
- return -ENODEV;
- }
- device_desc.idVendor = cpu_to_le16(idVendor);
- device_desc.idProduct = cpu_to_le16(idProduct);
- if (bcdDevice)
- device_desc.bcdDevice = cpu_to_le16(bcdDevice);
- }
-
- if (iManufacturer)
- strlcpy(manufacturer, iManufacturer, sizeof manufacturer);
-
- if (iProduct)
- strlcpy(product_desc, iProduct, sizeof product_desc);
-
if (iSerialNum)
strlcpy(serial_num, iSerialNum, sizeof serial_num);
@@ -1442,17 +1185,16 @@ autoconf_fail:
goto autoconf_fail;
out_ep->driver_data = out_ep; /* claim */
-#ifdef CONFIG_USB_GADGET_DUALSPEED
/* assumes that all endpoints are dual-speed */
hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
-#endif /* DUALSPEED */
usb_gadget_set_selfpowered(gadget);
if (gadget->is_otg) {
- otg_desc.bmAttributes |= USB_OTG_HNP,
- config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+ otg_descriptor.bmAttributes |= USB_OTG_HNP;
+ printer_cfg_driver.descriptors = otg_desc;
+ printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
spin_lock_init(&dev->lock);
@@ -1466,7 +1208,6 @@ autoconf_fail:
init_waitqueue_head(&dev->tx_wait);
init_waitqueue_head(&dev->tx_flush_wait);
- dev->config = 0;
dev->interface = -1;
dev->printer_cdev_open = 0;
dev->printer_status = PRINTER_NOT_ERROR;
@@ -1477,14 +1218,6 @@ autoconf_fail:
dev->in_ep = in_ep;
dev->out_ep = out_ep;
- /* preallocate control message data and buffer */
- dev->req = printer_req_alloc(gadget->ep0, USB_DESC_BUFSIZE,
- GFP_KERNEL);
- if (!dev->req) {
- status = -ENOMEM;
- goto fail;
- }
-
for (i = 0; i < QLEN; i++) {
req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL);
if (!req) {
@@ -1513,45 +1246,37 @@ autoconf_fail:
list_add(&req->list, &dev->rx_reqs);
}
- dev->req->complete = printer_setup_complete;
-
/* finish hookup to lower layer ... */
dev->gadget = gadget;
- set_gadget_data(gadget, dev);
- gadget->ep0->driver_data = dev;
INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, out_ep->name,
in_ep->name);
-
return 0;
fail:
- printer_unbind(gadget);
+ printer_cfg_unbind(c);
return status;
}
-/*-------------------------------------------------------------------------*/
+static int printer_unbind(struct usb_composite_dev *cdev)
+{
+ return 0;
+}
-static struct usb_gadget_driver printer_driver = {
- .max_speed = DEVSPEED,
+static int __init printer_bind(struct usb_composite_dev *cdev)
+{
+ return usb_add_config(cdev, &printer_cfg_driver, printer_bind_config);
+}
- .function = (char *) driver_desc,
+static struct usb_composite_driver printer_driver = {
+ .name = shortname,
+ .dev = &device_desc,
+ .strings = dev_strings,
+ .max_speed = USB_SPEED_HIGH,
.unbind = printer_unbind,
-
- .setup = printer_setup,
- .disconnect = printer_disconnect,
-
- .driver = {
- .name = (char *) shortname,
- .owner = THIS_MODULE,
- },
};
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Craig Nadler");
-MODULE_LICENSE("GPL");
-
static int __init
init(void)
{
@@ -1560,23 +1285,23 @@ init(void)
usb_gadget_class = class_create(THIS_MODULE, "usb_printer_gadget");
if (IS_ERR(usb_gadget_class)) {
status = PTR_ERR(usb_gadget_class);
- ERROR(dev, "unable to create usb_gadget class %d\n", status);
+ pr_err("unable to create usb_gadget class %d\n", status);
return status;
}
status = alloc_chrdev_region(&g_printer_devno, 0, 1,
"USB printer gadget");
if (status) {
- ERROR(dev, "alloc_chrdev_region %d\n", status);
+ pr_err("alloc_chrdev_region %d\n", status);
class_destroy(usb_gadget_class);
return status;
}
- status = usb_gadget_probe_driver(&printer_driver, printer_bind);
+ status = usb_composite_probe(&printer_driver, printer_bind);
if (status) {
class_destroy(usb_gadget_class);
unregister_chrdev_region(g_printer_devno, 1);
- DBG(dev, "usb_gadget_probe_driver %x\n", status);
+ pr_err("usb_gadget_probe_driver %x\n", status);
}
return status;
@@ -1586,15 +1311,14 @@ module_init(init);
static void __exit
cleanup(void)
{
- int status;
-
mutex_lock(&usb_printer_gadget.lock_printer_io);
- status = usb_gadget_unregister_driver(&printer_driver);
- if (status)
- ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
-
+ usb_composite_unregister(&printer_driver);
unregister_chrdev_region(g_printer_devno, 1);
class_destroy(usb_gadget_class);
mutex_unlock(&usb_printer_gadget.lock_printer_io);
}
module_exit(cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Craig Nadler");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index 41ed69c96d8c..d7c8cb3bf759 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -218,7 +218,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep,
struct pxa25x_udc *dev;
ep = container_of (_ep, struct pxa25x_ep, ep);
- if (!_ep || !desc || ep->desc || _ep->name == ep0name
+ if (!_ep || !desc || ep->ep.desc || _ep->name == ep0name
|| desc->bDescriptorType != USB_DT_ENDPOINT
|| ep->bEndpointAddress != desc->bEndpointAddress
|| ep->fifo_size < usb_endpoint_maxp (desc)) {
@@ -249,7 +249,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep,
return -ESHUTDOWN;
}
- ep->desc = desc;
+ ep->ep.desc = desc;
ep->stopped = 0;
ep->pio_irqs = 0;
ep->ep.maxpacket = usb_endpoint_maxp (desc);
@@ -269,7 +269,7 @@ static int pxa25x_ep_disable (struct usb_ep *_ep)
unsigned long flags;
ep = container_of (_ep, struct pxa25x_ep, ep);
- if (!_ep || !ep->desc) {
+ if (!_ep || !ep->ep.desc) {
DMSG("%s, %s not enabled\n", __func__,
_ep ? ep->ep.name : NULL);
return -EINVAL;
@@ -281,7 +281,6 @@ static int pxa25x_ep_disable (struct usb_ep *_ep)
/* flush fifo (mostly for IN buffers) */
pxa25x_ep_fifo_flush (_ep);
- ep->desc = NULL;
ep->ep.desc = NULL;
ep->stopped = 1;
@@ -390,7 +389,7 @@ write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
{
unsigned max;
- max = usb_endpoint_maxp(ep->desc);
+ max = usb_endpoint_maxp(ep->ep.desc);
do {
unsigned count;
int is_last, is_short;
@@ -644,7 +643,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
}
ep = container_of(_ep, struct pxa25x_ep, ep);
- if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+ if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) {
DMSG("%s, bad ep\n", __func__);
return -EINVAL;
}
@@ -660,7 +659,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
* we can report per-packet status. that also helps with dma.
*/
if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
- && req->req.length > usb_endpoint_maxp (ep->desc)))
+ && req->req.length > usb_endpoint_maxp(ep->ep.desc)))
return -EMSGSIZE;
DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n",
@@ -673,7 +672,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
/* kickstart this i/o queue? */
if (list_empty(&ep->queue) && !ep->stopped) {
- if (ep->desc == NULL/* ep0 */) {
+ if (ep->ep.desc == NULL/* ep0 */) {
unsigned length = _req->length;
switch (dev->ep0state) {
@@ -722,7 +721,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
req = NULL;
}
- if (likely (req && ep->desc))
+ if (likely(req && ep->ep.desc))
pio_irq_enable(ep->bEndpointAddress);
}
@@ -749,7 +748,7 @@ static void nuke(struct pxa25x_ep *ep, int status)
queue);
done(ep, req, status);
}
- if (ep->desc)
+ if (ep->ep.desc)
pio_irq_disable (ep->bEndpointAddress);
}
@@ -792,7 +791,7 @@ static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value)
ep = container_of(_ep, struct pxa25x_ep, ep);
if (unlikely (!_ep
- || (!ep->desc && ep->ep.name != ep0name))
+ || (!ep->ep.desc && ep->ep.name != ep0name))
|| ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
DMSG("%s, bad ep\n", __func__);
return -EINVAL;
@@ -820,7 +819,7 @@ static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value)
*ep->reg_udccs = UDCCS_BI_FST|UDCCS_BI_FTF;
/* ep0 needs special care */
- if (!ep->desc) {
+ if (!ep->ep.desc) {
start_watchdog(ep->dev);
ep->dev->req_pending = 0;
ep->dev->ep0state = EP0_STALL;
@@ -1087,7 +1086,7 @@ udc_seq_show(struct seq_file *m, void *_d)
if (i != 0) {
const struct usb_endpoint_descriptor *desc;
- desc = ep->desc;
+ desc = ep->ep.desc;
if (!desc)
continue;
tmp = *dev->ep [i].reg_udccs;
@@ -1191,7 +1190,6 @@ static void udc_reinit(struct pxa25x_udc *dev)
if (i != 0)
list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
- ep->desc = NULL;
ep->ep.desc = NULL;
ep->stopped = 0;
INIT_LIST_HEAD (&ep->queue);
diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h
index 893e917f048e..861f4df6ea22 100644
--- a/drivers/usb/gadget/pxa25x_udc.h
+++ b/drivers/usb/gadget/pxa25x_udc.h
@@ -41,7 +41,6 @@ struct pxa25x_ep {
struct usb_ep ep;
struct pxa25x_udc *dev;
- const struct usb_endpoint_descriptor *desc;
struct list_head queue;
unsigned long pio_irqs;
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index c4401e7dd3a6..f3ac2a20c27c 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -459,7 +459,7 @@ static int alloc_pipe_config(struct r8a66597_ep *ep,
unsigned char *counter;
int ret;
- ep->desc = desc;
+ ep->ep.desc = desc;
if (ep->pipenum) /* already allocated pipe */
return 0;
@@ -648,7 +648,7 @@ static int sudmac_alloc_channel(struct r8a66597 *r8a66597,
/* set SUDMAC parameters */
dma = &r8a66597->dma;
dma->used = 1;
- if (ep->desc->bEndpointAddress & USB_DIR_IN) {
+ if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) {
dma->dir = 1;
} else {
dma->dir = 0;
@@ -770,7 +770,7 @@ static void start_packet_read(struct r8a66597_ep *ep,
static void start_packet(struct r8a66597_ep *ep, struct r8a66597_request *req)
{
- if (ep->desc->bEndpointAddress & USB_DIR_IN)
+ if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
start_packet_write(ep, req);
else
start_packet_read(ep, req);
@@ -930,7 +930,7 @@ __acquires(r8a66597->lock)
if (restart) {
req = get_request_from_ep(ep);
- if (ep->desc)
+ if (ep->ep.desc)
start_packet(ep, req);
}
}
@@ -1116,7 +1116,7 @@ static void irq_pipe_ready(struct r8a66597 *r8a66597, u16 status, u16 enb)
r8a66597_write(r8a66597, ~check, BRDYSTS);
ep = r8a66597->pipenum2ep[pipenum];
req = get_request_from_ep(ep);
- if (ep->desc->bEndpointAddress & USB_DIR_IN)
+ if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
irq_packet_write(ep, req);
else
irq_packet_read(ep, req);
@@ -1170,7 +1170,7 @@ __acquires(r8a66597->lock)
switch (ctrl->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_DEVICE:
- status = 1 << USB_DEVICE_SELF_POWERED;
+ status = r8a66597->device_status;
break;
case USB_RECIP_INTERFACE:
status = 0;
@@ -1627,7 +1627,7 @@ static int r8a66597_queue(struct usb_ep *_ep, struct usb_request *_req,
req->req.actual = 0;
req->req.status = -EINPROGRESS;
- if (ep->desc == NULL) /* control */
+ if (ep->ep.desc == NULL) /* control */
start_ep0(ep, req);
else {
if (request && !ep->busy)
@@ -1692,7 +1692,7 @@ static int r8a66597_set_wedge(struct usb_ep *_ep)
ep = container_of(_ep, struct r8a66597_ep, ep);
- if (!ep || !ep->desc)
+ if (!ep || !ep->ep.desc)
return -EINVAL;
spin_lock_irqsave(&ep->r8a66597->lock, flags);
@@ -1800,11 +1800,24 @@ static int r8a66597_pullup(struct usb_gadget *gadget, int is_on)
return 0;
}
+static int r8a66597_set_selfpowered(struct usb_gadget *gadget, int is_self)
+{
+ struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
+
+ if (is_self)
+ r8a66597->device_status |= 1 << USB_DEVICE_SELF_POWERED;
+ else
+ r8a66597->device_status &= ~(1 << USB_DEVICE_SELF_POWERED);
+
+ return 0;
+}
+
static struct usb_gadget_ops r8a66597_gadget_ops = {
.get_frame = r8a66597_get_frame,
.udc_start = r8a66597_start,
.udc_stop = r8a66597_stop,
.pullup = r8a66597_pullup,
+ .set_selfpowered = r8a66597_set_selfpowered,
};
static int __exit r8a66597_remove(struct platform_device *pdev)
diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h
index 8e3de61cd4b8..99908c76ccd1 100644
--- a/drivers/usb/gadget/r8a66597-udc.h
+++ b/drivers/usb/gadget/r8a66597-udc.h
@@ -72,7 +72,7 @@ struct r8a66597_ep {
unsigned use_dma:1;
u16 pipenum;
u16 type;
- const struct usb_endpoint_descriptor *desc;
+
/* register address */
unsigned char fifoaddr;
unsigned char fifosel;
@@ -111,6 +111,7 @@ struct r8a66597 {
u16 old_vbus;
u16 scount;
u16 old_dvsq;
+ u16 device_status; /* for GET_STATUS */
/* pipe config */
unsigned char bulk;
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 105b206cd844..f4abb0ed9872 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -1,4 +1,5 @@
-/* linux/drivers/usb/gadget/s3c-hsotg.c
+/**
+ * linux/drivers/usb/gadget/s3c-hsotg.c
*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
@@ -13,7 +14,7 @@
* 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>
@@ -27,21 +28,25 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
+#include <linux/platform_data/s3c-hsotg.h>
#include <mach/map.h>
-#include <plat/regs-usb-hsotg-phy.h>
-#include <plat/regs-usb-hsotg.h>
-#include <mach/regs-sys.h>
-#include <plat/udc-hs.h>
-#include <plat/cpu.h>
+#include "s3c-hsotg.h"
#define DMA_ADDR_INVALID (~((dma_addr_t)0))
-/* EP0_MPS_LIMIT
+static const char * const s3c_hsotg_supply_names[] = {
+ "vusb_d", /* digital USB supply, 1.2V */
+ "vusb_a", /* analog USB supply, 1.1V */
+};
+
+/*
+ * EP0_MPS_LIMIT
*
* Unfortunately there seems to be a limit of the amount of data that can
* be transferred by IN transactions on EP0. This is either 127 bytes or 3
@@ -125,8 +130,6 @@ struct s3c_hsotg_ep {
char name[10];
};
-#define S3C_HSOTG_EPS (8+1) /* limit to 9 for the moment */
-
/**
* struct s3c_hsotg - driver state.
* @dev: The parent device supplied to the probe function
@@ -135,7 +138,9 @@ struct s3c_hsotg_ep {
* @regs: The memory area mapped for accessing registers.
* @regs_res: The resource that was allocated when claiming register space.
* @irq: The IRQ number we are using
+ * @supplies: Definition of USB power supplies
* @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
+ * @num_of_eps: Number of available EPs (excluding EP0)
* @debug_root: root directrory for debugfs.
* @debug_file: main status file for debugfs.
* @debug_fifo: FIFO status file for debugfs.
@@ -143,6 +148,8 @@ struct s3c_hsotg_ep {
* @ep0_buff: Buffer for EP0 reply data, if needed.
* @ctrl_buff: Buffer for EP0 control requests.
* @ctrl_req: Request for EP0 control packets.
+ * @setup: NAK management for EP0 SETUP
+ * @last_rst: Time of last reset
* @eps: The endpoints being supplied to the gadget framework
*/
struct s3c_hsotg {
@@ -155,7 +162,10 @@ struct s3c_hsotg {
int irq;
struct clk *clk;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)];
+
unsigned int dedicated_fifos:1;
+ unsigned char num_of_eps;
struct dentry *debug_root;
struct dentry *debug_file;
@@ -167,7 +177,9 @@ struct s3c_hsotg {
u8 ctrl_buff[8];
struct usb_gadget gadget;
- struct s3c_hsotg_ep eps[];
+ unsigned int setup;
+ unsigned long last_rst;
+ struct s3c_hsotg_ep *eps;
};
/**
@@ -244,14 +256,14 @@ static inline bool using_dma(struct s3c_hsotg *hsotg)
*/
static void s3c_hsotg_en_gsint(struct s3c_hsotg *hsotg, u32 ints)
{
- u32 gsintmsk = readl(hsotg->regs + S3C_GINTMSK);
+ u32 gsintmsk = readl(hsotg->regs + GINTMSK);
u32 new_gsintmsk;
new_gsintmsk = gsintmsk | ints;
if (new_gsintmsk != gsintmsk) {
dev_dbg(hsotg->dev, "gsintmsk now 0x%08x\n", new_gsintmsk);
- writel(new_gsintmsk, hsotg->regs + S3C_GINTMSK);
+ writel(new_gsintmsk, hsotg->regs + GINTMSK);
}
}
@@ -262,13 +274,13 @@ static void s3c_hsotg_en_gsint(struct s3c_hsotg *hsotg, u32 ints)
*/
static void s3c_hsotg_disable_gsint(struct s3c_hsotg *hsotg, u32 ints)
{
- u32 gsintmsk = readl(hsotg->regs + S3C_GINTMSK);
+ u32 gsintmsk = readl(hsotg->regs + GINTMSK);
u32 new_gsintmsk;
new_gsintmsk = gsintmsk & ~ints;
if (new_gsintmsk != gsintmsk)
- writel(new_gsintmsk, hsotg->regs + S3C_GINTMSK);
+ writel(new_gsintmsk, hsotg->regs + GINTMSK);
}
/**
@@ -293,12 +305,12 @@ static void s3c_hsotg_ctrl_epint(struct s3c_hsotg *hsotg,
bit <<= 16;
local_irq_save(flags);
- daint = readl(hsotg->regs + S3C_DAINTMSK);
+ daint = readl(hsotg->regs + DAINTMSK);
if (en)
daint |= bit;
else
daint &= ~bit;
- writel(daint, hsotg->regs + S3C_DAINTMSK);
+ writel(daint, hsotg->regs + DAINTMSK);
local_irq_restore(flags);
}
@@ -314,52 +326,51 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
int timeout;
u32 val;
- /* the ryu 2.6.24 release ahs
- writel(0x1C0, hsotg->regs + S3C_GRXFSIZ);
- writel(S3C_GNPTXFSIZ_NPTxFStAddr(0x200) |
- S3C_GNPTXFSIZ_NPTxFDep(0x1C0),
- hsotg->regs + S3C_GNPTXFSIZ);
- */
-
/* set FIFO sizes to 2048/1024 */
- writel(2048, hsotg->regs + S3C_GRXFSIZ);
- writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) |
- S3C_GNPTXFSIZ_NPTxFDep(1024),
- hsotg->regs + S3C_GNPTXFSIZ);
+ writel(2048, hsotg->regs + GRXFSIZ);
+ writel(GNPTXFSIZ_NPTxFStAddr(2048) |
+ GNPTXFSIZ_NPTxFDep(1024),
+ hsotg->regs + GNPTXFSIZ);
- /* arange all the rest of the TX FIFOs, as some versions of this
+ /*
+ * arange all the rest of the TX FIFOs, as some versions of this
* block have overlapping default addresses. This also ensures
* that if the settings have been changed, then they are set to
- * known values. */
+ * known values.
+ */
/* start at the end of the GNPTXFSIZ, rounded up */
addr = 2048 + 1024;
size = 768;
- /* currently we allocate TX FIFOs for all possible endpoints,
- * and assume that they are all the same size. */
+ /*
+ * currently we allocate TX FIFOs for all possible endpoints,
+ * and assume that they are all the same size.
+ */
for (ep = 1; ep <= 15; ep++) {
val = addr;
- val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT;
+ val |= size << DPTXFSIZn_DPTxFSize_SHIFT;
addr += size;
- writel(val, hsotg->regs + S3C_DPTXFSIZn(ep));
+ writel(val, hsotg->regs + DPTXFSIZn(ep));
}
- /* according to p428 of the design guide, we need to ensure that
- * all fifos are flushed before continuing */
+ /*
+ * according to p428 of the design guide, we need to ensure that
+ * all fifos are flushed before continuing
+ */
- writel(S3C_GRSTCTL_TxFNum(0x10) | S3C_GRSTCTL_TxFFlsh |
- S3C_GRSTCTL_RxFFlsh, hsotg->regs + S3C_GRSTCTL);
+ writel(GRSTCTL_TxFNum(0x10) | GRSTCTL_TxFFlsh |
+ GRSTCTL_RxFFlsh, hsotg->regs + GRSTCTL);
/* wait until the fifos are both flushed */
timeout = 100;
while (1) {
- val = readl(hsotg->regs + S3C_GRSTCTL);
+ val = readl(hsotg->regs + GRSTCTL);
- if ((val & (S3C_GRSTCTL_TxFFlsh | S3C_GRSTCTL_RxFFlsh)) == 0)
+ if ((val & (GRSTCTL_TxFFlsh | GRSTCTL_RxFFlsh)) == 0)
break;
if (--timeout == 0) {
@@ -415,7 +426,7 @@ static inline int is_ep_periodic(struct s3c_hsotg_ep *hs_ep)
*
* This is the reverse of s3c_hsotg_map_dma(), called for the completion
* of a request to ensure the buffer is ready for access by the caller.
-*/
+ */
static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
struct s3c_hsotg_req *hs_req)
@@ -456,13 +467,13 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,
* otherwise -ENOSPC is returned if the FIFO space was used up.
*
* This routine is only needed for PIO
-*/
+ */
static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
struct s3c_hsotg_req *hs_req)
{
bool periodic = is_ep_periodic(hs_ep);
- u32 gnptxsts = readl(hsotg->regs + S3C_GNPTXSTS);
+ u32 gnptxsts = readl(hsotg->regs + GNPTXSTS);
int buf_pos = hs_req->req.actual;
int to_write = hs_ep->size_loaded;
void *data;
@@ -476,20 +487,23 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
return 0;
if (periodic && !hsotg->dedicated_fifos) {
- u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index));
+ u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
int size_left;
int size_done;
- /* work out how much data was loaded so we can calculate
- * how much data is left in the fifo. */
+ /*
+ * work out how much data was loaded so we can calculate
+ * how much data is left in the fifo.
+ */
- size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
+ size_left = DxEPTSIZ_XferSize_GET(epsize);
- /* if shared fifo, we cannot write anything until the
+ /*
+ * if shared fifo, we cannot write anything until the
* previous data has been completely sent.
*/
if (hs_ep->fifo_load != 0) {
- s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
+ s3c_hsotg_en_gsint(hsotg, GINTSTS_PTxFEmp);
return -ENOSPC;
}
@@ -510,47 +524,50 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
__func__, can_write);
if (can_write <= 0) {
- s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
+ s3c_hsotg_en_gsint(hsotg, GINTSTS_PTxFEmp);
return -ENOSPC;
}
} else if (hsotg->dedicated_fifos && hs_ep->index != 0) {
- can_write = readl(hsotg->regs + S3C_DTXFSTS(hs_ep->index));
+ can_write = readl(hsotg->regs + DTXFSTS(hs_ep->index));
can_write &= 0xffff;
can_write *= 4;
} else {
- if (S3C_GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) {
+ if (GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) {
dev_dbg(hsotg->dev,
"%s: no queue slots available (0x%08x)\n",
__func__, gnptxsts);
- s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_NPTxFEmp);
+ s3c_hsotg_en_gsint(hsotg, GINTSTS_NPTxFEmp);
return -ENOSPC;
}
- can_write = S3C_GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts);
+ can_write = GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts);
can_write *= 4; /* fifo size is in 32bit quantities. */
}
dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n",
__func__, gnptxsts, can_write, to_write, hs_ep->ep.maxpacket);
- /* limit to 512 bytes of data, it seems at least on the non-periodic
+ /*
+ * limit to 512 bytes of data, it seems at least on the non-periodic
* FIFO, requests of >512 cause the endpoint to get stuck with a
* fragment of the end of the transfer in it.
*/
if (can_write > 512)
can_write = 512;
- /* limit the write to one max-packet size worth of data, but allow
+ /*
+ * limit the write to one max-packet size worth of data, but allow
* the transfer to return that it did not run out of fifo space
- * doing it. */
+ * doing it.
+ */
if (to_write > hs_ep->ep.maxpacket) {
to_write = hs_ep->ep.maxpacket;
s3c_hsotg_en_gsint(hsotg,
- periodic ? S3C_GINTSTS_PTxFEmp :
- S3C_GINTSTS_NPTxFEmp);
+ periodic ? GINTSTS_PTxFEmp :
+ GINTSTS_NPTxFEmp);
}
/* see if we can write data */
@@ -559,8 +576,8 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
to_write = can_write;
pkt_round = to_write % hs_ep->ep.maxpacket;
- /* Not sure, but we probably shouldn't be writing partial
- * packets into the FIFO, so round the write down to an
+ /*
+ * Round the write down to an
* exact number of packets.
*
* Note, we do not currently check to see if we can ever
@@ -570,12 +587,14 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
if (pkt_round)
to_write -= pkt_round;
- /* enable correct FIFO interrupt to alert us when there
- * is more room left. */
+ /*
+ * enable correct FIFO interrupt to alert us when there
+ * is more room left.
+ */
s3c_hsotg_en_gsint(hsotg,
- periodic ? S3C_GINTSTS_PTxFEmp :
- S3C_GINTSTS_NPTxFEmp);
+ periodic ? GINTSTS_PTxFEmp :
+ GINTSTS_NPTxFEmp);
}
dev_dbg(hsotg->dev, "write %d/%d, can_write %d, done %d\n",
@@ -593,7 +612,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
to_write = DIV_ROUND_UP(to_write, 4);
data = hs_req->req.buf + buf_pos;
- writesl(hsotg->regs + S3C_EPFIFO(hs_ep->index), data, to_write);
+ writesl(hsotg->regs + EPFIFO(hs_ep->index), data, to_write);
return (to_write >= can_write) ? -ENOSPC : 0;
}
@@ -612,12 +631,12 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep)
unsigned maxpkt;
if (index != 0) {
- maxsize = S3C_DxEPTSIZ_XferSize_LIMIT + 1;
- maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1;
+ maxsize = DxEPTSIZ_XferSize_LIMIT + 1;
+ maxpkt = DxEPTSIZ_PktCnt_LIMIT + 1;
} else {
maxsize = 64+64;
if (hs_ep->dir_in)
- maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1;
+ maxpkt = DIEPTSIZ0_PktCnt_LIMIT + 1;
else
maxpkt = 2;
}
@@ -626,8 +645,10 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep)
maxpkt--;
maxsize--;
- /* constrain by packet count if maxpkts*pktsize is greater
- * than the length register size. */
+ /*
+ * constrain by packet count if maxpkts*pktsize is greater
+ * than the length register size.
+ */
if ((maxpkt * hs_ep->ep.maxpacket) < maxsize)
maxsize = maxpkt * hs_ep->ep.maxpacket;
@@ -674,8 +695,8 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
}
}
- epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index);
- epsize_reg = dir_in ? S3C_DIEPTSIZ(index) : S3C_DOEPTSIZ(index);
+ epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
+ epsize_reg = dir_in ? DIEPTSIZ(index) : DOEPTSIZ(index);
dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x, ep %d, dir %s\n",
__func__, readl(hsotg->regs + epctrl_reg), index,
@@ -684,13 +705,14 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
/* If endpoint is stalled, we will restart request later */
ctrl = readl(hsotg->regs + epctrl_reg);
- if (ctrl & S3C_DxEPCTL_Stall) {
+ if (ctrl & DxEPCTL_Stall) {
dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index);
return;
}
length = ureq->length - ureq->actual;
-
+ dev_dbg(hsotg->dev, "ureq->length:%d ureq->actual:%d\n",
+ ureq->length, ureq->actual);
if (0)
dev_dbg(hsotg->dev,
"REQ buf %p len %d dma 0x%08x noi=%d zp=%d snok=%d\n",
@@ -717,20 +739,22 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
packets = 1; /* send one packet if length is zero. */
if (dir_in && index != 0)
- epsize = S3C_DxEPTSIZ_MC(1);
+ epsize = DxEPTSIZ_MC(1);
else
epsize = 0;
if (index != 0 && ureq->zero) {
- /* test for the packets being exactly right for the
- * transfer */
+ /*
+ * test for the packets being exactly right for the
+ * transfer
+ */
if (length == (packets * hs_ep->ep.maxpacket))
packets++;
}
- epsize |= S3C_DxEPTSIZ_PktCnt(packets);
- epsize |= S3C_DxEPTSIZ_XferSize(length);
+ epsize |= DxEPTSIZ_PktCnt(packets);
+ epsize |= DxEPTSIZ_XferSize(length);
dev_dbg(hsotg->dev, "%s: %d@%d/%d, 0x%08x => 0x%08x\n",
__func__, packets, length, ureq->length, epsize, epsize_reg);
@@ -744,26 +768,38 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
if (using_dma(hsotg) && !continuing) {
unsigned int dma_reg;
- /* write DMA address to control register, buffer already
- * synced by s3c_hsotg_ep_queue(). */
+ /*
+ * write DMA address to control register, buffer already
+ * synced by s3c_hsotg_ep_queue().
+ */
- dma_reg = dir_in ? S3C_DIEPDMA(index) : S3C_DOEPDMA(index);
+ dma_reg = dir_in ? DIEPDMA(index) : DOEPDMA(index);
writel(ureq->dma, hsotg->regs + dma_reg);
dev_dbg(hsotg->dev, "%s: 0x%08x => 0x%08x\n",
__func__, ureq->dma, dma_reg);
}
- ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */
- ctrl |= S3C_DxEPCTL_USBActEp;
- ctrl |= S3C_DxEPCTL_CNAK; /* clear NAK set by core */
+ ctrl |= DxEPCTL_EPEna; /* ensure ep enabled */
+ ctrl |= DxEPCTL_USBActEp;
+
+ dev_dbg(hsotg->dev, "setup req:%d\n", hsotg->setup);
+
+ /* For Setup request do not clear NAK */
+ if (hsotg->setup && index == 0)
+ hsotg->setup = 0;
+ else
+ ctrl |= DxEPCTL_CNAK; /* clear NAK set by core */
+
dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
writel(ctrl, hsotg->regs + epctrl_reg);
- /* set these, it seems that DMA support increments past the end
+ /*
+ * set these, it seems that DMA support increments past the end
* of the packet buffer so we need to calculate the length from
- * this information. */
+ * this information.
+ */
hs_ep->size_loaded = length;
hs_ep->last_load = ureq->actual;
@@ -774,17 +810,21 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req);
}
- /* clear the INTknTXFEmpMsk when we start request, more as a aide
- * to debugging to see what is going on. */
+ /*
+ * clear the INTknTXFEmpMsk when we start request, more as a aide
+ * to debugging to see what is going on.
+ */
if (dir_in)
- writel(S3C_DIEPMSK_INTknTXFEmpMsk,
- hsotg->regs + S3C_DIEPINT(index));
+ writel(DIEPMSK_INTknTXFEmpMsk,
+ hsotg->regs + DIEPINT(index));
- /* Note, trying to clear the NAK here causes problems with transmit
- * on the S3C6400 ending up with the TXFIFO becoming full. */
+ /*
+ * Note, trying to clear the NAK here causes problems with transmit
+ * on the S3C6400 ending up with the TXFIFO becoming full.
+ */
/* check ep is enabled */
- if (!(readl(hsotg->regs + epctrl_reg) & S3C_DxEPCTL_EPEna))
+ if (!(readl(hsotg->regs + epctrl_reg) & DxEPCTL_EPEna))
dev_warn(hsotg->dev,
"ep%d: failed to become enabled (DxEPCTL=0x%08x)?\n",
index, readl(hsotg->regs + epctrl_reg));
@@ -804,7 +844,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
* then ensure the buffer has been synced to memory. If our buffer has no
* DMA memory, then we map the memory and mark our request to allow us to
* cleanup on completion.
-*/
+ */
static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
struct usb_request *req)
@@ -922,7 +962,7 @@ static void s3c_hsotg_complete_oursetup(struct usb_ep *ep,
*
* Convert the given wIndex into a pointer to an driver endpoint
* structure, or return NULL if it is not a valid endpoint.
-*/
+ */
static struct s3c_hsotg_ep *ep_from_windex(struct s3c_hsotg *hsotg,
u32 windex)
{
@@ -933,7 +973,7 @@ static struct s3c_hsotg_ep *ep_from_windex(struct s3c_hsotg *hsotg,
if (windex >= 0x100)
return NULL;
- if (idx > S3C_HSOTG_EPS)
+ if (idx > hsotg->num_of_eps)
return NULL;
if (idx && ep->dir_in != dir)
@@ -1151,24 +1191,28 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
ctrl->bRequest, ctrl->bRequestType,
ctrl->wValue, ctrl->wLength);
- /* record the direction of the request, for later use when enquing
- * packets onto EP0. */
+ /*
+ * record the direction of the request, for later use when enquing
+ * packets onto EP0.
+ */
ep0->dir_in = (ctrl->bRequestType & USB_DIR_IN) ? 1 : 0;
dev_dbg(hsotg->dev, "ctrl: dir_in=%d\n", ep0->dir_in);
- /* if we've no data with this request, then the last part of the
- * transaction is going to implicitly be IN. */
+ /*
+ * if we've no data with this request, then the last part of the
+ * transaction is going to implicitly be IN.
+ */
if (ctrl->wLength == 0)
ep0->dir_in = 1;
if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
switch (ctrl->bRequest) {
case USB_REQ_SET_ADDRESS:
- dcfg = readl(hsotg->regs + S3C_DCFG);
- dcfg &= ~S3C_DCFG_DevAddr_MASK;
- dcfg |= ctrl->wValue << S3C_DCFG_DevAddr_SHIFT;
- writel(dcfg, hsotg->regs + S3C_DCFG);
+ dcfg = readl(hsotg->regs + DCFG);
+ dcfg &= ~DCFG_DevAddr_MASK;
+ dcfg |= ctrl->wValue << DCFG_DevAddr_SHIFT;
+ writel(dcfg, hsotg->regs + DCFG);
dev_info(hsotg->dev, "new address %d\n", ctrl->wValue);
@@ -1194,7 +1238,8 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret);
}
- /* the request is either unhandlable, or is not formatted correctly
+ /*
+ * the request is either unhandlable, or is not formatted correctly
* so respond with a STALL for the status stage to indicate failure.
*/
@@ -1203,22 +1248,26 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
u32 ctrl;
dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in);
- reg = (ep0->dir_in) ? S3C_DIEPCTL0 : S3C_DOEPCTL0;
+ reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0;
- /* S3C_DxEPCTL_Stall will be cleared by EP once it has
- * taken effect, so no need to clear later. */
+ /*
+ * DxEPCTL_Stall will be cleared by EP once it has
+ * taken effect, so no need to clear later.
+ */
ctrl = readl(hsotg->regs + reg);
- ctrl |= S3C_DxEPCTL_Stall;
- ctrl |= S3C_DxEPCTL_CNAK;
+ ctrl |= DxEPCTL_Stall;
+ ctrl |= DxEPCTL_CNAK;
writel(ctrl, hsotg->regs + reg);
dev_dbg(hsotg->dev,
"written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n",
ctrl, reg, readl(hsotg->regs + reg));
- /* don't believe we need to anything more to get the EP
- * to reply with a STALL packet */
+ /*
+ * don't believe we need to anything more to get the EP
+ * to reply with a STALL packet
+ */
}
}
@@ -1279,8 +1328,10 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg)
ret = s3c_hsotg_ep_queue(&hsotg->eps[0].ep, req, GFP_ATOMIC);
if (ret < 0) {
dev_err(hsotg->dev, "%s: failed queue (%d)\n", __func__, ret);
- /* Don't think there's much we can do other than watch the
- * driver fail. */
+ /*
+ * Don't think there's much we can do other than watch the
+ * driver fail.
+ */
}
}
@@ -1296,7 +1347,7 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg)
* on the endpoint.
*
* Note, expects the ep to already be locked as appropriate.
-*/
+ */
static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
struct s3c_hsotg_req *hs_req,
@@ -1312,8 +1363,10 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
dev_dbg(hsotg->dev, "complete: ep %p %s, req %p, %d => %p\n",
hs_ep, hs_ep->ep.name, hs_req, result, hs_req->req.complete);
- /* only replace the status if we've not already set an error
- * from a previous transaction */
+ /*
+ * only replace the status if we've not already set an error
+ * from a previous transaction
+ */
if (hs_req->req.status == -EINPROGRESS)
hs_req->req.status = result;
@@ -1324,8 +1377,10 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
if (using_dma(hsotg))
s3c_hsotg_unmap_dma(hsotg, hs_ep, hs_req);
- /* call the complete request with the locks off, just in case the
- * request tries to queue more work for this endpoint. */
+ /*
+ * call the complete request with the locks off, just in case the
+ * request tries to queue more work for this endpoint.
+ */
if (hs_req->req.complete) {
spin_unlock(&hs_ep->lock);
@@ -1333,9 +1388,11 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
spin_lock(&hs_ep->lock);
}
- /* Look to see if there is anything else to do. Note, the completion
+ /*
+ * Look to see if there is anything else to do. Note, the completion
* of the previous request may have caused a new request to be started
- * so be careful when doing this. */
+ * so be careful when doing this.
+ */
if (!hs_ep->req && result >= 0) {
restart = !list_empty(&hs_ep->queue);
@@ -1355,7 +1412,7 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
*
* See s3c_hsotg_complete_request(), but called with the endpoint's
* lock held.
-*/
+ */
static void s3c_hsotg_complete_request_lock(struct s3c_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
struct s3c_hsotg_req *hs_req,
@@ -1382,13 +1439,13 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
{
struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep_idx];
struct s3c_hsotg_req *hs_req = hs_ep->req;
- void __iomem *fifo = hsotg->regs + S3C_EPFIFO(ep_idx);
+ void __iomem *fifo = hsotg->regs + EPFIFO(ep_idx);
int to_read;
int max_req;
int read_ptr;
if (!hs_req) {
- u32 epctl = readl(hsotg->regs + S3C_DOEPCTL(ep_idx));
+ u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx));
int ptr;
dev_warn(hsotg->dev,
@@ -1412,7 +1469,8 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
__func__, to_read, max_req, read_ptr, hs_req->req.length);
if (to_read > max_req) {
- /* more data appeared than we where willing
+ /*
+ * more data appeared than we where willing
* to deal with in this request.
*/
@@ -1424,8 +1482,10 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
hs_req->req.actual += to_read;
to_read = DIV_ROUND_UP(to_read, 4);
- /* note, we might over-write the buffer end by 3 bytes depending on
- * alignment of the data. */
+ /*
+ * note, we might over-write the buffer end by 3 bytes depending on
+ * alignment of the data.
+ */
readsl(fifo, hs_req->req.buf + read_ptr, to_read);
spin_unlock(&hs_ep->lock);
@@ -1465,14 +1525,14 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg,
dev_dbg(hsotg->dev, "sending zero-length packet\n");
/* issue a zero-sized packet to terminate this */
- writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) |
- S3C_DxEPTSIZ_XferSize(0), hsotg->regs + S3C_DIEPTSIZ(0));
+ writel(DxEPTSIZ_MC(1) | DxEPTSIZ_PktCnt(1) |
+ DxEPTSIZ_XferSize(0), hsotg->regs + DIEPTSIZ(0));
- ctrl = readl(hsotg->regs + S3C_DIEPCTL0);
- ctrl |= S3C_DxEPCTL_CNAK; /* clear NAK set by core */
- ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */
- ctrl |= S3C_DxEPCTL_USBActEp;
- writel(ctrl, hsotg->regs + S3C_DIEPCTL0);
+ ctrl = readl(hsotg->regs + DIEPCTL0);
+ ctrl |= DxEPCTL_CNAK; /* clear NAK set by core */
+ ctrl |= DxEPCTL_EPEna; /* ensure ep enabled */
+ ctrl |= DxEPCTL_USBActEp;
+ writel(ctrl, hsotg->regs + DIEPCTL0);
}
/**
@@ -1484,15 +1544,15 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg,
* The RXFIFO has delivered an OutDone event, which means that the data
* transfer for an OUT endpoint has been completed, either by a short
* packet or by the finish of a transfer.
-*/
+ */
static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
int epnum, bool was_setup)
{
- u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum));
+ u32 epsize = readl(hsotg->regs + DOEPTSIZ(epnum));
struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum];
struct s3c_hsotg_req *hs_req = hs_ep->req;
struct usb_request *req = &hs_req->req;
- unsigned size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
+ unsigned size_left = DxEPTSIZ_XferSize_GET(epsize);
int result = 0;
if (!hs_req) {
@@ -1503,7 +1563,8 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
if (using_dma(hsotg)) {
unsigned size_done;
- /* Calculate the size of the transfer by checking how much
+ /*
+ * Calculate the size of the transfer by checking how much
* is left in the endpoint size register and then working it
* out from the amount we loaded for the transfer.
*
@@ -1521,17 +1582,29 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
if (req->actual < req->length && size_left == 0) {
s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true);
return;
+ } else if (epnum == 0) {
+ /*
+ * After was_setup = 1 =>
+ * set CNAK for non Setup requests
+ */
+ hsotg->setup = was_setup ? 0 : 1;
}
if (req->actual < req->length && req->short_not_ok) {
dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n",
__func__, req->actual, req->length);
- /* todo - what should we return here? there's no one else
- * even bothering to check the status. */
+ /*
+ * todo - what should we return here? there's no one else
+ * even bothering to check the status.
+ */
}
if (epnum == 0) {
+ /*
+ * Condition req->complete != s3c_hsotg_complete_setup says:
+ * send ZLP when we have an asynchronous request from gadget
+ */
if (!was_setup && req->complete != s3c_hsotg_complete_setup)
s3c_hsotg_send_zlp(hsotg, hs_req);
}
@@ -1544,14 +1617,14 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
* @hsotg: The device instance
*
* Return the current frame number
-*/
+ */
static u32 s3c_hsotg_read_frameno(struct s3c_hsotg *hsotg)
{
u32 dsts;
- dsts = readl(hsotg->regs + S3C_DSTS);
- dsts &= S3C_DSTS_SOFFN_MASK;
- dsts >>= S3C_DSTS_SOFFN_SHIFT;
+ dsts = readl(hsotg->regs + DSTS);
+ dsts &= DSTS_SOFFN_MASK;
+ dsts >>= DSTS_SOFFN_SHIFT;
return dsts;
}
@@ -1574,29 +1647,29 @@ static u32 s3c_hsotg_read_frameno(struct s3c_hsotg *hsotg)
*/
static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg)
{
- u32 grxstsr = readl(hsotg->regs + S3C_GRXSTSP);
+ u32 grxstsr = readl(hsotg->regs + GRXSTSP);
u32 epnum, status, size;
WARN_ON(using_dma(hsotg));
- epnum = grxstsr & S3C_GRXSTS_EPNum_MASK;
- status = grxstsr & S3C_GRXSTS_PktSts_MASK;
+ epnum = grxstsr & GRXSTS_EPNum_MASK;
+ status = grxstsr & GRXSTS_PktSts_MASK;
- size = grxstsr & S3C_GRXSTS_ByteCnt_MASK;
- size >>= S3C_GRXSTS_ByteCnt_SHIFT;
+ size = grxstsr & GRXSTS_ByteCnt_MASK;
+ size >>= GRXSTS_ByteCnt_SHIFT;
if (1)
dev_dbg(hsotg->dev, "%s: GRXSTSP=0x%08x (%d@%d)\n",
__func__, grxstsr, size, epnum);
-#define __status(x) ((x) >> S3C_GRXSTS_PktSts_SHIFT)
+#define __status(x) ((x) >> GRXSTS_PktSts_SHIFT)
- switch (status >> S3C_GRXSTS_PktSts_SHIFT) {
- case __status(S3C_GRXSTS_PktSts_GlobalOutNAK):
+ switch (status >> GRXSTS_PktSts_SHIFT) {
+ case __status(GRXSTS_PktSts_GlobalOutNAK):
dev_dbg(hsotg->dev, "GlobalOutNAK\n");
break;
- case __status(S3C_GRXSTS_PktSts_OutDone):
+ case __status(GRXSTS_PktSts_OutDone):
dev_dbg(hsotg->dev, "OutDone (Frame=0x%08x)\n",
s3c_hsotg_read_frameno(hsotg));
@@ -1604,24 +1677,24 @@ static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg)
s3c_hsotg_handle_outdone(hsotg, epnum, false);
break;
- case __status(S3C_GRXSTS_PktSts_SetupDone):
+ case __status(GRXSTS_PktSts_SetupDone):
dev_dbg(hsotg->dev,
"SetupDone (Frame=0x%08x, DOPEPCTL=0x%08x)\n",
s3c_hsotg_read_frameno(hsotg),
- readl(hsotg->regs + S3C_DOEPCTL(0)));
+ readl(hsotg->regs + DOEPCTL(0)));
s3c_hsotg_handle_outdone(hsotg, epnum, true);
break;
- case __status(S3C_GRXSTS_PktSts_OutRX):
+ case __status(GRXSTS_PktSts_OutRX):
s3c_hsotg_rx_data(hsotg, epnum, size);
break;
- case __status(S3C_GRXSTS_PktSts_SetupRX):
+ case __status(GRXSTS_PktSts_SetupRX):
dev_dbg(hsotg->dev,
"SetupRX (Frame=0x%08x, DOPEPCTL=0x%08x)\n",
s3c_hsotg_read_frameno(hsotg),
- readl(hsotg->regs + S3C_DOEPCTL(0)));
+ readl(hsotg->regs + DOEPCTL(0)));
s3c_hsotg_rx_data(hsotg, epnum, size);
break;
@@ -1638,18 +1711,18 @@ static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg)
/**
* s3c_hsotg_ep0_mps - turn max packet size into register setting
* @mps: The maximum packet size in bytes.
-*/
+ */
static u32 s3c_hsotg_ep0_mps(unsigned int mps)
{
switch (mps) {
case 64:
- return S3C_D0EPCTL_MPS_64;
+ return D0EPCTL_MPS_64;
case 32:
- return S3C_D0EPCTL_MPS_32;
+ return D0EPCTL_MPS_32;
case 16:
- return S3C_D0EPCTL_MPS_16;
+ return D0EPCTL_MPS_16;
case 8:
- return S3C_D0EPCTL_MPS_8;
+ return D0EPCTL_MPS_8;
}
/* bad max packet size, warn and return invalid result */
@@ -1680,7 +1753,7 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg,
if (mpsval > 3)
goto bad_mps;
} else {
- if (mps >= S3C_DxEPCTL_MPS_LIMIT+1)
+ if (mps >= DxEPCTL_MPS_LIMIT+1)
goto bad_mps;
mpsval = mps;
@@ -1688,19 +1761,21 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg,
hs_ep->ep.maxpacket = mps;
- /* update both the in and out endpoint controldir_ registers, even
- * if one of the directions may not be in use. */
+ /*
+ * update both the in and out endpoint controldir_ registers, even
+ * if one of the directions may not be in use.
+ */
- reg = readl(regs + S3C_DIEPCTL(ep));
- reg &= ~S3C_DxEPCTL_MPS_MASK;
+ reg = readl(regs + DIEPCTL(ep));
+ reg &= ~DxEPCTL_MPS_MASK;
reg |= mpsval;
- writel(reg, regs + S3C_DIEPCTL(ep));
+ writel(reg, regs + DIEPCTL(ep));
if (ep) {
- reg = readl(regs + S3C_DOEPCTL(ep));
- reg &= ~S3C_DxEPCTL_MPS_MASK;
+ reg = readl(regs + DOEPCTL(ep));
+ reg &= ~DxEPCTL_MPS_MASK;
reg |= mpsval;
- writel(reg, regs + S3C_DOEPCTL(ep));
+ writel(reg, regs + DOEPCTL(ep));
}
return;
@@ -1719,16 +1794,16 @@ static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx)
int timeout;
int val;
- writel(S3C_GRSTCTL_TxFNum(idx) | S3C_GRSTCTL_TxFFlsh,
- hsotg->regs + S3C_GRSTCTL);
+ writel(GRSTCTL_TxFNum(idx) | GRSTCTL_TxFFlsh,
+ hsotg->regs + GRSTCTL);
/* wait until the fifo is flushed */
timeout = 100;
while (1) {
- val = readl(hsotg->regs + S3C_GRSTCTL);
+ val = readl(hsotg->regs + GRSTCTL);
- if ((val & (S3C_GRSTCTL_TxFFlsh)) == 0)
+ if ((val & (GRSTCTL_TxFFlsh)) == 0)
break;
if (--timeout == 0) {
@@ -1778,7 +1853,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep)
{
struct s3c_hsotg_req *hs_req = hs_ep->req;
- u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index));
+ u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
int size_left, size_done;
if (!hs_req) {
@@ -1786,7 +1861,15 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
return;
}
- /* Calculate the size of the transfer by checking how much is left
+ /* Finish ZLP handling for IN EP0 transactions */
+ if (hsotg->eps[0].sent_zlp) {
+ dev_dbg(hsotg->dev, "zlp packet received\n");
+ s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0);
+ return;
+ }
+
+ /*
+ * Calculate the size of the transfer by checking how much is left
* in the endpoint size register and then working it out from
* the amount we loaded for the transfer.
*
@@ -1795,7 +1878,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
* aligned).
*/
- size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
+ size_left = DxEPTSIZ_XferSize_GET(epsize);
size_done = hs_ep->size_loaded - size_left;
size_done += hs_ep->last_load;
@@ -1805,9 +1888,28 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
__func__, hs_req->req.actual, size_done);
hs_req->req.actual = size_done;
+ dev_dbg(hsotg->dev, "req->length:%d req->actual:%d req->zero:%d\n",
+ hs_req->req.length, hs_req->req.actual, hs_req->req.zero);
+
+ /*
+ * Check if dealing with Maximum Packet Size(MPS) IN transfer at EP0
+ * When sent data is a multiple MPS size (e.g. 64B ,128B ,192B
+ * ,256B ... ), after last MPS sized packet send IN ZLP packet to
+ * inform the host that no more data is available.
+ * The state of req.zero member is checked to be sure that the value to
+ * send is smaller than wValue expected from host.
+ * Check req.length to NOT send another ZLP when the current one is
+ * under completion (the one for which this completion has been called).
+ */
+ if (hs_req->req.length && hs_ep->index == 0 && hs_req->req.zero &&
+ hs_req->req.length == hs_req->req.actual &&
+ !(hs_req->req.length % hs_ep->ep.maxpacket)) {
- /* if we did all of the transfer, and there is more data left
- * around, then try restarting the rest of the request */
+ dev_dbg(hsotg->dev, "ep0 zlp IN packet sent\n");
+ s3c_hsotg_send_zlp(hsotg, hs_req);
+
+ return;
+ }
if (!size_left && hs_req->req.actual < hs_req->req.length) {
dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__);
@@ -1823,14 +1925,14 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
* @dir_in: Set if this is an IN endpoint
*
* Process and clear any interrupt pending for an individual endpoint
-*/
+ */
static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
int dir_in)
{
struct s3c_hsotg_ep *hs_ep = &hsotg->eps[idx];
- u32 epint_reg = dir_in ? S3C_DIEPINT(idx) : S3C_DOEPINT(idx);
- u32 epctl_reg = dir_in ? S3C_DIEPCTL(idx) : S3C_DOEPCTL(idx);
- u32 epsiz_reg = dir_in ? S3C_DIEPTSIZ(idx) : S3C_DOEPTSIZ(idx);
+ u32 epint_reg = dir_in ? DIEPINT(idx) : DOEPINT(idx);
+ u32 epctl_reg = dir_in ? DIEPCTL(idx) : DOEPCTL(idx);
+ u32 epsiz_reg = dir_in ? DIEPTSIZ(idx) : DOEPTSIZ(idx);
u32 ints;
ints = readl(hsotg->regs + epint_reg);
@@ -1841,28 +1943,32 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n",
__func__, idx, dir_in ? "in" : "out", ints);
- if (ints & S3C_DxEPINT_XferCompl) {
+ if (ints & DxEPINT_XferCompl) {
dev_dbg(hsotg->dev,
"%s: XferCompl: DxEPCTL=0x%08x, DxEPTSIZ=%08x\n",
__func__, readl(hsotg->regs + epctl_reg),
readl(hsotg->regs + epsiz_reg));
- /* we get OutDone from the FIFO, so we only need to look
- * at completing IN requests here */
+ /*
+ * we get OutDone from the FIFO, so we only need to look
+ * at completing IN requests here
+ */
if (dir_in) {
s3c_hsotg_complete_in(hsotg, hs_ep);
if (idx == 0 && !hs_ep->req)
s3c_hsotg_enqueue_setup(hsotg);
} else if (using_dma(hsotg)) {
- /* We're using DMA, we need to fire an OutDone here
- * as we ignore the RXFIFO. */
+ /*
+ * We're using DMA, we need to fire an OutDone here
+ * as we ignore the RXFIFO.
+ */
s3c_hsotg_handle_outdone(hsotg, idx, false);
}
}
- if (ints & S3C_DxEPINT_EPDisbld) {
+ if (ints & DxEPINT_EPDisbld) {
dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__);
if (dir_in) {
@@ -1870,27 +1976,29 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
s3c_hsotg_txfifo_flush(hsotg, idx);
- if ((epctl & S3C_DxEPCTL_Stall) &&
- (epctl & S3C_DxEPCTL_EPType_Bulk)) {
- int dctl = readl(hsotg->regs + S3C_DCTL);
+ if ((epctl & DxEPCTL_Stall) &&
+ (epctl & DxEPCTL_EPType_Bulk)) {
+ int dctl = readl(hsotg->regs + DCTL);
- dctl |= S3C_DCTL_CGNPInNAK;
- writel(dctl, hsotg->regs + S3C_DCTL);
+ dctl |= DCTL_CGNPInNAK;
+ writel(dctl, hsotg->regs + DCTL);
}
}
}
- if (ints & S3C_DxEPINT_AHBErr)
+ if (ints & DxEPINT_AHBErr)
dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__);
- if (ints & S3C_DxEPINT_Setup) { /* Setup or Timeout */
+ if (ints & DxEPINT_Setup) { /* Setup or Timeout */
dev_dbg(hsotg->dev, "%s: Setup/Timeout\n", __func__);
if (using_dma(hsotg) && idx == 0) {
- /* this is the notification we've received a
+ /*
+ * this is the notification we've received a
* setup packet. In non-DMA mode we'd get this
* from the RXFIFO, instead we need to process
- * the setup here. */
+ * the setup here.
+ */
if (dir_in)
WARN_ON_ONCE(1);
@@ -1899,26 +2007,25 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
}
}
- if (ints & S3C_DxEPINT_Back2BackSetup)
+ if (ints & DxEPINT_Back2BackSetup)
dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__);
if (dir_in) {
- /* not sure if this is important, but we'll clear it anyway
- */
- if (ints & S3C_DIEPMSK_INTknTXFEmpMsk) {
+ /* not sure if this is important, but we'll clear it anyway */
+ if (ints & DIEPMSK_INTknTXFEmpMsk) {
dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n",
__func__, idx);
}
/* this probably means something bad is happening */
- if (ints & S3C_DIEPMSK_INTknEPMisMsk) {
+ if (ints & DIEPMSK_INTknEPMisMsk) {
dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n",
__func__, idx);
}
/* FIFO has space or is empty (see GAHBCFG) */
if (hsotg->dedicated_fifos &&
- ints & S3C_DIEPMSK_TxFIFOEmpty) {
+ ints & DIEPMSK_TxFIFOEmpty) {
dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n",
__func__, idx);
if (!using_dma(hsotg))
@@ -1933,40 +2040,45 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
*
* Handle updating the device settings after the enumeration phase has
* been completed.
-*/
+ */
static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg)
{
- u32 dsts = readl(hsotg->regs + S3C_DSTS);
+ u32 dsts = readl(hsotg->regs + DSTS);
int ep0_mps = 0, ep_mps;
- /* This should signal the finish of the enumeration phase
+ /*
+ * This should signal the finish of the enumeration phase
* of the USB handshaking, so we should now know what rate
- * we connected at. */
+ * we connected at.
+ */
dev_dbg(hsotg->dev, "EnumDone (DSTS=0x%08x)\n", dsts);
- /* note, since we're limited by the size of transfer on EP0, and
+ /*
+ * note, since we're limited by the size of transfer on EP0, and
* it seems IN transfers must be a even number of packets we do
- * not advertise a 64byte MPS on EP0. */
+ * not advertise a 64byte MPS on EP0.
+ */
/* catch both EnumSpd_FS and EnumSpd_FS48 */
- switch (dsts & S3C_DSTS_EnumSpd_MASK) {
- case S3C_DSTS_EnumSpd_FS:
- case S3C_DSTS_EnumSpd_FS48:
+ switch (dsts & DSTS_EnumSpd_MASK) {
+ case DSTS_EnumSpd_FS:
+ case DSTS_EnumSpd_FS48:
hsotg->gadget.speed = USB_SPEED_FULL;
ep0_mps = EP0_MPS_LIMIT;
ep_mps = 64;
break;
- case S3C_DSTS_EnumSpd_HS:
+ case DSTS_EnumSpd_HS:
hsotg->gadget.speed = USB_SPEED_HIGH;
ep0_mps = EP0_MPS_LIMIT;
ep_mps = 512;
break;
- case S3C_DSTS_EnumSpd_LS:
+ case DSTS_EnumSpd_LS:
hsotg->gadget.speed = USB_SPEED_LOW;
- /* note, we don't actually support LS in this driver at the
+ /*
+ * note, we don't actually support LS in this driver at the
* moment, and the documentation seems to imply that it isn't
* supported by the PHYs on some of the devices.
*/
@@ -1975,13 +2087,15 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg)
dev_info(hsotg->dev, "new device is %s\n",
usb_speed_string(hsotg->gadget.speed));
- /* we should now know the maximum packet size for an
- * endpoint, so set the endpoints to a default value. */
+ /*
+ * we should now know the maximum packet size for an
+ * endpoint, so set the endpoints to a default value.
+ */
if (ep0_mps) {
int i;
s3c_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps);
- for (i = 1; i < S3C_HSOTG_EPS; i++)
+ for (i = 1; i < hsotg->num_of_eps; i++)
s3c_hsotg_set_ep_maxpacket(hsotg, i, ep_mps);
}
@@ -1990,8 +2104,8 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg)
s3c_hsotg_enqueue_setup(hsotg);
dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
- readl(hsotg->regs + S3C_DIEPCTL0),
- readl(hsotg->regs + S3C_DOEPCTL0));
+ readl(hsotg->regs + DIEPCTL0),
+ readl(hsotg->regs + DOEPCTL0));
}
/**
@@ -2014,8 +2128,10 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
spin_lock_irqsave(&ep->lock, flags);
list_for_each_entry_safe(req, treq, &ep->queue, queue) {
- /* currently, we can't do much about an already
- * running request on an in endpoint */
+ /*
+ * currently, we can't do much about an already
+ * running request on an in endpoint
+ */
if (ep->req == req && ep->dir_in && !force)
continue;
@@ -2033,18 +2149,18 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
(_hs)->driver->_entry(&(_hs)->gadget);
/**
- * s3c_hsotg_disconnect_irq - disconnect irq service
+ * s3c_hsotg_disconnect - disconnect service
* @hsotg: The device state.
*
- * A disconnect IRQ has been received, meaning that the host has
- * lost contact with the bus. Remove all current transactions
- * and signal the gadget driver that this has happened.
-*/
-static void s3c_hsotg_disconnect_irq(struct s3c_hsotg *hsotg)
+ * The device has been disconnected. Remove all current
+ * transactions and signal the gadget driver that this
+ * has happened.
+ */
+static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg)
{
unsigned ep;
- for (ep = 0; ep < S3C_HSOTG_EPS; ep++)
+ for (ep = 0; ep < hsotg->num_of_eps; ep++)
kill_all_requests(hsotg, &hsotg->eps[ep], -ESHUTDOWN, true);
call_gadget(hsotg, disconnect);
@@ -2062,7 +2178,7 @@ static void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic)
/* look through for any more data to transmit */
- for (epno = 0; epno < S3C_HSOTG_EPS; epno++) {
+ for (epno = 0; epno < hsotg->num_of_eps; epno++) {
ep = &hsotg->eps[epno];
if (!ep->dir_in)
@@ -2078,12 +2194,187 @@ static void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic)
}
}
-static struct s3c_hsotg *our_hsotg;
-
/* IRQ flags which will trigger a retry around the IRQ loop */
-#define IRQ_RETRY_MASK (S3C_GINTSTS_NPTxFEmp | \
- S3C_GINTSTS_PTxFEmp | \
- S3C_GINTSTS_RxFLvl)
+#define IRQ_RETRY_MASK (GINTSTS_NPTxFEmp | \
+ GINTSTS_PTxFEmp | \
+ GINTSTS_RxFLvl)
+
+/**
+ * s3c_hsotg_corereset - issue softreset to the core
+ * @hsotg: The device state
+ *
+ * Issue a soft reset to the core, and await the core finishing it.
+ */
+static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
+{
+ int timeout;
+ u32 grstctl;
+
+ dev_dbg(hsotg->dev, "resetting core\n");
+
+ /* issue soft reset */
+ writel(GRSTCTL_CSftRst, hsotg->regs + GRSTCTL);
+
+ timeout = 1000;
+ do {
+ grstctl = readl(hsotg->regs + GRSTCTL);
+ } while ((grstctl & GRSTCTL_CSftRst) && timeout-- > 0);
+
+ if (grstctl & GRSTCTL_CSftRst) {
+ dev_err(hsotg->dev, "Failed to get CSftRst asserted\n");
+ return -EINVAL;
+ }
+
+ timeout = 1000;
+
+ while (1) {
+ u32 grstctl = readl(hsotg->regs + GRSTCTL);
+
+ if (timeout-- < 0) {
+ dev_info(hsotg->dev,
+ "%s: reset failed, GRSTCTL=%08x\n",
+ __func__, grstctl);
+ return -ETIMEDOUT;
+ }
+
+ if (!(grstctl & GRSTCTL_AHBIdle))
+ continue;
+
+ break; /* reset done */
+ }
+
+ dev_dbg(hsotg->dev, "reset successful\n");
+ return 0;
+}
+
+/**
+ * s3c_hsotg_core_init - issue softreset to the core
+ * @hsotg: The device state
+ *
+ * Issue a soft reset to the core, and await the core finishing it.
+ */
+static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg)
+{
+ s3c_hsotg_corereset(hsotg);
+
+ /*
+ * we must now enable ep0 ready for host detection and then
+ * set configuration.
+ */
+
+ /* set the PLL on, remove the HNP/SRP and set the PHY */
+ writel(GUSBCFG_PHYIf16 | GUSBCFG_TOutCal(7) |
+ (0x5 << 10), hsotg->regs + GUSBCFG);
+
+ s3c_hsotg_init_fifo(hsotg);
+
+ __orr32(hsotg->regs + DCTL, DCTL_SftDiscon);
+
+ writel(1 << 18 | DCFG_DevSpd_HS, hsotg->regs + DCFG);
+
+ /* Clear any pending OTG interrupts */
+ writel(0xffffffff, hsotg->regs + GOTGINT);
+
+ /* Clear any pending interrupts */
+ writel(0xffffffff, hsotg->regs + GINTSTS);
+
+ writel(GINTSTS_ErlySusp | GINTSTS_SessReqInt |
+ GINTSTS_GOUTNakEff | GINTSTS_GINNakEff |
+ GINTSTS_ConIDStsChng | GINTSTS_USBRst |
+ GINTSTS_EnumDone | GINTSTS_OTGInt |
+ GINTSTS_USBSusp | GINTSTS_WkUpInt,
+ hsotg->regs + GINTMSK);
+
+ if (using_dma(hsotg))
+ writel(GAHBCFG_GlblIntrEn | GAHBCFG_DMAEn |
+ GAHBCFG_HBstLen_Incr4,
+ hsotg->regs + GAHBCFG);
+ else
+ writel(GAHBCFG_GlblIntrEn, hsotg->regs + GAHBCFG);
+
+ /*
+ * Enabling INTknTXFEmpMsk here seems to be a big mistake, we end
+ * up being flooded with interrupts if the host is polling the
+ * endpoint to try and read data.
+ */
+
+ writel(((hsotg->dedicated_fifos) ? DIEPMSK_TxFIFOEmpty : 0) |
+ DIEPMSK_EPDisbldMsk | DIEPMSK_XferComplMsk |
+ DIEPMSK_TimeOUTMsk | DIEPMSK_AHBErrMsk |
+ DIEPMSK_INTknEPMisMsk,
+ hsotg->regs + DIEPMSK);
+
+ /*
+ * don't need XferCompl, we get that from RXFIFO in slave mode. In
+ * DMA mode we may need this.
+ */
+ writel((using_dma(hsotg) ? (DIEPMSK_XferComplMsk |
+ DIEPMSK_TimeOUTMsk) : 0) |
+ DOEPMSK_EPDisbldMsk | DOEPMSK_AHBErrMsk |
+ DOEPMSK_SetupMsk,
+ hsotg->regs + DOEPMSK);
+
+ writel(0, hsotg->regs + DAINTMSK);
+
+ dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
+ readl(hsotg->regs + DIEPCTL0),
+ readl(hsotg->regs + DOEPCTL0));
+
+ /* enable in and out endpoint interrupts */
+ s3c_hsotg_en_gsint(hsotg, GINTSTS_OEPInt | GINTSTS_IEPInt);
+
+ /*
+ * Enable the RXFIFO when in slave mode, as this is how we collect
+ * the data. In DMA mode, we get events from the FIFO but also
+ * things we cannot process, so do not use it.
+ */
+ if (!using_dma(hsotg))
+ s3c_hsotg_en_gsint(hsotg, GINTSTS_RxFLvl);
+
+ /* Enable interrupts for EP0 in and out */
+ s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1);
+ s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1);
+
+ __orr32(hsotg->regs + DCTL, DCTL_PWROnPrgDone);
+ udelay(10); /* see openiboot */
+ __bic32(hsotg->regs + DCTL, DCTL_PWROnPrgDone);
+
+ dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + DCTL));
+
+ /*
+ * DxEPCTL_USBActEp says RO in manual, but seems to be set by
+ * writing to the EPCTL register..
+ */
+
+ /* set to read 1 8byte packet */
+ writel(DxEPTSIZ_MC(1) | DxEPTSIZ_PktCnt(1) |
+ DxEPTSIZ_XferSize(8), hsotg->regs + DOEPTSIZ0);
+
+ writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
+ DxEPCTL_CNAK | DxEPCTL_EPEna |
+ DxEPCTL_USBActEp,
+ hsotg->regs + DOEPCTL0);
+
+ /* enable, but don't activate EP0in */
+ writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
+ DxEPCTL_USBActEp, hsotg->regs + DIEPCTL0);
+
+ s3c_hsotg_enqueue_setup(hsotg);
+
+ dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
+ readl(hsotg->regs + DIEPCTL0),
+ readl(hsotg->regs + DOEPCTL0));
+
+ /* clear global NAKs */
+ writel(DCTL_CGOUTNak | DCTL_CGNPInNAK,
+ hsotg->regs + DCTL);
+
+ /* must be at-least 3ms to allow bus to see disconnect */
+ mdelay(3);
+
+ /* remove the soft-disconnect and let's go */
+ __bic32(hsotg->regs + DCTL, DCTL_SftDiscon);
+}
/**
* s3c_hsotg_irq - handle device interrupt
@@ -2098,52 +2389,45 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
u32 gintmsk;
irq_retry:
- gintsts = readl(hsotg->regs + S3C_GINTSTS);
- gintmsk = readl(hsotg->regs + S3C_GINTMSK);
+ gintsts = readl(hsotg->regs + GINTSTS);
+ gintmsk = readl(hsotg->regs + GINTMSK);
dev_dbg(hsotg->dev, "%s: %08x %08x (%08x) retry %d\n",
__func__, gintsts, gintsts & gintmsk, gintmsk, retry_count);
gintsts &= gintmsk;
- if (gintsts & S3C_GINTSTS_OTGInt) {
- u32 otgint = readl(hsotg->regs + S3C_GOTGINT);
+ if (gintsts & GINTSTS_OTGInt) {
+ u32 otgint = readl(hsotg->regs + GOTGINT);
dev_info(hsotg->dev, "OTGInt: %08x\n", otgint);
- writel(otgint, hsotg->regs + S3C_GOTGINT);
- }
-
- if (gintsts & S3C_GINTSTS_DisconnInt) {
- dev_dbg(hsotg->dev, "%s: DisconnInt\n", __func__);
- writel(S3C_GINTSTS_DisconnInt, hsotg->regs + S3C_GINTSTS);
-
- s3c_hsotg_disconnect_irq(hsotg);
+ writel(otgint, hsotg->regs + GOTGINT);
}
- if (gintsts & S3C_GINTSTS_SessReqInt) {
+ if (gintsts & GINTSTS_SessReqInt) {
dev_dbg(hsotg->dev, "%s: SessReqInt\n", __func__);
- writel(S3C_GINTSTS_SessReqInt, hsotg->regs + S3C_GINTSTS);
+ writel(GINTSTS_SessReqInt, hsotg->regs + GINTSTS);
}
- if (gintsts & S3C_GINTSTS_EnumDone) {
- writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS);
+ if (gintsts & GINTSTS_EnumDone) {
+ writel(GINTSTS_EnumDone, hsotg->regs + GINTSTS);
s3c_hsotg_irq_enumdone(hsotg);
}
- if (gintsts & S3C_GINTSTS_ConIDStsChng) {
+ if (gintsts & GINTSTS_ConIDStsChng) {
dev_dbg(hsotg->dev, "ConIDStsChg (DSTS=0x%08x, GOTCTL=%08x)\n",
- readl(hsotg->regs + S3C_DSTS),
- readl(hsotg->regs + S3C_GOTGCTL));
+ readl(hsotg->regs + DSTS),
+ readl(hsotg->regs + GOTGCTL));
- writel(S3C_GINTSTS_ConIDStsChng, hsotg->regs + S3C_GINTSTS);
+ writel(GINTSTS_ConIDStsChng, hsotg->regs + GINTSTS);
}
- if (gintsts & (S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt)) {
- u32 daint = readl(hsotg->regs + S3C_DAINT);
- u32 daint_out = daint >> S3C_DAINT_OutEP_SHIFT;
- u32 daint_in = daint & ~(daint_out << S3C_DAINT_OutEP_SHIFT);
+ if (gintsts & (GINTSTS_OEPInt | GINTSTS_IEPInt)) {
+ u32 daint = readl(hsotg->regs + DAINT);
+ u32 daint_out = daint >> DAINT_OutEP_SHIFT;
+ u32 daint_in = daint & ~(daint_out << DAINT_OutEP_SHIFT);
int ep;
dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint);
@@ -2159,102 +2443,116 @@ irq_retry:
}
}
- if (gintsts & S3C_GINTSTS_USBRst) {
+ if (gintsts & GINTSTS_USBRst) {
+
+ u32 usb_status = readl(hsotg->regs + GOTGCTL);
+
dev_info(hsotg->dev, "%s: USBRst\n", __func__);
dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
- readl(hsotg->regs + S3C_GNPTXSTS));
+ readl(hsotg->regs + GNPTXSTS));
- writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS);
+ writel(GINTSTS_USBRst, hsotg->regs + GINTSTS);
- kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true);
+ if (usb_status & GOTGCTL_BSESVLD) {
+ if (time_after(jiffies, hsotg->last_rst +
+ msecs_to_jiffies(200))) {
- /* it seems after a reset we can end up with a situation
- * where the TXFIFO still has data in it... the docs
- * suggest resetting all the fifos, so use the init_fifo
- * code to relayout and flush the fifos.
- */
+ kill_all_requests(hsotg, &hsotg->eps[0],
+ -ECONNRESET, true);
- s3c_hsotg_init_fifo(hsotg);
-
- s3c_hsotg_enqueue_setup(hsotg);
+ s3c_hsotg_core_init(hsotg);
+ hsotg->last_rst = jiffies;
+ }
+ }
}
/* check both FIFOs */
- if (gintsts & S3C_GINTSTS_NPTxFEmp) {
+ if (gintsts & GINTSTS_NPTxFEmp) {
dev_dbg(hsotg->dev, "NPTxFEmp\n");
- /* Disable the interrupt to stop it happening again
+ /*
+ * Disable the interrupt to stop it happening again
* unless one of these endpoint routines decides that
- * it needs re-enabling */
+ * it needs re-enabling
+ */
- s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_NPTxFEmp);
+ s3c_hsotg_disable_gsint(hsotg, GINTSTS_NPTxFEmp);
s3c_hsotg_irq_fifoempty(hsotg, false);
}
- if (gintsts & S3C_GINTSTS_PTxFEmp) {
+ if (gintsts & GINTSTS_PTxFEmp) {
dev_dbg(hsotg->dev, "PTxFEmp\n");
- /* See note in S3C_GINTSTS_NPTxFEmp */
+ /* See note in GINTSTS_NPTxFEmp */
- s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
+ s3c_hsotg_disable_gsint(hsotg, GINTSTS_PTxFEmp);
s3c_hsotg_irq_fifoempty(hsotg, true);
}
- if (gintsts & S3C_GINTSTS_RxFLvl) {
- /* note, since GINTSTS_RxFLvl doubles as FIFO-not-empty,
+ if (gintsts & GINTSTS_RxFLvl) {
+ /*
+ * note, since GINTSTS_RxFLvl doubles as FIFO-not-empty,
* we need to retry s3c_hsotg_handle_rx if this is still
- * set. */
+ * set.
+ */
s3c_hsotg_handle_rx(hsotg);
}
- if (gintsts & S3C_GINTSTS_ModeMis) {
+ if (gintsts & GINTSTS_ModeMis) {
dev_warn(hsotg->dev, "warning, mode mismatch triggered\n");
- writel(S3C_GINTSTS_ModeMis, hsotg->regs + S3C_GINTSTS);
+ writel(GINTSTS_ModeMis, hsotg->regs + GINTSTS);
}
- if (gintsts & S3C_GINTSTS_USBSusp) {
- dev_info(hsotg->dev, "S3C_GINTSTS_USBSusp\n");
- writel(S3C_GINTSTS_USBSusp, hsotg->regs + S3C_GINTSTS);
+ if (gintsts & GINTSTS_USBSusp) {
+ dev_info(hsotg->dev, "GINTSTS_USBSusp\n");
+ writel(GINTSTS_USBSusp, hsotg->regs + GINTSTS);
call_gadget(hsotg, suspend);
+ s3c_hsotg_disconnect(hsotg);
}
- if (gintsts & S3C_GINTSTS_WkUpInt) {
- dev_info(hsotg->dev, "S3C_GINTSTS_WkUpIn\n");
- writel(S3C_GINTSTS_WkUpInt, hsotg->regs + S3C_GINTSTS);
+ if (gintsts & GINTSTS_WkUpInt) {
+ dev_info(hsotg->dev, "GINTSTS_WkUpIn\n");
+ writel(GINTSTS_WkUpInt, hsotg->regs + GINTSTS);
call_gadget(hsotg, resume);
}
- if (gintsts & S3C_GINTSTS_ErlySusp) {
- dev_dbg(hsotg->dev, "S3C_GINTSTS_ErlySusp\n");
- writel(S3C_GINTSTS_ErlySusp, hsotg->regs + S3C_GINTSTS);
+ if (gintsts & GINTSTS_ErlySusp) {
+ dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n");
+ writel(GINTSTS_ErlySusp, hsotg->regs + GINTSTS);
+
+ s3c_hsotg_disconnect(hsotg);
}
- /* these next two seem to crop-up occasionally causing the core
+ /*
+ * these next two seem to crop-up occasionally causing the core
* to shutdown the USB transfer, so try clearing them and logging
- * the occurrence. */
+ * the occurrence.
+ */
- if (gintsts & S3C_GINTSTS_GOUTNakEff) {
+ if (gintsts & GINTSTS_GOUTNakEff) {
dev_info(hsotg->dev, "GOUTNakEff triggered\n");
- writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL);
+ writel(DCTL_CGOUTNak, hsotg->regs + DCTL);
s3c_hsotg_dump(hsotg);
}
- if (gintsts & S3C_GINTSTS_GINNakEff) {
+ if (gintsts & GINTSTS_GINNakEff) {
dev_info(hsotg->dev, "GINNakEff triggered\n");
- writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL);
+ writel(DCTL_CGNPInNAK, hsotg->regs + DCTL);
s3c_hsotg_dump(hsotg);
}
- /* if we've had fifo events, we should try and go around the
- * loop again to see if there's any point in returning yet. */
+ /*
+ * if we've had fifo events, we should try and go around the
+ * loop again to see if there's any point in returning yet.
+ */
if (gintsts & IRQ_RETRY_MASK && --retry_count > 0)
goto irq_retry;
@@ -2268,7 +2566,7 @@ irq_retry:
* @desc: The USB endpoint descriptor to configure with.
*
* This is called from the USB gadget code's usb_ep_enable().
-*/
+ */
static int s3c_hsotg_ep_enable(struct usb_ep *ep,
const struct usb_endpoint_descriptor *desc)
{
@@ -2300,7 +2598,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
/* note, we handle this here instead of s3c_hsotg_set_ep_maxpacket */
- epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index);
+ epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
epctrl = readl(hsotg->regs + epctrl_reg);
dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n",
@@ -2308,20 +2606,23 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
spin_lock_irqsave(&hs_ep->lock, flags);
- epctrl &= ~(S3C_DxEPCTL_EPType_MASK | S3C_DxEPCTL_MPS_MASK);
- epctrl |= S3C_DxEPCTL_MPS(mps);
+ epctrl &= ~(DxEPCTL_EPType_MASK | DxEPCTL_MPS_MASK);
+ epctrl |= DxEPCTL_MPS(mps);
- /* mark the endpoint as active, otherwise the core may ignore
- * transactions entirely for this endpoint */
- epctrl |= S3C_DxEPCTL_USBActEp;
+ /*
+ * mark the endpoint as active, otherwise the core may ignore
+ * transactions entirely for this endpoint
+ */
+ epctrl |= DxEPCTL_USBActEp;
- /* set the NAK status on the endpoint, otherwise we might try and
+ /*
+ * set the NAK status on the endpoint, otherwise we might try and
* do something with data that we've yet got a request to process
* since the RXFIFO will take data for an endpoint even if the
* size register hasn't been set.
*/
- epctrl |= S3C_DxEPCTL_SNAK;
+ epctrl |= DxEPCTL_SNAK;
/* update the endpoint state */
hs_ep->ep.maxpacket = mps;
@@ -2336,37 +2637,40 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
goto out;
case USB_ENDPOINT_XFER_BULK:
- epctrl |= S3C_DxEPCTL_EPType_Bulk;
+ epctrl |= DxEPCTL_EPType_Bulk;
break;
case USB_ENDPOINT_XFER_INT:
if (dir_in) {
- /* Allocate our TxFNum by simply using the index
+ /*
+ * Allocate our TxFNum by simply using the index
* of the endpoint for the moment. We could do
* something better if the host indicates how
- * many FIFOs we are expecting to use. */
+ * many FIFOs we are expecting to use.
+ */
hs_ep->periodic = 1;
- epctrl |= S3C_DxEPCTL_TxFNum(index);
+ epctrl |= DxEPCTL_TxFNum(index);
}
- epctrl |= S3C_DxEPCTL_EPType_Intterupt;
+ epctrl |= DxEPCTL_EPType_Intterupt;
break;
case USB_ENDPOINT_XFER_CONTROL:
- epctrl |= S3C_DxEPCTL_EPType_Control;
+ epctrl |= DxEPCTL_EPType_Control;
break;
}
- /* if the hardware has dedicated fifos, we must give each IN EP
+ /*
+ * if the hardware has dedicated fifos, we must give each IN EP
* a unique tx-fifo even if it is non-periodic.
*/
if (dir_in && hsotg->dedicated_fifos)
- epctrl |= S3C_DxEPCTL_TxFNum(index);
+ epctrl |= DxEPCTL_TxFNum(index);
/* for non control endpoints, set PID to D0 */
if (index)
- epctrl |= S3C_DxEPCTL_SetD0PID;
+ epctrl |= DxEPCTL_SetD0PID;
dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n",
__func__, epctrl);
@@ -2383,6 +2687,10 @@ out:
return ret;
}
+/**
+ * s3c_hsotg_ep_disable - disable given endpoint
+ * @ep: The endpoint to disable.
+ */
static int s3c_hsotg_ep_disable(struct usb_ep *ep)
{
struct s3c_hsotg_ep *hs_ep = our_ep(ep);
@@ -2400,7 +2708,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
return -EINVAL;
}
- epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index);
+ epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
/* terminate all requests with shutdown */
kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false);
@@ -2408,9 +2716,9 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
spin_lock_irqsave(&hs_ep->lock, flags);
ctrl = readl(hsotg->regs + epctrl_reg);
- ctrl &= ~S3C_DxEPCTL_EPEna;
- ctrl &= ~S3C_DxEPCTL_USBActEp;
- ctrl |= S3C_DxEPCTL_SNAK;
+ ctrl &= ~DxEPCTL_EPEna;
+ ctrl &= ~DxEPCTL_USBActEp;
+ ctrl |= DxEPCTL_SNAK;
dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
writel(ctrl, hsotg->regs + epctrl_reg);
@@ -2426,7 +2734,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
* on_list - check request is on the given endpoint
* @ep: The endpoint to check.
* @test: The request to test if it is on the endpoint.
-*/
+ */
static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test)
{
struct s3c_hsotg_req *req, *treq;
@@ -2439,6 +2747,11 @@ static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test)
return false;
}
+/**
+ * s3c_hsotg_ep_dequeue - dequeue given endpoint
+ * @ep: The endpoint to dequeue.
+ * @req: The request to be removed from a queue.
+ */
static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
{
struct s3c_hsotg_req *hs_req = our_req(req);
@@ -2461,6 +2774,11 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
return 0;
}
+/**
+ * s3c_hsotg_ep_sethalt - set halt on a given endpoint
+ * @ep: The endpoint to set halt.
+ * @value: Set or unset the halt.
+ */
static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
{
struct s3c_hsotg_ep *hs_ep = our_ep(ep);
@@ -2477,34 +2795,34 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
/* write both IN and OUT control registers */
- epreg = S3C_DIEPCTL(index);
+ epreg = DIEPCTL(index);
epctl = readl(hs->regs + epreg);
if (value) {
- epctl |= S3C_DxEPCTL_Stall + S3C_DxEPCTL_SNAK;
- if (epctl & S3C_DxEPCTL_EPEna)
- epctl |= S3C_DxEPCTL_EPDis;
+ epctl |= DxEPCTL_Stall + DxEPCTL_SNAK;
+ if (epctl & DxEPCTL_EPEna)
+ epctl |= DxEPCTL_EPDis;
} else {
- epctl &= ~S3C_DxEPCTL_Stall;
- xfertype = epctl & S3C_DxEPCTL_EPType_MASK;
- if (xfertype == S3C_DxEPCTL_EPType_Bulk ||
- xfertype == S3C_DxEPCTL_EPType_Intterupt)
- epctl |= S3C_DxEPCTL_SetD0PID;
+ epctl &= ~DxEPCTL_Stall;
+ xfertype = epctl & DxEPCTL_EPType_MASK;
+ if (xfertype == DxEPCTL_EPType_Bulk ||
+ xfertype == DxEPCTL_EPType_Intterupt)
+ epctl |= DxEPCTL_SetD0PID;
}
writel(epctl, hs->regs + epreg);
- epreg = S3C_DOEPCTL(index);
+ epreg = DOEPCTL(index);
epctl = readl(hs->regs + epreg);
if (value)
- epctl |= S3C_DxEPCTL_Stall;
+ epctl |= DxEPCTL_Stall;
else {
- epctl &= ~S3C_DxEPCTL_Stall;
- xfertype = epctl & S3C_DxEPCTL_EPType_MASK;
- if (xfertype == S3C_DxEPCTL_EPType_Bulk ||
- xfertype == S3C_DxEPCTL_EPType_Intterupt)
- epctl |= S3C_DxEPCTL_SetD0PID;
+ epctl &= ~DxEPCTL_Stall;
+ xfertype = epctl & DxEPCTL_EPType_MASK;
+ if (xfertype == DxEPCTL_EPType_Bulk ||
+ xfertype == DxEPCTL_EPType_Intterupt)
+ epctl |= DxEPCTL_SetD0PID;
}
writel(epctl, hs->regs + epreg);
@@ -2526,57 +2844,91 @@ static struct usb_ep_ops s3c_hsotg_ep_ops = {
};
/**
- * s3c_hsotg_corereset - issue softreset to the core
- * @hsotg: The device state
+ * s3c_hsotg_phy_enable - enable platform phy dev
+ * @hsotg: The driver state
*
- * Issue a soft reset to the core, and await the core finishing it.
-*/
-static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
+ * A wrapper for platform code responsible for controlling
+ * low-level USB code
+ */
+static void s3c_hsotg_phy_enable(struct s3c_hsotg *hsotg)
{
- int timeout;
- u32 grstctl;
+ struct platform_device *pdev = to_platform_device(hsotg->dev);
- dev_dbg(hsotg->dev, "resetting core\n");
+ dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev);
+ if (hsotg->plat->phy_init)
+ hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
+}
- /* issue soft reset */
- writel(S3C_GRSTCTL_CSftRst, hsotg->regs + S3C_GRSTCTL);
+/**
+ * s3c_hsotg_phy_disable - disable platform phy dev
+ * @hsotg: The driver state
+ *
+ * A wrapper for platform code responsible for controlling
+ * low-level USB code
+ */
+static void s3c_hsotg_phy_disable(struct s3c_hsotg *hsotg)
+{
+ struct platform_device *pdev = to_platform_device(hsotg->dev);
- timeout = 1000;
- do {
- grstctl = readl(hsotg->regs + S3C_GRSTCTL);
- } while ((grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0);
+ if (hsotg->plat->phy_exit)
+ hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
+}
- if (grstctl & S3C_GRSTCTL_CSftRst) {
- dev_err(hsotg->dev, "Failed to get CSftRst asserted\n");
- return -EINVAL;
- }
+/**
+ * s3c_hsotg_init - initalize the usb core
+ * @hsotg: The driver state
+ */
+static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
+{
+ /* unmask subset of endpoint interrupts */
- timeout = 1000;
+ writel(DIEPMSK_TimeOUTMsk | DIEPMSK_AHBErrMsk |
+ DIEPMSK_EPDisbldMsk | DIEPMSK_XferComplMsk,
+ hsotg->regs + DIEPMSK);
- while (1) {
- u32 grstctl = readl(hsotg->regs + S3C_GRSTCTL);
+ writel(DOEPMSK_SetupMsk | DOEPMSK_AHBErrMsk |
+ DOEPMSK_EPDisbldMsk | DOEPMSK_XferComplMsk,
+ hsotg->regs + DOEPMSK);
- if (timeout-- < 0) {
- dev_info(hsotg->dev,
- "%s: reset failed, GRSTCTL=%08x\n",
- __func__, grstctl);
- return -ETIMEDOUT;
- }
+ writel(0, hsotg->regs + DAINTMSK);
- if (!(grstctl & S3C_GRSTCTL_AHBIdle))
- continue;
+ /* Be in disconnected state until gadget is registered */
+ __orr32(hsotg->regs + DCTL, DCTL_SftDiscon);
- break; /* reset done */
+ if (0) {
+ /* post global nak until we're ready */
+ writel(DCTL_SGNPInNAK | DCTL_SGOUTNak,
+ hsotg->regs + DCTL);
}
- dev_dbg(hsotg->dev, "reset successful\n");
- return 0;
+ /* setup fifos */
+
+ dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
+ readl(hsotg->regs + GRXFSIZ),
+ readl(hsotg->regs + GNPTXFSIZ));
+
+ s3c_hsotg_init_fifo(hsotg);
+
+ /* set the PLL on, remove the HNP/SRP and set the PHY */
+ writel(GUSBCFG_PHYIf16 | GUSBCFG_TOutCal(7) | (0x5 << 10),
+ hsotg->regs + GUSBCFG);
+
+ writel(using_dma(hsotg) ? GAHBCFG_DMAEn : 0x0,
+ hsotg->regs + GAHBCFG);
}
-static int s3c_hsotg_start(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *))
+/**
+ * s3c_hsotg_udc_start - prepare the udc for work
+ * @gadget: The usb gadget state
+ * @driver: The usb gadget driver
+ *
+ * Perform initialization to prepare udc device and driver
+ * to work.
+ */
+static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
{
- struct s3c_hsotg *hsotg = our_hsotg;
+ struct s3c_hsotg *hsotg = to_hsotg(gadget);
int ret;
if (!hsotg) {
@@ -2592,7 +2944,7 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver,
if (driver->max_speed < USB_SPEED_FULL)
dev_err(hsotg->dev, "%s: bad speed\n", __func__);
- if (!bind || !driver->setup) {
+ if (!driver->setup) {
dev_err(hsotg->dev, "%s: missing entry points\n", __func__);
return -EINVAL;
}
@@ -2605,135 +2957,17 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver,
hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask;
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
- ret = device_add(&hsotg->gadget.dev);
+ ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
+ hsotg->supplies);
if (ret) {
- dev_err(hsotg->dev, "failed to register gadget device\n");
+ dev_err(hsotg->dev, "failed to enable supplies: %d\n", ret);
goto err;
}
- ret = bind(&hsotg->gadget);
- if (ret) {
- dev_err(hsotg->dev, "failed bind %s\n", driver->driver.name);
-
- hsotg->gadget.dev.driver = NULL;
- hsotg->driver = NULL;
- goto err;
- }
-
- /* we must now enable ep0 ready for host detection and then
- * set configuration. */
-
- s3c_hsotg_corereset(hsotg);
-
- /* set the PLL on, remove the HNP/SRP and set the PHY */
- writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) |
- (0x5 << 10), hsotg->regs + S3C_GUSBCFG);
-
- /* looks like soft-reset changes state of FIFOs */
- s3c_hsotg_init_fifo(hsotg);
-
- __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
-
- writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG);
-
- /* Clear any pending OTG interrupts */
- writel(0xffffffff, hsotg->regs + S3C_GOTGINT);
-
- /* Clear any pending interrupts */
- writel(0xffffffff, hsotg->regs + S3C_GINTSTS);
-
- writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt |
- S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst |
- S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt |
- S3C_GINTSTS_USBSusp | S3C_GINTSTS_WkUpInt |
- S3C_GINTSTS_GOUTNakEff | S3C_GINTSTS_GINNakEff |
- S3C_GINTSTS_ErlySusp,
- hsotg->regs + S3C_GINTMSK);
-
- if (using_dma(hsotg))
- writel(S3C_GAHBCFG_GlblIntrEn | S3C_GAHBCFG_DMAEn |
- S3C_GAHBCFG_HBstLen_Incr4,
- hsotg->regs + S3C_GAHBCFG);
- else
- writel(S3C_GAHBCFG_GlblIntrEn, hsotg->regs + S3C_GAHBCFG);
-
- /* Enabling INTknTXFEmpMsk here seems to be a big mistake, we end
- * up being flooded with interrupts if the host is polling the
- * endpoint to try and read data. */
-
- writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
- S3C_DIEPMSK_INTknEPMisMsk |
- S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk |
- ((hsotg->dedicated_fifos) ? S3C_DIEPMSK_TxFIFOEmpty : 0),
- hsotg->regs + S3C_DIEPMSK);
-
- /* don't need XferCompl, we get that from RXFIFO in slave mode. In
- * DMA mode we may need this. */
- writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk |
- S3C_DOEPMSK_EPDisbldMsk |
- (using_dma(hsotg) ? (S3C_DIEPMSK_XferComplMsk |
- S3C_DIEPMSK_TimeOUTMsk) : 0),
- hsotg->regs + S3C_DOEPMSK);
-
- writel(0, hsotg->regs + S3C_DAINTMSK);
-
- dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
- readl(hsotg->regs + S3C_DIEPCTL0),
- readl(hsotg->regs + S3C_DOEPCTL0));
-
- /* enable in and out endpoint interrupts */
- s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt);
-
- /* Enable the RXFIFO when in slave mode, as this is how we collect
- * the data. In DMA mode, we get events from the FIFO but also
- * things we cannot process, so do not use it. */
- if (!using_dma(hsotg))
- s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_RxFLvl);
-
- /* Enable interrupts for EP0 in and out */
- s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1);
- s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1);
-
- __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone);
- udelay(10); /* see openiboot */
- __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone);
-
- dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL));
-
- /* S3C_DxEPCTL_USBActEp says RO in manual, but seems to be set by
- writing to the EPCTL register.. */
-
- /* set to read 1 8byte packet */
- writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) |
- S3C_DxEPTSIZ_XferSize(8), hsotg->regs + DOEPTSIZ0);
-
- writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
- S3C_DxEPCTL_CNAK | S3C_DxEPCTL_EPEna |
- S3C_DxEPCTL_USBActEp,
- hsotg->regs + S3C_DOEPCTL0);
-
- /* enable, but don't activate EP0in */
- writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
- S3C_DxEPCTL_USBActEp, hsotg->regs + S3C_DIEPCTL0);
-
- s3c_hsotg_enqueue_setup(hsotg);
-
- dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
- readl(hsotg->regs + S3C_DIEPCTL0),
- readl(hsotg->regs + S3C_DOEPCTL0));
-
- /* clear global NAKs */
- writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK,
- hsotg->regs + S3C_DCTL);
-
- /* must be at-least 3ms to allow bus to see disconnect */
- msleep(3);
-
- /* remove the soft-disconnect and let's go */
- __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
-
- /* report to the user, and return */
+ s3c_hsotg_phy_enable(hsotg);
+ s3c_hsotg_core_init(hsotg);
+ hsotg->last_rst = jiffies;
dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
return 0;
@@ -2743,9 +2977,17 @@ err:
return ret;
}
-static int s3c_hsotg_stop(struct usb_gadget_driver *driver)
+/**
+ * s3c_hsotg_udc_stop - stop the udc
+ * @gadget: The usb gadget state
+ * @driver: The usb gadget driver
+ *
+ * Stop udc hw block and stay tunned for future transmissions
+ */
+static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
{
- struct s3c_hsotg *hsotg = our_hsotg;
+ struct s3c_hsotg *hsotg = to_hsotg(gadget);
int ep;
if (!hsotg)
@@ -2755,16 +2997,15 @@ static int s3c_hsotg_stop(struct usb_gadget_driver *driver)
return -EINVAL;
/* all endpoints should be shutdown */
- for (ep = 0; ep < S3C_HSOTG_EPS; ep++)
+ for (ep = 0; ep < hsotg->num_of_eps; ep++)
s3c_hsotg_ep_disable(&hsotg->eps[ep].ep);
- call_gadget(hsotg, disconnect);
+ s3c_hsotg_phy_disable(hsotg);
+ regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
- driver->unbind(&hsotg->gadget);
hsotg->driver = NULL;
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
-
- device_del(&hsotg->gadget.dev);
+ hsotg->gadget.dev.driver = NULL;
dev_info(hsotg->dev, "unregistered gadget driver '%s'\n",
driver->driver.name);
@@ -2772,6 +3013,12 @@ static int s3c_hsotg_stop(struct usb_gadget_driver *driver)
return 0;
}
+/**
+ * s3c_hsotg_gadget_getframe - read the frame number
+ * @gadget: The usb gadget state
+ *
+ * Read the {micro} frame number
+ */
static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget)
{
return s3c_hsotg_read_frameno(to_hsotg(gadget));
@@ -2779,8 +3026,8 @@ static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget)
static struct usb_gadget_ops s3c_hsotg_gadget_ops = {
.get_frame = s3c_hsotg_gadget_getframe,
- .start = s3c_hsotg_start,
- .stop = s3c_hsotg_stop,
+ .udc_start = s3c_hsotg_udc_start,
+ .udc_stop = s3c_hsotg_udc_stop,
};
/**
@@ -2827,111 +3074,42 @@ static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg,
hs_ep->ep.maxpacket = epnum ? 512 : EP0_MPS_LIMIT;
hs_ep->ep.ops = &s3c_hsotg_ep_ops;
- /* Read the FIFO size for the Periodic TX FIFO, even if we're
+ /*
+ * Read the FIFO size for the Periodic TX FIFO, even if we're
* an OUT endpoint, we may as well do this if in future the
* code is changed to make each endpoint's direction changeable.
*/
- ptxfifo = readl(hsotg->regs + S3C_DPTXFSIZn(epnum));
- hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4;
+ ptxfifo = readl(hsotg->regs + DPTXFSIZn(epnum));
+ hs_ep->fifo_size = DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4;
- /* if we're using dma, we need to set the next-endpoint pointer
+ /*
+ * if we're using dma, we need to set the next-endpoint pointer
* to be something valid.
*/
if (using_dma(hsotg)) {
- u32 next = S3C_DxEPCTL_NextEp((epnum + 1) % 15);
- writel(next, hsotg->regs + S3C_DIEPCTL(epnum));
- writel(next, hsotg->regs + S3C_DOEPCTL(epnum));
+ u32 next = DxEPCTL_NextEp((epnum + 1) % 15);
+ writel(next, hsotg->regs + DIEPCTL(epnum));
+ writel(next, hsotg->regs + DOEPCTL(epnum));
}
}
/**
- * s3c_hsotg_otgreset - reset the OtG phy block
- * @hsotg: The host state.
+ * s3c_hsotg_hw_cfg - read HW configuration registers
+ * @param: The device state
*
- * Power up the phy, set the basic configuration and start the PHY.
+ * Read the USB core HW configuration registers
*/
-static void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg)
-{
- struct clk *xusbxti;
- u32 pwr, osc;
-
- pwr = readl(S3C_PHYPWR);
- pwr &= ~0x19;
- writel(pwr, S3C_PHYPWR);
- mdelay(1);
-
- osc = hsotg->plat->is_osc ? S3C_PHYCLK_EXT_OSC : 0;
-
- xusbxti = clk_get(hsotg->dev, "xusbxti");
- if (xusbxti && !IS_ERR(xusbxti)) {
- switch (clk_get_rate(xusbxti)) {
- case 12*MHZ:
- osc |= S3C_PHYCLK_CLKSEL_12M;
- break;
- case 24*MHZ:
- osc |= S3C_PHYCLK_CLKSEL_24M;
- break;
- default:
- case 48*MHZ:
- /* default reference clock */
- break;
- }
- clk_put(xusbxti);
- }
-
- writel(osc | 0x10, S3C_PHYCLK);
-
- /* issue a full set of resets to the otg and core */
-
- writel(S3C_RSTCON_PHY, S3C_RSTCON);
- udelay(20); /* at-least 10uS */
- writel(0, S3C_RSTCON);
-}
-
-
-static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_hw_cfg(struct s3c_hsotg *hsotg)
{
- u32 cfg4;
-
- /* unmask subset of endpoint interrupts */
-
- writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
- S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk,
- hsotg->regs + S3C_DIEPMSK);
-
- writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk |
- S3C_DOEPMSK_EPDisbldMsk | S3C_DOEPMSK_XferComplMsk,
- hsotg->regs + S3C_DOEPMSK);
-
- writel(0, hsotg->regs + S3C_DAINTMSK);
-
- /* Be in disconnected state until gadget is registered */
- __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
-
- if (0) {
- /* post global nak until we're ready */
- writel(S3C_DCTL_SGNPInNAK | S3C_DCTL_SGOUTNak,
- hsotg->regs + S3C_DCTL);
- }
-
- /* setup fifos */
-
- dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
- readl(hsotg->regs + S3C_GRXFSIZ),
- readl(hsotg->regs + S3C_GNPTXFSIZ));
-
- s3c_hsotg_init_fifo(hsotg);
-
- /* set the PLL on, remove the HNP/SRP and set the PHY */
- writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) | (0x5 << 10),
- hsotg->regs + S3C_GUSBCFG);
+ u32 cfg2, cfg4;
+ /* check hardware configuration */
- writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0,
- hsotg->regs + S3C_GAHBCFG);
+ cfg2 = readl(hsotg->regs + 0x48);
+ hsotg->num_of_eps = (cfg2 >> 10) & 0xF;
- /* check hardware configuration */
+ dev_info(hsotg->dev, "EPs:%d\n", hsotg->num_of_eps);
cfg4 = readl(hsotg->regs + 0x50);
hsotg->dedicated_fifos = (cfg4 >> 25) & 1;
@@ -2940,6 +3118,10 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
hsotg->dedicated_fifos ? "dedicated" : "shared");
}
+/**
+ * s3c_hsotg_dump - dump state of the udc
+ * @param: The device state
+ */
static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
{
#ifdef DEBUG
@@ -2949,46 +3131,45 @@ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
int idx;
dev_info(dev, "DCFG=0x%08x, DCTL=0x%08x, DIEPMSK=%08x\n",
- readl(regs + S3C_DCFG), readl(regs + S3C_DCTL),
- readl(regs + S3C_DIEPMSK));
+ readl(regs + DCFG), readl(regs + DCTL),
+ readl(regs + DIEPMSK));
dev_info(dev, "GAHBCFG=0x%08x, 0x44=0x%08x\n",
- readl(regs + S3C_GAHBCFG), readl(regs + 0x44));
+ readl(regs + GAHBCFG), readl(regs + 0x44));
dev_info(dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
- readl(regs + S3C_GRXFSIZ), readl(regs + S3C_GNPTXFSIZ));
+ readl(regs + GRXFSIZ), readl(regs + GNPTXFSIZ));
/* show periodic fifo settings */
for (idx = 1; idx <= 15; idx++) {
- val = readl(regs + S3C_DPTXFSIZn(idx));
+ val = readl(regs + DPTXFSIZn(idx));
dev_info(dev, "DPTx[%d] FSize=%d, StAddr=0x%08x\n", idx,
- val >> S3C_DPTXFSIZn_DPTxFSize_SHIFT,
- val & S3C_DPTXFSIZn_DPTxFStAddr_MASK);
+ val >> DPTXFSIZn_DPTxFSize_SHIFT,
+ val & DPTXFSIZn_DPTxFStAddr_MASK);
}
for (idx = 0; idx < 15; idx++) {
dev_info(dev,
"ep%d-in: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", idx,
- readl(regs + S3C_DIEPCTL(idx)),
- readl(regs + S3C_DIEPTSIZ(idx)),
- readl(regs + S3C_DIEPDMA(idx)));
+ readl(regs + DIEPCTL(idx)),
+ readl(regs + DIEPTSIZ(idx)),
+ readl(regs + DIEPDMA(idx)));
- val = readl(regs + S3C_DOEPCTL(idx));
+ val = readl(regs + DOEPCTL(idx));
dev_info(dev,
"ep%d-out: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n",
- idx, readl(regs + S3C_DOEPCTL(idx)),
- readl(regs + S3C_DOEPTSIZ(idx)),
- readl(regs + S3C_DOEPDMA(idx)));
+ idx, readl(regs + DOEPCTL(idx)),
+ readl(regs + DOEPTSIZ(idx)),
+ readl(regs + DOEPDMA(idx)));
}
dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n",
- readl(regs + S3C_DVBUSDIS), readl(regs + S3C_DVBUSPULSE));
+ readl(regs + DVBUSDIS), readl(regs + DVBUSPULSE));
#endif
}
-
/**
* state_show - debugfs: show overall driver and device state.
* @seq: The seq file to write to.
@@ -3005,38 +3186,38 @@ static int state_show(struct seq_file *seq, void *v)
int idx;
seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n",
- readl(regs + S3C_DCFG),
- readl(regs + S3C_DCTL),
- readl(regs + S3C_DSTS));
+ readl(regs + DCFG),
+ readl(regs + DCTL),
+ readl(regs + DSTS));
seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n",
- readl(regs + S3C_DIEPMSK), readl(regs + S3C_DOEPMSK));
+ readl(regs + DIEPMSK), readl(regs + DOEPMSK));
seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n",
- readl(regs + S3C_GINTMSK),
- readl(regs + S3C_GINTSTS));
+ readl(regs + GINTMSK),
+ readl(regs + GINTSTS));
seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n",
- readl(regs + S3C_DAINTMSK),
- readl(regs + S3C_DAINT));
+ readl(regs + DAINTMSK),
+ readl(regs + DAINT));
seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n",
- readl(regs + S3C_GNPTXSTS),
- readl(regs + S3C_GRXSTSR));
+ readl(regs + GNPTXSTS),
+ readl(regs + GRXSTSR));
seq_printf(seq, "\nEndpoint status:\n");
for (idx = 0; idx < 15; idx++) {
u32 in, out;
- in = readl(regs + S3C_DIEPCTL(idx));
- out = readl(regs + S3C_DOEPCTL(idx));
+ in = readl(regs + DIEPCTL(idx));
+ out = readl(regs + DOEPCTL(idx));
seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x",
idx, in, out);
- in = readl(regs + S3C_DIEPTSIZ(idx));
- out = readl(regs + S3C_DOEPTSIZ(idx));
+ in = readl(regs + DIEPTSIZ(idx));
+ out = readl(regs + DOEPTSIZ(idx));
seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x",
in, out);
@@ -3067,7 +3248,7 @@ static const struct file_operations state_fops = {
*
* Show the FIFO information for the overall fifo and all the
* periodic transmission FIFOs.
-*/
+ */
static int fifo_show(struct seq_file *seq, void *v)
{
struct s3c_hsotg *hsotg = seq->private;
@@ -3076,21 +3257,21 @@ static int fifo_show(struct seq_file *seq, void *v)
int idx;
seq_printf(seq, "Non-periodic FIFOs:\n");
- seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + S3C_GRXFSIZ));
+ seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ));
- val = readl(regs + S3C_GNPTXFSIZ);
+ val = readl(regs + GNPTXFSIZ);
seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n",
- val >> S3C_GNPTXFSIZ_NPTxFDep_SHIFT,
- val & S3C_GNPTXFSIZ_NPTxFStAddr_MASK);
+ val >> GNPTXFSIZ_NPTxFDep_SHIFT,
+ val & GNPTXFSIZ_NPTxFStAddr_MASK);
seq_printf(seq, "\nPeriodic TXFIFOs:\n");
for (idx = 1; idx <= 15; idx++) {
- val = readl(regs + S3C_DPTXFSIZn(idx));
+ val = readl(regs + DPTXFSIZn(idx));
seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx,
- val >> S3C_DPTXFSIZn_DPTxFSize_SHIFT,
- val & S3C_DPTXFSIZn_DPTxFStAddr_MASK);
+ val >> DPTXFSIZn_DPTxFSize_SHIFT,
+ val & DPTXFSIZn_DPTxFStAddr_MASK);
}
return 0;
@@ -3122,7 +3303,7 @@ static const char *decode_direction(int is_in)
*
* This debugfs entry shows the state of the given endpoint (one is
* registered for each available).
-*/
+ */
static int ep_show(struct seq_file *seq, void *v)
{
struct s3c_hsotg_ep *ep = seq->private;
@@ -3139,20 +3320,20 @@ static int ep_show(struct seq_file *seq, void *v)
/* first show the register state */
seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n",
- readl(regs + S3C_DIEPCTL(index)),
- readl(regs + S3C_DOEPCTL(index)));
+ readl(regs + DIEPCTL(index)),
+ readl(regs + DOEPCTL(index)));
seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n",
- readl(regs + S3C_DIEPDMA(index)),
- readl(regs + S3C_DOEPDMA(index)));
+ readl(regs + DIEPDMA(index)),
+ readl(regs + DOEPDMA(index)));
seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n",
- readl(regs + S3C_DIEPINT(index)),
- readl(regs + S3C_DOEPINT(index)));
+ readl(regs + DIEPINT(index)),
+ readl(regs + DOEPINT(index)));
seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n",
- readl(regs + S3C_DIEPTSIZ(index)),
- readl(regs + S3C_DOEPTSIZ(index)));
+ readl(regs + DIEPTSIZ(index)),
+ readl(regs + DOEPTSIZ(index)));
seq_printf(seq, "\n");
seq_printf(seq, "mps %d\n", ep->ep.maxpacket);
@@ -3202,7 +3383,7 @@ static const struct file_operations ep_fops = {
* about the state of the system. The directory name is created
* with the same name as the device itself, in case we end up
* with multiple blocks in future systems.
-*/
+ */
static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
{
struct dentry *root;
@@ -3231,7 +3412,7 @@ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
/* create one file for each endpoint */
- for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) {
+ for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) {
struct s3c_hsotg_ep *ep = &hsotg->eps[epidx];
ep->debugfs = debugfs_create_file(ep->name, 0444,
@@ -3248,12 +3429,12 @@ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
* @hsotg: The driver state
*
* Cleanup (remove) the debugfs files for use on module exit.
-*/
+ */
static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
{
unsigned epidx;
- for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) {
+ for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) {
struct s3c_hsotg_ep *ep = &hsotg->eps[epidx];
debugfs_remove(ep->debugfs);
}
@@ -3264,48 +3445,39 @@ static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
}
/**
- * s3c_hsotg_gate - set the hardware gate for the block
- * @pdev: The device we bound to
- * @on: On or off.
- *
- * Set the hardware gate setting into the block. If we end up on
- * something other than an S3C64XX, then we might need to change this
- * to using a platform data callback, or some other mechanism.
+ * s3c_hsotg_release - release callback for hsotg device
+ * @dev: Device to for which release is called
*/
-static void s3c_hsotg_gate(struct platform_device *pdev, bool on)
+static void s3c_hsotg_release(struct device *dev)
{
- unsigned long flags;
- u32 others;
-
- local_irq_save(flags);
-
- others = __raw_readl(S3C64XX_OTHERS);
- if (on)
- others |= S3C64XX_OTHERS_USBMASK;
- else
- others &= ~S3C64XX_OTHERS_USBMASK;
- __raw_writel(others, S3C64XX_OTHERS);
+ struct s3c_hsotg *hsotg = dev_get_drvdata(dev);
- local_irq_restore(flags);
+ kfree(hsotg);
}
-static struct s3c_hsotg_plat s3c_hsotg_default_pdata;
+/**
+ * s3c_hsotg_probe - probe function for hsotg driver
+ * @pdev: The platform information for the driver
+ */
static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
{
struct s3c_hsotg_plat *plat = pdev->dev.platform_data;
struct device *dev = &pdev->dev;
+ struct s3c_hsotg_ep *eps;
struct s3c_hsotg *hsotg;
struct resource *res;
int epnum;
int ret;
+ int i;
- if (!plat)
- plat = &s3c_hsotg_default_pdata;
+ plat = pdev->dev.platform_data;
+ if (!plat) {
+ dev_err(&pdev->dev, "no platform data defined\n");
+ return -EINVAL;
+ }
- hsotg = kzalloc(sizeof(struct s3c_hsotg) +
- sizeof(struct s3c_hsotg_ep) * S3C_HSOTG_EPS,
- GFP_KERNEL);
+ hsotg = kzalloc(sizeof(struct s3c_hsotg), GFP_KERNEL);
if (!hsotg) {
dev_err(dev, "cannot get memory\n");
return -ENOMEM;
@@ -3371,6 +3543,54 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
hsotg->gadget.dev.parent = dev;
hsotg->gadget.dev.dma_mask = dev->dma_mask;
+ hsotg->gadget.dev.release = s3c_hsotg_release;
+
+ /* reset the system */
+
+ clk_prepare_enable(hsotg->clk);
+
+ /* regulators */
+
+ for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
+ hsotg->supplies[i].supply = s3c_hsotg_supply_names[i];
+
+ ret = regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
+ hsotg->supplies);
+ if (ret) {
+ dev_err(dev, "failed to request supplies: %d\n", ret);
+ goto err_irq;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
+ hsotg->supplies);
+
+ if (ret) {
+ dev_err(hsotg->dev, "failed to enable supplies: %d\n", ret);
+ goto err_supplies;
+ }
+
+ /* usb phy enable */
+ s3c_hsotg_phy_enable(hsotg);
+
+ s3c_hsotg_corereset(hsotg);
+ s3c_hsotg_init(hsotg);
+ s3c_hsotg_hw_cfg(hsotg);
+
+ /* hsotg->num_of_eps holds number of EPs other than ep0 */
+
+ if (hsotg->num_of_eps == 0) {
+ dev_err(dev, "wrong number of EPs (zero)\n");
+ goto err_supplies;
+ }
+
+ eps = kcalloc(hsotg->num_of_eps + 1, sizeof(struct s3c_hsotg_ep),
+ GFP_KERNEL);
+ if (!eps) {
+ dev_err(dev, "cannot get memory\n");
+ goto err_supplies;
+ }
+
+ hsotg->eps = eps;
/* setup endpoint information */
@@ -3383,39 +3603,47 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
GFP_KERNEL);
if (!hsotg->ctrl_req) {
dev_err(dev, "failed to allocate ctrl req\n");
- goto err_regs;
+ goto err_ep_mem;
}
- /* reset the system */
+ /* initialise the endpoints now the core has been initialised */
+ for (epnum = 0; epnum < hsotg->num_of_eps; epnum++)
+ s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum);
- clk_enable(hsotg->clk);
+ /* disable power and clock */
- s3c_hsotg_gate(pdev, true);
+ ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
+ hsotg->supplies);
+ if (ret) {
+ dev_err(hsotg->dev, "failed to disable supplies: %d\n", ret);
+ goto err_ep_mem;
+ }
- s3c_hsotg_otgreset(hsotg);
- s3c_hsotg_corereset(hsotg);
- s3c_hsotg_init(hsotg);
+ s3c_hsotg_phy_disable(hsotg);
- /* initialise the endpoints now the core has been initialised */
- for (epnum = 0; epnum < S3C_HSOTG_EPS; epnum++)
- s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum);
+ ret = device_add(&hsotg->gadget.dev);
+ if (ret) {
+ put_device(&hsotg->gadget.dev);
+ goto err_ep_mem;
+ }
ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
if (ret)
- goto err_add_udc;
+ goto err_ep_mem;
s3c_hsotg_create_debug(hsotg);
s3c_hsotg_dump(hsotg);
- our_hsotg = hsotg;
return 0;
-err_add_udc:
- s3c_hsotg_gate(pdev, false);
- clk_disable(hsotg->clk);
- clk_put(hsotg->clk);
-
+err_ep_mem:
+ kfree(eps);
+err_supplies:
+ s3c_hsotg_phy_disable(hsotg);
+ regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
+err_irq:
+ free_irq(hsotg->irq, hsotg);
err_regs:
iounmap(hsotg->regs);
@@ -3423,12 +3651,17 @@ err_regs_res:
release_resource(hsotg->regs_res);
kfree(hsotg->regs_res);
err_clk:
+ clk_disable_unprepare(hsotg->clk);
clk_put(hsotg->clk);
err_mem:
kfree(hsotg);
return ret;
}
+/**
+ * s3c_hsotg_remove - remove function for hsotg driver
+ * @pdev: The platform information for the driver
+ */
static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
{
struct s3c_hsotg *hsotg = platform_get_drvdata(pdev);
@@ -3437,7 +3670,10 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
s3c_hsotg_delete_debug(hsotg);
- usb_gadget_unregister_driver(hsotg->driver);
+ if (hsotg->driver) {
+ /* should have been done already by driver model core */
+ usb_gadget_unregister_driver(hsotg->driver);
+ }
free_irq(hsotg->irq, hsotg);
iounmap(hsotg->regs);
@@ -3445,12 +3681,13 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
release_resource(hsotg->regs_res);
kfree(hsotg->regs_res);
- s3c_hsotg_gate(pdev, false);
+ s3c_hsotg_phy_disable(hsotg);
+ regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
- clk_disable(hsotg->clk);
+ clk_disable_unprepare(hsotg->clk);
clk_put(hsotg->clk);
- kfree(hsotg);
+ device_unregister(&hsotg->gadget.dev);
return 0;
}
diff --git a/drivers/usb/gadget/s3c-hsotg.h b/drivers/usb/gadget/s3c-hsotg.h
new file mode 100644
index 000000000000..d650b1295831
--- /dev/null
+++ b/drivers/usb/gadget/s3c-hsotg.h
@@ -0,0 +1,377 @@
+/* drivers/usb/gadget/s3c-hsotg.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * USB2.0 Highspeed/OtG Synopsis DWC2 device block registers
+ *
+ * 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 __REGS_USB_HSOTG_H
+#define __REGS_USB_HSOTG_H __FILE__
+
+#define HSOTG_REG(x) (x)
+
+#define GOTGCTL HSOTG_REG(0x000)
+#define GOTGCTL_BSESVLD (1 << 19)
+#define GOTGCTL_ASESVLD (1 << 18)
+#define GOTGCTL_DBNC_SHORT (1 << 17)
+#define GOTGCTL_CONID_B (1 << 16)
+#define GOTGCTL_DEVHNPEN (1 << 11)
+#define GOTGCTL_HSSETHNPEN (1 << 10)
+#define GOTGCTL_HNPREQ (1 << 9)
+#define GOTGCTL_HSTNEGSCS (1 << 8)
+#define GOTGCTL_SESREQ (1 << 1)
+#define GOTGCTL_SESREQSCS (1 << 0)
+
+#define GOTGINT HSOTG_REG(0x004)
+#define GOTGINT_DbnceDone (1 << 19)
+#define GOTGINT_ADevTOUTChg (1 << 18)
+#define GOTGINT_HstNegDet (1 << 17)
+#define GOTGINT_HstnegSucStsChng (1 << 9)
+#define GOTGINT_SesReqSucStsChng (1 << 8)
+#define GOTGINT_SesEndDet (1 << 2)
+
+#define GAHBCFG HSOTG_REG(0x008)
+#define GAHBCFG_PTxFEmpLvl (1 << 8)
+#define GAHBCFG_NPTxFEmpLvl (1 << 7)
+#define GAHBCFG_DMAEn (1 << 5)
+#define GAHBCFG_HBstLen_MASK (0xf << 1)
+#define GAHBCFG_HBstLen_SHIFT (1)
+#define GAHBCFG_HBstLen_Single (0x0 << 1)
+#define GAHBCFG_HBstLen_Incr (0x1 << 1)
+#define GAHBCFG_HBstLen_Incr4 (0x3 << 1)
+#define GAHBCFG_HBstLen_Incr8 (0x5 << 1)
+#define GAHBCFG_HBstLen_Incr16 (0x7 << 1)
+#define GAHBCFG_GlblIntrEn (1 << 0)
+
+#define GUSBCFG HSOTG_REG(0x00C)
+#define GUSBCFG_PHYLPClkSel (1 << 15)
+#define GUSBCFG_HNPCap (1 << 9)
+#define GUSBCFG_SRPCap (1 << 8)
+#define GUSBCFG_PHYIf16 (1 << 3)
+#define GUSBCFG_TOutCal_MASK (0x7 << 0)
+#define GUSBCFG_TOutCal_SHIFT (0)
+#define GUSBCFG_TOutCal_LIMIT (0x7)
+#define GUSBCFG_TOutCal(_x) ((_x) << 0)
+
+#define GRSTCTL HSOTG_REG(0x010)
+
+#define GRSTCTL_AHBIdle (1 << 31)
+#define GRSTCTL_DMAReq (1 << 30)
+#define GRSTCTL_TxFNum_MASK (0x1f << 6)
+#define GRSTCTL_TxFNum_SHIFT (6)
+#define GRSTCTL_TxFNum_LIMIT (0x1f)
+#define GRSTCTL_TxFNum(_x) ((_x) << 6)
+#define GRSTCTL_TxFFlsh (1 << 5)
+#define GRSTCTL_RxFFlsh (1 << 4)
+#define GRSTCTL_INTknQFlsh (1 << 3)
+#define GRSTCTL_FrmCntrRst (1 << 2)
+#define GRSTCTL_HSftRst (1 << 1)
+#define GRSTCTL_CSftRst (1 << 0)
+
+#define GINTSTS HSOTG_REG(0x014)
+#define GINTMSK HSOTG_REG(0x018)
+
+#define GINTSTS_WkUpInt (1 << 31)
+#define GINTSTS_SessReqInt (1 << 30)
+#define GINTSTS_DisconnInt (1 << 29)
+#define GINTSTS_ConIDStsChng (1 << 28)
+#define GINTSTS_PTxFEmp (1 << 26)
+#define GINTSTS_HChInt (1 << 25)
+#define GINTSTS_PrtInt (1 << 24)
+#define GINTSTS_FetSusp (1 << 22)
+#define GINTSTS_incompIP (1 << 21)
+#define GINTSTS_IncomplSOIN (1 << 20)
+#define GINTSTS_OEPInt (1 << 19)
+#define GINTSTS_IEPInt (1 << 18)
+#define GINTSTS_EPMis (1 << 17)
+#define GINTSTS_EOPF (1 << 15)
+#define GINTSTS_ISOutDrop (1 << 14)
+#define GINTSTS_EnumDone (1 << 13)
+#define GINTSTS_USBRst (1 << 12)
+#define GINTSTS_USBSusp (1 << 11)
+#define GINTSTS_ErlySusp (1 << 10)
+#define GINTSTS_GOUTNakEff (1 << 7)
+#define GINTSTS_GINNakEff (1 << 6)
+#define GINTSTS_NPTxFEmp (1 << 5)
+#define GINTSTS_RxFLvl (1 << 4)
+#define GINTSTS_SOF (1 << 3)
+#define GINTSTS_OTGInt (1 << 2)
+#define GINTSTS_ModeMis (1 << 1)
+#define GINTSTS_CurMod_Host (1 << 0)
+
+#define GRXSTSR HSOTG_REG(0x01C)
+#define GRXSTSP HSOTG_REG(0x020)
+
+#define GRXSTS_FN_MASK (0x7f << 25)
+#define GRXSTS_FN_SHIFT (25)
+
+#define GRXSTS_PktSts_MASK (0xf << 17)
+#define GRXSTS_PktSts_SHIFT (17)
+#define GRXSTS_PktSts_GlobalOutNAK (0x1 << 17)
+#define GRXSTS_PktSts_OutRX (0x2 << 17)
+#define GRXSTS_PktSts_OutDone (0x3 << 17)
+#define GRXSTS_PktSts_SetupDone (0x4 << 17)
+#define GRXSTS_PktSts_SetupRX (0x6 << 17)
+
+#define GRXSTS_DPID_MASK (0x3 << 15)
+#define GRXSTS_DPID_SHIFT (15)
+#define GRXSTS_ByteCnt_MASK (0x7ff << 4)
+#define GRXSTS_ByteCnt_SHIFT (4)
+#define GRXSTS_EPNum_MASK (0xf << 0)
+#define GRXSTS_EPNum_SHIFT (0)
+
+#define GRXFSIZ HSOTG_REG(0x024)
+
+#define GNPTXFSIZ HSOTG_REG(0x028)
+
+#define GNPTXFSIZ_NPTxFDep_MASK (0xffff << 16)
+#define GNPTXFSIZ_NPTxFDep_SHIFT (16)
+#define GNPTXFSIZ_NPTxFDep_LIMIT (0xffff)
+#define GNPTXFSIZ_NPTxFDep(_x) ((_x) << 16)
+#define GNPTXFSIZ_NPTxFStAddr_MASK (0xffff << 0)
+#define GNPTXFSIZ_NPTxFStAddr_SHIFT (0)
+#define GNPTXFSIZ_NPTxFStAddr_LIMIT (0xffff)
+#define GNPTXFSIZ_NPTxFStAddr(_x) ((_x) << 0)
+
+#define GNPTXSTS HSOTG_REG(0x02C)
+
+#define GNPTXSTS_NPtxQTop_MASK (0x7f << 24)
+#define GNPTXSTS_NPtxQTop_SHIFT (24)
+
+#define GNPTXSTS_NPTxQSpcAvail_MASK (0xff << 16)
+#define GNPTXSTS_NPTxQSpcAvail_SHIFT (16)
+#define GNPTXSTS_NPTxQSpcAvail_GET(_v) (((_v) >> 16) & 0xff)
+
+#define GNPTXSTS_NPTxFSpcAvail_MASK (0xffff << 0)
+#define GNPTXSTS_NPTxFSpcAvail_SHIFT (0)
+#define GNPTXSTS_NPTxFSpcAvail_GET(_v) (((_v) >> 0) & 0xffff)
+
+
+#define HPTXFSIZ HSOTG_REG(0x100)
+
+#define DPTXFSIZn(_a) HSOTG_REG(0x104 + (((_a) - 1) * 4))
+
+#define DPTXFSIZn_DPTxFSize_MASK (0xffff << 16)
+#define DPTXFSIZn_DPTxFSize_SHIFT (16)
+#define DPTXFSIZn_DPTxFSize_GET(_v) (((_v) >> 16) & 0xffff)
+#define DPTXFSIZn_DPTxFSize_LIMIT (0xffff)
+#define DPTXFSIZn_DPTxFSize(_x) ((_x) << 16)
+
+#define DPTXFSIZn_DPTxFStAddr_MASK (0xffff << 0)
+#define DPTXFSIZn_DPTxFStAddr_SHIFT (0)
+
+/* Device mode registers */
+#define DCFG HSOTG_REG(0x800)
+
+#define DCFG_EPMisCnt_MASK (0x1f << 18)
+#define DCFG_EPMisCnt_SHIFT (18)
+#define DCFG_EPMisCnt_LIMIT (0x1f)
+#define DCFG_EPMisCnt(_x) ((_x) << 18)
+
+#define DCFG_PerFrInt_MASK (0x3 << 11)
+#define DCFG_PerFrInt_SHIFT (11)
+#define DCFG_PerFrInt_LIMIT (0x3)
+#define DCFG_PerFrInt(_x) ((_x) << 11)
+
+#define DCFG_DevAddr_MASK (0x7f << 4)
+#define DCFG_DevAddr_SHIFT (4)
+#define DCFG_DevAddr_LIMIT (0x7f)
+#define DCFG_DevAddr(_x) ((_x) << 4)
+
+#define DCFG_NZStsOUTHShk (1 << 2)
+
+#define DCFG_DevSpd_MASK (0x3 << 0)
+#define DCFG_DevSpd_SHIFT (0)
+#define DCFG_DevSpd_HS (0x0 << 0)
+#define DCFG_DevSpd_FS (0x1 << 0)
+#define DCFG_DevSpd_LS (0x2 << 0)
+#define DCFG_DevSpd_FS48 (0x3 << 0)
+
+#define DCTL HSOTG_REG(0x804)
+
+#define DCTL_PWROnPrgDone (1 << 11)
+#define DCTL_CGOUTNak (1 << 10)
+#define DCTL_SGOUTNak (1 << 9)
+#define DCTL_CGNPInNAK (1 << 8)
+#define DCTL_SGNPInNAK (1 << 7)
+#define DCTL_TstCtl_MASK (0x7 << 4)
+#define DCTL_TstCtl_SHIFT (4)
+#define DCTL_GOUTNakSts (1 << 3)
+#define DCTL_GNPINNakSts (1 << 2)
+#define DCTL_SftDiscon (1 << 1)
+#define DCTL_RmtWkUpSig (1 << 0)
+
+#define DSTS HSOTG_REG(0x808)
+
+#define DSTS_SOFFN_MASK (0x3fff << 8)
+#define DSTS_SOFFN_SHIFT (8)
+#define DSTS_SOFFN_LIMIT (0x3fff)
+#define DSTS_SOFFN(_x) ((_x) << 8)
+#define DSTS_ErraticErr (1 << 3)
+#define DSTS_EnumSpd_MASK (0x3 << 1)
+#define DSTS_EnumSpd_SHIFT (1)
+#define DSTS_EnumSpd_HS (0x0 << 1)
+#define DSTS_EnumSpd_FS (0x1 << 1)
+#define DSTS_EnumSpd_LS (0x2 << 1)
+#define DSTS_EnumSpd_FS48 (0x3 << 1)
+
+#define DSTS_SuspSts (1 << 0)
+
+#define DIEPMSK HSOTG_REG(0x810)
+
+#define DIEPMSK_TxFIFOEmpty (1 << 7)
+#define DIEPMSK_INEPNakEffMsk (1 << 6)
+#define DIEPMSK_INTknEPMisMsk (1 << 5)
+#define DIEPMSK_INTknTXFEmpMsk (1 << 4)
+#define DIEPMSK_TimeOUTMsk (1 << 3)
+#define DIEPMSK_AHBErrMsk (1 << 2)
+#define DIEPMSK_EPDisbldMsk (1 << 1)
+#define DIEPMSK_XferComplMsk (1 << 0)
+
+#define DOEPMSK HSOTG_REG(0x814)
+
+#define DOEPMSK_Back2BackSetup (1 << 6)
+#define DOEPMSK_OUTTknEPdisMsk (1 << 4)
+#define DOEPMSK_SetupMsk (1 << 3)
+#define DOEPMSK_AHBErrMsk (1 << 2)
+#define DOEPMSK_EPDisbldMsk (1 << 1)
+#define DOEPMSK_XferComplMsk (1 << 0)
+
+#define DAINT HSOTG_REG(0x818)
+#define DAINTMSK HSOTG_REG(0x81C)
+
+#define DAINT_OutEP_SHIFT (16)
+#define DAINT_OutEP(x) (1 << ((x) + 16))
+#define DAINT_InEP(x) (1 << (x))
+
+#define DTKNQR1 HSOTG_REG(0x820)
+#define DTKNQR2 HSOTG_REG(0x824)
+#define DTKNQR3 HSOTG_REG(0x830)
+#define DTKNQR4 HSOTG_REG(0x834)
+
+#define DVBUSDIS HSOTG_REG(0x828)
+#define DVBUSPULSE HSOTG_REG(0x82C)
+
+#define DIEPCTL0 HSOTG_REG(0x900)
+#define DOEPCTL0 HSOTG_REG(0xB00)
+#define DIEPCTL(_a) HSOTG_REG(0x900 + ((_a) * 0x20))
+#define DOEPCTL(_a) HSOTG_REG(0xB00 + ((_a) * 0x20))
+
+/* EP0 specialness:
+ * bits[29..28] - reserved (no SetD0PID, SetD1PID)
+ * bits[25..22] - should always be zero, this isn't a periodic endpoint
+ * bits[10..0] - MPS setting differenct for EP0
+ */
+#define D0EPCTL_MPS_MASK (0x3 << 0)
+#define D0EPCTL_MPS_SHIFT (0)
+#define D0EPCTL_MPS_64 (0x0 << 0)
+#define D0EPCTL_MPS_32 (0x1 << 0)
+#define D0EPCTL_MPS_16 (0x2 << 0)
+#define D0EPCTL_MPS_8 (0x3 << 0)
+
+#define DxEPCTL_EPEna (1 << 31)
+#define DxEPCTL_EPDis (1 << 30)
+#define DxEPCTL_SetD1PID (1 << 29)
+#define DxEPCTL_SetOddFr (1 << 29)
+#define DxEPCTL_SetD0PID (1 << 28)
+#define DxEPCTL_SetEvenFr (1 << 28)
+#define DxEPCTL_SNAK (1 << 27)
+#define DxEPCTL_CNAK (1 << 26)
+#define DxEPCTL_TxFNum_MASK (0xf << 22)
+#define DxEPCTL_TxFNum_SHIFT (22)
+#define DxEPCTL_TxFNum_LIMIT (0xf)
+#define DxEPCTL_TxFNum(_x) ((_x) << 22)
+
+#define DxEPCTL_Stall (1 << 21)
+#define DxEPCTL_Snp (1 << 20)
+#define DxEPCTL_EPType_MASK (0x3 << 18)
+#define DxEPCTL_EPType_SHIFT (18)
+#define DxEPCTL_EPType_Control (0x0 << 18)
+#define DxEPCTL_EPType_Iso (0x1 << 18)
+#define DxEPCTL_EPType_Bulk (0x2 << 18)
+#define DxEPCTL_EPType_Intterupt (0x3 << 18)
+
+#define DxEPCTL_NAKsts (1 << 17)
+#define DxEPCTL_DPID (1 << 16)
+#define DxEPCTL_EOFrNum (1 << 16)
+#define DxEPCTL_USBActEp (1 << 15)
+#define DxEPCTL_NextEp_MASK (0xf << 11)
+#define DxEPCTL_NextEp_SHIFT (11)
+#define DxEPCTL_NextEp_LIMIT (0xf)
+#define DxEPCTL_NextEp(_x) ((_x) << 11)
+
+#define DxEPCTL_MPS_MASK (0x7ff << 0)
+#define DxEPCTL_MPS_SHIFT (0)
+#define DxEPCTL_MPS_LIMIT (0x7ff)
+#define DxEPCTL_MPS(_x) ((_x) << 0)
+
+#define DIEPINT(_a) HSOTG_REG(0x908 + ((_a) * 0x20))
+#define DOEPINT(_a) HSOTG_REG(0xB08 + ((_a) * 0x20))
+
+#define DxEPINT_INEPNakEff (1 << 6)
+#define DxEPINT_Back2BackSetup (1 << 6)
+#define DxEPINT_INTknEPMis (1 << 5)
+#define DxEPINT_INTknTXFEmp (1 << 4)
+#define DxEPINT_OUTTknEPdis (1 << 4)
+#define DxEPINT_Timeout (1 << 3)
+#define DxEPINT_Setup (1 << 3)
+#define DxEPINT_AHBErr (1 << 2)
+#define DxEPINT_EPDisbld (1 << 1)
+#define DxEPINT_XferCompl (1 << 0)
+
+#define DIEPTSIZ0 HSOTG_REG(0x910)
+
+#define DIEPTSIZ0_PktCnt_MASK (0x3 << 19)
+#define DIEPTSIZ0_PktCnt_SHIFT (19)
+#define DIEPTSIZ0_PktCnt_LIMIT (0x3)
+#define DIEPTSIZ0_PktCnt(_x) ((_x) << 19)
+
+#define DIEPTSIZ0_XferSize_MASK (0x7f << 0)
+#define DIEPTSIZ0_XferSize_SHIFT (0)
+#define DIEPTSIZ0_XferSize_LIMIT (0x7f)
+#define DIEPTSIZ0_XferSize(_x) ((_x) << 0)
+
+#define DOEPTSIZ0 HSOTG_REG(0xB10)
+#define DOEPTSIZ0_SUPCnt_MASK (0x3 << 29)
+#define DOEPTSIZ0_SUPCnt_SHIFT (29)
+#define DOEPTSIZ0_SUPCnt_LIMIT (0x3)
+#define DOEPTSIZ0_SUPCnt(_x) ((_x) << 29)
+
+#define DOEPTSIZ0_PktCnt (1 << 19)
+#define DOEPTSIZ0_XferSize_MASK (0x7f << 0)
+#define DOEPTSIZ0_XferSize_SHIFT (0)
+
+#define DIEPTSIZ(_a) HSOTG_REG(0x910 + ((_a) * 0x20))
+#define DOEPTSIZ(_a) HSOTG_REG(0xB10 + ((_a) * 0x20))
+
+#define DxEPTSIZ_MC_MASK (0x3 << 29)
+#define DxEPTSIZ_MC_SHIFT (29)
+#define DxEPTSIZ_MC_LIMIT (0x3)
+#define DxEPTSIZ_MC(_x) ((_x) << 29)
+
+#define DxEPTSIZ_PktCnt_MASK (0x3ff << 19)
+#define DxEPTSIZ_PktCnt_SHIFT (19)
+#define DxEPTSIZ_PktCnt_GET(_v) (((_v) >> 19) & 0x3ff)
+#define DxEPTSIZ_PktCnt_LIMIT (0x3ff)
+#define DxEPTSIZ_PktCnt(_x) ((_x) << 19)
+
+#define DxEPTSIZ_XferSize_MASK (0x7ffff << 0)
+#define DxEPTSIZ_XferSize_SHIFT (0)
+#define DxEPTSIZ_XferSize_GET(_v) (((_v) >> 0) & 0x7ffff)
+#define DxEPTSIZ_XferSize_LIMIT (0x7ffff)
+#define DxEPTSIZ_XferSize(_x) ((_x) << 0)
+
+#define DIEPDMA(_a) HSOTG_REG(0x914 + ((_a) * 0x20))
+#define DOEPDMA(_a) HSOTG_REG(0xB14 + ((_a) * 0x20))
+#define DTXFSTS(_a) HSOTG_REG(0x918 + ((_a) * 0x20))
+
+#define EPFIFO(_a) HSOTG_REG(0x1000 + ((_a) * 0x1000))
+
+#endif /* __REGS_USB_HSOTG_H */
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index cef9b82ff911..36c6836eeb0f 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -110,7 +110,6 @@ struct s3c_hsudc_ep {
struct usb_ep ep;
char name[20];
struct s3c_hsudc *dev;
- const struct usb_endpoint_descriptor *desc;
struct list_head queue;
u8 stopped;
u8 wedge;
@@ -761,7 +760,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep,
u32 ecr = 0;
hsep = our_ep(_ep);
- if (!_ep || !desc || hsep->desc || _ep->name == ep0name
+ if (!_ep || !desc || hsep->ep.desc || _ep->name == ep0name
|| desc->bDescriptorType != USB_DT_ENDPOINT
|| hsep->bEndpointAddress != desc->bEndpointAddress
|| ep_maxpacket(hsep) < usb_endpoint_maxp(desc))
@@ -783,7 +782,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep,
writel(ecr, hsudc->regs + S3C_ECR);
hsep->stopped = hsep->wedge = 0;
- hsep->desc = desc;
+ hsep->ep.desc = desc;
hsep->ep.maxpacket = usb_endpoint_maxp(desc);
s3c_hsudc_set_halt(_ep, 0);
@@ -806,7 +805,7 @@ static int s3c_hsudc_ep_disable(struct usb_ep *_ep)
struct s3c_hsudc *hsudc = hsep->dev;
unsigned long flags;
- if (!_ep || !hsep->desc)
+ if (!_ep || !hsep->ep.desc)
return -EINVAL;
spin_lock_irqsave(&hsudc->lock, flags);
@@ -816,7 +815,6 @@ static int s3c_hsudc_ep_disable(struct usb_ep *_ep)
s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN);
- hsep->desc = 0;
hsep->ep.desc = NULL;
hsep->stopped = 1;
@@ -1006,7 +1004,6 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc,
hsep->ep.maxpacket = epnum ? 512 : 64;
hsep->ep.ops = &s3c_hsudc_ep_ops;
hsep->fifo = hsudc->regs + S3C_BR(epnum);
- hsep->desc = 0;
hsep->ep.desc = NULL;
hsep->stopped = 0;
hsep->wedge = 0;
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 195524cde6c3..3de71d37d75e 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1062,7 +1062,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
ep = to_s3c2410_ep(_ep);
- if (!_ep || !desc || ep->desc
+ if (!_ep || !desc || ep->ep.desc
|| _ep->name == ep0name
|| desc->bDescriptorType != USB_DT_ENDPOINT)
return -EINVAL;
@@ -1075,7 +1075,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
local_irq_save (flags);
_ep->maxpacket = max & 0x7ff;
- ep->desc = desc;
+ ep->ep.desc = desc;
ep->halted = 0;
ep->bEndpointAddress = desc->bEndpointAddress;
@@ -1136,7 +1136,7 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep)
unsigned long flags;
u32 int_en_reg;
- if (!_ep || !ep->desc) {
+ if (!_ep || !ep->ep.desc) {
dprintk(DEBUG_NORMAL, "%s not enabled\n",
_ep ? ep->ep.name : NULL);
return -EINVAL;
@@ -1146,7 +1146,6 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep)
dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name);
- ep->desc = NULL;
ep->ep.desc = NULL;
ep->halted = 1;
@@ -1195,7 +1194,7 @@ s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req)
dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
- if (!ep || !_req || (!ep->desc && _ep->name != ep0name))
+ if (!ep || !_req || (!ep->ep.desc && _ep->name != ep0name))
return;
WARN_ON (!list_empty (&req->queue));
@@ -1215,7 +1214,7 @@ static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req,
int fifo_count = 0;
unsigned long flags;
- if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+ if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) {
dprintk(DEBUG_NORMAL, "%s: invalid args\n", __func__);
return -EINVAL;
}
@@ -1363,7 +1362,7 @@ static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value)
unsigned long flags;
u32 idx;
- if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+ if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) {
dprintk(DEBUG_NORMAL, "%s: inval 2\n", __func__);
return -EINVAL;
}
@@ -1629,7 +1628,6 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
ep->dev = dev;
- ep->desc = NULL;
ep->ep.desc = NULL;
ep->halted = 0;
INIT_LIST_HEAD (&ep->queue);
diff --git a/drivers/usb/gadget/s3c2410_udc.h b/drivers/usb/gadget/s3c2410_udc.h
index 1653bae08b80..3e80fd5c820f 100644
--- a/drivers/usb/gadget/s3c2410_udc.h
+++ b/drivers/usb/gadget/s3c2410_udc.h
@@ -19,7 +19,6 @@ struct s3c2410_ep {
unsigned long last_io; /* jiffies timestamp */
struct usb_gadget *gadget;
struct s3c2410_udc *dev;
- const struct usb_endpoint_descriptor *desc;
struct usb_ep ep;
u8 num;
diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c
new file mode 100644
index 000000000000..c46439c8dd74
--- /dev/null
+++ b/drivers/usb/gadget/tcm_usb_gadget.c
@@ -0,0 +1,2480 @@
+/* Target based USB-Gadget
+ *
+ * UAS protocol handling, target callbacks, configfs handling,
+ * BBB (USB Mass Storage Class Bulk-Only (BBB) and Transport protocol handling.
+ *
+ * Author: Sebastian Andrzej Siewior <bigeasy at linutronix dot de>
+ * License: GPLv2 as published by FSF.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/configfs.h>
+#include <linux/ctype.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/composite.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/storage.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_tcq.h>
+#include <target/target_core_base.h>
+#include <target/target_core_fabric.h>
+#include <target/target_core_fabric_configfs.h>
+#include <target/target_core_configfs.h>
+#include <target/configfs_macros.h>
+#include <asm/unaligned.h>
+
+#include "usbstring.c"
+#include "epautoconf.c"
+#include "config.c"
+#include "composite.c"
+
+#include "tcm_usb_gadget.h"
+
+static struct target_fabric_configfs *usbg_fabric_configfs;
+
+static inline struct f_uas *to_f_uas(struct usb_function *f)
+{
+ return container_of(f, struct f_uas, function);
+}
+
+static void usbg_cmd_release(struct kref *);
+
+static inline void usbg_cleanup_cmd(struct usbg_cmd *cmd)
+{
+ kref_put(&cmd->ref, usbg_cmd_release);
+}
+
+/* Start bot.c code */
+
+static int bot_enqueue_cmd_cbw(struct f_uas *fu)
+{
+ int ret;
+
+ if (fu->flags & USBG_BOT_CMD_PEND)
+ return 0;
+
+ ret = usb_ep_queue(fu->ep_out, fu->cmd.req, GFP_ATOMIC);
+ if (!ret)
+ fu->flags |= USBG_BOT_CMD_PEND;
+ return ret;
+}
+
+static void bot_status_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct usbg_cmd *cmd = req->context;
+ struct f_uas *fu = cmd->fu;
+
+ usbg_cleanup_cmd(cmd);
+ if (req->status < 0) {
+ pr_err("ERR %s(%d)\n", __func__, __LINE__);
+ return;
+ }
+
+ /* CSW completed, wait for next CBW */
+ bot_enqueue_cmd_cbw(fu);
+}
+
+static void bot_enqueue_sense_code(struct f_uas *fu, struct usbg_cmd *cmd)
+{
+ struct bulk_cs_wrap *csw = &fu->bot_status.csw;
+ int ret;
+ u8 *sense;
+ unsigned int csw_stat;
+
+ csw_stat = cmd->csw_code;
+
+ /*
+ * We can't send SENSE as a response. So we take ASC & ASCQ from our
+ * sense buffer and queue it and hope the host sends a REQUEST_SENSE
+ * command where it learns why we failed.
+ */
+ sense = cmd->sense_iu.sense;
+
+ csw->Tag = cmd->bot_tag;
+ csw->Status = csw_stat;
+ fu->bot_status.req->context = cmd;
+ ret = usb_ep_queue(fu->ep_in, fu->bot_status.req, GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d) ERR: %d\n", __func__, __LINE__, ret);
+}
+
+static void bot_err_compl(struct usb_ep *ep, struct usb_request *req)
+{
+ struct usbg_cmd *cmd = req->context;
+ struct f_uas *fu = cmd->fu;
+
+ if (req->status < 0)
+ pr_err("ERR %s(%d)\n", __func__, __LINE__);
+
+ if (cmd->data_len) {
+ if (cmd->data_len > ep->maxpacket) {
+ req->length = ep->maxpacket;
+ cmd->data_len -= ep->maxpacket;
+ } else {
+ req->length = cmd->data_len;
+ cmd->data_len = 0;
+ }
+
+ usb_ep_queue(ep, req, GFP_ATOMIC);
+ return ;
+ }
+ bot_enqueue_sense_code(fu, cmd);
+}
+
+static void bot_send_bad_status(struct usbg_cmd *cmd)
+{
+ struct f_uas *fu = cmd->fu;
+ struct bulk_cs_wrap *csw = &fu->bot_status.csw;
+ struct usb_request *req;
+ struct usb_ep *ep;
+
+ csw->Residue = cpu_to_le32(cmd->data_len);
+
+ if (cmd->data_len) {
+ if (cmd->is_read) {
+ ep = fu->ep_in;
+ req = fu->bot_req_in;
+ } else {
+ ep = fu->ep_out;
+ req = fu->bot_req_out;
+ }
+
+ if (cmd->data_len > fu->ep_in->maxpacket) {
+ req->length = ep->maxpacket;
+ cmd->data_len -= ep->maxpacket;
+ } else {
+ req->length = cmd->data_len;
+ cmd->data_len = 0;
+ }
+ req->complete = bot_err_compl;
+ req->context = cmd;
+ req->buf = fu->cmd.buf;
+ usb_ep_queue(ep, req, GFP_KERNEL);
+ } else {
+ bot_enqueue_sense_code(fu, cmd);
+ }
+}
+
+static int bot_send_status(struct usbg_cmd *cmd, bool moved_data)
+{
+ struct f_uas *fu = cmd->fu;
+ struct bulk_cs_wrap *csw = &fu->bot_status.csw;
+ int ret;
+
+ if (cmd->se_cmd.scsi_status == SAM_STAT_GOOD) {
+ if (!moved_data && cmd->data_len) {
+ /*
+ * the host wants to move data, we don't. Fill / empty
+ * the pipe and then send the csw with reside set.
+ */
+ cmd->csw_code = US_BULK_STAT_OK;
+ bot_send_bad_status(cmd);
+ return 0;
+ }
+
+ csw->Tag = cmd->bot_tag;
+ csw->Residue = cpu_to_le32(0);
+ csw->Status = US_BULK_STAT_OK;
+ fu->bot_status.req->context = cmd;
+
+ ret = usb_ep_queue(fu->ep_in, fu->bot_status.req, GFP_KERNEL);
+ if (ret)
+ pr_err("%s(%d) ERR: %d\n", __func__, __LINE__, ret);
+ } else {
+ cmd->csw_code = US_BULK_STAT_FAIL;
+ bot_send_bad_status(cmd);
+ }
+ return 0;
+}
+
+/*
+ * Called after command (no data transfer) or after the write (to device)
+ * operation is completed
+ */
+static int bot_send_status_response(struct usbg_cmd *cmd)
+{
+ bool moved_data = false;
+
+ if (!cmd->is_read)
+ moved_data = true;
+ return bot_send_status(cmd, moved_data);
+}
+
+/* Read request completed, now we have to send the CSW */
+static void bot_read_compl(struct usb_ep *ep, struct usb_request *req)
+{
+ struct usbg_cmd *cmd = req->context;
+
+ if (req->status < 0)
+ pr_err("ERR %s(%d)\n", __func__, __LINE__);
+
+ bot_send_status(cmd, true);
+}
+
+static int bot_send_read_response(struct usbg_cmd *cmd)
+{
+ struct f_uas *fu = cmd->fu;
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct usb_gadget *gadget = fuas_to_gadget(fu);
+ int ret;
+
+ if (!cmd->data_len) {
+ cmd->csw_code = US_BULK_STAT_PHASE;
+ bot_send_bad_status(cmd);
+ return 0;
+ }
+
+ if (!gadget->sg_supported) {
+ cmd->data_buf = kmalloc(se_cmd->data_length, GFP_ATOMIC);
+ if (!cmd->data_buf)
+ return -ENOMEM;
+
+ sg_copy_to_buffer(se_cmd->t_data_sg,
+ se_cmd->t_data_nents,
+ cmd->data_buf,
+ se_cmd->data_length);
+
+ fu->bot_req_in->buf = cmd->data_buf;
+ } else {
+ fu->bot_req_in->buf = NULL;
+ fu->bot_req_in->num_sgs = se_cmd->t_data_nents;
+ fu->bot_req_in->sg = se_cmd->t_data_sg;
+ }
+
+ fu->bot_req_in->complete = bot_read_compl;
+ fu->bot_req_in->length = se_cmd->data_length;
+ fu->bot_req_in->context = cmd;
+ ret = usb_ep_queue(fu->ep_in, fu->bot_req_in, GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d)\n", __func__, __LINE__);
+ return 0;
+}
+
+static void usbg_data_write_cmpl(struct usb_ep *, struct usb_request *);
+static int usbg_prepare_w_request(struct usbg_cmd *, struct usb_request *);
+
+static int bot_send_write_request(struct usbg_cmd *cmd)
+{
+ struct f_uas *fu = cmd->fu;
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct usb_gadget *gadget = fuas_to_gadget(fu);
+ int ret;
+
+ init_completion(&cmd->write_complete);
+ cmd->fu = fu;
+
+ if (!cmd->data_len) {
+ cmd->csw_code = US_BULK_STAT_PHASE;
+ return -EINVAL;
+ }
+
+ if (!gadget->sg_supported) {
+ cmd->data_buf = kmalloc(se_cmd->data_length, GFP_KERNEL);
+ if (!cmd->data_buf)
+ return -ENOMEM;
+
+ fu->bot_req_out->buf = cmd->data_buf;
+ } else {
+ fu->bot_req_out->buf = NULL;
+ fu->bot_req_out->num_sgs = se_cmd->t_data_nents;
+ fu->bot_req_out->sg = se_cmd->t_data_sg;
+ }
+
+ fu->bot_req_out->complete = usbg_data_write_cmpl;
+ fu->bot_req_out->length = se_cmd->data_length;
+ fu->bot_req_out->context = cmd;
+
+ ret = usbg_prepare_w_request(cmd, fu->bot_req_out);
+ if (ret)
+ goto cleanup;
+ ret = usb_ep_queue(fu->ep_out, fu->bot_req_out, GFP_KERNEL);
+ if (ret)
+ pr_err("%s(%d)\n", __func__, __LINE__);
+
+ wait_for_completion(&cmd->write_complete);
+ transport_generic_process_write(se_cmd);
+cleanup:
+ return ret;
+}
+
+static int bot_submit_command(struct f_uas *, void *, unsigned int);
+
+static void bot_cmd_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_uas *fu = req->context;
+ int ret;
+
+ fu->flags &= ~USBG_BOT_CMD_PEND;
+
+ if (req->status < 0)
+ return;
+
+ ret = bot_submit_command(fu, req->buf, req->actual);
+ if (ret)
+ pr_err("%s(%d): %d\n", __func__, __LINE__, ret);
+}
+
+static int bot_prepare_reqs(struct f_uas *fu)
+{
+ int ret;
+
+ fu->bot_req_in = usb_ep_alloc_request(fu->ep_in, GFP_KERNEL);
+ if (!fu->bot_req_in)
+ goto err;
+
+ fu->bot_req_out = usb_ep_alloc_request(fu->ep_out, GFP_KERNEL);
+ if (!fu->bot_req_out)
+ goto err_out;
+
+ fu->cmd.req = usb_ep_alloc_request(fu->ep_out, GFP_KERNEL);
+ if (!fu->cmd.req)
+ goto err_cmd;
+
+ fu->bot_status.req = usb_ep_alloc_request(fu->ep_in, GFP_KERNEL);
+ if (!fu->bot_status.req)
+ goto err_sts;
+
+ fu->bot_status.req->buf = &fu->bot_status.csw;
+ fu->bot_status.req->length = US_BULK_CS_WRAP_LEN;
+ fu->bot_status.req->complete = bot_status_complete;
+ fu->bot_status.csw.Signature = cpu_to_le32(US_BULK_CS_SIGN);
+
+ fu->cmd.buf = kmalloc(fu->ep_out->maxpacket, GFP_KERNEL);
+ if (!fu->cmd.buf)
+ goto err_buf;
+
+ fu->cmd.req->complete = bot_cmd_complete;
+ fu->cmd.req->buf = fu->cmd.buf;
+ fu->cmd.req->length = fu->ep_out->maxpacket;
+ fu->cmd.req->context = fu;
+
+ ret = bot_enqueue_cmd_cbw(fu);
+ if (ret)
+ goto err_queue;
+ return 0;
+err_queue:
+ kfree(fu->cmd.buf);
+ fu->cmd.buf = NULL;
+err_buf:
+ usb_ep_free_request(fu->ep_in, fu->bot_status.req);
+err_sts:
+ usb_ep_free_request(fu->ep_out, fu->cmd.req);
+ fu->cmd.req = NULL;
+err_cmd:
+ usb_ep_free_request(fu->ep_out, fu->bot_req_out);
+ fu->bot_req_out = NULL;
+err_out:
+ usb_ep_free_request(fu->ep_in, fu->bot_req_in);
+ fu->bot_req_in = NULL;
+err:
+ pr_err("BOT: endpoint setup failed\n");
+ return -ENOMEM;
+}
+
+void bot_cleanup_old_alt(struct f_uas *fu)
+{
+ if (!(fu->flags & USBG_ENABLED))
+ return;
+
+ usb_ep_disable(fu->ep_in);
+ usb_ep_disable(fu->ep_out);
+
+ if (!fu->bot_req_in)
+ return;
+
+ usb_ep_free_request(fu->ep_in, fu->bot_req_in);
+ usb_ep_free_request(fu->ep_out, fu->bot_req_out);
+ usb_ep_free_request(fu->ep_out, fu->cmd.req);
+ usb_ep_free_request(fu->ep_out, fu->bot_status.req);
+
+ kfree(fu->cmd.buf);
+
+ fu->bot_req_in = NULL;
+ fu->bot_req_out = NULL;
+ fu->cmd.req = NULL;
+ fu->bot_status.req = NULL;
+ fu->cmd.buf = NULL;
+}
+
+static void bot_set_alt(struct f_uas *fu)
+{
+ struct usb_function *f = &fu->function;
+ struct usb_gadget *gadget = f->config->cdev->gadget;
+ int ret;
+
+ fu->flags = USBG_IS_BOT;
+
+ config_ep_by_speed(gadget, f, fu->ep_in);
+ ret = usb_ep_enable(fu->ep_in);
+ if (ret)
+ goto err_b_in;
+
+ config_ep_by_speed(gadget, f, fu->ep_out);
+ ret = usb_ep_enable(fu->ep_out);
+ if (ret)
+ goto err_b_out;
+
+ ret = bot_prepare_reqs(fu);
+ if (ret)
+ goto err_wq;
+ fu->flags |= USBG_ENABLED;
+ pr_info("Using the BOT protocol\n");
+ return;
+err_wq:
+ usb_ep_disable(fu->ep_out);
+err_b_out:
+ usb_ep_disable(fu->ep_in);
+err_b_in:
+ fu->flags = USBG_IS_BOT;
+}
+
+static int usbg_bot_setup(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct f_uas *fu = to_f_uas(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+ int luns;
+ u8 *ret_lun;
+
+ switch (ctrl->bRequest) {
+ case US_BULK_GET_MAX_LUN:
+ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_CLASS |
+ USB_RECIP_INTERFACE))
+ return -ENOTSUPP;
+
+ if (w_length < 1)
+ return -EINVAL;
+ if (w_value != 0)
+ return -EINVAL;
+ luns = atomic_read(&fu->tpg->tpg_port_count);
+ if (!luns) {
+ pr_err("No LUNs configured?\n");
+ return -EINVAL;
+ }
+ /*
+ * If 4 LUNs are present we return 3 i.e. LUN 0..3 can be
+ * accessed. The upper limit is 0xf
+ */
+ luns--;
+ if (luns > 0xf) {
+ pr_info_once("Limiting the number of luns to 16\n");
+ luns = 0xf;
+ }
+ ret_lun = cdev->req->buf;
+ *ret_lun = luns;
+ cdev->req->length = 1;
+ return usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC);
+ break;
+
+ case US_BULK_RESET_REQUEST:
+ /* XXX maybe we should remove previous requests for IN + OUT */
+ bot_enqueue_cmd_cbw(fu);
+ return 0;
+ break;
+ };
+ return -ENOTSUPP;
+}
+
+/* Start uas.c code */
+
+static void uasp_cleanup_one_stream(struct f_uas *fu, struct uas_stream *stream)
+{
+ /* We have either all three allocated or none */
+ if (!stream->req_in)
+ return;
+
+ usb_ep_free_request(fu->ep_in, stream->req_in);
+ usb_ep_free_request(fu->ep_out, stream->req_out);
+ usb_ep_free_request(fu->ep_status, stream->req_status);
+
+ stream->req_in = NULL;
+ stream->req_out = NULL;
+ stream->req_status = NULL;
+}
+
+static void uasp_free_cmdreq(struct f_uas *fu)
+{
+ usb_ep_free_request(fu->ep_cmd, fu->cmd.req);
+ kfree(fu->cmd.buf);
+ fu->cmd.req = NULL;
+ fu->cmd.buf = NULL;
+}
+
+static void uasp_cleanup_old_alt(struct f_uas *fu)
+{
+ int i;
+
+ if (!(fu->flags & USBG_ENABLED))
+ return;
+
+ usb_ep_disable(fu->ep_in);
+ usb_ep_disable(fu->ep_out);
+ usb_ep_disable(fu->ep_status);
+ usb_ep_disable(fu->ep_cmd);
+
+ for (i = 0; i < UASP_SS_EP_COMP_NUM_STREAMS; i++)
+ uasp_cleanup_one_stream(fu, &fu->stream[i]);
+ uasp_free_cmdreq(fu);
+}
+
+static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req);
+
+static int uasp_prepare_r_request(struct usbg_cmd *cmd)
+{
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct f_uas *fu = cmd->fu;
+ struct usb_gadget *gadget = fuas_to_gadget(fu);
+ struct uas_stream *stream = cmd->stream;
+
+ if (!gadget->sg_supported) {
+ cmd->data_buf = kmalloc(se_cmd->data_length, GFP_ATOMIC);
+ if (!cmd->data_buf)
+ return -ENOMEM;
+
+ sg_copy_to_buffer(se_cmd->t_data_sg,
+ se_cmd->t_data_nents,
+ cmd->data_buf,
+ se_cmd->data_length);
+
+ stream->req_in->buf = cmd->data_buf;
+ } else {
+ stream->req_in->buf = NULL;
+ stream->req_in->num_sgs = se_cmd->t_data_nents;
+ stream->req_in->sg = se_cmd->t_data_sg;
+ }
+
+ stream->req_in->complete = uasp_status_data_cmpl;
+ stream->req_in->length = se_cmd->data_length;
+ stream->req_in->context = cmd;
+
+ cmd->state = UASP_SEND_STATUS;
+ return 0;
+}
+
+static void uasp_prepare_status(struct usbg_cmd *cmd)
+{
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct sense_iu *iu = &cmd->sense_iu;
+ struct uas_stream *stream = cmd->stream;
+
+ cmd->state = UASP_QUEUE_COMMAND;
+ iu->iu_id = IU_ID_STATUS;
+ iu->tag = cpu_to_be16(cmd->tag);
+
+ /*
+ * iu->status_qual = cpu_to_be16(STATUS QUALIFIER SAM-4. Where R U?);
+ */
+ iu->len = cpu_to_be16(se_cmd->scsi_sense_length);
+ iu->status = se_cmd->scsi_status;
+ stream->req_status->context = cmd;
+ stream->req_status->length = se_cmd->scsi_sense_length + 16;
+ stream->req_status->buf = iu;
+ stream->req_status->complete = uasp_status_data_cmpl;
+}
+
+static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req)
+{
+ struct usbg_cmd *cmd = req->context;
+ struct uas_stream *stream = cmd->stream;
+ struct f_uas *fu = cmd->fu;
+ int ret;
+
+ if (req->status < 0)
+ goto cleanup;
+
+ switch (cmd->state) {
+ case UASP_SEND_DATA:
+ ret = uasp_prepare_r_request(cmd);
+ if (ret)
+ goto cleanup;
+ ret = usb_ep_queue(fu->ep_in, stream->req_in, GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
+ break;
+
+ case UASP_RECEIVE_DATA:
+ ret = usbg_prepare_w_request(cmd, stream->req_out);
+ if (ret)
+ goto cleanup;
+ ret = usb_ep_queue(fu->ep_out, stream->req_out, GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
+ break;
+
+ case UASP_SEND_STATUS:
+ uasp_prepare_status(cmd);
+ ret = usb_ep_queue(fu->ep_status, stream->req_status,
+ GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
+ break;
+
+ case UASP_QUEUE_COMMAND:
+ usbg_cleanup_cmd(cmd);
+ usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
+ break;
+
+ default:
+ BUG();
+ };
+ return;
+
+cleanup:
+ usbg_cleanup_cmd(cmd);
+}
+
+static int uasp_send_status_response(struct usbg_cmd *cmd)
+{
+ struct f_uas *fu = cmd->fu;
+ struct uas_stream *stream = cmd->stream;
+ struct sense_iu *iu = &cmd->sense_iu;
+
+ iu->tag = cpu_to_be16(cmd->tag);
+ stream->req_status->complete = uasp_status_data_cmpl;
+ stream->req_status->context = cmd;
+ cmd->fu = fu;
+ uasp_prepare_status(cmd);
+ return usb_ep_queue(fu->ep_status, stream->req_status, GFP_ATOMIC);
+}
+
+static int uasp_send_read_response(struct usbg_cmd *cmd)
+{
+ struct f_uas *fu = cmd->fu;
+ struct uas_stream *stream = cmd->stream;
+ struct sense_iu *iu = &cmd->sense_iu;
+ int ret;
+
+ cmd->fu = fu;
+
+ iu->tag = cpu_to_be16(cmd->tag);
+ if (fu->flags & USBG_USE_STREAMS) {
+
+ ret = uasp_prepare_r_request(cmd);
+ if (ret)
+ goto out;
+ ret = usb_ep_queue(fu->ep_in, stream->req_in, GFP_ATOMIC);
+ if (ret) {
+ pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
+ kfree(cmd->data_buf);
+ cmd->data_buf = NULL;
+ }
+
+ } else {
+
+ iu->iu_id = IU_ID_READ_READY;
+ iu->tag = cpu_to_be16(cmd->tag);
+
+ stream->req_status->complete = uasp_status_data_cmpl;
+ stream->req_status->context = cmd;
+
+ cmd->state = UASP_SEND_DATA;
+ stream->req_status->buf = iu;
+ stream->req_status->length = sizeof(struct iu);
+
+ ret = usb_ep_queue(fu->ep_status, stream->req_status,
+ GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
+ }
+out:
+ return ret;
+}
+
+static int uasp_send_write_request(struct usbg_cmd *cmd)
+{
+ struct f_uas *fu = cmd->fu;
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct uas_stream *stream = cmd->stream;
+ struct sense_iu *iu = &cmd->sense_iu;
+ int ret;
+
+ init_completion(&cmd->write_complete);
+ cmd->fu = fu;
+
+ iu->tag = cpu_to_be16(cmd->tag);
+
+ if (fu->flags & USBG_USE_STREAMS) {
+
+ ret = usbg_prepare_w_request(cmd, stream->req_out);
+ if (ret)
+ goto cleanup;
+ ret = usb_ep_queue(fu->ep_out, stream->req_out, GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d)\n", __func__, __LINE__);
+
+ } else {
+
+ iu->iu_id = IU_ID_WRITE_READY;
+ iu->tag = cpu_to_be16(cmd->tag);
+
+ stream->req_status->complete = uasp_status_data_cmpl;
+ stream->req_status->context = cmd;
+
+ cmd->state = UASP_RECEIVE_DATA;
+ stream->req_status->buf = iu;
+ stream->req_status->length = sizeof(struct iu);
+
+ ret = usb_ep_queue(fu->ep_status, stream->req_status,
+ GFP_ATOMIC);
+ if (ret)
+ pr_err("%s(%d)\n", __func__, __LINE__);
+ }
+
+ wait_for_completion(&cmd->write_complete);
+ transport_generic_process_write(se_cmd);
+cleanup:
+ return ret;
+}
+
+static int usbg_submit_command(struct f_uas *, void *, unsigned int);
+
+static void uasp_cmd_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_uas *fu = req->context;
+ int ret;
+
+ if (req->status < 0)
+ return;
+
+ ret = usbg_submit_command(fu, req->buf, req->actual);
+ /*
+ * Once we tune for performance enqueue the command req here again so
+ * we can receive a second command while we processing this one. Pay
+ * attention to properly sync STAUS endpoint with DATA IN + OUT so you
+ * don't break HS.
+ */
+ if (!ret)
+ return;
+ usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
+}
+
+static int uasp_alloc_stream_res(struct f_uas *fu, struct uas_stream *stream)
+{
+ stream->req_in = usb_ep_alloc_request(fu->ep_in, GFP_KERNEL);
+ if (!stream->req_in)
+ goto out;
+
+ stream->req_out = usb_ep_alloc_request(fu->ep_out, GFP_KERNEL);
+ if (!stream->req_out)
+ goto err_out;
+
+ stream->req_status = usb_ep_alloc_request(fu->ep_status, GFP_KERNEL);
+ if (!stream->req_status)
+ goto err_sts;
+
+ return 0;
+err_sts:
+ usb_ep_free_request(fu->ep_status, stream->req_status);
+ stream->req_status = NULL;
+err_out:
+ usb_ep_free_request(fu->ep_out, stream->req_out);
+ stream->req_out = NULL;
+out:
+ return -ENOMEM;
+}
+
+static int uasp_alloc_cmd(struct f_uas *fu)
+{
+ fu->cmd.req = usb_ep_alloc_request(fu->ep_cmd, GFP_KERNEL);
+ if (!fu->cmd.req)
+ goto err;
+
+ fu->cmd.buf = kmalloc(fu->ep_cmd->maxpacket, GFP_KERNEL);
+ if (!fu->cmd.buf)
+ goto err_buf;
+
+ fu->cmd.req->complete = uasp_cmd_complete;
+ fu->cmd.req->buf = fu->cmd.buf;
+ fu->cmd.req->length = fu->ep_cmd->maxpacket;
+ fu->cmd.req->context = fu;
+ return 0;
+
+err_buf:
+ usb_ep_free_request(fu->ep_cmd, fu->cmd.req);
+err:
+ return -ENOMEM;
+}
+
+static void uasp_setup_stream_res(struct f_uas *fu, int max_streams)
+{
+ int i;
+
+ for (i = 0; i < max_streams; i++) {
+ struct uas_stream *s = &fu->stream[i];
+
+ s->req_in->stream_id = i + 1;
+ s->req_out->stream_id = i + 1;
+ s->req_status->stream_id = i + 1;
+ }
+}
+
+static int uasp_prepare_reqs(struct f_uas *fu)
+{
+ int ret;
+ int i;
+ int max_streams;
+
+ if (fu->flags & USBG_USE_STREAMS)
+ max_streams = UASP_SS_EP_COMP_NUM_STREAMS;
+ else
+ max_streams = 1;
+
+ for (i = 0; i < max_streams; i++) {
+ ret = uasp_alloc_stream_res(fu, &fu->stream[i]);
+ if (ret)
+ goto err_cleanup;
+ }
+
+ ret = uasp_alloc_cmd(fu);
+ if (ret)
+ goto err_free_stream;
+ uasp_setup_stream_res(fu, max_streams);
+
+ ret = usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
+ if (ret)
+ goto err_free_stream;
+
+ return 0;
+
+err_free_stream:
+ uasp_free_cmdreq(fu);
+
+err_cleanup:
+ if (i) {
+ do {
+ uasp_cleanup_one_stream(fu, &fu->stream[i - 1]);
+ i--;
+ } while (i);
+ }
+ pr_err("UASP: endpoint setup failed\n");
+ return ret;
+}
+
+static void uasp_set_alt(struct f_uas *fu)
+{
+ struct usb_function *f = &fu->function;
+ struct usb_gadget *gadget = f->config->cdev->gadget;
+ int ret;
+
+ fu->flags = USBG_IS_UAS;
+
+ if (gadget->speed == USB_SPEED_SUPER)
+ fu->flags |= USBG_USE_STREAMS;
+
+ config_ep_by_speed(gadget, f, fu->ep_in);
+ ret = usb_ep_enable(fu->ep_in);
+ if (ret)
+ goto err_b_in;
+
+ config_ep_by_speed(gadget, f, fu->ep_out);
+ ret = usb_ep_enable(fu->ep_out);
+ if (ret)
+ goto err_b_out;
+
+ config_ep_by_speed(gadget, f, fu->ep_cmd);
+ ret = usb_ep_enable(fu->ep_cmd);
+ if (ret)
+ goto err_cmd;
+ config_ep_by_speed(gadget, f, fu->ep_status);
+ ret = usb_ep_enable(fu->ep_status);
+ if (ret)
+ goto err_status;
+
+ ret = uasp_prepare_reqs(fu);
+ if (ret)
+ goto err_wq;
+ fu->flags |= USBG_ENABLED;
+
+ pr_info("Using the UAS protocol\n");
+ return;
+err_wq:
+ usb_ep_disable(fu->ep_status);
+err_status:
+ usb_ep_disable(fu->ep_cmd);
+err_cmd:
+ usb_ep_disable(fu->ep_out);
+err_b_out:
+ usb_ep_disable(fu->ep_in);
+err_b_in:
+ fu->flags = 0;
+}
+
+static int get_cmd_dir(const unsigned char *cdb)
+{
+ int ret;
+
+ switch (cdb[0]) {
+ case READ_6:
+ case READ_10:
+ case READ_12:
+ case READ_16:
+ case INQUIRY:
+ case MODE_SENSE:
+ case MODE_SENSE_10:
+ case SERVICE_ACTION_IN:
+ case MAINTENANCE_IN:
+ case PERSISTENT_RESERVE_IN:
+ case SECURITY_PROTOCOL_IN:
+ case ACCESS_CONTROL_IN:
+ case REPORT_LUNS:
+ case READ_BLOCK_LIMITS:
+ case READ_POSITION:
+ case READ_CAPACITY:
+ case READ_TOC:
+ case READ_FORMAT_CAPACITIES:
+ case REQUEST_SENSE:
+ ret = DMA_FROM_DEVICE;
+ break;
+
+ case WRITE_6:
+ case WRITE_10:
+ case WRITE_12:
+ case WRITE_16:
+ case MODE_SELECT:
+ case MODE_SELECT_10:
+ case WRITE_VERIFY:
+ case WRITE_VERIFY_12:
+ case PERSISTENT_RESERVE_OUT:
+ case MAINTENANCE_OUT:
+ case SECURITY_PROTOCOL_OUT:
+ case ACCESS_CONTROL_OUT:
+ ret = DMA_TO_DEVICE;
+ break;
+ case ALLOW_MEDIUM_REMOVAL:
+ case TEST_UNIT_READY:
+ case SYNCHRONIZE_CACHE:
+ case START_STOP:
+ case ERASE:
+ case REZERO_UNIT:
+ case SEEK_10:
+ case SPACE:
+ case VERIFY:
+ case WRITE_FILEMARKS:
+ ret = DMA_NONE;
+ break;
+ default:
+ pr_warn("target: Unknown data direction for SCSI Opcode "
+ "0x%02x\n", cdb[0]);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static void usbg_data_write_cmpl(struct usb_ep *ep, struct usb_request *req)
+{
+ struct usbg_cmd *cmd = req->context;
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+
+ if (req->status < 0) {
+ pr_err("%s() state %d transfer failed\n", __func__, cmd->state);
+ goto cleanup;
+ }
+
+ if (req->num_sgs == 0) {
+ sg_copy_from_buffer(se_cmd->t_data_sg,
+ se_cmd->t_data_nents,
+ cmd->data_buf,
+ se_cmd->data_length);
+ }
+
+ complete(&cmd->write_complete);
+ return;
+
+cleanup:
+ usbg_cleanup_cmd(cmd);
+}
+
+static int usbg_prepare_w_request(struct usbg_cmd *cmd, struct usb_request *req)
+{
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct f_uas *fu = cmd->fu;
+ struct usb_gadget *gadget = fuas_to_gadget(fu);
+
+ if (!gadget->sg_supported) {
+ cmd->data_buf = kmalloc(se_cmd->data_length, GFP_ATOMIC);
+ if (!cmd->data_buf)
+ return -ENOMEM;
+
+ req->buf = cmd->data_buf;
+ } else {
+ req->buf = NULL;
+ req->num_sgs = se_cmd->t_data_nents;
+ req->sg = se_cmd->t_data_sg;
+ }
+
+ req->complete = usbg_data_write_cmpl;
+ req->length = se_cmd->data_length;
+ req->context = cmd;
+ return 0;
+}
+
+static int usbg_send_status_response(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+ struct f_uas *fu = cmd->fu;
+
+ if (fu->flags & USBG_IS_BOT)
+ return bot_send_status_response(cmd);
+ else
+ return uasp_send_status_response(cmd);
+}
+
+static int usbg_send_write_request(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+ struct f_uas *fu = cmd->fu;
+
+ if (fu->flags & USBG_IS_BOT)
+ return bot_send_write_request(cmd);
+ else
+ return uasp_send_write_request(cmd);
+}
+
+static int usbg_send_read_response(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+ struct f_uas *fu = cmd->fu;
+
+ if (fu->flags & USBG_IS_BOT)
+ return bot_send_read_response(cmd);
+ else
+ return uasp_send_read_response(cmd);
+}
+
+static void usbg_cmd_work(struct work_struct *work)
+{
+ struct usbg_cmd *cmd = container_of(work, struct usbg_cmd, work);
+ struct se_cmd *se_cmd;
+ struct tcm_usbg_nexus *tv_nexus;
+ struct usbg_tpg *tpg;
+ int dir;
+
+ se_cmd = &cmd->se_cmd;
+ tpg = cmd->fu->tpg;
+ tv_nexus = tpg->tpg_nexus;
+ dir = get_cmd_dir(cmd->cmd_buf);
+ if (dir < 0) {
+ transport_init_se_cmd(se_cmd,
+ tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
+ tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
+ cmd->prio_attr, cmd->sense_iu.sense);
+
+ transport_send_check_condition_and_sense(se_cmd,
+ TCM_UNSUPPORTED_SCSI_OPCODE, 1);
+ usbg_cleanup_cmd(cmd);
+ return;
+ }
+
+ target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
+ cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun,
+ 0, cmd->prio_attr, dir, TARGET_SCF_UNKNOWN_SIZE);
+}
+
+static int usbg_submit_command(struct f_uas *fu,
+ void *cmdbuf, unsigned int len)
+{
+ struct command_iu *cmd_iu = cmdbuf;
+ struct usbg_cmd *cmd;
+ struct usbg_tpg *tpg;
+ struct se_cmd *se_cmd;
+ struct tcm_usbg_nexus *tv_nexus;
+ u32 cmd_len;
+ int ret;
+
+ if (cmd_iu->iu_id != IU_ID_COMMAND) {
+ pr_err("Unsupported type %d\n", cmd_iu->iu_id);
+ return -EINVAL;
+ }
+
+ cmd = kzalloc(sizeof *cmd, GFP_ATOMIC);
+ if (!cmd)
+ return -ENOMEM;
+
+ cmd->fu = fu;
+
+ /* XXX until I figure out why I can't free in on complete */
+ kref_init(&cmd->ref);
+ kref_get(&cmd->ref);
+
+ tpg = fu->tpg;
+ cmd_len = (cmd_iu->len & ~0x3) + 16;
+ if (cmd_len > USBG_MAX_CMD)
+ goto err;
+
+ memcpy(cmd->cmd_buf, cmd_iu->cdb, cmd_len);
+
+ cmd->tag = be16_to_cpup(&cmd_iu->tag);
+ if (fu->flags & USBG_USE_STREAMS) {
+ if (cmd->tag > UASP_SS_EP_COMP_NUM_STREAMS)
+ goto err;
+ if (!cmd->tag)
+ cmd->stream = &fu->stream[0];
+ else
+ cmd->stream = &fu->stream[cmd->tag - 1];
+ } else {
+ cmd->stream = &fu->stream[0];
+ }
+
+ tv_nexus = tpg->tpg_nexus;
+ if (!tv_nexus) {
+ pr_err("Missing nexus, ignoring command\n");
+ goto err;
+ }
+
+ switch (cmd_iu->prio_attr & 0x7) {
+ case UAS_HEAD_TAG:
+ cmd->prio_attr = MSG_HEAD_TAG;
+ break;
+ case UAS_ORDERED_TAG:
+ cmd->prio_attr = MSG_ORDERED_TAG;
+ break;
+ case UAS_ACA:
+ cmd->prio_attr = MSG_ACA_TAG;
+ break;
+ default:
+ pr_debug_once("Unsupported prio_attr: %02x.\n",
+ cmd_iu->prio_attr);
+ case UAS_SIMPLE_TAG:
+ cmd->prio_attr = MSG_SIMPLE_TAG;
+ break;
+ }
+
+ se_cmd = &cmd->se_cmd;
+ cmd->unpacked_lun = scsilun_to_int(&cmd_iu->lun);
+
+ INIT_WORK(&cmd->work, usbg_cmd_work);
+ ret = queue_work(tpg->workqueue, &cmd->work);
+ if (ret < 0)
+ goto err;
+
+ return 0;
+err:
+ kfree(cmd);
+ return -EINVAL;
+}
+
+static void bot_cmd_work(struct work_struct *work)
+{
+ struct usbg_cmd *cmd = container_of(work, struct usbg_cmd, work);
+ struct se_cmd *se_cmd;
+ struct tcm_usbg_nexus *tv_nexus;
+ struct usbg_tpg *tpg;
+ int dir;
+
+ se_cmd = &cmd->se_cmd;
+ tpg = cmd->fu->tpg;
+ tv_nexus = tpg->tpg_nexus;
+ dir = get_cmd_dir(cmd->cmd_buf);
+ if (dir < 0) {
+ transport_init_se_cmd(se_cmd,
+ tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
+ tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
+ cmd->prio_attr, cmd->sense_iu.sense);
+
+ transport_send_check_condition_and_sense(se_cmd,
+ TCM_UNSUPPORTED_SCSI_OPCODE, 1);
+ usbg_cleanup_cmd(cmd);
+ return;
+ }
+
+ target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
+ cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun,
+ cmd->data_len, cmd->prio_attr, dir, 0);
+}
+
+static int bot_submit_command(struct f_uas *fu,
+ void *cmdbuf, unsigned int len)
+{
+ struct bulk_cb_wrap *cbw = cmdbuf;
+ struct usbg_cmd *cmd;
+ struct usbg_tpg *tpg;
+ struct se_cmd *se_cmd;
+ struct tcm_usbg_nexus *tv_nexus;
+ u32 cmd_len;
+ int ret;
+
+ if (cbw->Signature != cpu_to_le32(US_BULK_CB_SIGN)) {
+ pr_err("Wrong signature on CBW\n");
+ return -EINVAL;
+ }
+ if (len != 31) {
+ pr_err("Wrong length for CBW\n");
+ return -EINVAL;
+ }
+
+ cmd_len = cbw->Length;
+ if (cmd_len < 1 || cmd_len > 16)
+ return -EINVAL;
+
+ cmd = kzalloc(sizeof *cmd, GFP_ATOMIC);
+ if (!cmd)
+ return -ENOMEM;
+
+ cmd->fu = fu;
+
+ /* XXX until I figure out why I can't free in on complete */
+ kref_init(&cmd->ref);
+ kref_get(&cmd->ref);
+
+ tpg = fu->tpg;
+
+ memcpy(cmd->cmd_buf, cbw->CDB, cmd_len);
+
+ cmd->bot_tag = cbw->Tag;
+
+ tv_nexus = tpg->tpg_nexus;
+ if (!tv_nexus) {
+ pr_err("Missing nexus, ignoring command\n");
+ goto err;
+ }
+
+ cmd->prio_attr = MSG_SIMPLE_TAG;
+ se_cmd = &cmd->se_cmd;
+ cmd->unpacked_lun = cbw->Lun;
+ cmd->is_read = cbw->Flags & US_BULK_FLAG_IN ? 1 : 0;
+ cmd->data_len = le32_to_cpu(cbw->DataTransferLength);
+
+ INIT_WORK(&cmd->work, bot_cmd_work);
+ ret = queue_work(tpg->workqueue, &cmd->work);
+ if (ret < 0)
+ goto err;
+
+ return 0;
+err:
+ kfree(cmd);
+ return -EINVAL;
+}
+
+/* Start fabric.c code */
+
+static int usbg_check_true(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static int usbg_check_false(struct se_portal_group *se_tpg)
+{
+ return 0;
+}
+
+static char *usbg_get_fabric_name(void)
+{
+ return "usb_gadget";
+}
+
+static u8 usbg_get_fabric_proto_ident(struct se_portal_group *se_tpg)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+ struct usbg_tport *tport = tpg->tport;
+ u8 proto_id;
+
+ switch (tport->tport_proto_id) {
+ case SCSI_PROTOCOL_SAS:
+ default:
+ proto_id = sas_get_fabric_proto_ident(se_tpg);
+ break;
+ }
+
+ return proto_id;
+}
+
+static char *usbg_get_fabric_wwn(struct se_portal_group *se_tpg)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+ struct usbg_tport *tport = tpg->tport;
+
+ return &tport->tport_name[0];
+}
+
+static u16 usbg_get_tag(struct se_portal_group *se_tpg)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+ return tpg->tport_tpgt;
+}
+
+static u32 usbg_get_default_depth(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static u32 usbg_get_pr_transport_id(
+ struct se_portal_group *se_tpg,
+ struct se_node_acl *se_nacl,
+ struct t10_pr_registration *pr_reg,
+ int *format_code,
+ unsigned char *buf)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+ struct usbg_tport *tport = tpg->tport;
+ int ret = 0;
+
+ switch (tport->tport_proto_id) {
+ case SCSI_PROTOCOL_SAS:
+ default:
+ ret = sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
+ format_code, buf);
+ break;
+ }
+
+ return ret;
+}
+
+static u32 usbg_get_pr_transport_id_len(
+ struct se_portal_group *se_tpg,
+ struct se_node_acl *se_nacl,
+ struct t10_pr_registration *pr_reg,
+ int *format_code)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+ struct usbg_tport *tport = tpg->tport;
+ int ret = 0;
+
+ switch (tport->tport_proto_id) {
+ case SCSI_PROTOCOL_SAS:
+ default:
+ ret = sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
+ format_code);
+ break;
+ }
+
+ return ret;
+}
+
+static char *usbg_parse_pr_out_transport_id(
+ struct se_portal_group *se_tpg,
+ const char *buf,
+ u32 *out_tid_len,
+ char **port_nexus_ptr)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+ struct usbg_tport *tport = tpg->tport;
+ char *tid = NULL;
+
+ switch (tport->tport_proto_id) {
+ case SCSI_PROTOCOL_SAS:
+ default:
+ tid = sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
+ port_nexus_ptr);
+ }
+
+ return tid;
+}
+
+static struct se_node_acl *usbg_alloc_fabric_acl(struct se_portal_group *se_tpg)
+{
+ struct usbg_nacl *nacl;
+
+ nacl = kzalloc(sizeof(struct usbg_nacl), GFP_KERNEL);
+ if (!nacl) {
+ printk(KERN_ERR "Unable to alocate struct usbg_nacl\n");
+ return NULL;
+ }
+
+ return &nacl->se_node_acl;
+}
+
+static void usbg_release_fabric_acl(
+ struct se_portal_group *se_tpg,
+ struct se_node_acl *se_nacl)
+{
+ struct usbg_nacl *nacl = container_of(se_nacl,
+ struct usbg_nacl, se_node_acl);
+ kfree(nacl);
+}
+
+static u32 usbg_tpg_get_inst_index(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static int usbg_new_cmd(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+ int ret;
+
+ ret = target_setup_cmd_from_cdb(se_cmd, cmd->cmd_buf);
+ if (ret)
+ return ret;
+
+ return transport_generic_map_mem_to_cmd(se_cmd, NULL, 0, NULL, 0);
+}
+
+static void usbg_cmd_release(struct kref *ref)
+{
+ struct usbg_cmd *cmd = container_of(ref, struct usbg_cmd,
+ ref);
+
+ transport_generic_free_cmd(&cmd->se_cmd, 0);
+}
+
+static void usbg_release_cmd(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+ kfree(cmd->data_buf);
+ kfree(cmd);
+ return;
+}
+
+static int usbg_shutdown_session(struct se_session *se_sess)
+{
+ return 0;
+}
+
+static void usbg_close_session(struct se_session *se_sess)
+{
+ return;
+}
+
+static u32 usbg_sess_get_index(struct se_session *se_sess)
+{
+ return 0;
+}
+
+/*
+ * XXX Error recovery: return != 0 if we expect writes. Dunno when that could be
+ */
+static int usbg_write_pending_status(struct se_cmd *se_cmd)
+{
+ return 0;
+}
+
+static void usbg_set_default_node_attrs(struct se_node_acl *nacl)
+{
+ return;
+}
+
+static u32 usbg_get_task_tag(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+ struct f_uas *fu = cmd->fu;
+
+ if (fu->flags & USBG_IS_BOT)
+ return le32_to_cpu(cmd->bot_tag);
+ else
+ return cmd->tag;
+}
+
+static int usbg_get_cmd_state(struct se_cmd *se_cmd)
+{
+ return 0;
+}
+
+static int usbg_queue_tm_rsp(struct se_cmd *se_cmd)
+{
+ return 0;
+}
+
+static u16 usbg_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_length)
+{
+ return 0;
+}
+
+static u16 usbg_get_fabric_sense_len(void)
+{
+ return 0;
+}
+
+static const char *usbg_check_wwn(const char *name)
+{
+ const char *n;
+ unsigned int len;
+
+ n = strstr(name, "naa.");
+ if (!n)
+ return NULL;
+ n += 4;
+ len = strlen(n);
+ if (len == 0 || len > USBG_NAMELEN - 1)
+ return NULL;
+ return n;
+}
+
+static struct se_node_acl *usbg_make_nodeacl(
+ struct se_portal_group *se_tpg,
+ struct config_group *group,
+ const char *name)
+{
+ struct se_node_acl *se_nacl, *se_nacl_new;
+ struct usbg_nacl *nacl;
+ u64 wwpn = 0;
+ u32 nexus_depth;
+ const char *wnn_name;
+
+ wnn_name = usbg_check_wwn(name);
+ if (!wnn_name)
+ return ERR_PTR(-EINVAL);
+ se_nacl_new = usbg_alloc_fabric_acl(se_tpg);
+ if (!(se_nacl_new))
+ return ERR_PTR(-ENOMEM);
+
+ nexus_depth = 1;
+ /*
+ * se_nacl_new may be released by core_tpg_add_initiator_node_acl()
+ * when converting a NodeACL from demo mode -> explict
+ */
+ se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new,
+ name, nexus_depth);
+ if (IS_ERR(se_nacl)) {
+ usbg_release_fabric_acl(se_tpg, se_nacl_new);
+ return se_nacl;
+ }
+ /*
+ * Locate our struct usbg_nacl and set the FC Nport WWPN
+ */
+ nacl = container_of(se_nacl, struct usbg_nacl, se_node_acl);
+ nacl->iport_wwpn = wwpn;
+ snprintf(nacl->iport_name, sizeof(nacl->iport_name), "%s", name);
+ return se_nacl;
+}
+
+static void usbg_drop_nodeacl(struct se_node_acl *se_acl)
+{
+ struct usbg_nacl *nacl = container_of(se_acl,
+ struct usbg_nacl, se_node_acl);
+ core_tpg_del_initiator_node_acl(se_acl->se_tpg, se_acl, 1);
+ kfree(nacl);
+}
+
+struct usbg_tpg *the_only_tpg_I_currently_have;
+
+static struct se_portal_group *usbg_make_tpg(
+ struct se_wwn *wwn,
+ struct config_group *group,
+ const char *name)
+{
+ struct usbg_tport *tport = container_of(wwn, struct usbg_tport,
+ tport_wwn);
+ struct usbg_tpg *tpg;
+ unsigned long tpgt;
+ int ret;
+
+ if (strstr(name, "tpgt_") != name)
+ return ERR_PTR(-EINVAL);
+ if (kstrtoul(name + 5, 0, &tpgt) || tpgt > UINT_MAX)
+ return ERR_PTR(-EINVAL);
+ if (the_only_tpg_I_currently_have) {
+ pr_err("Until the gadget framework can't handle multiple\n");
+ pr_err("gadgets, you can't do this here.\n");
+ return ERR_PTR(-EBUSY);
+ }
+
+ tpg = kzalloc(sizeof(struct usbg_tpg), GFP_KERNEL);
+ if (!tpg) {
+ printk(KERN_ERR "Unable to allocate struct usbg_tpg");
+ return ERR_PTR(-ENOMEM);
+ }
+ mutex_init(&tpg->tpg_mutex);
+ atomic_set(&tpg->tpg_port_count, 0);
+ tpg->workqueue = alloc_workqueue("tcm_usb_gadget", 0, 1);
+ if (!tpg->workqueue) {
+ kfree(tpg);
+ return NULL;
+ }
+
+ tpg->tport = tport;
+ tpg->tport_tpgt = tpgt;
+
+ ret = core_tpg_register(&usbg_fabric_configfs->tf_ops, wwn,
+ &tpg->se_tpg, tpg,
+ TRANSPORT_TPG_TYPE_NORMAL);
+ if (ret < 0) {
+ destroy_workqueue(tpg->workqueue);
+ kfree(tpg);
+ return NULL;
+ }
+ the_only_tpg_I_currently_have = tpg;
+ return &tpg->se_tpg;
+}
+
+static void usbg_drop_tpg(struct se_portal_group *se_tpg)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg,
+ struct usbg_tpg, se_tpg);
+
+ core_tpg_deregister(se_tpg);
+ destroy_workqueue(tpg->workqueue);
+ kfree(tpg);
+ the_only_tpg_I_currently_have = NULL;
+}
+
+static struct se_wwn *usbg_make_tport(
+ struct target_fabric_configfs *tf,
+ struct config_group *group,
+ const char *name)
+{
+ struct usbg_tport *tport;
+ const char *wnn_name;
+ u64 wwpn = 0;
+
+ wnn_name = usbg_check_wwn(name);
+ if (!wnn_name)
+ return ERR_PTR(-EINVAL);
+
+ tport = kzalloc(sizeof(struct usbg_tport), GFP_KERNEL);
+ if (!(tport)) {
+ printk(KERN_ERR "Unable to allocate struct usbg_tport");
+ return ERR_PTR(-ENOMEM);
+ }
+ tport->tport_wwpn = wwpn;
+ snprintf(tport->tport_name, sizeof(tport->tport_name), wnn_name);
+ return &tport->tport_wwn;
+}
+
+static void usbg_drop_tport(struct se_wwn *wwn)
+{
+ struct usbg_tport *tport = container_of(wwn,
+ struct usbg_tport, tport_wwn);
+ kfree(tport);
+}
+
+/*
+ * If somebody feels like dropping the version property, go ahead.
+ */
+static ssize_t usbg_wwn_show_attr_version(
+ struct target_fabric_configfs *tf,
+ char *page)
+{
+ return sprintf(page, "usb-gadget fabric module\n");
+}
+TF_WWN_ATTR_RO(usbg, version);
+
+static struct configfs_attribute *usbg_wwn_attrs[] = {
+ &usbg_wwn_version.attr,
+ NULL,
+};
+
+static ssize_t tcm_usbg_tpg_show_enable(
+ struct se_portal_group *se_tpg,
+ char *page)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
+
+ return snprintf(page, PAGE_SIZE, "%u\n", tpg->gadget_connect);
+}
+
+static int usbg_attach(struct usbg_tpg *);
+static void usbg_detach(struct usbg_tpg *);
+
+static ssize_t tcm_usbg_tpg_store_enable(
+ struct se_portal_group *se_tpg,
+ const char *page,
+ size_t count)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
+ unsigned long op;
+ ssize_t ret;
+
+ ret = kstrtoul(page, 0, &op);
+ if (ret < 0)
+ return -EINVAL;
+ if (op > 1)
+ return -EINVAL;
+
+ if (op && tpg->gadget_connect)
+ goto out;
+ if (!op && !tpg->gadget_connect)
+ goto out;
+
+ if (op) {
+ ret = usbg_attach(tpg);
+ if (ret)
+ goto out;
+ } else {
+ usbg_detach(tpg);
+ }
+ tpg->gadget_connect = op;
+out:
+ return count;
+}
+TF_TPG_BASE_ATTR(tcm_usbg, enable, S_IRUGO | S_IWUSR);
+
+static ssize_t tcm_usbg_tpg_show_nexus(
+ struct se_portal_group *se_tpg,
+ char *page)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
+ struct tcm_usbg_nexus *tv_nexus;
+ ssize_t ret;
+
+ mutex_lock(&tpg->tpg_mutex);
+ tv_nexus = tpg->tpg_nexus;
+ if (!tv_nexus) {
+ ret = -ENODEV;
+ goto out;
+ }
+ ret = snprintf(page, PAGE_SIZE, "%s\n",
+ tv_nexus->tvn_se_sess->se_node_acl->initiatorname);
+out:
+ mutex_unlock(&tpg->tpg_mutex);
+ return ret;
+}
+
+static int tcm_usbg_make_nexus(struct usbg_tpg *tpg, char *name)
+{
+ struct se_portal_group *se_tpg;
+ struct tcm_usbg_nexus *tv_nexus;
+ int ret;
+
+ mutex_lock(&tpg->tpg_mutex);
+ if (tpg->tpg_nexus) {
+ ret = -EEXIST;
+ pr_debug("tpg->tpg_nexus already exists\n");
+ goto err_unlock;
+ }
+ se_tpg = &tpg->se_tpg;
+
+ ret = -ENOMEM;
+ tv_nexus = kzalloc(sizeof(*tv_nexus), GFP_KERNEL);
+ if (!tv_nexus) {
+ pr_err("Unable to allocate struct tcm_vhost_nexus\n");
+ goto err_unlock;
+ }
+ tv_nexus->tvn_se_sess = transport_init_session();
+ if (IS_ERR(tv_nexus->tvn_se_sess))
+ goto err_free;
+
+ /*
+ * Since we are running in 'demo mode' this call with generate a
+ * struct se_node_acl for the tcm_vhost struct se_portal_group with
+ * the SCSI Initiator port name of the passed configfs group 'name'.
+ */
+ tv_nexus->tvn_se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
+ se_tpg, name);
+ if (!tv_nexus->tvn_se_sess->se_node_acl) {
+ pr_debug("core_tpg_check_initiator_node_acl() failed"
+ " for %s\n", name);
+ goto err_session;
+ }
+ /*
+ * Now register the TCM vHost virtual I_T Nexus as active with the
+ * call to __transport_register_session()
+ */
+ __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
+ tv_nexus->tvn_se_sess, tv_nexus);
+ tpg->tpg_nexus = tv_nexus;
+ mutex_unlock(&tpg->tpg_mutex);
+ return 0;
+
+err_session:
+ transport_free_session(tv_nexus->tvn_se_sess);
+err_free:
+ kfree(tv_nexus);
+err_unlock:
+ mutex_unlock(&tpg->tpg_mutex);
+ return ret;
+}
+
+static int tcm_usbg_drop_nexus(struct usbg_tpg *tpg)
+{
+ struct se_session *se_sess;
+ struct tcm_usbg_nexus *tv_nexus;
+ int ret = -ENODEV;
+
+ mutex_lock(&tpg->tpg_mutex);
+ tv_nexus = tpg->tpg_nexus;
+ if (!tv_nexus)
+ goto out;
+
+ se_sess = tv_nexus->tvn_se_sess;
+ if (!se_sess)
+ goto out;
+
+ if (atomic_read(&tpg->tpg_port_count)) {
+ ret = -EPERM;
+ pr_err("Unable to remove Host I_T Nexus with"
+ " active TPG port count: %d\n",
+ atomic_read(&tpg->tpg_port_count));
+ goto out;
+ }
+
+ pr_debug("Removing I_T Nexus to Initiator Port: %s\n",
+ tv_nexus->tvn_se_sess->se_node_acl->initiatorname);
+ /*
+ * Release the SCSI I_T Nexus to the emulated vHost Target Port
+ */
+ transport_deregister_session(tv_nexus->tvn_se_sess);
+ tpg->tpg_nexus = NULL;
+
+ kfree(tv_nexus);
+out:
+ mutex_unlock(&tpg->tpg_mutex);
+ return 0;
+}
+
+static ssize_t tcm_usbg_tpg_store_nexus(
+ struct se_portal_group *se_tpg,
+ const char *page,
+ size_t count)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
+ unsigned char i_port[USBG_NAMELEN], *ptr;
+ int ret;
+
+ if (!strncmp(page, "NULL", 4)) {
+ ret = tcm_usbg_drop_nexus(tpg);
+ return (!ret) ? count : ret;
+ }
+ if (strlen(page) > USBG_NAMELEN) {
+ pr_err("Emulated NAA Sas Address: %s, exceeds"
+ " max: %d\n", page, USBG_NAMELEN);
+ return -EINVAL;
+ }
+ snprintf(i_port, USBG_NAMELEN, "%s", page);
+
+ ptr = strstr(i_port, "naa.");
+ if (!ptr) {
+ pr_err("Missing 'naa.' prefix\n");
+ return -EINVAL;
+ }
+
+ if (i_port[strlen(i_port) - 1] == '\n')
+ i_port[strlen(i_port) - 1] = '\0';
+
+ ret = tcm_usbg_make_nexus(tpg, &i_port[4]);
+ if (ret < 0)
+ return ret;
+ return count;
+}
+TF_TPG_BASE_ATTR(tcm_usbg, nexus, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *usbg_base_attrs[] = {
+ &tcm_usbg_tpg_enable.attr,
+ &tcm_usbg_tpg_nexus.attr,
+ NULL,
+};
+
+static int usbg_port_link(struct se_portal_group *se_tpg, struct se_lun *lun)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
+
+ atomic_inc(&tpg->tpg_port_count);
+ smp_mb__after_atomic_inc();
+ return 0;
+}
+
+static void usbg_port_unlink(struct se_portal_group *se_tpg,
+ struct se_lun *se_lun)
+{
+ struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
+
+ atomic_dec(&tpg->tpg_port_count);
+ smp_mb__after_atomic_dec();
+}
+
+static int usbg_check_stop_free(struct se_cmd *se_cmd)
+{
+ struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
+ se_cmd);
+
+ kref_put(&cmd->ref, usbg_cmd_release);
+ return 1;
+}
+
+static struct target_core_fabric_ops usbg_ops = {
+ .get_fabric_name = usbg_get_fabric_name,
+ .get_fabric_proto_ident = usbg_get_fabric_proto_ident,
+ .tpg_get_wwn = usbg_get_fabric_wwn,
+ .tpg_get_tag = usbg_get_tag,
+ .tpg_get_default_depth = usbg_get_default_depth,
+ .tpg_get_pr_transport_id = usbg_get_pr_transport_id,
+ .tpg_get_pr_transport_id_len = usbg_get_pr_transport_id_len,
+ .tpg_parse_pr_out_transport_id = usbg_parse_pr_out_transport_id,
+ .tpg_check_demo_mode = usbg_check_true,
+ .tpg_check_demo_mode_cache = usbg_check_false,
+ .tpg_check_demo_mode_write_protect = usbg_check_false,
+ .tpg_check_prod_mode_write_protect = usbg_check_false,
+ .tpg_alloc_fabric_acl = usbg_alloc_fabric_acl,
+ .tpg_release_fabric_acl = usbg_release_fabric_acl,
+ .tpg_get_inst_index = usbg_tpg_get_inst_index,
+ .new_cmd_map = usbg_new_cmd,
+ .release_cmd = usbg_release_cmd,
+ .shutdown_session = usbg_shutdown_session,
+ .close_session = usbg_close_session,
+ .sess_get_index = usbg_sess_get_index,
+ .sess_get_initiator_sid = NULL,
+ .write_pending = usbg_send_write_request,
+ .write_pending_status = usbg_write_pending_status,
+ .set_default_node_attributes = usbg_set_default_node_attrs,
+ .get_task_tag = usbg_get_task_tag,
+ .get_cmd_state = usbg_get_cmd_state,
+ .queue_data_in = usbg_send_read_response,
+ .queue_status = usbg_send_status_response,
+ .queue_tm_rsp = usbg_queue_tm_rsp,
+ .get_fabric_sense_len = usbg_get_fabric_sense_len,
+ .set_fabric_sense_len = usbg_set_fabric_sense_len,
+ .check_stop_free = usbg_check_stop_free,
+
+ .fabric_make_wwn = usbg_make_tport,
+ .fabric_drop_wwn = usbg_drop_tport,
+ .fabric_make_tpg = usbg_make_tpg,
+ .fabric_drop_tpg = usbg_drop_tpg,
+ .fabric_post_link = usbg_port_link,
+ .fabric_pre_unlink = usbg_port_unlink,
+ .fabric_make_np = NULL,
+ .fabric_drop_np = NULL,
+ .fabric_make_nodeacl = usbg_make_nodeacl,
+ .fabric_drop_nodeacl = usbg_drop_nodeacl,
+};
+
+static int usbg_register_configfs(void)
+{
+ struct target_fabric_configfs *fabric;
+ int ret;
+
+ fabric = target_fabric_configfs_init(THIS_MODULE, "usb_gadget");
+ if (IS_ERR(fabric)) {
+ printk(KERN_ERR "target_fabric_configfs_init() failed\n");
+ return PTR_ERR(fabric);
+ }
+
+ fabric->tf_ops = usbg_ops;
+ TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = usbg_wwn_attrs;
+ TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = usbg_base_attrs;
+ TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
+ TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL;
+ ret = target_fabric_configfs_register(fabric);
+ if (ret < 0) {
+ printk(KERN_ERR "target_fabric_configfs_register() failed"
+ " for usb-gadget\n");
+ return ret;
+ }
+ usbg_fabric_configfs = fabric;
+ return 0;
+};
+
+static void usbg_deregister_configfs(void)
+{
+ if (!(usbg_fabric_configfs))
+ return;
+
+ target_fabric_configfs_deregister(usbg_fabric_configfs);
+ usbg_fabric_configfs = NULL;
+};
+
+/* Start gadget.c code */
+
+static struct usb_interface_descriptor bot_intf_desc = {
+ .bLength = sizeof(bot_intf_desc),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 2,
+ .bAlternateSetting = USB_G_ALT_INT_BBB,
+ .bInterfaceClass = USB_CLASS_MASS_STORAGE,
+ .bInterfaceSubClass = USB_SC_SCSI,
+ .bInterfaceProtocol = USB_PR_BULK,
+ .iInterface = USB_G_STR_INT_UAS,
+};
+
+static struct usb_interface_descriptor uasp_intf_desc = {
+ .bLength = sizeof(uasp_intf_desc),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bNumEndpoints = 4,
+ .bAlternateSetting = USB_G_ALT_INT_UAS,
+ .bInterfaceClass = USB_CLASS_MASS_STORAGE,
+ .bInterfaceSubClass = USB_SC_SCSI,
+ .bInterfaceProtocol = USB_PR_UAS,
+ .iInterface = USB_G_STR_INT_BBB,
+};
+
+static struct usb_endpoint_descriptor uasp_bi_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor uasp_fs_bi_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_pipe_usage_descriptor uasp_bi_pipe_desc = {
+ .bLength = sizeof(uasp_bi_pipe_desc),
+ .bDescriptorType = USB_DT_PIPE_USAGE,
+ .bPipeID = DATA_IN_PIPE_ID,
+};
+
+static struct usb_endpoint_descriptor uasp_ss_bi_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor uasp_bi_ep_comp_desc = {
+ .bLength = sizeof(uasp_bi_ep_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ .bMaxBurst = 0,
+ .bmAttributes = UASP_SS_EP_COMP_LOG_STREAMS,
+ .wBytesPerInterval = 0,
+};
+
+static struct usb_ss_ep_comp_descriptor bot_bi_ep_comp_desc = {
+ .bLength = sizeof(bot_bi_ep_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ .bMaxBurst = 0,
+};
+
+static struct usb_endpoint_descriptor uasp_bo_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor uasp_fs_bo_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_pipe_usage_descriptor uasp_bo_pipe_desc = {
+ .bLength = sizeof(uasp_bo_pipe_desc),
+ .bDescriptorType = USB_DT_PIPE_USAGE,
+ .bPipeID = DATA_OUT_PIPE_ID,
+};
+
+static struct usb_endpoint_descriptor uasp_ss_bo_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(0x400),
+};
+
+static struct usb_ss_ep_comp_descriptor uasp_bo_ep_comp_desc = {
+ .bLength = sizeof(uasp_bo_ep_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ .bmAttributes = UASP_SS_EP_COMP_LOG_STREAMS,
+};
+
+static struct usb_ss_ep_comp_descriptor bot_bo_ep_comp_desc = {
+ .bLength = sizeof(bot_bo_ep_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+};
+
+static struct usb_endpoint_descriptor uasp_status_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor uasp_fs_status_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_pipe_usage_descriptor uasp_status_pipe_desc = {
+ .bLength = sizeof(uasp_status_pipe_desc),
+ .bDescriptorType = USB_DT_PIPE_USAGE,
+ .bPipeID = STATUS_PIPE_ID,
+};
+
+static struct usb_endpoint_descriptor uasp_ss_status_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor uasp_status_in_ep_comp_desc = {
+ .bLength = sizeof(uasp_status_in_ep_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ .bmAttributes = UASP_SS_EP_COMP_LOG_STREAMS,
+};
+
+static struct usb_endpoint_descriptor uasp_cmd_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor uasp_fs_cmd_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_pipe_usage_descriptor uasp_cmd_pipe_desc = {
+ .bLength = sizeof(uasp_cmd_pipe_desc),
+ .bDescriptorType = USB_DT_PIPE_USAGE,
+ .bPipeID = CMD_PIPE_ID,
+};
+
+static struct usb_endpoint_descriptor uasp_ss_cmd_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor uasp_cmd_comp_desc = {
+ .bLength = sizeof(uasp_cmd_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+};
+
+static struct usb_descriptor_header *uasp_fs_function_desc[] = {
+ (struct usb_descriptor_header *) &bot_intf_desc,
+ (struct usb_descriptor_header *) &uasp_fs_bi_desc,
+ (struct usb_descriptor_header *) &uasp_fs_bo_desc,
+
+ (struct usb_descriptor_header *) &uasp_intf_desc,
+ (struct usb_descriptor_header *) &uasp_fs_bi_desc,
+ (struct usb_descriptor_header *) &uasp_bi_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_fs_bo_desc,
+ (struct usb_descriptor_header *) &uasp_bo_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_fs_status_desc,
+ (struct usb_descriptor_header *) &uasp_status_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_fs_cmd_desc,
+ (struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
+};
+
+static struct usb_descriptor_header *uasp_hs_function_desc[] = {
+ (struct usb_descriptor_header *) &bot_intf_desc,
+ (struct usb_descriptor_header *) &uasp_bi_desc,
+ (struct usb_descriptor_header *) &uasp_bo_desc,
+
+ (struct usb_descriptor_header *) &uasp_intf_desc,
+ (struct usb_descriptor_header *) &uasp_bi_desc,
+ (struct usb_descriptor_header *) &uasp_bi_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_bo_desc,
+ (struct usb_descriptor_header *) &uasp_bo_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_status_desc,
+ (struct usb_descriptor_header *) &uasp_status_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_cmd_desc,
+ (struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
+ NULL,
+};
+
+static struct usb_descriptor_header *uasp_ss_function_desc[] = {
+ (struct usb_descriptor_header *) &bot_intf_desc,
+ (struct usb_descriptor_header *) &uasp_ss_bi_desc,
+ (struct usb_descriptor_header *) &bot_bi_ep_comp_desc,
+ (struct usb_descriptor_header *) &uasp_ss_bo_desc,
+ (struct usb_descriptor_header *) &bot_bo_ep_comp_desc,
+
+ (struct usb_descriptor_header *) &uasp_intf_desc,
+ (struct usb_descriptor_header *) &uasp_ss_bi_desc,
+ (struct usb_descriptor_header *) &uasp_bi_ep_comp_desc,
+ (struct usb_descriptor_header *) &uasp_bi_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_ss_bo_desc,
+ (struct usb_descriptor_header *) &uasp_bo_ep_comp_desc,
+ (struct usb_descriptor_header *) &uasp_bo_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_ss_status_desc,
+ (struct usb_descriptor_header *) &uasp_status_in_ep_comp_desc,
+ (struct usb_descriptor_header *) &uasp_status_pipe_desc,
+ (struct usb_descriptor_header *) &uasp_ss_cmd_desc,
+ (struct usb_descriptor_header *) &uasp_cmd_comp_desc,
+ (struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
+ NULL,
+};
+
+#define UAS_VENDOR_ID 0x0525 /* NetChip */
+#define UAS_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */
+
+static struct usb_device_descriptor usbg_device_desc = {
+ .bLength = sizeof(usbg_device_desc),
+ .bDescriptorType = USB_DT_DEVICE,
+ .bcdUSB = cpu_to_le16(0x0200),
+ .bDeviceClass = USB_CLASS_PER_INTERFACE,
+ .idVendor = cpu_to_le16(UAS_VENDOR_ID),
+ .idProduct = cpu_to_le16(UAS_PRODUCT_ID),
+ .iManufacturer = USB_G_STR_MANUFACTOR,
+ .iProduct = USB_G_STR_PRODUCT,
+ .iSerialNumber = USB_G_STR_SERIAL,
+
+ .bNumConfigurations = 1,
+};
+
+static struct usb_string usbg_us_strings[] = {
+ { USB_G_STR_MANUFACTOR, "Target Manufactor"},
+ { USB_G_STR_PRODUCT, "Target Product"},
+ { USB_G_STR_SERIAL, "000000000001"},
+ { USB_G_STR_CONFIG, "default config"},
+ { USB_G_STR_INT_UAS, "USB Attached SCSI"},
+ { USB_G_STR_INT_BBB, "Bulk Only Transport"},
+ { },
+};
+
+static struct usb_gadget_strings usbg_stringtab = {
+ .language = 0x0409,
+ .strings = usbg_us_strings,
+};
+
+static struct usb_gadget_strings *usbg_strings[] = {
+ &usbg_stringtab,
+ NULL,
+};
+
+static int guas_unbind(struct usb_composite_dev *cdev)
+{
+ return 0;
+}
+
+static struct usb_configuration usbg_config_driver = {
+ .label = "Linux Target",
+ .bConfigurationValue = 1,
+ .iConfiguration = USB_G_STR_CONFIG,
+ .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
+};
+
+static void give_back_ep(struct usb_ep **pep)
+{
+ struct usb_ep *ep = *pep;
+ if (!ep)
+ return;
+ ep->driver_data = NULL;
+}
+
+static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct f_uas *fu = to_f_uas(f);
+ struct usb_gadget *gadget = c->cdev->gadget;
+ struct usb_ep *ep;
+ int iface;
+
+ iface = usb_interface_id(c, f);
+ if (iface < 0)
+ return iface;
+
+ bot_intf_desc.bInterfaceNumber = iface;
+ uasp_intf_desc.bInterfaceNumber = iface;
+ fu->iface = iface;
+ ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bi_desc,
+ &uasp_bi_ep_comp_desc);
+ if (!ep)
+ goto ep_fail;
+
+ ep->driver_data = fu;
+ fu->ep_in = ep;
+
+ ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bo_desc,
+ &uasp_bo_ep_comp_desc);
+ if (!ep)
+ goto ep_fail;
+ ep->driver_data = fu;
+ fu->ep_out = ep;
+
+ ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_status_desc,
+ &uasp_status_in_ep_comp_desc);
+ if (!ep)
+ goto ep_fail;
+ ep->driver_data = fu;
+ fu->ep_status = ep;
+
+ ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_cmd_desc,
+ &uasp_cmd_comp_desc);
+ if (!ep)
+ goto ep_fail;
+ ep->driver_data = fu;
+ fu->ep_cmd = ep;
+
+ /* Assume endpoint addresses are the same for both speeds */
+ uasp_bi_desc.bEndpointAddress = uasp_ss_bi_desc.bEndpointAddress;
+ uasp_bo_desc.bEndpointAddress = uasp_ss_bo_desc.bEndpointAddress;
+ uasp_status_desc.bEndpointAddress =
+ uasp_ss_status_desc.bEndpointAddress;
+ uasp_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
+
+ uasp_fs_bi_desc.bEndpointAddress = uasp_ss_bi_desc.bEndpointAddress;
+ uasp_fs_bo_desc.bEndpointAddress = uasp_ss_bo_desc.bEndpointAddress;
+ uasp_fs_status_desc.bEndpointAddress =
+ uasp_ss_status_desc.bEndpointAddress;
+ uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
+
+ return 0;
+ep_fail:
+ pr_err("Can't claim all required eps\n");
+
+ give_back_ep(&fu->ep_in);
+ give_back_ep(&fu->ep_out);
+ give_back_ep(&fu->ep_status);
+ give_back_ep(&fu->ep_cmd);
+ return -ENOTSUPP;
+}
+
+static void usbg_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct f_uas *fu = to_f_uas(f);
+
+ kfree(fu);
+}
+
+struct guas_setup_wq {
+ struct work_struct work;
+ struct f_uas *fu;
+ unsigned int alt;
+};
+
+static void usbg_delayed_set_alt(struct work_struct *wq)
+{
+ struct guas_setup_wq *work = container_of(wq, struct guas_setup_wq,
+ work);
+ struct f_uas *fu = work->fu;
+ int alt = work->alt;
+
+ kfree(work);
+
+ if (fu->flags & USBG_IS_BOT)
+ bot_cleanup_old_alt(fu);
+ if (fu->flags & USBG_IS_UAS)
+ uasp_cleanup_old_alt(fu);
+
+ if (alt == USB_G_ALT_INT_BBB)
+ bot_set_alt(fu);
+ else if (alt == USB_G_ALT_INT_UAS)
+ uasp_set_alt(fu);
+ usb_composite_setup_continue(fu->function.config->cdev);
+}
+
+static int usbg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_uas *fu = to_f_uas(f);
+
+ if ((alt == USB_G_ALT_INT_BBB) || (alt == USB_G_ALT_INT_UAS)) {
+ struct guas_setup_wq *work;
+
+ work = kmalloc(sizeof(*work), GFP_ATOMIC);
+ if (!work)
+ return -ENOMEM;
+ INIT_WORK(&work->work, usbg_delayed_set_alt);
+ work->fu = fu;
+ work->alt = alt;
+ schedule_work(&work->work);
+ return USB_GADGET_DELAYED_STATUS;
+ }
+ return -EOPNOTSUPP;
+}
+
+static void usbg_disable(struct usb_function *f)
+{
+ struct f_uas *fu = to_f_uas(f);
+
+ if (fu->flags & USBG_IS_UAS)
+ uasp_cleanup_old_alt(fu);
+ else if (fu->flags & USBG_IS_BOT)
+ bot_cleanup_old_alt(fu);
+ fu->flags = 0;
+}
+
+static int usbg_setup(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct f_uas *fu = to_f_uas(f);
+
+ if (!(fu->flags & USBG_IS_BOT))
+ return -EOPNOTSUPP;
+
+ return usbg_bot_setup(f, ctrl);
+}
+
+static int usbg_cfg_bind(struct usb_configuration *c)
+{
+ struct f_uas *fu;
+ int ret;
+
+ fu = kzalloc(sizeof(*fu), GFP_KERNEL);
+ if (!fu)
+ return -ENOMEM;
+ fu->function.name = "Target Function";
+ fu->function.descriptors = uasp_fs_function_desc;
+ fu->function.hs_descriptors = uasp_hs_function_desc;
+ fu->function.ss_descriptors = uasp_ss_function_desc;
+ fu->function.bind = usbg_bind;
+ fu->function.unbind = usbg_unbind;
+ fu->function.set_alt = usbg_set_alt;
+ fu->function.setup = usbg_setup;
+ fu->function.disable = usbg_disable;
+ fu->tpg = the_only_tpg_I_currently_have;
+
+ ret = usb_add_function(c, &fu->function);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ kfree(fu);
+ return ret;
+}
+
+static int usb_target_bind(struct usb_composite_dev *cdev)
+{
+ int ret;
+
+ ret = usb_add_config(cdev, &usbg_config_driver,
+ usbg_cfg_bind);
+ return 0;
+}
+
+static struct usb_composite_driver usbg_driver = {
+ .name = "g_target",
+ .dev = &usbg_device_desc,
+ .strings = usbg_strings,
+ .max_speed = USB_SPEED_SUPER,
+ .unbind = guas_unbind,
+};
+
+static int usbg_attach(struct usbg_tpg *tpg)
+{
+ return usb_composite_probe(&usbg_driver, usb_target_bind);
+}
+
+static void usbg_detach(struct usbg_tpg *tpg)
+{
+ usb_composite_unregister(&usbg_driver);
+}
+
+static int __init usb_target_gadget_init(void)
+{
+ int ret;
+
+ ret = usbg_register_configfs();
+ return ret;
+}
+module_init(usb_target_gadget_init);
+
+static void __exit usb_target_gadget_exit(void)
+{
+ usbg_deregister_configfs();
+}
+module_exit(usb_target_gadget_exit);
+
+MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
+MODULE_DESCRIPTION("usb-gadget fabric");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/gadget/tcm_usb_gadget.h b/drivers/usb/gadget/tcm_usb_gadget.h
new file mode 100644
index 000000000000..bb18999a9a8d
--- /dev/null
+++ b/drivers/usb/gadget/tcm_usb_gadget.h
@@ -0,0 +1,146 @@
+#ifndef __TARGET_USB_GADGET_H__
+#define __TARGET_USB_GADGET_H__
+
+#include <linux/kref.h>
+/* #include <linux/usb/uas.h> */
+#include <linux/usb/composite.h>
+#include <linux/usb/uas.h>
+#include <linux/usb/storage.h>
+#include <scsi/scsi.h>
+#include <target/target_core_base.h>
+#include <target/target_core_fabric.h>
+
+#define USBG_NAMELEN 32
+
+#define fuas_to_gadget(f) (f->function.config->cdev->gadget)
+#define UASP_SS_EP_COMP_LOG_STREAMS 4
+#define UASP_SS_EP_COMP_NUM_STREAMS (1 << UASP_SS_EP_COMP_LOG_STREAMS)
+
+#define USB_G_STR_MANUFACTOR 1
+#define USB_G_STR_PRODUCT 2
+#define USB_G_STR_SERIAL 3
+#define USB_G_STR_CONFIG 4
+#define USB_G_STR_INT_UAS 5
+#define USB_G_STR_INT_BBB 6
+
+#define USB_G_ALT_INT_BBB 0
+#define USB_G_ALT_INT_UAS 1
+
+struct usbg_nacl {
+ /* Binary World Wide unique Port Name for SAS Initiator port */
+ u64 iport_wwpn;
+ /* ASCII formatted WWPN for Sas Initiator port */
+ char iport_name[USBG_NAMELEN];
+ /* Returned by usbg_make_nodeacl() */
+ struct se_node_acl se_node_acl;
+};
+
+struct tcm_usbg_nexus {
+ struct se_session *tvn_se_sess;
+};
+
+struct usbg_tpg {
+ struct mutex tpg_mutex;
+ /* SAS port target portal group tag for TCM */
+ u16 tport_tpgt;
+ /* Pointer back to usbg_tport */
+ struct usbg_tport *tport;
+ struct workqueue_struct *workqueue;
+ /* Returned by usbg_make_tpg() */
+ struct se_portal_group se_tpg;
+ u32 gadget_connect;
+ struct tcm_usbg_nexus *tpg_nexus;
+ atomic_t tpg_port_count;
+};
+
+struct usbg_tport {
+ /* SCSI protocol the tport is providing */
+ u8 tport_proto_id;
+ /* Binary World Wide unique Port Name for SAS Target port */
+ u64 tport_wwpn;
+ /* ASCII formatted WWPN for SAS Target port */
+ char tport_name[USBG_NAMELEN];
+ /* Returned by usbg_make_tport() */
+ struct se_wwn tport_wwn;
+};
+
+enum uas_state {
+ UASP_SEND_DATA,
+ UASP_RECEIVE_DATA,
+ UASP_SEND_STATUS,
+ UASP_QUEUE_COMMAND,
+};
+
+#define USBG_MAX_CMD 64
+struct usbg_cmd {
+ /* common */
+ u8 cmd_buf[USBG_MAX_CMD];
+ u32 data_len;
+ struct work_struct work;
+ int unpacked_lun;
+ struct se_cmd se_cmd;
+ void *data_buf; /* used if no sg support available */
+ struct f_uas *fu;
+ struct completion write_complete;
+ struct kref ref;
+
+ /* UAS only */
+ u16 tag;
+ u16 prio_attr;
+ struct sense_iu sense_iu;
+ enum uas_state state;
+ struct uas_stream *stream;
+
+ /* BOT only */
+ __le32 bot_tag;
+ unsigned int csw_code;
+ unsigned is_read:1;
+
+};
+
+struct uas_stream {
+ struct usb_request *req_in;
+ struct usb_request *req_out;
+ struct usb_request *req_status;
+};
+
+struct usbg_cdb {
+ struct usb_request *req;
+ void *buf;
+};
+
+struct bot_status {
+ struct usb_request *req;
+ struct bulk_cs_wrap csw;
+};
+
+struct f_uas {
+ struct usbg_tpg *tpg;
+ struct usb_function function;
+ u16 iface;
+
+ u32 flags;
+#define USBG_ENABLED (1 << 0)
+#define USBG_IS_UAS (1 << 1)
+#define USBG_USE_STREAMS (1 << 2)
+#define USBG_IS_BOT (1 << 3)
+#define USBG_BOT_CMD_PEND (1 << 4)
+
+ struct usbg_cdb cmd;
+ struct usb_ep *ep_in;
+ struct usb_ep *ep_out;
+
+ /* UAS */
+ struct usb_ep *ep_status;
+ struct usb_ep *ep_cmd;
+ struct uas_stream stream[UASP_SS_EP_COMP_NUM_STREAMS];
+
+ /* BOT */
+ struct bot_status bot_status;
+ struct usb_request *bot_req_in;
+ struct usb_request *bot_req_out;
+};
+
+extern struct usbg_tpg *the_only_tpg_I_currently_have;
+
+#endif
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 29c854bbca44..47cf48b51c9d 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -744,10 +744,11 @@ static struct device_type gadget_type = {
};
/**
- * gether_setup - initialize one ethernet-over-usb link
+ * gether_setup_name - initialize one ethernet-over-usb link
* @g: gadget to associated with these links
* @ethaddr: NULL, or a buffer in which the ethernet address of the
* host side of the link is recorded
+ * @netname: name for network device (for example, "usb")
* Context: may sleep
*
* This sets up the single network link that may be exported by a
@@ -756,7 +757,8 @@ static struct device_type gadget_type = {
*
* Returns negative errno, or zero on success
*/
-int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
+int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
+ const char *netname)
{
struct eth_dev *dev;
struct net_device *net;
@@ -780,7 +782,7 @@ int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
/* network device setup */
dev->net = net;
- strcpy(net->name, "usb%d");
+ snprintf(net->name, sizeof(net->name), "%s%%d", netname);
if (get_ether_addr(dev_addr, net->dev_addr))
dev_warn(&g->dev,
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index 8012357e98aa..6f4a1623d854 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -69,9 +69,28 @@ struct gether {
|USB_CDC_PACKET_TYPE_PROMISCUOUS \
|USB_CDC_PACKET_TYPE_DIRECTED)
+/* variant of gether_setup that allows customizing network device name */
+int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
+ const char *netname);
/* netdev setup/teardown as directed by the gadget driver */
-int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]);
+/* gether_setup - initialize one ethernet-over-usb link
+ * @g: gadget to associated with these links
+ * @ethaddr: NULL, or a buffer in which the ethernet address of the
+ * host side of the link is recorded
+ * Context: may sleep
+ *
+ * This sets up the single network link that may be exported by a
+ * gadget driver using this framework. The link layer addresses are
+ * set up using module parameters.
+ *
+ * Returns negative errno, or zero on success
+ */
+static inline int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
+{
+ return gether_setup_name(g, ethaddr, "usb");
+}
+
void gether_cleanup(void);
/* connect/disconnect is handled by individual functions */
@@ -99,16 +118,37 @@ int eem_bind_config(struct usb_configuration *c);
#ifdef USB_ETH_RNDIS
-int rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ u32 vendorID, const char *manufacturer);
#else
static inline int
-rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ u32 vendorID, const char *manufacturer)
{
return 0;
}
#endif
+/**
+ * rndis_bind_config - add RNDIS network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ * side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup(). Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+static inline int rndis_bind_config(struct usb_configuration *c,
+ u8 ethaddr[ETH_ALEN])
+{
+ return rndis_bind_config_vendor(c, ethaddr, 0, NULL);
+}
+
+
#endif /* __U_ETHER_H */
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 6c23938d2711..5b3f5fffea92 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -94,17 +94,14 @@ struct gs_buf {
* (and thus for each /dev/ node).
*/
struct gs_port {
+ struct tty_port port;
spinlock_t port_lock; /* guard port_* access */
struct gserial *port_usb;
- struct tty_struct *port_tty;
- unsigned open_count;
bool openclose; /* open/close in progress */
u8 port_num;
- wait_queue_head_t close_wait; /* wait for last close */
-
struct list_head read_pool;
int read_started;
int read_allocated;
@@ -412,8 +409,8 @@ __acquires(&port->port_lock)
break;
}
- if (do_tty_wake && port->port_tty)
- tty_wakeup(port->port_tty);
+ if (do_tty_wake && port->port.tty)
+ tty_wakeup(port->port.tty);
return status;
}
@@ -435,7 +432,7 @@ __acquires(&port->port_lock)
struct tty_struct *tty;
/* no more rx if closed */
- tty = port->port_tty;
+ tty = port->port.tty;
if (!tty)
break;
@@ -488,7 +485,7 @@ static void gs_rx_push(unsigned long _port)
/* hand any queued data to the tty */
spin_lock_irq(&port->port_lock);
- tty = port->port_tty;
+ tty = port->port.tty;
while (!list_empty(queue)) {
struct usb_request *req;
@@ -699,7 +696,7 @@ static int gs_start_io(struct gs_port *port)
/* unblock any pending writes into our circular buffer */
if (started) {
- tty_wakeup(port->port_tty);
+ tty_wakeup(port->port.tty);
} else {
gs_free_requests(ep, head, &port->read_allocated);
gs_free_requests(port->port_usb->in, &port->write_pool,
@@ -734,9 +731,9 @@ static int gs_open(struct tty_struct *tty, struct file *file)
spin_lock_irq(&port->port_lock);
/* already open? Great. */
- if (port->open_count) {
+ if (port->port.count) {
status = 0;
- port->open_count++;
+ port->port.count++;
/* currently opening/closing? wait ... */
} else if (port->openclose) {
@@ -793,9 +790,9 @@ static int gs_open(struct tty_struct *tty, struct file *file)
/* REVISIT maybe wait for "carrier detect" */
tty->driver_data = port;
- port->port_tty = tty;
+ port->port.tty = tty;
- port->open_count = 1;
+ port->port.count = 1;
port->openclose = false;
/* if connected, start the I/O stream */
@@ -837,11 +834,11 @@ static void gs_close(struct tty_struct *tty, struct file *file)
spin_lock_irq(&port->port_lock);
- if (port->open_count != 1) {
- if (port->open_count == 0)
+ if (port->port.count != 1) {
+ if (port->port.count == 0)
WARN_ON(1);
else
- --port->open_count;
+ --port->port.count;
goto exit;
}
@@ -851,7 +848,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
* and sleep if necessary
*/
port->openclose = true;
- port->open_count = 0;
+ port->port.count = 0;
gser = port->port_usb;
if (gser && gser->disconnect)
@@ -879,14 +876,14 @@ static void gs_close(struct tty_struct *tty, struct file *file)
gs_buf_clear(&port->port_write_buf);
tty->driver_data = NULL;
- port->port_tty = NULL;
+ port->port.tty = NULL;
port->openclose = false;
pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
port->port_num, tty, file);
- wake_up_interruptible(&port->close_wait);
+ wake_up_interruptible(&port->port.close_wait);
exit:
spin_unlock_irq(&port->port_lock);
}
@@ -917,7 +914,7 @@ static int gs_put_char(struct tty_struct *tty, unsigned char ch)
unsigned long flags;
int status;
- pr_vdebug("gs_put_char: (%d,%p) char=0x%x, called from %p\n",
+ pr_vdebug("gs_put_char: (%d,%p) char=0x%x, called from %pf\n",
port->port_num, tty, ch, __builtin_return_address(0));
spin_lock_irqsave(&port->port_lock, flags);
@@ -1025,7 +1022,7 @@ static const struct tty_operations gs_tty_ops = {
static struct tty_driver *gs_tty_driver;
-static int __init
+static int
gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
{
struct gs_port *port;
@@ -1034,8 +1031,8 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
if (port == NULL)
return -ENOMEM;
+ tty_port_init(&port->port);
spin_lock_init(&port->port_lock);
- init_waitqueue_head(&port->close_wait);
init_waitqueue_head(&port->drain_wait);
tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
@@ -1071,7 +1068,7 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
*
* Returns negative errno or zero.
*/
-int __init gserial_setup(struct usb_gadget *g, unsigned count)
+int gserial_setup(struct usb_gadget *g, unsigned count)
{
unsigned i;
struct usb_cdc_line_coding coding;
@@ -1155,7 +1152,7 @@ static int gs_closed(struct gs_port *port)
int cond;
spin_lock_irq(&port->port_lock);
- cond = (port->open_count == 0) && !port->openclose;
+ cond = (port->port.count == 0) && !port->openclose;
spin_unlock_irq(&port->port_lock);
return cond;
}
@@ -1194,7 +1191,7 @@ void gserial_cleanup(void)
tasklet_kill(&port->push);
/* wait for old opens to finish */
- wait_event(port->close_wait, gs_closed(port));
+ wait_event(port->port.close_wait, gs_closed(port));
WARN_ON(port->port_usb != NULL);
@@ -1268,7 +1265,7 @@ int gserial_connect(struct gserial *gser, u8 port_num)
/* if it's already open, start I/O ... and notify the serial
* protocol about open/close status (connect/disconnect).
*/
- if (port->open_count) {
+ if (port->port.count) {
pr_debug("gserial_connect: start ttyGS%d\n", port->port_num);
gs_start_io(port);
if (gser->connect)
@@ -1315,10 +1312,10 @@ void gserial_disconnect(struct gserial *gser)
port->port_usb = NULL;
gser->ioport = NULL;
- if (port->open_count > 0 || port->openclose) {
+ if (port->port.count > 0 || port->openclose) {
wake_up_interruptible(&port->drain_wait);
- if (port->port_tty)
- tty_hangup(port->port_tty);
+ if (port->port.tty)
+ tty_hangup(port->port.tty);
}
spin_unlock_irqrestore(&port->port_lock, flags);
@@ -1331,7 +1328,7 @@ void gserial_disconnect(struct gserial *gser)
/* finally, free any unused/unusable I/O buffers */
spin_lock_irqsave(&port->port_lock, flags);
- if (port->open_count == 0 && !port->openclose)
+ if (port->port.count == 0 && !port->openclose)
gs_buf_free(&port->port_write_buf);
gs_free_requests(gser->out, &port->read_pool, NULL);
gs_free_requests(gser->out, &port->read_queue, NULL);
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 31d34832907e..12ad516ada77 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -72,7 +72,7 @@
static const char longname[] = "Gadget Zero";
-unsigned buflen = 4096;
+unsigned buflen = 4096; /* only used for bulk endpoints */
module_param(buflen, uint, 0);
/*
@@ -170,14 +170,17 @@ static struct usb_gadget_strings *dev_strings[] = {
/*-------------------------------------------------------------------------*/
-struct usb_request *alloc_ep_req(struct usb_ep *ep)
+struct usb_request *alloc_ep_req(struct usb_ep *ep, int len)
{
struct usb_request *req;
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (req) {
- req->length = buflen;
- req->buf = kmalloc(buflen, GFP_ATOMIC);
+ if (len)
+ req->length = len;
+ else
+ req->length = buflen;
+ req->buf = kmalloc(req->length, GFP_ATOMIC);
if (!req->buf) {
usb_ep_free_request(ep, req);
req = NULL;
@@ -206,10 +209,15 @@ static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
}
void disable_endpoints(struct usb_composite_dev *cdev,
- struct usb_ep *in, struct usb_ep *out)
+ struct usb_ep *in, struct usb_ep *out,
+ struct usb_ep *iso_in, struct usb_ep *iso_out)
{
disable_ep(cdev, in);
disable_ep(cdev, out);
+ if (iso_in)
+ disable_ep(cdev, iso_in);
+ if (iso_out)
+ disable_ep(cdev, iso_out);
}
/*-------------------------------------------------------------------------*/
@@ -311,7 +319,6 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
device_desc.bcdDevice = cpu_to_le16(0x9999);
}
-
INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index f788eb86707c..83e58df29fe3 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -65,7 +65,7 @@ config USB_EHCI_HCD
config USB_EHCI_ROOT_HUB_TT
bool "Root Hub Transaction Translators"
- depends on USB_EHCI_HCD
+ depends on USB_EHCI_HCD || USB_CHIPIDEA_HOST
---help---
Some EHCI chips have vendor-specific extensions to integrate
transaction translators, so that no OHCI or UHCI companion
@@ -77,7 +77,7 @@ config USB_EHCI_ROOT_HUB_TT
config USB_EHCI_TT_NEWSCHED
bool "Improved Transaction Translator scheduling"
- depends on USB_EHCI_HCD
+ depends on USB_EHCI_HCD || USB_CHIPIDEA_HOST
default y
---help---
This changes the periodic scheduling code to fill more of the low
@@ -110,13 +110,14 @@ config USB_EHCI_BIG_ENDIAN_MMIO
depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || \
ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
PPC_MPC512x || CPU_CAVIUM_OCTEON || \
- PMC_MSP || SPARC_LEON)
+ PMC_MSP || SPARC_LEON || MIPS_SEAD3)
default y
config USB_EHCI_BIG_ENDIAN_DESC
bool
depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
- PPC_MPC512x || PMC_MSP || SPARC_LEON)
+ PPC_MPC512x || PMC_MSP || SPARC_LEON || \
+ MIPS_SEAD3)
default y
config XPS_USB_HCD_XILINX
@@ -152,7 +153,7 @@ config USB_EHCI_HCD_OMAP
bool "EHCI support for OMAP3 and later chips"
depends on USB_EHCI_HCD && ARCH_OMAP
default y
- --- help ---
+ ---help---
Enables support for the on-chip EHCI controller on
OMAP3 and later chips.
@@ -291,6 +292,7 @@ config USB_OHCI_HCD
depends on USB && USB_ARCH_HAS_OHCI
select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
select USB_OTG_UTILS if ARCH_OMAP
+ select USB_ISP1301 if ARCH_LPC32XX || ARCH_PNX4008
---help---
The Open Host Controller Interface (OHCI) is a standard for accessing
USB 1.1 host controller hardware. It does more in hardware than Intel's
@@ -373,10 +375,15 @@ config USB_OHCI_HCD_PCI
If unsure, say Y.
config USB_OHCI_HCD_SSB
- bool "OHCI support for Broadcom SSB OHCI core"
+ bool "OHCI support for Broadcom SSB OHCI core (DEPRECATED)"
depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) && EXPERIMENTAL
+ select USB_HCD_SSB
+ select USB_OHCI_HCD_PLATFORM
default n
---help---
+ This option is deprecated now and the driver was removed, use
+ USB_HCD_SSB and USB_OHCI_HCD_PLATFORM instead.
+
Support for the Sonics Silicon Backplane (SSB) attached
Broadcom USB OHCI core.
@@ -638,3 +645,27 @@ config USB_OCTEON_OHCI
config USB_OCTEON2_COMMON
bool
default y if USB_OCTEON_EHCI || USB_OCTEON_OHCI
+
+config USB_HCD_BCMA
+ tristate "BCMA usb host driver"
+ depends on BCMA && EXPERIMENTAL
+ select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
+ select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
+ help
+ Enbale support for the EHCI and OCHI host controller on an bcma bus.
+ It converts the bcma driver into two platform device drivers
+ for ehci and ohci.
+
+ If unsure, say N.
+
+config USB_HCD_SSB
+ tristate "SSB usb host driver"
+ depends on SSB && EXPERIMENTAL
+ select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
+ select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
+ help
+ Enbale support for the EHCI and OCHI host controller on an bcma bus.
+ It converts the bcma driver into two platform device drivers
+ for ehci and ohci.
+
+ If unsure, say N.
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 0982bcc140bd..9e0a89ced15c 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -41,3 +41,5 @@ obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o
obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o
obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
obj-$(CONFIG_MIPS_ALCHEMY) += alchemy-common.o
+obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o
+obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o
diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c
new file mode 100644
index 000000000000..443da21d73ca
--- /dev/null
+++ b/drivers/usb/host/bcma-hcd.c
@@ -0,0 +1,335 @@
+/*
+ * Broadcom specific Advanced Microcontroller Bus
+ * Broadcom USB-core driver (BCMA bus glue)
+ *
+ * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Based on ssb-ohci driver
+ * Copyright 2007 Michael Buesch <m@bues.ch>
+ *
+ * Derived from the OHCI-PCI driver
+ * Copyright 1999 Roman Weissgaerber
+ * Copyright 2000-2002 David Brownell
+ * Copyright 1999 Linus Torvalds
+ * Copyright 1999 Gregory P. Smith
+ *
+ * Derived from the USBcore related parts of Broadcom-SB
+ * Copyright 2005-2011 Broadcom Corporation
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+#include <linux/bcma/bcma.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
+
+MODULE_AUTHOR("Hauke Mehrtens");
+MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
+MODULE_LICENSE("GPL");
+
+struct bcma_hcd_device {
+ struct platform_device *ehci_dev;
+ struct platform_device *ohci_dev;
+};
+
+/* Wait for bitmask in a register to get set or cleared.
+ * timeout is in units of ten-microseconds.
+ */
+static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask,
+ int timeout)
+{
+ int i;
+ u32 val;
+
+ for (i = 0; i < timeout; i++) {
+ val = bcma_read32(dev, reg);
+ if ((val & bitmask) == bitmask)
+ return 0;
+ udelay(10);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static void __devinit bcma_hcd_4716wa(struct bcma_device *dev)
+{
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+ /* Work around for 4716 failures. */
+ if (dev->bus->chipinfo.id == 0x4716) {
+ u32 tmp;
+
+ tmp = bcma_cpu_clock(&dev->bus->drv_mips);
+ if (tmp >= 480000000)
+ tmp = 0x1846b; /* set CDR to 0x11(fast) */
+ else if (tmp == 453000000)
+ tmp = 0x1046b; /* set CDR to 0x10(slow) */
+ else
+ tmp = 0;
+
+ /* Change Shim mdio control reg to fix host not acking at
+ * high frequencies
+ */
+ if (tmp) {
+ bcma_write32(dev, 0x524, 0x1); /* write sel to enable */
+ udelay(500);
+
+ bcma_write32(dev, 0x524, tmp);
+ udelay(500);
+ bcma_write32(dev, 0x524, 0x4ab);
+ udelay(500);
+ bcma_read32(dev, 0x528);
+ bcma_write32(dev, 0x528, 0x80000000);
+ }
+ }
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
+}
+
+/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
+static void __devinit bcma_hcd_init_chip(struct bcma_device *dev)
+{
+ u32 tmp;
+
+ /*
+ * USB 2.0 special considerations:
+ *
+ * 1. Since the core supports both OHCI and EHCI functions, it must
+ * only be reset once.
+ *
+ * 2. In addition to the standard SI reset sequence, the Host Control
+ * Register must be programmed to bring the USB core and various
+ * phy components out of reset.
+ */
+ if (!bcma_core_is_enabled(dev)) {
+ bcma_core_enable(dev, 0);
+ mdelay(10);
+ if (dev->id.rev >= 5) {
+ /* Enable Misc PLL */
+ tmp = bcma_read32(dev, 0x1e0);
+ tmp |= 0x100;
+ bcma_write32(dev, 0x1e0, tmp);
+ if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100))
+ printk(KERN_EMERG "Failed to enable misc PPL!\n");
+
+ /* Take out of resets */
+ bcma_write32(dev, 0x200, 0x4ff);
+ udelay(25);
+ bcma_write32(dev, 0x200, 0x6ff);
+ udelay(25);
+
+ /* Make sure digital and AFE are locked in USB PHY */
+ bcma_write32(dev, 0x524, 0x6b);
+ udelay(50);
+ tmp = bcma_read32(dev, 0x524);
+ udelay(50);
+ bcma_write32(dev, 0x524, 0xab);
+ udelay(50);
+ tmp = bcma_read32(dev, 0x524);
+ udelay(50);
+ bcma_write32(dev, 0x524, 0x2b);
+ udelay(50);
+ tmp = bcma_read32(dev, 0x524);
+ udelay(50);
+ bcma_write32(dev, 0x524, 0x10ab);
+ udelay(50);
+ tmp = bcma_read32(dev, 0x524);
+
+ if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) {
+ tmp = bcma_read32(dev, 0x528);
+ printk(KERN_EMERG
+ "USB20H mdio_rddata 0x%08x\n", tmp);
+ }
+ bcma_write32(dev, 0x528, 0x80000000);
+ tmp = bcma_read32(dev, 0x314);
+ udelay(265);
+ bcma_write32(dev, 0x200, 0x7ff);
+ udelay(10);
+
+ /* Take USB and HSIC out of non-driving modes */
+ bcma_write32(dev, 0x510, 0);
+ } else {
+ bcma_write32(dev, 0x200, 0x7ff);
+
+ udelay(1);
+ }
+
+ bcma_hcd_4716wa(dev);
+ }
+}
+
+static const struct usb_ehci_pdata ehci_pdata = {
+};
+
+static const struct usb_ohci_pdata ohci_pdata = {
+};
+
+static struct platform_device * __devinit
+bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr)
+{
+ struct platform_device *hci_dev;
+ struct resource hci_res[2];
+ int ret = -ENOMEM;
+
+ memset(hci_res, 0, sizeof(hci_res));
+
+ hci_res[0].start = addr;
+ hci_res[0].end = hci_res[0].start + 0x1000 - 1;
+ hci_res[0].flags = IORESOURCE_MEM;
+
+ hci_res[1].start = dev->irq;
+ hci_res[1].flags = IORESOURCE_IRQ;
+
+ hci_dev = platform_device_alloc(ohci ? "ohci-platform" :
+ "ehci-platform" , 0);
+ if (!hci_dev)
+ return NULL;
+
+ hci_dev->dev.parent = &dev->dev;
+ hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
+
+ ret = platform_device_add_resources(hci_dev, hci_res,
+ ARRAY_SIZE(hci_res));
+ if (ret)
+ goto err_alloc;
+ if (ohci)
+ ret = platform_device_add_data(hci_dev, &ohci_pdata,
+ sizeof(ohci_pdata));
+ else
+ ret = platform_device_add_data(hci_dev, &ehci_pdata,
+ sizeof(ehci_pdata));
+ if (ret)
+ goto err_alloc;
+ ret = platform_device_add(hci_dev);
+ if (ret)
+ goto err_alloc;
+
+ return hci_dev;
+
+err_alloc:
+ platform_device_put(hci_dev);
+ return ERR_PTR(ret);
+}
+
+static int __devinit bcma_hcd_probe(struct bcma_device *dev)
+{
+ int err;
+ u16 chipid_top;
+ u32 ohci_addr;
+ struct bcma_hcd_device *usb_dev;
+ struct bcma_chipinfo *chipinfo;
+
+ chipinfo = &dev->bus->chipinfo;
+ /* USBcores are only connected on embedded devices. */
+ chipid_top = (chipinfo->id & 0xFF00);
+ if (chipid_top != 0x4700 && chipid_top != 0x5300)
+ return -ENODEV;
+
+ /* TODO: Probably need checks here; is the core connected? */
+
+ if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
+ dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
+ return -EOPNOTSUPP;
+
+ usb_dev = kzalloc(sizeof(struct bcma_hcd_device), GFP_KERNEL);
+ if (!usb_dev)
+ return -ENOMEM;
+
+ bcma_hcd_init_chip(dev);
+
+ /* In AI chips EHCI is addrspace 0, OHCI is 1 */
+ ohci_addr = dev->addr1;
+ if ((chipinfo->id == 0x5357 || chipinfo->id == 0x4749)
+ && chipinfo->rev == 0)
+ ohci_addr = 0x18009000;
+
+ usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr);
+ if (IS_ERR(usb_dev->ohci_dev)) {
+ err = PTR_ERR(usb_dev->ohci_dev);
+ goto err_free_usb_dev;
+ }
+
+ usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr);
+ if (IS_ERR(usb_dev->ehci_dev)) {
+ err = PTR_ERR(usb_dev->ehci_dev);
+ goto err_unregister_ohci_dev;
+ }
+
+ bcma_set_drvdata(dev, usb_dev);
+ return 0;
+
+err_unregister_ohci_dev:
+ platform_device_unregister(usb_dev->ohci_dev);
+err_free_usb_dev:
+ kfree(usb_dev);
+ return err;
+}
+
+static void __devexit bcma_hcd_remove(struct bcma_device *dev)
+{
+ struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
+ struct platform_device *ohci_dev = usb_dev->ohci_dev;
+ struct platform_device *ehci_dev = usb_dev->ehci_dev;
+
+ if (ohci_dev)
+ platform_device_unregister(ohci_dev);
+ if (ehci_dev)
+ platform_device_unregister(ehci_dev);
+
+ bcma_core_disable(dev, 0);
+}
+
+static void bcma_hcd_shutdown(struct bcma_device *dev)
+{
+ bcma_core_disable(dev, 0);
+}
+
+#ifdef CONFIG_PM
+
+static int bcma_hcd_suspend(struct bcma_device *dev)
+{
+ bcma_core_disable(dev, 0);
+
+ return 0;
+}
+
+static int bcma_hcd_resume(struct bcma_device *dev)
+{
+ bcma_core_enable(dev, 0);
+
+ return 0;
+}
+
+#else /* !CONFIG_PM */
+#define bcma_hcd_suspend NULL
+#define bcma_hcd_resume NULL
+#endif /* CONFIG_PM */
+
+static const struct bcma_device_id bcma_hcd_table[] __devinitconst = {
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
+ BCMA_CORETABLE_END
+};
+MODULE_DEVICE_TABLE(bcma, bcma_hcd_table);
+
+static struct bcma_driver bcma_hcd_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = bcma_hcd_table,
+ .probe = bcma_hcd_probe,
+ .remove = __devexit_p(bcma_hcd_remove),
+ .shutdown = bcma_hcd_shutdown,
+ .suspend = bcma_hcd_suspend,
+ .resume = bcma_hcd_resume,
+};
+
+static int __init bcma_hcd_init(void)
+{
+ return bcma_driver_register(&bcma_hcd_driver);
+}
+module_init(bcma_hcd_init);
+
+static void __exit bcma_hcd_exit(void)
+{
+ bcma_driver_unregister(&bcma_hcd_driver);
+}
+module_exit(bcma_hcd_exit);
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 680e1a31fb87..7561966fbdc4 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -1025,10 +1025,8 @@ static ssize_t debug_lpm_write(struct file *file, const char __user *user_buf,
if (strict_strtoul(buf + 5, 16, &hird))
return -EINVAL;
printk(KERN_INFO "setting hird %s %lu\n", buf + 6, hird);
- temp = ehci_readl(ehci, &ehci->regs->command);
- temp &= ~CMD_HIRD;
- temp |= hird << 24;
- ehci_writel(ehci, temp, &ehci->regs->command);
+ ehci->command = (ehci->command & ~CMD_HIRD) | (hird << 24);
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
} else if (strncmp(buf, "disable", 7) == 0) {
if (strict_strtoul(buf + 8, 10, &port))
return -EINVAL;
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index d0a84bd3f3eb..43362577b54a 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -1,6 +1,6 @@
/*
* Copyright 2005-2009 MontaVista Software, Inc.
- * Copyright 2008 Freescale Semiconductor, Inc.
+ * Copyright 2008,2012 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -150,8 +150,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
retval = otg_set_host(ehci->transceiver->otg,
&ehci_to_hcd(ehci)->self);
if (retval) {
- if (ehci->transceiver)
- put_device(ehci->transceiver->dev);
+ usb_put_transceiver(ehci->transceiver);
goto err4;
}
} else {
@@ -195,7 +194,7 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
if (ehci->transceiver) {
otg_set_host(ehci->transceiver->otg, NULL);
- put_device(ehci->transceiver->dev);
+ usb_put_transceiver(ehci->transceiver);
}
usb_remove_hcd(hcd);
@@ -211,22 +210,32 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
usb_put_hcd(hcd);
}
-static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
+static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
enum fsl_usb2_phy_modes phy_mode,
unsigned int port_offset)
{
- u32 portsc;
- struct usb_hcd *hcd = ehci_to_hcd(ehci);
+ u32 portsc, temp;
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
void __iomem *non_ehci = hcd->regs;
- struct fsl_usb2_platform_data *pdata;
+ struct device *dev = hcd->self.controller;
+ struct fsl_usb2_platform_data *pdata = dev->platform_data;
- pdata = hcd->self.controller->platform_data;
+ if (pdata->controller_ver < 0) {
+ dev_warn(hcd->self.controller, "Could not get controller version\n");
+ return;
+ }
portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
switch (phy_mode) {
case FSL_USB2_PHY_ULPI:
+ if (pdata->controller_ver) {
+ /* controller version 1.6 or above */
+ temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+ out_be32(non_ehci + FSL_SOC_USB_CTRL, temp |
+ USB_CTRL_USB_EN | ULPI_PHY_CLK_SEL);
+ }
portsc |= PORT_PTS_ULPI;
break;
case FSL_USB2_PHY_SERIAL:
@@ -236,6 +245,14 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
portsc |= PORT_PTS_PTW;
/* fall through */
case FSL_USB2_PHY_UTMI:
+ if (pdata->controller_ver) {
+ /* controller version 1.6 or above */
+ temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+ out_be32(non_ehci + FSL_SOC_USB_CTRL, temp |
+ UTMI_PHY_EN | USB_CTRL_USB_EN);
+ mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to
+ become stable - 10ms*/
+ }
/* enable UTMI PHY */
if (pdata->have_sysif_regs)
setbits32(non_ehci + FSL_SOC_USB_CTRL,
@@ -276,7 +293,7 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
(pdata->operating_mode == FSL_USB2_DR_OTG))
- ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
+ ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0);
if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
unsigned int chip, rev, svr;
@@ -290,9 +307,9 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
ehci->has_fsl_port_bug = 1;
if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
- ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
+ ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0);
if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
- ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1);
+ ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1);
}
if (pdata->have_sysif_regs) {
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index 863fb0c080d7..88403684d10b 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc.
+/* Copyright (C) 2005-2010,2012 Freescale Semiconductor, Inc.
* Copyright (c) 2005 MontaVista Software
*
* This program is free software; you can redistribute it and/or modify it
@@ -50,4 +50,15 @@
#define CTRL_UTMI_PHY_EN (1<<9)
#define CTRL_PHY_CLK_VALID (1 << 17)
#define SNOOP_SIZE_2GB 0x1e
+
+/* control Register Bit Masks */
+#define ULPI_INT_EN (1<<0)
+#define WU_INT_EN (1<<1)
+#define USB_CTRL_USB_EN (1<<2)
+#define LINE_STATE_FILTER__EN (1<<3)
+#define KEEP_OTG_ON (1<<4)
+#define OTG_PORT (1<<5)
+#define PLL_RESET (1<<8)
+#define UTMI_PHY_EN (1<<9)
+#define ULPI_PHY_CLK_SEL (1<<10)
#endif /* _EHCI_FSL_H */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 4a3bc5b7a06f..b100f5f9f4b6 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -226,8 +226,13 @@ static int ehci_halt (struct ehci_hcd *ehci)
if ((temp & STS_HALT) != 0)
return 0;
+ /*
+ * This routine gets called during probe before ehci->command
+ * has been initialized, so we can't rely on its value.
+ */
+ ehci->command &= ~CMD_RUN;
temp = ehci_readl(ehci, &ehci->regs->command);
- temp &= ~CMD_RUN;
+ temp &= ~(CMD_RUN | CMD_IAAD);
ehci_writel(ehci, temp, &ehci->regs->command);
return handshake (ehci, &ehci->regs->status,
STS_HALT, STS_HALT, 16 * 125);
@@ -363,16 +368,14 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
#endif
/* wait for any schedule enables/disables to take effect */
- temp = ehci_readl(ehci, &ehci->regs->command) << 10;
- temp &= STS_ASS | STS_PSS;
+ temp = (ehci->command << 10) & (STS_ASS | STS_PSS);
if (handshake_on_error_set_halt(ehci, &ehci->regs->status,
STS_ASS | STS_PSS, temp, 16 * 125))
return;
/* then disable anything that's still active */
- temp = ehci_readl(ehci, &ehci->regs->command);
- temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE);
- ehci_writel(ehci, temp, &ehci->regs->command);
+ ehci->command &= ~(CMD_ASE | CMD_PSE);
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
/* hardware can take 16 microframes to turn off ... */
handshake_on_error_set_halt(ehci, &ehci->regs->status,
@@ -417,9 +420,6 @@ static void ehci_iaa_watchdog(unsigned long param)
* CMD_IAAD when it sets STS_IAA.)
*/
cmd = ehci_readl(ehci, &ehci->regs->command);
- if (cmd & CMD_IAAD)
- ehci_writel(ehci, cmd & ~CMD_IAAD,
- &ehci->regs->command);
/* If IAA is set here it either legitimately triggered
* before we cleared IAAD above (but _way_ late, so we'll
@@ -894,11 +894,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
/* complete the unlinking of some qh [4.15.2.3] */
if (status & STS_IAA) {
/* guard against (alleged) silicon errata */
- if (cmd & CMD_IAAD) {
- ehci_writel(ehci, cmd & ~CMD_IAAD,
- &ehci->regs->command);
+ if (cmd & CMD_IAAD)
ehci_dbg(ehci, "IAA with IAAD still set?\n");
- }
if (ehci->reclaim) {
COUNT(ehci->stats.reclaim);
end_unlink_async(ehci);
@@ -1248,6 +1245,13 @@ static int ehci_get_frame (struct usb_hcd *hcd)
}
/*-------------------------------------------------------------------------*/
+/*
+ * The EHCI in ChipIdea HDRC cannot be a separate module or device,
+ * because its registers (and irq) are shared between host/gadget/otg
+ * functions and in order to facilitate role switching we cannot
+ * give the ehci driver exclusive access to those.
+ */
+#ifndef CHIPIDEA_EHCI
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR (DRIVER_AUTHOR);
@@ -1378,6 +1382,11 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_ls1x_driver
#endif
+#ifdef CONFIG_MIPS_SEAD3
+#include "ehci-sead3.c"
+#define PLATFORM_DRIVER ehci_hcd_sead3_driver
+#endif
+
#ifdef CONFIG_USB_EHCI_HCD_PLATFORM
#include "ehci-platform.c"
#define PLATFORM_DRIVER ehci_platform_driver
@@ -1501,3 +1510,4 @@ static void __exit ehci_hcd_cleanup(void)
}
module_exit(ehci_hcd_cleanup);
+#endif /* CHIPIDEA_EHCI */
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 38fe07623152..fc9e7cc6ac9b 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -233,7 +233,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
/* stop schedules, clean any completed work */
if (ehci->rh_state == EHCI_RH_RUNNING)
ehci_quiesce (ehci);
- ehci->command = ehci_readl(ehci, &ehci->regs->command);
ehci_work(ehci);
/* Unlike other USB host controller types, EHCI doesn't have
@@ -374,6 +373,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
/* restore CMD_RUN, framelist size, and irq threshold */
+ ehci->command |= CMD_RUN;
ehci_writel(ehci, ehci->command, &ehci->regs->command);
ehci->rh_state = EHCI_RH_RUNNING;
@@ -531,7 +531,8 @@ static int check_reset_complete (
if (ehci->has_amcc_usb23)
set_ohci_hcfs(ehci, 1);
} else {
- ehci_dbg (ehci, "port %d high speed\n", index + 1);
+ ehci_dbg(ehci, "port %d reset complete, port enabled\n",
+ index + 1);
/* ensure 440EPx ohci controller state is suspended */
if (ehci->has_amcc_usb23)
set_ohci_hcfs(ehci, 0);
@@ -699,6 +700,7 @@ static int ehci_hub_control (
goto error;
wIndex--;
temp = ehci_readl(ehci, status_reg);
+ temp &= ~PORT_RWC_BITS;
/*
* Even if OWNER is set, so the port is owned by the
@@ -712,8 +714,7 @@ static int ehci_hub_control (
ehci_writel(ehci, temp & ~PORT_PE, status_reg);
break;
case USB_PORT_FEAT_C_ENABLE:
- ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_PEC,
- status_reg);
+ ehci_writel(ehci, temp | PORT_PEC, status_reg);
break;
case USB_PORT_FEAT_SUSPEND:
if (temp & PORT_RESET)
@@ -742,7 +743,7 @@ static int ehci_hub_control (
spin_lock_irqsave(&ehci->lock, flags);
}
/* resume signaling for 20 msec */
- temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+ temp &= ~PORT_WAKE_BITS;
ehci_writel(ehci, temp | PORT_RESUME, status_reg);
ehci->reset_done[wIndex] = jiffies
+ msecs_to_jiffies(20);
@@ -752,9 +753,8 @@ static int ehci_hub_control (
break;
case USB_PORT_FEAT_POWER:
if (HCS_PPC (ehci->hcs_params))
- ehci_writel(ehci,
- temp & ~(PORT_RWC_BITS | PORT_POWER),
- status_reg);
+ ehci_writel(ehci, temp & ~PORT_POWER,
+ status_reg);
break;
case USB_PORT_FEAT_C_CONNECTION:
if (ehci->has_lpm) {
@@ -762,12 +762,10 @@ static int ehci_hub_control (
temp &= ~PORT_LPM;
temp &= ~PORT_DEV_ADDR;
}
- ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC,
- status_reg);
+ ehci_writel(ehci, temp | PORT_CSC, status_reg);
break;
case USB_PORT_FEAT_C_OVER_CURRENT:
- ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_OCC,
- status_reg);
+ ehci_writel(ehci, temp | PORT_OCC, status_reg);
break;
case USB_PORT_FEAT_C_RESET:
/* GetPortStatus clears reset */
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 5c78f9e71466..a44294d13494 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -242,15 +242,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
ehci_reset(omap_ehci);
- ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
- if (ret) {
- dev_err(dev, "failed to add hcd with err %d\n", ret);
- goto err_add_hcd;
- }
-
- /* root ports should always stay powered */
- ehci_port_power(omap_ehci, 1);
-
if (pdata->phy_reset) {
/* Hold the PHY in RESET for enough time till
* PHY is settled and ready
@@ -258,12 +249,21 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
udelay(10);
if (gpio_is_valid(pdata->reset_gpio_port[0]))
- gpio_set_value(pdata->reset_gpio_port[0], 1);
+ gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
if (gpio_is_valid(pdata->reset_gpio_port[1]))
- gpio_set_value(pdata->reset_gpio_port[1], 1);
+ gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
}
+ ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ if (ret) {
+ dev_err(dev, "failed to add hcd with err %d\n", ret);
+ goto err_add_hcd;
+ }
+
+ /* root ports should always stay powered */
+ ehci_port_power(omap_ehci, 1);
+
return 0;
err_add_hcd:
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index fe8dc069164e..bc94d7bf072d 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -368,7 +368,9 @@ static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
{
return pdev->class == PCI_CLASS_SERIAL_USB_EHCI &&
pdev->vendor == PCI_VENDOR_ID_INTEL &&
- pdev->device == 0x1E26;
+ (pdev->device == 0x1E26 ||
+ pdev->device == 0x8C2D ||
+ pdev->device == 0x8C26);
}
static void ehci_enable_xhci_companion(void)
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index d238b4e24bb6..dfe881a34ae2 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -75,8 +75,6 @@ static const struct hc_driver ehci_platform_hc_driver = {
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
- .update_device = ehci_update_device,
-
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};
@@ -94,12 +92,12 @@ static int __devinit ehci_platform_probe(struct platform_device *dev)
irq = platform_get_irq(dev, 0);
if (irq < 0) {
- pr_err("no irq provieded");
+ pr_err("no irq provided");
return irq;
}
res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!res_mem) {
- pr_err("no memory recourse provieded");
+ pr_err("no memory recourse provided");
return -ENXIO;
}
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 36ca5077cdf7..4378bf72bbac 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -943,7 +943,8 @@ qh_make (
}
break;
default:
- dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed);
+ ehci_dbg(ehci, "bogus dev %p speed %d\n", urb->dev,
+ urb->dev->speed);
done:
qh_put (qh);
return NULL;
@@ -981,14 +982,12 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
head = ehci->async;
timer_action_done (ehci, TIMER_ASYNC_OFF);
if (!head->qh_next.qh) {
- u32 cmd = ehci_readl(ehci, &ehci->regs->command);
-
- if (!(cmd & CMD_ASE)) {
+ if (!(ehci->command & CMD_ASE)) {
/* in case a clear of CMD_ASE didn't take yet */
(void)handshake(ehci, &ehci->regs->status,
STS_ASS, 0, 150);
- cmd |= CMD_ASE;
- ehci_writel(ehci, cmd, &ehci->regs->command);
+ ehci->command |= CMD_ASE;
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
/* posted write need not be known to HC yet ... */
}
}
@@ -1204,7 +1203,6 @@ static void end_unlink_async (struct ehci_hcd *ehci)
static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
- int cmd = ehci_readl(ehci, &ehci->regs->command);
struct ehci_qh *prev;
#ifdef DEBUG
@@ -1222,8 +1220,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
if (ehci->rh_state != EHCI_RH_HALTED
&& !ehci->reclaim) {
/* ... and CMD_IAAD clear */
- ehci_writel(ehci, cmd & ~CMD_ASE,
- &ehci->regs->command);
+ ehci->command &= ~CMD_ASE;
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
wmb ();
// handshake later, if we need to
timer_action_done (ehci, TIMER_ASYNC_OFF);
@@ -1253,8 +1251,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
return;
}
- cmd |= CMD_IAAD;
- ehci_writel(ehci, cmd, &ehci->regs->command);
+ ehci_writel(ehci, ehci->command | CMD_IAAD, &ehci->regs->command);
(void)ehci_readl(ehci, &ehci->regs->command);
iaa_watchdog_start(ehci);
}
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
index f098e2a291a0..c474cec064e4 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-s5p.c
@@ -232,6 +232,8 @@ static int s5p_ehci_suspend(struct device *dev)
if (pdata && pdata->phy_exit)
pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
+ clk_disable(s5p_ehci->clk);
+
return rc;
}
@@ -243,6 +245,8 @@ static int s5p_ehci_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
+ clk_enable(s5p_ehci->clk);
+
if (pdata && pdata->phy_init)
pdata->phy_init(pdev, S5P_USB_PHY_HOST);
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index a60679cbbf85..33182c6d1ff9 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -481,7 +481,6 @@ static int tt_no_collision (
static int enable_periodic (struct ehci_hcd *ehci)
{
- u32 cmd;
int status;
if (ehci->periodic_sched++)
@@ -497,8 +496,8 @@ static int enable_periodic (struct ehci_hcd *ehci)
return status;
}
- cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE;
- ehci_writel(ehci, cmd, &ehci->regs->command);
+ ehci->command |= CMD_PSE;
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
/* posted write ... PSS happens later */
/* make sure ehci_work scans these */
@@ -511,7 +510,6 @@ static int enable_periodic (struct ehci_hcd *ehci)
static int disable_periodic (struct ehci_hcd *ehci)
{
- u32 cmd;
int status;
if (--ehci->periodic_sched)
@@ -537,8 +535,8 @@ static int disable_periodic (struct ehci_hcd *ehci)
return status;
}
- cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE;
- ehci_writel(ehci, cmd, &ehci->regs->command);
+ ehci->command &= ~CMD_PSE;
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
/* posted write ... */
free_cached_lists(ehci);
@@ -1333,34 +1331,36 @@ sitd_slot_ok (
if (mask & ~0xffff)
return 0;
+ /* check bandwidth */
+ uframe %= period_uframes;
+ frame = uframe >> 3;
+
+#ifdef CONFIG_USB_EHCI_TT_NEWSCHED
+ /* The tt's fullspeed bus bandwidth must be available.
+ * tt_available scheduling guarantees 10+% for control/bulk.
+ */
+ uf = uframe & 7;
+ if (!tt_available(ehci, period_uframes >> 3,
+ stream->udev, frame, uf, stream->tt_usecs))
+ return 0;
+#else
+ /* tt must be idle for start(s), any gap, and csplit.
+ * assume scheduling slop leaves 10+% for control/bulk.
+ */
+ if (!tt_no_collision(ehci, period_uframes >> 3,
+ stream->udev, frame, mask))
+ return 0;
+#endif
+
/* this multi-pass logic is simple, but performance may
* suffer when the schedule data isn't cached.
*/
-
- /* check bandwidth */
- uframe %= period_uframes;
do {
u32 max_used;
frame = uframe >> 3;
uf = uframe & 7;
-#ifdef CONFIG_USB_EHCI_TT_NEWSCHED
- /* The tt's fullspeed bus bandwidth must be available.
- * tt_available scheduling guarantees 10+% for control/bulk.
- */
- if (!tt_available (ehci, period_uframes << 3,
- stream->udev, frame, uf, stream->tt_usecs))
- return 0;
-#else
- /* tt must be idle for start(s), any gap, and csplit.
- * assume scheduling slop leaves 10+% for control/bulk.
- */
- if (!tt_no_collision (ehci, period_uframes << 3,
- stream->udev, frame, mask))
- return 0;
-#endif
-
/* check starts (OUT uses more than one) */
max_used = ehci->uframe_periodic_max - stream->usecs;
for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) {
@@ -2358,7 +2358,8 @@ restart:
* in the previous frame for completions.
*/
if (q.fstn->hw_prev != EHCI_LIST_END(ehci)) {
- dbg ("ignoring completions from FSTNs");
+ ehci_dbg(ehci,
+ "ignoring completions from FSTNs\n");
}
type = Q_NEXT_TYPE(ehci, q.fstn->hw_next);
q = q.fstn->fstn_next;
@@ -2441,7 +2442,7 @@ restart:
q = *q_p;
break;
default:
- dbg ("corrupt type %d frame %d shadow %p",
+ ehci_dbg(ehci, "corrupt type %d frame %d shadow %p\n",
type, frame, q.ptr);
// BUG ();
q.ptr = NULL;
diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c
new file mode 100644
index 000000000000..cc199e87a7a9
--- /dev/null
+++ b/drivers/usb/host/ehci-sead3.c
@@ -0,0 +1,266 @@
+/*
+ * MIPS CI13320A EHCI Host Controller driver
+ * Based on "ehci-au1xxx.c" by K.Boge <karsten.boge@amd.com>
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License 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.
+ */
+
+#include <linux/platform_device.h>
+
+static int ehci_sead3_setup(struct usb_hcd *hcd)
+{
+ int ret;
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+ ehci->caps = hcd->regs + 0x100;
+
+#ifdef __BIG_ENDIAN
+ ehci->big_endian_mmio = 1;
+ ehci->big_endian_desc = 1;
+#endif
+
+ ret = ehci_setup(hcd);
+ if (ret)
+ return ret;
+
+ ehci->need_io_watchdog = 0;
+
+ /* Set burst length to 16 words. */
+ ehci_writel(ehci, 0x1010, &ehci->regs->reserved[1]);
+
+ return ret;
+}
+
+const struct hc_driver ehci_sead3_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "SEAD-3 EHCI",
+ .hcd_priv_size = sizeof(struct ehci_hcd),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = ehci_irq,
+ .flags = HCD_MEMORY | HCD_USB2,
+
+ /*
+ * basic lifecycle operations
+ *
+ */
+ .reset = ehci_sead3_setup,
+ .start = ehci_run,
+ .stop = ehci_stop,
+ .shutdown = ehci_shutdown,
+
+ /*
+ * managing i/o requests and associated device resources
+ */
+ .urb_enqueue = ehci_urb_enqueue,
+ .urb_dequeue = ehci_urb_dequeue,
+ .endpoint_disable = ehci_endpoint_disable,
+ .endpoint_reset = ehci_endpoint_reset,
+
+ /*
+ * scheduling support
+ */
+ .get_frame_number = ehci_get_frame,
+
+ /*
+ * root hub support
+ */
+ .hub_status_data = ehci_hub_status_data,
+ .hub_control = ehci_hub_control,
+ .bus_suspend = ehci_bus_suspend,
+ .bus_resume = ehci_bus_resume,
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
+
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+};
+
+static int ehci_hcd_sead3_drv_probe(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd;
+ struct resource *res;
+ int ret;
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ if (pdev->resource[1].flags != IORESOURCE_IRQ) {
+ pr_debug("resource[1] is not IORESOURCE_IRQ");
+ return -ENOMEM;
+ }
+ hcd = usb_create_hcd(&ehci_sead3_hc_driver, &pdev->dev, "SEAD-3");
+ if (!hcd)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ hcd->rsrc_start = res->start;
+ hcd->rsrc_len = resource_size(res);
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+ pr_debug("request_mem_region failed");
+ ret = -EBUSY;
+ goto err1;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ pr_debug("ioremap failed");
+ ret = -ENOMEM;
+ goto err2;
+ }
+
+ /* Root hub has integrated TT. */
+ hcd->has_tt = 1;
+
+ ret = usb_add_hcd(hcd, pdev->resource[1].start,
+ IRQF_SHARED);
+ if (ret == 0) {
+ platform_set_drvdata(pdev, hcd);
+ return ret;
+ }
+
+ iounmap(hcd->regs);
+err2:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+ usb_put_hcd(hcd);
+ return ret;
+}
+
+static int ehci_hcd_sead3_drv_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);
+ usb_put_hcd(hcd);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int ehci_hcd_sead3_drv_suspend(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ unsigned long flags;
+ int rc = 0;
+
+ if (time_before(jiffies, ehci->next_statechange))
+ msleep(20);
+
+ /* Root hub was already suspended. Disable irq emission and
+ * mark HW unaccessible. The PM and USB cores make sure that
+ * the root hub is either suspended or stopped.
+ */
+ ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
+ spin_lock_irqsave(&ehci->lock, flags);
+ ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ (void)ehci_readl(ehci, &ehci->regs->intr_enable);
+
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ spin_unlock_irqrestore(&ehci->lock, flags);
+
+ /* could save FLADJ in case of Vaux power loss
+ * ... we'd only use it to handle clock skew
+ */
+
+ return rc;
+}
+
+static int ehci_hcd_sead3_drv_resume(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+ /* maybe restore FLADJ. */
+
+ if (time_before(jiffies, ehci->next_statechange))
+ msleep(100);
+
+ /* Mark hardware accessible again as we are out of D3 state by now */
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+ /* If CF is still set, we maintained PCI Vaux power.
+ * Just undo the effect of ehci_pci_suspend().
+ */
+ if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+ int mask = INTR_MASK;
+
+ ehci_prepare_ports_for_controller_resume(ehci);
+ if (!hcd->self.root_hub->do_remote_wakeup)
+ mask &= ~STS_PCD;
+ ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+ ehci_readl(ehci, &ehci->regs->intr_enable);
+ return 0;
+ }
+
+ ehci_dbg(ehci, "lost power, restarting\n");
+ usb_root_hub_lost_power(hcd->self.root_hub);
+
+ /* Else reset, to cope with power loss or flush-to-storage
+ * style "resume" having let BIOS kick in during reboot.
+ */
+ (void) ehci_halt(ehci);
+ (void) ehci_reset(ehci);
+
+ /* emptying the schedule aborts any urbs */
+ spin_lock_irq(&ehci->lock);
+ if (ehci->reclaim)
+ end_unlink_async(ehci);
+ ehci_work(ehci);
+ spin_unlock_irq(&ehci->lock);
+
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+ ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
+
+ /* here we "know" root ports should always stay powered */
+ ehci_port_power(ehci, 1);
+
+ ehci->rh_state = EHCI_RH_SUSPENDED;
+
+ return 0;
+}
+
+static const struct dev_pm_ops sead3_ehci_pmops = {
+ .suspend = ehci_hcd_sead3_drv_suspend,
+ .resume = ehci_hcd_sead3_drv_resume,
+};
+
+#define SEAD3_EHCI_PMOPS (&sead3_ehci_pmops)
+
+#else
+#define SEAD3_EHCI_PMOPS NULL
+#endif
+
+static struct platform_driver ehci_hcd_sead3_driver = {
+ .probe = ehci_hcd_sead3_drv_probe,
+ .remove = ehci_hcd_sead3_drv_remove,
+ .shutdown = usb_hcd_platform_shutdown,
+ .driver = {
+ .name = "sead3-ehci",
+ .owner = THIS_MODULE,
+ .pm = SEAD3_EHCI_PMOPS,
+ }
+};
+
+MODULE_ALIAS("platform:sead3-ehci");
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
index 9d9cf47d80da..ca819cdd0c5e 100644
--- a/drivers/usb/host/ehci-sh.c
+++ b/drivers/usb/host/ehci-sh.c
@@ -11,6 +11,7 @@
*/
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/platform_data/ehci-sh.h>
struct ehci_sh_priv {
struct clk *iclk, *fclk;
@@ -100,6 +101,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
const struct hc_driver *driver = &ehci_sh_hc_driver;
struct resource *res;
struct ehci_sh_priv *priv;
+ struct ehci_sh_platdata *pdata;
struct usb_hcd *hcd;
int irq, ret;
@@ -124,6 +126,9 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
goto fail_create_hcd;
}
+ if (pdev->dev.platform_data != NULL)
+ pdata = pdev->dev.platform_data;
+
/* initialize hcd */
hcd = usb_create_hcd(&ehci_sh_hc_driver, &pdev->dev,
dev_name(&pdev->dev));
@@ -168,6 +173,9 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
clk_enable(priv->fclk);
clk_enable(priv->iclk);
+ if (pdata && pdata->phy_init)
+ pdata->phy_init();
+
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to add hcd");
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index 6e928559169c..37ba8c8d2fd0 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -13,6 +13,7 @@
#include <linux/clk.h>
#include <linux/jiffies.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
@@ -25,12 +26,12 @@ struct spear_ehci {
static void spear_start_ehci(struct spear_ehci *ehci)
{
- clk_enable(ehci->clk);
+ clk_prepare_enable(ehci->clk);
}
static void spear_stop_ehci(struct spear_ehci *ehci)
{
- clk_disable(ehci->clk);
+ clk_disable_unprepare(ehci->clk);
}
static int ehci_spear_setup(struct usb_hcd *hcd)
@@ -168,6 +169,8 @@ static int ehci_spear_drv_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend,
ehci_spear_drv_resume);
+static u64 spear_ehci_dma_mask = DMA_BIT_MASK(32);
+
static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd ;
@@ -175,12 +178,9 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
struct resource *res;
struct clk *usbh_clk;
const struct hc_driver *driver = &ehci_spear_hc_driver;
- int *pdata = pdev->dev.platform_data;
int irq, retval;
char clk_name[20] = "usbh_clk";
-
- if (pdata == NULL)
- return -EFAULT;
+ static int instance = -1;
if (usb_disabled())
return -ENODEV;
@@ -191,8 +191,22 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
goto fail_irq_get;
}
- if (*pdata >= 0)
- sprintf(clk_name, "usbh.%01d_clk", *pdata);
+ /*
+ * Right now device-tree probed devices don't get dma_mask set.
+ * Since shared usb code relies on it, set it here for now.
+ * Once we have dma capability bindings this can go away.
+ */
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &spear_ehci_dma_mask;
+
+ /*
+ * Increment the device instance, when probing via device-tree
+ */
+ if (pdev->id < 0)
+ instance++;
+ else
+ instance = pdev->id;
+ sprintf(clk_name, "usbh.%01d_clk", instance);
usbh_clk = clk_get(NULL, clk_name);
if (IS_ERR(usbh_clk)) {
@@ -277,6 +291,11 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
return 0;
}
+static struct of_device_id spear_ehci_id_table[] __devinitdata = {
+ { .compatible = "st,spear600-ehci", },
+ { },
+};
+
static struct platform_driver spear_ehci_hcd_driver = {
.probe = spear_ehci_hcd_drv_probe,
.remove = spear_ehci_hcd_drv_remove,
@@ -285,6 +304,7 @@ static struct platform_driver spear_ehci_hcd_driver = {
.name = "spear-ehci",
.bus = &platform_bus_type,
.pm = &ehci_spear_pm_ops,
+ .of_match_table = of_match_ptr(spear_ehci_id_table),
}
};
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index f214a80cdee2..4a44bf833611 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -147,18 +147,7 @@ static int tegra_ehci_hub_control(
spin_lock_irqsave(&ehci->lock, flags);
- /*
- * In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits
- * that are write on clear, by writing back the register read value, so
- * USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits
- */
- if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) {
- temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS;
- ehci_writel(ehci, temp & ~PORT_PE, status_reg);
- goto done;
- }
-
- else if (typeReq == GetPortStatus) {
+ if (typeReq == GetPortStatus) {
temp = ehci_readl(ehci, status_reg);
if (tegra->port_resuming && !(temp & PORT_SUSPEND)) {
/* Resume completed, re-enable disconnect detection */
@@ -174,7 +163,7 @@ static int tegra_ehci_hub_control(
goto done;
}
- temp &= ~PORT_WKCONN_E;
+ temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E);
temp |= PORT_WKDISC_E | PORT_WKOC_E;
ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
@@ -319,26 +308,23 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
return retval;
}
-struct temp_buffer {
+struct dma_aligned_buffer {
void *kmalloc_ptr;
void *old_xfer_buffer;
u8 data[0];
};
-static void free_temp_buffer(struct urb *urb)
+static void free_dma_aligned_buffer(struct urb *urb)
{
- enum dma_data_direction dir;
- struct temp_buffer *temp;
+ struct dma_aligned_buffer *temp;
if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
return;
- dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
- temp = container_of(urb->transfer_buffer, struct temp_buffer,
- data);
+ temp = container_of(urb->transfer_buffer,
+ struct dma_aligned_buffer, data);
- if (dir == DMA_FROM_DEVICE)
+ if (usb_urb_dir_in(urb))
memcpy(temp->old_xfer_buffer, temp->data,
urb->transfer_buffer_length);
urb->transfer_buffer = temp->old_xfer_buffer;
@@ -347,10 +333,9 @@ static void free_temp_buffer(struct urb *urb)
urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
}
-static int alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
+static int alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags)
{
- enum dma_data_direction dir;
- struct temp_buffer *temp, *kmalloc_ptr;
+ struct dma_aligned_buffer *temp, *kmalloc_ptr;
size_t kmalloc_size;
if (urb->num_sgs || urb->sg ||
@@ -358,22 +343,19 @@ static int alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
!((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1)))
return 0;
- dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
/* Allocate a buffer with enough padding for alignment */
kmalloc_size = urb->transfer_buffer_length +
- sizeof(struct temp_buffer) + TEGRA_USB_DMA_ALIGN - 1;
+ sizeof(struct dma_aligned_buffer) + TEGRA_USB_DMA_ALIGN - 1;
kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
if (!kmalloc_ptr)
return -ENOMEM;
- /* Position our struct temp_buffer such that data is aligned */
+ /* Position our struct dma_aligned_buffer such that data is aligned */
temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1;
-
temp->kmalloc_ptr = kmalloc_ptr;
temp->old_xfer_buffer = urb->transfer_buffer;
- if (dir == DMA_TO_DEVICE)
+ if (usb_urb_dir_out(urb))
memcpy(temp->data, urb->transfer_buffer,
urb->transfer_buffer_length);
urb->transfer_buffer = temp->data;
@@ -388,13 +370,13 @@ static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
{
int ret;
- ret = alloc_temp_buffer(urb, mem_flags);
+ ret = alloc_dma_aligned_buffer(urb, mem_flags);
if (ret)
return ret;
ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
if (ret)
- free_temp_buffer(urb);
+ free_dma_aligned_buffer(urb);
return ret;
}
@@ -402,49 +384,51 @@ static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
{
usb_hcd_unmap_urb_for_dma(hcd, urb);
- free_temp_buffer(urb);
+ free_dma_aligned_buffer(urb);
}
static const struct hc_driver tegra_ehci_hc_driver = {
.description = hcd_name,
.product_desc = "Tegra EHCI Host Controller",
.hcd_priv_size = sizeof(struct ehci_hcd),
-
.flags = HCD_USB2 | HCD_MEMORY,
- .reset = tegra_ehci_setup,
+ /* standard ehci functions */
.irq = ehci_irq,
-
.start = ehci_run,
.stop = ehci_stop,
- .shutdown = tegra_ehci_shutdown,
.urb_enqueue = ehci_urb_enqueue,
.urb_dequeue = ehci_urb_dequeue,
- .map_urb_for_dma = tegra_ehci_map_urb_for_dma,
- .unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma,
.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 = tegra_ehci_hub_control,
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
+
+ /* modified ehci functions for tegra */
+ .reset = tegra_ehci_setup,
+ .shutdown = tegra_ehci_shutdown,
+ .map_urb_for_dma = tegra_ehci_map_urb_for_dma,
+ .unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma,
+ .hub_control = tegra_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,
};
-static int setup_vbus_gpio(struct platform_device *pdev)
+static int setup_vbus_gpio(struct platform_device *pdev,
+ struct tegra_ehci_platform_data *pdata)
{
int err = 0;
int gpio;
- if (!pdev->dev.of_node)
- return 0;
-
- gpio = of_get_named_gpio(pdev->dev.of_node, "nvidia,vbus-gpio", 0);
+ gpio = pdata->vbus_gpio;
+ if (!gpio_is_valid(gpio))
+ gpio = of_get_named_gpio(pdev->dev.of_node,
+ "nvidia,vbus-gpio", 0);
if (!gpio_is_valid(gpio))
return 0;
@@ -664,7 +648,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &tegra_ehci_dma_mask;
- setup_vbus_gpio(pdev);
+ setup_vbus_gpio(pdev, pdata);
tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL);
if (!tegra)
diff --git a/drivers/usb/host/fhci-tds.c b/drivers/usb/host/fhci-tds.c
index 0ea577bfca2a..c5ed88199292 100644
--- a/drivers/usb/host/fhci-tds.c
+++ b/drivers/usb/host/fhci-tds.c
@@ -155,7 +155,7 @@ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem,
struct endpoint *ep;
struct usb_td __iomem *td;
unsigned long ep_offset;
- char *err_for = "enpoint PRAM";
+ char *err_for = "endpoint PRAM";
int ep_mem_size;
u32 i;
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index ab333ac6071d..22ff6b3a676f 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -119,6 +119,39 @@ error:
static const struct of_device_id fsl_usb2_mph_dr_of_match[];
+static int usb_get_ver_info(struct device_node *np)
+{
+ int ver = -1;
+
+ /*
+ * returns 1 for usb controller version 1.6
+ * returns 2 for usb controller version 2.2
+ * returns 0 otherwise
+ */
+ if (of_device_is_compatible(np, "fsl-usb2-dr")) {
+ if (of_device_is_compatible(np, "fsl-usb2-dr-v1.6"))
+ ver = FSL_USB_VER_1_6;
+ else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.2"))
+ ver = FSL_USB_VER_2_2;
+ else /* for previous controller versions */
+ ver = FSL_USB_VER_OLD;
+
+ if (ver > -1)
+ return ver;
+ }
+
+ if (of_device_is_compatible(np, "fsl-usb2-mph")) {
+ if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6"))
+ ver = FSL_USB_VER_1_6;
+ else if (of_device_is_compatible(np, "fsl-usb2-mph-v2.2"))
+ ver = FSL_USB_VER_2_2;
+ else /* for previous controller versions */
+ ver = FSL_USB_VER_OLD;
+ }
+
+ return ver;
+}
+
static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
{
struct device_node *np = ofdev->dev.of_node;
@@ -166,6 +199,14 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
prop = of_get_property(np, "phy_type", NULL);
pdata->phy_mode = determine_usb_phy(prop);
+ pdata->controller_ver = usb_get_ver_info(np);
+
+ if (pdata->have_sysif_regs) {
+ if (pdata->controller_ver < 0) {
+ dev_warn(&ofdev->dev, "Could not get controller version\n");
+ return -ENODEV;
+ }
+ }
for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) {
if (!dev_data->drivers[i])
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index fc72d44bf787..a35bbddf8968 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/drivers/usb/host/isp1760-hcd.c
@@ -1562,11 +1562,14 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
retval = -ESHUTDOWN;
+ qtd_list_free(&new_qtds);
goto out;
}
retval = usb_hcd_link_urb_to_ep(hcd, urb);
- if (retval)
+ if (retval) {
+ qtd_list_free(&new_qtds);
goto out;
+ }
qh = urb->ep->hcpriv;
if (qh) {
@@ -1584,6 +1587,7 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
if (!qh) {
retval = -ENOMEM;
usb_hcd_unlink_urb_from_ep(hcd, urb);
+ qtd_list_free(&new_qtds);
goto out;
}
list_add_tail(&qh->qh_list, ep_queue);
@@ -1683,6 +1687,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
list_for_each_entry(qtd, &qh->qtd_list, qtd_list)
if (qtd->urb == urb) {
dequeue_urb_from_qtd(hcd, qh, qtd);
+ list_move(&qtd->qtd_list, &qh->qtd_list);
break;
}
@@ -2176,7 +2181,7 @@ static const struct hc_driver isp1760_hc_driver = {
int __init init_kmem_once(void)
{
- urb_listitem_cachep = kmem_cache_create("isp1760 urb_listitem",
+ urb_listitem_cachep = kmem_cache_create("isp1760_urb_listitem",
sizeof(struct urb_listitem), 0, SLAB_TEMPORARY |
SLAB_MEM_SPREAD, NULL);
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
index 4592dc17a9f9..fff114fd5461 100644
--- a/drivers/usb/host/isp1760-if.c
+++ b/drivers/usb/host/isp1760-if.c
@@ -398,6 +398,9 @@ static int __devinit isp1760_plat_probe(struct platform_device *pdev)
hcd = isp1760_register(mem_res->start, mem_size, irq_res->start,
irqflags, -ENOENT,
&pdev->dev, dev_name(&pdev->dev), devflags);
+
+ dev_set_drvdata(&pdev->dev, hcd);
+
if (IS_ERR(hcd)) {
pr_warning("isp1760: Failed to register the HCD device\n");
ret = -ENODEV;
@@ -417,11 +420,16 @@ static int __devexit isp1760_plat_remove(struct platform_device *pdev)
{
struct resource *mem_res;
resource_size_t mem_size;
+ struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev);
+
+ usb_remove_hcd(hcd);
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mem_size = resource_size(mem_res);
release_mem_region(mem_res->start, mem_size);
+ usb_put_hcd(hcd);
+
return 0;
}
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 13ebeca8e73e..a665b3eaa746 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -129,7 +129,7 @@ static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver,
if (!hcd)
return -ENOMEM;
hcd->rsrc_start = pdev->resource[0].start;
- hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
+ hcd->rsrc_len = resource_size(&pdev->resource[0]);
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
pr_debug("request_mem_region failed\n");
@@ -223,7 +223,7 @@ static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd,
/*-------------------------------------------------------------------------*/
static int __devinit
-ohci_at91_start (struct usb_hcd *hcd)
+ohci_at91_reset (struct usb_hcd *hcd)
{
struct at91_usbh_data *board = hcd->self.controller->platform_data;
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
@@ -233,9 +233,18 @@ ohci_at91_start (struct usb_hcd *hcd)
return ret;
ohci->num_ports = board->ports;
+ return 0;
+}
+
+static int __devinit
+ohci_at91_start (struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+ int ret;
if ((ret = ohci_run(ohci)) < 0) {
- err("can't start %s", hcd->self.bus_name);
+ dev_err(hcd->self.controller, "can't start %s\n",
+ hcd->self.bus_name);
ohci_stop(hcd);
return ret;
}
@@ -418,6 +427,7 @@ static const struct hc_driver ohci_at91_hc_driver = {
/*
* basic lifecycle operations
*/
+ .reset = ohci_at91_reset,
.start = ohci_at91_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 4ea63b2cac42..c611699b4aa6 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -37,7 +37,8 @@ static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd)
return ret;
if ((ret = ohci_run(ohci)) < 0) {
- err ("can't start %s", hcd->self.bus_name);
+ dev_err(hcd->self.controller, "can't start %s",
+ hcd->self.bus_name);
ohci_stop(hcd);
return ret;
}
diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c
index 5a00a1e1c6ca..2c9f233047be 100644
--- a/drivers/usb/host/ohci-cns3xxx.c
+++ b/drivers/usb/host/ohci-cns3xxx.c
@@ -41,7 +41,8 @@ cns3xxx_ohci_start(struct usb_hcd *hcd)
ret = ohci_run(ohci);
if (ret < 0) {
- err("can't start %s", hcd->self.bus_name);
+ dev_err(hcd->self.controller, "can't start %s\n",
+ hcd->self.bus_name);
ohci_stop(hcd);
return ret;
}
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 843509778a33..269b1e0f7691 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -454,3 +454,5 @@ static struct platform_driver ohci_hcd_da8xx_driver = {
.name = "ohci",
},
};
+
+MODULE_ALIAS("platform:ohci");
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index e4bcb62b930a..31b81f9eacdc 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -29,14 +29,14 @@ urb_print(struct urb * urb, char * str, int small, int status)
unsigned int pipe= urb->pipe;
if (!urb->dev || !urb->dev->bus) {
- dbg("%s URB: no dev", str);
+ printk(KERN_DEBUG "%s URB: no dev\n", str);
return;
}
#ifndef OHCI_VERBOSE_DEBUG
if (status != 0)
#endif
- dbg("%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d",
+ printk(KERN_DEBUG "%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d\n",
str,
urb,
usb_pipedevice (pipe),
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index 3d63574d2c7e..dbfbd1dfd2e2 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -47,7 +47,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver,
struct usb_hcd *hcd;
if (pdev->resource[1].flags != IORESOURCE_IRQ) {
- dbg("resource[1] is not IORESOURCE_IRQ");
+ dev_dbg(&pdev->dev, "resource[1] is not IORESOURCE_IRQ\n");
return -ENOMEM;
}
@@ -65,14 +65,14 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver,
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
if (hcd->regs == NULL) {
- dbg("ioremap failed");
+ dev_dbg(&pdev->dev, "ioremap failed\n");
retval = -ENOMEM;
goto err2;
}
usb_host_clock = clk_get(&pdev->dev, NULL);
if (IS_ERR(usb_host_clock)) {
- dbg("clk_get failed");
+ dev_dbg(&pdev->dev, "clk_get failed\n");
retval = PTR_ERR(usb_host_clock);
goto err3;
}
@@ -116,7 +116,8 @@ static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd)
return ret;
if ((ret = ohci_run(ohci)) < 0) {
- err("can't start %s", hcd->self.bus_name);
+ dev_err(hcd->self.controller, "can't start %s\n",
+ hcd->self.bus_name);
ohci_stop(hcd);
return ret;
}
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index 37bb20ebb6fc..2909621ea196 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -35,7 +35,8 @@ static int ohci_exynos_start(struct usb_hcd *hcd)
ret = ohci_run(ohci);
if (ret < 0) {
- err("can't start %s", hcd->self.bus_name);
+ dev_err(hcd->self.controller, "can't start %s\n",
+ hcd->self.bus_name);
ohci_stop(hcd);
return ret;
}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 235171f29460..e0adf5c0cf55 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1080,11 +1080,6 @@ MODULE_LICENSE ("GPL");
#define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver
#endif
-#ifdef CONFIG_USB_OHCI_HCD_SSB
-#include "ohci-ssb.c"
-#define SSB_OHCI_DRIVER ssb_ohci_driver
-#endif
-
#ifdef CONFIG_MFD_SM501
#include "ohci-sm501.c"
#define SM501_OHCI_DRIVER ohci_hcd_sm501_driver
@@ -1128,8 +1123,7 @@ MODULE_LICENSE ("GPL");
!defined(SA1111_DRIVER) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(SM501_OHCI_DRIVER) && \
- !defined(TMIO_OHCI_DRIVER) && \
- !defined(SSB_OHCI_DRIVER)
+ !defined(TMIO_OHCI_DRIVER)
#error "missing bus glue for ohci-hcd"
#endif
@@ -1195,12 +1189,6 @@ static int __init ohci_hcd_mod_init(void)
goto error_pci;
#endif
-#ifdef SSB_OHCI_DRIVER
- retval = ssb_driver_register(&SSB_OHCI_DRIVER);
- if (retval)
- goto error_ssb;
-#endif
-
#ifdef SM501_OHCI_DRIVER
retval = platform_driver_register(&SM501_OHCI_DRIVER);
if (retval < 0)
@@ -1224,10 +1212,6 @@ static int __init ohci_hcd_mod_init(void)
platform_driver_unregister(&SM501_OHCI_DRIVER);
error_sm501:
#endif
-#ifdef SSB_OHCI_DRIVER
- ssb_driver_unregister(&SSB_OHCI_DRIVER);
- error_ssb:
-#endif
#ifdef PCI_DRIVER
pci_unregister_driver(&PCI_DRIVER);
error_pci:
@@ -1275,9 +1259,6 @@ static void __exit ohci_hcd_mod_exit(void)
#ifdef SM501_OHCI_DRIVER
platform_driver_unregister(&SM501_OHCI_DRIVER);
#endif
-#ifdef SSB_OHCI_DRIVER
- ssb_driver_unregister(&SSB_OHCI_DRIVER);
-#endif
#ifdef PCI_DRIVER
pci_unregister_driver(&PCI_DRIVER);
#endif
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index 6618de1d881d..1e364ec962fb 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -22,6 +22,8 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
+#include <linux/of.h>
+#include <linux/usb/isp1301.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -29,7 +31,6 @@
#include <mach/platform.h>
#include <mach/irqs.h>
-#include <asm/gpio.h>
#define USB_CONFIG_BASE 0x31020000
#define PWRMAN_BASE 0x40004000
@@ -38,7 +39,9 @@
/* USB_CTRL bit defines */
#define USB_SLAVE_HCLK_EN (1 << 24)
+#define USB_DEV_NEED_CLK_EN (1 << 22)
#define USB_HOST_NEED_CLK_EN (1 << 21)
+#define PAD_CONTROL_LAST_DRIVEN (1 << 19)
#define USB_OTG_CLK_CTRL IO_ADDRESS(USB_CONFIG_BASE + 0xFF4)
#define USB_OTG_CLK_STAT IO_ADDRESS(USB_CONFIG_BASE + 0xFF8)
@@ -56,54 +59,6 @@
#define TRANSPARENT_I2C_EN (1 << 7)
#define HOST_EN (1 << 0)
-/* ISP1301 USB transceiver I2C registers */
-#define ISP1301_MODE_CONTROL_1 0x04 /* u8 read, set, +1 clear */
-
-#define MC1_SPEED_REG (1 << 0)
-#define MC1_SUSPEND_REG (1 << 1)
-#define MC1_DAT_SE0 (1 << 2)
-#define MC1_TRANSPARENT (1 << 3)
-#define MC1_BDIS_ACON_EN (1 << 4)
-#define MC1_OE_INT_EN (1 << 5)
-#define MC1_UART_EN (1 << 6)
-#define MC1_MASK 0x7f
-
-#define ISP1301_MODE_CONTROL_2 0x12 /* u8 read, set, +1 clear */
-
-#define MC2_GLOBAL_PWR_DN (1 << 0)
-#define MC2_SPD_SUSP_CTRL (1 << 1)
-#define MC2_BI_DI (1 << 2)
-#define MC2_TRANSP_BDIR0 (1 << 3)
-#define MC2_TRANSP_BDIR1 (1 << 4)
-#define MC2_AUDIO_EN (1 << 5)
-#define MC2_PSW_EN (1 << 6)
-#define MC2_EN2V7 (1 << 7)
-
-#define ISP1301_OTG_CONTROL_1 0x06 /* u8 read, set, +1 clear */
-# define OTG1_DP_PULLUP (1 << 0)
-# define OTG1_DM_PULLUP (1 << 1)
-# define OTG1_DP_PULLDOWN (1 << 2)
-# define OTG1_DM_PULLDOWN (1 << 3)
-# define OTG1_ID_PULLDOWN (1 << 4)
-# define OTG1_VBUS_DRV (1 << 5)
-# define OTG1_VBUS_DISCHRG (1 << 6)
-# define OTG1_VBUS_CHRG (1 << 7)
-#define ISP1301_OTG_STATUS 0x10 /* u8 readonly */
-# define OTG_B_SESS_END (1 << 6)
-# define OTG_B_SESS_VLD (1 << 7)
-
-#define ISP1301_I2C_ADDR 0x2C
-
-#define ISP1301_I2C_MODE_CONTROL_1 0x4
-#define ISP1301_I2C_MODE_CONTROL_2 0x12
-#define ISP1301_I2C_OTG_CONTROL_1 0x6
-#define ISP1301_I2C_OTG_CONTROL_2 0x10
-#define ISP1301_I2C_INTERRUPT_SOURCE 0x8
-#define ISP1301_I2C_INTERRUPT_LATCH 0xA
-#define ISP1301_I2C_INTERRUPT_FALLING 0xC
-#define ISP1301_I2C_INTERRUPT_RISING 0xE
-#define ISP1301_I2C_REG_CLEAR_ADDR 1
-
/* On LPC32xx, those are undefined */
#ifndef start_int_set_falling_edge
#define start_int_set_falling_edge(irq)
@@ -113,42 +68,12 @@
#define start_int_umask(irq)
#endif
-static struct i2c_driver isp1301_driver;
static struct i2c_client *isp1301_i2c_client;
extern int usb_disabled(void);
-extern int ocpi_enable(void);
static struct clk *usb_clk;
-static const unsigned short normal_i2c[] =
- { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END };
-
-static int isp1301_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- return 0;
-}
-
-static int isp1301_remove(struct i2c_client *client)
-{
- return 0;
-}
-
-static const struct i2c_device_id isp1301_id[] = {
- { "isp1301_nxp", 0 },
- { }
-};
-
-static struct i2c_driver isp1301_driver = {
- .driver = {
- .name = "isp1301_nxp",
- },
- .probe = isp1301_probe,
- .remove = isp1301_remove,
- .id_table = isp1301_id,
-};
-
static void isp1301_configure_pnx4008(void)
{
/* PNX4008 only supports DAT_SE0 USB mode */
@@ -220,7 +145,7 @@ static void isp1301_configure_lpc32xx(void)
ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
/* Enable usb_need_clk clock after transceiver is initialized */
- __raw_writel((__raw_readl(USB_CTRL) | (1 << 22)), USB_CTRL);
+ __raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL);
printk(KERN_INFO "ISP1301 Vendor ID : 0x%04x\n",
i2c_smbus_read_word_data(isp1301_i2c_client, 0x00));
@@ -372,65 +297,55 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev)
struct usb_hcd *hcd = 0;
struct ohci_hcd *ohci;
const struct hc_driver *driver = &ohci_nxp_hc_driver;
- struct i2c_adapter *i2c_adap;
- struct i2c_board_info i2c_info;
-
+ struct resource *res;
int ret = 0, irq;
+ struct device_node *isp1301_node;
- dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (nxp)\n", hcd_name);
- if (usb_disabled()) {
- err("USB is disabled");
- ret = -ENODEV;
- goto out;
+ if (pdev->dev.of_node) {
+ isp1301_node = of_parse_phandle(pdev->dev.of_node,
+ "transceiver", 0);
+ } else {
+ isp1301_node = NULL;
}
- if (pdev->num_resources != 2
- || pdev->resource[0].flags != IORESOURCE_MEM
- || pdev->resource[1].flags != IORESOURCE_IRQ) {
- err("Invalid resource configuration");
- ret = -ENODEV;
+ isp1301_i2c_client = isp1301_get_client(isp1301_node);
+ if (!isp1301_i2c_client) {
+ ret = -EPROBE_DEFER;
goto out;
}
- /* Enable AHB slave USB clock, needed for further USB clock control */
- __raw_writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL);
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
- ret = i2c_add_driver(&isp1301_driver);
- if (ret < 0) {
- err("failed to add ISP1301 driver");
- goto out;
- }
- i2c_adap = i2c_get_adapter(2);
- memset(&i2c_info, 0, sizeof(struct i2c_board_info));
- strlcpy(i2c_info.type, "isp1301_nxp", I2C_NAME_SIZE);
- isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
- normal_i2c, NULL);
- i2c_put_adapter(i2c_adap);
- if (!isp1301_i2c_client) {
- err("failed to connect I2C to ISP1301 USB Transceiver");
+ dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (nxp)\n", hcd_name);
+ if (usb_disabled()) {
+ dev_err(&pdev->dev, "USB is disabled\n");
ret = -ENODEV;
- goto out_i2c_driver;
+ goto out;
}
+ /* Enable AHB slave USB clock, needed for further USB clock control */
+ __raw_writel(USB_SLAVE_HCLK_EN | PAD_CONTROL_LAST_DRIVEN, USB_CTRL);
+
isp1301_configure();
/* Enable USB PLL */
usb_clk = clk_get(&pdev->dev, "ck_pll5");
if (IS_ERR(usb_clk)) {
- err("failed to acquire USB PLL");
+ dev_err(&pdev->dev, "failed to acquire USB PLL\n");
ret = PTR_ERR(usb_clk);
goto out1;
}
ret = clk_enable(usb_clk);
if (ret < 0) {
- err("failed to start USB PLL");
+ dev_err(&pdev->dev, "failed to start USB PLL\n");
goto out2;
}
ret = clk_set_rate(usb_clk, 48000);
if (ret < 0) {
- err("failed to set USB clock rate");
+ dev_err(&pdev->dev, "failed to set USB clock rate\n");
goto out3;
}
@@ -442,9 +357,9 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev)
while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) !=
USB_CLOCK_MASK) ;
- hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev));
+ hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
- err("Failed to allocate HC buffer");
+ dev_err(&pdev->dev, "Failed to allocate HC buffer\n");
ret = -ENOMEM;
goto out3;
}
@@ -452,14 +367,21 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev)
/* Set all USB bits in the Start Enable register */
nxp_set_usb_bits();
- hcd->rsrc_start = pdev->resource[0].start;
- hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- dev_dbg(&pdev->dev, "request_mem_region failed\n");
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Failed to get MEM resource\n");
+ ret = -ENOMEM;
+ goto out4;
+ }
+
+ hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
+ if (!hcd->regs) {
+ dev_err(&pdev->dev, "Failed to devm_request_and_ioremap\n");
ret = -ENOMEM;
goto out4;
}
- hcd->regs = (void __iomem *)pdev->resource[0].start;
+ hcd->rsrc_start = res->start;
+ hcd->rsrc_len = resource_size(res);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -486,10 +408,7 @@ out3:
out2:
clk_put(usb_clk);
out1:
- i2c_unregister_device(isp1301_i2c_client);
isp1301_i2c_client = NULL;
-out_i2c_driver:
- i2c_del_driver(&isp1301_driver);
out:
return ret;
}
@@ -507,7 +426,6 @@ static int usb_hcd_nxp_remove(struct platform_device *pdev)
clk_put(usb_clk);
i2c_unregister_device(isp1301_i2c_client);
isp1301_i2c_client = NULL;
- i2c_del_driver(&isp1301_driver);
platform_set_drvdata(pdev, NULL);
@@ -517,10 +435,19 @@ static int usb_hcd_nxp_remove(struct platform_device *pdev)
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:usb-ohci");
+#ifdef CONFIG_OF
+static const struct of_device_id usb_hcd_nxp_match[] = {
+ { .compatible = "nxp,ohci-nxp" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, usb_hcd_nxp_match);
+#endif
+
static struct platform_driver usb_hcd_nxp_driver = {
.driver = {
.name = "usb-ohci",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(usb_hcd_nxp_match),
},
.probe = usb_hcd_nxp_probe,
.remove = usb_hcd_nxp_remove,
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 96451e41ee8a..9ce35d0d9d5d 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -205,8 +205,9 @@ static int ohci_omap_init(struct usb_hcd *hcd)
need_transceiver = need_transceiver
|| machine_is_omap_h2() || machine_is_omap_h3();
- if (cpu_is_omap16xx())
- ocpi_enable();
+ /* XXX OMAP16xx only */
+ if (config->ocpi_enable)
+ config->ocpi_enable();
#ifdef CONFIG_USB_OTG
if (need_transceiver) {
@@ -217,8 +218,7 @@ static int ohci_omap_init(struct usb_hcd *hcd)
dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n",
ohci->transceiver->label, status);
if (status) {
- if (ohci->transceiver)
- put_device(ohci->transceiver->dev);
+ usb_put_transceiver(ohci->transceiver);
return status;
}
} else {
@@ -405,7 +405,7 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
usb_remove_hcd(hcd);
if (ohci->transceiver) {
(void) otg_set_host(ohci->transceiver->otg, 0);
- put_device(ohci->transceiver->dev);
+ usb_put_transceiver(ohci->transceiver);
}
if (machine_is_omap_osk())
gpio_free(9);
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index ec5c6791c8b4..670c7059c9ae 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -93,13 +93,13 @@ static int __devinit ohci_platform_probe(struct platform_device *dev)
irq = platform_get_irq(dev, 0);
if (irq < 0) {
- pr_err("no irq provieded");
+ pr_err("no irq provided");
return irq;
}
res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!res_mem) {
- pr_err("no memory recourse provieded");
+ pr_err("no memory recourse provided");
return -ENXIO;
}
diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
index f13d08f94d6b..148d27d6a67c 100644
--- a/drivers/usb/host/ohci-pnx8550.c
+++ b/drivers/usb/host/ohci-pnx8550.c
@@ -157,7 +157,8 @@ ohci_pnx8550_start (struct usb_hcd *hcd)
return ret;
if ((ret = ohci_run (ohci)) < 0) {
- err ("can't start %s", hcd->self.bus_name);
+ dev_err(hcd->self.controller, "can't start %s",
+ hcd->self.bus_name);
ohci_stop (hcd);
return ret;
}
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index d24cc89de16f..e27d5ae2b9eb 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -29,7 +29,8 @@ ohci_ppc_of_start(struct usb_hcd *hcd)
return ret;
if ((ret = ohci_run(ohci)) < 0) {
- err("can't start %s", ohci_to_hcd(ohci)->self.bus_name);
+ dev_err(hcd->self.controller, "can't start %s\n",
+ hcd->self.bus_name);
ohci_stop(hcd);
return ret;
}
@@ -236,7 +237,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match);
#if !defined(CONFIG_USB_OHCI_HCD_PPC_OF_BE) && \
!defined(CONFIG_USB_OHCI_HCD_PPC_OF_LE)
-#error "No endianess selected for ppc-of-ohci"
+#error "No endianness selected for ppc-of-ohci"
#endif
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index 1514b7067470..185c39ed81b7 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -130,7 +130,8 @@ ohci_ppc_soc_start(struct usb_hcd *hcd)
return ret;
if ((ret = ohci_run(ohci)) < 0) {
- err("can't start %s", ohci_to_hcd(ohci)->self.bus_name);
+ dev_err(hcd->self.controller, "can't start %s\n",
+ hcd->self.bus_name);
ohci_stop(hcd);
return ret;
}
diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
index 6fd4fa1f19bb..2ee1d8d713d2 100644
--- a/drivers/usb/host/ohci-ps3.c
+++ b/drivers/usb/host/ohci-ps3.c
@@ -45,7 +45,8 @@ static int __devinit ps3_ohci_hc_start(struct usb_hcd *hcd)
result = ohci_run(ohci);
if (result < 0) {
- err("can't start %s", hcd->self.bus_name);
+ dev_err(hcd->self.controller, "can't start %s\n",
+ hcd->self.bus_name);
ohci_stop(hcd);
}
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index c31b2815be1c..e1a3cc6d28dc 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -419,7 +419,8 @@ ohci_pxa27x_start (struct usb_hcd *hcd)
return ret;
if ((ret = ohci_run (ohci)) < 0) {
- err ("can't start %s", hcd->self.bus_name);
+ dev_err(hcd->self.controller, "can't start %s",
+ hcd->self.bus_name);
ohci_stop (hcd);
return ret;
}
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 56dcf069246d..664c869eb096 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -420,7 +420,8 @@ ohci_s3c2410_start(struct usb_hcd *hcd)
ret = ohci_run(ohci);
if (ret < 0) {
- err("can't start %s", hcd->self.bus_name);
+ dev_err(hcd->self.controller, "can't start %s\n",
+ hcd->self.bus_name);
ohci_stop(hcd);
return ret;
}
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index e1004fb37bd9..b6cc92520924 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -46,7 +46,7 @@ static void dump_hci_status(struct usb_hcd *hcd, const char *label)
{
unsigned long status = sa1111_readl(hcd->regs + USB_STATUS);
- dbg("%s USB_STATUS = { %s%s%s%s%s}", label,
+ printk(KERN_DEBUG "%s USB_STATUS = { %s%s%s%s%s}\n", label,
((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""),
((status & USB_STATUS_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""),
((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "),
@@ -193,7 +193,7 @@ static int ohci_hcd_sa1111_probe(struct sa1111_dev *dev)
hcd->rsrc_len = resource_size(&dev->res);
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- dbg("request_mem_region failed");
+ dev_dbg(&dev->dev, "request_mem_region failed\n");
ret = -EBUSY;
goto err1;
}
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
index 84686d90805b..76a20c278362 100644
--- a/drivers/usb/host/ohci-sh.c
+++ b/drivers/usb/host/ohci-sh.c
@@ -88,20 +88,20 @@ static int ohci_hcd_sh_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
- err("platform_get_resource error.");
+ dev_err(&pdev->dev, "platform_get_resource error.\n");
return -ENODEV;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- err("platform_get_irq error.");
+ dev_err(&pdev->dev, "platform_get_irq error.\n");
return -ENODEV;
}
/* initialize hcd */
hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name);
if (!hcd) {
- err("Failed to create hcd");
+ dev_err(&pdev->dev, "Failed to create hcd\n");
return -ENOMEM;
}
@@ -110,7 +110,7 @@ static int ohci_hcd_sh_probe(struct platform_device *pdev)
hcd->rsrc_len = resource_size(res);
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (ret != 0) {
- err("Failed to add hcd");
+ dev_err(&pdev->dev, "Failed to add hcd\n");
usb_put_hcd(hcd);
return ret;
}
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
index 95c16489e883..fc7305ee3c9c 100644
--- a/drivers/usb/host/ohci-spear.c
+++ b/drivers/usb/host/ohci-spear.c
@@ -14,6 +14,7 @@
#include <linux/signal.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/of.h>
struct spear_ohci {
struct ohci_hcd ohci;
@@ -24,12 +25,12 @@ struct spear_ohci {
static void spear_start_ohci(struct spear_ohci *ohci)
{
- clk_enable(ohci->clk);
+ clk_prepare_enable(ohci->clk);
}
static void spear_stop_ohci(struct spear_ohci *ohci)
{
- clk_disable(ohci->clk);
+ clk_disable_unprepare(ohci->clk);
}
static int __devinit ohci_spear_start(struct usb_hcd *hcd)
@@ -90,6 +91,8 @@ static const struct hc_driver ohci_spear_hc_driver = {
.start_port_reset = ohci_start_port_reset,
};
+static u64 spear_ohci_dma_mask = DMA_BIT_MASK(32);
+
static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
{
const struct hc_driver *driver = &ohci_spear_hc_driver;
@@ -98,11 +101,8 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
struct spear_ohci *ohci_p;
struct resource *res;
int retval, irq;
- int *pdata = pdev->dev.platform_data;
char clk_name[20] = "usbh_clk";
-
- if (pdata == NULL)
- return -EFAULT;
+ static int instance = -1;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -110,8 +110,22 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
goto fail_irq_get;
}
- if (*pdata >= 0)
- sprintf(clk_name, "usbh.%01d_clk", *pdata);
+ /*
+ * Right now device-tree probed devices don't get dma_mask set.
+ * Since shared usb code relies on it, set it here for now.
+ * Once we have dma capability bindings this can go away.
+ */
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &spear_ohci_dma_mask;
+
+ /*
+ * Increment the device instance, when probing via device-tree
+ */
+ if (pdev->id < 0)
+ instance++;
+ else
+ instance = pdev->id;
+ sprintf(clk_name, "usbh.%01d_clk", instance);
usbh_clk = clk_get(NULL, clk_name);
if (IS_ERR(usbh_clk)) {
@@ -222,6 +236,11 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev)
}
#endif
+static struct of_device_id spear_ohci_id_table[] __devinitdata = {
+ { .compatible = "st,spear600-ohci", },
+ { },
+};
+
/* Driver definition to register with the platform bus */
static struct platform_driver spear_ohci_hcd_driver = {
.probe = spear_ohci_hcd_drv_probe,
@@ -233,6 +252,7 @@ static struct platform_driver spear_ohci_hcd_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "spear-ohci",
+ .of_match_table = of_match_ptr(spear_ohci_id_table),
},
};
diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
deleted file mode 100644
index 5ba18595d6f7..000000000000
--- a/drivers/usb/host/ohci-ssb.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Sonics Silicon Backplane
- * Broadcom USB-core OHCI driver
- *
- * Copyright 2007 Michael Buesch <m@bues.ch>
- *
- * Derived from the OHCI-PCI driver
- * Copyright 1999 Roman Weissgaerber
- * Copyright 2000-2002 David Brownell
- * Copyright 1999 Linus Torvalds
- * Copyright 1999 Gregory P. Smith
- *
- * Derived from the USBcore related parts of Broadcom-SB
- * Copyright 2005 Broadcom Corporation
- *
- * Licensed under the GNU/GPL. See COPYING for details.
- */
-#include <linux/ssb/ssb.h>
-
-
-#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
-
-struct ssb_ohci_device {
- struct ohci_hcd ohci; /* _must_ be at the beginning. */
-
- u32 enable_flags;
-};
-
-static inline
-struct ssb_ohci_device *hcd_to_ssb_ohci(struct usb_hcd *hcd)
-{
- return (struct ssb_ohci_device *)(hcd->hcd_priv);
-}
-
-
-static int ssb_ohci_reset(struct usb_hcd *hcd)
-{
- struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
- struct ohci_hcd *ohci = &ohcidev->ohci;
- int err;
-
- ohci_hcd_init(ohci);
- err = ohci_init(ohci);
-
- return err;
-}
-
-static int ssb_ohci_start(struct usb_hcd *hcd)
-{
- struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
- struct ohci_hcd *ohci = &ohcidev->ohci;
- int err;
-
- err = ohci_run(ohci);
- if (err < 0) {
- ohci_err(ohci, "can't start\n");
- ohci_stop(hcd);
- }
-
- return err;
-}
-
-static const struct hc_driver ssb_ohci_hc_driver = {
- .description = "ssb-usb-ohci",
- .product_desc = "SSB OHCI Controller",
- .hcd_priv_size = sizeof(struct ssb_ohci_device),
-
- .irq = ohci_irq,
- .flags = HCD_MEMORY | HCD_USB11,
-
- .reset = ssb_ohci_reset,
- .start = ssb_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 void ssb_ohci_detach(struct ssb_device *dev)
-{
- struct usb_hcd *hcd = ssb_get_drvdata(dev);
-
- if (hcd->driver->shutdown)
- hcd->driver->shutdown(hcd);
- usb_remove_hcd(hcd);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- usb_put_hcd(hcd);
- ssb_device_disable(dev, 0);
-}
-
-static int ssb_ohci_attach(struct ssb_device *dev)
-{
- struct ssb_ohci_device *ohcidev;
- struct usb_hcd *hcd;
- int err = -ENOMEM;
- u32 tmp, flags = 0;
-
- if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
- dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
- return -EOPNOTSUPP;
-
- if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
- /* Put the device into host-mode. */
- flags |= SSB_OHCI_TMSLOW_HOSTMODE;
- ssb_device_enable(dev, flags);
- } else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
- /*
- * USB 2.0 special considerations:
- *
- * In addition to the standard SSB reset sequence, the Host
- * Control Register must be programmed to bring the USB core
- * and various phy components out of reset.
- */
- ssb_device_enable(dev, 0);
- ssb_write32(dev, 0x200, 0x7ff);
-
- /* Change Flush control reg */
- tmp = ssb_read32(dev, 0x400);
- tmp &= ~8;
- ssb_write32(dev, 0x400, tmp);
- tmp = ssb_read32(dev, 0x400);
-
- /* Change Shim control reg */
- tmp = ssb_read32(dev, 0x304);
- tmp &= ~0x100;
- ssb_write32(dev, 0x304, tmp);
- tmp = ssb_read32(dev, 0x304);
-
- udelay(1);
-
- /* Work around for 5354 failures */
- if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) {
- /* Change syn01 reg */
- tmp = 0x00fe00fe;
- ssb_write32(dev, 0x894, tmp);
-
- /* Change syn03 reg */
- tmp = ssb_read32(dev, 0x89c);
- tmp |= 0x1;
- ssb_write32(dev, 0x89c, tmp);
- }
- } else
- ssb_device_enable(dev, 0);
-
- hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
- dev_name(dev->dev));
- if (!hcd)
- goto err_dev_disable;
- ohcidev = hcd_to_ssb_ohci(hcd);
- ohcidev->enable_flags = flags;
-
- tmp = ssb_read32(dev, SSB_ADMATCH0);
- hcd->rsrc_start = ssb_admatch_base(tmp);
- hcd->rsrc_len = ssb_admatch_size(tmp);
- hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
- if (!hcd->regs)
- goto err_put_hcd;
- err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED);
- if (err)
- goto err_iounmap;
-
- ssb_set_drvdata(dev, hcd);
-
- return err;
-
-err_iounmap:
- iounmap(hcd->regs);
-err_put_hcd:
- usb_put_hcd(hcd);
-err_dev_disable:
- ssb_device_disable(dev, flags);
- return err;
-}
-
-static int ssb_ohci_probe(struct ssb_device *dev,
- const struct ssb_device_id *id)
-{
- int err;
- u16 chipid_top;
-
- /* USBcores are only connected on embedded devices. */
- chipid_top = (dev->bus->chip_id & 0xFF00);
- if (chipid_top != 0x4700 && chipid_top != 0x5300)
- return -ENODEV;
-
- /* TODO: Probably need checks here; is the core connected? */
-
- if (usb_disabled())
- return -ENODEV;
-
- /* We currently always attach SSB_DEV_USB11_HOSTDEV
- * as HOST OHCI. If we want to attach it as Client device,
- * we must branch here and call into the (yet to
- * be written) Client mode driver. Same for remove(). */
-
- err = ssb_ohci_attach(dev);
-
- return err;
-}
-
-static void ssb_ohci_remove(struct ssb_device *dev)
-{
- ssb_ohci_detach(dev);
-}
-
-#ifdef CONFIG_PM
-
-static int ssb_ohci_suspend(struct ssb_device *dev, pm_message_t state)
-{
- ssb_device_disable(dev, 0);
-
- return 0;
-}
-
-static int ssb_ohci_resume(struct ssb_device *dev)
-{
- struct usb_hcd *hcd = ssb_get_drvdata(dev);
- struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
-
- ssb_device_enable(dev, ohcidev->enable_flags);
-
- ohci_finish_controller_resume(hcd);
- return 0;
-}
-
-#else /* !CONFIG_PM */
-#define ssb_ohci_suspend NULL
-#define ssb_ohci_resume NULL
-#endif /* CONFIG_PM */
-
-static const struct ssb_device_id ssb_ohci_table[] = {
- SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
- SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
- SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
- SSB_DEVTABLE_END
-};
-MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);
-
-static struct ssb_driver ssb_ohci_driver = {
- .name = KBUILD_MODNAME,
- .id_table = ssb_ohci_table,
- .probe = ssb_ohci_probe,
- .remove = ssb_ohci_remove,
- .suspend = ssb_ohci_suspend,
- .resume = ssb_ohci_resume,
-};
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
index 120bfe6ede38..60c2b0722f2e 100644
--- a/drivers/usb/host/ohci-tmio.c
+++ b/drivers/usb/host/ohci-tmio.c
@@ -140,7 +140,8 @@ static int ohci_tmio_start(struct usb_hcd *hcd)
return ret;
if ((ret = ohci_run(ohci)) < 0) {
- err("can't start %s", hcd->self.bus_name);
+ dev_err(hcd->self.controller, "can't start %s\n",
+ hcd->self.bus_name);
ohci_stop(hcd);
return ret;
}
diff --git a/drivers/usb/host/ohci-xls.c b/drivers/usb/host/ohci-xls.c
index a2247867af86..41e378f17c66 100644
--- a/drivers/usb/host/ohci-xls.c
+++ b/drivers/usb/host/ohci-xls.c
@@ -88,7 +88,8 @@ static int __devinit ohci_xls_start(struct usb_hcd *hcd)
ohci = hcd_to_ohci(hcd);
ret = ohci_run(ohci);
if (ret < 0) {
- err("can't start %s", hcd->self.bus_name);
+ dev_err(hcd->self.controller, "can't start %s\n",
+ hcd->self.bus_name);
ohci_stop(hcd);
return ret;
}
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index 3b38030b02a8..4f0f0339532f 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -1399,8 +1399,8 @@ static struct ehci_qh *qh_make(struct oxu_hcd *oxu,
* But interval 1 scheduling is simpler, and
* includes high bandwidth.
*/
- dbg("intr period %d uframes, NYET!",
- urb->interval);
+ oxu_dbg(oxu, "intr period %d uframes, NYET!\n",
+ urb->interval);
goto done;
}
} else {
@@ -1471,7 +1471,7 @@ static struct ehci_qh *qh_make(struct oxu_hcd *oxu,
}
break;
default:
- dbg("bogus dev %p speed %d", urb->dev, urb->dev->speed);
+ oxu_dbg(oxu, "bogus dev %p speed %d\n", urb->dev, urb->dev->speed);
done:
qh_put(qh);
return NULL;
@@ -2307,7 +2307,7 @@ restart:
qh_put(temp.qh);
break;
default:
- dbg("corrupt type %d frame %d shadow %p",
+ oxu_dbg(oxu, "corrupt type %d frame %d shadow %p\n",
type, frame, q.ptr);
q.ptr = NULL;
}
@@ -2991,8 +2991,9 @@ static int oxu_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
/* shouldn't happen often, but ...
* FIXME kill those tds' urbs
*/
- err("can't reschedule qh %p, err %d",
- qh, status);
+ dev_err(hcd->self.controller,
+ "can't reschedule qh %p, err %d\n", qh,
+ status);
}
return status;
}
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 32dada8c8b4f..df0828cb2aa3 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -9,6 +9,7 @@
*/
#include <linux/types.h>
+#include <linux/kconfig.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
@@ -712,12 +713,28 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done,
return -ETIMEDOUT;
}
-bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
+#define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI 0x8C31
+
+bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev)
{
return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI;
}
+
+/* The Intel Lynx Point chipset also has switchable ports. */
+bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev)
+{
+ return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
+ pdev->vendor == PCI_VENDOR_ID_INTEL &&
+ pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI;
+}
+
+bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
+{
+ return usb_is_intel_ppt_switchable_xhci(pdev) ||
+ usb_is_intel_lpt_switchable_xhci(pdev);
+}
EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci);
/*
@@ -742,6 +759,19 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
{
u32 ports_available;
+ /* Don't switchover the ports if the user hasn't compiled the xHCI
+ * driver. Otherwise they will see "dead" USB ports that don't power
+ * the devices.
+ */
+ if (!IS_ENABLED(CONFIG_USB_XHCI_HCD)) {
+ dev_warn(&xhci_pdev->dev,
+ "CONFIG_USB_XHCI_HCD is turned off, "
+ "defaulting to EHCI.\n");
+ dev_warn(&xhci_pdev->dev,
+ "USB 3.0 devices will work at USB 2.0 speeds.\n");
+ return;
+ }
+
ports_available = 0xffffffff;
/* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable
* Register, to turn on SuperSpeed terminations for all
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 2bf1320dc9c3..c868be65e763 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -401,7 +401,7 @@ static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb)
if (r8a66597->address_map & (1 << addr))
continue;
- dbg("alloc_address: r8a66597_addr=%d", addr);
+ dev_dbg(&urb->dev->dev, "alloc_address: r8a66597_addr=%d\n", addr);
r8a66597->address_map |= 1 << addr;
if (make_r8a66597_device(r8a66597, urb, addr) < 0)
@@ -426,7 +426,7 @@ static void free_usb_address(struct r8a66597 *r8a66597,
if (!dev)
return;
- dbg("free_addr: addr=%d", dev->address);
+ dev_dbg(&dev->udev->dev, "free_addr: addr=%d\n", dev->address);
dev->state = USB_STATE_DEFAULT;
r8a66597->address_map &= ~(1 << dev->address);
@@ -819,7 +819,7 @@ static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb,
struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
struct r8a66597_pipe *pipe = hep->hcpriv;
- dbg("enable_pipe:");
+ dev_dbg(&dev->udev->dev, "enable_pipe:\n");
pipe->info = *info;
set_pipe_reg_addr(pipe, R8A66597_PIPE_NO_DMA);
@@ -898,7 +898,7 @@ static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597,
force_dequeue(r8a66597, pipenum, dev->address);
}
- dbg("disable_pipe");
+ dev_dbg(&dev->udev->dev, "disable_pipe\n");
r8a66597->dma_map &= ~(dev->dma_map);
dev->dma_map = 0;
@@ -2264,7 +2264,7 @@ static int r8a66597_bus_suspend(struct usb_hcd *hcd)
struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
int port;
- dbg("%s", __func__);
+ dev_dbg(&r8a66597->device0.udev->dev, "%s\n", __func__);
for (port = 0; port < r8a66597->max_root_hub; port++) {
struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
@@ -2273,7 +2273,7 @@ static int r8a66597_bus_suspend(struct usb_hcd *hcd)
if (!(rh->port & USB_PORT_STAT_ENABLE))
continue;
- dbg("suspend port = %d", port);
+ dev_dbg(&rh->dev->udev->dev, "suspend port = %d\n", port);
r8a66597_bclr(r8a66597, UACT, dvstctr_reg); /* suspend */
rh->port |= USB_PORT_STAT_SUSPEND;
@@ -2295,7 +2295,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
int port;
- dbg("%s", __func__);
+ dev_dbg(&r8a66597->device0.udev->dev, "%s\n", __func__);
for (port = 0; port < r8a66597->max_root_hub; port++) {
struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
@@ -2304,7 +2304,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
if (!(rh->port & USB_PORT_STAT_SUSPEND))
continue;
- dbg("resume port = %d", port);
+ dev_dbg(&rh->dev->udev->dev, "resume port = %d\n", port);
rh->port &= ~USB_PORT_STAT_SUSPEND;
rh->port |= USB_PORT_STAT_C_SUSPEND << 16;
r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
@@ -2360,7 +2360,7 @@ static int r8a66597_suspend(struct device *dev)
struct r8a66597 *r8a66597 = dev_get_drvdata(dev);
int port;
- dbg("%s", __func__);
+ dev_dbg(dev, "%s\n", __func__);
disable_controller(r8a66597);
@@ -2378,7 +2378,7 @@ static int r8a66597_resume(struct device *dev)
struct r8a66597 *r8a66597 = dev_get_drvdata(dev);
struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597);
- dbg("%s", __func__);
+ dev_dbg(dev, "%s\n", __func__);
enable_controller(r8a66597);
usb_root_hub_lost_power(hcd->self.root_hub);
diff --git a/drivers/usb/host/ssb-hcd.c b/drivers/usb/host/ssb-hcd.c
new file mode 100644
index 000000000000..c2a29faba076
--- /dev/null
+++ b/drivers/usb/host/ssb-hcd.c
@@ -0,0 +1,280 @@
+/*
+ * Sonics Silicon Backplane
+ * Broadcom USB-core driver (SSB bus glue)
+ *
+ * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Based on ssb-ohci driver
+ * Copyright 2007 Michael Buesch <m@bues.ch>
+ *
+ * Derived from the OHCI-PCI driver
+ * Copyright 1999 Roman Weissgaerber
+ * Copyright 2000-2002 David Brownell
+ * Copyright 1999 Linus Torvalds
+ * Copyright 1999 Gregory P. Smith
+ *
+ * Derived from the USBcore related parts of Broadcom-SB
+ * Copyright 2005-2011 Broadcom Corporation
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+#include <linux/ssb/ssb.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
+
+MODULE_AUTHOR("Hauke Mehrtens");
+MODULE_DESCRIPTION("Common USB driver for SSB Bus");
+MODULE_LICENSE("GPL");
+
+#define SSB_HCD_TMSLOW_HOSTMODE (1 << 29)
+
+struct ssb_hcd_device {
+ struct platform_device *ehci_dev;
+ struct platform_device *ohci_dev;
+
+ u32 enable_flags;
+};
+
+static void __devinit ssb_hcd_5354wa(struct ssb_device *dev)
+{
+#ifdef CONFIG_SSB_DRIVER_MIPS
+ /* Work around for 5354 failures */
+ if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) {
+ /* Change syn01 reg */
+ ssb_write32(dev, 0x894, 0x00fe00fe);
+
+ /* Change syn03 reg */
+ ssb_write32(dev, 0x89c, ssb_read32(dev, 0x89c) | 0x1);
+ }
+#endif
+}
+
+static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev)
+{
+ if (dev->id.coreid == SSB_DEV_USB20_HOST) {
+ /*
+ * USB 2.0 special considerations:
+ *
+ * In addition to the standard SSB reset sequence, the Host
+ * Control Register must be programmed to bring the USB core
+ * and various phy components out of reset.
+ */
+ ssb_write32(dev, 0x200, 0x7ff);
+
+ /* Change Flush control reg */
+ ssb_write32(dev, 0x400, ssb_read32(dev, 0x400) & ~8);
+ ssb_read32(dev, 0x400);
+
+ /* Change Shim control reg */
+ ssb_write32(dev, 0x304, ssb_read32(dev, 0x304) & ~0x100);
+ ssb_read32(dev, 0x304);
+
+ udelay(1);
+
+ ssb_hcd_5354wa(dev);
+ }
+}
+
+/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
+static u32 __devinit ssb_hcd_init_chip(struct ssb_device *dev)
+{
+ u32 flags = 0;
+
+ if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
+ /* Put the device into host-mode. */
+ flags |= SSB_HCD_TMSLOW_HOSTMODE;
+
+ ssb_device_enable(dev, flags);
+
+ ssb_hcd_usb20wa(dev);
+
+ return flags;
+}
+
+static const struct usb_ehci_pdata ehci_pdata = {
+};
+
+static const struct usb_ohci_pdata ohci_pdata = {
+};
+
+static struct platform_device * __devinit
+ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len)
+{
+ struct platform_device *hci_dev;
+ struct resource hci_res[2];
+ int ret = -ENOMEM;
+
+ memset(hci_res, 0, sizeof(hci_res));
+
+ hci_res[0].start = addr;
+ hci_res[0].end = hci_res[0].start + len - 1;
+ hci_res[0].flags = IORESOURCE_MEM;
+
+ hci_res[1].start = dev->irq;
+ hci_res[1].flags = IORESOURCE_IRQ;
+
+ hci_dev = platform_device_alloc(ohci ? "ohci-platform" :
+ "ehci-platform" , 0);
+ if (!hci_dev)
+ return NULL;
+
+ hci_dev->dev.parent = dev->dev;
+ hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
+
+ ret = platform_device_add_resources(hci_dev, hci_res,
+ ARRAY_SIZE(hci_res));
+ if (ret)
+ goto err_alloc;
+ if (ohci)
+ ret = platform_device_add_data(hci_dev, &ohci_pdata,
+ sizeof(ohci_pdata));
+ else
+ ret = platform_device_add_data(hci_dev, &ehci_pdata,
+ sizeof(ehci_pdata));
+ if (ret)
+ goto err_alloc;
+ ret = platform_device_add(hci_dev);
+ if (ret)
+ goto err_alloc;
+
+ return hci_dev;
+
+err_alloc:
+ platform_device_put(hci_dev);
+ return ERR_PTR(ret);
+}
+
+static int __devinit ssb_hcd_probe(struct ssb_device *dev,
+ const struct ssb_device_id *id)
+{
+ int err, tmp;
+ int start, len;
+ u16 chipid_top;
+ u16 coreid = dev->id.coreid;
+ struct ssb_hcd_device *usb_dev;
+
+ /* USBcores are only connected on embedded devices. */
+ chipid_top = (dev->bus->chip_id & 0xFF00);
+ if (chipid_top != 0x4700 && chipid_top != 0x5300)
+ return -ENODEV;
+
+ /* TODO: Probably need checks here; is the core connected? */
+
+ if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
+ dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
+ return -EOPNOTSUPP;
+
+ usb_dev = kzalloc(sizeof(struct ssb_hcd_device), GFP_KERNEL);
+ if (!usb_dev)
+ return -ENOMEM;
+
+ /* We currently always attach SSB_DEV_USB11_HOSTDEV
+ * as HOST OHCI. If we want to attach it as Client device,
+ * we must branch here and call into the (yet to
+ * be written) Client mode driver. Same for remove(). */
+ usb_dev->enable_flags = ssb_hcd_init_chip(dev);
+
+ tmp = ssb_read32(dev, SSB_ADMATCH0);
+
+ start = ssb_admatch_base(tmp);
+ len = (coreid == SSB_DEV_USB20_HOST) ? 0x800 : ssb_admatch_size(tmp);
+ usb_dev->ohci_dev = ssb_hcd_create_pdev(dev, true, start, len);
+ if (IS_ERR(usb_dev->ohci_dev)) {
+ err = PTR_ERR(usb_dev->ohci_dev);
+ goto err_free_usb_dev;
+ }
+
+ if (coreid == SSB_DEV_USB20_HOST) {
+ start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */
+ usb_dev->ehci_dev = ssb_hcd_create_pdev(dev, false, start, len);
+ if (IS_ERR(usb_dev->ehci_dev)) {
+ err = PTR_ERR(usb_dev->ehci_dev);
+ goto err_unregister_ohci_dev;
+ }
+ }
+
+ ssb_set_drvdata(dev, usb_dev);
+ return 0;
+
+err_unregister_ohci_dev:
+ platform_device_unregister(usb_dev->ohci_dev);
+err_free_usb_dev:
+ kfree(usb_dev);
+ return err;
+}
+
+static void __devexit ssb_hcd_remove(struct ssb_device *dev)
+{
+ struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev);
+ struct platform_device *ohci_dev = usb_dev->ohci_dev;
+ struct platform_device *ehci_dev = usb_dev->ehci_dev;
+
+ if (ohci_dev)
+ platform_device_unregister(ohci_dev);
+ if (ehci_dev)
+ platform_device_unregister(ehci_dev);
+
+ ssb_device_disable(dev, 0);
+}
+
+static void __devexit ssb_hcd_shutdown(struct ssb_device *dev)
+{
+ ssb_device_disable(dev, 0);
+}
+
+#ifdef CONFIG_PM
+
+static int ssb_hcd_suspend(struct ssb_device *dev, pm_message_t state)
+{
+ ssb_device_disable(dev, 0);
+
+ return 0;
+}
+
+static int ssb_hcd_resume(struct ssb_device *dev)
+{
+ struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev);
+
+ ssb_device_enable(dev, usb_dev->enable_flags);
+
+ return 0;
+}
+
+#else /* !CONFIG_PM */
+#define ssb_hcd_suspend NULL
+#define ssb_hcd_resume NULL
+#endif /* CONFIG_PM */
+
+static const struct ssb_device_id ssb_hcd_table[] __devinitconst = {
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
+ SSB_DEVTABLE_END
+};
+MODULE_DEVICE_TABLE(ssb, ssb_hcd_table);
+
+static struct ssb_driver ssb_hcd_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = ssb_hcd_table,
+ .probe = ssb_hcd_probe,
+ .remove = __devexit_p(ssb_hcd_remove),
+ .shutdown = ssb_hcd_shutdown,
+ .suspend = ssb_hcd_suspend,
+ .resume = ssb_hcd_resume,
+};
+
+static int __init ssb_hcd_init(void)
+{
+ return ssb_driver_register(&ssb_hcd_driver);
+}
+module_init(ssb_hcd_init);
+
+static void __exit ssb_hcd_exit(void)
+{
+ ssb_driver_unregister(&ssb_hcd_driver);
+}
+module_exit(ssb_hcd_exit);
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 673ad120c43e..2732ef660c5c 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -475,6 +475,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
struct xhci_bus_state *bus_state;
u16 link_state = 0;
u16 wake_mask = 0;
+ u16 timeout = 0;
max_ports = xhci_get_ports(hcd, &port_array);
bus_state = &xhci->bus_state[hcd_index(hcd)];
@@ -558,6 +559,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
xhci_dbg(xhci, "Resume USB2 port %d\n",
wIndex + 1);
bus_state->resume_done[wIndex] = 0;
+ clear_bit(wIndex, &bus_state->resuming_ports);
xhci_set_link_state(xhci, port_array, wIndex,
XDEV_U0);
xhci_dbg(xhci, "set port %d resume\n",
@@ -622,6 +624,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
link_state = (wIndex & 0xff00) >> 3;
if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK)
wake_mask = wIndex & 0xff00;
+ /* The MSB of wIndex is the U1/U2 timeout */
+ timeout = (wIndex & 0xff00) >> 8;
wIndex &= 0xff;
if (!wIndex || wIndex > max_ports)
goto error;
@@ -746,6 +750,22 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp = xhci_readl(xhci, port_array[wIndex]);
break;
+ case USB_PORT_FEAT_U1_TIMEOUT:
+ if (hcd->speed != HCD_USB3)
+ goto error;
+ temp = xhci_readl(xhci, port_array[wIndex] + 1);
+ temp &= ~PORT_U1_TIMEOUT_MASK;
+ temp |= PORT_U1_TIMEOUT(timeout);
+ xhci_writel(xhci, temp, port_array[wIndex] + 1);
+ break;
+ case USB_PORT_FEAT_U2_TIMEOUT:
+ if (hcd->speed != HCD_USB3)
+ goto error;
+ temp = xhci_readl(xhci, port_array[wIndex] + 1);
+ temp &= ~PORT_U2_TIMEOUT_MASK;
+ temp |= PORT_U2_TIMEOUT(timeout);
+ xhci_writel(xhci, temp, port_array[wIndex] + 1);
+ break;
default:
goto error;
}
@@ -845,7 +865,12 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
/* Initial status is no changes */
retval = (max_ports + 8) / 8;
memset(buf, 0, retval);
- status = 0;
+
+ /*
+ * Inform the usbcore about resume-in-progress by returning
+ * a non-zero value even if there are no status changes.
+ */
+ status = bus_state->resuming_ports;
mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC;
@@ -885,15 +910,11 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
spin_lock_irqsave(&xhci->lock, flags);
if (hcd->self.root_hub->do_remote_wakeup) {
- port_index = max_ports;
- while (port_index--) {
- if (bus_state->resume_done[port_index] != 0) {
- spin_unlock_irqrestore(&xhci->lock, flags);
- xhci_dbg(xhci, "suspend failed because "
- "port %d is resuming\n",
- port_index + 1);
- return -EBUSY;
- }
+ if (bus_state->resuming_ports) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ xhci_dbg(xhci, "suspend failed because "
+ "a port is resuming\n");
+ return -EBUSY;
}
}
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 68eaa908ac8e..ec4338eec826 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1791,6 +1791,14 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
{
struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
struct dev_info *dev_info, *next;
+ struct list_head *tt_list_head;
+ struct list_head *tt;
+ struct list_head *endpoints;
+ struct list_head *ep, *q;
+ struct xhci_tt_bw_info *tt_info;
+ struct xhci_interval_bw_table *bwt;
+ struct xhci_virt_ep *virt_ep;
+
unsigned long flags;
int size;
int i;
@@ -1807,6 +1815,9 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci->event_ring = NULL;
xhci_dbg(xhci, "Freed event ring\n");
+ if (xhci->lpm_command)
+ xhci_free_command(xhci, xhci->lpm_command);
+ xhci->cmd_ring_reserved_trbs = 0;
if (xhci->cmd_ring)
xhci_ring_free(xhci, xhci->cmd_ring);
xhci->cmd_ring = NULL;
@@ -1849,8 +1860,26 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
}
spin_unlock_irqrestore(&xhci->lock, flags);
+ bwt = &xhci->rh_bw->bw_table;
+ for (i = 0; i < XHCI_MAX_INTERVAL; i++) {
+ endpoints = &bwt->interval_bw[i].endpoints;
+ list_for_each_safe(ep, q, endpoints) {
+ virt_ep = list_entry(ep, struct xhci_virt_ep, bw_endpoint_list);
+ list_del(&virt_ep->bw_endpoint_list);
+ kfree(virt_ep);
+ }
+ }
+
+ tt_list_head = &xhci->rh_bw->tts;
+ list_for_each_safe(tt, q, tt_list_head) {
+ tt_info = list_entry(tt, struct xhci_tt_bw_info, tt_list);
+ list_del(tt);
+ kfree(tt_info);
+ }
+
xhci->num_usb2_ports = 0;
xhci->num_usb3_ports = 0;
+ xhci->num_active_eps = 0;
kfree(xhci->usb2_ports);
kfree(xhci->usb3_ports);
kfree(xhci->port_array);
@@ -2350,6 +2379,16 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
xhci_dbg_cmd_ptrs(xhci);
+ xhci->lpm_command = xhci_alloc_command(xhci, true, true, flags);
+ if (!xhci->lpm_command)
+ goto fail;
+
+ /* Reserve one command ring TRB for disabling LPM.
+ * Since the USB core grabs the shared usb_bus bandwidth mutex before
+ * disabling LPM, we only need to reserve one TRB for all devices.
+ */
+ xhci->cmd_ring_reserved_trbs++;
+
val = xhci_readl(xhci, &xhci->cap_regs->db_off);
val &= DBOFF_MASK;
xhci_dbg(xhci, "// Doorbell array is located at offset 0x%x"
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 7a856a767e77..18b231b0c5d3 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -72,6 +72,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci_dbg(xhci, "QUIRK: Fresco Logic revision %u "
"has broken MSI implementation\n",
pdev->revision);
+ xhci->quirks |= XHCI_TRUST_TX_LENGTH;
}
if (pdev->vendor == PCI_VENDOR_ID_NEC)
@@ -83,6 +84,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
/* AMD PLL quirk */
if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info())
xhci->quirks |= XHCI_AMD_PLL_FIX;
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
+ xhci->quirks |= XHCI_LPM_SUPPORT;
+ xhci->quirks |= XHCI_INTEL_HOST;
+ }
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) {
xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
@@ -169,6 +174,13 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (retval)
goto put_usb3_hcd;
/* Roothub already marked as USB 3.0 speed */
+
+ /* We know the LPM timeout algorithms for this host, let the USB core
+ * enable and disable LPM for devices under the USB 3.0 roothub.
+ */
+ if (xhci->quirks & XHCI_LPM_SUPPORT)
+ hcd_to_bus(xhci->shared_hcd)->root_hub->lpm_capable = 1;
+
return 0;
put_usb3_hcd:
@@ -292,6 +304,8 @@ static const struct hc_driver xhci_pci_hc_driver = {
*/
.update_device = xhci_update_device,
.set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm,
+ .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout,
+ .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 3d9422f16a20..23b4aefd1036 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1377,6 +1377,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
xhci_dbg(xhci, "resume HS port %d\n", port_id);
bus_state->resume_done[faked_port_index] = jiffies +
msecs_to_jiffies(20);
+ set_bit(faked_port_index, &bus_state->resuming_ports);
mod_timer(&hcd->rh_timer,
bus_state->resume_done[faked_port_index]);
/* Do the rest in GetPortStatus */
@@ -1786,8 +1787,12 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
/* handle completion code */
switch (trb_comp_code) {
case COMP_SUCCESS:
- frame->status = 0;
- break;
+ if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
+ frame->status = 0;
+ break;
+ }
+ if ((xhci->quirks & XHCI_TRUST_TX_LENGTH))
+ trb_comp_code = COMP_SHORT_TX;
case COMP_SHORT_TX:
frame->status = td->urb->transfer_flags & URB_SHORT_NOT_OK ?
-EREMOTEIO : 0;
@@ -1803,6 +1808,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
break;
case COMP_DEV_ERR:
case COMP_STALL:
+ case COMP_TX_ERR:
frame->status = -EPROTO;
skip_td = true;
break;
@@ -1883,13 +1889,16 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
switch (trb_comp_code) {
case COMP_SUCCESS:
/* Double check that the HW transferred everything. */
- if (event_trb != td->last_trb) {
+ if (event_trb != td->last_trb ||
+ TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
xhci_warn(xhci, "WARN Successful completion "
"on short TX\n");
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
*status = -EREMOTEIO;
else
*status = 0;
+ if ((xhci->quirks & XHCI_TRUST_TX_LENGTH))
+ trb_comp_code = COMP_SHORT_TX;
} else {
*status = 0;
}
@@ -2048,6 +2057,13 @@ static int handle_tx_event(struct xhci_hcd *xhci,
* transfer type
*/
case COMP_SUCCESS:
+ if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
+ break;
+ if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
+ trb_comp_code = COMP_SHORT_TX;
+ else
+ xhci_warn(xhci, "WARN Successful completion on short TX: "
+ "needs XHCI_TRUST_TX_LENGTH quirk?\n");
case COMP_SHORT_TX:
break;
case COMP_STOP:
@@ -2270,7 +2286,7 @@ cleanup:
(status != 0 &&
!usb_endpoint_xfer_isoc(&urb->ep->desc)))
xhci_dbg(xhci, "Giveback URB %p, len = %d, "
- "expected = %x, status = %d\n",
+ "expected = %d, status = %d\n",
urb, urb->actual_length,
urb->transfer_buffer_length,
status);
@@ -3593,12 +3609,12 @@ int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
/* Queue an evaluate context command TRB */
int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
- u32 slot_id)
+ u32 slot_id, bool command_must_succeed)
{
return queue_command(xhci, lower_32_bits(in_ctx_ptr),
upper_32_bits(in_ctx_ptr), 0,
TRB_TYPE(TRB_EVAL_CONTEXT) | SLOT_ID_FOR_TRB(slot_id),
- false);
+ command_must_succeed);
}
/*
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 36641a7f2371..afdc73ee84a6 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -152,7 +152,7 @@ int xhci_reset(struct xhci_hcd *xhci)
{
u32 command;
u32 state;
- int ret;
+ int ret, i;
state = xhci_readl(xhci, &xhci->op_regs->status);
if ((state & STS_HALT) == 0) {
@@ -175,7 +175,15 @@ int xhci_reset(struct xhci_hcd *xhci)
* xHCI cannot write to any doorbells or operational registers other
* than status until the "Controller Not Ready" flag is cleared.
*/
- return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
+ ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
+
+ for (i = 0; i < 2; ++i) {
+ xhci->bus_state[i].port_c_suspend = 0;
+ xhci->bus_state[i].suspended_ports = 0;
+ xhci->bus_state[i].resuming_ports = 0;
+ }
+
+ return ret;
}
#ifdef CONFIG_PCI
@@ -2438,7 +2446,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
udev->slot_id, must_succeed);
else
ret = xhci_queue_evaluate_context(xhci, in_ctx->dma,
- udev->slot_id);
+ udev->slot_id, must_succeed);
if (ret < 0) {
if (command)
list_del(&command->cmd_list);
@@ -3863,6 +3871,474 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
#endif /* CONFIG_USB_SUSPEND */
+/*---------------------- USB 3.0 Link PM functions ------------------------*/
+
+#ifdef CONFIG_PM
+/* Service interval in nanoseconds = 2^(bInterval - 1) * 125us * 1000ns / 1us */
+static unsigned long long xhci_service_interval_to_ns(
+ struct usb_endpoint_descriptor *desc)
+{
+ return (1 << (desc->bInterval - 1)) * 125 * 1000;
+}
+
+static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
+ enum usb3_link_state state)
+{
+ unsigned long long sel;
+ unsigned long long pel;
+ unsigned int max_sel_pel;
+ char *state_name;
+
+ switch (state) {
+ case USB3_LPM_U1:
+ /* Convert SEL and PEL stored in nanoseconds to microseconds */
+ sel = DIV_ROUND_UP(udev->u1_params.sel, 1000);
+ pel = DIV_ROUND_UP(udev->u1_params.pel, 1000);
+ max_sel_pel = USB3_LPM_MAX_U1_SEL_PEL;
+ state_name = "U1";
+ break;
+ case USB3_LPM_U2:
+ sel = DIV_ROUND_UP(udev->u2_params.sel, 1000);
+ pel = DIV_ROUND_UP(udev->u2_params.pel, 1000);
+ max_sel_pel = USB3_LPM_MAX_U2_SEL_PEL;
+ state_name = "U2";
+ break;
+ default:
+ dev_warn(&udev->dev, "%s: Can't get timeout for non-U1 or U2 state.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (sel <= max_sel_pel && pel <= max_sel_pel)
+ return USB3_LPM_DEVICE_INITIATED;
+
+ if (sel > max_sel_pel)
+ dev_dbg(&udev->dev, "Device-initiated %s disabled "
+ "due to long SEL %llu ms\n",
+ state_name, sel);
+ else
+ dev_dbg(&udev->dev, "Device-initiated %s disabled "
+ "due to long PEL %llu\n ms",
+ state_name, pel);
+ return USB3_LPM_DISABLED;
+}
+
+/* Returns the hub-encoded U1 timeout value.
+ * The U1 timeout should be the maximum of the following values:
+ * - For control endpoints, U1 system exit latency (SEL) * 3
+ * - For bulk endpoints, U1 SEL * 5
+ * - For interrupt endpoints:
+ * - Notification EPs, U1 SEL * 3
+ * - Periodic EPs, max(105% of bInterval, U1 SEL * 2)
+ * - For isochronous endpoints, max(105% of bInterval, U1 SEL * 2)
+ */
+static u16 xhci_calculate_intel_u1_timeout(struct usb_device *udev,
+ struct usb_endpoint_descriptor *desc)
+{
+ unsigned long long timeout_ns;
+ int ep_type;
+ int intr_type;
+
+ ep_type = usb_endpoint_type(desc);
+ switch (ep_type) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ timeout_ns = udev->u1_params.sel * 3;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ timeout_ns = udev->u1_params.sel * 5;
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ intr_type = usb_endpoint_interrupt_type(desc);
+ if (intr_type == USB_ENDPOINT_INTR_NOTIFICATION) {
+ timeout_ns = udev->u1_params.sel * 3;
+ break;
+ }
+ /* Otherwise the calculation is the same as isoc eps */
+ case USB_ENDPOINT_XFER_ISOC:
+ timeout_ns = xhci_service_interval_to_ns(desc);
+ timeout_ns = DIV_ROUND_UP_ULL(timeout_ns * 105, 100);
+ if (timeout_ns < udev->u1_params.sel * 2)
+ timeout_ns = udev->u1_params.sel * 2;
+ break;
+ default:
+ return 0;
+ }
+
+ /* The U1 timeout is encoded in 1us intervals. */
+ timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 1000);
+ /* Don't return a timeout of zero, because that's USB3_LPM_DISABLED. */
+ if (timeout_ns == USB3_LPM_DISABLED)
+ timeout_ns++;
+
+ /* If the necessary timeout value is bigger than what we can set in the
+ * USB 3.0 hub, we have to disable hub-initiated U1.
+ */
+ if (timeout_ns <= USB3_LPM_U1_MAX_TIMEOUT)
+ return timeout_ns;
+ dev_dbg(&udev->dev, "Hub-initiated U1 disabled "
+ "due to long timeout %llu ms\n", timeout_ns);
+ return xhci_get_timeout_no_hub_lpm(udev, USB3_LPM_U1);
+}
+
+/* Returns the hub-encoded U2 timeout value.
+ * The U2 timeout should be the maximum of:
+ * - 10 ms (to avoid the bandwidth impact on the scheduler)
+ * - largest bInterval of any active periodic endpoint (to avoid going
+ * into lower power link states between intervals).
+ * - the U2 Exit Latency of the device
+ */
+static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
+ struct usb_endpoint_descriptor *desc)
+{
+ unsigned long long timeout_ns;
+ unsigned long long u2_del_ns;
+
+ timeout_ns = 10 * 1000 * 1000;
+
+ if ((usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) &&
+ (xhci_service_interval_to_ns(desc) > timeout_ns))
+ timeout_ns = xhci_service_interval_to_ns(desc);
+
+ u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000;
+ if (u2_del_ns > timeout_ns)
+ timeout_ns = u2_del_ns;
+
+ /* The U2 timeout is encoded in 256us intervals */
+ timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 256 * 1000);
+ /* If the necessary timeout value is bigger than what we can set in the
+ * USB 3.0 hub, we have to disable hub-initiated U2.
+ */
+ if (timeout_ns <= USB3_LPM_U2_MAX_TIMEOUT)
+ return timeout_ns;
+ dev_dbg(&udev->dev, "Hub-initiated U2 disabled "
+ "due to long timeout %llu ms\n", timeout_ns);
+ return xhci_get_timeout_no_hub_lpm(udev, USB3_LPM_U2);
+}
+
+static u16 xhci_call_host_update_timeout_for_endpoint(struct xhci_hcd *xhci,
+ struct usb_device *udev,
+ struct usb_endpoint_descriptor *desc,
+ enum usb3_link_state state,
+ u16 *timeout)
+{
+ if (state == USB3_LPM_U1) {
+ if (xhci->quirks & XHCI_INTEL_HOST)
+ return xhci_calculate_intel_u1_timeout(udev, desc);
+ } else {
+ if (xhci->quirks & XHCI_INTEL_HOST)
+ return xhci_calculate_intel_u2_timeout(udev, desc);
+ }
+
+ return USB3_LPM_DISABLED;
+}
+
+static int xhci_update_timeout_for_endpoint(struct xhci_hcd *xhci,
+ struct usb_device *udev,
+ struct usb_endpoint_descriptor *desc,
+ enum usb3_link_state state,
+ u16 *timeout)
+{
+ u16 alt_timeout;
+
+ alt_timeout = xhci_call_host_update_timeout_for_endpoint(xhci, udev,
+ desc, state, timeout);
+
+ /* If we found we can't enable hub-initiated LPM, or
+ * the U1 or U2 exit latency was too high to allow
+ * device-initiated LPM as well, just stop searching.
+ */
+ if (alt_timeout == USB3_LPM_DISABLED ||
+ alt_timeout == USB3_LPM_DEVICE_INITIATED) {
+ *timeout = alt_timeout;
+ return -E2BIG;
+ }
+ if (alt_timeout > *timeout)
+ *timeout = alt_timeout;
+ return 0;
+}
+
+static int xhci_update_timeout_for_interface(struct xhci_hcd *xhci,
+ struct usb_device *udev,
+ struct usb_host_interface *alt,
+ enum usb3_link_state state,
+ u16 *timeout)
+{
+ int j;
+
+ for (j = 0; j < alt->desc.bNumEndpoints; j++) {
+ if (xhci_update_timeout_for_endpoint(xhci, udev,
+ &alt->endpoint[j].desc, state, timeout))
+ return -E2BIG;
+ continue;
+ }
+ return 0;
+}
+
+static int xhci_check_intel_tier_policy(struct usb_device *udev,
+ enum usb3_link_state state)
+{
+ struct usb_device *parent;
+ unsigned int num_hubs;
+
+ if (state == USB3_LPM_U2)
+ return 0;
+
+ /* Don't enable U1 if the device is on a 2nd tier hub or lower. */
+ for (parent = udev->parent, num_hubs = 0; parent->parent;
+ parent = parent->parent)
+ num_hubs++;
+
+ if (num_hubs < 2)
+ return 0;
+
+ dev_dbg(&udev->dev, "Disabling U1 link state for device"
+ " below second-tier hub.\n");
+ dev_dbg(&udev->dev, "Plug device into first-tier hub "
+ "to decrease power consumption.\n");
+ return -E2BIG;
+}
+
+static int xhci_check_tier_policy(struct xhci_hcd *xhci,
+ struct usb_device *udev,
+ enum usb3_link_state state)
+{
+ if (xhci->quirks & XHCI_INTEL_HOST)
+ return xhci_check_intel_tier_policy(udev, state);
+ return -EINVAL;
+}
+
+/* Returns the U1 or U2 timeout that should be enabled.
+ * If the tier check or timeout setting functions return with a non-zero exit
+ * code, that means the timeout value has been finalized and we shouldn't look
+ * at any more endpoints.
+ */
+static u16 xhci_calculate_lpm_timeout(struct usb_hcd *hcd,
+ struct usb_device *udev, enum usb3_link_state state)
+{
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct usb_host_config *config;
+ char *state_name;
+ int i;
+ u16 timeout = USB3_LPM_DISABLED;
+
+ if (state == USB3_LPM_U1)
+ state_name = "U1";
+ else if (state == USB3_LPM_U2)
+ state_name = "U2";
+ else {
+ dev_warn(&udev->dev, "Can't enable unknown link state %i\n",
+ state);
+ return timeout;
+ }
+
+ if (xhci_check_tier_policy(xhci, udev, state) < 0)
+ return timeout;
+
+ /* Gather some information about the currently installed configuration
+ * and alternate interface settings.
+ */
+ if (xhci_update_timeout_for_endpoint(xhci, udev, &udev->ep0.desc,
+ state, &timeout))
+ return timeout;
+
+ config = udev->actconfig;
+ if (!config)
+ return timeout;
+
+ for (i = 0; i < USB_MAXINTERFACES; i++) {
+ struct usb_driver *driver;
+ struct usb_interface *intf = config->interface[i];
+
+ if (!intf)
+ continue;
+
+ /* Check if any currently bound drivers want hub-initiated LPM
+ * disabled.
+ */
+ if (intf->dev.driver) {
+ driver = to_usb_driver(intf->dev.driver);
+ if (driver && driver->disable_hub_initiated_lpm) {
+ dev_dbg(&udev->dev, "Hub-initiated %s disabled "
+ "at request of driver %s\n",
+ state_name, driver->name);
+ return xhci_get_timeout_no_hub_lpm(udev, state);
+ }
+ }
+
+ /* Not sure how this could happen... */
+ if (!intf->cur_altsetting)
+ continue;
+
+ if (xhci_update_timeout_for_interface(xhci, udev,
+ intf->cur_altsetting,
+ state, &timeout))
+ return timeout;
+ }
+ return timeout;
+}
+
+/*
+ * Issue an Evaluate Context command to change the Maximum Exit Latency in the
+ * slot context. If that succeeds, store the new MEL in the xhci_virt_device.
+ */
+static int xhci_change_max_exit_latency(struct xhci_hcd *xhci,
+ struct usb_device *udev, u16 max_exit_latency)
+{
+ struct xhci_virt_device *virt_dev;
+ struct xhci_command *command;
+ struct xhci_input_control_ctx *ctrl_ctx;
+ struct xhci_slot_ctx *slot_ctx;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&xhci->lock, flags);
+ if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ return 0;
+ }
+
+ /* Attempt to issue an Evaluate Context command to change the MEL. */
+ virt_dev = xhci->devs[udev->slot_id];
+ command = xhci->lpm_command;
+ xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+
+ ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx);
+ ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
+ slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx);
+ slot_ctx->dev_info2 &= cpu_to_le32(~((u32) MAX_EXIT));
+ slot_ctx->dev_info2 |= cpu_to_le32(max_exit_latency);
+
+ xhci_dbg(xhci, "Set up evaluate context for LPM MEL change.\n");
+ xhci_dbg(xhci, "Slot %u Input Context:\n", udev->slot_id);
+ xhci_dbg_ctx(xhci, command->in_ctx, 0);
+
+ /* Issue and wait for the evaluate context command. */
+ ret = xhci_configure_endpoint(xhci, udev, command,
+ true, true);
+ xhci_dbg(xhci, "Slot %u Output Context:\n", udev->slot_id);
+ xhci_dbg_ctx(xhci, virt_dev->out_ctx, 0);
+
+ if (!ret) {
+ spin_lock_irqsave(&xhci->lock, flags);
+ virt_dev->current_mel = max_exit_latency;
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ }
+ return ret;
+}
+
+static int calculate_max_exit_latency(struct usb_device *udev,
+ enum usb3_link_state state_changed,
+ u16 hub_encoded_timeout)
+{
+ unsigned long long u1_mel_us = 0;
+ unsigned long long u2_mel_us = 0;
+ unsigned long long mel_us = 0;
+ bool disabling_u1;
+ bool disabling_u2;
+ bool enabling_u1;
+ bool enabling_u2;
+
+ disabling_u1 = (state_changed == USB3_LPM_U1 &&
+ hub_encoded_timeout == USB3_LPM_DISABLED);
+ disabling_u2 = (state_changed == USB3_LPM_U2 &&
+ hub_encoded_timeout == USB3_LPM_DISABLED);
+
+ enabling_u1 = (state_changed == USB3_LPM_U1 &&
+ hub_encoded_timeout != USB3_LPM_DISABLED);
+ enabling_u2 = (state_changed == USB3_LPM_U2 &&
+ hub_encoded_timeout != USB3_LPM_DISABLED);
+
+ /* If U1 was already enabled and we're not disabling it,
+ * or we're going to enable U1, account for the U1 max exit latency.
+ */
+ if ((udev->u1_params.timeout != USB3_LPM_DISABLED && !disabling_u1) ||
+ enabling_u1)
+ u1_mel_us = DIV_ROUND_UP(udev->u1_params.mel, 1000);
+ if ((udev->u2_params.timeout != USB3_LPM_DISABLED && !disabling_u2) ||
+ enabling_u2)
+ u2_mel_us = DIV_ROUND_UP(udev->u2_params.mel, 1000);
+
+ if (u1_mel_us > u2_mel_us)
+ mel_us = u1_mel_us;
+ else
+ mel_us = u2_mel_us;
+ /* xHCI host controller max exit latency field is only 16 bits wide. */
+ if (mel_us > MAX_EXIT) {
+ dev_warn(&udev->dev, "Link PM max exit latency of %lluus "
+ "is too big.\n", mel_us);
+ return -E2BIG;
+ }
+ return mel_us;
+}
+
+/* Returns the USB3 hub-encoded value for the U1/U2 timeout. */
+int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
+ struct usb_device *udev, enum usb3_link_state state)
+{
+ struct xhci_hcd *xhci;
+ u16 hub_encoded_timeout;
+ int mel;
+ int ret;
+
+ xhci = hcd_to_xhci(hcd);
+ /* The LPM timeout values are pretty host-controller specific, so don't
+ * enable hub-initiated timeouts unless the vendor has provided
+ * information about their timeout algorithm.
+ */
+ if (!xhci || !(xhci->quirks & XHCI_LPM_SUPPORT) ||
+ !xhci->devs[udev->slot_id])
+ return USB3_LPM_DISABLED;
+
+ hub_encoded_timeout = xhci_calculate_lpm_timeout(hcd, udev, state);
+ mel = calculate_max_exit_latency(udev, state, hub_encoded_timeout);
+ if (mel < 0) {
+ /* Max Exit Latency is too big, disable LPM. */
+ hub_encoded_timeout = USB3_LPM_DISABLED;
+ mel = 0;
+ }
+
+ ret = xhci_change_max_exit_latency(xhci, udev, mel);
+ if (ret)
+ return ret;
+ return hub_encoded_timeout;
+}
+
+int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
+ struct usb_device *udev, enum usb3_link_state state)
+{
+ struct xhci_hcd *xhci;
+ u16 mel;
+ int ret;
+
+ xhci = hcd_to_xhci(hcd);
+ if (!xhci || !(xhci->quirks & XHCI_LPM_SUPPORT) ||
+ !xhci->devs[udev->slot_id])
+ return 0;
+
+ mel = calculate_max_exit_latency(udev, state, USB3_LPM_DISABLED);
+ ret = xhci_change_max_exit_latency(xhci, udev, mel);
+ if (ret)
+ return ret;
+ return 0;
+}
+#else /* CONFIG_PM */
+
+int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
+ struct usb_device *udev, enum usb3_link_state state)
+{
+ return USB3_LPM_DISABLED;
+}
+
+int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
+ struct usb_device *udev, enum usb3_link_state state)
+{
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+/*-------------------------------------------------------------------------*/
+
/* Once a hub descriptor is fetched for a device, we need to update the xHC's
* internal data structures for the device.
*/
@@ -4090,7 +4566,6 @@ static int __init xhci_hcd_init(void)
BUILD_BUG_ON(sizeof(struct xhci_intr_reg) != 8*32/8);
/* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */
BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8);
- BUILD_BUG_ON(sizeof(struct xhci_doorbell_array) != 256*32/8);
return 0;
unreg_pci:
xhci_unregister_pci();
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 3d69c4b2b542..de3d6e3e57be 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -362,8 +362,10 @@ struct xhci_op_regs {
* Timeout can be up to 127us. 0xFF means an infinite timeout.
*/
#define PORT_U1_TIMEOUT(p) ((p) & 0xff)
+#define PORT_U1_TIMEOUT_MASK 0xff
/* Inactivity timer value for transitions into U2 */
#define PORT_U2_TIMEOUT(p) (((p) & 0xff) << 8)
+#define PORT_U2_TIMEOUT_MASK (0xff << 8)
/* Bits 24:31 for port testing */
/* USB2 Protocol PORTSPMSC */
@@ -914,6 +916,8 @@ struct xhci_virt_device {
u8 real_port;
struct xhci_interval_bw_table *bw_table;
struct xhci_tt_bw_info *tt_info;
+ /* The current max exit latency for the enabled USB3 link states. */
+ u16 current_mel;
};
/*
@@ -1362,6 +1366,8 @@ struct xhci_bus_state {
u32 suspended_ports;
u32 port_remote_wakeup;
unsigned long resume_done[USB_MAXCHILDREN];
+ /* which ports have started to resume */
+ unsigned long resuming_ports;
};
static inline unsigned int hcd_index(struct usb_hcd *hcd)
@@ -1422,6 +1428,8 @@ struct xhci_hcd {
/* slot enabling and address device helpers */
struct completion addr_dev;
int slot_id;
+ /* For USB 3.0 LPM enable/disable. */
+ struct xhci_command *lpm_command;
/* Internal mirror of the HW's dcbaa */
struct xhci_virt_device *devs[MAX_HC_SLOTS];
/* For keeping track of bandwidth domains per roothub. */
@@ -1479,6 +1487,9 @@ struct xhci_hcd {
#define XHCI_RESET_ON_RESUME (1 << 7)
#define XHCI_SW_BW_CHECKING (1 << 8)
#define XHCI_AMD_0x96_HOST (1 << 9)
+#define XHCI_TRUST_TX_LENGTH (1 << 10)
+#define XHCI_LPM_SUPPORT (1 << 11)
+#define XHCI_INTEL_HOST (1 << 12)
unsigned int num_active_eps;
unsigned int limit_active_eps;
/* There are two roothubs to keep track of bus suspend info for */
@@ -1752,7 +1763,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
u32 slot_id, bool command_must_succeed);
int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
- u32 slot_id);
+ u32 slot_id, bool command_must_succeed);
int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
unsigned int ep_index);
int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id);
@@ -1776,6 +1787,10 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
/* xHCI roothub code */
void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,
int port_id, u32 link_state);
+int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
+ struct usb_device *udev, enum usb3_link_state state);
+int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
+ struct usb_device *udev, enum usb3_link_state state);
void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
int port_id, u32 port_bit);
int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index 575b56c79e97..7121b50098d3 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -284,18 +284,16 @@ static void mdc800_usb_irq (struct urb *urb)
int data_received=0, wake_up;
unsigned char* b=urb->transfer_buffer;
struct mdc800_data* mdc800=urb->context;
+ struct device *dev = &mdc800->dev->dev;
int status = urb->status;
if (status >= 0) {
-
- //dbg ("%i %i %i %i %i %i %i %i \n",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]);
-
if (mdc800_isBusy (b))
{
if (!mdc800->camera_busy)
{
mdc800->camera_busy=1;
- dbg ("gets busy");
+ dev_dbg(dev, "gets busy\n");
}
}
else
@@ -303,13 +301,13 @@ static void mdc800_usb_irq (struct urb *urb)
if (mdc800->camera_busy && mdc800_isReady (b))
{
mdc800->camera_busy=0;
- dbg ("gets ready");
+ dev_dbg(dev, "gets ready\n");
}
}
if (!(mdc800_isBusy (b) || mdc800_isReady (b)))
{
/* Store Data in camera_answer field */
- dbg ("%i %i %i %i %i %i %i %i ",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]);
+ dev_dbg(dev, "%i %i %i %i %i %i %i %i \n",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]);
memcpy (mdc800->camera_response,b,8);
data_received=1;
@@ -441,7 +439,7 @@ static int mdc800_usb_probe (struct usb_interface *intf,
int irq_interval=0;
int retval;
- dbg ("(mdc800_usb_probe) called.");
+ dev_dbg(&intf->dev, "(%s) called.\n", __func__);
if (mdc800->dev != NULL)
@@ -554,7 +552,7 @@ static void mdc800_usb_disconnect (struct usb_interface *intf)
{
struct mdc800_data* mdc800 = usb_get_intfdata(intf);
- dbg ("(mdc800_usb_disconnect) called");
+ dev_dbg(&intf->dev, "(%s) called\n", __func__);
if (mdc800) {
if (mdc800->state == NOT_CONNECTED)
@@ -656,7 +654,7 @@ static int mdc800_device_open (struct inode* inode, struct file *file)
}
mdc800->open=1;
- dbg ("Mustek MDC800 device opened.");
+ dev_dbg(&mdc800->dev->dev, "Mustek MDC800 device opened.\n");
error_out:
mutex_unlock(&mdc800->io_lock);
@@ -670,7 +668,6 @@ error_out:
static int mdc800_device_release (struct inode* inode, struct file *file)
{
int retval=0;
- dbg ("Mustek MDC800 device closed.");
mutex_lock(&mdc800->io_lock);
if (mdc800->open && (mdc800->state != NOT_CONNECTED))
@@ -927,7 +924,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s
{
mdc800->pic_len=(int) 65536*(unsigned char) mdc800->camera_response[0]+256*(unsigned char) mdc800->camera_response[1]+(unsigned char) mdc800->camera_response[2];
- dbg ("cached imagesize = %i",mdc800->pic_len);
+ dev_dbg(&mdc800->dev->dev, "cached imagesize = %i\n", mdc800->pic_len);
}
}
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index ac0d75a9005a..0fc6e5fc745f 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -88,6 +88,7 @@ static struct workqueue_struct *wq;
static void appledisplay_complete(struct urb *urb)
{
struct appledisplay *pdata = urb->context;
+ struct device *dev = &pdata->udev->dev;
unsigned long flags;
int status = urb->status;
int retval;
@@ -97,18 +98,18 @@ static void appledisplay_complete(struct urb *urb)
/* success */
break;
case -EOVERFLOW:
- printk(KERN_ERR "appletouch: OVERFLOW with data "
- "length %d, actual length is %d\n",
+ dev_err(dev,
+ "OVERFLOW with data length %d, actual length is %d\n",
ACD_URB_BUFFER_LEN, pdata->urb->actual_length);
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
/* This urb is terminated, clean up */
- dbg("%s - urb shuttingdown with status: %d",
+ dev_dbg(dev, "%s - urb shuttingdown with status: %d\n",
__func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
+ dev_dbg(dev, "%s - nonzero urb status received: %d/n",
__func__, status);
goto exit;
}
@@ -132,8 +133,7 @@ static void appledisplay_complete(struct urb *urb)
exit:
retval = usb_submit_urb(pdata->urb, GFP_ATOMIC);
if (retval) {
- dev_err(&pdata->udev->dev,
- "%s - usb_submit_urb failed with result %d\n",
+ dev_err(dev, "%s - usb_submit_urb failed with result %d\n",
__func__, retval);
}
}
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index da97dcec1f32..d65984dee751 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -78,18 +78,14 @@ static int emi26_load_firmware (struct usb_device *dev)
const struct firmware *bitstream_fw = NULL;
const struct firmware *firmware_fw = NULL;
const struct ihex_binrec *rec;
- int err;
+ int err = -ENOMEM;
int i;
__u32 addr; /* Address to write */
__u8 *buf;
buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL);
- if (!buf) {
- dev_err(&dev->dev, "%s - error loading firmware: error = %d\n",
- __func__, -ENOMEM);
- err = -ENOMEM;
+ if (!buf)
goto wraperr;
- }
err = request_ihex_firmware(&loader_fw, "emi26/loader.fw", &dev->dev);
if (err)
@@ -111,11 +107,8 @@ static int emi26_load_firmware (struct usb_device *dev)
/* Assert reset (stop the CPU in the EMI) */
err = emi26_set_reset(dev,1);
- if (err < 0) {
- dev_err(&dev->dev,"%s - error loading firmware: error = %d\n",
- __func__, err);
+ if (err < 0)
goto wraperr;
- }
rec = (const struct ihex_binrec *)loader_fw->data;
/* 1. We need to put the loader for the FPGA into the EZ-USB */
@@ -123,19 +116,15 @@ static int emi26_load_firmware (struct usb_device *dev)
err = emi26_writememory(dev, be32_to_cpu(rec->addr),
rec->data, be16_to_cpu(rec->len),
ANCHOR_LOAD_INTERNAL);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
rec = ihex_next_binrec(rec);
}
/* De-assert reset (let the CPU run) */
err = emi26_set_reset(dev,0);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
msleep(250); /* let device settle */
/* 2. We upload the FPGA firmware into the EMI
@@ -153,18 +142,14 @@ static int emi26_load_firmware (struct usb_device *dev)
rec = ihex_next_binrec(rec);
}
err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
} while (rec);
/* Assert reset (stop the CPU in the EMI) */
err = emi26_set_reset(dev,1);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
/* 3. We need to put the loader for the firmware into the EZ-USB (again...) */
for (rec = (const struct ihex_binrec *)loader_fw->data;
@@ -172,19 +157,15 @@ static int emi26_load_firmware (struct usb_device *dev)
err = emi26_writememory(dev, be32_to_cpu(rec->addr),
rec->data, be16_to_cpu(rec->len),
ANCHOR_LOAD_INTERNAL);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
}
msleep(250); /* let device settle */
/* De-assert reset (let the CPU run) */
err = emi26_set_reset(dev,0);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
/* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
@@ -194,19 +175,15 @@ static int emi26_load_firmware (struct usb_device *dev)
err = emi26_writememory(dev, be32_to_cpu(rec->addr),
rec->data, be16_to_cpu(rec->len),
ANCHOR_LOAD_EXTERNAL);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
}
}
-
+
/* Assert reset (stop the CPU in the EMI) */
err = emi26_set_reset(dev,1);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
for (rec = (const struct ihex_binrec *)firmware_fw->data;
rec; rec = ihex_next_binrec(rec)) {
@@ -214,19 +191,15 @@ static int emi26_load_firmware (struct usb_device *dev)
err = emi26_writememory(dev, be32_to_cpu(rec->addr),
rec->data, be16_to_cpu(rec->len),
ANCHOR_LOAD_INTERNAL);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
}
}
/* De-assert reset (let the CPU run) */
err = emi26_set_reset(dev,0);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
msleep(250); /* let device settle */
/* return 1 to fail the driver inialization
@@ -234,6 +207,10 @@ static int emi26_load_firmware (struct usb_device *dev)
err = 1;
wraperr:
+ if (err < 0)
+ dev_err(&dev->dev,"%s - error loading firmware: error = %d\n",
+ __func__, err);
+
release_firmware(loader_fw);
release_firmware(bitstream_fw);
release_firmware(firmware_fw);
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 4e0f167a6c4e..ff08015b230c 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -56,7 +56,7 @@ static int emi62_writememory(struct usb_device *dev, int address,
unsigned char *buffer = kmemdup(data, length, GFP_KERNEL);
if (!buffer) {
- err("emi62: kmalloc(%d) failed.", length);
+ dev_err(&dev->dev, "kmalloc(%d) failed.\n", length);
return -ENOMEM;
}
/* Note: usb_control_msg returns negative value on error or length of the
@@ -73,9 +73,8 @@ static int emi62_set_reset (struct usb_device *dev, unsigned char reset_bit)
dev_info(&dev->dev, "%s - %d\n", __func__, reset_bit);
response = emi62_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
- if (response < 0) {
- err("emi62: set_reset (%d) failed", reset_bit);
- }
+ if (response < 0)
+ dev_err(&dev->dev, "set_reset (%d) failed\n", reset_bit);
return response;
}
@@ -87,18 +86,15 @@ static int emi62_load_firmware (struct usb_device *dev)
const struct firmware *bitstream_fw = NULL;
const struct firmware *firmware_fw = NULL;
const struct ihex_binrec *rec;
- int err;
+ int err = -ENOMEM;
int i;
__u32 addr; /* Address to write */
__u8 *buf;
dev_dbg(&dev->dev, "load_firmware\n");
buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL);
- if (!buf) {
- err( "%s - error loading firmware: error = %d", __func__, -ENOMEM);
- err = -ENOMEM;
+ if (!buf)
goto wraperr;
- }
err = request_ihex_firmware(&loader_fw, "emi62/loader.fw", &dev->dev);
if (err)
@@ -112,16 +108,13 @@ static int emi62_load_firmware (struct usb_device *dev)
err = request_ihex_firmware(&firmware_fw, FIRMWARE_FW, &dev->dev);
if (err) {
nofw:
- err( "%s - request_firmware() failed", __func__);
goto wraperr;
}
/* Assert reset (stop the CPU in the EMI) */
err = emi62_set_reset(dev,1);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
rec = (const struct ihex_binrec *)loader_fw->data;
@@ -130,19 +123,15 @@ static int emi62_load_firmware (struct usb_device *dev)
err = emi62_writememory(dev, be32_to_cpu(rec->addr),
rec->data, be16_to_cpu(rec->len),
ANCHOR_LOAD_INTERNAL);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
rec = ihex_next_binrec(rec);
}
/* De-assert reset (let the CPU run) */
err = emi62_set_reset(dev,0);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
msleep(250); /* let device settle */
/* 2. We upload the FPGA firmware into the EMI
@@ -160,18 +149,14 @@ static int emi62_load_firmware (struct usb_device *dev)
rec = ihex_next_binrec(rec);
}
err = emi62_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
} while (rec);
/* Assert reset (stop the CPU in the EMI) */
err = emi62_set_reset(dev,1);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
/* 3. We need to put the loader for the firmware into the EZ-USB (again...) */
for (rec = (const struct ihex_binrec *)loader_fw->data;
@@ -179,18 +164,14 @@ static int emi62_load_firmware (struct usb_device *dev)
err = emi62_writememory(dev, be32_to_cpu(rec->addr),
rec->data, be16_to_cpu(rec->len),
ANCHOR_LOAD_INTERNAL);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
}
/* De-assert reset (let the CPU run) */
err = emi62_set_reset(dev,0);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
msleep(250); /* let device settle */
/* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
@@ -201,19 +182,15 @@ static int emi62_load_firmware (struct usb_device *dev)
err = emi62_writememory(dev, be32_to_cpu(rec->addr),
rec->data, be16_to_cpu(rec->len),
ANCHOR_LOAD_EXTERNAL);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
}
}
/* Assert reset (stop the CPU in the EMI) */
err = emi62_set_reset(dev,1);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
for (rec = (const struct ihex_binrec *)firmware_fw->data;
rec; rec = ihex_next_binrec(rec)) {
@@ -221,19 +198,15 @@ static int emi62_load_firmware (struct usb_device *dev)
err = emi62_writememory(dev, be32_to_cpu(rec->addr),
rec->data, be16_to_cpu(rec->len),
ANCHOR_LOAD_EXTERNAL);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
}
}
/* De-assert reset (let the CPU run) */
err = emi62_set_reset(dev,0);
- if (err < 0) {
- err("%s - error loading firmware: error = %d", __func__, err);
+ if (err < 0)
goto wraperr;
- }
msleep(250); /* let device settle */
release_firmware(loader_fw);
@@ -247,6 +220,9 @@ static int emi62_load_firmware (struct usb_device *dev)
return 1;
wraperr:
+ if (err < 0)
+ dev_err(&dev->dev,"%s - error loading firmware: error = %d\n",
+ __func__, err);
release_firmware(loader_fw);
release_firmware(bitstream_fw);
release_firmware(firmware_fw);
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 0dee24698504..ce978384fda1 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -200,7 +200,8 @@ reset:
return -EAGAIN;
/* should be IMGSIZE == 65040 */
- dbg("read %d bytes fingerprint data", bytes_read);
+ dev_dbg(&dev->interface->dev, "read %d bytes fingerprint data\n",
+ bytes_read);
return result;
}
@@ -366,14 +367,14 @@ static int idmouse_probe(struct usb_interface *interface,
kmalloc(IMGSIZE + dev->bulk_in_size, GFP_KERNEL);
if (!dev->bulk_in_buffer) {
- err("Unable to allocate input buffer.");
+ dev_err(&interface->dev, "Unable to allocate input buffer.\n");
idmouse_delete(dev);
return -ENOMEM;
}
}
if (!(dev->bulk_in_endpointAddr)) {
- err("Unable to find bulk-in endpoint.");
+ dev_err(&interface->dev, "Unable to find bulk-in endpoint.\n");
idmouse_delete(dev);
return -ENODEV;
}
@@ -385,7 +386,7 @@ static int idmouse_probe(struct usb_interface *interface,
result = usb_register_dev(interface, &idmouse_class);
if (result) {
/* something prevented us from registering this device */
- err("Unble to allocate minor number.");
+ dev_err(&interface->dev, "Unble to allocate minor number.\n");
usb_set_intfdata(interface, NULL);
idmouse_delete(dev);
return result;
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 4fd0dc835ae5..db46143c67a6 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -610,8 +610,8 @@ static int iowarrior_open(struct inode *inode, struct file *file)
interface = usb_find_interface(&iowarrior_driver, subminor);
if (!interface) {
mutex_unlock(&iowarrior_mutex);
- err("%s - error, can't find device for minor %d", __func__,
- subminor);
+ printk(KERN_ERR "%s - error, can't find device for minor %d\n",
+ __func__, subminor);
return -ENODEV;
}
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 5db4ab52061e..ac762299eaa8 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -334,8 +334,8 @@ static int ld_usb_open(struct inode *inode, struct file *file)
interface = usb_find_interface(&ld_usb_driver, subminor);
if (!interface) {
- err("%s - error, can't find device for minor %d\n",
- __func__, subminor);
+ printk(KERN_ERR "%s - error, can't find device for minor %d\n",
+ __func__, subminor);
return -ENODEV;
}
@@ -485,7 +485,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
/* verify that the device wasn't unplugged */
if (dev->intf == NULL) {
retval = -ENODEV;
- err("No device or device unplugged %d\n", retval);
+ printk(KERN_ERR "ldusb: No device or device unplugged %d\n", retval);
goto unlock_exit;
}
@@ -565,7 +565,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
/* verify that the device wasn't unplugged */
if (dev->intf == NULL) {
retval = -ENODEV;
- err("No device or device unplugged %d\n", retval);
+ printk(KERN_ERR "ldusb: No device or device unplugged %d\n", retval);
goto unlock_exit;
}
@@ -603,7 +603,9 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
bytes_to_write,
USB_CTRL_SET_TIMEOUT * HZ);
if (retval < 0)
- err("Couldn't submit HID_REQ_SET_REPORT %d\n", retval);
+ dev_err(&dev->intf->dev,
+ "Couldn't submit HID_REQ_SET_REPORT %d\n",
+ retval);
goto unlock_exit;
}
@@ -624,7 +626,8 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
if (retval) {
dev->interrupt_out_busy = 0;
- err("Couldn't submit interrupt_out_urb %d\n", retval);
+ dev_err(&dev->intf->dev,
+ "Couldn't submit interrupt_out_urb %d\n", retval);
goto unlock_exit;
}
retval = bytes_to_write;
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 575222042767..a2702cbfe804 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -354,8 +354,8 @@ static int tower_open (struct inode *inode, struct file *file)
interface = usb_find_interface (&tower_driver, subminor);
if (!interface) {
- err ("%s - error, can't find device for minor %d",
- __func__, subminor);
+ printk(KERN_ERR "%s - error, can't find device for minor %d\n",
+ __func__, subminor);
retval = -ENODEV;
goto exit;
}
@@ -397,7 +397,8 @@ static int tower_open (struct inode *inode, struct file *file)
sizeof(reset_reply),
1000);
if (result < 0) {
- err("LEGO USB Tower reset control request failed");
+ dev_err(&dev->udev->dev,
+ "LEGO USB Tower reset control request failed\n");
retval = result;
goto unlock_exit;
}
@@ -420,7 +421,8 @@ static int tower_open (struct inode *inode, struct file *file)
retval = usb_submit_urb (dev->interrupt_in_urb, GFP_KERNEL);
if (retval) {
- err("Couldn't submit interrupt_in_urb %d", retval);
+ dev_err(&dev->udev->dev,
+ "Couldn't submit interrupt_in_urb %d\n", retval);
dev->interrupt_in_running = 0;
dev->open_count = 0;
goto unlock_exit;
@@ -608,7 +610,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
/* verify that the device wasn't unplugged */
if (dev->udev == NULL) {
retval = -ENODEV;
- err("No device or device unplugged %d", retval);
+ printk(KERN_ERR "legousbtower: No device or device unplugged %d\n", retval);
goto unlock_exit;
}
@@ -697,7 +699,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
/* verify that the device wasn't unplugged */
if (dev->udev == NULL) {
retval = -ENODEV;
- err("No device or device unplugged %d", retval);
+ printk(KERN_ERR "legousbtower: No device or device unplugged %d\n", retval);
goto unlock_exit;
}
@@ -744,7 +746,8 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
retval = usb_submit_urb (dev->interrupt_out_urb, GFP_KERNEL);
if (retval) {
dev->interrupt_out_busy = 0;
- err("Couldn't submit interrupt_out_urb %d", retval);
+ dev_err(&dev->udev->dev,
+ "Couldn't submit interrupt_out_urb %d\n", retval);
goto unlock_exit;
}
retval = bytes_to_write;
@@ -803,9 +806,10 @@ resubmit:
/* resubmit if we're still running */
if (dev->interrupt_in_running && dev->udev) {
retval = usb_submit_urb (dev->interrupt_in_urb, GFP_ATOMIC);
- if (retval) {
- err("%s: usb_submit_urb failed (%d)", __func__, retval);
- }
+ if (retval)
+ dev_err(&dev->udev->dev,
+ "%s: usb_submit_urb failed (%d)\n",
+ __func__, retval);
}
exit:
@@ -852,6 +856,7 @@ static void tower_interrupt_out_callback (struct urb *urb)
*/
static int tower_probe (struct usb_interface *interface, const struct usb_device_id *id)
{
+ struct device *idev = &interface->dev;
struct usb_device *udev = interface_to_usbdev(interface);
struct lego_usb_tower *dev = NULL;
struct usb_host_interface *iface_desc;
@@ -871,7 +876,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
dev = kmalloc (sizeof(struct lego_usb_tower), GFP_KERNEL);
if (dev == NULL) {
- err ("Out of memory");
+ dev_err(idev, "Out of memory\n");
goto exit;
}
@@ -915,37 +920,37 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
}
}
if(dev->interrupt_in_endpoint == NULL) {
- err("interrupt in endpoint not found");
+ dev_err(idev, "interrupt in endpoint not found\n");
goto error;
}
if (dev->interrupt_out_endpoint == NULL) {
- err("interrupt out endpoint not found");
+ dev_err(idev, "interrupt out endpoint not found\n");
goto error;
}
dev->read_buffer = kmalloc (read_buffer_size, GFP_KERNEL);
if (!dev->read_buffer) {
- err("Couldn't allocate read_buffer");
+ dev_err(idev, "Couldn't allocate read_buffer\n");
goto error;
}
dev->interrupt_in_buffer = kmalloc (usb_endpoint_maxp(dev->interrupt_in_endpoint), GFP_KERNEL);
if (!dev->interrupt_in_buffer) {
- err("Couldn't allocate interrupt_in_buffer");
+ dev_err(idev, "Couldn't allocate interrupt_in_buffer\n");
goto error;
}
dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->interrupt_in_urb) {
- err("Couldn't allocate interrupt_in_urb");
+ dev_err(idev, "Couldn't allocate interrupt_in_urb\n");
goto error;
}
dev->interrupt_out_buffer = kmalloc (write_buffer_size, GFP_KERNEL);
if (!dev->interrupt_out_buffer) {
- err("Couldn't allocate interrupt_out_buffer");
+ dev_err(idev, "Couldn't allocate interrupt_out_buffer\n");
goto error;
}
dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->interrupt_out_urb) {
- err("Couldn't allocate interrupt_out_urb");
+ dev_err(idev, "Couldn't allocate interrupt_out_urb\n");
goto error;
}
dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval;
@@ -958,7 +963,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
if (retval) {
/* something prevented us from registering this driver */
- err ("Not able to get a minor for this device.");
+ dev_err(idev, "Not able to get a minor for this device.\n");
usb_set_intfdata (interface, NULL);
goto error;
}
@@ -980,7 +985,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
sizeof(get_version_reply),
1000);
if (result < 0) {
- err("LEGO USB Tower get version control request failed");
+ dev_err(idev, "LEGO USB Tower get version control request failed\n");
retval = result;
goto error;
}
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 487a8ce0775e..1084124c4a44 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -153,10 +153,10 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
requesttype = rio_cmd.requesttype | USB_DIR_IN |
USB_TYPE_VENDOR | USB_RECIP_DEVICE;
- dbg
- ("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x",
- requesttype, rio_cmd.request, rio_cmd.value,
- rio_cmd.index, rio_cmd.length);
+ dev_dbg(&rio->rio_dev->dev,
+ "sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n",
+ requesttype, rio_cmd.request, rio_cmd.value,
+ rio_cmd.index, rio_cmd.length);
/* Send rio control message */
retries = 3;
while (retries) {
@@ -171,11 +171,14 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
if (result == -ETIMEDOUT)
retries--;
else if (result < 0) {
- err("Error executing ioctrl. code = %d", result);
+ dev_err(&rio->rio_dev->dev,
+ "Error executing ioctrl. code = %d\n",
+ result);
retries = 0;
} else {
- dbg("Executed ioctl. Result = %d (data=%02x)",
- result, buffer[0]);
+ dev_dbg(&rio->rio_dev->dev,
+ "Executed ioctl. Result = %d (data=%02x)\n",
+ result, buffer[0]);
if (copy_to_user(rio_cmd.buffer, buffer,
rio_cmd.length)) {
free_page((unsigned long) buffer);
@@ -221,9 +224,10 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
requesttype = rio_cmd.requesttype | USB_DIR_OUT |
USB_TYPE_VENDOR | USB_RECIP_DEVICE;
- dbg("sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x",
- requesttype, rio_cmd.request, rio_cmd.value,
- rio_cmd.index, rio_cmd.length);
+ dev_dbg(&rio->rio_dev->dev,
+ "sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n",
+ requesttype, rio_cmd.request, rio_cmd.value,
+ rio_cmd.index, rio_cmd.length);
/* Send rio control message */
retries = 3;
while (retries) {
@@ -238,10 +242,13 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
if (result == -ETIMEDOUT)
retries--;
else if (result < 0) {
- err("Error executing ioctrl. code = %d", result);
+ dev_err(&rio->rio_dev->dev,
+ "Error executing ioctrl. code = %d\n",
+ result);
retries = 0;
} else {
- dbg("Executed ioctl. Result = %d", result);
+ dev_dbg(&rio->rio_dev->dev,
+ "Executed ioctl. Result = %d\n", result);
retries = 0;
}
@@ -313,8 +320,9 @@ write_rio(struct file *file, const char __user *buffer,
usb_sndbulkpipe(rio->rio_dev, 2),
obuf, thistime, &partial, 5000);
- dbg("write stats: result:%d thistime:%lu partial:%u",
- result, thistime, partial);
+ dev_dbg(&rio->rio_dev->dev,
+ "write stats: result:%d thistime:%lu partial:%u\n",
+ result, thistime, partial);
if (result == -ETIMEDOUT) { /* NAK - so hold for a while */
if (!maxretry--) {
@@ -332,7 +340,8 @@ write_rio(struct file *file, const char __user *buffer,
break;
};
if (result) {
- err("Write Whoops - %x", result);
+ dev_err(&rio->rio_dev->dev, "Write Whoops - %x\n",
+ result);
errn = -EIO;
goto error;
}
@@ -393,15 +402,17 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
ibuf, this_read, &partial,
8000);
- dbg("read stats: result:%d this_read:%u partial:%u",
- result, this_read, partial);
+ dev_dbg(&rio->rio_dev->dev,
+ "read stats: result:%d this_read:%u partial:%u\n",
+ result, this_read, partial);
if (partial) {
count = this_read = partial;
} else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */
if (!maxretry--) {
mutex_unlock(&(rio->lock));
- err("read_rio: maxretry timeout");
+ dev_err(&rio->rio_dev->dev,
+ "read_rio: maxretry timeout\n");
return -ETIME;
}
prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE);
@@ -410,8 +421,9 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
continue;
} else if (result != -EREMOTEIO) {
mutex_unlock(&(rio->lock));
- err("Read Whoops - result:%u partial:%u this_read:%u",
- result, partial, this_read);
+ dev_err(&rio->rio_dev->dev,
+ "Read Whoops - result:%u partial:%u this_read:%u\n",
+ result, partial, this_read);
return -EIO;
} else {
mutex_unlock(&(rio->lock));
@@ -459,26 +471,29 @@ static int probe_rio(struct usb_interface *intf,
retval = usb_register_dev(intf, &usb_rio_class);
if (retval) {
- err("Not able to get a minor for this device.");
+ dev_err(&dev->dev,
+ "Not able to get a minor for this device.\n");
return -ENOMEM;
}
rio->rio_dev = dev;
if (!(rio->obuf = kmalloc(OBUF_SIZE, GFP_KERNEL))) {
- err("probe_rio: Not enough memory for the output buffer");
+ dev_err(&dev->dev,
+ "probe_rio: Not enough memory for the output buffer\n");
usb_deregister_dev(intf, &usb_rio_class);
return -ENOMEM;
}
- dbg("probe_rio: obuf address:%p", rio->obuf);
+ dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf);
if (!(rio->ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL))) {
- err("probe_rio: Not enough memory for the input buffer");
+ dev_err(&dev->dev,
+ "probe_rio: Not enough memory for the input buffer\n");
usb_deregister_dev(intf, &usb_rio_class);
kfree(rio->obuf);
return -ENOMEM;
}
- dbg("probe_rio: ibuf address:%p", rio->ibuf);
+ dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf);
mutex_init(&(rio->lock));
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index e2b4bd31c2b6..89927bcff974 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -87,8 +87,8 @@ static int lcd_open(struct inode *inode, struct file *file)
interface = usb_find_interface(&lcd_driver, subminor);
if (!interface) {
mutex_unlock(&lcd_mutex);
- err("USBLCD: %s - error, can't find device for minor %d",
- __func__, subminor);
+ printk(KERN_ERR "USBLCD: %s - error, can't find device for minor %d\n",
+ __func__, subminor);
return -ENODEV;
}
@@ -209,8 +209,8 @@ static void lcd_write_bulk_callback(struct urb *urb)
!(status == -ENOENT ||
status == -ECONNRESET ||
status == -ESHUTDOWN)) {
- dbg("USBLCD: %s - nonzero write bulk status received: %d",
- __func__, status);
+ dev_dbg(&dev->interface->dev,
+ "nonzero write bulk status received: %d\n", status);
}
/* free up our allocated buffer */
@@ -268,8 +268,9 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer,
/* send the data out the bulk port */
retval = usb_submit_urb(urb, GFP_KERNEL);
if (retval) {
- err("USBLCD: %s - failed submitting write urb, error %d",
- __func__, retval);
+ dev_err(&dev->udev->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, retval);
goto error_unanchor;
}
@@ -322,7 +323,7 @@ static int lcd_probe(struct usb_interface *interface,
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
- err("Out of memory");
+ dev_err(&interface->dev, "Out of memory\n");
goto error;
}
kref_init(&dev->kref);
@@ -352,7 +353,8 @@ static int lcd_probe(struct usb_interface *interface,
dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!dev->bulk_in_buffer) {
- err("Could not allocate bulk_in_buffer");
+ dev_err(&interface->dev,
+ "Could not allocate bulk_in_buffer\n");
goto error;
}
}
@@ -364,7 +366,8 @@ static int lcd_probe(struct usb_interface *interface,
}
}
if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
- err("Could not find both bulk-in and bulk-out endpoints");
+ dev_err(&interface->dev,
+ "Could not find both bulk-in and bulk-out endpoints\n");
goto error;
}
@@ -375,7 +378,8 @@ static int lcd_probe(struct usb_interface *interface,
retval = usb_register_dev(interface, &lcd_class);
if (retval) {
/* something prevented us from registering this driver */
- err("Not able to get a minor for this device.");
+ dev_err(&interface->dev,
+ "Not able to get a minor for this device.\n");
usb_set_intfdata(interface, NULL);
goto error;
}
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 9dcb68f04f03..055b84adedac 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -1028,7 +1028,10 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param)
case 13: /* short read, resembling case 10 */
req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0);
/* last data packet "should" be DATA1, not DATA0 */
- len = 1024 - udev->descriptor.bMaxPacketSize0;
+ if (udev->speed == USB_SPEED_SUPER)
+ len = 1024 - 512;
+ else
+ len = 1024 - udev->descriptor.bMaxPacketSize0;
expected = -EREMOTEIO;
break;
case 14: /* short read; try to fill the last packet */
@@ -1387,11 +1390,15 @@ static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb)
static int halt_simple(struct usbtest_dev *dev)
{
- int ep;
- int retval = 0;
- struct urb *urb;
+ int ep;
+ int retval = 0;
+ struct urb *urb;
+ struct usb_device *udev = testdev_to_usbdev(dev);
- urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 512);
+ if (udev->speed == USB_SPEED_SUPER)
+ urb = simple_alloc_urb(udev, 0, 1024);
+ else
+ urb = simple_alloc_urb(udev, 0, 512);
if (urb == NULL)
return -ENOMEM;
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 8b1d94a76914..29cad9e0a7a9 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -85,9 +85,9 @@ static void destroy_priv(struct kref *kref)
{
struct parport_uss720_private *priv = container_of(kref, struct parport_uss720_private, ref_count);
+ dev_dbg(&priv->usbdev->dev, "destroying priv datastructure\n");
usb_put_dev(priv->usbdev);
kfree(priv);
- dbg("destroying priv datastructure");
}
static void destroy_async(struct kref *kref)
@@ -118,14 +118,17 @@ static void async_complete(struct urb *urb)
priv = rq->priv;
pp = priv->pp;
if (status) {
- err("async_complete: urb error %d", status);
+ dev_err(&urb->dev->dev, "async_complete: urb error %d\n",
+ status);
} else if (rq->dr.bRequest == 3) {
memcpy(priv->reg, rq->reg, sizeof(priv->reg));
#if 0
- dbg("async_complete regs %02x %02x %02x %02x %02x %02x %02x",
- (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], (unsigned int)priv->reg[2],
- (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], (unsigned int)priv->reg[5],
- (unsigned int)priv->reg[6]);
+ dev_dbg(&priv->usbdev->dev,
+ "async_complete regs %02x %02x %02x %02x %02x %02x %02x\n",
+ (unsigned int)priv->reg[0], (unsigned int)priv->reg[1],
+ (unsigned int)priv->reg[2], (unsigned int)priv->reg[3],
+ (unsigned int)priv->reg[4], (unsigned int)priv->reg[5],
+ (unsigned int)priv->reg[6]);
#endif
/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
if (rq->reg[2] & rq->reg[1] & 0x10 && pp)
@@ -151,7 +154,7 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p
return NULL;
rq = kmalloc(sizeof(struct uss720_async_request), mem_flags);
if (!rq) {
- err("submit_async_request out of memory");
+ dev_err(&usbdev->dev, "submit_async_request out of memory\n");
return NULL;
}
kref_init(&rq->ref_count);
@@ -162,7 +165,7 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p
rq->urb = usb_alloc_urb(0, mem_flags);
if (!rq->urb) {
kref_put(&rq->ref_count, destroy_async);
- err("submit_async_request out of memory");
+ dev_err(&usbdev->dev, "submit_async_request out of memory\n");
return NULL;
}
rq->dr.bRequestType = requesttype;
@@ -182,7 +185,7 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p
if (!ret)
return rq;
destroy_async(&rq->ref_count);
- err("submit_async_request submit_urb failed with %d", ret);
+ dev_err(&usbdev->dev, "submit_async_request submit_urb failed with %d\n", ret);
return NULL;
}
@@ -217,7 +220,8 @@ static int get_1284_register(struct parport *pp, unsigned char reg, unsigned cha
priv = pp->private_data;
rq = submit_async_request(priv, 3, 0xc0, ((unsigned int)reg) << 8, 0, mem_flags);
if (!rq) {
- err("get_1284_register(%u) failed", (unsigned int)reg);
+ dev_err(&priv->usbdev->dev, "get_1284_register(%u) failed",
+ (unsigned int)reg);
return -EIO;
}
if (!val) {
@@ -248,7 +252,8 @@ static int set_1284_register(struct parport *pp, unsigned char reg, unsigned cha
priv = pp->private_data;
rq = submit_async_request(priv, 4, 0x40, (((unsigned int)reg) << 8) | val, 0, mem_flags);
if (!rq) {
- err("set_1284_register(%u,%u) failed", (unsigned int)reg, (unsigned int)val);
+ dev_err(&priv->usbdev->dev, "set_1284_register(%u,%u) failed",
+ (unsigned int)reg, (unsigned int)val);
return -EIO;
}
kref_put(&rq->ref_count, destroy_async);
@@ -690,9 +695,9 @@ static int uss720_probe(struct usb_interface *intf,
unsigned char reg;
int i;
- dbg("probe: vendor id 0x%x, device id 0x%x\n",
- le16_to_cpu(usbdev->descriptor.idVendor),
- le16_to_cpu(usbdev->descriptor.idProduct));
+ dev_dbg(&intf->dev, "probe: vendor id 0x%x, device id 0x%x\n",
+ le16_to_cpu(usbdev->descriptor.idVendor),
+ le16_to_cpu(usbdev->descriptor.idProduct));
/* our known interfaces have 3 alternate settings */
if (intf->num_altsetting != 3) {
@@ -700,7 +705,7 @@ static int uss720_probe(struct usb_interface *intf,
return -ENODEV;
}
i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2);
- dbg("set inteface result %d", i);
+ dev_dbg(&intf->dev, "set inteface result %d\n", i);
interface = intf->cur_altsetting;
@@ -731,11 +736,13 @@ static int uss720_probe(struct usb_interface *intf,
set_1284_register(pp, 2, 0x0c, GFP_KERNEL);
/* debugging */
get_1284_register(pp, 0, &reg, GFP_KERNEL);
- dbg("reg: %02x %02x %02x %02x %02x %02x %02x",
- priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
+ dev_dbg(&intf->dev, "reg: %02x %02x %02x %02x %02x %02x %02x\n",
+ priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3],
+ priv->reg[4], priv->reg[5], priv->reg[6]);
endpoint = &interface->endpoint[2];
- dbg("epaddr %d interval %d", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);
+ dev_dbg(&intf->dev, "epaddr %d interval %d\n",
+ endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);
parport_announce_port(pp);
usb_set_intfdata(intf, pp);
@@ -753,20 +760,20 @@ static void uss720_disconnect(struct usb_interface *intf)
struct parport_uss720_private *priv;
struct usb_device *usbdev;
- dbg("disconnect");
+ dev_dbg(&intf->dev, "disconnect\n");
usb_set_intfdata(intf, NULL);
if (pp) {
priv = pp->private_data;
usbdev = priv->usbdev;
priv->usbdev = NULL;
priv->pp = NULL;
- dbg("parport_remove_port");
+ dev_dbg(&intf->dev, "parport_remove_port\n");
parport_remove_port(pp);
parport_put_port(pp);
kill_all_async_requests_priv(priv);
kref_put(&priv->ref_count, destroy_priv);
}
- dbg("disconnect done");
+ dev_dbg(&intf->dev, "disconnect done\n");
}
/* table of cables that work through this driver */
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
index 70201462e19c..42ad2e6d86c4 100644
--- a/drivers/usb/misc/yurex.c
+++ b/drivers/usb/misc/yurex.c
@@ -83,7 +83,8 @@ static void yurex_control_callback(struct urb *urb)
int status = urb->status;
if (status) {
- err("%s - control failed: %d\n", __func__, status);
+ dev_err(&urb->dev->dev, "%s - control failed: %d\n",
+ __func__, status);
wake_up_interruptible(&dev->waitq);
return;
}
@@ -94,7 +95,7 @@ static void yurex_delete(struct kref *kref)
{
struct usb_yurex *dev = to_yurex_dev(kref);
- dbg("yurex_delete");
+ dev_dbg(&dev->interface->dev, "%s\n", __func__);
usb_put_dev(dev->udev);
if (dev->cntl_urb) {
@@ -137,8 +138,9 @@ static void yurex_interrupt(struct urb *urb)
case 0: /*success*/
break;
case -EOVERFLOW:
- err("%s - overflow with length %d, actual length is %d",
- __func__, YUREX_BUF_SIZE, dev->urb->actual_length);
+ dev_err(&dev->interface->dev,
+ "%s - overflow with length %d, actual length is %d\n",
+ __func__, YUREX_BUF_SIZE, dev->urb->actual_length);
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
@@ -146,7 +148,8 @@ static void yurex_interrupt(struct urb *urb)
/* The device is terminated, clean up */
return;
default:
- err("%s - unknown status received: %d", __func__, status);
+ dev_err(&dev->interface->dev,
+ "%s - unknown status received: %d\n", __func__, status);
goto exit;
}
@@ -162,16 +165,19 @@ static void yurex_interrupt(struct urb *urb)
if (i != 5)
dev->bbu <<= 8;
}
- dbg("%s count: %lld", __func__, dev->bbu);
+ dev_dbg(&dev->interface->dev, "%s count: %lld\n",
+ __func__, dev->bbu);
spin_unlock_irqrestore(&dev->lock, flags);
kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
}
else
- dbg("data format error - no EOF");
+ dev_dbg(&dev->interface->dev,
+ "data format error - no EOF\n");
break;
case CMD_ACK:
- dbg("%s ack: %c", __func__, buf[1]);
+ dev_dbg(&dev->interface->dev, "%s ack: %c\n",
+ __func__, buf[1]);
wake_up_interruptible(&dev->waitq);
break;
}
@@ -179,7 +185,7 @@ static void yurex_interrupt(struct urb *urb)
exit:
retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
if (retval) {
- err("%s - usb_submit_urb failed: %d",
+ dev_err(&dev->interface->dev, "%s - usb_submit_urb failed: %d\n",
__func__, retval);
}
}
@@ -196,7 +202,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
- err("Out of memory");
+ dev_err(&interface->dev, "Out of memory\n");
goto error;
}
kref_init(&dev->kref);
@@ -219,7 +225,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
}
if (!dev->int_in_endpointAddr) {
retval = -ENODEV;
- err("Could not find endpoints");
+ dev_err(&interface->dev, "Could not find endpoints\n");
goto error;
}
@@ -227,14 +233,14 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
/* allocate control URB */
dev->cntl_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->cntl_urb) {
- err("Could not allocate control URB");
+ dev_err(&interface->dev, "Could not allocate control URB\n");
goto error;
}
/* allocate buffer for control req */
dev->cntl_req = kmalloc(YUREX_BUF_SIZE, GFP_KERNEL);
if (!dev->cntl_req) {
- err("Could not allocate cntl_req");
+ dev_err(&interface->dev, "Could not allocate cntl_req\n");
goto error;
}
@@ -243,7 +249,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
GFP_KERNEL,
&dev->cntl_urb->transfer_dma);
if (!dev->cntl_buffer) {
- err("Could not allocate cntl_buffer");
+ dev_err(&interface->dev, "Could not allocate cntl_buffer\n");
goto error;
}
@@ -265,7 +271,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
/* allocate interrupt URB */
dev->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->urb) {
- err("Could not allocate URB");
+ dev_err(&interface->dev, "Could not allocate URB\n");
goto error;
}
@@ -273,7 +279,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
dev->int_buffer = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE,
GFP_KERNEL, &dev->urb->transfer_dma);
if (!dev->int_buffer) {
- err("Could not allocate int_buffer");
+ dev_err(&interface->dev, "Could not allocate int_buffer\n");
goto error;
}
@@ -285,7 +291,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
dev->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
if (usb_submit_urb(dev->urb, GFP_KERNEL)) {
retval = -EIO;
- err("Could not submitting URB");
+ dev_err(&interface->dev, "Could not submitting URB\n");
goto error;
}
@@ -295,7 +301,8 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
/* we can register the device now, as it is ready */
retval = usb_register_dev(interface, &yurex_class);
if (retval) {
- err("Not able to get a minor for this device.");
+ dev_err(&interface->dev,
+ "Not able to get a minor for this device.\n");
usb_set_intfdata(interface, NULL);
goto error;
}
@@ -368,8 +375,8 @@ static int yurex_open(struct inode *inode, struct file *file)
interface = usb_find_interface(&yurex_driver, subminor);
if (!interface) {
- err("%s - error, can't find device for minor %d",
- __func__, subminor);
+ printk(KERN_ERR "%s - error, can't find device for minor %d",
+ __func__, subminor);
retval = -ENODEV;
goto exit;
}
@@ -505,7 +512,8 @@ static ssize_t yurex_write(struct file *file, const char *user_buffer, size_t co
/* send the data as the control msg */
prepare_to_wait(&dev->waitq, &wait, TASK_INTERRUPTIBLE);
- dbg("%s - submit %c", __func__, dev->cntl_buffer[0]);
+ dev_dbg(&dev->interface->dev, "%s - submit %c\n", __func__,
+ dev->cntl_buffer[0]);
retval = usb_submit_urb(dev->cntl_urb, GFP_KERNEL);
if (retval >= 0)
timeout = schedule_timeout(YUREX_WRITE_TIMEOUT);
@@ -514,7 +522,9 @@ static ssize_t yurex_write(struct file *file, const char *user_buffer, size_t co
mutex_unlock(&dev->io_mutex);
if (retval < 0) {
- err("%s - failed to send bulk msg, error %d", __func__, retval);
+ dev_err(&dev->interface->dev,
+ "%s - failed to send bulk msg, error %d\n",
+ __func__, retval);
goto error;
}
if (set && timeout)
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index f70cab3beeec..ef0c3f9f0947 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -8,6 +8,7 @@ config USB_MUSB_HDRC
tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
depends on USB && USB_GADGET
select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN)
+ select NOP_USB_XCEIV if (SOC_OMAPTI81XX || SOC_OMAPAM33XX)
select TWL4030_USB if MACH_OMAP_3430SDP
select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
select USB_OTG_UTILS
@@ -54,6 +55,10 @@ config USB_MUSB_AM35X
tristate "AM35x"
depends on ARCH_OMAP
+config USB_MUSB_DSPS
+ tristate "TI DSPS platforms"
+ depends on SOC_OMAPTI81XX || SOC_OMAPAM33XX
+
config USB_MUSB_BLACKFIN
tristate "Blackfin"
depends on (BF54x && !BF544) || (BF52x && ! BF522 && !BF523)
@@ -70,7 +75,8 @@ choice
default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI
default USB_TUSB_OMAP_DMA if USB_MUSB_TUSB6010
- default MUSB_PIO_ONLY if USB_MUSB_TUSB6010 || USB_MUSB_DA8XX || USB_MUSB_AM35X
+ default MUSB_PIO_ONLY if USB_MUSB_TUSB6010 || USB_MUSB_DA8XX || USB_MUSB_AM35X \
+ || USB_MUSB_DSPS
help
Unfortunately, only one option can be enabled here. Ideally one
should be able to build all these drivers into one kernel to
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 88bfb9dee4bf..3b858715b5ea 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -13,6 +13,7 @@ musb_hdrc-$(CONFIG_DEBUG_FS) += musb_debugfs.o
# Hardware Glue Layer
obj-$(CONFIG_USB_MUSB_OMAP2PLUS) += omap2430.o
obj-$(CONFIG_USB_MUSB_AM35X) += am35x.o
+obj-$(CONFIG_USB_MUSB_DSPS) += musb_dsps.o
obj-$(CONFIG_USB_MUSB_TUSB6010) += tusb6010.o
obj-$(CONFIG_USB_MUSB_DAVINCI) += davinci.o
obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index 66bc376005d2..8637c1f69fc3 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -6,6 +6,7 @@
* The TUSB6020, using VLYNQ, has CPPI that looks much like DaVinci.
*/
+#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/usb.h>
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 66aaccf04490..db3dff854b71 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -1034,7 +1034,9 @@ static void musb_shutdown(struct platform_device *pdev)
|| defined(CONFIG_USB_MUSB_OMAP2PLUS) \
|| defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE) \
|| defined(CONFIG_USB_MUSB_AM35X) \
- || defined(CONFIG_USB_MUSB_AM35X_MODULE)
+ || defined(CONFIG_USB_MUSB_AM35X_MODULE) \
+ || defined(CONFIG_USB_MUSB_DSPS) \
+ || defined(CONFIG_USB_MUSB_DSPS_MODULE)
static ushort __devinitdata fifo_mode = 4;
#elif defined(CONFIG_USB_MUSB_UX500) \
|| defined(CONFIG_USB_MUSB_UX500_MODULE)
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
new file mode 100644
index 000000000000..23db42db761a
--- /dev/null
+++ b/drivers/usb/musb/musb_dsps.c
@@ -0,0 +1,711 @@
+/*
+ * Texas Instruments DSPS platforms "glue layer"
+ *
+ * Copyright (C) 2012, by Texas Instruments
+ *
+ * Based on the am35x "glue layer" code.
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux 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.
+ *
+ * The Inventra Controller Driver for Linux 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 The Inventra Controller Driver for Linux ; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * musb_dsps.c will be a common file for all the TI DSPS platforms
+ * such as dm64x, dm36x, dm35x, da8x, am35x and ti81x.
+ * For now only ti81x is using this and in future davinci.c, am35x.c
+ * da8xx.c would be merged to this file after testing.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm_runtime.h>
+#include <linux/module.h>
+
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+
+#include <plat/usb.h>
+
+#include "musb_core.h"
+
+/**
+ * avoid using musb_readx()/musb_writex() as glue layer should not be
+ * dependent on musb core layer symbols.
+ */
+static inline u8 dsps_readb(const void __iomem *addr, unsigned offset)
+ { return __raw_readb(addr + offset); }
+
+static inline u32 dsps_readl(const void __iomem *addr, unsigned offset)
+ { return __raw_readl(addr + offset); }
+
+static inline void dsps_writeb(void __iomem *addr, unsigned offset, u8 data)
+ { __raw_writeb(data, addr + offset); }
+
+static inline void dsps_writel(void __iomem *addr, unsigned offset, u32 data)
+ { __raw_writel(data, addr + offset); }
+
+/**
+ * DSPS musb wrapper register offset.
+ * FIXME: This should be expanded to have all the wrapper registers from TI DSPS
+ * musb ips.
+ */
+struct dsps_musb_wrapper {
+ u16 revision;
+ u16 control;
+ u16 status;
+ u16 eoi;
+ u16 epintr_set;
+ u16 epintr_clear;
+ u16 epintr_status;
+ u16 coreintr_set;
+ u16 coreintr_clear;
+ u16 coreintr_status;
+ u16 phy_utmi;
+ u16 mode;
+
+ /* bit positions for control */
+ unsigned reset:5;
+
+ /* bit positions for interrupt */
+ unsigned usb_shift:5;
+ u32 usb_mask;
+ u32 usb_bitmap;
+ unsigned drvvbus:5;
+
+ unsigned txep_shift:5;
+ u32 txep_mask;
+ u32 txep_bitmap;
+
+ unsigned rxep_shift:5;
+ u32 rxep_mask;
+ u32 rxep_bitmap;
+
+ /* bit positions for phy_utmi */
+ unsigned otg_disable:5;
+
+ /* bit positions for mode */
+ unsigned iddig:5;
+ /* miscellaneous stuff */
+ u32 musb_core_offset;
+ u8 poll_seconds;
+};
+
+/**
+ * DSPS glue structure.
+ */
+struct dsps_glue {
+ struct device *dev;
+ struct platform_device *musb; /* child musb pdev */
+ const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
+ struct timer_list timer; /* otg_workaround timer */
+};
+
+/**
+ * dsps_musb_enable - enable interrupts
+ */
+static void dsps_musb_enable(struct musb *musb)
+{
+ struct device *dev = musb->controller;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ void __iomem *reg_base = musb->ctrl_base;
+ u32 epmask, coremask;
+
+ /* Workaround: setup IRQs through both register sets. */
+ epmask = ((musb->epmask & wrp->txep_mask) << wrp->txep_shift) |
+ ((musb->epmask & wrp->rxep_mask) << wrp->rxep_shift);
+ coremask = (wrp->usb_bitmap & ~MUSB_INTR_SOF);
+
+ dsps_writel(reg_base, wrp->epintr_set, epmask);
+ dsps_writel(reg_base, wrp->coreintr_set, coremask);
+ /* Force the DRVVBUS IRQ so we can start polling for ID change. */
+ if (is_otg_enabled(musb))
+ dsps_writel(reg_base, wrp->coreintr_set,
+ (1 << wrp->drvvbus) << wrp->usb_shift);
+}
+
+/**
+ * dsps_musb_disable - disable HDRC and flush interrupts
+ */
+static void dsps_musb_disable(struct musb *musb)
+{
+ struct device *dev = musb->controller;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ void __iomem *reg_base = musb->ctrl_base;
+
+ dsps_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap);
+ dsps_writel(reg_base, wrp->epintr_clear,
+ wrp->txep_bitmap | wrp->rxep_bitmap);
+ dsps_writeb(musb->mregs, MUSB_DEVCTL, 0);
+ dsps_writel(reg_base, wrp->eoi, 0);
+}
+
+static void otg_timer(unsigned long _musb)
+{
+ struct musb *musb = (void *)_musb;
+ void __iomem *mregs = musb->mregs;
+ struct device *dev = musb->controller;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ u8 devctl;
+ unsigned long flags;
+
+ /*
+ * We poll because DSPS IP's won't expose several OTG-critical
+ * status change events (from the transceiver) otherwise.
+ */
+ devctl = dsps_readb(mregs, MUSB_DEVCTL);
+ dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
+ otg_state_string(musb->xceiv->state));
+
+ spin_lock_irqsave(&musb->lock, flags);
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_WAIT_BCON:
+ devctl &= ~MUSB_DEVCTL_SESSION;
+ dsps_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+ devctl = dsps_readb(musb->mregs, MUSB_DEVCTL);
+ if (devctl & MUSB_DEVCTL_BDEVICE) {
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ MUSB_DEV_MODE(musb);
+ } else {
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ MUSB_HST_MODE(musb);
+ }
+ break;
+ case OTG_STATE_A_WAIT_VFALL:
+ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ dsps_writel(musb->ctrl_base, wrp->coreintr_set,
+ MUSB_INTR_VBUSERROR << wrp->usb_shift);
+ break;
+ case OTG_STATE_B_IDLE:
+ if (!is_peripheral_enabled(musb))
+ break;
+
+ devctl = dsps_readb(mregs, MUSB_DEVCTL);
+ if (devctl & MUSB_DEVCTL_BDEVICE)
+ mod_timer(&glue->timer,
+ jiffies + wrp->poll_seconds * HZ);
+ else
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ break;
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
+{
+ struct device *dev = musb->controller;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ static unsigned long last_timer;
+
+ if (!is_otg_enabled(musb))
+ return;
+
+ if (timeout == 0)
+ timeout = jiffies + msecs_to_jiffies(3);
+
+ /* Never idle if active, or when VBUS timeout is not set as host */
+ if (musb->is_active || (musb->a_wait_bcon == 0 &&
+ musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
+ dev_dbg(musb->controller, "%s active, deleting timer\n",
+ otg_state_string(musb->xceiv->state));
+ del_timer(&glue->timer);
+ last_timer = jiffies;
+ return;
+ }
+
+ if (time_after(last_timer, timeout) && timer_pending(&glue->timer)) {
+ dev_dbg(musb->controller,
+ "Longer idle timer already pending, ignoring...\n");
+ return;
+ }
+ last_timer = timeout;
+
+ dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
+ otg_state_string(musb->xceiv->state),
+ jiffies_to_msecs(timeout - jiffies));
+ mod_timer(&glue->timer, timeout);
+}
+
+static irqreturn_t dsps_interrupt(int irq, void *hci)
+{
+ struct musb *musb = hci;
+ void __iomem *reg_base = musb->ctrl_base;
+ struct device *dev = musb->controller;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ unsigned long flags;
+ irqreturn_t ret = IRQ_NONE;
+ u32 epintr, usbintr;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ /* Get endpoint interrupts */
+ epintr = dsps_readl(reg_base, wrp->epintr_status);
+ musb->int_rx = (epintr & wrp->rxep_bitmap) >> wrp->rxep_shift;
+ musb->int_tx = (epintr & wrp->txep_bitmap) >> wrp->txep_shift;
+
+ if (epintr)
+ dsps_writel(reg_base, wrp->epintr_status, epintr);
+
+ /* Get usb core interrupts */
+ usbintr = dsps_readl(reg_base, wrp->coreintr_status);
+ if (!usbintr && !epintr)
+ goto eoi;
+
+ musb->int_usb = (usbintr & wrp->usb_bitmap) >> wrp->usb_shift;
+ if (usbintr)
+ dsps_writel(reg_base, wrp->coreintr_status, usbintr);
+
+ dev_dbg(musb->controller, "usbintr (%x) epintr(%x)\n",
+ usbintr, epintr);
+ /*
+ * DRVVBUS IRQs are the only proxy we have (a very poor one!) for
+ * DSPS IP's missing ID change IRQ. We need an ID change IRQ to
+ * switch appropriately between halves of the OTG state machine.
+ * Managing DEVCTL.SESSION per Mentor docs requires that we know its
+ * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
+ * Also, DRVVBUS pulses for SRP (but not at 5V) ...
+ */
+ if ((usbintr & MUSB_INTR_BABBLE) && is_host_enabled(musb))
+ pr_info("CAUTION: musb: Babble Interrupt Occured\n");
+
+ if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
+ int drvvbus = dsps_readl(reg_base, wrp->status);
+ void __iomem *mregs = musb->mregs;
+ u8 devctl = dsps_readb(mregs, MUSB_DEVCTL);
+ int err;
+
+ err = is_host_enabled(musb) && (musb->int_usb &
+ MUSB_INTR_VBUSERROR);
+ if (err) {
+ /*
+ * The Mentor core doesn't debounce VBUS as needed
+ * to cope with device connect current spikes. This
+ * means it's not uncommon for bus-powered devices
+ * to get VBUS errors during enumeration.
+ *
+ * This is a workaround, but newer RTL from Mentor
+ * seems to allow a better one: "re"-starting sessions
+ * without waiting for VBUS to stop registering in
+ * devctl.
+ */
+ musb->int_usb &= ~MUSB_INTR_VBUSERROR;
+ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ mod_timer(&glue->timer,
+ jiffies + wrp->poll_seconds * HZ);
+ WARNING("VBUS error workaround (delay coming)\n");
+ } else if (is_host_enabled(musb) && drvvbus) {
+ musb->is_active = 1;
+ MUSB_HST_MODE(musb);
+ musb->xceiv->otg->default_a = 1;
+ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ del_timer(&glue->timer);
+ } else {
+ musb->is_active = 0;
+ MUSB_DEV_MODE(musb);
+ musb->xceiv->otg->default_a = 0;
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ }
+
+ /* NOTE: this must complete power-on within 100 ms. */
+ dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
+ drvvbus ? "on" : "off",
+ otg_state_string(musb->xceiv->state),
+ err ? " ERROR" : "",
+ devctl);
+ ret = IRQ_HANDLED;
+ }
+
+ if (musb->int_tx || musb->int_rx || musb->int_usb)
+ ret |= musb_interrupt(musb);
+
+ eoi:
+ /* EOI needs to be written for the IRQ to be re-asserted. */
+ if (ret == IRQ_HANDLED || epintr || usbintr)
+ dsps_writel(reg_base, wrp->eoi, 1);
+
+ /* Poll for ID change */
+ if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE)
+ mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return ret;
+}
+
+static int dsps_musb_init(struct musb *musb)
+{
+ struct device *dev = musb->controller;
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ struct omap_musb_board_data *data = plat->board_data;
+ void __iomem *reg_base = musb->ctrl_base;
+ u32 rev, val;
+ int status;
+
+ /* mentor core register starts at offset of 0x400 from musb base */
+ musb->mregs += wrp->musb_core_offset;
+
+ /* NOP driver needs change if supporting dual instance */
+ usb_nop_xceiv_register();
+ musb->xceiv = usb_get_transceiver();
+ if (!musb->xceiv)
+ return -ENODEV;
+
+ /* Returns zero if e.g. not clocked */
+ rev = dsps_readl(reg_base, wrp->revision);
+ if (!rev) {
+ status = -ENODEV;
+ goto err0;
+ }
+
+ if (is_host_enabled(musb))
+ setup_timer(&glue->timer, otg_timer, (unsigned long) musb);
+
+ /* Reset the musb */
+ dsps_writel(reg_base, wrp->control, (1 << wrp->reset));
+
+ /* Start the on-chip PHY and its PLL. */
+ if (data->set_phy_power)
+ data->set_phy_power(1);
+
+ musb->isr = dsps_interrupt;
+
+ /* reset the otgdisable bit, needed for host mode to work */
+ val = dsps_readl(reg_base, wrp->phy_utmi);
+ val &= ~(1 << wrp->otg_disable);
+ dsps_writel(musb->ctrl_base, wrp->phy_utmi, val);
+
+ /* clear level interrupt */
+ dsps_writel(reg_base, wrp->eoi, 0);
+
+ return 0;
+err0:
+ usb_put_transceiver(musb->xceiv);
+ usb_nop_xceiv_unregister();
+ return status;
+}
+
+static int dsps_musb_exit(struct musb *musb)
+{
+ struct device *dev = musb->controller;
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct omap_musb_board_data *data = plat->board_data;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+
+ if (is_host_enabled(musb))
+ del_timer_sync(&glue->timer);
+
+ /* Shutdown the on-chip PHY and its PLL. */
+ if (data->set_phy_power)
+ data->set_phy_power(0);
+
+ /* NOP driver needs change if supporting dual instance */
+ usb_put_transceiver(musb->xceiv);
+ usb_nop_xceiv_unregister();
+
+ return 0;
+}
+
+static struct musb_platform_ops dsps_ops = {
+ .init = dsps_musb_init,
+ .exit = dsps_musb_exit,
+
+ .enable = dsps_musb_enable,
+ .disable = dsps_musb_disable,
+
+ .try_idle = dsps_musb_try_idle,
+};
+
+static u64 musb_dmamask = DMA_BIT_MASK(32);
+
+static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
+{
+ struct device *dev = glue->dev;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct musb_hdrc_platform_data *pdata = dev->platform_data;
+ struct platform_device *musb;
+ struct resource *res;
+ struct resource resources[2];
+ char res_name[10];
+ int ret;
+
+ /* get memory resource */
+ sprintf(res_name, "musb%d", id);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
+ if (!res) {
+ dev_err(dev, "%s get mem resource failed\n", res_name);
+ ret = -ENODEV;
+ goto err0;
+ }
+ res->parent = NULL;
+ resources[0] = *res;
+
+ /* get irq resource */
+ sprintf(res_name, "musb%d-irq", id);
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
+ if (!res) {
+ dev_err(dev, "%s get irq resource failed\n", res_name);
+ ret = -ENODEV;
+ goto err0;
+ }
+ strcpy((u8 *)res->name, "mc");
+ res->parent = NULL;
+ resources[1] = *res;
+
+ /* allocate the child platform device */
+ musb = platform_device_alloc("musb-hdrc", -1);
+ if (!musb) {
+ dev_err(dev, "failed to allocate musb device\n");
+ ret = -ENOMEM;
+ goto err0;
+ }
+
+ musb->dev.parent = dev;
+ musb->dev.dma_mask = &musb_dmamask;
+ musb->dev.coherent_dma_mask = musb_dmamask;
+
+ glue->musb = musb;
+
+ pdata->platform_ops = &dsps_ops;
+
+ ret = platform_device_add_resources(musb, resources, 2);
+ if (ret) {
+ dev_err(dev, "failed to add resources\n");
+ goto err1;
+ }
+
+ ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+ if (ret) {
+ dev_err(dev, "failed to add platform_data\n");
+ goto err1;
+ }
+
+ ret = platform_device_add(musb);
+ if (ret) {
+ dev_err(dev, "failed to register musb device\n");
+ goto err1;
+ }
+
+ return 0;
+
+err1:
+ platform_device_put(musb);
+err0:
+ return ret;
+}
+
+static void __devexit dsps_delete_musb_pdev(struct dsps_glue *glue)
+{
+ platform_device_del(glue->musb);
+ platform_device_put(glue->musb);
+}
+
+static int __devinit dsps_probe(struct platform_device *pdev)
+{
+ const struct platform_device_id *id = platform_get_device_id(pdev);
+ const struct dsps_musb_wrapper *wrp =
+ (struct dsps_musb_wrapper *)id->driver_data;
+ struct dsps_glue *glue;
+ struct resource *iomem;
+ int ret;
+
+ /* allocate glue */
+ glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+ if (!glue) {
+ dev_err(&pdev->dev, "unable to allocate glue memory\n");
+ ret = -ENOMEM;
+ goto err0;
+ }
+
+ /* get memory resource */
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iomem) {
+ dev_err(&pdev->dev, "failed to get usbss mem resourse\n");
+ ret = -ENODEV;
+ goto err1;
+ }
+
+ glue->dev = &pdev->dev;
+
+ glue->wrp = kmemdup(wrp, sizeof(*wrp), GFP_KERNEL);
+ if (!glue->wrp) {
+ dev_err(&pdev->dev, "failed to duplicate wrapper struct memory\n");
+ ret = -ENOMEM;
+ goto err1;
+ }
+ platform_set_drvdata(pdev, glue);
+
+ /* create the child platform device for first instances of musb */
+ ret = dsps_create_musb_pdev(glue, 0);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "failed to create child pdev\n");
+ goto err2;
+ }
+
+ /* enable the usbss clocks */
+ pm_runtime_enable(&pdev->dev);
+
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "pm_runtime_get_sync FAILED");
+ goto err3;
+ }
+
+ return 0;
+
+err3:
+ pm_runtime_disable(&pdev->dev);
+err2:
+ kfree(glue->wrp);
+err1:
+ kfree(glue);
+err0:
+ return ret;
+}
+static int __devexit dsps_remove(struct platform_device *pdev)
+{
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+
+ /* delete the child platform device */
+ dsps_delete_musb_pdev(glue);
+
+ /* disable usbss clocks */
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ kfree(glue->wrp);
+ kfree(glue);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int dsps_suspend(struct device *dev)
+{
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct omap_musb_board_data *data = plat->board_data;
+
+ /* Shutdown the on-chip PHY and its PLL. */
+ if (data->set_phy_power)
+ data->set_phy_power(0);
+
+ return 0;
+}
+
+static int dsps_resume(struct device *dev)
+{
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct omap_musb_board_data *data = plat->board_data;
+
+ /* Start the on-chip PHY and its PLL. */
+ if (data->set_phy_power)
+ data->set_phy_power(1);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
+
+static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = {
+ .revision = 0x00,
+ .control = 0x14,
+ .status = 0x18,
+ .eoi = 0x24,
+ .epintr_set = 0x38,
+ .epintr_clear = 0x40,
+ .epintr_status = 0x30,
+ .coreintr_set = 0x3c,
+ .coreintr_clear = 0x44,
+ .coreintr_status = 0x34,
+ .phy_utmi = 0xe0,
+ .mode = 0xe8,
+ .reset = 0,
+ .otg_disable = 21,
+ .iddig = 8,
+ .usb_shift = 0,
+ .usb_mask = 0x1ff,
+ .usb_bitmap = (0x1ff << 0),
+ .drvvbus = 8,
+ .txep_shift = 0,
+ .txep_mask = 0xffff,
+ .txep_bitmap = (0xffff << 0),
+ .rxep_shift = 16,
+ .rxep_mask = 0xfffe,
+ .rxep_bitmap = (0xfffe << 16),
+ .musb_core_offset = 0x400,
+ .poll_seconds = 2,
+};
+
+static const struct platform_device_id musb_dsps_id_table[] __devinitconst = {
+ {
+ .name = "musb-ti81xx",
+ .driver_data = (kernel_ulong_t) &ti81xx_driver_data,
+ },
+ { }, /* Terminating Entry */
+};
+MODULE_DEVICE_TABLE(platform, musb_dsps_id_table);
+
+static const struct of_device_id musb_dsps_of_match[] __devinitconst = {
+ { .compatible = "musb-ti81xx", },
+ { .compatible = "ti,ti81xx-musb", },
+ { .compatible = "ti,am335x-musb", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
+
+static struct platform_driver dsps_usbss_driver = {
+ .probe = dsps_probe,
+ .remove = __devexit_p(dsps_remove),
+ .driver = {
+ .name = "musb-dsps",
+ .pm = &dsps_pm_ops,
+ .of_match_table = musb_dsps_of_match,
+ },
+ .id_table = musb_dsps_id_table,
+};
+
+MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer");
+MODULE_AUTHOR("Ravi B <ravibabu@ti.com>");
+MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init dsps_init(void)
+{
+ return platform_driver_register(&dsps_usbss_driver);
+}
+subsys_initcall(dsps_init);
+
+static void __exit dsps_exit(void)
+{
+ platform_driver_unregister(&dsps_usbss_driver);
+}
+module_exit(dsps_exit);
diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h
index 1d5eda26fbd1..f7c1c8e2dc3f 100644
--- a/drivers/usb/musb/musb_io.h
+++ b/drivers/usb/musb/musb_io.h
@@ -40,7 +40,7 @@
#if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \
&& !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \
&& !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) \
- && !defined(CONFIG_MIPS)
+ && !defined(CONFIG_MIPS) && !defined(CONFIG_M68K)
static inline void readsl(const void __iomem *addr, void *buf, int len)
{ insl((unsigned long)addr, buf, len); }
static inline void readsw(const void __iomem *addr, void *buf, int len)
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c
index a0a2178974fe..bde6298a9693 100644
--- a/drivers/usb/otg/gpio_vbus.c
+++ b/drivers/usb/otg/gpio_vbus.c
@@ -37,7 +37,9 @@ struct gpio_vbus_data {
struct regulator *vbus_draw;
int vbus_draw_enabled;
unsigned mA;
- struct work_struct work;
+ struct delayed_work work;
+ int vbus;
+ int irq;
};
@@ -51,8 +53,7 @@ struct gpio_vbus_data {
* edges might be workable.
*/
#define VBUS_IRQ_FLAGS \
- ( IRQF_SAMPLE_RANDOM | IRQF_SHARED \
- | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING )
+ (IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)
/* interface to regulator framework */
@@ -94,20 +95,26 @@ static int is_vbus_powered(struct gpio_vbus_mach_info *pdata)
static void gpio_vbus_work(struct work_struct *work)
{
struct gpio_vbus_data *gpio_vbus =
- container_of(work, struct gpio_vbus_data, work);
+ container_of(work, struct gpio_vbus_data, work.work);
struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
- int gpio, status;
+ int gpio, status, vbus;
if (!gpio_vbus->phy.otg->gadget)
return;
+ vbus = is_vbus_powered(pdata);
+ if ((vbus ^ gpio_vbus->vbus) == 0)
+ return;
+ gpio_vbus->vbus = vbus;
+
/* Peripheral controllers which manage the pullup themselves won't have
* gpio_pullup configured here. If it's configured here, we'll do what
* isp1301_omap::b_peripheral() does and enable the pullup here... although
* that may complicate usb_gadget_{,dis}connect() support.
*/
gpio = pdata->gpio_pullup;
- if (is_vbus_powered(pdata)) {
+
+ if (vbus) {
status = USB_EVENT_VBUS;
gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL;
gpio_vbus->phy.last_event = status;
@@ -152,7 +159,7 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data)
otg->gadget ? otg->gadget->name : "none");
if (otg->gadget)
- schedule_work(&gpio_vbus->work);
+ schedule_delayed_work(&gpio_vbus->work, msecs_to_jiffies(100));
return IRQ_HANDLED;
}
@@ -166,12 +173,11 @@ static int gpio_vbus_set_peripheral(struct usb_otg *otg,
struct gpio_vbus_data *gpio_vbus;
struct gpio_vbus_mach_info *pdata;
struct platform_device *pdev;
- int gpio, irq;
+ int gpio;
gpio_vbus = container_of(otg->phy, struct gpio_vbus_data, phy);
pdev = to_platform_device(gpio_vbus->dev);
pdata = gpio_vbus->dev->platform_data;
- irq = gpio_to_irq(pdata->gpio_vbus);
gpio = pdata->gpio_pullup;
if (!gadget) {
@@ -195,7 +201,8 @@ static int gpio_vbus_set_peripheral(struct usb_otg *otg,
dev_dbg(&pdev->dev, "registered gadget '%s'\n", gadget->name);
/* initialize connection state */
- gpio_vbus_irq(irq, pdev);
+ gpio_vbus->vbus = 0; /* start with disconnected */
+ gpio_vbus_irq(gpio_vbus->irq, pdev);
return 0;
}
@@ -235,6 +242,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
struct gpio_vbus_data *gpio_vbus;
struct resource *res;
int err, gpio, irq;
+ unsigned long irqflags;
if (!pdata || !gpio_is_valid(pdata->gpio_vbus))
return -EINVAL;
@@ -271,10 +279,13 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res) {
irq = res->start;
- res->flags &= IRQF_TRIGGER_MASK;
- res->flags |= IRQF_SAMPLE_RANDOM | IRQF_SHARED;
- } else
+ irqflags = (res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED;
+ } else {
irq = gpio_to_irq(gpio);
+ irqflags = VBUS_IRQ_FLAGS;
+ }
+
+ gpio_vbus->irq = irq;
/* if data line pullup is in use, initialize it to "not pulling up" */
gpio = pdata->gpio_pullup;
@@ -290,8 +301,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
gpio_direction_output(gpio, pdata->gpio_pullup_inverted);
}
- err = request_irq(irq, gpio_vbus_irq, VBUS_IRQ_FLAGS,
- "vbus_detect", pdev);
+ err = request_irq(irq, gpio_vbus_irq, irqflags, "vbus_detect", pdev);
if (err) {
dev_err(&pdev->dev, "can't request irq %i, err: %d\n",
irq, err);
@@ -300,7 +310,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
ATOMIC_INIT_NOTIFIER_HEAD(&gpio_vbus->phy.notifier);
- INIT_WORK(&gpio_vbus->work, gpio_vbus_work);
+ INIT_DELAYED_WORK(&gpio_vbus->work, gpio_vbus_work);
gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw");
if (IS_ERR(gpio_vbus->vbus_draw)) {
@@ -317,9 +327,12 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
goto err_otg;
}
+ device_init_wakeup(&pdev->dev, pdata->wakeup);
+
return 0;
err_otg:
- free_irq(irq, &pdev->dev);
+ regulator_put(gpio_vbus->vbus_draw);
+ free_irq(irq, pdev);
err_irq:
if (gpio_is_valid(pdata->gpio_pullup))
gpio_free(pdata->gpio_pullup);
@@ -337,11 +350,13 @@ static int __exit gpio_vbus_remove(struct platform_device *pdev)
struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
int gpio = pdata->gpio_vbus;
+ device_init_wakeup(&pdev->dev, 0);
+ cancel_delayed_work_sync(&gpio_vbus->work);
regulator_put(gpio_vbus->vbus_draw);
usb_set_transceiver(NULL);
- free_irq(gpio_to_irq(gpio), &pdev->dev);
+ free_irq(gpio_vbus->irq, pdev);
if (gpio_is_valid(pdata->gpio_pullup))
gpio_free(pdata->gpio_pullup);
gpio_free(gpio);
@@ -352,6 +367,33 @@ static int __exit gpio_vbus_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int gpio_vbus_pm_suspend(struct device *dev)
+{
+ struct gpio_vbus_data *gpio_vbus = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(gpio_vbus->irq);
+
+ return 0;
+}
+
+static int gpio_vbus_pm_resume(struct device *dev)
+{
+ struct gpio_vbus_data *gpio_vbus = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(gpio_vbus->irq);
+
+ return 0;
+}
+
+static const struct dev_pm_ops gpio_vbus_dev_pm_ops = {
+ .suspend = gpio_vbus_pm_suspend,
+ .resume = gpio_vbus_pm_resume,
+};
+#endif
+
/* NOTE: the gpio-vbus device may *NOT* be hotplugged */
MODULE_ALIAS("platform:gpio-vbus");
@@ -360,6 +402,9 @@ static struct platform_driver gpio_vbus_driver = {
.driver = {
.name = "gpio-vbus",
.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &gpio_vbus_dev_pm_ops,
+#endif
},
.remove = __exit_p(gpio_vbus_remove),
};
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index e3fa387ca81e..d2a9a8e691b9 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -455,7 +455,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
twl->irq_enabled = true;
status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"twl6030_usb", twl);
if (status < 0) {
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
@@ -467,7 +467,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
}
status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"twl6030_usb", twl);
if (status < 0) {
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
new file mode 100644
index 000000000000..3cfabcba7447
--- /dev/null
+++ b/drivers/usb/phy/Kconfig
@@ -0,0 +1,17 @@
+#
+# Physical Layer USB driver configuration
+#
+comment "USB Physical Layer drivers"
+ depends on USB
+
+config USB_ISP1301
+ tristate "NXP ISP1301 USB transceiver support"
+ depends on USB
+ depends on I2C
+ help
+ Say Y here to add support for the NXP ISP1301 USB transceiver driver.
+ This chip is typically used as USB transceiver for USB host, gadget
+ and OTG drivers (to be selected separately).
+
+ To compile this driver as a module, choose M here: the
+ module will be called isp1301.
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
new file mode 100644
index 000000000000..eca095b1a890
--- /dev/null
+++ b/drivers/usb/phy/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for physical layer USB drivers
+#
+
+ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
+
+obj-$(CONFIG_USB_ISP1301) += isp1301.o
diff --git a/drivers/usb/phy/isp1301.c b/drivers/usb/phy/isp1301.c
new file mode 100644
index 000000000000..b19f4932a037
--- /dev/null
+++ b/drivers/usb/phy/isp1301.c
@@ -0,0 +1,77 @@
+/*
+ * NXP ISP1301 USB transceiver driver
+ *
+ * Copyright (C) 2012 Roland Stigge
+ *
+ * Author: Roland Stigge <stigge@antcom.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+
+#define DRV_NAME "isp1301"
+
+#define ISP1301_I2C_ADDR 0x2C
+
+static const unsigned short normal_i2c[] = {
+ ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END
+};
+
+static const struct i2c_device_id isp1301_id[] = {
+ { "isp1301", 0 },
+ { }
+};
+
+static struct i2c_client *isp1301_i2c_client;
+
+static int isp1301_probe(struct i2c_client *client,
+ const struct i2c_device_id *i2c_id)
+{
+ isp1301_i2c_client = client;
+ return 0;
+}
+
+static int isp1301_remove(struct i2c_client *client)
+{
+ return 0;
+}
+
+static struct i2c_driver isp1301_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ },
+ .probe = isp1301_probe,
+ .remove = isp1301_remove,
+ .id_table = isp1301_id,
+};
+
+module_i2c_driver(isp1301_driver);
+
+static int match(struct device *dev, void *data)
+{
+ struct device_node *node = (struct device_node *)data;
+ return (dev->of_node == node) &&
+ (dev->driver == &isp1301_driver.driver);
+}
+
+struct i2c_client *isp1301_get_client(struct device_node *node)
+{
+ if (node) { /* reference of ISP1301 I2C node via DT */
+ struct device *dev = bus_find_device(&i2c_bus_type, NULL,
+ node, match);
+ if (!dev)
+ return NULL;
+ return to_i2c_client(dev);
+ } else { /* non-DT: only one ISP1301 chip supported */
+ return isp1301_i2c_client;
+ }
+}
+EXPORT_SYMBOL_GPL(isp1301_get_client);
+
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_DESCRIPTION("NXP ISP1301 USB transceiver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 00bd2a5e0362..28478ce26c34 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -55,6 +55,7 @@ struct usbhsg_gpriv {
#define USBHSG_STATUS_STARTED (1 << 0)
#define USBHSG_STATUS_REGISTERD (1 << 1)
#define USBHSG_STATUS_WEDGE (1 << 2)
+#define USBHSG_STATUS_SELF_POWERED (1 << 3)
};
struct usbhsg_recip_handle {
@@ -333,7 +334,10 @@ static int usbhsg_recip_handler_std_get_device(struct usbhs_priv *priv,
struct usb_ctrlrequest *ctrl)
{
struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
- unsigned short status = 1 << USB_DEVICE_SELF_POWERED;
+ unsigned short status = 0;
+
+ if (usbhsg_status_has(gpriv, USBHSG_STATUS_SELF_POWERED))
+ status = 1 << USB_DEVICE_SELF_POWERED;
__usbhsg_recip_send_status(gpriv, status);
@@ -879,8 +883,21 @@ static int usbhsg_get_frame(struct usb_gadget *gadget)
return usbhs_frame_get_num(priv);
}
+static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self)
+{
+ struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
+
+ if (is_self)
+ usbhsg_status_set(gpriv, USBHSG_STATUS_SELF_POWERED);
+ else
+ usbhsg_status_clr(gpriv, USBHSG_STATUS_SELF_POWERED);
+
+ return 0;
+}
+
static struct usb_gadget_ops usbhsg_gadget_ops = {
.get_frame = usbhsg_get_frame,
+ .set_selfpowered = usbhsg_set_selfpowered,
.udc_start = usbhsg_gadget_start,
.udc_stop = usbhsg_gadget_stop,
};
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 7141d6599060..325d2910f9f9 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -669,6 +669,15 @@ config USB_SERIAL_SSU100
To compile this driver as a module, choose M here: the
module will be called ssu100.
+config USB_SERIAL_QT2
+ tristate "USB Quatech Serial Driver for USB 2 devices"
+ help
+ Say Y here if you want to use the Quatech USB 2
+ serial adapters.
+
+ To compile this driver as a module, choose M here: the
+ module will be called quatech-serial.
+
config USB_SERIAL_DEBUG
tristate "USB Debugging Device"
help
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 07f198ee0486..1dc483a8bfc7 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o
obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
obj-$(CONFIG_USB_SERIAL_QCAUX) += qcaux.o
obj-$(CONFIG_USB_SERIAL_QUALCOMM) += qcserial.o
+obj-$(CONFIG_USB_SERIAL_QT2) += quatech2.o
obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o
obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index eec4fb9a35c1..d634e6635632 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -111,13 +111,14 @@ static int aircable_probe(struct usb_serial *serial,
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
endpoint = &iface_desc->endpoint[i].desc;
if (usb_endpoint_is_bulk_out(endpoint)) {
- dbg("found bulk out on endpoint %d", i);
+ dev_dbg(&serial->dev->dev,
+ "found bulk out on endpoint %d\n", i);
++num_bulk_out;
}
}
if (num_bulk_out == 0) {
- dbg("Invalid interface, discarding");
+ dev_dbg(&serial->dev->dev, "Invalid interface, discarding\n");
return -ENODEV;
}
@@ -133,7 +134,7 @@ static int aircable_process_packet(struct tty_struct *tty,
packet += HCI_HEADER_LENGTH;
}
if (len <= 0) {
- dbg("%s - malformed packet", __func__);
+ dev_dbg(&port->dev, "%s - malformed packet\n", __func__);
return 0;
}
@@ -170,13 +171,6 @@ static void aircable_process_read_urb(struct urb *urb)
tty_kref_put(tty);
}
-static struct usb_driver aircable_driver = {
- .name = "aircable",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver aircable_device = {
.driver = {
.owner = THIS_MODULE,
@@ -196,7 +190,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&aircable_device, NULL
};
-module_usb_serial_driver(aircable_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index f99f47100dd8..f8ce97d8b0ad 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -265,7 +265,7 @@ static void ark3116_set_termios(struct tty_struct *tty,
hcr = (cflag & CRTSCTS) ? 0x03 : 0x00;
/* calc baudrate */
- dbg("%s - setting bps to %d", __func__, bps);
+ dev_dbg(&port->dev, "%s - setting bps to %d\n", __func__, bps);
eval = 0;
switch (bps) {
case 0:
@@ -292,8 +292,8 @@ static void ark3116_set_termios(struct tty_struct *tty,
/* keep old LCR_SBC bit */
lcr |= (priv->lcr & UART_LCR_SBC);
- dbg("%s - setting hcr:0x%02x,lcr:0x%02x,quot:%d",
- __func__, hcr, lcr, quot);
+ dev_dbg(&port->dev, "%s - setting hcr:0x%02x,lcr:0x%02x,quot:%d\n",
+ __func__, hcr, lcr, quot);
/* handshake control */
if (priv->hcr != hcr) {
@@ -375,8 +375,9 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
result = usb_serial_generic_open(tty, port);
if (result) {
- dbg("%s - usb_serial_generic_open failed: %d",
- __func__, result);
+ dev_dbg(&port->dev,
+ "%s - usb_serial_generic_open failed: %d\n",
+ __func__, result);
goto err_out;
}
@@ -622,24 +623,26 @@ static void ark3116_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
break;
case 0: /* success */
/* discovered this by trail and error... */
if ((urb->actual_length == 4) && (data[0] == 0xe8)) {
const __u8 id = data[1]&UART_IIR_ID;
- dbg("%s: iir=%02x", __func__, data[1]);
+ dev_dbg(&port->dev, "%s: iir=%02x\n", __func__, data[1]);
if (id == UART_IIR_MSI) {
- dbg("%s: msr=%02x", __func__, data[3]);
+ dev_dbg(&port->dev, "%s: msr=%02x\n",
+ __func__, data[3]);
ark3116_update_msr(port, data[3]);
break;
} else if (id == UART_IIR_RLSI) {
- dbg("%s: lsr=%02x", __func__, data[2]);
+ dev_dbg(&port->dev, "%s: lsr=%02x\n",
+ __func__, data[2]);
ark3116_update_lsr(port, data[2]);
break;
}
@@ -714,13 +717,6 @@ static void ark3116_process_read_urb(struct urb *urb)
tty_kref_put(tty);
}
-static struct usb_driver ark3116_driver = {
- .name = "ark3116",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver ark3116_device = {
.driver = {
.owner = THIS_MODULE,
@@ -747,7 +743,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&ark3116_device, NULL
};
-module_usb_serial_driver(ark3116_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index a52e0d2cec31..6b7365632951 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -2,17 +2,17 @@
* Belkin USB Serial Adapter Driver
*
* Copyright (C) 2000 William Greathouse (wgreathouse@smva.com)
- * Copyright (C) 2000-2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2000-2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2010 Johan Hovold (jhovold@gmail.com)
*
* This program is largely derived from work by the linux-usb group
* and associated source files. Please see the usb/serial files for
* individual credits and copyrights.
*
- * 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 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.
*
* See Documentation/usb/usb-serial.txt for more information on using this
* driver
@@ -62,7 +62,7 @@ static int belkin_sa_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
-static const struct usb_device_id id_table_combined[] = {
+static const struct usb_device_id id_table[] = {
{ USB_DEVICE(BELKIN_SA_VID, BELKIN_SA_PID) },
{ USB_DEVICE(BELKIN_OLD_VID, BELKIN_OLD_PID) },
{ USB_DEVICE(PERACOM_VID, PERACOM_PID) },
@@ -71,14 +71,7 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE(usb, id_table_combined);
-
-static struct usb_driver belkin_driver = {
- .name = "belkin",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
-};
+MODULE_DEVICE_TABLE(usb, id_table);
/* All of the device info needed for the serial converters */
static struct usb_serial_driver belkin_device = {
@@ -87,7 +80,7 @@ static struct usb_serial_driver belkin_device = {
.name = "belkin",
},
.description = "Belkin / Peracom / GoHubs USB Serial Adapter",
- .id_table = id_table_combined,
+ .id_table = id_table,
.num_ports = 1,
.open = belkin_sa_open,
.close = belkin_sa_close,
@@ -159,8 +152,6 @@ static void belkin_sa_release(struct usb_serial *serial)
{
int i;
- dbg("%s", __func__);
-
for (i = 0; i < serial->num_ports; ++i)
kfree(usb_get_serial_port_data(serial->port[i]));
}
@@ -170,8 +161,6 @@ static int belkin_sa_open(struct tty_struct *tty,
{
int retval;
- dbg("%s port %d", __func__, port->number);
-
retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (retval) {
dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
@@ -187,8 +176,6 @@ static int belkin_sa_open(struct tty_struct *tty,
static void belkin_sa_close(struct usb_serial_port *port)
{
- dbg("%s port %d", __func__, port->number);
-
usb_serial_generic_close(port);
usb_kill_urb(port->interrupt_in_urb);
}
@@ -210,12 +197,12 @@ static void belkin_sa_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
@@ -403,7 +390,9 @@ static void belkin_sa_set_termios(struct tty_struct *tty,
case CS8:
urb_value = BELKIN_SA_DATA_BITS(8);
break;
- default: dbg("CSIZE was not CS5-CS8, using default of 8");
+ default:
+ dev_dbg(&port->dev,
+ "CSIZE was not CS5-CS8, using default of 8\n");
urb_value = BELKIN_SA_DATA_BITS(8);
break;
}
@@ -463,8 +452,6 @@ static int belkin_sa_tiocmget(struct tty_struct *tty)
unsigned long control_state;
unsigned long flags;
- dbg("%s", __func__);
-
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -484,8 +471,6 @@ static int belkin_sa_tiocmset(struct tty_struct *tty,
int rts = 0;
int dtr = 0;
- dbg("%s", __func__);
-
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
@@ -524,7 +509,7 @@ exit:
return retval;
}
-module_usb_serial_driver(belkin_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index ed8adb052ca7..f398d1e34474 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -124,8 +124,15 @@ static ssize_t store_new_id(struct device_driver *driver,
return retval;
}
+static ssize_t show_dynids(struct device_driver *driver, char *buf)
+{
+ struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver);
+
+ return usb_show_dynids(&usb_drv->dynids, buf);
+}
+
static struct driver_attribute drv_attrs[] = {
- __ATTR(new_id, S_IWUSR, NULL, store_new_id),
+ __ATTR(new_id, S_IRUGO | S_IWUSR, show_dynids, store_new_id),
__ATTR_NULL,
};
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index aaab32db31d0..cabd1b15ddce 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -125,8 +125,6 @@ static int ch341_set_baudrate(struct usb_device *dev,
unsigned long factor;
short divisor;
- dbg("ch341_set_baudrate(%d)", priv->baud_rate);
-
if (!priv->baud_rate)
return -EINVAL;
factor = (CH341_BAUDBASE_FACTOR / priv->baud_rate);
@@ -153,7 +151,6 @@ static int ch341_set_baudrate(struct usb_device *dev,
static int ch341_set_handshake(struct usb_device *dev, u8 control)
{
- dbg("ch341_set_handshake(0x%02x)", control);
return ch341_control_out(dev, 0xa4, ~control, 0);
}
@@ -164,8 +161,6 @@ static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
const unsigned size = 8;
unsigned long flags;
- dbg("ch341_get_status()");
-
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
@@ -196,8 +191,6 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
int r;
const unsigned size = 8;
- dbg("ch341_configure()");
-
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
@@ -254,8 +247,6 @@ static int ch341_attach(struct usb_serial *serial)
struct ch341_private *priv;
int r;
- dbg("ch341_attach()");
-
/* private data */
priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);
if (!priv)
@@ -290,7 +281,6 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on)
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
/* drop DTR and RTS */
spin_lock_irqsave(&priv->lock, flags);
if (on)
@@ -304,8 +294,6 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on)
static void ch341_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
-
usb_serial_generic_close(port);
usb_kill_urb(port->interrupt_in_urb);
}
@@ -318,8 +306,6 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
int r;
- dbg("ch341_open()");
-
priv->baud_rate = DEFAULT_BAUD_RATE;
r = ch341_configure(serial->dev, priv);
@@ -358,8 +344,6 @@ static void ch341_set_termios(struct tty_struct *tty,
unsigned baud_rate;
unsigned long flags;
- dbg("ch341_set_termios()");
-
baud_rate = tty_get_baud_rate(tty);
priv->baud_rate = baud_rate;
@@ -393,8 +377,6 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state)
uint16_t reg_contents;
uint8_t *break_reg;
- dbg("%s()", __func__);
-
break_reg = kmalloc(2, GFP_KERNEL);
if (!break_reg) {
dev_err(&port->dev, "%s - kmalloc failed\n", __func__);
@@ -461,8 +443,6 @@ static void ch341_read_int_callback(struct urb *urb)
unsigned int actual_length = urb->actual_length;
int status;
- dbg("%s (%d)", __func__, port->number);
-
switch (urb->status) {
case 0:
/* success */
@@ -580,8 +560,6 @@ static int ch341_tiocmget(struct tty_struct *tty)
u8 status;
unsigned int result;
- dbg("%s (%d)", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
mcr = priv->line_control;
status = priv->line_status;
@@ -599,35 +577,18 @@ static int ch341_tiocmget(struct tty_struct *tty)
return result;
}
-
-static int ch341_reset_resume(struct usb_interface *intf)
+static int ch341_reset_resume(struct usb_serial *serial)
{
- struct usb_device *dev = interface_to_usbdev(intf);
- struct usb_serial *serial = NULL;
struct ch341_private *priv;
- serial = usb_get_intfdata(intf);
priv = usb_get_serial_port_data(serial->port[0]);
- /*reconfigure ch341 serial port after bus-reset*/
- ch341_configure(dev, priv);
-
- usb_serial_resume(intf);
+ /* reconfigure ch341 serial port after bus-reset */
+ ch341_configure(serial->dev, priv);
return 0;
}
-static struct usb_driver ch341_driver = {
- .name = "ch341",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .reset_resume = ch341_reset_resume,
- .id_table = id_table,
- .supports_autosuspend = 1,
-};
-
static struct usb_serial_driver ch341_device = {
.driver = {
.owner = THIS_MODULE,
@@ -646,13 +607,14 @@ static struct usb_serial_driver ch341_device = {
.tiocmset = ch341_tiocmset,
.read_int_callback = ch341_read_int_callback,
.attach = ch341_attach,
+ .reset_resume = ch341_reset_resume,
};
static struct usb_serial_driver * const serial_drivers[] = {
&ch341_device, NULL
};
-module_usb_serial_driver(ch341_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 1ee6b2ab0f89..b9cca6dcde07 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -113,7 +113,8 @@ static int usb_console_setup(struct console *co, char *options)
serial = usb_serial_get_by_index(co->index);
if (serial == NULL) {
/* no device is connected yet, sorry :( */
- err("No USB device connected to ttyUSB%i", co->index);
+ printk(KERN_ERR "No USB device connected to ttyUSB%i\n",
+ co->index);
return -ENODEV;
}
@@ -137,7 +138,7 @@ static int usb_console_setup(struct console *co, char *options)
tty = kzalloc(sizeof(*tty), GFP_KERNEL);
if (!tty) {
retval = -ENOMEM;
- err("no more memory");
+ dev_err(&port->dev, "no more memory\n");
goto reset_open_count;
}
kref_init(&tty->kref);
@@ -146,7 +147,7 @@ static int usb_console_setup(struct console *co, char *options)
tty->index = co->index;
if (tty_init_termios(tty)) {
retval = -ENOMEM;
- err("no more memory");
+ dev_err(&port->dev, "no more memory\n");
goto free_tty;
}
}
@@ -159,7 +160,7 @@ static int usb_console_setup(struct console *co, char *options)
retval = usb_serial_generic_open(NULL, port);
if (retval) {
- err("could not open USB console port");
+ dev_err(&port->dev, "could not open USB console port\n");
goto fail;
}
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index ec30f95ef399..1b1926200ba7 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -156,13 +156,6 @@ struct cp210x_port_private {
__u8 bInterfaceNumber;
};
-static struct usb_driver cp210x_driver = {
- .name = "cp210x",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver cp210x_device = {
.driver = {
.owner = THIS_MODULE,
@@ -188,8 +181,10 @@ static struct usb_serial_driver * const serial_drivers[] = {
};
/* Config request types */
-#define REQTYPE_HOST_TO_DEVICE 0x41
-#define REQTYPE_DEVICE_TO_HOST 0xc1
+#define REQTYPE_HOST_TO_INTERFACE 0x41
+#define REQTYPE_INTERFACE_TO_HOST 0xc1
+#define REQTYPE_HOST_TO_DEVICE 0x40
+#define REQTYPE_DEVICE_TO_HOST 0xc0
/* Config request codes */
#define CP210X_IFC_ENABLE 0x00
@@ -286,7 +281,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
/* Issue the request, attempting to read 'size' bytes */
result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- request, REQTYPE_DEVICE_TO_HOST, 0x0000,
+ request, REQTYPE_INTERFACE_TO_HOST, 0x0000,
port_priv->bInterfaceNumber, buf, size,
USB_CTRL_GET_TIMEOUT);
@@ -340,13 +335,13 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
if (size > 2) {
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
- request, REQTYPE_HOST_TO_DEVICE, 0x0000,
+ request, REQTYPE_HOST_TO_INTERFACE, 0x0000,
port_priv->bInterfaceNumber, buf, size,
USB_CTRL_SET_TIMEOUT);
} else {
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
- request, REQTYPE_HOST_TO_DEVICE, data[0],
+ request, REQTYPE_HOST_TO_INTERFACE, data[0],
port_priv->bInterfaceNumber, NULL, 0,
USB_CTRL_SET_TIMEOUT);
}
@@ -422,8 +417,6 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
{
int result;
- dbg("%s - port %d", __func__, port->number);
-
result = cp210x_set_config_single(port, CP210X_IFC_ENABLE,
UART_ENABLE);
if (result) {
@@ -443,8 +436,6 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
static void cp210x_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
-
usb_serial_generic_close(port);
mutex_lock(&port->serial->disc_mutex);
@@ -488,8 +479,6 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
unsigned int baud;
unsigned int bits;
- dbg("%s - port %d", __func__, port->number);
-
cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4);
dbg("%s - baud rate = %d", __func__, baud);
@@ -787,8 +776,6 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port,
{
unsigned int control = 0;
- dbg("%s - port %d", __func__, port->number);
-
if (set & TIOCM_RTS) {
control |= CONTROL_RTS;
control |= CONTROL_WRITE_RTS;
@@ -825,8 +812,6 @@ static int cp210x_tiocmget (struct tty_struct *tty)
unsigned int control;
int result;
- dbg("%s - port %d", __func__, port->number);
-
cp210x_get_config(port, CP210X_GET_MDMSTS, &control, 1);
result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0)
@@ -846,7 +831,6 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
struct usb_serial_port *port = tty->driver_data;
unsigned int state;
- dbg("%s - port %d", __func__, port->number);
if (break_state == 0)
state = BREAK_OFF;
else
@@ -891,7 +875,7 @@ static void cp210x_release(struct usb_serial *serial)
}
}
-module_usb_serial_driver(cp210x_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index d39b9418f2fb..3aa0b530f68e 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -77,13 +77,6 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver cyberjack_driver = {
- .name = "cyberjack",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver cyberjack_device = {
.driver = {
.owner = THIS_MODULE,
@@ -122,8 +115,6 @@ static int cyberjack_startup(struct usb_serial *serial)
struct cyberjack_private *priv;
int i;
- dbg("%s", __func__);
-
/* allocate the private data structure */
priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
if (!priv)
@@ -155,8 +146,6 @@ static void cyberjack_disconnect(struct usb_serial *serial)
{
int i;
- dbg("%s", __func__);
-
for (i = 0; i < serial->num_ports; ++i)
usb_kill_urb(serial->port[i]->interrupt_in_urb);
}
@@ -165,8 +154,6 @@ static void cyberjack_release(struct usb_serial *serial)
{
int i;
- dbg("%s", __func__);
-
for (i = 0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
kfree(usb_get_serial_port_data(serial->port[i]));
@@ -180,8 +167,6 @@ static int cyberjack_open(struct tty_struct *tty,
unsigned long flags;
int result = 0;
- dbg("%s - port %d", __func__, port->number);
-
dbg("%s - usb_clear_halt", __func__);
usb_clear_halt(port->serial->dev, port->write_urb->pipe);
@@ -197,8 +182,6 @@ static int cyberjack_open(struct tty_struct *tty,
static void cyberjack_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
-
if (port->serial->dev) {
/* shutdown any bulk reads that might be going on */
usb_kill_urb(port->write_urb);
@@ -214,8 +197,6 @@ static int cyberjack_write(struct tty_struct *tty,
int result;
int wrexpected;
- dbg("%s - port %d", __func__, port->number);
-
if (count == 0) {
dbg("%s - write request of 0 bytes", __func__);
return 0;
@@ -307,8 +288,6 @@ static void cyberjack_read_int_callback(struct urb *urb)
int status = urb->status;
int result;
- dbg("%s - port %d", __func__, port->number);
-
/* the urb might have been killed. */
if (status)
return;
@@ -367,8 +346,6 @@ static void cyberjack_read_bulk_callback(struct urb *urb)
int result;
int status = urb->status;
- dbg("%s - port %d", __func__, port->number);
-
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, data);
if (status) {
@@ -417,8 +394,6 @@ static void cyberjack_write_bulk_callback(struct urb *urb)
struct cyberjack_private *priv = usb_get_serial_port_data(port);
int status = urb->status;
- dbg("%s - port %d", __func__, port->number);
-
set_bit(0, &port->write_urbs_free);
if (status) {
dbg("%s - nonzero write bulk status received: %d",
@@ -475,7 +450,7 @@ exit:
usb_serial_port_softint(port);
}
-module_usb_serial_driver(cyberjack_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index afc886c75d2f..b78c34eb5d3f 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -89,13 +89,6 @@ static const struct usb_device_id id_table_combined[] = {
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver cypress_driver = {
- .name = "cypress",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
-};
-
enum packet_format {
packet_format_1, /* b0:status, b1:payload count */
packet_format_2 /* b0[7:3]:status, b0[2:0]:payload count */
@@ -305,8 +298,6 @@ static int cypress_serial_control(struct tty_struct *tty,
const unsigned int feature_len = 5;
unsigned long flags;
- dbg("%s", __func__);
-
priv = usb_get_serial_port_data(port);
if (!priv->comm_is_ok)
@@ -451,8 +442,6 @@ static int generic_startup(struct usb_serial *serial)
struct cypress_private *priv;
struct usb_serial_port *port = serial->port[0];
- dbg("%s - port %d", __func__, port->number);
-
priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -505,8 +494,6 @@ static int cypress_earthmate_startup(struct usb_serial *serial)
struct cypress_private *priv;
struct usb_serial_port *port = serial->port[0];
- dbg("%s", __func__);
-
if (generic_startup(serial)) {
dbg("%s - Failed setting up port %d", __func__,
port->number);
@@ -537,8 +524,6 @@ static int cypress_hidcom_startup(struct usb_serial *serial)
{
struct cypress_private *priv;
- dbg("%s", __func__);
-
if (generic_startup(serial)) {
dbg("%s - Failed setting up port %d", __func__,
serial->port[0]->number);
@@ -556,8 +541,6 @@ static int cypress_ca42v2_startup(struct usb_serial *serial)
{
struct cypress_private *priv;
- dbg("%s", __func__);
-
if (generic_startup(serial)) {
dbg("%s - Failed setting up port %d", __func__,
serial->port[0]->number);
@@ -575,10 +558,7 @@ static void cypress_release(struct usb_serial *serial)
{
struct cypress_private *priv;
- dbg("%s - port %d", __func__, serial->port[0]->number);
-
/* all open ports are closed at this point */
-
priv = usb_get_serial_port_data(serial->port[0]);
if (priv) {
@@ -595,8 +575,6 @@ static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port)
unsigned long flags;
int result = 0;
- dbg("%s - port %d", __func__, port->number);
-
if (!priv->comm_is_ok)
return -EIO;
@@ -661,8 +639,6 @@ static void cypress_close(struct usb_serial_port *port)
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
/* writing is potentially harmful, lock must be taken */
mutex_lock(&port->serial->disc_mutex);
if (port->serial->disconnected) {
@@ -720,7 +696,6 @@ static void cypress_send(struct usb_serial_port *port)
if (!priv->comm_is_ok)
return;
- dbg("%s - port %d", __func__, port->number);
dbg("%s - interrupt out size is %d", __func__,
port->interrupt_out_size);
@@ -828,8 +803,6 @@ static int cypress_write_room(struct tty_struct *tty)
int room = 0;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
room = kfifo_avail(&priv->write_fifo);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -847,8 +820,6 @@ static int cypress_tiocmget(struct tty_struct *tty)
unsigned int result = 0;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
control = priv->line_control;
status = priv->current_status;
@@ -874,8 +845,6 @@ static int cypress_tiocmset(struct tty_struct *tty,
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
if (set & TIOCM_RTS)
priv->line_control |= CONTROL_RTS;
@@ -948,8 +917,6 @@ static void cypress_set_termios(struct tty_struct *tty,
__u8 oldlines;
int linechange = 0;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
/* We can't clean this one up as we don't know the device type
early enough */
@@ -1096,8 +1063,6 @@ static int cypress_chars_in_buffer(struct tty_struct *tty)
int chars = 0;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
chars = kfifo_len(&priv->write_fifo);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1112,8 +1077,6 @@ static void cypress_throttle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irq(&priv->lock);
priv->rx_flags = THROTTLED;
spin_unlock_irq(&priv->lock);
@@ -1126,8 +1089,6 @@ static void cypress_unthrottle(struct tty_struct *tty)
struct cypress_private *priv = usb_get_serial_port_data(port);
int actually_throttled, result;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irq(&priv->lock);
actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
priv->rx_flags = 0;
@@ -1161,8 +1122,6 @@ static void cypress_read_int_callback(struct urb *urb)
int i = 0;
int status = urb->status;
- dbg("%s - port %d", __func__, port->number);
-
switch (status) {
case 0: /* success */
break;
@@ -1303,8 +1262,6 @@ static void cypress_write_int_callback(struct urb *urb)
int result;
int status = urb->status;
- dbg("%s - port %d", __func__, port->number);
-
switch (status) {
case 0:
/* success */
@@ -1346,7 +1303,7 @@ static void cypress_write_int_callback(struct urb *urb)
cypress_send(port);
}
-module_usb_serial_driver(cypress_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 999f91bf70de..b5cd838093ef 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -271,14 +271,6 @@ static const struct usb_device_id id_table_4[] = {
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver digi_driver = {
- .name = "digi_acceleport",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
-};
-
-
/* device info needed for the Digi serial converter */
static struct usb_serial_driver digi_acceleport_2_device = {
@@ -657,9 +649,6 @@ static void digi_rx_throttle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
-
- dbg("digi_rx_throttle: TOP: port=%d", priv->dp_port_num);
-
/* stop receiving characters by not resubmitting the read urb */
spin_lock_irqsave(&priv->dp_port_lock, flags);
priv->dp_throttled = 1;
@@ -675,8 +664,6 @@ static void digi_rx_unthrottle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
- dbg("digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num);
-
spin_lock_irqsave(&priv->dp_port_lock, flags);
/* restart read chain */
@@ -904,8 +891,6 @@ static int digi_tiocmget(struct tty_struct *tty)
unsigned int val;
unsigned long flags;
- dbg("%s: TOP: port=%d", __func__, priv->dp_port_num);
-
spin_lock_irqsave(&priv->dp_port_lock, flags);
val = priv->dp_modem_signals;
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
@@ -921,8 +906,6 @@ static int digi_tiocmset(struct tty_struct *tty,
unsigned int val;
unsigned long flags;
- dbg("%s: TOP: port=%d", __func__, priv->dp_port_num);
-
spin_lock_irqsave(&priv->dp_port_lock, flags);
val = (priv->dp_modem_signals & ~clear) | set;
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
@@ -1013,8 +996,6 @@ static void digi_write_bulk_callback(struct urb *urb)
int ret = 0;
int status = urb->status;
- dbg("digi_write_bulk_callback: TOP, status=%d", status);
-
/* port and serial sanity check */
if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
pr_err("%s: port or port->private is NULL, status=%d\n",
@@ -1121,8 +1102,6 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
struct digi_port *priv = usb_get_serial_port_data(port);
struct ktermios not_termios;
- dbg("digi_open: TOP: port=%d", priv->dp_port_num);
-
/* be sure the device is started up */
if (digi_startup_device(port->serial) != 0)
return -ENXIO;
@@ -1160,8 +1139,6 @@ static void digi_close(struct usb_serial_port *port)
unsigned char buf[32];
struct digi_port *priv = usb_get_serial_port_data(port);
- dbg("digi_close: TOP: port=%d", priv->dp_port_num);
-
mutex_lock(&port->serial->disc_mutex);
/* if disconnected, just clear flags */
if (port->serial->disconnected)
@@ -1220,7 +1197,6 @@ exit:
wake_up_interruptible(&priv->dp_close_wait);
spin_unlock_irq(&priv->dp_port_lock);
mutex_unlock(&port->serial->disc_mutex);
- dbg("digi_close: done");
}
@@ -1269,8 +1245,6 @@ static int digi_startup(struct usb_serial *serial)
struct digi_port *priv;
struct digi_serial *serial_priv;
- dbg("digi_startup: TOP");
-
/* allocate the private data structures for all ports */
/* number of regular ports + 1 for the out-of-band port */
for (i = 0; i < serial->type->num_ports + 1; i++) {
@@ -1325,7 +1299,6 @@ static int digi_startup(struct usb_serial *serial)
static void digi_disconnect(struct usb_serial *serial)
{
int i;
- dbg("digi_disconnect: TOP, in_interrupt()=%ld", in_interrupt());
/* stop reads and writes on all ports */
for (i = 0; i < serial->type->num_ports + 1; i++) {
@@ -1338,7 +1311,6 @@ static void digi_disconnect(struct usb_serial *serial)
static void digi_release(struct usb_serial *serial)
{
int i;
- dbg("digi_release: TOP, in_interrupt()=%ld", in_interrupt());
/* free the private data structures for all ports */
/* number of regular ports + 1 for the out-of-band port */
@@ -1356,8 +1328,6 @@ static void digi_read_bulk_callback(struct urb *urb)
int ret;
int status = urb->status;
- dbg("digi_read_bulk_callback: TOP");
-
/* port sanity check, do not resubmit if port is not valid */
if (port == NULL)
return;
@@ -1507,9 +1477,6 @@ static int digi_read_oob_callback(struct urb *urb)
int i;
unsigned int rts;
- dbg("digi_read_oob_callback: port=%d, len=%d",
- priv->dp_port_num, urb->actual_length);
-
/* handle each oob command */
for (i = 0; i < urb->actual_length - 3;) {
opcode = ((unsigned char *)urb->transfer_buffer)[i++];
@@ -1580,7 +1547,7 @@ static int digi_read_oob_callback(struct urb *urb)
}
-module_usb_serial_driver(digi_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 5b99fc09e327..cdf61dd07318 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -51,13 +51,6 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver empeg_driver = {
- .name = "empeg",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver empeg_device = {
.driver = {
.owner = THIS_MODULE,
@@ -80,14 +73,12 @@ static int empeg_startup(struct usb_serial *serial)
{
int r;
- dbg("%s", __func__);
-
if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
dev_err(&serial->dev->dev, "active config #%d != 1 ??\n",
serial->dev->actconfig->desc.bConfigurationValue);
return -ENODEV;
}
- dbg("%s - reset config", __func__);
+
r = usb_reset_configuration(serial->dev);
/* continue on with initialization */
@@ -138,7 +129,7 @@ static void empeg_init_termios(struct tty_struct *tty)
tty_encode_baud_rate(tty, 115200, 115200);
}
-module_usb_serial_driver(empeg_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
index 3cfc762f5056..800e8eb60003 100644
--- a/drivers/usb/serial/ezusb.c
+++ b/drivers/usb/serial/ezusb.c
@@ -26,7 +26,6 @@ int ezusb_writememory(struct usb_serial *serial, int address,
int result;
unsigned char *transfer_buffer;
- /* dbg("ezusb_writememory %x, %d", address, length); */
if (!serial->dev) {
printk(KERN_ERR "ezusb: %s - no physical device present, "
"failing.\n", __func__);
@@ -50,7 +49,6 @@ int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit)
{
int response;
- /* dbg("%s - %d", __func__, reset_bit); */
response = ezusb_writememory(serial, CPUCS_REG, &reset_bit, 1, 0xa0);
if (response < 0)
dev_err(&serial->dev->dev, "%s- %d failed\n",
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index 88c0b1963920..499b15fd82f1 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -68,8 +68,6 @@ static void f81232_read_int_callback(struct urb *urb)
int status = urb->status;
int retval;
- dbg("%s (%d)", __func__, port->number);
-
switch (status) {
case 0:
/* success */
@@ -78,12 +76,12 @@ static void f81232_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__,
- status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__,
- status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
@@ -133,7 +131,7 @@ static void f81232_process_read_urb(struct urb *urb)
tty_flag = TTY_PARITY;
else if (line_status & UART_FRAME_ERROR)
tty_flag = TTY_FRAME;
- dbg("%s - tty_flag = %d", __func__, tty_flag);
+ dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__, tty_flag);
/* overrun is special, not associated with a char */
if (line_status & UART_OVERRUN_ERROR)
@@ -203,7 +201,6 @@ static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port)
if (tty)
f81232_set_termios(tty, port, &tmp_termios);
- dbg("%s - submitting interrupt urb", __func__);
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result) {
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
@@ -293,7 +290,9 @@ static int f81232_ioctl(struct tty_struct *tty,
{
struct serial_struct ser;
struct usb_serial_port *port = tty->driver_data;
- dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
+
+ dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__,
+ port->number, cmd);
switch (cmd) {
case TIOCGSERIAL:
@@ -309,10 +308,12 @@ static int f81232_ioctl(struct tty_struct *tty,
return 0;
case TIOCMIWAIT:
- dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
+ dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,
+ port->number);
return wait_modem_info(port, arg);
default:
- dbg("%s not supported = 0x%04x", __func__, cmd);
+ dev_dbg(&port->dev, "%s not supported = 0x%04x\n",
+ __func__, cmd);
break;
}
return -ENOIOCTLCMD;
@@ -353,24 +354,12 @@ static void f81232_release(struct usb_serial *serial)
}
}
-static struct usb_driver f81232_driver = {
- .name = "f81232",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .no_dynamic_id = 1,
- .supports_autosuspend = 1,
-};
-
static struct usb_serial_driver f81232_device = {
.driver = {
.owner = THIS_MODULE,
.name = "f81232",
},
.id_table = id_table,
- .usb_driver = &f81232_driver,
.num_ports = 1,
.bulk_in_size = 256,
.bulk_out_size = 256,
@@ -394,7 +383,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
NULL,
};
-module_usb_serial_driver(f81232_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION("Fintek F81232 USB to serial adaptor driver");
MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org");
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 02e7f2d32d52..8c084ea34e26 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -809,6 +809,7 @@ static struct usb_device_id id_table_combined [] = {
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },
{ USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) },
+ { USB_DEVICE(PI_VID, PI_E861_PID) },
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
@@ -861,13 +862,6 @@ static struct usb_device_id id_table_combined [] = {
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver ftdi_driver = {
- .name = "ftdi_sio",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
-};
-
static const char *ftdi_chip_name[] = {
[SIO] = "SIO", /* the serial part of FT8U100AX */
[FT8U232AM] = "FT8U232AM",
@@ -1285,8 +1279,6 @@ static int read_latency_timer(struct usb_serial_port *port)
unsigned char *buf;
int rv;
- dbg("%s", __func__);
-
buf = kmalloc(1, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -1593,8 +1585,6 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
struct ftdi_private *priv = usb_get_serial_port_data(port);
int retval = 0;
- dbg("%s", __func__);
-
/* XXX I've no idea if the original SIO supports the event_char
* sysfs parameter, so I'm playing it safe. */
if (priv->chip_type != SIO) {
@@ -1619,8 +1609,6 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
- dbg("%s", __func__);
-
/* XXX see create_sysfs_attrs */
if (priv->chip_type != SIO) {
device_remove_file(&port->dev, &dev_attr_event_char);
@@ -1667,8 +1655,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
- dbg("%s", __func__);
-
priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
if (!priv) {
dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__,
@@ -1704,8 +1690,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
/* Called from usbserial:serial_probe */
static void ftdi_USB_UIRT_setup(struct ftdi_private *priv)
{
- dbg("%s", __func__);
-
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 77;
priv->force_baud = 38400;
@@ -1716,8 +1700,6 @@ static void ftdi_USB_UIRT_setup(struct ftdi_private *priv)
static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv)
{
- dbg("%s", __func__);
-
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 240;
priv->force_baud = 38400;
@@ -1767,8 +1749,6 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
struct usb_device *udev = serial->dev;
struct usb_interface *interface = serial->interface;
- dbg("%s", __func__);
-
if (interface == udev->actconfig->interface[0]) {
dev_info(&udev->dev,
"Ignoring serial port reserved for JTAG\n");
@@ -1782,8 +1762,6 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)
{
struct usb_device *udev = serial->dev;
- dbg("%s", __func__);
-
if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
(udev->product && !strcmp(udev->product, "BeagleBone/XDS100")))
return ftdi_jtag_probe(serial);
@@ -1800,8 +1778,6 @@ static int ftdi_stmclite_probe(struct usb_serial *serial)
struct usb_device *udev = serial->dev;
struct usb_interface *interface = serial->interface;
- dbg("%s", __func__);
-
if (interface == udev->actconfig->interface[2])
return 0;
@@ -1839,8 +1815,6 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
- dbg("%s", __func__);
-
priv->dev_gone = true;
wake_up_interruptible_all(&priv->delta_msr_wait);
@@ -1858,8 +1832,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
struct ftdi_private *priv = usb_get_serial_port_data(port);
int result;
- dbg("%s", __func__);
-
/* No error checking for this (will get errors later anyway) */
/* See ftdi_sio.h for description of what is reset */
usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -1918,8 +1890,6 @@ static void ftdi_close(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
- dbg("%s", __func__);
-
usb_serial_generic_close(port);
kref_put(&priv->kref, ftdi_sio_priv_release);
}
@@ -1976,8 +1946,6 @@ static int ftdi_process_packet(struct tty_struct *tty,
char flag;
char *ch;
- dbg("%s - port %d", __func__, port->number);
-
if (len < 2) {
dbg("malformed packet");
return 0;
@@ -2121,8 +2089,6 @@ static void ftdi_set_termios(struct tty_struct *tty,
unsigned char vstop;
unsigned char vstart;
- dbg("%s", __func__);
-
/* Force baud rate if this device requires it, unless it is set to
B0. */
if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) {
@@ -2295,8 +2261,6 @@ static int ftdi_tiocmget(struct tty_struct *tty)
int len;
int ret;
- dbg("%s TIOCMGET", __func__);
-
buf = kmalloc(2, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -2346,7 +2310,7 @@ static int ftdi_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s TIOCMSET", __func__);
+
return update_mctrl(port, set, clear);
}
@@ -2435,7 +2399,6 @@ static int __init ftdi_init(void)
{
int retval;
- dbg("%s", __func__);
if (vendor > 0 && product > 0) {
/* Add user specified VID/PID to reserved element of table. */
int i;
@@ -2445,7 +2408,7 @@ static int __init ftdi_init(void)
id_table_combined[i].idVendor = vendor;
id_table_combined[i].idProduct = product;
}
- retval = usb_serial_register_drivers(&ftdi_driver, serial_drivers);
+ retval = usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, id_table_combined);
if (retval == 0)
printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
DRIVER_DESC "\n");
@@ -2454,9 +2417,7 @@ static int __init ftdi_init(void)
static void __exit ftdi_exit(void)
{
- dbg("%s", __func__);
-
- usb_serial_deregister_drivers(&ftdi_driver, serial_drivers);
+ usb_serial_deregister_drivers(serial_drivers);
}
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 0838baf892f3..f3c7c78ede33 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -785,6 +785,14 @@
#define RTSYSTEMS_SERIAL_VX7_PID 0x9e52 /* Serial converter for VX-7 Radios using FT232RL */
#define RTSYSTEMS_CT29B_PID 0x9e54 /* CT29B Radio Cable */
+
+/*
+ * Physik Instrumente
+ * http://www.physikinstrumente.com/en/products/
+ */
+#define PI_VID 0x1a72 /* Vendor ID */
+#define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */
+
/*
* Bayer Ascensia Contour blood glucose meter USB-converter cable.
* http://winglucofacts.com/cables/
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
index 4577b3607922..235707961ca3 100644
--- a/drivers/usb/serial/funsoft.c
+++ b/drivers/usb/serial/funsoft.c
@@ -24,13 +24,6 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver funsoft_driver = {
- .name = "funsoft",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver funsoft_device = {
.driver = {
.owner = THIS_MODULE,
@@ -44,7 +37,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&funsoft_device, NULL
};
-module_usb_serial_driver(funsoft_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index e8eb6347bf3a..346c15a51066 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -216,16 +216,8 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(GARMIN_VENDOR_ID, 3) },
{ } /* Terminating entry */
};
-
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver garmin_driver = {
- .name = "garmin_gps",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static inline int getLayerId(const __u8 *usbPacket)
{
@@ -345,8 +337,6 @@ static void pkt_clear(struct garmin_data *garmin_data_p)
unsigned long flags;
struct garmin_packet *result = NULL;
- dbg("%s", __func__);
-
spin_lock_irqsave(&garmin_data_p->lock, flags);
while (!list_empty(&garmin_data_p->pktlist)) {
result = (struct garmin_packet *)garmin_data_p->pktlist.next;
@@ -939,8 +929,6 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port)
int status = 0;
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->mode = initial_mode;
garmin_data_p->count = 0;
@@ -996,8 +984,6 @@ static void garmin_write_bulk_callback(struct urb *urb)
struct garmin_data *garmin_data_p =
usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
-
if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer)) {
if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
@@ -1027,9 +1013,6 @@ static int garmin_write_bulk(struct usb_serial_port *port,
unsigned char *buffer;
int status;
- dbg("%s - port %d, state %d", __func__, port->number,
- garmin_data_p->state);
-
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags &= ~FLAGS_DROP_DATA;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
@@ -1224,8 +1207,6 @@ static void garmin_read_bulk_callback(struct urb *urb)
int status = urb->status;
int retval;
- dbg("%s - port %d", __func__, port->number);
-
if (!serial) {
dbg("%s - bad serial pointer, exiting", __func__);
return;
@@ -1384,7 +1365,6 @@ static void garmin_throttle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
/* set flag, data received will be put into a queue
for later processing */
spin_lock_irq(&garmin_data_p->lock);
@@ -1399,7 +1379,6 @@ static void garmin_unthrottle(struct tty_struct *tty)
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
int status;
- dbg("%s - port %d", __func__, port->number);
spin_lock_irq(&garmin_data_p->lock);
garmin_data_p->flags &= ~FLAGS_THROTTLED;
spin_unlock_irq(&garmin_data_p->lock);
@@ -1441,8 +1420,6 @@ static int garmin_attach(struct usb_serial *serial)
struct usb_serial_port *port = serial->port[0];
struct garmin_data *garmin_data_p = NULL;
- dbg("%s", __func__);
-
garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
if (garmin_data_p == NULL) {
dev_err(&port->dev, "%s - Out of memory\n", __func__);
@@ -1471,8 +1448,6 @@ static void garmin_disconnect(struct usb_serial *serial)
struct usb_serial_port *port = serial->port[0];
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
- dbg("%s", __func__);
-
usb_kill_urb(port->interrupt_in_urb);
del_timer_sync(&garmin_data_p->timer);
}
@@ -1483,8 +1458,6 @@ static void garmin_release(struct usb_serial *serial)
struct usb_serial_port *port = serial->port[0];
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
- dbg("%s", __func__);
-
kfree(garmin_data_p);
}
@@ -1516,7 +1489,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&garmin_device, NULL
};
-module_usb_serial_driver(garmin_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 664deb63807c..105a6d898ca4 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -28,9 +28,6 @@ static int debug;
#ifdef CONFIG_USB_SERIAL_GENERIC
-static int generic_probe(struct usb_interface *interface,
- const struct usb_device_id *id);
-
static __u16 vendor = 0x05f9;
static __u16 product = 0xffff;
@@ -49,13 +46,6 @@ static const struct usb_device_id generic_serial_ids[] = {
{}
};
-static struct usb_driver generic_driver = {
- .name = "usbserial_generic",
- .probe = generic_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = generic_serial_ids,
-};
-
/* All of the device info needed for the Generic Serial Converter */
struct usb_serial_driver usb_serial_generic_device = {
.driver = {
@@ -75,16 +65,6 @@ static struct usb_serial_driver * const serial_drivers[] = {
&usb_serial_generic_device, NULL
};
-static int generic_probe(struct usb_interface *interface,
- const struct usb_device_id *id)
-{
- const struct usb_device_id *id_pattern;
-
- id_pattern = usb_match_id(interface, generic_device_ids);
- if (id_pattern != NULL)
- return usb_serial_probe(interface, id);
- return -ENODEV;
-}
#endif
int usb_serial_generic_register(int _debug)
@@ -99,7 +79,7 @@ int usb_serial_generic_register(int _debug)
USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
/* register our generic driver with ourselves */
- retval = usb_serial_register_drivers(&generic_driver, serial_drivers);
+ retval = usb_serial_register_drivers(serial_drivers, "usbserial_generic", generic_serial_ids);
#endif
return retval;
}
@@ -108,7 +88,7 @@ void usb_serial_generic_deregister(void)
{
#ifdef CONFIG_USB_SERIAL_GENERIC
/* remove our generic driver */
- usb_serial_deregister_drivers(&generic_driver, serial_drivers);
+ usb_serial_deregister_drivers(serial_drivers);
#endif
}
@@ -117,8 +97,6 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port
int result = 0;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
/* clear the throttle flags */
spin_lock_irqsave(&port->lock, flags);
port->throttled = 0;
@@ -139,12 +117,9 @@ static void generic_cleanup(struct usb_serial_port *port)
unsigned long flags;
int i;
- dbg("%s - port %d", __func__, port->number);
-
if (serial->dev) {
/* shutdown any bulk transfers that might be going on */
if (port->bulk_out_size) {
- usb_kill_urb(port->write_urb);
for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
usb_kill_urb(port->write_urbs[i]);
@@ -161,7 +136,6 @@ static void generic_cleanup(struct usb_serial_port *port)
void usb_serial_generic_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
generic_cleanup(port);
}
EXPORT_SYMBOL_GPL(usb_serial_generic_close);
@@ -249,8 +223,6 @@ int usb_serial_generic_write(struct tty_struct *tty,
{
int result;
- dbg("%s - port %d", __func__, port->number);
-
/* only do something if we have a bulk out endpoint */
if (!port->bulk_out_size)
return -ENODEV;
@@ -273,8 +245,6 @@ int usb_serial_generic_write_room(struct tty_struct *tty)
unsigned long flags;
int room;
- dbg("%s - port %d", __func__, port->number);
-
if (!port->bulk_out_size)
return 0;
@@ -282,7 +252,7 @@ int usb_serial_generic_write_room(struct tty_struct *tty)
room = kfifo_avail(&port->write_fifo);
spin_unlock_irqrestore(&port->lock, flags);
- dbg("%s - returns %d", __func__, room);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
return room;
}
@@ -292,8 +262,6 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
unsigned long flags;
int chars;
- dbg("%s - port %d", __func__, port->number);
-
if (!port->bulk_out_size)
return 0;
@@ -301,7 +269,7 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
chars = kfifo_len(&port->write_fifo) + port->tx_bytes;
spin_unlock_irqrestore(&port->lock, flags);
- dbg("%s - returns %d", __func__, chars);
+ dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
return chars;
}
@@ -313,7 +281,8 @@ static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
if (!test_and_clear_bit(index, &port->read_urbs_free))
return 0;
- dbg("%s - port %d, urb %d\n", __func__, port->number, index);
+ dev_dbg(&port->dev, "%s - port %d, urb %d\n", __func__,
+ port->number, index);
res = usb_submit_urb(port->read_urbs[index], mem_flags);
if (res) {
@@ -335,8 +304,6 @@ int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port,
int res;
int i;
- dbg("%s - port %d", __func__, port->number);
-
for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
res = usb_serial_generic_submit_read_urb(port, i, mem_flags);
if (res)
@@ -395,10 +362,12 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
}
set_bit(i, &port->read_urbs_free);
- dbg("%s - port %d, urb %d, len %d\n", __func__, port->number, i,
- urb->actual_length);
+ dev_dbg(&port->dev, "%s - port %d, urb %d, len %d\n",
+ __func__, port->number, i, urb->actual_length);
+
if (urb->status) {
- dbg("%s - non-zero urb status: %d\n", __func__, urb->status);
+ dev_dbg(&port->dev, "%s - non-zero urb status: %d\n",
+ __func__, urb->status);
return;
}
@@ -424,8 +393,6 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)
int status = urb->status;
int i;
- dbg("%s - port %d", __func__, port->number);
-
for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
if (port->write_urbs[i] == urb)
break;
@@ -436,7 +403,8 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)
spin_unlock_irqrestore(&port->lock, flags);
if (status) {
- dbg("%s - non-zero urb status: %d", __func__, status);
+ dev_dbg(&port->dev, "%s - non-zero urb status: %d\n",
+ __func__, status);
spin_lock_irqsave(&port->lock, flags);
kfifo_reset_out(&port->write_fifo);
@@ -454,8 +422,6 @@ void usb_serial_generic_throttle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
/* Set the throttle request flag. It will be picked up
* by usb_serial_generic_read_bulk_callback(). */
spin_lock_irqsave(&port->lock, flags);
@@ -469,8 +435,6 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
int was_throttled;
- dbg("%s - port %d", __func__, port->number);
-
/* Clear the throttle flags */
spin_lock_irq(&port->lock);
was_throttled = port->throttled;
@@ -525,7 +489,8 @@ void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
{
struct tty_port *port = &usb_port->port;
- dbg("%s - port %d, status %d", __func__, usb_port->number, status);
+ dev_dbg(&usb_port->dev, "%s - port %d, status %d\n", __func__,
+ usb_port->number, status);
if (status)
wake_up_interruptible(&port->open_wait);
@@ -566,8 +531,6 @@ void usb_serial_generic_disconnect(struct usb_serial *serial)
{
int i;
- dbg("%s", __func__);
-
/* stop reads and writes on all ports */
for (i = 0; i < serial->num_ports; ++i)
generic_cleanup(serial->port[i]);
@@ -576,5 +539,4 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect);
void usb_serial_generic_release(struct usb_serial *serial)
{
- dbg("%s", __func__);
}
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 2563e788c9b3..0bbaf21a9d1e 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -36,13 +36,6 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver hp49gp_driver = {
- .name = "hp4X",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver hp49gp_device = {
.driver = {
.owner = THIS_MODULE,
@@ -56,7 +49,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&hp49gp_device, NULL
};
-module_usb_serial_driver(hp49gp_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 323e87235711..e1f5ccd1e8f8 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -3181,7 +3181,7 @@ static void edge_release(struct usb_serial *serial)
kfree(edge_serial);
}
-module_usb_serial_driver(io_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index d0e7c9affb6f..350afddb55ba 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -95,13 +95,6 @@ static const struct usb_device_id id_table_combined[] = {
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver io_driver = {
- .name = "io_edgeport",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
-};
-
static struct usb_serial_driver edgeport_2port_device = {
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 40a95a7fe383..3936904c6419 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -197,14 +197,6 @@ static const struct usb_device_id id_table_combined[] = {
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver io_driver = {
- .name = "io_ti",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
-};
-
-
static unsigned char OperationalMajorVersion;
static unsigned char OperationalMinorVersion;
static unsigned short OperationalBuildNumber;
@@ -547,6 +539,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
{
int baud_rate;
struct tty_struct *tty = tty_port_tty_get(&port->port->port);
+ struct usb_serial *serial = port->port->serial;
wait_queue_t wait;
unsigned long flags;
@@ -561,7 +554,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
set_current_state(TASK_INTERRUPTIBLE);
if (kfifo_len(&port->write_fifo) == 0
|| timeout == 0 || signal_pending(current)
- || !usb_get_intfdata(port->port->serial->interface))
+ || serial->disconnected)
/* disconnect */
break;
spin_unlock_irqrestore(&port->ep_lock, flags);
@@ -578,7 +571,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
/* wait for data to drain from the device */
timeout += jiffies;
while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
- && usb_get_intfdata(port->port->serial->interface)) {
+ && !serial->disconnected) {
/* not disconnected */
if (!tx_active(port))
break;
@@ -586,7 +579,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
}
/* disconnected */
- if (!usb_get_intfdata(port->port->serial->interface))
+ if (serial->disconnected)
return;
/* wait one more character time, based on baud rate */
@@ -2003,8 +1996,8 @@ static void edge_close(struct usb_serial_port *port)
{
struct edgeport_serial *edge_serial;
struct edgeport_port *edge_port;
+ struct usb_serial *serial = port->serial;
int port_number;
- int status;
dbg("%s - port %d", __func__, port->number);
@@ -2028,12 +2021,18 @@ static void edge_close(struct usb_serial_port *port)
* send a close port command to it */
dbg("%s - send umpc_close_port", __func__);
port_number = port->number - port->serial->minor;
- status = send_cmd(port->serial->dev,
+
+ mutex_lock(&serial->disc_mutex);
+ if (!serial->disconnected) {
+ send_cmd(serial->dev,
UMPC_CLOSE_PORT,
(__u8)(UMPM_UART1_PORT + port_number),
0,
NULL,
0);
+ }
+ mutex_unlock(&serial->disc_mutex);
+
mutex_lock(&edge_serial->es_lock);
--edge_port->edge_serial->num_ports_open;
if (edge_port->edge_serial->num_ports_open <= 0) {
@@ -2783,7 +2782,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&edgeport_1port_device, &edgeport_2port_device, NULL
};
-module_usb_serial_driver(io_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 10c02b8b5664..c85a7eb87d4e 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -33,7 +33,6 @@
#define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>"
#define DRIVER_DESC "USB PocketPC PDA driver"
-static __u16 product, vendor;
static bool debug;
static int connect_retries = KP_RETRIES;
static int initial_wait;
@@ -45,8 +44,6 @@ static int ipaq_calc_num_ports(struct usb_serial *serial);
static int ipaq_startup(struct usb_serial *serial);
static struct usb_device_id ipaq_id_table [] = {
- /* The first entry is a placeholder for the insmod-specified device */
- { USB_DEVICE(0x049F, 0x0003) },
{ USB_DEVICE(0x0104, 0x00BE) }, /* Socket USB Sync */
{ USB_DEVICE(0x03F0, 0x1016) }, /* HP USB Sync */
{ USB_DEVICE(0x03F0, 0x1116) }, /* HP USB Sync 1611 */
@@ -505,13 +502,6 @@ static struct usb_device_id ipaq_id_table [] = {
MODULE_DEVICE_TABLE(usb, ipaq_id_table);
-static struct usb_driver ipaq_driver = {
- .name = "ipaq",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = ipaq_id_table,
-};
-
/* All of the device info needed for the Compaq iPAQ */
static struct usb_serial_driver ipaq_device = {
@@ -539,8 +529,6 @@ static int ipaq_open(struct tty_struct *tty,
int result = 0;
int retries = connect_retries;
- dbg("%s - port %d", __func__, port->number);
-
msleep(1000*initial_wait);
/*
@@ -577,7 +565,7 @@ static int ipaq_calc_num_ports(struct usb_serial *serial)
*/
int ipaq_num_ports = 1;
- dbg("%s - numberofendpoints: %d", __FUNCTION__,
+ dev_dbg(&serial->dev->dev, "%s - numberofendpoints: %d\n", __func__,
(int)serial->interface->cur_altsetting->desc.bNumEndpoints);
/*
@@ -596,8 +584,6 @@ static int ipaq_calc_num_ports(struct usb_serial *serial)
static int ipaq_startup(struct usb_serial *serial)
{
- dbg("%s", __func__);
-
/* Some of the devices in ipaq_id_table[] are composite, and we
* shouldn't bind to all the interfaces. This test will rule out
* some obviously invalid possibilities.
@@ -617,36 +603,14 @@ static int ipaq_startup(struct usb_serial *serial)
return -ENODEV;
}
- dbg("%s - iPAQ module configured for %d ports",
- __FUNCTION__, serial->num_ports);
+ dev_dbg(&serial->dev->dev,
+ "%s - iPAQ module configured for %d ports\n", __func__,
+ serial->num_ports);
return usb_reset_configuration(serial->dev);
}
-static int __init ipaq_init(void)
-{
- int retval;
-
- if (vendor) {
- ipaq_id_table[0].idVendor = vendor;
- ipaq_id_table[0].idProduct = product;
- }
-
- retval = usb_serial_register_drivers(&ipaq_driver, serial_drivers);
- if (retval == 0)
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return retval;
-}
-
-static void __exit ipaq_exit(void)
-{
- usb_serial_deregister_drivers(&ipaq_driver, serial_drivers);
-}
-
-
-module_init(ipaq_init);
-module_exit(ipaq_exit);
+module_usb_serial_driver(serial_drivers, ipaq_id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
@@ -655,12 +619,6 @@ MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
-module_param(vendor, ushort, 0);
-MODULE_PARM_DESC(vendor, "User specified USB idVendor");
-
-module_param(product, ushort, 0);
-MODULE_PARM_DESC(product, "User specified USB idProduct");
-
module_param(connect_retries, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(connect_retries,
"Maximum number of connect retries (one second each)");
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 76a06406e26a..5811d34b6c6b 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -132,19 +132,11 @@ enum {
#define IPW_WANTS_TO_SEND 0x30
-static const struct usb_device_id usb_ipw_ids[] = {
+static const struct usb_device_id id_table[] = {
{ USB_DEVICE(IPW_VID, IPW_PID) },
{ },
};
-
-MODULE_DEVICE_TABLE(usb, usb_ipw_ids);
-
-static struct usb_driver usb_ipw_driver = {
- .name = "ipwtty",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = usb_ipw_ids,
-};
+MODULE_DEVICE_TABLE(usb, id_table);
static bool debug;
@@ -155,8 +147,6 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
u8 *buf_flow_init;
int result;
- dbg("%s", __func__);
-
buf_flow_init = kmemdup(buf_flow_static, 16, GFP_KERNEL);
if (!buf_flow_init)
return -ENOMEM;
@@ -317,7 +307,7 @@ static struct usb_serial_driver ipw_device = {
.name = "ipw",
},
.description = "IPWireless converter",
- .id_table = usb_ipw_ids,
+ .id_table = id_table,
.num_ports = 1,
.disconnect = usb_wwan_disconnect,
.open = ipw_open,
@@ -333,7 +323,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&ipw_device, NULL
};
-module_usb_serial_driver(usb_ipw_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
/* Module information */
MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 84965cd65c76..fc09414c960f 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -77,13 +77,6 @@ static const struct usb_device_id ir_id_table[] = {
MODULE_DEVICE_TABLE(usb, ir_id_table);
-static struct usb_driver ir_driver = {
- .name = "ir-usb",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = ir_id_table,
-};
-
static struct usb_serial_driver ir_device = {
.driver = {
.owner = THIS_MODULE,
@@ -103,18 +96,21 @@ static struct usb_serial_driver * const serial_drivers[] = {
&ir_device, NULL
};
-static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc)
+static inline void irda_usb_dump_class_desc(struct usb_serial *serial,
+ struct usb_irda_cs_descriptor *desc)
{
- dbg("bLength=%x", desc->bLength);
- dbg("bDescriptorType=%x", desc->bDescriptorType);
- dbg("bcdSpecRevision=%x", __le16_to_cpu(desc->bcdSpecRevision));
- dbg("bmDataSize=%x", desc->bmDataSize);
- dbg("bmWindowSize=%x", desc->bmWindowSize);
- dbg("bmMinTurnaroundTime=%d", desc->bmMinTurnaroundTime);
- dbg("wBaudRate=%x", __le16_to_cpu(desc->wBaudRate));
- dbg("bmAdditionalBOFs=%x", desc->bmAdditionalBOFs);
- dbg("bIrdaRateSniff=%x", desc->bIrdaRateSniff);
- dbg("bMaxUnicastList=%x", desc->bMaxUnicastList);
+ struct device *dev = &serial->dev->dev;
+
+ dev_dbg(dev, "bLength=%x\n", desc->bLength);
+ dev_dbg(dev, "bDescriptorType=%x\n", desc->bDescriptorType);
+ dev_dbg(dev, "bcdSpecRevision=%x\n", __le16_to_cpu(desc->bcdSpecRevision));
+ dev_dbg(dev, "bmDataSize=%x\n", desc->bmDataSize);
+ dev_dbg(dev, "bmWindowSize=%x\n", desc->bmWindowSize);
+ dev_dbg(dev, "bmMinTurnaroundTime=%d\n", desc->bmMinTurnaroundTime);
+ dev_dbg(dev, "wBaudRate=%x\n", __le16_to_cpu(desc->wBaudRate));
+ dev_dbg(dev, "bmAdditionalBOFs=%x\n", desc->bmAdditionalBOFs);
+ dev_dbg(dev, "bIrdaRateSniff=%x\n", desc->bIrdaRateSniff);
+ dev_dbg(dev, "bMaxUnicastList=%x\n", desc->bMaxUnicastList);
}
/*------------------------------------------------------------------*/
@@ -130,8 +126,9 @@ static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc)
* Based on the same function in drivers/net/irda/irda-usb.c
*/
static struct usb_irda_cs_descriptor *
-irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
+irda_usb_find_class_desc(struct usb_serial *serial, unsigned int ifnum)
{
+ struct usb_device *dev = serial->dev;
struct usb_irda_cs_descriptor *desc;
int ret;
@@ -144,20 +141,20 @@ irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, ifnum, desc, sizeof(*desc), 1000);
- dbg("%s - ret=%d", __func__, ret);
+ dev_dbg(&serial->dev->dev, "%s - ret=%d\n", __func__, ret);
if (ret < sizeof(*desc)) {
- dbg("%s - class descriptor read %s (%d)",
- __func__,
- (ret < 0) ? "failed" : "too short",
- ret);
+ dev_dbg(&serial->dev->dev,
+ "%s - class descriptor read %s (%d)\n", __func__,
+ (ret < 0) ? "failed" : "too short", ret);
goto error;
}
if (desc->bDescriptorType != USB_DT_CS_IRDA) {
- dbg("%s - bad class descriptor type", __func__);
+ dev_dbg(&serial->dev->dev, "%s - bad class descriptor type\n",
+ __func__);
goto error;
}
- irda_usb_dump_class_desc(desc);
+ irda_usb_dump_class_desc(serial, desc);
return desc;
error:
@@ -207,14 +204,15 @@ static int ir_startup(struct usb_serial *serial)
{
struct usb_irda_cs_descriptor *irda_desc;
- irda_desc = irda_usb_find_class_desc(serial->dev, 0);
+ irda_desc = irda_usb_find_class_desc(serial, 0);
if (!irda_desc) {
dev_err(&serial->dev->dev,
"IRDA class descriptor not found, device not bound\n");
return -ENODEV;
}
- dbg("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
+ dev_dbg(&serial->dev->dev,
+ "%s - Baud rates supported:%s%s%s%s%s%s%s%s%s\n",
__func__,
(irda_desc->wBaudRate & USB_IRDA_BR_2400) ? " 2400" : "",
(irda_desc->wBaudRate & USB_IRDA_BR_9600) ? " 9600" : "",
@@ -264,8 +262,6 @@ static int ir_open(struct tty_struct *tty, struct usb_serial_port *port)
{
int i;
- dbg("%s - port %d", __func__, port->number);
-
for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET;
@@ -322,15 +318,11 @@ static void ir_process_read_urb(struct urb *urb)
static void ir_set_termios_callback(struct urb *urb)
{
- struct usb_serial_port *port = urb->context;
- int status = urb->status;
-
- dbg("%s - port %d", __func__, port->number);
-
kfree(urb->transfer_buffer);
- if (status)
- dbg("%s - non-zero urb status: %d", __func__, status);
+ if (urb->status)
+ dev_dbg(&urb->dev->dev, "%s - non-zero urb status: %d\n",
+ __func__, urb->status);
}
static void ir_set_termios(struct tty_struct *tty,
@@ -342,8 +334,6 @@ static void ir_set_termios(struct tty_struct *tty,
speed_t baud;
int ir_baud;
- dbg("%s - port %d", __func__, port->number);
-
baud = tty_get_baud_rate(tty);
/*
@@ -447,7 +437,7 @@ static int __init ir_init(void)
ir_device.bulk_out_size = buffer_size;
}
- retval = usb_serial_register_drivers(&ir_driver, serial_drivers);
+ retval = usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, ir_id_table);
if (retval == 0)
printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
DRIVER_DESC "\n");
@@ -456,7 +446,7 @@ static int __init ir_init(void)
static void __exit ir_exit(void)
{
- usb_serial_deregister_drivers(&ir_driver, serial_drivers);
+ usb_serial_deregister_drivers(serial_drivers);
}
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index f2192d527db0..22b1eb5040b7 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -51,13 +51,6 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver iuu_driver = {
- .name = "iuu_phoenix",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
/* turbo parameter */
static int boost = 100;
static int clockmode = 1;
@@ -135,8 +128,6 @@ static void iuu_release(struct usb_serial *serial)
if (!port)
return;
- dbg("%s", __func__);
-
if (priv) {
iuu_free_buf(priv);
dbg("%s - I will free all", __func__);
@@ -198,8 +189,6 @@ static void iuu_rxcmd(struct urb *urb)
int result;
int status = urb->status;
- dbg("%s - enter", __func__);
-
if (status) {
dbg("%s - status = %d", __func__, status);
/* error stop all */
@@ -221,7 +210,6 @@ static int iuu_reset(struct usb_serial_port *port, u8 wt)
struct iuu_private *priv = usb_get_serial_port_data(port);
int result;
char *buf_ptr = port->write_urb->transfer_buffer;
- dbg("%s - enter", __func__);
/* Prepare the reset sequence */
@@ -255,8 +243,6 @@ static void iuu_update_status_callback(struct urb *urb)
u8 *st;
int status = urb->status;
- dbg("%s - enter", __func__);
-
if (status) {
dbg("%s - status = %d", __func__, status);
/* error stop all */
@@ -299,8 +285,6 @@ static int iuu_status(struct usb_serial_port *port)
{
int result;
- dbg("%s - enter", __func__);
-
memset(port->write_urb->transfer_buffer, IUU_GET_STATE_REGISTER, 1);
usb_fill_bulk_urb(port->write_urb, port->serial->dev,
usb_sndbulkpipe(port->serial->dev,
@@ -318,8 +302,6 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
struct usb_serial *serial = port->serial;
int actual = 0;
- dbg("%s - enter", __func__);
-
/* send the data out the bulk port */
status =
@@ -341,10 +323,7 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
struct usb_serial *serial = port->serial;
int actual = 0;
- dbg("%s - enter", __func__);
-
/* send the data out the bulk port */
-
status =
usb_bulk_msg(serial->dev,
usb_rcvbulkpipe(serial->dev,
@@ -367,8 +346,6 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R,
if (!buf)
return -ENOMEM;
- dbg("%s - enter", __func__);
-
buf[0] = IUU_SET_LED;
buf[1] = R & 0xFF;
buf[2] = (R >> 8) & 0xFF;
@@ -460,8 +437,6 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
unsigned int P2 = 0;
int frq = (int)dwFrq;
- dbg("%s - enter", __func__);
-
if (frq == 0) {
priv->buf[Count++] = IUU_UART_WRITE_I2C;
priv->buf[Count++] = FrqGenAdr << 1;
@@ -590,8 +565,6 @@ static int iuu_uart_flush(struct usb_serial_port *port)
u8 rxcmd = IUU_UART_RX;
struct iuu_private *priv = usb_get_serial_port_data(port);
- dbg("%s - enter", __func__);
-
if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0)
return -EIO;
@@ -630,8 +603,6 @@ static void read_buf_callback(struct urb *urb)
struct tty_struct *tty;
int status = urb->status;
- dbg("%s - status = %d", __func__, status);
-
if (status) {
if (status == -EPROTO) {
/* reschedule needed */
@@ -659,7 +630,6 @@ static int iuu_bulk_write(struct usb_serial_port *port)
int i;
int buf_len;
char *buf_ptr = port->write_urb->transfer_buffer;
- dbg("%s - enter", __func__);
spin_lock_irqsave(&priv->lock, flags);
*buf_ptr++ = IUU_UART_ESC;
@@ -691,7 +661,6 @@ static int iuu_bulk_write(struct usb_serial_port *port)
static int iuu_read_buf(struct usb_serial_port *port, int len)
{
int result;
- dbg("%s - enter", __func__);
usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
@@ -713,8 +682,6 @@ static void iuu_uart_read_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
priv->poll++;
- dbg("%s - enter", __func__);
-
if (status) {
dbg("%s - status = %d", __func__, status);
/* error stop all */
@@ -771,7 +738,6 @@ static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port,
{
struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- dbg("%s - enter", __func__);
if (count > 256)
return -ENOMEM;
@@ -792,8 +758,6 @@ static void read_rxcmd_callback(struct urb *urb)
int result;
int status = urb->status;
- dbg("%s - status = %d", __func__, status);
-
if (status) {
/* error stop all */
return;
@@ -1015,8 +979,6 @@ static void iuu_close(struct usb_serial_port *port)
if (!serial)
return;
- dbg("%s - port %d", __func__, port->number);
-
iuu_uart_off(port);
if (serial->dev) {
/* free writebuf */
@@ -1031,7 +993,6 @@ static void iuu_close(struct usb_serial_port *port)
static void iuu_init_termios(struct tty_struct *tty)
{
- dbg("%s - enter", __func__);
*(tty->termios) = tty_std_termios;
tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
| TIOCM_CTS | CSTOPB | PARENB;
@@ -1188,8 +1149,6 @@ static int iuu_vcc_set(struct usb_serial_port *port, unsigned int vcc)
if (!buf)
return -ENOMEM;
- dbg("%s - enter", __func__);
-
buf[0] = IUU_SET_VCC;
buf[1] = vcc & 0xFF;
buf[2] = (vcc >> 8) & 0xFF;
@@ -1250,15 +1209,11 @@ static DEVICE_ATTR(vcc_mode, S_IRUSR | S_IWUSR, show_vcc_mode,
static int iuu_create_sysfs_attrs(struct usb_serial_port *port)
{
- dbg("%s", __func__);
-
return device_create_file(&port->dev, &dev_attr_vcc_mode);
}
static int iuu_remove_sysfs_attrs(struct usb_serial_port *port)
{
- dbg("%s", __func__);
-
device_remove_file(&port->dev, &dev_attr_vcc_mode);
return 0;
}
@@ -1294,7 +1249,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&iuu_device, NULL
};
-module_usb_serial_driver(iuu_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR("Alain Degreffe eczema@ecze.com");
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index a39ddd1b0dca..a1b99243dac9 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -130,15 +130,13 @@ struct keyspan_port_private {
#include "keyspan_usa67msg.h"
-module_usb_serial_driver(keyspan_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, keyspan_ids_combined);
static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct keyspan_port_private *p_priv;
- dbg("%s", __func__);
-
p_priv = usb_get_serial_port_data(port);
if (break_state == -1)
@@ -158,8 +156,6 @@ static void keyspan_set_termios(struct tty_struct *tty,
const struct keyspan_device_details *d_details;
unsigned int cflag;
- dbg("%s", __func__);
-
p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
cflag = tty->termios->c_cflag;
@@ -306,8 +302,6 @@ static void usa26_indat_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg("%s", __func__);
-
endpoint = usb_pipeendpoint(urb->pipe);
if (status) {
@@ -369,8 +363,6 @@ static void usa2x_outdat_callback(struct urb *urb)
static void usa26_inack_callback(struct urb *urb)
{
- dbg("%s", __func__);
-
}
static void usa26_outcont_callback(struct urb *urb)
@@ -452,7 +444,6 @@ exit: ;
static void usa26_glocont_callback(struct urb *urb)
{
- dbg("%s", __func__);
}
@@ -465,8 +456,6 @@ static void usa28_indat_callback(struct urb *urb)
struct keyspan_port_private *p_priv;
int status = urb->status;
- dbg("%s", __func__);
-
port = urb->context;
p_priv = usb_get_serial_port_data(port);
data = urb->transfer_buffer;
@@ -505,7 +494,6 @@ static void usa28_indat_callback(struct urb *urb)
static void usa28_inack_callback(struct urb *urb)
{
- dbg("%s", __func__);
}
static void usa28_outcont_callback(struct urb *urb)
@@ -585,7 +573,6 @@ exit: ;
static void usa28_glocont_callback(struct urb *urb)
{
- dbg("%s", __func__);
}
@@ -596,8 +583,6 @@ static void usa49_glocont_callback(struct urb *urb)
struct keyspan_port_private *p_priv;
int i;
- dbg("%s", __func__);
-
serial = urb->context;
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
@@ -625,8 +610,6 @@ static void usa49_instat_callback(struct urb *urb)
int old_dcd_state;
int status = urb->status;
- dbg("%s", __func__);
-
serial = urb->context;
if (status) {
@@ -679,7 +662,6 @@ exit: ;
static void usa49_inack_callback(struct urb *urb)
{
- dbg("%s", __func__);
}
static void usa49_indat_callback(struct urb *urb)
@@ -691,8 +673,6 @@ static void usa49_indat_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg("%s", __func__);
-
endpoint = usb_pipeendpoint(urb->pipe);
if (status) {
@@ -742,8 +722,6 @@ static void usa49wg_indat_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg("%s", __func__);
-
serial = urb->context;
if (status) {
@@ -806,7 +784,6 @@ static void usa49wg_indat_callback(struct urb *urb)
/* not used, usa-49 doesn't have per-port control endpoints */
static void usa49_outcont_callback(struct urb *urb)
{
- dbg("%s", __func__);
}
static void usa90_indat_callback(struct urb *urb)
@@ -819,8 +796,6 @@ static void usa90_indat_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg("%s", __func__);
-
endpoint = usb_pipeendpoint(urb->pipe);
if (status) {
@@ -957,8 +932,6 @@ static void usa67_instat_callback(struct urb *urb)
int old_dcd_state;
int status = urb->status;
- dbg("%s", __func__);
-
serial = urb->context;
if (status) {
@@ -1010,8 +983,6 @@ static void usa67_glocont_callback(struct urb *urb)
struct keyspan_port_private *p_priv;
int i;
- dbg("%s", __func__);
-
serial = urb->context;
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
@@ -1035,7 +1006,6 @@ static int keyspan_write_room(struct tty_struct *tty)
int data_len;
struct urb *this_urb;
- dbg("%s", __func__);
p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
@@ -1078,8 +1048,6 @@ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
- dbg("%s - port%d.", __func__, port->number);
-
/* Set some sane defaults */
p_priv->rts_state = 1;
p_priv->dtr_state = 1;
@@ -1165,7 +1133,6 @@ static void keyspan_close(struct usb_serial_port *port)
struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
- dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
@@ -1438,8 +1405,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
struct callbacks *cback;
int endp;
- dbg("%s", __func__);
-
s_priv = usb_get_serial_data(serial);
d_details = s_priv->device_details;
@@ -1853,8 +1818,6 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
struct urb *this_urb;
int device_port, err;
- dbg("%s", __func__);
-
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
@@ -1980,8 +1943,6 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
struct urb *this_urb;
int err, device_port;
- dbg("%s", __func__);
-
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
@@ -2168,8 +2129,6 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
int err;
u8 prescaler;
- dbg("%s", __func__);
-
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
@@ -2300,8 +2259,6 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
struct urb *this_urb;
int err, device_port;
- dbg("%s", __func__);
-
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
@@ -2442,8 +2399,6 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
struct keyspan_serial_private *s_priv;
const struct keyspan_device_details *d_details;
- dbg("%s", __func__);
-
s_priv = usb_get_serial_data(serial);
d_details = s_priv->device_details;
@@ -2477,8 +2432,6 @@ static int keyspan_startup(struct usb_serial *serial)
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
- dbg("%s", __func__);
-
for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
if (d_details->product_id ==
le16_to_cpu(serial->dev->descriptor.idProduct))
@@ -2538,8 +2491,6 @@ static void keyspan_disconnect(struct usb_serial *serial)
struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
- dbg("%s", __func__);
-
s_priv = usb_get_serial_data(serial);
/* Stop reading/writing urbs */
@@ -2579,8 +2530,6 @@ static void keyspan_release(struct usb_serial *serial)
struct usb_serial_port *port;
struct keyspan_serial_private *s_priv;
- dbg("%s", __func__);
-
s_priv = usb_get_serial_data(serial);
/* dbg("Freeing serial->private."); */
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 622853c9e384..fe1c5d91692c 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -487,13 +487,6 @@ static const struct usb_device_id keyspan_ids_combined[] = {
MODULE_DEVICE_TABLE(usb, keyspan_ids_combined);
-static struct usb_driver keyspan_driver = {
- .name = "keyspan",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = keyspan_ids_combined,
-};
-
/* usb_device_id table for the pre-firmware download keyspan devices */
static const struct usb_device_id keyspan_pre_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_pre_product_id) },
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 693bcdfcb3d5..a4ac3cfeffc4 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -86,13 +86,6 @@ static const struct usb_device_id id_table_combined[] = {
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver keyspan_pda_driver = {
- .name = "keyspan_pda",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
-};
-
static const struct usb_device_id id_table_std[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_ID) },
{ } /* Terminating entry */
@@ -131,7 +124,6 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)
struct usb_serial *serial = priv->serial;
int result;
- dbg(" request_unthrottle");
/* ask the device to tell us when the tx buffer becomes
sufficiently empty */
result = usb_control_msg(serial->dev,
@@ -226,7 +218,7 @@ static void keyspan_pda_rx_throttle(struct tty_struct *tty)
send an XOFF, although it might make sense to foist that off
upon the device too. */
struct usb_serial_port *port = tty->driver_data;
- dbg("keyspan_pda_rx_throttle port %d", port->number);
+
usb_kill_urb(port->interrupt_in_urb);
}
@@ -235,7 +227,7 @@ static void keyspan_pda_rx_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
/* just restart the receive interrupt URB */
- dbg("keyspan_pda_rx_unthrottle port %d", port->number);
+
if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL))
dbg(" usb_submit_urb(read urb) failed");
}
@@ -466,7 +458,6 @@ static int keyspan_pda_write(struct tty_struct *tty,
select() or poll() too) until we receive that unthrottle interrupt.
Block if we can't write anything at all, otherwise write as much as
we can. */
- dbg("keyspan_pda_write(%d)", count);
if (count == 0) {
dbg(" write request of 0 bytes");
return 0;
@@ -766,8 +757,6 @@ static int keyspan_pda_startup(struct usb_serial *serial)
static void keyspan_pda_release(struct usb_serial *serial)
{
- dbg("%s", __func__);
-
kfree(usb_get_serial_port_data(serial->port[0]));
}
@@ -834,7 +823,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
NULL
};
-module_usb_serial_driver(keyspan_pda_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 10f05407e535..5bed59cd5776 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -86,13 +86,6 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver kl5kusb105d_driver = {
- .name = "kl5kusb105d",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver kl5kusb105d_device = {
.driver = {
.owner = THIS_MODULE,
@@ -282,8 +275,6 @@ static void klsi_105_release(struct usb_serial *serial)
{
int i;
- dbg("%s", __func__);
-
for (i = 0; i < serial->num_ports; ++i)
kfree(usb_get_serial_port_data(serial->port[i]));
}
@@ -298,8 +289,6 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
struct klsi_105_port_settings *cfg;
unsigned long flags;
- dbg("%s port %d", __func__, port->number);
-
/* Do a defined restart:
* Set up sane default baud rate and send the 'READ_ON'
* vendor command.
@@ -376,8 +365,6 @@ static void klsi_105_close(struct usb_serial_port *port)
{
int rc;
- dbg("%s port %d", __func__, port->number);
-
mutex_lock(&port->serial->disc_mutex);
if (!port->serial->disconnected) {
/* send READ_OFF */
@@ -646,7 +633,6 @@ static int klsi_105_tiocmget(struct tty_struct *tty)
unsigned long flags;
int rc;
unsigned long line_state;
- dbg("%s - request, just guessing", __func__);
rc = klsi_105_get_line_state(port, &line_state);
if (rc < 0) {
@@ -668,8 +654,6 @@ static int klsi_105_tiocmset(struct tty_struct *tty,
{
int retval = -EINVAL;
- dbg("%s", __func__);
-
/* if this ever gets implemented, it should be done something like this:
struct usb_serial *serial = port->serial;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
@@ -692,7 +676,7 @@ static int klsi_105_tiocmset(struct tty_struct *tty,
return retval;
}
-module_usb_serial_driver(kl5kusb105d_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 4a9a75eb9b95..fafeabb64c55 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -81,18 +81,8 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_KAAN_SIM_PRODUCT_ID) },
{ } /* Terminating entry */
};
-
-
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver kobil_driver = {
- .name = "kobil",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
-
static struct usb_serial_driver kobil_device = {
.driver = {
.owner = THIS_MODULE,
@@ -193,7 +183,6 @@ static int kobil_startup(struct usb_serial *serial)
static void kobil_release(struct usb_serial *serial)
{
int i;
- dbg("%s - port %d", __func__, serial->port[0]->number);
for (i = 0; i < serial->num_ports; ++i)
kfree(usb_get_serial_port_data(serial->port[i]));
@@ -217,7 +206,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
int transfer_buffer_length = 8;
int write_urb_transfer_buffer_length = 8;
- dbg("%s - port %d", __func__, port->number);
priv = usb_get_serial_port_data(port);
/* allocate memory for transfer buffer */
@@ -327,8 +315,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
static void kobil_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
-
/* FIXME: Add rts/dtr methods */
if (port->write_urb) {
usb_poison_urb(port->write_urb);
@@ -349,8 +335,6 @@ static void kobil_read_int_callback(struct urb *urb)
int status = urb->status;
/* char *dbg_data; */
- dbg("%s - port %d", __func__, port->number);
-
if (status) {
dbg("%s - port %d Read int status not zero: %d",
__func__, port->number, status);
@@ -474,7 +458,6 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
static int kobil_write_room(struct tty_struct *tty)
{
- /* dbg("%s - port %d", __func__, port->number); */
/* FIXME */
return 8;
}
@@ -683,7 +666,7 @@ static int kobil_ioctl(struct tty_struct *tty,
}
}
-module_usb_serial_driver(kobil_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 6edd26130e25..d0ec1aa52719 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -73,22 +73,14 @@ static void mct_u232_unthrottle(struct tty_struct *tty);
/*
* All of the device info needed for the MCT USB-RS232 converter.
*/
-static const struct usb_device_id id_table_combined[] = {
+static const struct usb_device_id id_table[] = {
{ USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
{ USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
{ USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
{ USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
{ } /* Terminating entry */
};
-
-MODULE_DEVICE_TABLE(usb, id_table_combined);
-
-static struct usb_driver mct_u232_driver = {
- .name = "mct_u232",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
-};
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_serial_driver mct_u232_device = {
.driver = {
@@ -96,7 +88,7 @@ static struct usb_serial_driver mct_u232_device = {
.name = "mct_u232",
},
.description = "MCT U232",
- .id_table = id_table_combined,
+ .id_table = id_table,
.num_ports = 1,
.open = mct_u232_open,
.close = mct_u232_close,
@@ -427,8 +419,6 @@ static void mct_u232_release(struct usb_serial *serial)
struct mct_u232_private *priv;
int i;
- dbg("%s", __func__);
-
for (i = 0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
priv = usb_get_serial_port_data(serial->port[i]);
@@ -446,8 +436,6 @@ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
unsigned char last_lcr;
unsigned char last_msr;
- dbg("%s port %d", __func__, port->number);
-
/* Compensate for a hardware bug: although the Sitecom U232-P25
* device reports a maximum output packet size of 32 bytes,
* it seems to be able to accept only 16 bytes (and that's what
@@ -528,8 +516,6 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
static void mct_u232_close(struct usb_serial_port *port)
{
- dbg("%s port %d", __func__, port->number);
-
if (port->serial->dev) {
/* shutdown our urbs */
usb_kill_urb(port->write_urb);
@@ -572,7 +558,6 @@ static void mct_u232_read_int_callback(struct urb *urb)
return;
}
- dbg("%s - port %d", __func__, port->number);
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, data);
@@ -733,8 +718,6 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
unsigned char lcr;
unsigned long flags;
- dbg("%sstate=%d", __func__, break_state);
-
spin_lock_irqsave(&priv->lock, flags);
lcr = priv->last_lcr;
@@ -753,8 +736,6 @@ static int mct_u232_tiocmget(struct tty_struct *tty)
unsigned int control_state;
unsigned long flags;
- dbg("%s", __func__);
-
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -771,8 +752,6 @@ static int mct_u232_tiocmset(struct tty_struct *tty,
unsigned int control_state;
unsigned long flags;
- dbg("%s", __func__);
-
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
@@ -796,8 +775,6 @@ static void mct_u232_throttle(struct tty_struct *tty)
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned int control_state;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irq(&priv->lock);
priv->rx_flags |= THROTTLED;
if (C_CRTSCTS(tty)) {
@@ -816,8 +793,6 @@ static void mct_u232_unthrottle(struct tty_struct *tty)
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned int control_state;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irq(&priv->lock);
if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
priv->rx_flags &= ~THROTTLED;
@@ -906,7 +881,7 @@ static int mct_u232_get_icount(struct tty_struct *tty,
return 0;
}
-module_usb_serial_driver(mct_u232_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c
index 08d16e8c002d..81423f7361db 100644
--- a/drivers/usb/serial/metro-usb.c
+++ b/drivers/usb/serial/metro-usb.c
@@ -17,7 +17,6 @@
#include <linux/tty_flip.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
-#include <linux/errno.h>
#include <linux/uaccess.h>
#include <linux/usb/serial.h>
@@ -56,6 +55,47 @@ MODULE_DEVICE_TABLE(usb, id_table);
/* Input parameter constants. */
static bool debug;
+/* UNI-Directional mode commands for device configure */
+#define UNI_CMD_OPEN 0x80
+#define UNI_CMD_CLOSE 0xFF
+
+inline int metrousb_is_unidirectional_mode(struct usb_serial_port *port)
+{
+ __u16 product_id = le16_to_cpu(
+ port->serial->dev->descriptor.idProduct);
+
+ return product_id == FOCUS_PRODUCT_ID_UNI;
+}
+
+static int metrousb_send_unidirectional_cmd(u8 cmd, struct usb_serial_port *port)
+{
+ int ret;
+ int actual_len;
+ u8 *buffer_cmd = NULL;
+
+ if (!metrousb_is_unidirectional_mode(port))
+ return 0;
+
+ buffer_cmd = kzalloc(sizeof(cmd), GFP_KERNEL);
+ if (!buffer_cmd)
+ return -ENOMEM;
+
+ *buffer_cmd = cmd;
+
+ ret = usb_interrupt_msg(port->serial->dev,
+ usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress),
+ buffer_cmd, sizeof(cmd),
+ &actual_len, USB_CTRL_SET_TIMEOUT);
+
+ kfree(buffer_cmd);
+
+ if (ret < 0)
+ return ret;
+ else if (actual_len != sizeof(cmd))
+ return -EIO;
+ return 0;
+}
+
static void metrousb_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
@@ -78,12 +118,12 @@ static void metrousb_read_int_callback(struct urb *urb)
/* urb has been terminated. */
dev_dbg(&port->dev,
"%s - urb shutting down, error code=%d\n",
- __func__, result);
+ __func__, urb->status);
return;
default:
dev_dbg(&port->dev,
"%s - non-zero urb received, error code=%d\n",
- __func__, result);
+ __func__, urb->status);
goto exit;
}
@@ -91,7 +131,7 @@ static void metrousb_read_int_callback(struct urb *urb)
/* Set the data read from the usb port into the serial port buffer. */
tty = tty_port_tty_get(&port->port);
if (!tty) {
- dev_dbg(&port->dev, "%s - bad tty pointer - exiting\n",
+ dev_err(&port->dev, "%s - bad tty pointer - exiting\n",
__func__);
return;
}
@@ -121,7 +161,7 @@ static void metrousb_read_int_callback(struct urb *urb)
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result)
- dev_dbg(&port->dev,
+ dev_err(&port->dev,
"%s - failed submitting interrupt in urb, error code=%d\n",
__func__, result);
}
@@ -131,11 +171,19 @@ exit:
/* Try to resubmit the urb. */
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
- dev_dbg(&port->dev,
+ dev_err(&port->dev,
"%s - failed submitting interrupt in urb, error code=%d\n",
__func__, result);
}
+static void metrousb_write_int_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+
+ dev_warn(&port->dev, "%s not implemented yet.\n",
+ __func__);
+}
+
static void metrousb_cleanup(struct usb_serial_port *port)
{
dev_dbg(&port->dev, "%s\n", __func__);
@@ -146,6 +194,9 @@ static void metrousb_cleanup(struct usb_serial_port *port)
usb_unlink_urb(port->interrupt_in_urb);
usb_kill_urb(port->interrupt_in_urb);
}
+
+ /* Send deactivate cmd to device */
+ metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
}
}
@@ -160,7 +211,7 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
/* Make sure the urb is initialized. */
if (!port->interrupt_in_urb) {
- dev_dbg(&port->dev, "%s - interrupt urb not initialized\n",
+ dev_err(&port->dev, "%s - interrupt urb not initialized\n",
__func__);
return -ENODEV;
}
@@ -191,12 +242,21 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result) {
- dev_dbg(&port->dev,
+ dev_err(&port->dev,
"%s - failed submitting interrupt in urb, error code=%d\n",
__func__, result);
goto exit;
}
+ /* Send activate cmd to device */
+ result = metrousb_send_unidirectional_cmd(UNI_CMD_OPEN, port);
+ if (result) {
+ dev_err(&port->dev,
+ "%s - failed to configure device for port number=%d, error code=%d\n",
+ __func__, port->number, result);
+ goto exit;
+ }
+
dev_dbg(&port->dev, "%s - port open\n", __func__);
exit:
return result;
@@ -221,7 +281,7 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr
METROUSB_SET_REQUEST_TYPE, METROUSB_SET_MODEM_CTRL_REQUEST,
control_state, 0, NULL, 0, WDR_TIMEOUT);
if (retval < 0)
- dev_dbg(&serial->dev->dev,
+ dev_err(&serial->dev->dev,
"%s - set modem ctrl=0x%x failed, error code=%d\n",
__func__, mcr, retval);
@@ -354,29 +414,23 @@ static void metrousb_unthrottle(struct tty_struct *tty)
port->interrupt_in_urb->dev = port->serial->dev;
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result)
- dev_dbg(tty->dev,
+ dev_err(tty->dev,
"failed submitting interrupt in urb error code=%d\n",
result);
}
-static struct usb_driver metrousb_driver = {
- .name = "metro-usb",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table
-};
-
static struct usb_serial_driver metrousb_device = {
.driver = {
.owner = THIS_MODULE,
.name = "metro-usb",
},
- .description = "Metrologic USB to serial converter.",
+ .description = "Metrologic USB to Serial",
.id_table = id_table,
.num_ports = 1,
.open = metrousb_open,
.close = metrousb_cleanup,
.read_int_callback = metrousb_read_int_callback,
+ .write_int_callback = metrousb_write_int_callback,
.attach = metrousb_startup,
.release = metrousb_shutdown,
.throttle = metrousb_throttle,
@@ -390,7 +444,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
NULL,
};
-module_usb_serial_driver(metrousb_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Philip Nicastro");
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index bdce82034122..a07dd3c8cfef 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -79,12 +79,12 @@ static struct usb_serial_driver moschip7720_2port_driver;
#define MOSCHIP_DEVICE_ID_7720 0x7720
#define MOSCHIP_DEVICE_ID_7715 0x7715
-static const struct usb_device_id moschip_port_id_table[] = {
+static const struct usb_device_id id_table[] = {
{ USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7720) },
{ USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7715) },
{ } /* terminating entry */
};
-MODULE_DEVICE_TABLE(usb, moschip_port_id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
#ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
@@ -257,7 +257,6 @@ static void destroy_mos_parport(struct kref *kref)
struct mos7715_parport *mos_parport =
container_of(kref, struct mos7715_parport, ref_count);
- dbg("%s called", __func__);
kfree(mos_parport);
}
@@ -266,7 +265,7 @@ static void destroy_urbtracker(struct kref *kref)
struct urbtracker *urbtrack =
container_of(kref, struct urbtracker, ref_count);
struct mos7715_parport *mos_parport = urbtrack->mos_parport;
- dbg("%s called", __func__);
+
usb_free_urb(urbtrack->urb);
kfree(urbtrack);
kref_put(&mos_parport->ref_count, destroy_mos_parport);
@@ -285,8 +284,6 @@ static void send_deferred_urbs(unsigned long _mos_parport)
struct urbtracker *urbtrack;
struct list_head *cursor, *next;
- dbg("%s called", __func__);
-
/* if release function ran, game over */
if (unlikely(mos_parport->serial == NULL))
return;
@@ -335,7 +332,7 @@ static void async_complete(struct urb *urb)
{
struct urbtracker *urbtrack = urb->context;
int status = urb->status;
- dbg("%s called", __func__);
+
if (unlikely(status))
dbg("%s - nonzero urb status received: %d", __func__, status);
@@ -355,7 +352,6 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
struct usb_ctrlrequest setup;
struct usb_serial *serial = mos_parport->serial;
struct usb_device *usbdev = serial->dev;
- dbg("%s called", __func__);
/* create and initialize the control urb and containing urbtracker */
urbtrack = kmalloc(sizeof(struct urbtracker), GFP_ATOMIC);
@@ -476,7 +472,7 @@ static inline void parport_epilogue(struct parport *pp)
static void parport_mos7715_write_data(struct parport *pp, unsigned char d)
{
struct mos7715_parport *mos_parport = pp->private_data;
- dbg("%s called: %2.2x", __func__, d);
+
if (parport_prologue(pp) < 0)
return;
mos7715_change_mode(mos_parport, SPP);
@@ -488,7 +484,7 @@ static unsigned char parport_mos7715_read_data(struct parport *pp)
{
struct mos7715_parport *mos_parport = pp->private_data;
unsigned char d;
- dbg("%s called", __func__);
+
if (parport_prologue(pp) < 0)
return 0;
read_mos_reg(mos_parport->serial, dummy, DPR, &d);
@@ -500,7 +496,7 @@ static void parport_mos7715_write_control(struct parport *pp, unsigned char d)
{
struct mos7715_parport *mos_parport = pp->private_data;
__u8 data;
- dbg("%s called: %2.2x", __func__, d);
+
if (parport_prologue(pp) < 0)
return;
data = ((__u8)d & 0x0f) | (mos_parport->shadowDCR & 0xf0);
@@ -513,7 +509,7 @@ static unsigned char parport_mos7715_read_control(struct parport *pp)
{
struct mos7715_parport *mos_parport = pp->private_data;
__u8 dcr;
- dbg("%s called", __func__);
+
spin_lock(&release_lock);
mos_parport = pp->private_data;
if (unlikely(mos_parport == NULL)) {
@@ -531,7 +527,7 @@ static unsigned char parport_mos7715_frob_control(struct parport *pp,
{
struct mos7715_parport *mos_parport = pp->private_data;
__u8 dcr;
- dbg("%s called", __func__);
+
mask &= 0x0f;
val &= 0x0f;
if (parport_prologue(pp) < 0)
@@ -547,7 +543,7 @@ static unsigned char parport_mos7715_read_status(struct parport *pp)
{
unsigned char status;
struct mos7715_parport *mos_parport = pp->private_data;
- dbg("%s called", __func__);
+
spin_lock(&release_lock);
mos_parport = pp->private_data;
if (unlikely(mos_parport == NULL)) { /* release called */
@@ -561,17 +557,16 @@ static unsigned char parport_mos7715_read_status(struct parport *pp)
static void parport_mos7715_enable_irq(struct parport *pp)
{
- dbg("%s called", __func__);
}
+
static void parport_mos7715_disable_irq(struct parport *pp)
{
- dbg("%s called", __func__);
}
static void parport_mos7715_data_forward(struct parport *pp)
{
struct mos7715_parport *mos_parport = pp->private_data;
- dbg("%s called", __func__);
+
if (parport_prologue(pp) < 0)
return;
mos7715_change_mode(mos_parport, PS2);
@@ -583,7 +578,7 @@ static void parport_mos7715_data_forward(struct parport *pp)
static void parport_mos7715_data_reverse(struct parport *pp)
{
struct mos7715_parport *mos_parport = pp->private_data;
- dbg("%s called", __func__);
+
if (parport_prologue(pp) < 0)
return;
mos7715_change_mode(mos_parport, PS2);
@@ -595,7 +590,6 @@ static void parport_mos7715_data_reverse(struct parport *pp)
static void parport_mos7715_init_state(struct pardevice *dev,
struct parport_state *s)
{
- dbg("%s called", __func__);
s->u.pc.ctr = DCR_INIT_VAL;
s->u.pc.ecr = ECR_INIT_VAL;
}
@@ -605,7 +599,7 @@ static void parport_mos7715_save_state(struct parport *pp,
struct parport_state *s)
{
struct mos7715_parport *mos_parport;
- dbg("%s called", __func__);
+
spin_lock(&release_lock);
mos_parport = pp->private_data;
if (unlikely(mos_parport == NULL)) { /* release called */
@@ -622,7 +616,7 @@ static void parport_mos7715_restore_state(struct parport *pp,
struct parport_state *s)
{
struct mos7715_parport *mos_parport;
- dbg("%s called", __func__);
+
spin_lock(&release_lock);
mos_parport = pp->private_data;
if (unlikely(mos_parport == NULL)) { /* release called */
@@ -641,7 +635,7 @@ static size_t parport_mos7715_write_compat(struct parport *pp,
int retval;
struct mos7715_parport *mos_parport = pp->private_data;
int actual_len;
- dbg("%s called: %u chars", __func__, (unsigned int)len);
+
if (parport_prologue(pp) < 0)
return 0;
mos7715_change_mode(mos_parport, PPF);
@@ -2164,20 +2158,13 @@ static void mos7720_release(struct usb_serial *serial)
kfree(usb_get_serial_port_data(serial->port[i]));
}
-static struct usb_driver usb_driver = {
- .name = "moschip7720",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = moschip_port_id_table,
-};
-
static struct usb_serial_driver moschip7720_2port_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "moschip7720",
},
.description = "Moschip 2 port adapter",
- .id_table = moschip_port_id_table,
+ .id_table = id_table,
.calc_num_ports = mos77xx_calc_num_ports,
.open = mos7720_open,
.close = mos7720_close,
@@ -2203,7 +2190,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&moschip7720_2port_driver, NULL
};
-module_usb_serial_driver(usb_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index c526550694a0..29160f8b5101 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -114,10 +114,10 @@
#define USB_VENDOR_ID_MOSCHIP 0x9710
#define MOSCHIP_DEVICE_ID_7840 0x7840
#define MOSCHIP_DEVICE_ID_7820 0x7820
+#define MOSCHIP_DEVICE_ID_7810 0x7810
/* The native component can have its vendor/device id's overridden
* in vendor-specific implementations. Such devices can be handled
- * by making a change here, in moschip_port_id_table, and in
- * moschip_id_table_combined
+ * by making a change here, in id_table.
*/
#define USB_VENDOR_ID_BANDB 0x0856
#define BANDB_DEVICE_ID_USO9ML2_2 0xAC22
@@ -184,31 +184,16 @@
#define NUM_URBS 16 /* URB Count */
#define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */
+/* LED on/off milliseconds*/
+#define LED_ON_MS 500
+#define LED_OFF_MS 500
-static const struct usb_device_id moschip_port_id_table[] = {
- {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
- {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)},
- {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
- {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
- {} /* terminating entry */
-};
+static int device_type;
-static const struct usb_device_id moschip_id_table_combined[] __devinitconst = {
+static const struct usb_device_id id_table[] __devinitconst = {
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
+ {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7810)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)},
@@ -226,8 +211,7 @@ static const struct usb_device_id moschip_id_table_combined[] __devinitconst = {
{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
{} /* terminating entry */
};
-
-MODULE_DEVICE_TABLE(usb, moschip_id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table);
/* This structure holds all of the local port information */
@@ -261,8 +245,13 @@ struct moschip_port {
struct urb *write_urb_pool[NUM_URBS];
char busy[NUM_URBS];
bool read_urb_busy;
-};
+ /* For device(s) with LED indicator */
+ bool has_led;
+ bool led_flag;
+ struct timer_list led_timer1; /* Timer for LED on */
+ struct timer_list led_timer2; /* Timer for LED off */
+};
static bool debug;
@@ -572,6 +561,69 @@ static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
return ret;
}
+static void mos7840_set_led_callback(struct urb *urb)
+{
+ switch (urb->status) {
+ case 0:
+ /* Success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* This urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __func__,
+ urb->status);
+ break;
+ default:
+ dbg("%s - nonzero urb status received: %d", __func__,
+ urb->status);
+ }
+}
+
+static void mos7840_set_led_async(struct moschip_port *mcs, __u16 wval,
+ __u16 reg)
+{
+ struct usb_device *dev = mcs->port->serial->dev;
+ struct usb_ctrlrequest *dr = mcs->dr;
+
+ dr->bRequestType = MCS_WR_RTYPE;
+ dr->bRequest = MCS_WRREQ;
+ dr->wValue = cpu_to_le16(wval);
+ dr->wIndex = cpu_to_le16(reg);
+ dr->wLength = cpu_to_le16(0);
+
+ usb_fill_control_urb(mcs->control_urb, dev, usb_sndctrlpipe(dev, 0),
+ (unsigned char *)dr, NULL, 0, mos7840_set_led_callback, NULL);
+
+ usb_submit_urb(mcs->control_urb, GFP_ATOMIC);
+}
+
+static void mos7840_set_led_sync(struct usb_serial_port *port, __u16 reg,
+ __u16 val)
+{
+ struct usb_device *dev = port->serial->dev;
+
+ usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, MCS_WR_RTYPE,
+ val, reg, NULL, 0, MOS_WDR_TIMEOUT);
+}
+
+static void mos7840_led_off(unsigned long arg)
+{
+ struct moschip_port *mcs = (struct moschip_port *) arg;
+
+ /* Turn off LED */
+ mos7840_set_led_async(mcs, 0x0300, MODEM_CONTROL_REGISTER);
+ mod_timer(&mcs->led_timer2,
+ jiffies + msecs_to_jiffies(LED_OFF_MS));
+}
+
+static void mos7840_led_flag_off(unsigned long arg)
+{
+ struct moschip_port *mcs = (struct moschip_port *) arg;
+
+ mcs->led_flag = false;
+}
+
/*****************************************************************************
* mos7840_interrupt_callback
* this is the callback function for when we have received data on the
@@ -591,8 +643,6 @@ static void mos7840_interrupt_callback(struct urb *urb)
__u16 wval, wreg = 0;
int status = urb->status;
- dbg("%s", " : Entering");
-
switch (status) {
case 0:
/* success */
@@ -766,12 +816,8 @@ static void mos7840_bulk_in_callback(struct urb *urb)
return;
}
- dbg("%s", "Entering... ");
-
data = urb->transfer_buffer;
- dbg("%s", "Entering ...........");
-
if (urb->actual_length) {
tty = tty_port_tty_get(&mos7840_port->port->port);
if (tty) {
@@ -792,6 +838,14 @@ static void mos7840_bulk_in_callback(struct urb *urb)
return;
}
+ /* Turn on LED */
+ if (mos7840_port->has_led && !mos7840_port->led_flag) {
+ mos7840_port->led_flag = true;
+ mos7840_set_led_async(mos7840_port, 0x0301,
+ MODEM_CONTROL_REGISTER);
+ mod_timer(&mos7840_port->led_timer1,
+ jiffies + msecs_to_jiffies(LED_ON_MS));
+ }
mos7840_port->read_urb_busy = true;
retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
@@ -835,8 +889,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
return;
}
- dbg("%s", "Entering .........");
-
tty = tty_port_tty_get(&mos7840_port->port->port);
if (tty && mos7840_port->open)
tty_wakeup(tty);
@@ -878,8 +930,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
struct moschip_port *mos7840_port;
struct moschip_port *port0;
- dbg ("%s enter", __func__);
-
if (mos7840_port_paranoia_check(port, __func__)) {
dbg("%s", "Port Paranoia failed");
return -ENODEV;
@@ -1151,10 +1201,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
dbg("usb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p",
serial, mos7840_port, port);
- dbg ("%s leave", __func__);
-
return 0;
-
}
/*****************************************************************************
@@ -1175,18 +1222,14 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty)
unsigned long flags;
struct moschip_port *mos7840_port;
- dbg("%s", " mos7840_chars_in_buffer:entering ...........");
-
if (mos7840_port_paranoia_check(port, __func__)) {
dbg("%s", "Invalid port");
return 0;
}
mos7840_port = mos7840_get_port_private(port);
- if (mos7840_port == NULL) {
- dbg("%s", "mos7840_break:leaving ...........");
+ if (mos7840_port == NULL)
return 0;
- }
spin_lock_irqsave(&mos7840_port->pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i)
@@ -1211,8 +1254,6 @@ static void mos7840_close(struct usb_serial_port *port)
int j;
__u16 Data;
- dbg("%s", "mos7840_close:entering...");
-
if (mos7840_port_paranoia_check(port, __func__)) {
dbg("%s", "Port Paranoia failed");
return;
@@ -1287,8 +1328,6 @@ static void mos7840_close(struct usb_serial_port *port)
mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
mos7840_port->open = 0;
-
- dbg("%s", "Leaving ............");
}
/************************************************************************
@@ -1343,9 +1382,6 @@ static void mos7840_break(struct tty_struct *tty, int break_state)
struct usb_serial *serial;
struct moschip_port *mos7840_port;
- dbg("%s", "Entering ...........");
- dbg("mos7840_break: Start");
-
if (mos7840_port_paranoia_check(port, __func__)) {
dbg("%s", "Port Paranoia failed");
return;
@@ -1395,8 +1431,6 @@ static int mos7840_write_room(struct tty_struct *tty)
unsigned long flags;
struct moschip_port *mos7840_port;
- dbg("%s", " mos7840_write_room:entering ...........");
-
if (mos7840_port_paranoia_check(port, __func__)) {
dbg("%s", "Invalid port");
dbg("%s", " mos7840_write_room:leaving ...........");
@@ -1445,9 +1479,6 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
/* __u16 Data; */
const unsigned char *current_position = data;
unsigned char *data1;
- dbg("%s", "entering ...........");
- /* dbg("mos7840_write: mos7840_port->shadowLCR is %x",
- mos7840_port->shadowLCR); */
#ifdef NOTMOS7840
Data = 0x00;
@@ -1554,6 +1585,14 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
data1 = urb->transfer_buffer;
dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress);
+ /* Turn on LED */
+ if (mos7840_port->has_led && !mos7840_port->led_flag) {
+ mos7840_port->led_flag = true;
+ mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0301);
+ mod_timer(&mos7840_port->led_timer1,
+ jiffies + msecs_to_jiffies(LED_ON_MS));
+ }
+
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
@@ -1602,8 +1641,6 @@ static void mos7840_throttle(struct tty_struct *tty)
return;
}
- dbg("%s", "Entering ..........");
-
/* if we are implementing XON/XOFF, send the stop character */
if (I_IXOFF(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
@@ -1646,8 +1683,6 @@ static void mos7840_unthrottle(struct tty_struct *tty)
return;
}
- dbg("%s", "Entering ..........");
-
/* if we are implementing XON/XOFF, send the start character */
if (I_IXOFF(tty)) {
unsigned char start_char = START_CHAR(tty);
@@ -1676,8 +1711,6 @@ static int mos7840_tiocmget(struct tty_struct *tty)
int status;
mos7840_port = mos7840_get_port_private(port);
- dbg("%s - port %d", __func__, port->number);
-
if (mos7840_port == NULL)
return -ENODEV;
@@ -1704,8 +1737,6 @@ static int mos7840_tiocmset(struct tty_struct *tty,
unsigned int mcr;
int status;
- dbg("%s - port %d", __func__, port->number);
-
mos7840_port = mos7840_get_port_private(port);
if (mos7840_port == NULL)
@@ -1746,7 +1777,6 @@ static int mos7840_tiocmset(struct tty_struct *tty,
static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
__u16 *clk_sel_val)
{
-
dbg("%s - %d", __func__, baudRate);
if (baudRate <= 115200) {
@@ -1839,8 +1869,6 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
return -1;
}
- dbg("%s", "Entering ..........");
-
number = mos7840_port->port->number - mos7840_port->port->serial->minor;
dbg("%s - port = %d, baud = %d", __func__,
@@ -1966,8 +1994,6 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
return;
}
- dbg("%s", "Entering ..........");
-
lData = LCR_BITS_8;
lStop = LCR_STOP_1;
lParity = LCR_PAR_NONE;
@@ -2108,7 +2134,7 @@ static void mos7840_set_termios(struct tty_struct *tty,
unsigned int cflag;
struct usb_serial *serial;
struct moschip_port *mos7840_port;
- dbg("mos7840_set_termios: START");
+
if (mos7840_port_paranoia_check(port, __func__)) {
dbg("%s", "Invalid port");
return;
@@ -2327,28 +2353,74 @@ static int mos7840_ioctl(struct tty_struct *tty,
return -ENOIOCTLCMD;
}
+static int mos7810_check(struct usb_serial *serial)
+{
+ int i, pass_count = 0;
+ __u16 data = 0, mcr_data = 0;
+ __u16 test_pattern = 0x55AA;
+
+ /* Store MCR setting */
+ usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ MCS_RDREQ, MCS_RD_RTYPE, 0x0300, MODEM_CONTROL_REGISTER,
+ &mcr_data, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+
+ for (i = 0; i < 16; i++) {
+ /* Send the 1-bit test pattern out to MCS7810 test pin */
+ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ MCS_WRREQ, MCS_WR_RTYPE,
+ (0x0300 | (((test_pattern >> i) & 0x0001) << 1)),
+ MODEM_CONTROL_REGISTER, NULL, 0, MOS_WDR_TIMEOUT);
+
+ /* Read the test pattern back */
+ usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &data,
+ VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+
+ /* If this is a MCS7810 device, both test patterns must match */
+ if (((test_pattern >> i) ^ (~data >> 1)) & 0x0001)
+ break;
+
+ pass_count++;
+ }
+
+ /* Restore MCR setting */
+ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCS_WRREQ,
+ MCS_WR_RTYPE, 0x0300 | mcr_data, MODEM_CONTROL_REGISTER, NULL,
+ 0, MOS_WDR_TIMEOUT);
+
+ if (pass_count == 16)
+ return 1;
+
+ return 0;
+}
+
static int mos7840_calc_num_ports(struct usb_serial *serial)
{
- __u16 Data = 0x00;
- int ret = 0;
+ __u16 data = 0x00;
int mos7840_num_ports;
- ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &Data,
+ usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &data,
VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
- if ((Data & 0x01) == 0) {
- mos7840_num_ports = 2;
- serial->num_bulk_in = 2;
- serial->num_bulk_out = 2;
- serial->num_ports = 2;
+ if (serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7810 ||
+ serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7820) {
+ device_type = serial->dev->descriptor.idProduct;
} else {
- mos7840_num_ports = 4;
- serial->num_bulk_in = 4;
- serial->num_bulk_out = 4;
- serial->num_ports = 4;
+ /* For a MCS7840 device GPIO0 must be set to 1 */
+ if ((data & 0x01) == 1)
+ device_type = MOSCHIP_DEVICE_ID_7840;
+ else if (mos7810_check(serial))
+ device_type = MOSCHIP_DEVICE_ID_7810;
+ else
+ device_type = MOSCHIP_DEVICE_ID_7820;
}
+ mos7840_num_ports = (device_type >> 4) & 0x000F;
+ serial->num_bulk_in = mos7840_num_ports;
+ serial->num_bulk_out = mos7840_num_ports;
+ serial->num_ports = mos7840_num_ports;
+
return mos7840_num_ports;
}
@@ -2361,9 +2433,7 @@ static int mos7840_startup(struct usb_serial *serial)
struct moschip_port *mos7840_port;
struct usb_device *dev;
int i, status;
-
__u16 Data;
- dbg("%s", "mos7840_startup :Entering..........");
if (!serial) {
dbg("%s", "Invalid Handler");
@@ -2372,9 +2442,6 @@ static int mos7840_startup(struct usb_serial *serial)
dev = serial->dev;
- dbg("%s", "Entering...");
- dbg ("mos7840_startup: serial = %p", serial);
-
/* we set up the pointers to the endpoints in the mos7840_open *
* function, as the structures aren't created yet. */
@@ -2563,6 +2630,34 @@ static int mos7840_startup(struct usb_serial *serial)
status = -ENOMEM;
goto error;
}
+
+ mos7840_port->has_led = false;
+
+ /* Initialize LED timers */
+ if (device_type == MOSCHIP_DEVICE_ID_7810) {
+ mos7840_port->has_led = true;
+
+ init_timer(&mos7840_port->led_timer1);
+ mos7840_port->led_timer1.function = mos7840_led_off;
+ mos7840_port->led_timer1.expires =
+ jiffies + msecs_to_jiffies(LED_ON_MS);
+ mos7840_port->led_timer1.data =
+ (unsigned long)mos7840_port;
+
+ init_timer(&mos7840_port->led_timer2);
+ mos7840_port->led_timer2.function =
+ mos7840_led_flag_off;
+ mos7840_port->led_timer2.expires =
+ jiffies + msecs_to_jiffies(LED_OFF_MS);
+ mos7840_port->led_timer2.data =
+ (unsigned long)mos7840_port;
+
+ mos7840_port->led_flag = false;
+
+ /* Turn off LED */
+ mos7840_set_led_sync(serial->port[i],
+ MODEM_CONTROL_REGISTER, 0x0300);
+ }
}
dbg ("mos7840_startup: all ports configured...........");
@@ -2602,7 +2697,6 @@ static void mos7840_disconnect(struct usb_serial *serial)
int i;
unsigned long flags;
struct moschip_port *mos7840_port;
- dbg("%s", " disconnect :entering..........");
if (!serial) {
dbg("%s", "Invalid Handler");
@@ -2624,9 +2718,6 @@ static void mos7840_disconnect(struct usb_serial *serial)
usb_kill_urb(mos7840_port->control_urb);
}
}
-
- dbg("%s", "Thank u :: ");
-
}
/****************************************************************************
@@ -2638,7 +2729,6 @@ static void mos7840_release(struct usb_serial *serial)
{
int i;
struct moschip_port *mos7840_port;
- dbg("%s", " release :entering..........");
if (!serial) {
dbg("%s", "Invalid Handler");
@@ -2654,30 +2744,28 @@ static void mos7840_release(struct usb_serial *serial)
mos7840_port = mos7840_get_port_private(serial->port[i]);
dbg("mos7840_port %d = %p", i, mos7840_port);
if (mos7840_port) {
+ if (mos7840_port->has_led) {
+ /* Turn off LED */
+ mos7840_set_led_sync(mos7840_port->port,
+ MODEM_CONTROL_REGISTER, 0x0300);
+
+ del_timer_sync(&mos7840_port->led_timer1);
+ del_timer_sync(&mos7840_port->led_timer2);
+ }
kfree(mos7840_port->ctrl_buf);
kfree(mos7840_port->dr);
kfree(mos7840_port);
}
}
-
- dbg("%s", "Thank u :: ");
-
}
-static struct usb_driver io_driver = {
- .name = "mos7840",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = moschip_id_table_combined,
-};
-
static struct usb_serial_driver moschip7840_4port_device = {
.driver = {
.owner = THIS_MODULE,
.name = "mos7840",
},
.description = DRIVER_DESC,
- .id_table = moschip_port_id_table,
+ .id_table = id_table,
.num_ports = 4,
.open = mos7840_open,
.close = mos7840_close,
@@ -2707,7 +2795,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&moschip7840_4port_device, NULL
};
-module_usb_serial_driver(io_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c
index 3ab6214b4bbf..c5ff6c7795a6 100644
--- a/drivers/usb/serial/moto_modem.c
+++ b/drivers/usb/serial/moto_modem.c
@@ -31,13 +31,6 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver moto_driver = {
- .name = "moto-modem",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver moto_device = {
.driver = {
.owner = THIS_MODULE,
@@ -51,5 +44,5 @@ static struct usb_serial_driver * const serial_drivers[] = {
&moto_device, NULL
};
-module_usb_serial_driver(moto_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 29ab6eb5b536..d95452cc076d 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -30,13 +30,6 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver navman_driver = {
- .name = "navman",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static void navman_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
@@ -53,12 +46,12 @@ static void navman_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
@@ -84,10 +77,9 @@ static int navman_open(struct tty_struct *tty, struct usb_serial_port *port)
{
int result = 0;
- dbg("%s - port %d", __func__, port->number);
-
if (port->interrupt_in_urb) {
- dbg("%s - adding interrupt input for treo", __func__);
+ dev_dbg(&port->dev, "%s - adding interrupt input for treo\n",
+ __func__);
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result)
dev_err(&port->dev,
@@ -99,16 +91,12 @@ static int navman_open(struct tty_struct *tty, struct usb_serial_port *port)
static void navman_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
-
usb_kill_urb(port->interrupt_in_urb);
}
static int navman_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
- dbg("%s - port %d", __func__, port->number);
-
/*
* This device can't write any data, only read from the device
*/
@@ -132,7 +120,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&navman_device, NULL
};
-module_usb_serial_driver(navman_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 88dc785bb298..6f3d7051c7f4 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -54,17 +54,8 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(ZYXEL_VENDOR_ID, BT_IGNITIONPRO_ID) },
{ } /* Terminating entry */
};
-
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver omninet_driver = {
- .name = "omninet",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
-
static struct usb_serial_driver zyxel_omninet_device = {
.driver = {
.owner = THIS_MODULE,
@@ -144,8 +135,6 @@ static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port)
struct usb_serial_port *wport;
int result = 0;
- dbg("%s - port %d", __func__, port->number);
-
wport = serial->port[1];
tty_port_tty_set(&wport->port, tty);
@@ -160,7 +149,6 @@ static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port)
static void omninet_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
usb_kill_urb(port->read_urb);
}
@@ -178,8 +166,6 @@ static void omninet_read_bulk_callback(struct urb *urb)
int result;
int i;
- dbg("%s - port %d", __func__, port->number);
-
if (status) {
dbg("%s - nonzero read bulk status received: %d",
__func__, status);
@@ -225,8 +211,6 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
int result;
- dbg("%s - port %d", __func__, port->number);
-
if (count == 0) {
dbg("%s - write request of 0 bytes", __func__);
return 0;
@@ -289,8 +273,6 @@ static void omninet_write_bulk_callback(struct urb *urb)
struct usb_serial_port *port = urb->context;
int status = urb->status;
- dbg("%s - port %0x", __func__, port->number);
-
set_bit(0, &port->write_urbs_free);
if (status) {
dbg("%s - nonzero write bulk status received: %d",
@@ -306,8 +288,6 @@ static void omninet_disconnect(struct usb_serial *serial)
{
struct usb_serial_port *wport = serial->port[1];
- dbg("%s", __func__);
-
usb_kill_urb(wport->write_urb);
}
@@ -316,12 +296,10 @@ static void omninet_release(struct usb_serial *serial)
{
struct usb_serial_port *port = serial->port[0];
- dbg("%s", __func__);
-
kfree(usb_get_serial_port_data(port));
}
-module_usb_serial_driver(omninet_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 82cc9d202b83..02cb1b7f6559 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -70,8 +70,6 @@ static void opticon_read_bulk_callback(struct urb *urb)
int data_length;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
switch (status) {
case 0:
/* success */
@@ -179,8 +177,6 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port)
unsigned long flags;
int result = 0;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
priv->throttled = false;
priv->actually_throttled = false;
@@ -216,8 +212,6 @@ static void opticon_close(struct usb_serial_port *port)
{
struct opticon_private *priv = usb_get_serial_data(port->serial);
- dbg("%s - port %d", __func__, port->number);
-
/* shutdown our urbs */
usb_kill_urb(priv->bulk_read_urb);
}
@@ -256,8 +250,6 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
int status;
struct usb_ctrlrequest *dr;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
if (priv->outstanding_urbs > URB_UPPER_LIMIT) {
spin_unlock_irqrestore(&priv->lock, flags);
@@ -338,8 +330,6 @@ static int opticon_write_room(struct tty_struct *tty)
struct opticon_private *priv = usb_get_serial_data(port->serial);
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
/*
* We really can take almost anything the user throws at us
* but let's pick a nice big number to tell the tty
@@ -362,7 +352,6 @@ static void opticon_throttle(struct tty_struct *tty)
struct opticon_private *priv = usb_get_serial_data(port->serial);
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags);
priv->throttled = true;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -376,8 +365,6 @@ static void opticon_unthrottle(struct tty_struct *tty)
unsigned long flags;
int result, was_throttled;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
priv->throttled = false;
was_throttled = priv->actually_throttled;
@@ -400,10 +387,6 @@ static int opticon_tiocmget(struct tty_struct *tty)
unsigned long flags;
int result = 0;
- dbg("%s - port %d", __func__, port->number);
- if (!usb_get_intfdata(port->serial->interface))
- return -ENODEV;
-
spin_lock_irqsave(&priv->lock, flags);
if (priv->rts)
result |= TIOCM_RTS;
@@ -419,13 +402,13 @@ static int opticon_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
+ struct usb_serial *serial = port->serial;
struct opticon_private *priv = usb_get_serial_data(port->serial);
unsigned long flags;
bool rts;
bool changed = false;
+ int ret;
- if (!usb_get_intfdata(port->serial->interface))
- return -ENODEV;
/* We only support RTS so we only handle that */
spin_lock_irqsave(&priv->lock, flags);
@@ -441,7 +424,14 @@ static int opticon_tiocmset(struct tty_struct *tty,
return 0;
/* Send the new RTS state to the connected device */
- return send_control_msg(port, CONTROL_RTS, !rts);
+ mutex_lock(&serial->disc_mutex);
+ if (!serial->disconnected)
+ ret = send_control_msg(port, CONTROL_RTS, !rts);
+ else
+ ret = -ENODEV;
+ mutex_unlock(&serial->disc_mutex);
+
+ return ret;
}
static int get_serial_info(struct opticon_private *priv,
@@ -555,8 +545,6 @@ static void opticon_disconnect(struct usb_serial *serial)
{
struct opticon_private *priv = usb_get_serial_data(serial);
- dbg("%s", __func__);
-
usb_kill_urb(priv->bulk_read_urb);
usb_free_urb(priv->bulk_read_urb);
}
@@ -565,24 +553,20 @@ static void opticon_release(struct usb_serial *serial)
{
struct opticon_private *priv = usb_get_serial_data(serial);
- dbg("%s", __func__);
-
kfree(priv->bulk_in_buffer);
kfree(priv);
}
-static int opticon_suspend(struct usb_interface *intf, pm_message_t message)
+static int opticon_suspend(struct usb_serial *serial, pm_message_t message)
{
- struct usb_serial *serial = usb_get_intfdata(intf);
struct opticon_private *priv = usb_get_serial_data(serial);
usb_kill_urb(priv->bulk_read_urb);
return 0;
}
-static int opticon_resume(struct usb_interface *intf)
+static int opticon_resume(struct usb_serial *serial)
{
- struct usb_serial *serial = usb_get_intfdata(intf);
struct opticon_private *priv = usb_get_serial_data(serial);
struct usb_serial_port *port = serial->port[0];
int result;
@@ -597,15 +581,6 @@ static int opticon_resume(struct usb_interface *intf)
return result;
}
-static struct usb_driver opticon_driver = {
- .name = "opticon",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .suspend = opticon_suspend,
- .resume = opticon_resume,
- .id_table = id_table,
-};
-
static struct usb_serial_driver opticon_device = {
.driver = {
.owner = THIS_MODULE,
@@ -625,13 +600,15 @@ static struct usb_serial_driver opticon_device = {
.ioctl = opticon_ioctl,
.tiocmget = opticon_tiocmget,
.tiocmset = opticon_tiocmset,
+ .suspend = opticon_suspend,
+ .resume = opticon_resume,
};
static struct usb_serial_driver * const serial_drivers[] = {
&opticon_device, NULL
};
-module_usb_serial_driver(opticon_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index f4465ccddc35..1aae9028cd0b 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1220,18 +1220,6 @@ static const struct usb_device_id option_ids[] = {
};
MODULE_DEVICE_TABLE(usb, option_ids);
-static struct usb_driver option_driver = {
- .name = "option",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
-#ifdef CONFIG_PM
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .supports_autosuspend = 1,
-#endif
- .id_table = option_ids,
-};
-
/* The card has three separate interfaces, which the serial driver
* recognizes separately, thus num_port=1.
*/
@@ -1300,7 +1288,7 @@ struct option_port_private {
unsigned long tx_start_time[N_OUT_URB];
};
-module_usb_serial_driver(option_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, option_ids);
static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason,
const struct option_blacklist_info *blacklist)
@@ -1375,7 +1363,6 @@ static void option_instat_callback(struct urb *urb)
struct usb_serial_port *port = urb->context;
struct option_port_private *portdata = usb_get_serial_port_data(port);
- dbg("%s", __func__);
dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
if (status == 0) {
@@ -1413,7 +1400,7 @@ static void option_instat_callback(struct urb *urb)
req_pkt->bRequestType, req_pkt->bRequest);
}
} else
- err("%s: error %d", __func__, status);
+ dev_err(&port->dev, "%s: error %d\n", __func__, status);
/* Resubmit urb so we continue receiving IRQ data */
if (status != -ESHUTDOWN && status != -ENOENT) {
@@ -1437,7 +1424,6 @@ static int option_send_setup(struct usb_serial_port *port)
struct option_port_private *portdata;
int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
int val = 0;
- dbg("%s", __func__);
if (is_blacklisted(ifNum, OPTION_BLACKLIST_SENDSETUP,
(struct option_blacklist_info *) intfdata->private)) {
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index 5fdc33c6a3c0..5976b65ab6ee 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -66,13 +66,6 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver oti6858_driver = {
- .name = "oti6858",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static bool debug;
/* requests */
@@ -211,8 +204,6 @@ static void setup_line(struct work_struct *work)
unsigned long flags;
int result;
- dbg("%s(port = %d)", __func__, port->number);
-
new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL);
if (new_setup == NULL) {
dev_err(&port->dev, "%s(): out of memory!\n", __func__);
@@ -282,8 +273,6 @@ static void send_data(struct work_struct *work)
unsigned long flags;
u8 *allow;
- dbg("%s(port = %d)", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
if (priv->flags.write_urb_in_use) {
spin_unlock_irqrestore(&priv->lock, flags);
@@ -379,8 +368,6 @@ static int oti6858_startup(struct usb_serial *serial)
static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
- dbg("%s(port = %d, count = %d)", __func__, port->number, count);
-
if (!count)
return count;
@@ -395,8 +382,6 @@ static int oti6858_write_room(struct tty_struct *tty)
int room = 0;
unsigned long flags;
- dbg("%s(port = %d)", __func__, port->number);
-
spin_lock_irqsave(&port->lock, flags);
room = kfifo_avail(&port->write_fifo);
spin_unlock_irqrestore(&port->lock, flags);
@@ -410,8 +395,6 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty)
int chars = 0;
unsigned long flags;
- dbg("%s(port = %d)", __func__, port->number);
-
spin_lock_irqsave(&port->lock, flags);
chars = kfifo_len(&port->write_fifo);
spin_unlock_irqrestore(&port->lock, flags);
@@ -437,8 +420,6 @@ static void oti6858_set_termios(struct tty_struct *tty,
__le16 divisor;
int br;
- dbg("%s(port = %d)", __func__, port->number);
-
if (!tty) {
dbg("%s(): no tty structures", __func__);
return;
@@ -545,8 +526,6 @@ static int oti6858_open(struct tty_struct *tty, struct usb_serial_port *port)
unsigned long flags;
int result;
- dbg("%s(port = %d)", __func__, port->number);
-
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
@@ -602,8 +581,6 @@ static void oti6858_close(struct usb_serial_port *port)
struct oti6858_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- dbg("%s(port = %d)", __func__, port->number);
-
spin_lock_irqsave(&port->lock, flags);
/* clear out any remaining data in the buffer */
kfifo_reset_out(&port->write_fifo);
@@ -633,9 +610,6 @@ static int oti6858_tiocmset(struct tty_struct *tty,
dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)",
__func__, port->number, set, clear);
- if (!usb_get_intfdata(port->serial->interface))
- return -ENODEV;
-
/* FIXME: check if this is correct (active high/low) */
spin_lock_irqsave(&priv->lock, flags);
control = priv->pending_setup.control;
@@ -663,11 +637,6 @@ static int oti6858_tiocmget(struct tty_struct *tty)
unsigned pin_state;
unsigned result = 0;
- dbg("%s(port = %d)", __func__, port->number);
-
- if (!usb_get_intfdata(port->serial->interface))
- return -ENODEV;
-
spin_lock_irqsave(&priv->lock, flags);
pin_state = priv->status.pin_state & PIN_MASK;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -750,8 +719,6 @@ static void oti6858_release(struct usb_serial *serial)
{
int i;
- dbg("%s()", __func__);
-
for (i = 0; i < serial->num_ports; ++i)
kfree(usb_get_serial_port_data(serial->port[i]));
}
@@ -763,9 +730,6 @@ static void oti6858_read_int_callback(struct urb *urb)
int transient = 0, can_recv = 0, resubmit = 1;
int status = urb->status;
- dbg("%s(port = %d, status = %d)",
- __func__, port->number, status);
-
switch (status) {
case 0:
/* success */
@@ -882,9 +846,6 @@ static void oti6858_read_bulk_callback(struct urb *urb)
int status = urb->status;
int result;
- dbg("%s(port = %d, status = %d)",
- __func__, port->number, status);
-
spin_lock_irqsave(&priv->lock, flags);
priv->flags.read_urb_in_use = 0;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -916,9 +877,6 @@ static void oti6858_write_bulk_callback(struct urb *urb)
int status = urb->status;
int result;
- dbg("%s(port = %d, status = %d)",
- __func__, port->number, status);
-
switch (status) {
case 0:
/* success */
@@ -958,7 +916,7 @@ static void oti6858_write_bulk_callback(struct urb *urb)
}
}
-module_usb_serial_driver(oti6858_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(OTI6858_DESCRIPTION);
MODULE_AUTHOR(OTI6858_AUTHOR);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index a1a9062954c4..13b8dd6481f5 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -38,8 +38,6 @@
static bool debug;
-#define PL2303_CLOSING_WAIT (30*HZ)
-
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) },
@@ -97,16 +95,6 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver pl2303_driver = {
- .name = "pl2303",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .supports_autosuspend = 1,
-};
-
#define SET_LINE_REQUEST_TYPE 0x21
#define SET_LINE_REQUEST 0x20
@@ -161,8 +149,9 @@ static int pl2303_vendor_read(__u16 value, __u16 index,
int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE,
value, index, buf, 1, 100);
- dbg("0x%x:0x%x:0x%x:0x%x %d - %x", VENDOR_READ_REQUEST_TYPE,
- VENDOR_READ_REQUEST, value, index, res, buf[0]);
+ dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x %d - %x\n",
+ VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, value, index,
+ res, buf[0]);
return res;
}
@@ -172,8 +161,9 @@ static int pl2303_vendor_write(__u16 value, __u16 index,
int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE,
value, index, NULL, 0, 100);
- dbg("0x%x:0x%x:0x%x:0x%x %d", VENDOR_WRITE_REQUEST_TYPE,
- VENDOR_WRITE_REQUEST, value, index, res);
+ dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x %d\n",
+ VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, value, index,
+ res);
return res;
}
@@ -196,7 +186,7 @@ static int pl2303_startup(struct usb_serial *serial)
type = type_1;
else if (serial->dev->descriptor.bDeviceClass == 0xFF)
type = type_1;
- dbg("device type: %d", type);
+ dev_dbg(&serial->interface->dev, "device type: %d\n", type);
for (i = 0; i < serial->num_ports; ++i) {
priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL);
@@ -243,7 +233,8 @@ static int set_control_lines(struct usb_device *dev, u8 value)
retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
value, 0, NULL, 0, 100);
- dbg("%s - value = %d, retval = %d", __func__, value, retval);
+ dev_dbg(&dev->dev, "%s - value = %d, retval = %d\n", __func__,
+ value, retval);
return retval;
}
@@ -265,8 +256,6 @@ static void pl2303_set_termios(struct tty_struct *tty,
int baud_floor, baud_ceil;
int k;
- dbg("%s - port %d", __func__, port->number);
-
/* The PL2303 is reported to lose bytes if you change
serial settings even to the same values as before. Thus
we actually need to filter in this specific case */
@@ -287,7 +276,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
0, 0, buf, 7, 100);
- dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i,
+ dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
if (cflag & CSIZE) {
@@ -306,7 +295,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
buf[6] = 8;
break;
}
- dbg("%s - data bits = %d", __func__, buf[6]);
+ dev_dbg(&port->dev, "data bits = %d\n", buf[6]);
}
/* For reference buf[0]:buf[3] baud rate value */
@@ -315,7 +304,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
* 9600 baud (at least my PL2303X always does)
*/
baud = tty_get_baud_rate(tty);
- dbg("%s - baud requested = %d", __func__, baud);
+ dev_dbg(&port->dev, "baud requested = %d\n", baud);
if (baud) {
/* Set baudrate to nearest supported value */
for (k=0; k<ARRAY_SIZE(baud_sup); k++) {
@@ -341,7 +330,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
else if (baud > 6000000)
baud = 6000000;
}
- dbg("%s - baud set = %d", __func__, baud);
+ dev_dbg(&port->dev, "baud set = %d\n", baud);
if (baud <= 115200) {
buf[0] = baud & 0xff;
buf[1] = (baud >> 8) & 0xff;
@@ -372,14 +361,14 @@ static void pl2303_set_termios(struct tty_struct *tty,
*/
if ((cflag & CSIZE) == CS5) {
buf[4] = 1;
- dbg("%s - stop bits = 1.5", __func__);
+ dev_dbg(&port->dev, "stop bits = 1.5\n");
} else {
buf[4] = 2;
- dbg("%s - stop bits = 2", __func__);
+ dev_dbg(&port->dev, "stop bits = 2\n");
}
} else {
buf[4] = 0;
- dbg("%s - stop bits = 1", __func__);
+ dev_dbg(&port->dev, "stop bits = 1\n");
}
if (cflag & PARENB) {
@@ -391,29 +380,29 @@ static void pl2303_set_termios(struct tty_struct *tty,
if (cflag & PARODD) {
if (cflag & CMSPAR) {
buf[5] = 3;
- dbg("%s - parity = mark", __func__);
+ dev_dbg(&port->dev, "parity = mark\n");
} else {
buf[5] = 1;
- dbg("%s - parity = odd", __func__);
+ dev_dbg(&port->dev, "parity = odd\n");
}
} else {
if (cflag & CMSPAR) {
buf[5] = 4;
- dbg("%s - parity = space", __func__);
+ dev_dbg(&port->dev, "parity = space\n");
} else {
buf[5] = 2;
- dbg("%s - parity = even", __func__);
+ dev_dbg(&port->dev, "parity = even\n");
}
}
} else {
buf[5] = 0;
- dbg("%s - parity = none", __func__);
+ dev_dbg(&port->dev, "parity = none\n");
}
i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE,
0, 0, buf, 7, 100);
- dbg("0x21:0x20:0:0 %d", i);
+ dev_dbg(&port->dev, "0x21:0x20:0:0 %d\n", i);
/* change control lines if we are switching to or from B0 */
spin_lock_irqsave(&priv->lock, flags);
@@ -435,7 +424,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
0, 0, buf, 7, 100);
- dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i,
+ dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
if (cflag & CRTSCTS) {
@@ -473,8 +462,6 @@ static void pl2303_dtr_rts(struct usb_serial_port *port, int on)
static void pl2303_close(struct usb_serial_port *port)
{
- dbg("%s - port %d", __func__, port->number);
-
usb_serial_generic_close(port);
usb_kill_urb(port->interrupt_in_urb);
}
@@ -486,8 +473,6 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
struct pl2303_private *priv = usb_get_serial_port_data(port);
int result;
- dbg("%s - port %d", __func__, port->number);
-
if (priv->type != HX) {
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
@@ -501,7 +486,6 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
if (tty)
pl2303_set_termios(tty, port, &tmp_termios);
- dbg("%s - submitting interrupt urb", __func__);
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result) {
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
@@ -523,12 +507,11 @@ static int pl2303_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
+ struct usb_serial *serial = port->serial;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 control;
-
- if (!usb_get_intfdata(port->serial->interface))
- return -ENODEV;
+ int ret;
spin_lock_irqsave(&priv->lock, flags);
if (set & TIOCM_RTS)
@@ -542,7 +525,14 @@ static int pl2303_tiocmset(struct tty_struct *tty,
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
- return set_control_lines(port->serial->dev, control);
+ mutex_lock(&serial->disc_mutex);
+ if (!serial->disconnected)
+ ret = set_control_lines(serial->dev, control);
+ else
+ ret = -ENODEV;
+ mutex_unlock(&serial->disc_mutex);
+
+ return ret;
}
static int pl2303_tiocmget(struct tty_struct *tty)
@@ -554,11 +544,6 @@ static int pl2303_tiocmget(struct tty_struct *tty)
unsigned int status;
unsigned int result;
- dbg("%s (%d)", __func__, port->number);
-
- if (!usb_get_intfdata(port->serial->interface))
- return -ENODEV;
-
spin_lock_irqsave(&priv->lock, flags);
mcr = priv->line_control;
status = priv->line_status;
@@ -571,7 +556,7 @@ static int pl2303_tiocmget(struct tty_struct *tty)
| ((status & UART_RING) ? TIOCM_RI : 0)
| ((status & UART_DCD) ? TIOCM_CD : 0);
- dbg("%s - result = %x", __func__, result);
+ dev_dbg(&port->dev, "%s - result = %x\n", __func__, result);
return result;
}
@@ -625,7 +610,8 @@ static int pl2303_ioctl(struct tty_struct *tty,
{
struct serial_struct ser;
struct usb_serial_port *port = tty->driver_data;
- dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
+
+ dev_dbg(&port->dev, "%s cmd = 0x%04x\n", __func__, cmd);
switch (cmd) {
case TIOCGSERIAL:
@@ -641,10 +627,10 @@ static int pl2303_ioctl(struct tty_struct *tty,
return 0;
case TIOCMIWAIT:
- dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
+ dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__);
return wait_modem_info(port, arg);
default:
- dbg("%s not supported = 0x%04x", __func__, cmd);
+ dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd);
break;
}
return -ENOIOCTLCMD;
@@ -657,20 +643,18 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
u16 state;
int result;
- dbg("%s - port %d", __func__, port->number);
-
if (break_state == 0)
state = BREAK_OFF;
else
state = BREAK_ON;
- dbg("%s - turning break %s", __func__,
+ dev_dbg(&port->dev, "%s - turning break %s\n", __func__,
state == BREAK_OFF ? "off" : "on");
result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
0, NULL, 0, 100);
if (result)
- dbg("%s - error sending break = %d", __func__, result);
+ dev_err(&port->dev, "error sending break = %d\n", result);
}
static void pl2303_release(struct usb_serial *serial)
@@ -678,8 +662,6 @@ static void pl2303_release(struct usb_serial *serial)
int i;
struct pl2303_private *priv;
- dbg("%s", __func__);
-
for (i = 0; i < serial->num_ports; ++i) {
priv = usb_get_serial_port_data(serial->port[i]);
kfree(priv);
@@ -742,8 +724,6 @@ static void pl2303_read_int_callback(struct urb *urb)
int status = urb->status;
int retval;
- dbg("%s (%d)", __func__, port->number);
-
switch (status) {
case 0:
/* success */
@@ -752,12 +732,12 @@ static void pl2303_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__,
- status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__,
- status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
@@ -769,7 +749,7 @@ static void pl2303_read_int_callback(struct urb *urb)
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- dev_err(&urb->dev->dev,
+ dev_err(&port->dev,
"%s - usb_submit_urb failed with result %d\n",
__func__, retval);
}
@@ -807,7 +787,7 @@ static void pl2303_process_read_urb(struct urb *urb)
tty_flag = TTY_PARITY;
else if (line_status & UART_FRAME_ERROR)
tty_flag = TTY_FRAME;
- dbg("%s - tty_flag = %d", __func__, tty_flag);
+ dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__, tty_flag);
/* overrun is special, not associated with a char */
if (line_status & UART_OVERRUN_ERROR)
@@ -855,7 +835,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&pl2303_device, NULL
};
-module_usb_serial_driver(pl2303_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c
index 966245680f55..a4edc7ee9c8a 100644
--- a/drivers/usb/serial/qcaux.c
+++ b/drivers/usb/serial/qcaux.c
@@ -77,13 +77,6 @@ static struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver qcaux_driver = {
- .name = "qcaux",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver qcaux_device = {
.driver = {
.owner = THIS_MODULE,
@@ -97,5 +90,5 @@ static struct usb_serial_driver * const serial_drivers[] = {
&qcaux_device, NULL
};
-module_usb_serial_driver(qcaux_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 0206b10c9e6e..0d5fe59ebb9e 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -112,32 +112,22 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver qcdriver = {
- .name = "qcserial",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .supports_autosuspend = true,
-};
-
static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
{
struct usb_wwan_intf_private *data;
struct usb_host_interface *intf = serial->interface->cur_altsetting;
+ struct device *dev = &serial->dev->dev;
int retval = -ENODEV;
__u8 nintf;
__u8 ifnum;
bool is_gobi1k = id->driver_info ? true : false;
- dbg("%s", __func__);
- dbg("Is Gobi 1000 = %d", is_gobi1k);
+ dev_dbg(dev, "Is Gobi 1000 = %d\n", is_gobi1k);
nintf = serial->dev->actconfig->desc.bNumInterfaces;
- dbg("Num Interfaces = %d", nintf);
+ dev_dbg(dev, "Num Interfaces = %d\n", nintf);
ifnum = intf->desc.bInterfaceNumber;
- dbg("This Interface = %d", ifnum);
+ dev_dbg(dev, "This Interface = %d\n", ifnum);
data = kzalloc(sizeof(struct usb_wwan_intf_private),
GFP_KERNEL);
@@ -158,7 +148,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
if (intf->desc.bNumEndpoints == 2 &&
usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) &&
usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
- dbg("QDL port found");
+ dev_dbg(dev, "QDL port found\n");
if (serial->interface->num_altsetting == 1) {
retval = 0; /* Success */
@@ -167,7 +157,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
retval = usb_set_interface(serial->dev, ifnum, 1);
if (retval < 0) {
- dev_err(&serial->dev->dev,
+ dev_err(dev,
"Could not set interface, error %d\n",
retval);
retval = -ENODEV;
@@ -196,20 +186,20 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
*/
if (ifnum == 1 && !is_gobi1k) {
- dbg("Gobi 2K+ DM/DIAG interface found");
+ dev_dbg(dev, "Gobi 2K+ DM/DIAG interface found\n");
retval = usb_set_interface(serial->dev, ifnum, 0);
if (retval < 0) {
- dev_err(&serial->dev->dev,
+ dev_err(dev,
"Could not set interface, error %d\n",
retval);
retval = -ENODEV;
kfree(data);
}
} else if (ifnum == 2) {
- dbg("Modem port found");
+ dev_dbg(dev, "Modem port found\n");
retval = usb_set_interface(serial->dev, ifnum, 0);
if (retval < 0) {
- dev_err(&serial->dev->dev,
+ dev_err(dev,
"Could not set interface, error %d\n",
retval);
retval = -ENODEV;
@@ -221,10 +211,10 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
* # echo "\$GPS_START" > /dev/ttyUSBx
* # echo "\$GPS_STOP" > /dev/ttyUSBx
*/
- dbg("Gobi 2K+ NMEA GPS interface found");
+ dev_dbg(dev, "Gobi 2K+ NMEA GPS interface found\n");
retval = usb_set_interface(serial->dev, ifnum, 0);
if (retval < 0) {
- dev_err(&serial->dev->dev,
+ dev_err(dev,
"Could not set interface, error %d\n",
retval);
retval = -ENODEV;
@@ -234,8 +224,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
break;
default:
- dev_err(&serial->dev->dev,
- "unknown number of interfaces: %d\n", nintf);
+ dev_err(dev, "unknown number of interfaces: %d\n", nintf);
kfree(data);
retval = -ENODEV;
}
@@ -250,8 +239,6 @@ static void qc_release(struct usb_serial *serial)
{
struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);
- dbg("%s", __func__);
-
/* Call usb_wwan release & free the private data allocated in qcprobe */
usb_wwan_release(serial);
usb_set_serial_data(serial, NULL);
@@ -285,7 +272,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&qcdevice, NULL
};
-module_usb_serial_driver(qcdriver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
new file mode 100644
index 000000000000..8dd88ebe9863
--- /dev/null
+++ b/drivers/usb/serial/quatech2.c
@@ -0,0 +1,1155 @@
+/*
+ * usb-serial driver for Quatech USB 2 devices
+ *
+ * Copyright (C) 2012 Bill Pemberton (wfp5p@virginia.edu)
+ *
+ * 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.
+ *
+ *
+ * These devices all have only 1 bulk in and 1 bulk out that is shared
+ * for all serial ports.
+ *
+ */
+
+#include <asm/unaligned.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/uaccess.h>
+
+static bool debug;
+
+/* default urb timeout for usb operations */
+#define QT2_USB_TIMEOUT USB_CTRL_SET_TIMEOUT
+
+#define QT_OPEN_CLOSE_CHANNEL 0xca
+#define QT_SET_GET_DEVICE 0xc2
+#define QT_SET_GET_REGISTER 0xc0
+#define QT_GET_SET_PREBUF_TRIG_LVL 0xcc
+#define QT_SET_ATF 0xcd
+#define QT_TRANSFER_IN 0xc0
+#define QT_HW_FLOW_CONTROL_MASK 0xc5
+#define QT_SW_FLOW_CONTROL_MASK 0xc6
+#define QT2_BREAK_CONTROL 0xc8
+#define QT2_GET_SET_UART 0xc1
+#define QT2_FLUSH_DEVICE 0xc4
+#define QT2_GET_SET_QMCR 0xe1
+#define QT2_QMCR_RS232 0x40
+#define QT2_QMCR_RS422 0x10
+
+#define SERIAL_CRTSCTS ((UART_MCR_RTS << 8) | UART_MSR_CTS)
+
+#define SERIAL_EVEN_PARITY (UART_LCR_PARITY | UART_LCR_EPAR)
+
+/* status bytes for the device */
+#define QT2_CONTROL_BYTE 0x1b
+#define QT2_LINE_STATUS 0x00 /* following 1 byte is line status */
+#define QT2_MODEM_STATUS 0x01 /* following 1 byte is modem status */
+#define QT2_XMIT_HOLD 0x02 /* following 2 bytes are ?? */
+#define QT2_CHANGE_PORT 0x03 /* following 1 byte is port to change to */
+#define QT2_REC_FLUSH 0x04 /* no following info */
+#define QT2_XMIT_FLUSH 0x05 /* no following info */
+#define QT2_CONTROL_ESCAPE 0xff /* pass through previous 2 control bytes */
+
+#define MAX_BAUD_RATE 921600
+#define DEFAULT_BAUD_RATE 9600
+
+#define QT2_WRITE_BUFFER_SIZE 512 /* size of write buffer */
+#define QT2_WRITE_CONTROL_SIZE 5 /* control bytes used for a write */
+
+/* Version Information */
+#define DRIVER_VERSION "v0.1"
+#define DRIVER_DESC "Quatech 2nd gen USB to Serial Driver"
+
+#define USB_VENDOR_ID_QUATECH 0x061d
+#define QUATECH_SSU2_100 0xC120 /* RS232 single port */
+#define QUATECH_DSU2_100 0xC140 /* RS232 dual port */
+#define QUATECH_DSU2_400 0xC150 /* RS232/422/485 dual port */
+#define QUATECH_QSU2_100 0xC160 /* RS232 four port */
+#define QUATECH_QSU2_400 0xC170 /* RS232/422/485 four port */
+#define QUATECH_ESU2_100 0xC1A0 /* RS232 eight port */
+#define QUATECH_ESU2_400 0xC180 /* RS232/422/485 eight port */
+
+struct qt2_device_detail {
+ int product_id;
+ int num_ports;
+};
+
+#define QT_DETAILS(prod, ports) \
+ .product_id = (prod), \
+ .num_ports = (ports)
+
+static const struct qt2_device_detail qt2_device_details[] = {
+ {QT_DETAILS(QUATECH_SSU2_100, 1)},
+ {QT_DETAILS(QUATECH_DSU2_400, 2)},
+ {QT_DETAILS(QUATECH_DSU2_100, 2)},
+ {QT_DETAILS(QUATECH_QSU2_400, 4)},
+ {QT_DETAILS(QUATECH_QSU2_100, 4)},
+ {QT_DETAILS(QUATECH_ESU2_400, 8)},
+ {QT_DETAILS(QUATECH_ESU2_100, 8)},
+ {QT_DETAILS(0, 0)} /* Terminating entry */
+};
+
+static const struct usb_device_id id_table[] = {
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU2_100)},
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU2_100)},
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU2_400)},
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU2_100)},
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU2_400)},
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU2_100)},
+ {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU2_400)},
+ {} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+struct qt2_serial_private {
+ unsigned char current_port; /* current port for incoming data */
+
+ struct urb *read_urb; /* shared among all ports */
+ char read_buffer[512];
+};
+
+struct qt2_port_private {
+ bool is_open;
+ u8 device_port;
+
+ spinlock_t urb_lock;
+ bool urb_in_use;
+ struct urb *write_urb;
+ char write_buffer[QT2_WRITE_BUFFER_SIZE];
+
+ spinlock_t lock;
+ u8 shadowLSR;
+ u8 shadowMSR;
+
+ wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+ struct async_icount icount;
+
+ struct usb_serial_port *port;
+};
+
+static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch);
+static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch);
+static void qt2_write_bulk_callback(struct urb *urb);
+static void qt2_read_bulk_callback(struct urb *urb);
+
+static void qt2_release(struct usb_serial *serial)
+{
+ int i;
+
+ kfree(usb_get_serial_data(serial));
+
+ for (i = 0; i < serial->num_ports; i++)
+ kfree(usb_get_serial_port_data(serial->port[i]));
+}
+
+static inline int calc_baud_divisor(int baudrate)
+{
+ int divisor, rem;
+
+ divisor = MAX_BAUD_RATE / baudrate;
+ rem = MAX_BAUD_RATE % baudrate;
+ /* Round to nearest divisor */
+ if (((rem * 2) >= baudrate) && (baudrate != 110))
+ divisor++;
+
+ return divisor;
+}
+
+static inline int qt2_set_port_config(struct usb_device *dev,
+ unsigned char port_number,
+ u16 baudrate, u16 lcr)
+{
+ int divisor = calc_baud_divisor(baudrate);
+ u16 index = ((u16) (lcr << 8) | (u16) (port_number));
+
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ QT2_GET_SET_UART, 0x40,
+ divisor, index, NULL, 0, QT2_USB_TIMEOUT);
+}
+
+static inline int qt2_control_msg(struct usb_device *dev,
+ u8 request, u16 data, u16 index)
+{
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ request, 0x40, data, index,
+ NULL, 0, QT2_USB_TIMEOUT);
+}
+
+static inline int qt2_setdevice(struct usb_device *dev, u8 *data)
+{
+ u16 x = ((u16) (data[1] << 8) | (u16) (data[0]));
+
+ return qt2_control_msg(dev, QT_SET_GET_DEVICE, x, 0);
+}
+
+
+static inline int qt2_getdevice(struct usb_device *dev, u8 *data)
+{
+ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ QT_SET_GET_DEVICE, 0xc0, 0, 0,
+ data, 3, QT2_USB_TIMEOUT);
+}
+
+static inline int qt2_getregister(struct usb_device *dev,
+ u8 uart,
+ u8 reg,
+ u8 *data)
+{
+ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ QT_SET_GET_REGISTER, 0xc0, reg,
+ uart, data, sizeof(*data), QT2_USB_TIMEOUT);
+
+}
+
+static inline int qt2_setregister(struct usb_device *dev,
+ u8 uart, u8 reg, u16 data)
+{
+ u16 value = (data << 8) | reg;
+
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ QT_SET_GET_REGISTER, 0x40, value, uart,
+ NULL, 0, QT2_USB_TIMEOUT);
+}
+
+static inline int update_mctrl(struct qt2_port_private *port_priv,
+ unsigned int set, unsigned int clear)
+{
+ struct usb_serial_port *port = port_priv->port;
+ struct usb_device *dev = port->serial->dev;
+ unsigned urb_value;
+ int status;
+
+ if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
+ dev_dbg(&port->dev,
+ "update_mctrl - DTR|RTS not being set|cleared\n");
+ return 0; /* no change */
+ }
+
+ clear &= ~set; /* 'set' takes precedence over 'clear' */
+ urb_value = 0;
+ if (set & TIOCM_DTR)
+ urb_value |= UART_MCR_DTR;
+ if (set & TIOCM_RTS)
+ urb_value |= UART_MCR_RTS;
+
+ status = qt2_setregister(dev, port_priv->device_port, UART_MCR,
+ urb_value);
+ if (status < 0)
+ dev_err(&port->dev,
+ "update_mctrl - Error from MODEM_CTRL urb: %i\n",
+ status);
+ return status;
+}
+
+static int qt2_calc_num_ports(struct usb_serial *serial)
+{
+ struct qt2_device_detail d;
+ int i;
+
+ for (i = 0; d = qt2_device_details[i], d.product_id != 0; i++) {
+ if (d.product_id == le16_to_cpu(serial->dev->descriptor.idProduct))
+ return d.num_ports;
+ }
+
+ /* we didn't recognize the device */
+ dev_err(&serial->dev->dev,
+ "don't know the number of ports, assuming 1\n");
+
+ return 1;
+}
+
+static void qt2_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ struct ktermios *old_termios)
+{
+ struct usb_device *dev = port->serial->dev;
+ struct qt2_port_private *port_priv;
+ struct ktermios *termios = tty->termios;
+ u16 baud;
+ unsigned int cflag = termios->c_cflag;
+ u16 new_lcr = 0;
+ int status;
+
+ port_priv = usb_get_serial_port_data(port);
+
+ if (cflag & PARENB) {
+ if (cflag & PARODD)
+ new_lcr |= UART_LCR_PARITY;
+ else
+ new_lcr |= SERIAL_EVEN_PARITY;
+ }
+
+ switch (cflag & CSIZE) {
+ case CS5:
+ new_lcr |= UART_LCR_WLEN5;
+ break;
+ case CS6:
+ new_lcr |= UART_LCR_WLEN6;
+ break;
+ case CS7:
+ new_lcr |= UART_LCR_WLEN7;
+ break;
+ default:
+ case CS8:
+ new_lcr |= UART_LCR_WLEN8;
+ break;
+ }
+
+ baud = tty_get_baud_rate(tty);
+ if (!baud)
+ baud = 9600;
+
+ status = qt2_set_port_config(dev, port_priv->device_port, baud,
+ new_lcr);
+ if (status < 0)
+ dev_err(&port->dev, "%s - qt2_set_port_config failed: %i\n",
+ __func__, status);
+
+ if (cflag & CRTSCTS)
+ status = qt2_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
+ SERIAL_CRTSCTS,
+ port_priv->device_port);
+ else
+ status = qt2_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
+ 0, port_priv->device_port);
+ if (status < 0)
+ dev_err(&port->dev, "%s - set HW flow control failed: %i\n",
+ __func__, status);
+
+ if (I_IXOFF(tty) || I_IXON(tty)) {
+ u16 x = ((u16) (START_CHAR(tty) << 8) | (u16) (STOP_CHAR(tty)));
+
+ status = qt2_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
+ x, port_priv->device_port);
+ } else
+ status = qt2_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
+ 0, port_priv->device_port);
+
+ if (status < 0)
+ dev_err(&port->dev, "%s - set SW flow control failed: %i\n",
+ __func__, status);
+
+}
+
+static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port)
+{
+ struct usb_serial *serial;
+ struct qt2_serial_private *serial_priv;
+ struct qt2_port_private *port_priv;
+ u8 *data;
+ u16 device_port;
+ int status;
+ unsigned long flags;
+
+ device_port = (u16) (port->number - port->serial->minor);
+
+ serial = port->serial;
+
+ port_priv = usb_get_serial_port_data(port);
+ serial_priv = usb_get_serial_data(serial);
+
+ /* set the port to RS232 mode */
+ status = qt2_control_msg(serial->dev, QT2_GET_SET_QMCR,
+ QT2_QMCR_RS232, device_port);
+ if (status < 0) {
+ dev_err(&port->dev,
+ "%s failed to set RS232 mode for port %i error %i\n",
+ __func__, device_port, status);
+ return status;
+ }
+
+ data = kzalloc(2, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /* open the port */
+ status = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ QT_OPEN_CLOSE_CHANNEL,
+ 0xc0, 0,
+ device_port, data, 2, QT2_USB_TIMEOUT);
+
+ if (status < 0) {
+ dev_err(&port->dev, "%s - open port failed %i", __func__,
+ status);
+ kfree(data);
+ return status;
+ }
+
+ spin_lock_irqsave(&port_priv->lock, flags);
+ port_priv->shadowLSR = data[0];
+ port_priv->shadowMSR = data[1];
+ spin_unlock_irqrestore(&port_priv->lock, flags);
+
+ kfree(data);
+
+ /* set to default speed and 8bit word size */
+ status = qt2_set_port_config(serial->dev, device_port,
+ DEFAULT_BAUD_RATE, UART_LCR_WLEN8);
+ if (status < 0) {
+ dev_err(&port->dev,
+ "%s - initial setup failed for port %i (%i)\n",
+ __func__, port->number, device_port);
+ return status;
+ }
+
+ port_priv->is_open = true;
+ port_priv->device_port = (u8) device_port;
+
+ if (tty)
+ qt2_set_termios(tty, port, tty->termios);
+
+ return 0;
+
+}
+
+static void qt2_close(struct usb_serial_port *port)
+{
+ struct usb_serial *serial;
+ struct qt2_serial_private *serial_priv;
+ struct qt2_port_private *port_priv;
+ unsigned long flags;
+ int i;
+
+ serial = port->serial;
+ serial_priv = usb_get_serial_data(serial);
+ port_priv = usb_get_serial_port_data(port);
+
+ port_priv->is_open = false;
+
+ spin_lock_irqsave(&port_priv->urb_lock, flags);
+ if (port_priv->write_urb->status == -EINPROGRESS)
+ usb_kill_urb(port_priv->write_urb);
+ port_priv->urb_in_use = false;
+ spin_unlock_irqrestore(&port_priv->urb_lock, flags);
+
+ /* flush the port transmit buffer */
+ i = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ QT2_FLUSH_DEVICE, 0x40, 1,
+ port_priv->device_port, NULL, 0, QT2_USB_TIMEOUT);
+
+ if (i < 0)
+ dev_err(&port->dev, "%s - transmit buffer flush failed: %i\n",
+ __func__, i);
+
+ /* flush the port receive buffer */
+ i = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ QT2_FLUSH_DEVICE, 0x40, 0,
+ port_priv->device_port, NULL, 0, QT2_USB_TIMEOUT);
+
+ if (i < 0)
+ dev_err(&port->dev, "%s - receive buffer flush failed: %i\n",
+ __func__, i);
+
+ /* close the port */
+ i = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ QT_OPEN_CLOSE_CHANNEL,
+ 0x40, 0,
+ port_priv->device_port, NULL, 0, QT2_USB_TIMEOUT);
+
+ if (i < 0)
+ dev_err(&port->dev, "%s - close port failed %i\n",
+ __func__, i);
+
+}
+
+static void qt2_disconnect(struct usb_serial *serial)
+{
+ struct qt2_serial_private *serial_priv = usb_get_serial_data(serial);
+ struct qt2_port_private *port_priv;
+ int i;
+
+ if (serial_priv->read_urb->status == -EINPROGRESS)
+ usb_kill_urb(serial_priv->read_urb);
+
+ usb_free_urb(serial_priv->read_urb);
+
+ for (i = 0; i < serial->num_ports; i++) {
+ port_priv = usb_get_serial_port_data(serial->port[i]);
+
+ if (port_priv->write_urb->status == -EINPROGRESS)
+ usb_kill_urb(port_priv->write_urb);
+ usb_free_urb(port_priv->write_urb);
+ }
+}
+
+static int get_serial_info(struct usb_serial_port *port,
+ struct serial_struct __user *retinfo)
+{
+ struct serial_struct tmp;
+
+ if (!retinfo)
+ return -EFAULT;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.line = port->serial->minor;
+ tmp.port = 0;
+ tmp.irq = 0;
+ tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+ tmp.xmit_fifo_size = port->bulk_out_size;
+ tmp.baud_base = 9600;
+ tmp.close_delay = 5*HZ;
+ tmp.closing_wait = 30*HZ;
+
+ if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+ return -EFAULT;
+ return 0;
+}
+
+static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+{
+ struct qt2_port_private *priv = usb_get_serial_port_data(port);
+ struct async_icount prev, cur;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ prev = priv->icount;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ while (1) {
+ wait_event_interruptible(priv->delta_msr_wait,
+ ((priv->icount.rng != prev.rng) ||
+ (priv->icount.dsr != prev.dsr) ||
+ (priv->icount.dcd != prev.dcd) ||
+ (priv->icount.cts != prev.cts)));
+
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ cur = priv->icount;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if ((prev.rng == cur.rng) &&
+ (prev.dsr == cur.dsr) &&
+ (prev.dcd == cur.dcd) &&
+ (prev.cts == cur.cts))
+ return -EIO;
+
+ if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) ||
+ (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) ||
+ (arg & TIOCM_CD && (prev.dcd != cur.dcd)) ||
+ (arg & TIOCM_CTS && (prev.cts != cur.cts)))
+ return 0;
+ }
+ return 0;
+}
+
+static int qt2_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct qt2_port_private *priv = usb_get_serial_port_data(port);
+ struct async_icount cnow = priv->icount;
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+
+ return 0;
+}
+
+static int qt2_ioctl(struct tty_struct *tty,
+ unsigned int cmd, unsigned long arg)
+{
+ struct usb_serial_port *port = tty->driver_data;
+
+ switch (cmd) {
+ case TIOCGSERIAL:
+ return get_serial_info(port,
+ (struct serial_struct __user *)arg);
+
+ case TIOCMIWAIT:
+ return wait_modem_info(port, arg);
+
+ default:
+ break;
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static void qt2_process_status(struct usb_serial_port *port, unsigned char *ch)
+{
+ switch (*ch) {
+ case QT2_LINE_STATUS:
+ qt2_update_lsr(port, ch + 1);
+ break;
+ case QT2_MODEM_STATUS:
+ qt2_update_msr(port, ch + 1);
+ break;
+ }
+}
+
+/* not needed, kept to document functionality */
+static void qt2_process_xmit_empty(struct usb_serial_port *port,
+ unsigned char *ch)
+{
+ int bytes_written;
+
+ bytes_written = (int)(*ch) + (int)(*(ch + 1) << 4);
+}
+
+/* not needed, kept to document functionality */
+static void qt2_process_flush(struct usb_serial_port *port, unsigned char *ch)
+{
+ return;
+}
+
+void qt2_process_read_urb(struct urb *urb)
+{
+ struct usb_serial *serial;
+ struct qt2_serial_private *serial_priv;
+ struct usb_serial_port *port;
+ struct qt2_port_private *port_priv;
+ struct tty_struct *tty;
+ bool escapeflag;
+ unsigned char *ch;
+ int i;
+ unsigned char newport;
+ int len = urb->actual_length;
+
+ if (!len)
+ return;
+
+ ch = urb->transfer_buffer;
+ tty = NULL;
+ serial = urb->context;
+ serial_priv = usb_get_serial_data(serial);
+ port = serial->port[serial_priv->current_port];
+ port_priv = usb_get_serial_port_data(port);
+
+ if (port_priv->is_open)
+ tty = tty_port_tty_get(&port->port);
+
+ for (i = 0; i < urb->actual_length; i++) {
+ ch = (unsigned char *)urb->transfer_buffer + i;
+ if ((i <= (len - 3)) &&
+ (*ch == QT2_CONTROL_BYTE) &&
+ (*(ch + 1) == QT2_CONTROL_BYTE)) {
+ escapeflag = false;
+ switch (*(ch + 2)) {
+ case QT2_LINE_STATUS:
+ case QT2_MODEM_STATUS:
+ if (i > (len - 4)) {
+ dev_warn(&port->dev,
+ "%s - status message too short\n",
+ __func__);
+ break;
+ }
+ qt2_process_status(port, ch + 2);
+ i += 3;
+ escapeflag = true;
+ break;
+ case QT2_XMIT_HOLD:
+ if (i > (len - 5)) {
+ dev_warn(&port->dev,
+ "%s - xmit_empty message too short\n",
+ __func__);
+ break;
+ }
+ qt2_process_xmit_empty(port, ch + 3);
+ i += 4;
+ escapeflag = true;
+ break;
+ case QT2_CHANGE_PORT:
+ if (i > (len - 4)) {
+ dev_warn(&port->dev,
+ "%s - change_port message too short\n",
+ __func__);
+ break;
+ }
+ if (tty) {
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+ }
+
+ newport = *(ch + 3);
+
+ if (newport > serial->num_ports) {
+ dev_err(&port->dev,
+ "%s - port change to invalid port: %i\n",
+ __func__, newport);
+ break;
+ }
+
+ serial_priv->current_port = newport;
+ port = serial->port[serial_priv->current_port];
+ port_priv = usb_get_serial_port_data(port);
+ if (port_priv->is_open)
+ tty = tty_port_tty_get(&port->port);
+ else
+ tty = NULL;
+ i += 3;
+ escapeflag = true;
+ break;
+ case QT2_REC_FLUSH:
+ case QT2_XMIT_FLUSH:
+ qt2_process_flush(port, ch + 2);
+ i += 2;
+ escapeflag = true;
+ break;
+ case QT2_CONTROL_ESCAPE:
+ tty_buffer_request_room(tty, 2);
+ tty_insert_flip_string(tty, ch, 2);
+ i += 2;
+ escapeflag = true;
+ break;
+ default:
+ dev_warn(&port->dev,
+ "%s - unsupported command %i\n",
+ __func__, *(ch + 2));
+ break;
+ }
+ if (escapeflag)
+ continue;
+ }
+
+ if (tty) {
+ tty_buffer_request_room(tty, 1);
+ tty_insert_flip_string(tty, ch, 1);
+ }
+ }
+
+ if (tty) {
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+ }
+}
+
+static void qt2_write_bulk_callback(struct urb *urb)
+{
+ struct usb_serial_port *port;
+ struct qt2_port_private *port_priv;
+
+ port = urb->context;
+ port_priv = usb_get_serial_port_data(port);
+
+ spin_lock(&port_priv->urb_lock);
+
+ port_priv->urb_in_use = false;
+ usb_serial_port_softint(port);
+
+ spin_unlock(&port_priv->urb_lock);
+
+}
+
+static void qt2_read_bulk_callback(struct urb *urb)
+{
+ struct usb_serial *serial = urb->context;
+ int status;
+
+ if (urb->status) {
+ dev_warn(&serial->dev->dev,
+ "%s - non-zero urb status: %i\n", __func__,
+ urb->status);
+ return;
+ }
+
+ qt2_process_read_urb(urb);
+
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status != 0)
+ dev_err(&serial->dev->dev,
+ "%s - resubmit read urb failed: %i\n",
+ __func__, status);
+}
+
+static int qt2_setup_urbs(struct usb_serial *serial)
+{
+ struct usb_serial_port *port;
+ struct usb_serial_port *port0;
+ struct qt2_serial_private *serial_priv;
+ struct qt2_port_private *port_priv;
+ int pcount, status;
+
+ port0 = serial->port[0];
+
+ serial_priv = usb_get_serial_data(serial);
+ serial_priv->read_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!serial_priv->read_urb) {
+ dev_err(&serial->dev->dev, "No free urbs available\n");
+ return -ENOMEM;
+ }
+
+ usb_fill_bulk_urb(serial_priv->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port0->bulk_in_endpointAddress),
+ serial_priv->read_buffer,
+ sizeof(serial_priv->read_buffer),
+ qt2_read_bulk_callback, serial);
+
+ /* setup write_urb for each port */
+ for (pcount = 0; pcount < serial->num_ports; pcount++) {
+
+ port = serial->port[pcount];
+ port_priv = usb_get_serial_port_data(port);
+
+ port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!port_priv->write_urb) {
+ dev_err(&serial->dev->dev,
+ "failed to alloc write_urb for port %i\n",
+ pcount);
+ return -ENOMEM;
+ }
+
+ usb_fill_bulk_urb(port_priv->write_urb,
+ serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port0->
+ bulk_out_endpointAddress),
+ port_priv->write_buffer,
+ sizeof(port_priv->write_buffer),
+ qt2_write_bulk_callback, port);
+ }
+
+ status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL);
+ if (status != 0) {
+ dev_err(&serial->dev->dev,
+ "%s - submit read urb failed %i\n", __func__, status);
+ return status;
+ }
+
+ return 0;
+
+}
+
+static int qt2_attach(struct usb_serial *serial)
+{
+ struct qt2_serial_private *serial_priv;
+ struct qt2_port_private *port_priv;
+ int status, pcount;
+
+ /* power on unit */
+ status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ 0xc2, 0x40, 0x8000, 0, NULL, 0,
+ QT2_USB_TIMEOUT);
+ if (status < 0) {
+ dev_err(&serial->dev->dev,
+ "%s - failed to power on unit: %i\n", __func__, status);
+ return status;
+ }
+
+ serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+ if (!serial_priv) {
+ dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ usb_set_serial_data(serial, serial_priv);
+
+ for (pcount = 0; pcount < serial->num_ports; pcount++) {
+ port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
+ if (!port_priv) {
+ dev_err(&serial->dev->dev,
+ "%s- kmalloc(%Zd) failed.\n", __func__,
+ sizeof(*port_priv));
+ pcount--;
+ status = -ENOMEM;
+ goto attach_failed;
+ }
+
+ spin_lock_init(&port_priv->lock);
+ spin_lock_init(&port_priv->urb_lock);
+ init_waitqueue_head(&port_priv->delta_msr_wait);
+
+ port_priv->port = serial->port[pcount];
+
+ usb_set_serial_port_data(serial->port[pcount], port_priv);
+ }
+
+ status = qt2_setup_urbs(serial);
+ if (status != 0)
+ goto attach_failed;
+
+ return 0;
+
+attach_failed:
+ for (/* empty */; pcount >= 0; pcount--) {
+ port_priv = usb_get_serial_port_data(serial->port[pcount]);
+ kfree(port_priv);
+ }
+ kfree(serial_priv);
+ return status;
+}
+
+static int qt2_tiocmget(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct usb_device *dev = port->serial->dev;
+ struct qt2_port_private *port_priv = usb_get_serial_port_data(port);
+ u8 *d;
+ int r;
+
+ d = kzalloc(2, GFP_KERNEL);
+ if (!d)
+ return -ENOMEM;
+
+ r = qt2_getregister(dev, port_priv->device_port, UART_MCR, d);
+ if (r < 0)
+ goto mget_out;
+
+ r = qt2_getregister(dev, port_priv->device_port, UART_MSR, d + 1);
+ if (r < 0)
+ goto mget_out;
+
+ r = (d[0] & UART_MCR_DTR ? TIOCM_DTR : 0) |
+ (d[0] & UART_MCR_RTS ? TIOCM_RTS : 0) |
+ (d[1] & UART_MSR_CTS ? TIOCM_CTS : 0) |
+ (d[1] & UART_MSR_DCD ? TIOCM_CAR : 0) |
+ (d[1] & UART_MSR_RI ? TIOCM_RI : 0) |
+ (d[1] & UART_MSR_DSR ? TIOCM_DSR : 0);
+
+mget_out:
+ kfree(d);
+ return r;
+}
+
+static int qt2_tiocmset(struct tty_struct *tty,
+ unsigned int set, unsigned int clear)
+{
+ struct qt2_port_private *port_priv;
+
+ port_priv = usb_get_serial_port_data(tty->driver_data);
+ return update_mctrl(port_priv, set, clear);
+}
+
+static void qt2_break_ctl(struct tty_struct *tty, int break_state)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct qt2_port_private *port_priv;
+ int status;
+ u16 val;
+
+ port_priv = usb_get_serial_port_data(port);
+
+ if (!port_priv->is_open) {
+ dev_err(&port->dev,
+ "%s - port is not open\n", __func__);
+ return;
+ }
+
+ val = (break_state == -1) ? 1 : 0;
+
+ status = qt2_control_msg(port->serial->dev, QT2_BREAK_CONTROL,
+ val, port_priv->device_port);
+ if (status < 0)
+ dev_warn(&port->dev,
+ "%s - failed to send control message: %i\n", __func__,
+ status);
+}
+
+
+
+static void qt2_dtr_rts(struct usb_serial_port *port, int on)
+{
+ struct usb_device *dev = port->serial->dev;
+ struct qt2_port_private *port_priv = usb_get_serial_port_data(port);
+
+ mutex_lock(&port->serial->disc_mutex);
+ if (!port->serial->disconnected) {
+ /* Disable flow control */
+ if (!on && qt2_setregister(dev, port_priv->device_port,
+ UART_MCR, 0) < 0)
+ dev_warn(&port->dev, "error from flowcontrol urb\n");
+ /* drop RTS and DTR */
+ if (on)
+ update_mctrl(port_priv, TIOCM_DTR | TIOCM_RTS, 0);
+ else
+ update_mctrl(port_priv, 0, TIOCM_DTR | TIOCM_RTS);
+ }
+ mutex_unlock(&port->serial->disc_mutex);
+}
+
+static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)
+{
+ struct qt2_port_private *port_priv;
+ u8 newMSR = (u8) *ch;
+ unsigned long flags;
+
+ port_priv = usb_get_serial_port_data(port);
+
+ spin_lock_irqsave(&port_priv->lock, flags);
+ port_priv->shadowMSR = newMSR;
+ spin_unlock_irqrestore(&port_priv->lock, flags);
+
+ if (newMSR & UART_MSR_ANY_DELTA) {
+ /* update input line counters */
+ if (newMSR & UART_MSR_DCTS)
+ port_priv->icount.cts++;
+
+ if (newMSR & UART_MSR_DDSR)
+ port_priv->icount.dsr++;
+
+ if (newMSR & UART_MSR_DDCD)
+ port_priv->icount.dcd++;
+
+ if (newMSR & UART_MSR_TERI)
+ port_priv->icount.rng++;
+
+ wake_up_interruptible(&port_priv->delta_msr_wait);
+ }
+}
+
+static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch)
+{
+ struct qt2_port_private *port_priv;
+ struct async_icount *icount;
+ unsigned long flags;
+ u8 newLSR = (u8) *ch;
+
+ port_priv = usb_get_serial_port_data(port);
+
+ if (newLSR & UART_LSR_BI)
+ newLSR &= (u8) (UART_LSR_OE | UART_LSR_BI);
+
+ spin_lock_irqsave(&port_priv->lock, flags);
+ port_priv->shadowLSR = newLSR;
+ spin_unlock_irqrestore(&port_priv->lock, flags);
+
+ icount = &port_priv->icount;
+
+ if (newLSR & UART_LSR_BRK_ERROR_BITS) {
+
+ if (newLSR & UART_LSR_BI)
+ icount->brk++;
+
+ if (newLSR & UART_LSR_OE)
+ icount->overrun++;
+
+ if (newLSR & UART_LSR_PE)
+ icount->parity++;
+
+ if (newLSR & UART_LSR_FE)
+ icount->frame++;
+ }
+
+}
+
+static int qt2_write_room(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct qt2_port_private *port_priv;
+ unsigned long flags = 0;
+ int r;
+
+ port_priv = usb_get_serial_port_data(port);
+
+ spin_lock_irqsave(&port_priv->urb_lock, flags);
+
+ if (port_priv->urb_in_use)
+ r = 0;
+ else
+ r = QT2_WRITE_BUFFER_SIZE - QT2_WRITE_CONTROL_SIZE;
+
+ spin_unlock_irqrestore(&port_priv->urb_lock, flags);
+
+ return r;
+}
+
+static int qt2_write(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ const unsigned char *buf, int count)
+{
+ struct qt2_port_private *port_priv;
+ struct urb *write_urb;
+ unsigned char *data;
+ unsigned long flags;
+ int status;
+ int bytes_out = 0;
+
+ port_priv = usb_get_serial_port_data(port);
+
+ if (port_priv->write_urb == NULL) {
+ dev_err(&port->dev, "%s - no output urb\n", __func__);
+ return 0;
+ }
+ write_urb = port_priv->write_urb;
+
+ count = min(count, QT2_WRITE_BUFFER_SIZE - QT2_WRITE_CONTROL_SIZE);
+
+ data = write_urb->transfer_buffer;
+ spin_lock_irqsave(&port_priv->urb_lock, flags);
+ if (port_priv->urb_in_use == true) {
+ printk(KERN_INFO "qt2_write - urb is in use\n");
+ goto write_out;
+ }
+
+ *data++ = QT2_CONTROL_BYTE;
+ *data++ = QT2_CONTROL_BYTE;
+ *data++ = port_priv->device_port;
+ put_unaligned_le16(count, data);
+ data += 2;
+ memcpy(data, buf, count);
+
+ write_urb->transfer_buffer_length = count + QT2_WRITE_CONTROL_SIZE;
+
+ status = usb_submit_urb(write_urb, GFP_ATOMIC);
+ if (status == 0) {
+ port_priv->urb_in_use = true;
+ bytes_out += count;
+ }
+
+write_out:
+ spin_unlock_irqrestore(&port_priv->urb_lock, flags);
+ return bytes_out;
+}
+
+
+static struct usb_serial_driver qt2_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "quatech-serial",
+ },
+ .description = DRIVER_DESC,
+ .id_table = id_table,
+ .open = qt2_open,
+ .close = qt2_close,
+ .write = qt2_write,
+ .write_room = qt2_write_room,
+ .calc_num_ports = qt2_calc_num_ports,
+ .attach = qt2_attach,
+ .release = qt2_release,
+ .disconnect = qt2_disconnect,
+ .dtr_rts = qt2_dtr_rts,
+ .break_ctl = qt2_break_ctl,
+ .tiocmget = qt2_tiocmget,
+ .tiocmset = qt2_tiocmset,
+ .get_icount = qt2_get_icount,
+ .ioctl = qt2_ioctl,
+ .set_termios = qt2_set_termios,
+};
+
+static struct usb_serial_driver *const serial_drivers[] = {
+ &qt2_device, NULL
+};
+
+module_usb_serial_driver(serial_drivers, id_table);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index ae4ee30c7411..36e9d9fc0618 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -151,13 +151,6 @@ static struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver safe_driver = {
- .name = "safe_serial",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static const __u16 crc10_table[256] = {
0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff,
0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
@@ -339,12 +332,12 @@ static int __init safe_init(void)
}
}
- return usb_serial_register_drivers(&safe_driver, serial_drivers);
+ return usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, id_table);
}
static void __exit safe_exit(void)
{
- usb_serial_deregister_drivers(&safe_driver, serial_drivers);
+ usb_serial_deregister_drivers(serial_drivers);
}
module_init(safe_init);
diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c
index 46c0430fd38b..e4a1787cdbac 100644
--- a/drivers/usb/serial/siemens_mpi.c
+++ b/drivers/usb/serial/siemens_mpi.c
@@ -29,13 +29,6 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver siemens_usb_mpi_driver = {
- .name = "siemens_mpi",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver siemens_usb_mpi_device = {
.driver = {
.owner = THIS_MODULE,
@@ -49,7 +42,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&siemens_usb_mpi_device, NULL
};
-module_usb_serial_driver(siemens_usb_mpi_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 8c8bf806f6fa..ba54a0a8235c 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -63,9 +63,7 @@ struct sierra_intf_private {
static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
{
- int result;
- dev_dbg(&udev->dev, "%s\n", __func__);
- result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
SWIMS_USB_REQUEST_SetPower, /* __u8 request */
USB_TYPE_VENDOR, /* __u8 request type */
swiState, /* __u16 value */
@@ -73,14 +71,11 @@ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
NULL, /* void *data */
0, /* __u16 size */
USB_CTRL_SET_TIMEOUT); /* int timeout */
- return result;
}
static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
{
- int result;
- dev_dbg(&udev->dev, "%s\n", __func__);
- result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
SWIMS_USB_REQUEST_SetNmea, /* __u8 request */
USB_TYPE_VENDOR, /* __u8 request type */
enable, /* __u16 value */
@@ -88,7 +83,6 @@ static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
NULL, /* void *data */
0, /* __u16 size */
USB_CTRL_SET_TIMEOUT); /* int timeout */
- return result;
}
static int sierra_calc_num_ports(struct usb_serial *serial)
@@ -96,8 +90,6 @@ static int sierra_calc_num_ports(struct usb_serial *serial)
int num_ports = 0;
u8 ifnum, numendpoints;
- dev_dbg(&serial->dev->dev, "%s\n", __func__);
-
ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
numendpoints = serial->interface->cur_altsetting->desc.bNumEndpoints;
@@ -150,7 +142,6 @@ static int sierra_calc_interface(struct usb_serial *serial)
int interface;
struct usb_interface *p_interface;
struct usb_host_interface *p_host_interface;
- dev_dbg(&serial->dev->dev, "%s\n", __func__);
/* Get the interface structure pointer from the serial struct */
p_interface = serial->interface;
@@ -175,9 +166,8 @@ static int sierra_probe(struct usb_serial *serial,
u8 ifnum;
udev = serial->dev;
- dev_dbg(&udev->dev, "%s\n", __func__);
-
ifnum = sierra_calc_interface(serial);
+
/*
* If this interface supports more than 1 alternate
* select the 2nd one
@@ -344,8 +334,6 @@ static int sierra_send_setup(struct usb_serial_port *port)
int do_send = 0;
int retval;
- dev_dbg(&port->dev, "%s\n", __func__);
-
portdata = usb_get_serial_port_data(port);
if (portdata->dtr_state)
@@ -393,7 +381,6 @@ static int sierra_send_setup(struct usb_serial_port *port)
static void sierra_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
- dev_dbg(&port->dev, "%s\n", __func__);
tty_termios_copy_hw(tty->termios, old_termios);
sierra_send_setup(port);
}
@@ -404,7 +391,6 @@ static int sierra_tiocmget(struct tty_struct *tty)
unsigned int value;
struct sierra_port_private *portdata;
- dev_dbg(&port->dev, "%s\n", __func__);
portdata = usb_get_serial_port_data(port);
value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
@@ -441,8 +427,7 @@ static void sierra_release_urb(struct urb *urb)
{
struct usb_serial_port *port;
if (urb) {
- port = urb->context;
- dev_dbg(&port->dev, "%s: %p\n", __func__, urb);
+ port = urb->context;
kfree(urb->transfer_buffer);
usb_free_urb(urb);
}
@@ -455,7 +440,6 @@ static void sierra_outdat_callback(struct urb *urb)
struct sierra_intf_private *intfdata;
int status = urb->status;
- dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number);
intfdata = port->serial->private;
/* free up the transfer buffer, as usb_free_urb() does not do this */
@@ -598,8 +582,6 @@ static void sierra_indat_callback(struct urb *urb)
endpoint = usb_pipeendpoint(urb->pipe);
port = urb->context;
- dev_dbg(&port->dev, "%s: %p\n", __func__, urb);
-
if (status) {
dev_dbg(&port->dev, "%s: nonzero status: %d on"
" endpoint %02x\n", __func__, status, endpoint);
@@ -697,8 +679,6 @@ static int sierra_write_room(struct tty_struct *tty)
struct sierra_port_private *portdata = usb_get_serial_port_data(port);
unsigned long flags;
- dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number);
-
/* try to give a good number back based on if we have any free urbs at
* this point in time */
spin_lock_irqsave(&portdata->lock, flags);
@@ -805,8 +785,6 @@ static void sierra_close(struct usb_serial_port *port)
struct sierra_port_private *portdata;
struct sierra_intf_private *intfdata = port->serial->private;
-
- dev_dbg(&port->dev, "%s\n", __func__);
portdata = usb_get_serial_port_data(port);
portdata->rts_state = 0;
@@ -851,8 +829,6 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port);
- dev_dbg(&port->dev, "%s\n", __func__);
-
/* Set some sane defaults */
portdata->rts_state = 1;
portdata->dtr_state = 1;
@@ -915,8 +891,6 @@ static int sierra_startup(struct usb_serial *serial)
int i;
u8 ifnum;
- dev_dbg(&serial->dev->dev, "%s\n", __func__);
-
/* Set Device mode to D0 */
sierra_set_power_state(serial->dev, 0x0000);
@@ -977,8 +951,6 @@ static void sierra_release(struct usb_serial *serial)
struct usb_serial_port *port;
struct sierra_port_private *portdata;
- dev_dbg(&serial->dev->dev, "%s\n", __func__);
-
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
if (!port)
@@ -1067,29 +1039,11 @@ static int sierra_resume(struct usb_serial *serial)
return ec ? -EIO : 0;
}
-static int sierra_reset_resume(struct usb_interface *intf)
-{
- struct usb_serial *serial = usb_get_intfdata(intf);
- dev_err(&serial->dev->dev, "%s\n", __func__);
- return usb_serial_resume(intf);
-}
#else
#define sierra_suspend NULL
#define sierra_resume NULL
-#define sierra_reset_resume NULL
#endif
-static struct usb_driver sierra_driver = {
- .name = "sierra",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .reset_resume = sierra_reset_resume,
- .id_table = id_table,
- .supports_autosuspend = 1,
-};
-
static struct usb_serial_driver sierra_device = {
.driver = {
.owner = THIS_MODULE,
@@ -1118,7 +1072,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&sierra_device, NULL
};
-module_usb_serial_driver(sierra_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index f06c9a8f3d37..cad608984710 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -151,14 +151,6 @@ enum spcp8x5_type {
SPCP835_TYPE,
};
-static struct usb_driver spcp8x5_driver = {
- .name = "spcp8x5",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
-
struct spcp8x5_private {
spinlock_t lock;
enum spcp8x5_type type;
@@ -433,7 +425,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
if (i < 0)
dev_err(&port->dev, "Set UART format %#x failed (error = %d)\n",
uartdata, i);
- dbg("0x21:0x40:0:0 %d", i);
+ dev_dbg(&port->dev, "0x21:0x40:0:0 %d\n", i);
if (cflag & CRTSCTS) {
/* enable hardware flow control */
@@ -454,8 +446,6 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)
u8 status = 0x30;
/* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */
- dbg("%s - port %d", __func__, port->number);
-
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
@@ -579,15 +569,19 @@ static int spcp8x5_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
- dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
+
+ dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__,
+ port->number, cmd);
switch (cmd) {
case TIOCMIWAIT:
- dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
+ dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,
+ port->number);
return spcp8x5_wait_modem_info(port, arg);
default:
- dbg("%s not supported = 0x%04x", __func__, cmd);
+ dev_dbg(&port->dev, "%s not supported = 0x%04x", __func__,
+ cmd);
break;
}
@@ -666,7 +660,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&spcp8x5_device, NULL
};
-module_usb_serial_driver(spcp8x5_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 3cdc8a52de44..3fee23bf0c14 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -59,20 +59,8 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)},
{} /* Terminating entry */
};
-
MODULE_DEVICE_TABLE(usb, id_table);
-
-static struct usb_driver ssu100_driver = {
- .name = "ssu100",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .supports_autosuspend = 1,
-};
-
struct ssu100_port_private {
spinlock_t status_lock;
u8 shadowLSR;
@@ -85,7 +73,6 @@ static void ssu100_release(struct usb_serial *serial)
{
struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port);
- dbg("%s", __func__);
kfree(priv);
}
@@ -171,8 +158,6 @@ static int ssu100_initdevice(struct usb_device *dev)
u8 *data;
int result = 0;
- dbg("%s", __func__);
-
data = kzalloc(3, GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -237,8 +222,6 @@ static void ssu100_set_termios(struct tty_struct *tty,
u16 urb_value = 0; /* will hold the new flags */
int result;
- dbg("%s", __func__);
-
if (cflag & PARENB) {
if (cflag & PARODD)
urb_value |= UART_LCR_PARITY;
@@ -312,8 +295,6 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
int result;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
data = kzalloc(2, GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -348,7 +329,6 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
static void ssu100_close(struct usb_serial_port *port)
{
- dbg("%s", __func__);
usb_serial_generic_close(port);
}
@@ -467,8 +447,6 @@ static int ssu100_attach(struct usb_serial *serial)
struct ssu100_port_private *priv;
struct usb_serial_port *port = *serial->port;
- dbg("%s", __func__);
-
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__,
@@ -490,8 +468,6 @@ static int ssu100_tiocmget(struct tty_struct *tty)
u8 *d;
int r;
- dbg("%s\n", __func__);
-
d = kzalloc(2, GFP_KERNEL);
if (!d)
return -ENOMEM;
@@ -522,7 +498,6 @@ static int ssu100_tiocmset(struct tty_struct *tty,
struct usb_serial_port *port = tty->driver_data;
struct usb_device *dev = port->serial->dev;
- dbg("%s\n", __func__);
return update_mctrl(dev, set, clear);
}
@@ -530,8 +505,6 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on)
{
struct usb_device *dev = port->serial->dev;
- dbg("%s\n", __func__);
-
mutex_lock(&port->serial->disc_mutex);
if (!port->serial->disconnected) {
/* Disable flow control */
@@ -618,8 +591,6 @@ static int ssu100_process_packet(struct urb *urb,
int i;
char *ch;
- dbg("%s - port %d", __func__, port->number);
-
if ((len >= 4) &&
(packet[0] == 0x1b) && (packet[1] == 0x1b) &&
((packet[2] == 0x00) || (packet[2] == 0x01))) {
@@ -656,8 +627,6 @@ static void ssu100_process_read_urb(struct urb *urb)
struct tty_struct *tty;
int count;
- dbg("%s", __func__);
-
tty = tty_port_tty_get(&port->port);
if (!tty)
return;
@@ -695,7 +664,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&ssu100_device, NULL
};
-module_usb_serial_driver(ssu100_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
index 1a5be136e6cf..e53d2aac35c5 100644
--- a/drivers/usb/serial/symbolserial.c
+++ b/drivers/usb/serial/symbolserial.c
@@ -54,8 +54,6 @@ static void symbol_int_callback(struct urb *urb)
int result;
int data_length;
- dbg("%s - port %d", __func__, port->number);
-
switch (status) {
case 0:
/* success */
@@ -64,12 +62,12 @@ static void symbol_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
@@ -125,8 +123,6 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
unsigned long flags;
int result = 0;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&priv->lock, flags);
priv->throttled = false;
priv->actually_throttled = false;
@@ -150,8 +146,6 @@ static void symbol_close(struct usb_serial_port *port)
{
struct symbol_private *priv = usb_get_serial_data(port->serial);
- dbg("%s - port %d", __func__, port->number);
-
/* shutdown our urbs */
usb_kill_urb(priv->int_urb);
}
@@ -161,7 +155,6 @@ static void symbol_throttle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct symbol_private *priv = usb_get_serial_data(port->serial);
- dbg("%s - port %d", __func__, port->number);
spin_lock_irq(&priv->lock);
priv->throttled = true;
spin_unlock_irq(&priv->lock);
@@ -174,8 +167,6 @@ static void symbol_unthrottle(struct tty_struct *tty)
int result;
bool was_throttled;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irq(&priv->lock);
priv->throttled = false;
was_throttled = priv->actually_throttled;
@@ -266,8 +257,6 @@ static void symbol_disconnect(struct usb_serial *serial)
{
struct symbol_private *priv = usb_get_serial_data(serial);
- dbg("%s", __func__);
-
usb_kill_urb(priv->int_urb);
usb_free_urb(priv->int_urb);
}
@@ -276,19 +265,10 @@ static void symbol_release(struct usb_serial *serial)
{
struct symbol_private *priv = usb_get_serial_data(serial);
- dbg("%s", __func__);
-
kfree(priv->int_buffer);
kfree(priv);
}
-static struct usb_driver symbol_driver = {
- .name = "symbol",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver symbol_device = {
.driver = {
.owner = THIS_MODULE,
@@ -309,7 +289,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&symbol_device, NULL
};
-module_usb_serial_driver(symbol_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index ab74123d658e..a4404f5ad68e 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -165,7 +165,7 @@ static unsigned int product_5052_count;
/* the array dimension is the number of default entries plus */
/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */
/* null entry */
-static struct usb_device_id ti_id_table_3410[14+TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_3410[15+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -180,6 +180,7 @@ static struct usb_device_id ti_id_table_3410[14+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
};
static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
@@ -189,7 +190,7 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
};
-static struct usb_device_id ti_id_table_combined[18+2*TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_combined[19+2*TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -208,16 +209,10 @@ static struct usb_device_id ti_id_table_combined[18+2*TI_EXTRA_VID_PID_COUNT+1]
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
{ }
};
-static struct usb_driver ti_usb_driver = {
- .name = "ti_usb_3410_5052",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = ti_id_table_combined,
-};
-
static struct usb_serial_driver ti_1port_device = {
.driver = {
.owner = THIS_MODULE,
@@ -344,20 +339,18 @@ static int __init ti_init(void)
ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
}
- ret = usb_serial_register_drivers(&ti_usb_driver, serial_drivers);
+ ret = usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, ti_id_table_combined);
if (ret == 0)
printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":"
TI_DRIVER_DESC "\n");
return ret;
}
-
static void __exit ti_exit(void)
{
- usb_serial_deregister_drivers(&ti_usb_driver, serial_drivers);
+ usb_serial_deregister_drivers(serial_drivers);
}
-
module_init(ti_init);
module_exit(ti_exit);
@@ -394,7 +387,9 @@ static int ti_startup(struct usb_serial *serial)
/* if we have only 1 configuration, download firmware */
if (dev->descriptor.bNumConfigurations == 1) {
- if ((status = ti_download_firmware(tdev)) != 0)
+ status = ti_download_firmware(tdev);
+
+ if (status != 0)
goto free_tdev;
/* 3410 must be reset, 5052 resets itself */
@@ -463,8 +458,6 @@ static void ti_release(struct usb_serial *serial)
struct ti_device *tdev = usb_get_serial_data(serial);
struct ti_port *tport;
- dbg("%s", __func__);
-
for (i = 0; i < serial->num_ports; ++i) {
tport = usb_get_serial_port_data(serial->port[i]);
if (tport) {
@@ -489,8 +482,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
TI_PIPE_TIMEOUT_ENABLE |
(TI_TRANSFER_TIMEOUT << 2));
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return -ENODEV;
@@ -631,8 +622,6 @@ static void ti_close(struct usb_serial_port *port)
int status;
int do_unlock;
- dbg("%s - port %d", __func__, port->number);
-
tdev = usb_get_serial_data(port->serial);
tport = usb_get_serial_port_data(port);
if (tdev == NULL || tport == NULL)
@@ -666,8 +655,6 @@ static void ti_close(struct usb_serial_port *port)
}
if (do_unlock)
mutex_unlock(&tdev->td_open_close_lock);
-
- dbg("%s - exit", __func__);
}
@@ -676,8 +663,6 @@ static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
{
struct ti_port *tport = usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
-
if (count == 0) {
dbg("%s - write request of 0 bytes", __func__);
return 0;
@@ -701,8 +686,6 @@ static int ti_write_room(struct tty_struct *tty)
int room = 0;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return 0;
@@ -722,8 +705,6 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
int chars = 0;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return 0;
@@ -741,8 +722,6 @@ static void ti_throttle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return;
@@ -758,8 +737,6 @@ static void ti_unthrottle(struct tty_struct *tty)
struct ti_port *tport = usb_get_serial_port_data(port);
int status;
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return;
@@ -854,8 +831,6 @@ static void ti_set_termios(struct tty_struct *tty,
int port_number = port->number - port->serial->minor;
unsigned int mcr;
- dbg("%s - port %d", __func__, port->number);
-
cflag = tty->termios->c_cflag;
iflag = tty->termios->c_iflag;
@@ -988,8 +963,6 @@ static int ti_tiocmget(struct tty_struct *tty)
unsigned int mcr;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return -ENODEV;
@@ -1020,8 +993,6 @@ static int ti_tiocmset(struct tty_struct *tty,
unsigned int mcr;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
-
if (tport == NULL)
return -ENODEV;
@@ -1084,8 +1055,6 @@ static void ti_interrupt_callback(struct urb *urb)
int retval;
__u8 msr;
- dbg("%s", __func__);
-
switch (status) {
case 0:
break;
@@ -1165,8 +1134,6 @@ static void ti_bulk_in_callback(struct urb *urb)
int retval = 0;
struct tty_struct *tty;
- dbg("%s", __func__);
-
switch (status) {
case 0:
break;
@@ -1233,8 +1200,6 @@ static void ti_bulk_out_callback(struct urb *urb)
struct usb_serial_port *port = tport->tp_port;
int status = urb->status;
- dbg("%s - port %d", __func__, port->number);
-
tport->tp_write_urb_in_use = 0;
switch (status) {
@@ -1287,9 +1252,6 @@ static void ti_send(struct ti_port *tport)
struct tty_struct *tty = tty_port_tty_get(&port->port); /* FIXME */
unsigned long flags;
-
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irqsave(&tport->tp_lock, flags);
if (tport->tp_write_urb_in_use)
@@ -1366,8 +1328,6 @@ static int ti_get_lsr(struct ti_port *tport)
int port_number = port->number - port->serial->minor;
struct ti_port_status *data;
- dbg("%s - port %d", __func__, port->number);
-
size = sizeof(struct ti_port_status);
data = kmalloc(size, GFP_KERNEL);
if (!data) {
@@ -1480,8 +1440,6 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
struct usb_serial_port *port = tport->tp_port;
wait_queue_t wait;
- dbg("%s - port %d", __func__, port->number);
-
spin_lock_irq(&tport->tp_lock);
/* wait for data to drain from the buffer */
@@ -1679,11 +1637,12 @@ static int ti_download_firmware(struct ti_device *tdev)
const struct firmware *fw_p;
char buf[32];
- dbg("%s\n", __func__);
/* try ID specific firmware first, then try generic firmware */
sprintf(buf, "ti_usb-v%04x-p%04x.fw", dev->descriptor.idVendor,
dev->descriptor.idProduct);
- if ((status = request_firmware(&fw_p, buf, &dev->dev)) != 0) {
+ status = request_firmware(&fw_p, buf, &dev->dev);
+
+ if (status != 0) {
buf[0] = '\0';
if (dev->descriptor.idVendor == MTS_VENDOR_ID) {
switch (dev->descriptor.idProduct) {
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
index f140f1b9d5c0..b353e7e3d480 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.h
+++ b/drivers/usb/serial/ti_usb_3410_5052.h
@@ -37,6 +37,7 @@
#define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */
#define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */
#define TI_5052_FIRMWARE_PRODUCT_ID 0x505F /* firmware is running */
+#define FRI2_PRODUCT_ID 0x5053 /* Fish River Island II */
/* Multi-Tech vendor and product ids */
#define MTS_VENDOR_ID 0x06E0
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 97355a15bbea..6a1b609a0d94 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1,7 +1,7 @@
/*
* USB Serial Converter driver
*
- * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 1999 - 2012 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2000 Peter Berger (pberger@brimson.com)
* Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
*
@@ -43,17 +43,6 @@
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
#define DRIVER_DESC "USB Serial Driver core"
-/* Driver structure we register with the USB core */
-static struct usb_driver usb_serial_driver = {
- .name = "usbserial",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .suspend = usb_serial_suspend,
- .resume = usb_serial_resume,
- .no_dynamic_id = 1,
- .supports_autosuspend = 1,
-};
-
/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
the MODULE_DEVICE_TABLE declarations in each serial driver
cause the "hotplug" program to pull in whatever module is necessary
@@ -710,7 +699,7 @@ static const struct tty_port_operations serial_port_ops = {
.shutdown = serial_down,
};
-int usb_serial_probe(struct usb_interface *interface,
+static int usb_serial_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(interface);
@@ -856,6 +845,8 @@ int usb_serial_probe(struct usb_interface *interface,
module_put(type->driver.owner);
return -EIO;
}
+ dev_info(&interface->dev, "The \"generic\" usb-serial driver is only for testing and one-off prototypes.\n");
+ dev_info(&interface->dev, "Tell linux-usb@vger.kernel.org to add your device to a proper driver.\n");
}
#endif
if (!num_ports) {
@@ -1043,6 +1034,8 @@ int usb_serial_probe(struct usb_interface *interface,
dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
}
+ usb_set_intfdata(interface, serial);
+
/* if this device type has an attach function, call it */
if (type->attach) {
retval = type->attach(serial);
@@ -1087,10 +1080,7 @@ int usb_serial_probe(struct usb_interface *interface,
serial->disconnected = 0;
usb_serial_console_init(debug, minor);
-
exit:
- /* success */
- usb_set_intfdata(interface, serial);
module_put(type->driver.owner);
return 0;
@@ -1099,9 +1089,8 @@ probe_error:
module_put(type->driver.owner);
return -EIO;
}
-EXPORT_SYMBOL_GPL(usb_serial_probe);
-void usb_serial_disconnect(struct usb_interface *interface)
+static void usb_serial_disconnect(struct usb_interface *interface)
{
int i;
struct usb_serial *serial = usb_get_intfdata(interface);
@@ -1112,7 +1101,6 @@ void usb_serial_disconnect(struct usb_interface *interface)
dbg("%s", __func__);
mutex_lock(&serial->disc_mutex);
- usb_set_intfdata(interface, NULL);
/* must set a flag, to signal subdrivers */
serial->disconnected = 1;
mutex_unlock(&serial->disc_mutex);
@@ -1137,7 +1125,6 @@ void usb_serial_disconnect(struct usb_interface *interface)
usb_serial_put(serial);
dev_info(dev, "device disconnected\n");
}
-EXPORT_SYMBOL_GPL(usb_serial_disconnect);
int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
{
@@ -1181,6 +1168,22 @@ int usb_serial_resume(struct usb_interface *intf)
}
EXPORT_SYMBOL(usb_serial_resume);
+static int usb_serial_reset_resume(struct usb_interface *intf)
+{
+ struct usb_serial *serial = usb_get_intfdata(intf);
+ int rv;
+
+ serial->suspending = 0;
+ if (serial->type->reset_resume)
+ rv = serial->type->reset_resume(serial);
+ else {
+ rv = -EOPNOTSUPP;
+ intf->needs_binding = 1;
+ }
+
+ return rv;
+}
+
static const struct tty_operations serial_ops = {
.open = serial_open,
.close = serial_close,
@@ -1204,6 +1207,17 @@ static const struct tty_operations serial_ops = {
struct tty_driver *usb_serial_tty_driver;
+/* Driver structure we register with the USB core */
+static struct usb_driver usb_serial_driver = {
+ .name = "usbserial",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .suspend = usb_serial_suspend,
+ .resume = usb_serial_resume,
+ .no_dynamic_id = 1,
+ .supports_autosuspend = 1,
+};
+
static int __init usb_serial_init(void)
{
int i;
@@ -1338,7 +1352,6 @@ static int usb_serial_register(struct usb_serial_driver *driver)
driver->description);
return -EINVAL;
}
- driver->usb_driver->supports_autosuspend = 1;
/* Add this device to our list of devices */
mutex_lock(&table_lock);
@@ -1369,18 +1382,19 @@ static void usb_serial_deregister(struct usb_serial_driver *device)
/**
* usb_serial_register_drivers - register drivers for a usb-serial module
- * @udriver: usb_driver used for matching devices/interfaces
* @serial_drivers: NULL-terminated array of pointers to drivers to be registered
+ * @name: name of the usb_driver for this set of @serial_drivers
+ * @id_table: list of all devices this @serial_drivers set binds to
*
- * Registers @udriver and all the drivers in the @serial_drivers array.
- * Automatically fills in the .no_dynamic_id field in @udriver and
- * the .usb_driver field in each serial driver.
+ * Registers all the drivers in the @serial_drivers array, and dynamically
+ * creates a struct usb_driver with the name @name and id_table of @id_table.
*/
-int usb_serial_register_drivers(struct usb_driver *udriver,
- struct usb_serial_driver * const serial_drivers[])
+int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[],
+ const char *name,
+ const struct usb_device_id *id_table)
{
int rc;
- const struct usb_device_id *saved_id_table;
+ struct usb_driver *udriver;
struct usb_serial_driver * const *sd;
/*
@@ -1391,12 +1405,30 @@ int usb_serial_register_drivers(struct usb_driver *udriver,
* Performance hack: We don't want udriver to be probed until
* the serial drivers are registered, because the probe would
* simply fail for lack of a matching serial driver.
- * Therefore save off udriver's id_table until we are all set.
+ * So we leave udriver's id_table set to NULL until we are all set.
+ *
+ * Suspend/resume support is implemented in the usb-serial core,
+ * so fill in the PM-related fields in udriver.
*/
- saved_id_table = udriver->id_table;
- udriver->id_table = NULL;
+ udriver = kzalloc(sizeof(*udriver), GFP_KERNEL);
+ if (!udriver)
+ return -ENOMEM;
+ udriver->name = name;
udriver->no_dynamic_id = 1;
+ udriver->supports_autosuspend = 1;
+ udriver->suspend = usb_serial_suspend;
+ udriver->resume = usb_serial_resume;
+ udriver->probe = usb_serial_probe;
+ udriver->disconnect = usb_serial_disconnect;
+
+ /* we only set the reset_resume field if the serial_driver has one */
+ for (sd = serial_drivers; *sd; ++sd) {
+ if ((*sd)->reset_resume)
+ udriver->reset_resume = usb_serial_reset_resume;
+ break;
+ }
+
rc = usb_register(udriver);
if (rc)
return rc;
@@ -1408,8 +1440,8 @@ int usb_serial_register_drivers(struct usb_driver *udriver,
goto failed;
}
- /* Now restore udriver's id_table and look for matches */
- udriver->id_table = saved_id_table;
+ /* Now set udriver's id_table and look for matches */
+ udriver->id_table = id_table;
rc = driver_attach(&udriver->drvwrap.driver);
return 0;
@@ -1423,17 +1455,20 @@ EXPORT_SYMBOL_GPL(usb_serial_register_drivers);
/**
* usb_serial_deregister_drivers - deregister drivers for a usb-serial module
- * @udriver: usb_driver to unregister
* @serial_drivers: NULL-terminated array of pointers to drivers to be deregistered
*
- * Deregisters @udriver and all the drivers in the @serial_drivers array.
+ * Deregisters all the drivers in the @serial_drivers array and deregisters and
+ * frees the struct usb_driver that was created by the call to
+ * usb_serial_register_drivers().
*/
-void usb_serial_deregister_drivers(struct usb_driver *udriver,
- struct usb_serial_driver * const serial_drivers[])
+void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_drivers[])
{
+ struct usb_driver *udriver = (*serial_drivers)->usb_driver;
+
for (; *serial_drivers; ++serial_drivers)
usb_serial_deregister(*serial_drivers);
usb_deregister(udriver);
+ kfree(udriver);
}
EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers);
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
index e3e8995a4739..5760f97ee508 100644
--- a/drivers/usb/serial/usb_debug.c
+++ b/drivers/usb/serial/usb_debug.c
@@ -35,13 +35,6 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver debug_driver = {
- .name = "debug",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
/* This HW really does not support a serial break, so one will be
* emulated when ever the break state is set to true.
*/
@@ -83,5 +76,5 @@ static struct usb_serial_driver * const serial_drivers[] = {
&debug_device, NULL
};
-module_usb_serial_driver(debug_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index c88657dd31c8..f35971dff4a5 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -43,11 +43,8 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
{
struct usb_serial *serial = port->serial;
struct usb_wwan_port_private *portdata;
-
struct usb_wwan_intf_private *intfdata;
- dbg("%s", __func__);
-
intfdata = port->serial->private;
if (!intfdata->send_setup)
@@ -69,8 +66,6 @@ void usb_wwan_set_termios(struct tty_struct *tty,
{
struct usb_wwan_intf_private *intfdata = port->serial->private;
- dbg("%s", __func__);
-
/* Doesn't support option setting */
tty_termios_copy_hw(tty->termios, old_termios);
@@ -286,8 +281,6 @@ static void usb_wwan_indat_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg("%s: %p", __func__, urb);
-
endpoint = usb_pipeendpoint(urb->pipe);
port = urb->context;
@@ -307,20 +300,17 @@ static void usb_wwan_indat_callback(struct urb *urb)
}
/* Resubmit urb so we continue receiving */
- if (status != -ESHUTDOWN) {
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err) {
- if (err != -EPERM) {
- printk(KERN_ERR "%s: resubmit read urb failed. "
- "(%d)", __func__, err);
- /* busy also in error unless we are killed */
- usb_mark_last_busy(port->serial->dev);
- }
- } else {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err) {
+ if (err != -EPERM) {
+ printk(KERN_ERR "%s: resubmit read urb failed. "
+ "(%d)", __func__, err);
+ /* busy also in error unless we are killed */
usb_mark_last_busy(port->serial->dev);
}
+ } else {
+ usb_mark_last_busy(port->serial->dev);
}
-
}
}
@@ -331,8 +321,6 @@ static void usb_wwan_outdat_callback(struct urb *urb)
struct usb_wwan_intf_private *intfdata;
int i;
- dbg("%s", __func__);
-
port = urb->context;
intfdata = port->serial->private;
@@ -406,8 +394,6 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port);
intfdata = serial->private;
- dbg("%s", __func__);
-
/* Start reading from the IN endpoint */
for (i = 0; i < N_IN_URB; i++) {
urb = portdata->in_urbs[i];
@@ -441,7 +427,6 @@ void usb_wwan_close(struct usb_serial_port *port)
struct usb_wwan_port_private *portdata;
struct usb_wwan_intf_private *intfdata = port->serial->private;
- dbg("%s", __func__);
portdata = usb_get_serial_port_data(port);
if (serial->dev) {
@@ -492,8 +477,6 @@ static void usb_wwan_setup_urbs(struct usb_serial *serial)
struct usb_serial_port *port;
struct usb_wwan_port_private *portdata;
- dbg("%s", __func__);
-
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
portdata = usb_get_serial_port_data(port);
@@ -534,8 +517,6 @@ int usb_wwan_startup(struct usb_serial *serial)
struct usb_wwan_port_private *portdata;
u8 *buffer;
- dbg("%s", __func__);
-
/* Now setup per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
@@ -603,8 +584,6 @@ static void stop_read_write_urbs(struct usb_serial *serial)
void usb_wwan_disconnect(struct usb_serial *serial)
{
- dbg("%s", __func__);
-
stop_read_write_urbs(serial);
}
EXPORT_SYMBOL(usb_wwan_disconnect);
@@ -615,8 +594,6 @@ void usb_wwan_release(struct usb_serial *serial)
struct usb_serial_port *port;
struct usb_wwan_port_private *portdata;
- dbg("%s", __func__);
-
/* Now free them */
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
@@ -649,8 +626,6 @@ int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message)
struct usb_wwan_intf_private *intfdata = serial->private;
int b;
- dbg("%s entered", __func__);
-
if (PMSG_IS_AUTO(message)) {
spin_lock_irq(&intfdata->susp_lock);
b = intfdata->in_flight;
@@ -714,7 +689,6 @@ int usb_wwan_resume(struct usb_serial *serial)
struct urb *urb;
int err = 0;
- dbg("%s entered", __func__);
/* get the interrupt URBs resubmitted unconditionally */
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
@@ -725,8 +699,8 @@ int usb_wwan_resume(struct usb_serial *serial)
err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
dbg("Submitted interrupt URB for port %d (result %d)", i, err);
if (err < 0) {
- err("%s: Error %d for interrupt URB of port%d",
- __func__, err, i);
+ dev_err(&port->dev, "%s: Error %d for interrupt URB\n",
+ __func__, err);
goto err_out;
}
}
@@ -747,8 +721,8 @@ int usb_wwan_resume(struct usb_serial *serial)
urb = portdata->in_urbs[j];
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0) {
- err("%s: Error %d for bulk URB %d",
- __func__, err, i);
+ dev_err(&port->dev, "%s: Error %d for bulk URB %d\n",
+ __func__, err, i);
spin_unlock_irq(&intfdata->susp_lock);
goto err_out;
}
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 71d696474f24..f253c91383da 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -53,8 +53,6 @@ static int palm_os_4_probe(struct usb_serial *serial,
/* Parameters that may be passed into the module. */
static bool debug;
-static __u16 vendor;
-static __u16 product;
static struct usb_device_id id_table [] = {
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID),
@@ -115,14 +113,12 @@ static struct usb_device_id id_table [] = {
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
- { }, /* optional parameter entry */
{ } /* Terminating entry */
};
static struct usb_device_id clie_id_5_table [] = {
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
- { }, /* optional parameter entry */
{ } /* Terminating entry */
};
@@ -162,19 +158,11 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID) },
{ USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID) },
- { }, /* optional parameter entry */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver visor_driver = {
- .name = "visor",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
-};
-
/* All of the device info needed for the Handspring Visor,
and Palm 4.0 devices */
static struct usb_serial_driver handspring_device = {
@@ -244,8 +232,6 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port)
{
int result = 0;
- dbg("%s - port %d", __func__, port->number);
-
if (!port->read_urb) {
/* this is needed for some brain dead Sony devices */
dev_err(&port->dev, "Device lied about number of ports, please use a lower one.\n");
@@ -258,7 +244,7 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port)
goto exit;
if (port->interrupt_in_urb) {
- dbg("%s - adding interrupt input for treo", __func__);
+ dev_dbg(&port->dev, "adding interrupt input for treo\n");
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result)
dev_err(&port->dev,
@@ -274,8 +260,6 @@ static void visor_close(struct usb_serial_port *port)
{
unsigned char *transfer_buffer;
- dbg("%s - port %d", __func__, port->number);
-
/* shutdown our urbs */
usb_serial_generic_close(port);
usb_kill_urb(port->interrupt_in_urb);
@@ -310,12 +294,12 @@ static void visor_read_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
+ __func__, status);
goto exit;
}
@@ -348,8 +332,6 @@ static int palm_os_3_probe(struct usb_serial *serial,
int i;
int num_ports = 0;
- dbg("%s", __func__);
-
transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL);
if (!transfer_buffer) {
dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
@@ -445,8 +427,6 @@ static int palm_os_4_probe(struct usb_serial *serial,
unsigned char *transfer_buffer;
int retval;
- dbg("%s", __func__);
-
transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL);
if (!transfer_buffer) {
dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
@@ -478,8 +458,6 @@ static int visor_probe(struct usb_serial *serial,
int (*startup)(struct usb_serial *serial,
const struct usb_device_id *id);
- dbg("%s", __func__);
-
/*
* some Samsung Android phones in modem mode have the same ID
* as SPH-I500, but they are ACM devices, so dont bind to them
@@ -521,8 +499,6 @@ static int clie_3_5_startup(struct usb_serial *serial)
int result;
u8 *data;
- dbg("%s", __func__);
-
data = kmalloc(1, GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -585,8 +561,6 @@ static int treo_attach(struct usb_serial *serial)
(serial->num_interrupt_in == 0))
return 0;
- dbg("%s", __func__);
-
/*
* It appears that Treos and Kyoceras want to use the
* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
@@ -622,8 +596,6 @@ static int clie_5_attach(struct usb_serial *serial)
unsigned int pipe;
int j;
- dbg("%s", __func__);
-
/* TH55 registers 2 ports.
Communication in from the UX50/TH55 uses bulk_in_endpointAddress
from port 0. Communication out to the UX50/TH55 uses
@@ -648,59 +620,7 @@ static int clie_5_attach(struct usb_serial *serial)
return 0;
}
-static int __init visor_init(void)
-{
- int i, retval;
- /* Only if parameters were passed to us */
- if (vendor > 0 && product > 0) {
- struct usb_device_id usb_dev_temp[] = {
- {
- USB_DEVICE(vendor, product),
- .driver_info =
- (kernel_ulong_t) &palm_os_4_probe
- }
- };
-
- /* Find the last entry in id_table */
- for (i = 0;; i++) {
- if (id_table[i].idVendor == 0) {
- id_table[i] = usb_dev_temp[0];
- break;
- }
- }
- /* Find the last entry in id_table_combined */
- for (i = 0;; i++) {
- if (id_table_combined[i].idVendor == 0) {
- id_table_combined[i] = usb_dev_temp[0];
- break;
- }
- }
- printk(KERN_INFO KBUILD_MODNAME
- ": Untested USB device specified at time of module insertion\n");
- printk(KERN_INFO KBUILD_MODNAME
- ": Warning: This is not guaranteed to work\n");
- printk(KERN_INFO KBUILD_MODNAME
- ": Using a newer kernel is preferred to this method\n");
- printk(KERN_INFO KBUILD_MODNAME
- ": Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x\n",
- vendor, product);
- }
-
- retval = usb_serial_register_drivers(&visor_driver, serial_drivers);
- if (retval == 0)
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
- return retval;
-}
-
-
-static void __exit visor_exit (void)
-{
- usb_serial_deregister_drivers(&visor_driver, serial_drivers);
-}
-
-
-module_init(visor_init);
-module_exit(visor_exit);
+module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
@@ -708,9 +628,3 @@ MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
-
-module_param(vendor, ushort, 0);
-MODULE_PARM_DESC(vendor, "User specified vendor ID");
-module_param(product, ushort, 0);
-MODULE_PARM_DESC(product, "User specified product ID");
-
diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c
index 078f338b5feb..0c0aa876c209 100644
--- a/drivers/usb/serial/vivopay-serial.c
+++ b/drivers/usb/serial/vivopay-serial.c
@@ -25,13 +25,6 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver vivopay_serial_driver = {
- .name = "vivopay-serial",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver vivopay_serial_device = {
.driver = {
.owner = THIS_MODULE,
@@ -45,7 +38,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&vivopay_serial_device, NULL
};
-module_usb_serial_driver(vivopay_serial_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR("Forest Bond <forest.bond@outpostembedded.com>");
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 407e23c87946..473635e7f5db 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -45,7 +45,6 @@ static bool debug;
/*
* Version Information
*/
-#define DRIVER_VERSION "v2.0"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Stuart MacDonald <stuartm@connecttech.com>"
#define DRIVER_DESC "USB ConnectTech WhiteHEAT driver"
@@ -78,12 +77,6 @@ static const struct usb_device_id id_table_combined[] = {
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static struct usb_driver whiteheat_driver = {
- .name = "whiteheat",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
-};
/* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
static int whiteheat_firmware_download(struct usb_serial *serial,
@@ -96,10 +89,6 @@ static void whiteheat_release(struct usb_serial *serial);
static int whiteheat_open(struct tty_struct *tty,
struct usb_serial_port *port);
static void whiteheat_close(struct usb_serial_port *port);
-static int whiteheat_write(struct tty_struct *tty,
- struct usb_serial_port *port,
- const unsigned char *buf, int count);
-static int whiteheat_write_room(struct tty_struct *tty);
static int whiteheat_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
static void whiteheat_set_termios(struct tty_struct *tty,
@@ -108,11 +97,6 @@ static int whiteheat_tiocmget(struct tty_struct *tty);
static int whiteheat_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
static void whiteheat_break_ctl(struct tty_struct *tty, int break_state);
-static int whiteheat_chars_in_buffer(struct tty_struct *tty);
-static void whiteheat_throttle(struct tty_struct *tty);
-static void whiteheat_unthrottle(struct tty_struct *tty);
-static void whiteheat_read_callback(struct urb *urb);
-static void whiteheat_write_callback(struct urb *urb);
static struct usb_serial_driver whiteheat_fake_device = {
.driver = {
@@ -138,18 +122,13 @@ static struct usb_serial_driver whiteheat_device = {
.release = whiteheat_release,
.open = whiteheat_open,
.close = whiteheat_close,
- .write = whiteheat_write,
- .write_room = whiteheat_write_room,
.ioctl = whiteheat_ioctl,
.set_termios = whiteheat_set_termios,
.break_ctl = whiteheat_break_ctl,
.tiocmget = whiteheat_tiocmget,
.tiocmset = whiteheat_tiocmset,
- .chars_in_buffer = whiteheat_chars_in_buffer,
- .throttle = whiteheat_throttle,
- .unthrottle = whiteheat_unthrottle,
- .read_bulk_callback = whiteheat_read_callback,
- .write_bulk_callback = whiteheat_write_callback,
+ .throttle = usb_serial_generic_throttle,
+ .unthrottle = usb_serial_generic_unthrottle,
};
static struct usb_serial_driver * const serial_drivers[] = {
@@ -166,29 +145,8 @@ struct whiteheat_command_private {
__u8 result_buffer[64];
};
-
-#define THROTTLED 0x01
-#define ACTUALLY_THROTTLED 0x02
-
-static int urb_pool_size = 8;
-
-struct whiteheat_urb_wrap {
- struct list_head list;
- struct urb *urb;
-};
-
struct whiteheat_private {
- spinlock_t lock;
- __u8 flags;
__u8 mcr; /* FIXME: no locking on mcr */
- struct list_head rx_urbs_free;
- struct list_head rx_urbs_submitted;
- struct list_head rx_urb_q;
- struct work_struct rx_work;
- struct usb_serial_port *port;
- struct list_head tx_urbs_free;
- struct list_head tx_urbs_submitted;
- struct mutex deathwarrant;
};
@@ -198,12 +156,6 @@ static void stop_command_port(struct usb_serial *serial);
static void command_port_write_callback(struct urb *urb);
static void command_port_read_callback(struct urb *urb);
-static int start_port_read(struct usb_serial_port *port);
-static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb,
- struct list_head *head);
-static struct list_head *list_first(struct list_head *head);
-static void rx_data_softint(struct work_struct *work);
-
static int firm_send_command(struct usb_serial_port *port, __u8 command,
__u8 *data, __u8 datasize);
static int firm_open(struct usb_serial_port *port);
@@ -247,8 +199,6 @@ static int whiteheat_firmware_download(struct usb_serial *serial,
const struct firmware *loader_fw = NULL, *firmware_fw = NULL;
const struct ihex_binrec *record;
- dbg("%s", __func__);
-
if (request_ihex_firmware(&firmware_fw, "whiteheat.fw",
&serial->dev->dev)) {
dev_err(&serial->dev->dev,
@@ -349,11 +299,6 @@ static int whiteheat_attach(struct usb_serial *serial)
__u8 *command;
__u8 *result;
int i;
- int j;
- struct urb *urb;
- int buf_size;
- struct whiteheat_urb_wrap *wrap;
- struct list_head *tmp;
command_port = serial->port[COMMAND_PORT];
@@ -408,8 +353,8 @@ static int whiteheat_attach(struct usb_serial *serial)
hw_info = (struct whiteheat_hw_info *)&result[1];
- dev_info(&serial->dev->dev, "%s: Driver %s: Firmware v%d.%02d\n",
- serial->type->description, DRIVER_VERSION,
+ dev_info(&serial->dev->dev, "%s: Firmware v%d.%02d\n",
+ serial->type->description,
hw_info->sw_major_rev, hw_info->sw_minor_rev);
for (i = 0; i < serial->num_ports; i++) {
@@ -423,72 +368,7 @@ static int whiteheat_attach(struct usb_serial *serial)
goto no_private;
}
- spin_lock_init(&info->lock);
- mutex_init(&info->deathwarrant);
- info->flags = 0;
info->mcr = 0;
- INIT_WORK(&info->rx_work, rx_data_softint);
- info->port = port;
-
- INIT_LIST_HEAD(&info->rx_urbs_free);
- INIT_LIST_HEAD(&info->rx_urbs_submitted);
- INIT_LIST_HEAD(&info->rx_urb_q);
- INIT_LIST_HEAD(&info->tx_urbs_free);
- INIT_LIST_HEAD(&info->tx_urbs_submitted);
-
- for (j = 0; j < urb_pool_size; j++) {
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb) {
- dev_err(&port->dev, "No free urbs available\n");
- goto no_rx_urb;
- }
- buf_size = port->read_urb->transfer_buffer_length;
- urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL);
- if (!urb->transfer_buffer) {
- dev_err(&port->dev,
- "Couldn't allocate urb buffer\n");
- goto no_rx_buf;
- }
- wrap = kmalloc(sizeof(*wrap), GFP_KERNEL);
- if (!wrap) {
- dev_err(&port->dev,
- "Couldn't allocate urb wrapper\n");
- goto no_rx_wrap;
- }
- usb_fill_bulk_urb(urb, serial->dev,
- usb_rcvbulkpipe(serial->dev,
- port->bulk_in_endpointAddress),
- urb->transfer_buffer, buf_size,
- whiteheat_read_callback, port);
- wrap->urb = urb;
- list_add(&wrap->list, &info->rx_urbs_free);
-
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb) {
- dev_err(&port->dev, "No free urbs available\n");
- goto no_tx_urb;
- }
- buf_size = port->write_urb->transfer_buffer_length;
- urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL);
- if (!urb->transfer_buffer) {
- dev_err(&port->dev,
- "Couldn't allocate urb buffer\n");
- goto no_tx_buf;
- }
- wrap = kmalloc(sizeof(*wrap), GFP_KERNEL);
- if (!wrap) {
- dev_err(&port->dev,
- "Couldn't allocate urb wrapper\n");
- goto no_tx_wrap;
- }
- usb_fill_bulk_urb(urb, serial->dev,
- usb_sndbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
- urb->transfer_buffer, buf_size,
- whiteheat_write_callback, port);
- wrap->urb = urb;
- list_add(&wrap->list, &info->tx_urbs_free);
- }
usb_set_serial_port_data(port, info);
}
@@ -531,29 +411,6 @@ no_command_private:
for (i = serial->num_ports - 1; i >= 0; i--) {
port = serial->port[i];
info = usb_get_serial_port_data(port);
- for (j = urb_pool_size - 1; j >= 0; j--) {
- tmp = list_first(&info->tx_urbs_free);
- list_del(tmp);
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- kfree(wrap);
-no_tx_wrap:
- kfree(urb->transfer_buffer);
-no_tx_buf:
- usb_free_urb(urb);
-no_tx_urb:
- tmp = list_first(&info->rx_urbs_free);
- list_del(tmp);
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- kfree(wrap);
-no_rx_wrap:
- kfree(urb->transfer_buffer);
-no_rx_buf:
- usb_free_urb(urb);
-no_rx_urb:
- ;
- }
kfree(info);
no_private:
;
@@ -569,56 +426,27 @@ no_command_buffer:
static void whiteheat_release(struct usb_serial *serial)
{
struct usb_serial_port *command_port;
- struct usb_serial_port *port;
struct whiteheat_private *info;
- struct whiteheat_urb_wrap *wrap;
- struct urb *urb;
- struct list_head *tmp;
- struct list_head *tmp2;
int i;
- dbg("%s", __func__);
-
/* free up our private data for our command port */
command_port = serial->port[COMMAND_PORT];
kfree(usb_get_serial_port_data(command_port));
for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- info = usb_get_serial_port_data(port);
- list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) {
- list_del(tmp);
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- kfree(wrap);
- kfree(urb->transfer_buffer);
- usb_free_urb(urb);
- }
- list_for_each_safe(tmp, tmp2, &info->tx_urbs_free) {
- list_del(tmp);
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- kfree(wrap);
- kfree(urb->transfer_buffer);
- usb_free_urb(urb);
- }
+ info = usb_get_serial_port_data(serial->port[i]);
kfree(info);
}
}
static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
{
- int retval = 0;
-
- dbg("%s - port %d", __func__, port->number);
+ int retval;
retval = start_command_port(port->serial);
if (retval)
goto exit;
- if (tty)
- tty->low_latency = 1;
-
/* send an open port command */
retval = firm_open(port);
if (retval) {
@@ -640,144 +468,25 @@ static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
usb_clear_halt(port->serial->dev, port->read_urb->pipe);
usb_clear_halt(port->serial->dev, port->write_urb->pipe);
- /* Start reading from the device */
- retval = start_port_read(port);
+ retval = usb_serial_generic_open(tty, port);
if (retval) {
- dev_err(&port->dev,
- "%s - failed submitting read urb, error %d\n",
- __func__, retval);
firm_close(port);
stop_command_port(port->serial);
goto exit;
}
-
exit:
- dbg("%s - exit, retval = %d", __func__, retval);
return retval;
}
static void whiteheat_close(struct usb_serial_port *port)
{
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- struct whiteheat_urb_wrap *wrap;
- struct urb *urb;
- struct list_head *tmp;
- struct list_head *tmp2;
-
- dbg("%s - port %d", __func__, port->number);
-
firm_report_tx_done(port);
firm_close(port);
- /* shutdown our bulk reads and writes */
- mutex_lock(&info->deathwarrant);
- spin_lock_irq(&info->lock);
- list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- list_del(tmp);
- spin_unlock_irq(&info->lock);
- usb_kill_urb(urb);
- spin_lock_irq(&info->lock);
- list_add(tmp, &info->rx_urbs_free);
- }
- list_for_each_safe(tmp, tmp2, &info->rx_urb_q)
- list_move(tmp, &info->rx_urbs_free);
- list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) {
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- list_del(tmp);
- spin_unlock_irq(&info->lock);
- usb_kill_urb(urb);
- spin_lock_irq(&info->lock);
- list_add(tmp, &info->tx_urbs_free);
- }
- spin_unlock_irq(&info->lock);
- mutex_unlock(&info->deathwarrant);
- stop_command_port(port->serial);
-}
-
-
-static int whiteheat_write(struct tty_struct *tty,
- struct usb_serial_port *port, const unsigned char *buf, int count)
-{
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- struct whiteheat_urb_wrap *wrap;
- struct urb *urb;
- int result;
- int bytes;
- int sent = 0;
- unsigned long flags;
- struct list_head *tmp;
-
- dbg("%s - port %d", __func__, port->number);
-
- if (count == 0) {
- dbg("%s - write request of 0 bytes", __func__);
- return (0);
- }
-
- while (count) {
- spin_lock_irqsave(&info->lock, flags);
- if (list_empty(&info->tx_urbs_free)) {
- spin_unlock_irqrestore(&info->lock, flags);
- break;
- }
- tmp = list_first(&info->tx_urbs_free);
- list_del(tmp);
- spin_unlock_irqrestore(&info->lock, flags);
-
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- bytes = (count > port->bulk_out_size) ?
- port->bulk_out_size : count;
- memcpy(urb->transfer_buffer, buf + sent, bytes);
-
- usb_serial_debug_data(debug, &port->dev,
- __func__, bytes, urb->transfer_buffer);
-
- urb->transfer_buffer_length = bytes;
- result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result) {
- dev_err_console(port,
- "%s - failed submitting write urb, error %d\n",
- __func__, result);
- sent = result;
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->tx_urbs_free);
- spin_unlock_irqrestore(&info->lock, flags);
- break;
- } else {
- sent += bytes;
- count -= bytes;
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->tx_urbs_submitted);
- spin_unlock_irqrestore(&info->lock, flags);
- }
- }
-
- return sent;
-}
-
-static int whiteheat_write_room(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- struct list_head *tmp;
- int room = 0;
- unsigned long flags;
-
- dbg("%s - port %d", __func__, port->number);
+ usb_serial_generic_close(port);
- spin_lock_irqsave(&info->lock, flags);
- list_for_each(tmp, &info->tx_urbs_free)
- room++;
- spin_unlock_irqrestore(&info->lock, flags);
- room *= port->bulk_out_size;
-
- dbg("%s - returns %d", __func__, room);
- return (room);
+ stop_command_port(port->serial);
}
static int whiteheat_tiocmget(struct tty_struct *tty)
@@ -786,8 +495,6 @@ static int whiteheat_tiocmget(struct tty_struct *tty)
struct whiteheat_private *info = usb_get_serial_port_data(port);
unsigned int modem_signals = 0;
- dbg("%s - port %d", __func__, port->number);
-
firm_get_dtr_rts(port);
if (info->mcr & UART_MCR_DTR)
modem_signals |= TIOCM_DTR;
@@ -803,8 +510,6 @@ static int whiteheat_tiocmset(struct tty_struct *tty,
struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
- dbg("%s - port %d", __func__, port->number);
-
if (set & TIOCM_RTS)
info->mcr |= UART_MCR_RTS;
if (set & TIOCM_DTR)
@@ -837,7 +542,7 @@ static int whiteheat_ioctl(struct tty_struct *tty,
serstruct.line = port->serial->minor;
serstruct.port = port->number;
serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
- serstruct.xmit_fifo_size = port->bulk_out_size;
+ serstruct.xmit_fifo_size = kfifo_size(&port->write_fifo);
serstruct.custom_divisor = 0;
serstruct.baud_base = 460800;
serstruct.close_delay = CLOSING_DELAY;
@@ -867,60 +572,6 @@ static void whiteheat_break_ctl(struct tty_struct *tty, int break_state)
}
-static int whiteheat_chars_in_buffer(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- struct list_head *tmp;
- struct whiteheat_urb_wrap *wrap;
- int chars = 0;
- unsigned long flags;
-
- dbg("%s - port %d", __func__, port->number);
-
- spin_lock_irqsave(&info->lock, flags);
- list_for_each(tmp, &info->tx_urbs_submitted) {
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- chars += wrap->urb->transfer_buffer_length;
- }
- spin_unlock_irqrestore(&info->lock, flags);
-
- dbg("%s - returns %d", __func__, chars);
- return chars;
-}
-
-
-static void whiteheat_throttle(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
-
- dbg("%s - port %d", __func__, port->number);
-
- spin_lock_irq(&info->lock);
- info->flags |= THROTTLED;
- spin_unlock_irq(&info->lock);
-}
-
-
-static void whiteheat_unthrottle(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- int actually_throttled;
-
- dbg("%s - port %d", __func__, port->number);
-
- spin_lock_irq(&info->lock);
- actually_throttled = info->flags & ACTUALLY_THROTTLED;
- info->flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
- spin_unlock_irq(&info->lock);
-
- if (actually_throttled)
- rx_data_softint(&info->rx_work);
-}
-
-
/*****************************************************************************
* Connect Tech's White Heat callback routines
*****************************************************************************/
@@ -928,8 +579,6 @@ static void command_port_write_callback(struct urb *urb)
{
int status = urb->status;
- dbg("%s", __func__);
-
if (status) {
dbg("nonzero urb status: %d", status);
return;
@@ -945,8 +594,6 @@ static void command_port_read_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int result;
- dbg("%s", __func__);
-
command_info = usb_get_serial_port_data(command_port);
if (!command_info) {
dbg("%s - command_info is NULL, exiting.", __func__);
@@ -989,80 +636,6 @@ static void command_port_read_callback(struct urb *urb)
}
-static void whiteheat_read_callback(struct urb *urb)
-{
- struct usb_serial_port *port = urb->context;
- struct whiteheat_urb_wrap *wrap;
- unsigned char *data = urb->transfer_buffer;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- int status = urb->status;
-
- dbg("%s - port %d", __func__, port->number);
-
- spin_lock(&info->lock);
- wrap = urb_to_wrap(urb, &info->rx_urbs_submitted);
- if (!wrap) {
- spin_unlock(&info->lock);
- dev_err(&port->dev, "%s - Not my urb!\n", __func__);
- return;
- }
- list_del(&wrap->list);
- spin_unlock(&info->lock);
-
- if (status) {
- dbg("%s - nonzero read bulk status received: %d",
- __func__, status);
- spin_lock(&info->lock);
- list_add(&wrap->list, &info->rx_urbs_free);
- spin_unlock(&info->lock);
- return;
- }
-
- usb_serial_debug_data(debug, &port->dev,
- __func__, urb->actual_length, data);
-
- spin_lock(&info->lock);
- list_add_tail(&wrap->list, &info->rx_urb_q);
- if (info->flags & THROTTLED) {
- info->flags |= ACTUALLY_THROTTLED;
- spin_unlock(&info->lock);
- return;
- }
- spin_unlock(&info->lock);
-
- schedule_work(&info->rx_work);
-}
-
-
-static void whiteheat_write_callback(struct urb *urb)
-{
- struct usb_serial_port *port = urb->context;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- struct whiteheat_urb_wrap *wrap;
- int status = urb->status;
-
- dbg("%s - port %d", __func__, port->number);
-
- spin_lock(&info->lock);
- wrap = urb_to_wrap(urb, &info->tx_urbs_submitted);
- if (!wrap) {
- spin_unlock(&info->lock);
- dev_err(&port->dev, "%s - Not my urb!\n", __func__);
- return;
- }
- list_move(&wrap->list, &info->tx_urbs_free);
- spin_unlock(&info->lock);
-
- if (status) {
- dbg("%s - nonzero write bulk status received: %d",
- __func__, status);
- return;
- }
-
- usb_serial_port_softint(port);
-}
-
-
/*****************************************************************************
* Connect Tech's White Heat firmware interface
*****************************************************************************/
@@ -1337,124 +910,7 @@ static void stop_command_port(struct usb_serial *serial)
mutex_unlock(&command_info->mutex);
}
-
-static int start_port_read(struct usb_serial_port *port)
-{
- struct whiteheat_private *info = usb_get_serial_port_data(port);
- struct whiteheat_urb_wrap *wrap;
- struct urb *urb;
- int retval = 0;
- unsigned long flags;
- struct list_head *tmp;
- struct list_head *tmp2;
-
- spin_lock_irqsave(&info->lock, flags);
-
- list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) {
- list_del(tmp);
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- spin_unlock_irqrestore(&info->lock, flags);
- retval = usb_submit_urb(urb, GFP_KERNEL);
- if (retval) {
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->rx_urbs_free);
- list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
- list_del(tmp);
- spin_unlock_irqrestore(&info->lock, flags);
- usb_kill_urb(urb);
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->rx_urbs_free);
- }
- break;
- }
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->rx_urbs_submitted);
- }
-
- spin_unlock_irqrestore(&info->lock, flags);
-
- return retval;
-}
-
-
-static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb,
- struct list_head *head)
-{
- struct whiteheat_urb_wrap *wrap;
- struct list_head *tmp;
-
- list_for_each(tmp, head) {
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- if (wrap->urb == urb)
- return wrap;
- }
-
- return NULL;
-}
-
-
-static struct list_head *list_first(struct list_head *head)
-{
- return head->next;
-}
-
-
-static void rx_data_softint(struct work_struct *work)
-{
- struct whiteheat_private *info =
- container_of(work, struct whiteheat_private, rx_work);
- struct usb_serial_port *port = info->port;
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- struct whiteheat_urb_wrap *wrap;
- struct urb *urb;
- unsigned long flags;
- struct list_head *tmp;
- struct list_head *tmp2;
- int result;
- int sent = 0;
-
- spin_lock_irqsave(&info->lock, flags);
- if (info->flags & THROTTLED) {
- spin_unlock_irqrestore(&info->lock, flags);
- goto out;
- }
-
- list_for_each_safe(tmp, tmp2, &info->rx_urb_q) {
- list_del(tmp);
- spin_unlock_irqrestore(&info->lock, flags);
-
- wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
- urb = wrap->urb;
-
- if (tty && urb->actual_length)
- sent += tty_insert_flip_string(tty,
- urb->transfer_buffer, urb->actual_length);
-
- result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result) {
- dev_err(&port->dev,
- "%s - failed resubmitting read urb, error %d\n",
- __func__, result);
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->rx_urbs_free);
- continue;
- }
-
- spin_lock_irqsave(&info->lock, flags);
- list_add(tmp, &info->rx_urbs_submitted);
- }
- spin_unlock_irqrestore(&info->lock, flags);
-
- if (sent)
- tty_flip_buffer_push(tty);
-out:
- tty_kref_put(tty);
-}
-
-module_usb_serial_driver(whiteheat_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
@@ -1463,8 +919,5 @@ MODULE_LICENSE("GPL");
MODULE_FIRMWARE("whiteheat.fw");
MODULE_FIRMWARE("whiteheat_loader.fw");
-module_param(urb_pool_size, int, 0);
-MODULE_PARM_DESC(urb_pool_size, "Number of urbs to use for buffering");
-
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/zio.c b/drivers/usb/serial/zio.c
index 9d0bb3752cd4..c043aa84a0ba 100644
--- a/drivers/usb/serial/zio.c
+++ b/drivers/usb/serial/zio.c
@@ -22,13 +22,6 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_driver zio_driver = {
- .name = "zio",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static struct usb_serial_driver zio_device = {
.driver = {
.owner = THIS_MODULE,
@@ -42,5 +35,5 @@ static struct usb_serial_driver * const serial_drivers[] = {
&zio_device, NULL
};
-module_usb_serial_driver(zio_driver, serial_drivers);
+module_usb_serial_driver(serial_drivers, id_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
index e7e678109500..b28f2ad127d4 100644
--- a/drivers/usb/storage/ene_ub6250.c
+++ b/drivers/usb/storage/ene_ub6250.c
@@ -1933,11 +1933,7 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag)
kfree(buf);
nofw:
- if (sd_fw != NULL) {
- release_firmware(sd_fw);
- sd_fw = NULL;
- }
-
+ release_firmware(sd_fw);
return result;
}
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 856ad92c40de..1719886bb9be 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -110,7 +110,7 @@ UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
-/* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
+/* Deduced by Jonathan Woithe <jwoithe@just42.net>
* Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
* always fails and confuses drive.
*/
@@ -1885,6 +1885,13 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Jesse Feddema <jdfeddema@gmail.com> */
+UNUSUAL_DEV( 0x177f, 0x0400, 0x0000, 0x0000,
+ "Yarvik",
+ "PMP400",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ),
+
/* Reported by Hans de Goede <hdegoede@redhat.com>
* These Appotech controllers are found in Picture Frames, they provide a
* (buggy) emulation of a cdrom drive which contains the windows software
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 2653e73db623..e23c30ab66da 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -121,7 +121,7 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");
}
static struct us_unusual_dev us_unusual_dev_list[] = {
-# include "unusual_devs.h"
+# include "unusual_devs.h"
{ } /* Terminating entry */
};
@@ -261,17 +261,17 @@ EXPORT_SYMBOL_GPL(usb_stor_post_reset);
void fill_inquiry_response(struct us_data *us, unsigned char *data,
unsigned int data_len)
{
- if (data_len<36) // You lose.
+ if (data_len < 36) /* You lose. */
return;
memset(data+8, ' ', 28);
- if(data[0]&0x20) { /* USB device currently not connected. Return
+ if (data[0]&0x20) { /* USB device currently not connected. Return
peripheral qualifier 001b ("...however, the
physical device is not currently connected
to this logical unit") and leave vendor and
product identification empty. ("If the target
does store some of the INQUIRY data on the
- device, it may return zeros or ASCII spaces
+ device, it may return zeros or ASCII spaces
(20h) in those fields until the data is
available from the device."). */
} else {
@@ -298,7 +298,7 @@ static int usb_stor_control_thread(void * __us)
struct us_data *us = (struct us_data *)__us;
struct Scsi_Host *host = us_to_host(us);
- for(;;) {
+ for (;;) {
US_DEBUGP("*** thread sleeping.\n");
if (wait_for_completion_interruptible(&us->cmnd_ready))
break;
@@ -327,7 +327,7 @@ static int usb_stor_control_thread(void * __us)
scsi_unlock(host);
- /* reject the command if the direction indicator
+ /* reject the command if the direction indicator
* is UNKNOWN
*/
if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
@@ -338,7 +338,7 @@ static int usb_stor_control_thread(void * __us)
/* reject if target != 0 or if LUN is higher than
* the maximum known LUN
*/
- else if (us->srb->device->id &&
+ else if (us->srb->device->id &&
!(us->fflags & US_FL_SCM_MULT_TARG)) {
US_DEBUGP("Bad target number (%d:%d)\n",
us->srb->device->id, us->srb->device->lun);
@@ -351,7 +351,7 @@ static int usb_stor_control_thread(void * __us)
us->srb->result = DID_BAD_TARGET << 16;
}
- /* Handle those devices which need us to fake
+ /* Handle those devices which need us to fake
* their inquiry data */
else if ((us->srb->cmnd[0] == INQUIRY) &&
(us->fflags & US_FL_FIX_INQUIRY)) {
@@ -376,7 +376,7 @@ static int usb_stor_control_thread(void * __us)
/* indicate that the command is done */
if (us->srb->result != DID_ABORT << 16) {
- US_DEBUGP("scsi cmd done, result=0x%x\n",
+ US_DEBUGP("scsi cmd done, result=0x%x\n",
us->srb->result);
us->srb->scsi_done(us->srb);
} else {
@@ -414,7 +414,7 @@ SkipForAbort:
}
__set_current_state(TASK_RUNNING);
return 0;
-}
+}
/***********************************************************************
* Device probing and disconnecting
@@ -732,7 +732,7 @@ static int get_pipes(struct us_data *us)
us->recv_ctrl_pipe = usb_rcvctrlpipe(us->pusb_dev, 0);
us->send_bulk_pipe = usb_sndbulkpipe(us->pusb_dev,
usb_endpoint_num(ep_out));
- us->recv_bulk_pipe = usb_rcvbulkpipe(us->pusb_dev,
+ us->recv_bulk_pipe = usb_rcvbulkpipe(us->pusb_dev,
usb_endpoint_num(ep_in));
if (ep_int) {
us->recv_intr_pipe = usb_rcvintpipe(us->pusb_dev,
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index b4a71679c933..0616f235bd6b 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -93,8 +93,8 @@ static int skel_open(struct inode *inode, struct file *file)
interface = usb_find_interface(&skel_driver, subminor);
if (!interface) {
- err("%s - error, can't find device for minor %d",
- __func__, subminor);
+ pr_err("%s - error, can't find device for minor %d\n",
+ __func__, subminor);
retval = -ENODEV;
goto exit;
}
@@ -179,8 +179,9 @@ static void skel_read_bulk_callback(struct urb *urb)
if (!(urb->status == -ENOENT ||
urb->status == -ECONNRESET ||
urb->status == -ESHUTDOWN))
- err("%s - nonzero write bulk status received: %d",
- __func__, urb->status);
+ dev_err(&dev->interface->dev,
+ "%s - nonzero write bulk status received: %d\n",
+ __func__, urb->status);
dev->errors = urb->status;
} else {
@@ -213,7 +214,8 @@ static int skel_do_read_io(struct usb_skel *dev, size_t count)
/* do it */
rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL);
if (rv < 0) {
- err("%s - failed submitting read urb, error %d",
+ dev_err(&dev->interface->dev,
+ "%s - failed submitting read urb, error %d\n",
__func__, rv);
dev->bulk_in_filled = 0;
rv = (rv == -ENOMEM) ? rv : -EIO;
@@ -364,8 +366,9 @@ static void skel_write_bulk_callback(struct urb *urb)
if (!(urb->status == -ENOENT ||
urb->status == -ECONNRESET ||
urb->status == -ESHUTDOWN))
- err("%s - nonzero write bulk status received: %d",
- __func__, urb->status);
+ dev_err(&dev->interface->dev,
+ "%s - nonzero write bulk status received: %d\n",
+ __func__, urb->status);
spin_lock(&dev->err_lock);
dev->errors = urb->status;
@@ -459,8 +462,9 @@ static ssize_t skel_write(struct file *file, const char *user_buffer,
retval = usb_submit_urb(urb, GFP_KERNEL);
mutex_unlock(&dev->io_mutex);
if (retval) {
- err("%s - failed submitting write urb, error %d", __func__,
- retval);
+ dev_err(&dev->interface->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, retval);
goto error_unanchor;
}
@@ -519,7 +523,7 @@ static int skel_probe(struct usb_interface *interface,
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
- err("Out of memory");
+ dev_err(&interface->dev, "Out of memory\n");
goto error;
}
kref_init(&dev->kref);
@@ -546,12 +550,14 @@ static int skel_probe(struct usb_interface *interface,
dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!dev->bulk_in_buffer) {
- err("Could not allocate bulk_in_buffer");
+ dev_err(&interface->dev,
+ "Could not allocate bulk_in_buffer\n");
goto error;
}
dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->bulk_in_urb) {
- err("Could not allocate bulk_in_urb");
+ dev_err(&interface->dev,
+ "Could not allocate bulk_in_urb\n");
goto error;
}
}
@@ -563,7 +569,8 @@ static int skel_probe(struct usb_interface *interface,
}
}
if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
- err("Could not find both bulk-in and bulk-out endpoints");
+ dev_err(&interface->dev,
+ "Could not find both bulk-in and bulk-out endpoints\n");
goto error;
}
@@ -574,7 +581,8 @@ static int skel_probe(struct usb_interface *interface,
retval = usb_register_dev(interface, &skel_class);
if (retval) {
/* something prevented us from registering this driver */
- err("Not able to get a minor for this device.");
+ dev_err(&interface->dev,
+ "Not able to get a minor for this device.\n");
usb_set_intfdata(interface, NULL);
goto error;
}
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index ffbce4525468..fe3b6ec87122 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -536,7 +536,7 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
for (page = (unsigned long)fbdev->fb_mem;
page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len);
page += PAGE_SIZE) {
-#if CONFIG_DMA_NONCOHERENT
+#ifdef CONFIG_DMA_NONCOHERENT
SetPageReserved(virt_to_page(CAC_ADDR((void *)page)));
#else
SetPageReserved(virt_to_page(page));
diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
index 99b354b8e257..f994c8b8f10a 100644
--- a/drivers/video/clps711xfb.c
+++ b/drivers/video/clps711xfb.c
@@ -33,7 +33,6 @@
#include <asm/mach-types.h>
#include <linux/uaccess.h>
-#include <asm/hardware/clps7111.h>
#include <mach/syspld.h>
struct fb_info *cfb;
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 4a89f889852d..6c6bc578d0fc 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -45,6 +45,7 @@
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
+#include <linux/pinctrl/consumer.h>
#include <mach/mxsfb.h>
#define REG_SET 4
@@ -756,6 +757,7 @@ static int __devinit mxsfb_probe(struct platform_device *pdev)
struct mxsfb_info *host;
struct fb_info *fb_info;
struct fb_modelist *modelist;
+ struct pinctrl *pinctrl;
int i, ret;
if (!pdata) {
@@ -793,6 +795,12 @@ static int __devinit mxsfb_probe(struct platform_device *pdev)
host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ goto error_getpin;
+ }
+
host->clk = clk_get(&host->pdev->dev, NULL);
if (IS_ERR(host->clk)) {
ret = PTR_ERR(host->clk);
@@ -848,6 +856,7 @@ error_init_fb:
error_pseudo_pallette:
clk_put(host->clk);
error_getclock:
+error_getpin:
iounmap(host->base);
error_ioremap:
framebuffer_release(fb_info);
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 408a9927be92..c3853c92279b 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -10,12 +10,12 @@ config PANEL_GENERIC_DPI
Supports LCD Panel used in TI SDP3430 and EVM boards,
OMAP3517 EVM boards and CM-T35.
-config PANEL_DVI
- tristate "DVI output"
+config PANEL_TFP410
+ tristate "TFP410 DPI-to-DVI chip"
depends on OMAP2_DSS_DPI && I2C
help
- Driver for external monitors, connected via DVI. The driver uses i2c
- to read EDID information from the monitor.
+ Driver for TFP410 DPI-to-DVI chip. The driver uses i2c to read EDID
+ information from the monitor.
config PANEL_LGPHILIPS_LB035Q02
tristate "LG.Philips LB035Q02 LCD Panel"
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index fbfafc6eebb4..58a5176b07b0 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -1,5 +1,5 @@
obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o
-obj-$(CONFIG_PANEL_DVI) += panel-dvi.o
+obj-$(CONFIG_PANEL_TFP410) += panel-tfp410.o
obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 0f21fa5a16ae..b2dd88b48420 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -993,6 +993,15 @@ static int taal_probe(struct omap_dss_device *dssdev)
dev_set_drvdata(&dssdev->dev, td);
+ if (gpio_is_valid(panel_data->reset_gpio)) {
+ r = gpio_request_one(panel_data->reset_gpio, GPIOF_OUT_INIT_LOW,
+ "taal rst");
+ if (r) {
+ dev_err(&dssdev->dev, "failed to request reset gpio\n");
+ goto err_rst_gpio;
+ }
+ }
+
taal_hw_reset(dssdev);
if (panel_data->use_dsi_backlight) {
@@ -1073,6 +1082,9 @@ err_gpio:
if (bldev != NULL)
backlight_device_unregister(bldev);
err_bl:
+ if (gpio_is_valid(panel_data->reset_gpio))
+ gpio_free(panel_data->reset_gpio);
+err_rst_gpio:
destroy_workqueue(td->workqueue);
err_wq:
free_regulators(panel_config->regulators, panel_config->num_regulators);
@@ -1116,15 +1128,25 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
free_regulators(td->panel_config->regulators,
td->panel_config->num_regulators);
+ if (gpio_is_valid(panel_data->reset_gpio))
+ gpio_free(panel_data->reset_gpio);
+
kfree(td);
}
static int taal_power_on(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
u8 id1, id2, id3;
int r;
+ r = omapdss_dsi_configure_pins(dssdev, &panel_data->pin_config);
+ if (r) {
+ dev_err(&dssdev->dev, "failed to configure DSI pins\n");
+ goto err0;
+ };
+
r = omapdss_dsi_display_enable(dssdev);
if (r) {
dev_err(&dssdev->dev, "failed to enable DSI\n");
diff --git a/drivers/video/omap2/displays/panel-dvi.c b/drivers/video/omap2/displays/panel-tfp410.c
index 03eb14af33e0..52637fa8fda8 100644
--- a/drivers/video/omap2/displays/panel-dvi.c
+++ b/drivers/video/omap2/displays/panel-tfp410.c
@@ -1,5 +1,5 @@
/*
- * DVI output support
+ * TFP410 DPI-to-DVI chip
*
* Copyright (C) 2011 Texas Instruments Inc
* Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
@@ -21,11 +21,12 @@
#include <linux/slab.h>
#include <video/omapdss.h>
#include <linux/i2c.h>
+#include <linux/gpio.h>
#include <drm/drm_edid.h>
-#include <video/omap-panel-dvi.h>
+#include <video/omap-panel-tfp410.h>
-static const struct omap_video_timings panel_dvi_default_timings = {
+static const struct omap_video_timings tfp410_default_timings = {
.x_res = 640,
.y_res = 480,
@@ -44,17 +45,19 @@ struct panel_drv_data {
struct omap_dss_device *dssdev;
struct mutex lock;
+
+ int pd_gpio;
};
-static inline struct panel_dvi_platform_data
+static inline struct tfp410_platform_data
*get_pdata(const struct omap_dss_device *dssdev)
{
return dssdev->data;
}
-static int panel_dvi_power_on(struct omap_dss_device *dssdev)
+static int tfp410_power_on(struct omap_dss_device *dssdev)
{
- struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
+ struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
int r;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
@@ -64,57 +67,72 @@ static int panel_dvi_power_on(struct omap_dss_device *dssdev)
if (r)
goto err0;
- if (pdata->platform_enable) {
- r = pdata->platform_enable(dssdev);
- if (r)
- goto err1;
- }
+ if (gpio_is_valid(ddata->pd_gpio))
+ gpio_set_value(ddata->pd_gpio, 1);
return 0;
-err1:
- omapdss_dpi_display_disable(dssdev);
err0:
return r;
}
-static void panel_dvi_power_off(struct omap_dss_device *dssdev)
+static void tfp410_power_off(struct omap_dss_device *dssdev)
{
- struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
+ struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return;
- if (pdata->platform_disable)
- pdata->platform_disable(dssdev);
+ if (gpio_is_valid(ddata->pd_gpio))
+ gpio_set_value(ddata->pd_gpio, 0);
omapdss_dpi_display_disable(dssdev);
}
-static int panel_dvi_probe(struct omap_dss_device *dssdev)
+static int tfp410_probe(struct omap_dss_device *dssdev)
{
+ struct tfp410_platform_data *pdata = get_pdata(dssdev);
struct panel_drv_data *ddata;
+ int r;
ddata = kzalloc(sizeof(*ddata), GFP_KERNEL);
if (!ddata)
return -ENOMEM;
- dssdev->panel.timings = panel_dvi_default_timings;
+ dssdev->panel.timings = tfp410_default_timings;
dssdev->panel.config = OMAP_DSS_LCD_TFT;
ddata->dssdev = dssdev;
mutex_init(&ddata->lock);
+ if (pdata)
+ ddata->pd_gpio = pdata->power_down_gpio;
+ else
+ ddata->pd_gpio = -1;
+
+ if (gpio_is_valid(ddata->pd_gpio)) {
+ r = gpio_request_one(ddata->pd_gpio, GPIOF_OUT_INIT_LOW,
+ "tfp410 pd");
+ if (r) {
+ dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n",
+ ddata->pd_gpio);
+ ddata->pd_gpio = -1;
+ }
+ }
+
dev_set_drvdata(&dssdev->dev, ddata);
return 0;
}
-static void __exit panel_dvi_remove(struct omap_dss_device *dssdev)
+static void __exit tfp410_remove(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
mutex_lock(&ddata->lock);
+ if (gpio_is_valid(ddata->pd_gpio))
+ gpio_free(ddata->pd_gpio);
+
dev_set_drvdata(&dssdev->dev, NULL);
mutex_unlock(&ddata->lock);
@@ -122,14 +140,14 @@ static void __exit panel_dvi_remove(struct omap_dss_device *dssdev)
kfree(ddata);
}
-static int panel_dvi_enable(struct omap_dss_device *dssdev)
+static int tfp410_enable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
int r;
mutex_lock(&ddata->lock);
- r = panel_dvi_power_on(dssdev);
+ r = tfp410_power_on(dssdev);
if (r == 0)
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
@@ -138,26 +156,26 @@ static int panel_dvi_enable(struct omap_dss_device *dssdev)
return r;
}
-static void panel_dvi_disable(struct omap_dss_device *dssdev)
+static void tfp410_disable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
mutex_lock(&ddata->lock);
- panel_dvi_power_off(dssdev);
+ tfp410_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
mutex_unlock(&ddata->lock);
}
-static int panel_dvi_suspend(struct omap_dss_device *dssdev)
+static int tfp410_suspend(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
mutex_lock(&ddata->lock);
- panel_dvi_power_off(dssdev);
+ tfp410_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
@@ -166,14 +184,14 @@ static int panel_dvi_suspend(struct omap_dss_device *dssdev)
return 0;
}
-static int panel_dvi_resume(struct omap_dss_device *dssdev)
+static int tfp410_resume(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
int r;
mutex_lock(&ddata->lock);
- r = panel_dvi_power_on(dssdev);
+ r = tfp410_power_on(dssdev);
if (r == 0)
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
@@ -182,7 +200,7 @@ static int panel_dvi_resume(struct omap_dss_device *dssdev)
return r;
}
-static void panel_dvi_set_timings(struct omap_dss_device *dssdev,
+static void tfp410_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
@@ -192,7 +210,7 @@ static void panel_dvi_set_timings(struct omap_dss_device *dssdev,
mutex_unlock(&ddata->lock);
}
-static void panel_dvi_get_timings(struct omap_dss_device *dssdev,
+static void tfp410_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
@@ -202,7 +220,7 @@ static void panel_dvi_get_timings(struct omap_dss_device *dssdev,
mutex_unlock(&ddata->lock);
}
-static int panel_dvi_check_timings(struct omap_dss_device *dssdev,
+static int tfp410_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
@@ -216,7 +234,7 @@ static int panel_dvi_check_timings(struct omap_dss_device *dssdev,
}
-static int panel_dvi_ddc_read(struct i2c_adapter *adapter,
+static int tfp410_ddc_read(struct i2c_adapter *adapter,
unsigned char *buf, u16 count, u8 offset)
{
int r, retries;
@@ -247,11 +265,11 @@ static int panel_dvi_ddc_read(struct i2c_adapter *adapter,
return r < 0 ? r : -EIO;
}
-static int panel_dvi_read_edid(struct omap_dss_device *dssdev,
+static int tfp410_read_edid(struct omap_dss_device *dssdev,
u8 *edid, int len)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
- struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
+ struct tfp410_platform_data *pdata = get_pdata(dssdev);
struct i2c_adapter *adapter;
int r, l, bytes_read;
@@ -271,7 +289,7 @@ static int panel_dvi_read_edid(struct omap_dss_device *dssdev,
}
l = min(EDID_LENGTH, len);
- r = panel_dvi_ddc_read(adapter, edid, l, 0);
+ r = tfp410_ddc_read(adapter, edid, l, 0);
if (r)
goto err;
@@ -281,7 +299,7 @@ static int panel_dvi_read_edid(struct omap_dss_device *dssdev,
if (len > EDID_LENGTH && edid[0x7e] > 0) {
l = min(EDID_LENGTH, len - EDID_LENGTH);
- r = panel_dvi_ddc_read(adapter, edid + EDID_LENGTH,
+ r = tfp410_ddc_read(adapter, edid + EDID_LENGTH,
l, EDID_LENGTH);
if (r)
goto err;
@@ -298,10 +316,10 @@ err:
return r;
}
-static bool panel_dvi_detect(struct omap_dss_device *dssdev)
+static bool tfp410_detect(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
- struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
+ struct tfp410_platform_data *pdata = get_pdata(dssdev);
struct i2c_adapter *adapter;
unsigned char out;
int r;
@@ -315,7 +333,7 @@ static bool panel_dvi_detect(struct omap_dss_device *dssdev)
if (!adapter)
goto out;
- r = panel_dvi_ddc_read(adapter, &out, 1, 0);
+ r = tfp410_ddc_read(adapter, &out, 1, 0);
mutex_unlock(&ddata->lock);
@@ -326,38 +344,38 @@ out:
return true;
}
-static struct omap_dss_driver panel_dvi_driver = {
- .probe = panel_dvi_probe,
- .remove = __exit_p(panel_dvi_remove),
+static struct omap_dss_driver tfp410_driver = {
+ .probe = tfp410_probe,
+ .remove = __exit_p(tfp410_remove),
- .enable = panel_dvi_enable,
- .disable = panel_dvi_disable,
- .suspend = panel_dvi_suspend,
- .resume = panel_dvi_resume,
+ .enable = tfp410_enable,
+ .disable = tfp410_disable,
+ .suspend = tfp410_suspend,
+ .resume = tfp410_resume,
- .set_timings = panel_dvi_set_timings,
- .get_timings = panel_dvi_get_timings,
- .check_timings = panel_dvi_check_timings,
+ .set_timings = tfp410_set_timings,
+ .get_timings = tfp410_get_timings,
+ .check_timings = tfp410_check_timings,
- .read_edid = panel_dvi_read_edid,
- .detect = panel_dvi_detect,
+ .read_edid = tfp410_read_edid,
+ .detect = tfp410_detect,
.driver = {
- .name = "dvi",
+ .name = "tfp410",
.owner = THIS_MODULE,
},
};
-static int __init panel_dvi_init(void)
+static int __init tfp410_init(void)
{
- return omap_dss_register_driver(&panel_dvi_driver);
+ return omap_dss_register_driver(&tfp410_driver);
}
-static void __exit panel_dvi_exit(void)
+static void __exit tfp410_exit(void)
{
- omap_dss_unregister_driver(&panel_dvi_driver);
+ omap_dss_unregister_driver(&tfp410_driver);
}
-module_init(panel_dvi_init);
-module_exit(panel_dvi_exit);
+module_init(tfp410_init);
+module_exit(tfp410_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 662d14f8c2c3..210a3c4f6150 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -2076,65 +2076,6 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
}
}
-static int dsi_parse_lane_config(struct omap_dss_device *dssdev)
-{
- struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- u8 lanes[DSI_MAX_NR_LANES];
- u8 polarities[DSI_MAX_NR_LANES];
- int num_lanes, i;
-
- static const enum dsi_lane_function functions[] = {
- DSI_LANE_CLK,
- DSI_LANE_DATA1,
- DSI_LANE_DATA2,
- DSI_LANE_DATA3,
- DSI_LANE_DATA4,
- };
-
- lanes[0] = dssdev->phy.dsi.clk_lane;
- lanes[1] = dssdev->phy.dsi.data1_lane;
- lanes[2] = dssdev->phy.dsi.data2_lane;
- lanes[3] = dssdev->phy.dsi.data3_lane;
- lanes[4] = dssdev->phy.dsi.data4_lane;
- polarities[0] = dssdev->phy.dsi.clk_pol;
- polarities[1] = dssdev->phy.dsi.data1_pol;
- polarities[2] = dssdev->phy.dsi.data2_pol;
- polarities[3] = dssdev->phy.dsi.data3_pol;
- polarities[4] = dssdev->phy.dsi.data4_pol;
-
- num_lanes = 0;
-
- for (i = 0; i < dsi->num_lanes_supported; ++i)
- dsi->lanes[i].function = DSI_LANE_UNUSED;
-
- for (i = 0; i < dsi->num_lanes_supported; ++i) {
- int num;
-
- if (lanes[i] == DSI_LANE_UNUSED)
- break;
-
- num = lanes[i] - 1;
-
- if (num >= dsi->num_lanes_supported)
- return -EINVAL;
-
- if (dsi->lanes[num].function != DSI_LANE_UNUSED)
- return -EINVAL;
-
- dsi->lanes[num].function = functions[i];
- dsi->lanes[num].polarity = polarities[i];
- num_lanes++;
- }
-
- if (num_lanes < 2 || num_lanes > dsi->num_lanes_supported)
- return -EINVAL;
-
- dsi->num_lanes_used = num_lanes;
-
- return 0;
-}
-
static int dsi_set_lane_config(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -3975,6 +3916,74 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
}
}
+int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
+ const struct omap_dsi_pin_config *pin_cfg)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ int num_pins;
+ const int *pins;
+ struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
+ int num_lanes;
+ int i;
+
+ static const enum dsi_lane_function functions[] = {
+ DSI_LANE_CLK,
+ DSI_LANE_DATA1,
+ DSI_LANE_DATA2,
+ DSI_LANE_DATA3,
+ DSI_LANE_DATA4,
+ };
+
+ num_pins = pin_cfg->num_pins;
+ pins = pin_cfg->pins;
+
+ if (num_pins < 4 || num_pins > dsi->num_lanes_supported * 2
+ || num_pins % 2 != 0)
+ return -EINVAL;
+
+ for (i = 0; i < DSI_MAX_NR_LANES; ++i)
+ lanes[i].function = DSI_LANE_UNUSED;
+
+ num_lanes = 0;
+
+ for (i = 0; i < num_pins; i += 2) {
+ u8 lane, pol;
+ int dx, dy;
+
+ dx = pins[i];
+ dy = pins[i + 1];
+
+ if (dx < 0 || dx >= dsi->num_lanes_supported * 2)
+ return -EINVAL;
+
+ if (dy < 0 || dy >= dsi->num_lanes_supported * 2)
+ return -EINVAL;
+
+ if (dx & 1) {
+ if (dy != dx - 1)
+ return -EINVAL;
+ pol = 1;
+ } else {
+ if (dy != dx + 1)
+ return -EINVAL;
+ pol = 0;
+ }
+
+ lane = dx / 2;
+
+ lanes[lane].function = functions[i / 2];
+ lanes[lane].polarity = pol;
+ num_lanes++;
+ }
+
+ memcpy(dsi->lanes, lanes, sizeof(dsi->lanes));
+ dsi->num_lanes_used = num_lanes;
+
+ return 0;
+}
+EXPORT_SYMBOL(omapdss_dsi_configure_pins);
+
int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4339,12 +4348,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
int dsi_module = dsi_get_dsidev_id(dsidev);
int r;
- r = dsi_parse_lane_config(dssdev);
- if (r) {
- DSSERR("illegal lane config");
- goto err0;
- }
-
r = dsi_pll_init(dsidev, true, true);
if (r)
goto err0;
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 7a0b301587f6..e672698bd820 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -758,7 +758,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
}
lcdc_write_chan(ch, LDDFR, tmp);
- lcdc_write_chan(ch, LDMLSR, ch->pitch);
+ lcdc_write_chan(ch, LDMLSR, ch->line_size);
lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
if (ch->format->yuv)
lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
@@ -847,6 +847,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
ch->base_addr_y = ch->dma_handle;
ch->base_addr_c = ch->base_addr_y + ch->xres * ch->yres_virtual;
+ ch->line_size = ch->pitch;
/* Enable MERAM if possible. */
if (mdev == NULL || mdev->ops == NULL ||
@@ -882,7 +883,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
meram = mdev->ops->meram_register(mdev, ch->cfg->meram_cfg,
ch->pitch, ch->yres, pixelformat,
- &ch->pitch);
+ &ch->line_size);
if (!IS_ERR(meram)) {
mdev->ops->meram_update(mdev, meram,
ch->base_addr_y, ch->base_addr_c,
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index da1c26e78a57..5c3bddd2cb72 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -84,6 +84,7 @@ struct sh_mobile_lcdc_chan {
unsigned long base_addr_y;
unsigned long base_addr_c;
+ unsigned int line_size;
int (*notify)(struct sh_mobile_lcdc_chan *ch,
enum sh_mobile_lcdc_entity_event event,
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index a159b63e18b9..7af1e8166182 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -1594,7 +1594,7 @@ static int dlfb_usb_probe(struct usb_interface *interface,
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
- err("dlfb_usb_probe: failed alloc of dev struct\n");
+ dev_err(&interface->dev, "dlfb_usb_probe: failed alloc of dev struct\n");
goto error;
}
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 1a61939b85fc..f38b17a86c35 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -46,4 +46,15 @@ config VIRTIO_BALLOON
If unsure, say N.
+config VIRTIO_MMIO_CMDLINE_DEVICES
+ bool "Memory mapped virtio devices parameter parsing"
+ depends on VIRTIO_MMIO
+ ---help---
+ Allow virtio-mmio devices instantiation via the kernel command line
+ or module parameters. Be aware that using incorrect parameters (base
+ address in particular) can crash your system - you have been warned.
+ See Documentation/kernel-parameters.txt for details.
+
+ If unsure, say 'N'.
+
endmenu
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 984c501c258f..f3558070e375 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -2,9 +2,10 @@
#include <linux/spinlock.h>
#include <linux/virtio_config.h>
#include <linux/module.h>
+#include <linux/idr.h>
/* Unique numbering for virtio devices. */
-static unsigned int dev_index;
+static DEFINE_IDA(virtio_index_ida);
static ssize_t device_show(struct device *_d,
struct device_attribute *attr, char *buf)
@@ -193,7 +194,11 @@ int register_virtio_device(struct virtio_device *dev)
dev->dev.bus = &virtio_bus;
/* Assign a unique device index and hence name. */
- dev->index = dev_index++;
+ err = ida_simple_get(&virtio_index_ida, 0, 0, GFP_KERNEL);
+ if (err < 0)
+ goto out;
+
+ dev->index = err;
dev_set_name(&dev->dev, "virtio%u", dev->index);
/* We always start by resetting the device, in case a previous
@@ -208,6 +213,7 @@ int register_virtio_device(struct virtio_device *dev)
/* device_register() causes the bus infrastructure to look for a
* matching driver. */
err = device_register(&dev->dev);
+out:
if (err)
add_status(dev, VIRTIO_CONFIG_S_FAILED);
return err;
@@ -217,6 +223,7 @@ EXPORT_SYMBOL_GPL(register_virtio_device);
void unregister_virtio_device(struct virtio_device *dev)
{
device_unregister(&dev->dev);
+ ida_simple_remove(&virtio_index_ida, dev->index);
}
EXPORT_SYMBOL_GPL(unregister_virtio_device);
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index c2d05a8279fd..bfbc15ca38dd 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -381,20 +381,25 @@ out:
return err;
}
-static void __devexit virtballoon_remove(struct virtio_device *vdev)
+static void remove_common(struct virtio_balloon *vb)
{
- struct virtio_balloon *vb = vdev->priv;
-
- kthread_stop(vb->thread);
-
/* There might be pages left in the balloon: free them. */
while (vb->num_pages)
leak_balloon(vb, vb->num_pages);
+ update_balloon_size(vb);
/* Now we reset the device so we can clean up the queues. */
- vdev->config->reset(vdev);
+ vb->vdev->config->reset(vb->vdev);
- vdev->config->del_vqs(vdev);
+ vb->vdev->config->del_vqs(vb->vdev);
+}
+
+static void __devexit virtballoon_remove(struct virtio_device *vdev)
+{
+ struct virtio_balloon *vb = vdev->priv;
+
+ kthread_stop(vb->thread);
+ remove_common(vb);
kfree(vb);
}
@@ -408,17 +413,11 @@ static int virtballoon_freeze(struct virtio_device *vdev)
* function is called.
*/
- while (vb->num_pages)
- leak_balloon(vb, vb->num_pages);
- update_balloon_size(vb);
-
- /* Ensure we don't get any more requests from the host */
- vdev->config->reset(vdev);
- vdev->config->del_vqs(vdev);
+ remove_common(vb);
return 0;
}
-static int restore_common(struct virtio_device *vdev)
+static int virtballoon_restore(struct virtio_device *vdev)
{
struct virtio_balloon *vb = vdev->priv;
int ret;
@@ -431,11 +430,6 @@ static int restore_common(struct virtio_device *vdev)
update_balloon_size(vb);
return 0;
}
-
-static int virtballoon_restore(struct virtio_device *vdev)
-{
- return restore_common(vdev);
-}
#endif
static unsigned int features[] = {
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 01d6dc250d5c..453db0c403d8 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -6,6 +6,50 @@
* This module allows virtio devices to be used over a virtual, memory mapped
* platform device.
*
+ * The guest device(s) may be instantiated in one of three equivalent ways:
+ *
+ * 1. Static platform device in board's code, eg.:
+ *
+ * static struct platform_device v2m_virtio_device = {
+ * .name = "virtio-mmio",
+ * .id = -1,
+ * .num_resources = 2,
+ * .resource = (struct resource []) {
+ * {
+ * .start = 0x1001e000,
+ * .end = 0x1001e0ff,
+ * .flags = IORESOURCE_MEM,
+ * }, {
+ * .start = 42 + 32,
+ * .end = 42 + 32,
+ * .flags = IORESOURCE_IRQ,
+ * },
+ * }
+ * };
+ *
+ * 2. Device Tree node, eg.:
+ *
+ * virtio_block@1e000 {
+ * compatible = "virtio,mmio";
+ * reg = <0x1e000 0x100>;
+ * interrupts = <42>;
+ * }
+ *
+ * 3. Kernel module (or command line) parameter. Can be used more than once -
+ * one device will be created for each one. Syntax:
+ *
+ * [virtio_mmio.]device=<size>@<baseaddr>:<irq>[:<id>]
+ * where:
+ * <size> := size (can use standard suffixes like K, M or G)
+ * <baseaddr> := physical base address
+ * <irq> := interrupt number (as passed to request_irq())
+ * <id> := (optional) platform device id
+ * eg.:
+ * virtio_mmio.device=0x100@0x100b0000:48 \
+ * virtio_mmio.device=1K@0x1001e000:74
+ *
+ *
+ *
* Registers layout (all 32-bit wide):
*
* offset d. name description
@@ -42,6 +86,8 @@
* See the COPYING file in the top-level directory.
*/
+#define pr_fmt(fmt) "virtio-mmio: " fmt
+
#include <linux/highmem.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -449,6 +495,122 @@ static int __devexit virtio_mmio_remove(struct platform_device *pdev)
+/* Devices list parameter */
+
+#if defined(CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES)
+
+static struct device vm_cmdline_parent = {
+ .init_name = "virtio-mmio-cmdline",
+};
+
+static int vm_cmdline_parent_registered;
+static int vm_cmdline_id;
+
+static int vm_cmdline_set(const char *device,
+ const struct kernel_param *kp)
+{
+ int err;
+ struct resource resources[2] = {};
+ char *str;
+ long long int base;
+ int processed, consumed = 0;
+ struct platform_device *pdev;
+
+ resources[0].flags = IORESOURCE_MEM;
+ resources[1].flags = IORESOURCE_IRQ;
+
+ resources[0].end = memparse(device, &str) - 1;
+
+ processed = sscanf(str, "@%lli:%u%n:%d%n",
+ &base, &resources[1].start, &consumed,
+ &vm_cmdline_id, &consumed);
+
+ if (processed < 2 || processed > 3 || str[consumed])
+ return -EINVAL;
+
+ resources[0].start = base;
+ resources[0].end += base;
+ resources[1].end = resources[1].start;
+
+ if (!vm_cmdline_parent_registered) {
+ err = device_register(&vm_cmdline_parent);
+ if (err) {
+ pr_err("Failed to register parent device!\n");
+ return err;
+ }
+ vm_cmdline_parent_registered = 1;
+ }
+
+ pr_info("Registering device virtio-mmio.%d at 0x%llx-0x%llx, IRQ %d.\n",
+ vm_cmdline_id,
+ (unsigned long long)resources[0].start,
+ (unsigned long long)resources[0].end,
+ (int)resources[1].start);
+
+ pdev = platform_device_register_resndata(&vm_cmdline_parent,
+ "virtio-mmio", vm_cmdline_id++,
+ resources, ARRAY_SIZE(resources), NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+ return 0;
+}
+
+static int vm_cmdline_get_device(struct device *dev, void *data)
+{
+ char *buffer = data;
+ unsigned int len = strlen(buffer);
+ struct platform_device *pdev = to_platform_device(dev);
+
+ snprintf(buffer + len, PAGE_SIZE - len, "0x%llx@0x%llx:%llu:%d\n",
+ pdev->resource[0].end - pdev->resource[0].start + 1ULL,
+ (unsigned long long)pdev->resource[0].start,
+ (unsigned long long)pdev->resource[1].start,
+ pdev->id);
+ return 0;
+}
+
+static int vm_cmdline_get(char *buffer, const struct kernel_param *kp)
+{
+ buffer[0] = '\0';
+ device_for_each_child(&vm_cmdline_parent, buffer,
+ vm_cmdline_get_device);
+ return strlen(buffer) + 1;
+}
+
+static struct kernel_param_ops vm_cmdline_param_ops = {
+ .set = vm_cmdline_set,
+ .get = vm_cmdline_get,
+};
+
+device_param_cb(device, &vm_cmdline_param_ops, NULL, S_IRUSR);
+
+static int vm_unregister_cmdline_device(struct device *dev,
+ void *data)
+{
+ platform_device_unregister(to_platform_device(dev));
+
+ return 0;
+}
+
+static void vm_unregister_cmdline_devices(void)
+{
+ if (vm_cmdline_parent_registered) {
+ device_for_each_child(&vm_cmdline_parent, NULL,
+ vm_unregister_cmdline_device);
+ device_unregister(&vm_cmdline_parent);
+ vm_cmdline_parent_registered = 0;
+ }
+}
+
+#else
+
+static void vm_unregister_cmdline_devices(void)
+{
+}
+
+#endif
+
/* Platform driver */
static struct of_device_id virtio_mmio_match[] = {
@@ -475,6 +637,7 @@ static int __init virtio_mmio_init(void)
static void __exit virtio_mmio_exit(void)
{
platform_driver_unregister(&virtio_mmio_driver);
+ vm_unregister_cmdline_devices();
}
module_init(virtio_mmio_init);
diff --git a/drivers/staging/vme/Kconfig b/drivers/vme/Kconfig
index 6411ae51ed3f..c5c22465a805 100644
--- a/drivers/staging/vme/Kconfig
+++ b/drivers/vme/Kconfig
@@ -10,10 +10,10 @@ menuconfig VME_BUS
if VME_BUS
-source "drivers/staging/vme/bridges/Kconfig"
+source "drivers/vme/bridges/Kconfig"
-source "drivers/staging/vme/devices/Kconfig"
+source "drivers/vme/boards/Kconfig"
-source "drivers/staging/vme/boards/Kconfig"
+source "drivers/staging/vme/devices/Kconfig"
endif # VME
diff --git a/drivers/vme/Makefile b/drivers/vme/Makefile
new file mode 100644
index 000000000000..d7bfcb9fd5a1
--- /dev/null
+++ b/drivers/vme/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the VME bridge device drivers.
+#
+obj-$(CONFIG_VME_BUS) += vme.o
+
+obj-y += bridges/
+obj-y += boards/
diff --git a/drivers/staging/vme/boards/Kconfig b/drivers/vme/boards/Kconfig
index 761631353527..761631353527 100644
--- a/drivers/staging/vme/boards/Kconfig
+++ b/drivers/vme/boards/Kconfig
diff --git a/drivers/staging/vme/boards/Makefile b/drivers/vme/boards/Makefile
index 43658340885d..43658340885d 100644
--- a/drivers/staging/vme/boards/Makefile
+++ b/drivers/vme/boards/Makefile
diff --git a/drivers/staging/vme/boards/vme_vmivme7805.c b/drivers/vme/boards/vme_vmivme7805.c
index 8e05bb4e135a..8e05bb4e135a 100644
--- a/drivers/staging/vme/boards/vme_vmivme7805.c
+++ b/drivers/vme/boards/vme_vmivme7805.c
diff --git a/drivers/staging/vme/boards/vme_vmivme7805.h b/drivers/vme/boards/vme_vmivme7805.h
index 44c2c449808c..44c2c449808c 100644
--- a/drivers/staging/vme/boards/vme_vmivme7805.h
+++ b/drivers/vme/boards/vme_vmivme7805.h
diff --git a/drivers/staging/vme/bridges/Kconfig b/drivers/vme/bridges/Kconfig
index 9331064e0476..9331064e0476 100644
--- a/drivers/staging/vme/bridges/Kconfig
+++ b/drivers/vme/bridges/Kconfig
diff --git a/drivers/staging/vme/bridges/Makefile b/drivers/vme/bridges/Makefile
index 59638afcd502..59638afcd502 100644
--- a/drivers/staging/vme/bridges/Makefile
+++ b/drivers/vme/bridges/Makefile
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c
index 515b8b8e32a8..e0df92ec44bd 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.c
+++ b/drivers/vme/bridges/vme_ca91cx42.c
@@ -29,8 +29,8 @@
#include <linux/time.h>
#include <linux/io.h>
#include <linux/uaccess.h>
+#include <linux/vme.h>
-#include "../vme.h"
#include "../vme_bridge.h"
#include "vme_ca91cx42.h"
@@ -1501,7 +1501,7 @@ static int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge)
}
-void *ca91cx42_alloc_consistent(struct device *parent, size_t size,
+static void *ca91cx42_alloc_consistent(struct device *parent, size_t size,
dma_addr_t *dma)
{
struct pci_dev *pdev;
@@ -1512,8 +1512,8 @@ void *ca91cx42_alloc_consistent(struct device *parent, size_t size,
return pci_alloc_consistent(pdev, size, dma);
}
-void ca91cx42_free_consistent(struct device *parent, size_t size, void *vaddr,
- dma_addr_t dma)
+static void ca91cx42_free_consistent(struct device *parent, size_t size,
+ void *vaddr, dma_addr_t dma)
{
struct pci_dev *pdev;
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.h b/drivers/vme/bridges/vme_ca91cx42.h
index 02a7c794db05..02a7c794db05 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.h
+++ b/drivers/vme/bridges/vme_ca91cx42.h
diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c
index f50582169b24..f6385f7a66d9 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.c
+++ b/drivers/vme/bridges/vme_tsi148.c
@@ -29,8 +29,9 @@
#include <linux/time.h>
#include <linux/io.h>
#include <linux/uaccess.h>
+#include <linux/byteorder/generic.h>
+#include <linux/vme.h>
-#include "../vme.h"
#include "../vme_bridge.h"
#include "vme_tsi148.h"
@@ -1415,51 +1416,55 @@ static unsigned int tsi148_master_rmw(struct vme_master_resource *image,
return result;
}
-static int tsi148_dma_set_vme_src_attributes(struct device *dev, u32 *attr,
+static int tsi148_dma_set_vme_src_attributes(struct device *dev, __be32 *attr,
u32 aspace, u32 cycle, u32 dwidth)
{
+ u32 val;
+
+ val = be32_to_cpu(*attr);
+
/* Setup 2eSST speeds */
switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
case VME_2eSST160:
- *attr |= TSI148_LCSR_DSAT_2eSSTM_160;
+ val |= TSI148_LCSR_DSAT_2eSSTM_160;
break;
case VME_2eSST267:
- *attr |= TSI148_LCSR_DSAT_2eSSTM_267;
+ val |= TSI148_LCSR_DSAT_2eSSTM_267;
break;
case VME_2eSST320:
- *attr |= TSI148_LCSR_DSAT_2eSSTM_320;
+ val |= TSI148_LCSR_DSAT_2eSSTM_320;
break;
}
/* Setup cycle types */
if (cycle & VME_SCT)
- *attr |= TSI148_LCSR_DSAT_TM_SCT;
+ val |= TSI148_LCSR_DSAT_TM_SCT;
if (cycle & VME_BLT)
- *attr |= TSI148_LCSR_DSAT_TM_BLT;
+ val |= TSI148_LCSR_DSAT_TM_BLT;
if (cycle & VME_MBLT)
- *attr |= TSI148_LCSR_DSAT_TM_MBLT;
+ val |= TSI148_LCSR_DSAT_TM_MBLT;
if (cycle & VME_2eVME)
- *attr |= TSI148_LCSR_DSAT_TM_2eVME;
+ val |= TSI148_LCSR_DSAT_TM_2eVME;
if (cycle & VME_2eSST)
- *attr |= TSI148_LCSR_DSAT_TM_2eSST;
+ val |= TSI148_LCSR_DSAT_TM_2eSST;
if (cycle & VME_2eSSTB) {
dev_err(dev, "Currently not setting Broadcast Select "
"Registers\n");
- *attr |= TSI148_LCSR_DSAT_TM_2eSSTB;
+ val |= TSI148_LCSR_DSAT_TM_2eSSTB;
}
/* Setup data width */
switch (dwidth) {
case VME_D16:
- *attr |= TSI148_LCSR_DSAT_DBW_16;
+ val |= TSI148_LCSR_DSAT_DBW_16;
break;
case VME_D32:
- *attr |= TSI148_LCSR_DSAT_DBW_32;
+ val |= TSI148_LCSR_DSAT_DBW_32;
break;
default:
dev_err(dev, "Invalid data width\n");
@@ -1469,31 +1474,31 @@ static int tsi148_dma_set_vme_src_attributes(struct device *dev, u32 *attr,
/* Setup address space */
switch (aspace) {
case VME_A16:
- *attr |= TSI148_LCSR_DSAT_AMODE_A16;
+ val |= TSI148_LCSR_DSAT_AMODE_A16;
break;
case VME_A24:
- *attr |= TSI148_LCSR_DSAT_AMODE_A24;
+ val |= TSI148_LCSR_DSAT_AMODE_A24;
break;
case VME_A32:
- *attr |= TSI148_LCSR_DSAT_AMODE_A32;
+ val |= TSI148_LCSR_DSAT_AMODE_A32;
break;
case VME_A64:
- *attr |= TSI148_LCSR_DSAT_AMODE_A64;
+ val |= TSI148_LCSR_DSAT_AMODE_A64;
break;
case VME_CRCSR:
- *attr |= TSI148_LCSR_DSAT_AMODE_CRCSR;
+ val |= TSI148_LCSR_DSAT_AMODE_CRCSR;
break;
case VME_USER1:
- *attr |= TSI148_LCSR_DSAT_AMODE_USER1;
+ val |= TSI148_LCSR_DSAT_AMODE_USER1;
break;
case VME_USER2:
- *attr |= TSI148_LCSR_DSAT_AMODE_USER2;
+ val |= TSI148_LCSR_DSAT_AMODE_USER2;
break;
case VME_USER3:
- *attr |= TSI148_LCSR_DSAT_AMODE_USER3;
+ val |= TSI148_LCSR_DSAT_AMODE_USER3;
break;
case VME_USER4:
- *attr |= TSI148_LCSR_DSAT_AMODE_USER4;
+ val |= TSI148_LCSR_DSAT_AMODE_USER4;
break;
default:
dev_err(dev, "Invalid address space\n");
@@ -1502,58 +1507,64 @@ static int tsi148_dma_set_vme_src_attributes(struct device *dev, u32 *attr,
}
if (cycle & VME_SUPER)
- *attr |= TSI148_LCSR_DSAT_SUP;
+ val |= TSI148_LCSR_DSAT_SUP;
if (cycle & VME_PROG)
- *attr |= TSI148_LCSR_DSAT_PGM;
+ val |= TSI148_LCSR_DSAT_PGM;
+
+ *attr = cpu_to_be32(val);
return 0;
}
-static int tsi148_dma_set_vme_dest_attributes(struct device *dev, u32 *attr,
+static int tsi148_dma_set_vme_dest_attributes(struct device *dev, __be32 *attr,
u32 aspace, u32 cycle, u32 dwidth)
{
+ u32 val;
+
+ val = be32_to_cpu(*attr);
+
/* Setup 2eSST speeds */
switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
case VME_2eSST160:
- *attr |= TSI148_LCSR_DDAT_2eSSTM_160;
+ val |= TSI148_LCSR_DDAT_2eSSTM_160;
break;
case VME_2eSST267:
- *attr |= TSI148_LCSR_DDAT_2eSSTM_267;
+ val |= TSI148_LCSR_DDAT_2eSSTM_267;
break;
case VME_2eSST320:
- *attr |= TSI148_LCSR_DDAT_2eSSTM_320;
+ val |= TSI148_LCSR_DDAT_2eSSTM_320;
break;
}
/* Setup cycle types */
if (cycle & VME_SCT)
- *attr |= TSI148_LCSR_DDAT_TM_SCT;
+ val |= TSI148_LCSR_DDAT_TM_SCT;
if (cycle & VME_BLT)
- *attr |= TSI148_LCSR_DDAT_TM_BLT;
+ val |= TSI148_LCSR_DDAT_TM_BLT;
if (cycle & VME_MBLT)
- *attr |= TSI148_LCSR_DDAT_TM_MBLT;
+ val |= TSI148_LCSR_DDAT_TM_MBLT;
if (cycle & VME_2eVME)
- *attr |= TSI148_LCSR_DDAT_TM_2eVME;
+ val |= TSI148_LCSR_DDAT_TM_2eVME;
if (cycle & VME_2eSST)
- *attr |= TSI148_LCSR_DDAT_TM_2eSST;
+ val |= TSI148_LCSR_DDAT_TM_2eSST;
if (cycle & VME_2eSSTB) {
dev_err(dev, "Currently not setting Broadcast Select "
"Registers\n");
- *attr |= TSI148_LCSR_DDAT_TM_2eSSTB;
+ val |= TSI148_LCSR_DDAT_TM_2eSSTB;
}
/* Setup data width */
switch (dwidth) {
case VME_D16:
- *attr |= TSI148_LCSR_DDAT_DBW_16;
+ val |= TSI148_LCSR_DDAT_DBW_16;
break;
case VME_D32:
- *attr |= TSI148_LCSR_DDAT_DBW_32;
+ val |= TSI148_LCSR_DDAT_DBW_32;
break;
default:
dev_err(dev, "Invalid data width\n");
@@ -1563,31 +1574,31 @@ static int tsi148_dma_set_vme_dest_attributes(struct device *dev, u32 *attr,
/* Setup address space */
switch (aspace) {
case VME_A16:
- *attr |= TSI148_LCSR_DDAT_AMODE_A16;
+ val |= TSI148_LCSR_DDAT_AMODE_A16;
break;
case VME_A24:
- *attr |= TSI148_LCSR_DDAT_AMODE_A24;
+ val |= TSI148_LCSR_DDAT_AMODE_A24;
break;
case VME_A32:
- *attr |= TSI148_LCSR_DDAT_AMODE_A32;
+ val |= TSI148_LCSR_DDAT_AMODE_A32;
break;
case VME_A64:
- *attr |= TSI148_LCSR_DDAT_AMODE_A64;
+ val |= TSI148_LCSR_DDAT_AMODE_A64;
break;
case VME_CRCSR:
- *attr |= TSI148_LCSR_DDAT_AMODE_CRCSR;
+ val |= TSI148_LCSR_DDAT_AMODE_CRCSR;
break;
case VME_USER1:
- *attr |= TSI148_LCSR_DDAT_AMODE_USER1;
+ val |= TSI148_LCSR_DDAT_AMODE_USER1;
break;
case VME_USER2:
- *attr |= TSI148_LCSR_DDAT_AMODE_USER2;
+ val |= TSI148_LCSR_DDAT_AMODE_USER2;
break;
case VME_USER3:
- *attr |= TSI148_LCSR_DDAT_AMODE_USER3;
+ val |= TSI148_LCSR_DDAT_AMODE_USER3;
break;
case VME_USER4:
- *attr |= TSI148_LCSR_DDAT_AMODE_USER4;
+ val |= TSI148_LCSR_DDAT_AMODE_USER4;
break;
default:
dev_err(dev, "Invalid address space\n");
@@ -1596,25 +1607,28 @@ static int tsi148_dma_set_vme_dest_attributes(struct device *dev, u32 *attr,
}
if (cycle & VME_SUPER)
- *attr |= TSI148_LCSR_DDAT_SUP;
+ val |= TSI148_LCSR_DDAT_SUP;
if (cycle & VME_PROG)
- *attr |= TSI148_LCSR_DDAT_PGM;
+ val |= TSI148_LCSR_DDAT_PGM;
+
+ *attr = cpu_to_be32(val);
return 0;
}
/*
* Add a link list descriptor to the list
+ *
+ * Note: DMA engine expects the DMA descriptor to be big endian.
*/
static int tsi148_dma_list_add(struct vme_dma_list *list,
struct vme_dma_attr *src, struct vme_dma_attr *dest, size_t count)
{
struct tsi148_dma_entry *entry, *prev;
- u32 address_high, address_low;
+ u32 address_high, address_low, val;
struct vme_dma_pattern *pattern_attr;
struct vme_dma_pci *pci_attr;
struct vme_dma_vme *vme_attr;
- dma_addr_t desc_ptr;
int retval = 0;
struct vme_bridge *tsi148_bridge;
@@ -1648,34 +1662,36 @@ static int tsi148_dma_list_add(struct vme_dma_list *list,
case VME_DMA_PATTERN:
pattern_attr = src->private;
- entry->descriptor.dsal = pattern_attr->pattern;
- entry->descriptor.dsat = TSI148_LCSR_DSAT_TYP_PAT;
+ entry->descriptor.dsal = cpu_to_be32(pattern_attr->pattern);
+
+ val = TSI148_LCSR_DSAT_TYP_PAT;
+
/* Default behaviour is 32 bit pattern */
if (pattern_attr->type & VME_DMA_PATTERN_BYTE)
- entry->descriptor.dsat |= TSI148_LCSR_DSAT_PSZ;
+ val |= TSI148_LCSR_DSAT_PSZ;
/* It seems that the default behaviour is to increment */
if ((pattern_attr->type & VME_DMA_PATTERN_INCREMENT) == 0)
- entry->descriptor.dsat |= TSI148_LCSR_DSAT_NIN;
-
+ val |= TSI148_LCSR_DSAT_NIN;
+ entry->descriptor.dsat = cpu_to_be32(val);
break;
case VME_DMA_PCI:
pci_attr = src->private;
reg_split((unsigned long long)pci_attr->address, &address_high,
&address_low);
- entry->descriptor.dsau = address_high;
- entry->descriptor.dsal = address_low;
- entry->descriptor.dsat = TSI148_LCSR_DSAT_TYP_PCI;
+ entry->descriptor.dsau = cpu_to_be32(address_high);
+ entry->descriptor.dsal = cpu_to_be32(address_low);
+ entry->descriptor.dsat = cpu_to_be32(TSI148_LCSR_DSAT_TYP_PCI);
break;
case VME_DMA_VME:
vme_attr = src->private;
reg_split((unsigned long long)vme_attr->address, &address_high,
&address_low);
- entry->descriptor.dsau = address_high;
- entry->descriptor.dsal = address_low;
- entry->descriptor.dsat = TSI148_LCSR_DSAT_TYP_VME;
+ entry->descriptor.dsau = cpu_to_be32(address_high);
+ entry->descriptor.dsal = cpu_to_be32(address_low);
+ entry->descriptor.dsat = cpu_to_be32(TSI148_LCSR_DSAT_TYP_VME);
retval = tsi148_dma_set_vme_src_attributes(
tsi148_bridge->parent, &entry->descriptor.dsat,
@@ -1691,9 +1707,8 @@ static int tsi148_dma_list_add(struct vme_dma_list *list,
}
/* Assume last link - this will be over-written by adding another */
- entry->descriptor.dnlau = 0;
- entry->descriptor.dnlal = TSI148_LCSR_DNLAL_LLA;
-
+ entry->descriptor.dnlau = cpu_to_be32(0);
+ entry->descriptor.dnlal = cpu_to_be32(TSI148_LCSR_DNLAL_LLA);
/* Fill out destination part */
switch (dest->type) {
@@ -1702,18 +1717,18 @@ static int tsi148_dma_list_add(struct vme_dma_list *list,
reg_split((unsigned long long)pci_attr->address, &address_high,
&address_low);
- entry->descriptor.ddau = address_high;
- entry->descriptor.ddal = address_low;
- entry->descriptor.ddat = TSI148_LCSR_DDAT_TYP_PCI;
+ entry->descriptor.ddau = cpu_to_be32(address_high);
+ entry->descriptor.ddal = cpu_to_be32(address_low);
+ entry->descriptor.ddat = cpu_to_be32(TSI148_LCSR_DDAT_TYP_PCI);
break;
case VME_DMA_VME:
vme_attr = dest->private;
reg_split((unsigned long long)vme_attr->address, &address_high,
&address_low);
- entry->descriptor.ddau = address_high;
- entry->descriptor.ddal = address_low;
- entry->descriptor.ddat = TSI148_LCSR_DDAT_TYP_VME;
+ entry->descriptor.ddau = cpu_to_be32(address_high);
+ entry->descriptor.ddal = cpu_to_be32(address_low);
+ entry->descriptor.ddat = cpu_to_be32(TSI148_LCSR_DDAT_TYP_VME);
retval = tsi148_dma_set_vme_dest_attributes(
tsi148_bridge->parent, &entry->descriptor.ddat,
@@ -1729,7 +1744,7 @@ static int tsi148_dma_list_add(struct vme_dma_list *list,
}
/* Fill out count */
- entry->descriptor.dcnt = (u32)count;
+ entry->descriptor.dcnt = cpu_to_be32((u32)count);
/* Add to list */
list_add_tail(&entry->list, &list->entries);
@@ -1739,9 +1754,15 @@ static int tsi148_dma_list_add(struct vme_dma_list *list,
prev = list_entry(entry->list.prev, struct tsi148_dma_entry,
list);
/* We need the bus address for the pointer */
- desc_ptr = virt_to_bus(&entry->descriptor);
- reg_split(desc_ptr, &prev->descriptor.dnlau,
- &prev->descriptor.dnlal);
+ entry->dma_handle = dma_map_single(tsi148_bridge->parent,
+ &entry->descriptor,
+ sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE);
+
+ reg_split((unsigned long long)entry->dma_handle, &address_high,
+ &address_low);
+ entry->descriptor.dnlau = cpu_to_be32(address_high);
+ entry->descriptor.dnlal = cpu_to_be32(address_low);
+
}
return 0;
@@ -1784,7 +1805,6 @@ static int tsi148_dma_list_exec(struct vme_dma_list *list)
struct vme_dma_resource *ctrlr;
int channel, retval = 0;
struct tsi148_dma_entry *entry;
- dma_addr_t bus_addr;
u32 bus_addr_high, bus_addr_low;
u32 val, dctlreg = 0;
struct vme_bridge *tsi148_bridge;
@@ -1817,23 +1837,29 @@ static int tsi148_dma_list_exec(struct vme_dma_list *list)
entry = list_first_entry(&list->entries, struct tsi148_dma_entry,
list);
- bus_addr = virt_to_bus(&entry->descriptor);
+ entry->dma_handle = dma_map_single(tsi148_bridge->parent,
+ &entry->descriptor,
+ sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE);
mutex_unlock(&ctrlr->mtx);
- reg_split(bus_addr, &bus_addr_high, &bus_addr_low);
+ reg_split(entry->dma_handle, &bus_addr_high, &bus_addr_low);
iowrite32be(bus_addr_high, bridge->base +
TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAU);
iowrite32be(bus_addr_low, bridge->base +
TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAL);
+ dctlreg = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] +
+ TSI148_LCSR_OFFSET_DCTL);
+
/* Start the operation */
iowrite32be(dctlreg | TSI148_LCSR_DCTL_DGO, bridge->base +
TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL);
wait_event_interruptible(bridge->dma_queue[channel],
tsi148_dma_busy(ctrlr->parent, channel));
+
/*
* Read status register, this register is valid until we kick off a
* new transfer.
@@ -1864,10 +1890,15 @@ static int tsi148_dma_list_empty(struct vme_dma_list *list)
struct list_head *pos, *temp;
struct tsi148_dma_entry *entry;
+ struct vme_bridge *tsi148_bridge = list->parent->parent;
+
/* detach and free each entry */
list_for_each_safe(pos, temp, &list->entries) {
list_del(pos);
entry = list_entry(pos, struct tsi148_dma_entry, list);
+
+ dma_unmap_single(tsi148_bridge->parent, entry->dma_handle,
+ sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE);
kfree(entry);
}
@@ -2110,7 +2141,7 @@ static int tsi148_slot_get(struct vme_bridge *tsi148_bridge)
return (int)slot;
}
-void *tsi148_alloc_consistent(struct device *parent, size_t size,
+static void *tsi148_alloc_consistent(struct device *parent, size_t size,
dma_addr_t *dma)
{
struct pci_dev *pdev;
@@ -2121,8 +2152,8 @@ void *tsi148_alloc_consistent(struct device *parent, size_t size,
return pci_alloc_consistent(pdev, size, dma);
}
-void tsi148_free_consistent(struct device *parent, size_t size, void *vaddr,
- dma_addr_t dma)
+static void tsi148_free_consistent(struct device *parent, size_t size,
+ void *vaddr, dma_addr_t dma)
{
struct pci_dev *pdev;
diff --git a/drivers/staging/vme/bridges/vme_tsi148.h b/drivers/vme/bridges/vme_tsi148.h
index a3ac2fe98816..f5ed14382a8d 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.h
+++ b/drivers/vme/bridges/vme_tsi148.h
@@ -56,16 +56,16 @@ struct tsi148_driver {
* correctly laid out - It must also be aligned on 64-bit boundaries.
*/
struct tsi148_dma_descriptor {
- u32 dsau; /* Source Address */
- u32 dsal;
- u32 ddau; /* Destination Address */
- u32 ddal;
- u32 dsat; /* Source attributes */
- u32 ddat; /* Destination attributes */
- u32 dnlau; /* Next link address */
- u32 dnlal;
- u32 dcnt; /* Byte count */
- u32 ddbs; /* 2eSST Broadcast select */
+ __be32 dsau; /* Source Address */
+ __be32 dsal;
+ __be32 ddau; /* Destination Address */
+ __be32 ddal;
+ __be32 dsat; /* Source attributes */
+ __be32 ddat; /* Destination attributes */
+ __be32 dnlau; /* Next link address */
+ __be32 dnlal;
+ __be32 dcnt; /* Byte count */
+ __be32 ddbs; /* 2eSST Broadcast select */
};
struct tsi148_dma_entry {
@@ -75,6 +75,7 @@ struct tsi148_dma_entry {
*/
struct tsi148_dma_descriptor descriptor;
struct list_head list;
+ dma_addr_t dma_handle;
};
/*
diff --git a/drivers/staging/vme/vme.c b/drivers/vme/vme.c
index 70722ae52321..95a9f71d793e 100644
--- a/drivers/staging/vme/vme.c
+++ b/drivers/vme/vme.c
@@ -30,8 +30,8 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
+#include <linux/vme.h>
-#include "vme.h"
#include "vme_bridge.h"
/* Bitmask and list of registered buses both protected by common mutex */
@@ -98,14 +98,13 @@ void *vme_alloc_consistent(struct vme_resource *resource, size_t size,
}
if (bridge->parent == NULL) {
- printk(KERN_ERR "Dev entry NULL for"
- " bridge %s\n", bridge->name);
+ printk(KERN_ERR "Dev entry NULL for bridge %s\n", bridge->name);
return NULL;
}
if (bridge->alloc_consistent == NULL) {
- printk(KERN_ERR "alloc_consistent not supported by"
- " bridge %s\n", bridge->name);
+ printk(KERN_ERR "alloc_consistent not supported by bridge %s\n",
+ bridge->name);
return NULL;
}
@@ -133,14 +132,13 @@ void vme_free_consistent(struct vme_resource *resource, size_t size,
}
if (bridge->parent == NULL) {
- printk(KERN_ERR "Dev entry NULL for"
- " bridge %s\n", bridge->name);
+ printk(KERN_ERR "Dev entry NULL for bridge %s\n", bridge->name);
return;
}
if (bridge->free_consistent == NULL) {
- printk(KERN_ERR "free_consistent not supported by"
- " bridge %s\n", bridge->name);
+ printk(KERN_ERR "free_consistent not supported by bridge %s\n",
+ bridge->name);
return;
}
@@ -747,15 +745,13 @@ struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type)
attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL);
if (attributes == NULL) {
- printk(KERN_ERR "Unable to allocate memory for attributes "
- "structure\n");
+ printk(KERN_ERR "Unable to allocate memory for attributes structure\n");
goto err_attr;
}
pattern_attr = kmalloc(sizeof(struct vme_dma_pattern), GFP_KERNEL);
if (pattern_attr == NULL) {
- printk(KERN_ERR "Unable to allocate memory for pattern "
- "attributes\n");
+ printk(KERN_ERR "Unable to allocate memory for pattern attributes\n");
goto err_pat;
}
@@ -786,15 +782,13 @@ struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t address)
attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL);
if (attributes == NULL) {
- printk(KERN_ERR "Unable to allocate memory for attributes "
- "structure\n");
+ printk(KERN_ERR "Unable to allocate memory for attributes structure\n");
goto err_attr;
}
pci_attr = kmalloc(sizeof(struct vme_dma_pci), GFP_KERNEL);
if (pci_attr == NULL) {
- printk(KERN_ERR "Unable to allocate memory for pci "
- "attributes\n");
+ printk(KERN_ERR "Unable to allocate memory for pci attributes\n");
goto err_pci;
}
@@ -826,15 +820,13 @@ struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long address,
attributes = kmalloc(
sizeof(struct vme_dma_attr), GFP_KERNEL);
if (attributes == NULL) {
- printk(KERN_ERR "Unable to allocate memory for attributes "
- "structure\n");
+ printk(KERN_ERR "Unable to allocate memory for attributes structure\n");
goto err_attr;
}
vme_attr = kmalloc(sizeof(struct vme_dma_vme), GFP_KERNEL);
if (vme_attr == NULL) {
- printk(KERN_ERR "Unable to allocate memory for vme "
- "attributes\n");
+ printk(KERN_ERR "Unable to allocate memory for vme attributes\n");
goto err_vme;
}
@@ -982,8 +974,8 @@ void vme_irq_handler(struct vme_bridge *bridge, int level, int statid)
if (call != NULL)
call(level, statid, priv_data);
else
- printk(KERN_WARNING "Spurilous VME interrupt, level:%x, "
- "vector:%x\n", level, statid);
+ printk(KERN_WARNING "Spurilous VME interrupt, level:%x, vector:%x\n",
+ level, statid);
}
EXPORT_SYMBOL(vme_irq_handler);
@@ -1112,8 +1104,7 @@ struct vme_resource *vme_lm_request(struct vme_dev *vdev)
struct vme_lm_resource, list);
if (lm == NULL) {
- printk(KERN_ERR "Registered NULL Location Monitor "
- "resource\n");
+ printk(KERN_ERR "Registered NULL Location Monitor resource\n");
continue;
}
diff --git a/drivers/staging/vme/vme_bridge.h b/drivers/vme/vme_bridge.h
index 934949abd745..934949abd745 100644
--- a/drivers/staging/vme/vme_bridge.h
+++ b/drivers/vme/vme_bridge.h
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index fd2c7bd9dfbe..6743bde038cc 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -16,7 +16,7 @@ config W1_CON
depends on CONNECTOR
bool "Userspace communication over connector"
default y
- --- help ---
+ ---help---
This allows to communicate with userspace using connector. For more
information see <file:Documentation/connector/connector.txt>.
There are three types of messages between w1 core and userspace:
diff --git a/drivers/w1/slaves/w1_ds2408.c b/drivers/w1/slaves/w1_ds2408.c
index 7c8cdb8aed26..8e813eed0f0a 100644
--- a/drivers/w1/slaves/w1_ds2408.c
+++ b/drivers/w1/slaves/w1_ds2408.c
@@ -332,7 +332,6 @@ static struct bin_attribute w1_f29_sysfs_bin_files[NB_SYSFS_BIN_FILES] = {
},
.size = 1,
.read = w1_f29_read_cond_search_mask,
- .write = 0,
},
{
.attr = {
@@ -341,7 +340,6 @@ static struct bin_attribute w1_f29_sysfs_bin_files[NB_SYSFS_BIN_FILES] = {
},
.size = 1,
.read = w1_f29_read_cond_search_polarity,
- .write = 0,
},
{
.attr = {
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 9761950697b4..2f2e894ea0c8 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -1027,7 +1027,7 @@ static int __init w1_init(void)
retval = driver_register(&w1_slave_driver);
if (retval) {
printk(KERN_ERR
- "Failed to register master driver. err=%d.\n",
+ "Failed to register slave driver. err=%d.\n",
retval);
goto err_out_master_unregister;
}
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index 3135b2c63998..e10acc237733 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -31,6 +31,9 @@
static int w1_delay_parm = 1;
module_param_named(delay_coef, w1_delay_parm, int, 0);
+static int w1_disable_irqs = 0;
+module_param_named(disable_irqs, w1_disable_irqs, int, 0);
+
static u8 w1_crc8_table[] = {
0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
@@ -79,6 +82,10 @@ static u8 w1_touch_bit(struct w1_master *dev, int bit)
*/
static void w1_write_bit(struct w1_master *dev, int bit)
{
+ unsigned long flags = 0;
+
+ if(w1_disable_irqs) local_irq_save(flags);
+
if (bit) {
dev->bus_master->write_bit(dev->bus_master->data, 0);
w1_delay(6);
@@ -90,6 +97,8 @@ static void w1_write_bit(struct w1_master *dev, int bit)
dev->bus_master->write_bit(dev->bus_master->data, 1);
w1_delay(10);
}
+
+ if(w1_disable_irqs) local_irq_restore(flags);
}
/**
@@ -158,7 +167,7 @@ EXPORT_SYMBOL_GPL(w1_write_8);
static u8 w1_read_bit(struct w1_master *dev)
{
int result;
- unsigned long flags;
+ unsigned long flags = 0;
/* sample timing is critical here */
local_irq_save(flags);
@@ -318,6 +327,9 @@ EXPORT_SYMBOL_GPL(w1_read_block);
int w1_reset_bus(struct w1_master *dev)
{
int result;
+ unsigned long flags = 0;
+
+ if(w1_disable_irqs) local_irq_save(flags);
if (dev->bus_master->reset_bus)
result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1;
@@ -330,19 +342,21 @@ int w1_reset_bus(struct w1_master *dev)
* cpu for such a short amount of time AND get it back in
* the maximum amount of time.
*/
- w1_delay(480);
+ w1_delay(500);
dev->bus_master->write_bit(dev->bus_master->data, 1);
w1_delay(70);
result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1;
- /* minmum 70 (above) + 410 = 480 us
+ /* minmum 70 (above) + 430 = 500 us
* There aren't any timing requirements between a reset and
* the following transactions. Sleeping is safe here.
*/
- /* w1_delay(410); min required time */
+ /* w1_delay(430); min required time */
msleep(1);
}
+ if(w1_disable_irqs) local_irq_restore(flags);
+
return result;
}
EXPORT_SYMBOL_GPL(w1_reset_bus);
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 37096246c937..a18bf6358eb8 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -129,17 +129,6 @@ config 977_WATCHDOG
Not sure? It's safe to say N.
-config IXP2000_WATCHDOG
- tristate "IXP2000 Watchdog"
- depends on ARCH_IXP2000
- help
- Say Y here if to include support for the watchdog timer
- in the Intel IXP2000(2400, 2800, 2850) network processors.
- This driver can be built as a module by choosing M. The module
- will be called ixp2000_wdt.
-
- Say N if you are unsure.
-
config IXP4XX_WATCHDOG
tristate "IXP4xx Watchdog"
depends on ARCH_IXP4XX
@@ -543,7 +532,7 @@ config WAFER_WDT
config I6300ESB_WDT
tristate "Intel 6300ESB Timer/Watchdog"
- depends on X86 && PCI
+ depends on PCI
---help---
Hardware driver for the watchdog timer built into the Intel
6300ESB controller hub.
@@ -551,6 +540,19 @@ config I6300ESB_WDT
To compile this driver as a module, choose M here: the
module will be called i6300esb.
+config IE6XX_WDT
+ tristate "Intel Atom E6xx Watchdog"
+ depends on X86 && PCI
+ select WATCHDOG_CORE
+ select MFD_CORE
+ select LPC_SCH
+ ---help---
+ Hardware driver for the watchdog timer built into the Intel
+ Atom E6XX (TunnelCreek) processor.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ie6xx_wdt.
+
config INTEL_SCU_WATCHDOG
bool "Intel SCU Watchdog for Mobile Platforms"
depends on X86_MRST
@@ -607,7 +609,12 @@ config IT87_WDT
depends on X86 && EXPERIMENTAL
---help---
This is the driver for the hardware watchdog on the ITE IT8702,
- IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 Super I/O chips.
+ IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 and IT8728
+ Super I/O chips.
+
+ If the driver does not work, then make sure that the game port in
+ the BIOS is enabled.
+
This watchdog simply watches your kernel to make sure it doesn't
freeze, and if it does, it reboots your computer after a certain
amount of time.
@@ -780,7 +787,7 @@ config SMSC37B787_WDT
config VIA_WDT
tristate "VIA Watchdog Timer"
- depends on X86
+ depends on X86 && PCI
select WATCHDOG_CORE
---help---
This is the driver for the hardware watchdog timer on VIA
@@ -937,7 +944,7 @@ config BCM47XX_WDT
tristate "Broadcom BCM47xx Watchdog Timer"
depends on BCM47XX
help
- Hardware driver for the Broadcom BCM47xx Watchog Timer.
+ Hardware driver for the Broadcom BCM47xx Watchdog Timer.
config RC32434_WDT
tristate "IDT RC32434 SoC Watchdog Timer"
@@ -1138,6 +1145,7 @@ config ZVM_WATCHDOG
config SH_WDT
tristate "SuperH Watchdog"
depends on SUPERH && (CPU_SH3 || CPU_SH4)
+ select WATCHDOG_CORE
help
This driver adds watchdog support for the integrated watchdog in the
SuperH processors. If you have one of these processors and wish
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index e8f479a16402..442bfbe0882a 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -36,7 +36,6 @@ obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
obj-$(CONFIG_TWL4030_WATCHDOG) += twl4030_wdt.o
obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
obj-$(CONFIG_977_WATCHDOG) += wdt977.o
-obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o
obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
@@ -81,6 +80,7 @@ obj-$(CONFIG_IB700_WDT) += ib700wdt.o
obj-$(CONFIG_IBMASR) += ibmasr.o
obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o
+obj-$(CONFIG_IE6XX_WDT) += ie6xx_wdt.o
obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o
ifeq ($(CONFIG_ITCO_VENDOR_SUPPORT),y)
obj-$(CONFIG_ITCO_WDT) += iTCO_vendor_support.o
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index 639ae9a23fbc..dc30dbd21cf1 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -282,29 +282,19 @@ static int __devinit ar7_wdt_probe(struct platform_device *pdev)
platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
if (!ar7_regs_wdt) {
pr_err("could not get registers resource\n");
- rc = -ENODEV;
- goto out;
- }
-
- if (!request_mem_region(ar7_regs_wdt->start,
- resource_size(ar7_regs_wdt), LONGNAME)) {
- pr_warn("watchdog I/O region busy\n");
- rc = -EBUSY;
- goto out;
+ return -ENODEV;
}
- ar7_wdt = ioremap(ar7_regs_wdt->start, resource_size(ar7_regs_wdt));
+ ar7_wdt = devm_request_and_ioremap(&pdev->dev, ar7_regs_wdt);
if (!ar7_wdt) {
pr_err("could not ioremap registers\n");
- rc = -ENXIO;
- goto out_mem_region;
+ return -ENXIO;
}
vbus_clk = clk_get(NULL, "vbus");
if (IS_ERR(vbus_clk)) {
pr_err("could not get vbus clock\n");
- rc = PTR_ERR(vbus_clk);
- goto out_mem_region;
+ return PTR_ERR(vbus_clk);
}
ar7_wdt_disable_wdt();
@@ -314,24 +304,21 @@ static int __devinit ar7_wdt_probe(struct platform_device *pdev)
rc = misc_register(&ar7_wdt_miscdev);
if (rc) {
pr_err("unable to register misc device\n");
- goto out_alloc;
+ goto out;
}
- goto out;
+ return 0;
-out_alloc:
- iounmap(ar7_wdt);
-out_mem_region:
- release_mem_region(ar7_regs_wdt->start, resource_size(ar7_regs_wdt));
out:
+ clk_put(vbus_clk);
+ vbus_clk = NULL;
return rc;
}
static int __devexit ar7_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&ar7_wdt_miscdev);
- iounmap(ar7_wdt);
- release_mem_region(ar7_regs_wdt->start, resource_size(ar7_regs_wdt));
-
+ clk_put(vbus_clk);
+ vbus_clk = NULL;
return 0;
}
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 9f13b897fd64..2b763815aeec 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -147,7 +147,6 @@ struct cmn_registers {
static unsigned int hpwdt_nmi_decoding;
static unsigned int allow_kdump;
-static unsigned int priority; /* hpwdt at end of die_notify list */
static unsigned int is_icru;
static DEFINE_SPINLOCK(rom_lock);
static void *cru_rom_addr;
@@ -723,28 +722,35 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
}
/*
- * If the priority is set to 1, then we will be put first on the
- * die notify list to handle a critical NMI. The default is to
- * be last so other users of the NMI signal can function.
+ * Only one function can register for NMI_UNKNOWN
*/
- retval = register_nmi_handler(NMI_UNKNOWN, hpwdt_pretimeout,
- (priority) ? NMI_FLAG_FIRST : 0,
- "hpwdt");
- if (retval != 0) {
- dev_warn(&dev->dev,
- "Unable to register a die notifier (err=%d).\n",
- retval);
- if (cru_rom_addr)
- iounmap(cru_rom_addr);
- }
+ retval = register_nmi_handler(NMI_UNKNOWN, hpwdt_pretimeout, 0, "hpwdt");
+ if (retval)
+ goto error;
+ retval = register_nmi_handler(NMI_SERR, hpwdt_pretimeout, 0, "hpwdt");
+ if (retval)
+ goto error1;
+ retval = register_nmi_handler(NMI_IO_CHECK, hpwdt_pretimeout, 0, "hpwdt");
+ if (retval)
+ goto error2;
dev_info(&dev->dev,
"HP Watchdog Timer Driver: NMI decoding initialized"
- ", allow kernel dump: %s (default = 0/OFF)"
- ", priority: %s (default = 0/LAST).\n",
- (allow_kdump == 0) ? "OFF" : "ON",
- (priority == 0) ? "LAST" : "FIRST");
+ ", allow kernel dump: %s (default = 0/OFF)\n",
+ (allow_kdump == 0) ? "OFF" : "ON");
return 0;
+
+error2:
+ unregister_nmi_handler(NMI_SERR, "hpwdt");
+error1:
+ unregister_nmi_handler(NMI_UNKNOWN, "hpwdt");
+error:
+ dev_warn(&dev->dev,
+ "Unable to register a die notifier (err=%d).\n",
+ retval);
+ if (cru_rom_addr)
+ iounmap(cru_rom_addr);
+ return retval;
}
static void hpwdt_exit_nmi_decoding(void)
@@ -855,16 +861,6 @@ static struct pci_driver hpwdt_driver = {
.remove = __devexit_p(hpwdt_exit),
};
-static void __exit hpwdt_cleanup(void)
-{
- pci_unregister_driver(&hpwdt_driver);
-}
-
-static int __init hpwdt_init(void)
-{
- return pci_register_driver(&hpwdt_driver);
-}
-
MODULE_AUTHOR("Tom Mingarelli");
MODULE_DESCRIPTION("hp watchdog driver");
MODULE_LICENSE("GPL");
@@ -881,11 +877,6 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
#ifdef CONFIG_HPWDT_NMI_DECODING
module_param(allow_kdump, int, 0);
MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs");
-
-module_param(priority, int, 0);
-MODULE_PARM_DESC(priority, "The hpwdt driver handles NMIs first or last"
- " (default = 0/Last)\n");
#endif /* !CONFIG_HPWDT_NMI_DECODING */
-module_init(hpwdt_init);
-module_exit(hpwdt_cleanup);
+module_pci_driver(hpwdt_driver);
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index 738032a36bcf..276877d5b6a3 100644
--- a/drivers/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -492,19 +492,7 @@ static struct pci_driver esb_driver = {
.shutdown = esb_shutdown,
};
-static int __init watchdog_init(void)
-{
- return pci_register_driver(&esb_driver);
-}
-
-static void __exit watchdog_cleanup(void)
-{
- pci_unregister_driver(&esb_driver);
- pr_info("Watchdog Module Unloaded\n");
-}
-
-module_init(watchdog_init);
-module_exit(watchdog_cleanup);
+module_pci_driver(esb_driver);
MODULE_AUTHOR("Ross Biro and David Härdeman");
MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets");
diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c
new file mode 100644
index 000000000000..5f0d776f902c
--- /dev/null
+++ b/drivers/watchdog/ie6xx_wdt.c
@@ -0,0 +1,348 @@
+/*
+ * Intel Atom E6xx Watchdog driver
+ *
+ * Copyright (C) 2011 Alexander Stein
+ * <alexander.stein@systec-electronic.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General
+ * Public License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * The full GNU General Public License is included in this
+ * distribution in the file called COPYING.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <linux/miscdevice.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/spinlock.h>
+
+#define DRIVER_NAME "ie6xx_wdt"
+
+#define PV1 0x00
+#define PV2 0x04
+
+#define RR0 0x0c
+#define RR1 0x0d
+#define WDT_RELOAD 0x01
+#define WDT_TOUT 0x02
+
+#define WDTCR 0x10
+#define WDT_PRE_SEL 0x04
+#define WDT_RESET_SEL 0x08
+#define WDT_RESET_EN 0x10
+#define WDT_TOUT_EN 0x20
+
+#define DCR 0x14
+
+#define WDTLR 0x18
+#define WDT_LOCK 0x01
+#define WDT_ENABLE 0x02
+#define WDT_TOUT_CNF 0x03
+
+#define MIN_TIME 1
+#define MAX_TIME (10 * 60) /* 10 minutes */
+#define DEFAULT_TIME 60
+
+static unsigned int timeout = DEFAULT_TIME;
+module_param(timeout, uint, 0);
+MODULE_PARM_DESC(timeout,
+ "Default Watchdog timer setting ("
+ __MODULE_STRING(DEFAULT_TIME) "s)."
+ "The range is from 1 to 600");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+ "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static u8 resetmode = 0x10;
+module_param(resetmode, byte, 0);
+MODULE_PARM_DESC(resetmode,
+ "Resetmode bits: 0x08 warm reset (cold reset otherwise), "
+ "0x10 reset enable, 0x20 disable toggle GPIO[4] (default=0x10)");
+
+static struct {
+ unsigned short sch_wdtba;
+ struct spinlock unlock_sequence;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs;
+#endif
+} ie6xx_wdt_data;
+
+/*
+ * This is needed to write to preload and reload registers
+ * struct ie6xx_wdt_data.unlock_sequence must be used
+ * to prevent sequence interrupts
+ */
+static void ie6xx_wdt_unlock_registers(void)
+{
+ outb(0x80, ie6xx_wdt_data.sch_wdtba + RR0);
+ outb(0x86, ie6xx_wdt_data.sch_wdtba + RR0);
+}
+
+static int ie6xx_wdt_ping(struct watchdog_device *wdd)
+{
+ spin_lock(&ie6xx_wdt_data.unlock_sequence);
+ ie6xx_wdt_unlock_registers();
+ outb(WDT_RELOAD, ie6xx_wdt_data.sch_wdtba + RR1);
+ spin_unlock(&ie6xx_wdt_data.unlock_sequence);
+ return 0;
+}
+
+static int ie6xx_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t)
+{
+ u32 preload;
+ u64 clock;
+ u8 wdtcr;
+
+ /* Watchdog clock is PCI Clock (33MHz) */
+ clock = 33000000;
+ /* and the preload value is loaded into [34:15] of the down counter */
+ preload = (t * clock) >> 15;
+ /*
+ * Manual states preload must be one less.
+ * Does not wrap as t is at least 1
+ */
+ preload -= 1;
+
+ spin_lock(&ie6xx_wdt_data.unlock_sequence);
+
+ /* Set ResetMode & Enable prescaler for range 10ms to 10 min */
+ wdtcr = resetmode & 0x38;
+ outb(wdtcr, ie6xx_wdt_data.sch_wdtba + WDTCR);
+
+ ie6xx_wdt_unlock_registers();
+ outl(0, ie6xx_wdt_data.sch_wdtba + PV1);
+
+ ie6xx_wdt_unlock_registers();
+ outl(preload, ie6xx_wdt_data.sch_wdtba + PV2);
+
+ ie6xx_wdt_unlock_registers();
+ outb(WDT_RELOAD | WDT_TOUT, ie6xx_wdt_data.sch_wdtba + RR1);
+
+ spin_unlock(&ie6xx_wdt_data.unlock_sequence);
+
+ wdd->timeout = t;
+ return 0;
+}
+
+static int ie6xx_wdt_start(struct watchdog_device *wdd)
+{
+ ie6xx_wdt_set_timeout(wdd, wdd->timeout);
+
+ /* Enable the watchdog timer */
+ spin_lock(&ie6xx_wdt_data.unlock_sequence);
+ outb(WDT_ENABLE, ie6xx_wdt_data.sch_wdtba + WDTLR);
+ spin_unlock(&ie6xx_wdt_data.unlock_sequence);
+
+ return 0;
+}
+
+static int ie6xx_wdt_stop(struct watchdog_device *wdd)
+{
+ if (inb(ie6xx_wdt_data.sch_wdtba + WDTLR) & WDT_LOCK)
+ return -1;
+
+ /* Disable the watchdog timer */
+ spin_lock(&ie6xx_wdt_data.unlock_sequence);
+ outb(0, ie6xx_wdt_data.sch_wdtba + WDTLR);
+ spin_unlock(&ie6xx_wdt_data.unlock_sequence);
+
+ return 0;
+}
+
+static const struct watchdog_info ie6xx_wdt_info = {
+ .identity = "Intel Atom E6xx Watchdog",
+ .options = WDIOF_SETTIMEOUT |
+ WDIOF_MAGICCLOSE |
+ WDIOF_KEEPALIVEPING,
+};
+
+static const struct watchdog_ops ie6xx_wdt_ops = {
+ .owner = THIS_MODULE,
+ .start = ie6xx_wdt_start,
+ .stop = ie6xx_wdt_stop,
+ .ping = ie6xx_wdt_ping,
+ .set_timeout = ie6xx_wdt_set_timeout,
+};
+
+static struct watchdog_device ie6xx_wdt_dev = {
+ .info = &ie6xx_wdt_info,
+ .ops = &ie6xx_wdt_ops,
+ .min_timeout = MIN_TIME,
+ .max_timeout = MAX_TIME,
+};
+
+#ifdef CONFIG_DEBUG_FS
+
+static int ie6xx_wdt_dbg_show(struct seq_file *s, void *unused)
+{
+ seq_printf(s, "PV1 = 0x%08x\n",
+ inl(ie6xx_wdt_data.sch_wdtba + PV1));
+ seq_printf(s, "PV2 = 0x%08x\n",
+ inl(ie6xx_wdt_data.sch_wdtba + PV2));
+ seq_printf(s, "RR = 0x%08x\n",
+ inw(ie6xx_wdt_data.sch_wdtba + RR0));
+ seq_printf(s, "WDTCR = 0x%08x\n",
+ inw(ie6xx_wdt_data.sch_wdtba + WDTCR));
+ seq_printf(s, "DCR = 0x%08x\n",
+ inl(ie6xx_wdt_data.sch_wdtba + DCR));
+ seq_printf(s, "WDTLR = 0x%08x\n",
+ inw(ie6xx_wdt_data.sch_wdtba + WDTLR));
+
+ seq_printf(s, "\n");
+ return 0;
+}
+
+static int ie6xx_wdt_dbg_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ie6xx_wdt_dbg_show, NULL);
+}
+
+static const struct file_operations ie6xx_wdt_dbg_operations = {
+ .open = ie6xx_wdt_dbg_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void __devinit ie6xx_wdt_debugfs_init(void)
+{
+ /* /sys/kernel/debug/ie6xx_wdt */
+ ie6xx_wdt_data.debugfs = debugfs_create_file("ie6xx_wdt",
+ S_IFREG | S_IRUGO, NULL, NULL, &ie6xx_wdt_dbg_operations);
+}
+
+static void __devexit ie6xx_wdt_debugfs_exit(void)
+{
+ debugfs_remove(ie6xx_wdt_data.debugfs);
+}
+
+#else
+static void __devinit ie6xx_wdt_debugfs_init(void)
+{
+}
+
+static void __devexit ie6xx_wdt_debugfs_exit(void)
+{
+}
+#endif
+
+static int __devinit ie6xx_wdt_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ u8 wdtlr;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!res)
+ return -ENODEV;
+
+ if (!request_region(res->start, resource_size(res), pdev->name)) {
+ dev_err(&pdev->dev, "Watchdog region 0x%llx already in use!\n",
+ (u64)res->start);
+ return -EBUSY;
+ }
+
+ ie6xx_wdt_data.sch_wdtba = res->start;
+ dev_dbg(&pdev->dev, "WDT = 0x%X\n", ie6xx_wdt_data.sch_wdtba);
+
+ ie6xx_wdt_dev.timeout = timeout;
+ watchdog_set_nowayout(&ie6xx_wdt_dev, nowayout);
+
+ spin_lock_init(&ie6xx_wdt_data.unlock_sequence);
+
+ wdtlr = inb(ie6xx_wdt_data.sch_wdtba + WDTLR);
+ if (wdtlr & WDT_LOCK)
+ dev_warn(&pdev->dev,
+ "Watchdog Timer is Locked (Reg=0x%x)\n", wdtlr);
+
+ ie6xx_wdt_debugfs_init();
+
+ ret = watchdog_register_device(&ie6xx_wdt_dev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Watchdog timer: cannot register device (err =%d)\n",
+ ret);
+ goto misc_register_error;
+ }
+
+ return 0;
+
+misc_register_error:
+ ie6xx_wdt_debugfs_exit();
+ release_region(res->start, resource_size(res));
+ ie6xx_wdt_data.sch_wdtba = 0;
+ return ret;
+}
+
+static int __devexit ie6xx_wdt_remove(struct platform_device *pdev)
+{
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ ie6xx_wdt_stop(NULL);
+ watchdog_unregister_device(&ie6xx_wdt_dev);
+ ie6xx_wdt_debugfs_exit();
+ release_region(res->start, resource_size(res));
+ ie6xx_wdt_data.sch_wdtba = 0;
+
+ return 0;
+}
+
+static struct platform_driver ie6xx_wdt_driver = {
+ .probe = ie6xx_wdt_probe,
+ .remove = __devexit_p(ie6xx_wdt_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ie6xx_wdt_init(void)
+{
+ /* Check boot parameters to verify that their initial values */
+ /* are in range. */
+ if ((timeout < MIN_TIME) ||
+ (timeout > MAX_TIME)) {
+ pr_err("Watchdog timer: value of timeout %d (dec) "
+ "is out of range from %d to %d (dec)\n",
+ timeout, MIN_TIME, MAX_TIME);
+ return -EINVAL;
+ }
+
+ return platform_driver_register(&ie6xx_wdt_driver);
+}
+
+static void __exit ie6xx_wdt_exit(void)
+{
+ platform_driver_unregister(&ie6xx_wdt_driver);
+}
+
+late_initcall(ie6xx_wdt_init);
+module_exit(ie6xx_wdt_exit);
+
+MODULE_AUTHOR("Alexander Stein <alexander.stein@systec-electronic.com>");
+MODULE_DESCRIPTION("Intel Atom E6xx Watchdog Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
index 8a741bcb5124..d3dcc6988b5f 100644
--- a/drivers/watchdog/it87_wdt.c
+++ b/drivers/watchdog/it87_wdt.c
@@ -12,7 +12,8 @@
* http://www.ite.com.tw/
*
* Support of the watchdog timers, which are available on
- * IT8702, IT8712, IT8716, IT8718, IT8720, IT8721 and IT8726.
+ * IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726
+ * and IT8728.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -84,6 +85,7 @@
#define IT8720_ID 0x8720
#define IT8721_ID 0x8721
#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */
+#define IT8728_ID 0x8728
/* GPIO Configuration Registers LDN=0x07 */
#define WDTCTRL 0x71
@@ -95,7 +97,7 @@
#define WDT_CIRINT 0x80
#define WDT_MOUSEINT 0x40
#define WDT_KYBINT 0x20
-#define WDT_GAMEPORT 0x10 /* not in it8718, it8720, it8721 */
+#define WDT_GAMEPORT 0x10 /* not in it8718, it8720, it8721, it8728 */
#define WDT_FORCE 0x02
#define WDT_ZERO 0x01
@@ -616,6 +618,7 @@ static int __init it87_wdt_init(void)
case IT8718_ID:
case IT8720_ID:
case IT8721_ID:
+ case IT8728_ID:
max_units = 65535;
try_gameport = 0;
break;
diff --git a/drivers/watchdog/ixp2000_wdt.c b/drivers/watchdog/ixp2000_wdt.c
deleted file mode 100644
index 3f047a58d3ae..000000000000
--- a/drivers/watchdog/ixp2000_wdt.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * drivers/char/watchdog/ixp2000_wdt.c
- *
- * Watchdog driver for Intel IXP2000 network processors
- *
- * Adapted from the IXP4xx watchdog driver by Lennert Buytenhek.
- * The original version carries these notices:
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright 2004 (c) MontaVista, Software, Inc.
- * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/timer.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/uaccess.h>
-#include <mach/hardware.h>
-
-static bool nowayout = WATCHDOG_NOWAYOUT;
-static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */
-static unsigned long wdt_status;
-static DEFINE_SPINLOCK(wdt_lock);
-
-#define WDT_IN_USE 0
-#define WDT_OK_TO_CLOSE 1
-
-static unsigned long wdt_tick_rate;
-
-static void wdt_enable(void)
-{
- spin_lock(&wdt_lock);
- ixp2000_reg_write(IXP2000_RESET0, *(IXP2000_RESET0) | WDT_RESET_ENABLE);
- ixp2000_reg_write(IXP2000_TWDE, WDT_ENABLE);
- ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate);
- ixp2000_reg_write(IXP2000_T4_CTL, TIMER_DIVIDER_256 | TIMER_ENABLE);
- spin_unlock(&wdt_lock);
-}
-
-static void wdt_disable(void)
-{
- spin_lock(&wdt_lock);
- ixp2000_reg_write(IXP2000_T4_CTL, 0);
- spin_unlock(&wdt_lock);
-}
-
-static void wdt_keepalive(void)
-{
- spin_lock(&wdt_lock);
- ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate);
- spin_unlock(&wdt_lock);
-}
-
-static int ixp2000_wdt_open(struct inode *inode, struct file *file)
-{
- if (test_and_set_bit(WDT_IN_USE, &wdt_status))
- return -EBUSY;
-
- clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
- wdt_enable();
-
- return nonseekable_open(inode, file);
-}
-
-static ssize_t ixp2000_wdt_write(struct file *file, const char *data,
- size_t len, loff_t *ppos)
-{
- if (len) {
- if (!nowayout) {
- size_t i;
-
- clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
- for (i = 0; i != len; i++) {
- char c;
-
- if (get_user(c, data + i))
- return -EFAULT;
- if (c == 'V')
- set_bit(WDT_OK_TO_CLOSE, &wdt_status);
- }
- }
- wdt_keepalive();
- }
-
- return len;
-}
-
-
-static const struct watchdog_info ident = {
- .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
- WDIOF_KEEPALIVEPING,
- .identity = "IXP2000 Watchdog",
-};
-
-static long ixp2000_wdt_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- int ret = -ENOTTY;
- int time;
-
- switch (cmd) {
- case WDIOC_GETSUPPORT:
- ret = copy_to_user((struct watchdog_info *)arg, &ident,
- sizeof(ident)) ? -EFAULT : 0;
- break;
-
- case WDIOC_GETSTATUS:
- ret = put_user(0, (int *)arg);
- break;
-
- case WDIOC_GETBOOTSTATUS:
- ret = put_user(0, (int *)arg);
- break;
-
- case WDIOC_KEEPALIVE:
- wdt_enable();
- ret = 0;
- break;
-
- case WDIOC_SETTIMEOUT:
- ret = get_user(time, (int *)arg);
- if (ret)
- break;
-
- if (time <= 0 || time > 60) {
- ret = -EINVAL;
- break;
- }
-
- heartbeat = time;
- wdt_keepalive();
- /* Fall through */
-
- case WDIOC_GETTIMEOUT:
- ret = put_user(heartbeat, (int *)arg);
- break;
- }
-
- return ret;
-}
-
-static int ixp2000_wdt_release(struct inode *inode, struct file *file)
-{
- if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
- wdt_disable();
- else
- pr_crit("Device closed unexpectedly - timer will not stop\n");
- clear_bit(WDT_IN_USE, &wdt_status);
- clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
- return 0;
-}
-
-
-static const struct file_operations ixp2000_wdt_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .write = ixp2000_wdt_write,
- .unlocked_ioctl = ixp2000_wdt_ioctl,
- .open = ixp2000_wdt_open,
- .release = ixp2000_wdt_release,
-};
-
-static struct miscdevice ixp2000_wdt_miscdev = {
- .minor = WATCHDOG_MINOR,
- .name = "watchdog",
- .fops = &ixp2000_wdt_fops,
-};
-
-static int __init ixp2000_wdt_init(void)
-{
- if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
- pr_info("Unable to use IXP2000 watchdog due to IXP2800 erratum #25\n");
- return -EIO;
- }
- wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
- return misc_register(&ixp2000_wdt_miscdev);
-}
-
-static void __exit ixp2000_wdt_exit(void)
-{
- misc_deregister(&ixp2000_wdt_miscdev);
-}
-
-module_init(ixp2000_wdt_init);
-module_exit(ixp2000_wdt_exit);
-
-MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
-MODULE_DESCRIPTION("IXP2000 Network Processor Watchdog");
-
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)");
-
-module_param(nowayout, bool, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c
index c891399bed6a..ee6900da8678 100644
--- a/drivers/watchdog/pcwd_pci.c
+++ b/drivers/watchdog/pcwd_pci.c
@@ -707,6 +707,7 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
goto err_out_disable_device;
}
+ spin_lock_init(&pcipcwd_private.io_lock);
pcipcwd_private.pdev = pdev;
pcipcwd_private.io_addr = pci_resource_start(pdev, 0);
@@ -814,22 +815,7 @@ static struct pci_driver pcipcwd_driver = {
.remove = __devexit_p(pcipcwd_card_exit),
};
-static int __init pcipcwd_init_module(void)
-{
- spin_lock_init(&pcipcwd_private.io_lock);
-
- return pci_register_driver(&pcipcwd_driver);
-}
-
-static void __exit pcipcwd_cleanup_module(void)
-{
- pci_unregister_driver(&pcipcwd_driver);
-
- pr_info("Watchdog Module Unloaded\n");
-}
-
-module_init(pcipcwd_init_module);
-module_exit(pcipcwd_cleanup_module);
+module_pci_driver(pcipcwd_driver);
MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
MODULE_DESCRIPTION("Berkshire PCI-PC Watchdog driver");
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
index 6b8432f61d05..87722e126058 100644
--- a/drivers/watchdog/pnx4008_wdt.c
+++ b/drivers/watchdog/pnx4008_wdt.c
@@ -32,6 +32,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/err.h>
+#include <linux/of.h>
#include <mach/hardware.h>
/* WatchDog Timer - Chapter 23 Page 207 */
@@ -201,10 +202,19 @@ static int __devexit pnx4008_wdt_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id pnx4008_wdt_match[] = {
+ { .compatible = "nxp,pnx4008-wdt" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pnx4008_wdt_match);
+#endif
+
static struct platform_driver platform_wdt_driver = {
.driver = {
.name = "pnx4008-watchdog",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(pnx4008_wdt_match),
},
.probe = pnx4008_wdt_probe,
.remove = __devexit_p(pnx4008_wdt_remove),
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 04e5a6de47d7..200ece5e2a22 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -40,6 +40,7 @@
#include <linux/cpufreq.h>
#include <linux/slab.h>
#include <linux/err.h>
+#include <linux/of.h>
#include <mach/map.h>
@@ -201,7 +202,7 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd, unsigned timeou
writel(count, wdt_base + S3C2410_WTDAT);
writel(wtcon, wdt_base + S3C2410_WTCON);
- wdd->timeout = timeout;
+ wdd->timeout = (count * divisor) / freq;
return 0;
}
@@ -503,8 +504,6 @@ static const struct of_device_id s3c2410_wdt_match[] = {
{},
};
MODULE_DEVICE_TABLE(of, s3c2410_wdt_match);
-#else
-#define s3c2410_wdt_match NULL
#endif
static struct platform_driver s3c2410wdt_driver = {
@@ -516,7 +515,7 @@ static struct platform_driver s3c2410wdt_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "s3c2410-wdt",
- .of_match_table = s3c2410_wdt_match,
+ .of_match_table = of_match_ptr(s3c2410_wdt_match),
},
};
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c
index bd86f32d63ab..f8477002b728 100644
--- a/drivers/watchdog/sch311x_wdt.c
+++ b/drivers/watchdog/sch311x_wdt.c
@@ -41,7 +41,6 @@
#define DRV_NAME "sch311x_wdt"
/* Runtime registers */
-#define RESGEN 0x1d
#define GP60 0x47
#define WDT_TIME_OUT 0x65
#define WDT_VAL 0x66
@@ -69,10 +68,6 @@ static unsigned short force_id;
module_param(force_id, ushort, 0);
MODULE_PARM_DESC(force_id, "Override the detected device ID");
-static unsigned short therm_trip;
-module_param(therm_trip, ushort, 0);
-MODULE_PARM_DESC(therm_trip, "Should a ThermTrip trigger the reset generator");
-
#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
module_param(timeout, int, 0);
@@ -358,26 +353,16 @@ static struct miscdevice sch311x_wdt_miscdev = {
static int __devinit sch311x_wdt_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- unsigned char val;
int err;
spin_lock_init(&sch311x_wdt_data.io_lock);
- if (!request_region(sch311x_wdt_data.runtime_reg + RESGEN, 1,
- DRV_NAME)) {
- dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n",
- sch311x_wdt_data.runtime_reg + RESGEN,
- sch311x_wdt_data.runtime_reg + RESGEN);
- err = -EBUSY;
- goto exit;
- }
-
if (!request_region(sch311x_wdt_data.runtime_reg + GP60, 1, DRV_NAME)) {
dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n",
sch311x_wdt_data.runtime_reg + GP60,
sch311x_wdt_data.runtime_reg + GP60);
err = -EBUSY;
- goto exit_release_region;
+ goto exit;
}
if (!request_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4,
@@ -386,7 +371,7 @@ static int __devinit sch311x_wdt_probe(struct platform_device *pdev)
sch311x_wdt_data.runtime_reg + WDT_TIME_OUT,
sch311x_wdt_data.runtime_reg + WDT_CTRL);
err = -EBUSY;
- goto exit_release_region2;
+ goto exit_release_region;
}
/* Make sure that the watchdog is not running */
@@ -414,24 +399,13 @@ static int __devinit sch311x_wdt_probe(struct platform_device *pdev)
/* Get status at boot */
sch311x_wdt_get_status(&sch311x_wdt_data.boot_status);
- /* enable watchdog */
- /* -- Reset Generator --
- * Bit 0 Enable Watchdog Timer Generation: 0* = Enabled, 1 = Disabled
- * Bit 1 Thermtrip Source Select: O* = No Source, 1 = Source
- * Bit 2 WDT2_CTL: WDT input bit
- * Bit 3-7 Reserved
- */
- outb(0, sch311x_wdt_data.runtime_reg + RESGEN);
- val = therm_trip ? 0x06 : 0x04;
- outb(val, sch311x_wdt_data.runtime_reg + RESGEN);
-
sch311x_wdt_miscdev.parent = dev;
err = misc_register(&sch311x_wdt_miscdev);
if (err != 0) {
dev_err(dev, "cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, err);
- goto exit_release_region3;
+ goto exit_release_region2;
}
dev_info(dev,
@@ -440,12 +414,10 @@ static int __devinit sch311x_wdt_probe(struct platform_device *pdev)
return 0;
-exit_release_region3:
- release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4);
exit_release_region2:
- release_region(sch311x_wdt_data.runtime_reg + GP60, 1);
+ release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4);
exit_release_region:
- release_region(sch311x_wdt_data.runtime_reg + RESGEN, 1);
+ release_region(sch311x_wdt_data.runtime_reg + GP60, 1);
sch311x_wdt_data.runtime_reg = 0;
exit:
return err;
@@ -461,7 +433,6 @@ static int __devexit sch311x_wdt_remove(struct platform_device *pdev)
misc_deregister(&sch311x_wdt_miscdev);
release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4);
release_region(sch311x_wdt_data.runtime_reg + GP60, 1);
- release_region(sch311x_wdt_data.runtime_reg + RESGEN, 1);
sch311x_wdt_data.runtime_reg = 0;
return 0;
}
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index 93958a7763e6..e5b59bebcdb1 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -3,7 +3,7 @@
*
* Watchdog driver for integrated watchdog in the SuperH processors.
*
- * Copyright (C) 2001 - 2010 Paul Mundt <lethal@linux-sh.org>
+ * Copyright (C) 2001 - 2012 Paul Mundt <lethal@linux-sh.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
@@ -25,16 +25,15 @@
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/types.h>
+#include <linux/spinlock.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
-#include <linux/reboot.h>
-#include <linux/notifier.h>
-#include <linux/ioport.h>
+#include <linux/pm_runtime.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/io.h>
-#include <linux/uaccess.h>
+#include <linux/clk.h>
#include <asm/watchdog.h>
#define DRV_NAME "sh-wdt"
@@ -69,10 +68,6 @@
static int clock_division_ratio = WTCSR_CKS_4096;
#define next_ping_period(cks) (jiffies + msecs_to_jiffies(cks - 4))
-static const struct watchdog_info sh_wdt_info;
-static struct platform_device *sh_wdt_dev;
-static DEFINE_SPINLOCK(shwdt_lock);
-
#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
static bool nowayout = WATCHDOG_NOWAYOUT;
@@ -81,19 +76,22 @@ static unsigned long next_heartbeat;
struct sh_wdt {
void __iomem *base;
struct device *dev;
+ struct clk *clk;
+ spinlock_t lock;
struct timer_list timer;
-
- unsigned long enabled;
- char expect_close;
};
-static void sh_wdt_start(struct sh_wdt *wdt)
+static int sh_wdt_start(struct watchdog_device *wdt_dev)
{
+ struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
unsigned long flags;
u8 csr;
- spin_lock_irqsave(&shwdt_lock, flags);
+ pm_runtime_get_sync(wdt->dev);
+ clk_enable(wdt->clk);
+
+ spin_lock_irqsave(&wdt->lock, flags);
next_heartbeat = jiffies + (heartbeat * HZ);
mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
@@ -122,15 +120,18 @@ static void sh_wdt_start(struct sh_wdt *wdt)
csr &= ~RSTCSR_RSTS;
sh_wdt_write_rstcsr(csr);
#endif
- spin_unlock_irqrestore(&shwdt_lock, flags);
+ spin_unlock_irqrestore(&wdt->lock, flags);
+
+ return 0;
}
-static void sh_wdt_stop(struct sh_wdt *wdt)
+static int sh_wdt_stop(struct watchdog_device *wdt_dev)
{
+ struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
unsigned long flags;
u8 csr;
- spin_lock_irqsave(&shwdt_lock, flags);
+ spin_lock_irqsave(&wdt->lock, flags);
del_timer(&wdt->timer);
@@ -138,28 +139,39 @@ static void sh_wdt_stop(struct sh_wdt *wdt)
csr &= ~WTCSR_TME;
sh_wdt_write_csr(csr);
- spin_unlock_irqrestore(&shwdt_lock, flags);
+ spin_unlock_irqrestore(&wdt->lock, flags);
+
+ clk_disable(wdt->clk);
+ pm_runtime_put_sync(wdt->dev);
+
+ return 0;
}
-static inline void sh_wdt_keepalive(struct sh_wdt *wdt)
+static int sh_wdt_keepalive(struct watchdog_device *wdt_dev)
{
+ struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
unsigned long flags;
- spin_lock_irqsave(&shwdt_lock, flags);
+ spin_lock_irqsave(&wdt->lock, flags);
next_heartbeat = jiffies + (heartbeat * HZ);
- spin_unlock_irqrestore(&shwdt_lock, flags);
+ spin_unlock_irqrestore(&wdt->lock, flags);
+
+ return 0;
}
-static int sh_wdt_set_heartbeat(int t)
+static int sh_wdt_set_heartbeat(struct watchdog_device *wdt_dev, unsigned t)
{
+ struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
unsigned long flags;
if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */
return -EINVAL;
- spin_lock_irqsave(&shwdt_lock, flags);
+ spin_lock_irqsave(&wdt->lock, flags);
heartbeat = t;
- spin_unlock_irqrestore(&shwdt_lock, flags);
+ wdt_dev->timeout = t;
+ spin_unlock_irqrestore(&wdt->lock, flags);
+
return 0;
}
@@ -168,7 +180,7 @@ static void sh_wdt_ping(unsigned long data)
struct sh_wdt *wdt = (struct sh_wdt *)data;
unsigned long flags;
- spin_lock_irqsave(&shwdt_lock, flags);
+ spin_lock_irqsave(&wdt->lock, flags);
if (time_before(jiffies, next_heartbeat)) {
u8 csr;
@@ -182,137 +194,9 @@ static void sh_wdt_ping(unsigned long data)
} else
dev_warn(wdt->dev, "Heartbeat lost! Will not ping "
"the watchdog\n");
- spin_unlock_irqrestore(&shwdt_lock, flags);
-}
-
-static int sh_wdt_open(struct inode *inode, struct file *file)
-{
- struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev);
-
- if (test_and_set_bit(0, &wdt->enabled))
- return -EBUSY;
- if (nowayout)
- __module_get(THIS_MODULE);
-
- file->private_data = wdt;
-
- sh_wdt_start(wdt);
-
- return nonseekable_open(inode, file);
-}
-
-static int sh_wdt_close(struct inode *inode, struct file *file)
-{
- struct sh_wdt *wdt = file->private_data;
-
- if (wdt->expect_close == 42) {
- sh_wdt_stop(wdt);
- } else {
- dev_crit(wdt->dev, "Unexpected close, not "
- "stopping watchdog!\n");
- sh_wdt_keepalive(wdt);
- }
-
- clear_bit(0, &wdt->enabled);
- wdt->expect_close = 0;
-
- return 0;
-}
-
-static ssize_t sh_wdt_write(struct file *file, const char *buf,
- size_t count, loff_t *ppos)
-{
- struct sh_wdt *wdt = file->private_data;
-
- if (count) {
- if (!nowayout) {
- size_t i;
-
- wdt->expect_close = 0;
-
- for (i = 0; i != count; i++) {
- char c;
- if (get_user(c, buf + i))
- return -EFAULT;
- if (c == 'V')
- wdt->expect_close = 42;
- }
- }
- sh_wdt_keepalive(wdt);
- }
-
- return count;
+ spin_unlock_irqrestore(&wdt->lock, flags);
}
-static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct sh_wdt *wdt = file->private_data;
- int new_heartbeat;
- int options, retval = -EINVAL;
-
- switch (cmd) {
- case WDIOC_GETSUPPORT:
- return copy_to_user((struct watchdog_info *)arg,
- &sh_wdt_info, sizeof(sh_wdt_info)) ? -EFAULT : 0;
- case WDIOC_GETSTATUS:
- case WDIOC_GETBOOTSTATUS:
- return put_user(0, (int *)arg);
- case WDIOC_SETOPTIONS:
- if (get_user(options, (int *)arg))
- return -EFAULT;
-
- if (options & WDIOS_DISABLECARD) {
- sh_wdt_stop(wdt);
- retval = 0;
- }
-
- if (options & WDIOS_ENABLECARD) {
- sh_wdt_start(wdt);
- retval = 0;
- }
-
- return retval;
- case WDIOC_KEEPALIVE:
- sh_wdt_keepalive(wdt);
- return 0;
- case WDIOC_SETTIMEOUT:
- if (get_user(new_heartbeat, (int *)arg))
- return -EFAULT;
-
- if (sh_wdt_set_heartbeat(new_heartbeat))
- return -EINVAL;
-
- sh_wdt_keepalive(wdt);
- /* Fall */
- case WDIOC_GETTIMEOUT:
- return put_user(heartbeat, (int *)arg);
- default:
- return -ENOTTY;
- }
- return 0;
-}
-
-static int sh_wdt_notify_sys(struct notifier_block *this,
- unsigned long code, void *unused)
-{
- struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev);
-
- if (code == SYS_DOWN || code == SYS_HALT)
- sh_wdt_stop(wdt);
-
- return NOTIFY_DONE;
-}
-
-static const struct file_operations sh_wdt_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .write = sh_wdt_write,
- .unlocked_ioctl = sh_wdt_ioctl,
- .open = sh_wdt_open,
- .release = sh_wdt_close,
-};
-
static const struct watchdog_info sh_wdt_info = {
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE,
@@ -320,14 +204,17 @@ static const struct watchdog_info sh_wdt_info = {
.identity = "SH WDT",
};
-static struct notifier_block sh_wdt_notifier = {
- .notifier_call = sh_wdt_notify_sys,
+static const struct watchdog_ops sh_wdt_ops = {
+ .owner = THIS_MODULE,
+ .start = sh_wdt_start,
+ .stop = sh_wdt_stop,
+ .ping = sh_wdt_keepalive,
+ .set_timeout = sh_wdt_set_heartbeat,
};
-static struct miscdevice sh_wdt_miscdev = {
- .minor = WATCHDOG_MINOR,
- .name = "watchdog",
- .fops = &sh_wdt_fops,
+static struct watchdog_device sh_wdt_dev = {
+ .info = &sh_wdt_info,
+ .ops = &sh_wdt_ops,
};
static int __devinit sh_wdt_probe(struct platform_device *pdev)
@@ -347,39 +234,49 @@ static int __devinit sh_wdt_probe(struct platform_device *pdev)
if (unlikely(!res))
return -EINVAL;
- if (!devm_request_mem_region(&pdev->dev, res->start,
- resource_size(res), DRV_NAME))
- return -EBUSY;
-
wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL);
- if (unlikely(!wdt)) {
- rc = -ENOMEM;
- goto out_release;
- }
+ if (unlikely(!wdt))
+ return -ENOMEM;
wdt->dev = &pdev->dev;
- wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ wdt->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(wdt->clk)) {
+ /*
+ * Clock framework support is optional, continue on
+ * anyways if we don't find a matching clock.
+ */
+ wdt->clk = NULL;
+ }
+
+ wdt->base = devm_request_and_ioremap(wdt->dev, res);
if (unlikely(!wdt->base)) {
- rc = -ENXIO;
- goto out_err;
+ rc = -EADDRNOTAVAIL;
+ goto err;
}
- rc = register_reboot_notifier(&sh_wdt_notifier);
+ watchdog_set_nowayout(&sh_wdt_dev, nowayout);
+ watchdog_set_drvdata(&sh_wdt_dev, wdt);
+
+ spin_lock_init(&wdt->lock);
+
+ rc = sh_wdt_set_heartbeat(&sh_wdt_dev, heartbeat);
if (unlikely(rc)) {
- dev_err(&pdev->dev,
- "Can't register reboot notifier (err=%d)\n", rc);
- goto out_unmap;
+ /* Default timeout if invalid */
+ sh_wdt_set_heartbeat(&sh_wdt_dev, WATCHDOG_HEARTBEAT);
+
+ dev_warn(&pdev->dev,
+ "heartbeat value must be 1<=x<=3600, using %d\n",
+ sh_wdt_dev.timeout);
}
- sh_wdt_miscdev.parent = wdt->dev;
+ dev_info(&pdev->dev, "configured with heartbeat=%d sec (nowayout=%d)\n",
+ sh_wdt_dev.timeout, nowayout);
- rc = misc_register(&sh_wdt_miscdev);
+ rc = watchdog_register_device(&sh_wdt_dev);
if (unlikely(rc)) {
- dev_err(&pdev->dev,
- "Can't register miscdev on minor=%d (err=%d)\n",
- sh_wdt_miscdev.minor, rc);
- goto out_unreg;
+ dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc);
+ goto err;
}
init_timer(&wdt->timer);
@@ -388,20 +285,15 @@ static int __devinit sh_wdt_probe(struct platform_device *pdev)
wdt->timer.expires = next_ping_period(clock_division_ratio);
platform_set_drvdata(pdev, wdt);
- sh_wdt_dev = pdev;
dev_info(&pdev->dev, "initialized.\n");
+ pm_runtime_enable(&pdev->dev);
+
return 0;
-out_unreg:
- unregister_reboot_notifier(&sh_wdt_notifier);
-out_unmap:
- devm_iounmap(&pdev->dev, wdt->base);
-out_err:
- devm_kfree(&pdev->dev, wdt);
-out_release:
- devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
+err:
+ clk_put(wdt->clk);
return rc;
}
@@ -409,36 +301,35 @@ out_release:
static int __devexit sh_wdt_remove(struct platform_device *pdev)
{
struct sh_wdt *wdt = platform_get_drvdata(pdev);
- struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
platform_set_drvdata(pdev, NULL);
- misc_deregister(&sh_wdt_miscdev);
+ watchdog_unregister_device(&sh_wdt_dev);
- sh_wdt_dev = NULL;
-
- unregister_reboot_notifier(&sh_wdt_notifier);
- devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
- devm_iounmap(&pdev->dev, wdt->base);
- devm_kfree(&pdev->dev, wdt);
+ pm_runtime_disable(&pdev->dev);
+ clk_put(wdt->clk);
return 0;
}
+static void sh_wdt_shutdown(struct platform_device *pdev)
+{
+ sh_wdt_stop(&sh_wdt_dev);
+}
+
static struct platform_driver sh_wdt_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
- .probe = sh_wdt_probe,
- .remove = __devexit_p(sh_wdt_remove),
+ .probe = sh_wdt_probe,
+ .remove = __devexit_p(sh_wdt_remove),
+ .shutdown = sh_wdt_shutdown,
};
static int __init sh_wdt_init(void)
{
- int rc;
-
if (unlikely(clock_division_ratio < 0x5 ||
clock_division_ratio > 0x7)) {
clock_division_ratio = WTCSR_CKS_4096;
@@ -447,17 +338,6 @@ static int __init sh_wdt_init(void)
clock_division_ratio);
}
- rc = sh_wdt_set_heartbeat(heartbeat);
- if (unlikely(rc)) {
- heartbeat = WATCHDOG_HEARTBEAT;
-
- pr_info("heartbeat value must be 1<=x<=3600, using %d\n",
- heartbeat);
- }
-
- pr_info("configured with heartbeat=%d sec (nowayout=%d)\n",
- heartbeat, nowayout);
-
return platform_driver_register(&sh_wdt_driver);
}
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
index 59108e48ada3..ae5e82cb83fa 100644
--- a/drivers/watchdog/sp5100_tco.c
+++ b/drivers/watchdog/sp5100_tco.c
@@ -313,7 +313,7 @@ static unsigned char __devinit sp5100_tco_setupdevice(void)
tcobase_phys = val;
tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE);
- if (tcobase == 0) {
+ if (!tcobase) {
pr_err("failed to get tcobase address\n");
goto unreg_mem_region;
}
diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c
index 465e08273c97..5603e31afdab 100644
--- a/drivers/watchdog/via_wdt.c
+++ b/drivers/watchdog/via_wdt.c
@@ -202,6 +202,9 @@ static int __devinit wdt_probe(struct pci_dev *pdev,
goto err_out_release;
}
+ if (timeout < 1 || timeout > WDT_TIMEOUT_MAX)
+ timeout = WDT_TIMEOUT;
+
wdt_dev.timeout = timeout;
watchdog_set_nowayout(&wdt_dev, nowayout);
if (readl(wdt_mem) & VIA_WDT_FIRED)
@@ -250,20 +253,7 @@ static struct pci_driver wdt_driver = {
.remove = __devexit_p(wdt_remove),
};
-static int __init wdt_init(void)
-{
- if (timeout < 1 || timeout > WDT_TIMEOUT_MAX)
- timeout = WDT_TIMEOUT;
- return pci_register_driver(&wdt_driver);
-}
-
-static void __exit wdt_exit(void)
-{
- pci_unregister_driver(&wdt_driver);
-}
-
-module_init(wdt_init);
-module_exit(wdt_exit);
+module_pci_driver(wdt_driver);
MODULE_AUTHOR("Marc Vertes");
MODULE_DESCRIPTION("Driver for watchdog timer on VIA chipset");
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
index 1c888c7d4cce..e32654efdbb6 100644
--- a/drivers/watchdog/wdt_pci.c
+++ b/drivers/watchdog/wdt_pci.c
@@ -739,39 +739,7 @@ static struct pci_driver wdtpci_driver = {
.remove = __devexit_p(wdtpci_remove_one),
};
-
-/**
- * wdtpci_cleanup:
- *
- * Unload the watchdog. You cannot do this with any file handles open.
- * If your watchdog is set to continue ticking on close and you unload
- * it, well it keeps ticking. We won't get the interrupt but the board
- * will not touch PC memory so all is fine. You just have to load a new
- * module in xx seconds or reboot.
- */
-
-static void __exit wdtpci_cleanup(void)
-{
- pci_unregister_driver(&wdtpci_driver);
-}
-
-
-/**
- * wdtpci_init:
- *
- * Set up the WDT watchdog board. All we have to do is grab the
- * resources we require and bitch if anyone beat us to them.
- * The open() function will actually kick the board off.
- */
-
-static int __init wdtpci_init(void)
-{
- return pci_register_driver(&wdtpci_driver);
-}
-
-
-module_init(wdtpci_init);
-module_exit(wdtpci_cleanup);
+module_pci_driver(wdtpci_driver);
MODULE_AUTHOR("JP Nollmann, Alan Cox");
MODULE_DESCRIPTION("Driver for the ICS PCI-WDT500/501 watchdog cards");
diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c
index b1815c5ed7a7..87d66d236c3e 100644
--- a/drivers/watchdog/wm831x_wdt.c
+++ b/drivers/watchdog/wm831x_wdt.c
@@ -247,8 +247,9 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
reg |= pdata->software << WM831X_WDOG_RST_SRC_SHIFT;
if (pdata->update_gpio) {
- ret = gpio_request(pdata->update_gpio,
- "Watchdog update");
+ ret = gpio_request_one(pdata->update_gpio,
+ GPIOF_DIR_OUT | GPIOF_INIT_LOW,
+ "Watchdog update");
if (ret < 0) {
dev_err(wm831x->dev,
"Failed to request update GPIO: %d\n",
@@ -256,14 +257,6 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
goto err;
}
- ret = gpio_direction_output(pdata->update_gpio, 0);
- if (ret != 0) {
- dev_err(wm831x->dev,
- "gpio_direction_output returned: %d\n",
- ret);
- goto err_gpio;
- }
-
driver_data->update_gpio = pdata->update_gpio;
/* Make sure the watchdog takes hardware updates */
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index ea20c51d24c7..8d2501e604dd 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -71,7 +71,7 @@ config XEN_DEV_EVTCHN
tristate "Xen /dev/xen/evtchn device"
default y
help
- The evtchn driver allows a userspace process to triger event
+ The evtchn driver allows a userspace process to trigger event
channels and to receive notification of an event channel
firing.
If in doubt, say yes.
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index e95d1b64082c..022574202749 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -33,7 +33,7 @@ config ARCH_BINFMT_ELF_RANDOMIZE_PIE
config BINFMT_ELF_FDPIC
bool "Kernel support for FDPIC ELF binaries"
default y
- depends on (FRV || BLACKFIN || (SUPERH32 && !MMU))
+ depends on (FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X)
help
ELF FDPIC binaries are based on ELF, but allow the individual load
segments of a binary to be located in memory independently of each
diff --git a/fs/aio.c b/fs/aio.c
index 67a6db3e1b6f..e7f2fad7b4ce 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1456,6 +1456,10 @@ static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb, bool compat)
if (ret < 0)
goto out;
+ ret = rw_verify_area(type, kiocb->ki_filp, &kiocb->ki_pos, ret);
+ if (ret < 0)
+ goto out;
+
kiocb->ki_nr_segs = kiocb->ki_nbytes;
kiocb->ki_cur_seg = 0;
/* ki_nbytes/left now reflect bytes instead of segs */
@@ -1467,11 +1471,17 @@ out:
return ret;
}
-static ssize_t aio_setup_single_vector(struct kiocb *kiocb)
+static ssize_t aio_setup_single_vector(int type, struct file * file, struct kiocb *kiocb)
{
+ int bytes;
+
+ bytes = rw_verify_area(type, file, &kiocb->ki_pos, kiocb->ki_left);
+ if (bytes < 0)
+ return bytes;
+
kiocb->ki_iovec = &kiocb->ki_inline_vec;
kiocb->ki_iovec->iov_base = kiocb->ki_buf;
- kiocb->ki_iovec->iov_len = kiocb->ki_left;
+ kiocb->ki_iovec->iov_len = bytes;
kiocb->ki_nr_segs = 1;
kiocb->ki_cur_seg = 0;
return 0;
@@ -1496,10 +1506,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf,
kiocb->ki_left)))
break;
- ret = security_file_permission(file, MAY_READ);
- if (unlikely(ret))
- break;
- ret = aio_setup_single_vector(kiocb);
+ ret = aio_setup_single_vector(READ, file, kiocb);
if (ret)
break;
ret = -EINVAL;
@@ -1514,10 +1521,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf,
kiocb->ki_left)))
break;
- ret = security_file_permission(file, MAY_WRITE);
- if (unlikely(ret))
- break;
- ret = aio_setup_single_vector(kiocb);
+ ret = aio_setup_single_vector(WRITE, file, kiocb);
if (ret)
break;
ret = -EINVAL;
@@ -1528,9 +1532,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
ret = -EBADF;
if (unlikely(!(file->f_mode & FMODE_READ)))
break;
- ret = security_file_permission(file, MAY_READ);
- if (unlikely(ret))
- break;
ret = aio_setup_vectored_rw(READ, kiocb, compat);
if (ret)
break;
@@ -1542,9 +1543,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
ret = -EBADF;
if (unlikely(!(file->f_mode & FMODE_WRITE)))
break;
- ret = security_file_permission(file, MAY_WRITE);
- if (unlikely(ret))
- break;
ret = aio_setup_vectored_rw(WRITE, kiocb, compat);
if (ret)
break;
diff --git a/fs/bio.c b/fs/bio.c
index e453924036e9..84da88539046 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -505,9 +505,14 @@ EXPORT_SYMBOL(bio_clone);
int bio_get_nr_vecs(struct block_device *bdev)
{
struct request_queue *q = bdev_get_queue(bdev);
- return min_t(unsigned,
+ int nr_pages;
+
+ nr_pages = min_t(unsigned,
queue_max_segments(q),
queue_max_sectors(q) / (PAGE_SIZE >> 9) + 1);
+
+ return min_t(unsigned, nr_pages, BIO_MAX_PAGES);
+
}
EXPORT_SYMBOL(bio_get_nr_vecs);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index e08f6a20a5bb..ba11c30f302d 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -70,7 +70,7 @@ static void bdev_inode_switch_bdi(struct inode *inode,
spin_unlock(&dst->wb.list_lock);
}
-static sector_t max_block(struct block_device *bdev)
+sector_t blkdev_max_block(struct block_device *bdev)
{
sector_t retval = ~((sector_t)0);
loff_t sz = i_size_read(bdev->bd_inode);
@@ -163,7 +163,7 @@ static int
blkdev_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh, int create)
{
- if (iblock >= max_block(I_BDEV(inode))) {
+ if (iblock >= blkdev_max_block(I_BDEV(inode))) {
if (create)
return -EIO;
@@ -185,7 +185,7 @@ static int
blkdev_get_blocks(struct inode *inode, sector_t iblock,
struct buffer_head *bh, int create)
{
- sector_t end_block = max_block(I_BDEV(inode));
+ sector_t end_block = blkdev_max_block(I_BDEV(inode));
unsigned long max_blocks = bh->b_size >> inode->i_blkbits;
if ((iblock + max_blocks) > end_block) {
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index a7ffc88a7dbe..e1fe74a2ce16 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2753,7 +2753,7 @@ static int write_dev_flush(struct btrfs_device *device, int wait)
* one reference for us, and we leave it for the
* caller
*/
- device->flush_bio = NULL;;
+ device->flush_bio = NULL;
bio = bio_alloc(GFP_NOFS, 0);
if (!bio)
return -ENOMEM;
diff --git a/fs/buffer.c b/fs/buffer.c
index 351e18ea2e53..ad5938ca357c 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -921,6 +921,7 @@ init_page_buffers(struct page *page, struct block_device *bdev,
struct buffer_head *head = page_buffers(page);
struct buffer_head *bh = head;
int uptodate = PageUptodate(page);
+ sector_t end_block = blkdev_max_block(I_BDEV(bdev->bd_inode));
do {
if (!buffer_mapped(bh)) {
@@ -929,7 +930,8 @@ init_page_buffers(struct page *page, struct block_device *bdev,
bh->b_blocknr = block;
if (uptodate)
set_buffer_uptodate(bh);
- set_buffer_mapped(bh);
+ if (block < end_block)
+ set_buffer_mapped(bh);
}
block++;
bh = bh->b_this_page;
diff --git a/fs/dcache.c b/fs/dcache.c
index b80531c91779..8c1ab8fb5012 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -153,16 +153,12 @@ int proc_nr_dentry(ctl_table *table, int write, void __user *buffer,
* In contrast, 'ct' and 'tcount' can be from a pathname, and do
* need the careful unaligned handling.
*/
-static inline int dentry_cmp(const unsigned char *cs, size_t scount,
- const unsigned char *ct, size_t tcount)
+static inline int dentry_string_cmp(const unsigned char *cs, const unsigned char *ct, unsigned tcount)
{
unsigned long a,b,mask;
- if (unlikely(scount != tcount))
- return 1;
-
for (;;) {
- a = load_unaligned_zeropad(cs);
+ a = *(unsigned long *)cs;
b = load_unaligned_zeropad(ct);
if (tcount < sizeof(unsigned long))
break;
@@ -180,12 +176,8 @@ static inline int dentry_cmp(const unsigned char *cs, size_t scount,
#else
-static inline int dentry_cmp(const unsigned char *cs, size_t scount,
- const unsigned char *ct, size_t tcount)
+static inline int dentry_string_cmp(const unsigned char *cs, const unsigned char *ct, unsigned tcount)
{
- if (scount != tcount)
- return 1;
-
do {
if (*cs != *ct)
return 1;
@@ -198,6 +190,30 @@ static inline int dentry_cmp(const unsigned char *cs, size_t scount,
#endif
+static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *ct, unsigned tcount)
+{
+ const unsigned char *cs;
+ /*
+ * Be careful about RCU walk racing with rename:
+ * use ACCESS_ONCE to fetch the name pointer.
+ *
+ * NOTE! Even if a rename will mean that the length
+ * was not loaded atomically, we don't care. The
+ * RCU walk will check the sequence count eventually,
+ * and catch it. And we won't overrun the buffer,
+ * because we're reading the name pointer atomically,
+ * and a dentry name is guaranteed to be properly
+ * terminated with a NUL byte.
+ *
+ * End result: even if 'len' is wrong, we'll exit
+ * early because the data cannot match (there can
+ * be no NUL in the ct/tcount data)
+ */
+ cs = ACCESS_ONCE(dentry->d_name.name);
+ smp_read_barrier_depends();
+ return dentry_string_cmp(cs, ct, tcount);
+}
+
static void __d_free(struct rcu_head *head)
{
struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
@@ -1258,6 +1274,13 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
if (!dentry)
return NULL;
+ /*
+ * We guarantee that the inline name is always NUL-terminated.
+ * This way the memcpy() done by the name switching in rename
+ * will still always have a NUL at the end, even if we might
+ * be overwriting an internal NUL character
+ */
+ dentry->d_iname[DNAME_INLINE_LEN-1] = 0;
if (name->len > DNAME_INLINE_LEN-1) {
dname = kmalloc(name->len + 1, GFP_KERNEL);
if (!dname) {
@@ -1267,13 +1290,16 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
} else {
dname = dentry->d_iname;
}
- dentry->d_name.name = dname;
dentry->d_name.len = name->len;
dentry->d_name.hash = name->hash;
memcpy(dname, name->name, name->len);
dname[name->len] = 0;
+ /* Make sure we always see the terminating NUL character */
+ smp_wmb();
+ dentry->d_name.name = dname;
+
dentry->d_count = 1;
dentry->d_flags = 0;
spin_lock_init(&dentry->d_lock);
@@ -1439,18 +1465,18 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry,
}
list_for_each_entry(alias, &inode->i_dentry, d_alias) {
- struct qstr *qstr = &alias->d_name;
-
/*
* Don't need alias->d_lock here, because aliases with
* d_parent == entry->d_parent are not subject to name or
* parent changes, because the parent inode i_mutex is held.
*/
- if (qstr->hash != hash)
+ if (alias->d_name.hash != hash)
continue;
if (alias->d_parent != entry->d_parent)
continue;
- if (dentry_cmp(qstr->name, qstr->len, name, len))
+ if (alias->d_name.len != len)
+ continue;
+ if (dentry_cmp(alias, name, len))
continue;
__dget(alias);
return alias;
@@ -1489,7 +1515,7 @@ struct dentry *d_make_root(struct inode *root_inode)
struct dentry *res = NULL;
if (root_inode) {
- static const struct qstr name = { .name = "/", .len = 1 };
+ static const struct qstr name = QSTR_INIT("/", 1);
res = __d_alloc(root_inode->i_sb, &name);
if (res)
@@ -1727,6 +1753,48 @@ err_out:
}
EXPORT_SYMBOL(d_add_ci);
+/*
+ * Do the slow-case of the dentry name compare.
+ *
+ * Unlike the dentry_cmp() function, we need to atomically
+ * load the name, length and inode information, so that the
+ * filesystem can rely on them, and can use the 'name' and
+ * 'len' information without worrying about walking off the
+ * end of memory etc.
+ *
+ * Thus the read_seqcount_retry() and the "duplicate" info
+ * in arguments (the low-level filesystem should not look
+ * at the dentry inode or name contents directly, since
+ * rename can change them while we're in RCU mode).
+ */
+enum slow_d_compare {
+ D_COMP_OK,
+ D_COMP_NOMATCH,
+ D_COMP_SEQRETRY,
+};
+
+static noinline enum slow_d_compare slow_dentry_cmp(
+ const struct dentry *parent,
+ struct inode *inode,
+ struct dentry *dentry,
+ unsigned int seq,
+ const struct qstr *name)
+{
+ int tlen = dentry->d_name.len;
+ const char *tname = dentry->d_name.name;
+ struct inode *i = dentry->d_inode;
+
+ if (read_seqcount_retry(&dentry->d_seq, seq)) {
+ cpu_relax();
+ return D_COMP_SEQRETRY;
+ }
+ if (parent->d_op->d_compare(parent, inode,
+ dentry, i,
+ tlen, tname, name))
+ return D_COMP_NOMATCH;
+ return D_COMP_OK;
+}
+
/**
* __d_lookup_rcu - search for a dentry (racy, store-free)
* @parent: parent dentry
@@ -1753,15 +1821,17 @@ EXPORT_SYMBOL(d_add_ci);
* the returned dentry, so long as its parent's seqlock is checked after the
* child is looked up. Thus, an interlocking stepping of sequence lock checks
* is formed, giving integrity down the path walk.
+ *
+ * NOTE! The caller *has* to check the resulting dentry against the sequence
+ * number we've returned before using any of the resulting dentry state!
*/
struct dentry *__d_lookup_rcu(const struct dentry *parent,
const struct qstr *name,
- unsigned *seqp, struct inode **inode)
+ unsigned *seqp, struct inode *inode)
{
- unsigned int len = name->len;
- unsigned int hash = name->hash;
+ u64 hashlen = name->hash_len;
const unsigned char *str = name->name;
- struct hlist_bl_head *b = d_hash(parent, hash);
+ struct hlist_bl_head *b = d_hash(parent, hashlen_hash(hashlen));
struct hlist_bl_node *node;
struct dentry *dentry;
@@ -1787,49 +1857,47 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent,
*/
hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {
unsigned seq;
- struct inode *i;
- const char *tname;
- int tlen;
-
- if (dentry->d_name.hash != hash)
- continue;
seqretry:
- seq = read_seqcount_begin(&dentry->d_seq);
+ /*
+ * The dentry sequence count protects us from concurrent
+ * renames, and thus protects inode, parent and name fields.
+ *
+ * The caller must perform a seqcount check in order
+ * to do anything useful with the returned dentry,
+ * including using the 'd_inode' pointer.
+ *
+ * NOTE! We do a "raw" seqcount_begin here. That means that
+ * we don't wait for the sequence count to stabilize if it
+ * is in the middle of a sequence change. If we do the slow
+ * dentry compare, we will do seqretries until it is stable,
+ * and if we end up with a successful lookup, we actually
+ * want to exit RCU lookup anyway.
+ */
+ seq = raw_seqcount_begin(&dentry->d_seq);
if (dentry->d_parent != parent)
continue;
if (d_unhashed(dentry))
continue;
- tlen = dentry->d_name.len;
- tname = dentry->d_name.name;
- i = dentry->d_inode;
- prefetch(tname);
- /*
- * This seqcount check is required to ensure name and
- * len are loaded atomically, so as not to walk off the
- * edge of memory when walking. If we could load this
- * atomically some other way, we could drop this check.
- */
- if (read_seqcount_retry(&dentry->d_seq, seq))
- goto seqretry;
+ *seqp = seq;
+
if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) {
- if (parent->d_op->d_compare(parent, *inode,
- dentry, i,
- tlen, tname, name))
+ if (dentry->d_name.hash != hashlen_hash(hashlen))
continue;
- } else {
- if (dentry_cmp(tname, tlen, str, len))
+ switch (slow_dentry_cmp(parent, inode, dentry, seq, name)) {
+ case D_COMP_OK:
+ return dentry;
+ case D_COMP_NOMATCH:
continue;
+ default:
+ goto seqretry;
+ }
}
- /*
- * No extra seqcount check is required after the name
- * compare. The caller must perform a seqcount check in
- * order to do anything useful with the returned dentry
- * anyway.
- */
- *seqp = seq;
- *inode = i;
- return dentry;
+
+ if (dentry->d_name.hash_len != hashlen)
+ continue;
+ if (!dentry_cmp(dentry, str, hashlen_len(hashlen)))
+ return dentry;
}
return NULL;
}
@@ -1908,8 +1976,6 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name)
rcu_read_lock();
hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {
- const char *tname;
- int tlen;
if (dentry->d_name.hash != hash)
continue;
@@ -1924,15 +1990,17 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name)
* It is safe to compare names since d_move() cannot
* change the qstr (protected by d_lock).
*/
- tlen = dentry->d_name.len;
- tname = dentry->d_name.name;
if (parent->d_flags & DCACHE_OP_COMPARE) {
+ int tlen = dentry->d_name.len;
+ const char *tname = dentry->d_name.name;
if (parent->d_op->d_compare(parent, parent->d_inode,
dentry, dentry->d_inode,
tlen, tname, name))
goto next;
} else {
- if (dentry_cmp(tname, tlen, str, len))
+ if (dentry->d_name.len != len)
+ goto next;
+ if (dentry_cmp(dentry, str, len))
goto next;
}
diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c
index 90e5997262ea..63dc19c54d5a 100644
--- a/fs/dlm/ast.c
+++ b/fs/dlm/ast.c
@@ -310,6 +310,7 @@ void dlm_callback_resume(struct dlm_ls *ls)
}
mutex_unlock(&ls->ls_cb_mutex);
- log_debug(ls, "dlm_callback_resume %d", count);
+ if (count)
+ log_debug(ls, "dlm_callback_resume %d", count);
}
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 3a564d197e99..bc342f7ac3af 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -38,6 +38,7 @@
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/idr.h>
+#include <linux/ratelimit.h>
#include <asm/uaccess.h>
#include <linux/dlm.h>
@@ -74,6 +75,13 @@ do { \
(ls)->ls_name , ##args); \
} while (0)
+#define log_limit(ls, fmt, args...) \
+do { \
+ if (dlm_config.ci_log_debug) \
+ printk_ratelimited(KERN_DEBUG "dlm: %s: " fmt "\n", \
+ (ls)->ls_name , ##args); \
+} while (0)
+
#define DLM_ASSERT(x, do) \
{ \
if (!(x)) \
@@ -263,6 +271,8 @@ struct dlm_lkb {
ktime_t lkb_last_cast_time; /* for debugging */
ktime_t lkb_last_bast_time; /* for debugging */
+ uint64_t lkb_recover_seq; /* from ls_recover_seq */
+
char *lkb_lvbptr;
struct dlm_lksb *lkb_lksb; /* caller's status block */
void (*lkb_astfn) (void *astparam);
@@ -317,7 +327,7 @@ enum rsb_flags {
RSB_NEW_MASTER,
RSB_NEW_MASTER2,
RSB_RECOVER_CONVERT,
- RSB_LOCKS_PURGED,
+ RSB_RECOVER_GRANT,
};
static inline void rsb_set_flag(struct dlm_rsb *r, enum rsb_flags flag)
@@ -563,6 +573,7 @@ struct dlm_ls {
struct mutex ls_requestqueue_mutex;
struct dlm_rcom *ls_recover_buf;
int ls_recover_nodeid; /* for debugging */
+ unsigned int ls_recover_locks_in; /* for log info */
uint64_t ls_rcom_seq;
spinlock_t ls_rcom_spin;
struct list_head ls_recover_list;
@@ -589,6 +600,7 @@ struct dlm_ls {
#define LSFL_UEVENT_WAIT 5
#define LSFL_TIMEWARN 6
#define LSFL_CB_DELAY 7
+#define LSFL_NODIR 8
/* much of this is just saving user space pointers associated with the
lock that we pass back to the user lib with an ast */
@@ -636,7 +648,7 @@ static inline int dlm_recovery_stopped(struct dlm_ls *ls)
static inline int dlm_no_directory(struct dlm_ls *ls)
{
- return (ls->ls_exflags & DLM_LSFL_NODIR) ? 1 : 0;
+ return test_bit(LSFL_NODIR, &ls->ls_flags);
}
int dlm_netlink_init(void);
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 4c58d4a3adc4..bdafb65a5234 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -160,11 +160,12 @@ static const int __quecvt_compat_matrix[8][8] = {
void dlm_print_lkb(struct dlm_lkb *lkb)
{
- printk(KERN_ERR "lkb: nodeid %d id %x remid %x exflags %x flags %x\n"
- " status %d rqmode %d grmode %d wait_type %d\n",
+ printk(KERN_ERR "lkb: nodeid %d id %x remid %x exflags %x flags %x "
+ "sts %d rq %d gr %d wait_type %d wait_nodeid %d seq %llu\n",
lkb->lkb_nodeid, lkb->lkb_id, lkb->lkb_remid, lkb->lkb_exflags,
lkb->lkb_flags, lkb->lkb_status, lkb->lkb_rqmode,
- lkb->lkb_grmode, lkb->lkb_wait_type);
+ lkb->lkb_grmode, lkb->lkb_wait_type, lkb->lkb_wait_nodeid,
+ (unsigned long long)lkb->lkb_recover_seq);
}
static void dlm_print_rsb(struct dlm_rsb *r)
@@ -251,8 +252,6 @@ static inline int is_process_copy(struct dlm_lkb *lkb)
static inline int is_master_copy(struct dlm_lkb *lkb)
{
- if (lkb->lkb_flags & DLM_IFL_MSTCPY)
- DLM_ASSERT(lkb->lkb_nodeid, dlm_print_lkb(lkb););
return (lkb->lkb_flags & DLM_IFL_MSTCPY) ? 1 : 0;
}
@@ -479,6 +478,9 @@ static int _search_rsb(struct dlm_ls *ls, char *name, int len, int b,
kref_get(&r->res_ref);
goto out;
}
+ if (error == -ENOTBLK)
+ goto out;
+
error = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].toss, name, len, flags, &r);
if (error)
goto out;
@@ -586,6 +588,23 @@ static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
return error;
}
+static void dlm_dump_rsb_hash(struct dlm_ls *ls, uint32_t hash)
+{
+ struct rb_node *n;
+ struct dlm_rsb *r;
+ int i;
+
+ for (i = 0; i < ls->ls_rsbtbl_size; i++) {
+ spin_lock(&ls->ls_rsbtbl[i].lock);
+ for (n = rb_first(&ls->ls_rsbtbl[i].keep); n; n = rb_next(n)) {
+ r = rb_entry(n, struct dlm_rsb, res_hashnode);
+ if (r->res_hash == hash)
+ dlm_dump_rsb(r);
+ }
+ spin_unlock(&ls->ls_rsbtbl[i].lock);
+ }
+}
+
/* This is only called to add a reference when the code already holds
a valid reference to the rsb, so there's no need for locking. */
@@ -1064,8 +1083,9 @@ static int _remove_from_waiters(struct dlm_lkb *lkb, int mstype,
goto out_del;
}
- log_error(ls, "remwait error %x reply %d flags %x no wait_type",
- lkb->lkb_id, mstype, lkb->lkb_flags);
+ log_error(ls, "remwait error %x remote %d %x msg %d flags %x no wait",
+ lkb->lkb_id, ms ? ms->m_header.h_nodeid : 0, lkb->lkb_remid,
+ mstype, lkb->lkb_flags);
return -1;
out_del:
@@ -1498,13 +1518,13 @@ static void _grant_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
}
lkb->lkb_rqmode = DLM_LOCK_IV;
+ lkb->lkb_highbast = 0;
}
static void grant_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
{
set_lvb_lock(r, lkb);
_grant_lock(r, lkb);
- lkb->lkb_highbast = 0;
}
static void grant_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb,
@@ -1866,7 +1886,8 @@ static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now,
/* Returns the highest requested mode of all blocked conversions; sets
cw if there's a blocked conversion to DLM_LOCK_CW. */
-static int grant_pending_convert(struct dlm_rsb *r, int high, int *cw)
+static int grant_pending_convert(struct dlm_rsb *r, int high, int *cw,
+ unsigned int *count)
{
struct dlm_lkb *lkb, *s;
int hi, demoted, quit, grant_restart, demote_restart;
@@ -1885,6 +1906,8 @@ static int grant_pending_convert(struct dlm_rsb *r, int high, int *cw)
if (can_be_granted(r, lkb, 0, &deadlk)) {
grant_lock_pending(r, lkb);
grant_restart = 1;
+ if (count)
+ (*count)++;
continue;
}
@@ -1918,14 +1941,17 @@ static int grant_pending_convert(struct dlm_rsb *r, int high, int *cw)
return max_t(int, high, hi);
}
-static int grant_pending_wait(struct dlm_rsb *r, int high, int *cw)
+static int grant_pending_wait(struct dlm_rsb *r, int high, int *cw,
+ unsigned int *count)
{
struct dlm_lkb *lkb, *s;
list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) {
- if (can_be_granted(r, lkb, 0, NULL))
+ if (can_be_granted(r, lkb, 0, NULL)) {
grant_lock_pending(r, lkb);
- else {
+ if (count)
+ (*count)++;
+ } else {
high = max_t(int, lkb->lkb_rqmode, high);
if (lkb->lkb_rqmode == DLM_LOCK_CW)
*cw = 1;
@@ -1954,16 +1980,20 @@ static int lock_requires_bast(struct dlm_lkb *gr, int high, int cw)
return 0;
}
-static void grant_pending_locks(struct dlm_rsb *r)
+static void grant_pending_locks(struct dlm_rsb *r, unsigned int *count)
{
struct dlm_lkb *lkb, *s;
int high = DLM_LOCK_IV;
int cw = 0;
- DLM_ASSERT(is_master(r), dlm_dump_rsb(r););
+ if (!is_master(r)) {
+ log_print("grant_pending_locks r nodeid %d", r->res_nodeid);
+ dlm_dump_rsb(r);
+ return;
+ }
- high = grant_pending_convert(r, high, &cw);
- high = grant_pending_wait(r, high, &cw);
+ high = grant_pending_convert(r, high, &cw, count);
+ high = grant_pending_wait(r, high, &cw, count);
if (high == DLM_LOCK_IV)
return;
@@ -2499,7 +2529,7 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
before we try again to grant this one. */
if (is_demoted(lkb)) {
- grant_pending_convert(r, DLM_LOCK_IV, NULL);
+ grant_pending_convert(r, DLM_LOCK_IV, NULL, NULL);
if (_can_be_granted(r, lkb, 1)) {
grant_lock(r, lkb);
queue_cast(r, lkb, 0);
@@ -2527,7 +2557,7 @@ static void do_convert_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
{
switch (error) {
case 0:
- grant_pending_locks(r);
+ grant_pending_locks(r, NULL);
/* grant_pending_locks also sends basts */
break;
case -EAGAIN:
@@ -2550,7 +2580,7 @@ static int do_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb)
static void do_unlock_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
int error)
{
- grant_pending_locks(r);
+ grant_pending_locks(r, NULL);
}
/* returns: 0 did nothing, -DLM_ECANCEL canceled lock */
@@ -2571,7 +2601,7 @@ static void do_cancel_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
int error)
{
if (error)
- grant_pending_locks(r);
+ grant_pending_locks(r, NULL);
}
/*
@@ -3372,7 +3402,7 @@ static int validate_message(struct dlm_lkb *lkb, struct dlm_message *ms)
return error;
}
-static void receive_request(struct dlm_ls *ls, struct dlm_message *ms)
+static int receive_request(struct dlm_ls *ls, struct dlm_message *ms)
{
struct dlm_lkb *lkb;
struct dlm_rsb *r;
@@ -3412,14 +3442,15 @@ static void receive_request(struct dlm_ls *ls, struct dlm_message *ms)
error = 0;
if (error)
dlm_put_lkb(lkb);
- return;
+ return 0;
fail:
setup_stub_lkb(ls, ms);
send_request_reply(&ls->ls_stub_rsb, &ls->ls_stub_lkb, error);
+ return error;
}
-static void receive_convert(struct dlm_ls *ls, struct dlm_message *ms)
+static int receive_convert(struct dlm_ls *ls, struct dlm_message *ms)
{
struct dlm_lkb *lkb;
struct dlm_rsb *r;
@@ -3429,6 +3460,15 @@ static void receive_convert(struct dlm_ls *ls, struct dlm_message *ms)
if (error)
goto fail;
+ if (lkb->lkb_remid != ms->m_lkid) {
+ log_error(ls, "receive_convert %x remid %x recover_seq %llu "
+ "remote %d %x", lkb->lkb_id, lkb->lkb_remid,
+ (unsigned long long)lkb->lkb_recover_seq,
+ ms->m_header.h_nodeid, ms->m_lkid);
+ error = -ENOENT;
+ goto fail;
+ }
+
r = lkb->lkb_resource;
hold_rsb(r);
@@ -3456,14 +3496,15 @@ static void receive_convert(struct dlm_ls *ls, struct dlm_message *ms)
unlock_rsb(r);
put_rsb(r);
dlm_put_lkb(lkb);
- return;
+ return 0;
fail:
setup_stub_lkb(ls, ms);
send_convert_reply(&ls->ls_stub_rsb, &ls->ls_stub_lkb, error);
+ return error;
}
-static void receive_unlock(struct dlm_ls *ls, struct dlm_message *ms)
+static int receive_unlock(struct dlm_ls *ls, struct dlm_message *ms)
{
struct dlm_lkb *lkb;
struct dlm_rsb *r;
@@ -3473,6 +3514,14 @@ static void receive_unlock(struct dlm_ls *ls, struct dlm_message *ms)
if (error)
goto fail;
+ if (lkb->lkb_remid != ms->m_lkid) {
+ log_error(ls, "receive_unlock %x remid %x remote %d %x",
+ lkb->lkb_id, lkb->lkb_remid,
+ ms->m_header.h_nodeid, ms->m_lkid);
+ error = -ENOENT;
+ goto fail;
+ }
+
r = lkb->lkb_resource;
hold_rsb(r);
@@ -3497,14 +3546,15 @@ static void receive_unlock(struct dlm_ls *ls, struct dlm_message *ms)
unlock_rsb(r);
put_rsb(r);
dlm_put_lkb(lkb);
- return;
+ return 0;
fail:
setup_stub_lkb(ls, ms);
send_unlock_reply(&ls->ls_stub_rsb, &ls->ls_stub_lkb, error);
+ return error;
}
-static void receive_cancel(struct dlm_ls *ls, struct dlm_message *ms)
+static int receive_cancel(struct dlm_ls *ls, struct dlm_message *ms)
{
struct dlm_lkb *lkb;
struct dlm_rsb *r;
@@ -3532,25 +3582,23 @@ static void receive_cancel(struct dlm_ls *ls, struct dlm_message *ms)
unlock_rsb(r);
put_rsb(r);
dlm_put_lkb(lkb);
- return;
+ return 0;
fail:
setup_stub_lkb(ls, ms);
send_cancel_reply(&ls->ls_stub_rsb, &ls->ls_stub_lkb, error);
+ return error;
}
-static void receive_grant(struct dlm_ls *ls, struct dlm_message *ms)
+static int receive_grant(struct dlm_ls *ls, struct dlm_message *ms)
{
struct dlm_lkb *lkb;
struct dlm_rsb *r;
int error;
error = find_lkb(ls, ms->m_remid, &lkb);
- if (error) {
- log_debug(ls, "receive_grant from %d no lkb %x",
- ms->m_header.h_nodeid, ms->m_remid);
- return;
- }
+ if (error)
+ return error;
r = lkb->lkb_resource;
@@ -3570,20 +3618,18 @@ static void receive_grant(struct dlm_ls *ls, struct dlm_message *ms)
unlock_rsb(r);
put_rsb(r);
dlm_put_lkb(lkb);
+ return 0;
}
-static void receive_bast(struct dlm_ls *ls, struct dlm_message *ms)
+static int receive_bast(struct dlm_ls *ls, struct dlm_message *ms)
{
struct dlm_lkb *lkb;
struct dlm_rsb *r;
int error;
error = find_lkb(ls, ms->m_remid, &lkb);
- if (error) {
- log_debug(ls, "receive_bast from %d no lkb %x",
- ms->m_header.h_nodeid, ms->m_remid);
- return;
- }
+ if (error)
+ return error;
r = lkb->lkb_resource;
@@ -3595,10 +3641,12 @@ static void receive_bast(struct dlm_ls *ls, struct dlm_message *ms)
goto out;
queue_bast(r, lkb, ms->m_bastmode);
+ lkb->lkb_highbast = ms->m_bastmode;
out:
unlock_rsb(r);
put_rsb(r);
dlm_put_lkb(lkb);
+ return 0;
}
static void receive_lookup(struct dlm_ls *ls, struct dlm_message *ms)
@@ -3653,18 +3701,15 @@ static void receive_purge(struct dlm_ls *ls, struct dlm_message *ms)
do_purge(ls, ms->m_nodeid, ms->m_pid);
}
-static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
+static int receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
{
struct dlm_lkb *lkb;
struct dlm_rsb *r;
int error, mstype, result;
error = find_lkb(ls, ms->m_remid, &lkb);
- if (error) {
- log_debug(ls, "receive_request_reply from %d no lkb %x",
- ms->m_header.h_nodeid, ms->m_remid);
- return;
- }
+ if (error)
+ return error;
r = lkb->lkb_resource;
hold_rsb(r);
@@ -3676,8 +3721,13 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
mstype = lkb->lkb_wait_type;
error = remove_from_waiters(lkb, DLM_MSG_REQUEST_REPLY);
- if (error)
+ if (error) {
+ log_error(ls, "receive_request_reply %x remote %d %x result %d",
+ lkb->lkb_id, ms->m_header.h_nodeid, ms->m_lkid,
+ ms->m_result);
+ dlm_dump_rsb(r);
goto out;
+ }
/* Optimization: the dir node was also the master, so it took our
lookup as a request and sent request reply instead of lookup reply */
@@ -3755,6 +3805,7 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
unlock_rsb(r);
put_rsb(r);
dlm_put_lkb(lkb);
+ return 0;
}
static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
@@ -3793,8 +3844,11 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
break;
default:
- log_error(r->res_ls, "receive_convert_reply %x error %d",
- lkb->lkb_id, ms->m_result);
+ log_error(r->res_ls, "receive_convert_reply %x remote %d %x %d",
+ lkb->lkb_id, ms->m_header.h_nodeid, ms->m_lkid,
+ ms->m_result);
+ dlm_print_rsb(r);
+ dlm_print_lkb(lkb);
}
}
@@ -3821,20 +3875,18 @@ static void _receive_convert_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
put_rsb(r);
}
-static void receive_convert_reply(struct dlm_ls *ls, struct dlm_message *ms)
+static int receive_convert_reply(struct dlm_ls *ls, struct dlm_message *ms)
{
struct dlm_lkb *lkb;
int error;
error = find_lkb(ls, ms->m_remid, &lkb);
- if (error) {
- log_debug(ls, "receive_convert_reply from %d no lkb %x",
- ms->m_header.h_nodeid, ms->m_remid);
- return;
- }
+ if (error)
+ return error;
_receive_convert_reply(lkb, ms);
dlm_put_lkb(lkb);
+ return 0;
}
static void _receive_unlock_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
@@ -3873,20 +3925,18 @@ static void _receive_unlock_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
put_rsb(r);
}
-static void receive_unlock_reply(struct dlm_ls *ls, struct dlm_message *ms)
+static int receive_unlock_reply(struct dlm_ls *ls, struct dlm_message *ms)
{
struct dlm_lkb *lkb;
int error;
error = find_lkb(ls, ms->m_remid, &lkb);
- if (error) {
- log_debug(ls, "receive_unlock_reply from %d no lkb %x",
- ms->m_header.h_nodeid, ms->m_remid);
- return;
- }
+ if (error)
+ return error;
_receive_unlock_reply(lkb, ms);
dlm_put_lkb(lkb);
+ return 0;
}
static void _receive_cancel_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
@@ -3925,20 +3975,18 @@ static void _receive_cancel_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
put_rsb(r);
}
-static void receive_cancel_reply(struct dlm_ls *ls, struct dlm_message *ms)
+static int receive_cancel_reply(struct dlm_ls *ls, struct dlm_message *ms)
{
struct dlm_lkb *lkb;
int error;
error = find_lkb(ls, ms->m_remid, &lkb);
- if (error) {
- log_debug(ls, "receive_cancel_reply from %d no lkb %x",
- ms->m_header.h_nodeid, ms->m_remid);
- return;
- }
+ if (error)
+ return error;
_receive_cancel_reply(lkb, ms);
dlm_put_lkb(lkb);
+ return 0;
}
static void receive_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms)
@@ -3949,7 +3997,7 @@ static void receive_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms)
error = find_lkb(ls, ms->m_lkid, &lkb);
if (error) {
- log_error(ls, "receive_lookup_reply no lkb");
+ log_error(ls, "receive_lookup_reply no lkid %x", ms->m_lkid);
return;
}
@@ -3993,8 +4041,11 @@ static void receive_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms)
dlm_put_lkb(lkb);
}
-static void _receive_message(struct dlm_ls *ls, struct dlm_message *ms)
+static void _receive_message(struct dlm_ls *ls, struct dlm_message *ms,
+ uint32_t saved_seq)
{
+ int error = 0, noent = 0;
+
if (!dlm_is_member(ls, ms->m_header.h_nodeid)) {
log_debug(ls, "ignore non-member message %d from %d %x %x %d",
ms->m_type, ms->m_header.h_nodeid, ms->m_lkid,
@@ -4007,47 +4058,50 @@ static void _receive_message(struct dlm_ls *ls, struct dlm_message *ms)
/* messages sent to a master node */
case DLM_MSG_REQUEST:
- receive_request(ls, ms);
+ error = receive_request(ls, ms);
break;
case DLM_MSG_CONVERT:
- receive_convert(ls, ms);
+ error = receive_convert(ls, ms);
break;
case DLM_MSG_UNLOCK:
- receive_unlock(ls, ms);
+ error = receive_unlock(ls, ms);
break;
case DLM_MSG_CANCEL:
- receive_cancel(ls, ms);
+ noent = 1;
+ error = receive_cancel(ls, ms);
break;
/* messages sent from a master node (replies to above) */
case DLM_MSG_REQUEST_REPLY:
- receive_request_reply(ls, ms);
+ error = receive_request_reply(ls, ms);
break;
case DLM_MSG_CONVERT_REPLY:
- receive_convert_reply(ls, ms);
+ error = receive_convert_reply(ls, ms);
break;
case DLM_MSG_UNLOCK_REPLY:
- receive_unlock_reply(ls, ms);
+ error = receive_unlock_reply(ls, ms);
break;
case DLM_MSG_CANCEL_REPLY:
- receive_cancel_reply(ls, ms);
+ error = receive_cancel_reply(ls, ms);
break;
/* messages sent from a master node (only two types of async msg) */
case DLM_MSG_GRANT:
- receive_grant(ls, ms);
+ noent = 1;
+ error = receive_grant(ls, ms);
break;
case DLM_MSG_BAST:
- receive_bast(ls, ms);
+ noent = 1;
+ error = receive_bast(ls, ms);
break;
/* messages sent to a dir node */
@@ -4075,6 +4129,37 @@ static void _receive_message(struct dlm_ls *ls, struct dlm_message *ms)
default:
log_error(ls, "unknown message type %d", ms->m_type);
}
+
+ /*
+ * When checking for ENOENT, we're checking the result of
+ * find_lkb(m_remid):
+ *
+ * The lock id referenced in the message wasn't found. This may
+ * happen in normal usage for the async messages and cancel, so
+ * only use log_debug for them.
+ *
+ * Some errors are expected and normal.
+ */
+
+ if (error == -ENOENT && noent) {
+ log_debug(ls, "receive %d no %x remote %d %x saved_seq %u",
+ ms->m_type, ms->m_remid, ms->m_header.h_nodeid,
+ ms->m_lkid, saved_seq);
+ } else if (error == -ENOENT) {
+ log_error(ls, "receive %d no %x remote %d %x saved_seq %u",
+ ms->m_type, ms->m_remid, ms->m_header.h_nodeid,
+ ms->m_lkid, saved_seq);
+
+ if (ms->m_type == DLM_MSG_CONVERT)
+ dlm_dump_rsb_hash(ls, ms->m_hash);
+ }
+
+ if (error == -EINVAL) {
+ log_error(ls, "receive %d inval from %d lkid %x remid %x "
+ "saved_seq %u",
+ ms->m_type, ms->m_header.h_nodeid,
+ ms->m_lkid, ms->m_remid, saved_seq);
+ }
}
/* If the lockspace is in recovery mode (locking stopped), then normal
@@ -4092,16 +4177,17 @@ static void dlm_receive_message(struct dlm_ls *ls, struct dlm_message *ms,
dlm_add_requestqueue(ls, nodeid, ms);
} else {
dlm_wait_requestqueue(ls);
- _receive_message(ls, ms);
+ _receive_message(ls, ms, 0);
}
}
/* This is called by dlm_recoverd to process messages that were saved on
the requestqueue. */
-void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms)
+void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms,
+ uint32_t saved_seq)
{
- _receive_message(ls, ms);
+ _receive_message(ls, ms, saved_seq);
}
/* This is called by the midcomms layer when something is received for
@@ -4137,9 +4223,11 @@ void dlm_receive_buffer(union dlm_packet *p, int nodeid)
ls = dlm_find_lockspace_global(hd->h_lockspace);
if (!ls) {
- if (dlm_config.ci_log_debug)
- log_print("invalid lockspace %x from %d cmd %d type %d",
- hd->h_lockspace, nodeid, hd->h_cmd, type);
+ if (dlm_config.ci_log_debug) {
+ printk_ratelimited(KERN_DEBUG "dlm: invalid lockspace "
+ "%u from %d cmd %d type %d\n",
+ hd->h_lockspace, nodeid, hd->h_cmd, type);
+ }
if (hd->h_cmd == DLM_RCOM && type == DLM_RCOM_STATUS)
dlm_send_ls_not_ready(nodeid, &p->rcom);
@@ -4187,15 +4275,13 @@ static void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb,
/* A waiting lkb needs recovery if the master node has failed, or
the master node is changing (only when no directory is used) */
-static int waiter_needs_recovery(struct dlm_ls *ls, struct dlm_lkb *lkb)
+static int waiter_needs_recovery(struct dlm_ls *ls, struct dlm_lkb *lkb,
+ int dir_nodeid)
{
- if (dlm_is_removed(ls, lkb->lkb_nodeid))
+ if (dlm_no_directory(ls))
return 1;
- if (!dlm_no_directory(ls))
- return 0;
-
- if (dlm_dir_nodeid(lkb->lkb_resource) != lkb->lkb_nodeid)
+ if (dlm_is_removed(ls, lkb->lkb_wait_nodeid))
return 1;
return 0;
@@ -4212,6 +4298,7 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
struct dlm_lkb *lkb, *safe;
struct dlm_message *ms_stub;
int wait_type, stub_unlock_result, stub_cancel_result;
+ int dir_nodeid;
ms_stub = kmalloc(sizeof(struct dlm_message), GFP_KERNEL);
if (!ms_stub) {
@@ -4223,13 +4310,21 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
list_for_each_entry_safe(lkb, safe, &ls->ls_waiters, lkb_wait_reply) {
+ dir_nodeid = dlm_dir_nodeid(lkb->lkb_resource);
+
/* exclude debug messages about unlocks because there can be so
many and they aren't very interesting */
if (lkb->lkb_wait_type != DLM_MSG_UNLOCK) {
- log_debug(ls, "recover_waiter %x nodeid %d "
- "msg %d to %d", lkb->lkb_id, lkb->lkb_nodeid,
- lkb->lkb_wait_type, lkb->lkb_wait_nodeid);
+ log_debug(ls, "waiter %x remote %x msg %d r_nodeid %d "
+ "lkb_nodeid %d wait_nodeid %d dir_nodeid %d",
+ lkb->lkb_id,
+ lkb->lkb_remid,
+ lkb->lkb_wait_type,
+ lkb->lkb_resource->res_nodeid,
+ lkb->lkb_nodeid,
+ lkb->lkb_wait_nodeid,
+ dir_nodeid);
}
/* all outstanding lookups, regardless of destination will be
@@ -4240,7 +4335,7 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
continue;
}
- if (!waiter_needs_recovery(ls, lkb))
+ if (!waiter_needs_recovery(ls, lkb, dir_nodeid))
continue;
wait_type = lkb->lkb_wait_type;
@@ -4373,8 +4468,11 @@ int dlm_recover_waiters_post(struct dlm_ls *ls)
ou = is_overlap_unlock(lkb);
err = 0;
- log_debug(ls, "recover_waiter %x nodeid %d msg %d r_nodeid %d",
- lkb->lkb_id, lkb->lkb_nodeid, mstype, r->res_nodeid);
+ log_debug(ls, "waiter %x remote %x msg %d r_nodeid %d "
+ "lkb_nodeid %d wait_nodeid %d dir_nodeid %d "
+ "overlap %d %d", lkb->lkb_id, lkb->lkb_remid, mstype,
+ r->res_nodeid, lkb->lkb_nodeid, lkb->lkb_wait_nodeid,
+ dlm_dir_nodeid(r), oc, ou);
/* At this point we assume that we won't get a reply to any
previous op or overlap op on this lock. First, do a big
@@ -4426,9 +4524,12 @@ int dlm_recover_waiters_post(struct dlm_ls *ls)
}
}
- if (err)
- log_error(ls, "recover_waiters_post %x %d %x %d %d",
- lkb->lkb_id, mstype, lkb->lkb_flags, oc, ou);
+ if (err) {
+ log_error(ls, "waiter %x msg %d r_nodeid %d "
+ "dir_nodeid %d overlap %d %d",
+ lkb->lkb_id, mstype, r->res_nodeid,
+ dlm_dir_nodeid(r), oc, ou);
+ }
unlock_rsb(r);
put_rsb(r);
dlm_put_lkb(lkb);
@@ -4437,112 +4538,177 @@ int dlm_recover_waiters_post(struct dlm_ls *ls)
return error;
}
-static void purge_queue(struct dlm_rsb *r, struct list_head *queue,
- int (*test)(struct dlm_ls *ls, struct dlm_lkb *lkb))
+static void purge_mstcpy_list(struct dlm_ls *ls, struct dlm_rsb *r,
+ struct list_head *list)
{
- struct dlm_ls *ls = r->res_ls;
struct dlm_lkb *lkb, *safe;
- list_for_each_entry_safe(lkb, safe, queue, lkb_statequeue) {
- if (test(ls, lkb)) {
- rsb_set_flag(r, RSB_LOCKS_PURGED);
- del_lkb(r, lkb);
- /* this put should free the lkb */
- if (!dlm_put_lkb(lkb))
- log_error(ls, "purged lkb not released");
- }
+ list_for_each_entry_safe(lkb, safe, list, lkb_statequeue) {
+ if (!is_master_copy(lkb))
+ continue;
+
+ /* don't purge lkbs we've added in recover_master_copy for
+ the current recovery seq */
+
+ if (lkb->lkb_recover_seq == ls->ls_recover_seq)
+ continue;
+
+ del_lkb(r, lkb);
+
+ /* this put should free the lkb */
+ if (!dlm_put_lkb(lkb))
+ log_error(ls, "purged mstcpy lkb not released");
}
}
-static int purge_dead_test(struct dlm_ls *ls, struct dlm_lkb *lkb)
+void dlm_purge_mstcpy_locks(struct dlm_rsb *r)
{
- return (is_master_copy(lkb) && dlm_is_removed(ls, lkb->lkb_nodeid));
-}
+ struct dlm_ls *ls = r->res_ls;
-static int purge_mstcpy_test(struct dlm_ls *ls, struct dlm_lkb *lkb)
-{
- return is_master_copy(lkb);
+ purge_mstcpy_list(ls, r, &r->res_grantqueue);
+ purge_mstcpy_list(ls, r, &r->res_convertqueue);
+ purge_mstcpy_list(ls, r, &r->res_waitqueue);
}
-static void purge_dead_locks(struct dlm_rsb *r)
+static void purge_dead_list(struct dlm_ls *ls, struct dlm_rsb *r,
+ struct list_head *list,
+ int nodeid_gone, unsigned int *count)
{
- purge_queue(r, &r->res_grantqueue, &purge_dead_test);
- purge_queue(r, &r->res_convertqueue, &purge_dead_test);
- purge_queue(r, &r->res_waitqueue, &purge_dead_test);
-}
+ struct dlm_lkb *lkb, *safe;
-void dlm_purge_mstcpy_locks(struct dlm_rsb *r)
-{
- purge_queue(r, &r->res_grantqueue, &purge_mstcpy_test);
- purge_queue(r, &r->res_convertqueue, &purge_mstcpy_test);
- purge_queue(r, &r->res_waitqueue, &purge_mstcpy_test);
+ list_for_each_entry_safe(lkb, safe, list, lkb_statequeue) {
+ if (!is_master_copy(lkb))
+ continue;
+
+ if ((lkb->lkb_nodeid == nodeid_gone) ||
+ dlm_is_removed(ls, lkb->lkb_nodeid)) {
+
+ del_lkb(r, lkb);
+
+ /* this put should free the lkb */
+ if (!dlm_put_lkb(lkb))
+ log_error(ls, "purged dead lkb not released");
+
+ rsb_set_flag(r, RSB_RECOVER_GRANT);
+
+ (*count)++;
+ }
+ }
}
/* Get rid of locks held by nodes that are gone. */
-int dlm_purge_locks(struct dlm_ls *ls)
+void dlm_recover_purge(struct dlm_ls *ls)
{
struct dlm_rsb *r;
+ struct dlm_member *memb;
+ int nodes_count = 0;
+ int nodeid_gone = 0;
+ unsigned int lkb_count = 0;
- log_debug(ls, "dlm_purge_locks");
+ /* cache one removed nodeid to optimize the common
+ case of a single node removed */
+
+ list_for_each_entry(memb, &ls->ls_nodes_gone, list) {
+ nodes_count++;
+ nodeid_gone = memb->nodeid;
+ }
+
+ if (!nodes_count)
+ return;
down_write(&ls->ls_root_sem);
list_for_each_entry(r, &ls->ls_root_list, res_root_list) {
hold_rsb(r);
lock_rsb(r);
- if (is_master(r))
- purge_dead_locks(r);
+ if (is_master(r)) {
+ purge_dead_list(ls, r, &r->res_grantqueue,
+ nodeid_gone, &lkb_count);
+ purge_dead_list(ls, r, &r->res_convertqueue,
+ nodeid_gone, &lkb_count);
+ purge_dead_list(ls, r, &r->res_waitqueue,
+ nodeid_gone, &lkb_count);
+ }
unlock_rsb(r);
unhold_rsb(r);
-
- schedule();
+ cond_resched();
}
up_write(&ls->ls_root_sem);
- return 0;
+ if (lkb_count)
+ log_debug(ls, "dlm_recover_purge %u locks for %u nodes",
+ lkb_count, nodes_count);
}
-static struct dlm_rsb *find_purged_rsb(struct dlm_ls *ls, int bucket)
+static struct dlm_rsb *find_grant_rsb(struct dlm_ls *ls, int bucket)
{
struct rb_node *n;
- struct dlm_rsb *r, *r_ret = NULL;
+ struct dlm_rsb *r;
spin_lock(&ls->ls_rsbtbl[bucket].lock);
for (n = rb_first(&ls->ls_rsbtbl[bucket].keep); n; n = rb_next(n)) {
r = rb_entry(n, struct dlm_rsb, res_hashnode);
- if (!rsb_flag(r, RSB_LOCKS_PURGED))
+
+ if (!rsb_flag(r, RSB_RECOVER_GRANT))
+ continue;
+ rsb_clear_flag(r, RSB_RECOVER_GRANT);
+ if (!is_master(r))
continue;
hold_rsb(r);
- rsb_clear_flag(r, RSB_LOCKS_PURGED);
- r_ret = r;
- break;
+ spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+ return r;
}
spin_unlock(&ls->ls_rsbtbl[bucket].lock);
- return r_ret;
+ return NULL;
}
-void dlm_grant_after_purge(struct dlm_ls *ls)
+/*
+ * Attempt to grant locks on resources that we are the master of.
+ * Locks may have become grantable during recovery because locks
+ * from departed nodes have been purged (or not rebuilt), allowing
+ * previously blocked locks to now be granted. The subset of rsb's
+ * we are interested in are those with lkb's on either the convert or
+ * waiting queues.
+ *
+ * Simplest would be to go through each master rsb and check for non-empty
+ * convert or waiting queues, and attempt to grant on those rsbs.
+ * Checking the queues requires lock_rsb, though, for which we'd need
+ * to release the rsbtbl lock. This would make iterating through all
+ * rsb's very inefficient. So, we rely on earlier recovery routines
+ * to set RECOVER_GRANT on any rsb's that we should attempt to grant
+ * locks for.
+ */
+
+void dlm_recover_grant(struct dlm_ls *ls)
{
struct dlm_rsb *r;
int bucket = 0;
+ unsigned int count = 0;
+ unsigned int rsb_count = 0;
+ unsigned int lkb_count = 0;
while (1) {
- r = find_purged_rsb(ls, bucket);
+ r = find_grant_rsb(ls, bucket);
if (!r) {
if (bucket == ls->ls_rsbtbl_size - 1)
break;
bucket++;
continue;
}
+ rsb_count++;
+ count = 0;
lock_rsb(r);
- if (is_master(r)) {
- grant_pending_locks(r);
- confirm_master(r, 0);
- }
+ grant_pending_locks(r, &count);
+ lkb_count += count;
+ confirm_master(r, 0);
unlock_rsb(r);
put_rsb(r);
- schedule();
+ cond_resched();
}
+
+ if (lkb_count)
+ log_debug(ls, "dlm_recover_grant %u locks on %u resources",
+ lkb_count, rsb_count);
}
static struct dlm_lkb *search_remid_list(struct list_head *head, int nodeid,
@@ -4631,6 +4797,7 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf;
struct dlm_rsb *r;
struct dlm_lkb *lkb;
+ uint32_t remid = 0;
int error;
if (rl->rl_parent_lkid) {
@@ -4638,14 +4805,31 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
goto out;
}
- error = find_rsb(ls, rl->rl_name, le16_to_cpu(rl->rl_namelen),
- R_MASTER, &r);
+ remid = le32_to_cpu(rl->rl_lkid);
+
+ /* In general we expect the rsb returned to be R_MASTER, but we don't
+ have to require it. Recovery of masters on one node can overlap
+ recovery of locks on another node, so one node can send us MSTCPY
+ locks before we've made ourselves master of this rsb. We can still
+ add new MSTCPY locks that we receive here without any harm; when
+ we make ourselves master, dlm_recover_masters() won't touch the
+ MSTCPY locks we've received early. */
+
+ error = find_rsb(ls, rl->rl_name, le16_to_cpu(rl->rl_namelen), 0, &r);
if (error)
goto out;
+ if (dlm_no_directory(ls) && (dlm_dir_nodeid(r) != dlm_our_nodeid())) {
+ log_error(ls, "dlm_recover_master_copy remote %d %x not dir",
+ rc->rc_header.h_nodeid, remid);
+ error = -EBADR;
+ put_rsb(r);
+ goto out;
+ }
+
lock_rsb(r);
- lkb = search_remid(r, rc->rc_header.h_nodeid, le32_to_cpu(rl->rl_lkid));
+ lkb = search_remid(r, rc->rc_header.h_nodeid, remid);
if (lkb) {
error = -EEXIST;
goto out_remid;
@@ -4664,19 +4848,25 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
attach_lkb(r, lkb);
add_lkb(r, lkb, rl->rl_status);
error = 0;
+ ls->ls_recover_locks_in++;
+
+ if (!list_empty(&r->res_waitqueue) || !list_empty(&r->res_convertqueue))
+ rsb_set_flag(r, RSB_RECOVER_GRANT);
out_remid:
/* this is the new value returned to the lock holder for
saving in its process-copy lkb */
rl->rl_remid = cpu_to_le32(lkb->lkb_id);
+ lkb->lkb_recover_seq = ls->ls_recover_seq;
+
out_unlock:
unlock_rsb(r);
put_rsb(r);
out:
- if (error)
- log_debug(ls, "recover_master_copy %d %x", error,
- le32_to_cpu(rl->rl_lkid));
+ if (error && error != -EEXIST)
+ log_debug(ls, "dlm_recover_master_copy remote %d %x error %d",
+ rc->rc_header.h_nodeid, remid, error);
rl->rl_result = cpu_to_le32(error);
return error;
}
@@ -4687,41 +4877,52 @@ int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf;
struct dlm_rsb *r;
struct dlm_lkb *lkb;
- int error;
+ uint32_t lkid, remid;
+ int error, result;
+
+ lkid = le32_to_cpu(rl->rl_lkid);
+ remid = le32_to_cpu(rl->rl_remid);
+ result = le32_to_cpu(rl->rl_result);
- error = find_lkb(ls, le32_to_cpu(rl->rl_lkid), &lkb);
+ error = find_lkb(ls, lkid, &lkb);
if (error) {
- log_error(ls, "recover_process_copy no lkid %x",
- le32_to_cpu(rl->rl_lkid));
+ log_error(ls, "dlm_recover_process_copy no %x remote %d %x %d",
+ lkid, rc->rc_header.h_nodeid, remid, result);
return error;
}
- DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb););
-
- error = le32_to_cpu(rl->rl_result);
-
r = lkb->lkb_resource;
hold_rsb(r);
lock_rsb(r);
- switch (error) {
+ if (!is_process_copy(lkb)) {
+ log_error(ls, "dlm_recover_process_copy bad %x remote %d %x %d",
+ lkid, rc->rc_header.h_nodeid, remid, result);
+ dlm_dump_rsb(r);
+ unlock_rsb(r);
+ put_rsb(r);
+ dlm_put_lkb(lkb);
+ return -EINVAL;
+ }
+
+ switch (result) {
case -EBADR:
/* There's a chance the new master received our lock before
dlm_recover_master_reply(), this wouldn't happen if we did
a barrier between recover_masters and recover_locks. */
- log_debug(ls, "master copy not ready %x r %lx %s", lkb->lkb_id,
- (unsigned long)r, r->res_name);
+
+ log_debug(ls, "dlm_recover_process_copy %x remote %d %x %d",
+ lkid, rc->rc_header.h_nodeid, remid, result);
+
dlm_send_rcom_lock(r, lkb);
goto out;
case -EEXIST:
- log_debug(ls, "master copy exists %x", lkb->lkb_id);
- /* fall through */
case 0:
- lkb->lkb_remid = le32_to_cpu(rl->rl_remid);
+ lkb->lkb_remid = remid;
break;
default:
- log_error(ls, "dlm_recover_process_copy unknown error %d %x",
- error, lkb->lkb_id);
+ log_error(ls, "dlm_recover_process_copy %x remote %d %x %d unk",
+ lkid, rc->rc_header.h_nodeid, remid, result);
}
/* an ack for dlm_recover_locks() which waits for replies from
diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h
index 1a255307f6ff..c8b226c62807 100644
--- a/fs/dlm/lock.h
+++ b/fs/dlm/lock.h
@@ -15,7 +15,8 @@
void dlm_dump_rsb(struct dlm_rsb *r);
void dlm_print_lkb(struct dlm_lkb *lkb);
-void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms);
+void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms,
+ uint32_t saved_seq);
void dlm_receive_buffer(union dlm_packet *p, int nodeid);
int dlm_modes_compat(int mode1, int mode2);
void dlm_put_rsb(struct dlm_rsb *r);
@@ -31,9 +32,9 @@ void dlm_adjust_timeouts(struct dlm_ls *ls);
int dlm_search_rsb_tree(struct rb_root *tree, char *name, int len,
unsigned int flags, struct dlm_rsb **r_ret);
-int dlm_purge_locks(struct dlm_ls *ls);
+void dlm_recover_purge(struct dlm_ls *ls);
void dlm_purge_mstcpy_locks(struct dlm_rsb *r);
-void dlm_grant_after_purge(struct dlm_ls *ls);
+void dlm_recover_grant(struct dlm_ls *ls);
int dlm_recover_waiters_post(struct dlm_ls *ls);
void dlm_recover_waiters_pre(struct dlm_ls *ls);
int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index a1ea25face82..ca506abbdd3b 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -74,6 +74,19 @@ static ssize_t dlm_id_store(struct dlm_ls *ls, const char *buf, size_t len)
return len;
}
+static ssize_t dlm_nodir_show(struct dlm_ls *ls, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", dlm_no_directory(ls));
+}
+
+static ssize_t dlm_nodir_store(struct dlm_ls *ls, const char *buf, size_t len)
+{
+ int val = simple_strtoul(buf, NULL, 0);
+ if (val == 1)
+ set_bit(LSFL_NODIR, &ls->ls_flags);
+ return len;
+}
+
static ssize_t dlm_recover_status_show(struct dlm_ls *ls, char *buf)
{
uint32_t status = dlm_recover_status(ls);
@@ -107,6 +120,12 @@ static struct dlm_attr dlm_attr_id = {
.store = dlm_id_store
};
+static struct dlm_attr dlm_attr_nodir = {
+ .attr = {.name = "nodir", .mode = S_IRUGO | S_IWUSR},
+ .show = dlm_nodir_show,
+ .store = dlm_nodir_store
+};
+
static struct dlm_attr dlm_attr_recover_status = {
.attr = {.name = "recover_status", .mode = S_IRUGO},
.show = dlm_recover_status_show
@@ -121,6 +140,7 @@ static struct attribute *dlm_attrs[] = {
&dlm_attr_control.attr,
&dlm_attr_event.attr,
&dlm_attr_id.attr,
+ &dlm_attr_nodir.attr,
&dlm_attr_recover_status.attr,
&dlm_attr_recover_nodeid.attr,
NULL,
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 133ef6dc7cb7..5c1b0e38c7a4 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -142,6 +142,7 @@ struct writequeue_entry {
static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT];
static int dlm_local_count;
+static int dlm_allow_conn;
/* Work queues */
static struct workqueue_struct *recv_workqueue;
@@ -710,6 +711,13 @@ static int tcp_accept_from_sock(struct connection *con)
struct connection *newcon;
struct connection *addcon;
+ mutex_lock(&connections_lock);
+ if (!dlm_allow_conn) {
+ mutex_unlock(&connections_lock);
+ return -1;
+ }
+ mutex_unlock(&connections_lock);
+
memset(&peeraddr, 0, sizeof(peeraddr));
result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_STREAM,
IPPROTO_TCP, &newsock);
@@ -1503,6 +1511,7 @@ void dlm_lowcomms_stop(void)
socket activity.
*/
mutex_lock(&connections_lock);
+ dlm_allow_conn = 0;
foreach_conn(stop_conn);
mutex_unlock(&connections_lock);
@@ -1530,7 +1539,7 @@ int dlm_lowcomms_start(void)
if (!dlm_local_count) {
error = -ENOTCONN;
log_print("no local IP address has been set");
- goto out;
+ goto fail;
}
error = -ENOMEM;
@@ -1538,7 +1547,13 @@ int dlm_lowcomms_start(void)
__alignof__(struct connection), 0,
NULL);
if (!con_cache)
- goto out;
+ goto fail;
+
+ error = work_start();
+ if (error)
+ goto fail_destroy;
+
+ dlm_allow_conn = 1;
/* Start listening */
if (dlm_config.ci_protocol == 0)
@@ -1548,20 +1563,17 @@ int dlm_lowcomms_start(void)
if (error)
goto fail_unlisten;
- error = work_start();
- if (error)
- goto fail_unlisten;
-
return 0;
fail_unlisten:
+ dlm_allow_conn = 0;
con = nodeid2con(0,0);
if (con) {
close_connection(con, false);
kmem_cache_free(con_cache, con);
}
+fail_destroy:
kmem_cache_destroy(con_cache);
-
-out:
+fail:
return error;
}
diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c
index da64df7576e1..7cd24bccd4fe 100644
--- a/fs/dlm/memory.c
+++ b/fs/dlm/memory.c
@@ -21,21 +21,19 @@ static struct kmem_cache *rsb_cache;
int __init dlm_memory_init(void)
{
- int ret = 0;
-
lkb_cache = kmem_cache_create("dlm_lkb", sizeof(struct dlm_lkb),
__alignof__(struct dlm_lkb), 0, NULL);
if (!lkb_cache)
- ret = -ENOMEM;
+ return -ENOMEM;
rsb_cache = kmem_cache_create("dlm_rsb", sizeof(struct dlm_rsb),
__alignof__(struct dlm_rsb), 0, NULL);
if (!rsb_cache) {
kmem_cache_destroy(lkb_cache);
- ret = -ENOMEM;
+ return -ENOMEM;
}
- return ret;
+ return 0;
}
void dlm_memory_exit(void)
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c
index ac5c616c9696..64d3e2b958c7 100644
--- a/fs/dlm/rcom.c
+++ b/fs/dlm/rcom.c
@@ -486,47 +486,50 @@ int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
return 0;
}
-static int is_old_reply(struct dlm_ls *ls, struct dlm_rcom *rc)
+/* Called by dlm_recv; corresponds to dlm_receive_message() but special
+ recovery-only comms are sent through here. */
+
+void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
{
+ int lock_size = sizeof(struct dlm_rcom) + sizeof(struct rcom_lock);
+ int stop, reply = 0, lock = 0;
+ uint32_t status;
uint64_t seq;
- int rv = 0;
switch (rc->rc_type) {
+ case DLM_RCOM_LOCK:
+ lock = 1;
+ break;
+ case DLM_RCOM_LOCK_REPLY:
+ lock = 1;
+ reply = 1;
+ break;
case DLM_RCOM_STATUS_REPLY:
case DLM_RCOM_NAMES_REPLY:
case DLM_RCOM_LOOKUP_REPLY:
- case DLM_RCOM_LOCK_REPLY:
- spin_lock(&ls->ls_recover_lock);
- seq = ls->ls_recover_seq;
- spin_unlock(&ls->ls_recover_lock);
- if (rc->rc_seq_reply != seq) {
- log_debug(ls, "ignoring old reply %x from %d "
- "seq_reply %llx expect %llx",
- rc->rc_type, rc->rc_header.h_nodeid,
- (unsigned long long)rc->rc_seq_reply,
- (unsigned long long)seq);
- rv = 1;
- }
- }
- return rv;
-}
-
-/* Called by dlm_recv; corresponds to dlm_receive_message() but special
- recovery-only comms are sent through here. */
+ reply = 1;
+ };
-void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
-{
- int lock_size = sizeof(struct dlm_rcom) + sizeof(struct rcom_lock);
+ spin_lock(&ls->ls_recover_lock);
+ status = ls->ls_recover_status;
+ stop = test_bit(LSFL_RECOVERY_STOP, &ls->ls_flags);
+ seq = ls->ls_recover_seq;
+ spin_unlock(&ls->ls_recover_lock);
- if (dlm_recovery_stopped(ls) && (rc->rc_type != DLM_RCOM_STATUS)) {
- log_debug(ls, "ignoring recovery message %x from %d",
- rc->rc_type, nodeid);
+ if ((stop && (rc->rc_type != DLM_RCOM_STATUS)) ||
+ (reply && (rc->rc_seq_reply != seq)) ||
+ (lock && !(status & DLM_RS_DIR))) {
+ log_limit(ls, "dlm_receive_rcom ignore msg %d "
+ "from %d %llu %llu recover seq %llu sts %x gen %u",
+ rc->rc_type,
+ nodeid,
+ (unsigned long long)rc->rc_seq,
+ (unsigned long long)rc->rc_seq_reply,
+ (unsigned long long)seq,
+ status, ls->ls_generation);
goto out;
}
- if (is_old_reply(ls, rc))
- goto out;
-
switch (rc->rc_type) {
case DLM_RCOM_STATUS:
receive_rcom_status(ls, rc);
diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c
index 34d5adf1fce7..7554e4dac6bb 100644
--- a/fs/dlm/recover.c
+++ b/fs/dlm/recover.c
@@ -339,9 +339,12 @@ static void set_lock_master(struct list_head *queue, int nodeid)
{
struct dlm_lkb *lkb;
- list_for_each_entry(lkb, queue, lkb_statequeue)
- if (!(lkb->lkb_flags & DLM_IFL_MSTCPY))
+ list_for_each_entry(lkb, queue, lkb_statequeue) {
+ if (!(lkb->lkb_flags & DLM_IFL_MSTCPY)) {
lkb->lkb_nodeid = nodeid;
+ lkb->lkb_remid = 0;
+ }
+ }
}
static void set_master_lkbs(struct dlm_rsb *r)
@@ -354,18 +357,16 @@ static void set_master_lkbs(struct dlm_rsb *r)
/*
* Propagate the new master nodeid to locks
* The NEW_MASTER flag tells dlm_recover_locks() which rsb's to consider.
- * The NEW_MASTER2 flag tells recover_lvb() and set_locks_purged() which
+ * The NEW_MASTER2 flag tells recover_lvb() and recover_grant() which
* rsb's to consider.
*/
static void set_new_master(struct dlm_rsb *r, int nodeid)
{
- lock_rsb(r);
r->res_nodeid = nodeid;
set_master_lkbs(r);
rsb_set_flag(r, RSB_NEW_MASTER);
rsb_set_flag(r, RSB_NEW_MASTER2);
- unlock_rsb(r);
}
/*
@@ -376,9 +377,9 @@ static void set_new_master(struct dlm_rsb *r, int nodeid)
static int recover_master(struct dlm_rsb *r)
{
struct dlm_ls *ls = r->res_ls;
- int error, dir_nodeid, ret_nodeid, our_nodeid = dlm_our_nodeid();
-
- dir_nodeid = dlm_dir_nodeid(r);
+ int error, ret_nodeid;
+ int our_nodeid = dlm_our_nodeid();
+ int dir_nodeid = dlm_dir_nodeid(r);
if (dir_nodeid == our_nodeid) {
error = dlm_dir_lookup(ls, our_nodeid, r->res_name,
@@ -388,7 +389,9 @@ static int recover_master(struct dlm_rsb *r)
if (ret_nodeid == our_nodeid)
ret_nodeid = 0;
+ lock_rsb(r);
set_new_master(r, ret_nodeid);
+ unlock_rsb(r);
} else {
recover_list_add(r);
error = dlm_send_rcom_lookup(r, dir_nodeid);
@@ -398,24 +401,33 @@ static int recover_master(struct dlm_rsb *r)
}
/*
- * When not using a directory, most resource names will hash to a new static
- * master nodeid and the resource will need to be remastered.
+ * All MSTCPY locks are purged and rebuilt, even if the master stayed the same.
+ * This is necessary because recovery can be started, aborted and restarted,
+ * causing the master nodeid to briefly change during the aborted recovery, and
+ * change back to the original value in the second recovery. The MSTCPY locks
+ * may or may not have been purged during the aborted recovery. Another node
+ * with an outstanding request in waiters list and a request reply saved in the
+ * requestqueue, cannot know whether it should ignore the reply and resend the
+ * request, or accept the reply and complete the request. It must do the
+ * former if the remote node purged MSTCPY locks, and it must do the later if
+ * the remote node did not. This is solved by always purging MSTCPY locks, in
+ * which case, the request reply would always be ignored and the request
+ * resent.
*/
static int recover_master_static(struct dlm_rsb *r)
{
- int master = dlm_dir_nodeid(r);
+ int dir_nodeid = dlm_dir_nodeid(r);
+ int new_master = dir_nodeid;
- if (master == dlm_our_nodeid())
- master = 0;
+ if (dir_nodeid == dlm_our_nodeid())
+ new_master = 0;
- if (r->res_nodeid != master) {
- if (is_master(r))
- dlm_purge_mstcpy_locks(r);
- set_new_master(r, master);
- return 1;
- }
- return 0;
+ lock_rsb(r);
+ dlm_purge_mstcpy_locks(r);
+ set_new_master(r, new_master);
+ unlock_rsb(r);
+ return 1;
}
/*
@@ -481,7 +493,9 @@ int dlm_recover_master_reply(struct dlm_ls *ls, struct dlm_rcom *rc)
if (nodeid == dlm_our_nodeid())
nodeid = 0;
+ lock_rsb(r);
set_new_master(r, nodeid);
+ unlock_rsb(r);
recover_list_del(r);
if (recover_list_empty(ls))
@@ -556,8 +570,6 @@ int dlm_recover_locks(struct dlm_ls *ls)
struct dlm_rsb *r;
int error, count = 0;
- log_debug(ls, "dlm_recover_locks");
-
down_read(&ls->ls_root_sem);
list_for_each_entry(r, &ls->ls_root_list, res_root_list) {
if (is_master(r)) {
@@ -584,7 +596,7 @@ int dlm_recover_locks(struct dlm_ls *ls)
}
up_read(&ls->ls_root_sem);
- log_debug(ls, "dlm_recover_locks %d locks", count);
+ log_debug(ls, "dlm_recover_locks %d out", count);
error = dlm_wait_function(ls, &recover_list_empty);
out:
@@ -721,21 +733,19 @@ static void recover_conversion(struct dlm_rsb *r)
}
/* We've become the new master for this rsb and waiting/converting locks may
- need to be granted in dlm_grant_after_purge() due to locks that may have
+ need to be granted in dlm_recover_grant() due to locks that may have
existed from a removed node. */
-static void set_locks_purged(struct dlm_rsb *r)
+static void recover_grant(struct dlm_rsb *r)
{
if (!list_empty(&r->res_waitqueue) || !list_empty(&r->res_convertqueue))
- rsb_set_flag(r, RSB_LOCKS_PURGED);
+ rsb_set_flag(r, RSB_RECOVER_GRANT);
}
void dlm_recover_rsbs(struct dlm_ls *ls)
{
struct dlm_rsb *r;
- int count = 0;
-
- log_debug(ls, "dlm_recover_rsbs");
+ unsigned int count = 0;
down_read(&ls->ls_root_sem);
list_for_each_entry(r, &ls->ls_root_list, res_root_list) {
@@ -744,7 +754,7 @@ void dlm_recover_rsbs(struct dlm_ls *ls)
if (rsb_flag(r, RSB_RECOVER_CONVERT))
recover_conversion(r);
if (rsb_flag(r, RSB_NEW_MASTER2))
- set_locks_purged(r);
+ recover_grant(r);
recover_lvb(r);
count++;
}
@@ -754,7 +764,8 @@ void dlm_recover_rsbs(struct dlm_ls *ls)
}
up_read(&ls->ls_root_sem);
- log_debug(ls, "dlm_recover_rsbs %d rsbs", count);
+ if (count)
+ log_debug(ls, "dlm_recover_rsbs %d done", count);
}
/* Create a single list of all root rsb's to be used during recovery */
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c
index 3780caf7ae0c..f1a9073c0835 100644
--- a/fs/dlm/recoverd.c
+++ b/fs/dlm/recoverd.c
@@ -54,7 +54,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
unsigned long start;
int error, neg = 0;
- log_debug(ls, "dlm_recover %llx", (unsigned long long)rv->seq);
+ log_debug(ls, "dlm_recover %llu", (unsigned long long)rv->seq);
mutex_lock(&ls->ls_recoverd_active);
@@ -84,6 +84,8 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
goto fail;
}
+ ls->ls_recover_locks_in = 0;
+
dlm_set_recover_status(ls, DLM_RS_NODES);
error = dlm_recover_members_wait(ls);
@@ -130,7 +132,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
* Clear lkb's for departed nodes.
*/
- dlm_purge_locks(ls);
+ dlm_recover_purge(ls);
/*
* Get new master nodeid's for rsb's that were mastered on
@@ -161,6 +163,9 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
goto fail;
}
+ log_debug(ls, "dlm_recover_locks %u in",
+ ls->ls_recover_locks_in);
+
/*
* Finalize state in master rsb's now that all locks can be
* checked. This includes conversion resolution and lvb
@@ -225,9 +230,9 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
goto fail;
}
- dlm_grant_after_purge(ls);
+ dlm_recover_grant(ls);
- log_debug(ls, "dlm_recover %llx generation %u done: %u ms",
+ log_debug(ls, "dlm_recover %llu generation %u done: %u ms",
(unsigned long long)rv->seq, ls->ls_generation,
jiffies_to_msecs(jiffies - start));
mutex_unlock(&ls->ls_recoverd_active);
@@ -237,7 +242,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
fail:
dlm_release_root_list(ls);
- log_debug(ls, "dlm_recover %llx error %d",
+ log_debug(ls, "dlm_recover %llu error %d",
(unsigned long long)rv->seq, error);
mutex_unlock(&ls->ls_recoverd_active);
return error;
diff --git a/fs/dlm/requestqueue.c b/fs/dlm/requestqueue.c
index a44fa22890e1..1695f1b0dd45 100644
--- a/fs/dlm/requestqueue.c
+++ b/fs/dlm/requestqueue.c
@@ -19,6 +19,7 @@
struct rq_entry {
struct list_head list;
+ uint32_t recover_seq;
int nodeid;
struct dlm_message request;
};
@@ -41,6 +42,7 @@ void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_message *ms)
return;
}
+ e->recover_seq = ls->ls_recover_seq & 0xFFFFFFFF;
e->nodeid = nodeid;
memcpy(&e->request, ms, ms->m_header.h_length);
@@ -63,6 +65,7 @@ void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_message *ms)
int dlm_process_requestqueue(struct dlm_ls *ls)
{
struct rq_entry *e;
+ struct dlm_message *ms;
int error = 0;
mutex_lock(&ls->ls_requestqueue_mutex);
@@ -76,7 +79,15 @@ int dlm_process_requestqueue(struct dlm_ls *ls)
e = list_entry(ls->ls_requestqueue.next, struct rq_entry, list);
mutex_unlock(&ls->ls_requestqueue_mutex);
- dlm_receive_message_saved(ls, &e->request);
+ ms = &e->request;
+
+ log_limit(ls, "dlm_process_requestqueue msg %d from %d "
+ "lkid %x remid %x result %d seq %u",
+ ms->m_type, ms->m_header.h_nodeid,
+ ms->m_lkid, ms->m_remid, ms->m_result,
+ e->recover_seq);
+
+ dlm_receive_message_saved(ls, &e->request, e->recover_seq);
mutex_lock(&ls->ls_requestqueue_mutex);
list_del(&e->list);
@@ -138,35 +149,7 @@ static int purge_request(struct dlm_ls *ls, struct dlm_message *ms, int nodeid)
if (!dlm_no_directory(ls))
return 0;
- /* with no directory, the master is likely to change as a part of
- recovery; requests to/from the defunct master need to be purged */
-
- switch (type) {
- case DLM_MSG_REQUEST:
- case DLM_MSG_CONVERT:
- case DLM_MSG_UNLOCK:
- case DLM_MSG_CANCEL:
- /* we're no longer the master of this resource, the sender
- will resend to the new master (see waiter_needs_recovery) */
-
- if (dlm_hash2nodeid(ls, ms->m_hash) != dlm_our_nodeid())
- return 1;
- break;
-
- case DLM_MSG_REQUEST_REPLY:
- case DLM_MSG_CONVERT_REPLY:
- case DLM_MSG_UNLOCK_REPLY:
- case DLM_MSG_CANCEL_REPLY:
- case DLM_MSG_GRANT:
- /* this reply is from the former master of the resource,
- we'll resend to the new master if needed */
-
- if (dlm_hash2nodeid(ls, ms->m_hash) != nodeid)
- return 1;
- break;
- }
-
- return 0;
+ return 1;
}
void dlm_purge_requestqueue(struct dlm_ls *ls)
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index c0b3c70ee87a..079d1be65ba9 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -33,6 +33,7 @@
#include <linux/bitops.h>
#include <linux/mutex.h>
#include <linux/anon_inodes.h>
+#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/mman.h>
@@ -87,7 +88,7 @@
*/
/* Epoll private bits inside the event mask */
-#define EP_PRIVATE_BITS (EPOLLONESHOT | EPOLLET)
+#define EP_PRIVATE_BITS (EPOLLWAKEUP | EPOLLONESHOT | EPOLLET)
/* Maximum number of nesting allowed inside epoll sets */
#define EP_MAX_NESTS 4
@@ -154,6 +155,9 @@ struct epitem {
/* List header used to link this item to the "struct file" items list */
struct list_head fllink;
+ /* wakeup_source used when EPOLLWAKEUP is set */
+ struct wakeup_source *ws;
+
/* The structure that describe the interested events and the source fd */
struct epoll_event event;
};
@@ -194,6 +198,9 @@ struct eventpoll {
*/
struct epitem *ovflist;
+ /* wakeup_source used when ep_scan_ready_list is running */
+ struct wakeup_source *ws;
+
/* The user that created the eventpoll descriptor */
struct user_struct *user;
@@ -588,8 +595,10 @@ static int ep_scan_ready_list(struct eventpoll *ep,
* queued into ->ovflist but the "txlist" might already
* contain them, and the list_splice() below takes care of them.
*/
- if (!ep_is_linked(&epi->rdllink))
+ if (!ep_is_linked(&epi->rdllink)) {
list_add_tail(&epi->rdllink, &ep->rdllist);
+ __pm_stay_awake(epi->ws);
+ }
}
/*
* We need to set back ep->ovflist to EP_UNACTIVE_PTR, so that after
@@ -602,6 +611,7 @@ static int ep_scan_ready_list(struct eventpoll *ep,
* Quickly re-inject items left on "txlist".
*/
list_splice(&txlist, &ep->rdllist);
+ __pm_relax(ep->ws);
if (!list_empty(&ep->rdllist)) {
/*
@@ -656,6 +666,8 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
list_del_init(&epi->rdllink);
spin_unlock_irqrestore(&ep->lock, flags);
+ wakeup_source_unregister(epi->ws);
+
/* At this point it is safe to free the eventpoll item */
kmem_cache_free(epi_cache, epi);
@@ -706,6 +718,7 @@ static void ep_free(struct eventpoll *ep)
mutex_unlock(&epmutex);
mutex_destroy(&ep->mtx);
free_uid(ep->user);
+ wakeup_source_unregister(ep->ws);
kfree(ep);
}
@@ -737,6 +750,7 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head,
* callback, but it's not actually ready, as far as
* caller requested events goes. We can remove it here.
*/
+ __pm_relax(epi->ws);
list_del_init(&epi->rdllink);
}
}
@@ -927,13 +941,23 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
if (epi->next == EP_UNACTIVE_PTR) {
epi->next = ep->ovflist;
ep->ovflist = epi;
+ if (epi->ws) {
+ /*
+ * Activate ep->ws since epi->ws may get
+ * deactivated at any time.
+ */
+ __pm_stay_awake(ep->ws);
+ }
+
}
goto out_unlock;
}
/* If this file is already in the ready list we exit soon */
- if (!ep_is_linked(&epi->rdllink))
+ if (!ep_is_linked(&epi->rdllink)) {
list_add_tail(&epi->rdllink, &ep->rdllist);
+ __pm_stay_awake(epi->ws);
+ }
/*
* Wake up ( if active ) both the eventpoll wait list and the ->poll()
@@ -1091,6 +1115,30 @@ static int reverse_path_check(void)
return error;
}
+static int ep_create_wakeup_source(struct epitem *epi)
+{
+ const char *name;
+
+ if (!epi->ep->ws) {
+ epi->ep->ws = wakeup_source_register("eventpoll");
+ if (!epi->ep->ws)
+ return -ENOMEM;
+ }
+
+ name = epi->ffd.file->f_path.dentry->d_name.name;
+ epi->ws = wakeup_source_register(name);
+ if (!epi->ws)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void ep_destroy_wakeup_source(struct epitem *epi)
+{
+ wakeup_source_unregister(epi->ws);
+ epi->ws = NULL;
+}
+
/*
* Must be called with "mtx" held.
*/
@@ -1118,6 +1166,13 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
epi->event = *event;
epi->nwait = 0;
epi->next = EP_UNACTIVE_PTR;
+ if (epi->event.events & EPOLLWAKEUP) {
+ error = ep_create_wakeup_source(epi);
+ if (error)
+ goto error_create_wakeup_source;
+ } else {
+ epi->ws = NULL;
+ }
/* Initialize the poll table using the queue callback */
epq.epi = epi;
@@ -1164,6 +1219,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
/* If the file is already "ready" we drop it inside the ready list */
if ((revents & event->events) && !ep_is_linked(&epi->rdllink)) {
list_add_tail(&epi->rdllink, &ep->rdllist);
+ __pm_stay_awake(epi->ws);
/* Notify waiting tasks that events are available */
if (waitqueue_active(&ep->wq))
@@ -1204,6 +1260,9 @@ error_unregister:
list_del_init(&epi->rdllink);
spin_unlock_irqrestore(&ep->lock, flags);
+ wakeup_source_unregister(epi->ws);
+
+error_create_wakeup_source:
kmem_cache_free(epi_cache, epi);
return error;
@@ -1229,6 +1288,12 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even
epi->event.events = event->events;
pt._key = event->events;
epi->event.data = event->data; /* protected by mtx */
+ if (epi->event.events & EPOLLWAKEUP) {
+ if (!epi->ws)
+ ep_create_wakeup_source(epi);
+ } else if (epi->ws) {
+ ep_destroy_wakeup_source(epi);
+ }
/*
* Get current event bits. We can safely use the file* here because
@@ -1244,6 +1309,7 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even
spin_lock_irq(&ep->lock);
if (!ep_is_linked(&epi->rdllink)) {
list_add_tail(&epi->rdllink, &ep->rdllist);
+ __pm_stay_awake(epi->ws);
/* Notify waiting tasks that events are available */
if (waitqueue_active(&ep->wq))
@@ -1282,6 +1348,18 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head,
!list_empty(head) && eventcnt < esed->maxevents;) {
epi = list_first_entry(head, struct epitem, rdllink);
+ /*
+ * Activate ep->ws before deactivating epi->ws to prevent
+ * triggering auto-suspend here (in case we reactive epi->ws
+ * below).
+ *
+ * This could be rearranged to delay the deactivation of epi->ws
+ * instead, but then epi->ws would temporarily be out of sync
+ * with ep_is_linked().
+ */
+ if (epi->ws && epi->ws->active)
+ __pm_stay_awake(ep->ws);
+ __pm_relax(epi->ws);
list_del_init(&epi->rdllink);
pt._key = epi->event.events;
@@ -1298,6 +1376,7 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head,
if (__put_user(revents, &uevent->events) ||
__put_user(epi->event.data, &uevent->data)) {
list_add(&epi->rdllink, head);
+ __pm_stay_awake(epi->ws);
return eventcnt ? eventcnt : -EFAULT;
}
eventcnt++;
@@ -1317,6 +1396,7 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head,
* poll callback will queue them in ep->ovflist.
*/
list_add_tail(&epi->rdllink, &ep->rdllist);
+ __pm_stay_awake(epi->ws);
}
}
}
@@ -1629,6 +1709,10 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
if (!tfile->f_op || !tfile->f_op->poll)
goto error_tgt_fput;
+ /* Check if EPOLLWAKEUP is allowed */
+ if ((epds.events & EPOLLWAKEUP) && !capable(CAP_EPOLLWAKEUP))
+ epds.events &= ~EPOLLWAKEUP;
+
/*
* We have to check that the file structure underneath the file descriptor
* the user passed to us _is_ an eventpoll file. And also we do not permit
diff --git a/fs/exec.c b/fs/exec.c
index b1fd2025e59a..1e8efdc80412 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1245,6 +1245,13 @@ static int check_unsafe_exec(struct linux_binprm *bprm)
bprm->unsafe |= LSM_UNSAFE_PTRACE;
}
+ /*
+ * This isn't strictly necessary, but it makes it harder for LSMs to
+ * mess up.
+ */
+ if (current->no_new_privs)
+ bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS;
+
n_fs = 1;
spin_lock(&p->fs->lock);
rcu_read_lock();
@@ -1288,7 +1295,8 @@ int prepare_binprm(struct linux_binprm *bprm)
bprm->cred->euid = current_euid();
bprm->cred->egid = current_egid();
- if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
+ if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) &&
+ !current->no_new_privs) {
/* Set-uid? */
if (mode & S_ISUID) {
bprm->per_clear |= PER_CLEAR_ON_SETID;
@@ -1930,8 +1938,21 @@ static int coredump_wait(int exit_code, struct core_state *core_state)
core_waiters = zap_threads(tsk, mm, core_state, exit_code);
up_write(&mm->mmap_sem);
- if (core_waiters > 0)
+ if (core_waiters > 0) {
+ struct core_thread *ptr;
+
wait_for_completion(&core_state->startup);
+ /*
+ * Wait for all the threads to become inactive, so that
+ * all the thread context (extended register state, like
+ * fpu etc) gets copied to the memory.
+ */
+ ptr = core_state->dumper.next;
+ while (ptr != NULL) {
+ wait_task_inactive(ptr->task, 0);
+ ptr = ptr->next;
+ }
+ }
return core_waiters;
}
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index dffb86536285..f663a67d7bf0 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -79,7 +79,7 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, str
struct dentry *ext2_get_parent(struct dentry *child)
{
- struct qstr dotdot = {.name = "..", .len = 2};
+ struct qstr dotdot = QSTR_INIT("..", 2);
unsigned long ino = ext2_inode_by_name(child->d_inode, &dotdot);
if (!ino)
return ERR_PTR(-ENOENT);
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index d7940b24cf68..eeb63dfc5d20 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1045,7 +1045,7 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
struct dentry *ext3_get_parent(struct dentry *child)
{
unsigned long ino;
- struct qstr dotdot = {.name = "..", .len = 2};
+ struct qstr dotdot = QSTR_INIT("..", 2);
struct ext3_dir_entry_2 * de;
struct buffer_head *bh;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 349d7b3671c8..e2a3f4b0ff78 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1052,10 +1052,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru
struct dentry *ext4_get_parent(struct dentry *child)
{
__u32 ino;
- static const struct qstr dotdot = {
- .name = "..",
- .len = 2,
- };
+ static const struct qstr dotdot = QSTR_INIT("..", 2);
struct ext4_dir_entry_2 * de;
struct buffer_head *bh;
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 230eb0f005b6..bd4a5892c93c 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -73,12 +73,8 @@ static int gfs2_set_mode(struct inode *inode, umode_t mode)
int error = 0;
if (mode != inode->i_mode) {
- struct iattr iattr;
-
- iattr.ia_valid = ATTR_MODE;
- iattr.ia_mode = mode;
-
- error = gfs2_setattr_simple(inode, &iattr);
+ inode->i_mode = mode;
+ mark_inode_dirty(inode);
}
return error;
@@ -126,9 +122,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
return PTR_ERR(acl);
if (!acl) {
mode &= ~current_umask();
- if (mode != inode->i_mode)
- error = gfs2_set_mode(inode, mode);
- return error;
+ return gfs2_set_mode(inode, mode);
}
if (S_ISDIR(inode->i_mode)) {
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 9b2ff0e851b1..e80a464850c8 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -36,8 +36,8 @@
#include "glops.h"
-void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
- unsigned int from, unsigned int to)
+static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
+ unsigned int from, unsigned int to)
{
struct buffer_head *head = page_buffers(page);
unsigned int bsize = head->b_size;
@@ -517,15 +517,14 @@ out:
/**
* gfs2_internal_read - read an internal file
* @ip: The gfs2 inode
- * @ra_state: The readahead state (or NULL for no readahead)
* @buf: The buffer to fill
* @pos: The file position
* @size: The amount to read
*
*/
-int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state,
- char *buf, loff_t *pos, unsigned size)
+int gfs2_internal_read(struct gfs2_inode *ip, char *buf, loff_t *pos,
+ unsigned size)
{
struct address_space *mapping = ip->i_inode.i_mapping;
unsigned long index = *pos / PAGE_CACHE_SIZE;
@@ -943,8 +942,8 @@ static void gfs2_discard(struct gfs2_sbd *sdp, struct buffer_head *bh)
clear_buffer_dirty(bh);
bd = bh->b_private;
if (bd) {
- if (!list_empty(&bd->bd_le.le_list) && !buffer_pinned(bh))
- list_del_init(&bd->bd_le.le_list);
+ if (!list_empty(&bd->bd_list) && !buffer_pinned(bh))
+ list_del_init(&bd->bd_list);
else
gfs2_remove_from_journal(bh, current->journal_info, 0);
}
@@ -1084,10 +1083,9 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
bd = bh->b_private;
if (bd) {
gfs2_assert_warn(sdp, bd->bd_bh == bh);
- gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr));
- if (!list_empty(&bd->bd_le.le_list)) {
+ if (!list_empty(&bd->bd_list)) {
if (!buffer_pinned(bh))
- list_del_init(&bd->bd_le.le_list);
+ list_del_init(&bd->bd_list);
else
bd = NULL;
}
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 03c04febe26f..dab54099dd98 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -324,7 +324,7 @@ static int lookup_metapath(struct gfs2_inode *ip, struct metapath *mp)
if (!dblock)
return x + 1;
- ret = gfs2_meta_indirect_buffer(ip, x+1, dblock, 0, &mp->mp_bh[x+1]);
+ ret = gfs2_meta_indirect_buffer(ip, x+1, dblock, &mp->mp_bh[x+1]);
if (ret)
return ret;
}
@@ -882,7 +882,7 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
top = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + mp->mp_list[0];
bottom = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + sdp->sd_diptrs;
} else {
- error = gfs2_meta_indirect_buffer(ip, height, block, 0, &bh);
+ error = gfs2_meta_indirect_buffer(ip, height, block, &bh);
if (error)
return error;
@@ -1169,6 +1169,7 @@ static int do_grow(struct inode *inode, u64 size)
struct buffer_head *dibh;
struct gfs2_qadata *qa = NULL;
int error;
+ int unstuff = 0;
if (gfs2_is_stuffed(ip) &&
(size > (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)))) {
@@ -1183,13 +1184,14 @@ static int do_grow(struct inode *inode, u64 size)
error = gfs2_inplace_reserve(ip, 1);
if (error)
goto do_grow_qunlock;
+ unstuff = 1;
}
error = gfs2_trans_begin(sdp, RES_DINODE + RES_STATFS + RES_RG_BIT, 0);
if (error)
goto do_grow_release;
- if (qa) {
+ if (unstuff) {
error = gfs2_unstuff_dinode(ip, NULL);
if (error)
goto do_end_trans;
@@ -1208,7 +1210,7 @@ static int do_grow(struct inode *inode, u64 size)
do_end_trans:
gfs2_trans_end(sdp);
do_grow_release:
- if (qa) {
+ if (unstuff) {
gfs2_inplace_release(ip);
do_grow_qunlock:
gfs2_quota_unlock(ip);
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index a836056343f0..8aaeb07a07b5 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -821,7 +821,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
struct buffer_head *bh;
struct gfs2_leaf *leaf;
struct gfs2_dirent *dent;
- struct qstr name = { .name = "", .len = 0, .hash = 0 };
+ struct qstr name = { .name = "" };
error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
if (error)
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index a3d2c9ee8d66..31b199f6efc1 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -558,14 +558,14 @@ fail:
}
/**
- * gfs2_close - called to close a struct file
+ * gfs2_release - called to close a struct file
* @inode: the inode the struct file belongs to
* @file: the struct file being closed
*
* Returns: errno
*/
-static int gfs2_close(struct inode *inode, struct file *file)
+static int gfs2_release(struct inode *inode, struct file *file)
{
struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
struct gfs2_file *fp;
@@ -1005,7 +1005,7 @@ const struct file_operations gfs2_file_fops = {
.unlocked_ioctl = gfs2_ioctl,
.mmap = gfs2_mmap,
.open = gfs2_open,
- .release = gfs2_close,
+ .release = gfs2_release,
.fsync = gfs2_fsync,
.lock = gfs2_lock,
.flock = gfs2_flock,
@@ -1019,7 +1019,7 @@ const struct file_operations gfs2_dir_fops = {
.readdir = gfs2_readdir,
.unlocked_ioctl = gfs2_ioctl,
.open = gfs2_open,
- .release = gfs2_close,
+ .release = gfs2_release,
.fsync = gfs2_fsync,
.lock = gfs2_lock,
.flock = gfs2_flock,
@@ -1037,7 +1037,7 @@ const struct file_operations gfs2_file_fops_nolock = {
.unlocked_ioctl = gfs2_ioctl,
.mmap = gfs2_mmap,
.open = gfs2_open,
- .release = gfs2_close,
+ .release = gfs2_release,
.fsync = gfs2_fsync,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
@@ -1049,7 +1049,7 @@ const struct file_operations gfs2_dir_fops_nolock = {
.readdir = gfs2_readdir,
.unlocked_ioctl = gfs2_ioctl,
.open = gfs2_open,
- .release = gfs2_close,
+ .release = gfs2_release,
.fsync = gfs2_fsync,
.llseek = default_llseek,
};
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 1656df7aacd2..4bdcf3784187 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -94,7 +94,6 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
/* A shortened, inline version of gfs2_trans_begin() */
tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64));
tr.tr_ip = (unsigned long)__builtin_return_address(0);
- INIT_LIST_HEAD(&tr.tr_list_buf);
gfs2_log_reserve(sdp, tr.tr_reserved);
BUG_ON(current->journal_info);
current->journal_info = &tr;
@@ -379,11 +378,6 @@ int gfs2_inode_refresh(struct gfs2_inode *ip)
if (error)
return error;
- if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), dibh, GFS2_METATYPE_DI)) {
- brelse(dibh);
- return -EIO;
- }
-
error = gfs2_dinode_in(ip, dibh->b_data);
brelse(dibh);
clear_bit(GIF_INVALID, &ip->i_flags);
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 47d0bda5ac2b..67fd6beffece 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -26,7 +26,7 @@
#define DIO_METADATA 0x00000020
struct gfs2_log_operations;
-struct gfs2_log_element;
+struct gfs2_bufdata;
struct gfs2_holder;
struct gfs2_glock;
struct gfs2_quota_data;
@@ -52,7 +52,7 @@ struct gfs2_log_header_host {
*/
struct gfs2_log_operations {
- void (*lo_add) (struct gfs2_sbd *sdp, struct gfs2_log_element *le);
+ void (*lo_add) (struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
void (*lo_before_commit) (struct gfs2_sbd *sdp);
void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_ail *ai);
void (*lo_before_scan) (struct gfs2_jdesc *jd,
@@ -64,11 +64,6 @@ struct gfs2_log_operations {
const char *lo_name;
};
-struct gfs2_log_element {
- struct list_head le_list;
- const struct gfs2_log_operations *le_ops;
-};
-
#define GBF_FULL 1
struct gfs2_bitmap {
@@ -118,15 +113,10 @@ TAS_BUFFER_FNS(Zeronew, zeronew)
struct gfs2_bufdata {
struct buffer_head *bd_bh;
struct gfs2_glock *bd_gl;
+ u64 bd_blkno;
- union {
- struct list_head list_tr;
- u64 blkno;
- } u;
-#define bd_list_tr u.list_tr
-#define bd_blkno u.blkno
-
- struct gfs2_log_element bd_le;
+ struct list_head bd_list;
+ const struct gfs2_log_operations *bd_ops;
struct gfs2_ail *bd_ail;
struct list_head bd_ail_st_list;
@@ -411,13 +401,10 @@ struct gfs2_trans {
int tr_touched;
- unsigned int tr_num_buf;
unsigned int tr_num_buf_new;
unsigned int tr_num_databuf_new;
unsigned int tr_num_buf_rm;
unsigned int tr_num_databuf_rm;
- struct list_head tr_list_buf;
-
unsigned int tr_num_revoke;
unsigned int tr_num_revoke_rm;
};
@@ -556,7 +543,6 @@ struct gfs2_sb_host {
struct lm_lockstruct {
int ls_jid;
unsigned int ls_first;
- unsigned int ls_nodir;
const struct lm_lockops *ls_ops;
dlm_lockspace_t *ls_dlm;
@@ -699,7 +685,6 @@ struct gfs2_sbd {
struct list_head sd_log_le_buf;
struct list_head sd_log_le_revoke;
- struct list_head sd_log_le_rg;
struct list_head sd_log_le_databuf;
struct list_head sd_log_le_ordered;
@@ -716,7 +701,9 @@ struct gfs2_sbd {
struct rw_semaphore sd_log_flush_lock;
atomic_t sd_log_in_flight;
+ struct bio *sd_log_bio;
wait_queue_head_t sd_log_flush_wait;
+ int sd_log_error;
unsigned int sd_log_flush_head;
u64 sd_log_flush_wrapped;
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index 276e7b52b658..c53c7477f6da 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -17,10 +17,7 @@
extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask);
extern int gfs2_internal_read(struct gfs2_inode *ip,
- struct file_ra_state *ra_state,
char *buf, loff_t *pos, unsigned size);
-extern void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
- unsigned int from, unsigned int to);
extern void gfs2_set_aops(struct inode *inode);
static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index 5f5e70e047dc..4a38db739ca0 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -1209,8 +1209,6 @@ static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)
fsname++;
flags = DLM_LSFL_FS | DLM_LSFL_NEWEXCL;
- if (ls->ls_nodir)
- flags |= DLM_LSFL_NODIR;
/*
* create/join lockspace
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 4752eadc7f6e..f4beeb9c81c1 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -32,8 +32,6 @@
#include "dir.h"
#include "trace_gfs2.h"
-#define PULL 1
-
/**
* gfs2_struct2blk - compute stuff
* @sdp: the filesystem
@@ -359,18 +357,6 @@ retry:
return 0;
}
-u64 gfs2_log_bmap(struct gfs2_sbd *sdp, unsigned int lbn)
-{
- struct gfs2_journal_extent *je;
-
- list_for_each_entry(je, &sdp->sd_jdesc->extent_list, extent_list) {
- if (lbn >= je->lblock && lbn < je->lblock + je->blocks)
- return je->dblock + lbn - je->lblock;
- }
-
- return -1;
-}
-
/**
* log_distance - Compute distance between two journal blocks
* @sdp: The GFS2 superblock
@@ -466,17 +452,6 @@ static unsigned int current_tail(struct gfs2_sbd *sdp)
return tail;
}
-void gfs2_log_incr_head(struct gfs2_sbd *sdp)
-{
- BUG_ON((sdp->sd_log_flush_head == sdp->sd_log_tail) &&
- (sdp->sd_log_flush_head != sdp->sd_log_head));
-
- if (++sdp->sd_log_flush_head == sdp->sd_jdesc->jd_blocks) {
- sdp->sd_log_flush_head = 0;
- sdp->sd_log_flush_wrapped = 1;
- }
-}
-
static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
{
unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail);
@@ -511,8 +486,8 @@ static int bd_cmp(void *priv, struct list_head *a, struct list_head *b)
{
struct gfs2_bufdata *bda, *bdb;
- bda = list_entry(a, struct gfs2_bufdata, bd_le.le_list);
- bdb = list_entry(b, struct gfs2_bufdata, bd_le.le_list);
+ bda = list_entry(a, struct gfs2_bufdata, bd_list);
+ bdb = list_entry(b, struct gfs2_bufdata, bd_list);
if (bda->bd_bh->b_blocknr < bdb->bd_bh->b_blocknr)
return -1;
@@ -530,8 +505,8 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp)
gfs2_log_lock(sdp);
list_sort(NULL, &sdp->sd_log_le_ordered, &bd_cmp);
while (!list_empty(&sdp->sd_log_le_ordered)) {
- bd = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_bufdata, bd_le.le_list);
- list_move(&bd->bd_le.le_list, &written);
+ bd = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_bufdata, bd_list);
+ list_move(&bd->bd_list, &written);
bh = bd->bd_bh;
if (!buffer_dirty(bh))
continue;
@@ -558,7 +533,7 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
gfs2_log_lock(sdp);
while (!list_empty(&sdp->sd_log_le_ordered)) {
- bd = list_entry(sdp->sd_log_le_ordered.prev, struct gfs2_bufdata, bd_le.le_list);
+ bd = list_entry(sdp->sd_log_le_ordered.prev, struct gfs2_bufdata, bd_list);
bh = bd->bd_bh;
if (buffer_locked(bh)) {
get_bh(bh);
@@ -568,7 +543,7 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
gfs2_log_lock(sdp);
continue;
}
- list_del_init(&bd->bd_le.le_list);
+ list_del_init(&bd->bd_list);
}
gfs2_log_unlock(sdp);
}
@@ -580,25 +555,19 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
* Returns: the initialized log buffer descriptor
*/
-static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
+static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
{
- u64 blkno = gfs2_log_bmap(sdp, sdp->sd_log_flush_head);
- struct buffer_head *bh;
struct gfs2_log_header *lh;
unsigned int tail;
u32 hash;
-
- bh = sb_getblk(sdp->sd_vfs, blkno);
- lock_buffer(bh);
- memset(bh->b_data, 0, bh->b_size);
- set_buffer_uptodate(bh);
- clear_buffer_dirty(bh);
+ int rw = WRITE_FLUSH_FUA | REQ_META;
+ struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
+ lh = page_address(page);
+ clear_page(lh);
gfs2_ail1_empty(sdp);
tail = current_tail(sdp);
- lh = (struct gfs2_log_header *)bh->b_data;
- memset(lh, 0, sizeof(struct gfs2_log_header));
lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH);
lh->lh_header.__pad0 = cpu_to_be64(0);
@@ -608,31 +577,22 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
lh->lh_flags = cpu_to_be32(flags);
lh->lh_tail = cpu_to_be32(tail);
lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
- hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header));
+ hash = gfs2_disk_hash(page_address(page), sizeof(struct gfs2_log_header));
lh->lh_hash = cpu_to_be32(hash);
- bh->b_end_io = end_buffer_write_sync;
- get_bh(bh);
if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) {
gfs2_ordered_wait(sdp);
log_flush_wait(sdp);
- submit_bh(WRITE_SYNC | REQ_META | REQ_PRIO, bh);
- } else {
- submit_bh(WRITE_FLUSH_FUA | REQ_META, bh);
+ rw = WRITE_SYNC | REQ_META | REQ_PRIO;
}
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh))
- gfs2_io_error_bh(sdp, bh);
- brelse(bh);
+ sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
+ gfs2_log_write_page(sdp, page);
+ gfs2_log_flush_bio(sdp, rw);
+ log_flush_wait(sdp);
if (sdp->sd_log_tail != tail)
log_pull_tail(sdp, tail);
- else
- gfs2_assert_withdraw(sdp, !pull);
-
- sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
- gfs2_log_incr_head(sdp);
}
/**
@@ -678,15 +638,14 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
gfs2_ordered_write(sdp);
lops_before_commit(sdp);
+ gfs2_log_flush_bio(sdp, WRITE);
if (sdp->sd_log_head != sdp->sd_log_flush_head) {
- log_write_header(sdp, 0, 0);
+ log_write_header(sdp, 0);
} else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
- gfs2_log_lock(sdp);
atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
trace_gfs2_log_blocks(sdp, -1);
- gfs2_log_unlock(sdp);
- log_write_header(sdp, 0, PULL);
+ log_write_header(sdp, 0);
}
lops_after_commit(sdp, ai);
@@ -735,21 +694,6 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
gfs2_log_unlock(sdp);
}
-static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
-{
- struct list_head *head = &tr->tr_list_buf;
- struct gfs2_bufdata *bd;
-
- gfs2_log_lock(sdp);
- while (!list_empty(head)) {
- bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr);
- list_del_init(&bd->bd_list_tr);
- tr->tr_num_buf--;
- }
- gfs2_log_unlock(sdp);
- gfs2_assert_warn(sdp, !tr->tr_num_buf);
-}
-
/**
* gfs2_log_commit - Commit a transaction to the log
* @sdp: the filesystem
@@ -768,8 +712,6 @@ static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{
log_refund(sdp, tr);
- buf_lo_incore_commit(sdp, tr);
-
up_read(&sdp->sd_log_flush_lock);
if (atomic_read(&sdp->sd_log_pinned) > atomic_read(&sdp->sd_log_thresh1) ||
@@ -798,8 +740,7 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
sdp->sd_log_flush_head = sdp->sd_log_head;
sdp->sd_log_flush_wrapped = 0;
- log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT,
- (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL);
+ log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT);
gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks);
gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail);
@@ -854,11 +795,9 @@ int gfs2_logd(void *data)
struct gfs2_sbd *sdp = data;
unsigned long t = 1;
DEFINE_WAIT(wait);
- unsigned preflush;
while (!kthread_should_stop()) {
- preflush = atomic_read(&sdp->sd_log_pinned);
if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
gfs2_ail1_empty(sdp);
gfs2_log_flush(sdp, NULL);
diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h
index ff07454b582c..3fd5215ea25f 100644
--- a/fs/gfs2/log.h
+++ b/fs/gfs2/log.h
@@ -52,8 +52,6 @@ extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
unsigned int ssize);
extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
-extern void gfs2_log_incr_head(struct gfs2_sbd *sdp);
-extern u64 gfs2_log_bmap(struct gfs2_sbd *sdp, unsigned int lbn);
extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl);
extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 6b1efb594d90..852c1be1dd3b 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -127,146 +127,277 @@ static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh,
atomic_dec(&sdp->sd_log_pinned);
}
-
-static inline struct gfs2_log_descriptor *bh_log_desc(struct buffer_head *bh)
+static void gfs2_log_incr_head(struct gfs2_sbd *sdp)
{
- return (struct gfs2_log_descriptor *)bh->b_data;
+ BUG_ON((sdp->sd_log_flush_head == sdp->sd_log_tail) &&
+ (sdp->sd_log_flush_head != sdp->sd_log_head));
+
+ if (++sdp->sd_log_flush_head == sdp->sd_jdesc->jd_blocks) {
+ sdp->sd_log_flush_head = 0;
+ sdp->sd_log_flush_wrapped = 1;
+ }
}
-static inline __be64 *bh_log_ptr(struct buffer_head *bh)
+static u64 gfs2_log_bmap(struct gfs2_sbd *sdp)
{
- struct gfs2_log_descriptor *ld = bh_log_desc(bh);
- return (__force __be64 *)(ld + 1);
+ unsigned int lbn = sdp->sd_log_flush_head;
+ struct gfs2_journal_extent *je;
+ u64 block;
+
+ list_for_each_entry(je, &sdp->sd_jdesc->extent_list, extent_list) {
+ if (lbn >= je->lblock && lbn < je->lblock + je->blocks) {
+ block = je->dblock + lbn - je->lblock;
+ gfs2_log_incr_head(sdp);
+ return block;
+ }
+ }
+
+ return -1;
}
-static inline __be64 *bh_ptr_end(struct buffer_head *bh)
+/**
+ * gfs2_end_log_write_bh - end log write of pagecache data with buffers
+ * @sdp: The superblock
+ * @bvec: The bio_vec
+ * @error: The i/o status
+ *
+ * This finds the relavent buffers and unlocks then and sets the
+ * error flag according to the status of the i/o request. This is
+ * used when the log is writing data which has an in-place version
+ * that is pinned in the pagecache.
+ */
+
+static void gfs2_end_log_write_bh(struct gfs2_sbd *sdp, struct bio_vec *bvec,
+ int error)
{
- return (__force __be64 *)(bh->b_data + bh->b_size);
+ struct buffer_head *bh, *next;
+ struct page *page = bvec->bv_page;
+ unsigned size;
+
+ bh = page_buffers(page);
+ size = bvec->bv_len;
+ while (bh_offset(bh) < bvec->bv_offset)
+ bh = bh->b_this_page;
+ do {
+ if (error)
+ set_buffer_write_io_error(bh);
+ unlock_buffer(bh);
+ next = bh->b_this_page;
+ size -= bh->b_size;
+ brelse(bh);
+ bh = next;
+ } while(bh && size);
}
/**
- * gfs2_log_write_endio - End of I/O for a log buffer
- * @bh: The buffer head
- * @uptodate: I/O Status
+ * gfs2_end_log_write - end of i/o to the log
+ * @bio: The bio
+ * @error: Status of i/o request
+ *
+ * Each bio_vec contains either data from the pagecache or data
+ * relating to the log itself. Here we iterate over the bio_vec
+ * array, processing both kinds of data.
*
*/
-static void gfs2_log_write_endio(struct buffer_head *bh, int uptodate)
+static void gfs2_end_log_write(struct bio *bio, int error)
{
- struct gfs2_sbd *sdp = bh->b_private;
- bh->b_private = NULL;
+ struct gfs2_sbd *sdp = bio->bi_private;
+ struct bio_vec *bvec;
+ struct page *page;
+ int i;
- end_buffer_write_sync(bh, uptodate);
+ if (error) {
+ sdp->sd_log_error = error;
+ fs_err(sdp, "Error %d writing to log\n", error);
+ }
+
+ bio_for_each_segment(bvec, bio, i) {
+ page = bvec->bv_page;
+ if (page_has_buffers(page))
+ gfs2_end_log_write_bh(sdp, bvec, error);
+ else
+ mempool_free(page, gfs2_page_pool);
+ }
+
+ bio_put(bio);
if (atomic_dec_and_test(&sdp->sd_log_in_flight))
wake_up(&sdp->sd_log_flush_wait);
}
/**
- * gfs2_log_get_buf - Get and initialize a buffer to use for log control data
- * @sdp: The GFS2 superblock
+ * gfs2_log_flush_bio - Submit any pending log bio
+ * @sdp: The superblock
+ * @rw: The rw flags
*
- * tReturns: the buffer_head
+ * Submit any pending part-built or full bio to the block device. If
+ * there is no pending bio, then this is a no-op.
*/
-static struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp)
+void gfs2_log_flush_bio(struct gfs2_sbd *sdp, int rw)
{
- u64 blkno = gfs2_log_bmap(sdp, sdp->sd_log_flush_head);
- struct buffer_head *bh;
+ if (sdp->sd_log_bio) {
+ atomic_inc(&sdp->sd_log_in_flight);
+ submit_bio(rw, sdp->sd_log_bio);
+ sdp->sd_log_bio = NULL;
+ }
+}
- bh = sb_getblk(sdp->sd_vfs, blkno);
- lock_buffer(bh);
- memset(bh->b_data, 0, bh->b_size);
- set_buffer_uptodate(bh);
- clear_buffer_dirty(bh);
- gfs2_log_incr_head(sdp);
- atomic_inc(&sdp->sd_log_in_flight);
- bh->b_private = sdp;
- bh->b_end_io = gfs2_log_write_endio;
+/**
+ * gfs2_log_alloc_bio - Allocate a new bio for log writing
+ * @sdp: The superblock
+ * @blkno: The next device block number we want to write to
+ *
+ * This should never be called when there is a cached bio in the
+ * super block. When it returns, there will be a cached bio in the
+ * super block which will have as many bio_vecs as the device is
+ * happy to handle.
+ *
+ * Returns: Newly allocated bio
+ */
- return bh;
+static struct bio *gfs2_log_alloc_bio(struct gfs2_sbd *sdp, u64 blkno)
+{
+ struct super_block *sb = sdp->sd_vfs;
+ unsigned nrvecs = bio_get_nr_vecs(sb->s_bdev);
+ struct bio *bio;
+
+ BUG_ON(sdp->sd_log_bio);
+
+ while (1) {
+ bio = bio_alloc(GFP_NOIO, nrvecs);
+ if (likely(bio))
+ break;
+ nrvecs = max(nrvecs/2, 1U);
+ }
+
+ bio->bi_sector = blkno * (sb->s_blocksize >> 9);
+ bio->bi_bdev = sb->s_bdev;
+ bio->bi_end_io = gfs2_end_log_write;
+ bio->bi_private = sdp;
+
+ sdp->sd_log_bio = bio;
+
+ return bio;
}
/**
- * gfs2_fake_write_endio -
- * @bh: The buffer head
- * @uptodate: The I/O Status
+ * gfs2_log_get_bio - Get cached log bio, or allocate a new one
+ * @sdp: The superblock
+ * @blkno: The device block number we want to write to
+ *
+ * If there is a cached bio, then if the next block number is sequential
+ * with the previous one, return it, otherwise flush the bio to the
+ * device. If there is not a cached bio, or we just flushed it, then
+ * allocate a new one.
*
+ * Returns: The bio to use for log writes
*/
-static void gfs2_fake_write_endio(struct buffer_head *bh, int uptodate)
+static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno)
{
- struct buffer_head *real_bh = bh->b_private;
- struct gfs2_bufdata *bd = real_bh->b_private;
- struct gfs2_sbd *sdp = bd->bd_gl->gl_sbd;
+ struct bio *bio = sdp->sd_log_bio;
+ u64 nblk;
+
+ if (bio) {
+ nblk = bio->bi_sector + bio_sectors(bio);
+ nblk >>= sdp->sd_fsb2bb_shift;
+ if (blkno == nblk)
+ return bio;
+ gfs2_log_flush_bio(sdp, WRITE);
+ }
- end_buffer_write_sync(bh, uptodate);
- mempool_free(bh, gfs2_bh_pool);
- unlock_buffer(real_bh);
- brelse(real_bh);
- if (atomic_dec_and_test(&sdp->sd_log_in_flight))
- wake_up(&sdp->sd_log_flush_wait);
+ return gfs2_log_alloc_bio(sdp, blkno);
}
+
/**
- * gfs2_log_fake_buf - Build a fake buffer head to write metadata buffer to log
+ * gfs2_log_write - write to log
* @sdp: the filesystem
- * @data: the data the buffer_head should point to
+ * @page: the page to write
+ * @size: the size of the data to write
+ * @offset: the offset within the page
*
- * Returns: the log buffer descriptor
+ * Try and add the page segment to the current bio. If that fails,
+ * submit the current bio to the device and create a new one, and
+ * then add the page segment to that.
*/
-static struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
- struct buffer_head *real)
+static void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
+ unsigned size, unsigned offset)
{
- u64 blkno = gfs2_log_bmap(sdp, sdp->sd_log_flush_head);
- struct buffer_head *bh;
+ u64 blkno = gfs2_log_bmap(sdp);
+ struct bio *bio;
+ int ret;
+
+ bio = gfs2_log_get_bio(sdp, blkno);
+ ret = bio_add_page(bio, page, size, offset);
+ if (ret == 0) {
+ gfs2_log_flush_bio(sdp, WRITE);
+ bio = gfs2_log_alloc_bio(sdp, blkno);
+ ret = bio_add_page(bio, page, size, offset);
+ WARN_ON(ret == 0);
+ }
+}
+
+/**
+ * gfs2_log_write_bh - write a buffer's content to the log
+ * @sdp: The super block
+ * @bh: The buffer pointing to the in-place location
+ *
+ * This writes the content of the buffer to the next available location
+ * in the log. The buffer will be unlocked once the i/o to the log has
+ * completed.
+ */
- bh = mempool_alloc(gfs2_bh_pool, GFP_NOFS);
- atomic_set(&bh->b_count, 1);
- bh->b_state = (1 << BH_Mapped) | (1 << BH_Uptodate) | (1 << BH_Lock);
- set_bh_page(bh, real->b_page, bh_offset(real));
- bh->b_blocknr = blkno;
- bh->b_size = sdp->sd_sb.sb_bsize;
- bh->b_bdev = sdp->sd_vfs->s_bdev;
- bh->b_private = real;
- bh->b_end_io = gfs2_fake_write_endio;
+static void gfs2_log_write_bh(struct gfs2_sbd *sdp, struct buffer_head *bh)
+{
+ gfs2_log_write(sdp, bh->b_page, bh->b_size, bh_offset(bh));
+}
- gfs2_log_incr_head(sdp);
- atomic_inc(&sdp->sd_log_in_flight);
+/**
+ * gfs2_log_write_page - write one block stored in a page, into the log
+ * @sdp: The superblock
+ * @page: The struct page
+ *
+ * This writes the first block-sized part of the page into the log. Note
+ * that the page must have been allocated from the gfs2_page_pool mempool
+ * and that after this has been called, ownership has been transferred and
+ * the page may be freed at any time.
+ */
- return bh;
+void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page)
+{
+ struct super_block *sb = sdp->sd_vfs;
+ gfs2_log_write(sdp, page, sb->s_blocksize, 0);
}
-static struct buffer_head *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type)
+static struct page *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type,
+ u32 ld_length, u32 ld_data1)
{
- struct buffer_head *bh = gfs2_log_get_buf(sdp);
- struct gfs2_log_descriptor *ld = bh_log_desc(bh);
+ struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
+ struct gfs2_log_descriptor *ld = page_address(page);
+ clear_page(ld);
ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
ld->ld_header.mh_type = cpu_to_be32(GFS2_METATYPE_LD);
ld->ld_header.mh_format = cpu_to_be32(GFS2_FORMAT_LD);
ld->ld_type = cpu_to_be32(ld_type);
- ld->ld_length = 0;
- ld->ld_data1 = 0;
+ ld->ld_length = cpu_to_be32(ld_length);
+ ld->ld_data1 = cpu_to_be32(ld_data1);
ld->ld_data2 = 0;
- memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved));
- return bh;
+ return page;
}
-static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
+static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
{
- struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le);
struct gfs2_meta_header *mh;
struct gfs2_trans *tr;
lock_buffer(bd->bd_bh);
gfs2_log_lock(sdp);
- if (!list_empty(&bd->bd_list_tr))
- goto out;
tr = current->journal_info;
tr->tr_touched = 1;
- tr->tr_num_buf++;
- list_add(&bd->bd_list_tr, &tr->tr_list_buf);
- if (!list_empty(&le->le_list))
+ if (!list_empty(&bd->bd_list))
goto out;
set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
@@ -276,62 +407,86 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
mh->__pad0 = cpu_to_be64(0);
mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);
sdp->sd_log_num_buf++;
- list_add(&le->le_list, &sdp->sd_log_le_buf);
+ list_add(&bd->bd_list, &sdp->sd_log_le_buf);
tr->tr_num_buf_new++;
out:
gfs2_log_unlock(sdp);
unlock_buffer(bd->bd_bh);
}
-static void buf_lo_before_commit(struct gfs2_sbd *sdp)
+static void gfs2_check_magic(struct buffer_head *bh)
+{
+ void *kaddr;
+ __be32 *ptr;
+
+ clear_buffer_escaped(bh);
+ kaddr = kmap_atomic(bh->b_page);
+ ptr = kaddr + bh_offset(bh);
+ if (*ptr == cpu_to_be32(GFS2_MAGIC))
+ set_buffer_escaped(bh);
+ kunmap_atomic(kaddr);
+}
+
+static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit,
+ unsigned int total, struct list_head *blist,
+ bool is_databuf)
{
- struct buffer_head *bh;
struct gfs2_log_descriptor *ld;
struct gfs2_bufdata *bd1 = NULL, *bd2;
- unsigned int total;
- unsigned int limit;
+ struct page *page;
unsigned int num;
unsigned n;
__be64 *ptr;
- limit = buf_limit(sdp);
- /* for 4k blocks, limit = 503 */
-
gfs2_log_lock(sdp);
- total = sdp->sd_log_num_buf;
- bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list);
+ bd1 = bd2 = list_prepare_entry(bd1, blist, bd_list);
while(total) {
num = total;
if (total > limit)
num = limit;
gfs2_log_unlock(sdp);
- bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_METADATA);
+ page = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_METADATA, num + 1, num);
+ ld = page_address(page);
gfs2_log_lock(sdp);
- ld = bh_log_desc(bh);
- ptr = bh_log_ptr(bh);
- ld->ld_length = cpu_to_be32(num + 1);
- ld->ld_data1 = cpu_to_be32(num);
+ ptr = (__be64 *)(ld + 1);
n = 0;
- list_for_each_entry_continue(bd1, &sdp->sd_log_le_buf,
- bd_le.le_list) {
+ list_for_each_entry_continue(bd1, blist, bd_list) {
*ptr++ = cpu_to_be64(bd1->bd_bh->b_blocknr);
+ if (is_databuf) {
+ gfs2_check_magic(bd1->bd_bh);
+ *ptr++ = cpu_to_be64(buffer_escaped(bd1->bd_bh) ? 1 : 0);
+ }
if (++n >= num)
break;
}
gfs2_log_unlock(sdp);
- submit_bh(WRITE_SYNC, bh);
+ gfs2_log_write_page(sdp, page);
gfs2_log_lock(sdp);
n = 0;
- list_for_each_entry_continue(bd2, &sdp->sd_log_le_buf,
- bd_le.le_list) {
+ list_for_each_entry_continue(bd2, blist, bd_list) {
get_bh(bd2->bd_bh);
gfs2_log_unlock(sdp);
lock_buffer(bd2->bd_bh);
- bh = gfs2_log_fake_buf(sdp, bd2->bd_bh);
- submit_bh(WRITE_SYNC, bh);
+
+ if (buffer_escaped(bd2->bd_bh)) {
+ void *kaddr;
+ page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
+ ptr = page_address(page);
+ kaddr = kmap_atomic(bd2->bd_bh->b_page);
+ memcpy(ptr, kaddr + bh_offset(bd2->bd_bh),
+ bd2->bd_bh->b_size);
+ kunmap_atomic(kaddr);
+ *(__be32 *)ptr = 0;
+ clear_buffer_escaped(bd2->bd_bh);
+ unlock_buffer(bd2->bd_bh);
+ brelse(bd2->bd_bh);
+ gfs2_log_write_page(sdp, page);
+ } else {
+ gfs2_log_write_bh(sdp, bd2->bd_bh);
+ }
gfs2_log_lock(sdp);
if (++n >= num)
break;
@@ -343,14 +498,22 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
gfs2_log_unlock(sdp);
}
+static void buf_lo_before_commit(struct gfs2_sbd *sdp)
+{
+ unsigned int limit = buf_limit(sdp); /* 503 for 4k blocks */
+
+ gfs2_before_commit(sdp, limit, sdp->sd_log_num_buf,
+ &sdp->sd_log_le_buf, 0);
+}
+
static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
{
struct list_head *head = &sdp->sd_log_le_buf;
struct gfs2_bufdata *bd;
while (!list_empty(head)) {
- bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list);
- list_del_init(&bd->bd_le.le_list);
+ bd = list_entry(head->next, struct gfs2_bufdata, bd_list);
+ list_del_init(&bd->bd_list);
sdp->sd_log_num_buf--;
gfs2_unpin(sdp, bd->bd_bh, ai);
@@ -437,9 +600,8 @@ static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks);
}
-static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
+static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
{
- struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le);
struct gfs2_glock *gl = bd->bd_gl;
struct gfs2_trans *tr;
@@ -449,48 +611,48 @@ static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
sdp->sd_log_num_revoke++;
atomic_inc(&gl->gl_revokes);
set_bit(GLF_LFLUSH, &gl->gl_flags);
- list_add(&le->le_list, &sdp->sd_log_le_revoke);
+ list_add(&bd->bd_list, &sdp->sd_log_le_revoke);
}
static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
{
struct gfs2_log_descriptor *ld;
struct gfs2_meta_header *mh;
- struct buffer_head *bh;
unsigned int offset;
struct list_head *head = &sdp->sd_log_le_revoke;
struct gfs2_bufdata *bd;
+ struct page *page;
+ unsigned int length;
if (!sdp->sd_log_num_revoke)
return;
- bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_REVOKE);
- ld = bh_log_desc(bh);
- ld->ld_length = cpu_to_be32(gfs2_struct2blk(sdp, sdp->sd_log_num_revoke,
- sizeof(u64)));
- ld->ld_data1 = cpu_to_be32(sdp->sd_log_num_revoke);
+ length = gfs2_struct2blk(sdp, sdp->sd_log_num_revoke, sizeof(u64));
+ page = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_REVOKE, length, sdp->sd_log_num_revoke);
+ ld = page_address(page);
offset = sizeof(struct gfs2_log_descriptor);
- list_for_each_entry(bd, head, bd_le.le_list) {
+ list_for_each_entry(bd, head, bd_list) {
sdp->sd_log_num_revoke--;
if (offset + sizeof(u64) > sdp->sd_sb.sb_bsize) {
- submit_bh(WRITE_SYNC, bh);
- bh = gfs2_log_get_buf(sdp);
- mh = (struct gfs2_meta_header *)bh->b_data;
+ gfs2_log_write_page(sdp, page);
+ page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
+ mh = page_address(page);
+ clear_page(mh);
mh->mh_magic = cpu_to_be32(GFS2_MAGIC);
mh->mh_type = cpu_to_be32(GFS2_METATYPE_LB);
mh->mh_format = cpu_to_be32(GFS2_FORMAT_LB);
offset = sizeof(struct gfs2_meta_header);
}
- *(__be64 *)(bh->b_data + offset) = cpu_to_be64(bd->bd_blkno);
+ *(__be64 *)(page_address(page) + offset) = cpu_to_be64(bd->bd_blkno);
offset += sizeof(u64);
}
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
- submit_bh(WRITE_SYNC, bh);
+ gfs2_log_write_page(sdp, page);
}
static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
@@ -500,8 +662,8 @@ static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
struct gfs2_glock *gl;
while (!list_empty(head)) {
- bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list);
- list_del_init(&bd->bd_le.le_list);
+ bd = list_entry(head->next, struct gfs2_bufdata, bd_list);
+ list_del_init(&bd->bd_list);
gl = bd->bd_gl;
atomic_dec(&gl->gl_revokes);
clear_bit(GLF_LFLUSH, &gl->gl_flags);
@@ -604,108 +766,33 @@ static void revoke_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
* blocks, which isn't an enormous overhead but twice as much as
* for normal metadata blocks.
*/
-static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
+static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
{
- struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le);
struct gfs2_trans *tr = current->journal_info;
struct address_space *mapping = bd->bd_bh->b_page->mapping;
struct gfs2_inode *ip = GFS2_I(mapping->host);
lock_buffer(bd->bd_bh);
gfs2_log_lock(sdp);
- if (tr) {
- if (!list_empty(&bd->bd_list_tr))
- goto out;
+ if (tr)
tr->tr_touched = 1;
- if (gfs2_is_jdata(ip)) {
- tr->tr_num_buf++;
- list_add(&bd->bd_list_tr, &tr->tr_list_buf);
- }
- }
- if (!list_empty(&le->le_list))
+ if (!list_empty(&bd->bd_list))
goto out;
-
set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
if (gfs2_is_jdata(ip)) {
gfs2_pin(sdp, bd->bd_bh);
tr->tr_num_databuf_new++;
sdp->sd_log_num_databuf++;
- list_add_tail(&le->le_list, &sdp->sd_log_le_databuf);
+ list_add_tail(&bd->bd_list, &sdp->sd_log_le_databuf);
} else {
- list_add_tail(&le->le_list, &sdp->sd_log_le_ordered);
+ list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered);
}
out:
gfs2_log_unlock(sdp);
unlock_buffer(bd->bd_bh);
}
-static void gfs2_check_magic(struct buffer_head *bh)
-{
- void *kaddr;
- __be32 *ptr;
-
- clear_buffer_escaped(bh);
- kaddr = kmap_atomic(bh->b_page);
- ptr = kaddr + bh_offset(bh);
- if (*ptr == cpu_to_be32(GFS2_MAGIC))
- set_buffer_escaped(bh);
- kunmap_atomic(kaddr);
-}
-
-static void gfs2_write_blocks(struct gfs2_sbd *sdp, struct buffer_head *bh,
- struct list_head *list, struct list_head *done,
- unsigned int n)
-{
- struct buffer_head *bh1;
- struct gfs2_log_descriptor *ld;
- struct gfs2_bufdata *bd;
- __be64 *ptr;
-
- if (!bh)
- return;
-
- ld = bh_log_desc(bh);
- ld->ld_length = cpu_to_be32(n + 1);
- ld->ld_data1 = cpu_to_be32(n);
-
- ptr = bh_log_ptr(bh);
-
- get_bh(bh);
- submit_bh(WRITE_SYNC, bh);
- gfs2_log_lock(sdp);
- while(!list_empty(list)) {
- bd = list_entry(list->next, struct gfs2_bufdata, bd_le.le_list);
- list_move_tail(&bd->bd_le.le_list, done);
- get_bh(bd->bd_bh);
- while (be64_to_cpu(*ptr) != bd->bd_bh->b_blocknr) {
- gfs2_log_incr_head(sdp);
- ptr += 2;
- }
- gfs2_log_unlock(sdp);
- lock_buffer(bd->bd_bh);
- if (buffer_escaped(bd->bd_bh)) {
- void *kaddr;
- bh1 = gfs2_log_get_buf(sdp);
- kaddr = kmap_atomic(bd->bd_bh->b_page);
- memcpy(bh1->b_data, kaddr + bh_offset(bd->bd_bh),
- bh1->b_size);
- kunmap_atomic(kaddr);
- *(__be32 *)bh1->b_data = 0;
- clear_buffer_escaped(bd->bd_bh);
- unlock_buffer(bd->bd_bh);
- brelse(bd->bd_bh);
- } else {
- bh1 = gfs2_log_fake_buf(sdp, bd->bd_bh);
- }
- submit_bh(WRITE_SYNC, bh1);
- gfs2_log_lock(sdp);
- ptr += 2;
- }
- gfs2_log_unlock(sdp);
- brelse(bh);
-}
-
/**
* databuf_lo_before_commit - Scan the data buffers, writing as we go
*
@@ -713,37 +800,10 @@ static void gfs2_write_blocks(struct gfs2_sbd *sdp, struct buffer_head *bh,
static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
{
- struct gfs2_bufdata *bd = NULL;
- struct buffer_head *bh = NULL;
- unsigned int n = 0;
- __be64 *ptr = NULL, *end = NULL;
- LIST_HEAD(processed);
- LIST_HEAD(in_progress);
+ unsigned int limit = buf_limit(sdp) / 2;
- gfs2_log_lock(sdp);
- while (!list_empty(&sdp->sd_log_le_databuf)) {
- if (ptr == end) {
- gfs2_log_unlock(sdp);
- gfs2_write_blocks(sdp, bh, &in_progress, &processed, n);
- n = 0;
- bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_JDATA);
- ptr = bh_log_ptr(bh);
- end = bh_ptr_end(bh) - 1;
- gfs2_log_lock(sdp);
- continue;
- }
- bd = list_entry(sdp->sd_log_le_databuf.next, struct gfs2_bufdata, bd_le.le_list);
- list_move_tail(&bd->bd_le.le_list, &in_progress);
- gfs2_check_magic(bd->bd_bh);
- *ptr++ = cpu_to_be64(bd->bd_bh->b_blocknr);
- *ptr++ = cpu_to_be64(buffer_escaped(bh) ? 1 : 0);
- n++;
- }
- gfs2_log_unlock(sdp);
- gfs2_write_blocks(sdp, bh, &in_progress, &processed, n);
- gfs2_log_lock(sdp);
- list_splice(&processed, &sdp->sd_log_le_databuf);
- gfs2_log_unlock(sdp);
+ gfs2_before_commit(sdp, limit, sdp->sd_log_num_databuf,
+ &sdp->sd_log_le_databuf, 1);
}
static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
@@ -822,8 +882,8 @@ static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
struct gfs2_bufdata *bd;
while (!list_empty(head)) {
- bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list);
- list_del_init(&bd->bd_le.le_list);
+ bd = list_entry(head->next, struct gfs2_bufdata, bd_list);
+ list_del_init(&bd->bd_list);
sdp->sd_log_num_databuf--;
gfs2_unpin(sdp, bd->bd_bh, ai);
}
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h
index 3c0b2737658a..954a330585f4 100644
--- a/fs/gfs2/lops.h
+++ b/fs/gfs2/lops.h
@@ -27,6 +27,8 @@ extern const struct gfs2_log_operations gfs2_rg_lops;
extern const struct gfs2_log_operations gfs2_databuf_lops;
extern const struct gfs2_log_operations *gfs2_log_ops[];
+extern void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page);
+extern void gfs2_log_flush_bio(struct gfs2_sbd *sdp, int rw);
static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
{
@@ -44,17 +46,17 @@ static inline unsigned int databuf_limit(struct gfs2_sbd *sdp)
return limit;
}
-static inline void lops_init_le(struct gfs2_log_element *le,
+static inline void lops_init_le(struct gfs2_bufdata *bd,
const struct gfs2_log_operations *lops)
{
- INIT_LIST_HEAD(&le->le_list);
- le->le_ops = lops;
+ INIT_LIST_HEAD(&bd->bd_list);
+ bd->bd_ops = lops;
}
-static inline void lops_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
+static inline void lops_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
{
- if (le->le_ops->lo_add)
- le->le_ops->lo_add(sdp, le);
+ if (bd->bd_ops->lo_add)
+ bd->bd_ops->lo_add(sdp, bd);
}
static inline void lops_before_commit(struct gfs2_sbd *sdp)
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index 754426b1e52c..6cdb0f2a1b09 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -70,16 +70,6 @@ static void gfs2_init_gl_aspace_once(void *foo)
address_space_init_once(mapping);
}
-static void *gfs2_bh_alloc(gfp_t mask, void *data)
-{
- return alloc_buffer_head(mask);
-}
-
-static void gfs2_bh_free(void *ptr, void *data)
-{
- return free_buffer_head(ptr);
-}
-
/**
* init_gfs2_fs - Register GFS2 as a filesystem
*
@@ -143,6 +133,12 @@ static int __init init_gfs2_fs(void)
if (!gfs2_quotad_cachep)
goto fail;
+ gfs2_rsrv_cachep = kmem_cache_create("gfs2_mblk",
+ sizeof(struct gfs2_blkreserv),
+ 0, 0, NULL);
+ if (!gfs2_rsrv_cachep)
+ goto fail;
+
register_shrinker(&qd_shrinker);
error = register_filesystem(&gfs2_fs_type);
@@ -164,8 +160,8 @@ static int __init init_gfs2_fs(void)
if (!gfs2_control_wq)
goto fail_recovery;
- gfs2_bh_pool = mempool_create(1024, gfs2_bh_alloc, gfs2_bh_free, NULL);
- if (!gfs2_bh_pool)
+ gfs2_page_pool = mempool_create_page_pool(64, 0);
+ if (!gfs2_page_pool)
goto fail_control;
gfs2_register_debugfs();
@@ -186,6 +182,9 @@ fail:
unregister_shrinker(&qd_shrinker);
gfs2_glock_exit();
+ if (gfs2_rsrv_cachep)
+ kmem_cache_destroy(gfs2_rsrv_cachep);
+
if (gfs2_quotad_cachep)
kmem_cache_destroy(gfs2_quotad_cachep);
@@ -225,7 +224,8 @@ static void __exit exit_gfs2_fs(void)
rcu_barrier();
- mempool_destroy(gfs2_bh_pool);
+ mempool_destroy(gfs2_page_pool);
+ kmem_cache_destroy(gfs2_rsrv_cachep);
kmem_cache_destroy(gfs2_quotad_cachep);
kmem_cache_destroy(gfs2_rgrpd_cachep);
kmem_cache_destroy(gfs2_bufdata_cachep);
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 181586e673f9..6c1e5d1c404a 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -293,11 +293,10 @@ void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh,
bd->bd_bh = bh;
bd->bd_gl = gl;
- INIT_LIST_HEAD(&bd->bd_list_tr);
if (meta)
- lops_init_le(&bd->bd_le, &gfs2_buf_lops);
+ lops_init_le(bd, &gfs2_buf_lops);
else
- lops_init_le(&bd->bd_le, &gfs2_databuf_lops);
+ lops_init_le(bd, &gfs2_databuf_lops);
bh->b_private = bd;
if (meta)
@@ -313,7 +312,7 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
if (test_clear_buffer_pinned(bh)) {
trace_gfs2_pin(bd, 0);
atomic_dec(&sdp->sd_log_pinned);
- list_del_init(&bd->bd_le.le_list);
+ list_del_init(&bd->bd_list);
if (meta) {
gfs2_assert_warn(sdp, sdp->sd_log_num_buf);
sdp->sd_log_num_buf--;
@@ -375,33 +374,24 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)
* @ip: The GFS2 inode
* @height: The level of this buf in the metadata (indir addr) tree (if any)
* @num: The block number (device relative) of the buffer
- * @new: Non-zero if we may create a new buffer
* @bhp: the buffer is returned here
*
* Returns: errno
*/
int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
- int new, struct buffer_head **bhp)
+ struct buffer_head **bhp)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_glock *gl = ip->i_gl;
struct buffer_head *bh;
int ret = 0;
+ u32 mtype = height ? GFS2_METATYPE_IN : GFS2_METATYPE_DI;
- if (new) {
- BUG_ON(height == 0);
- bh = gfs2_meta_new(gl, num);
- gfs2_trans_add_bh(ip->i_gl, bh, 1);
- gfs2_metatype_set(bh, GFS2_METATYPE_IN, GFS2_FORMAT_IN);
- gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
- } else {
- u32 mtype = height ? GFS2_METATYPE_IN : GFS2_METATYPE_DI;
- ret = gfs2_meta_read(gl, num, DIO_WAIT, &bh);
- if (ret == 0 && gfs2_metatype_check(sdp, bh, mtype)) {
- brelse(bh);
- ret = -EIO;
- }
+ ret = gfs2_meta_read(gl, num, DIO_WAIT, &bh);
+ if (ret == 0 && gfs2_metatype_check(sdp, bh, mtype)) {
+ brelse(bh);
+ ret = -EIO;
}
*bhp = bh;
return ret;
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index 22c526593131..c30973b07a7c 100644
--- a/fs/gfs2/meta_io.h
+++ b/fs/gfs2/meta_io.h
@@ -65,12 +65,12 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr,
void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen);
int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
- int new, struct buffer_head **bhp);
+ struct buffer_head **bhp);
static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip,
struct buffer_head **bhp)
{
- return gfs2_meta_indirect_buffer(ip, 0, ip->i_no_addr, 0, bhp);
+ return gfs2_meta_indirect_buffer(ip, 0, ip->i_no_addr, bhp);
}
struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen);
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 6f3a18f9e176..b8c250fc4922 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -99,7 +99,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
atomic_set(&sdp->sd_log_pinned, 0);
INIT_LIST_HEAD(&sdp->sd_log_le_buf);
INIT_LIST_HEAD(&sdp->sd_log_le_revoke);
- INIT_LIST_HEAD(&sdp->sd_log_le_rg);
INIT_LIST_HEAD(&sdp->sd_log_le_databuf);
INIT_LIST_HEAD(&sdp->sd_log_le_ordered);
@@ -994,6 +993,7 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
ls->ls_jid = option;
break;
case Opt_id:
+ case Opt_nodir:
/* Obsolete, but left for backward compat purposes */
break;
case Opt_first:
@@ -1002,12 +1002,6 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
goto hostdata_error;
ls->ls_first = option;
break;
- case Opt_nodir:
- ret = match_int(&tmp[0], &option);
- if (ret || (option != 0 && option != 1))
- goto hostdata_error;
- ls->ls_nodir = option;
- break;
case Opt_err:
default:
hostdata_error:
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 6019da3dcaed..b97178e7d397 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -652,7 +652,7 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
}
memset(&q, 0, sizeof(struct gfs2_quota));
- err = gfs2_internal_read(ip, NULL, (char *)&q, &loc, sizeof(q));
+ err = gfs2_internal_read(ip, (char *)&q, &loc, sizeof(q));
if (err < 0)
return err;
@@ -744,7 +744,7 @@ get_a_page:
i_size_write(inode, size);
inode->i_mtime = inode->i_atime = CURRENT_TIME;
mark_inode_dirty(inode);
- return err;
+ return 0;
unlock_out:
unlock_page(page);
@@ -852,7 +852,7 @@ static int update_qd(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd)
memset(&q, 0, sizeof(struct gfs2_quota));
pos = qd2offset(qd);
- error = gfs2_internal_read(ip, NULL, (char *)&q, &pos, sizeof(q));
+ error = gfs2_internal_read(ip, (char *)&q, &pos, sizeof(q));
if (error < 0)
return error;
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 3df65c9ab73b..f74fb9bd1973 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -70,15 +70,15 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
/**
* gfs2_setbit - Set a bit in the bitmaps
- * @buffer: the buffer that holds the bitmaps
- * @buflen: the length (in bytes) of the buffer
+ * @rgd: the resource group descriptor
+ * @buf2: the clone buffer that holds the bitmaps
+ * @bi: the bitmap structure
* @block: the block to set
* @new_state: the new state of the block
*
*/
-static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1,
- unsigned char *buf2, unsigned int offset,
+static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf2,
struct gfs2_bitmap *bi, u32 block,
unsigned char new_state)
{
@@ -86,8 +86,8 @@ static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1,
unsigned int buflen = bi->bi_len;
const unsigned int bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE;
- byte1 = buf1 + offset + (block / GFS2_NBBY);
- end = buf1 + offset + buflen;
+ byte1 = bi->bi_bh->b_data + bi->bi_offset + (block / GFS2_NBBY);
+ end = bi->bi_bh->b_data + bi->bi_offset + buflen;
BUG_ON(byte1 >= end);
@@ -110,7 +110,7 @@ static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1,
*byte1 ^= (cur_state ^ new_state) << bit;
if (buf2) {
- byte2 = buf2 + offset + (block / GFS2_NBBY);
+ byte2 = buf2 + bi->bi_offset + (block / GFS2_NBBY);
cur_state = (*byte2 >> bit) & GFS2_BIT_MASK;
*byte2 ^= (cur_state ^ new_state) << bit;
}
@@ -118,6 +118,7 @@ static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1,
/**
* gfs2_testbit - test a bit in the bitmaps
+ * @rgd: the resource group descriptor
* @buffer: the buffer that holds the bitmaps
* @buflen: the length (in bytes) of the buffer
* @block: the block to read
@@ -179,7 +180,7 @@ static inline u64 gfs2_bit_search(const __le64 *ptr, u64 mask, u8 state)
/**
* gfs2_bitfit - Search an rgrp's bitmap buffer to find a bit-pair representing
* a block in a given allocation state.
- * @buffer: the buffer that holds the bitmaps
+ * @buf: the buffer that holds the bitmaps
* @len: the length (in bytes) of the buffer
* @goal: start search at this block's bit-pair (within @buffer)
* @state: GFS2_BLKST_XXX the state of the block we're looking for.
@@ -231,6 +232,7 @@ static u32 gfs2_bitfit(const u8 *buf, const unsigned int len,
/**
* gfs2_bitcount - count the number of bits in a certain state
+ * @rgd: the resource group descriptor
* @buffer: the buffer that holds the bitmaps
* @buflen: the length (in bytes) of the buffer
* @state: the state of the block we're looking for
@@ -264,7 +266,6 @@ static u32 gfs2_bitcount(struct gfs2_rgrpd *rgd, const u8 *buffer,
/**
* gfs2_rgrp_verify - Verify that a resource group is consistent
- * @sdp: the filesystem
* @rgd: the rgrp
*
*/
@@ -322,7 +323,8 @@ static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block)
/**
* gfs2_blk2rgrpd - Find resource group for a given data/meta block number
* @sdp: The GFS2 superblock
- * @n: The data block number
+ * @blk: The data block number
+ * @exact: True if this needs to be an exact match
*
* Returns: The resource group, or NULL if not found
*/
@@ -380,7 +382,7 @@ struct gfs2_rgrpd *gfs2_rgrpd_get_first(struct gfs2_sbd *sdp)
/**
* gfs2_rgrpd_get_next - get the next RG
- * @rgd: A RG
+ * @rgd: the resource group descriptor
*
* Returns: The next rgrp
*/
@@ -529,6 +531,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
/**
* gfs2_ri_total - Total up the file system space, according to the rindex.
+ * @sdp: the filesystem
*
*/
u64 gfs2_ri_total(struct gfs2_sbd *sdp)
@@ -537,16 +540,14 @@ u64 gfs2_ri_total(struct gfs2_sbd *sdp)
struct inode *inode = sdp->sd_rindex;
struct gfs2_inode *ip = GFS2_I(inode);
char buf[sizeof(struct gfs2_rindex)];
- struct file_ra_state ra_state;
int error, rgrps;
- file_ra_state_init(&ra_state, inode->i_mapping);
for (rgrps = 0;; rgrps++) {
loff_t pos = rgrps * sizeof(struct gfs2_rindex);
if (pos + sizeof(struct gfs2_rindex) > i_size_read(inode))
break;
- error = gfs2_internal_read(ip, &ra_state, buf, &pos,
+ error = gfs2_internal_read(ip, buf, &pos,
sizeof(struct gfs2_rindex));
if (error != sizeof(struct gfs2_rindex))
break;
@@ -582,13 +583,12 @@ static int rgd_insert(struct gfs2_rgrpd *rgd)
/**
* read_rindex_entry - Pull in a new resource index entry from the disk
- * @gl: The glock covering the rindex inode
+ * @ip: Pointer to the rindex inode
*
* Returns: 0 on success, > 0 on EOF, error code otherwise
*/
-static int read_rindex_entry(struct gfs2_inode *ip,
- struct file_ra_state *ra_state)
+static int read_rindex_entry(struct gfs2_inode *ip)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
@@ -599,7 +599,7 @@ static int read_rindex_entry(struct gfs2_inode *ip,
if (pos >= i_size_read(&ip->i_inode))
return 1;
- error = gfs2_internal_read(ip, ra_state, (char *)&buf, &pos,
+ error = gfs2_internal_read(ip, (char *)&buf, &pos,
sizeof(struct gfs2_rindex));
if (error != sizeof(struct gfs2_rindex))
@@ -655,13 +655,10 @@ fail:
static int gfs2_ri_update(struct gfs2_inode *ip)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
- struct inode *inode = &ip->i_inode;
- struct file_ra_state ra_state;
int error;
- file_ra_state_init(&ra_state, inode->i_mapping);
do {
- error = read_rindex_entry(ip, &ra_state);
+ error = read_rindex_entry(ip);
} while (error == 0);
if (error < 0)
@@ -741,7 +738,7 @@ static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf)
/**
* gfs2_rgrp_go_lock - Read in a RG's header and bitmaps
- * @rgd: the struct gfs2_rgrpd describing the RG to read in
+ * @gh: The glock holder for the resource group
*
* Read in all of a Resource Group's header and bitmap blocks.
* Caller must eventually call gfs2_rgrp_relse() to free the bitmaps.
@@ -801,7 +798,7 @@ fail:
/**
* gfs2_rgrp_go_unlock - Release RG bitmaps read in with gfs2_rgrp_bh_get()
- * @rgd: the struct gfs2_rgrpd describing the RG to read in
+ * @gh: The glock holder for the resource group
*
*/
@@ -1002,11 +999,13 @@ struct gfs2_qadata *gfs2_qadata_get(struct gfs2_inode *ip)
* Returns: the struct gfs2_qadata
*/
-static struct gfs2_blkreserv *gfs2_blkrsv_get(struct gfs2_inode *ip)
+static int gfs2_blkrsv_get(struct gfs2_inode *ip)
{
BUG_ON(ip->i_res != NULL);
- ip->i_res = kzalloc(sizeof(struct gfs2_blkreserv), GFP_NOFS);
- return ip->i_res;
+ ip->i_res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS);
+ if (!ip->i_res)
+ return -ENOMEM;
+ return 0;
}
/**
@@ -1038,6 +1037,8 @@ static inline u32 gfs2_bi2rgd_blk(struct gfs2_bitmap *bi, u32 blk)
/**
* try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes
* @rgd: The rgrp
+ * @last_unlinked: block address of the last dinode we unlinked
+ * @skip: block address we should explicitly not unlink
*
* Returns: 0 if no error
* The inode, if one has been found, in inode.
@@ -1102,7 +1103,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
/**
* get_local_rgrp - Choose and lock a rgrp for allocation
* @ip: the inode to reserve space for
- * @rgp: the chosen and locked rgrp
+ * @last_unlinked: the last unlinked block
*
* Try to acquire rgrp in way which avoids contending with others.
*
@@ -1164,13 +1165,14 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
static void gfs2_blkrsv_put(struct gfs2_inode *ip)
{
BUG_ON(ip->i_res == NULL);
- kfree(ip->i_res);
+ kmem_cache_free(gfs2_rsrv_cachep, ip->i_res);
ip->i_res = NULL;
}
/**
* gfs2_inplace_reserve - Reserve space in the filesystem
* @ip: the inode to reserve space for
+ * @requested: the number of blocks to be reserved
*
* Returns: errno
*/
@@ -1179,14 +1181,15 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_blkreserv *rs;
- int error = 0;
+ int error;
u64 last_unlinked = NO_BLOCK;
int tries = 0;
- rs = gfs2_blkrsv_get(ip);
- if (!rs)
- return -ENOMEM;
+ error = gfs2_blkrsv_get(ip);
+ if (error)
+ return error;
+ rs = ip->i_res;
rs->rs_requested = requested;
if (gfs2_assert_warn(sdp, requested)) {
error = -EINVAL;
@@ -1268,7 +1271,6 @@ static unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
* @rgd: the resource group descriptor
* @goal: the goal block within the RG (start here to search for avail block)
* @state: GFS2_BLKST_XXX the before-allocation state to find
- * @dinode: TRUE if the first block we allocate is for a dinode
* @rbi: address of the pointer to the bitmap containing the block found
*
* Walk rgrp's bitmap to find bits that represent a block in @state.
@@ -1282,13 +1284,12 @@ static unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
* Returns: the block number found relative to the bitmap rbi
*/
-static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
- unsigned char state,
+static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, unsigned char state,
struct gfs2_bitmap **rbi)
{
struct gfs2_bitmap *bi = NULL;
const u32 length = rgd->rd_length;
- u32 blk = BFITNOENT;
+ u32 biblk = BFITNOENT;
unsigned int buf, x;
const u8 *buffer = NULL;
@@ -1325,8 +1326,8 @@ do_search:
if (state != GFS2_BLKST_UNLINKED && bi->bi_clone)
buffer = bi->bi_clone + bi->bi_offset;
- blk = gfs2_bitfit(buffer, bi->bi_len, goal, state);
- if (blk != BFITNOENT)
+ biblk = gfs2_bitfit(buffer, bi->bi_len, goal, state);
+ if (biblk != BFITNOENT)
break;
if ((goal == 0) && (state == GFS2_BLKST_FREE))
@@ -1339,10 +1340,10 @@ skip:
goal = 0;
}
- if (blk != BFITNOENT)
+ if (biblk != BFITNOENT)
*rbi = bi;
- return blk;
+ return biblk;
}
/**
@@ -1367,8 +1368,8 @@ static u64 gfs2_alloc_extent(struct gfs2_rgrpd *rgd, struct gfs2_bitmap *bi,
*n = 0;
buffer = bi->bi_bh->b_data + bi->bi_offset;
gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
- gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset,
- bi, blk, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);
+ gfs2_setbit(rgd, bi->bi_clone, bi, blk,
+ dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);
(*n)++;
goal = blk;
while (*n < elen) {
@@ -1378,8 +1379,7 @@ static u64 gfs2_alloc_extent(struct gfs2_rgrpd *rgd, struct gfs2_bitmap *bi,
if (gfs2_testbit(rgd, buffer, bi->bi_len, goal) !=
GFS2_BLKST_FREE)
break;
- gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset,
- bi, goal, GFS2_BLKST_USED);
+ gfs2_setbit(rgd, bi->bi_clone, bi, goal, GFS2_BLKST_USED);
(*n)++;
}
blk = gfs2_bi2rgd_blk(bi, blk);
@@ -1436,8 +1436,7 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
bi->bi_len);
}
gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
- gfs2_setbit(rgd, bi->bi_bh->b_data, NULL, bi->bi_offset,
- bi, buf_blk, new_state);
+ gfs2_setbit(rgd, NULL, bi, buf_blk, new_state);
}
return rgd;
@@ -1557,7 +1556,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
ip->i_inode.i_gid);
rgd->rd_free_clone -= *nblocks;
- trace_gfs2_block_alloc(ip, block, *nblocks,
+ trace_gfs2_block_alloc(ip, rgd, block, *nblocks,
dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);
*bn = block;
return 0;
@@ -1584,7 +1583,7 @@ void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta)
rgd = rgblk_free(sdp, bstart, blen, GFS2_BLKST_FREE);
if (!rgd)
return;
- trace_gfs2_block_alloc(ip, bstart, blen, GFS2_BLKST_FREE);
+ trace_gfs2_block_alloc(ip, rgd, bstart, blen, GFS2_BLKST_FREE);
rgd->rd_free += blen;
rgd->rd_flags &= ~GFS2_RGF_TRIMMED;
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
@@ -1622,7 +1621,7 @@ void gfs2_unlink_di(struct inode *inode)
rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_UNLINKED);
if (!rgd)
return;
- trace_gfs2_block_alloc(ip, blkno, 1, GFS2_BLKST_UNLINKED);
+ trace_gfs2_block_alloc(ip, rgd, blkno, 1, GFS2_BLKST_UNLINKED);
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
}
@@ -1652,7 +1651,7 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)
void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip)
{
gfs2_free_uninit_di(rgd, ip->i_no_addr);
- trace_gfs2_block_alloc(ip, ip->i_no_addr, 1, GFS2_BLKST_FREE);
+ trace_gfs2_block_alloc(ip, rgd, ip->i_no_addr, 1, GFS2_BLKST_FREE);
gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid);
gfs2_meta_wipe(ip, ip->i_no_addr, 1);
}
@@ -1752,7 +1751,6 @@ void gfs2_rlist_add(struct gfs2_inode *ip, struct gfs2_rgrp_list *rlist,
* and initialize an array of glock holders for them
* @rlist: the list of resource groups
* @state: the lock state to acquire the RG lock in
- * @flags: the modifier flags for the holder structures
*
* FIXME: Don't use NOFAIL
*
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index d33172c291ba..9c2592b1d5ff 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -368,10 +368,7 @@ int gfs2_recover_set(struct gfs2_sbd *sdp, unsigned jid)
struct gfs2_jdesc *jd;
int rv;
- rv = -ESHUTDOWN;
spin_lock(&sdp->sd_jindex_spin);
- if (test_bit(SDF_NORECOVERY, &sdp->sd_flags))
- goto out;
rv = -EBUSY;
if (sdp->sd_jdesc->jd_jid == jid)
goto out;
@@ -396,8 +393,13 @@ static ssize_t recover_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
if (rv != 1)
return -EINVAL;
- rv = gfs2_recover_set(sdp, jid);
+ if (test_bit(SDF_NORECOVERY, &sdp->sd_flags)) {
+ rv = -ESHUTDOWN;
+ goto out;
+ }
+ rv = gfs2_recover_set(sdp, jid);
+out:
return rv ? rv : len;
}
diff --git a/fs/gfs2/trace_gfs2.h b/fs/gfs2/trace_gfs2.h
index dfa89cd75534..1b8b81588199 100644
--- a/fs/gfs2/trace_gfs2.h
+++ b/fs/gfs2/trace_gfs2.h
@@ -457,10 +457,10 @@ TRACE_EVENT(gfs2_bmap,
/* Keep track of blocks as they are allocated/freed */
TRACE_EVENT(gfs2_block_alloc,
- TP_PROTO(const struct gfs2_inode *ip, u64 block, unsigned len,
- u8 block_state),
+ TP_PROTO(const struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
+ u64 block, unsigned len, u8 block_state),
- TP_ARGS(ip, block, len, block_state),
+ TP_ARGS(ip, rgd, block, len, block_state),
TP_STRUCT__entry(
__field( dev_t, dev )
@@ -468,6 +468,8 @@ TRACE_EVENT(gfs2_block_alloc,
__field( u64, inum )
__field( u32, len )
__field( u8, block_state )
+ __field( u64, rd_addr )
+ __field( u32, rd_free_clone )
),
TP_fast_assign(
@@ -476,14 +478,18 @@ TRACE_EVENT(gfs2_block_alloc,
__entry->inum = ip->i_no_addr;
__entry->len = len;
__entry->block_state = block_state;
+ __entry->rd_addr = rgd->rd_addr;
+ __entry->rd_free_clone = rgd->rd_free_clone;
),
- TP_printk("%u,%u bmap %llu alloc %llu/%lu %s",
+ TP_printk("%u,%u bmap %llu alloc %llu/%lu %s rg:%llu rf:%u",
MAJOR(__entry->dev), MINOR(__entry->dev),
(unsigned long long)__entry->inum,
(unsigned long long)__entry->start,
(unsigned long)__entry->len,
- block_state_name(__entry->block_state))
+ block_state_name(__entry->block_state),
+ (unsigned long long)__entry->rd_addr,
+ __entry->rd_free_clone)
);
#endif /* _TRACE_GFS2_H */
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index 86ac75d99d31..ad3e2fb763d7 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -50,8 +50,6 @@ int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
if (revokes)
tr->tr_reserved += gfs2_struct2blk(sdp, revokes,
sizeof(u64));
- INIT_LIST_HEAD(&tr->tr_list_buf);
-
gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh);
error = gfs2_glock_nq(&tr->tr_t_gh);
@@ -93,10 +91,21 @@ static void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks)
up_read(&sdp->sd_log_flush_lock);
}
+static void gfs2_print_trans(const struct gfs2_trans *tr)
+{
+ print_symbol(KERN_WARNING "GFS2: Transaction created at: %s\n", tr->tr_ip);
+ printk(KERN_WARNING "GFS2: blocks=%u revokes=%u reserved=%u touched=%d\n",
+ tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, tr->tr_touched);
+ printk(KERN_WARNING "GFS2: Buf %u/%u Databuf %u/%u Revoke %u/%u\n",
+ tr->tr_num_buf_new, tr->tr_num_buf_rm,
+ tr->tr_num_databuf_new, tr->tr_num_databuf_rm,
+ tr->tr_num_revoke, tr->tr_num_revoke_rm);
+}
+
void gfs2_trans_end(struct gfs2_sbd *sdp)
{
struct gfs2_trans *tr = current->journal_info;
-
+ s64 nbuf;
BUG_ON(!tr);
current->journal_info = NULL;
@@ -110,16 +119,13 @@ void gfs2_trans_end(struct gfs2_sbd *sdp)
return;
}
- if (gfs2_assert_withdraw(sdp, tr->tr_num_buf <= tr->tr_blocks)) {
- fs_err(sdp, "tr_num_buf = %u, tr_blocks = %u ",
- tr->tr_num_buf, tr->tr_blocks);
- print_symbol(KERN_WARNING "GFS2: Transaction created at: %s\n", tr->tr_ip);
- }
- if (gfs2_assert_withdraw(sdp, tr->tr_num_revoke <= tr->tr_revokes)) {
- fs_err(sdp, "tr_num_revoke = %u, tr_revokes = %u ",
- tr->tr_num_revoke, tr->tr_revokes);
- print_symbol(KERN_WARNING "GFS2: Transaction created at: %s\n", tr->tr_ip);
- }
+ nbuf = tr->tr_num_buf_new + tr->tr_num_databuf_new;
+ nbuf -= tr->tr_num_buf_rm;
+ nbuf -= tr->tr_num_databuf_rm;
+
+ if (gfs2_assert_withdraw(sdp, (nbuf <= tr->tr_blocks) &&
+ (tr->tr_num_revoke <= tr->tr_revokes)))
+ gfs2_print_trans(tr);
gfs2_log_commit(sdp, tr);
if (tr->tr_t_gh.gh_gl) {
@@ -152,16 +158,16 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta)
gfs2_attach_bufdata(gl, bh, meta);
bd = bh->b_private;
}
- lops_add(sdp, &bd->bd_le);
+ lops_add(sdp, bd);
}
void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
{
- BUG_ON(!list_empty(&bd->bd_le.le_list));
+ BUG_ON(!list_empty(&bd->bd_list));
BUG_ON(!list_empty(&bd->bd_ail_st_list));
BUG_ON(!list_empty(&bd->bd_ail_gl_list));
- lops_init_le(&bd->bd_le, &gfs2_revoke_lops);
- lops_add(sdp, &bd->bd_le);
+ lops_init_le(bd, &gfs2_revoke_lops);
+ lops_add(sdp, bd);
}
void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len)
@@ -171,9 +177,9 @@ void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len)
unsigned int n = len;
gfs2_log_lock(sdp);
- list_for_each_entry_safe(bd, tmp, &sdp->sd_log_le_revoke, bd_le.le_list) {
+ list_for_each_entry_safe(bd, tmp, &sdp->sd_log_le_revoke, bd_list) {
if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) {
- list_del_init(&bd->bd_le.le_list);
+ list_del_init(&bd->bd_list);
gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke);
sdp->sd_log_num_revoke--;
kmem_cache_free(gfs2_bufdata_cachep, bd);
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index 9e7765e8e7b0..f00d7c5744f6 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -25,7 +25,8 @@ struct kmem_cache *gfs2_inode_cachep __read_mostly;
struct kmem_cache *gfs2_bufdata_cachep __read_mostly;
struct kmem_cache *gfs2_rgrpd_cachep __read_mostly;
struct kmem_cache *gfs2_quotad_cachep __read_mostly;
-mempool_t *gfs2_bh_pool __read_mostly;
+struct kmem_cache *gfs2_rsrv_cachep __read_mostly;
+mempool_t *gfs2_page_pool __read_mostly;
void gfs2_assert_i(struct gfs2_sbd *sdp)
{
diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h
index a4ce76c67dbb..3586b0dd6aa7 100644
--- a/fs/gfs2/util.h
+++ b/fs/gfs2/util.h
@@ -152,7 +152,8 @@ extern struct kmem_cache *gfs2_inode_cachep;
extern struct kmem_cache *gfs2_bufdata_cachep;
extern struct kmem_cache *gfs2_rgrpd_cachep;
extern struct kmem_cache *gfs2_quotad_cachep;
-extern mempool_t *gfs2_bh_pool;
+extern struct kmem_cache *gfs2_rsrv_cachep;
+extern mempool_t *gfs2_page_pool;
static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt,
unsigned int *p)
diff --git a/fs/libfs.c b/fs/libfs.c
index 18d08f5db53a..f86ec27a4230 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -68,7 +68,7 @@ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct na
int dcache_dir_open(struct inode *inode, struct file *file)
{
- static struct qstr cursor_name = {.len = 1, .name = "."};
+ static struct qstr cursor_name = QSTR_INIT(".", 1);
file->private_data = d_alloc(file->f_path.dentry, &cursor_name);
@@ -225,7 +225,7 @@ struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
struct dentry *dentry;
struct inode *root;
- struct qstr d_name = {.name = name, .len = strlen(name)};
+ struct qstr d_name = QSTR_INIT(name, strlen(name));
if (IS_ERR(s))
return ERR_CAST(s);
diff --git a/fs/namei.c b/fs/namei.c
index c42791914f82..f9e883c1b856 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -116,47 +116,37 @@
* POSIX.1 2.4: an empty pathname is invalid (ENOENT).
* PATH_MAX includes the nul terminator --RR.
*/
-static int do_getname(const char __user *filename, char *page)
-{
- int retval;
- unsigned long len = PATH_MAX;
-
- if (!segment_eq(get_fs(), KERNEL_DS)) {
- if ((unsigned long) filename >= TASK_SIZE)
- return -EFAULT;
- if (TASK_SIZE - (unsigned long) filename < PATH_MAX)
- len = TASK_SIZE - (unsigned long) filename;
- }
-
- retval = strncpy_from_user(page, filename, len);
- if (retval > 0) {
- if (retval < len)
- return 0;
- return -ENAMETOOLONG;
- } else if (!retval)
- retval = -ENOENT;
- return retval;
-}
-
static char *getname_flags(const char __user *filename, int flags, int *empty)
{
- char *result = __getname();
- int retval;
+ char *result = __getname(), *err;
+ int len;
- if (!result)
+ if (unlikely(!result))
return ERR_PTR(-ENOMEM);
- retval = do_getname(filename, result);
- if (retval < 0) {
- if (retval == -ENOENT && empty)
+ len = strncpy_from_user(result, filename, PATH_MAX);
+ err = ERR_PTR(len);
+ if (unlikely(len < 0))
+ goto error;
+
+ /* The empty path is special. */
+ if (unlikely(!len)) {
+ if (empty)
*empty = 1;
- if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) {
- __putname(result);
- return ERR_PTR(retval);
- }
+ err = ERR_PTR(-ENOENT);
+ if (!(flags & LOOKUP_EMPTY))
+ goto error;
+ }
+
+ err = ERR_PTR(-ENAMETOOLONG);
+ if (likely(len < PATH_MAX)) {
+ audit_getname(result);
+ return result;
}
- audit_getname(result);
- return result;
+
+error:
+ __putname(result);
+ return err;
}
char *getname(const char __user * filename)
@@ -1154,12 +1144,25 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
*/
if (nd->flags & LOOKUP_RCU) {
unsigned seq;
- *inode = nd->inode;
- dentry = __d_lookup_rcu(parent, name, &seq, inode);
+ dentry = __d_lookup_rcu(parent, name, &seq, nd->inode);
if (!dentry)
goto unlazy;
- /* Memory barrier in read_seqcount_begin of child is enough */
+ /*
+ * This sequence count validates that the inode matches
+ * the dentry name information from lookup.
+ */
+ *inode = dentry->d_inode;
+ if (read_seqcount_retry(&dentry->d_seq, seq))
+ return -ECHILD;
+
+ /*
+ * This sequence count validates that the parent had no
+ * changes while we did the lookup of the dentry above.
+ *
+ * The memory barrier in read_seqcount_begin of child is
+ * enough, we can use __read_seqcount_retry here.
+ */
if (__read_seqcount_retry(&parent->d_seq, nd->seq))
return -ECHILD;
nd->seq = seq;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 8789210c6905..eedd24d0ad2e 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -477,10 +477,7 @@ different:
static
void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
{
- struct qstr filename = {
- .len = entry->len,
- .name = entry->name,
- };
+ struct qstr filename = QSTR_INIT(entry->name, entry->len);
struct dentry *dentry;
struct dentry *alias;
struct inode *dir = parent->d_inode;
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 5242eae6711a..75c68299358e 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -398,8 +398,7 @@ nfs3_proc_remove(struct inode *dir, struct qstr *name)
{
struct nfs_removeargs arg = {
.fh = NFS_FH(dir),
- .name.len = name->len,
- .name.name = name->name,
+ .name = *name,
};
struct nfs_removeres res;
struct rpc_message msg = {
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 99650aaf8937..ab985f6f0da8 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2782,8 +2782,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
struct nfs_server *server = NFS_SERVER(dir);
struct nfs_removeargs args = {
.fh = NFS_FH(dir),
- .name.len = name->len,
- .name.name = name->name,
+ .name = *name,
.bitmask = server->attr_bitmask,
};
struct nfs_removeres res = {
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index b63b6f4d14fb..d6408b6437de 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -335,8 +335,7 @@ nfs_proc_remove(struct inode *dir, struct qstr *name)
{
struct nfs_removeargs arg = {
.fh = NFS_FH(dir),
- .name.len = name->len,
- .name.name = name->name,
+ .name = *name,
};
struct rpc_message msg = {
.rpc_proc = &nfs_procedures[NFSPROC_REMOVE],
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index fce2bbee66d4..0bb2c2010b95 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -441,7 +441,7 @@ static struct dentry *nilfs_get_parent(struct dentry *child)
{
unsigned long ino;
struct inode *inode;
- struct qstr dotdot = {.name = "..", .len = 2};
+ struct qstr dotdot = QSTR_INIT("..", 2);
struct nilfs_root *root;
ino = nilfs_inode_by_name(child->d_inode, &dotdot);
diff --git a/fs/open.c b/fs/open.c
index 5720854156db..5eccdcea2d1b 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -681,7 +681,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
f->f_op = fops_get(inode->i_fop);
- error = security_dentry_open(f, cred);
+ error = security_file_open(f, cred);
if (error)
goto cleanup_all;
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 1c8b280146d7..57b8159f26f3 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1799,10 +1799,15 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
if (task) {
files = get_files_struct(task);
if (files) {
+ struct file *file;
rcu_read_lock();
- if (fcheck_files(files, fd)) {
+ file = fcheck_files(files, fd);
+ if (file) {
+ unsigned i_mode, f_mode = file->f_mode;
+
rcu_read_unlock();
put_files_struct(files);
+
if (task_dumpable(task)) {
rcu_read_lock();
cred = __task_cred(task);
@@ -1813,7 +1818,14 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
inode->i_uid = 0;
inode->i_gid = 0;
}
- inode->i_mode &= ~(S_ISUID | S_ISGID);
+
+ i_mode = S_IFLNK;
+ if (f_mode & FMODE_READ)
+ i_mode |= S_IRUSR | S_IXUSR;
+ if (f_mode & FMODE_WRITE)
+ i_mode |= S_IWUSR | S_IXUSR;
+ inode->i_mode = i_mode;
+
security_task_to_inode(task, inode);
put_task_struct(task);
return 1;
@@ -1837,8 +1849,6 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
struct dentry *dentry, struct task_struct *task, const void *ptr)
{
unsigned fd = *(const unsigned *)ptr;
- struct file *file;
- struct files_struct *files;
struct inode *inode;
struct proc_inode *ei;
struct dentry *error = ERR_PTR(-ENOENT);
@@ -1848,25 +1858,6 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
goto out;
ei = PROC_I(inode);
ei->fd = fd;
- files = get_files_struct(task);
- if (!files)
- goto out_iput;
- inode->i_mode = S_IFLNK;
-
- /*
- * We are not taking a ref to the file structure, so we must
- * hold ->file_lock.
- */
- spin_lock(&files->file_lock);
- file = fcheck_files(files, fd);
- if (!file)
- goto out_unlock;
- if (file->f_mode & FMODE_READ)
- inode->i_mode |= S_IRUSR | S_IXUSR;
- if (file->f_mode & FMODE_WRITE)
- inode->i_mode |= S_IWUSR | S_IXUSR;
- spin_unlock(&files->file_lock);
- put_files_struct(files);
inode->i_op = &proc_pid_link_inode_operations;
inode->i_size = 64;
@@ -1879,12 +1870,6 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
out:
return error;
-out_unlock:
- spin_unlock(&files->file_lock);
- put_files_struct(files);
-out_iput:
- iput(inode);
- goto out;
}
static struct dentry *proc_lookupfd_common(struct inode *dir,
@@ -2177,16 +2162,16 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
goto out;
result = ERR_PTR(-EACCES);
- if (lock_trace(task))
+ if (!ptrace_may_access(task, PTRACE_MODE_READ))
goto out_put_task;
result = ERR_PTR(-ENOENT);
if (dname_to_vma_addr(dentry, &vm_start, &vm_end))
- goto out_unlock;
+ goto out_put_task;
mm = get_task_mm(task);
if (!mm)
- goto out_unlock;
+ goto out_put_task;
down_read(&mm->mmap_sem);
vma = find_exact_vma(mm, vm_start, vm_end);
@@ -2198,8 +2183,6 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
out_no_vma:
up_read(&mm->mmap_sem);
mmput(mm);
-out_unlock:
- unlock_trace(task);
out_put_task:
put_task_struct(task);
out:
@@ -2233,7 +2216,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto out;
ret = -EACCES;
- if (lock_trace(task))
+ if (!ptrace_may_access(task, PTRACE_MODE_READ))
goto out_put_task;
ret = 0;
@@ -2241,12 +2224,12 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir)
case 0:
ino = inode->i_ino;
if (filldir(dirent, ".", 1, 0, ino, DT_DIR) < 0)
- goto out_unlock;
+ goto out_put_task;
filp->f_pos++;
case 1:
ino = parent_ino(dentry);
if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
- goto out_unlock;
+ goto out_put_task;
filp->f_pos++;
default:
{
@@ -2257,7 +2240,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir)
mm = get_task_mm(task);
if (!mm)
- goto out_unlock;
+ goto out_put_task;
down_read(&mm->mmap_sem);
nr_files = 0;
@@ -2287,7 +2270,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir)
flex_array_free(fa);
up_read(&mm->mmap_sem);
mmput(mm);
- goto out_unlock;
+ goto out_put_task;
}
for (i = 0, vma = mm->mmap, pos = 2; vma;
vma = vma->vm_next) {
@@ -2332,8 +2315,6 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
}
-out_unlock:
- unlock_trace(task);
out_put_task:
put_task_struct(task);
out:
diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig
index 8007ae7c0d8c..23ade2680a4a 100644
--- a/fs/pstore/Kconfig
+++ b/fs/pstore/Kconfig
@@ -11,3 +11,20 @@ config PSTORE
(e.g. ACPI_APEI on X86) which will select this for you.
If you don't have a platform persistent store driver,
say N.
+
+config PSTORE_RAM
+ tristate "Log panic/oops to a RAM buffer"
+ depends on PSTORE
+ depends on HAS_IOMEM
+ depends on HAVE_MEMBLOCK
+ select REED_SOLOMON
+ select REED_SOLOMON_ENC8
+ select REED_SOLOMON_DEC8
+ help
+ This enables panic and oops messages to be logged to a circular
+ buffer in RAM where it can be read back at some later point.
+
+ Note that for historical reasons, the module will be named
+ "ramoops.ko".
+
+ For more information, see Documentation/ramoops.txt.
diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile
index 760f4bce7d1d..278a44e0d4e1 100644
--- a/fs/pstore/Makefile
+++ b/fs/pstore/Makefile
@@ -5,3 +5,6 @@
obj-y += pstore.o
pstore-objs += inode.o platform.o
+
+ramoops-objs += ram.o ram_core.o
+obj-$(CONFIG_PSTORE_RAM) += ramoops.o
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
new file mode 100644
index 000000000000..9123cce28c1e
--- /dev/null
+++ b/fs/pstore/ram.c
@@ -0,0 +1,383 @@
+/*
+ * RAM Oops/Panic logger
+ *
+ * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
+ * Copyright (C) 2011 Kees Cook <keescook@chromium.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/pstore.h>
+#include <linux/time.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/pstore_ram.h>
+
+#define RAMOOPS_KERNMSG_HDR "===="
+#define MIN_MEM_SIZE 4096UL
+
+static ulong record_size = MIN_MEM_SIZE;
+module_param(record_size, ulong, 0400);
+MODULE_PARM_DESC(record_size,
+ "size of each dump done on oops/panic");
+
+static ulong mem_address;
+module_param(mem_address, ulong, 0400);
+MODULE_PARM_DESC(mem_address,
+ "start of reserved RAM used to store oops/panic logs");
+
+static ulong mem_size;
+module_param(mem_size, ulong, 0400);
+MODULE_PARM_DESC(mem_size,
+ "size of reserved RAM used to store oops/panic logs");
+
+static int dump_oops = 1;
+module_param(dump_oops, int, 0600);
+MODULE_PARM_DESC(dump_oops,
+ "set to 1 to dump oopses, 0 to only dump panics (default 1)");
+
+static int ramoops_ecc;
+module_param_named(ecc, ramoops_ecc, int, 0600);
+MODULE_PARM_DESC(ramoops_ecc,
+ "set to 1 to enable ECC support");
+
+struct ramoops_context {
+ struct persistent_ram_zone **przs;
+ phys_addr_t phys_addr;
+ unsigned long size;
+ size_t record_size;
+ int dump_oops;
+ bool ecc;
+ unsigned int count;
+ unsigned int max_count;
+ unsigned int read_count;
+ struct pstore_info pstore;
+};
+
+static struct platform_device *dummy;
+static struct ramoops_platform_data *dummy_data;
+
+static int ramoops_pstore_open(struct pstore_info *psi)
+{
+ struct ramoops_context *cxt = psi->data;
+
+ cxt->read_count = 0;
+ return 0;
+}
+
+static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
+ struct timespec *time,
+ char **buf,
+ struct pstore_info *psi)
+{
+ ssize_t size;
+ struct ramoops_context *cxt = psi->data;
+ struct persistent_ram_zone *prz;
+
+ if (cxt->read_count >= cxt->max_count)
+ return -EINVAL;
+
+ *id = cxt->read_count++;
+ prz = cxt->przs[*id];
+
+ /* Only supports dmesg output so far. */
+ *type = PSTORE_TYPE_DMESG;
+ /* TODO(kees): Bogus time for the moment. */
+ time->tv_sec = 0;
+ time->tv_nsec = 0;
+
+ size = persistent_ram_old_size(prz);
+ *buf = kmalloc(size, GFP_KERNEL);
+ if (*buf == NULL)
+ return -ENOMEM;
+ memcpy(*buf, persistent_ram_old(prz), size);
+
+ return size;
+}
+
+static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz)
+{
+ char *hdr;
+ struct timeval timestamp;
+ size_t len;
+
+ do_gettimeofday(&timestamp);
+ hdr = kasprintf(GFP_ATOMIC, RAMOOPS_KERNMSG_HDR "%lu.%lu\n",
+ (long)timestamp.tv_sec, (long)timestamp.tv_usec);
+ WARN_ON_ONCE(!hdr);
+ len = hdr ? strlen(hdr) : 0;
+ persistent_ram_write(prz, hdr, len);
+ kfree(hdr);
+
+ return len;
+}
+
+static int ramoops_pstore_write(enum pstore_type_id type,
+ enum kmsg_dump_reason reason,
+ u64 *id,
+ unsigned int part,
+ size_t size, struct pstore_info *psi)
+{
+ struct ramoops_context *cxt = psi->data;
+ struct persistent_ram_zone *prz = cxt->przs[cxt->count];
+ size_t hlen;
+
+ /* Currently ramoops is designed to only store dmesg dumps. */
+ if (type != PSTORE_TYPE_DMESG)
+ return -EINVAL;
+
+ /* Out of the various dmesg dump types, ramoops is currently designed
+ * to only store crash logs, rather than storing general kernel logs.
+ */
+ if (reason != KMSG_DUMP_OOPS &&
+ reason != KMSG_DUMP_PANIC)
+ return -EINVAL;
+
+ /* Skip Oopes when configured to do so. */
+ if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops)
+ return -EINVAL;
+
+ /* Explicitly only take the first part of any new crash.
+ * If our buffer is larger than kmsg_bytes, this can never happen,
+ * and if our buffer is smaller than kmsg_bytes, we don't want the
+ * report split across multiple records.
+ */
+ if (part != 1)
+ return -ENOSPC;
+
+ hlen = ramoops_write_kmsg_hdr(prz);
+ if (size + hlen > prz->buffer_size)
+ size = prz->buffer_size - hlen;
+ persistent_ram_write(prz, cxt->pstore.buf, size);
+
+ cxt->count = (cxt->count + 1) % cxt->max_count;
+
+ return 0;
+}
+
+static int ramoops_pstore_erase(enum pstore_type_id type, u64 id,
+ struct pstore_info *psi)
+{
+ struct ramoops_context *cxt = psi->data;
+
+ if (id >= cxt->max_count)
+ return -EINVAL;
+
+ persistent_ram_free_old(cxt->przs[id]);
+
+ return 0;
+}
+
+static struct ramoops_context oops_cxt = {
+ .pstore = {
+ .owner = THIS_MODULE,
+ .name = "ramoops",
+ .open = ramoops_pstore_open,
+ .read = ramoops_pstore_read,
+ .write = ramoops_pstore_write,
+ .erase = ramoops_pstore_erase,
+ },
+};
+
+static int __init ramoops_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ramoops_platform_data *pdata = pdev->dev.platform_data;
+ struct ramoops_context *cxt = &oops_cxt;
+ int err = -EINVAL;
+ int i;
+
+ /* Only a single ramoops area allowed at a time, so fail extra
+ * probes.
+ */
+ if (cxt->max_count)
+ goto fail_out;
+
+ if (!pdata->mem_size || !pdata->record_size) {
+ pr_err("The memory size and the record size must be "
+ "non-zero\n");
+ goto fail_out;
+ }
+
+ pdata->mem_size = rounddown_pow_of_two(pdata->mem_size);
+ pdata->record_size = rounddown_pow_of_two(pdata->record_size);
+
+ /* Check for the minimum memory size */
+ if (pdata->mem_size < MIN_MEM_SIZE &&
+ pdata->record_size < MIN_MEM_SIZE) {
+ pr_err("memory size too small, minimum is %lu\n",
+ MIN_MEM_SIZE);
+ goto fail_out;
+ }
+
+ if (pdata->mem_size < pdata->record_size) {
+ pr_err("The memory size must be larger than the "
+ "records size\n");
+ goto fail_out;
+ }
+
+ cxt->max_count = pdata->mem_size / pdata->record_size;
+ cxt->count = 0;
+ cxt->size = pdata->mem_size;
+ cxt->phys_addr = pdata->mem_address;
+ cxt->record_size = pdata->record_size;
+ cxt->dump_oops = pdata->dump_oops;
+ cxt->ecc = pdata->ecc;
+
+ cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_count, GFP_KERNEL);
+ if (!cxt->przs) {
+ err = -ENOMEM;
+ dev_err(dev, "failed to initialize a prz array\n");
+ goto fail_out;
+ }
+
+ for (i = 0; i < cxt->max_count; i++) {
+ size_t sz = cxt->record_size;
+ phys_addr_t start = cxt->phys_addr + sz * i;
+
+ cxt->przs[i] = persistent_ram_new(start, sz, cxt->ecc);
+ if (IS_ERR(cxt->przs[i])) {
+ err = PTR_ERR(cxt->przs[i]);
+ dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
+ sz, (unsigned long long)start, err);
+ goto fail_przs;
+ }
+ }
+
+ cxt->pstore.data = cxt;
+ cxt->pstore.bufsize = cxt->przs[0]->buffer_size;
+ cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL);
+ spin_lock_init(&cxt->pstore.buf_lock);
+ if (!cxt->pstore.buf) {
+ pr_err("cannot allocate pstore buffer\n");
+ goto fail_clear;
+ }
+
+ err = pstore_register(&cxt->pstore);
+ if (err) {
+ pr_err("registering with pstore failed\n");
+ goto fail_buf;
+ }
+
+ /*
+ * Update the module parameter variables as well so they are visible
+ * through /sys/module/ramoops/parameters/
+ */
+ mem_size = pdata->mem_size;
+ mem_address = pdata->mem_address;
+ record_size = pdata->record_size;
+ dump_oops = pdata->dump_oops;
+
+ pr_info("attached 0x%lx@0x%llx (%ux0x%zx), ecc: %s\n",
+ cxt->size, (unsigned long long)cxt->phys_addr,
+ cxt->max_count, cxt->record_size,
+ ramoops_ecc ? "on" : "off");
+
+ return 0;
+
+fail_buf:
+ kfree(cxt->pstore.buf);
+fail_clear:
+ cxt->pstore.bufsize = 0;
+ cxt->max_count = 0;
+fail_przs:
+ for (i = 0; cxt->przs[i]; i++)
+ persistent_ram_free(cxt->przs[i]);
+ kfree(cxt->przs);
+fail_out:
+ return err;
+}
+
+static int __exit ramoops_remove(struct platform_device *pdev)
+{
+#if 0
+ /* TODO(kees): We cannot unload ramoops since pstore doesn't support
+ * unregistering yet.
+ */
+ struct ramoops_context *cxt = &oops_cxt;
+
+ iounmap(cxt->virt_addr);
+ release_mem_region(cxt->phys_addr, cxt->size);
+ cxt->max_count = 0;
+
+ /* TODO(kees): When pstore supports unregistering, call it here. */
+ kfree(cxt->pstore.buf);
+ cxt->pstore.bufsize = 0;
+
+ return 0;
+#endif
+ return -EBUSY;
+}
+
+static struct platform_driver ramoops_driver = {
+ .remove = __exit_p(ramoops_remove),
+ .driver = {
+ .name = "ramoops",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ramoops_init(void)
+{
+ int ret;
+ ret = platform_driver_probe(&ramoops_driver, ramoops_probe);
+ if (ret == -ENODEV) {
+ /*
+ * If we didn't find a platform device, we use module parameters
+ * building platform data on the fly.
+ */
+ pr_info("platform device not found, using module parameters\n");
+ dummy_data = kzalloc(sizeof(struct ramoops_platform_data),
+ GFP_KERNEL);
+ if (!dummy_data)
+ return -ENOMEM;
+ dummy_data->mem_size = mem_size;
+ dummy_data->mem_address = mem_address;
+ dummy_data->record_size = record_size;
+ dummy_data->dump_oops = dump_oops;
+ dummy_data->ecc = ramoops_ecc;
+ dummy = platform_create_bundle(&ramoops_driver, ramoops_probe,
+ NULL, 0, dummy_data,
+ sizeof(struct ramoops_platform_data));
+
+ if (IS_ERR(dummy))
+ ret = PTR_ERR(dummy);
+ else
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static void __exit ramoops_exit(void)
+{
+ platform_driver_unregister(&ramoops_driver);
+ kfree(dummy_data);
+}
+
+module_init(ramoops_init);
+module_exit(ramoops_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marco Stornelli <marco.stornelli@gmail.com>");
+MODULE_DESCRIPTION("RAM Oops/Panic logger/driver");
diff --git a/drivers/staging/android/persistent_ram.c b/fs/pstore/ram_core.c
index 8d8c1e33e0ff..31f8d184f3a0 100644
--- a/drivers/staging/android/persistent_ram.c
+++ b/fs/pstore/ram_core.c
@@ -23,7 +23,8 @@
#include <linux/rslib.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#include "persistent_ram.h"
+#include <linux/pstore_ram.h>
+#include <asm/page.h>
struct persistent_ram_buffer {
uint32_t sig;
@@ -79,23 +80,6 @@ static inline void buffer_size_add(struct persistent_ram_zone *prz, size_t a)
} while (atomic_cmpxchg(&prz->buffer->size, old, new) != old);
}
-/* increase the size counter, retuning an error if it hits the max size */
-static inline ssize_t buffer_size_add_clamp(struct persistent_ram_zone *prz,
- size_t a)
-{
- size_t old;
- size_t new;
-
- do {
- old = atomic_read(&prz->buffer->size);
- new = old + a;
- if (new > prz->buffer_size)
- return -ENOMEM;
- } while (atomic_cmpxchg(&prz->buffer->size, old, new) != old);
-
- return 0;
-}
-
static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz,
uint8_t *data, size_t len, uint8_t *ecc)
{
@@ -300,7 +284,7 @@ int notrace persistent_ram_write(struct persistent_ram_zone *prz,
c = prz->buffer_size;
}
- buffer_size_add_clamp(prz, c);
+ buffer_size_add(prz, c);
start = buffer_start_add(prz, c);
@@ -335,14 +319,14 @@ void persistent_ram_free_old(struct persistent_ram_zone *prz)
prz->old_log_size = 0;
}
-static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
- struct persistent_ram_zone *prz)
+static void *persistent_ram_vmap(phys_addr_t start, size_t size)
{
struct page **pages;
phys_addr_t page_start;
unsigned int page_count;
pgprot_t prot;
unsigned int i;
+ void *vaddr;
page_start = start - offset_in_page(start);
page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE);
@@ -353,17 +337,44 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
if (!pages) {
pr_err("%s: Failed to allocate array for %u pages\n", __func__,
page_count);
- return -ENOMEM;
+ return NULL;
}
for (i = 0; i < page_count; i++) {
phys_addr_t addr = page_start + i * PAGE_SIZE;
pages[i] = pfn_to_page(addr >> PAGE_SHIFT);
}
- prz->vaddr = vmap(pages, page_count, VM_MAP, prot);
+ vaddr = vmap(pages, page_count, VM_MAP, prot);
kfree(pages);
+
+ return vaddr;
+}
+
+static void *persistent_ram_iomap(phys_addr_t start, size_t size)
+{
+ if (!request_mem_region(start, size, "persistent_ram")) {
+ pr_err("request mem region (0x%llx@0x%llx) failed\n",
+ (unsigned long long)size, (unsigned long long)start);
+ return NULL;
+ }
+
+ return ioremap(start, size);
+}
+
+static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
+ struct persistent_ram_zone *prz)
+{
+ prz->paddr = start;
+ prz->size = size;
+
+ if (pfn_valid(start >> PAGE_SHIFT))
+ prz->vaddr = persistent_ram_vmap(start, size);
+ else
+ prz->vaddr = persistent_ram_iomap(start, size);
+
if (!prz->vaddr) {
- pr_err("%s: Failed to map %u pages\n", __func__, page_count);
+ pr_err("%s: Failed to map 0x%llx pages at 0x%llx\n", __func__,
+ (unsigned long long)size, (unsigned long long)start);
return -ENOMEM;
}
@@ -373,6 +384,79 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
return 0;
}
+static int __init persistent_ram_post_init(struct persistent_ram_zone *prz, bool ecc)
+{
+ int ret;
+
+ prz->ecc = ecc;
+
+ ret = persistent_ram_init_ecc(prz, prz->buffer_size);
+ if (ret)
+ return ret;
+
+ if (prz->buffer->sig == PERSISTENT_RAM_SIG) {
+ if (buffer_size(prz) > prz->buffer_size ||
+ buffer_start(prz) > buffer_size(prz))
+ pr_info("persistent_ram: found existing invalid buffer,"
+ " size %zu, start %zu\n",
+ buffer_size(prz), buffer_start(prz));
+ else {
+ pr_info("persistent_ram: found existing buffer,"
+ " size %zu, start %zu\n",
+ buffer_size(prz), buffer_start(prz));
+ persistent_ram_save_old(prz);
+ }
+ } else {
+ pr_info("persistent_ram: no valid data in buffer"
+ " (sig = 0x%08x)\n", prz->buffer->sig);
+ }
+
+ prz->buffer->sig = PERSISTENT_RAM_SIG;
+ atomic_set(&prz->buffer->start, 0);
+ atomic_set(&prz->buffer->size, 0);
+
+ return 0;
+}
+
+void persistent_ram_free(struct persistent_ram_zone *prz)
+{
+ if (pfn_valid(prz->paddr >> PAGE_SHIFT)) {
+ vunmap(prz->vaddr);
+ } else {
+ iounmap(prz->vaddr);
+ release_mem_region(prz->paddr, prz->size);
+ }
+ persistent_ram_free_old(prz);
+ kfree(prz);
+}
+
+struct persistent_ram_zone * __init persistent_ram_new(phys_addr_t start,
+ size_t size,
+ bool ecc)
+{
+ struct persistent_ram_zone *prz;
+ int ret = -ENOMEM;
+
+ prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL);
+ if (!prz) {
+ pr_err("persistent_ram: failed to allocate persistent ram zone\n");
+ goto err;
+ }
+
+ ret = persistent_ram_buffer_map(start, size, prz);
+ if (ret)
+ goto err;
+
+ persistent_ram_post_init(prz, ecc);
+ persistent_ram_update_header_ecc(prz);
+
+ return prz;
+err:
+ kfree(prz);
+ return ERR_PTR(ret);
+}
+
+#ifndef MODULE
static int __init persistent_ram_buffer_init(const char *name,
struct persistent_ram_zone *prz)
{
@@ -407,39 +491,13 @@ struct persistent_ram_zone *__persistent_ram_init(struct device *dev, bool ecc)
goto err;
}
- INIT_LIST_HEAD(&prz->node);
-
ret = persistent_ram_buffer_init(dev_name(dev), prz);
if (ret) {
pr_err("persistent_ram: failed to initialize buffer\n");
goto err;
}
- prz->ecc = ecc;
- ret = persistent_ram_init_ecc(prz, prz->buffer_size);
- if (ret)
- goto err;
-
- if (prz->buffer->sig == PERSISTENT_RAM_SIG) {
- if (buffer_size(prz) > prz->buffer_size ||
- buffer_start(prz) > buffer_size(prz))
- pr_info("persistent_ram: found existing invalid buffer,"
- " size %ld, start %ld\n",
- buffer_size(prz), buffer_start(prz));
- else {
- pr_info("persistent_ram: found existing buffer,"
- " size %ld, start %ld\n",
- buffer_size(prz), buffer_start(prz));
- persistent_ram_save_old(prz);
- }
- } else {
- pr_info("persistent_ram: no valid data in buffer"
- " (sig = 0x%08x)\n", prz->buffer->sig);
- }
-
- prz->buffer->sig = PERSISTENT_RAM_SIG;
- atomic_set(&prz->buffer->start, 0);
- atomic_set(&prz->buffer->size, 0);
+ persistent_ram_post_init(prz, ecc);
return prz;
err:
@@ -471,3 +529,4 @@ int __init persistent_ram_early_init(struct persistent_ram *ram)
return 0;
}
+#endif
diff --git a/fs/stat.c b/fs/stat.c
index c733dc5753ae..0cef3366a919 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -57,12 +57,13 @@ EXPORT_SYMBOL(vfs_getattr);
int vfs_fstat(unsigned int fd, struct kstat *stat)
{
- struct file *f = fget(fd);
+ int fput_needed;
+ struct file *f = fget_light(fd, &fput_needed);
int error = -EBADF;
if (f) {
error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
- fput(f);
+ fput_light(f, fput_needed);
}
return error;
}
@@ -190,24 +191,32 @@ SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, stat
#endif /* __ARCH_WANT_OLD_STAT */
+#if BITS_PER_LONG == 32
+# define choose_32_64(a,b) a
+#else
+# define choose_32_64(a,b) b
+#endif
+
+#define valid_dev(x) choose_32_64(old_valid_dev,new_valid_dev)(x)
+#define encode_dev(x) choose_32_64(old_encode_dev,new_encode_dev)(x)
+
+#ifndef INIT_STRUCT_STAT_PADDING
+# define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st))
+#endif
+
static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
{
struct stat tmp;
-#if BITS_PER_LONG == 32
- if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
+ if (!valid_dev(stat->dev) || !valid_dev(stat->rdev))
return -EOVERFLOW;
-#else
- if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
+#if BITS_PER_LONG == 32
+ if (stat->size > MAX_NON_LFS)
return -EOVERFLOW;
#endif
- memset(&tmp, 0, sizeof(tmp));
-#if BITS_PER_LONG == 32
- tmp.st_dev = old_encode_dev(stat->dev);
-#else
- tmp.st_dev = new_encode_dev(stat->dev);
-#endif
+ INIT_STRUCT_STAT_PADDING(tmp);
+ tmp.st_dev = encode_dev(stat->dev);
tmp.st_ino = stat->ino;
if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
return -EOVERFLOW;
@@ -217,15 +226,7 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
return -EOVERFLOW;
SET_UID(tmp.st_uid, stat->uid);
SET_GID(tmp.st_gid, stat->gid);
-#if BITS_PER_LONG == 32
- tmp.st_rdev = old_encode_dev(stat->rdev);
-#else
- tmp.st_rdev = new_encode_dev(stat->rdev);
-#endif
-#if BITS_PER_LONG == 32
- if (stat->size > MAX_NON_LFS)
- return -EOVERFLOW;
-#endif
+ tmp.st_rdev = encode_dev(stat->rdev);
tmp.st_size = stat->size;
tmp.st_atime = stat->atime.tv_sec;
tmp.st_mtime = stat->mtime.tv_sec;
@@ -327,11 +328,15 @@ SYSCALL_DEFINE3(readlink, const char __user *, path, char __user *, buf,
/* ---------- LFS-64 ----------- */
#ifdef __ARCH_WANT_STAT64
+#ifndef INIT_STRUCT_STAT64_PADDING
+# define INIT_STRUCT_STAT64_PADDING(st) memset(&st, 0, sizeof(st))
+#endif
+
static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
{
struct stat64 tmp;
- memset(&tmp, 0, sizeof(struct stat64));
+ INIT_STRUCT_STAT64_PADDING(tmp);
#ifdef CONFIG_MIPS
/* mips has weird padding, so we don't get 64 bits there */
if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 35a36d39fa2c..e6bb9b2a4cbe 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -132,6 +132,24 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children);
}
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+
+/* Test for attributes that want to ignore lockdep for read-locking */
+static bool ignore_lockdep(struct sysfs_dirent *sd)
+{
+ return sysfs_type(sd) == SYSFS_KOBJ_ATTR &&
+ sd->s_attr.attr->ignore_lockdep;
+}
+
+#else
+
+static inline bool ignore_lockdep(struct sysfs_dirent *sd)
+{
+ return true;
+}
+
+#endif
+
/**
* sysfs_get_active - get an active reference to sysfs_dirent
* @sd: sysfs_dirent to get an active reference to
@@ -155,15 +173,17 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
return NULL;
t = atomic_cmpxchg(&sd->s_active, v, v + 1);
- if (likely(t == v)) {
- rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
- return sd;
- }
+ if (likely(t == v))
+ break;
if (t < 0)
return NULL;
cpu_relax();
}
+
+ if (likely(!ignore_lockdep(sd)))
+ rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
+ return sd;
}
/**
@@ -180,7 +200,8 @@ void sysfs_put_active(struct sysfs_dirent *sd)
if (unlikely(!sd))
return;
- rwsem_release(&sd->dep_map, 1, _RET_IP_);
+ if (likely(!ignore_lockdep(sd)))
+ rwsem_release(&sd->dep_map, 1, _RET_IP_);
v = atomic_dec_return(&sd->s_active);
if (likely(v != SD_DEACTIVATED_BIAS))
return;
@@ -858,7 +879,6 @@ int sysfs_rename(struct sysfs_dirent *sd,
struct sysfs_dirent *new_parent_sd, const void *new_ns,
const char *new_name)
{
- const char *dup_name = NULL;
int error;
mutex_lock(&sysfs_mutex);
@@ -875,11 +895,11 @@ int sysfs_rename(struct sysfs_dirent *sd,
/* rename sysfs_dirent */
if (strcmp(sd->s_name, new_name) != 0) {
error = -ENOMEM;
- new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
+ new_name = kstrdup(new_name, GFP_KERNEL);
if (!new_name)
goto out;
- dup_name = sd->s_name;
+ kfree(sd->s_name);
sd->s_name = new_name;
}
@@ -895,7 +915,6 @@ int sysfs_rename(struct sysfs_dirent *sd,
error = 0;
out:
mutex_unlock(&sysfs_mutex);
- kfree(dup_name);
return error;
}
diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig
index f8b0160da2da..ba66d508006a 100644
--- a/fs/ubifs/Kconfig
+++ b/fs/ubifs/Kconfig
@@ -11,12 +11,6 @@ config UBIFS_FS
help
UBIFS is a file system for flash devices which works on top of UBI.
-config UBIFS_FS_XATTR
- bool "Extended attributes support"
- depends on UBIFS_FS
- help
- This option enables support of extended attributes.
-
config UBIFS_FS_ADVANCED_COMPR
bool "Advanced compression options"
depends on UBIFS_FS
@@ -41,20 +35,3 @@ config UBIFS_FS_ZLIB
default y
help
Zlib compresses better than LZO but it is slower. Say 'Y' if unsure.
-
-# Debugging-related stuff
-config UBIFS_FS_DEBUG
- bool "Enable debugging support"
- depends on UBIFS_FS
- select DEBUG_FS
- select KALLSYMS
- help
- This option enables UBIFS debugging support. It makes sure various
- assertions, self-checks, debugging messages and test modes are compiled
- in (this all is compiled out otherwise). Assertions are light-weight
- and this option also enables them. Self-checks, debugging messages and
- test modes are switched off by default. Thus, it is safe and actually
- recommended to have debugging support enabled, and it should not slow
- down UBIFS. You can then further enable / disable individual debugging
- features using UBIFS module parameters and the corresponding sysfs
- interfaces.
diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile
index 80e93c35e496..2c6f0cb816b4 100644
--- a/fs/ubifs/Makefile
+++ b/fs/ubifs/Makefile
@@ -3,7 +3,4 @@ obj-$(CONFIG_UBIFS_FS) += ubifs.o
ubifs-y += shrinker.o journal.o file.o dir.o super.o sb.o io.o
ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o
ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o
-ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o
-
-ubifs-$(CONFIG_UBIFS_FS_DEBUG) += debug.o
-ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o
+ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o xattr.o debug.o
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
index fb3b5c813a30..8eda717cb99b 100644
--- a/fs/ubifs/commit.c
+++ b/fs/ubifs/commit.c
@@ -496,7 +496,9 @@ int ubifs_gc_should_commit(struct ubifs_info *c)
return ret;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
+/*
+ * Everything below is related to debugging.
+ */
/**
* struct idx_node - hold index nodes during index tree traversal.
@@ -714,14 +716,14 @@ out:
return 0;
out_dump:
- dbg_err("dumping index node (iip=%d)", i->iip);
- dbg_dump_node(c, idx);
+ ubifs_err("dumping index node (iip=%d)", i->iip);
+ ubifs_dump_node(c, idx);
list_del(&i->list);
kfree(i);
if (!list_empty(&list)) {
i = list_entry(list.prev, struct idx_node, list);
- dbg_err("dumping parent index node");
- dbg_dump_node(c, &i->idx);
+ ubifs_err("dumping parent index node");
+ ubifs_dump_node(c, &i->idx);
}
out_free:
while (!list_empty(&list)) {
@@ -734,5 +736,3 @@ out_free:
err = -EINVAL;
return err;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 1934084e2088..685a83756b2b 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -34,8 +34,6 @@
#include <linux/random.h>
#include "ubifs.h"
-#ifdef CONFIG_UBIFS_FS_DEBUG
-
static DEFINE_SPINLOCK(dbg_lock);
static const char *get_key_fmt(int fmt)
@@ -232,7 +230,7 @@ static void dump_ch(const struct ubifs_ch *ch)
printk(KERN_ERR "\tlen %u\n", le32_to_cpu(ch->len));
}
-void dbg_dump_inode(struct ubifs_info *c, const struct inode *inode)
+void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode)
{
const struct ubifs_inode *ui = ubifs_inode(inode);
struct qstr nm = { .name = NULL };
@@ -300,7 +298,7 @@ void dbg_dump_inode(struct ubifs_info *c, const struct inode *inode)
kfree(pdent);
}
-void dbg_dump_node(const struct ubifs_info *c, const void *node)
+void ubifs_dump_node(const struct ubifs_info *c, const void *node)
{
int i, n;
union ubifs_key key;
@@ -603,7 +601,7 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node)
spin_unlock(&dbg_lock);
}
-void dbg_dump_budget_req(const struct ubifs_budget_req *req)
+void ubifs_dump_budget_req(const struct ubifs_budget_req *req)
{
spin_lock(&dbg_lock);
printk(KERN_ERR "Budgeting request: new_ino %d, dirtied_ino %d\n",
@@ -620,7 +618,7 @@ void dbg_dump_budget_req(const struct ubifs_budget_req *req)
spin_unlock(&dbg_lock);
}
-void dbg_dump_lstats(const struct ubifs_lp_stats *lst)
+void ubifs_dump_lstats(const struct ubifs_lp_stats *lst)
{
spin_lock(&dbg_lock);
printk(KERN_ERR "(pid %d) Lprops statistics: empty_lebs %d, "
@@ -634,7 +632,7 @@ void dbg_dump_lstats(const struct ubifs_lp_stats *lst)
spin_unlock(&dbg_lock);
}
-void dbg_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi)
+void ubifs_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi)
{
int i;
struct rb_node *rb;
@@ -707,7 +705,7 @@ out_unlock:
spin_unlock(&c->space_lock);
}
-void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp)
+void ubifs_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp)
{
int i, spc, dark = 0, dead = 0;
struct rb_node *rb;
@@ -801,7 +799,7 @@ void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp)
printk(KERN_CONT ")\n");
}
-void dbg_dump_lprops(struct ubifs_info *c)
+void ubifs_dump_lprops(struct ubifs_info *c)
{
int lnum, err;
struct ubifs_lprops lp;
@@ -810,20 +808,20 @@ void dbg_dump_lprops(struct ubifs_info *c)
printk(KERN_ERR "(pid %d) start dumping LEB properties\n",
current->pid);
ubifs_get_lp_stats(c, &lst);
- dbg_dump_lstats(&lst);
+ ubifs_dump_lstats(&lst);
for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) {
err = ubifs_read_one_lp(c, lnum, &lp);
if (err)
ubifs_err("cannot read lprops for LEB %d", lnum);
- dbg_dump_lprop(c, &lp);
+ ubifs_dump_lprop(c, &lp);
}
printk(KERN_ERR "(pid %d) finish dumping LEB properties\n",
current->pid);
}
-void dbg_dump_lpt_info(struct ubifs_info *c)
+void ubifs_dump_lpt_info(struct ubifs_info *c)
{
int i;
@@ -862,8 +860,8 @@ void dbg_dump_lpt_info(struct ubifs_info *c)
spin_unlock(&dbg_lock);
}
-void dbg_dump_sleb(const struct ubifs_info *c,
- const struct ubifs_scan_leb *sleb, int offs)
+void ubifs_dump_sleb(const struct ubifs_info *c,
+ const struct ubifs_scan_leb *sleb, int offs)
{
struct ubifs_scan_node *snod;
@@ -874,11 +872,11 @@ void dbg_dump_sleb(const struct ubifs_info *c,
cond_resched();
printk(KERN_ERR "Dumping node at LEB %d:%d len %d\n", sleb->lnum,
snod->offs, snod->len);
- dbg_dump_node(c, snod->node);
+ ubifs_dump_node(c, snod->node);
}
}
-void dbg_dump_leb(const struct ubifs_info *c, int lnum)
+void ubifs_dump_leb(const struct ubifs_info *c, int lnum)
{
struct ubifs_scan_leb *sleb;
struct ubifs_scan_node *snod;
@@ -909,7 +907,7 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum)
cond_resched();
printk(KERN_ERR "Dumping node at LEB %d:%d len %d\n", lnum,
snod->offs, snod->len);
- dbg_dump_node(c, snod->node);
+ ubifs_dump_node(c, snod->node);
}
printk(KERN_ERR "(pid %d) finish dumping LEB %d\n",
@@ -921,8 +919,8 @@ out:
return;
}
-void dbg_dump_znode(const struct ubifs_info *c,
- const struct ubifs_znode *znode)
+void ubifs_dump_znode(const struct ubifs_info *c,
+ const struct ubifs_znode *znode)
{
int n;
const struct ubifs_zbranch *zbr;
@@ -965,7 +963,7 @@ void dbg_dump_znode(const struct ubifs_info *c,
spin_unlock(&dbg_lock);
}
-void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat)
+void ubifs_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat)
{
int i;
@@ -981,8 +979,8 @@ void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat)
printk(KERN_ERR "(pid %d) finish dumping heap\n", current->pid);
}
-void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
- struct ubifs_nnode *parent, int iip)
+void ubifs_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
+ struct ubifs_nnode *parent, int iip)
{
int i;
@@ -999,7 +997,7 @@ void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
}
}
-void dbg_dump_tnc(struct ubifs_info *c)
+void ubifs_dump_tnc(struct ubifs_info *c)
{
struct ubifs_znode *znode;
int level;
@@ -1014,7 +1012,7 @@ void dbg_dump_tnc(struct ubifs_info *c)
level = znode->level;
printk(KERN_ERR "== Level %d ==\n", level);
}
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode);
}
printk(KERN_ERR "(pid %d) finish dumping TNC tree\n", current->pid);
@@ -1023,18 +1021,18 @@ void dbg_dump_tnc(struct ubifs_info *c)
static int dump_znode(struct ubifs_info *c, struct ubifs_znode *znode,
void *priv)
{
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
return 0;
}
/**
- * dbg_dump_index - dump the on-flash index.
+ * ubifs_dump_index - dump the on-flash index.
* @c: UBIFS file-system description object
*
- * This function dumps whole UBIFS indexing B-tree, unlike 'dbg_dump_tnc()'
+ * This function dumps whole UBIFS indexing B-tree, unlike 'ubifs_dump_tnc()'
* which dumps only in-memory znodes and does not read znodes which from flash.
*/
-void dbg_dump_index(struct ubifs_info *c)
+void ubifs_dump_index(struct ubifs_info *c)
{
dbg_walk_index(c, NULL, dump_znode, NULL);
}
@@ -1120,15 +1118,15 @@ int dbg_check_space_info(struct ubifs_info *c)
out:
ubifs_msg("saved lprops statistics dump");
- dbg_dump_lstats(&d->saved_lst);
+ ubifs_dump_lstats(&d->saved_lst);
ubifs_msg("saved budgeting info dump");
- dbg_dump_budg(c, &d->saved_bi);
+ ubifs_dump_budg(c, &d->saved_bi);
ubifs_msg("saved idx_gc_cnt %d", d->saved_idx_gc_cnt);
ubifs_msg("current lprops statistics dump");
ubifs_get_lp_stats(c, &lst);
- dbg_dump_lstats(&lst);
+ ubifs_dump_lstats(&lst);
ubifs_msg("current budgeting info dump");
- dbg_dump_budg(c, &c->bi);
+ ubifs_dump_budg(c, &c->bi);
dump_stack();
return -EINVAL;
}
@@ -1160,7 +1158,7 @@ int dbg_check_synced_i_size(const struct ubifs_info *c, struct inode *inode)
"is clean", ui->ui_size, ui->synced_i_size);
ubifs_err("i_ino %lu, i_mode %#x, i_size %lld", inode->i_ino,
inode->i_mode, i_size_read(inode));
- dbg_dump_stack();
+ dump_stack();
err = -EINVAL;
}
spin_unlock(&ui->ui_lock);
@@ -1223,14 +1221,14 @@ int dbg_check_dir(struct ubifs_info *c, const struct inode *dir)
"but calculated size is %llu", dir->i_ino,
(unsigned long long)i_size_read(dir),
(unsigned long long)size);
- dbg_dump_inode(c, dir);
+ ubifs_dump_inode(c, dir);
dump_stack();
return -EINVAL;
}
if (dir->i_nlink != nlink) {
ubifs_err("directory inode %lu has nlink %u, but calculated "
"nlink is %u", dir->i_ino, dir->i_nlink, nlink);
- dbg_dump_inode(c, dir);
+ ubifs_dump_inode(c, dir);
dump_stack();
return -EINVAL;
}
@@ -1287,25 +1285,25 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
err = 1;
key_read(c, &dent1->key, &key);
if (keys_cmp(c, &zbr1->key, &key)) {
- dbg_err("1st entry at %d:%d has key %s", zbr1->lnum,
- zbr1->offs, dbg_snprintf_key(c, &key, key_buf,
- DBG_KEY_BUF_LEN));
- dbg_err("but it should have key %s according to tnc",
- dbg_snprintf_key(c, &zbr1->key, key_buf,
- DBG_KEY_BUF_LEN));
- dbg_dump_node(c, dent1);
+ ubifs_err("1st entry at %d:%d has key %s", zbr1->lnum,
+ zbr1->offs, dbg_snprintf_key(c, &key, key_buf,
+ DBG_KEY_BUF_LEN));
+ ubifs_err("but it should have key %s according to tnc",
+ dbg_snprintf_key(c, &zbr1->key, key_buf,
+ DBG_KEY_BUF_LEN));
+ ubifs_dump_node(c, dent1);
goto out_free;
}
key_read(c, &dent2->key, &key);
if (keys_cmp(c, &zbr2->key, &key)) {
- dbg_err("2nd entry at %d:%d has key %s", zbr1->lnum,
- zbr1->offs, dbg_snprintf_key(c, &key, key_buf,
- DBG_KEY_BUF_LEN));
- dbg_err("but it should have key %s according to tnc",
- dbg_snprintf_key(c, &zbr2->key, key_buf,
- DBG_KEY_BUF_LEN));
- dbg_dump_node(c, dent2);
+ ubifs_err("2nd entry at %d:%d has key %s", zbr1->lnum,
+ zbr1->offs, dbg_snprintf_key(c, &key, key_buf,
+ DBG_KEY_BUF_LEN));
+ ubifs_err("but it should have key %s according to tnc",
+ dbg_snprintf_key(c, &zbr2->key, key_buf,
+ DBG_KEY_BUF_LEN));
+ ubifs_dump_node(c, dent2);
goto out_free;
}
@@ -1318,15 +1316,15 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
goto out_free;
}
if (cmp == 0 && nlen1 == nlen2)
- dbg_err("2 xent/dent nodes with the same name");
+ ubifs_err("2 xent/dent nodes with the same name");
else
- dbg_err("bad order of colliding key %s",
- dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
+ ubifs_err("bad order of colliding key %s",
+ dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
ubifs_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs);
- dbg_dump_node(c, dent1);
+ ubifs_dump_node(c, dent1);
ubifs_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs);
- dbg_dump_node(c, dent2);
+ ubifs_dump_node(c, dent2);
out_free:
kfree(dent2);
@@ -1529,10 +1527,10 @@ static int dbg_check_znode(struct ubifs_info *c, struct ubifs_zbranch *zbr)
out:
ubifs_err("failed, error %d", err);
ubifs_msg("dump of the znode");
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
if (zp) {
ubifs_msg("dump of the parent znode");
- dbg_dump_znode(c, zp);
+ ubifs_dump_znode(c, zp);
}
dump_stack();
return -EINVAL;
@@ -1599,9 +1597,9 @@ int dbg_check_tnc(struct ubifs_info *c, int extra)
return err;
if (err) {
ubifs_msg("first znode");
- dbg_dump_znode(c, prev);
+ ubifs_dump_znode(c, prev);
ubifs_msg("second znode");
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
return -EINVAL;
}
}
@@ -1690,7 +1688,7 @@ int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
if (err) {
ubifs_err("znode checking function returned "
"error %d", err);
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
goto out_dump;
}
}
@@ -1758,7 +1756,7 @@ out_dump:
else
zbr = &c->zroot;
ubifs_msg("dump of znode at LEB %d:%d", zbr->lnum, zbr->offs);
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
out_unlock:
mutex_unlock(&c->tnc_mutex);
return err;
@@ -2194,7 +2192,7 @@ out:
out_dump:
ubifs_msg("dump of node at LEB %d:%d", zbr->lnum, zbr->offs);
- dbg_dump_node(c, node);
+ ubifs_dump_node(c, node);
out_free:
kfree(node);
return err;
@@ -2352,7 +2350,7 @@ out_dump:
ubifs_msg("dump of the inode %lu sitting in LEB %d:%d",
(unsigned long)fscki->inum, zbr->lnum, zbr->offs);
- dbg_dump_node(c, ino);
+ ubifs_dump_node(c, ino);
kfree(ino);
return -EINVAL;
}
@@ -2423,12 +2421,12 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
if (sa->type != UBIFS_DATA_NODE) {
ubifs_err("bad node type %d", sa->type);
- dbg_dump_node(c, sa->node);
+ ubifs_dump_node(c, sa->node);
return -EINVAL;
}
if (sb->type != UBIFS_DATA_NODE) {
ubifs_err("bad node type %d", sb->type);
- dbg_dump_node(c, sb->node);
+ ubifs_dump_node(c, sb->node);
return -EINVAL;
}
@@ -2459,8 +2457,8 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
return 0;
error_dump:
- dbg_dump_node(c, sa->node);
- dbg_dump_node(c, sb->node);
+ ubifs_dump_node(c, sa->node);
+ ubifs_dump_node(c, sb->node);
return -EINVAL;
}
@@ -2491,13 +2489,13 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
sa->type != UBIFS_XENT_NODE) {
ubifs_err("bad node type %d", sa->type);
- dbg_dump_node(c, sa->node);
+ ubifs_dump_node(c, sa->node);
return -EINVAL;
}
if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
sa->type != UBIFS_XENT_NODE) {
ubifs_err("bad node type %d", sb->type);
- dbg_dump_node(c, sb->node);
+ ubifs_dump_node(c, sb->node);
return -EINVAL;
}
@@ -2547,9 +2545,9 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
error_dump:
ubifs_msg("dumping first node");
- dbg_dump_node(c, sa->node);
+ ubifs_dump_node(c, sa->node);
ubifs_msg("dumping second node");
- dbg_dump_node(c, sb->node);
+ ubifs_dump_node(c, sb->node);
return -EINVAL;
return 0;
}
@@ -2678,7 +2676,7 @@ static void cut_data(const void *buf, unsigned int len)
}
int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
- int offs, int len, int dtype)
+ int offs, int len)
{
int err, failing;
@@ -2688,7 +2686,7 @@ int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
failing = power_cut_emulated(c, lnum, 1);
if (failing)
cut_data(buf, len);
- err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
+ err = ubi_leb_write(c->ubi, lnum, buf, offs, len);
if (err)
return err;
if (failing)
@@ -2697,7 +2695,7 @@ int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
}
int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf,
- int len, int dtype)
+ int len)
{
int err;
@@ -2705,7 +2703,7 @@ int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf,
return -EROFS;
if (power_cut_emulated(c, lnum, 1))
return -EROFS;
- err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
+ err = ubi_leb_change(c->ubi, lnum, buf, len);
if (err)
return err;
if (power_cut_emulated(c, lnum, 1))
@@ -2729,7 +2727,7 @@ int dbg_leb_unmap(struct ubifs_info *c, int lnum)
return 0;
}
-int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype)
+int dbg_leb_map(struct ubifs_info *c, int lnum)
{
int err;
@@ -2737,7 +2735,7 @@ int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype)
return -EROFS;
if (power_cut_emulated(c, lnum, 0))
return -EROFS;
- err = ubi_leb_map(c->ubi, lnum, dtype);
+ err = ubi_leb_map(c->ubi, lnum);
if (err)
return err;
if (power_cut_emulated(c, lnum, 0))
@@ -2857,16 +2855,16 @@ static ssize_t dfs_file_write(struct file *file, const char __user *u,
* 'ubifs-debug' file-system instead.
*/
if (file->f_path.dentry == d->dfs_dump_lprops) {
- dbg_dump_lprops(c);
+ ubifs_dump_lprops(c);
return count;
}
if (file->f_path.dentry == d->dfs_dump_budg) {
- dbg_dump_budg(c, &c->bi);
+ ubifs_dump_budg(c, &c->bi);
return count;
}
if (file->f_path.dentry == d->dfs_dump_tnc) {
mutex_lock(&c->tnc_mutex);
- dbg_dump_tnc(c);
+ ubifs_dump_tnc(c);
mutex_unlock(&c->tnc_mutex);
return count;
}
@@ -3189,5 +3187,3 @@ void ubifs_debugging_exit(struct ubifs_info *c)
{
kfree(c->dbg);
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index 9f717655df18..486a8e024fb6 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -29,8 +29,6 @@ typedef int (*dbg_leaf_callback)(struct ubifs_info *c,
typedef int (*dbg_znode_callback)(struct ubifs_info *c,
struct ubifs_znode *znode, void *priv);
-#ifdef CONFIG_UBIFS_FS_DEBUG
-
/*
* The UBIFS debugfs directory name pattern and maximum name length (3 for "ubi"
* + 1 for "_" and plus 2x2 for 2 UBI numbers and 1 for the trailing zero byte.
@@ -149,7 +147,7 @@ struct ubifs_global_debug_info {
if (unlikely(!(expr))) { \
printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
__func__, __LINE__, current->pid); \
- dbg_dump_stack(); \
+ dump_stack(); \
} \
} while (0)
@@ -161,12 +159,6 @@ struct ubifs_global_debug_info {
} \
} while (0)
-#define dbg_dump_stack() dump_stack()
-
-#define dbg_err(fmt, ...) do { \
- ubifs_err(fmt, ##__VA_ARGS__); \
-} while (0)
-
#define ubifs_dbg_msg(type, fmt, ...) \
pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__)
@@ -257,27 +249,27 @@ const char *dbg_get_key_dump(const struct ubifs_info *c,
const union ubifs_key *key);
const char *dbg_snprintf_key(const struct ubifs_info *c,
const union ubifs_key *key, char *buffer, int len);
-void dbg_dump_inode(struct ubifs_info *c, const struct inode *inode);
-void dbg_dump_node(const struct ubifs_info *c, const void *node);
-void dbg_dump_lpt_node(const struct ubifs_info *c, void *node, int lnum,
- int offs);
-void dbg_dump_budget_req(const struct ubifs_budget_req *req);
-void dbg_dump_lstats(const struct ubifs_lp_stats *lst);
-void dbg_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi);
-void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp);
-void dbg_dump_lprops(struct ubifs_info *c);
-void dbg_dump_lpt_info(struct ubifs_info *c);
-void dbg_dump_leb(const struct ubifs_info *c, int lnum);
-void dbg_dump_sleb(const struct ubifs_info *c,
- const struct ubifs_scan_leb *sleb, int offs);
-void dbg_dump_znode(const struct ubifs_info *c,
- const struct ubifs_znode *znode);
-void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat);
-void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
- struct ubifs_nnode *parent, int iip);
-void dbg_dump_tnc(struct ubifs_info *c);
-void dbg_dump_index(struct ubifs_info *c);
-void dbg_dump_lpt_lebs(const struct ubifs_info *c);
+void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode);
+void ubifs_dump_node(const struct ubifs_info *c, const void *node);
+void ubifs_dump_budget_req(const struct ubifs_budget_req *req);
+void ubifs_dump_lstats(const struct ubifs_lp_stats *lst);
+void ubifs_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi);
+void ubifs_dump_lprop(const struct ubifs_info *c,
+ const struct ubifs_lprops *lp);
+void ubifs_dump_lprops(struct ubifs_info *c);
+void ubifs_dump_lpt_info(struct ubifs_info *c);
+void ubifs_dump_leb(const struct ubifs_info *c, int lnum);
+void ubifs_dump_sleb(const struct ubifs_info *c,
+ const struct ubifs_scan_leb *sleb, int offs);
+void ubifs_dump_znode(const struct ubifs_info *c,
+ const struct ubifs_znode *znode);
+void ubifs_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap,
+ int cat);
+void ubifs_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
+ struct ubifs_nnode *parent, int iip);
+void ubifs_dump_tnc(struct ubifs_info *c);
+void ubifs_dump_index(struct ubifs_info *c);
+void ubifs_dump_lpt_lebs(const struct ubifs_info *c);
int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
dbg_znode_callback znode_cb, void *priv);
@@ -307,11 +299,10 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head);
int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head);
int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
- int len, int dtype);
-int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
- int dtype);
+ int len);
+int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len);
int dbg_leb_unmap(struct ubifs_info *c, int lnum);
-int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype);
+int dbg_leb_map(struct ubifs_info *c, int lnum);
/* Debugfs-related stuff */
int dbg_debugfs_init(void);
@@ -319,162 +310,4 @@ void dbg_debugfs_exit(void);
int dbg_debugfs_init_fs(struct ubifs_info *c);
void dbg_debugfs_exit_fs(struct ubifs_info *c);
-#else /* !CONFIG_UBIFS_FS_DEBUG */
-
-/* Use "if (0)" to make compiler check arguments even if debugging is off */
-#define ubifs_assert(expr) do { \
- if (0) \
- printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
- __func__, __LINE__, current->pid); \
-} while (0)
-
-#define dbg_err(fmt, ...) do { \
- if (0) \
- ubifs_err(fmt, ##__VA_ARGS__); \
-} while (0)
-
-#define DBGKEY(key) ((char *)(key))
-#define DBGKEY1(key) ((char *)(key))
-
-#define ubifs_dbg_msg(fmt, ...) do { \
- if (0) \
- printk(KERN_DEBUG fmt "\n", ##__VA_ARGS__); \
-} while (0)
-
-#define dbg_dump_stack()
-#define ubifs_assert_cmt_locked(c)
-
-#define dbg_msg(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_gen(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_jnl(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_jnlk(key, fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_tnc(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_tnck(key, fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_lp(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_find(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_mnt(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_mntk(key, fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_io(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_cmt(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_budg(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_log(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_gc(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_scan(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_rcvry(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-
-static inline int ubifs_debugging_init(struct ubifs_info *c) { return 0; }
-static inline void ubifs_debugging_exit(struct ubifs_info *c) { return; }
-static inline const char *dbg_ntype(int type) { return ""; }
-static inline const char *dbg_cstate(int cmt_state) { return ""; }
-static inline const char *dbg_jhead(int jhead) { return ""; }
-static inline const char *
-dbg_get_key_dump(const struct ubifs_info *c,
- const union ubifs_key *key) { return ""; }
-static inline const char *
-dbg_snprintf_key(const struct ubifs_info *c,
- const union ubifs_key *key, char *buffer,
- int len) { return ""; }
-static inline void dbg_dump_inode(struct ubifs_info *c,
- const struct inode *inode) { return; }
-static inline void dbg_dump_node(const struct ubifs_info *c,
- const void *node) { return; }
-static inline void dbg_dump_lpt_node(const struct ubifs_info *c,
- void *node, int lnum,
- int offs) { return; }
-static inline void
-dbg_dump_budget_req(const struct ubifs_budget_req *req) { return; }
-static inline void
-dbg_dump_lstats(const struct ubifs_lp_stats *lst) { return; }
-static inline void
-dbg_dump_budg(struct ubifs_info *c,
- const struct ubifs_budg_info *bi) { return; }
-static inline void dbg_dump_lprop(const struct ubifs_info *c,
- const struct ubifs_lprops *lp) { return; }
-static inline void dbg_dump_lprops(struct ubifs_info *c) { return; }
-static inline void dbg_dump_lpt_info(struct ubifs_info *c) { return; }
-static inline void dbg_dump_leb(const struct ubifs_info *c,
- int lnum) { return; }
-static inline void
-dbg_dump_sleb(const struct ubifs_info *c,
- const struct ubifs_scan_leb *sleb, int offs) { return; }
-static inline void
-dbg_dump_znode(const struct ubifs_info *c,
- const struct ubifs_znode *znode) { return; }
-static inline void dbg_dump_heap(struct ubifs_info *c,
- struct ubifs_lpt_heap *heap,
- int cat) { return; }
-static inline void dbg_dump_pnode(struct ubifs_info *c,
- struct ubifs_pnode *pnode,
- struct ubifs_nnode *parent,
- int iip) { return; }
-static inline void dbg_dump_tnc(struct ubifs_info *c) { return; }
-static inline void dbg_dump_index(struct ubifs_info *c) { return; }
-static inline void dbg_dump_lpt_lebs(const struct ubifs_info *c) { return; }
-
-static inline int dbg_walk_index(struct ubifs_info *c,
- dbg_leaf_callback leaf_cb,
- dbg_znode_callback znode_cb,
- void *priv) { return 0; }
-static inline void dbg_save_space_info(struct ubifs_info *c) { return; }
-static inline int dbg_check_space_info(struct ubifs_info *c) { return 0; }
-static inline int dbg_check_lprops(struct ubifs_info *c) { return 0; }
-static inline int
-dbg_old_index_check_init(struct ubifs_info *c,
- struct ubifs_zbranch *zroot) { return 0; }
-static inline int
-dbg_check_old_index(struct ubifs_info *c,
- struct ubifs_zbranch *zroot) { return 0; }
-static inline int dbg_check_cats(struct ubifs_info *c) { return 0; }
-static inline int dbg_check_ltab(struct ubifs_info *c) { return 0; }
-static inline int dbg_chk_lpt_free_spc(struct ubifs_info *c) { return 0; }
-static inline int dbg_chk_lpt_sz(struct ubifs_info *c,
- int action, int len) { return 0; }
-static inline int
-dbg_check_synced_i_size(const struct ubifs_info *c,
- struct inode *inode) { return 0; }
-static inline int dbg_check_dir(struct ubifs_info *c,
- const struct inode *dir) { return 0; }
-static inline int dbg_check_tnc(struct ubifs_info *c, int extra) { return 0; }
-static inline int dbg_check_idx_size(struct ubifs_info *c,
- long long idx_size) { return 0; }
-static inline int dbg_check_filesystem(struct ubifs_info *c) { return 0; }
-static inline void dbg_check_heap(struct ubifs_info *c,
- struct ubifs_lpt_heap *heap,
- int cat, int add_pos) { return; }
-static inline int dbg_check_lpt_nodes(struct ubifs_info *c,
- struct ubifs_cnode *cnode, int row, int col) { return 0; }
-static inline int dbg_check_inode_size(struct ubifs_info *c,
- const struct inode *inode,
- loff_t size) { return 0; }
-static inline int
-dbg_check_data_nodes_order(struct ubifs_info *c,
- struct list_head *head) { return 0; }
-static inline int
-dbg_check_nondata_nodes_order(struct ubifs_info *c,
- struct list_head *head) { return 0; }
-
-static inline int dbg_leb_write(struct ubifs_info *c, int lnum,
- const void *buf, int offset,
- int len, int dtype) { return 0; }
-static inline int dbg_leb_change(struct ubifs_info *c, int lnum,
- const void *buf, int len,
- int dtype) { return 0; }
-static inline int dbg_leb_unmap(struct ubifs_info *c, int lnum) { return 0; }
-static inline int dbg_leb_map(struct ubifs_info *c, int lnum,
- int dtype) { return 0; }
-
-static inline int dbg_is_chk_gen(const struct ubifs_info *c) { return 0; }
-static inline int dbg_is_chk_index(const struct ubifs_info *c) { return 0; }
-static inline int dbg_is_chk_orph(const struct ubifs_info *c) { return 0; }
-static inline int dbg_is_chk_lprops(const struct ubifs_info *c) { return 0; }
-static inline int dbg_is_chk_fs(const struct ubifs_info *c) { return 0; }
-static inline int dbg_is_tst_rcvry(const struct ubifs_info *c) { return 0; }
-static inline int dbg_is_power_cut(const struct ubifs_info *c) { return 0; }
-
-static inline int dbg_debugfs_init(void) { return 0; }
-static inline void dbg_debugfs_exit(void) { return; }
-static inline int dbg_debugfs_init_fs(struct ubifs_info *c) { return 0; }
-static inline int dbg_debugfs_exit_fs(struct ubifs_info *c) { return 0; }
-
-#endif /* !CONFIG_UBIFS_FS_DEBUG */
#endif /* !__UBIFS_DEBUG_H__ */
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index ec9f1870ab7f..62a2727f4ecf 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -170,8 +170,6 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
return inode;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
-
static int dbg_check_name(const struct ubifs_info *c,
const struct ubifs_dent_node *dent,
const struct qstr *nm)
@@ -185,12 +183,6 @@ static int dbg_check_name(const struct ubifs_info *c,
return 0;
}
-#else
-
-#define dbg_check_name(c, dent, nm) 0
-
-#endif
-
static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
{
@@ -1187,12 +1179,10 @@ const struct inode_operations ubifs_dir_inode_operations = {
.rename = ubifs_rename,
.setattr = ubifs_setattr,
.getattr = ubifs_getattr,
-#ifdef CONFIG_UBIFS_FS_XATTR
.setxattr = ubifs_setxattr,
.getxattr = ubifs_getxattr,
.listxattr = ubifs_listxattr,
.removexattr = ubifs_removexattr,
-#endif
};
const struct file_operations ubifs_dir_operations = {
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 5c8f6dc1d28b..35389ca2d267 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -97,7 +97,7 @@ static int read_block(struct inode *inode, void *addr, unsigned int block,
dump:
ubifs_err("bad data node (block %u, inode %lu)",
block, inode->i_ino);
- dbg_dump_node(c, dn);
+ ubifs_dump_node(c, dn);
return -EINVAL;
}
@@ -1562,12 +1562,10 @@ const struct address_space_operations ubifs_file_address_operations = {
const struct inode_operations ubifs_file_inode_operations = {
.setattr = ubifs_setattr,
.getattr = ubifs_getattr,
-#ifdef CONFIG_UBIFS_FS_XATTR
.setxattr = ubifs_setxattr,
.getxattr = ubifs_getxattr,
.listxattr = ubifs_listxattr,
.removexattr = ubifs_removexattr,
-#endif
};
const struct inode_operations ubifs_symlink_inode_operations = {
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index ded29f6224c2..04dd6f47635e 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -109,7 +109,7 @@ static int switch_gc_head(struct ubifs_info *c)
return err;
c->gc_lnum = -1;
- err = ubifs_wbuf_seek_nolock(wbuf, gc_lnum, 0, UBI_LONGTERM);
+ err = ubifs_wbuf_seek_nolock(wbuf, gc_lnum, 0);
return err;
}
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index 9228950a658f..e18b9889a51b 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -109,13 +109,13 @@ int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
if (err && (err != -EBADMSG || even_ebadmsg)) {
ubifs_err("reading %d bytes from LEB %d:%d failed, error %d",
len, lnum, offs, err);
- dbg_dump_stack();
+ dump_stack();
}
return err;
}
int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
- int len, int dtype)
+ int len)
{
int err;
@@ -123,20 +123,19 @@ int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
if (c->ro_error)
return -EROFS;
if (!dbg_is_tst_rcvry(c))
- err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
+ err = ubi_leb_write(c->ubi, lnum, buf, offs, len);
else
- err = dbg_leb_write(c, lnum, buf, offs, len, dtype);
+ err = dbg_leb_write(c, lnum, buf, offs, len);
if (err) {
ubifs_err("writing %d bytes to LEB %d:%d failed, error %d",
len, lnum, offs, err);
ubifs_ro_mode(c, err);
- dbg_dump_stack();
+ dump_stack();
}
return err;
}
-int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
- int dtype)
+int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len)
{
int err;
@@ -144,14 +143,14 @@ int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
if (c->ro_error)
return -EROFS;
if (!dbg_is_tst_rcvry(c))
- err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
+ err = ubi_leb_change(c->ubi, lnum, buf, len);
else
- err = dbg_leb_change(c, lnum, buf, len, dtype);
+ err = dbg_leb_change(c, lnum, buf, len);
if (err) {
ubifs_err("changing %d bytes in LEB %d failed, error %d",
len, lnum, err);
ubifs_ro_mode(c, err);
- dbg_dump_stack();
+ dump_stack();
}
return err;
}
@@ -170,12 +169,12 @@ int ubifs_leb_unmap(struct ubifs_info *c, int lnum)
if (err) {
ubifs_err("unmap LEB %d failed, error %d", lnum, err);
ubifs_ro_mode(c, err);
- dbg_dump_stack();
+ dump_stack();
}
return err;
}
-int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype)
+int ubifs_leb_map(struct ubifs_info *c, int lnum)
{
int err;
@@ -183,13 +182,13 @@ int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype)
if (c->ro_error)
return -EROFS;
if (!dbg_is_tst_rcvry(c))
- err = ubi_leb_map(c->ubi, lnum, dtype);
+ err = ubi_leb_map(c->ubi, lnum);
else
- err = dbg_leb_map(c, lnum, dtype);
+ err = dbg_leb_map(c, lnum);
if (err) {
ubifs_err("mapping LEB %d failed, error %d", lnum, err);
ubifs_ro_mode(c, err);
- dbg_dump_stack();
+ dump_stack();
}
return err;
}
@@ -202,7 +201,7 @@ int ubifs_is_mapped(const struct ubifs_info *c, int lnum)
if (err < 0) {
ubifs_err("ubi_is_mapped failed for LEB %d, error %d",
lnum, err);
- dbg_dump_stack();
+ dump_stack();
}
return err;
}
@@ -294,8 +293,8 @@ out_len:
out:
if (!quiet) {
ubifs_err("bad node at LEB %d:%d", lnum, offs);
- dbg_dump_node(c, buf);
- dbg_dump_stack();
+ ubifs_dump_node(c, buf);
+ dump_stack();
}
return err;
}
@@ -523,8 +522,7 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
dirt = sync_len - wbuf->used;
if (dirt)
ubifs_pad(c, wbuf->buf + wbuf->used, dirt);
- err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, sync_len,
- wbuf->dtype);
+ err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, sync_len);
if (err)
return err;
@@ -562,14 +560,12 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
* @wbuf: write-buffer
* @lnum: logical eraseblock number to seek to
* @offs: logical eraseblock offset to seek to
- * @dtype: data type
*
* This function targets the write-buffer to logical eraseblock @lnum:@offs.
* The write-buffer has to be empty. Returns zero in case of success and a
* negative error code in case of failure.
*/
-int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
- int dtype)
+int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs)
{
const struct ubifs_info *c = wbuf->c;
@@ -592,7 +588,6 @@ int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
wbuf->avail = wbuf->size;
wbuf->used = 0;
spin_unlock(&wbuf->lock);
- wbuf->dtype = dtype;
return 0;
}
@@ -719,8 +714,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
dbg_io("flush jhead %s wbuf to LEB %d:%d",
dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf,
- wbuf->offs, wbuf->size,
- wbuf->dtype);
+ wbuf->offs, wbuf->size);
if (err)
goto out;
@@ -756,7 +750,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs,
- wbuf->size, wbuf->dtype);
+ wbuf->size);
if (err)
goto out;
@@ -775,7 +769,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
dbg_io("write %d bytes to LEB %d:%d",
wbuf->size, wbuf->lnum, wbuf->offs);
err = ubifs_leb_write(c, wbuf->lnum, buf, wbuf->offs,
- wbuf->size, wbuf->dtype);
+ wbuf->size);
if (err)
goto out;
@@ -797,7 +791,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum,
wbuf->offs);
err = ubifs_leb_write(c, wbuf->lnum, buf + written,
- wbuf->offs, n, wbuf->dtype);
+ wbuf->offs, n);
if (err)
goto out;
wbuf->offs += n;
@@ -841,9 +835,9 @@ exit:
out:
ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",
len, wbuf->lnum, wbuf->offs, err);
- dbg_dump_node(c, buf);
- dbg_dump_stack();
- dbg_dump_leb(c, wbuf->lnum);
+ ubifs_dump_node(c, buf);
+ dump_stack();
+ ubifs_dump_leb(c, wbuf->lnum);
return err;
}
@@ -854,7 +848,6 @@ out:
* @len: node length
* @lnum: logical eraseblock number
* @offs: offset within the logical eraseblock
- * @dtype: node life-time hint (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
*
* This function automatically fills node magic number, assigns sequence
* number, and calculates node CRC checksum. The length of the @buf buffer has
@@ -863,7 +856,7 @@ out:
* success and a negative error code in case of failure.
*/
int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
- int offs, int dtype)
+ int offs)
{
int err, buf_len = ALIGN(len, c->min_io_size);
@@ -879,9 +872,9 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
return -EROFS;
ubifs_prepare_node(c, buf, len, 1);
- err = ubifs_leb_write(c, lnum, buf, offs, buf_len, dtype);
+ err = ubifs_leb_write(c, lnum, buf, offs, buf_len);
if (err)
- dbg_dump_node(c, buf);
+ ubifs_dump_node(c, buf);
return err;
}
@@ -960,8 +953,8 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
out:
ubifs_err("bad node at LEB %d:%d", lnum, offs);
- dbg_dump_node(c, buf);
- dbg_dump_stack();
+ ubifs_dump_node(c, buf);
+ dump_stack();
return -EINVAL;
}
@@ -1017,8 +1010,8 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
out:
ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs,
ubi_is_mapped(c->ubi, lnum));
- dbg_dump_node(c, buf);
- dbg_dump_stack();
+ ubifs_dump_node(c, buf);
+ dump_stack();
return -EINVAL;
}
@@ -1056,7 +1049,6 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
*/
size = c->max_write_size - (c->leb_start % c->max_write_size);
wbuf->avail = wbuf->size = size;
- wbuf->dtype = UBI_UNKNOWN;
wbuf->sync_callback = NULL;
mutex_init(&wbuf->io_mutex);
spin_lock_init(&wbuf->lock);
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index 2f438ab2e7a2..12c0f154ca83 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -214,7 +214,7 @@ out:
err = ubifs_add_bud_to_log(c, jhead, lnum, offs);
if (err)
goto out_return;
- err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, wbuf->dtype);
+ err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs);
if (err)
goto out_unlock;
@@ -385,9 +385,9 @@ out:
if (err == -ENOSPC) {
/* This are some budgeting problems, print useful information */
down_write(&c->commit_sem);
- dbg_dump_stack();
- dbg_dump_budg(c, &c->bi);
- dbg_dump_lprops(c);
+ dump_stack();
+ ubifs_dump_budg(c, &c->bi);
+ ubifs_dump_lprops(c);
cmt_retries = dbg_check_lprops(c);
up_write(&c->commit_sem);
}
@@ -1267,7 +1267,6 @@ out_free:
return err;
}
-#ifdef CONFIG_UBIFS_FS_XATTR
/**
* ubifs_jnl_delete_xattr - delete an extended attribute.
@@ -1462,4 +1461,3 @@ out_free:
return err;
}
-#endif /* CONFIG_UBIFS_FS_XATTR */
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
index f9fd068d1ae0..c80b15d6c8de 100644
--- a/fs/ubifs/log.c
+++ b/fs/ubifs/log.c
@@ -29,11 +29,7 @@
#include "ubifs.h"
-#ifdef CONFIG_UBIFS_FS_DEBUG
static int dbg_check_bud_bytes(struct ubifs_info *c);
-#else
-#define dbg_check_bud_bytes(c) 0
-#endif
/**
* ubifs_search_bud - search bud LEB.
@@ -262,7 +258,7 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
* an unclean reboot, because the target LEB might have been
* unmapped, but not yet physically erased.
*/
- err = ubifs_leb_map(c, bud->lnum, UBI_SHORTTERM);
+ err = ubifs_leb_map(c, bud->lnum);
if (err)
goto out_unlock;
}
@@ -270,7 +266,7 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
dbg_log("write ref LEB %d:%d",
c->lhead_lnum, c->lhead_offs);
err = ubifs_write_node(c, ref, UBIFS_REF_NODE_SZ, c->lhead_lnum,
- c->lhead_offs, UBI_SHORTTERM);
+ c->lhead_offs);
if (err)
goto out_unlock;
@@ -422,7 +418,7 @@ int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum)
len = ALIGN(len, c->min_io_size);
dbg_log("writing commit start at LEB %d:0, len %d", c->lhead_lnum, len);
- err = ubifs_leb_write(c, c->lhead_lnum, cs, 0, len, UBI_SHORTTERM);
+ err = ubifs_leb_write(c, c->lhead_lnum, cs, 0, len);
if (err)
goto out;
@@ -623,7 +619,7 @@ static int add_node(struct ubifs_info *c, void *buf, int *lnum, int *offs,
int sz = ALIGN(*offs, c->min_io_size), err;
ubifs_pad(c, buf + *offs, sz - *offs);
- err = ubifs_leb_change(c, *lnum, buf, sz, UBI_SHORTTERM);
+ err = ubifs_leb_change(c, *lnum, buf, sz);
if (err)
return err;
*lnum = ubifs_next_log_lnum(c, *lnum);
@@ -702,7 +698,7 @@ int ubifs_consolidate_log(struct ubifs_info *c)
int sz = ALIGN(offs, c->min_io_size);
ubifs_pad(c, buf + offs, sz - offs);
- err = ubifs_leb_change(c, write_lnum, buf, sz, UBI_SHORTTERM);
+ err = ubifs_leb_change(c, write_lnum, buf, sz);
if (err)
goto out_free;
offs = ALIGN(offs, c->min_io_size);
@@ -734,8 +730,6 @@ out_free:
return err;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
-
/**
* dbg_check_bud_bytes - make sure bud bytes calculation are all right.
* @c: UBIFS file-system description object
@@ -767,5 +761,3 @@ static int dbg_check_bud_bytes(struct ubifs_info *c)
return err;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c
index f8a181e647cc..86eb8e533249 100644
--- a/fs/ubifs/lprops.c
+++ b/fs/ubifs/lprops.c
@@ -447,7 +447,7 @@ static void change_category(struct ubifs_info *c, struct ubifs_lprops *lprops)
int new_cat = ubifs_categorize_lprops(c, lprops);
if (old_cat == new_cat) {
- struct ubifs_lpt_heap *heap = &c->lpt_heap[new_cat - 1];
+ struct ubifs_lpt_heap *heap;
/* lprops on a heap now must be moved up or down */
if (new_cat < 1 || new_cat > LPROPS_HEAP_CNT)
@@ -846,7 +846,9 @@ const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c)
return lprops;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
+/*
+ * Everything below is related to debugging.
+ */
/**
* dbg_check_cats - check category heaps and lists.
@@ -1001,8 +1003,8 @@ void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat,
out:
if (err) {
dbg_msg("failed cat %d hpos %d err %d", cat, i, err);
- dbg_dump_stack();
- dbg_dump_heap(c, heap, cat);
+ dump_stack();
+ ubifs_dump_heap(c, heap, cat);
}
}
@@ -1109,8 +1111,8 @@ static int scan_check_cb(struct ubifs_info *c,
if (IS_ERR(sleb)) {
ret = PTR_ERR(sleb);
if (ret == -EUCLEAN) {
- dbg_dump_lprops(c);
- dbg_dump_budg(c, &c->bi);
+ ubifs_dump_lprops(c);
+ ubifs_dump_budg(c, &c->bi);
}
goto out;
}
@@ -1237,7 +1239,7 @@ out_print:
ubifs_err("bad accounting of LEB %d: free %d, dirty %d flags %#x, "
"should be free %d, dirty %d",
lnum, lp->free, lp->dirty, lp->flags, free, dirty);
- dbg_dump_leb(c, lnum);
+ ubifs_dump_leb(c, lnum);
out_destroy:
ubifs_scan_destroy(sleb);
ret = -EINVAL;
@@ -1315,5 +1317,3 @@ int dbg_check_lprops(struct ubifs_info *c)
out:
return err;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index 66d59d0a1402..ce33b2beb151 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -701,8 +701,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
alen = ALIGN(len, c->min_io_size);
set_ltab(c, lnum, c->leb_size - alen, alen - len);
memset(p, 0xff, alen - len);
- err = ubifs_leb_change(c, lnum++, buf, alen,
- UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum++, buf, alen);
if (err)
goto out;
p = buf;
@@ -732,8 +731,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
set_ltab(c, lnum, c->leb_size - alen,
alen - len);
memset(p, 0xff, alen - len);
- err = ubifs_leb_change(c, lnum++, buf, alen,
- UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum++, buf, alen);
if (err)
goto out;
p = buf;
@@ -780,8 +778,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
alen = ALIGN(len, c->min_io_size);
set_ltab(c, lnum, c->leb_size - alen, alen - len);
memset(p, 0xff, alen - len);
- err = ubifs_leb_change(c, lnum++, buf, alen,
- UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum++, buf, alen);
if (err)
goto out;
p = buf;
@@ -806,7 +803,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
alen = ALIGN(len, c->min_io_size);
set_ltab(c, lnum, c->leb_size - alen, alen - len);
memset(p, 0xff, alen - len);
- err = ubifs_leb_change(c, lnum++, buf, alen, UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum++, buf, alen);
if (err)
goto out;
p = buf;
@@ -826,7 +823,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
/* Write remaining buffer */
memset(p, 0xff, alen - len);
- err = ubifs_leb_change(c, lnum, buf, alen, UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum, buf, alen);
if (err)
goto out;
@@ -926,7 +923,7 @@ static int check_lpt_crc(void *buf, int len)
if (crc != calc_crc) {
ubifs_err("invalid crc in LPT node: crc %hx calc %hx", crc,
calc_crc);
- dbg_dump_stack();
+ dump_stack();
return -EINVAL;
}
return 0;
@@ -949,7 +946,7 @@ static int check_lpt_type(uint8_t **addr, int *pos, int type)
if (node_type != type) {
ubifs_err("invalid type (%d) in LPT node type %d", node_type,
type);
- dbg_dump_stack();
+ dump_stack();
return -EINVAL;
}
return 0;
@@ -1247,7 +1244,7 @@ int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
out:
ubifs_err("error %d reading nnode at %d:%d", err, lnum, offs);
- dbg_dump_stack();
+ dump_stack();
kfree(nnode);
return err;
}
@@ -1312,8 +1309,8 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
out:
ubifs_err("error %d reading pnode at %d:%d", err, lnum, offs);
- dbg_dump_pnode(c, pnode, parent, iip);
- dbg_dump_stack();
+ ubifs_dump_pnode(c, pnode, parent, iip);
+ dump_stack();
dbg_msg("calc num: %d", calc_pnode_num_from_parent(c, parent, iip));
kfree(pnode);
return err;
@@ -1740,16 +1737,20 @@ int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr)
if (rd) {
err = lpt_init_rd(c);
if (err)
- return err;
+ goto out_err;
}
if (wr) {
err = lpt_init_wr(c);
if (err)
- return err;
+ goto out_err;
}
return 0;
+
+out_err:
+ ubifs_lpt_free(c, 0);
+ return err;
}
/**
@@ -2080,8 +2081,6 @@ out:
return err;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
-
/**
* dbg_chk_pnode - check a pnode.
* @c: the UBIFS file-system description object
@@ -2096,8 +2095,8 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
int i;
if (pnode->num != col) {
- dbg_err("pnode num %d expected %d parent num %d iip %d",
- pnode->num, col, pnode->parent->num, pnode->iip);
+ ubifs_err("pnode num %d expected %d parent num %d iip %d",
+ pnode->num, col, pnode->parent->num, pnode->iip);
return -EINVAL;
}
for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
@@ -2111,14 +2110,14 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
if (lnum >= c->leb_cnt)
continue;
if (lprops->lnum != lnum) {
- dbg_err("bad LEB number %d expected %d",
- lprops->lnum, lnum);
+ ubifs_err("bad LEB number %d expected %d",
+ lprops->lnum, lnum);
return -EINVAL;
}
if (lprops->flags & LPROPS_TAKEN) {
if (cat != LPROPS_UNCAT) {
- dbg_err("LEB %d taken but not uncat %d",
- lprops->lnum, cat);
+ ubifs_err("LEB %d taken but not uncat %d",
+ lprops->lnum, cat);
return -EINVAL;
}
continue;
@@ -2130,8 +2129,8 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
case LPROPS_FRDI_IDX:
break;
default:
- dbg_err("LEB %d index but cat %d",
- lprops->lnum, cat);
+ ubifs_err("LEB %d index but cat %d",
+ lprops->lnum, cat);
return -EINVAL;
}
} else {
@@ -2143,8 +2142,8 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
case LPROPS_FREEABLE:
break;
default:
- dbg_err("LEB %d not index but cat %d",
- lprops->lnum, cat);
+ ubifs_err("LEB %d not index but cat %d",
+ lprops->lnum, cat);
return -EINVAL;
}
}
@@ -2184,24 +2183,24 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
break;
}
if (!found) {
- dbg_err("LEB %d cat %d not found in cat heap/list",
- lprops->lnum, cat);
+ ubifs_err("LEB %d cat %d not found in cat heap/list",
+ lprops->lnum, cat);
return -EINVAL;
}
switch (cat) {
case LPROPS_EMPTY:
if (lprops->free != c->leb_size) {
- dbg_err("LEB %d cat %d free %d dirty %d",
- lprops->lnum, cat, lprops->free,
- lprops->dirty);
+ ubifs_err("LEB %d cat %d free %d dirty %d",
+ lprops->lnum, cat, lprops->free,
+ lprops->dirty);
return -EINVAL;
}
case LPROPS_FREEABLE:
case LPROPS_FRDI_IDX:
if (lprops->free + lprops->dirty != c->leb_size) {
- dbg_err("LEB %d cat %d free %d dirty %d",
- lprops->lnum, cat, lprops->free,
- lprops->dirty);
+ ubifs_err("LEB %d cat %d free %d dirty %d",
+ lprops->lnum, cat, lprops->free,
+ lprops->dirty);
return -EINVAL;
}
}
@@ -2235,9 +2234,10 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
/* cnode is a nnode */
num = calc_nnode_num(row, col);
if (cnode->num != num) {
- dbg_err("nnode num %d expected %d "
- "parent num %d iip %d", cnode->num, num,
- (nnode ? nnode->num : 0), cnode->iip);
+ ubifs_err("nnode num %d expected %d "
+ "parent num %d iip %d",
+ cnode->num, num,
+ (nnode ? nnode->num : 0), cnode->iip);
return -EINVAL;
}
nn = (struct ubifs_nnode *)cnode;
@@ -2274,5 +2274,3 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
}
return 0;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index cddd6bd214f4..4fa70734e6e7 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -30,11 +30,7 @@
#include <linux/random.h>
#include "ubifs.h"
-#ifdef CONFIG_UBIFS_FS_DEBUG
static int dbg_populate_lsave(struct ubifs_info *c);
-#else
-#define dbg_populate_lsave(c) 0
-#endif
/**
* first_dirty_cnode - find first dirty cnode.
@@ -324,11 +320,10 @@ static int layout_cnodes(struct ubifs_info *c)
return 0;
no_space:
- ubifs_err("LPT out of space");
- dbg_err("LPT out of space at LEB %d:%d needing %d, done_ltab %d, "
- "done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
- dbg_dump_lpt_info(c);
- dbg_dump_lpt_lebs(c);
+ ubifs_err("LPT out of space at LEB %d:%d needing %d, done_ltab %d, "
+ "done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
+ ubifs_dump_lpt_info(c);
+ ubifs_dump_lpt_lebs(c);
dump_stack();
return err;
}
@@ -421,7 +416,7 @@ static int write_cnodes(struct ubifs_info *c)
alen = ALIGN(wlen, c->min_io_size);
memset(buf + offs, 0xff, alen - wlen);
err = ubifs_leb_write(c, lnum, buf + from, from,
- alen, UBI_SHORTTERM);
+ alen);
if (err)
return err;
}
@@ -479,8 +474,7 @@ static int write_cnodes(struct ubifs_info *c)
wlen = offs - from;
alen = ALIGN(wlen, c->min_io_size);
memset(buf + offs, 0xff, alen - wlen);
- err = ubifs_leb_write(c, lnum, buf + from, from, alen,
- UBI_SHORTTERM);
+ err = ubifs_leb_write(c, lnum, buf + from, from, alen);
if (err)
return err;
dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
@@ -506,8 +500,7 @@ static int write_cnodes(struct ubifs_info *c)
wlen = offs - from;
alen = ALIGN(wlen, c->min_io_size);
memset(buf + offs, 0xff, alen - wlen);
- err = ubifs_leb_write(c, lnum, buf + from, from, alen,
- UBI_SHORTTERM);
+ err = ubifs_leb_write(c, lnum, buf + from, from, alen);
if (err)
return err;
dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
@@ -531,7 +524,7 @@ static int write_cnodes(struct ubifs_info *c)
wlen = offs - from;
alen = ALIGN(wlen, c->min_io_size);
memset(buf + offs, 0xff, alen - wlen);
- err = ubifs_leb_write(c, lnum, buf + from, from, alen, UBI_SHORTTERM);
+ err = ubifs_leb_write(c, lnum, buf + from, from, alen);
if (err)
return err;
@@ -552,11 +545,10 @@ static int write_cnodes(struct ubifs_info *c)
return 0;
no_space:
- ubifs_err("LPT out of space mismatch");
- dbg_err("LPT out of space mismatch at LEB %d:%d needing %d, done_ltab "
- "%d, done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
- dbg_dump_lpt_info(c);
- dbg_dump_lpt_lebs(c);
+ ubifs_err("LPT out of space mismatch at LEB %d:%d needing %d, done_ltab "
+ "%d, done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
+ ubifs_dump_lpt_info(c);
+ ubifs_dump_lpt_lebs(c);
dump_stack();
return err;
}
@@ -1497,7 +1489,9 @@ void ubifs_lpt_free(struct ubifs_info *c, int wr_only)
kfree(c->lpt_nod_buf);
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
+/*
+ * Everything below is related to debugging.
+ */
/**
* dbg_is_all_ff - determine if a buffer contains only 0xFF bytes.
@@ -1735,7 +1729,7 @@ int dbg_check_ltab(struct ubifs_info *c)
for (lnum = c->lpt_first; lnum <= c->lpt_last; lnum++) {
err = dbg_check_ltab_lnum(c, lnum);
if (err) {
- dbg_err("failed at LEB %d", lnum);
+ ubifs_err("failed at LEB %d", lnum);
return err;
}
}
@@ -1767,10 +1761,10 @@ int dbg_chk_lpt_free_spc(struct ubifs_info *c)
free += c->leb_size;
}
if (free < c->lpt_sz) {
- dbg_err("LPT space error: free %lld lpt_sz %lld",
- free, c->lpt_sz);
- dbg_dump_lpt_info(c);
- dbg_dump_lpt_lebs(c);
+ ubifs_err("LPT space error: free %lld lpt_sz %lld",
+ free, c->lpt_sz);
+ ubifs_dump_lpt_info(c);
+ ubifs_dump_lpt_lebs(c);
dump_stack();
return -EINVAL;
}
@@ -1807,13 +1801,13 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
d->chk_lpt_lebs = 0;
d->chk_lpt_wastage = 0;
if (c->dirty_pn_cnt > c->pnode_cnt) {
- dbg_err("dirty pnodes %d exceed max %d",
- c->dirty_pn_cnt, c->pnode_cnt);
+ ubifs_err("dirty pnodes %d exceed max %d",
+ c->dirty_pn_cnt, c->pnode_cnt);
err = -EINVAL;
}
if (c->dirty_nn_cnt > c->nnode_cnt) {
- dbg_err("dirty nnodes %d exceed max %d",
- c->dirty_nn_cnt, c->nnode_cnt);
+ ubifs_err("dirty nnodes %d exceed max %d",
+ c->dirty_nn_cnt, c->nnode_cnt);
err = -EINVAL;
}
return err;
@@ -1830,23 +1824,23 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
chk_lpt_sz *= d->chk_lpt_lebs;
chk_lpt_sz += len - c->nhead_offs;
if (d->chk_lpt_sz != chk_lpt_sz) {
- dbg_err("LPT wrote %lld but space used was %lld",
- d->chk_lpt_sz, chk_lpt_sz);
+ ubifs_err("LPT wrote %lld but space used was %lld",
+ d->chk_lpt_sz, chk_lpt_sz);
err = -EINVAL;
}
if (d->chk_lpt_sz > c->lpt_sz) {
- dbg_err("LPT wrote %lld but lpt_sz is %lld",
- d->chk_lpt_sz, c->lpt_sz);
+ ubifs_err("LPT wrote %lld but lpt_sz is %lld",
+ d->chk_lpt_sz, c->lpt_sz);
err = -EINVAL;
}
if (d->chk_lpt_sz2 && d->chk_lpt_sz != d->chk_lpt_sz2) {
- dbg_err("LPT layout size %lld but wrote %lld",
- d->chk_lpt_sz, d->chk_lpt_sz2);
+ ubifs_err("LPT layout size %lld but wrote %lld",
+ d->chk_lpt_sz, d->chk_lpt_sz2);
err = -EINVAL;
}
if (d->chk_lpt_sz2 && d->new_nhead_offs != len) {
- dbg_err("LPT new nhead offs: expected %d was %d",
- d->new_nhead_offs, len);
+ ubifs_err("LPT new nhead offs: expected %d was %d",
+ d->new_nhead_offs, len);
err = -EINVAL;
}
lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
@@ -1855,13 +1849,13 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
if (c->big_lpt)
lpt_sz += c->lsave_sz;
if (d->chk_lpt_sz - d->chk_lpt_wastage > lpt_sz) {
- dbg_err("LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
- d->chk_lpt_sz, d->chk_lpt_wastage, lpt_sz);
+ ubifs_err("LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
+ d->chk_lpt_sz, d->chk_lpt_wastage, lpt_sz);
err = -EINVAL;
}
if (err) {
- dbg_dump_lpt_info(c);
- dbg_dump_lpt_lebs(c);
+ ubifs_dump_lpt_info(c);
+ ubifs_dump_lpt_lebs(c);
dump_stack();
}
d->chk_lpt_sz2 = d->chk_lpt_sz;
@@ -1880,7 +1874,7 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
}
/**
- * dbg_dump_lpt_leb - dump an LPT LEB.
+ * ubifs_dump_lpt_leb - dump an LPT LEB.
* @c: UBIFS file-system description object
* @lnum: LEB number to dump
*
@@ -1986,13 +1980,13 @@ out:
}
/**
- * dbg_dump_lpt_lebs - dump LPT lebs.
+ * ubifs_dump_lpt_lebs - dump LPT lebs.
* @c: UBIFS file-system description object
*
* This function dumps all LPT LEBs. The caller has to make sure the LPT is
* locked.
*/
-void dbg_dump_lpt_lebs(const struct ubifs_info *c)
+void ubifs_dump_lpt_lebs(const struct ubifs_info *c)
{
int i;
@@ -2046,5 +2040,3 @@ static int dbg_populate_lsave(struct ubifs_info *c)
return 1;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c
index 278c2382e8c2..ab83ace9910a 100644
--- a/fs/ubifs/master.c
+++ b/fs/ubifs/master.c
@@ -241,7 +241,7 @@ static int validate_master(const struct ubifs_info *c)
out:
ubifs_err("bad master node at offset %d error %d", c->mst_offs, err);
- dbg_dump_node(c, c->mst_node);
+ ubifs_dump_node(c, c->mst_node);
return -EINVAL;
}
@@ -317,7 +317,7 @@ int ubifs_read_master(struct ubifs_info *c)
if (c->leb_cnt < old_leb_cnt ||
c->leb_cnt < UBIFS_MIN_LEB_CNT) {
ubifs_err("bad leb_cnt on master node");
- dbg_dump_node(c, c->mst_node);
+ ubifs_dump_node(c, c->mst_node);
return -EINVAL;
}
@@ -379,7 +379,7 @@ int ubifs_write_master(struct ubifs_info *c)
c->mst_offs = offs;
c->mst_node->highest_inum = cpu_to_le64(c->highest_inum);
- err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM);
+ err = ubifs_write_node(c, c->mst_node, len, lnum, offs);
if (err)
return err;
@@ -390,7 +390,7 @@ int ubifs_write_master(struct ubifs_info *c)
if (err)
return err;
}
- err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM);
+ err = ubifs_write_node(c, c->mst_node, len, lnum, offs);
return err;
}
diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c
index c542c73cfa3c..b02734db187c 100644
--- a/fs/ubifs/orphan.c
+++ b/fs/ubifs/orphan.c
@@ -52,11 +52,7 @@
* than the maximum number of orphans allowed.
*/
-#ifdef CONFIG_UBIFS_FS_DEBUG
static int dbg_check_orphans(struct ubifs_info *c);
-#else
-#define dbg_check_orphans(c) 0
-#endif
/**
* ubifs_add_orphan - add an orphan.
@@ -92,7 +88,7 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
else if (inum > o->inum)
p = &(*p)->rb_right;
else {
- dbg_err("orphaned twice");
+ ubifs_err("orphaned twice");
spin_unlock(&c->orphan_lock);
kfree(orphan);
return 0;
@@ -158,8 +154,8 @@ void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
}
}
spin_unlock(&c->orphan_lock);
- dbg_err("missing orphan ino %lu", (unsigned long)inum);
- dbg_dump_stack();
+ ubifs_err("missing orphan ino %lu", (unsigned long)inum);
+ dump_stack();
}
/**
@@ -248,8 +244,7 @@ static int do_write_orph_node(struct ubifs_info *c, int len, int atomic)
ubifs_assert(c->ohead_offs == 0);
ubifs_prepare_node(c, c->orph_buf, len, 1);
len = ALIGN(len, c->min_io_size);
- err = ubifs_leb_change(c, c->ohead_lnum, c->orph_buf, len,
- UBI_SHORTTERM);
+ err = ubifs_leb_change(c, c->ohead_lnum, c->orph_buf, len);
} else {
if (c->ohead_offs == 0) {
/* Ensure LEB has been unmapped */
@@ -258,7 +253,7 @@ static int do_write_orph_node(struct ubifs_info *c, int len, int atomic)
return err;
}
err = ubifs_write_node(c, c->orph_buf, len, c->ohead_lnum,
- c->ohead_offs, UBI_SHORTTERM);
+ c->ohead_offs);
}
return err;
}
@@ -569,7 +564,7 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
if (snod->type != UBIFS_ORPH_NODE) {
ubifs_err("invalid node type %d in orphan area at "
"%d:%d", snod->type, sleb->lnum, snod->offs);
- dbg_dump_node(c, snod->node);
+ ubifs_dump_node(c, snod->node);
return -EINVAL;
}
@@ -597,7 +592,7 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
ubifs_err("out of order commit number %llu in "
"orphan node at %d:%d",
cmt_no, sleb->lnum, snod->offs);
- dbg_dump_node(c, snod->node);
+ ubifs_dump_node(c, snod->node);
return -EINVAL;
}
dbg_rcvry("out of date LEB %d", sleb->lnum);
@@ -725,7 +720,9 @@ int ubifs_mount_orphans(struct ubifs_info *c, int unclean, int read_only)
return err;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
+/*
+ * Everything below is related to debugging.
+ */
struct check_orphan {
struct rb_node rb;
@@ -968,5 +965,3 @@ out:
kfree(ci.node);
return err;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index 2a935b317232..c30d976b4be8 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -213,10 +213,10 @@ static int write_rcvrd_mst_node(struct ubifs_info *c,
mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY);
ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1);
- err = ubifs_leb_change(c, lnum, mst, sz, UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum, mst, sz);
if (err)
goto out;
- err = ubifs_leb_change(c, lnum + 1, mst, sz, UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum + 1, mst, sz);
if (err)
goto out;
out:
@@ -362,12 +362,12 @@ out_err:
out_free:
ubifs_err("failed to recover master node");
if (mst1) {
- dbg_err("dumping first master node");
- dbg_dump_node(c, mst1);
+ ubifs_err("dumping first master node");
+ ubifs_dump_node(c, mst1);
}
if (mst2) {
- dbg_err("dumping second master node");
- dbg_dump_node(c, mst2);
+ ubifs_err("dumping second master node");
+ ubifs_dump_node(c, mst2);
}
vfree(buf2);
vfree(buf1);
@@ -555,8 +555,7 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
ubifs_pad(c, buf, pad_len);
}
}
- err = ubifs_leb_change(c, lnum, sleb->buf, len,
- UBI_UNKNOWN);
+ err = ubifs_leb_change(c, lnum, sleb->buf, len);
if (err)
return err;
}
@@ -683,7 +682,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
ret, lnum, offs);
break;
} else {
- dbg_err("unexpected return value %d", ret);
+ ubifs_err("unexpected return value %d", ret);
err = -EINVAL;
goto error;
}
@@ -789,7 +788,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
corrupted_rescan:
/* Re-scan the corrupted data with verbose messages */
- dbg_err("corruptio %d", ret);
+ ubifs_err("corruptio %d", ret);
ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
corrupted:
ubifs_scanned_corruption(c, lnum, offs, buf);
@@ -827,17 +826,17 @@ static int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs,
goto out_free;
ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0);
if (ret != SCANNED_A_NODE) {
- dbg_err("Not a valid node");
+ ubifs_err("Not a valid node");
goto out_err;
}
if (cs_node->ch.node_type != UBIFS_CS_NODE) {
- dbg_err("Node a CS node, type is %d", cs_node->ch.node_type);
+ ubifs_err("Node a CS node, type is %d", cs_node->ch.node_type);
goto out_err;
}
if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) {
- dbg_err("CS node cmt_no %llu != current cmt_no %llu",
- (unsigned long long)le64_to_cpu(cs_node->cmt_no),
- c->cmt_no);
+ ubifs_err("CS node cmt_no %llu != current cmt_no %llu",
+ (unsigned long long)le64_to_cpu(cs_node->cmt_no),
+ c->cmt_no);
goto out_err;
}
*cs_sqnum = le64_to_cpu(cs_node->ch.sqnum);
@@ -941,7 +940,7 @@ static int recover_head(struct ubifs_info *c, int lnum, int offs, void *sbuf)
err = ubifs_leb_read(c, lnum, sbuf, 0, offs, 1);
if (err)
return err;
- return ubifs_leb_change(c, lnum, sbuf, offs, UBI_UNKNOWN);
+ return ubifs_leb_change(c, lnum, sbuf, offs);
}
return 0;
@@ -1071,7 +1070,7 @@ static int clean_an_unclean_leb(struct ubifs_info *c,
}
/* Write back the LEB atomically */
- err = ubifs_leb_change(c, lnum, sbuf, len, UBI_UNKNOWN);
+ err = ubifs_leb_change(c, lnum, sbuf, len);
if (err)
return err;
@@ -1138,9 +1137,9 @@ static int grab_empty_leb(struct ubifs_info *c)
*/
lnum = ubifs_find_free_leb_for_idx(c);
if (lnum < 0) {
- dbg_err("could not find an empty LEB");
- dbg_dump_lprops(c);
- dbg_dump_budg(c, &c->bi);
+ ubifs_err("could not find an empty LEB");
+ ubifs_dump_lprops(c);
+ ubifs_dump_budg(c, &c->bi);
return lnum;
}
@@ -1218,7 +1217,7 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c)
}
mutex_unlock(&wbuf->io_mutex);
if (err < 0) {
- dbg_err("GC failed, error %d", err);
+ ubifs_err("GC failed, error %d", err);
if (err == -EAGAIN)
err = -EINVAL;
return err;
@@ -1472,7 +1471,7 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
len -= 1;
len = ALIGN(len + 1, c->min_io_size);
/* Atomically write the fixed LEB back again */
- err = ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN);
+ err = ubifs_leb_change(c, lnum, c->sbuf, len);
if (err)
goto out;
dbg_rcvry("inode %lu at %d:%d size %lld -> %lld",
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index b007637f0406..3a2da7e476e5 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -154,8 +154,7 @@ static int set_bud_lprops(struct ubifs_info *c, struct bud_entry *b)
/* Make sure the journal head points to the latest bud */
err = ubifs_wbuf_seek_nolock(&c->jheads[b->bud->jhead].wbuf,
- b->bud->lnum, c->leb_size - b->free,
- UBI_SHORTTERM);
+ b->bud->lnum, c->leb_size - b->free);
out:
ubifs_release_lprops(c);
@@ -686,7 +685,7 @@ out:
out_dump:
ubifs_err("bad node is at LEB %d:%d", lnum, snod->offs);
- dbg_dump_node(c, snod->node);
+ ubifs_dump_node(c, snod->node);
ubifs_scan_destroy(sleb);
return -EINVAL;
}
@@ -861,16 +860,16 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
* numbers.
*/
if (snod->type != UBIFS_CS_NODE) {
- dbg_err("first log node at LEB %d:%d is not CS node",
- lnum, offs);
+ ubifs_err("first log node at LEB %d:%d is not CS node",
+ lnum, offs);
goto out_dump;
}
if (le64_to_cpu(node->cmt_no) != c->cmt_no) {
- dbg_err("first CS node at LEB %d:%d has wrong "
- "commit number %llu expected %llu",
- lnum, offs,
- (unsigned long long)le64_to_cpu(node->cmt_no),
- c->cmt_no);
+ ubifs_err("first CS node at LEB %d:%d has wrong "
+ "commit number %llu expected %llu",
+ lnum, offs,
+ (unsigned long long)le64_to_cpu(node->cmt_no),
+ c->cmt_no);
goto out_dump;
}
@@ -892,7 +891,7 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
/* Make sure the first node sits at offset zero of the LEB */
if (snod->offs != 0) {
- dbg_err("first node is not at zero offset");
+ ubifs_err("first node is not at zero offset");
goto out_dump;
}
@@ -905,8 +904,8 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
}
if (snod->sqnum < c->cs_sqnum) {
- dbg_err("bad sqnum %llu, commit sqnum %llu",
- snod->sqnum, c->cs_sqnum);
+ ubifs_err("bad sqnum %llu, commit sqnum %llu",
+ snod->sqnum, c->cs_sqnum);
goto out_dump;
}
@@ -958,7 +957,7 @@ out:
out_dump:
ubifs_err("log error detected while replaying the log at LEB %d:%d",
lnum, offs + snod->offs);
- dbg_dump_node(c, snod->node);
+ ubifs_dump_node(c, snod->node);
ubifs_scan_destroy(sleb);
return -EINVAL;
}
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index 771f7fb6ce92..ef3d1ba6d992 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -130,7 +130,6 @@ static int create_default_filesystem(struct ubifs_info *c)
* orphan node.
*/
orph_lebs = UBIFS_MIN_ORPH_LEBS;
-#ifdef CONFIG_UBIFS_FS_DEBUG
if (c->leb_cnt - min_leb_cnt > 1)
/*
* For debugging purposes it is better to have at least 2
@@ -138,7 +137,6 @@ static int create_default_filesystem(struct ubifs_info *c)
* consolidations and would be stressed more.
*/
orph_lebs += 1;
-#endif
main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS - log_lebs;
main_lebs -= orph_lebs;
@@ -196,7 +194,7 @@ static int create_default_filesystem(struct ubifs_info *c)
sup->rp_size = cpu_to_le64(tmp64);
sup->ro_compat_version = cpu_to_le32(UBIFS_RO_COMPAT_VERSION);
- err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0, UBI_LONGTERM);
+ err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0);
kfree(sup);
if (err)
return err;
@@ -252,14 +250,13 @@ static int create_default_filesystem(struct ubifs_info *c)
mst->total_used = cpu_to_le64(UBIFS_INO_NODE_SZ);
- err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0,
- UBI_UNKNOWN);
+ err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0);
if (err) {
kfree(mst);
return err;
}
- err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1, 0,
- UBI_UNKNOWN);
+ err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1,
+ 0);
kfree(mst);
if (err)
return err;
@@ -282,8 +279,7 @@ static int create_default_filesystem(struct ubifs_info *c)
key_write_idx(c, &key, &br->key);
br->lnum = cpu_to_le32(main_first + DEFAULT_DATA_LEB);
br->len = cpu_to_le32(UBIFS_INO_NODE_SZ);
- err = ubifs_write_node(c, idx, tmp, main_first + DEFAULT_IDX_LEB, 0,
- UBI_UNKNOWN);
+ err = ubifs_write_node(c, idx, tmp, main_first + DEFAULT_IDX_LEB, 0);
kfree(idx);
if (err)
return err;
@@ -315,8 +311,7 @@ static int create_default_filesystem(struct ubifs_info *c)
ino->flags = cpu_to_le32(UBIFS_COMPR_FL);
err = ubifs_write_node(c, ino, UBIFS_INO_NODE_SZ,
- main_first + DEFAULT_DATA_LEB, 0,
- UBI_UNKNOWN);
+ main_first + DEFAULT_DATA_LEB, 0);
kfree(ino);
if (err)
return err;
@@ -335,8 +330,7 @@ static int create_default_filesystem(struct ubifs_info *c)
return -ENOMEM;
cs->ch.node_type = UBIFS_CS_NODE;
- err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM,
- 0, UBI_UNKNOWN);
+ err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM, 0);
kfree(cs);
ubifs_msg("default file-system created");
@@ -475,7 +469,7 @@ static int validate_sb(struct ubifs_info *c, struct ubifs_sb_node *sup)
failed:
ubifs_err("bad superblock, error %d", err);
- dbg_dump_node(c, sup);
+ ubifs_dump_node(c, sup);
return -EINVAL;
}
@@ -518,7 +512,7 @@ int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup)
int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size);
ubifs_prepare_node(c, sup, UBIFS_SB_NODE_SZ, 1);
- return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len, UBI_LONGTERM);
+ return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len);
}
/**
@@ -691,7 +685,7 @@ static int fixup_leb(struct ubifs_info *c, int lnum, int len)
if (err)
return err;
- return ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN);
+ return ubifs_leb_change(c, lnum, c->sbuf, len);
}
/**
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
index 37383e8011b1..7c40e6025fd6 100644
--- a/fs/ubifs/scan.c
+++ b/fs/ubifs/scan.c
@@ -101,7 +101,7 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
if (!quiet) {
ubifs_err("bad pad node at LEB %d:%d",
lnum, offs);
- dbg_dump_node(c, pad);
+ ubifs_dump_node(c, pad);
}
return SCANNED_A_BAD_PAD_NODE;
}
@@ -109,8 +109,8 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
/* Make the node pads to 8-byte boundary */
if ((node_len + pad_len) & 7) {
if (!quiet)
- dbg_err("bad padding length %d - %d",
- offs, offs + node_len + pad_len);
+ ubifs_err("bad padding length %d - %d",
+ offs, offs + node_len + pad_len);
return SCANNED_A_BAD_PAD_NODE;
}
@@ -245,7 +245,7 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
len = c->leb_size - offs;
if (len > 8192)
len = 8192;
- dbg_err("first %d bytes from LEB %d:%d", len, lnum, offs);
+ ubifs_err("first %d bytes from LEB %d:%d", len, lnum, offs);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
}
@@ -300,16 +300,16 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
switch (ret) {
case SCANNED_GARBAGE:
- dbg_err("garbage");
+ ubifs_err("garbage");
goto corrupted;
case SCANNED_A_NODE:
break;
case SCANNED_A_CORRUPT_NODE:
case SCANNED_A_BAD_PAD_NODE:
- dbg_err("bad node");
+ ubifs_err("bad node");
goto corrupted;
default:
- dbg_err("unknown");
+ ubifs_err("unknown");
err = -EINVAL;
goto error;
}
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 76e4e0566ad6..001acccac0d6 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -246,8 +246,8 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
out_invalid:
ubifs_err("inode %lu validation failed, error %d", inode->i_ino, err);
- dbg_dump_node(c, ino);
- dbg_dump_inode(c, inode);
+ ubifs_dump_node(c, ino);
+ ubifs_dump_inode(c, inode);
err = -EINVAL;
out_ino:
kfree(ino);
@@ -668,8 +668,8 @@ static int init_constants_sb(struct ubifs_info *c)
tmp = UBIFS_CS_NODE_SZ + UBIFS_REF_NODE_SZ * c->jhead_cnt;
tmp = ALIGN(tmp, c->min_io_size);
if (tmp > c->leb_size) {
- dbg_err("too small LEB size %d, at least %d needed",
- c->leb_size, tmp);
+ ubifs_err("too small LEB size %d, at least %d needed",
+ c->leb_size, tmp);
return -EINVAL;
}
@@ -683,8 +683,8 @@ static int init_constants_sb(struct ubifs_info *c)
tmp /= c->leb_size;
tmp += 1;
if (c->log_lebs < tmp) {
- dbg_err("too small log %d LEBs, required min. %d LEBs",
- c->log_lebs, tmp);
+ ubifs_err("too small log %d LEBs, required min. %d LEBs",
+ c->log_lebs, tmp);
return -EINVAL;
}
@@ -813,13 +813,10 @@ static int alloc_wbufs(struct ubifs_info *c)
c->jheads[i].grouped = 1;
}
- c->jheads[BASEHD].wbuf.dtype = UBI_SHORTTERM;
/*
- * Garbage Collector head likely contains long-term data and
- * does not need to be synchronized by timer. Also GC head nodes are
- * not grouped.
+ * Garbage Collector head does not need to be synchronized by timer.
+ * Also GC head nodes are not grouped.
*/
- c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM;
c->jheads[GCHD].wbuf.no_timer = 1;
c->jheads[GCHD].grouped = 0;
@@ -863,7 +860,7 @@ static void free_orphans(struct ubifs_info *c)
orph = list_entry(c->orph_list.next, struct ubifs_orphan, list);
list_del(&orph->list);
kfree(orph);
- dbg_err("orphan list not empty at unmount");
+ ubifs_err("orphan list not empty at unmount");
}
vfree(c->orph_buf);
@@ -1147,8 +1144,8 @@ static int check_free_space(struct ubifs_info *c)
ubifs_assert(c->dark_wm > 0);
if (c->lst.total_free + c->lst.total_dirty < c->dark_wm) {
ubifs_err("insufficient free space to mount in R/W mode");
- dbg_dump_budg(c, &c->bi);
- dbg_dump_lprops(c);
+ ubifs_dump_budg(c, &c->bi);
+ ubifs_dump_lprops(c);
return -ENOSPC;
}
return 0;
@@ -1301,7 +1298,7 @@ static int mount_ubifs(struct ubifs_info *c)
if (!c->ro_mount && c->space_fixup) {
err = ubifs_fixup_free_space(c);
if (err)
- goto out_master;
+ goto out_lpt;
}
if (!c->ro_mount) {
@@ -2126,8 +2123,8 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
*/
ubi = open_ubi(name, UBI_READONLY);
if (IS_ERR(ubi)) {
- dbg_err("cannot open \"%s\", error %d",
- name, (int)PTR_ERR(ubi));
+ ubifs_err("cannot open \"%s\", error %d",
+ name, (int)PTR_ERR(ubi));
return ERR_CAST(ubi);
}
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 16ad84d8402f..349f31a30f40 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -339,8 +339,8 @@ static int lnc_add(struct ubifs_info *c, struct ubifs_zbranch *zbr,
err = ubifs_validate_entry(c, dent);
if (err) {
- dbg_dump_stack();
- dbg_dump_node(c, dent);
+ dump_stack();
+ ubifs_dump_node(c, dent);
return err;
}
@@ -372,8 +372,8 @@ static int lnc_add_directly(struct ubifs_info *c, struct ubifs_zbranch *zbr,
err = ubifs_validate_entry(c, node);
if (err) {
- dbg_dump_stack();
- dbg_dump_node(c, node);
+ dump_stack();
+ ubifs_dump_node(c, node);
return err;
}
@@ -1733,8 +1733,8 @@ out_err:
err = -EINVAL;
out:
ubifs_err("bad node at LEB %d:%d", zbr->lnum, zbr->offs);
- dbg_dump_node(c, buf);
- dbg_dump_stack();
+ ubifs_dump_node(c, buf);
+ dump_stack();
return err;
}
@@ -1775,7 +1775,7 @@ int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu)
if (err && err != -EBADMSG) {
ubifs_err("failed to read from LEB %d:%d, error %d",
lnum, offs, err);
- dbg_dump_stack();
+ dump_stack();
dbg_tnck(&bu->key, "key ");
return err;
}
@@ -2361,7 +2361,7 @@ int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key,
* by passing 'ubifs_tnc_remove_nm()' the same key but
* an unmatchable name.
*/
- struct qstr noname = { .len = 0, .name = "" };
+ struct qstr noname = { .name = "" };
err = dbg_check_tnc(c, 0);
mutex_unlock(&c->tnc_mutex);
@@ -2403,7 +2403,7 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
err = ubifs_add_dirt(c, zbr->lnum, zbr->len);
if (err) {
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
return err;
}
@@ -2649,7 +2649,7 @@ int ubifs_tnc_remove_range(struct ubifs_info *c, union ubifs_key *from_key,
err = ubifs_add_dirt(c, znode->zbranch[i].lnum,
znode->zbranch[i].len);
if (err) {
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
goto out_unlock;
}
dbg_tnck(key, "removing key ");
@@ -3275,8 +3275,6 @@ out_unlock:
return err;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
-
/**
* dbg_check_inode_size - check if inode size is correct.
* @c: UBIFS file-system description object
@@ -3335,13 +3333,11 @@ out_dump:
(unsigned long)inode->i_ino, size,
((loff_t)block) << UBIFS_BLOCK_SHIFT);
mutex_unlock(&c->tnc_mutex);
- dbg_dump_inode(c, inode);
- dbg_dump_stack();
+ ubifs_dump_inode(c, inode);
+ dump_stack();
return -EINVAL;
out_unlock:
mutex_unlock(&c->tnc_mutex);
return err;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
index 4c15f07a8bb2..523bbad69c0c 100644
--- a/fs/ubifs/tnc_commit.c
+++ b/fs/ubifs/tnc_commit.c
@@ -54,18 +54,16 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx,
br->len = cpu_to_le32(zbr->len);
if (!zbr->lnum || !zbr->len) {
ubifs_err("bad ref in znode");
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
if (zbr->znode)
- dbg_dump_znode(c, zbr->znode);
+ ubifs_dump_znode(c, zbr->znode);
}
}
ubifs_prepare_node(c, idx, len, 0);
-#ifdef CONFIG_UBIFS_FS_DEBUG
znode->lnum = lnum;
znode->offs = offs;
znode->len = len;
-#endif
err = insert_old_idx_znode(c, znode);
@@ -322,8 +320,7 @@ static int layout_leb_in_gaps(struct ubifs_info *c, int *p)
0, 0, 0);
if (err)
return err;
- err = ubifs_leb_change(c, lnum, c->ileb_buf, c->ileb_len,
- UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum, c->ileb_buf, c->ileb_len);
if (err)
return err;
dbg_gc("LEB %d wrote %d index nodes", lnum, tot_written);
@@ -388,8 +385,8 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt)
* option which forces in-the-gaps is enabled.
*/
ubifs_warn("out of space");
- dbg_dump_budg(c, &c->bi);
- dbg_dump_lprops(c);
+ ubifs_dump_budg(c, &c->bi);
+ ubifs_dump_lprops(c);
}
/* Try to commit anyway */
err = 0;
@@ -456,11 +453,9 @@ static int layout_in_empty_space(struct ubifs_info *c)
offs = buf_offs + used;
-#ifdef CONFIG_UBIFS_FS_DEBUG
znode->lnum = lnum;
znode->offs = offs;
znode->len = len;
-#endif
/* Update the parent */
zp = znode->parent;
@@ -536,10 +531,8 @@ static int layout_in_empty_space(struct ubifs_info *c)
break;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
c->dbg->new_ihead_lnum = lnum;
c->dbg->new_ihead_offs = buf_offs;
-#endif
return 0;
}
@@ -864,9 +857,9 @@ static int write_index(struct ubifs_info *c)
br->len = cpu_to_le32(zbr->len);
if (!zbr->lnum || !zbr->len) {
ubifs_err("bad ref in znode");
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
if (zbr->znode)
- dbg_dump_znode(c, zbr->znode);
+ ubifs_dump_znode(c, zbr->znode);
}
}
len = ubifs_idx_node_sz(c, znode->child_cnt);
@@ -881,13 +874,11 @@ static int write_index(struct ubifs_info *c)
}
offs = buf_offs + used;
-#ifdef CONFIG_UBIFS_FS_DEBUG
if (lnum != znode->lnum || offs != znode->offs ||
len != znode->len) {
ubifs_err("inconsistent znode posn");
return -EINVAL;
}
-#endif
/* Grab some stuff from znode while we still can */
cnext = znode->cnext;
@@ -959,8 +950,7 @@ static int write_index(struct ubifs_info *c)
}
/* The buffer is full or there are no more znodes to do */
- err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs, blen,
- UBI_SHORTTERM);
+ err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs, blen);
if (err)
return err;
buf_offs += blen;
@@ -982,13 +972,11 @@ static int write_index(struct ubifs_info *c)
break;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
if (lnum != c->dbg->new_ihead_lnum ||
buf_offs != c->dbg->new_ihead_offs) {
ubifs_err("inconsistent ihead");
return -EINVAL;
}
-#endif
c->ihead_lnum = lnum;
c->ihead_offs = buf_offs;
diff --git a/fs/ubifs/tnc_misc.c b/fs/ubifs/tnc_misc.c
index dc28fe6ec07a..d38ac7f9654b 100644
--- a/fs/ubifs/tnc_misc.c
+++ b/fs/ubifs/tnc_misc.c
@@ -293,10 +293,10 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
lnum, offs, znode->level, znode->child_cnt);
if (znode->child_cnt > c->fanout || znode->level > UBIFS_MAX_LEVELS) {
- dbg_err("current fanout %d, branch count %d",
- c->fanout, znode->child_cnt);
- dbg_err("max levels %d, znode level %d",
- UBIFS_MAX_LEVELS, znode->level);
+ ubifs_err("current fanout %d, branch count %d",
+ c->fanout, znode->child_cnt);
+ ubifs_err("max levels %d, znode level %d",
+ UBIFS_MAX_LEVELS, znode->level);
err = 1;
goto out_dump;
}
@@ -316,7 +316,7 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
if (zbr->lnum < c->main_first ||
zbr->lnum >= c->leb_cnt || zbr->offs < 0 ||
zbr->offs + zbr->len > c->leb_size || zbr->offs & 7) {
- dbg_err("bad branch %d", i);
+ ubifs_err("bad branch %d", i);
err = 2;
goto out_dump;
}
@@ -340,19 +340,19 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
type = key_type(c, &zbr->key);
if (c->ranges[type].max_len == 0) {
if (zbr->len != c->ranges[type].len) {
- dbg_err("bad target node (type %d) length (%d)",
- type, zbr->len);
- dbg_err("have to be %d", c->ranges[type].len);
+ ubifs_err("bad target node (type %d) length (%d)",
+ type, zbr->len);
+ ubifs_err("have to be %d", c->ranges[type].len);
err = 4;
goto out_dump;
}
} else if (zbr->len < c->ranges[type].min_len ||
zbr->len > c->ranges[type].max_len) {
- dbg_err("bad target node (type %d) length (%d)",
- type, zbr->len);
- dbg_err("have to be in range of %d-%d",
- c->ranges[type].min_len,
- c->ranges[type].max_len);
+ ubifs_err("bad target node (type %d) length (%d)",
+ type, zbr->len);
+ ubifs_err("have to be in range of %d-%d",
+ c->ranges[type].min_len,
+ c->ranges[type].max_len);
err = 5;
goto out_dump;
}
@@ -370,13 +370,13 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
cmp = keys_cmp(c, key1, key2);
if (cmp > 0) {
- dbg_err("bad key order (keys %d and %d)", i, i + 1);
+ ubifs_err("bad key order (keys %d and %d)", i, i + 1);
err = 6;
goto out_dump;
} else if (cmp == 0 && !is_hash_key(c, key1)) {
/* These can only be keys with colliding hash */
- dbg_err("keys %d and %d are not hashed but equivalent",
- i, i + 1);
+ ubifs_err("keys %d and %d are not hashed but equivalent",
+ i, i + 1);
err = 7;
goto out_dump;
}
@@ -387,7 +387,7 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
out_dump:
ubifs_err("bad indexing node at LEB %d:%d, error %d", lnum, offs, err);
- dbg_dump_node(c, idx);
+ ubifs_dump_node(c, idx);
kfree(idx);
return -EINVAL;
}
@@ -486,7 +486,7 @@ int ubifs_tnc_read_node(struct ubifs_info *c, struct ubifs_zbranch *zbr,
zbr->lnum, zbr->offs);
dbg_tnck(key, "looked for key ");
dbg_tnck(&key1, "but found node's key ");
- dbg_dump_node(c, node);
+ ubifs_dump_node(c, node);
return -EINVAL;
}
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 93d59aceaaef..1e5a08623d11 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -650,8 +650,6 @@ typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c,
* @avail: number of bytes available in the write-buffer
* @used: number of used bytes in the write-buffer
* @size: write-buffer size (in [@c->min_io_size, @c->max_write_size] range)
- * @dtype: type of data stored in this LEB (%UBI_LONGTERM, %UBI_SHORTTERM,
- * %UBI_UNKNOWN)
* @jhead: journal head the mutex belongs to (note, needed only to shut lockdep
* up by 'mutex_lock_nested()).
* @sync_callback: write-buffer synchronization callback
@@ -685,7 +683,6 @@ struct ubifs_wbuf {
int avail;
int used;
int size;
- int dtype;
int jhead;
int (*sync_callback)(struct ubifs_info *c, int lnum, int free, int pad);
struct mutex io_mutex;
@@ -762,6 +759,9 @@ struct ubifs_zbranch {
* @offs: offset of the corresponding indexing node
* @len: length of the corresponding indexing node
* @zbranch: array of znode branches (@c->fanout elements)
+ *
+ * Note! The @lnum, @offs, and @len fields are not really needed - we have them
+ * only for internal consistency check. They could be removed to save some RAM.
*/
struct ubifs_znode {
struct ubifs_znode *parent;
@@ -772,9 +772,9 @@ struct ubifs_znode {
int child_cnt;
int iip;
int alt;
-#ifdef CONFIG_UBIFS_FS_DEBUG
- int lnum, offs, len;
-#endif
+ int lnum;
+ int offs;
+ int len;
struct ubifs_zbranch zbranch[];
};
@@ -1444,9 +1444,7 @@ struct ubifs_info {
struct rb_root size_tree;
struct ubifs_mount_opts mount_opts;
-#ifdef CONFIG_UBIFS_FS_DEBUG
struct ubifs_debug_info *dbg;
-#endif
};
extern struct list_head ubifs_infos;
@@ -1468,22 +1466,20 @@ void ubifs_ro_mode(struct ubifs_info *c, int err);
int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
int len, int even_ebadmsg);
int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
- int len, int dtype);
-int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
- int dtype);
+ int len);
+int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len);
int ubifs_leb_unmap(struct ubifs_info *c, int lnum);
-int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype);
+int ubifs_leb_map(struct ubifs_info *c, int lnum);
int ubifs_is_mapped(const struct ubifs_info *c, int lnum);
int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len);
-int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
- int dtype);
+int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs);
int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf);
int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
int lnum, int offs);
int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
int lnum, int offs);
int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum,
- int offs, int dtype);
+ int offs);
int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
int offs, int quiet, int must_chk_crc);
void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad);
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index 85b272268754..0f7139bdb2c2 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -298,7 +298,7 @@ int ubifs_setxattr(struct dentry *dentry, const char *name,
{
struct inode *inode, *host = dentry->d_inode;
struct ubifs_info *c = host->i_sb->s_fs_info;
- struct qstr nm = { .name = name, .len = strlen(name) };
+ struct qstr nm = QSTR_INIT(name, strlen(name));
struct ubifs_dent_node *xent;
union ubifs_key key;
int err, type;
@@ -361,7 +361,7 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
{
struct inode *inode, *host = dentry->d_inode;
struct ubifs_info *c = host->i_sb->s_fs_info;
- struct qstr nm = { .name = name, .len = strlen(name) };
+ struct qstr nm = QSTR_INIT(name, strlen(name));
struct ubifs_inode *ui;
struct ubifs_dent_node *xent;
union ubifs_key key;
@@ -399,8 +399,8 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
if (buf) {
/* If @buf is %NULL we are supposed to return the length */
if (ui->data_len > size) {
- dbg_err("buffer size %zd, xattr len %d",
- size, ui->data_len);
+ ubifs_err("buffer size %zd, xattr len %d",
+ size, ui->data_len);
err = -ERANGE;
goto out_iput;
}
@@ -524,7 +524,7 @@ int ubifs_removexattr(struct dentry *dentry, const char *name)
{
struct inode *inode, *host = dentry->d_inode;
struct ubifs_info *c = host->i_sb->s_fs_info;
- struct qstr nm = { .name = name, .len = strlen(name) };
+ struct qstr nm = QSTR_INIT(name, strlen(name));
struct ubifs_dent_node *xent;
union ubifs_key key;
int err;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 38de8f234b94..a165c66e3eef 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -1193,7 +1193,7 @@ static struct dentry *udf_get_parent(struct dentry *child)
{
struct kernel_lb_addr tloc;
struct inode *inode = NULL;
- struct qstr dotdot = {.name = "..", .len = 2};
+ struct qstr dotdot = QSTR_INIT("..", 2);
struct fileIdentDesc cfi;
struct udf_fileident_bh fibh;
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index ac8e279eccc6..302f340d0071 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -146,10 +146,7 @@ static struct dentry *ufs_fh_to_parent(struct super_block *sb, struct fid *fid,
static struct dentry *ufs_get_parent(struct dentry *child)
{
- struct qstr dot_dot = {
- .name = "..",
- .len = 2,
- };
+ struct qstr dot_dot = QSTR_INIT("..", 2);
ino_t ino;
ino = ufs_inode_by_name(child->d_inode, &dot_dot);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index f1c8ca60e824..b0d62820ada1 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -51,6 +51,37 @@ acpi_evaluate_reference(acpi_handle handle,
struct acpi_object_list *arguments,
struct acpi_handle_list *list);
+struct acpi_pld {
+ unsigned int revision:7; /* 0 */
+ unsigned int ignore_colour:1; /* 7 */
+ unsigned int colour:24; /* 8 */
+ unsigned int width:16; /* 32 */
+ unsigned int height:16; /* 48 */
+ unsigned int user_visible:1; /* 64 */
+ unsigned int dock:1; /* 65 */
+ unsigned int lid:1; /* 66 */
+ unsigned int panel:3; /* 67 */
+ unsigned int vertical_pos:2; /* 70 */
+ unsigned int horizontal_pos:2; /* 72 */
+ unsigned int shape:4; /* 74 */
+ unsigned int group_orientation:1; /* 78 */
+ unsigned int group_token:8; /* 79 */
+ unsigned int group_position:8; /* 87 */
+ unsigned int bay:1; /* 95 */
+ unsigned int ejectable:1; /* 96 */
+ unsigned int ospm_eject_required:1; /* 97 */
+ unsigned int cabinet_number:8; /* 98 */
+ unsigned int card_cage_number:8; /* 106 */
+ unsigned int reference:1; /* 114 */
+ unsigned int rotation:4; /* 115 */
+ unsigned int order:5; /* 119 */
+ unsigned int reserved:4; /* 124 */
+ unsigned int vertical_offset:16; /* 128 */
+ unsigned int horizontal_offset:16; /* 144 */
+} __attribute__((__packed__));
+
+acpi_status
+acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld *pld);
#ifdef CONFIG_ACPI
#include <linux/proc_fs.h>
@@ -407,6 +438,11 @@ static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
}
#endif
+#else /* CONFIG_ACPI */
+
+static int register_acpi_bus_type(struct acpi_bus_type *bus) { return 0; }
+static int unregister_acpi_bus_type(struct acpi_bus_type *bus) { return 0; }
+
#endif /* CONFIG_ACPI */
#endif /*__ACPI_BUS_H__*/
diff --git a/include/asm-generic/pci-bridge.h b/include/asm-generic/pci-bridge.h
index a5b5d5a89a4f..20db2e5a0a69 100644
--- a/include/asm-generic/pci-bridge.h
+++ b/include/asm-generic/pci-bridge.h
@@ -30,6 +30,12 @@ enum {
PCI_ENABLE_PROC_DOMAINS = 0x00000010,
/* ... except for domain 0 */
PCI_COMPAT_DOMAIN_0 = 0x00000020,
+
+ /* PCIe downstream ports are bridges that normally lead to only a
+ * device 0, but if this is set, we scan all possible devices, not
+ * just device 0.
+ */
+ PCI_SCAN_ALL_PCIE_DEVS = 0x00000040,
};
#ifdef CONFIG_PCI
diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
index 5e5e3865f1ed..8ed67779fc09 100644
--- a/include/asm-generic/siginfo.h
+++ b/include/asm-generic/siginfo.h
@@ -98,9 +98,18 @@ typedef struct siginfo {
__ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
+
+ /* SIGSYS */
+ struct {
+ void __user *_call_addr; /* calling user insn */
+ int _syscall; /* triggering system call number */
+ unsigned int _arch; /* AUDIT_ARCH_* of syscall */
+ } _sigsys;
} _sifields;
} __ARCH_SI_ATTRIBUTES siginfo_t;
+/* If the arch shares siginfo, then it has SIGSYS. */
+#define __ARCH_SIGSYS
#endif
/*
@@ -124,6 +133,11 @@ typedef struct siginfo {
#define si_addr_lsb _sifields._sigfault._addr_lsb
#define si_band _sifields._sigpoll._band
#define si_fd _sifields._sigpoll._fd
+#ifdef __ARCH_SIGSYS
+#define si_call_addr _sifields._sigsys._call_addr
+#define si_syscall _sifields._sigsys._syscall
+#define si_arch _sifields._sigsys._arch
+#endif
#ifdef __KERNEL__
#define __SI_MASK 0xffff0000u
@@ -134,6 +148,7 @@ typedef struct siginfo {
#define __SI_CHLD (4 << 16)
#define __SI_RT (5 << 16)
#define __SI_MESGQ (6 << 16)
+#define __SI_SYS (7 << 16)
#define __SI_CODE(T,N) ((T) | ((N) & 0xffff))
#else
#define __SI_KILL 0
@@ -143,6 +158,7 @@ typedef struct siginfo {
#define __SI_CHLD 0
#define __SI_RT 0
#define __SI_MESGQ 0
+#define __SI_SYS 0
#define __SI_CODE(T,N) (N)
#endif
@@ -240,6 +256,12 @@ typedef struct siginfo {
#define NSIGPOLL 6
/*
+ * SIGSYS si_codes
+ */
+#define SYS_SECCOMP (__SI_SYS|1) /* seccomp triggered */
+#define NSIGSYS 1
+
+/*
* sigevent definitions
*
* It seems likely that SIGEV_THREAD will have to be handled from
diff --git a/include/asm-generic/syscall.h b/include/asm-generic/syscall.h
index 5c122ae6bfa6..5b09392db673 100644
--- a/include/asm-generic/syscall.h
+++ b/include/asm-generic/syscall.h
@@ -142,4 +142,18 @@ void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
unsigned int i, unsigned int n,
const unsigned long *args);
+/**
+ * syscall_get_arch - return the AUDIT_ARCH for the current system call
+ * @task: task of interest, must be in system call entry tracing
+ * @regs: task_pt_regs() of @task
+ *
+ * Returns the AUDIT_ARCH_* based on the system call convention in use.
+ *
+ * It's only valid to call this when @task is stopped on entry to a system
+ * call, due to %TIF_SYSCALL_TRACE, %TIF_SYSCALL_AUDIT, or %TIF_SECCOMP.
+ *
+ * Architectures which permit CONFIG_HAVE_ARCH_SECCOMP_FILTER must
+ * provide an implementation of this.
+ */
+int syscall_get_arch(struct task_struct *task, struct pt_regs *regs);
#endif /* _ASM_SYSCALL_H */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8aeadf6b553a..4e2e1cc505ab 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -486,8 +486,8 @@
CPU_DISCARD(init.data) \
MEM_DISCARD(init.data) \
KERNEL_CTORS() \
- *(.init.rodata) \
MCOUNT_REC() \
+ *(.init.rodata) \
FTRACE_EVENTS() \
TRACE_SYSCALLS() \
DEV_DISCARD(init.rodata) \
diff --git a/include/keys/keyring-type.h b/include/keys/keyring-type.h
index 843f872a4b63..cf49159b0e3a 100644
--- a/include/keys/keyring-type.h
+++ b/include/keys/keyring-type.h
@@ -24,7 +24,7 @@ struct keyring_list {
unsigned short maxkeys; /* max keys this list can hold */
unsigned short nkeys; /* number of keys currently held */
unsigned short delkey; /* key to be unlinked by RCU */
- struct key *keys[0];
+ struct key __rcu *keys[0];
};
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index b738f2dc38d9..39737839ce29 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -167,7 +167,6 @@ header-y += if_arp.h
header-y += if_bonding.h
header-y += if_bridge.h
header-y += if_cablemodem.h
-header-y += if_ec.h
header-y += if_eql.h
header-y += if_ether.h
header-y += if_fc.h
@@ -239,6 +238,7 @@ header-y += map_to_7segment.h
header-y += matroxfb.h
header-y += mdio.h
header-y += media.h
+header-y += mei.h
header-y += mempolicy.h
header-y += meye.h
header-y += mii.h
@@ -331,6 +331,7 @@ header-y += scc.h
header-y += sched.h
header-y += screen_info.h
header-y += sdla.h
+header-y += seccomp.h
header-y += securebits.h
header-y += selinux_netlink.h
header-y += sem.h
@@ -380,6 +381,7 @@ header-y += unistd.h
header-y += usbdevice_fs.h
header-y += utime.h
header-y += utsname.h
+header-y += uuid.h
header-y += uvcvideo.h
header-y += v4l2-mediabus.h
header-y += v4l2-subdev.h
diff --git a/include/linux/alarmtimer.h b/include/linux/alarmtimer.h
index 975009e1cbe6..96c5c249b086 100644
--- a/include/linux/alarmtimer.h
+++ b/include/linux/alarmtimer.h
@@ -76,4 +76,7 @@ static inline int alarmtimer_callback_running(struct alarm *timer)
}
+/* Provide way to access the rtc device being used by alarmtimers */
+struct rtc_device *alarmtimer_get_rtcdev(void);
+
#endif
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
index 8d54f79457ba..d36417158d8f 100644
--- a/include/linux/amba/bus.h
+++ b/include/linux/amba/bus.h
@@ -63,6 +63,14 @@ struct amba_device *amba_device_alloc(const char *, resource_size_t, size_t);
void amba_device_put(struct amba_device *);
int amba_device_add(struct amba_device *, struct resource *);
int amba_device_register(struct amba_device *, struct resource *);
+struct amba_device *amba_apb_device_add(struct device *parent, const char *name,
+ resource_size_t base, size_t size,
+ int irq1, int irq2, void *pdata,
+ unsigned int periphid);
+struct amba_device *amba_ahb_device_add(struct device *parent, const char *name,
+ resource_size_t base, size_t size,
+ int irq1, int irq2, void *pdata,
+ unsigned int periphid);
void amba_device_unregister(struct amba_device *);
struct amba_device *amba_find_device(const char *, struct device *, unsigned int, unsigned int);
int amba_request_regions(struct amba_device *, const char *);
diff --git a/include/linux/audit.h b/include/linux/audit.h
index ed3ef1972496..22f292a917a3 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -463,7 +463,7 @@ extern void audit_putname(const char *name);
extern void __audit_inode(const char *name, const struct dentry *dentry);
extern void __audit_inode_child(const struct dentry *dentry,
const struct inode *parent);
-extern void __audit_seccomp(unsigned long syscall);
+extern void __audit_seccomp(unsigned long syscall, long signr, int code);
extern void __audit_ptrace(struct task_struct *t);
static inline int audit_dummy_context(void)
@@ -508,10 +508,10 @@ static inline void audit_inode_child(const struct dentry *dentry,
}
void audit_core_dumps(long signr);
-static inline void audit_seccomp(unsigned long syscall)
+static inline void audit_seccomp(unsigned long syscall, long signr, int code)
{
if (unlikely(!audit_dummy_context()))
- __audit_seccomp(syscall);
+ __audit_seccomp(syscall, signr, code);
}
static inline void audit_ptrace(struct task_struct *t)
@@ -634,7 +634,7 @@ extern int audit_signals;
#define audit_inode(n,d) do { (void)(d); } while (0)
#define audit_inode_child(i,p) do { ; } while (0)
#define audit_core_dumps(i) do { ; } while (0)
-#define audit_seccomp(i) do { ; } while (0)
+#define audit_seccomp(i,s,c) do { ; } while (0)
#define auditsc_get_stamp(c,t,s) (0)
#define audit_get_loginuid(t) (-1)
#define audit_get_sessionid(t) (-1)
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 5af9a075498f..98bb2901d7b7 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -139,6 +139,7 @@ struct bcma_device {
u8 core_unit;
u32 addr;
+ u32 addr1;
u32 wrap;
void __iomem *io_addr;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 2aa24664a5b5..4d4ac24a263e 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1,9 +1,10 @@
#ifndef _LINUX_BLKDEV_H
#define _LINUX_BLKDEV_H
+#include <linux/sched.h>
+
#ifdef CONFIG_BLOCK
-#include <linux/sched.h>
#include <linux/major.h>
#include <linux/genhd.h>
#include <linux/list.h>
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 12d52dedb229..c398cff3dab7 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -360,8 +360,11 @@ struct cpu_vfs_cap_data {
#define CAP_WAKE_ALARM 35
+/* Allow preventing system suspends while epoll events are pending */
-#define CAP_LAST_CAP CAP_WAKE_ALARM
+#define CAP_EPOLLWAKEUP 36
+
+#define CAP_LAST_CAP CAP_EPOLLWAKEUP
#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 5a85b3415c1b..d3f5fba2c159 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -16,6 +16,7 @@
#include <linux/prio_heap.h>
#include <linux/rwsem.h>
#include <linux/idr.h>
+#include <linux/workqueue.h>
#ifdef CONFIG_CGROUPS
@@ -76,12 +77,16 @@ struct cgroup_subsys_state {
unsigned long flags;
/* ID for this css, if possible */
struct css_id __rcu *id;
+
+ /* Used to put @cgroup->dentry on the last css_put() */
+ struct work_struct dput_work;
};
/* bits in struct cgroup_subsys_state flags field */
enum {
CSS_ROOT, /* This CSS is the root of the subsystem */
CSS_REMOVED, /* This CSS is dead */
+ CSS_CLEAR_CSS_REFS, /* @ss->__DEPRECATED_clear_css_refs */
};
/* Caller must verify that the css is not for root cgroup */
@@ -115,16 +120,12 @@ static inline bool css_is_removed(struct cgroup_subsys_state *css)
* the css has been destroyed.
*/
+extern bool __css_tryget(struct cgroup_subsys_state *css);
static inline bool css_tryget(struct cgroup_subsys_state *css)
{
if (test_bit(CSS_ROOT, &css->flags))
return true;
- while (!atomic_inc_not_zero(&css->refcnt)) {
- if (test_bit(CSS_REMOVED, &css->flags))
- return false;
- cpu_relax();
- }
- return true;
+ return __css_tryget(css);
}
/*
@@ -132,11 +133,11 @@ static inline bool css_tryget(struct cgroup_subsys_state *css)
* css_get() or css_tryget()
*/
-extern void __css_put(struct cgroup_subsys_state *css, int count);
+extern void __css_put(struct cgroup_subsys_state *css);
static inline void css_put(struct cgroup_subsys_state *css)
{
if (!test_bit(CSS_ROOT, &css->flags))
- __css_put(css, 1);
+ __css_put(css);
}
/* bits in struct cgroup flags field */
@@ -175,6 +176,7 @@ struct cgroup {
*/
struct list_head sibling; /* my parent's children */
struct list_head children; /* my children */
+ struct list_head files; /* my files */
struct cgroup *parent; /* my parent */
struct dentry __rcu *dentry; /* cgroup fs entry, RCU protected */
@@ -191,6 +193,9 @@ struct cgroup {
*/
struct list_head css_sets;
+ struct list_head allcg_node; /* cgroupfs_root->allcg_list */
+ struct list_head cft_q_node; /* used during cftype add/rm */
+
/*
* Linked list running through all cgroups that can
* potentially be reaped by the release agent. Protected by
@@ -275,11 +280,17 @@ struct cgroup_map_cb {
* - the 'cftype' of the file is file->f_dentry->d_fsdata
*/
-#define MAX_CFTYPE_NAME 64
+/* cftype->flags */
+#define CFTYPE_ONLY_ON_ROOT (1U << 0) /* only create on root cg */
+#define CFTYPE_NOT_ON_ROOT (1U << 1) /* don't create onp root cg */
+
+#define MAX_CFTYPE_NAME 64
+
struct cftype {
/*
* By convention, the name should begin with the name of the
- * subsystem, followed by a period
+ * subsystem, followed by a period. Zero length string indicates
+ * end of cftype array.
*/
char name[MAX_CFTYPE_NAME];
int private;
@@ -295,6 +306,9 @@ struct cftype {
*/
size_t max_write_len;
+ /* CFTYPE_* flags */
+ unsigned int flags;
+
int (*open)(struct inode *inode, struct file *file);
ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft,
struct file *file,
@@ -373,6 +387,16 @@ struct cftype {
struct eventfd_ctx *eventfd);
};
+/*
+ * cftype_sets describe cftypes belonging to a subsystem and are chained at
+ * cgroup_subsys->cftsets. Each cftset points to an array of cftypes
+ * terminated by zero length name.
+ */
+struct cftype_set {
+ struct list_head node; /* chained at subsys->cftsets */
+ const struct cftype *cfts;
+};
+
struct cgroup_scanner {
struct cgroup *cg;
int (*test_task)(struct task_struct *p, struct cgroup_scanner *scan);
@@ -382,21 +406,8 @@ struct cgroup_scanner {
void *data;
};
-/*
- * Add a new file to the given cgroup directory. Should only be
- * called by subsystems from within a populate() method
- */
-int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys,
- const struct cftype *cft);
-
-/*
- * Add a set of new files to the given cgroup directory. Should
- * only be called by subsystems from within a populate() method
- */
-int cgroup_add_files(struct cgroup *cgrp,
- struct cgroup_subsys *subsys,
- const struct cftype cft[],
- int count);
+int cgroup_add_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts);
+int cgroup_rm_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts);
int cgroup_is_removed(const struct cgroup *cgrp);
@@ -461,7 +472,6 @@ struct cgroup_subsys {
void (*fork)(struct task_struct *task);
void (*exit)(struct cgroup *cgrp, struct cgroup *old_cgrp,
struct task_struct *task);
- int (*populate)(struct cgroup_subsys *ss, struct cgroup *cgrp);
void (*post_clone)(struct cgroup *cgrp);
void (*bind)(struct cgroup *root);
@@ -474,6 +484,18 @@ struct cgroup_subsys {
* (not available in early_init time.)
*/
bool use_id;
+
+ /*
+ * If %true, cgroup removal will try to clear css refs by retrying
+ * ss->pre_destroy() until there's no css ref left. This behavior
+ * is strictly for backward compatibility and will be removed as
+ * soon as the current user (memcg) is updated.
+ *
+ * If %false, ss->pre_destroy() can't fail and cgroup removal won't
+ * wait for css refs to drop to zero before proceeding.
+ */
+ bool __DEPRECATED_clear_css_refs;
+
#define MAX_CGROUP_TYPE_NAMELEN 32
const char *name;
@@ -500,6 +522,13 @@ struct cgroup_subsys {
struct idr idr;
spinlock_t id_lock;
+ /* list of cftype_sets */
+ struct list_head cftsets;
+
+ /* base cftypes, automatically [de]registered with subsys itself */
+ struct cftype *base_cftypes;
+ struct cftype_set base_cftset;
+
/* should be defined only by modular subsystems */
struct module *module;
};
diff --git a/include/linux/clk.h b/include/linux/clk.h
index b0252726df61..70cf722ac3af 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -101,6 +101,26 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);
struct clk *clk_get(struct device *dev, const char *id);
/**
+ * devm_clk_get - lookup and obtain a managed reference to a clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock comsumer ID
+ *
+ * Returns a struct clk corresponding to the clock producer, or
+ * valid IS_ERR() condition containing errno. The implementation
+ * uses @dev and @id to determine the clock consumer, and thereby
+ * the clock producer. (IOW, @id may be identical strings, but
+ * clk_get may return different clock producers depending on @dev.)
+ *
+ * Drivers must assume that the clock source is not enabled.
+ *
+ * devm_clk_get should not be called from within interrupt context.
+ *
+ * The clock will automatically be freed when the device is unbound
+ * from the bus.
+ */
+struct clk *devm_clk_get(struct device *dev, const char *id);
+
+/**
* clk_prepare - prepare a clock source
* @clk: clock source
*
@@ -206,6 +226,18 @@ unsigned long clk_get_rate(struct clk *clk);
*/
void clk_put(struct clk *clk);
+/**
+ * devm_clk_put - "free" a managed clock source
+ * @dev: device used to acuqire the clock
+ * @clk: clock source acquired with devm_clk_get()
+ *
+ * Note: drivers must ensure that all clk_enable calls made on this
+ * clock source are balanced by clk_disable calls prior to calling
+ * this function.
+ *
+ * clk_put should not be called from within interrupt context.
+ */
+void devm_clk_put(struct device *dev, struct clk *clk);
/*
* The remaining APIs are optional for machine class support.
diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h
index d9a4fd028c9d..a6a6f603103b 100644
--- a/include/linux/clkdev.h
+++ b/include/linux/clkdev.h
@@ -40,4 +40,7 @@ void clkdev_drop(struct clk_lookup *cl);
void clkdev_add_table(struct clk_lookup *, size_t);
int clk_add_alias(const char *, const char *, char *, struct device *);
+int clk_register_clkdev(struct clk *, const char *, const char *, ...);
+int clk_register_clkdevs(struct clk *, struct clk_lookup *, size_t);
+
#endif
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index ee28844ae68e..7230bb59a06f 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -36,8 +36,6 @@ extern void cpu_remove_dev_attr(struct device_attribute *attr);
extern int cpu_add_dev_attr_group(struct attribute_group *attrs);
extern void cpu_remove_dev_attr_group(struct attribute_group *attrs);
-extern int sched_create_sysfs_power_savings_entries(struct device *dev);
-
#ifdef CONFIG_HOTPLUG_CPU
extern void unregister_cpu(struct cpu *cpu);
extern ssize_t arch_cpu_probe(const char *, size_t);
diff --git a/include/linux/cs5535.h b/include/linux/cs5535.h
index c077aec3a6ff..cfe83239d7f0 100644
--- a/include/linux/cs5535.h
+++ b/include/linux/cs5535.h
@@ -95,6 +95,7 @@ static inline int cs5535_pic_unreqz_select_high(unsigned int group,
/* CS5536_PM1_STS bits */
#define CS5536_WAK_FLAG (1 << 15)
+#define CS5536_RTC_FLAG (1 << 10)
#define CS5536_PWRBTN_FLAG (1 << 8)
/* CS5536_PM1_EN bits */
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 7e11f1418203..094789ff3e9f 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -25,6 +25,13 @@ struct vfsmount;
#define IS_ROOT(x) ((x) == (x)->d_parent)
+/* The hash is always the low bits of hash_len */
+#ifdef __LITTLE_ENDIAN
+ #define HASH_LEN_DECLARE u32 hash; u32 len;
+#else
+ #define HASH_LEN_DECLARE u32 len; u32 hash;
+#endif
+
/*
* "quick string" -- eases parameter passing, but more importantly
* saves "metadata" about the string (ie length and the hash).
@@ -33,11 +40,19 @@ struct vfsmount;
* dentry.
*/
struct qstr {
- unsigned int hash;
- unsigned int len;
+ union {
+ struct {
+ HASH_LEN_DECLARE;
+ };
+ u64 hash_len;
+ };
const unsigned char *name;
};
+#define QSTR_INIT(n,l) { { { .len = l } }, .name = n }
+#define hashlen_hash(hashlen) ((u32) (hashlen))
+#define hashlen_len(hashlen) ((u32)((hashlen) >> 32))
+
struct dentry_stat_t {
int nr_dentry;
int nr_unused;
@@ -282,7 +297,7 @@ extern struct dentry *d_hash_and_lookup(struct dentry *, struct qstr *);
extern struct dentry *__d_lookup(struct dentry *, struct qstr *);
extern struct dentry *__d_lookup_rcu(const struct dentry *parent,
const struct qstr *name,
- unsigned *seq, struct inode **inode);
+ unsigned *seq, struct inode *inode);
/**
* __d_rcu_to_refcount - take a refcount on dentry if sequence check is ok
diff --git a/include/linux/device.h b/include/linux/device.h
index 5ad17cccdd71..e04f5776f6d0 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -23,6 +23,7 @@
#include <linux/mutex.h>
#include <linux/pm.h>
#include <linux/atomic.h>
+#include <linux/ratelimit.h>
#include <asm/device.h>
struct device;
@@ -502,7 +503,10 @@ ssize_t device_store_int(struct device *dev, struct device_attribute *attr,
{ __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
#define DEVICE_INT_ATTR(_name, _mode, _var) \
struct dev_ext_attribute dev_attr_##_name = \
- { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
+ { __ATTR(_name, _mode, device_show_int, device_store_int), &(_var) }
+#define DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \
+ struct device_attribute dev_attr_##_name = \
+ __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store)
extern int device_create_file(struct device *device,
const struct device_attribute *entry);
@@ -541,6 +545,8 @@ extern void *devres_remove(struct device *dev, dr_release_t release,
dr_match_t match, void *match_data);
extern int devres_destroy(struct device *dev, dr_release_t release,
dr_match_t match, void *match_data);
+extern int devres_release(struct device *dev, dr_release_t release,
+ dr_match_t match, void *match_data);
/* devres group */
extern void * __must_check devres_open_group(struct device *dev, void *id,
@@ -931,6 +937,32 @@ int _dev_info(const struct device *dev, const char *fmt, ...)
#endif
+#define dev_level_ratelimited(dev_level, dev, fmt, ...) \
+do { \
+ static DEFINE_RATELIMIT_STATE(_rs, \
+ DEFAULT_RATELIMIT_INTERVAL, \
+ DEFAULT_RATELIMIT_BURST); \
+ if (__ratelimit(&_rs)) \
+ dev_level(dev, fmt, ##__VA_ARGS__); \
+} while (0)
+
+#define dev_emerg_ratelimited(dev, fmt, ...) \
+ dev_level_ratelimited(dev_emerg, dev, fmt, ##__VA_ARGS__)
+#define dev_alert_ratelimited(dev, fmt, ...) \
+ dev_level_ratelimited(dev_alert, dev, fmt, ##__VA_ARGS__)
+#define dev_crit_ratelimited(dev, fmt, ...) \
+ dev_level_ratelimited(dev_crit, dev, fmt, ##__VA_ARGS__)
+#define dev_err_ratelimited(dev, fmt, ...) \
+ dev_level_ratelimited(dev_err, dev, fmt, ##__VA_ARGS__)
+#define dev_warn_ratelimited(dev, fmt, ...) \
+ dev_level_ratelimited(dev_warn, dev, fmt, ##__VA_ARGS__)
+#define dev_notice_ratelimited(dev, fmt, ...) \
+ dev_level_ratelimited(dev_notice, dev, fmt, ##__VA_ARGS__)
+#define dev_info_ratelimited(dev, fmt, ...) \
+ dev_level_ratelimited(dev_info, dev, fmt, ##__VA_ARGS__)
+#define dev_dbg_ratelimited(dev, fmt, ...) \
+ dev_level_ratelimited(dev_dbg, dev, fmt, ##__VA_ARGS__)
+
/*
* Stupid hackaround for existing uses of non-printk uses dev_info
*
diff --git a/include/linux/dlm.h b/include/linux/dlm.h
index 6c7f6e9546c7..520152411cd1 100644
--- a/include/linux/dlm.h
+++ b/include/linux/dlm.h
@@ -67,7 +67,6 @@ struct dlm_lksb {
/* dlm_new_lockspace() flags */
-#define DLM_LSFL_NODIR 0x00000001
#define DLM_LSFL_TIMEWARN 0x00000002
#define DLM_LSFL_FS 0x00000004
#define DLM_LSFL_NEWEXCL 0x00000008
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index 731a60975101..b029d1aa2d12 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -114,91 +114,6 @@ struct irte {
};
};
-#ifdef CONFIG_IRQ_REMAP
-extern int intr_remapping_enabled;
-extern int intr_remapping_supported(void);
-extern int enable_intr_remapping(void);
-extern void disable_intr_remapping(void);
-extern int reenable_intr_remapping(int);
-
-extern int get_irte(int irq, struct irte *entry);
-extern int modify_irte(int irq, struct irte *irte_modified);
-extern int alloc_irte(struct intel_iommu *iommu, int irq, u16 count);
-extern int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index,
- u16 sub_handle);
-extern int map_irq_to_irte_handle(int irq, u16 *sub_handle);
-extern int free_irte(int irq);
-
-extern struct intel_iommu *map_dev_to_ir(struct pci_dev *dev);
-extern struct intel_iommu *map_ioapic_to_ir(int apic);
-extern struct intel_iommu *map_hpet_to_ir(u8 id);
-extern int set_ioapic_sid(struct irte *irte, int apic);
-extern int set_hpet_sid(struct irte *irte, u8 id);
-extern int set_msi_sid(struct irte *irte, struct pci_dev *dev);
-#else
-static inline int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
-{
- return -1;
-}
-static inline int modify_irte(int irq, struct irte *irte_modified)
-{
- return -1;
-}
-static inline int free_irte(int irq)
-{
- return -1;
-}
-static inline int map_irq_to_irte_handle(int irq, u16 *sub_handle)
-{
- return -1;
-}
-static inline int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index,
- u16 sub_handle)
-{
- return -1;
-}
-static inline struct intel_iommu *map_dev_to_ir(struct pci_dev *dev)
-{
- return NULL;
-}
-static inline struct intel_iommu *map_ioapic_to_ir(int apic)
-{
- return NULL;
-}
-static inline struct intel_iommu *map_hpet_to_ir(unsigned int hpet_id)
-{
- return NULL;
-}
-static inline int set_ioapic_sid(struct irte *irte, int apic)
-{
- return 0;
-}
-static inline int set_hpet_sid(struct irte *irte, u8 id)
-{
- return -1;
-}
-static inline int set_msi_sid(struct irte *irte, struct pci_dev *dev)
-{
- return 0;
-}
-
-#define intr_remapping_enabled (0)
-
-static inline int enable_intr_remapping(void)
-{
- return -1;
-}
-
-static inline void disable_intr_remapping(void)
-{
-}
-
-static inline int reenable_intr_remapping(int eim)
-{
- return 0;
-}
-#endif
-
enum {
IRQ_REMAP_XAPIC_MODE,
IRQ_REMAP_X2APIC_MODE,
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 7e3c53a900d8..c18257b0fa72 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -17,8 +17,8 @@ struct _ddebug {
const char *format;
unsigned int lineno:18;
/*
- * The flags field controls the behaviour at the callsite.
- * The bits here are changed dynamically when the user
+ * The flags field controls the behaviour at the callsite.
+ * The bits here are changed dynamically when the user
* writes commands to <debugfs>/dynamic_debug/control
*/
#define _DPRINTK_FLAGS_NONE 0
@@ -44,6 +44,9 @@ extern int ddebug_remove_module(const char *mod_name);
extern __printf(2, 3)
int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
+extern int ddebug_dyndbg_module_param_cb(char *param, char *val,
+ const char *modname);
+
struct device;
extern __printf(3, 4)
@@ -94,11 +97,26 @@ do { \
#else
+#include <linux/string.h>
+#include <linux/errno.h>
+
static inline int ddebug_remove_module(const char *mod)
{
return 0;
}
+static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,
+ const char *modname)
+{
+ if (strstr(param, "dyndbg")) {
+ /* avoid pr_warn(), which wants pr_fmt() fully defined */
+ printk(KERN_WARNING "dyndbg param is supported only in "
+ "CONFIG_DYNAMIC_DEBUG builds\n");
+ return 0; /* allow and ignore */
+ }
+ return -EINVAL;
+}
+
#define dynamic_pr_debug(fmt, ...) \
do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0)
#define dynamic_dev_dbg(dev, fmt, ...) \
diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h
index 657ab55beda0..6f8be328770a 100644
--- a/include/linux/eventpoll.h
+++ b/include/linux/eventpoll.h
@@ -26,6 +26,18 @@
#define EPOLL_CTL_DEL 2
#define EPOLL_CTL_MOD 3
+/*
+ * Request the handling of system wakeup events so as to prevent system suspends
+ * from happening while those events are being processed.
+ *
+ * Assuming neither EPOLLET nor EPOLLONESHOT is set, system suspends will not be
+ * re-allowed until epoll_wait is called again after consuming the wakeup
+ * event(s).
+ *
+ * Requires CAP_EPOLLWAKEUP
+ */
+#define EPOLLWAKEUP (1 << 29)
+
/* Set the One Shot behaviour for the target file descriptor */
#define EPOLLONESHOT (1 << 30)
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
new file mode 100644
index 000000000000..cdd401477656
--- /dev/null
+++ b/include/linux/extcon.h
@@ -0,0 +1,324 @@
+/*
+ * External connector (extcon) class driver
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Author: Donggeun Kim <dg77.kim@samsung.com>
+ * Author: MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * based on switch class driver
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+*/
+
+#ifndef __LINUX_EXTCON_H__
+#define __LINUX_EXTCON_H__
+
+#include <linux/notifier.h>
+
+#define SUPPORTED_CABLE_MAX 32
+#define CABLE_NAME_MAX 30
+
+/*
+ * The standard cable name is to help support general notifier
+ * and notifee device drivers to share the common names.
+ * Please use standard cable names unless your notifier device has
+ * a very unique and abnormal cable or
+ * the cable type is supposed to be used with only one unique
+ * pair of notifier/notifee devices.
+ *
+ * Please add any other "standard" cables used with extcon dev.
+ *
+ * You may add a dot and number to specify version or specification
+ * of the specific cable if it is required. (e.g., "Fast-charger.18"
+ * and "Fast-charger.10" for 1.8A and 1.0A chargers)
+ * However, the notifee and notifier should be able to handle such
+ * string and if the notifee can negotiate the protocol or idenify,
+ * you don't need such convention. This convention is helpful when
+ * notifier can distinguish but notifiee cannot.
+ */
+enum extcon_cable_name {
+ EXTCON_USB = 0,
+ EXTCON_USB_HOST,
+ EXTCON_TA, /* Travel Adaptor */
+ EXTCON_FAST_CHARGER,
+ EXTCON_SLOW_CHARGER,
+ EXTCON_CHARGE_DOWNSTREAM, /* Charging an external device */
+ EXTCON_HDMI,
+ EXTCON_MHL,
+ EXTCON_DVI,
+ EXTCON_VGA,
+ EXTCON_DOCK,
+ EXTCON_LINE_IN,
+ EXTCON_LINE_OUT,
+ EXTCON_MIC_IN,
+ EXTCON_HEADPHONE_OUT,
+ EXTCON_SPDIF_IN,
+ EXTCON_SPDIF_OUT,
+ EXTCON_VIDEO_IN,
+ EXTCON_VIDEO_OUT,
+ EXTCON_MECHANICAL,
+};
+extern const char *extcon_cable_name[];
+
+struct extcon_cable;
+
+/**
+ * struct extcon_dev - An extcon device represents one external connector.
+ * @name The name of this extcon device. Parent device name is used
+ * if NULL.
+ * @supported_cable Array of supported cable name ending with NULL.
+ * If supported_cable is NULL, cable name related APIs
+ * are disabled.
+ * @mutually_exclusive Array of mutually exclusive set of cables that cannot
+ * be attached simultaneously. The array should be
+ * ending with NULL or be NULL (no mutually exclusive
+ * cables). For example, if it is { 0x7, 0x30, 0}, then,
+ * {0, 1}, {0, 1, 2}, {0, 2}, {1, 2}, or {4, 5} cannot
+ * be attached simulataneously. {0x7, 0} is equivalent to
+ * {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
+ * can be no simultaneous connections.
+ * @print_name An optional callback to override the method to print the
+ * name of the extcon device.
+ * @print_state An optional callback to override the method to print the
+ * status of the extcon device.
+ * @dev Device of this extcon. Do not provide at register-time.
+ * @state Attach/detach state of this extcon. Do not provide at
+ * register-time
+ * @nh Notifier for the state change events from this extcon
+ * @entry To support list of extcon devices so that uses can search
+ * for extcon devices based on the extcon name.
+ * @lock
+ * @max_supported Internal value to store the number of cables.
+ * @extcon_dev_type Device_type struct to provide attribute_groups
+ * customized for each extcon device.
+ * @cables Sysfs subdirectories. Each represents one cable.
+ *
+ * In most cases, users only need to provide "User initializing data" of
+ * this struct when registering an extcon. In some exceptional cases,
+ * optional callbacks may be needed. However, the values in "internal data"
+ * are overwritten by register function.
+ */
+struct extcon_dev {
+ /* --- Optional user initializing data --- */
+ const char *name;
+ const char **supported_cable;
+ const u32 *mutually_exclusive;
+
+ /* --- Optional callbacks to override class functions --- */
+ ssize_t (*print_name)(struct extcon_dev *edev, char *buf);
+ ssize_t (*print_state)(struct extcon_dev *edev, char *buf);
+
+ /* --- Internal data. Please do not set. --- */
+ struct device *dev;
+ u32 state;
+ struct raw_notifier_head nh;
+ struct list_head entry;
+ spinlock_t lock; /* could be called by irq handler */
+ int max_supported;
+
+ /* /sys/class/extcon/.../cable.n/... */
+ struct device_type extcon_dev_type;
+ struct extcon_cable *cables;
+ /* /sys/class/extcon/.../mutually_exclusive/... */
+ struct attribute_group attr_g_muex;
+ struct attribute **attrs_muex;
+ struct device_attribute *d_attrs_muex;
+};
+
+/**
+ * struct extcon_cable - An internal data for each cable of extcon device.
+ * @edev The extcon device
+ * @cable_index Index of this cable in the edev
+ * @attr_g Attribute group for the cable
+ * @attr_name "name" sysfs entry
+ * @attr_state "state" sysfs entry
+ * @attrs Array pointing to attr_name and attr_state for attr_g
+ */
+struct extcon_cable {
+ struct extcon_dev *edev;
+ int cable_index;
+
+ struct attribute_group attr_g;
+ struct device_attribute attr_name;
+ struct device_attribute attr_state;
+
+ struct attribute *attrs[3]; /* to be fed to attr_g.attrs */
+};
+
+/**
+ * struct extcon_specific_cable_nb - An internal data for
+ * extcon_register_interest().
+ * @internal_nb a notifier block bridging extcon notifier and cable notifier.
+ * @user_nb user provided notifier block for events from a specific cable.
+ * @cable_index the target cable.
+ * @edev the target extcon device.
+ * @previous_value the saved previous event value.
+ */
+struct extcon_specific_cable_nb {
+ struct notifier_block internal_nb;
+ struct notifier_block *user_nb;
+ int cable_index;
+ struct extcon_dev *edev;
+ unsigned long previous_value;
+};
+
+#if IS_ENABLED(CONFIG_EXTCON)
+
+/*
+ * Following APIs are for notifiers or configurations.
+ * Notifiers are the external port and connection devices.
+ */
+extern int extcon_dev_register(struct extcon_dev *edev, struct device *dev);
+extern void extcon_dev_unregister(struct extcon_dev *edev);
+extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name);
+
+/*
+ * get/set/update_state access the 32b encoded state value, which represents
+ * states of all possible cables of the multistate port. For example, if one
+ * calls extcon_set_state(edev, 0x7), it may mean that all the three cables
+ * are attached to the port.
+ */
+static inline u32 extcon_get_state(struct extcon_dev *edev)
+{
+ return edev->state;
+}
+
+extern int extcon_set_state(struct extcon_dev *edev, u32 state);
+extern int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state);
+
+/*
+ * get/set_cable_state access each bit of the 32b encoded state value.
+ * They are used to access the status of each cable based on the cable_name
+ * or cable_index, which is retrived by extcon_find_cable_index
+ */
+extern int extcon_find_cable_index(struct extcon_dev *sdev,
+ const char *cable_name);
+extern int extcon_get_cable_state_(struct extcon_dev *edev, int cable_index);
+extern int extcon_set_cable_state_(struct extcon_dev *edev, int cable_index,
+ bool cable_state);
+
+extern int extcon_get_cable_state(struct extcon_dev *edev,
+ const char *cable_name);
+extern int extcon_set_cable_state(struct extcon_dev *edev,
+ const char *cable_name, bool cable_state);
+
+/*
+ * Following APIs are for notifiees (those who want to be notified)
+ * to register a callback for events from a specific cable of the extcon.
+ * Notifiees are the connected device drivers wanting to get notified by
+ * a specific external port of a connection device.
+ */
+extern int extcon_register_interest(struct extcon_specific_cable_nb *obj,
+ const char *extcon_name,
+ const char *cable_name,
+ struct notifier_block *nb);
+extern int extcon_unregister_interest(struct extcon_specific_cable_nb *nb);
+
+/*
+ * Following APIs are to monitor every action of a notifier.
+ * Registerer gets notified for every external port of a connection device.
+ * Probably this could be used to debug an action of notifier; however,
+ * we do not recommend to use this at normal 'notifiee' device drivers who
+ * want to be notified by a specific external port of the notifier.
+ */
+extern int extcon_register_notifier(struct extcon_dev *edev,
+ struct notifier_block *nb);
+extern int extcon_unregister_notifier(struct extcon_dev *edev,
+ struct notifier_block *nb);
+#else /* CONFIG_EXTCON */
+static inline int extcon_dev_register(struct extcon_dev *edev,
+ struct device *dev)
+{
+ return 0;
+}
+
+static inline void extcon_dev_unregister(struct extcon_dev *edev) { }
+
+static inline u32 extcon_get_state(struct extcon_dev *edev)
+{
+ return 0;
+}
+
+static inline int extcon_set_state(struct extcon_dev *edev, u32 state)
+{
+ return 0;
+}
+
+static inline int extcon_update_state(struct extcon_dev *edev, u32 mask,
+ u32 state)
+{
+ return 0;
+}
+
+static inline int extcon_find_cable_index(struct extcon_dev *edev,
+ const char *cable_name)
+{
+ return 0;
+}
+
+static inline int extcon_get_cable_state_(struct extcon_dev *edev,
+ int cable_index)
+{
+ return 0;
+}
+
+static inline int extcon_set_cable_state_(struct extcon_dev *edev,
+ int cable_index, bool cable_state)
+{
+ return 0;
+}
+
+static inline int extcon_get_cable_state(struct extcon_dev *edev,
+ const char *cable_name)
+{
+ return 0;
+}
+
+static inline int extcon_set_cable_state(struct extcon_dev *edev,
+ const char *cable_name, int state)
+{
+ return 0;
+}
+
+static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
+{
+ return NULL;
+}
+
+static inline int extcon_register_notifier(struct extcon_dev *edev,
+ struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int extcon_unregister_notifier(struct extcon_dev *edev,
+ struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int extcon_register_interest(struct extcon_specific_cable_nb *obj,
+ const char *extcon_name,
+ const char *cable_name,
+ struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int extcon_unregister_interest(struct extcon_specific_cable_nb
+ *obj)
+{
+ return 0;
+}
+#endif /* CONFIG_EXTCON */
+#endif /* __LINUX_EXTCON_H__ */
diff --git a/include/linux/extcon/extcon_gpio.h b/include/linux/extcon/extcon_gpio.h
new file mode 100644
index 000000000000..a2129b73dcb1
--- /dev/null
+++ b/include/linux/extcon/extcon_gpio.h
@@ -0,0 +1,52 @@
+/*
+ * External connector (extcon) class generic GPIO driver
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Author: MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * based on switch class driver
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+*/
+#ifndef __EXTCON_GPIO_H__
+#define __EXTCON_GPIO_H__ __FILE__
+
+#include <linux/extcon.h>
+
+/**
+ * struct gpio_extcon_platform_data - A simple GPIO-controlled extcon device.
+ * @name The name of this GPIO extcon device.
+ * @gpio Corresponding GPIO.
+ * @debounce Debounce time for GPIO IRQ in ms.
+ * @irq_flags IRQ Flags (e.g., IRQF_TRIGGER_LOW).
+ * @state_on print_state is overriden with state_on if attached. If Null,
+ * default method of extcon class is used.
+ * @state_off print_state is overriden with state_on if dettached. If Null,
+ * default method of extcon class is used.
+ *
+ * Note that in order for state_on or state_off to be valid, both state_on
+ * and state_off should be not NULL. If at least one of them is NULL,
+ * the print_state is not overriden.
+ */
+struct gpio_extcon_platform_data {
+ const char *name;
+ unsigned gpio;
+ unsigned long debounce;
+ unsigned long irq_flags;
+
+ /* if NULL, "0" or "1" will be printed */
+ const char *state_on;
+ const char *state_off;
+};
+
+#endif /* __EXTCON_GPIO_H__ */
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 72090994d789..82b01357af8b 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -10,6 +10,7 @@
#ifdef __KERNEL__
#include <linux/atomic.h>
+#include <linux/compat.h>
#endif
/*
@@ -133,6 +134,16 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
#ifdef __KERNEL__
+#ifdef CONFIG_COMPAT
+/*
+ * A struct sock_filter is architecture independent.
+ */
+struct compat_sock_fprog {
+ u16 len;
+ compat_uptr_t filter; /* struct sock_filter * */
+};
+#endif
+
struct sk_buff;
struct sock;
@@ -233,6 +244,7 @@ enum {
BPF_S_ANC_RXHASH,
BPF_S_ANC_CPU,
BPF_S_ANC_ALU_XOR_X,
+ BPF_S_ANC_SECCOMP_LD_W,
};
#endif /* __KERNEL__ */
diff --git a/include/linux/firewire.h b/include/linux/firewire.h
index cdc9b719e9c7..e83c24af358a 100644
--- a/include/linux/firewire.h
+++ b/include/linux/firewire.h
@@ -135,6 +135,20 @@ struct fw_card {
__be32 maint_utility_register;
};
+static inline struct fw_card *fw_card_get(struct fw_card *card)
+{
+ kref_get(&card->kref);
+
+ return card;
+}
+
+void fw_card_release(struct kref *kref);
+
+static inline void fw_card_put(struct fw_card *card)
+{
+ kref_put(&card->kref, fw_card_release);
+}
+
struct fw_attribute_group {
struct attribute_group *groups[2];
struct attribute_group group;
@@ -325,6 +339,7 @@ int fw_core_add_address_handler(struct fw_address_handler *handler,
void fw_core_remove_address_handler(struct fw_address_handler *handler);
void fw_send_response(struct fw_card *card,
struct fw_request *request, int rcode);
+int fw_get_request_speed(struct fw_request *request);
void fw_send_request(struct fw_card *card, struct fw_transaction *t,
int tcode, int destination_id, int generation, int speed,
unsigned long long offset, void *payload, size_t length,
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 8de675523e46..25c40b9f848a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2051,6 +2051,7 @@ extern void unregister_blkdev(unsigned int, const char *);
extern struct block_device *bdget(dev_t);
extern struct block_device *bdgrab(struct block_device *bdev);
extern void bd_set_size(struct block_device *, loff_t size);
+extern sector_t blkdev_max_block(struct block_device *bdev);
extern void bd_forget(struct inode *inode);
extern void bdput(struct block_device *);
extern void invalidate_bdev(struct block_device *);
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index fffdf00f87b9..15be561e7397 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -6,7 +6,7 @@
*
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
*
- * Copyright 2004 Freescale Semiconductor, Inc
+ * Copyright 2004,2012 Freescale Semiconductor, Inc
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -17,6 +17,12 @@
#ifndef _FSL_DEVICE_H_
#define _FSL_DEVICE_H_
+#define FSL_UTMI_PHY_DLY 10 /*As per P1010RM, delay for UTMI
+ PHY CLK to become stable - 10ms*/
+#define FSL_USB_VER_OLD 0
+#define FSL_USB_VER_1_6 1
+#define FSL_USB_VER_2_2 2
+
#include <linux/types.h>
/*
@@ -63,6 +69,7 @@ struct platform_device;
struct fsl_usb2_platform_data {
/* board specific information */
+ int controller_ver;
enum fsl_usb2_operating_modes operating_mode;
enum fsl_usb2_phy_modes phy_mode;
unsigned int port_enables;
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 72a6cabb4d5b..55e6d63d46d0 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -286,10 +286,16 @@ struct ftrace_rec_iter *ftrace_rec_iter_start(void);
struct ftrace_rec_iter *ftrace_rec_iter_next(struct ftrace_rec_iter *iter);
struct dyn_ftrace *ftrace_rec_iter_record(struct ftrace_rec_iter *iter);
+#define for_ftrace_rec_iter(iter) \
+ for (iter = ftrace_rec_iter_start(); \
+ iter; \
+ iter = ftrace_rec_iter_next(iter))
+
+
int ftrace_update_record(struct dyn_ftrace *rec, int enable);
int ftrace_test_record(struct dyn_ftrace *rec, int enable);
void ftrace_run_stop_machine(int command);
-int ftrace_location(unsigned long ip);
+unsigned long ftrace_location(unsigned long ip);
extern ftrace_func_t ftrace_trace_function;
@@ -308,11 +314,14 @@ ftrace_set_early_filter(struct ftrace_ops *ops, char *buf, int enable);
/* defined in arch */
extern int ftrace_ip_converted(unsigned long ip);
extern int ftrace_dyn_arch_init(void *data);
+extern void ftrace_replace_code(int enable);
extern int ftrace_update_ftrace_func(ftrace_func_t func);
extern void ftrace_caller(void);
extern void ftrace_call(void);
extern void mcount_call(void);
+void ftrace_modify_all_code(int command);
+
#ifndef FTRACE_ADDR
#define FTRACE_ADDR ((unsigned long)ftrace_caller)
#endif
@@ -485,8 +494,12 @@ static inline void __ftrace_enabled_restore(int enabled)
extern void trace_preempt_on(unsigned long a0, unsigned long a1);
extern void trace_preempt_off(unsigned long a0, unsigned long a1);
#else
- static inline void trace_preempt_on(unsigned long a0, unsigned long a1) { }
- static inline void trace_preempt_off(unsigned long a0, unsigned long a1) { }
+/*
+ * Use defines instead of static inlines because some arches will make code out
+ * of the CALLER_ADDR, when we really want these to be a real nop.
+ */
+# define trace_preempt_on(a0, a1) do { } while (0)
+# define trace_preempt_off(a0, a1) do { } while (0)
#endif
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 5f3f3be5af09..176a939d1547 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -179,6 +179,7 @@ enum {
TRACE_EVENT_FL_RECORDED_CMD_BIT,
TRACE_EVENT_FL_CAP_ANY_BIT,
TRACE_EVENT_FL_NO_SET_FILTER_BIT,
+ TRACE_EVENT_FL_IGNORE_ENABLE_BIT,
};
enum {
@@ -187,6 +188,7 @@ enum {
TRACE_EVENT_FL_RECORDED_CMD = (1 << TRACE_EVENT_FL_RECORDED_CMD_BIT),
TRACE_EVENT_FL_CAP_ANY = (1 << TRACE_EVENT_FL_CAP_ANY_BIT),
TRACE_EVENT_FL_NO_SET_FILTER = (1 << TRACE_EVENT_FL_NO_SET_FILTER_BIT),
+ TRACE_EVENT_FL_IGNORE_ENABLE = (1 << TRACE_EVENT_FL_IGNORE_ENABLE_BIT),
};
struct ftrace_event_call {
diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h
index fadff28505bb..79b3eb37243a 100644
--- a/include/linux/generic_serial.h
+++ b/include/linux/generic_serial.h
@@ -4,7 +4,6 @@
* Copyright (C) 1998 R.E.Wolff@BitWizard.nl
*
* written for the SX serial driver.
- * Contains the code that should be shared over all the serial drivers.
*
* Version 0.1 -- December, 1998.
*/
@@ -12,45 +11,8 @@
#ifndef GENERIC_SERIAL_H
#define GENERIC_SERIAL_H
-#ifdef __KERNEL__
-#include <linux/mutex.h>
-#include <linux/tty.h>
-
-struct real_driver {
- void (*disable_tx_interrupts) (void *);
- void (*enable_tx_interrupts) (void *);
- void (*disable_rx_interrupts) (void *);
- void (*enable_rx_interrupts) (void *);
- void (*shutdown_port) (void*);
- int (*set_real_termios) (void*);
- int (*chars_in_buffer) (void*);
- void (*close) (void*);
- void (*hungup) (void*);
- void (*getserial) (void*, struct serial_struct *sp);
-};
-
-
-
-struct gs_port {
- int magic;
- struct tty_port port;
- unsigned char *xmit_buf;
- int xmit_head;
- int xmit_tail;
- int xmit_cnt;
- struct mutex port_write_mutex;
- unsigned long event;
- unsigned short closing_wait;
- int close_delay;
- struct real_driver *rd;
- int wakeup_chars;
- int baud_base;
- int baud;
- int custom_divisor;
- spinlock_t driver_lock;
-};
-
-#endif /* __KERNEL__ */
+#warning Use of this header is deprecated.
+#warning Since nobody sets the constants defined here for you, you should not, in any case, use them. Including the header is thus pointless.
/* Flags */
/* Warning: serial.h defines some ASYNC_ flags, they say they are "only"
@@ -60,8 +22,6 @@ struct gs_port {
#define GS_RX_INTEN 0x00400000
#define GS_ACTIVE 0x00200000
-
-
#define GS_TYPE_NORMAL 1
#define GS_DEBUG_FLUSH 0x00000001
@@ -72,24 +32,4 @@ struct gs_port {
#define GS_DEBUG_FLOW 0x00000020
#define GS_DEBUG_WRITE 0x00000040
-#ifdef __KERNEL__
-int gs_put_char(struct tty_struct *tty, unsigned char ch);
-int gs_write(struct tty_struct *tty,
- const unsigned char *buf, int count);
-int gs_write_room(struct tty_struct *tty);
-int gs_chars_in_buffer(struct tty_struct *tty);
-void gs_flush_buffer(struct tty_struct *tty);
-void gs_flush_chars(struct tty_struct *tty);
-void gs_stop(struct tty_struct *tty);
-void gs_start(struct tty_struct *tty);
-void gs_hangup(struct tty_struct *tty);
-int gs_block_til_ready(void *port, struct file *filp);
-void gs_close(struct tty_struct *tty, struct file *filp);
-void gs_set_termios (struct tty_struct * tty,
- struct ktermios * old_termios);
-int gs_init_port(struct gs_port *port);
-int gs_setserial(struct gs_port *port, struct serial_struct __user *sp);
-int gs_getserial(struct gs_port *port, struct serial_struct __user *sp);
-void gs_got_break(struct gs_port *port);
-#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index e61d3192448e..017a7fb5a1fc 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -222,12 +222,6 @@ static inline void part_pack_uuid(const u8 *uuid_str, u8 *to)
}
}
-static inline char *part_unpack_uuid(const u8 *uuid, char *out)
-{
- sprintf(out, "%pU", uuid);
- return out;
-}
-
static inline int disk_max_parts(struct gendisk *disk)
{
if (disk->flags & GENHD_FL_EXT_DEVT)
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 3a95da60fd3e..449fa385703d 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -317,7 +317,6 @@ struct hid_item {
#define HID_QUIRK_BADPAD 0x00000020
#define HID_QUIRK_MULTI_INPUT 0x00000040
#define HID_QUIRK_HIDINPUT_FORCE 0x00000080
-#define HID_QUIRK_MULTITOUCH 0x00000100
#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
#define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000
#define HID_QUIRK_NO_INIT_REPORTS 0x20000000
@@ -325,6 +324,12 @@ struct hid_item {
#define HID_QUIRK_NO_INPUT_SYNC 0x80000000
/*
+ * HID device groups
+ */
+#define HID_GROUP_GENERIC 0x0001
+#define HID_GROUP_MULTITOUCH 0x0002
+
+/*
* This is the global environment of the parser. This information is
* persistent for main-items. The global environment can be saved and
* restored with PUSH/POP statements.
@@ -467,6 +472,8 @@ struct hid_driver;
struct hid_ll_driver;
struct hid_device { /* device report descriptor */
+ __u8 *dev_rdesc;
+ unsigned dev_rsize;
__u8 *rdesc;
unsigned rsize;
struct hid_collection *collection; /* List of HID collections */
@@ -474,6 +481,7 @@ struct hid_device { /* device report descriptor */
unsigned maxcollection; /* Number of parsed collections */
unsigned maxapplication; /* Number of applications */
__u16 bus; /* BUS ID */
+ __u16 group; /* Report group */
__u32 vendor; /* Vendor ID */
__u32 product; /* Product ID */
__u32 version; /* HID version */
@@ -578,12 +586,12 @@ struct hid_descriptor {
struct hid_class_descriptor desc[1];
} __attribute__ ((packed));
-#define HID_DEVICE(b, ven, prod) \
- .bus = (b), \
- .vendor = (ven), .product = (prod)
-
-#define HID_USB_DEVICE(ven, prod) HID_DEVICE(BUS_USB, ven, prod)
-#define HID_BLUETOOTH_DEVICE(ven, prod) HID_DEVICE(BUS_BLUETOOTH, ven, prod)
+#define HID_DEVICE(b, g, ven, prod) \
+ .bus = (b), .group = (g), .vendor = (ven), .product = (prod)
+#define HID_USB_DEVICE(ven, prod) \
+ .bus = BUS_USB, .vendor = (ven), .product = (prod)
+#define HID_BLUETOOTH_DEVICE(ven, prod) \
+ .bus = BUS_BLUETOOTH, .vendor = (ven), .product = (prod)
#define HID_REPORT_ID(rep) \
.report_type = (rep)
@@ -735,6 +743,7 @@ void hid_output_report(struct hid_report *report, __u8 *data);
struct hid_device *hid_allocate_device(void);
struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
+int hid_open_report(struct hid_device *device);
int hid_check_keys_pressed(struct hid_device *hid);
int hid_connect(struct hid_device *hid, unsigned int connect_mask);
void hid_disconnect(struct hid_device *hid);
@@ -805,16 +814,7 @@ static inline void hid_map_usage_clear(struct hid_input *hidinput,
*/
static inline int __must_check hid_parse(struct hid_device *hdev)
{
- int ret;
-
- if (hdev->status & HID_STAT_PARSED)
- return 0;
-
- ret = hdev->ll_driver->parse(hdev);
- if (!ret)
- hdev->status |= HID_STAT_PARSED;
-
- return ret;
+ return hid_open_report(hdev);
}
/**
@@ -896,7 +896,7 @@ static inline int hid_hw_power(struct hid_device *hdev, int level)
return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0;
}
-void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
+int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
int interrupt);
extern int hid_generic_init(void);
diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h
index 4b88e697c4e9..45e9fcb8d877 100644
--- a/include/linux/hidraw.h
+++ b/include/linux/hidraw.h
@@ -76,13 +76,13 @@ struct hidraw_list {
#ifdef CONFIG_HIDRAW
int hidraw_init(void);
void hidraw_exit(void);
-void hidraw_report_event(struct hid_device *, u8 *, int);
+int hidraw_report_event(struct hid_device *, u8 *, int);
int hidraw_connect(struct hid_device *);
void hidraw_disconnect(struct hid_device *);
#else
static inline int hidraw_init(void) { return 0; }
static inline void hidraw_exit(void) { }
-static inline void hidraw_report_event(struct hid_device *hid, u8 *data, int len) { }
+static inline int hidraw_report_event(struct hid_device *hid, u8 *data, int len) { return 0; }
static inline int hidraw_connect(struct hid_device *hid) { return -1; }
static inline void hidraw_disconnect(struct hid_device *hid) { }
#endif
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 6af8738ae7e9..68ed7f7e1fc9 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1062,8 +1062,10 @@ struct hyperv_service_callback {
void (*callback) (void *context);
};
+#define MAX_SRV_VER 0x7ffffff
extern void vmbus_prep_negotiate_resp(struct icmsg_hdr *,
- struct icmsg_negotiate *, u8 *);
+ struct icmsg_negotiate *, u8 *, int,
+ int);
int hv_kvp_init(struct hv_util_service *);
void hv_kvp_deinit(void);
diff --git a/include/linux/i2c-pnx.h b/include/linux/i2c-pnx.h
index a87124d4d533..1bc74afe7a35 100644
--- a/include/linux/i2c-pnx.h
+++ b/include/linux/i2c-pnx.h
@@ -29,14 +29,10 @@ struct i2c_pnx_algo_data {
struct i2c_pnx_mif mif;
int last;
struct clk *clk;
- struct i2c_pnx_data *i2c_pnx;
struct i2c_adapter adapter;
-};
-
-struct i2c_pnx_data {
- const char *name;
- u32 base;
- int irq;
+ phys_addr_t base;
+ int irq;
+ u32 timeout;
};
#endif /* __I2C_PNX_H__ */
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 1f90de0cfdbe..3993477103a5 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -171,8 +171,6 @@ static inline int twl_class_is_ ##class(void) \
TWL_CLASS_IS(4030, TWL4030_CLASS_ID)
TWL_CLASS_IS(6030, TWL6030_CLASS_ID)
-#define TWL6025_SUBCLASS BIT(4) /* TWL6025 has changed registers */
-
/*
* Read and write single 8-bit registers
*/
@@ -746,6 +744,17 @@ struct twl_regulator_driver_data {
void *data;
unsigned long features;
};
+/* chip-specific feature flags, for twl_regulator_driver_data.features */
+#define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */
+#define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */
+#define TWL5031 BIT(2) /* twl5031 has different registers */
+#define TWL6030_CLASS BIT(3) /* TWL6030 class */
+#define TWL6025_SUBCLASS BIT(4) /* TWL6025 has changed registers */
+#define TWL4030_ALLOW_UNSUPPORTED BIT(5) /* Some voltages are possible
+ * but not officially supported.
+ * This flag is necessary to
+ * enable them.
+ */
/*----------------------------------------------------------------------*/
diff --git a/include/linux/if_ec.h b/include/linux/if_ec.h
deleted file mode 100644
index d85f9f48129f..000000000000
--- a/include/linux/if_ec.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Definitions for Econet sockets. */
-
-#ifndef __LINUX_IF_EC
-#define __LINUX_IF_EC
-
-/* User visible stuff. Glibc provides its own but libc5 folk will use these */
-
-struct ec_addr {
- unsigned char station; /* Station number. */
- unsigned char net; /* Network number. */
-};
-
-struct sockaddr_ec {
- unsigned short sec_family;
- unsigned char port; /* Port number. */
- unsigned char cb; /* Control/flag byte. */
- unsigned char type; /* Type of message. */
- struct ec_addr addr;
- unsigned long cookie;
-};
-
-#define ECTYPE_PACKET_RECEIVED 0 /* Packet received */
-#define ECTYPE_TRANSMIT_STATUS 0x10 /* Transmit completed,
- low nibble holds status */
-
-#define ECTYPE_TRANSMIT_OK 1
-#define ECTYPE_TRANSMIT_NOT_LISTENING 2
-#define ECTYPE_TRANSMIT_NET_ERROR 3
-#define ECTYPE_TRANSMIT_NO_CLOCK 4
-#define ECTYPE_TRANSMIT_LINE_JAMMED 5
-#define ECTYPE_TRANSMIT_NOT_PRESENT 6
-
-#ifdef __KERNEL__
-
-#define EC_HLEN 6
-
-/* This is what an Econet frame looks like on the wire. */
-struct ec_framehdr {
- unsigned char dst_stn;
- unsigned char dst_net;
- unsigned char src_stn;
- unsigned char src_net;
- unsigned char cb;
- unsigned char port;
-};
-
-struct econet_sock {
- /* struct sock has to be the first member of econet_sock */
- struct sock sk;
- unsigned char cb;
- unsigned char port;
- unsigned char station;
- unsigned char net;
- unsigned short num;
-};
-
-static inline struct econet_sock *ec_sk(const struct sock *sk)
-{
- return (struct econet_sock *)sk;
-}
-
-struct ec_device {
- unsigned char station, net; /* Econet protocol address */
-};
-
-#endif
-
-#endif
diff --git a/drivers/staging/iio/buffer.h b/include/linux/iio/buffer.h
index df2046dcb623..fb0fe46fd659 100644
--- a/drivers/staging/iio/buffer.h
+++ b/include/linux/iio/buffer.h
@@ -10,7 +10,7 @@
#ifndef _IIO_BUFFER_GENERIC_H_
#define _IIO_BUFFER_GENERIC_H_
#include <linux/sysfs.h>
-#include "iio.h"
+#include <linux/iio/iio.h>
#ifdef CONFIG_IIO_BUFFER
@@ -56,7 +56,6 @@ struct iio_buffer_access_funcs {
* @scan_el_attrs: [DRIVER] control of scan elements if that scan mode
* control method is used
* @scan_mask: [INTERN] bitmask used in masking scan mode elements
- * @scan_index_timestamp:[INTERN] cache of the index to the timestamp
* @scan_timestamp: [INTERN] does the scan mode include a timestamp
* @access: [DRIVER] buffer access functions associated with the
* implementation.
@@ -74,7 +73,6 @@ struct iio_buffer {
struct attribute_group *scan_el_attrs;
long *scan_mask;
bool scan_timestamp;
- unsigned scan_index_timestamp;
const struct iio_buffer_access_funcs *access;
struct list_head scan_el_dev_attr_list;
struct attribute_group scan_el_group;
diff --git a/drivers/staging/iio/consumer.h b/include/linux/iio/consumer.h
index 36a060cd3a21..1a15e560a5a1 100644
--- a/drivers/staging/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -9,7 +9,7 @@
*/
#ifndef _IIO_INKERN_CONSUMER_H_
#define _IIO_INKERN_CONSUMER_H
-#include "types.h"
+#include <linux/iio/types.h>
struct iio_dev;
struct iio_chan_spec;
diff --git a/drivers/staging/iio/driver.h b/include/linux/iio/driver.h
index a4f8b2e05af5..a4f8b2e05af5 100644
--- a/drivers/staging/iio/driver.h
+++ b/include/linux/iio/driver.h
diff --git a/drivers/staging/iio/events.h b/include/linux/iio/events.h
index c25f0e3c92e9..b5acbf93c5da 100644
--- a/drivers/staging/iio/events.h
+++ b/include/linux/iio/events.h
@@ -11,7 +11,7 @@
#include <linux/ioctl.h>
#include <linux/types.h>
-#include "types.h"
+#include <linux/iio/types.h>
/**
* struct iio_event_data - The actual event being pushed to userspace
diff --git a/drivers/staging/iio/iio.h b/include/linux/iio/iio.h
index b9cd454f69e2..3a4f6a3ab80d 100644
--- a/drivers/staging/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -12,22 +12,17 @@
#include <linux/device.h>
#include <linux/cdev.h>
-#include "types.h"
+#include <linux/iio/types.h>
/* IIO TODO LIST */
/*
* Provide means of adjusting timer accuracy.
* Currently assumes nano seconds.
*/
-enum iio_data_type {
- IIO_RAW,
- IIO_PROCESSED,
-};
-
-/* Could add the raw attributes as well - allowing buffer only devices */
enum iio_chan_info_enum {
- /* 0 is reserved for raw attributes */
- IIO_CHAN_INFO_SCALE = 1,
+ IIO_CHAN_INFO_RAW = 0,
+ IIO_CHAN_INFO_PROCESSED,
+ IIO_CHAN_INFO_SCALE,
IIO_CHAN_INFO_OFFSET,
IIO_CHAN_INFO_CALIBSCALE,
IIO_CHAN_INFO_CALIBBIAS,
@@ -36,11 +31,19 @@ enum iio_chan_info_enum {
IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW,
IIO_CHAN_INFO_AVERAGE_RAW,
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY,
+ IIO_CHAN_INFO_SAMP_FREQ,
+ IIO_CHAN_INFO_FREQUENCY,
+ IIO_CHAN_INFO_PHASE,
+ IIO_CHAN_INFO_HARDWAREGAIN,
};
#define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2)
#define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1)
+#define IIO_CHAN_INFO_RAW_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_RAW)
+#define IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PROCESSED)
#define IIO_CHAN_INFO_SCALE_SEPARATE_BIT \
IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SCALE)
#define IIO_CHAN_INFO_SCALE_SHARED_BIT \
@@ -81,6 +84,22 @@ enum iio_chan_info_enum {
#define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT \
IIO_CHAN_INFO_SEPARATE_BIT( \
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY)
+#define IIO_CHAN_INFO_SAMP_FREQ_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SAMP_FREQ)
+#define IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT \
+ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_SAMP_FREQ)
+#define IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_FREQUENCY)
+#define IIO_CHAN_INFO_FREQUENCY_SHARED_BIT \
+ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_FREQUENCY)
+#define IIO_CHAN_INFO_PHASE_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PHASE)
+#define IIO_CHAN_INFO_PHASE_SHARED_BIT \
+ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PHASE)
+#define IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT \
+ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_HARDWAREGAIN)
+#define IIO_CHAN_INFO_HARDWAREGAIN_SHARED_BIT \
+ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_HARDWAREGAIN)
enum iio_endian {
IIO_CPU,
@@ -97,14 +116,17 @@ struct iio_dev;
* @shared: Whether this attribute is shared between all channels.
* @read: Read callback for this info attribute, may be NULL.
* @write: Write callback for this info attribute, may be NULL.
+ * @private: Data private to the driver.
*/
struct iio_chan_spec_ext_info {
const char *name;
bool shared;
- ssize_t (*read)(struct iio_dev *, struct iio_chan_spec const *,
- char *buf);
- ssize_t (*write)(struct iio_dev *, struct iio_chan_spec const *,
- const char *buf, size_t len);
+ ssize_t (*read)(struct iio_dev *, uintptr_t private,
+ struct iio_chan_spec const *, char *buf);
+ ssize_t (*write)(struct iio_dev *, uintptr_t private,
+ struct iio_chan_spec const *, const char *buf,
+ size_t len);
+ uintptr_t private;
};
/**
@@ -136,8 +158,6 @@ struct iio_chan_spec_ext_info {
* correspond to the first name that the channel is referred
* to by in the datasheet (e.g. IND), or the nearest
* possible compound name (e.g. IND-INC).
- * @processed_val: Flag to specify the data access attribute should be
- * *_input rather than *_raw.
* @modified: Does a modifier apply to this channel. What these are
* depends on the channel type. Modifier is set in
* channel2. Examples are IIO_MOD_X for axial sensors about
@@ -164,9 +184,8 @@ struct iio_chan_spec {
long info_mask;
long event_mask;
const struct iio_chan_spec_ext_info *ext_info;
- char *extend_name;
+ const char *extend_name;
const char *datasheet_name;
- unsigned processed_val:1;
unsigned modified:1;
unsigned indexed:1;
unsigned output:1;
@@ -176,23 +195,6 @@ struct iio_chan_spec {
#define IIO_ST(si, rb, sb, sh) \
{ .sign = si, .realbits = rb, .storagebits = sb, .shift = sh }
-/* Macro assumes input channels */
-#define IIO_CHAN(_type, _mod, _indexed, _proc, _name, _chan, _chan2, \
- _inf_mask, _address, _si, _stype, _event_mask) \
- { .type = _type, \
- .output = 0, \
- .modified = _mod, \
- .indexed = _indexed, \
- .processed_val = _proc, \
- .extend_name = _name, \
- .channel = _chan, \
- .channel2 = _chan2, \
- .info_mask = _inf_mask, \
- .address = _address, \
- .scan_index = _si, \
- .scan_type = _stype, \
- .event_mask = _event_mask }
-
#define IIO_CHAN_SOFT_TIMESTAMP(_si) \
{ .type = IIO_TIMESTAMP, .channel = -1, \
.scan_index = _si, .scan_type = IIO_ST('s', 64, 64, 0) }
@@ -315,12 +317,15 @@ struct iio_buffer_setup_ops {
* and owner
* @event_interface: [INTERN] event chrdevs associated with interrupt lines
* @buffer: [DRIVER] any buffer present
+ * @scan_bytes: [INTERN] num bytes captured to be fed to buffer demux
* @mlock: [INTERN] lock used to prevent simultaneous device state
* changes
* @available_scan_masks: [DRIVER] optional array of allowed bitmasks
* @masklength: [INTERN] the length of the mask established from
* channels
* @active_scan_mask: [INTERN] union of all scan masks requested by buffers
+ * @scan_timestamp: [INTERN] set if any buffers have requested timestamp
+ * @scan_index_timestamp:[INTERN] cache of the index to the timestamp
* @trig: [INTERN] current device trigger (buffer modes)
* @pollfunc: [DRIVER] function run on trigger being received
* @channels: [DRIVER] channel specification structure table
@@ -331,6 +336,8 @@ struct iio_buffer_setup_ops {
* @name: [DRIVER] name of the device.
* @info: [DRIVER] callbacks and constant info from driver
* @info_exist_lock: [INTERN] lock to prevent use during removal
+ * @setup_ops: [DRIVER] callbacks to call before and after buffer
+ * enable/disable
* @chrdev: [INTERN] associated character device
* @groups: [INTERN] attribute groups
* @groupcounter: [INTERN] index of next attribute group
@@ -348,11 +355,14 @@ struct iio_dev {
struct iio_event_interface *event_interface;
struct iio_buffer *buffer;
+ int scan_bytes;
struct mutex mlock;
const unsigned long *available_scan_masks;
unsigned masklength;
const unsigned long *active_scan_mask;
+ bool scan_timestamp;
+ unsigned scan_index_timestamp;
struct iio_trigger *trig;
struct iio_poll_func *pollfunc;
@@ -408,22 +418,33 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp);
extern struct bus_type iio_bus_type;
/**
- * iio_put_device() - reference counted deallocation of struct device
+ * iio_device_put() - reference counted deallocation of struct device
* @dev: the iio_device containing the device
**/
-static inline void iio_put_device(struct iio_dev *indio_dev)
+static inline void iio_device_put(struct iio_dev *indio_dev)
{
if (indio_dev)
put_device(&indio_dev->dev);
};
+/**
+ * dev_to_iio_dev() - Get IIO device struct from a device struct
+ * @dev: The device embedded in the IIO device
+ *
+ * Note: The device must be a IIO device, otherwise the result is undefined.
+ */
+static inline struct iio_dev *dev_to_iio_dev(struct device *dev)
+{
+ return container_of(dev, struct iio_dev, dev);
+}
+
/* Can we make this smaller? */
#define IIO_ALIGN L1_CACHE_BYTES
/**
- * iio_allocate_device() - allocate an iio_dev from a driver
+ * iio_device_alloc() - allocate an iio_dev from a driver
* @sizeof_priv: Space to allocate for private structure.
**/
-struct iio_dev *iio_allocate_device(int sizeof_priv);
+struct iio_dev *iio_device_alloc(int sizeof_priv);
static inline void *iio_priv(const struct iio_dev *indio_dev)
{
@@ -437,10 +458,10 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv)
}
/**
- * iio_free_device() - free an iio_dev from a driver
+ * iio_device_free() - free an iio_dev from a driver
* @dev: the iio_dev associated with the device
**/
-void iio_free_device(struct iio_dev *indio_dev);
+void iio_device_free(struct iio_dev *indio_dev);
/**
* iio_buffer_enabled() - helper function to test if the buffer is enabled
diff --git a/drivers/staging/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h
index 9f7da016af04..014d5a13b32b 100644
--- a/drivers/staging/iio/kfifo_buf.h
+++ b/include/linux/iio/kfifo_buf.h
@@ -1,7 +1,7 @@
#include <linux/kfifo.h>
-#include "iio.h"
-#include "buffer.h"
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev);
void iio_kfifo_free(struct iio_buffer *r);
diff --git a/drivers/staging/iio/machine.h b/include/linux/iio/machine.h
index 0b1f19bfdc44..0b1f19bfdc44 100644
--- a/drivers/staging/iio/machine.h
+++ b/include/linux/iio/machine.h
diff --git a/drivers/staging/iio/sysfs.h b/include/linux/iio/sysfs.h
index bfedb73b850e..bfedb73b850e 100644
--- a/drivers/staging/iio/sysfs.h
+++ b/include/linux/iio/sysfs.h
diff --git a/drivers/staging/iio/trigger.h b/include/linux/iio/trigger.h
index 1cfca231db8f..a9819940a84c 100644
--- a/drivers/staging/iio/trigger.h
+++ b/include/linux/iio/trigger.h
@@ -78,13 +78,13 @@ static inline struct iio_trigger *to_iio_trigger(struct device *d)
return container_of(d, struct iio_trigger, dev);
};
-static inline void iio_put_trigger(struct iio_trigger *trig)
+static inline void iio_trigger_put(struct iio_trigger *trig)
{
module_put(trig->ops->owner);
put_device(&trig->dev);
};
-static inline void iio_get_trigger(struct iio_trigger *trig)
+static inline void iio_trigger_get(struct iio_trigger *trig)
{
get_device(&trig->dev);
__module_get(trig->ops->owner);
@@ -113,7 +113,7 @@ void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time);
irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private);
-__printf(1, 2) struct iio_trigger *iio_allocate_trigger(const char *fmt, ...);
-void iio_free_trigger(struct iio_trigger *trig);
+__printf(1, 2) struct iio_trigger *iio_trigger_alloc(const char *fmt, ...);
+void iio_trigger_free(struct iio_trigger *trig);
#endif /* _IIO_TRIGGER_H_ */
diff --git a/drivers/staging/iio/trigger_consumer.h b/include/linux/iio/trigger_consumer.h
index 60d64b356945..60d64b356945 100644
--- a/drivers/staging/iio/trigger_consumer.h
+++ b/include/linux/iio/trigger_consumer.h
diff --git a/drivers/staging/iio/types.h b/include/linux/iio/types.h
index 0c3213666901..1b073b1cc7c2 100644
--- a/drivers/staging/iio/types.h
+++ b/include/linux/iio/types.h
@@ -27,6 +27,7 @@ enum iio_chan_type {
IIO_ANGL,
IIO_TIMESTAMP,
IIO_CAPACITANCE,
+ IIO_ALTVOLTAGE,
};
enum iio_modifier {
@@ -49,5 +50,6 @@ enum iio_modifier {
#define IIO_VAL_INT 1
#define IIO_VAL_INT_PLUS_MICRO 2
#define IIO_VAL_INT_PLUS_NANO 3
+#define IIO_VAL_INT_PLUS_MICRO_DB 4
#endif /* _IIO_TYPES_H_ */
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 2aea5d22db07..c91171599cb6 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -93,27 +93,27 @@ typedef irqreturn_t (*irq_handler_t)(int, void *);
/**
* struct irqaction - per interrupt action descriptor
* @handler: interrupt handler function
- * @flags: flags (see IRQF_* above)
* @name: name of the device
* @dev_id: cookie to identify the device
* @percpu_dev_id: cookie to identify the device
* @next: pointer to the next irqaction for shared interrupts
* @irq: interrupt number
- * @dir: pointer to the proc/irq/NN/name entry
+ * @flags: flags (see IRQF_* above)
* @thread_fn: interrupt handler function for threaded interrupts
* @thread: thread pointer for threaded interrupts
* @thread_flags: flags related to @thread
* @thread_mask: bitmask for keeping track of @thread activity
+ * @dir: pointer to the proc/irq/NN/name entry
*/
struct irqaction {
irq_handler_t handler;
- unsigned long flags;
void *dev_id;
void __percpu *percpu_dev_id;
struct irqaction *next;
- int irq;
irq_handler_t thread_fn;
struct task_struct *thread;
+ unsigned int irq;
+ unsigned int flags;
unsigned long thread_flags;
unsigned long thread_mask;
const char *name;
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index e885ba23de70..589e0e75efae 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -223,5 +223,12 @@ extern int
walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
void *arg, int (*func)(unsigned long, unsigned long, void *));
+/* True if any part of r1 overlaps r2 */
+static inline bool resource_overlaps(struct resource *r1, struct resource *r2)
+{
+ return (r1->start <= r2->end && r1->end >= r2->start);
+}
+
+
#endif /* __ASSEMBLY__ */
#endif /* _LINUX_IOPORT_H */
diff --git a/include/linux/irq.h b/include/linux/irq.h
index b27cfcfd3a59..61f5cec031e0 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -335,11 +335,6 @@ struct irq_chip {
void (*irq_print_chip)(struct irq_data *data, struct seq_file *p);
unsigned long flags;
-
- /* Currently used only by UML, might disappear one day.*/
-#ifdef CONFIG_IRQ_RELEASE_METHOD
- void (*release)(unsigned int irq, void *dev_id);
-#endif
};
/*
diff --git a/include/linux/isdn.h b/include/linux/isdn.h
index 292f27a793d4..215c41602af8 100644
--- a/include/linux/isdn.h
+++ b/include/linux/isdn.h
@@ -15,6 +15,7 @@
#define __ISDN_H__
#include <linux/ioctl.h>
+#include <linux/tty.h>
#define ISDN_MAX_DRIVERS 32
#define ISDN_MAX_CHANNELS 64
@@ -392,21 +393,8 @@ typedef struct isdn_net_dev_s {
/*======================= Start of ISDN-tty stuff ===========================*/
#define ISDN_ASYNC_MAGIC 0x49344C01 /* for paranoia-checking */
-#define ISDN_ASYNC_INITIALIZED 0x80000000 /* port was initialized */
-#define ISDN_ASYNC_CALLOUT_ACTIVE 0x40000000 /* Call out device active */
-#define ISDN_ASYNC_NORMAL_ACTIVE 0x20000000 /* Normal device active */
-#define ISDN_ASYNC_CLOSING 0x08000000 /* Serial port is closing */
-#define ISDN_ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */
-#define ISDN_ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */
-#define ISDN_ASYNC_HUP_NOTIFY 0x0001 /* Notify tty on hangups/closes */
-#define ISDN_ASYNC_SESSION_LOCKOUT 0x0100 /* Lock cua opens on session */
-#define ISDN_ASYNC_PGRP_LOCKOUT 0x0200 /* Lock cua opens on pgrp */
-#define ISDN_ASYNC_CALLOUT_NOHUP 0x0400 /* No hangup for cui */
-#define ISDN_ASYNC_SPLIT_TERMIOS 0x0008 /* Sep. termios for dialin/out */
#define ISDN_SERIAL_XMIT_SIZE 1024 /* Default bufsize for write */
#define ISDN_SERIAL_XMIT_MAX 4000 /* Maximum bufsize for write */
-#define ISDN_SERIAL_TYPE_NORMAL 1
-#define ISDN_SERIAL_TYPE_CALLOUT 2
#ifdef CONFIG_ISDN_AUDIO
/* For using sk_buffs with audio we need some private variables
@@ -448,17 +436,12 @@ typedef struct atemu {
/* Private data (similar to async_struct in <linux/serial.h>) */
typedef struct modem_info {
int magic;
- struct module *owner;
- int flags; /* defined in tty.h */
+ struct tty_port port;
int x_char; /* xon/xoff character */
int mcr; /* Modem control register */
int msr; /* Modem status register */
int lsr; /* Line status register */
int line;
- int count; /* # of fd on device */
- int blocked_open; /* # of blocked opens */
- long session; /* Session of opening process */
- long pgrp; /* pgrp of opening process */
int online; /* 1 = B-Channel is up, drop data */
/* 2 = B-Channel is up, deliver d.*/
int dialing; /* Dial in progress or ATA */
@@ -478,7 +461,6 @@ typedef struct modem_info {
int send_outstanding;/* # of outstanding send-requests */
int xmit_size; /* max. # of chars in xmit_buf */
int xmit_count; /* # of chars in xmit_buf */
- unsigned char *xmit_buf; /* transmit buffer */
struct sk_buff_head xmit_queue; /* transmit queue */
atomic_t xmit_lock; /* Semaphore for isdn_tty_write */
#ifdef CONFIG_ISDN_AUDIO
@@ -496,11 +478,7 @@ typedef struct modem_info {
struct T30_s *fax; /* T30 Fax Group 3 data/interface */
int faxonline; /* Fax-channel status */
#endif
- struct tty_struct *tty; /* Pointer to corresponding tty */
atemu emu; /* AT-emulator data */
- struct ktermios normal_termios; /* For saving termios structs */
- struct ktermios callout_termios;
- wait_queue_head_t open_wait, close_wait;
spinlock_t readlock;
} modem_info;
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 645231c373c8..c0d34420a913 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -480,15 +480,16 @@ do { \
#define trace_printk(fmt, args...) \
do { \
+ static const char *trace_printk_fmt \
+ __attribute__((section("__trace_printk_fmt"))) = \
+ __builtin_constant_p(fmt) ? fmt : NULL; \
+ \
__trace_printk_check_format(fmt, ##args); \
- if (__builtin_constant_p(fmt)) { \
- static const char *trace_printk_fmt \
- __attribute__((section("__trace_printk_fmt"))) = \
- __builtin_constant_p(fmt) ? fmt : NULL; \
\
+ if (__builtin_constant_p(fmt)) \
__trace_bprintk(_THIS_IP_, trace_printk_fmt, ##args); \
- } else \
- __trace_printk(_THIS_IP_, fmt, ##args); \
+ else \
+ __trace_printk(_THIS_IP_, fmt, ##args); \
} while (0)
extern __printf(2, 3)
diff --git a/include/linux/key.h b/include/linux/key.h
index 96933b1e5d24..5231800770e1 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -124,7 +124,10 @@ static inline unsigned long is_key_possessed(const key_ref_t key_ref)
struct key {
atomic_t usage; /* number of references */
key_serial_t serial; /* key serial number */
- struct rb_node serial_node;
+ union {
+ struct list_head graveyard_link;
+ struct rb_node serial_node;
+ };
struct key_type *type; /* type of key */
struct rw_semaphore sem; /* change vs change sem */
struct key_user *user; /* owner of this key */
@@ -133,6 +136,7 @@ struct key {
time_t expiry; /* time at which key expires (or 0) */
time_t revoked_at; /* time at which key was revoked */
};
+ time_t last_used_at; /* last time used for LRU keyring discard */
uid_t uid;
gid_t gid;
key_perm_t perm; /* access permissions */
@@ -156,6 +160,7 @@ struct key {
#define KEY_FLAG_USER_CONSTRUCT 4 /* set if key is being constructed in userspace */
#define KEY_FLAG_NEGATIVE 5 /* set if key is negative */
#define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */
+#define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */
/* the description string
* - this is used to match a key against search criteria
@@ -199,6 +204,7 @@ extern struct key *key_alloc(struct key_type *type,
#define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */
extern void key_revoke(struct key *key);
+extern void key_invalidate(struct key *key);
extern void key_put(struct key *key);
static inline struct key *key_get(struct key *key)
@@ -236,7 +242,7 @@ extern struct key *request_key_async_with_auxdata(struct key_type *type,
extern int wait_for_key_construction(struct key *key, bool intr);
-extern int key_validate(struct key *key);
+extern int key_validate(const struct key *key);
extern key_ref_t key_create_or_update(key_ref_t keyring,
const char *type,
@@ -319,6 +325,7 @@ extern void key_init(void);
#define key_serial(k) 0
#define key_get(k) ({ NULL; })
#define key_revoke(k) do { } while(0)
+#define key_invalidate(k) do { } while(0)
#define key_put(k) do { } while(0)
#define key_ref_put(k) do { } while(0)
#define make_key_ref(k, p) NULL
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
index 9b0b865ce622..c9b7f4faf97a 100644
--- a/include/linux/keyctl.h
+++ b/include/linux/keyctl.h
@@ -55,5 +55,6 @@
#define KEYCTL_SESSION_TO_PARENT 18 /* apply session keyring to parent process */
#define KEYCTL_REJECT 19 /* reject a partially constructed key */
#define KEYCTL_INSTANTIATE_IOV 20 /* instantiate a partially constructed key */
+#define KEYCTL_INVALIDATE 21 /* invalidate a key */
#endif /* _LINUX_KEYCTL_H */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index e926df7b54c9..6e887c742a27 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -247,6 +247,7 @@ enum {
ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host only */
ATA_HOST_STARTED = (1 << 1), /* Host started */
ATA_HOST_PARALLEL_SCAN = (1 << 2), /* Ports on this host can be scanned in parallel */
+ ATA_HOST_IGNORE_ATA = (1 << 3), /* Ignore ATA devices on this host. */
/* bits 24:31 of host->flags are reserved for LLD specific flags */
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index d36619ead3ba..00e46376e28f 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -157,6 +157,24 @@ struct lockdep_map {
#endif
};
+static inline void lockdep_copy_map(struct lockdep_map *to,
+ struct lockdep_map *from)
+{
+ int i;
+
+ *to = *from;
+ /*
+ * Since the class cache can be modified concurrently we could observe
+ * half pointers (64bit arch using 32bit copy insns). Therefore clear
+ * the caches and take the performance hit.
+ *
+ * XXX it doesn't work well with lockdep_set_class_and_subclass(), since
+ * that relies on cache abuse.
+ */
+ for (i = 0; i < NR_LOCKDEP_CACHING_CLASSES; i++)
+ to->class_cache[i] = NULL;
+}
+
/*
* Every lock has a list of other locks that were taken after it.
* We only grow the list, never remove from it:
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index fad48aab893b..1cc89e9df480 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -53,7 +53,6 @@ struct common_audit_data {
#define LSM_AUDIT_DATA_KMOD 8
#define LSM_AUDIT_DATA_INODE 9
#define LSM_AUDIT_DATA_DENTRY 10
- struct task_struct *tsk;
union {
struct path path;
struct dentry *dentry;
@@ -93,11 +92,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
int ipv6_skb_to_auditdata(struct sk_buff *skb,
struct common_audit_data *ad, u8 *proto);
-/* Initialize an LSM audit data structure. */
-#define COMMON_AUDIT_DATA_INIT(_d, _t) \
- { memset((_d), 0, sizeof(struct common_audit_data)); \
- (_d)->type = LSM_AUDIT_DATA_##_t; }
-
void common_lsm_audit(struct common_audit_data *a,
void (*pre_audit)(struct audit_buffer *, void *),
void (*post_audit)(struct audit_buffer *, void *));
diff --git a/drivers/staging/mei/mei.h b/include/linux/mei.h
index bc0d8b69c49e..bc0d8b69c49e 100644
--- a/drivers/staging/mei/mei.h
+++ b/include/linux/mei.h
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index ee96cd51d8b2..1318ca622633 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -6,7 +6,7 @@
*
* ABX500 core access functions.
* The abx500 interface is used for the Analog Baseband chip
- * ab3100, ab5500, and ab8500.
+ * ab3100 and ab8500.
*
* Author: Mattias Wallin <mattias.wallin@stericsson.com>
* Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
@@ -30,9 +30,6 @@ struct device;
#define AB3100_P1G 0xc6
#define AB3100_R2A 0xc7
#define AB3100_R2B 0xc8
-#define AB5500_1_0 0x20
-#define AB5500_1_1 0x21
-#define AB5500_2_0 0x24
/*
* AB3100, EVENTA1, A2 and A3 event register flags
diff --git a/include/linux/mfd/abx500/ab5500.h b/include/linux/mfd/abx500/ab5500.h
deleted file mode 100644
index 54f820ed73bb..000000000000
--- a/include/linux/mfd/abx500/ab5500.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson 2011
- *
- * License Terms: GNU General Public License v2
- */
-#ifndef MFD_AB5500_H
-#define MFD_AB5500_H
-
-struct device;
-
-enum ab5500_devid {
- AB5500_DEVID_ADC,
- AB5500_DEVID_LEDS,
- AB5500_DEVID_POWER,
- AB5500_DEVID_REGULATORS,
- AB5500_DEVID_SIM,
- AB5500_DEVID_RTC,
- AB5500_DEVID_CHARGER,
- AB5500_DEVID_FUELGAUGE,
- AB5500_DEVID_VIBRATOR,
- AB5500_DEVID_CODEC,
- AB5500_DEVID_USB,
- AB5500_DEVID_OTP,
- AB5500_DEVID_VIDEO,
- AB5500_DEVID_DBIECI,
- AB5500_DEVID_ONSWA,
- AB5500_NUM_DEVICES,
-};
-
-enum ab5500_banks {
- AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP = 0,
- AB5500_BANK_VDDDIG_IO_I2C_CLK_TST = 1,
- AB5500_BANK_VDENC = 2,
- AB5500_BANK_SIM_USBSIM = 3,
- AB5500_BANK_LED = 4,
- AB5500_BANK_ADC = 5,
- AB5500_BANK_RTC = 6,
- AB5500_BANK_STARTUP = 7,
- AB5500_BANK_DBI_ECI = 8,
- AB5500_BANK_CHG = 9,
- AB5500_BANK_FG_BATTCOM_ACC = 10,
- AB5500_BANK_USB = 11,
- AB5500_BANK_IT = 12,
- AB5500_BANK_VIBRA = 13,
- AB5500_BANK_AUDIO_HEADSETUSB = 14,
- AB5500_NUM_BANKS = 15,
-};
-
-enum ab5500_banks_addr {
- AB5500_ADDR_VIT_IO_I2C_CLK_TST_OTP = 0x4A,
- AB5500_ADDR_VDDDIG_IO_I2C_CLK_TST = 0x4B,
- AB5500_ADDR_VDENC = 0x06,
- AB5500_ADDR_SIM_USBSIM = 0x04,
- AB5500_ADDR_LED = 0x10,
- AB5500_ADDR_ADC = 0x0A,
- AB5500_ADDR_RTC = 0x0F,
- AB5500_ADDR_STARTUP = 0x03,
- AB5500_ADDR_DBI_ECI = 0x07,
- AB5500_ADDR_CHG = 0x0B,
- AB5500_ADDR_FG_BATTCOM_ACC = 0x0C,
- AB5500_ADDR_USB = 0x05,
- AB5500_ADDR_IT = 0x0E,
- AB5500_ADDR_VIBRA = 0x02,
- AB5500_ADDR_AUDIO_HEADSETUSB = 0x0D,
-};
-
-/*
- * Interrupt register offsets
- * Bank : 0x0E
- */
-#define AB5500_IT_SOURCE0_REG 0x20
-#define AB5500_IT_SOURCE1_REG 0x21
-#define AB5500_IT_SOURCE2_REG 0x22
-#define AB5500_IT_SOURCE3_REG 0x23
-#define AB5500_IT_SOURCE4_REG 0x24
-#define AB5500_IT_SOURCE5_REG 0x25
-#define AB5500_IT_SOURCE6_REG 0x26
-#define AB5500_IT_SOURCE7_REG 0x27
-#define AB5500_IT_SOURCE8_REG 0x28
-#define AB5500_IT_SOURCE9_REG 0x29
-#define AB5500_IT_SOURCE10_REG 0x2A
-#define AB5500_IT_SOURCE11_REG 0x2B
-#define AB5500_IT_SOURCE12_REG 0x2C
-#define AB5500_IT_SOURCE13_REG 0x2D
-#define AB5500_IT_SOURCE14_REG 0x2E
-#define AB5500_IT_SOURCE15_REG 0x2F
-#define AB5500_IT_SOURCE16_REG 0x30
-#define AB5500_IT_SOURCE17_REG 0x31
-#define AB5500_IT_SOURCE18_REG 0x32
-#define AB5500_IT_SOURCE19_REG 0x33
-#define AB5500_IT_SOURCE20_REG 0x34
-#define AB5500_IT_SOURCE21_REG 0x35
-#define AB5500_IT_SOURCE22_REG 0x36
-#define AB5500_IT_SOURCE23_REG 0x37
-
-#define AB5500_NUM_IRQ_REGS 23
-
-/**
- * struct ab5500
- * @access_mutex: lock out concurrent accesses to the AB registers
- * @dev: a pointer to the device struct for this chip driver
- * @ab5500_irq: the analog baseband irq
- * @irq_base: the platform configuration irq base for subdevices
- * @chip_name: name of this chip variant
- * @chip_id: 8 bit chip ID for this chip variant
- * @irq_lock: a lock to protect the mask
- * @abb_events: a local bit mask of the prcmu wakeup events
- * @event_mask: a local copy of the mask event registers
- * @last_event_mask: a copy of the last event_mask written to hardware
- * @startup_events: a copy of the first reading of the event registers
- * @startup_events_read: whether the first events have been read
- */
-struct ab5500 {
- struct mutex access_mutex;
- struct device *dev;
- unsigned int ab5500_irq;
- unsigned int irq_base;
- char chip_name[32];
- u8 chip_id;
- struct mutex irq_lock;
- u32 abb_events;
- u8 mask[AB5500_NUM_IRQ_REGS];
- u8 oldmask[AB5500_NUM_IRQ_REGS];
- u8 startup_events[AB5500_NUM_IRQ_REGS];
- bool startup_events_read;
-#ifdef CONFIG_DEBUG_FS
- unsigned int debug_bank;
- unsigned int debug_address;
-#endif
-};
-
-struct ab5500_platform_data {
- struct {unsigned int base; unsigned int count; } irq;
- void *dev_data[AB5500_NUM_DEVICES];
- struct abx500_init_settings *init_settings;
- unsigned int init_settings_sz;
- bool pm_power_off;
-};
-
-#endif /* MFD_AB5500_H */
diff --git a/include/linux/mfd/asic3.h b/include/linux/mfd/asic3.h
index ed793b77a1c5..ef6faa5cee46 100644
--- a/include/linux/mfd/asic3.h
+++ b/include/linux/mfd/asic3.h
@@ -138,6 +138,7 @@ struct asic3_platform_data {
#define ASIC3_GPIOC13_nPWAIT ASIC3_CONFIG_GPIO(45, 1, 1, 0)
#define ASIC3_GPIOC14_nPIOIS16 ASIC3_CONFIG_GPIO(46, 1, 1, 0)
#define ASIC3_GPIOC15_nPIOR ASIC3_CONFIG_GPIO(47, 1, 0, 0)
+#define ASIC3_GPIOD4_CF_nCD ASIC3_CONFIG_GPIO(52, 1, 0, 0)
#define ASIC3_GPIOD11_nCIOIS16 ASIC3_CONFIG_GPIO(59, 1, 0, 0)
#define ASIC3_GPIOD12_nCWAIT ASIC3_CONFIG_GPIO(60, 1, 0, 0)
#define ASIC3_GPIOD15_nPIOW ASIC3_CONFIG_GPIO(63, 1, 0, 0)
diff --git a/include/linux/mfd/da9052/da9052.h b/include/linux/mfd/da9052/da9052.h
index 7ffbd6e9e7fc..8313cd9658e3 100644
--- a/include/linux/mfd/da9052/da9052.h
+++ b/include/linux/mfd/da9052/da9052.h
@@ -80,6 +80,7 @@ struct da9052 {
struct regmap *regmap;
int irq_base;
+ struct regmap_irq_chip_data *irq_data;
u8 chip_id;
int chip_irq;
diff --git a/include/linux/mfd/db5500-prcmu.h b/include/linux/mfd/db5500-prcmu.h
deleted file mode 100644
index 5a049dfaf153..000000000000
--- a/include/linux/mfd/db5500-prcmu.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License v2
- *
- * U5500 PRCMU API.
- */
-#ifndef __MFD_DB5500_PRCMU_H
-#define __MFD_DB5500_PRCMU_H
-
-static inline int prcmu_resetout(u8 resoutn, u8 state)
-{
- return 0;
-}
-
-static inline int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state)
-{
- return 0;
-}
-
-static inline int db5500_prcmu_request_clock(u8 clock, bool enable)
-{
- return 0;
-}
-
-static inline int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
- bool keep_ap_pll)
-{
- return 0;
-}
-
-static inline int db5500_prcmu_config_esram0_deep_sleep(u8 state)
-{
- return 0;
-}
-
-static inline u16 db5500_prcmu_get_reset_code(void)
-{
- return 0;
-}
-
-static inline bool db5500_prcmu_is_ac_wake_requested(void)
-{
- return 0;
-}
-
-static inline int db5500_prcmu_set_arm_opp(u8 opp)
-{
- return 0;
-}
-
-static inline int db5500_prcmu_get_arm_opp(void)
-{
- return 0;
-}
-
-static inline void db5500_prcmu_config_abb_event_readout(u32 abb_events) {}
-
-static inline void db5500_prcmu_get_abb_event_buffer(void __iomem **buf) {}
-
-static inline void db5500_prcmu_system_reset(u16 reset_code) {}
-
-static inline void db5500_prcmu_enable_wakeups(u32 wakeups) {}
-
-#ifdef CONFIG_MFD_DB5500_PRCMU
-
-void db5500_prcmu_early_init(void);
-int db5500_prcmu_set_display_clocks(void);
-int db5500_prcmu_disable_dsipll(void);
-int db5500_prcmu_enable_dsipll(void);
-int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
-int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
-
-#else /* !CONFIG_UX500_SOC_DB5500 */
-
-static inline void db5500_prcmu_early_init(void) {}
-
-static inline int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
-{
- return -ENOSYS;
-}
-
-static inline int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
-{
- return -ENOSYS;
-}
-
-static inline int db5500_prcmu_set_display_clocks(void)
-{
- return 0;
-}
-
-static inline int db5500_prcmu_disable_dsipll(void)
-{
- return 0;
-}
-
-static inline int db5500_prcmu_enable_dsipll(void)
-{
- return 0;
-}
-
-#endif /* CONFIG_MFD_DB5500_PRCMU */
-
-#endif /* __MFD_DB5500_PRCMU_H */
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
index d7674eb7305f..5a13f93d8f1c 100644
--- a/include/linux/mfd/dbx500-prcmu.h
+++ b/include/linux/mfd/dbx500-prcmu.h
@@ -55,17 +55,6 @@ enum prcmu_wakeup_index {
#define NUM_EPOD_ID 8
/*
- * DB5500 EPODs
- */
-#define DB5500_EPOD_ID_BASE 0x0100
-#define DB5500_EPOD_ID_SGA (DB5500_EPOD_ID_BASE + 0)
-#define DB5500_EPOD_ID_HVA (DB5500_EPOD_ID_BASE + 1)
-#define DB5500_EPOD_ID_SIA (DB5500_EPOD_ID_BASE + 2)
-#define DB5500_EPOD_ID_DISP (DB5500_EPOD_ID_BASE + 3)
-#define DB5500_EPOD_ID_ESRAM12 (DB5500_EPOD_ID_BASE + 6)
-#define DB5500_NUM_EPOD_ID 7
-
-/*
* state definition for EPOD (power domain)
* - EPOD_STATE_NO_CHANGE: The EPOD should remain unchanged
* - EPOD_STATE_OFF: The EPOD is switched off
@@ -80,29 +69,6 @@ enum prcmu_wakeup_index {
#define EPOD_STATE_ON_CLK_OFF 0x03
#define EPOD_STATE_ON 0x04
-/* DB5500 CLKOUT IDs */
-enum {
- DB5500_CLKOUT0 = 0,
- DB5500_CLKOUT1,
-};
-
-/* DB5500 CLKOUTx sources */
-enum {
- DB5500_CLKOUT_REF_CLK_SEL0,
- DB5500_CLKOUT_RTC_CLK0_SEL0,
- DB5500_CLKOUT_ULP_CLK_SEL0,
- DB5500_CLKOUT_STATIC0,
- DB5500_CLKOUT_REFCLK,
- DB5500_CLKOUT_ULPCLK,
- DB5500_CLKOUT_ARMCLK,
- DB5500_CLKOUT_SYSACC0CLK,
- DB5500_CLKOUT_SOC0PLLCLK,
- DB5500_CLKOUT_SOC1PLLCLK,
- DB5500_CLKOUT_DDRPLLCLK,
- DB5500_CLKOUT_TVCLK,
- DB5500_CLKOUT_IRDACLK,
-};
-
/*
* CLKOUT sources
*/
@@ -248,101 +214,66 @@ enum ddr_pwrst {
};
#include <linux/mfd/db8500-prcmu.h>
-#include <linux/mfd/db5500-prcmu.h>
-#if defined(CONFIG_UX500_SOC_DB8500) || defined(CONFIG_UX500_SOC_DB5500)
+#if defined(CONFIG_UX500_SOC_DB8500)
#include <mach/id.h>
static inline void __init prcmu_early_init(void)
{
- if (cpu_is_u5500())
- return db5500_prcmu_early_init();
- else
- return db8500_prcmu_early_init();
+ return db8500_prcmu_early_init();
}
static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
bool keep_ap_pll)
{
- if (cpu_is_u5500())
- return db5500_prcmu_set_power_state(state, keep_ulp_clk,
- keep_ap_pll);
- else
- return db8500_prcmu_set_power_state(state, keep_ulp_clk,
- keep_ap_pll);
+ return db8500_prcmu_set_power_state(state, keep_ulp_clk,
+ keep_ap_pll);
}
static inline u8 prcmu_get_power_state_result(void)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_get_power_state_result();
+ return db8500_prcmu_get_power_state_result();
}
static inline int prcmu_gic_decouple(void)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_gic_decouple();
+ return db8500_prcmu_gic_decouple();
}
static inline int prcmu_gic_recouple(void)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_gic_recouple();
+ return db8500_prcmu_gic_recouple();
}
static inline bool prcmu_gic_pending_irq(void)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_gic_pending_irq();
+ return db8500_prcmu_gic_pending_irq();
}
static inline bool prcmu_is_cpu_in_wfi(int cpu)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_is_cpu_in_wfi(cpu);
+ return db8500_prcmu_is_cpu_in_wfi(cpu);
}
static inline int prcmu_copy_gic_settings(void)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_copy_gic_settings();
+ return db8500_prcmu_copy_gic_settings();
}
static inline bool prcmu_pending_irq(void)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_pending_irq();
+ return db8500_prcmu_pending_irq();
}
static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_set_epod(epod_id, epod_state);
+ return db8500_prcmu_set_epod(epod_id, epod_state);
}
static inline void prcmu_enable_wakeups(u32 wakeups)
{
- if (cpu_is_u5500())
- db5500_prcmu_enable_wakeups(wakeups);
- else
- db8500_prcmu_enable_wakeups(wakeups);
+ db8500_prcmu_enable_wakeups(wakeups);
}
static inline void prcmu_disable_wakeups(void)
@@ -352,18 +283,12 @@ static inline void prcmu_disable_wakeups(void)
static inline void prcmu_config_abb_event_readout(u32 abb_events)
{
- if (cpu_is_u5500())
- db5500_prcmu_config_abb_event_readout(abb_events);
- else
- db8500_prcmu_config_abb_event_readout(abb_events);
+ db8500_prcmu_config_abb_event_readout(abb_events);
}
static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
{
- if (cpu_is_u5500())
- db5500_prcmu_get_abb_event_buffer(buf);
- else
- db8500_prcmu_get_abb_event_buffer(buf);
+ db8500_prcmu_get_abb_event_buffer(buf);
}
int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
@@ -374,10 +299,7 @@ int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
static inline int prcmu_request_clock(u8 clock, bool enable)
{
- if (cpu_is_u5500())
- return db5500_prcmu_request_clock(clock, enable);
- else
- return db8500_prcmu_request_clock(clock, enable);
+ return db8500_prcmu_request_clock(clock, enable);
}
unsigned long prcmu_clock_rate(u8 clock);
@@ -386,211 +308,133 @@ int prcmu_set_clock_rate(u8 clock, unsigned long rate);
static inline int prcmu_set_ddr_opp(u8 opp)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_set_ddr_opp(opp);
+ return db8500_prcmu_set_ddr_opp(opp);
}
static inline int prcmu_get_ddr_opp(void)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_get_ddr_opp();
+ return db8500_prcmu_get_ddr_opp();
}
static inline int prcmu_set_arm_opp(u8 opp)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_set_arm_opp(opp);
+ return db8500_prcmu_set_arm_opp(opp);
}
static inline int prcmu_get_arm_opp(void)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_get_arm_opp();
+ return db8500_prcmu_get_arm_opp();
}
static inline int prcmu_set_ape_opp(u8 opp)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_set_ape_opp(opp);
+ return db8500_prcmu_set_ape_opp(opp);
}
static inline int prcmu_get_ape_opp(void)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_get_ape_opp();
+ return db8500_prcmu_get_ape_opp();
}
static inline void prcmu_system_reset(u16 reset_code)
{
- if (cpu_is_u5500())
- return db5500_prcmu_system_reset(reset_code);
- else
- return db8500_prcmu_system_reset(reset_code);
+ return db8500_prcmu_system_reset(reset_code);
}
static inline u16 prcmu_get_reset_code(void)
{
- if (cpu_is_u5500())
- return db5500_prcmu_get_reset_code();
- else
- return db8500_prcmu_get_reset_code();
+ return db8500_prcmu_get_reset_code();
}
void prcmu_ac_wake_req(void);
void prcmu_ac_sleep_req(void);
static inline void prcmu_modem_reset(void)
{
- if (cpu_is_u5500())
- return;
- else
- return db8500_prcmu_modem_reset();
+ return db8500_prcmu_modem_reset();
}
static inline bool prcmu_is_ac_wake_requested(void)
{
- if (cpu_is_u5500())
- return db5500_prcmu_is_ac_wake_requested();
- else
- return db8500_prcmu_is_ac_wake_requested();
+ return db8500_prcmu_is_ac_wake_requested();
}
static inline int prcmu_set_display_clocks(void)
{
- if (cpu_is_u5500())
- return db5500_prcmu_set_display_clocks();
- else
- return db8500_prcmu_set_display_clocks();
+ return db8500_prcmu_set_display_clocks();
}
static inline int prcmu_disable_dsipll(void)
{
- if (cpu_is_u5500())
- return db5500_prcmu_disable_dsipll();
- else
- return db8500_prcmu_disable_dsipll();
+ return db8500_prcmu_disable_dsipll();
}
static inline int prcmu_enable_dsipll(void)
{
- if (cpu_is_u5500())
- return db5500_prcmu_enable_dsipll();
- else
- return db8500_prcmu_enable_dsipll();
+ return db8500_prcmu_enable_dsipll();
}
static inline int prcmu_config_esram0_deep_sleep(u8 state)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_config_esram0_deep_sleep(state);
+ return db8500_prcmu_config_esram0_deep_sleep(state);
}
static inline int prcmu_config_hotdog(u8 threshold)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_config_hotdog(threshold);
+ return db8500_prcmu_config_hotdog(threshold);
}
static inline int prcmu_config_hotmon(u8 low, u8 high)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_config_hotmon(low, high);
+ return db8500_prcmu_config_hotmon(low, high);
}
static inline int prcmu_start_temp_sense(u16 cycles32k)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_start_temp_sense(cycles32k);
+ return db8500_prcmu_start_temp_sense(cycles32k);
}
static inline int prcmu_stop_temp_sense(void)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_stop_temp_sense();
+ return db8500_prcmu_stop_temp_sense();
}
static inline u32 prcmu_read(unsigned int reg)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_read(reg);
+ return db8500_prcmu_read(reg);
}
static inline void prcmu_write(unsigned int reg, u32 value)
{
- if (cpu_is_u5500())
- return;
- else
- db8500_prcmu_write(reg, value);
+ db8500_prcmu_write(reg, value);
}
static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
{
- if (cpu_is_u5500())
- return;
- else
- db8500_prcmu_write_masked(reg, mask, value);
+ db8500_prcmu_write_masked(reg, mask, value);
}
static inline int prcmu_enable_a9wdog(u8 id)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_enable_a9wdog(id);
+ return db8500_prcmu_enable_a9wdog(id);
}
static inline int prcmu_disable_a9wdog(u8 id)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_disable_a9wdog(id);
+ return db8500_prcmu_disable_a9wdog(id);
}
static inline int prcmu_kick_a9wdog(u8 id)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_kick_a9wdog(id);
+ return db8500_prcmu_kick_a9wdog(id);
}
static inline int prcmu_load_a9wdog(u8 id, u32 timeout)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_load_a9wdog(id, timeout);
+ return db8500_prcmu_load_a9wdog(id, timeout);
}
static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
{
- if (cpu_is_u5500())
- return -EINVAL;
- else
- return db8500_prcmu_config_a9wdog(num, sleep_auto_off);
+ return db8500_prcmu_config_a9wdog(num, sleep_auto_off);
}
#else
@@ -768,7 +612,7 @@ static inline void prcmu_clear(unsigned int reg, u32 bits)
prcmu_write_masked(reg, bits, 0);
}
-#if defined(CONFIG_UX500_SOC_DB8500) || defined(CONFIG_UX500_SOC_DB5500)
+#if defined(CONFIG_UX500_SOC_DB8500)
/**
* prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1.
diff --git a/include/linux/mfd/max8997.h b/include/linux/mfd/max8997.h
index 28726dd540f2..b40c08cd30bc 100644
--- a/include/linux/mfd/max8997.h
+++ b/include/linux/mfd/max8997.h
@@ -99,34 +99,11 @@ struct max8997_muic_reg_data {
/**
* struct max8997_muic_platform_data
- * @usb_callback: callback function for USB
- * inform callee of USB type (HOST or DEVICE)
- * and attached state(true or false)
- * @charger_callback: callback function for charger
- * inform callee of charger_type
- * and attached state(true or false)
- * @deskdock_callback: callback function for desk dock
- * inform callee of attached state(true or false)
- * @cardock_callback: callback function for car dock
- * inform callee of attached state(true or false)
- * @mhl_callback: callback function for MHL (Mobile High-definition Link)
- * inform callee of attached state(true or false)
- * @uart_callback: callback function for JIG UART
- * inform callee of attached state(true or false)
* @init_data: array of max8997_muic_reg_data
* used for initializing registers of MAX8997 MUIC device
* @num_init_data: array size of init_data
*/
struct max8997_muic_platform_data {
- void (*usb_callback)(enum max8997_muic_usb_type usb_type,
- bool attached);
- void (*charger_callback)(bool attached,
- enum max8997_muic_charger_type charger_type);
- void (*deskdock_callback) (bool attached);
- void (*cardock_callback) (bool attached);
- void (*mhl_callback) (bool attached);
- void (*uart_callback) (bool attached);
-
struct max8997_muic_reg_data *init_data;
int num_init_data;
};
diff --git a/include/linux/mfd/mc13xxx.h b/include/linux/mfd/mc13xxx.h
index 10e038bac8dd..bf070755982e 100644
--- a/include/linux/mfd/mc13xxx.h
+++ b/include/linux/mfd/mc13xxx.h
@@ -170,6 +170,16 @@ struct mc13xxx_ts_platform_data {
bool atox;
};
+enum mc13783_ssi_port {
+ MC13783_SSI1_PORT,
+ MC13783_SSI2_PORT,
+};
+
+struct mc13xxx_codec_platform_data {
+ enum mc13783_ssi_port adc_ssi_port;
+ enum mc13783_ssi_port dac_ssi_port;
+};
+
struct mc13xxx_platform_data {
#define MC13XXX_USE_TOUCHSCREEN (1 << 0)
#define MC13XXX_USE_CODEC (1 << 1)
@@ -181,6 +191,7 @@ struct mc13xxx_platform_data {
struct mc13xxx_leds_platform_data *leds;
struct mc13xxx_buttons_platform_data *buttons;
struct mc13xxx_ts_platform_data touch;
+ struct mc13xxx_codec_platform_data *codec;
};
#define MC13XXX_ADC_MODE_TS 1
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
new file mode 100644
index 000000000000..9cbc642d40ad
--- /dev/null
+++ b/include/linux/mfd/palmas.h
@@ -0,0 +1,2620 @@
+/*
+ * TI Palmas
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_PALMAS_H
+#define __LINUX_MFD_PALMAS_H
+
+#include <linux/usb/otg.h>
+#include <linux/leds.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+#define PALMAS_NUM_CLIENTS 3
+
+struct palmas_pmic;
+
+struct palmas {
+ struct device *dev;
+
+ struct i2c_client *i2c_clients[PALMAS_NUM_CLIENTS];
+ struct regmap *regmap[PALMAS_NUM_CLIENTS];
+
+ /* Stored chip id */
+ int id;
+
+ /* IRQ Data */
+ int irq;
+ u32 irq_mask;
+ struct mutex irq_lock;
+ struct regmap_irq_chip_data *irq_data;
+
+ /* Child Devices */
+ struct palmas_pmic *pmic;
+
+ /* GPIO MUXing */
+ u8 gpio_muxed;
+ u8 led_muxed;
+ u8 pwm_muxed;
+};
+
+struct palmas_reg_init {
+ /* warm_rest controls the voltage levels after a warm reset
+ *
+ * 0: reload default values from OTP on warm reset
+ * 1: maintain voltage from VSEL on warm reset
+ */
+ int warm_reset;
+
+ /* roof_floor controls whether the regulator uses the i2c style
+ * of DVS or uses the method where a GPIO or other control method is
+ * attached to the NSLEEP/ENABLE1/ENABLE2 pins
+ *
+ * For SMPS
+ *
+ * 0: i2c selection of voltage
+ * 1: pin selection of voltage.
+ *
+ * For LDO unused
+ */
+ int roof_floor;
+
+ /* sleep_mode is the mode loaded to MODE_SLEEP bits as defined in
+ * the data sheet.
+ *
+ * For SMPS
+ *
+ * 0: Off
+ * 1: AUTO
+ * 2: ECO
+ * 3: Forced PWM
+ *
+ * For LDO
+ *
+ * 0: Off
+ * 1: On
+ */
+ int mode_sleep;
+
+ /* tstep is the timestep loaded to the TSTEP register
+ *
+ * For SMPS
+ *
+ * 0: Jump (no slope control)
+ * 1: 10mV/us
+ * 2: 5mV/us
+ * 3: 2.5mV/us
+ *
+ * For LDO unused
+ */
+ int tstep;
+
+ /* voltage_sel is the bitfield loaded onto the SMPSX_VOLTAGE
+ * register. Set this is the default voltage set in OTP needs
+ * to be overridden.
+ */
+ u8 vsel;
+
+};
+
+struct palmas_pmic_platform_data {
+ /* An array of pointers to regulator init data indexed by regulator
+ * ID
+ */
+ struct regulator_init_data **reg_data;
+
+ /* An array of pointers to structures containing sleep mode and DVS
+ * configuration for regulators indexed by ID
+ */
+ struct palmas_reg_init **reg_init;
+
+ /* use LDO6 for vibrator control */
+ int ldo6_vibrator;
+
+
+};
+
+struct palmas_platform_data {
+ int gpio_base;
+
+ /* bit value to be loaded to the POWER_CTRL register */
+ u8 power_ctrl;
+
+ /*
+ * boolean to select if we want to configure muxing here
+ * then the two value to load into the registers if true
+ */
+ int mux_from_pdata;
+ u8 pad1, pad2;
+
+ struct palmas_pmic_platform_data *pmic_pdata;
+};
+
+/* Define the palmas IRQ numbers */
+enum palmas_irqs {
+ /* INT1 registers */
+ PALMAS_CHARG_DET_N_VBUS_OVV_IRQ,
+ PALMAS_PWRON_IRQ,
+ PALMAS_LONG_PRESS_KEY_IRQ,
+ PALMAS_RPWRON_IRQ,
+ PALMAS_PWRDOWN_IRQ,
+ PALMAS_HOTDIE_IRQ,
+ PALMAS_VSYS_MON_IRQ,
+ PALMAS_VBAT_MON_IRQ,
+ /* INT2 registers */
+ PALMAS_RTC_ALARM_IRQ,
+ PALMAS_RTC_TIMER_IRQ,
+ PALMAS_WDT_IRQ,
+ PALMAS_BATREMOVAL_IRQ,
+ PALMAS_RESET_IN_IRQ,
+ PALMAS_FBI_BB_IRQ,
+ PALMAS_SHORT_IRQ,
+ PALMAS_VAC_ACOK_IRQ,
+ /* INT3 registers */
+ PALMAS_GPADC_AUTO_0_IRQ,
+ PALMAS_GPADC_AUTO_1_IRQ,
+ PALMAS_GPADC_EOC_SW_IRQ,
+ PALMAS_GPADC_EOC_RT_IRQ,
+ PALMAS_ID_OTG_IRQ,
+ PALMAS_ID_IRQ,
+ PALMAS_VBUS_OTG_IRQ,
+ PALMAS_VBUS_IRQ,
+ /* INT4 registers */
+ PALMAS_GPIO_0_IRQ,
+ PALMAS_GPIO_1_IRQ,
+ PALMAS_GPIO_2_IRQ,
+ PALMAS_GPIO_3_IRQ,
+ PALMAS_GPIO_4_IRQ,
+ PALMAS_GPIO_5_IRQ,
+ PALMAS_GPIO_6_IRQ,
+ PALMAS_GPIO_7_IRQ,
+ /* Total Number IRQs */
+ PALMAS_NUM_IRQ,
+};
+
+enum palmas_regulators {
+ /* SMPS regulators */
+ PALMAS_REG_SMPS12,
+ PALMAS_REG_SMPS123,
+ PALMAS_REG_SMPS3,
+ PALMAS_REG_SMPS45,
+ PALMAS_REG_SMPS457,
+ PALMAS_REG_SMPS6,
+ PALMAS_REG_SMPS7,
+ PALMAS_REG_SMPS8,
+ PALMAS_REG_SMPS9,
+ PALMAS_REG_SMPS10,
+ /* LDO regulators */
+ PALMAS_REG_LDO1,
+ PALMAS_REG_LDO2,
+ PALMAS_REG_LDO3,
+ PALMAS_REG_LDO4,
+ PALMAS_REG_LDO5,
+ PALMAS_REG_LDO6,
+ PALMAS_REG_LDO7,
+ PALMAS_REG_LDO8,
+ PALMAS_REG_LDO9,
+ PALMAS_REG_LDOLN,
+ PALMAS_REG_LDOUSB,
+ /* Total number of regulators */
+ PALMAS_NUM_REGS,
+};
+
+struct palmas_pmic {
+ struct palmas *palmas;
+ struct device *dev;
+ struct regulator_desc desc[PALMAS_NUM_REGS];
+ struct regulator_dev *rdev[PALMAS_NUM_REGS];
+ struct mutex mutex;
+
+ int smps123;
+ int smps457;
+
+ int range[PALMAS_REG_SMPS10];
+};
+
+/* defines so we can store the mux settings */
+#define PALMAS_GPIO_0_MUXED (1 << 0)
+#define PALMAS_GPIO_1_MUXED (1 << 1)
+#define PALMAS_GPIO_2_MUXED (1 << 2)
+#define PALMAS_GPIO_3_MUXED (1 << 3)
+#define PALMAS_GPIO_4_MUXED (1 << 4)
+#define PALMAS_GPIO_5_MUXED (1 << 5)
+#define PALMAS_GPIO_6_MUXED (1 << 6)
+#define PALMAS_GPIO_7_MUXED (1 << 7)
+
+#define PALMAS_LED1_MUXED (1 << 0)
+#define PALMAS_LED2_MUXED (1 << 1)
+
+#define PALMAS_PWM1_MUXED (1 << 0)
+#define PALMAS_PWM2_MUXED (1 << 1)
+
+/* helper macro to get correct slave number */
+#define PALMAS_BASE_TO_SLAVE(x) ((x >> 8) - 1)
+#define PALMAS_BASE_TO_REG(x, y) ((x & 0xff) + y)
+
+/* Base addresses of IP blocks in Palmas */
+#define PALMAS_SMPS_DVS_BASE 0x20
+#define PALMAS_RTC_BASE 0x100
+#define PALMAS_VALIDITY_BASE 0x118
+#define PALMAS_SMPS_BASE 0x120
+#define PALMAS_LDO_BASE 0x150
+#define PALMAS_DVFS_BASE 0x180
+#define PALMAS_PMU_CONTROL_BASE 0x1A0
+#define PALMAS_RESOURCE_BASE 0x1D4
+#define PALMAS_PU_PD_OD_BASE 0x1F4
+#define PALMAS_LED_BASE 0x200
+#define PALMAS_INTERRUPT_BASE 0x210
+#define PALMAS_USB_OTG_BASE 0x250
+#define PALMAS_VIBRATOR_BASE 0x270
+#define PALMAS_GPIO_BASE 0x280
+#define PALMAS_USB_BASE 0x290
+#define PALMAS_GPADC_BASE 0x2C0
+#define PALMAS_TRIM_GPADC_BASE 0x3CD
+
+/* Registers for function RTC */
+#define PALMAS_SECONDS_REG 0x0
+#define PALMAS_MINUTES_REG 0x1
+#define PALMAS_HOURS_REG 0x2
+#define PALMAS_DAYS_REG 0x3
+#define PALMAS_MONTHS_REG 0x4
+#define PALMAS_YEARS_REG 0x5
+#define PALMAS_WEEKS_REG 0x6
+#define PALMAS_ALARM_SECONDS_REG 0x8
+#define PALMAS_ALARM_MINUTES_REG 0x9
+#define PALMAS_ALARM_HOURS_REG 0xA
+#define PALMAS_ALARM_DAYS_REG 0xB
+#define PALMAS_ALARM_MONTHS_REG 0xC
+#define PALMAS_ALARM_YEARS_REG 0xD
+#define PALMAS_RTC_CTRL_REG 0x10
+#define PALMAS_RTC_STATUS_REG 0x11
+#define PALMAS_RTC_INTERRUPTS_REG 0x12
+#define PALMAS_RTC_COMP_LSB_REG 0x13
+#define PALMAS_RTC_COMP_MSB_REG 0x14
+#define PALMAS_RTC_RES_PROG_REG 0x15
+#define PALMAS_RTC_RESET_STATUS_REG 0x16
+
+/* Bit definitions for SECONDS_REG */
+#define PALMAS_SECONDS_REG_SEC1_MASK 0x70
+#define PALMAS_SECONDS_REG_SEC1_SHIFT 4
+#define PALMAS_SECONDS_REG_SEC0_MASK 0x0f
+#define PALMAS_SECONDS_REG_SEC0_SHIFT 0
+
+/* Bit definitions for MINUTES_REG */
+#define PALMAS_MINUTES_REG_MIN1_MASK 0x70
+#define PALMAS_MINUTES_REG_MIN1_SHIFT 4
+#define PALMAS_MINUTES_REG_MIN0_MASK 0x0f
+#define PALMAS_MINUTES_REG_MIN0_SHIFT 0
+
+/* Bit definitions for HOURS_REG */
+#define PALMAS_HOURS_REG_PM_NAM 0x80
+#define PALMAS_HOURS_REG_PM_NAM_SHIFT 7
+#define PALMAS_HOURS_REG_HOUR1_MASK 0x30
+#define PALMAS_HOURS_REG_HOUR1_SHIFT 4
+#define PALMAS_HOURS_REG_HOUR0_MASK 0x0f
+#define PALMAS_HOURS_REG_HOUR0_SHIFT 0
+
+/* Bit definitions for DAYS_REG */
+#define PALMAS_DAYS_REG_DAY1_MASK 0x30
+#define PALMAS_DAYS_REG_DAY1_SHIFT 4
+#define PALMAS_DAYS_REG_DAY0_MASK 0x0f
+#define PALMAS_DAYS_REG_DAY0_SHIFT 0
+
+/* Bit definitions for MONTHS_REG */
+#define PALMAS_MONTHS_REG_MONTH1 0x10
+#define PALMAS_MONTHS_REG_MONTH1_SHIFT 4
+#define PALMAS_MONTHS_REG_MONTH0_MASK 0x0f
+#define PALMAS_MONTHS_REG_MONTH0_SHIFT 0
+
+/* Bit definitions for YEARS_REG */
+#define PALMAS_YEARS_REG_YEAR1_MASK 0xf0
+#define PALMAS_YEARS_REG_YEAR1_SHIFT 4
+#define PALMAS_YEARS_REG_YEAR0_MASK 0x0f
+#define PALMAS_YEARS_REG_YEAR0_SHIFT 0
+
+/* Bit definitions for WEEKS_REG */
+#define PALMAS_WEEKS_REG_WEEK_MASK 0x07
+#define PALMAS_WEEKS_REG_WEEK_SHIFT 0
+
+/* Bit definitions for ALARM_SECONDS_REG */
+#define PALMAS_ALARM_SECONDS_REG_ALARM_SEC1_MASK 0x70
+#define PALMAS_ALARM_SECONDS_REG_ALARM_SEC1_SHIFT 4
+#define PALMAS_ALARM_SECONDS_REG_ALARM_SEC0_MASK 0x0f
+#define PALMAS_ALARM_SECONDS_REG_ALARM_SEC0_SHIFT 0
+
+/* Bit definitions for ALARM_MINUTES_REG */
+#define PALMAS_ALARM_MINUTES_REG_ALARM_MIN1_MASK 0x70
+#define PALMAS_ALARM_MINUTES_REG_ALARM_MIN1_SHIFT 4
+#define PALMAS_ALARM_MINUTES_REG_ALARM_MIN0_MASK 0x0f
+#define PALMAS_ALARM_MINUTES_REG_ALARM_MIN0_SHIFT 0
+
+/* Bit definitions for ALARM_HOURS_REG */
+#define PALMAS_ALARM_HOURS_REG_ALARM_PM_NAM 0x80
+#define PALMAS_ALARM_HOURS_REG_ALARM_PM_NAM_SHIFT 7
+#define PALMAS_ALARM_HOURS_REG_ALARM_HOUR1_MASK 0x30
+#define PALMAS_ALARM_HOURS_REG_ALARM_HOUR1_SHIFT 4
+#define PALMAS_ALARM_HOURS_REG_ALARM_HOUR0_MASK 0x0f
+#define PALMAS_ALARM_HOURS_REG_ALARM_HOUR0_SHIFT 0
+
+/* Bit definitions for ALARM_DAYS_REG */
+#define PALMAS_ALARM_DAYS_REG_ALARM_DAY1_MASK 0x30
+#define PALMAS_ALARM_DAYS_REG_ALARM_DAY1_SHIFT 4
+#define PALMAS_ALARM_DAYS_REG_ALARM_DAY0_MASK 0x0f
+#define PALMAS_ALARM_DAYS_REG_ALARM_DAY0_SHIFT 0
+
+/* Bit definitions for ALARM_MONTHS_REG */
+#define PALMAS_ALARM_MONTHS_REG_ALARM_MONTH1 0x10
+#define PALMAS_ALARM_MONTHS_REG_ALARM_MONTH1_SHIFT 4
+#define PALMAS_ALARM_MONTHS_REG_ALARM_MONTH0_MASK 0x0f
+#define PALMAS_ALARM_MONTHS_REG_ALARM_MONTH0_SHIFT 0
+
+/* Bit definitions for ALARM_YEARS_REG */
+#define PALMAS_ALARM_YEARS_REG_ALARM_YEAR1_MASK 0xf0
+#define PALMAS_ALARM_YEARS_REG_ALARM_YEAR1_SHIFT 4
+#define PALMAS_ALARM_YEARS_REG_ALARM_YEAR0_MASK 0x0f
+#define PALMAS_ALARM_YEARS_REG_ALARM_YEAR0_SHIFT 0
+
+/* Bit definitions for RTC_CTRL_REG */
+#define PALMAS_RTC_CTRL_REG_RTC_V_OPT 0x80
+#define PALMAS_RTC_CTRL_REG_RTC_V_OPT_SHIFT 7
+#define PALMAS_RTC_CTRL_REG_GET_TIME 0x40
+#define PALMAS_RTC_CTRL_REG_GET_TIME_SHIFT 6
+#define PALMAS_RTC_CTRL_REG_SET_32_COUNTER 0x20
+#define PALMAS_RTC_CTRL_REG_SET_32_COUNTER_SHIFT 5
+#define PALMAS_RTC_CTRL_REG_TEST_MODE 0x10
+#define PALMAS_RTC_CTRL_REG_TEST_MODE_SHIFT 4
+#define PALMAS_RTC_CTRL_REG_MODE_12_24 0x08
+#define PALMAS_RTC_CTRL_REG_MODE_12_24_SHIFT 3
+#define PALMAS_RTC_CTRL_REG_AUTO_COMP 0x04
+#define PALMAS_RTC_CTRL_REG_AUTO_COMP_SHIFT 2
+#define PALMAS_RTC_CTRL_REG_ROUND_30S 0x02
+#define PALMAS_RTC_CTRL_REG_ROUND_30S_SHIFT 1
+#define PALMAS_RTC_CTRL_REG_STOP_RTC 0x01
+#define PALMAS_RTC_CTRL_REG_STOP_RTC_SHIFT 0
+
+/* Bit definitions for RTC_STATUS_REG */
+#define PALMAS_RTC_STATUS_REG_POWER_UP 0x80
+#define PALMAS_RTC_STATUS_REG_POWER_UP_SHIFT 7
+#define PALMAS_RTC_STATUS_REG_ALARM 0x40
+#define PALMAS_RTC_STATUS_REG_ALARM_SHIFT 6
+#define PALMAS_RTC_STATUS_REG_EVENT_1D 0x20
+#define PALMAS_RTC_STATUS_REG_EVENT_1D_SHIFT 5
+#define PALMAS_RTC_STATUS_REG_EVENT_1H 0x10
+#define PALMAS_RTC_STATUS_REG_EVENT_1H_SHIFT 4
+#define PALMAS_RTC_STATUS_REG_EVENT_1M 0x08
+#define PALMAS_RTC_STATUS_REG_EVENT_1M_SHIFT 3
+#define PALMAS_RTC_STATUS_REG_EVENT_1S 0x04
+#define PALMAS_RTC_STATUS_REG_EVENT_1S_SHIFT 2
+#define PALMAS_RTC_STATUS_REG_RUN 0x02
+#define PALMAS_RTC_STATUS_REG_RUN_SHIFT 1
+
+/* Bit definitions for RTC_INTERRUPTS_REG */
+#define PALMAS_RTC_INTERRUPTS_REG_IT_SLEEP_MASK_EN 0x10
+#define PALMAS_RTC_INTERRUPTS_REG_IT_SLEEP_MASK_EN_SHIFT 4
+#define PALMAS_RTC_INTERRUPTS_REG_IT_ALARM 0x08
+#define PALMAS_RTC_INTERRUPTS_REG_IT_ALARM_SHIFT 3
+#define PALMAS_RTC_INTERRUPTS_REG_IT_TIMER 0x04
+#define PALMAS_RTC_INTERRUPTS_REG_IT_TIMER_SHIFT 2
+#define PALMAS_RTC_INTERRUPTS_REG_EVERY_MASK 0x03
+#define PALMAS_RTC_INTERRUPTS_REG_EVERY_SHIFT 0
+
+/* Bit definitions for RTC_COMP_LSB_REG */
+#define PALMAS_RTC_COMP_LSB_REG_RTC_COMP_LSB_MASK 0xff
+#define PALMAS_RTC_COMP_LSB_REG_RTC_COMP_LSB_SHIFT 0
+
+/* Bit definitions for RTC_COMP_MSB_REG */
+#define PALMAS_RTC_COMP_MSB_REG_RTC_COMP_MSB_MASK 0xff
+#define PALMAS_RTC_COMP_MSB_REG_RTC_COMP_MSB_SHIFT 0
+
+/* Bit definitions for RTC_RES_PROG_REG */
+#define PALMAS_RTC_RES_PROG_REG_SW_RES_PROG_MASK 0x3f
+#define PALMAS_RTC_RES_PROG_REG_SW_RES_PROG_SHIFT 0
+
+/* Bit definitions for RTC_RESET_STATUS_REG */
+#define PALMAS_RTC_RESET_STATUS_REG_RESET_STATUS 0x01
+#define PALMAS_RTC_RESET_STATUS_REG_RESET_STATUS_SHIFT 0
+
+/* Registers for function BACKUP */
+#define PALMAS_BACKUP0 0x0
+#define PALMAS_BACKUP1 0x1
+#define PALMAS_BACKUP2 0x2
+#define PALMAS_BACKUP3 0x3
+#define PALMAS_BACKUP4 0x4
+#define PALMAS_BACKUP5 0x5
+#define PALMAS_BACKUP6 0x6
+#define PALMAS_BACKUP7 0x7
+
+/* Bit definitions for BACKUP0 */
+#define PALMAS_BACKUP0_BACKUP_MASK 0xff
+#define PALMAS_BACKUP0_BACKUP_SHIFT 0
+
+/* Bit definitions for BACKUP1 */
+#define PALMAS_BACKUP1_BACKUP_MASK 0xff
+#define PALMAS_BACKUP1_BACKUP_SHIFT 0
+
+/* Bit definitions for BACKUP2 */
+#define PALMAS_BACKUP2_BACKUP_MASK 0xff
+#define PALMAS_BACKUP2_BACKUP_SHIFT 0
+
+/* Bit definitions for BACKUP3 */
+#define PALMAS_BACKUP3_BACKUP_MASK 0xff
+#define PALMAS_BACKUP3_BACKUP_SHIFT 0
+
+/* Bit definitions for BACKUP4 */
+#define PALMAS_BACKUP4_BACKUP_MASK 0xff
+#define PALMAS_BACKUP4_BACKUP_SHIFT 0
+
+/* Bit definitions for BACKUP5 */
+#define PALMAS_BACKUP5_BACKUP_MASK 0xff
+#define PALMAS_BACKUP5_BACKUP_SHIFT 0
+
+/* Bit definitions for BACKUP6 */
+#define PALMAS_BACKUP6_BACKUP_MASK 0xff
+#define PALMAS_BACKUP6_BACKUP_SHIFT 0
+
+/* Bit definitions for BACKUP7 */
+#define PALMAS_BACKUP7_BACKUP_MASK 0xff
+#define PALMAS_BACKUP7_BACKUP_SHIFT 0
+
+/* Registers for function SMPS */
+#define PALMAS_SMPS12_CTRL 0x0
+#define PALMAS_SMPS12_TSTEP 0x1
+#define PALMAS_SMPS12_FORCE 0x2
+#define PALMAS_SMPS12_VOLTAGE 0x3
+#define PALMAS_SMPS3_CTRL 0x4
+#define PALMAS_SMPS3_VOLTAGE 0x7
+#define PALMAS_SMPS45_CTRL 0x8
+#define PALMAS_SMPS45_TSTEP 0x9
+#define PALMAS_SMPS45_FORCE 0xA
+#define PALMAS_SMPS45_VOLTAGE 0xB
+#define PALMAS_SMPS6_CTRL 0xC
+#define PALMAS_SMPS6_TSTEP 0xD
+#define PALMAS_SMPS6_FORCE 0xE
+#define PALMAS_SMPS6_VOLTAGE 0xF
+#define PALMAS_SMPS7_CTRL 0x10
+#define PALMAS_SMPS7_VOLTAGE 0x13
+#define PALMAS_SMPS8_CTRL 0x14
+#define PALMAS_SMPS8_TSTEP 0x15
+#define PALMAS_SMPS8_FORCE 0x16
+#define PALMAS_SMPS8_VOLTAGE 0x17
+#define PALMAS_SMPS9_CTRL 0x18
+#define PALMAS_SMPS9_VOLTAGE 0x1B
+#define PALMAS_SMPS10_CTRL 0x1C
+#define PALMAS_SMPS10_STATUS 0x1F
+#define PALMAS_SMPS_CTRL 0x24
+#define PALMAS_SMPS_PD_CTRL 0x25
+#define PALMAS_SMPS_DITHER_EN 0x26
+#define PALMAS_SMPS_THERMAL_EN 0x27
+#define PALMAS_SMPS_THERMAL_STATUS 0x28
+#define PALMAS_SMPS_SHORT_STATUS 0x29
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN 0x2A
+#define PALMAS_SMPS_POWERGOOD_MASK1 0x2B
+#define PALMAS_SMPS_POWERGOOD_MASK2 0x2C
+
+/* Bit definitions for SMPS12_CTRL */
+#define PALMAS_SMPS12_CTRL_WR_S 0x80
+#define PALMAS_SMPS12_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS12_CTRL_ROOF_FLOOR_EN 0x40
+#define PALMAS_SMPS12_CTRL_ROOF_FLOOR_EN_SHIFT 6
+#define PALMAS_SMPS12_CTRL_STATUS_MASK 0x30
+#define PALMAS_SMPS12_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS12_CTRL_MODE_SLEEP_MASK 0x0c
+#define PALMAS_SMPS12_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK 0x03
+#define PALMAS_SMPS12_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for SMPS12_TSTEP */
+#define PALMAS_SMPS12_TSTEP_TSTEP_MASK 0x03
+#define PALMAS_SMPS12_TSTEP_TSTEP_SHIFT 0
+
+/* Bit definitions for SMPS12_FORCE */
+#define PALMAS_SMPS12_FORCE_CMD 0x80
+#define PALMAS_SMPS12_FORCE_CMD_SHIFT 7
+#define PALMAS_SMPS12_FORCE_VSEL_MASK 0x7f
+#define PALMAS_SMPS12_FORCE_VSEL_SHIFT 0
+
+/* Bit definitions for SMPS12_VOLTAGE */
+#define PALMAS_SMPS12_VOLTAGE_RANGE 0x80
+#define PALMAS_SMPS12_VOLTAGE_RANGE_SHIFT 7
+#define PALMAS_SMPS12_VOLTAGE_VSEL_MASK 0x7f
+#define PALMAS_SMPS12_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for SMPS3_CTRL */
+#define PALMAS_SMPS3_CTRL_WR_S 0x80
+#define PALMAS_SMPS3_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS3_CTRL_STATUS_MASK 0x30
+#define PALMAS_SMPS3_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS3_CTRL_MODE_SLEEP_MASK 0x0c
+#define PALMAS_SMPS3_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS3_CTRL_MODE_ACTIVE_MASK 0x03
+#define PALMAS_SMPS3_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for SMPS3_VOLTAGE */
+#define PALMAS_SMPS3_VOLTAGE_RANGE 0x80
+#define PALMAS_SMPS3_VOLTAGE_RANGE_SHIFT 7
+#define PALMAS_SMPS3_VOLTAGE_VSEL_MASK 0x7f
+#define PALMAS_SMPS3_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for SMPS45_CTRL */
+#define PALMAS_SMPS45_CTRL_WR_S 0x80
+#define PALMAS_SMPS45_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS45_CTRL_ROOF_FLOOR_EN 0x40
+#define PALMAS_SMPS45_CTRL_ROOF_FLOOR_EN_SHIFT 6
+#define PALMAS_SMPS45_CTRL_STATUS_MASK 0x30
+#define PALMAS_SMPS45_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS45_CTRL_MODE_SLEEP_MASK 0x0c
+#define PALMAS_SMPS45_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS45_CTRL_MODE_ACTIVE_MASK 0x03
+#define PALMAS_SMPS45_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for SMPS45_TSTEP */
+#define PALMAS_SMPS45_TSTEP_TSTEP_MASK 0x03
+#define PALMAS_SMPS45_TSTEP_TSTEP_SHIFT 0
+
+/* Bit definitions for SMPS45_FORCE */
+#define PALMAS_SMPS45_FORCE_CMD 0x80
+#define PALMAS_SMPS45_FORCE_CMD_SHIFT 7
+#define PALMAS_SMPS45_FORCE_VSEL_MASK 0x7f
+#define PALMAS_SMPS45_FORCE_VSEL_SHIFT 0
+
+/* Bit definitions for SMPS45_VOLTAGE */
+#define PALMAS_SMPS45_VOLTAGE_RANGE 0x80
+#define PALMAS_SMPS45_VOLTAGE_RANGE_SHIFT 7
+#define PALMAS_SMPS45_VOLTAGE_VSEL_MASK 0x7f
+#define PALMAS_SMPS45_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for SMPS6_CTRL */
+#define PALMAS_SMPS6_CTRL_WR_S 0x80
+#define PALMAS_SMPS6_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS6_CTRL_ROOF_FLOOR_EN 0x40
+#define PALMAS_SMPS6_CTRL_ROOF_FLOOR_EN_SHIFT 6
+#define PALMAS_SMPS6_CTRL_STATUS_MASK 0x30
+#define PALMAS_SMPS6_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS6_CTRL_MODE_SLEEP_MASK 0x0c
+#define PALMAS_SMPS6_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS6_CTRL_MODE_ACTIVE_MASK 0x03
+#define PALMAS_SMPS6_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for SMPS6_TSTEP */
+#define PALMAS_SMPS6_TSTEP_TSTEP_MASK 0x03
+#define PALMAS_SMPS6_TSTEP_TSTEP_SHIFT 0
+
+/* Bit definitions for SMPS6_FORCE */
+#define PALMAS_SMPS6_FORCE_CMD 0x80
+#define PALMAS_SMPS6_FORCE_CMD_SHIFT 7
+#define PALMAS_SMPS6_FORCE_VSEL_MASK 0x7f
+#define PALMAS_SMPS6_FORCE_VSEL_SHIFT 0
+
+/* Bit definitions for SMPS6_VOLTAGE */
+#define PALMAS_SMPS6_VOLTAGE_RANGE 0x80
+#define PALMAS_SMPS6_VOLTAGE_RANGE_SHIFT 7
+#define PALMAS_SMPS6_VOLTAGE_VSEL_MASK 0x7f
+#define PALMAS_SMPS6_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for SMPS7_CTRL */
+#define PALMAS_SMPS7_CTRL_WR_S 0x80
+#define PALMAS_SMPS7_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS7_CTRL_STATUS_MASK 0x30
+#define PALMAS_SMPS7_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS7_CTRL_MODE_SLEEP_MASK 0x0c
+#define PALMAS_SMPS7_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS7_CTRL_MODE_ACTIVE_MASK 0x03
+#define PALMAS_SMPS7_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for SMPS7_VOLTAGE */
+#define PALMAS_SMPS7_VOLTAGE_RANGE 0x80
+#define PALMAS_SMPS7_VOLTAGE_RANGE_SHIFT 7
+#define PALMAS_SMPS7_VOLTAGE_VSEL_MASK 0x7f
+#define PALMAS_SMPS7_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for SMPS8_CTRL */
+#define PALMAS_SMPS8_CTRL_WR_S 0x80
+#define PALMAS_SMPS8_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS8_CTRL_ROOF_FLOOR_EN 0x40
+#define PALMAS_SMPS8_CTRL_ROOF_FLOOR_EN_SHIFT 6
+#define PALMAS_SMPS8_CTRL_STATUS_MASK 0x30
+#define PALMAS_SMPS8_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS8_CTRL_MODE_SLEEP_MASK 0x0c
+#define PALMAS_SMPS8_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS8_CTRL_MODE_ACTIVE_MASK 0x03
+#define PALMAS_SMPS8_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for SMPS8_TSTEP */
+#define PALMAS_SMPS8_TSTEP_TSTEP_MASK 0x03
+#define PALMAS_SMPS8_TSTEP_TSTEP_SHIFT 0
+
+/* Bit definitions for SMPS8_FORCE */
+#define PALMAS_SMPS8_FORCE_CMD 0x80
+#define PALMAS_SMPS8_FORCE_CMD_SHIFT 7
+#define PALMAS_SMPS8_FORCE_VSEL_MASK 0x7f
+#define PALMAS_SMPS8_FORCE_VSEL_SHIFT 0
+
+/* Bit definitions for SMPS8_VOLTAGE */
+#define PALMAS_SMPS8_VOLTAGE_RANGE 0x80
+#define PALMAS_SMPS8_VOLTAGE_RANGE_SHIFT 7
+#define PALMAS_SMPS8_VOLTAGE_VSEL_MASK 0x7f
+#define PALMAS_SMPS8_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for SMPS9_CTRL */
+#define PALMAS_SMPS9_CTRL_WR_S 0x80
+#define PALMAS_SMPS9_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS9_CTRL_STATUS_MASK 0x30
+#define PALMAS_SMPS9_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS9_CTRL_MODE_SLEEP_MASK 0x0c
+#define PALMAS_SMPS9_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS9_CTRL_MODE_ACTIVE_MASK 0x03
+#define PALMAS_SMPS9_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for SMPS9_VOLTAGE */
+#define PALMAS_SMPS9_VOLTAGE_RANGE 0x80
+#define PALMAS_SMPS9_VOLTAGE_RANGE_SHIFT 7
+#define PALMAS_SMPS9_VOLTAGE_VSEL_MASK 0x7f
+#define PALMAS_SMPS9_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for SMPS10_CTRL */
+#define PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK 0xf0
+#define PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT 4
+#define PALMAS_SMPS10_CTRL_MODE_ACTIVE_MASK 0x0f
+#define PALMAS_SMPS10_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for SMPS10_STATUS */
+#define PALMAS_SMPS10_STATUS_STATUS_MASK 0x0f
+#define PALMAS_SMPS10_STATUS_STATUS_SHIFT 0
+
+/* Bit definitions for SMPS_CTRL */
+#define PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN 0x20
+#define PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN_SHIFT 5
+#define PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN 0x10
+#define PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN_SHIFT 4
+#define PALMAS_SMPS_CTRL_SMPS45_PHASE_CTRL_MASK 0x0c
+#define PALMAS_SMPS_CTRL_SMPS45_PHASE_CTRL_SHIFT 2
+#define PALMAS_SMPS_CTRL_SMPS123_PHASE_CTRL_MASK 0x03
+#define PALMAS_SMPS_CTRL_SMPS123_PHASE_CTRL_SHIFT 0
+
+/* Bit definitions for SMPS_PD_CTRL */
+#define PALMAS_SMPS_PD_CTRL_SMPS9 0x40
+#define PALMAS_SMPS_PD_CTRL_SMPS9_SHIFT 6
+#define PALMAS_SMPS_PD_CTRL_SMPS8 0x20
+#define PALMAS_SMPS_PD_CTRL_SMPS8_SHIFT 5
+#define PALMAS_SMPS_PD_CTRL_SMPS7 0x10
+#define PALMAS_SMPS_PD_CTRL_SMPS7_SHIFT 4
+#define PALMAS_SMPS_PD_CTRL_SMPS6 0x08
+#define PALMAS_SMPS_PD_CTRL_SMPS6_SHIFT 3
+#define PALMAS_SMPS_PD_CTRL_SMPS45 0x04
+#define PALMAS_SMPS_PD_CTRL_SMPS45_SHIFT 2
+#define PALMAS_SMPS_PD_CTRL_SMPS3 0x02
+#define PALMAS_SMPS_PD_CTRL_SMPS3_SHIFT 1
+#define PALMAS_SMPS_PD_CTRL_SMPS12 0x01
+#define PALMAS_SMPS_PD_CTRL_SMPS12_SHIFT 0
+
+/* Bit definitions for SMPS_THERMAL_EN */
+#define PALMAS_SMPS_THERMAL_EN_SMPS9 0x40
+#define PALMAS_SMPS_THERMAL_EN_SMPS9_SHIFT 6
+#define PALMAS_SMPS_THERMAL_EN_SMPS8 0x20
+#define PALMAS_SMPS_THERMAL_EN_SMPS8_SHIFT 5
+#define PALMAS_SMPS_THERMAL_EN_SMPS6 0x08
+#define PALMAS_SMPS_THERMAL_EN_SMPS6_SHIFT 3
+#define PALMAS_SMPS_THERMAL_EN_SMPS457 0x04
+#define PALMAS_SMPS_THERMAL_EN_SMPS457_SHIFT 2
+#define PALMAS_SMPS_THERMAL_EN_SMPS123 0x01
+#define PALMAS_SMPS_THERMAL_EN_SMPS123_SHIFT 0
+
+/* Bit definitions for SMPS_THERMAL_STATUS */
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS9 0x40
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS9_SHIFT 6
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS8 0x20
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS8_SHIFT 5
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS6 0x08
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS6_SHIFT 3
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS457 0x04
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS457_SHIFT 2
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS123 0x01
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS123_SHIFT 0
+
+/* Bit definitions for SMPS_SHORT_STATUS */
+#define PALMAS_SMPS_SHORT_STATUS_SMPS10 0x80
+#define PALMAS_SMPS_SHORT_STATUS_SMPS10_SHIFT 7
+#define PALMAS_SMPS_SHORT_STATUS_SMPS9 0x40
+#define PALMAS_SMPS_SHORT_STATUS_SMPS9_SHIFT 6
+#define PALMAS_SMPS_SHORT_STATUS_SMPS8 0x20
+#define PALMAS_SMPS_SHORT_STATUS_SMPS8_SHIFT 5
+#define PALMAS_SMPS_SHORT_STATUS_SMPS7 0x10
+#define PALMAS_SMPS_SHORT_STATUS_SMPS7_SHIFT 4
+#define PALMAS_SMPS_SHORT_STATUS_SMPS6 0x08
+#define PALMAS_SMPS_SHORT_STATUS_SMPS6_SHIFT 3
+#define PALMAS_SMPS_SHORT_STATUS_SMPS45 0x04
+#define PALMAS_SMPS_SHORT_STATUS_SMPS45_SHIFT 2
+#define PALMAS_SMPS_SHORT_STATUS_SMPS3 0x02
+#define PALMAS_SMPS_SHORT_STATUS_SMPS3_SHIFT 1
+#define PALMAS_SMPS_SHORT_STATUS_SMPS12 0x01
+#define PALMAS_SMPS_SHORT_STATUS_SMPS12_SHIFT 0
+
+/* Bit definitions for SMPS_NEGATIVE_CURRENT_LIMIT_EN */
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS9 0x40
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS9_SHIFT 6
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS8 0x20
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS8_SHIFT 5
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS7 0x10
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS7_SHIFT 4
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS6 0x08
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS6_SHIFT 3
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS45 0x04
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS45_SHIFT 2
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS3 0x02
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS3_SHIFT 1
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS12 0x01
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS12_SHIFT 0
+
+/* Bit definitions for SMPS_POWERGOOD_MASK1 */
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS10 0x80
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS10_SHIFT 7
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS9 0x40
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS9_SHIFT 6
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS8 0x20
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS8_SHIFT 5
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS7 0x10
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS7_SHIFT 4
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS6 0x08
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS6_SHIFT 3
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS45 0x04
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS45_SHIFT 2
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS3 0x02
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS3_SHIFT 1
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS12 0x01
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS12_SHIFT 0
+
+/* Bit definitions for SMPS_POWERGOOD_MASK2 */
+#define PALMAS_SMPS_POWERGOOD_MASK2_POWERGOOD_TYPE_SELECT 0x80
+#define PALMAS_SMPS_POWERGOOD_MASK2_POWERGOOD_TYPE_SELECT_SHIFT 7
+#define PALMAS_SMPS_POWERGOOD_MASK2_GPIO_7 0x04
+#define PALMAS_SMPS_POWERGOOD_MASK2_GPIO_7_SHIFT 2
+#define PALMAS_SMPS_POWERGOOD_MASK2_VBUS 0x02
+#define PALMAS_SMPS_POWERGOOD_MASK2_VBUS_SHIFT 1
+#define PALMAS_SMPS_POWERGOOD_MASK2_ACOK 0x01
+#define PALMAS_SMPS_POWERGOOD_MASK2_ACOK_SHIFT 0
+
+/* Registers for function LDO */
+#define PALMAS_LDO1_CTRL 0x0
+#define PALMAS_LDO1_VOLTAGE 0x1
+#define PALMAS_LDO2_CTRL 0x2
+#define PALMAS_LDO2_VOLTAGE 0x3
+#define PALMAS_LDO3_CTRL 0x4
+#define PALMAS_LDO3_VOLTAGE 0x5
+#define PALMAS_LDO4_CTRL 0x6
+#define PALMAS_LDO4_VOLTAGE 0x7
+#define PALMAS_LDO5_CTRL 0x8
+#define PALMAS_LDO5_VOLTAGE 0x9
+#define PALMAS_LDO6_CTRL 0xA
+#define PALMAS_LDO6_VOLTAGE 0xB
+#define PALMAS_LDO7_CTRL 0xC
+#define PALMAS_LDO7_VOLTAGE 0xD
+#define PALMAS_LDO8_CTRL 0xE
+#define PALMAS_LDO8_VOLTAGE 0xF
+#define PALMAS_LDO9_CTRL 0x10
+#define PALMAS_LDO9_VOLTAGE 0x11
+#define PALMAS_LDOLN_CTRL 0x12
+#define PALMAS_LDOLN_VOLTAGE 0x13
+#define PALMAS_LDOUSB_CTRL 0x14
+#define PALMAS_LDOUSB_VOLTAGE 0x15
+#define PALMAS_LDO_CTRL 0x1A
+#define PALMAS_LDO_PD_CTRL1 0x1B
+#define PALMAS_LDO_PD_CTRL2 0x1C
+#define PALMAS_LDO_SHORT_STATUS1 0x1D
+#define PALMAS_LDO_SHORT_STATUS2 0x1E
+
+/* Bit definitions for LDO1_CTRL */
+#define PALMAS_LDO1_CTRL_WR_S 0x80
+#define PALMAS_LDO1_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO1_CTRL_STATUS 0x10
+#define PALMAS_LDO1_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO1_CTRL_MODE_SLEEP 0x04
+#define PALMAS_LDO1_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO1_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_LDO1_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for LDO1_VOLTAGE */
+#define PALMAS_LDO1_VOLTAGE_VSEL_MASK 0x3f
+#define PALMAS_LDO1_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for LDO2_CTRL */
+#define PALMAS_LDO2_CTRL_WR_S 0x80
+#define PALMAS_LDO2_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO2_CTRL_STATUS 0x10
+#define PALMAS_LDO2_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO2_CTRL_MODE_SLEEP 0x04
+#define PALMAS_LDO2_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO2_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_LDO2_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for LDO2_VOLTAGE */
+#define PALMAS_LDO2_VOLTAGE_VSEL_MASK 0x3f
+#define PALMAS_LDO2_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for LDO3_CTRL */
+#define PALMAS_LDO3_CTRL_WR_S 0x80
+#define PALMAS_LDO3_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO3_CTRL_STATUS 0x10
+#define PALMAS_LDO3_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO3_CTRL_MODE_SLEEP 0x04
+#define PALMAS_LDO3_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO3_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_LDO3_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for LDO3_VOLTAGE */
+#define PALMAS_LDO3_VOLTAGE_VSEL_MASK 0x3f
+#define PALMAS_LDO3_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for LDO4_CTRL */
+#define PALMAS_LDO4_CTRL_WR_S 0x80
+#define PALMAS_LDO4_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO4_CTRL_STATUS 0x10
+#define PALMAS_LDO4_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO4_CTRL_MODE_SLEEP 0x04
+#define PALMAS_LDO4_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO4_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_LDO4_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for LDO4_VOLTAGE */
+#define PALMAS_LDO4_VOLTAGE_VSEL_MASK 0x3f
+#define PALMAS_LDO4_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for LDO5_CTRL */
+#define PALMAS_LDO5_CTRL_WR_S 0x80
+#define PALMAS_LDO5_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO5_CTRL_STATUS 0x10
+#define PALMAS_LDO5_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO5_CTRL_MODE_SLEEP 0x04
+#define PALMAS_LDO5_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO5_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_LDO5_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for LDO5_VOLTAGE */
+#define PALMAS_LDO5_VOLTAGE_VSEL_MASK 0x3f
+#define PALMAS_LDO5_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for LDO6_CTRL */
+#define PALMAS_LDO6_CTRL_WR_S 0x80
+#define PALMAS_LDO6_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO6_CTRL_LDO_VIB_EN 0x40
+#define PALMAS_LDO6_CTRL_LDO_VIB_EN_SHIFT 6
+#define PALMAS_LDO6_CTRL_STATUS 0x10
+#define PALMAS_LDO6_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO6_CTRL_MODE_SLEEP 0x04
+#define PALMAS_LDO6_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO6_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_LDO6_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for LDO6_VOLTAGE */
+#define PALMAS_LDO6_VOLTAGE_VSEL_MASK 0x3f
+#define PALMAS_LDO6_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for LDO7_CTRL */
+#define PALMAS_LDO7_CTRL_WR_S 0x80
+#define PALMAS_LDO7_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO7_CTRL_STATUS 0x10
+#define PALMAS_LDO7_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO7_CTRL_MODE_SLEEP 0x04
+#define PALMAS_LDO7_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO7_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_LDO7_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for LDO7_VOLTAGE */
+#define PALMAS_LDO7_VOLTAGE_VSEL_MASK 0x3f
+#define PALMAS_LDO7_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for LDO8_CTRL */
+#define PALMAS_LDO8_CTRL_WR_S 0x80
+#define PALMAS_LDO8_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO8_CTRL_LDO_TRACKING_EN 0x40
+#define PALMAS_LDO8_CTRL_LDO_TRACKING_EN_SHIFT 6
+#define PALMAS_LDO8_CTRL_STATUS 0x10
+#define PALMAS_LDO8_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO8_CTRL_MODE_SLEEP 0x04
+#define PALMAS_LDO8_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO8_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_LDO8_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for LDO8_VOLTAGE */
+#define PALMAS_LDO8_VOLTAGE_VSEL_MASK 0x3f
+#define PALMAS_LDO8_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for LDO9_CTRL */
+#define PALMAS_LDO9_CTRL_WR_S 0x80
+#define PALMAS_LDO9_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO9_CTRL_LDO_BYPASS_EN 0x40
+#define PALMAS_LDO9_CTRL_LDO_BYPASS_EN_SHIFT 6
+#define PALMAS_LDO9_CTRL_STATUS 0x10
+#define PALMAS_LDO9_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO9_CTRL_MODE_SLEEP 0x04
+#define PALMAS_LDO9_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO9_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_LDO9_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for LDO9_VOLTAGE */
+#define PALMAS_LDO9_VOLTAGE_VSEL_MASK 0x3f
+#define PALMAS_LDO9_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for LDOLN_CTRL */
+#define PALMAS_LDOLN_CTRL_WR_S 0x80
+#define PALMAS_LDOLN_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDOLN_CTRL_STATUS 0x10
+#define PALMAS_LDOLN_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDOLN_CTRL_MODE_SLEEP 0x04
+#define PALMAS_LDOLN_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDOLN_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_LDOLN_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for LDOLN_VOLTAGE */
+#define PALMAS_LDOLN_VOLTAGE_VSEL_MASK 0x3f
+#define PALMAS_LDOLN_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for LDOUSB_CTRL */
+#define PALMAS_LDOUSB_CTRL_WR_S 0x80
+#define PALMAS_LDOUSB_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDOUSB_CTRL_STATUS 0x10
+#define PALMAS_LDOUSB_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDOUSB_CTRL_MODE_SLEEP 0x04
+#define PALMAS_LDOUSB_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDOUSB_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_LDOUSB_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for LDOUSB_VOLTAGE */
+#define PALMAS_LDOUSB_VOLTAGE_VSEL_MASK 0x3f
+#define PALMAS_LDOUSB_VOLTAGE_VSEL_SHIFT 0
+
+/* Bit definitions for LDO_CTRL */
+#define PALMAS_LDO_CTRL_LDOUSB_ON_VBUS_VSYS 0x01
+#define PALMAS_LDO_CTRL_LDOUSB_ON_VBUS_VSYS_SHIFT 0
+
+/* Bit definitions for LDO_PD_CTRL1 */
+#define PALMAS_LDO_PD_CTRL1_LDO8 0x80
+#define PALMAS_LDO_PD_CTRL1_LDO8_SHIFT 7
+#define PALMAS_LDO_PD_CTRL1_LDO7 0x40
+#define PALMAS_LDO_PD_CTRL1_LDO7_SHIFT 6
+#define PALMAS_LDO_PD_CTRL1_LDO6 0x20
+#define PALMAS_LDO_PD_CTRL1_LDO6_SHIFT 5
+#define PALMAS_LDO_PD_CTRL1_LDO5 0x10
+#define PALMAS_LDO_PD_CTRL1_LDO5_SHIFT 4
+#define PALMAS_LDO_PD_CTRL1_LDO4 0x08
+#define PALMAS_LDO_PD_CTRL1_LDO4_SHIFT 3
+#define PALMAS_LDO_PD_CTRL1_LDO3 0x04
+#define PALMAS_LDO_PD_CTRL1_LDO3_SHIFT 2
+#define PALMAS_LDO_PD_CTRL1_LDO2 0x02
+#define PALMAS_LDO_PD_CTRL1_LDO2_SHIFT 1
+#define PALMAS_LDO_PD_CTRL1_LDO1 0x01
+#define PALMAS_LDO_PD_CTRL1_LDO1_SHIFT 0
+
+/* Bit definitions for LDO_PD_CTRL2 */
+#define PALMAS_LDO_PD_CTRL2_LDOUSB 0x04
+#define PALMAS_LDO_PD_CTRL2_LDOUSB_SHIFT 2
+#define PALMAS_LDO_PD_CTRL2_LDOLN 0x02
+#define PALMAS_LDO_PD_CTRL2_LDOLN_SHIFT 1
+#define PALMAS_LDO_PD_CTRL2_LDO9 0x01
+#define PALMAS_LDO_PD_CTRL2_LDO9_SHIFT 0
+
+/* Bit definitions for LDO_SHORT_STATUS1 */
+#define PALMAS_LDO_SHORT_STATUS1_LDO8 0x80
+#define PALMAS_LDO_SHORT_STATUS1_LDO8_SHIFT 7
+#define PALMAS_LDO_SHORT_STATUS1_LDO7 0x40
+#define PALMAS_LDO_SHORT_STATUS1_LDO7_SHIFT 6
+#define PALMAS_LDO_SHORT_STATUS1_LDO6 0x20
+#define PALMAS_LDO_SHORT_STATUS1_LDO6_SHIFT 5
+#define PALMAS_LDO_SHORT_STATUS1_LDO5 0x10
+#define PALMAS_LDO_SHORT_STATUS1_LDO5_SHIFT 4
+#define PALMAS_LDO_SHORT_STATUS1_LDO4 0x08
+#define PALMAS_LDO_SHORT_STATUS1_LDO4_SHIFT 3
+#define PALMAS_LDO_SHORT_STATUS1_LDO3 0x04
+#define PALMAS_LDO_SHORT_STATUS1_LDO3_SHIFT 2
+#define PALMAS_LDO_SHORT_STATUS1_LDO2 0x02
+#define PALMAS_LDO_SHORT_STATUS1_LDO2_SHIFT 1
+#define PALMAS_LDO_SHORT_STATUS1_LDO1 0x01
+#define PALMAS_LDO_SHORT_STATUS1_LDO1_SHIFT 0
+
+/* Bit definitions for LDO_SHORT_STATUS2 */
+#define PALMAS_LDO_SHORT_STATUS2_LDOVANA 0x08
+#define PALMAS_LDO_SHORT_STATUS2_LDOVANA_SHIFT 3
+#define PALMAS_LDO_SHORT_STATUS2_LDOUSB 0x04
+#define PALMAS_LDO_SHORT_STATUS2_LDOUSB_SHIFT 2
+#define PALMAS_LDO_SHORT_STATUS2_LDOLN 0x02
+#define PALMAS_LDO_SHORT_STATUS2_LDOLN_SHIFT 1
+#define PALMAS_LDO_SHORT_STATUS2_LDO9 0x01
+#define PALMAS_LDO_SHORT_STATUS2_LDO9_SHIFT 0
+
+/* Registers for function PMU_CONTROL */
+#define PALMAS_DEV_CTRL 0x0
+#define PALMAS_POWER_CTRL 0x1
+#define PALMAS_VSYS_LO 0x2
+#define PALMAS_VSYS_MON 0x3
+#define PALMAS_VBAT_MON 0x4
+#define PALMAS_WATCHDOG 0x5
+#define PALMAS_BOOT_STATUS 0x6
+#define PALMAS_BATTERY_BOUNCE 0x7
+#define PALMAS_BACKUP_BATTERY_CTRL 0x8
+#define PALMAS_LONG_PRESS_KEY 0x9
+#define PALMAS_OSC_THERM_CTRL 0xA
+#define PALMAS_BATDEBOUNCING 0xB
+#define PALMAS_SWOFF_HWRST 0xF
+#define PALMAS_SWOFF_COLDRST 0x10
+#define PALMAS_SWOFF_STATUS 0x11
+#define PALMAS_PMU_CONFIG 0x12
+#define PALMAS_SPARE 0x14
+#define PALMAS_PMU_SECONDARY_INT 0x15
+#define PALMAS_SW_REVISION 0x17
+#define PALMAS_EXT_CHRG_CTRL 0x18
+#define PALMAS_PMU_SECONDARY_INT2 0x19
+
+/* Bit definitions for DEV_CTRL */
+#define PALMAS_DEV_CTRL_DEV_STATUS_MASK 0x0c
+#define PALMAS_DEV_CTRL_DEV_STATUS_SHIFT 2
+#define PALMAS_DEV_CTRL_SW_RST 0x02
+#define PALMAS_DEV_CTRL_SW_RST_SHIFT 1
+#define PALMAS_DEV_CTRL_DEV_ON 0x01
+#define PALMAS_DEV_CTRL_DEV_ON_SHIFT 0
+
+/* Bit definitions for POWER_CTRL */
+#define PALMAS_POWER_CTRL_ENABLE2_MASK 0x04
+#define PALMAS_POWER_CTRL_ENABLE2_MASK_SHIFT 2
+#define PALMAS_POWER_CTRL_ENABLE1_MASK 0x02
+#define PALMAS_POWER_CTRL_ENABLE1_MASK_SHIFT 1
+#define PALMAS_POWER_CTRL_NSLEEP_MASK 0x01
+#define PALMAS_POWER_CTRL_NSLEEP_MASK_SHIFT 0
+
+/* Bit definitions for VSYS_LO */
+#define PALMAS_VSYS_LO_THRESHOLD_MASK 0x1f
+#define PALMAS_VSYS_LO_THRESHOLD_SHIFT 0
+
+/* Bit definitions for VSYS_MON */
+#define PALMAS_VSYS_MON_ENABLE 0x80
+#define PALMAS_VSYS_MON_ENABLE_SHIFT 7
+#define PALMAS_VSYS_MON_THRESHOLD_MASK 0x3f
+#define PALMAS_VSYS_MON_THRESHOLD_SHIFT 0
+
+/* Bit definitions for VBAT_MON */
+#define PALMAS_VBAT_MON_ENABLE 0x80
+#define PALMAS_VBAT_MON_ENABLE_SHIFT 7
+#define PALMAS_VBAT_MON_THRESHOLD_MASK 0x3f
+#define PALMAS_VBAT_MON_THRESHOLD_SHIFT 0
+
+/* Bit definitions for WATCHDOG */
+#define PALMAS_WATCHDOG_LOCK 0x20
+#define PALMAS_WATCHDOG_LOCK_SHIFT 5
+#define PALMAS_WATCHDOG_ENABLE 0x10
+#define PALMAS_WATCHDOG_ENABLE_SHIFT 4
+#define PALMAS_WATCHDOG_MODE 0x08
+#define PALMAS_WATCHDOG_MODE_SHIFT 3
+#define PALMAS_WATCHDOG_TIMER_MASK 0x07
+#define PALMAS_WATCHDOG_TIMER_SHIFT 0
+
+/* Bit definitions for BOOT_STATUS */
+#define PALMAS_BOOT_STATUS_BOOT1 0x02
+#define PALMAS_BOOT_STATUS_BOOT1_SHIFT 1
+#define PALMAS_BOOT_STATUS_BOOT0 0x01
+#define PALMAS_BOOT_STATUS_BOOT0_SHIFT 0
+
+/* Bit definitions for BATTERY_BOUNCE */
+#define PALMAS_BATTERY_BOUNCE_BB_DELAY_MASK 0x3f
+#define PALMAS_BATTERY_BOUNCE_BB_DELAY_SHIFT 0
+
+/* Bit definitions for BACKUP_BATTERY_CTRL */
+#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_18_15 0x80
+#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_18_15_SHIFT 7
+#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_EN_SLP 0x40
+#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_EN_SLP_SHIFT 6
+#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_EN_OFF 0x20
+#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_EN_OFF_SHIFT 5
+#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_PWEN 0x10
+#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_PWEN_SHIFT 4
+#define PALMAS_BACKUP_BATTERY_CTRL_BBS_BBC_LOW_ICHRG 0x08
+#define PALMAS_BACKUP_BATTERY_CTRL_BBS_BBC_LOW_ICHRG_SHIFT 3
+#define PALMAS_BACKUP_BATTERY_CTRL_BB_SEL_MASK 0x06
+#define PALMAS_BACKUP_BATTERY_CTRL_BB_SEL_SHIFT 1
+#define PALMAS_BACKUP_BATTERY_CTRL_BB_CHG_EN 0x01
+#define PALMAS_BACKUP_BATTERY_CTRL_BB_CHG_EN_SHIFT 0
+
+/* Bit definitions for LONG_PRESS_KEY */
+#define PALMAS_LONG_PRESS_KEY_LPK_LOCK 0x80
+#define PALMAS_LONG_PRESS_KEY_LPK_LOCK_SHIFT 7
+#define PALMAS_LONG_PRESS_KEY_LPK_INT_CLR 0x10
+#define PALMAS_LONG_PRESS_KEY_LPK_INT_CLR_SHIFT 4
+#define PALMAS_LONG_PRESS_KEY_LPK_TIME_MASK 0x0c
+#define PALMAS_LONG_PRESS_KEY_LPK_TIME_SHIFT 2
+#define PALMAS_LONG_PRESS_KEY_PWRON_DEBOUNCE_MASK 0x03
+#define PALMAS_LONG_PRESS_KEY_PWRON_DEBOUNCE_SHIFT 0
+
+/* Bit definitions for OSC_THERM_CTRL */
+#define PALMAS_OSC_THERM_CTRL_VANA_ON_IN_SLEEP 0x80
+#define PALMAS_OSC_THERM_CTRL_VANA_ON_IN_SLEEP_SHIFT 7
+#define PALMAS_OSC_THERM_CTRL_INT_MASK_IN_SLEEP 0x40
+#define PALMAS_OSC_THERM_CTRL_INT_MASK_IN_SLEEP_SHIFT 6
+#define PALMAS_OSC_THERM_CTRL_RC15MHZ_ON_IN_SLEEP 0x20
+#define PALMAS_OSC_THERM_CTRL_RC15MHZ_ON_IN_SLEEP_SHIFT 5
+#define PALMAS_OSC_THERM_CTRL_THERM_OFF_IN_SLEEP 0x10
+#define PALMAS_OSC_THERM_CTRL_THERM_OFF_IN_SLEEP_SHIFT 4
+#define PALMAS_OSC_THERM_CTRL_THERM_HD_SEL_MASK 0x0c
+#define PALMAS_OSC_THERM_CTRL_THERM_HD_SEL_SHIFT 2
+#define PALMAS_OSC_THERM_CTRL_OSC_BYPASS 0x02
+#define PALMAS_OSC_THERM_CTRL_OSC_BYPASS_SHIFT 1
+#define PALMAS_OSC_THERM_CTRL_OSC_HPMODE 0x01
+#define PALMAS_OSC_THERM_CTRL_OSC_HPMODE_SHIFT 0
+
+/* Bit definitions for BATDEBOUNCING */
+#define PALMAS_BATDEBOUNCING_BAT_DEB_BYPASS 0x80
+#define PALMAS_BATDEBOUNCING_BAT_DEB_BYPASS_SHIFT 7
+#define PALMAS_BATDEBOUNCING_BINS_DEB_MASK 0x78
+#define PALMAS_BATDEBOUNCING_BINS_DEB_SHIFT 3
+#define PALMAS_BATDEBOUNCING_BEXT_DEB_MASK 0x07
+#define PALMAS_BATDEBOUNCING_BEXT_DEB_SHIFT 0
+
+/* Bit definitions for SWOFF_HWRST */
+#define PALMAS_SWOFF_HWRST_PWRON_LPK 0x80
+#define PALMAS_SWOFF_HWRST_PWRON_LPK_SHIFT 7
+#define PALMAS_SWOFF_HWRST_PWRDOWN 0x40
+#define PALMAS_SWOFF_HWRST_PWRDOWN_SHIFT 6
+#define PALMAS_SWOFF_HWRST_WTD 0x20
+#define PALMAS_SWOFF_HWRST_WTD_SHIFT 5
+#define PALMAS_SWOFF_HWRST_TSHUT 0x10
+#define PALMAS_SWOFF_HWRST_TSHUT_SHIFT 4
+#define PALMAS_SWOFF_HWRST_RESET_IN 0x08
+#define PALMAS_SWOFF_HWRST_RESET_IN_SHIFT 3
+#define PALMAS_SWOFF_HWRST_SW_RST 0x04
+#define PALMAS_SWOFF_HWRST_SW_RST_SHIFT 2
+#define PALMAS_SWOFF_HWRST_VSYS_LO 0x02
+#define PALMAS_SWOFF_HWRST_VSYS_LO_SHIFT 1
+#define PALMAS_SWOFF_HWRST_GPADC_SHUTDOWN 0x01
+#define PALMAS_SWOFF_HWRST_GPADC_SHUTDOWN_SHIFT 0
+
+/* Bit definitions for SWOFF_COLDRST */
+#define PALMAS_SWOFF_COLDRST_PWRON_LPK 0x80
+#define PALMAS_SWOFF_COLDRST_PWRON_LPK_SHIFT 7
+#define PALMAS_SWOFF_COLDRST_PWRDOWN 0x40
+#define PALMAS_SWOFF_COLDRST_PWRDOWN_SHIFT 6
+#define PALMAS_SWOFF_COLDRST_WTD 0x20
+#define PALMAS_SWOFF_COLDRST_WTD_SHIFT 5
+#define PALMAS_SWOFF_COLDRST_TSHUT 0x10
+#define PALMAS_SWOFF_COLDRST_TSHUT_SHIFT 4
+#define PALMAS_SWOFF_COLDRST_RESET_IN 0x08
+#define PALMAS_SWOFF_COLDRST_RESET_IN_SHIFT 3
+#define PALMAS_SWOFF_COLDRST_SW_RST 0x04
+#define PALMAS_SWOFF_COLDRST_SW_RST_SHIFT 2
+#define PALMAS_SWOFF_COLDRST_VSYS_LO 0x02
+#define PALMAS_SWOFF_COLDRST_VSYS_LO_SHIFT 1
+#define PALMAS_SWOFF_COLDRST_GPADC_SHUTDOWN 0x01
+#define PALMAS_SWOFF_COLDRST_GPADC_SHUTDOWN_SHIFT 0
+
+/* Bit definitions for SWOFF_STATUS */
+#define PALMAS_SWOFF_STATUS_PWRON_LPK 0x80
+#define PALMAS_SWOFF_STATUS_PWRON_LPK_SHIFT 7
+#define PALMAS_SWOFF_STATUS_PWRDOWN 0x40
+#define PALMAS_SWOFF_STATUS_PWRDOWN_SHIFT 6
+#define PALMAS_SWOFF_STATUS_WTD 0x20
+#define PALMAS_SWOFF_STATUS_WTD_SHIFT 5
+#define PALMAS_SWOFF_STATUS_TSHUT 0x10
+#define PALMAS_SWOFF_STATUS_TSHUT_SHIFT 4
+#define PALMAS_SWOFF_STATUS_RESET_IN 0x08
+#define PALMAS_SWOFF_STATUS_RESET_IN_SHIFT 3
+#define PALMAS_SWOFF_STATUS_SW_RST 0x04
+#define PALMAS_SWOFF_STATUS_SW_RST_SHIFT 2
+#define PALMAS_SWOFF_STATUS_VSYS_LO 0x02
+#define PALMAS_SWOFF_STATUS_VSYS_LO_SHIFT 1
+#define PALMAS_SWOFF_STATUS_GPADC_SHUTDOWN 0x01
+#define PALMAS_SWOFF_STATUS_GPADC_SHUTDOWN_SHIFT 0
+
+/* Bit definitions for PMU_CONFIG */
+#define PALMAS_PMU_CONFIG_MULTI_CELL_EN 0x40
+#define PALMAS_PMU_CONFIG_MULTI_CELL_EN_SHIFT 6
+#define PALMAS_PMU_CONFIG_SPARE_MASK 0x30
+#define PALMAS_PMU_CONFIG_SPARE_SHIFT 4
+#define PALMAS_PMU_CONFIG_SWOFF_DLY_MASK 0x0c
+#define PALMAS_PMU_CONFIG_SWOFF_DLY_SHIFT 2
+#define PALMAS_PMU_CONFIG_GATE_RESET_OUT 0x02
+#define PALMAS_PMU_CONFIG_GATE_RESET_OUT_SHIFT 1
+#define PALMAS_PMU_CONFIG_AUTODEVON 0x01
+#define PALMAS_PMU_CONFIG_AUTODEVON_SHIFT 0
+
+/* Bit definitions for SPARE */
+#define PALMAS_SPARE_SPARE_MASK 0xf8
+#define PALMAS_SPARE_SPARE_SHIFT 3
+#define PALMAS_SPARE_REGEN3_OD 0x04
+#define PALMAS_SPARE_REGEN3_OD_SHIFT 2
+#define PALMAS_SPARE_REGEN2_OD 0x02
+#define PALMAS_SPARE_REGEN2_OD_SHIFT 1
+#define PALMAS_SPARE_REGEN1_OD 0x01
+#define PALMAS_SPARE_REGEN1_OD_SHIFT 0
+
+/* Bit definitions for PMU_SECONDARY_INT */
+#define PALMAS_PMU_SECONDARY_INT_VBUS_OVV_INT_SRC 0x80
+#define PALMAS_PMU_SECONDARY_INT_VBUS_OVV_INT_SRC_SHIFT 7
+#define PALMAS_PMU_SECONDARY_INT_CHARG_DET_N_INT_SRC 0x40
+#define PALMAS_PMU_SECONDARY_INT_CHARG_DET_N_INT_SRC_SHIFT 6
+#define PALMAS_PMU_SECONDARY_INT_BB_INT_SRC 0x20
+#define PALMAS_PMU_SECONDARY_INT_BB_INT_SRC_SHIFT 5
+#define PALMAS_PMU_SECONDARY_INT_FBI_INT_SRC 0x10
+#define PALMAS_PMU_SECONDARY_INT_FBI_INT_SRC_SHIFT 4
+#define PALMAS_PMU_SECONDARY_INT_VBUS_OVV_MASK 0x08
+#define PALMAS_PMU_SECONDARY_INT_VBUS_OVV_MASK_SHIFT 3
+#define PALMAS_PMU_SECONDARY_INT_CHARG_DET_N_MASK 0x04
+#define PALMAS_PMU_SECONDARY_INT_CHARG_DET_N_MASK_SHIFT 2
+#define PALMAS_PMU_SECONDARY_INT_BB_MASK 0x02
+#define PALMAS_PMU_SECONDARY_INT_BB_MASK_SHIFT 1
+#define PALMAS_PMU_SECONDARY_INT_FBI_MASK 0x01
+#define PALMAS_PMU_SECONDARY_INT_FBI_MASK_SHIFT 0
+
+/* Bit definitions for SW_REVISION */
+#define PALMAS_SW_REVISION_SW_REVISION_MASK 0xff
+#define PALMAS_SW_REVISION_SW_REVISION_SHIFT 0
+
+/* Bit definitions for EXT_CHRG_CTRL */
+#define PALMAS_EXT_CHRG_CTRL_VBUS_OVV_STATUS 0x80
+#define PALMAS_EXT_CHRG_CTRL_VBUS_OVV_STATUS_SHIFT 7
+#define PALMAS_EXT_CHRG_CTRL_CHARG_DET_N_STATUS 0x40
+#define PALMAS_EXT_CHRG_CTRL_CHARG_DET_N_STATUS_SHIFT 6
+#define PALMAS_EXT_CHRG_CTRL_VSYS_DEBOUNCE_DELAY 0x08
+#define PALMAS_EXT_CHRG_CTRL_VSYS_DEBOUNCE_DELAY_SHIFT 3
+#define PALMAS_EXT_CHRG_CTRL_CHRG_DET_N 0x04
+#define PALMAS_EXT_CHRG_CTRL_CHRG_DET_N_SHIFT 2
+#define PALMAS_EXT_CHRG_CTRL_AUTO_ACA_EN 0x02
+#define PALMAS_EXT_CHRG_CTRL_AUTO_ACA_EN_SHIFT 1
+#define PALMAS_EXT_CHRG_CTRL_AUTO_LDOUSB_EN 0x01
+#define PALMAS_EXT_CHRG_CTRL_AUTO_LDOUSB_EN_SHIFT 0
+
+/* Bit definitions for PMU_SECONDARY_INT2 */
+#define PALMAS_PMU_SECONDARY_INT2_DVFS2_INT_SRC 0x20
+#define PALMAS_PMU_SECONDARY_INT2_DVFS2_INT_SRC_SHIFT 5
+#define PALMAS_PMU_SECONDARY_INT2_DVFS1_INT_SRC 0x10
+#define PALMAS_PMU_SECONDARY_INT2_DVFS1_INT_SRC_SHIFT 4
+#define PALMAS_PMU_SECONDARY_INT2_DVFS2_MASK 0x02
+#define PALMAS_PMU_SECONDARY_INT2_DVFS2_MASK_SHIFT 1
+#define PALMAS_PMU_SECONDARY_INT2_DVFS1_MASK 0x01
+#define PALMAS_PMU_SECONDARY_INT2_DVFS1_MASK_SHIFT 0
+
+/* Registers for function RESOURCE */
+#define PALMAS_CLK32KG_CTRL 0x0
+#define PALMAS_CLK32KGAUDIO_CTRL 0x1
+#define PALMAS_REGEN1_CTRL 0x2
+#define PALMAS_REGEN2_CTRL 0x3
+#define PALMAS_SYSEN1_CTRL 0x4
+#define PALMAS_SYSEN2_CTRL 0x5
+#define PALMAS_NSLEEP_RES_ASSIGN 0x6
+#define PALMAS_NSLEEP_SMPS_ASSIGN 0x7
+#define PALMAS_NSLEEP_LDO_ASSIGN1 0x8
+#define PALMAS_NSLEEP_LDO_ASSIGN2 0x9
+#define PALMAS_ENABLE1_RES_ASSIGN 0xA
+#define PALMAS_ENABLE1_SMPS_ASSIGN 0xB
+#define PALMAS_ENABLE1_LDO_ASSIGN1 0xC
+#define PALMAS_ENABLE1_LDO_ASSIGN2 0xD
+#define PALMAS_ENABLE2_RES_ASSIGN 0xE
+#define PALMAS_ENABLE2_SMPS_ASSIGN 0xF
+#define PALMAS_ENABLE2_LDO_ASSIGN1 0x10
+#define PALMAS_ENABLE2_LDO_ASSIGN2 0x11
+#define PALMAS_REGEN3_CTRL 0x12
+
+/* Bit definitions for CLK32KG_CTRL */
+#define PALMAS_CLK32KG_CTRL_STATUS 0x10
+#define PALMAS_CLK32KG_CTRL_STATUS_SHIFT 4
+#define PALMAS_CLK32KG_CTRL_MODE_SLEEP 0x04
+#define PALMAS_CLK32KG_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_CLK32KG_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_CLK32KG_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for CLK32KGAUDIO_CTRL */
+#define PALMAS_CLK32KGAUDIO_CTRL_STATUS 0x10
+#define PALMAS_CLK32KGAUDIO_CTRL_STATUS_SHIFT 4
+#define PALMAS_CLK32KGAUDIO_CTRL_RESERVED3 0x08
+#define PALMAS_CLK32KGAUDIO_CTRL_RESERVED3_SHIFT 3
+#define PALMAS_CLK32KGAUDIO_CTRL_MODE_SLEEP 0x04
+#define PALMAS_CLK32KGAUDIO_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for REGEN1_CTRL */
+#define PALMAS_REGEN1_CTRL_STATUS 0x10
+#define PALMAS_REGEN1_CTRL_STATUS_SHIFT 4
+#define PALMAS_REGEN1_CTRL_MODE_SLEEP 0x04
+#define PALMAS_REGEN1_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_REGEN1_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_REGEN1_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for REGEN2_CTRL */
+#define PALMAS_REGEN2_CTRL_STATUS 0x10
+#define PALMAS_REGEN2_CTRL_STATUS_SHIFT 4
+#define PALMAS_REGEN2_CTRL_MODE_SLEEP 0x04
+#define PALMAS_REGEN2_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_REGEN2_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_REGEN2_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for SYSEN1_CTRL */
+#define PALMAS_SYSEN1_CTRL_STATUS 0x10
+#define PALMAS_SYSEN1_CTRL_STATUS_SHIFT 4
+#define PALMAS_SYSEN1_CTRL_MODE_SLEEP 0x04
+#define PALMAS_SYSEN1_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SYSEN1_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_SYSEN1_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for SYSEN2_CTRL */
+#define PALMAS_SYSEN2_CTRL_STATUS 0x10
+#define PALMAS_SYSEN2_CTRL_STATUS_SHIFT 4
+#define PALMAS_SYSEN2_CTRL_MODE_SLEEP 0x04
+#define PALMAS_SYSEN2_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SYSEN2_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_SYSEN2_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Bit definitions for NSLEEP_RES_ASSIGN */
+#define PALMAS_NSLEEP_RES_ASSIGN_REGEN3 0x40
+#define PALMAS_NSLEEP_RES_ASSIGN_REGEN3_SHIFT 6
+#define PALMAS_NSLEEP_RES_ASSIGN_CLK32KGAUDIO 0x20
+#define PALMAS_NSLEEP_RES_ASSIGN_CLK32KGAUDIO_SHIFT 5
+#define PALMAS_NSLEEP_RES_ASSIGN_CLK32KG 0x10
+#define PALMAS_NSLEEP_RES_ASSIGN_CLK32KG_SHIFT 4
+#define PALMAS_NSLEEP_RES_ASSIGN_SYSEN2 0x08
+#define PALMAS_NSLEEP_RES_ASSIGN_SYSEN2_SHIFT 3
+#define PALMAS_NSLEEP_RES_ASSIGN_SYSEN1 0x04
+#define PALMAS_NSLEEP_RES_ASSIGN_SYSEN1_SHIFT 2
+#define PALMAS_NSLEEP_RES_ASSIGN_REGEN2 0x02
+#define PALMAS_NSLEEP_RES_ASSIGN_REGEN2_SHIFT 1
+#define PALMAS_NSLEEP_RES_ASSIGN_REGEN1 0x01
+#define PALMAS_NSLEEP_RES_ASSIGN_REGEN1_SHIFT 0
+
+/* Bit definitions for NSLEEP_SMPS_ASSIGN */
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS10 0x80
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS10_SHIFT 7
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS9 0x40
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS9_SHIFT 6
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS8 0x20
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS8_SHIFT 5
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS7 0x10
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS7_SHIFT 4
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS6 0x08
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS6_SHIFT 3
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS45 0x04
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS45_SHIFT 2
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS3 0x02
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS3_SHIFT 1
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS12 0x01
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS12_SHIFT 0
+
+/* Bit definitions for NSLEEP_LDO_ASSIGN1 */
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO8 0x80
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO8_SHIFT 7
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO7 0x40
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO7_SHIFT 6
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO6 0x20
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO6_SHIFT 5
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO5 0x10
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO5_SHIFT 4
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO4 0x08
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO4_SHIFT 3
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO3 0x04
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO3_SHIFT 2
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO2 0x02
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO2_SHIFT 1
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO1 0x01
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO1_SHIFT 0
+
+/* Bit definitions for NSLEEP_LDO_ASSIGN2 */
+#define PALMAS_NSLEEP_LDO_ASSIGN2_LDOUSB 0x04
+#define PALMAS_NSLEEP_LDO_ASSIGN2_LDOUSB_SHIFT 2
+#define PALMAS_NSLEEP_LDO_ASSIGN2_LDOLN 0x02
+#define PALMAS_NSLEEP_LDO_ASSIGN2_LDOLN_SHIFT 1
+#define PALMAS_NSLEEP_LDO_ASSIGN2_LDO9 0x01
+#define PALMAS_NSLEEP_LDO_ASSIGN2_LDO9_SHIFT 0
+
+/* Bit definitions for ENABLE1_RES_ASSIGN */
+#define PALMAS_ENABLE1_RES_ASSIGN_REGEN3 0x40
+#define PALMAS_ENABLE1_RES_ASSIGN_REGEN3_SHIFT 6
+#define PALMAS_ENABLE1_RES_ASSIGN_CLK32KGAUDIO 0x20
+#define PALMAS_ENABLE1_RES_ASSIGN_CLK32KGAUDIO_SHIFT 5
+#define PALMAS_ENABLE1_RES_ASSIGN_CLK32KG 0x10
+#define PALMAS_ENABLE1_RES_ASSIGN_CLK32KG_SHIFT 4
+#define PALMAS_ENABLE1_RES_ASSIGN_SYSEN2 0x08
+#define PALMAS_ENABLE1_RES_ASSIGN_SYSEN2_SHIFT 3
+#define PALMAS_ENABLE1_RES_ASSIGN_SYSEN1 0x04
+#define PALMAS_ENABLE1_RES_ASSIGN_SYSEN1_SHIFT 2
+#define PALMAS_ENABLE1_RES_ASSIGN_REGEN2 0x02
+#define PALMAS_ENABLE1_RES_ASSIGN_REGEN2_SHIFT 1
+#define PALMAS_ENABLE1_RES_ASSIGN_REGEN1 0x01
+#define PALMAS_ENABLE1_RES_ASSIGN_REGEN1_SHIFT 0
+
+/* Bit definitions for ENABLE1_SMPS_ASSIGN */
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS10 0x80
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS10_SHIFT 7
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS9 0x40
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS9_SHIFT 6
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS8 0x20
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS8_SHIFT 5
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS7 0x10
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS7_SHIFT 4
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS6 0x08
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS6_SHIFT 3
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS45 0x04
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS45_SHIFT 2
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS3 0x02
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS3_SHIFT 1
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS12 0x01
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS12_SHIFT 0
+
+/* Bit definitions for ENABLE1_LDO_ASSIGN1 */
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO8 0x80
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO8_SHIFT 7
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO7 0x40
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO7_SHIFT 6
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO6 0x20
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO6_SHIFT 5
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO5 0x10
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO5_SHIFT 4
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO4 0x08
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO4_SHIFT 3
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO3 0x04
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO3_SHIFT 2
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO2 0x02
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO2_SHIFT 1
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO1 0x01
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO1_SHIFT 0
+
+/* Bit definitions for ENABLE1_LDO_ASSIGN2 */
+#define PALMAS_ENABLE1_LDO_ASSIGN2_LDOUSB 0x04
+#define PALMAS_ENABLE1_LDO_ASSIGN2_LDOUSB_SHIFT 2
+#define PALMAS_ENABLE1_LDO_ASSIGN2_LDOLN 0x02
+#define PALMAS_ENABLE1_LDO_ASSIGN2_LDOLN_SHIFT 1
+#define PALMAS_ENABLE1_LDO_ASSIGN2_LDO9 0x01
+#define PALMAS_ENABLE1_LDO_ASSIGN2_LDO9_SHIFT 0
+
+/* Bit definitions for ENABLE2_RES_ASSIGN */
+#define PALMAS_ENABLE2_RES_ASSIGN_REGEN3 0x40
+#define PALMAS_ENABLE2_RES_ASSIGN_REGEN3_SHIFT 6
+#define PALMAS_ENABLE2_RES_ASSIGN_CLK32KGAUDIO 0x20
+#define PALMAS_ENABLE2_RES_ASSIGN_CLK32KGAUDIO_SHIFT 5
+#define PALMAS_ENABLE2_RES_ASSIGN_CLK32KG 0x10
+#define PALMAS_ENABLE2_RES_ASSIGN_CLK32KG_SHIFT 4
+#define PALMAS_ENABLE2_RES_ASSIGN_SYSEN2 0x08
+#define PALMAS_ENABLE2_RES_ASSIGN_SYSEN2_SHIFT 3
+#define PALMAS_ENABLE2_RES_ASSIGN_SYSEN1 0x04
+#define PALMAS_ENABLE2_RES_ASSIGN_SYSEN1_SHIFT 2
+#define PALMAS_ENABLE2_RES_ASSIGN_REGEN2 0x02
+#define PALMAS_ENABLE2_RES_ASSIGN_REGEN2_SHIFT 1
+#define PALMAS_ENABLE2_RES_ASSIGN_REGEN1 0x01
+#define PALMAS_ENABLE2_RES_ASSIGN_REGEN1_SHIFT 0
+
+/* Bit definitions for ENABLE2_SMPS_ASSIGN */
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS10 0x80
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS10_SHIFT 7
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS9 0x40
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS9_SHIFT 6
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS8 0x20
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS8_SHIFT 5
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS7 0x10
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS7_SHIFT 4
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS6 0x08
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS6_SHIFT 3
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS45 0x04
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS45_SHIFT 2
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS3 0x02
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS3_SHIFT 1
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS12 0x01
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS12_SHIFT 0
+
+/* Bit definitions for ENABLE2_LDO_ASSIGN1 */
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO8 0x80
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO8_SHIFT 7
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO7 0x40
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO7_SHIFT 6
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO6 0x20
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO6_SHIFT 5
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO5 0x10
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO5_SHIFT 4
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO4 0x08
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO4_SHIFT 3
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO3 0x04
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO3_SHIFT 2
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO2 0x02
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO2_SHIFT 1
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO1 0x01
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO1_SHIFT 0
+
+/* Bit definitions for ENABLE2_LDO_ASSIGN2 */
+#define PALMAS_ENABLE2_LDO_ASSIGN2_LDOUSB 0x04
+#define PALMAS_ENABLE2_LDO_ASSIGN2_LDOUSB_SHIFT 2
+#define PALMAS_ENABLE2_LDO_ASSIGN2_LDOLN 0x02
+#define PALMAS_ENABLE2_LDO_ASSIGN2_LDOLN_SHIFT 1
+#define PALMAS_ENABLE2_LDO_ASSIGN2_LDO9 0x01
+#define PALMAS_ENABLE2_LDO_ASSIGN2_LDO9_SHIFT 0
+
+/* Bit definitions for REGEN3_CTRL */
+#define PALMAS_REGEN3_CTRL_STATUS 0x10
+#define PALMAS_REGEN3_CTRL_STATUS_SHIFT 4
+#define PALMAS_REGEN3_CTRL_MODE_SLEEP 0x04
+#define PALMAS_REGEN3_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_REGEN3_CTRL_MODE_ACTIVE 0x01
+#define PALMAS_REGEN3_CTRL_MODE_ACTIVE_SHIFT 0
+
+/* Registers for function PAD_CONTROL */
+#define PALMAS_PU_PD_INPUT_CTRL1 0x0
+#define PALMAS_PU_PD_INPUT_CTRL2 0x1
+#define PALMAS_PU_PD_INPUT_CTRL3 0x2
+#define PALMAS_OD_OUTPUT_CTRL 0x4
+#define PALMAS_POLARITY_CTRL 0x5
+#define PALMAS_PRIMARY_SECONDARY_PAD1 0x6
+#define PALMAS_PRIMARY_SECONDARY_PAD2 0x7
+#define PALMAS_I2C_SPI 0x8
+#define PALMAS_PU_PD_INPUT_CTRL4 0x9
+#define PALMAS_PRIMARY_SECONDARY_PAD3 0xA
+
+/* Bit definitions for PU_PD_INPUT_CTRL1 */
+#define PALMAS_PU_PD_INPUT_CTRL1_RESET_IN_PD 0x40
+#define PALMAS_PU_PD_INPUT_CTRL1_RESET_IN_PD_SHIFT 6
+#define PALMAS_PU_PD_INPUT_CTRL1_GPADC_START_PU 0x20
+#define PALMAS_PU_PD_INPUT_CTRL1_GPADC_START_PU_SHIFT 5
+#define PALMAS_PU_PD_INPUT_CTRL1_GPADC_START_PD 0x10
+#define PALMAS_PU_PD_INPUT_CTRL1_GPADC_START_PD_SHIFT 4
+#define PALMAS_PU_PD_INPUT_CTRL1_PWRDOWN_PD 0x04
+#define PALMAS_PU_PD_INPUT_CTRL1_PWRDOWN_PD_SHIFT 2
+#define PALMAS_PU_PD_INPUT_CTRL1_NRESWARM_PU 0x02
+#define PALMAS_PU_PD_INPUT_CTRL1_NRESWARM_PU_SHIFT 1
+
+/* Bit definitions for PU_PD_INPUT_CTRL2 */
+#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE2_PU 0x20
+#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE2_PU_SHIFT 5
+#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE2_PD 0x10
+#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE2_PD_SHIFT 4
+#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE1_PU 0x08
+#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE1_PU_SHIFT 3
+#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE1_PD 0x04
+#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE1_PD_SHIFT 2
+#define PALMAS_PU_PD_INPUT_CTRL2_NSLEEP_PU 0x02
+#define PALMAS_PU_PD_INPUT_CTRL2_NSLEEP_PU_SHIFT 1
+#define PALMAS_PU_PD_INPUT_CTRL2_NSLEEP_PD 0x01
+#define PALMAS_PU_PD_INPUT_CTRL2_NSLEEP_PD_SHIFT 0
+
+/* Bit definitions for PU_PD_INPUT_CTRL3 */
+#define PALMAS_PU_PD_INPUT_CTRL3_ACOK_PD 0x40
+#define PALMAS_PU_PD_INPUT_CTRL3_ACOK_PD_SHIFT 6
+#define PALMAS_PU_PD_INPUT_CTRL3_CHRG_DET_N_PD 0x10
+#define PALMAS_PU_PD_INPUT_CTRL3_CHRG_DET_N_PD_SHIFT 4
+#define PALMAS_PU_PD_INPUT_CTRL3_POWERHOLD_PD 0x04
+#define PALMAS_PU_PD_INPUT_CTRL3_POWERHOLD_PD_SHIFT 2
+#define PALMAS_PU_PD_INPUT_CTRL3_MSECURE_PD 0x01
+#define PALMAS_PU_PD_INPUT_CTRL3_MSECURE_PD_SHIFT 0
+
+/* Bit definitions for OD_OUTPUT_CTRL */
+#define PALMAS_OD_OUTPUT_CTRL_PWM_2_OD 0x80
+#define PALMAS_OD_OUTPUT_CTRL_PWM_2_OD_SHIFT 7
+#define PALMAS_OD_OUTPUT_CTRL_VBUSDET_OD 0x40
+#define PALMAS_OD_OUTPUT_CTRL_VBUSDET_OD_SHIFT 6
+#define PALMAS_OD_OUTPUT_CTRL_PWM_1_OD 0x20
+#define PALMAS_OD_OUTPUT_CTRL_PWM_1_OD_SHIFT 5
+#define PALMAS_OD_OUTPUT_CTRL_INT_OD 0x08
+#define PALMAS_OD_OUTPUT_CTRL_INT_OD_SHIFT 3
+
+/* Bit definitions for POLARITY_CTRL */
+#define PALMAS_POLARITY_CTRL_INT_POLARITY 0x80
+#define PALMAS_POLARITY_CTRL_INT_POLARITY_SHIFT 7
+#define PALMAS_POLARITY_CTRL_ENABLE2_POLARITY 0x40
+#define PALMAS_POLARITY_CTRL_ENABLE2_POLARITY_SHIFT 6
+#define PALMAS_POLARITY_CTRL_ENABLE1_POLARITY 0x20
+#define PALMAS_POLARITY_CTRL_ENABLE1_POLARITY_SHIFT 5
+#define PALMAS_POLARITY_CTRL_NSLEEP_POLARITY 0x10
+#define PALMAS_POLARITY_CTRL_NSLEEP_POLARITY_SHIFT 4
+#define PALMAS_POLARITY_CTRL_RESET_IN_POLARITY 0x08
+#define PALMAS_POLARITY_CTRL_RESET_IN_POLARITY_SHIFT 3
+#define PALMAS_POLARITY_CTRL_GPIO_3_CHRG_DET_N_POLARITY 0x04
+#define PALMAS_POLARITY_CTRL_GPIO_3_CHRG_DET_N_POLARITY_SHIFT 2
+#define PALMAS_POLARITY_CTRL_POWERGOOD_USB_PSEL_POLARITY 0x02
+#define PALMAS_POLARITY_CTRL_POWERGOOD_USB_PSEL_POLARITY_SHIFT 1
+#define PALMAS_POLARITY_CTRL_PWRDOWN_POLARITY 0x01
+#define PALMAS_POLARITY_CTRL_PWRDOWN_POLARITY_SHIFT 0
+
+/* Bit definitions for PRIMARY_SECONDARY_PAD1 */
+#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_3 0x80
+#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_3_SHIFT 7
+#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK 0x60
+#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_SHIFT 5
+#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK 0x18
+#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT 3
+#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_0 0x04
+#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_0_SHIFT 2
+#define PALMAS_PRIMARY_SECONDARY_PAD1_VAC 0x02
+#define PALMAS_PRIMARY_SECONDARY_PAD1_VAC_SHIFT 1
+#define PALMAS_PRIMARY_SECONDARY_PAD1_POWERGOOD 0x01
+#define PALMAS_PRIMARY_SECONDARY_PAD1_POWERGOOD_SHIFT 0
+
+/* Bit definitions for PRIMARY_SECONDARY_PAD2 */
+#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_MASK 0x30
+#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_SHIFT 4
+#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_6 0x08
+#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_6_SHIFT 3
+#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_5_MASK 0x06
+#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_5_SHIFT 1
+#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_4 0x01
+#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_4_SHIFT 0
+
+/* Bit definitions for I2C_SPI */
+#define PALMAS_I2C_SPI_I2C2OTP_EN 0x80
+#define PALMAS_I2C_SPI_I2C2OTP_EN_SHIFT 7
+#define PALMAS_I2C_SPI_I2C2OTP_PAGESEL 0x40
+#define PALMAS_I2C_SPI_I2C2OTP_PAGESEL_SHIFT 6
+#define PALMAS_I2C_SPI_ID_I2C2 0x20
+#define PALMAS_I2C_SPI_ID_I2C2_SHIFT 5
+#define PALMAS_I2C_SPI_I2C_SPI 0x10
+#define PALMAS_I2C_SPI_I2C_SPI_SHIFT 4
+#define PALMAS_I2C_SPI_ID_I2C1_MASK 0x0f
+#define PALMAS_I2C_SPI_ID_I2C1_SHIFT 0
+
+/* Bit definitions for PU_PD_INPUT_CTRL4 */
+#define PALMAS_PU_PD_INPUT_CTRL4_DVFS2_DAT_PD 0x40
+#define PALMAS_PU_PD_INPUT_CTRL4_DVFS2_DAT_PD_SHIFT 6
+#define PALMAS_PU_PD_INPUT_CTRL4_DVFS2_CLK_PD 0x10
+#define PALMAS_PU_PD_INPUT_CTRL4_DVFS2_CLK_PD_SHIFT 4
+#define PALMAS_PU_PD_INPUT_CTRL4_DVFS1_DAT_PD 0x04
+#define PALMAS_PU_PD_INPUT_CTRL4_DVFS1_DAT_PD_SHIFT 2
+#define PALMAS_PU_PD_INPUT_CTRL4_DVFS1_CLK_PD 0x01
+#define PALMAS_PU_PD_INPUT_CTRL4_DVFS1_CLK_PD_SHIFT 0
+
+/* Bit definitions for PRIMARY_SECONDARY_PAD3 */
+#define PALMAS_PRIMARY_SECONDARY_PAD3_DVFS2 0x02
+#define PALMAS_PRIMARY_SECONDARY_PAD3_DVFS2_SHIFT 1
+#define PALMAS_PRIMARY_SECONDARY_PAD3_DVFS1 0x01
+#define PALMAS_PRIMARY_SECONDARY_PAD3_DVFS1_SHIFT 0
+
+/* Registers for function LED_PWM */
+#define PALMAS_LED_PERIOD_CTRL 0x0
+#define PALMAS_LED_CTRL 0x1
+#define PALMAS_PWM_CTRL1 0x2
+#define PALMAS_PWM_CTRL2 0x3
+
+/* Bit definitions for LED_PERIOD_CTRL */
+#define PALMAS_LED_PERIOD_CTRL_LED_2_PERIOD_MASK 0x38
+#define PALMAS_LED_PERIOD_CTRL_LED_2_PERIOD_SHIFT 3
+#define PALMAS_LED_PERIOD_CTRL_LED_1_PERIOD_MASK 0x07
+#define PALMAS_LED_PERIOD_CTRL_LED_1_PERIOD_SHIFT 0
+
+/* Bit definitions for LED_CTRL */
+#define PALMAS_LED_CTRL_LED_2_SEQ 0x20
+#define PALMAS_LED_CTRL_LED_2_SEQ_SHIFT 5
+#define PALMAS_LED_CTRL_LED_1_SEQ 0x10
+#define PALMAS_LED_CTRL_LED_1_SEQ_SHIFT 4
+#define PALMAS_LED_CTRL_LED_2_ON_TIME_MASK 0x0c
+#define PALMAS_LED_CTRL_LED_2_ON_TIME_SHIFT 2
+#define PALMAS_LED_CTRL_LED_1_ON_TIME_MASK 0x03
+#define PALMAS_LED_CTRL_LED_1_ON_TIME_SHIFT 0
+
+/* Bit definitions for PWM_CTRL1 */
+#define PALMAS_PWM_CTRL1_PWM_FREQ_EN 0x02
+#define PALMAS_PWM_CTRL1_PWM_FREQ_EN_SHIFT 1
+#define PALMAS_PWM_CTRL1_PWM_FREQ_SEL 0x01
+#define PALMAS_PWM_CTRL1_PWM_FREQ_SEL_SHIFT 0
+
+/* Bit definitions for PWM_CTRL2 */
+#define PALMAS_PWM_CTRL2_PWM_DUTY_SEL_MASK 0xff
+#define PALMAS_PWM_CTRL2_PWM_DUTY_SEL_SHIFT 0
+
+/* Registers for function INTERRUPT */
+#define PALMAS_INT1_STATUS 0x0
+#define PALMAS_INT1_MASK 0x1
+#define PALMAS_INT1_LINE_STATE 0x2
+#define PALMAS_INT1_EDGE_DETECT1_RESERVED 0x3
+#define PALMAS_INT1_EDGE_DETECT2_RESERVED 0x4
+#define PALMAS_INT2_STATUS 0x5
+#define PALMAS_INT2_MASK 0x6
+#define PALMAS_INT2_LINE_STATE 0x7
+#define PALMAS_INT2_EDGE_DETECT1_RESERVED 0x8
+#define PALMAS_INT2_EDGE_DETECT2_RESERVED 0x9
+#define PALMAS_INT3_STATUS 0xA
+#define PALMAS_INT3_MASK 0xB
+#define PALMAS_INT3_LINE_STATE 0xC
+#define PALMAS_INT3_EDGE_DETECT1_RESERVED 0xD
+#define PALMAS_INT3_EDGE_DETECT2_RESERVED 0xE
+#define PALMAS_INT4_STATUS 0xF
+#define PALMAS_INT4_MASK 0x10
+#define PALMAS_INT4_LINE_STATE 0x11
+#define PALMAS_INT4_EDGE_DETECT1 0x12
+#define PALMAS_INT4_EDGE_DETECT2 0x13
+#define PALMAS_INT_CTRL 0x14
+
+/* Bit definitions for INT1_STATUS */
+#define PALMAS_INT1_STATUS_VBAT_MON 0x80
+#define PALMAS_INT1_STATUS_VBAT_MON_SHIFT 7
+#define PALMAS_INT1_STATUS_VSYS_MON 0x40
+#define PALMAS_INT1_STATUS_VSYS_MON_SHIFT 6
+#define PALMAS_INT1_STATUS_HOTDIE 0x20
+#define PALMAS_INT1_STATUS_HOTDIE_SHIFT 5
+#define PALMAS_INT1_STATUS_PWRDOWN 0x10
+#define PALMAS_INT1_STATUS_PWRDOWN_SHIFT 4
+#define PALMAS_INT1_STATUS_RPWRON 0x08
+#define PALMAS_INT1_STATUS_RPWRON_SHIFT 3
+#define PALMAS_INT1_STATUS_LONG_PRESS_KEY 0x04
+#define PALMAS_INT1_STATUS_LONG_PRESS_KEY_SHIFT 2
+#define PALMAS_INT1_STATUS_PWRON 0x02
+#define PALMAS_INT1_STATUS_PWRON_SHIFT 1
+#define PALMAS_INT1_STATUS_CHARG_DET_N_VBUS_OVV 0x01
+#define PALMAS_INT1_STATUS_CHARG_DET_N_VBUS_OVV_SHIFT 0
+
+/* Bit definitions for INT1_MASK */
+#define PALMAS_INT1_MASK_VBAT_MON 0x80
+#define PALMAS_INT1_MASK_VBAT_MON_SHIFT 7
+#define PALMAS_INT1_MASK_VSYS_MON 0x40
+#define PALMAS_INT1_MASK_VSYS_MON_SHIFT 6
+#define PALMAS_INT1_MASK_HOTDIE 0x20
+#define PALMAS_INT1_MASK_HOTDIE_SHIFT 5
+#define PALMAS_INT1_MASK_PWRDOWN 0x10
+#define PALMAS_INT1_MASK_PWRDOWN_SHIFT 4
+#define PALMAS_INT1_MASK_RPWRON 0x08
+#define PALMAS_INT1_MASK_RPWRON_SHIFT 3
+#define PALMAS_INT1_MASK_LONG_PRESS_KEY 0x04
+#define PALMAS_INT1_MASK_LONG_PRESS_KEY_SHIFT 2
+#define PALMAS_INT1_MASK_PWRON 0x02
+#define PALMAS_INT1_MASK_PWRON_SHIFT 1
+#define PALMAS_INT1_MASK_CHARG_DET_N_VBUS_OVV 0x01
+#define PALMAS_INT1_MASK_CHARG_DET_N_VBUS_OVV_SHIFT 0
+
+/* Bit definitions for INT1_LINE_STATE */
+#define PALMAS_INT1_LINE_STATE_VBAT_MON 0x80
+#define PALMAS_INT1_LINE_STATE_VBAT_MON_SHIFT 7
+#define PALMAS_INT1_LINE_STATE_VSYS_MON 0x40
+#define PALMAS_INT1_LINE_STATE_VSYS_MON_SHIFT 6
+#define PALMAS_INT1_LINE_STATE_HOTDIE 0x20
+#define PALMAS_INT1_LINE_STATE_HOTDIE_SHIFT 5
+#define PALMAS_INT1_LINE_STATE_PWRDOWN 0x10
+#define PALMAS_INT1_LINE_STATE_PWRDOWN_SHIFT 4
+#define PALMAS_INT1_LINE_STATE_RPWRON 0x08
+#define PALMAS_INT1_LINE_STATE_RPWRON_SHIFT 3
+#define PALMAS_INT1_LINE_STATE_LONG_PRESS_KEY 0x04
+#define PALMAS_INT1_LINE_STATE_LONG_PRESS_KEY_SHIFT 2
+#define PALMAS_INT1_LINE_STATE_PWRON 0x02
+#define PALMAS_INT1_LINE_STATE_PWRON_SHIFT 1
+#define PALMAS_INT1_LINE_STATE_CHARG_DET_N_VBUS_OVV 0x01
+#define PALMAS_INT1_LINE_STATE_CHARG_DET_N_VBUS_OVV_SHIFT 0
+
+/* Bit definitions for INT2_STATUS */
+#define PALMAS_INT2_STATUS_VAC_ACOK 0x80
+#define PALMAS_INT2_STATUS_VAC_ACOK_SHIFT 7
+#define PALMAS_INT2_STATUS_SHORT 0x40
+#define PALMAS_INT2_STATUS_SHORT_SHIFT 6
+#define PALMAS_INT2_STATUS_FBI_BB 0x20
+#define PALMAS_INT2_STATUS_FBI_BB_SHIFT 5
+#define PALMAS_INT2_STATUS_RESET_IN 0x10
+#define PALMAS_INT2_STATUS_RESET_IN_SHIFT 4
+#define PALMAS_INT2_STATUS_BATREMOVAL 0x08
+#define PALMAS_INT2_STATUS_BATREMOVAL_SHIFT 3
+#define PALMAS_INT2_STATUS_WDT 0x04
+#define PALMAS_INT2_STATUS_WDT_SHIFT 2
+#define PALMAS_INT2_STATUS_RTC_TIMER 0x02
+#define PALMAS_INT2_STATUS_RTC_TIMER_SHIFT 1
+#define PALMAS_INT2_STATUS_RTC_ALARM 0x01
+#define PALMAS_INT2_STATUS_RTC_ALARM_SHIFT 0
+
+/* Bit definitions for INT2_MASK */
+#define PALMAS_INT2_MASK_VAC_ACOK 0x80
+#define PALMAS_INT2_MASK_VAC_ACOK_SHIFT 7
+#define PALMAS_INT2_MASK_SHORT 0x40
+#define PALMAS_INT2_MASK_SHORT_SHIFT 6
+#define PALMAS_INT2_MASK_FBI_BB 0x20
+#define PALMAS_INT2_MASK_FBI_BB_SHIFT 5
+#define PALMAS_INT2_MASK_RESET_IN 0x10
+#define PALMAS_INT2_MASK_RESET_IN_SHIFT 4
+#define PALMAS_INT2_MASK_BATREMOVAL 0x08
+#define PALMAS_INT2_MASK_BATREMOVAL_SHIFT 3
+#define PALMAS_INT2_MASK_WDT 0x04
+#define PALMAS_INT2_MASK_WDT_SHIFT 2
+#define PALMAS_INT2_MASK_RTC_TIMER 0x02
+#define PALMAS_INT2_MASK_RTC_TIMER_SHIFT 1
+#define PALMAS_INT2_MASK_RTC_ALARM 0x01
+#define PALMAS_INT2_MASK_RTC_ALARM_SHIFT 0
+
+/* Bit definitions for INT2_LINE_STATE */
+#define PALMAS_INT2_LINE_STATE_VAC_ACOK 0x80
+#define PALMAS_INT2_LINE_STATE_VAC_ACOK_SHIFT 7
+#define PALMAS_INT2_LINE_STATE_SHORT 0x40
+#define PALMAS_INT2_LINE_STATE_SHORT_SHIFT 6
+#define PALMAS_INT2_LINE_STATE_FBI_BB 0x20
+#define PALMAS_INT2_LINE_STATE_FBI_BB_SHIFT 5
+#define PALMAS_INT2_LINE_STATE_RESET_IN 0x10
+#define PALMAS_INT2_LINE_STATE_RESET_IN_SHIFT 4
+#define PALMAS_INT2_LINE_STATE_BATREMOVAL 0x08
+#define PALMAS_INT2_LINE_STATE_BATREMOVAL_SHIFT 3
+#define PALMAS_INT2_LINE_STATE_WDT 0x04
+#define PALMAS_INT2_LINE_STATE_WDT_SHIFT 2
+#define PALMAS_INT2_LINE_STATE_RTC_TIMER 0x02
+#define PALMAS_INT2_LINE_STATE_RTC_TIMER_SHIFT 1
+#define PALMAS_INT2_LINE_STATE_RTC_ALARM 0x01
+#define PALMAS_INT2_LINE_STATE_RTC_ALARM_SHIFT 0
+
+/* Bit definitions for INT3_STATUS */
+#define PALMAS_INT3_STATUS_VBUS 0x80
+#define PALMAS_INT3_STATUS_VBUS_SHIFT 7
+#define PALMAS_INT3_STATUS_VBUS_OTG 0x40
+#define PALMAS_INT3_STATUS_VBUS_OTG_SHIFT 6
+#define PALMAS_INT3_STATUS_ID 0x20
+#define PALMAS_INT3_STATUS_ID_SHIFT 5
+#define PALMAS_INT3_STATUS_ID_OTG 0x10
+#define PALMAS_INT3_STATUS_ID_OTG_SHIFT 4
+#define PALMAS_INT3_STATUS_GPADC_EOC_RT 0x08
+#define PALMAS_INT3_STATUS_GPADC_EOC_RT_SHIFT 3
+#define PALMAS_INT3_STATUS_GPADC_EOC_SW 0x04
+#define PALMAS_INT3_STATUS_GPADC_EOC_SW_SHIFT 2
+#define PALMAS_INT3_STATUS_GPADC_AUTO_1 0x02
+#define PALMAS_INT3_STATUS_GPADC_AUTO_1_SHIFT 1
+#define PALMAS_INT3_STATUS_GPADC_AUTO_0 0x01
+#define PALMAS_INT3_STATUS_GPADC_AUTO_0_SHIFT 0
+
+/* Bit definitions for INT3_MASK */
+#define PALMAS_INT3_MASK_VBUS 0x80
+#define PALMAS_INT3_MASK_VBUS_SHIFT 7
+#define PALMAS_INT3_MASK_VBUS_OTG 0x40
+#define PALMAS_INT3_MASK_VBUS_OTG_SHIFT 6
+#define PALMAS_INT3_MASK_ID 0x20
+#define PALMAS_INT3_MASK_ID_SHIFT 5
+#define PALMAS_INT3_MASK_ID_OTG 0x10
+#define PALMAS_INT3_MASK_ID_OTG_SHIFT 4
+#define PALMAS_INT3_MASK_GPADC_EOC_RT 0x08
+#define PALMAS_INT3_MASK_GPADC_EOC_RT_SHIFT 3
+#define PALMAS_INT3_MASK_GPADC_EOC_SW 0x04
+#define PALMAS_INT3_MASK_GPADC_EOC_SW_SHIFT 2
+#define PALMAS_INT3_MASK_GPADC_AUTO_1 0x02
+#define PALMAS_INT3_MASK_GPADC_AUTO_1_SHIFT 1
+#define PALMAS_INT3_MASK_GPADC_AUTO_0 0x01
+#define PALMAS_INT3_MASK_GPADC_AUTO_0_SHIFT 0
+
+/* Bit definitions for INT3_LINE_STATE */
+#define PALMAS_INT3_LINE_STATE_VBUS 0x80
+#define PALMAS_INT3_LINE_STATE_VBUS_SHIFT 7
+#define PALMAS_INT3_LINE_STATE_VBUS_OTG 0x40
+#define PALMAS_INT3_LINE_STATE_VBUS_OTG_SHIFT 6
+#define PALMAS_INT3_LINE_STATE_ID 0x20
+#define PALMAS_INT3_LINE_STATE_ID_SHIFT 5
+#define PALMAS_INT3_LINE_STATE_ID_OTG 0x10
+#define PALMAS_INT3_LINE_STATE_ID_OTG_SHIFT 4
+#define PALMAS_INT3_LINE_STATE_GPADC_EOC_RT 0x08
+#define PALMAS_INT3_LINE_STATE_GPADC_EOC_RT_SHIFT 3
+#define PALMAS_INT3_LINE_STATE_GPADC_EOC_SW 0x04
+#define PALMAS_INT3_LINE_STATE_GPADC_EOC_SW_SHIFT 2
+#define PALMAS_INT3_LINE_STATE_GPADC_AUTO_1 0x02
+#define PALMAS_INT3_LINE_STATE_GPADC_AUTO_1_SHIFT 1
+#define PALMAS_INT3_LINE_STATE_GPADC_AUTO_0 0x01
+#define PALMAS_INT3_LINE_STATE_GPADC_AUTO_0_SHIFT 0
+
+/* Bit definitions for INT4_STATUS */
+#define PALMAS_INT4_STATUS_GPIO_7 0x80
+#define PALMAS_INT4_STATUS_GPIO_7_SHIFT 7
+#define PALMAS_INT4_STATUS_GPIO_6 0x40
+#define PALMAS_INT4_STATUS_GPIO_6_SHIFT 6
+#define PALMAS_INT4_STATUS_GPIO_5 0x20
+#define PALMAS_INT4_STATUS_GPIO_5_SHIFT 5
+#define PALMAS_INT4_STATUS_GPIO_4 0x10
+#define PALMAS_INT4_STATUS_GPIO_4_SHIFT 4
+#define PALMAS_INT4_STATUS_GPIO_3 0x08
+#define PALMAS_INT4_STATUS_GPIO_3_SHIFT 3
+#define PALMAS_INT4_STATUS_GPIO_2 0x04
+#define PALMAS_INT4_STATUS_GPIO_2_SHIFT 2
+#define PALMAS_INT4_STATUS_GPIO_1 0x02
+#define PALMAS_INT4_STATUS_GPIO_1_SHIFT 1
+#define PALMAS_INT4_STATUS_GPIO_0 0x01
+#define PALMAS_INT4_STATUS_GPIO_0_SHIFT 0
+
+/* Bit definitions for INT4_MASK */
+#define PALMAS_INT4_MASK_GPIO_7 0x80
+#define PALMAS_INT4_MASK_GPIO_7_SHIFT 7
+#define PALMAS_INT4_MASK_GPIO_6 0x40
+#define PALMAS_INT4_MASK_GPIO_6_SHIFT 6
+#define PALMAS_INT4_MASK_GPIO_5 0x20
+#define PALMAS_INT4_MASK_GPIO_5_SHIFT 5
+#define PALMAS_INT4_MASK_GPIO_4 0x10
+#define PALMAS_INT4_MASK_GPIO_4_SHIFT 4
+#define PALMAS_INT4_MASK_GPIO_3 0x08
+#define PALMAS_INT4_MASK_GPIO_3_SHIFT 3
+#define PALMAS_INT4_MASK_GPIO_2 0x04
+#define PALMAS_INT4_MASK_GPIO_2_SHIFT 2
+#define PALMAS_INT4_MASK_GPIO_1 0x02
+#define PALMAS_INT4_MASK_GPIO_1_SHIFT 1
+#define PALMAS_INT4_MASK_GPIO_0 0x01
+#define PALMAS_INT4_MASK_GPIO_0_SHIFT 0
+
+/* Bit definitions for INT4_LINE_STATE */
+#define PALMAS_INT4_LINE_STATE_GPIO_7 0x80
+#define PALMAS_INT4_LINE_STATE_GPIO_7_SHIFT 7
+#define PALMAS_INT4_LINE_STATE_GPIO_6 0x40
+#define PALMAS_INT4_LINE_STATE_GPIO_6_SHIFT 6
+#define PALMAS_INT4_LINE_STATE_GPIO_5 0x20
+#define PALMAS_INT4_LINE_STATE_GPIO_5_SHIFT 5
+#define PALMAS_INT4_LINE_STATE_GPIO_4 0x10
+#define PALMAS_INT4_LINE_STATE_GPIO_4_SHIFT 4
+#define PALMAS_INT4_LINE_STATE_GPIO_3 0x08
+#define PALMAS_INT4_LINE_STATE_GPIO_3_SHIFT 3
+#define PALMAS_INT4_LINE_STATE_GPIO_2 0x04
+#define PALMAS_INT4_LINE_STATE_GPIO_2_SHIFT 2
+#define PALMAS_INT4_LINE_STATE_GPIO_1 0x02
+#define PALMAS_INT4_LINE_STATE_GPIO_1_SHIFT 1
+#define PALMAS_INT4_LINE_STATE_GPIO_0 0x01
+#define PALMAS_INT4_LINE_STATE_GPIO_0_SHIFT 0
+
+/* Bit definitions for INT4_EDGE_DETECT1 */
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_3_RISING 0x80
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_3_RISING_SHIFT 7
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_3_FALLING 0x40
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_3_FALLING_SHIFT 6
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_2_RISING 0x20
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_2_RISING_SHIFT 5
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_2_FALLING 0x10
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_2_FALLING_SHIFT 4
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_1_RISING 0x08
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_1_RISING_SHIFT 3
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_1_FALLING 0x04
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_1_FALLING_SHIFT 2
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_0_RISING 0x02
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_0_RISING_SHIFT 1
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_0_FALLING 0x01
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_0_FALLING_SHIFT 0
+
+/* Bit definitions for INT4_EDGE_DETECT2 */
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_7_RISING 0x80
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_7_RISING_SHIFT 7
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_7_FALLING 0x40
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_7_FALLING_SHIFT 6
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_6_RISING 0x20
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_6_RISING_SHIFT 5
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_6_FALLING 0x10
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_6_FALLING_SHIFT 4
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_5_RISING 0x08
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_5_RISING_SHIFT 3
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_5_FALLING 0x04
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_5_FALLING_SHIFT 2
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_4_RISING 0x02
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_4_RISING_SHIFT 1
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_4_FALLING 0x01
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_4_FALLING_SHIFT 0
+
+/* Bit definitions for INT_CTRL */
+#define PALMAS_INT_CTRL_INT_PENDING 0x04
+#define PALMAS_INT_CTRL_INT_PENDING_SHIFT 2
+#define PALMAS_INT_CTRL_INT_CLEAR 0x01
+#define PALMAS_INT_CTRL_INT_CLEAR_SHIFT 0
+
+/* Registers for function USB_OTG */
+#define PALMAS_USB_WAKEUP 0x3
+#define PALMAS_USB_VBUS_CTRL_SET 0x4
+#define PALMAS_USB_VBUS_CTRL_CLR 0x5
+#define PALMAS_USB_ID_CTRL_SET 0x6
+#define PALMAS_USB_ID_CTRL_CLEAR 0x7
+#define PALMAS_USB_VBUS_INT_SRC 0x8
+#define PALMAS_USB_VBUS_INT_LATCH_SET 0x9
+#define PALMAS_USB_VBUS_INT_LATCH_CLR 0xA
+#define PALMAS_USB_VBUS_INT_EN_LO_SET 0xB
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR 0xC
+#define PALMAS_USB_VBUS_INT_EN_HI_SET 0xD
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR 0xE
+#define PALMAS_USB_ID_INT_SRC 0xF
+#define PALMAS_USB_ID_INT_LATCH_SET 0x10
+#define PALMAS_USB_ID_INT_LATCH_CLR 0x11
+#define PALMAS_USB_ID_INT_EN_LO_SET 0x12
+#define PALMAS_USB_ID_INT_EN_LO_CLR 0x13
+#define PALMAS_USB_ID_INT_EN_HI_SET 0x14
+#define PALMAS_USB_ID_INT_EN_HI_CLR 0x15
+#define PALMAS_USB_OTG_ADP_CTRL 0x16
+#define PALMAS_USB_OTG_ADP_HIGH 0x17
+#define PALMAS_USB_OTG_ADP_LOW 0x18
+#define PALMAS_USB_OTG_ADP_RISE 0x19
+#define PALMAS_USB_OTG_REVISION 0x1A
+
+/* Bit definitions for USB_WAKEUP */
+#define PALMAS_USB_WAKEUP_ID_WK_UP_COMP 0x01
+#define PALMAS_USB_WAKEUP_ID_WK_UP_COMP_SHIFT 0
+
+/* Bit definitions for USB_VBUS_CTRL_SET */
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_CHRG_VSYS 0x80
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_CHRG_VSYS_SHIFT 7
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_DISCHRG 0x20
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_DISCHRG_SHIFT 5
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_IADP_SRC 0x10
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_IADP_SRC_SHIFT 4
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_IADP_SINK 0x08
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_IADP_SINK_SHIFT 3
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP 0x04
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP_SHIFT 2
+
+/* Bit definitions for USB_VBUS_CTRL_CLR */
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_CHRG_VSYS 0x80
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_CHRG_VSYS_SHIFT 7
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_DISCHRG 0x20
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_DISCHRG_SHIFT 5
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_IADP_SRC 0x10
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_IADP_SRC_SHIFT 4
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_IADP_SINK 0x08
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_IADP_SINK_SHIFT 3
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_ACT_COMP 0x04
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_ACT_COMP_SHIFT 2
+
+/* Bit definitions for USB_ID_CTRL_SET */
+#define PALMAS_USB_ID_CTRL_SET_ID_PU_220K 0x80
+#define PALMAS_USB_ID_CTRL_SET_ID_PU_220K_SHIFT 7
+#define PALMAS_USB_ID_CTRL_SET_ID_PU_100K 0x40
+#define PALMAS_USB_ID_CTRL_SET_ID_PU_100K_SHIFT 6
+#define PALMAS_USB_ID_CTRL_SET_ID_GND_DRV 0x20
+#define PALMAS_USB_ID_CTRL_SET_ID_GND_DRV_SHIFT 5
+#define PALMAS_USB_ID_CTRL_SET_ID_SRC_16U 0x10
+#define PALMAS_USB_ID_CTRL_SET_ID_SRC_16U_SHIFT 4
+#define PALMAS_USB_ID_CTRL_SET_ID_SRC_5U 0x08
+#define PALMAS_USB_ID_CTRL_SET_ID_SRC_5U_SHIFT 3
+#define PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP 0x04
+#define PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP_SHIFT 2
+
+/* Bit definitions for USB_ID_CTRL_CLEAR */
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_PU_220K 0x80
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_PU_220K_SHIFT 7
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_PU_100K 0x40
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_PU_100K_SHIFT 6
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_GND_DRV 0x20
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_GND_DRV_SHIFT 5
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_SRC_16U 0x10
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_SRC_16U_SHIFT 4
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_SRC_5U 0x08
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_SRC_5U_SHIFT 3
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_ACT_COMP 0x04
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_ACT_COMP_SHIFT 2
+
+/* Bit definitions for USB_VBUS_INT_SRC */
+#define PALMAS_USB_VBUS_INT_SRC_VOTG_SESS_VLD 0x80
+#define PALMAS_USB_VBUS_INT_SRC_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_SRC_VADP_PRB 0x40
+#define PALMAS_USB_VBUS_INT_SRC_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_SRC_VADP_SNS 0x20
+#define PALMAS_USB_VBUS_INT_SRC_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_SRC_VA_VBUS_VLD 0x08
+#define PALMAS_USB_VBUS_INT_SRC_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_SRC_VA_SESS_VLD 0x04
+#define PALMAS_USB_VBUS_INT_SRC_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_SRC_VB_SESS_VLD 0x02
+#define PALMAS_USB_VBUS_INT_SRC_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_SRC_VB_SESS_END 0x01
+#define PALMAS_USB_VBUS_INT_SRC_VB_SESS_END_SHIFT 0
+
+/* Bit definitions for USB_VBUS_INT_LATCH_SET */
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VOTG_SESS_VLD 0x80
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VADP_PRB 0x40
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VADP_SNS 0x20
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_LATCH_SET_ADP 0x10
+#define PALMAS_USB_VBUS_INT_LATCH_SET_ADP_SHIFT 4
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VA_VBUS_VLD 0x08
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VA_SESS_VLD 0x04
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VB_SESS_VLD 0x02
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VB_SESS_END 0x01
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VB_SESS_END_SHIFT 0
+
+/* Bit definitions for USB_VBUS_INT_LATCH_CLR */
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VOTG_SESS_VLD 0x80
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VADP_PRB 0x40
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VADP_SNS 0x20
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_ADP 0x10
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_ADP_SHIFT 4
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VA_VBUS_VLD 0x08
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VA_SESS_VLD 0x04
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VB_SESS_VLD 0x02
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VB_SESS_END 0x01
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VB_SESS_END_SHIFT 0
+
+/* Bit definitions for USB_VBUS_INT_EN_LO_SET */
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VOTG_SESS_VLD 0x80
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VADP_PRB 0x40
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VADP_SNS 0x20
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VA_VBUS_VLD 0x08
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VA_SESS_VLD 0x04
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VB_SESS_VLD 0x02
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VB_SESS_END 0x01
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VB_SESS_END_SHIFT 0
+
+/* Bit definitions for USB_VBUS_INT_EN_LO_CLR */
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VOTG_SESS_VLD 0x80
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VADP_PRB 0x40
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VADP_SNS 0x20
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VA_VBUS_VLD 0x08
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VA_SESS_VLD 0x04
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VB_SESS_VLD 0x02
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VB_SESS_END 0x01
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VB_SESS_END_SHIFT 0
+
+/* Bit definitions for USB_VBUS_INT_EN_HI_SET */
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VOTG_SESS_VLD 0x80
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VADP_PRB 0x40
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VADP_SNS 0x20
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_ADP 0x10
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_ADP_SHIFT 4
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VA_VBUS_VLD 0x08
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VA_SESS_VLD 0x04
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VB_SESS_VLD 0x02
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VB_SESS_END 0x01
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VB_SESS_END_SHIFT 0
+
+/* Bit definitions for USB_VBUS_INT_EN_HI_CLR */
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VOTG_SESS_VLD 0x80
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VADP_PRB 0x40
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VADP_SNS 0x20
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_ADP 0x10
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_ADP_SHIFT 4
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VA_VBUS_VLD 0x08
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VA_SESS_VLD 0x04
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VB_SESS_VLD 0x02
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VB_SESS_END 0x01
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VB_SESS_END_SHIFT 0
+
+/* Bit definitions for USB_ID_INT_SRC */
+#define PALMAS_USB_ID_INT_SRC_ID_FLOAT 0x10
+#define PALMAS_USB_ID_INT_SRC_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_SRC_ID_A 0x08
+#define PALMAS_USB_ID_INT_SRC_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_SRC_ID_B 0x04
+#define PALMAS_USB_ID_INT_SRC_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_SRC_ID_C 0x02
+#define PALMAS_USB_ID_INT_SRC_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_SRC_ID_GND 0x01
+#define PALMAS_USB_ID_INT_SRC_ID_GND_SHIFT 0
+
+/* Bit definitions for USB_ID_INT_LATCH_SET */
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_FLOAT 0x10
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_A 0x08
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_B 0x04
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_C 0x02
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_GND 0x01
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_GND_SHIFT 0
+
+/* Bit definitions for USB_ID_INT_LATCH_CLR */
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_FLOAT 0x10
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_A 0x08
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_B 0x04
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_C 0x02
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_GND 0x01
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_GND_SHIFT 0
+
+/* Bit definitions for USB_ID_INT_EN_LO_SET */
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_FLOAT 0x10
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_A 0x08
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_B 0x04
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_C 0x02
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_GND 0x01
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_GND_SHIFT 0
+
+/* Bit definitions for USB_ID_INT_EN_LO_CLR */
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_FLOAT 0x10
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_A 0x08
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_B 0x04
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_C 0x02
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_GND 0x01
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_GND_SHIFT 0
+
+/* Bit definitions for USB_ID_INT_EN_HI_SET */
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT 0x10
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_A 0x08
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_B 0x04
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_C 0x02
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_GND 0x01
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_GND_SHIFT 0
+
+/* Bit definitions for USB_ID_INT_EN_HI_CLR */
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT 0x10
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_A 0x08
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_B 0x04
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_C 0x02
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND 0x01
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND_SHIFT 0
+
+/* Bit definitions for USB_OTG_ADP_CTRL */
+#define PALMAS_USB_OTG_ADP_CTRL_ADP_EN 0x04
+#define PALMAS_USB_OTG_ADP_CTRL_ADP_EN_SHIFT 2
+#define PALMAS_USB_OTG_ADP_CTRL_ADP_MODE_MASK 0x03
+#define PALMAS_USB_OTG_ADP_CTRL_ADP_MODE_SHIFT 0
+
+/* Bit definitions for USB_OTG_ADP_HIGH */
+#define PALMAS_USB_OTG_ADP_HIGH_T_ADP_HIGH_MASK 0xff
+#define PALMAS_USB_OTG_ADP_HIGH_T_ADP_HIGH_SHIFT 0
+
+/* Bit definitions for USB_OTG_ADP_LOW */
+#define PALMAS_USB_OTG_ADP_LOW_T_ADP_LOW_MASK 0xff
+#define PALMAS_USB_OTG_ADP_LOW_T_ADP_LOW_SHIFT 0
+
+/* Bit definitions for USB_OTG_ADP_RISE */
+#define PALMAS_USB_OTG_ADP_RISE_T_ADP_RISE_MASK 0xff
+#define PALMAS_USB_OTG_ADP_RISE_T_ADP_RISE_SHIFT 0
+
+/* Bit definitions for USB_OTG_REVISION */
+#define PALMAS_USB_OTG_REVISION_OTG_REV 0x01
+#define PALMAS_USB_OTG_REVISION_OTG_REV_SHIFT 0
+
+/* Registers for function VIBRATOR */
+#define PALMAS_VIBRA_CTRL 0x0
+
+/* Bit definitions for VIBRA_CTRL */
+#define PALMAS_VIBRA_CTRL_PWM_DUTY_SEL_MASK 0x06
+#define PALMAS_VIBRA_CTRL_PWM_DUTY_SEL_SHIFT 1
+#define PALMAS_VIBRA_CTRL_PWM_FREQ_SEL 0x01
+#define PALMAS_VIBRA_CTRL_PWM_FREQ_SEL_SHIFT 0
+
+/* Registers for function GPIO */
+#define PALMAS_GPIO_DATA_IN 0x0
+#define PALMAS_GPIO_DATA_DIR 0x1
+#define PALMAS_GPIO_DATA_OUT 0x2
+#define PALMAS_GPIO_DEBOUNCE_EN 0x3
+#define PALMAS_GPIO_CLEAR_DATA_OUT 0x4
+#define PALMAS_GPIO_SET_DATA_OUT 0x5
+#define PALMAS_PU_PD_GPIO_CTRL1 0x6
+#define PALMAS_PU_PD_GPIO_CTRL2 0x7
+#define PALMAS_OD_OUTPUT_GPIO_CTRL 0x8
+
+/* Bit definitions for GPIO_DATA_IN */
+#define PALMAS_GPIO_DATA_IN_GPIO_7_IN 0x80
+#define PALMAS_GPIO_DATA_IN_GPIO_7_IN_SHIFT 7
+#define PALMAS_GPIO_DATA_IN_GPIO_6_IN 0x40
+#define PALMAS_GPIO_DATA_IN_GPIO_6_IN_SHIFT 6
+#define PALMAS_GPIO_DATA_IN_GPIO_5_IN 0x20
+#define PALMAS_GPIO_DATA_IN_GPIO_5_IN_SHIFT 5
+#define PALMAS_GPIO_DATA_IN_GPIO_4_IN 0x10
+#define PALMAS_GPIO_DATA_IN_GPIO_4_IN_SHIFT 4
+#define PALMAS_GPIO_DATA_IN_GPIO_3_IN 0x08
+#define PALMAS_GPIO_DATA_IN_GPIO_3_IN_SHIFT 3
+#define PALMAS_GPIO_DATA_IN_GPIO_2_IN 0x04
+#define PALMAS_GPIO_DATA_IN_GPIO_2_IN_SHIFT 2
+#define PALMAS_GPIO_DATA_IN_GPIO_1_IN 0x02
+#define PALMAS_GPIO_DATA_IN_GPIO_1_IN_SHIFT 1
+#define PALMAS_GPIO_DATA_IN_GPIO_0_IN 0x01
+#define PALMAS_GPIO_DATA_IN_GPIO_0_IN_SHIFT 0
+
+/* Bit definitions for GPIO_DATA_DIR */
+#define PALMAS_GPIO_DATA_DIR_GPIO_7_DIR 0x80
+#define PALMAS_GPIO_DATA_DIR_GPIO_7_DIR_SHIFT 7
+#define PALMAS_GPIO_DATA_DIR_GPIO_6_DIR 0x40
+#define PALMAS_GPIO_DATA_DIR_GPIO_6_DIR_SHIFT 6
+#define PALMAS_GPIO_DATA_DIR_GPIO_5_DIR 0x20
+#define PALMAS_GPIO_DATA_DIR_GPIO_5_DIR_SHIFT 5
+#define PALMAS_GPIO_DATA_DIR_GPIO_4_DIR 0x10
+#define PALMAS_GPIO_DATA_DIR_GPIO_4_DIR_SHIFT 4
+#define PALMAS_GPIO_DATA_DIR_GPIO_3_DIR 0x08
+#define PALMAS_GPIO_DATA_DIR_GPIO_3_DIR_SHIFT 3
+#define PALMAS_GPIO_DATA_DIR_GPIO_2_DIR 0x04
+#define PALMAS_GPIO_DATA_DIR_GPIO_2_DIR_SHIFT 2
+#define PALMAS_GPIO_DATA_DIR_GPIO_1_DIR 0x02
+#define PALMAS_GPIO_DATA_DIR_GPIO_1_DIR_SHIFT 1
+#define PALMAS_GPIO_DATA_DIR_GPIO_0_DIR 0x01
+#define PALMAS_GPIO_DATA_DIR_GPIO_0_DIR_SHIFT 0
+
+/* Bit definitions for GPIO_DATA_OUT */
+#define PALMAS_GPIO_DATA_OUT_GPIO_7_OUT 0x80
+#define PALMAS_GPIO_DATA_OUT_GPIO_7_OUT_SHIFT 7
+#define PALMAS_GPIO_DATA_OUT_GPIO_6_OUT 0x40
+#define PALMAS_GPIO_DATA_OUT_GPIO_6_OUT_SHIFT 6
+#define PALMAS_GPIO_DATA_OUT_GPIO_5_OUT 0x20
+#define PALMAS_GPIO_DATA_OUT_GPIO_5_OUT_SHIFT 5
+#define PALMAS_GPIO_DATA_OUT_GPIO_4_OUT 0x10
+#define PALMAS_GPIO_DATA_OUT_GPIO_4_OUT_SHIFT 4
+#define PALMAS_GPIO_DATA_OUT_GPIO_3_OUT 0x08
+#define PALMAS_GPIO_DATA_OUT_GPIO_3_OUT_SHIFT 3
+#define PALMAS_GPIO_DATA_OUT_GPIO_2_OUT 0x04
+#define PALMAS_GPIO_DATA_OUT_GPIO_2_OUT_SHIFT 2
+#define PALMAS_GPIO_DATA_OUT_GPIO_1_OUT 0x02
+#define PALMAS_GPIO_DATA_OUT_GPIO_1_OUT_SHIFT 1
+#define PALMAS_GPIO_DATA_OUT_GPIO_0_OUT 0x01
+#define PALMAS_GPIO_DATA_OUT_GPIO_0_OUT_SHIFT 0
+
+/* Bit definitions for GPIO_DEBOUNCE_EN */
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_7_DEBOUNCE_EN 0x80
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_7_DEBOUNCE_EN_SHIFT 7
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_6_DEBOUNCE_EN 0x40
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_6_DEBOUNCE_EN_SHIFT 6
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_5_DEBOUNCE_EN 0x20
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_5_DEBOUNCE_EN_SHIFT 5
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_4_DEBOUNCE_EN 0x10
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_4_DEBOUNCE_EN_SHIFT 4
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_3_DEBOUNCE_EN 0x08
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_3_DEBOUNCE_EN_SHIFT 3
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_2_DEBOUNCE_EN 0x04
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_2_DEBOUNCE_EN_SHIFT 2
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_1_DEBOUNCE_EN 0x02
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_1_DEBOUNCE_EN_SHIFT 1
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_0_DEBOUNCE_EN 0x01
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_0_DEBOUNCE_EN_SHIFT 0
+
+/* Bit definitions for GPIO_CLEAR_DATA_OUT */
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_7_CLEAR_DATA_OUT 0x80
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_7_CLEAR_DATA_OUT_SHIFT 7
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_6_CLEAR_DATA_OUT 0x40
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_6_CLEAR_DATA_OUT_SHIFT 6
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_5_CLEAR_DATA_OUT 0x20
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_5_CLEAR_DATA_OUT_SHIFT 5
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_4_CLEAR_DATA_OUT 0x10
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_4_CLEAR_DATA_OUT_SHIFT 4
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_3_CLEAR_DATA_OUT 0x08
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_3_CLEAR_DATA_OUT_SHIFT 3
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_2_CLEAR_DATA_OUT 0x04
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_2_CLEAR_DATA_OUT_SHIFT 2
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_1_CLEAR_DATA_OUT 0x02
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_1_CLEAR_DATA_OUT_SHIFT 1
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_0_CLEAR_DATA_OUT 0x01
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_0_CLEAR_DATA_OUT_SHIFT 0
+
+/* Bit definitions for GPIO_SET_DATA_OUT */
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_7_SET_DATA_OUT 0x80
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_7_SET_DATA_OUT_SHIFT 7
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_6_SET_DATA_OUT 0x40
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_6_SET_DATA_OUT_SHIFT 6
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_5_SET_DATA_OUT 0x20
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_5_SET_DATA_OUT_SHIFT 5
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_4_SET_DATA_OUT 0x10
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_4_SET_DATA_OUT_SHIFT 4
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_3_SET_DATA_OUT 0x08
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_3_SET_DATA_OUT_SHIFT 3
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_2_SET_DATA_OUT 0x04
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_2_SET_DATA_OUT_SHIFT 2
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_1_SET_DATA_OUT 0x02
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_1_SET_DATA_OUT_SHIFT 1
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_0_SET_DATA_OUT 0x01
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_0_SET_DATA_OUT_SHIFT 0
+
+/* Bit definitions for PU_PD_GPIO_CTRL1 */
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_3_PD 0x40
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_3_PD_SHIFT 6
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_2_PU 0x20
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_2_PU_SHIFT 5
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_2_PD 0x10
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_2_PD_SHIFT 4
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_1_PU 0x08
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_1_PU_SHIFT 3
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_1_PD 0x04
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_1_PD_SHIFT 2
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_0_PD 0x01
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_0_PD_SHIFT 0
+
+/* Bit definitions for PU_PD_GPIO_CTRL2 */
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_7_PD 0x40
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_7_PD_SHIFT 6
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_6_PU 0x20
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_6_PU_SHIFT 5
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_6_PD 0x10
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_6_PD_SHIFT 4
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_5_PU 0x08
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_5_PU_SHIFT 3
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_5_PD 0x04
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_5_PD_SHIFT 2
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_4_PU 0x02
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_4_PU_SHIFT 1
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_4_PD 0x01
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_4_PD_SHIFT 0
+
+/* Bit definitions for OD_OUTPUT_GPIO_CTRL */
+#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_5_OD 0x20
+#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_5_OD_SHIFT 5
+#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_2_OD 0x04
+#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_2_OD_SHIFT 2
+#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_1_OD 0x02
+#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_1_OD_SHIFT 1
+
+/* Registers for function GPADC */
+#define PALMAS_GPADC_CTRL1 0x0
+#define PALMAS_GPADC_CTRL2 0x1
+#define PALMAS_GPADC_RT_CTRL 0x2
+#define PALMAS_GPADC_AUTO_CTRL 0x3
+#define PALMAS_GPADC_STATUS 0x4
+#define PALMAS_GPADC_RT_SELECT 0x5
+#define PALMAS_GPADC_RT_CONV0_LSB 0x6
+#define PALMAS_GPADC_RT_CONV0_MSB 0x7
+#define PALMAS_GPADC_AUTO_SELECT 0x8
+#define PALMAS_GPADC_AUTO_CONV0_LSB 0x9
+#define PALMAS_GPADC_AUTO_CONV0_MSB 0xA
+#define PALMAS_GPADC_AUTO_CONV1_LSB 0xB
+#define PALMAS_GPADC_AUTO_CONV1_MSB 0xC
+#define PALMAS_GPADC_SW_SELECT 0xD
+#define PALMAS_GPADC_SW_CONV0_LSB 0xE
+#define PALMAS_GPADC_SW_CONV0_MSB 0xF
+#define PALMAS_GPADC_THRES_CONV0_LSB 0x10
+#define PALMAS_GPADC_THRES_CONV0_MSB 0x11
+#define PALMAS_GPADC_THRES_CONV1_LSB 0x12
+#define PALMAS_GPADC_THRES_CONV1_MSB 0x13
+#define PALMAS_GPADC_SMPS_ILMONITOR_EN 0x14
+#define PALMAS_GPADC_SMPS_VSEL_MONITORING 0x15
+
+/* Bit definitions for GPADC_CTRL1 */
+#define PALMAS_GPADC_CTRL1_RESERVED_MASK 0xc0
+#define PALMAS_GPADC_CTRL1_RESERVED_SHIFT 6
+#define PALMAS_GPADC_CTRL1_CURRENT_SRC_CH3_MASK 0x30
+#define PALMAS_GPADC_CTRL1_CURRENT_SRC_CH3_SHIFT 4
+#define PALMAS_GPADC_CTRL1_CURRENT_SRC_CH0_MASK 0x0c
+#define PALMAS_GPADC_CTRL1_CURRENT_SRC_CH0_SHIFT 2
+#define PALMAS_GPADC_CTRL1_BAT_REMOVAL_DET 0x02
+#define PALMAS_GPADC_CTRL1_BAT_REMOVAL_DET_SHIFT 1
+#define PALMAS_GPADC_CTRL1_GPADC_FORCE 0x01
+#define PALMAS_GPADC_CTRL1_GPADC_FORCE_SHIFT 0
+
+/* Bit definitions for GPADC_CTRL2 */
+#define PALMAS_GPADC_CTRL2_RESERVED_MASK 0x06
+#define PALMAS_GPADC_CTRL2_RESERVED_SHIFT 1
+
+/* Bit definitions for GPADC_RT_CTRL */
+#define PALMAS_GPADC_RT_CTRL_EXTEND_DELAY 0x02
+#define PALMAS_GPADC_RT_CTRL_EXTEND_DELAY_SHIFT 1
+#define PALMAS_GPADC_RT_CTRL_START_POLARITY 0x01
+#define PALMAS_GPADC_RT_CTRL_START_POLARITY_SHIFT 0
+
+/* Bit definitions for GPADC_AUTO_CTRL */
+#define PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV1 0x80
+#define PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV1_SHIFT 7
+#define PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV0 0x40
+#define PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV0_SHIFT 6
+#define PALMAS_GPADC_AUTO_CTRL_AUTO_CONV1_EN 0x20
+#define PALMAS_GPADC_AUTO_CTRL_AUTO_CONV1_EN_SHIFT 5
+#define PALMAS_GPADC_AUTO_CTRL_AUTO_CONV0_EN 0x10
+#define PALMAS_GPADC_AUTO_CTRL_AUTO_CONV0_EN_SHIFT 4
+#define PALMAS_GPADC_AUTO_CTRL_COUNTER_CONV_MASK 0x0f
+#define PALMAS_GPADC_AUTO_CTRL_COUNTER_CONV_SHIFT 0
+
+/* Bit definitions for GPADC_STATUS */
+#define PALMAS_GPADC_STATUS_GPADC_AVAILABLE 0x10
+#define PALMAS_GPADC_STATUS_GPADC_AVAILABLE_SHIFT 4
+
+/* Bit definitions for GPADC_RT_SELECT */
+#define PALMAS_GPADC_RT_SELECT_RT_CONV_EN 0x80
+#define PALMAS_GPADC_RT_SELECT_RT_CONV_EN_SHIFT 7
+#define PALMAS_GPADC_RT_SELECT_RT_CONV0_SEL_MASK 0x0f
+#define PALMAS_GPADC_RT_SELECT_RT_CONV0_SEL_SHIFT 0
+
+/* Bit definitions for GPADC_RT_CONV0_LSB */
+#define PALMAS_GPADC_RT_CONV0_LSB_RT_CONV0_LSB_MASK 0xff
+#define PALMAS_GPADC_RT_CONV0_LSB_RT_CONV0_LSB_SHIFT 0
+
+/* Bit definitions for GPADC_RT_CONV0_MSB */
+#define PALMAS_GPADC_RT_CONV0_MSB_RT_CONV0_MSB_MASK 0x0f
+#define PALMAS_GPADC_RT_CONV0_MSB_RT_CONV0_MSB_SHIFT 0
+
+/* Bit definitions for GPADC_AUTO_SELECT */
+#define PALMAS_GPADC_AUTO_SELECT_AUTO_CONV1_SEL_MASK 0xf0
+#define PALMAS_GPADC_AUTO_SELECT_AUTO_CONV1_SEL_SHIFT 4
+#define PALMAS_GPADC_AUTO_SELECT_AUTO_CONV0_SEL_MASK 0x0f
+#define PALMAS_GPADC_AUTO_SELECT_AUTO_CONV0_SEL_SHIFT 0
+
+/* Bit definitions for GPADC_AUTO_CONV0_LSB */
+#define PALMAS_GPADC_AUTO_CONV0_LSB_AUTO_CONV0_LSB_MASK 0xff
+#define PALMAS_GPADC_AUTO_CONV0_LSB_AUTO_CONV0_LSB_SHIFT 0
+
+/* Bit definitions for GPADC_AUTO_CONV0_MSB */
+#define PALMAS_GPADC_AUTO_CONV0_MSB_AUTO_CONV0_MSB_MASK 0x0f
+#define PALMAS_GPADC_AUTO_CONV0_MSB_AUTO_CONV0_MSB_SHIFT 0
+
+/* Bit definitions for GPADC_AUTO_CONV1_LSB */
+#define PALMAS_GPADC_AUTO_CONV1_LSB_AUTO_CONV1_LSB_MASK 0xff
+#define PALMAS_GPADC_AUTO_CONV1_LSB_AUTO_CONV1_LSB_SHIFT 0
+
+/* Bit definitions for GPADC_AUTO_CONV1_MSB */
+#define PALMAS_GPADC_AUTO_CONV1_MSB_AUTO_CONV1_MSB_MASK 0x0f
+#define PALMAS_GPADC_AUTO_CONV1_MSB_AUTO_CONV1_MSB_SHIFT 0
+
+/* Bit definitions for GPADC_SW_SELECT */
+#define PALMAS_GPADC_SW_SELECT_SW_CONV_EN 0x80
+#define PALMAS_GPADC_SW_SELECT_SW_CONV_EN_SHIFT 7
+#define PALMAS_GPADC_SW_SELECT_SW_START_CONV0 0x10
+#define PALMAS_GPADC_SW_SELECT_SW_START_CONV0_SHIFT 4
+#define PALMAS_GPADC_SW_SELECT_SW_CONV0_SEL_MASK 0x0f
+#define PALMAS_GPADC_SW_SELECT_SW_CONV0_SEL_SHIFT 0
+
+/* Bit definitions for GPADC_SW_CONV0_LSB */
+#define PALMAS_GPADC_SW_CONV0_LSB_SW_CONV0_LSB_MASK 0xff
+#define PALMAS_GPADC_SW_CONV0_LSB_SW_CONV0_LSB_SHIFT 0
+
+/* Bit definitions for GPADC_SW_CONV0_MSB */
+#define PALMAS_GPADC_SW_CONV0_MSB_SW_CONV0_MSB_MASK 0x0f
+#define PALMAS_GPADC_SW_CONV0_MSB_SW_CONV0_MSB_SHIFT 0
+
+/* Bit definitions for GPADC_THRES_CONV0_LSB */
+#define PALMAS_GPADC_THRES_CONV0_LSB_THRES_CONV0_LSB_MASK 0xff
+#define PALMAS_GPADC_THRES_CONV0_LSB_THRES_CONV0_LSB_SHIFT 0
+
+/* Bit definitions for GPADC_THRES_CONV0_MSB */
+#define PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_POL 0x80
+#define PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_POL_SHIFT 7
+#define PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_MSB_MASK 0x0f
+#define PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_MSB_SHIFT 0
+
+/* Bit definitions for GPADC_THRES_CONV1_LSB */
+#define PALMAS_GPADC_THRES_CONV1_LSB_THRES_CONV1_LSB_MASK 0xff
+#define PALMAS_GPADC_THRES_CONV1_LSB_THRES_CONV1_LSB_SHIFT 0
+
+/* Bit definitions for GPADC_THRES_CONV1_MSB */
+#define PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_POL 0x80
+#define PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_POL_SHIFT 7
+#define PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_MSB_MASK 0x0f
+#define PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_MSB_SHIFT 0
+
+/* Bit definitions for GPADC_SMPS_ILMONITOR_EN */
+#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_EN 0x20
+#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_EN_SHIFT 5
+#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_REXT 0x10
+#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_REXT_SHIFT 4
+#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_SEL_MASK 0x0f
+#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_SEL_SHIFT 0
+
+/* Bit definitions for GPADC_SMPS_VSEL_MONITORING */
+#define PALMAS_GPADC_SMPS_VSEL_MONITORING_ACTIVE_PHASE 0x80
+#define PALMAS_GPADC_SMPS_VSEL_MONITORING_ACTIVE_PHASE_SHIFT 7
+#define PALMAS_GPADC_SMPS_VSEL_MONITORING_SMPS_VSEL_MONITORING_MASK 0x7f
+#define PALMAS_GPADC_SMPS_VSEL_MONITORING_SMPS_VSEL_MONITORING_SHIFT 0
+
+/* Registers for function GPADC */
+#define PALMAS_GPADC_TRIM1 0x0
+#define PALMAS_GPADC_TRIM2 0x1
+#define PALMAS_GPADC_TRIM3 0x2
+#define PALMAS_GPADC_TRIM4 0x3
+#define PALMAS_GPADC_TRIM5 0x4
+#define PALMAS_GPADC_TRIM6 0x5
+#define PALMAS_GPADC_TRIM7 0x6
+#define PALMAS_GPADC_TRIM8 0x7
+#define PALMAS_GPADC_TRIM9 0x8
+#define PALMAS_GPADC_TRIM10 0x9
+#define PALMAS_GPADC_TRIM11 0xA
+#define PALMAS_GPADC_TRIM12 0xB
+#define PALMAS_GPADC_TRIM13 0xC
+#define PALMAS_GPADC_TRIM14 0xD
+#define PALMAS_GPADC_TRIM15 0xE
+#define PALMAS_GPADC_TRIM16 0xF
+
+#endif /* __LINUX_MFD_PALMAS_H */
diff --git a/include/linux/mfd/rc5t583.h b/include/linux/mfd/rc5t583.h
index 0b64b19d81ab..c42fe92a727d 100644
--- a/include/linux/mfd/rc5t583.h
+++ b/include/linux/mfd/rc5t583.h
@@ -250,6 +250,26 @@ enum {
RC5T583_EXT_PWRREQ2_CONTROL = 0x2,
};
+enum {
+ RC5T583_REGULATOR_DC0,
+ RC5T583_REGULATOR_DC1,
+ RC5T583_REGULATOR_DC2,
+ RC5T583_REGULATOR_DC3,
+ RC5T583_REGULATOR_LDO0,
+ RC5T583_REGULATOR_LDO1,
+ RC5T583_REGULATOR_LDO2,
+ RC5T583_REGULATOR_LDO3,
+ RC5T583_REGULATOR_LDO4,
+ RC5T583_REGULATOR_LDO5,
+ RC5T583_REGULATOR_LDO6,
+ RC5T583_REGULATOR_LDO7,
+ RC5T583_REGULATOR_LDO8,
+ RC5T583_REGULATOR_LDO9,
+
+ /* Should be last entry */
+ RC5T583_REGULATOR_MAX,
+};
+
struct rc5t583 {
struct device *dev;
struct regmap *regmap;
@@ -273,11 +293,20 @@ struct rc5t583 {
* The board specific data is provided through this structure.
* @irq_base: Irq base number on which this device registers their interrupts.
* @enable_shutdown: Enable shutdown through the input pin "shutdown".
+ * @regulator_deepsleep_slot: The slot number on which device goes to sleep
+ * in device sleep mode.
+ * @regulator_ext_pwr_control: External power request regulator control. The
+ * regulator output enable/disable is controlled by the external
+ * power request input state.
+ * @reg_init_data: Regulator init data.
*/
struct rc5t583_platform_data {
int irq_base;
bool enable_shutdown;
+ int regulator_deepsleep_slot[RC5T583_REGULATOR_MAX];
+ unsigned long regulator_ext_pwr_control[RC5T583_REGULATOR_MAX];
+ struct regulator_init_data *reg_init_data[RC5T583_REGULATOR_MAX];
};
static inline int rc5t583_write(struct device *dev, uint8_t reg, uint8_t val)
diff --git a/include/linux/mfd/s5m87xx/s5m-core.h b/include/linux/mfd/s5m87xx/s5m-core.h
index a7480b57f92d..21603b42f22f 100644
--- a/include/linux/mfd/s5m87xx/s5m-core.h
+++ b/include/linux/mfd/s5m87xx/s5m-core.h
@@ -335,6 +335,7 @@ extern int s5m_reg_update(struct s5m87xx_dev *s5m87xx, u8 reg, u8 val, u8 mask);
struct s5m_platform_data {
struct s5m_regulator_data *regulators;
+ struct s5m_opmode_data *opmode;
int device_type;
int num_regulators;
diff --git a/include/linux/mfd/s5m87xx/s5m-pmic.h b/include/linux/mfd/s5m87xx/s5m-pmic.h
index a72a5d27e62e..7c719f20f58a 100644
--- a/include/linux/mfd/s5m87xx/s5m-pmic.h
+++ b/include/linux/mfd/s5m87xx/s5m-pmic.h
@@ -58,6 +58,8 @@ enum s5m8767_regulators {
S5M8767_REG_MAX,
};
+#define S5M8767_ENCTRL_SHIFT 6
+
/* S5M8763 regulator ids */
enum s5m8763_regulators {
S5M8763_LDO1,
@@ -97,4 +99,31 @@ struct s5m_regulator_data {
struct regulator_init_data *initdata;
};
+/*
+ * s5m_opmode_data - regulator operation mode data
+ * @id: regulator id
+ * @mode: regulator operation mode
+ */
+struct s5m_opmode_data {
+ int id;
+ int mode;
+};
+
+/*
+ * s5m regulator operation mode
+ * S5M_OPMODE_OFF Regulator always OFF
+ * S5M_OPMODE_ON Regulator always ON
+ * S5M_OPMODE_LOWPOWER Regulator is on in low-power mode
+ * S5M_OPMODE_SUSPEND Regulator is changed by PWREN pin
+ * If PWREN is high, regulator is on
+ * If PWREN is low, regulator is off
+ */
+
+enum s5m_opmode {
+ S5M_OPMODE_OFF,
+ S5M_OPMODE_ON,
+ S5M_OPMODE_LOWPOWER,
+ S5M_OPMODE_SUSPEND,
+};
+
#endif /* __LINUX_MFD_S5M_PMIC_H */
diff --git a/include/linux/mfd/tps65090.h b/include/linux/mfd/tps65090.h
index 38e31c55adbb..6bc31d854626 100644
--- a/include/linux/mfd/tps65090.h
+++ b/include/linux/mfd/tps65090.h
@@ -22,6 +22,19 @@
#ifndef __LINUX_MFD_TPS65090_H
#define __LINUX_MFD_TPS65090_H
+#include <linux/irq.h>
+
+struct tps65090 {
+ struct mutex lock;
+ struct device *dev;
+ struct i2c_client *client;
+ struct regmap *rmap;
+ struct irq_chip irq_chip;
+ struct mutex irq_lock;
+ int irq_base;
+ unsigned int id;
+};
+
struct tps65090_subdev_info {
int id;
const char *name;
diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h
index b19176eab44d..f350fd0ba1df 100644
--- a/include/linux/mfd/tps6586x.h
+++ b/include/linux/mfd/tps6586x.h
@@ -68,6 +68,7 @@ struct tps6586x_subdev_info {
int id;
const char *name;
void *platform_data;
+ struct device_node *of_node;
};
struct tps6586x_platform_data {
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index 1d7a3f7b3b5d..dcc9631b3052 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -26,7 +26,7 @@ struct wm831x_backlight_pdata {
struct wm831x_backup_pdata {
int charger_enable;
int no_constant_voltage; /** Disable constant voltage charging */
- int vlim; /** Voltage limit in milivolts */
+ int vlim; /** Voltage limit in millivolts */
int ilim; /** Current limit in microamps */
};
diff --git a/include/linux/mfd/wm8994/core.h b/include/linux/mfd/wm8994/core.h
index 9eff2a351ec5..6695c3ec4518 100644
--- a/include/linux/mfd/wm8994/core.h
+++ b/include/linux/mfd/wm8994/core.h
@@ -17,6 +17,7 @@
#include <linux/mutex.h>
#include <linux/interrupt.h>
+#include <linux/regmap.h>
enum wm8994_type {
WM8994 = 0,
@@ -26,7 +27,6 @@ enum wm8994_type {
struct regulator_dev;
struct regulator_bulk_data;
-struct regmap;
#define WM8994_NUM_GPIO_REGS 11
#define WM8994_NUM_LDO_REGS 2
@@ -94,17 +94,17 @@ static inline int wm8994_request_irq(struct wm8994 *wm8994, int irq,
irq_handler_t handler, const char *name,
void *data)
{
- if (!wm8994->irq_base)
+ if (!wm8994->irq_data)
return -EINVAL;
- return request_threaded_irq(wm8994->irq_base + irq, NULL, handler,
- IRQF_TRIGGER_RISING, name,
+ return request_threaded_irq(regmap_irq_get_virq(wm8994->irq_data, irq),
+ NULL, handler, IRQF_TRIGGER_RISING, name,
data);
}
static inline void wm8994_free_irq(struct wm8994 *wm8994, int irq, void *data)
{
- if (!wm8994->irq_base)
+ if (!wm8994->irq_data)
return;
- free_irq(wm8994->irq_base + irq, data);
+ free_irq(regmap_irq_get_virq(wm8994->irq_data, irq), data);
}
int wm8994_irq_init(struct wm8994 *wm8994);
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 6d028247f79d..6e27fa99e8b9 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -98,6 +98,12 @@ enum {
MLX4_DEV_CAP_FLAG_SENSE_SUPPORT = 1LL << 55
};
+enum {
+ MLX4_DEV_CAP_FLAG2_RSS = 1LL << 0,
+ MLX4_DEV_CAP_FLAG2_RSS_TOP = 1LL << 1,
+ MLX4_DEV_CAP_FLAG2_RSS_XOR = 1LL << 2
+};
+
#define MLX4_ATTR_EXTENDED_PORT_INFO cpu_to_be16(0xff90)
enum {
@@ -292,11 +298,13 @@ struct mlx4_caps {
u32 max_msg_sz;
u32 page_size_cap;
u64 flags;
+ u64 flags2;
u32 bmme_flags;
u32 reserved_lkey;
u16 stat_rate_support;
u8 port_width_cap[MLX4_MAX_PORTS + 1];
int max_gso_sz;
+ int max_rss_tbl_sz;
int reserved_qps_cnt[MLX4_NUM_QP_REGION];
int reserved_qps;
int reserved_qps_base[MLX4_NUM_QP_REGION];
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
index 96005d75893c..338388ba260a 100644
--- a/include/linux/mlx4/qp.h
+++ b/include/linux/mlx4/qp.h
@@ -234,7 +234,8 @@ struct mlx4_wqe_mlx_seg {
u8 owner;
u8 reserved1[2];
u8 opcode;
- u8 reserved2[3];
+ __be16 sched_prio;
+ u8 reserved2;
u8 size;
/*
* [17] VL15
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 74aa71bea1e4..7d5c37f24c63 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -896,10 +896,8 @@ int zap_vma_ptes(struct vm_area_struct *vma, unsigned long address,
unsigned long size);
void zap_page_range(struct vm_area_struct *vma, unsigned long address,
unsigned long size, struct zap_details *);
-void unmap_vmas(struct mmu_gather *tlb,
- struct vm_area_struct *start_vma, unsigned long start_addr,
- unsigned long end_addr, unsigned long *nr_accounted,
- struct zap_details *);
+void unmap_vmas(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
+ unsigned long start, unsigned long end);
/**
* mm_walk - callbacks for walk_page_range
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index dff711509661..41aa49b74821 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -30,7 +30,7 @@
/*
* PAGE_ALLOC_COSTLY_ORDER is the order at which allocations are deemed
* costly to service. That is between allocation orders which should
- * coelesce naturally under reasonable reclaim pressure and those which
+ * coalesce naturally under reasonable reclaim pressure and those which
* will not.
*/
#define PAGE_ALLOC_COSTLY_ORDER 3
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 501da4cb8a6d..5db93821f9c7 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -132,10 +132,12 @@ struct usb_device_id {
#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
#define HID_ANY_ID (~0)
+#define HID_BUS_ANY 0xffff
+#define HID_GROUP_ANY 0x0000
struct hid_device_id {
__u16 bus;
- __u16 pad1;
+ __u16 group;
__u32 vendor;
__u32 product;
kernel_ulong_t driver_data
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index ea36486378d8..1b14d25162cb 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -320,7 +320,8 @@ extern int parse_args(const char *name,
unsigned num,
s16 level_min,
s16 level_max,
- int (*unknown)(char *param, char *val));
+ int (*unknown)(char *param, char *val,
+ const char *doing));
/* Called by module remove. */
#ifdef CONFIG_SYSFS
diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h
index db4836bed514..c3918a0684fe 100644
--- a/include/linux/mtd/ubi.h
+++ b/include/linux/mtd/ubi.h
@@ -25,6 +25,9 @@
#include <linux/types.h>
#include <mtd/ubi-user.h>
+/* All voumes/LEBs */
+#define UBI_ALL -1
+
/*
* enum ubi_open_mode - UBI volume open mode constants.
*
@@ -208,14 +211,15 @@ void ubi_close_volume(struct ubi_volume_desc *desc);
int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
int len, int check);
int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int offset, int len, int dtype);
+ int offset, int len);
int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int len, int dtype);
+ int len);
int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum);
int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum);
-int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype);
+int ubi_leb_map(struct ubi_volume_desc *desc, int lnum);
int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum);
int ubi_sync(int ubi_num);
+int ubi_flush(int ubi_num, int vol_id, int lnum);
/*
* This function is the same as the 'ubi_leb_read()' function, but it does not
@@ -226,25 +230,4 @@ static inline int ubi_read(struct ubi_volume_desc *desc, int lnum, char *buf,
{
return ubi_leb_read(desc, lnum, buf, offset, len, 0);
}
-
-/*
- * This function is the same as the 'ubi_leb_write()' functions, but it does
- * not have the data type argument.
- */
-static inline int ubi_write(struct ubi_volume_desc *desc, int lnum,
- const void *buf, int offset, int len)
-{
- return ubi_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN);
-}
-
-/*
- * This function is the same as the 'ubi_leb_change()' functions, but it does
- * not have the data type argument.
- */
-static inline int ubi_change(struct ubi_volume_desc *desc, int lnum,
- const void *buf, int len)
-{
- return ubi_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
-}
-
#endif /* !__LINUX_UBI_H__ */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index b0f6f22723c3..e7fd468f7126 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1155,7 +1155,6 @@ struct net_device {
struct in_device __rcu *ip_ptr; /* IPv4 specific data */
struct dn_dev __rcu *dn_ptr; /* DECnet specific data */
struct inet6_dev __rcu *ip6_ptr; /* IPv6 specific data */
- void *ec_ptr; /* Econet specific data */
void *ax25_ptr; /* AX.25 specific data */
struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data,
assign before registering */
@@ -2143,7 +2142,6 @@ extern struct sk_buff * napi_get_frags(struct napi_struct *napi);
extern gro_result_t napi_frags_finish(struct napi_struct *napi,
struct sk_buff *skb,
gro_result_t ret);
-extern struct sk_buff * napi_frags_skb(struct napi_struct *napi);
extern gro_result_t napi_gro_frags(struct napi_struct *napi);
static inline void napi_free_frags(struct napi_struct *napi)
diff --git a/include/linux/of.h b/include/linux/of.h
index fa7fb1d97458..2ec1083af7ff 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -193,6 +193,17 @@ extern struct device_node *of_get_next_child(const struct device_node *node,
for (child = of_get_next_child(parent, NULL); child != NULL; \
child = of_get_next_child(parent, child))
+static inline int of_get_child_count(const struct device_node *np)
+{
+ struct device_node *child;
+ int num = 0;
+
+ for_each_child_of_node(np, child)
+ num++;
+
+ return num;
+}
+
extern struct device_node *of_find_node_with_property(
struct device_node *from, const char *prop_name);
#define for_each_node_with_property(dn, prop_name) \
@@ -259,6 +270,37 @@ extern void of_detach_node(struct device_node *);
#endif
#define of_match_ptr(_ptr) (_ptr)
+
+/*
+ * struct property *prop;
+ * const __be32 *p;
+ * u32 u;
+ *
+ * of_property_for_each_u32(np, "propname", prop, p, u)
+ * printk("U32 value: %x\n", u);
+ */
+const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
+ u32 *pu);
+#define of_property_for_each_u32(np, propname, prop, p, u) \
+ for (prop = of_find_property(np, propname, NULL), \
+ p = of_prop_next_u32(prop, NULL, &u); \
+ p; \
+ p = of_prop_next_u32(prop, p, &u))
+
+/*
+ * struct property *prop;
+ * const char *s;
+ *
+ * of_property_for_each_string(np, "propname", prop, s)
+ * printk("String value: %s\n", s);
+ */
+const char *of_prop_next_string(struct property *prop, const char *cur);
+#define of_property_for_each_string(np, propname, prop, s) \
+ for (prop = of_find_property(np, propname, NULL), \
+ s = of_prop_next_string(prop, NULL); \
+ s; \
+ s = of_prop_next_string(prop, s))
+
#else /* CONFIG_OF */
static inline bool of_have_populated_dt(void)
@@ -269,6 +311,11 @@ static inline bool of_have_populated_dt(void)
#define for_each_child_of_node(parent, child) \
while (0)
+static inline int of_get_child_count(const struct device_node *np)
+{
+ return 0;
+}
+
static inline int of_device_is_compatible(const struct device_node *device,
const char *name)
{
@@ -349,6 +396,10 @@ static inline int of_machine_is_compatible(const char *compat)
#define of_match_ptr(_ptr) NULL
#define of_match_node(_matches, _node) NULL
+#define of_property_for_each_u32(np, propname, prop, p, u) \
+ while (0)
+#define of_property_for_each_string(np, propname, prop, s) \
+ while (0)
#endif /* CONFIG_OF */
/**
diff --git a/include/linux/of_serial.h b/include/linux/of_serial.h
new file mode 100644
index 000000000000..4a73ed80b4c0
--- /dev/null
+++ b/include/linux/of_serial.h
@@ -0,0 +1,17 @@
+#ifndef __LINUX_OF_SERIAL_H
+#define __LINUX_OF_SERIAL_H
+
+/*
+ * FIXME remove this file when tegra finishes conversion to open firmware,
+ * expectation is that all quirks will then be self-contained in
+ * drivers/tty/serial/of_serial.c.
+ */
+#ifdef CONFIG_ARCH_TEGRA
+extern void tegra_serial_handle_break(struct uart_port *port);
+#else
+static inline void tegra_serial_handle_break(struct uart_port *port)
+{
+}
+#endif
+
+#endif /* __LINUX_OF_SERIAL */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index e444f5b49118..17b7b5b01b4a 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -375,11 +375,18 @@ struct pci_host_bridge_window {
};
struct pci_host_bridge {
- struct list_head list;
+ struct device dev;
struct pci_bus *bus; /* root bus */
struct list_head windows; /* pci_host_bridge_windows */
+ void (*release_fn)(struct pci_host_bridge *);
+ void *release_data;
};
+#define to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
+void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
+ void (*release_fn)(struct pci_host_bridge *),
+ void *release_data);
+
/*
* The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
* to P2P or CardBus bridge windows) go in a table. Additional ones (for
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index 21638ae14e07..2b9f82c037c9 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -166,60 +166,6 @@ extern phys_addr_t per_cpu_ptr_to_phys(void *addr);
(typeof(type) __percpu *)__alloc_percpu(sizeof(type), __alignof__(type))
/*
- * Optional methods for optimized non-lvalue per-cpu variable access.
- *
- * @var can be a percpu variable or a field of it and its size should
- * equal char, int or long. percpu_read() evaluates to a lvalue and
- * all others to void.
- *
- * These operations are guaranteed to be atomic.
- * The generic versions disable interrupts. Archs are
- * encouraged to implement single-instruction alternatives which don't
- * require protection.
- */
-#ifndef percpu_read
-# define percpu_read(var) \
- ({ \
- typeof(var) *pr_ptr__ = &(var); \
- typeof(var) pr_ret__; \
- pr_ret__ = get_cpu_var(*pr_ptr__); \
- put_cpu_var(*pr_ptr__); \
- pr_ret__; \
- })
-#endif
-
-#define __percpu_generic_to_op(var, val, op) \
-do { \
- typeof(var) *pgto_ptr__ = &(var); \
- get_cpu_var(*pgto_ptr__) op val; \
- put_cpu_var(*pgto_ptr__); \
-} while (0)
-
-#ifndef percpu_write
-# define percpu_write(var, val) __percpu_generic_to_op(var, (val), =)
-#endif
-
-#ifndef percpu_add
-# define percpu_add(var, val) __percpu_generic_to_op(var, (val), +=)
-#endif
-
-#ifndef percpu_sub
-# define percpu_sub(var, val) __percpu_generic_to_op(var, (val), -=)
-#endif
-
-#ifndef percpu_and
-# define percpu_and(var, val) __percpu_generic_to_op(var, (val), &=)
-#endif
-
-#ifndef percpu_or
-# define percpu_or(var, val) __percpu_generic_to_op(var, (val), |=)
-#endif
-
-#ifndef percpu_xor
-# define percpu_xor(var, val) __percpu_generic_to_op(var, (val), ^=)
-#endif
-
-/*
* Branching function to split up a function into a set of functions that
* are called for different scalar sizes of the objects handled.
*/
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index ddbb6a901f65..f32578634d9d 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1132,11 +1132,14 @@ struct perf_sample_data {
struct perf_branch_stack *br_stack;
};
-static inline void perf_sample_data_init(struct perf_sample_data *data, u64 addr)
+static inline void perf_sample_data_init(struct perf_sample_data *data,
+ u64 addr, u64 period)
{
+ /* remaining struct members initialized in perf_prepare_sample() */
data->addr = addr;
data->raw = NULL;
data->br_stack = NULL;
+ data->period = period;
}
extern void perf_output_sample(struct perf_output_handle *handle,
diff --git a/include/linux/pinctrl/consumer.h b/include/linux/pinctrl/consumer.h
index 191e72688481..6dd96fb45482 100644
--- a/include/linux/pinctrl/consumer.h
+++ b/include/linux/pinctrl/consumer.h
@@ -36,6 +36,9 @@ extern struct pinctrl_state * __must_check pinctrl_lookup_state(
const char *name);
extern int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s);
+extern struct pinctrl * __must_check devm_pinctrl_get(struct device *dev);
+extern void devm_pinctrl_put(struct pinctrl *p);
+
#else /* !CONFIG_PINCTRL */
static inline int pinctrl_request_gpio(unsigned gpio)
@@ -79,6 +82,15 @@ static inline int pinctrl_select_state(struct pinctrl *p,
return 0;
}
+static inline struct pinctrl * __must_check devm_pinctrl_get(struct device *dev)
+{
+ return NULL;
+}
+
+static inline void devm_pinctrl_put(struct pinctrl *p)
+{
+}
+
#endif /* CONFIG_PINCTRL */
static inline struct pinctrl * __must_check pinctrl_get_select(
@@ -113,6 +125,38 @@ static inline struct pinctrl * __must_check pinctrl_get_select_default(
return pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT);
}
+static inline struct pinctrl * __must_check devm_pinctrl_get_select(
+ struct device *dev, const char *name)
+{
+ struct pinctrl *p;
+ struct pinctrl_state *s;
+ int ret;
+
+ p = devm_pinctrl_get(dev);
+ if (IS_ERR(p))
+ return p;
+
+ s = pinctrl_lookup_state(p, name);
+ if (IS_ERR(s)) {
+ devm_pinctrl_put(p);
+ return ERR_PTR(PTR_ERR(s));
+ }
+
+ ret = pinctrl_select_state(p, s);
+ if (ret < 0) {
+ devm_pinctrl_put(p);
+ return ERR_PTR(ret);
+ }
+
+ return p;
+}
+
+static inline struct pinctrl * __must_check devm_pinctrl_get_select_default(
+ struct device *dev)
+{
+ return devm_pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT);
+}
+
#ifdef CONFIG_PINCONF
extern int pin_config_get(const char *dev_name, const char *name,
diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h
index e4d1de742502..7d22ab00343f 100644
--- a/include/linux/pinctrl/machine.h
+++ b/include/linux/pinctrl/machine.h
@@ -154,7 +154,7 @@ struct pinctrl_map {
extern int pinctrl_register_mappings(struct pinctrl_map const *map,
unsigned num_maps);
-
+extern void pinctrl_provide_dummies(void);
#else
static inline int pinctrl_register_mappings(struct pinctrl_map const *map,
@@ -163,5 +163,8 @@ static inline int pinctrl_register_mappings(struct pinctrl_map const *map,
return 0;
}
-#endif /* !CONFIG_PINMUX */
+static inline void pinctrl_provide_dummies(void)
+{
+}
+#endif /* !CONFIG_PINCTRL */
#endif
diff --git a/include/linux/pinctrl/pinconf.h b/include/linux/pinctrl/pinconf.h
index ec431f03362d..e7a720104a47 100644
--- a/include/linux/pinctrl/pinconf.h
+++ b/include/linux/pinctrl/pinconf.h
@@ -25,7 +25,6 @@ struct seq_file;
* @pin_config_get: get the config of a certain pin, if the requested config
* is not available on this controller this should return -ENOTSUPP
* and if it is available but disabled it should return -EINVAL
- * @pin_config_get: get the config of a certain pin
* @pin_config_set: configure an individual pin
* @pin_config_group_get: get configurations for an entire pin group
* @pin_config_group_set: configure all pins in a group
@@ -33,6 +32,8 @@ struct seq_file;
* per-device info for a certain pin in debugfs
* @pin_config_group_dbg_show: optional debugfs display hook that will provide
* per-device info for a certain group in debugfs
+ * @pin_config_config_dbg_show: optional debugfs display hook that will decode
+ * and display a driver's pin configuration parameter
*/
struct pinconf_ops {
#ifdef CONFIG_GENERIC_PINCONF
@@ -56,6 +57,9 @@ struct pinconf_ops {
void (*pin_config_group_dbg_show) (struct pinctrl_dev *pctldev,
struct seq_file *s,
unsigned selector);
+ void (*pin_config_config_dbg_show) (struct pinctrl_dev *pctldev,
+ struct seq_file *s,
+ unsigned long config);
};
#endif
diff --git a/include/linux/pinctrl/pinctrl-state.h b/include/linux/pinctrl/pinctrl-state.h
index 3920e28b4da7..634608dc6c89 100644
--- a/include/linux/pinctrl/pinctrl-state.h
+++ b/include/linux/pinctrl/pinctrl-state.h
@@ -2,5 +2,18 @@
* Standard pin control state definitions
*/
+/**
+ * @PINCTRL_STATE_DEFAULT: the state the pinctrl handle shall be put
+ * into as default, usually this means the pins are up and ready to
+ * be used by the device driver. This state is commonly used by
+ * hogs to configure muxing and pins at boot.
+ * @PINCTRL_STATE_IDLE: the state the pinctrl handle shall be put into
+ * when the pins are idle. Could typically be set from a
+ * pm_runtime_suspend() operation.
+ * @PINCTRL_STATE_SLEEP: the state the pinctrl handle shall be put into
+ * when the pins are sleeping. Could typically be set from a
+ * common suspend() function.
+ */
#define PINCTRL_STATE_DEFAULT "default"
#define PINCTRL_STATE_IDLE "idle"
+#define PINCTRL_STATE_SLEEP "sleep"
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index 4e9f0788c221..3b894a668d32 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -21,9 +21,11 @@
struct device;
struct pinctrl_dev;
+struct pinctrl_map;
struct pinmux_ops;
struct pinconf_ops;
struct gpio_chip;
+struct device_node;
/**
* struct pinctrl_pin_desc - boards/machines provide information on their
@@ -64,17 +66,24 @@ struct pinctrl_gpio_range {
/**
* struct pinctrl_ops - global pin control operations, to be implemented by
* pin controller drivers.
- * @list_groups: list the number of selectable named groups available
- * in this pinmux driver, the core will begin on 0 and call this
- * repeatedly as long as it returns >= 0 to enumerate the groups
+ * @get_groups_count: Returns the count of total number of groups registered.
* @get_group_name: return the group name of the pin group
* @get_group_pins: return an array of pins corresponding to a certain
* group selector @pins, and the size of the array in @num_pins
* @pin_dbg_show: optional debugfs display hook that will provide per-device
* info for a certain pin in debugfs
+ * @dt_node_to_map: parse a device tree "pin configuration node", and create
+ * mapping table entries for it. These are returned through the @map and
+ * @num_maps output parameters. This function is optional, and may be
+ * omitted for pinctrl drivers that do not support device tree.
+ * @dt_free_map: free mapping table entries created via @dt_node_to_map. The
+ * top-level @map pointer must be freed, along with any dynamically
+ * allocated members of the mapping table entries themselves. This
+ * function is optional, and may be omitted for pinctrl drivers that do
+ * not support device tree.
*/
struct pinctrl_ops {
- int (*list_groups) (struct pinctrl_dev *pctldev, unsigned selector);
+ int (*get_groups_count) (struct pinctrl_dev *pctldev);
const char *(*get_group_name) (struct pinctrl_dev *pctldev,
unsigned selector);
int (*get_group_pins) (struct pinctrl_dev *pctldev,
@@ -83,6 +92,11 @@ struct pinctrl_ops {
unsigned *num_pins);
void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned offset);
+ int (*dt_node_to_map) (struct pinctrl_dev *pctldev,
+ struct device_node *np_config,
+ struct pinctrl_map **map, unsigned *num_maps);
+ void (*dt_free_map) (struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps);
};
/**
diff --git a/include/linux/pinctrl/pinmux.h b/include/linux/pinctrl/pinmux.h
index 47e9237edd47..1818dcbdd9ab 100644
--- a/include/linux/pinctrl/pinmux.h
+++ b/include/linux/pinctrl/pinmux.h
@@ -23,15 +23,14 @@ struct pinctrl_dev;
/**
* struct pinmux_ops - pinmux operations, to be implemented by pin controller
* drivers that support pinmuxing
- * @request: called by the core to see if a certain pin can be made available
+ * @request: called by the core to see if a certain pin can be made
* available for muxing. This is called by the core to acquire the pins
* before selecting any actual mux setting across a function. The driver
* is allowed to answer "no" by returning a negative error code
* @free: the reverse function of the request() callback, frees a pin after
* being requested
- * @list_functions: list the number of selectable named functions available
- * in this pinmux driver, the core will begin on 0 and call this
- * repeatedly as long as it returns >= 0 to enumerate mux settings
+ * @get_functions_count: returns number of selectable named functions available
+ * in this pinmux driver
* @get_function_name: return the function name of the muxing selector,
* called by the core to figure out which mux setting it shall map a
* certain device to
@@ -62,7 +61,7 @@ struct pinctrl_dev;
struct pinmux_ops {
int (*request) (struct pinctrl_dev *pctldev, unsigned offset);
int (*free) (struct pinctrl_dev *pctldev, unsigned offset);
- int (*list_functions) (struct pinctrl_dev *pctldev, unsigned selector);
+ int (*get_functions_count) (struct pinctrl_dev *pctldev);
const char *(*get_function_name) (struct pinctrl_dev *pctldev,
unsigned selector);
int (*get_function_groups) (struct pinctrl_dev *pctldev,
diff --git a/include/linux/platform_data/at91_adc.h b/include/linux/platform_data/at91_adc.h
new file mode 100644
index 000000000000..e15745b4f3a5
--- /dev/null
+++ b/include/linux/platform_data/at91_adc.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 Free Electrons
+ *
+ * Licensed under the GPLv2 or later.
+ */
+
+#ifndef _AT91_ADC_H_
+#define _AT91_ADC_H_
+
+/**
+ * struct at91_adc_reg_desc - Various informations relative to registers
+ * @channel_base: Base offset for the channel data registers
+ * @drdy_mask: Mask of the DRDY field in the relevant registers
+ (Interruptions registers mostly)
+ * @status_register: Offset of the Interrupt Status Register
+ * @trigger_register: Offset of the Trigger setup register
+ */
+struct at91_adc_reg_desc {
+ u8 channel_base;
+ u32 drdy_mask;
+ u8 status_register;
+ u8 trigger_register;
+};
+
+/**
+ * struct at91_adc_trigger - description of triggers
+ * @name: name of the trigger advertised to the user
+ * @value: value to set in the ADC's trigger setup register
+ to enable the trigger
+ * @is_external: Does the trigger rely on an external pin?
+ */
+struct at91_adc_trigger {
+ const char *name;
+ u8 value;
+ bool is_external;
+};
+
+/**
+ * struct at91_adc_data - platform data for ADC driver
+ * @channels_used: channels in use on the board as a bitmask
+ * @num_channels: global number of channels available on the board
+ * @registers: Registers definition on the board
+ * @startup_time: startup time of the ADC in microseconds
+ * @trigger_list: Triggers available in the ADC
+ * @trigger_number: Number of triggers available in the ADC
+ * @use_external_triggers: does the board has external triggers availables
+ * @vref: Reference voltage for the ADC in millivolts
+ */
+struct at91_adc_data {
+ unsigned long channels_used;
+ u8 num_channels;
+ struct at91_adc_reg_desc *registers;
+ u8 startup_time;
+ struct at91_adc_trigger *trigger_list;
+ u8 trigger_number;
+ bool use_external_triggers;
+ u16 vref;
+};
+
+extern void __init at91_add_device_adc(struct at91_adc_data *data);
+#endif
diff --git a/include/linux/platform_data/ehci-sh.h b/include/linux/platform_data/ehci-sh.h
new file mode 100644
index 000000000000..5c15a738e116
--- /dev/null
+++ b/include/linux/platform_data/ehci-sh.h
@@ -0,0 +1,28 @@
+/*
+ * EHCI SuperH driver platform data
+ *
+ * Copyright (C) 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __USB_EHCI_SH_H
+#define __USB_EHCI_SH_H
+
+struct ehci_sh_platdata {
+ void (*phy_init)(void); /* Phy init function */
+};
+
+#endif /* __USB_EHCI_SH_H */
diff --git a/include/linux/platform_data/emif_plat.h b/include/linux/platform_data/emif_plat.h
new file mode 100644
index 000000000000..03378ca84061
--- /dev/null
+++ b/include/linux/platform_data/emif_plat.h
@@ -0,0 +1,128 @@
+/*
+ * Definitions for TI EMIF device platform data
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __EMIF_PLAT_H
+#define __EMIF_PLAT_H
+
+/* Low power modes - EMIF_PWR_MGMT_CTRL */
+#define EMIF_LP_MODE_DISABLE 0
+#define EMIF_LP_MODE_CLOCK_STOP 1
+#define EMIF_LP_MODE_SELF_REFRESH 2
+#define EMIF_LP_MODE_PWR_DN 4
+
+/* Hardware capabilities */
+#define EMIF_HW_CAPS_LL_INTERFACE 0x00000001
+
+/*
+ * EMIF IP Revisions
+ * EMIF4D - Used in OMAP4
+ * EMIF4D5 - Used in OMAP5
+ */
+#define EMIF_4D 1
+#define EMIF_4D5 2
+
+/*
+ * PHY types
+ * ATTILAPHY - Used in OMAP4
+ * INTELLIPHY - Used in OMAP5
+ */
+#define EMIF_PHY_TYPE_ATTILAPHY 1
+#define EMIF_PHY_TYPE_INTELLIPHY 2
+
+/* Custom config requests */
+#define EMIF_CUSTOM_CONFIG_LPMODE 0x00000001
+#define EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL 0x00000002
+
+#ifndef __ASSEMBLY__
+/**
+ * struct ddr_device_info - All information about the DDR device except AC
+ * timing parameters
+ * @type: Device type (LPDDR2-S4, LPDDR2-S2 etc)
+ * @density: Device density
+ * @io_width: Bus width
+ * @cs1_used: Whether there is a DDR device attached to the second
+ * chip-select(CS1) of this EMIF instance
+ * @cal_resistors_per_cs: Whether there is one calibration resistor per
+ * chip-select or whether it's a single one for both
+ * @manufacturer: Manufacturer name string
+ */
+struct ddr_device_info {
+ u32 type;
+ u32 density;
+ u32 io_width;
+ u32 cs1_used;
+ u32 cal_resistors_per_cs;
+ char manufacturer[10];
+};
+
+/**
+ * struct emif_custom_configs - Custom configuration parameters/policies
+ * passed from the platform layer
+ * @mask: Mask to indicate which configs are requested
+ * @lpmode: LPMODE to be used in PWR_MGMT_CTRL register
+ * @lpmode_timeout_performance: Timeout before LPMODE entry when higher
+ * performance is desired at the cost of power (typically
+ * at higher OPPs)
+ * @lpmode_timeout_power: Timeout before LPMODE entry when better power
+ * savings is desired and performance is not important
+ * (typically at lower loads indicated by lower OPPs)
+ * @lpmode_freq_threshold: The DDR frequency threshold to identify between
+ * the above two cases:
+ * timeout = (freq >= lpmode_freq_threshold) ?
+ * lpmode_timeout_performance :
+ * lpmode_timeout_power;
+ * @temp_alert_poll_interval_ms: LPDDR2 MR4 polling interval at nominal
+ * temperature(in milliseconds). When temperature is high
+ * polling is done 4 times as frequently.
+ */
+struct emif_custom_configs {
+ u32 mask;
+ u32 lpmode;
+ u32 lpmode_timeout_performance;
+ u32 lpmode_timeout_power;
+ u32 lpmode_freq_threshold;
+ u32 temp_alert_poll_interval_ms;
+};
+
+/**
+ * struct emif_platform_data - Platform data passed on EMIF platform
+ * device creation. Used by the driver.
+ * @hw_caps: Hw capabilities of the EMIF IP in the respective SoC
+ * @device_info: Device info structure containing information such
+ * as type, bus width, density etc
+ * @timings: Timings information from device datasheet passed
+ * as an array of 'struct lpddr2_timings'. Can be NULL
+ * if if default timings are ok
+ * @timings_arr_size: Size of the timings array. Depends on the number
+ * of different frequencies for which timings data
+ * is provided
+ * @min_tck: Minimum value of some timing parameters in terms
+ * of number of cycles. Can be NULL if default values
+ * are ok
+ * @custom_configs: Custom configurations requested by SoC or board
+ * code and the data for them. Can be NULL if default
+ * configurations done by the driver are ok. See
+ * documentation for 'struct emif_custom_configs' for
+ * more details
+ */
+struct emif_platform_data {
+ u32 hw_caps;
+ struct ddr_device_info *device_info;
+ const struct lpddr2_timings *timings;
+ u32 timings_arr_size;
+ const struct lpddr2_min_tck *min_tck;
+ struct emif_custom_configs *custom_configs;
+ u32 ip_rev;
+ u32 phy_type;
+};
+#endif /* __ASSEMBLY__ */
+
+#endif /* __LINUX_EMIF_H */
diff --git a/include/linux/platform_data/gpio-em.h b/include/linux/platform_data/gpio-em.h
new file mode 100644
index 000000000000..573edfb046c4
--- /dev/null
+++ b/include/linux/platform_data/gpio-em.h
@@ -0,0 +1,10 @@
+#ifndef __GPIO_EM_H__
+#define __GPIO_EM_H__
+
+struct gpio_em_config {
+ unsigned int gpio_base;
+ unsigned int irq_base;
+ unsigned int number_of_pins;
+};
+
+#endif /* __GPIO_EM_H__ */
diff --git a/include/linux/platform_data/ina2xx.h b/include/linux/platform_data/ina2xx.h
new file mode 100644
index 000000000000..9abc0ca7259b
--- /dev/null
+++ b/include/linux/platform_data/ina2xx.h
@@ -0,0 +1,19 @@
+/*
+ * Driver for Texas Instruments INA219, INA226 power monitor chips
+ *
+ * Copyright (C) 2012 Lothar Felten <l-felten@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * For further information, see the Documentation/hwmon/ina2xx file.
+ */
+
+/**
+ * struct ina2xx_platform_data - ina2xx info
+ * @shunt_uohms shunt resistance in microohms
+ */
+struct ina2xx_platform_data {
+ long shunt_uohms;
+};
diff --git a/arch/arm/plat-samsung/include/plat/udc-hs.h b/include/linux/platform_data/s3c-hsotg.h
index c9e3667cb2b1..97ec12c2ded4 100644
--- a/arch/arm/plat-samsung/include/plat/udc-hs.h
+++ b/include/linux/platform_data/s3c-hsotg.h
@@ -1,4 +1,4 @@
-/* arch/arm/plat-s3c/include/plat/udc-hs.h
+/* include/linux/platform_data/s3c-hsotg.h
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
@@ -25,7 +25,8 @@ enum s3c_hsotg_dmamode {
*/
struct s3c_hsotg_plat {
enum s3c_hsotg_dmamode dma;
- unsigned int is_osc : 1;
+ unsigned int is_osc:1;
+ int phy_type;
int (*phy_init)(struct platform_device *pdev, int type);
int (*phy_exit)(struct platform_device *pdev, int type);
diff --git a/include/linux/platform_data/tegra_usb.h b/include/linux/platform_data/tegra_usb.h
index 6bca5b569acb..66c673fef408 100644
--- a/include/linux/platform_data/tegra_usb.h
+++ b/include/linux/platform_data/tegra_usb.h
@@ -26,6 +26,7 @@ struct tegra_ehci_platform_data {
/* power down the phy on bus suspend */
int power_down_on_bus_suspend;
void *phy_config;
+ int vbus_gpio;
};
#endif /* _TEGRA_USB_H_ */
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 715305e05123..f067e60a3832 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -544,8 +544,6 @@ struct dev_pm_info {
unsigned long active_jiffies;
unsigned long suspended_jiffies;
unsigned long accounting_timestamp;
- ktime_t suspend_time;
- s64 max_time_suspended_ns;
struct dev_pm_qos_request *pq_req;
#endif
struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 91f8286106ea..30f794eb3826 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -14,6 +14,7 @@
#include <linux/pm.h>
#include <linux/err.h>
#include <linux/of.h>
+#include <linux/notifier.h>
enum gpd_status {
GPD_STATE_ACTIVE = 0, /* PM domain is active */
@@ -70,9 +71,9 @@ struct generic_pm_domain {
int (*power_on)(struct generic_pm_domain *domain);
s64 power_on_latency_ns;
struct gpd_dev_ops dev_ops;
- s64 break_even_ns; /* Power break even for the entire domain. */
s64 max_off_time_ns; /* Maximum allowed "suspended" time. */
- ktime_t power_off_time;
+ bool max_off_time_changed;
+ bool cached_power_down_ok;
struct device_node *of_node; /* Node in device tree */
};
@@ -93,13 +94,17 @@ struct gpd_timing_data {
s64 start_latency_ns;
s64 save_state_latency_ns;
s64 restore_state_latency_ns;
- s64 break_even_ns;
+ s64 effective_constraint_ns;
+ bool constraint_changed;
+ bool cached_stop_ok;
};
struct generic_pm_domain_data {
struct pm_domain_data base;
struct gpd_dev_ops ops;
struct gpd_timing_data td;
+ struct notifier_block nb;
+ struct mutex lock;
bool need_restore;
bool always_on;
};
@@ -141,6 +146,7 @@ static inline int pm_genpd_of_add_device(struct device_node *genpd_node,
extern int pm_genpd_remove_device(struct generic_pm_domain *genpd,
struct device *dev);
extern void pm_genpd_dev_always_on(struct device *dev, bool val);
+extern void pm_genpd_dev_need_restore(struct device *dev, bool val);
extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *new_subdomain);
extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
@@ -184,6 +190,7 @@ static inline int pm_genpd_remove_device(struct generic_pm_domain *genpd,
return -ENOSYS;
}
static inline void pm_genpd_dev_always_on(struct device *dev, bool val) {}
+static inline void pm_genpd_dev_need_restore(struct device *dev, bool val) {}
static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *new_sd)
{
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index 609daae7a014..f271860c78d5 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -150,9 +150,6 @@ static inline void pm_runtime_set_autosuspend_delay(struct device *dev,
static inline unsigned long pm_runtime_autosuspend_expiration(
struct device *dev) { return 0; }
-static inline void pm_runtime_update_max_time_suspended(struct device *dev,
- s64 delta_ns) {}
-
#endif /* !CONFIG_PM_RUNTIME */
static inline int pm_runtime_idle(struct device *dev)
diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h
index d9f05113e5fb..569781faa504 100644
--- a/include/linux/pm_wakeup.h
+++ b/include/linux/pm_wakeup.h
@@ -33,12 +33,15 @@
*
* @total_time: Total time this wakeup source has been active.
* @max_time: Maximum time this wakeup source has been continuously active.
- * @last_time: Monotonic clock when the wakeup source's was activated last time.
+ * @last_time: Monotonic clock when the wakeup source's was touched last time.
+ * @prevent_sleep_time: Total time this source has been preventing autosleep.
* @event_count: Number of signaled wakeup events.
* @active_count: Number of times the wakeup sorce was activated.
* @relax_count: Number of times the wakeup sorce was deactivated.
- * @hit_count: Number of times the wakeup sorce might abort system suspend.
+ * @expire_count: Number of times the wakeup source's timeout has expired.
+ * @wakeup_count: Number of times the wakeup source might abort suspend.
* @active: Status of the wakeup source.
+ * @has_timeout: The wakeup source has been activated with a timeout.
*/
struct wakeup_source {
const char *name;
@@ -49,11 +52,15 @@ struct wakeup_source {
ktime_t total_time;
ktime_t max_time;
ktime_t last_time;
+ ktime_t start_prevent_time;
+ ktime_t prevent_sleep_time;
unsigned long event_count;
unsigned long active_count;
unsigned long relax_count;
- unsigned long hit_count;
- unsigned int active:1;
+ unsigned long expire_count;
+ unsigned long wakeup_count;
+ bool active:1;
+ bool autosleep_enabled:1;
};
#ifdef CONFIG_PM_SLEEP
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index e0cfec2490aa..78b76e24cc7e 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -124,4 +124,19 @@
#define PR_SET_CHILD_SUBREAPER 36
#define PR_GET_CHILD_SUBREAPER 37
+/*
+ * If no_new_privs is set, then operations that grant new privileges (i.e.
+ * execve) will either fail or not grant them. This affects suid/sgid,
+ * file capabilities, and LSMs.
+ *
+ * Operations that merely manipulate or drop existing privileges (setresuid,
+ * capset, etc.) will still work. Drop those privileges if you want them gone.
+ *
+ * Changing LSM security domain is considered a new privilege. So, for example,
+ * asking selinux for a specific new context (e.g. with runcon) will result
+ * in execve returning -EPERM.
+ */
+#define PR_SET_NO_NEW_PRIVS 38
+#define PR_GET_NO_NEW_PRIVS 39
+
#endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 0525927f203f..1bec2f7a2d42 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -95,8 +95,19 @@ extern int printk_needs_cpu(int cpu);
extern void printk_tick(void);
#ifdef CONFIG_PRINTK
+asmlinkage __printf(5, 0)
+int vprintk_emit(int facility, int level,
+ const char *dict, size_t dictlen,
+ const char *fmt, va_list args);
+
asmlinkage __printf(1, 0)
int vprintk(const char *fmt, va_list args);
+
+asmlinkage __printf(5, 6) __cold
+asmlinkage int printk_emit(int facility, int level,
+ const char *dict, size_t dictlen,
+ const char *fmt, ...);
+
asmlinkage __printf(1, 2) __cold
int printk(const char *fmt, ...);
@@ -289,6 +300,8 @@ extern void dump_stack(void) __cold;
no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif
+extern const struct file_operations kmsg_fops;
+
enum {
DUMP_PREFIX_NONE,
DUMP_PREFIX_ADDRESS,
diff --git a/drivers/staging/android/persistent_ram.h b/include/linux/pstore_ram.h
index f41e2086c645..7ed7fd4dba49 100644
--- a/drivers/staging/android/persistent_ram.h
+++ b/include/linux/pstore_ram.h
@@ -1,4 +1,6 @@
/*
+ * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
+ * Copyright (C) 2011 Kees Cook <keescook@chromium.org>
* Copyright (C) 2011 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
@@ -12,13 +14,14 @@
*
*/
-#ifndef __LINUX_PERSISTENT_RAM_H__
-#define __LINUX_PERSISTENT_RAM_H__
+#ifndef __LINUX_PSTORE_RAM_H__
+#define __LINUX_PSTORE_RAM_H__
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/types.h>
+#include <linux/init.h>
struct persistent_ram_buffer;
@@ -38,7 +41,8 @@ struct persistent_ram {
};
struct persistent_ram_zone {
- struct list_head node;
+ phys_addr_t paddr;
+ size_t size;
void *vaddr;
struct persistent_ram_buffer *buffer;
size_t buffer_size;
@@ -57,12 +61,14 @@ struct persistent_ram_zone {
char *old_log;
size_t old_log_size;
- size_t old_log_footer_size;
- bool early;
};
int persistent_ram_early_init(struct persistent_ram *ram);
+struct persistent_ram_zone * __init persistent_ram_new(phys_addr_t start,
+ size_t size,
+ bool ecc);
+void persistent_ram_free(struct persistent_ram_zone *prz);
struct persistent_ram_zone *persistent_ram_init_ringbuffer(struct device *dev,
bool ecc);
@@ -75,4 +81,18 @@ void persistent_ram_free_old(struct persistent_ram_zone *prz);
ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
char *str, size_t len);
+/*
+ * Ramoops platform data
+ * @mem_size memory size for ramoops
+ * @mem_address physical memory address to contain ramoops
+ */
+
+struct ramoops_platform_data {
+ unsigned long mem_size;
+ unsigned long mem_address;
+ unsigned long record_size;
+ int dump_oops;
+ bool ecc;
+};
+
#endif
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 5c719627c2aa..597e4fdb97fe 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -58,6 +58,7 @@
#define PTRACE_EVENT_EXEC 4
#define PTRACE_EVENT_VFORK_DONE 5
#define PTRACE_EVENT_EXIT 6
+#define PTRACE_EVENT_SECCOMP 7
/* Extended result codes which enabled by means other than options. */
#define PTRACE_EVENT_STOP 128
@@ -69,8 +70,9 @@
#define PTRACE_O_TRACEEXEC (1 << PTRACE_EVENT_EXEC)
#define PTRACE_O_TRACEVFORKDONE (1 << PTRACE_EVENT_VFORK_DONE)
#define PTRACE_O_TRACEEXIT (1 << PTRACE_EVENT_EXIT)
+#define PTRACE_O_TRACESECCOMP (1 << PTRACE_EVENT_SECCOMP)
-#define PTRACE_O_MASK 0x0000007f
+#define PTRACE_O_MASK 0x000000ff
#include <asm/ptrace.h>
@@ -98,6 +100,7 @@
#define PT_TRACE_EXEC PT_EVENT_FLAG(PTRACE_EVENT_EXEC)
#define PT_TRACE_VFORK_DONE PT_EVENT_FLAG(PTRACE_EVENT_VFORK_DONE)
#define PT_TRACE_EXIT PT_EVENT_FLAG(PTRACE_EVENT_EXIT)
+#define PT_TRACE_SECCOMP PT_EVENT_FLAG(PTRACE_EVENT_SECCOMP)
/* single stepping state bits (used on ARM and PA-RISC) */
#define PT_SINGLESTEP_BIT 31
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index 8c0a3adc5df5..ee753536ab70 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -233,7 +233,10 @@ struct mdp_superblock_1 {
__le32 delta_disks; /* change in number of raid_disks */
__le32 new_layout; /* new layout */
__le32 new_chunk; /* new chunk size (512byte sectors) */
- __u8 pad1[128-124]; /* set to 0 when written */
+ __le32 new_offset; /* signed number to add to data_offset in new
+ * layout. 0 == no-change. This can be
+ * different on each device in the array.
+ */
/* constant this-device information - 64 bytes */
__le64 data_offset; /* sector start of data, often 0 */
@@ -281,10 +284,18 @@ struct mdp_superblock_1 {
* active device with same 'role'.
* 'recovery_offset' is also set.
*/
+#define MD_FEATURE_RESHAPE_BACKWARDS 32 /* Reshape doesn't change number
+ * of devices, but is going
+ * backwards anyway.
+ */
+#define MD_FEATURE_NEW_OFFSET 64 /* new_offset must be honoured */
#define MD_FEATURE_ALL (MD_FEATURE_BITMAP_OFFSET \
|MD_FEATURE_RECOVERY_OFFSET \
|MD_FEATURE_RESHAPE_ACTIVE \
|MD_FEATURE_BAD_BLOCKS \
- |MD_FEATURE_REPLACEMENT)
+ |MD_FEATURE_REPLACEMENT \
+ |MD_FEATURE_RESHAPE_BACKWARDS \
+ |MD_FEATURE_NEW_OFFSET \
+ )
#endif
diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h
index 53272e9860a7..640c69ceec96 100644
--- a/include/linux/raid/pq.h
+++ b/include/linux/raid/pq.h
@@ -99,8 +99,20 @@ extern const struct raid6_calls raid6_altivec2;
extern const struct raid6_calls raid6_altivec4;
extern const struct raid6_calls raid6_altivec8;
+struct raid6_recov_calls {
+ void (*data2)(int, size_t, int, int, void **);
+ void (*datap)(int, size_t, int, void **);
+ int (*valid)(void);
+ const char *name;
+ int priority;
+};
+
+extern const struct raid6_recov_calls raid6_recov_intx1;
+extern const struct raid6_recov_calls raid6_recov_ssse3;
+
/* Algorithm list */
extern const struct raid6_calls * const raid6_algos[];
+extern const struct raid6_recov_calls *const raid6_recov_algos[];
int raid6_select_algo(void);
/* Return values from chk_syndrome */
@@ -111,14 +123,16 @@ int raid6_select_algo(void);
/* Galois field tables */
extern const u8 raid6_gfmul[256][256] __attribute__((aligned(256)));
+extern const u8 raid6_vgfmul[256][32] __attribute__((aligned(256)));
extern const u8 raid6_gfexp[256] __attribute__((aligned(256)));
extern const u8 raid6_gfinv[256] __attribute__((aligned(256)));
extern const u8 raid6_gfexi[256] __attribute__((aligned(256)));
/* Recovery routines */
-void raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
+extern void (*raid6_2data_recov)(int disks, size_t bytes, int faila, int failb,
void **ptrs);
-void raid6_datap_recov(int disks, size_t bytes, int faila, void **ptrs);
+extern void (*raid6_datap_recov)(int disks, size_t bytes, int faila,
+ void **ptrs);
void raid6_dual_recov(int disks, size_t bytes, int faila, int failb,
void **ptrs);
diff --git a/include/linux/ramoops.h b/include/linux/ramoops.h
deleted file mode 100644
index 484fef81cd3a..000000000000
--- a/include/linux/ramoops.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __RAMOOPS_H
-#define __RAMOOPS_H
-
-/*
- * Ramoops platform data
- * @mem_size memory size for ramoops
- * @mem_address physical memory address to contain ramoops
- */
-
-struct ramoops_platform_data {
- unsigned long mem_size;
- unsigned long mem_address;
- unsigned long record_size;
- int dump_oops;
-};
-
-#endif
diff --git a/include/linux/rational.h b/include/linux/rational.h
index 4f532fcd9eea..bfa6a2bcfb32 100644
--- a/include/linux/rational.h
+++ b/include/linux/rational.h
@@ -1,7 +1,7 @@
/*
* rational fractions
*
- * Copyright (C) 2009 emlix GmbH, Oskar Schirmer <os@emlix.com>
+ * Copyright (C) 2009 emlix GmbH, Oskar Schirmer <oskar@scara.com>
*
* helper functions when coping with rational numbers,
* e.g. when calculating optimum numerator/denominator pairs for
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index d079290843a9..e0f0fab20415 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -30,6 +30,7 @@
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
+#ifndef CONFIG_DEBUG_LIST
static inline void __list_add_rcu(struct list_head *new,
struct list_head *prev, struct list_head *next)
{
@@ -38,6 +39,10 @@ static inline void __list_add_rcu(struct list_head *new,
rcu_assign_pointer(list_next_rcu(prev), new);
next->prev = new;
}
+#else
+extern void __list_add_rcu(struct list_head *new,
+ struct list_head *prev, struct list_head *next);
+#endif
/**
* list_add_rcu - add a new entry to rcu-protected list
@@ -108,7 +113,7 @@ static inline void list_add_tail_rcu(struct list_head *new,
*/
static inline void list_del_rcu(struct list_head *entry)
{
- __list_del(entry->prev, entry->next);
+ __list_del_entry(entry);
entry->prev = LIST_POISON2;
}
@@ -228,18 +233,43 @@ static inline void list_splice_init_rcu(struct list_head *list,
})
/**
- * list_first_entry_rcu - get the first element from a list
+ * Where are list_empty_rcu() and list_first_entry_rcu()?
+ *
+ * Implementing those functions following their counterparts list_empty() and
+ * list_first_entry() is not advisable because they lead to subtle race
+ * conditions as the following snippet shows:
+ *
+ * if (!list_empty_rcu(mylist)) {
+ * struct foo *bar = list_first_entry_rcu(mylist, struct foo, list_member);
+ * do_something(bar);
+ * }
+ *
+ * The list may not be empty when list_empty_rcu checks it, but it may be when
+ * list_first_entry_rcu rereads the ->next pointer.
+ *
+ * Rereading the ->next pointer is not a problem for list_empty() and
+ * list_first_entry() because they would be protected by a lock that blocks
+ * writers.
+ *
+ * See list_first_or_null_rcu for an alternative.
+ */
+
+/**
+ * list_first_or_null_rcu - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
- * Note, that list is expected to be not empty.
+ * Note that if the list is empty, it returns NULL.
*
* This primitive may safely run concurrently with the _rcu list-mutation
* primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
*/
-#define list_first_entry_rcu(ptr, type, member) \
- list_entry_rcu((ptr)->next, type, member)
+#define list_first_or_null_rcu(ptr, type, member) \
+ ({struct list_head *__ptr = (ptr); \
+ struct list_head __rcu *__next = list_next_rcu(__ptr); \
+ likely(__ptr != __next) ? container_of(__next, type, member) : NULL; \
+ })
/**
* list_for_each_entry_rcu - iterate over rcu list of given type
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 20fb776a1d4a..26d1a47591f1 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -184,12 +184,14 @@ static inline int rcu_preempt_depth(void)
/* Internal to kernel */
extern void rcu_sched_qs(int cpu);
extern void rcu_bh_qs(int cpu);
+extern void rcu_preempt_note_context_switch(void);
extern void rcu_check_callbacks(int cpu, int user);
struct notifier_block;
extern void rcu_idle_enter(void);
extern void rcu_idle_exit(void);
extern void rcu_irq_enter(void);
extern void rcu_irq_exit(void);
+extern void exit_rcu(void);
/**
* RCU_NONIDLE - Indicate idle-loop code that needs RCU readers
@@ -922,6 +924,21 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
kfree_call_rcu(head, (rcu_callback)offset);
}
+/*
+ * Does the specified offset indicate that the corresponding rcu_head
+ * structure can be handled by kfree_rcu()?
+ */
+#define __is_kfree_rcu_offset(offset) ((offset) < 4096)
+
+/*
+ * Helper macro for kfree_rcu() to prevent argument-expansion eyestrain.
+ */
+#define __kfree_rcu(head, offset) \
+ do { \
+ BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
+ call_rcu(head, (void (*)(struct rcu_head *))(unsigned long)(offset)); \
+ } while (0)
+
/**
* kfree_rcu() - kfree an object after a grace period.
* @ptr: pointer to kfree
@@ -944,6 +961,9 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
*
* Note that the allowable offset might decrease in the future, for example,
* to allow something like kmem_cache_free_rcu().
+ *
+ * The BUILD_BUG_ON check must not involve any function calls, hence the
+ * checks are done in macros here.
*/
#define kfree_rcu(ptr, rcu_head) \
__kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index e93df77176d1..adb5e5a38cae 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -87,14 +87,6 @@ static inline void kfree_call_rcu(struct rcu_head *head,
#ifdef CONFIG_TINY_RCU
-static inline void rcu_preempt_note_context_switch(void)
-{
-}
-
-static inline void exit_rcu(void)
-{
-}
-
static inline int rcu_needs_cpu(int cpu)
{
return 0;
@@ -102,8 +94,6 @@ static inline int rcu_needs_cpu(int cpu)
#else /* #ifdef CONFIG_TINY_RCU */
-void rcu_preempt_note_context_switch(void);
-extern void exit_rcu(void);
int rcu_preempt_needs_cpu(void);
static inline int rcu_needs_cpu(int cpu)
@@ -116,7 +106,6 @@ static inline int rcu_needs_cpu(int cpu)
static inline void rcu_note_context_switch(int cpu)
{
rcu_sched_qs(cpu);
- rcu_preempt_note_context_switch();
}
/*
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index e8ee5dd0854c..3c6083cde4fc 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -45,18 +45,6 @@ static inline void rcu_virt_note_context_switch(int cpu)
rcu_note_context_switch(cpu);
}
-#ifdef CONFIG_TREE_PREEMPT_RCU
-
-extern void exit_rcu(void);
-
-#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-
-static inline void exit_rcu(void)
-{
-}
-
-#endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */
-
extern void synchronize_rcu_bh(void);
extern void synchronize_sched_expedited(void);
extern void synchronize_rcu_expedited(void);
@@ -98,13 +86,6 @@ extern void rcu_force_quiescent_state(void);
extern void rcu_bh_force_quiescent_state(void);
extern void rcu_sched_force_quiescent_state(void);
-/* A context switch is a grace period for RCU-sched and RCU-bh. */
-static inline int rcu_blocking_is_gp(void)
-{
- might_sleep(); /* Check for RCU read-side critical section. */
- return num_online_cpus() == 1;
-}
-
extern void rcu_scheduler_starting(void);
extern int rcu_scheduler_active __read_mostly;
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index a90abb6bfa64..56af22ec9aba 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -46,7 +46,13 @@ struct reg_default {
/**
* Configuration for the register map of a device.
*
+ * @name: Optional name of the regmap. Useful when a device has multiple
+ * register regions.
+ *
* @reg_bits: Number of bits in a register address, mandatory.
+ * @reg_stride: The register address stride. Valid register addresses are a
+ * multiple of this value. If set to 0, a value of 1 will be
+ * used.
* @pad_bits: Number of bits of padding between register and value.
* @val_bits: Number of bits in a register value, mandatory.
*
@@ -70,6 +76,9 @@ struct reg_default {
* @write_flag_mask: Mask to be set in the top byte of the register when doing
* a write. If both read_flag_mask and write_flag_mask are
* empty the regmap_bus default masks are used.
+ * @use_single_rw: If set, converts the bulk read and write operations into
+ * a series of single read and write operations. This is useful
+ * for device that does not support bulk read and write.
*
* @cache_type: The actual cache type.
* @reg_defaults_raw: Power on reset values for registers (for use with
@@ -77,7 +86,10 @@ struct reg_default {
* @num_reg_defaults_raw: Number of elements in reg_defaults_raw.
*/
struct regmap_config {
+ const char *name;
+
int reg_bits;
+ int reg_stride;
int pad_bits;
int val_bits;
@@ -95,20 +107,25 @@ struct regmap_config {
u8 read_flag_mask;
u8 write_flag_mask;
+
+ bool use_single_rw;
};
-typedef int (*regmap_hw_write)(struct device *dev, const void *data,
+typedef int (*regmap_hw_write)(void *context, const void *data,
size_t count);
-typedef int (*regmap_hw_gather_write)(struct device *dev,
+typedef int (*regmap_hw_gather_write)(void *context,
const void *reg, size_t reg_len,
const void *val, size_t val_len);
-typedef int (*regmap_hw_read)(struct device *dev,
+typedef int (*regmap_hw_read)(void *context,
const void *reg_buf, size_t reg_size,
void *val_buf, size_t val_size);
+typedef void (*regmap_hw_free_context)(void *context);
/**
* Description of a hardware bus for the register map infrastructure.
*
+ * @fast_io: Register IO is fast. Use a spinlock instead of a mutex
+ * to perform locking.
* @write: Write operation.
* @gather_write: Write operation with split register/value, return -ENOTSUPP
* if not implemented on a given device.
@@ -118,31 +135,42 @@ typedef int (*regmap_hw_read)(struct device *dev,
* a read.
*/
struct regmap_bus {
+ bool fast_io;
regmap_hw_write write;
regmap_hw_gather_write gather_write;
regmap_hw_read read;
+ regmap_hw_free_context free_context;
u8 read_flag_mask;
};
struct regmap *regmap_init(struct device *dev,
const struct regmap_bus *bus,
+ void *bus_context,
const struct regmap_config *config);
struct regmap *regmap_init_i2c(struct i2c_client *i2c,
const struct regmap_config *config);
struct regmap *regmap_init_spi(struct spi_device *dev,
const struct regmap_config *config);
+struct regmap *regmap_init_mmio(struct device *dev,
+ void __iomem *regs,
+ const struct regmap_config *config);
struct regmap *devm_regmap_init(struct device *dev,
const struct regmap_bus *bus,
+ void *bus_context,
const struct regmap_config *config);
struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c,
const struct regmap_config *config);
struct regmap *devm_regmap_init_spi(struct spi_device *dev,
const struct regmap_config *config);
+struct regmap *devm_regmap_init_mmio(struct device *dev,
+ void __iomem *regs,
+ const struct regmap_config *config);
void regmap_exit(struct regmap *map);
int regmap_reinit_cache(struct regmap *map,
const struct regmap_config *config);
+struct regmap *dev_get_regmap(struct device *dev, const char *name);
int regmap_write(struct regmap *map, unsigned int reg, unsigned int val);
int regmap_raw_write(struct regmap *map, unsigned int reg,
const void *val, size_t val_len);
@@ -191,6 +219,7 @@ struct regmap_irq {
* @status_base: Base status register address.
* @mask_base: Base mask register address.
* @ack_base: Base ack address. If zero then the chip is clear on read.
+ * @irq_reg_stride: Stride to use for chips where registers are not contiguous.
*
* @num_regs: Number of registers in each control bank.
* @irqs: Descriptors for individual IRQs. Interrupt numbers are
@@ -203,6 +232,7 @@ struct regmap_irq_chip {
unsigned int status_base;
unsigned int mask_base;
unsigned int ack_base;
+ unsigned int irq_reg_stride;
int num_regs;
@@ -217,6 +247,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
struct regmap_irq_chip_data **data);
void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data);
int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data);
+int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq);
#else
@@ -327,6 +358,13 @@ static inline int regmap_register_patch(struct regmap *map,
return -EINVAL;
}
+static inline struct regmap *dev_get_regmap(struct device *dev,
+ const char *name)
+{
+ WARN_ONCE(1, "regmap API is disabled");
+ return NULL;
+}
+
#endif
#endif
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index fa8b55b8191c..b0432cc2b169 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -19,6 +19,7 @@
#include <linux/notifier.h>
#include <linux/regulator/consumer.h>
+struct regmap;
struct regulator_dev;
struct regulator_init_data;
@@ -45,6 +46,7 @@ enum regulator_status {
* The driver should select the voltage closest to min_uV.
* @set_voltage_sel: Set the voltage for the regulator using the specified
* selector.
+ * @map_voltage: Convert a voltage into a selector
* @get_voltage: Return the currently configured voltage for the regulator.
* @get_voltage_sel: Return the currently configured voltage selector for the
* regulator.
@@ -90,6 +92,7 @@ struct regulator_ops {
/* get/set regulator voltage */
int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV,
unsigned *selector);
+ int (*map_voltage)(struct regulator_dev *, int min_uV, int max_uV);
int (*set_voltage_sel) (struct regulator_dev *, unsigned selector);
int (*get_voltage) (struct regulator_dev *);
int (*get_voltage_sel) (struct regulator_dev *);
@@ -148,19 +151,30 @@ enum regulator_type {
};
/**
- * struct regulator_desc - Regulator descriptor
+ * struct regulator_desc - Static regulator descriptor
*
- * Each regulator registered with the core is described with a structure of
- * this type.
+ * Each regulator registered with the core is described with a
+ * structure of this type and a struct regulator_config. This
+ * structure contains the non-varying parts of the regulator
+ * description.
*
* @name: Identifying name for the regulator.
* @supply_name: Identifying the regulator supply
* @id: Numerical identifier for the regulator.
- * @n_voltages: Number of selectors available for ops.list_voltage().
* @ops: Regulator operations table.
* @irq: Interrupt number for the regulator.
* @type: Indicates if the regulator is a voltage or current regulator.
* @owner: Module providing the regulator, used for refcounting.
+ *
+ * @n_voltages: Number of selectors available for ops.list_voltage().
+ *
+ * @min_uV: Voltage given by the lowest selector (if linear mapping)
+ * @uV_step: Voltage increase with each selector (if linear mapping)
+ *
+ * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_
+ * @vsel_mask: Mask for register bitfield used for selector
+ * @enable_reg: Register for control when using regmap enable/disable ops
+ * @enable_mask: Mask for control when using regmap enable/disable ops
*/
struct regulator_desc {
const char *name;
@@ -171,6 +185,36 @@ struct regulator_desc {
int irq;
enum regulator_type type;
struct module *owner;
+
+ unsigned int min_uV;
+ unsigned int uV_step;
+
+ unsigned int vsel_reg;
+ unsigned int vsel_mask;
+ unsigned int enable_reg;
+ unsigned int enable_mask;
+};
+
+/**
+ * struct regulator_config - Dynamic regulator descriptor
+ *
+ * Each regulator registered with the core is described with a
+ * structure of this type and a struct regulator_desc. This structure
+ * contains the runtime variable parts of the regulator description.
+ *
+ * @dev: struct device for the regulator
+ * @init_data: platform provided init data, passed through by driver
+ * @driver_data: private regulator data
+ * @of_node: OpenFirmware node to parse for device tree bindings (may be
+ * NULL).
+ * @regmap: regmap to use for core regmap helpers
+ */
+struct regulator_config {
+ struct device *dev;
+ const struct regulator_init_data *init_data;
+ void *driver_data;
+ struct device_node *of_node;
+ struct regmap *regmap;
};
/*
@@ -184,7 +228,7 @@ struct regulator_desc {
* no other direct access).
*/
struct regulator_dev {
- struct regulator_desc *desc;
+ const struct regulator_desc *desc;
int exclusive;
u32 use_count;
u32 open_count;
@@ -201,6 +245,7 @@ struct regulator_dev {
struct device dev;
struct regulation_constraints *constraints;
struct regulator *supply; /* for tree */
+ struct regmap *regmap;
struct delayed_work disable_work;
int deferred_disables;
@@ -210,9 +255,9 @@ struct regulator_dev {
struct dentry *debugfs;
};
-struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
- struct device *dev, const struct regulator_init_data *init_data,
- void *driver_data, struct device_node *of_node);
+struct regulator_dev *
+regulator_register(const struct regulator_desc *regulator_desc,
+ const struct regulator_config *config);
void regulator_unregister(struct regulator_dev *rdev);
int regulator_notifier_call_chain(struct regulator_dev *rdev,
@@ -224,6 +269,18 @@ int rdev_get_id(struct regulator_dev *rdev);
int regulator_mode_to_status(unsigned int);
+int regulator_list_voltage_linear(struct regulator_dev *rdev,
+ unsigned int selector);
+int regulator_map_voltage_linear(struct regulator_dev *rdev,
+ int min_uV, int max_uV);
+int regulator_map_voltage_iterate(struct regulator_dev *rdev,
+ int min_uV, int max_uV);
+int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev);
+int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel);
+int regulator_is_enabled_regmap(struct regulator_dev *rdev);
+int regulator_enable_regmap(struct regulator_dev *rdev);
+int regulator_disable_regmap(struct regulator_dev *rdev);
+
void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);
#endif
diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h
index 936a7d8c11a9..f83f7440b488 100644
--- a/include/linux/regulator/fixed.h
+++ b/include/linux/regulator/fixed.h
@@ -26,6 +26,12 @@ struct regulator_init_data;
* @gpio: GPIO to use for enable control
* set to -EINVAL if not used
* @startup_delay: Start-up time in microseconds
+ * @gpio_is_open_drain: Gpio pin is open drain or normal type.
+ * If it is open drain type then HIGH will be set
+ * through PULL-UP with setting gpio as input
+ * and low will be set as gpio-output with driven
+ * to low. For non-open-drain case, the gpio will
+ * will be in output and drive to low/high accordingly.
* @enable_high: Polarity of enable GPIO
* 1 = Active high, 0 = Active low
* @enabled_at_boot: Whether regulator has been enabled at
@@ -43,6 +49,7 @@ struct fixed_voltage_config {
int microvolts;
int gpio;
unsigned startup_delay;
+ unsigned gpio_is_open_drain:1;
unsigned enable_high:1;
unsigned enabled_at_boot:1;
struct regulator_init_data *init_data;
diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h
index 769704f296e5..f9217965aaa3 100644
--- a/include/linux/regulator/of_regulator.h
+++ b/include/linux/regulator/of_regulator.h
@@ -6,10 +6,20 @@
#ifndef __LINUX_OF_REG_H
#define __LINUX_OF_REG_H
+struct of_regulator_match {
+ const char *name;
+ void *driver_data;
+ struct regulator_init_data *init_data;
+ struct device_node *of_node;
+};
+
#if defined(CONFIG_OF)
extern struct regulator_init_data
*of_get_regulator_init_data(struct device *dev,
struct device_node *node);
+extern int of_regulator_match(struct device *dev, struct device_node *node,
+ struct of_regulator_match *matches,
+ unsigned int num_matches);
#else
static inline struct regulator_init_data
*of_get_regulator_init_data(struct device *dev,
@@ -17,6 +27,14 @@ static inline struct regulator_init_data
{
return NULL;
}
+
+static inline int of_regulator_match(struct device *dev,
+ struct device_node *node,
+ struct of_regulator_match *matches,
+ unsigned int num_matches)
+{
+ return 0;
+}
#endif /* CONFIG_OF */
#endif /* __LINUX_OF_REG_H */
diff --git a/include/linux/regulator/tps62360.h b/include/linux/regulator/tps62360.h
index 6a5c1b2c751e..a4c49394c497 100644
--- a/include/linux/regulator/tps62360.h
+++ b/include/linux/regulator/tps62360.h
@@ -26,13 +26,10 @@
#ifndef __LINUX_REGULATOR_TPS62360_H
#define __LINUX_REGULATOR_TPS62360_H
-#include <linux/regulator/machine.h>
-
/*
* struct tps62360_regulator_platform_data - tps62360 regulator platform data.
*
* @reg_init_data: The regulator init data.
- * @en_force_pwm: Enable force pwm or not.
* @en_discharge: Enable discharge the output capacitor via internal
* register.
* @en_internal_pulldn: internal pull down enable or not.
@@ -44,8 +41,7 @@
* @vsel1_def_state: Default state of vsel1. 1 if it is high else 0.
*/
struct tps62360_regulator_platform_data {
- struct regulator_init_data reg_init_data;
- bool en_force_pwm;
+ struct regulator_init_data *reg_init_data;
bool en_discharge;
bool en_internal_pulldn;
int vsel0_gpio;
diff --git a/include/linux/regulator/tps65090-regulator.h b/include/linux/regulator/tps65090-regulator.h
new file mode 100644
index 000000000000..0fa04b64db3e
--- /dev/null
+++ b/include/linux/regulator/tps65090-regulator.h
@@ -0,0 +1,50 @@
+/*
+ * Regulator driver interface for TI TPS65090 PMIC family
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __REGULATOR_TPS65090_H
+#define __REGULATOR_TPS65090_H
+
+#include <linux/regulator/machine.h>
+
+#define tps65090_rails(_name) "tps65090_"#_name
+
+enum {
+ TPS65090_ID_DCDC1,
+ TPS65090_ID_DCDC2,
+ TPS65090_ID_DCDC3,
+ TPS65090_ID_FET1,
+ TPS65090_ID_FET2,
+ TPS65090_ID_FET3,
+ TPS65090_ID_FET4,
+ TPS65090_ID_FET5,
+ TPS65090_ID_FET6,
+ TPS65090_ID_FET7,
+};
+
+/*
+ * struct tps65090_regulator_platform_data
+ *
+ * @regulator: The regulator init data.
+ * @slew_rate_uV_per_us: Slew rate microvolt per microsec.
+ */
+
+struct tps65090_regulator_platform_data {
+ struct regulator_init_data regulator;
+};
+
+#endif /* __REGULATOR_TPS65090_H */
diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h
index da81af086eaf..fb201896a8b0 100644
--- a/include/linux/res_counter.h
+++ b/include/linux/res_counter.h
@@ -116,7 +116,7 @@ void res_counter_init(struct res_counter *counter, struct res_counter *parent);
*/
int __must_check res_counter_charge_locked(struct res_counter *counter,
- unsigned long val);
+ unsigned long val, bool force);
int __must_check res_counter_charge(struct res_counter *counter,
unsigned long val, struct res_counter **limit_fail_at);
int __must_check res_counter_charge_nofail(struct res_counter *counter,
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index 7be2e88f23fd..6c8835f74f79 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -96,9 +96,11 @@ __ring_buffer_alloc(unsigned long size, unsigned flags, struct lock_class_key *k
__ring_buffer_alloc((size), (flags), &__key); \
})
+#define RING_BUFFER_ALL_CPUS -1
+
void ring_buffer_free(struct ring_buffer *buffer);
-int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size);
+int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size, int cpu);
void ring_buffer_change_overwrite(struct ring_buffer *buffer, int val);
@@ -129,7 +131,7 @@ ring_buffer_read(struct ring_buffer_iter *iter, u64 *ts);
void ring_buffer_iter_reset(struct ring_buffer_iter *iter);
int ring_buffer_iter_empty(struct ring_buffer_iter *iter);
-unsigned long ring_buffer_size(struct ring_buffer *buffer);
+unsigned long ring_buffer_size(struct ring_buffer *buffer, int cpu);
void ring_buffer_reset_cpu(struct ring_buffer *buffer, int cpu);
void ring_buffer_reset(struct ring_buffer *buffer);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 81a173c0897d..28fa9d02fd59 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -855,61 +855,14 @@ enum cpu_idle_type {
#define SD_WAKE_AFFINE 0x0020 /* Wake task to waking CPU */
#define SD_PREFER_LOCAL 0x0040 /* Prefer to keep tasks local to this domain */
#define SD_SHARE_CPUPOWER 0x0080 /* Domain members share cpu power */
-#define SD_POWERSAVINGS_BALANCE 0x0100 /* Balance for power savings */
#define SD_SHARE_PKG_RESOURCES 0x0200 /* Domain members share cpu pkg resources */
#define SD_SERIALIZE 0x0400 /* Only a single load balancing instance */
#define SD_ASYM_PACKING 0x0800 /* Place busy groups earlier in the domain */
#define SD_PREFER_SIBLING 0x1000 /* Prefer to place tasks in a sibling domain */
#define SD_OVERLAP 0x2000 /* sched_domains of this level overlap */
-enum powersavings_balance_level {
- POWERSAVINGS_BALANCE_NONE = 0, /* No power saving load balance */
- POWERSAVINGS_BALANCE_BASIC, /* Fill one thread/core/package
- * first for long running threads
- */
- POWERSAVINGS_BALANCE_WAKEUP, /* Also bias task wakeups to semi-idle
- * cpu package for power savings
- */
- MAX_POWERSAVINGS_BALANCE_LEVELS
-};
-
-extern int sched_mc_power_savings, sched_smt_power_savings;
-
-static inline int sd_balance_for_mc_power(void)
-{
- if (sched_smt_power_savings)
- return SD_POWERSAVINGS_BALANCE;
-
- if (!sched_mc_power_savings)
- return SD_PREFER_SIBLING;
-
- return 0;
-}
-
-static inline int sd_balance_for_package_power(void)
-{
- if (sched_mc_power_savings | sched_smt_power_savings)
- return SD_POWERSAVINGS_BALANCE;
-
- return SD_PREFER_SIBLING;
-}
-
extern int __weak arch_sd_sibiling_asym_packing(void);
-/*
- * Optimise SD flags for power savings:
- * SD_BALANCE_NEWIDLE helps aggressive task consolidation and power savings.
- * Keep default SD flags if sched_{smt,mc}_power_saving=0
- */
-
-static inline int sd_power_saving_flags(void)
-{
- if (sched_mc_power_savings | sched_smt_power_savings)
- return SD_BALANCE_NEWIDLE;
-
- return 0;
-}
-
struct sched_group_power {
atomic_t ref;
/*
@@ -1341,6 +1294,8 @@ struct task_struct {
* execve */
unsigned in_iowait:1;
+ /* task may not gain privileges */
+ unsigned no_new_privs:1;
/* Revert to default priority/policy when forking */
unsigned sched_reset_on_fork:1;
@@ -1450,7 +1405,7 @@ struct task_struct {
uid_t loginuid;
unsigned int sessionid;
#endif
- seccomp_t seccomp;
+ struct seccomp seccomp;
/* Thread group tracking */
u32 parent_exec_id;
@@ -1905,12 +1860,22 @@ static inline void rcu_copy_process(struct task_struct *p)
INIT_LIST_HEAD(&p->rcu_node_entry);
}
+static inline void rcu_switch_from(struct task_struct *prev)
+{
+ if (prev->rcu_read_lock_nesting != 0)
+ rcu_preempt_note_context_switch();
+}
+
#else
static inline void rcu_copy_process(struct task_struct *p)
{
}
+static inline void rcu_switch_from(struct task_struct *prev)
+{
+}
+
#endif
#ifdef CONFIG_SMP
@@ -1950,7 +1915,7 @@ static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
*/
extern unsigned long long notrace sched_clock(void);
/*
- * See the comment in kernel/sched_clock.c
+ * See the comment in kernel/sched/clock.c
*/
extern u64 cpu_clock(int cpu);
extern u64 local_clock(void);
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index cc7a4e9cc7ad..84f6320da50f 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -1,25 +1,90 @@
#ifndef _LINUX_SECCOMP_H
#define _LINUX_SECCOMP_H
-
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+
+/* Valid values for seccomp.mode and prctl(PR_SET_SECCOMP, <mode>) */
+#define SECCOMP_MODE_DISABLED 0 /* seccomp is not in use. */
+#define SECCOMP_MODE_STRICT 1 /* uses hard-coded filter. */
+#define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
+
+/*
+ * All BPF programs must return a 32-bit value.
+ * The bottom 16-bits are for optional return data.
+ * The upper 16-bits are ordered from least permissive values to most.
+ *
+ * The ordering ensures that a min_t() over composed return values always
+ * selects the least permissive choice.
+ */
+#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
+#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
+#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
+#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
+#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
+
+/* Masks for the return value sections. */
+#define SECCOMP_RET_ACTION 0x7fff0000U
+#define SECCOMP_RET_DATA 0x0000ffffU
+
+/**
+ * struct seccomp_data - the format the BPF program executes over.
+ * @nr: the system call number
+ * @arch: indicates system call convention as an AUDIT_ARCH_* value
+ * as defined in <linux/audit.h>.
+ * @instruction_pointer: at the time of the system call.
+ * @args: up to 6 system call arguments always stored as 64-bit values
+ * regardless of the architecture.
+ */
+struct seccomp_data {
+ int nr;
+ __u32 arch;
+ __u64 instruction_pointer;
+ __u64 args[6];
+};
+
+#ifdef __KERNEL__
#ifdef CONFIG_SECCOMP
#include <linux/thread_info.h>
#include <asm/seccomp.h>
-typedef struct { int mode; } seccomp_t;
-
-extern void __secure_computing(int);
-static inline void secure_computing(int this_syscall)
+struct seccomp_filter;
+/**
+ * struct seccomp - the state of a seccomp'ed process
+ *
+ * @mode: indicates one of the valid values above for controlled
+ * system calls available to a process.
+ * @filter: The metadata and ruleset for determining what system calls
+ * are allowed for a task.
+ *
+ * @filter must only be accessed from the context of current as there
+ * is no locking.
+ */
+struct seccomp {
+ int mode;
+ struct seccomp_filter *filter;
+};
+
+extern int __secure_computing(int);
+static inline int secure_computing(int this_syscall)
{
if (unlikely(test_thread_flag(TIF_SECCOMP)))
- __secure_computing(this_syscall);
+ return __secure_computing(this_syscall);
+ return 0;
+}
+
+/* A wrapper for architectures supporting only SECCOMP_MODE_STRICT. */
+static inline void secure_computing_strict(int this_syscall)
+{
+ BUG_ON(secure_computing(this_syscall) != 0);
}
extern long prctl_get_seccomp(void);
-extern long prctl_set_seccomp(unsigned long);
+extern long prctl_set_seccomp(unsigned long, char __user *);
-static inline int seccomp_mode(seccomp_t *s)
+static inline int seccomp_mode(struct seccomp *s)
{
return s->mode;
}
@@ -28,25 +93,41 @@ static inline int seccomp_mode(seccomp_t *s)
#include <linux/errno.h>
-typedef struct { } seccomp_t;
+struct seccomp { };
+struct seccomp_filter { };
-#define secure_computing(x) do { } while (0)
+static inline int secure_computing(int this_syscall) { return 0; }
+static inline void secure_computing_strict(int this_syscall) { return; }
static inline long prctl_get_seccomp(void)
{
return -EINVAL;
}
-static inline long prctl_set_seccomp(unsigned long arg2)
+static inline long prctl_set_seccomp(unsigned long arg2, char __user *arg3)
{
return -EINVAL;
}
-static inline int seccomp_mode(seccomp_t *s)
+static inline int seccomp_mode(struct seccomp *s)
{
return 0;
}
-
#endif /* CONFIG_SECCOMP */
+#ifdef CONFIG_SECCOMP_FILTER
+extern void put_seccomp_filter(struct task_struct *tsk);
+extern void get_seccomp_filter(struct task_struct *tsk);
+extern u32 seccomp_bpf_load(int off);
+#else /* CONFIG_SECCOMP_FILTER */
+static inline void put_seccomp_filter(struct task_struct *tsk)
+{
+ return;
+}
+static inline void get_seccomp_filter(struct task_struct *tsk)
+{
+ return;
+}
+#endif /* CONFIG_SECCOMP_FILTER */
+#endif /* __KERNEL__ */
#endif /* _LINUX_SECCOMP_H */
diff --git a/include/linux/security.h b/include/linux/security.h
index 673afbb8238a..ab0e091ce5fa 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -144,6 +144,7 @@ struct request_sock;
#define LSM_UNSAFE_SHARE 1
#define LSM_UNSAFE_PTRACE 2
#define LSM_UNSAFE_PTRACE_CAP 4
+#define LSM_UNSAFE_NO_NEW_PRIVS 8
#ifdef CONFIG_MMU
extern int mmap_min_addr_handler(struct ctl_table *table, int write,
@@ -639,10 +640,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* to receive an open file descriptor via socket IPC.
* @file contains the file structure being received.
* Return 0 if permission is granted.
- *
- * Security hook for dentry
- *
- * @dentry_open
+ * @file_open
* Save open-time permission checking state for later use upon
* file_permission, and recheck access if anything has changed
* since inode_permission.
@@ -1497,7 +1495,7 @@ struct security_operations {
int (*file_send_sigiotask) (struct task_struct *tsk,
struct fown_struct *fown, int sig);
int (*file_receive) (struct file *file);
- int (*dentry_open) (struct file *file, const struct cred *cred);
+ int (*file_open) (struct file *file, const struct cred *cred);
int (*task_create) (unsigned long clone_flags);
void (*task_free) (struct task_struct *task);
@@ -1756,7 +1754,7 @@ int security_file_set_fowner(struct file *file);
int security_file_send_sigiotask(struct task_struct *tsk,
struct fown_struct *fown, int sig);
int security_file_receive(struct file *file);
-int security_dentry_open(struct file *file, const struct cred *cred);
+int security_file_open(struct file *file, const struct cred *cred);
int security_task_create(unsigned long clone_flags);
void security_task_free(struct task_struct *task);
int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
@@ -2227,8 +2225,8 @@ static inline int security_file_receive(struct file *file)
return 0;
}
-static inline int security_dentry_open(struct file *file,
- const struct cred *cred)
+static inline int security_file_open(struct file *file,
+ const struct cred *cred)
{
return 0;
}
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 6c5047dbfea3..a416e92012ef 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -38,6 +38,7 @@ struct plat_serial8250_port {
int (*handle_irq)(struct uart_port *);
void (*pm)(struct uart_port *, unsigned int state,
unsigned old);
+ void (*handle_break)(struct uart_port *);
};
/*
@@ -67,6 +68,7 @@ enum {
struct uart_port;
struct uart_8250_port;
+int serial8250_register_8250_port(struct uart_8250_port *);
int serial8250_register_port(struct uart_port *);
void serial8250_unregister_port(int line);
void serial8250_suspend_port(int line);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 2db407a40051..65db9928e15f 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -310,6 +310,7 @@ struct uart_port {
int (*handle_irq)(struct uart_port *);
void (*pm)(struct uart_port *, unsigned int state,
unsigned int old);
+ void (*handle_break)(struct uart_port *);
unsigned int irq; /* irq number */
unsigned long irqflags; /* irq flags */
unsigned int uartclk; /* base uart clock */
@@ -533,6 +534,10 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
static inline int uart_handle_break(struct uart_port *port)
{
struct uart_state *state = port->state;
+
+ if (port->handle_break)
+ port->handle_break(port);
+
#ifdef SUPPORT_SYSRQ
if (port->cons && port->cons->index == port->line) {
if (!port->sysrq) {
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
index 78779074f6e8..eb763adf9815 100644
--- a/include/linux/serial_sci.h
+++ b/include/linux/serial_sci.h
@@ -52,6 +52,8 @@ enum {
/* SCSPTR, optional */
#define SCSPTR_RTSIO (1 << 7)
#define SCSPTR_CTSIO (1 << 5)
+#define SCSPTR_SPB2IO (1 << 1)
+#define SCSPTR_SPB2DT (1 << 0)
/* Offsets into the sci_port->irqs array */
enum {
diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
index 0a9d8f2ac519..c513b73cd7cb 100644
--- a/include/linux/sh_clk.h
+++ b/include/linux/sh_clk.h
@@ -59,7 +59,15 @@ struct clk {
unsigned int nr_freqs;
};
-#define CLK_ENABLE_ON_INIT (1 << 0)
+#define CLK_ENABLE_ON_INIT BIT(0)
+
+#define CLK_ENABLE_REG_32BIT BIT(1) /* default access size */
+#define CLK_ENABLE_REG_16BIT BIT(2)
+#define CLK_ENABLE_REG_8BIT BIT(3)
+
+#define CLK_ENABLE_REG_MASK (CLK_ENABLE_REG_32BIT | \
+ CLK_ENABLE_REG_16BIT | \
+ CLK_ENABLE_REG_8BIT)
/* drivers/sh/clk.c */
unsigned long followparent_recalc(struct clk *);
@@ -102,7 +110,7 @@ long clk_round_parent(struct clk *clk, unsigned long target,
unsigned long *best_freq, unsigned long *parent_freq,
unsigned int div_min, unsigned int div_max);
-#define SH_CLK_MSTP32(_parent, _enable_reg, _enable_bit, _flags) \
+#define SH_CLK_MSTP(_parent, _enable_reg, _enable_bit, _flags) \
{ \
.parent = _parent, \
.enable_reg = (void __iomem *)_enable_reg, \
@@ -110,7 +118,27 @@ long clk_round_parent(struct clk *clk, unsigned long target,
.flags = _flags, \
}
-int sh_clk_mstp32_register(struct clk *clks, int nr);
+#define SH_CLK_MSTP32(_p, _r, _b, _f) \
+ SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_32BIT)
+
+#define SH_CLK_MSTP16(_p, _r, _b, _f) \
+ SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_16BIT)
+
+#define SH_CLK_MSTP8(_p, _r, _b, _f) \
+ SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_8BIT)
+
+int sh_clk_mstp_register(struct clk *clks, int nr);
+
+/*
+ * MSTP registration never really cared about access size, despite the
+ * original enable/disable pairs assuming a 32-bit access. Clocks are
+ * responsible for defining their access sizes either directly or via the
+ * clock definition wrappers.
+ */
+static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr)
+{
+ return sh_clk_mstp_register(clks, nr);
+}
#define SH_CLK_DIV4(_parent, _reg, _shift, _div_bitmap, _flags) \
{ \
diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h
index 6aed0805927f..32383285da68 100644
--- a/include/linux/sh_intc.h
+++ b/include/linux/sh_intc.h
@@ -133,7 +133,6 @@ struct intc_desc symbol __initdata = { \
}
int register_intc_controller(struct intc_desc *desc);
-void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs);
int intc_set_priority(unsigned int irq, unsigned int prio);
int intc_irq_lookup(const char *chipname, intc_enum enum_id);
void intc_finalize(void);
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index bb47314c7179..0e501714d47f 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -562,6 +562,11 @@ extern void kfree_skb(struct sk_buff *skb);
extern void consume_skb(struct sk_buff *skb);
extern void __kfree_skb(struct sk_buff *skb);
extern struct kmem_cache *skbuff_head_cache;
+
+extern void kfree_skb_partial(struct sk_buff *skb, bool head_stolen);
+extern bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
+ bool *fragstolen, int *delta_truesize);
+
extern struct sk_buff *__alloc_skb(unsigned int size,
gfp_t priority, int fclone, int node);
extern struct sk_buff *build_skb(void *data, unsigned int frag_size);
@@ -1680,31 +1685,11 @@ static inline void __skb_queue_purge(struct sk_buff_head *list)
kfree_skb(skb);
}
-/**
- * __dev_alloc_skb - allocate an skbuff for receiving
- * @length: length to allocate
- * @gfp_mask: get_free_pages mask, passed to alloc_skb
- *
- * Allocate a new &sk_buff and assign it a usage count of one. The
- * buffer has unspecified headroom built in. Users should allocate
- * the headroom they think they need without accounting for the
- * built in space. The built in space is used for optimisations.
- *
- * %NULL is returned if there is no free memory.
- */
-static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
- gfp_t gfp_mask)
-{
- struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
- if (likely(skb))
- skb_reserve(skb, NET_SKB_PAD);
- return skb;
-}
-
-extern struct sk_buff *dev_alloc_skb(unsigned int length);
+extern void *netdev_alloc_frag(unsigned int fragsz);
extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
- unsigned int length, gfp_t gfp_mask);
+ unsigned int length,
+ gfp_t gfp_mask);
/**
* netdev_alloc_skb - allocate an skbuff for rx on a specific device
@@ -1720,11 +1705,25 @@ extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
* allocates memory it can be called from an interrupt.
*/
static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
- unsigned int length)
+ unsigned int length)
{
return __netdev_alloc_skb(dev, length, GFP_ATOMIC);
}
+/* legacy helper around __netdev_alloc_skb() */
+static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
+ gfp_t gfp_mask)
+{
+ return __netdev_alloc_skb(NULL, length, gfp_mask);
+}
+
+/* legacy helper around netdev_alloc_skb() */
+static inline struct sk_buff *dev_alloc_skb(unsigned int length)
+{
+ return netdev_alloc_skb(NULL, length);
+}
+
+
static inline struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev,
unsigned int length, gfp_t gfp)
{
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 10530d92c04b..717fb746c9a8 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -61,7 +61,7 @@ extern void smp_prepare_cpus(unsigned int max_cpus);
/*
* Bring a CPU up
*/
-extern int __cpu_up(unsigned int cpunum);
+extern int __cpu_up(unsigned int cpunum, struct task_struct *tidle);
/*
* Final polishing of CPUs
@@ -81,6 +81,8 @@ void __smp_call_function_single(int cpuid, struct call_single_data *data,
int smp_call_function_any(const struct cpumask *mask,
smp_call_func_t func, void *info, int wait);
+void kick_all_cpus_sync(void);
+
/*
* Generic and arch helpers
*/
@@ -192,6 +194,8 @@ smp_call_function_any(const struct cpumask *mask, smp_call_func_t func,
return smp_call_function_single(0, func, info, wait);
}
+static inline void kick_all_cpus_sync(void) { }
+
#endif /* !SMP */
/*
diff --git a/include/linux/spi/eeprom.h b/include/linux/spi/eeprom.h
index 306e7b1c69ed..403e007aef68 100644
--- a/include/linux/spi/eeprom.h
+++ b/include/linux/spi/eeprom.h
@@ -20,6 +20,16 @@ struct spi_eeprom {
#define EE_ADDR3 0x0004 /* 24 bit addrs */
#define EE_READONLY 0x0008 /* disallow writes */
+ /*
+ * Certain EEPROMS have a size that is larger than the number of address
+ * bytes would allow (e.g. like M95040 from ST that has 512 Byte size
+ * but uses only one address byte (A0 to A7) for addressing.) For
+ * the extra address bit (A8, A16 or A24) bit 3 of the instruction byte
+ * is used. This instruction bit is normally defined as don't care for
+ * other AT25 like chips.
+ */
+#define EE_INSTR_BIT3_IS_ADDR 0x0010
+
/* for exporting this chip's data to other kernel code */
void (*setup)(struct memory_accessor *mem, void *context);
void *context;
diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index d3d5fa54f25e..55a5c52cbb25 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -29,26 +29,35 @@
#include <linux/mutex.h>
#include <linux/rcupdate.h>
+#include <linux/workqueue.h>
struct srcu_struct_array {
- int c[2];
+ unsigned long c[2];
+ unsigned long seq[2];
+};
+
+struct rcu_batch {
+ struct rcu_head *head, **tail;
};
struct srcu_struct {
- int completed;
+ unsigned completed;
struct srcu_struct_array __percpu *per_cpu_ref;
- struct mutex mutex;
+ spinlock_t queue_lock; /* protect ->batch_queue, ->running */
+ bool running;
+ /* callbacks just queued */
+ struct rcu_batch batch_queue;
+ /* callbacks try to do the first check_zero */
+ struct rcu_batch batch_check0;
+ /* callbacks done with the first check_zero and the flip */
+ struct rcu_batch batch_check1;
+ struct rcu_batch batch_done;
+ struct delayed_work work;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
};
-#ifndef CONFIG_PREEMPT
-#define srcu_barrier() barrier()
-#else /* #ifndef CONFIG_PREEMPT */
-#define srcu_barrier()
-#endif /* #else #ifndef CONFIG_PREEMPT */
-
#ifdef CONFIG_DEBUG_LOCK_ALLOC
int __init_srcu_struct(struct srcu_struct *sp, const char *name,
@@ -67,12 +76,33 @@ int init_srcu_struct(struct srcu_struct *sp);
#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+/**
+ * call_srcu() - Queue a callback for invocation after an SRCU grace period
+ * @sp: srcu_struct in queue the callback
+ * @head: structure to be used for queueing the SRCU callback.
+ * @func: function to be invoked after the SRCU grace period
+ *
+ * The callback function will be invoked some time after a full SRCU
+ * grace period elapses, in other words after all pre-existing SRCU
+ * read-side critical sections have completed. However, the callback
+ * function might well execute concurrently with other SRCU read-side
+ * critical sections that started after call_srcu() was invoked. SRCU
+ * read-side critical sections are delimited by srcu_read_lock() and
+ * srcu_read_unlock(), and may be nested.
+ *
+ * The callback will be invoked from process context, but must nevertheless
+ * be fast and must not block.
+ */
+void call_srcu(struct srcu_struct *sp, struct rcu_head *head,
+ void (*func)(struct rcu_head *head));
+
void cleanup_srcu_struct(struct srcu_struct *sp);
int __srcu_read_lock(struct srcu_struct *sp) __acquires(sp);
void __srcu_read_unlock(struct srcu_struct *sp, int idx) __releases(sp);
void synchronize_srcu(struct srcu_struct *sp);
void synchronize_srcu_expedited(struct srcu_struct *sp);
long srcu_batches_completed(struct srcu_struct *sp);
+void srcu_barrier(struct srcu_struct *sp);
#ifdef CONFIG_DEBUG_LOCK_ALLOC
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index ac1c114c499d..cd83059fb592 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -356,8 +356,9 @@ extern int unregister_pm_notifier(struct notifier_block *nb);
extern bool events_check_enabled;
extern bool pm_wakeup_pending(void);
-extern bool pm_get_wakeup_count(unsigned int *count);
+extern bool pm_get_wakeup_count(unsigned int *count, bool block);
extern bool pm_save_wakeup_count(unsigned int count);
+extern void pm_wakep_autosleep_enabled(bool set);
static inline void lock_system_sleep(void)
{
@@ -407,6 +408,17 @@ static inline void unlock_system_sleep(void) {}
#endif /* !CONFIG_PM_SLEEP */
+#ifdef CONFIG_PM_AUTOSLEEP
+
+/* kernel/power/autosleep.c */
+void queue_up_suspend_work(void);
+
+#else /* !CONFIG_PM_AUTOSLEEP */
+
+static inline void queue_up_suspend_work(void) {}
+
+#endif /* !CONFIG_PM_AUTOSLEEP */
+
#ifdef CONFIG_ARCH_SAVE_PAGE_KEYS
/*
* The ARCH_SAVE_PAGE_KEYS functions can be used by an architecture
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 0010009b2f00..381f06db2fe5 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -27,6 +27,7 @@ struct attribute {
const char *name;
umode_t mode;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ bool ignore_lockdep:1;
struct lock_class_key *key;
struct lock_class_key skey;
#endif
@@ -80,6 +81,17 @@ struct attribute_group {
#define __ATTR_NULL { .attr = { .name = NULL } }
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#define __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) { \
+ .attr = {.name = __stringify(_name), .mode = _mode, \
+ .ignore_lockdep = true }, \
+ .show = _show, \
+ .store = _store, \
+}
+#else
+#define __ATTR_IGNORE_LOCKDEP __ATTR
+#endif
+
#define attr_name(_attr) (_attr).attr.name
struct file;
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index d9b42c5be088..4c5b63283377 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -426,7 +426,7 @@ struct tcp_sock {
struct sk_buff_head out_of_order_queue; /* Out of order segments go here */
- /* SACKs data, these 2 need to be together (see tcp_build_and_update_options) */
+ /* SACKs data, these 2 need to be together (see tcp_options_write) */
struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */
struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index 8d03f079688c..db78775eff3b 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -54,6 +54,12 @@ extern long do_no_restart_syscall(struct restart_block *parm);
#ifdef __KERNEL__
+#ifdef CONFIG_DEBUG_STACK_USAGE
+# define THREADINFO_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO)
+#else
+# define THREADINFO_GFP (GFP_KERNEL | __GFP_NOTRACK)
+#endif
+
/*
* flag set/clear/test wrappers
* - pass TIF_xxxx constants to these functions
diff --git a/include/linux/ti_wilink_st.h b/include/linux/ti_wilink_st.h
index 2ef4385da6bf..3ca0269dd0b5 100644
--- a/include/linux/ti_wilink_st.h
+++ b/include/linux/ti_wilink_st.h
@@ -25,6 +25,8 @@
#ifndef TI_WILINK_ST_H
#define TI_WILINK_ST_H
+#include <linux/skbuff.h>
+
/**
* enum proto-type - The protocol on WiLink chips which share a
* common physical interface like UART.
diff --git a/include/linux/topology.h b/include/linux/topology.h
index e26db031303b..e91cd43394df 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -70,7 +70,6 @@ int arch_update_cpu_topology(void);
* Below are the 3 major initializers used in building sched_domains:
* SD_SIBLING_INIT, for SMT domains
* SD_CPU_INIT, for SMP domains
- * SD_NODE_INIT, for NUMA domains
*
* Any architecture that cares to do any tuning to these values should do so
* by defining their own arch-specific initializer in include/asm/topology.h.
@@ -99,7 +98,6 @@ int arch_update_cpu_topology(void);
| 0*SD_BALANCE_WAKE \
| 1*SD_WAKE_AFFINE \
| 1*SD_SHARE_CPUPOWER \
- | 0*SD_POWERSAVINGS_BALANCE \
| 1*SD_SHARE_PKG_RESOURCES \
| 0*SD_SERIALIZE \
| 0*SD_PREFER_SIBLING \
@@ -135,8 +133,6 @@ int arch_update_cpu_topology(void);
| 0*SD_SHARE_CPUPOWER \
| 1*SD_SHARE_PKG_RESOURCES \
| 0*SD_SERIALIZE \
- | sd_balance_for_mc_power() \
- | sd_power_saving_flags() \
, \
.last_balance = jiffies, \
.balance_interval = 1, \
@@ -168,56 +164,18 @@ int arch_update_cpu_topology(void);
| 0*SD_SHARE_CPUPOWER \
| 0*SD_SHARE_PKG_RESOURCES \
| 0*SD_SERIALIZE \
- | sd_balance_for_package_power() \
- | sd_power_saving_flags() \
, \
.last_balance = jiffies, \
.balance_interval = 1, \
}
#endif
-/* sched_domains SD_ALLNODES_INIT for NUMA machines */
-#define SD_ALLNODES_INIT (struct sched_domain) { \
- .min_interval = 64, \
- .max_interval = 64*num_online_cpus(), \
- .busy_factor = 128, \
- .imbalance_pct = 133, \
- .cache_nice_tries = 1, \
- .busy_idx = 3, \
- .idle_idx = 3, \
- .flags = 1*SD_LOAD_BALANCE \
- | 1*SD_BALANCE_NEWIDLE \
- | 0*SD_BALANCE_EXEC \
- | 0*SD_BALANCE_FORK \
- | 0*SD_BALANCE_WAKE \
- | 0*SD_WAKE_AFFINE \
- | 0*SD_SHARE_CPUPOWER \
- | 0*SD_POWERSAVINGS_BALANCE \
- | 0*SD_SHARE_PKG_RESOURCES \
- | 1*SD_SERIALIZE \
- | 0*SD_PREFER_SIBLING \
- , \
- .last_balance = jiffies, \
- .balance_interval = 64, \
-}
-
-#ifndef SD_NODES_PER_DOMAIN
-#define SD_NODES_PER_DOMAIN 16
-#endif
-
#ifdef CONFIG_SCHED_BOOK
#ifndef SD_BOOK_INIT
#error Please define an appropriate SD_BOOK_INIT in include/asm/topology.h!!!
#endif
#endif /* CONFIG_SCHED_BOOK */
-#ifdef CONFIG_NUMA
-#ifndef SD_NODE_INIT
-#error Please define an appropriate SD_NODE_INIT in include/asm/topology.h!!!
-#endif
-
-#endif /* CONFIG_NUMA */
-
#ifdef CONFIG_USE_PERCPU_NUMA_NODE_ID
DECLARE_PER_CPU(int, numa_node);
@@ -239,7 +197,7 @@ static inline int cpu_to_node(int cpu)
#ifndef set_numa_node
static inline void set_numa_node(int node)
{
- percpu_write(numa_node, node);
+ this_cpu_write(numa_node, node);
}
#endif
@@ -274,7 +232,7 @@ DECLARE_PER_CPU(int, _numa_mem_);
#ifndef set_numa_mem
static inline void set_numa_mem(int node)
{
- percpu_write(_numa_mem_, node);
+ this_cpu_write(_numa_mem_, node);
}
#endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 9f47ab540f65..4990ef2b1fb7 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -268,6 +268,7 @@ struct tty_struct {
struct mutex ldisc_mutex;
struct tty_ldisc *ldisc;
+ struct mutex legacy_mutex;
struct mutex termios_mutex;
spinlock_t ctrl_lock;
/* Termios values are protected by the termios mutex */
@@ -605,8 +606,12 @@ extern long vt_compat_ioctl(struct tty_struct *tty,
/* tty_mutex.c */
/* functions for preparation of BKL removal */
-extern void __lockfunc tty_lock(void) __acquires(tty_lock);
-extern void __lockfunc tty_unlock(void) __releases(tty_lock);
+extern void __lockfunc tty_lock(struct tty_struct *tty);
+extern void __lockfunc tty_unlock(struct tty_struct *tty);
+extern void __lockfunc tty_lock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2);
+extern void __lockfunc tty_unlock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2);
/*
* this shall be called only from where BTM is held (like close)
@@ -621,9 +626,9 @@ extern void __lockfunc tty_unlock(void) __releases(tty_lock);
static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,
long timeout)
{
- tty_unlock(); /* tty->ops->close holds the BTM, drop it while waiting */
+ tty_unlock(tty); /* tty->ops->close holds the BTM, drop it while waiting */
tty_wait_until_sent(tty, timeout);
- tty_lock();
+ tty_lock(tty);
}
/*
@@ -638,16 +643,16 @@ static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,
*
* Do not use in new code.
*/
-#define wait_event_interruptible_tty(wq, condition) \
+#define wait_event_interruptible_tty(tty, wq, condition) \
({ \
int __ret = 0; \
if (!(condition)) { \
- __wait_event_interruptible_tty(wq, condition, __ret); \
+ __wait_event_interruptible_tty(tty, wq, condition, __ret); \
} \
__ret; \
})
-#define __wait_event_interruptible_tty(wq, condition, ret) \
+#define __wait_event_interruptible_tty(tty, wq, condition, ret) \
do { \
DEFINE_WAIT(__wait); \
\
@@ -656,9 +661,9 @@ do { \
if (condition) \
break; \
if (!signal_pending(current)) { \
- tty_unlock(); \
+ tty_unlock(tty); \
schedule(); \
- tty_lock(); \
+ tty_lock(tty); \
continue; \
} \
ret = -ERESTARTSYS; \
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index ff7dc08696a8..fb79dd8d1537 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -110,6 +110,7 @@
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/pps_kernel.h>
+#include <linux/wait.h>
struct tty_ldisc_ops {
int magic;
@@ -154,6 +155,7 @@ struct tty_ldisc_ops {
struct tty_ldisc {
struct tty_ldisc_ops *ops;
atomic_t users;
+ wait_queue_head_t wq_idle;
};
#define TTY_LDISC_MAGIC 0x5403
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 73b68d1f2cb0..dea39dc551d4 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -351,10 +351,6 @@ struct usb_bus {
int bandwidth_int_reqs; /* number of Interrupt requests */
int bandwidth_isoc_reqs; /* number of Isoc. requests */
-#ifdef CONFIG_USB_DEVICEFS
- struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */
-#endif
-
#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
struct mon_bus *mon_bus; /* non-null when associated */
int monitored; /* non-zero when monitored */
@@ -382,6 +378,45 @@ enum usb_device_removable {
USB_DEVICE_FIXED,
};
+/*
+ * USB 3.0 Link Power Management (LPM) parameters.
+ *
+ * PEL and SEL are USB 3.0 Link PM latencies for device-initiated LPM exit.
+ * MEL is the USB 3.0 Link PM latency for host-initiated LPM exit.
+ * All three are stored in nanoseconds.
+ */
+struct usb3_lpm_parameters {
+ /*
+ * Maximum exit latency (MEL) for the host to send a packet to the
+ * device (either a Ping for isoc endpoints, or a data packet for
+ * interrupt endpoints), the hubs to decode the packet, and for all hubs
+ * in the path to transition the links to U0.
+ */
+ unsigned int mel;
+ /*
+ * Maximum exit latency for a device-initiated LPM transition to bring
+ * all links into U0. Abbreviated as "PEL" in section 9.4.12 of the USB
+ * 3.0 spec, with no explanation of what "P" stands for. "Path"?
+ */
+ unsigned int pel;
+
+ /*
+ * The System Exit Latency (SEL) includes PEL, and three other
+ * latencies. After a device initiates a U0 transition, it will take
+ * some time from when the device sends the ERDY to when it will finally
+ * receive the data packet. Basically, SEL should be the worse-case
+ * latency from when a device starts initiating a U0 transition to when
+ * it will get data.
+ */
+ unsigned int sel;
+ /*
+ * The idle timeout value that is currently programmed into the parent
+ * hub for this device. When the timer counts to zero, the parent hub
+ * will initiate an LPM transition to either U1 or U2.
+ */
+ int timeout;
+};
+
/**
* struct usb_device - kernel's representation of a USB device
* @devnum: device number; address on a USB bus
@@ -439,6 +474,12 @@ enum usb_device_removable {
* specific data for the device.
* @slot_id: Slot ID assigned by xHCI
* @removable: Device can be physically removed from this port
+ * @u1_params: exit latencies for USB3 U1 LPM state, and hub-initiated timeout.
+ * @u2_params: exit latencies for USB3 U2 LPM state, and hub-initiated timeout.
+ * @lpm_disable_count: Ref count used by usb_disable_lpm() and usb_enable_lpm()
+ * to keep track of the number of functions that require USB 3.0 Link Power
+ * Management to be disabled for this usb_device. This count should only
+ * be manipulated by those functions, with the bandwidth_mutex is held.
*
* Notes:
* Usbcore drivers should not set usbdev->state directly. Instead use
@@ -485,6 +526,7 @@ struct usb_device {
unsigned lpm_capable:1;
unsigned usb2_hw_lpm_capable:1;
unsigned usb2_hw_lpm_enabled:1;
+ unsigned usb3_lpm_enabled:1;
int string_langid;
/* static strings from the device */
@@ -493,12 +535,6 @@ struct usb_device {
char *serial;
struct list_head filelist;
-#ifdef CONFIG_USB_DEVICE_CLASS
- struct device *usb_classdev;
-#endif
-#ifdef CONFIG_USB_DEVICEFS
- struct dentry *usbfs_dentry;
-#endif
int maxchild;
struct usb_device **children;
@@ -517,6 +553,10 @@ struct usb_device {
struct wusb_dev *wusb_dev;
int slot_id;
enum usb_device_removable removable;
+ struct usb3_lpm_parameters u1_params;
+ struct usb3_lpm_parameters u2_params;
+ unsigned lpm_disable_count;
+ unsigned hub_initiated_lpm_disable_count;
};
#define to_usb_device(d) container_of(d, struct usb_device, dev)
@@ -583,6 +623,12 @@ static inline void usb_mark_last_busy(struct usb_device *udev)
{ }
#endif
+extern int usb_disable_lpm(struct usb_device *udev);
+extern void usb_enable_lpm(struct usb_device *udev);
+/* Same as above, but these functions lock/unlock the bandwidth_mutex. */
+extern int usb_unlocked_disable_lpm(struct usb_device *udev);
+extern void usb_unlocked_enable_lpm(struct usb_device *udev);
+
/*-------------------------------------------------------------------------*/
/* for drivers using iso endpoints */
@@ -800,6 +846,8 @@ extern ssize_t usb_store_new_id(struct usb_dynids *dynids,
struct device_driver *driver,
const char *buf, size_t count);
+extern ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf);
+
/**
* struct usbdrv_wrap - wrapper for driver-model structure
* @driver: The driver-model core driver structure.
@@ -850,6 +898,9 @@ struct usbdrv_wrap {
* for interfaces bound to this driver.
* @soft_unbind: if set to 1, the USB core will not kill URBs and disable
* endpoints before calling the driver's disconnect method.
+ * @disable_hub_initiated_lpm: if set to 0, the USB core will not allow hubs
+ * to initiate lower power link state transitions when an idle timeout
+ * occurs. Device-initiated USB 3.0 link PM will still be allowed.
*
* USB interface drivers must provide a name, probe() and disconnect()
* methods, and an id_table. Other driver fields are optional.
@@ -890,6 +941,7 @@ struct usb_driver {
struct usbdrv_wrap drvwrap;
unsigned int no_dynamic_id:1;
unsigned int supports_autosuspend:1;
+ unsigned int disable_hub_initiated_lpm:1;
unsigned int soft_unbind:1;
};
#define to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver)
@@ -1379,6 +1431,7 @@ extern int usb_unlink_urb(struct urb *urb);
extern void usb_kill_urb(struct urb *urb);
extern void usb_poison_urb(struct urb *urb);
extern void usb_unpoison_urb(struct urb *urb);
+extern void usb_block_urb(struct urb *urb);
extern void usb_kill_anchored_urbs(struct usb_anchor *anchor);
extern void usb_poison_anchored_urbs(struct usb_anchor *anchor);
extern void usb_unpoison_anchored_urbs(struct usb_anchor *anchor);
@@ -1391,6 +1444,8 @@ extern struct urb *usb_get_from_anchor(struct usb_anchor *anchor);
extern void usb_scuttle_anchored_urbs(struct usb_anchor *anchor);
extern int usb_anchor_empty(struct usb_anchor *anchor);
+#define usb_unblock_urb usb_unpoison_urb
+
/**
* usb_urb_dir_in - check if an URB describes an IN transfer
* @urb: URB to be checked
@@ -1627,6 +1682,7 @@ static inline int usb_translate_errors(int error_code)
case 0:
case -ENOMEM:
case -ENODEV:
+ case -EOPNOTSUPP:
return error_code;
default:
return -EIO;
@@ -1652,9 +1708,6 @@ do { \
} while (0)
#endif
-#define err(format, arg...) \
- printk(KERN_ERR KBUILD_MODNAME ": " format "\n", ##arg)
-
/* debugfs stuff */
extern struct dentry *usb_debug_root;
diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h
index f1d26b6067f1..b6c2863b2c94 100644
--- a/include/linux/usb/ch11.h
+++ b/include/linux/usb/ch11.h
@@ -76,6 +76,8 @@
#define USB_PORT_FEAT_C_BH_PORT_RESET 29
#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30
+#define USB_PORT_LPM_TIMEOUT(p) (((p) & 0xff) << 8)
+
/* USB 3.0 hub remote wake mask bits, see table 10-14 */
#define USB_PORT_FEAT_REMOTE_WAKE_CONNECT (1 << 8)
#define USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT (1 << 9)
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index af21f3115919..d1d732c2838d 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -88,6 +88,8 @@
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
+#define USB_REQ_SET_SEL 0x30
+#define USB_REQ_SET_ISOCH_DELAY 0x31
#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */
#define USB_REQ_GET_ENCRYPTION 0x0E
@@ -390,6 +392,11 @@ struct usb_endpoint_descriptor {
#define USB_ENDPOINT_XFER_INT 3
#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80
+/* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */
+#define USB_ENDPOINT_INTRTYPE 0x30
+#define USB_ENDPOINT_INTR_PERIODIC (0 << 4)
+#define USB_ENDPOINT_INTR_NOTIFICATION (1 << 4)
+
#define USB_ENDPOINT_SYNCTYPE 0x0c
#define USB_ENDPOINT_SYNC_NONE (0 << 2)
#define USB_ENDPOINT_SYNC_ASYNC (1 << 2)
@@ -592,6 +599,12 @@ static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd)
return __le16_to_cpu(epd->wMaxPacketSize);
}
+static inline int usb_endpoint_interrupt_type(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return epd->bmAttributes & USB_ENDPOINT_INTRTYPE;
+}
+
/*-------------------------------------------------------------------------*/
/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */
@@ -933,6 +946,51 @@ enum usb_device_state {
*/
};
+enum usb3_link_state {
+ USB3_LPM_U0 = 0,
+ USB3_LPM_U1,
+ USB3_LPM_U2,
+ USB3_LPM_U3
+};
+
+/*
+ * A U1 timeout of 0x0 means the parent hub will reject any transitions to U1.
+ * 0xff means the parent hub will accept transitions to U1, but will not
+ * initiate a transition.
+ *
+ * A U1 timeout of 0x1 to 0x7F also causes the hub to initiate a transition to
+ * U1 after that many microseconds. Timeouts of 0x80 to 0xFE are reserved
+ * values.
+ *
+ * A U2 timeout of 0x0 means the parent hub will reject any transitions to U2.
+ * 0xff means the parent hub will accept transitions to U2, but will not
+ * initiate a transition.
+ *
+ * A U2 timeout of 0x1 to 0xFE also causes the hub to initiate a transition to
+ * U2 after N*256 microseconds. Therefore a U2 timeout value of 0x1 means a U2
+ * idle timer of 256 microseconds, 0x2 means 512 microseconds, 0xFE means
+ * 65.024ms.
+ */
+#define USB3_LPM_DISABLED 0x0
+#define USB3_LPM_U1_MAX_TIMEOUT 0x7F
+#define USB3_LPM_U2_MAX_TIMEOUT 0xFE
+#define USB3_LPM_DEVICE_INITIATED 0xFF
+
+struct usb_set_sel_req {
+ __u8 u1_sel;
+ __u8 u1_pel;
+ __le16 u2_sel;
+ __le16 u2_pel;
+} __attribute__ ((packed));
+
+/*
+ * The Set System Exit Latency control transfer provides one byte each for
+ * U1 SEL and U1 PEL, so the max exit latency is 0xFF. U2 SEL and U2 PEL each
+ * are two bytes long.
+ */
+#define USB3_LPM_MAX_U1_SEL_PEL 0xFF
+#define USB3_LPM_MAX_U2_SEL_PEL 0xFFFF
+
/*-------------------------------------------------------------------------*/
/*
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
new file mode 100644
index 000000000000..edb90d6cfd12
--- /dev/null
+++ b/include/linux/usb/chipidea.h
@@ -0,0 +1,28 @@
+/*
+ * Platform data for the chipidea USB dual role controller
+ */
+
+#ifndef __LINUX_USB_CHIPIDEA_H
+#define __LINUX_USB_CHIPIDEA_H
+
+struct ci13xxx;
+struct ci13xxx_udc_driver {
+ const char *name;
+ /* offset of the capability registers */
+ uintptr_t capoffset;
+ unsigned power_budget;
+ unsigned long flags;
+#define CI13XXX_REGS_SHARED BIT(0)
+#define CI13XXX_REQUIRE_TRANSCEIVER BIT(1)
+#define CI13XXX_PULLUP_ON_VBUS BIT(2)
+#define CI13XXX_DISABLE_STREAMING BIT(3)
+
+#define CI13XXX_CONTROLLER_RESET_EVENT 0
+#define CI13XXX_CONTROLLER_STOPPED_EVENT 1
+ void (*notify_event) (struct ci13xxx *udc, unsigned event);
+};
+
+/* Default offset of capability registers */
+#define DEF_CAPOFFSET 0x100
+
+#endif
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index a316fba73518..9d8c3b634493 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -242,6 +242,9 @@ int usb_add_config(struct usb_composite_dev *,
struct usb_configuration *,
int (*)(struct usb_configuration *));
+void usb_remove_config(struct usb_composite_dev *,
+ struct usb_configuration *);
+
/**
* struct usb_composite_driver - groups configurations into a gadget
* @name: For diagnostics, identifies the driver.
@@ -250,6 +253,8 @@ int usb_add_config(struct usb_composite_dev *,
* @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is
* not set. If NULL a default "<system> <release> with <udc>" value
* will be used.
+ * @iSerialNumber: Used as iSerialNumber override if @dev->iSerialNumber is
+ * not set.
* @dev: Template descriptor for the device, including default device
* identifiers.
* @strings: tables of strings, keyed by identifiers assigned during bind()
@@ -280,6 +285,7 @@ struct usb_composite_driver {
const char *name;
const char *iProduct;
const char *iManufacturer;
+ const char *iSerialNumber;
const struct usb_device_descriptor *dev;
struct usb_gadget_strings **strings;
enum usb_device_speed max_speed;
diff --git a/include/linux/usb/functionfs.h b/include/linux/usb/functionfs.h
index 7587ef934ba8..a843d0851364 100644
--- a/include/linux/usb/functionfs.h
+++ b/include/linux/usb/functionfs.h
@@ -190,8 +190,10 @@ static int functionfs_ready_callback(struct ffs_data *ffs)
__attribute__((warn_unused_result, nonnull));
static void functionfs_closed_callback(struct ffs_data *ffs)
__attribute__((nonnull));
-static int functionfs_check_dev_callback(const char *dev_name)
+static void *functionfs_acquire_dev_callback(const char *dev_name)
__attribute__((warn_unused_result, nonnull));
+static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
+ __attribute__((nonnull));
#endif
diff --git a/include/linux/usb/gpio_vbus.h b/include/linux/usb/gpio_vbus.h
index d9f03ccc2d60..837bba604a0b 100644
--- a/include/linux/usb/gpio_vbus.h
+++ b/include/linux/usb/gpio_vbus.h
@@ -17,6 +17,7 @@
* @gpio_pullup: optional D+ or D- pullup GPIO (else negative/invalid)
* @gpio_vbus_inverted: true if gpio_vbus is active low
* @gpio_pullup_inverted: true if gpio_pullup is active low
+ * @wakeup: configure gpio_vbus as a wake-up source
*
* The VBUS sensing GPIO should have a pulldown, which will normally be
* part of a resistor ladder turning a 4.0V-5.25V level on VBUS into a
@@ -27,4 +28,5 @@ struct gpio_vbus_mach_info {
int gpio_pullup;
bool gpio_vbus_inverted;
bool gpio_pullup_inverted;
+ bool wakeup;
};
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index d28cc78a38e4..7f855d50cdf5 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -344,6 +344,15 @@ struct hc_driver {
*/
int (*update_device)(struct usb_hcd *, struct usb_device *);
int (*set_usb2_hw_lpm)(struct usb_hcd *, struct usb_device *, int);
+ /* USB 3.0 Link Power Management */
+ /* Returns the USB3 hub-encoded value for the U1/U2 timeout. */
+ int (*enable_usb3_lpm_timeout)(struct usb_hcd *,
+ struct usb_device *, enum usb3_link_state state);
+ /* The xHCI host controller can still fail the command to
+ * disable the LPM timeouts, so this can return an error code.
+ */
+ int (*disable_usb3_lpm_timeout)(struct usb_hcd *,
+ struct usb_device *, enum usb3_link_state state);
};
extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
@@ -584,29 +593,6 @@ static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
}
#endif /* CONFIG_USB_SUSPEND */
-
-/*
- * USB device fs stuff
- */
-
-#ifdef CONFIG_USB_DEVICEFS
-
-/*
- * these are expected to be called from the USB core/hub thread
- * with the kernel lock held
- */
-extern void usbfs_update_special(void);
-extern int usbfs_init(void);
-extern void usbfs_cleanup(void);
-
-#else /* CONFIG_USB_DEVICEFS */
-
-static inline void usbfs_update_special(void) {}
-static inline int usbfs_init(void) { return 0; }
-static inline void usbfs_cleanup(void) { }
-
-#endif /* CONFIG_USB_DEVICEFS */
-
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
diff --git a/include/linux/usb/isp1301.h b/include/linux/usb/isp1301.h
new file mode 100644
index 000000000000..d3a851c28b6a
--- /dev/null
+++ b/include/linux/usb/isp1301.h
@@ -0,0 +1,80 @@
+/*
+ * NXP ISP1301 USB transceiver driver
+ *
+ * Copyright (C) 2012 Roland Stigge <stigge@antcom.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __LINUX_USB_ISP1301_H
+#define __LINUX_USB_ISP1301_H
+
+#include <linux/of.h>
+
+/* I2C Register definitions: */
+
+#define ISP1301_I2C_MODE_CONTROL_1 0x04 /* u8 read, set, +1 clear */
+
+#define MC1_SPEED_REG (1 << 0)
+#define MC1_SUSPEND_REG (1 << 1)
+#define MC1_DAT_SE0 (1 << 2)
+#define MC1_TRANSPARENT (1 << 3)
+#define MC1_BDIS_ACON_EN (1 << 4)
+#define MC1_OE_INT_EN (1 << 5)
+#define MC1_UART_EN (1 << 6)
+#define MC1_MASK 0x7f
+
+#define ISP1301_I2C_MODE_CONTROL_2 0x12 /* u8 read, set, +1 clear */
+
+#define MC2_GLOBAL_PWR_DN (1 << 0)
+#define MC2_SPD_SUSP_CTRL (1 << 1)
+#define MC2_BI_DI (1 << 2)
+#define MC2_TRANSP_BDIR0 (1 << 3)
+#define MC2_TRANSP_BDIR1 (1 << 4)
+#define MC2_AUDIO_EN (1 << 5)
+#define MC2_PSW_EN (1 << 6)
+#define MC2_EN2V7 (1 << 7)
+
+#define ISP1301_I2C_OTG_CONTROL_1 0x06 /* u8 read, set, +1 clear */
+
+#define OTG1_DP_PULLUP (1 << 0)
+#define OTG1_DM_PULLUP (1 << 1)
+#define OTG1_DP_PULLDOWN (1 << 2)
+#define OTG1_DM_PULLDOWN (1 << 3)
+#define OTG1_ID_PULLDOWN (1 << 4)
+#define OTG1_VBUS_DRV (1 << 5)
+#define OTG1_VBUS_DISCHRG (1 << 6)
+#define OTG1_VBUS_CHRG (1 << 7)
+
+#define ISP1301_I2C_OTG_CONTROL_2 0x10 /* u8 readonly */
+
+#define OTG_B_SESS_END (1 << 6)
+#define OTG_B_SESS_VLD (1 << 7)
+
+#define ISP1301_I2C_INTERRUPT_SOURCE 0x8
+#define ISP1301_I2C_INTERRUPT_LATCH 0xA
+#define ISP1301_I2C_INTERRUPT_FALLING 0xC
+#define ISP1301_I2C_INTERRUPT_RISING 0xE
+
+#define INT_VBUS_VLD (1 << 0)
+#define INT_SESS_VLD (1 << 1)
+#define INT_DP_HI (1 << 2)
+#define INT_ID_GND (1 << 3)
+#define INT_DM_HI (1 << 4)
+#define INT_ID_FLOAT (1 << 5)
+#define INT_BDIS_ACON (1 << 6)
+#define INT_CR_INT (1 << 7)
+
+#define ISP1301_I2C_REG_CLEAR_ADDR 1 /* Register Address Modifier */
+
+struct i2c_client *isp1301_get_client(struct device_node *node);
+
+#endif /* __LINUX_USB_ISP1301_H */
diff --git a/include/linux/usb/langwell_udc.h b/include/linux/usb/langwell_udc.h
deleted file mode 100644
index 2d2d1bbad9d2..000000000000
--- a/include/linux/usb/langwell_udc.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Intel Langwell USB Device Controller driver
- * Copyright (C) 2008-2009, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __LANGWELL_UDC_H
-#define __LANGWELL_UDC_H
-
-
-/* MACRO defines */
-#define CAP_REG_OFFSET 0x0
-#define OP_REG_OFFSET 0x28
-
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
-
-#define DQH_ALIGNMENT 2048
-#define DTD_ALIGNMENT 64
-#define DMA_BOUNDARY 4096
-
-#define EP0_MAX_PKT_SIZE 64
-#define EP_DIR_IN 1
-#define EP_DIR_OUT 0
-
-#define FLUSH_TIMEOUT 1000
-#define RESET_TIMEOUT 1000
-#define SETUPSTAT_TIMEOUT 100
-#define PRIME_TIMEOUT 100
-
-
-/* device memory space registers */
-
-/* Capability Registers, BAR0 + CAP_REG_OFFSET */
-struct langwell_cap_regs {
- /* offset: 0x0 */
- u8 caplength; /* offset of Operational Register */
- u8 _reserved3;
- u16 hciversion; /* H: BCD encoding of host version */
- u32 hcsparams; /* H: host port steering logic capability */
- u32 hccparams; /* H: host multiple mode control capability */
-#define HCC_LEN BIT(17) /* Link power management (LPM) capability */
- u8 _reserved4[0x20-0xc];
- /* offset: 0x20 */
- u16 dciversion; /* BCD encoding of device version */
- u8 _reserved5[0x24-0x22];
- u32 dccparams; /* overall device controller capability */
-#define HOSTCAP BIT(8) /* host capable */
-#define DEVCAP BIT(7) /* device capable */
-#define DEN(d) \
- (((d)>>0)&0x1f) /* bits 4:0, device endpoint number */
-} __attribute__ ((packed));
-
-
-/* Operational Registers, BAR0 + OP_REG_OFFSET */
-struct langwell_op_regs {
- /* offset: 0x28 */
- u32 extsts;
-#define EXTS_TI1 BIT(4) /* general purpose timer interrupt 1 */
-#define EXTS_TI1TI0 BIT(3) /* general purpose timer interrupt 0 */
-#define EXTS_TI1UPI BIT(2) /* USB host periodic interrupt */
-#define EXTS_TI1UAI BIT(1) /* USB host asynchronous interrupt */
-#define EXTS_TI1NAKI BIT(0) /* NAK interrupt */
- u32 extintr;
-#define EXTI_TIE1 BIT(4) /* general purpose timer interrupt enable 1 */
-#define EXTI_TIE0 BIT(3) /* general purpose timer interrupt enable 0 */
-#define EXTI_UPIE BIT(2) /* USB host periodic interrupt enable */
-#define EXTI_UAIE BIT(1) /* USB host asynchronous interrupt enable */
-#define EXTI_NAKE BIT(0) /* NAK interrupt enable */
- /* offset: 0x30 */
- u32 usbcmd;
-#define CMD_HIRD(u) \
- (((u)>>24)&0xf) /* bits 27:24, host init resume duration */
-#define CMD_ITC(u) \
- (((u)>>16)&0xff) /* bits 23:16, interrupt threshold control */
-#define CMD_PPE BIT(15) /* per-port change events enable */
-#define CMD_ATDTW BIT(14) /* add dTD tripwire */
-#define CMD_SUTW BIT(13) /* setup tripwire */
-#define CMD_ASPE BIT(11) /* asynchronous schedule park mode enable */
-#define CMD_FS2 BIT(10) /* frame list size */
-#define CMD_ASP1 BIT(9) /* asynchronous schedule park mode count */
-#define CMD_ASP0 BIT(8)
-#define CMD_LR BIT(7) /* light host/device controller reset */
-#define CMD_IAA BIT(6) /* interrupt on async advance doorbell */
-#define CMD_ASE BIT(5) /* asynchronous schedule enable */
-#define CMD_PSE BIT(4) /* periodic schedule enable */
-#define CMD_FS1 BIT(3)
-#define CMD_FS0 BIT(2)
-#define CMD_RST BIT(1) /* controller reset */
-#define CMD_RUNSTOP BIT(0) /* run/stop */
- u32 usbsts;
-#define STS_PPCI(u) \
- (((u)>>16)&0xffff) /* bits 31:16, port-n change detect */
-#define STS_AS BIT(15) /* asynchronous schedule status */
-#define STS_PS BIT(14) /* periodic schedule status */
-#define STS_RCL BIT(13) /* reclamation */
-#define STS_HCH BIT(12) /* HC halted */
-#define STS_ULPII BIT(10) /* ULPI interrupt */
-#define STS_SLI BIT(8) /* DC suspend */
-#define STS_SRI BIT(7) /* SOF received */
-#define STS_URI BIT(6) /* USB reset received */
-#define STS_AAI BIT(5) /* interrupt on async advance */
-#define STS_SEI BIT(4) /* system error */
-#define STS_FRI BIT(3) /* frame list rollover */
-#define STS_PCI BIT(2) /* port change detect */
-#define STS_UEI BIT(1) /* USB error interrupt */
-#define STS_UI BIT(0) /* USB interrupt */
- u32 usbintr;
-/* bits 31:16, per-port interrupt enable */
-#define INTR_PPCE(u) (((u)>>16)&0xffff)
-#define INTR_ULPIE BIT(10) /* ULPI enable */
-#define INTR_SLE BIT(8) /* DC sleep/suspend enable */
-#define INTR_SRE BIT(7) /* SOF received enable */
-#define INTR_URE BIT(6) /* USB reset enable */
-#define INTR_AAE BIT(5) /* interrupt on async advance enable */
-#define INTR_SEE BIT(4) /* system error enable */
-#define INTR_FRE BIT(3) /* frame list rollover enable */
-#define INTR_PCE BIT(2) /* port change detect enable */
-#define INTR_UEE BIT(1) /* USB error interrupt enable */
-#define INTR_UE BIT(0) /* USB interrupt enable */
- u32 frindex; /* frame index */
-#define FRINDEX_MASK (0x3fff << 0)
- u32 ctrldssegment; /* not used */
- u32 deviceaddr;
-#define USBADR_SHIFT 25
-#define USBADR(d) \
- (((d)>>25)&0x7f) /* bits 31:25, device address */
-#define USBADR_MASK (0x7f << 25)
-#define USBADRA BIT(24) /* device address advance */
- u32 endpointlistaddr;/* endpoint list top memory address */
-/* bits 31:11, endpoint list pointer */
-#define EPBASE(d) (((d)>>11)&0x1fffff)
-#define ENDPOINTLISTADDR_MASK (0x1fffff << 11)
- u32 ttctrl; /* H: TT operatin, not used */
- /* offset: 0x50 */
- u32 burstsize; /* burst size of data movement */
-#define TXPBURST(b) \
- (((b)>>8)&0xff) /* bits 15:8, TX burst length */
-#define RXPBURST(b) \
- (((b)>>0)&0xff) /* bits 7:0, RX burst length */
- u32 txfilltuning; /* TX tuning */
- u32 txttfilltuning; /* H: TX TT tuning */
- u32 ic_usb; /* control the IC_USB FS/LS transceiver */
- /* offset: 0x60 */
- u32 ulpi_viewport; /* indirect access to ULPI PHY */
-#define ULPIWU BIT(31) /* ULPI wakeup */
-#define ULPIRUN BIT(30) /* ULPI read/write run */
-#define ULPIRW BIT(29) /* ULPI read/write control */
-#define ULPISS BIT(27) /* ULPI sync state */
-#define ULPIPORT(u) \
- (((u)>>24)&7) /* bits 26:24, ULPI port number */
-#define ULPIADDR(u) \
- (((u)>>16)&0xff) /* bits 23:16, ULPI data address */
-#define ULPIDATRD(u) \
- (((u)>>8)&0xff) /* bits 15:8, ULPI data read */
-#define ULPIDATWR(u) \
- (((u)>>0)&0xff) /* bits 7:0, ULPI date write */
- u8 _reserved6[0x70-0x64];
- /* offset: 0x70 */
- u32 configflag; /* H: not used */
- u32 portsc1; /* port status */
-#define DA(p) \
- (((p)>>25)&0x7f) /* bits 31:25, device address */
-#define PORTS_SSTS (BIT(24) | BIT(23)) /* suspend status */
-#define PORTS_WKOC BIT(22) /* wake on over-current enable */
-#define PORTS_WKDS BIT(21) /* wake on disconnect enable */
-#define PORTS_WKCN BIT(20) /* wake on connect enable */
-#define PORTS_PTC(p) (((p)>>16)&0xf) /* bits 19:16, port test control */
-#define PORTS_PIC (BIT(15) | BIT(14)) /* port indicator control */
-#define PORTS_PO BIT(13) /* port owner */
-#define PORTS_PP BIT(12) /* port power */
-#define PORTS_LS (BIT(11) | BIT(10)) /* line status */
-#define PORTS_SLP BIT(9) /* suspend using L1 */
-#define PORTS_PR BIT(8) /* port reset */
-#define PORTS_SUSP BIT(7) /* suspend */
-#define PORTS_FPR BIT(6) /* force port resume */
-#define PORTS_OCC BIT(5) /* over-current change */
-#define PORTS_OCA BIT(4) /* over-current active */
-#define PORTS_PEC BIT(3) /* port enable/disable change */
-#define PORTS_PE BIT(2) /* port enable/disable */
-#define PORTS_CSC BIT(1) /* connect status change */
-#define PORTS_CCS BIT(0) /* current connect status */
- u8 _reserved7[0xb4-0x78];
- /* offset: 0xb4 */
- u32 devlc; /* control LPM and each USB port behavior */
-/* bits 31:29, parallel transceiver select */
-#define LPM_PTS(d) (((d)>>29)&7)
-#define LPM_STS BIT(28) /* serial transceiver select */
-#define LPM_PTW BIT(27) /* parallel transceiver width */
-#define LPM_PSPD(d) (((d)>>25)&3) /* bits 26:25, port speed */
-#define LPM_PSPD_MASK (BIT(26) | BIT(25))
-#define LPM_SPEED_FULL 0
-#define LPM_SPEED_LOW 1
-#define LPM_SPEED_HIGH 2
-#define LPM_SRT BIT(24) /* shorten reset time */
-#define LPM_PFSC BIT(23) /* port force full speed connect */
-#define LPM_PHCD BIT(22) /* PHY low power suspend clock disable */
-#define LPM_STL BIT(16) /* STALL reply to LPM token */
-#define LPM_BA(d) \
- (((d)>>1)&0x7ff) /* bits 11:1, BmAttributes */
-#define LPM_NYT_ACK BIT(0) /* NYET/ACK reply to LPM token */
- u8 _reserved8[0xf4-0xb8];
- /* offset: 0xf4 */
- u32 otgsc; /* On-The-Go status and control */
-#define OTGSC_DPIE BIT(30) /* data pulse interrupt enable */
-#define OTGSC_MSE BIT(29) /* 1 ms timer interrupt enable */
-#define OTGSC_BSEIE BIT(28) /* B session end interrupt enable */
-#define OTGSC_BSVIE BIT(27) /* B session valid interrupt enable */
-#define OTGSC_ASVIE BIT(26) /* A session valid interrupt enable */
-#define OTGSC_AVVIE BIT(25) /* A VBUS valid interrupt enable */
-#define OTGSC_IDIE BIT(24) /* USB ID interrupt enable */
-#define OTGSC_DPIS BIT(22) /* data pulse interrupt status */
-#define OTGSC_MSS BIT(21) /* 1 ms timer interrupt status */
-#define OTGSC_BSEIS BIT(20) /* B session end interrupt status */
-#define OTGSC_BSVIS BIT(19) /* B session valid interrupt status */
-#define OTGSC_ASVIS BIT(18) /* A session valid interrupt status */
-#define OTGSC_AVVIS BIT(17) /* A VBUS valid interrupt status */
-#define OTGSC_IDIS BIT(16) /* USB ID interrupt status */
-#define OTGSC_DPS BIT(14) /* data bus pulsing status */
-#define OTGSC_MST BIT(13) /* 1 ms timer toggle */
-#define OTGSC_BSE BIT(12) /* B session end */
-#define OTGSC_BSV BIT(11) /* B session valid */
-#define OTGSC_ASV BIT(10) /* A session valid */
-#define OTGSC_AVV BIT(9) /* A VBUS valid */
-#define OTGSC_USBID BIT(8) /* USB ID */
-#define OTGSC_HABA BIT(7) /* hw assist B-disconnect to A-connect */
-#define OTGSC_HADP BIT(6) /* hw assist data pulse */
-#define OTGSC_IDPU BIT(5) /* ID pullup */
-#define OTGSC_DP BIT(4) /* data pulsing */
-#define OTGSC_OT BIT(3) /* OTG termination */
-#define OTGSC_HAAR BIT(2) /* hw assist auto reset */
-#define OTGSC_VC BIT(1) /* VBUS charge */
-#define OTGSC_VD BIT(0) /* VBUS discharge */
- u32 usbmode;
-#define MODE_VBPS BIT(5) /* R/W VBUS power select */
-#define MODE_SDIS BIT(4) /* R/W stream disable mode */
-#define MODE_SLOM BIT(3) /* R/W setup lockout mode */
-#define MODE_ENSE BIT(2) /* endian select */
-#define MODE_CM(u) (((u)>>0)&3) /* bits 1:0, controller mode */
-#define MODE_IDLE 0
-#define MODE_DEVICE 2
-#define MODE_HOST 3
- u8 _reserved9[0x100-0xfc];
- /* offset: 0x100 */
- u32 endptnak;
-#define EPTN(e) \
- (((e)>>16)&0xffff) /* bits 31:16, TX endpoint NAK */
-#define EPRN(e) \
- (((e)>>0)&0xffff) /* bits 15:0, RX endpoint NAK */
- u32 endptnaken;
-#define EPTNE(e) \
- (((e)>>16)&0xffff) /* bits 31:16, TX endpoint NAK enable */
-#define EPRNE(e) \
- (((e)>>0)&0xffff) /* bits 15:0, RX endpoint NAK enable */
- u32 endptsetupstat;
-#define SETUPSTAT_MASK (0xffff << 0) /* bits 15:0 */
-#define EP0SETUPSTAT_MASK 1
- u32 endptprime;
-/* bits 31:16, prime endpoint transmit buffer */
-#define PETB(e) (((e)>>16)&0xffff)
-/* bits 15:0, prime endpoint receive buffer */
-#define PERB(e) (((e)>>0)&0xffff)
- /* offset: 0x110 */
- u32 endptflush;
-/* bits 31:16, flush endpoint transmit buffer */
-#define FETB(e) (((e)>>16)&0xffff)
-/* bits 15:0, flush endpoint receive buffer */
-#define FERB(e) (((e)>>0)&0xffff)
- u32 endptstat;
-/* bits 31:16, endpoint transmit buffer ready */
-#define ETBR(e) (((e)>>16)&0xffff)
-/* bits 15:0, endpoint receive buffer ready */
-#define ERBR(e) (((e)>>0)&0xffff)
- u32 endptcomplete;
-/* bits 31:16, endpoint transmit complete event */
-#define ETCE(e) (((e)>>16)&0xffff)
-/* bits 15:0, endpoint receive complete event */
-#define ERCE(e) (((e)>>0)&0xffff)
- /* offset: 0x11c */
- u32 endptctrl[16];
-#define EPCTRL_TXE BIT(23) /* TX endpoint enable */
-#define EPCTRL_TXR BIT(22) /* TX data toggle reset */
-#define EPCTRL_TXI BIT(21) /* TX data toggle inhibit */
-#define EPCTRL_TXT(e) (((e)>>18)&3) /* bits 19:18, TX endpoint type */
-#define EPCTRL_TXT_SHIFT 18
-#define EPCTRL_TXD BIT(17) /* TX endpoint data source */
-#define EPCTRL_TXS BIT(16) /* TX endpoint STALL */
-#define EPCTRL_RXE BIT(7) /* RX endpoint enable */
-#define EPCTRL_RXR BIT(6) /* RX data toggle reset */
-#define EPCTRL_RXI BIT(5) /* RX data toggle inhibit */
-#define EPCTRL_RXT(e) (((e)>>2)&3) /* bits 3:2, RX endpoint type */
-#define EPCTRL_RXT_SHIFT 2 /* bits 19:18, TX endpoint type */
-#define EPCTRL_RXD BIT(1) /* RX endpoint data sink */
-#define EPCTRL_RXS BIT(0) /* RX endpoint STALL */
-} __attribute__ ((packed));
-
-#endif /* __LANGWELL_UDC_H */
-
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 474283888233..86c0b451745d 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -1,7 +1,7 @@
/*
* USB Serial Converter stuff
*
- * Copyright (C) 1999 - 2005
+ * Copyright (C) 1999 - 2012
* Greg Kroah-Hartman (greg@kroah.com)
*
* This program is free software; you can redistribute it and/or modify
@@ -249,6 +249,7 @@ struct usb_serial_driver {
int (*suspend)(struct usb_serial *serial, pm_message_t message);
int (*resume)(struct usb_serial *serial);
+ int (*reset_resume)(struct usb_serial *serial);
/* serial function calls */
/* Called by console and by the tty layer */
@@ -292,16 +293,11 @@ struct usb_serial_driver {
#define to_usb_serial_driver(d) \
container_of(d, struct usb_serial_driver, driver)
-extern int usb_serial_register_drivers(struct usb_driver *udriver,
- struct usb_serial_driver * const serial_drivers[]);
-extern void usb_serial_deregister_drivers(struct usb_driver *udriver,
- struct usb_serial_driver * const serial_drivers[]);
+extern int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[],
+ const char *name, const struct usb_device_id *id_table);
+extern void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_drivers[]);
extern void usb_serial_port_softint(struct usb_serial_port *port);
-extern int usb_serial_probe(struct usb_interface *iface,
- const struct usb_device_id *id);
-extern void usb_serial_disconnect(struct usb_interface *iface);
-
extern int usb_serial_suspend(struct usb_interface *intf, pm_message_t message);
extern int usb_serial_resume(struct usb_interface *intf);
@@ -400,8 +396,8 @@ do { \
/*
* module_usb_serial_driver() - Helper macro for registering a USB Serial driver
- * @__usb_driver: usb_driver struct to register
* @__serial_drivers: list of usb_serial drivers to register
+ * @__ids: all device ids that @__serial_drivers bind to
*
* Helper macro for USB serial drivers which do not do anything special
* in module init/exit. This eliminates a lot of boilerplate. Each
@@ -409,9 +405,21 @@ do { \
* module_init() and module_exit()
*
*/
-#define module_usb_serial_driver(__usb_driver, __serial_drivers) \
- module_driver(__usb_driver, usb_serial_register_drivers, \
- usb_serial_deregister_drivers, __serial_drivers)
+#define usb_serial_module_driver(__name, __serial_drivers, __ids) \
+static int __init usb_serial_module_init(void) \
+{ \
+ return usb_serial_register_drivers(__serial_drivers, \
+ __name, __ids); \
+} \
+module_init(usb_serial_module_init); \
+static void __exit usb_serial_module_exit(void) \
+{ \
+ usb_serial_deregister_drivers(__serial_drivers); \
+} \
+module_exit(usb_serial_module_exit);
+
+#define module_usb_serial_driver(__serial_drivers, __ids) \
+ usb_serial_module_driver(KBUILD_MODNAME, __serial_drivers, __ids)
#endif /* __LINUX_USB_SERIAL_H */
diff --git a/include/linux/uuid.h b/include/linux/uuid.h
index 5b7efbfcee4e..f86c37bfd4a0 100644
--- a/include/linux/uuid.h
+++ b/include/linux/uuid.h
@@ -54,6 +54,8 @@ typedef struct {
UUID_BE(0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00)
+#ifdef __KERNEL__
+
static inline int uuid_le_cmp(const uuid_le u1, const uuid_le u2)
{
return memcmp(&u1, &u2, sizeof(uuid_le));
@@ -67,4 +69,6 @@ static inline int uuid_be_cmp(const uuid_be u1, const uuid_be u2)
extern void uuid_le_gen(uuid_le *u);
extern void uuid_be_gen(uuid_be *u);
+#endif /* __KERNEL__ */
+
#endif
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 7323a3390206..fc457f452f64 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -74,15 +74,6 @@
* @set_status: write the status byte
* vdev: the virtio_device
* status: the new status byte
- * @request_vqs: request the specified number of virtqueues
- * vdev: the virtio_device
- * max_vqs: the max number of virtqueues we want
- * If supplied, must call before any virtqueues are instantiated.
- * To modify the max number of virtqueues after request_vqs has been
- * called, call free_vqs and then request_vqs with a new value.
- * @free_vqs: cleanup resources allocated by request_vqs
- * vdev: the virtio_device
- * If supplied, must call after all virtqueues have been deleted.
* @reset: reset the device
* vdev: the virtio device
* After this, status and feature negotiation must be done again
@@ -156,7 +147,7 @@ static inline bool virtio_has_feature(const struct virtio_device *vdev,
* @vdev: the virtio device
* @fbit: the feature bit
* @offset: the type to search for.
- * @val: a pointer to the value to fill in.
+ * @v: a pointer to the value to fill in.
*
* The return value is -ENOENT if the feature doesn't exist. Otherwise
* the config value is copied into whatever is pointed to by v. */
diff --git a/drivers/staging/vme/vme.h b/include/linux/vme.h
index c9d65bf14cec..c9d65bf14cec 100644
--- a/drivers/staging/vme/vme.h
+++ b/include/linux/vme.h
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index e33d77f15bda..50ae7d0c279e 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -70,7 +70,6 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list);
int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list);
int con_set_default_unimap(struct vc_data *vc);
void con_free_unimap(struct vc_data *vc);
-void con_protect_unimap(struct vc_data *vc, int rdonly);
int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
#define vc_translate(vc, c) ((vc)->vc_translate[(c) | \
diff --git a/include/memory/jedec_ddr.h b/include/memory/jedec_ddr.h
new file mode 100644
index 000000000000..ddad0f870e5d
--- /dev/null
+++ b/include/memory/jedec_ddr.h
@@ -0,0 +1,175 @@
+/*
+ * Definitions for DDR memories based on JEDEC specs
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __LINUX_JEDEC_DDR_H
+#define __LINUX_JEDEC_DDR_H
+
+#include <linux/types.h>
+
+/* DDR Densities */
+#define DDR_DENSITY_64Mb 1
+#define DDR_DENSITY_128Mb 2
+#define DDR_DENSITY_256Mb 3
+#define DDR_DENSITY_512Mb 4
+#define DDR_DENSITY_1Gb 5
+#define DDR_DENSITY_2Gb 6
+#define DDR_DENSITY_4Gb 7
+#define DDR_DENSITY_8Gb 8
+#define DDR_DENSITY_16Gb 9
+#define DDR_DENSITY_32Gb 10
+
+/* DDR type */
+#define DDR_TYPE_DDR2 1
+#define DDR_TYPE_DDR3 2
+#define DDR_TYPE_LPDDR2_S4 3
+#define DDR_TYPE_LPDDR2_S2 4
+#define DDR_TYPE_LPDDR2_NVM 5
+
+/* DDR IO width */
+#define DDR_IO_WIDTH_4 1
+#define DDR_IO_WIDTH_8 2
+#define DDR_IO_WIDTH_16 3
+#define DDR_IO_WIDTH_32 4
+
+/* Number of Row bits */
+#define R9 9
+#define R10 10
+#define R11 11
+#define R12 12
+#define R13 13
+#define R14 14
+#define R15 15
+#define R16 16
+
+/* Number of Column bits */
+#define C7 7
+#define C8 8
+#define C9 9
+#define C10 10
+#define C11 11
+#define C12 12
+
+/* Number of Banks */
+#define B1 0
+#define B2 1
+#define B4 2
+#define B8 3
+
+/* Refresh rate in nano-seconds */
+#define T_REFI_15_6 15600
+#define T_REFI_7_8 7800
+#define T_REFI_3_9 3900
+
+/* tRFC values */
+#define T_RFC_90 90000
+#define T_RFC_110 110000
+#define T_RFC_130 130000
+#define T_RFC_160 160000
+#define T_RFC_210 210000
+#define T_RFC_300 300000
+#define T_RFC_350 350000
+
+/* Mode register numbers */
+#define DDR_MR0 0
+#define DDR_MR1 1
+#define DDR_MR2 2
+#define DDR_MR3 3
+#define DDR_MR4 4
+#define DDR_MR5 5
+#define DDR_MR6 6
+#define DDR_MR7 7
+#define DDR_MR8 8
+#define DDR_MR9 9
+#define DDR_MR10 10
+#define DDR_MR11 11
+#define DDR_MR16 16
+#define DDR_MR17 17
+#define DDR_MR18 18
+
+/*
+ * LPDDR2 related defines
+ */
+
+/* MR4 register fields */
+#define MR4_SDRAM_REF_RATE_SHIFT 0
+#define MR4_SDRAM_REF_RATE_MASK 7
+#define MR4_TUF_SHIFT 7
+#define MR4_TUF_MASK (1 << 7)
+
+/* MR4 SDRAM Refresh Rate field values */
+#define SDRAM_TEMP_NOMINAL 0x3
+#define SDRAM_TEMP_RESERVED_4 0x4
+#define SDRAM_TEMP_HIGH_DERATE_REFRESH 0x5
+#define SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS 0x6
+#define SDRAM_TEMP_VERY_HIGH_SHUTDOWN 0x7
+
+#define NUM_DDR_ADDR_TABLE_ENTRIES 11
+#define NUM_DDR_TIMING_TABLE_ENTRIES 4
+
+/* Structure for DDR addressing info from the JEDEC spec */
+struct lpddr2_addressing {
+ u32 num_banks;
+ u32 tREFI_ns;
+ u32 tRFCab_ps;
+};
+
+/*
+ * Structure for timings from the LPDDR2 datasheet
+ * All parameters are in pico seconds(ps) unless explicitly indicated
+ * with a suffix like tRAS_max_ns below
+ */
+struct lpddr2_timings {
+ u32 max_freq;
+ u32 min_freq;
+ u32 tRPab;
+ u32 tRCD;
+ u32 tWR;
+ u32 tRAS_min;
+ u32 tRRD;
+ u32 tWTR;
+ u32 tXP;
+ u32 tRTP;
+ u32 tCKESR;
+ u32 tDQSCK_max;
+ u32 tDQSCK_max_derated;
+ u32 tFAW;
+ u32 tZQCS;
+ u32 tZQCL;
+ u32 tZQinit;
+ u32 tRAS_max_ns;
+};
+
+/*
+ * Min value for some parameters in terms of number of tCK cycles(nCK)
+ * Please set to zero parameters that are not valid for a given memory
+ * type
+ */
+struct lpddr2_min_tck {
+ u32 tRPab;
+ u32 tRCD;
+ u32 tWR;
+ u32 tRASmin;
+ u32 tRRD;
+ u32 tWTR;
+ u32 tXP;
+ u32 tRTP;
+ u32 tCKE;
+ u32 tCKESR;
+ u32 tFAW;
+};
+
+extern const struct lpddr2_addressing
+ lpddr2_jedec_addressing_table[NUM_DDR_ADDR_TABLE_ENTRIES];
+extern const struct lpddr2_timings
+ lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES];
+extern const struct lpddr2_min_tck lpddr2_jedec_min_tck;
+
+#endif /* __LINUX_JEDEC_DDR_H */
diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h
index 3c4109777aff..8787349fbafe 100644
--- a/include/mtd/ubi-user.h
+++ b/include/mtd/ubi-user.h
@@ -196,23 +196,6 @@
#define UBI_MAX_RNVOL 32
/*
- * UBI data type hint constants.
- *
- * UBI_LONGTERM: long-term data
- * UBI_SHORTTERM: short-term data
- * UBI_UNKNOWN: data persistence is unknown
- *
- * These constants are used when data is written to UBI volumes in order to
- * help the UBI wear-leveling unit to find more appropriate physical
- * eraseblocks.
- */
-enum {
- UBI_LONGTERM = 1,
- UBI_SHORTTERM = 2,
- UBI_UNKNOWN = 3,
-};
-
-/*
* UBI volume type constants.
*
* @UBI_DYNAMIC_VOLUME: dynamic volume
@@ -375,25 +358,34 @@ struct ubi_rnvol_req {
* requests.
* @lnum: logical eraseblock number to change
* @bytes: how many bytes will be written to the logical eraseblock
- * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
+ * @dtype: pass "3" for better compatibility with old kernels
* @padding: reserved for future, not used, has to be zeroed
+ *
+ * The @dtype field used to inform UBI about what kind of data will be written
+ * to the LEB: long term (value 1), short term (value 2), unknown (value 3).
+ * UBI tried to pick a PEB with lower erase counter for short term data and a
+ * PEB with higher erase counter for long term data. But this was not really
+ * used because users usually do not know this and could easily mislead UBI. We
+ * removed this feature in May 2012. UBI currently just ignores the @dtype
+ * field. But for better compatibility with older kernels it is recommended to
+ * set @dtype to 3 (unknown).
*/
struct ubi_leb_change_req {
__s32 lnum;
__s32 bytes;
- __s8 dtype;
+ __s8 dtype; /* obsolete, do not use! */
__s8 padding[7];
} __packed;
/**
* struct ubi_map_req - a data structure used in map LEB requests.
+ * @dtype: pass "3" for better compatibility with old kernels
* @lnum: logical eraseblock number to unmap
- * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
* @padding: reserved for future, not used, has to be zeroed
*/
struct ubi_map_req {
__s32 lnum;
- __s8 dtype;
+ __s8 dtype; /* obsolete, do not use! */
__s8 padding[3];
} __packed;
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 27f450ba9514..f2b801c4b555 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -131,9 +131,9 @@ extern int ipv6_sock_mc_join(struct sock *sk, int ifindex,
extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
const struct in6_addr *addr);
extern void ipv6_sock_mc_close(struct sock *sk);
-extern int inet6_mc_check(struct sock *sk,
- const struct in6_addr *mc_addr,
- const struct in6_addr *src_addr);
+extern bool inet6_mc_check(struct sock *sk,
+ const struct in6_addr *mc_addr,
+ const struct in6_addr *src_addr);
extern int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr);
extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr);
@@ -146,10 +146,10 @@ extern void ipv6_mc_init_dev(struct inet6_dev *idev);
extern void ipv6_mc_destroy_dev(struct inet6_dev *idev);
extern void addrconf_dad_failure(struct inet6_ifaddr *ifp);
-extern int ipv6_chk_mcast_addr(struct net_device *dev,
- const struct in6_addr *group,
- const struct in6_addr *src_addr);
-extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr);
+extern bool ipv6_chk_mcast_addr(struct net_device *dev,
+ const struct in6_addr *group,
+ const struct in6_addr *src_addr);
+extern bool ipv6_is_mld(struct sk_buff *skb, int nexthdr);
extern void addrconf_prefix_rcv(struct net_device *dev,
u8 *opt, int len, bool sllao);
@@ -163,8 +163,8 @@ extern void ipv6_sock_ac_close(struct sock *sk);
extern int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr);
extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr);
-extern int ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
- const struct in6_addr *addr);
+extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
+ const struct in6_addr *addr);
/* Device notifier */
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
index 16ff29a7bb30..2431cf83aeca 100644
--- a/include/net/inet_frag.h
+++ b/include/net/inet_frag.h
@@ -46,8 +46,7 @@ struct inet_frags {
void *arg);
void (*destructor)(struct inet_frag_queue *);
void (*skb_free)(struct sk_buff *);
- int (*match)(struct inet_frag_queue *q,
- void *arg);
+ bool (*match)(struct inet_frag_queue *q, void *arg);
void (*frag_expire)(unsigned long data);
};
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index c062b6773cc7..37c1a1ed82c1 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -175,7 +175,7 @@ static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst,
spin_unlock(&sk->sk_dst_lock);
}
-static inline int ipv6_unicast_destination(struct sk_buff *skb)
+static inline bool ipv6_unicast_destination(const struct sk_buff *skb)
{
struct rt6_info *rt = (struct rt6_info *) skb_dst(skb);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 4332e9aad853..aecf88436abf 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -263,7 +263,7 @@ extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_t
struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
struct ipv6_txoptions *opt);
-extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb);
+extern bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb);
int ip6_frag_nqueues(struct net *net);
int ip6_frag_mem(struct net *net);
@@ -332,8 +332,8 @@ static inline void ipv6_addr_set(struct in6_addr *addr,
addr->s6_addr32[3] = w4;
}
-static inline int ipv6_addr_equal(const struct in6_addr *a1,
- const struct in6_addr *a2)
+static inline bool ipv6_addr_equal(const struct in6_addr *a1,
+ const struct in6_addr *a2)
{
return ((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
(a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
@@ -341,27 +341,27 @@ static inline int ipv6_addr_equal(const struct in6_addr *a1,
(a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0;
}
-static inline int __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2,
- unsigned int prefixlen)
+static inline bool __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2,
+ unsigned int prefixlen)
{
unsigned int pdw, pbi;
/* check complete u32 in prefix */
pdw = prefixlen >> 5;
if (pdw && memcmp(a1, a2, pdw << 2))
- return 0;
+ return false;
/* check incomplete u32 in prefix */
pbi = prefixlen & 0x1f;
if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi))))
- return 0;
+ return false;
- return 1;
+ return true;
}
-static inline int ipv6_prefix_equal(const struct in6_addr *a1,
- const struct in6_addr *a2,
- unsigned int prefixlen)
+static inline bool ipv6_prefix_equal(const struct in6_addr *a1,
+ const struct in6_addr *a2,
+ unsigned int prefixlen)
{
return __ipv6_prefix_equal(a1->s6_addr32, a2->s6_addr32,
prefixlen);
@@ -387,21 +387,21 @@ struct ip6_create_arg {
};
void ip6_frag_init(struct inet_frag_queue *q, void *a);
-int ip6_frag_match(struct inet_frag_queue *q, void *a);
+bool ip6_frag_match(struct inet_frag_queue *q, void *a);
-static inline int ipv6_addr_any(const struct in6_addr *a)
+static inline bool ipv6_addr_any(const struct in6_addr *a)
{
return (a->s6_addr32[0] | a->s6_addr32[1] |
a->s6_addr32[2] | a->s6_addr32[3]) == 0;
}
-static inline int ipv6_addr_loopback(const struct in6_addr *a)
+static inline bool ipv6_addr_loopback(const struct in6_addr *a)
{
return (a->s6_addr32[0] | a->s6_addr32[1] |
a->s6_addr32[2] | (a->s6_addr32[3] ^ htonl(1))) == 0;
}
-static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
+static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
{
return (a->s6_addr32[0] | a->s6_addr32[1] |
(a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0;
@@ -411,7 +411,7 @@ static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
* Check for a RFC 4843 ORCHID address
* (Overlay Routable Cryptographic Hash Identifiers)
*/
-static inline int ipv6_addr_orchid(const struct in6_addr *a)
+static inline bool ipv6_addr_orchid(const struct in6_addr *a)
{
return (a->s6_addr32[0] & htonl(0xfffffff0)) == htonl(0x20010010);
}
@@ -559,7 +559,7 @@ extern void ipv6_push_frag_opts(struct sk_buff *skb,
extern int ipv6_skip_exthdr(const struct sk_buff *, int start,
u8 *nexthdrp, __be16 *frag_offp);
-extern int ipv6_ext_hdr(u8 nexthdr);
+extern bool ipv6_ext_hdr(u8 nexthdr);
extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
diff --git a/include/net/lapb.h b/include/net/lapb.h
index fd2bf572ee1d..df892a94f2c6 100644
--- a/include/net/lapb.h
+++ b/include/net/lapb.h
@@ -149,4 +149,10 @@ extern int lapb_t1timer_running(struct lapb_cb *lapb);
*/
#define LAPB_DEBUG 0
+#define lapb_dbg(level, fmt, ...) \
+do { \
+ if (level < LAPB_DEBUG) \
+ pr_debug(fmt, ##__VA_ARGS__); \
+} while (0)
+
#endif
diff --git a/include/net/rawv6.h b/include/net/rawv6.h
index cf7577234457..e7ea660e4db6 100644
--- a/include/net/rawv6.h
+++ b/include/net/rawv6.h
@@ -5,7 +5,7 @@
void raw6_icmp_error(struct sk_buff *, int nexthdr,
u8 type, u8 code, int inner_offset, __be32);
-int raw6_local_deliver(struct sk_buff *, int);
+bool raw6_local_deliver(struct sk_buff *, int);
extern int rawv6_rcv(struct sock *sk,
struct sk_buff *skb);
diff --git a/include/net/sock.h b/include/net/sock.h
index da931555e000..d89f0582b6b6 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -70,16 +70,16 @@
struct cgroup;
struct cgroup_subsys;
#ifdef CONFIG_NET
-int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss);
-void mem_cgroup_sockets_destroy(struct cgroup *cgrp);
+int mem_cgroup_sockets_init(struct mem_cgroup *memcg, struct cgroup_subsys *ss);
+void mem_cgroup_sockets_destroy(struct mem_cgroup *memcg);
#else
static inline
-int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss)
+int mem_cgroup_sockets_init(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
{
return 0;
}
static inline
-void mem_cgroup_sockets_destroy(struct cgroup *cgrp)
+void mem_cgroup_sockets_destroy(struct mem_cgroup *memcg)
{
}
#endif
@@ -914,9 +914,9 @@ struct proto {
* This function has to setup any files the protocol want to
* appear in the kmem cgroup filesystem.
*/
- int (*init_cgroup)(struct cgroup *cgrp,
+ int (*init_cgroup)(struct mem_cgroup *memcg,
struct cgroup_subsys *ss);
- void (*destroy_cgroup)(struct cgroup *cgrp);
+ void (*destroy_cgroup)(struct mem_cgroup *memcg);
struct cg_proto *(*proto_cgroup)(struct mem_cgroup *memcg);
#endif
};
diff --git a/include/net/tcp_memcontrol.h b/include/net/tcp_memcontrol.h
index 48410ff25c9e..7df18bc43a97 100644
--- a/include/net/tcp_memcontrol.h
+++ b/include/net/tcp_memcontrol.h
@@ -12,8 +12,8 @@ struct tcp_memcontrol {
};
struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg);
-int tcp_init_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss);
-void tcp_destroy_cgroup(struct cgroup *cgrp);
+int tcp_init_cgroup(struct mem_cgroup *memcg, struct cgroup_subsys *ss);
+void tcp_destroy_cgroup(struct mem_cgroup *memcg);
unsigned long long tcp_max_memory(const struct mem_cgroup *memcg);
void tcp_prot_mem(struct mem_cgroup *memcg, long val, int idx);
#endif /* _TCP_MEMCG_H */
diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
index b513f57e1725..3d81b90cc315 100644
--- a/include/rdma/ib_mad.h
+++ b/include/rdma/ib_mad.h
@@ -160,7 +160,7 @@ struct ib_rmpp_hdr {
typedef u64 __bitwise ib_sa_comp_mask;
-#define IB_SA_COMP_MASK(n) ((__force ib_sa_comp_mask) cpu_to_be64(1ull << n))
+#define IB_SA_COMP_MASK(n) ((__force ib_sa_comp_mask) cpu_to_be64(1ull << (n)))
/*
* ib_sa_hdr and ib_sa_mad structures must be packed because they have
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index c3cca5a4dacd..07996af8265a 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -605,7 +605,7 @@ enum ib_qp_type {
IB_QPT_UD,
IB_QPT_RAW_IPV6,
IB_QPT_RAW_ETHERTYPE,
- /* Save 8 for RAW_PACKET */
+ IB_QPT_RAW_PACKET = 8,
IB_QPT_XRC_INI = 9,
IB_QPT_XRC_TGT,
IB_QPT_MAX
@@ -964,7 +964,7 @@ struct ib_qp {
struct ib_srq *srq;
struct ib_xrcd *xrcd; /* XRC TGT QPs only */
struct list_head xrcd_list;
- atomic_t usecnt; /* count times opened */
+ atomic_t usecnt; /* count times opened, mcast attaches */
struct list_head open_list;
struct ib_qp *real_qp;
struct ib_uobject *uobject;
diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
index 988ba06b3ad6..c1260d80ef30 100644
--- a/include/scsi/iscsi_proto.h
+++ b/include/scsi/iscsi_proto.h
@@ -661,6 +661,8 @@ struct iscsi_reject {
#define ISCSI_DEF_TIME2WAIT 2
+#define ISCSI_NAME_LEN 224
+
/************************* RFC 3720 End *****************************/
#endif /* ISCSI_PROTO_H */
diff --git a/include/scsi/sas.h b/include/scsi/sas.h
index a577a833603d..be3eb0bf1ac0 100644
--- a/include/scsi/sas.h
+++ b/include/scsi/sas.h
@@ -103,6 +103,7 @@ enum sas_dev_type {
};
enum sas_protocol {
+ SAS_PROTOCOL_NONE = 0,
SAS_PROTOCOL_SATA = 0x01,
SAS_PROTOCOL_SMP = 0x02,
SAS_PROTOCOL_STP = 0x04,
diff --git a/include/sound/asound.h b/include/sound/asound.h
index a2e4ff5ba9e9..0876a1e76aef 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -70,6 +70,20 @@ struct snd_aes_iec958 {
/****************************************************************************
* *
+ * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort *
+ * *
+ ****************************************************************************/
+
+struct snd_cea_861_aud_if {
+ unsigned char db1_ct_cc; /* coding type and channel count */
+ unsigned char db2_sf_ss; /* sample frequency and size */
+ unsigned char db3; /* not used, all zeros */
+ unsigned char db4_ca; /* channel allocation code */
+ unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
+};
+
+/****************************************************************************
+ * *
* Section for driver hardware dependent interface - /dev/snd/hw? *
* *
****************************************************************************/
diff --git a/include/sound/asoundef.h b/include/sound/asoundef.h
index 20ebf3298eba..bb05c02f89b0 100644
--- a/include/sound/asoundef.h
+++ b/include/sound/asoundef.h
@@ -170,6 +170,47 @@
#define IEC958_AES5_CON_CGMSA_COPYNOMORE (2<<0) /* condition not be used */
#define IEC958_AES5_CON_CGMSA_COPYNEVER (3<<0) /* no copying is permitted */
+/****************************************************************************
+ * *
+ * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort *
+ * *
+ ****************************************************************************/
+#define CEA861_AUDIO_INFOFRAME_DB1CC (7<<0) /* mask - channel count */
+#define CEA861_AUDIO_INFOFRAME_DB1CT (0xf<<4) /* mask - coding type */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_FROM_STREAM (0<<4) /* refer to stream */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_IEC60958 (1<<4) /* IEC-60958 L-PCM */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_AC3 (2<<4) /* AC-3 */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_MPEG1 (3<<4) /* MPEG1 Layers 1 & 2 */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_MP3 (4<<4) /* MPEG1 Layer 3 */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_MPEG2_MULTICH (5<<4) /* MPEG2 Multichannel */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_AAC (6<<4) /* AAC */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_DTS (7<<4) /* DTS */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_ATRAC (8<<4) /* ATRAC */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_ONEBIT (9<<4) /* One Bit Audio */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_DOLBY_DIG_PLUS (10<<4) /* Dolby Digital + */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_DTS_HD (11<<4) /* DTS-HD */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_MAT (12<<4) /* MAT (MLP) */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_DST (13<<4) /* DST */
+#define CEA861_AUDIO_INFOFRAME_DB1CT_WMA_PRO (14<<4) /* WMA Pro */
+#define CEA861_AUDIO_INFOFRAME_DB2SF (7<<2) /* mask - sample frequency */
+#define CEA861_AUDIO_INFOFRAME_DB2SF_FROM_STREAM (0<<2) /* refer to stream */
+#define CEA861_AUDIO_INFOFRAME_DB2SF_32000 (1<<2) /* 32kHz */
+#define CEA861_AUDIO_INFOFRAME_DB2SF_44100 (2<<2) /* 44.1kHz */
+#define CEA861_AUDIO_INFOFRAME_DB2SF_48000 (3<<2) /* 48kHz */
+#define CEA861_AUDIO_INFOFRAME_DB2SF_88200 (4<<2) /* 88.2kHz */
+#define CEA861_AUDIO_INFOFRAME_DB2SF_96000 (5<<2) /* 96kHz */
+#define CEA861_AUDIO_INFOFRAME_DB2SF_176400 (6<<2) /* 176.4kHz */
+#define CEA861_AUDIO_INFOFRAME_DB2SF_192000 (7<<2) /* 192kHz */
+#define CEA861_AUDIO_INFOFRAME_DB2SS (3<<0) /* mask - sample size */
+#define CEA861_AUDIO_INFOFRAME_DB2SS_FROM_STREAM (0<<0) /* refer to stream */
+#define CEA861_AUDIO_INFOFRAME_DB2SS_16BIT (1<<0) /* 16 bits */
+#define CEA861_AUDIO_INFOFRAME_DB2SS_20BIT (2<<0) /* 20 bits */
+#define CEA861_AUDIO_INFOFRAME_DB2SS_24BIT (3<<0) /* 24 bits */
+#define CEA861_AUDIO_INFOFRAME_DB5_DM_INH (1<<7) /* mask - inhibit downmixing */
+#define CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PERMITTED (0<<7) /* stereo downmix permitted */
+#define CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED (1<<7) /* stereo downmis prohibited */
+#define CEA861_AUDIO_INFOFRAME_DB5_LSV (0xf<<3) /* mask - level-shift values */
+
/*****************************************************************************
* *
* MIDI v1.0 interface *
diff --git a/include/sound/cs42l52.h b/include/sound/cs42l52.h
new file mode 100644
index 000000000000..4c68955f7330
--- /dev/null
+++ b/include/sound/cs42l52.h
@@ -0,0 +1,36 @@
+/*
+ * linux/sound/cs42l52.h -- Platform data for CS42L52
+ *
+ * Copyright (c) 2012 Cirrus Logic Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __CS42L52_H
+#define __CS42L52_H
+
+struct cs42l52_platform_data {
+
+ /* MICBIAS Level. Check datasheet Pg48 */
+ unsigned int micbias_lvl;
+
+ /* MICA mode selection 0=Single 1=Differential */
+ unsigned int mica_cfg;
+
+ /* MICB mode selection 0=Single 1=Differential */
+ unsigned int micb_cfg;
+
+ /* MICA Select 0=MIC1A 1=MIC2A */
+ unsigned int mica_sel;
+
+ /* MICB Select 0=MIC2A 1=MIC2B */
+ unsigned int micb_sel;
+
+ /* Charge Pump Freq. Check datasheet Pg73 */
+ unsigned int chgfreq;
+
+};
+
+#endif /* __CS42L52_H */
diff --git a/include/sound/max98095.h b/include/sound/max98095.h
index 7513a42dd4aa..e87ae67b0a55 100644
--- a/include/sound/max98095.h
+++ b/include/sound/max98095.h
@@ -49,6 +49,18 @@ struct max98095_pdata {
*/
unsigned int digmic_left_mode:1;
unsigned int digmic_right_mode:1;
+
+ /* Pin5 is the mechanical method of sensing jack insertion
+ * but it is something that might not be supported.
+ * 0 = PIN5 not supported
+ * 1 = PIN5 supported
+ */
+ unsigned int jack_detect_pin5en:1;
+
+ /* Slew amount for jack detection. Calculated as 4 * (delay + 1).
+ * Default delay is 24 to get a time of 100ms.
+ */
+ unsigned int jack_detect_delay;
};
#endif
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
index b457e87fbd08..906010344dd7 100644
--- a/include/sound/sh_fsi.h
+++ b/include/sound/sh_fsi.h
@@ -21,10 +21,11 @@
/*
* flags format
*
- * 0x000000BA
+ * 0x00000CBA
*
* A: inversion
* B: format mode
+ * C: chip specific
*/
/* A: clock inversion */
@@ -39,6 +40,9 @@
#define SH_FSI_FMT_DAI (0 << 4)
#define SH_FSI_FMT_SPDIF (1 << 4)
+/* C: chip specific */
+#define SH_FSI_OPTION_MASK 0x00000F00
+#define SH_FSI_ENABLE_STREAM_MODE (1 << 8) /* for 16bit data */
/*
* set_rate return value
@@ -84,16 +88,4 @@ struct sh_fsi_platform_info {
struct sh_fsi_port_info port_b;
};
-/*
- * for fsi-ak4642
- */
-struct fsi_ak4642_info {
- const char *name;
- const char *card;
- const char *cpu_dai;
- const char *codec;
- const char *platform;
- int id;
-};
-
#endif /* __SOUND_FSI_H */
diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h
new file mode 100644
index 000000000000..4b62b8dc6a4f
--- /dev/null
+++ b/include/sound/simple_card.h
@@ -0,0 +1,38 @@
+/*
+ * ASoC simple sound card support
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.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 __SIMPLE_CARD_H
+#define __SIMPLE_CARD_H
+
+#include <sound/soc.h>
+
+struct asoc_simple_dai_init_info {
+ unsigned int fmt;
+ unsigned int cpu_daifmt;
+ unsigned int codec_daifmt;
+ unsigned int sysclk;
+};
+
+struct asoc_simple_card_info {
+ const char *name;
+ const char *card;
+ const char *cpu_dai;
+ const char *codec;
+ const char *platform;
+ const char *codec_dai;
+ struct asoc_simple_dai_init_info *init; /* for snd_link.init */
+
+ /* used in simple-card.c */
+ struct snd_soc_dai_link snd_link;
+ struct snd_soc_card snd_card;
+};
+
+#endif /* __SIMPLE_CARD_H */
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index c429f248cf4e..1f69e0af2941 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -173,6 +173,8 @@ struct snd_soc_dai_ops {
struct snd_soc_dai *);
int (*trigger)(struct snd_pcm_substream *, int,
struct snd_soc_dai *);
+ int (*bespoke_trigger)(struct snd_pcm_substream *, int,
+ struct snd_soc_dai *);
/*
* For hardware based FIFO caused delay reporting.
* Optional.
@@ -196,6 +198,7 @@ struct snd_soc_dai_driver {
const char *name;
unsigned int id;
int ac97_control;
+ unsigned int base;
/* DAI driver callbacks */
int (*probe)(struct snd_soc_dai *dai);
@@ -241,6 +244,7 @@ struct snd_soc_dai {
struct snd_soc_dapm_widget *playback_widget;
struct snd_soc_dapm_widget *capture_widget;
+ struct snd_soc_dapm_context dapm;
/* DAI DMA data */
void *playback_dma_data;
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 8da3c2409060..e3833d9f1914 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -141,10 +141,6 @@ struct device;
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, \
.num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags}
-#define SND_SOC_DAPM_MICBIAS_E(wname, wreg, wshift, winvert, wevent, wflags) \
-{ .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
- .invert = winvert, .kcontrol_news = NULL, .num_kcontrols = 0, \
- .event = wevent, .event_flags = wflags}
#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \
wevent, wflags) \
{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
@@ -324,6 +320,8 @@ struct snd_soc_dapm_path;
struct snd_soc_dapm_pin;
struct snd_soc_dapm_route;
struct snd_soc_dapm_context;
+struct regulator;
+struct snd_soc_dapm_widget_list;
int dapm_reg_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
@@ -359,6 +357,10 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
struct snd_soc_dai *dai);
int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
+int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
+ const struct snd_soc_pcm_stream *params,
+ struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink);
/* dapm path setup */
int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm);
@@ -369,8 +371,8 @@ int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num);
/* dapm events */
-int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
- struct snd_soc_dai *dai, int event);
+void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
+ int event);
void snd_soc_dapm_shutdown(struct snd_soc_card *card);
/* external DAPM widget events */
@@ -402,6 +404,10 @@ void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
/* Mostly internal - should not normally be used */
void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason);
+/* dapm path query */
+int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
+ struct snd_soc_dapm_widget_list **list);
+
/* dapm widget types */
enum snd_soc_dapm_type {
snd_soc_dapm_input = 0, /* input pin */
@@ -430,6 +436,12 @@ enum snd_soc_dapm_type {
snd_soc_dapm_aif_out, /* audio interface output */
snd_soc_dapm_siggen, /* signal generator */
snd_soc_dapm_dai, /* link to DAI structure */
+ snd_soc_dapm_dai_link, /* link between two DAI structures */
+};
+
+enum snd_soc_dapm_subclass {
+ SND_SOC_DAPM_CLASS_INIT = 0,
+ SND_SOC_DAPM_CLASS_RUNTIME = 1,
};
/*
@@ -482,9 +494,11 @@ struct snd_soc_dapm_widget {
struct snd_soc_dapm_context *dapm;
void *priv; /* widget specific data */
+ struct regulator *regulator; /* attached regulator */
+ const struct snd_soc_pcm_stream *params; /* params for dai links */
/* dapm control */
- short reg; /* negative reg = no direct dapm */
+ int reg; /* negative reg = no direct dapm */
unsigned char shift; /* bits to shift */
unsigned int saved_value; /* widget saved value */
unsigned int value; /* widget current value */
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h
new file mode 100644
index 000000000000..04598f1efd77
--- /dev/null
+++ b/include/sound/soc-dpcm.h
@@ -0,0 +1,138 @@
+/*
+ * linux/sound/soc-dpcm.h -- ALSA SoC Dynamic PCM Support
+ *
+ * Author: Liam Girdwood <lrg@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_SOC_DPCM_H
+#define __LINUX_SND_SOC_DPCM_H
+
+#include <linux/list.h>
+#include <sound/pcm.h>
+
+struct snd_soc_pcm_runtime;
+
+/*
+ * Types of runtime_update to perform. e.g. originated from FE PCM ops
+ * or audio route changes triggered by muxes/mixers.
+ */
+enum snd_soc_dpcm_update {
+ SND_SOC_DPCM_UPDATE_NO = 0,
+ SND_SOC_DPCM_UPDATE_BE,
+ SND_SOC_DPCM_UPDATE_FE,
+};
+
+/*
+ * Dynamic PCM Frontend -> Backend link management states.
+ */
+enum snd_soc_dpcm_link_state {
+ SND_SOC_DPCM_LINK_STATE_NEW = 0, /* newly created link */
+ SND_SOC_DPCM_LINK_STATE_FREE, /* link to be dismantled */
+};
+
+/*
+ * Dynamic PCM Frontend -> Backend link PCM states.
+ */
+enum snd_soc_dpcm_state {
+ SND_SOC_DPCM_STATE_NEW = 0,
+ SND_SOC_DPCM_STATE_OPEN,
+ SND_SOC_DPCM_STATE_HW_PARAMS,
+ SND_SOC_DPCM_STATE_PREPARE,
+ SND_SOC_DPCM_STATE_START,
+ SND_SOC_DPCM_STATE_STOP,
+ SND_SOC_DPCM_STATE_PAUSED,
+ SND_SOC_DPCM_STATE_SUSPEND,
+ SND_SOC_DPCM_STATE_HW_FREE,
+ SND_SOC_DPCM_STATE_CLOSE,
+};
+
+/*
+ * Dynamic PCM trigger ordering. Triggering flexibility is required as some
+ * DSPs require triggering before/after their CPU platform and DAIs.
+ *
+ * i.e. some clients may want to manually order this call in their PCM
+ * trigger() whilst others will just use the regular core ordering.
+ */
+enum snd_soc_dpcm_trigger {
+ SND_SOC_DPCM_TRIGGER_PRE = 0,
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_BESPOKE,
+};
+
+/*
+ * Dynamic PCM link
+ * This links together a FE and BE DAI at runtime and stores the link
+ * state information and the hw_params configuration.
+ */
+struct snd_soc_dpcm {
+ /* FE and BE DAIs*/
+ struct snd_soc_pcm_runtime *be;
+ struct snd_soc_pcm_runtime *fe;
+
+ /* link state */
+ enum snd_soc_dpcm_link_state state;
+
+ /* list of BE and FE for this DPCM link */
+ struct list_head list_be;
+ struct list_head list_fe;
+
+ /* hw params for this link - may be different for each link */
+ struct snd_pcm_hw_params hw_params;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_state;
+#endif
+};
+
+/*
+ * Dynamic PCM runtime data.
+ */
+struct snd_soc_dpcm_runtime {
+ struct list_head be_clients;
+ struct list_head fe_clients;
+
+ int users;
+ struct snd_pcm_runtime *runtime;
+ struct snd_pcm_hw_params hw_params;
+
+ /* state and update */
+ enum snd_soc_dpcm_update runtime_update;
+ enum snd_soc_dpcm_state state;
+};
+
+/* can this BE stop and free */
+int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
+ struct snd_soc_pcm_runtime *be, int stream);
+
+/* can this BE perform a hw_params() */
+int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
+ struct snd_soc_pcm_runtime *be, int stream);
+
+/* is the current PCM operation for this FE ? */
+int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream);
+
+/* is the current PCM operation for this BE ? */
+int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe,
+ struct snd_soc_pcm_runtime *be, int stream);
+
+/* get the substream for this BE */
+struct snd_pcm_substream *
+ snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream);
+
+/* get the BE runtime state */
+enum snd_soc_dpcm_state
+ snd_soc_dpcm_be_get_state(struct snd_soc_pcm_runtime *be, int stream);
+
+/* set the BE runtime state */
+void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,
+ enum snd_soc_dpcm_state state);
+
+/* internal use only */
+int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
+int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
+int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *);
+
+#endif
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 2ebf7877c148..c703871f5f65 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -55,6 +55,18 @@
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
.put = snd_soc_put_volsw, \
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
+#define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+ SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+ .tlv.p = (tlv_array),\
+ .info = snd_soc_info_volsw, \
+ .get = snd_soc_get_volsw_sx,\
+ .put = snd_soc_put_volsw_sx, \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = xreg, .rreg = xreg, \
+ .shift = xshift, .rshift = xshift, \
+ .max = xmax, .min = xmin} }
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
@@ -85,6 +97,18 @@
.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
xmax, xinvert) }
+#define SOC_DOUBLE_R_SX_TLV(xname, xreg, xrreg, xshift, xmin, xmax, tlv_array) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+ SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+ .tlv.p = (tlv_array), \
+ .info = snd_soc_info_volsw, \
+ .get = snd_soc_get_volsw_sx, \
+ .put = snd_soc_put_volsw_sx, \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = xreg, .rreg = xrreg, \
+ .shift = xshift, .rshift = xshift, \
+ .max = xmax, .min = xmin} }
#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
@@ -171,20 +195,6 @@
.get = xhandler_get, .put = xhandler_put, \
.private_value = (unsigned long)&xenum }
-#define SOC_DOUBLE_R_SX_TLV(xname, xreg_left, xreg_right, xshift,\
- xmin, xmax, tlv_array) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
- SNDRV_CTL_ELEM_ACCESS_READWRITE, \
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw_2r_sx, \
- .get = snd_soc_get_volsw_2r_sx, \
- .put = snd_soc_put_volsw_2r_sx, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = xreg_left, \
- .rreg = xreg_right, .shift = xshift, \
- .min = xmin, .max = xmax} }
-
#define SND_SOC_BYTES(xname, xbase, xregs) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
@@ -200,6 +210,19 @@
{.base = xbase, .num_regs = xregs, \
.mask = xmask }) }
+#define SOC_SINGLE_XR_SX(xname, xregbase, xregcount, xnbits, \
+ xmin, xmax, xinvert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+ .info = snd_soc_info_xr_sx, .get = snd_soc_get_xr_sx, \
+ .put = snd_soc_put_xr_sx, \
+ .private_value = (unsigned long)&(struct soc_mreg_control) \
+ {.regbase = xregbase, .regcount = xregcount, .nbits = xnbits, \
+ .invert = xinvert, .min = xmin, .max = xmax} }
+
+#define SOC_SINGLE_STROBE(xname, xreg, xshift, xinvert) \
+ SOC_SINGLE_EXT(xname, xreg, xshift, 1, xinvert, \
+ snd_soc_get_strobe, snd_soc_put_strobe)
+
/*
* Simplified versions of above macros, declaring a struct and calculating
* ARRAY_SIZE internally
@@ -264,6 +287,7 @@ struct snd_soc_jack_zone;
struct snd_soc_jack_pin;
struct snd_soc_cache_ops;
#include <sound/soc-dapm.h>
+#include <sound/soc-dpcm.h>
#ifdef CONFIG_GPIOLIB
struct snd_soc_jack_gpio;
@@ -288,6 +312,11 @@ enum snd_soc_pcm_subclass {
SND_SOC_PCM_CLASS_BE = 1,
};
+enum snd_soc_card_subclass {
+ SND_SOC_CARD_CLASS_INIT = 0,
+ SND_SOC_CARD_CLASS_RUNTIME = 1,
+};
+
int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir);
int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
@@ -333,6 +362,11 @@ int snd_soc_platform_write(struct snd_soc_platform *platform,
unsigned int reg, unsigned int val);
int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
+struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
+ const char *dai_link, int stream);
+struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
+ const char *dai_link);
+
/* Utility functions to get clock rates from various things */
int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
@@ -343,6 +377,9 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *parms);
int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
const struct snd_pcm_hardware *hw);
+int snd_soc_platform_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_platform *platform);
+
/* Jack reporting */
int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
struct snd_soc_jack *jack);
@@ -413,6 +450,10 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
#define snd_soc_get_volsw_2r snd_soc_get_volsw
#define snd_soc_put_volsw_2r snd_soc_put_volsw
+int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
@@ -421,19 +462,22 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_limit_volume(struct snd_soc_codec *codec,
const char *name, int max);
-int snd_soc_info_volsw_2r_sx(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo);
-int snd_soc_get_volsw_2r_sx(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
-
+int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo);
+int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int snd_soc_get_strobe(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int snd_soc_put_strobe(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
/**
* struct snd_soc_reg_access - Describes whether a given register is
@@ -513,6 +557,7 @@ struct snd_soc_jack_gpio {
#endif
struct snd_soc_jack {
+ struct mutex mutex;
struct snd_jack *jack;
struct snd_soc_codec *codec;
struct list_head pins;
@@ -711,6 +756,7 @@ struct snd_soc_platform_driver {
/* platform IO - used for platform DAPM */
unsigned int (*read)(struct snd_soc_platform *, unsigned int);
int (*write)(struct snd_soc_platform *, unsigned int, unsigned int);
+ int (*bespoke_trigger)(struct snd_pcm_substream *, int);
};
struct snd_soc_platform {
@@ -746,21 +792,36 @@ struct snd_soc_dai_link {
const char *cpu_dai_name;
const struct device_node *cpu_dai_of_node;
const char *codec_dai_name;
+ int be_id; /* optional ID for machine driver BE identification */
+
+ const struct snd_soc_pcm_stream *params;
unsigned int dai_fmt; /* format to set on init */
+ enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */
+
/* Keep DAI active over suspend */
unsigned int ignore_suspend:1;
/* Symmetry requirements */
unsigned int symmetric_rates:1;
+ /* Do not create a PCM for this DAI link (Backend link) */
+ unsigned int no_pcm:1;
+
+ /* This DAI link can route to other DAI links at runtime (Frontend)*/
+ unsigned int dynamic:1;
+
/* pmdown_time is ignored at stop */
unsigned int ignore_pmdown_time:1;
/* codec/machine specific init - e.g. add machine controls */
int (*init)(struct snd_soc_pcm_runtime *rtd);
+ /* optional hw_params re-writing for BE and FE sync */
+ int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params);
+
/* machine stream operations */
struct snd_soc_ops *ops;
};
@@ -800,6 +861,7 @@ struct snd_soc_card {
struct list_head list;
struct mutex mutex;
+ struct mutex dapm_mutex;
bool instantiated;
@@ -889,9 +951,11 @@ struct snd_soc_pcm_runtime {
enum snd_soc_pcm_subclass pcm_subclass;
struct snd_pcm_ops ops;
- unsigned int complete:1;
unsigned int dev_registered:1;
+ /* Dynamic PCM BE runtime data */
+ struct snd_soc_dpcm_runtime dpcm[2];
+
long pmdown_time;
/* runtime devices */
@@ -902,6 +966,10 @@ struct snd_soc_pcm_runtime {
struct snd_soc_dai *cpu_dai;
struct delayed_work delayed_work;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_dpcm_root;
+ struct dentry *debugfs_dpcm_state;
+#endif
};
/* mixer control */
@@ -916,6 +984,12 @@ struct soc_bytes {
u32 mask;
};
+/* multi register control */
+struct soc_mreg_control {
+ long min, max;
+ unsigned int regbase, regcount, nbits, invert;
+};
+
/* enumerated kcontrol */
struct soc_enum {
unsigned short reg;
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index 8c9ff1b14396..2d7db85e93ae 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -23,12 +23,11 @@ struct se_subsystem_api {
struct se_device *(*create_virtdevice)(struct se_hba *,
struct se_subsystem_dev *, void *);
void (*free_device)(void *);
- int (*transport_complete)(struct se_task *task);
- struct se_task *(*alloc_task)(unsigned char *cdb);
- int (*do_task)(struct se_task *);
+ int (*transport_complete)(struct se_cmd *cmd, struct scatterlist *);
+ int (*execute_cmd)(struct se_cmd *, struct scatterlist *, u32,
+ enum dma_data_direction);
int (*do_discard)(struct se_device *, sector_t, u32);
- void (*do_sync_cache)(struct se_task *);
- void (*free_task)(struct se_task *);
+ void (*do_sync_cache)(struct se_cmd *);
ssize_t (*check_configfs_dev_params)(struct se_hba *,
struct se_subsystem_dev *);
ssize_t (*set_configfs_dev_params)(struct se_hba *,
@@ -38,7 +37,7 @@ struct se_subsystem_api {
u32 (*get_device_rev)(struct se_device *);
u32 (*get_device_type)(struct se_device *);
sector_t (*get_blocks)(struct se_device *);
- unsigned char *(*get_sense_buffer)(struct se_task *);
+ unsigned char *(*get_sense_buffer)(struct se_cmd *);
};
int transport_subsystem_register(struct se_subsystem_api *);
@@ -48,10 +47,7 @@ struct se_device *transport_add_device_to_core_hba(struct se_hba *,
struct se_subsystem_api *, struct se_subsystem_dev *, u32,
void *, struct se_dev_limits *, const char *, const char *);
-void transport_complete_sync_cache(struct se_cmd *, int);
-void transport_complete_task(struct se_task *, int);
-
-void target_get_task_cdb(struct se_task *, unsigned char *);
+void target_complete_cmd(struct se_cmd *, u8);
void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *);
int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *);
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index aaccc5f5fc9f..dc35d8660aa6 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -73,9 +73,8 @@
/*
* struct se_device->dev_flags
*/
-#define DF_READ_ONLY 0x00000001
-#define DF_SPC2_RESERVATIONS 0x00000002
-#define DF_SPC2_RESERVATIONS_WITH_ISID 0x00000004
+#define DF_SPC2_RESERVATIONS 0x00000001
+#define DF_SPC2_RESERVATIONS_WITH_ISID 0x00000002
/* struct se_dev_attrib sanity values */
/* Default max_unmap_lba_count */
@@ -141,14 +140,6 @@ enum transport_tpg_type_table {
TRANSPORT_TPG_TYPE_DISCOVERY = 1,
};
-/* struct se_task->task_flags */
-enum se_task_flags {
- TF_ACTIVE = (1 << 0),
- TF_SENT = (1 << 1),
- TF_REQUEST_STOP = (1 << 2),
- TF_HAS_SENSE = (1 << 3),
-};
-
/* Special transport agnostic struct se_cmd->t_states */
enum transport_state_table {
TRANSPORT_NO_STATE = 0,
@@ -234,6 +225,7 @@ enum tcm_sense_reason_table {
enum target_sc_flags_table {
TARGET_SCF_BIDI_OP = 0x01,
TARGET_SCF_ACK_KREF = 0x02,
+ TARGET_SCF_UNKNOWN_SIZE = 0x04,
};
/* fabric independent task management function values */
@@ -338,6 +330,7 @@ struct t10_alua_tg_pt_gp {
int tg_pt_gp_alua_access_type;
int tg_pt_gp_nonop_delay_msecs;
int tg_pt_gp_trans_delay_msecs;
+ int tg_pt_gp_implict_trans_secs;
int tg_pt_gp_pref;
int tg_pt_gp_write_metadata;
/* Used by struct t10_alua_tg_pt_gp->tg_pt_gp_md_buf_len */
@@ -485,23 +478,6 @@ struct se_queue_obj {
wait_queue_head_t thread_wq;
};
-struct se_task {
- unsigned long long task_lba;
- u32 task_sectors;
- u32 task_size;
- struct se_cmd *task_se_cmd;
- struct scatterlist *task_sg;
- u32 task_sg_nents;
- u16 task_flags;
- u8 task_scsi_status;
- enum dma_data_direction task_data_direction;
- struct list_head t_list;
- struct list_head t_execute_list;
- struct list_head t_state_list;
- bool t_state_active;
- struct completion task_stop_comp;
-};
-
struct se_tmr_req {
/* Task Management function to be performed */
u8 function;
@@ -538,6 +514,7 @@ struct se_cmd {
/* Used to signal cmd->se_tfo->check_release_cmd() usage per cmd */
unsigned check_release:1;
unsigned cmd_wait_set:1;
+ unsigned unknown_data_length:1;
/* See se_cmd_flags_table */
u32 se_cmd_flags;
u32 se_ordered_id;
@@ -565,18 +542,13 @@ struct se_cmd {
struct completion cmd_wait_comp;
struct kref cmd_kref;
struct target_core_fabric_ops *se_tfo;
- int (*execute_task)(struct se_task *);
+ int (*execute_cmd)(struct se_cmd *);
void (*transport_complete_callback)(struct se_cmd *);
unsigned char *t_task_cdb;
unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE];
unsigned long long t_task_lba;
- u32 t_tasks_sg_chained_no;
atomic_t t_fe_count;
- atomic_t t_se_count;
- atomic_t t_task_cdbs_left;
- atomic_t t_task_cdbs_ex_left;
- atomic_t t_task_cdbs_sent;
unsigned int transport_state;
#define CMD_T_ABORTED (1 << 0)
#define CMD_T_ACTIVE (1 << 1)
@@ -588,11 +560,12 @@ struct se_cmd {
#define CMD_T_LUN_STOP (1 << 7)
#define CMD_T_LUN_FE_STOP (1 << 8)
#define CMD_T_DEV_ACTIVE (1 << 9)
+#define CMD_T_REQUEST_STOP (1 << 10)
+#define CMD_T_BUSY (1 << 11)
spinlock_t t_state_lock;
struct completion t_transport_stop_comp;
struct completion transport_lun_fe_stop_comp;
struct completion transport_lun_stop_comp;
- struct scatterlist *t_tasks_sg_chained;
struct work_struct work;
@@ -602,10 +575,15 @@ struct se_cmd {
struct scatterlist *t_bidi_data_sg;
unsigned int t_bidi_data_nents;
- /* Used for BIDI READ */
- struct list_head t_task_list;
- u32 t_task_list_num;
+ struct list_head execute_list;
+ struct list_head state_list;
+ bool state_active;
+
+ /* old task stop completion, consider merging with some of the above */
+ struct completion task_stop_comp;
+ /* backend private data */
+ void *priv;
};
struct se_ua {
@@ -731,7 +709,6 @@ struct se_dev_attrib {
u32 hw_block_size;
u32 block_size;
u32 hw_max_sectors;
- u32 max_sectors;
u32 fabric_max_sectors;
u32 optimal_sectors;
u32 hw_queue_depth;
@@ -829,8 +806,8 @@ struct se_device {
struct task_struct *process_thread;
struct work_struct qf_work_queue;
struct list_head delayed_cmd_list;
- struct list_head execute_task_list;
- struct list_head state_task_list;
+ struct list_head execute_list;
+ struct list_head state_list;
struct list_head qf_cmd_list;
/* Pointer to associated SE HBA */
struct se_hba *se_hba;
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index 10c690809601..116959933f46 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -3,12 +3,6 @@
struct target_core_fabric_ops {
struct configfs_subsystem *tf_subsys;
- /*
- * Optional to signal struct se_task->task_sg[] padding entries
- * for scatterlist chaining using transport_do_task_sg_link(),
- * disabled by default
- */
- bool task_sg_chaining;
char *(*get_fabric_name)(void);
u8 (*get_fabric_proto_ident)(struct se_portal_group *);
char *(*tpg_get_wwn)(struct se_portal_group *);
@@ -102,7 +96,7 @@ void __transport_register_session(struct se_portal_group *,
void transport_register_session(struct se_portal_group *,
struct se_node_acl *, struct se_session *, void *);
void target_get_session(struct se_session *);
-int target_put_session(struct se_session *);
+void target_put_session(struct se_session *);
void transport_free_session(struct se_session *);
void target_put_nacl(struct se_node_acl *);
void transport_deregister_session_configfs(struct se_session *);
@@ -112,7 +106,7 @@ void transport_deregister_session(struct se_session *);
void transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *,
struct se_session *, u32, int, int, unsigned char *);
int transport_lookup_cmd_lun(struct se_cmd *, u32);
-int transport_generic_allocate_tasks(struct se_cmd *, unsigned char *);
+int target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *);
void target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
unsigned char *, u32, u32, int, int, int);
int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
@@ -124,7 +118,6 @@ int transport_generic_handle_cdb_map(struct se_cmd *);
int transport_generic_handle_data(struct se_cmd *);
int transport_generic_map_mem_to_cmd(struct se_cmd *cmd,
struct scatterlist *, u32, struct scatterlist *, u32);
-void transport_do_task_sg_chain(struct se_cmd *);
int transport_generic_new_cmd(struct se_cmd *);
void transport_generic_process_write(struct se_cmd *);
diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h
index ab26f8aa3c78..5fc2dcdd21cd 100644
--- a/include/trace/events/asoc.h
+++ b/include/trace/events/asoc.h
@@ -7,6 +7,8 @@
#include <linux/ktime.h>
#include <linux/tracepoint.h>
+#define DAPM_DIRECT "(direct)"
+
struct snd_soc_jack;
struct snd_soc_codec;
struct snd_soc_platform;
@@ -241,6 +243,84 @@ TRACE_EVENT(snd_soc_dapm_walk_done,
(int)__entry->path_checks, (int)__entry->neighbour_checks)
);
+TRACE_EVENT(snd_soc_dapm_output_path,
+
+ TP_PROTO(struct snd_soc_dapm_widget *widget,
+ struct snd_soc_dapm_path *path),
+
+ TP_ARGS(widget, path),
+
+ TP_STRUCT__entry(
+ __string( wname, widget->name )
+ __string( pname, path->name ? path->name : DAPM_DIRECT)
+ __string( psname, path->sink->name )
+ __field( int, path_sink )
+ __field( int, path_connect )
+ ),
+
+ TP_fast_assign(
+ __assign_str(wname, widget->name);
+ __assign_str(pname, path->name ? path->name : DAPM_DIRECT);
+ __assign_str(psname, path->sink->name);
+ __entry->path_connect = path->connect;
+ __entry->path_sink = (long)path->sink;
+ ),
+
+ TP_printk("%c%s -> %s -> %s\n",
+ (int) __entry->path_sink &&
+ (int) __entry->path_connect ? '*' : ' ',
+ __get_str(wname), __get_str(pname), __get_str(psname))
+);
+
+TRACE_EVENT(snd_soc_dapm_input_path,
+
+ TP_PROTO(struct snd_soc_dapm_widget *widget,
+ struct snd_soc_dapm_path *path),
+
+ TP_ARGS(widget, path),
+
+ TP_STRUCT__entry(
+ __string( wname, widget->name )
+ __string( pname, path->name ? path->name : DAPM_DIRECT)
+ __string( psname, path->source->name )
+ __field( int, path_source )
+ __field( int, path_connect )
+ ),
+
+ TP_fast_assign(
+ __assign_str(wname, widget->name);
+ __assign_str(pname, path->name ? path->name : DAPM_DIRECT);
+ __assign_str(psname, path->source->name);
+ __entry->path_connect = path->connect;
+ __entry->path_source = (long)path->source;
+ ),
+
+ TP_printk("%c%s <- %s <- %s\n",
+ (int) __entry->path_source &&
+ (int) __entry->path_connect ? '*' : ' ',
+ __get_str(wname), __get_str(pname), __get_str(psname))
+);
+
+TRACE_EVENT(snd_soc_dapm_connected,
+
+ TP_PROTO(int paths, int stream),
+
+ TP_ARGS(paths, stream),
+
+ TP_STRUCT__entry(
+ __field( int, paths )
+ __field( int, stream )
+ ),
+
+ TP_fast_assign(
+ __entry->paths = paths;
+ __entry->stream = stream;
+ ),
+
+ TP_printk("%s: found %d paths\n",
+ __entry->stream ? "capture" : "playback", __entry->paths)
+);
+
TRACE_EVENT(snd_soc_jack_irq,
TP_PROTO(const char *name),
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index cae9a94f025d..0c9783841a30 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -65,6 +65,40 @@ TRACE_EVENT(machine_suspend,
TP_printk("state=%lu", (unsigned long)__entry->state)
);
+DECLARE_EVENT_CLASS(wakeup_source,
+
+ TP_PROTO(const char *name, unsigned int state),
+
+ TP_ARGS(name, state),
+
+ TP_STRUCT__entry(
+ __string( name, name )
+ __field( u64, state )
+ ),
+
+ TP_fast_assign(
+ __assign_str(name, name);
+ __entry->state = state;
+ ),
+
+ TP_printk("%s state=0x%lx", __get_str(name),
+ (unsigned long)__entry->state)
+);
+
+DEFINE_EVENT(wakeup_source, wakeup_source_activate,
+
+ TP_PROTO(const char *name, unsigned int state),
+
+ TP_ARGS(name, state)
+);
+
+DEFINE_EVENT(wakeup_source, wakeup_source_deactivate,
+
+ TP_PROTO(const char *name, unsigned int state),
+
+ TP_ARGS(name, state)
+);
+
#ifdef CONFIG_EVENT_POWER_TRACING_DEPRECATED
/*
diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h
index 337099783f37..1480900c511c 100644
--- a/include/trace/events/rcu.h
+++ b/include/trace/events/rcu.h
@@ -292,6 +292,8 @@ TRACE_EVENT(rcu_dyntick,
* "More callbacks": Still more callbacks, try again to clear them out.
* "Callbacks drained": All callbacks processed, off to dyntick idle!
* "Timer": Timer fired to cause CPU to continue processing callbacks.
+ * "Demigrate": Timer fired on wrong CPU, woke up correct CPU.
+ * "Cleanup after idle": Idle exited, timer canceled.
*/
TRACE_EVENT(rcu_prep_idle,
diff --git a/include/trace/events/workqueue.h b/include/trace/events/workqueue.h
index 7d497291c85d..4018f5058f27 100644
--- a/include/trace/events/workqueue.h
+++ b/include/trace/events/workqueue.h
@@ -103,7 +103,7 @@ TRACE_EVENT(workqueue_execute_start,
);
/**
- * workqueue_execute_end - called immediately before the workqueue callback
+ * workqueue_execute_end - called immediately after the workqueue callback
* @work: pointer to struct work_struct
*
* Allows to track workqueue execution.
diff --git a/include/video/omap-panel-nokia-dsi.h b/include/video/omap-panel-nokia-dsi.h
index 7dc71f9c13e6..04219a295539 100644
--- a/include/video/omap-panel-nokia-dsi.h
+++ b/include/video/omap-panel-nokia-dsi.h
@@ -11,6 +11,7 @@ struct omap_dss_device;
* @esd_interval: interval of ESD checks, 0 = disabled (ms)
* @ulps_timeout: time to wait before entering ULPS, 0 = disabled (ms)
* @use_dsi_backlight: true if panel uses DSI command to control backlight
+ * @pin_config: DSI pin configuration
*/
struct nokia_dsi_panel_data {
const char *name;
@@ -24,6 +25,8 @@ struct nokia_dsi_panel_data {
unsigned ulps_timeout;
bool use_dsi_backlight;
+
+ struct omap_dsi_pin_config pin_config;
};
#endif /* __OMAP_NOKIA_DSI_PANEL_H */
diff --git a/include/video/omap-panel-dvi.h b/include/video/omap-panel-tfp410.h
index 87ad567b4229..68c31d79c571 100644
--- a/include/video/omap-panel-dvi.h
+++ b/include/video/omap-panel-tfp410.h
@@ -1,5 +1,5 @@
/*
- * Header for DVI output driver
+ * Header for TFP410 chip driver
*
* Copyright (C) 2011 Texas Instruments Inc
* Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
@@ -17,21 +17,19 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __OMAP_PANEL_DVI_H
-#define __OMAP_PANEL_DVI_H
+#ifndef __OMAP_PANEL_TFP410_H
+#define __OMAP_PANEL_TFP410_H
struct omap_dss_device;
/**
- * struct panel_dvi_platform_data - panel driver configuration data
- * @platform_enable: platform specific panel enable function
- * @platform_disable: platform specific panel disable function
+ * struct tfp410_platform_data - panel driver configuration data
* @i2c_bus_num: i2c bus id for the panel
+ * @power_down_gpio: gpio number for PD pin (or -1 if not available)
*/
-struct panel_dvi_platform_data {
- int (*platform_enable)(struct omap_dss_device *dssdev);
- void (*platform_disable)(struct omap_dss_device *dssdev);
+struct tfp410_platform_data {
u16 i2c_bus_num;
+ int power_down_gpio;
};
-#endif /* __OMAP_PANEL_DVI_H */
+#endif /* __OMAP_PANEL_TFP410_H */
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 483f67caa7ad..1c46a14341dd 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -468,6 +468,21 @@ struct omap_overlay_manager {
int (*wait_for_vsync)(struct omap_overlay_manager *mgr);
};
+/* 22 pins means 1 clk lane and 10 data lanes */
+#define OMAP_DSS_MAX_DSI_PINS 22
+
+struct omap_dsi_pin_config {
+ int num_pins;
+ /*
+ * pin numbers in the following order:
+ * clk+, clk-
+ * data1+, data1-
+ * data2+, data2-
+ * ...
+ */
+ int pins[OMAP_DSS_MAX_DSI_PINS];
+};
+
struct omap_dss_device {
struct device dev;
@@ -490,17 +505,6 @@ struct omap_dss_device {
} sdi;
struct {
- u8 clk_lane;
- u8 clk_pol;
- u8 data1_lane;
- u8 data1_pol;
- u8 data2_lane;
- u8 data2_pol;
- u8 data3_lane;
- u8 data3_pol;
- u8 data4_lane;
- u8 data4_pol;
-
int module;
bool ext_te;
@@ -687,6 +691,8 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel);
int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
+int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
+ const struct omap_dsi_pin_config *pin_cfg);
int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
diff --git a/include/video/vga.h b/include/video/vga.h
index 2b8691f7d256..cac567f22e62 100644
--- a/include/video/vga.h
+++ b/include/video/vga.h
@@ -19,29 +19,7 @@
#include <linux/types.h>
#include <asm/io.h>
-#ifndef CONFIG_AMIGA
#include <asm/vga.h>
-#else
-/*
- * FIXME
- * Ugh, we don't have PCI space, so map readb() and friends to use Zorro space
- * for MMIO accesses. This should make cirrusfb work again on Amiga
- */
-#undef inb_p
-#undef inw_p
-#undef outb_p
-#undef outw
-#undef readb
-#undef writeb
-#undef writew
-#define inb_p(port) 0
-#define inw_p(port) 0
-#define outb_p(port, val) do { } while (0)
-#define outw(port, val) do { } while (0)
-#define readb z_readb
-#define writeb z_writeb
-#define writew z_writew
-#endif
#include <asm/byteorder.h>
diff --git a/init/Kconfig b/init/Kconfig
index 6cfd71d06463..a30fe085940e 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -27,6 +27,9 @@ config IRQ_WORK
bool
depends on HAVE_IRQ_WORK
+config BUILDTIME_EXTABLE_SORT
+ bool
+
menu "General setup"
config EXPERIMENTAL
@@ -458,6 +461,33 @@ config RCU_FANOUT
Select a specific number if testing RCU itself.
Take the default if unsure.
+config RCU_FANOUT_LEAF
+ int "Tree-based hierarchical RCU leaf-level fanout value"
+ range 2 RCU_FANOUT if 64BIT
+ range 2 RCU_FANOUT if !64BIT
+ depends on TREE_RCU || TREE_PREEMPT_RCU
+ default 16
+ help
+ This option controls the leaf-level fanout of hierarchical
+ implementations of RCU, and allows trading off cache misses
+ against lock contention. Systems that synchronize their
+ scheduling-clock interrupts for energy-efficiency reasons will
+ want the default because the smaller leaf-level fanout keeps
+ lock contention levels acceptably low. Very large systems
+ (hundreds or thousands of CPUs) will instead want to set this
+ value to the maximum value possible in order to reduce the
+ number of cache misses incurred during RCU's grace-period
+ initialization. These systems tend to run CPU-bound, and thus
+ are not helped by synchronized interrupts, and thus tend to
+ skew them, which reduces lock contention enough that large
+ leaf-level fanouts work well.
+
+ Select a specific number if testing RCU itself.
+
+ Select the maximum permissible value for large systems.
+
+ Take the default if unsure.
+
config RCU_FANOUT_EXACT
bool "Disable tree-based hierarchical RCU auto-balancing"
depends on TREE_RCU || TREE_PREEMPT_RCU
@@ -515,10 +545,25 @@ config RCU_BOOST_PRIO
depends on RCU_BOOST
default 1
help
- This option specifies the real-time priority to which preempted
- RCU readers are to be boosted. If you are working with CPU-bound
- real-time applications, you should specify a priority higher then
- the highest-priority CPU-bound application.
+ This option specifies the real-time priority to which long-term
+ preempted RCU readers are to be boosted. If you are working
+ with a real-time application that has one or more CPU-bound
+ threads running at a real-time priority level, you should set
+ RCU_BOOST_PRIO to a priority higher then the highest-priority
+ real-time CPU-bound thread. The default RCU_BOOST_PRIO value
+ of 1 is appropriate in the common case, which is real-time
+ applications that do not have any CPU-bound threads.
+
+ Some real-time applications might not have a single real-time
+ thread that saturates a given CPU, but instead might have
+ multiple real-time threads that, taken together, fully utilize
+ that CPU. In this case, you should set RCU_BOOST_PRIO to
+ a priority higher than the lowest-priority thread that is
+ conspiring to prevent the CPU from running any non-real-time
+ tasks. For example, if one thread at priority 10 and another
+ thread at priority 5 are between themselves fully consuming
+ the CPU time on a given CPU, then RCU_BOOST_PRIO should be
+ set to priority 6 or higher.
Specify the real-time priority, or take the default if unsure.
@@ -1156,7 +1201,7 @@ menu "Kernel Performance Events And Counters"
config PERF_EVENTS
bool "Kernel performance events and counters"
- default y if (PROFILING || PERF_COUNTERS)
+ default y if PROFILING
depends on HAVE_PERF_EVENTS
select ANON_INODES
select IRQ_WORK
@@ -1183,18 +1228,6 @@ config PERF_EVENTS
Say Y if unsure.
-config PERF_COUNTERS
- bool "Kernel performance counters (old config option)"
- depends on HAVE_PERF_EVENTS
- help
- This config has been obsoleted by the PERF_EVENTS
- config option - please see that one for details.
-
- It has no effect on the kernel whether you enable
- it or not, it is a compatibility placeholder.
-
- Say N if unsure.
-
config DEBUG_PERF_USE_VMALLOC
default n
bool "Debug: use vmalloc to back perf mmap() buffers"
diff --git a/init/Makefile b/init/Makefile
index 0bf677aa0872..7bc47ee31c36 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -10,6 +10,10 @@ obj-$(CONFIG_BLK_DEV_INITRD) += initramfs.o
endif
obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o
+ifneq ($(CONFIG_ARCH_INIT_TASK),y)
+obj-y += init_task.o
+endif
+
mounts-y := do_mounts.o
mounts-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o
mounts-$(CONFIG_BLK_DEV_INITRD) += do_mounts_initrd.o
diff --git a/arch/alpha/kernel/init_task.c b/init/init_task.c
index 6f80ca4f9766..8b2f3996b035 100644
--- a/arch/alpha/kernel/init_task.c
+++ b/init/init_task.c
@@ -1,17 +1,24 @@
-#include <linux/mm.h>
-#include <linux/module.h>
+#include <linux/init_task.h>
+#include <linux/export.h>
+#include <linux/mqueue.h>
#include <linux/sched.h>
#include <linux/init.h>
-#include <linux/init_task.h>
#include <linux/fs.h>
-#include <linux/mqueue.h>
-#include <asm/uaccess.h>
+#include <linux/mm.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+
+/* Initial task structure */
struct task_struct init_task = INIT_TASK(init_task);
EXPORT_SYMBOL(init_task);
+/*
+ * Initial thread structure. Alignment of this is handled by a special
+ * linker map entry.
+ */
union thread_union init_thread_union __init_task_data =
{ INIT_THREAD_INFO(init_task) };
diff --git a/init/main.c b/init/main.c
index 44b2433334c7..1ca6b32c4828 100644
--- a/init/main.c
+++ b/init/main.c
@@ -226,7 +226,7 @@ static int __init loglevel(char *str)
early_param("loglevel", loglevel);
/* Change NUL term back to "=", to make "param" the whole string. */
-static int __init repair_env_string(char *param, char *val)
+static int __init repair_env_string(char *param, char *val, const char *unused)
{
if (val) {
/* param=val or param="val"? */
@@ -246,9 +246,9 @@ static int __init repair_env_string(char *param, char *val)
* Unknown boot options get handed to init, unless they look like
* unused parameters (modprobe will find them in /proc/cmdline).
*/
-static int __init unknown_bootoption(char *param, char *val)
+static int __init unknown_bootoption(char *param, char *val, const char *unused)
{
- repair_env_string(param, val);
+ repair_env_string(param, val, unused);
/* Handle obsolete-style parameters */
if (obsolete_checksetup(param))
@@ -385,7 +385,7 @@ static noinline void __init_refok rest_init(void)
}
/* Check for early params. */
-static int __init do_early_param(char *param, char *val)
+static int __init do_early_param(char *param, char *val, const char *unused)
{
const struct obs_kernel_param *p;
@@ -560,9 +560,6 @@ asmlinkage void __init start_kernel(void)
early_boot_irqs_disabled = false;
local_irq_enable();
- /* Interrupts are enabled now so all GFP allocations are safe. */
- gfp_allowed_mask = __GFP_BITS_MASK;
-
kmem_cache_init_late();
/*
@@ -728,14 +725,14 @@ static initcall_t *initcall_levels[] __initdata = {
};
static char *initcall_level_names[] __initdata = {
- "early parameters",
- "core parameters",
- "postcore parameters",
- "arch parameters",
- "subsys parameters",
- "fs parameters",
- "device parameters",
- "late parameters",
+ "early",
+ "core",
+ "postcore",
+ "arch",
+ "subsys",
+ "fs",
+ "device",
+ "late",
};
static void __init do_initcall_level(int level)
@@ -748,7 +745,7 @@ static void __init do_initcall_level(int level)
static_command_line, __start___param,
__stop___param - __start___param,
level, level,
- repair_env_string);
+ &repair_env_string);
for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
do_one_initcall(*fn);
@@ -758,8 +755,13 @@ static void __init do_initcalls(void)
{
int level;
- for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)
+ for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) {
+ pr_info("initlevel:%d=%s, %d registered initcalls\n",
+ level, initcall_level_names[level],
+ (int) (initcall_levels[level+1]
+ - initcall_levels[level]));
do_initcall_level(level);
+ }
}
/*
@@ -842,6 +844,10 @@ static int __init kernel_init(void * unused)
* Wait until kthreadd is all set-up.
*/
wait_for_completion(&kthreadd_done);
+
+ /* Now the scheduler is fully set up and can do blocking allocations */
+ gfp_allowed_mask = __GFP_BITS_MASK;
+
/*
* init can allocate pages on any node
*/
diff --git a/kernel/Makefile b/kernel/Makefile
index cb41b9547c9f..6c07f30fa9b7 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_DEBUG_RT_MUTEXES) += rtmutex-debug.o
obj-$(CONFIG_RT_MUTEX_TESTER) += rtmutex-tester.o
obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_SMP) += smpboot.o
ifneq ($(CONFIG_SMP),y)
obj-y += up.o
endif
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index af1de0f34eae..4b96415527b8 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -67,6 +67,7 @@
#include <linux/syscalls.h>
#include <linux/capability.h>
#include <linux/fs_struct.h>
+#include <linux/compat.h>
#include "audit.h"
@@ -2710,13 +2711,16 @@ void audit_core_dumps(long signr)
audit_log_end(ab);
}
-void __audit_seccomp(unsigned long syscall)
+void __audit_seccomp(unsigned long syscall, long signr, int code)
{
struct audit_buffer *ab;
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
- audit_log_abend(ab, "seccomp", SIGKILL);
+ audit_log_abend(ab, "seccomp", signr);
audit_log_format(ab, " syscall=%ld", syscall);
+ audit_log_format(ab, " compat=%d", is_compat_task());
+ audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current));
+ audit_log_format(ab, " code=0x%x", code);
audit_log_end(ab);
}
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index ed64ccac67c9..ad8eae5bb801 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -60,9 +60,13 @@
#include <linux/eventfd.h>
#include <linux/poll.h>
#include <linux/flex_array.h> /* used in cgroup_attach_proc */
+#include <linux/kthread.h>
#include <linux/atomic.h>
+/* css deactivation bias, makes css->refcnt negative to deny new trygets */
+#define CSS_DEACT_BIAS INT_MIN
+
/*
* cgroup_mutex is the master lock. Any modification to cgroup or its
* hierarchy must be performed while holding it.
@@ -127,6 +131,9 @@ struct cgroupfs_root {
/* A list running through the active hierarchies */
struct list_head root_list;
+ /* All cgroups on this root, cgroup_mutex protected */
+ struct list_head allcg_list;
+
/* Hierarchy-specific flags */
unsigned long flags;
@@ -145,6 +152,15 @@ struct cgroupfs_root {
static struct cgroupfs_root rootnode;
/*
+ * cgroupfs file entry, pointed to from leaf dentry->d_fsdata.
+ */
+struct cfent {
+ struct list_head node;
+ struct dentry *dentry;
+ struct cftype *type;
+};
+
+/*
* CSS ID -- ID per subsys's Cgroup Subsys State(CSS). used only when
* cgroup_subsys->use_id != 0.
*/
@@ -239,6 +255,14 @@ int cgroup_lock_is_held(void)
EXPORT_SYMBOL_GPL(cgroup_lock_is_held);
+/* the current nr of refs, always >= 0 whether @css is deactivated or not */
+static int css_refcnt(struct cgroup_subsys_state *css)
+{
+ int v = atomic_read(&css->refcnt);
+
+ return v >= 0 ? v : v - CSS_DEACT_BIAS;
+}
+
/* convenient tests for these bits */
inline int cgroup_is_removed(const struct cgroup *cgrp)
{
@@ -279,6 +303,21 @@ list_for_each_entry(_ss, &_root->subsys_list, sibling)
#define for_each_active_root(_root) \
list_for_each_entry(_root, &roots, root_list)
+static inline struct cgroup *__d_cgrp(struct dentry *dentry)
+{
+ return dentry->d_fsdata;
+}
+
+static inline struct cfent *__d_cfe(struct dentry *dentry)
+{
+ return dentry->d_fsdata;
+}
+
+static inline struct cftype *__d_cft(struct dentry *dentry)
+{
+ return __d_cfe(dentry)->type;
+}
+
/* the list of cgroups eligible for automatic release. Protected by
* release_list_lock */
static LIST_HEAD(release_list);
@@ -816,12 +855,17 @@ static int cgroup_call_pre_destroy(struct cgroup *cgrp)
struct cgroup_subsys *ss;
int ret = 0;
- for_each_subsys(cgrp->root, ss)
- if (ss->pre_destroy) {
- ret = ss->pre_destroy(cgrp);
- if (ret)
- break;
+ for_each_subsys(cgrp->root, ss) {
+ if (!ss->pre_destroy)
+ continue;
+
+ ret = ss->pre_destroy(cgrp);
+ if (ret) {
+ /* ->pre_destroy() failure is being deprecated */
+ WARN_ON_ONCE(!ss->__DEPRECATED_clear_css_refs);
+ break;
}
+ }
return ret;
}
@@ -864,6 +908,14 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
BUG_ON(!list_empty(&cgrp->pidlists));
kfree_rcu(cgrp, rcu_head);
+ } else {
+ struct cfent *cfe = __d_cfe(dentry);
+ struct cgroup *cgrp = dentry->d_parent->d_fsdata;
+
+ WARN_ONCE(!list_empty(&cfe->node) &&
+ cgrp != &cgrp->root->top_cgroup,
+ "cfe still linked for %s\n", cfe->type->name);
+ kfree(cfe);
}
iput(inode);
}
@@ -882,34 +934,36 @@ static void remove_dir(struct dentry *d)
dput(parent);
}
-static void cgroup_clear_directory(struct dentry *dentry)
-{
- struct list_head *node;
-
- BUG_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
- spin_lock(&dentry->d_lock);
- node = dentry->d_subdirs.next;
- while (node != &dentry->d_subdirs) {
- struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
-
- spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
- list_del_init(node);
- if (d->d_inode) {
- /* This should never be called on a cgroup
- * directory with child cgroups */
- BUG_ON(d->d_inode->i_mode & S_IFDIR);
- dget_dlock(d);
- spin_unlock(&d->d_lock);
- spin_unlock(&dentry->d_lock);
- d_delete(d);
- simple_unlink(dentry->d_inode, d);
- dput(d);
- spin_lock(&dentry->d_lock);
- } else
- spin_unlock(&d->d_lock);
- node = dentry->d_subdirs.next;
+static int cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft)
+{
+ struct cfent *cfe;
+
+ lockdep_assert_held(&cgrp->dentry->d_inode->i_mutex);
+ lockdep_assert_held(&cgroup_mutex);
+
+ list_for_each_entry(cfe, &cgrp->files, node) {
+ struct dentry *d = cfe->dentry;
+
+ if (cft && cfe->type != cft)
+ continue;
+
+ dget(d);
+ d_delete(d);
+ simple_unlink(d->d_inode, d);
+ list_del_init(&cfe->node);
+ dput(d);
+
+ return 0;
}
- spin_unlock(&dentry->d_lock);
+ return -ENOENT;
+}
+
+static void cgroup_clear_directory(struct dentry *dir)
+{
+ struct cgroup *cgrp = __d_cgrp(dir);
+
+ while (!list_empty(&cgrp->files))
+ cgroup_rm_file(cgrp, NULL);
}
/*
@@ -1294,6 +1348,11 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
if (ret)
goto out_unlock;
+ /* See feature-removal-schedule.txt */
+ if (opts.subsys_bits != root->actual_subsys_bits || opts.release_agent)
+ pr_warning("cgroup: option changes via remount are deprecated (pid=%d comm=%s)\n",
+ task_tgid_nr(current), current->comm);
+
/* Don't allow flags or name to change at remount */
if (opts.flags != root->flags ||
(opts.name && strcmp(opts.name, root->name))) {
@@ -1308,7 +1367,8 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
goto out_unlock;
}
- /* (re)populate subsystem files */
+ /* clear out any existing files and repopulate subsystem files */
+ cgroup_clear_directory(cgrp->dentry);
cgroup_populate_dir(cgrp);
if (opts.release_agent)
@@ -1333,6 +1393,7 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp)
{
INIT_LIST_HEAD(&cgrp->sibling);
INIT_LIST_HEAD(&cgrp->children);
+ INIT_LIST_HEAD(&cgrp->files);
INIT_LIST_HEAD(&cgrp->css_sets);
INIT_LIST_HEAD(&cgrp->release_list);
INIT_LIST_HEAD(&cgrp->pidlists);
@@ -1344,11 +1405,14 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp)
static void init_cgroup_root(struct cgroupfs_root *root)
{
struct cgroup *cgrp = &root->top_cgroup;
+
INIT_LIST_HEAD(&root->subsys_list);
INIT_LIST_HEAD(&root->root_list);
+ INIT_LIST_HEAD(&root->allcg_list);
root->number_of_cgroups = 1;
cgrp->root = root;
cgrp->top_cgroup = cgrp;
+ list_add_tail(&cgrp->allcg_node, &root->allcg_list);
init_cgroup_housekeeping(cgrp);
}
@@ -1692,16 +1756,6 @@ static struct file_system_type cgroup_fs_type = {
static struct kobject *cgroup_kobj;
-static inline struct cgroup *__d_cgrp(struct dentry *dentry)
-{
- return dentry->d_fsdata;
-}
-
-static inline struct cftype *__d_cft(struct dentry *dentry)
-{
- return dentry->d_fsdata;
-}
-
/**
* cgroup_path - generate the path of a cgroup
* @cgrp: the cgroup in question
@@ -2172,6 +2226,18 @@ retry_find_task:
if (threadgroup)
tsk = tsk->group_leader;
+
+ /*
+ * Workqueue threads may acquire PF_THREAD_BOUND and become
+ * trapped in a cpuset, or RT worker may be born in a cgroup
+ * with no rt_runtime allocated. Just say no.
+ */
+ if (tsk == kthreadd_task || (tsk->flags & PF_THREAD_BOUND)) {
+ ret = -EINVAL;
+ rcu_read_unlock();
+ goto out_unlock_cgroup;
+ }
+
get_task_struct(tsk);
rcu_read_unlock();
@@ -2603,50 +2669,191 @@ static umode_t cgroup_file_mode(const struct cftype *cft)
return mode;
}
-int cgroup_add_file(struct cgroup *cgrp,
- struct cgroup_subsys *subsys,
- const struct cftype *cft)
+static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys,
+ const struct cftype *cft)
{
struct dentry *dir = cgrp->dentry;
+ struct cgroup *parent = __d_cgrp(dir);
struct dentry *dentry;
+ struct cfent *cfe;
int error;
umode_t mode;
-
char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 };
+
+ /* does @cft->flags tell us to skip creation on @cgrp? */
+ if ((cft->flags & CFTYPE_NOT_ON_ROOT) && !cgrp->parent)
+ return 0;
+ if ((cft->flags & CFTYPE_ONLY_ON_ROOT) && cgrp->parent)
+ return 0;
+
if (subsys && !test_bit(ROOT_NOPREFIX, &cgrp->root->flags)) {
strcpy(name, subsys->name);
strcat(name, ".");
}
strcat(name, cft->name);
+
BUG_ON(!mutex_is_locked(&dir->d_inode->i_mutex));
+
+ cfe = kzalloc(sizeof(*cfe), GFP_KERNEL);
+ if (!cfe)
+ return -ENOMEM;
+
dentry = lookup_one_len(name, dir, strlen(name));
- if (!IS_ERR(dentry)) {
- mode = cgroup_file_mode(cft);
- error = cgroup_create_file(dentry, mode | S_IFREG,
- cgrp->root->sb);
- if (!error)
- dentry->d_fsdata = (void *)cft;
- dput(dentry);
- } else
+ if (IS_ERR(dentry)) {
error = PTR_ERR(dentry);
+ goto out;
+ }
+
+ mode = cgroup_file_mode(cft);
+ error = cgroup_create_file(dentry, mode | S_IFREG, cgrp->root->sb);
+ if (!error) {
+ cfe->type = (void *)cft;
+ cfe->dentry = dentry;
+ dentry->d_fsdata = cfe;
+ list_add_tail(&cfe->node, &parent->files);
+ cfe = NULL;
+ }
+ dput(dentry);
+out:
+ kfree(cfe);
return error;
}
-EXPORT_SYMBOL_GPL(cgroup_add_file);
-int cgroup_add_files(struct cgroup *cgrp,
- struct cgroup_subsys *subsys,
- const struct cftype cft[],
- int count)
+static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
+ const struct cftype cfts[], bool is_add)
{
- int i, err;
- for (i = 0; i < count; i++) {
- err = cgroup_add_file(cgrp, subsys, &cft[i]);
- if (err)
- return err;
+ const struct cftype *cft;
+ int err, ret = 0;
+
+ for (cft = cfts; cft->name[0] != '\0'; cft++) {
+ if (is_add)
+ err = cgroup_add_file(cgrp, subsys, cft);
+ else
+ err = cgroup_rm_file(cgrp, cft);
+ if (err) {
+ pr_warning("cgroup_addrm_files: failed to %s %s, err=%d\n",
+ is_add ? "add" : "remove", cft->name, err);
+ ret = err;
+ }
+ }
+ return ret;
+}
+
+static DEFINE_MUTEX(cgroup_cft_mutex);
+
+static void cgroup_cfts_prepare(void)
+ __acquires(&cgroup_cft_mutex) __acquires(&cgroup_mutex)
+{
+ /*
+ * Thanks to the entanglement with vfs inode locking, we can't walk
+ * the existing cgroups under cgroup_mutex and create files.
+ * Instead, we increment reference on all cgroups and build list of
+ * them using @cgrp->cft_q_node. Grab cgroup_cft_mutex to ensure
+ * exclusive access to the field.
+ */
+ mutex_lock(&cgroup_cft_mutex);
+ mutex_lock(&cgroup_mutex);
+}
+
+static void cgroup_cfts_commit(struct cgroup_subsys *ss,
+ const struct cftype *cfts, bool is_add)
+ __releases(&cgroup_mutex) __releases(&cgroup_cft_mutex)
+{
+ LIST_HEAD(pending);
+ struct cgroup *cgrp, *n;
+
+ /* %NULL @cfts indicates abort and don't bother if @ss isn't attached */
+ if (cfts && ss->root != &rootnode) {
+ list_for_each_entry(cgrp, &ss->root->allcg_list, allcg_node) {
+ dget(cgrp->dentry);
+ list_add_tail(&cgrp->cft_q_node, &pending);
+ }
+ }
+
+ mutex_unlock(&cgroup_mutex);
+
+ /*
+ * All new cgroups will see @cfts update on @ss->cftsets. Add/rm
+ * files for all cgroups which were created before.
+ */
+ list_for_each_entry_safe(cgrp, n, &pending, cft_q_node) {
+ struct inode *inode = cgrp->dentry->d_inode;
+
+ mutex_lock(&inode->i_mutex);
+ mutex_lock(&cgroup_mutex);
+ if (!cgroup_is_removed(cgrp))
+ cgroup_addrm_files(cgrp, ss, cfts, is_add);
+ mutex_unlock(&cgroup_mutex);
+ mutex_unlock(&inode->i_mutex);
+
+ list_del_init(&cgrp->cft_q_node);
+ dput(cgrp->dentry);
}
+
+ mutex_unlock(&cgroup_cft_mutex);
+}
+
+/**
+ * cgroup_add_cftypes - add an array of cftypes to a subsystem
+ * @ss: target cgroup subsystem
+ * @cfts: zero-length name terminated array of cftypes
+ *
+ * Register @cfts to @ss. Files described by @cfts are created for all
+ * existing cgroups to which @ss is attached and all future cgroups will
+ * have them too. This function can be called anytime whether @ss is
+ * attached or not.
+ *
+ * Returns 0 on successful registration, -errno on failure. Note that this
+ * function currently returns 0 as long as @cfts registration is successful
+ * even if some file creation attempts on existing cgroups fail.
+ */
+int cgroup_add_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts)
+{
+ struct cftype_set *set;
+
+ set = kzalloc(sizeof(*set), GFP_KERNEL);
+ if (!set)
+ return -ENOMEM;
+
+ cgroup_cfts_prepare();
+ set->cfts = cfts;
+ list_add_tail(&set->node, &ss->cftsets);
+ cgroup_cfts_commit(ss, cfts, true);
+
return 0;
}
-EXPORT_SYMBOL_GPL(cgroup_add_files);
+EXPORT_SYMBOL_GPL(cgroup_add_cftypes);
+
+/**
+ * cgroup_rm_cftypes - remove an array of cftypes from a subsystem
+ * @ss: target cgroup subsystem
+ * @cfts: zero-length name terminated array of cftypes
+ *
+ * Unregister @cfts from @ss. Files described by @cfts are removed from
+ * all existing cgroups to which @ss is attached and all future cgroups
+ * won't have them either. This function can be called anytime whether @ss
+ * is attached or not.
+ *
+ * Returns 0 on successful unregistration, -ENOENT if @cfts is not
+ * registered with @ss.
+ */
+int cgroup_rm_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts)
+{
+ struct cftype_set *set;
+
+ cgroup_cfts_prepare();
+
+ list_for_each_entry(set, &ss->cftsets, node) {
+ if (set->cfts == cfts) {
+ list_del_init(&set->node);
+ cgroup_cfts_commit(ss, cfts, false);
+ return 0;
+ }
+ }
+
+ cgroup_cfts_commit(ss, NULL, false);
+ return -ENOENT;
+}
/**
* cgroup_task_count - count the number of tasks in a cgroup.
@@ -3625,13 +3832,14 @@ static struct cftype files[] = {
.read_u64 = cgroup_clone_children_read,
.write_u64 = cgroup_clone_children_write,
},
-};
-
-static struct cftype cft_release_agent = {
- .name = "release_agent",
- .read_seq_string = cgroup_release_agent_show,
- .write_string = cgroup_release_agent_write,
- .max_write_len = PATH_MAX,
+ {
+ .name = "release_agent",
+ .flags = CFTYPE_ONLY_ON_ROOT,
+ .read_seq_string = cgroup_release_agent_show,
+ .write_string = cgroup_release_agent_write,
+ .max_write_len = PATH_MAX,
+ },
+ { } /* terminate */
};
static int cgroup_populate_dir(struct cgroup *cgrp)
@@ -3639,22 +3847,18 @@ static int cgroup_populate_dir(struct cgroup *cgrp)
int err;
struct cgroup_subsys *ss;
- /* First clear out any existing files */
- cgroup_clear_directory(cgrp->dentry);
-
- err = cgroup_add_files(cgrp, NULL, files, ARRAY_SIZE(files));
+ err = cgroup_addrm_files(cgrp, NULL, files, true);
if (err < 0)
return err;
- if (cgrp == cgrp->top_cgroup) {
- if ((err = cgroup_add_file(cgrp, NULL, &cft_release_agent)) < 0)
- return err;
- }
-
+ /* process cftsets of each subsystem */
for_each_subsys(cgrp->root, ss) {
- if (ss->populate && (err = ss->populate(ss, cgrp)) < 0)
- return err;
+ struct cftype_set *set;
+
+ list_for_each_entry(set, &ss->cftsets, node)
+ cgroup_addrm_files(cgrp, ss, set->cfts, true);
}
+
/* This cgroup is ready now */
for_each_subsys(cgrp->root, ss) {
struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
@@ -3670,6 +3874,14 @@ static int cgroup_populate_dir(struct cgroup *cgrp)
return 0;
}
+static void css_dput_fn(struct work_struct *work)
+{
+ struct cgroup_subsys_state *css =
+ container_of(work, struct cgroup_subsys_state, dput_work);
+
+ dput(css->cgroup->dentry);
+}
+
static void init_cgroup_css(struct cgroup_subsys_state *css,
struct cgroup_subsys *ss,
struct cgroup *cgrp)
@@ -3682,6 +3894,16 @@ static void init_cgroup_css(struct cgroup_subsys_state *css,
set_bit(CSS_ROOT, &css->flags);
BUG_ON(cgrp->subsys[ss->subsys_id]);
cgrp->subsys[ss->subsys_id] = css;
+
+ /*
+ * If !clear_css_refs, css holds an extra ref to @cgrp->dentry
+ * which is put on the last css_put(). dput() requires process
+ * context, which css_put() may be called without. @css->dput_work
+ * will be used to invoke dput() asynchronously from css_put().
+ */
+ INIT_WORK(&css->dput_work, css_dput_fn);
+ if (ss->__DEPRECATED_clear_css_refs)
+ set_bit(CSS_CLEAR_CSS_REFS, &css->flags);
}
static void cgroup_lock_hierarchy(struct cgroupfs_root *root)
@@ -3784,9 +4006,16 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
if (err < 0)
goto err_remove;
+ /* If !clear_css_refs, each css holds a ref to the cgroup's dentry */
+ for_each_subsys(root, ss)
+ if (!ss->__DEPRECATED_clear_css_refs)
+ dget(dentry);
+
/* The cgroup directory was pre-locked for us */
BUG_ON(!mutex_is_locked(&cgrp->dentry->d_inode->i_mutex));
+ list_add_tail(&cgrp->allcg_node, &root->allcg_list);
+
err = cgroup_populate_dir(cgrp);
/* If err < 0, we have a half-filled directory - oh well ;) */
@@ -3826,18 +4055,19 @@ static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
return cgroup_create(c_parent, dentry, mode | S_IFDIR);
}
+/*
+ * Check the reference count on each subsystem. Since we already
+ * established that there are no tasks in the cgroup, if the css refcount
+ * is also 1, then there should be no outstanding references, so the
+ * subsystem is safe to destroy. We scan across all subsystems rather than
+ * using the per-hierarchy linked list of mounted subsystems since we can
+ * be called via check_for_release() with no synchronization other than
+ * RCU, and the subsystem linked list isn't RCU-safe.
+ */
static int cgroup_has_css_refs(struct cgroup *cgrp)
{
- /* Check the reference count on each subsystem. Since we
- * already established that there are no tasks in the
- * cgroup, if the css refcount is also 1, then there should
- * be no outstanding references, so the subsystem is safe to
- * destroy. We scan across all subsystems rather than using
- * the per-hierarchy linked list of mounted subsystems since
- * we can be called via check_for_release() with no
- * synchronization other than RCU, and the subsystem linked
- * list isn't RCU-safe */
int i;
+
/*
* We won't need to lock the subsys array, because the subsystems
* we're concerned about aren't going anywhere since our cgroup root
@@ -3846,17 +4076,21 @@ static int cgroup_has_css_refs(struct cgroup *cgrp)
for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
struct cgroup_subsys *ss = subsys[i];
struct cgroup_subsys_state *css;
+
/* Skip subsystems not present or not in this hierarchy */
if (ss == NULL || ss->root != cgrp->root)
continue;
+
css = cgrp->subsys[ss->subsys_id];
- /* When called from check_for_release() it's possible
+ /*
+ * When called from check_for_release() it's possible
* that by this point the cgroup has been removed
* and the css deleted. But a false-positive doesn't
* matter, since it can only happen if the cgroup
* has been deleted and hence no longer needs the
- * release agent to be called anyway. */
- if (css && (atomic_read(&css->refcnt) > 1))
+ * release agent to be called anyway.
+ */
+ if (css && css_refcnt(css) > 1)
return 1;
}
return 0;
@@ -3866,51 +4100,63 @@ static int cgroup_has_css_refs(struct cgroup *cgrp)
* Atomically mark all (or else none) of the cgroup's CSS objects as
* CSS_REMOVED. Return true on success, or false if the cgroup has
* busy subsystems. Call with cgroup_mutex held
+ *
+ * Depending on whether a subsys has __DEPRECATED_clear_css_refs set or
+ * not, cgroup removal behaves differently.
+ *
+ * If clear is set, css refcnt for the subsystem should be zero before
+ * cgroup removal can be committed. This is implemented by
+ * CGRP_WAIT_ON_RMDIR and retry logic around ->pre_destroy(), which may be
+ * called multiple times until all css refcnts reach zero and is allowed to
+ * veto removal on any invocation. This behavior is deprecated and will be
+ * removed as soon as the existing user (memcg) is updated.
+ *
+ * If clear is not set, each css holds an extra reference to the cgroup's
+ * dentry and cgroup removal proceeds regardless of css refs.
+ * ->pre_destroy() will be called at least once and is not allowed to fail.
+ * On the last put of each css, whenever that may be, the extra dentry ref
+ * is put so that dentry destruction happens only after all css's are
+ * released.
*/
-
static int cgroup_clear_css_refs(struct cgroup *cgrp)
{
struct cgroup_subsys *ss;
unsigned long flags;
bool failed = false;
+
local_irq_save(flags);
+
+ /*
+ * Block new css_tryget() by deactivating refcnt. If all refcnts
+ * for subsystems w/ clear_css_refs set were 1 at the moment of
+ * deactivation, we succeeded.
+ */
for_each_subsys(cgrp->root, ss) {
struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
- int refcnt;
- while (1) {
- /* We can only remove a CSS with a refcnt==1 */
- refcnt = atomic_read(&css->refcnt);
- if (refcnt > 1) {
- failed = true;
- goto done;
- }
- BUG_ON(!refcnt);
- /*
- * Drop the refcnt to 0 while we check other
- * subsystems. This will cause any racing
- * css_tryget() to spin until we set the
- * CSS_REMOVED bits or abort
- */
- if (atomic_cmpxchg(&css->refcnt, refcnt, 0) == refcnt)
- break;
- cpu_relax();
- }
+
+ WARN_ON(atomic_read(&css->refcnt) < 0);
+ atomic_add(CSS_DEACT_BIAS, &css->refcnt);
+
+ if (ss->__DEPRECATED_clear_css_refs)
+ failed |= css_refcnt(css) != 1;
}
- done:
+
+ /*
+ * If succeeded, set REMOVED and put all the base refs; otherwise,
+ * restore refcnts to positive values. Either way, all in-progress
+ * css_tryget() will be released.
+ */
for_each_subsys(cgrp->root, ss) {
struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
- if (failed) {
- /*
- * Restore old refcnt if we previously managed
- * to clear it from 1 to 0
- */
- if (!atomic_read(&css->refcnt))
- atomic_set(&css->refcnt, 1);
- } else {
- /* Commit the fact that the CSS is removed */
+
+ if (!failed) {
set_bit(CSS_REMOVED, &css->flags);
+ css_put(css);
+ } else {
+ atomic_sub(CSS_DEACT_BIAS, &css->refcnt);
}
}
+
local_irq_restore(flags);
return !failed;
}
@@ -3995,6 +4241,8 @@ again:
list_del_init(&cgrp->sibling);
cgroup_unlock_hierarchy(cgrp->root);
+ list_del_init(&cgrp->allcg_node);
+
d = dget(cgrp->dentry);
cgroup_d_remove_dir(d);
@@ -4021,12 +4269,29 @@ again:
return 0;
}
+static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss)
+{
+ INIT_LIST_HEAD(&ss->cftsets);
+
+ /*
+ * base_cftset is embedded in subsys itself, no need to worry about
+ * deregistration.
+ */
+ if (ss->base_cftypes) {
+ ss->base_cftset.cfts = ss->base_cftypes;
+ list_add_tail(&ss->base_cftset.node, &ss->cftsets);
+ }
+}
+
static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
{
struct cgroup_subsys_state *css;
printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name);
+ /* init base cftset */
+ cgroup_init_cftsets(ss);
+
/* Create the top cgroup state for this subsystem */
list_add(&ss->sibling, &rootnode.subsys_list);
ss->root = &rootnode;
@@ -4096,6 +4361,9 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
return 0;
}
+ /* init base cftset */
+ cgroup_init_cftsets(ss);
+
/*
* need to register a subsys id before anything else - for example,
* init_cgroup_css needs it.
@@ -4685,21 +4953,41 @@ static void check_for_release(struct cgroup *cgrp)
}
/* Caller must verify that the css is not for root cgroup */
-void __css_put(struct cgroup_subsys_state *css, int count)
+bool __css_tryget(struct cgroup_subsys_state *css)
+{
+ do {
+ int v = css_refcnt(css);
+
+ if (atomic_cmpxchg(&css->refcnt, v, v + 1) == v)
+ return true;
+ cpu_relax();
+ } while (!test_bit(CSS_REMOVED, &css->flags));
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(__css_tryget);
+
+/* Caller must verify that the css is not for root cgroup */
+void __css_put(struct cgroup_subsys_state *css)
{
struct cgroup *cgrp = css->cgroup;
- int val;
+
rcu_read_lock();
- val = atomic_sub_return(count, &css->refcnt);
- if (val == 1) {
+ atomic_dec(&css->refcnt);
+ switch (css_refcnt(css)) {
+ case 1:
if (notify_on_release(cgrp)) {
set_bit(CGRP_RELEASABLE, &cgrp->flags);
check_for_release(cgrp);
}
cgroup_wakeup_rmdir_waiter(cgrp);
+ break;
+ case 0:
+ if (!test_bit(CSS_CLEAR_CSS_REFS, &css->flags))
+ schedule_work(&css->dput_work);
+ break;
}
rcu_read_unlock();
- WARN_ON_ONCE(val < 1);
}
EXPORT_SYMBOL_GPL(__css_put);
@@ -4818,7 +5106,7 @@ unsigned short css_id(struct cgroup_subsys_state *css)
* on this or this is under rcu_read_lock(). Once css->id is allocated,
* it's unchanged until freed.
*/
- cssid = rcu_dereference_check(css->id, atomic_read(&css->refcnt));
+ cssid = rcu_dereference_check(css->id, css_refcnt(css));
if (cssid)
return cssid->id;
@@ -4830,7 +5118,7 @@ unsigned short css_depth(struct cgroup_subsys_state *css)
{
struct css_id *cssid;
- cssid = rcu_dereference_check(css->id, atomic_read(&css->refcnt));
+ cssid = rcu_dereference_check(css->id, css_refcnt(css));
if (cssid)
return cssid->depth;
@@ -5211,19 +5499,15 @@ static struct cftype debug_files[] = {
.name = "releasable",
.read_u64 = releasable_read,
},
-};
-static int debug_populate(struct cgroup_subsys *ss, struct cgroup *cont)
-{
- return cgroup_add_files(cont, ss, debug_files,
- ARRAY_SIZE(debug_files));
-}
+ { } /* terminate */
+};
struct cgroup_subsys debug_subsys = {
.name = "debug",
.create = debug_create,
.destroy = debug_destroy,
- .populate = debug_populate,
.subsys_id = debug_subsys_id,
+ .base_cftypes = debug_files,
};
#endif /* CONFIG_CGROUP_DEBUG */
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index f86e93920b62..3649fc6b3eaa 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -358,24 +358,19 @@ static int freezer_write(struct cgroup *cgroup,
static struct cftype files[] = {
{
.name = "state",
+ .flags = CFTYPE_NOT_ON_ROOT,
.read_seq_string = freezer_read,
.write_string = freezer_write,
},
+ { } /* terminate */
};
-static int freezer_populate(struct cgroup_subsys *ss, struct cgroup *cgroup)
-{
- if (!cgroup->parent)
- return 0;
- return cgroup_add_files(cgroup, ss, files, ARRAY_SIZE(files));
-}
-
struct cgroup_subsys freezer_subsys = {
.name = "freezer",
.create = freezer_create,
.destroy = freezer_destroy,
- .populate = freezer_populate,
.subsys_id = freezer_subsys_id,
.can_attach = freezer_can_attach,
.fork = freezer_fork,
+ .base_cftypes = files,
};
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 2060c6e57027..0e6353cf147a 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -17,6 +17,8 @@
#include <linux/gfp.h>
#include <linux/suspend.h>
+#include "smpboot.h"
+
#ifdef CONFIG_SMP
/* Serializes the updates to cpu_online_mask, cpu_present_mask */
static DEFINE_MUTEX(cpu_add_remove_lock);
@@ -295,11 +297,19 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
int ret, nr_calls = 0;
void *hcpu = (void *)(long)cpu;
unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
+ struct task_struct *idle;
if (cpu_online(cpu) || !cpu_present(cpu))
return -EINVAL;
cpu_hotplug_begin();
+
+ idle = idle_thread_get(cpu);
+ if (IS_ERR(idle)) {
+ ret = PTR_ERR(idle);
+ goto out;
+ }
+
ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls);
if (ret) {
nr_calls--;
@@ -309,7 +319,7 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
}
/* Arch-specific enabling code. */
- ret = __cpu_up(cpu);
+ ret = __cpu_up(cpu, idle);
if (ret != 0)
goto out_notify;
BUG_ON(!cpu_online(cpu));
@@ -320,6 +330,7 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
out_notify:
if (ret != 0)
__cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL);
+out:
cpu_hotplug_done();
return ret;
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 14f7070b4ba2..8c8bd652dd12 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1765,28 +1765,17 @@ static struct cftype files[] = {
.write_u64 = cpuset_write_u64,
.private = FILE_SPREAD_SLAB,
},
-};
-
-static struct cftype cft_memory_pressure_enabled = {
- .name = "memory_pressure_enabled",
- .read_u64 = cpuset_read_u64,
- .write_u64 = cpuset_write_u64,
- .private = FILE_MEMORY_PRESSURE_ENABLED,
-};
-static int cpuset_populate(struct cgroup_subsys *ss, struct cgroup *cont)
-{
- int err;
+ {
+ .name = "memory_pressure_enabled",
+ .flags = CFTYPE_ONLY_ON_ROOT,
+ .read_u64 = cpuset_read_u64,
+ .write_u64 = cpuset_write_u64,
+ .private = FILE_MEMORY_PRESSURE_ENABLED,
+ },
- err = cgroup_add_files(cont, ss, files, ARRAY_SIZE(files));
- if (err)
- return err;
- /* memory_pressure_enabled is in root cpuset only */
- if (!cont->parent)
- err = cgroup_add_file(cont, ss,
- &cft_memory_pressure_enabled);
- return err;
-}
+ { } /* terminate */
+};
/*
* post_clone() is called during cgroup_create() when the
@@ -1887,9 +1876,9 @@ struct cgroup_subsys cpuset_subsys = {
.destroy = cpuset_destroy,
.can_attach = cpuset_can_attach,
.attach = cpuset_attach,
- .populate = cpuset_populate,
.post_clone = cpuset_post_clone,
.subsys_id = cpuset_subsys_id,
+ .base_cftypes = files,
.early_init = 1,
};
diff --git a/kernel/events/core.c b/kernel/events/core.c
index fd126f82b57c..5b06cbbf6931 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4957,7 +4957,7 @@ void __perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr)
if (rctx < 0)
return;
- perf_sample_data_init(&data, addr);
+ perf_sample_data_init(&data, addr, 0);
do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, &data, regs);
@@ -5215,7 +5215,7 @@ void perf_tp_event(u64 addr, u64 count, void *record, int entry_size,
.data = record,
};
- perf_sample_data_init(&data, addr);
+ perf_sample_data_init(&data, addr, 0);
data.raw = &raw;
hlist_for_each_entry_rcu(event, node, head, hlist_entry) {
@@ -5318,7 +5318,7 @@ void perf_bp_event(struct perf_event *bp, void *data)
struct perf_sample_data sample;
struct pt_regs *regs = data;
- perf_sample_data_init(&sample, bp->attr.bp_addr);
+ perf_sample_data_init(&sample, bp->attr.bp_addr, 0);
if (!bp->hw.state && !perf_exclude_event(bp, regs))
perf_swevent_event(bp, 1, &sample, regs);
@@ -5344,13 +5344,12 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
event->pmu->read(event);
- perf_sample_data_init(&data, 0);
- data.period = event->hw.last_period;
+ perf_sample_data_init(&data, 0, event->hw.last_period);
regs = get_irq_regs();
if (regs && !perf_exclude_event(event, regs)) {
if (!(event->attr.exclude_idle && is_idle_task(current)))
- if (perf_event_overflow(event, &data, regs))
+ if (__perf_event_overflow(event, 1, &data, regs))
ret = HRTIMER_NORESTART;
}
diff --git a/kernel/extable.c b/kernel/extable.c
index 5339705b8241..fe35a634bf76 100644
--- a/kernel/extable.c
+++ b/kernel/extable.c
@@ -35,10 +35,16 @@ DEFINE_MUTEX(text_mutex);
extern struct exception_table_entry __start___ex_table[];
extern struct exception_table_entry __stop___ex_table[];
+/* Cleared by build time tools if the table is already sorted. */
+u32 __initdata main_extable_sort_needed = 1;
+
/* Sort the kernel's built-in exception table */
void __init sort_main_extable(void)
{
- sort_extable(__start___ex_table, __stop___ex_table);
+ if (main_extable_sort_needed)
+ sort_extable(__start___ex_table, __stop___ex_table);
+ else
+ pr_notice("__ex_table already sorted, skipping sort\n");
}
/* Given an address, look for it in the exception tables. */
diff --git a/kernel/fork.c b/kernel/fork.c
index 687a15d56243..05c813dc9ecc 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -34,6 +34,7 @@
#include <linux/cgroup.h>
#include <linux/security.h>
#include <linux/hugetlb.h>
+#include <linux/seccomp.h>
#include <linux/swap.h>
#include <linux/syscalls.h>
#include <linux/jiffies.h>
@@ -112,32 +113,67 @@ int nr_processes(void)
return total;
}
-#ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
-# define alloc_task_struct_node(node) \
- kmem_cache_alloc_node(task_struct_cachep, GFP_KERNEL, node)
-# define free_task_struct(tsk) \
- kmem_cache_free(task_struct_cachep, (tsk))
+#ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR
static struct kmem_cache *task_struct_cachep;
+
+static inline struct task_struct *alloc_task_struct_node(int node)
+{
+ return kmem_cache_alloc_node(task_struct_cachep, GFP_KERNEL, node);
+}
+
+void __weak arch_release_task_struct(struct task_struct *tsk) { }
+
+static inline void free_task_struct(struct task_struct *tsk)
+{
+ arch_release_task_struct(tsk);
+ kmem_cache_free(task_struct_cachep, tsk);
+}
#endif
-#ifndef __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+#ifndef CONFIG_ARCH_THREAD_INFO_ALLOCATOR
+void __weak arch_release_thread_info(struct thread_info *ti) { }
+
+/*
+ * Allocate pages if THREAD_SIZE is >= PAGE_SIZE, otherwise use a
+ * kmemcache based allocator.
+ */
+# if THREAD_SIZE >= PAGE_SIZE
static struct thread_info *alloc_thread_info_node(struct task_struct *tsk,
int node)
{
-#ifdef CONFIG_DEBUG_STACK_USAGE
- gfp_t mask = GFP_KERNEL | __GFP_ZERO;
-#else
- gfp_t mask = GFP_KERNEL;
-#endif
- struct page *page = alloc_pages_node(node, mask, THREAD_SIZE_ORDER);
+ struct page *page = alloc_pages_node(node, THREADINFO_GFP,
+ THREAD_SIZE_ORDER);
return page ? page_address(page) : NULL;
}
static inline void free_thread_info(struct thread_info *ti)
{
+ arch_release_thread_info(ti);
free_pages((unsigned long)ti, THREAD_SIZE_ORDER);
}
+# else
+static struct kmem_cache *thread_info_cache;
+
+static struct thread_info *alloc_thread_info_node(struct task_struct *tsk,
+ int node)
+{
+ return kmem_cache_alloc_node(thread_info_cache, THREADINFO_GFP, node);
+}
+
+static void free_thread_info(struct thread_info *ti)
+{
+ arch_release_thread_info(ti);
+ kmem_cache_free(thread_info_cache, ti);
+}
+
+void thread_info_cache_init(void)
+{
+ thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
+ THREAD_SIZE, 0, NULL);
+ BUG_ON(thread_info_cache == NULL);
+}
+# endif
#endif
/* SLAB cache for signal_struct structures (tsk->signal) */
@@ -171,6 +207,7 @@ void free_task(struct task_struct *tsk)
free_thread_info(tsk->stack);
rt_mutex_debug_task_free(tsk);
ftrace_graph_exit_task(tsk);
+ put_seccomp_filter(tsk);
free_task_struct(tsk);
}
EXPORT_SYMBOL(free_task);
@@ -204,17 +241,11 @@ void __put_task_struct(struct task_struct *tsk)
}
EXPORT_SYMBOL_GPL(__put_task_struct);
-/*
- * macro override instead of weak attribute alias, to workaround
- * gcc 4.1.0 and 4.1.1 bugs with weak attribute and empty functions.
- */
-#ifndef arch_task_cache_init
-#define arch_task_cache_init()
-#endif
+void __init __weak arch_task_cache_init(void) { }
void __init fork_init(unsigned long mempages)
{
-#ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
+#ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR
#ifndef ARCH_MIN_TASKALIGN
#define ARCH_MIN_TASKALIGN L1_CACHE_BYTES
#endif
@@ -261,8 +292,6 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
int node = tsk_fork_get_node(orig);
int err;
- prepare_to_copy(orig);
-
tsk = alloc_task_struct_node(node);
if (!tsk)
return NULL;
@@ -1163,6 +1192,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
goto fork_out;
ftrace_graph_init_task(p);
+ get_seccomp_filter(p);
rt_mutex_init_task(p);
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index c21449f85a2a..6df614912b9d 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -108,8 +108,10 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
touch_nmi_watchdog();
- if (sysctl_hung_task_panic)
+ if (sysctl_hung_task_panic) {
+ trigger_all_cpu_backtrace();
panic("hung_task: blocked tasks");
+ }
}
/*
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 3914c1e03cff..fc275e4f629b 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -379,8 +379,10 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
* If its disabled or no action available
* keep it masked and get out of here
*/
- if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data)))
+ if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
+ desc->istate |= IRQS_PENDING;
goto out_unlock;
+ }
handle_irq_event(desc);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 89a3ea82569b..bb32326afe87 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -565,8 +565,8 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
* IRQF_TRIGGER_* but the PIC does not support multiple
* flow-types?
*/
- pr_debug("No set_type function for IRQ %d (%s)\n", irq,
- chip ? (chip->name ? : "unknown") : "unknown");
+ pr_debug("genirq: No set_type function for IRQ %d (%s)\n", irq,
+ chip ? (chip->name ? : "unknown") : "unknown");
return 0;
}
@@ -600,7 +600,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
ret = 0;
break;
default:
- pr_err("setting trigger mode %lu for irq %u failed (%pF)\n",
+ pr_err("genirq: Setting trigger mode %lu for irq %u failed (%pF)\n",
flags, irq, chip->irq_set_type);
}
if (unmask)
@@ -837,8 +837,7 @@ void exit_irq_thread(void)
action = kthread_data(tsk);
- printk(KERN_ERR
- "exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
+ pr_err("genirq: exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
tsk->comm ? tsk->comm : "", tsk->pid, action->irq);
desc = irq_to_desc(action->irq);
@@ -878,7 +877,6 @@ static int
__setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
{
struct irqaction *old, **old_ptr;
- const char *old_name = NULL;
unsigned long flags, thread_mask = 0;
int ret, nested, shared = 0;
cpumask_var_t mask;
@@ -972,10 +970,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
*/
if (!((old->flags & new->flags) & IRQF_SHARED) ||
((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) ||
- ((old->flags ^ new->flags) & IRQF_ONESHOT)) {
- old_name = old->name;
+ ((old->flags ^ new->flags) & IRQF_ONESHOT))
goto mismatch;
- }
/* All handlers must agree on per-cpuness */
if ((old->flags & IRQF_PERCPU) !=
@@ -1031,6 +1027,27 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
* all existing action->thread_mask bits.
*/
new->thread_mask = 1 << ffz(thread_mask);
+
+ } else if (new->handler == irq_default_primary_handler) {
+ /*
+ * The interrupt was requested with handler = NULL, so
+ * we use the default primary handler for it. But it
+ * does not have the oneshot flag set. In combination
+ * with level interrupts this is deadly, because the
+ * default primary handler just wakes the thread, then
+ * the irq lines is reenabled, but the device still
+ * has the level irq asserted. Rinse and repeat....
+ *
+ * While this works for edge type interrupts, we play
+ * it safe and reject unconditionally because we can't
+ * say for sure which type this interrupt really
+ * has. The type flags are unreliable as the
+ * underlying chip implementation can override them.
+ */
+ pr_err("genirq: Threaded irq requested with handler=NULL and !ONESHOT for irq %d\n",
+ irq);
+ ret = -EINVAL;
+ goto out_mask;
}
if (!shared) {
@@ -1078,7 +1095,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
if (nmsk != omsk)
/* hope the handler works with current trigger mode */
- pr_warning("IRQ %d uses trigger mode %u; requested %u\n",
+ pr_warning("genirq: irq %d uses trigger mode %u; requested %u\n",
irq, nmsk, omsk);
}
@@ -1115,14 +1132,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
return 0;
mismatch:
-#ifdef CONFIG_DEBUG_SHIRQ
if (!(new->flags & IRQF_PROBE_SHARED)) {
- printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
- if (old_name)
- printk(KERN_ERR "current handler: %s\n", old_name);
+ pr_err("genirq: Flags mismatch irq %d. %08x (%s) vs. %08x (%s)\n",
+ irq, new->flags, new->name, old->flags, old->name);
+#ifdef CONFIG_DEBUG_SHIRQ
dump_stack();
- }
#endif
+ }
ret = -EBUSY;
out_mask:
@@ -1204,12 +1220,6 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
/* Found it - now remove it from the list of entries: */
*action_ptr = action->next;
- /* Currently used only by UML, might disappear one day: */
-#ifdef CONFIG_IRQ_RELEASE_METHOD
- if (desc->irq_data.chip->release)
- desc->irq_data.chip->release(irq, dev_id);
-#endif
-
/* If this was the last handler, shut down the IRQ line: */
if (!desc->action)
irq_shutdown(desc);
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c
index 15e53b1766a6..cb228bf21760 100644
--- a/kernel/irq/pm.c
+++ b/kernel/irq/pm.c
@@ -103,8 +103,13 @@ int check_wakeup_irqs(void)
int irq;
for_each_irq_desc(irq, desc) {
+ /*
+ * Only interrupts which are marked as wakeup source
+ * and have not been disabled before the suspend check
+ * can abort suspend.
+ */
if (irqd_is_wakeup_set(&desc->irq_data)) {
- if (desc->istate & IRQS_PENDING)
+ if (desc->depth == 1 && desc->istate & IRQS_PENDING)
return -EBUSY;
continue;
}
diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
index 14dd5761e8c9..6454db7b6a4d 100644
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -58,10 +58,13 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq)
/*
* We do not resend level type interrupts. Level type
* interrupts are resent by hardware when they are still
- * active.
+ * active. Clear the pending bit so suspend/resume does not
+ * get confused.
*/
- if (irq_settings_is_level(desc))
+ if (irq_settings_is_level(desc)) {
+ desc->istate &= ~IRQS_PENDING;
return;
+ }
if (desc->istate & IRQS_REPLAY)
return;
if (desc->istate & IRQS_PENDING) {
diff --git a/kernel/module.c b/kernel/module.c
index 78ac6ec1e425..a4e60973ca73 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2953,7 +2953,7 @@ static struct module *load_module(void __user *umod,
/* Module is ready to execute: parsing args may do that. */
err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
- -32768, 32767, NULL);
+ -32768, 32767, &ddebug_dyndbg_module_param_cb);
if (err < 0)
goto unlink;
diff --git a/kernel/params.c b/kernel/params.c
index f37d82631347..ed35345be536 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -85,11 +85,13 @@ bool parameq(const char *a, const char *b)
static int parse_one(char *param,
char *val,
+ const char *doing,
const struct kernel_param *params,
unsigned num_params,
s16 min_level,
s16 max_level,
- int (*handle_unknown)(char *param, char *val))
+ int (*handle_unknown)(char *param, char *val,
+ const char *doing))
{
unsigned int i;
int err;
@@ -104,8 +106,8 @@ static int parse_one(char *param,
if (!val && params[i].ops->set != param_set_bool
&& params[i].ops->set != param_set_bint)
return -EINVAL;
- pr_debug("They are equal! Calling %p\n",
- params[i].ops->set);
+ pr_debug("handling %s with %p\n", param,
+ params[i].ops->set);
mutex_lock(&param_lock);
err = params[i].ops->set(val, &params[i]);
mutex_unlock(&param_lock);
@@ -114,11 +116,11 @@ static int parse_one(char *param,
}
if (handle_unknown) {
- pr_debug("Unknown argument: calling %p\n", handle_unknown);
- return handle_unknown(param, val);
+ pr_debug("doing %s: %s='%s'\n", doing, param, val);
+ return handle_unknown(param, val, doing);
}
- pr_debug("Unknown argument `%s'\n", param);
+ pr_debug("Unknown argument '%s'\n", param);
return -ENOENT;
}
@@ -175,49 +177,47 @@ static char *next_arg(char *args, char **param, char **val)
}
/* Args looks like "foo=bar,bar2 baz=fuz wiz". */
-int parse_args(const char *name,
+int parse_args(const char *doing,
char *args,
const struct kernel_param *params,
unsigned num,
s16 min_level,
s16 max_level,
- int (*unknown)(char *param, char *val))
+ int (*unknown)(char *param, char *val, const char *doing))
{
char *param, *val;
- pr_debug("Parsing ARGS: %s\n", args);
-
/* Chew leading spaces */
args = skip_spaces(args);
+ if (*args)
+ pr_debug("doing %s, parsing ARGS: '%s'\n", doing, args);
+
while (*args) {
int ret;
int irq_was_disabled;
args = next_arg(args, &param, &val);
irq_was_disabled = irqs_disabled();
- ret = parse_one(param, val, params, num,
+ ret = parse_one(param, val, doing, params, num,
min_level, max_level, unknown);
- if (irq_was_disabled && !irqs_disabled()) {
- printk(KERN_WARNING "parse_args(): option '%s' enabled "
- "irq's!\n", param);
- }
+ if (irq_was_disabled && !irqs_disabled())
+ pr_warn("%s: option '%s' enabled irq's!\n",
+ doing, param);
+
switch (ret) {
case -ENOENT:
- printk(KERN_ERR "%s: Unknown parameter `%s'\n",
- name, param);
+ pr_err("%s: Unknown parameter `%s'\n", doing, param);
return ret;
case -ENOSPC:
- printk(KERN_ERR
- "%s: `%s' too large for parameter `%s'\n",
- name, val ?: "", param);
+ pr_err("%s: `%s' too large for parameter `%s'\n",
+ doing, val ?: "", param);
return ret;
case 0:
break;
default:
- printk(KERN_ERR
- "%s: `%s' invalid for parameter `%s'\n",
- name, val ?: "", param);
+ pr_err("%s: `%s' invalid for parameter `%s'\n",
+ doing, val ?: "", param);
return ret;
}
}
@@ -263,8 +263,7 @@ STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, strict_strtoul);
int param_set_charp(const char *val, const struct kernel_param *kp)
{
if (strlen(val) > 1024) {
- printk(KERN_ERR "%s: string parameter too long\n",
- kp->name);
+ pr_err("%s: string parameter too long\n", kp->name);
return -ENOSPC;
}
@@ -400,8 +399,7 @@ static int param_array(const char *name,
int len;
if (*num == max) {
- printk(KERN_ERR "%s: can only take %i arguments\n",
- name, max);
+ pr_err("%s: can only take %i arguments\n", name, max);
return -EINVAL;
}
len = strcspn(val, ",");
@@ -420,8 +418,7 @@ static int param_array(const char *name,
} while (save == ',');
if (*num < min) {
- printk(KERN_ERR "%s: needs at least %i arguments\n",
- name, min);
+ pr_err("%s: needs at least %i arguments\n", name, min);
return -EINVAL;
}
return 0;
@@ -480,7 +477,7 @@ int param_set_copystring(const char *val, const struct kernel_param *kp)
const struct kparam_string *kps = kp->str;
if (strlen(val)+1 > kps->maxlen) {
- printk(KERN_ERR "%s: string doesn't fit in %u chars.\n",
+ pr_err("%s: string doesn't fit in %u chars.\n",
kp->name, kps->maxlen-1);
return -ENOSPC;
}
@@ -750,11 +747,8 @@ static struct module_kobject * __init locate_module_kobject(const char *name)
#endif
if (err) {
kobject_put(&mk->kobj);
- printk(KERN_ERR
- "Module '%s' failed add to sysfs, error number %d\n",
+ pr_crit("Adding module '%s' to sysfs failed (%d), the system may be unstable.\n",
name, err);
- printk(KERN_ERR
- "The system will be unstable now.\n");
return NULL;
}
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index deb5461e3216..8f9b4eb974e0 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -103,6 +103,33 @@ config PM_SLEEP_SMP
select HOTPLUG
select HOTPLUG_CPU
+config PM_AUTOSLEEP
+ bool "Opportunistic sleep"
+ depends on PM_SLEEP
+ default n
+ ---help---
+ Allow the kernel to trigger a system transition into a global sleep
+ state automatically whenever there are no active wakeup sources.
+
+config PM_WAKELOCKS
+ bool "User space wakeup sources interface"
+ depends on PM_SLEEP
+ default n
+ ---help---
+ Allow user space to create, activate and deactivate wakeup source
+ objects with the help of a sysfs-based interface.
+
+config PM_WAKELOCKS_LIMIT
+ int "Maximum number of user space wakeup sources (0 = no limit)"
+ range 0 100000
+ default 100
+ depends on PM_WAKELOCKS
+
+config PM_WAKELOCKS_GC
+ bool "Garbage collector for user space wakeup sources"
+ depends on PM_WAKELOCKS
+ default y
+
config PM_RUNTIME
bool "Run-time PM core functionality"
depends on !IA64_HP_SIM
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 66d808ec5252..29472bff11ef 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -9,5 +9,7 @@ obj-$(CONFIG_SUSPEND) += suspend.o
obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o
obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o \
block_io.o
+obj-$(CONFIG_PM_AUTOSLEEP) += autosleep.o
+obj-$(CONFIG_PM_WAKELOCKS) += wakelock.o
obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
diff --git a/kernel/power/autosleep.c b/kernel/power/autosleep.c
new file mode 100644
index 000000000000..ca304046d9e2
--- /dev/null
+++ b/kernel/power/autosleep.c
@@ -0,0 +1,127 @@
+/*
+ * kernel/power/autosleep.c
+ *
+ * Opportunistic sleep support.
+ *
+ * Copyright (C) 2012 Rafael J. Wysocki <rjw@sisk.pl>
+ */
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/pm_wakeup.h>
+
+#include "power.h"
+
+static suspend_state_t autosleep_state;
+static struct workqueue_struct *autosleep_wq;
+/*
+ * Note: it is only safe to mutex_lock(&autosleep_lock) if a wakeup_source
+ * is active, otherwise a deadlock with try_to_suspend() is possible.
+ * Alternatively mutex_lock_interruptible() can be used. This will then fail
+ * if an auto_sleep cycle tries to freeze processes.
+ */
+static DEFINE_MUTEX(autosleep_lock);
+static struct wakeup_source *autosleep_ws;
+
+static void try_to_suspend(struct work_struct *work)
+{
+ unsigned int initial_count, final_count;
+
+ if (!pm_get_wakeup_count(&initial_count, true))
+ goto out;
+
+ mutex_lock(&autosleep_lock);
+
+ if (!pm_save_wakeup_count(initial_count)) {
+ mutex_unlock(&autosleep_lock);
+ goto out;
+ }
+
+ if (autosleep_state == PM_SUSPEND_ON) {
+ mutex_unlock(&autosleep_lock);
+ return;
+ }
+ if (autosleep_state >= PM_SUSPEND_MAX)
+ hibernate();
+ else
+ pm_suspend(autosleep_state);
+
+ mutex_unlock(&autosleep_lock);
+
+ if (!pm_get_wakeup_count(&final_count, false))
+ goto out;
+
+ /*
+ * If the wakeup occured for an unknown reason, wait to prevent the
+ * system from trying to suspend and waking up in a tight loop.
+ */
+ if (final_count == initial_count)
+ schedule_timeout_uninterruptible(HZ / 2);
+
+ out:
+ queue_up_suspend_work();
+}
+
+static DECLARE_WORK(suspend_work, try_to_suspend);
+
+void queue_up_suspend_work(void)
+{
+ if (!work_pending(&suspend_work) && autosleep_state > PM_SUSPEND_ON)
+ queue_work(autosleep_wq, &suspend_work);
+}
+
+suspend_state_t pm_autosleep_state(void)
+{
+ return autosleep_state;
+}
+
+int pm_autosleep_lock(void)
+{
+ return mutex_lock_interruptible(&autosleep_lock);
+}
+
+void pm_autosleep_unlock(void)
+{
+ mutex_unlock(&autosleep_lock);
+}
+
+int pm_autosleep_set_state(suspend_state_t state)
+{
+
+#ifndef CONFIG_HIBERNATION
+ if (state >= PM_SUSPEND_MAX)
+ return -EINVAL;
+#endif
+
+ __pm_stay_awake(autosleep_ws);
+
+ mutex_lock(&autosleep_lock);
+
+ autosleep_state = state;
+
+ __pm_relax(autosleep_ws);
+
+ if (state > PM_SUSPEND_ON) {
+ pm_wakep_autosleep_enabled(true);
+ queue_up_suspend_work();
+ } else {
+ pm_wakep_autosleep_enabled(false);
+ }
+
+ mutex_unlock(&autosleep_lock);
+ return 0;
+}
+
+int __init pm_autosleep_init(void)
+{
+ autosleep_ws = wakeup_source_register("autosleep");
+ if (!autosleep_ws)
+ return -ENOMEM;
+
+ autosleep_wq = alloc_ordered_workqueue("autosleep", 0);
+ if (autosleep_wq)
+ return 0;
+
+ wakeup_source_unregister(autosleep_ws);
+ return -ENOMEM;
+}
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index e09dfbfeecee..8b53db38a279 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -25,6 +25,8 @@
#include <linux/freezer.h>
#include <linux/gfp.h>
#include <linux/syscore_ops.h>
+#include <linux/ctype.h>
+#include <linux/genhd.h>
#include <scsi/scsi_scan.h>
#include "power.h"
@@ -722,6 +724,17 @@ static int software_resume(void)
/* Check if the device is there */
swsusp_resume_device = name_to_dev_t(resume_file);
+
+ /*
+ * name_to_dev_t is ineffective to verify parition if resume_file is in
+ * integer format. (e.g. major:minor)
+ */
+ if (isdigit(resume_file[0]) && resume_wait) {
+ int partno;
+ while (!get_gendisk(swsusp_resume_device, &partno))
+ msleep(10);
+ }
+
if (!swsusp_resume_device) {
/*
* Some device discovery might still be in progress; we need
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 1c12581f1c62..428f8a034e96 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -269,8 +269,7 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
return (s - buf);
}
-static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
- const char *buf, size_t n)
+static suspend_state_t decode_state(const char *buf, size_t n)
{
#ifdef CONFIG_SUSPEND
suspend_state_t state = PM_SUSPEND_STANDBY;
@@ -278,27 +277,48 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
#endif
char *p;
int len;
- int error = -EINVAL;
p = memchr(buf, '\n', n);
len = p ? p - buf : n;
- /* First, check if we are requested to hibernate */
- if (len == 4 && !strncmp(buf, "disk", len)) {
- error = hibernate();
- goto Exit;
- }
+ /* Check hibernation first. */
+ if (len == 4 && !strncmp(buf, "disk", len))
+ return PM_SUSPEND_MAX;
#ifdef CONFIG_SUSPEND
- for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
- if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) {
- error = pm_suspend(state);
- break;
- }
- }
+ for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++)
+ if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
+ return state;
#endif
- Exit:
+ return PM_SUSPEND_ON;
+}
+
+static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ suspend_state_t state;
+ int error;
+
+ error = pm_autosleep_lock();
+ if (error)
+ return error;
+
+ if (pm_autosleep_state() > PM_SUSPEND_ON) {
+ error = -EBUSY;
+ goto out;
+ }
+
+ state = decode_state(buf, n);
+ if (state < PM_SUSPEND_MAX)
+ error = pm_suspend(state);
+ else if (state == PM_SUSPEND_MAX)
+ error = hibernate();
+ else
+ error = -EINVAL;
+
+ out:
+ pm_autosleep_unlock();
return error ? error : n;
}
@@ -339,7 +359,8 @@ static ssize_t wakeup_count_show(struct kobject *kobj,
{
unsigned int val;
- return pm_get_wakeup_count(&val) ? sprintf(buf, "%u\n", val) : -EINTR;
+ return pm_get_wakeup_count(&val, true) ?
+ sprintf(buf, "%u\n", val) : -EINTR;
}
static ssize_t wakeup_count_store(struct kobject *kobj,
@@ -347,15 +368,106 @@ static ssize_t wakeup_count_store(struct kobject *kobj,
const char *buf, size_t n)
{
unsigned int val;
+ int error;
+
+ error = pm_autosleep_lock();
+ if (error)
+ return error;
+
+ if (pm_autosleep_state() > PM_SUSPEND_ON) {
+ error = -EBUSY;
+ goto out;
+ }
+ error = -EINVAL;
if (sscanf(buf, "%u", &val) == 1) {
if (pm_save_wakeup_count(val))
- return n;
+ error = n;
}
- return -EINVAL;
+
+ out:
+ pm_autosleep_unlock();
+ return error;
}
power_attr(wakeup_count);
+
+#ifdef CONFIG_PM_AUTOSLEEP
+static ssize_t autosleep_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ suspend_state_t state = pm_autosleep_state();
+
+ if (state == PM_SUSPEND_ON)
+ return sprintf(buf, "off\n");
+
+#ifdef CONFIG_SUSPEND
+ if (state < PM_SUSPEND_MAX)
+ return sprintf(buf, "%s\n", valid_state(state) ?
+ pm_states[state] : "error");
+#endif
+#ifdef CONFIG_HIBERNATION
+ return sprintf(buf, "disk\n");
+#else
+ return sprintf(buf, "error");
+#endif
+}
+
+static ssize_t autosleep_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ suspend_state_t state = decode_state(buf, n);
+ int error;
+
+ if (state == PM_SUSPEND_ON
+ && strcmp(buf, "off") && strcmp(buf, "off\n"))
+ return -EINVAL;
+
+ error = pm_autosleep_set_state(state);
+ return error ? error : n;
+}
+
+power_attr(autosleep);
+#endif /* CONFIG_PM_AUTOSLEEP */
+
+#ifdef CONFIG_PM_WAKELOCKS
+static ssize_t wake_lock_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return pm_show_wakelocks(buf, true);
+}
+
+static ssize_t wake_lock_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ int error = pm_wake_lock(buf);
+ return error ? error : n;
+}
+
+power_attr(wake_lock);
+
+static ssize_t wake_unlock_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return pm_show_wakelocks(buf, false);
+}
+
+static ssize_t wake_unlock_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ int error = pm_wake_unlock(buf);
+ return error ? error : n;
+}
+
+power_attr(wake_unlock);
+
+#endif /* CONFIG_PM_WAKELOCKS */
#endif /* CONFIG_PM_SLEEP */
#ifdef CONFIG_PM_TRACE
@@ -409,6 +521,13 @@ static struct attribute * g[] = {
#ifdef CONFIG_PM_SLEEP
&pm_async_attr.attr,
&wakeup_count_attr.attr,
+#ifdef CONFIG_PM_AUTOSLEEP
+ &autosleep_attr.attr,
+#endif
+#ifdef CONFIG_PM_WAKELOCKS
+ &wake_lock_attr.attr,
+ &wake_unlock_attr.attr,
+#endif
#ifdef CONFIG_PM_DEBUG
&pm_test_attr.attr,
#endif
@@ -444,7 +563,10 @@ static int __init pm_init(void)
power_kobj = kobject_create_and_add("power", NULL);
if (!power_kobj)
return -ENOMEM;
- return sysfs_create_group(power_kobj, &attr_group);
+ error = sysfs_create_group(power_kobj, &attr_group);
+ if (error)
+ return error;
+ return pm_autosleep_init();
}
core_initcall(pm_init);
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 98f3622d7407..b0bd4beaebfe 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -264,3 +264,30 @@ static inline void suspend_thaw_processes(void)
{
}
#endif
+
+#ifdef CONFIG_PM_AUTOSLEEP
+
+/* kernel/power/autosleep.c */
+extern int pm_autosleep_init(void);
+extern int pm_autosleep_lock(void);
+extern void pm_autosleep_unlock(void);
+extern suspend_state_t pm_autosleep_state(void);
+extern int pm_autosleep_set_state(suspend_state_t state);
+
+#else /* !CONFIG_PM_AUTOSLEEP */
+
+static inline int pm_autosleep_init(void) { return 0; }
+static inline int pm_autosleep_lock(void) { return 0; }
+static inline void pm_autosleep_unlock(void) {}
+static inline suspend_state_t pm_autosleep_state(void) { return PM_SUSPEND_ON; }
+
+#endif /* !CONFIG_PM_AUTOSLEEP */
+
+#ifdef CONFIG_PM_WAKELOCKS
+
+/* kernel/power/wakelock.c */
+extern ssize_t pm_show_wakelocks(char *buf, bool show_active);
+extern int pm_wake_lock(const char *buf);
+extern int pm_wake_unlock(const char *buf);
+
+#endif /* !CONFIG_PM_WAKELOCKS */
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index eef311a58a64..11e22c068e8b 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -6,7 +6,7 @@
*
* Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz>
* Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
- * Copyright (C) 2010 Bojan Smojver <bojan@rexursive.com>
+ * Copyright (C) 2010-2012 Bojan Smojver <bojan@rexursive.com>
*
* This file is released under the GPLv2.
*
@@ -282,14 +282,17 @@ static int write_page(void *buf, sector_t offset, struct bio **bio_chain)
return -ENOSPC;
if (bio_chain) {
- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+ src = (void *)__get_free_page(__GFP_WAIT | __GFP_NOWARN |
+ __GFP_NORETRY);
if (src) {
copy_page(src, buf);
} else {
ret = hib_wait_on_bio_chain(bio_chain); /* Free pages */
if (ret)
return ret;
- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+ src = (void *)__get_free_page(__GFP_WAIT |
+ __GFP_NOWARN |
+ __GFP_NORETRY);
if (src) {
copy_page(src, buf);
} else {
@@ -367,12 +370,17 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf,
clear_page(handle->cur);
handle->cur_swap = offset;
handle->k = 0;
- }
- if (bio_chain && low_free_pages() <= handle->reqd_free_pages) {
- error = hib_wait_on_bio_chain(bio_chain);
- if (error)
- goto out;
- handle->reqd_free_pages = reqd_free_pages();
+
+ if (bio_chain && low_free_pages() <= handle->reqd_free_pages) {
+ error = hib_wait_on_bio_chain(bio_chain);
+ if (error)
+ goto out;
+ /*
+ * Recalculate the number of required free pages, to
+ * make sure we never take more than half.
+ */
+ handle->reqd_free_pages = reqd_free_pages();
+ }
}
out:
return error;
@@ -419,8 +427,9 @@ static int swap_writer_finish(struct swap_map_handle *handle,
/* Maximum number of threads for compression/decompression. */
#define LZO_THREADS 3
-/* Maximum number of pages for read buffering. */
-#define LZO_READ_PAGES (MAP_PAGE_ENTRIES * 8)
+/* Minimum/maximum number of pages for read buffering. */
+#define LZO_MIN_RD_PAGES 1024
+#define LZO_MAX_RD_PAGES 8192
/**
@@ -631,12 +640,6 @@ static int save_image_lzo(struct swap_map_handle *handle,
}
/*
- * Adjust number of free pages after all allocations have been done.
- * We don't want to run out of pages when writing.
- */
- handle->reqd_free_pages = reqd_free_pages();
-
- /*
* Start the CRC32 thread.
*/
init_waitqueue_head(&crc->go);
@@ -657,6 +660,12 @@ static int save_image_lzo(struct swap_map_handle *handle,
goto out_clean;
}
+ /*
+ * Adjust the number of required free pages after all allocations have
+ * been done. We don't want to run out of pages when writing.
+ */
+ handle->reqd_free_pages = reqd_free_pages();
+
printk(KERN_INFO
"PM: Using %u thread(s) for compression.\n"
"PM: Compressing and saving image data (%u pages) ... ",
@@ -1067,7 +1076,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
unsigned i, thr, run_threads, nr_threads;
unsigned ring = 0, pg = 0, ring_size = 0,
have = 0, want, need, asked = 0;
- unsigned long read_pages;
+ unsigned long read_pages = 0;
unsigned char **page = NULL;
struct dec_data *data = NULL;
struct crc_data *crc = NULL;
@@ -1079,7 +1088,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
nr_threads = num_online_cpus() - 1;
nr_threads = clamp_val(nr_threads, 1, LZO_THREADS);
- page = vmalloc(sizeof(*page) * LZO_READ_PAGES);
+ page = vmalloc(sizeof(*page) * LZO_MAX_RD_PAGES);
if (!page) {
printk(KERN_ERR "PM: Failed to allocate LZO page\n");
ret = -ENOMEM;
@@ -1144,15 +1153,22 @@ static int load_image_lzo(struct swap_map_handle *handle,
}
/*
- * Adjust number of pages for read buffering, in case we are short.
+ * Set the number of pages for read buffering.
+ * This is complete guesswork, because we'll only know the real
+ * picture once prepare_image() is called, which is much later on
+ * during the image load phase. We'll assume the worst case and
+ * say that none of the image pages are from high memory.
*/
- read_pages = (nr_free_pages() - snapshot_get_image_size()) >> 1;
- read_pages = clamp_val(read_pages, LZO_CMP_PAGES, LZO_READ_PAGES);
+ if (low_free_pages() > snapshot_get_image_size())
+ read_pages = (low_free_pages() - snapshot_get_image_size()) / 2;
+ read_pages = clamp_val(read_pages, LZO_MIN_RD_PAGES, LZO_MAX_RD_PAGES);
for (i = 0; i < read_pages; i++) {
page[i] = (void *)__get_free_page(i < LZO_CMP_PAGES ?
__GFP_WAIT | __GFP_HIGH :
- __GFP_WAIT);
+ __GFP_WAIT | __GFP_NOWARN |
+ __GFP_NORETRY);
+
if (!page[i]) {
if (i < LZO_CMP_PAGES) {
ring_size = i;
diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c
new file mode 100644
index 000000000000..c8fba3380076
--- /dev/null
+++ b/kernel/power/wakelock.c
@@ -0,0 +1,259 @@
+/*
+ * kernel/power/wakelock.c
+ *
+ * User space wakeup sources support.
+ *
+ * Copyright (C) 2012 Rafael J. Wysocki <rjw@sisk.pl>
+ *
+ * This code is based on the analogous interface allowing user space to
+ * manipulate wakelocks on Android.
+ */
+
+#include <linux/ctype.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include <linux/slab.h>
+
+static DEFINE_MUTEX(wakelocks_lock);
+
+struct wakelock {
+ char *name;
+ struct rb_node node;
+ struct wakeup_source ws;
+#ifdef CONFIG_PM_WAKELOCKS_GC
+ struct list_head lru;
+#endif
+};
+
+static struct rb_root wakelocks_tree = RB_ROOT;
+
+ssize_t pm_show_wakelocks(char *buf, bool show_active)
+{
+ struct rb_node *node;
+ struct wakelock *wl;
+ char *str = buf;
+ char *end = buf + PAGE_SIZE;
+
+ mutex_lock(&wakelocks_lock);
+
+ for (node = rb_first(&wakelocks_tree); node; node = rb_next(node)) {
+ wl = rb_entry(node, struct wakelock, node);
+ if (wl->ws.active == show_active)
+ str += scnprintf(str, end - str, "%s ", wl->name);
+ }
+ if (str > buf)
+ str--;
+
+ str += scnprintf(str, end - str, "\n");
+
+ mutex_unlock(&wakelocks_lock);
+ return (str - buf);
+}
+
+#if CONFIG_PM_WAKELOCKS_LIMIT > 0
+static unsigned int number_of_wakelocks;
+
+static inline bool wakelocks_limit_exceeded(void)
+{
+ return number_of_wakelocks > CONFIG_PM_WAKELOCKS_LIMIT;
+}
+
+static inline void increment_wakelocks_number(void)
+{
+ number_of_wakelocks++;
+}
+
+static inline void decrement_wakelocks_number(void)
+{
+ number_of_wakelocks--;
+}
+#else /* CONFIG_PM_WAKELOCKS_LIMIT = 0 */
+static inline bool wakelocks_limit_exceeded(void) { return false; }
+static inline void increment_wakelocks_number(void) {}
+static inline void decrement_wakelocks_number(void) {}
+#endif /* CONFIG_PM_WAKELOCKS_LIMIT */
+
+#ifdef CONFIG_PM_WAKELOCKS_GC
+#define WL_GC_COUNT_MAX 100
+#define WL_GC_TIME_SEC 300
+
+static LIST_HEAD(wakelocks_lru_list);
+static unsigned int wakelocks_gc_count;
+
+static inline void wakelocks_lru_add(struct wakelock *wl)
+{
+ list_add(&wl->lru, &wakelocks_lru_list);
+}
+
+static inline void wakelocks_lru_most_recent(struct wakelock *wl)
+{
+ list_move(&wl->lru, &wakelocks_lru_list);
+}
+
+static void wakelocks_gc(void)
+{
+ struct wakelock *wl, *aux;
+ ktime_t now;
+
+ if (++wakelocks_gc_count <= WL_GC_COUNT_MAX)
+ return;
+
+ now = ktime_get();
+ list_for_each_entry_safe_reverse(wl, aux, &wakelocks_lru_list, lru) {
+ u64 idle_time_ns;
+ bool active;
+
+ spin_lock_irq(&wl->ws.lock);
+ idle_time_ns = ktime_to_ns(ktime_sub(now, wl->ws.last_time));
+ active = wl->ws.active;
+ spin_unlock_irq(&wl->ws.lock);
+
+ if (idle_time_ns < ((u64)WL_GC_TIME_SEC * NSEC_PER_SEC))
+ break;
+
+ if (!active) {
+ wakeup_source_remove(&wl->ws);
+ rb_erase(&wl->node, &wakelocks_tree);
+ list_del(&wl->lru);
+ kfree(wl->name);
+ kfree(wl);
+ decrement_wakelocks_number();
+ }
+ }
+ wakelocks_gc_count = 0;
+}
+#else /* !CONFIG_PM_WAKELOCKS_GC */
+static inline void wakelocks_lru_add(struct wakelock *wl) {}
+static inline void wakelocks_lru_most_recent(struct wakelock *wl) {}
+static inline void wakelocks_gc(void) {}
+#endif /* !CONFIG_PM_WAKELOCKS_GC */
+
+static struct wakelock *wakelock_lookup_add(const char *name, size_t len,
+ bool add_if_not_found)
+{
+ struct rb_node **node = &wakelocks_tree.rb_node;
+ struct rb_node *parent = *node;
+ struct wakelock *wl;
+
+ while (*node) {
+ int diff;
+
+ parent = *node;
+ wl = rb_entry(*node, struct wakelock, node);
+ diff = strncmp(name, wl->name, len);
+ if (diff == 0) {
+ if (wl->name[len])
+ diff = -1;
+ else
+ return wl;
+ }
+ if (diff < 0)
+ node = &(*node)->rb_left;
+ else
+ node = &(*node)->rb_right;
+ }
+ if (!add_if_not_found)
+ return ERR_PTR(-EINVAL);
+
+ if (wakelocks_limit_exceeded())
+ return ERR_PTR(-ENOSPC);
+
+ /* Not found, we have to add a new one. */
+ wl = kzalloc(sizeof(*wl), GFP_KERNEL);
+ if (!wl)
+ return ERR_PTR(-ENOMEM);
+
+ wl->name = kstrndup(name, len, GFP_KERNEL);
+ if (!wl->name) {
+ kfree(wl);
+ return ERR_PTR(-ENOMEM);
+ }
+ wl->ws.name = wl->name;
+ wakeup_source_add(&wl->ws);
+ rb_link_node(&wl->node, parent, node);
+ rb_insert_color(&wl->node, &wakelocks_tree);
+ wakelocks_lru_add(wl);
+ increment_wakelocks_number();
+ return wl;
+}
+
+int pm_wake_lock(const char *buf)
+{
+ const char *str = buf;
+ struct wakelock *wl;
+ u64 timeout_ns = 0;
+ size_t len;
+ int ret = 0;
+
+ while (*str && !isspace(*str))
+ str++;
+
+ len = str - buf;
+ if (!len)
+ return -EINVAL;
+
+ if (*str && *str != '\n') {
+ /* Find out if there's a valid timeout string appended. */
+ ret = kstrtou64(skip_spaces(str), 10, &timeout_ns);
+ if (ret)
+ return -EINVAL;
+ }
+
+ mutex_lock(&wakelocks_lock);
+
+ wl = wakelock_lookup_add(buf, len, true);
+ if (IS_ERR(wl)) {
+ ret = PTR_ERR(wl);
+ goto out;
+ }
+ if (timeout_ns) {
+ u64 timeout_ms = timeout_ns + NSEC_PER_MSEC - 1;
+
+ do_div(timeout_ms, NSEC_PER_MSEC);
+ __pm_wakeup_event(&wl->ws, timeout_ms);
+ } else {
+ __pm_stay_awake(&wl->ws);
+ }
+
+ wakelocks_lru_most_recent(wl);
+
+ out:
+ mutex_unlock(&wakelocks_lock);
+ return ret;
+}
+
+int pm_wake_unlock(const char *buf)
+{
+ struct wakelock *wl;
+ size_t len;
+ int ret = 0;
+
+ len = strlen(buf);
+ if (!len)
+ return -EINVAL;
+
+ if (buf[len-1] == '\n')
+ len--;
+
+ if (!len)
+ return -EINVAL;
+
+ mutex_lock(&wakelocks_lock);
+
+ wl = wakelock_lookup_add(buf, len, false);
+ if (IS_ERR(wl)) {
+ ret = PTR_ERR(wl);
+ goto out;
+ }
+ __pm_relax(&wl->ws);
+
+ wakelocks_lru_most_recent(wl);
+ wakelocks_gc();
+
+ out:
+ mutex_unlock(&wakelocks_lock);
+ return ret;
+}
diff --git a/kernel/printk.c b/kernel/printk.c
index b663c2c95d39..32462d2b364a 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -41,6 +41,7 @@
#include <linux/cpu.h>
#include <linux/notifier.h>
#include <linux/rculist.h>
+#include <linux/poll.h>
#include <asm/uaccess.h>
@@ -54,8 +55,6 @@ void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
{
}
-#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
-
/* printk's without a loglevel use this.. */
#define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL
@@ -99,24 +98,6 @@ EXPORT_SYMBOL_GPL(console_drivers);
static int console_locked, console_suspended;
/*
- * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars
- * It is also used in interesting ways to provide interlocking in
- * console_unlock();.
- */
-static DEFINE_RAW_SPINLOCK(logbuf_lock);
-
-#define LOG_BUF_MASK (log_buf_len-1)
-#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
-
-/*
- * The indices into log_buf are not constrained to log_buf_len - they
- * must be masked before subscripting
- */
-static unsigned log_start; /* Index into log_buf: next char to be read by syslog() */
-static unsigned con_start; /* Index into log_buf: next char to be sent to consoles */
-static unsigned log_end; /* Index into log_buf: most-recently-written-char + 1 */
-
-/*
* If exclusive_console is non-NULL then only this console is to be printed to.
*/
static struct console *exclusive_console;
@@ -145,13 +126,491 @@ EXPORT_SYMBOL(console_set_on_cmdline);
/* Flag: console code may call schedule() */
static int console_may_schedule;
+/*
+ * The printk log buffer consists of a chain of concatenated variable
+ * length records. Every record starts with a record header, containing
+ * the overall length of the record.
+ *
+ * The heads to the first and last entry in the buffer, as well as the
+ * sequence numbers of these both entries are maintained when messages
+ * are stored..
+ *
+ * If the heads indicate available messages, the length in the header
+ * tells the start next message. A length == 0 for the next message
+ * indicates a wrap-around to the beginning of the buffer.
+ *
+ * Every record carries the monotonic timestamp in microseconds, as well as
+ * the standard userspace syslog level and syslog facility. The usual
+ * kernel messages use LOG_KERN; userspace-injected messages always carry
+ * a matching syslog facility, by default LOG_USER. The origin of every
+ * message can be reliably determined that way.
+ *
+ * The human readable log message directly follows the message header. The
+ * length of the message text is stored in the header, the stored message
+ * is not terminated.
+ *
+ * Optionally, a message can carry a dictionary of properties (key/value pairs),
+ * to provide userspace with a machine-readable message context.
+ *
+ * Examples for well-defined, commonly used property names are:
+ * DEVICE=b12:8 device identifier
+ * b12:8 block dev_t
+ * c127:3 char dev_t
+ * n8 netdev ifindex
+ * +sound:card0 subsystem:devname
+ * SUBSYSTEM=pci driver-core subsystem name
+ *
+ * Valid characters in property names are [a-zA-Z0-9.-_]. The plain text value
+ * follows directly after a '=' character. Every property is terminated by
+ * a '\0' character. The last property is not terminated.
+ *
+ * Example of a message structure:
+ * 0000 ff 8f 00 00 00 00 00 00 monotonic time in nsec
+ * 0008 34 00 record is 52 bytes long
+ * 000a 0b 00 text is 11 bytes long
+ * 000c 1f 00 dictionary is 23 bytes long
+ * 000e 03 00 LOG_KERN (facility) LOG_ERR (level)
+ * 0010 69 74 27 73 20 61 20 6c "it's a l"
+ * 69 6e 65 "ine"
+ * 001b 44 45 56 49 43 "DEVIC"
+ * 45 3d 62 38 3a 32 00 44 "E=b8:2\0D"
+ * 52 49 56 45 52 3d 62 75 "RIVER=bu"
+ * 67 "g"
+ * 0032 00 00 00 padding to next message header
+ *
+ * The 'struct log' buffer header must never be directly exported to
+ * userspace, it is a kernel-private implementation detail that might
+ * need to be changed in the future, when the requirements change.
+ *
+ * /dev/kmsg exports the structured data in the following line format:
+ * "level,sequnum,timestamp;<message text>\n"
+ *
+ * The optional key/value pairs are attached as continuation lines starting
+ * with a space character and terminated by a newline. All possible
+ * non-prinatable characters are escaped in the "\xff" notation.
+ *
+ * Users of the export format should ignore possible additional values
+ * separated by ',', and find the message after the ';' character.
+ */
+
+struct log {
+ u64 ts_nsec; /* timestamp in nanoseconds */
+ u16 len; /* length of entire record */
+ u16 text_len; /* length of text buffer */
+ u16 dict_len; /* length of dictionary buffer */
+ u16 level; /* syslog level + facility */
+};
+
+/*
+ * The logbuf_lock protects kmsg buffer, indices, counters. It is also
+ * used in interesting ways to provide interlocking in console_unlock();
+ */
+static DEFINE_RAW_SPINLOCK(logbuf_lock);
+
+/* the next printk record to read by syslog(READ) or /proc/kmsg */
+static u64 syslog_seq;
+static u32 syslog_idx;
+
+/* index and sequence number of the first record stored in the buffer */
+static u64 log_first_seq;
+static u32 log_first_idx;
+
+/* index and sequence number of the next record to store in the buffer */
+static u64 log_next_seq;
#ifdef CONFIG_PRINTK
+static u32 log_next_idx;
+
+/* the next printk record to read after the last 'clear' command */
+static u64 clear_seq;
+static u32 clear_idx;
+
+#define LOG_LINE_MAX 1024
-static char __log_buf[__LOG_BUF_LEN];
+/* record buffer */
+#if !defined(CONFIG_64BIT) || defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+#define LOG_ALIGN 4
+#else
+#define LOG_ALIGN 8
+#endif
+#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
+static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN);
static char *log_buf = __log_buf;
-static int log_buf_len = __LOG_BUF_LEN;
-static unsigned logged_chars; /* Number of chars produced since last read+clear operation */
-static int saved_console_loglevel = -1;
+static u32 log_buf_len = __LOG_BUF_LEN;
+
+/* cpu currently holding logbuf_lock */
+static volatile unsigned int logbuf_cpu = UINT_MAX;
+
+/* human readable text of the record */
+static char *log_text(const struct log *msg)
+{
+ return (char *)msg + sizeof(struct log);
+}
+
+/* optional key/value pair dictionary attached to the record */
+static char *log_dict(const struct log *msg)
+{
+ return (char *)msg + sizeof(struct log) + msg->text_len;
+}
+
+/* get record by index; idx must point to valid msg */
+static struct log *log_from_idx(u32 idx)
+{
+ struct log *msg = (struct log *)(log_buf + idx);
+
+ /*
+ * A length == 0 record is the end of buffer marker. Wrap around and
+ * read the message at the start of the buffer.
+ */
+ if (!msg->len)
+ return (struct log *)log_buf;
+ return msg;
+}
+
+/* get next record; idx must point to valid msg */
+static u32 log_next(u32 idx)
+{
+ struct log *msg = (struct log *)(log_buf + idx);
+
+ /* length == 0 indicates the end of the buffer; wrap */
+ /*
+ * A length == 0 record is the end of buffer marker. Wrap around and
+ * read the message at the start of the buffer as *this* one, and
+ * return the one after that.
+ */
+ if (!msg->len) {
+ msg = (struct log *)log_buf;
+ return msg->len;
+ }
+ return idx + msg->len;
+}
+
+/* insert record into the buffer, discard old ones, update heads */
+static void log_store(int facility, int level,
+ const char *dict, u16 dict_len,
+ const char *text, u16 text_len)
+{
+ struct log *msg;
+ u32 size, pad_len;
+
+ /* number of '\0' padding bytes to next message */
+ size = sizeof(struct log) + text_len + dict_len;
+ pad_len = (-size) & (LOG_ALIGN - 1);
+ size += pad_len;
+
+ while (log_first_seq < log_next_seq) {
+ u32 free;
+
+ if (log_next_idx > log_first_idx)
+ free = max(log_buf_len - log_next_idx, log_first_idx);
+ else
+ free = log_first_idx - log_next_idx;
+
+ if (free > size + sizeof(struct log))
+ break;
+
+ /* drop old messages until we have enough contiuous space */
+ log_first_idx = log_next(log_first_idx);
+ log_first_seq++;
+ }
+
+ if (log_next_idx + size + sizeof(struct log) >= log_buf_len) {
+ /*
+ * This message + an additional empty header does not fit
+ * at the end of the buffer. Add an empty header with len == 0
+ * to signify a wrap around.
+ */
+ memset(log_buf + log_next_idx, 0, sizeof(struct log));
+ log_next_idx = 0;
+ }
+
+ /* fill message */
+ msg = (struct log *)(log_buf + log_next_idx);
+ memcpy(log_text(msg), text, text_len);
+ msg->text_len = text_len;
+ memcpy(log_dict(msg), dict, dict_len);
+ msg->dict_len = dict_len;
+ msg->level = (facility << 3) | (level & 7);
+ msg->ts_nsec = local_clock();
+ memset(log_dict(msg) + dict_len, 0, pad_len);
+ msg->len = sizeof(struct log) + text_len + dict_len + pad_len;
+
+ /* insert message */
+ log_next_idx += msg->len;
+ log_next_seq++;
+}
+
+/* /dev/kmsg - userspace message inject/listen interface */
+struct devkmsg_user {
+ u64 seq;
+ u32 idx;
+ struct mutex lock;
+ char buf[8192];
+};
+
+static ssize_t devkmsg_writev(struct kiocb *iocb, const struct iovec *iv,
+ unsigned long count, loff_t pos)
+{
+ char *buf, *line;
+ int i;
+ int level = default_message_loglevel;
+ int facility = 1; /* LOG_USER */
+ size_t len = iov_length(iv, count);
+ ssize_t ret = len;
+
+ if (len > LOG_LINE_MAX)
+ return -EINVAL;
+ buf = kmalloc(len+1, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ line = buf;
+ for (i = 0; i < count; i++) {
+ if (copy_from_user(line, iv[i].iov_base, iv[i].iov_len))
+ goto out;
+ line += iv[i].iov_len;
+ }
+
+ /*
+ * Extract and skip the syslog prefix <[0-9]*>. Coming from userspace
+ * the decimal value represents 32bit, the lower 3 bit are the log
+ * level, the rest are the log facility.
+ *
+ * If no prefix or no userspace facility is specified, we
+ * enforce LOG_USER, to be able to reliably distinguish
+ * kernel-generated messages from userspace-injected ones.
+ */
+ line = buf;
+ if (line[0] == '<') {
+ char *endp = NULL;
+
+ i = simple_strtoul(line+1, &endp, 10);
+ if (endp && endp[0] == '>') {
+ level = i & 7;
+ if (i >> 3)
+ facility = i >> 3;
+ endp++;
+ len -= endp - line;
+ line = endp;
+ }
+ }
+ line[len] = '\0';
+
+ printk_emit(facility, level, NULL, 0, "%s", line);
+out:
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t devkmsg_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct devkmsg_user *user = file->private_data;
+ struct log *msg;
+ u64 ts_usec;
+ size_t i;
+ size_t len;
+ ssize_t ret;
+
+ if (!user)
+ return -EBADF;
+
+ mutex_lock(&user->lock);
+ raw_spin_lock(&logbuf_lock);
+ while (user->seq == log_next_seq) {
+ if (file->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ raw_spin_unlock(&logbuf_lock);
+ goto out;
+ }
+
+ raw_spin_unlock(&logbuf_lock);
+ ret = wait_event_interruptible(log_wait,
+ user->seq != log_next_seq);
+ if (ret)
+ goto out;
+ raw_spin_lock(&logbuf_lock);
+ }
+
+ if (user->seq < log_first_seq) {
+ /* our last seen message is gone, return error and reset */
+ user->idx = log_first_idx;
+ user->seq = log_first_seq;
+ ret = -EPIPE;
+ raw_spin_unlock(&logbuf_lock);
+ goto out;
+ }
+
+ msg = log_from_idx(user->idx);
+ ts_usec = msg->ts_nsec;
+ do_div(ts_usec, 1000);
+ len = sprintf(user->buf, "%u,%llu,%llu;",
+ msg->level, user->seq, ts_usec);
+
+ /* escape non-printable characters */
+ for (i = 0; i < msg->text_len; i++) {
+ unsigned char c = log_text(msg)[i];
+
+ if (c < ' ' || c >= 128)
+ len += sprintf(user->buf + len, "\\x%02x", c);
+ else
+ user->buf[len++] = c;
+ }
+ user->buf[len++] = '\n';
+
+ if (msg->dict_len) {
+ bool line = true;
+
+ for (i = 0; i < msg->dict_len; i++) {
+ unsigned char c = log_dict(msg)[i];
+
+ if (line) {
+ user->buf[len++] = ' ';
+ line = false;
+ }
+
+ if (c == '\0') {
+ user->buf[len++] = '\n';
+ line = true;
+ continue;
+ }
+
+ if (c < ' ' || c >= 128) {
+ len += sprintf(user->buf + len, "\\x%02x", c);
+ continue;
+ }
+
+ user->buf[len++] = c;
+ }
+ user->buf[len++] = '\n';
+ }
+
+ user->idx = log_next(user->idx);
+ user->seq++;
+ raw_spin_unlock(&logbuf_lock);
+
+ if (len > count) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (copy_to_user(buf, user->buf, len)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ ret = len;
+out:
+ mutex_unlock(&user->lock);
+ return ret;
+}
+
+static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
+{
+ struct devkmsg_user *user = file->private_data;
+ loff_t ret = 0;
+
+ if (!user)
+ return -EBADF;
+ if (offset)
+ return -ESPIPE;
+
+ raw_spin_lock(&logbuf_lock);
+ switch (whence) {
+ case SEEK_SET:
+ /* the first record */
+ user->idx = log_first_idx;
+ user->seq = log_first_seq;
+ break;
+ case SEEK_DATA:
+ /*
+ * The first record after the last SYSLOG_ACTION_CLEAR,
+ * like issued by 'dmesg -c'. Reading /dev/kmsg itself
+ * changes no global state, and does not clear anything.
+ */
+ user->idx = clear_idx;
+ user->seq = clear_seq;
+ break;
+ case SEEK_END:
+ /* after the last record */
+ user->idx = log_next_idx;
+ user->seq = log_next_seq;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ raw_spin_unlock(&logbuf_lock);
+ return ret;
+}
+
+static unsigned int devkmsg_poll(struct file *file, poll_table *wait)
+{
+ struct devkmsg_user *user = file->private_data;
+ int ret = 0;
+
+ if (!user)
+ return POLLERR|POLLNVAL;
+
+ poll_wait(file, &log_wait, wait);
+
+ raw_spin_lock(&logbuf_lock);
+ if (user->seq < log_next_seq) {
+ /* return error when data has vanished underneath us */
+ if (user->seq < log_first_seq)
+ ret = POLLIN|POLLRDNORM|POLLERR|POLLPRI;
+ ret = POLLIN|POLLRDNORM;
+ }
+ raw_spin_unlock(&logbuf_lock);
+
+ return ret;
+}
+
+static int devkmsg_open(struct inode *inode, struct file *file)
+{
+ struct devkmsg_user *user;
+ int err;
+
+ /* write-only does not need any file context */
+ if ((file->f_flags & O_ACCMODE) == O_WRONLY)
+ return 0;
+
+ err = security_syslog(SYSLOG_ACTION_READ_ALL);
+ if (err)
+ return err;
+
+ user = kmalloc(sizeof(struct devkmsg_user), GFP_KERNEL);
+ if (!user)
+ return -ENOMEM;
+
+ mutex_init(&user->lock);
+
+ raw_spin_lock(&logbuf_lock);
+ user->idx = log_first_idx;
+ user->seq = log_first_seq;
+ raw_spin_unlock(&logbuf_lock);
+
+ file->private_data = user;
+ return 0;
+}
+
+static int devkmsg_release(struct inode *inode, struct file *file)
+{
+ struct devkmsg_user *user = file->private_data;
+
+ if (!user)
+ return 0;
+
+ mutex_destroy(&user->lock);
+ kfree(user);
+ return 0;
+}
+
+const struct file_operations kmsg_fops = {
+ .open = devkmsg_open,
+ .read = devkmsg_read,
+ .aio_write = devkmsg_writev,
+ .llseek = devkmsg_llseek,
+ .poll = devkmsg_poll,
+ .release = devkmsg_release,
+};
#ifdef CONFIG_KEXEC
/*
@@ -165,9 +624,9 @@ static int saved_console_loglevel = -1;
void log_buf_kexec_setup(void)
{
VMCOREINFO_SYMBOL(log_buf);
- VMCOREINFO_SYMBOL(log_end);
VMCOREINFO_SYMBOL(log_buf_len);
- VMCOREINFO_SYMBOL(logged_chars);
+ VMCOREINFO_SYMBOL(log_first_idx);
+ VMCOREINFO_SYMBOL(log_next_idx);
}
#endif
@@ -191,7 +650,6 @@ early_param("log_buf_len", log_buf_len_setup);
void __init setup_log_buf(int early)
{
unsigned long flags;
- unsigned start, dest_idx, offset;
char *new_log_buf;
int free;
@@ -219,20 +677,8 @@ void __init setup_log_buf(int early)
log_buf_len = new_log_buf_len;
log_buf = new_log_buf;
new_log_buf_len = 0;
- free = __LOG_BUF_LEN - log_end;
-
- offset = start = min(con_start, log_start);
- dest_idx = 0;
- while (start != log_end) {
- unsigned log_idx_mask = start & (__LOG_BUF_LEN - 1);
-
- log_buf[dest_idx] = __log_buf[log_idx_mask];
- start++;
- dest_idx++;
- }
- log_start -= offset;
- con_start -= offset;
- log_end -= offset;
+ free = __LOG_BUF_LEN - log_next_idx;
+ memcpy(log_buf, __log_buf, __LOG_BUF_LEN);
raw_spin_unlock_irqrestore(&logbuf_lock, flags);
pr_info("log_buf_len: %d\n", log_buf_len);
@@ -332,11 +778,202 @@ static int check_syslog_permissions(int type, bool from_file)
return 0;
}
+#if defined(CONFIG_PRINTK_TIME)
+static bool printk_time = 1;
+#else
+static bool printk_time;
+#endif
+module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);
+
+static size_t print_prefix(const struct log *msg, bool syslog, char *buf)
+{
+ size_t len = 0;
+
+ if (syslog) {
+ if (buf) {
+ len += sprintf(buf, "<%u>", msg->level);
+ } else {
+ len += 3;
+ if (msg->level > 9)
+ len++;
+ if (msg->level > 99)
+ len++;
+ }
+ }
+
+ if (printk_time) {
+ if (buf) {
+ unsigned long long ts = msg->ts_nsec;
+ unsigned long rem_nsec = do_div(ts, 1000000000);
+
+ len += sprintf(buf + len, "[%5lu.%06lu] ",
+ (unsigned long) ts, rem_nsec / 1000);
+ } else {
+ len += 15;
+ }
+ }
+
+ return len;
+}
+
+static size_t msg_print_text(const struct log *msg, bool syslog,
+ char *buf, size_t size)
+{
+ const char *text = log_text(msg);
+ size_t text_size = msg->text_len;
+ size_t len = 0;
+
+ do {
+ const char *next = memchr(text, '\n', text_size);
+ size_t text_len;
+
+ if (next) {
+ text_len = next - text;
+ next++;
+ text_size -= next - text;
+ } else {
+ text_len = text_size;
+ }
+
+ if (buf) {
+ if (print_prefix(msg, syslog, NULL) +
+ text_len + 1>= size - len)
+ break;
+
+ len += print_prefix(msg, syslog, buf + len);
+ memcpy(buf + len, text, text_len);
+ len += text_len;
+ buf[len++] = '\n';
+ } else {
+ /* SYSLOG_ACTION_* buffer size only calculation */
+ len += print_prefix(msg, syslog, NULL);
+ len += text_len + 1;
+ }
+
+ text = next;
+ } while (text);
+
+ return len;
+}
+
+static int syslog_print(char __user *buf, int size)
+{
+ char *text;
+ struct log *msg;
+ int len;
+
+ text = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
+ if (!text)
+ return -ENOMEM;
+
+ raw_spin_lock_irq(&logbuf_lock);
+ if (syslog_seq < log_first_seq) {
+ /* messages are gone, move to first one */
+ syslog_seq = log_first_seq;
+ syslog_idx = log_first_idx;
+ }
+ msg = log_from_idx(syslog_idx);
+ len = msg_print_text(msg, true, text, LOG_LINE_MAX);
+ syslog_idx = log_next(syslog_idx);
+ syslog_seq++;
+ raw_spin_unlock_irq(&logbuf_lock);
+
+ if (len > 0 && copy_to_user(buf, text, len))
+ len = -EFAULT;
+
+ kfree(text);
+ return len;
+}
+
+static int syslog_print_all(char __user *buf, int size, bool clear)
+{
+ char *text;
+ int len = 0;
+
+ text = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
+ if (!text)
+ return -ENOMEM;
+
+ raw_spin_lock_irq(&logbuf_lock);
+ if (buf) {
+ u64 next_seq;
+ u64 seq;
+ u32 idx;
+
+ if (clear_seq < log_first_seq) {
+ /* messages are gone, move to first available one */
+ clear_seq = log_first_seq;
+ clear_idx = log_first_idx;
+ }
+
+ /*
+ * Find first record that fits, including all following records,
+ * into the user-provided buffer for this dump.
+ */
+ seq = clear_seq;
+ idx = clear_idx;
+ while (seq < log_next_seq) {
+ struct log *msg = log_from_idx(idx);
+
+ len += msg_print_text(msg, true, NULL, 0);
+ idx = log_next(idx);
+ seq++;
+ }
+ seq = clear_seq;
+ idx = clear_idx;
+ while (len > size && seq < log_next_seq) {
+ struct log *msg = log_from_idx(idx);
+
+ len -= msg_print_text(msg, true, NULL, 0);
+ idx = log_next(idx);
+ seq++;
+ }
+
+ /* last message in this dump */
+ next_seq = log_next_seq;
+
+ len = 0;
+ while (len >= 0 && seq < next_seq) {
+ struct log *msg = log_from_idx(idx);
+ int textlen;
+
+ textlen = msg_print_text(msg, true, text, LOG_LINE_MAX);
+ if (textlen < 0) {
+ len = textlen;
+ break;
+ }
+ idx = log_next(idx);
+ seq++;
+
+ raw_spin_unlock_irq(&logbuf_lock);
+ if (copy_to_user(buf + len, text, textlen))
+ len = -EFAULT;
+ else
+ len += textlen;
+ raw_spin_lock_irq(&logbuf_lock);
+
+ if (seq < log_first_seq) {
+ /* messages are gone, move to next one */
+ seq = log_first_seq;
+ idx = log_first_idx;
+ }
+ }
+ }
+
+ if (clear) {
+ clear_seq = log_next_seq;
+ clear_idx = log_next_idx;
+ }
+ raw_spin_unlock_irq(&logbuf_lock);
+
+ kfree(text);
+ return len;
+}
+
int do_syslog(int type, char __user *buf, int len, bool from_file)
{
- unsigned i, j, limit, count;
- int do_clear = 0;
- char c;
+ bool clear = false;
+ static int saved_console_loglevel = -1;
int error;
error = check_syslog_permissions(type, from_file);
@@ -364,28 +1001,14 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
goto out;
}
error = wait_event_interruptible(log_wait,
- (log_start - log_end));
+ syslog_seq != log_next_seq);
if (error)
goto out;
- i = 0;
- raw_spin_lock_irq(&logbuf_lock);
- while (!error && (log_start != log_end) && i < len) {
- c = LOG_BUF(log_start);
- log_start++;
- raw_spin_unlock_irq(&logbuf_lock);
- error = __put_user(c,buf);
- buf++;
- i++;
- cond_resched();
- raw_spin_lock_irq(&logbuf_lock);
- }
- raw_spin_unlock_irq(&logbuf_lock);
- if (!error)
- error = i;
+ error = syslog_print(buf, len);
break;
/* Read/clear last kernel messages */
case SYSLOG_ACTION_READ_CLEAR:
- do_clear = 1;
+ clear = true;
/* FALL THRU */
/* Read last kernel messages */
case SYSLOG_ACTION_READ_ALL:
@@ -399,52 +1022,11 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
error = -EFAULT;
goto out;
}
- count = len;
- if (count > log_buf_len)
- count = log_buf_len;
- raw_spin_lock_irq(&logbuf_lock);
- if (count > logged_chars)
- count = logged_chars;
- if (do_clear)
- logged_chars = 0;
- limit = log_end;
- /*
- * __put_user() could sleep, and while we sleep
- * printk() could overwrite the messages
- * we try to copy to user space. Therefore
- * the messages are copied in reverse. <manfreds>
- */
- for (i = 0; i < count && !error; i++) {
- j = limit-1-i;
- if (j + log_buf_len < log_end)
- break;
- c = LOG_BUF(j);
- raw_spin_unlock_irq(&logbuf_lock);
- error = __put_user(c,&buf[count-1-i]);
- cond_resched();
- raw_spin_lock_irq(&logbuf_lock);
- }
- raw_spin_unlock_irq(&logbuf_lock);
- if (error)
- break;
- error = i;
- if (i != count) {
- int offset = count-error;
- /* buffer overflow during copy, correct user buffer. */
- for (i = 0; i < error; i++) {
- if (__get_user(c,&buf[i+offset]) ||
- __put_user(c,&buf[i])) {
- error = -EFAULT;
- break;
- }
- cond_resched();
- }
- }
+ error = syslog_print_all(buf, len, clear);
break;
/* Clear ring buffer */
case SYSLOG_ACTION_CLEAR:
- logged_chars = 0;
- break;
+ syslog_print_all(NULL, 0, true);
/* Disable logging to console */
case SYSLOG_ACTION_CONSOLE_OFF:
if (saved_console_loglevel == -1)
@@ -472,7 +1054,35 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
break;
/* Number of chars in the log buffer */
case SYSLOG_ACTION_SIZE_UNREAD:
- error = log_end - log_start;
+ raw_spin_lock_irq(&logbuf_lock);
+ if (syslog_seq < log_first_seq) {
+ /* messages are gone, move to first one */
+ syslog_seq = log_first_seq;
+ syslog_idx = log_first_idx;
+ }
+ if (from_file) {
+ /*
+ * Short-cut for poll(/"proc/kmsg") which simply checks
+ * for pending data, not the size; return the count of
+ * records, not the length.
+ */
+ error = log_next_idx - syslog_idx;
+ } else {
+ u64 seq;
+ u32 idx;
+
+ error = 0;
+ seq = syslog_seq;
+ idx = syslog_idx;
+ while (seq < log_next_seq) {
+ struct log *msg = log_from_idx(idx);
+
+ error += msg_print_text(msg, true, NULL, 0);
+ idx = log_next(idx);
+ seq++;
+ }
+ }
+ raw_spin_unlock_irq(&logbuf_lock);
break;
/* Size of the log buffer */
case SYSLOG_ACTION_SIZE_BUFFER:
@@ -501,29 +1111,11 @@ void kdb_syslog_data(char *syslog_data[4])
{
syslog_data[0] = log_buf;
syslog_data[1] = log_buf + log_buf_len;
- syslog_data[2] = log_buf + log_end -
- (logged_chars < log_buf_len ? logged_chars : log_buf_len);
- syslog_data[3] = log_buf + log_end;
+ syslog_data[2] = log_buf + log_first_idx;
+ syslog_data[3] = log_buf + log_next_idx;
}
#endif /* CONFIG_KGDB_KDB */
-/*
- * Call the console drivers on a range of log_buf
- */
-static void __call_console_drivers(unsigned start, unsigned end)
-{
- struct console *con;
-
- for_each_console(con) {
- if (exclusive_console && con != exclusive_console)
- continue;
- if ((con->flags & CON_ENABLED) && con->write &&
- (cpu_online(smp_processor_id()) ||
- (con->flags & CON_ANYTIME)))
- con->write(con, &LOG_BUF(start), end - start);
- }
-}
-
static bool __read_mostly ignore_loglevel;
static int __init ignore_loglevel_setup(char *str)
@@ -540,142 +1132,33 @@ MODULE_PARM_DESC(ignore_loglevel, "ignore loglevel setting, to"
"print all kernel messages to the console.");
/*
- * Write out chars from start to end - 1 inclusive
- */
-static void _call_console_drivers(unsigned start,
- unsigned end, int msg_log_level)
-{
- trace_console(&LOG_BUF(0), start, end, log_buf_len);
-
- if ((msg_log_level < console_loglevel || ignore_loglevel) &&
- console_drivers && start != end) {
- if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
- /* wrapped write */
- __call_console_drivers(start & LOG_BUF_MASK,
- log_buf_len);
- __call_console_drivers(0, end & LOG_BUF_MASK);
- } else {
- __call_console_drivers(start, end);
- }
- }
-}
-
-/*
- * Parse the syslog header <[0-9]*>. The decimal value represents 32bit, the
- * lower 3 bit are the log level, the rest are the log facility. In case
- * userspace passes usual userspace syslog messages to /dev/kmsg or
- * /dev/ttyprintk, the log prefix might contain the facility. Printk needs
- * to extract the correct log level for in-kernel processing, and not mangle
- * the original value.
- *
- * If a prefix is found, the length of the prefix is returned. If 'level' is
- * passed, it will be filled in with the log level without a possible facility
- * value. If 'special' is passed, the special printk prefix chars are accepted
- * and returned. If no valid header is found, 0 is returned and the passed
- * variables are not touched.
- */
-static size_t log_prefix(const char *p, unsigned int *level, char *special)
-{
- unsigned int lev = 0;
- char sp = '\0';
- size_t len;
-
- if (p[0] != '<' || !p[1])
- return 0;
- if (p[2] == '>') {
- /* usual single digit level number or special char */
- switch (p[1]) {
- case '0' ... '7':
- lev = p[1] - '0';
- break;
- case 'c': /* KERN_CONT */
- case 'd': /* KERN_DEFAULT */
- sp = p[1];
- break;
- default:
- return 0;
- }
- len = 3;
- } else {
- /* multi digit including the level and facility number */
- char *endp = NULL;
-
- lev = (simple_strtoul(&p[1], &endp, 10) & 7);
- if (endp == NULL || endp[0] != '>')
- return 0;
- len = (endp + 1) - p;
- }
-
- /* do not accept special char if not asked for */
- if (sp && !special)
- return 0;
-
- if (special) {
- *special = sp;
- /* return special char, do not touch level */
- if (sp)
- return len;
- }
-
- if (level)
- *level = lev;
- return len;
-}
-
-/*
* Call the console drivers, asking them to write out
* log_buf[start] to log_buf[end - 1].
* The console_lock must be held.
*/
-static void call_console_drivers(unsigned start, unsigned end)
+static void call_console_drivers(int level, const char *text, size_t len)
{
- unsigned cur_index, start_print;
- static int msg_level = -1;
+ struct console *con;
- BUG_ON(((int)(start - end)) > 0);
+ trace_console(text, 0, len, len);
- cur_index = start;
- start_print = start;
- while (cur_index != end) {
- if (msg_level < 0 && ((end - cur_index) > 2)) {
- /* strip log prefix */
- cur_index += log_prefix(&LOG_BUF(cur_index), &msg_level, NULL);
- start_print = cur_index;
- }
- while (cur_index != end) {
- char c = LOG_BUF(cur_index);
-
- cur_index++;
- if (c == '\n') {
- if (msg_level < 0) {
- /*
- * printk() has already given us loglevel tags in
- * the buffer. This code is here in case the
- * log buffer has wrapped right round and scribbled
- * on those tags
- */
- msg_level = default_message_loglevel;
- }
- _call_console_drivers(start_print, cur_index, msg_level);
- msg_level = -1;
- start_print = cur_index;
- break;
- }
- }
- }
- _call_console_drivers(start_print, end, msg_level);
-}
+ if (level >= console_loglevel && !ignore_loglevel)
+ return;
+ if (!console_drivers)
+ return;
-static void emit_log_char(char c)
-{
- LOG_BUF(log_end) = c;
- log_end++;
- if (log_end - log_start > log_buf_len)
- log_start = log_end - log_buf_len;
- if (log_end - con_start > log_buf_len)
- con_start = log_end - log_buf_len;
- if (logged_chars < log_buf_len)
- logged_chars++;
+ for_each_console(con) {
+ if (exclusive_console && con != exclusive_console)
+ continue;
+ if (!(con->flags & CON_ENABLED))
+ continue;
+ if (!con->write)
+ continue;
+ if (!cpu_online(smp_processor_id()) &&
+ !(con->flags & CON_ANYTIME))
+ continue;
+ con->write(con, text, len);
+ }
}
/*
@@ -700,16 +1183,6 @@ static void zap_locks(void)
sema_init(&console_sem, 1);
}
-#if defined(CONFIG_PRINTK_TIME)
-static bool printk_time = 1;
-#else
-static bool printk_time = 0;
-#endif
-module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);
-
-static bool always_kmsg_dump;
-module_param_named(always_kmsg_dump, always_kmsg_dump, bool, S_IRUGO | S_IWUSR);
-
/* Check if we have any console registered that can be called early in boot. */
static int have_callable_console(void)
{
@@ -722,51 +1195,6 @@ static int have_callable_console(void)
return 0;
}
-/**
- * printk - print a kernel message
- * @fmt: format string
- *
- * This is printk(). It can be called from any context. We want it to work.
- *
- * We try to grab the console_lock. If we succeed, it's easy - we log the output and
- * call the console drivers. If we fail to get the semaphore we place the output
- * into the log buffer and return. The current holder of the console_sem will
- * notice the new output in console_unlock(); and will send it to the
- * consoles before releasing the lock.
- *
- * One effect of this deferred printing is that code which calls printk() and
- * then changes console_loglevel may break. This is because console_loglevel
- * is inspected when the actual printing occurs.
- *
- * See also:
- * printf(3)
- *
- * See the vsnprintf() documentation for format string extensions over C99.
- */
-
-asmlinkage int printk(const char *fmt, ...)
-{
- va_list args;
- int r;
-
-#ifdef CONFIG_KGDB_KDB
- if (unlikely(kdb_trap_printk)) {
- va_start(args, fmt);
- r = vkdb_printf(fmt, args);
- va_end(args);
- return r;
- }
-#endif
- va_start(args, fmt);
- r = vprintk(fmt, args);
- va_end(args);
-
- return r;
-}
-
-/* cpu currently holding logbuf_lock */
-static volatile unsigned int printk_cpu = UINT_MAX;
-
/*
* Can we actually use the console at this time on this cpu?
*
@@ -810,17 +1238,12 @@ static int console_trylock_for_printk(unsigned int cpu)
retval = 0;
}
}
- printk_cpu = UINT_MAX;
+ logbuf_cpu = UINT_MAX;
if (wake)
up(&console_sem);
raw_spin_unlock(&logbuf_lock);
return retval;
}
-static const char recursion_bug_msg [] =
- KERN_CRIT "BUG: recent printk recursion!\n";
-static int recursion_bug;
-static int new_text_line = 1;
-static char printk_buf[1024];
int printk_delay_msec __read_mostly;
@@ -836,15 +1259,23 @@ static inline void printk_delay(void)
}
}
-asmlinkage int vprintk(const char *fmt, va_list args)
+asmlinkage int vprintk_emit(int facility, int level,
+ const char *dict, size_t dictlen,
+ const char *fmt, va_list args)
{
- int printed_len = 0;
- int current_log_level = default_message_loglevel;
+ static int recursion_bug;
+ static char cont_buf[LOG_LINE_MAX];
+ static size_t cont_len;
+ static int cont_level;
+ static struct task_struct *cont_task;
+ static char textbuf[LOG_LINE_MAX];
+ char *text = textbuf;
+ size_t text_len;
unsigned long flags;
int this_cpu;
- char *p;
- size_t plen;
- char special;
+ bool newline = false;
+ bool prefix = false;
+ int printed_len = 0;
boot_delay_msec();
printk_delay();
@@ -856,7 +1287,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
/*
* Ouch, printk recursed into itself!
*/
- if (unlikely(printk_cpu == this_cpu)) {
+ if (unlikely(logbuf_cpu == this_cpu)) {
/*
* If a crash is occurring during printk() on this CPU,
* then try to get the crash message out but make sure
@@ -873,97 +1304,110 @@ asmlinkage int vprintk(const char *fmt, va_list args)
lockdep_off();
raw_spin_lock(&logbuf_lock);
- printk_cpu = this_cpu;
+ logbuf_cpu = this_cpu;
if (recursion_bug) {
+ static const char recursion_msg[] =
+ "BUG: recent printk recursion!";
+
recursion_bug = 0;
- strcpy(printk_buf, recursion_bug_msg);
- printed_len = strlen(recursion_bug_msg);
+ printed_len += strlen(recursion_msg);
+ /* emit KERN_CRIT message */
+ log_store(0, 2, NULL, 0, recursion_msg, printed_len);
}
- /* Emit the output into the temporary buffer */
- printed_len += vscnprintf(printk_buf + printed_len,
- sizeof(printk_buf) - printed_len, fmt, args);
- p = printk_buf;
+ /*
+ * The printf needs to come first; we need the syslog
+ * prefix which might be passed-in as a parameter.
+ */
+ text_len = vscnprintf(text, sizeof(textbuf), fmt, args);
- /* Read log level and handle special printk prefix */
- plen = log_prefix(p, &current_log_level, &special);
- if (plen) {
- p += plen;
+ /* mark and strip a trailing newline */
+ if (text_len && text[text_len-1] == '\n') {
+ text_len--;
+ newline = true;
+ }
- switch (special) {
- case 'c': /* Strip <c> KERN_CONT, continue line */
- plen = 0;
- break;
- case 'd': /* Strip <d> KERN_DEFAULT, start new line */
- plen = 0;
- default:
- if (!new_text_line) {
- emit_log_char('\n');
- new_text_line = 1;
- }
+ /* strip syslog prefix and extract log level or control flags */
+ if (text[0] == '<' && text[1] && text[2] == '>') {
+ switch (text[1]) {
+ case '0' ... '7':
+ if (level == -1)
+ level = text[1] - '0';
+ case 'd': /* KERN_DEFAULT */
+ prefix = true;
+ case 'c': /* KERN_CONT */
+ text += 3;
+ text_len -= 3;
}
}
- /*
- * Copy the output into log_buf. If the caller didn't provide
- * the appropriate log prefix, we insert them here
- */
- for (; *p; p++) {
- if (new_text_line) {
- new_text_line = 0;
-
- if (plen) {
- /* Copy original log prefix */
- int i;
-
- for (i = 0; i < plen; i++)
- emit_log_char(printk_buf[i]);
- printed_len += plen;
- } else {
- /* Add log prefix */
- emit_log_char('<');
- emit_log_char(current_log_level + '0');
- emit_log_char('>');
- printed_len += 3;
- }
+ if (level == -1)
+ level = default_message_loglevel;
- if (printk_time) {
- /* Add the current time stamp */
- char tbuf[50], *tp;
- unsigned tlen;
- unsigned long long t;
- unsigned long nanosec_rem;
-
- t = cpu_clock(printk_cpu);
- nanosec_rem = do_div(t, 1000000000);
- tlen = sprintf(tbuf, "[%5lu.%06lu] ",
- (unsigned long) t,
- nanosec_rem / 1000);
-
- for (tp = tbuf; tp < tbuf + tlen; tp++)
- emit_log_char(*tp);
- printed_len += tlen;
- }
+ if (dict) {
+ prefix = true;
+ newline = true;
+ }
- if (!*p)
- break;
+ if (!newline) {
+ if (cont_len && (prefix || cont_task != current)) {
+ /*
+ * Flush earlier buffer, which is either from a
+ * different thread, or when we got a new prefix.
+ */
+ log_store(facility, cont_level, NULL, 0, cont_buf, cont_len);
+ cont_len = 0;
}
- emit_log_char(*p);
- if (*p == '\n')
- new_text_line = 1;
+ if (!cont_len) {
+ cont_level = level;
+ cont_task = current;
+ }
+
+ /* buffer or append to earlier buffer from the same thread */
+ if (cont_len + text_len > sizeof(cont_buf))
+ text_len = sizeof(cont_buf) - cont_len;
+ memcpy(cont_buf + cont_len, text, text_len);
+ cont_len += text_len;
+ } else {
+ if (cont_len && cont_task == current) {
+ if (prefix) {
+ /*
+ * New prefix from the same thread; flush. We
+ * either got no earlier newline, or we race
+ * with an interrupt.
+ */
+ log_store(facility, cont_level,
+ NULL, 0, cont_buf, cont_len);
+ cont_len = 0;
+ }
+
+ /* append to the earlier buffer and flush */
+ if (cont_len + text_len > sizeof(cont_buf))
+ text_len = sizeof(cont_buf) - cont_len;
+ memcpy(cont_buf + cont_len, text, text_len);
+ cont_len += text_len;
+ log_store(facility, cont_level,
+ NULL, 0, cont_buf, cont_len);
+ cont_len = 0;
+ cont_task = NULL;
+ printed_len = cont_len;
+ } else {
+ /* ordinary single and terminated line */
+ log_store(facility, level,
+ dict, dictlen, text, text_len);
+ printed_len = text_len;
+ }
}
/*
- * Try to acquire and then immediately release the
- * console semaphore. The release will do all the
- * actual magic (print out buffers, wake up klogd,
- * etc).
+ * Try to acquire and then immediately release the console semaphore.
+ * The release will print out buffers and wake up /dev/kmsg and syslog()
+ * users.
*
- * The console_trylock_for_printk() function
- * will release 'logbuf_lock' regardless of whether it
- * actually gets the semaphore or not.
+ * The console_trylock_for_printk() function will release 'logbuf_lock'
+ * regardless of whether it actually gets the console semaphore or not.
*/
if (console_trylock_for_printk(this_cpu))
console_unlock();
@@ -974,16 +1418,81 @@ out_restore_irqs:
return printed_len;
}
-EXPORT_SYMBOL(printk);
-EXPORT_SYMBOL(vprintk);
+EXPORT_SYMBOL(vprintk_emit);
-#else
+asmlinkage int vprintk(const char *fmt, va_list args)
+{
+ return vprintk_emit(0, -1, NULL, 0, fmt, args);
+}
+EXPORT_SYMBOL(vprintk);
-static void call_console_drivers(unsigned start, unsigned end)
+asmlinkage int printk_emit(int facility, int level,
+ const char *dict, size_t dictlen,
+ const char *fmt, ...)
{
+ va_list args;
+ int r;
+
+ va_start(args, fmt);
+ r = vprintk_emit(facility, level, dict, dictlen, fmt, args);
+ va_end(args);
+
+ return r;
}
+EXPORT_SYMBOL(printk_emit);
+/**
+ * printk - print a kernel message
+ * @fmt: format string
+ *
+ * This is printk(). It can be called from any context. We want it to work.
+ *
+ * We try to grab the console_lock. If we succeed, it's easy - we log the
+ * output and call the console drivers. If we fail to get the semaphore, we
+ * place the output into the log buffer and return. The current holder of
+ * the console_sem will notice the new output in console_unlock(); and will
+ * send it to the consoles before releasing the lock.
+ *
+ * One effect of this deferred printing is that code which calls printk() and
+ * then changes console_loglevel may break. This is because console_loglevel
+ * is inspected when the actual printing occurs.
+ *
+ * See also:
+ * printf(3)
+ *
+ * See the vsnprintf() documentation for format string extensions over C99.
+ */
+asmlinkage int printk(const char *fmt, ...)
+{
+ va_list args;
+ int r;
+
+#ifdef CONFIG_KGDB_KDB
+ if (unlikely(kdb_trap_printk)) {
+ va_start(args, fmt);
+ r = vkdb_printf(fmt, args);
+ va_end(args);
+ return r;
+ }
#endif
+ va_start(args, fmt);
+ r = vprintk_emit(0, -1, NULL, 0, fmt, args);
+ va_end(args);
+
+ return r;
+}
+EXPORT_SYMBOL(printk);
+
+#else
+
+#define LOG_LINE_MAX 0
+static struct log *log_from_idx(u32 idx) { return NULL; }
+static u32 log_next(u32 idx) { return 0; }
+static void call_console_drivers(int level, const char *text, size_t len) {}
+static size_t msg_print_text(const struct log *msg, bool syslog,
+ char *buf, size_t size) { return 0; }
+
+#endif /* CONFIG_PRINTK */
static int __add_preferred_console(char *name, int idx, char *options,
char *brl_options)
@@ -1217,7 +1726,7 @@ int is_console_locked(void)
}
/*
- * Delayed printk facility, for scheduler-internal messages:
+ * Delayed printk version, for scheduler-internal messages:
*/
#define PRINTK_BUF_SIZE 512
@@ -1253,6 +1762,10 @@ void wake_up_klogd(void)
this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
}
+/* the next printk record to write to the console */
+static u64 console_seq;
+static u32 console_idx;
+
/**
* console_unlock - unlock the console system
*
@@ -1263,15 +1776,16 @@ void wake_up_klogd(void)
* by printk(). If this is the case, console_unlock(); emits
* the output prior to releasing the lock.
*
- * If there is output waiting for klogd, we wake it up.
+ * If there is output waiting, we wake /dev/kmsg and syslog() users.
*
* console_unlock(); may be called from any context.
*/
void console_unlock(void)
{
+ static u64 seen_seq;
unsigned long flags;
- unsigned _con_start, _log_end;
- unsigned wake_klogd = 0, retry = 0;
+ bool wake_klogd = false;
+ bool retry;
if (console_suspended) {
up(&console_sem);
@@ -1281,17 +1795,38 @@ void console_unlock(void)
console_may_schedule = 0;
again:
- for ( ; ; ) {
+ for (;;) {
+ struct log *msg;
+ static char text[LOG_LINE_MAX];
+ size_t len;
+ int level;
+
raw_spin_lock_irqsave(&logbuf_lock, flags);
- wake_klogd |= log_start - log_end;
- if (con_start == log_end)
- break; /* Nothing to print */
- _con_start = con_start;
- _log_end = log_end;
- con_start = log_end; /* Flush */
+ if (seen_seq != log_next_seq) {
+ wake_klogd = true;
+ seen_seq = log_next_seq;
+ }
+
+ if (console_seq < log_first_seq) {
+ /* messages are gone, move to first one */
+ console_seq = log_first_seq;
+ console_idx = log_first_idx;
+ }
+
+ if (console_seq == log_next_seq)
+ break;
+
+ msg = log_from_idx(console_idx);
+ level = msg->level & 7;
+
+ len = msg_print_text(msg, false, text, sizeof(text));
+
+ console_idx = log_next(console_idx);
+ console_seq++;
raw_spin_unlock(&logbuf_lock);
+
stop_critical_timings(); /* don't trace print latency */
- call_console_drivers(_con_start, _log_end);
+ call_console_drivers(level, text, len);
start_critical_timings();
local_irq_restore(flags);
}
@@ -1312,8 +1847,7 @@ again:
* flush, no worries.
*/
raw_spin_lock(&logbuf_lock);
- if (con_start != log_end)
- retry = 1;
+ retry = console_seq != log_next_seq;
raw_spin_unlock_irqrestore(&logbuf_lock, flags);
if (retry && console_trylock())
@@ -1549,7 +2083,8 @@ void register_console(struct console *newcon)
* for us.
*/
raw_spin_lock_irqsave(&logbuf_lock, flags);
- con_start = log_start;
+ console_seq = syslog_seq;
+ console_idx = syslog_idx;
raw_spin_unlock_irqrestore(&logbuf_lock, flags);
/*
* We're about to replay the log buffer. Only do this to the
@@ -1758,6 +2293,9 @@ int kmsg_dump_unregister(struct kmsg_dumper *dumper)
}
EXPORT_SYMBOL_GPL(kmsg_dump_unregister);
+static bool always_kmsg_dump;
+module_param_named(always_kmsg_dump, always_kmsg_dump, bool, S_IRUGO | S_IWUSR);
+
/**
* kmsg_dump - dump kernel log to kernel message dumpers.
* @reason: the reason (oops, panic etc) for dumping
@@ -1767,8 +2305,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_unregister);
*/
void kmsg_dump(enum kmsg_dump_reason reason)
{
- unsigned long end;
- unsigned chars;
+ u64 idx;
struct kmsg_dumper *dumper;
const char *s1, *s2;
unsigned long l1, l2;
@@ -1780,24 +2317,27 @@ void kmsg_dump(enum kmsg_dump_reason reason)
/* Theoretically, the log could move on after we do this, but
there's not a lot we can do about that. The new messages
will overwrite the start of what we dump. */
+
raw_spin_lock_irqsave(&logbuf_lock, flags);
- end = log_end & LOG_BUF_MASK;
- chars = logged_chars;
- raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+ if (syslog_seq < log_first_seq)
+ idx = syslog_idx;
+ else
+ idx = log_first_idx;
- if (chars > end) {
- s1 = log_buf + log_buf_len - chars + end;
- l1 = chars - end;
+ if (idx > log_next_idx) {
+ s1 = log_buf;
+ l1 = log_next_idx;
- s2 = log_buf;
- l2 = end;
+ s2 = log_buf + idx;
+ l2 = log_buf_len - idx;
} else {
s1 = "";
l1 = 0;
- s2 = log_buf + end - chars;
- l2 = chars;
+ s2 = log_buf + idx;
+ l2 = log_next_idx - idx;
}
+ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
rcu_read_lock();
list_for_each_entry_rcu(dumper, &dump_list, list)
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index a86f1741cc27..95cba41ce1e9 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -51,6 +51,34 @@
#include "rcu.h"
+#ifdef CONFIG_PREEMPT_RCU
+
+/*
+ * Check for a task exiting while in a preemptible-RCU read-side
+ * critical section, clean up if so. No need to issue warnings,
+ * as debug_check_no_locks_held() already does this if lockdep
+ * is enabled.
+ */
+void exit_rcu(void)
+{
+ struct task_struct *t = current;
+
+ if (likely(list_empty(&current->rcu_node_entry)))
+ return;
+ t->rcu_read_lock_nesting = 1;
+ barrier();
+ t->rcu_read_unlock_special = RCU_READ_UNLOCK_BLOCKED;
+ __rcu_read_unlock();
+}
+
+#else /* #ifdef CONFIG_PREEMPT_RCU */
+
+void exit_rcu(void)
+{
+}
+
+#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
+
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key rcu_lock_key;
struct lockdep_map rcu_lock_map =
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h
index 22ecea0dfb62..fc31a2d65100 100644
--- a/kernel/rcutiny_plugin.h
+++ b/kernel/rcutiny_plugin.h
@@ -851,22 +851,6 @@ int rcu_preempt_needs_cpu(void)
return rcu_preempt_ctrlblk.rcb.rcucblist != NULL;
}
-/*
- * Check for a task exiting while in a preemptible -RCU read-side
- * critical section, clean up if so. No need to issue warnings,
- * as debug_check_no_locks_held() already does this if lockdep
- * is enabled.
- */
-void exit_rcu(void)
-{
- struct task_struct *t = current;
-
- if (t->rcu_read_lock_nesting == 0)
- return;
- t->rcu_read_lock_nesting = 1;
- __rcu_read_unlock();
-}
-
#else /* #ifdef CONFIG_TINY_PREEMPT_RCU */
#ifdef CONFIG_RCU_TRACE
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index a89b381a8c6e..e66b34ab7555 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -64,6 +64,7 @@ static int irqreader = 1; /* RCU readers from irq (timers). */
static int fqs_duration; /* Duration of bursts (us), 0 to disable. */
static int fqs_holdoff; /* Hold time within burst (us). */
static int fqs_stutter = 3; /* Wait time between bursts (s). */
+static int n_barrier_cbs; /* Number of callbacks to test RCU barriers. */
static int onoff_interval; /* Wait time between CPU hotplugs, 0=disable. */
static int onoff_holdoff; /* Seconds after boot before CPU hotplugs. */
static int shutdown_secs; /* Shutdown time (s). <=0 for no shutdown. */
@@ -96,6 +97,8 @@ module_param(fqs_holdoff, int, 0444);
MODULE_PARM_DESC(fqs_holdoff, "Holdoff time within fqs bursts (us)");
module_param(fqs_stutter, int, 0444);
MODULE_PARM_DESC(fqs_stutter, "Wait time between fqs bursts (s)");
+module_param(n_barrier_cbs, int, 0444);
+MODULE_PARM_DESC(n_barrier_cbs, "# of callbacks/kthreads for barrier testing");
module_param(onoff_interval, int, 0444);
MODULE_PARM_DESC(onoff_interval, "Time between CPU hotplugs (s), 0=disable");
module_param(onoff_holdoff, int, 0444);
@@ -139,6 +142,8 @@ static struct task_struct *shutdown_task;
static struct task_struct *onoff_task;
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
static struct task_struct *stall_task;
+static struct task_struct **barrier_cbs_tasks;
+static struct task_struct *barrier_task;
#define RCU_TORTURE_PIPE_LEN 10
@@ -164,6 +169,7 @@ static atomic_t n_rcu_torture_alloc_fail;
static atomic_t n_rcu_torture_free;
static atomic_t n_rcu_torture_mberror;
static atomic_t n_rcu_torture_error;
+static long n_rcu_torture_barrier_error;
static long n_rcu_torture_boost_ktrerror;
static long n_rcu_torture_boost_rterror;
static long n_rcu_torture_boost_failure;
@@ -173,6 +179,8 @@ static long n_offline_attempts;
static long n_offline_successes;
static long n_online_attempts;
static long n_online_successes;
+static long n_barrier_attempts;
+static long n_barrier_successes;
static struct list_head rcu_torture_removed;
static cpumask_var_t shuffle_tmp_mask;
@@ -197,6 +205,10 @@ static unsigned long shutdown_time; /* jiffies to system shutdown. */
static unsigned long boost_starttime; /* jiffies of next boost test start. */
DEFINE_MUTEX(boost_mutex); /* protect setting boost_starttime */
/* and boost task create/destroy. */
+static atomic_t barrier_cbs_count; /* Barrier callbacks registered. */
+static atomic_t barrier_cbs_invoked; /* Barrier callbacks invoked. */
+static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */
+static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);
/* Mediate rmmod and system shutdown. Concurrent rmmod & shutdown illegal! */
@@ -327,6 +339,7 @@ struct rcu_torture_ops {
int (*completed)(void);
void (*deferred_free)(struct rcu_torture *p);
void (*sync)(void);
+ void (*call)(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
void (*cb_barrier)(void);
void (*fqs)(void);
int (*stats)(char *page);
@@ -417,6 +430,7 @@ static struct rcu_torture_ops rcu_ops = {
.completed = rcu_torture_completed,
.deferred_free = rcu_torture_deferred_free,
.sync = synchronize_rcu,
+ .call = call_rcu,
.cb_barrier = rcu_barrier,
.fqs = rcu_force_quiescent_state,
.stats = NULL,
@@ -460,6 +474,7 @@ static struct rcu_torture_ops rcu_sync_ops = {
.completed = rcu_torture_completed,
.deferred_free = rcu_sync_torture_deferred_free,
.sync = synchronize_rcu,
+ .call = NULL,
.cb_barrier = NULL,
.fqs = rcu_force_quiescent_state,
.stats = NULL,
@@ -477,6 +492,7 @@ static struct rcu_torture_ops rcu_expedited_ops = {
.completed = rcu_no_completed,
.deferred_free = rcu_sync_torture_deferred_free,
.sync = synchronize_rcu_expedited,
+ .call = NULL,
.cb_barrier = NULL,
.fqs = rcu_force_quiescent_state,
.stats = NULL,
@@ -519,6 +535,7 @@ static struct rcu_torture_ops rcu_bh_ops = {
.completed = rcu_bh_torture_completed,
.deferred_free = rcu_bh_torture_deferred_free,
.sync = synchronize_rcu_bh,
+ .call = call_rcu_bh,
.cb_barrier = rcu_barrier_bh,
.fqs = rcu_bh_force_quiescent_state,
.stats = NULL,
@@ -535,6 +552,7 @@ static struct rcu_torture_ops rcu_bh_sync_ops = {
.completed = rcu_bh_torture_completed,
.deferred_free = rcu_sync_torture_deferred_free,
.sync = synchronize_rcu_bh,
+ .call = NULL,
.cb_barrier = NULL,
.fqs = rcu_bh_force_quiescent_state,
.stats = NULL,
@@ -551,6 +569,7 @@ static struct rcu_torture_ops rcu_bh_expedited_ops = {
.completed = rcu_bh_torture_completed,
.deferred_free = rcu_sync_torture_deferred_free,
.sync = synchronize_rcu_bh_expedited,
+ .call = NULL,
.cb_barrier = NULL,
.fqs = rcu_bh_force_quiescent_state,
.stats = NULL,
@@ -606,6 +625,11 @@ static int srcu_torture_completed(void)
return srcu_batches_completed(&srcu_ctl);
}
+static void srcu_torture_deferred_free(struct rcu_torture *rp)
+{
+ call_srcu(&srcu_ctl, &rp->rtort_rcu, rcu_torture_cb);
+}
+
static void srcu_torture_synchronize(void)
{
synchronize_srcu(&srcu_ctl);
@@ -620,7 +644,7 @@ static int srcu_torture_stats(char *page)
cnt += sprintf(&page[cnt], "%s%s per-CPU(idx=%d):",
torture_type, TORTURE_FLAG, idx);
for_each_possible_cpu(cpu) {
- cnt += sprintf(&page[cnt], " %d(%d,%d)", cpu,
+ cnt += sprintf(&page[cnt], " %d(%lu,%lu)", cpu,
per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[!idx],
per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[idx]);
}
@@ -635,13 +659,29 @@ static struct rcu_torture_ops srcu_ops = {
.read_delay = srcu_read_delay,
.readunlock = srcu_torture_read_unlock,
.completed = srcu_torture_completed,
- .deferred_free = rcu_sync_torture_deferred_free,
+ .deferred_free = srcu_torture_deferred_free,
.sync = srcu_torture_synchronize,
+ .call = NULL,
.cb_barrier = NULL,
.stats = srcu_torture_stats,
.name = "srcu"
};
+static struct rcu_torture_ops srcu_sync_ops = {
+ .init = srcu_torture_init,
+ .cleanup = srcu_torture_cleanup,
+ .readlock = srcu_torture_read_lock,
+ .read_delay = srcu_read_delay,
+ .readunlock = srcu_torture_read_unlock,
+ .completed = srcu_torture_completed,
+ .deferred_free = rcu_sync_torture_deferred_free,
+ .sync = srcu_torture_synchronize,
+ .call = NULL,
+ .cb_barrier = NULL,
+ .stats = srcu_torture_stats,
+ .name = "srcu_sync"
+};
+
static int srcu_torture_read_lock_raw(void) __acquires(&srcu_ctl)
{
return srcu_read_lock_raw(&srcu_ctl);
@@ -659,13 +699,29 @@ static struct rcu_torture_ops srcu_raw_ops = {
.read_delay = srcu_read_delay,
.readunlock = srcu_torture_read_unlock_raw,
.completed = srcu_torture_completed,
- .deferred_free = rcu_sync_torture_deferred_free,
+ .deferred_free = srcu_torture_deferred_free,
.sync = srcu_torture_synchronize,
+ .call = NULL,
.cb_barrier = NULL,
.stats = srcu_torture_stats,
.name = "srcu_raw"
};
+static struct rcu_torture_ops srcu_raw_sync_ops = {
+ .init = srcu_torture_init,
+ .cleanup = srcu_torture_cleanup,
+ .readlock = srcu_torture_read_lock_raw,
+ .read_delay = srcu_read_delay,
+ .readunlock = srcu_torture_read_unlock_raw,
+ .completed = srcu_torture_completed,
+ .deferred_free = rcu_sync_torture_deferred_free,
+ .sync = srcu_torture_synchronize,
+ .call = NULL,
+ .cb_barrier = NULL,
+ .stats = srcu_torture_stats,
+ .name = "srcu_raw_sync"
+};
+
static void srcu_torture_synchronize_expedited(void)
{
synchronize_srcu_expedited(&srcu_ctl);
@@ -680,6 +736,7 @@ static struct rcu_torture_ops srcu_expedited_ops = {
.completed = srcu_torture_completed,
.deferred_free = rcu_sync_torture_deferred_free,
.sync = srcu_torture_synchronize_expedited,
+ .call = NULL,
.cb_barrier = NULL,
.stats = srcu_torture_stats,
.name = "srcu_expedited"
@@ -1129,7 +1186,8 @@ rcu_torture_printk(char *page)
"rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d "
"rtmbe: %d rtbke: %ld rtbre: %ld "
"rtbf: %ld rtb: %ld nt: %ld "
- "onoff: %ld/%ld:%ld/%ld",
+ "onoff: %ld/%ld:%ld/%ld "
+ "barrier: %ld/%ld:%ld",
rcu_torture_current,
rcu_torture_current_version,
list_empty(&rcu_torture_freelist),
@@ -1145,14 +1203,17 @@ rcu_torture_printk(char *page)
n_online_successes,
n_online_attempts,
n_offline_successes,
- n_offline_attempts);
+ n_offline_attempts,
+ n_barrier_successes,
+ n_barrier_attempts,
+ n_rcu_torture_barrier_error);
+ cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
if (atomic_read(&n_rcu_torture_mberror) != 0 ||
+ n_rcu_torture_barrier_error != 0 ||
n_rcu_torture_boost_ktrerror != 0 ||
n_rcu_torture_boost_rterror != 0 ||
- n_rcu_torture_boost_failure != 0)
- cnt += sprintf(&page[cnt], " !!!");
- cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
- if (i > 1) {
+ n_rcu_torture_boost_failure != 0 ||
+ i > 1) {
cnt += sprintf(&page[cnt], "!!! ");
atomic_inc(&n_rcu_torture_error);
WARN_ON_ONCE(1);
@@ -1337,6 +1398,7 @@ static void rcutorture_booster_cleanup(int cpu)
/* This must be outside of the mutex, otherwise deadlock! */
kthread_stop(t);
+ boost_tasks[cpu] = NULL;
}
static int rcutorture_booster_init(int cpu)
@@ -1484,13 +1546,15 @@ static void rcu_torture_onoff_cleanup(void)
return;
VERBOSE_PRINTK_STRING("Stopping rcu_torture_onoff task");
kthread_stop(onoff_task);
+ onoff_task = NULL;
}
#else /* #ifdef CONFIG_HOTPLUG_CPU */
-static void
+static int
rcu_torture_onoff_init(void)
{
+ return 0;
}
static void rcu_torture_onoff_cleanup(void)
@@ -1554,6 +1618,152 @@ static void rcu_torture_stall_cleanup(void)
return;
VERBOSE_PRINTK_STRING("Stopping rcu_torture_stall_task.");
kthread_stop(stall_task);
+ stall_task = NULL;
+}
+
+/* Callback function for RCU barrier testing. */
+void rcu_torture_barrier_cbf(struct rcu_head *rcu)
+{
+ atomic_inc(&barrier_cbs_invoked);
+}
+
+/* kthread function to register callbacks used to test RCU barriers. */
+static int rcu_torture_barrier_cbs(void *arg)
+{
+ long myid = (long)arg;
+ struct rcu_head rcu;
+
+ init_rcu_head_on_stack(&rcu);
+ VERBOSE_PRINTK_STRING("rcu_torture_barrier_cbs task started");
+ set_user_nice(current, 19);
+ do {
+ wait_event(barrier_cbs_wq[myid],
+ atomic_read(&barrier_cbs_count) == n_barrier_cbs ||
+ kthread_should_stop() ||
+ fullstop != FULLSTOP_DONTSTOP);
+ if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
+ break;
+ cur_ops->call(&rcu, rcu_torture_barrier_cbf);
+ if (atomic_dec_and_test(&barrier_cbs_count))
+ wake_up(&barrier_wq);
+ } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
+ VERBOSE_PRINTK_STRING("rcu_torture_barrier_cbs task stopping");
+ rcutorture_shutdown_absorb("rcu_torture_barrier_cbs");
+ while (!kthread_should_stop())
+ schedule_timeout_interruptible(1);
+ cur_ops->cb_barrier();
+ destroy_rcu_head_on_stack(&rcu);
+ return 0;
+}
+
+/* kthread function to drive and coordinate RCU barrier testing. */
+static int rcu_torture_barrier(void *arg)
+{
+ int i;
+
+ VERBOSE_PRINTK_STRING("rcu_torture_barrier task starting");
+ do {
+ atomic_set(&barrier_cbs_invoked, 0);
+ atomic_set(&barrier_cbs_count, n_barrier_cbs);
+ /* wake_up() path contains the required barriers. */
+ for (i = 0; i < n_barrier_cbs; i++)
+ wake_up(&barrier_cbs_wq[i]);
+ wait_event(barrier_wq,
+ atomic_read(&barrier_cbs_count) == 0 ||
+ kthread_should_stop() ||
+ fullstop != FULLSTOP_DONTSTOP);
+ if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
+ break;
+ n_barrier_attempts++;
+ cur_ops->cb_barrier();
+ if (atomic_read(&barrier_cbs_invoked) != n_barrier_cbs) {
+ n_rcu_torture_barrier_error++;
+ WARN_ON_ONCE(1);
+ }
+ n_barrier_successes++;
+ schedule_timeout_interruptible(HZ / 10);
+ } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
+ VERBOSE_PRINTK_STRING("rcu_torture_barrier task stopping");
+ rcutorture_shutdown_absorb("rcu_torture_barrier_cbs");
+ while (!kthread_should_stop())
+ schedule_timeout_interruptible(1);
+ return 0;
+}
+
+/* Initialize RCU barrier testing. */
+static int rcu_torture_barrier_init(void)
+{
+ int i;
+ int ret;
+
+ if (n_barrier_cbs == 0)
+ return 0;
+ if (cur_ops->call == NULL || cur_ops->cb_barrier == NULL) {
+ printk(KERN_ALERT "%s" TORTURE_FLAG
+ " Call or barrier ops missing for %s,\n",
+ torture_type, cur_ops->name);
+ printk(KERN_ALERT "%s" TORTURE_FLAG
+ " RCU barrier testing omitted from run.\n",
+ torture_type);
+ return 0;
+ }
+ atomic_set(&barrier_cbs_count, 0);
+ atomic_set(&barrier_cbs_invoked, 0);
+ barrier_cbs_tasks =
+ kzalloc(n_barrier_cbs * sizeof(barrier_cbs_tasks[0]),
+ GFP_KERNEL);
+ barrier_cbs_wq =
+ kzalloc(n_barrier_cbs * sizeof(barrier_cbs_wq[0]),
+ GFP_KERNEL);
+ if (barrier_cbs_tasks == NULL || barrier_cbs_wq == 0)
+ return -ENOMEM;
+ for (i = 0; i < n_barrier_cbs; i++) {
+ init_waitqueue_head(&barrier_cbs_wq[i]);
+ barrier_cbs_tasks[i] = kthread_run(rcu_torture_barrier_cbs,
+ (void *)(long)i,
+ "rcu_torture_barrier_cbs");
+ if (IS_ERR(barrier_cbs_tasks[i])) {
+ ret = PTR_ERR(barrier_cbs_tasks[i]);
+ VERBOSE_PRINTK_ERRSTRING("Failed to create rcu_torture_barrier_cbs");
+ barrier_cbs_tasks[i] = NULL;
+ return ret;
+ }
+ }
+ barrier_task = kthread_run(rcu_torture_barrier, NULL,
+ "rcu_torture_barrier");
+ if (IS_ERR(barrier_task)) {
+ ret = PTR_ERR(barrier_task);
+ VERBOSE_PRINTK_ERRSTRING("Failed to create rcu_torture_barrier");
+ barrier_task = NULL;
+ }
+ return 0;
+}
+
+/* Clean up after RCU barrier testing. */
+static void rcu_torture_barrier_cleanup(void)
+{
+ int i;
+
+ if (barrier_task != NULL) {
+ VERBOSE_PRINTK_STRING("Stopping rcu_torture_barrier task");
+ kthread_stop(barrier_task);
+ barrier_task = NULL;
+ }
+ if (barrier_cbs_tasks != NULL) {
+ for (i = 0; i < n_barrier_cbs; i++) {
+ if (barrier_cbs_tasks[i] != NULL) {
+ VERBOSE_PRINTK_STRING("Stopping rcu_torture_barrier_cbs task");
+ kthread_stop(barrier_cbs_tasks[i]);
+ barrier_cbs_tasks[i] = NULL;
+ }
+ }
+ kfree(barrier_cbs_tasks);
+ barrier_cbs_tasks = NULL;
+ }
+ if (barrier_cbs_wq != NULL) {
+ kfree(barrier_cbs_wq);
+ barrier_cbs_wq = NULL;
+ }
}
static int rcutorture_cpu_notify(struct notifier_block *self,
@@ -1598,6 +1808,7 @@ rcu_torture_cleanup(void)
fullstop = FULLSTOP_RMMOD;
mutex_unlock(&fullstop_mutex);
unregister_reboot_notifier(&rcutorture_shutdown_nb);
+ rcu_torture_barrier_cleanup();
rcu_torture_stall_cleanup();
if (stutter_task) {
VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task");
@@ -1665,6 +1876,7 @@ rcu_torture_cleanup(void)
VERBOSE_PRINTK_STRING("Stopping rcu_torture_shutdown task");
kthread_stop(shutdown_task);
}
+ shutdown_task = NULL;
rcu_torture_onoff_cleanup();
/* Wait for all RCU callbacks to fire. */
@@ -1676,7 +1888,7 @@ rcu_torture_cleanup(void)
if (cur_ops->cleanup)
cur_ops->cleanup();
- if (atomic_read(&n_rcu_torture_error))
+ if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
else if (n_online_successes != n_online_attempts ||
n_offline_successes != n_offline_attempts)
@@ -1692,10 +1904,12 @@ rcu_torture_init(void)
int i;
int cpu;
int firsterr = 0;
+ int retval;
static struct rcu_torture_ops *torture_ops[] =
{ &rcu_ops, &rcu_sync_ops, &rcu_expedited_ops,
&rcu_bh_ops, &rcu_bh_sync_ops, &rcu_bh_expedited_ops,
- &srcu_ops, &srcu_raw_ops, &srcu_expedited_ops,
+ &srcu_ops, &srcu_sync_ops, &srcu_raw_ops,
+ &srcu_raw_sync_ops, &srcu_expedited_ops,
&sched_ops, &sched_sync_ops, &sched_expedited_ops, };
mutex_lock(&fullstop_mutex);
@@ -1749,6 +1963,7 @@ rcu_torture_init(void)
atomic_set(&n_rcu_torture_free, 0);
atomic_set(&n_rcu_torture_mberror, 0);
atomic_set(&n_rcu_torture_error, 0);
+ n_rcu_torture_barrier_error = 0;
n_rcu_torture_boost_ktrerror = 0;
n_rcu_torture_boost_rterror = 0;
n_rcu_torture_boost_failure = 0;
@@ -1872,7 +2087,6 @@ rcu_torture_init(void)
test_boost_duration = 2;
if ((test_boost == 1 && cur_ops->can_boost) ||
test_boost == 2) {
- int retval;
boost_starttime = jiffies + test_boost_interval * HZ;
register_cpu_notifier(&rcutorture_cpu_nb);
@@ -1897,9 +2111,22 @@ rcu_torture_init(void)
goto unwind;
}
}
- rcu_torture_onoff_init();
+ i = rcu_torture_onoff_init();
+ if (i != 0) {
+ firsterr = i;
+ goto unwind;
+ }
register_reboot_notifier(&rcutorture_shutdown_nb);
- rcu_torture_stall_init();
+ i = rcu_torture_stall_init();
+ if (i != 0) {
+ firsterr = i;
+ goto unwind;
+ }
+ retval = rcu_torture_barrier_init();
+ if (retval != 0) {
+ firsterr = retval;
+ goto unwind;
+ }
rcutorture_record_test_transition();
mutex_unlock(&fullstop_mutex);
return 0;
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index d0c5baf1ab18..0da7b88d92d0 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -75,6 +75,8 @@ static struct lock_class_key rcu_node_class[NUM_RCU_LVLS];
.gpnum = -300, \
.completed = -300, \
.onofflock = __RAW_SPIN_LOCK_UNLOCKED(&structname##_state.onofflock), \
+ .orphan_nxttail = &structname##_state.orphan_nxtlist, \
+ .orphan_donetail = &structname##_state.orphan_donelist, \
.fqslock = __RAW_SPIN_LOCK_UNLOCKED(&structname##_state.fqslock), \
.n_force_qs = 0, \
.n_force_qs_ngp = 0, \
@@ -145,6 +147,13 @@ static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp);
unsigned long rcutorture_testseq;
unsigned long rcutorture_vernum;
+/* State information for rcu_barrier() and friends. */
+
+static DEFINE_PER_CPU(struct rcu_head, rcu_barrier_head) = {NULL};
+static atomic_t rcu_barrier_cpu_count;
+static DEFINE_MUTEX(rcu_barrier_mutex);
+static struct completion rcu_barrier_completion;
+
/*
* Return true if an RCU grace period is in progress. The ACCESS_ONCE()s
* permit this function to be invoked without holding the root rcu_node
@@ -192,7 +201,6 @@ void rcu_note_context_switch(int cpu)
{
trace_rcu_utilization("Start context switch");
rcu_sched_qs(cpu);
- rcu_preempt_note_context_switch(cpu);
trace_rcu_utilization("End context switch");
}
EXPORT_SYMBOL_GPL(rcu_note_context_switch);
@@ -1311,95 +1319,133 @@ rcu_check_quiescent_state(struct rcu_state *rsp, struct rcu_data *rdp)
#ifdef CONFIG_HOTPLUG_CPU
/*
- * Move a dying CPU's RCU callbacks to online CPU's callback list.
- * Also record a quiescent state for this CPU for the current grace period.
- * Synchronization and interrupt disabling are not required because
- * this function executes in stop_machine() context. Therefore, cleanup
- * operations that might block must be done later from the CPU_DEAD
- * notifier.
- *
- * Note that the outgoing CPU's bit has already been cleared in the
- * cpu_online_mask. This allows us to randomly pick a callback
- * destination from the bits set in that mask.
+ * Send the specified CPU's RCU callbacks to the orphanage. The
+ * specified CPU must be offline, and the caller must hold the
+ * ->onofflock.
*/
-static void rcu_cleanup_dying_cpu(struct rcu_state *rsp)
+static void
+rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
+ struct rcu_node *rnp, struct rcu_data *rdp)
{
int i;
- unsigned long mask;
- int receive_cpu = cpumask_any(cpu_online_mask);
- struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
- struct rcu_data *receive_rdp = per_cpu_ptr(rsp->rda, receive_cpu);
- RCU_TRACE(struct rcu_node *rnp = rdp->mynode); /* For dying CPU. */
- /* First, adjust the counts. */
+ /*
+ * Orphan the callbacks. First adjust the counts. This is safe
+ * because ->onofflock excludes _rcu_barrier()'s adoption of
+ * the callbacks, thus no memory barrier is required.
+ */
if (rdp->nxtlist != NULL) {
- receive_rdp->qlen_lazy += rdp->qlen_lazy;
- receive_rdp->qlen += rdp->qlen;
+ rsp->qlen_lazy += rdp->qlen_lazy;
+ rsp->qlen += rdp->qlen;
+ rdp->n_cbs_orphaned += rdp->qlen;
rdp->qlen_lazy = 0;
rdp->qlen = 0;
}
/*
- * Next, move ready-to-invoke callbacks to be invoked on some
- * other CPU. These will not be required to pass through another
- * grace period: They are done, regardless of CPU.
+ * Next, move those callbacks still needing a grace period to
+ * the orphanage, where some other CPU will pick them up.
+ * Some of the callbacks might have gone partway through a grace
+ * period, but that is too bad. They get to start over because we
+ * cannot assume that grace periods are synchronized across CPUs.
+ * We don't bother updating the ->nxttail[] array yet, instead
+ * we just reset the whole thing later on.
*/
- if (rdp->nxtlist != NULL &&
- rdp->nxttail[RCU_DONE_TAIL] != &rdp->nxtlist) {
- struct rcu_head *oldhead;
- struct rcu_head **oldtail;
- struct rcu_head **newtail;
-
- oldhead = rdp->nxtlist;
- oldtail = receive_rdp->nxttail[RCU_DONE_TAIL];
- rdp->nxtlist = *rdp->nxttail[RCU_DONE_TAIL];
- *rdp->nxttail[RCU_DONE_TAIL] = *oldtail;
- *receive_rdp->nxttail[RCU_DONE_TAIL] = oldhead;
- newtail = rdp->nxttail[RCU_DONE_TAIL];
- for (i = RCU_DONE_TAIL; i < RCU_NEXT_SIZE; i++) {
- if (receive_rdp->nxttail[i] == oldtail)
- receive_rdp->nxttail[i] = newtail;
- if (rdp->nxttail[i] == newtail)
- rdp->nxttail[i] = &rdp->nxtlist;
- }
+ if (*rdp->nxttail[RCU_DONE_TAIL] != NULL) {
+ *rsp->orphan_nxttail = *rdp->nxttail[RCU_DONE_TAIL];
+ rsp->orphan_nxttail = rdp->nxttail[RCU_NEXT_TAIL];
+ *rdp->nxttail[RCU_DONE_TAIL] = NULL;
}
/*
- * Finally, put the rest of the callbacks at the end of the list.
- * The ones that made it partway through get to start over: We
- * cannot assume that grace periods are synchronized across CPUs.
- * (We could splice RCU_WAIT_TAIL into RCU_NEXT_READY_TAIL, but
- * this does not seem compelling. Not yet, anyway.)
+ * Then move the ready-to-invoke callbacks to the orphanage,
+ * where some other CPU will pick them up. These will not be
+ * required to pass though another grace period: They are done.
*/
if (rdp->nxtlist != NULL) {
- *receive_rdp->nxttail[RCU_NEXT_TAIL] = rdp->nxtlist;
- receive_rdp->nxttail[RCU_NEXT_TAIL] =
- rdp->nxttail[RCU_NEXT_TAIL];
- receive_rdp->n_cbs_adopted += rdp->qlen;
- rdp->n_cbs_orphaned += rdp->qlen;
-
- rdp->nxtlist = NULL;
- for (i = 0; i < RCU_NEXT_SIZE; i++)
- rdp->nxttail[i] = &rdp->nxtlist;
+ *rsp->orphan_donetail = rdp->nxtlist;
+ rsp->orphan_donetail = rdp->nxttail[RCU_DONE_TAIL];
}
+ /* Finally, initialize the rcu_data structure's list to empty. */
+ rdp->nxtlist = NULL;
+ for (i = 0; i < RCU_NEXT_SIZE; i++)
+ rdp->nxttail[i] = &rdp->nxtlist;
+}
+
+/*
+ * Adopt the RCU callbacks from the specified rcu_state structure's
+ * orphanage. The caller must hold the ->onofflock.
+ */
+static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
+{
+ int i;
+ struct rcu_data *rdp = __this_cpu_ptr(rsp->rda);
+
/*
- * Record a quiescent state for the dying CPU. This is safe
- * only because we have already cleared out the callbacks.
- * (Otherwise, the RCU core might try to schedule the invocation
- * of callbacks on this now-offline CPU, which would be bad.)
+ * If there is an rcu_barrier() operation in progress, then
+ * only the task doing that operation is permitted to adopt
+ * callbacks. To do otherwise breaks rcu_barrier() and friends
+ * by causing them to fail to wait for the callbacks in the
+ * orphanage.
*/
- mask = rdp->grpmask; /* rnp->grplo is constant. */
+ if (rsp->rcu_barrier_in_progress &&
+ rsp->rcu_barrier_in_progress != current)
+ return;
+
+ /* Do the accounting first. */
+ rdp->qlen_lazy += rsp->qlen_lazy;
+ rdp->qlen += rsp->qlen;
+ rdp->n_cbs_adopted += rsp->qlen;
+ rsp->qlen_lazy = 0;
+ rsp->qlen = 0;
+
+ /*
+ * We do not need a memory barrier here because the only way we
+ * can get here if there is an rcu_barrier() in flight is if
+ * we are the task doing the rcu_barrier().
+ */
+
+ /* First adopt the ready-to-invoke callbacks. */
+ if (rsp->orphan_donelist != NULL) {
+ *rsp->orphan_donetail = *rdp->nxttail[RCU_DONE_TAIL];
+ *rdp->nxttail[RCU_DONE_TAIL] = rsp->orphan_donelist;
+ for (i = RCU_NEXT_SIZE - 1; i >= RCU_DONE_TAIL; i--)
+ if (rdp->nxttail[i] == rdp->nxttail[RCU_DONE_TAIL])
+ rdp->nxttail[i] = rsp->orphan_donetail;
+ rsp->orphan_donelist = NULL;
+ rsp->orphan_donetail = &rsp->orphan_donelist;
+ }
+
+ /* And then adopt the callbacks that still need a grace period. */
+ if (rsp->orphan_nxtlist != NULL) {
+ *rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_nxtlist;
+ rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_nxttail;
+ rsp->orphan_nxtlist = NULL;
+ rsp->orphan_nxttail = &rsp->orphan_nxtlist;
+ }
+}
+
+/*
+ * Trace the fact that this CPU is going offline.
+ */
+static void rcu_cleanup_dying_cpu(struct rcu_state *rsp)
+{
+ RCU_TRACE(unsigned long mask);
+ RCU_TRACE(struct rcu_data *rdp = this_cpu_ptr(rsp->rda));
+ RCU_TRACE(struct rcu_node *rnp = rdp->mynode);
+
+ RCU_TRACE(mask = rdp->grpmask);
trace_rcu_grace_period(rsp->name,
rnp->gpnum + 1 - !!(rnp->qsmask & mask),
"cpuofl");
- rcu_report_qs_rdp(smp_processor_id(), rsp, rdp, rsp->gpnum);
- /* Note that rcu_report_qs_rdp() might call trace_rcu_grace_period(). */
}
/*
* The CPU has been completely removed, and some other CPU is reporting
- * this fact from process context. Do the remainder of the cleanup.
+ * this fact from process context. Do the remainder of the cleanup,
+ * including orphaning the outgoing CPU's RCU callbacks, and also
+ * adopting them, if there is no _rcu_barrier() instance running.
* There can only be one CPU hotplug operation at a time, so no other
* CPU can be attempting to update rcu_cpu_kthread_task.
*/
@@ -1409,17 +1455,21 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
unsigned long mask;
int need_report = 0;
struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
- struct rcu_node *rnp = rdp->mynode; /* Outgoing CPU's rnp. */
+ struct rcu_node *rnp = rdp->mynode; /* Outgoing CPU's rdp & rnp. */
/* Adjust any no-longer-needed kthreads. */
rcu_stop_cpu_kthread(cpu);
rcu_node_kthread_setaffinity(rnp, -1);
- /* Remove the dying CPU from the bitmasks in the rcu_node hierarchy. */
+ /* Remove the dead CPU from the bitmasks in the rcu_node hierarchy. */
/* Exclude any attempts to start a new grace period. */
raw_spin_lock_irqsave(&rsp->onofflock, flags);
+ /* Orphan the dead CPU's callbacks, and adopt them if appropriate. */
+ rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp);
+ rcu_adopt_orphan_cbs(rsp);
+
/* Remove the outgoing CPU from the masks in the rcu_node hierarchy. */
mask = rdp->grpmask; /* rnp->grplo is constant. */
do {
@@ -1456,6 +1506,10 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
#else /* #ifdef CONFIG_HOTPLUG_CPU */
+static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
+{
+}
+
static void rcu_cleanup_dying_cpu(struct rcu_state *rsp)
{
}
@@ -1524,9 +1578,6 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
rcu_is_callbacks_kthread());
/* Update count, and requeue any remaining callbacks. */
- rdp->qlen_lazy -= count_lazy;
- rdp->qlen -= count;
- rdp->n_cbs_invoked += count;
if (list != NULL) {
*tail = rdp->nxtlist;
rdp->nxtlist = list;
@@ -1536,6 +1587,10 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
else
break;
}
+ smp_mb(); /* List handling before counting for rcu_barrier(). */
+ rdp->qlen_lazy -= count_lazy;
+ rdp->qlen -= count;
+ rdp->n_cbs_invoked += count;
/* Reinstate batch limit if we have worked down the excess. */
if (rdp->blimit == LONG_MAX && rdp->qlen <= qlowmark)
@@ -1823,11 +1878,14 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
rdp = this_cpu_ptr(rsp->rda);
/* Add the callback to our list. */
- *rdp->nxttail[RCU_NEXT_TAIL] = head;
- rdp->nxttail[RCU_NEXT_TAIL] = &head->next;
rdp->qlen++;
if (lazy)
rdp->qlen_lazy++;
+ else
+ rcu_idle_count_callbacks_posted();
+ smp_mb(); /* Count before adding callback for rcu_barrier(). */
+ *rdp->nxttail[RCU_NEXT_TAIL] = head;
+ rdp->nxttail[RCU_NEXT_TAIL] = &head->next;
if (__is_kfree_rcu_offset((unsigned long)func))
trace_rcu_kfree_callback(rsp->name, head, (unsigned long)func,
@@ -1893,6 +1951,38 @@ void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
}
EXPORT_SYMBOL_GPL(call_rcu_bh);
+/*
+ * Because a context switch is a grace period for RCU-sched and RCU-bh,
+ * any blocking grace-period wait automatically implies a grace period
+ * if there is only one CPU online at any point time during execution
+ * of either synchronize_sched() or synchronize_rcu_bh(). It is OK to
+ * occasionally incorrectly indicate that there are multiple CPUs online
+ * when there was in fact only one the whole time, as this just adds
+ * some overhead: RCU still operates correctly.
+ *
+ * Of course, sampling num_online_cpus() with preemption enabled can
+ * give erroneous results if there are concurrent CPU-hotplug operations.
+ * For example, given a demonic sequence of preemptions in num_online_cpus()
+ * and CPU-hotplug operations, there could be two or more CPUs online at
+ * all times, but num_online_cpus() might well return one (or even zero).
+ *
+ * However, all such demonic sequences require at least one CPU-offline
+ * operation. Furthermore, rcu_blocking_is_gp() giving the wrong answer
+ * is only a problem if there is an RCU read-side critical section executing
+ * throughout. But RCU-sched and RCU-bh read-side critical sections
+ * disable either preemption or bh, which prevents a CPU from going offline.
+ * Therefore, the only way that rcu_blocking_is_gp() can incorrectly return
+ * that there is only one CPU when in fact there was more than one throughout
+ * is when there were no RCU readers in the system. If there are no
+ * RCU readers, the grace period by definition can be of zero length,
+ * regardless of the number of online CPUs.
+ */
+static inline int rcu_blocking_is_gp(void)
+{
+ might_sleep(); /* Check for RCU read-side critical section. */
+ return num_online_cpus() <= 1;
+}
+
/**
* synchronize_sched - wait until an rcu-sched grace period has elapsed.
*
@@ -2166,11 +2256,10 @@ static int rcu_cpu_has_callbacks(int cpu)
rcu_preempt_cpu_has_callbacks(cpu);
}
-static DEFINE_PER_CPU(struct rcu_head, rcu_barrier_head) = {NULL};
-static atomic_t rcu_barrier_cpu_count;
-static DEFINE_MUTEX(rcu_barrier_mutex);
-static struct completion rcu_barrier_completion;
-
+/*
+ * RCU callback function for _rcu_barrier(). If we are last, wake
+ * up the task executing _rcu_barrier().
+ */
static void rcu_barrier_callback(struct rcu_head *notused)
{
if (atomic_dec_and_test(&rcu_barrier_cpu_count))
@@ -2200,27 +2289,94 @@ static void _rcu_barrier(struct rcu_state *rsp,
void (*call_rcu_func)(struct rcu_head *head,
void (*func)(struct rcu_head *head)))
{
- BUG_ON(in_interrupt());
+ int cpu;
+ unsigned long flags;
+ struct rcu_data *rdp;
+ struct rcu_head rh;
+
+ init_rcu_head_on_stack(&rh);
+
/* Take mutex to serialize concurrent rcu_barrier() requests. */
mutex_lock(&rcu_barrier_mutex);
- init_completion(&rcu_barrier_completion);
+
+ smp_mb(); /* Prevent any prior operations from leaking in. */
+
/*
- * Initialize rcu_barrier_cpu_count to 1, then invoke
- * rcu_barrier_func() on each CPU, so that each CPU also has
- * incremented rcu_barrier_cpu_count. Only then is it safe to
- * decrement rcu_barrier_cpu_count -- otherwise the first CPU
- * might complete its grace period before all of the other CPUs
- * did their increment, causing this function to return too
- * early. Note that on_each_cpu() disables irqs, which prevents
- * any CPUs from coming online or going offline until each online
- * CPU has queued its RCU-barrier callback.
+ * Initialize the count to one rather than to zero in order to
+ * avoid a too-soon return to zero in case of a short grace period
+ * (or preemption of this task). Also flag this task as doing
+ * an rcu_barrier(). This will prevent anyone else from adopting
+ * orphaned callbacks, which could cause otherwise failure if a
+ * CPU went offline and quickly came back online. To see this,
+ * consider the following sequence of events:
+ *
+ * 1. We cause CPU 0 to post an rcu_barrier_callback() callback.
+ * 2. CPU 1 goes offline, orphaning its callbacks.
+ * 3. CPU 0 adopts CPU 1's orphaned callbacks.
+ * 4. CPU 1 comes back online.
+ * 5. We cause CPU 1 to post an rcu_barrier_callback() callback.
+ * 6. Both rcu_barrier_callback() callbacks are invoked, awakening
+ * us -- but before CPU 1's orphaned callbacks are invoked!!!
*/
+ init_completion(&rcu_barrier_completion);
atomic_set(&rcu_barrier_cpu_count, 1);
- on_each_cpu(rcu_barrier_func, (void *)call_rcu_func, 1);
+ raw_spin_lock_irqsave(&rsp->onofflock, flags);
+ rsp->rcu_barrier_in_progress = current;
+ raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
+
+ /*
+ * Force every CPU with callbacks to register a new callback
+ * that will tell us when all the preceding callbacks have
+ * been invoked. If an offline CPU has callbacks, wait for
+ * it to either come back online or to finish orphaning those
+ * callbacks.
+ */
+ for_each_possible_cpu(cpu) {
+ preempt_disable();
+ rdp = per_cpu_ptr(rsp->rda, cpu);
+ if (cpu_is_offline(cpu)) {
+ preempt_enable();
+ while (cpu_is_offline(cpu) && ACCESS_ONCE(rdp->qlen))
+ schedule_timeout_interruptible(1);
+ } else if (ACCESS_ONCE(rdp->qlen)) {
+ smp_call_function_single(cpu, rcu_barrier_func,
+ (void *)call_rcu_func, 1);
+ preempt_enable();
+ } else {
+ preempt_enable();
+ }
+ }
+
+ /*
+ * Now that all online CPUs have rcu_barrier_callback() callbacks
+ * posted, we can adopt all of the orphaned callbacks and place
+ * an rcu_barrier_callback() callback after them. When that is done,
+ * we are guaranteed to have an rcu_barrier_callback() callback
+ * following every callback that could possibly have been
+ * registered before _rcu_barrier() was called.
+ */
+ raw_spin_lock_irqsave(&rsp->onofflock, flags);
+ rcu_adopt_orphan_cbs(rsp);
+ rsp->rcu_barrier_in_progress = NULL;
+ raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
+ atomic_inc(&rcu_barrier_cpu_count);
+ smp_mb__after_atomic_inc(); /* Ensure atomic_inc() before callback. */
+ call_rcu_func(&rh, rcu_barrier_callback);
+
+ /*
+ * Now that we have an rcu_barrier_callback() callback on each
+ * CPU, and thus each counted, remove the initial count.
+ */
if (atomic_dec_and_test(&rcu_barrier_cpu_count))
complete(&rcu_barrier_completion);
+
+ /* Wait for all rcu_barrier_callback() callbacks to be invoked. */
wait_for_completion(&rcu_barrier_completion);
+
+ /* Other rcu_barrier() invocations can now safely proceed. */
mutex_unlock(&rcu_barrier_mutex);
+
+ destroy_rcu_head_on_stack(&rh);
}
/**
@@ -2417,7 +2573,7 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp)
for (i = NUM_RCU_LVLS - 1; i > 0; i--)
rsp->levelspread[i] = CONFIG_RCU_FANOUT;
- rsp->levelspread[0] = RCU_FANOUT_LEAF;
+ rsp->levelspread[0] = CONFIG_RCU_FANOUT_LEAF;
}
#else /* #ifdef CONFIG_RCU_FANOUT_EXACT */
static void __init rcu_init_levelspread(struct rcu_state *rsp)
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index cdd1be0a4072..7f5d138dedf5 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -29,18 +29,14 @@
#include <linux/seqlock.h>
/*
- * Define shape of hierarchy based on NR_CPUS and CONFIG_RCU_FANOUT.
+ * Define shape of hierarchy based on NR_CPUS, CONFIG_RCU_FANOUT, and
+ * CONFIG_RCU_FANOUT_LEAF.
* In theory, it should be possible to add more levels straightforwardly.
* In practice, this did work well going from three levels to four.
* Of course, your mileage may vary.
*/
#define MAX_RCU_LVLS 4
-#if CONFIG_RCU_FANOUT > 16
-#define RCU_FANOUT_LEAF 16
-#else /* #if CONFIG_RCU_FANOUT > 16 */
-#define RCU_FANOUT_LEAF (CONFIG_RCU_FANOUT)
-#endif /* #else #if CONFIG_RCU_FANOUT > 16 */
-#define RCU_FANOUT_1 (RCU_FANOUT_LEAF)
+#define RCU_FANOUT_1 (CONFIG_RCU_FANOUT_LEAF)
#define RCU_FANOUT_2 (RCU_FANOUT_1 * CONFIG_RCU_FANOUT)
#define RCU_FANOUT_3 (RCU_FANOUT_2 * CONFIG_RCU_FANOUT)
#define RCU_FANOUT_4 (RCU_FANOUT_3 * CONFIG_RCU_FANOUT)
@@ -371,6 +367,17 @@ struct rcu_state {
raw_spinlock_t onofflock; /* exclude on/offline and */
/* starting new GP. */
+ struct rcu_head *orphan_nxtlist; /* Orphaned callbacks that */
+ /* need a grace period. */
+ struct rcu_head **orphan_nxttail; /* Tail of above. */
+ struct rcu_head *orphan_donelist; /* Orphaned callbacks that */
+ /* are ready to invoke. */
+ struct rcu_head **orphan_donetail; /* Tail of above. */
+ long qlen_lazy; /* Number of lazy callbacks. */
+ long qlen; /* Total number of callbacks. */
+ struct task_struct *rcu_barrier_in_progress;
+ /* Task doing rcu_barrier(), */
+ /* or NULL if no barrier. */
raw_spinlock_t fqslock; /* Only one task forcing */
/* quiescent states. */
unsigned long jiffies_force_qs; /* Time at which to invoke */
@@ -423,7 +430,6 @@ DECLARE_PER_CPU(char, rcu_cpu_has_work);
/* Forward declarations for rcutree_plugin.h */
static void rcu_bootup_announce(void);
long rcu_batches_completed(void);
-static void rcu_preempt_note_context_switch(int cpu);
static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp);
#ifdef CONFIG_HOTPLUG_CPU
static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp,
@@ -471,6 +477,7 @@ static void __cpuinit rcu_prepare_kthreads(int cpu);
static void rcu_prepare_for_idle_init(int cpu);
static void rcu_cleanup_after_idle(int cpu);
static void rcu_prepare_for_idle(int cpu);
+static void rcu_idle_count_callbacks_posted(void);
static void print_cpu_stall_info_begin(void);
static void print_cpu_stall_info(struct rcu_state *rsp, int cpu);
static void print_cpu_stall_info_end(void);
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index c023464816be..2411000d9869 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -153,7 +153,7 @@ static void rcu_preempt_qs(int cpu)
*
* Caller must disable preemption.
*/
-static void rcu_preempt_note_context_switch(int cpu)
+void rcu_preempt_note_context_switch(void)
{
struct task_struct *t = current;
unsigned long flags;
@@ -164,7 +164,7 @@ static void rcu_preempt_note_context_switch(int cpu)
(t->rcu_read_unlock_special & RCU_READ_UNLOCK_BLOCKED) == 0) {
/* Possibly blocking in an RCU read-side critical section. */
- rdp = per_cpu_ptr(rcu_preempt_state.rda, cpu);
+ rdp = __this_cpu_ptr(rcu_preempt_state.rda);
rnp = rdp->mynode;
raw_spin_lock_irqsave(&rnp->lock, flags);
t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED;
@@ -228,7 +228,7 @@ static void rcu_preempt_note_context_switch(int cpu)
* means that we continue to block the current grace period.
*/
local_irq_save(flags);
- rcu_preempt_qs(cpu);
+ rcu_preempt_qs(smp_processor_id());
local_irq_restore(flags);
}
@@ -969,22 +969,6 @@ static void __init __rcu_init_preempt(void)
rcu_init_one(&rcu_preempt_state, &rcu_preempt_data);
}
-/*
- * Check for a task exiting while in a preemptible-RCU read-side
- * critical section, clean up if so. No need to issue warnings,
- * as debug_check_no_locks_held() already does this if lockdep
- * is enabled.
- */
-void exit_rcu(void)
-{
- struct task_struct *t = current;
-
- if (t->rcu_read_lock_nesting == 0)
- return;
- t->rcu_read_lock_nesting = 1;
- __rcu_read_unlock();
-}
-
#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
static struct rcu_state *rcu_state = &rcu_sched_state;
@@ -1018,14 +1002,6 @@ void rcu_force_quiescent_state(void)
EXPORT_SYMBOL_GPL(rcu_force_quiescent_state);
/*
- * Because preemptible RCU does not exist, we never have to check for
- * CPUs being in quiescent states.
- */
-static void rcu_preempt_note_context_switch(int cpu)
-{
-}
-
-/*
* Because preemptible RCU does not exist, there are never any preempted
* RCU readers.
*/
@@ -1938,6 +1914,14 @@ static void rcu_prepare_for_idle(int cpu)
{
}
+/*
+ * Don't bother keeping a running count of the number of RCU callbacks
+ * posted because CONFIG_RCU_FAST_NO_HZ=n.
+ */
+static void rcu_idle_count_callbacks_posted(void)
+{
+}
+
#else /* #if !defined(CONFIG_RCU_FAST_NO_HZ) */
/*
@@ -1978,11 +1962,20 @@ static void rcu_prepare_for_idle(int cpu)
#define RCU_IDLE_GP_DELAY 6 /* Roughly one grace period. */
#define RCU_IDLE_LAZY_GP_DELAY (6 * HZ) /* Roughly six seconds. */
+/* Loop counter for rcu_prepare_for_idle(). */
static DEFINE_PER_CPU(int, rcu_dyntick_drain);
+/* If rcu_dyntick_holdoff==jiffies, don't try to enter dyntick-idle mode. */
static DEFINE_PER_CPU(unsigned long, rcu_dyntick_holdoff);
-static DEFINE_PER_CPU(struct hrtimer, rcu_idle_gp_timer);
-static ktime_t rcu_idle_gp_wait; /* If some non-lazy callbacks. */
-static ktime_t rcu_idle_lazy_gp_wait; /* If only lazy callbacks. */
+/* Timer to awaken the CPU if it enters dyntick-idle mode with callbacks. */
+static DEFINE_PER_CPU(struct timer_list, rcu_idle_gp_timer);
+/* Scheduled expiry time for rcu_idle_gp_timer to allow reposting. */
+static DEFINE_PER_CPU(unsigned long, rcu_idle_gp_timer_expires);
+/* Enable special processing on first attempt to enter dyntick-idle mode. */
+static DEFINE_PER_CPU(bool, rcu_idle_first_pass);
+/* Running count of non-lazy callbacks posted, never decremented. */
+static DEFINE_PER_CPU(unsigned long, rcu_nonlazy_posted);
+/* Snapshot of rcu_nonlazy_posted to detect meaningful exits from idle. */
+static DEFINE_PER_CPU(unsigned long, rcu_nonlazy_posted_snap);
/*
* Allow the CPU to enter dyntick-idle mode if either: (1) There are no
@@ -1995,6 +1988,8 @@ static ktime_t rcu_idle_lazy_gp_wait; /* If only lazy callbacks. */
*/
int rcu_needs_cpu(int cpu)
{
+ /* Flag a new idle sojourn to the idle-entry state machine. */
+ per_cpu(rcu_idle_first_pass, cpu) = 1;
/* If no callbacks, RCU doesn't need the CPU. */
if (!rcu_cpu_has_callbacks(cpu))
return 0;
@@ -2045,16 +2040,34 @@ static bool rcu_cpu_has_nonlazy_callbacks(int cpu)
}
/*
+ * Handler for smp_call_function_single(). The only point of this
+ * handler is to wake the CPU up, so the handler does only tracing.
+ */
+void rcu_idle_demigrate(void *unused)
+{
+ trace_rcu_prep_idle("Demigrate");
+}
+
+/*
* Timer handler used to force CPU to start pushing its remaining RCU
* callbacks in the case where it entered dyntick-idle mode with callbacks
* pending. The hander doesn't really need to do anything because the
* real work is done upon re-entry to idle, or by the next scheduling-clock
* interrupt should idle not be re-entered.
+ *
+ * One special case: the timer gets migrated without awakening the CPU
+ * on which the timer was scheduled on. In this case, we must wake up
+ * that CPU. We do so with smp_call_function_single().
*/
-static enum hrtimer_restart rcu_idle_gp_timer_func(struct hrtimer *hrtp)
+static void rcu_idle_gp_timer_func(unsigned long cpu_in)
{
+ int cpu = (int)cpu_in;
+
trace_rcu_prep_idle("Timer");
- return HRTIMER_NORESTART;
+ if (cpu != smp_processor_id())
+ smp_call_function_single(cpu, rcu_idle_demigrate, NULL, 0);
+ else
+ WARN_ON_ONCE(1); /* Getting here can hang the system... */
}
/*
@@ -2062,19 +2075,11 @@ static enum hrtimer_restart rcu_idle_gp_timer_func(struct hrtimer *hrtp)
*/
static void rcu_prepare_for_idle_init(int cpu)
{
- static int firsttime = 1;
- struct hrtimer *hrtp = &per_cpu(rcu_idle_gp_timer, cpu);
-
- hrtimer_init(hrtp, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- hrtp->function = rcu_idle_gp_timer_func;
- if (firsttime) {
- unsigned int upj = jiffies_to_usecs(RCU_IDLE_GP_DELAY);
-
- rcu_idle_gp_wait = ns_to_ktime(upj * (u64)1000);
- upj = jiffies_to_usecs(RCU_IDLE_LAZY_GP_DELAY);
- rcu_idle_lazy_gp_wait = ns_to_ktime(upj * (u64)1000);
- firsttime = 0;
- }
+ per_cpu(rcu_dyntick_holdoff, cpu) = jiffies - 1;
+ setup_timer(&per_cpu(rcu_idle_gp_timer, cpu),
+ rcu_idle_gp_timer_func, cpu);
+ per_cpu(rcu_idle_gp_timer_expires, cpu) = jiffies - 1;
+ per_cpu(rcu_idle_first_pass, cpu) = 1;
}
/*
@@ -2084,7 +2089,8 @@ static void rcu_prepare_for_idle_init(int cpu)
*/
static void rcu_cleanup_after_idle(int cpu)
{
- hrtimer_cancel(&per_cpu(rcu_idle_gp_timer, cpu));
+ del_timer(&per_cpu(rcu_idle_gp_timer, cpu));
+ trace_rcu_prep_idle("Cleanup after idle");
}
/*
@@ -2108,6 +2114,29 @@ static void rcu_cleanup_after_idle(int cpu)
*/
static void rcu_prepare_for_idle(int cpu)
{
+ struct timer_list *tp;
+
+ /*
+ * If this is an idle re-entry, for example, due to use of
+ * RCU_NONIDLE() or the new idle-loop tracing API within the idle
+ * loop, then don't take any state-machine actions, unless the
+ * momentary exit from idle queued additional non-lazy callbacks.
+ * Instead, repost the rcu_idle_gp_timer if this CPU has callbacks
+ * pending.
+ */
+ if (!per_cpu(rcu_idle_first_pass, cpu) &&
+ (per_cpu(rcu_nonlazy_posted, cpu) ==
+ per_cpu(rcu_nonlazy_posted_snap, cpu))) {
+ if (rcu_cpu_has_callbacks(cpu)) {
+ tp = &per_cpu(rcu_idle_gp_timer, cpu);
+ mod_timer_pinned(tp, per_cpu(rcu_idle_gp_timer_expires, cpu));
+ }
+ return;
+ }
+ per_cpu(rcu_idle_first_pass, cpu) = 0;
+ per_cpu(rcu_nonlazy_posted_snap, cpu) =
+ per_cpu(rcu_nonlazy_posted, cpu) - 1;
+
/*
* If there are no callbacks on this CPU, enter dyntick-idle mode.
* Also reset state to avoid prejudicing later attempts.
@@ -2140,11 +2169,15 @@ static void rcu_prepare_for_idle(int cpu)
per_cpu(rcu_dyntick_drain, cpu) = 0;
per_cpu(rcu_dyntick_holdoff, cpu) = jiffies;
if (rcu_cpu_has_nonlazy_callbacks(cpu))
- hrtimer_start(&per_cpu(rcu_idle_gp_timer, cpu),
- rcu_idle_gp_wait, HRTIMER_MODE_REL);
+ per_cpu(rcu_idle_gp_timer_expires, cpu) =
+ jiffies + RCU_IDLE_GP_DELAY;
else
- hrtimer_start(&per_cpu(rcu_idle_gp_timer, cpu),
- rcu_idle_lazy_gp_wait, HRTIMER_MODE_REL);
+ per_cpu(rcu_idle_gp_timer_expires, cpu) =
+ jiffies + RCU_IDLE_LAZY_GP_DELAY;
+ tp = &per_cpu(rcu_idle_gp_timer, cpu);
+ mod_timer_pinned(tp, per_cpu(rcu_idle_gp_timer_expires, cpu));
+ per_cpu(rcu_nonlazy_posted_snap, cpu) =
+ per_cpu(rcu_nonlazy_posted, cpu);
return; /* Nothing more to do immediately. */
} else if (--per_cpu(rcu_dyntick_drain, cpu) <= 0) {
/* We have hit the limit, so time to give up. */
@@ -2184,6 +2217,19 @@ static void rcu_prepare_for_idle(int cpu)
trace_rcu_prep_idle("Callbacks drained");
}
+/*
+ * Keep a running count of the number of non-lazy callbacks posted
+ * on this CPU. This running counter (which is never decremented) allows
+ * rcu_prepare_for_idle() to detect when something out of the idle loop
+ * posts a callback, even if an equal number of callbacks are invoked.
+ * Of course, callbacks should only be posted from within a trace event
+ * designed to be called from idle or from within RCU_NONIDLE().
+ */
+static void rcu_idle_count_callbacks_posted(void)
+{
+ __this_cpu_add(rcu_nonlazy_posted, 1);
+}
+
#endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */
#ifdef CONFIG_RCU_CPU_STALL_INFO
@@ -2192,14 +2238,12 @@ static void rcu_prepare_for_idle(int cpu)
static void print_cpu_stall_fast_no_hz(char *cp, int cpu)
{
- struct hrtimer *hrtp = &per_cpu(rcu_idle_gp_timer, cpu);
+ struct timer_list *tltp = &per_cpu(rcu_idle_gp_timer, cpu);
- sprintf(cp, "drain=%d %c timer=%lld",
+ sprintf(cp, "drain=%d %c timer=%lu",
per_cpu(rcu_dyntick_drain, cpu),
per_cpu(rcu_dyntick_holdoff, cpu) == jiffies ? 'H' : '.',
- hrtimer_active(hrtp)
- ? ktime_to_us(hrtimer_get_remaining(hrtp))
- : -1);
+ timer_pending(tltp) ? tltp->expires - jiffies : -1);
}
#else /* #ifdef CONFIG_RCU_FAST_NO_HZ */
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c
index ed459edeff43..d4bc16ddd1d4 100644
--- a/kernel/rcutree_trace.c
+++ b/kernel/rcutree_trace.c
@@ -271,13 +271,13 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
gpnum = rsp->gpnum;
seq_printf(m, "c=%lu g=%lu s=%d jfq=%ld j=%x "
- "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu\n",
+ "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n",
rsp->completed, gpnum, rsp->fqs_state,
(long)(rsp->jiffies_force_qs - jiffies),
(int)(jiffies & 0xffff),
rsp->n_force_qs, rsp->n_force_qs_ngp,
rsp->n_force_qs - rsp->n_force_qs_ngp,
- rsp->n_force_qs_lh);
+ rsp->n_force_qs_lh, rsp->qlen_lazy, rsp->qlen);
for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < NUM_RCU_NODES; rnp++) {
if (rnp->level != level) {
seq_puts(m, "\n");
diff --git a/kernel/res_counter.c b/kernel/res_counter.c
index d508363858b3..bebe2b170d49 100644
--- a/kernel/res_counter.c
+++ b/kernel/res_counter.c
@@ -22,75 +22,70 @@ void res_counter_init(struct res_counter *counter, struct res_counter *parent)
counter->parent = parent;
}
-int res_counter_charge_locked(struct res_counter *counter, unsigned long val)
+int res_counter_charge_locked(struct res_counter *counter, unsigned long val,
+ bool force)
{
+ int ret = 0;
+
if (counter->usage + val > counter->limit) {
counter->failcnt++;
- return -ENOMEM;
+ ret = -ENOMEM;
+ if (!force)
+ return ret;
}
counter->usage += val;
if (counter->usage > counter->max_usage)
counter->max_usage = counter->usage;
- return 0;
+ return ret;
}
-int res_counter_charge(struct res_counter *counter, unsigned long val,
- struct res_counter **limit_fail_at)
+static int __res_counter_charge(struct res_counter *counter, unsigned long val,
+ struct res_counter **limit_fail_at, bool force)
{
- int ret;
+ int ret, r;
unsigned long flags;
struct res_counter *c, *u;
+ r = ret = 0;
*limit_fail_at = NULL;
local_irq_save(flags);
for (c = counter; c != NULL; c = c->parent) {
spin_lock(&c->lock);
- ret = res_counter_charge_locked(c, val);
+ r = res_counter_charge_locked(c, val, force);
spin_unlock(&c->lock);
- if (ret < 0) {
+ if (r < 0 && !ret) {
+ ret = r;
*limit_fail_at = c;
- goto undo;
+ if (!force)
+ break;
}
}
- ret = 0;
- goto done;
-undo:
- for (u = counter; u != c; u = u->parent) {
- spin_lock(&u->lock);
- res_counter_uncharge_locked(u, val);
- spin_unlock(&u->lock);
+
+ if (ret < 0 && !force) {
+ for (u = counter; u != c; u = u->parent) {
+ spin_lock(&u->lock);
+ res_counter_uncharge_locked(u, val);
+ spin_unlock(&u->lock);
+ }
}
-done:
local_irq_restore(flags);
+
return ret;
}
+int res_counter_charge(struct res_counter *counter, unsigned long val,
+ struct res_counter **limit_fail_at)
+{
+ return __res_counter_charge(counter, val, limit_fail_at, false);
+}
+
int res_counter_charge_nofail(struct res_counter *counter, unsigned long val,
struct res_counter **limit_fail_at)
{
- int ret, r;
- unsigned long flags;
- struct res_counter *c;
-
- r = ret = 0;
- *limit_fail_at = NULL;
- local_irq_save(flags);
- for (c = counter; c != NULL; c = c->parent) {
- spin_lock(&c->lock);
- r = res_counter_charge_locked(c, val);
- if (r)
- c->usage += val;
- spin_unlock(&c->lock);
- if (r < 0 && ret == 0) {
- *limit_fail_at = c;
- ret = r;
- }
- }
- local_irq_restore(flags);
-
- return ret;
+ return __res_counter_charge(counter, val, limit_fail_at, true);
}
+
void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val)
{
if (WARN_ON(counter->usage < val))
diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
index 9a7dd35102a3..173ea52f3af0 100644
--- a/kernel/sched/Makefile
+++ b/kernel/sched/Makefile
@@ -16,5 +16,3 @@ obj-$(CONFIG_SMP) += cpupri.o
obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
obj-$(CONFIG_SCHEDSTATS) += stats.o
obj-$(CONFIG_SCHED_DEBUG) += debug.o
-
-
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 0533a688ce22..a5a9d39b845c 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -83,6 +83,7 @@
#include "sched.h"
#include "../workqueue_sched.h"
+#include "../smpboot.h"
#define CREATE_TRACE_POINTS
#include <trace/events/sched.h>
@@ -692,8 +693,6 @@ int tg_nop(struct task_group *tg, void *data)
}
#endif
-void update_cpu_load(struct rq *this_rq);
-
static void set_load_weight(struct task_struct *p)
{
int prio = p->static_prio - MAX_RT_PRIO;
@@ -2083,6 +2082,7 @@ context_switch(struct rq *rq, struct task_struct *prev,
#endif
/* Here we just switch the register state and the stack. */
+ rcu_switch_from(prev);
switch_to(prev, next, prev);
barrier();
@@ -2486,22 +2486,13 @@ decay_load_missed(unsigned long load, unsigned long missed_updates, int idx)
* scheduler tick (TICK_NSEC). With tickless idle this will not be called
* every tick. We fix it up based on jiffies.
*/
-void update_cpu_load(struct rq *this_rq)
+static void __update_cpu_load(struct rq *this_rq, unsigned long this_load,
+ unsigned long pending_updates)
{
- unsigned long this_load = this_rq->load.weight;
- unsigned long curr_jiffies = jiffies;
- unsigned long pending_updates;
int i, scale;
this_rq->nr_load_updates++;
- /* Avoid repeated calls on same jiffy, when moving in and out of idle */
- if (curr_jiffies == this_rq->last_load_update_tick)
- return;
-
- pending_updates = curr_jiffies - this_rq->last_load_update_tick;
- this_rq->last_load_update_tick = curr_jiffies;
-
/* Update our load: */
this_rq->cpu_load[0] = this_load; /* Fasttrack for idx 0 */
for (i = 1, scale = 2; i < CPU_LOAD_IDX_MAX; i++, scale += scale) {
@@ -2526,9 +2517,45 @@ void update_cpu_load(struct rq *this_rq)
sched_avg_update(this_rq);
}
+/*
+ * Called from nohz_idle_balance() to update the load ratings before doing the
+ * idle balance.
+ */
+void update_idle_cpu_load(struct rq *this_rq)
+{
+ unsigned long curr_jiffies = jiffies;
+ unsigned long load = this_rq->load.weight;
+ unsigned long pending_updates;
+
+ /*
+ * Bloody broken means of dealing with nohz, but better than nothing..
+ * jiffies is updated by one cpu, another cpu can drift wrt the jiffy
+ * update and see 0 difference the one time and 2 the next, even though
+ * we ticked at roughtly the same rate.
+ *
+ * Hence we only use this from nohz_idle_balance() and skip this
+ * nonsense when called from the scheduler_tick() since that's
+ * guaranteed a stable rate.
+ */
+ if (load || curr_jiffies == this_rq->last_load_update_tick)
+ return;
+
+ pending_updates = curr_jiffies - this_rq->last_load_update_tick;
+ this_rq->last_load_update_tick = curr_jiffies;
+
+ __update_cpu_load(this_rq, load, pending_updates);
+}
+
+/*
+ * Called from scheduler_tick()
+ */
static void update_cpu_load_active(struct rq *this_rq)
{
- update_cpu_load(this_rq);
+ /*
+ * See the mess in update_idle_cpu_load().
+ */
+ this_rq->last_load_update_tick = jiffies;
+ __update_cpu_load(this_rq, this_rq->load.weight, 1);
calc_load_account_active(this_rq);
}
@@ -3113,6 +3140,7 @@ static noinline void __schedule_bug(struct task_struct *prev)
if (irqs_disabled())
print_irqtrace_events(prev);
dump_stack();
+ add_taint(TAINT_WARN);
}
/*
@@ -5560,7 +5588,8 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
break;
}
- if (cpumask_intersects(groupmask, sched_group_cpus(group))) {
+ if (!(sd->flags & SD_OVERLAP) &&
+ cpumask_intersects(groupmask, sched_group_cpus(group))) {
printk(KERN_CONT "\n");
printk(KERN_ERR "ERROR: repeated CPUs\n");
break;
@@ -5898,99 +5927,11 @@ static int __init isolated_cpu_setup(char *str)
__setup("isolcpus=", isolated_cpu_setup);
-#ifdef CONFIG_NUMA
-
-/**
- * find_next_best_node - find the next node to include in a sched_domain
- * @node: node whose sched_domain we're building
- * @used_nodes: nodes already in the sched_domain
- *
- * Find the next node to include in a given scheduling domain. Simply
- * finds the closest node not already in the @used_nodes map.
- *
- * Should use nodemask_t.
- */
-static int find_next_best_node(int node, nodemask_t *used_nodes)
-{
- int i, n, val, min_val, best_node = -1;
-
- min_val = INT_MAX;
-
- for (i = 0; i < nr_node_ids; i++) {
- /* Start at @node */
- n = (node + i) % nr_node_ids;
-
- if (!nr_cpus_node(n))
- continue;
-
- /* Skip already used nodes */
- if (node_isset(n, *used_nodes))
- continue;
-
- /* Simple min distance search */
- val = node_distance(node, n);
-
- if (val < min_val) {
- min_val = val;
- best_node = n;
- }
- }
-
- if (best_node != -1)
- node_set(best_node, *used_nodes);
- return best_node;
-}
-
-/**
- * sched_domain_node_span - get a cpumask for a node's sched_domain
- * @node: node whose cpumask we're constructing
- * @span: resulting cpumask
- *
- * Given a node, construct a good cpumask for its sched_domain to span. It
- * should be one that prevents unnecessary balancing, but also spreads tasks
- * out optimally.
- */
-static void sched_domain_node_span(int node, struct cpumask *span)
-{
- nodemask_t used_nodes;
- int i;
-
- cpumask_clear(span);
- nodes_clear(used_nodes);
-
- cpumask_or(span, span, cpumask_of_node(node));
- node_set(node, used_nodes);
-
- for (i = 1; i < SD_NODES_PER_DOMAIN; i++) {
- int next_node = find_next_best_node(node, &used_nodes);
- if (next_node < 0)
- break;
- cpumask_or(span, span, cpumask_of_node(next_node));
- }
-}
-
-static const struct cpumask *cpu_node_mask(int cpu)
-{
- lockdep_assert_held(&sched_domains_mutex);
-
- sched_domain_node_span(cpu_to_node(cpu), sched_domains_tmpmask);
-
- return sched_domains_tmpmask;
-}
-
-static const struct cpumask *cpu_allnodes_mask(int cpu)
-{
- return cpu_possible_mask;
-}
-#endif /* CONFIG_NUMA */
-
static const struct cpumask *cpu_cpu_mask(int cpu)
{
return cpumask_of_node(cpu_to_node(cpu));
}
-int sched_smt_power_savings = 0, sched_mc_power_savings = 0;
-
struct sd_data {
struct sched_domain **__percpu sd;
struct sched_group **__percpu sg;
@@ -6020,6 +5961,7 @@ struct sched_domain_topology_level {
sched_domain_init_f init;
sched_domain_mask_f mask;
int flags;
+ int numa_level;
struct sd_data data;
};
@@ -6211,10 +6153,6 @@ sd_init_##type(struct sched_domain_topology_level *tl, int cpu) \
}
SD_INIT_FUNC(CPU)
-#ifdef CONFIG_NUMA
- SD_INIT_FUNC(ALLNODES)
- SD_INIT_FUNC(NODE)
-#endif
#ifdef CONFIG_SCHED_SMT
SD_INIT_FUNC(SIBLING)
#endif
@@ -6336,15 +6274,184 @@ static struct sched_domain_topology_level default_topology[] = {
{ sd_init_BOOK, cpu_book_mask, },
#endif
{ sd_init_CPU, cpu_cpu_mask, },
-#ifdef CONFIG_NUMA
- { sd_init_NODE, cpu_node_mask, SDTL_OVERLAP, },
- { sd_init_ALLNODES, cpu_allnodes_mask, },
-#endif
{ NULL, },
};
static struct sched_domain_topology_level *sched_domain_topology = default_topology;
+#ifdef CONFIG_NUMA
+
+static int sched_domains_numa_levels;
+static int sched_domains_numa_scale;
+static int *sched_domains_numa_distance;
+static struct cpumask ***sched_domains_numa_masks;
+static int sched_domains_curr_level;
+
+static inline int sd_local_flags(int level)
+{
+ if (sched_domains_numa_distance[level] > REMOTE_DISTANCE)
+ return 0;
+
+ return SD_BALANCE_EXEC | SD_BALANCE_FORK | SD_WAKE_AFFINE;
+}
+
+static struct sched_domain *
+sd_numa_init(struct sched_domain_topology_level *tl, int cpu)
+{
+ struct sched_domain *sd = *per_cpu_ptr(tl->data.sd, cpu);
+ int level = tl->numa_level;
+ int sd_weight = cpumask_weight(
+ sched_domains_numa_masks[level][cpu_to_node(cpu)]);
+
+ *sd = (struct sched_domain){
+ .min_interval = sd_weight,
+ .max_interval = 2*sd_weight,
+ .busy_factor = 32,
+ .imbalance_pct = 125,
+ .cache_nice_tries = 2,
+ .busy_idx = 3,
+ .idle_idx = 2,
+ .newidle_idx = 0,
+ .wake_idx = 0,
+ .forkexec_idx = 0,
+
+ .flags = 1*SD_LOAD_BALANCE
+ | 1*SD_BALANCE_NEWIDLE
+ | 0*SD_BALANCE_EXEC
+ | 0*SD_BALANCE_FORK
+ | 0*SD_BALANCE_WAKE
+ | 0*SD_WAKE_AFFINE
+ | 0*SD_PREFER_LOCAL
+ | 0*SD_SHARE_CPUPOWER
+ | 0*SD_SHARE_PKG_RESOURCES
+ | 1*SD_SERIALIZE
+ | 0*SD_PREFER_SIBLING
+ | sd_local_flags(level)
+ ,
+ .last_balance = jiffies,
+ .balance_interval = sd_weight,
+ };
+ SD_INIT_NAME(sd, NUMA);
+ sd->private = &tl->data;
+
+ /*
+ * Ugly hack to pass state to sd_numa_mask()...
+ */
+ sched_domains_curr_level = tl->numa_level;
+
+ return sd;
+}
+
+static const struct cpumask *sd_numa_mask(int cpu)
+{
+ return sched_domains_numa_masks[sched_domains_curr_level][cpu_to_node(cpu)];
+}
+
+static void sched_init_numa(void)
+{
+ int next_distance, curr_distance = node_distance(0, 0);
+ struct sched_domain_topology_level *tl;
+ int level = 0;
+ int i, j, k;
+
+ sched_domains_numa_scale = curr_distance;
+ sched_domains_numa_distance = kzalloc(sizeof(int) * nr_node_ids, GFP_KERNEL);
+ if (!sched_domains_numa_distance)
+ return;
+
+ /*
+ * O(nr_nodes^2) deduplicating selection sort -- in order to find the
+ * unique distances in the node_distance() table.
+ *
+ * Assumes node_distance(0,j) includes all distances in
+ * node_distance(i,j) in order to avoid cubic time.
+ *
+ * XXX: could be optimized to O(n log n) by using sort()
+ */
+ next_distance = curr_distance;
+ for (i = 0; i < nr_node_ids; i++) {
+ for (j = 0; j < nr_node_ids; j++) {
+ int distance = node_distance(0, j);
+ if (distance > curr_distance &&
+ (distance < next_distance ||
+ next_distance == curr_distance))
+ next_distance = distance;
+ }
+ if (next_distance != curr_distance) {
+ sched_domains_numa_distance[level++] = next_distance;
+ sched_domains_numa_levels = level;
+ curr_distance = next_distance;
+ } else break;
+ }
+ /*
+ * 'level' contains the number of unique distances, excluding the
+ * identity distance node_distance(i,i).
+ *
+ * The sched_domains_nume_distance[] array includes the actual distance
+ * numbers.
+ */
+
+ sched_domains_numa_masks = kzalloc(sizeof(void *) * level, GFP_KERNEL);
+ if (!sched_domains_numa_masks)
+ return;
+
+ /*
+ * Now for each level, construct a mask per node which contains all
+ * cpus of nodes that are that many hops away from us.
+ */
+ for (i = 0; i < level; i++) {
+ sched_domains_numa_masks[i] =
+ kzalloc(nr_node_ids * sizeof(void *), GFP_KERNEL);
+ if (!sched_domains_numa_masks[i])
+ return;
+
+ for (j = 0; j < nr_node_ids; j++) {
+ struct cpumask *mask = kzalloc_node(cpumask_size(), GFP_KERNEL, j);
+ if (!mask)
+ return;
+
+ sched_domains_numa_masks[i][j] = mask;
+
+ for (k = 0; k < nr_node_ids; k++) {
+ if (node_distance(j, k) > sched_domains_numa_distance[i])
+ continue;
+
+ cpumask_or(mask, mask, cpumask_of_node(k));
+ }
+ }
+ }
+
+ tl = kzalloc((ARRAY_SIZE(default_topology) + level) *
+ sizeof(struct sched_domain_topology_level), GFP_KERNEL);
+ if (!tl)
+ return;
+
+ /*
+ * Copy the default topology bits..
+ */
+ for (i = 0; default_topology[i].init; i++)
+ tl[i] = default_topology[i];
+
+ /*
+ * .. and append 'j' levels of NUMA goodness.
+ */
+ for (j = 0; j < level; i++, j++) {
+ tl[i] = (struct sched_domain_topology_level){
+ .init = sd_numa_init,
+ .mask = sd_numa_mask,
+ .flags = SDTL_OVERLAP,
+ .numa_level = j,
+ };
+ }
+
+ sched_domain_topology = tl;
+}
+#else
+static inline void sched_init_numa(void)
+{
+}
+#endif /* CONFIG_NUMA */
+
static int __sdt_alloc(const struct cpumask *cpu_map)
{
struct sched_domain_topology_level *tl;
@@ -6382,6 +6489,8 @@ static int __sdt_alloc(const struct cpumask *cpu_map)
if (!sg)
return -ENOMEM;
+ sg->next = sg;
+
*per_cpu_ptr(sdd->sg, j) = sg;
sgp = kzalloc_node(sizeof(struct sched_group_power),
@@ -6710,97 +6819,6 @@ match2:
mutex_unlock(&sched_domains_mutex);
}
-#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
-static void reinit_sched_domains(void)
-{
- get_online_cpus();
-
- /* Destroy domains first to force the rebuild */
- partition_sched_domains(0, NULL, NULL);
-
- rebuild_sched_domains();
- put_online_cpus();
-}
-
-static ssize_t sched_power_savings_store(const char *buf, size_t count, int smt)
-{
- unsigned int level = 0;
-
- if (sscanf(buf, "%u", &level) != 1)
- return -EINVAL;
-
- /*
- * level is always be positive so don't check for
- * level < POWERSAVINGS_BALANCE_NONE which is 0
- * What happens on 0 or 1 byte write,
- * need to check for count as well?
- */
-
- if (level >= MAX_POWERSAVINGS_BALANCE_LEVELS)
- return -EINVAL;
-
- if (smt)
- sched_smt_power_savings = level;
- else
- sched_mc_power_savings = level;
-
- reinit_sched_domains();
-
- return count;
-}
-
-#ifdef CONFIG_SCHED_MC
-static ssize_t sched_mc_power_savings_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%u\n", sched_mc_power_savings);
-}
-static ssize_t sched_mc_power_savings_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- return sched_power_savings_store(buf, count, 0);
-}
-static DEVICE_ATTR(sched_mc_power_savings, 0644,
- sched_mc_power_savings_show,
- sched_mc_power_savings_store);
-#endif
-
-#ifdef CONFIG_SCHED_SMT
-static ssize_t sched_smt_power_savings_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%u\n", sched_smt_power_savings);
-}
-static ssize_t sched_smt_power_savings_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- return sched_power_savings_store(buf, count, 1);
-}
-static DEVICE_ATTR(sched_smt_power_savings, 0644,
- sched_smt_power_savings_show,
- sched_smt_power_savings_store);
-#endif
-
-int __init sched_create_sysfs_power_savings_entries(struct device *dev)
-{
- int err = 0;
-
-#ifdef CONFIG_SCHED_SMT
- if (smt_capable())
- err = device_create_file(dev, &dev_attr_sched_smt_power_savings);
-#endif
-#ifdef CONFIG_SCHED_MC
- if (!err && mc_capable())
- err = device_create_file(dev, &dev_attr_sched_mc_power_savings);
-#endif
- return err;
-}
-#endif /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */
-
/*
* Update cpusets according to cpu_active mask. If cpusets are
* disabled, cpuset_update_active_cpus() becomes a simple wrapper
@@ -6838,6 +6856,8 @@ void __init sched_init_smp(void)
alloc_cpumask_var(&non_isolated_cpus, GFP_KERNEL);
alloc_cpumask_var(&fallback_doms, GFP_KERNEL);
+ sched_init_numa();
+
get_online_cpus();
mutex_lock(&sched_domains_mutex);
init_sched_domains(cpu_active_mask);
@@ -7059,6 +7079,7 @@ void __init sched_init(void)
/* May be allocated at isolcpus cmdline parse time */
if (cpu_isolated_map == NULL)
zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT);
+ idle_thread_set_boot_cpu();
#endif
init_sched_fair_class();
@@ -7980,13 +8001,9 @@ static struct cftype cpu_files[] = {
.write_u64 = cpu_rt_period_write_uint,
},
#endif
+ { } /* terminate */
};
-static int cpu_cgroup_populate(struct cgroup_subsys *ss, struct cgroup *cont)
-{
- return cgroup_add_files(cont, ss, cpu_files, ARRAY_SIZE(cpu_files));
-}
-
struct cgroup_subsys cpu_cgroup_subsys = {
.name = "cpu",
.create = cpu_cgroup_create,
@@ -7994,8 +8011,8 @@ struct cgroup_subsys cpu_cgroup_subsys = {
.can_attach = cpu_cgroup_can_attach,
.attach = cpu_cgroup_attach,
.exit = cpu_cgroup_exit,
- .populate = cpu_cgroup_populate,
.subsys_id = cpu_cgroup_subsys_id,
+ .base_cftypes = cpu_files,
.early_init = 1,
};
@@ -8180,13 +8197,9 @@ static struct cftype files[] = {
.name = "stat",
.read_map = cpuacct_stats_show,
},
+ { } /* terminate */
};
-static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
-{
- return cgroup_add_files(cgrp, ss, files, ARRAY_SIZE(files));
-}
-
/*
* charge this task's execution time to its accounting group.
*
@@ -8218,7 +8231,7 @@ struct cgroup_subsys cpuacct_subsys = {
.name = "cpuacct",
.create = cpuacct_create,
.destroy = cpuacct_destroy,
- .populate = cpuacct_populate,
.subsys_id = cpuacct_subsys_id,
+ .base_cftypes = files,
};
#endif /* CONFIG_CGROUP_CPUACCT */
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
index 09acaa15161d..6f79596e0ea9 100644
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
@@ -202,7 +202,7 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
SPLIT_NS(spread0));
SEQ_printf(m, " .%-30s: %d\n", "nr_spread_over",
cfs_rq->nr_spread_over);
- SEQ_printf(m, " .%-30s: %ld\n", "nr_running", cfs_rq->nr_running);
+ SEQ_printf(m, " .%-30s: %d\n", "nr_running", cfs_rq->nr_running);
SEQ_printf(m, " .%-30s: %ld\n", "load", cfs_rq->load.weight);
#ifdef CONFIG_FAIR_GROUP_SCHED
#ifdef CONFIG_SMP
@@ -260,8 +260,14 @@ static void print_cpu(struct seq_file *m, int cpu)
SEQ_printf(m, "\ncpu#%d\n", cpu);
#endif
-#define P(x) \
- SEQ_printf(m, " .%-30s: %Ld\n", #x, (long long)(rq->x))
+#define P(x) \
+do { \
+ if (sizeof(rq->x) == 4) \
+ SEQ_printf(m, " .%-30s: %ld\n", #x, (long)(rq->x)); \
+ else \
+ SEQ_printf(m, " .%-30s: %Ld\n", #x, (long long)(rq->x));\
+} while (0)
+
#define PN(x) \
SEQ_printf(m, " .%-30s: %Ld.%06ld\n", #x, SPLIT_NS(rq->x))
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index e9553640c1c3..940e6d17cf96 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -2721,7 +2721,7 @@ select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flags)
* If power savings logic is enabled for a domain, see if we
* are not overloaded, if so, don't balance wider.
*/
- if (tmp->flags & (SD_POWERSAVINGS_BALANCE|SD_PREFER_LOCAL)) {
+ if (tmp->flags & (SD_PREFER_LOCAL)) {
unsigned long power = 0;
unsigned long nr_running = 0;
unsigned long capacity;
@@ -2734,9 +2734,6 @@ select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flags)
capacity = DIV_ROUND_CLOSEST(power, SCHED_POWER_SCALE);
- if (tmp->flags & SD_POWERSAVINGS_BALANCE)
- nr_running /= 2;
-
if (nr_running < capacity)
want_sd = 0;
}
@@ -3082,7 +3079,7 @@ struct lb_env {
struct rq *dst_rq;
enum cpu_idle_type idle;
- long load_move;
+ long imbalance;
unsigned int flags;
unsigned int loop;
@@ -3218,7 +3215,7 @@ static unsigned long task_h_load(struct task_struct *p);
static const unsigned int sched_nr_migrate_break = 32;
/*
- * move_tasks tries to move up to load_move weighted load from busiest to
+ * move_tasks tries to move up to imbalance weighted load from busiest to
* this_rq, as part of a balancing operation within domain "sd".
* Returns 1 if successful and 0 otherwise.
*
@@ -3231,7 +3228,7 @@ static int move_tasks(struct lb_env *env)
unsigned long load;
int pulled = 0;
- if (env->load_move <= 0)
+ if (env->imbalance <= 0)
return 0;
while (!list_empty(tasks)) {
@@ -3257,7 +3254,7 @@ static int move_tasks(struct lb_env *env)
if (sched_feat(LB_MIN) && load < 16 && !env->sd->nr_balance_failed)
goto next;
- if ((load / 2) > env->load_move)
+ if ((load / 2) > env->imbalance)
goto next;
if (!can_migrate_task(p, env))
@@ -3265,7 +3262,7 @@ static int move_tasks(struct lb_env *env)
move_task(p, env);
pulled++;
- env->load_move -= load;
+ env->imbalance -= load;
#ifdef CONFIG_PREEMPT
/*
@@ -3281,7 +3278,7 @@ static int move_tasks(struct lb_env *env)
* We only want to steal up to the prescribed amount of
* weighted load.
*/
- if (env->load_move <= 0)
+ if (env->imbalance <= 0)
break;
continue;
@@ -3435,14 +3432,6 @@ struct sd_lb_stats {
unsigned int busiest_group_weight;
int group_imb; /* Is there imbalance in this sd */
-#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
- int power_savings_balance; /* Is powersave balance needed for this sd */
- struct sched_group *group_min; /* Least loaded group in sd */
- struct sched_group *group_leader; /* Group which relieves group_min */
- unsigned long min_load_per_task; /* load_per_task in group_min */
- unsigned long leader_nr_running; /* Nr running of group_leader */
- unsigned long min_nr_running; /* Nr running of group_min */
-#endif
};
/*
@@ -3486,148 +3475,6 @@ static inline int get_sd_load_idx(struct sched_domain *sd,
return load_idx;
}
-
-#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
-/**
- * init_sd_power_savings_stats - Initialize power savings statistics for
- * the given sched_domain, during load balancing.
- *
- * @sd: Sched domain whose power-savings statistics are to be initialized.
- * @sds: Variable containing the statistics for sd.
- * @idle: Idle status of the CPU at which we're performing load-balancing.
- */
-static inline void init_sd_power_savings_stats(struct sched_domain *sd,
- struct sd_lb_stats *sds, enum cpu_idle_type idle)
-{
- /*
- * Busy processors will not participate in power savings
- * balance.
- */
- if (idle == CPU_NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
- sds->power_savings_balance = 0;
- else {
- sds->power_savings_balance = 1;
- sds->min_nr_running = ULONG_MAX;
- sds->leader_nr_running = 0;
- }
-}
-
-/**
- * update_sd_power_savings_stats - Update the power saving stats for a
- * sched_domain while performing load balancing.
- *
- * @group: sched_group belonging to the sched_domain under consideration.
- * @sds: Variable containing the statistics of the sched_domain
- * @local_group: Does group contain the CPU for which we're performing
- * load balancing ?
- * @sgs: Variable containing the statistics of the group.
- */
-static inline void update_sd_power_savings_stats(struct sched_group *group,
- struct sd_lb_stats *sds, int local_group, struct sg_lb_stats *sgs)
-{
-
- if (!sds->power_savings_balance)
- return;
-
- /*
- * If the local group is idle or completely loaded
- * no need to do power savings balance at this domain
- */
- if (local_group && (sds->this_nr_running >= sgs->group_capacity ||
- !sds->this_nr_running))
- sds->power_savings_balance = 0;
-
- /*
- * If a group is already running at full capacity or idle,
- * don't include that group in power savings calculations
- */
- if (!sds->power_savings_balance ||
- sgs->sum_nr_running >= sgs->group_capacity ||
- !sgs->sum_nr_running)
- return;
-
- /*
- * Calculate the group which has the least non-idle load.
- * This is the group from where we need to pick up the load
- * for saving power
- */
- if ((sgs->sum_nr_running < sds->min_nr_running) ||
- (sgs->sum_nr_running == sds->min_nr_running &&
- group_first_cpu(group) > group_first_cpu(sds->group_min))) {
- sds->group_min = group;
- sds->min_nr_running = sgs->sum_nr_running;
- sds->min_load_per_task = sgs->sum_weighted_load /
- sgs->sum_nr_running;
- }
-
- /*
- * Calculate the group which is almost near its
- * capacity but still has some space to pick up some load
- * from other group and save more power
- */
- if (sgs->sum_nr_running + 1 > sgs->group_capacity)
- return;
-
- if (sgs->sum_nr_running > sds->leader_nr_running ||
- (sgs->sum_nr_running == sds->leader_nr_running &&
- group_first_cpu(group) < group_first_cpu(sds->group_leader))) {
- sds->group_leader = group;
- sds->leader_nr_running = sgs->sum_nr_running;
- }
-}
-
-/**
- * check_power_save_busiest_group - see if there is potential for some power-savings balance
- * @sds: Variable containing the statistics of the sched_domain
- * under consideration.
- * @this_cpu: Cpu at which we're currently performing load-balancing.
- * @imbalance: Variable to store the imbalance.
- *
- * Description:
- * Check if we have potential to perform some power-savings balance.
- * If yes, set the busiest group to be the least loaded group in the
- * sched_domain, so that it's CPUs can be put to idle.
- *
- * Returns 1 if there is potential to perform power-savings balance.
- * Else returns 0.
- */
-static inline int check_power_save_busiest_group(struct sd_lb_stats *sds,
- int this_cpu, unsigned long *imbalance)
-{
- if (!sds->power_savings_balance)
- return 0;
-
- if (sds->this != sds->group_leader ||
- sds->group_leader == sds->group_min)
- return 0;
-
- *imbalance = sds->min_load_per_task;
- sds->busiest = sds->group_min;
-
- return 1;
-
-}
-#else /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */
-static inline void init_sd_power_savings_stats(struct sched_domain *sd,
- struct sd_lb_stats *sds, enum cpu_idle_type idle)
-{
- return;
-}
-
-static inline void update_sd_power_savings_stats(struct sched_group *group,
- struct sd_lb_stats *sds, int local_group, struct sg_lb_stats *sgs)
-{
- return;
-}
-
-static inline int check_power_save_busiest_group(struct sd_lb_stats *sds,
- int this_cpu, unsigned long *imbalance)
-{
- return 0;
-}
-#endif /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */
-
-
unsigned long default_scale_freq_power(struct sched_domain *sd, int cpu)
{
return SCHED_POWER_SCALE;
@@ -3765,24 +3612,22 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group)
* update_sg_lb_stats - Update sched_group's statistics for load balancing.
* @sd: The sched_domain whose statistics are to be updated.
* @group: sched_group whose statistics are to be updated.
- * @this_cpu: Cpu for which load balance is currently performed.
- * @idle: Idle status of this_cpu
* @load_idx: Load index of sched_domain of this_cpu for load calc.
* @local_group: Does group contain this_cpu.
* @cpus: Set of cpus considered for load balancing.
* @balance: Should we balance.
* @sgs: variable to hold the statistics for this group.
*/
-static inline void update_sg_lb_stats(struct sched_domain *sd,
- struct sched_group *group, int this_cpu,
- enum cpu_idle_type idle, int load_idx,
+static inline void update_sg_lb_stats(struct lb_env *env,
+ struct sched_group *group, int load_idx,
int local_group, const struct cpumask *cpus,
int *balance, struct sg_lb_stats *sgs)
{
- unsigned long load, max_cpu_load, min_cpu_load, max_nr_running;
- int i;
+ unsigned long nr_running, max_nr_running, min_nr_running;
+ unsigned long load, max_cpu_load, min_cpu_load;
unsigned int balance_cpu = -1, first_idle_cpu = 0;
unsigned long avg_load_per_task = 0;
+ int i;
if (local_group)
balance_cpu = group_first_cpu(group);
@@ -3791,10 +3636,13 @@ static inline void update_sg_lb_stats(struct sched_domain *sd,
max_cpu_load = 0;
min_cpu_load = ~0UL;
max_nr_running = 0;
+ min_nr_running = ~0UL;
for_each_cpu_and(i, sched_group_cpus(group), cpus) {
struct rq *rq = cpu_rq(i);
+ nr_running = rq->nr_running;
+
/* Bias balancing toward cpus of our domain */
if (local_group) {
if (idle_cpu(i) && !first_idle_cpu) {
@@ -3805,16 +3653,19 @@ static inline void update_sg_lb_stats(struct sched_domain *sd,
load = target_load(i, load_idx);
} else {
load = source_load(i, load_idx);
- if (load > max_cpu_load) {
+ if (load > max_cpu_load)
max_cpu_load = load;
- max_nr_running = rq->nr_running;
- }
if (min_cpu_load > load)
min_cpu_load = load;
+
+ if (nr_running > max_nr_running)
+ max_nr_running = nr_running;
+ if (min_nr_running > nr_running)
+ min_nr_running = nr_running;
}
sgs->group_load += load;
- sgs->sum_nr_running += rq->nr_running;
+ sgs->sum_nr_running += nr_running;
sgs->sum_weighted_load += weighted_cpuload(i);
if (idle_cpu(i))
sgs->idle_cpus++;
@@ -3827,14 +3678,14 @@ static inline void update_sg_lb_stats(struct sched_domain *sd,
* to do the newly idle load balance.
*/
if (local_group) {
- if (idle != CPU_NEWLY_IDLE) {
- if (balance_cpu != this_cpu) {
+ if (env->idle != CPU_NEWLY_IDLE) {
+ if (balance_cpu != env->dst_cpu) {
*balance = 0;
return;
}
- update_group_power(sd, this_cpu);
+ update_group_power(env->sd, env->dst_cpu);
} else if (time_after_eq(jiffies, group->sgp->next_update))
- update_group_power(sd, this_cpu);
+ update_group_power(env->sd, env->dst_cpu);
}
/* Adjust by relative CPU power of the group */
@@ -3852,13 +3703,14 @@ static inline void update_sg_lb_stats(struct sched_domain *sd,
if (sgs->sum_nr_running)
avg_load_per_task = sgs->sum_weighted_load / sgs->sum_nr_running;
- if ((max_cpu_load - min_cpu_load) >= avg_load_per_task && max_nr_running > 1)
+ if ((max_cpu_load - min_cpu_load) >= avg_load_per_task &&
+ (max_nr_running - min_nr_running) > 1)
sgs->group_imb = 1;
sgs->group_capacity = DIV_ROUND_CLOSEST(group->sgp->power,
SCHED_POWER_SCALE);
if (!sgs->group_capacity)
- sgs->group_capacity = fix_small_capacity(sd, group);
+ sgs->group_capacity = fix_small_capacity(env->sd, group);
sgs->group_weight = group->group_weight;
if (sgs->group_capacity > sgs->sum_nr_running)
@@ -3876,11 +3728,10 @@ static inline void update_sg_lb_stats(struct sched_domain *sd,
* Determine if @sg is a busier group than the previously selected
* busiest group.
*/
-static bool update_sd_pick_busiest(struct sched_domain *sd,
+static bool update_sd_pick_busiest(struct lb_env *env,
struct sd_lb_stats *sds,
struct sched_group *sg,
- struct sg_lb_stats *sgs,
- int this_cpu)
+ struct sg_lb_stats *sgs)
{
if (sgs->avg_load <= sds->max_load)
return false;
@@ -3896,8 +3747,8 @@ static bool update_sd_pick_busiest(struct sched_domain *sd,
* numbered CPUs in the group, therefore mark all groups
* higher than ourself as busy.
*/
- if ((sd->flags & SD_ASYM_PACKING) && sgs->sum_nr_running &&
- this_cpu < group_first_cpu(sg)) {
+ if ((env->sd->flags & SD_ASYM_PACKING) && sgs->sum_nr_running &&
+ env->dst_cpu < group_first_cpu(sg)) {
if (!sds->busiest)
return true;
@@ -3917,28 +3768,27 @@ static bool update_sd_pick_busiest(struct sched_domain *sd,
* @balance: Should we balance.
* @sds: variable to hold the statistics for this sched_domain.
*/
-static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu,
- enum cpu_idle_type idle, const struct cpumask *cpus,
- int *balance, struct sd_lb_stats *sds)
+static inline void update_sd_lb_stats(struct lb_env *env,
+ const struct cpumask *cpus,
+ int *balance, struct sd_lb_stats *sds)
{
- struct sched_domain *child = sd->child;
- struct sched_group *sg = sd->groups;
+ struct sched_domain *child = env->sd->child;
+ struct sched_group *sg = env->sd->groups;
struct sg_lb_stats sgs;
int load_idx, prefer_sibling = 0;
if (child && child->flags & SD_PREFER_SIBLING)
prefer_sibling = 1;
- init_sd_power_savings_stats(sd, sds, idle);
- load_idx = get_sd_load_idx(sd, idle);
+ load_idx = get_sd_load_idx(env->sd, env->idle);
do {
int local_group;
- local_group = cpumask_test_cpu(this_cpu, sched_group_cpus(sg));
+ local_group = cpumask_test_cpu(env->dst_cpu, sched_group_cpus(sg));
memset(&sgs, 0, sizeof(sgs));
- update_sg_lb_stats(sd, sg, this_cpu, idle, load_idx,
- local_group, cpus, balance, &sgs);
+ update_sg_lb_stats(env, sg, load_idx, local_group,
+ cpus, balance, &sgs);
if (local_group && !(*balance))
return;
@@ -3966,7 +3816,7 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu,
sds->this_load_per_task = sgs.sum_weighted_load;
sds->this_has_capacity = sgs.group_has_capacity;
sds->this_idle_cpus = sgs.idle_cpus;
- } else if (update_sd_pick_busiest(sd, sds, sg, &sgs, this_cpu)) {
+ } else if (update_sd_pick_busiest(env, sds, sg, &sgs)) {
sds->max_load = sgs.avg_load;
sds->busiest = sg;
sds->busiest_nr_running = sgs.sum_nr_running;
@@ -3978,9 +3828,8 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu,
sds->group_imb = sgs.group_imb;
}
- update_sd_power_savings_stats(sg, sds, local_group, &sgs);
sg = sg->next;
- } while (sg != sd->groups);
+ } while (sg != env->sd->groups);
}
/**
@@ -4008,24 +3857,23 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu,
* @this_cpu: The cpu at whose sched_domain we're performing load-balance.
* @imbalance: returns amount of imbalanced due to packing.
*/
-static int check_asym_packing(struct sched_domain *sd,
- struct sd_lb_stats *sds,
- int this_cpu, unsigned long *imbalance)
+static int check_asym_packing(struct lb_env *env, struct sd_lb_stats *sds)
{
int busiest_cpu;
- if (!(sd->flags & SD_ASYM_PACKING))
+ if (!(env->sd->flags & SD_ASYM_PACKING))
return 0;
if (!sds->busiest)
return 0;
busiest_cpu = group_first_cpu(sds->busiest);
- if (this_cpu > busiest_cpu)
+ if (env->dst_cpu > busiest_cpu)
return 0;
- *imbalance = DIV_ROUND_CLOSEST(sds->max_load * sds->busiest->sgp->power,
- SCHED_POWER_SCALE);
+ env->imbalance = DIV_ROUND_CLOSEST(
+ sds->max_load * sds->busiest->sgp->power, SCHED_POWER_SCALE);
+
return 1;
}
@@ -4037,8 +3885,8 @@ static int check_asym_packing(struct sched_domain *sd,
* @this_cpu: The cpu at whose sched_domain we're performing load-balance.
* @imbalance: Variable to store the imbalance.
*/
-static inline void fix_small_imbalance(struct sd_lb_stats *sds,
- int this_cpu, unsigned long *imbalance)
+static inline
+void fix_small_imbalance(struct lb_env *env, struct sd_lb_stats *sds)
{
unsigned long tmp, pwr_now = 0, pwr_move = 0;
unsigned int imbn = 2;
@@ -4049,9 +3897,10 @@ static inline void fix_small_imbalance(struct sd_lb_stats *sds,
if (sds->busiest_load_per_task >
sds->this_load_per_task)
imbn = 1;
- } else
+ } else {
sds->this_load_per_task =
- cpu_avg_load_per_task(this_cpu);
+ cpu_avg_load_per_task(env->dst_cpu);
+ }
scaled_busy_load_per_task = sds->busiest_load_per_task
* SCHED_POWER_SCALE;
@@ -4059,7 +3908,7 @@ static inline void fix_small_imbalance(struct sd_lb_stats *sds,
if (sds->max_load - sds->this_load + scaled_busy_load_per_task >=
(scaled_busy_load_per_task * imbn)) {
- *imbalance = sds->busiest_load_per_task;
+ env->imbalance = sds->busiest_load_per_task;
return;
}
@@ -4096,18 +3945,16 @@ static inline void fix_small_imbalance(struct sd_lb_stats *sds,
/* Move if we gain throughput */
if (pwr_move > pwr_now)
- *imbalance = sds->busiest_load_per_task;
+ env->imbalance = sds->busiest_load_per_task;
}
/**
* calculate_imbalance - Calculate the amount of imbalance present within the
* groups of a given sched_domain during load balance.
+ * @env: load balance environment
* @sds: statistics of the sched_domain whose imbalance is to be calculated.
- * @this_cpu: Cpu for which currently load balance is being performed.
- * @imbalance: The variable to store the imbalance.
*/
-static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu,
- unsigned long *imbalance)
+static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *sds)
{
unsigned long max_pull, load_above_capacity = ~0UL;
@@ -4123,8 +3970,8 @@ static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu,
* its cpu_power, while calculating max_load..)
*/
if (sds->max_load < sds->avg_load) {
- *imbalance = 0;
- return fix_small_imbalance(sds, this_cpu, imbalance);
+ env->imbalance = 0;
+ return fix_small_imbalance(env, sds);
}
if (!sds->group_imb) {
@@ -4152,7 +3999,7 @@ static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu,
max_pull = min(sds->max_load - sds->avg_load, load_above_capacity);
/* How much load to actually move to equalise the imbalance */
- *imbalance = min(max_pull * sds->busiest->sgp->power,
+ env->imbalance = min(max_pull * sds->busiest->sgp->power,
(sds->avg_load - sds->this_load) * sds->this->sgp->power)
/ SCHED_POWER_SCALE;
@@ -4162,8 +4009,8 @@ static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu,
* a think about bumping its value to force at least one task to be
* moved
*/
- if (*imbalance < sds->busiest_load_per_task)
- return fix_small_imbalance(sds, this_cpu, imbalance);
+ if (env->imbalance < sds->busiest_load_per_task)
+ return fix_small_imbalance(env, sds);
}
@@ -4194,9 +4041,7 @@ static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu,
* put to idle by rebalancing its tasks onto our group.
*/
static struct sched_group *
-find_busiest_group(struct sched_domain *sd, int this_cpu,
- unsigned long *imbalance, enum cpu_idle_type idle,
- const struct cpumask *cpus, int *balance)
+find_busiest_group(struct lb_env *env, const struct cpumask *cpus, int *balance)
{
struct sd_lb_stats sds;
@@ -4206,7 +4051,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
* Compute the various statistics relavent for load balancing at
* this level.
*/
- update_sd_lb_stats(sd, this_cpu, idle, cpus, balance, &sds);
+ update_sd_lb_stats(env, cpus, balance, &sds);
/*
* this_cpu is not the appropriate cpu to perform load balancing at
@@ -4215,8 +4060,8 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
if (!(*balance))
goto ret;
- if ((idle == CPU_IDLE || idle == CPU_NEWLY_IDLE) &&
- check_asym_packing(sd, &sds, this_cpu, imbalance))
+ if ((env->idle == CPU_IDLE || env->idle == CPU_NEWLY_IDLE) &&
+ check_asym_packing(env, &sds))
return sds.busiest;
/* There is no busy sibling group to pull tasks from */
@@ -4234,7 +4079,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
goto force_balance;
/* SD_BALANCE_NEWIDLE trumps SMP nice when underutilized */
- if (idle == CPU_NEWLY_IDLE && sds.this_has_capacity &&
+ if (env->idle == CPU_NEWLY_IDLE && sds.this_has_capacity &&
!sds.busiest_has_capacity)
goto force_balance;
@@ -4252,7 +4097,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
if (sds.this_load >= sds.avg_load)
goto out_balanced;
- if (idle == CPU_IDLE) {
+ if (env->idle == CPU_IDLE) {
/*
* This cpu is idle. If the busiest group load doesn't
* have more tasks than the number of available cpu's and
@@ -4267,34 +4112,27 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
* In the CPU_NEWLY_IDLE, CPU_NOT_IDLE cases, use
* imbalance_pct to be conservative.
*/
- if (100 * sds.max_load <= sd->imbalance_pct * sds.this_load)
+ if (100 * sds.max_load <= env->sd->imbalance_pct * sds.this_load)
goto out_balanced;
}
force_balance:
/* Looks like there is an imbalance. Compute it */
- calculate_imbalance(&sds, this_cpu, imbalance);
+ calculate_imbalance(env, &sds);
return sds.busiest;
out_balanced:
- /*
- * There is no obvious imbalance. But check if we can do some balancing
- * to save power.
- */
- if (check_power_save_busiest_group(&sds, this_cpu, imbalance))
- return sds.busiest;
ret:
- *imbalance = 0;
+ env->imbalance = 0;
return NULL;
}
/*
* find_busiest_queue - find the busiest runqueue among the cpus in group.
*/
-static struct rq *
-find_busiest_queue(struct sched_domain *sd, struct sched_group *group,
- enum cpu_idle_type idle, unsigned long imbalance,
- const struct cpumask *cpus)
+static struct rq *find_busiest_queue(struct lb_env *env,
+ struct sched_group *group,
+ const struct cpumask *cpus)
{
struct rq *busiest = NULL, *rq;
unsigned long max_load = 0;
@@ -4307,7 +4145,7 @@ find_busiest_queue(struct sched_domain *sd, struct sched_group *group,
unsigned long wl;
if (!capacity)
- capacity = fix_small_capacity(sd, group);
+ capacity = fix_small_capacity(env->sd, group);
if (!cpumask_test_cpu(i, cpus))
continue;
@@ -4319,7 +4157,7 @@ find_busiest_queue(struct sched_domain *sd, struct sched_group *group,
* When comparing with imbalance, use weighted_cpuload()
* which is not scaled with the cpu power.
*/
- if (capacity && rq->nr_running == 1 && wl > imbalance)
+ if (capacity && rq->nr_running == 1 && wl > env->imbalance)
continue;
/*
@@ -4348,40 +4186,19 @@ find_busiest_queue(struct sched_domain *sd, struct sched_group *group,
/* Working cpumask for load_balance and load_balance_newidle. */
DEFINE_PER_CPU(cpumask_var_t, load_balance_tmpmask);
-static int need_active_balance(struct sched_domain *sd, int idle,
- int busiest_cpu, int this_cpu)
+static int need_active_balance(struct lb_env *env)
{
- if (idle == CPU_NEWLY_IDLE) {
+ struct sched_domain *sd = env->sd;
+
+ if (env->idle == CPU_NEWLY_IDLE) {
/*
* ASYM_PACKING needs to force migrate tasks from busy but
* higher numbered CPUs in order to pack all tasks in the
* lowest numbered CPUs.
*/
- if ((sd->flags & SD_ASYM_PACKING) && busiest_cpu > this_cpu)
+ if ((sd->flags & SD_ASYM_PACKING) && env->src_cpu > env->dst_cpu)
return 1;
-
- /*
- * The only task running in a non-idle cpu can be moved to this
- * cpu in an attempt to completely freeup the other CPU
- * package.
- *
- * The package power saving logic comes from
- * find_busiest_group(). If there are no imbalance, then
- * f_b_g() will return NULL. However when sched_mc={1,2} then
- * f_b_g() will select a group from which a running task may be
- * pulled to this cpu in order to make the other package idle.
- * If there is no opportunity to make a package idle and if
- * there are no imbalance, then f_b_g() will return NULL and no
- * action will be taken in load_balance_newidle().
- *
- * Under normal task pull operation due to imbalance, there
- * will be more than one task in the source run queue and
- * move_tasks() will succeed. ld_moved will be true and this
- * active balance code will not be triggered.
- */
- if (sched_mc_power_savings < POWERSAVINGS_BALANCE_WAKEUP)
- return 0;
}
return unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2);
@@ -4399,7 +4216,6 @@ static int load_balance(int this_cpu, struct rq *this_rq,
{
int ld_moved, active_balance = 0;
struct sched_group *group;
- unsigned long imbalance;
struct rq *busiest;
unsigned long flags;
struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask);
@@ -4417,8 +4233,7 @@ static int load_balance(int this_cpu, struct rq *this_rq,
schedstat_inc(sd, lb_count[idle]);
redo:
- group = find_busiest_group(sd, this_cpu, &imbalance, idle,
- cpus, balance);
+ group = find_busiest_group(&env, cpus, balance);
if (*balance == 0)
goto out_balanced;
@@ -4428,7 +4243,7 @@ redo:
goto out_balanced;
}
- busiest = find_busiest_queue(sd, group, idle, imbalance, cpus);
+ busiest = find_busiest_queue(&env, group, cpus);
if (!busiest) {
schedstat_inc(sd, lb_nobusyq[idle]);
goto out_balanced;
@@ -4436,7 +4251,7 @@ redo:
BUG_ON(busiest == this_rq);
- schedstat_add(sd, lb_imbalance[idle], imbalance);
+ schedstat_add(sd, lb_imbalance[idle], env.imbalance);
ld_moved = 0;
if (busiest->nr_running > 1) {
@@ -4447,10 +4262,9 @@ redo:
* correctly treated as an imbalance.
*/
env.flags |= LBF_ALL_PINNED;
- env.load_move = imbalance;
- env.src_cpu = busiest->cpu;
- env.src_rq = busiest;
- env.loop_max = min_t(unsigned long, sysctl_sched_nr_migrate, busiest->nr_running);
+ env.src_cpu = busiest->cpu;
+ env.src_rq = busiest;
+ env.loop_max = min(sysctl_sched_nr_migrate, busiest->nr_running);
more_balance:
local_irq_save(flags);
@@ -4492,7 +4306,7 @@ more_balance:
if (idle != CPU_NEWLY_IDLE)
sd->nr_balance_failed++;
- if (need_active_balance(sd, idle, cpu_of(busiest), this_cpu)) {
+ if (need_active_balance(&env)) {
raw_spin_lock_irqsave(&busiest->lock, flags);
/* don't kick the active_load_balance_cpu_stop,
@@ -4519,10 +4333,11 @@ more_balance:
}
raw_spin_unlock_irqrestore(&busiest->lock, flags);
- if (active_balance)
+ if (active_balance) {
stop_one_cpu_nowait(cpu_of(busiest),
active_load_balance_cpu_stop, busiest,
&busiest->active_balance_work);
+ }
/*
* We've kicked active balancing, reset the failure
@@ -4703,104 +4518,15 @@ static struct {
unsigned long next_balance; /* in jiffy units */
} nohz ____cacheline_aligned;
-#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
-/**
- * lowest_flag_domain - Return lowest sched_domain containing flag.
- * @cpu: The cpu whose lowest level of sched domain is to
- * be returned.
- * @flag: The flag to check for the lowest sched_domain
- * for the given cpu.
- *
- * Returns the lowest sched_domain of a cpu which contains the given flag.
- */
-static inline struct sched_domain *lowest_flag_domain(int cpu, int flag)
-{
- struct sched_domain *sd;
-
- for_each_domain(cpu, sd)
- if (sd->flags & flag)
- break;
-
- return sd;
-}
-
-/**
- * for_each_flag_domain - Iterates over sched_domains containing the flag.
- * @cpu: The cpu whose domains we're iterating over.
- * @sd: variable holding the value of the power_savings_sd
- * for cpu.
- * @flag: The flag to filter the sched_domains to be iterated.
- *
- * Iterates over all the scheduler domains for a given cpu that has the 'flag'
- * set, starting from the lowest sched_domain to the highest.
- */
-#define for_each_flag_domain(cpu, sd, flag) \
- for (sd = lowest_flag_domain(cpu, flag); \
- (sd && (sd->flags & flag)); sd = sd->parent)
-
-/**
- * find_new_ilb - Finds the optimum idle load balancer for nomination.
- * @cpu: The cpu which is nominating a new idle_load_balancer.
- *
- * Returns: Returns the id of the idle load balancer if it exists,
- * Else, returns >= nr_cpu_ids.
- *
- * This algorithm picks the idle load balancer such that it belongs to a
- * semi-idle powersavings sched_domain. The idea is to try and avoid
- * completely idle packages/cores just for the purpose of idle load balancing
- * when there are other idle cpu's which are better suited for that job.
- */
-static int find_new_ilb(int cpu)
+static inline int find_new_ilb(int call_cpu)
{
int ilb = cpumask_first(nohz.idle_cpus_mask);
- struct sched_group *ilbg;
- struct sched_domain *sd;
-
- /*
- * Have idle load balancer selection from semi-idle packages only
- * when power-aware load balancing is enabled
- */
- if (!(sched_smt_power_savings || sched_mc_power_savings))
- goto out_done;
-
- /*
- * Optimize for the case when we have no idle CPUs or only one
- * idle CPU. Don't walk the sched_domain hierarchy in such cases
- */
- if (cpumask_weight(nohz.idle_cpus_mask) < 2)
- goto out_done;
-
- rcu_read_lock();
- for_each_flag_domain(cpu, sd, SD_POWERSAVINGS_BALANCE) {
- ilbg = sd->groups;
-
- do {
- if (ilbg->group_weight !=
- atomic_read(&ilbg->sgp->nr_busy_cpus)) {
- ilb = cpumask_first_and(nohz.idle_cpus_mask,
- sched_group_cpus(ilbg));
- goto unlock;
- }
-
- ilbg = ilbg->next;
-
- } while (ilbg != sd->groups);
- }
-unlock:
- rcu_read_unlock();
-out_done:
if (ilb < nr_cpu_ids && idle_cpu(ilb))
return ilb;
return nr_cpu_ids;
}
-#else /* (CONFIG_SCHED_MC || CONFIG_SCHED_SMT) */
-static inline int find_new_ilb(int call_cpu)
-{
- return nr_cpu_ids;
-}
-#endif
/*
* Kick a CPU to do the nohz balancing, if it is time for it. We pick the
@@ -5023,7 +4749,7 @@ static void nohz_idle_balance(int this_cpu, enum cpu_idle_type idle)
raw_spin_lock_irq(&this_rq->lock);
update_rq_clock(this_rq);
- update_cpu_load(this_rq);
+ update_idle_cpu_load(this_rq);
raw_spin_unlock_irq(&this_rq->lock);
rebalance_domains(balance_cpu, CPU_IDLE);
diff --git a/kernel/sched/idle_task.c b/kernel/sched/idle_task.c
index 91b4c957f289..b44d604b35d1 100644
--- a/kernel/sched/idle_task.c
+++ b/kernel/sched/idle_task.c
@@ -4,7 +4,7 @@
* idle-task scheduling class.
*
* (NOTE: these are not related to SCHED_IDLE tasks which are
- * handled in sched_fair.c)
+ * handled in sched/fair.c)
*/
#ifdef CONFIG_SMP
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 44af55e6d5d0..c5565c3c515f 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1803,44 +1803,40 @@ static void task_woken_rt(struct rq *rq, struct task_struct *p)
static void set_cpus_allowed_rt(struct task_struct *p,
const struct cpumask *new_mask)
{
- int weight = cpumask_weight(new_mask);
+ struct rq *rq;
+ int weight;
BUG_ON(!rt_task(p));
- /*
- * Update the migration status of the RQ if we have an RT task
- * which is running AND changing its weight value.
- */
- if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
- struct rq *rq = task_rq(p);
-
- if (!task_current(rq, p)) {
- /*
- * Make sure we dequeue this task from the pushable list
- * before going further. It will either remain off of
- * the list because we are no longer pushable, or it
- * will be requeued.
- */
- if (p->rt.nr_cpus_allowed > 1)
- dequeue_pushable_task(rq, p);
+ if (!p->on_rq)
+ return;
- /*
- * Requeue if our weight is changing and still > 1
- */
- if (weight > 1)
- enqueue_pushable_task(rq, p);
+ weight = cpumask_weight(new_mask);
- }
+ /*
+ * Only update if the process changes its state from whether it
+ * can migrate or not.
+ */
+ if ((p->rt.nr_cpus_allowed > 1) == (weight > 1))
+ return;
- if ((p->rt.nr_cpus_allowed <= 1) && (weight > 1)) {
- rq->rt.rt_nr_migratory++;
- } else if ((p->rt.nr_cpus_allowed > 1) && (weight <= 1)) {
- BUG_ON(!rq->rt.rt_nr_migratory);
- rq->rt.rt_nr_migratory--;
- }
+ rq = task_rq(p);
- update_rt_migration(&rq->rt);
+ /*
+ * The process used to be able to migrate OR it can now migrate
+ */
+ if (weight <= 1) {
+ if (!task_current(rq, p))
+ dequeue_pushable_task(rq, p);
+ BUG_ON(!rq->rt.rt_nr_migratory);
+ rq->rt.rt_nr_migratory--;
+ } else {
+ if (!task_current(rq, p))
+ enqueue_pushable_task(rq, p);
+ rq->rt.rt_nr_migratory++;
}
+
+ update_rt_migration(&rq->rt);
}
/* Assumes rq->lock is held */
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index fb3acba4d52e..ba9dccfd24ce 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -201,7 +201,7 @@ struct cfs_bandwidth { };
/* CFS-related fields in a runqueue */
struct cfs_rq {
struct load_weight load;
- unsigned long nr_running, h_nr_running;
+ unsigned int nr_running, h_nr_running;
u64 exec_clock;
u64 min_vruntime;
@@ -279,7 +279,7 @@ static inline int rt_bandwidth_enabled(void)
/* Real-Time classes' related field in a runqueue: */
struct rt_rq {
struct rt_prio_array active;
- unsigned long rt_nr_running;
+ unsigned int rt_nr_running;
#if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED
struct {
int curr; /* highest queued rt task prio */
@@ -353,7 +353,7 @@ struct rq {
* nr_running and cpu_load should be in the same cacheline because
* remote CPUs use both these fields when doing load calculation.
*/
- unsigned long nr_running;
+ unsigned int nr_running;
#define CPU_LOAD_IDX_MAX 5
unsigned long cpu_load[CPU_LOAD_IDX_MAX];
unsigned long last_load_update_tick;
@@ -876,7 +876,7 @@ extern void resched_cpu(int cpu);
extern struct rt_bandwidth def_rt_bandwidth;
extern void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime);
-extern void update_cpu_load(struct rq *this_rq);
+extern void update_idle_cpu_load(struct rq *this_rq);
#ifdef CONFIG_CGROUP_CPUACCT
#include <linux/cgroup.h>
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index e8d76c5895ea..ee376beedaf9 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -3,16 +3,357 @@
*
* Copyright 2004-2005 Andrea Arcangeli <andrea@cpushare.com>
*
- * This defines a simple but solid secure-computing mode.
+ * Copyright (C) 2012 Google, Inc.
+ * Will Drewry <wad@chromium.org>
+ *
+ * This defines a simple but solid secure-computing facility.
+ *
+ * Mode 1 uses a fixed list of allowed system calls.
+ * Mode 2 allows user-defined system call filters in the form
+ * of Berkeley Packet Filters/Linux Socket Filters.
*/
+#include <linux/atomic.h>
#include <linux/audit.h>
-#include <linux/seccomp.h>
-#include <linux/sched.h>
#include <linux/compat.h>
+#include <linux/sched.h>
+#include <linux/seccomp.h>
/* #define SECCOMP_DEBUG 1 */
-#define NR_SECCOMP_MODES 1
+
+#ifdef CONFIG_SECCOMP_FILTER
+#include <asm/syscall.h>
+#include <linux/filter.h>
+#include <linux/ptrace.h>
+#include <linux/security.h>
+#include <linux/slab.h>
+#include <linux/tracehook.h>
+#include <linux/uaccess.h>
+
+/**
+ * struct seccomp_filter - container for seccomp BPF programs
+ *
+ * @usage: reference count to manage the object lifetime.
+ * get/put helpers should be used when accessing an instance
+ * outside of a lifetime-guarded section. In general, this
+ * is only needed for handling filters shared across tasks.
+ * @prev: points to a previously installed, or inherited, filter
+ * @len: the number of instructions in the program
+ * @insns: the BPF program instructions to evaluate
+ *
+ * seccomp_filter objects are organized in a tree linked via the @prev
+ * pointer. For any task, it appears to be a singly-linked list starting
+ * with current->seccomp.filter, the most recently attached or inherited filter.
+ * However, multiple filters may share a @prev node, by way of fork(), which
+ * results in a unidirectional tree existing in memory. This is similar to
+ * how namespaces work.
+ *
+ * seccomp_filter objects should never be modified after being attached
+ * to a task_struct (other than @usage).
+ */
+struct seccomp_filter {
+ atomic_t usage;
+ struct seccomp_filter *prev;
+ unsigned short len; /* Instruction count */
+ struct sock_filter insns[];
+};
+
+/* Limit any path through the tree to 256KB worth of instructions. */
+#define MAX_INSNS_PER_PATH ((1 << 18) / sizeof(struct sock_filter))
+
+/**
+ * get_u32 - returns a u32 offset into data
+ * @data: a unsigned 64 bit value
+ * @index: 0 or 1 to return the first or second 32-bits
+ *
+ * This inline exists to hide the length of unsigned long. If a 32-bit
+ * unsigned long is passed in, it will be extended and the top 32-bits will be
+ * 0. If it is a 64-bit unsigned long, then whatever data is resident will be
+ * properly returned.
+ *
+ * Endianness is explicitly ignored and left for BPF program authors to manage
+ * as per the specific architecture.
+ */
+static inline u32 get_u32(u64 data, int index)
+{
+ return ((u32 *)&data)[index];
+}
+
+/* Helper for bpf_load below. */
+#define BPF_DATA(_name) offsetof(struct seccomp_data, _name)
+/**
+ * bpf_load: checks and returns a pointer to the requested offset
+ * @off: offset into struct seccomp_data to load from
+ *
+ * Returns the requested 32-bits of data.
+ * seccomp_check_filter() should assure that @off is 32-bit aligned
+ * and not out of bounds. Failure to do so is a BUG.
+ */
+u32 seccomp_bpf_load(int off)
+{
+ struct pt_regs *regs = task_pt_regs(current);
+ if (off == BPF_DATA(nr))
+ return syscall_get_nr(current, regs);
+ if (off == BPF_DATA(arch))
+ return syscall_get_arch(current, regs);
+ if (off >= BPF_DATA(args[0]) && off < BPF_DATA(args[6])) {
+ unsigned long value;
+ int arg = (off - BPF_DATA(args[0])) / sizeof(u64);
+ int index = !!(off % sizeof(u64));
+ syscall_get_arguments(current, regs, arg, 1, &value);
+ return get_u32(value, index);
+ }
+ if (off == BPF_DATA(instruction_pointer))
+ return get_u32(KSTK_EIP(current), 0);
+ if (off == BPF_DATA(instruction_pointer) + sizeof(u32))
+ return get_u32(KSTK_EIP(current), 1);
+ /* seccomp_check_filter should make this impossible. */
+ BUG();
+}
+
+/**
+ * seccomp_check_filter - verify seccomp filter code
+ * @filter: filter to verify
+ * @flen: length of filter
+ *
+ * Takes a previously checked filter (by sk_chk_filter) and
+ * redirects all filter code that loads struct sk_buff data
+ * and related data through seccomp_bpf_load. It also
+ * enforces length and alignment checking of those loads.
+ *
+ * Returns 0 if the rule set is legal or -EINVAL if not.
+ */
+static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen)
+{
+ int pc;
+ for (pc = 0; pc < flen; pc++) {
+ struct sock_filter *ftest = &filter[pc];
+ u16 code = ftest->code;
+ u32 k = ftest->k;
+
+ switch (code) {
+ case BPF_S_LD_W_ABS:
+ ftest->code = BPF_S_ANC_SECCOMP_LD_W;
+ /* 32-bit aligned and not out of bounds. */
+ if (k >= sizeof(struct seccomp_data) || k & 3)
+ return -EINVAL;
+ continue;
+ case BPF_S_LD_W_LEN:
+ ftest->code = BPF_S_LD_IMM;
+ ftest->k = sizeof(struct seccomp_data);
+ continue;
+ case BPF_S_LDX_W_LEN:
+ ftest->code = BPF_S_LDX_IMM;
+ ftest->k = sizeof(struct seccomp_data);
+ continue;
+ /* Explicitly include allowed calls. */
+ case BPF_S_RET_K:
+ case BPF_S_RET_A:
+ case BPF_S_ALU_ADD_K:
+ case BPF_S_ALU_ADD_X:
+ case BPF_S_ALU_SUB_K:
+ case BPF_S_ALU_SUB_X:
+ case BPF_S_ALU_MUL_K:
+ case BPF_S_ALU_MUL_X:
+ case BPF_S_ALU_DIV_X:
+ case BPF_S_ALU_AND_K:
+ case BPF_S_ALU_AND_X:
+ case BPF_S_ALU_OR_K:
+ case BPF_S_ALU_OR_X:
+ case BPF_S_ALU_LSH_K:
+ case BPF_S_ALU_LSH_X:
+ case BPF_S_ALU_RSH_K:
+ case BPF_S_ALU_RSH_X:
+ case BPF_S_ALU_NEG:
+ case BPF_S_LD_IMM:
+ case BPF_S_LDX_IMM:
+ case BPF_S_MISC_TAX:
+ case BPF_S_MISC_TXA:
+ case BPF_S_ALU_DIV_K:
+ case BPF_S_LD_MEM:
+ case BPF_S_LDX_MEM:
+ case BPF_S_ST:
+ case BPF_S_STX:
+ case BPF_S_JMP_JA:
+ case BPF_S_JMP_JEQ_K:
+ case BPF_S_JMP_JEQ_X:
+ case BPF_S_JMP_JGE_K:
+ case BPF_S_JMP_JGE_X:
+ case BPF_S_JMP_JGT_K:
+ case BPF_S_JMP_JGT_X:
+ case BPF_S_JMP_JSET_K:
+ case BPF_S_JMP_JSET_X:
+ continue;
+ default:
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+/**
+ * seccomp_run_filters - evaluates all seccomp filters against @syscall
+ * @syscall: number of the current system call
+ *
+ * Returns valid seccomp BPF response codes.
+ */
+static u32 seccomp_run_filters(int syscall)
+{
+ struct seccomp_filter *f;
+ u32 ret = SECCOMP_RET_ALLOW;
+
+ /* Ensure unexpected behavior doesn't result in failing open. */
+ if (WARN_ON(current->seccomp.filter == NULL))
+ return SECCOMP_RET_KILL;
+
+ /*
+ * All filters in the list are evaluated and the lowest BPF return
+ * value always takes priority (ignoring the DATA).
+ */
+ for (f = current->seccomp.filter; f; f = f->prev) {
+ u32 cur_ret = sk_run_filter(NULL, f->insns);
+ if ((cur_ret & SECCOMP_RET_ACTION) < (ret & SECCOMP_RET_ACTION))
+ ret = cur_ret;
+ }
+ return ret;
+}
+
+/**
+ * seccomp_attach_filter: Attaches a seccomp filter to current.
+ * @fprog: BPF program to install
+ *
+ * Returns 0 on success or an errno on failure.
+ */
+static long seccomp_attach_filter(struct sock_fprog *fprog)
+{
+ struct seccomp_filter *filter;
+ unsigned long fp_size = fprog->len * sizeof(struct sock_filter);
+ unsigned long total_insns = fprog->len;
+ long ret;
+
+ if (fprog->len == 0 || fprog->len > BPF_MAXINSNS)
+ return -EINVAL;
+
+ for (filter = current->seccomp.filter; filter; filter = filter->prev)
+ total_insns += filter->len + 4; /* include a 4 instr penalty */
+ if (total_insns > MAX_INSNS_PER_PATH)
+ return -ENOMEM;
+
+ /*
+ * Installing a seccomp filter requires that the task have
+ * CAP_SYS_ADMIN in its namespace or be running with no_new_privs.
+ * This avoids scenarios where unprivileged tasks can affect the
+ * behavior of privileged children.
+ */
+ if (!current->no_new_privs &&
+ security_capable_noaudit(current_cred(), current_user_ns(),
+ CAP_SYS_ADMIN) != 0)
+ return -EACCES;
+
+ /* Allocate a new seccomp_filter */
+ filter = kzalloc(sizeof(struct seccomp_filter) + fp_size,
+ GFP_KERNEL|__GFP_NOWARN);
+ if (!filter)
+ return -ENOMEM;
+ atomic_set(&filter->usage, 1);
+ filter->len = fprog->len;
+
+ /* Copy the instructions from fprog. */
+ ret = -EFAULT;
+ if (copy_from_user(filter->insns, fprog->filter, fp_size))
+ goto fail;
+
+ /* Check and rewrite the fprog via the skb checker */
+ ret = sk_chk_filter(filter->insns, filter->len);
+ if (ret)
+ goto fail;
+
+ /* Check and rewrite the fprog for seccomp use */
+ ret = seccomp_check_filter(filter->insns, filter->len);
+ if (ret)
+ goto fail;
+
+ /*
+ * If there is an existing filter, make it the prev and don't drop its
+ * task reference.
+ */
+ filter->prev = current->seccomp.filter;
+ current->seccomp.filter = filter;
+ return 0;
+fail:
+ kfree(filter);
+ return ret;
+}
+
+/**
+ * seccomp_attach_user_filter - attaches a user-supplied sock_fprog
+ * @user_filter: pointer to the user data containing a sock_fprog.
+ *
+ * Returns 0 on success and non-zero otherwise.
+ */
+long seccomp_attach_user_filter(char __user *user_filter)
+{
+ struct sock_fprog fprog;
+ long ret = -EFAULT;
+
+#ifdef CONFIG_COMPAT
+ if (is_compat_task()) {
+ struct compat_sock_fprog fprog32;
+ if (copy_from_user(&fprog32, user_filter, sizeof(fprog32)))
+ goto out;
+ fprog.len = fprog32.len;
+ fprog.filter = compat_ptr(fprog32.filter);
+ } else /* falls through to the if below. */
+#endif
+ if (copy_from_user(&fprog, user_filter, sizeof(fprog)))
+ goto out;
+ ret = seccomp_attach_filter(&fprog);
+out:
+ return ret;
+}
+
+/* get_seccomp_filter - increments the reference count of the filter on @tsk */
+void get_seccomp_filter(struct task_struct *tsk)
+{
+ struct seccomp_filter *orig = tsk->seccomp.filter;
+ if (!orig)
+ return;
+ /* Reference count is bounded by the number of total processes. */
+ atomic_inc(&orig->usage);
+}
+
+/* put_seccomp_filter - decrements the ref count of tsk->seccomp.filter */
+void put_seccomp_filter(struct task_struct *tsk)
+{
+ struct seccomp_filter *orig = tsk->seccomp.filter;
+ /* Clean up single-reference branches iteratively. */
+ while (orig && atomic_dec_and_test(&orig->usage)) {
+ struct seccomp_filter *freeme = orig;
+ orig = orig->prev;
+ kfree(freeme);
+ }
+}
+
+/**
+ * seccomp_send_sigsys - signals the task to allow in-process syscall emulation
+ * @syscall: syscall number to send to userland
+ * @reason: filter-supplied reason code to send to userland (via si_errno)
+ *
+ * Forces a SIGSYS with a code of SYS_SECCOMP and related sigsys info.
+ */
+static void seccomp_send_sigsys(int syscall, int reason)
+{
+ struct siginfo info;
+ memset(&info, 0, sizeof(info));
+ info.si_signo = SIGSYS;
+ info.si_code = SYS_SECCOMP;
+ info.si_call_addr = (void __user *)KSTK_EIP(current);
+ info.si_errno = reason;
+ info.si_arch = syscall_get_arch(current, task_pt_regs(current));
+ info.si_syscall = syscall;
+ force_sig_info(SIGSYS, &info, current);
+}
+#endif /* CONFIG_SECCOMP_FILTER */
/*
* Secure computing mode 1 allows only read/write/exit/sigreturn.
@@ -31,13 +372,15 @@ static int mode1_syscalls_32[] = {
};
#endif
-void __secure_computing(int this_syscall)
+int __secure_computing(int this_syscall)
{
int mode = current->seccomp.mode;
- int * syscall;
+ int exit_sig = 0;
+ int *syscall;
+ u32 ret;
switch (mode) {
- case 1:
+ case SECCOMP_MODE_STRICT:
syscall = mode1_syscalls;
#ifdef CONFIG_COMPAT
if (is_compat_task())
@@ -45,9 +388,54 @@ void __secure_computing(int this_syscall)
#endif
do {
if (*syscall == this_syscall)
- return;
+ return 0;
} while (*++syscall);
+ exit_sig = SIGKILL;
+ ret = SECCOMP_RET_KILL;
+ break;
+#ifdef CONFIG_SECCOMP_FILTER
+ case SECCOMP_MODE_FILTER: {
+ int data;
+ ret = seccomp_run_filters(this_syscall);
+ data = ret & SECCOMP_RET_DATA;
+ ret &= SECCOMP_RET_ACTION;
+ switch (ret) {
+ case SECCOMP_RET_ERRNO:
+ /* Set the low-order 16-bits as a errno. */
+ syscall_set_return_value(current, task_pt_regs(current),
+ -data, 0);
+ goto skip;
+ case SECCOMP_RET_TRAP:
+ /* Show the handler the original registers. */
+ syscall_rollback(current, task_pt_regs(current));
+ /* Let the filter pass back 16 bits of data. */
+ seccomp_send_sigsys(this_syscall, data);
+ goto skip;
+ case SECCOMP_RET_TRACE:
+ /* Skip these calls if there is no tracer. */
+ if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP))
+ goto skip;
+ /* Allow the BPF to provide the event message */
+ ptrace_event(PTRACE_EVENT_SECCOMP, data);
+ /*
+ * The delivery of a fatal signal during event
+ * notification may silently skip tracer notification.
+ * Terminating the task now avoids executing a system
+ * call that may not be intended.
+ */
+ if (fatal_signal_pending(current))
+ break;
+ return 0;
+ case SECCOMP_RET_ALLOW:
+ return 0;
+ case SECCOMP_RET_KILL:
+ default:
+ break;
+ }
+ exit_sig = SIGSYS;
break;
+ }
+#endif
default:
BUG();
}
@@ -55,8 +443,13 @@ void __secure_computing(int this_syscall)
#ifdef SECCOMP_DEBUG
dump_stack();
#endif
- audit_seccomp(this_syscall);
- do_exit(SIGKILL);
+ audit_seccomp(this_syscall, exit_sig, ret);
+ do_exit(exit_sig);
+#ifdef CONFIG_SECCOMP_FILTER
+skip:
+ audit_seccomp(this_syscall, exit_sig, ret);
+#endif
+ return -1;
}
long prctl_get_seccomp(void)
@@ -64,25 +457,48 @@ long prctl_get_seccomp(void)
return current->seccomp.mode;
}
-long prctl_set_seccomp(unsigned long seccomp_mode)
+/**
+ * prctl_set_seccomp: configures current->seccomp.mode
+ * @seccomp_mode: requested mode to use
+ * @filter: optional struct sock_fprog for use with SECCOMP_MODE_FILTER
+ *
+ * This function may be called repeatedly with a @seccomp_mode of
+ * SECCOMP_MODE_FILTER to install additional filters. Every filter
+ * successfully installed will be evaluated (in reverse order) for each system
+ * call the task makes.
+ *
+ * Once current->seccomp.mode is non-zero, it may not be changed.
+ *
+ * Returns 0 on success or -EINVAL on failure.
+ */
+long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter)
{
- long ret;
+ long ret = -EINVAL;
- /* can set it only once to be even more secure */
- ret = -EPERM;
- if (unlikely(current->seccomp.mode))
+ if (current->seccomp.mode &&
+ current->seccomp.mode != seccomp_mode)
goto out;
- ret = -EINVAL;
- if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
- current->seccomp.mode = seccomp_mode;
- set_thread_flag(TIF_SECCOMP);
+ switch (seccomp_mode) {
+ case SECCOMP_MODE_STRICT:
+ ret = 0;
#ifdef TIF_NOTSC
disable_TSC();
#endif
- ret = 0;
+ break;
+#ifdef CONFIG_SECCOMP_FILTER
+ case SECCOMP_MODE_FILTER:
+ ret = seccomp_attach_user_filter(filter);
+ if (ret)
+ goto out;
+ break;
+#endif
+ default:
+ goto out;
}
- out:
+ current->seccomp.mode = seccomp_mode;
+ set_thread_flag(TIF_SECCOMP);
+out:
return ret;
}
diff --git a/kernel/semaphore.c b/kernel/semaphore.c
index 60636a4e25c3..4567fc020fe3 100644
--- a/kernel/semaphore.c
+++ b/kernel/semaphore.c
@@ -118,7 +118,7 @@ EXPORT_SYMBOL(down_killable);
* down_trylock - try to acquire the semaphore, without waiting
* @sem: the semaphore to be acquired
*
- * Try to acquire the semaphore atomically. Returns 0 if the mutex has
+ * Try to acquire the semaphore atomically. Returns 0 if the semaphore has
* been acquired successfully or 1 if it it cannot be acquired.
*
* NOTE: This return value is inverted from both spin_trylock and
diff --git a/kernel/signal.c b/kernel/signal.c
index 17afcaf582d0..1a006b5d9d9d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -160,7 +160,7 @@ void recalc_sigpending(void)
#define SYNCHRONOUS_MASK \
(sigmask(SIGSEGV) | sigmask(SIGBUS) | sigmask(SIGILL) | \
- sigmask(SIGTRAP) | sigmask(SIGFPE))
+ sigmask(SIGTRAP) | sigmask(SIGFPE) | sigmask(SIGSYS))
int next_signal(struct sigpending *pending, sigset_t *mask)
{
@@ -2706,6 +2706,13 @@ int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from)
err |= __put_user(from->si_uid, &to->si_uid);
err |= __put_user(from->si_ptr, &to->si_ptr);
break;
+#ifdef __ARCH_SIGSYS
+ case __SI_SYS:
+ err |= __put_user(from->si_call_addr, &to->si_call_addr);
+ err |= __put_user(from->si_syscall, &to->si_syscall);
+ err |= __put_user(from->si_arch, &to->si_arch);
+ break;
+#endif
default: /* this is just in case for now ... */
err |= __put_user(from->si_pid, &to->si_pid);
err |= __put_user(from->si_uid, &to->si_uid);
diff --git a/kernel/smp.c b/kernel/smp.c
index 2f8b10ecf759..d0ae5b24875e 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -13,6 +13,8 @@
#include <linux/smp.h>
#include <linux/cpu.h>
+#include "smpboot.h"
+
#ifdef CONFIG_USE_GENERIC_SMP_HELPERS
static struct {
struct list_head queue;
@@ -669,6 +671,8 @@ void __init smp_init(void)
{
unsigned int cpu;
+ idle_threads_init();
+
/* FIXME: This should be done in userspace --RR */
for_each_present_cpu(cpu) {
if (num_online_cpus() >= setup_max_cpus)
@@ -791,3 +795,26 @@ void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),
}
}
EXPORT_SYMBOL(on_each_cpu_cond);
+
+static void do_nothing(void *unused)
+{
+}
+
+/**
+ * kick_all_cpus_sync - Force all cpus out of idle
+ *
+ * Used to synchronize the update of pm_idle function pointer. It's
+ * called after the pointer is updated and returns after the dummy
+ * callback function has been executed on all cpus. The execution of
+ * the function can only happen on the remote cpus after they have
+ * left the idle function which had been called via pm_idle function
+ * pointer. So it's guaranteed that nothing uses the previous pointer
+ * anymore.
+ */
+void kick_all_cpus_sync(void)
+{
+ /* Make sure the change is visible before we kick the cpus */
+ smp_mb();
+ smp_call_function(do_nothing, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(kick_all_cpus_sync);
diff --git a/kernel/smpboot.c b/kernel/smpboot.c
new file mode 100644
index 000000000000..e1a797e028a3
--- /dev/null
+++ b/kernel/smpboot.c
@@ -0,0 +1,62 @@
+/*
+ * Common SMP CPU bringup/teardown functions
+ */
+#include <linux/err.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/percpu.h>
+
+#include "smpboot.h"
+
+#ifdef CONFIG_GENERIC_SMP_IDLE_THREAD
+/*
+ * For the hotplug case we keep the task structs around and reuse
+ * them.
+ */
+static DEFINE_PER_CPU(struct task_struct *, idle_threads);
+
+struct task_struct * __cpuinit idle_thread_get(unsigned int cpu)
+{
+ struct task_struct *tsk = per_cpu(idle_threads, cpu);
+
+ if (!tsk)
+ return ERR_PTR(-ENOMEM);
+ init_idle(tsk, cpu);
+ return tsk;
+}
+
+void __init idle_thread_set_boot_cpu(void)
+{
+ per_cpu(idle_threads, smp_processor_id()) = current;
+}
+
+static inline void idle_init(unsigned int cpu)
+{
+ struct task_struct *tsk = per_cpu(idle_threads, cpu);
+
+ if (!tsk) {
+ tsk = fork_idle(cpu);
+ if (IS_ERR(tsk))
+ pr_err("SMP: fork_idle() failed for CPU %u\n", cpu);
+ else
+ per_cpu(idle_threads, cpu) = tsk;
+ }
+}
+
+/**
+ * idle_thread_init - Initialize the idle thread for a cpu
+ * @cpu: The cpu for which the idle thread should be initialized
+ *
+ * Creates the thread if it does not exist.
+ */
+void __init idle_threads_init(void)
+{
+ unsigned int cpu;
+
+ for_each_possible_cpu(cpu) {
+ if (cpu != smp_processor_id())
+ idle_init(cpu);
+ }
+}
+#endif
diff --git a/kernel/smpboot.h b/kernel/smpboot.h
new file mode 100644
index 000000000000..80c0acfb8472
--- /dev/null
+++ b/kernel/smpboot.h
@@ -0,0 +1,18 @@
+#ifndef SMPBOOT_H
+#define SMPBOOT_H
+
+struct task_struct;
+
+int smpboot_prepare(unsigned int cpu);
+
+#ifdef CONFIG_GENERIC_SMP_IDLE_THREAD
+struct task_struct *idle_thread_get(unsigned int cpu);
+void idle_thread_set_boot_cpu(void);
+void idle_threads_init(void);
+#else
+static inline struct task_struct *idle_thread_get(unsigned int cpu) { return NULL; }
+static inline void idle_thread_set_boot_cpu(void) { }
+static inline void idle_threads_init(void) { }
+#endif
+
+#endif
diff --git a/kernel/srcu.c b/kernel/srcu.c
index ba35f3a4a1f4..2095be3318d5 100644
--- a/kernel/srcu.c
+++ b/kernel/srcu.c
@@ -34,10 +34,77 @@
#include <linux/delay.h>
#include <linux/srcu.h>
+/*
+ * Initialize an rcu_batch structure to empty.
+ */
+static inline void rcu_batch_init(struct rcu_batch *b)
+{
+ b->head = NULL;
+ b->tail = &b->head;
+}
+
+/*
+ * Enqueue a callback onto the tail of the specified rcu_batch structure.
+ */
+static inline void rcu_batch_queue(struct rcu_batch *b, struct rcu_head *head)
+{
+ *b->tail = head;
+ b->tail = &head->next;
+}
+
+/*
+ * Is the specified rcu_batch structure empty?
+ */
+static inline bool rcu_batch_empty(struct rcu_batch *b)
+{
+ return b->tail == &b->head;
+}
+
+/*
+ * Remove the callback at the head of the specified rcu_batch structure
+ * and return a pointer to it, or return NULL if the structure is empty.
+ */
+static inline struct rcu_head *rcu_batch_dequeue(struct rcu_batch *b)
+{
+ struct rcu_head *head;
+
+ if (rcu_batch_empty(b))
+ return NULL;
+
+ head = b->head;
+ b->head = head->next;
+ if (b->tail == &head->next)
+ rcu_batch_init(b);
+
+ return head;
+}
+
+/*
+ * Move all callbacks from the rcu_batch structure specified by "from" to
+ * the structure specified by "to".
+ */
+static inline void rcu_batch_move(struct rcu_batch *to, struct rcu_batch *from)
+{
+ if (!rcu_batch_empty(from)) {
+ *to->tail = from->head;
+ to->tail = from->tail;
+ rcu_batch_init(from);
+ }
+}
+
+/* single-thread state-machine */
+static void process_srcu(struct work_struct *work);
+
static int init_srcu_struct_fields(struct srcu_struct *sp)
{
sp->completed = 0;
- mutex_init(&sp->mutex);
+ spin_lock_init(&sp->queue_lock);
+ sp->running = false;
+ rcu_batch_init(&sp->batch_queue);
+ rcu_batch_init(&sp->batch_check0);
+ rcu_batch_init(&sp->batch_check1);
+ rcu_batch_init(&sp->batch_done);
+ INIT_DELAYED_WORK(&sp->work, process_srcu);
sp->per_cpu_ref = alloc_percpu(struct srcu_struct_array);
return sp->per_cpu_ref ? 0 : -ENOMEM;
}
@@ -73,21 +140,116 @@ EXPORT_SYMBOL_GPL(init_srcu_struct);
#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
/*
- * srcu_readers_active_idx -- returns approximate number of readers
- * active on the specified rank of per-CPU counters.
+ * Returns approximate total of the readers' ->seq[] values for the
+ * rank of per-CPU counters specified by idx.
*/
+static unsigned long srcu_readers_seq_idx(struct srcu_struct *sp, int idx)
+{
+ int cpu;
+ unsigned long sum = 0;
+ unsigned long t;
-static int srcu_readers_active_idx(struct srcu_struct *sp, int idx)
+ for_each_possible_cpu(cpu) {
+ t = ACCESS_ONCE(per_cpu_ptr(sp->per_cpu_ref, cpu)->seq[idx]);
+ sum += t;
+ }
+ return sum;
+}
+
+/*
+ * Returns approximate number of readers active on the specified rank
+ * of the per-CPU ->c[] counters.
+ */
+static unsigned long srcu_readers_active_idx(struct srcu_struct *sp, int idx)
{
int cpu;
- int sum;
+ unsigned long sum = 0;
+ unsigned long t;
- sum = 0;
- for_each_possible_cpu(cpu)
- sum += per_cpu_ptr(sp->per_cpu_ref, cpu)->c[idx];
+ for_each_possible_cpu(cpu) {
+ t = ACCESS_ONCE(per_cpu_ptr(sp->per_cpu_ref, cpu)->c[idx]);
+ sum += t;
+ }
return sum;
}
+/*
+ * Return true if the number of pre-existing readers is determined to
+ * be stably zero. An example unstable zero can occur if the call
+ * to srcu_readers_active_idx() misses an __srcu_read_lock() increment,
+ * but due to task migration, sees the corresponding __srcu_read_unlock()
+ * decrement. This can happen because srcu_readers_active_idx() takes
+ * time to sum the array, and might in fact be interrupted or preempted
+ * partway through the summation.
+ */
+static bool srcu_readers_active_idx_check(struct srcu_struct *sp, int idx)
+{
+ unsigned long seq;
+
+ seq = srcu_readers_seq_idx(sp, idx);
+
+ /*
+ * The following smp_mb() A pairs with the smp_mb() B located in
+ * __srcu_read_lock(). This pairing ensures that if an
+ * __srcu_read_lock() increments its counter after the summation
+ * in srcu_readers_active_idx(), then the corresponding SRCU read-side
+ * critical section will see any changes made prior to the start
+ * of the current SRCU grace period.
+ *
+ * Also, if the above call to srcu_readers_seq_idx() saw the
+ * increment of ->seq[], then the call to srcu_readers_active_idx()
+ * must see the increment of ->c[].
+ */
+ smp_mb(); /* A */
+
+ /*
+ * Note that srcu_readers_active_idx() can incorrectly return
+ * zero even though there is a pre-existing reader throughout.
+ * To see this, suppose that task A is in a very long SRCU
+ * read-side critical section that started on CPU 0, and that
+ * no other reader exists, so that the sum of the counters
+ * is equal to one. Then suppose that task B starts executing
+ * srcu_readers_active_idx(), summing up to CPU 1, and then that
+ * task C starts reading on CPU 0, so that its increment is not
+ * summed, but finishes reading on CPU 2, so that its decrement
+ * -is- summed. Then when task B completes its sum, it will
+ * incorrectly get zero, despite the fact that task A has been
+ * in its SRCU read-side critical section the whole time.
+ *
+ * We therefore do a validation step should srcu_readers_active_idx()
+ * return zero.
+ */
+ if (srcu_readers_active_idx(sp, idx) != 0)
+ return false;
+
+ /*
+ * The remainder of this function is the validation step.
+ * The following smp_mb() D pairs with the smp_mb() C in
+ * __srcu_read_unlock(). If the __srcu_read_unlock() was seen
+ * by srcu_readers_active_idx() above, then any destructive
+ * operation performed after the grace period will happen after
+ * the corresponding SRCU read-side critical section.
+ *
+ * Note that there can be at most NR_CPUS worth of readers using
+ * the old index, which is not enough to overflow even a 32-bit
+ * integer. (Yes, this does mean that systems having more than
+ * a billion or so CPUs need to be 64-bit systems.) Therefore,
+ * the sum of the ->seq[] counters cannot possibly overflow.
+ * Therefore, the only way that the return values of the two
+ * calls to srcu_readers_seq_idx() can be equal is if there were
+ * no increments of the corresponding rank of ->seq[] counts
+ * in the interim. But the missed-increment scenario laid out
+ * above includes an increment of the ->seq[] counter by
+ * the corresponding __srcu_read_lock(). Therefore, if this
+ * scenario occurs, the return values from the two calls to
+ * srcu_readers_seq_idx() will differ, and thus the validation
+ * step below suffices.
+ */
+ smp_mb(); /* D */
+
+ return srcu_readers_seq_idx(sp, idx) == seq;
+}
+
/**
* srcu_readers_active - returns approximate number of readers.
* @sp: which srcu_struct to count active readers (holding srcu_read_lock).
@@ -98,7 +260,14 @@ static int srcu_readers_active_idx(struct srcu_struct *sp, int idx)
*/
static int srcu_readers_active(struct srcu_struct *sp)
{
- return srcu_readers_active_idx(sp, 0) + srcu_readers_active_idx(sp, 1);
+ int cpu;
+ unsigned long sum = 0;
+
+ for_each_possible_cpu(cpu) {
+ sum += ACCESS_ONCE(per_cpu_ptr(sp->per_cpu_ref, cpu)->c[0]);
+ sum += ACCESS_ONCE(per_cpu_ptr(sp->per_cpu_ref, cpu)->c[1]);
+ }
+ return sum;
}
/**
@@ -131,10 +300,11 @@ int __srcu_read_lock(struct srcu_struct *sp)
int idx;
preempt_disable();
- idx = sp->completed & 0x1;
- barrier(); /* ensure compiler looks -once- at sp->completed. */
- per_cpu_ptr(sp->per_cpu_ref, smp_processor_id())->c[idx]++;
- srcu_barrier(); /* ensure compiler won't misorder critical section. */
+ idx = rcu_dereference_index_check(sp->completed,
+ rcu_read_lock_sched_held()) & 0x1;
+ ACCESS_ONCE(this_cpu_ptr(sp->per_cpu_ref)->c[idx]) += 1;
+ smp_mb(); /* B */ /* Avoid leaking the critical section. */
+ ACCESS_ONCE(this_cpu_ptr(sp->per_cpu_ref)->seq[idx]) += 1;
preempt_enable();
return idx;
}
@@ -149,8 +319,8 @@ EXPORT_SYMBOL_GPL(__srcu_read_lock);
void __srcu_read_unlock(struct srcu_struct *sp, int idx)
{
preempt_disable();
- srcu_barrier(); /* ensure compiler won't misorder critical section. */
- per_cpu_ptr(sp->per_cpu_ref, smp_processor_id())->c[idx]--;
+ smp_mb(); /* C */ /* Avoid leaking the critical section. */
+ ACCESS_ONCE(this_cpu_ptr(sp->per_cpu_ref)->c[idx]) -= 1;
preempt_enable();
}
EXPORT_SYMBOL_GPL(__srcu_read_unlock);
@@ -163,106 +333,119 @@ EXPORT_SYMBOL_GPL(__srcu_read_unlock);
* we repeatedly block for 1-millisecond time periods. This approach
* has done well in testing, so there is no need for a config parameter.
*/
-#define SYNCHRONIZE_SRCU_READER_DELAY 10
+#define SRCU_RETRY_CHECK_DELAY 5
+#define SYNCHRONIZE_SRCU_TRYCOUNT 2
+#define SYNCHRONIZE_SRCU_EXP_TRYCOUNT 12
/*
- * Helper function for synchronize_srcu() and synchronize_srcu_expedited().
+ * @@@ Wait until all pre-existing readers complete. Such readers
+ * will have used the index specified by "idx".
+ * the caller should ensures the ->completed is not changed while checking
+ * and idx = (->completed & 1) ^ 1
*/
-static void __synchronize_srcu(struct srcu_struct *sp, void (*sync_func)(void))
+static bool try_check_zero(struct srcu_struct *sp, int idx, int trycount)
{
- int idx;
-
- rcu_lockdep_assert(!lock_is_held(&sp->dep_map) &&
- !lock_is_held(&rcu_bh_lock_map) &&
- !lock_is_held(&rcu_lock_map) &&
- !lock_is_held(&rcu_sched_lock_map),
- "Illegal synchronize_srcu() in same-type SRCU (or RCU) read-side critical section");
-
- idx = sp->completed;
- mutex_lock(&sp->mutex);
+ for (;;) {
+ if (srcu_readers_active_idx_check(sp, idx))
+ return true;
+ if (--trycount <= 0)
+ return false;
+ udelay(SRCU_RETRY_CHECK_DELAY);
+ }
+}
- /*
- * Check to see if someone else did the work for us while we were
- * waiting to acquire the lock. We need -two- advances of
- * the counter, not just one. If there was but one, we might have
- * shown up -after- our helper's first synchronize_sched(), thus
- * having failed to prevent CPU-reordering races with concurrent
- * srcu_read_unlock()s on other CPUs (see comment below). So we
- * either (1) wait for two or (2) supply the second ourselves.
- */
+/*
+ * Increment the ->completed counter so that future SRCU readers will
+ * use the other rank of the ->c[] and ->seq[] arrays. This allows
+ * us to wait for pre-existing readers in a starvation-free manner.
+ */
+static void srcu_flip(struct srcu_struct *sp)
+{
+ sp->completed++;
+}
- if ((sp->completed - idx) >= 2) {
- mutex_unlock(&sp->mutex);
- return;
+/*
+ * Enqueue an SRCU callback on the specified srcu_struct structure,
+ * initiating grace-period processing if it is not already running.
+ */
+void call_srcu(struct srcu_struct *sp, struct rcu_head *head,
+ void (*func)(struct rcu_head *head))
+{
+ unsigned long flags;
+
+ head->next = NULL;
+ head->func = func;
+ spin_lock_irqsave(&sp->queue_lock, flags);
+ rcu_batch_queue(&sp->batch_queue, head);
+ if (!sp->running) {
+ sp->running = true;
+ queue_delayed_work(system_nrt_wq, &sp->work, 0);
}
+ spin_unlock_irqrestore(&sp->queue_lock, flags);
+}
+EXPORT_SYMBOL_GPL(call_srcu);
- sync_func(); /* Force memory barrier on all CPUs. */
+struct rcu_synchronize {
+ struct rcu_head head;
+ struct completion completion;
+};
- /*
- * The preceding synchronize_sched() ensures that any CPU that
- * sees the new value of sp->completed will also see any preceding
- * changes to data structures made by this CPU. This prevents
- * some other CPU from reordering the accesses in its SRCU
- * read-side critical section to precede the corresponding
- * srcu_read_lock() -- ensuring that such references will in
- * fact be protected.
- *
- * So it is now safe to do the flip.
- */
+/*
+ * Awaken the corresponding synchronize_srcu() instance now that a
+ * grace period has elapsed.
+ */
+static void wakeme_after_rcu(struct rcu_head *head)
+{
+ struct rcu_synchronize *rcu;
- idx = sp->completed & 0x1;
- sp->completed++;
+ rcu = container_of(head, struct rcu_synchronize, head);
+ complete(&rcu->completion);
+}
- sync_func(); /* Force memory barrier on all CPUs. */
+static void srcu_advance_batches(struct srcu_struct *sp, int trycount);
+static void srcu_reschedule(struct srcu_struct *sp);
- /*
- * At this point, because of the preceding synchronize_sched(),
- * all srcu_read_lock() calls using the old counters have completed.
- * Their corresponding critical sections might well be still
- * executing, but the srcu_read_lock() primitives themselves
- * will have finished executing. We initially give readers
- * an arbitrarily chosen 10 microseconds to get out of their
- * SRCU read-side critical sections, then loop waiting 1/HZ
- * seconds per iteration. The 10-microsecond value has done
- * very well in testing.
- */
-
- if (srcu_readers_active_idx(sp, idx))
- udelay(SYNCHRONIZE_SRCU_READER_DELAY);
- while (srcu_readers_active_idx(sp, idx))
- schedule_timeout_interruptible(1);
+/*
+ * Helper function for synchronize_srcu() and synchronize_srcu_expedited().
+ */
+static void __synchronize_srcu(struct srcu_struct *sp, int trycount)
+{
+ struct rcu_synchronize rcu;
+ struct rcu_head *head = &rcu.head;
+ bool done = false;
- sync_func(); /* Force memory barrier on all CPUs. */
+ rcu_lockdep_assert(!lock_is_held(&sp->dep_map) &&
+ !lock_is_held(&rcu_bh_lock_map) &&
+ !lock_is_held(&rcu_lock_map) &&
+ !lock_is_held(&rcu_sched_lock_map),
+ "Illegal synchronize_srcu() in same-type SRCU (or RCU) read-side critical section");
- /*
- * The preceding synchronize_sched() forces all srcu_read_unlock()
- * primitives that were executing concurrently with the preceding
- * for_each_possible_cpu() loop to have completed by this point.
- * More importantly, it also forces the corresponding SRCU read-side
- * critical sections to have also completed, and the corresponding
- * references to SRCU-protected data items to be dropped.
- *
- * Note:
- *
- * Despite what you might think at first glance, the
- * preceding synchronize_sched() -must- be within the
- * critical section ended by the following mutex_unlock().
- * Otherwise, a task taking the early exit can race
- * with a srcu_read_unlock(), which might have executed
- * just before the preceding srcu_readers_active() check,
- * and whose CPU might have reordered the srcu_read_unlock()
- * with the preceding critical section. In this case, there
- * is nothing preventing the synchronize_sched() task that is
- * taking the early exit from freeing a data structure that
- * is still being referenced (out of order) by the task
- * doing the srcu_read_unlock().
- *
- * Alternatively, the comparison with "2" on the early exit
- * could be changed to "3", but this increases synchronize_srcu()
- * latency for bulk loads. So the current code is preferred.
- */
+ init_completion(&rcu.completion);
+
+ head->next = NULL;
+ head->func = wakeme_after_rcu;
+ spin_lock_irq(&sp->queue_lock);
+ if (!sp->running) {
+ /* steal the processing owner */
+ sp->running = true;
+ rcu_batch_queue(&sp->batch_check0, head);
+ spin_unlock_irq(&sp->queue_lock);
+
+ srcu_advance_batches(sp, trycount);
+ if (!rcu_batch_empty(&sp->batch_done)) {
+ BUG_ON(sp->batch_done.head != head);
+ rcu_batch_dequeue(&sp->batch_done);
+ done = true;
+ }
+ /* give the processing owner to work_struct */
+ srcu_reschedule(sp);
+ } else {
+ rcu_batch_queue(&sp->batch_queue, head);
+ spin_unlock_irq(&sp->queue_lock);
+ }
- mutex_unlock(&sp->mutex);
+ if (!done)
+ wait_for_completion(&rcu.completion);
}
/**
@@ -281,7 +464,7 @@ static void __synchronize_srcu(struct srcu_struct *sp, void (*sync_func)(void))
*/
void synchronize_srcu(struct srcu_struct *sp)
{
- __synchronize_srcu(sp, synchronize_sched);
+ __synchronize_srcu(sp, SYNCHRONIZE_SRCU_TRYCOUNT);
}
EXPORT_SYMBOL_GPL(synchronize_srcu);
@@ -289,18 +472,11 @@ EXPORT_SYMBOL_GPL(synchronize_srcu);
* synchronize_srcu_expedited - Brute-force SRCU grace period
* @sp: srcu_struct with which to synchronize.
*
- * Wait for an SRCU grace period to elapse, but use a "big hammer"
- * approach to force the grace period to end quickly. This consumes
- * significant time on all CPUs and is unfriendly to real-time workloads,
- * so is thus not recommended for any sort of common-case code. In fact,
- * if you are using synchronize_srcu_expedited() in a loop, please
- * restructure your code to batch your updates, and then use a single
- * synchronize_srcu() instead.
+ * Wait for an SRCU grace period to elapse, but be more aggressive about
+ * spinning rather than blocking when waiting.
*
* Note that it is illegal to call this function while holding any lock
- * that is acquired by a CPU-hotplug notifier. And yes, it is also illegal
- * to call this function from a CPU-hotplug notifier. Failing to observe
- * these restriction will result in deadlock. It is also illegal to call
+ * that is acquired by a CPU-hotplug notifier. It is also illegal to call
* synchronize_srcu_expedited() from the corresponding SRCU read-side
* critical section; doing so will result in deadlock. However, it is
* perfectly legal to call synchronize_srcu_expedited() on one srcu_struct
@@ -309,20 +485,166 @@ EXPORT_SYMBOL_GPL(synchronize_srcu);
*/
void synchronize_srcu_expedited(struct srcu_struct *sp)
{
- __synchronize_srcu(sp, synchronize_sched_expedited);
+ __synchronize_srcu(sp, SYNCHRONIZE_SRCU_EXP_TRYCOUNT);
}
EXPORT_SYMBOL_GPL(synchronize_srcu_expedited);
/**
+ * srcu_barrier - Wait until all in-flight call_srcu() callbacks complete.
+ */
+void srcu_barrier(struct srcu_struct *sp)
+{
+ synchronize_srcu(sp);
+}
+EXPORT_SYMBOL_GPL(srcu_barrier);
+
+/**
* srcu_batches_completed - return batches completed.
* @sp: srcu_struct on which to report batch completion.
*
* Report the number of batches, correlated with, but not necessarily
* precisely the same as, the number of grace periods that have elapsed.
*/
-
long srcu_batches_completed(struct srcu_struct *sp)
{
return sp->completed;
}
EXPORT_SYMBOL_GPL(srcu_batches_completed);
+
+#define SRCU_CALLBACK_BATCH 10
+#define SRCU_INTERVAL 1
+
+/*
+ * Move any new SRCU callbacks to the first stage of the SRCU grace
+ * period pipeline.
+ */
+static void srcu_collect_new(struct srcu_struct *sp)
+{
+ if (!rcu_batch_empty(&sp->batch_queue)) {
+ spin_lock_irq(&sp->queue_lock);
+ rcu_batch_move(&sp->batch_check0, &sp->batch_queue);
+ spin_unlock_irq(&sp->queue_lock);
+ }
+}
+
+/*
+ * Core SRCU state machine. Advance callbacks from ->batch_check0 to
+ * ->batch_check1 and then to ->batch_done as readers drain.
+ */
+static void srcu_advance_batches(struct srcu_struct *sp, int trycount)
+{
+ int idx = 1 ^ (sp->completed & 1);
+
+ /*
+ * Because readers might be delayed for an extended period after
+ * fetching ->completed for their index, at any point in time there
+ * might well be readers using both idx=0 and idx=1. We therefore
+ * need to wait for readers to clear from both index values before
+ * invoking a callback.
+ */
+
+ if (rcu_batch_empty(&sp->batch_check0) &&
+ rcu_batch_empty(&sp->batch_check1))
+ return; /* no callbacks need to be advanced */
+
+ if (!try_check_zero(sp, idx, trycount))
+ return; /* failed to advance, will try after SRCU_INTERVAL */
+
+ /*
+ * The callbacks in ->batch_check1 have already done with their
+ * first zero check and flip back when they were enqueued on
+ * ->batch_check0 in a previous invocation of srcu_advance_batches().
+ * (Presumably try_check_zero() returned false during that
+ * invocation, leaving the callbacks stranded on ->batch_check1.)
+ * They are therefore ready to invoke, so move them to ->batch_done.
+ */
+ rcu_batch_move(&sp->batch_done, &sp->batch_check1);
+
+ if (rcu_batch_empty(&sp->batch_check0))
+ return; /* no callbacks need to be advanced */
+ srcu_flip(sp);
+
+ /*
+ * The callbacks in ->batch_check0 just finished their
+ * first check zero and flip, so move them to ->batch_check1
+ * for future checking on the other idx.
+ */
+ rcu_batch_move(&sp->batch_check1, &sp->batch_check0);
+
+ /*
+ * SRCU read-side critical sections are normally short, so check
+ * at least twice in quick succession after a flip.
+ */
+ trycount = trycount < 2 ? 2 : trycount;
+ if (!try_check_zero(sp, idx^1, trycount))
+ return; /* failed to advance, will try after SRCU_INTERVAL */
+
+ /*
+ * The callbacks in ->batch_check1 have now waited for all
+ * pre-existing readers using both idx values. They are therefore
+ * ready to invoke, so move them to ->batch_done.
+ */
+ rcu_batch_move(&sp->batch_done, &sp->batch_check1);
+}
+
+/*
+ * Invoke a limited number of SRCU callbacks that have passed through
+ * their grace period. If there are more to do, SRCU will reschedule
+ * the workqueue.
+ */
+static void srcu_invoke_callbacks(struct srcu_struct *sp)
+{
+ int i;
+ struct rcu_head *head;
+
+ for (i = 0; i < SRCU_CALLBACK_BATCH; i++) {
+ head = rcu_batch_dequeue(&sp->batch_done);
+ if (!head)
+ break;
+ local_bh_disable();
+ head->func(head);
+ local_bh_enable();
+ }
+}
+
+/*
+ * Finished one round of SRCU grace period. Start another if there are
+ * more SRCU callbacks queued, otherwise put SRCU into not-running state.
+ */
+static void srcu_reschedule(struct srcu_struct *sp)
+{
+ bool pending = true;
+
+ if (rcu_batch_empty(&sp->batch_done) &&
+ rcu_batch_empty(&sp->batch_check1) &&
+ rcu_batch_empty(&sp->batch_check0) &&
+ rcu_batch_empty(&sp->batch_queue)) {
+ spin_lock_irq(&sp->queue_lock);
+ if (rcu_batch_empty(&sp->batch_done) &&
+ rcu_batch_empty(&sp->batch_check1) &&
+ rcu_batch_empty(&sp->batch_check0) &&
+ rcu_batch_empty(&sp->batch_queue)) {
+ sp->running = false;
+ pending = false;
+ }
+ spin_unlock_irq(&sp->queue_lock);
+ }
+
+ if (pending)
+ queue_delayed_work(system_nrt_wq, &sp->work, SRCU_INTERVAL);
+}
+
+/*
+ * This is the work-queue function that handles SRCU grace periods.
+ */
+static void process_srcu(struct work_struct *work)
+{
+ struct srcu_struct *sp;
+
+ sp = container_of(work, struct srcu_struct, work.work);
+
+ srcu_collect_new(sp);
+ srcu_advance_batches(sp, 1);
+ srcu_invoke_callbacks(sp);
+ srcu_reschedule(sp);
+}
diff --git a/kernel/sys.c b/kernel/sys.c
index e7006eb6c1e4..ba0ae8eea6fb 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1908,7 +1908,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
error = prctl_get_seccomp();
break;
case PR_SET_SECCOMP:
- error = prctl_set_seccomp(arg2);
+ error = prctl_set_seccomp(arg2, (char __user *)arg3);
break;
case PR_GET_TSC:
error = GET_TSC_CTL(arg2);
@@ -1979,6 +1979,16 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
error = put_user(me->signal->is_child_subreaper,
(int __user *) arg2);
break;
+ case PR_SET_NO_NEW_PRIVS:
+ if (arg2 != 1 || arg3 || arg4 || arg5)
+ return -EINVAL;
+
+ current->no_new_privs = 1;
+ break;
+ case PR_GET_NO_NEW_PRIVS:
+ if (arg2 || arg3 || arg4 || arg5)
+ return -EINVAL;
+ return current->no_new_privs ? 1 : 0;
default:
error = -EINVAL;
break;
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 8a538c55fc7b..aa27d391bfc8 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -59,7 +59,7 @@ static DEFINE_SPINLOCK(rtcdev_lock);
* If one has not already been chosen, it checks to see if a
* functional rtc device is available.
*/
-static struct rtc_device *alarmtimer_get_rtcdev(void)
+struct rtc_device *alarmtimer_get_rtcdev(void)
{
unsigned long flags;
struct rtc_device *ret;
@@ -115,7 +115,7 @@ static void alarmtimer_rtc_interface_remove(void)
class_interface_unregister(&alarmtimer_rtc_interface);
}
#else
-static inline struct rtc_device *alarmtimer_get_rtcdev(void)
+struct rtc_device *alarmtimer_get_rtcdev(void)
{
return NULL;
}
diff --git a/kernel/timer.c b/kernel/timer.c
index a297ffcf888e..09de9a941cd7 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -861,7 +861,13 @@ EXPORT_SYMBOL(mod_timer);
*
* mod_timer_pinned() is a way to update the expire field of an
* active timer (if the timer is inactive it will be activated)
- * and not allow the timer to be migrated to a different CPU.
+ * and to ensure that the timer is scheduled on the current CPU.
+ *
+ * Note that this does not prevent the timer from being migrated
+ * when the current CPU goes offline. If this is a problem for
+ * you, use CPU-hotplug notifiers to handle it correctly, for
+ * example, cancelling the timer when the corresponding CPU goes
+ * offline.
*
* mod_timer_pinned(timer, expires) is equivalent to:
*
@@ -1102,7 +1108,9 @@ static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long),
* warnings as well as problems when looking into
* timer->lockdep_map, make a copy and use that here.
*/
- struct lockdep_map lockdep_map = timer->lockdep_map;
+ struct lockdep_map lockdep_map;
+
+ lockdep_copy_map(&lockdep_map, &timer->lockdep_map);
#endif
/*
* Couple the lock chain with the lock chain at
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index a1d2849f2473..f347ac91292d 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -141,7 +141,6 @@ if FTRACE
config FUNCTION_TRACER
bool "Kernel Function Tracer"
depends on HAVE_FUNCTION_TRACER
- select FRAME_POINTER if !ARM_UNWIND && !PPC && !S390 && !MICROBLAZE
select KALLSYMS
select GENERIC_TRACER
select CONTEXT_SWITCH_TRACER
@@ -272,7 +271,7 @@ config PROFILE_ANNOTATED_BRANCHES
bool "Trace likely/unlikely profiler"
select TRACE_BRANCH_PROFILING
help
- This tracer profiles all the the likely and unlikely macros
+ This tracer profiles all likely and unlikely macros
in the kernel. It will display the results in:
/sys/kernel/debug/tracing/trace_stat/branch_annotated
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 5f39a07fe5ea..b3afe0e76f79 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -41,7 +41,6 @@ obj-$(CONFIG_STACK_TRACER) += trace_stack.o
obj-$(CONFIG_MMIOTRACE) += trace_mmiotrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += trace_functions_graph.o
obj-$(CONFIG_TRACE_BRANCH_PROFILING) += trace_branch.o
-obj-$(CONFIG_WORKQUEUE_TRACER) += trace_workqueue.o
obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o
ifeq ($(CONFIG_BLOCK),y)
obj-$(CONFIG_EVENT_TRACING) += blktrace.o
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 0fa92f677c92..a008663d86c8 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1383,44 +1383,73 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
static int ftrace_cmp_recs(const void *a, const void *b)
{
- const struct dyn_ftrace *reca = a;
- const struct dyn_ftrace *recb = b;
+ const struct dyn_ftrace *key = a;
+ const struct dyn_ftrace *rec = b;
- if (reca->ip > recb->ip)
- return 1;
- if (reca->ip < recb->ip)
+ if (key->flags < rec->ip)
return -1;
+ if (key->ip >= rec->ip + MCOUNT_INSN_SIZE)
+ return 1;
return 0;
}
-/**
- * ftrace_location - return true if the ip giving is a traced location
- * @ip: the instruction pointer to check
- *
- * Returns 1 if @ip given is a pointer to a ftrace location.
- * That is, the instruction that is either a NOP or call to
- * the function tracer. It checks the ftrace internal tables to
- * determine if the address belongs or not.
- */
-int ftrace_location(unsigned long ip)
+static unsigned long ftrace_location_range(unsigned long start, unsigned long end)
{
struct ftrace_page *pg;
struct dyn_ftrace *rec;
struct dyn_ftrace key;
- key.ip = ip;
+ key.ip = start;
+ key.flags = end; /* overload flags, as it is unsigned long */
for (pg = ftrace_pages_start; pg; pg = pg->next) {
+ if (end < pg->records[0].ip ||
+ start >= (pg->records[pg->index - 1].ip + MCOUNT_INSN_SIZE))
+ continue;
rec = bsearch(&key, pg->records, pg->index,
sizeof(struct dyn_ftrace),
ftrace_cmp_recs);
if (rec)
- return 1;
+ return rec->ip;
}
return 0;
}
+/**
+ * ftrace_location - return true if the ip giving is a traced location
+ * @ip: the instruction pointer to check
+ *
+ * Returns rec->ip if @ip given is a pointer to a ftrace location.
+ * That is, the instruction that is either a NOP or call to
+ * the function tracer. It checks the ftrace internal tables to
+ * determine if the address belongs or not.
+ */
+unsigned long ftrace_location(unsigned long ip)
+{
+ return ftrace_location_range(ip, ip);
+}
+
+/**
+ * ftrace_text_reserved - return true if range contains an ftrace location
+ * @start: start of range to search
+ * @end: end of range to search (inclusive). @end points to the last byte to check.
+ *
+ * Returns 1 if @start and @end contains a ftrace location.
+ * That is, the instruction that is either a NOP or call to
+ * the function tracer. It checks the ftrace internal tables to
+ * determine if the address belongs or not.
+ */
+int ftrace_text_reserved(void *start, void *end)
+{
+ unsigned long ret;
+
+ ret = ftrace_location_range((unsigned long)start,
+ (unsigned long)end);
+
+ return (int)!!ret;
+}
+
static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
int filter_hash,
bool inc)
@@ -1520,35 +1549,6 @@ static void ftrace_hash_rec_enable(struct ftrace_ops *ops,
__ftrace_hash_rec_update(ops, filter_hash, 1);
}
-static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip)
-{
- if (ftrace_pages->index == ftrace_pages->size) {
- /* We should have allocated enough */
- if (WARN_ON(!ftrace_pages->next))
- return NULL;
- ftrace_pages = ftrace_pages->next;
- }
-
- return &ftrace_pages->records[ftrace_pages->index++];
-}
-
-static struct dyn_ftrace *
-ftrace_record_ip(unsigned long ip)
-{
- struct dyn_ftrace *rec;
-
- if (ftrace_disabled)
- return NULL;
-
- rec = ftrace_alloc_dyn_node(ip);
- if (!rec)
- return NULL;
-
- rec->ip = ip;
-
- return rec;
-}
-
static void print_ip_ins(const char *fmt, unsigned char *p)
{
int i;
@@ -1598,21 +1598,6 @@ void ftrace_bug(int failed, unsigned long ip)
}
}
-
-/* Return 1 if the address range is reserved for ftrace */
-int ftrace_text_reserved(void *start, void *end)
-{
- struct dyn_ftrace *rec;
- struct ftrace_page *pg;
-
- do_for_each_ftrace_rec(pg, rec) {
- if (rec->ip <= (unsigned long)end &&
- rec->ip + MCOUNT_INSN_SIZE > (unsigned long)start)
- return 1;
- } while_for_each_ftrace_rec();
- return 0;
-}
-
static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update)
{
unsigned long flag = 0UL;
@@ -1698,7 +1683,7 @@ __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
return -1; /* unknow ftrace bug */
}
-static void ftrace_replace_code(int update)
+void __weak ftrace_replace_code(int enable)
{
struct dyn_ftrace *rec;
struct ftrace_page *pg;
@@ -1708,7 +1693,7 @@ static void ftrace_replace_code(int update)
return;
do_for_each_ftrace_rec(pg, rec) {
- failed = __ftrace_replace_code(rec, update);
+ failed = __ftrace_replace_code(rec, enable);
if (failed) {
ftrace_bug(failed, rec->ip);
/* Stop processing */
@@ -1826,22 +1811,27 @@ int __weak ftrace_arch_code_modify_post_process(void)
return 0;
}
-static int __ftrace_modify_code(void *data)
+void ftrace_modify_all_code(int command)
{
- int *command = data;
-
- if (*command & FTRACE_UPDATE_CALLS)
+ if (command & FTRACE_UPDATE_CALLS)
ftrace_replace_code(1);
- else if (*command & FTRACE_DISABLE_CALLS)
+ else if (command & FTRACE_DISABLE_CALLS)
ftrace_replace_code(0);
- if (*command & FTRACE_UPDATE_TRACE_FUNC)
+ if (command & FTRACE_UPDATE_TRACE_FUNC)
ftrace_update_ftrace_func(ftrace_trace_function);
- if (*command & FTRACE_START_FUNC_RET)
+ if (command & FTRACE_START_FUNC_RET)
ftrace_enable_ftrace_graph_caller();
- else if (*command & FTRACE_STOP_FUNC_RET)
+ else if (command & FTRACE_STOP_FUNC_RET)
ftrace_disable_ftrace_graph_caller();
+}
+
+static int __ftrace_modify_code(void *data)
+{
+ int *command = data;
+
+ ftrace_modify_all_code(*command);
return 0;
}
@@ -2469,57 +2459,35 @@ static int
ftrace_avail_open(struct inode *inode, struct file *file)
{
struct ftrace_iterator *iter;
- int ret;
if (unlikely(ftrace_disabled))
return -ENODEV;
- iter = kzalloc(sizeof(*iter), GFP_KERNEL);
- if (!iter)
- return -ENOMEM;
-
- iter->pg = ftrace_pages_start;
- iter->ops = &global_ops;
-
- ret = seq_open(file, &show_ftrace_seq_ops);
- if (!ret) {
- struct seq_file *m = file->private_data;
-
- m->private = iter;
- } else {
- kfree(iter);
+ iter = __seq_open_private(file, &show_ftrace_seq_ops, sizeof(*iter));
+ if (iter) {
+ iter->pg = ftrace_pages_start;
+ iter->ops = &global_ops;
}
- return ret;
+ return iter ? 0 : -ENOMEM;
}
static int
ftrace_enabled_open(struct inode *inode, struct file *file)
{
struct ftrace_iterator *iter;
- int ret;
if (unlikely(ftrace_disabled))
return -ENODEV;
- iter = kzalloc(sizeof(*iter), GFP_KERNEL);
- if (!iter)
- return -ENOMEM;
-
- iter->pg = ftrace_pages_start;
- iter->flags = FTRACE_ITER_ENABLED;
- iter->ops = &global_ops;
-
- ret = seq_open(file, &show_ftrace_seq_ops);
- if (!ret) {
- struct seq_file *m = file->private_data;
-
- m->private = iter;
- } else {
- kfree(iter);
+ iter = __seq_open_private(file, &show_ftrace_seq_ops, sizeof(*iter));
+ if (iter) {
+ iter->pg = ftrace_pages_start;
+ iter->flags = FTRACE_ITER_ENABLED;
+ iter->ops = &global_ops;
}
- return ret;
+ return iter ? 0 : -ENOMEM;
}
static void ftrace_filter_reset(struct ftrace_hash *hash)
@@ -3688,22 +3656,36 @@ static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
return 0;
}
-static void ftrace_swap_recs(void *a, void *b, int size)
+static int ftrace_cmp_ips(const void *a, const void *b)
+{
+ const unsigned long *ipa = a;
+ const unsigned long *ipb = b;
+
+ if (*ipa > *ipb)
+ return 1;
+ if (*ipa < *ipb)
+ return -1;
+ return 0;
+}
+
+static void ftrace_swap_ips(void *a, void *b, int size)
{
- struct dyn_ftrace *reca = a;
- struct dyn_ftrace *recb = b;
- struct dyn_ftrace t;
+ unsigned long *ipa = a;
+ unsigned long *ipb = b;
+ unsigned long t;
- t = *reca;
- *reca = *recb;
- *recb = t;
+ t = *ipa;
+ *ipa = *ipb;
+ *ipb = t;
}
static int ftrace_process_locs(struct module *mod,
unsigned long *start,
unsigned long *end)
{
+ struct ftrace_page *start_pg;
struct ftrace_page *pg;
+ struct dyn_ftrace *rec;
unsigned long count;
unsigned long *p;
unsigned long addr;
@@ -3715,8 +3697,11 @@ static int ftrace_process_locs(struct module *mod,
if (!count)
return 0;
- pg = ftrace_allocate_pages(count);
- if (!pg)
+ sort(start, count, sizeof(*start),
+ ftrace_cmp_ips, ftrace_swap_ips);
+
+ start_pg = ftrace_allocate_pages(count);
+ if (!start_pg)
return -ENOMEM;
mutex_lock(&ftrace_lock);
@@ -3729,7 +3714,7 @@ static int ftrace_process_locs(struct module *mod,
if (!mod) {
WARN_ON(ftrace_pages || ftrace_pages_start);
/* First initialization */
- ftrace_pages = ftrace_pages_start = pg;
+ ftrace_pages = ftrace_pages_start = start_pg;
} else {
if (!ftrace_pages)
goto out;
@@ -3740,11 +3725,11 @@ static int ftrace_process_locs(struct module *mod,
ftrace_pages = ftrace_pages->next;
}
- ftrace_pages->next = pg;
- ftrace_pages = pg;
+ ftrace_pages->next = start_pg;
}
p = start;
+ pg = start_pg;
while (p < end) {
addr = ftrace_call_adjust(*p++);
/*
@@ -3755,17 +3740,26 @@ static int ftrace_process_locs(struct module *mod,
*/
if (!addr)
continue;
- if (!ftrace_record_ip(addr))
- break;
+
+ if (pg->index == pg->size) {
+ /* We should have allocated enough */
+ if (WARN_ON(!pg->next))
+ break;
+ pg = pg->next;
+ }
+
+ rec = &pg->records[pg->index++];
+ rec->ip = addr;
}
- /* These new locations need to be initialized */
- ftrace_new_pgs = pg;
+ /* We should have used all pages */
+ WARN_ON(pg->next);
+
+ /* Assign the last page to ftrace_pages */
+ ftrace_pages = pg;
- /* Make each individual set of pages sorted by ips */
- for (; pg; pg = pg->next)
- sort(pg->records, pg->index, sizeof(struct dyn_ftrace),
- ftrace_cmp_recs, ftrace_swap_recs);
+ /* These new locations need to be initialized */
+ ftrace_new_pgs = start_pg;
/*
* We only need to disable interrupts on start up
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index cf8d11e91efd..6420cda62336 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -23,6 +23,8 @@
#include <asm/local.h>
#include "trace.h"
+static void update_pages_handler(struct work_struct *work);
+
/*
* The ring buffer header is special. We must manually up keep it.
*/
@@ -449,6 +451,7 @@ struct ring_buffer_per_cpu {
raw_spinlock_t reader_lock; /* serialize readers */
arch_spinlock_t lock;
struct lock_class_key lock_key;
+ unsigned int nr_pages;
struct list_head *pages;
struct buffer_page *head_page; /* read from head */
struct buffer_page *tail_page; /* write to tail */
@@ -466,13 +469,18 @@ struct ring_buffer_per_cpu {
unsigned long read_bytes;
u64 write_stamp;
u64 read_stamp;
+ /* ring buffer pages to update, > 0 to add, < 0 to remove */
+ int nr_pages_to_update;
+ struct list_head new_pages; /* new pages to add */
+ struct work_struct update_pages_work;
+ struct completion update_done;
};
struct ring_buffer {
- unsigned pages;
unsigned flags;
int cpus;
atomic_t record_disabled;
+ atomic_t resize_disabled;
cpumask_var_t cpumask;
struct lock_class_key *reader_lock_key;
@@ -937,6 +945,10 @@ static int rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer)
struct list_head *head = cpu_buffer->pages;
struct buffer_page *bpage, *tmp;
+ /* Reset the head page if it exists */
+ if (cpu_buffer->head_page)
+ rb_set_head_page(cpu_buffer);
+
rb_head_page_deactivate(cpu_buffer);
if (RB_WARN_ON(cpu_buffer, head->next->prev != head))
@@ -963,14 +975,10 @@ static int rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer)
return 0;
}
-static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
- unsigned nr_pages)
+static int __rb_allocate_pages(int nr_pages, struct list_head *pages, int cpu)
{
+ int i;
struct buffer_page *bpage, *tmp;
- LIST_HEAD(pages);
- unsigned i;
-
- WARN_ON(!nr_pages);
for (i = 0; i < nr_pages; i++) {
struct page *page;
@@ -981,15 +989,13 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
*/
bpage = kzalloc_node(ALIGN(sizeof(*bpage), cache_line_size()),
GFP_KERNEL | __GFP_NORETRY,
- cpu_to_node(cpu_buffer->cpu));
+ cpu_to_node(cpu));
if (!bpage)
goto free_pages;
- rb_check_bpage(cpu_buffer, bpage);
+ list_add(&bpage->list, pages);
- list_add(&bpage->list, &pages);
-
- page = alloc_pages_node(cpu_to_node(cpu_buffer->cpu),
+ page = alloc_pages_node(cpu_to_node(cpu),
GFP_KERNEL | __GFP_NORETRY, 0);
if (!page)
goto free_pages;
@@ -997,6 +1003,27 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
rb_init_page(bpage->page);
}
+ return 0;
+
+free_pages:
+ list_for_each_entry_safe(bpage, tmp, pages, list) {
+ list_del_init(&bpage->list);
+ free_buffer_page(bpage);
+ }
+
+ return -ENOMEM;
+}
+
+static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
+ unsigned nr_pages)
+{
+ LIST_HEAD(pages);
+
+ WARN_ON(!nr_pages);
+
+ if (__rb_allocate_pages(nr_pages, &pages, cpu_buffer->cpu))
+ return -ENOMEM;
+
/*
* The ring buffer page list is a circular list that does not
* start and end with a list head. All page list items point to
@@ -1005,20 +1032,15 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
cpu_buffer->pages = pages.next;
list_del(&pages);
+ cpu_buffer->nr_pages = nr_pages;
+
rb_check_pages(cpu_buffer);
return 0;
-
- free_pages:
- list_for_each_entry_safe(bpage, tmp, &pages, list) {
- list_del_init(&bpage->list);
- free_buffer_page(bpage);
- }
- return -ENOMEM;
}
static struct ring_buffer_per_cpu *
-rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu)
+rb_allocate_cpu_buffer(struct ring_buffer *buffer, int nr_pages, int cpu)
{
struct ring_buffer_per_cpu *cpu_buffer;
struct buffer_page *bpage;
@@ -1035,6 +1057,8 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu)
raw_spin_lock_init(&cpu_buffer->reader_lock);
lockdep_set_class(&cpu_buffer->reader_lock, buffer->reader_lock_key);
cpu_buffer->lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
+ INIT_WORK(&cpu_buffer->update_pages_work, update_pages_handler);
+ init_completion(&cpu_buffer->update_done);
bpage = kzalloc_node(ALIGN(sizeof(*bpage), cache_line_size()),
GFP_KERNEL, cpu_to_node(cpu));
@@ -1052,7 +1076,7 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu)
INIT_LIST_HEAD(&cpu_buffer->reader_page->list);
- ret = rb_allocate_pages(cpu_buffer, buffer->pages);
+ ret = rb_allocate_pages(cpu_buffer, nr_pages);
if (ret < 0)
goto fail_free_reader;
@@ -1113,7 +1137,7 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
{
struct ring_buffer *buffer;
int bsize;
- int cpu;
+ int cpu, nr_pages;
/* keep it in its own cache line */
buffer = kzalloc(ALIGN(sizeof(*buffer), cache_line_size()),
@@ -1124,14 +1148,14 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
if (!alloc_cpumask_var(&buffer->cpumask, GFP_KERNEL))
goto fail_free_buffer;
- buffer->pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
+ nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
buffer->flags = flags;
buffer->clock = trace_clock_local;
buffer->reader_lock_key = key;
/* need at least two pages */
- if (buffer->pages < 2)
- buffer->pages = 2;
+ if (nr_pages < 2)
+ nr_pages = 2;
/*
* In case of non-hotplug cpu, if the ring-buffer is allocated
@@ -1154,7 +1178,7 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
for_each_buffer_cpu(buffer, cpu) {
buffer->buffers[cpu] =
- rb_allocate_cpu_buffer(buffer, cpu);
+ rb_allocate_cpu_buffer(buffer, nr_pages, cpu);
if (!buffer->buffers[cpu])
goto fail_free_buffers;
}
@@ -1222,58 +1246,222 @@ void ring_buffer_set_clock(struct ring_buffer *buffer,
static void rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer);
-static void
-rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned nr_pages)
+static inline unsigned long rb_page_entries(struct buffer_page *bpage)
{
- struct buffer_page *bpage;
- struct list_head *p;
- unsigned i;
+ return local_read(&bpage->entries) & RB_WRITE_MASK;
+}
+
+static inline unsigned long rb_page_write(struct buffer_page *bpage)
+{
+ return local_read(&bpage->write) & RB_WRITE_MASK;
+}
+
+static int
+rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned int nr_pages)
+{
+ struct list_head *tail_page, *to_remove, *next_page;
+ struct buffer_page *to_remove_page, *tmp_iter_page;
+ struct buffer_page *last_page, *first_page;
+ unsigned int nr_removed;
+ unsigned long head_bit;
+ int page_entries;
+
+ head_bit = 0;
raw_spin_lock_irq(&cpu_buffer->reader_lock);
- rb_head_page_deactivate(cpu_buffer);
+ atomic_inc(&cpu_buffer->record_disabled);
+ /*
+ * We don't race with the readers since we have acquired the reader
+ * lock. We also don't race with writers after disabling recording.
+ * This makes it easy to figure out the first and the last page to be
+ * removed from the list. We unlink all the pages in between including
+ * the first and last pages. This is done in a busy loop so that we
+ * lose the least number of traces.
+ * The pages are freed after we restart recording and unlock readers.
+ */
+ tail_page = &cpu_buffer->tail_page->list;
- for (i = 0; i < nr_pages; i++) {
- if (RB_WARN_ON(cpu_buffer, list_empty(cpu_buffer->pages)))
- goto out;
- p = cpu_buffer->pages->next;
- bpage = list_entry(p, struct buffer_page, list);
- list_del_init(&bpage->list);
- free_buffer_page(bpage);
+ /*
+ * tail page might be on reader page, we remove the next page
+ * from the ring buffer
+ */
+ if (cpu_buffer->tail_page == cpu_buffer->reader_page)
+ tail_page = rb_list_head(tail_page->next);
+ to_remove = tail_page;
+
+ /* start of pages to remove */
+ first_page = list_entry(rb_list_head(to_remove->next),
+ struct buffer_page, list);
+
+ for (nr_removed = 0; nr_removed < nr_pages; nr_removed++) {
+ to_remove = rb_list_head(to_remove)->next;
+ head_bit |= (unsigned long)to_remove & RB_PAGE_HEAD;
}
- if (RB_WARN_ON(cpu_buffer, list_empty(cpu_buffer->pages)))
- goto out;
- rb_reset_cpu(cpu_buffer);
- rb_check_pages(cpu_buffer);
+ next_page = rb_list_head(to_remove)->next;
-out:
+ /*
+ * Now we remove all pages between tail_page and next_page.
+ * Make sure that we have head_bit value preserved for the
+ * next page
+ */
+ tail_page->next = (struct list_head *)((unsigned long)next_page |
+ head_bit);
+ next_page = rb_list_head(next_page);
+ next_page->prev = tail_page;
+
+ /* make sure pages points to a valid page in the ring buffer */
+ cpu_buffer->pages = next_page;
+
+ /* update head page */
+ if (head_bit)
+ cpu_buffer->head_page = list_entry(next_page,
+ struct buffer_page, list);
+
+ /*
+ * change read pointer to make sure any read iterators reset
+ * themselves
+ */
+ cpu_buffer->read = 0;
+
+ /* pages are removed, resume tracing and then free the pages */
+ atomic_dec(&cpu_buffer->record_disabled);
raw_spin_unlock_irq(&cpu_buffer->reader_lock);
+
+ RB_WARN_ON(cpu_buffer, list_empty(cpu_buffer->pages));
+
+ /* last buffer page to remove */
+ last_page = list_entry(rb_list_head(to_remove), struct buffer_page,
+ list);
+ tmp_iter_page = first_page;
+
+ do {
+ to_remove_page = tmp_iter_page;
+ rb_inc_page(cpu_buffer, &tmp_iter_page);
+
+ /* update the counters */
+ page_entries = rb_page_entries(to_remove_page);
+ if (page_entries) {
+ /*
+ * If something was added to this page, it was full
+ * since it is not the tail page. So we deduct the
+ * bytes consumed in ring buffer from here.
+ * No need to update overruns, since this page is
+ * deleted from ring buffer and its entries are
+ * already accounted for.
+ */
+ local_sub(BUF_PAGE_SIZE, &cpu_buffer->entries_bytes);
+ }
+
+ /*
+ * We have already removed references to this list item, just
+ * free up the buffer_page and its page
+ */
+ free_buffer_page(to_remove_page);
+ nr_removed--;
+
+ } while (to_remove_page != last_page);
+
+ RB_WARN_ON(cpu_buffer, nr_removed);
+
+ return nr_removed == 0;
}
-static void
-rb_insert_pages(struct ring_buffer_per_cpu *cpu_buffer,
- struct list_head *pages, unsigned nr_pages)
+static int
+rb_insert_pages(struct ring_buffer_per_cpu *cpu_buffer)
{
- struct buffer_page *bpage;
- struct list_head *p;
- unsigned i;
+ struct list_head *pages = &cpu_buffer->new_pages;
+ int retries, success;
raw_spin_lock_irq(&cpu_buffer->reader_lock);
- rb_head_page_deactivate(cpu_buffer);
+ /*
+ * We are holding the reader lock, so the reader page won't be swapped
+ * in the ring buffer. Now we are racing with the writer trying to
+ * move head page and the tail page.
+ * We are going to adapt the reader page update process where:
+ * 1. We first splice the start and end of list of new pages between
+ * the head page and its previous page.
+ * 2. We cmpxchg the prev_page->next to point from head page to the
+ * start of new pages list.
+ * 3. Finally, we update the head->prev to the end of new list.
+ *
+ * We will try this process 10 times, to make sure that we don't keep
+ * spinning.
+ */
+ retries = 10;
+ success = 0;
+ while (retries--) {
+ struct list_head *head_page, *prev_page, *r;
+ struct list_head *last_page, *first_page;
+ struct list_head *head_page_with_bit;
- for (i = 0; i < nr_pages; i++) {
- if (RB_WARN_ON(cpu_buffer, list_empty(pages)))
- goto out;
- p = pages->next;
- bpage = list_entry(p, struct buffer_page, list);
- list_del_init(&bpage->list);
- list_add_tail(&bpage->list, cpu_buffer->pages);
+ head_page = &rb_set_head_page(cpu_buffer)->list;
+ prev_page = head_page->prev;
+
+ first_page = pages->next;
+ last_page = pages->prev;
+
+ head_page_with_bit = (struct list_head *)
+ ((unsigned long)head_page | RB_PAGE_HEAD);
+
+ last_page->next = head_page_with_bit;
+ first_page->prev = prev_page;
+
+ r = cmpxchg(&prev_page->next, head_page_with_bit, first_page);
+
+ if (r == head_page_with_bit) {
+ /*
+ * yay, we replaced the page pointer to our new list,
+ * now, we just have to update to head page's prev
+ * pointer to point to end of list
+ */
+ head_page->prev = last_page;
+ success = 1;
+ break;
+ }
}
- rb_reset_cpu(cpu_buffer);
- rb_check_pages(cpu_buffer);
-out:
+ if (success)
+ INIT_LIST_HEAD(pages);
+ /*
+ * If we weren't successful in adding in new pages, warn and stop
+ * tracing
+ */
+ RB_WARN_ON(cpu_buffer, !success);
raw_spin_unlock_irq(&cpu_buffer->reader_lock);
+
+ /* free pages if they weren't inserted */
+ if (!success) {
+ struct buffer_page *bpage, *tmp;
+ list_for_each_entry_safe(bpage, tmp, &cpu_buffer->new_pages,
+ list) {
+ list_del_init(&bpage->list);
+ free_buffer_page(bpage);
+ }
+ }
+ return success;
+}
+
+static void rb_update_pages(struct ring_buffer_per_cpu *cpu_buffer)
+{
+ int success;
+
+ if (cpu_buffer->nr_pages_to_update > 0)
+ success = rb_insert_pages(cpu_buffer);
+ else
+ success = rb_remove_pages(cpu_buffer,
+ -cpu_buffer->nr_pages_to_update);
+
+ if (success)
+ cpu_buffer->nr_pages += cpu_buffer->nr_pages_to_update;
+}
+
+static void update_pages_handler(struct work_struct *work)
+{
+ struct ring_buffer_per_cpu *cpu_buffer = container_of(work,
+ struct ring_buffer_per_cpu, update_pages_work);
+ rb_update_pages(cpu_buffer);
+ complete(&cpu_buffer->update_done);
}
/**
@@ -1283,16 +1471,14 @@ out:
*
* Minimum size is 2 * BUF_PAGE_SIZE.
*
- * Returns -1 on failure.
+ * Returns 0 on success and < 0 on failure.
*/
-int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
+int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size,
+ int cpu_id)
{
struct ring_buffer_per_cpu *cpu_buffer;
- unsigned nr_pages, rm_pages, new_pages;
- struct buffer_page *bpage, *tmp;
- unsigned long buffer_size;
- LIST_HEAD(pages);
- int i, cpu;
+ unsigned nr_pages;
+ int cpu, err = 0;
/*
* Always succeed at resizing a non-existent buffer:
@@ -1302,113 +1488,154 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
size = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
size *= BUF_PAGE_SIZE;
- buffer_size = buffer->pages * BUF_PAGE_SIZE;
/* we need a minimum of two pages */
if (size < BUF_PAGE_SIZE * 2)
size = BUF_PAGE_SIZE * 2;
- if (size == buffer_size)
- return size;
-
- atomic_inc(&buffer->record_disabled);
+ nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
- /* Make sure all writers are done with this buffer. */
- synchronize_sched();
+ /*
+ * Don't succeed if resizing is disabled, as a reader might be
+ * manipulating the ring buffer and is expecting a sane state while
+ * this is true.
+ */
+ if (atomic_read(&buffer->resize_disabled))
+ return -EBUSY;
+ /* prevent another thread from changing buffer sizes */
mutex_lock(&buffer->mutex);
- get_online_cpus();
-
- nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
- if (size < buffer_size) {
+ if (cpu_id == RING_BUFFER_ALL_CPUS) {
+ /* calculate the pages to update */
+ for_each_buffer_cpu(buffer, cpu) {
+ cpu_buffer = buffer->buffers[cpu];
- /* easy case, just free pages */
- if (RB_WARN_ON(buffer, nr_pages >= buffer->pages))
- goto out_fail;
+ cpu_buffer->nr_pages_to_update = nr_pages -
+ cpu_buffer->nr_pages;
+ /*
+ * nothing more to do for removing pages or no update
+ */
+ if (cpu_buffer->nr_pages_to_update <= 0)
+ continue;
+ /*
+ * to add pages, make sure all new pages can be
+ * allocated without receiving ENOMEM
+ */
+ INIT_LIST_HEAD(&cpu_buffer->new_pages);
+ if (__rb_allocate_pages(cpu_buffer->nr_pages_to_update,
+ &cpu_buffer->new_pages, cpu)) {
+ /* not enough memory for new pages */
+ err = -ENOMEM;
+ goto out_err;
+ }
+ }
- rm_pages = buffer->pages - nr_pages;
+ get_online_cpus();
+ /*
+ * Fire off all the required work handlers
+ * We can't schedule on offline CPUs, but it's not necessary
+ * since we can change their buffer sizes without any race.
+ */
+ for_each_buffer_cpu(buffer, cpu) {
+ cpu_buffer = buffer->buffers[cpu];
+ if (!cpu_buffer->nr_pages_to_update)
+ continue;
+
+ if (cpu_online(cpu))
+ schedule_work_on(cpu,
+ &cpu_buffer->update_pages_work);
+ else
+ rb_update_pages(cpu_buffer);
+ }
+ /* wait for all the updates to complete */
for_each_buffer_cpu(buffer, cpu) {
cpu_buffer = buffer->buffers[cpu];
- rb_remove_pages(cpu_buffer, rm_pages);
+ if (!cpu_buffer->nr_pages_to_update)
+ continue;
+
+ if (cpu_online(cpu))
+ wait_for_completion(&cpu_buffer->update_done);
+ cpu_buffer->nr_pages_to_update = 0;
}
- goto out;
- }
- /*
- * This is a bit more difficult. We only want to add pages
- * when we can allocate enough for all CPUs. We do this
- * by allocating all the pages and storing them on a local
- * link list. If we succeed in our allocation, then we
- * add these pages to the cpu_buffers. Otherwise we just free
- * them all and return -ENOMEM;
- */
- if (RB_WARN_ON(buffer, nr_pages <= buffer->pages))
- goto out_fail;
+ put_online_cpus();
+ } else {
+ cpu_buffer = buffer->buffers[cpu_id];
- new_pages = nr_pages - buffer->pages;
+ if (nr_pages == cpu_buffer->nr_pages)
+ goto out;
- for_each_buffer_cpu(buffer, cpu) {
- for (i = 0; i < new_pages; i++) {
- struct page *page;
- /*
- * __GFP_NORETRY flag makes sure that the allocation
- * fails gracefully without invoking oom-killer and
- * the system is not destabilized.
- */
- bpage = kzalloc_node(ALIGN(sizeof(*bpage),
- cache_line_size()),
- GFP_KERNEL | __GFP_NORETRY,
- cpu_to_node(cpu));
- if (!bpage)
- goto free_pages;
- list_add(&bpage->list, &pages);
- page = alloc_pages_node(cpu_to_node(cpu),
- GFP_KERNEL | __GFP_NORETRY, 0);
- if (!page)
- goto free_pages;
- bpage->page = page_address(page);
- rb_init_page(bpage->page);
+ cpu_buffer->nr_pages_to_update = nr_pages -
+ cpu_buffer->nr_pages;
+
+ INIT_LIST_HEAD(&cpu_buffer->new_pages);
+ if (cpu_buffer->nr_pages_to_update > 0 &&
+ __rb_allocate_pages(cpu_buffer->nr_pages_to_update,
+ &cpu_buffer->new_pages, cpu_id)) {
+ err = -ENOMEM;
+ goto out_err;
}
- }
- for_each_buffer_cpu(buffer, cpu) {
- cpu_buffer = buffer->buffers[cpu];
- rb_insert_pages(cpu_buffer, &pages, new_pages);
- }
+ get_online_cpus();
- if (RB_WARN_ON(buffer, !list_empty(&pages)))
- goto out_fail;
+ if (cpu_online(cpu_id)) {
+ schedule_work_on(cpu_id,
+ &cpu_buffer->update_pages_work);
+ wait_for_completion(&cpu_buffer->update_done);
+ } else
+ rb_update_pages(cpu_buffer);
+
+ cpu_buffer->nr_pages_to_update = 0;
+ put_online_cpus();
+ }
out:
- buffer->pages = nr_pages;
- put_online_cpus();
+ /*
+ * The ring buffer resize can happen with the ring buffer
+ * enabled, so that the update disturbs the tracing as little
+ * as possible. But if the buffer is disabled, we do not need
+ * to worry about that, and we can take the time to verify
+ * that the buffer is not corrupt.
+ */
+ if (atomic_read(&buffer->record_disabled)) {
+ atomic_inc(&buffer->record_disabled);
+ /*
+ * Even though the buffer was disabled, we must make sure
+ * that it is truly disabled before calling rb_check_pages.
+ * There could have been a race between checking
+ * record_disable and incrementing it.
+ */
+ synchronize_sched();
+ for_each_buffer_cpu(buffer, cpu) {
+ cpu_buffer = buffer->buffers[cpu];
+ rb_check_pages(cpu_buffer);
+ }
+ atomic_dec(&buffer->record_disabled);
+ }
+
mutex_unlock(&buffer->mutex);
+ return size;
- atomic_dec(&buffer->record_disabled);
+ out_err:
+ for_each_buffer_cpu(buffer, cpu) {
+ struct buffer_page *bpage, *tmp;
- return size;
+ cpu_buffer = buffer->buffers[cpu];
+ cpu_buffer->nr_pages_to_update = 0;
- free_pages:
- list_for_each_entry_safe(bpage, tmp, &pages, list) {
- list_del_init(&bpage->list);
- free_buffer_page(bpage);
- }
- put_online_cpus();
- mutex_unlock(&buffer->mutex);
- atomic_dec(&buffer->record_disabled);
- return -ENOMEM;
+ if (list_empty(&cpu_buffer->new_pages))
+ continue;
- /*
- * Something went totally wrong, and we are too paranoid
- * to even clean up the mess.
- */
- out_fail:
- put_online_cpus();
+ list_for_each_entry_safe(bpage, tmp, &cpu_buffer->new_pages,
+ list) {
+ list_del_init(&bpage->list);
+ free_buffer_page(bpage);
+ }
+ }
mutex_unlock(&buffer->mutex);
- atomic_dec(&buffer->record_disabled);
- return -1;
+ return err;
}
EXPORT_SYMBOL_GPL(ring_buffer_resize);
@@ -1447,21 +1674,11 @@ rb_iter_head_event(struct ring_buffer_iter *iter)
return __rb_page_index(iter->head_page, iter->head);
}
-static inline unsigned long rb_page_write(struct buffer_page *bpage)
-{
- return local_read(&bpage->write) & RB_WRITE_MASK;
-}
-
static inline unsigned rb_page_commit(struct buffer_page *bpage)
{
return local_read(&bpage->page->commit);
}
-static inline unsigned long rb_page_entries(struct buffer_page *bpage)
-{
- return local_read(&bpage->entries) & RB_WRITE_MASK;
-}
-
/* Size is determined by what has been committed */
static inline unsigned rb_page_size(struct buffer_page *bpage)
{
@@ -1510,7 +1727,7 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
* assign the commit to the tail.
*/
again:
- max_count = cpu_buffer->buffer->pages * 100;
+ max_count = cpu_buffer->nr_pages * 100;
while (cpu_buffer->commit_page != cpu_buffer->tail_page) {
if (RB_WARN_ON(cpu_buffer, !(--max_count)))
@@ -3486,6 +3703,7 @@ ring_buffer_read_prepare(struct ring_buffer *buffer, int cpu)
iter->cpu_buffer = cpu_buffer;
+ atomic_inc(&buffer->resize_disabled);
atomic_inc(&cpu_buffer->record_disabled);
return iter;
@@ -3548,7 +3766,14 @@ ring_buffer_read_finish(struct ring_buffer_iter *iter)
{
struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer;
+ /*
+ * Ring buffer is disabled from recording, here's a good place
+ * to check the integrity of the ring buffer.
+ */
+ rb_check_pages(cpu_buffer);
+
atomic_dec(&cpu_buffer->record_disabled);
+ atomic_dec(&cpu_buffer->buffer->resize_disabled);
kfree(iter);
}
EXPORT_SYMBOL_GPL(ring_buffer_read_finish);
@@ -3588,9 +3813,18 @@ EXPORT_SYMBOL_GPL(ring_buffer_read);
* ring_buffer_size - return the size of the ring buffer (in bytes)
* @buffer: The ring buffer.
*/
-unsigned long ring_buffer_size(struct ring_buffer *buffer)
+unsigned long ring_buffer_size(struct ring_buffer *buffer, int cpu)
{
- return BUF_PAGE_SIZE * buffer->pages;
+ /*
+ * Earlier, this method returned
+ * BUF_PAGE_SIZE * buffer->nr_pages
+ * Since the nr_pages field is now removed, we have converted this to
+ * return the per cpu buffer value.
+ */
+ if (!cpumask_test_cpu(cpu, buffer->cpumask))
+ return 0;
+
+ return BUF_PAGE_SIZE * buffer->buffers[cpu]->nr_pages;
}
EXPORT_SYMBOL_GPL(ring_buffer_size);
@@ -3611,6 +3845,7 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer)
cpu_buffer->commit_page = cpu_buffer->head_page;
INIT_LIST_HEAD(&cpu_buffer->reader_page->list);
+ INIT_LIST_HEAD(&cpu_buffer->new_pages);
local_set(&cpu_buffer->reader_page->write, 0);
local_set(&cpu_buffer->reader_page->entries, 0);
local_set(&cpu_buffer->reader_page->page->commit, 0);
@@ -3647,8 +3882,12 @@ void ring_buffer_reset_cpu(struct ring_buffer *buffer, int cpu)
if (!cpumask_test_cpu(cpu, buffer->cpumask))
return;
+ atomic_inc(&buffer->resize_disabled);
atomic_inc(&cpu_buffer->record_disabled);
+ /* Make sure all commits have finished */
+ synchronize_sched();
+
raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
if (RB_WARN_ON(cpu_buffer, local_read(&cpu_buffer->committing)))
@@ -3664,6 +3903,7 @@ void ring_buffer_reset_cpu(struct ring_buffer *buffer, int cpu)
raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
atomic_dec(&cpu_buffer->record_disabled);
+ atomic_dec(&buffer->resize_disabled);
}
EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu);
@@ -3765,8 +4005,11 @@ int ring_buffer_swap_cpu(struct ring_buffer *buffer_a,
!cpumask_test_cpu(cpu, buffer_b->cpumask))
goto out;
+ cpu_buffer_a = buffer_a->buffers[cpu];
+ cpu_buffer_b = buffer_b->buffers[cpu];
+
/* At least make sure the two buffers are somewhat the same */
- if (buffer_a->pages != buffer_b->pages)
+ if (cpu_buffer_a->nr_pages != cpu_buffer_b->nr_pages)
goto out;
ret = -EAGAIN;
@@ -3780,9 +4023,6 @@ int ring_buffer_swap_cpu(struct ring_buffer *buffer_a,
if (atomic_read(&buffer_b->record_disabled))
goto out;
- cpu_buffer_a = buffer_a->buffers[cpu];
- cpu_buffer_b = buffer_b->buffers[cpu];
-
if (atomic_read(&cpu_buffer_a->record_disabled))
goto out;
@@ -4071,6 +4311,8 @@ static int rb_cpu_notify(struct notifier_block *self,
struct ring_buffer *buffer =
container_of(self, struct ring_buffer, cpu_notify);
long cpu = (long)hcpu;
+ int cpu_i, nr_pages_same;
+ unsigned int nr_pages;
switch (action) {
case CPU_UP_PREPARE:
@@ -4078,8 +4320,23 @@ static int rb_cpu_notify(struct notifier_block *self,
if (cpumask_test_cpu(cpu, buffer->cpumask))
return NOTIFY_OK;
+ nr_pages = 0;
+ nr_pages_same = 1;
+ /* check if all cpu sizes are same */
+ for_each_buffer_cpu(buffer, cpu_i) {
+ /* fill in the size from first enabled cpu */
+ if (nr_pages == 0)
+ nr_pages = buffer->buffers[cpu_i]->nr_pages;
+ if (nr_pages != buffer->buffers[cpu_i]->nr_pages) {
+ nr_pages_same = 0;
+ break;
+ }
+ }
+ /* allocate minimum pages, user can later expand it */
+ if (!nr_pages_same)
+ nr_pages = 2;
buffer->buffers[cpu] =
- rb_allocate_cpu_buffer(buffer, cpu);
+ rb_allocate_cpu_buffer(buffer, nr_pages, cpu);
if (!buffer->buffers[cpu]) {
WARN(1, "failed to allocate ring buffer on CPU %ld\n",
cpu);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 2a22255c1010..68032c6177db 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -87,18 +87,6 @@ static int tracing_disabled = 1;
DEFINE_PER_CPU(int, ftrace_cpu_disabled);
-static inline void ftrace_disable_cpu(void)
-{
- preempt_disable();
- __this_cpu_inc(ftrace_cpu_disabled);
-}
-
-static inline void ftrace_enable_cpu(void)
-{
- __this_cpu_dec(ftrace_cpu_disabled);
- preempt_enable();
-}
-
cpumask_var_t __read_mostly tracing_buffer_mask;
/*
@@ -629,7 +617,6 @@ ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt)
static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)
{
int len;
- void *ret;
if (s->len <= s->readpos)
return -EBUSY;
@@ -637,9 +624,7 @@ static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)
len = s->len - s->readpos;
if (cnt > len)
cnt = len;
- ret = memcpy(buf, s->buffer + s->readpos, cnt);
- if (!ret)
- return -EFAULT;
+ memcpy(buf, s->buffer + s->readpos, cnt);
s->readpos += cnt;
return cnt;
@@ -751,8 +736,6 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
arch_spin_lock(&ftrace_max_lock);
- ftrace_disable_cpu();
-
ret = ring_buffer_swap_cpu(max_tr.buffer, tr->buffer, cpu);
if (ret == -EBUSY) {
@@ -766,8 +749,6 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
"Failed to swap buffers due to commit in progress\n");
}
- ftrace_enable_cpu();
-
WARN_ON_ONCE(ret && ret != -EAGAIN && ret != -EBUSY);
__update_max_tr(tr, tsk, cpu);
@@ -782,8 +763,6 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
* Register a new plugin tracer.
*/
int register_tracer(struct tracer *type)
-__releases(kernel_lock)
-__acquires(kernel_lock)
{
struct tracer *t;
int ret = 0;
@@ -841,7 +820,8 @@ __acquires(kernel_lock)
/* If we expanded the buffers, make sure the max is expanded too */
if (ring_buffer_expanded && type->use_max_tr)
- ring_buffer_resize(max_tr.buffer, trace_buf_size);
+ ring_buffer_resize(max_tr.buffer, trace_buf_size,
+ RING_BUFFER_ALL_CPUS);
/* the test is responsible for initializing and enabling */
pr_info("Testing tracer %s: ", type->name);
@@ -857,7 +837,8 @@ __acquires(kernel_lock)
/* Shrink the max buffer again */
if (ring_buffer_expanded && type->use_max_tr)
- ring_buffer_resize(max_tr.buffer, 1);
+ ring_buffer_resize(max_tr.buffer, 1,
+ RING_BUFFER_ALL_CPUS);
printk(KERN_CONT "PASSED\n");
}
@@ -917,13 +898,6 @@ out:
mutex_unlock(&trace_types_lock);
}
-static void __tracing_reset(struct ring_buffer *buffer, int cpu)
-{
- ftrace_disable_cpu();
- ring_buffer_reset_cpu(buffer, cpu);
- ftrace_enable_cpu();
-}
-
void tracing_reset(struct trace_array *tr, int cpu)
{
struct ring_buffer *buffer = tr->buffer;
@@ -932,7 +906,7 @@ void tracing_reset(struct trace_array *tr, int cpu)
/* Make sure all commits have finished */
synchronize_sched();
- __tracing_reset(buffer, cpu);
+ ring_buffer_reset_cpu(buffer, cpu);
ring_buffer_record_enable(buffer);
}
@@ -950,7 +924,7 @@ void tracing_reset_online_cpus(struct trace_array *tr)
tr->time_start = ftrace_now(tr->cpu);
for_each_online_cpu(cpu)
- __tracing_reset(buffer, cpu);
+ ring_buffer_reset_cpu(buffer, cpu);
ring_buffer_record_enable(buffer);
}
@@ -1498,25 +1472,119 @@ static void __trace_userstack(struct trace_array *tr, unsigned long flags)
#endif /* CONFIG_STACKTRACE */
+/* created for use with alloc_percpu */
+struct trace_buffer_struct {
+ char buffer[TRACE_BUF_SIZE];
+};
+
+static struct trace_buffer_struct *trace_percpu_buffer;
+static struct trace_buffer_struct *trace_percpu_sirq_buffer;
+static struct trace_buffer_struct *trace_percpu_irq_buffer;
+static struct trace_buffer_struct *trace_percpu_nmi_buffer;
+
+/*
+ * The buffer used is dependent on the context. There is a per cpu
+ * buffer for normal context, softirq contex, hard irq context and
+ * for NMI context. Thise allows for lockless recording.
+ *
+ * Note, if the buffers failed to be allocated, then this returns NULL
+ */
+static char *get_trace_buf(void)
+{
+ struct trace_buffer_struct *percpu_buffer;
+ struct trace_buffer_struct *buffer;
+
+ /*
+ * If we have allocated per cpu buffers, then we do not
+ * need to do any locking.
+ */
+ if (in_nmi())
+ percpu_buffer = trace_percpu_nmi_buffer;
+ else if (in_irq())
+ percpu_buffer = trace_percpu_irq_buffer;
+ else if (in_softirq())
+ percpu_buffer = trace_percpu_sirq_buffer;
+ else
+ percpu_buffer = trace_percpu_buffer;
+
+ if (!percpu_buffer)
+ return NULL;
+
+ buffer = per_cpu_ptr(percpu_buffer, smp_processor_id());
+
+ return buffer->buffer;
+}
+
+static int alloc_percpu_trace_buffer(void)
+{
+ struct trace_buffer_struct *buffers;
+ struct trace_buffer_struct *sirq_buffers;
+ struct trace_buffer_struct *irq_buffers;
+ struct trace_buffer_struct *nmi_buffers;
+
+ buffers = alloc_percpu(struct trace_buffer_struct);
+ if (!buffers)
+ goto err_warn;
+
+ sirq_buffers = alloc_percpu(struct trace_buffer_struct);
+ if (!sirq_buffers)
+ goto err_sirq;
+
+ irq_buffers = alloc_percpu(struct trace_buffer_struct);
+ if (!irq_buffers)
+ goto err_irq;
+
+ nmi_buffers = alloc_percpu(struct trace_buffer_struct);
+ if (!nmi_buffers)
+ goto err_nmi;
+
+ trace_percpu_buffer = buffers;
+ trace_percpu_sirq_buffer = sirq_buffers;
+ trace_percpu_irq_buffer = irq_buffers;
+ trace_percpu_nmi_buffer = nmi_buffers;
+
+ return 0;
+
+ err_nmi:
+ free_percpu(irq_buffers);
+ err_irq:
+ free_percpu(sirq_buffers);
+ err_sirq:
+ free_percpu(buffers);
+ err_warn:
+ WARN(1, "Could not allocate percpu trace_printk buffer");
+ return -ENOMEM;
+}
+
+void trace_printk_init_buffers(void)
+{
+ static int buffers_allocated;
+
+ if (buffers_allocated)
+ return;
+
+ if (alloc_percpu_trace_buffer())
+ return;
+
+ pr_info("ftrace: Allocated trace_printk buffers\n");
+
+ buffers_allocated = 1;
+}
+
/**
* trace_vbprintk - write binary msg to tracing buffer
*
*/
int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
{
- static arch_spinlock_t trace_buf_lock =
- (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
- static u32 trace_buf[TRACE_BUF_SIZE];
-
struct ftrace_event_call *call = &event_bprint;
struct ring_buffer_event *event;
struct ring_buffer *buffer;
struct trace_array *tr = &global_trace;
- struct trace_array_cpu *data;
struct bprint_entry *entry;
unsigned long flags;
- int disable;
- int cpu, len = 0, size, pc;
+ char *tbuffer;
+ int len = 0, size, pc;
if (unlikely(tracing_selftest_running || tracing_disabled))
return 0;
@@ -1526,43 +1594,36 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
pc = preempt_count();
preempt_disable_notrace();
- cpu = raw_smp_processor_id();
- data = tr->data[cpu];
- disable = atomic_inc_return(&data->disabled);
- if (unlikely(disable != 1))
+ tbuffer = get_trace_buf();
+ if (!tbuffer) {
+ len = 0;
goto out;
+ }
- /* Lockdep uses trace_printk for lock tracing */
- local_irq_save(flags);
- arch_spin_lock(&trace_buf_lock);
- len = vbin_printf(trace_buf, TRACE_BUF_SIZE, fmt, args);
+ len = vbin_printf((u32 *)tbuffer, TRACE_BUF_SIZE/sizeof(int), fmt, args);
- if (len > TRACE_BUF_SIZE || len < 0)
- goto out_unlock;
+ if (len > TRACE_BUF_SIZE/sizeof(int) || len < 0)
+ goto out;
+ local_save_flags(flags);
size = sizeof(*entry) + sizeof(u32) * len;
buffer = tr->buffer;
event = trace_buffer_lock_reserve(buffer, TRACE_BPRINT, size,
flags, pc);
if (!event)
- goto out_unlock;
+ goto out;
entry = ring_buffer_event_data(event);
entry->ip = ip;
entry->fmt = fmt;
- memcpy(entry->buf, trace_buf, sizeof(u32) * len);
+ memcpy(entry->buf, tbuffer, sizeof(u32) * len);
if (!filter_check_discard(call, entry, buffer, event)) {
ring_buffer_unlock_commit(buffer, event);
ftrace_trace_stack(buffer, flags, 6, pc);
}
-out_unlock:
- arch_spin_unlock(&trace_buf_lock);
- local_irq_restore(flags);
-
out:
- atomic_dec_return(&data->disabled);
preempt_enable_notrace();
unpause_graph_tracing();
@@ -1588,58 +1649,53 @@ int trace_array_printk(struct trace_array *tr,
int trace_array_vprintk(struct trace_array *tr,
unsigned long ip, const char *fmt, va_list args)
{
- static arch_spinlock_t trace_buf_lock = __ARCH_SPIN_LOCK_UNLOCKED;
- static char trace_buf[TRACE_BUF_SIZE];
-
struct ftrace_event_call *call = &event_print;
struct ring_buffer_event *event;
struct ring_buffer *buffer;
- struct trace_array_cpu *data;
- int cpu, len = 0, size, pc;
+ int len = 0, size, pc;
struct print_entry *entry;
- unsigned long irq_flags;
- int disable;
+ unsigned long flags;
+ char *tbuffer;
if (tracing_disabled || tracing_selftest_running)
return 0;
+ /* Don't pollute graph traces with trace_vprintk internals */
+ pause_graph_tracing();
+
pc = preempt_count();
preempt_disable_notrace();
- cpu = raw_smp_processor_id();
- data = tr->data[cpu];
- disable = atomic_inc_return(&data->disabled);
- if (unlikely(disable != 1))
+
+ tbuffer = get_trace_buf();
+ if (!tbuffer) {
+ len = 0;
goto out;
+ }
- pause_graph_tracing();
- raw_local_irq_save(irq_flags);
- arch_spin_lock(&trace_buf_lock);
- len = vsnprintf(trace_buf, TRACE_BUF_SIZE, fmt, args);
+ len = vsnprintf(tbuffer, TRACE_BUF_SIZE, fmt, args);
+ if (len > TRACE_BUF_SIZE)
+ goto out;
+ local_save_flags(flags);
size = sizeof(*entry) + len + 1;
buffer = tr->buffer;
event = trace_buffer_lock_reserve(buffer, TRACE_PRINT, size,
- irq_flags, pc);
+ flags, pc);
if (!event)
- goto out_unlock;
+ goto out;
entry = ring_buffer_event_data(event);
entry->ip = ip;
- memcpy(&entry->buf, trace_buf, len);
+ memcpy(&entry->buf, tbuffer, len);
entry->buf[len] = '\0';
if (!filter_check_discard(call, entry, buffer, event)) {
ring_buffer_unlock_commit(buffer, event);
- ftrace_trace_stack(buffer, irq_flags, 6, pc);
+ ftrace_trace_stack(buffer, flags, 6, pc);
}
-
- out_unlock:
- arch_spin_unlock(&trace_buf_lock);
- raw_local_irq_restore(irq_flags);
- unpause_graph_tracing();
out:
- atomic_dec_return(&data->disabled);
preempt_enable_notrace();
+ unpause_graph_tracing();
return len;
}
@@ -1652,14 +1708,9 @@ EXPORT_SYMBOL_GPL(trace_vprintk);
static void trace_iterator_increment(struct trace_iterator *iter)
{
- /* Don't allow ftrace to trace into the ring buffers */
- ftrace_disable_cpu();
-
iter->idx++;
if (iter->buffer_iter[iter->cpu])
ring_buffer_read(iter->buffer_iter[iter->cpu], NULL);
-
- ftrace_enable_cpu();
}
static struct trace_entry *
@@ -1669,17 +1720,12 @@ peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts,
struct ring_buffer_event *event;
struct ring_buffer_iter *buf_iter = iter->buffer_iter[cpu];
- /* Don't allow ftrace to trace into the ring buffers */
- ftrace_disable_cpu();
-
if (buf_iter)
event = ring_buffer_iter_peek(buf_iter, ts);
else
event = ring_buffer_peek(iter->tr->buffer, cpu, ts,
lost_events);
- ftrace_enable_cpu();
-
if (event) {
iter->ent_size = ring_buffer_event_length(event);
return ring_buffer_event_data(event);
@@ -1769,11 +1815,8 @@ void *trace_find_next_entry_inc(struct trace_iterator *iter)
static void trace_consume(struct trace_iterator *iter)
{
- /* Don't allow ftrace to trace into the ring buffers */
- ftrace_disable_cpu();
ring_buffer_consume(iter->tr->buffer, iter->cpu, &iter->ts,
&iter->lost_events);
- ftrace_enable_cpu();
}
static void *s_next(struct seq_file *m, void *v, loff_t *pos)
@@ -1862,16 +1905,12 @@ static void *s_start(struct seq_file *m, loff_t *pos)
iter->cpu = 0;
iter->idx = -1;
- ftrace_disable_cpu();
-
if (cpu_file == TRACE_PIPE_ALL_CPU) {
for_each_tracing_cpu(cpu)
tracing_iter_reset(iter, cpu);
} else
tracing_iter_reset(iter, cpu_file);
- ftrace_enable_cpu();
-
iter->leftover = 0;
for (p = iter; p && l < *pos; p = s_next(m, p, &l))
;
@@ -2332,15 +2371,13 @@ static struct trace_iterator *
__tracing_open(struct inode *inode, struct file *file)
{
long cpu_file = (long) inode->i_private;
- void *fail_ret = ERR_PTR(-ENOMEM);
struct trace_iterator *iter;
- struct seq_file *m;
- int cpu, ret;
+ int cpu;
if (tracing_disabled)
return ERR_PTR(-ENODEV);
- iter = kzalloc(sizeof(*iter), GFP_KERNEL);
+ iter = __seq_open_private(file, &tracer_seq_ops, sizeof(*iter));
if (!iter)
return ERR_PTR(-ENOMEM);
@@ -2397,32 +2434,15 @@ __tracing_open(struct inode *inode, struct file *file)
tracing_iter_reset(iter, cpu);
}
- ret = seq_open(file, &tracer_seq_ops);
- if (ret < 0) {
- fail_ret = ERR_PTR(ret);
- goto fail_buffer;
- }
-
- m = file->private_data;
- m->private = iter;
-
mutex_unlock(&trace_types_lock);
return iter;
- fail_buffer:
- for_each_tracing_cpu(cpu) {
- if (iter->buffer_iter[cpu])
- ring_buffer_read_finish(iter->buffer_iter[cpu]);
- }
- free_cpumask_var(iter->started);
- tracing_start();
fail:
mutex_unlock(&trace_types_lock);
kfree(iter->trace);
- kfree(iter);
-
- return fail_ret;
+ seq_release_private(inode, file);
+ return ERR_PTR(-ENOMEM);
}
int tracing_open_generic(struct inode *inode, struct file *filp)
@@ -2458,11 +2478,10 @@ static int tracing_release(struct inode *inode, struct file *file)
tracing_start();
mutex_unlock(&trace_types_lock);
- seq_release(inode, file);
mutex_destroy(&iter->mutex);
free_cpumask_var(iter->started);
kfree(iter->trace);
- kfree(iter);
+ seq_release_private(inode, file);
return 0;
}
@@ -2648,10 +2667,12 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf,
if (cpumask_test_cpu(cpu, tracing_cpumask) &&
!cpumask_test_cpu(cpu, tracing_cpumask_new)) {
atomic_inc(&global_trace.data[cpu]->disabled);
+ ring_buffer_record_disable_cpu(global_trace.buffer, cpu);
}
if (!cpumask_test_cpu(cpu, tracing_cpumask) &&
cpumask_test_cpu(cpu, tracing_cpumask_new)) {
atomic_dec(&global_trace.data[cpu]->disabled);
+ ring_buffer_record_enable_cpu(global_trace.buffer, cpu);
}
}
arch_spin_unlock(&ftrace_max_lock);
@@ -2974,7 +2995,14 @@ int tracer_init(struct tracer *t, struct trace_array *tr)
return t->init(tr);
}
-static int __tracing_resize_ring_buffer(unsigned long size)
+static void set_buffer_entries(struct trace_array *tr, unsigned long val)
+{
+ int cpu;
+ for_each_tracing_cpu(cpu)
+ tr->data[cpu]->entries = val;
+}
+
+static int __tracing_resize_ring_buffer(unsigned long size, int cpu)
{
int ret;
@@ -2985,19 +3013,32 @@ static int __tracing_resize_ring_buffer(unsigned long size)
*/
ring_buffer_expanded = 1;
- ret = ring_buffer_resize(global_trace.buffer, size);
+ ret = ring_buffer_resize(global_trace.buffer, size, cpu);
if (ret < 0)
return ret;
if (!current_trace->use_max_tr)
goto out;
- ret = ring_buffer_resize(max_tr.buffer, size);
+ ret = ring_buffer_resize(max_tr.buffer, size, cpu);
if (ret < 0) {
- int r;
+ int r = 0;
+
+ if (cpu == RING_BUFFER_ALL_CPUS) {
+ int i;
+ for_each_tracing_cpu(i) {
+ r = ring_buffer_resize(global_trace.buffer,
+ global_trace.data[i]->entries,
+ i);
+ if (r < 0)
+ break;
+ }
+ } else {
+ r = ring_buffer_resize(global_trace.buffer,
+ global_trace.data[cpu]->entries,
+ cpu);
+ }
- r = ring_buffer_resize(global_trace.buffer,
- global_trace.entries);
if (r < 0) {
/*
* AARGH! We are left with different
@@ -3019,43 +3060,39 @@ static int __tracing_resize_ring_buffer(unsigned long size)
return ret;
}
- max_tr.entries = size;
+ if (cpu == RING_BUFFER_ALL_CPUS)
+ set_buffer_entries(&max_tr, size);
+ else
+ max_tr.data[cpu]->entries = size;
+
out:
- global_trace.entries = size;
+ if (cpu == RING_BUFFER_ALL_CPUS)
+ set_buffer_entries(&global_trace, size);
+ else
+ global_trace.data[cpu]->entries = size;
return ret;
}
-static ssize_t tracing_resize_ring_buffer(unsigned long size)
+static ssize_t tracing_resize_ring_buffer(unsigned long size, int cpu_id)
{
- int cpu, ret = size;
+ int ret = size;
mutex_lock(&trace_types_lock);
- tracing_stop();
-
- /* disable all cpu buffers */
- for_each_tracing_cpu(cpu) {
- if (global_trace.data[cpu])
- atomic_inc(&global_trace.data[cpu]->disabled);
- if (max_tr.data[cpu])
- atomic_inc(&max_tr.data[cpu]->disabled);
+ if (cpu_id != RING_BUFFER_ALL_CPUS) {
+ /* make sure, this cpu is enabled in the mask */
+ if (!cpumask_test_cpu(cpu_id, tracing_buffer_mask)) {
+ ret = -EINVAL;
+ goto out;
+ }
}
- if (size != global_trace.entries)
- ret = __tracing_resize_ring_buffer(size);
-
+ ret = __tracing_resize_ring_buffer(size, cpu_id);
if (ret < 0)
ret = -ENOMEM;
- for_each_tracing_cpu(cpu) {
- if (global_trace.data[cpu])
- atomic_dec(&global_trace.data[cpu]->disabled);
- if (max_tr.data[cpu])
- atomic_dec(&max_tr.data[cpu]->disabled);
- }
-
- tracing_start();
+out:
mutex_unlock(&trace_types_lock);
return ret;
@@ -3078,7 +3115,8 @@ int tracing_update_buffers(void)
mutex_lock(&trace_types_lock);
if (!ring_buffer_expanded)
- ret = __tracing_resize_ring_buffer(trace_buf_size);
+ ret = __tracing_resize_ring_buffer(trace_buf_size,
+ RING_BUFFER_ALL_CPUS);
mutex_unlock(&trace_types_lock);
return ret;
@@ -3102,7 +3140,8 @@ static int tracing_set_tracer(const char *buf)
mutex_lock(&trace_types_lock);
if (!ring_buffer_expanded) {
- ret = __tracing_resize_ring_buffer(trace_buf_size);
+ ret = __tracing_resize_ring_buffer(trace_buf_size,
+ RING_BUFFER_ALL_CPUS);
if (ret < 0)
goto out;
ret = 0;
@@ -3128,8 +3167,8 @@ static int tracing_set_tracer(const char *buf)
* The max_tr ring buffer has some state (e.g. ring->clock) and
* we want preserve it.
*/
- ring_buffer_resize(max_tr.buffer, 1);
- max_tr.entries = 1;
+ ring_buffer_resize(max_tr.buffer, 1, RING_BUFFER_ALL_CPUS);
+ set_buffer_entries(&max_tr, 1);
}
destroy_trace_option_files(topts);
@@ -3137,10 +3176,17 @@ static int tracing_set_tracer(const char *buf)
topts = create_trace_option_files(current_trace);
if (current_trace->use_max_tr) {
- ret = ring_buffer_resize(max_tr.buffer, global_trace.entries);
- if (ret < 0)
- goto out;
- max_tr.entries = global_trace.entries;
+ int cpu;
+ /* we need to make per cpu buffer sizes equivalent */
+ for_each_tracing_cpu(cpu) {
+ ret = ring_buffer_resize(max_tr.buffer,
+ global_trace.data[cpu]->entries,
+ cpu);
+ if (ret < 0)
+ goto out;
+ max_tr.data[cpu]->entries =
+ global_trace.data[cpu]->entries;
+ }
}
if (t->init) {
@@ -3642,30 +3688,82 @@ out_err:
goto out;
}
+struct ftrace_entries_info {
+ struct trace_array *tr;
+ int cpu;
+};
+
+static int tracing_entries_open(struct inode *inode, struct file *filp)
+{
+ struct ftrace_entries_info *info;
+
+ if (tracing_disabled)
+ return -ENODEV;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->tr = &global_trace;
+ info->cpu = (unsigned long)inode->i_private;
+
+ filp->private_data = info;
+
+ return 0;
+}
+
static ssize_t
tracing_entries_read(struct file *filp, char __user *ubuf,
size_t cnt, loff_t *ppos)
{
- struct trace_array *tr = filp->private_data;
- char buf[96];
- int r;
+ struct ftrace_entries_info *info = filp->private_data;
+ struct trace_array *tr = info->tr;
+ char buf[64];
+ int r = 0;
+ ssize_t ret;
mutex_lock(&trace_types_lock);
- if (!ring_buffer_expanded)
- r = sprintf(buf, "%lu (expanded: %lu)\n",
- tr->entries >> 10,
- trace_buf_size >> 10);
- else
- r = sprintf(buf, "%lu\n", tr->entries >> 10);
+
+ if (info->cpu == RING_BUFFER_ALL_CPUS) {
+ int cpu, buf_size_same;
+ unsigned long size;
+
+ size = 0;
+ buf_size_same = 1;
+ /* check if all cpu sizes are same */
+ for_each_tracing_cpu(cpu) {
+ /* fill in the size from first enabled cpu */
+ if (size == 0)
+ size = tr->data[cpu]->entries;
+ if (size != tr->data[cpu]->entries) {
+ buf_size_same = 0;
+ break;
+ }
+ }
+
+ if (buf_size_same) {
+ if (!ring_buffer_expanded)
+ r = sprintf(buf, "%lu (expanded: %lu)\n",
+ size >> 10,
+ trace_buf_size >> 10);
+ else
+ r = sprintf(buf, "%lu\n", size >> 10);
+ } else
+ r = sprintf(buf, "X\n");
+ } else
+ r = sprintf(buf, "%lu\n", tr->data[info->cpu]->entries >> 10);
+
mutex_unlock(&trace_types_lock);
- return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+ ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+ return ret;
}
static ssize_t
tracing_entries_write(struct file *filp, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{
+ struct ftrace_entries_info *info = filp->private_data;
unsigned long val;
int ret;
@@ -3680,7 +3778,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
/* value is in KB */
val <<= 10;
- ret = tracing_resize_ring_buffer(val);
+ ret = tracing_resize_ring_buffer(val, info->cpu);
if (ret < 0)
return ret;
@@ -3689,6 +3787,16 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
return cnt;
}
+static int
+tracing_entries_release(struct inode *inode, struct file *filp)
+{
+ struct ftrace_entries_info *info = filp->private_data;
+
+ kfree(info);
+
+ return 0;
+}
+
static ssize_t
tracing_total_entries_read(struct file *filp, char __user *ubuf,
size_t cnt, loff_t *ppos)
@@ -3700,7 +3808,7 @@ tracing_total_entries_read(struct file *filp, char __user *ubuf,
mutex_lock(&trace_types_lock);
for_each_tracing_cpu(cpu) {
- size += tr->entries >> 10;
+ size += tr->data[cpu]->entries >> 10;
if (!ring_buffer_expanded)
expanded_size += trace_buf_size >> 10;
}
@@ -3734,7 +3842,7 @@ tracing_free_buffer_release(struct inode *inode, struct file *filp)
if (trace_flags & TRACE_ITER_STOP_ON_FREE)
tracing_off();
/* resize the ring buffer to 0 */
- tracing_resize_ring_buffer(0);
+ tracing_resize_ring_buffer(0, RING_BUFFER_ALL_CPUS);
return 0;
}
@@ -3749,14 +3857,14 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
struct print_entry *entry;
unsigned long irq_flags;
struct page *pages[2];
+ void *map_page[2];
int nr_pages = 1;
ssize_t written;
- void *page1;
- void *page2;
int offset;
int size;
int len;
int ret;
+ int i;
if (tracing_disabled)
return -EINVAL;
@@ -3795,9 +3903,8 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
goto out;
}
- page1 = kmap_atomic(pages[0]);
- if (nr_pages == 2)
- page2 = kmap_atomic(pages[1]);
+ for (i = 0; i < nr_pages; i++)
+ map_page[i] = kmap_atomic(pages[i]);
local_save_flags(irq_flags);
size = sizeof(*entry) + cnt + 2; /* possible \n added */
@@ -3815,10 +3922,10 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
if (nr_pages == 2) {
len = PAGE_SIZE - offset;
- memcpy(&entry->buf, page1 + offset, len);
- memcpy(&entry->buf[len], page2, cnt - len);
+ memcpy(&entry->buf, map_page[0] + offset, len);
+ memcpy(&entry->buf[len], map_page[1], cnt - len);
} else
- memcpy(&entry->buf, page1 + offset, cnt);
+ memcpy(&entry->buf, map_page[0] + offset, cnt);
if (entry->buf[cnt - 1] != '\n') {
entry->buf[cnt] = '\n';
@@ -3833,11 +3940,10 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
*fpos += written;
out_unlock:
- if (nr_pages == 2)
- kunmap_atomic(page2);
- kunmap_atomic(page1);
- while (nr_pages > 0)
- put_page(pages[--nr_pages]);
+ for (i = 0; i < nr_pages; i++){
+ kunmap_atomic(map_page[i]);
+ put_page(pages[i]);
+ }
out:
return written;
}
@@ -3933,9 +4039,10 @@ static const struct file_operations tracing_pipe_fops = {
};
static const struct file_operations tracing_entries_fops = {
- .open = tracing_open_generic,
+ .open = tracing_entries_open,
.read = tracing_entries_read,
.write = tracing_entries_write,
+ .release = tracing_entries_release,
.llseek = generic_file_llseek,
};
@@ -4367,6 +4474,9 @@ static void tracing_init_debugfs_percpu(long cpu)
struct dentry *d_cpu;
char cpu_dir[30]; /* 30 characters should be more than enough */
+ if (!d_percpu)
+ return;
+
snprintf(cpu_dir, 30, "cpu%ld", cpu);
d_cpu = debugfs_create_dir(cpu_dir, d_percpu);
if (!d_cpu) {
@@ -4387,6 +4497,9 @@ static void tracing_init_debugfs_percpu(long cpu)
trace_create_file("stats", 0444, d_cpu,
(void *) cpu, &tracing_stats_fops);
+
+ trace_create_file("buffer_size_kb", 0444, d_cpu,
+ (void *) cpu, &tracing_entries_fops);
}
#ifdef CONFIG_FTRACE_SELFTEST
@@ -4718,7 +4831,7 @@ static __init int tracer_init_debugfs(void)
(void *) TRACE_PIPE_ALL_CPU, &tracing_pipe_fops);
trace_create_file("buffer_size_kb", 0644, d_tracer,
- &global_trace, &tracing_entries_fops);
+ (void *) RING_BUFFER_ALL_CPUS, &tracing_entries_fops);
trace_create_file("buffer_total_size_kb", 0444, d_tracer,
&global_trace, &tracing_total_entries_fops);
@@ -4957,6 +5070,10 @@ __init static int tracer_alloc_buffers(void)
if (!alloc_cpumask_var(&tracing_cpumask, GFP_KERNEL))
goto out_free_buffer_mask;
+ /* Only allocate trace_printk buffers if a trace_printk exists */
+ if (__stop___trace_bprintk_fmt != __start___trace_bprintk_fmt)
+ trace_printk_init_buffers();
+
/* To save memory, keep the ring buffer size to its minimum */
if (ring_buffer_expanded)
ring_buf_size = trace_buf_size;
@@ -4975,7 +5092,6 @@ __init static int tracer_alloc_buffers(void)
WARN_ON(1);
goto out_free_cpumask;
}
- global_trace.entries = ring_buffer_size(global_trace.buffer);
if (global_trace.buffer_disabled)
tracing_off();
@@ -4988,7 +5104,6 @@ __init static int tracer_alloc_buffers(void)
ring_buffer_free(global_trace.buffer);
goto out_free_cpumask;
}
- max_tr.entries = 1;
#endif
/* Allocate the first page for all buffers */
@@ -4997,6 +5112,12 @@ __init static int tracer_alloc_buffers(void)
max_tr.data[i] = &per_cpu(max_tr_data, i);
}
+ set_buffer_entries(&global_trace,
+ ring_buffer_size(global_trace.buffer, 0));
+#ifdef CONFIG_TRACER_MAX_TRACE
+ set_buffer_entries(&max_tr, 1);
+#endif
+
trace_init_cmdlines();
register_tracer(&nop_trace);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index f95d65da6db8..6c6f7933eede 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -131,6 +131,7 @@ struct trace_array_cpu {
atomic_t disabled;
void *buffer_page; /* ring buffer spare */
+ unsigned long entries;
unsigned long saved_latency;
unsigned long critical_start;
unsigned long critical_end;
@@ -152,7 +153,6 @@ struct trace_array_cpu {
*/
struct trace_array {
struct ring_buffer *buffer;
- unsigned long entries;
int cpu;
int buffer_disabled;
cycle_t time_start;
@@ -826,6 +826,8 @@ extern struct list_head ftrace_events;
extern const char *__start___trace_bprintk_fmt[];
extern const char *__stop___trace_bprintk_fmt[];
+void trace_printk_init_buffers(void);
+
#undef FTRACE_ENTRY
#define FTRACE_ENTRY(call, struct_name, id, tstruct, print, filter) \
extern struct ftrace_event_call \
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 079a93ae8a9d..29111da1d100 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -294,6 +294,9 @@ static int __ftrace_set_clr_event(const char *match, const char *sub,
if (!call->name || !call->class || !call->class->reg)
continue;
+ if (call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)
+ continue;
+
if (match &&
strcmp(match, call->name) != 0 &&
strcmp(match, call->class->system) != 0)
@@ -1164,7 +1167,7 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
return -1;
}
- if (call->class->reg)
+ if (call->class->reg && !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE))
trace_create_file("enable", 0644, call->dir, call,
enable);
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c
index 3dd15e8bc856..e039906b037d 100644
--- a/kernel/trace/trace_export.c
+++ b/kernel/trace/trace_export.c
@@ -180,6 +180,7 @@ struct ftrace_event_call __used event_##call = { \
.event.type = etype, \
.class = &event_class_ftrace_##call, \
.print_fmt = print, \
+ .flags = TRACE_EVENT_FL_IGNORE_ENABLE, \
}; \
struct ftrace_event_call __used \
__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call;
diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c
index 6fd4ffd042f9..a9077c1b4ad3 100644
--- a/kernel/trace/trace_printk.c
+++ b/kernel/trace/trace_printk.c
@@ -51,6 +51,10 @@ void hold_module_trace_bprintk_format(const char **start, const char **end)
const char **iter;
char *fmt;
+ /* allocate the trace_printk per cpu buffers */
+ if (start != end)
+ trace_printk_init_buffers();
+
mutex_lock(&btrace_mutex);
for (iter = start; iter < end; iter++) {
struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter);
diff --git a/kernel/trace/trace_workqueue.c b/kernel/trace/trace_workqueue.c
deleted file mode 100644
index 209b379a4721..000000000000
--- a/kernel/trace/trace_workqueue.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Workqueue statistical tracer.
- *
- * Copyright (C) 2008 Frederic Weisbecker <fweisbec@gmail.com>
- *
- */
-
-
-#include <trace/events/workqueue.h>
-#include <linux/list.h>
-#include <linux/percpu.h>
-#include <linux/slab.h>
-#include <linux/kref.h>
-#include "trace_stat.h"
-#include "trace.h"
-
-
-/* A cpu workqueue thread */
-struct cpu_workqueue_stats {
- struct list_head list;
- struct kref kref;
- int cpu;
- pid_t pid;
-/* Can be inserted from interrupt or user context, need to be atomic */
- atomic_t inserted;
-/*
- * Don't need to be atomic, works are serialized in a single workqueue thread
- * on a single CPU.
- */
- unsigned int executed;
-};
-
-/* List of workqueue threads on one cpu */
-struct workqueue_global_stats {
- struct list_head list;
- spinlock_t lock;
-};
-
-/* Don't need a global lock because allocated before the workqueues, and
- * never freed.
- */
-static DEFINE_PER_CPU(struct workqueue_global_stats, all_workqueue_stat);
-#define workqueue_cpu_stat(cpu) (&per_cpu(all_workqueue_stat, cpu))
-
-static void cpu_workqueue_stat_free(struct kref *kref)
-{
- kfree(container_of(kref, struct cpu_workqueue_stats, kref));
-}
-
-/* Insertion of a work */
-static void
-probe_workqueue_insertion(void *ignore,
- struct task_struct *wq_thread,
- struct work_struct *work)
-{
- int cpu = cpumask_first(&wq_thread->cpus_allowed);
- struct cpu_workqueue_stats *node;
- unsigned long flags;
-
- spin_lock_irqsave(&workqueue_cpu_stat(cpu)->lock, flags);
- list_for_each_entry(node, &workqueue_cpu_stat(cpu)->list, list) {
- if (node->pid == wq_thread->pid) {
- atomic_inc(&node->inserted);
- goto found;
- }
- }
- pr_debug("trace_workqueue: entry not found\n");
-found:
- spin_unlock_irqrestore(&workqueue_cpu_stat(cpu)->lock, flags);
-}
-
-/* Execution of a work */
-static void
-probe_workqueue_execution(void *ignore,
- struct task_struct *wq_thread,
- struct work_struct *work)
-{
- int cpu = cpumask_first(&wq_thread->cpus_allowed);
- struct cpu_workqueue_stats *node;
- unsigned long flags;
-
- spin_lock_irqsave(&workqueue_cpu_stat(cpu)->lock, flags);
- list_for_each_entry(node, &workqueue_cpu_stat(cpu)->list, list) {
- if (node->pid == wq_thread->pid) {
- node->executed++;
- goto found;
- }
- }
- pr_debug("trace_workqueue: entry not found\n");
-found:
- spin_unlock_irqrestore(&workqueue_cpu_stat(cpu)->lock, flags);
-}
-
-/* Creation of a cpu workqueue thread */
-static void probe_workqueue_creation(void *ignore,
- struct task_struct *wq_thread, int cpu)
-{
- struct cpu_workqueue_stats *cws;
- unsigned long flags;
-
- WARN_ON(cpu < 0);
-
- /* Workqueues are sometimes created in atomic context */
- cws = kzalloc(sizeof(struct cpu_workqueue_stats), GFP_ATOMIC);
- if (!cws) {
- pr_warning("trace_workqueue: not enough memory\n");
- return;
- }
- INIT_LIST_HEAD(&cws->list);
- kref_init(&cws->kref);
- cws->cpu = cpu;
- cws->pid = wq_thread->pid;
-
- spin_lock_irqsave(&workqueue_cpu_stat(cpu)->lock, flags);
- list_add_tail(&cws->list, &workqueue_cpu_stat(cpu)->list);
- spin_unlock_irqrestore(&workqueue_cpu_stat(cpu)->lock, flags);
-}
-
-/* Destruction of a cpu workqueue thread */
-static void
-probe_workqueue_destruction(void *ignore, struct task_struct *wq_thread)
-{
- /* Workqueue only execute on one cpu */
- int cpu = cpumask_first(&wq_thread->cpus_allowed);
- struct cpu_workqueue_stats *node, *next;
- unsigned long flags;
-
- spin_lock_irqsave(&workqueue_cpu_stat(cpu)->lock, flags);
- list_for_each_entry_safe(node, next, &workqueue_cpu_stat(cpu)->list,
- list) {
- if (node->pid == wq_thread->pid) {
- list_del(&node->list);
- kref_put(&node->kref, cpu_workqueue_stat_free);
- goto found;
- }
- }
-
- pr_debug("trace_workqueue: don't find workqueue to destroy\n");
-found:
- spin_unlock_irqrestore(&workqueue_cpu_stat(cpu)->lock, flags);
-
-}
-
-static struct cpu_workqueue_stats *workqueue_stat_start_cpu(int cpu)
-{
- unsigned long flags;
- struct cpu_workqueue_stats *ret = NULL;
-
-
- spin_lock_irqsave(&workqueue_cpu_stat(cpu)->lock, flags);
-
- if (!list_empty(&workqueue_cpu_stat(cpu)->list)) {
- ret = list_entry(workqueue_cpu_stat(cpu)->list.next,
- struct cpu_workqueue_stats, list);
- kref_get(&ret->kref);
- }
-
- spin_unlock_irqrestore(&workqueue_cpu_stat(cpu)->lock, flags);
-
- return ret;
-}
-
-static void *workqueue_stat_start(struct tracer_stat *trace)
-{
- int cpu;
- void *ret = NULL;
-
- for_each_possible_cpu(cpu) {
- ret = workqueue_stat_start_cpu(cpu);
- if (ret)
- return ret;
- }
- return NULL;
-}
-
-static void *workqueue_stat_next(void *prev, int idx)
-{
- struct cpu_workqueue_stats *prev_cws = prev;
- struct cpu_workqueue_stats *ret;
- int cpu = prev_cws->cpu;
- unsigned long flags;
-
- spin_lock_irqsave(&workqueue_cpu_stat(cpu)->lock, flags);
- if (list_is_last(&prev_cws->list, &workqueue_cpu_stat(cpu)->list)) {
- spin_unlock_irqrestore(&workqueue_cpu_stat(cpu)->lock, flags);
- do {
- cpu = cpumask_next(cpu, cpu_possible_mask);
- if (cpu >= nr_cpu_ids)
- return NULL;
- } while (!(ret = workqueue_stat_start_cpu(cpu)));
- return ret;
- } else {
- ret = list_entry(prev_cws->list.next,
- struct cpu_workqueue_stats, list);
- kref_get(&ret->kref);
- }
- spin_unlock_irqrestore(&workqueue_cpu_stat(cpu)->lock, flags);
-
- return ret;
-}
-
-static int workqueue_stat_show(struct seq_file *s, void *p)
-{
- struct cpu_workqueue_stats *cws = p;
- struct pid *pid;
- struct task_struct *tsk;
-
- pid = find_get_pid(cws->pid);
- if (pid) {
- tsk = get_pid_task(pid, PIDTYPE_PID);
- if (tsk) {
- seq_printf(s, "%3d %6d %6u %s\n", cws->cpu,
- atomic_read(&cws->inserted), cws->executed,
- tsk->comm);
- put_task_struct(tsk);
- }
- put_pid(pid);
- }
-
- return 0;
-}
-
-static void workqueue_stat_release(void *stat)
-{
- struct cpu_workqueue_stats *node = stat;
-
- kref_put(&node->kref, cpu_workqueue_stat_free);
-}
-
-static int workqueue_stat_headers(struct seq_file *s)
-{
- seq_printf(s, "# CPU INSERTED EXECUTED NAME\n");
- seq_printf(s, "# | | | |\n");
- return 0;
-}
-
-struct tracer_stat workqueue_stats __read_mostly = {
- .name = "workqueues",
- .stat_start = workqueue_stat_start,
- .stat_next = workqueue_stat_next,
- .stat_show = workqueue_stat_show,
- .stat_release = workqueue_stat_release,
- .stat_headers = workqueue_stat_headers
-};
-
-
-int __init stat_workqueue_init(void)
-{
- if (register_stat_tracer(&workqueue_stats)) {
- pr_warning("Unable to register workqueue stat tracer\n");
- return 1;
- }
-
- return 0;
-}
-fs_initcall(stat_workqueue_init);
-
-/*
- * Workqueues are created very early, just after pre-smp initcalls.
- * So we must register our tracepoints at this stage.
- */
-int __init trace_workqueue_early_init(void)
-{
- int ret, cpu;
-
- for_each_possible_cpu(cpu) {
- spin_lock_init(&workqueue_cpu_stat(cpu)->lock);
- INIT_LIST_HEAD(&workqueue_cpu_stat(cpu)->list);
- }
-
- ret = register_trace_workqueue_insertion(probe_workqueue_insertion, NULL);
- if (ret)
- goto out;
-
- ret = register_trace_workqueue_execution(probe_workqueue_execution, NULL);
- if (ret)
- goto no_insertion;
-
- ret = register_trace_workqueue_creation(probe_workqueue_creation, NULL);
- if (ret)
- goto no_execution;
-
- ret = register_trace_workqueue_destruction(probe_workqueue_destruction, NULL);
- if (ret)
- goto no_creation;
-
- return 0;
-
-no_creation:
- unregister_trace_workqueue_creation(probe_workqueue_creation, NULL);
-no_execution:
- unregister_trace_workqueue_execution(probe_workqueue_execution, NULL);
-no_insertion:
- unregister_trace_workqueue_insertion(probe_workqueue_insertion, NULL);
-out:
- pr_warning("trace_workqueue: unable to trace workqueues\n");
-
- return 1;
-}
-early_initcall(trace_workqueue_early_init);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 5abf42f63c08..9a3128dc67df 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1032,7 +1032,10 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,
cwq = get_cwq(gcwq->cpu, wq);
trace_workqueue_queue_work(cpu, cwq, work);
- BUG_ON(!list_empty(&work->entry));
+ if (WARN_ON(!list_empty(&work->entry))) {
+ spin_unlock_irqrestore(&gcwq->lock, flags);
+ return;
+ }
cwq->nr_in_flight[cwq->work_color]++;
work_flags = work_color_to_flags(cwq->work_color);
@@ -1210,8 +1213,13 @@ static void worker_enter_idle(struct worker *worker)
} else
wake_up_all(&gcwq->trustee_wait);
- /* sanity check nr_running */
- WARN_ON_ONCE(gcwq->nr_workers == gcwq->nr_idle &&
+ /*
+ * Sanity check nr_running. Because trustee releases gcwq->lock
+ * between setting %WORKER_ROGUE and zapping nr_running, the
+ * warning may trigger spuriously. Check iff trustee is idle.
+ */
+ WARN_ON_ONCE(gcwq->trustee_state == TRUSTEE_DONE &&
+ gcwq->nr_workers == gcwq->nr_idle &&
atomic_read(get_gcwq_nr_running(gcwq->cpu)));
}
@@ -1810,7 +1818,9 @@ __acquires(&gcwq->lock)
* lock freed" warnings as well as problems when looking into
* work->lockdep_map, make a copy and use that here.
*/
- struct lockdep_map lockdep_map = work->lockdep_map;
+ struct lockdep_map lockdep_map;
+
+ lockdep_copy_map(&lockdep_map, &work->lockdep_map);
#endif
/*
* A single work shouldn't be executed concurrently by
@@ -2506,6 +2516,9 @@ bool flush_work(struct work_struct *work)
{
struct wq_barrier barr;
+ lock_map_acquire(&work->lockdep_map);
+ lock_map_release(&work->lockdep_map);
+
if (start_flush_work(work, &barr, true)) {
wait_for_completion(&barr.done);
destroy_work_on_stack(&barr.work);
diff --git a/lib/Kconfig b/lib/Kconfig
index 4a8aba2e5cc0..0e25c03939e3 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -353,6 +353,14 @@ config CORDIC
This option provides an implementation of the CORDIC algorithm;
calculations are in fixed point. Module will be called cordic.
+config DDR
+ bool "JEDEC DDR data"
+ help
+ Data from JEDEC specs for DDR SDRAM memories,
+ particularly the AC timing parameters and addressing
+ information. This data is useful for drivers handling
+ DDR SDRAM controllers.
+
config MPILIB
tristate
select CLZ_TAB
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 6777153f18f3..a42d3ae39648 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -3,12 +3,16 @@ config PRINTK_TIME
bool "Show timing information on printks"
depends on PRINTK
help
- Selecting this option causes timing information to be
- included in printk output. This allows you to measure
- the interval between kernel operations, including bootup
- operations. This is useful for identifying long delays
- in kernel startup. Or add printk.time=1 at boot-time.
- See Documentation/kernel-parameters.txt
+ Selecting this option causes time stamps of the printk()
+ messages to be added to the output of the syslog() system
+ call and at the console.
+
+ The timestamp is always recorded internally, and exported
+ to /dev/kmsg. This flag just specifies if the timestamp should
+ be included, not that the timestamp is recorded.
+
+ The behavior is also controlled by the kernel command line
+ parameter printk.time=1. See Documentation/kernel-parameters.txt
config DEFAULT_MESSAGE_LOGLEVEL
int "Default message log level (1-7)"
@@ -70,6 +74,15 @@ config STRIP_ASM_SYMS
that look like '.Lxxx') so they don't pollute the output of
get_wchan() and suchlike.
+config READABLE_ASM
+ bool "Generate readable assembler code"
+ depends on DEBUG_KERNEL
+ help
+ Disable some compiler optimizations that tend to generate human unreadable
+ assembler output. This may make the kernel slightly slower, but it helps
+ to keep kernel developers who have to stare a lot at assembler listings
+ sane.
+
config UNUSED_SYMBOLS
bool "Enable unused/obsolete exported symbols"
default y if X86
@@ -1205,8 +1218,13 @@ config DYNAMIC_DEBUG
otherwise be available at runtime. These messages can then be
enabled/disabled based on various levels of scope - per source file,
function, module, format string, and line number. This mechanism
- implicitly enables all pr_debug() and dev_dbg() calls. The impact of
- this compile option is a larger kernel text size of about 2%.
+ implicitly compiles in all pr_debug() and dev_dbg() calls, which
+ enlarges the kernel text size by about 2%.
+
+ If a source file is compiled with DEBUG flag set, any
+ pr_debug() calls in it are enabled by default, but can be
+ disabled at runtime as below. Note that DEBUG flag is
+ turned on by many CONFIG_*DEBUG* options.
Usage:
@@ -1223,16 +1241,16 @@ config DYNAMIC_DEBUG
lineno : line number of the debug statement
module : module that contains the debug statement
function : function that contains the debug statement
- flags : 'p' means the line is turned 'on' for printing
+ flags : '=p' means the line is turned 'on' for printing
format : the format used for the debug statement
From a live system:
nullarbor:~ # cat <debugfs>/dynamic_debug/control
# filename:lineno [module]function flags format
- fs/aio.c:222 [aio]__put_ioctx - "__put_ioctx:\040freeing\040%p\012"
- fs/aio.c:248 [aio]ioctx_alloc - "ENOMEM:\040nr_events\040too\040high\012"
- fs/aio.c:1770 [aio]sys_io_cancel - "calling\040cancel\012"
+ fs/aio.c:222 [aio]__put_ioctx =_ "__put_ioctx:\040freeing\040%p\012"
+ fs/aio.c:248 [aio]ioctx_alloc =_ "ENOMEM:\040nr_events\040too\040high\012"
+ fs/aio.c:1770 [aio]sys_io_cancel =_ "calling\040cancel\012"
Example usage:
diff --git a/lib/Makefile b/lib/Makefile
index 18515f0267c4..74290c9e2864 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -123,6 +123,8 @@ obj-$(CONFIG_SIGNATURE) += digsig.o
obj-$(CONFIG_CLZ_TAB) += clz_tab.o
+obj-$(CONFIG_DDR) += jedec_ddr_data.o
+
hostprogs-y := gen_crc32table
clean-files := crc32table.h
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
index 0ab9ae8057f0..d11808ca4bc4 100644
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -79,30 +79,29 @@ static const char *obj_states[ODEBUG_STATE_MAX] = {
[ODEBUG_STATE_NOTAVAILABLE] = "not available",
};
-static int fill_pool(void)
+static void fill_pool(void)
{
gfp_t gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
struct debug_obj *new;
unsigned long flags;
if (likely(obj_pool_free >= ODEBUG_POOL_MIN_LEVEL))
- return obj_pool_free;
+ return;
if (unlikely(!obj_cache))
- return obj_pool_free;
+ return;
while (obj_pool_free < ODEBUG_POOL_MIN_LEVEL) {
new = kmem_cache_zalloc(obj_cache, gfp);
if (!new)
- return obj_pool_free;
+ return;
raw_spin_lock_irqsave(&pool_lock, flags);
hlist_add_head(&new->node, &obj_pool);
obj_pool_free++;
raw_spin_unlock_irqrestore(&pool_lock, flags);
}
- return obj_pool_free;
}
/*
@@ -1052,10 +1051,10 @@ static int __init debug_objects_replace_static_objects(void)
cnt++;
}
}
+ local_irq_enable();
printk(KERN_DEBUG "ODEBUG: %d of %d active objects replaced\n", cnt,
obj_pool_used);
- local_irq_enable();
return 0;
free:
hlist_for_each_entry_safe(obj, node, tmp, &objects, node) {
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 310c753cf83e..7ca29a0a3019 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -107,20 +107,22 @@ static char *ddebug_describe_flags(struct _ddebug *dp, char *buf,
return buf;
}
-#define vpr_info_dq(q, msg) \
-do { \
- if (verbose) \
- /* trim last char off format print */ \
- pr_info("%s: func=\"%s\" file=\"%s\" " \
- "module=\"%s\" format=\"%.*s\" " \
- "lineno=%u-%u", \
- msg, \
- q->function ? q->function : "", \
- q->filename ? q->filename : "", \
- q->module ? q->module : "", \
- (int)(q->format ? strlen(q->format) - 1 : 0), \
- q->format ? q->format : "", \
- q->first_lineno, q->last_lineno); \
+#define vpr_info(fmt, ...) \
+ if (verbose) do { pr_info(fmt, ##__VA_ARGS__); } while (0)
+
+#define vpr_info_dq(q, msg) \
+do { \
+ /* trim last char off format print */ \
+ vpr_info("%s: func=\"%s\" file=\"%s\" " \
+ "module=\"%s\" format=\"%.*s\" " \
+ "lineno=%u-%u", \
+ msg, \
+ q->function ? q->function : "", \
+ q->filename ? q->filename : "", \
+ q->module ? q->module : "", \
+ (int)(q->format ? strlen(q->format) - 1 : 0), \
+ q->format ? q->format : "", \
+ q->first_lineno, q->last_lineno); \
} while (0)
/*
@@ -180,12 +182,11 @@ static int ddebug_change(const struct ddebug_query *query,
if (newflags == dp->flags)
continue;
dp->flags = newflags;
- if (verbose)
- pr_info("changed %s:%d [%s]%s =%s\n",
- trim_prefix(dp->filename), dp->lineno,
- dt->mod_name, dp->function,
- ddebug_describe_flags(dp, flagbuf,
- sizeof(flagbuf)));
+ vpr_info("changed %s:%d [%s]%s =%s\n",
+ trim_prefix(dp->filename), dp->lineno,
+ dt->mod_name, dp->function,
+ ddebug_describe_flags(dp, flagbuf,
+ sizeof(flagbuf)));
}
}
mutex_unlock(&ddebug_lock);
@@ -337,7 +338,7 @@ static int check_set(const char **dest, char *src, char *name)
* Returns 0 on success, <0 on error.
*/
static int ddebug_parse_query(char *words[], int nwords,
- struct ddebug_query *query)
+ struct ddebug_query *query, const char *modname)
{
unsigned int i;
int rc;
@@ -347,6 +348,10 @@ static int ddebug_parse_query(char *words[], int nwords,
return -EINVAL;
memset(query, 0, sizeof(*query));
+ if (modname)
+ /* support $modname.dyndbg=<multiple queries> */
+ query->module = modname;
+
for (i = 0 ; i < nwords ; i += 2) {
if (!strcmp(words[i], "func"))
rc = check_set(&query->function, words[i+1], "func");
@@ -410,8 +415,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
default:
return -EINVAL;
}
- if (verbose)
- pr_info("op='%c'\n", op);
+ vpr_info("op='%c'\n", op);
for ( ; *str ; ++str) {
for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) {
@@ -423,8 +427,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
if (i < 0)
return -EINVAL;
}
- if (verbose)
- pr_info("flags=0x%x\n", flags);
+ vpr_info("flags=0x%x\n", flags);
/* calculate final *flagsp, *maskp according to mask and op */
switch (op) {
@@ -441,12 +444,11 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
*flagsp = 0;
break;
}
- if (verbose)
- pr_info("*flagsp=0x%x *maskp=0x%x\n", *flagsp, *maskp);
+ vpr_info("*flagsp=0x%x *maskp=0x%x\n", *flagsp, *maskp);
return 0;
}
-static int ddebug_exec_query(char *query_string)
+static int ddebug_exec_query(char *query_string, const char *modname)
{
unsigned int flags = 0, mask = 0;
struct ddebug_query query;
@@ -457,7 +459,7 @@ static int ddebug_exec_query(char *query_string)
nwords = ddebug_tokenize(query_string, words, MAXWORDS);
if (nwords <= 0)
return -EINVAL;
- if (ddebug_parse_query(words, nwords-1, &query))
+ if (ddebug_parse_query(words, nwords-1, &query, modname))
return -EINVAL;
if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
return -EINVAL;
@@ -473,7 +475,7 @@ static int ddebug_exec_query(char *query_string)
last error or number of matching callsites. Module name is either
in param (for boot arg) or perhaps in query string.
*/
-static int ddebug_exec_queries(char *query)
+static int ddebug_exec_queries(char *query, const char *modname)
{
char *split;
int i, errs = 0, exitcode = 0, rc, nfound = 0;
@@ -487,10 +489,9 @@ static int ddebug_exec_queries(char *query)
if (!query || !*query || *query == '#')
continue;
- if (verbose)
- pr_info("query %d: \"%s\"\n", i, query);
+ vpr_info("query %d: \"%s\"\n", i, query);
- rc = ddebug_exec_query(query);
+ rc = ddebug_exec_query(query, modname);
if (rc < 0) {
errs++;
exitcode = rc;
@@ -498,7 +499,7 @@ static int ddebug_exec_queries(char *query)
nfound += rc;
i++;
}
- pr_info("processed %d queries, with %d matches, %d errs\n",
+ vpr_info("processed %d queries, with %d matches, %d errs\n",
i, nfound, errs);
if (exitcode)
@@ -653,10 +654,9 @@ static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
return -EFAULT;
}
tmpbuf[len] = '\0';
- if (verbose)
- pr_info("read %d bytes from userspace\n", (int)len);
+ vpr_info("read %d bytes from userspace\n", (int)len);
- ret = ddebug_exec_queries(tmpbuf);
+ ret = ddebug_exec_queries(tmpbuf, NULL);
kfree(tmpbuf);
if (ret < 0)
return ret;
@@ -717,8 +717,7 @@ static void *ddebug_proc_start(struct seq_file *m, loff_t *pos)
struct _ddebug *dp;
int n = *pos;
- if (verbose)
- pr_info("called m=%p *pos=%lld\n", m, (unsigned long long)*pos);
+ vpr_info("called m=%p *pos=%lld\n", m, (unsigned long long)*pos);
mutex_lock(&ddebug_lock);
@@ -742,9 +741,8 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
struct ddebug_iter *iter = m->private;
struct _ddebug *dp;
- if (verbose)
- pr_info("called m=%p p=%p *pos=%lld\n",
- m, p, (unsigned long long)*pos);
+ vpr_info("called m=%p p=%p *pos=%lld\n",
+ m, p, (unsigned long long)*pos);
if (p == SEQ_START_TOKEN)
dp = ddebug_iter_first(iter);
@@ -766,8 +764,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
struct _ddebug *dp = p;
char flagsbuf[10];
- if (verbose)
- pr_info("called m=%p p=%p\n", m, p);
+ vpr_info("called m=%p p=%p\n", m, p);
if (p == SEQ_START_TOKEN) {
seq_puts(m,
@@ -791,8 +788,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
*/
static void ddebug_proc_stop(struct seq_file *m, void *p)
{
- if (verbose)
- pr_info("called m=%p p=%p\n", m, p);
+ vpr_info("called m=%p p=%p\n", m, p);
mutex_unlock(&ddebug_lock);
}
@@ -815,8 +811,7 @@ static int ddebug_proc_open(struct inode *inode, struct file *file)
struct ddebug_iter *iter;
int err;
- if (verbose)
- pr_info("called\n");
+ vpr_info("called\n");
iter = kzalloc(sizeof(*iter), GFP_KERNEL);
if (iter == NULL)
@@ -866,12 +861,51 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
list_add_tail(&dt->link, &ddebug_tables);
mutex_unlock(&ddebug_lock);
- if (verbose)
- pr_info("%u debug prints in module %s\n", n, dt->mod_name);
+ vpr_info("%u debug prints in module %s\n", n, dt->mod_name);
return 0;
}
EXPORT_SYMBOL_GPL(ddebug_add_module);
+/* helper for ddebug_dyndbg_(boot|module)_param_cb */
+static int ddebug_dyndbg_param_cb(char *param, char *val,
+ const char *modname, int on_err)
+{
+ char *sep;
+
+ sep = strchr(param, '.');
+ if (sep) {
+ /* needed only for ddebug_dyndbg_boot_param_cb */
+ *sep = '\0';
+ modname = param;
+ param = sep + 1;
+ }
+ if (strcmp(param, "dyndbg"))
+ return on_err; /* determined by caller */
+
+ ddebug_exec_queries((val ? val : "+p"), modname);
+
+ return 0; /* query failure shouldnt stop module load */
+}
+
+/* handle both dyndbg and $module.dyndbg params at boot */
+static int ddebug_dyndbg_boot_param_cb(char *param, char *val,
+ const char *unused)
+{
+ vpr_info("%s=\"%s\"\n", param, val);
+ return ddebug_dyndbg_param_cb(param, val, NULL, 0);
+}
+
+/*
+ * modprobe foo finds foo.params in boot-args, strips "foo.", and
+ * passes them to load_module(). This callback gets unknown params,
+ * processes dyndbg params, rejects others.
+ */
+int ddebug_dyndbg_module_param_cb(char *param, char *val, const char *module)
+{
+ vpr_info("module: %s %s=\"%s\"\n", module, param, val);
+ return ddebug_dyndbg_param_cb(param, val, module, -ENOENT);
+}
+
static void ddebug_table_free(struct ddebug_table *dt)
{
list_del_init(&dt->link);
@@ -888,8 +922,7 @@ int ddebug_remove_module(const char *mod_name)
struct ddebug_table *dt, *nextdt;
int ret = -ENOENT;
- if (verbose)
- pr_info("removing module \"%s\"\n", mod_name);
+ vpr_info("removing module \"%s\"\n", mod_name);
mutex_lock(&ddebug_lock);
list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) {
@@ -940,8 +973,10 @@ static int __init dynamic_debug_init(void)
{
struct _ddebug *iter, *iter_start;
const char *modname = NULL;
+ char *cmdline;
int ret = 0;
- int n = 0;
+ int n = 0, entries = 0, modct = 0;
+ int verbose_bytes = 0;
if (__start___verbose == __stop___verbose) {
pr_warn("_ddebug table is empty in a "
@@ -952,10 +987,15 @@ static int __init dynamic_debug_init(void)
modname = iter->modname;
iter_start = iter;
for (; iter < __stop___verbose; iter++) {
+ entries++;
+ verbose_bytes += strlen(iter->modname) + strlen(iter->function)
+ + strlen(iter->filename) + strlen(iter->format);
+
if (strcmp(modname, iter->modname)) {
+ modct++;
ret = ddebug_add_module(iter_start, n, modname);
if (ret)
- goto out_free;
+ goto out_err;
n = 0;
modname = iter->modname;
iter_start = iter;
@@ -964,29 +1004,45 @@ static int __init dynamic_debug_init(void)
}
ret = ddebug_add_module(iter_start, n, modname);
if (ret)
- goto out_free;
+ goto out_err;
+
+ ddebug_init_success = 1;
+ vpr_info("%d modules, %d entries and %d bytes in ddebug tables,"
+ " %d bytes in (readonly) verbose section\n",
+ modct, entries, (int)( modct * sizeof(struct ddebug_table)),
+ verbose_bytes + (int)(__stop___verbose - __start___verbose));
- /* ddebug_query boot param got passed -> set it up */
+ /* apply ddebug_query boot param, dont unload tables on err */
if (ddebug_setup_string[0] != '\0') {
- ret = ddebug_exec_queries(ddebug_setup_string);
+ pr_warn("ddebug_query param name is deprecated,"
+ " change it to dyndbg\n");
+ ret = ddebug_exec_queries(ddebug_setup_string, NULL);
if (ret < 0)
pr_warn("Invalid ddebug boot param %s",
ddebug_setup_string);
else
pr_info("%d changes by ddebug_query\n", ret);
-
- /* keep tables even on ddebug_query parse error */
- ret = 0;
}
+ /* now that ddebug tables are loaded, process all boot args
+ * again to find and activate queries given in dyndbg params.
+ * While this has already been done for known boot params, it
+ * ignored the unknown ones (dyndbg in particular). Reusing
+ * parse_args avoids ad-hoc parsing. This will also attempt
+ * to activate queries for not-yet-loaded modules, which is
+ * slightly noisy if verbose, but harmless.
+ */
+ cmdline = kstrdup(saved_command_line, GFP_KERNEL);
+ parse_args("dyndbg params", cmdline, NULL,
+ 0, 0, 0, &ddebug_dyndbg_boot_param_cb);
+ kfree(cmdline);
+ return 0;
-out_free:
- if (ret)
- ddebug_remove_all_tables();
- else
- ddebug_init_success = 1;
+out_err:
+ ddebug_remove_all_tables();
return 0;
}
/* Allow early initialization for boot messages via boot param */
-arch_initcall(dynamic_debug_init);
+early_initcall(dynamic_debug_init);
+
/* Debugfs setup must be done later */
-module_init(dynamic_debug_init_debugfs);
+fs_initcall(dynamic_debug_init_debugfs);
diff --git a/lib/jedec_ddr_data.c b/lib/jedec_ddr_data.c
new file mode 100644
index 000000000000..6d2cbf1d567f
--- /dev/null
+++ b/lib/jedec_ddr_data.c
@@ -0,0 +1,135 @@
+/*
+ * DDR addressing details and AC timing parameters from JEDEC specs
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <memory/jedec_ddr.h>
+#include <linux/module.h>
+
+/* LPDDR2 addressing details from JESD209-2 section 2.4 */
+const struct lpddr2_addressing
+ lpddr2_jedec_addressing_table[NUM_DDR_ADDR_TABLE_ENTRIES] = {
+ {B4, T_REFI_15_6, T_RFC_90}, /* 64M */
+ {B4, T_REFI_15_6, T_RFC_90}, /* 128M */
+ {B4, T_REFI_7_8, T_RFC_90}, /* 256M */
+ {B4, T_REFI_7_8, T_RFC_90}, /* 512M */
+ {B8, T_REFI_7_8, T_RFC_130}, /* 1GS4 */
+ {B8, T_REFI_3_9, T_RFC_130}, /* 2GS4 */
+ {B8, T_REFI_3_9, T_RFC_130}, /* 4G */
+ {B8, T_REFI_3_9, T_RFC_210}, /* 8G */
+ {B4, T_REFI_7_8, T_RFC_130}, /* 1GS2 */
+ {B4, T_REFI_3_9, T_RFC_130}, /* 2GS2 */
+};
+EXPORT_SYMBOL_GPL(lpddr2_jedec_addressing_table);
+
+/* LPDDR2 AC timing parameters from JESD209-2 section 12 */
+const struct lpddr2_timings
+ lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES] = {
+ /* Speed bin 400(200 MHz) */
+ [0] = {
+ .max_freq = 200000000,
+ .min_freq = 10000000,
+ .tRPab = 21000,
+ .tRCD = 18000,
+ .tWR = 15000,
+ .tRAS_min = 42000,
+ .tRRD = 10000,
+ .tWTR = 10000,
+ .tXP = 7500,
+ .tRTP = 7500,
+ .tCKESR = 15000,
+ .tDQSCK_max = 5500,
+ .tFAW = 50000,
+ .tZQCS = 90000,
+ .tZQCL = 360000,
+ .tZQinit = 1000000,
+ .tRAS_max_ns = 70000,
+ .tDQSCK_max_derated = 6000,
+ },
+ /* Speed bin 533(266 MHz) */
+ [1] = {
+ .max_freq = 266666666,
+ .min_freq = 10000000,
+ .tRPab = 21000,
+ .tRCD = 18000,
+ .tWR = 15000,
+ .tRAS_min = 42000,
+ .tRRD = 10000,
+ .tWTR = 7500,
+ .tXP = 7500,
+ .tRTP = 7500,
+ .tCKESR = 15000,
+ .tDQSCK_max = 5500,
+ .tFAW = 50000,
+ .tZQCS = 90000,
+ .tZQCL = 360000,
+ .tZQinit = 1000000,
+ .tRAS_max_ns = 70000,
+ .tDQSCK_max_derated = 6000,
+ },
+ /* Speed bin 800(400 MHz) */
+ [2] = {
+ .max_freq = 400000000,
+ .min_freq = 10000000,
+ .tRPab = 21000,
+ .tRCD = 18000,
+ .tWR = 15000,
+ .tRAS_min = 42000,
+ .tRRD = 10000,
+ .tWTR = 7500,
+ .tXP = 7500,
+ .tRTP = 7500,
+ .tCKESR = 15000,
+ .tDQSCK_max = 5500,
+ .tFAW = 50000,
+ .tZQCS = 90000,
+ .tZQCL = 360000,
+ .tZQinit = 1000000,
+ .tRAS_max_ns = 70000,
+ .tDQSCK_max_derated = 6000,
+ },
+ /* Speed bin 1066(533 MHz) */
+ [3] = {
+ .max_freq = 533333333,
+ .min_freq = 10000000,
+ .tRPab = 21000,
+ .tRCD = 18000,
+ .tWR = 15000,
+ .tRAS_min = 42000,
+ .tRRD = 10000,
+ .tWTR = 7500,
+ .tXP = 7500,
+ .tRTP = 7500,
+ .tCKESR = 15000,
+ .tDQSCK_max = 5500,
+ .tFAW = 50000,
+ .tZQCS = 90000,
+ .tZQCL = 360000,
+ .tZQinit = 1000000,
+ .tRAS_max_ns = 70000,
+ .tDQSCK_max_derated = 5620,
+ },
+};
+EXPORT_SYMBOL_GPL(lpddr2_jedec_timings);
+
+const struct lpddr2_min_tck lpddr2_jedec_min_tck = {
+ .tRPab = 3,
+ .tRCD = 3,
+ .tWR = 3,
+ .tRASmin = 3,
+ .tRRD = 2,
+ .tWTR = 2,
+ .tXP = 2,
+ .tRTP = 2,
+ .tCKE = 3,
+ .tCKESR = 3,
+ .tFAW = 8
+};
+EXPORT_SYMBOL_GPL(lpddr2_jedec_min_tck);
diff --git a/lib/kobject.c b/lib/kobject.c
index aeefa8bc8b1c..e07ee1fcd6f1 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -47,13 +47,11 @@ static int populate_dir(struct kobject *kobj)
static int create_dir(struct kobject *kobj)
{
int error = 0;
- if (kobject_name(kobj)) {
- error = sysfs_create_dir(kobj);
- if (!error) {
- error = populate_dir(kobj);
- if (error)
- sysfs_remove_dir(kobj);
- }
+ error = sysfs_create_dir(kobj);
+ if (!error) {
+ error = populate_dir(kobj);
+ if (error)
+ sysfs_remove_dir(kobj);
}
return error;
}
@@ -634,7 +632,7 @@ struct kobject *kobject_create(void)
/**
* kobject_create_and_add - create a struct kobject dynamically and register it with sysfs
*
- * @name: the name for the kset
+ * @name: the name for the kobject
* @parent: the parent kobject of this kobject, if any.
*
* This function creates a kobject structure dynamically and registers it
diff --git a/lib/list_debug.c b/lib/list_debug.c
index 982b850d4e7a..3810b481f940 100644
--- a/lib/list_debug.c
+++ b/lib/list_debug.c
@@ -10,6 +10,7 @@
#include <linux/list.h>
#include <linux/bug.h>
#include <linux/kernel.h>
+#include <linux/rculist.h>
/*
* Insert a new entry between two known consecutive entries.
@@ -75,3 +76,24 @@ void list_del(struct list_head *entry)
entry->prev = LIST_POISON2;
}
EXPORT_SYMBOL(list_del);
+
+/*
+ * RCU variants.
+ */
+void __list_add_rcu(struct list_head *new,
+ struct list_head *prev, struct list_head *next)
+{
+ WARN(next->prev != prev,
+ "list_add_rcu corruption. next->prev should be "
+ "prev (%p), but was %p. (next=%p).\n",
+ prev, next->prev, next);
+ WARN(prev->next != next,
+ "list_add_rcu corruption. prev->next should be "
+ "next (%p), but was %p. (prev=%p).\n",
+ next, prev->next, prev);
+ new->next = next;
+ new->prev = prev;
+ rcu_assign_pointer(list_next_rcu(prev), new);
+ next->prev = new;
+}
+EXPORT_SYMBOL(__list_add_rcu);
diff --git a/lib/raid6/Makefile b/lib/raid6/Makefile
index 8a38102770f3..de06dfe165b8 100644
--- a/lib/raid6/Makefile
+++ b/lib/raid6/Makefile
@@ -1,6 +1,6 @@
obj-$(CONFIG_RAID6_PQ) += raid6_pq.o
-raid6_pq-y += algos.o recov.o tables.o int1.o int2.o int4.o \
+raid6_pq-y += algos.o recov.o recov_ssse3.o tables.o int1.o int2.o int4.o \
int8.o int16.o int32.o altivec1.o altivec2.o altivec4.o \
altivec8.o mmx.o sse1.o sse2.o
hostprogs-y += mktables
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
index 8b02f60ffc86..589f5f50ad2e 100644
--- a/lib/raid6/algos.c
+++ b/lib/raid6/algos.c
@@ -17,11 +17,11 @@
*/
#include <linux/raid/pq.h>
-#include <linux/module.h>
#ifndef __KERNEL__
#include <sys/mman.h>
#include <stdio.h>
#else
+#include <linux/module.h>
#include <linux/gfp.h>
#if !RAID6_USE_EMPTY_ZERO_PAGE
/* In .bss so it's zeroed */
@@ -34,10 +34,6 @@ struct raid6_calls raid6_call;
EXPORT_SYMBOL_GPL(raid6_call);
const struct raid6_calls * const raid6_algos[] = {
- &raid6_intx1,
- &raid6_intx2,
- &raid6_intx4,
- &raid6_intx8,
#if defined(__ia64__)
&raid6_intx16,
&raid6_intx32,
@@ -61,6 +57,24 @@ const struct raid6_calls * const raid6_algos[] = {
&raid6_altivec4,
&raid6_altivec8,
#endif
+ &raid6_intx1,
+ &raid6_intx2,
+ &raid6_intx4,
+ &raid6_intx8,
+ NULL
+};
+
+void (*raid6_2data_recov)(int, size_t, int, int, void **);
+EXPORT_SYMBOL_GPL(raid6_2data_recov);
+
+void (*raid6_datap_recov)(int, size_t, int, void **);
+EXPORT_SYMBOL_GPL(raid6_datap_recov);
+
+const struct raid6_recov_calls *const raid6_recov_algos[] = {
+#if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__)
+ &raid6_recov_ssse3,
+#endif
+ &raid6_recov_intx1,
NULL
};
@@ -72,59 +86,55 @@ const struct raid6_calls * const raid6_algos[] = {
#define time_before(x, y) ((x) < (y))
#endif
-/* Try to pick the best algorithm */
-/* This code uses the gfmul table as convenient data set to abuse */
-
-int __init raid6_select_algo(void)
+static inline const struct raid6_recov_calls *raid6_choose_recov(void)
{
- const struct raid6_calls * const * algo;
- const struct raid6_calls * best;
- char *syndromes;
- void *dptrs[(65536/PAGE_SIZE)+2];
- int i, disks;
- unsigned long perf, bestperf;
- int bestprefer;
- unsigned long j0, j1;
+ const struct raid6_recov_calls *const *algo;
+ const struct raid6_recov_calls *best;
- disks = (65536/PAGE_SIZE)+2;
- for ( i = 0 ; i < disks-2 ; i++ ) {
- dptrs[i] = ((char *)raid6_gfmul) + PAGE_SIZE*i;
- }
+ for (best = NULL, algo = raid6_recov_algos; *algo; algo++)
+ if (!best || (*algo)->priority > best->priority)
+ if (!(*algo)->valid || (*algo)->valid())
+ best = *algo;
- /* Normal code - use a 2-page allocation to avoid D$ conflict */
- syndromes = (void *) __get_free_pages(GFP_KERNEL, 1);
+ if (best) {
+ raid6_2data_recov = best->data2;
+ raid6_datap_recov = best->datap;
- if ( !syndromes ) {
- printk("raid6: Yikes! No memory available.\n");
- return -ENOMEM;
- }
+ printk("raid6: using %s recovery algorithm\n", best->name);
+ } else
+ printk("raid6: Yikes! No recovery algorithm found!\n");
- dptrs[disks-2] = syndromes;
- dptrs[disks-1] = syndromes + PAGE_SIZE;
+ return best;
+}
+
+static inline const struct raid6_calls *raid6_choose_gen(
+ void *(*const dptrs)[(65536/PAGE_SIZE)+2], const int disks)
+{
+ unsigned long perf, bestperf, j0, j1;
+ const struct raid6_calls *const *algo;
+ const struct raid6_calls *best;
- bestperf = 0; bestprefer = 0; best = NULL;
+ for (bestperf = 0, best = NULL, algo = raid6_algos; *algo; algo++) {
+ if (!best || (*algo)->prefer >= best->prefer) {
+ if ((*algo)->valid && !(*algo)->valid())
+ continue;
- for ( algo = raid6_algos ; *algo ; algo++ ) {
- if ( !(*algo)->valid || (*algo)->valid() ) {
perf = 0;
preempt_disable();
j0 = jiffies;
- while ( (j1 = jiffies) == j0 )
+ while ((j1 = jiffies) == j0)
cpu_relax();
while (time_before(jiffies,
j1 + (1<<RAID6_TIME_JIFFIES_LG2))) {
- (*algo)->gen_syndrome(disks, PAGE_SIZE, dptrs);
+ (*algo)->gen_syndrome(disks, PAGE_SIZE, *dptrs);
perf++;
}
preempt_enable();
- if ( (*algo)->prefer > bestprefer ||
- ((*algo)->prefer == bestprefer &&
- perf > bestperf) ) {
- best = *algo;
- bestprefer = best->prefer;
+ if (perf > bestperf) {
bestperf = perf;
+ best = *algo;
}
printk("raid6: %-8s %5ld MB/s\n", (*algo)->name,
(perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2));
@@ -139,9 +149,46 @@ int __init raid6_select_algo(void)
} else
printk("raid6: Yikes! No algorithm found!\n");
+ return best;
+}
+
+
+/* Try to pick the best algorithm */
+/* This code uses the gfmul table as convenient data set to abuse */
+
+int __init raid6_select_algo(void)
+{
+ const int disks = (65536/PAGE_SIZE)+2;
+
+ const struct raid6_calls *gen_best;
+ const struct raid6_recov_calls *rec_best;
+ char *syndromes;
+ void *dptrs[(65536/PAGE_SIZE)+2];
+ int i;
+
+ for (i = 0; i < disks-2; i++)
+ dptrs[i] = ((char *)raid6_gfmul) + PAGE_SIZE*i;
+
+ /* Normal code - use a 2-page allocation to avoid D$ conflict */
+ syndromes = (void *) __get_free_pages(GFP_KERNEL, 1);
+
+ if (!syndromes) {
+ printk("raid6: Yikes! No memory available.\n");
+ return -ENOMEM;
+ }
+
+ dptrs[disks-2] = syndromes;
+ dptrs[disks-1] = syndromes + PAGE_SIZE;
+
+ /* select raid gen_syndrome function */
+ gen_best = raid6_choose_gen(&dptrs, disks);
+
+ /* select raid recover functions */
+ rec_best = raid6_choose_recov();
+
free_pages((unsigned long)syndromes, 1);
- return best ? 0 : -EINVAL;
+ return gen_best && rec_best ? 0 : -EINVAL;
}
static void raid6_exit(void)
diff --git a/lib/raid6/mktables.c b/lib/raid6/mktables.c
index 8a3780902cec..39787db588b0 100644
--- a/lib/raid6/mktables.c
+++ b/lib/raid6/mktables.c
@@ -81,6 +81,31 @@ int main(int argc, char *argv[])
printf("EXPORT_SYMBOL(raid6_gfmul);\n");
printf("#endif\n");
+ /* Compute vector multiplication table */
+ printf("\nconst u8 __attribute__((aligned(256)))\n"
+ "raid6_vgfmul[256][32] =\n"
+ "{\n");
+ for (i = 0; i < 256; i++) {
+ printf("\t{\n");
+ for (j = 0; j < 16; j += 8) {
+ printf("\t\t");
+ for (k = 0; k < 8; k++)
+ printf("0x%02x,%c", gfmul(i, j + k),
+ (k == 7) ? '\n' : ' ');
+ }
+ for (j = 0; j < 16; j += 8) {
+ printf("\t\t");
+ for (k = 0; k < 8; k++)
+ printf("0x%02x,%c", gfmul(i, (j + k) << 4),
+ (k == 7) ? '\n' : ' ');
+ }
+ printf("\t},\n");
+ }
+ printf("};\n");
+ printf("#ifdef __KERNEL__\n");
+ printf("EXPORT_SYMBOL(raid6_vgfmul);\n");
+ printf("#endif\n");
+
/* Compute power-of-2 table (exponent) */
v = 1;
printf("\nconst u8 __attribute__((aligned(256)))\n"
diff --git a/lib/raid6/recov.c b/lib/raid6/recov.c
index fe275d7b6b36..1805a5cc5daa 100644
--- a/lib/raid6/recov.c
+++ b/lib/raid6/recov.c
@@ -22,7 +22,7 @@
#include <linux/raid/pq.h>
/* Recover two failed data blocks. */
-void raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
+void raid6_2data_recov_intx1(int disks, size_t bytes, int faila, int failb,
void **ptrs)
{
u8 *p, *q, *dp, *dq;
@@ -64,10 +64,9 @@ void raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
p++; q++;
}
}
-EXPORT_SYMBOL_GPL(raid6_2data_recov);
/* Recover failure of one data block plus the P block */
-void raid6_datap_recov(int disks, size_t bytes, int faila, void **ptrs)
+void raid6_datap_recov_intx1(int disks, size_t bytes, int faila, void **ptrs)
{
u8 *p, *q, *dq;
const u8 *qmul; /* Q multiplier table */
@@ -96,7 +95,15 @@ void raid6_datap_recov(int disks, size_t bytes, int faila, void **ptrs)
q++; dq++;
}
}
-EXPORT_SYMBOL_GPL(raid6_datap_recov);
+
+
+const struct raid6_recov_calls raid6_recov_intx1 = {
+ .data2 = raid6_2data_recov_intx1,
+ .datap = raid6_datap_recov_intx1,
+ .valid = NULL,
+ .name = "intx1",
+ .priority = 0,
+};
#ifndef __KERNEL__
/* Testing only */
diff --git a/lib/raid6/recov_ssse3.c b/lib/raid6/recov_ssse3.c
new file mode 100644
index 000000000000..37ae61930559
--- /dev/null
+++ b/lib/raid6/recov_ssse3.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__)
+
+#include <linux/raid/pq.h>
+#include "x86.h"
+
+static int raid6_has_ssse3(void)
+{
+ return boot_cpu_has(X86_FEATURE_XMM) &&
+ boot_cpu_has(X86_FEATURE_XMM2) &&
+ boot_cpu_has(X86_FEATURE_SSSE3);
+}
+
+void raid6_2data_recov_ssse3(int disks, size_t bytes, int faila, int failb,
+ void **ptrs)
+{
+ u8 *p, *q, *dp, *dq;
+ const u8 *pbmul; /* P multiplier table for B data */
+ const u8 *qmul; /* Q multiplier table (for both) */
+ static const u8 __aligned(16) x0f[16] = {
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f};
+
+ p = (u8 *)ptrs[disks-2];
+ q = (u8 *)ptrs[disks-1];
+
+ /* Compute syndrome with zero for the missing data pages
+ Use the dead data pages as temporary storage for
+ delta p and delta q */
+ dp = (u8 *)ptrs[faila];
+ ptrs[faila] = (void *)raid6_empty_zero_page;
+ ptrs[disks-2] = dp;
+ dq = (u8 *)ptrs[failb];
+ ptrs[failb] = (void *)raid6_empty_zero_page;
+ ptrs[disks-1] = dq;
+
+ raid6_call.gen_syndrome(disks, bytes, ptrs);
+
+ /* Restore pointer table */
+ ptrs[faila] = dp;
+ ptrs[failb] = dq;
+ ptrs[disks-2] = p;
+ ptrs[disks-1] = q;
+
+ /* Now, pick the proper data tables */
+ pbmul = raid6_vgfmul[raid6_gfexi[failb-faila]];
+ qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila] ^
+ raid6_gfexp[failb]]];
+
+ kernel_fpu_begin();
+
+ asm volatile("movdqa %0,%%xmm7" : : "m" (x0f[0]));
+
+#ifdef CONFIG_X86_64
+ asm volatile("movdqa %0,%%xmm6" : : "m" (qmul[0]));
+ asm volatile("movdqa %0,%%xmm14" : : "m" (pbmul[0]));
+ asm volatile("movdqa %0,%%xmm15" : : "m" (pbmul[16]));
+#endif
+
+ /* Now do it... */
+ while (bytes) {
+#ifdef CONFIG_X86_64
+ /* xmm6, xmm14, xmm15 */
+
+ asm volatile("movdqa %0,%%xmm1" : : "m" (q[0]));
+ asm volatile("movdqa %0,%%xmm9" : : "m" (q[16]));
+ asm volatile("movdqa %0,%%xmm0" : : "m" (p[0]));
+ asm volatile("movdqa %0,%%xmm8" : : "m" (p[16]));
+ asm volatile("pxor %0,%%xmm1" : : "m" (dq[0]));
+ asm volatile("pxor %0,%%xmm9" : : "m" (dq[16]));
+ asm volatile("pxor %0,%%xmm0" : : "m" (dp[0]));
+ asm volatile("pxor %0,%%xmm8" : : "m" (dp[16]));
+
+ /* xmm0/8 = px */
+
+ asm volatile("movdqa %xmm6,%xmm4");
+ asm volatile("movdqa %0,%%xmm5" : : "m" (qmul[16]));
+ asm volatile("movdqa %xmm6,%xmm12");
+ asm volatile("movdqa %xmm5,%xmm13");
+ asm volatile("movdqa %xmm1,%xmm3");
+ asm volatile("movdqa %xmm9,%xmm11");
+ asm volatile("movdqa %xmm0,%xmm2"); /* xmm2/10 = px */
+ asm volatile("movdqa %xmm8,%xmm10");
+ asm volatile("psraw $4,%xmm1");
+ asm volatile("psraw $4,%xmm9");
+ asm volatile("pand %xmm7,%xmm3");
+ asm volatile("pand %xmm7,%xmm11");
+ asm volatile("pand %xmm7,%xmm1");
+ asm volatile("pand %xmm7,%xmm9");
+ asm volatile("pshufb %xmm3,%xmm4");
+ asm volatile("pshufb %xmm11,%xmm12");
+ asm volatile("pshufb %xmm1,%xmm5");
+ asm volatile("pshufb %xmm9,%xmm13");
+ asm volatile("pxor %xmm4,%xmm5");
+ asm volatile("pxor %xmm12,%xmm13");
+
+ /* xmm5/13 = qx */
+
+ asm volatile("movdqa %xmm14,%xmm4");
+ asm volatile("movdqa %xmm15,%xmm1");
+ asm volatile("movdqa %xmm14,%xmm12");
+ asm volatile("movdqa %xmm15,%xmm9");
+ asm volatile("movdqa %xmm2,%xmm3");
+ asm volatile("movdqa %xmm10,%xmm11");
+ asm volatile("psraw $4,%xmm2");
+ asm volatile("psraw $4,%xmm10");
+ asm volatile("pand %xmm7,%xmm3");
+ asm volatile("pand %xmm7,%xmm11");
+ asm volatile("pand %xmm7,%xmm2");
+ asm volatile("pand %xmm7,%xmm10");
+ asm volatile("pshufb %xmm3,%xmm4");
+ asm volatile("pshufb %xmm11,%xmm12");
+ asm volatile("pshufb %xmm2,%xmm1");
+ asm volatile("pshufb %xmm10,%xmm9");
+ asm volatile("pxor %xmm4,%xmm1");
+ asm volatile("pxor %xmm12,%xmm9");
+
+ /* xmm1/9 = pbmul[px] */
+ asm volatile("pxor %xmm5,%xmm1");
+ asm volatile("pxor %xmm13,%xmm9");
+ /* xmm1/9 = db = DQ */
+ asm volatile("movdqa %%xmm1,%0" : "=m" (dq[0]));
+ asm volatile("movdqa %%xmm9,%0" : "=m" (dq[16]));
+
+ asm volatile("pxor %xmm1,%xmm0");
+ asm volatile("pxor %xmm9,%xmm8");
+ asm volatile("movdqa %%xmm0,%0" : "=m" (dp[0]));
+ asm volatile("movdqa %%xmm8,%0" : "=m" (dp[16]));
+
+ bytes -= 32;
+ p += 32;
+ q += 32;
+ dp += 32;
+ dq += 32;
+#else
+ asm volatile("movdqa %0,%%xmm1" : : "m" (*q));
+ asm volatile("movdqa %0,%%xmm0" : : "m" (*p));
+ asm volatile("pxor %0,%%xmm1" : : "m" (*dq));
+ asm volatile("pxor %0,%%xmm0" : : "m" (*dp));
+
+ /* 1 = dq ^ q
+ * 0 = dp ^ p
+ */
+ asm volatile("movdqa %0,%%xmm4" : : "m" (qmul[0]));
+ asm volatile("movdqa %0,%%xmm5" : : "m" (qmul[16]));
+
+ asm volatile("movdqa %xmm1,%xmm3");
+ asm volatile("psraw $4,%xmm1");
+ asm volatile("pand %xmm7,%xmm3");
+ asm volatile("pand %xmm7,%xmm1");
+ asm volatile("pshufb %xmm3,%xmm4");
+ asm volatile("pshufb %xmm1,%xmm5");
+ asm volatile("pxor %xmm4,%xmm5");
+
+ asm volatile("movdqa %xmm0,%xmm2"); /* xmm2 = px */
+
+ /* xmm5 = qx */
+
+ asm volatile("movdqa %0,%%xmm4" : : "m" (pbmul[0]));
+ asm volatile("movdqa %0,%%xmm1" : : "m" (pbmul[16]));
+ asm volatile("movdqa %xmm2,%xmm3");
+ asm volatile("psraw $4,%xmm2");
+ asm volatile("pand %xmm7,%xmm3");
+ asm volatile("pand %xmm7,%xmm2");
+ asm volatile("pshufb %xmm3,%xmm4");
+ asm volatile("pshufb %xmm2,%xmm1");
+ asm volatile("pxor %xmm4,%xmm1");
+
+ /* xmm1 = pbmul[px] */
+ asm volatile("pxor %xmm5,%xmm1");
+ /* xmm1 = db = DQ */
+ asm volatile("movdqa %%xmm1,%0" : "=m" (*dq));
+
+ asm volatile("pxor %xmm1,%xmm0");
+ asm volatile("movdqa %%xmm0,%0" : "=m" (*dp));
+
+ bytes -= 16;
+ p += 16;
+ q += 16;
+ dp += 16;
+ dq += 16;
+#endif
+ }
+
+ kernel_fpu_end();
+}
+
+
+void raid6_datap_recov_ssse3(int disks, size_t bytes, int faila, void **ptrs)
+{
+ u8 *p, *q, *dq;
+ const u8 *qmul; /* Q multiplier table */
+ static const u8 __aligned(16) x0f[16] = {
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f};
+
+ p = (u8 *)ptrs[disks-2];
+ q = (u8 *)ptrs[disks-1];
+
+ /* Compute syndrome with zero for the missing data page
+ Use the dead data page as temporary storage for delta q */
+ dq = (u8 *)ptrs[faila];
+ ptrs[faila] = (void *)raid6_empty_zero_page;
+ ptrs[disks-1] = dq;
+
+ raid6_call.gen_syndrome(disks, bytes, ptrs);
+
+ /* Restore pointer table */
+ ptrs[faila] = dq;
+ ptrs[disks-1] = q;
+
+ /* Now, pick the proper data tables */
+ qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila]]];
+
+ kernel_fpu_begin();
+
+ asm volatile("movdqa %0, %%xmm7" : : "m" (x0f[0]));
+
+ while (bytes) {
+#ifdef CONFIG_X86_64
+ asm volatile("movdqa %0, %%xmm3" : : "m" (dq[0]));
+ asm volatile("movdqa %0, %%xmm4" : : "m" (dq[16]));
+ asm volatile("pxor %0, %%xmm3" : : "m" (q[0]));
+ asm volatile("movdqa %0, %%xmm0" : : "m" (qmul[0]));
+
+ /* xmm3 = q[0] ^ dq[0] */
+
+ asm volatile("pxor %0, %%xmm4" : : "m" (q[16]));
+ asm volatile("movdqa %0, %%xmm1" : : "m" (qmul[16]));
+
+ /* xmm4 = q[16] ^ dq[16] */
+
+ asm volatile("movdqa %xmm3, %xmm6");
+ asm volatile("movdqa %xmm4, %xmm8");
+
+ /* xmm4 = xmm8 = q[16] ^ dq[16] */
+
+ asm volatile("psraw $4, %xmm3");
+ asm volatile("pand %xmm7, %xmm6");
+ asm volatile("pand %xmm7, %xmm3");
+ asm volatile("pshufb %xmm6, %xmm0");
+ asm volatile("pshufb %xmm3, %xmm1");
+ asm volatile("movdqa %0, %%xmm10" : : "m" (qmul[0]));
+ asm volatile("pxor %xmm0, %xmm1");
+ asm volatile("movdqa %0, %%xmm11" : : "m" (qmul[16]));
+
+ /* xmm1 = qmul[q[0] ^ dq[0]] */
+
+ asm volatile("psraw $4, %xmm4");
+ asm volatile("pand %xmm7, %xmm8");
+ asm volatile("pand %xmm7, %xmm4");
+ asm volatile("pshufb %xmm8, %xmm10");
+ asm volatile("pshufb %xmm4, %xmm11");
+ asm volatile("movdqa %0, %%xmm2" : : "m" (p[0]));
+ asm volatile("pxor %xmm10, %xmm11");
+ asm volatile("movdqa %0, %%xmm12" : : "m" (p[16]));
+
+ /* xmm11 = qmul[q[16] ^ dq[16]] */
+
+ asm volatile("pxor %xmm1, %xmm2");
+
+ /* xmm2 = p[0] ^ qmul[q[0] ^ dq[0]] */
+
+ asm volatile("pxor %xmm11, %xmm12");
+
+ /* xmm12 = p[16] ^ qmul[q[16] ^ dq[16]] */
+
+ asm volatile("movdqa %%xmm1, %0" : "=m" (dq[0]));
+ asm volatile("movdqa %%xmm11, %0" : "=m" (dq[16]));
+
+ asm volatile("movdqa %%xmm2, %0" : "=m" (p[0]));
+ asm volatile("movdqa %%xmm12, %0" : "=m" (p[16]));
+
+ bytes -= 32;
+ p += 32;
+ q += 32;
+ dq += 32;
+
+#else
+ asm volatile("movdqa %0, %%xmm3" : : "m" (dq[0]));
+ asm volatile("movdqa %0, %%xmm0" : : "m" (qmul[0]));
+ asm volatile("pxor %0, %%xmm3" : : "m" (q[0]));
+ asm volatile("movdqa %0, %%xmm1" : : "m" (qmul[16]));
+
+ /* xmm3 = *q ^ *dq */
+
+ asm volatile("movdqa %xmm3, %xmm6");
+ asm volatile("movdqa %0, %%xmm2" : : "m" (p[0]));
+ asm volatile("psraw $4, %xmm3");
+ asm volatile("pand %xmm7, %xmm6");
+ asm volatile("pand %xmm7, %xmm3");
+ asm volatile("pshufb %xmm6, %xmm0");
+ asm volatile("pshufb %xmm3, %xmm1");
+ asm volatile("pxor %xmm0, %xmm1");
+
+ /* xmm1 = qmul[*q ^ *dq */
+
+ asm volatile("pxor %xmm1, %xmm2");
+
+ /* xmm2 = *p ^ qmul[*q ^ *dq] */
+
+ asm volatile("movdqa %%xmm1, %0" : "=m" (dq[0]));
+ asm volatile("movdqa %%xmm2, %0" : "=m" (p[0]));
+
+ bytes -= 16;
+ p += 16;
+ q += 16;
+ dq += 16;
+#endif
+ }
+
+ kernel_fpu_end();
+}
+
+const struct raid6_recov_calls raid6_recov_ssse3 = {
+ .data2 = raid6_2data_recov_ssse3,
+ .datap = raid6_datap_recov_ssse3,
+ .valid = raid6_has_ssse3,
+#ifdef CONFIG_X86_64
+ .name = "ssse3x2",
+#else
+ .name = "ssse3x1",
+#endif
+ .priority = 1,
+};
+
+#endif
diff --git a/lib/raid6/test/Makefile b/lib/raid6/test/Makefile
index aa651697b6dc..c76151d94764 100644
--- a/lib/raid6/test/Makefile
+++ b/lib/raid6/test/Makefile
@@ -23,7 +23,7 @@ RANLIB = ranlib
all: raid6.a raid6test
raid6.a: int1.o int2.o int4.o int8.o int16.o int32.o mmx.o sse1.o sse2.o \
- altivec1.o altivec2.o altivec4.o altivec8.o recov.o algos.o \
+ altivec1.o altivec2.o altivec4.o altivec8.o recov.o recov_ssse3.o algos.o \
tables.o
rm -f $@
$(AR) cq $@ $^
diff --git a/lib/raid6/test/test.c b/lib/raid6/test/test.c
index 7a930318b17d..5a485b7a7d3c 100644
--- a/lib/raid6/test/test.c
+++ b/lib/raid6/test/test.c
@@ -90,25 +90,35 @@ static int test_disks(int i, int j)
int main(int argc, char *argv[])
{
const struct raid6_calls *const *algo;
+ const struct raid6_recov_calls *const *ra;
int i, j;
int err = 0;
makedata();
- for (algo = raid6_algos; *algo; algo++) {
- if (!(*algo)->valid || (*algo)->valid()) {
- raid6_call = **algo;
+ for (ra = raid6_recov_algos; *ra; ra++) {
+ if ((*ra)->valid && !(*ra)->valid())
+ continue;
+ raid6_2data_recov = (*ra)->data2;
+ raid6_datap_recov = (*ra)->datap;
- /* Nuke syndromes */
- memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE);
+ printf("using recovery %s\n", (*ra)->name);
- /* Generate assumed good syndrome */
- raid6_call.gen_syndrome(NDISKS, PAGE_SIZE,
- (void **)&dataptrs);
+ for (algo = raid6_algos; *algo; algo++) {
+ if (!(*algo)->valid || (*algo)->valid()) {
+ raid6_call = **algo;
- for (i = 0; i < NDISKS-1; i++)
- for (j = i+1; j < NDISKS; j++)
- err += test_disks(i, j);
+ /* Nuke syndromes */
+ memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE);
+
+ /* Generate assumed good syndrome */
+ raid6_call.gen_syndrome(NDISKS, PAGE_SIZE,
+ (void **)&dataptrs);
+
+ for (i = 0; i < NDISKS-1; i++)
+ for (j = i+1; j < NDISKS; j++)
+ err += test_disks(i, j);
+ }
}
printf("\n");
}
diff --git a/lib/raid6/x86.h b/lib/raid6/x86.h
index cb2a8c91c886..d55d63232c55 100644
--- a/lib/raid6/x86.h
+++ b/lib/raid6/x86.h
@@ -35,24 +35,29 @@ static inline void kernel_fpu_end(void)
{
}
+#define __aligned(x) __attribute__((aligned(x)))
+
#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */
#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE and FXRSTOR instructions
* (fast save and restore) */
#define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */
#define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */
+#define X86_FEATURE_XMM3 (4*32+ 0) /* "pni" SSE-3 */
+#define X86_FEATURE_SSSE3 (4*32+ 9) /* Supplemental SSE-3 */
+#define X86_FEATURE_AVX (4*32+28) /* Advanced Vector Extensions */
#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */
/* Should work well enough on modern CPUs for testing */
static inline int boot_cpu_has(int flag)
{
- u32 eax = (flag >> 5) ? 0x80000001 : 1;
- u32 edx;
+ u32 eax = (flag & 0x20) ? 0x80000001 : 1;
+ u32 ecx, edx;
asm volatile("cpuid"
- : "+a" (eax), "=d" (edx)
- : : "ecx", "ebx");
+ : "+a" (eax), "=d" (edx), "=c" (ecx)
+ : : "ebx");
- return (edx >> (flag & 31)) & 1;
+ return ((flag & 0x80 ? ecx : edx) >> (flag & 31)) & 1;
}
#endif /* ndef __KERNEL__ */
diff --git a/lib/rational.c b/lib/rational.c
index d326da3976f5..f0aa21c2a762 100644
--- a/lib/rational.c
+++ b/lib/rational.c
@@ -1,7 +1,7 @@
/*
* rational fractions
*
- * Copyright (C) 2009 emlix GmbH, Oskar Schirmer <os@emlix.com>
+ * Copyright (C) 2009 emlix GmbH, Oskar Schirmer <oskar@scara.com>
*
* helper functions when coping with rational numbers
*/
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index b659260c56ad..f342778a0c0a 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3873,14 +3873,21 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
return val << PAGE_SHIFT;
}
-static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
+static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft,
+ struct file *file, char __user *buf,
+ size_t nbytes, loff_t *ppos)
{
struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+ char str[64];
u64 val;
- int type, name;
+ int type, name, len;
type = MEMFILE_TYPE(cft->private);
name = MEMFILE_ATTR(cft->private);
+
+ if (!do_swap_account && type == _MEMSWAP)
+ return -EOPNOTSUPP;
+
switch (type) {
case _MEM:
if (name == RES_USAGE)
@@ -3897,7 +3904,9 @@ static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
default:
BUG();
}
- return val;
+
+ len = scnprintf(str, sizeof(str), "%llu\n", (unsigned long long)val);
+ return simple_read_from_buffer(buf, nbytes, ppos, str, len);
}
/*
* The user of this function is...
@@ -3913,6 +3922,10 @@ static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
type = MEMFILE_TYPE(cft->private);
name = MEMFILE_ATTR(cft->private);
+
+ if (!do_swap_account && type == _MEMSWAP)
+ return -EOPNOTSUPP;
+
switch (name) {
case RES_LIMIT:
if (mem_cgroup_is_root(memcg)) { /* Can't set limit on root */
@@ -3978,12 +3991,15 @@ out:
static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
{
- struct mem_cgroup *memcg;
+ struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
int type, name;
- memcg = mem_cgroup_from_cont(cont);
type = MEMFILE_TYPE(event);
name = MEMFILE_ATTR(event);
+
+ if (!do_swap_account && type == _MEMSWAP)
+ return -EOPNOTSUPP;
+
switch (name) {
case RES_MAX_USAGE:
if (type == _MEM)
@@ -4624,29 +4640,22 @@ static int mem_control_numa_stat_open(struct inode *unused, struct file *file)
#endif /* CONFIG_NUMA */
#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
-static int register_kmem_files(struct cgroup *cont, struct cgroup_subsys *ss)
+static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
{
- /*
- * Part of this would be better living in a separate allocation
- * function, leaving us with just the cgroup tree population work.
- * We, however, depend on state such as network's proto_list that
- * is only initialized after cgroup creation. I found the less
- * cumbersome way to deal with it to defer it all to populate time
- */
- return mem_cgroup_sockets_init(cont, ss);
+ return mem_cgroup_sockets_init(memcg, ss);
};
-static void kmem_cgroup_destroy(struct cgroup *cont)
+static void kmem_cgroup_destroy(struct mem_cgroup *memcg)
{
- mem_cgroup_sockets_destroy(cont);
+ mem_cgroup_sockets_destroy(memcg);
}
#else
-static int register_kmem_files(struct cgroup *cont, struct cgroup_subsys *ss)
+static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
{
return 0;
}
-static void kmem_cgroup_destroy(struct cgroup *cont)
+static void kmem_cgroup_destroy(struct mem_cgroup *memcg)
{
}
#endif
@@ -4655,7 +4664,7 @@ static struct cftype mem_cgroup_files[] = {
{
.name = "usage_in_bytes",
.private = MEMFILE_PRIVATE(_MEM, RES_USAGE),
- .read_u64 = mem_cgroup_read,
+ .read = mem_cgroup_read,
.register_event = mem_cgroup_usage_register_event,
.unregister_event = mem_cgroup_usage_unregister_event,
},
@@ -4663,25 +4672,25 @@ static struct cftype mem_cgroup_files[] = {
.name = "max_usage_in_bytes",
.private = MEMFILE_PRIVATE(_MEM, RES_MAX_USAGE),
.trigger = mem_cgroup_reset,
- .read_u64 = mem_cgroup_read,
+ .read = mem_cgroup_read,
},
{
.name = "limit_in_bytes",
.private = MEMFILE_PRIVATE(_MEM, RES_LIMIT),
.write_string = mem_cgroup_write,
- .read_u64 = mem_cgroup_read,
+ .read = mem_cgroup_read,
},
{
.name = "soft_limit_in_bytes",
.private = MEMFILE_PRIVATE(_MEM, RES_SOFT_LIMIT),
.write_string = mem_cgroup_write,
- .read_u64 = mem_cgroup_read,
+ .read = mem_cgroup_read,
},
{
.name = "failcnt",
.private = MEMFILE_PRIVATE(_MEM, RES_FAILCNT),
.trigger = mem_cgroup_reset,
- .read_u64 = mem_cgroup_read,
+ .read = mem_cgroup_read,
},
{
.name = "stat",
@@ -4721,14 +4730,11 @@ static struct cftype mem_cgroup_files[] = {
.mode = S_IRUGO,
},
#endif
-};
-
#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
-static struct cftype memsw_cgroup_files[] = {
{
.name = "memsw.usage_in_bytes",
.private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE),
- .read_u64 = mem_cgroup_read,
+ .read = mem_cgroup_read,
.register_event = mem_cgroup_usage_register_event,
.unregister_event = mem_cgroup_usage_unregister_event,
},
@@ -4736,35 +4742,23 @@ static struct cftype memsw_cgroup_files[] = {
.name = "memsw.max_usage_in_bytes",
.private = MEMFILE_PRIVATE(_MEMSWAP, RES_MAX_USAGE),
.trigger = mem_cgroup_reset,
- .read_u64 = mem_cgroup_read,
+ .read = mem_cgroup_read,
},
{
.name = "memsw.limit_in_bytes",
.private = MEMFILE_PRIVATE(_MEMSWAP, RES_LIMIT),
.write_string = mem_cgroup_write,
- .read_u64 = mem_cgroup_read,
+ .read = mem_cgroup_read,
},
{
.name = "memsw.failcnt",
.private = MEMFILE_PRIVATE(_MEMSWAP, RES_FAILCNT),
.trigger = mem_cgroup_reset,
- .read_u64 = mem_cgroup_read,
+ .read = mem_cgroup_read,
},
-};
-
-static int register_memsw_files(struct cgroup *cont, struct cgroup_subsys *ss)
-{
- if (!do_swap_account)
- return 0;
- return cgroup_add_files(cont, ss, memsw_cgroup_files,
- ARRAY_SIZE(memsw_cgroup_files));
-};
-#else
-static int register_memsw_files(struct cgroup *cont, struct cgroup_subsys *ss)
-{
- return 0;
-}
#endif
+ { }, /* terminate */
+};
static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
{
@@ -5016,6 +5010,17 @@ mem_cgroup_create(struct cgroup *cont)
memcg->move_charge_at_immigrate = 0;
mutex_init(&memcg->thresholds_lock);
spin_lock_init(&memcg->move_lock);
+
+ error = memcg_init_kmem(memcg, &mem_cgroup_subsys);
+ if (error) {
+ /*
+ * We call put now because our (and parent's) refcnts
+ * are already in place. mem_cgroup_put() will internally
+ * call __mem_cgroup_free, so return directly
+ */
+ mem_cgroup_put(memcg);
+ return ERR_PTR(error);
+ }
return &memcg->css;
free_out:
__mem_cgroup_free(memcg);
@@ -5033,28 +5038,11 @@ static void mem_cgroup_destroy(struct cgroup *cont)
{
struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
- kmem_cgroup_destroy(cont);
+ kmem_cgroup_destroy(memcg);
mem_cgroup_put(memcg);
}
-static int mem_cgroup_populate(struct cgroup_subsys *ss,
- struct cgroup *cont)
-{
- int ret;
-
- ret = cgroup_add_files(cont, ss, mem_cgroup_files,
- ARRAY_SIZE(mem_cgroup_files));
-
- if (!ret)
- ret = register_memsw_files(cont, ss);
-
- if (!ret)
- ret = register_kmem_files(cont, ss);
-
- return ret;
-}
-
#ifdef CONFIG_MMU
/* Handlers for move charge at task migration. */
#define PRECHARGE_COUNT_AT_ONCE 256
@@ -5481,7 +5469,7 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd,
* part of thp split is not executed yet.
*/
if (pmd_trans_huge_lock(pmd, vma) == 1) {
- if (!mc.precharge) {
+ if (mc.precharge < HPAGE_PMD_NR) {
spin_unlock(&vma->vm_mm->page_table_lock);
return 0;
}
@@ -5638,12 +5626,13 @@ struct cgroup_subsys mem_cgroup_subsys = {
.create = mem_cgroup_create,
.pre_destroy = mem_cgroup_pre_destroy,
.destroy = mem_cgroup_destroy,
- .populate = mem_cgroup_populate,
.can_attach = mem_cgroup_can_attach,
.cancel_attach = mem_cgroup_cancel_attach,
.attach = mem_cgroup_move_task,
+ .base_cftypes = mem_cgroup_files,
.early_init = 0,
.use_id = 1,
+ .__DEPRECATED_clear_css_refs = true,
};
#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
diff --git a/mm/memory.c b/mm/memory.c
index 6105f475fa86..1e77da6d82c1 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1295,7 +1295,7 @@ static void unmap_page_range(struct mmu_gather *tlb,
static void unmap_single_vma(struct mmu_gather *tlb,
struct vm_area_struct *vma, unsigned long start_addr,
- unsigned long end_addr, unsigned long *nr_accounted,
+ unsigned long end_addr,
struct zap_details *details)
{
unsigned long start = max(vma->vm_start, start_addr);
@@ -1307,9 +1307,6 @@ static void unmap_single_vma(struct mmu_gather *tlb,
if (end <= vma->vm_start)
return;
- if (vma->vm_flags & VM_ACCOUNT)
- *nr_accounted += (end - start) >> PAGE_SHIFT;
-
if (unlikely(is_pfn_mapping(vma)))
untrack_pfn_vma(vma, 0, 0);
@@ -1339,8 +1336,6 @@ static void unmap_single_vma(struct mmu_gather *tlb,
* @vma: the starting vma
* @start_addr: virtual address at which to start unmapping
* @end_addr: virtual address at which to end unmapping
- * @nr_accounted: Place number of unmapped pages in vm-accountable vma's here
- * @details: details of nonlinear truncation or shared cache invalidation
*
* Unmap all pages in the vma list.
*
@@ -1355,15 +1350,13 @@ static void unmap_single_vma(struct mmu_gather *tlb,
*/
void unmap_vmas(struct mmu_gather *tlb,
struct vm_area_struct *vma, unsigned long start_addr,
- unsigned long end_addr, unsigned long *nr_accounted,
- struct zap_details *details)
+ unsigned long end_addr)
{
struct mm_struct *mm = vma->vm_mm;
mmu_notifier_invalidate_range_start(mm, start_addr, end_addr);
for ( ; vma && vma->vm_start < end_addr; vma = vma->vm_next)
- unmap_single_vma(tlb, vma, start_addr, end_addr, nr_accounted,
- details);
+ unmap_single_vma(tlb, vma, start_addr, end_addr, NULL);
mmu_notifier_invalidate_range_end(mm, start_addr, end_addr);
}
@@ -1376,19 +1369,21 @@ void unmap_vmas(struct mmu_gather *tlb,
*
* Caller must protect the VMA list
*/
-void zap_page_range(struct vm_area_struct *vma, unsigned long address,
+void zap_page_range(struct vm_area_struct *vma, unsigned long start,
unsigned long size, struct zap_details *details)
{
struct mm_struct *mm = vma->vm_mm;
struct mmu_gather tlb;
- unsigned long end = address + size;
- unsigned long nr_accounted = 0;
+ unsigned long end = start + size;
lru_add_drain();
tlb_gather_mmu(&tlb, mm, 0);
update_hiwater_rss(mm);
- unmap_vmas(&tlb, vma, address, end, &nr_accounted, details);
- tlb_finish_mmu(&tlb, address, end);
+ mmu_notifier_invalidate_range_start(mm, start, end);
+ for ( ; vma && vma->vm_start < end; vma = vma->vm_next)
+ unmap_single_vma(&tlb, vma, start, end, details);
+ mmu_notifier_invalidate_range_end(mm, start, end);
+ tlb_finish_mmu(&tlb, start, end);
}
/**
@@ -1406,13 +1401,12 @@ static void zap_page_range_single(struct vm_area_struct *vma, unsigned long addr
struct mm_struct *mm = vma->vm_mm;
struct mmu_gather tlb;
unsigned long end = address + size;
- unsigned long nr_accounted = 0;
lru_add_drain();
tlb_gather_mmu(&tlb, mm, 0);
update_hiwater_rss(mm);
mmu_notifier_invalidate_range_start(mm, address, end);
- unmap_single_vma(&tlb, vma, address, end, &nr_accounted, details);
+ unmap_single_vma(&tlb, vma, address, end, details);
mmu_notifier_invalidate_range_end(mm, address, end);
tlb_finish_mmu(&tlb, address, end);
}
diff --git a/mm/mmap.c b/mm/mmap.c
index 848ef52d9603..69a1889f3790 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1889,15 +1889,20 @@ find_extend_vma(struct mm_struct * mm, unsigned long addr)
*/
static void remove_vma_list(struct mm_struct *mm, struct vm_area_struct *vma)
{
+ unsigned long nr_accounted = 0;
+
/* Update high watermark before we lower total_vm */
update_hiwater_vm(mm);
do {
long nrpages = vma_pages(vma);
+ if (vma->vm_flags & VM_ACCOUNT)
+ nr_accounted += nrpages;
mm->total_vm -= nrpages;
vm_stat_account(mm, vma->vm_flags, vma->vm_file, -nrpages);
vma = remove_vma(vma);
} while (vma);
+ vm_unacct_memory(nr_accounted);
validate_mm(mm);
}
@@ -1912,13 +1917,11 @@ static void unmap_region(struct mm_struct *mm,
{
struct vm_area_struct *next = prev? prev->vm_next: mm->mmap;
struct mmu_gather tlb;
- unsigned long nr_accounted = 0;
lru_add_drain();
tlb_gather_mmu(&tlb, mm, 0);
update_hiwater_rss(mm);
- unmap_vmas(&tlb, vma, start, end, &nr_accounted, NULL);
- vm_unacct_memory(nr_accounted);
+ unmap_vmas(&tlb, vma, start, end);
free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS,
next ? next->vm_start : 0);
tlb_finish_mmu(&tlb, start, end);
@@ -2305,8 +2308,7 @@ void exit_mmap(struct mm_struct *mm)
tlb_gather_mmu(&tlb, mm, 1);
/* update_hiwater_rss(mm) here? but nobody should be looking */
/* Use -1 here to ensure all VMAs in the mm are unmapped */
- unmap_vmas(&tlb, vma, 0, -1, &nr_accounted, NULL);
- vm_unacct_memory(nr_accounted);
+ unmap_vmas(&tlb, vma, 0, -1);
free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, 0);
tlb_finish_mmu(&tlb, 0, -1);
@@ -2315,8 +2317,12 @@ void exit_mmap(struct mm_struct *mm)
* Walk the list again, actually closing and freeing it,
* with preemption enabled, without holding any MM locks.
*/
- while (vma)
+ while (vma) {
+ if (vma->vm_flags & VM_ACCOUNT)
+ nr_accounted += vma_pages(vma);
vma = remove_vma(vma);
+ }
+ vm_unacct_memory(nr_accounted);
BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT);
}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 918330f71dba..9f389e50ed18 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4763,12 +4763,12 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
for (i = 0; i < MAX_NR_ZONES; i++) {
if (i == ZONE_MOVABLE)
continue;
- printk(" %-8s ", zone_names[i]);
+ printk(KERN_CONT " %-8s ", zone_names[i]);
if (arch_zone_lowest_possible_pfn[i] ==
arch_zone_highest_possible_pfn[i])
- printk("empty\n");
+ printk(KERN_CONT "empty\n");
else
- printk("%0#10lx -> %0#10lx\n",
+ printk(KERN_CONT "%0#10lx -> %0#10lx\n",
arch_zone_lowest_possible_pfn[i],
arch_zone_highest_possible_pfn[i]);
}
diff --git a/mm/slub.c b/mm/slub.c
index ffe13fdf8144..80848cd3901c 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2040,7 +2040,7 @@ static bool has_cpu_slab(int cpu, void *info)
struct kmem_cache *s = info;
struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu);
- return !!(c->page);
+ return c->page || c->partial;
}
static void flush_all(struct kmem_cache *s)
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index 3d432068f627..5af18d11b518 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -615,7 +615,8 @@ static void p9_virtio_remove(struct virtio_device *vdev)
{
struct virtio_chan *chan = vdev->priv;
- BUG_ON(chan->inuse);
+ if (chan->inuse)
+ p9_virtio_close(chan->client);
vdev->config->del_vqs(vdev);
mutex_lock(&virtio_9p_lock);
diff --git a/net/Kconfig b/net/Kconfig
index da1282359303..245831bec09a 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -207,7 +207,6 @@ source "net/ipx/Kconfig"
source "drivers/net/appletalk/Kconfig"
source "net/x25/Kconfig"
source "net/lapb/Kconfig"
-source "net/econet/Kconfig"
source "net/wanrouter/Kconfig"
source "net/phonet/Kconfig"
source "net/ieee802154/Kconfig"
@@ -247,9 +246,6 @@ config BQL
select DQL
default y
-config HAVE_BPF_JIT
- bool
-
config BPF_JIT
bool "enable BPF Just In Time compiler"
depends on HAVE_BPF_JIT
@@ -341,3 +337,7 @@ source "net/nfc/Kconfig"
endif # if NET
+
+# Used by archs to tell that they support BPF_JIT
+config HAVE_BPF_JIT
+ bool
diff --git a/net/Makefile b/net/Makefile
index 2a97cded8601..4f4ee083064c 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -40,7 +40,6 @@ obj-$(CONFIG_AF_RXRPC) += rxrpc/
obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_L2TP) += l2tp/
obj-$(CONFIG_DECNET) += decnet/
-obj-$(CONFIG_ECONET) += econet/
obj-$(CONFIG_PHONET) += phonet/
ifneq ($(CONFIG_VLAN_8021Q),)
obj-y += 8021q/
diff --git a/net/atm/lec.h b/net/atm/lec.h
index c730e57de199..a86aff9a3c04 100644
--- a/net/atm/lec.h
+++ b/net/atm/lec.h
@@ -55,11 +55,11 @@ struct lane2_ops {
* frames.
*
* 1. Dix Ethernet EtherType frames encoded by placing EtherType
- * field in h_type field. Data follows immediatelly after header.
+ * field in h_type field. Data follows immediately after header.
* 2. LLC Data frames whose total length, including LLC field and data,
* but not padding required to meet the minimum data frame length,
* is less than 1536(0x0600) MUST be encoded by placing that length
- * in the h_type field. The LLC field follows header immediatelly.
+ * in the h_type field. The LLC field follows header immediately.
* 3. LLC data frames longer than this maximum MUST be encoded by placing
* the value 0 in the h_type field.
*
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index d478be11d562..2c20d765b394 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -1195,41 +1195,16 @@ int hidp_get_conninfo(struct hidp_conninfo *ci)
return err;
}
-static const struct hid_device_id hidp_table[] = {
- { HID_BLUETOOTH_DEVICE(HID_ANY_ID, HID_ANY_ID) },
- { }
-};
-
-static struct hid_driver hidp_driver = {
- .name = "generic-bluetooth",
- .id_table = hidp_table,
-};
-
static int __init hidp_init(void)
{
- int ret;
-
BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
- ret = hid_register_driver(&hidp_driver);
- if (ret)
- goto err;
-
- ret = hidp_init_sockets();
- if (ret)
- goto err_drv;
-
- return 0;
-err_drv:
- hid_unregister_driver(&hidp_driver);
-err:
- return ret;
+ return hidp_init_sockets();
}
static void __exit hidp_exit(void)
{
hidp_cleanup_sockets();
- hid_unregister_driver(&hidp_driver);
}
module_init(hidp_init);
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 4bf54b377255..aa5d73b786ac 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -48,13 +48,12 @@
static struct tty_driver *rfcomm_tty_driver;
struct rfcomm_dev {
+ struct tty_port port;
struct list_head list;
- atomic_t refcnt;
char name[12];
int id;
unsigned long flags;
- atomic_t opened;
int err;
bdaddr_t src;
@@ -64,9 +63,7 @@ struct rfcomm_dev {
uint modem_status;
struct rfcomm_dlc *dlc;
- struct tty_struct *tty;
wait_queue_head_t wait;
- struct work_struct wakeup_task;
struct device *tty_dev;
@@ -82,11 +79,18 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb);
static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err);
static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig);
-static void rfcomm_tty_wakeup(struct work_struct *work);
-
/* ---- Device functions ---- */
-static void rfcomm_dev_destruct(struct rfcomm_dev *dev)
+
+/*
+ * The reason this isn't actually a race, as you no doubt have a little voice
+ * screaming at you in your head, is that the refcount should never actually
+ * reach zero unless the device has already been taken off the list, in
+ * rfcomm_dev_del(). And if that's not true, we'll hit the BUG() in
+ * rfcomm_dev_destruct() anyway.
+ */
+static void rfcomm_dev_destruct(struct tty_port *port)
{
+ struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
struct rfcomm_dlc *dlc = dev->dlc;
BT_DBG("dev %p dlc %p", dev, dlc);
@@ -113,23 +117,9 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev)
module_put(THIS_MODULE);
}
-static inline void rfcomm_dev_hold(struct rfcomm_dev *dev)
-{
- atomic_inc(&dev->refcnt);
-}
-
-static inline void rfcomm_dev_put(struct rfcomm_dev *dev)
-{
- /* The reason this isn't actually a race, as you no
- doubt have a little voice screaming at you in your
- head, is that the refcount should never actually
- reach zero unless the device has already been taken
- off the list, in rfcomm_dev_del(). And if that's not
- true, we'll hit the BUG() in rfcomm_dev_destruct()
- anyway. */
- if (atomic_dec_and_test(&dev->refcnt))
- rfcomm_dev_destruct(dev);
-}
+static const struct tty_port_operations rfcomm_port_ops = {
+ .destruct = rfcomm_dev_destruct,
+};
static struct rfcomm_dev *__rfcomm_dev_get(int id)
{
@@ -154,7 +144,7 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id)
if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
dev = NULL;
else
- rfcomm_dev_hold(dev);
+ tty_port_get(&dev->port);
}
spin_unlock(&rfcomm_dev_lock);
@@ -241,7 +231,6 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
sprintf(dev->name, "rfcomm%d", dev->id);
list_add(&dev->list, head);
- atomic_set(&dev->refcnt, 1);
bacpy(&dev->src, &req->src);
bacpy(&dev->dst, &req->dst);
@@ -250,10 +239,9 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
dev->flags = req->flags &
((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
- atomic_set(&dev->opened, 0);
-
+ tty_port_init(&dev->port);
+ dev->port.ops = &rfcomm_port_ops;
init_waitqueue_head(&dev->wait);
- INIT_WORK(&dev->wakeup_task, rfcomm_tty_wakeup);
skb_queue_head_init(&dev->pending);
@@ -320,18 +308,23 @@ free:
static void rfcomm_dev_del(struct rfcomm_dev *dev)
{
+ unsigned long flags;
BT_DBG("dev %p", dev);
BUG_ON(test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags));
- if (atomic_read(&dev->opened) > 0)
+ spin_lock_irqsave(&dev->port.lock, flags);
+ if (dev->port.count > 0) {
+ spin_unlock_irqrestore(&dev->port.lock, flags);
return;
+ }
+ spin_unlock_irqrestore(&dev->port.lock, flags);
spin_lock(&rfcomm_dev_lock);
list_del_init(&dev->list);
spin_unlock(&rfcomm_dev_lock);
- rfcomm_dev_put(dev);
+ tty_port_put(&dev->port);
}
/* ---- Send buffer ---- */
@@ -345,15 +338,16 @@ static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc)
static void rfcomm_wfree(struct sk_buff *skb)
{
struct rfcomm_dev *dev = (void *) skb->sk;
+ struct tty_struct *tty = dev->port.tty;
atomic_sub(skb->truesize, &dev->wmem_alloc);
- if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags))
- queue_work(system_nrt_wq, &dev->wakeup_task);
- rfcomm_dev_put(dev);
+ if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags) && tty)
+ tty_wakeup(tty);
+ tty_port_put(&dev->port);
}
static inline void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev)
{
- rfcomm_dev_hold(dev);
+ tty_port_get(&dev->port);
atomic_add(skb->truesize, &dev->wmem_alloc);
skb->sk = (void *) dev;
skb->destructor = rfcomm_wfree;
@@ -432,7 +426,7 @@ static int rfcomm_release_dev(void __user *arg)
return -ENODEV;
if (dev->flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) {
- rfcomm_dev_put(dev);
+ tty_port_put(&dev->port);
return -EPERM;
}
@@ -440,12 +434,12 @@ static int rfcomm_release_dev(void __user *arg)
rfcomm_dlc_close(dev->dlc, 0);
/* Shut down TTY synchronously before freeing rfcomm_dev */
- if (dev->tty)
- tty_vhangup(dev->tty);
+ if (dev->port.tty)
+ tty_vhangup(dev->port.tty);
if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
rfcomm_dev_del(dev);
- rfcomm_dev_put(dev);
+ tty_port_put(&dev->port);
return 0;
}
@@ -523,7 +517,7 @@ static int rfcomm_get_dev_info(void __user *arg)
if (copy_to_user(arg, &di, sizeof(di)))
err = -EFAULT;
- rfcomm_dev_put(dev);
+ tty_port_put(&dev->port);
return err;
}
@@ -559,7 +553,7 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
return;
}
- tty = dev->tty;
+ tty = dev->port.tty;
if (!tty || !skb_queue_empty(&dev->pending)) {
skb_queue_tail(&dev->pending, skb);
return;
@@ -585,13 +579,13 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
wake_up_interruptible(&dev->wait);
if (dlc->state == BT_CLOSED) {
- if (!dev->tty) {
+ if (!dev->port.tty) {
if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
/* Drop DLC lock here to avoid deadlock
* 1. rfcomm_dev_get will take rfcomm_dev_lock
* but in rfcomm_dev_add there's lock order:
* rfcomm_dev_lock -> dlc lock
- * 2. rfcomm_dev_put will deadlock if it's
+ * 2. tty_port_put will deadlock if it's
* the last reference
*/
rfcomm_dlc_unlock(dlc);
@@ -601,11 +595,11 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
}
rfcomm_dev_del(dev);
- rfcomm_dev_put(dev);
+ tty_port_put(&dev->port);
rfcomm_dlc_lock(dlc);
}
} else
- tty_hangup(dev->tty);
+ tty_hangup(dev->port.tty);
}
}
@@ -618,8 +612,8 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig)
BT_DBG("dlc %p dev %p v24_sig 0x%02x", dlc, dev, v24_sig);
if ((dev->modem_status & TIOCM_CD) && !(v24_sig & RFCOMM_V24_DV)) {
- if (dev->tty && !C_CLOCAL(dev->tty))
- tty_hangup(dev->tty);
+ if (dev->port.tty && !C_CLOCAL(dev->port.tty))
+ tty_hangup(dev->port.tty);
}
dev->modem_status =
@@ -630,21 +624,9 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig)
}
/* ---- TTY functions ---- */
-static void rfcomm_tty_wakeup(struct work_struct *work)
-{
- struct rfcomm_dev *dev = container_of(work, struct rfcomm_dev,
- wakeup_task);
- struct tty_struct *tty = dev->tty;
- if (!tty)
- return;
-
- BT_DBG("dev %p tty %p", dev, tty);
- tty_wakeup(tty);
-}
-
static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev)
{
- struct tty_struct *tty = dev->tty;
+ struct tty_struct *tty = dev->port.tty;
struct sk_buff *skb;
int inserted = 0;
@@ -671,6 +653,7 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
DECLARE_WAITQUEUE(wait, current);
struct rfcomm_dev *dev;
struct rfcomm_dlc *dlc;
+ unsigned long flags;
int err, id;
id = tty->index;
@@ -686,10 +669,14 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
return -ENODEV;
BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst),
- dev->channel, atomic_read(&dev->opened));
+ dev->channel, dev->port.count);
- if (atomic_inc_return(&dev->opened) > 1)
+ spin_lock_irqsave(&dev->port.lock, flags);
+ if (++dev->port.count > 1) {
+ spin_unlock_irqrestore(&dev->port.lock, flags);
return 0;
+ }
+ spin_unlock_irqrestore(&dev->port.lock, flags);
dlc = dev->dlc;
@@ -697,7 +684,7 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
rfcomm_dlc_lock(dlc);
tty->driver_data = dev;
- dev->tty = tty;
+ dev->port.tty = tty;
rfcomm_dlc_unlock(dlc);
set_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
@@ -723,9 +710,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
break;
}
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->wait, &wait);
@@ -744,13 +731,17 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
{
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
+ unsigned long flags;
+
if (!dev)
return;
BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc,
- atomic_read(&dev->opened));
+ dev->port.count);
- if (atomic_dec_and_test(&dev->opened)) {
+ spin_lock_irqsave(&dev->port.lock, flags);
+ if (!--dev->port.count) {
+ spin_unlock_irqrestore(&dev->port.lock, flags);
if (dev->tty_dev->parent)
device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST);
@@ -758,11 +749,10 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
rfcomm_dlc_close(dev->dlc, 0);
clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
- cancel_work_sync(&dev->wakeup_task);
rfcomm_dlc_lock(dev->dlc);
tty->driver_data = NULL;
- dev->tty = NULL;
+ dev->port.tty = NULL;
rfcomm_dlc_unlock(dev->dlc);
if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
@@ -770,11 +760,12 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
list_del_init(&dev->list);
spin_unlock(&rfcomm_dev_lock);
- rfcomm_dev_put(dev);
+ tty_port_put(&dev->port);
}
- }
+ } else
+ spin_unlock_irqrestore(&dev->port.lock, flags);
- rfcomm_dev_put(dev);
+ tty_port_put(&dev->port);
}
static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
@@ -1083,7 +1074,7 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
if (rfcomm_dev_get(dev->id) == NULL)
return;
rfcomm_dev_del(dev);
- rfcomm_dev_put(dev);
+ tty_port_put(&dev->port);
}
}
diff --git a/net/caif/Kconfig b/net/caif/Kconfig
index 936361e5a2b6..d3694953b1d7 100644
--- a/net/caif/Kconfig
+++ b/net/caif/Kconfig
@@ -25,7 +25,7 @@ config CAIF_DEBUG
bool "Enable Debug"
depends on CAIF
default n
- --- help ---
+ ---help---
Enable the inclusion of debug code in the CAIF stack.
Be aware that doing this will impact performance.
If unsure say N.
diff --git a/net/compat.c b/net/compat.c
index e240441a2317..1b96281892de 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -328,14 +328,6 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm)
__scm_destroy(scm);
}
-/*
- * A struct sock_filter is architecture independent.
- */
-struct compat_sock_fprog {
- u16 len;
- compat_uptr_t filter; /* struct sock_filter * */
-};
-
static int do_set_attach_filter(struct socket *sock, int level, int optname,
char __user *optval, unsigned int optlen)
{
diff --git a/net/core/dev.c b/net/core/dev.c
index 33684b6e95e2..cd0981977f5c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3602,7 +3602,7 @@ gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb,
}
EXPORT_SYMBOL(napi_frags_finish);
-struct sk_buff *napi_frags_skb(struct napi_struct *napi)
+static struct sk_buff *napi_frags_skb(struct napi_struct *napi)
{
struct sk_buff *skb = napi->skb;
struct ethhdr *eth;
@@ -3637,7 +3637,6 @@ struct sk_buff *napi_frags_skb(struct napi_struct *napi)
out:
return skb;
}
-EXPORT_SYMBOL(napi_frags_skb);
gro_result_t napi_gro_frags(struct napi_struct *napi)
{
diff --git a/net/core/filter.c b/net/core/filter.c
index 47a5f055e7f3..a3eddb515d1b 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -38,6 +38,7 @@
#include <linux/filter.h>
#include <linux/reciprocal_div.h>
#include <linux/ratelimit.h>
+#include <linux/seccomp.h>
/* No hurry in this branch
*
@@ -355,6 +356,11 @@ load_b:
A = 0;
continue;
}
+#ifdef CONFIG_SECCOMP_FILTER
+ case BPF_S_ANC_SECCOMP_LD_W:
+ A = seccomp_bpf_load(fentry->k);
+ continue;
+#endif
default:
WARN_RATELIMIT(1, "Unknown code:%u jt:%u tf:%u k:%u\n",
fentry->code, fentry->jt,
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c
index 09eda68b6763..5b8aa2fae48b 100644
--- a/net/core/netprio_cgroup.c
+++ b/net/core/netprio_cgroup.c
@@ -25,21 +25,6 @@
#include <net/sock.h>
#include <net/netprio_cgroup.h>
-static struct cgroup_subsys_state *cgrp_create(struct cgroup *cgrp);
-static void cgrp_destroy(struct cgroup *cgrp);
-static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp);
-
-struct cgroup_subsys net_prio_subsys = {
- .name = "net_prio",
- .create = cgrp_create,
- .destroy = cgrp_destroy,
- .populate = cgrp_populate,
-#ifdef CONFIG_NETPRIO_CGROUP
- .subsys_id = net_prio_subsys_id,
-#endif
- .module = THIS_MODULE
-};
-
#define PRIOIDX_SZ 128
static unsigned long prioidx_map[PRIOIDX_SZ];
@@ -259,12 +244,19 @@ static struct cftype ss_files[] = {
.read_map = read_priomap,
.write_string = write_priomap,
},
+ { } /* terminate */
};
-static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
-{
- return cgroup_add_files(cgrp, ss, ss_files, ARRAY_SIZE(ss_files));
-}
+struct cgroup_subsys net_prio_subsys = {
+ .name = "net_prio",
+ .create = cgrp_create,
+ .destroy = cgrp_destroy,
+#ifdef CONFIG_NETPRIO_CGROUP
+ .subsys_id = net_prio_subsys_id,
+#endif
+ .base_cftypes = ss_files,
+ .module = THIS_MODULE
+};
static int netprio_device_event(struct notifier_block *unused,
unsigned long event, void *ptr)
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 30eb768cd677..cce9e53528b1 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3749,13 +3749,13 @@ static void __exit pg_cleanup(void)
{
struct pktgen_thread *t;
struct list_head *q, *n;
- struct list_head list;
+ LIST_HEAD(list);
/* Stop all interfaces & threads */
pktgen_exiting = true;
mutex_lock(&pktgen_thread_lock);
- list_splice(&list, &pktgen_threads);
+ list_splice_init(&pktgen_threads, &list);
mutex_unlock(&pktgen_thread_lock);
list_for_each_safe(q, n, &list) {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 7645df1bada0..016694d62484 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -300,6 +300,40 @@ struct netdev_alloc_cache {
static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache);
/**
+ * netdev_alloc_frag - allocate a page fragment
+ * @fragsz: fragment size
+ *
+ * Allocates a frag from a page for receive buffer.
+ * Uses GFP_ATOMIC allocations.
+ */
+void *netdev_alloc_frag(unsigned int fragsz)
+{
+ struct netdev_alloc_cache *nc;
+ void *data = NULL;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ nc = &__get_cpu_var(netdev_alloc_cache);
+ if (unlikely(!nc->page)) {
+refill:
+ nc->page = alloc_page(GFP_ATOMIC | __GFP_COLD);
+ nc->offset = 0;
+ }
+ if (likely(nc->page)) {
+ if (nc->offset + fragsz > PAGE_SIZE) {
+ put_page(nc->page);
+ goto refill;
+ }
+ data = page_address(nc->page) + nc->offset;
+ nc->offset += fragsz;
+ get_page(nc->page);
+ }
+ local_irq_restore(flags);
+ return data;
+}
+EXPORT_SYMBOL(netdev_alloc_frag);
+
+/**
* __netdev_alloc_skb - allocate an skbuff for rx on a specific device
* @dev: network device to receive on
* @length: length to allocate
@@ -313,32 +347,20 @@ static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache);
* %NULL is returned if there is no free memory.
*/
struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
- unsigned int length, gfp_t gfp_mask)
+ unsigned int length, gfp_t gfp_mask)
{
- struct sk_buff *skb;
+ struct sk_buff *skb = NULL;
unsigned int fragsz = SKB_DATA_ALIGN(length + NET_SKB_PAD) +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
if (fragsz <= PAGE_SIZE && !(gfp_mask & __GFP_WAIT)) {
- struct netdev_alloc_cache *nc;
- void *data = NULL;
+ void *data = netdev_alloc_frag(fragsz);
- nc = &get_cpu_var(netdev_alloc_cache);
- if (!nc->page) {
-refill: nc->page = alloc_page(gfp_mask);
- nc->offset = 0;
+ if (likely(data)) {
+ skb = build_skb(data, fragsz);
+ if (unlikely(!skb))
+ put_page(virt_to_head_page(data));
}
- if (likely(nc->page)) {
- if (nc->offset + fragsz > PAGE_SIZE) {
- put_page(nc->page);
- goto refill;
- }
- data = page_address(nc->page) + nc->offset;
- nc->offset += fragsz;
- get_page(nc->page);
- }
- put_cpu_var(netdev_alloc_cache);
- skb = data ? build_skb(data, fragsz) : NULL;
} else {
skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, NUMA_NO_NODE);
}
@@ -360,28 +382,6 @@ void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
}
EXPORT_SYMBOL(skb_add_rx_frag);
-/**
- * dev_alloc_skb - allocate an skbuff for receiving
- * @length: length to allocate
- *
- * Allocate a new &sk_buff and assign it a usage count of one. The
- * buffer has unspecified headroom built in. Users should allocate
- * the headroom they think they need without accounting for the
- * built in space. The built in space is used for optimisations.
- *
- * %NULL is returned if there is no free memory. Although this function
- * allocates memory it can be called from an interrupt.
- */
-struct sk_buff *dev_alloc_skb(unsigned int length)
-{
- /*
- * There is more code here than it seems:
- * __dev_alloc_skb is an inline
- */
- return __dev_alloc_skb(length, GFP_ATOMIC);
-}
-EXPORT_SYMBOL(dev_alloc_skb);
-
static void skb_drop_list(struct sk_buff **listp)
{
struct sk_buff *list = *listp;
@@ -3346,3 +3346,89 @@ void __skb_warn_lro_forwarding(const struct sk_buff *skb)
skb->dev->name);
}
EXPORT_SYMBOL(__skb_warn_lro_forwarding);
+
+void kfree_skb_partial(struct sk_buff *skb, bool head_stolen)
+{
+ if (head_stolen)
+ kmem_cache_free(skbuff_head_cache, skb);
+ else
+ __kfree_skb(skb);
+}
+EXPORT_SYMBOL(kfree_skb_partial);
+
+/**
+ * skb_try_coalesce - try to merge skb to prior one
+ * @to: prior buffer
+ * @from: buffer to add
+ * @fragstolen: pointer to boolean
+ *
+ */
+bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
+ bool *fragstolen, int *delta_truesize)
+{
+ int i, delta, len = from->len;
+
+ *fragstolen = false;
+
+ if (skb_cloned(to))
+ return false;
+
+ if (len <= skb_tailroom(to)) {
+ BUG_ON(skb_copy_bits(from, 0, skb_put(to, len), len));
+ *delta_truesize = 0;
+ return true;
+ }
+
+ if (skb_has_frag_list(to) || skb_has_frag_list(from))
+ return false;
+
+ if (skb_headlen(from) != 0) {
+ struct page *page;
+ unsigned int offset;
+
+ if (skb_shinfo(to)->nr_frags +
+ skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS)
+ return false;
+
+ if (skb_head_is_locked(from))
+ return false;
+
+ delta = from->truesize - SKB_DATA_ALIGN(sizeof(struct sk_buff));
+
+ page = virt_to_head_page(from->head);
+ offset = from->data - (unsigned char *)page_address(page);
+
+ skb_fill_page_desc(to, skb_shinfo(to)->nr_frags,
+ page, offset, skb_headlen(from));
+ *fragstolen = true;
+ } else {
+ if (skb_shinfo(to)->nr_frags +
+ skb_shinfo(from)->nr_frags > MAX_SKB_FRAGS)
+ return false;
+
+ delta = from->truesize -
+ SKB_TRUESIZE(skb_end_pointer(from) - from->head);
+ }
+
+ WARN_ON_ONCE(delta < len);
+
+ memcpy(skb_shinfo(to)->frags + skb_shinfo(to)->nr_frags,
+ skb_shinfo(from)->frags,
+ skb_shinfo(from)->nr_frags * sizeof(skb_frag_t));
+ skb_shinfo(to)->nr_frags += skb_shinfo(from)->nr_frags;
+
+ if (!skb_cloned(from))
+ skb_shinfo(from)->nr_frags = 0;
+
+ /* if the skb is cloned this does nothing since we set nr_frags to 0 */
+ for (i = 0; i < skb_shinfo(from)->nr_frags; i++)
+ skb_frag_ref(from, i);
+
+ to->truesize += delta;
+ to->len += len;
+ to->data_len += len;
+
+ *delta_truesize = delta;
+ return true;
+}
+EXPORT_SYMBOL(skb_try_coalesce);
diff --git a/net/core/sock.c b/net/core/sock.c
index 5efcd6307fa7..f372d9bf4976 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -143,7 +143,7 @@ static DEFINE_MUTEX(proto_list_mutex);
static LIST_HEAD(proto_list);
#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
-int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss)
+int mem_cgroup_sockets_init(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
{
struct proto *proto;
int ret = 0;
@@ -151,7 +151,7 @@ int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss)
mutex_lock(&proto_list_mutex);
list_for_each_entry(proto, &proto_list, node) {
if (proto->init_cgroup) {
- ret = proto->init_cgroup(cgrp, ss);
+ ret = proto->init_cgroup(memcg, ss);
if (ret)
goto out;
}
@@ -162,19 +162,19 @@ int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss)
out:
list_for_each_entry_continue_reverse(proto, &proto_list, node)
if (proto->destroy_cgroup)
- proto->destroy_cgroup(cgrp);
+ proto->destroy_cgroup(memcg);
mutex_unlock(&proto_list_mutex);
return ret;
}
-void mem_cgroup_sockets_destroy(struct cgroup *cgrp)
+void mem_cgroup_sockets_destroy(struct mem_cgroup *memcg)
{
struct proto *proto;
mutex_lock(&proto_list_mutex);
list_for_each_entry_reverse(proto, &proto_list, node)
if (proto->destroy_cgroup)
- proto->destroy_cgroup(cgrp);
+ proto->destroy_cgroup(memcg);
mutex_unlock(&proto_list_mutex);
}
#endif
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
index 6f70ea935b0b..d9507dd05818 100644
--- a/net/dns_resolver/dns_key.c
+++ b/net/dns_resolver/dns_key.c
@@ -249,9 +249,6 @@ static int __init init_dns_resolver(void)
struct key *keyring;
int ret;
- printk(KERN_NOTICE "Registering the %s key type\n",
- key_type_dns_resolver.name);
-
/* create an override credential set with a special thread keyring in
* which DNS requests are cached
*
@@ -301,8 +298,6 @@ static void __exit exit_dns_resolver(void)
key_revoke(dns_resolver_cache->thread_keyring);
unregister_key_type(&key_type_dns_resolver);
put_cred(dns_resolver_cache);
- printk(KERN_NOTICE "Unregistered %s key type\n",
- key_type_dns_resolver.name);
}
module_init(init_dns_resolver)
diff --git a/net/econet/Kconfig b/net/econet/Kconfig
deleted file mode 100644
index 39a2d2975e0e..000000000000
--- a/net/econet/Kconfig
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Acorn Econet/AUN protocols
-#
-
-config ECONET
- tristate "Acorn Econet/AUN protocols (EXPERIMENTAL)"
- depends on EXPERIMENTAL && INET
- ---help---
- Econet is a fairly old and slow networking protocol mainly used by
- Acorn computers to access file and print servers. It uses native
- Econet network cards. AUN is an implementation of the higher level
- parts of Econet that runs over ordinary Ethernet connections, on
- top of the UDP packet protocol, which in turn runs on top of the
- Internet protocol IP.
-
- If you say Y here, you can choose with the next two options whether
- to send Econet/AUN traffic over a UDP Ethernet connection or over
- a native Econet network card.
-
- To compile this driver as a module, choose M here: the module
- will be called econet.
-
-config ECONET_AUNUDP
- bool "AUN over UDP"
- depends on ECONET
- help
- Say Y here if you want to send Econet/AUN traffic over a UDP
- connection (UDP is a packet based protocol that runs on top of the
- Internet protocol IP) using an ordinary Ethernet network card.
-
-config ECONET_NATIVE
- bool "Native Econet"
- depends on ECONET
- help
- Say Y here if you have a native Econet network card installed in
- your computer.
diff --git a/net/econet/Makefile b/net/econet/Makefile
deleted file mode 100644
index 05fae8be2fed..000000000000
--- a/net/econet/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for Econet support code.
-#
-
-obj-$(CONFIG_ECONET) += econet.o
-
-econet-y := af_econet.o
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
deleted file mode 100644
index fa14ca76b77b..000000000000
--- a/net/econet/af_econet.c
+++ /dev/null
@@ -1,1172 +0,0 @@
-/*
- * An implementation of the Acorn Econet and AUN protocols.
- * Philip Blundell <philb@gnu.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.
- *
- */
-
-#define pr_fmt(fmt) fmt
-
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/route.h>
-#include <linux/inet.h>
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-#include <linux/wireless.h>
-#include <linux/skbuff.h>
-#include <linux/udp.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <net/sock.h>
-#include <net/inet_common.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-#include <linux/if_ec.h>
-#include <net/udp.h>
-#include <net/ip.h>
-#include <linux/spinlock.h>
-#include <linux/rcupdate.h>
-#include <linux/bitops.h>
-#include <linux/mutex.h>
-
-#include <linux/uaccess.h>
-
-static const struct proto_ops econet_ops;
-static struct hlist_head econet_sklist;
-static DEFINE_SPINLOCK(econet_lock);
-static DEFINE_MUTEX(econet_mutex);
-
-/* Since there are only 256 possible network numbers (or fewer, depends
- how you count) it makes sense to use a simple lookup table. */
-static struct net_device *net2dev_map[256];
-
-#define EC_PORT_IP 0xd2
-
-#ifdef CONFIG_ECONET_AUNUDP
-static DEFINE_SPINLOCK(aun_queue_lock);
-static struct socket *udpsock;
-#define AUN_PORT 0x8000
-
-struct aunhdr {
- unsigned char code; /* AUN magic protocol byte */
- unsigned char port;
- unsigned char cb;
- unsigned char pad;
- unsigned long handle;
-};
-
-static unsigned long aun_seq;
-
-/* Queue of packets waiting to be transmitted. */
-static struct sk_buff_head aun_queue;
-static struct timer_list ab_cleanup_timer;
-
-#endif /* CONFIG_ECONET_AUNUDP */
-
-/* Per-packet information */
-struct ec_cb {
- struct sockaddr_ec sec;
- unsigned long cookie; /* Supplied by user. */
-#ifdef CONFIG_ECONET_AUNUDP
- int done;
- unsigned long seq; /* Sequencing */
- unsigned long timeout; /* Timeout */
- unsigned long start; /* jiffies */
-#endif
-#ifdef CONFIG_ECONET_NATIVE
- void (*sent)(struct sk_buff *, int result);
-#endif
-};
-
-static void econet_remove_socket(struct hlist_head *list, struct sock *sk)
-{
- spin_lock_bh(&econet_lock);
- sk_del_node_init(sk);
- spin_unlock_bh(&econet_lock);
-}
-
-static void econet_insert_socket(struct hlist_head *list, struct sock *sk)
-{
- spin_lock_bh(&econet_lock);
- sk_add_node(sk, list);
- spin_unlock_bh(&econet_lock);
-}
-
-/*
- * Pull a packet from our receive queue and hand it to the user.
- * If necessary we block.
- */
-
-static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *msg, size_t len, int flags)
-{
- struct sock *sk = sock->sk;
- struct sk_buff *skb;
- size_t copied;
- int err;
-
- msg->msg_namelen = sizeof(struct sockaddr_ec);
-
- mutex_lock(&econet_mutex);
-
- /*
- * Call the generic datagram receiver. This handles all sorts
- * of horrible races and re-entrancy so we can forget about it
- * in the protocol layers.
- *
- * Now it will return ENETDOWN, if device have just gone down,
- * but then it will block.
- */
-
- skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err);
-
- /*
- * An error occurred so return it. Because skb_recv_datagram()
- * handles the blocking we don't see and worry about blocking
- * retries.
- */
-
- if (skb == NULL)
- goto out;
-
- /*
- * You lose any data beyond the buffer you gave. If it worries a
- * user program they can ask the device for its MTU anyway.
- */
-
- copied = skb->len;
- if (copied > len) {
- copied = len;
- msg->msg_flags |= MSG_TRUNC;
- }
-
- /* We can't use skb_copy_datagram here */
- err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
- if (err)
- goto out_free;
- sk->sk_stamp = skb->tstamp;
-
- if (msg->msg_name)
- memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
-
- /*
- * Free or return the buffer as appropriate. Again this
- * hides all the races and re-entrancy issues from us.
- */
- err = copied;
-
-out_free:
- skb_free_datagram(sk, skb);
-out:
- mutex_unlock(&econet_mutex);
- return err;
-}
-
-/*
- * Bind an Econet socket.
- */
-
-static int econet_bind(struct socket *sock, struct sockaddr *uaddr,
- int addr_len)
-{
- struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
- struct sock *sk;
- struct econet_sock *eo;
-
- /*
- * Check legality
- */
-
- if (addr_len < sizeof(struct sockaddr_ec) ||
- sec->sec_family != AF_ECONET)
- return -EINVAL;
-
- mutex_lock(&econet_mutex);
-
- sk = sock->sk;
- eo = ec_sk(sk);
-
- eo->cb = sec->cb;
- eo->port = sec->port;
- eo->station = sec->addr.station;
- eo->net = sec->addr.net;
-
- mutex_unlock(&econet_mutex);
-
- return 0;
-}
-
-#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)
-/*
- * Queue a transmit result for the user to be told about.
- */
-
-static void tx_result(struct sock *sk, unsigned long cookie, int result)
-{
- struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
- struct ec_cb *eb;
- struct sockaddr_ec *sec;
-
- if (skb == NULL) {
- pr_debug("econet: memory squeeze, transmit result dropped\n");
- return;
- }
-
- eb = (struct ec_cb *)&skb->cb;
- sec = (struct sockaddr_ec *)&eb->sec;
- memset(sec, 0, sizeof(struct sockaddr_ec));
- sec->cookie = cookie;
- sec->type = ECTYPE_TRANSMIT_STATUS | result;
- sec->sec_family = AF_ECONET;
-
- if (sock_queue_rcv_skb(sk, skb) < 0)
- kfree_skb(skb);
-}
-#endif
-
-#ifdef CONFIG_ECONET_NATIVE
-/*
- * Called by the Econet hardware driver when a packet transmit
- * has completed. Tell the user.
- */
-
-static void ec_tx_done(struct sk_buff *skb, int result)
-{
- struct ec_cb *eb = (struct ec_cb *)&skb->cb;
- tx_result(skb->sk, eb->cookie, result);
-}
-#endif
-
-/*
- * Send a packet. We have to work out which device it's going out on
- * and hence whether to use real Econet or the UDP emulation.
- */
-
-static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *msg, size_t len)
-{
- struct sockaddr_ec *saddr = (struct sockaddr_ec *)msg->msg_name;
- struct net_device *dev;
- struct ec_addr addr;
- int err;
- unsigned char port, cb;
-#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)
- struct sock *sk = sock->sk;
- struct sk_buff *skb;
- struct ec_cb *eb;
-#endif
-#ifdef CONFIG_ECONET_AUNUDP
- struct msghdr udpmsg;
- struct iovec iov[2];
- struct aunhdr ah;
- struct sockaddr_in udpdest;
- __kernel_size_t size;
- mm_segment_t oldfs;
- char *userbuf;
-#endif
-
- /*
- * Check the flags.
- */
-
- if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
- return -EINVAL;
-
- /*
- * Get and verify the address.
- */
-
- mutex_lock(&econet_mutex);
-
- if (saddr == NULL || msg->msg_namelen < sizeof(struct sockaddr_ec)) {
- mutex_unlock(&econet_mutex);
- return -EINVAL;
- }
- addr.station = saddr->addr.station;
- addr.net = saddr->addr.net;
- port = saddr->port;
- cb = saddr->cb;
-
- /* Look for a device with the right network number. */
- dev = net2dev_map[addr.net];
-
- /* If not directly reachable, use some default */
- if (dev == NULL) {
- dev = net2dev_map[0];
- /* No interfaces at all? */
- if (dev == NULL) {
- mutex_unlock(&econet_mutex);
- return -ENETDOWN;
- }
- }
-
- if (dev->type == ARPHRD_ECONET) {
- /* Real hardware Econet. We're not worthy etc. */
-#ifdef CONFIG_ECONET_NATIVE
- unsigned short proto = 0;
- int hlen, tlen;
- int res;
-
- if (len + 15 > dev->mtu) {
- mutex_unlock(&econet_mutex);
- return -EMSGSIZE;
- }
-
- dev_hold(dev);
-
- hlen = LL_RESERVED_SPACE(dev);
- tlen = dev->needed_tailroom;
- skb = sock_alloc_send_skb(sk, len + hlen + tlen,
- msg->msg_flags & MSG_DONTWAIT, &err);
- if (skb == NULL)
- goto out_unlock;
-
- skb_reserve(skb, hlen);
- skb_reset_network_header(skb);
-
- eb = (struct ec_cb *)&skb->cb;
-
- eb->cookie = saddr->cookie;
- eb->sec = *saddr;
- eb->sent = ec_tx_done;
-
- err = -EINVAL;
- res = dev_hard_header(skb, dev, ntohs(proto), &addr, NULL, len);
- if (res < 0)
- goto out_free;
- if (res > 0) {
- struct ec_framehdr *fh;
- /* Poke in our control byte and
- port number. Hack, hack. */
- fh = (struct ec_framehdr *)skb->data;
- fh->cb = cb;
- fh->port = port;
- if (sock->type != SOCK_DGRAM) {
- skb_reset_tail_pointer(skb);
- skb->len = 0;
- }
- }
-
- /* Copy the data. Returns -EFAULT on error */
- err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
- skb->protocol = proto;
- skb->dev = dev;
- skb->priority = sk->sk_priority;
- if (err)
- goto out_free;
-
- err = -ENETDOWN;
- if (!(dev->flags & IFF_UP))
- goto out_free;
-
- /*
- * Now send it
- */
-
- dev_queue_xmit(skb);
- dev_put(dev);
- mutex_unlock(&econet_mutex);
- return len;
-
-out_free:
- kfree_skb(skb);
-out_unlock:
- if (dev)
- dev_put(dev);
-#else
- err = -EPROTOTYPE;
-#endif
- mutex_unlock(&econet_mutex);
-
- return err;
- }
-
-#ifdef CONFIG_ECONET_AUNUDP
- /* AUN virtual Econet. */
-
- if (udpsock == NULL) {
- mutex_unlock(&econet_mutex);
- return -ENETDOWN; /* No socket - can't send */
- }
-
- if (len > 32768) {
- err = -E2BIG;
- goto error;
- }
-
- /* Make up a UDP datagram and hand it off to some higher intellect. */
-
- memset(&udpdest, 0, sizeof(udpdest));
- udpdest.sin_family = AF_INET;
- udpdest.sin_port = htons(AUN_PORT);
-
- /* At the moment we use the stupid Acorn scheme of Econet address
- y.x maps to IP a.b.c.x. This should be replaced with something
- more flexible and more aware of subnet masks. */
- {
- struct in_device *idev;
- unsigned long network = 0;
-
- rcu_read_lock();
- idev = __in_dev_get_rcu(dev);
- if (idev) {
- if (idev->ifa_list)
- network = ntohl(idev->ifa_list->ifa_address) &
- 0xffffff00; /* !!! */
- }
- rcu_read_unlock();
- udpdest.sin_addr.s_addr = htonl(network | addr.station);
- }
-
- memset(&ah, 0, sizeof(ah));
- ah.port = port;
- ah.cb = cb & 0x7f;
- ah.code = 2; /* magic */
-
- /* tack our header on the front of the iovec */
- size = sizeof(struct aunhdr);
- iov[0].iov_base = (void *)&ah;
- iov[0].iov_len = size;
-
- userbuf = vmalloc(len);
- if (userbuf == NULL) {
- err = -ENOMEM;
- goto error;
- }
-
- iov[1].iov_base = userbuf;
- iov[1].iov_len = len;
- err = memcpy_fromiovec(userbuf, msg->msg_iov, len);
- if (err)
- goto error_free_buf;
-
- /* Get a skbuff (no data, just holds our cb information) */
- skb = sock_alloc_send_skb(sk, 0, msg->msg_flags & MSG_DONTWAIT, &err);
- if (skb == NULL)
- goto error_free_buf;
-
- eb = (struct ec_cb *)&skb->cb;
-
- eb->cookie = saddr->cookie;
- eb->timeout = 5 * HZ;
- eb->start = jiffies;
- ah.handle = aun_seq;
- eb->seq = (aun_seq++);
- eb->sec = *saddr;
-
- skb_queue_tail(&aun_queue, skb);
-
- udpmsg.msg_name = (void *)&udpdest;
- udpmsg.msg_namelen = sizeof(udpdest);
- udpmsg.msg_iov = &iov[0];
- udpmsg.msg_iovlen = 2;
- udpmsg.msg_control = NULL;
- udpmsg.msg_controllen = 0;
- udpmsg.msg_flags = 0;
-
- oldfs = get_fs();
- set_fs(KERNEL_DS); /* More privs :-) */
- err = sock_sendmsg(udpsock, &udpmsg, size);
- set_fs(oldfs);
-
-error_free_buf:
- vfree(userbuf);
-error:
-#else
- err = -EPROTOTYPE;
-#endif
- mutex_unlock(&econet_mutex);
-
- return err;
-}
-
-/*
- * Look up the address of a socket.
- */
-
-static int econet_getname(struct socket *sock, struct sockaddr *uaddr,
- int *uaddr_len, int peer)
-{
- struct sock *sk;
- struct econet_sock *eo;
- struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
-
- if (peer)
- return -EOPNOTSUPP;
-
- memset(sec, 0, sizeof(*sec));
- mutex_lock(&econet_mutex);
-
- sk = sock->sk;
- eo = ec_sk(sk);
-
- sec->sec_family = AF_ECONET;
- sec->port = eo->port;
- sec->addr.station = eo->station;
- sec->addr.net = eo->net;
-
- mutex_unlock(&econet_mutex);
-
- *uaddr_len = sizeof(*sec);
- return 0;
-}
-
-static void econet_destroy_timer(unsigned long data)
-{
- struct sock *sk = (struct sock *)data;
-
- if (!sk_has_allocations(sk)) {
- sk_free(sk);
- return;
- }
-
- sk->sk_timer.expires = jiffies + 10 * HZ;
- add_timer(&sk->sk_timer);
- pr_debug("econet: socket destroy delayed\n");
-}
-
-/*
- * Close an econet socket.
- */
-
-static int econet_release(struct socket *sock)
-{
- struct sock *sk;
-
- mutex_lock(&econet_mutex);
-
- sk = sock->sk;
- if (!sk)
- goto out_unlock;
-
- econet_remove_socket(&econet_sklist, sk);
-
- /*
- * Now the socket is dead. No more input will appear.
- */
-
- sk->sk_state_change(sk); /* It is useless. Just for sanity. */
-
- sock_orphan(sk);
-
- /* Purge queues */
-
- skb_queue_purge(&sk->sk_receive_queue);
-
- if (sk_has_allocations(sk)) {
- sk->sk_timer.data = (unsigned long)sk;
- sk->sk_timer.expires = jiffies + HZ;
- sk->sk_timer.function = econet_destroy_timer;
- add_timer(&sk->sk_timer);
-
- goto out_unlock;
- }
-
- sk_free(sk);
-
-out_unlock:
- mutex_unlock(&econet_mutex);
- return 0;
-}
-
-static struct proto econet_proto = {
- .name = "ECONET",
- .owner = THIS_MODULE,
- .obj_size = sizeof(struct econet_sock),
-};
-
-/*
- * Create an Econet socket
- */
-
-static int econet_create(struct net *net, struct socket *sock, int protocol,
- int kern)
-{
- struct sock *sk;
- struct econet_sock *eo;
- int err;
-
- if (!net_eq(net, &init_net))
- return -EAFNOSUPPORT;
-
- /* Econet only provides datagram services. */
- if (sock->type != SOCK_DGRAM)
- return -ESOCKTNOSUPPORT;
-
- sock->state = SS_UNCONNECTED;
-
- err = -ENOBUFS;
- sk = sk_alloc(net, PF_ECONET, GFP_KERNEL, &econet_proto);
- if (sk == NULL)
- goto out;
-
- sk->sk_reuse = SK_CAN_REUSE;
- sock->ops = &econet_ops;
- sock_init_data(sock, sk);
-
- eo = ec_sk(sk);
- sock_reset_flag(sk, SOCK_ZAPPED);
- sk->sk_family = PF_ECONET;
- eo->num = protocol;
-
- econet_insert_socket(&econet_sklist, sk);
- return 0;
-out:
- return err;
-}
-
-/*
- * Handle Econet specific ioctls
- */
-
-static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
-{
- struct ifreq ifr;
- struct ec_device *edev;
- struct net_device *dev;
- struct sockaddr_ec *sec;
- int err;
-
- /*
- * Fetch the caller's info block into kernel space
- */
-
- if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
- return -EFAULT;
-
- dev = dev_get_by_name(&init_net, ifr.ifr_name);
- if (dev == NULL)
- return -ENODEV;
-
- sec = (struct sockaddr_ec *)&ifr.ifr_addr;
-
- mutex_lock(&econet_mutex);
-
- err = 0;
- switch (cmd) {
- case SIOCSIFADDR:
- if (!capable(CAP_NET_ADMIN)) {
- err = -EPERM;
- break;
- }
-
- edev = dev->ec_ptr;
- if (edev == NULL) {
- /* Magic up a new one. */
- edev = kzalloc(sizeof(struct ec_device), GFP_KERNEL);
- if (edev == NULL) {
- err = -ENOMEM;
- break;
- }
- dev->ec_ptr = edev;
- } else
- net2dev_map[edev->net] = NULL;
- edev->station = sec->addr.station;
- edev->net = sec->addr.net;
- net2dev_map[sec->addr.net] = dev;
- if (!net2dev_map[0])
- net2dev_map[0] = dev;
- break;
-
- case SIOCGIFADDR:
- edev = dev->ec_ptr;
- if (edev == NULL) {
- err = -ENODEV;
- break;
- }
- memset(sec, 0, sizeof(struct sockaddr_ec));
- sec->addr.station = edev->station;
- sec->addr.net = edev->net;
- sec->sec_family = AF_ECONET;
- dev_put(dev);
- if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
- err = -EFAULT;
- break;
-
- default:
- err = -EINVAL;
- break;
- }
-
- mutex_unlock(&econet_mutex);
-
- dev_put(dev);
-
- return err;
-}
-
-/*
- * Handle generic ioctls
- */
-
-static int econet_ioctl(struct socket *sock, unsigned int cmd,
- unsigned long arg)
-{
- struct sock *sk = sock->sk;
- void __user *argp = (void __user *)arg;
-
- switch (cmd) {
- case SIOCGSTAMP:
- return sock_get_timestamp(sk, argp);
-
- case SIOCGSTAMPNS:
- return sock_get_timestampns(sk, argp);
-
- case SIOCSIFADDR:
- case SIOCGIFADDR:
- return ec_dev_ioctl(sock, cmd, argp);
-
- }
-
- return -ENOIOCTLCMD;
-}
-
-static const struct net_proto_family econet_family_ops = {
- .family = PF_ECONET,
- .create = econet_create,
- .owner = THIS_MODULE,
-};
-
-static const struct proto_ops econet_ops = {
- .family = PF_ECONET,
- .owner = THIS_MODULE,
- .release = econet_release,
- .bind = econet_bind,
- .connect = sock_no_connect,
- .socketpair = sock_no_socketpair,
- .accept = sock_no_accept,
- .getname = econet_getname,
- .poll = datagram_poll,
- .ioctl = econet_ioctl,
- .listen = sock_no_listen,
- .shutdown = sock_no_shutdown,
- .setsockopt = sock_no_setsockopt,
- .getsockopt = sock_no_getsockopt,
- .sendmsg = econet_sendmsg,
- .recvmsg = econet_recvmsg,
- .mmap = sock_no_mmap,
- .sendpage = sock_no_sendpage,
-};
-
-#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)
-/*
- * Find the listening socket, if any, for the given data.
- */
-
-static struct sock *ec_listening_socket(unsigned char port, unsigned char
- station, unsigned char net)
-{
- struct sock *sk;
- struct hlist_node *node;
-
- spin_lock(&econet_lock);
- sk_for_each(sk, node, &econet_sklist) {
- struct econet_sock *opt = ec_sk(sk);
- if ((opt->port == port || opt->port == 0) &&
- (opt->station == station || opt->station == 0) &&
- (opt->net == net || opt->net == 0)) {
- sock_hold(sk);
- goto found;
- }
- }
- sk = NULL;
-found:
- spin_unlock(&econet_lock);
- return sk;
-}
-
-/*
- * Queue a received packet for a socket.
- */
-
-static int ec_queue_packet(struct sock *sk, struct sk_buff *skb,
- unsigned char stn, unsigned char net,
- unsigned char cb, unsigned char port)
-{
- struct ec_cb *eb = (struct ec_cb *)&skb->cb;
- struct sockaddr_ec *sec = (struct sockaddr_ec *)&eb->sec;
-
- memset(sec, 0, sizeof(struct sockaddr_ec));
- sec->sec_family = AF_ECONET;
- sec->type = ECTYPE_PACKET_RECEIVED;
- sec->port = port;
- sec->cb = cb;
- sec->addr.net = net;
- sec->addr.station = stn;
-
- return sock_queue_rcv_skb(sk, skb);
-}
-#endif
-
-#ifdef CONFIG_ECONET_AUNUDP
-/*
- * Send an AUN protocol response.
- */
-
-static void aun_send_response(__u32 addr, unsigned long seq, int code, int cb)
-{
- struct sockaddr_in sin = {
- .sin_family = AF_INET,
- .sin_port = htons(AUN_PORT),
- .sin_addr = {.s_addr = addr}
- };
- struct aunhdr ah = {.code = code, .cb = cb, .handle = seq};
- struct kvec iov = {.iov_base = (void *)&ah, .iov_len = sizeof(ah)};
- struct msghdr udpmsg;
-
- udpmsg.msg_name = (void *)&sin;
- udpmsg.msg_namelen = sizeof(sin);
- udpmsg.msg_control = NULL;
- udpmsg.msg_controllen = 0;
- udpmsg.msg_flags = 0;
-
- kernel_sendmsg(udpsock, &udpmsg, &iov, 1, sizeof(ah));
-}
-
-
-/*
- * Handle incoming AUN packets. Work out if anybody wants them,
- * and send positive or negative acknowledgements as appropriate.
- */
-
-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;
-
- if (dst)
- edev = dst->dev->ec_ptr;
-
- if (!edev)
- goto bad;
-
- sk = ec_listening_socket(ah->port, stn, edev->net);
- if (sk == NULL)
- goto bad; /* Nobody wants it */
-
- newskb = alloc_skb((len - sizeof(struct aunhdr) + 15) & ~15,
- GFP_ATOMIC);
- if (newskb == NULL) {
- pr_debug("AUN: memory squeeze, dropping packet\n");
- /* Send nack and hope sender tries again */
- goto bad;
- }
-
- memcpy(skb_put(newskb, len - sizeof(struct aunhdr)), (void *)(ah + 1),
- len - sizeof(struct aunhdr));
-
- if (ec_queue_packet(sk, newskb, stn, edev->net, ah->cb, ah->port)) {
- /* Socket is bankrupt. */
- kfree_skb(newskb);
- goto bad;
- }
-
- aun_send_response(ip->saddr, ah->handle, 3, 0);
- sock_put(sk);
- return;
-
-bad:
- aun_send_response(ip->saddr, ah->handle, 4, 0);
- if (sk)
- sock_put(sk);
-}
-
-/*
- * Handle incoming AUN transmit acknowledgements. If the sequence
- * number matches something in our backlog then kill it and tell
- * the user. If the remote took too long to reply then we may have
- * dropped the packet already.
- */
-
-static void aun_tx_ack(unsigned long seq, int result)
-{
- struct sk_buff *skb;
- unsigned long flags;
- struct ec_cb *eb;
-
- spin_lock_irqsave(&aun_queue_lock, flags);
- skb_queue_walk(&aun_queue, skb) {
- eb = (struct ec_cb *)&skb->cb;
- if (eb->seq == seq)
- goto foundit;
- }
- spin_unlock_irqrestore(&aun_queue_lock, flags);
- pr_debug("AUN: unknown sequence %ld\n", seq);
- return;
-
-foundit:
- tx_result(skb->sk, eb->cookie, result);
- skb_unlink(skb, &aun_queue);
- spin_unlock_irqrestore(&aun_queue_lock, flags);
- kfree_skb(skb);
-}
-
-/*
- * Deal with received AUN frames - sort out what type of thing it is
- * and hand it to the right function.
- */
-
-static void aun_data_available(struct sock *sk, int slen)
-{
- int err;
- struct sk_buff *skb;
- unsigned char *data;
- struct aunhdr *ah;
- size_t len;
-
- while ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) {
- if (err == -EAGAIN) {
- pr_err("AUN: no data available?!\n");
- return;
- }
- pr_debug("AUN: recvfrom() error %d\n", -err);
- }
-
- data = skb_transport_header(skb) + sizeof(struct udphdr);
- ah = (struct aunhdr *)data;
- len = skb->len - sizeof(struct udphdr);
-
- switch (ah->code) {
- case 2:
- aun_incoming(skb, ah, len);
- break;
- case 3:
- aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_OK);
- break;
- case 4:
- aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_NOT_LISTENING);
- break;
- default:
- pr_debug("AUN: unknown packet type: %d\n", data[0]);
- }
-
- skb_free_datagram(sk, skb);
-}
-
-/*
- * Called by the timer to manage the AUN transmit queue. If a packet
- * was sent to a dead or nonexistent host then we will never get an
- * acknowledgement back. After a few seconds we need to spot this and
- * drop the packet.
- */
-
-static void ab_cleanup(unsigned long h)
-{
- struct sk_buff *skb, *n;
- unsigned long flags;
-
- spin_lock_irqsave(&aun_queue_lock, flags);
- skb_queue_walk_safe(&aun_queue, skb, n) {
- struct ec_cb *eb = (struct ec_cb *)&skb->cb;
- if ((jiffies - eb->start) > eb->timeout) {
- tx_result(skb->sk, eb->cookie,
- ECTYPE_TRANSMIT_NOT_PRESENT);
- skb_unlink(skb, &aun_queue);
- kfree_skb(skb);
- }
- }
- spin_unlock_irqrestore(&aun_queue_lock, flags);
-
- mod_timer(&ab_cleanup_timer, jiffies + (HZ * 2));
-}
-
-static int __init aun_udp_initialise(void)
-{
- int error;
- struct sockaddr_in sin;
-
- skb_queue_head_init(&aun_queue);
- setup_timer(&ab_cleanup_timer, ab_cleanup, 0);
- ab_cleanup_timer.expires = jiffies + (HZ * 2);
- add_timer(&ab_cleanup_timer);
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_port = htons(AUN_PORT);
-
- /* We can count ourselves lucky Acorn machines are too dim to
- speak IPv6. :-) */
- error = sock_create_kern(PF_INET, SOCK_DGRAM, 0, &udpsock);
- if (error < 0) {
- pr_err("AUN: socket error %d\n", -error);
- return error;
- }
-
- udpsock->sk->sk_reuse = SK_CAN_REUSE;
- udpsock->sk->sk_allocation = GFP_ATOMIC; /* we're going to call it
- from interrupts */
-
- error = udpsock->ops->bind(udpsock, (struct sockaddr *)&sin,
- sizeof(sin));
- if (error < 0) {
- pr_err("AUN: bind error %d\n", -error);
- goto release;
- }
-
- udpsock->sk->sk_data_ready = aun_data_available;
-
- return 0;
-
-release:
- sock_release(udpsock);
- udpsock = NULL;
- return error;
-}
-#endif
-
-#ifdef CONFIG_ECONET_NATIVE
-
-/*
- * Receive an Econet frame from a device.
- */
-
-static int econet_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt, struct net_device *orig_dev)
-{
- struct ec_framehdr *hdr;
- struct sock *sk = NULL;
- struct ec_device *edev = dev->ec_ptr;
-
- if (!net_eq(dev_net(dev), &init_net))
- goto drop;
-
- if (skb->pkt_type == PACKET_OTHERHOST)
- goto drop;
-
- if (!edev)
- goto drop;
-
- skb = skb_share_check(skb, GFP_ATOMIC);
- if (skb == NULL)
- return NET_RX_DROP;
-
- if (!pskb_may_pull(skb, sizeof(struct ec_framehdr)))
- goto drop;
-
- hdr = (struct ec_framehdr *)skb->data;
-
- /* First check for encapsulated IP */
- if (hdr->port == EC_PORT_IP) {
- skb->protocol = htons(ETH_P_IP);
- skb_pull(skb, sizeof(struct ec_framehdr));
- netif_rx(skb);
- return NET_RX_SUCCESS;
- }
-
- sk = ec_listening_socket(hdr->port, hdr->src_stn, hdr->src_net);
- if (!sk)
- goto drop;
-
- if (ec_queue_packet(sk, skb, edev->net, hdr->src_stn, hdr->cb,
- hdr->port))
- goto drop;
- sock_put(sk);
- return NET_RX_SUCCESS;
-
-drop:
- if (sk)
- sock_put(sk);
- kfree_skb(skb);
- return NET_RX_DROP;
-}
-
-static struct packet_type econet_packet_type __read_mostly = {
- .type = cpu_to_be16(ETH_P_ECONET),
- .func = econet_rcv,
-};
-
-static void econet_hw_initialise(void)
-{
- dev_add_pack(&econet_packet_type);
-}
-
-#endif
-
-static int econet_notifier(struct notifier_block *this, unsigned long msg,
- void *data)
-{
- struct net_device *dev = data;
- struct ec_device *edev;
-
- if (!net_eq(dev_net(dev), &init_net))
- return NOTIFY_DONE;
-
- switch (msg) {
- case NETDEV_UNREGISTER:
- /* A device has gone down - kill any data we hold for it. */
- edev = dev->ec_ptr;
- if (edev) {
- if (net2dev_map[0] == dev)
- net2dev_map[0] = NULL;
- net2dev_map[edev->net] = NULL;
- kfree(edev);
- dev->ec_ptr = NULL;
- }
- break;
- }
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block econet_netdev_notifier = {
- .notifier_call = econet_notifier,
-};
-
-static void __exit econet_proto_exit(void)
-{
-#ifdef CONFIG_ECONET_AUNUDP
- del_timer(&ab_cleanup_timer);
- if (udpsock)
- sock_release(udpsock);
-#endif
- unregister_netdevice_notifier(&econet_netdev_notifier);
-#ifdef CONFIG_ECONET_NATIVE
- dev_remove_pack(&econet_packet_type);
-#endif
- sock_unregister(econet_family_ops.family);
- proto_unregister(&econet_proto);
-}
-
-static int __init econet_proto_init(void)
-{
- int err = proto_register(&econet_proto, 0);
-
- if (err != 0)
- goto out;
- sock_register(&econet_family_ops);
-#ifdef CONFIG_ECONET_AUNUDP
- aun_udp_initialise();
-#endif
-#ifdef CONFIG_ECONET_NATIVE
- econet_hw_initialise();
-#endif
- register_netdevice_notifier(&econet_netdev_notifier);
-out:
- return err;
-}
-
-module_init(econet_proto_init);
-module_exit(econet_proto_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_NETPROTO(PF_ECONET);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 9f9bd139335f..9dbd3dd6022d 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -148,17 +148,17 @@ static unsigned int ip4_hashfn(struct inet_frag_queue *q)
return ipqhashfn(ipq->id, ipq->saddr, ipq->daddr, ipq->protocol);
}
-static int ip4_frag_match(struct inet_frag_queue *q, void *a)
+static bool ip4_frag_match(struct inet_frag_queue *q, void *a)
{
struct ipq *qp;
struct ip4_create_arg *arg = a;
qp = container_of(q, struct ipq, q);
return qp->id == arg->iph->id &&
- qp->saddr == arg->iph->saddr &&
- qp->daddr == arg->iph->daddr &&
- qp->protocol == arg->iph->protocol &&
- qp->user == arg->user;
+ qp->saddr == arg->iph->saddr &&
+ qp->daddr == arg->iph->daddr &&
+ qp->protocol == arg->iph->protocol &&
+ qp->user == arg->user;
}
/* Memory Tracking Functions. */
@@ -545,6 +545,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
int len;
int ihlen;
int err;
+ int sum_truesize;
u8 ecn;
ipq_kill(qp);
@@ -611,19 +612,32 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
atomic_add(clone->truesize, &qp->q.net->mem);
}
- skb_shinfo(head)->frag_list = head->next;
skb_push(head, head->data - skb_network_header(head));
- for (fp=head->next; fp; fp = fp->next) {
- head->data_len += fp->len;
- head->len += fp->len;
+ sum_truesize = head->truesize;
+ for (fp = head->next; fp;) {
+ bool headstolen;
+ int delta;
+ struct sk_buff *next = fp->next;
+
+ sum_truesize += fp->truesize;
if (head->ip_summed != fp->ip_summed)
head->ip_summed = CHECKSUM_NONE;
else if (head->ip_summed == CHECKSUM_COMPLETE)
head->csum = csum_add(head->csum, fp->csum);
- head->truesize += fp->truesize;
+
+ if (skb_try_coalesce(head, fp, &headstolen, &delta)) {
+ kfree_skb_partial(fp, headstolen);
+ } else {
+ if (!skb_shinfo(head)->frag_list)
+ skb_shinfo(head)->frag_list = fp;
+ head->data_len += fp->len;
+ head->len += fp->len;
+ head->truesize += fp->truesize;
+ }
+ fp = next;
}
- atomic_sub(head->truesize, &qp->q.net->mem);
+ atomic_sub(sum_truesize, &qp->q.net->mem);
head->next = NULL;
head->dev = dev;
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 430015010e57..67e8a6b086ea 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -1621,11 +1621,13 @@ static int __init ip_auto_config_setup(char *addrs)
return 1;
}
+__setup("ip=", ip_auto_config_setup);
static int __init nfsaddrs_config_setup(char *addrs)
{
return ip_auto_config_setup(addrs);
}
+__setup("nfsaddrs=", nfsaddrs_config_setup);
static int __init vendor_class_identifier_setup(char *addrs)
{
@@ -1636,7 +1638,4 @@ static int __init vendor_class_identifier_setup(char *addrs)
vendor_class_identifier);
return 1;
}
-
-__setup("ip=", ip_auto_config_setup);
-__setup("nfsaddrs=", nfsaddrs_config_setup);
__setup("dhcpclass=", vendor_class_identifier_setup);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 76e5880cdb07..ffcb3b016843 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3408,9 +3408,15 @@ struct ip_rt_acct __percpu *ip_rt_acct __read_mostly;
static __initdata unsigned long rhash_entries;
static int __init set_rhash_entries(char *str)
{
+ ssize_t ret;
+
if (!str)
return 0;
- rhash_entries = simple_strtoul(str, &str, 0);
+
+ ret = kstrtoul(str, 0, &rhash_entries);
+ if (ret)
+ return 0;
+
return 1;
}
__setup("rhash_entries=", set_rhash_entries);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 63ddaee7209f..bb485fcb077e 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -917,8 +917,7 @@ new_segment:
wait_for_sndbuf:
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
wait_for_memory:
- if (copied)
- tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
+ tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
goto do_error;
@@ -3462,9 +3461,15 @@ extern struct tcp_congestion_ops tcp_reno;
static __initdata unsigned long thash_entries;
static int __init set_thash_entries(char *str)
{
+ ssize_t ret;
+
if (!str)
return 0;
- thash_entries = simple_strtoul(str, &str, 0);
+
+ ret = kstrtoul(str, 0, &thash_entries);
+ if (ret)
+ return 0;
+
return 1;
}
__setup("thash_entries=", set_thash_entries);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index b961ef54b17d..cfa2aa128342 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4549,84 +4549,23 @@ static bool tcp_try_coalesce(struct sock *sk,
struct sk_buff *from,
bool *fragstolen)
{
- int i, delta, len = from->len;
+ int delta;
*fragstolen = false;
- if (tcp_hdr(from)->fin || skb_cloned(to))
+ if (tcp_hdr(from)->fin)
return false;
-
- if (len <= skb_tailroom(to)) {
- BUG_ON(skb_copy_bits(from, 0, skb_put(to, len), len));
- goto merge;
- }
-
- if (skb_has_frag_list(to) || skb_has_frag_list(from))
+ if (!skb_try_coalesce(to, from, fragstolen, &delta))
return false;
- if (skb_headlen(from) != 0) {
- struct page *page;
- unsigned int offset;
-
- if (skb_shinfo(to)->nr_frags +
- skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS)
- return false;
-
- if (skb_head_is_locked(from))
- return false;
-
- delta = from->truesize - SKB_DATA_ALIGN(sizeof(struct sk_buff));
-
- page = virt_to_head_page(from->head);
- offset = from->data - (unsigned char *)page_address(page);
-
- skb_fill_page_desc(to, skb_shinfo(to)->nr_frags,
- page, offset, skb_headlen(from));
- *fragstolen = true;
- } else {
- if (skb_shinfo(to)->nr_frags +
- skb_shinfo(from)->nr_frags > MAX_SKB_FRAGS)
- return false;
-
- delta = from->truesize -
- SKB_TRUESIZE(skb_end_pointer(from) - from->head);
- }
-
- WARN_ON_ONCE(delta < len);
-
- memcpy(skb_shinfo(to)->frags + skb_shinfo(to)->nr_frags,
- skb_shinfo(from)->frags,
- skb_shinfo(from)->nr_frags * sizeof(skb_frag_t));
- skb_shinfo(to)->nr_frags += skb_shinfo(from)->nr_frags;
-
- if (!skb_cloned(from))
- skb_shinfo(from)->nr_frags = 0;
-
- /* if the skb is cloned this does nothing since we set nr_frags to 0 */
- for (i = 0; i < skb_shinfo(from)->nr_frags; i++)
- skb_frag_ref(from, i);
-
- to->truesize += delta;
atomic_add(delta, &sk->sk_rmem_alloc);
sk_mem_charge(sk, delta);
- to->len += len;
- to->data_len += len;
-
-merge:
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRCVCOALESCE);
TCP_SKB_CB(to)->end_seq = TCP_SKB_CB(from)->end_seq;
TCP_SKB_CB(to)->ack_seq = TCP_SKB_CB(from)->ack_seq;
return true;
}
-static void kfree_skb_partial(struct sk_buff *skb, bool head_stolen)
-{
- if (head_stolen)
- kmem_cache_free(skbuff_head_cache, skb);
- else
- __kfree_skb(skb);
-}
-
static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb)
{
struct tcp_sock *tp = tcp_sk(sk);
diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c
index e795272fbe9e..151703791bb0 100644
--- a/net/ipv4/tcp_memcontrol.c
+++ b/net/ipv4/tcp_memcontrol.c
@@ -6,37 +6,6 @@
#include <linux/memcontrol.h>
#include <linux/module.h>
-static u64 tcp_cgroup_read(struct cgroup *cont, struct cftype *cft);
-static int tcp_cgroup_write(struct cgroup *cont, struct cftype *cft,
- const char *buffer);
-static int tcp_cgroup_reset(struct cgroup *cont, unsigned int event);
-
-static struct cftype tcp_files[] = {
- {
- .name = "kmem.tcp.limit_in_bytes",
- .write_string = tcp_cgroup_write,
- .read_u64 = tcp_cgroup_read,
- .private = RES_LIMIT,
- },
- {
- .name = "kmem.tcp.usage_in_bytes",
- .read_u64 = tcp_cgroup_read,
- .private = RES_USAGE,
- },
- {
- .name = "kmem.tcp.failcnt",
- .private = RES_FAILCNT,
- .trigger = tcp_cgroup_reset,
- .read_u64 = tcp_cgroup_read,
- },
- {
- .name = "kmem.tcp.max_usage_in_bytes",
- .private = RES_MAX_USAGE,
- .trigger = tcp_cgroup_reset,
- .read_u64 = tcp_cgroup_read,
- },
-};
-
static inline struct tcp_memcontrol *tcp_from_cgproto(struct cg_proto *cg_proto)
{
return container_of(cg_proto, struct tcp_memcontrol, cg_proto);
@@ -49,7 +18,7 @@ static void memcg_tcp_enter_memory_pressure(struct sock *sk)
}
EXPORT_SYMBOL(memcg_tcp_enter_memory_pressure);
-int tcp_init_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss)
+int tcp_init_cgroup(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
{
/*
* The root cgroup does not use res_counters, but rather,
@@ -59,13 +28,12 @@ int tcp_init_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss)
struct res_counter *res_parent = NULL;
struct cg_proto *cg_proto, *parent_cg;
struct tcp_memcontrol *tcp;
- struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
struct mem_cgroup *parent = parent_mem_cgroup(memcg);
struct net *net = current->nsproxy->net_ns;
cg_proto = tcp_prot.proto_cgroup(memcg);
if (!cg_proto)
- goto create_files;
+ return 0;
tcp = tcp_from_cgproto(cg_proto);
@@ -88,15 +56,12 @@ int tcp_init_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss)
cg_proto->sockets_allocated = &tcp->tcp_sockets_allocated;
cg_proto->memcg = memcg;
-create_files:
- return cgroup_add_files(cgrp, ss, tcp_files,
- ARRAY_SIZE(tcp_files));
+ return 0;
}
EXPORT_SYMBOL(tcp_init_cgroup);
-void tcp_destroy_cgroup(struct cgroup *cgrp)
+void tcp_destroy_cgroup(struct mem_cgroup *memcg)
{
- struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
struct cg_proto *cg_proto;
struct tcp_memcontrol *tcp;
u64 val;
@@ -270,3 +235,37 @@ void tcp_prot_mem(struct mem_cgroup *memcg, long val, int idx)
tcp->tcp_prot_mem[idx] = val;
}
+
+static struct cftype tcp_files[] = {
+ {
+ .name = "kmem.tcp.limit_in_bytes",
+ .write_string = tcp_cgroup_write,
+ .read_u64 = tcp_cgroup_read,
+ .private = RES_LIMIT,
+ },
+ {
+ .name = "kmem.tcp.usage_in_bytes",
+ .read_u64 = tcp_cgroup_read,
+ .private = RES_USAGE,
+ },
+ {
+ .name = "kmem.tcp.failcnt",
+ .private = RES_FAILCNT,
+ .trigger = tcp_cgroup_reset,
+ .read_u64 = tcp_cgroup_read,
+ },
+ {
+ .name = "kmem.tcp.max_usage_in_bytes",
+ .private = RES_MAX_USAGE,
+ .trigger = tcp_cgroup_reset,
+ .read_u64 = tcp_cgroup_read,
+ },
+ { } /* terminate */
+};
+
+static int __init tcp_memcontrol_init(void)
+{
+ WARN_ON(cgroup_add_cftypes(&mem_cgroup_subsys, tcp_files));
+ return 0;
+}
+__initcall(tcp_memcontrol_init);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 279fd0846302..609397ee78fb 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2173,9 +2173,15 @@ void udp4_proc_exit(void)
static __initdata unsigned long uhash_entries;
static int __init set_uhash_entries(char *str)
{
+ ssize_t ret;
+
if (!str)
return 0;
- uhash_entries = simple_strtoul(str, &str, 0);
+
+ ret = kstrtoul(str, 0, &uhash_entries);
+ if (ret)
+ return 0;
+
if (uhash_entries && uhash_entries < UDP_HTABLE_SIZE_MIN)
uhash_entries = UDP_HTABLE_SIZE_MIN;
return 1;
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
index 95aea16b8b6f..eb6a63632d3c 100644
--- a/net/ipv6/addrlabel.c
+++ b/net/ipv6/addrlabel.c
@@ -129,7 +129,7 @@ static void ip6addrlbl_free_rcu(struct rcu_head *h)
ip6addrlbl_free(container_of(h, struct ip6addrlbl_entry, rcu));
}
-static inline int ip6addrlbl_hold(struct ip6addrlbl_entry *p)
+static bool ip6addrlbl_hold(struct ip6addrlbl_entry *p)
{
return atomic_inc_not_zero(&p->refcnt);
}
@@ -141,20 +141,20 @@ static inline void ip6addrlbl_put(struct ip6addrlbl_entry *p)
}
/* Find label */
-static int __ip6addrlbl_match(struct net *net,
- struct ip6addrlbl_entry *p,
- const struct in6_addr *addr,
- int addrtype, int ifindex)
+static bool __ip6addrlbl_match(struct net *net,
+ const struct ip6addrlbl_entry *p,
+ const struct in6_addr *addr,
+ int addrtype, int ifindex)
{
if (!net_eq(ip6addrlbl_net(p), net))
- return 0;
+ return false;
if (p->ifindex && p->ifindex != ifindex)
- return 0;
+ return false;
if (p->addrtype && p->addrtype != addrtype)
- return 0;
+ return false;
if (!ipv6_prefix_equal(addr, &p->prefix, p->prefixlen))
- return 0;
- return 1;
+ return false;
+ return true;
}
static struct ip6addrlbl_entry *__ipv6_addr_label(struct net *net,
@@ -456,8 +456,8 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh,
return err;
}
-static inline void ip6addrlbl_putmsg(struct nlmsghdr *nlh,
- int prefixlen, int ifindex, u32 lseq)
+static void ip6addrlbl_putmsg(struct nlmsghdr *nlh,
+ int prefixlen, int ifindex, u32 lseq)
{
struct ifaddrlblmsg *ifal = nlmsg_data(nlh);
ifal->ifal_family = AF_INET6;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 138d4986c327..e22e6d88bac6 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -678,10 +678,10 @@ int inet6_sk_rebuild_header(struct sock *sk)
}
EXPORT_SYMBOL_GPL(inet6_sk_rebuild_header);
-int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
+bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb)
{
- struct ipv6_pinfo *np = inet6_sk(sk);
- struct inet6_skb_parm *opt = IP6CB(skb);
+ const struct ipv6_pinfo *np = inet6_sk(sk);
+ const struct inet6_skb_parm *opt = IP6CB(skb);
if (np->rxopt.all) {
if ((opt->hop && (np->rxopt.bits.hopopts ||
@@ -693,9 +693,9 @@ int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
np->rxopt.bits.osrcrt)) ||
((opt->dst1 || opt->dst0) &&
(np->rxopt.bits.dstopts || np->rxopt.bits.odstopts)))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
EXPORT_SYMBOL_GPL(ipv6_opt_accepted);
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 5d32e7a93b26..f1a4a2c28ed3 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -113,7 +113,7 @@ static inline struct scatterlist *ah_req_sg(struct crypto_ahash *ahash,
__alignof__(struct scatterlist));
}
-static int zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
+static bool zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
{
u8 *opt = (u8 *)opthdr;
int len = ipv6_optlen(opthdr);
@@ -145,10 +145,10 @@ static int zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
len -= optlen;
}
if (len == 0)
- return 1;
+ return true;
bad:
- return 0;
+ return false;
}
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index db00d27ffb16..cdf02be5f191 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -342,7 +342,7 @@ static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr)
* check if the interface has this anycast address
* called with rcu_read_lock()
*/
-static int ipv6_chk_acast_dev(struct net_device *dev, const struct in6_addr *addr)
+static bool ipv6_chk_acast_dev(struct net_device *dev, const struct in6_addr *addr)
{
struct inet6_dev *idev;
struct ifacaddr6 *aca;
@@ -356,16 +356,16 @@ static int ipv6_chk_acast_dev(struct net_device *dev, const struct in6_addr *add
read_unlock_bh(&idev->lock);
return aca != NULL;
}
- return 0;
+ return false;
}
/*
* check if given interface (or any, if dev==0) has this anycast address
*/
-int ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
- const struct in6_addr *addr)
+bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
+ const struct in6_addr *addr)
{
- int found = 0;
+ bool found = false;
rcu_read_lock();
if (dev)
@@ -373,7 +373,7 @@ int ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
else
for_each_netdev_rcu(net, dev)
if (ipv6_chk_acast_dev(dev, addr)) {
- found = 1;
+ found = true;
break;
}
rcu_read_unlock();
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index b8b61ac88bc2..be2b67d631e5 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -34,9 +34,9 @@
#include <linux/errqueue.h>
#include <asm/uaccess.h>
-static inline int ipv6_mapped_addr_any(const struct in6_addr *a)
+static bool ipv6_mapped_addr_any(const struct in6_addr *a)
{
- return (ipv6_addr_v4mapped(a) && (a->s6_addr32[3] == 0));
+ return ipv6_addr_v4mapped(a) && (a->s6_addr32[3] == 0);
}
int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index a3cded6a1997..6447dc49429f 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -96,14 +96,14 @@ EXPORT_SYMBOL_GPL(ipv6_find_tlv);
/*
* Parsing tlv encoded headers.
*
- * Parsing function "func" returns 1, if parsing succeed
- * and 0, if it failed.
+ * Parsing function "func" returns true, if parsing succeed
+ * and false, if it failed.
* It MUST NOT touch skb->h.
*/
struct tlvtype_proc {
int type;
- int (*func)(struct sk_buff *skb, int offset);
+ bool (*func)(struct sk_buff *skb, int offset);
};
/*********************
@@ -112,11 +112,11 @@ struct tlvtype_proc {
/* An unknown option is detected, decide what to do */
-static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
+static bool ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
{
switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) {
case 0: /* ignore */
- return 1;
+ return true;
case 1: /* drop packet */
break;
@@ -129,21 +129,22 @@ static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
break;
case 2: /* send ICMP PARM PROB regardless and drop packet */
icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
- return 0;
+ return false;
}
kfree_skb(skb);
- return 0;
+ return false;
}
/* Parse tlv encoded option header (hop-by-hop or destination) */
-static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
+static bool ip6_parse_tlv(const struct tlvtype_proc *procs, struct sk_buff *skb)
{
- struct tlvtype_proc *curr;
+ const struct tlvtype_proc *curr;
const unsigned char *nh = skb_network_header(skb);
int off = skb_network_header_len(skb);
int len = (skb_transport_header(skb)[1] + 1) << 3;
+ int padlen = 0;
if (skb_transport_offset(skb) + len > skb_headlen(skb))
goto bad;
@@ -158,6 +159,9 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
switch (nh[off]) {
case IPV6_TLV_PAD1:
optlen = 1;
+ padlen++;
+ if (padlen > 7)
+ goto bad;
break;
case IPV6_TLV_PADN:
@@ -166,7 +170,8 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
* of 8. 7 is therefore the highest valid value.
* See also RFC 4942, Section 2.1.9.5.
*/
- if (optlen > 7)
+ padlen += optlen;
+ if (padlen > 7)
goto bad;
/* RFC 4942 recommends receiving hosts to
* actively check PadN payload to contain
@@ -186,25 +191,33 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
/* type specific length/alignment
checks will be performed in the
func(). */
- if (curr->func(skb, off) == 0)
- return 0;
+ if (curr->func(skb, off) == false)
+ return false;
break;
}
}
if (curr->type < 0) {
if (ip6_tlvopt_unknown(skb, off) == 0)
- return 0;
+ return false;
}
+ padlen = 0;
break;
}
off += optlen;
len -= optlen;
}
+ /* This case will not be caught by above check since its padding
+ * length is smaller than 7:
+ * 1 byte NH + 1 byte Length + 6 bytes Padding
+ */
+ if ((padlen == 6) && ((off - skb_network_header_len(skb)) == 8))
+ goto bad;
+
if (len == 0)
- return 1;
+ return true;
bad:
kfree_skb(skb);
- return 0;
+ return false;
}
/*****************************
@@ -212,7 +225,7 @@ bad:
*****************************/
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-static int ipv6_dest_hao(struct sk_buff *skb, int optoff)
+static bool ipv6_dest_hao(struct sk_buff *skb, int optoff)
{
struct ipv6_destopt_hao *hao;
struct inet6_skb_parm *opt = IP6CB(skb);
@@ -266,15 +279,15 @@ static int ipv6_dest_hao(struct sk_buff *skb, int optoff)
if (skb->tstamp.tv64 == 0)
__net_timestamp(skb);
- return 1;
+ return true;
discard:
kfree_skb(skb);
- return 0;
+ return false;
}
#endif
-static struct tlvtype_proc tlvprocdestopt_lst[] = {
+static const struct tlvtype_proc tlvprocdestopt_lst[] = {
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
{
.type = IPV6_TLV_HAO,
@@ -579,23 +592,23 @@ static inline struct net *ipv6_skb_net(struct sk_buff *skb)
/* Router Alert as of RFC 2711 */
-static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
+static bool ipv6_hop_ra(struct sk_buff *skb, int optoff)
{
const unsigned char *nh = skb_network_header(skb);
if (nh[optoff + 1] == 2) {
IP6CB(skb)->ra = optoff;
- return 1;
+ return true;
}
LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
nh[optoff + 1]);
kfree_skb(skb);
- return 0;
+ return false;
}
/* Jumbo payload */
-static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
+static bool ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
{
const unsigned char *nh = skb_network_header(skb);
struct net *net = ipv6_skb_net(skb);
@@ -614,13 +627,13 @@ static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
- return 0;
+ return false;
}
if (ipv6_hdr(skb)->payload_len) {
IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
- return 0;
+ return false;
}
if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
@@ -632,14 +645,14 @@ static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
goto drop;
- return 1;
+ return true;
drop:
kfree_skb(skb);
- return 0;
+ return false;
}
-static struct tlvtype_proc tlvprochopopt_lst[] = {
+static const struct tlvtype_proc tlvprochopopt_lst[] = {
{
.type = IPV6_TLV_ROUTERALERT,
.func = ipv6_hop_ra,
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index 7b1a884634d5..f73d59a14131 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -9,7 +9,7 @@
* find out if nexthdr is a well-known extension header or a protocol
*/
-int ipv6_ext_hdr(u8 nexthdr)
+bool ipv6_ext_hdr(u8 nexthdr)
{
/*
* find out if nexthdr is an extension header or a protocol
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 23c56ce9e86b..091a2971c7b7 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -131,7 +131,7 @@ void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos)
* --ANK (980726)
*/
-static int is_ineligible(struct sk_buff *skb)
+static bool is_ineligible(const struct sk_buff *skb)
{
int ptr = (u8 *)(ipv6_hdr(skb) + 1) - skb->data;
int len = skb->len - ptr;
@@ -139,11 +139,11 @@ static int is_ineligible(struct sk_buff *skb)
__be16 frag_off;
if (len < 0)
- return 1;
+ return true;
ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, &frag_off);
if (ptr < 0)
- return 0;
+ return false;
if (nexthdr == IPPROTO_ICMPV6) {
u8 _type, *tp;
tp = skb_header_pointer(skb,
@@ -151,9 +151,9 @@ static int is_ineligible(struct sk_buff *skb)
sizeof(_type), &_type);
if (tp == NULL ||
!(*tp & ICMPV6_INFOMSG_MASK))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/*
@@ -208,14 +208,14 @@ static inline bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
* highest-order two bits set to 10
*/
-static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset)
+static bool opt_unrec(struct sk_buff *skb, __u32 offset)
{
u8 _optval, *op;
offset += skb_network_offset(skb);
op = skb_header_pointer(skb, offset, sizeof(_optval), &_optval);
if (op == NULL)
- return 1;
+ return true;
return (*op & 0xC0) == 0x80;
}
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index cb43df690210..9772fbd8a3f5 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -433,32 +433,32 @@ static int mem_check(struct sock *sk)
return 0;
}
-static int ipv6_hdr_cmp(struct ipv6_opt_hdr *h1, struct ipv6_opt_hdr *h2)
+static bool ipv6_hdr_cmp(struct ipv6_opt_hdr *h1, struct ipv6_opt_hdr *h2)
{
if (h1 == h2)
- return 0;
+ return false;
if (h1 == NULL || h2 == NULL)
- return 1;
+ return true;
if (h1->hdrlen != h2->hdrlen)
- return 1;
+ return true;
return memcmp(h1+1, h2+1, ((h1->hdrlen+1)<<3) - sizeof(*h1));
}
-static int ipv6_opt_cmp(struct ipv6_txoptions *o1, struct ipv6_txoptions *o2)
+static bool ipv6_opt_cmp(struct ipv6_txoptions *o1, struct ipv6_txoptions *o2)
{
if (o1 == o2)
- return 0;
+ return false;
if (o1 == NULL || o2 == NULL)
- return 1;
+ return true;
if (o1->opt_nflen != o2->opt_nflen)
- return 1;
+ return true;
if (ipv6_hdr_cmp(o1->hopopt, o2->hopopt))
- return 1;
+ return true;
if (ipv6_hdr_cmp(o1->dst0opt, o2->dst0opt))
- return 1;
+ return true;
if (ipv6_hdr_cmp((struct ipv6_opt_hdr *)o1->srcrt, (struct ipv6_opt_hdr *)o2->srcrt))
- return 1;
- return 0;
+ return true;
+ return false;
}
static inline void fl_link(struct ipv6_pinfo *np, struct ipv6_fl_socklist *sfl,
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 1ca5d45a12e8..21a15dfe4a9e 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -170,7 +170,8 @@ static int ip6_input_finish(struct sk_buff *skb)
{
const struct inet6_protocol *ipprot;
unsigned int nhoff;
- int nexthdr, raw;
+ int nexthdr;
+ bool raw;
u8 hash;
struct inet6_dev *idev;
struct net *net = dev_net(skb_dst(skb)->dev);
@@ -251,7 +252,7 @@ int ip6_input(struct sk_buff *skb)
int ip6_mc_input(struct sk_buff *skb)
{
const struct ipv6hdr *hdr;
- int deliver;
+ bool deliver;
IP6_UPD_PO_STATS_BH(dev_net(skb_dst(skb)->dev),
ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INMCAST,
@@ -287,7 +288,7 @@ int ip6_mc_input(struct sk_buff *skb)
* is for MLD (0x0000).
*/
if ((ptr[2] | ptr[3]) == 0) {
- deliver = 0;
+ deliver = false;
if (!ipv6_ext_hdr(nexthdr)) {
/* BUG */
@@ -312,7 +313,7 @@ int ip6_mc_input(struct sk_buff *skb)
case ICMPV6_MGM_REPORT:
case ICMPV6_MGM_REDUCTION:
case ICMPV6_MLD2_REPORT:
- deliver = 1;
+ deliver = true;
break;
}
goto out;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index be2264e7dd2d..d99fdc699625 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -643,7 +643,10 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
/* We must not fragment if the socket is set to force MTU discovery
* or if the skb it not generated by a local socket.
*/
- if (!skb->local_df && skb->len > mtu) {
+ if (unlikely(!skb->local_df && skb->len > mtu)) {
+ if (skb->sk && dst_allfrag(skb_dst(skb)))
+ sk_nocaps_add(skb->sk, NETIF_F_GSO_MASK);
+
skb->dev = skb_dst(skb)->dev;
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
@@ -788,6 +791,10 @@ slow_path_clean:
}
slow_path:
+ if ((skb->ip_summed == CHECKSUM_PARTIAL) &&
+ skb_checksum_help(skb))
+ goto fail;
+
left = skb->len - hlen; /* Space per frame */
ptr = hlen; /* Where to start from */
@@ -1198,7 +1205,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
int copy;
int err;
int offset = 0;
- int csummode = CHECKSUM_NONE;
__u8 tx_flags = 0;
if (flags&MSG_PROBE)
@@ -1411,7 +1417,7 @@ alloc_new_skb:
/*
* Fill in the control structures
*/
- skb->ip_summed = csummode;
+ skb->ip_summed = CHECKSUM_NONE;
skb->csum = 0;
/* reserve for fragmentation and ipsec header */
skb_reserve(skb, hh_len + sizeof(struct frag_hdr) +
@@ -1454,7 +1460,6 @@ alloc_new_skb:
transhdrlen = 0;
exthdrlen = 0;
dst_exthdrlen = 0;
- csummode = CHECKSUM_NONE;
/*
* Put the packet on the pending queue
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index e65c56009bb0..c9015fad8d65 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -818,7 +818,7 @@ static void init_tel_txopt(struct ipv6_tel_txoption *opt, __u8 encap_limit)
* 0 else
**/
-static inline int
+static inline bool
ip6_tnl_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr)
{
return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr);
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 2a3a22cf7604..6d0f5dc8e3a6 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -606,13 +606,13 @@ done:
return err;
}
-int inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
- const struct in6_addr *src_addr)
+bool inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
+ const struct in6_addr *src_addr)
{
struct ipv6_pinfo *np = inet6_sk(sk);
struct ipv6_mc_socklist *mc;
struct ip6_sf_socklist *psl;
- int rv = 1;
+ bool rv = true;
rcu_read_lock();
for_each_pmc_rcu(np, mc) {
@@ -621,7 +621,7 @@ int inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
}
if (!mc) {
rcu_read_unlock();
- return 1;
+ return true;
}
read_lock(&mc->sflock);
psl = mc->sflist;
@@ -635,9 +635,9 @@ int inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
break;
}
if (mc->sfmode == MCAST_INCLUDE && i >= psl->sl_count)
- rv = 0;
+ rv = false;
if (mc->sfmode == MCAST_EXCLUDE && i < psl->sl_count)
- rv = 0;
+ rv = false;
}
read_unlock(&mc->sflock);
rcu_read_unlock();
@@ -931,15 +931,15 @@ int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
/*
* identify MLD packets for MLD filter exceptions
*/
-int ipv6_is_mld(struct sk_buff *skb, int nexthdr)
+bool ipv6_is_mld(struct sk_buff *skb, int nexthdr)
{
struct icmp6hdr *pic;
if (nexthdr != IPPROTO_ICMPV6)
- return 0;
+ return false;
if (!pskb_may_pull(skb, sizeof(struct icmp6hdr)))
- return 0;
+ return false;
pic = icmp6_hdr(skb);
@@ -948,22 +948,22 @@ int ipv6_is_mld(struct sk_buff *skb, int nexthdr)
case ICMPV6_MGM_REPORT:
case ICMPV6_MGM_REDUCTION:
case ICMPV6_MLD2_REPORT:
- return 1;
+ return true;
default:
break;
}
- return 0;
+ return false;
}
/*
* check if the interface/address pair is valid
*/
-int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
- const struct in6_addr *src_addr)
+bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
+ const struct in6_addr *src_addr)
{
struct inet6_dev *idev;
struct ifmcaddr6 *mc;
- int rv = 0;
+ bool rv = false;
rcu_read_lock();
idev = __in6_dev_get(dev);
@@ -990,7 +990,7 @@ int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
rv = mc->mca_sfcount[MCAST_EXCLUDE] !=0;
spin_unlock_bh(&mc->mca_lock);
} else
- rv = 1; /* don't filter unspecified source */
+ rv = true; /* don't filter unspecified source */
}
read_unlock_bh(&idev->lock);
}
@@ -1046,8 +1046,8 @@ static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime)
}
/* mark EXCLUDE-mode sources */
-static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs,
- const struct in6_addr *srcs)
+static bool mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs,
+ const struct in6_addr *srcs)
{
struct ip6_sf_list *psf;
int i, scount;
@@ -1070,12 +1070,12 @@ static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs,
}
pmc->mca_flags &= ~MAF_GSQUERY;
if (scount == nsrcs) /* all sources excluded */
- return 0;
- return 1;
+ return false;
+ return true;
}
-static int mld_marksources(struct ifmcaddr6 *pmc, int nsrcs,
- const struct in6_addr *srcs)
+static bool mld_marksources(struct ifmcaddr6 *pmc, int nsrcs,
+ const struct in6_addr *srcs)
{
struct ip6_sf_list *psf;
int i, scount;
@@ -1099,10 +1099,10 @@ static int mld_marksources(struct ifmcaddr6 *pmc, int nsrcs,
}
if (!scount) {
pmc->mca_flags &= ~MAF_GSQUERY;
- return 0;
+ return false;
}
pmc->mca_flags |= MAF_GSQUERY;
- return 1;
+ return true;
}
/* called with rcu_read_lock() */
@@ -1276,17 +1276,17 @@ int igmp6_event_report(struct sk_buff *skb)
return 0;
}
-static int is_in(struct ifmcaddr6 *pmc, struct ip6_sf_list *psf, int type,
- int gdeleted, int sdeleted)
+static bool is_in(struct ifmcaddr6 *pmc, struct ip6_sf_list *psf, int type,
+ int gdeleted, int sdeleted)
{
switch (type) {
case MLD2_MODE_IS_INCLUDE:
case MLD2_MODE_IS_EXCLUDE:
if (gdeleted || sdeleted)
- return 0;
+ return false;
if (!((pmc->mca_flags & MAF_GSQUERY) && !psf->sf_gsresp)) {
if (pmc->mca_sfmode == MCAST_INCLUDE)
- return 1;
+ return true;
/* don't include if this source is excluded
* in all filters
*/
@@ -1295,29 +1295,29 @@ static int is_in(struct ifmcaddr6 *pmc, struct ip6_sf_list *psf, int type,
return pmc->mca_sfcount[MCAST_EXCLUDE] ==
psf->sf_count[MCAST_EXCLUDE];
}
- return 0;
+ return false;
case MLD2_CHANGE_TO_INCLUDE:
if (gdeleted || sdeleted)
- return 0;
+ return false;
return psf->sf_count[MCAST_INCLUDE] != 0;
case MLD2_CHANGE_TO_EXCLUDE:
if (gdeleted || sdeleted)
- return 0;
+ return false;
if (pmc->mca_sfcount[MCAST_EXCLUDE] == 0 ||
psf->sf_count[MCAST_INCLUDE])
- return 0;
+ return false;
return pmc->mca_sfcount[MCAST_EXCLUDE] ==
psf->sf_count[MCAST_EXCLUDE];
case MLD2_ALLOW_NEW_SOURCES:
if (gdeleted || !psf->sf_crcount)
- return 0;
+ return false;
return (pmc->mca_sfmode == MCAST_INCLUDE) ^ sdeleted;
case MLD2_BLOCK_OLD_SOURCES:
if (pmc->mca_sfmode == MCAST_INCLUDE)
return gdeleted || (psf->sf_crcount && sdeleted);
return psf->sf_crcount && !gdeleted && !sdeleted;
}
- return 0;
+ return false;
}
static int
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index c7a27ac906df..54f62d3b8dd6 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -348,7 +348,7 @@ static int ndisc_constructor(struct neighbour *neigh)
struct net_device *dev = neigh->dev;
struct inet6_dev *in6_dev;
struct neigh_parms *parms;
- int is_multicast = ipv6_addr_is_multicast(addr);
+ bool is_multicast = ipv6_addr_is_multicast(addr);
in6_dev = in6_dev_get(dev);
if (in6_dev == NULL) {
@@ -725,7 +725,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
struct inet6_dev *idev = NULL;
struct neighbour *neigh;
int dad = ipv6_addr_any(saddr);
- int inc;
+ bool inc;
int is_router = -1;
if (ipv6_addr_is_multicast(&msg->target)) {
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 5bddea778840..93d69836fded 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -72,7 +72,7 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
const struct in6_addr *rmt_addr, int dif)
{
struct hlist_node *node;
- int is_multicast = ipv6_addr_is_multicast(loc_addr);
+ bool is_multicast = ipv6_addr_is_multicast(loc_addr);
sk_for_each_from(sk, node)
if (inet_sk(sk)->inet_num == num) {
@@ -153,12 +153,12 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister);
*
* Caller owns SKB so we must make clones.
*/
-static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
+static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
{
const struct in6_addr *saddr;
const struct in6_addr *daddr;
struct sock *sk;
- int delivered = 0;
+ bool delivered = false;
__u8 hash;
struct net *net;
@@ -179,7 +179,7 @@ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
while (sk) {
int filtered;
- delivered = 1;
+ delivered = true;
switch (nexthdr) {
case IPPROTO_ICMPV6:
filtered = icmpv6_filter(sk, skb);
@@ -225,7 +225,7 @@ out:
return delivered;
}
-int raw6_local_deliver(struct sk_buff *skb, int nexthdr)
+bool raw6_local_deliver(struct sk_buff *skb, int nexthdr)
{
struct sock *raw_sk;
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index f1b86fdc06ad..4ff9af628e72 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -134,15 +134,16 @@ static unsigned int ip6_hashfn(struct inet_frag_queue *q)
return inet6_hash_frag(fq->id, &fq->saddr, &fq->daddr, ip6_frags.rnd);
}
-int ip6_frag_match(struct inet_frag_queue *q, void *a)
+bool ip6_frag_match(struct inet_frag_queue *q, void *a)
{
struct frag_queue *fq;
struct ip6_create_arg *arg = a;
fq = container_of(q, struct frag_queue, q);
- return (fq->id == arg->id && fq->user == arg->user &&
- ipv6_addr_equal(&fq->saddr, arg->src) &&
- ipv6_addr_equal(&fq->daddr, arg->dst));
+ return fq->id == arg->id &&
+ fq->user == arg->user &&
+ ipv6_addr_equal(&fq->saddr, arg->src) &&
+ ipv6_addr_equal(&fq->daddr, arg->dst);
}
EXPORT_SYMBOL(ip6_frag_match);
@@ -414,6 +415,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
struct sk_buff *fp, *head = fq->q.fragments;
int payload_len;
unsigned int nhoff;
+ int sum_truesize;
fq_kill(fq);
@@ -483,20 +485,33 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
head->mac_header += sizeof(struct frag_hdr);
head->network_header += sizeof(struct frag_hdr);
- skb_shinfo(head)->frag_list = head->next;
skb_reset_transport_header(head);
skb_push(head, head->data - skb_network_header(head));
- for (fp=head->next; fp; fp = fp->next) {
- head->data_len += fp->len;
- head->len += fp->len;
+ sum_truesize = head->truesize;
+ for (fp = head->next; fp;) {
+ bool headstolen;
+ int delta;
+ struct sk_buff *next = fp->next;
+
+ sum_truesize += fp->truesize;
if (head->ip_summed != fp->ip_summed)
head->ip_summed = CHECKSUM_NONE;
else if (head->ip_summed == CHECKSUM_COMPLETE)
head->csum = csum_add(head->csum, fp->csum);
- head->truesize += fp->truesize;
+
+ if (skb_try_coalesce(head, fp, &headstolen, &delta)) {
+ kfree_skb_partial(fp, headstolen);
+ } else {
+ if (!skb_shinfo(head)->frag_list)
+ skb_shinfo(head)->frag_list = fp;
+ head->data_len += fp->len;
+ head->len += fp->len;
+ head->truesize += fp->truesize;
+ }
+ fp = next;
}
- atomic_sub(head->truesize, &fq->q.net->mem);
+ atomic_sub(sum_truesize, &fq->q.net->mem);
head->next = NULL;
head->dev = dev;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 90119a32b89d..999a982ad3fd 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -333,22 +333,22 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
}
}
-static __inline__ int rt6_check_expired(const struct rt6_info *rt)
+static bool rt6_check_expired(const struct rt6_info *rt)
{
struct rt6_info *ort = NULL;
if (rt->rt6i_flags & RTF_EXPIRES) {
if (time_after(jiffies, rt->dst.expires))
- return 1;
+ return true;
} else if (rt->dst.from) {
ort = (struct rt6_info *) rt->dst.from;
return (ort->rt6i_flags & RTF_EXPIRES) &&
time_after(jiffies, ort->dst.expires);
}
- return 0;
+ return false;
}
-static inline int rt6_need_strict(const struct in6_addr *daddr)
+static bool rt6_need_strict(const struct in6_addr *daddr)
{
return ipv6_addr_type(daddr) &
(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index c1d91a713e8e..f05099fc5901 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -103,7 +103,7 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum)
{
unsigned int hash2_nulladdr =
udp6_portaddr_hash(sock_net(sk), &in6addr_any, snum);
- unsigned int hash2_partial =
+ unsigned int hash2_partial =
udp6_portaddr_hash(sock_net(sk), &inet6_sk(sk)->rcv_saddr, 0);
/* precompute partial secondary hash */
@@ -349,7 +349,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
bool slow;
if (addr_len)
- *addr_len=sizeof(struct sockaddr_in6);
+ *addr_len = sizeof(struct sockaddr_in6);
if (flags & MSG_ERRQUEUE)
return ipv6_recv_error(sk, msg, len);
@@ -1379,7 +1379,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
* do checksum of UDP packets sent as multiple IP fragments.
*/
offset = skb_checksum_start_offset(skb);
- csum = skb_checksum(skb, offset, skb->len- offset, 0);
+ csum = skb_checksum(skb, offset, skb->len - offset, 0);
offset += skb->csum_offset;
*(__sum16 *)(skb->data + offset) = csum_fold(csum);
skb->ip_summed = CHECKSUM_NONE;
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 824d4a3338ae..dfd6faaf0ea7 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -1901,9 +1901,7 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
(const unsigned short __user *)argp);
break;
case SIOCGSTAMP:
- rc = -EINVAL;
- if (sk)
- rc = sock_get_timestamp(sk, argp);
+ rc = sock_get_timestamp(sk, argp);
break;
case SIOCGIFDSTADDR:
case SIOCSIFDSTADDR:
diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c
index ab3d35f23257..3cdaa046c1bc 100644
--- a/net/lapb/lapb_iface.c
+++ b/net/lapb/lapb_iface.c
@@ -15,6 +15,8 @@
* 2000-10-29 Henner Eisen lapb_data_indication() return status.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/types.h>
@@ -279,9 +281,7 @@ int lapb_connect_request(struct net_device *dev)
lapb_establish_data_link(lapb);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S0 -> S1\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S0 -> S1\n", lapb->dev);
lapb->state = LAPB_STATE_1;
rc = LAPB_OK;
@@ -305,12 +305,8 @@ int lapb_disconnect_request(struct net_device *dev)
goto out_put;
case LAPB_STATE_1:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->dev);
-#endif
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
-#endif
+ lapb_dbg(1, "(%p) S1 TX DISC(1)\n", lapb->dev);
+ lapb_dbg(0, "(%p) S1 -> S0\n", lapb->dev);
lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
lapb->state = LAPB_STATE_0;
lapb_start_t1timer(lapb);
@@ -329,12 +325,8 @@ int lapb_disconnect_request(struct net_device *dev)
lapb_stop_t2timer(lapb);
lapb->state = LAPB_STATE_2;
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 DISC(1)\n", lapb->dev);
-#endif
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S2\n", lapb->dev);
-#endif
+ lapb_dbg(1, "(%p) S3 DISC(1)\n", lapb->dev);
+ lapb_dbg(0, "(%p) S3 -> S2\n", lapb->dev);
rc = LAPB_OK;
out_put:
diff --git a/net/lapb/lapb_in.c b/net/lapb/lapb_in.c
index f4e3c1accab7..5dba899131b3 100644
--- a/net/lapb/lapb_in.c
+++ b/net/lapb/lapb_in.c
@@ -15,6 +15,8 @@
* 2000-10-29 Henner Eisen lapb_data_indication() return status.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -44,25 +46,16 @@ static void lapb_state0_machine(struct lapb_cb *lapb, struct sk_buff *skb,
{
switch (frame->type) {
case LAPB_SABM:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 RX SABM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S0 RX SABM(%d)\n", lapb->dev, frame->pf);
if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S0 TX DM(%d)\n",
+ lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_DM, frame->pf,
LAPB_RESPONSE);
} else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n", lapb->dev);
-#endif
+ lapb_dbg(1, "(%p) S0 TX UA(%d)\n",
+ lapb->dev, frame->pf);
+ lapb_dbg(0, "(%p) S0 -> S3\n", lapb->dev);
lapb_send_control(lapb, LAPB_UA, frame->pf,
LAPB_RESPONSE);
lapb_stop_t1timer(lapb);
@@ -78,18 +71,11 @@ static void lapb_state0_machine(struct lapb_cb *lapb, struct sk_buff *skb,
break;
case LAPB_SABME:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 RX SABME(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S0 RX SABME(%d)\n", lapb->dev, frame->pf);
if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n", lapb->dev);
-#endif
+ lapb_dbg(1, "(%p) S0 TX UA(%d)\n",
+ lapb->dev, frame->pf);
+ lapb_dbg(0, "(%p) S0 -> S3\n", lapb->dev);
lapb_send_control(lapb, LAPB_UA, frame->pf,
LAPB_RESPONSE);
lapb_stop_t1timer(lapb);
@@ -102,22 +88,16 @@ static void lapb_state0_machine(struct lapb_cb *lapb, struct sk_buff *skb,
lapb->va = 0;
lapb_connect_indication(lapb, LAPB_OK);
} else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S0 TX DM(%d)\n",
+ lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_DM, frame->pf,
LAPB_RESPONSE);
}
break;
case LAPB_DISC:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S0 RX DISC(%d)\n",
- lapb->dev, frame->pf);
- printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S0 RX DISC(%d)\n", lapb->dev, frame->pf);
+ lapb_dbg(1, "(%p) S0 TX UA(%d)\n", lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
break;
@@ -137,68 +117,45 @@ static void lapb_state1_machine(struct lapb_cb *lapb, struct sk_buff *skb,
{
switch (frame->type) {
case LAPB_SABM:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 RX SABM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S1 RX SABM(%d)\n", lapb->dev, frame->pf);
if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S1 TX DM(%d)\n",
+ lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_DM, frame->pf,
LAPB_RESPONSE);
} else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S1 TX UA(%d)\n",
+ lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_UA, frame->pf,
LAPB_RESPONSE);
}
break;
case LAPB_SABME:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 RX SABME(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S1 RX SABME(%d)\n", lapb->dev, frame->pf);
if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S1 TX UA(%d)\n",
+ lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_UA, frame->pf,
LAPB_RESPONSE);
} else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S1 TX DM(%d)\n",
+ lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_DM, frame->pf,
LAPB_RESPONSE);
}
break;
case LAPB_DISC:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 RX DISC(%d)\n",
- lapb->dev, frame->pf);
- printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S1 RX DISC(%d)\n", lapb->dev, frame->pf);
+ lapb_dbg(1, "(%p) S1 TX DM(%d)\n", lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE);
break;
case LAPB_UA:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 RX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S1 RX UA(%d)\n", lapb->dev, frame->pf);
if (frame->pf) {
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S1 -> S3\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S1 -> S3\n", lapb->dev);
lapb_stop_t1timer(lapb);
lapb_stop_t2timer(lapb);
lapb->state = LAPB_STATE_3;
@@ -212,14 +169,9 @@ static void lapb_state1_machine(struct lapb_cb *lapb, struct sk_buff *skb,
break;
case LAPB_DM:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 RX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S1 RX DM(%d)\n", lapb->dev, frame->pf);
if (frame->pf) {
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S1 -> S0\n", lapb->dev);
lapb_clear_queues(lapb);
lapb->state = LAPB_STATE_0;
lapb_start_t1timer(lapb);
@@ -242,34 +194,22 @@ static void lapb_state2_machine(struct lapb_cb *lapb, struct sk_buff *skb,
switch (frame->type) {
case LAPB_SABM:
case LAPB_SABME:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S2 RX {SABM,SABME}(%d)\n",
- lapb->dev, frame->pf);
- printk(KERN_DEBUG "lapb: (%p) S2 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S2 RX {SABM,SABME}(%d)\n",
+ lapb->dev, frame->pf);
+ lapb_dbg(1, "(%p) S2 TX DM(%d)\n", lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE);
break;
case LAPB_DISC:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S2 RX DISC(%d)\n",
- lapb->dev, frame->pf);
- printk(KERN_DEBUG "lapb: (%p) S2 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S2 RX DISC(%d)\n", lapb->dev, frame->pf);
+ lapb_dbg(1, "(%p) S2 TX UA(%d)\n", lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
break;
case LAPB_UA:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S2 RX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S2 RX UA(%d)\n", lapb->dev, frame->pf);
if (frame->pf) {
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S2 -> S0\n", lapb->dev);
lapb->state = LAPB_STATE_0;
lapb_start_t1timer(lapb);
lapb_stop_t2timer(lapb);
@@ -278,14 +218,9 @@ static void lapb_state2_machine(struct lapb_cb *lapb, struct sk_buff *skb,
break;
case LAPB_DM:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S2 RX DM(%d)\n", lapb->dev, frame->pf);
if (frame->pf) {
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S2 -> S0\n", lapb->dev);
lapb->state = LAPB_STATE_0;
lapb_start_t1timer(lapb);
lapb_stop_t2timer(lapb);
@@ -297,12 +232,9 @@ static void lapb_state2_machine(struct lapb_cb *lapb, struct sk_buff *skb,
case LAPB_REJ:
case LAPB_RNR:
case LAPB_RR:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S2 RX {I,REJ,RNR,RR}(%d)\n",
- lapb->dev, frame->pf);
- printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
+ lapb_dbg(1, "(%p) S2 RX {I,REJ,RNR,RR}(%d)\n",
lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S2 RX DM(%d)\n", lapb->dev, frame->pf);
if (frame->pf)
lapb_send_control(lapb, LAPB_DM, frame->pf,
LAPB_RESPONSE);
@@ -325,22 +257,15 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
switch (frame->type) {
case LAPB_SABM:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX SABM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S3 RX SABM(%d)\n", lapb->dev, frame->pf);
if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S3 TX DM(%d)\n",
+ lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_DM, frame->pf,
LAPB_RESPONSE);
} else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S3 TX UA(%d)\n",
+ lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_UA, frame->pf,
LAPB_RESPONSE);
lapb_stop_t1timer(lapb);
@@ -355,15 +280,10 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
break;
case LAPB_SABME:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX SABME(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S3 RX SABME(%d)\n", lapb->dev, frame->pf);
if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S3 TX UA(%d)\n",
+ lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_UA, frame->pf,
LAPB_RESPONSE);
lapb_stop_t1timer(lapb);
@@ -375,23 +295,16 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
lapb->va = 0;
lapb_requeue_frames(lapb);
} else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S3 TX DM(%d)\n",
+ lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_DM, frame->pf,
LAPB_RESPONSE);
}
break;
case LAPB_DISC:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX DISC(%d)\n",
- lapb->dev, frame->pf);
-#endif
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev);
-#endif
+ lapb_dbg(1, "(%p) S3 RX DISC(%d)\n", lapb->dev, frame->pf);
+ lapb_dbg(0, "(%p) S3 -> S0\n", lapb->dev);
lapb_clear_queues(lapb);
lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
lapb_start_t1timer(lapb);
@@ -401,13 +314,8 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
break;
case LAPB_DM:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev);
-#endif
+ lapb_dbg(1, "(%p) S3 RX DM(%d)\n", lapb->dev, frame->pf);
+ lapb_dbg(0, "(%p) S3 -> S0\n", lapb->dev);
lapb_clear_queues(lapb);
lapb->state = LAPB_STATE_0;
lapb_start_t1timer(lapb);
@@ -416,10 +324,8 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
break;
case LAPB_RNR:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX RNR(%d) R%d\n",
- lapb->dev, frame->pf, frame->nr);
-#endif
+ lapb_dbg(1, "(%p) S3 RX RNR(%d) R%d\n",
+ lapb->dev, frame->pf, frame->nr);
lapb->condition |= LAPB_PEER_RX_BUSY_CONDITION;
lapb_check_need_response(lapb, frame->cr, frame->pf);
if (lapb_validate_nr(lapb, frame->nr)) {
@@ -428,9 +334,7 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
lapb->frmr_data = *frame;
lapb->frmr_type = LAPB_FRMR_Z;
lapb_transmit_frmr(lapb);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev);
lapb_start_t1timer(lapb);
lapb_stop_t2timer(lapb);
lapb->state = LAPB_STATE_4;
@@ -439,10 +343,8 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
break;
case LAPB_RR:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX RR(%d) R%d\n",
- lapb->dev, frame->pf, frame->nr);
-#endif
+ lapb_dbg(1, "(%p) S3 RX RR(%d) R%d\n",
+ lapb->dev, frame->pf, frame->nr);
lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
lapb_check_need_response(lapb, frame->cr, frame->pf);
if (lapb_validate_nr(lapb, frame->nr)) {
@@ -451,9 +353,7 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
lapb->frmr_data = *frame;
lapb->frmr_type = LAPB_FRMR_Z;
lapb_transmit_frmr(lapb);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev);
lapb_start_t1timer(lapb);
lapb_stop_t2timer(lapb);
lapb->state = LAPB_STATE_4;
@@ -462,10 +362,8 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
break;
case LAPB_REJ:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX REJ(%d) R%d\n",
- lapb->dev, frame->pf, frame->nr);
-#endif
+ lapb_dbg(1, "(%p) S3 RX REJ(%d) R%d\n",
+ lapb->dev, frame->pf, frame->nr);
lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
lapb_check_need_response(lapb, frame->cr, frame->pf);
if (lapb_validate_nr(lapb, frame->nr)) {
@@ -477,9 +375,7 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
lapb->frmr_data = *frame;
lapb->frmr_type = LAPB_FRMR_Z;
lapb_transmit_frmr(lapb);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev);
lapb_start_t1timer(lapb);
lapb_stop_t2timer(lapb);
lapb->state = LAPB_STATE_4;
@@ -488,17 +384,13 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
break;
case LAPB_I:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX I(%d) S%d R%d\n",
- lapb->dev, frame->pf, frame->ns, frame->nr);
-#endif
+ lapb_dbg(1, "(%p) S3 RX I(%d) S%d R%d\n",
+ lapb->dev, frame->pf, frame->ns, frame->nr);
if (!lapb_validate_nr(lapb, frame->nr)) {
lapb->frmr_data = *frame;
lapb->frmr_type = LAPB_FRMR_Z;
lapb_transmit_frmr(lapb);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev);
lapb_start_t1timer(lapb);
lapb_stop_t2timer(lapb);
lapb->state = LAPB_STATE_4;
@@ -522,7 +414,7 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
* a frame lost on the wire.
*/
if (cn == NET_RX_DROP) {
- printk(KERN_DEBUG "LAPB: rx congestion\n");
+ pr_debug("rx congestion\n");
break;
}
lapb->vr = (lapb->vr + 1) % modulus;
@@ -541,11 +433,8 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
if (frame->pf)
lapb_enquiry_response(lapb);
} else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG
- "lapb: (%p) S3 TX REJ(%d) R%d\n",
- lapb->dev, frame->pf, lapb->vr);
-#endif
+ lapb_dbg(1, "(%p) S3 TX REJ(%d) R%d\n",
+ lapb->dev, frame->pf, lapb->vr);
lapb->condition |= LAPB_REJECT_CONDITION;
lapb_send_control(lapb, LAPB_REJ, frame->pf,
LAPB_RESPONSE);
@@ -555,31 +444,22 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
break;
case LAPB_FRMR:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX FRMR(%d) %02X "
- "%02X %02X %02X %02X\n", lapb->dev, frame->pf,
- skb->data[0], skb->data[1], skb->data[2],
- skb->data[3], skb->data[4]);
-#endif
+ lapb_dbg(1, "(%p) S3 RX FRMR(%d) %02X %02X %02X %02X %02X\n",
+ lapb->dev, frame->pf,
+ skb->data[0], skb->data[1], skb->data[2],
+ skb->data[3], skb->data[4]);
lapb_establish_data_link(lapb);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S3 -> S1\n", lapb->dev);
lapb_requeue_frames(lapb);
lapb->state = LAPB_STATE_1;
break;
case LAPB_ILLEGAL:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S3 RX ILLEGAL(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S3 RX ILLEGAL(%d)\n", lapb->dev, frame->pf);
lapb->frmr_data = *frame;
lapb->frmr_type = LAPB_FRMR_W;
lapb_transmit_frmr(lapb);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev);
lapb_start_t1timer(lapb);
lapb_stop_t2timer(lapb);
lapb->state = LAPB_STATE_4;
@@ -600,25 +480,16 @@ static void lapb_state4_machine(struct lapb_cb *lapb, struct sk_buff *skb,
{
switch (frame->type) {
case LAPB_SABM:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S4 RX SABM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S4 RX SABM(%d)\n", lapb->dev, frame->pf);
if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S4 TX DM(%d)\n",
+ lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_DM, frame->pf,
LAPB_RESPONSE);
} else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n", lapb->dev);
-#endif
+ lapb_dbg(1, "(%p) S4 TX UA(%d)\n",
+ lapb->dev, frame->pf);
+ lapb_dbg(0, "(%p) S4 -> S3\n", lapb->dev);
lapb_send_control(lapb, LAPB_UA, frame->pf,
LAPB_RESPONSE);
lapb_stop_t1timer(lapb);
@@ -634,18 +505,11 @@ static void lapb_state4_machine(struct lapb_cb *lapb, struct sk_buff *skb,
break;
case LAPB_SABME:
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S4 RX SABME(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S4 RX SABME(%d)\n", lapb->dev, frame->pf);
if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
- lapb->dev, frame->pf);
-#endif
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n", lapb->dev);
-#endif
+ lapb_dbg(1, "(%p) S4 TX UA(%d)\n",
+ lapb->dev, frame->pf);
+ lapb_dbg(0, "(%p) S4 -> S3\n", lapb->dev);
lapb_send_control(lapb, LAPB_UA, frame->pf,
LAPB_RESPONSE);
lapb_stop_t1timer(lapb);
@@ -658,10 +522,8 @@ static void lapb_state4_machine(struct lapb_cb *lapb, struct sk_buff *skb,
lapb->va = 0;
lapb_connect_indication(lapb, LAPB_OK);
} else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
- lapb->dev, frame->pf);
-#endif
+ lapb_dbg(1, "(%p) S4 TX DM(%d)\n",
+ lapb->dev, frame->pf);
lapb_send_control(lapb, LAPB_DM, frame->pf,
LAPB_RESPONSE);
}
diff --git a/net/lapb/lapb_out.c b/net/lapb/lapb_out.c
index baab2760f651..ba4d015bd1a6 100644
--- a/net/lapb/lapb_out.c
+++ b/net/lapb/lapb_out.c
@@ -14,6 +14,8 @@
* LAPB 002 Jonathan Naylor New timer architecture.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -60,10 +62,8 @@ static void lapb_send_iframe(struct lapb_cb *lapb, struct sk_buff *skb, int poll
*frame |= lapb->vs << 1;
}
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S%d TX I(%d) S%d R%d\n",
- lapb->dev, lapb->state, poll_bit, lapb->vs, lapb->vr);
-#endif
+ lapb_dbg(1, "(%p) S%d TX I(%d) S%d R%d\n",
+ lapb->dev, lapb->state, poll_bit, lapb->vs, lapb->vr);
lapb_transmit_buffer(lapb, skb, LAPB_COMMAND);
}
@@ -148,11 +148,9 @@ void lapb_transmit_buffer(struct lapb_cb *lapb, struct sk_buff *skb, int type)
}
}
-#if LAPB_DEBUG > 2
- printk(KERN_DEBUG "lapb: (%p) S%d TX %02X %02X %02X\n",
- lapb->dev, lapb->state,
- skb->data[0], skb->data[1], skb->data[2]);
-#endif
+ lapb_dbg(2, "(%p) S%d TX %02X %02X %02X\n",
+ lapb->dev, lapb->state,
+ skb->data[0], skb->data[1], skb->data[2]);
if (!lapb_data_transmit(lapb, skb))
kfree_skb(skb);
@@ -164,16 +162,10 @@ void lapb_establish_data_link(struct lapb_cb *lapb)
lapb->n2count = 0;
if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S%d TX SABME(1)\n",
- lapb->dev, lapb->state);
-#endif
+ lapb_dbg(1, "(%p) S%d TX SABME(1)\n", lapb->dev, lapb->state);
lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND);
} else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S%d TX SABM(1)\n",
- lapb->dev, lapb->state);
-#endif
+ lapb_dbg(1, "(%p) S%d TX SABM(1)\n", lapb->dev, lapb->state);
lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND);
}
@@ -183,10 +175,8 @@ void lapb_establish_data_link(struct lapb_cb *lapb)
void lapb_enquiry_response(struct lapb_cb *lapb)
{
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S%d TX RR(1) R%d\n",
- lapb->dev, lapb->state, lapb->vr);
-#endif
+ lapb_dbg(1, "(%p) S%d TX RR(1) R%d\n",
+ lapb->dev, lapb->state, lapb->vr);
lapb_send_control(lapb, LAPB_RR, LAPB_POLLON, LAPB_RESPONSE);
@@ -195,10 +185,8 @@ void lapb_enquiry_response(struct lapb_cb *lapb)
void lapb_timeout_response(struct lapb_cb *lapb)
{
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S%d TX RR(0) R%d\n",
- lapb->dev, lapb->state, lapb->vr);
-#endif
+ lapb_dbg(1, "(%p) S%d TX RR(0) R%d\n",
+ lapb->dev, lapb->state, lapb->vr);
lapb_send_control(lapb, LAPB_RR, LAPB_POLLOFF, LAPB_RESPONSE);
lapb->condition &= ~LAPB_ACK_PENDING_CONDITION;
diff --git a/net/lapb/lapb_subr.c b/net/lapb/lapb_subr.c
index 066225b4e824..9d0a426eccbb 100644
--- a/net/lapb/lapb_subr.c
+++ b/net/lapb/lapb_subr.c
@@ -13,6 +13,8 @@
* LAPB 001 Jonathan Naylor Started Coding
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -111,11 +113,9 @@ int lapb_decode(struct lapb_cb *lapb, struct sk_buff *skb,
{
frame->type = LAPB_ILLEGAL;
-#if LAPB_DEBUG > 2
- printk(KERN_DEBUG "lapb: (%p) S%d RX %02X %02X %02X\n",
- lapb->dev, lapb->state,
- skb->data[0], skb->data[1], skb->data[2]);
-#endif
+ lapb_dbg(2, "(%p) S%d RX %02X %02X %02X\n",
+ lapb->dev, lapb->state,
+ skb->data[0], skb->data[1], skb->data[2]);
/* We always need to look at 2 bytes, sometimes we need
* to look at 3 and those cases are handled below.
@@ -284,12 +284,10 @@ void lapb_transmit_frmr(struct lapb_cb *lapb)
dptr++;
*dptr++ = lapb->frmr_type;
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S%d TX FRMR %02X %02X %02X %02X %02X\n",
- lapb->dev, lapb->state,
- skb->data[1], skb->data[2], skb->data[3],
- skb->data[4], skb->data[5]);
-#endif
+ lapb_dbg(1, "(%p) S%d TX FRMR %02X %02X %02X %02X %02X\n",
+ lapb->dev, lapb->state,
+ skb->data[1], skb->data[2], skb->data[3],
+ skb->data[4], skb->data[5]);
} else {
dptr = skb_put(skb, 4);
*dptr++ = LAPB_FRMR;
@@ -301,11 +299,9 @@ void lapb_transmit_frmr(struct lapb_cb *lapb)
dptr++;
*dptr++ = lapb->frmr_type;
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S%d TX FRMR %02X %02X %02X\n",
- lapb->dev, lapb->state, skb->data[1],
- skb->data[2], skb->data[3]);
-#endif
+ lapb_dbg(1, "(%p) S%d TX FRMR %02X %02X %02X\n",
+ lapb->dev, lapb->state, skb->data[1],
+ skb->data[2], skb->data[3]);
}
lapb_transmit_buffer(lapb, skb, LAPB_RESPONSE);
diff --git a/net/lapb/lapb_timer.c b/net/lapb/lapb_timer.c
index f8cd641dfc82..54563ad8aeb1 100644
--- a/net/lapb/lapb_timer.c
+++ b/net/lapb/lapb_timer.c
@@ -14,6 +14,8 @@
* LAPB 002 Jonathan Naylor New timer architecture.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -105,21 +107,17 @@ static void lapb_t1timer_expiry(unsigned long param)
lapb_clear_queues(lapb);
lapb->state = LAPB_STATE_0;
lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S1 -> S0\n", lapb->dev);
return;
} else {
lapb->n2count++;
if (lapb->mode & LAPB_EXTENDED) {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 TX SABME(1)\n", lapb->dev);
-#endif
+ lapb_dbg(1, "(%p) S1 TX SABME(1)\n",
+ lapb->dev);
lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND);
} else {
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S1 TX SABM(1)\n", lapb->dev);
-#endif
+ lapb_dbg(1, "(%p) S1 TX SABM(1)\n",
+ lapb->dev);
lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND);
}
}
@@ -133,15 +131,11 @@ static void lapb_t1timer_expiry(unsigned long param)
lapb_clear_queues(lapb);
lapb->state = LAPB_STATE_0;
lapb_disconnect_confirmation(lapb, LAPB_TIMEDOUT);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S2 -> S0\n", lapb->dev);
return;
} else {
lapb->n2count++;
-#if LAPB_DEBUG > 1
- printk(KERN_DEBUG "lapb: (%p) S2 TX DISC(1)\n", lapb->dev);
-#endif
+ lapb_dbg(1, "(%p) S2 TX DISC(1)\n", lapb->dev);
lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
}
break;
@@ -155,9 +149,7 @@ static void lapb_t1timer_expiry(unsigned long param)
lapb->state = LAPB_STATE_0;
lapb_stop_t2timer(lapb);
lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S3 -> S0\n", lapb->dev);
return;
} else {
lapb->n2count++;
@@ -173,9 +165,7 @@ static void lapb_t1timer_expiry(unsigned long param)
lapb_clear_queues(lapb);
lapb->state = LAPB_STATE_0;
lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
-#if LAPB_DEBUG > 0
- printk(KERN_DEBUG "lapb: (%p) S4 -> S0\n", lapb->dev);
-#endif
+ lapb_dbg(0, "(%p) S4 -> S0\n", lapb->dev);
return;
} else {
lapb->n2count++;
diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c
index 4d5057902839..ee2e5bc5a8c7 100644
--- a/net/netfilter/xt_TEE.c
+++ b/net/netfilter/xt_TEE.c
@@ -87,7 +87,7 @@ tee_tg4(struct sk_buff *skb, const struct xt_action_param *par)
const struct xt_tee_tginfo *info = par->targinfo;
struct iphdr *iph;
- if (percpu_read(tee_active))
+ if (__this_cpu_read(tee_active))
return XT_CONTINUE;
/*
* Copy the skb, and route the copy. Will later return %XT_CONTINUE for
@@ -124,9 +124,9 @@ tee_tg4(struct sk_buff *skb, const struct xt_action_param *par)
ip_send_check(iph);
if (tee_tg_route4(skb, info)) {
- percpu_write(tee_active, true);
+ __this_cpu_write(tee_active, true);
ip_local_out(skb);
- percpu_write(tee_active, false);
+ __this_cpu_write(tee_active, false);
} else {
kfree_skb(skb);
}
@@ -168,7 +168,7 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_tee_tginfo *info = par->targinfo;
- if (percpu_read(tee_active))
+ if (__this_cpu_read(tee_active))
return XT_CONTINUE;
skb = pskb_copy(skb, GFP_ATOMIC);
if (skb == NULL)
@@ -186,9 +186,9 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par)
--iph->hop_limit;
}
if (tee_tg_route6(skb, info)) {
- percpu_write(tee_active, true);
+ __this_cpu_write(tee_active, true);
ip6_local_out(skb);
- percpu_write(tee_active, false);
+ __this_cpu_write(tee_active, false);
} else {
kfree_skb(skb);
}
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index 1afaa284fcd7..7743ea8d1d38 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -22,22 +22,6 @@
#include <net/sock.h>
#include <net/cls_cgroup.h>
-static struct cgroup_subsys_state *cgrp_create(struct cgroup *cgrp);
-static void cgrp_destroy(struct cgroup *cgrp);
-static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp);
-
-struct cgroup_subsys net_cls_subsys = {
- .name = "net_cls",
- .create = cgrp_create,
- .destroy = cgrp_destroy,
- .populate = cgrp_populate,
-#ifdef CONFIG_NET_CLS_CGROUP
- .subsys_id = net_cls_subsys_id,
-#endif
- .module = THIS_MODULE,
-};
-
-
static inline struct cgroup_cls_state *cgrp_cls_state(struct cgroup *cgrp)
{
return container_of(cgroup_subsys_state(cgrp, net_cls_subsys_id),
@@ -86,12 +70,19 @@ static struct cftype ss_files[] = {
.read_u64 = read_classid,
.write_u64 = write_classid,
},
+ { } /* terminate */
};
-static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
-{
- return cgroup_add_files(cgrp, ss, ss_files, ARRAY_SIZE(ss_files));
-}
+struct cgroup_subsys net_cls_subsys = {
+ .name = "net_cls",
+ .create = cgrp_create,
+ .destroy = cgrp_destroy,
+#ifdef CONFIG_NET_CLS_CGROUP
+ .subsys_id = net_cls_subsys_id,
+#endif
+ .base_cftypes = ss_files,
+ .module = THIS_MODULE,
+};
struct cls_cgroup_head {
u32 handle;
diff --git a/net/socket.c b/net/socket.c
index 2a2898ce596e..6e0ccc09b313 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -479,7 +479,7 @@ static struct socket *sock_alloc(void)
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
- percpu_add(sockets_in_use, 1);
+ this_cpu_add(sockets_in_use, 1);
return sock;
}
@@ -522,7 +522,7 @@ void sock_release(struct socket *sock)
if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
printk(KERN_ERR "sock_release: fasync list not empty!\n");
- percpu_sub(sockets_in_use, 1);
+ this_cpu_sub(sockets_in_use, 1);
if (!sock->file) {
iput(SOCK_INODE(sock));
return;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index adf2990acebf..7fee13b331d1 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -127,9 +127,7 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
{
static uint32_t clntid;
char name[15];
- struct qstr q = {
- .name = name,
- };
+ struct qstr q = { .name = name };
struct dentry *dir, *dentry;
int error;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 3b62cf288031..fd2423991c2d 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -1059,12 +1059,9 @@ static const struct rpc_filelist files[] = {
struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
const unsigned char *dir_name)
{
- struct qstr dir = {
- .name = dir_name,
- .len = strlen(dir_name),
- .hash = full_name_hash(dir_name, strlen(dir_name)),
- };
+ struct qstr dir = QSTR_INIT(dir_name, strlen(dir_name));
+ dir.hash = full_name_hash(dir.name, dir.len);
return d_lookup(sb->s_root, &dir);
}
EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 3c87a1c4066f..c53e8f42aa75 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -26,6 +26,7 @@
#include <linux/cache.h>
#include <linux/audit.h>
#include <net/dst.h>
+#include <net/flow.h>
#include <net/xfrm.h>
#include <net/ip.h>
#ifdef CONFIG_XFRM_STATISTICS
diff --git a/samples/Makefile b/samples/Makefile
index 2f75851ec629..5ef08bba96ce 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -1,4 +1,4 @@
# Makefile for Linux samples code
obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ tracepoints/ trace_events/ \
- hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/
+ hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/
diff --git a/samples/seccomp/Makefile b/samples/seccomp/Makefile
new file mode 100644
index 000000000000..16aa2d424985
--- /dev/null
+++ b/samples/seccomp/Makefile
@@ -0,0 +1,32 @@
+# kbuild trick to avoid linker error. Can be omitted if a module is built.
+obj- := dummy.o
+
+hostprogs-$(CONFIG_SECCOMP_FILTER) := bpf-fancy dropper bpf-direct
+
+HOSTCFLAGS_bpf-fancy.o += -I$(objtree)/usr/include
+HOSTCFLAGS_bpf-fancy.o += -idirafter $(objtree)/include
+HOSTCFLAGS_bpf-helper.o += -I$(objtree)/usr/include
+HOSTCFLAGS_bpf-helper.o += -idirafter $(objtree)/include
+bpf-fancy-objs := bpf-fancy.o bpf-helper.o
+
+HOSTCFLAGS_dropper.o += -I$(objtree)/usr/include
+HOSTCFLAGS_dropper.o += -idirafter $(objtree)/include
+dropper-objs := dropper.o
+
+HOSTCFLAGS_bpf-direct.o += -I$(objtree)/usr/include
+HOSTCFLAGS_bpf-direct.o += -idirafter $(objtree)/include
+bpf-direct-objs := bpf-direct.o
+
+# Try to match the kernel target.
+ifeq ($(CONFIG_64BIT),)
+HOSTCFLAGS_bpf-direct.o += -m32
+HOSTCFLAGS_dropper.o += -m32
+HOSTCFLAGS_bpf-helper.o += -m32
+HOSTCFLAGS_bpf-fancy.o += -m32
+HOSTLOADLIBES_bpf-direct += -m32
+HOSTLOADLIBES_bpf-fancy += -m32
+HOSTLOADLIBES_dropper += -m32
+endif
+
+# Tell kbuild to always build the programs
+always := $(hostprogs-y)
diff --git a/samples/seccomp/bpf-direct.c b/samples/seccomp/bpf-direct.c
new file mode 100644
index 000000000000..151ec3f52189
--- /dev/null
+++ b/samples/seccomp/bpf-direct.c
@@ -0,0 +1,190 @@
+/*
+ * Seccomp filter example for x86 (32-bit and 64-bit) with BPF macros
+ *
+ * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
+ * Author: Will Drewry <wad@chromium.org>
+ *
+ * The code may be used by anyone for any purpose,
+ * and can serve as a starting point for developing
+ * applications using prctl(PR_SET_SECCOMP, 2, ...).
+ */
+#if defined(__i386__) || defined(__x86_64__)
+#define SUPPORTED_ARCH 1
+#endif
+
+#if defined(SUPPORTED_ARCH)
+#define __USE_GNU 1
+#define _GNU_SOURCE 1
+
+#include <linux/types.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+#include <linux/unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+
+#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]))
+#define syscall_nr (offsetof(struct seccomp_data, nr))
+
+#if defined(__i386__)
+#define REG_RESULT REG_EAX
+#define REG_SYSCALL REG_EAX
+#define REG_ARG0 REG_EBX
+#define REG_ARG1 REG_ECX
+#define REG_ARG2 REG_EDX
+#define REG_ARG3 REG_ESI
+#define REG_ARG4 REG_EDI
+#define REG_ARG5 REG_EBP
+#elif defined(__x86_64__)
+#define REG_RESULT REG_RAX
+#define REG_SYSCALL REG_RAX
+#define REG_ARG0 REG_RDI
+#define REG_ARG1 REG_RSI
+#define REG_ARG2 REG_RDX
+#define REG_ARG3 REG_R10
+#define REG_ARG4 REG_R8
+#define REG_ARG5 REG_R9
+#endif
+
+#ifndef PR_SET_NO_NEW_PRIVS
+#define PR_SET_NO_NEW_PRIVS 38
+#endif
+
+#ifndef SYS_SECCOMP
+#define SYS_SECCOMP 1
+#endif
+
+static void emulator(int nr, siginfo_t *info, void *void_context)
+{
+ ucontext_t *ctx = (ucontext_t *)(void_context);
+ int syscall;
+ char *buf;
+ ssize_t bytes;
+ size_t len;
+ if (info->si_code != SYS_SECCOMP)
+ return;
+ if (!ctx)
+ return;
+ syscall = ctx->uc_mcontext.gregs[REG_SYSCALL];
+ buf = (char *) ctx->uc_mcontext.gregs[REG_ARG1];
+ len = (size_t) ctx->uc_mcontext.gregs[REG_ARG2];
+
+ if (syscall != __NR_write)
+ return;
+ if (ctx->uc_mcontext.gregs[REG_ARG0] != STDERR_FILENO)
+ return;
+ /* Redirect stderr messages to stdout. Doesn't handle EINTR, etc */
+ ctx->uc_mcontext.gregs[REG_RESULT] = -1;
+ if (write(STDOUT_FILENO, "[ERR] ", 6) > 0) {
+ bytes = write(STDOUT_FILENO, buf, len);
+ ctx->uc_mcontext.gregs[REG_RESULT] = bytes;
+ }
+ return;
+}
+
+static int install_emulator(void)
+{
+ struct sigaction act;
+ sigset_t mask;
+ memset(&act, 0, sizeof(act));
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGSYS);
+
+ act.sa_sigaction = &emulator;
+ act.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGSYS, &act, NULL) < 0) {
+ perror("sigaction");
+ return -1;
+ }
+ if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
+ perror("sigprocmask");
+ return -1;
+ }
+ return 0;
+}
+
+static int install_filter(void)
+{
+ struct sock_filter filter[] = {
+ /* Grab the system call number */
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr),
+ /* Jump table for the allowed syscalls */
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_rt_sigreturn, 0, 1),
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
+#ifdef __NR_sigreturn
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_sigreturn, 0, 1),
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
+#endif
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit_group, 0, 1),
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit, 0, 1),
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_read, 1, 0),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_write, 3, 2),
+
+ /* Check that read is only using stdin. */
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_arg(0)),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDIN_FILENO, 4, 0),
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
+
+ /* Check that write is only using stdout */
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_arg(0)),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDOUT_FILENO, 1, 0),
+ /* Trap attempts to write to stderr */
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDERR_FILENO, 1, 2),
+
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP),
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
+ };
+ struct sock_fprog prog = {
+ .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+ .filter = filter,
+ };
+
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+ perror("prctl(NO_NEW_PRIVS)");
+ return 1;
+ }
+
+
+ if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
+ perror("prctl");
+ return 1;
+ }
+ return 0;
+}
+
+#define payload(_c) (_c), sizeof((_c))
+int main(int argc, char **argv)
+{
+ char buf[4096];
+ ssize_t bytes = 0;
+ if (install_emulator())
+ return 1;
+ if (install_filter())
+ return 1;
+ syscall(__NR_write, STDOUT_FILENO,
+ payload("OHAI! WHAT IS YOUR NAME? "));
+ bytes = syscall(__NR_read, STDIN_FILENO, buf, sizeof(buf));
+ syscall(__NR_write, STDOUT_FILENO, payload("HELLO, "));
+ syscall(__NR_write, STDOUT_FILENO, buf, bytes);
+ syscall(__NR_write, STDERR_FILENO,
+ payload("Error message going to STDERR\n"));
+ return 0;
+}
+#else /* SUPPORTED_ARCH */
+/*
+ * This sample is x86-only. Since kernel samples are compiled with the
+ * host toolchain, a non-x86 host will result in using only the main()
+ * below.
+ */
+int main(void)
+{
+ return 1;
+}
+#endif /* SUPPORTED_ARCH */
diff --git a/samples/seccomp/bpf-fancy.c b/samples/seccomp/bpf-fancy.c
new file mode 100644
index 000000000000..8eb483aaec46
--- /dev/null
+++ b/samples/seccomp/bpf-fancy.c
@@ -0,0 +1,102 @@
+/*
+ * Seccomp BPF example using a macro-based generator.
+ *
+ * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
+ * Author: Will Drewry <wad@chromium.org>
+ *
+ * The code may be used by anyone for any purpose,
+ * and can serve as a starting point for developing
+ * applications using prctl(PR_ATTACH_SECCOMP_FILTER).
+ */
+
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+#include <linux/unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+
+#include "bpf-helper.h"
+
+#ifndef PR_SET_NO_NEW_PRIVS
+#define PR_SET_NO_NEW_PRIVS 38
+#endif
+
+int main(int argc, char **argv)
+{
+ struct bpf_labels l;
+ static const char msg1[] = "Please type something: ";
+ static const char msg2[] = "You typed: ";
+ char buf[256];
+ struct sock_filter filter[] = {
+ /* TODO: LOAD_SYSCALL_NR(arch) and enforce an arch */
+ LOAD_SYSCALL_NR,
+ SYSCALL(__NR_exit, ALLOW),
+ SYSCALL(__NR_exit_group, ALLOW),
+ SYSCALL(__NR_write, JUMP(&l, write_fd)),
+ SYSCALL(__NR_read, JUMP(&l, read)),
+ DENY, /* Don't passthrough into a label */
+
+ LABEL(&l, read),
+ ARG(0),
+ JNE(STDIN_FILENO, DENY),
+ ARG(1),
+ JNE((unsigned long)buf, DENY),
+ ARG(2),
+ JGE(sizeof(buf), DENY),
+ ALLOW,
+
+ LABEL(&l, write_fd),
+ ARG(0),
+ JEQ(STDOUT_FILENO, JUMP(&l, write_buf)),
+ JEQ(STDERR_FILENO, JUMP(&l, write_buf)),
+ DENY,
+
+ LABEL(&l, write_buf),
+ ARG(1),
+ JEQ((unsigned long)msg1, JUMP(&l, msg1_len)),
+ JEQ((unsigned long)msg2, JUMP(&l, msg2_len)),
+ JEQ((unsigned long)buf, JUMP(&l, buf_len)),
+ DENY,
+
+ LABEL(&l, msg1_len),
+ ARG(2),
+ JLT(sizeof(msg1), ALLOW),
+ DENY,
+
+ LABEL(&l, msg2_len),
+ ARG(2),
+ JLT(sizeof(msg2), ALLOW),
+ DENY,
+
+ LABEL(&l, buf_len),
+ ARG(2),
+ JLT(sizeof(buf), ALLOW),
+ DENY,
+ };
+ struct sock_fprog prog = {
+ .filter = filter,
+ .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+ };
+ ssize_t bytes;
+ bpf_resolve_jumps(&l, filter, sizeof(filter)/sizeof(*filter));
+
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+ perror("prctl(NO_NEW_PRIVS)");
+ return 1;
+ }
+
+ if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
+ perror("prctl(SECCOMP)");
+ return 1;
+ }
+ syscall(__NR_write, STDOUT_FILENO, msg1, strlen(msg1));
+ bytes = syscall(__NR_read, STDIN_FILENO, buf, sizeof(buf)-1);
+ bytes = (bytes > 0 ? bytes : 0);
+ syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2));
+ syscall(__NR_write, STDERR_FILENO, buf, bytes);
+ /* Now get killed */
+ syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2)+2);
+ return 0;
+}
diff --git a/samples/seccomp/bpf-helper.c b/samples/seccomp/bpf-helper.c
new file mode 100644
index 000000000000..579cfe331886
--- /dev/null
+++ b/samples/seccomp/bpf-helper.c
@@ -0,0 +1,89 @@
+/*
+ * Seccomp BPF helper functions
+ *
+ * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
+ * Author: Will Drewry <wad@chromium.org>
+ *
+ * The code may be used by anyone for any purpose,
+ * and can serve as a starting point for developing
+ * applications using prctl(PR_ATTACH_SECCOMP_FILTER).
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "bpf-helper.h"
+
+int bpf_resolve_jumps(struct bpf_labels *labels,
+ struct sock_filter *filter, size_t count)
+{
+ struct sock_filter *begin = filter;
+ __u8 insn = count - 1;
+
+ if (count < 1)
+ return -1;
+ /*
+ * Walk it once, backwards, to build the label table and do fixups.
+ * Since backward jumps are disallowed by BPF, this is easy.
+ */
+ filter += insn;
+ for (; filter >= begin; --insn, --filter) {
+ if (filter->code != (BPF_JMP+BPF_JA))
+ continue;
+ switch ((filter->jt<<8)|filter->jf) {
+ case (JUMP_JT<<8)|JUMP_JF:
+ if (labels->labels[filter->k].location == 0xffffffff) {
+ fprintf(stderr, "Unresolved label: '%s'\n",
+ labels->labels[filter->k].label);
+ return 1;
+ }
+ filter->k = labels->labels[filter->k].location -
+ (insn + 1);
+ filter->jt = 0;
+ filter->jf = 0;
+ continue;
+ case (LABEL_JT<<8)|LABEL_JF:
+ if (labels->labels[filter->k].location != 0xffffffff) {
+ fprintf(stderr, "Duplicate label use: '%s'\n",
+ labels->labels[filter->k].label);
+ return 1;
+ }
+ labels->labels[filter->k].location = insn;
+ filter->k = 0; /* fall through */
+ filter->jt = 0;
+ filter->jf = 0;
+ continue;
+ }
+ }
+ return 0;
+}
+
+/* Simple lookup table for labels. */
+__u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label)
+{
+ struct __bpf_label *begin = labels->labels, *end;
+ int id;
+ if (labels->count == 0) {
+ begin->label = label;
+ begin->location = 0xffffffff;
+ labels->count++;
+ return 0;
+ }
+ end = begin + labels->count;
+ for (id = 0; begin < end; ++begin, ++id) {
+ if (!strcmp(label, begin->label))
+ return id;
+ }
+ begin->label = label;
+ begin->location = 0xffffffff;
+ labels->count++;
+ return id;
+}
+
+void seccomp_bpf_print(struct sock_filter *filter, size_t count)
+{
+ struct sock_filter *end = filter + count;
+ for ( ; filter < end; ++filter)
+ printf("{ code=%u,jt=%u,jf=%u,k=%u },\n",
+ filter->code, filter->jt, filter->jf, filter->k);
+}
diff --git a/samples/seccomp/bpf-helper.h b/samples/seccomp/bpf-helper.h
new file mode 100644
index 000000000000..643279dd30fb
--- /dev/null
+++ b/samples/seccomp/bpf-helper.h
@@ -0,0 +1,238 @@
+/*
+ * Example wrapper around BPF macros.
+ *
+ * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
+ * Author: Will Drewry <wad@chromium.org>
+ *
+ * The code may be used by anyone for any purpose,
+ * and can serve as a starting point for developing
+ * applications using prctl(PR_SET_SECCOMP, 2, ...).
+ *
+ * No guarantees are provided with respect to the correctness
+ * or functionality of this code.
+ */
+#ifndef __BPF_HELPER_H__
+#define __BPF_HELPER_H__
+
+#include <asm/bitsperlong.h> /* for __BITS_PER_LONG */
+#include <endian.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h> /* for seccomp_data */
+#include <linux/types.h>
+#include <linux/unistd.h>
+#include <stddef.h>
+
+#define BPF_LABELS_MAX 256
+struct bpf_labels {
+ int count;
+ struct __bpf_label {
+ const char *label;
+ __u32 location;
+ } labels[BPF_LABELS_MAX];
+};
+
+int bpf_resolve_jumps(struct bpf_labels *labels,
+ struct sock_filter *filter, size_t count);
+__u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label);
+void seccomp_bpf_print(struct sock_filter *filter, size_t count);
+
+#define JUMP_JT 0xff
+#define JUMP_JF 0xff
+#define LABEL_JT 0xfe
+#define LABEL_JF 0xfe
+
+#define ALLOW \
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
+#define DENY \
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
+#define JUMP(labels, label) \
+ BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
+ JUMP_JT, JUMP_JF)
+#define LABEL(labels, label) \
+ BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
+ LABEL_JT, LABEL_JF)
+#define SYSCALL(nr, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (nr), 0, 1), \
+ jt
+
+/* Lame, but just an example */
+#define FIND_LABEL(labels, label) seccomp_bpf_label((labels), #label)
+
+#define EXPAND(...) __VA_ARGS__
+/* Map all width-sensitive operations */
+#if __BITS_PER_LONG == 32
+
+#define JEQ(x, jt) JEQ32(x, EXPAND(jt))
+#define JNE(x, jt) JNE32(x, EXPAND(jt))
+#define JGT(x, jt) JGT32(x, EXPAND(jt))
+#define JLT(x, jt) JLT32(x, EXPAND(jt))
+#define JGE(x, jt) JGE32(x, EXPAND(jt))
+#define JLE(x, jt) JLE32(x, EXPAND(jt))
+#define JA(x, jt) JA32(x, EXPAND(jt))
+#define ARG(i) ARG_32(i)
+#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
+
+#elif __BITS_PER_LONG == 64
+
+/* Ensure that we load the logically correct offset. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define ENDIAN(_lo, _hi) _lo, _hi
+#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
+#define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define ENDIAN(_lo, _hi) _hi, _lo
+#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
+#define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
+#else
+#error "Unknown endianness"
+#endif
+
+union arg64 {
+ struct {
+ __u32 ENDIAN(lo32, hi32);
+ };
+ __u64 u64;
+};
+
+#define JEQ(x, jt) \
+ JEQ64(((union arg64){.u64 = (x)}).lo32, \
+ ((union arg64){.u64 = (x)}).hi32, \
+ EXPAND(jt))
+#define JGT(x, jt) \
+ JGT64(((union arg64){.u64 = (x)}).lo32, \
+ ((union arg64){.u64 = (x)}).hi32, \
+ EXPAND(jt))
+#define JGE(x, jt) \
+ JGE64(((union arg64){.u64 = (x)}).lo32, \
+ ((union arg64){.u64 = (x)}).hi32, \
+ EXPAND(jt))
+#define JNE(x, jt) \
+ JNE64(((union arg64){.u64 = (x)}).lo32, \
+ ((union arg64){.u64 = (x)}).hi32, \
+ EXPAND(jt))
+#define JLT(x, jt) \
+ JLT64(((union arg64){.u64 = (x)}).lo32, \
+ ((union arg64){.u64 = (x)}).hi32, \
+ EXPAND(jt))
+#define JLE(x, jt) \
+ JLE64(((union arg64){.u64 = (x)}).lo32, \
+ ((union arg64){.u64 = (x)}).hi32, \
+ EXPAND(jt))
+
+#define JA(x, jt) \
+ JA64(((union arg64){.u64 = (x)}).lo32, \
+ ((union arg64){.u64 = (x)}).hi32, \
+ EXPAND(jt))
+#define ARG(i) ARG_64(i)
+
+#else
+#error __BITS_PER_LONG value unusable.
+#endif
+
+/* Loads the arg into A */
+#define ARG_32(idx) \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx))
+
+/* Loads hi into A and lo in X */
+#define ARG_64(idx) \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)), \
+ BPF_STMT(BPF_ST, 0), /* lo -> M[0] */ \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, HI_ARG(idx)), \
+ BPF_STMT(BPF_ST, 1) /* hi -> M[1] */
+
+#define JEQ32(value, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 0, 1), \
+ jt
+
+#define JNE32(value, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 1, 0), \
+ jt
+
+/* Checks the lo, then swaps to check the hi. A=lo,X=hi */
+#define JEQ64(lo, hi, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+ BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 0, 2), \
+ BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+ jt, \
+ BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define JNE64(lo, hi, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 5, 0), \
+ BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 2, 0), \
+ BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+ jt, \
+ BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define JA32(value, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \
+ jt
+
+#define JA64(lo, hi, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (hi), 3, 0), \
+ BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+ BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (lo), 0, 2), \
+ BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+ jt, \
+ BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define JGE32(value, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \
+ jt
+
+#define JLT32(value, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \
+ jt
+
+/* Shortcut checking if hi > arg.hi. */
+#define JGE64(lo, hi, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+ BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 0, 2), \
+ BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+ jt, \
+ BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define JLT64(lo, hi, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+ BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
+ BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+ jt, \
+ BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define JGT32(value, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \
+ jt
+
+#define JLE32(value, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \
+ jt
+
+/* Check hi > args.hi first, then do the GE checking */
+#define JGT64(lo, hi, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+ BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 0, 2), \
+ BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+ jt, \
+ BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define JLE64(lo, hi, jt) \
+ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 6, 0), \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \
+ BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
+ BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+ jt, \
+ BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define LOAD_SYSCALL_NR \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
+ offsetof(struct seccomp_data, nr))
+
+#endif /* __BPF_HELPER_H__ */
diff --git a/samples/seccomp/dropper.c b/samples/seccomp/dropper.c
new file mode 100644
index 000000000000..c69c347c7011
--- /dev/null
+++ b/samples/seccomp/dropper.c
@@ -0,0 +1,68 @@
+/*
+ * Naive system call dropper built on seccomp_filter.
+ *
+ * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
+ * Author: Will Drewry <wad@chromium.org>
+ *
+ * The code may be used by anyone for any purpose,
+ * and can serve as a starting point for developing
+ * applications using prctl(PR_SET_SECCOMP, 2, ...).
+ *
+ * When run, returns the specified errno for the specified
+ * system call number against the given architecture.
+ *
+ * Run this one as root as PR_SET_NO_NEW_PRIVS is not called.
+ */
+
+#include <errno.h>
+#include <linux/audit.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+#include <linux/unistd.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+
+static int install_filter(int nr, int arch, int error)
+{
+ struct sock_filter filter[] = {
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
+ (offsetof(struct seccomp_data, arch))),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, arch, 0, 3),
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
+ (offsetof(struct seccomp_data, nr))),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, nr, 0, 1),
+ BPF_STMT(BPF_RET+BPF_K,
+ SECCOMP_RET_ERRNO|(error & SECCOMP_RET_DATA)),
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
+ };
+ struct sock_fprog prog = {
+ .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+ .filter = filter,
+ };
+ if (prctl(PR_SET_SECCOMP, 2, &prog)) {
+ perror("prctl");
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 5) {
+ fprintf(stderr, "Usage:\n"
+ "dropper <syscall_nr> <arch> <errno> <prog> [<args>]\n"
+ "Hint: AUDIT_ARCH_I386: 0x%X\n"
+ " AUDIT_ARCH_X86_64: 0x%X\n"
+ "\n", AUDIT_ARCH_I386, AUDIT_ARCH_X86_64);
+ return 1;
+ }
+ if (install_filter(strtol(argv[1], NULL, 0), strtol(argv[2], NULL, 0),
+ strtol(argv[3], NULL, 0)))
+ return 1;
+ execv(argv[4], &argv[4]);
+ printf("Failed to execv\n");
+ return 255;
+}
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 105b21f08185..65f362d931b5 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -9,3 +9,4 @@ unifdef
ihex2fw
recordmcount
docproc
+sortextable
diff --git a/scripts/Makefile b/scripts/Makefile
index df7678febf27..a55b0067758a 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -8,11 +8,16 @@
# conmakehash: Create arrays for initializing the kernel console tables
# docproc: Used in Documentation/DocBook
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include
+
hostprogs-$(CONFIG_KALLSYMS) += kallsyms
hostprogs-$(CONFIG_LOGO) += pnmtologo
hostprogs-$(CONFIG_VT) += conmakehash
hostprogs-$(CONFIG_IKCONFIG) += bin2c
hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
+hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
+
+HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include
always := $(hostprogs-y) $(hostprogs-m)
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 44ddaa542db6..5759751a1f61 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -336,10 +336,13 @@ static int do_hid_entry(const char *filename,
struct hid_device_id *id, char *alias)
{
id->bus = TO_NATIVE(id->bus);
+ id->group = TO_NATIVE(id->group);
id->vendor = TO_NATIVE(id->vendor);
id->product = TO_NATIVE(id->product);
- sprintf(alias, "hid:b%04X", id->bus);
+ sprintf(alias, "hid:");
+ ADD(alias, "b", id->bus != HID_BUS_ANY, id->bus);
+ ADD(alias, "g", id->group != HID_GROUP_ANY, id->group);
ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor);
ADD(alias, "p", id->product != HID_ANY_ID, id->product);
diff --git a/scripts/sortextable.c b/scripts/sortextable.c
new file mode 100644
index 000000000000..1ca9ceb95eb6
--- /dev/null
+++ b/scripts/sortextable.c
@@ -0,0 +1,322 @@
+/*
+ * sortextable.c: Sort the kernel's exception table
+ *
+ * Copyright 2011 - 2012 Cavium, Inc.
+ *
+ * Based on code taken from recortmcount.c which is:
+ *
+ * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
+ * Licensed under the GNU General Public License, version 2 (GPLv2).
+ *
+ * Restructured to fit Linux format, as well as other updates:
+ * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
+ */
+
+/*
+ * Strategy: alter the vmlinux file in-place.
+ */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <getopt.h>
+#include <elf.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <tools/be_byteshift.h>
+#include <tools/le_byteshift.h>
+
+static int fd_map; /* File descriptor for file being modified. */
+static int mmap_failed; /* Boolean flag. */
+static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */
+static struct stat sb; /* Remember .st_size, etc. */
+static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
+
+/* setjmp() return values */
+enum {
+ SJ_SETJMP = 0, /* hardwired first return */
+ SJ_FAIL,
+ SJ_SUCCEED
+};
+
+/* Per-file resource cleanup when multiple files. */
+static void
+cleanup(void)
+{
+ if (!mmap_failed)
+ munmap(ehdr_curr, sb.st_size);
+ close(fd_map);
+}
+
+static void __attribute__((noreturn))
+fail_file(void)
+{
+ cleanup();
+ longjmp(jmpenv, SJ_FAIL);
+}
+
+static void __attribute__((noreturn))
+succeed_file(void)
+{
+ cleanup();
+ longjmp(jmpenv, SJ_SUCCEED);
+}
+
+
+/*
+ * Get the whole file as a programming convenience in order to avoid
+ * malloc+lseek+read+free of many pieces. If successful, then mmap
+ * avoids copying unused pieces; else just read the whole file.
+ * Open for both read and write.
+ */
+static void *mmap_file(char const *fname)
+{
+ void *addr;
+
+ fd_map = open(fname, O_RDWR);
+ if (fd_map < 0 || fstat(fd_map, &sb) < 0) {
+ perror(fname);
+ fail_file();
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ fprintf(stderr, "not a regular file: %s\n", fname);
+ fail_file();
+ }
+ addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ fd_map, 0);
+ if (addr == MAP_FAILED) {
+ mmap_failed = 1;
+ fprintf(stderr, "Could not mmap file: %s\n", fname);
+ fail_file();
+ }
+ return addr;
+}
+
+static uint64_t r8be(const uint64_t *x)
+{
+ return get_unaligned_be64(x);
+}
+static uint32_t rbe(const uint32_t *x)
+{
+ return get_unaligned_be32(x);
+}
+static uint16_t r2be(const uint16_t *x)
+{
+ return get_unaligned_be16(x);
+}
+static uint64_t r8le(const uint64_t *x)
+{
+ return get_unaligned_le64(x);
+}
+static uint32_t rle(const uint32_t *x)
+{
+ return get_unaligned_le32(x);
+}
+static uint16_t r2le(const uint16_t *x)
+{
+ return get_unaligned_le16(x);
+}
+
+static void w8be(uint64_t val, uint64_t *x)
+{
+ put_unaligned_be64(val, x);
+}
+static void wbe(uint32_t val, uint32_t *x)
+{
+ put_unaligned_be32(val, x);
+}
+static void w2be(uint16_t val, uint16_t *x)
+{
+ put_unaligned_be16(val, x);
+}
+static void w8le(uint64_t val, uint64_t *x)
+{
+ put_unaligned_le64(val, x);
+}
+static void wle(uint32_t val, uint32_t *x)
+{
+ put_unaligned_le32(val, x);
+}
+static void w2le(uint16_t val, uint16_t *x)
+{
+ put_unaligned_le16(val, x);
+}
+
+static uint64_t (*r8)(const uint64_t *);
+static uint32_t (*r)(const uint32_t *);
+static uint16_t (*r2)(const uint16_t *);
+static void (*w8)(uint64_t, uint64_t *);
+static void (*w)(uint32_t, uint32_t *);
+static void (*w2)(uint16_t, uint16_t *);
+
+typedef void (*table_sort_t)(char *, int);
+
+/* 32 bit and 64 bit are very similar */
+#include "sortextable.h"
+#define SORTEXTABLE_64
+#include "sortextable.h"
+
+static int compare_x86_table(const void *a, const void *b)
+{
+ int32_t av = (int32_t)r(a);
+ int32_t bv = (int32_t)r(b);
+
+ if (av < bv)
+ return -1;
+ if (av > bv)
+ return 1;
+ return 0;
+}
+
+static void sort_x86_table(char *extab_image, int image_size)
+{
+ int i;
+
+ /*
+ * Do the same thing the runtime sort does, first normalize to
+ * being relative to the start of the section.
+ */
+ i = 0;
+ while (i < image_size) {
+ uint32_t *loc = (uint32_t *)(extab_image + i);
+ w(r(loc) + i, loc);
+ i += 4;
+ }
+
+ qsort(extab_image, image_size / 8, 8, compare_x86_table);
+
+ /* Now denormalize. */
+ i = 0;
+ while (i < image_size) {
+ uint32_t *loc = (uint32_t *)(extab_image + i);
+ w(r(loc) - i, loc);
+ i += 4;
+ }
+}
+
+static void
+do_file(char const *const fname)
+{
+ table_sort_t custom_sort;
+ Elf32_Ehdr *ehdr = mmap_file(fname);
+
+ ehdr_curr = ehdr;
+ switch (ehdr->e_ident[EI_DATA]) {
+ default:
+ fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
+ ehdr->e_ident[EI_DATA], fname);
+ fail_file();
+ break;
+ case ELFDATA2LSB:
+ r = rle;
+ r2 = r2le;
+ r8 = r8le;
+ w = wle;
+ w2 = w2le;
+ w8 = w8le;
+ break;
+ case ELFDATA2MSB:
+ r = rbe;
+ r2 = r2be;
+ r8 = r8be;
+ w = wbe;
+ w2 = w2be;
+ w8 = w8be;
+ break;
+ } /* end switch */
+ if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0
+ || r2(&ehdr->e_type) != ET_EXEC
+ || ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
+ fprintf(stderr, "unrecognized ET_EXEC file %s\n", fname);
+ fail_file();
+ }
+
+ custom_sort = NULL;
+ switch (r2(&ehdr->e_machine)) {
+ default:
+ fprintf(stderr, "unrecognized e_machine %d %s\n",
+ r2(&ehdr->e_machine), fname);
+ fail_file();
+ break;
+ case EM_386:
+ case EM_X86_64:
+ custom_sort = sort_x86_table;
+ break;
+ case EM_MIPS:
+ break;
+ } /* end switch */
+
+ switch (ehdr->e_ident[EI_CLASS]) {
+ default:
+ fprintf(stderr, "unrecognized ELF class %d %s\n",
+ ehdr->e_ident[EI_CLASS], fname);
+ fail_file();
+ break;
+ case ELFCLASS32:
+ if (r2(&ehdr->e_ehsize) != sizeof(Elf32_Ehdr)
+ || r2(&ehdr->e_shentsize) != sizeof(Elf32_Shdr)) {
+ fprintf(stderr,
+ "unrecognized ET_EXEC file: %s\n", fname);
+ fail_file();
+ }
+ do32(ehdr, fname, custom_sort);
+ break;
+ case ELFCLASS64: {
+ Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
+ if (r2(&ghdr->e_ehsize) != sizeof(Elf64_Ehdr)
+ || r2(&ghdr->e_shentsize) != sizeof(Elf64_Shdr)) {
+ fprintf(stderr,
+ "unrecognized ET_EXEC file: %s\n", fname);
+ fail_file();
+ }
+ do64(ghdr, fname, custom_sort);
+ break;
+ }
+ } /* end switch */
+
+ cleanup();
+}
+
+int
+main(int argc, char *argv[])
+{
+ int n_error = 0; /* gcc-4.3.0 false positive complaint */
+ int i;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: sortextable vmlinux...\n");
+ return 0;
+ }
+
+ /* Process each file in turn, allowing deep failure. */
+ for (i = 1; i < argc; i++) {
+ char *file = argv[i];
+ int const sjval = setjmp(jmpenv);
+
+ switch (sjval) {
+ default:
+ fprintf(stderr, "internal error: %s\n", file);
+ exit(1);
+ break;
+ case SJ_SETJMP: /* normal sequence */
+ /* Avoid problems if early cleanup() */
+ fd_map = -1;
+ ehdr_curr = NULL;
+ mmap_failed = 1;
+ do_file(file);
+ break;
+ case SJ_FAIL: /* error in do_file or below */
+ ++n_error;
+ break;
+ case SJ_SUCCEED: /* premature success */
+ /* do nothing */
+ break;
+ } /* end switch */
+ }
+ return !!n_error;
+}
diff --git a/scripts/sortextable.h b/scripts/sortextable.h
new file mode 100644
index 000000000000..e4fd45b7e456
--- /dev/null
+++ b/scripts/sortextable.h
@@ -0,0 +1,191 @@
+/*
+ * sortextable.h
+ *
+ * Copyright 2011 - 2012 Cavium, Inc.
+ *
+ * Some of this code was taken out of recordmcount.h written by:
+ *
+ * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
+ * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
+ *
+ *
+ * Licensed under the GNU General Public License, version 2 (GPLv2).
+ */
+
+#undef extable_ent_size
+#undef compare_extable
+#undef do_func
+#undef Elf_Addr
+#undef Elf_Ehdr
+#undef Elf_Shdr
+#undef Elf_Rel
+#undef Elf_Rela
+#undef Elf_Sym
+#undef ELF_R_SYM
+#undef Elf_r_sym
+#undef ELF_R_INFO
+#undef Elf_r_info
+#undef ELF_ST_BIND
+#undef ELF_ST_TYPE
+#undef fn_ELF_R_SYM
+#undef fn_ELF_R_INFO
+#undef uint_t
+#undef _r
+#undef _w
+
+#ifdef SORTEXTABLE_64
+# define extable_ent_size 16
+# define compare_extable compare_extable_64
+# define do_func do64
+# define Elf_Addr Elf64_Addr
+# define Elf_Ehdr Elf64_Ehdr
+# define Elf_Shdr Elf64_Shdr
+# define Elf_Rel Elf64_Rel
+# define Elf_Rela Elf64_Rela
+# define Elf_Sym Elf64_Sym
+# define ELF_R_SYM ELF64_R_SYM
+# define Elf_r_sym Elf64_r_sym
+# define ELF_R_INFO ELF64_R_INFO
+# define Elf_r_info Elf64_r_info
+# define ELF_ST_BIND ELF64_ST_BIND
+# define ELF_ST_TYPE ELF64_ST_TYPE
+# define fn_ELF_R_SYM fn_ELF64_R_SYM
+# define fn_ELF_R_INFO fn_ELF64_R_INFO
+# define uint_t uint64_t
+# define _r r8
+# define _w w8
+#else
+# define extable_ent_size 8
+# define compare_extable compare_extable_32
+# define do_func do32
+# define Elf_Addr Elf32_Addr
+# define Elf_Ehdr Elf32_Ehdr
+# define Elf_Shdr Elf32_Shdr
+# define Elf_Rel Elf32_Rel
+# define Elf_Rela Elf32_Rela
+# define Elf_Sym Elf32_Sym
+# define ELF_R_SYM ELF32_R_SYM
+# define Elf_r_sym Elf32_r_sym
+# define ELF_R_INFO ELF32_R_INFO
+# define Elf_r_info Elf32_r_info
+# define ELF_ST_BIND ELF32_ST_BIND
+# define ELF_ST_TYPE ELF32_ST_TYPE
+# define fn_ELF_R_SYM fn_ELF32_R_SYM
+# define fn_ELF_R_INFO fn_ELF32_R_INFO
+# define uint_t uint32_t
+# define _r r
+# define _w w
+#endif
+
+static int compare_extable(const void *a, const void *b)
+{
+ Elf_Addr av = _r(a);
+ Elf_Addr bv = _r(b);
+
+ if (av < bv)
+ return -1;
+ if (av > bv)
+ return 1;
+ return 0;
+}
+
+static void
+do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
+{
+ Elf_Shdr *shdr;
+ Elf_Shdr *shstrtab_sec;
+ Elf_Shdr *strtab_sec = NULL;
+ Elf_Shdr *symtab_sec = NULL;
+ Elf_Shdr *extab_sec = NULL;
+ Elf_Sym *sym;
+ Elf_Sym *sort_needed_sym;
+ Elf_Shdr *sort_needed_sec;
+ Elf_Rel *relocs = NULL;
+ int relocs_size;
+ uint32_t *sort_done_location;
+ const char *secstrtab;
+ const char *strtab;
+ char *extab_image;
+ int extab_index = 0;
+ int i;
+ int idx;
+
+ shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff));
+ shstrtab_sec = shdr + r2(&ehdr->e_shstrndx);
+ secstrtab = (const char *)ehdr + _r(&shstrtab_sec->sh_offset);
+ for (i = 0; i < r2(&ehdr->e_shnum); i++) {
+ idx = r(&shdr[i].sh_name);
+ if (strcmp(secstrtab + idx, "__ex_table") == 0) {
+ extab_sec = shdr + i;
+ extab_index = i;
+ }
+ if ((r(&shdr[i].sh_type) == SHT_REL ||
+ r(&shdr[i].sh_type) == SHT_RELA) &&
+ r(&shdr[i].sh_info) == extab_index) {
+ relocs = (void *)ehdr + _r(&shdr[i].sh_offset);
+ relocs_size = _r(&shdr[i].sh_size);
+ }
+ if (strcmp(secstrtab + idx, ".symtab") == 0)
+ symtab_sec = shdr + i;
+ if (strcmp(secstrtab + idx, ".strtab") == 0)
+ strtab_sec = shdr + i;
+ }
+ if (strtab_sec == NULL) {
+ fprintf(stderr, "no .strtab in file: %s\n", fname);
+ fail_file();
+ }
+ if (symtab_sec == NULL) {
+ fprintf(stderr, "no .symtab in file: %s\n", fname);
+ fail_file();
+ }
+ if (extab_sec == NULL) {
+ fprintf(stderr, "no __ex_table in file: %s\n", fname);
+ fail_file();
+ }
+ strtab = (const char *)ehdr + _r(&strtab_sec->sh_offset);
+
+ extab_image = (void *)ehdr + _r(&extab_sec->sh_offset);
+
+ if (custom_sort) {
+ custom_sort(extab_image, _r(&extab_sec->sh_size));
+ } else {
+ int num_entries = _r(&extab_sec->sh_size) / extable_ent_size;
+ qsort(extab_image, num_entries,
+ extable_ent_size, compare_extable);
+ }
+ /* If there were relocations, we no longer need them. */
+ if (relocs)
+ memset(relocs, 0, relocs_size);
+
+ /* find main_extable_sort_needed */
+ sort_needed_sym = NULL;
+ for (i = 0; i < _r(&symtab_sec->sh_size) / sizeof(Elf_Sym); i++) {
+ sym = (void *)ehdr + _r(&symtab_sec->sh_offset);
+ sym += i;
+ if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
+ continue;
+ idx = r(&sym->st_name);
+ if (strcmp(strtab + idx, "main_extable_sort_needed") == 0) {
+ sort_needed_sym = sym;
+ break;
+ }
+ }
+ if (sort_needed_sym == NULL) {
+ fprintf(stderr,
+ "no main_extable_sort_needed symbol in file: %s\n",
+ fname);
+ fail_file();
+ }
+ sort_needed_sec = &shdr[r2(&sort_needed_sym->st_shndx)];
+ sort_done_location = (void *)ehdr +
+ _r(&sort_needed_sec->sh_offset) +
+ _r(&sort_needed_sym->st_value) -
+ _r(&sort_needed_sec->sh_addr);
+
+#if 1
+ printf("sort done marker at %lx\n",
+ (unsigned long)((char *)sort_done_location - (char *)ehdr));
+#endif
+ /* We sorted it, clear the flag. */
+ w(0, sort_done_location);
+}
diff --git a/security/Kconfig b/security/Kconfig
index ccc61f8006b2..e9c6ac724fef 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -4,73 +4,7 @@
menu "Security options"
-config KEYS
- bool "Enable access key retention support"
- help
- This option provides support for retaining authentication tokens and
- access keys in the kernel.
-
- It also includes provision of methods by which such keys might be
- associated with a process so that network filesystems, encryption
- support and the like can find them.
-
- Furthermore, a special type of key is available that acts as keyring:
- a searchable sequence of keys. Each process is equipped with access
- to five standard keyrings: UID-specific, GID-specific, session,
- process and thread.
-
- If you are unsure as to whether this is required, answer N.
-
-config TRUSTED_KEYS
- tristate "TRUSTED KEYS"
- depends on KEYS && TCG_TPM
- select CRYPTO
- select CRYPTO_HMAC
- select CRYPTO_SHA1
- help
- This option provides support for creating, sealing, and unsealing
- keys in the kernel. Trusted keys are random number symmetric keys,
- generated and RSA-sealed by the TPM. The TPM only unseals the keys,
- if the boot PCRs and other criteria match. Userspace will only ever
- see encrypted blobs.
-
- If you are unsure as to whether this is required, answer N.
-
-config ENCRYPTED_KEYS
- tristate "ENCRYPTED KEYS"
- depends on KEYS
- select CRYPTO
- select CRYPTO_HMAC
- select CRYPTO_AES
- select CRYPTO_CBC
- select CRYPTO_SHA256
- select CRYPTO_RNG
- help
- This option provides support for create/encrypting/decrypting keys
- in the kernel. Encrypted keys are kernel generated random numbers,
- which are encrypted/decrypted with a 'master' symmetric key. The
- 'master' key can be either a trusted-key or user-key type.
- Userspace only ever sees/stores encrypted blobs.
-
- If you are unsure as to whether this is required, answer N.
-
-config KEYS_DEBUG_PROC_KEYS
- bool "Enable the /proc/keys file by which keys may be viewed"
- depends on KEYS
- help
- This option turns on support for the /proc/keys file - through which
- can be listed all the keys on the system that are viewable by the
- reading process.
-
- The only keys included in the list are those that grant View
- permission to the reading process whether or not it possesses them.
- Note that LSM security checks are still performed, and may further
- filter out keys that the current process is not authorised to view.
-
- Only key attributes are listed here; key payloads are not included in
- the resulting table.
-
- If you are unsure as to whether this is required, answer N.
+source security/keys/Kconfig
config SECURITY_DMESG_RESTRICT
bool "Restrict unprivileged access to the kernel syslog"
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
index cc3520d39a78..3ae28db5a64f 100644
--- a/security/apparmor/audit.c
+++ b/security/apparmor/audit.c
@@ -111,7 +111,7 @@ static const char *const aa_audit_type[] = {
static void audit_pre(struct audit_buffer *ab, void *ca)
{
struct common_audit_data *sa = ca;
- struct task_struct *tsk = sa->tsk ? sa->tsk : current;
+ struct task_struct *tsk = sa->aad->tsk ? sa->aad->tsk : current;
if (aa_g_audit_header) {
audit_log_format(ab, "apparmor=");
@@ -149,6 +149,12 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, sa->aad->name);
}
+
+ if (sa->aad->tsk) {
+ audit_log_format(ab, " pid=%d comm=", tsk->pid);
+ audit_log_untrustedstring(ab, tsk->comm);
+ }
+
}
/**
@@ -205,7 +211,8 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
aa_audit_msg(type, sa, cb);
if (sa->aad->type == AUDIT_APPARMOR_KILL)
- (void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current);
+ (void)send_sig_info(SIGKILL, NULL,
+ sa->aad->tsk ? sa->aad->tsk : current);
if (sa->aad->type == AUDIT_APPARMOR_ALLOWED)
return complain_error(sa->aad->error);
diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
index 088dba3bf7dc..887a5e948945 100644
--- a/security/apparmor/capability.c
+++ b/security/apparmor/capability.c
@@ -65,10 +65,10 @@ static int audit_caps(struct aa_profile *profile, struct task_struct *task,
int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
- COMMON_AUDIT_DATA_INIT(&sa, CAP);
+ sa.type = LSM_AUDIT_DATA_CAP;
sa.aad = &aad;
- sa.tsk = task;
sa.u.cap = cap;
+ sa.aad->tsk = task;
sa.aad->op = OP_CAPABLE;
sa.aad->error = error;
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 6327685c101e..b81ea10a17a3 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -394,6 +394,11 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
new_profile = find_attach(ns, &ns->base.profiles, name);
if (!new_profile)
goto cleanup;
+ /*
+ * NOTE: Domain transitions from unconfined are allowed
+ * even when no_new_privs is set because this aways results
+ * in a further reduction of permissions.
+ */
goto apply;
}
@@ -455,6 +460,16 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
/* fail exec */
error = -EACCES;
+ /*
+ * Policy has specified a domain transition, if no_new_privs then
+ * fail the exec.
+ */
+ if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) {
+ aa_put_profile(new_profile);
+ error = -EPERM;
+ goto cleanup;
+ }
+
if (!new_profile)
goto audit;
@@ -609,6 +624,14 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
const char *target = NULL, *info = NULL;
int error = 0;
+ /*
+ * Fail explicitly requested domain transitions if no_new_privs.
+ * There is no exception for unconfined as change_hat is not
+ * available.
+ */
+ if (current->no_new_privs)
+ return -EPERM;
+
/* released below */
cred = get_current_cred();
cxt = cred->security;
@@ -750,6 +773,18 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
cxt = cred->security;
profile = aa_cred_profile(cred);
+ /*
+ * Fail explicitly requested domain transitions if no_new_privs
+ * and not unconfined.
+ * Domain transitions from unconfined are allowed even when
+ * no_new_privs is set because this aways results in a reduction
+ * of permissions.
+ */
+ if (current->no_new_privs && !unconfined(profile)) {
+ put_cred(cred);
+ return -EPERM;
+ }
+
if (ns_name) {
/* released below */
ns = aa_find_namespace(profile->ns, ns_name);
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index 2f8fcba9ce4b..cf19d4093ca4 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -108,7 +108,7 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
- COMMON_AUDIT_DATA_INIT(&sa, NONE);
+ sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad;
aad.op = op,
aad.fs.request = request;
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index 3868b1e5d5ba..4b7e18951aea 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -110,6 +110,7 @@ struct apparmor_audit_data {
void *profile;
const char *name;
const char *info;
+ struct task_struct *tsk;
union {
void *target;
struct {
diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c
index c3da93a5150d..cf1071b14232 100644
--- a/security/apparmor/ipc.c
+++ b/security/apparmor/ipc.c
@@ -42,7 +42,7 @@ static int aa_audit_ptrace(struct aa_profile *profile,
{
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
- COMMON_AUDIT_DATA_INIT(&sa, NONE);
+ sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad;
aad.op = OP_PTRACE;
aad.target = target;
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index e75829ba0ff9..7430298116d6 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -66,7 +66,7 @@ void aa_info_message(const char *str)
if (audit_enabled) {
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
- COMMON_AUDIT_DATA_INIT(&sa, NONE);
+ sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad;
aad.info = str;
aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index ad05d391974d..032daab449b0 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -373,7 +373,7 @@ static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
AA_MAY_META_READ);
}
-static int apparmor_dentry_open(struct file *file, const struct cred *cred)
+static int apparmor_file_open(struct file *file, const struct cred *cred)
{
struct aa_file_cxt *fcxt = file->f_security;
struct aa_profile *profile;
@@ -589,7 +589,7 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
} else {
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
- COMMON_AUDIT_DATA_INIT(&sa, NONE);
+ sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad;
aad.op = OP_SETPROCATTR;
aad.info = name;
@@ -640,9 +640,9 @@ static struct security_operations apparmor_ops = {
.path_chmod = apparmor_path_chmod,
.path_chown = apparmor_path_chown,
.path_truncate = apparmor_path_truncate,
- .dentry_open = apparmor_dentry_open,
.inode_getattr = apparmor_inode_getattr,
+ .file_open = apparmor_file_open,
.file_permission = apparmor_file_permission,
.file_alloc_security = apparmor_file_alloc_security,
.file_free_security = apparmor_file_free_security,
diff --git a/security/apparmor/path.c b/security/apparmor/path.c
index 2daeea4f9266..e91ffee80162 100644
--- a/security/apparmor/path.c
+++ b/security/apparmor/path.c
@@ -94,6 +94,8 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
* be returned.
*/
if (!res || IS_ERR(res)) {
+ if (PTR_ERR(res) == -ENAMETOOLONG)
+ return -ENAMETOOLONG;
connected = 0;
res = dentry_path_raw(path->dentry, buf, buflen);
if (IS_ERR(res)) {
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index f1f7506a464d..cf5fd220309b 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -903,6 +903,10 @@ struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *hname)
profile = aa_get_profile(__lookup_profile(&ns->base, hname));
read_unlock(&ns->lock);
+ /* the unconfined profile is not in the regular profile list */
+ if (!profile && strcmp(hname, "unconfined") == 0)
+ profile = aa_get_profile(ns->unconfined);
+
/* refcount released by caller */
return profile;
}
@@ -965,7 +969,7 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info,
{
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
- COMMON_AUDIT_DATA_INIT(&sa, NONE);
+ sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad;
aad.op = op;
aad.name = name;
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index deab7c7e8dc0..329b1fd30749 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -95,7 +95,7 @@ static int audit_iface(struct aa_profile *new, const char *name,
struct aa_profile *profile = __aa_current_profile();
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
- COMMON_AUDIT_DATA_INIT(&sa, NONE);
+ sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad;
if (e)
aad.iface.pos = e->pos - e->start;
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
index 2fe8613efe33..e1f3d7ef2c54 100644
--- a/security/apparmor/resource.c
+++ b/security/apparmor/resource.c
@@ -52,7 +52,7 @@ static int audit_resource(struct aa_profile *profile, unsigned int resource,
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
- COMMON_AUDIT_DATA_INIT(&sa, NONE);
+ sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad;
aad.op = OP_SETRLIMIT,
aad.rlim.rlim = resource;
diff --git a/security/capability.c b/security/capability.c
index 5bb21b1c448c..fca889676c5e 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -348,7 +348,7 @@ static int cap_file_receive(struct file *file)
return 0;
}
-static int cap_dentry_open(struct file *file, const struct cred *cred)
+static int cap_file_open(struct file *file, const struct cred *cred)
{
return 0;
}
@@ -956,7 +956,7 @@ void __init security_fixup_ops(struct security_operations *ops)
set_to_cap_if_null(ops, file_set_fowner);
set_to_cap_if_null(ops, file_send_sigiotask);
set_to_cap_if_null(ops, file_receive);
- set_to_cap_if_null(ops, dentry_open);
+ set_to_cap_if_null(ops, file_open);
set_to_cap_if_null(ops, task_create);
set_to_cap_if_null(ops, task_free);
set_to_cap_if_null(ops, cred_alloc_blank);
diff --git a/security/commoncap.c b/security/commoncap.c
index 71a166a05975..f80d11609391 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -512,14 +512,17 @@ skip:
/* Don't let someone trace a set[ug]id/setpcap binary with the revised
- * credentials unless they have the appropriate permit
+ * credentials unless they have the appropriate permit.
+ *
+ * In addition, if NO_NEW_PRIVS, then ensure we get no new privs.
*/
if ((new->euid != old->uid ||
new->egid != old->gid ||
!cap_issubset(new->cap_permitted, old->cap_permitted)) &&
bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
/* downgrade; they get no more than they had, and maybe less */
- if (!capable(CAP_SETUID)) {
+ if (!capable(CAP_SETUID) ||
+ (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) {
new->euid = new->uid;
new->egid = new->gid;
}
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index c43a3323feea..442204cc22d9 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -447,22 +447,16 @@ static struct cftype dev_cgroup_files[] = {
.read_seq_string = devcgroup_seq_read,
.private = DEVCG_LIST,
},
+ { } /* terminate */
};
-static int devcgroup_populate(struct cgroup_subsys *ss,
- struct cgroup *cgroup)
-{
- return cgroup_add_files(cgroup, ss, dev_cgroup_files,
- ARRAY_SIZE(dev_cgroup_files));
-}
-
struct cgroup_subsys devices_subsys = {
.name = "devices",
.can_attach = devcgroup_can_attach,
.create = devcgroup_create,
.destroy = devcgroup_destroy,
- .populate = devcgroup_populate,
.subsys_id = devices_subsys_id,
+ .base_cftypes = dev_cgroup_files,
};
int __devcgroup_inode_permission(struct inode *inode, int mask)
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 1eff5cb001e5..b17be79b9cf2 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -194,7 +194,9 @@ int ima_bprm_check(struct linux_binprm *bprm)
{
int rc;
- rc = process_measurement(bprm->file, bprm->filename,
+ rc = process_measurement(bprm->file,
+ (strcmp(bprm->filename, bprm->interp) == 0) ?
+ bprm->filename : bprm->interp,
MAY_EXEC, BPRM_CHECK);
return 0;
}
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
new file mode 100644
index 000000000000..a90d6d300dbd
--- /dev/null
+++ b/security/keys/Kconfig
@@ -0,0 +1,71 @@
+#
+# Key management configuration
+#
+
+config KEYS
+ bool "Enable access key retention support"
+ help
+ This option provides support for retaining authentication tokens and
+ access keys in the kernel.
+
+ It also includes provision of methods by which such keys might be
+ associated with a process so that network filesystems, encryption
+ support and the like can find them.
+
+ Furthermore, a special type of key is available that acts as keyring:
+ a searchable sequence of keys. Each process is equipped with access
+ to five standard keyrings: UID-specific, GID-specific, session,
+ process and thread.
+
+ If you are unsure as to whether this is required, answer N.
+
+config TRUSTED_KEYS
+ tristate "TRUSTED KEYS"
+ depends on KEYS && TCG_TPM
+ select CRYPTO
+ select CRYPTO_HMAC
+ select CRYPTO_SHA1
+ help
+ This option provides support for creating, sealing, and unsealing
+ keys in the kernel. Trusted keys are random number symmetric keys,
+ generated and RSA-sealed by the TPM. The TPM only unseals the keys,
+ if the boot PCRs and other criteria match. Userspace will only ever
+ see encrypted blobs.
+
+ If you are unsure as to whether this is required, answer N.
+
+config ENCRYPTED_KEYS
+ tristate "ENCRYPTED KEYS"
+ depends on KEYS
+ select CRYPTO
+ select CRYPTO_HMAC
+ select CRYPTO_AES
+ select CRYPTO_CBC
+ select CRYPTO_SHA256
+ select CRYPTO_RNG
+ help
+ This option provides support for create/encrypting/decrypting keys
+ in the kernel. Encrypted keys are kernel generated random numbers,
+ which are encrypted/decrypted with a 'master' symmetric key. The
+ 'master' key can be either a trusted-key or user-key type.
+ Userspace only ever sees/stores encrypted blobs.
+
+ If you are unsure as to whether this is required, answer N.
+
+config KEYS_DEBUG_PROC_KEYS
+ bool "Enable the /proc/keys file by which keys may be viewed"
+ depends on KEYS
+ help
+ This option turns on support for the /proc/keys file - through which
+ can be listed all the keys on the system that are viewable by the
+ reading process.
+
+ The only keys included in the list are those that grant View
+ permission to the reading process whether or not it possesses them.
+ Note that LSM security checks are still performed, and may further
+ filter out keys that the current process is not authorised to view.
+
+ Only key attributes are listed here; key payloads are not included in
+ the resulting table.
+
+ If you are unsure as to whether this is required, answer N.
diff --git a/security/keys/Makefile b/security/keys/Makefile
index a56f1ffdc64d..504aaa008388 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -2,6 +2,9 @@
# Makefile for key management
#
+#
+# Core
+#
obj-y := \
gc.o \
key.o \
@@ -12,9 +15,12 @@ obj-y := \
request_key.o \
request_key_auth.o \
user_defined.o
-
-obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
-obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
obj-$(CONFIG_KEYS_COMPAT) += compat.o
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_SYSCTL) += sysctl.o
+
+#
+# Key types
+#
+obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
+obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
diff --git a/security/keys/compat.c b/security/keys/compat.c
index 4c48e13448f8..fab4f8dda6c6 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -135,6 +135,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
return compat_keyctl_instantiate_key_iov(
arg2, compat_ptr(arg3), arg4, arg5);
+ case KEYCTL_INVALIDATE:
+ return keyctl_invalidate_key(arg2);
+
default:
return -EOPNOTSUPP;
}
diff --git a/security/keys/gc.c b/security/keys/gc.c
index a42b45531aac..61ab7c82ebb1 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -72,6 +72,15 @@ void key_schedule_gc(time_t gc_at)
}
/*
+ * Schedule a dead links collection run.
+ */
+void key_schedule_gc_links(void)
+{
+ set_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags);
+ queue_work(system_nrt_wq, &key_gc_work);
+}
+
+/*
* Some key's cleanup time was met after it expired, so we need to get the
* reaper to go through a cycle finding expired keys.
*/
@@ -79,8 +88,7 @@ static void key_gc_timer_func(unsigned long data)
{
kenter("");
key_gc_next_run = LONG_MAX;
- set_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags);
- queue_work(system_nrt_wq, &key_gc_work);
+ key_schedule_gc_links();
}
/*
@@ -131,12 +139,12 @@ void key_gc_keytype(struct key_type *ktype)
static void key_gc_keyring(struct key *keyring, time_t limit)
{
struct keyring_list *klist;
- struct key *key;
int loop;
kenter("%x", key_serial(keyring));
- if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
+ if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) |
+ (1 << KEY_FLAG_REVOKED)))
goto dont_gc;
/* scan the keyring looking for dead keys */
@@ -148,9 +156,8 @@ static void key_gc_keyring(struct key *keyring, time_t limit)
loop = klist->nkeys;
smp_rmb();
for (loop--; loop >= 0; loop--) {
- key = klist->keys[loop];
- if (test_bit(KEY_FLAG_DEAD, &key->flags) ||
- (key->expiry > 0 && key->expiry <= limit))
+ struct key *key = rcu_dereference(klist->keys[loop]);
+ if (key_is_dead(key, limit))
goto do_gc;
}
@@ -168,38 +175,45 @@ do_gc:
}
/*
- * Garbage collect an unreferenced, detached key
+ * Garbage collect a list of unreferenced, detached keys
*/
-static noinline void key_gc_unused_key(struct key *key)
+static noinline void key_gc_unused_keys(struct list_head *keys)
{
- key_check(key);
-
- security_key_free(key);
-
- /* deal with the user's key tracking and quota */
- if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
- spin_lock(&key->user->lock);
- key->user->qnkeys--;
- key->user->qnbytes -= key->quotalen;
- spin_unlock(&key->user->lock);
- }
+ while (!list_empty(keys)) {
+ struct key *key =
+ list_entry(keys->next, struct key, graveyard_link);
+ list_del(&key->graveyard_link);
+
+ kdebug("- %u", key->serial);
+ key_check(key);
+
+ security_key_free(key);
+
+ /* deal with the user's key tracking and quota */
+ if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
+ spin_lock(&key->user->lock);
+ key->user->qnkeys--;
+ key->user->qnbytes -= key->quotalen;
+ spin_unlock(&key->user->lock);
+ }
- atomic_dec(&key->user->nkeys);
- if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
- atomic_dec(&key->user->nikeys);
+ atomic_dec(&key->user->nkeys);
+ if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
+ atomic_dec(&key->user->nikeys);
- key_user_put(key->user);
+ key_user_put(key->user);
- /* now throw away the key memory */
- if (key->type->destroy)
- key->type->destroy(key);
+ /* now throw away the key memory */
+ if (key->type->destroy)
+ key->type->destroy(key);
- kfree(key->description);
+ kfree(key->description);
#ifdef KEY_DEBUGGING
- key->magic = KEY_DEBUG_MAGIC_X;
+ key->magic = KEY_DEBUG_MAGIC_X;
#endif
- kmem_cache_free(key_jar, key);
+ kmem_cache_free(key_jar, key);
+ }
}
/*
@@ -211,6 +225,7 @@ static noinline void key_gc_unused_key(struct key *key)
*/
static void key_garbage_collector(struct work_struct *work)
{
+ static LIST_HEAD(graveyard);
static u8 gc_state; /* Internal persistent state */
#define KEY_GC_REAP_AGAIN 0x01 /* - Need another cycle */
#define KEY_GC_REAPING_LINKS 0x02 /* - We need to reap links */
@@ -316,15 +331,22 @@ maybe_resched:
key_schedule_gc(new_timer);
}
- if (unlikely(gc_state & KEY_GC_REAPING_DEAD_2)) {
- /* Make sure everyone revalidates their keys if we marked a
- * bunch as being dead and make sure all keyring ex-payloads
- * are destroyed.
+ if (unlikely(gc_state & KEY_GC_REAPING_DEAD_2) ||
+ !list_empty(&graveyard)) {
+ /* Make sure that all pending keyring payload destructions are
+ * fulfilled and that people aren't now looking at dead or
+ * dying keys that they don't have a reference upon or a link
+ * to.
*/
- kdebug("dead sync");
+ kdebug("gc sync");
synchronize_rcu();
}
+ if (!list_empty(&graveyard)) {
+ kdebug("gc keys");
+ key_gc_unused_keys(&graveyard);
+ }
+
if (unlikely(gc_state & (KEY_GC_REAPING_DEAD_1 |
KEY_GC_REAPING_DEAD_2))) {
if (!(gc_state & KEY_GC_FOUND_DEAD_KEY)) {
@@ -359,7 +381,7 @@ found_unreferenced_key:
rb_erase(&key->serial_node, &key_serial_tree);
spin_unlock(&key_serial_lock);
- key_gc_unused_key(key);
+ list_add_tail(&key->graveyard_link, &graveyard);
gc_state |= KEY_GC_REAP_AGAIN;
goto maybe_resched;
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 65647f825584..f711b094ed41 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -152,7 +152,8 @@ extern long join_session_keyring(const char *name);
extern struct work_struct key_gc_work;
extern unsigned key_gc_delay;
extern void keyring_gc(struct key *keyring, time_t limit);
-extern void key_schedule_gc(time_t expiry_at);
+extern void key_schedule_gc(time_t gc_at);
+extern void key_schedule_gc_links(void);
extern void key_gc_keytype(struct key_type *ktype);
extern int key_task_permission(const key_ref_t key_ref,
@@ -197,6 +198,17 @@ extern struct key *request_key_auth_new(struct key *target,
extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
/*
+ * Determine whether a key is dead.
+ */
+static inline bool key_is_dead(struct key *key, time_t limit)
+{
+ return
+ key->flags & ((1 << KEY_FLAG_DEAD) |
+ (1 << KEY_FLAG_INVALIDATED)) ||
+ (key->expiry > 0 && key->expiry <= limit);
+}
+
+/*
* keyctl() functions
*/
extern long keyctl_get_keyring_ID(key_serial_t, int);
@@ -225,6 +237,7 @@ extern long keyctl_reject_key(key_serial_t, unsigned, unsigned, key_serial_t);
extern long keyctl_instantiate_key_iov(key_serial_t,
const struct iovec __user *,
unsigned, key_serial_t);
+extern long keyctl_invalidate_key(key_serial_t);
extern long keyctl_instantiate_key_common(key_serial_t,
const struct iovec __user *,
diff --git a/security/keys/key.c b/security/keys/key.c
index 06783cffb3af..c9bf66ac36e0 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -955,6 +955,28 @@ void key_revoke(struct key *key)
EXPORT_SYMBOL(key_revoke);
/**
+ * key_invalidate - Invalidate a key.
+ * @key: The key to be invalidated.
+ *
+ * Mark a key as being invalidated and have it cleaned up immediately. The key
+ * is ignored by all searches and other operations from this point.
+ */
+void key_invalidate(struct key *key)
+{
+ kenter("%d", key_serial(key));
+
+ key_check(key);
+
+ if (!test_bit(KEY_FLAG_INVALIDATED, &key->flags)) {
+ down_write_nested(&key->sem, 1);
+ if (!test_and_set_bit(KEY_FLAG_INVALIDATED, &key->flags))
+ key_schedule_gc_links();
+ up_write(&key->sem);
+ }
+}
+EXPORT_SYMBOL(key_invalidate);
+
+/**
* register_key_type - Register a type of key.
* @ktype: The new key type.
*
@@ -980,6 +1002,8 @@ int register_key_type(struct key_type *ktype)
/* store the type */
list_add(&ktype->link, &key_types_list);
+
+ pr_notice("Key type %s registered\n", ktype->name);
ret = 0;
out:
@@ -1002,6 +1026,7 @@ void unregister_key_type(struct key_type *ktype)
list_del_init(&ktype->link);
downgrade_write(&key_types_sem);
key_gc_keytype(ktype);
+ pr_notice("Key type %s unregistered\n", ktype->name);
up_read(&key_types_sem);
}
EXPORT_SYMBOL(unregister_key_type);
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index fb767c6cd99f..ddb3e05bc5fc 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -375,6 +375,37 @@ error:
}
/*
+ * Invalidate a key.
+ *
+ * The key must be grant the caller Invalidate permission for this to work.
+ * The key and any links to the key will be automatically garbage collected
+ * immediately.
+ *
+ * If successful, 0 is returned.
+ */
+long keyctl_invalidate_key(key_serial_t id)
+{
+ key_ref_t key_ref;
+ long ret;
+
+ kenter("%d", id);
+
+ key_ref = lookup_user_key(id, 0, KEY_SEARCH);
+ if (IS_ERR(key_ref)) {
+ ret = PTR_ERR(key_ref);
+ goto error;
+ }
+
+ key_invalidate(key_ref_to_ptr(key_ref));
+ ret = 0;
+
+ key_ref_put(key_ref);
+error:
+ kleave(" = %ld", ret);
+ return ret;
+}
+
+/*
* Clear the specified keyring, creating an empty process keyring if one of the
* special keyring IDs is used.
*
@@ -1622,6 +1653,9 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
(unsigned) arg4,
(key_serial_t) arg5);
+ case KEYCTL_INVALIDATE:
+ return keyctl_invalidate_key((key_serial_t) arg2);
+
default:
return -EOPNOTSUPP;
}
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index d605f75292e4..7445875f6818 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -25,6 +25,15 @@
(keyring)->payload.subscriptions, \
rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem)))
+#define rcu_deref_link_locked(klist, index, keyring) \
+ (rcu_dereference_protected( \
+ (klist)->keys[index], \
+ rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem)))
+
+#define MAX_KEYRING_LINKS \
+ min_t(size_t, USHRT_MAX - 1, \
+ ((PAGE_SIZE - sizeof(struct keyring_list)) / sizeof(struct key *)))
+
#define KEY_LINK_FIXQUOTA 1UL
/*
@@ -138,6 +147,11 @@ static int keyring_match(const struct key *keyring, const void *description)
/*
* Clean up a keyring when it is destroyed. Unpublish its name if it had one
* and dispose of its data.
+ *
+ * The garbage collector detects the final key_put(), removes the keyring from
+ * the serial number tree and then does RCU synchronisation before coming here,
+ * so we shouldn't need to worry about code poking around here with the RCU
+ * readlock held by this time.
*/
static void keyring_destroy(struct key *keyring)
{
@@ -154,11 +168,10 @@ static void keyring_destroy(struct key *keyring)
write_unlock(&keyring_name_lock);
}
- klist = rcu_dereference_check(keyring->payload.subscriptions,
- atomic_read(&keyring->usage) == 0);
+ klist = rcu_access_pointer(keyring->payload.subscriptions);
if (klist) {
for (loop = klist->nkeys - 1; loop >= 0; loop--)
- key_put(klist->keys[loop]);
+ key_put(rcu_access_pointer(klist->keys[loop]));
kfree(klist);
}
}
@@ -214,7 +227,8 @@ static long keyring_read(const struct key *keyring,
ret = -EFAULT;
for (loop = 0; loop < klist->nkeys; loop++) {
- key = klist->keys[loop];
+ key = rcu_deref_link_locked(klist, loop,
+ keyring);
tmp = sizeof(key_serial_t);
if (tmp > buflen)
@@ -309,6 +323,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
bool no_state_check)
{
struct {
+ /* Need a separate keylist pointer for RCU purposes */
+ struct key *keyring;
struct keyring_list *keylist;
int kix;
} stack[KEYRING_SEARCH_MAX_DEPTH];
@@ -366,13 +382,17 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
/* otherwise, the top keyring must not be revoked, expired, or
* negatively instantiated if we are to search it */
key_ref = ERR_PTR(-EAGAIN);
- if (kflags & ((1 << KEY_FLAG_REVOKED) | (1 << KEY_FLAG_NEGATIVE)) ||
+ if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
+ (1 << KEY_FLAG_REVOKED) |
+ (1 << KEY_FLAG_NEGATIVE)) ||
(keyring->expiry && now.tv_sec >= keyring->expiry))
goto error_2;
/* start processing a new keyring */
descend:
- if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
+ kflags = keyring->flags;
+ if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
+ (1 << KEY_FLAG_REVOKED)))
goto not_this_keyring;
keylist = rcu_dereference(keyring->payload.subscriptions);
@@ -383,16 +403,17 @@ descend:
nkeys = keylist->nkeys;
smp_rmb();
for (kix = 0; kix < nkeys; kix++) {
- key = keylist->keys[kix];
+ key = rcu_dereference(keylist->keys[kix]);
kflags = key->flags;
/* ignore keys not of this type */
if (key->type != type)
continue;
- /* skip revoked keys and expired keys */
+ /* skip invalidated, revoked and expired keys */
if (!no_state_check) {
- if (kflags & (1 << KEY_FLAG_REVOKED))
+ if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
+ (1 << KEY_FLAG_REVOKED)))
continue;
if (key->expiry && now.tv_sec >= key->expiry)
@@ -426,7 +447,7 @@ ascend:
nkeys = keylist->nkeys;
smp_rmb();
for (; kix < nkeys; kix++) {
- key = keylist->keys[kix];
+ key = rcu_dereference(keylist->keys[kix]);
if (key->type != &key_type_keyring)
continue;
@@ -441,6 +462,7 @@ ascend:
continue;
/* stack the current position */
+ stack[sp].keyring = keyring;
stack[sp].keylist = keylist;
stack[sp].kix = kix;
sp++;
@@ -456,6 +478,7 @@ not_this_keyring:
if (sp > 0) {
/* resume the processing of a keyring higher up in the tree */
sp--;
+ keyring = stack[sp].keyring;
keylist = stack[sp].keylist;
kix = stack[sp].kix + 1;
goto ascend;
@@ -467,6 +490,10 @@ not_this_keyring:
/* we found a viable match */
found:
atomic_inc(&key->usage);
+ key->last_used_at = now.tv_sec;
+ keyring->last_used_at = now.tv_sec;
+ while (sp > 0)
+ stack[--sp].keyring->last_used_at = now.tv_sec;
key_check(key);
key_ref = make_key_ref(key, possessed);
error_2:
@@ -531,14 +558,14 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
nkeys = klist->nkeys;
smp_rmb();
for (loop = 0; loop < nkeys ; loop++) {
- key = klist->keys[loop];
-
+ key = rcu_dereference(klist->keys[loop]);
if (key->type == ktype &&
(!key->type->match ||
key->type->match(key, description)) &&
key_permission(make_key_ref(key, possessed),
perm) == 0 &&
- !test_bit(KEY_FLAG_REVOKED, &key->flags)
+ !(key->flags & ((1 << KEY_FLAG_INVALIDATED) |
+ (1 << KEY_FLAG_REVOKED)))
)
goto found;
}
@@ -549,6 +576,8 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
found:
atomic_inc(&key->usage);
+ keyring->last_used_at = key->last_used_at =
+ current_kernel_time().tv_sec;
rcu_read_unlock();
return make_key_ref(key, possessed);
}
@@ -602,6 +631,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
* (ie. it has a zero usage count) */
if (!atomic_inc_not_zero(&keyring->usage))
continue;
+ keyring->last_used_at = current_kernel_time().tv_sec;
goto out;
}
}
@@ -654,7 +684,7 @@ ascend:
nkeys = keylist->nkeys;
smp_rmb();
for (; kix < nkeys; kix++) {
- key = keylist->keys[kix];
+ key = rcu_dereference(keylist->keys[kix]);
if (key == A)
goto cycle_detected;
@@ -711,7 +741,7 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
container_of(rcu, struct keyring_list, rcu);
if (klist->delkey != USHRT_MAX)
- key_put(klist->keys[klist->delkey]);
+ key_put(rcu_access_pointer(klist->keys[klist->delkey]));
kfree(klist);
}
@@ -725,8 +755,9 @@ int __key_link_begin(struct key *keyring, const struct key_type *type,
struct keyring_list *klist, *nklist;
unsigned long prealloc;
unsigned max;
+ time_t lowest_lru;
size_t size;
- int loop, ret;
+ int loop, lru, ret;
kenter("%d,%s,%s,", key_serial(keyring), type->name, description);
@@ -747,31 +778,39 @@ int __key_link_begin(struct key *keyring, const struct key_type *type,
klist = rcu_dereference_locked_keyring(keyring);
/* see if there's a matching key we can displace */
+ lru = -1;
if (klist && klist->nkeys > 0) {
+ lowest_lru = TIME_T_MAX;
for (loop = klist->nkeys - 1; loop >= 0; loop--) {
- if (klist->keys[loop]->type == type &&
- strcmp(klist->keys[loop]->description,
- description) == 0
- ) {
- /* found a match - we'll replace this one with
- * the new key */
- size = sizeof(struct key *) * klist->maxkeys;
- size += sizeof(*klist);
- BUG_ON(size > PAGE_SIZE);
-
- ret = -ENOMEM;
- nklist = kmemdup(klist, size, GFP_KERNEL);
- if (!nklist)
- goto error_sem;
-
- /* note replacement slot */
- klist->delkey = nklist->delkey = loop;
- prealloc = (unsigned long)nklist;
+ struct key *key = rcu_deref_link_locked(klist, loop,
+ keyring);
+ if (key->type == type &&
+ strcmp(key->description, description) == 0) {
+ /* Found a match - we'll replace the link with
+ * one to the new key. We record the slot
+ * position.
+ */
+ klist->delkey = loop;
+ prealloc = 0;
goto done;
}
+ if (key->last_used_at < lowest_lru) {
+ lowest_lru = key->last_used_at;
+ lru = loop;
+ }
}
}
+ /* If the keyring is full then do an LRU discard */
+ if (klist &&
+ klist->nkeys == klist->maxkeys &&
+ klist->maxkeys >= MAX_KEYRING_LINKS) {
+ kdebug("LRU discard %d\n", lru);
+ klist->delkey = lru;
+ prealloc = 0;
+ goto done;
+ }
+
/* check that we aren't going to overrun the user's quota */
ret = key_payload_reserve(keyring,
keyring->datalen + KEYQUOTA_LINK_BYTES);
@@ -780,20 +819,19 @@ int __key_link_begin(struct key *keyring, const struct key_type *type,
if (klist && klist->nkeys < klist->maxkeys) {
/* there's sufficient slack space to append directly */
- nklist = NULL;
+ klist->delkey = klist->nkeys;
prealloc = KEY_LINK_FIXQUOTA;
} else {
/* grow the key list */
max = 4;
- if (klist)
+ if (klist) {
max += klist->maxkeys;
+ if (max > MAX_KEYRING_LINKS)
+ max = MAX_KEYRING_LINKS;
+ BUG_ON(max <= klist->maxkeys);
+ }
- ret = -ENFILE;
- if (max > USHRT_MAX - 1)
- goto error_quota;
size = sizeof(*klist) + sizeof(struct key *) * max;
- if (size > PAGE_SIZE)
- goto error_quota;
ret = -ENOMEM;
nklist = kmalloc(size, GFP_KERNEL);
@@ -813,10 +851,10 @@ int __key_link_begin(struct key *keyring, const struct key_type *type,
}
/* add the key into the new space */
- nklist->keys[nklist->delkey] = NULL;
+ RCU_INIT_POINTER(nklist->keys[nklist->delkey], NULL);
+ prealloc = (unsigned long)nklist | KEY_LINK_FIXQUOTA;
}
- prealloc = (unsigned long)nklist | KEY_LINK_FIXQUOTA;
done:
*_prealloc = prealloc;
kleave(" = 0");
@@ -862,6 +900,7 @@ void __key_link(struct key *keyring, struct key *key,
unsigned long *_prealloc)
{
struct keyring_list *klist, *nklist;
+ struct key *discard;
nklist = (struct keyring_list *)(*_prealloc & ~KEY_LINK_FIXQUOTA);
*_prealloc = 0;
@@ -871,14 +910,16 @@ void __key_link(struct key *keyring, struct key *key,
klist = rcu_dereference_locked_keyring(keyring);
atomic_inc(&key->usage);
+ keyring->last_used_at = key->last_used_at =
+ current_kernel_time().tv_sec;
/* there's a matching key we can displace or an empty slot in a newly
* allocated list we can fill */
if (nklist) {
- kdebug("replace %hu/%hu/%hu",
+ kdebug("reissue %hu/%hu/%hu",
nklist->delkey, nklist->nkeys, nklist->maxkeys);
- nklist->keys[nklist->delkey] = key;
+ RCU_INIT_POINTER(nklist->keys[nklist->delkey], key);
rcu_assign_pointer(keyring->payload.subscriptions, nklist);
@@ -889,9 +930,23 @@ void __key_link(struct key *keyring, struct key *key,
klist->delkey, klist->nkeys, klist->maxkeys);
call_rcu(&klist->rcu, keyring_unlink_rcu_disposal);
}
+ } else if (klist->delkey < klist->nkeys) {
+ kdebug("replace %hu/%hu/%hu",
+ klist->delkey, klist->nkeys, klist->maxkeys);
+
+ discard = rcu_dereference_protected(
+ klist->keys[klist->delkey],
+ rwsem_is_locked(&keyring->sem));
+ rcu_assign_pointer(klist->keys[klist->delkey], key);
+ /* The garbage collector will take care of RCU
+ * synchronisation */
+ key_put(discard);
} else {
/* there's sufficient slack space to append directly */
- klist->keys[klist->nkeys] = key;
+ kdebug("append %hu/%hu/%hu",
+ klist->delkey, klist->nkeys, klist->maxkeys);
+
+ RCU_INIT_POINTER(klist->keys[klist->delkey], key);
smp_wmb();
klist->nkeys++;
}
@@ -998,7 +1053,7 @@ int key_unlink(struct key *keyring, struct key *key)
if (klist) {
/* search the keyring for the key */
for (loop = 0; loop < klist->nkeys; loop++)
- if (klist->keys[loop] == key)
+ if (rcu_access_pointer(klist->keys[loop]) == key)
goto key_is_present;
}
@@ -1061,7 +1116,7 @@ static void keyring_clear_rcu_disposal(struct rcu_head *rcu)
klist = container_of(rcu, struct keyring_list, rcu);
for (loop = klist->nkeys - 1; loop >= 0; loop--)
- key_put(klist->keys[loop]);
+ key_put(rcu_access_pointer(klist->keys[loop]));
kfree(klist);
}
@@ -1128,15 +1183,6 @@ static void keyring_revoke(struct key *keyring)
}
/*
- * Determine whether a key is dead.
- */
-static bool key_is_dead(struct key *key, time_t limit)
-{
- return test_bit(KEY_FLAG_DEAD, &key->flags) ||
- (key->expiry > 0 && key->expiry <= limit);
-}
-
-/*
* Collect garbage from the contents of a keyring, replacing the old list with
* a new one with the pointers all shuffled down.
*
@@ -1161,7 +1207,8 @@ void keyring_gc(struct key *keyring, time_t limit)
/* work out how many subscriptions we're keeping */
keep = 0;
for (loop = klist->nkeys - 1; loop >= 0; loop--)
- if (!key_is_dead(klist->keys[loop], limit))
+ if (!key_is_dead(rcu_deref_link_locked(klist, loop, keyring),
+ limit))
keep++;
if (keep == klist->nkeys)
@@ -1182,11 +1229,11 @@ void keyring_gc(struct key *keyring, time_t limit)
*/
keep = 0;
for (loop = klist->nkeys - 1; loop >= 0; loop--) {
- key = klist->keys[loop];
+ key = rcu_deref_link_locked(klist, loop, keyring);
if (!key_is_dead(key, limit)) {
if (keep >= max)
goto discard_new;
- new->keys[keep++] = key_get(key);
+ RCU_INIT_POINTER(new->keys[keep++], key_get(key));
}
}
new->nkeys = keep;
diff --git a/security/keys/permission.c b/security/keys/permission.c
index c35b5229e3cd..57d96363d7f1 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -87,32 +87,29 @@ EXPORT_SYMBOL(key_task_permission);
* key_validate - Validate a key.
* @key: The key to be validated.
*
- * Check that a key is valid, returning 0 if the key is okay, -EKEYREVOKED if
- * the key's type has been removed or if the key has been revoked or
- * -EKEYEXPIRED if the key has expired.
+ * Check that a key is valid, returning 0 if the key is okay, -ENOKEY if the
+ * key is invalidated, -EKEYREVOKED if the key's type has been removed or if
+ * the key has been revoked or -EKEYEXPIRED if the key has expired.
*/
-int key_validate(struct key *key)
+int key_validate(const struct key *key)
{
- struct timespec now;
- int ret = 0;
-
- if (key) {
- /* check it's still accessible */
- ret = -EKEYREVOKED;
- if (test_bit(KEY_FLAG_REVOKED, &key->flags) ||
- test_bit(KEY_FLAG_DEAD, &key->flags))
- goto error;
-
- /* check it hasn't expired */
- ret = 0;
- if (key->expiry) {
- now = current_kernel_time();
- if (now.tv_sec >= key->expiry)
- ret = -EKEYEXPIRED;
- }
+ unsigned long flags = key->flags;
+
+ if (flags & (1 << KEY_FLAG_INVALIDATED))
+ return -ENOKEY;
+
+ /* check it's still accessible */
+ if (flags & ((1 << KEY_FLAG_REVOKED) |
+ (1 << KEY_FLAG_DEAD)))
+ return -EKEYREVOKED;
+
+ /* check it hasn't expired */
+ if (key->expiry) {
+ struct timespec now = current_kernel_time();
+ if (now.tv_sec >= key->expiry)
+ return -EKEYEXPIRED;
}
-error:
- return ret;
+ return 0;
}
EXPORT_SYMBOL(key_validate);
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 49bbc97943ad..30d1ddfd9cef 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -242,7 +242,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
#define showflag(KEY, LETTER, FLAG) \
(test_bit(FLAG, &(KEY)->flags) ? LETTER : '-')
- seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ",
+ seq_printf(m, "%08x %c%c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ",
key->serial,
showflag(key, 'I', KEY_FLAG_INSTANTIATED),
showflag(key, 'R', KEY_FLAG_REVOKED),
@@ -250,6 +250,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
showflag(key, 'Q', KEY_FLAG_IN_QUOTA),
showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT),
showflag(key, 'N', KEY_FLAG_NEGATIVE),
+ showflag(key, 'i', KEY_FLAG_INVALIDATED),
atomic_read(&key->usage),
xbuf,
key->perm,
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index be7ecb2018dd..e137fcd7042c 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -732,6 +732,8 @@ try_again:
if (ret < 0)
goto invalid_key;
+ key->last_used_at = current_kernel_time().tv_sec;
+
error:
put_cred(cred);
return key_ref;
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 90c129b0102f..8d8d97dbb389 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -213,12 +213,15 @@ static void dump_common_audit_data(struct audit_buffer *ab,
{
struct task_struct *tsk = current;
- if (a->tsk)
- tsk = a->tsk;
- if (tsk && tsk->pid) {
- audit_log_format(ab, " pid=%d comm=", tsk->pid);
- audit_log_untrustedstring(ab, tsk->comm);
- }
+ /*
+ * To keep stack sizes in check force programers to notice if they
+ * start making this union too large! See struct lsm_network_audit
+ * as an example of how to deal with large data.
+ */
+ BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2);
+
+ audit_log_format(ab, " pid=%d comm=", tsk->pid);
+ audit_log_untrustedstring(ab, tsk->comm);
switch (a->type) {
case LSM_AUDIT_DATA_NONE:
diff --git a/security/security.c b/security/security.c
index bf619ffc9a4d..5497a57fba01 100644
--- a/security/security.c
+++ b/security/security.c
@@ -701,11 +701,11 @@ int security_file_receive(struct file *file)
return security_ops->file_receive(file);
}
-int security_dentry_open(struct file *file, const struct cred *cred)
+int security_file_open(struct file *file, const struct cred *cred)
{
int ret;
- ret = security_ops->dentry_open(file, cred);
+ ret = security_ops->file_open(file, cred);
if (ret)
return ret;
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 8ee42b2a5f19..68d82daed257 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -65,14 +65,8 @@ struct avc_cache {
};
struct avc_callback_node {
- int (*callback) (u32 event, u32 ssid, u32 tsid,
- u16 tclass, u32 perms,
- u32 *out_retained);
+ int (*callback) (u32 event);
u32 events;
- u32 ssid;
- u32 tsid;
- u16 tclass;
- u32 perms;
struct avc_callback_node *next;
};
@@ -436,9 +430,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
{
struct common_audit_data *ad = a;
audit_log_format(ab, "avc: %s ",
- ad->selinux_audit_data->slad->denied ? "denied" : "granted");
- avc_dump_av(ab, ad->selinux_audit_data->slad->tclass,
- ad->selinux_audit_data->slad->audited);
+ ad->selinux_audit_data->denied ? "denied" : "granted");
+ avc_dump_av(ab, ad->selinux_audit_data->tclass,
+ ad->selinux_audit_data->audited);
audit_log_format(ab, " for ");
}
@@ -452,25 +446,23 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
{
struct common_audit_data *ad = a;
audit_log_format(ab, " ");
- avc_dump_query(ab, ad->selinux_audit_data->slad->ssid,
- ad->selinux_audit_data->slad->tsid,
- ad->selinux_audit_data->slad->tclass);
+ avc_dump_query(ab, ad->selinux_audit_data->ssid,
+ ad->selinux_audit_data->tsid,
+ ad->selinux_audit_data->tclass);
}
/* This is the slow part of avc audit with big stack footprint */
-static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
+noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
u32 requested, u32 audited, u32 denied,
struct common_audit_data *a,
unsigned flags)
{
struct common_audit_data stack_data;
- struct selinux_audit_data sad = {0,};
- struct selinux_late_audit_data slad;
+ struct selinux_audit_data sad;
if (!a) {
a = &stack_data;
- COMMON_AUDIT_DATA_INIT(a, NONE);
- a->selinux_audit_data = &sad;
+ a->type = LSM_AUDIT_DATA_NONE;
}
/*
@@ -484,104 +476,34 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
(flags & MAY_NOT_BLOCK))
return -ECHILD;
- slad.tclass = tclass;
- slad.requested = requested;
- slad.ssid = ssid;
- slad.tsid = tsid;
- slad.audited = audited;
- slad.denied = denied;
+ sad.tclass = tclass;
+ sad.requested = requested;
+ sad.ssid = ssid;
+ sad.tsid = tsid;
+ sad.audited = audited;
+ sad.denied = denied;
+
+ a->selinux_audit_data = &sad;
- a->selinux_audit_data->slad = &slad;
common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback);
return 0;
}
/**
- * avc_audit - Audit the granting or denial of permissions.
- * @ssid: source security identifier
- * @tsid: target security identifier
- * @tclass: target security class
- * @requested: requested permissions
- * @avd: access vector decisions
- * @result: result from avc_has_perm_noaudit
- * @a: auxiliary audit data
- * @flags: VFS walk flags
- *
- * Audit the granting or denial of permissions in accordance
- * with the policy. This function is typically called by
- * avc_has_perm() after a permission check, but can also be
- * called directly by callers who use avc_has_perm_noaudit()
- * in order to separate the permission check from the auditing.
- * For example, this separation is useful when the permission check must
- * be performed under a lock, to allow the lock to be released
- * before calling the auditing code.
- */
-inline int avc_audit(u32 ssid, u32 tsid,
- u16 tclass, u32 requested,
- struct av_decision *avd, int result, struct common_audit_data *a,
- unsigned flags)
-{
- u32 denied, audited;
- denied = requested & ~avd->allowed;
- if (unlikely(denied)) {
- audited = denied & avd->auditdeny;
- /*
- * a->selinux_audit_data->auditdeny is TRICKY! Setting a bit in
- * this field means that ANY denials should NOT be audited if
- * the policy contains an explicit dontaudit rule for that
- * permission. Take notice that this is unrelated to the
- * actual permissions that were denied. As an example lets
- * assume:
- *
- * denied == READ
- * avd.auditdeny & ACCESS == 0 (not set means explicit rule)
- * selinux_audit_data->auditdeny & ACCESS == 1
- *
- * We will NOT audit the denial even though the denied
- * permission was READ and the auditdeny checks were for
- * ACCESS
- */
- if (a &&
- a->selinux_audit_data->auditdeny &&
- !(a->selinux_audit_data->auditdeny & avd->auditdeny))
- audited = 0;
- } else if (result)
- audited = denied = requested;
- else
- audited = requested & avd->auditallow;
- if (likely(!audited))
- return 0;
-
- return slow_avc_audit(ssid, tsid, tclass,
- requested, audited, denied,
- a, flags);
-}
-
-/**
* avc_add_callback - Register a callback for security events.
* @callback: callback function
* @events: security events
- * @ssid: source security identifier or %SECSID_WILD
- * @tsid: target security identifier or %SECSID_WILD
- * @tclass: target security class
- * @perms: permissions
*
- * Register a callback function for events in the set @events
- * related to the SID pair (@ssid, @tsid)
- * and the permissions @perms, interpreting
- * @perms based on @tclass. Returns %0 on success or
- * -%ENOMEM if insufficient memory exists to add the callback.
+ * Register a callback function for events in the set @events.
+ * Returns %0 on success or -%ENOMEM if insufficient memory
+ * exists to add the callback.
*/
-int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
- u16 tclass, u32 perms,
- u32 *out_retained),
- u32 events, u32 ssid, u32 tsid,
- u16 tclass, u32 perms)
+int __init avc_add_callback(int (*callback)(u32 event), u32 events)
{
struct avc_callback_node *c;
int rc = 0;
- c = kmalloc(sizeof(*c), GFP_ATOMIC);
+ c = kmalloc(sizeof(*c), GFP_KERNEL);
if (!c) {
rc = -ENOMEM;
goto out;
@@ -589,9 +511,6 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
c->callback = callback;
c->events = events;
- c->ssid = ssid;
- c->tsid = tsid;
- c->perms = perms;
c->next = avc_callbacks;
avc_callbacks = c;
out:
@@ -731,8 +650,7 @@ int avc_ss_reset(u32 seqno)
for (c = avc_callbacks; c; c = c->next) {
if (c->events & AVC_CALLBACK_RESET) {
- tmprc = c->callback(AVC_CALLBACK_RESET,
- 0, 0, 0, 0, NULL);
+ tmprc = c->callback(AVC_CALLBACK_RESET);
/* save the first error encountered for the return
value and continue processing the callbacks */
if (!rc)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d85b793c9321..fa2341b68331 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1420,16 +1420,13 @@ static int cred_has_capability(const struct cred *cred,
int cap, int audit)
{
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
struct av_decision avd;
u16 sclass;
u32 sid = cred_sid(cred);
u32 av = CAP_TO_MASK(cap);
int rc;
- COMMON_AUDIT_DATA_INIT(&ad, CAP);
- ad.selinux_audit_data = &sad;
- ad.tsk = current;
+ ad.type = LSM_AUDIT_DATA_CAP;
ad.u.cap = cap;
switch (CAP_TO_INDEX(cap)) {
@@ -1488,20 +1485,6 @@ static int inode_has_perm(const struct cred *cred,
return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
}
-static int inode_has_perm_noadp(const struct cred *cred,
- struct inode *inode,
- u32 perms,
- unsigned flags)
-{
- struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
-
- COMMON_AUDIT_DATA_INIT(&ad, INODE);
- ad.u.inode = inode;
- ad.selinux_audit_data = &sad;
- return inode_has_perm(cred, inode, perms, &ad, flags);
-}
-
/* Same as inode_has_perm, but pass explicit audit data containing
the dentry to help the auditing code to more easily generate the
pathname if needed. */
@@ -1511,11 +1494,9 @@ static inline int dentry_has_perm(const struct cred *cred,
{
struct inode *inode = dentry->d_inode;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
- COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+ ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry;
- ad.selinux_audit_data = &sad;
return inode_has_perm(cred, inode, av, &ad, 0);
}
@@ -1528,11 +1509,9 @@ static inline int path_has_perm(const struct cred *cred,
{
struct inode *inode = path->dentry->d_inode;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
- COMMON_AUDIT_DATA_INIT(&ad, PATH);
+ ad.type = LSM_AUDIT_DATA_PATH;
ad.u.path = *path;
- ad.selinux_audit_data = &sad;
return inode_has_perm(cred, inode, av, &ad, 0);
}
@@ -1551,13 +1530,11 @@ static int file_has_perm(const struct cred *cred,
struct file_security_struct *fsec = file->f_security;
struct inode *inode = file->f_path.dentry->d_inode;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 sid = cred_sid(cred);
int rc;
- COMMON_AUDIT_DATA_INIT(&ad, PATH);
+ ad.type = LSM_AUDIT_DATA_PATH;
ad.u.path = file->f_path;
- ad.selinux_audit_data = &sad;
if (sid != fsec->sid) {
rc = avc_has_perm(sid, fsec->sid,
@@ -1587,7 +1564,6 @@ static int may_create(struct inode *dir,
struct superblock_security_struct *sbsec;
u32 sid, newsid;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
int rc;
dsec = dir->i_security;
@@ -1596,9 +1572,8 @@ static int may_create(struct inode *dir,
sid = tsec->sid;
newsid = tsec->create_sid;
- COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+ ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry;
- ad.selinux_audit_data = &sad;
rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
DIR__ADD_NAME | DIR__SEARCH,
@@ -1643,7 +1618,6 @@ static int may_link(struct inode *dir,
{
struct inode_security_struct *dsec, *isec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
u32 av;
int rc;
@@ -1651,9 +1625,8 @@ static int may_link(struct inode *dir,
dsec = dir->i_security;
isec = dentry->d_inode->i_security;
- COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+ ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry;
- ad.selinux_audit_data = &sad;
av = DIR__SEARCH;
av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
@@ -1688,7 +1661,6 @@ static inline int may_rename(struct inode *old_dir,
{
struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
u32 av;
int old_is_dir, new_is_dir;
@@ -1699,8 +1671,7 @@ static inline int may_rename(struct inode *old_dir,
old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
new_dsec = new_dir->i_security;
- COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = old_dentry;
rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
@@ -1986,7 +1957,6 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
struct task_security_struct *new_tsec;
struct inode_security_struct *isec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
struct inode *inode = bprm->file->f_path.dentry->d_inode;
int rc;
@@ -2016,6 +1986,13 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
new_tsec->sid = old_tsec->exec_sid;
/* Reset exec SID on execve. */
new_tsec->exec_sid = 0;
+
+ /*
+ * Minimize confusion: if no_new_privs and a transition is
+ * explicitly requested, then fail the exec.
+ */
+ if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
+ return -EPERM;
} else {
/* Check for a default transition on this program. */
rc = security_transition_sid(old_tsec->sid, isec->sid,
@@ -2025,11 +2002,11 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
return rc;
}
- COMMON_AUDIT_DATA_INIT(&ad, PATH);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_PATH;
ad.u.path = bprm->file->f_path;
- if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
+ if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ||
+ (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))
new_tsec->sid = old_tsec->sid;
if (new_tsec->sid == old_tsec->sid) {
@@ -2115,8 +2092,6 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm)
static inline void flush_unauthorized_files(const struct cred *cred,
struct files_struct *files)
{
- struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
struct file *file, *devnull = NULL;
struct tty_struct *tty;
struct fdtable *fdt;
@@ -2128,21 +2103,17 @@ static inline void flush_unauthorized_files(const struct cred *cred,
spin_lock(&tty_files_lock);
if (!list_empty(&tty->tty_files)) {
struct tty_file_private *file_priv;
- struct inode *inode;
/* Revalidate access to controlling tty.
- Use inode_has_perm on the tty inode directly rather
+ Use path_has_perm on the tty path directly rather
than using file_has_perm, as this particular open
file may belong to another process and we are only
interested in the inode-based check here. */
file_priv = list_first_entry(&tty->tty_files,
struct tty_file_private, list);
file = file_priv->file;
- inode = file->f_path.dentry->d_inode;
- if (inode_has_perm_noadp(cred, inode,
- FILE__READ | FILE__WRITE, 0)) {
+ if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE))
drop_tty = 1;
- }
}
spin_unlock(&tty_files_lock);
tty_kref_put(tty);
@@ -2152,10 +2123,6 @@ static inline void flush_unauthorized_files(const struct cred *cred,
no_tty();
/* Revalidate access to inherited open files. */
-
- COMMON_AUDIT_DATA_INIT(&ad, INODE);
- ad.selinux_audit_data = &sad;
-
spin_lock(&files->file_lock);
for (;;) {
unsigned long set, i;
@@ -2492,7 +2459,6 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
{
const struct cred *cred = current_cred();
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
int rc;
rc = superblock_doinit(sb, data);
@@ -2503,8 +2469,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
if (flags & MS_KERNMOUNT)
return 0;
- COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = sb->s_root;
return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
}
@@ -2513,10 +2478,8 @@ static int selinux_sb_statfs(struct dentry *dentry)
{
const struct cred *cred = current_cred();
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
- COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry->d_sb->s_root;
return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
}
@@ -2676,14 +2639,35 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
return dentry_has_perm(cred, dentry, FILE__READ);
}
+static noinline int audit_inode_permission(struct inode *inode,
+ u32 perms, u32 audited, u32 denied,
+ unsigned flags)
+{
+ struct common_audit_data ad;
+ struct inode_security_struct *isec = inode->i_security;
+ int rc;
+
+ ad.type = LSM_AUDIT_DATA_INODE;
+ ad.u.inode = inode;
+
+ rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
+ audited, denied, &ad, flags);
+ if (rc)
+ return rc;
+ return 0;
+}
+
static int selinux_inode_permission(struct inode *inode, int mask)
{
const struct cred *cred = current_cred();
- struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 perms;
bool from_access;
unsigned flags = mask & MAY_NOT_BLOCK;
+ struct inode_security_struct *isec;
+ u32 sid;
+ struct av_decision avd;
+ int rc, rc2;
+ u32 audited, denied;
from_access = mask & MAY_ACCESS;
mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
@@ -2692,22 +2676,34 @@ static int selinux_inode_permission(struct inode *inode, int mask)
if (!mask)
return 0;
- COMMON_AUDIT_DATA_INIT(&ad, INODE);
- ad.selinux_audit_data = &sad;
- ad.u.inode = inode;
+ validate_creds(cred);
- if (from_access)
- ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS;
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
perms = file_mask_to_av(inode->i_mode, mask);
- return inode_has_perm(cred, inode, perms, &ad, flags);
+ sid = cred_sid(cred);
+ isec = inode->i_security;
+
+ rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
+ audited = avc_audit_required(perms, &avd, rc,
+ from_access ? FILE__AUDIT_ACCESS : 0,
+ &denied);
+ if (likely(!audited))
+ return rc;
+
+ rc2 = audit_inode_permission(inode, perms, audited, denied, flags);
+ if (rc2)
+ return rc2;
+ return rc;
}
static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
{
const struct cred *cred = current_cred();
unsigned int ia_valid = iattr->ia_valid;
+ __u32 av = FILE__WRITE;
/* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
if (ia_valid & ATTR_FORCE) {
@@ -2721,7 +2717,10 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
return dentry_has_perm(cred, dentry, FILE__SETATTR);
- return dentry_has_perm(cred, dentry, FILE__WRITE);
+ if (ia_valid & ATTR_SIZE)
+ av |= FILE__OPEN;
+
+ return dentry_has_perm(cred, dentry, av);
}
static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
@@ -2763,7 +2762,6 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
struct inode_security_struct *isec = inode->i_security;
struct superblock_security_struct *sbsec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 newsid, sid = current_sid();
int rc = 0;
@@ -2777,8 +2775,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
if (!inode_owner_or_capable(inode))
return -EPERM;
- COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry;
rc = avc_has_perm(sid, isec->sid, isec->sclass,
@@ -2788,8 +2785,25 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
rc = security_context_to_sid(value, size, &newsid);
if (rc == -EINVAL) {
- if (!capable(CAP_MAC_ADMIN))
+ if (!capable(CAP_MAC_ADMIN)) {
+ struct audit_buffer *ab;
+ size_t audit_size;
+ const char *str;
+
+ /* We strip a nul only if it is at the end, otherwise the
+ * context contains a nul and we should audit that */
+ str = value;
+ if (str[size - 1] == '\0')
+ audit_size = size - 1;
+ else
+ audit_size = size;
+ ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
+ audit_log_format(ab, "op=setxattr invalid_context=");
+ audit_log_n_untrustedstring(ab, value, audit_size);
+ audit_log_end(ab);
+
return rc;
+ }
rc = security_context_to_sid_force(value, size, &newsid);
}
if (rc)
@@ -2969,7 +2983,7 @@ static int selinux_file_permission(struct file *file, int mask)
if (sid == fsec->sid && fsec->isid == isec->sid &&
fsec->pseqno == avc_policy_seqno())
- /* No change since dentry_open check. */
+ /* No change since file_open check. */
return 0;
return selinux_revalidate_file_permission(file, mask);
@@ -3228,15 +3242,13 @@ static int selinux_file_receive(struct file *file)
return file_has_perm(cred, file, file_to_av(file));
}
-static int selinux_dentry_open(struct file *file, const struct cred *cred)
+static int selinux_file_open(struct file *file, const struct cred *cred)
{
struct file_security_struct *fsec;
- struct inode *inode;
struct inode_security_struct *isec;
- inode = file->f_path.dentry->d_inode;
fsec = file->f_security;
- isec = inode->i_security;
+ isec = file->f_path.dentry->d_inode->i_security;
/*
* Save inode label and policy sequence number
* at open-time so that selinux_file_permission
@@ -3254,7 +3266,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)
* new inode label or new policy.
* This check is not redundant - do not remove.
*/
- return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0);
+ return path_has_perm(cred, &file->f_path, open_file_to_av(file));
}
/* task security operations */
@@ -3373,12 +3385,10 @@ static int selinux_kernel_module_request(char *kmod_name)
{
u32 sid;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
sid = task_sid(current);
- COMMON_AUDIT_DATA_INIT(&ad, KMOD);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_KMOD;
ad.u.kmod_name = kmod_name;
return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
@@ -3751,15 +3761,13 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
{
struct sk_security_struct *sksec = sk->sk_security;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
u32 tsid = task_sid(task);
if (sksec->sid == SECINITSID_KERNEL)
return 0;
- COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
ad.u.net->sk = sk;
@@ -3839,7 +3847,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
char *addrp;
struct sk_security_struct *sksec = sk->sk_security;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
struct sockaddr_in *addr4 = NULL;
struct sockaddr_in6 *addr6 = NULL;
@@ -3866,8 +3873,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
snum, &sid);
if (err)
goto out;
- COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
ad.u.net->sport = htons(snum);
ad.u.net->family = family;
@@ -3901,8 +3907,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
if (err)
goto out;
- COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
ad.u.net->sport = htons(snum);
ad.u.net->family = family;
@@ -3937,7 +3942,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
if (sksec->sclass == SECCLASS_TCP_SOCKET ||
sksec->sclass == SECCLASS_DCCP_SOCKET) {
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
struct sockaddr_in *addr4 = NULL;
struct sockaddr_in6 *addr6 = NULL;
@@ -3963,8 +3967,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
- COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
ad.u.net->dport = htons(snum);
ad.u.net->family = sk->sk_family;
@@ -4056,12 +4059,10 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
struct sk_security_struct *sksec_other = other->sk_security;
struct sk_security_struct *sksec_new = newsk->sk_security;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
int err;
- COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
ad.u.net->sk = other;
@@ -4090,11 +4091,9 @@ static int selinux_socket_unix_may_send(struct socket *sock,
struct sk_security_struct *ssec = sock->sk->sk_security;
struct sk_security_struct *osec = other->sk->sk_security;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
- COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
ad.u.net->sk = other->sk;
@@ -4132,12 +4131,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
struct sk_security_struct *sksec = sk->sk_security;
u32 sk_sid = sksec->sid;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
char *addrp;
- COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
ad.u.net->netif = skb->skb_iif;
ad.u.net->family = family;
@@ -4167,7 +4164,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
u16 family = sk->sk_family;
u32 sk_sid = sksec->sid;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
char *addrp;
u8 secmark_active;
@@ -4192,8 +4188,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
if (!secmark_active && !peerlbl_active)
return 0;
- COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
ad.u.net->netif = skb->skb_iif;
ad.u.net->family = family;
@@ -4531,7 +4526,6 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
char *addrp;
u32 peer_sid;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
u8 secmark_active;
u8 netlbl_active;
@@ -4549,8 +4543,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
return NF_DROP;
- COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
ad.u.net->netif = ifindex;
ad.u.net->family = family;
@@ -4640,7 +4633,6 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
struct sock *sk = skb->sk;
struct sk_security_struct *sksec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
char *addrp;
u8 proto;
@@ -4649,8 +4641,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
return NF_ACCEPT;
sksec = sk->sk_security;
- COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
ad.u.net->netif = ifindex;
ad.u.net->family = family;
@@ -4675,7 +4666,6 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
u32 peer_sid;
struct sock *sk;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,};
char *addrp;
u8 secmark_active;
@@ -4722,8 +4712,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
secmark_perm = PACKET__SEND;
}
- COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
ad.u.net->netif = ifindex;
ad.u.net->family = family;
@@ -4841,13 +4830,11 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
isec = ipc_perms->security;
- COMMON_AUDIT_DATA_INIT(&ad, IPC);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = ipc_perms->key;
return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
@@ -4868,7 +4855,6 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
int rc;
@@ -4878,8 +4864,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
isec = msq->q_perm.security;
- COMMON_AUDIT_DATA_INIT(&ad, IPC);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
@@ -4900,13 +4885,11 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
isec = msq->q_perm.security;
- COMMON_AUDIT_DATA_INIT(&ad, IPC);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = msq->q_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
@@ -4946,7 +4929,6 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
struct ipc_security_struct *isec;
struct msg_security_struct *msec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
int rc;
@@ -4967,8 +4949,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
return rc;
}
- COMMON_AUDIT_DATA_INIT(&ad, IPC);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = msq->q_perm.key;
/* Can this process write to the queue? */
@@ -4993,15 +4974,13 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
struct ipc_security_struct *isec;
struct msg_security_struct *msec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 sid = task_sid(target);
int rc;
isec = msq->q_perm.security;
msec = msg->security;
- COMMON_AUDIT_DATA_INIT(&ad, IPC);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(sid, isec->sid,
@@ -5017,7 +4996,6 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
int rc;
@@ -5027,8 +5005,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
isec = shp->shm_perm.security;
- COMMON_AUDIT_DATA_INIT(&ad, IPC);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = shp->shm_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
@@ -5049,13 +5026,11 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
isec = shp->shm_perm.security;
- COMMON_AUDIT_DATA_INIT(&ad, IPC);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = shp->shm_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
@@ -5113,7 +5088,6 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
int rc;
@@ -5123,8 +5097,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
isec = sma->sem_perm.security;
- COMMON_AUDIT_DATA_INIT(&ad, IPC);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = sma->sem_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
@@ -5145,13 +5118,11 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg)
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
isec = sma->sem_perm.security;
- COMMON_AUDIT_DATA_INIT(&ad, IPC);
- ad.selinux_audit_data = &sad;
+ ad.type = LSM_AUDIT_DATA_IPC;
ad.u.ipc_id = sma->sem_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
@@ -5331,8 +5302,23 @@ static int selinux_setprocattr(struct task_struct *p,
}
error = security_context_to_sid(value, size, &sid);
if (error == -EINVAL && !strcmp(name, "fscreate")) {
- if (!capable(CAP_MAC_ADMIN))
+ if (!capable(CAP_MAC_ADMIN)) {
+ struct audit_buffer *ab;
+ size_t audit_size;
+
+ /* We strip a nul only if it is at the end, otherwise the
+ * context contains a nul and we should audit that */
+ if (str[size - 1] == '\0')
+ audit_size = size - 1;
+ else
+ audit_size = size;
+ ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
+ audit_log_format(ab, "op=fscreate invalid_context=");
+ audit_log_n_untrustedstring(ab, value, audit_size);
+ audit_log_end(ab);
+
return error;
+ }
error = security_context_to_sid_force(value, size,
&sid);
}
@@ -5592,7 +5578,7 @@ static struct security_operations selinux_ops = {
.file_send_sigiotask = selinux_file_send_sigiotask,
.file_receive = selinux_file_receive,
- .dentry_open = selinux_dentry_open,
+ .file_open = selinux_file_open,
.task_create = selinux_task_create,
.cred_alloc_blank = selinux_cred_alloc_blank,
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 1931370233d7..92d0ab561db8 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -49,7 +49,7 @@ struct avc_cache_stats {
/*
* We only need this data after we have decided to send an audit message.
*/
-struct selinux_late_audit_data {
+struct selinux_audit_data {
u32 ssid;
u32 tsid;
u16 tclass;
@@ -60,28 +60,86 @@ struct selinux_late_audit_data {
};
/*
- * We collect this at the beginning or during an selinux security operation
- */
-struct selinux_audit_data {
- /*
- * auditdeny is a bit tricky and unintuitive. See the
- * comments in avc.c for it's meaning and usage.
- */
- u32 auditdeny;
- struct selinux_late_audit_data *slad;
-};
-
-/*
* AVC operations
*/
void __init avc_init(void);
-int avc_audit(u32 ssid, u32 tsid,
- u16 tclass, u32 requested,
- struct av_decision *avd,
- int result,
- struct common_audit_data *a, unsigned flags);
+static inline u32 avc_audit_required(u32 requested,
+ struct av_decision *avd,
+ int result,
+ u32 auditdeny,
+ u32 *deniedp)
+{
+ u32 denied, audited;
+ denied = requested & ~avd->allowed;
+ if (unlikely(denied)) {
+ audited = denied & avd->auditdeny;
+ /*
+ * auditdeny is TRICKY! Setting a bit in
+ * this field means that ANY denials should NOT be audited if
+ * the policy contains an explicit dontaudit rule for that
+ * permission. Take notice that this is unrelated to the
+ * actual permissions that were denied. As an example lets
+ * assume:
+ *
+ * denied == READ
+ * avd.auditdeny & ACCESS == 0 (not set means explicit rule)
+ * auditdeny & ACCESS == 1
+ *
+ * We will NOT audit the denial even though the denied
+ * permission was READ and the auditdeny checks were for
+ * ACCESS
+ */
+ if (auditdeny && !(auditdeny & avd->auditdeny))
+ audited = 0;
+ } else if (result)
+ audited = denied = requested;
+ else
+ audited = requested & avd->auditallow;
+ *deniedp = denied;
+ return audited;
+}
+
+int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
+ u32 requested, u32 audited, u32 denied,
+ struct common_audit_data *a,
+ unsigned flags);
+
+/**
+ * avc_audit - Audit the granting or denial of permissions.
+ * @ssid: source security identifier
+ * @tsid: target security identifier
+ * @tclass: target security class
+ * @requested: requested permissions
+ * @avd: access vector decisions
+ * @result: result from avc_has_perm_noaudit
+ * @a: auxiliary audit data
+ * @flags: VFS walk flags
+ *
+ * Audit the granting or denial of permissions in accordance
+ * with the policy. This function is typically called by
+ * avc_has_perm() after a permission check, but can also be
+ * called directly by callers who use avc_has_perm_noaudit()
+ * in order to separate the permission check from the auditing.
+ * For example, this separation is useful when the permission check must
+ * be performed under a lock, to allow the lock to be released
+ * before calling the auditing code.
+ */
+static inline int avc_audit(u32 ssid, u32 tsid,
+ u16 tclass, u32 requested,
+ struct av_decision *avd,
+ int result,
+ struct common_audit_data *a, unsigned flags)
+{
+ u32 audited, denied;
+ audited = avc_audit_required(requested, avd, result, 0, &denied);
+ if (likely(!audited))
+ return 0;
+ return slow_avc_audit(ssid, tsid, tclass,
+ requested, audited, denied,
+ a, flags);
+}
#define AVC_STRICT 1 /* Ignore permissive mode. */
int avc_has_perm_noaudit(u32 ssid, u32 tsid,
@@ -112,11 +170,7 @@ u32 avc_policy_seqno(void);
#define AVC_CALLBACK_AUDITDENY_ENABLE 64
#define AVC_CALLBACK_AUDITDENY_DISABLE 128
-int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
- u16 tclass, u32 perms,
- u32 *out_retained),
- u32 events, u32 ssid, u32 tsid,
- u16 tclass, u32 perms);
+int avc_add_callback(int (*callback)(u32 event), u32 events);
/* Exported to selinuxfs */
int avc_get_hash_stats(char *page);
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index d871e8ad2103..dde2005407aa 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -31,13 +31,15 @@
#define POLICYDB_VERSION_BOUNDARY 24
#define POLICYDB_VERSION_FILENAME_TRANS 25
#define POLICYDB_VERSION_ROLETRANS 26
+#define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27
+#define POLICYDB_VERSION_DEFAULT_TYPE 28
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
#else
-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_ROLETRANS
+#define POLICYDB_VERSION_MAX POLICYDB_VERSION_DEFAULT_TYPE
#endif
/* Mask for just the mount related flags */
diff --git a/security/selinux/netif.c b/security/selinux/netif.c
index 326f22cbe405..47a49d1a6f6a 100644
--- a/security/selinux/netif.c
+++ b/security/selinux/netif.c
@@ -252,8 +252,7 @@ static void sel_netif_flush(void)
spin_unlock_bh(&sel_netif_lock);
}
-static int sel_netif_avc_callback(u32 event, u32 ssid, u32 tsid,
- u16 class, u32 perms, u32 *retained)
+static int sel_netif_avc_callback(u32 event)
{
if (event == AVC_CALLBACK_RESET) {
sel_netif_flush();
@@ -292,8 +291,7 @@ static __init int sel_netif_init(void)
register_netdevice_notifier(&sel_netif_netdev_notifier);
- err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET,
- SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+ err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET);
if (err)
panic("avc_add_callback() failed, error %d\n", err);
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index 86365857c088..28f911cdd7c7 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -297,8 +297,7 @@ static void sel_netnode_flush(void)
spin_unlock_bh(&sel_netnode_lock);
}
-static int sel_netnode_avc_callback(u32 event, u32 ssid, u32 tsid,
- u16 class, u32 perms, u32 *retained)
+static int sel_netnode_avc_callback(u32 event)
{
if (event == AVC_CALLBACK_RESET) {
sel_netnode_flush();
@@ -320,8 +319,7 @@ static __init int sel_netnode_init(void)
sel_netnode_hash[iter].size = 0;
}
- ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET,
- SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+ ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET);
if (ret != 0)
panic("avc_add_callback() failed, error %d\n", ret);
diff --git a/security/selinux/netport.c b/security/selinux/netport.c
index 7b9eb1faf68b..d35379781c2c 100644
--- a/security/selinux/netport.c
+++ b/security/selinux/netport.c
@@ -234,8 +234,7 @@ static void sel_netport_flush(void)
spin_unlock_bh(&sel_netport_lock);
}
-static int sel_netport_avc_callback(u32 event, u32 ssid, u32 tsid,
- u16 class, u32 perms, u32 *retained)
+static int sel_netport_avc_callback(u32 event)
{
if (event == AVC_CALLBACK_RESET) {
sel_netport_flush();
@@ -257,8 +256,7 @@ static __init int sel_netport_init(void)
sel_netport_hash[iter].size = 0;
}
- ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET,
- SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+ ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET);
if (ret != 0)
panic("avc_add_callback() failed, error %d\n", ret);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index d7018bfa1f00..4e93f9ef970b 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -496,6 +496,7 @@ static const struct file_operations sel_policy_ops = {
.read = sel_read_policy,
.mmap = sel_mmap_policy,
.release = sel_release_policy,
+ .llseek = generic_file_llseek,
};
static ssize_t sel_write_load(struct file *file, const char __user *buf,
@@ -1232,6 +1233,7 @@ static int sel_make_bools(void)
kfree(bool_pending_names[i]);
kfree(bool_pending_names);
kfree(bool_pending_values);
+ bool_num = 0;
bool_pending_names = NULL;
bool_pending_values = NULL;
@@ -1532,11 +1534,6 @@ static int sel_make_initcon_files(struct dentry *dir)
return 0;
}
-static inline unsigned int sel_div(unsigned long a, unsigned long b)
-{
- return a / b - (a % b < 0);
-}
-
static inline unsigned long sel_class_to_ino(u16 class)
{
return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET;
@@ -1544,7 +1541,7 @@ static inline unsigned long sel_class_to_ino(u16 class)
static inline u16 sel_ino_to_class(unsigned long ino)
{
- return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1);
+ return (ino & SEL_INO_MASK) / (SEL_VEC_MAX + 1);
}
static inline unsigned long sel_perm_to_ino(u16 class, u32 perm)
@@ -1831,7 +1828,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
[SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
[SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
[SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO},
- [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUSR},
+ [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO},
/* last one */ {""}
};
ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h
index 45e8fb0515f8..212e3479a0d9 100644
--- a/security/selinux/ss/context.h
+++ b/security/selinux/ss/context.h
@@ -74,6 +74,26 @@ out:
return rc;
}
+/*
+ * Sets both levels in the MLS range of 'dst' to the high level of 'src'.
+ */
+static inline int mls_context_cpy_high(struct context *dst, struct context *src)
+{
+ int rc;
+
+ dst->range.level[0].sens = src->range.level[1].sens;
+ rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[1].cat);
+ if (rc)
+ goto out;
+
+ dst->range.level[1].sens = src->range.level[1].sens;
+ rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat);
+ if (rc)
+ ebitmap_destroy(&dst->range.level[0].cat);
+out:
+ return rc;
+}
+
static inline int mls_context_cmp(struct context *c1, struct context *c2)
{
return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index fbf9c5816c71..40de8d3f208e 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -517,6 +517,8 @@ int mls_compute_sid(struct context *scontext,
{
struct range_trans rtr;
struct mls_range *r;
+ struct class_datum *cladatum;
+ int default_range = 0;
if (!policydb.mls_enabled)
return 0;
@@ -530,6 +532,28 @@ int mls_compute_sid(struct context *scontext,
r = hashtab_search(policydb.range_tr, &rtr);
if (r)
return mls_range_set(newcontext, r);
+
+ if (tclass && tclass <= policydb.p_classes.nprim) {
+ cladatum = policydb.class_val_to_struct[tclass - 1];
+ if (cladatum)
+ default_range = cladatum->default_range;
+ }
+
+ switch (default_range) {
+ case DEFAULT_SOURCE_LOW:
+ return mls_context_cpy_low(newcontext, scontext);
+ case DEFAULT_SOURCE_HIGH:
+ return mls_context_cpy_high(newcontext, scontext);
+ case DEFAULT_SOURCE_LOW_HIGH:
+ return mls_context_cpy(newcontext, scontext);
+ case DEFAULT_TARGET_LOW:
+ return mls_context_cpy_low(newcontext, tcontext);
+ case DEFAULT_TARGET_HIGH:
+ return mls_context_cpy_high(newcontext, tcontext);
+ case DEFAULT_TARGET_LOW_HIGH:
+ return mls_context_cpy(newcontext, tcontext);
+ }
+
/* Fallthrough */
case AVTAB_CHANGE:
if ((tclass == policydb.process_class) || (sock == true))
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index a7f61d52f05c..9cd9b7c661ec 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -133,6 +133,16 @@ static struct policydb_compat_info policydb_compat[] = {
.sym_num = SYM_NUM,
.ocon_num = OCON_NUM,
},
+ {
+ .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NUM,
+ },
+ {
+ .version = POLICYDB_VERSION_DEFAULT_TYPE,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NUM,
+ },
};
static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -1306,6 +1316,23 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
goto bad;
}
+ if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) {
+ rc = next_entry(buf, fp, sizeof(u32) * 3);
+ if (rc)
+ goto bad;
+
+ cladatum->default_user = le32_to_cpu(buf[0]);
+ cladatum->default_role = le32_to_cpu(buf[1]);
+ cladatum->default_range = le32_to_cpu(buf[2]);
+ }
+
+ if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) {
+ rc = next_entry(buf, fp, sizeof(u32) * 1);
+ if (rc)
+ goto bad;
+ cladatum->default_type = le32_to_cpu(buf[0]);
+ }
+
rc = hashtab_insert(h, key, cladatum);
if (rc)
goto bad;
@@ -2832,6 +2859,23 @@ static int class_write(void *vkey, void *datum, void *ptr)
if (rc)
return rc;
+ if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) {
+ buf[0] = cpu_to_le32(cladatum->default_user);
+ buf[1] = cpu_to_le32(cladatum->default_role);
+ buf[2] = cpu_to_le32(cladatum->default_range);
+
+ rc = put_entry(buf, sizeof(uint32_t), 3, fp);
+ if (rc)
+ return rc;
+ }
+
+ if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) {
+ buf[0] = cpu_to_le32(cladatum->default_type);
+ rc = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (rc)
+ return rc;
+ }
+
return 0;
}
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index b846c0387180..da637471d4ce 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -60,6 +60,20 @@ struct class_datum {
struct symtab permissions; /* class-specific permission symbol table */
struct constraint_node *constraints; /* constraints on class permissions */
struct constraint_node *validatetrans; /* special transition rules */
+/* Options how a new object user, role, and type should be decided */
+#define DEFAULT_SOURCE 1
+#define DEFAULT_TARGET 2
+ char default_user;
+ char default_role;
+ char default_type;
+/* Options how a new object range should be decided */
+#define DEFAULT_SOURCE_LOW 1
+#define DEFAULT_SOURCE_HIGH 2
+#define DEFAULT_SOURCE_LOW_HIGH 3
+#define DEFAULT_TARGET_LOW 4
+#define DEFAULT_TARGET_HIGH 5
+#define DEFAULT_TARGET_LOW_HIGH 6
+ char default_range;
};
/* Role attributes */
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 185f849a26f6..4321b8fc8863 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1018,9 +1018,11 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
if (context->len) {
*scontext_len = context->len;
- *scontext = kstrdup(context->str, GFP_ATOMIC);
- if (!(*scontext))
- return -ENOMEM;
+ if (scontext) {
+ *scontext = kstrdup(context->str, GFP_ATOMIC);
+ if (!(*scontext))
+ return -ENOMEM;
+ }
return 0;
}
@@ -1389,6 +1391,7 @@ static int security_compute_sid(u32 ssid,
u32 *out_sid,
bool kern)
{
+ struct class_datum *cladatum = NULL;
struct context *scontext = NULL, *tcontext = NULL, newcontext;
struct role_trans *roletr = NULL;
struct avtab_key avkey;
@@ -1437,12 +1440,20 @@ static int security_compute_sid(u32 ssid,
goto out_unlock;
}
+ if (tclass && tclass <= policydb.p_classes.nprim)
+ cladatum = policydb.class_val_to_struct[tclass - 1];
+
/* Set the user identity. */
switch (specified) {
case AVTAB_TRANSITION:
case AVTAB_CHANGE:
- /* Use the process user identity. */
- newcontext.user = scontext->user;
+ if (cladatum && cladatum->default_user == DEFAULT_TARGET) {
+ newcontext.user = tcontext->user;
+ } else {
+ /* notice this gets both DEFAULT_SOURCE and unset */
+ /* Use the process user identity. */
+ newcontext.user = scontext->user;
+ }
break;
case AVTAB_MEMBER:
/* Use the related object owner. */
@@ -1450,16 +1461,31 @@ static int security_compute_sid(u32 ssid,
break;
}
- /* Set the role and type to default values. */
- if ((tclass == policydb.process_class) || (sock == true)) {
- /* Use the current role and type of process. */
+ /* Set the role to default values. */
+ if (cladatum && cladatum->default_role == DEFAULT_SOURCE) {
newcontext.role = scontext->role;
- newcontext.type = scontext->type;
+ } else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
+ newcontext.role = tcontext->role;
} else {
- /* Use the well-defined object role. */
- newcontext.role = OBJECT_R_VAL;
- /* Use the type of the related object. */
+ if ((tclass == policydb.process_class) || (sock == true))
+ newcontext.role = scontext->role;
+ else
+ newcontext.role = OBJECT_R_VAL;
+ }
+
+ /* Set the type to default values. */
+ if (cladatum && cladatum->default_type == DEFAULT_SOURCE) {
+ newcontext.type = scontext->type;
+ } else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
newcontext.type = tcontext->type;
+ } else {
+ if ((tclass == policydb.process_class) || (sock == true)) {
+ /* Use the type of process. */
+ newcontext.type = scontext->type;
+ } else {
+ /* Use the type of the related object. */
+ newcontext.type = tcontext->type;
+ }
}
/* Look for a type transition/member/change rule. */
@@ -3018,8 +3044,7 @@ out:
static int (*aurule_callback)(void) = audit_update_lsm_rules;
-static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid,
- u16 class, u32 perms, u32 *retained)
+static int aurule_avc_callback(u32 event)
{
int err = 0;
@@ -3032,8 +3057,7 @@ static int __init aurule_init(void)
{
int err;
- err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET,
- SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+ err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET);
if (err)
panic("avc_add_callback() failed, error %d\n", err);
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 4ede719922ed..cc361b8f3d13 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -23,13 +23,19 @@
#include <linux/lsm_audit.h>
/*
+ * Smack labels were limited to 23 characters for a long time.
+ */
+#define SMK_LABELLEN 24
+#define SMK_LONGLABEL 256
+
+/*
+ * Maximum number of bytes for the levels in a CIPSO IP option.
* Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
* bigger than can be used, and 24 is the next lower multiple
* of 8, and there are too many issues if there isn't space set
* aside for the terminating null byte.
*/
-#define SMK_MAXLEN 23
-#define SMK_LABELLEN (SMK_MAXLEN+1)
+#define SMK_CIPSOLEN 24
struct superblock_smack {
char *smk_root;
@@ -66,6 +72,7 @@ struct task_smack {
#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
#define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */
+#define SMK_INODE_CHANGED 0x04 /* smack was transmuted */
/*
* A label access rule.
@@ -78,15 +85,6 @@ struct smack_rule {
};
/*
- * An entry in the table mapping smack values to
- * CIPSO level/category-set values.
- */
-struct smack_cipso {
- int smk_level;
- char smk_catset[SMK_LABELLEN];
-};
-
-/*
* An entry in the table identifying hosts.
*/
struct smk_netlbladdr {
@@ -113,22 +111,19 @@ struct smk_netlbladdr {
* interfaces don't. The secid should go away when all of
* these components have been repaired.
*
- * If there is a cipso value associated with the label it
- * gets stored here, too. This will most likely be rare as
- * the cipso direct mapping in used internally.
+ * The cipso value associated with the label gets stored here, too.
*
* Keep the access rules for this subject label here so that
* the entire set of rules does not need to be examined every
* time.
*/
struct smack_known {
- struct list_head list;
- char smk_known[SMK_LABELLEN];
- u32 smk_secid;
- struct smack_cipso *smk_cipso;
- spinlock_t smk_cipsolock; /* for changing cipso map */
- struct list_head smk_rules; /* access rules */
- struct mutex smk_rules_lock; /* lock for the rules */
+ struct list_head list;
+ char *smk_known;
+ u32 smk_secid;
+ struct netlbl_lsm_secattr smk_netlabel; /* on wire labels */
+ struct list_head smk_rules; /* access rules */
+ struct mutex smk_rules_lock; /* lock for rules */
};
/*
@@ -165,6 +160,7 @@ struct smack_known {
#define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */
#define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */
#define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */
+#define SMACK_CIPSO_MAPPED_DEFAULT 251 /* Also arbitrary */
#define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */
#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */
#define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */
@@ -215,10 +211,9 @@ struct inode_smack *new_inode_smack(char *);
int smk_access_entry(char *, char *, struct list_head *);
int smk_access(char *, char *, int, struct smk_audit_info *);
int smk_curacc(char *, u32, struct smk_audit_info *);
-int smack_to_cipso(const char *, struct smack_cipso *);
-char *smack_from_cipso(u32, char *);
char *smack_from_secid(const u32);
-void smk_parse_smack(const char *string, int len, char *smack);
+char *smk_parse_smack(const char *string, int len);
+int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
char *smk_import(const char *, int);
struct smack_known *smk_import_entry(const char *, int);
struct smack_known *smk_find_entry(const char *);
@@ -228,6 +223,7 @@ u32 smack_to_secid(const char *);
* Shared data.
*/
extern int smack_cipso_direct;
+extern int smack_cipso_mapped;
extern char *smack_net_ambient;
extern char *smack_onlycap;
extern const char *smack_cipso_option;
@@ -239,24 +235,13 @@ extern struct smack_known smack_known_invalid;
extern struct smack_known smack_known_star;
extern struct smack_known smack_known_web;
+extern struct mutex smack_known_lock;
extern struct list_head smack_known_list;
extern struct list_head smk_netlbladdr_list;
extern struct security_operations smack_ops;
/*
- * Stricly for CIPSO level manipulation.
- * Set the category bit number in a smack label sized buffer.
- */
-static inline void smack_catset_bit(int cat, char *catsetp)
-{
- if (cat > SMK_LABELLEN * 8)
- return;
-
- catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
-}
-
-/*
* Is the directory transmuting?
*/
static inline int smk_inode_transmutable(const struct inode *isp)
@@ -319,7 +304,7 @@ void smack_log(char *subject_label, char *object_label,
static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
char type)
{
- memset(a, 0, sizeof(*a));
+ memset(&a->sad, 0, sizeof(a->sad));
a->a.type = type;
a->a.smack_audit_data = &a->sad;
a->a.smack_audit_data->function = func;
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index c8115f7308f8..9f3705e92712 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -19,37 +19,31 @@
struct smack_known smack_known_huh = {
.smk_known = "?",
.smk_secid = 2,
- .smk_cipso = NULL,
};
struct smack_known smack_known_hat = {
.smk_known = "^",
.smk_secid = 3,
- .smk_cipso = NULL,
};
struct smack_known smack_known_star = {
.smk_known = "*",
.smk_secid = 4,
- .smk_cipso = NULL,
};
struct smack_known smack_known_floor = {
.smk_known = "_",
.smk_secid = 5,
- .smk_cipso = NULL,
};
struct smack_known smack_known_invalid = {
.smk_known = "",
.smk_secid = 6,
- .smk_cipso = NULL,
};
struct smack_known smack_known_web = {
.smk_known = "@",
.smk_secid = 7,
- .smk_cipso = NULL,
};
LIST_HEAD(smack_known_list);
@@ -331,7 +325,7 @@ void smack_log(char *subject_label, char *object_label, int request,
}
#endif
-static DEFINE_MUTEX(smack_known_lock);
+DEFINE_MUTEX(smack_known_lock);
/**
* smk_find_entry - find a label on the list, return the list entry
@@ -345,7 +339,7 @@ struct smack_known *smk_find_entry(const char *string)
struct smack_known *skp;
list_for_each_entry_rcu(skp, &smack_known_list, list) {
- if (strncmp(skp->smk_known, string, SMK_MAXLEN) == 0)
+ if (strcmp(skp->smk_known, string) == 0)
return skp;
}
@@ -356,27 +350,76 @@ struct smack_known *smk_find_entry(const char *string)
* smk_parse_smack - parse smack label from a text string
* @string: a text string that might contain a Smack label
* @len: the maximum size, or zero if it is NULL terminated.
- * @smack: parsed smack label, or NULL if parse error
+ *
+ * Returns a pointer to the clean label, or NULL
*/
-void smk_parse_smack(const char *string, int len, char *smack)
+char *smk_parse_smack(const char *string, int len)
{
- int found;
+ char *smack;
int i;
- if (len <= 0 || len > SMK_MAXLEN)
- len = SMK_MAXLEN;
-
- for (i = 0, found = 0; i < SMK_LABELLEN; i++) {
- if (found)
- smack[i] = '\0';
- else if (i >= len || string[i] > '~' || string[i] <= ' ' ||
- string[i] == '/' || string[i] == '"' ||
- string[i] == '\\' || string[i] == '\'') {
- smack[i] = '\0';
- found = 1;
- } else
- smack[i] = string[i];
+ if (len <= 0)
+ len = strlen(string) + 1;
+
+ /*
+ * Reserve a leading '-' as an indicator that
+ * this isn't a label, but an option to interfaces
+ * including /smack/cipso and /smack/cipso2
+ */
+ if (string[0] == '-')
+ return NULL;
+
+ for (i = 0; i < len; i++)
+ if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' ||
+ string[i] == '"' || string[i] == '\\' || string[i] == '\'')
+ break;
+
+ if (i == 0 || i >= SMK_LONGLABEL)
+ return NULL;
+
+ smack = kzalloc(i + 1, GFP_KERNEL);
+ if (smack != NULL) {
+ strncpy(smack, string, i + 1);
+ smack[i] = '\0';
}
+ return smack;
+}
+
+/**
+ * smk_netlbl_mls - convert a catset to netlabel mls categories
+ * @catset: the Smack categories
+ * @sap: where to put the netlabel categories
+ *
+ * Allocates and fills attr.mls
+ * Returns 0 on success, error code on failure.
+ */
+int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
+ int len)
+{
+ unsigned char *cp;
+ unsigned char m;
+ int cat;
+ int rc;
+ int byte;
+
+ sap->flags |= NETLBL_SECATTR_MLS_CAT;
+ sap->attr.mls.lvl = level;
+ sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
+ sap->attr.mls.cat->startbit = 0;
+
+ for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++)
+ for (m = 0x80; m != 0; m >>= 1, cat++) {
+ if ((m & *cp) == 0)
+ continue;
+ rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat,
+ cat, GFP_ATOMIC);
+ if (rc < 0) {
+ netlbl_secattr_catmap_free(sap->attr.mls.cat);
+ return rc;
+ }
+ }
+
+ return 0;
}
/**
@@ -390,33 +433,59 @@ void smk_parse_smack(const char *string, int len, char *smack)
struct smack_known *smk_import_entry(const char *string, int len)
{
struct smack_known *skp;
- char smack[SMK_LABELLEN];
+ char *smack;
+ int slen;
+ int rc;
- smk_parse_smack(string, len, smack);
- if (smack[0] == '\0')
+ smack = smk_parse_smack(string, len);
+ if (smack == NULL)
return NULL;
mutex_lock(&smack_known_lock);
skp = smk_find_entry(smack);
+ if (skp != NULL)
+ goto freeout;
- if (skp == NULL) {
- skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
- if (skp != NULL) {
- strncpy(skp->smk_known, smack, SMK_MAXLEN);
- skp->smk_secid = smack_next_secid++;
- skp->smk_cipso = NULL;
- INIT_LIST_HEAD(&skp->smk_rules);
- spin_lock_init(&skp->smk_cipsolock);
- mutex_init(&skp->smk_rules_lock);
- /*
- * Make sure that the entry is actually
- * filled before putting it on the list.
- */
- list_add_rcu(&skp->list, &smack_known_list);
- }
- }
+ skp = kzalloc(sizeof(*skp), GFP_KERNEL);
+ if (skp == NULL)
+ goto freeout;
+ skp->smk_known = smack;
+ skp->smk_secid = smack_next_secid++;
+ skp->smk_netlabel.domain = skp->smk_known;
+ skp->smk_netlabel.flags =
+ NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
+ /*
+ * If direct labeling works use it.
+ * Otherwise use mapped labeling.
+ */
+ slen = strlen(smack);
+ if (slen < SMK_CIPSOLEN)
+ rc = smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
+ &skp->smk_netlabel, slen);
+ else
+ rc = smk_netlbl_mls(smack_cipso_mapped, (char *)&skp->smk_secid,
+ &skp->smk_netlabel, sizeof(skp->smk_secid));
+
+ if (rc >= 0) {
+ INIT_LIST_HEAD(&skp->smk_rules);
+ mutex_init(&skp->smk_rules_lock);
+ /*
+ * Make sure that the entry is actually
+ * filled before putting it on the list.
+ */
+ list_add_rcu(&skp->list, &smack_known_list);
+ goto unlockout;
+ }
+ /*
+ * smk_netlbl_mls failed.
+ */
+ kfree(skp);
+ skp = NULL;
+freeout:
+ kfree(smack);
+unlockout:
mutex_unlock(&smack_known_lock);
return skp;
@@ -479,79 +548,9 @@ char *smack_from_secid(const u32 secid)
*/
u32 smack_to_secid(const char *smack)
{
- struct smack_known *skp;
+ struct smack_known *skp = smk_find_entry(smack);
- rcu_read_lock();
- list_for_each_entry_rcu(skp, &smack_known_list, list) {
- if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
- rcu_read_unlock();
- return skp->smk_secid;
- }
- }
- rcu_read_unlock();
- return 0;
-}
-
-/**
- * smack_from_cipso - find the Smack label associated with a CIPSO option
- * @level: Bell & LaPadula level from the network
- * @cp: Bell & LaPadula categories from the network
- *
- * This is a simple lookup in the label table.
- *
- * Return the matching label from the label list or NULL.
- */
-char *smack_from_cipso(u32 level, char *cp)
-{
- struct smack_known *kp;
- char *final = NULL;
-
- rcu_read_lock();
- list_for_each_entry(kp, &smack_known_list, list) {
- if (kp->smk_cipso == NULL)
- continue;
-
- spin_lock_bh(&kp->smk_cipsolock);
-
- if (kp->smk_cipso->smk_level == level &&
- memcmp(kp->smk_cipso->smk_catset, cp, SMK_LABELLEN) == 0)
- final = kp->smk_known;
-
- spin_unlock_bh(&kp->smk_cipsolock);
-
- if (final != NULL)
- break;
- }
- rcu_read_unlock();
-
- return final;
-}
-
-/**
- * smack_to_cipso - find the CIPSO option to go with a Smack label
- * @smack: a pointer to the smack label in question
- * @cp: where to put the result
- *
- * Returns zero if a value is available, non-zero otherwise.
- */
-int smack_to_cipso(const char *smack, struct smack_cipso *cp)
-{
- struct smack_known *kp;
- int found = 0;
-
- rcu_read_lock();
- list_for_each_entry_rcu(kp, &smack_known_list, list) {
- if (kp->smk_known == smack ||
- strcmp(kp->smk_known, smack) == 0) {
- found = 1;
- break;
- }
- }
- rcu_read_unlock();
-
- if (found == 0 || kp->smk_cipso == NULL)
- return -ENOENT;
-
- memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso));
- return 0;
+ if (skp == NULL)
+ return 0;
+ return skp->smk_secid;
}
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 45c32f074166..d583c0545808 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -30,7 +30,6 @@
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/pipe_fs_i.h>
-#include <net/netlabel.h>
#include <net/cipso_ipv4.h>
#include <linux/audit.h>
#include <linux/magic.h>
@@ -57,16 +56,23 @@
static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp)
{
int rc;
- char in[SMK_LABELLEN];
+ char *buffer;
+ char *result = NULL;
if (ip->i_op->getxattr == NULL)
return NULL;
- rc = ip->i_op->getxattr(dp, name, in, SMK_LABELLEN);
- if (rc < 0)
+ buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
+ if (buffer == NULL)
return NULL;
- return smk_import(in, rc);
+ rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL);
+ if (rc > 0)
+ result = smk_import(buffer, rc);
+
+ kfree(buffer);
+
+ return result;
}
/**
@@ -79,7 +85,7 @@ struct inode_smack *new_inode_smack(char *smack)
{
struct inode_smack *isp;
- isp = kzalloc(sizeof(struct inode_smack), GFP_KERNEL);
+ isp = kzalloc(sizeof(struct inode_smack), GFP_NOFS);
if (isp == NULL)
return NULL;
@@ -556,13 +562,14 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
void **value, size_t *len)
{
struct smack_known *skp;
+ struct inode_smack *issp = inode->i_security;
char *csp = smk_of_current();
char *isp = smk_of_inode(inode);
char *dsp = smk_of_inode(dir);
int may;
if (name) {
- *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL);
+ *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_NOFS);
if (*name == NULL)
return -ENOMEM;
}
@@ -577,12 +584,15 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
* If the access rule allows transmutation and
* the directory requests transmutation then
* by all means transmute.
+ * Mark the inode as changed.
*/
if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
- smk_inode_transmutable(dir))
+ smk_inode_transmutable(dir)) {
isp = dsp;
+ issp->smk_flags |= SMK_INODE_CHANGED;
+ }
- *value = kstrdup(isp, GFP_KERNEL);
+ *value = kstrdup(isp, GFP_NOFS);
if (*value == NULL)
return -ENOMEM;
}
@@ -821,7 +831,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
* check label validity here so import wont fail on
* post_setxattr
*/
- if (size == 0 || size >= SMK_LABELLEN ||
+ if (size == 0 || size >= SMK_LONGLABEL ||
smk_import(value, size) == NULL)
rc = -EINVAL;
} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
@@ -1349,7 +1359,7 @@ static int smack_file_receive(struct file *file)
}
/**
- * smack_dentry_open - Smack dentry open processing
+ * smack_file_open - Smack dentry open processing
* @file: the object
* @cred: unused
*
@@ -1357,7 +1367,7 @@ static int smack_file_receive(struct file *file)
*
* Returns 0
*/
-static int smack_dentry_open(struct file *file, const struct cred *cred)
+static int smack_file_open(struct file *file, const struct cred *cred)
{
struct inode_smack *isp = file->f_path.dentry->d_inode->i_security;
@@ -1820,65 +1830,6 @@ static char *smack_host_label(struct sockaddr_in *sip)
}
/**
- * smack_set_catset - convert a capset to netlabel mls categories
- * @catset: the Smack categories
- * @sap: where to put the netlabel categories
- *
- * Allocates and fills attr.mls.cat
- */
-static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap)
-{
- unsigned char *cp;
- unsigned char m;
- int cat;
- int rc;
- int byte;
-
- if (!catset)
- return;
-
- sap->flags |= NETLBL_SECATTR_MLS_CAT;
- sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
- sap->attr.mls.cat->startbit = 0;
-
- for (cat = 1, cp = catset, byte = 0; byte < SMK_LABELLEN; cp++, byte++)
- for (m = 0x80; m != 0; m >>= 1, cat++) {
- if ((m & *cp) == 0)
- continue;
- rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat,
- cat, GFP_ATOMIC);
- }
-}
-
-/**
- * smack_to_secattr - fill a secattr from a smack value
- * @smack: the smack value
- * @nlsp: where the result goes
- *
- * Casey says that CIPSO is good enough for now.
- * It can be used to effect.
- * It can also be abused to effect when necessary.
- * Apologies to the TSIG group in general and GW in particular.
- */
-static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
-{
- struct smack_cipso cipso;
- int rc;
-
- nlsp->domain = smack;
- nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
-
- rc = smack_to_cipso(smack, &cipso);
- if (rc == 0) {
- nlsp->attr.mls.lvl = cipso.smk_level;
- smack_set_catset(cipso.smk_catset, nlsp);
- } else {
- nlsp->attr.mls.lvl = smack_cipso_direct;
- smack_set_catset(smack, nlsp);
- }
-}
-
-/**
* smack_netlabel - Set the secattr on a socket
* @sk: the socket
* @labeled: socket label scheme
@@ -1890,8 +1841,8 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
*/
static int smack_netlabel(struct sock *sk, int labeled)
{
+ struct smack_known *skp;
struct socket_smack *ssp = sk->sk_security;
- struct netlbl_lsm_secattr secattr;
int rc = 0;
/*
@@ -1909,10 +1860,8 @@ static int smack_netlabel(struct sock *sk, int labeled)
labeled == SMACK_UNLABELED_SOCKET)
netlbl_sock_delattr(sk);
else {
- netlbl_secattr_init(&secattr);
- smack_to_secattr(ssp->smk_out, &secattr);
- rc = netlbl_sock_setattr(sk, sk->sk_family, &secattr);
- netlbl_secattr_destroy(&secattr);
+ skp = smk_find_entry(ssp->smk_out);
+ rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
}
bh_unlock_sock(sk);
@@ -1985,7 +1934,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
struct socket *sock;
int rc = 0;
- if (value == NULL || size > SMK_LABELLEN || size == 0)
+ if (value == NULL || size > SMK_LONGLABEL || size == 0)
return -EACCES;
sp = smk_import(value, size);
@@ -2552,6 +2501,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
char *final;
char trattr[TRANS_TRUE_SIZE];
int transflag = 0;
+ int rc;
struct dentry *dp;
if (inode == NULL)
@@ -2670,17 +2620,38 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
*/
dp = dget(opt_dentry);
fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp);
- if (fetched != NULL) {
+ if (fetched != NULL)
final = fetched;
- if (S_ISDIR(inode->i_mode)) {
- trattr[0] = '\0';
- inode->i_op->getxattr(dp,
+
+ /*
+ * Transmuting directory
+ */
+ if (S_ISDIR(inode->i_mode)) {
+ /*
+ * If this is a new directory and the label was
+ * transmuted when the inode was initialized
+ * set the transmute attribute on the directory
+ * and mark the inode.
+ *
+ * If there is a transmute attribute on the
+ * directory mark the inode.
+ */
+ if (isp->smk_flags & SMK_INODE_CHANGED) {
+ isp->smk_flags &= ~SMK_INODE_CHANGED;
+ rc = inode->i_op->setxattr(dp,
XATTR_NAME_SMACKTRANSMUTE,
- trattr, TRANS_TRUE_SIZE);
- if (strncmp(trattr, TRANS_TRUE,
- TRANS_TRUE_SIZE) == 0)
- transflag = SMK_INODE_TRANSMUTE;
+ TRANS_TRUE, TRANS_TRUE_SIZE,
+ 0);
+ } else {
+ rc = inode->i_op->getxattr(dp,
+ XATTR_NAME_SMACKTRANSMUTE, trattr,
+ TRANS_TRUE_SIZE);
+ if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
+ TRANS_TRUE_SIZE) != 0)
+ rc = -EINVAL;
}
+ if (rc >= 0)
+ transflag = SMK_INODE_TRANSMUTE;
}
isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
@@ -2759,7 +2730,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
if (!capable(CAP_MAC_ADMIN))
return -EPERM;
- if (value == NULL || size == 0 || size >= SMK_LABELLEN)
+ if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
return -EINVAL;
if (strcmp(name, "current") != 0)
@@ -2895,10 +2866,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
struct socket_smack *ssp)
{
- struct smack_known *skp;
- char smack[SMK_LABELLEN];
+ struct smack_known *kp;
char *sp;
- int pcat;
+ int found = 0;
if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
/*
@@ -2906,59 +2876,27 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
* If there are flags but no level netlabel isn't
* behaving the way we expect it to.
*
- * Get the categories, if any
+ * Look it up in the label table
* Without guidance regarding the smack value
* for the packet fall back on the network
* ambient value.
*/
- memset(smack, '\0', SMK_LABELLEN);
- if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0)
- for (pcat = -1;;) {
- pcat = netlbl_secattr_catmap_walk(
- sap->attr.mls.cat, pcat + 1);
- if (pcat < 0)
- break;
- smack_catset_bit(pcat, smack);
- }
- /*
- * If it is CIPSO using smack direct mapping
- * we are already done. WeeHee.
- */
- if (sap->attr.mls.lvl == smack_cipso_direct) {
- /*
- * The label sent is usually on the label list.
- *
- * If it is not we may still want to allow the
- * delivery.
- *
- * If the recipient is accepting all packets
- * because it is using the star ("*") label
- * for SMACK64IPIN provide the web ("@") label
- * so that a directed response will succeed.
- * This is not very correct from a MAC point
- * of view, but gets around the problem that
- * locking prevents adding the newly discovered
- * label to the list.
- * The case where the recipient is not using
- * the star label should obviously fail.
- * The easy way to do this is to provide the
- * star label as the subject label.
- */
- skp = smk_find_entry(smack);
- if (skp != NULL)
- return skp->smk_known;
- if (ssp != NULL &&
- ssp->smk_in == smack_known_star.smk_known)
- return smack_known_web.smk_known;
- return smack_known_star.smk_known;
+ rcu_read_lock();
+ list_for_each_entry(kp, &smack_known_list, list) {
+ if (sap->attr.mls.lvl != kp->smk_netlabel.attr.mls.lvl)
+ continue;
+ if (memcmp(sap->attr.mls.cat,
+ kp->smk_netlabel.attr.mls.cat,
+ SMK_CIPSOLEN) != 0)
+ continue;
+ found = 1;
+ break;
}
- /*
- * Look it up in the supplied table if it is not
- * a direct mapping.
- */
- sp = smack_from_cipso(sap->attr.mls.lvl, smack);
- if (sp != NULL)
- return sp;
+ rcu_read_unlock();
+
+ if (found)
+ return kp->smk_known;
+
if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known)
return smack_known_web.smk_known;
return smack_known_star.smk_known;
@@ -3158,11 +3096,13 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
struct request_sock *req)
{
u16 family = sk->sk_family;
+ struct smack_known *skp;
struct socket_smack *ssp = sk->sk_security;
struct netlbl_lsm_secattr secattr;
struct sockaddr_in addr;
struct iphdr *hdr;
char *sp;
+ char *hsp;
int rc;
struct smk_audit_info ad;
#ifdef CONFIG_AUDIT
@@ -3209,16 +3149,14 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
hdr = ip_hdr(skb);
addr.sin_addr.s_addr = hdr->saddr;
rcu_read_lock();
- if (smack_host_label(&addr) == NULL) {
- rcu_read_unlock();
- netlbl_secattr_init(&secattr);
- smack_to_secattr(sp, &secattr);
- rc = netlbl_req_setattr(req, &secattr);
- netlbl_secattr_destroy(&secattr);
- } else {
- rcu_read_unlock();
+ hsp = smack_host_label(&addr);
+ rcu_read_unlock();
+
+ if (hsp == NULL) {
+ skp = smk_find_entry(sp);
+ rc = netlbl_req_setattr(req, &skp->smk_netlabel);
+ } else
netlbl_req_delattr(req);
- }
return rc;
}
@@ -3400,7 +3338,7 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule,
char *rule = vrule;
if (!rule) {
- audit_log(actx, GFP_KERNEL, AUDIT_SELINUX_ERR,
+ audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
"Smack: missing rule\n");
return -ENOENT;
}
@@ -3549,7 +3487,7 @@ struct security_operations smack_ops = {
.file_send_sigiotask = smack_file_send_sigiotask,
.file_receive = smack_file_receive,
- .dentry_open = smack_dentry_open,
+ .file_open = smack_file_open,
.cred_alloc_blank = smack_cred_alloc_blank,
.cred_free = smack_cred_free,
@@ -3643,15 +3581,6 @@ struct security_operations smack_ops = {
static __init void init_smack_known_list(void)
{
/*
- * Initialize CIPSO locks
- */
- spin_lock_init(&smack_known_huh.smk_cipsolock);
- spin_lock_init(&smack_known_hat.smk_cipsolock);
- spin_lock_init(&smack_known_star.smk_cipsolock);
- spin_lock_init(&smack_known_floor.smk_cipsolock);
- spin_lock_init(&smack_known_invalid.smk_cipsolock);
- spin_lock_init(&smack_known_web.smk_cipsolock);
- /*
* Initialize rule list locks
*/
mutex_init(&smack_known_huh.smk_rules_lock);
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 038811cb7e62..1810c9a4ed48 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -22,7 +22,6 @@
#include <linux/mutex.h>
#include <linux/slab.h>
#include <net/net_namespace.h>
-#include <net/netlabel.h>
#include <net/cipso_ipv4.h>
#include <linux/seq_file.h>
#include <linux/ctype.h>
@@ -45,6 +44,11 @@ enum smk_inos {
SMK_LOGGING = 10, /* logging */
SMK_LOAD_SELF = 11, /* task specific rules */
SMK_ACCESSES = 12, /* access policy */
+ SMK_MAPPED = 13, /* CIPSO level indicating mapped label */
+ SMK_LOAD2 = 14, /* load policy with long labels */
+ SMK_LOAD_SELF2 = 15, /* load task specific rules with long labels */
+ SMK_ACCESS2 = 16, /* make an access check with long labels */
+ SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */
};
/*
@@ -60,7 +64,7 @@ static DEFINE_MUTEX(smk_netlbladdr_lock);
* If it isn't somehow marked, use this.
* It can be reset via smackfs/ambient
*/
-char *smack_net_ambient = smack_known_floor.smk_known;
+char *smack_net_ambient;
/*
* This is the level in a CIPSO header that indicates a
@@ -70,6 +74,13 @@ char *smack_net_ambient = smack_known_floor.smk_known;
int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
/*
+ * This is the level in a CIPSO header that indicates a
+ * secid is contained directly in the category set.
+ * It can be reset via smackfs/mapped
+ */
+int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
+
+/*
* Unless a process is running with this label even
* having CAP_MAC_OVERRIDE isn't enough to grant
* privilege to violate MAC policy. If no label is
@@ -89,7 +100,7 @@ LIST_HEAD(smk_netlbladdr_list);
/*
* Rule lists are maintained for each label.
- * This master list is just for reading /smack/load.
+ * This master list is just for reading /smack/load and /smack/load2.
*/
struct smack_master_list {
struct list_head list;
@@ -125,6 +136,18 @@ const char *smack_cipso_option = SMACK_CIPSO_OPTION;
#define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN)
#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
+/*
+ * Stricly for CIPSO level manipulation.
+ * Set the category bit number in a smack label sized buffer.
+ */
+static inline void smack_catset_bit(unsigned int cat, char *catsetp)
+{
+ if (cat == 0 || cat > (SMK_CIPSOLEN * 8))
+ return;
+
+ catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
+}
+
/**
* smk_netlabel_audit_set - fill a netlbl_audit struct
* @nap: structure to fill
@@ -137,12 +160,10 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap)
}
/*
- * Values for parsing single label host rules
+ * Value for parsing single label host rules
* "1.2.3.4 X"
- * "192.168.138.129/32 abcdefghijklmnopqrstuvw"
*/
#define SMK_NETLBLADDRMIN 9
-#define SMK_NETLBLADDRMAX 42
/**
* smk_set_access - add a rule to the rule list
@@ -188,33 +209,47 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
}
/**
- * smk_parse_rule - parse Smack rule from load string
- * @data: string to be parsed whose size is SMK_LOADLEN
+ * smk_fill_rule - Fill Smack rule from strings
+ * @subject: subject label string
+ * @object: object label string
+ * @access: access string
* @rule: Smack rule
* @import: if non-zero, import labels
+ *
+ * Returns 0 on success, -1 on failure
*/
-static int smk_parse_rule(const char *data, struct smack_rule *rule, int import)
+static int smk_fill_rule(const char *subject, const char *object,
+ const char *access, struct smack_rule *rule,
+ int import)
{
- char smack[SMK_LABELLEN];
+ int rc = -1;
+ int done;
+ const char *cp;
struct smack_known *skp;
if (import) {
- rule->smk_subject = smk_import(data, 0);
+ rule->smk_subject = smk_import(subject, 0);
if (rule->smk_subject == NULL)
return -1;
- rule->smk_object = smk_import(data + SMK_LABELLEN, 0);
+ rule->smk_object = smk_import(object, 0);
if (rule->smk_object == NULL)
return -1;
} else {
- smk_parse_smack(data, 0, smack);
- skp = smk_find_entry(smack);
+ cp = smk_parse_smack(subject, 0);
+ if (cp == NULL)
+ return -1;
+ skp = smk_find_entry(cp);
+ kfree(cp);
if (skp == NULL)
return -1;
rule->smk_subject = skp->smk_known;
- smk_parse_smack(data + SMK_LABELLEN, 0, smack);
- skp = smk_find_entry(smack);
+ cp = smk_parse_smack(object, 0);
+ if (cp == NULL)
+ return -1;
+ skp = smk_find_entry(cp);
+ kfree(cp);
if (skp == NULL)
return -1;
rule->smk_object = skp->smk_known;
@@ -222,90 +257,127 @@ static int smk_parse_rule(const char *data, struct smack_rule *rule, int import)
rule->smk_access = 0;
- switch (data[SMK_LABELLEN + SMK_LABELLEN]) {
- case '-':
- break;
- case 'r':
- case 'R':
- rule->smk_access |= MAY_READ;
- break;
- default:
- return -1;
+ for (cp = access, done = 0; *cp && !done; cp++) {
+ switch (*cp) {
+ case '-':
+ break;
+ case 'r':
+ case 'R':
+ rule->smk_access |= MAY_READ;
+ break;
+ case 'w':
+ case 'W':
+ rule->smk_access |= MAY_WRITE;
+ break;
+ case 'x':
+ case 'X':
+ rule->smk_access |= MAY_EXEC;
+ break;
+ case 'a':
+ case 'A':
+ rule->smk_access |= MAY_APPEND;
+ break;
+ case 't':
+ case 'T':
+ rule->smk_access |= MAY_TRANSMUTE;
+ break;
+ default:
+ done = 1;
+ break;
+ }
}
+ rc = 0;
- switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) {
- case '-':
- break;
- case 'w':
- case 'W':
- rule->smk_access |= MAY_WRITE;
- break;
- default:
- return -1;
- }
+ return rc;
+}
- switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) {
- case '-':
- break;
- case 'x':
- case 'X':
- rule->smk_access |= MAY_EXEC;
- break;
- default:
- return -1;
- }
+/**
+ * smk_parse_rule - parse Smack rule from load string
+ * @data: string to be parsed whose size is SMK_LOADLEN
+ * @rule: Smack rule
+ * @import: if non-zero, import labels
+ *
+ * Returns 0 on success, -1 on errors.
+ */
+static int smk_parse_rule(const char *data, struct smack_rule *rule, int import)
+{
+ int rc;
- switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) {
- case '-':
- break;
- case 'a':
- case 'A':
- rule->smk_access |= MAY_APPEND;
- break;
- default:
- return -1;
- }
+ rc = smk_fill_rule(data, data + SMK_LABELLEN,
+ data + SMK_LABELLEN + SMK_LABELLEN, rule, import);
+ return rc;
+}
- switch (data[SMK_LABELLEN + SMK_LABELLEN + 4]) {
- case '-':
- break;
- case 't':
- case 'T':
- rule->smk_access |= MAY_TRANSMUTE;
- break;
- default:
- return -1;
- }
+/**
+ * smk_parse_long_rule - parse Smack rule from rule string
+ * @data: string to be parsed, null terminated
+ * @rule: Smack rule
+ * @import: if non-zero, import labels
+ *
+ * Returns 0 on success, -1 on failure
+ */
+static int smk_parse_long_rule(const char *data, struct smack_rule *rule,
+ int import)
+{
+ char *subject;
+ char *object;
+ char *access;
+ int datalen;
+ int rc = -1;
- return 0;
+ /*
+ * This is probably inefficient, but safe.
+ */
+ datalen = strlen(data);
+ subject = kzalloc(datalen, GFP_KERNEL);
+ if (subject == NULL)
+ return -1;
+ object = kzalloc(datalen, GFP_KERNEL);
+ if (object == NULL)
+ goto free_out_s;
+ access = kzalloc(datalen, GFP_KERNEL);
+ if (access == NULL)
+ goto free_out_o;
+
+ if (sscanf(data, "%s %s %s", subject, object, access) == 3)
+ rc = smk_fill_rule(subject, object, access, rule, import);
+
+ kfree(access);
+free_out_o:
+ kfree(object);
+free_out_s:
+ kfree(subject);
+ return rc;
}
+#define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */
+#define SMK_LONG_FMT 1 /* Variable long label format */
/**
- * smk_write_load_list - write() for any /smack/load
+ * smk_write_rules_list - write() for any /smack rule file
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start - must be 0
* @rule_list: the list of rules to write to
* @rule_lock: lock for the rule list
+ * @format: /smack/load or /smack/load2 format.
*
* Get one smack access rule from above.
- * The format is exactly:
- * char subject[SMK_LABELLEN]
- * char object[SMK_LABELLEN]
- * char access[SMK_ACCESSLEN]
- *
- * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes.
+ * The format for SMK_LONG_FMT is:
+ * "subject<whitespace>object<whitespace>access[<whitespace>...]"
+ * The format for SMK_FIXED24_FMT is exactly:
+ * "subject object rwxat"
*/
-static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos,
- struct list_head *rule_list,
- struct mutex *rule_lock)
+static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos,
+ struct list_head *rule_list,
+ struct mutex *rule_lock, int format)
{
struct smack_master_list *smlp;
struct smack_known *skp;
struct smack_rule *rule;
char *data;
+ int datalen;
int rc = -EINVAL;
int load = 0;
@@ -315,13 +387,18 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
*/
if (*ppos != 0)
return -EINVAL;
- /*
- * Minor hack for backward compatibility
- */
- if (count < (SMK_OLOADLEN) || count > SMK_LOADLEN)
- return -EINVAL;
- data = kzalloc(SMK_LOADLEN, GFP_KERNEL);
+ if (format == SMK_FIXED24_FMT) {
+ /*
+ * Minor hack for backward compatibility
+ */
+ if (count != SMK_OLOADLEN && count != SMK_LOADLEN)
+ return -EINVAL;
+ datalen = SMK_LOADLEN;
+ } else
+ datalen = count + 1;
+
+ data = kzalloc(datalen, GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
@@ -330,20 +407,29 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
goto out;
}
- /*
- * More on the minor hack for backward compatibility
- */
- if (count == (SMK_OLOADLEN))
- data[SMK_OLOADLEN] = '-';
-
rule = kzalloc(sizeof(*rule), GFP_KERNEL);
if (rule == NULL) {
rc = -ENOMEM;
goto out;
}
- if (smk_parse_rule(data, rule, 1))
- goto out_free_rule;
+ if (format == SMK_LONG_FMT) {
+ /*
+ * Be sure the data string is terminated.
+ */
+ data[count] = '\0';
+ if (smk_parse_long_rule(data, rule, 1))
+ goto out_free_rule;
+ } else {
+ /*
+ * More on the minor hack for backward compatibility
+ */
+ if (count == (SMK_OLOADLEN))
+ data[SMK_OLOADLEN] = '-';
+ if (smk_parse_rule(data, rule, 1))
+ goto out_free_rule;
+ }
+
if (rule_list == NULL) {
load = 1;
@@ -354,18 +440,20 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
rc = count;
/*
- * If this is "load" as opposed to "load-self" and a new rule
+ * If this is a global as opposed to self and a new rule
* it needs to get added for reporting.
* smk_set_access returns true if there was already a rule
* for the subject/object pair, and false if it was new.
*/
- if (load && !smk_set_access(rule, rule_list, rule_lock)) {
- smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
- if (smlp != NULL) {
- smlp->smk_rule = rule;
- list_add_rcu(&smlp->list, &smack_rule_list);
- } else
- rc = -ENOMEM;
+ if (!smk_set_access(rule, rule_list, rule_lock)) {
+ if (load) {
+ smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
+ if (smlp != NULL) {
+ smlp->smk_rule = rule;
+ list_add_rcu(&smlp->list, &smack_rule_list);
+ } else
+ rc = -ENOMEM;
+ }
goto out;
}
@@ -421,29 +509,18 @@ static void smk_seq_stop(struct seq_file *s, void *v)
/* No-op */
}
-/*
- * Seq_file read operations for /smack/load
- */
-
-static void *load_seq_start(struct seq_file *s, loff_t *pos)
-{
- return smk_seq_start(s, pos, &smack_rule_list);
-}
-
-static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
+static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
{
- return smk_seq_next(s, v, pos, &smack_rule_list);
-}
-
-static int load_seq_show(struct seq_file *s, void *v)
-{
- struct list_head *list = v;
- struct smack_master_list *smlp =
- list_entry(list, struct smack_master_list, list);
- struct smack_rule *srp = smlp->smk_rule;
+ /*
+ * Don't show any rules with label names too long for
+ * interface file (/smack/load or /smack/load2)
+ * because you should expect to be able to write
+ * anything you read back.
+ */
+ if (strlen(srp->smk_subject) >= max || strlen(srp->smk_object) >= max)
+ return;
- seq_printf(s, "%s %s", (char *)srp->smk_subject,
- (char *)srp->smk_object);
+ seq_printf(s, "%s %s", srp->smk_subject, srp->smk_object);
seq_putc(s, ' ');
@@ -461,13 +538,36 @@ static int load_seq_show(struct seq_file *s, void *v)
seq_putc(s, '-');
seq_putc(s, '\n');
+}
+
+/*
+ * Seq_file read operations for /smack/load
+ */
+
+static void *load2_seq_start(struct seq_file *s, loff_t *pos)
+{
+ return smk_seq_start(s, pos, &smack_rule_list);
+}
+
+static void *load2_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ return smk_seq_next(s, v, pos, &smack_rule_list);
+}
+
+static int load_seq_show(struct seq_file *s, void *v)
+{
+ struct list_head *list = v;
+ struct smack_master_list *smlp =
+ list_entry(list, struct smack_master_list, list);
+
+ smk_rule_show(s, smlp->smk_rule, SMK_LABELLEN);
return 0;
}
static const struct seq_operations load_seq_ops = {
- .start = load_seq_start,
- .next = load_seq_next,
+ .start = load2_seq_start,
+ .next = load2_seq_next,
.show = load_seq_show,
.stop = smk_seq_stop,
};
@@ -504,7 +604,8 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
if (!capable(CAP_MAC_ADMIN))
return -EPERM;
- return smk_write_load_list(file, buf, count, ppos, NULL, NULL);
+ return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
+ SMK_FIXED24_FMT);
}
static const struct file_operations smk_load_ops = {
@@ -574,6 +675,8 @@ static void smk_unlbl_ambient(char *oldambient)
printk(KERN_WARNING "%s:%d remove rc = %d\n",
__func__, __LINE__, rc);
}
+ if (smack_net_ambient == NULL)
+ smack_net_ambient = smack_known_floor.smk_known;
rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET,
NULL, NULL, &nai);
@@ -605,27 +708,28 @@ static int cipso_seq_show(struct seq_file *s, void *v)
struct list_head *list = v;
struct smack_known *skp =
list_entry(list, struct smack_known, list);
- struct smack_cipso *scp = skp->smk_cipso;
- char *cbp;
+ struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
char sep = '/';
- int cat = 1;
int i;
- unsigned char m;
- if (scp == NULL)
+ /*
+ * Don't show a label that could not have been set using
+ * /smack/cipso. This is in support of the notion that
+ * anything read from /smack/cipso ought to be writeable
+ * to /smack/cipso.
+ *
+ * /smack/cipso2 should be used instead.
+ */
+ if (strlen(skp->smk_known) >= SMK_LABELLEN)
return 0;
- seq_printf(s, "%s %3d", (char *)&skp->smk_known, scp->smk_level);
+ seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
- cbp = scp->smk_catset;
- for (i = 0; i < SMK_LABELLEN; i++)
- for (m = 0x80; m != 0; m >>= 1) {
- if (m & cbp[i]) {
- seq_printf(s, "%c%d", sep, cat);
- sep = ',';
- }
- cat++;
- }
+ for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0;
+ i = netlbl_secattr_catmap_walk(cmp, i + 1)) {
+ seq_printf(s, "%c%d", sep, i);
+ sep = ',';
+ }
seq_putc(s, '\n');
@@ -653,23 +757,24 @@ static int smk_open_cipso(struct inode *inode, struct file *file)
}
/**
- * smk_write_cipso - write() for /smack/cipso
+ * smk_set_cipso - do the work for write() for cipso and cipso2
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start
+ * @format: /smack/cipso or /smack/cipso2
*
* Accepts only one cipso rule per write call.
* Returns number of bytes written or error code, as appropriate
*/
-static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos, int format)
{
struct smack_known *skp;
- struct smack_cipso *scp = NULL;
- char mapcatset[SMK_LABELLEN];
+ struct netlbl_lsm_secattr ncats;
+ char mapcatset[SMK_CIPSOLEN];
int maplevel;
- int cat;
+ unsigned int cat;
int catlen;
ssize_t rc = -EINVAL;
char *data = NULL;
@@ -686,7 +791,8 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
return -EPERM;
if (*ppos != 0)
return -EINVAL;
- if (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX)
+ if (format == SMK_FIXED24_FMT &&
+ (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX))
return -EINVAL;
data = kzalloc(count + 1, GFP_KERNEL);
@@ -698,11 +804,6 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
goto unlockedout;
}
- /* labels cannot begin with a '-' */
- if (data[0] == '-') {
- rc = -EINVAL;
- goto unlockedout;
- }
data[count] = '\0';
rule = data;
/*
@@ -715,7 +816,11 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
if (skp == NULL)
goto out;
- rule += SMK_LABELLEN;
+ if (format == SMK_FIXED24_FMT)
+ rule += SMK_LABELLEN;
+ else
+ rule += strlen(skp->smk_known);
+
ret = sscanf(rule, "%d", &maplevel);
if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL)
goto out;
@@ -725,41 +830,29 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM)
goto out;
- if (count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
+ if (format == SMK_FIXED24_FMT &&
+ count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
goto out;
memset(mapcatset, 0, sizeof(mapcatset));
for (i = 0; i < catlen; i++) {
rule += SMK_DIGITLEN;
- ret = sscanf(rule, "%d", &cat);
+ ret = sscanf(rule, "%u", &cat);
if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL)
goto out;
smack_catset_bit(cat, mapcatset);
}
- if (skp->smk_cipso == NULL) {
- scp = kzalloc(sizeof(struct smack_cipso), GFP_KERNEL);
- if (scp == NULL) {
- rc = -ENOMEM;
- goto out;
- }
+ rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN);
+ if (rc >= 0) {
+ netlbl_secattr_catmap_free(skp->smk_netlabel.attr.mls.cat);
+ skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat;
+ skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl;
+ rc = count;
}
- spin_lock_bh(&skp->smk_cipsolock);
-
- if (scp == NULL)
- scp = skp->smk_cipso;
- else
- skp->smk_cipso = scp;
-
- scp->smk_level = maplevel;
- memcpy(scp->smk_catset, mapcatset, sizeof(mapcatset));
-
- spin_unlock_bh(&skp->smk_cipsolock);
-
- rc = count;
out:
mutex_unlock(&smack_cipso_lock);
unlockedout:
@@ -767,6 +860,22 @@ unlockedout:
return rc;
}
+/**
+ * smk_write_cipso - write() for /smack/cipso
+ * @file: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start
+ *
+ * Accepts only one cipso rule per write call.
+ * Returns number of bytes written or error code, as appropriate
+ */
+static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return smk_set_cipso(file, buf, count, ppos, SMK_FIXED24_FMT);
+}
+
static const struct file_operations smk_cipso_ops = {
.open = smk_open_cipso,
.read = seq_read,
@@ -776,6 +885,80 @@ static const struct file_operations smk_cipso_ops = {
};
/*
+ * Seq_file read operations for /smack/cipso2
+ */
+
+/*
+ * Print cipso labels in format:
+ * label level[/cat[,cat]]
+ */
+static int cipso2_seq_show(struct seq_file *s, void *v)
+{
+ struct list_head *list = v;
+ struct smack_known *skp =
+ list_entry(list, struct smack_known, list);
+ struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
+ char sep = '/';
+ int i;
+
+ seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
+
+ for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0;
+ i = netlbl_secattr_catmap_walk(cmp, i + 1)) {
+ seq_printf(s, "%c%d", sep, i);
+ sep = ',';
+ }
+
+ seq_putc(s, '\n');
+
+ return 0;
+}
+
+static const struct seq_operations cipso2_seq_ops = {
+ .start = cipso_seq_start,
+ .next = cipso_seq_next,
+ .show = cipso2_seq_show,
+ .stop = smk_seq_stop,
+};
+
+/**
+ * smk_open_cipso2 - open() for /smack/cipso2
+ * @inode: inode structure representing file
+ * @file: "cipso2" file pointer
+ *
+ * Connect our cipso_seq_* operations with /smack/cipso2
+ * file_operations
+ */
+static int smk_open_cipso2(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &cipso2_seq_ops);
+}
+
+/**
+ * smk_write_cipso2 - write() for /smack/cipso2
+ * @file: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start
+ *
+ * Accepts only one cipso rule per write call.
+ * Returns number of bytes written or error code, as appropriate
+ */
+static ssize_t smk_write_cipso2(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return smk_set_cipso(file, buf, count, ppos, SMK_LONG_FMT);
+}
+
+static const struct file_operations smk_cipso2_ops = {
+ .open = smk_open_cipso2,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .write = smk_write_cipso2,
+ .release = seq_release,
+};
+
+/*
* Seq_file read operations for /smack/netlabel
*/
@@ -887,9 +1070,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
{
struct smk_netlbladdr *skp;
struct sockaddr_in newname;
- char smack[SMK_LABELLEN];
+ char *smack;
char *sp;
- char data[SMK_NETLBLADDRMAX + 1];
+ char *data;
char *host = (char *)&newname.sin_addr.s_addr;
int rc;
struct netlbl_audit audit_info;
@@ -911,10 +1094,23 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
return -EPERM;
if (*ppos != 0)
return -EINVAL;
- if (count < SMK_NETLBLADDRMIN || count > SMK_NETLBLADDRMAX)
+ if (count < SMK_NETLBLADDRMIN)
return -EINVAL;
- if (copy_from_user(data, buf, count) != 0)
- return -EFAULT;
+
+ data = kzalloc(count + 1, GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(data, buf, count) != 0) {
+ rc = -EFAULT;
+ goto free_data_out;
+ }
+
+ smack = kzalloc(count + 1, GFP_KERNEL);
+ if (smack == NULL) {
+ rc = -ENOMEM;
+ goto free_data_out;
+ }
data[count] = '\0';
@@ -923,24 +1119,34 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
if (rc != 6) {
rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
&host[0], &host[1], &host[2], &host[3], smack);
- if (rc != 5)
- return -EINVAL;
+ if (rc != 5) {
+ rc = -EINVAL;
+ goto free_out;
+ }
m = BEBITS;
}
- if (m > BEBITS)
- return -EINVAL;
+ if (m > BEBITS) {
+ rc = -EINVAL;
+ goto free_out;
+ }
- /* if smack begins with '-', its an option, don't import it */
+ /*
+ * If smack begins with '-', it is an option, don't import it
+ */
if (smack[0] != '-') {
sp = smk_import(smack, 0);
- if (sp == NULL)
- return -EINVAL;
+ if (sp == NULL) {
+ rc = -EINVAL;
+ goto free_out;
+ }
} else {
/* check known options */
if (strcmp(smack, smack_cipso_option) == 0)
sp = (char *)smack_cipso_option;
- else
- return -EINVAL;
+ else {
+ rc = -EINVAL;
+ goto free_out;
+ }
}
for (temp_mask = 0; m > 0; m--) {
@@ -1006,6 +1212,11 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
mutex_unlock(&smk_netlbladdr_lock);
+free_out:
+ kfree(smack);
+free_data_out:
+ kfree(data);
+
return rc;
}
@@ -1119,6 +1330,7 @@ static ssize_t smk_read_direct(struct file *filp, char __user *buf,
static ssize_t smk_write_direct(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
+ struct smack_known *skp;
char temp[80];
int i;
@@ -1136,7 +1348,20 @@ static ssize_t smk_write_direct(struct file *file, const char __user *buf,
if (sscanf(temp, "%d", &i) != 1)
return -EINVAL;
- smack_cipso_direct = i;
+ /*
+ * Don't do anything if the value hasn't actually changed.
+ * If it is changing reset the level on entries that were
+ * set up to be direct when they were created.
+ */
+ if (smack_cipso_direct != i) {
+ mutex_lock(&smack_known_lock);
+ list_for_each_entry_rcu(skp, &smack_known_list, list)
+ if (skp->smk_netlabel.attr.mls.lvl ==
+ smack_cipso_direct)
+ skp->smk_netlabel.attr.mls.lvl = i;
+ smack_cipso_direct = i;
+ mutex_unlock(&smack_known_lock);
+ }
return count;
}
@@ -1148,6 +1373,84 @@ static const struct file_operations smk_direct_ops = {
};
/**
+ * smk_read_mapped - read() for /smack/mapped
+ * @filp: file pointer, not actually used
+ * @buf: where to put the result
+ * @count: maximum to send along
+ * @ppos: where to start
+ *
+ * Returns number of bytes read or error code, as appropriate
+ */
+static ssize_t smk_read_mapped(struct file *filp, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char temp[80];
+ ssize_t rc;
+
+ if (*ppos != 0)
+ return 0;
+
+ sprintf(temp, "%d", smack_cipso_mapped);
+ rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
+
+ return rc;
+}
+
+/**
+ * smk_write_mapped - write() for /smack/mapped
+ * @file: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start
+ *
+ * Returns number of bytes written or error code, as appropriate
+ */
+static ssize_t smk_write_mapped(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct smack_known *skp;
+ char temp[80];
+ int i;
+
+ if (!capable(CAP_MAC_ADMIN))
+ return -EPERM;
+
+ if (count >= sizeof(temp) || count == 0)
+ return -EINVAL;
+
+ if (copy_from_user(temp, buf, count) != 0)
+ return -EFAULT;
+
+ temp[count] = '\0';
+
+ if (sscanf(temp, "%d", &i) != 1)
+ return -EINVAL;
+
+ /*
+ * Don't do anything if the value hasn't actually changed.
+ * If it is changing reset the level on entries that were
+ * set up to be mapped when they were created.
+ */
+ if (smack_cipso_mapped != i) {
+ mutex_lock(&smack_known_lock);
+ list_for_each_entry_rcu(skp, &smack_known_list, list)
+ if (skp->smk_netlabel.attr.mls.lvl ==
+ smack_cipso_mapped)
+ skp->smk_netlabel.attr.mls.lvl = i;
+ smack_cipso_mapped = i;
+ mutex_unlock(&smack_known_lock);
+ }
+
+ return count;
+}
+
+static const struct file_operations smk_mapped_ops = {
+ .read = smk_read_mapped,
+ .write = smk_write_mapped,
+ .llseek = default_llseek,
+};
+
+/**
* smk_read_ambient - read() for /smack/ambient
* @filp: file pointer, not actually used
* @buf: where to put the result
@@ -1195,22 +1498,28 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- char in[SMK_LABELLEN];
char *oldambient;
- char *smack;
+ char *smack = NULL;
+ char *data;
+ int rc = count;
if (!capable(CAP_MAC_ADMIN))
return -EPERM;
- if (count >= SMK_LABELLEN)
- return -EINVAL;
+ data = kzalloc(count + 1, GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
- if (copy_from_user(in, buf, count) != 0)
- return -EFAULT;
+ if (copy_from_user(data, buf, count) != 0) {
+ rc = -EFAULT;
+ goto out;
+ }
- smack = smk_import(in, count);
- if (smack == NULL)
- return -EINVAL;
+ smack = smk_import(data, count);
+ if (smack == NULL) {
+ rc = -EINVAL;
+ goto out;
+ }
mutex_lock(&smack_ambient_lock);
@@ -1220,7 +1529,9 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
mutex_unlock(&smack_ambient_lock);
- return count;
+out:
+ kfree(data);
+ return rc;
}
static const struct file_operations smk_ambient_ops = {
@@ -1271,8 +1582,9 @@ static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- char in[SMK_LABELLEN];
+ char *data;
char *sp = smk_of_task(current->cred->security);
+ int rc = count;
if (!capable(CAP_MAC_ADMIN))
return -EPERM;
@@ -1285,11 +1597,9 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
if (smack_onlycap != NULL && smack_onlycap != sp)
return -EPERM;
- if (count >= SMK_LABELLEN)
- return -EINVAL;
-
- if (copy_from_user(in, buf, count) != 0)
- return -EFAULT;
+ data = kzalloc(count, GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
/*
* Should the null string be passed in unset the onlycap value.
@@ -1297,10 +1607,17 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
* smk_import only expects to return NULL for errors. It
* is usually the case that a nullstring or "\n" would be
* bad to pass to smk_import but in fact this is useful here.
+ *
+ * smk_import will also reject a label beginning with '-',
+ * so "-usecapabilities" will also work.
*/
- smack_onlycap = smk_import(in, count);
+ if (copy_from_user(data, buf, count) != 0)
+ rc = -EFAULT;
+ else
+ smack_onlycap = smk_import(data, count);
- return count;
+ kfree(data);
+ return rc;
}
static const struct file_operations smk_onlycap_ops = {
@@ -1398,25 +1715,7 @@ static int load_self_seq_show(struct seq_file *s, void *v)
struct smack_rule *srp =
list_entry(list, struct smack_rule, list);
- seq_printf(s, "%s %s", (char *)srp->smk_subject,
- (char *)srp->smk_object);
-
- seq_putc(s, ' ');
-
- if (srp->smk_access & MAY_READ)
- seq_putc(s, 'r');
- if (srp->smk_access & MAY_WRITE)
- seq_putc(s, 'w');
- if (srp->smk_access & MAY_EXEC)
- seq_putc(s, 'x');
- if (srp->smk_access & MAY_APPEND)
- seq_putc(s, 'a');
- if (srp->smk_access & MAY_TRANSMUTE)
- seq_putc(s, 't');
- if (srp->smk_access == 0)
- seq_putc(s, '-');
-
- seq_putc(s, '\n');
+ smk_rule_show(s, srp, SMK_LABELLEN);
return 0;
}
@@ -1430,7 +1729,7 @@ static const struct seq_operations load_self_seq_ops = {
/**
- * smk_open_load_self - open() for /smack/load-self
+ * smk_open_load_self - open() for /smack/load-self2
* @inode: inode structure representing file
* @file: "load" file pointer
*
@@ -1454,8 +1753,8 @@ static ssize_t smk_write_load_self(struct file *file, const char __user *buf,
{
struct task_smack *tsp = current_security();
- return smk_write_load_list(file, buf, count, ppos, &tsp->smk_rules,
- &tsp->smk_rules_lock);
+ return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
+ &tsp->smk_rules_lock, SMK_FIXED24_FMT);
}
static const struct file_operations smk_load_self_ops = {
@@ -1467,24 +1766,42 @@ static const struct file_operations smk_load_self_ops = {
};
/**
- * smk_write_access - handle access check transaction
+ * smk_user_access - handle access check transaction
* @file: file pointer
* @buf: data from user space
* @count: bytes sent
* @ppos: where to start - must be 0
*/
-static ssize_t smk_write_access(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t smk_user_access(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos, int format)
{
struct smack_rule rule;
char *data;
+ char *cod;
int res;
data = simple_transaction_get(file, buf, count);
if (IS_ERR(data))
return PTR_ERR(data);
- if (count < SMK_LOADLEN || smk_parse_rule(data, &rule, 0))
+ if (format == SMK_FIXED24_FMT) {
+ if (count < SMK_LOADLEN)
+ return -EINVAL;
+ res = smk_parse_rule(data, &rule, 0);
+ } else {
+ /*
+ * Copy the data to make sure the string is terminated.
+ */
+ cod = kzalloc(count + 1, GFP_KERNEL);
+ if (cod == NULL)
+ return -ENOMEM;
+ memcpy(cod, data, count);
+ cod[count] = '\0';
+ res = smk_parse_long_rule(cod, &rule, 0);
+ kfree(cod);
+ }
+
+ if (res)
return -EINVAL;
res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access,
@@ -1493,7 +1810,23 @@ static ssize_t smk_write_access(struct file *file, const char __user *buf,
data[1] = '\0';
simple_transaction_set(file, 2);
- return SMK_LOADLEN;
+
+ if (format == SMK_FIXED24_FMT)
+ return SMK_LOADLEN;
+ return count;
+}
+
+/**
+ * smk_write_access - handle access check transaction
+ * @file: file pointer
+ * @buf: data from user space
+ * @count: bytes sent
+ * @ppos: where to start - must be 0
+ */
+static ssize_t smk_write_access(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return smk_user_access(file, buf, count, ppos, SMK_FIXED24_FMT);
}
static const struct file_operations smk_access_ops = {
@@ -1503,6 +1836,163 @@ static const struct file_operations smk_access_ops = {
.llseek = generic_file_llseek,
};
+
+/*
+ * Seq_file read operations for /smack/load2
+ */
+
+static int load2_seq_show(struct seq_file *s, void *v)
+{
+ struct list_head *list = v;
+ struct smack_master_list *smlp =
+ list_entry(list, struct smack_master_list, list);
+
+ smk_rule_show(s, smlp->smk_rule, SMK_LONGLABEL);
+
+ return 0;
+}
+
+static const struct seq_operations load2_seq_ops = {
+ .start = load2_seq_start,
+ .next = load2_seq_next,
+ .show = load2_seq_show,
+ .stop = smk_seq_stop,
+};
+
+/**
+ * smk_open_load2 - open() for /smack/load2
+ * @inode: inode structure representing file
+ * @file: "load2" file pointer
+ *
+ * For reading, use load2_seq_* seq_file reading operations.
+ */
+static int smk_open_load2(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &load2_seq_ops);
+}
+
+/**
+ * smk_write_load2 - write() for /smack/load2
+ * @file: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start - must be 0
+ *
+ */
+static ssize_t smk_write_load2(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ /*
+ * Must have privilege.
+ */
+ if (!capable(CAP_MAC_ADMIN))
+ return -EPERM;
+
+ return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
+ SMK_LONG_FMT);
+}
+
+static const struct file_operations smk_load2_ops = {
+ .open = smk_open_load2,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .write = smk_write_load2,
+ .release = seq_release,
+};
+
+/*
+ * Seq_file read operations for /smack/load-self2
+ */
+
+static void *load_self2_seq_start(struct seq_file *s, loff_t *pos)
+{
+ struct task_smack *tsp = current_security();
+
+ return smk_seq_start(s, pos, &tsp->smk_rules);
+}
+
+static void *load_self2_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ struct task_smack *tsp = current_security();
+
+ return smk_seq_next(s, v, pos, &tsp->smk_rules);
+}
+
+static int load_self2_seq_show(struct seq_file *s, void *v)
+{
+ struct list_head *list = v;
+ struct smack_rule *srp =
+ list_entry(list, struct smack_rule, list);
+
+ smk_rule_show(s, srp, SMK_LONGLABEL);
+
+ return 0;
+}
+
+static const struct seq_operations load_self2_seq_ops = {
+ .start = load_self2_seq_start,
+ .next = load_self2_seq_next,
+ .show = load_self2_seq_show,
+ .stop = smk_seq_stop,
+};
+
+/**
+ * smk_open_load_self2 - open() for /smack/load-self2
+ * @inode: inode structure representing file
+ * @file: "load" file pointer
+ *
+ * For reading, use load_seq_* seq_file reading operations.
+ */
+static int smk_open_load_self2(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &load_self2_seq_ops);
+}
+
+/**
+ * smk_write_load_self2 - write() for /smack/load-self2
+ * @file: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start - must be 0
+ *
+ */
+static ssize_t smk_write_load_self2(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct task_smack *tsp = current_security();
+
+ return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
+ &tsp->smk_rules_lock, SMK_LONG_FMT);
+}
+
+static const struct file_operations smk_load_self2_ops = {
+ .open = smk_open_load_self2,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .write = smk_write_load_self2,
+ .release = seq_release,
+};
+
+/**
+ * smk_write_access2 - handle access check transaction
+ * @file: file pointer
+ * @buf: data from user space
+ * @count: bytes sent
+ * @ppos: where to start - must be 0
+ */
+static ssize_t smk_write_access2(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return smk_user_access(file, buf, count, ppos, SMK_LONG_FMT);
+}
+
+static const struct file_operations smk_access2_ops = {
+ .write = smk_write_access2,
+ .read = simple_transaction_read,
+ .release = simple_transaction_release,
+ .llseek = generic_file_llseek,
+};
+
/**
* smk_fill_super - fill the /smackfs superblock
* @sb: the empty superblock
@@ -1539,6 +2029,16 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
"load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
[SMK_ACCESSES] = {
"access", &smk_access_ops, S_IRUGO|S_IWUGO},
+ [SMK_MAPPED] = {
+ "mapped", &smk_mapped_ops, S_IRUGO|S_IWUSR},
+ [SMK_LOAD2] = {
+ "load2", &smk_load2_ops, S_IRUGO|S_IWUSR},
+ [SMK_LOAD_SELF2] = {
+ "load-self2", &smk_load_self2_ops, S_IRUGO|S_IWUGO},
+ [SMK_ACCESS2] = {
+ "access2", &smk_access2_ops, S_IRUGO|S_IWUGO},
+ [SMK_CIPSO2] = {
+ "cipso2", &smk_cipso2_ops, S_IRUGO|S_IWUSR},
/* last one */
{""}
};
@@ -1581,6 +2081,15 @@ static struct file_system_type smk_fs_type = {
static struct vfsmount *smackfs_mount;
+static int __init smk_preset_netlabel(struct smack_known *skp)
+{
+ skp->smk_netlabel.domain = skp->smk_known;
+ skp->smk_netlabel.flags =
+ NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
+ return smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
+ &skp->smk_netlabel, strlen(skp->smk_known));
+}
+
/**
* init_smk_fs - get the smackfs superblock
*
@@ -1597,6 +2106,7 @@ static struct vfsmount *smackfs_mount;
static int __init init_smk_fs(void)
{
int err;
+ int rc;
if (!security_module_enable(&smack_ops))
return 0;
@@ -1614,6 +2124,25 @@ static int __init init_smk_fs(void)
smk_cipso_doi();
smk_unlbl_ambient(NULL);
+ rc = smk_preset_netlabel(&smack_known_floor);
+ if (err == 0 && rc < 0)
+ err = rc;
+ rc = smk_preset_netlabel(&smack_known_hat);
+ if (err == 0 && rc < 0)
+ err = rc;
+ rc = smk_preset_netlabel(&smack_known_huh);
+ if (err == 0 && rc < 0)
+ err = rc;
+ rc = smk_preset_netlabel(&smack_known_invalid);
+ if (err == 0 && rc < 0)
+ err = rc;
+ rc = smk_preset_netlabel(&smack_known_star);
+ if (err == 0 && rc < 0)
+ err = rc;
+ rc = smk_preset_netlabel(&smack_known_web);
+ if (err == 0 && rc < 0)
+ err = rc;
+
return err;
}
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 8656b16eef7b..2e0f12c62938 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -850,14 +850,9 @@ static int tomoyo_update_manager_entry(const char *manager,
policy_list[TOMOYO_ID_MANAGER],
};
int error = is_delete ? -ENOENT : -ENOMEM;
- if (tomoyo_domain_def(manager)) {
- if (!tomoyo_correct_domain(manager))
- return -EINVAL;
- e.is_domain = true;
- } else {
- if (!tomoyo_correct_path(manager))
- return -EINVAL;
- }
+ if (!tomoyo_correct_domain(manager) &&
+ !tomoyo_correct_word(manager))
+ return -EINVAL;
e.manager = tomoyo_get_name(manager);
if (e.manager) {
error = tomoyo_update_policy(&e.head, sizeof(e), &param,
@@ -932,23 +927,14 @@ static bool tomoyo_manager(void)
return true;
if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid))
return false;
- list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace.
- policy_list[TOMOYO_ID_MANAGER], head.list) {
- if (!ptr->head.is_deleted && ptr->is_domain
- && !tomoyo_pathcmp(domainname, ptr->manager)) {
- found = true;
- break;
- }
- }
- if (found)
- return true;
exe = tomoyo_get_exe();
if (!exe)
return false;
list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace.
policy_list[TOMOYO_ID_MANAGER], head.list) {
- if (!ptr->head.is_deleted && !ptr->is_domain
- && !strcmp(exe, ptr->manager->name)) {
+ if (!ptr->head.is_deleted &&
+ (!tomoyo_pathcmp(domainname, ptr->manager) ||
+ !strcmp(exe, ptr->manager->name))) {
found = true;
break;
}
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 30fd98369700..75e4dc1c02a0 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -860,7 +860,6 @@ struct tomoyo_aggregator {
/* Structure for policy manager. */
struct tomoyo_manager {
struct tomoyo_acl_head head;
- bool is_domain; /* True if manager is a domainname. */
/* A path to program or a domainname. */
const struct tomoyo_path_info *manager;
};
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 620d37c159a3..c2d04a50f76a 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -319,14 +319,14 @@ static int tomoyo_file_fcntl(struct file *file, unsigned int cmd,
}
/**
- * tomoyo_dentry_open - Target for security_dentry_open().
+ * tomoyo_file_open - Target for security_file_open().
*
* @f: Pointer to "struct file".
* @cred: Pointer to "struct cred".
*
* Returns 0 on success, negative value otherwise.
*/
-static int tomoyo_dentry_open(struct file *f, const struct cred *cred)
+static int tomoyo_file_open(struct file *f, const struct cred *cred)
{
int flags = f->f_flags;
/* Don't check read permission here if called from do_execve(). */
@@ -510,7 +510,7 @@ static struct security_operations tomoyo_security_ops = {
.bprm_set_creds = tomoyo_bprm_set_creds,
.bprm_check_security = tomoyo_bprm_check_security,
.file_fcntl = tomoyo_file_fcntl,
- .dentry_open = tomoyo_dentry_open,
+ .file_open = tomoyo_file_open,
.path_truncate = tomoyo_path_truncate,
.path_unlink = tomoyo_path_unlink,
.path_mkdir = tomoyo_path_mkdir,
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index 573723843a04..83554ee8a587 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -18,7 +18,12 @@
#include <linux/prctl.h>
#include <linux/ratelimit.h>
-static int ptrace_scope = 1;
+#define YAMA_SCOPE_DISABLED 0
+#define YAMA_SCOPE_RELATIONAL 1
+#define YAMA_SCOPE_CAPABILITY 2
+#define YAMA_SCOPE_NO_ATTACH 3
+
+static int ptrace_scope = YAMA_SCOPE_RELATIONAL;
/* describe a ptrace relationship for potential exception */
struct ptrace_relation {
@@ -251,17 +256,32 @@ static int yama_ptrace_access_check(struct task_struct *child,
return rc;
/* require ptrace target be a child of ptracer on attach */
- if (mode == PTRACE_MODE_ATTACH &&
- ptrace_scope &&
- !task_is_descendant(current, child) &&
- !ptracer_exception_found(current, child) &&
- !capable(CAP_SYS_PTRACE))
- rc = -EPERM;
+ if (mode == PTRACE_MODE_ATTACH) {
+ switch (ptrace_scope) {
+ case YAMA_SCOPE_DISABLED:
+ /* No additional restrictions. */
+ break;
+ case YAMA_SCOPE_RELATIONAL:
+ if (!task_is_descendant(current, child) &&
+ !ptracer_exception_found(current, child) &&
+ !ns_capable(task_user_ns(child), CAP_SYS_PTRACE))
+ rc = -EPERM;
+ break;
+ case YAMA_SCOPE_CAPABILITY:
+ if (!ns_capable(task_user_ns(child), CAP_SYS_PTRACE))
+ rc = -EPERM;
+ break;
+ case YAMA_SCOPE_NO_ATTACH:
+ default:
+ rc = -EPERM;
+ break;
+ }
+ }
if (rc) {
char name[sizeof(current->comm)];
- printk_ratelimited(KERN_NOTICE "ptrace of non-child"
- " pid %d was attempted by: %s (pid %d)\n",
+ printk_ratelimited(KERN_NOTICE
+ "ptrace of pid %d was attempted by: %s (pid %d)\n",
child->pid,
get_task_comm(name, current),
current->pid);
@@ -279,8 +299,27 @@ static struct security_operations yama_ops = {
};
#ifdef CONFIG_SYSCTL
+static int yama_dointvec_minmax(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ int rc;
+
+ if (write && !capable(CAP_SYS_PTRACE))
+ return -EPERM;
+
+ rc = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+ if (rc)
+ return rc;
+
+ /* Lock the max value if it ever gets set. */
+ if (write && *(int *)table->data == *(int *)table->extra2)
+ table->extra1 = table->extra2;
+
+ return rc;
+}
+
static int zero;
-static int one = 1;
+static int max_scope = YAMA_SCOPE_NO_ATTACH;
struct ctl_path yama_sysctl_path[] = {
{ .procname = "kernel", },
@@ -294,9 +333,9 @@ static struct ctl_table yama_sysctl_table[] = {
.data = &ptrace_scope,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dointvec_minmax,
+ .proc_handler = yama_dointvec_minmax,
.extra1 = &zero,
- .extra2 = &one,
+ .extra2 = &max_scope,
},
{ }
};
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index 115313ef54d6..f5ded640b395 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -991,6 +991,8 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
gpio_direction_output(pdata->reset_pin, 1);
chip->reset_pin = pdata->reset_pin;
}
+ } else {
+ chip->reset_pin = -EINVAL;
}
snd_card_set_dev(card, &pdev->dev);
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 471e1e3b0a99..a06b1651fcba 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -155,7 +155,7 @@ EXPORT_SYMBOL(snd_jack_new);
* @jack: The jack to configure
* @parent: The device to set as parent for the jack.
*
- * Set the parent for the jack input device in the device tree. This
+ * Set the parent for the jack devices in the device tree. This
* function is only valid prior to registration of the jack. If no
* parent is configured then the parent device will be the sound card.
*/
@@ -179,6 +179,9 @@ EXPORT_SYMBOL(snd_jack_set_parent);
* mapping is provided but keys are enabled in the jack type then
* BTN_n numeric buttons will be reported.
*
+ * If jacks are not reporting via the input API this call will have no
+ * effect.
+ *
* Note that this is intended to be use by simple devices with small
* numbers of keys that can be reported. It is also possible to
* access the input device directly - devices with complex input
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 4d18941178e6..faedb1481b24 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1894,6 +1894,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t xfer = 0;
snd_pcm_uframes_t offset = 0;
+ snd_pcm_uframes_t avail;
int err = 0;
if (size == 0)
@@ -1917,13 +1918,12 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
}
runtime->twake = runtime->control->avail_min ? : 1;
+ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+ snd_pcm_update_hw_ptr(substream);
+ avail = snd_pcm_playback_avail(runtime);
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
- snd_pcm_uframes_t avail;
snd_pcm_uframes_t cont;
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
- snd_pcm_update_hw_ptr(substream);
- avail = snd_pcm_playback_avail(runtime);
if (!avail) {
if (nonblock) {
err = -EAGAIN;
@@ -1971,6 +1971,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
offset += frames;
size -= frames;
xfer += frames;
+ avail -= frames;
if (runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) {
err = snd_pcm_start(substream);
@@ -2111,6 +2112,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t xfer = 0;
snd_pcm_uframes_t offset = 0;
+ snd_pcm_uframes_t avail;
int err = 0;
if (size == 0)
@@ -2141,13 +2143,12 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
}
runtime->twake = runtime->control->avail_min ? : 1;
+ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+ snd_pcm_update_hw_ptr(substream);
+ avail = snd_pcm_capture_avail(runtime);
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
- snd_pcm_uframes_t avail;
snd_pcm_uframes_t cont;
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
- snd_pcm_update_hw_ptr(substream);
- avail = snd_pcm_capture_avail(runtime);
if (!avail) {
if (runtime->status->state ==
SNDRV_PCM_STATE_DRAINING) {
@@ -2202,6 +2203,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
offset += frames;
size -= frames;
xfer += frames;
+ avail -= frames;
}
_end_unlock:
runtime->twake = 0;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 3fe99e644eb8..53b5ada8f7c3 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1360,7 +1360,14 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
{
- substream->runtime->trigger_master = substream;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ switch (runtime->status->state) {
+ case SNDRV_PCM_STATE_OPEN:
+ case SNDRV_PCM_STATE_DISCONNECTED:
+ case SNDRV_PCM_STATE_SUSPENDED:
+ return -EBADFD;
+ }
+ runtime->trigger_master = substream;
return 0;
}
@@ -1379,6 +1386,9 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
case SNDRV_PCM_STATE_RUNNING:
runtime->status->state = SNDRV_PCM_STATE_DRAINING;
break;
+ case SNDRV_PCM_STATE_XRUN:
+ runtime->status->state = SNDRV_PCM_STATE_SETUP;
+ break;
default:
break;
}
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index c70092043061..e9528333e36d 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -35,7 +35,7 @@
#include <linux/sound.h>
#include <linux/mutex.h>
-#define SNDRV_OSS_MINORS 128
+#define SNDRV_OSS_MINORS 256
static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
static DEFINE_MUTEX(sound_oss_mutex);
@@ -111,7 +111,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
int register1 = -1, register2 = -1;
struct device *carddev = snd_card_get_device_link(card);
- if (card && card->number >= 8)
+ if (card && card->number >= SNDRV_MINOR_OSS_DEVICES)
return 0; /* ignore silently */
if (minor < 0)
return minor;
@@ -170,7 +170,7 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
int track2 = -1;
struct snd_minor *mptr;
- if (card && card->number >= 8)
+ if (card && card->number >= SNDRV_MINOR_OSS_DEVICES)
return 0;
if (minor < 0)
return minor;
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index ad079b63b8ba..8b5c36f4d303 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -117,6 +117,7 @@ struct loopback_pcm {
/* timer stuff */
unsigned int irq_pos; /* fractional IRQ position */
unsigned int period_size_frac;
+ unsigned int last_drift;
unsigned long last_jiffies;
struct timer_list timer;
};
@@ -264,6 +265,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
return err;
dpcm->last_jiffies = jiffies;
dpcm->pcm_rate_shift = 0;
+ dpcm->last_drift = 0;
spin_lock(&cable->lock);
cable->running |= stream;
cable->pause &= ~stream;
@@ -444,34 +446,30 @@ static void copy_play_buf(struct loopback_pcm *play,
}
}
-#define BYTEPOS_UPDATE_POSONLY 0
-#define BYTEPOS_UPDATE_CLEAR 1
-#define BYTEPOS_UPDATE_COPY 2
-
-static void loopback_bytepos_update(struct loopback_pcm *dpcm,
- unsigned int delta,
- unsigned int cmd)
+static inline unsigned int bytepos_delta(struct loopback_pcm *dpcm,
+ unsigned int jiffies_delta)
{
- unsigned int count;
unsigned long last_pos;
+ unsigned int delta;
last_pos = byte_pos(dpcm, dpcm->irq_pos);
- dpcm->irq_pos += delta * dpcm->pcm_bps;
- count = byte_pos(dpcm, dpcm->irq_pos) - last_pos;
- if (!count)
- return;
- if (cmd == BYTEPOS_UPDATE_CLEAR)
- clear_capture_buf(dpcm, count);
- else if (cmd == BYTEPOS_UPDATE_COPY)
- copy_play_buf(dpcm->cable->streams[SNDRV_PCM_STREAM_PLAYBACK],
- dpcm->cable->streams[SNDRV_PCM_STREAM_CAPTURE],
- count);
- dpcm->buf_pos += count;
- dpcm->buf_pos %= dpcm->pcm_buffer_size;
+ dpcm->irq_pos += jiffies_delta * dpcm->pcm_bps;
+ delta = byte_pos(dpcm, dpcm->irq_pos) - last_pos;
+ if (delta >= dpcm->last_drift)
+ delta -= dpcm->last_drift;
+ dpcm->last_drift = 0;
if (dpcm->irq_pos >= dpcm->period_size_frac) {
dpcm->irq_pos %= dpcm->period_size_frac;
dpcm->period_update_pending = 1;
}
+ return delta;
+}
+
+static inline void bytepos_finish(struct loopback_pcm *dpcm,
+ unsigned int delta)
+{
+ dpcm->buf_pos += delta;
+ dpcm->buf_pos %= dpcm->pcm_buffer_size;
}
static unsigned int loopback_pos_update(struct loopback_cable *cable)
@@ -481,7 +479,7 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
struct loopback_pcm *dpcm_capt =
cable->streams[SNDRV_PCM_STREAM_CAPTURE];
unsigned long delta_play = 0, delta_capt = 0;
- unsigned int running;
+ unsigned int running, count1, count2;
unsigned long flags;
spin_lock_irqsave(&cable->lock, flags);
@@ -500,12 +498,13 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
goto unlock;
if (delta_play > delta_capt) {
- loopback_bytepos_update(dpcm_play, delta_play - delta_capt,
- BYTEPOS_UPDATE_POSONLY);
+ count1 = bytepos_delta(dpcm_play, delta_play - delta_capt);
+ bytepos_finish(dpcm_play, count1);
delta_play = delta_capt;
} else if (delta_play < delta_capt) {
- loopback_bytepos_update(dpcm_capt, delta_capt - delta_play,
- BYTEPOS_UPDATE_CLEAR);
+ count1 = bytepos_delta(dpcm_capt, delta_capt - delta_play);
+ clear_capture_buf(dpcm_capt, count1);
+ bytepos_finish(dpcm_capt, count1);
delta_capt = delta_play;
}
@@ -513,8 +512,17 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
goto unlock;
/* note delta_capt == delta_play at this moment */
- loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY);
- loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY);
+ count1 = bytepos_delta(dpcm_play, delta_play);
+ count2 = bytepos_delta(dpcm_capt, delta_capt);
+ if (count1 < count2) {
+ dpcm_capt->last_drift = count2 - count1;
+ count1 = count2;
+ } else if (count1 > count2) {
+ dpcm_play->last_drift = count1 - count2;
+ }
+ copy_play_buf(dpcm_play, dpcm_capt, count1);
+ bytepos_finish(dpcm_play, count1);
+ bytepos_finish(dpcm_capt, count1);
unlock:
spin_unlock_irqrestore(&cable->lock, flags);
return running;
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index 87657dd7714c..ea995af6d049 100644
--- a/sound/firewire/amdtp.c
+++ b/sound/firewire/amdtp.c
@@ -31,6 +31,8 @@
#define INTERRUPT_INTERVAL 16
#define QUEUE_LENGTH 48
+static void pcm_period_tasklet(unsigned long data);
+
/**
* amdtp_out_stream_init - initialize an AMDTP output stream structure
* @s: the AMDTP output stream to initialize
@@ -47,6 +49,7 @@ int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit,
s->flags = flags;
s->context = ERR_PTR(-1);
mutex_init(&s->mutex);
+ tasklet_init(&s->period_tasklet, pcm_period_tasklet, (unsigned long)s);
s->packet_index = 0;
return 0;
@@ -164,6 +167,21 @@ void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
}
EXPORT_SYMBOL(amdtp_out_stream_set_pcm_format);
+/**
+ * amdtp_out_stream_pcm_prepare - prepare PCM device for running
+ * @s: the AMDTP output stream
+ *
+ * This function should be called from the PCM device's .prepare callback.
+ */
+void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s)
+{
+ tasklet_kill(&s->period_tasklet);
+ s->pcm_buffer_pointer = 0;
+ s->pcm_period_pointer = 0;
+ s->pointer_flush = true;
+}
+EXPORT_SYMBOL(amdtp_out_stream_pcm_prepare);
+
static unsigned int calculate_data_blocks(struct amdtp_out_stream *s)
{
unsigned int phase, data_blocks;
@@ -376,11 +394,21 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
s->pcm_period_pointer += data_blocks;
if (s->pcm_period_pointer >= pcm->runtime->period_size) {
s->pcm_period_pointer -= pcm->runtime->period_size;
- snd_pcm_period_elapsed(pcm);
+ s->pointer_flush = false;
+ tasklet_hi_schedule(&s->period_tasklet);
}
}
}
+static void pcm_period_tasklet(unsigned long data)
+{
+ struct amdtp_out_stream *s = (void *)data;
+ struct snd_pcm_substream *pcm = ACCESS_ONCE(s->pcm);
+
+ if (pcm)
+ snd_pcm_period_elapsed(pcm);
+}
+
static void out_packet_callback(struct fw_iso_context *context, u32 cycle,
size_t header_length, void *header, void *data)
{
@@ -506,6 +534,24 @@ err_unlock:
EXPORT_SYMBOL(amdtp_out_stream_start);
/**
+ * amdtp_out_stream_pcm_pointer - get the PCM buffer position
+ * @s: the AMDTP output stream that transports the PCM data
+ *
+ * Returns the current buffer position, in frames.
+ */
+unsigned long amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s)
+{
+ /* this optimization is allowed to be racy */
+ if (s->pointer_flush)
+ fw_iso_context_flush_completions(s->context);
+ else
+ s->pointer_flush = true;
+
+ return ACCESS_ONCE(s->pcm_buffer_pointer);
+}
+EXPORT_SYMBOL(amdtp_out_stream_pcm_pointer);
+
+/**
* amdtp_out_stream_update - update the stream after a bus reset
* @s: the AMDTP output stream
*/
@@ -532,6 +578,7 @@ void amdtp_out_stream_stop(struct amdtp_out_stream *s)
return;
}
+ tasklet_kill(&s->period_tasklet);
fw_iso_context_stop(s->context);
fw_iso_context_destroy(s->context);
s->context = ERR_PTR(-1);
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h
index 537a9cb83581..b680c5ef01d6 100644
--- a/sound/firewire/amdtp.h
+++ b/sound/firewire/amdtp.h
@@ -1,6 +1,7 @@
#ifndef SOUND_FIREWIRE_AMDTP_H_INCLUDED
#define SOUND_FIREWIRE_AMDTP_H_INCLUDED
+#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include "packets-buffer.h"
@@ -55,6 +56,7 @@ struct amdtp_out_stream {
struct iso_packets_buffer buffer;
struct snd_pcm_substream *pcm;
+ struct tasklet_struct period_tasklet;
int packet_index;
unsigned int data_block_counter;
@@ -66,6 +68,7 @@ struct amdtp_out_stream {
unsigned int pcm_buffer_pointer;
unsigned int pcm_period_pointer;
+ bool pointer_flush;
};
int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit,
@@ -81,6 +84,8 @@ void amdtp_out_stream_stop(struct amdtp_out_stream *s);
void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
snd_pcm_format_t format);
+void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s);
+unsigned long amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s);
void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s);
/**
@@ -123,18 +128,6 @@ static inline bool amdtp_out_streaming_error(struct amdtp_out_stream *s)
}
/**
- * amdtp_out_stream_pcm_prepare - prepare PCM device for running
- * @s: the AMDTP output stream
- *
- * This function should be called from the PCM device's .prepare callback.
- */
-static inline void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s)
-{
- s->pcm_buffer_pointer = 0;
- s->pcm_period_pointer = 0;
-}
-
-/**
* amdtp_out_stream_pcm_trigger - start/stop playback from a PCM device
* @s: the AMDTP output stream
* @pcm: the PCM device to be started, or %NULL to stop the current device
@@ -149,18 +142,6 @@ static inline void amdtp_out_stream_pcm_trigger(struct amdtp_out_stream *s,
ACCESS_ONCE(s->pcm) = pcm;
}
-/**
- * amdtp_out_stream_pcm_pointer - get the PCM buffer position
- * @s: the AMDTP output stream that transports the PCM data
- *
- * Returns the current buffer position, in frames.
- */
-static inline unsigned long
-amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s)
-{
- return ACCESS_ONCE(s->pcm_buffer_pointer);
-}
-
static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc)
{
return sfc & 1;
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index d1f4351fb6ee..2d67c78c9f4b 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -7,7 +7,7 @@
Thanks to Pierfrancesco 'qM2' Passerini.
Generalised for soundcards based on DT-0196 and ALS-007 chips
- by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>: June 2002.
+ by Jonathan Woithe <jwoithe@just42.net>: June 2002.
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
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 5ca0939e4223..ff3af6e77d61 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -228,7 +228,7 @@ config SND_OXYGEN
Say Y here to include support for sound cards based on the
C-Media CMI8788 (Oxygen HD Audio) chip:
* Asound A-8788
- * Asus Xonar DG
+ * Asus Xonar DG/DGX
* AuzenTech X-Meridian
* AuzenTech X-Meridian 2G
* Bgears b-Enspirer
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 9d91d61902b4..e672ff4df2da 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -1062,17 +1062,4 @@ static struct pci_driver ad1889_pci_driver = {
.remove = __devexit_p(snd_ad1889_remove),
};
-static int __init
-alsa_ad1889_init(void)
-{
- return pci_register_driver(&ad1889_pci_driver);
-}
-
-static void __exit
-alsa_ad1889_fini(void)
-{
- pci_unregister_driver(&ad1889_pci_driver);
-}
-
-module_init(alsa_ad1889_init);
-module_exit(alsa_ad1889_fini);
+module_pci_driver(ad1889_pci_driver);
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index bdd6164e9c7e..9dfc27bf6cc6 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -2294,7 +2294,7 @@ static void __devexit snd_ali_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver ali5451_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ali_ids,
.probe = snd_ali_probe,
@@ -2305,15 +2305,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_ali_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_ali_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_ali_init)
-module_exit(alsa_card_ali_exit)
+module_pci_driver(ali5451_driver);
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 8196e229b2df..59d65388faf5 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -852,7 +852,7 @@ static int __devinit snd_als300_probe(struct pci_dev *pci,
return 0;
}
-static struct pci_driver driver = {
+static struct pci_driver als300_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_als300_ids,
.probe = snd_als300_probe,
@@ -863,15 +863,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_als300_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_als300_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_als300_init)
-module_exit(alsa_card_als300_exit)
+module_pci_driver(als300_driver);
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 3269b8011ea9..7d7f2598c748 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -1036,7 +1036,7 @@ static int snd_als4000_resume(struct pci_dev *pci)
#endif /* CONFIG_PM */
-static struct pci_driver driver = {
+static struct pci_driver als4000_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_als4000_ids,
.probe = snd_card_als4000_probe,
@@ -1047,15 +1047,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_als4000_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_als4000_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_als4000_init)
-module_exit(alsa_card_als4000_exit)
+module_pci_driver(als4000_driver);
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 590682f115ef..156a94f8a123 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1700,7 +1700,7 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver atiixp_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
@@ -1711,16 +1711,4 @@ static struct pci_driver driver = {
#endif
};
-
-static int __init alsa_card_atiixp_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_atiixp_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_atiixp_init)
-module_exit(alsa_card_atiixp_exit)
+module_pci_driver(atiixp_driver);
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 524d35f31232..30a4fd96ce73 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1331,7 +1331,7 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver atiixp_modem_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
@@ -1342,16 +1342,4 @@ static struct pci_driver driver = {
#endif
};
-
-static int __init alsa_card_atiixp_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_atiixp_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_atiixp_init)
-module_exit(alsa_card_atiixp_exit)
+module_pci_driver(atiixp_modem_driver);
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index f13ad536b2d5..ffc376f9f4e4 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -375,24 +375,11 @@ static void __devexit snd_vortex_remove(struct pci_dev *pci)
}
// pci_driver definition
-static struct pci_driver driver = {
+static struct pci_driver vortex_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_vortex_ids,
.probe = snd_vortex_probe,
.remove = __devexit_p(snd_vortex_remove),
};
-// initialization of the module
-static int __init alsa_card_vortex_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-// clean up the module
-static void __exit alsa_card_vortex_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_vortex_init)
-module_exit(alsa_card_vortex_exit)
+module_pci_driver(vortex_driver);
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index 1c5231931462..0f804741825f 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -112,8 +112,6 @@ struct aw2 {
/*********************************
* FUNCTION DECLARATIONS
********************************/
-static int __init alsa_card_aw2_init(void);
-static void __exit alsa_card_aw2_exit(void);
static int snd_aw2_dev_free(struct snd_device *device);
static int __devinit snd_aw2_create(struct snd_card *card,
struct pci_dev *pci, struct aw2 **rchip);
@@ -171,13 +169,15 @@ static DEFINE_PCI_DEVICE_TABLE(snd_aw2_ids) = {
MODULE_DEVICE_TABLE(pci, snd_aw2_ids);
/* pci_driver definition */
-static struct pci_driver driver = {
+static struct pci_driver aw2_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_aw2_ids,
.probe = snd_aw2_probe,
.remove = __devexit_p(snd_aw2_remove),
};
+module_pci_driver(aw2_driver);
+
/* operators for playback PCM alsa interface */
static struct snd_pcm_ops snd_aw2_playback_ops = {
.open = snd_aw2_pcm_playback_open,
@@ -217,23 +217,6 @@ static struct snd_kcontrol_new aw2_control __devinitdata = {
* FUNCTION IMPLEMENTATIONS
********************************/
-/* initialization of the module */
-static int __init alsa_card_aw2_init(void)
-{
- snd_printdd(KERN_DEBUG "aw2: Load aw2 module\n");
- return pci_register_driver(&driver);
-}
-
-/* clean up the module */
-static void __exit alsa_card_aw2_exit(void)
-{
- snd_printdd(KERN_DEBUG "aw2: Unload aw2 module\n");
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_aw2_init);
-module_exit(alsa_card_aw2_exit);
-
/* component-destructor */
static int snd_aw2_dev_free(struct snd_device *device)
{
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 496f14c1a731..f0b4d7493af5 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -2862,7 +2862,7 @@ snd_azf3328_resume(struct pci_dev *pci)
#endif /* CONFIG_PM */
-static struct pci_driver driver = {
+static struct pci_driver azf3328_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_azf3328_ids,
.probe = snd_azf3328_probe,
@@ -2873,23 +2873,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init
-alsa_card_azf3328_init(void)
-{
- int err;
- snd_azf3328_dbgcallenter();
- err = pci_register_driver(&driver);
- snd_azf3328_dbgcallleave();
- return err;
-}
-
-static void __exit
-alsa_card_azf3328_exit(void)
-{
- snd_azf3328_dbgcallenter();
- pci_unregister_driver(&driver);
- snd_azf3328_dbgcallleave();
-}
-
-module_init(alsa_card_azf3328_init)
-module_exit(alsa_card_azf3328_exit)
+module_pci_driver(azf3328_driver);
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 62d6163fc9d9..b6a95eeca095 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -836,8 +836,6 @@ static struct {
{0x7063, 0x2000}, /* pcHDTV HD-2000 TV */
};
-static struct pci_driver driver;
-
/* return the id of the card, or a negative value if it's blacklisted */
static int __devinit snd_bt87x_detect_card(struct pci_dev *pci)
{
@@ -964,24 +962,11 @@ static DEFINE_PCI_DEVICE_TABLE(snd_bt87x_default_ids) = {
{ }
};
-static struct pci_driver driver = {
+static struct pci_driver bt87x_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_bt87x_ids,
.probe = snd_bt87x_probe,
.remove = __devexit_p(snd_bt87x_remove),
};
-static int __init alsa_card_bt87x_init(void)
-{
- if (load_all)
- driver.id_table = snd_bt87x_default_ids;
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_bt87x_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_bt87x_init)
-module_exit(alsa_card_bt87x_exit)
+module_pci_driver(bt87x_driver);
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 08d6ebfe5a61..e76d68a7081f 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1932,7 +1932,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_ca0106_ids) = {
MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
// pci_driver definition
-static struct pci_driver driver = {
+static struct pci_driver ca0106_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ca0106_ids,
.probe = snd_ca0106_probe,
@@ -1943,17 +1943,4 @@ static struct pci_driver driver = {
#endif
};
-// initialization of the module
-static int __init alsa_card_ca0106_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-// clean up the module
-static void __exit alsa_card_ca0106_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_ca0106_init)
-module_exit(alsa_card_ca0106_exit)
+module_pci_driver(ca0106_driver);
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 19b06269adc2..3815bd4c6779 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -3398,7 +3398,7 @@ static int snd_cmipci_resume(struct pci_dev *pci)
}
#endif /* CONFIG_PM */
-static struct pci_driver driver = {
+static struct pci_driver cmipci_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cmipci_ids,
.probe = snd_cmipci_probe,
@@ -3409,15 +3409,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_cmipci_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_cmipci_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_cmipci_init)
-module_exit(alsa_card_cmipci_exit)
+module_pci_driver(cmipci_driver);
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index a9f368f60df6..33506ee569bd 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -2084,7 +2084,7 @@ static int cs4281_resume(struct pci_dev *pci)
}
#endif /* CONFIG_PM */
-static struct pci_driver driver = {
+static struct pci_driver cs4281_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs4281_ids,
.probe = snd_cs4281_probe,
@@ -2095,15 +2095,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_cs4281_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_cs4281_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_cs4281_init)
-module_exit(alsa_card_cs4281_exit)
+module_pci_driver(cs4281_driver);
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 819d79d0586d..6cc7404e0e8f 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -161,7 +161,7 @@ static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver cs46xx_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs46xx_ids,
.probe = snd_card_cs46xx_probe,
@@ -172,15 +172,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_cs46xx_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_cs46xx_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_cs46xx_init)
-module_exit(alsa_card_cs46xx_exit)
+module_pci_driver(cs46xx_driver);
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c
index c47cabff2bfa..f1e4229993af 100644
--- a/sound/pci/cs5530.c
+++ b/sound/pci/cs5530.c
@@ -291,23 +291,11 @@ static int __devinit snd_cs5530_probe(struct pci_dev *pci,
return 0;
}
-static struct pci_driver driver = {
+static struct pci_driver cs5530_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs5530_ids,
.probe = snd_cs5530_probe,
.remove = __devexit_p(snd_cs5530_remove),
};
-static int __init alsa_card_cs5530_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_cs5530_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_cs5530_init)
-module_exit(alsa_card_cs5530_exit)
-
+module_pci_driver(cs5530_driver);
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index a2fb2173e980..2c9697cf0a1a 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -394,7 +394,7 @@ static void __devexit snd_cs5535audio_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver cs5535audio_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs5535audio_ids,
.probe = snd_cs5535audio_probe,
@@ -405,18 +405,7 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_cs5535audio_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_cs5535audio_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_cs5535audio_init)
-module_exit(alsa_card_cs5535audio_exit)
+module_pci_driver(cs5535audio_driver);
MODULE_AUTHOR("Jaya Kumar");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c
index 15d95d2bacee..75aa2c338410 100644
--- a/sound/pci/ctxfi/xfi.c
+++ b/sound/pci/ctxfi/xfi.c
@@ -154,15 +154,4 @@ static struct pci_driver ct_driver = {
#endif
};
-static int __init ct_card_init(void)
-{
- return pci_register_driver(&ct_driver);
-}
-
-static void __exit ct_card_exit(void)
-{
- pci_unregister_driver(&ct_driver);
-}
-
-module_init(ct_card_init)
-module_exit(ct_card_exit)
+module_pci_driver(ct_driver);
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 595c11f904bb..0f8eda1dafdb 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -2328,7 +2328,7 @@ static void __devexit snd_echo_remove(struct pci_dev *pci)
******************************************************************************/
/* pci_driver definition */
-static struct pci_driver driver = {
+static struct pci_driver echo_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_echo_ids,
.probe = snd_echo_probe,
@@ -2339,22 +2339,4 @@ static struct pci_driver driver = {
#endif /* CONFIG_PM */
};
-
-
-/* initialization of the module */
-static int __init alsa_card_echo_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-
-
-/* clean up the module */
-static void __exit alsa_card_echo_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-
-module_init(alsa_card_echo_init)
-module_exit(alsa_card_echo_exit)
+module_pci_driver(echo_driver);
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 790c65d980c8..7fdbbe4d9965 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -263,7 +263,7 @@ static int snd_emu10k1_resume(struct pci_dev *pci)
}
#endif
-static struct pci_driver driver = {
+static struct pci_driver emu10k1_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_emu10k1_ids,
.probe = snd_card_emu10k1_probe,
@@ -274,15 +274,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_emu10k1_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_emu10k1_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_emu10k1_init)
-module_exit(alsa_card_emu10k1_exit)
+module_pci_driver(emu10k1_driver);
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 47a651cb6e84..5c8978b2c4d9 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -1612,24 +1612,11 @@ static DEFINE_PCI_DEVICE_TABLE(snd_emu10k1x_ids) = {
MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids);
// pci_driver definition
-static struct pci_driver driver = {
+static struct pci_driver emu10k1x_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_emu10k1x_ids,
.probe = snd_emu10k1x_probe,
.remove = __devexit_p(snd_emu10k1x_remove),
};
-// initialization of the module
-static int __init alsa_card_emu10k1x_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-// clean up the module
-static void __exit alsa_card_emu10k1x_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_emu10k1x_init)
-module_exit(alsa_card_emu10k1x_exit)
+module_pci_driver(emu10k1x_driver);
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 47a245e84190..3821c81d1c99 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -2488,7 +2488,7 @@ static void __devexit snd_audiopci_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver ens137x_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_audiopci_ids,
.probe = snd_audiopci_probe,
@@ -2499,15 +2499,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_ens137x_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_ens137x_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_ens137x_init)
-module_exit(alsa_card_ens137x_exit)
+module_pci_driver(ens137x_driver);
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 53eb76b41108..82c8d8c5c52a 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1882,7 +1882,7 @@ static void __devexit snd_es1938_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver es1938_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_es1938_ids,
.probe = snd_es1938_probe,
@@ -1893,15 +1893,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_es1938_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_es1938_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_es1938_init)
-module_exit(alsa_card_es1938_exit)
+module_pci_driver(es1938_driver);
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index a8faae1c85e4..67f47d891959 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -2898,7 +2898,7 @@ static void __devexit snd_es1968_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver es1968_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_es1968_ids,
.probe = snd_es1968_probe,
@@ -2909,15 +2909,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_es1968_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_es1968_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_es1968_init)
-module_exit(alsa_card_es1968_exit)
+module_pci_driver(es1968_driver);
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index a416ea8af3e9..f69662322750 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1416,7 +1416,7 @@ static int snd_fm801_resume(struct pci_dev *pci)
}
#endif
-static struct pci_driver driver = {
+static struct pci_driver fm801_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_fm801_ids,
.probe = snd_card_fm801_probe,
@@ -1427,15 +1427,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_fm801_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_fm801_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_fm801_init)
-module_exit(alsa_card_fm801_exit)
+module_pci_driver(fm801_driver);
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index ace157cc3d15..bd4149f1aaf4 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,6 +1,6 @@
snd-hda-intel-objs := hda_intel.o
-snd-hda-codec-y := hda_codec.o hda_jack.o
+snd-hda-codec-y := hda_codec.o hda_jack.o hda_auto_parser.o
snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
new file mode 100644
index 000000000000..6e9ef3e25093
--- /dev/null
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -0,0 +1,760 @@
+/*
+ * BIOS auto-parser helper functions for HD-audio
+ *
+ * Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+#include "hda_auto_parser.h"
+
+#define SFX "hda_codec: "
+
+/*
+ * Helper for automatic pin configuration
+ */
+
+static int is_in_nid_list(hda_nid_t nid, const hda_nid_t *list)
+{
+ for (; *list; list++)
+ if (*list == nid)
+ return 1;
+ return 0;
+}
+
+
+/*
+ * Sort an associated group of pins according to their sequence numbers.
+ */
+static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,
+ int num_pins)
+{
+ int i, j;
+ short seq;
+ hda_nid_t nid;
+
+ for (i = 0; i < num_pins; i++) {
+ for (j = i + 1; j < num_pins; j++) {
+ if (sequences[i] > sequences[j]) {
+ seq = sequences[i];
+ sequences[i] = sequences[j];
+ sequences[j] = seq;
+ nid = pins[i];
+ pins[i] = pins[j];
+ pins[j] = nid;
+ }
+ }
+ }
+}
+
+
+/* add the found input-pin to the cfg->inputs[] table */
+static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid,
+ int type)
+{
+ if (cfg->num_inputs < AUTO_CFG_MAX_INS) {
+ cfg->inputs[cfg->num_inputs].pin = nid;
+ cfg->inputs[cfg->num_inputs].type = type;
+ cfg->num_inputs++;
+ }
+}
+
+/* sort inputs in the order of AUTO_PIN_* type */
+static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg)
+{
+ int i, j;
+
+ for (i = 0; i < cfg->num_inputs; i++) {
+ for (j = i + 1; j < cfg->num_inputs; j++) {
+ if (cfg->inputs[i].type > cfg->inputs[j].type) {
+ struct auto_pin_cfg_item tmp;
+ tmp = cfg->inputs[i];
+ cfg->inputs[i] = cfg->inputs[j];
+ cfg->inputs[j] = tmp;
+ }
+ }
+ }
+}
+
+/* Reorder the surround channels
+ * ALSA sequence is front/surr/clfe/side
+ * HDA sequence is:
+ * 4-ch: front/surr => OK as it is
+ * 6-ch: front/clfe/surr
+ * 8-ch: front/clfe/rear/side|fc
+ */
+static void reorder_outputs(unsigned int nums, hda_nid_t *pins)
+{
+ hda_nid_t nid;
+
+ switch (nums) {
+ case 3:
+ case 4:
+ nid = pins[1];
+ pins[1] = pins[2];
+ pins[2] = nid;
+ break;
+ }
+}
+
+/*
+ * Parse all pin widgets and store the useful pin nids to cfg
+ *
+ * The number of line-outs or any primary output is stored in line_outs,
+ * and the corresponding output pins are assigned to line_out_pins[],
+ * in the order of front, rear, CLFE, side, ...
+ *
+ * If more extra outputs (speaker and headphone) are found, the pins are
+ * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
+ * is detected, one of speaker of HP pins is assigned as the primary
+ * output, i.e. to line_out_pins[0]. So, line_outs is always positive
+ * if any analog output exists.
+ *
+ * The analog input pins are assigned to inputs array.
+ * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
+ * respectively.
+ */
+int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
+ struct auto_pin_cfg *cfg,
+ const hda_nid_t *ignore_nids,
+ unsigned int cond_flags)
+{
+ hda_nid_t nid, end_nid;
+ short seq, assoc_line_out;
+ short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
+ short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
+ short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
+ int i;
+
+ memset(cfg, 0, sizeof(*cfg));
+
+ memset(sequences_line_out, 0, sizeof(sequences_line_out));
+ memset(sequences_speaker, 0, sizeof(sequences_speaker));
+ memset(sequences_hp, 0, sizeof(sequences_hp));
+ assoc_line_out = 0;
+
+ codec->ignore_misc_bit = true;
+ end_nid = codec->start_nid + codec->num_nodes;
+ for (nid = codec->start_nid; nid < end_nid; nid++) {
+ unsigned int wid_caps = get_wcaps(codec, nid);
+ unsigned int wid_type = get_wcaps_type(wid_caps);
+ unsigned int def_conf;
+ short assoc, loc, conn, dev;
+
+ /* read all default configuration for pin complex */
+ if (wid_type != AC_WID_PIN)
+ continue;
+ /* ignore the given nids (e.g. pc-beep returns error) */
+ if (ignore_nids && is_in_nid_list(nid, ignore_nids))
+ continue;
+
+ def_conf = snd_hda_codec_get_pincfg(codec, nid);
+ if (!(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
+ AC_DEFCFG_MISC_NO_PRESENCE))
+ codec->ignore_misc_bit = false;
+ conn = get_defcfg_connect(def_conf);
+ if (conn == AC_JACK_PORT_NONE)
+ continue;
+ loc = get_defcfg_location(def_conf);
+ dev = get_defcfg_device(def_conf);
+
+ /* workaround for buggy BIOS setups */
+ if (dev == AC_JACK_LINE_OUT) {
+ if (conn == AC_JACK_PORT_FIXED)
+ dev = AC_JACK_SPEAKER;
+ }
+
+ switch (dev) {
+ case AC_JACK_LINE_OUT:
+ seq = get_defcfg_sequence(def_conf);
+ assoc = get_defcfg_association(def_conf);
+
+ if (!(wid_caps & AC_WCAP_STEREO))
+ if (!cfg->mono_out_pin)
+ cfg->mono_out_pin = nid;
+ if (!assoc)
+ continue;
+ if (!assoc_line_out)
+ assoc_line_out = assoc;
+ else if (assoc_line_out != assoc)
+ continue;
+ if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
+ continue;
+ cfg->line_out_pins[cfg->line_outs] = nid;
+ sequences_line_out[cfg->line_outs] = seq;
+ cfg->line_outs++;
+ break;
+ case AC_JACK_SPEAKER:
+ seq = get_defcfg_sequence(def_conf);
+ assoc = get_defcfg_association(def_conf);
+ if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
+ continue;
+ cfg->speaker_pins[cfg->speaker_outs] = nid;
+ sequences_speaker[cfg->speaker_outs] = (assoc << 4) | seq;
+ cfg->speaker_outs++;
+ break;
+ case AC_JACK_HP_OUT:
+ seq = get_defcfg_sequence(def_conf);
+ assoc = get_defcfg_association(def_conf);
+ if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
+ continue;
+ cfg->hp_pins[cfg->hp_outs] = nid;
+ sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
+ cfg->hp_outs++;
+ break;
+ case AC_JACK_MIC_IN:
+ add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC);
+ break;
+ case AC_JACK_LINE_IN:
+ add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN);
+ break;
+ case AC_JACK_CD:
+ add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD);
+ break;
+ case AC_JACK_AUX:
+ add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX);
+ break;
+ case AC_JACK_SPDIF_OUT:
+ case AC_JACK_DIG_OTHER_OUT:
+ if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
+ continue;
+ cfg->dig_out_pins[cfg->dig_outs] = nid;
+ cfg->dig_out_type[cfg->dig_outs] =
+ (loc == AC_JACK_LOC_HDMI) ?
+ HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
+ cfg->dig_outs++;
+ break;
+ case AC_JACK_SPDIF_IN:
+ case AC_JACK_DIG_OTHER_IN:
+ cfg->dig_in_pin = nid;
+ if (loc == AC_JACK_LOC_HDMI)
+ cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
+ else
+ cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
+ break;
+ }
+ }
+
+ /* FIX-UP:
+ * If no line-out is defined but multiple HPs are found,
+ * some of them might be the real line-outs.
+ */
+ if (!cfg->line_outs && cfg->hp_outs > 1 &&
+ !(cond_flags & HDA_PINCFG_NO_HP_FIXUP)) {
+ int i = 0;
+ while (i < cfg->hp_outs) {
+ /* The real HPs should have the sequence 0x0f */
+ if ((sequences_hp[i] & 0x0f) == 0x0f) {
+ i++;
+ continue;
+ }
+ /* Move it to the line-out table */
+ cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
+ sequences_line_out[cfg->line_outs] = sequences_hp[i];
+ cfg->line_outs++;
+ cfg->hp_outs--;
+ memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
+ sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
+ memmove(sequences_hp + i, sequences_hp + i + 1,
+ sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
+ }
+ memset(cfg->hp_pins + cfg->hp_outs, 0,
+ sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs));
+ if (!cfg->hp_outs)
+ cfg->line_out_type = AUTO_PIN_HP_OUT;
+
+ }
+
+ /* sort by sequence */
+ sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
+ cfg->line_outs);
+ sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
+ cfg->speaker_outs);
+ sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
+ cfg->hp_outs);
+
+ /*
+ * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
+ * as a primary output
+ */
+ if (!cfg->line_outs &&
+ !(cond_flags & HDA_PINCFG_NO_LO_FIXUP)) {
+ if (cfg->speaker_outs) {
+ cfg->line_outs = cfg->speaker_outs;
+ memcpy(cfg->line_out_pins, cfg->speaker_pins,
+ sizeof(cfg->speaker_pins));
+ cfg->speaker_outs = 0;
+ memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
+ cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
+ } else if (cfg->hp_outs) {
+ cfg->line_outs = cfg->hp_outs;
+ memcpy(cfg->line_out_pins, cfg->hp_pins,
+ sizeof(cfg->hp_pins));
+ cfg->hp_outs = 0;
+ memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
+ cfg->line_out_type = AUTO_PIN_HP_OUT;
+ }
+ }
+
+ reorder_outputs(cfg->line_outs, cfg->line_out_pins);
+ reorder_outputs(cfg->hp_outs, cfg->hp_pins);
+ reorder_outputs(cfg->speaker_outs, cfg->speaker_pins);
+
+ sort_autocfg_input_pins(cfg);
+
+ /*
+ * debug prints of the parsed results
+ */
+ snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n",
+ cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
+ cfg->line_out_pins[2], cfg->line_out_pins[3],
+ cfg->line_out_pins[4],
+ cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" :
+ (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ?
+ "speaker" : "line"));
+ snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
+ cfg->speaker_outs, cfg->speaker_pins[0],
+ cfg->speaker_pins[1], cfg->speaker_pins[2],
+ cfg->speaker_pins[3], cfg->speaker_pins[4]);
+ snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
+ cfg->hp_outs, cfg->hp_pins[0],
+ cfg->hp_pins[1], cfg->hp_pins[2],
+ cfg->hp_pins[3], cfg->hp_pins[4]);
+ snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
+ if (cfg->dig_outs)
+ snd_printd(" dig-out=0x%x/0x%x\n",
+ cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
+ snd_printd(" inputs:");
+ for (i = 0; i < cfg->num_inputs; i++) {
+ snd_printd(" %s=0x%x",
+ hda_get_autocfg_input_label(codec, cfg, i),
+ cfg->inputs[i].pin);
+ }
+ snd_printd("\n");
+ if (cfg->dig_in_pin)
+ snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
+
+ return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_parse_pin_defcfg);
+
+int snd_hda_get_input_pin_attr(unsigned int def_conf)
+{
+ unsigned int loc = get_defcfg_location(def_conf);
+ unsigned int conn = get_defcfg_connect(def_conf);
+ if (conn == AC_JACK_PORT_NONE)
+ return INPUT_PIN_ATTR_UNUSED;
+ /* Windows may claim the internal mic to be BOTH, too */
+ if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH)
+ return INPUT_PIN_ATTR_INT;
+ if ((loc & 0x30) == AC_JACK_LOC_INTERNAL)
+ return INPUT_PIN_ATTR_INT;
+ if ((loc & 0x30) == AC_JACK_LOC_SEPARATE)
+ return INPUT_PIN_ATTR_DOCK;
+ if (loc == AC_JACK_LOC_REAR)
+ return INPUT_PIN_ATTR_REAR;
+ if (loc == AC_JACK_LOC_FRONT)
+ return INPUT_PIN_ATTR_FRONT;
+ return INPUT_PIN_ATTR_NORMAL;
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr);
+
+/**
+ * hda_get_input_pin_label - Give a label for the given input pin
+ *
+ * When check_location is true, the function checks the pin location
+ * for mic and line-in pins, and set an appropriate prefix like "Front",
+ * "Rear", "Internal".
+ */
+
+static const char *hda_get_input_pin_label(struct hda_codec *codec,
+ hda_nid_t pin, bool check_location)
+{
+ unsigned int def_conf;
+ static const char * const mic_names[] = {
+ "Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic",
+ };
+ int attr;
+
+ def_conf = snd_hda_codec_get_pincfg(codec, pin);
+
+ switch (get_defcfg_device(def_conf)) {
+ case AC_JACK_MIC_IN:
+ if (!check_location)
+ return "Mic";
+ attr = snd_hda_get_input_pin_attr(def_conf);
+ if (!attr)
+ return "None";
+ return mic_names[attr - 1];
+ case AC_JACK_LINE_IN:
+ if (!check_location)
+ return "Line";
+ attr = snd_hda_get_input_pin_attr(def_conf);
+ if (!attr)
+ return "None";
+ if (attr == INPUT_PIN_ATTR_DOCK)
+ return "Dock Line";
+ return "Line";
+ case AC_JACK_AUX:
+ return "Aux";
+ case AC_JACK_CD:
+ return "CD";
+ case AC_JACK_SPDIF_IN:
+ return "SPDIF In";
+ case AC_JACK_DIG_OTHER_IN:
+ return "Digital In";
+ default:
+ return "Misc";
+ }
+}
+
+/* Check whether the location prefix needs to be added to the label.
+ * If all mic-jacks are in the same location (e.g. rear panel), we don't
+ * have to put "Front" prefix to each label. In such a case, returns false.
+ */
+static int check_mic_location_need(struct hda_codec *codec,
+ const struct auto_pin_cfg *cfg,
+ int input)
+{
+ unsigned int defc;
+ int i, attr, attr2;
+
+ defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin);
+ attr = snd_hda_get_input_pin_attr(defc);
+ /* for internal or docking mics, we need locations */
+ if (attr <= INPUT_PIN_ATTR_NORMAL)
+ return 1;
+
+ attr = 0;
+ for (i = 0; i < cfg->num_inputs; i++) {
+ defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin);
+ attr2 = snd_hda_get_input_pin_attr(defc);
+ if (attr2 >= INPUT_PIN_ATTR_NORMAL) {
+ if (attr && attr != attr2)
+ return 1; /* different locations found */
+ attr = attr2;
+ }
+ }
+ return 0;
+}
+
+/**
+ * hda_get_autocfg_input_label - Get a label for the given input
+ *
+ * Get a label for the given input pin defined by the autocfg item.
+ * Unlike hda_get_input_pin_label(), this function checks all inputs
+ * defined in autocfg and avoids the redundant mic/line prefix as much as
+ * possible.
+ */
+const char *hda_get_autocfg_input_label(struct hda_codec *codec,
+ const struct auto_pin_cfg *cfg,
+ int input)
+{
+ int type = cfg->inputs[input].type;
+ int has_multiple_pins = 0;
+
+ if ((input > 0 && cfg->inputs[input - 1].type == type) ||
+ (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type))
+ has_multiple_pins = 1;
+ if (has_multiple_pins && type == AUTO_PIN_MIC)
+ has_multiple_pins &= check_mic_location_need(codec, cfg, input);
+ return hda_get_input_pin_label(codec, cfg->inputs[input].pin,
+ has_multiple_pins);
+}
+EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);
+
+/* return the position of NID in the list, or -1 if not found */
+static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
+{
+ int i;
+ for (i = 0; i < nums; i++)
+ if (list[i] == nid)
+ return i;
+ return -1;
+}
+
+/* get a unique suffix or an index number */
+static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins,
+ int num_pins, int *indexp)
+{
+ static const char * const channel_sfx[] = {
+ " Front", " Surround", " CLFE", " Side"
+ };
+ int i;
+
+ i = find_idx_in_nid_list(nid, pins, num_pins);
+ if (i < 0)
+ return NULL;
+ if (num_pins == 1)
+ return "";
+ if (num_pins > ARRAY_SIZE(channel_sfx)) {
+ if (indexp)
+ *indexp = i;
+ return "";
+ }
+ return channel_sfx[i];
+}
+
+static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,
+ const struct auto_pin_cfg *cfg,
+ const char *name, char *label, int maxlen,
+ int *indexp)
+{
+ unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
+ int attr = snd_hda_get_input_pin_attr(def_conf);
+ const char *pfx = "", *sfx = "";
+
+ /* handle as a speaker if it's a fixed line-out */
+ if (!strcmp(name, "Line Out") && attr == INPUT_PIN_ATTR_INT)
+ name = "Speaker";
+ /* check the location */
+ switch (attr) {
+ case INPUT_PIN_ATTR_DOCK:
+ pfx = "Dock ";
+ break;
+ case INPUT_PIN_ATTR_FRONT:
+ pfx = "Front ";
+ break;
+ }
+ if (cfg) {
+ /* try to give a unique suffix if needed */
+ sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs,
+ indexp);
+ if (!sfx)
+ sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs,
+ indexp);
+ if (!sfx) {
+ /* don't add channel suffix for Headphone controls */
+ int idx = find_idx_in_nid_list(nid, cfg->hp_pins,
+ cfg->hp_outs);
+ if (idx >= 0)
+ *indexp = idx;
+ sfx = "";
+ }
+ }
+ snprintf(label, maxlen, "%s%s%s", pfx, name, sfx);
+ return 1;
+}
+
+/**
+ * snd_hda_get_pin_label - Get a label for the given I/O pin
+ *
+ * Get a label for the given pin. This function works for both input and
+ * output pins. When @cfg is given as non-NULL, the function tries to get
+ * an optimized label using hda_get_autocfg_input_label().
+ *
+ * This function tries to give a unique label string for the pin as much as
+ * possible. For example, when the multiple line-outs are present, it adds
+ * the channel suffix like "Front", "Surround", etc (only when @cfg is given).
+ * If no unique name with a suffix is available and @indexp is non-NULL, the
+ * index number is stored in the pointer.
+ */
+int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
+ const struct auto_pin_cfg *cfg,
+ char *label, int maxlen, int *indexp)
+{
+ unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
+ const char *name = NULL;
+ int i;
+
+ if (indexp)
+ *indexp = 0;
+ if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
+ return 0;
+
+ switch (get_defcfg_device(def_conf)) {
+ case AC_JACK_LINE_OUT:
+ return fill_audio_out_name(codec, nid, cfg, "Line Out",
+ label, maxlen, indexp);
+ case AC_JACK_SPEAKER:
+ return fill_audio_out_name(codec, nid, cfg, "Speaker",
+ label, maxlen, indexp);
+ case AC_JACK_HP_OUT:
+ return fill_audio_out_name(codec, nid, cfg, "Headphone",
+ label, maxlen, indexp);
+ case AC_JACK_SPDIF_OUT:
+ case AC_JACK_DIG_OTHER_OUT:
+ if (get_defcfg_location(def_conf) == AC_JACK_LOC_HDMI)
+ name = "HDMI";
+ else
+ name = "SPDIF";
+ if (cfg && indexp) {
+ i = find_idx_in_nid_list(nid, cfg->dig_out_pins,
+ cfg->dig_outs);
+ if (i >= 0)
+ *indexp = i;
+ }
+ break;
+ default:
+ if (cfg) {
+ for (i = 0; i < cfg->num_inputs; i++) {
+ if (cfg->inputs[i].pin != nid)
+ continue;
+ name = hda_get_autocfg_input_label(codec, cfg, i);
+ if (name)
+ break;
+ }
+ }
+ if (!name)
+ name = hda_get_input_pin_label(codec, nid, true);
+ break;
+ }
+ if (!name)
+ return 0;
+ strlcpy(label, name, maxlen);
+ return 1;
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_pin_label);
+
+int snd_hda_gen_add_verbs(struct hda_gen_spec *spec,
+ const struct hda_verb *list)
+{
+ const struct hda_verb **v;
+ snd_array_init(&spec->verbs, sizeof(struct hda_verb *), 8);
+ v = snd_array_new(&spec->verbs);
+ if (!v)
+ return -ENOMEM;
+ *v = list;
+ return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_gen_add_verbs);
+
+void snd_hda_gen_apply_verbs(struct hda_codec *codec)
+{
+ struct hda_gen_spec *spec = codec->spec;
+ int i;
+ for (i = 0; i < spec->verbs.used; i++) {
+ struct hda_verb **v = snd_array_elem(&spec->verbs, i);
+ snd_hda_sequence_write(codec, *v);
+ }
+}
+EXPORT_SYMBOL_HDA(snd_hda_gen_apply_verbs);
+
+void snd_hda_apply_pincfgs(struct hda_codec *codec,
+ const struct hda_pintbl *cfg)
+{
+ for (; cfg->nid; cfg++)
+ snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
+}
+EXPORT_SYMBOL_HDA(snd_hda_apply_pincfgs);
+
+void snd_hda_apply_fixup(struct hda_codec *codec, int action)
+{
+ struct hda_gen_spec *spec = codec->spec;
+ int id = spec->fixup_id;
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ const char *modelname = spec->fixup_name;
+#endif
+ int depth = 0;
+
+ if (!spec->fixup_list)
+ return;
+
+ while (id >= 0) {
+ const struct hda_fixup *fix = spec->fixup_list + id;
+
+ switch (fix->type) {
+ case HDA_FIXUP_PINS:
+ if (action != HDA_FIXUP_ACT_PRE_PROBE || !fix->v.pins)
+ break;
+ snd_printdd(KERN_INFO SFX
+ "%s: Apply pincfg for %s\n",
+ codec->chip_name, modelname);
+ snd_hda_apply_pincfgs(codec, fix->v.pins);
+ break;
+ case HDA_FIXUP_VERBS:
+ if (action != HDA_FIXUP_ACT_PROBE || !fix->v.verbs)
+ break;
+ snd_printdd(KERN_INFO SFX
+ "%s: Apply fix-verbs for %s\n",
+ codec->chip_name, modelname);
+ snd_hda_gen_add_verbs(codec->spec, fix->v.verbs);
+ break;
+ case HDA_FIXUP_FUNC:
+ if (!fix->v.func)
+ break;
+ snd_printdd(KERN_INFO SFX
+ "%s: Apply fix-func for %s\n",
+ codec->chip_name, modelname);
+ fix->v.func(codec, fix, action);
+ break;
+ default:
+ snd_printk(KERN_ERR SFX
+ "%s: Invalid fixup type %d\n",
+ codec->chip_name, fix->type);
+ break;
+ }
+ if (!fix->chained)
+ break;
+ if (++depth > 10)
+ break;
+ id = fix->chain_id;
+ }
+}
+EXPORT_SYMBOL_HDA(snd_hda_apply_fixup);
+
+void snd_hda_pick_fixup(struct hda_codec *codec,
+ const struct hda_model_fixup *models,
+ const struct snd_pci_quirk *quirk,
+ const struct hda_fixup *fixlist)
+{
+ struct hda_gen_spec *spec = codec->spec;
+ const struct snd_pci_quirk *q;
+ int id = -1;
+ const char *name = NULL;
+
+ /* when model=nofixup is given, don't pick up any fixups */
+ if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
+ spec->fixup_list = NULL;
+ spec->fixup_id = -1;
+ return;
+ }
+
+ if (codec->modelname && models) {
+ while (models->name) {
+ if (!strcmp(codec->modelname, models->name)) {
+ id = models->id;
+ name = models->name;
+ break;
+ }
+ models++;
+ }
+ }
+ if (id < 0) {
+ q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
+ if (q) {
+ id = q->value;
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ name = q->name;
+#endif
+ }
+ }
+ if (id < 0) {
+ for (q = quirk; q->subvendor; q++) {
+ unsigned int vendorid =
+ q->subdevice | (q->subvendor << 16);
+ if (vendorid == codec->subsystem_id) {
+ id = q->value;
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ name = q->name;
+#endif
+ break;
+ }
+ }
+ }
+
+ spec->fixup_id = id;
+ if (id >= 0) {
+ spec->fixup_list = fixlist;
+ spec->fixup_name = name;
+ }
+}
+EXPORT_SYMBOL_HDA(snd_hda_pick_fixup);
diff --git a/sound/pci/hda/hda_auto_parser.h b/sound/pci/hda/hda_auto_parser.h
new file mode 100644
index 000000000000..2a7889dfbd1b
--- /dev/null
+++ b/sound/pci/hda/hda_auto_parser.h
@@ -0,0 +1,160 @@
+/*
+ * BIOS auto-parser helper functions for HD-audio
+ *
+ * Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __SOUND_HDA_AUTO_PARSER_H
+#define __SOUND_HDA_AUTO_PARSER_H
+
+/*
+ * Helper for automatic pin configuration
+ */
+
+enum {
+ AUTO_PIN_MIC,
+ AUTO_PIN_LINE_IN,
+ AUTO_PIN_CD,
+ AUTO_PIN_AUX,
+ AUTO_PIN_LAST
+};
+
+enum {
+ AUTO_PIN_LINE_OUT,
+ AUTO_PIN_SPEAKER_OUT,
+ AUTO_PIN_HP_OUT
+};
+
+#define AUTO_CFG_MAX_OUTS HDA_MAX_OUTS
+#define AUTO_CFG_MAX_INS 8
+
+struct auto_pin_cfg_item {
+ hda_nid_t pin;
+ int type;
+};
+
+struct auto_pin_cfg;
+const char *hda_get_autocfg_input_label(struct hda_codec *codec,
+ const struct auto_pin_cfg *cfg,
+ int input);
+int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
+ const struct auto_pin_cfg *cfg,
+ char *label, int maxlen, int *indexp);
+
+enum {
+ INPUT_PIN_ATTR_UNUSED, /* pin not connected */
+ INPUT_PIN_ATTR_INT, /* internal mic/line-in */
+ INPUT_PIN_ATTR_DOCK, /* docking mic/line-in */
+ INPUT_PIN_ATTR_NORMAL, /* mic/line-in jack */
+ INPUT_PIN_ATTR_FRONT, /* mic/line-in jack in front */
+ INPUT_PIN_ATTR_REAR, /* mic/line-in jack in rear */
+};
+
+int snd_hda_get_input_pin_attr(unsigned int def_conf);
+
+struct auto_pin_cfg {
+ int line_outs;
+ /* sorted in the order of Front/Surr/CLFE/Side */
+ hda_nid_t line_out_pins[AUTO_CFG_MAX_OUTS];
+ int speaker_outs;
+ hda_nid_t speaker_pins[AUTO_CFG_MAX_OUTS];
+ int hp_outs;
+ int line_out_type; /* AUTO_PIN_XXX_OUT */
+ hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS];
+ int num_inputs;
+ struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS];
+ int dig_outs;
+ hda_nid_t dig_out_pins[2];
+ hda_nid_t dig_in_pin;
+ hda_nid_t mono_out_pin;
+ int dig_out_type[2]; /* HDA_PCM_TYPE_XXX */
+ int dig_in_type; /* HDA_PCM_TYPE_XXX */
+};
+
+/* bit-flags for snd_hda_parse_pin_def_config() behavior */
+#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */
+#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */
+
+int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
+ struct auto_pin_cfg *cfg,
+ const hda_nid_t *ignore_nids,
+ unsigned int cond_flags);
+
+/* older function */
+#define snd_hda_parse_pin_def_config(codec, cfg, ignore) \
+ snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0)
+
+/*
+ */
+
+struct hda_gen_spec {
+ /* fix-up list */
+ int fixup_id;
+ const struct hda_fixup *fixup_list;
+ const char *fixup_name;
+
+ /* additional init verbs */
+ struct snd_array verbs;
+};
+
+
+/*
+ * Fix-up pin default configurations and add default verbs
+ */
+
+struct hda_pintbl {
+ hda_nid_t nid;
+ u32 val;
+};
+
+struct hda_model_fixup {
+ const int id;
+ const char *name;
+};
+
+struct hda_fixup {
+ int type;
+ bool chained;
+ int chain_id;
+ union {
+ const struct hda_pintbl *pins;
+ const struct hda_verb *verbs;
+ void (*func)(struct hda_codec *codec,
+ const struct hda_fixup *fix,
+ int action);
+ } v;
+};
+
+/* fixup types */
+enum {
+ HDA_FIXUP_INVALID,
+ HDA_FIXUP_PINS,
+ HDA_FIXUP_VERBS,
+ HDA_FIXUP_FUNC,
+};
+
+/* fixup action definitions */
+enum {
+ HDA_FIXUP_ACT_PRE_PROBE,
+ HDA_FIXUP_ACT_PROBE,
+ HDA_FIXUP_ACT_INIT,
+ HDA_FIXUP_ACT_BUILD,
+};
+
+int snd_hda_gen_add_verbs(struct hda_gen_spec *spec,
+ const struct hda_verb *list);
+void snd_hda_gen_apply_verbs(struct hda_codec *codec);
+void snd_hda_apply_pincfgs(struct hda_codec *codec,
+ const struct hda_pintbl *cfg);
+void snd_hda_apply_fixup(struct hda_codec *codec, int action);
+void snd_hda_pick_fixup(struct hda_codec *codec,
+ const struct hda_model_fixup *models,
+ const struct snd_pci_quirk *quirk,
+ const struct hda_fixup *fixlist);
+
+#endif /* __SOUND_HDA_AUTO_PARSER_H */
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 841475cc13b6..eb09a3348325 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -334,78 +334,67 @@ static hda_nid_t *lookup_conn_list(struct snd_array *array, hda_nid_t nid)
return NULL;
}
+/* read the connection and add to the cache */
+static int read_and_add_raw_conns(struct hda_codec *codec, hda_nid_t nid)
+{
+ hda_nid_t list[HDA_MAX_CONNECTIONS];
+ int len;
+
+ len = snd_hda_get_raw_connections(codec, nid, list, ARRAY_SIZE(list));
+ if (len < 0)
+ return len;
+ return snd_hda_override_conn_list(codec, nid, len, list);
+}
+
/**
- * snd_hda_get_conn_list - get connection list
+ * snd_hda_get_connections - copy connection list
* @codec: the HDA codec
* @nid: NID to parse
- * @listp: the pointer to store NID list
+ * @conn_list: connection list array; when NULL, checks only the size
+ * @max_conns: max. number of connections to store
*
* Parses the connection list of the given widget and stores the list
* of NIDs.
*
* Returns the number of connections, or a negative error code.
*/
-int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
- const hda_nid_t **listp)
+int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
+ hda_nid_t *conn_list, int max_conns)
{
struct snd_array *array = &codec->conn_lists;
- int len, err;
- hda_nid_t list[HDA_MAX_CONNECTIONS];
+ int len;
hda_nid_t *p;
bool added = false;
again:
+ mutex_lock(&codec->hash_mutex);
+ len = -1;
/* if the connection-list is already cached, read it */
p = lookup_conn_list(array, nid);
if (p) {
- if (listp)
- *listp = p + 2;
- return p[1];
+ len = p[1];
+ if (conn_list && len > max_conns) {
+ snd_printk(KERN_ERR "hda_codec: "
+ "Too many connections %d for NID 0x%x\n",
+ len, nid);
+ mutex_unlock(&codec->hash_mutex);
+ return -EINVAL;
+ }
+ if (conn_list && len)
+ memcpy(conn_list, p + 2, len * sizeof(hda_nid_t));
}
+ mutex_unlock(&codec->hash_mutex);
+ if (len >= 0)
+ return len;
if (snd_BUG_ON(added))
return -EINVAL;
- /* read the connection and add to the cache */
- len = snd_hda_get_raw_connections(codec, nid, list, HDA_MAX_CONNECTIONS);
+ len = read_and_add_raw_conns(codec, nid);
if (len < 0)
return len;
- err = snd_hda_override_conn_list(codec, nid, len, list);
- if (err < 0)
- return err;
added = true;
goto again;
}
-EXPORT_SYMBOL_HDA(snd_hda_get_conn_list);
-
-/**
- * snd_hda_get_connections - copy connection list
- * @codec: the HDA codec
- * @nid: NID to parse
- * @conn_list: connection list array
- * @max_conns: max. number of connections to store
- *
- * Parses the connection list of the given widget and stores the list
- * of NIDs.
- *
- * Returns the number of connections, or a negative error code.
- */
-int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
- hda_nid_t *conn_list, int max_conns)
-{
- const hda_nid_t *list;
- int len = snd_hda_get_conn_list(codec, nid, &list);
-
- if (len <= 0)
- return len;
- if (len > max_conns) {
- snd_printk(KERN_ERR "hda_codec: "
- "Too many connections %d for NID 0x%x\n",
- len, nid);
- return -EINVAL;
- }
- memcpy(conn_list, list, len * sizeof(hda_nid_t));
- return len;
-}
EXPORT_SYMBOL_HDA(snd_hda_get_connections);
/**
@@ -543,6 +532,7 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
hda_nid_t *p;
int i, old_used;
+ mutex_lock(&codec->hash_mutex);
p = lookup_conn_list(array, nid);
if (p)
*p = -1; /* invalidate the old entry */
@@ -553,10 +543,12 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
for (i = 0; i < len; i++)
if (!add_conn_list(array, list[i]))
goto error_add;
+ mutex_unlock(&codec->hash_mutex);
return 0;
error_add:
array->used = old_used;
+ mutex_unlock(&codec->hash_mutex);
return -ENOMEM;
}
EXPORT_SYMBOL_HDA(snd_hda_override_conn_list);
@@ -1255,6 +1247,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
codec->addr = codec_addr;
mutex_init(&codec->spdif_mutex);
mutex_init(&codec->control_mutex);
+ mutex_init(&codec->hash_mutex);
init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);
@@ -1264,15 +1257,9 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);
snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64);
snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16);
- if (codec->bus->modelname) {
- codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
- if (!codec->modelname) {
- snd_hda_codec_free(codec);
- return -ENODEV;
- }
- }
#ifdef CONFIG_SND_HDA_POWER_SAVE
+ spin_lock_init(&codec->power_lock);
INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
/* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
* the caller has to power down appropriatley after initialization
@@ -1281,6 +1268,14 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
hda_keep_power_on(codec);
#endif
+ if (codec->bus->modelname) {
+ codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
+ if (!codec->modelname) {
+ snd_hda_codec_free(codec);
+ return -ENODEV;
+ }
+ }
+
list_add_tail(&codec->list, &bus->codec_list);
bus->caddr_tbl[codec_addr] = codec;
@@ -1603,6 +1598,60 @@ get_alloc_amp_hash(struct hda_codec *codec, u32 key)
return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
}
+/* overwrite the value with the key in the caps hash */
+static int write_caps_hash(struct hda_codec *codec, u32 key, unsigned int val)
+{
+ struct hda_amp_info *info;
+
+ mutex_lock(&codec->hash_mutex);
+ info = get_alloc_amp_hash(codec, key);
+ if (!info) {
+ mutex_unlock(&codec->hash_mutex);
+ return -EINVAL;
+ }
+ info->amp_caps = val;
+ info->head.val |= INFO_AMP_CAPS;
+ mutex_unlock(&codec->hash_mutex);
+ return 0;
+}
+
+/* query the value from the caps hash; if not found, fetch the current
+ * value from the given function and store in the hash
+ */
+static unsigned int
+query_caps_hash(struct hda_codec *codec, hda_nid_t nid, int dir, u32 key,
+ unsigned int (*func)(struct hda_codec *, hda_nid_t, int))
+{
+ struct hda_amp_info *info;
+ unsigned int val;
+
+ mutex_lock(&codec->hash_mutex);
+ info = get_alloc_amp_hash(codec, key);
+ if (!info) {
+ mutex_unlock(&codec->hash_mutex);
+ return 0;
+ }
+ if (!(info->head.val & INFO_AMP_CAPS)) {
+ mutex_unlock(&codec->hash_mutex); /* for reentrance */
+ val = func(codec, nid, dir);
+ write_caps_hash(codec, key, val);
+ } else {
+ val = info->amp_caps;
+ mutex_unlock(&codec->hash_mutex);
+ }
+ return val;
+}
+
+static unsigned int read_amp_cap(struct hda_codec *codec, hda_nid_t nid,
+ int direction)
+{
+ if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
+ nid = codec->afg;
+ return snd_hda_param_read(codec, nid,
+ direction == HDA_OUTPUT ?
+ AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
+}
+
/**
* query_amp_caps - query AMP capabilities
* @codec: the HD-auio codec
@@ -1617,22 +1666,9 @@ get_alloc_amp_hash(struct hda_codec *codec, u32 key)
*/
u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
{
- struct hda_amp_info *info;
-
- info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
- if (!info)
- return 0;
- if (!(info->head.val & INFO_AMP_CAPS)) {
- if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
- nid = codec->afg;
- info->amp_caps = snd_hda_param_read(codec, nid,
- direction == HDA_OUTPUT ?
- AC_PAR_AMP_OUT_CAP :
- AC_PAR_AMP_IN_CAP);
- if (info->amp_caps)
- info->head.val |= INFO_AMP_CAPS;
- }
- return info->amp_caps;
+ return query_caps_hash(codec, nid, direction,
+ HDA_HASH_KEY(nid, direction, 0),
+ read_amp_cap);
}
EXPORT_SYMBOL_HDA(query_amp_caps);
@@ -1652,34 +1688,12 @@ EXPORT_SYMBOL_HDA(query_amp_caps);
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps)
{
- struct hda_amp_info *info;
-
- info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
- if (!info)
- return -EINVAL;
- info->amp_caps = caps;
- info->head.val |= INFO_AMP_CAPS;
- return 0;
+ return write_caps_hash(codec, HDA_HASH_KEY(nid, dir, 0), caps);
}
EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
-static unsigned int
-query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
- unsigned int (*func)(struct hda_codec *, hda_nid_t))
-{
- struct hda_amp_info *info;
-
- info = get_alloc_amp_hash(codec, key);
- if (!info)
- return 0;
- if (!info->head.val) {
- info->head.val |= INFO_AMP_CAPS;
- info->amp_caps = func(codec, nid);
- }
- return info->amp_caps;
-}
-
-static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
+static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid,
+ int dir)
{
return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
}
@@ -1697,7 +1711,7 @@ static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
*/
u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
{
- return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
+ return query_caps_hash(codec, nid, 0, HDA_HASH_PINCAP_KEY(nid),
read_pin_cap);
}
EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
@@ -1715,41 +1729,47 @@ EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
unsigned int caps)
{
- struct hda_amp_info *info;
- info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid));
- if (!info)
- return -ENOMEM;
- info->amp_caps = caps;
- info->head.val |= INFO_AMP_CAPS;
- return 0;
+ return write_caps_hash(codec, HDA_HASH_PINCAP_KEY(nid), caps);
}
EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps);
-/*
- * read the current volume to info
- * if the cache exists, read the cache value.
+/* read or sync the hash value with the current value;
+ * call within hash_mutex
*/
-static unsigned int get_vol_mute(struct hda_codec *codec,
- struct hda_amp_info *info, hda_nid_t nid,
- int ch, int direction, int index)
+static struct hda_amp_info *
+update_amp_hash(struct hda_codec *codec, hda_nid_t nid, int ch,
+ int direction, int index)
{
- u32 val, parm;
-
- if (info->head.val & INFO_AMP_VOL(ch))
- return info->vol[ch];
+ struct hda_amp_info *info;
+ unsigned int parm, val = 0;
+ bool val_read = false;
- parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
- parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
- parm |= index;
- val = snd_hda_codec_read(codec, nid, 0,
+ retry:
+ info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
+ if (!info)
+ return NULL;
+ if (!(info->head.val & INFO_AMP_VOL(ch))) {
+ if (!val_read) {
+ mutex_unlock(&codec->hash_mutex);
+ parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
+ parm |= direction == HDA_OUTPUT ?
+ AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
+ parm |= index;
+ val = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_AMP_GAIN_MUTE, parm);
- info->vol[ch] = val & 0xff;
- info->head.val |= INFO_AMP_VOL(ch);
- return info->vol[ch];
+ val &= 0xff;
+ val_read = true;
+ mutex_lock(&codec->hash_mutex);
+ goto retry;
+ }
+ info->vol[ch] = val;
+ info->head.val |= INFO_AMP_VOL(ch);
+ }
+ return info;
}
/*
- * write the current volume in info to the h/w and update the cache
+ * write the current volume in info to the h/w
*/
static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
hda_nid_t nid, int ch, int direction, int index,
@@ -1766,7 +1786,6 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
else
parm |= val;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
- info->vol[ch] = val;
}
/**
@@ -1783,10 +1802,14 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int index)
{
struct hda_amp_info *info;
- info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
- if (!info)
- return 0;
- return get_vol_mute(codec, info, nid, ch, direction, index);
+ unsigned int val = 0;
+
+ mutex_lock(&codec->hash_mutex);
+ info = update_amp_hash(codec, nid, ch, direction, index);
+ if (info)
+ val = info->vol[ch];
+ mutex_unlock(&codec->hash_mutex);
+ return val;
}
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
@@ -1808,15 +1831,23 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
{
struct hda_amp_info *info;
- info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
- if (!info)
- return 0;
if (snd_BUG_ON(mask & ~0xff))
mask &= 0xff;
val &= mask;
- val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
- if (info->vol[ch] == val)
+
+ mutex_lock(&codec->hash_mutex);
+ info = update_amp_hash(codec, nid, ch, direction, idx);
+ if (!info) {
+ mutex_unlock(&codec->hash_mutex);
+ return 0;
+ }
+ val |= info->vol[ch] & ~mask;
+ if (info->vol[ch] == val) {
+ mutex_unlock(&codec->hash_mutex);
return 0;
+ }
+ info->vol[ch] = val;
+ mutex_unlock(&codec->hash_mutex);
put_vol_mute(codec, info, nid, ch, direction, idx, val);
return 1;
}
@@ -2263,7 +2294,10 @@ int snd_hda_codec_reset(struct hda_codec *codec)
/* OK, let it free */
#ifdef CONFIG_SND_HDA_POWER_SAVE
- cancel_delayed_work(&codec->power_work);
+ cancel_delayed_work_sync(&codec->power_work);
+ codec->power_on = 0;
+ codec->power_transition = 0;
+ codec->power_jiffies = jiffies;
flush_workqueue(codec->bus->workq);
#endif
snd_hda_ctls_clear(codec);
@@ -2859,12 +2893,15 @@ static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
int idx = kcontrol->private_value;
- struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
+ struct hda_spdif_out *spdif;
+ mutex_lock(&codec->spdif_mutex);
+ spdif = snd_array_elem(&codec->spdif_out, idx);
ucontrol->value.iec958.status[0] = spdif->status & 0xff;
ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff;
ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff;
ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff;
+ mutex_unlock(&codec->spdif_mutex);
return 0;
}
@@ -2950,12 +2987,14 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
int idx = kcontrol->private_value;
- struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
- hda_nid_t nid = spdif->nid;
+ struct hda_spdif_out *spdif;
+ hda_nid_t nid;
unsigned short val;
int change;
mutex_lock(&codec->spdif_mutex);
+ spdif = snd_array_elem(&codec->spdif_out, idx);
+ nid = spdif->nid;
spdif->status = ucontrol->value.iec958.status[0] |
((unsigned int)ucontrol->value.iec958.status[1] << 8) |
((unsigned int)ucontrol->value.iec958.status[2] << 16) |
@@ -2977,9 +3016,12 @@ static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
int idx = kcontrol->private_value;
- struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
+ struct hda_spdif_out *spdif;
+ mutex_lock(&codec->spdif_mutex);
+ spdif = snd_array_elem(&codec->spdif_out, idx);
ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE;
+ mutex_unlock(&codec->spdif_mutex);
return 0;
}
@@ -2999,12 +3041,14 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
int idx = kcontrol->private_value;
- struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
- hda_nid_t nid = spdif->nid;
+ struct hda_spdif_out *spdif;
+ hda_nid_t nid;
unsigned short val;
int change;
mutex_lock(&codec->spdif_mutex);
+ spdif = snd_array_elem(&codec->spdif_out, idx);
+ nid = spdif->nid;
val = spdif->ctls & ~AC_DIG1_ENABLE;
if (ucontrol->value.integer.value[0])
val |= AC_DIG1_ENABLE;
@@ -3092,6 +3136,9 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
}
EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
+/* get the hda_spdif_out entry from the given NID
+ * call within spdif_mutex lock
+ */
struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
hda_nid_t nid)
{
@@ -3108,9 +3155,10 @@ EXPORT_SYMBOL_HDA(snd_hda_spdif_out_of_nid);
void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
{
- struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
+ struct hda_spdif_out *spdif;
mutex_lock(&codec->spdif_mutex);
+ spdif = snd_array_elem(&codec->spdif_out, idx);
spdif->nid = (u16)-1;
mutex_unlock(&codec->spdif_mutex);
}
@@ -3118,10 +3166,11 @@ EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_unassign);
void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
{
- struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
+ struct hda_spdif_out *spdif;
unsigned short val;
mutex_lock(&codec->spdif_mutex);
+ spdif = snd_array_elem(&codec->spdif_out, idx);
if (spdif->nid != nid) {
spdif->nid = nid;
val = spdif->ctls;
@@ -3486,11 +3535,14 @@ static void hda_call_codec_suspend(struct hda_codec *codec)
codec->afg ? codec->afg : codec->mfg,
AC_PWRST_D3);
#ifdef CONFIG_SND_HDA_POWER_SAVE
- snd_hda_update_power_acct(codec);
cancel_delayed_work(&codec->power_work);
+ spin_lock(&codec->power_lock);
+ snd_hda_update_power_acct(codec);
+ trace_hda_power_down(codec);
codec->power_on = 0;
codec->power_transition = 0;
codec->power_jiffies = jiffies;
+ spin_unlock(&codec->power_lock);
#endif
}
@@ -3499,6 +3551,10 @@ static void hda_call_codec_suspend(struct hda_codec *codec)
*/
static void hda_call_codec_resume(struct hda_codec *codec)
{
+ /* set as if powered on for avoiding re-entering the resume
+ * in the resume / power-save sequence
+ */
+ hda_keep_power_on(codec);
hda_set_power_state(codec,
codec->afg ? codec->afg : codec->mfg,
AC_PWRST_D0);
@@ -3514,6 +3570,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
}
+ snd_hda_power_down(codec); /* flag down before returning */
}
#endif /* CONFIG_PM */
@@ -3665,7 +3722,8 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
}
EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
-static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
+static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid,
+ int dir)
{
unsigned int val = 0;
if (nid != codec->afg &&
@@ -3680,11 +3738,12 @@ static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
{
- return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
+ return query_caps_hash(codec, nid, 0, HDA_HASH_PARPCM_KEY(nid),
get_pcm_param);
}
-static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
+static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid,
+ int dir)
{
unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
if (!streams || streams == -1)
@@ -3696,7 +3755,7 @@ static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
{
- return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
+ return query_caps_hash(codec, nid, 0, HDA_HASH_PARSTR_KEY(nid),
get_stream_param);
}
@@ -3775,11 +3834,13 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
bps = 20;
}
}
+#if 0 /* FIXME: CS4206 doesn't work, which is the only codec supporting float */
if (streams & AC_SUPFMT_FLOAT32) {
formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
if (!bps)
bps = 32;
}
+#endif
if (streams == AC_SUPFMT_AC3) {
/* should be exclusive */
/* temporary hack: we have still no proper support
@@ -4283,12 +4344,18 @@ static void hda_power_work(struct work_struct *work)
container_of(work, struct hda_codec, power_work.work);
struct hda_bus *bus = codec->bus;
+ spin_lock(&codec->power_lock);
+ if (codec->power_transition > 0) { /* during power-up sequence? */
+ spin_unlock(&codec->power_lock);
+ return;
+ }
if (!codec->power_on || codec->power_count) {
codec->power_transition = 0;
+ spin_unlock(&codec->power_lock);
return;
}
+ spin_unlock(&codec->power_lock);
- trace_hda_power_down(codec);
hda_call_codec_suspend(codec);
if (bus->ops.pm_notify)
bus->ops.pm_notify(bus);
@@ -4296,9 +4363,11 @@ static void hda_power_work(struct work_struct *work)
static void hda_keep_power_on(struct hda_codec *codec)
{
+ spin_lock(&codec->power_lock);
codec->power_count++;
codec->power_on = 1;
codec->power_jiffies = jiffies;
+ spin_unlock(&codec->power_lock);
}
/* update the power on/off account with the current jiffies */
@@ -4323,19 +4392,31 @@ void snd_hda_power_up(struct hda_codec *codec)
{
struct hda_bus *bus = codec->bus;
+ spin_lock(&codec->power_lock);
codec->power_count++;
- if (codec->power_on || codec->power_transition)
+ if (codec->power_on || codec->power_transition > 0) {
+ spin_unlock(&codec->power_lock);
return;
+ }
+ spin_unlock(&codec->power_lock);
+ cancel_delayed_work_sync(&codec->power_work);
+
+ spin_lock(&codec->power_lock);
trace_hda_power_up(codec);
snd_hda_update_power_acct(codec);
codec->power_on = 1;
codec->power_jiffies = jiffies;
+ codec->power_transition = 1; /* avoid reentrance */
+ spin_unlock(&codec->power_lock);
+
if (bus->ops.pm_notify)
bus->ops.pm_notify(bus);
hda_call_codec_resume(codec);
- cancel_delayed_work(&codec->power_work);
+
+ spin_lock(&codec->power_lock);
codec->power_transition = 0;
+ spin_unlock(&codec->power_lock);
}
EXPORT_SYMBOL_HDA(snd_hda_power_up);
@@ -4351,14 +4432,18 @@ EXPORT_SYMBOL_HDA(snd_hda_power_up);
*/
void snd_hda_power_down(struct hda_codec *codec)
{
+ spin_lock(&codec->power_lock);
--codec->power_count;
- if (!codec->power_on || codec->power_count || codec->power_transition)
+ if (!codec->power_on || codec->power_count || codec->power_transition) {
+ spin_unlock(&codec->power_lock);
return;
+ }
if (power_save(codec)) {
- codec->power_transition = 1; /* avoid reentrance */
+ codec->power_transition = -1; /* avoid reentrance */
queue_delayed_work(codec->bus->workq, &codec->power_work,
msecs_to_jiffies(power_save(codec) * 1000));
}
+ spin_unlock(&codec->power_lock);
}
EXPORT_SYMBOL_HDA(snd_hda_power_down);
@@ -4710,11 +4795,11 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
{
const hda_nid_t *nids = mout->dac_nids;
int chs = substream->runtime->channels;
- struct hda_spdif_out *spdif =
- snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);
+ struct hda_spdif_out *spdif;
int i;
mutex_lock(&codec->spdif_mutex);
+ spdif = snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);
if (mout->dig_out_nid && mout->share_spdif &&
mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
if (chs == 2 &&
@@ -4795,601 +4880,58 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
}
EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
-/*
- * Helper for automatic pin configuration
- */
-
-static int is_in_nid_list(hda_nid_t nid, const hda_nid_t *list)
-{
- for (; *list; list++)
- if (*list == nid)
- return 1;
- return 0;
-}
-
-
-/*
- * Sort an associated group of pins according to their sequence numbers.
- */
-static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,
- int num_pins)
-{
- int i, j;
- short seq;
- hda_nid_t nid;
-
- for (i = 0; i < num_pins; i++) {
- for (j = i + 1; j < num_pins; j++) {
- if (sequences[i] > sequences[j]) {
- seq = sequences[i];
- sequences[i] = sequences[j];
- sequences[j] = seq;
- nid = pins[i];
- pins[i] = pins[j];
- pins[j] = nid;
- }
- }
- }
-}
-
-
-/* add the found input-pin to the cfg->inputs[] table */
-static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid,
- int type)
-{
- if (cfg->num_inputs < AUTO_CFG_MAX_INS) {
- cfg->inputs[cfg->num_inputs].pin = nid;
- cfg->inputs[cfg->num_inputs].type = type;
- cfg->num_inputs++;
- }
-}
-
-/* sort inputs in the order of AUTO_PIN_* type */
-static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg)
-{
- int i, j;
-
- for (i = 0; i < cfg->num_inputs; i++) {
- for (j = i + 1; j < cfg->num_inputs; j++) {
- if (cfg->inputs[i].type > cfg->inputs[j].type) {
- struct auto_pin_cfg_item tmp;
- tmp = cfg->inputs[i];
- cfg->inputs[i] = cfg->inputs[j];
- cfg->inputs[j] = tmp;
- }
- }
- }
-}
-
-/* Reorder the surround channels
- * ALSA sequence is front/surr/clfe/side
- * HDA sequence is:
- * 4-ch: front/surr => OK as it is
- * 6-ch: front/clfe/surr
- * 8-ch: front/clfe/rear/side|fc
- */
-static void reorder_outputs(unsigned int nums, hda_nid_t *pins)
-{
- hda_nid_t nid;
-
- switch (nums) {
- case 3:
- case 4:
- nid = pins[1];
- pins[1] = pins[2];
- pins[2] = nid;
- break;
- }
-}
-
-/*
- * Parse all pin widgets and store the useful pin nids to cfg
- *
- * The number of line-outs or any primary output is stored in line_outs,
- * and the corresponding output pins are assigned to line_out_pins[],
- * in the order of front, rear, CLFE, side, ...
- *
- * If more extra outputs (speaker and headphone) are found, the pins are
- * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
- * is detected, one of speaker of HP pins is assigned as the primary
- * output, i.e. to line_out_pins[0]. So, line_outs is always positive
- * if any analog output exists.
- *
- * The analog input pins are assigned to inputs array.
- * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
- * respectively.
- */
-int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
- struct auto_pin_cfg *cfg,
- const hda_nid_t *ignore_nids,
- unsigned int cond_flags)
-{
- hda_nid_t nid, end_nid;
- short seq, assoc_line_out;
- short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
- short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
- short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
- int i;
-
- memset(cfg, 0, sizeof(*cfg));
-
- memset(sequences_line_out, 0, sizeof(sequences_line_out));
- memset(sequences_speaker, 0, sizeof(sequences_speaker));
- memset(sequences_hp, 0, sizeof(sequences_hp));
- assoc_line_out = 0;
-
- codec->ignore_misc_bit = true;
- end_nid = codec->start_nid + codec->num_nodes;
- for (nid = codec->start_nid; nid < end_nid; nid++) {
- unsigned int wid_caps = get_wcaps(codec, nid);
- unsigned int wid_type = get_wcaps_type(wid_caps);
- unsigned int def_conf;
- short assoc, loc, conn, dev;
-
- /* read all default configuration for pin complex */
- if (wid_type != AC_WID_PIN)
- continue;
- /* ignore the given nids (e.g. pc-beep returns error) */
- if (ignore_nids && is_in_nid_list(nid, ignore_nids))
- continue;
-
- def_conf = snd_hda_codec_get_pincfg(codec, nid);
- if (!(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
- AC_DEFCFG_MISC_NO_PRESENCE))
- codec->ignore_misc_bit = false;
- conn = get_defcfg_connect(def_conf);
- if (conn == AC_JACK_PORT_NONE)
- continue;
- loc = get_defcfg_location(def_conf);
- dev = get_defcfg_device(def_conf);
-
- /* workaround for buggy BIOS setups */
- if (dev == AC_JACK_LINE_OUT) {
- if (conn == AC_JACK_PORT_FIXED)
- dev = AC_JACK_SPEAKER;
- }
-
- switch (dev) {
- case AC_JACK_LINE_OUT:
- seq = get_defcfg_sequence(def_conf);
- assoc = get_defcfg_association(def_conf);
-
- if (!(wid_caps & AC_WCAP_STEREO))
- if (!cfg->mono_out_pin)
- cfg->mono_out_pin = nid;
- if (!assoc)
- continue;
- if (!assoc_line_out)
- assoc_line_out = assoc;
- else if (assoc_line_out != assoc)
- continue;
- if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
- continue;
- cfg->line_out_pins[cfg->line_outs] = nid;
- sequences_line_out[cfg->line_outs] = seq;
- cfg->line_outs++;
- break;
- case AC_JACK_SPEAKER:
- seq = get_defcfg_sequence(def_conf);
- assoc = get_defcfg_association(def_conf);
- if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
- continue;
- cfg->speaker_pins[cfg->speaker_outs] = nid;
- sequences_speaker[cfg->speaker_outs] = (assoc << 4) | seq;
- cfg->speaker_outs++;
- break;
- case AC_JACK_HP_OUT:
- seq = get_defcfg_sequence(def_conf);
- assoc = get_defcfg_association(def_conf);
- if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
- continue;
- cfg->hp_pins[cfg->hp_outs] = nid;
- sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
- cfg->hp_outs++;
- break;
- case AC_JACK_MIC_IN:
- add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC);
- break;
- case AC_JACK_LINE_IN:
- add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN);
- break;
- case AC_JACK_CD:
- add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD);
- break;
- case AC_JACK_AUX:
- add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX);
- break;
- case AC_JACK_SPDIF_OUT:
- case AC_JACK_DIG_OTHER_OUT:
- if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))
- continue;
- cfg->dig_out_pins[cfg->dig_outs] = nid;
- cfg->dig_out_type[cfg->dig_outs] =
- (loc == AC_JACK_LOC_HDMI) ?
- HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
- cfg->dig_outs++;
- break;
- case AC_JACK_SPDIF_IN:
- case AC_JACK_DIG_OTHER_IN:
- cfg->dig_in_pin = nid;
- if (loc == AC_JACK_LOC_HDMI)
- cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
- else
- cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
- break;
- }
- }
-
- /* FIX-UP:
- * If no line-out is defined but multiple HPs are found,
- * some of them might be the real line-outs.
- */
- if (!cfg->line_outs && cfg->hp_outs > 1 &&
- !(cond_flags & HDA_PINCFG_NO_HP_FIXUP)) {
- int i = 0;
- while (i < cfg->hp_outs) {
- /* The real HPs should have the sequence 0x0f */
- if ((sequences_hp[i] & 0x0f) == 0x0f) {
- i++;
- continue;
- }
- /* Move it to the line-out table */
- cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
- sequences_line_out[cfg->line_outs] = sequences_hp[i];
- cfg->line_outs++;
- cfg->hp_outs--;
- memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
- sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
- memmove(sequences_hp + i, sequences_hp + i + 1,
- sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
- }
- memset(cfg->hp_pins + cfg->hp_outs, 0,
- sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs));
- if (!cfg->hp_outs)
- cfg->line_out_type = AUTO_PIN_HP_OUT;
-
- }
-
- /* sort by sequence */
- sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
- cfg->line_outs);
- sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
- cfg->speaker_outs);
- sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
- cfg->hp_outs);
-
- /*
- * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
- * as a primary output
- */
- if (!cfg->line_outs &&
- !(cond_flags & HDA_PINCFG_NO_LO_FIXUP)) {
- if (cfg->speaker_outs) {
- cfg->line_outs = cfg->speaker_outs;
- memcpy(cfg->line_out_pins, cfg->speaker_pins,
- sizeof(cfg->speaker_pins));
- cfg->speaker_outs = 0;
- memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
- cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
- } else if (cfg->hp_outs) {
- cfg->line_outs = cfg->hp_outs;
- memcpy(cfg->line_out_pins, cfg->hp_pins,
- sizeof(cfg->hp_pins));
- cfg->hp_outs = 0;
- memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
- cfg->line_out_type = AUTO_PIN_HP_OUT;
- }
- }
-
- reorder_outputs(cfg->line_outs, cfg->line_out_pins);
- reorder_outputs(cfg->hp_outs, cfg->hp_pins);
- reorder_outputs(cfg->speaker_outs, cfg->speaker_pins);
-
- sort_autocfg_input_pins(cfg);
-
- /*
- * debug prints of the parsed results
- */
- snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n",
- cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
- cfg->line_out_pins[2], cfg->line_out_pins[3],
- cfg->line_out_pins[4],
- cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" :
- (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ?
- "speaker" : "line"));
- snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
- cfg->speaker_outs, cfg->speaker_pins[0],
- cfg->speaker_pins[1], cfg->speaker_pins[2],
- cfg->speaker_pins[3], cfg->speaker_pins[4]);
- snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
- cfg->hp_outs, cfg->hp_pins[0],
- cfg->hp_pins[1], cfg->hp_pins[2],
- cfg->hp_pins[3], cfg->hp_pins[4]);
- snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
- if (cfg->dig_outs)
- snd_printd(" dig-out=0x%x/0x%x\n",
- cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
- snd_printd(" inputs:");
- for (i = 0; i < cfg->num_inputs; i++) {
- snd_printd(" %s=0x%x",
- hda_get_autocfg_input_label(codec, cfg, i),
- cfg->inputs[i].pin);
- }
- snd_printd("\n");
- if (cfg->dig_in_pin)
- snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
-
- return 0;
-}
-EXPORT_SYMBOL_HDA(snd_hda_parse_pin_defcfg);
-
-int snd_hda_get_input_pin_attr(unsigned int def_conf)
-{
- unsigned int loc = get_defcfg_location(def_conf);
- unsigned int conn = get_defcfg_connect(def_conf);
- if (conn == AC_JACK_PORT_NONE)
- return INPUT_PIN_ATTR_UNUSED;
- /* Windows may claim the internal mic to be BOTH, too */
- if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH)
- return INPUT_PIN_ATTR_INT;
- if ((loc & 0x30) == AC_JACK_LOC_INTERNAL)
- return INPUT_PIN_ATTR_INT;
- if ((loc & 0x30) == AC_JACK_LOC_SEPARATE)
- return INPUT_PIN_ATTR_DOCK;
- if (loc == AC_JACK_LOC_REAR)
- return INPUT_PIN_ATTR_REAR;
- if (loc == AC_JACK_LOC_FRONT)
- return INPUT_PIN_ATTR_FRONT;
- return INPUT_PIN_ATTR_NORMAL;
-}
-EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr);
-
-/**
- * hda_get_input_pin_label - Give a label for the given input pin
- *
- * When check_location is true, the function checks the pin location
- * for mic and line-in pins, and set an appropriate prefix like "Front",
- * "Rear", "Internal".
- */
-
-static const char *hda_get_input_pin_label(struct hda_codec *codec,
- hda_nid_t pin, bool check_location)
-{
- unsigned int def_conf;
- static const char * const mic_names[] = {
- "Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic",
- };
- int attr;
-
- def_conf = snd_hda_codec_get_pincfg(codec, pin);
-
- switch (get_defcfg_device(def_conf)) {
- case AC_JACK_MIC_IN:
- if (!check_location)
- return "Mic";
- attr = snd_hda_get_input_pin_attr(def_conf);
- if (!attr)
- return "None";
- return mic_names[attr - 1];
- case AC_JACK_LINE_IN:
- if (!check_location)
- return "Line";
- attr = snd_hda_get_input_pin_attr(def_conf);
- if (!attr)
- return "None";
- if (attr == INPUT_PIN_ATTR_DOCK)
- return "Dock Line";
- return "Line";
- case AC_JACK_AUX:
- return "Aux";
- case AC_JACK_CD:
- return "CD";
- case AC_JACK_SPDIF_IN:
- return "SPDIF In";
- case AC_JACK_DIG_OTHER_IN:
- return "Digital In";
- default:
- return "Misc";
- }
-}
-
-/* Check whether the location prefix needs to be added to the label.
- * If all mic-jacks are in the same location (e.g. rear panel), we don't
- * have to put "Front" prefix to each label. In such a case, returns false.
- */
-static int check_mic_location_need(struct hda_codec *codec,
- const struct auto_pin_cfg *cfg,
- int input)
-{
- unsigned int defc;
- int i, attr, attr2;
-
- defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin);
- attr = snd_hda_get_input_pin_attr(defc);
- /* for internal or docking mics, we need locations */
- if (attr <= INPUT_PIN_ATTR_NORMAL)
- return 1;
-
- attr = 0;
- for (i = 0; i < cfg->num_inputs; i++) {
- defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin);
- attr2 = snd_hda_get_input_pin_attr(defc);
- if (attr2 >= INPUT_PIN_ATTR_NORMAL) {
- if (attr && attr != attr2)
- return 1; /* different locations found */
- attr = attr2;
- }
- }
- return 0;
-}
-
/**
- * hda_get_autocfg_input_label - Get a label for the given input
+ * snd_hda_get_default_vref - Get the default (mic) VREF pin bits
*
- * Get a label for the given input pin defined by the autocfg item.
- * Unlike hda_get_input_pin_label(), this function checks all inputs
- * defined in autocfg and avoids the redundant mic/line prefix as much as
- * possible.
- */
-const char *hda_get_autocfg_input_label(struct hda_codec *codec,
- const struct auto_pin_cfg *cfg,
- int input)
-{
- int type = cfg->inputs[input].type;
- int has_multiple_pins = 0;
-
- if ((input > 0 && cfg->inputs[input - 1].type == type) ||
- (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type))
- has_multiple_pins = 1;
- if (has_multiple_pins && type == AUTO_PIN_MIC)
- has_multiple_pins &= check_mic_location_need(codec, cfg, input);
- return hda_get_input_pin_label(codec, cfg->inputs[input].pin,
- has_multiple_pins);
-}
-EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);
-
-/* return the position of NID in the list, or -1 if not found */
-static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
-{
- int i;
- for (i = 0; i < nums; i++)
- if (list[i] == nid)
- return i;
- return -1;
-}
-
-/* get a unique suffix or an index number */
-static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins,
- int num_pins, int *indexp)
-{
- static const char * const channel_sfx[] = {
- " Front", " Surround", " CLFE", " Side"
- };
- int i;
-
- i = find_idx_in_nid_list(nid, pins, num_pins);
- if (i < 0)
- return NULL;
- if (num_pins == 1)
- return "";
- if (num_pins > ARRAY_SIZE(channel_sfx)) {
- if (indexp)
- *indexp = i;
- return "";
- }
- return channel_sfx[i];
-}
-
-static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,
- const struct auto_pin_cfg *cfg,
- const char *name, char *label, int maxlen,
- int *indexp)
-{
- unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
- int attr = snd_hda_get_input_pin_attr(def_conf);
- const char *pfx = "", *sfx = "";
-
- /* handle as a speaker if it's a fixed line-out */
- if (!strcmp(name, "Line Out") && attr == INPUT_PIN_ATTR_INT)
- name = "Speaker";
- /* check the location */
- switch (attr) {
- case INPUT_PIN_ATTR_DOCK:
- pfx = "Dock ";
- break;
- case INPUT_PIN_ATTR_FRONT:
- pfx = "Front ";
- break;
- }
- if (cfg) {
- /* try to give a unique suffix if needed */
- sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs,
- indexp);
- if (!sfx)
- sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs,
- indexp);
- if (!sfx) {
- /* don't add channel suffix for Headphone controls */
- int idx = find_idx_in_nid_list(nid, cfg->hp_pins,
- cfg->hp_outs);
- if (idx >= 0)
- *indexp = idx;
- sfx = "";
+ * Guess the suitable VREF pin bits to be set as the pin-control value.
+ * Note: the function doesn't set the AC_PINCTL_IN_EN bit.
+ */
+unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin)
+{
+ unsigned int pincap;
+ unsigned int oldval;
+ oldval = snd_hda_codec_read(codec, pin, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ pincap = snd_hda_query_pin_caps(codec, pin);
+ pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
+ /* Exception: if the default pin setup is vref50, we give it priority */
+ if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
+ return AC_PINCTL_VREF_80;
+ else if (pincap & AC_PINCAP_VREF_50)
+ return AC_PINCTL_VREF_50;
+ else if (pincap & AC_PINCAP_VREF_100)
+ return AC_PINCTL_VREF_100;
+ else if (pincap & AC_PINCAP_VREF_GRD)
+ return AC_PINCTL_VREF_GRD;
+ return AC_PINCTL_VREF_HIZ;
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_default_vref);
+
+int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
+ unsigned int val, bool cached)
+{
+ if (val) {
+ unsigned int cap = snd_hda_query_pin_caps(codec, pin);
+ if (cap && (val & AC_PINCTL_OUT_EN)) {
+ if (!(cap & AC_PINCAP_OUT))
+ val &= ~(AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
+ else if ((val & AC_PINCTL_HP_EN) &&
+ !(cap & AC_PINCAP_HP_DRV))
+ val &= ~AC_PINCTL_HP_EN;
}
- }
- snprintf(label, maxlen, "%s%s%s", pfx, name, sfx);
- return 1;
-}
-
-/**
- * snd_hda_get_pin_label - Get a label for the given I/O pin
- *
- * Get a label for the given pin. This function works for both input and
- * output pins. When @cfg is given as non-NULL, the function tries to get
- * an optimized label using hda_get_autocfg_input_label().
- *
- * This function tries to give a unique label string for the pin as much as
- * possible. For example, when the multiple line-outs are present, it adds
- * the channel suffix like "Front", "Surround", etc (only when @cfg is given).
- * If no unique name with a suffix is available and @indexp is non-NULL, the
- * index number is stored in the pointer.
- */
-int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
- const struct auto_pin_cfg *cfg,
- char *label, int maxlen, int *indexp)
-{
- unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
- const char *name = NULL;
- int i;
-
- if (indexp)
- *indexp = 0;
- if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
- return 0;
-
- switch (get_defcfg_device(def_conf)) {
- case AC_JACK_LINE_OUT:
- return fill_audio_out_name(codec, nid, cfg, "Line Out",
- label, maxlen, indexp);
- case AC_JACK_SPEAKER:
- return fill_audio_out_name(codec, nid, cfg, "Speaker",
- label, maxlen, indexp);
- case AC_JACK_HP_OUT:
- return fill_audio_out_name(codec, nid, cfg, "Headphone",
- label, maxlen, indexp);
- case AC_JACK_SPDIF_OUT:
- case AC_JACK_DIG_OTHER_OUT:
- if (get_defcfg_location(def_conf) == AC_JACK_LOC_HDMI)
- name = "HDMI";
- else
- name = "SPDIF";
- if (cfg && indexp) {
- i = find_idx_in_nid_list(nid, cfg->dig_out_pins,
- cfg->dig_outs);
- if (i >= 0)
- *indexp = i;
- }
- break;
- default:
- if (cfg) {
- for (i = 0; i < cfg->num_inputs; i++) {
- if (cfg->inputs[i].pin != nid)
- continue;
- name = hda_get_autocfg_input_label(codec, cfg, i);
- if (name)
- break;
- }
+ if (cap && (val & AC_PINCTL_IN_EN)) {
+ if (!(cap & AC_PINCAP_IN))
+ val &= ~(AC_PINCTL_IN_EN | AC_PINCTL_VREFEN);
}
- if (!name)
- name = hda_get_input_pin_label(codec, nid, true);
- break;
}
- if (!name)
- return 0;
- strlcpy(label, name, maxlen);
- return 1;
+ if (cached)
+ return snd_hda_codec_update_cache(codec, pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ else
+ return snd_hda_codec_write(codec, pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);
}
-EXPORT_SYMBOL_HDA(snd_hda_get_pin_label);
+EXPORT_SYMBOL_HDA(_snd_hda_set_pin_ctl);
/**
* snd_hda_add_imux_item - Add an item to input_mux
@@ -5444,8 +4986,6 @@ int snd_hda_suspend(struct hda_bus *bus)
list_for_each_entry(codec, &bus->codec_list, list) {
if (hda_codec_is_power_on(codec))
hda_call_codec_suspend(codec);
- if (codec->patch_ops.post_suspend)
- codec->patch_ops.post_suspend(codec);
}
return 0;
}
@@ -5465,10 +5005,7 @@ int snd_hda_resume(struct hda_bus *bus)
struct hda_codec *codec;
list_for_each_entry(codec, &bus->codec_list, list) {
- if (codec->patch_ops.pre_resume)
- codec->patch_ops.pre_resume(codec);
- if (snd_hda_codec_needs_resume(codec))
- hda_call_codec_resume(codec);
+ hda_call_codec_resume(codec);
}
return 0;
}
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 56b4f74c0b13..54b52819fb47 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -704,8 +704,6 @@ struct hda_codec_ops {
unsigned int power_state);
#ifdef CONFIG_PM
int (*suspend)(struct hda_codec *codec, pm_message_t state);
- int (*post_suspend)(struct hda_codec *codec);
- int (*pre_resume)(struct hda_codec *codec);
int (*resume)(struct hda_codec *codec);
#endif
#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -829,6 +827,7 @@ struct hda_codec {
struct mutex spdif_mutex;
struct mutex control_mutex;
+ struct mutex hash_mutex;
struct snd_array spdif_out;
unsigned int spdif_in_enable; /* SPDIF input enable? */
const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
@@ -861,12 +860,13 @@ struct hda_codec {
unsigned int no_jack_detect:1; /* Machine has no jack-detection */
#ifdef CONFIG_SND_HDA_POWER_SAVE
unsigned int power_on :1; /* current (global) power-state */
- unsigned int power_transition :1; /* power-state in transition */
+ int power_transition; /* power-state in transition */
int power_count; /* current (global) power refcount */
struct delayed_work power_work; /* delayed task for powerdown */
unsigned long power_on_acct;
unsigned long power_off_acct;
unsigned long power_jiffies;
+ spinlock_t power_lock;
#endif
/* codec-specific additional proc output */
@@ -911,10 +911,13 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
hda_nid_t *start_id);
int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
hda_nid_t *conn_list, int max_conns);
+static inline int
+snd_hda_get_num_conns(struct hda_codec *codec, hda_nid_t nid)
+{
+ return snd_hda_get_connections(codec, nid, NULL, 0);
+}
int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
hda_nid_t *conn_list, int max_conns);
-int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
- const hda_nid_t **listp);
int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums,
const hda_nid_t *list);
int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
@@ -1051,12 +1054,10 @@ const char *snd_hda_get_jack_location(u32 cfg);
#ifdef CONFIG_SND_HDA_POWER_SAVE
void snd_hda_power_up(struct hda_codec *codec);
void snd_hda_power_down(struct hda_codec *codec);
-#define snd_hda_codec_needs_resume(codec) codec->power_count
void snd_hda_update_power_acct(struct hda_codec *codec);
#else
static inline void snd_hda_power_up(struct hda_codec *codec) {}
static inline void snd_hda_power_down(struct hda_codec *codec) {}
-#define snd_hda_codec_needs_resume(codec) 1
#endif
#ifdef CONFIG_SND_HDA_PATCH_LOADER
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 1f350522bed4..4ab8102f87ea 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -497,6 +497,7 @@ enum {
AZX_DRIVER_NVIDIA,
AZX_DRIVER_TERA,
AZX_DRIVER_CTX,
+ AZX_DRIVER_CTHDA,
AZX_DRIVER_GENERIC,
AZX_NUM_DRIVERS, /* keep this as last entry */
};
@@ -518,6 +519,7 @@ enum {
#define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */
#define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */
#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */
+#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */
/* quirks for ATI SB / AMD Hudson */
#define AZX_DCAPS_PRESET_ATI_SB \
@@ -533,6 +535,9 @@ enum {
(AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI |\
AZX_DCAPS_ALIGN_BUFSIZE)
+#define AZX_DCAPS_PRESET_CTHDA \
+ (AZX_DCAPS_NO_MSI | AZX_DCAPS_POSFIX_LPIB | AZX_DCAPS_4K_BDLE_BOUNDARY)
+
static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_ICH] = "HDA Intel",
[AZX_DRIVER_PCH] = "HDA Intel PCH",
@@ -546,6 +551,7 @@ static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_NVIDIA] = "HDA NVidia",
[AZX_DRIVER_TERA] = "HDA Teradici",
[AZX_DRIVER_CTX] = "HDA Creative",
+ [AZX_DRIVER_CTHDA] = "HDA Creative",
[AZX_DRIVER_GENERIC] = "HD-Audio Generic",
};
@@ -1285,7 +1291,8 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
/*
* set up a BDL entry
*/
-static int setup_bdle(struct snd_pcm_substream *substream,
+static int setup_bdle(struct azx *chip,
+ struct snd_pcm_substream *substream,
struct azx_dev *azx_dev, u32 **bdlp,
int ofs, int size, int with_ioc)
{
@@ -1304,6 +1311,12 @@ static int setup_bdle(struct snd_pcm_substream *substream,
bdl[1] = cpu_to_le32(upper_32_bits(addr));
/* program the size field of the BDL entry */
chunk = snd_pcm_sgbuf_get_chunk_size(substream, ofs, size);
+ /* one BDLE cannot cross 4K boundary on CTHDA chips */
+ if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY) {
+ u32 remain = 0x1000 - (ofs & 0xfff);
+ if (chunk > remain)
+ chunk = remain;
+ }
bdl[2] = cpu_to_le32(chunk);
/* program the IOC to enable interrupt
* only when the whole fragment is processed
@@ -1356,7 +1369,7 @@ static int azx_setup_periods(struct azx *chip,
bdl_pos_adj[chip->dev_index]);
pos_adj = 0;
} else {
- ofs = setup_bdle(substream, azx_dev,
+ ofs = setup_bdle(chip, substream, azx_dev,
&bdl, ofs, pos_adj,
!substream->runtime->no_period_wakeup);
if (ofs < 0)
@@ -1366,10 +1379,10 @@ static int azx_setup_periods(struct azx *chip,
pos_adj = 0;
for (i = 0; i < periods; i++) {
if (i == periods - 1 && pos_adj)
- ofs = setup_bdle(substream, azx_dev, &bdl, ofs,
+ ofs = setup_bdle(chip, substream, azx_dev, &bdl, ofs,
period_bytes - pos_adj, 0);
else
- ofs = setup_bdle(substream, azx_dev, &bdl, ofs,
+ ofs = setup_bdle(chip, substream, azx_dev, &bdl, ofs,
period_bytes,
!substream->runtime->no_period_wakeup);
if (ofs < 0)
@@ -2353,17 +2366,6 @@ static void azx_power_notify(struct hda_bus *bus)
* power management
*/
-static int snd_hda_codecs_inuse(struct hda_bus *bus)
-{
- struct hda_codec *codec;
-
- list_for_each_entry(codec, &bus->codec_list, list) {
- if (snd_hda_codec_needs_resume(codec))
- return 1;
- }
- return 0;
-}
-
static int azx_suspend(struct pci_dev *pci, pm_message_t state)
{
struct snd_card *card = pci_get_drvdata(pci);
@@ -2410,8 +2412,7 @@ static int azx_resume(struct pci_dev *pci)
return -EIO;
azx_init_pci(chip);
- if (snd_hda_codecs_inuse(chip->bus))
- azx_init_chip(chip, 1);
+ azx_init_chip(chip, 1);
snd_hda_resume(chip->bus);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -2565,6 +2566,8 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
/* forced codec slots */
SND_PCI_QUIRK(0x1043, 0x1262, "ASUS W5Fm", 0x103),
SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103),
+ /* WinFast VP200 H (Teradici) user reported broken communication */
+ SND_PCI_QUIRK(0x3a21, 0x040d, "WinFast VP200 H", 0x101),
{}
};
@@ -3130,6 +3133,11 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
.driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
#endif
+ /* CTHDA chips */
+ { PCI_DEVICE(0x1102, 0x0010),
+ .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA },
+ { PCI_DEVICE(0x1102, 0x0012),
+ .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA },
/* Vortex86MX */
{ PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC },
/* VMware HDAudio */
@@ -3148,7 +3156,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
MODULE_DEVICE_TABLE(pci, azx_ids);
/* pci_driver definition */
-static struct pci_driver driver = {
+static struct pci_driver azx_driver = {
.name = KBUILD_MODNAME,
.id_table = azx_ids,
.probe = azx_probe,
@@ -3159,15 +3167,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_azx_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_azx_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_azx_init)
-module_exit(alsa_card_azx_exit)
+module_pci_driver(azx_driver);
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index d68948499fbc..2dd1c113a4c1 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -17,6 +17,7 @@
#include <sound/jack.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_auto_parser.h"
#include "hda_jack.h"
bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index c66655cf413a..8ae52465ec5d 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -12,6 +12,8 @@
#ifndef __SOUND_HDA_JACK_H
#define __SOUND_HDA_JACK_H
+struct auto_pin_cfg;
+
struct hda_jack_tbl {
hda_nid_t nid;
unsigned char action; /* event action (0 = none) */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 0ec9248165bc..9a096a8e0fc5 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -262,6 +262,8 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
const struct hda_input_mux *imux,
struct snd_ctl_elem_value *ucontrol, hda_nid_t nid,
unsigned int *cur_val);
+int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
+ int index, int *type_index_ret);
/*
* Channel mode helper
@@ -393,72 +395,7 @@ struct hda_bus_unsolicited {
struct hda_bus *bus;
};
-/*
- * Helper for automatic pin configuration
- */
-
-enum {
- AUTO_PIN_MIC,
- AUTO_PIN_LINE_IN,
- AUTO_PIN_CD,
- AUTO_PIN_AUX,
- AUTO_PIN_LAST
-};
-
-enum {
- AUTO_PIN_LINE_OUT,
- AUTO_PIN_SPEAKER_OUT,
- AUTO_PIN_HP_OUT
-};
-
-#define AUTO_CFG_MAX_OUTS HDA_MAX_OUTS
-#define AUTO_CFG_MAX_INS 8
-
-struct auto_pin_cfg_item {
- hda_nid_t pin;
- int type;
-};
-
-struct auto_pin_cfg;
-const char *hda_get_autocfg_input_label(struct hda_codec *codec,
- const struct auto_pin_cfg *cfg,
- int input);
-int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
- const struct auto_pin_cfg *cfg,
- char *label, int maxlen, int *indexp);
-int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
- int index, int *type_index_ret);
-
-enum {
- INPUT_PIN_ATTR_UNUSED, /* pin not connected */
- INPUT_PIN_ATTR_INT, /* internal mic/line-in */
- INPUT_PIN_ATTR_DOCK, /* docking mic/line-in */
- INPUT_PIN_ATTR_NORMAL, /* mic/line-in jack */
- INPUT_PIN_ATTR_FRONT, /* mic/line-in jack in front */
- INPUT_PIN_ATTR_REAR, /* mic/line-in jack in rear */
-};
-
-int snd_hda_get_input_pin_attr(unsigned int def_conf);
-
-struct auto_pin_cfg {
- int line_outs;
- /* sorted in the order of Front/Surr/CLFE/Side */
- hda_nid_t line_out_pins[AUTO_CFG_MAX_OUTS];
- int speaker_outs;
- hda_nid_t speaker_pins[AUTO_CFG_MAX_OUTS];
- int hp_outs;
- int line_out_type; /* AUTO_PIN_XXX_OUT */
- hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS];
- int num_inputs;
- struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS];
- int dig_outs;
- hda_nid_t dig_out_pins[2];
- hda_nid_t dig_in_pin;
- hda_nid_t mono_out_pin;
- int dig_out_type[2]; /* HDA_PCM_TYPE_XXX */
- int dig_in_type; /* HDA_PCM_TYPE_XXX */
-};
-
+/* helper macros to retrieve pin default-config values */
#define get_defcfg_connect(cfg) \
((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT)
#define get_defcfg_association(cfg) \
@@ -472,19 +409,6 @@ struct auto_pin_cfg {
#define get_defcfg_misc(cfg) \
((cfg & AC_DEFCFG_MISC) >> AC_DEFCFG_MISC_SHIFT)
-/* bit-flags for snd_hda_parse_pin_def_config() behavior */
-#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */
-#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */
-
-int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
- struct auto_pin_cfg *cfg,
- const hda_nid_t *ignore_nids,
- unsigned int cond_flags);
-
-/* older function */
-#define snd_hda_parse_pin_def_config(codec, cfg, ignore) \
- snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0)
-
/* amp values */
#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
@@ -502,6 +426,46 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
#define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN)
#define PIN_HP_AMP (AC_PINCTL_HP_EN)
+unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin);
+int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
+ unsigned int val, bool cached);
+
+/**
+ * _snd_hda_set_pin_ctl - Set a pin-control value safely
+ * @codec: the codec instance
+ * @pin: the pin NID to set the control
+ * @val: the pin-control value (AC_PINCTL_* bits)
+ *
+ * This function sets the pin-control value to the given pin, but
+ * filters out the invalid pin-control bits when the pin has no such
+ * capabilities. For example, when PIN_HP is passed but the pin has no
+ * HP-drive capability, the HP bit is omitted.
+ *
+ * The function doesn't check the input VREF capability bits, though.
+ * Use snd_hda_get_default_vref() to guess the right value.
+ * Also, this function is only for analog pins, not for HDMI pins.
+ */
+static inline int
+snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin, unsigned int val)
+{
+ return _snd_hda_set_pin_ctl(codec, pin, val, false);
+}
+
+/**
+ * snd_hda_set_pin_ctl_cache - Set a pin-control value safely
+ * @codec: the codec instance
+ * @pin: the pin NID to set the control
+ * @val: the pin-control value (AC_PINCTL_* bits)
+ *
+ * Just like snd_hda_set_pin_ctl() but write to cache as well.
+ */
+static inline int
+snd_hda_set_pin_ctl_cache(struct hda_codec *codec, hda_nid_t pin,
+ unsigned int val)
+{
+ return _snd_hda_set_pin_ctl(codec, pin, val, true);
+}
+
/*
* get widget capabilities
*/
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 7143393927da..d8b2d6dee986 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -28,6 +28,7 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_auto_parser.h"
#include "hda_beep.h"
#include "hda_jack.h"
@@ -1742,9 +1743,7 @@ static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
if (! ad198x_eapd_put(kcontrol, ucontrol))
return 0;
/* change speaker pin appropriately */
- snd_hda_codec_write(codec, 0x05, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- spec->cur_eapd ? PIN_OUT : 0);
+ snd_hda_set_pin_ctl(codec, 0x05, spec->cur_eapd ? PIN_OUT : 0);
/* toggle HP mute appropriately */
snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
HDA_AMP_MUTE,
@@ -3103,7 +3102,7 @@ static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
int dac_idx)
{
/* set as output */
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+ snd_hda_set_pin_ctl(codec, nid, pin_type);
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
switch (nid) {
case 0x11: /* port-A - DAC 03 */
@@ -3157,6 +3156,7 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec)
for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = cfg->inputs[i].pin;
int type = cfg->inputs[i].type;
+ int val;
switch (nid) {
case 0x15: /* port-C */
snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
@@ -3165,8 +3165,10 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec)
snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
break;
}
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- type == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
+ val = PIN_IN;
+ if (type == AUTO_PIN_MIC)
+ val |= snd_hda_get_default_vref(codec, nid);
+ snd_hda_set_pin_ctl(codec, nid, val);
if (nid != AD1988_PIN_CD_NID)
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
AMP_OUT_MUTE);
diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c
index 09ccfabb4a17..19ae14f739cb 100644
--- a/sound/pci/hda/patch_ca0110.c
+++ b/sound/pci/hda/patch_ca0110.c
@@ -26,6 +26,7 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_auto_parser.h"
/*
*/
@@ -341,8 +342,7 @@ static int ca0110_build_pcms(struct hda_codec *codec)
static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
{
if (pin) {
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
+ snd_hda_set_pin_ctl(codec, pin, PIN_HP);
if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)
snd_hda_codec_write(codec, pin, 0,
AC_VERB_SET_AMP_GAIN_MUTE,
@@ -356,8 +356,8 @@ static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
{
if (pin) {
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80);
+ snd_hda_set_pin_ctl(codec, pin, PIN_IN |
+ snd_hda_get_default_vref(codec, pin));
if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP)
snd_hda_codec_write(codec, pin, 0,
AC_VERB_SET_AMP_GAIN_MUTE,
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 21d91d580da8..d0d3540e39e7 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -30,6 +30,7 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_auto_parser.h"
#define WIDGET_CHIP_CTRL 0x15
#define WIDGET_DSP_CTRL 0x16
@@ -239,8 +240,7 @@ enum get_set {
static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
{
if (pin) {
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
+ snd_hda_set_pin_ctl(codec, pin, PIN_HP);
if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)
snd_hda_codec_write(codec, pin, 0,
AC_VERB_SET_AMP_GAIN_MUTE,
@@ -254,9 +254,8 @@ static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
{
if (pin) {
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- PIN_VREF80);
+ snd_hda_set_pin_ctl(codec, pin, PIN_IN |
+ snd_hda_get_default_vref(codec, pin));
if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP)
snd_hda_codec_write(codec, pin, 0,
AC_VERB_SET_AMP_GAIN_MUTE,
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index c83ccdba1e5a..9647ed4d7929 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -26,6 +26,7 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_auto_parser.h"
#include "hda_jack.h"
#include <sound/tlv.h>
@@ -933,8 +934,7 @@ static void cs_automute(struct hda_codec *codec)
pin_ctl = 0;
nid = cfg->speaker_pins[i];
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, pin_ctl);
+ snd_hda_set_pin_ctl(codec, nid, pin_ctl);
}
if (spec->gpio_eapd_hp) {
unsigned int gpio = hp_present ?
@@ -948,16 +948,14 @@ static void cs_automute(struct hda_codec *codec)
/* mute HPs if spdif jack (SENSE_B) is present */
for (i = 0; i < cfg->hp_outs; i++) {
nid = cfg->hp_pins[i];
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
+ snd_hda_set_pin_ctl(codec, nid,
(spdif_present && spec->sense_b) ? 0 : PIN_HP);
}
/* SPDIF TX on/off */
if (cfg->dig_outs) {
nid = cfg->dig_out_pins[0];
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
+ snd_hda_set_pin_ctl(codec, nid,
spdif_present ? PIN_OUT : 0);
}
@@ -1024,13 +1022,11 @@ static void init_output(struct hda_codec *codec)
/* set appropriate pin controls */
for (i = 0; i < cfg->line_outs; i++)
- snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+ snd_hda_set_pin_ctl(codec, cfg->line_out_pins[i], PIN_OUT);
/* HP */
for (i = 0; i < cfg->hp_outs; i++) {
hda_nid_t nid = cfg->hp_pins[i];
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
+ snd_hda_set_pin_ctl(codec, nid, PIN_HP);
if (!cfg->speaker_outs)
continue;
if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
@@ -1041,8 +1037,7 @@ static void init_output(struct hda_codec *codec)
/* Speaker */
for (i = 0; i < cfg->speaker_outs; i++)
- snd_hda_codec_write(codec, cfg->speaker_pins[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+ snd_hda_set_pin_ctl(codec, cfg->speaker_pins[i], PIN_OUT);
/* SPDIF is enabled on presence detect for CS421x */
if (spec->hp_detect || spec->spdif_detect)
@@ -1063,14 +1058,9 @@ static void init_input(struct hda_codec *codec)
continue;
/* set appropriate pin control and mute first */
ctl = PIN_IN;
- if (cfg->inputs[i].type == AUTO_PIN_MIC) {
- unsigned int caps = snd_hda_query_pin_caps(codec, pin);
- caps >>= AC_PINCAP_VREF_SHIFT;
- if (caps & AC_PINCAP_VREF_80)
- ctl = PIN_VREF80;
- }
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, ctl);
+ if (cfg->inputs[i].type == AUTO_PIN_MIC)
+ ctl |= snd_hda_get_default_vref(codec, pin);
+ snd_hda_set_pin_ctl(codec, pin, ctl);
snd_hda_codec_write(codec, spec->adc_nid[i], 0,
AC_VERB_SET_AMP_GAIN_MUTE,
AMP_IN_MUTE(spec->adc_idx[i]));
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index b6767b4ced44..c8fdaaefe702 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -29,6 +29,7 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_auto_parser.h"
#define NUM_PINS 11
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index d906c5b74cf0..3acb5824ad39 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -30,6 +30,7 @@
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_auto_parser.h"
#include "hda_beep.h"
#include "hda_jack.h"
@@ -66,6 +67,7 @@ struct imux_info {
};
struct conexant_spec {
+ struct hda_gen_spec gen;
const struct snd_kcontrol_new *mixers[5];
int num_mixers;
@@ -141,6 +143,7 @@ struct conexant_spec {
unsigned int hp_laptop:1;
unsigned int asus:1;
unsigned int pin_eapd_ctrls:1;
+ unsigned int fixup_stereo_dmic:1;
unsigned int adc_switching:1;
@@ -1601,17 +1604,13 @@ static void cxt5051_update_speaker(struct hda_codec *codec)
unsigned int pinctl;
/* headphone pin */
pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0;
- snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- pinctl);
+ snd_hda_set_pin_ctl(codec, 0x16, pinctl);
/* speaker pin */
pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- pinctl);
+ snd_hda_set_pin_ctl(codec, 0x1a, pinctl);
/* on ideapad there is an additional speaker (subwoofer) to mute */
if (spec->ideapad)
- snd_hda_codec_write(codec, 0x1b, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- pinctl);
+ snd_hda_set_pin_ctl(codec, 0x1b, pinctl);
}
/* turn on/off EAPD (+ mute HP) as a master switch */
@@ -1996,8 +1995,7 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
/* Port A (HP) */
pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0;
- snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- pinctl);
+ snd_hda_set_pin_ctl(codec, 0x19, pinctl);
/* Port D (HP/LO) */
pinctl = spec->cur_eapd ? spec->port_d_mode : 0;
@@ -2010,13 +2008,11 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
if (!hp_port_d_present(spec))
pinctl = 0;
}
- snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- pinctl);
+ snd_hda_set_pin_ctl(codec, 0x1c, pinctl);
/* CLASS_D AMP */
pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- pinctl);
+ snd_hda_set_pin_ctl(codec, 0x1f, pinctl);
}
/* turn on/off EAPD (+ mute HP) as a master switch */
@@ -2047,8 +2043,7 @@ static int cxt5066_set_olpc_dc_bias(struct hda_codec *codec)
/* Even though port F is the DC input, the bias is controlled on port B.
* we also leave that port as an active input (but unselected) in DC mode
* just in case that is necessary to make the bias setting take effect. */
- return snd_hda_codec_write_cache(codec, 0x1a, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
+ return snd_hda_set_pin_ctl_cache(codec, 0x1a,
cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index);
}
@@ -2081,14 +2076,14 @@ static void cxt5066_olpc_select_mic(struct hda_codec *codec)
}
/* disable DC (port F) */
- snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+ snd_hda_set_pin_ctl(codec, 0x1e, 0);
/* external mic, port B */
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ snd_hda_set_pin_ctl(codec, 0x1a,
spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0);
/* internal mic, port C */
- snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ snd_hda_set_pin_ctl(codec, 0x1b,
spec->ext_mic_present ? 0 : PIN_VREF80);
}
@@ -3357,9 +3352,7 @@ static void do_automute(struct hda_codec *codec, int num_pins,
struct conexant_spec *spec = codec->spec;
int i;
for (i = 0; i < num_pins; i++)
- snd_hda_codec_write(codec, pins[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- on ? PIN_OUT : 0);
+ snd_hda_set_pin_ctl(codec, pins[i], on ? PIN_OUT : 0);
if (spec->pin_eapd_ctrls)
cx_auto_turn_eapd(codec, num_pins, pins, on);
}
@@ -3976,8 +3969,7 @@ static void cx_auto_init_output(struct hda_codec *codec)
if (snd_hda_query_pin_caps(codec, cfg->hp_pins[i]) &
AC_PINCAP_HP_DRV)
val |= AC_PINCTL_HP_EN;
- snd_hda_codec_write(codec, cfg->hp_pins[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ snd_hda_set_pin_ctl(codec, cfg->hp_pins[i], val);
}
mute_outputs(codec, cfg->hp_outs, cfg->hp_pins);
mute_outputs(codec, cfg->line_outs, cfg->line_out_pins);
@@ -4030,13 +4022,11 @@ static void cx_auto_init_input(struct hda_codec *codec)
}
for (i = 0; i < cfg->num_inputs; i++) {
- unsigned int type;
+ hda_nid_t pin = cfg->inputs[i].pin;
+ unsigned int type = PIN_IN;
if (cfg->inputs[i].type == AUTO_PIN_MIC)
- type = PIN_VREF80;
- else
- type = PIN_IN;
- snd_hda_codec_write(codec, cfg->inputs[i].pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, type);
+ type |= snd_hda_get_default_vref(codec, pin);
+ snd_hda_set_pin_ctl(codec, pin, type);
}
if (spec->auto_mic) {
@@ -4063,11 +4053,9 @@ static void cx_auto_init_digital(struct hda_codec *codec)
struct auto_pin_cfg *cfg = &spec->autocfg;
if (spec->multiout.dig_out_nid)
- snd_hda_codec_write(codec, cfg->dig_out_pins[0], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+ snd_hda_set_pin_ctl(codec, cfg->dig_out_pins[0], PIN_OUT);
if (spec->dig_in_nid)
- snd_hda_codec_write(codec, cfg->dig_in_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
+ snd_hda_set_pin_ctl(codec, cfg->dig_in_pin, PIN_IN);
}
static int cx_auto_init(struct hda_codec *codec)
@@ -4084,9 +4072,9 @@ static int cx_auto_init(struct hda_codec *codec)
static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
const char *dir, int cidx,
- hda_nid_t nid, int hda_dir, int amp_idx)
+ hda_nid_t nid, int hda_dir, int amp_idx, int chs)
{
- static char name[32];
+ static char name[44];
static struct snd_kcontrol_new knew[] = {
HDA_CODEC_VOLUME(name, 0, 0, 0),
HDA_CODEC_MUTE(name, 0, 0, 0),
@@ -4096,7 +4084,7 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
for (i = 0; i < 2; i++) {
struct snd_kcontrol *kctl;
- knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, amp_idx,
+ knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, chs, amp_idx,
hda_dir);
knew[i].subdevice = HDA_SUBDEV_AMP_FLAG;
knew[i].index = cidx;
@@ -4115,7 +4103,7 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
}
#define cx_auto_add_volume(codec, str, dir, cidx, nid, hda_dir) \
- cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0)
+ cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0, 3)
#define cx_auto_add_pb_volume(codec, nid, str, idx) \
cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT)
@@ -4185,6 +4173,36 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
return 0;
}
+/* Returns zero if this is a normal stereo channel, and non-zero if it should
+ be split in two independent channels.
+ dest_label must be at least 44 characters. */
+static int cx_auto_get_rightch_label(struct hda_codec *codec, const char *label,
+ char *dest_label, int nid)
+{
+ struct conexant_spec *spec = codec->spec;
+ int i;
+
+ if (!spec->fixup_stereo_dmic)
+ return 0;
+
+ for (i = 0; i < AUTO_CFG_MAX_INS; i++) {
+ int def_conf;
+ if (spec->autocfg.inputs[i].pin != nid)
+ continue;
+
+ if (spec->autocfg.inputs[i].type != AUTO_PIN_MIC)
+ return 0;
+ def_conf = snd_hda_codec_get_pincfg(codec, nid);
+ if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT)
+ return 0;
+
+ /* Finally found the inverted internal mic! */
+ snprintf(dest_label, 44, "Inverted %s", label);
+ return 1;
+ }
+ return 0;
+}
+
static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid,
const char *label, const char *pfx,
int cidx)
@@ -4193,14 +4211,25 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid,
int i;
for (i = 0; i < spec->num_adc_nids; i++) {
+ char rightch_label[44];
hda_nid_t adc_nid = spec->adc_nids[i];
int idx = get_input_connection(codec, adc_nid, nid);
if (idx < 0)
continue;
if (codec->single_adc_amp)
idx = 0;
+
+ if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) {
+ /* Make two independent kcontrols for left and right */
+ int err = cx_auto_add_volume_idx(codec, label, pfx,
+ cidx, adc_nid, HDA_INPUT, idx, 1);
+ if (err < 0)
+ return err;
+ return cx_auto_add_volume_idx(codec, rightch_label, pfx,
+ cidx, adc_nid, HDA_INPUT, idx, 2);
+ }
return cx_auto_add_volume_idx(codec, label, pfx,
- cidx, adc_nid, HDA_INPUT, idx);
+ cidx, adc_nid, HDA_INPUT, idx, 3);
}
return 0;
}
@@ -4213,9 +4242,19 @@ static int cx_auto_add_boost_volume(struct hda_codec *codec, int idx,
int i, con;
nid = spec->imux_info[idx].pin;
- if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
+ if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
+ char rightch_label[44];
+ if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) {
+ int err = cx_auto_add_volume_idx(codec, label, " Boost",
+ cidx, nid, HDA_INPUT, 0, 1);
+ if (err < 0)
+ return err;
+ return cx_auto_add_volume_idx(codec, rightch_label, " Boost",
+ cidx, nid, HDA_INPUT, 0, 2);
+ }
return cx_auto_add_volume(codec, label, " Boost", cidx,
nid, HDA_INPUT);
+ }
con = __select_input_connection(codec, spec->imux_info[idx].adc, nid,
&mux, false, 0);
if (con < 0)
@@ -4370,37 +4409,21 @@ static const struct hda_codec_ops cx_auto_patch_ops = {
/*
* pin fix-up
*/
-struct cxt_pincfg {
- hda_nid_t nid;
- u32 val;
-};
-
-static void apply_pincfg(struct hda_codec *codec, const struct cxt_pincfg *cfg)
-{
- for (; cfg->nid; cfg++)
- snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
-
-}
-
-static void apply_pin_fixup(struct hda_codec *codec,
- const struct snd_pci_quirk *quirk,
- const struct cxt_pincfg **table)
-{
- quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
- if (quirk) {
- snd_printdd(KERN_INFO "hda_codec: applying pincfg for %s\n",
- quirk->name);
- apply_pincfg(codec, table[quirk->value]);
- }
-}
-
enum {
CXT_PINCFG_LENOVO_X200,
CXT_PINCFG_LENOVO_TP410,
+ CXT_FIXUP_STEREO_DMIC,
};
+static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ struct conexant_spec *spec = codec->spec;
+ spec->fixup_stereo_dmic = 1;
+}
+
/* ThinkPad X200 & co with cxt5051 */
-static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
+static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
{ 0x17, 0x21a11000 }, /* dock-mic */
{ 0x19, 0x2121103f }, /* dock-HP */
@@ -4409,16 +4432,26 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
};
/* ThinkPad 410/420/510/520, X201 & co with cxt5066 */
-static const struct cxt_pincfg cxt_pincfg_lenovo_tp410[] = {
+static const struct hda_pintbl cxt_pincfg_lenovo_tp410[] = {
{ 0x19, 0x042110ff }, /* HP (seq# overridden) */
{ 0x1a, 0x21a190f0 }, /* dock-mic */
{ 0x1c, 0x212140ff }, /* dock-HP */
{}
};
-static const struct cxt_pincfg *cxt_pincfg_tbl[] = {
- [CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200,
- [CXT_PINCFG_LENOVO_TP410] = cxt_pincfg_lenovo_tp410,
+static const struct hda_fixup cxt_fixups[] = {
+ [CXT_PINCFG_LENOVO_X200] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = cxt_pincfg_lenovo_x200,
+ },
+ [CXT_PINCFG_LENOVO_TP410] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = cxt_pincfg_lenovo_tp410,
+ },
+ [CXT_FIXUP_STEREO_DMIC] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = cxt_fixup_stereo_dmic,
+ },
};
static const struct snd_pci_quirk cxt5051_fixups[] = {
@@ -4432,6 +4465,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
+ SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
{}
};
@@ -4471,13 +4505,16 @@ static int patch_conexant_auto(struct hda_codec *codec)
case 0x14f15051:
add_cx5051_fake_mutes(codec);
codec->pin_amp_workaround = 1;
- apply_pin_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl);
+ snd_hda_pick_fixup(codec, NULL, cxt5051_fixups, cxt_fixups);
break;
default:
codec->pin_amp_workaround = 1;
- apply_pin_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl);
+ snd_hda_pick_fixup(codec, NULL, cxt5066_fixups, cxt_fixups);
+ break;
}
+ snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
+
/* Show mute-led control only on HP laptops
* This is a sort of white-list: on HP laptops, EAPD corresponds
* only to the mute-LED without actualy amp function. Meanwhile,
@@ -4556,6 +4593,12 @@ static const struct hda_codec_preset snd_hda_preset_conexant[] = {
.patch = patch_conexant_auto },
{ .id = 0x14f150b9, .name = "CX20665",
.patch = patch_conexant_auto },
+ { .id = 0x14f1510f, .name = "CX20751/2",
+ .patch = patch_conexant_auto },
+ { .id = 0x14f15110, .name = "CX20751/2",
+ .patch = patch_conexant_auto },
+ { .id = 0x14f15111, .name = "CX20753/4",
+ .patch = patch_conexant_auto },
{} /* terminator */
};
@@ -4576,6 +4619,9 @@ MODULE_ALIAS("snd-hda-codec-id:14f150ab");
MODULE_ALIAS("snd-hda-codec-id:14f150ac");
MODULE_ALIAS("snd-hda-codec-id:14f150b8");
MODULE_ALIAS("snd-hda-codec-id:14f150b9");
+MODULE_ALIAS("snd-hda-codec-id:14f1510f");
+MODULE_ALIAS("snd-hda-codec-id:14f15110");
+MODULE_ALIAS("snd-hda-codec-id:14f15111");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Conexant HD-audio codec");
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 83f345f3c961..ad319d4dc32f 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1592,10 +1592,10 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
unsigned int dataDCC2, channel_id;
int i;
struct hdmi_spec *spec = codec->spec;
- struct hda_spdif_out *spdif =
- snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid);
+ struct hda_spdif_out *spdif;
mutex_lock(&codec->spdif_mutex);
+ spdif = snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid);
chs = substream->runtime->channels;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 7810913d07a0..ff71dcef08ef 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6,7 +6,7 @@
* Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
* PeiSen Hou <pshou@realtek.com.tw>
* Takashi Iwai <tiwai@suse.de>
- * Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
+ * Jonathan Woithe <jwoithe@just42.net>
*
* This driver is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@
#include <sound/jack.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_auto_parser.h"
#include "hda_beep.h"
#include "hda_jack.h"
@@ -66,8 +67,6 @@ struct alc_customize_define {
unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
};
-struct alc_fixup;
-
struct alc_multi_io {
hda_nid_t pin; /* multi-io widget pin NID */
hda_nid_t dac; /* DAC to be connected */
@@ -82,19 +81,33 @@ enum {
#define MAX_VOL_NIDS 0x40
+/* make compatible with old code */
+#define alc_apply_pincfgs snd_hda_apply_pincfgs
+#define alc_apply_fixup snd_hda_apply_fixup
+#define alc_pick_fixup snd_hda_pick_fixup
+#define alc_fixup hda_fixup
+#define alc_pincfg hda_pintbl
+#define alc_model_fixup hda_model_fixup
+
+#define ALC_FIXUP_PINS HDA_FIXUP_PINS
+#define ALC_FIXUP_VERBS HDA_FIXUP_VERBS
+#define ALC_FIXUP_FUNC HDA_FIXUP_FUNC
+
+#define ALC_FIXUP_ACT_PRE_PROBE HDA_FIXUP_ACT_PRE_PROBE
+#define ALC_FIXUP_ACT_PROBE HDA_FIXUP_ACT_PROBE
+#define ALC_FIXUP_ACT_INIT HDA_FIXUP_ACT_INIT
+#define ALC_FIXUP_ACT_BUILD HDA_FIXUP_ACT_BUILD
+
+
struct alc_spec {
+ struct hda_gen_spec gen;
+
/* codec parameterization */
const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
unsigned int num_mixers;
const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
- const struct hda_verb *init_verbs[10]; /* initialization verbs
- * don't forget NULL
- * termination!
- */
- unsigned int num_init_verbs;
-
char stream_name_analog[32]; /* analog PCM stream */
const struct hda_pcm_stream *stream_analog_playback;
const struct hda_pcm_stream *stream_analog_capture;
@@ -210,11 +223,6 @@ struct alc_spec {
unsigned int pll_coef_idx, pll_coef_bit;
unsigned int coef0;
- /* fix-up list */
- int fixup_id;
- const struct alc_fixup *fixup_list;
- const char *fixup_name;
-
/* multi-io */
int multi_ios;
struct alc_multi_io multi_io[4];
@@ -319,13 +327,16 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
/* for shared I/O, change the pin-control accordingly */
if (spec->shared_mic_hp) {
+ unsigned int val;
+ hda_nid_t pin = spec->autocfg.inputs[1].pin;
/* NOTE: this assumes that there are only two inputs, the
* first is the real internal mic and the second is HP jack.
*/
- snd_hda_codec_write(codec, spec->autocfg.inputs[1].pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- spec->cur_mux[adc_idx] ?
- PIN_VREF80 : PIN_HP);
+ if (spec->cur_mux[adc_idx])
+ val = snd_hda_get_default_vref(codec, pin) | PIN_IN;
+ else
+ val = PIN_HP;
+ snd_hda_set_pin_ctl(codec, pin, val);
spec->automute_speaker = !spec->cur_mux[adc_idx];
call_update_outputs(codec);
}
@@ -338,7 +349,7 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
nid = get_capsrc(spec, adc_idx);
/* no selection? */
- num_conns = snd_hda_get_conn_list(codec, nid, NULL);
+ num_conns = snd_hda_get_num_conns(codec, nid);
if (num_conns <= 1)
return 1;
@@ -376,25 +387,9 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
int auto_pin_type)
{
unsigned int val = PIN_IN;
-
- if (auto_pin_type == AUTO_PIN_MIC) {
- unsigned int pincap;
- unsigned int oldval;
- oldval = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- pincap = snd_hda_query_pin_caps(codec, nid);
- pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
- /* if the default pin setup is vref50, we give it priority */
- if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
- val = PIN_VREF80;
- else if (pincap & AC_PINCAP_VREF_50)
- val = PIN_VREF50;
- else if (pincap & AC_PINCAP_VREF_100)
- val = PIN_VREF100;
- else if (pincap & AC_PINCAP_VREF_GRD)
- val = PIN_VREFGRD;
- }
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ if (auto_pin_type == AUTO_PIN_MIC)
+ val |= snd_hda_get_default_vref(codec, nid);
+ snd_hda_set_pin_ctl(codec, nid, val);
}
/*
@@ -409,13 +404,6 @@ static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
spec->mixers[spec->num_mixers++] = mix;
}
-static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
-{
- if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
- return;
- spec->init_verbs[spec->num_init_verbs++] = verb;
-}
-
/*
* GPIO setup tables, used in initialization
*/
@@ -517,9 +505,7 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
} else
val = 0;
val |= pin_bits;
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- val);
+ snd_hda_set_pin_ctl(codec, nid, val);
break;
case ALC_AUTOMUTE_AMP:
snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
@@ -1200,6 +1186,16 @@ static void alc_auto_check_switches(struct hda_codec *codec)
*/
#define ALC_FIXUP_SKU_IGNORE (2)
+static void alc_fixup_sku_ignore(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+ spec->cdefine.fixup = 1;
+ spec->cdefine.sku_cfg = ALC_FIXUP_SKU_IGNORE;
+ }
+}
+
static int alc_auto_parse_customize_define(struct hda_codec *codec)
{
unsigned int ass, tmp, i;
@@ -1403,178 +1399,6 @@ static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
}
/*
- * Fix-up pin default configurations and add default verbs
- */
-
-struct alc_pincfg {
- hda_nid_t nid;
- u32 val;
-};
-
-struct alc_model_fixup {
- const int id;
- const char *name;
-};
-
-struct alc_fixup {
- int type;
- bool chained;
- int chain_id;
- union {
- unsigned int sku;
- const struct alc_pincfg *pins;
- const struct hda_verb *verbs;
- void (*func)(struct hda_codec *codec,
- const struct alc_fixup *fix,
- int action);
- } v;
-};
-
-enum {
- ALC_FIXUP_INVALID,
- ALC_FIXUP_SKU,
- ALC_FIXUP_PINS,
- ALC_FIXUP_VERBS,
- ALC_FIXUP_FUNC,
-};
-
-enum {
- ALC_FIXUP_ACT_PRE_PROBE,
- ALC_FIXUP_ACT_PROBE,
- ALC_FIXUP_ACT_INIT,
- ALC_FIXUP_ACT_BUILD,
-};
-
-static void alc_apply_pincfgs(struct hda_codec *codec,
- const struct alc_pincfg *cfg)
-{
- for (; cfg->nid; cfg++)
- snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
-}
-
-static void alc_apply_fixup(struct hda_codec *codec, int action)
-{
- struct alc_spec *spec = codec->spec;
- int id = spec->fixup_id;
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- const char *modelname = spec->fixup_name;
-#endif
- int depth = 0;
-
- if (!spec->fixup_list)
- return;
-
- while (id >= 0) {
- const struct alc_fixup *fix = spec->fixup_list + id;
- const struct alc_pincfg *cfg;
-
- switch (fix->type) {
- case ALC_FIXUP_SKU:
- if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
- break;
- snd_printdd(KERN_INFO "hda_codec: %s: "
- "Apply sku override for %s\n",
- codec->chip_name, modelname);
- spec->cdefine.sku_cfg = fix->v.sku;
- spec->cdefine.fixup = 1;
- break;
- case ALC_FIXUP_PINS:
- cfg = fix->v.pins;
- if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
- break;
- snd_printdd(KERN_INFO "hda_codec: %s: "
- "Apply pincfg for %s\n",
- codec->chip_name, modelname);
- alc_apply_pincfgs(codec, cfg);
- break;
- case ALC_FIXUP_VERBS:
- if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
- break;
- snd_printdd(KERN_INFO "hda_codec: %s: "
- "Apply fix-verbs for %s\n",
- codec->chip_name, modelname);
- add_verb(codec->spec, fix->v.verbs);
- break;
- case ALC_FIXUP_FUNC:
- if (!fix->v.func)
- break;
- snd_printdd(KERN_INFO "hda_codec: %s: "
- "Apply fix-func for %s\n",
- codec->chip_name, modelname);
- fix->v.func(codec, fix, action);
- break;
- default:
- snd_printk(KERN_ERR "hda_codec: %s: "
- "Invalid fixup type %d\n",
- codec->chip_name, fix->type);
- break;
- }
- if (!fix->chained)
- break;
- if (++depth > 10)
- break;
- id = fix->chain_id;
- }
-}
-
-static void alc_pick_fixup(struct hda_codec *codec,
- const struct alc_model_fixup *models,
- const struct snd_pci_quirk *quirk,
- const struct alc_fixup *fixlist)
-{
- struct alc_spec *spec = codec->spec;
- const struct snd_pci_quirk *q;
- int id = -1;
- const char *name = NULL;
-
- /* when model=nofixup is given, don't pick up any fixups */
- if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
- spec->fixup_list = NULL;
- spec->fixup_id = -1;
- return;
- }
-
- if (codec->modelname && models) {
- while (models->name) {
- if (!strcmp(codec->modelname, models->name)) {
- id = models->id;
- name = models->name;
- break;
- }
- models++;
- }
- }
- if (id < 0) {
- q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
- if (q) {
- id = q->value;
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- name = q->name;
-#endif
- }
- }
- if (id < 0) {
- for (q = quirk; q->subvendor; q++) {
- unsigned int vendorid =
- q->subdevice | (q->subvendor << 16);
- if (vendorid == codec->subsystem_id) {
- id = q->value;
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- name = q->name;
-#endif
- break;
- }
- }
- }
-
- spec->fixup_id = id;
- if (id >= 0) {
- spec->fixup_list = fixlist;
- spec->fixup_name = name;
- }
-}
-
-/*
* COEF access helper functions
*/
static int alc_read_coef_idx(struct hda_codec *codec,
@@ -1621,8 +1445,7 @@ static void alc_auto_init_digital(struct hda_codec *codec)
pin = spec->autocfg.dig_out_pins[i];
if (!pin)
continue;
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+ snd_hda_set_pin_ctl(codec, pin, PIN_OUT);
if (!i)
dac = spec->multiout.dig_out_nid;
else
@@ -1635,9 +1458,7 @@ static void alc_auto_init_digital(struct hda_codec *codec)
}
pin = spec->autocfg.dig_in_pin;
if (pin)
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- PIN_IN);
+ snd_hda_set_pin_ctl(codec, pin, PIN_IN);
}
/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
@@ -2068,7 +1889,6 @@ static void alc_auto_init_std(struct hda_codec *codec);
static int alc_init(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int i;
if (spec->init_hook)
spec->init_hook(codec);
@@ -2076,8 +1896,6 @@ static int alc_init(struct hda_codec *codec)
alc_fix_pll(codec);
alc_auto_init_amp(codec, spec->init_amp);
- for (i = 0; i < spec->num_init_verbs; i++)
- snd_hda_sequence_write(codec, spec->init_verbs[i]);
alc_init_special_input_src(codec);
alc_auto_init_std(codec);
@@ -2725,7 +2543,6 @@ static int alc_auto_fill_adc_caps(struct hda_codec *codec)
nid = codec->start_nid;
for (i = 0; i < codec->num_nodes; i++, nid++) {
hda_nid_t src;
- const hda_nid_t *list;
unsigned int caps = get_wcaps(codec, nid);
int type = get_wcaps_type(caps);
@@ -2743,13 +2560,14 @@ static int alc_auto_fill_adc_caps(struct hda_codec *codec)
cap_nids[nums] = src;
break;
}
- n = snd_hda_get_conn_list(codec, src, &list);
+ n = snd_hda_get_num_conns(codec, src);
if (n > 1) {
cap_nids[nums] = src;
break;
} else if (n != 1)
break;
- src = *list;
+ if (snd_hda_get_connections(codec, src, &src, 1) != 1)
+ break;
}
if (++nums >= max_nums)
break;
@@ -2856,8 +2674,7 @@ static int alc_auto_create_shared_input(struct hda_codec *codec)
static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
unsigned int pin_type)
{
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- pin_type);
+ snd_hda_set_pin_ctl(codec, nid, pin_type);
/* unmute pin */
if (nid_has_mute(codec, nid, HDA_OUTPUT))
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
@@ -2891,7 +2708,7 @@ static void alc_auto_init_analog_input(struct hda_codec *codec)
/* mute all loopback inputs */
if (spec->mixer_nid) {
- int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
+ int nums = snd_hda_get_num_conns(codec, spec->mixer_nid);
for (i = 0; i < nums; i++)
snd_hda_codec_write(codec, spec->mixer_nid, 0,
AC_VERB_SET_AMP_GAIN_MUTE,
@@ -3521,7 +3338,7 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec,
if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
type = ALC_CTL_WIDGET_MUTE;
val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
- } else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) {
+ } else if (snd_hda_get_num_conns(codec, nid) == 1) {
type = ALC_CTL_WIDGET_MUTE;
val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
} else {
@@ -3998,9 +3815,7 @@ static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
if (output) {
- snd_hda_codec_update_cache(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- PIN_OUT);
+ snd_hda_set_pin_ctl_cache(codec, nid, PIN_OUT);
if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
HDA_AMP_MUTE, 0);
@@ -4009,9 +3824,8 @@ static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
HDA_AMP_MUTE, HDA_AMP_MUTE);
- snd_hda_codec_update_cache(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- spec->multi_io[idx].ctl_in);
+ snd_hda_set_pin_ctl_cache(codec, nid,
+ spec->multi_io[idx].ctl_in);
}
return 0;
}
@@ -4084,7 +3898,7 @@ static void alc_remove_invalid_adc_nids(struct hda_codec *codec)
nums = 0;
for (n = 0; n < spec->num_adc_nids; n++) {
hda_nid_t cap = spec->private_capsrc_nids[n];
- int num_conns = snd_hda_get_conn_list(codec, cap, NULL);
+ int num_conns = snd_hda_get_num_conns(codec, cap);
for (i = 0; i < imux->num_items; i++) {
hda_nid_t pin = spec->imux_pins[i];
if (pin) {
@@ -4213,7 +4027,7 @@ static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
HDA_AMP_MUTE, 0);
- } else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) {
+ } else if (snd_hda_get_num_conns(codec, cap) > 1) {
snd_hda_codec_write_cache(codec, cap, 0,
AC_VERB_SET_CONNECT_SEL, idx);
}
@@ -4427,6 +4241,25 @@ static int alc_parse_auto_config(struct hda_codec *codec,
return 1;
}
+/* common preparation job for alc_spec */
+static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
+{
+ struct alc_spec *spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+ int err;
+
+ if (!spec)
+ return -ENOMEM;
+ codec->spec = spec;
+ spec->mixer_nid = mixer_nid;
+
+ err = alc_codec_rename_from_preset(codec);
+ if (err < 0) {
+ kfree(spec);
+ return err;
+ }
+ return 0;
+}
+
static int alc880_parse_auto_config(struct hda_codec *codec)
{
static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
@@ -4808,13 +4641,11 @@ static int patch_alc880(struct hda_codec *codec)
struct alc_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
+ err = alc_alloc_spec(codec, 0x0b);
+ if (err < 0)
+ return err;
- spec->mixer_nid = 0x0b;
+ spec = codec->spec;
spec->need_dac_fix = 1;
alc_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl,
@@ -4890,7 +4721,7 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT);
spec->unsol_event = alc_sku_unsol_event;
- add_verb(codec->spec, alc_gpio1_init_verbs);
+ snd_hda_gen_add_verbs(&spec->gen, alc_gpio1_init_verbs);
}
}
@@ -5001,13 +4832,11 @@ static int patch_alc260(struct hda_codec *codec)
struct alc_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
+ err = alc_alloc_spec(codec, 0x07);
+ if (err < 0)
+ return err;
- spec->mixer_nid = 0x07;
+ spec = codec->spec;
alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
@@ -5171,8 +5000,7 @@ static void alc889_fixup_mbp_vref(struct hda_codec *codec,
val = snd_hda_codec_read(codec, nids[i], 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
val |= AC_PINCTL_VREF_80;
- snd_hda_codec_write(codec, nids[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ snd_hda_set_pin_ctl(codec, nids[i], val);
spec->keep_vref_in_automute = 1;
break;
}
@@ -5193,8 +5021,7 @@ static void alc889_fixup_imac91_vref(struct hda_codec *codec,
val = snd_hda_codec_read(codec, nids[i], 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
val |= AC_PINCTL_VREF_50;
- snd_hda_codec_write(codec, nids[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ snd_hda_set_pin_ctl(codec, nids[i], val);
}
spec->keep_vref_in_automute = 1;
}
@@ -5225,8 +5052,8 @@ static const struct alc_fixup alc882_fixups[] = {
}
},
[ALC882_FIXUP_ACER_ASPIRE_7736] = {
- .type = ALC_FIXUP_SKU,
- .v.sku = ALC_FIXUP_SKU_IGNORE,
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc_fixup_sku_ignore,
},
[ALC882_FIXUP_ASUS_W90V] = {
.type = ALC_FIXUP_PINS,
@@ -5476,13 +5303,11 @@ static int patch_alc882(struct hda_codec *codec)
struct alc_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
+ err = alc_alloc_spec(codec, 0x0b);
+ if (err < 0)
+ return err;
- spec->mixer_nid = 0x0b;
+ spec = codec->spec;
switch (codec->vendor_id) {
case 0x10ec0882:
@@ -5494,10 +5319,6 @@ static int patch_alc882(struct hda_codec *codec)
break;
}
- err = alc_codec_rename_from_preset(codec);
- if (err < 0)
- goto error;
-
alc_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl,
alc882_fixups);
alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
@@ -5621,13 +5442,11 @@ static int patch_alc262(struct hda_codec *codec)
struct alc_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
+ err = alc_alloc_spec(codec, 0x0b);
+ if (err < 0)
+ return err;
- spec->mixer_nid = 0x0b;
+ spec = codec->spec;
#if 0
/* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
@@ -5710,7 +5529,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
if (err > 0) {
if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
add_mixer(spec, alc268_beep_mixer);
- add_verb(spec, alc268_beep_init_verbs);
+ snd_hda_gen_add_verbs(&spec->gen, alc268_beep_init_verbs);
}
}
return err;
@@ -5723,13 +5542,12 @@ static int patch_alc268(struct hda_codec *codec)
struct alc_spec *spec;
int i, has_beep, err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
-
/* ALC268 has no aa-loopback mixer */
+ err = alc_alloc_spec(codec, 0);
+ if (err < 0)
+ return err;
+
+ spec = codec->spec;
/* automatic parse from the BIOS config */
err = alc268_parse_auto_config(codec);
@@ -5946,9 +5764,7 @@ static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled)
{
struct hda_codec *codec = private_data;
unsigned int pinval = enabled ? 0x20 : 0x24;
- snd_hda_codec_update_cache(codec, 0x19, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- pinval);
+ snd_hda_set_pin_ctl_cache(codec, 0x19, pinval);
}
static void alc269_fixup_mic2_mute(struct hda_codec *codec,
@@ -6015,8 +5831,8 @@ static const struct alc_fixup alc269_fixups[] = {
}
},
[ALC269_FIXUP_SKU_IGNORE] = {
- .type = ALC_FIXUP_SKU,
- .v.sku = ALC_FIXUP_SKU_IGNORE,
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc_fixup_sku_ignore,
},
[ALC269_FIXUP_ASUS_G73JW] = {
.type = ALC_FIXUP_PINS,
@@ -6242,19 +6058,13 @@ static void alc269_fill_coef(struct hda_codec *codec)
static int patch_alc269(struct hda_codec *codec)
{
struct alc_spec *spec;
- int err = 0;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
-
- spec->mixer_nid = 0x0b;
+ int err;
- err = alc_codec_rename_from_preset(codec);
+ err = alc_alloc_spec(codec, 0x0b);
if (err < 0)
- goto error;
+ return err;
+
+ spec = codec->spec;
if (codec->vendor_id == 0x10ec0269) {
spec->codec_variant = ALC269_TYPE_ALC269VA;
@@ -6346,8 +6156,7 @@ static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
val |= AC_PINCTL_IN_EN;
val |= AC_PINCTL_VREF_50;
- snd_hda_codec_write(codec, 0x0f, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ snd_hda_set_pin_ctl(codec, 0x0f, val);
spec->keep_vref_in_automute = 1;
}
@@ -6401,13 +6210,11 @@ static int patch_alc861(struct hda_codec *codec)
struct alc_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
+ err = alc_alloc_spec(codec, 0x15);
+ if (err < 0)
+ return err;
- spec->mixer_nid = 0x15;
+ spec = codec->spec;
alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
@@ -6504,13 +6311,11 @@ static int patch_alc861vd(struct hda_codec *codec)
struct alc_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
+ err = alc_alloc_spec(codec, 0x0b);
+ if (err < 0)
+ return err;
- spec->mixer_nid = 0x0b;
+ spec = codec->spec;
alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
@@ -6522,7 +6327,7 @@ static int patch_alc861vd(struct hda_codec *codec)
if (codec->vendor_id == 0x10ec0660) {
/* always turn on EAPD */
- add_verb(spec, alc660vd_eapd_verbs);
+ snd_hda_gen_add_verbs(&spec->gen, alc660vd_eapd_verbs);
}
if (!spec->no_analog) {
@@ -6635,8 +6440,8 @@ static const struct alc_fixup alc662_fixups[] = {
}
},
[ALC662_FIXUP_SKU_IGNORE] = {
- .type = ALC_FIXUP_SKU,
- .v.sku = ALC_FIXUP_SKU_IGNORE,
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc_fixup_sku_ignore,
},
[ALC662_FIXUP_HP_RP5800] = {
.type = ALC_FIXUP_PINS,
@@ -6849,25 +6654,19 @@ static const struct alc_model_fixup alc662_fixup_models[] = {
static int patch_alc662(struct hda_codec *codec)
{
struct alc_spec *spec;
- int err = 0;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return -ENOMEM;
+ int err;
- codec->spec = spec;
+ err = alc_alloc_spec(codec, 0x0b);
+ if (err < 0)
+ return err;
- spec->mixer_nid = 0x0b;
+ spec = codec->spec;
/* handle multiple HPs as is */
spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
alc_fix_pll_init(codec, 0x20, 0x04, 15);
- err = alc_codec_rename_from_preset(codec);
- if (err < 0)
- goto error;
-
if ((alc_get_coef0(codec) & (1 << 14)) &&
codec->bus->pci->subsystem_vendor == 0x1025 &&
spec->cdefine.platform_type == 1) {
@@ -6930,16 +6729,12 @@ static int alc680_parse_auto_config(struct hda_codec *codec)
*/
static int patch_alc680(struct hda_codec *codec)
{
- struct alc_spec *spec;
int err;
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
-
/* ALC680 has no aa-loopback mixer */
+ err = alc_alloc_spec(codec, 0);
+ if (err < 0)
+ return err;
/* automatic parse from the BIOS config */
err = alc680_parse_auto_config(codec);
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 2cb1e08f962a..7db8228f1b88 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -36,6 +36,7 @@
#include <sound/tlv.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_auto_parser.h"
#include "hda_beep.h"
#include "hda_jack.h"
@@ -221,6 +222,7 @@ struct sigmatel_spec {
unsigned char aloopback_shift;
/* power management */
+ unsigned int power_map_bits;
unsigned int num_pwrs;
const hda_nid_t *pwr_nids;
const hda_nid_t *dac_list;
@@ -314,6 +316,9 @@ struct sigmatel_spec {
struct hda_vmaster_mute_hook vmaster_mute;
};
+#define AC_VERB_IDT_SET_POWER_MAP 0x7ec
+#define AC_VERB_IDT_GET_POWER_MAP 0xfec
+
static const hda_nid_t stac9200_adc_nids[1] = {
0x03,
};
@@ -681,8 +686,7 @@ static int stac_vrefout_set(struct hda_codec *codec,
pinctl &= ~AC_PINCTL_VREFEN;
pinctl |= (new_vref & AC_PINCTL_VREFEN);
- error = snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
+ error = snd_hda_set_pin_ctl_cache(codec, nid, pinctl);
if (error < 0)
return error;
@@ -706,8 +710,7 @@ static unsigned int stac92xx_vref_set(struct hda_codec *codec,
else
pincfg |= AC_PINCTL_IN_EN;
- error = snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, pincfg);
+ error = snd_hda_set_pin_ctl_cache(codec, nid, pincfg);
if (error < 0)
return error;
else
@@ -2505,27 +2508,10 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
return 0;
}
-static unsigned int stac92xx_get_default_vref(struct hda_codec *codec,
- hda_nid_t nid)
-{
- unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
- pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
- if (pincap & AC_PINCAP_VREF_100)
- return AC_PINCTL_VREF_100;
- if (pincap & AC_PINCAP_VREF_80)
- return AC_PINCTL_VREF_80;
- if (pincap & AC_PINCAP_VREF_50)
- return AC_PINCTL_VREF_50;
- if (pincap & AC_PINCAP_VREF_GRD)
- return AC_PINCTL_VREF_GRD;
- return 0;
-}
-
static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type)
{
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+ snd_hda_set_pin_ctl_cache(codec, nid, pin_type);
}
#define stac92xx_hp_switch_info snd_ctl_boolean_mono_info
@@ -2594,7 +2580,7 @@ static int stac92xx_dc_bias_get(struct snd_kcontrol *kcontrol,
hda_nid_t nid = kcontrol->private_value;
unsigned int vref = stac92xx_vref_get(codec, nid);
- if (vref == stac92xx_get_default_vref(codec, nid))
+ if (vref == snd_hda_get_default_vref(codec, nid))
ucontrol->value.enumerated.item[0] = 0;
else if (vref == AC_PINCTL_VREF_GRD)
ucontrol->value.enumerated.item[0] = 1;
@@ -2613,7 +2599,7 @@ static int stac92xx_dc_bias_put(struct snd_kcontrol *kcontrol,
hda_nid_t nid = kcontrol->private_value;
if (ucontrol->value.enumerated.item[0] == 0)
- new_vref = stac92xx_get_default_vref(codec, nid);
+ new_vref = snd_hda_get_default_vref(codec, nid);
else if (ucontrol->value.enumerated.item[0] == 1)
new_vref = AC_PINCTL_VREF_GRD;
else if (ucontrol->value.enumerated.item[0] == 2)
@@ -2679,7 +2665,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
else {
unsigned int pinctl = AC_PINCTL_IN_EN;
if (io_idx) /* set VREF for mic */
- pinctl |= stac92xx_get_default_vref(codec, nid);
+ pinctl |= snd_hda_get_default_vref(codec, nid);
stac92xx_auto_set_pinctl(codec, nid, pinctl);
}
@@ -2847,7 +2833,7 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,
char name[22];
if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) {
- if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD
+ if (snd_hda_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD
&& nid == spec->line_switch)
control = STAC_CTL_WIDGET_IO_SWITCH;
else if (snd_hda_query_pin_caps(codec, nid)
@@ -4250,13 +4236,6 @@ static void stac_store_hints(struct hda_codec *codec)
val = snd_hda_get_bool_hint(codec, "eapd_switch");
if (val >= 0)
spec->eapd_switch = val;
- get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity);
- if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) {
- spec->gpio_mask |= spec->gpio_led;
- spec->gpio_dir |= spec->gpio_led;
- if (spec->gpio_led_polarity)
- spec->gpio_data |= spec->gpio_led;
- }
}
static void stac_issue_unsol_events(struct hda_codec *codec, int num_pins,
@@ -4354,7 +4333,7 @@ static int stac92xx_init(struct hda_codec *codec)
unsigned int pinctl, conf;
if (type == AUTO_PIN_MIC) {
/* for mic pins, force to initialize */
- pinctl = stac92xx_get_default_vref(codec, nid);
+ pinctl = snd_hda_get_default_vref(codec, nid);
pinctl |= AC_PINCTL_IN_EN;
stac92xx_auto_set_pinctl(codec, nid, pinctl);
} else {
@@ -4390,10 +4369,18 @@ static int stac92xx_init(struct hda_codec *codec)
hda_nid_t nid = spec->pwr_nids[i];
int pinctl, def_conf;
+ def_conf = snd_hda_codec_get_pincfg(codec, nid);
+ def_conf = get_defcfg_connect(def_conf);
+ if (def_conf == AC_JACK_PORT_NONE) {
+ /* power off unused ports */
+ stac_toggle_power_map(codec, nid, 0);
+ continue;
+ }
/* power on when no jack detection is available */
/* or when the VREF is used for controlling LED */
if (!spec->hp_detect ||
- spec->vref_mute_led_nid == nid) {
+ spec->vref_mute_led_nid == nid ||
+ !is_jack_detectable(codec, nid)) {
stac_toggle_power_map(codec, nid, 1);
continue;
}
@@ -4411,15 +4398,6 @@ static int stac92xx_init(struct hda_codec *codec)
stac_toggle_power_map(codec, nid, 1);
continue;
}
- def_conf = snd_hda_codec_get_pincfg(codec, nid);
- def_conf = get_defcfg_connect(def_conf);
- /* skip any ports that don't have jacks since presence
- * detection is useless */
- if (def_conf != AC_JACK_PORT_NONE &&
- !is_jack_detectable(codec, nid)) {
- stac_toggle_power_map(codec, nid, 1);
- continue;
- }
if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) {
stac_issue_unsol_event(codec, nid);
continue;
@@ -4432,6 +4410,12 @@ static int stac92xx_init(struct hda_codec *codec)
/* sync mute LED */
snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
+
+ /* sync the power-map */
+ if (spec->num_pwrs)
+ snd_hda_codec_write(codec, codec->afg, 0,
+ AC_VERB_IDT_SET_POWER_MAP,
+ spec->power_map_bits);
if (spec->dac_list)
stac92xx_power_down(codec);
return 0;
@@ -4460,8 +4444,7 @@ static void stac92xx_shutup_pins(struct hda_codec *codec)
struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
def_conf = snd_hda_codec_get_pincfg(codec, pin->nid);
if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)
- snd_hda_codec_write(codec, pin->nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+ snd_hda_set_pin_ctl(codec, pin->nid, 0);
}
}
@@ -4517,9 +4500,7 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
pin_ctl |= flag;
if (old_ctl != pin_ctl)
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- pin_ctl);
+ snd_hda_set_pin_ctl_cache(codec, nid, pin_ctl);
}
static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
@@ -4528,9 +4509,7 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
unsigned int pin_ctl = snd_hda_codec_read(codec, nid,
0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
if (pin_ctl & flag)
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- pin_ctl & ~flag);
+ snd_hda_set_pin_ctl_cache(codec, nid, pin_ctl & ~flag);
}
static inline int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
@@ -4682,14 +4661,18 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
idx = 1 << idx;
- val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) & 0xff;
+ val = spec->power_map_bits;
if (enable)
val &= ~idx;
else
val |= idx;
/* power down unused output ports */
- snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val);
+ if (val != spec->power_map_bits) {
+ spec->power_map_bits = val;
+ snd_hda_codec_write(codec, codec->afg, 0,
+ AC_VERB_IDT_SET_POWER_MAP, val);
+ }
}
static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid)
@@ -4866,6 +4849,11 @@ static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity)
struct sigmatel_spec *spec = codec->spec;
const struct dmi_device *dev = NULL;
+ if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) {
+ get_int_hint(codec, "gpio_led_polarity",
+ &spec->gpio_led_polarity);
+ return 1;
+ }
if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) {
while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING,
NULL, dev))) {
@@ -4952,7 +4940,8 @@ static void stac92hd_proc_hook(struct snd_info_buffer *buffer,
{
if (nid == codec->afg)
snd_iprintf(buffer, "Power-Map: 0x%02x\n",
- snd_hda_codec_read(codec, nid, 0, 0x0fec, 0x0));
+ snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_IDT_GET_POWER_MAP, 0));
}
static void analog_loop_proc_hook(struct snd_info_buffer *buffer,
@@ -5009,20 +4998,6 @@ static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
return 0;
}
-static int stac92xx_pre_resume(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- /* sync mute LED */
- if (spec->vref_mute_led_nid)
- stac_vrefout_set(codec, spec->vref_mute_led_nid,
- spec->vref_led);
- else if (spec->gpio_led)
- stac_gpio_set(codec, spec->gpio_mask,
- spec->gpio_dir, spec->gpio_data);
- return 0;
-}
-
static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,
unsigned int power_state)
{
@@ -5046,7 +5021,6 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,
#else
#define stac92xx_suspend NULL
#define stac92xx_resume NULL
-#define stac92xx_pre_resume NULL
#define stac92xx_set_power_state NULL
#endif /* CONFIG_PM */
@@ -5592,9 +5566,6 @@ again:
codec->patch_ops.set_power_state =
stac92xx_set_power_state;
}
-#ifdef CONFIG_PM
- codec->patch_ops.pre_resume = stac92xx_pre_resume;
-#endif
}
err = stac92xx_parse_auto_config(codec);
@@ -5901,9 +5872,6 @@ again:
codec->patch_ops.set_power_state =
stac92xx_set_power_state;
}
-#ifdef CONFIG_PM
- codec->patch_ops.pre_resume = stac92xx_pre_resume;
-#endif
}
spec->multiout.dac_nids = spec->dac_nids;
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 06214fdc9486..82b368068e08 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -54,6 +54,7 @@
#include <sound/asoundef.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_auto_parser.h"
#include "hda_jack.h"
/* Pin Widget NID */
@@ -484,7 +485,7 @@ static void activate_output_mix(struct hda_codec *codec, struct nid_path *path,
if (!path)
return;
- num = snd_hda_get_conn_list(codec, mix_nid, NULL);
+ num = snd_hda_get_num_conns(codec, mix_nid);
for (i = 0; i < num; i++) {
if (i == idx)
val = AMP_IN_UNMUTE(i);
@@ -532,8 +533,7 @@ static void init_output_pin(struct hda_codec *codec, hda_nid_t pin,
{
if (!pin)
return;
- snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- pin_type);
+ snd_hda_set_pin_ctl(codec, pin, pin_type);
if (snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD)
snd_hda_codec_write(codec, pin, 0,
AC_VERB_SET_EAPD_BTLENABLE, 0x02);
@@ -662,12 +662,12 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
hda_nid_t nid = cfg->inputs[i].pin;
if (spec->smart51_enabled && is_smart51_pins(codec, nid))
ctl = PIN_OUT;
- else if (cfg->inputs[i].type == AUTO_PIN_MIC)
- ctl = PIN_VREF50;
- else
+ else {
ctl = PIN_IN;
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, ctl);
+ if (cfg->inputs[i].type == AUTO_PIN_MIC)
+ ctl |= snd_hda_get_default_vref(codec, nid);
+ }
+ snd_hda_set_pin_ctl(codec, nid, ctl);
}
/* init input-src */
@@ -1006,9 +1006,7 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
parm |= out_in;
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- parm);
+ snd_hda_set_pin_ctl(codec, nid, parm);
if (out_in == AC_PINCTL_OUT_EN) {
mute_aa_path(codec, 1);
notify_aa_path_ctls(codec);
@@ -1647,8 +1645,7 @@ static void toggle_output_mutes(struct hda_codec *codec, int num_pins,
parm &= ~AC_PINCTL_OUT_EN;
else
parm |= AC_PINCTL_OUT_EN;
- snd_hda_codec_write(codec, pins[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, parm);
+ snd_hda_set_pin_ctl(codec, pins[i], parm);
}
}
@@ -1709,8 +1706,7 @@ static void via_gpio_control(struct hda_codec *codec)
if (gpio_data == 0x02) {
/* unmute line out */
- snd_hda_codec_write(codec, spec->autocfg.line_out_pins[0], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
+ snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0],
PIN_OUT);
if (vol_counter & 0x20) {
/* decrease volume */
@@ -1728,9 +1724,7 @@ static void via_gpio_control(struct hda_codec *codec)
}
} else if (!(gpio_data & 0x02)) {
/* mute line out */
- snd_hda_codec_write(codec, spec->autocfg.line_out_pins[0], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- 0);
+ snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0], 0);
}
}
@@ -2757,8 +2751,7 @@ static void via_auto_init_dig_in(struct hda_codec *codec)
struct via_spec *spec = codec->spec;
if (!spec->dig_in_nid)
return;
- snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
+ snd_hda_set_pin_ctl(codec, spec->autocfg.dig_in_pin, PIN_IN);
}
/* initialize the unsolicited events */
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 132a86e09d07..5be2e120a14e 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -2803,22 +2803,11 @@ static void __devexit snd_ice1712_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver ice1712_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ice1712_ids,
.probe = snd_ice1712_probe,
.remove = __devexit_p(snd_ice1712_remove),
};
-static int __init alsa_card_ice1712_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_ice1712_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_ice1712_init)
-module_exit(alsa_card_ice1712_exit)
+module_pci_driver(ice1712_driver);
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 812d10e43ae0..a01a00d1cf4d 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -2873,7 +2873,7 @@ static int snd_vt1724_resume(struct pci_dev *pci)
}
#endif
-static struct pci_driver driver = {
+static struct pci_driver vt1724_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_vt1724_ids,
.probe = snd_vt1724_probe,
@@ -2884,15 +2884,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_ice1724_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_ice1724_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_ice1724_init)
-module_exit(alsa_card_ice1724_exit)
+module_pci_driver(vt1724_driver);
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index e0a4263baa20..f4e2dd4da8cf 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -3338,7 +3338,7 @@ static void __devexit snd_intel8x0_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver intel8x0_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_intel8x0_ids,
.probe = snd_intel8x0_probe,
@@ -3349,16 +3349,4 @@ static struct pci_driver driver = {
#endif
};
-
-static int __init alsa_card_intel8x0_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_intel8x0_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_intel8x0_init)
-module_exit(alsa_card_intel8x0_exit)
+module_pci_driver(intel8x0_driver);
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index d689913a61be..fc27a6a69e77 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -1324,7 +1324,7 @@ static void __devexit snd_intel8x0m_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver intel8x0m_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_intel8x0m_ids,
.probe = snd_intel8x0m_probe,
@@ -1335,16 +1335,4 @@ static struct pci_driver driver = {
#endif
};
-
-static int __init alsa_card_intel8x0m_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_intel8x0m_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_intel8x0m_init)
-module_exit(alsa_card_intel8x0m_exit)
+module_pci_driver(intel8x0m_driver);
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 8fea45ab5882..e69ce5f9c31e 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2476,22 +2476,11 @@ static void __devexit snd_korg1212_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver korg1212_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_korg1212_ids,
.probe = snd_korg1212_probe,
.remove = __devexit_p(snd_korg1212_remove),
};
-static int __init alsa_card_korg1212_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_korg1212_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_korg1212_init)
-module_exit(alsa_card_korg1212_exit)
+module_pci_driver(korg1212_driver);
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index 375982736858..ac15166bee68 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -770,22 +770,11 @@ static DEFINE_PCI_DEVICE_TABLE(lola_ids) = {
MODULE_DEVICE_TABLE(pci, lola_ids);
/* pci_driver definition */
-static struct pci_driver driver = {
+static struct pci_driver lola_driver = {
.name = KBUILD_MODNAME,
.id_table = lola_ids,
.probe = lola_probe,
.remove = __devexit_p(lola_remove),
};
-static int __init alsa_card_lola_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_lola_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_lola_init)
-module_exit(alsa_card_lola_exit)
+module_pci_driver(lola_driver);
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
index d94c0c292bd0..d1ab43706735 100644
--- a/sound/pci/lx6464es/lx6464es.c
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -1141,24 +1141,11 @@ static void __devexit snd_lx6464es_remove(struct pci_dev *pci)
}
-static struct pci_driver driver = {
+static struct pci_driver lx6464es_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_lx6464es_ids,
.probe = snd_lx6464es_probe,
.remove = __devexit_p(snd_lx6464es_remove),
};
-
-/* module initialization */
-static int __init mod_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit mod_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(mod_init);
-module_exit(mod_exit);
+module_pci_driver(lx6464es_driver);
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 78229b0dad2b..deef21399586 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -2837,7 +2837,7 @@ static void __devexit snd_m3_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver m3_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_m3_ids,
.probe = snd_m3_probe,
@@ -2848,15 +2848,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_m3_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_m3_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_m3_init)
-module_exit(alsa_card_m3_exit)
+module_pci_driver(m3_driver);
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 487837c01c9f..0762610c99c0 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1380,22 +1380,11 @@ static void __devexit snd_mixart_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver mixart_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_mixart_ids,
.probe = snd_mixart_probe,
.remove = __devexit_p(snd_mixart_remove),
};
-static int __init alsa_card_mixart_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_mixart_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_mixart_init)
-module_exit(alsa_card_mixart_exit)
+module_pci_driver(mixart_driver);
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index ade2c64bd606..8159b05ee94d 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -1742,7 +1742,7 @@ static void __devexit snd_nm256_remove(struct pci_dev *pci)
}
-static struct pci_driver driver = {
+static struct pci_driver nm256_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_nm256_ids,
.probe = snd_nm256_probe,
@@ -1753,16 +1753,4 @@ static struct pci_driver driver = {
#endif
};
-
-static int __init alsa_card_nm256_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_nm256_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_nm256_init)
-module_exit(alsa_card_nm256_exit)
+module_pci_driver(nm256_driver);
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index eab663eef117..610275bfbaeb 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -94,6 +94,7 @@ enum {
MODEL_2CH_OUTPUT,
MODEL_HG2PCI,
MODEL_XONAR_DG,
+ MODEL_XONAR_DGX,
};
static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = {
@@ -109,6 +110,8 @@ static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = {
{ OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF },
/* Asus Xonar DG */
{ OXYGEN_PCI_SUBID(0x1043, 0x8467), .driver_data = MODEL_XONAR_DG },
+ /* Asus Xonar DGX */
+ { OXYGEN_PCI_SUBID(0x1043, 0x8521), .driver_data = MODEL_XONAR_DGX },
/* PCI 2.0 HD Audio */
{ OXYGEN_PCI_SUBID(0x13f6, 0x8782), .driver_data = MODEL_2CH_OUTPUT },
/* Kuroutoshikou CMI8787-HG2PCI */
@@ -827,6 +830,11 @@ static int __devinit get_oxygen_model(struct oxygen *chip,
break;
case MODEL_XONAR_DG:
chip->model = model_xonar_dg;
+ chip->model.shortname = "Xonar DG";
+ break;
+ case MODEL_XONAR_DGX:
+ chip->model = model_xonar_dg;
+ chip->model.shortname = "Xonar DGX";
break;
}
if (id->driver_data == MODEL_MERIDIAN ||
@@ -870,15 +878,4 @@ static struct pci_driver oxygen_driver = {
#endif
};
-static int __init alsa_card_oxygen_init(void)
-{
- return pci_register_driver(&oxygen_driver);
-}
-
-static void __exit alsa_card_oxygen_exit(void)
-{
- pci_unregister_driver(&oxygen_driver);
-}
-
-module_init(alsa_card_oxygen_init)
-module_exit(alsa_card_oxygen_exit)
+module_pci_driver(oxygen_driver);
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 3fdee4950174..19962c6d38c3 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -100,15 +100,4 @@ static struct pci_driver xonar_driver = {
.shutdown = oxygen_pci_shutdown,
};
-static int __init alsa_card_xonar_init(void)
-{
- return pci_register_driver(&xonar_driver);
-}
-
-static void __exit alsa_card_xonar_exit(void)
-{
- pci_unregister_driver(&xonar_driver);
-}
-
-module_init(alsa_card_xonar_init)
-module_exit(alsa_card_xonar_exit)
+module_pci_driver(xonar_driver);
diff --git a/sound/pci/oxygen/xonar_dg.c b/sound/pci/oxygen/xonar_dg.c
index 793bdf03d7e0..77acd790ea47 100644
--- a/sound/pci/oxygen/xonar_dg.c
+++ b/sound/pci/oxygen/xonar_dg.c
@@ -1,5 +1,5 @@
/*
- * card driver for the Xonar DG
+ * card driver for the Xonar DG/DGX
*
* Copyright (c) Clemens Ladisch <clemens@ladisch.de>
*
@@ -17,8 +17,8 @@
*/
/*
- * Xonar DG
- * --------
+ * Xonar DG/DGX
+ * ------------
*
* CMI8788:
*
@@ -581,7 +581,6 @@ static void dump_cs4245_registers(struct oxygen *chip,
}
struct oxygen_model model_xonar_dg = {
- .shortname = "Xonar DG",
.longname = "C-Media Oxygen HD Audio",
.chip = "CMI8786",
.init = dg_init,
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index fd1809ab73b4..0435f45e9513 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -1607,22 +1607,11 @@ static void __devexit pcxhr_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver pcxhr_driver = {
.name = KBUILD_MODNAME,
.id_table = pcxhr_ids,
.probe = pcxhr_probe,
.remove = __devexit_p(pcxhr_remove),
};
-static int __init pcxhr_module_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit pcxhr_module_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(pcxhr_module_init)
-module_exit(pcxhr_module_exit)
+module_pci_driver(pcxhr_driver);
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 0481d94aac9b..cbeb3f77350c 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1837,8 +1837,7 @@ static int snd_riptide_free(struct snd_riptide *chip)
}
if (chip->irq >= 0)
free_irq(chip->irq, chip);
- if (chip->fw_entry)
- release_firmware(chip->fw_entry);
+ release_firmware(chip->fw_entry);
release_and_free_resource(chip->res_port);
kfree(chip);
return 0;
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index b4819d5e41db..46b3629dda22 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1984,22 +1984,11 @@ static void __devexit snd_rme32_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver rme32_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_rme32_ids,
.probe = snd_rme32_probe,
.remove = __devexit_p(snd_rme32_remove),
};
-static int __init alsa_card_rme32_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_rme32_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_rme32_init)
-module_exit(alsa_card_rme32_exit)
+module_pci_driver(rme32_driver);
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index ba894158e76c..9b98dc406988 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -2395,22 +2395,11 @@ static void __devexit snd_rme96_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver rme96_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_rme96_ids,
.probe = snd_rme96_probe,
.remove = __devexit_p(snd_rme96_remove),
};
-static int __init alsa_card_rme96_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_rme96_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_rme96_init)
-module_exit(alsa_card_rme96_exit)
+module_pci_driver(rme96_driver);
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 0b2aea2ce172..0d6930c4f4b7 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -5636,22 +5636,11 @@ static void __devexit snd_hdsp_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver hdsp_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_hdsp_ids,
.probe = snd_hdsp_probe,
.remove = __devexit_p(snd_hdsp_remove),
};
-static int __init alsa_card_hdsp_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_hdsp_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_hdsp_init)
-module_exit(alsa_card_hdsp_exit)
+module_pci_driver(hdsp_driver);
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index bc030a2088da..0a5027b94714 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -6918,23 +6918,11 @@ static void __devexit snd_hdspm_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver hdspm_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_hdspm_ids,
.probe = snd_hdspm_probe,
.remove = __devexit_p(snd_hdspm_remove),
};
-
-static int __init alsa_card_hdspm_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_hdspm_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_hdspm_init)
-module_exit(alsa_card_hdspm_exit)
+module_pci_driver(hdspm_driver);
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index b737d1619cc7..a15fc100ab0c 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -2631,22 +2631,11 @@ static void __devexit snd_rme9652_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver rme9652_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_rme9652_ids,
.probe = snd_rme9652_probe,
.remove = __devexit_p(snd_rme9652_remove),
};
-static int __init alsa_card_hammerfall_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_hammerfall_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_hammerfall_init)
-module_exit(alsa_card_hammerfall_exit)
+module_pci_driver(rme9652_driver);
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index ff500a87f769..1552642765d6 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -1488,15 +1488,4 @@ static struct pci_driver sis7019_driver = {
#endif
};
-static int __init sis7019_init(void)
-{
- return pci_register_driver(&sis7019_driver);
-}
-
-static void __exit sis7019_exit(void)
-{
- pci_unregister_driver(&sis7019_driver);
-}
-
-module_init(sis7019_init);
-module_exit(sis7019_exit);
+module_pci_driver(sis7019_driver);
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 54cc802050f7..baa9946bedf0 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -1530,22 +1530,11 @@ static void __devexit snd_sonic_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver sonicvibes_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_sonic_ids,
.probe = snd_sonic_probe,
.remove = __devexit_p(snd_sonic_remove),
};
-static int __init alsa_card_sonicvibes_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_sonicvibes_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_sonicvibes_init)
-module_exit(alsa_card_sonicvibes_exit)
+module_pci_driver(sonicvibes_driver);
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 5f1def7f45e5..611983ec7321 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -172,7 +172,7 @@ static void __devexit snd_trident_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver trident_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_trident_ids,
.probe = snd_trident_probe,
@@ -183,15 +183,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_trident_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_trident_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_trident_init)
-module_exit(alsa_card_trident_exit)
+module_pci_driver(trident_driver);
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 75630408c6db..b5afab48943e 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -2619,7 +2619,7 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver via82xx_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_via82xx_ids,
.probe = snd_via82xx_probe,
@@ -2630,15 +2630,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_via82xx_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_via82xx_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_via82xx_init)
-module_exit(alsa_card_via82xx_exit)
+module_pci_driver(via82xx_driver);
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 5efcbcac506a..59fd47ed0a31 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -1223,7 +1223,7 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver via82xx_modem_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_via82xx_modem_ids,
.probe = snd_via82xx_probe,
@@ -1234,15 +1234,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_via82xx_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_via82xx_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_via82xx_init)
-module_exit(alsa_card_via82xx_exit)
+module_pci_driver(via82xx_modem_driver);
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index 6a534bfe1274..1ea1f656a5dc 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -289,7 +289,7 @@ static int snd_vx222_resume(struct pci_dev *pci)
}
#endif
-static struct pci_driver driver = {
+static struct pci_driver vx222_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_vx222_ids,
.probe = snd_vx222_probe,
@@ -300,15 +300,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_vx222_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_vx222_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_vx222_init)
-module_exit(alsa_card_vx222_exit)
+module_pci_driver(vx222_driver);
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 94ab728f5ca8..9a1d01d653a7 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -350,7 +350,7 @@ static void __devexit snd_card_ymfpci_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_driver driver = {
+static struct pci_driver ymfpci_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ymfpci_ids,
.probe = snd_card_ymfpci_probe,
@@ -361,15 +361,4 @@ static struct pci_driver driver = {
#endif
};
-static int __init alsa_card_ymfpci_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_ymfpci_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_ymfpci_init)
-module_exit(alsa_card_ymfpci_exit)
+module_pci_driver(ymfpci_driver);
diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c
index b11f82b5718f..f8b01c77b298 100644
--- a/sound/sh/sh_dac_audio.c
+++ b/sound/sh/sh_dac_audio.c
@@ -433,7 +433,7 @@ probe_error:
/*
* "driver" definition
*/
-static struct platform_driver driver = {
+static struct platform_driver sh_dac_driver = {
.probe = snd_sh_dac_probe,
.remove = snd_sh_dac_remove,
.driver = {
@@ -441,4 +441,4 @@ static struct platform_driver driver = {
},
};
-module_platform_driver(driver);
+module_platform_driver(sh_dac_driver);
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 91c985599d32..40b2ad1bb1cd 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -35,7 +35,6 @@ source "sound/soc/blackfin/Kconfig"
source "sound/soc/davinci/Kconfig"
source "sound/soc/ep93xx/Kconfig"
source "sound/soc/fsl/Kconfig"
-source "sound/soc/imx/Kconfig"
source "sound/soc/jz4740/Kconfig"
source "sound/soc/nuc900/Kconfig"
source "sound/soc/omap/Kconfig"
@@ -48,9 +47,13 @@ source "sound/soc/s6000/Kconfig"
source "sound/soc/sh/Kconfig"
source "sound/soc/tegra/Kconfig"
source "sound/soc/txx9/Kconfig"
+source "sound/soc/ux500/Kconfig"
# Supported codecs
source "sound/soc/codecs/Kconfig"
+# generic frame-work
+source "sound/soc/generic/Kconfig"
+
endif # SND_SOC
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 2feaf376e94b..70990f4017f4 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -6,13 +6,13 @@ obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o
obj-$(CONFIG_SND_SOC) += snd-soc-core.o
obj-$(CONFIG_SND_SOC) += codecs/
+obj-$(CONFIG_SND_SOC) += generic/
obj-$(CONFIG_SND_SOC) += atmel/
obj-$(CONFIG_SND_SOC) += au1x/
obj-$(CONFIG_SND_SOC) += blackfin/
obj-$(CONFIG_SND_SOC) += davinci/
obj-$(CONFIG_SND_SOC) += ep93xx/
obj-$(CONFIG_SND_SOC) += fsl/
-obj-$(CONFIG_SND_SOC) += imx/
obj-$(CONFIG_SND_SOC) += jz4740/
obj-$(CONFIG_SND_SOC) += mid-x86/
obj-$(CONFIG_SND_SOC) += mxs/
@@ -25,3 +25,4 @@ obj-$(CONFIG_SND_SOC) += s6000/
obj-$(CONFIG_SND_SOC) += sh/
obj-$(CONFIG_SND_SOC) += tegra/
obj-$(CONFIG_SND_SOC) += txx9/
+obj-$(CONFIG_SND_SOC) += ux500/
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c
index b39ad356b92b..7dbeef1099b4 100644
--- a/sound/soc/blackfin/bf5xx-ssm2602.c
+++ b/sound/soc/blackfin/bf5xx-ssm2602.c
@@ -44,16 +44,8 @@
static struct snd_soc_card bf5xx_ssm2602;
-static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+static int bf5xx_ssm2602_dai_init(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- unsigned int clk = 0;
- int ret = 0;
-
- pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
- params_format(params));
/*
* If you are using a crystal source which frequency is not 12MHz
* then modify the below case statement with frequency of the crystal.
@@ -61,31 +53,10 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
* If you are using the SPORT to generate clocking then this is
* where to do it.
*/
-
- switch (params_rate(params)) {
- case 8000:
- case 16000:
- case 48000:
- case 96000:
- case 11025:
- case 22050:
- case 44100:
- clk = 12000000;
- break;
- }
-
- ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
+ return snd_soc_dai_set_sysclk(rtd->codec_dai, SSM2602_SYSCLK, 12000000,
SND_SOC_CLOCK_IN);
- if (ret < 0)
- return ret;
-
- return 0;
}
-static struct snd_soc_ops bf5xx_ssm2602_ops = {
- .hw_params = bf5xx_ssm2602_hw_params,
-};
-
/* CODEC is master for BCLK and LRC in this configuration. */
#define BF5XX_SSM2602_DAIFMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \
SND_SOC_DAIFMT_CBM_CFM)
@@ -98,7 +69,7 @@ static struct snd_soc_dai_link bf5xx_ssm2602_dai[] = {
.codec_dai_name = "ssm2602-hifi",
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "ssm2602.0-001b",
- .ops = &bf5xx_ssm2602_ops,
+ .init = bf5xx_ssm2602_dai_init,
.dai_fmt = BF5XX_SSM2602_DAIFMT,
},
{
@@ -108,7 +79,7 @@ static struct snd_soc_dai_link bf5xx_ssm2602_dai[] = {
.codec_dai_name = "ssm2602-hifi",
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "ssm2602.0-001b",
- .ops = &bf5xx_ssm2602_ops,
+ .init = bf5xx_ssm2602_dai_init,
.dai_fmt = BF5XX_SSM2602_DAIFMT,
},
};
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 59d8efaa17e9..1e1613a438dd 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -29,6 +29,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_ALC5632 if I2C
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
select SND_SOC_CS42L51 if I2C
+ select SND_SOC_CS42L52 if I2C
select SND_SOC_CS42L73 if I2C
select SND_SOC_CS4270 if I2C
select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
@@ -37,11 +38,15 @@ config SND_SOC_ALL_CODECS
select SND_SOC_DFBMCS320
select SND_SOC_JZ4740_CODEC
select SND_SOC_LM4857 if I2C
+ select SND_SOC_LM49453 if I2C
select SND_SOC_MAX98088 if I2C
select SND_SOC_MAX98095 if I2C
select SND_SOC_MAX9850 if I2C
select SND_SOC_MAX9768 if I2C
select SND_SOC_MAX9877 if I2C
+ select SND_SOC_MC13783 if MFD_MC13XXX
+ select SND_SOC_ML26124 if I2C
+ select SND_SOC_OMAP_HDMI_CODEC if OMAP4_DSS_HDMI
select SND_SOC_PCM3008
select SND_SOC_RT5631 if I2C
select SND_SOC_SGTL5000 if I2C
@@ -181,6 +186,9 @@ config SND_SOC_CQ0093VC
config SND_SOC_CS42L51
tristate
+config SND_SOC_CS42L52
+ tristate
+
config SND_SOC_CS42L73
tristate
@@ -217,6 +225,9 @@ config SND_SOC_DFBMCS320
config SND_SOC_DMIC
tristate
+config SND_SOC_LM49453
+ tristate
+
config SND_SOC_MAX98088
tristate
@@ -226,6 +237,9 @@ config SND_SOC_MAX98095
config SND_SOC_MAX9850
tristate
+config SND_SOC_OMAP_HDMI_CODEC
+ tristate
+
config SND_SOC_PCM3008
tristate
@@ -435,5 +449,11 @@ config SND_SOC_MAX9768
config SND_SOC_MAX9877
tristate
+config SND_SOC_MC13783
+ tristate
+
+config SND_SOC_ML26124
+ tristate
+
config SND_SOC_TPA6130A2
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 6662eb0cdcc0..fc27fec39487 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -15,6 +15,7 @@ snd-soc-ak4642-objs := ak4642.o
snd-soc-ak4671-objs := ak4671.o
snd-soc-cq93vc-objs := cq93vc.o
snd-soc-cs42l51-objs := cs42l51.o
+snd-soc-cs42l52-objs := cs42l52.o
snd-soc-cs42l73-objs := cs42l73.o
snd-soc-cs4270-objs := cs4270.o
snd-soc-cs4271-objs := cs4271.o
@@ -25,10 +26,14 @@ snd-soc-dmic-objs := dmic.o
snd-soc-jz4740-codec-objs := jz4740.o
snd-soc-l3-objs := l3.o
snd-soc-lm4857-objs := lm4857.o
+snd-soc-lm49453-objs := lm49453.o
snd-soc-max9768-objs := max9768.o
snd-soc-max98088-objs := max98088.o
snd-soc-max98095-objs := max98095.o
snd-soc-max9850-objs := max9850.o
+snd-soc-mc13783-objs := mc13783.o
+snd-soc-ml26124-objs := ml26124.o
+snd-soc-omap-hdmi-codec-objs := omap-hdmi.o
snd-soc-pcm3008-objs := pcm3008.o
snd-soc-rt5631-objs := rt5631.o
snd-soc-sgtl5000-objs := sgtl5000.o
@@ -121,6 +126,7 @@ obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o
obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
+obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o
@@ -128,13 +134,17 @@ obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o
obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
+obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
-obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
+obj-$(CONFIG_SND_SOC_LM49453) += snd-soc-lm49453.o
obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o
obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
+obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
+obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
+obj-$(CONFIG_SND_SOC_OMAP_HDMI_CODEC) += snd-soc-omap-hdmi-codec.o
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 1bbad4c16d28..2023c749f232 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -26,13 +26,11 @@
static int ac97_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
- return snd_ac97_set_rate(codec->ac97, reg, runtime->rate);
+ return snd_ac97_set_rate(codec->ac97, reg, substream->runtime->rate);
}
#define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index 12e3b4118557..c67b50d8b317 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -162,9 +162,7 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
int word_len = 0;
-
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
/* bit size */
switch (params_format(params)) {
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index a4a6bef2c0bb..13e62be4f990 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -245,9 +245,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
int word_len = 0, master_rate = 0;
-
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
/* bit size */
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 78e9ce48bb99..3d50fc8646b6 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -258,8 +258,7 @@ static int adau1701_set_playback_pcm_format(struct snd_soc_codec *codec,
static int adau1701_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
snd_pcm_format_t format;
unsigned int val;
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index ceb96ecf5588..31d4483245d0 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -88,8 +88,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
int val = 0;
/* set the IEC958 bits: consumer mode, no copyright bit */
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 838ae8b22b50..618fdc30f73e 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -262,8 +262,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
u8 mode2 = snd_soc_read(codec, AK4535_MODE2) & ~(0x3 << 5);
int rate = params_rate(params), fs = 256;
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index c4d165a4bddf..543a12f471be 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -296,8 +296,7 @@ static int ak4641_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec);
int rate = params_rate(params), fs = 256;
u8 mode2;
@@ -517,67 +516,24 @@ static int ak4641_resume(struct snd_soc_codec *codec)
static int ak4641_probe(struct snd_soc_codec *codec)
{
- struct ak4641_platform_data *pdata = codec->dev->platform_data;
int ret;
-
- if (pdata) {
- if (gpio_is_valid(pdata->gpio_power)) {
- ret = gpio_request_one(pdata->gpio_power,
- GPIOF_OUT_INIT_LOW, "ak4641 power");
- if (ret)
- goto err_out;
- }
- if (gpio_is_valid(pdata->gpio_npdn)) {
- ret = gpio_request_one(pdata->gpio_npdn,
- GPIOF_OUT_INIT_LOW, "ak4641 npdn");
- if (ret)
- goto err_gpio;
-
- udelay(1); /* > 150 ns */
- gpio_set_value(pdata->gpio_npdn, 1);
- }
- }
-
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err_register;
+ return ret;
}
/* power on device */
ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
-
-err_register:
- if (pdata) {
- if (gpio_is_valid(pdata->gpio_power))
- gpio_set_value(pdata->gpio_power, 0);
- if (gpio_is_valid(pdata->gpio_npdn))
- gpio_free(pdata->gpio_npdn);
- }
-err_gpio:
- if (pdata && gpio_is_valid(pdata->gpio_power))
- gpio_free(pdata->gpio_power);
-err_out:
- return ret;
}
static int ak4641_remove(struct snd_soc_codec *codec)
{
- struct ak4641_platform_data *pdata = codec->dev->platform_data;
-
ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF);
- if (pdata) {
- if (gpio_is_valid(pdata->gpio_power)) {
- gpio_set_value(pdata->gpio_power, 0);
- gpio_free(pdata->gpio_power);
- }
- if (gpio_is_valid(pdata->gpio_npdn))
- gpio_free(pdata->gpio_npdn);
- }
return 0;
}
@@ -604,6 +560,7 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4641 = {
static int __devinit ak4641_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
+ struct ak4641_platform_data *pdata = i2c->dev.platform_data;
struct ak4641_priv *ak4641;
int ret;
@@ -612,16 +569,62 @@ static int __devinit ak4641_i2c_probe(struct i2c_client *i2c,
if (!ak4641)
return -ENOMEM;
+ if (pdata) {
+ if (gpio_is_valid(pdata->gpio_power)) {
+ ret = gpio_request_one(pdata->gpio_power,
+ GPIOF_OUT_INIT_LOW, "ak4641 power");
+ if (ret)
+ goto err_out;
+ }
+ if (gpio_is_valid(pdata->gpio_npdn)) {
+ ret = gpio_request_one(pdata->gpio_npdn,
+ GPIOF_OUT_INIT_LOW, "ak4641 npdn");
+ if (ret)
+ goto err_gpio;
+
+ udelay(1); /* > 150 ns */
+ gpio_set_value(pdata->gpio_npdn, 1);
+ }
+ }
+
i2c_set_clientdata(i2c, ak4641);
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_ak4641,
ak4641_dai, ARRAY_SIZE(ak4641_dai));
+ if (ret != 0)
+ goto err_gpio2;
+
+ return 0;
+
+err_gpio2:
+ if (pdata) {
+ if (gpio_is_valid(pdata->gpio_power))
+ gpio_set_value(pdata->gpio_power, 0);
+ if (gpio_is_valid(pdata->gpio_npdn))
+ gpio_free(pdata->gpio_npdn);
+ }
+err_gpio:
+ if (pdata && gpio_is_valid(pdata->gpio_power))
+ gpio_free(pdata->gpio_power);
+err_out:
return ret;
}
static int __devexit ak4641_i2c_remove(struct i2c_client *i2c)
{
+ struct ak4641_platform_data *pdata = i2c->dev.platform_data;
+
snd_soc_unregister_codec(&i2c->dev);
+
+ if (pdata) {
+ if (gpio_is_valid(pdata->gpio_power)) {
+ gpio_set_value(pdata->gpio_power, 0);
+ gpio_free(pdata->gpio_power);
+ }
+ if (gpio_is_valid(pdata->gpio_npdn))
+ gpio_free(pdata->gpio_npdn);
+ }
+
return 0;
}
@@ -641,23 +644,7 @@ static struct i2c_driver ak4641_i2c_driver = {
.id_table = ak4641_i2c_id,
};
-static int __init ak4641_modinit(void)
-{
- int ret;
-
- ret = i2c_add_driver(&ak4641_i2c_driver);
- if (ret != 0)
- pr_err("Failed to register AK4641 I2C driver: %d\n", ret);
-
- return ret;
-}
-module_init(ak4641_modinit);
-
-static void __exit ak4641_exit(void)
-{
- i2c_del_driver(&ak4641_i2c_driver);
-}
-module_exit(ak4641_exit);
+module_i2c_driver(ak4641_i2c_driver);
MODULE_DESCRIPTION("SoC AK4641 driver");
MODULE_AUTHOR("Harald Welte <laforge@gnufiish.org>");
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index d47b62ddb210..1960478ce6bb 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -705,8 +705,7 @@ static int alc5623_set_dai_fmt(struct snd_soc_dai *codec_dai,
static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
int coeff, rate;
u16 iface;
@@ -1084,25 +1083,7 @@ static struct i2c_driver alc5623_i2c_driver = {
.id_table = alc5623_i2c_table,
};
-static int __init alc5623_modinit(void)
-{
- int ret;
-
- ret = i2c_add_driver(&alc5623_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "%s: can't add i2c driver", __func__);
- return ret;
- }
-
- return ret;
-}
-module_init(alc5623_modinit);
-
-static void __exit alc5623_modexit(void)
-{
- i2c_del_driver(&alc5623_i2c_driver);
-}
-module_exit(alc5623_modexit);
+module_i2c_driver(alc5623_i2c_driver);
MODULE_DESCRIPTION("ASoC alc5621/2/3 driver");
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
index e2111e0ccad7..7dd02420b36d 100644
--- a/sound/soc/codecs/alc5632.c
+++ b/sound/soc/codecs/alc5632.c
@@ -861,8 +861,7 @@ static int alc5632_set_dai_fmt(struct snd_soc_dai *codec_dai,
static int alc5632_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
int coeff, rate;
u16 iface;
@@ -1131,7 +1130,7 @@ static __devinit int alc5632_i2c_probe(struct i2c_client *client,
i2c_set_clientdata(client, alc5632);
- alc5632->regmap = regmap_init_i2c(client, &alc5632_regmap);
+ alc5632->regmap = devm_regmap_init_i2c(client, &alc5632_regmap);
if (IS_ERR(alc5632->regmap)) {
ret = PTR_ERR(alc5632->regmap);
dev_err(&client->dev, "regmap_init() failed: %d\n", ret);
@@ -1143,7 +1142,6 @@ static __devinit int alc5632_i2c_probe(struct i2c_client *client,
if (ret1 != 0 || ret2 != 0) {
dev_err(&client->dev,
"Failed to read chip ID: ret1=%d, ret2=%d\n", ret1, ret2);
- regmap_exit(alc5632->regmap);
return -EIO;
}
@@ -1152,14 +1150,12 @@ static __devinit int alc5632_i2c_probe(struct i2c_client *client,
if ((vid1 != 0x10EC) || (vid2 != id->driver_data)) {
dev_err(&client->dev,
"Device is not a ALC5632: VID1=0x%x, VID2=0x%x\n", vid1, vid2);
- regmap_exit(alc5632->regmap);
return -EINVAL;
}
ret = alc5632_reset(alc5632->regmap);
if (ret < 0) {
dev_err(&client->dev, "Failed to issue reset\n");
- regmap_exit(alc5632->regmap);
return ret;
}
@@ -1177,7 +1173,6 @@ static __devinit int alc5632_i2c_probe(struct i2c_client *client,
if (ret < 0) {
dev_err(&client->dev, "Failed to register codec: %d\n", ret);
- regmap_exit(alc5632->regmap);
return ret;
}
@@ -1186,9 +1181,7 @@ static __devinit int alc5632_i2c_probe(struct i2c_client *client,
static __devexit int alc5632_i2c_remove(struct i2c_client *client)
{
- struct alc5632_priv *alc5632 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
- regmap_exit(alc5632->regmap);
return 0;
}
@@ -1209,25 +1202,7 @@ static struct i2c_driver alc5632_i2c_driver = {
.id_table = alc5632_i2c_table,
};
-static int __init alc5632_modinit(void)
-{
- int ret;
-
- ret = i2c_add_driver(&alc5632_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "%s: can't add i2c driver", __func__);
- return ret;
- }
-
- return ret;
-}
-module_init(alc5632_modinit);
-
-static void __exit alc5632_modexit(void)
-{
- i2c_del_driver(&alc5632_i2c_driver);
-}
-module_exit(alc5632_modexit);
+module_i2c_driver(alc5632_i2c_driver);
MODULE_DESCRIPTION("ASoC ALC5632 driver");
MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 1d672f528662..047917f0b8ae 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -307,8 +307,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int ret;
unsigned int i;
@@ -600,10 +599,12 @@ static int cs4270_soc_suspend(struct snd_soc_codec *codec)
static int cs4270_soc_resume(struct snd_soc_codec *codec)
{
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
- int reg;
+ int reg, ret;
- regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
- cs4270->supplies);
+ ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
+ cs4270->supplies);
+ if (ret != 0)
+ return ret;
/* In case the device was put to hard reset during sleep, we need to
* wait 500ns here before any I2C communication. */
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index bf7141280a74..9eb01d7d58a3 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -318,8 +318,7 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
int i, ret;
unsigned int ratio, val;
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index a8bf588e8740..091d0193f507 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -141,15 +141,15 @@ static const struct soc_enum cs42l51_chan_mix =
static const struct snd_kcontrol_new cs42l51_snd_controls[] = {
SOC_DOUBLE_R_SX_TLV("PCM Playback Volume",
CS42L51_PCMA_VOL, CS42L51_PCMB_VOL,
- 7, 0xffffff99, 0x18, adc_pcm_tlv),
+ 6, 0x19, 0x7F, adc_pcm_tlv),
SOC_DOUBLE_R("PCM Playback Switch",
CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1),
SOC_DOUBLE_R_SX_TLV("Analog Playback Volume",
CS42L51_AOUTA_VOL, CS42L51_AOUTB_VOL,
- 8, 0xffffff19, 0x18, aout_tlv),
+ 0, 0x34, 0xE4, aout_tlv),
SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
CS42L51_ADCA_VOL, CS42L51_ADCB_VOL,
- 7, 0xffffff99, 0x18, adc_pcm_tlv),
+ 6, 0x19, 0x7F, adc_pcm_tlv),
SOC_DOUBLE_R("ADC Mixer Switch",
CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1),
SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0),
@@ -356,8 +356,7 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
int ret;
unsigned int i;
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
new file mode 100644
index 000000000000..a7109413aef1
--- /dev/null
+++ b/sound/soc/codecs/cs42l52.c
@@ -0,0 +1,1295 @@
+/*
+ * cs42l52.c -- CS42L52 ALSA SoC audio driver
+ *
+ * Copyright 2012 CirrusLogic, Inc.
+ *
+ * Author: Georgi Vlaev <joe@nucleusys.com>
+ * Author: Brian Austin <brian.austin@cirrus.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/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/cs42l52.h>
+#include "cs42l52.h"
+
+struct sp_config {
+ u8 spc, format, spfs;
+ u32 srate;
+};
+
+struct cs42l52_private {
+ struct regmap *regmap;
+ struct snd_soc_codec *codec;
+ struct device *dev;
+ struct sp_config config;
+ struct cs42l52_platform_data pdata;
+ u32 sysclk;
+ u8 mclksel;
+ u32 mclk;
+ u8 flags;
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+ struct input_dev *beep;
+ struct work_struct beep_work;
+ int beep_rate;
+#endif
+};
+
+static const struct reg_default cs42l52_reg_defaults[] = {
+ { CS42L52_PWRCTL1, 0x9F }, /* r02 PWRCTL 1 */
+ { CS42L52_PWRCTL2, 0x07 }, /* r03 PWRCTL 2 */
+ { CS42L52_PWRCTL3, 0xFF }, /* r04 PWRCTL 3 */
+ { CS42L52_CLK_CTL, 0xA0 }, /* r05 Clocking Ctl */
+ { CS42L52_IFACE_CTL1, 0x00 }, /* r06 Interface Ctl 1 */
+ { CS42L52_ADC_PGA_A, 0x80 }, /* r08 Input A Select */
+ { CS42L52_ADC_PGA_B, 0x80 }, /* r09 Input B Select */
+ { CS42L52_ANALOG_HPF_CTL, 0xA5 }, /* r0A Analog HPF Ctl */
+ { CS42L52_ADC_HPF_FREQ, 0x00 }, /* r0B ADC HPF Corner Freq */
+ { CS42L52_ADC_MISC_CTL, 0x00 }, /* r0C Misc. ADC Ctl */
+ { CS42L52_PB_CTL1, 0x60 }, /* r0D Playback Ctl 1 */
+ { CS42L52_MISC_CTL, 0x02 }, /* r0E Misc. Ctl */
+ { CS42L52_PB_CTL2, 0x00 }, /* r0F Playback Ctl 2 */
+ { CS42L52_MICA_CTL, 0x00 }, /* r10 MICA Amp Ctl */
+ { CS42L52_MICB_CTL, 0x00 }, /* r11 MICB Amp Ctl */
+ { CS42L52_PGAA_CTL, 0x00 }, /* r12 PGAA Vol, Misc. */
+ { CS42L52_PGAB_CTL, 0x00 }, /* r13 PGAB Vol, Misc. */
+ { CS42L52_PASSTHRUA_VOL, 0x00 }, /* r14 Bypass A Vol */
+ { CS42L52_PASSTHRUB_VOL, 0x00 }, /* r15 Bypass B Vol */
+ { CS42L52_ADCA_VOL, 0x00 }, /* r16 ADCA Volume */
+ { CS42L52_ADCB_VOL, 0x00 }, /* r17 ADCB Volume */
+ { CS42L52_ADCA_MIXER_VOL, 0x80 }, /* r18 ADCA Mixer Volume */
+ { CS42L52_ADCB_MIXER_VOL, 0x80 }, /* r19 ADCB Mixer Volume */
+ { CS42L52_PCMA_MIXER_VOL, 0x00 }, /* r1A PCMA Mixer Volume */
+ { CS42L52_PCMB_MIXER_VOL, 0x00 }, /* r1B PCMB Mixer Volume */
+ { CS42L52_BEEP_FREQ, 0x00 }, /* r1C Beep Freq on Time */
+ { CS42L52_BEEP_VOL, 0x00 }, /* r1D Beep Volume off Time */
+ { CS42L52_BEEP_TONE_CTL, 0x00 }, /* r1E Beep Tone Cfg. */
+ { CS42L52_TONE_CTL, 0x00 }, /* r1F Tone Ctl */
+ { CS42L52_MASTERA_VOL, 0x88 }, /* r20 Master A Volume */
+ { CS42L52_MASTERB_VOL, 0x00 }, /* r21 Master B Volume */
+ { CS42L52_HPA_VOL, 0x00 }, /* r22 Headphone A Volume */
+ { CS42L52_HPB_VOL, 0x00 }, /* r23 Headphone B Volume */
+ { CS42L52_SPKA_VOL, 0x00 }, /* r24 Speaker A Volume */
+ { CS42L52_SPKB_VOL, 0x00 }, /* r25 Speaker B Volume */
+ { CS42L52_ADC_PCM_MIXER, 0x00 }, /* r26 Channel Mixer and Swap */
+ { CS42L52_LIMITER_CTL1, 0x00 }, /* r27 Limit Ctl 1 Thresholds */
+ { CS42L52_LIMITER_CTL2, 0x7F }, /* r28 Limit Ctl 2 Release Rate */
+ { CS42L52_LIMITER_AT_RATE, 0xC0 }, /* r29 Limiter Attack Rate */
+ { CS42L52_ALC_CTL, 0x00 }, /* r2A ALC Ctl 1 Attack Rate */
+ { CS42L52_ALC_RATE, 0x3F }, /* r2B ALC Release Rate */
+ { CS42L52_ALC_THRESHOLD, 0x3f }, /* r2C ALC Thresholds */
+ { CS42L52_NOISE_GATE_CTL, 0x00 }, /* r2D Noise Gate Ctl */
+ { CS42L52_CLK_STATUS, 0x00 }, /* r2E Overflow and Clock Status */
+ { CS42L52_BATT_COMPEN, 0x00 }, /* r2F battery Compensation */
+ { CS42L52_BATT_LEVEL, 0x00 }, /* r30 VP Battery Level */
+ { CS42L52_SPK_STATUS, 0x00 }, /* r31 Speaker Status */
+ { CS42L52_TEM_CTL, 0x3B }, /* r32 Temp Ctl */
+ { CS42L52_THE_FOLDBACK, 0x00 }, /* r33 Foldback */
+};
+
+static bool cs42l52_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS42L52_CHIP:
+ case CS42L52_PWRCTL1:
+ case CS42L52_PWRCTL2:
+ case CS42L52_PWRCTL3:
+ case CS42L52_CLK_CTL:
+ case CS42L52_IFACE_CTL1:
+ case CS42L52_IFACE_CTL2:
+ case CS42L52_ADC_PGA_A:
+ case CS42L52_ADC_PGA_B:
+ case CS42L52_ANALOG_HPF_CTL:
+ case CS42L52_ADC_HPF_FREQ:
+ case CS42L52_ADC_MISC_CTL:
+ case CS42L52_PB_CTL1:
+ case CS42L52_MISC_CTL:
+ case CS42L52_PB_CTL2:
+ case CS42L52_MICA_CTL:
+ case CS42L52_MICB_CTL:
+ case CS42L52_PGAA_CTL:
+ case CS42L52_PGAB_CTL:
+ case CS42L52_PASSTHRUA_VOL:
+ case CS42L52_PASSTHRUB_VOL:
+ case CS42L52_ADCA_VOL:
+ case CS42L52_ADCB_VOL:
+ case CS42L52_ADCA_MIXER_VOL:
+ case CS42L52_ADCB_MIXER_VOL:
+ case CS42L52_PCMA_MIXER_VOL:
+ case CS42L52_PCMB_MIXER_VOL:
+ case CS42L52_BEEP_FREQ:
+ case CS42L52_BEEP_VOL:
+ case CS42L52_BEEP_TONE_CTL:
+ case CS42L52_TONE_CTL:
+ case CS42L52_MASTERA_VOL:
+ case CS42L52_MASTERB_VOL:
+ case CS42L52_HPA_VOL:
+ case CS42L52_HPB_VOL:
+ case CS42L52_SPKA_VOL:
+ case CS42L52_SPKB_VOL:
+ case CS42L52_ADC_PCM_MIXER:
+ case CS42L52_LIMITER_CTL1:
+ case CS42L52_LIMITER_CTL2:
+ case CS42L52_LIMITER_AT_RATE:
+ case CS42L52_ALC_CTL:
+ case CS42L52_ALC_RATE:
+ case CS42L52_ALC_THRESHOLD:
+ case CS42L52_NOISE_GATE_CTL:
+ case CS42L52_CLK_STATUS:
+ case CS42L52_BATT_COMPEN:
+ case CS42L52_BATT_LEVEL:
+ case CS42L52_SPK_STATUS:
+ case CS42L52_TEM_CTL:
+ case CS42L52_THE_FOLDBACK:
+ case CS42L52_CHARGE_PUMP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs42l52_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS42L52_IFACE_CTL2:
+ case CS42L52_CLK_STATUS:
+ case CS42L52_BATT_LEVEL:
+ case CS42L52_SPK_STATUS:
+ case CS42L52_CHARGE_PUMP:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static DECLARE_TLV_DB_SCALE(hl_tlv, -10200, 50, 0);
+
+static DECLARE_TLV_DB_SCALE(hpd_tlv, -9600, 50, 1);
+
+static DECLARE_TLV_DB_SCALE(ipd_tlv, -9600, 100, 0);
+
+static DECLARE_TLV_DB_SCALE(mic_tlv, 1600, 100, 0);
+
+static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0);
+
+static const unsigned int limiter_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
+ 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0),
+};
+
+static const char * const cs42l52_adca_text[] = {
+ "Input1A", "Input2A", "Input3A", "Input4A", "PGA Input Left"};
+
+static const char * const cs42l52_adcb_text[] = {
+ "Input1B", "Input2B", "Input3B", "Input4B", "PGA Input Right"};
+
+static const struct soc_enum adca_enum =
+ SOC_ENUM_SINGLE(CS42L52_ADC_PGA_A, 5,
+ ARRAY_SIZE(cs42l52_adca_text), cs42l52_adca_text);
+
+static const struct soc_enum adcb_enum =
+ SOC_ENUM_SINGLE(CS42L52_ADC_PGA_B, 5,
+ ARRAY_SIZE(cs42l52_adcb_text), cs42l52_adcb_text);
+
+static const struct snd_kcontrol_new adca_mux =
+ SOC_DAPM_ENUM("Left ADC Input Capture Mux", adca_enum);
+
+static const struct snd_kcontrol_new adcb_mux =
+ SOC_DAPM_ENUM("Right ADC Input Capture Mux", adcb_enum);
+
+static const char * const mic_bias_level_text[] = {
+ "0.5 +VA", "0.6 +VA", "0.7 +VA",
+ "0.8 +VA", "0.83 +VA", "0.91 +VA"
+};
+
+static const struct soc_enum mic_bias_level_enum =
+ SOC_ENUM_SINGLE(CS42L52_IFACE_CTL1, 0,
+ ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text);
+
+static const char * const cs42l52_mic_text[] = { "Single", "Differential" };
+
+static const struct soc_enum mica_enum =
+ SOC_ENUM_SINGLE(CS42L52_MICA_CTL, 5,
+ ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text);
+
+static const struct soc_enum micb_enum =
+ SOC_ENUM_SINGLE(CS42L52_MICB_CTL, 5,
+ ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text);
+
+static const struct snd_kcontrol_new mica_mux =
+ SOC_DAPM_ENUM("Left Mic Input Capture Mux", mica_enum);
+
+static const struct snd_kcontrol_new micb_mux =
+ SOC_DAPM_ENUM("Right Mic Input Capture Mux", micb_enum);
+
+static const char * const digital_output_mux_text[] = {"ADC", "DSP"};
+
+static const struct soc_enum digital_output_mux_enum =
+ SOC_ENUM_SINGLE(CS42L52_ADC_MISC_CTL, 6,
+ ARRAY_SIZE(digital_output_mux_text),
+ digital_output_mux_text);
+
+static const struct snd_kcontrol_new digital_output_mux =
+ SOC_DAPM_ENUM("Digital Output Mux", digital_output_mux_enum);
+
+static const char * const hp_gain_num_text[] = {
+ "0.3959", "0.4571", "0.5111", "0.6047",
+ "0.7099", "0.8399", "1.000", "1.1430"
+};
+
+static const struct soc_enum hp_gain_enum =
+ SOC_ENUM_SINGLE(CS42L52_PB_CTL1, 4,
+ ARRAY_SIZE(hp_gain_num_text), hp_gain_num_text);
+
+static const char * const beep_pitch_text[] = {
+ "C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5",
+ "C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7"
+};
+
+static const struct soc_enum beep_pitch_enum =
+ SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 4,
+ ARRAY_SIZE(beep_pitch_text), beep_pitch_text);
+
+static const char * const beep_ontime_text[] = {
+ "86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s",
+ "1.80 s", "2.20 s", "2.50 s", "2.80 s", "3.20 s",
+ "3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s"
+};
+
+static const struct soc_enum beep_ontime_enum =
+ SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 0,
+ ARRAY_SIZE(beep_ontime_text), beep_ontime_text);
+
+static const char * const beep_offtime_text[] = {
+ "1.23 s", "2.58 s", "3.90 s", "5.20 s",
+ "6.60 s", "8.05 s", "9.35 s", "10.80 s"
+};
+
+static const struct soc_enum beep_offtime_enum =
+ SOC_ENUM_SINGLE(CS42L52_BEEP_VOL, 5,
+ ARRAY_SIZE(beep_offtime_text), beep_offtime_text);
+
+static const char * const beep_config_text[] = {
+ "Off", "Single", "Multiple", "Continuous"
+};
+
+static const struct soc_enum beep_config_enum =
+ SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 6,
+ ARRAY_SIZE(beep_config_text), beep_config_text);
+
+static const char * const beep_bass_text[] = {
+ "50 Hz", "100 Hz", "200 Hz", "250 Hz"
+};
+
+static const struct soc_enum beep_bass_enum =
+ SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 1,
+ ARRAY_SIZE(beep_bass_text), beep_bass_text);
+
+static const char * const beep_treble_text[] = {
+ "5 kHz", "7 kHz", "10 kHz", " 15 kHz"
+};
+
+static const struct soc_enum beep_treble_enum =
+ SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 3,
+ ARRAY_SIZE(beep_treble_text), beep_treble_text);
+
+static const char * const ng_threshold_text[] = {
+ "-34dB", "-37dB", "-40dB", "-43dB",
+ "-46dB", "-52dB", "-58dB", "-64dB"
+};
+
+static const struct soc_enum ng_threshold_enum =
+ SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 2,
+ ARRAY_SIZE(ng_threshold_text), ng_threshold_text);
+
+static const char * const cs42l52_ng_delay_text[] = {
+ "50ms", "100ms", "150ms", "200ms"};
+
+static const struct soc_enum ng_delay_enum =
+ SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 0,
+ ARRAY_SIZE(cs42l52_ng_delay_text), cs42l52_ng_delay_text);
+
+static const char * const cs42l52_ng_type_text[] = {
+ "Apply Specific", "Apply All"
+};
+
+static const struct soc_enum ng_type_enum =
+ SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 6,
+ ARRAY_SIZE(cs42l52_ng_type_text), cs42l52_ng_type_text);
+
+static const char * const left_swap_text[] = {
+ "Left", "LR 2", "Right"};
+
+static const char * const right_swap_text[] = {
+ "Right", "LR 2", "Left"};
+
+static const unsigned int swap_values[] = { 0, 1, 3 };
+
+static const struct soc_enum adca_swap_enum =
+ SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 1,
+ ARRAY_SIZE(left_swap_text),
+ left_swap_text,
+ swap_values);
+
+static const struct snd_kcontrol_new adca_mixer =
+ SOC_DAPM_ENUM("Route", adca_swap_enum);
+
+static const struct soc_enum pcma_swap_enum =
+ SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 1,
+ ARRAY_SIZE(left_swap_text),
+ left_swap_text,
+ swap_values);
+
+static const struct snd_kcontrol_new pcma_mixer =
+ SOC_DAPM_ENUM("Route", pcma_swap_enum);
+
+static const struct soc_enum adcb_swap_enum =
+ SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 1,
+ ARRAY_SIZE(right_swap_text),
+ right_swap_text,
+ swap_values);
+
+static const struct snd_kcontrol_new adcb_mixer =
+ SOC_DAPM_ENUM("Route", adcb_swap_enum);
+
+static const struct soc_enum pcmb_swap_enum =
+ SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 1,
+ ARRAY_SIZE(right_swap_text),
+ right_swap_text,
+ swap_values);
+
+static const struct snd_kcontrol_new pcmb_mixer =
+ SOC_DAPM_ENUM("Route", pcmb_swap_enum);
+
+
+static const struct snd_kcontrol_new passthrul_ctl =
+ SOC_DAPM_SINGLE("Switch", CS42L52_MISC_CTL, 6, 1, 0);
+
+static const struct snd_kcontrol_new passthrur_ctl =
+ SOC_DAPM_SINGLE("Switch", CS42L52_MISC_CTL, 7, 1, 0);
+
+static const struct snd_kcontrol_new spkl_ctl =
+ SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 0, 1, 1);
+
+static const struct snd_kcontrol_new spkr_ctl =
+ SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 2, 1, 1);
+
+static const struct snd_kcontrol_new hpl_ctl =
+ SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 4, 1, 1);
+
+static const struct snd_kcontrol_new hpr_ctl =
+ SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 6, 1, 1);
+
+static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
+
+ SOC_DOUBLE_R_SX_TLV("Master Volume", CS42L52_MASTERA_VOL,
+ CS42L52_MASTERB_VOL, 0, 0x34, 0xE4, hl_tlv),
+
+ SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L52_HPA_VOL,
+ CS42L52_HPB_VOL, 0, 0x34, 0xCC, hpd_tlv),
+
+ SOC_ENUM("Headphone Analog Gain", hp_gain_enum),
+
+ SOC_DOUBLE_R_SX_TLV("Speaker Volume", CS42L52_SPKA_VOL,
+ CS42L52_SPKB_VOL, 7, 0x1, 0xff, hl_tlv),
+
+ SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL,
+ CS42L52_PASSTHRUB_VOL, 6, 0x18, 0x90, pga_tlv),
+
+ SOC_DOUBLE("Bypass Mute", CS42L52_MISC_CTL, 4, 5, 1, 0),
+
+ SOC_DOUBLE_R_TLV("MIC Gain Volume", CS42L52_MICA_CTL,
+ CS42L52_MICB_CTL, 0, 0x10, 0, mic_tlv),
+
+ SOC_ENUM("MIC Bias Level", mic_bias_level_enum),
+
+ SOC_DOUBLE_R_SX_TLV("ADC Volume", CS42L52_ADCA_VOL,
+ CS42L52_ADCB_VOL, 7, 0x80, 0xA0, ipd_tlv),
+ SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
+ CS42L52_ADCA_MIXER_VOL, CS42L52_ADCB_MIXER_VOL,
+ 6, 0x7f, 0x19, ipd_tlv),
+
+ SOC_DOUBLE("ADC Switch", CS42L52_ADC_MISC_CTL, 0, 1, 1, 0),
+
+ SOC_DOUBLE_R("ADC Mixer Switch", CS42L52_ADCA_MIXER_VOL,
+ CS42L52_ADCB_MIXER_VOL, 7, 1, 1),
+
+ SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L52_PGAA_CTL,
+ CS42L52_PGAB_CTL, 0, 0x28, 0x30, pga_tlv),
+
+ SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume",
+ CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL,
+ 6, 0x7f, 0x19, hl_tlv),
+ SOC_DOUBLE_R("PCM Mixer Switch",
+ CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, 7, 1, 1),
+
+ SOC_ENUM("Beep Config", beep_config_enum),
+ SOC_ENUM("Beep Pitch", beep_pitch_enum),
+ SOC_ENUM("Beep on Time", beep_ontime_enum),
+ SOC_ENUM("Beep off Time", beep_offtime_enum),
+ SOC_SINGLE_TLV("Beep Volume", CS42L52_BEEP_VOL, 0, 0x1f, 0x07, hl_tlv),
+ SOC_SINGLE("Beep Mixer Switch", CS42L52_BEEP_TONE_CTL, 5, 1, 1),
+ SOC_ENUM("Beep Treble Corner Freq", beep_treble_enum),
+ SOC_ENUM("Beep Bass Corner Freq", beep_bass_enum),
+
+ SOC_SINGLE("Tone Control Switch", CS42L52_BEEP_TONE_CTL, 0, 1, 1),
+ SOC_SINGLE_TLV("Treble Gain Volume",
+ CS42L52_TONE_CTL, 4, 15, 1, hl_tlv),
+ SOC_SINGLE_TLV("Bass Gain Volume",
+ CS42L52_TONE_CTL, 0, 15, 1, hl_tlv),
+
+ /* Limiter */
+ SOC_SINGLE_TLV("Limiter Max Threshold Volume",
+ CS42L52_LIMITER_CTL1, 5, 7, 0, limiter_tlv),
+ SOC_SINGLE_TLV("Limiter Cushion Threshold Volume",
+ CS42L52_LIMITER_CTL1, 2, 7, 0, limiter_tlv),
+ SOC_SINGLE_TLV("Limiter Release Rate Volume",
+ CS42L52_LIMITER_CTL2, 0, 63, 0, limiter_tlv),
+ SOC_SINGLE_TLV("Limiter Attack Rate Volume",
+ CS42L52_LIMITER_AT_RATE, 0, 63, 0, limiter_tlv),
+
+ SOC_SINGLE("Limiter SR Switch", CS42L52_LIMITER_CTL1, 1, 1, 0),
+ SOC_SINGLE("Limiter ZC Switch", CS42L52_LIMITER_CTL1, 0, 1, 0),
+ SOC_SINGLE("Limiter Switch", CS42L52_LIMITER_CTL2, 7, 1, 0),
+
+ /* ALC */
+ SOC_SINGLE_TLV("ALC Attack Rate Volume", CS42L52_ALC_CTL,
+ 0, 63, 0, limiter_tlv),
+ SOC_SINGLE_TLV("ALC Release Rate Volume", CS42L52_ALC_RATE,
+ 0, 63, 0, limiter_tlv),
+ SOC_SINGLE_TLV("ALC Max Threshold Volume", CS42L52_ALC_THRESHOLD,
+ 5, 7, 0, limiter_tlv),
+ SOC_SINGLE_TLV("ALC Min Threshold Volume", CS42L52_ALC_THRESHOLD,
+ 2, 7, 0, limiter_tlv),
+
+ SOC_DOUBLE_R("ALC SR Capture Switch", CS42L52_PGAA_CTL,
+ CS42L52_PGAB_CTL, 7, 1, 1),
+ SOC_DOUBLE_R("ALC ZC Capture Switch", CS42L52_PGAA_CTL,
+ CS42L52_PGAB_CTL, 6, 1, 1),
+ SOC_DOUBLE("ALC Capture Switch", CS42L52_ALC_CTL, 6, 7, 1, 0),
+
+ /* Noise gate */
+ SOC_ENUM("NG Type Switch", ng_type_enum),
+ SOC_SINGLE("NG Enable Switch", CS42L52_NOISE_GATE_CTL, 6, 1, 0),
+ SOC_SINGLE("NG Boost Switch", CS42L52_NOISE_GATE_CTL, 5, 1, 1),
+ SOC_ENUM("NG Threshold", ng_threshold_enum),
+ SOC_ENUM("NG Delay", ng_delay_enum),
+
+ SOC_DOUBLE("HPF Switch", CS42L52_ANALOG_HPF_CTL, 5, 7, 1, 0),
+
+ SOC_DOUBLE("Analog SR Switch", CS42L52_ANALOG_HPF_CTL, 1, 3, 1, 1),
+ SOC_DOUBLE("Analog ZC Switch", CS42L52_ANALOG_HPF_CTL, 0, 2, 1, 1),
+ SOC_SINGLE("Digital SR Switch", CS42L52_MISC_CTL, 1, 1, 0),
+ SOC_SINGLE("Digital ZC Switch", CS42L52_MISC_CTL, 0, 1, 0),
+ SOC_SINGLE("Deemphasis Switch", CS42L52_MISC_CTL, 2, 1, 0),
+
+ SOC_SINGLE("Batt Compensation Switch", CS42L52_BATT_COMPEN, 7, 1, 0),
+ SOC_SINGLE("Batt VP Monitor Switch", CS42L52_BATT_COMPEN, 6, 1, 0),
+ SOC_SINGLE("Batt VP ref", CS42L52_BATT_COMPEN, 0, 0x0f, 0),
+
+ SOC_SINGLE("PGA AIN1L Switch", CS42L52_ADC_PGA_A, 0, 1, 0),
+ SOC_SINGLE("PGA AIN1R Switch", CS42L52_ADC_PGA_B, 0, 1, 0),
+ SOC_SINGLE("PGA AIN2L Switch", CS42L52_ADC_PGA_A, 1, 1, 0),
+ SOC_SINGLE("PGA AIN2R Switch", CS42L52_ADC_PGA_B, 1, 1, 0),
+
+ SOC_SINGLE("PGA AIN3L Switch", CS42L52_ADC_PGA_A, 2, 1, 0),
+ SOC_SINGLE("PGA AIN3R Switch", CS42L52_ADC_PGA_B, 2, 1, 0),
+
+ SOC_SINGLE("PGA AIN4L Switch", CS42L52_ADC_PGA_A, 3, 1, 0),
+ SOC_SINGLE("PGA AIN4R Switch", CS42L52_ADC_PGA_B, 3, 1, 0),
+
+ SOC_SINGLE("PGA MICA Switch", CS42L52_ADC_PGA_A, 4, 1, 0),
+ SOC_SINGLE("PGA MICB Switch", CS42L52_ADC_PGA_B, 4, 1, 0),
+
+};
+
+static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = {
+
+ SND_SOC_DAPM_INPUT("AIN1L"),
+ SND_SOC_DAPM_INPUT("AIN1R"),
+ SND_SOC_DAPM_INPUT("AIN2L"),
+ SND_SOC_DAPM_INPUT("AIN2R"),
+ SND_SOC_DAPM_INPUT("AIN3L"),
+ SND_SOC_DAPM_INPUT("AIN3R"),
+ SND_SOC_DAPM_INPUT("AIN4L"),
+ SND_SOC_DAPM_INPUT("AIN4R"),
+ SND_SOC_DAPM_INPUT("MICA"),
+ SND_SOC_DAPM_INPUT("MICB"),
+ SND_SOC_DAPM_SIGGEN("Beep"),
+
+ SND_SOC_DAPM_AIF_OUT("AIFOUTL", NULL, 0,
+ SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIFOUTR", NULL, 0,
+ SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_MUX("MICA Mux", SND_SOC_NOPM, 0, 0, &mica_mux),
+ SND_SOC_DAPM_MUX("MICB Mux", SND_SOC_NOPM, 0, 0, &micb_mux),
+
+ SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L52_PWRCTL1, 1, 1),
+ SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L52_PWRCTL1, 2, 1),
+ SND_SOC_DAPM_PGA("PGA Left", CS42L52_PWRCTL1, 3, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("PGA Right", CS42L52_PWRCTL1, 4, 1, NULL, 0),
+
+ SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adca_mux),
+ SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcb_mux),
+
+ SND_SOC_DAPM_MUX("ADC Left Swap", SND_SOC_NOPM,
+ 0, 0, &adca_mixer),
+ SND_SOC_DAPM_MUX("ADC Right Swap", SND_SOC_NOPM,
+ 0, 0, &adcb_mixer),
+
+ SND_SOC_DAPM_MUX("Output Mux", SND_SOC_NOPM,
+ 0, 0, &digital_output_mux),
+
+ SND_SOC_DAPM_PGA("PGA MICA", CS42L52_PWRCTL2, 1, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("PGA MICB", CS42L52_PWRCTL2, 2, 1, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("Mic Bias", CS42L52_PWRCTL2, 0, 1, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Charge Pump", CS42L52_PWRCTL1, 7, 1, NULL, 0),
+
+ SND_SOC_DAPM_AIF_IN("AIFINL", NULL, 0,
+ SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIFINR", NULL, 0,
+ SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_DAC("DAC Left", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("DAC Right", NULL, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_SWITCH("Bypass Left", CS42L52_MISC_CTL,
+ 6, 0, &passthrul_ctl),
+ SND_SOC_DAPM_SWITCH("Bypass Right", CS42L52_MISC_CTL,
+ 7, 0, &passthrur_ctl),
+
+ SND_SOC_DAPM_MUX("PCM Left Swap", SND_SOC_NOPM,
+ 0, 0, &pcma_mixer),
+ SND_SOC_DAPM_MUX("PCM Right Swap", SND_SOC_NOPM,
+ 0, 0, &pcmb_mixer),
+
+ SND_SOC_DAPM_SWITCH("HP Left Amp", SND_SOC_NOPM, 0, 0, &hpl_ctl),
+ SND_SOC_DAPM_SWITCH("HP Right Amp", SND_SOC_NOPM, 0, 0, &hpr_ctl),
+
+ SND_SOC_DAPM_SWITCH("SPK Left Amp", SND_SOC_NOPM, 0, 0, &spkl_ctl),
+ SND_SOC_DAPM_SWITCH("SPK Right Amp", SND_SOC_NOPM, 0, 0, &spkr_ctl),
+
+ SND_SOC_DAPM_OUTPUT("HPOUTA"),
+ SND_SOC_DAPM_OUTPUT("HPOUTB"),
+ SND_SOC_DAPM_OUTPUT("SPKOUTA"),
+ SND_SOC_DAPM_OUTPUT("SPKOUTB"),
+
+};
+
+static const struct snd_soc_dapm_route cs42l52_audio_map[] = {
+
+ {"Capture", NULL, "AIFOUTL"},
+ {"Capture", NULL, "AIFOUTL"},
+
+ {"AIFOUTL", NULL, "Output Mux"},
+ {"AIFOUTR", NULL, "Output Mux"},
+
+ {"Output Mux", "ADC", "ADC Left"},
+ {"Output Mux", "ADC", "ADC Right"},
+
+ {"ADC Left", NULL, "Charge Pump"},
+ {"ADC Right", NULL, "Charge Pump"},
+
+ {"Charge Pump", NULL, "ADC Left Mux"},
+ {"Charge Pump", NULL, "ADC Right Mux"},
+
+ {"ADC Left Mux", "Input1A", "AIN1L"},
+ {"ADC Right Mux", "Input1B", "AIN1R"},
+ {"ADC Left Mux", "Input2A", "AIN2L"},
+ {"ADC Right Mux", "Input2B", "AIN2R"},
+ {"ADC Left Mux", "Input3A", "AIN3L"},
+ {"ADC Right Mux", "Input3B", "AIN3R"},
+ {"ADC Left Mux", "Input4A", "AIN4L"},
+ {"ADC Right Mux", "Input4B", "AIN4R"},
+ {"ADC Left Mux", "PGA Input Left", "PGA Left"},
+ {"ADC Right Mux", "PGA Input Right" , "PGA Right"},
+
+ {"PGA Left", "Switch", "AIN1L"},
+ {"PGA Right", "Switch", "AIN1R"},
+ {"PGA Left", "Switch", "AIN2L"},
+ {"PGA Right", "Switch", "AIN2R"},
+ {"PGA Left", "Switch", "AIN3L"},
+ {"PGA Right", "Switch", "AIN3R"},
+ {"PGA Left", "Switch", "AIN4L"},
+ {"PGA Right", "Switch", "AIN4R"},
+
+ {"PGA Left", "Switch", "PGA MICA"},
+ {"PGA MICA", NULL, "MICA"},
+
+ {"PGA Right", "Switch", "PGA MICB"},
+ {"PGA MICB", NULL, "MICB"},
+
+ {"HPOUTA", NULL, "HP Left Amp"},
+ {"HPOUTB", NULL, "HP Right Amp"},
+ {"HP Left Amp", NULL, "Bypass Left"},
+ {"HP Right Amp", NULL, "Bypass Right"},
+ {"Bypass Left", "Switch", "PGA Left"},
+ {"Bypass Right", "Switch", "PGA Right"},
+ {"HP Left Amp", "Switch", "DAC Left"},
+ {"HP Right Amp", "Switch", "DAC Right"},
+
+ {"SPKOUTA", NULL, "SPK Left Amp"},
+ {"SPKOUTB", NULL, "SPK Right Amp"},
+
+ {"SPK Left Amp", NULL, "Beep"},
+ {"SPK Right Amp", NULL, "Beep"},
+ {"SPK Left Amp", "Switch", "Playback"},
+ {"SPK Right Amp", "Switch", "Playback"},
+
+ {"DAC Left", NULL, "Beep"},
+ {"DAC Right", NULL, "Beep"},
+ {"DAC Left", NULL, "Playback"},
+ {"DAC Right", NULL, "Playback"},
+
+ {"Output Mux", "DSP", "Playback"},
+ {"Output Mux", "DSP", "Playback"},
+
+ {"AIFINL", NULL, "Playback"},
+ {"AIFINR", NULL, "Playback"},
+
+};
+
+struct cs42l52_clk_para {
+ u32 mclk;
+ u32 rate;
+ u8 speed;
+ u8 group;
+ u8 videoclk;
+ u8 ratio;
+ u8 mclkdiv2;
+};
+
+static const struct cs42l52_clk_para clk_map_table[] = {
+ /*8k*/
+ {12288000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
+ {18432000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
+ {12000000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 0},
+ {24000000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 1},
+ {27000000, 8000, CLK_QS_MODE, CLK_32K, CLK_27M_MCLK, CLK_R_125, 0},
+
+ /*11.025k*/
+ {11289600, 11025, CLK_QS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
+ {16934400, 11025, CLK_QS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
+
+ /*16k*/
+ {12288000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
+ {18432000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
+ {12000000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 0},
+ {24000000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 1},
+ {27000000, 16000, CLK_HS_MODE, CLK_32K, CLK_27M_MCLK, CLK_R_125, 1},
+
+ /*22.05k*/
+ {11289600, 22050, CLK_HS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
+ {16934400, 22050, CLK_HS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
+
+ /* 32k */
+ {12288000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
+ {18432000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
+ {12000000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 0},
+ {24000000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 1},
+ {27000000, 32000, CLK_SS_MODE, CLK_32K, CLK_27M_MCLK, CLK_R_125, 0},
+
+ /* 44.1k */
+ {11289600, 44100, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
+ {16934400, 44100, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
+
+ /* 48k */
+ {12288000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
+ {18432000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
+ {12000000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 0},
+ {24000000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 1},
+ {27000000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_27M_MCLK, CLK_R_125, 1},
+
+ /* 88.2k */
+ {11289600, 88200, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
+ {16934400, 88200, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
+
+ /* 96k */
+ {12288000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
+ {18432000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
+ {12000000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 0},
+ {24000000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 1},
+};
+
+static int cs42l52_get_clk(int mclk, int rate)
+{
+ int i, ret = 0;
+ u_int mclk1, mclk2 = 0;
+
+ for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
+ if (clk_map_table[i].rate == rate) {
+ mclk1 = clk_map_table[i].mclk;
+ if (abs(mclk - mclk1) < abs(mclk - mclk2)) {
+ mclk2 = mclk1;
+ ret = i;
+ }
+ }
+ }
+ if (ret > ARRAY_SIZE(clk_map_table))
+ return -EINVAL;
+ return ret;
+}
+
+static int cs42l52_set_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
+
+ if ((freq >= CS42L52_MIN_CLK) && (freq <= CS42L52_MAX_CLK)) {
+ cs42l52->sysclk = freq;
+ } else {
+ dev_err(codec->dev, "Invalid freq paramter\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+ u8 iface = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ iface = CS42L52_IFACE_CTL1_MASTER;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ iface = CS42L52_IFACE_CTL1_SLAVE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ iface |= CS42L52_IFACE_CTL1_ADC_FMT_I2S |
+ CS42L52_IFACE_CTL1_DAC_FMT_I2S;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ iface |= CS42L52_IFACE_CTL1_DAC_FMT_RIGHT_J;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iface |= CS42L52_IFACE_CTL1_ADC_FMT_LEFT_J |
+ CS42L52_IFACE_CTL1_DAC_FMT_LEFT_J;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ iface |= CS42L52_IFACE_CTL1_DSP_MODE_EN;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ iface |= CS42L52_IFACE_CTL1_INV_SCLK;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface |= CS42L52_IFACE_CTL1_INV_SCLK;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ cs42l52->config.format = iface;
+ snd_soc_write(codec, CS42L52_IFACE_CTL1, cs42l52->config.format);
+
+ return 0;
+}
+
+static int cs42l52_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+
+ if (mute)
+ snd_soc_update_bits(codec, CS42L52_PB_CTL1,
+ CS42L52_PB_CTL1_MUTE_MASK,
+ CS42L52_PB_CTL1_MUTE);
+ else
+ snd_soc_update_bits(codec, CS42L52_PB_CTL1,
+ CS42L52_PB_CTL1_MUTE_MASK,
+ CS42L52_PB_CTL1_UNMUTE);
+
+ return 0;
+}
+
+static int cs42l52_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
+ u32 clk = 0;
+ int index;
+
+ index = cs42l52_get_clk(cs42l52->sysclk, params_rate(params));
+ if (index >= 0) {
+ cs42l52->sysclk = clk_map_table[index].mclk;
+
+ clk |= (clk_map_table[index].speed << CLK_SPEED_SHIFT) |
+ (clk_map_table[index].group << CLK_32K_SR_SHIFT) |
+ (clk_map_table[index].videoclk << CLK_27M_MCLK_SHIFT) |
+ (clk_map_table[index].ratio << CLK_RATIO_SHIFT) |
+ clk_map_table[index].mclkdiv2;
+
+ snd_soc_write(codec, CS42L52_CLK_CTL, clk);
+ } else {
+ dev_err(codec->dev, "can't get correct mclk\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cs42l52_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ snd_soc_update_bits(codec, CS42L52_PWRCTL1,
+ CS42L52_PWRCTL1_PDN_CODEC, 0);
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ regcache_cache_only(cs42l52->regmap, false);
+ regcache_sync(cs42l52->regmap);
+ }
+ snd_soc_write(codec, CS42L52_PWRCTL1, CS42L52_PWRCTL1_PDN_ALL);
+ break;
+ case SND_SOC_BIAS_OFF:
+ snd_soc_write(codec, CS42L52_PWRCTL1, CS42L52_PWRCTL1_PDN_ALL);
+ regcache_cache_only(cs42l52->regmap, true);
+ break;
+ }
+ codec->dapm.bias_level = level;
+
+ return 0;
+}
+
+#define CS42L52_RATES (SNDRV_PCM_RATE_8000_96000)
+
+#define CS42L52_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \
+ SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE)
+
+static struct snd_soc_dai_ops cs42l52_ops = {
+ .hw_params = cs42l52_pcm_hw_params,
+ .digital_mute = cs42l52_digital_mute,
+ .set_fmt = cs42l52_set_fmt,
+ .set_sysclk = cs42l52_set_sysclk,
+};
+
+static struct snd_soc_dai_driver cs42l52_dai = {
+ .name = "cs42l52",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = CS42L52_RATES,
+ .formats = CS42L52_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = CS42L52_RATES,
+ .formats = CS42L52_FORMATS,
+ },
+ .ops = &cs42l52_ops,
+};
+
+static int cs42l52_suspend(struct snd_soc_codec *codec)
+{
+ cs42l52_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static int cs42l52_resume(struct snd_soc_codec *codec)
+{
+ cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ return 0;
+}
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static int beep_rates[] = {
+ 261, 522, 585, 667, 706, 774, 889, 1000,
+ 1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182
+};
+
+static void cs42l52_beep_work(struct work_struct *work)
+{
+ struct cs42l52_private *cs42l52 =
+ container_of(work, struct cs42l52_private, beep_work);
+ struct snd_soc_codec *codec = cs42l52->codec;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ int i;
+ int val = 0;
+ int best = 0;
+
+ if (cs42l52->beep_rate) {
+ for (i = 0; i < ARRAY_SIZE(beep_rates); i++) {
+ if (abs(cs42l52->beep_rate - beep_rates[i]) <
+ abs(cs42l52->beep_rate - beep_rates[best]))
+ best = i;
+ }
+
+ dev_dbg(codec->dev, "Set beep rate %dHz for requested %dHz\n",
+ beep_rates[best], cs42l52->beep_rate);
+
+ val = (best << CS42L52_BEEP_RATE_SHIFT);
+
+ snd_soc_dapm_enable_pin(dapm, "Beep");
+ } else {
+ dev_dbg(codec->dev, "Disabling beep\n");
+ snd_soc_dapm_disable_pin(dapm, "Beep");
+ }
+
+ snd_soc_update_bits(codec, CS42L52_BEEP_FREQ,
+ CS42L52_BEEP_RATE_MASK, val);
+
+ snd_soc_dapm_sync(dapm);
+}
+
+/* For usability define a way of injecting beep events for the device -
+ * many systems will not have a keyboard.
+ */
+static int cs42l52_beep_event(struct input_dev *dev, unsigned int type,
+ unsigned int code, int hz)
+{
+ struct snd_soc_codec *codec = input_get_drvdata(dev);
+ struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "Beep event %x %x\n", code, hz);
+
+ switch (code) {
+ case SND_BELL:
+ if (hz)
+ hz = 261;
+ case SND_TONE:
+ break;
+ default:
+ return -1;
+ }
+
+ /* Kick the beep from a workqueue */
+ cs42l52->beep_rate = hz;
+ schedule_work(&cs42l52->beep_work);
+ return 0;
+}
+
+static ssize_t cs42l52_beep_set(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cs42l52_private *cs42l52 = dev_get_drvdata(dev);
+ long int time;
+ int ret;
+
+ ret = kstrtol(buf, 10, &time);
+ if (ret != 0)
+ return ret;
+
+ input_event(cs42l52->beep, EV_SND, SND_TONE, time);
+
+ return count;
+}
+
+static DEVICE_ATTR(beep, 0200, NULL, cs42l52_beep_set);
+
+static void cs42l52_init_beep(struct snd_soc_codec *codec)
+{
+ struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ cs42l52->beep = input_allocate_device();
+ if (!cs42l52->beep) {
+ dev_err(codec->dev, "Failed to allocate beep device\n");
+ return;
+ }
+
+ INIT_WORK(&cs42l52->beep_work, cs42l52_beep_work);
+ cs42l52->beep_rate = 0;
+
+ cs42l52->beep->name = "CS42L52 Beep Generator";
+ cs42l52->beep->phys = dev_name(codec->dev);
+ cs42l52->beep->id.bustype = BUS_I2C;
+
+ cs42l52->beep->evbit[0] = BIT_MASK(EV_SND);
+ cs42l52->beep->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
+ cs42l52->beep->event = cs42l52_beep_event;
+ cs42l52->beep->dev.parent = codec->dev;
+ input_set_drvdata(cs42l52->beep, codec);
+
+ ret = input_register_device(cs42l52->beep);
+ if (ret != 0) {
+ input_free_device(cs42l52->beep);
+ cs42l52->beep = NULL;
+ dev_err(codec->dev, "Failed to register beep device\n");
+ }
+
+ ret = device_create_file(codec->dev, &dev_attr_beep);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to create keyclick file: %d\n",
+ ret);
+ }
+}
+
+static void cs42l52_free_beep(struct snd_soc_codec *codec)
+{
+ struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
+
+ device_remove_file(codec->dev, &dev_attr_beep);
+ input_unregister_device(cs42l52->beep);
+ cancel_work_sync(&cs42l52->beep_work);
+ cs42l52->beep = NULL;
+
+ snd_soc_update_bits(codec, CS42L52_BEEP_TONE_CTL,
+ CS42L52_BEEP_EN_MASK, 0);
+}
+#else
+static void cs42l52_init_beep(struct snd_soc_codec *codec)
+{
+}
+
+static void cs42l52_free_beep(struct snd_soc_codec *codec)
+{
+}
+#endif
+
+static int cs42l52_probe(struct snd_soc_codec *codec)
+{
+ struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ codec->control_data = cs42l52->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+ regcache_cache_only(cs42l52->regmap, true);
+
+ cs42l52_init_beep(codec);
+
+ cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ cs42l52->sysclk = CS42L52_DEFAULT_CLK;
+ cs42l52->config.format = CS42L52_DEFAULT_FORMAT;
+
+ /* Set Platform MICx CFG */
+ snd_soc_update_bits(codec, CS42L52_MICA_CTL,
+ CS42L52_MIC_CTL_TYPE_MASK,
+ cs42l52->pdata.mica_cfg <<
+ CS42L52_MIC_CTL_TYPE_SHIFT);
+
+ snd_soc_update_bits(codec, CS42L52_MICB_CTL,
+ CS42L52_MIC_CTL_TYPE_MASK,
+ cs42l52->pdata.micb_cfg <<
+ CS42L52_MIC_CTL_TYPE_SHIFT);
+
+ /* if Single Ended, Get Mic_Select */
+ if (cs42l52->pdata.mica_cfg)
+ snd_soc_update_bits(codec, CS42L52_MICA_CTL,
+ CS42L52_MIC_CTL_MIC_SEL_MASK,
+ cs42l52->pdata.mica_sel <<
+ CS42L52_MIC_CTL_MIC_SEL_SHIFT);
+ if (cs42l52->pdata.micb_cfg)
+ snd_soc_update_bits(codec, CS42L52_MICB_CTL,
+ CS42L52_MIC_CTL_MIC_SEL_MASK,
+ cs42l52->pdata.micb_sel <<
+ CS42L52_MIC_CTL_MIC_SEL_SHIFT);
+
+ /* Set Platform Charge Pump Freq */
+ snd_soc_update_bits(codec, CS42L52_CHARGE_PUMP,
+ CS42L52_CHARGE_PUMP_MASK,
+ cs42l52->pdata.chgfreq <<
+ CS42L52_CHARGE_PUMP_SHIFT);
+
+ /* Set Platform Bias Level */
+ snd_soc_update_bits(codec, CS42L52_IFACE_CTL2,
+ CS42L52_IFACE_CTL2_BIAS_LVL,
+ cs42l52->pdata.micbias_lvl);
+
+ return ret;
+}
+
+static int cs42l52_remove(struct snd_soc_codec *codec)
+{
+ cs42l52_free_beep(codec);
+ cs42l52_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_cs42l52 = {
+ .probe = cs42l52_probe,
+ .remove = cs42l52_remove,
+ .suspend = cs42l52_suspend,
+ .resume = cs42l52_resume,
+ .set_bias_level = cs42l52_set_bias_level,
+
+ .dapm_widgets = cs42l52_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(cs42l52_dapm_widgets),
+ .dapm_routes = cs42l52_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(cs42l52_audio_map),
+
+ .controls = cs42l52_snd_controls,
+ .num_controls = ARRAY_SIZE(cs42l52_snd_controls),
+};
+
+/* Current and threshold powerup sequence Pg37 */
+static const struct reg_default cs42l52_threshold_patch[] = {
+
+ { 0x00, 0x99 },
+ { 0x3E, 0xBA },
+ { 0x47, 0x80 },
+ { 0x32, 0xBB },
+ { 0x32, 0x3B },
+ { 0x00, 0x00 },
+
+};
+
+static struct regmap_config cs42l52_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = CS42L52_MAX_REGISTER,
+ .reg_defaults = cs42l52_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(cs42l52_reg_defaults),
+ .readable_reg = cs42l52_readable_register,
+ .volatile_reg = cs42l52_volatile_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
+ const struct i2c_device_id *id)
+{
+ struct cs42l52_private *cs42l52;
+ int ret;
+ unsigned int devid = 0;
+ unsigned int reg;
+
+ cs42l52 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l52_private),
+ GFP_KERNEL);
+ if (cs42l52 == NULL)
+ return -ENOMEM;
+ cs42l52->dev = &i2c_client->dev;
+
+ cs42l52->regmap = regmap_init_i2c(i2c_client, &cs42l52_regmap);
+ if (IS_ERR(cs42l52->regmap)) {
+ ret = PTR_ERR(cs42l52->regmap);
+ dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+ goto err;
+ }
+
+ i2c_set_clientdata(i2c_client, cs42l52);
+
+ if (dev_get_platdata(&i2c_client->dev))
+ memcpy(&cs42l52->pdata, dev_get_platdata(&i2c_client->dev),
+ sizeof(cs42l52->pdata));
+
+ ret = regmap_register_patch(cs42l52->regmap, cs42l52_threshold_patch,
+ ARRAY_SIZE(cs42l52_threshold_patch));
+ if (ret != 0)
+ dev_warn(cs42l52->dev, "Failed to apply regmap patch: %d\n",
+ ret);
+
+ ret = regmap_read(cs42l52->regmap, CS42L52_CHIP, &reg);
+ devid = reg & CS42L52_CHIP_ID_MASK;
+ if (devid != CS42L52_CHIP_ID) {
+ ret = -ENODEV;
+ dev_err(&i2c_client->dev,
+ "CS42L52 Device ID (%X). Expected %X\n",
+ devid, CS42L52_CHIP_ID);
+ goto err_regmap;
+ }
+
+ regcache_cache_only(cs42l52->regmap, true);
+
+ ret = snd_soc_register_codec(&i2c_client->dev,
+ &soc_codec_dev_cs42l52, &cs42l52_dai, 1);
+ if (ret < 0)
+ goto err_regmap;
+ return 0;
+
+err_regmap:
+ regmap_exit(cs42l52->regmap);
+
+err:
+ return ret;
+}
+
+static int cs42l52_i2c_remove(struct i2c_client *client)
+{
+ struct cs42l52_private *cs42l52 = i2c_get_clientdata(client);
+
+ snd_soc_unregister_codec(&client->dev);
+ regmap_exit(cs42l52->regmap);
+
+ return 0;
+}
+
+static const struct i2c_device_id cs42l52_id[] = {
+ { "cs42l52", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, cs42l52_id);
+
+static struct i2c_driver cs42l52_i2c_driver = {
+ .driver = {
+ .name = "cs42l52",
+ .owner = THIS_MODULE,
+ },
+ .id_table = cs42l52_id,
+ .probe = cs42l52_i2c_probe,
+ .remove = __devexit_p(cs42l52_i2c_remove),
+};
+
+module_i2c_driver(cs42l52_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC CS42L52 driver");
+MODULE_AUTHOR("Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>");
+MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l52.h b/sound/soc/codecs/cs42l52.h
new file mode 100644
index 000000000000..60985c059071
--- /dev/null
+++ b/sound/soc/codecs/cs42l52.h
@@ -0,0 +1,274 @@
+/*
+ * cs42l52.h -- CS42L52 ALSA SoC audio driver
+ *
+ * Copyright 2012 CirrusLogic, Inc.
+ *
+ * Author: Georgi Vlaev <joe@nucleusys.com>
+ * Author: Brian Austin <brian.austin@cirrus.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 __CS42L52_H__
+#define __CS42L52_H__
+
+#define CS42L52_NAME "CS42L52"
+#define CS42L52_DEFAULT_CLK 12000000
+#define CS42L52_MIN_CLK 11000000
+#define CS42L52_MAX_CLK 27000000
+#define CS42L52_DEFAULT_FORMAT SNDRV_PCM_FMTBIT_S16_LE
+#define CS42L52_DEFAULT_MAX_CHANS 2
+#define CS42L52_SYSCLK 1
+
+#define CS42L52_CHIP_SWICTH (1 << 17)
+#define CS42L52_ALL_IN_ONE (1 << 16)
+#define CS42L52_CHIP_ONE 0x00
+#define CS42L52_CHIP_TWO 0x01
+#define CS42L52_CHIP_THR 0x02
+#define CS42L52_CHIP_MASK 0x0f
+
+#define CS42L52_FIX_BITS_CTL 0x00
+#define CS42L52_CHIP 0x01
+#define CS42L52_CHIP_ID 0xE0
+#define CS42L52_CHIP_ID_MASK 0xF8
+#define CS42L52_CHIP_REV_A0 0x00
+#define CS42L52_CHIP_REV_A1 0x01
+#define CS42L52_CHIP_REV_B0 0x02
+#define CS42L52_CHIP_REV_MASK 0x03
+
+#define CS42L52_PWRCTL1 0x02
+#define CS42L52_PWRCTL1_PDN_ALL 0x9F
+#define CS42L52_PWRCTL1_PDN_CHRG 0x80
+#define CS42L52_PWRCTL1_PDN_PGAB 0x10
+#define CS42L52_PWRCTL1_PDN_PGAA 0x08
+#define CS42L52_PWRCTL1_PDN_ADCB 0x04
+#define CS42L52_PWRCTL1_PDN_ADCA 0x02
+#define CS42L52_PWRCTL1_PDN_CODEC 0x01
+
+#define CS42L52_PWRCTL2 0x03
+#define CS42L52_PWRCTL2_OVRDB (1 << 4)
+#define CS42L52_PWRCTL2_OVRDA (1 << 3)
+#define CS42L52_PWRCTL2_PDN_MICB (1 << 2)
+#define CS42L52_PWRCTL2_PDN_MICB_SHIFT 2
+#define CS42L52_PWRCTL2_PDN_MICA (1 << 1)
+#define CS42L52_PWRCTL2_PDN_MICA_SHIFT 1
+#define CS42L52_PWRCTL2_PDN_MICBIAS (1 << 0)
+#define CS42L52_PWRCTL2_PDN_MICBIAS_SHIFT 0
+
+#define CS42L52_PWRCTL3 0x04
+#define CS42L52_PWRCTL3_HPB_PDN_SHIFT 6
+#define CS42L52_PWRCTL3_HPB_ON_LOW 0x00
+#define CS42L52_PWRCTL3_HPB_ON_HIGH 0x01
+#define CS42L52_PWRCTL3_HPB_ALWAYS_ON 0x02
+#define CS42L52_PWRCTL3_HPB_ALWAYS_OFF 0x03
+#define CS42L52_PWRCTL3_HPA_PDN_SHIFT 4
+#define CS42L52_PWRCTL3_HPA_ON_LOW 0x00
+#define CS42L52_PWRCTL3_HPA_ON_HIGH 0x01
+#define CS42L52_PWRCTL3_HPA_ALWAYS_ON 0x02
+#define CS42L52_PWRCTL3_HPA_ALWAYS_OFF 0x03
+#define CS42L52_PWRCTL3_SPKB_PDN_SHIFT 2
+#define CS42L52_PWRCTL3_SPKB_ON_LOW 0x00
+#define CS42L52_PWRCTL3_SPKB_ON_HIGH 0x01
+#define CS42L52_PWRCTL3_SPKB_ALWAYS_ON 0x02
+#define CS42L52_PWRCTL3_PDN_SPKB (1 << 2)
+#define CS42L52_PWRCTL3_PDN_SPKA (1 << 0)
+#define CS42L52_PWRCTL3_SPKA_PDN_SHIFT 0
+#define CS42L52_PWRCTL3_SPKA_ON_LOW 0x00
+#define CS42L52_PWRCTL3_SPKA_ON_HIGH 0x01
+#define CS42L52_PWRCTL3_SPKA_ALWAYS_ON 0x02
+
+#define CS42L52_DEFAULT_OUTPUT_STATE 0x05
+#define CS42L52_PWRCTL3_CONF_MASK 0x03
+
+#define CS42L52_CLK_CTL 0x05
+#define CLK_AUTODECT_ENABLE (1 << 7)
+#define CLK_SPEED_SHIFT 5
+#define CLK_DS_MODE 0x00
+#define CLK_SS_MODE 0x01
+#define CLK_HS_MODE 0x02
+#define CLK_QS_MODE 0x03
+#define CLK_32K_SR_SHIFT 4
+#define CLK_32K 0x01
+#define CLK_NO_32K 0x00
+#define CLK_27M_MCLK_SHIFT 3
+#define CLK_27M_MCLK 0x01
+#define CLK_NO_27M 0x00
+#define CLK_RATIO_SHIFT 1
+#define CLK_R_128 0x00
+#define CLK_R_125 0x01
+#define CLK_R_132 0x02
+#define CLK_R_136 0x03
+
+#define CS42L52_IFACE_CTL1 0x06
+#define CS42L52_IFACE_CTL1_MASTER (1 << 7)
+#define CS42L52_IFACE_CTL1_SLAVE (0 << 7)
+#define CS42L52_IFACE_CTL1_INV_SCLK (1 << 6)
+#define CS42L52_IFACE_CTL1_ADC_FMT_I2S (1 << 5)
+#define CS42L52_IFACE_CTL1_ADC_FMT_LEFT_J (0 << 5)
+#define CS42L52_IFACE_CTL1_DSP_MODE_EN (1 << 4)
+#define CS42L52_IFACE_CTL1_DAC_FMT_LEFT_J (0 << 2)
+#define CS42L52_IFACE_CTL1_DAC_FMT_I2S (1 << 2)
+#define CS42L52_IFACE_CTL1_DAC_FMT_RIGHT_J (2 << 2)
+#define CS42L52_IFACE_CTL1_WL_32BIT (0x00)
+#define CS42L52_IFACE_CTL1_WL_24BIT (0x01)
+#define CS42L52_IFACE_CTL1_WL_20BIT (0x02)
+#define CS42L52_IFACE_CTL1_WL_16BIT (0x03)
+#define CS42L52_IFACE_CTL1_WL_MASK 0xFFFF
+
+#define CS42L52_IFACE_CTL2 0x07
+#define CS42L52_IFACE_CTL2_SC_MC_EQ (1 << 6)
+#define CS42L52_IFACE_CTL2_LOOPBACK (1 << 5)
+#define CS42L52_IFACE_CTL2_S_MODE_OUTPUT_EN (0 << 4)
+#define CS42L52_IFACE_CTL2_S_MODE_OUTPUT_HIZ (1 << 4)
+#define CS42L52_IFACE_CTL2_HP_SW_INV (1 << 3)
+#define CS42L52_IFACE_CTL2_BIAS_LVL 0x07
+
+#define CS42L52_ADC_PGA_A 0x08
+#define CS42L52_ADC_PGA_B 0x09
+#define CS42L52_ADC_SEL_SHIFT 5
+#define CS42L52_ADC_SEL_AIN1 0x00
+#define CS42L52_ADC_SEL_AIN2 0x01
+#define CS42L52_ADC_SEL_AIN3 0x02
+#define CS42L52_ADC_SEL_AIN4 0x03
+#define CS42L52_ADC_SEL_PGA 0x04
+
+#define CS42L52_ANALOG_HPF_CTL 0x0A
+#define CS42L52_HPF_CTL_ANLGSFTB (1 << 3)
+#define CS42L52_HPF_CTL_ANLGSFTA (1 << 0)
+
+#define CS42L52_ADC_HPF_FREQ 0x0B
+#define CS42L52_ADC_MISC_CTL 0x0C
+#define CS42L52_ADC_MISC_CTL_SOURCE_DSP (1 << 6)
+
+#define CS42L52_PB_CTL1 0x0D
+#define CS42L52_PB_CTL1_HP_GAIN_SHIFT 5
+#define CS42L52_PB_CTL1_HP_GAIN_03959 0x00
+#define CS42L52_PB_CTL1_HP_GAIN_04571 0x01
+#define CS42L52_PB_CTL1_HP_GAIN_05111 0x02
+#define CS42L52_PB_CTL1_HP_GAIN_06047 0x03
+#define CS42L52_PB_CTL1_HP_GAIN_07099 0x04
+#define CS42L52_PB_CTL1_HP_GAIN_08399 0x05
+#define CS42L52_PB_CTL1_HP_GAIN_10000 0x06
+#define CS42L52_PB_CTL1_HP_GAIN_11430 0x07
+#define CS42L52_PB_CTL1_INV_PCMB (1 << 3)
+#define CS42L52_PB_CTL1_INV_PCMA (1 << 2)
+#define CS42L52_PB_CTL1_MSTB_MUTE (1 << 1)
+#define CS42L52_PB_CTL1_MSTA_MUTE (1 << 0)
+#define CS42L52_PB_CTL1_MUTE_MASK 0xFFFD
+#define CS42L52_PB_CTL1_MUTE 3
+#define CS42L52_PB_CTL1_UNMUTE 0
+
+#define CS42L52_MISC_CTL 0x0E
+#define CS42L52_MISC_CTL_DEEMPH (1 << 2)
+#define CS42L52_MISC_CTL_DIGSFT (1 << 1)
+#define CS42L52_MISC_CTL_DIGZC (1 << 0)
+
+#define CS42L52_PB_CTL2 0x0F
+#define CS42L52_PB_CTL2_HPB_MUTE (1 << 7)
+#define CS42L52_PB_CTL2_HPA_MUTE (1 << 6)
+#define CS42L52_PB_CTL2_SPKB_MUTE (1 << 5)
+#define CS42L52_PB_CTL2_SPKA_MUTE (1 << 4)
+#define CS42L52_PB_CTL2_SPK_SWAP (1 << 2)
+#define CS42L52_PB_CTL2_SPK_MONO (1 << 1)
+#define CS42L52_PB_CTL2_SPK_MUTE50 (1 << 0)
+
+#define CS42L52_MICA_CTL 0x10
+#define CS42L52_MICB_CTL 0x11
+#define CS42L52_MIC_CTL_MIC_SEL_MASK 0xBF
+#define CS42L52_MIC_CTL_MIC_SEL_SHIFT 6
+#define CS42L52_MIC_CTL_TYPE_MASK 0xDF
+#define CS42L52_MIC_CTL_TYPE_SHIFT 5
+
+
+#define CS42L52_PGAA_CTL 0x12
+#define CS42L52_PGAB_CTL 0x13
+#define CS42L52_PGAX_CTL_VOL_12DB 24
+#define CS42L52_PGAX_CTL_VOL_6DB 12 /*step size 0.5db*/
+
+#define CS42L52_PASSTHRUA_VOL 0x14
+#define CS42L52_PASSTHRUB_VOL 0x15
+
+#define CS42L52_ADCA_VOL 0x16
+#define CS42L52_ADCB_VOL 0x17
+#define CS42L52_ADCX_VOL_24DB 24 /*step size 1db*/
+#define CS42L52_ADCX_VOL_12DB 12
+#define CS42L52_ADCX_VOL_6DB 6
+
+#define CS42L52_ADCA_MIXER_VOL 0x18
+#define CS42L52_ADCB_MIXER_VOL 0x19
+#define CS42L52_ADC_MIXER_VOL_12DB 0x18
+
+#define CS42L52_PCMA_MIXER_VOL 0x1A
+#define CS42L52_PCMB_MIXER_VOL 0x1B
+
+#define CS42L52_BEEP_FREQ 0x1C
+#define CS42L52_BEEP_VOL 0x1D
+#define CS42L52_BEEP_TONE_CTL 0x1E
+#define CS42L52_BEEP_RATE_SHIFT 4
+#define CS42L52_BEEP_RATE_MASK 0x0F
+
+#define CS42L52_TONE_CTL 0x1F
+#define CS42L52_BEEP_EN_MASK 0x3F
+
+#define CS42L52_MASTERA_VOL 0x20
+#define CS42L52_MASTERB_VOL 0x21
+
+#define CS42L52_HPA_VOL 0x22
+#define CS42L52_HPB_VOL 0x23
+#define CS42L52_DEFAULT_HP_VOL 0xF0
+
+#define CS42L52_SPKA_VOL 0x24
+#define CS42L52_SPKB_VOL 0x25
+#define CS42L52_DEFAULT_SPK_VOL 0xF0
+
+#define CS42L52_ADC_PCM_MIXER 0x26
+
+#define CS42L52_LIMITER_CTL1 0x27
+#define CS42L52_LIMITER_CTL2 0x28
+#define CS42L52_LIMITER_AT_RATE 0x29
+
+#define CS42L52_ALC_CTL 0x2A
+#define CS42L52_ALC_CTL_ALCB_ENABLE_SHIFT 7
+#define CS42L52_ALC_CTL_ALCA_ENABLE_SHIFT 6
+#define CS42L52_ALC_CTL_FASTEST_ATTACK 0
+
+#define CS42L52_ALC_RATE 0x2B
+#define CS42L52_ALC_SLOWEST_RELEASE 0x3F
+
+#define CS42L52_ALC_THRESHOLD 0x2C
+#define CS42L52_ALC_MAX_RATE_SHIFT 5
+#define CS42L52_ALC_MIN_RATE_SHIFT 2
+#define CS42L52_ALC_RATE_0DB 0
+#define CS42L52_ALC_RATE_3DB 1
+#define CS42L52_ALC_RATE_6DB 2
+
+#define CS42L52_NOISE_GATE_CTL 0x2D
+#define CS42L52_NG_ENABLE_SHIFT 6
+#define CS42L52_NG_THRESHOLD_SHIFT 2
+#define CS42L52_NG_MIN_70DB 2
+#define CS42L52_NG_DELAY_SHIFT 0
+#define CS42L52_NG_DELAY_100MS 1
+
+#define CS42L52_CLK_STATUS 0x2E
+#define CS42L52_BATT_COMPEN 0x2F
+
+#define CS42L52_BATT_LEVEL 0x30
+#define CS42L52_SPK_STATUS 0x31
+#define CS42L52_SPK_STATUS_PIN_SHIFT 3
+#define CS42L52_SPK_STATUS_PIN_HIGH 1
+
+#define CS42L52_TEM_CTL 0x32
+#define CS42L52_TEM_CTL_SET 0x80
+#define CS42L52_THE_FOLDBACK 0x33
+#define CS42L52_CHARGE_PUMP 0x34
+#define CS42L52_CHARGE_PUMP_MASK 0xF0
+#define CS42L52_CHARGE_PUMP_SHIFT 4
+#define CS42L52_FIX_BITS1 0x3E
+#define CS42L52_FIX_BITS2 0x47
+
+#define CS42L52_MAX_REGISTER 0x34
+
+#endif
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index 3686417f5ea5..e0d45fdaa750 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -43,9 +43,6 @@ struct cs42l73_private {
};
static const struct reg_default cs42l73_reg_defaults[] = {
- { 1, 0x42 }, /* r01 - Device ID A&B */
- { 2, 0xA7 }, /* r02 - Device ID C&D */
- { 3, 0x30 }, /* r03 - Device ID E */
{ 6, 0xF1 }, /* r06 - Power Ctl 1 */
{ 7, 0xDF }, /* r07 - Power Ctl 2 */
{ 8, 0x3F }, /* r08 - Power Ctl 3 */
@@ -402,37 +399,37 @@ static const struct snd_kcontrol_new ear_amp_ctl =
static const struct snd_kcontrol_new cs42l73_snd_controls[] = {
SOC_DOUBLE_R_SX_TLV("Headphone Analog Playback Volume",
- CS42L73_HPAAVOL, CS42L73_HPBAVOL, 7,
- 0xffffffC1, 0x0C, hpaloa_tlv),
+ CS42L73_HPAAVOL, CS42L73_HPBAVOL, 0,
+ 0x41, 0x4B, hpaloa_tlv),
SOC_DOUBLE_R_SX_TLV("LineOut Analog Playback Volume", CS42L73_LOAAVOL,
- CS42L73_LOBAVOL, 7, 0xffffffC1, 0x0C, hpaloa_tlv),
+ CS42L73_LOBAVOL, 0, 0x41, 0x4B, hpaloa_tlv),
SOC_DOUBLE_R_SX_TLV("Input PGA Analog Volume", CS42L73_MICAPREPGAAVOL,
- CS42L73_MICBPREPGABVOL, 5, 0xffffff35,
- 0x34, micpga_tlv),
+ CS42L73_MICBPREPGABVOL, 5, 0x34,
+ 0x24, micpga_tlv),
SOC_DOUBLE_R("MIC Preamp Switch", CS42L73_MICAPREPGAAVOL,
CS42L73_MICBPREPGABVOL, 6, 1, 1),
SOC_DOUBLE_R_SX_TLV("Input Path Digital Volume", CS42L73_IPADVOL,
- CS42L73_IPBDVOL, 7, 0xffffffA0, 0xA0, ipd_tlv),
+ CS42L73_IPBDVOL, 0, 0xA0, 0x6C, ipd_tlv),
SOC_DOUBLE_R_SX_TLV("HL Digital Playback Volume",
- CS42L73_HLADVOL, CS42L73_HLBDVOL, 7, 0xffffffE5,
- 0xE4, hl_tlv),
+ CS42L73_HLADVOL, CS42L73_HLBDVOL,
+ 0, 0x34, 0xE4, hl_tlv),
SOC_SINGLE_TLV("ADC A Boost Volume",
CS42L73_ADCIPC, 2, 0x01, 1, adc_boost_tlv),
SOC_SINGLE_TLV("ADC B Boost Volume",
- CS42L73_ADCIPC, 6, 0x01, 1, adc_boost_tlv),
+ CS42L73_ADCIPC, 6, 0x01, 1, adc_boost_tlv),
- SOC_SINGLE_TLV("Speakerphone Digital Playback Volume",
- CS42L73_SPKDVOL, 0, 0xE4, 1, hl_tlv),
+ SOC_SINGLE_SX_TLV("Speakerphone Digital Volume",
+ CS42L73_SPKDVOL, 0, 0x34, 0xE4, hl_tlv),
- SOC_SINGLE_TLV("Ear Speaker Digital Playback Volume",
- CS42L73_ESLDVOL, 0, 0xE4, 1, hl_tlv),
+ SOC_SINGLE_SX_TLV("Ear Speaker Digital Volume",
+ CS42L73_ESLDVOL, 0, 0x34, 0xE4, hl_tlv),
SOC_DOUBLE_R("Headphone Analog Playback Switch", CS42L73_HPAAVOL,
CS42L73_HPBAVOL, 7, 1, 1),
@@ -599,17 +596,17 @@ static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("MIC2"),
SND_SOC_DAPM_SUPPLY("MIC2 Bias", CS42L73_PWRCTL2, 7, 1, NULL, 0),
- SND_SOC_DAPM_AIF_OUT("XSPOUTL", "XSP Capture", 0,
+ SND_SOC_DAPM_AIF_OUT("XSPOUTL", NULL, 0,
CS42L73_PWRCTL2, 1, 1),
- SND_SOC_DAPM_AIF_OUT("XSPOUTR", "XSP Capture", 0,
+ SND_SOC_DAPM_AIF_OUT("XSPOUTR", NULL, 0,
CS42L73_PWRCTL2, 1, 1),
- SND_SOC_DAPM_AIF_OUT("ASPOUTL", "ASP Capture", 0,
+ SND_SOC_DAPM_AIF_OUT("ASPOUTL", NULL, 0,
CS42L73_PWRCTL2, 3, 1),
- SND_SOC_DAPM_AIF_OUT("ASPOUTR", "ASP Capture", 0,
+ SND_SOC_DAPM_AIF_OUT("ASPOUTR", NULL, 0,
CS42L73_PWRCTL2, 3, 1),
- SND_SOC_DAPM_AIF_OUT("VSPOUTL", "VSP Capture", 0,
+ SND_SOC_DAPM_AIF_OUT("VSPOUTL", NULL, 0,
CS42L73_PWRCTL2, 4, 1),
- SND_SOC_DAPM_AIF_OUT("VSPOUTR", "VSP Capture", 0,
+ SND_SOC_DAPM_AIF_OUT("VSPOUTR", NULL, 0,
CS42L73_PWRCTL2, 4, 1),
SND_SOC_DAPM_PGA("PGA Left", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -638,21 +635,21 @@ static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = {
SND_SOC_DAPM_MIXER("VSPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("VSPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
- SND_SOC_DAPM_AIF_IN("XSPINL", "XSP Playback", 0,
+ SND_SOC_DAPM_AIF_IN("XSPINL", NULL, 0,
CS42L73_PWRCTL2, 0, 1),
- SND_SOC_DAPM_AIF_IN("XSPINR", "XSP Playback", 0,
+ SND_SOC_DAPM_AIF_IN("XSPINR", NULL, 0,
CS42L73_PWRCTL2, 0, 1),
- SND_SOC_DAPM_AIF_IN("XSPINM", "XSP Playback", 0,
+ SND_SOC_DAPM_AIF_IN("XSPINM", NULL, 0,
CS42L73_PWRCTL2, 0, 1),
- SND_SOC_DAPM_AIF_IN("ASPINL", "ASP Playback", 0,
+ SND_SOC_DAPM_AIF_IN("ASPINL", NULL, 0,
CS42L73_PWRCTL2, 2, 1),
- SND_SOC_DAPM_AIF_IN("ASPINR", "ASP Playback", 0,
+ SND_SOC_DAPM_AIF_IN("ASPINR", NULL, 0,
CS42L73_PWRCTL2, 2, 1),
- SND_SOC_DAPM_AIF_IN("ASPINM", "ASP Playback", 0,
+ SND_SOC_DAPM_AIF_IN("ASPINM", NULL, 0,
CS42L73_PWRCTL2, 2, 1),
- SND_SOC_DAPM_AIF_IN("VSPIN", "VSP Playback", 0,
+ SND_SOC_DAPM_AIF_IN("VSPIN", NULL, 0,
CS42L73_PWRCTL2, 4, 1),
SND_SOC_DAPM_MIXER("HL Left Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -776,6 +773,14 @@ static const struct snd_soc_dapm_route cs42l73_audio_map[] = {
{"HL Left Mixer", NULL, "VSPIN"},
{"HL Right Mixer", NULL, "VSPIN"},
+ {"ASPINL", NULL, "ASP Playback"},
+ {"ASPINM", NULL, "ASP Playback"},
+ {"ASPINR", NULL, "ASP Playback"},
+ {"XSPINL", NULL, "XSP Playback"},
+ {"XSPINM", NULL, "XSP Playback"},
+ {"XSPINR", NULL, "XSP Playback"},
+ {"VSPIN", NULL, "VSP Playback"},
+
/* Capture Paths */
{"MIC1", NULL, "MIC1 Bias"},
{"PGA Left Mux", "Mic 1", "MIC1"},
@@ -822,6 +827,13 @@ static const struct snd_soc_dapm_route cs42l73_audio_map[] = {
{"VSPOUTL", NULL, "VSPL Output Mixer"},
{"VSPOUTR", NULL, "VSPR Output Mixer"},
+
+ {"ASP Capture", NULL, "ASPOUTL"},
+ {"ASP Capture", NULL, "ASPOUTR"},
+ {"XSP Capture", NULL, "XSPOUTL"},
+ {"XSP Capture", NULL, "XSPOUTR"},
+ {"VSP Capture", NULL, "VSPOUTL"},
+ {"VSP Capture", NULL, "VSPOUTR"},
};
struct cs42l73_mclk_div {
@@ -1091,8 +1103,7 @@ static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
int id = dai->id;
int mclk_coeff;
@@ -1429,25 +1440,7 @@ static struct i2c_driver cs42l73_i2c_driver = {
};
-static int __init cs42l73_modinit(void)
-{
- int ret;
- ret = i2c_add_driver(&cs42l73_i2c_driver);
- if (ret != 0) {
- pr_err("Failed to register CS42L73 I2C driver: %d\n", ret);
- return ret;
- }
- return 0;
-}
-
-module_init(cs42l73_modinit);
-
-static void __exit cs42l73_exit(void)
-{
- i2c_del_driver(&cs42l73_i2c_driver);
-}
-
-module_exit(cs42l73_exit);
+module_i2c_driver(cs42l73_i2c_driver);
MODULE_DESCRIPTION("ASoC CS42L73 driver");
MODULE_AUTHOR("Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>");
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index 7843711729bc..af5db7080519 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <linux/i2c.h>
+#include <linux/spi/spi.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -27,6 +28,7 @@
#include <sound/tlv.h>
/* DA7210 register space */
+#define DA7210_PAGE_CONTROL 0x00
#define DA7210_CONTROL 0x01
#define DA7210_STATUS 0x02
#define DA7210_STARTUP1 0x03
@@ -146,6 +148,7 @@
#define DA7210_DAI_EN (1 << 7)
/*PLL_DIV3 bit fields */
+#define DA7210_PLL_DIV_L_MASK (0xF << 0)
#define DA7210_MCLK_RANGE_10_20_MHZ (1 << 4)
#define DA7210_PLL_BYP (1 << 6)
@@ -162,12 +165,16 @@
#define DA7210_PLL_FS_48000 (0xB << 0)
#define DA7210_PLL_FS_88200 (0xE << 0)
#define DA7210_PLL_FS_96000 (0xF << 0)
+#define DA7210_MCLK_DET_EN (0x1 << 5)
+#define DA7210_MCLK_SRM_EN (0x1 << 6)
#define DA7210_PLL_EN (0x1 << 7)
/* SOFTMUTE bit fields */
#define DA7210_RAMP_EN (1 << 6)
/* CONTROL bit fields */
+#define DA7210_REG_EN (1 << 0)
+#define DA7210_BIAS_EN (1 << 2)
#define DA7210_NOISE_SUP_EN (1 << 3)
/* IN_GAIN bit fields */
@@ -206,6 +213,47 @@
#define DA7210_OUT2_OUTMIX_L (1 << 6)
#define DA7210_OUT2_EN (1 << 7)
+struct pll_div {
+ int fref;
+ int fout;
+ u8 div1;
+ u8 div2;
+ u8 div3;
+ u8 mode; /* 0 = slave, 1 = master */
+};
+
+/* PLL dividers table */
+static const struct pll_div da7210_pll_div[] = {
+ /* for MASTER mode, fs = 44.1Khz */
+ { 12000000, 2822400, 0xE8, 0x6C, 0x2, 1}, /* MCLK=12Mhz */
+ { 13000000, 2822400, 0xDF, 0x28, 0xC, 1}, /* MCLK=13Mhz */
+ { 13500000, 2822400, 0xDB, 0x0A, 0xD, 1}, /* MCLK=13.5Mhz */
+ { 14400000, 2822400, 0xD4, 0x5A, 0x2, 1}, /* MCLK=14.4Mhz */
+ { 19200000, 2822400, 0xBB, 0x43, 0x9, 1}, /* MCLK=19.2Mhz */
+ { 19680000, 2822400, 0xB9, 0x6D, 0xA, 1}, /* MCLK=19.68Mhz */
+ { 19800000, 2822400, 0xB8, 0xFB, 0xB, 1}, /* MCLK=19.8Mhz */
+ /* for MASTER mode, fs = 48Khz */
+ { 12000000, 3072000, 0xF3, 0x12, 0x7, 1}, /* MCLK=12Mhz */
+ { 13000000, 3072000, 0xE8, 0xFD, 0x5, 1}, /* MCLK=13Mhz */
+ { 13500000, 3072000, 0xE4, 0x82, 0x3, 1}, /* MCLK=13.5Mhz */
+ { 14400000, 3072000, 0xDD, 0x3A, 0x0, 1}, /* MCLK=14.4Mhz */
+ { 19200000, 3072000, 0xC1, 0xEB, 0x8, 1}, /* MCLK=19.2Mhz */
+ { 19680000, 3072000, 0xBF, 0xEC, 0x0, 1}, /* MCLK=19.68Mhz */
+ { 19800000, 3072000, 0xBF, 0x70, 0x0, 1}, /* MCLK=19.8Mhz */
+ /* for SLAVE mode with SRM */
+ { 12000000, 2822400, 0xED, 0xBF, 0x5, 0}, /* MCLK=12Mhz */
+ { 13000000, 2822400, 0xE4, 0x13, 0x0, 0}, /* MCLK=13Mhz */
+ { 13500000, 2822400, 0xDF, 0xC6, 0x8, 0}, /* MCLK=13.5Mhz */
+ { 14400000, 2822400, 0xD8, 0xCA, 0x1, 0}, /* MCLK=14.4Mhz */
+ { 19200000, 2822400, 0xBE, 0x97, 0x9, 0}, /* MCLK=19.2Mhz */
+ { 19680000, 2822400, 0xBC, 0xAC, 0xD, 0}, /* MCLK=19.68Mhz */
+ { 19800000, 2822400, 0xBC, 0x35, 0xE, 0}, /* MCLK=19.8Mhz */
+};
+
+enum clk_src {
+ DA7210_CLKSRC_MCLK
+};
+
#define DA7210_VERSION "0.0.1"
/*
@@ -628,9 +676,12 @@ static const struct snd_soc_dapm_route da7210_audio_map[] = {
/* Codec private data */
struct da7210_priv {
struct regmap *regmap;
+ unsigned int mclk_rate;
+ int master;
};
static struct reg_default da7210_reg_defaults[] = {
+ { 0x00, 0x00 },
{ 0x01, 0x11 },
{ 0x03, 0x00 },
{ 0x04, 0x00 },
@@ -713,10 +764,10 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
+ struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
u32 dai_cfg1;
- u32 fs, bypass;
+ u32 fs, sysclk;
/* set DAI source to Left and Right ADC */
snd_soc_write(codec, DA7210_DAI_SRC_SEL,
@@ -749,43 +800,43 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
switch (params_rate(params)) {
case 8000:
fs = DA7210_PLL_FS_8000;
- bypass = DA7210_PLL_BYP;
+ sysclk = 3072000;
break;
case 11025:
fs = DA7210_PLL_FS_11025;
- bypass = 0;
+ sysclk = 2822400;
break;
case 12000:
fs = DA7210_PLL_FS_12000;
- bypass = DA7210_PLL_BYP;
+ sysclk = 3072000;
break;
case 16000:
fs = DA7210_PLL_FS_16000;
- bypass = DA7210_PLL_BYP;
+ sysclk = 3072000;
break;
case 22050:
fs = DA7210_PLL_FS_22050;
- bypass = 0;
+ sysclk = 2822400;
break;
case 32000:
fs = DA7210_PLL_FS_32000;
- bypass = DA7210_PLL_BYP;
+ sysclk = 3072000;
break;
case 44100:
fs = DA7210_PLL_FS_44100;
- bypass = 0;
+ sysclk = 2822400;
break;
case 48000:
fs = DA7210_PLL_FS_48000;
- bypass = DA7210_PLL_BYP;
+ sysclk = 3072000;
break;
case 88200:
fs = DA7210_PLL_FS_88200;
- bypass = 0;
+ sysclk = 2822400;
break;
case 96000:
fs = DA7210_PLL_FS_96000;
- bypass = DA7210_PLL_BYP;
+ sysclk = 3072000;
break;
default:
return -EINVAL;
@@ -795,8 +846,26 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
snd_soc_update_bits(codec, DA7210_STARTUP1, DA7210_SC_MST_EN, 0);
snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_FS_MASK, fs);
- snd_soc_update_bits(codec, DA7210_PLL_DIV3, DA7210_PLL_BYP, bypass);
+ if (da7210->mclk_rate && (da7210->mclk_rate != sysclk)) {
+ /* PLL mode, disable PLL bypass */
+ snd_soc_update_bits(codec, DA7210_PLL_DIV3, DA7210_PLL_BYP, 0);
+
+ if (!da7210->master) {
+ /* PLL slave mode, also enable SRM */
+ snd_soc_update_bits(codec, DA7210_PLL,
+ (DA7210_MCLK_SRM_EN |
+ DA7210_MCLK_DET_EN),
+ (DA7210_MCLK_SRM_EN |
+ DA7210_MCLK_DET_EN));
+ }
+ } else {
+ /* PLL bypass mode, enable PLL bypass and Auto Detection */
+ snd_soc_update_bits(codec, DA7210_PLL, DA7210_MCLK_DET_EN,
+ DA7210_MCLK_DET_EN);
+ snd_soc_update_bits(codec, DA7210_PLL_DIV3, DA7210_PLL_BYP,
+ DA7210_PLL_BYP);
+ }
/* Enable active mode */
snd_soc_update_bits(codec, DA7210_STARTUP1,
DA7210_SC_MST_EN, DA7210_SC_MST_EN);
@@ -810,17 +879,24 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
+ struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
u32 dai_cfg1;
u32 dai_cfg3;
dai_cfg1 = 0x7f & snd_soc_read(codec, DA7210_DAI_CFG1);
dai_cfg3 = 0xfc & snd_soc_read(codec, DA7210_DAI_CFG3);
+ if ((snd_soc_read(codec, DA7210_PLL) & DA7210_PLL_EN) &&
+ (!(snd_soc_read(codec, DA7210_PLL_DIV3) & DA7210_PLL_BYP)))
+ return -EINVAL;
+
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
+ da7210->master = 1;
dai_cfg1 |= DA7210_DAI_MODE_MASTER;
break;
case SND_SOC_DAIFMT_CBS_CFS:
+ da7210->master = 0;
dai_cfg1 |= DA7210_DAI_MODE_SLAVE;
break;
default:
@@ -872,10 +948,101 @@ static int da7210_mute(struct snd_soc_dai *dai, int mute)
#define DA7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+static int da7210_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
+
+ switch (clk_id) {
+ case DA7210_CLKSRC_MCLK:
+ switch (freq) {
+ case 12000000:
+ case 13000000:
+ case 13500000:
+ case 14400000:
+ case 19200000:
+ case 19680000:
+ case 19800000:
+ da7210->mclk_rate = freq;
+ return 0;
+ default:
+ dev_err(codec_dai->dev, "Unsupported MCLK value %d\n",
+ freq);
+ return -EINVAL;
+ }
+ break;
+ default:
+ dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id);
+ return -EINVAL;
+ }
+}
+
+/**
+ * da7210_set_dai_pll :Configure the codec PLL
+ * @param codec_dai : pointer to codec DAI
+ * @param pll_id : da7210 has only one pll, so pll_id is always zero
+ * @param fref : MCLK frequency, should be < 20MHz
+ * @param fout : FsDM value, Refer page 44 & 45 of datasheet
+ * @return int : Zero for success, negative error code for error
+ *
+ * Note: Supported PLL input frequencies are 12MHz, 13MHz, 13.5MHz, 14.4MHz,
+ * 19.2MHz, 19.6MHz and 19.8MHz
+ */
+static int da7210_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
+ int source, unsigned int fref, unsigned int fout)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
+
+ u8 pll_div1, pll_div2, pll_div3, cnt;
+
+ /* In slave mode, there is only one set of divisors */
+ if (!da7210->master)
+ fout = 2822400;
+
+ /* Search pll div array for correct divisors */
+ for (cnt = 0; cnt < ARRAY_SIZE(da7210_pll_div); cnt++) {
+ /* check fref, mode and fout */
+ if ((fref == da7210_pll_div[cnt].fref) &&
+ (da7210->master == da7210_pll_div[cnt].mode) &&
+ (fout == da7210_pll_div[cnt].fout)) {
+ /* all match, pick up divisors */
+ pll_div1 = da7210_pll_div[cnt].div1;
+ pll_div2 = da7210_pll_div[cnt].div2;
+ pll_div3 = da7210_pll_div[cnt].div3;
+ break;
+ }
+ }
+ if (cnt >= ARRAY_SIZE(da7210_pll_div))
+ goto err;
+
+ /* Disable active mode */
+ snd_soc_update_bits(codec, DA7210_STARTUP1, DA7210_SC_MST_EN, 0);
+ /* Write PLL dividers */
+ snd_soc_write(codec, DA7210_PLL_DIV1, pll_div1);
+ snd_soc_write(codec, DA7210_PLL_DIV2, pll_div2);
+ snd_soc_update_bits(codec, DA7210_PLL_DIV3,
+ DA7210_PLL_DIV_L_MASK, pll_div3);
+
+ /* Enable PLL */
+ snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN);
+
+ /* Enable active mode */
+ snd_soc_update_bits(codec, DA7210_STARTUP1, DA7210_SC_MST_EN,
+ DA7210_SC_MST_EN);
+ return 0;
+err:
+ dev_err(codec_dai->dev, "Unsupported PLL input frequency %d\n", fref);
+ return -EINVAL;
+}
+
/* DAI operations */
static const struct snd_soc_dai_ops da7210_dai_ops = {
.hw_params = da7210_hw_params,
.set_fmt = da7210_set_dai_fmt,
+ .set_sysclk = da7210_set_dai_sysclk,
+ .set_pll = da7210_set_dai_pll,
.digital_mute = da7210_mute,
};
@@ -915,24 +1082,11 @@ static int da7210_probe(struct snd_soc_codec *codec)
return ret;
}
- /* FIXME
- *
- * This driver use fixed value here
- * And below settings expects MCLK = 12.288MHz
- *
- * When you select different MCLK, please check...
- * DA7210_PLL_DIV1 val
- * DA7210_PLL_DIV2 val
- * DA7210_PLL_DIV3 val
- * DA7210_PLL_DIV3 :: DA7210_MCLK_RANGExxx
- */
+ da7210->mclk_rate = 0; /* This will be set from set_sysclk() */
+ da7210->master = 0; /* This will be set from set_fmt() */
- /*
- * make sure that DA7210 use bypass mode before start up
- */
- snd_soc_write(codec, DA7210_STARTUP1, 0);
- snd_soc_write(codec, DA7210_PLL_DIV3,
- DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
+ /* Enable internal regulator & bias current */
+ snd_soc_write(codec, DA7210_CONTROL, DA7210_REG_EN | DA7210_BIAS_EN);
/*
* ADC settings
@@ -1007,34 +1161,13 @@ static int da7210_probe(struct snd_soc_codec *codec)
/* Enable Aux2 */
snd_soc_write(codec, DA7210_AUX2, DA7210_AUX2_EN);
+ /* Set PLL Master clock range 10-20 MHz, enable PLL bypass */
+ snd_soc_write(codec, DA7210_PLL_DIV3, DA7210_MCLK_RANGE_10_20_MHZ |
+ DA7210_PLL_BYP);
+
/* Diable PLL and bypass it */
snd_soc_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);
- /*
- * If 48kHz sound came, it use bypass mode,
- * and when it is 44.1kHz, it use PLL.
- *
- * This time, this driver sets PLL always ON
- * and controls bypass/PLL mode by switching
- * DA7210_PLL_DIV3 :: DA7210_PLL_BYP bit.
- * see da7210_hw_params
- */
- snd_soc_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */
- snd_soc_write(codec, DA7210_PLL_DIV2, 0x99);
- snd_soc_write(codec, DA7210_PLL_DIV3, 0x0A |
- DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
- snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN);
-
- /* As suggested by Dialog */
- /* unlock */
- regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x8B);
- regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0xB4);
- regmap_write(da7210->regmap, DA7210_A_PLL1, 0x01);
- regmap_write(da7210->regmap, DA7210_A_CP_MODE, 0x7C);
- /* re-lock */
- regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x00);
- regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0x00);
-
/* Activate all enabled subsystem */
snd_soc_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
@@ -1055,7 +1188,26 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
.num_dapm_routes = ARRAY_SIZE(da7210_audio_map),
};
-static struct regmap_config da7210_regmap = {
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+static struct reg_default da7210_regmap_i2c_patch[] = {
+
+ /* System controller master disable */
+ { DA7210_STARTUP1, 0x00 },
+ /* Set PLL Master clock range 10-20 MHz */
+ { DA7210_PLL_DIV3, DA7210_MCLK_RANGE_10_20_MHZ },
+
+ /* to unlock */
+ { DA7210_A_HID_UNLOCK, 0x8B},
+ { DA7210_A_TEST_UNLOCK, 0xB4},
+ { DA7210_A_PLL1, 0x01},
+ { DA7210_A_CP_MODE, 0x7C},
+ /* to re-lock */
+ { DA7210_A_HID_UNLOCK, 0x00},
+ { DA7210_A_TEST_UNLOCK, 0x00},
+};
+
+static const struct regmap_config da7210_regmap_config_i2c = {
.reg_bits = 8,
.val_bits = 8,
@@ -1066,7 +1218,6 @@ static struct regmap_config da7210_regmap = {
.cache_type = REGCACHE_RBTREE,
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -1080,13 +1231,18 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, da7210);
- da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap);
+ da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap_config_i2c);
if (IS_ERR(da7210->regmap)) {
ret = PTR_ERR(da7210->regmap);
dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
return ret;
}
+ ret = regmap_register_patch(da7210->regmap, da7210_regmap_i2c_patch,
+ ARRAY_SIZE(da7210_regmap_i2c_patch));
+ if (ret != 0)
+ dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_da7210, &da7210_dai, 1);
if (ret < 0) {
@@ -1119,7 +1275,7 @@ MODULE_DEVICE_TABLE(i2c, da7210_i2c_id);
/* I2C codec control layer */
static struct i2c_driver da7210_i2c_driver = {
.driver = {
- .name = "da7210-codec",
+ .name = "da7210",
.owner = THIS_MODULE,
},
.probe = da7210_i2c_probe,
@@ -1128,12 +1284,112 @@ static struct i2c_driver da7210_i2c_driver = {
};
#endif
+#if defined(CONFIG_SPI_MASTER)
+
+static struct reg_default da7210_regmap_spi_patch[] = {
+ /* Dummy read to give two pulses over nCS for SPI */
+ { DA7210_AUX2, 0x00 },
+ { DA7210_AUX2, 0x00 },
+
+ /* System controller master disable */
+ { DA7210_STARTUP1, 0x00 },
+ /* Set PLL Master clock range 10-20 MHz */
+ { DA7210_PLL_DIV3, DA7210_MCLK_RANGE_10_20_MHZ },
+
+ /* to set PAGE1 of SPI register space */
+ { DA7210_PAGE_CONTROL, 0x80 },
+ /* to unlock */
+ { DA7210_A_HID_UNLOCK, 0x8B},
+ { DA7210_A_TEST_UNLOCK, 0xB4},
+ { DA7210_A_PLL1, 0x01},
+ { DA7210_A_CP_MODE, 0x7C},
+ /* to re-lock */
+ { DA7210_A_HID_UNLOCK, 0x00},
+ { DA7210_A_TEST_UNLOCK, 0x00},
+ /* to set back PAGE0 of SPI register space */
+ { DA7210_PAGE_CONTROL, 0x00 },
+};
+
+static const struct regmap_config da7210_regmap_config_spi = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .read_flag_mask = 0x01,
+ .write_flag_mask = 0x00,
+
+ .reg_defaults = da7210_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(da7210_reg_defaults),
+ .volatile_reg = da7210_volatile_register,
+ .readable_reg = da7210_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit da7210_spi_probe(struct spi_device *spi)
+{
+ struct da7210_priv *da7210;
+ int ret;
+
+ da7210 = devm_kzalloc(&spi->dev, sizeof(struct da7210_priv),
+ GFP_KERNEL);
+ if (!da7210)
+ return -ENOMEM;
+
+ spi_set_drvdata(spi, da7210);
+ da7210->regmap = devm_regmap_init_spi(spi, &da7210_regmap_config_spi);
+ if (IS_ERR(da7210->regmap)) {
+ ret = PTR_ERR(da7210->regmap);
+ dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_register_patch(da7210->regmap, da7210_regmap_spi_patch,
+ ARRAY_SIZE(da7210_regmap_spi_patch));
+ if (ret != 0)
+ dev_warn(&spi->dev, "Failed to apply regmap patch: %d\n", ret);
+
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_da7210, &da7210_dai, 1);
+ if (ret < 0)
+ goto err_regmap;
+
+ return ret;
+
+err_regmap:
+ regmap_exit(da7210->regmap);
+
+ return ret;
+}
+
+static int __devexit da7210_spi_remove(struct spi_device *spi)
+{
+ struct da7210_priv *da7210 = spi_get_drvdata(spi);
+ snd_soc_unregister_codec(&spi->dev);
+ regmap_exit(da7210->regmap);
+ return 0;
+}
+
+static struct spi_driver da7210_spi_driver = {
+ .driver = {
+ .name = "da7210",
+ .owner = THIS_MODULE,
+ },
+ .probe = da7210_spi_probe,
+ .remove = __devexit_p(da7210_spi_remove)
+};
+#endif
+
static int __init da7210_modinit(void)
{
int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&da7210_i2c_driver);
#endif
+#if defined(CONFIG_SPI_MASTER)
+ ret = spi_register_driver(&da7210_spi_driver);
+ if (ret) {
+ printk(KERN_ERR "Failed to register da7210 SPI driver: %d\n",
+ ret);
+ }
+#endif
return ret;
}
module_init(da7210_modinit);
@@ -1143,6 +1399,9 @@ static void __exit da7210_exit(void)
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&da7210_i2c_driver);
#endif
+#if defined(CONFIG_SPI_MASTER)
+ spi_unregister_driver(&da7210_spi_driver);
+#endif
}
module_exit(da7210_exit);
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index 4624e752a188..85d9cabe6d55 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -164,8 +164,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
uint32_t val;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec =rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
switch (params_rate(params)) {
case 8000:
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c
new file mode 100644
index 000000000000..802b9f176b16
--- /dev/null
+++ b/sound/soc/codecs/lm49453.c
@@ -0,0 +1,1550 @@
+/*
+ * lm49453.c - LM49453 ALSA Soc Audio driver
+ *
+ * Copyright (c) 2012 Texas Instruments, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * Initially based on sound/soc/codecs/wm8350.c
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <asm/div64.h>
+#include "lm49453.h"
+
+static struct reg_default lm49453_reg_defs[] = {
+ { 0, 0x00 },
+ { 1, 0x00 },
+ { 2, 0x00 },
+ { 3, 0x00 },
+ { 4, 0x00 },
+ { 5, 0x00 },
+ { 6, 0x00 },
+ { 7, 0x00 },
+ { 8, 0x00 },
+ { 9, 0x00 },
+ { 10, 0x00 },
+ { 11, 0x00 },
+ { 12, 0x00 },
+ { 13, 0x00 },
+ { 14, 0x00 },
+ { 15, 0x00 },
+ { 16, 0x00 },
+ { 17, 0x00 },
+ { 18, 0x00 },
+ { 19, 0x00 },
+ { 20, 0x00 },
+ { 21, 0x00 },
+ { 22, 0x00 },
+ { 23, 0x00 },
+ { 32, 0x00 },
+ { 33, 0x00 },
+ { 35, 0x00 },
+ { 36, 0x00 },
+ { 37, 0x00 },
+ { 46, 0x00 },
+ { 48, 0x00 },
+ { 49, 0x00 },
+ { 51, 0x00 },
+ { 56, 0x00 },
+ { 58, 0x00 },
+ { 59, 0x00 },
+ { 60, 0x00 },
+ { 61, 0x00 },
+ { 62, 0x00 },
+ { 63, 0x00 },
+ { 64, 0x00 },
+ { 65, 0x00 },
+ { 66, 0x00 },
+ { 67, 0x00 },
+ { 68, 0x00 },
+ { 69, 0x00 },
+ { 70, 0x00 },
+ { 71, 0x00 },
+ { 72, 0x00 },
+ { 73, 0x00 },
+ { 74, 0x00 },
+ { 75, 0x00 },
+ { 76, 0x00 },
+ { 77, 0x00 },
+ { 78, 0x00 },
+ { 79, 0x00 },
+ { 80, 0x00 },
+ { 81, 0x00 },
+ { 82, 0x00 },
+ { 83, 0x00 },
+ { 85, 0x00 },
+ { 85, 0x00 },
+ { 86, 0x00 },
+ { 87, 0x00 },
+ { 88, 0x00 },
+ { 89, 0x00 },
+ { 90, 0x00 },
+ { 91, 0x00 },
+ { 92, 0x00 },
+ { 93, 0x00 },
+ { 94, 0x00 },
+ { 95, 0x00 },
+ { 96, 0x01 },
+ { 97, 0x00 },
+ { 98, 0x00 },
+ { 99, 0x00 },
+ { 100, 0x00 },
+ { 101, 0x00 },
+ { 102, 0x00 },
+ { 103, 0x01 },
+ { 105, 0x01 },
+ { 106, 0x00 },
+ { 107, 0x01 },
+ { 107, 0x00 },
+ { 108, 0x00 },
+ { 109, 0x00 },
+ { 110, 0x00 },
+ { 111, 0x02 },
+ { 112, 0x02 },
+ { 113, 0x00 },
+ { 121, 0x80 },
+ { 122, 0xBB },
+ { 123, 0x80 },
+ { 124, 0xBB },
+ { 128, 0x00 },
+ { 130, 0x00 },
+ { 131, 0x00 },
+ { 132, 0x00 },
+ { 133, 0x0A },
+ { 134, 0x0A },
+ { 135, 0x0A },
+ { 136, 0x0F },
+ { 137, 0x00 },
+ { 138, 0x73 },
+ { 139, 0x33 },
+ { 140, 0x73 },
+ { 141, 0x33 },
+ { 142, 0x73 },
+ { 143, 0x33 },
+ { 144, 0x73 },
+ { 145, 0x33 },
+ { 146, 0x73 },
+ { 147, 0x33 },
+ { 148, 0x73 },
+ { 149, 0x33 },
+ { 150, 0x73 },
+ { 151, 0x33 },
+ { 152, 0x00 },
+ { 153, 0x00 },
+ { 154, 0x00 },
+ { 155, 0x00 },
+ { 176, 0x00 },
+ { 177, 0x00 },
+ { 178, 0x00 },
+ { 179, 0x00 },
+ { 180, 0x00 },
+ { 181, 0x00 },
+ { 182, 0x00 },
+ { 183, 0x00 },
+ { 184, 0x00 },
+ { 185, 0x00 },
+ { 186, 0x00 },
+ { 189, 0x00 },
+ { 188, 0x00 },
+ { 194, 0x00 },
+ { 195, 0x00 },
+ { 196, 0x00 },
+ { 197, 0x00 },
+ { 200, 0x00 },
+ { 201, 0x00 },
+ { 202, 0x00 },
+ { 203, 0x00 },
+ { 204, 0x00 },
+ { 205, 0x00 },
+ { 208, 0x00 },
+ { 209, 0x00 },
+ { 210, 0x00 },
+ { 211, 0x00 },
+ { 213, 0x00 },
+ { 214, 0x00 },
+ { 215, 0x00 },
+ { 216, 0x00 },
+ { 217, 0x00 },
+ { 218, 0x00 },
+ { 219, 0x00 },
+ { 221, 0x00 },
+ { 222, 0x00 },
+ { 224, 0x00 },
+ { 225, 0x00 },
+ { 226, 0x00 },
+ { 227, 0x00 },
+ { 228, 0x00 },
+ { 229, 0x00 },
+ { 230, 0x13 },
+ { 231, 0x00 },
+ { 232, 0x80 },
+ { 233, 0x0C },
+ { 234, 0xDD },
+ { 235, 0x00 },
+ { 236, 0x04 },
+ { 237, 0x00 },
+ { 238, 0x00 },
+ { 239, 0x00 },
+ { 240, 0x00 },
+ { 241, 0x00 },
+ { 242, 0x00 },
+ { 243, 0x00 },
+ { 244, 0x00 },
+ { 245, 0x00 },
+ { 248, 0x00 },
+ { 249, 0x00 },
+ { 254, 0x00 },
+ { 255, 0x00 },
+};
+
+/* codec private data */
+struct lm49453_priv {
+ struct regmap *regmap;
+ int fs_rate;
+};
+
+/* capture path controls */
+
+static const char *lm49453_mic2mode_text[] = {"Single Ended", "Differential"};
+
+static const SOC_ENUM_SINGLE_DECL(lm49453_mic2mode_enum, LM49453_P0_MICR_REG, 5,
+ lm49453_mic2mode_text);
+
+static const char *lm49453_dmic_cfg_text[] = {"DMICDAT1", "DMICDAT2"};
+
+static const SOC_ENUM_SINGLE_DECL(lm49453_dmic12_cfg_enum,
+ LM49453_P0_DIGITAL_MIC1_CONFIG_REG,
+ 7, lm49453_dmic_cfg_text);
+
+static const SOC_ENUM_SINGLE_DECL(lm49453_dmic34_cfg_enum,
+ LM49453_P0_DIGITAL_MIC2_CONFIG_REG,
+ 7, lm49453_dmic_cfg_text);
+
+/* MUX Controls */
+static const char *lm49453_adcl_mux_text[] = { "MIC1", "Aux_L" };
+
+static const char *lm49453_adcr_mux_text[] = { "MIC2", "Aux_R" };
+
+static const struct soc_enum lm49453_adcl_enum =
+ SOC_ENUM_SINGLE(LM49453_P0_ANALOG_MIXER_ADC_REG, 0,
+ ARRAY_SIZE(lm49453_adcl_mux_text),
+ lm49453_adcl_mux_text);
+
+static const struct soc_enum lm49453_adcr_enum =
+ SOC_ENUM_SINGLE(LM49453_P0_ANALOG_MIXER_ADC_REG, 1,
+ ARRAY_SIZE(lm49453_adcr_mux_text),
+ lm49453_adcr_mux_text);
+
+static const struct snd_kcontrol_new lm49453_adcl_mux_control =
+ SOC_DAPM_ENUM("ADC Left Mux", lm49453_adcl_enum);
+
+static const struct snd_kcontrol_new lm49453_adcr_mux_control =
+ SOC_DAPM_ENUM("ADC Right Mux", lm49453_adcr_enum);
+
+static const struct snd_kcontrol_new lm49453_headset_left_mixer[] = {
+SOC_DAPM_SINGLE("Port1_1 Switch", LM49453_P0_DACHPL1_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("Port1_2 Switch", LM49453_P0_DACHPL1_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("Port1_3 Switch", LM49453_P0_DACHPL1_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("Port1_4 Switch", LM49453_P0_DACHPL1_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("Port1_5 Switch", LM49453_P0_DACHPL1_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("Port1_6 Switch", LM49453_P0_DACHPL1_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_7 Switch", LM49453_P0_DACHPL1_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port1_8 Switch", LM49453_P0_DACHPL1_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_DACHPL2_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_DACHPL2_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_DACHPL2_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_DACHPL2_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_DACHPL2_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_DACHPL2_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port2_1 Switch", LM49453_P0_DACHPL2_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port2_2 Switch", LM49453_P0_DACHPL2_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("Sidetone Switch", LM49453_P0_STN_SEL_REG, 0, 0, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_headset_right_mixer[] = {
+SOC_DAPM_SINGLE("Port1_1 Switch", LM49453_P0_DACHPR1_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("Port1_2 Switch", LM49453_P0_DACHPR1_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("Port1_3 Switch", LM49453_P0_DACHPR1_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("Port1_4 Switch", LM49453_P0_DACHPR1_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("Port1_5 Switch", LM49453_P0_DACHPR1_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("Port1_6 Switch", LM49453_P0_DACHPR1_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_7 Switch", LM49453_P0_DACHPR1_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port1_8 Switch", LM49453_P0_DACHPR1_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_DACHPR2_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_DACHPR2_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_DACHPR2_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_DACHPR2_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_DACHPR2_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_DACHPR2_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port2_1 Switch", LM49453_P0_DACHPR2_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port2_2 Switch", LM49453_P0_DACHPR2_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("Sidetone Switch", LM49453_P0_STN_SEL_REG, 1, 0, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_speaker_left_mixer[] = {
+SOC_DAPM_SINGLE("Port1_1 Switch", LM49453_P0_DACLSL1_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("Port1_2 Switch", LM49453_P0_DACLSL1_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("Port1_3 Switch", LM49453_P0_DACLSL1_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("Port1_4 Switch", LM49453_P0_DACLSL1_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("Port1_5 Switch", LM49453_P0_DACLSL1_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("Port1_6 Switch", LM49453_P0_DACLSL1_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_7 Switch", LM49453_P0_DACLSL1_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port1_8 Switch", LM49453_P0_DACLSL1_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_DACLSL2_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_DACLSL2_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_DACLSL2_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_DACLSL2_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_DACLSL2_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_DACLSL2_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port2_1 Switch", LM49453_P0_DACLSL2_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port2_2 Switch", LM49453_P0_DACLSL2_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("Sidetone Switch", LM49453_P0_STN_SEL_REG, 2, 0, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_speaker_right_mixer[] = {
+SOC_DAPM_SINGLE("Port1_1 Switch", LM49453_P0_DACLSR1_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("Port1_2 Switch", LM49453_P0_DACLSR1_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("Port1_3 Switch", LM49453_P0_DACLSR1_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("Port1_4 Switch", LM49453_P0_DACLSR1_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("Port1_5 Switch", LM49453_P0_DACLSR1_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("Port1_6 Switch", LM49453_P0_DACLSR1_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_7 Switch", LM49453_P0_DACLSR1_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port1_8 Switch", LM49453_P0_DACLSR1_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_DACLSR2_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_DACLSR2_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_DACLSR2_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_DACLSR2_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_DACLSR2_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_DACLSR2_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port2_1 Switch", LM49453_P0_DACLSR2_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port2_2 Switch", LM49453_P0_DACLSR2_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("Sidetone Switch", LM49453_P0_STN_SEL_REG, 3, 0, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_haptic_left_mixer[] = {
+SOC_DAPM_SINGLE("Port1_1 Switch", LM49453_P0_DACHAL1_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("Port1_2 Switch", LM49453_P0_DACHAL1_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("Port1_3 Switch", LM49453_P0_DACHAL1_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("Port1_4 Switch", LM49453_P0_DACHAL1_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("Port1_5 Switch", LM49453_P0_DACHAL1_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("Port1_6 Switch", LM49453_P0_DACHAL1_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_7 Switch", LM49453_P0_DACHAL1_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port1_8 Switch", LM49453_P0_DACHAL1_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_DACHAL2_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_DACHAL2_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_DACHAL2_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_DACHAL2_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_DACHAL2_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_DACHAL2_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port2_1 Switch", LM49453_P0_DACHAL2_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port2_2 Switch", LM49453_P0_DACHAL2_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("Sidetone Switch", LM49453_P0_STN_SEL_REG, 4, 0, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_haptic_right_mixer[] = {
+SOC_DAPM_SINGLE("Port1_1 Switch", LM49453_P0_DACHAR1_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("Port1_2 Switch", LM49453_P0_DACHAR1_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("Port1_3 Switch", LM49453_P0_DACHAR1_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("Port1_4 Switch", LM49453_P0_DACHAR1_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("Port1_5 Switch", LM49453_P0_DACHAR1_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("Port1_6 Switch", LM49453_P0_DACHAR1_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_7 Switch", LM49453_P0_DACHAR1_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port1_8 Switch", LM49453_P0_DACHAR1_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_DACHAR2_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_DACHAR2_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_DACHAR2_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_DACHAR2_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_DACHAR2_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_DACHAR2_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port2_1 Switch", LM49453_P0_DACHAR2_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port2_2 Switch", LM49453_P0_DACHAR2_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("Sidetone Switch", LM49453_P0_STN_SEL_REG, 5, 0, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_lineout_left_mixer[] = {
+SOC_DAPM_SINGLE("Port1_1 Switch", LM49453_P0_DACLOL1_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("Port1_2 Switch", LM49453_P0_DACLOL1_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("Port1_3 Switch", LM49453_P0_DACLOL1_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("Port1_4 Switch", LM49453_P0_DACLOL1_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("Port1_5 Switch", LM49453_P0_DACLOL1_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("Port1_6 Switch", LM49453_P0_DACLOL1_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_7 Switch", LM49453_P0_DACLOL1_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port1_8 Switch", LM49453_P0_DACLOL1_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_DACLOL2_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_DACLOL2_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_DACLOL2_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_DACLOL2_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_DACLOL2_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_DACLOL2_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port2_1 Switch", LM49453_P0_DACLOL2_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port2_2 Switch", LM49453_P0_DACLOL2_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("Sidetone Switch", LM49453_P0_STN_SEL_REG, 6, 0, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_lineout_right_mixer[] = {
+SOC_DAPM_SINGLE("Port1_1 Switch", LM49453_P0_DACLOR1_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("Port1_2 Switch", LM49453_P0_DACLOR1_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("Port1_3 Switch", LM49453_P0_DACLOR1_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("Port1_4 Switch", LM49453_P0_DACLOR1_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("Port1_5 Switch", LM49453_P0_DACLOR1_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("Port1_6 Switch", LM49453_P0_DACLOR1_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_7 Switch", LM49453_P0_DACLOR1_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port1_8 Switch", LM49453_P0_DACLOR1_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_DACLOR2_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_DACLOR2_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_DACLOR2_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_DACLOR2_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_DACLOR2_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_DACLOR2_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port2_1 Switch", LM49453_P0_DACLOR2_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port2_2 Switch", LM49453_P0_DACLOR2_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("Sidetone Switch", LM49453_P0_STN_SEL_REG, 7, 0, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_port1_tx1_mixer[] = {
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_PORT1_TX1_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_PORT1_TX1_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_PORT1_TX1_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_PORT1_TX1_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_PORT1_TX1_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_PORT1_TX1_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_1 Switch", LM49453_P0_PORT1_TX1_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port2_1 Switch", LM49453_P0_PORT1_TX1_REG, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_port1_tx2_mixer[] = {
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_PORT1_TX2_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_PORT1_TX2_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_PORT1_TX2_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_PORT1_TX2_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_PORT1_TX2_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_PORT1_TX2_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_2 Switch", LM49453_P0_PORT1_TX2_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port2_2 Switch", LM49453_P0_PORT1_TX2_REG, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_port1_tx3_mixer[] = {
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_PORT1_TX3_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_PORT1_TX3_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_PORT1_TX3_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_PORT1_TX3_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_PORT1_TX3_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_PORT1_TX3_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_3 Switch", LM49453_P0_PORT1_TX3_REG, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_port1_tx4_mixer[] = {
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_PORT1_TX4_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_PORT1_TX4_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_PORT1_TX4_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_PORT1_TX4_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_PORT1_TX4_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_PORT1_TX4_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_4 Switch", LM49453_P0_PORT1_TX4_REG, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_port1_tx5_mixer[] = {
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_PORT1_TX5_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_PORT1_TX5_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_PORT1_TX5_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_PORT1_TX5_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_PORT1_TX5_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_PORT1_TX5_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_5 Switch", LM49453_P0_PORT1_TX5_REG, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_port1_tx6_mixer[] = {
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_PORT1_TX6_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_PORT1_TX6_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_PORT1_TX6_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_PORT1_TX6_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_PORT1_TX6_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_PORT1_TX6_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_6 Switch", LM49453_P0_PORT1_TX6_REG, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_port1_tx7_mixer[] = {
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_PORT1_TX7_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_PORT1_TX7_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_PORT1_TX7_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_PORT1_TX7_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_PORT1_TX7_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_PORT1_TX7_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_7 Switch", LM49453_P0_PORT1_TX7_REG, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_port1_tx8_mixer[] = {
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_PORT1_TX8_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_PORT1_TX8_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_PORT1_TX8_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_PORT1_TX8_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_PORT1_TX8_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_PORT1_TX8_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_8 Switch", LM49453_P0_PORT1_TX8_REG, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_port2_tx1_mixer[] = {
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_PORT2_TX1_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_PORT2_TX1_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_PORT2_TX1_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_PORT2_TX1_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_PORT2_TX1_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_PORT2_TX1_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_1 Switch", LM49453_P0_PORT2_TX1_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port2_1 Switch", LM49453_P0_PORT2_TX1_REG, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new lm49453_port2_tx2_mixer[] = {
+SOC_DAPM_SINGLE("DMIC1L Switch", LM49453_P0_PORT2_TX2_REG, 0, 1, 0),
+SOC_DAPM_SINGLE("DMIC1R Switch", LM49453_P0_PORT2_TX2_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DMIC2L Switch", LM49453_P0_PORT2_TX2_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("DMIC2R Switch", LM49453_P0_PORT2_TX2_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("ADCL Switch", LM49453_P0_PORT2_TX2_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("ADCR Switch", LM49453_P0_PORT2_TX2_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("Port1_2 Switch", LM49453_P0_PORT2_TX2_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("Port2_2 Switch", LM49453_P0_PORT2_TX2_REG, 7, 1, 0),
+};
+
+/* TLV Declarations */
+static const DECLARE_TLV_DB_SCALE(digital_tlv, -7650, 150, 1);
+static const DECLARE_TLV_DB_SCALE(port_tlv, 0, 600, 0);
+
+static const struct snd_kcontrol_new lm49453_sidetone_mixer_controls[] = {
+/* Sidetone supports mono only */
+SOC_DAPM_SINGLE_TLV("Sidetone ADCL Volume", LM49453_P0_STN_VOL_ADCL_REG,
+ 0, 0x3F, 0, digital_tlv),
+SOC_DAPM_SINGLE_TLV("Sidetone ADCR Volume", LM49453_P0_STN_VOL_ADCR_REG,
+ 0, 0x3F, 0, digital_tlv),
+SOC_DAPM_SINGLE_TLV("Sidetone DMIC1L Volume", LM49453_P0_STN_VOL_DMIC1L_REG,
+ 0, 0x3F, 0, digital_tlv),
+SOC_DAPM_SINGLE_TLV("Sidetone DMIC1R Volume", LM49453_P0_STN_VOL_DMIC1R_REG,
+ 0, 0x3F, 0, digital_tlv),
+SOC_DAPM_SINGLE_TLV("Sidetone DMIC2L Volume", LM49453_P0_STN_VOL_DMIC2L_REG,
+ 0, 0x3F, 0, digital_tlv),
+SOC_DAPM_SINGLE_TLV("Sidetone DMIC2R Volume", LM49453_P0_STN_VOL_DMIC2R_REG,
+ 0, 0x3F, 0, digital_tlv),
+};
+
+static const struct snd_kcontrol_new lm49453_snd_controls[] = {
+ /* mic1 and mic2 supports mono only */
+ SOC_SINGLE_TLV("Mic1 Volume", LM49453_P0_ADC_LEVELL_REG, 0, 6,
+ 0, digital_tlv),
+ SOC_SINGLE_TLV("Mic2 Volume", LM49453_P0_ADC_LEVELR_REG, 0, 6,
+ 0, digital_tlv),
+
+ SOC_DOUBLE_R_TLV("DMIC1 Volume", LM49453_P0_DMIC1_LEVELL_REG,
+ LM49453_P0_DMIC1_LEVELR_REG, 0, 6, 0, digital_tlv),
+ SOC_DOUBLE_R_TLV("DMIC2 Volume", LM49453_P0_DMIC2_LEVELL_REG,
+ LM49453_P0_DMIC2_LEVELR_REG, 0, 6, 0, digital_tlv),
+
+ SOC_DAPM_ENUM("Mic2Mode", lm49453_mic2mode_enum),
+ SOC_DAPM_ENUM("DMIC12 SRC", lm49453_dmic12_cfg_enum),
+ SOC_DAPM_ENUM("DMIC34 SRC", lm49453_dmic34_cfg_enum),
+
+ /* Capture path filter enable */
+ SOC_SINGLE("DMIC1 HPFilter Switch", LM49453_P0_ADC_FX_ENABLES_REG,
+ 0, 1, 0),
+ SOC_SINGLE("DMIC2 HPFilter Switch", LM49453_P0_ADC_FX_ENABLES_REG,
+ 1, 1, 0),
+ SOC_SINGLE("ADC HPFilter Switch", LM49453_P0_ADC_FX_ENABLES_REG,
+ 2, 1, 0),
+
+ SOC_DOUBLE_R_TLV("DAC HP Volume", LM49453_P0_DAC_HP_LEVELL_REG,
+ LM49453_P0_DAC_HP_LEVELR_REG, 0, 6, 0, digital_tlv),
+ SOC_DOUBLE_R_TLV("DAC LO Volume", LM49453_P0_DAC_LO_LEVELL_REG,
+ LM49453_P0_DAC_LO_LEVELR_REG, 0, 6, 0, digital_tlv),
+ SOC_DOUBLE_R_TLV("DAC LS Volume", LM49453_P0_DAC_LS_LEVELL_REG,
+ LM49453_P0_DAC_LS_LEVELR_REG, 0, 6, 0, digital_tlv),
+ SOC_DOUBLE_R_TLV("DAC HA Volume", LM49453_P0_DAC_HA_LEVELL_REG,
+ LM49453_P0_DAC_HA_LEVELR_REG, 0, 6, 0, digital_tlv),
+
+ SOC_SINGLE_TLV("EP Volume", LM49453_P0_DAC_LS_LEVELL_REG,
+ 0, 6, 0, digital_tlv),
+
+ SOC_SINGLE_TLV("PORT1_1_RX_LVL Volume", LM49453_P0_PORT1_RX_LVL1_REG,
+ 0, 3, 0, port_tlv),
+ SOC_SINGLE_TLV("PORT1_2_RX_LVL Volume", LM49453_P0_PORT1_RX_LVL1_REG,
+ 2, 3, 0, port_tlv),
+ SOC_SINGLE_TLV("PORT1_3_RX_LVL Volume", LM49453_P0_PORT1_RX_LVL1_REG,
+ 4, 3, 0, port_tlv),
+ SOC_SINGLE_TLV("PORT1_4_RX_LVL Volume", LM49453_P0_PORT1_RX_LVL1_REG,
+ 6, 3, 0, port_tlv),
+ SOC_SINGLE_TLV("PORT1_5_RX_LVL Volume", LM49453_P0_PORT1_RX_LVL2_REG,
+ 0, 3, 0, port_tlv),
+ SOC_SINGLE_TLV("PORT1_6_RX_LVL Volume", LM49453_P0_PORT1_RX_LVL2_REG,
+ 2, 3, 0, port_tlv),
+ SOC_SINGLE_TLV("PORT1_7_RX_LVL Volume", LM49453_P0_PORT1_RX_LVL2_REG,
+ 4, 3, 0, port_tlv),
+ SOC_SINGLE_TLV("PORT1_8_RX_LVL Volume", LM49453_P0_PORT1_RX_LVL2_REG,
+ 6, 3, 0, port_tlv),
+
+ SOC_SINGLE_TLV("PORT2_1_RX_LVL Volume", LM49453_P0_PORT2_RX_LVL_REG,
+ 0, 3, 0, port_tlv),
+ SOC_SINGLE_TLV("PORT2_2_RX_LVL Volume", LM49453_P0_PORT2_RX_LVL_REG,
+ 2, 3, 0, port_tlv),
+
+ SOC_SINGLE("Port1 Playback Switch", LM49453_P0_AUDIO_PORT1_BASIC_REG,
+ 1, 1, 0),
+ SOC_SINGLE("Port2 Playback Switch", LM49453_P0_AUDIO_PORT2_BASIC_REG,
+ 1, 1, 0),
+ SOC_SINGLE("Port1 Capture Switch", LM49453_P0_AUDIO_PORT1_BASIC_REG,
+ 2, 1, 0),
+ SOC_SINGLE("Port2 Capture Switch", LM49453_P0_AUDIO_PORT2_BASIC_REG,
+ 2, 1, 0)
+
+};
+
+/* DAPM widgets */
+static const struct snd_soc_dapm_widget lm49453_dapm_widgets[] = {
+
+ /* All end points HP,EP, LS, Lineout and Haptic */
+ SND_SOC_DAPM_OUTPUT("HPOUTL"),
+ SND_SOC_DAPM_OUTPUT("HPOUTR"),
+ SND_SOC_DAPM_OUTPUT("EPOUT"),
+ SND_SOC_DAPM_OUTPUT("LSOUTL"),
+ SND_SOC_DAPM_OUTPUT("LSOUTR"),
+ SND_SOC_DAPM_OUTPUT("LOOUTR"),
+ SND_SOC_DAPM_OUTPUT("LOOUTL"),
+ SND_SOC_DAPM_OUTPUT("HAOUTL"),
+ SND_SOC_DAPM_OUTPUT("HAOUTR"),
+
+ SND_SOC_DAPM_INPUT("AMIC1"),
+ SND_SOC_DAPM_INPUT("AMIC2"),
+ SND_SOC_DAPM_INPUT("DMIC1DAT"),
+ SND_SOC_DAPM_INPUT("DMIC2DAT"),
+ SND_SOC_DAPM_INPUT("AUXL"),
+ SND_SOC_DAPM_INPUT("AUXR"),
+
+ SND_SOC_DAPM_PGA("PORT1_1_RX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("PORT1_2_RX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("PORT1_3_RX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("PORT1_4_RX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("PORT1_5_RX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("PORT1_6_RX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("PORT1_7_RX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("PORT1_8_RX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("PORT2_1_RX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("PORT2_2_RX", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("AMIC1Bias", LM49453_P0_MICL_REG, 6, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("AMIC2Bias", LM49453_P0_MICR_REG, 6, 0, NULL, 0),
+
+ /* playback path driver enables */
+ SND_SOC_DAPM_OUT_DRV("Headset Switch",
+ LM49453_P0_PMC_SETUP_REG, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("Earpiece Switch",
+ LM49453_P0_EP_REG, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("Speaker Left Switch",
+ LM49453_P0_DIS_PKVL_FB_REG, 0, 1, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("Speaker Right Switch",
+ LM49453_P0_DIS_PKVL_FB_REG, 1, 1, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("Haptic Left Switch",
+ LM49453_P0_DIS_PKVL_FB_REG, 2, 1, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("Haptic Right Switch",
+ LM49453_P0_DIS_PKVL_FB_REG, 3, 1, NULL, 0),
+
+ /* DAC */
+ SND_SOC_DAPM_DAC("HPL DAC", "Headset", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("HPR DAC", "Headset", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("LSL DAC", "Speaker", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("LSR DAC", "Speaker", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("HAL DAC", "Haptic", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("HAR DAC", "Haptic", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("LOL DAC", "Lineout", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("LOR DAC", "Lineout", SND_SOC_NOPM, 0, 0),
+
+
+ SND_SOC_DAPM_PGA("AUXL Input",
+ LM49453_P0_ANALOG_MIXER_ADC_REG, 2, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("AUXR Input",
+ LM49453_P0_ANALOG_MIXER_ADC_REG, 3, 0, NULL, 0),
+
+ SND_SOC_DAPM_PGA("Sidetone", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* ADC */
+ SND_SOC_DAPM_ADC("DMIC1 Left", "Capture", SND_SOC_NOPM, 1, 0),
+ SND_SOC_DAPM_ADC("DMIC1 Right", "Capture", SND_SOC_NOPM, 1, 0),
+ SND_SOC_DAPM_ADC("DMIC2 Left", "Capture", SND_SOC_NOPM, 1, 0),
+ SND_SOC_DAPM_ADC("DMIC2 Right", "Capture", SND_SOC_NOPM, 1, 0),
+
+ SND_SOC_DAPM_ADC("ADC Left", "Capture", SND_SOC_NOPM, 1, 0),
+ SND_SOC_DAPM_ADC("ADC Right", "Capture", SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_MUX("ADCL Mux", SND_SOC_NOPM, 0, 0,
+ &lm49453_adcl_mux_control),
+ SND_SOC_DAPM_MUX("ADCR Mux", SND_SOC_NOPM, 0, 0,
+ &lm49453_adcr_mux_control),
+
+ SND_SOC_DAPM_MUX("Mic1 Input",
+ SND_SOC_NOPM, 0, 0, &lm49453_adcl_mux_control),
+
+ SND_SOC_DAPM_MUX("Mic2 Input",
+ SND_SOC_NOPM, 0, 0, &lm49453_adcr_mux_control),
+
+ /* AIF */
+ SND_SOC_DAPM_AIF_IN("PORT1_SDI", NULL, 0,
+ LM49453_P0_PULL_CONFIG1_REG, 2, 0),
+ SND_SOC_DAPM_AIF_IN("PORT2_SDI", NULL, 0,
+ LM49453_P0_PULL_CONFIG1_REG, 6, 0),
+
+ SND_SOC_DAPM_AIF_OUT("PORT1_SDO", NULL, 0,
+ LM49453_P0_PULL_CONFIG1_REG, 3, 0),
+ SND_SOC_DAPM_AIF_OUT("PORT2_SDO", NULL, 0,
+ LM49453_P0_PULL_CONFIG1_REG, 7, 0),
+
+ /* Port1 TX controls */
+ SND_SOC_DAPM_OUT_DRV("P1_1_TX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("P1_2_TX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("P1_3_TX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("P1_4_TX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("P1_5_TX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("P1_6_TX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("P1_7_TX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("P1_8_TX", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Port2 TX controls */
+ SND_SOC_DAPM_OUT_DRV("P2_1_TX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("P2_2_TX", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Sidetone Mixer */
+ SND_SOC_DAPM_MIXER("Sidetone Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_sidetone_mixer_controls,
+ ARRAY_SIZE(lm49453_sidetone_mixer_controls)),
+
+ /* DAC MIXERS */
+ SND_SOC_DAPM_MIXER("HPL Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_headset_left_mixer,
+ ARRAY_SIZE(lm49453_headset_left_mixer)),
+ SND_SOC_DAPM_MIXER("HPR Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_headset_right_mixer,
+ ARRAY_SIZE(lm49453_headset_right_mixer)),
+ SND_SOC_DAPM_MIXER("LOL Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_lineout_left_mixer,
+ ARRAY_SIZE(lm49453_lineout_left_mixer)),
+ SND_SOC_DAPM_MIXER("LOR Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_lineout_right_mixer,
+ ARRAY_SIZE(lm49453_lineout_right_mixer)),
+ SND_SOC_DAPM_MIXER("LSL Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_speaker_left_mixer,
+ ARRAY_SIZE(lm49453_speaker_left_mixer)),
+ SND_SOC_DAPM_MIXER("LSR Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_speaker_right_mixer,
+ ARRAY_SIZE(lm49453_speaker_right_mixer)),
+ SND_SOC_DAPM_MIXER("HAL Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_haptic_left_mixer,
+ ARRAY_SIZE(lm49453_haptic_left_mixer)),
+ SND_SOC_DAPM_MIXER("HAR Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_haptic_right_mixer,
+ ARRAY_SIZE(lm49453_haptic_right_mixer)),
+
+ /* Capture Mixer */
+ SND_SOC_DAPM_MIXER("Port1_1 Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_port1_tx1_mixer,
+ ARRAY_SIZE(lm49453_port1_tx1_mixer)),
+ SND_SOC_DAPM_MIXER("Port1_2 Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_port1_tx2_mixer,
+ ARRAY_SIZE(lm49453_port1_tx2_mixer)),
+ SND_SOC_DAPM_MIXER("Port1_3 Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_port1_tx3_mixer,
+ ARRAY_SIZE(lm49453_port1_tx3_mixer)),
+ SND_SOC_DAPM_MIXER("Port1_4 Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_port1_tx4_mixer,
+ ARRAY_SIZE(lm49453_port1_tx4_mixer)),
+ SND_SOC_DAPM_MIXER("Port1_5 Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_port1_tx5_mixer,
+ ARRAY_SIZE(lm49453_port1_tx5_mixer)),
+ SND_SOC_DAPM_MIXER("Port1_6 Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_port1_tx6_mixer,
+ ARRAY_SIZE(lm49453_port1_tx6_mixer)),
+ SND_SOC_DAPM_MIXER("Port1_7 Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_port1_tx7_mixer,
+ ARRAY_SIZE(lm49453_port1_tx7_mixer)),
+ SND_SOC_DAPM_MIXER("Port1_8 Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_port1_tx8_mixer,
+ ARRAY_SIZE(lm49453_port1_tx8_mixer)),
+
+ SND_SOC_DAPM_MIXER("Port2_1 Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_port2_tx1_mixer,
+ ARRAY_SIZE(lm49453_port2_tx1_mixer)),
+ SND_SOC_DAPM_MIXER("Port2_2 Mixer", SND_SOC_NOPM, 0, 0,
+ lm49453_port2_tx2_mixer,
+ ARRAY_SIZE(lm49453_port2_tx2_mixer)),
+};
+
+static const struct snd_soc_dapm_route lm49453_audio_map[] = {
+ /* Port SDI mapping */
+ { "PORT1_1_RX", "Port1 Playback Switch", "PORT1_SDI" },
+ { "PORT1_2_RX", "Port1 Playback Switch", "PORT1_SDI" },
+ { "PORT1_3_RX", "Port1 Playback Switch", "PORT1_SDI" },
+ { "PORT1_4_RX", "Port1 Playback Switch", "PORT1_SDI" },
+ { "PORT1_5_RX", "Port1 Playback Switch", "PORT1_SDI" },
+ { "PORT1_6_RX", "Port1 Playback Switch", "PORT1_SDI" },
+ { "PORT1_7_RX", "Port1 Playback Switch", "PORT1_SDI" },
+ { "PORT1_8_RX", "Port1 Playback Switch", "PORT1_SDI" },
+
+ { "PORT2_1_RX", "Port2 Playback Switch", "PORT2_SDI" },
+ { "PORT2_2_RX", "Port2 Playback Switch", "PORT2_SDI" },
+
+ /* HP mapping */
+ { "HPL Mixer", "Port1_1 Switch", "PORT1_1_RX" },
+ { "HPL Mixer", "Port1_2 Switch", "PORT1_2_RX" },
+ { "HPL Mixer", "Port1_3 Switch", "PORT1_3_RX" },
+ { "HPL Mixer", "Port1_4 Switch", "PORT1_4_RX" },
+ { "HPL Mixer", "Port1_5 Switch", "PORT1_5_RX" },
+ { "HPL Mixer", "Port1_6 Switch", "PORT1_6_RX" },
+ { "HPL Mixer", "Port1_7 Switch", "PORT1_7_RX" },
+ { "HPL Mixer", "Port1_8 Switch", "PORT1_8_RX" },
+
+ { "HPL Mixer", "Port2_1 Switch", "PORT2_1_RX" },
+ { "HPL Mixer", "Port2_2 Switch", "PORT2_2_RX" },
+
+ { "HPL Mixer", "ADCL Switch", "ADC Left" },
+ { "HPL Mixer", "ADCR Switch", "ADC Right" },
+ { "HPL Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "HPL Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "HPL Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "HPL Mixer", "DMIC2R Switch", "DMIC2 Right" },
+ { "HPL Mixer", "Sidetone Switch", "Sidetone" },
+
+ { "HPL DAC", NULL, "HPL Mixer" },
+
+ { "HPR Mixer", "Port1_1 Switch", "PORT1_1_RX" },
+ { "HPR Mixer", "Port1_2 Switch", "PORT1_2_RX" },
+ { "HPR Mixer", "Port1_3 Switch", "PORT1_3_RX" },
+ { "HPR Mixer", "Port1_4 Switch", "PORT1_4_RX" },
+ { "HPR Mixer", "Port1_5 Switch", "PORT1_5_RX" },
+ { "HPR Mixer", "Port1_6 Switch", "PORT1_6_RX" },
+ { "HPR Mixer", "Port1_7 Switch", "PORT1_7_RX" },
+ { "HPR Mixer", "Port1_8 Switch", "PORT1_8_RX" },
+
+ /* Port 2 */
+ { "HPR Mixer", "Port2_1 Switch", "PORT2_1_RX" },
+ { "HPR Mixer", "Port2_2 Switch", "PORT2_2_RX" },
+
+ { "HPR Mixer", "ADCL Switch", "ADC Left" },
+ { "HPR Mixer", "ADCR Switch", "ADC Right" },
+ { "HPR Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "HPR Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "HPR Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "HPR Mixer", "DMIC2L Switch", "DMIC2 Right" },
+ { "HPR Mixer", "Sidetone Switch", "Sidetone" },
+
+ { "HPR DAC", NULL, "HPR Mixer" },
+
+ { "HPOUTL", "Headset Switch", "HPL DAC"},
+ { "HPOUTR", "Headset Switch", "HPR DAC"},
+
+ /* EP map */
+ { "EPOUT", "Earpiece Switch", "HPL DAC" },
+
+ /* Speaker map */
+ { "LSL Mixer", "Port1_1 Switch", "PORT1_1_RX" },
+ { "LSL Mixer", "Port1_2 Switch", "PORT1_2_RX" },
+ { "LSL Mixer", "Port1_3 Switch", "PORT1_3_RX" },
+ { "LSL Mixer", "Port1_4 Switch", "PORT1_4_RX" },
+ { "LSL Mixer", "Port1_5 Switch", "PORT1_5_RX" },
+ { "LSL Mixer", "Port1_6 Switch", "PORT1_6_RX" },
+ { "LSL Mixer", "Port1_7 Switch", "PORT1_7_RX" },
+ { "LSL Mixer", "Port1_8 Switch", "PORT1_8_RX" },
+
+ /* Port 2 */
+ { "LSL Mixer", "Port2_1 Switch", "PORT2_1_RX" },
+ { "LSL Mixer", "Port2_2 Switch", "PORT2_2_RX" },
+
+ { "LSL Mixer", "ADCL Switch", "ADC Left" },
+ { "LSL Mixer", "ADCR Switch", "ADC Right" },
+ { "LSL Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "LSL Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "LSL Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "LSL Mixer", "DMIC2R Switch", "DMIC2 Right" },
+ { "LSL Mixer", "Sidetone Switch", "Sidetone" },
+
+ { "LSL DAC", NULL, "LSL Mixer" },
+
+ { "LSR Mixer", "Port1_1 Switch", "PORT1_1_RX" },
+ { "LSR Mixer", "Port1_2 Switch", "PORT1_2_RX" },
+ { "LSR Mixer", "Port1_3 Switch", "PORT1_3_RX" },
+ { "LSR Mixer", "Port1_4 Switch", "PORT1_4_RX" },
+ { "LSR Mixer", "Port1_5 Switch", "PORT1_5_RX" },
+ { "LSR Mixer", "Port1_6 Switch", "PORT1_6_RX" },
+ { "LSR Mixer", "Port1_7 Switch", "PORT1_7_RX" },
+ { "LSR Mixer", "Port1_8 Switch", "PORT1_8_RX" },
+
+ /* Port 2 */
+ { "LSR Mixer", "Port2_1 Switch", "PORT2_1_RX" },
+ { "LSR Mixer", "Port2_2 Switch", "PORT2_2_RX" },
+
+ { "LSR Mixer", "ADCL Switch", "ADC Left" },
+ { "LSR Mixer", "ADCR Switch", "ADC Right" },
+ { "LSR Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "LSR Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "LSR Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "LSR Mixer", "DMIC2R Switch", "DMIC2 Right" },
+ { "LSR Mixer", "Sidetone Switch", "Sidetone" },
+
+ { "LSR DAC", NULL, "LSR Mixer" },
+
+ { "LSOUTL", "Speaker Left Switch", "LSL DAC"},
+ { "LSOUTR", "Speaker Left Switch", "LSR DAC"},
+
+ /* Haptic map */
+ { "HAL Mixer", "Port1_1 Switch", "PORT1_1_RX" },
+ { "HAL Mixer", "Port1_2 Switch", "PORT1_2_RX" },
+ { "HAL Mixer", "Port1_3 Switch", "PORT1_3_RX" },
+ { "HAL Mixer", "Port1_4 Switch", "PORT1_4_RX" },
+ { "HAL Mixer", "Port1_5 Switch", "PORT1_5_RX" },
+ { "HAL Mixer", "Port1_6 Switch", "PORT1_6_RX" },
+ { "HAL Mixer", "Port1_7 Switch", "PORT1_7_RX" },
+ { "HAL Mixer", "Port1_8 Switch", "PORT1_8_RX" },
+
+ /* Port 2 */
+ { "HAL Mixer", "Port2_1 Switch", "PORT2_1_RX" },
+ { "HAL Mixer", "Port2_2 Switch", "PORT2_2_RX" },
+
+ { "HAL Mixer", "ADCL Switch", "ADC Left" },
+ { "HAL Mixer", "ADCR Switch", "ADC Right" },
+ { "HAL Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "HAL Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "HAL Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "HAL Mixer", "DMIC2R Switch", "DMIC2 Right" },
+ { "HAL Mixer", "Sidetone Switch", "Sidetone" },
+
+ { "HAL DAC", NULL, "HAL Mixer" },
+
+ { "HAR Mixer", "Port1_1 Switch", "PORT1_1_RX" },
+ { "HAR Mixer", "Port1_2 Switch", "PORT1_2_RX" },
+ { "HAR Mixer", "Port1_3 Switch", "PORT1_3_RX" },
+ { "HAR Mixer", "Port1_4 Switch", "PORT1_4_RX" },
+ { "HAR Mixer", "Port1_5 Switch", "PORT1_5_RX" },
+ { "HAR Mixer", "Port1_6 Switch", "PORT1_6_RX" },
+ { "HAR Mixer", "Port1_7 Switch", "PORT1_7_RX" },
+ { "HAR Mixer", "Port1_8 Switch", "PORT1_8_RX" },
+
+ /* Port 2 */
+ { "HAR Mixer", "Port2_1 Switch", "PORT2_1_RX" },
+ { "HAR Mixer", "Port2_2 Switch", "PORT2_2_RX" },
+
+ { "HAR Mixer", "ADCL Switch", "ADC Left" },
+ { "HAR Mixer", "ADCR Switch", "ADC Right" },
+ { "HAR Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "HAR Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "HAR Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "HAR Mixer", "DMIC2R Switch", "DMIC2 Right" },
+ { "HAR Mixer", "Sideton Switch", "Sidetone" },
+
+ { "HAR DAC", NULL, "HAR Mixer" },
+
+ { "HAOUTL", "Haptic Left Switch", "HAL DAC" },
+ { "HAOUTR", "Haptic Right Switch", "HAR DAC" },
+
+ /* Lineout map */
+ { "LOL Mixer", "Port1_1 Switch", "PORT1_1_RX" },
+ { "LOL Mixer", "Port1_2 Switch", "PORT1_2_RX" },
+ { "LOL Mixer", "Port1_3 Switch", "PORT1_3_RX" },
+ { "LOL Mixer", "Port1_4 Switch", "PORT1_4_RX" },
+ { "LOL Mixer", "Port1_5 Switch", "PORT1_5_RX" },
+ { "LOL Mixer", "Port1_6 Switch", "PORT1_6_RX" },
+ { "LOL Mixer", "Port1_7 Switch", "PORT1_7_RX" },
+ { "LOL Mixer", "Port1_8 Switch", "PORT1_8_RX" },
+
+ /* Port 2 */
+ { "LOL Mixer", "Port2_1 Switch", "PORT2_1_RX" },
+ { "LOL Mixer", "Port2_2 Switch", "PORT2_2_RX" },
+
+ { "LOL Mixer", "ADCL Switch", "ADC Left" },
+ { "LOL Mixer", "ADCR Switch", "ADC Right" },
+ { "LOL Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "LOL Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "LOL Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "LOL Mixer", "DMIC2R Switch", "DMIC2 Right" },
+ { "LOL Mixer", "Sidetone Switch", "Sidetone" },
+
+ { "LOL DAC", NULL, "LOL Mixer" },
+
+ { "LOR Mixer", "Port1_1 Switch", "PORT1_1_RX" },
+ { "LOR Mixer", "Port1_2 Switch", "PORT1_2_RX" },
+ { "LOR Mixer", "Port1_3 Switch", "PORT1_3_RX" },
+ { "LOR Mixer", "Port1_4 Switch", "PORT1_4_RX" },
+ { "LOR Mixer", "Port1_5 Switch", "PORT1_5_RX" },
+ { "LOR Mixer", "Port1_6 Switch", "PORT1_6_RX" },
+ { "LOR Mixer", "Port1_7 Switch", "PORT1_7_RX" },
+ { "LOR Mixer", "Port1_8 Switch", "PORT1_8_RX" },
+
+ /* Port 2 */
+ { "LOR Mixer", "Port2_1 Switch", "PORT2_1_RX" },
+ { "LOR Mixer", "Port2_2 Switch", "PORT2_2_RX" },
+
+ { "LOR Mixer", "ADCL Switch", "ADC Left" },
+ { "LOR Mixer", "ADCR Switch", "ADC Right" },
+ { "LOR Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "LOR Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "LOR Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "LOR Mixer", "DMIC2R Switch", "DMIC2 Right" },
+ { "LOR Mixer", "Sidetone Switch", "Sidetone" },
+
+ { "LOR DAC", NULL, "LOR Mixer" },
+
+ { "LOOUTL", NULL, "LOL DAC" },
+ { "LOOUTR", NULL, "LOR DAC" },
+
+ /* TX map */
+ /* Port1 mappings */
+ { "Port1_1 Mixer", "ADCL Switch", "ADC Left" },
+ { "Port1_1 Mixer", "ADCR Switch", "ADC Right" },
+ { "Port1_1 Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "Port1_1 Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "Port1_1 Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "Port1_1 Mixer", "DMIC2R Switch", "DMIC2 Right" },
+
+ { "Port1_2 Mixer", "ADCL Switch", "ADC Left" },
+ { "Port1_2 Mixer", "ADCR Switch", "ADC Right" },
+ { "Port1_2 Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "Port1_2 Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "Port1_2 Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "Port1_2 Mixer", "DMIC2R Switch", "DMIC2 Right" },
+
+ { "Port1_3 Mixer", "ADCL Switch", "ADC Left" },
+ { "Port1_3 Mixer", "ADCR Switch", "ADC Right" },
+ { "Port1_3 Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "Port1_3 Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "Port1_3 Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "Port1_3 Mixer", "DMIC2R Switch", "DMIC2 Right" },
+
+ { "Port1_4 Mixer", "ADCL Switch", "ADC Left" },
+ { "Port1_4 Mixer", "ADCR Switch", "ADC Right" },
+ { "Port1_4 Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "Port1_4 Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "Port1_4 Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "Port1_4 Mixer", "DMIC2R Switch", "DMIC2 Right" },
+
+ { "Port1_5 Mixer", "ADCL Switch", "ADC Left" },
+ { "Port1_5 Mixer", "ADCR Switch", "ADC Right" },
+ { "Port1_5 Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "Port1_5 Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "Port1_5 Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "Port1_5 Mixer", "DMIC2R Switch", "DMIC2 Right" },
+
+ { "Port1_6 Mixer", "ADCL Switch", "ADC Left" },
+ { "Port1_6 Mixer", "ADCR Switch", "ADC Right" },
+ { "Port1_6 Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "Port1_6 Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "Port1_6 Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "Port1_6 Mixer", "DMIC2R Switch", "DMIC2 Right" },
+
+ { "Port1_7 Mixer", "ADCL Switch", "ADC Left" },
+ { "Port1_7 Mixer", "ADCR Switch", "ADC Right" },
+ { "Port1_7 Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "Port1_7 Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "Port1_7 Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "Port1_7 Mixer", "DMIC2R Switch", "DMIC2 Right" },
+
+ { "Port1_8 Mixer", "ADCL Switch", "ADC Left" },
+ { "Port1_8 Mixer", "ADCR Switch", "ADC Right" },
+ { "Port1_8 Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "Port1_8 Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "Port1_8 Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "Port1_8 Mixer", "DMIC2R Switch", "DMIC2 Right" },
+
+ { "Port2_1 Mixer", "ADCL Switch", "ADC Left" },
+ { "Port2_1 Mixer", "ADCR Switch", "ADC Right" },
+ { "Port2_1 Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "Port2_1 Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "Port2_1 Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "Port2_1 Mixer", "DMIC2R Switch", "DMIC2 Right" },
+
+ { "Port2_2 Mixer", "ADCL Switch", "ADC Left" },
+ { "Port2_2 Mixer", "ADCR Switch", "ADC Right" },
+ { "Port2_2 Mixer", "DMIC1L Switch", "DMIC1 Left" },
+ { "Port2_2 Mixer", "DMIC1R Switch", "DMIC1 Right" },
+ { "Port2_2 Mixer", "DMIC2L Switch", "DMIC2 Left" },
+ { "Port2_2 Mixer", "DMIC2R Switch", "DMIC2 Right" },
+
+ { "P1_1_TX", NULL, "Port1_1 Mixer" },
+ { "P1_2_TX", NULL, "Port1_2 Mixer" },
+ { "P1_3_TX", NULL, "Port1_3 Mixer" },
+ { "P1_4_TX", NULL, "Port1_4 Mixer" },
+ { "P1_5_TX", NULL, "Port1_5 Mixer" },
+ { "P1_6_TX", NULL, "Port1_6 Mixer" },
+ { "P1_7_TX", NULL, "Port1_7 Mixer" },
+ { "P1_8_TX", NULL, "Port1_8 Mixer" },
+
+ { "P2_1_TX", NULL, "Port2_1 Mixer" },
+ { "P2_2_TX", NULL, "Port2_2 Mixer" },
+
+ { "PORT1_SDO", "Port1 Capture Switch", "P1_1_TX"},
+ { "PORT1_SDO", "Port1 Capture Switch", "P1_2_TX"},
+ { "PORT1_SDO", "Port1 Capture Switch", "P1_3_TX"},
+ { "PORT1_SDO", "Port1 Capture Switch", "P1_4_TX"},
+ { "PORT1_SDO", "Port1 Capture Switch", "P1_5_TX"},
+ { "PORT1_SDO", "Port1 Capture Switch", "P1_6_TX"},
+ { "PORT1_SDO", "Port1 Capture Switch", "P1_7_TX"},
+ { "PORT1_SDO", "Port1 Capture Switch", "P1_8_TX"},
+
+ { "PORT2_SDO", "Port2 Capture Switch", "P2_1_TX"},
+ { "PORT2_SDO", "Port2 Capture Switch", "P2_2_TX"},
+
+ { "Mic1 Input", NULL, "AMIC1" },
+ { "Mic2 Input", NULL, "AMIC2" },
+
+ { "AUXL Input", NULL, "AUXL" },
+ { "AUXR Input", NULL, "AUXR" },
+
+ /* AUX connections */
+ { "ADCL Mux", "Aux_L", "AUXL Input" },
+ { "ADCL Mux", "MIC1", "Mic1 Input" },
+
+ { "ADCR Mux", "Aux_R", "AUXR Input" },
+ { "ADCR Mux", "MIC2", "Mic2 Input" },
+
+ /* ADC connection */
+ { "ADC Left", NULL, "ADCL Mux"},
+ { "ADC Right", NULL, "ADCR Mux"},
+
+ { "DMIC1 Left", NULL, "DMIC1DAT"},
+ { "DMIC1 Right", NULL, "DMIC1DAT"},
+ { "DMIC2 Left", NULL, "DMIC2DAT"},
+ { "DMIC2 Right", NULL, "DMIC2DAT"},
+
+ /* Sidetone map */
+ { "Sidetone Mixer", NULL, "ADC Left" },
+ { "Sidetone Mixer", NULL, "ADC Right" },
+ { "Sidetone Mixer", NULL, "DMIC1 Left" },
+ { "Sidetone Mixer", NULL, "DMIC1 Right" },
+ { "Sidetone Mixer", NULL, "DMIC2 Left" },
+ { "Sidetone Mixer", NULL, "DMIC2 Right" },
+
+ { "Sidetone", "Sidetone Switch", "Sidetone Mixer" },
+};
+
+static int lm49453_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct lm49453_priv *lm49453 = snd_soc_codec_get_drvdata(codec);
+ u16 clk_div = 0;
+
+ lm49453->fs_rate = params_rate(params);
+
+ /* Setting DAC clock dividers based on substream sample rate. */
+ switch (lm49453->fs_rate) {
+ case 8000:
+ case 16000:
+ case 32000:
+ case 24000:
+ case 48000:
+ clk_div = 256;
+ break;
+ case 11025:
+ case 22050:
+ case 44100:
+ clk_div = 216;
+ break;
+ case 96000:
+ clk_div = 127;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_write(codec, LM49453_P0_ADC_CLK_DIV_REG, clk_div);
+ snd_soc_write(codec, LM49453_P0_DAC_HP_CLK_DIV_REG, clk_div);
+
+ return 0;
+}
+
+static int lm49453_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+
+ u16 aif_val;
+ int mode = 0;
+ int clk_phase = 0;
+ int clk_shift = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ aif_val = 0;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFM:
+ aif_val = LM49453_AUDIO_PORT1_BASIC_SYNC_MS;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ aif_val = LM49453_AUDIO_PORT1_BASIC_CLK_MS;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ aif_val = LM49453_AUDIO_PORT1_BASIC_CLK_MS |
+ LM49453_AUDIO_PORT1_BASIC_SYNC_MS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ mode = 1;
+ clk_phase = (1 << 5);
+ clk_shift = 1;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ mode = 1;
+ clk_phase = (1 << 5);
+ clk_shift = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, LM49453_P0_AUDIO_PORT1_BASIC_REG,
+ LM49453_AUDIO_PORT1_BASIC_FMT_MASK|BIT(1)|BIT(5),
+ (aif_val | mode | clk_phase));
+
+ snd_soc_write(codec, LM49453_P0_AUDIO_PORT1_RX_MSB_REG, clk_shift);
+
+ return 0;
+}
+
+static int lm49453_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
+ unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u16 pll_clk = 0;
+
+ switch (freq) {
+ case 12288000:
+ case 26000000:
+ case 19200000:
+ /* pll clk slection */
+ pll_clk = 0;
+ break;
+ case 48000:
+ case 32576:
+ /* fll clk slection */
+ pll_clk = BIT(4);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, LM49453_P0_PMC_SETUP_REG, BIT(4), pll_clk);
+
+ return 0;
+}
+
+static int lm49453_hp_mute(struct snd_soc_dai *dai, int mute)
+{
+ snd_soc_update_bits(dai->codec, LM49453_P0_DAC_DSP_REG, BIT(1)|BIT(0),
+ (mute ? (BIT(1)|BIT(0)) : 0));
+ return 0;
+}
+
+static int lm49453_lo_mute(struct snd_soc_dai *dai, int mute)
+{
+ snd_soc_update_bits(dai->codec, LM49453_P0_DAC_DSP_REG, BIT(3)|BIT(2),
+ (mute ? (BIT(3)|BIT(2)) : 0));
+ return 0;
+}
+
+static int lm49453_ls_mute(struct snd_soc_dai *dai, int mute)
+{
+ snd_soc_update_bits(dai->codec, LM49453_P0_DAC_DSP_REG, BIT(5)|BIT(4),
+ (mute ? (BIT(5)|BIT(4)) : 0));
+ return 0;
+}
+
+static int lm49453_ep_mute(struct snd_soc_dai *dai, int mute)
+{
+ snd_soc_update_bits(dai->codec, LM49453_P0_DAC_DSP_REG, BIT(4),
+ (mute ? BIT(4) : 0));
+ return 0;
+}
+
+static int lm49453_ha_mute(struct snd_soc_dai *dai, int mute)
+{
+ snd_soc_update_bits(dai->codec, LM49453_P0_DAC_DSP_REG, BIT(7)|BIT(6),
+ (mute ? (BIT(7)|BIT(6)) : 0));
+ return 0;
+}
+
+static int lm49453_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct lm49453_priv *lm49453 = snd_soc_codec_get_drvdata(codec);
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ case SND_SOC_BIAS_PREPARE:
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+ regcache_sync(lm49453->regmap);
+
+ snd_soc_update_bits(codec, LM49453_P0_PMC_SETUP_REG,
+ LM49453_PMC_SETUP_CHIP_EN, LM49453_CHIP_EN);
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ snd_soc_update_bits(codec, LM49453_P0_PMC_SETUP_REG,
+ LM49453_PMC_SETUP_CHIP_EN, 0);
+ break;
+ }
+
+ codec->dapm.bias_level = level;
+
+ return 0;
+}
+
+/* Formates supported by LM49453 driver. */
+#define LM49453_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops lm49453_headset_dai_ops = {
+ .hw_params = lm49453_hw_params,
+ .set_sysclk = lm49453_set_dai_sysclk,
+ .set_fmt = lm49453_set_dai_fmt,
+ .digital_mute = lm49453_hp_mute,
+};
+
+static struct snd_soc_dai_ops lm49453_speaker_dai_ops = {
+ .hw_params = lm49453_hw_params,
+ .set_sysclk = lm49453_set_dai_sysclk,
+ .set_fmt = lm49453_set_dai_fmt,
+ .digital_mute = lm49453_ls_mute,
+};
+
+static struct snd_soc_dai_ops lm49453_haptic_dai_ops = {
+ .hw_params = lm49453_hw_params,
+ .set_sysclk = lm49453_set_dai_sysclk,
+ .set_fmt = lm49453_set_dai_fmt,
+ .digital_mute = lm49453_ha_mute,
+};
+
+static struct snd_soc_dai_ops lm49453_ep_dai_ops = {
+ .hw_params = lm49453_hw_params,
+ .set_sysclk = lm49453_set_dai_sysclk,
+ .set_fmt = lm49453_set_dai_fmt,
+ .digital_mute = lm49453_ep_mute,
+};
+
+static struct snd_soc_dai_ops lm49453_lineout_dai_ops = {
+ .hw_params = lm49453_hw_params,
+ .set_sysclk = lm49453_set_dai_sysclk,
+ .set_fmt = lm49453_set_dai_fmt,
+ .digital_mute = lm49453_lo_mute,
+};
+
+/* LM49453 dai structure. */
+static const struct snd_soc_dai_driver lm49453_dai[] = {
+ {
+ .name = "LM49453 Headset",
+ .playback = {
+ .stream_name = "Headset",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = LM49453_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 5,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = LM49453_FORMATS,
+ },
+ .ops = &lm49453_headset_dai_ops,
+ .symmetric_rates = 1,
+ },
+ {
+ .name = "LM49453 Speaker",
+ .playback = {
+ .stream_name = "Speaker",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = LM49453_FORMATS,
+ },
+ .ops = &lm49453_speaker_dai_ops,
+ },
+ {
+ .name = "LM49453 Haptic",
+ .playback = {
+ .stream_name = "Haptic",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = LM49453_FORMATS,
+ },
+ .ops = &lm49453_haptic_dai_ops,
+ },
+ {
+ .name = "LM49453 Earpiece",
+ .playback = {
+ .stream_name = "Earpiece",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = LM49453_FORMATS,
+ },
+ .ops = &lm49453_ep_dai_ops,
+ },
+ {
+ .name = "LM49453 line out",
+ .playback = {
+ .stream_name = "Lineout",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = LM49453_FORMATS,
+ },
+ .ops = &lm49453_lineout_dai_ops,
+ },
+};
+
+static int lm49453_suspend(struct snd_soc_codec *codec)
+{
+ lm49453_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int lm49453_resume(struct snd_soc_codec *codec)
+{
+ lm49453_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ return 0;
+}
+
+static int lm49453_probe(struct snd_soc_codec *codec)
+{
+ struct lm49453_priv *lm49453 = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
+ codec->control_data = lm49453->regmap;
+
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* power down chip */
+static int lm49453_remove(struct snd_soc_codec *codec)
+{
+ lm49453_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_lm49453 = {
+ .probe = lm49453_probe,
+ .remove = lm49453_remove,
+ .suspend = lm49453_suspend,
+ .resume = lm49453_resume,
+ .set_bias_level = lm49453_set_bias_level,
+ .controls = lm49453_snd_controls,
+ .num_controls = ARRAY_SIZE(lm49453_snd_controls),
+ .dapm_widgets = lm49453_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(lm49453_dapm_widgets),
+ .dapm_routes = lm49453_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(lm49453_audio_map),
+ .idle_bias_off = true,
+};
+
+static const struct regmap_config lm49453_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = LM49453_MAX_REGISTER,
+ .reg_defaults = lm49453_reg_defs,
+ .num_reg_defaults = ARRAY_SIZE(lm49453_reg_defs),
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static __devinit int lm49453_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct lm49453_priv *lm49453;
+ int ret = 0;
+
+ lm49453 = devm_kzalloc(&i2c->dev, sizeof(struct lm49453_priv),
+ GFP_KERNEL);
+
+ if (lm49453 == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, lm49453);
+
+ lm49453->regmap = regmap_init_i2c(i2c, &lm49453_regmap_config);
+ if (IS_ERR(lm49453->regmap)) {
+ ret = PTR_ERR(lm49453->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_lm49453,
+ lm49453_dai, ARRAY_SIZE(lm49453_dai));
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
+ regmap_exit(lm49453->regmap);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int __devexit lm49453_i2c_remove(struct i2c_client *client)
+{
+ struct lm49453_priv *lm49453 = i2c_get_clientdata(client);
+
+ snd_soc_unregister_codec(&client->dev);
+ regmap_exit(lm49453->regmap);
+ return 0;
+}
+
+static const struct i2c_device_id lm49453_i2c_id[] = {
+ { "lm49453", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, lm49453_i2c_id);
+
+static struct i2c_driver lm49453_i2c_driver = {
+ .driver = {
+ .name = "lm49453",
+ .owner = THIS_MODULE,
+ },
+ .probe = lm49453_i2c_probe,
+ .remove = __devexit_p(lm49453_i2c_remove),
+ .id_table = lm49453_i2c_id,
+};
+
+module_i2c_driver(lm49453_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC LM49453 driver");
+MODULE_AUTHOR("M R Swami Reddy <MR.Swami.Reddy@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/lm49453.h b/sound/soc/codecs/lm49453.h
new file mode 100644
index 000000000000..a63cfa5c0883
--- /dev/null
+++ b/sound/soc/codecs/lm49453.h
@@ -0,0 +1,380 @@
+/*
+ * lm49453.h - LM49453 ALSA Soc Audio drive
+ *
+ * Copyright (c) 2012 Texas Instruments, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ */
+
+#ifndef _LM49453_H
+#define _LM49453_H
+
+#include <linux/bitops.h>
+
+/* LM49453_P0 register space for page0 */
+#define LM49453_P0_PMC_SETUP_REG 0x00
+#define LM49453_P0_PLL_CLK_SEL1_REG 0x01
+#define LM49453_P0_PLL_CLK_SEL2_REG 0x02
+#define LM49453_P0_PMC_CLK_DIV_REG 0x03
+#define LM49453_P0_HSDET_CLK_DIV_REG 0x04
+#define LM49453_P0_DMIC_CLK_DIV_REG 0x05
+#define LM49453_P0_ADC_CLK_DIV_REG 0x06
+#define LM49453_P0_DAC_OT_CLK_DIV_REG 0x07
+#define LM49453_P0_PLL_HF_M_REG 0x08
+#define LM49453_P0_PLL_LF_M_REG 0x09
+#define LM49453_P0_PLL_NL_REG 0x0A
+#define LM49453_P0_PLL_N_MODL_REG 0x0B
+#define LM49453_P0_PLL_N_MODH_REG 0x0C
+#define LM49453_P0_PLL_P1_REG 0x0D
+#define LM49453_P0_PLL_P2_REG 0x0E
+#define LM49453_P0_FLL_REF_FREQL_REG 0x0F
+#define LM49453_P0_FLL_REF_FREQH_REG 0x10
+#define LM49453_P0_VCO_TARGETLL_REG 0x11
+#define LM49453_P0_VCO_TARGETLH_REG 0x12
+#define LM49453_P0_VCO_TARGETHL_REG 0x13
+#define LM49453_P0_VCO_TARGETHH_REG 0x14
+#define LM49453_P0_PLL_CONFIG_REG 0x15
+#define LM49453_P0_DAC_CLK_SEL_REG 0x16
+#define LM49453_P0_DAC_HP_CLK_DIV_REG 0x17
+
+/* Analog Mixer Input Stages */
+#define LM49453_P0_MICL_REG 0x20
+#define LM49453_P0_MICR_REG 0x21
+#define LM49453_P0_EP_REG 0x24
+#define LM49453_P0_DIS_PKVL_FB_REG 0x25
+
+/* Analog Mixer Output Stages */
+#define LM49453_P0_ANALOG_MIXER_ADC_REG 0x2E
+
+/*ADC or DAC */
+#define LM49453_P0_ADC_DSP_REG 0x30
+#define LM49453_P0_DAC_DSP_REG 0x31
+
+/* EFFECTS ENABLES */
+#define LM49453_P0_ADC_FX_ENABLES_REG 0x33
+
+/* GPIO */
+#define LM49453_P0_GPIO1_REG 0x38
+#define LM49453_P0_GPIO2_REG 0x39
+#define LM49453_P0_GPIO3_REG 0x3A
+#define LM49453_P0_HAP_CTL_REG 0x3B
+#define LM49453_P0_HAP_FREQ_PROG_LEFTL_REG 0x3C
+#define LM49453_P0_HAP_FREQ_PROG_LEFTH_REG 0x3D
+#define LM49453_P0_HAP_FREQ_PROG_RIGHTL_REG 0x3E
+#define LM49453_P0_HAP_FREQ_PROG_RIGHTH_REG 0x3F
+
+/* DIGITAL MIXER */
+#define LM49453_P0_DMIX_CLK_SEL_REG 0x40
+#define LM49453_P0_PORT1_RX_LVL1_REG 0x41
+#define LM49453_P0_PORT1_RX_LVL2_REG 0x42
+#define LM49453_P0_PORT2_RX_LVL_REG 0x43
+#define LM49453_P0_PORT1_TX1_REG 0x44
+#define LM49453_P0_PORT1_TX2_REG 0x45
+#define LM49453_P0_PORT1_TX3_REG 0x46
+#define LM49453_P0_PORT1_TX4_REG 0x47
+#define LM49453_P0_PORT1_TX5_REG 0x48
+#define LM49453_P0_PORT1_TX6_REG 0x49
+#define LM49453_P0_PORT1_TX7_REG 0x4A
+#define LM49453_P0_PORT1_TX8_REG 0x4B
+#define LM49453_P0_PORT2_TX1_REG 0x4C
+#define LM49453_P0_PORT2_TX2_REG 0x4D
+#define LM49453_P0_STN_SEL_REG 0x4F
+#define LM49453_P0_DACHPL1_REG 0x50
+#define LM49453_P0_DACHPL2_REG 0x51
+#define LM49453_P0_DACHPR1_REG 0x52
+#define LM49453_P0_DACHPR2_REG 0x53
+#define LM49453_P0_DACLOL1_REG 0x54
+#define LM49453_P0_DACLOL2_REG 0x55
+#define LM49453_P0_DACLOR1_REG 0x56
+#define LM49453_P0_DACLOR2_REG 0x57
+#define LM49453_P0_DACLSL1_REG 0x58
+#define LM49453_P0_DACLSL2_REG 0x59
+#define LM49453_P0_DACLSR1_REG 0x5A
+#define LM49453_P0_DACLSR2_REG 0x5B
+#define LM49453_P0_DACHAL1_REG 0x5C
+#define LM49453_P0_DACHAL2_REG 0x5D
+#define LM49453_P0_DACHAR1_REG 0x5E
+#define LM49453_P0_DACHAR2_REG 0x5F
+
+/* AUDIO PORT 1 (TDM) */
+#define LM49453_P0_AUDIO_PORT1_BASIC_REG 0x60
+#define LM49453_P0_AUDIO_PORT1_CLK_GEN1_REG 0x61
+#define LM49453_P0_AUDIO_PORT1_CLK_GEN2_REG 0x62
+#define LM49453_P0_AUDIO_PORT1_CLK_GEN3_REG 0x63
+#define LM49453_P0_AUDIO_PORT1_SYNC_RATE_REG 0x64
+#define LM49453_P0_AUDIO_PORT1_SYNC_SDO_SETUP_REG 0x65
+#define LM49453_P0_AUDIO_PORT1_DATA_WIDTH_REG 0x66
+#define LM49453_P0_AUDIO_PORT1_RX_MSB_REG 0x67
+#define LM49453_P0_AUDIO_PORT1_TX_MSB_REG 0x68
+#define LM49453_P0_AUDIO_PORT1_TDM_CHANNELS_REG 0x69
+
+/* AUDIO PORT 2 */
+#define LM49453_P0_AUDIO_PORT2_BASIC_REG 0x6A
+#define LM49453_P0_AUDIO_PORT2_CLK_GEN1_REG 0x6B
+#define LM49453_P0_AUDIO_PORT2_CLK_GEN2_REG 0x6C
+#define LM49453_P0_AUDIO_PORT2_SYNC_GEN_REG 0x6D
+#define LM49453_P0_AUDIO_PORT2_DATA_WIDTH_REG 0x6E
+#define LM49453_P0_AUDIO_PORT2_RX_MODE_REG 0x6F
+#define LM49453_P0_AUDIO_PORT2_TX_MODE_REG 0x70
+
+/* SAMPLE RATE */
+#define LM49453_P0_PORT1_SR_LSB_REG 0x79
+#define LM49453_P0_PORT1_SR_MSB_REG 0x7A
+#define LM49453_P0_PORT2_SR_LSB_REG 0x7B
+#define LM49453_P0_PORT2_SR_MSB_REG 0x7C
+
+/* EFFECTS - HPFs */
+#define LM49453_P0_HPF_REG 0x80
+
+/* EFFECTS ADC ALC */
+#define LM49453_P0_ADC_ALC1_REG 0x82
+#define LM49453_P0_ADC_ALC2_REG 0x83
+#define LM49453_P0_ADC_ALC3_REG 0x84
+#define LM49453_P0_ADC_ALC4_REG 0x85
+#define LM49453_P0_ADC_ALC5_REG 0x86
+#define LM49453_P0_ADC_ALC6_REG 0x87
+#define LM49453_P0_ADC_ALC7_REG 0x88
+#define LM49453_P0_ADC_ALC8_REG 0x89
+#define LM49453_P0_DMIC1_LEVELL_REG 0x8A
+#define LM49453_P0_DMIC1_LEVELR_REG 0x8B
+#define LM49453_P0_DMIC2_LEVELL_REG 0x8C
+#define LM49453_P0_DMIC2_LEVELR_REG 0x8D
+#define LM49453_P0_ADC_LEVELL_REG 0x8E
+#define LM49453_P0_ADC_LEVELR_REG 0x8F
+#define LM49453_P0_DAC_HP_LEVELL_REG 0x90
+#define LM49453_P0_DAC_HP_LEVELR_REG 0x91
+#define LM49453_P0_DAC_LO_LEVELL_REG 0x92
+#define LM49453_P0_DAC_LO_LEVELR_REG 0x93
+#define LM49453_P0_DAC_LS_LEVELL_REG 0x94
+#define LM49453_P0_DAC_LS_LEVELR_REG 0x95
+#define LM49453_P0_DAC_HA_LEVELL_REG 0x96
+#define LM49453_P0_DAC_HA_LEVELR_REG 0x97
+#define LM49453_P0_SOFT_MUTE_REG 0x98
+#define LM49453_P0_DMIC_MUTE_CFG_REG 0x99
+#define LM49453_P0_ADC_MUTE_CFG_REG 0x9A
+#define LM49453_P0_DAC_MUTE_CFG_REG 0x9B
+
+/*DIGITAL MIC1 */
+#define LM49453_P0_DIGITAL_MIC1_CONFIG_REG 0xB0
+#define LM49453_P0_DIGITAL_MIC1_DATA_DELAYL_REG 0xB1
+#define LM49453_P0_DIGITAL_MIC1_DATA_DELAYR_REG 0xB2
+
+/*DIGITAL MIC2 */
+#define LM49453_P0_DIGITAL_MIC2_CONFIG_REG 0xB3
+#define LM49453_P0_DIGITAL_MIC2_DATA_DELAYL_REG 0xB4
+#define LM49453_P0_DIGITAL_MIC2_DATA_DELAYR_REG 0xB5
+
+/* ADC DECIMATOR */
+#define LM49453_P0_ADC_DECIMATOR_REG 0xB6
+
+/* DAC CONFIGURE */
+#define LM49453_P0_DAC_CONFIG_REG 0xB7
+
+/* SIDETONE */
+#define LM49453_P0_STN_VOL_ADCL_REG 0xB8
+#define LM49453_P0_STN_VOL_ADCR_REG 0xB9
+#define LM49453_P0_STN_VOL_DMIC1L_REG 0xBA
+#define LM49453_P0_STN_VOL_DMIC1R_REG 0xBB
+#define LM49453_P0_STN_VOL_DMIC2L_REG 0xBC
+#define LM49453_P0_STN_VOL_DMIC2R_REG 0xBD
+
+/* ADC/DAC CLIPPING MONITORS (Read Only/Write to Clear) */
+#define LM49453_P0_ADC_DEC_CLIP_REG 0xC2
+#define LM49453_P0_ADC_HPF_CLIP_REG 0xC3
+#define LM49453_P0_ADC_LVL_CLIP_REG 0xC4
+#define LM49453_P0_DAC_LVL_CLIP_REG 0xC5
+
+/* ADC ALC EFFECT MONITORS (Read Only) */
+#define LM49453_P0_ADC_LVLMONL_REG 0xC8
+#define LM49453_P0_ADC_LVLMONR_REG 0xC9
+#define LM49453_P0_ADC_ALCMONL_REG 0xCA
+#define LM49453_P0_ADC_ALCMONR_REG 0xCB
+#define LM49453_P0_ADC_MUTED_REG 0xCC
+#define LM49453_P0_DAC_MUTED_REG 0xCD
+
+/* HEADSET DETECT */
+#define LM49453_P0_HSD_PPB_LONG_CNT_LIMITL_REG 0xD0
+#define LM49453_P0_HSD_PPB_LONG_CNT_LIMITR_REG 0xD1
+#define LM49453_P0_HSD_PIN3_4_EX_LOOP_CNT_LIMITL_REG 0xD2
+#define LM49453_P0_HSD_PIN3_4_EX_LOOP_CNT_LIMITH_REG 0xD3
+#define LM49453_P0_HSD_TIMEOUT1_REG 0xD4
+#define LM49453_P0_HSD_TIMEOUT2_REG 0xD5
+#define LM49453_P0_HSD_TIMEOUT3_REG 0xD6
+#define LM49453_P0_HSD_PIN3_4_CFG_REG 0xD7
+#define LM49453_P0_HSD_IRQ1_REG 0xD8
+#define LM49453_P0_HSD_IRQ2_REG 0xD9
+#define LM49453_P0_HSD_IRQ3_REG 0xDA
+#define LM49453_P0_HSD_IRQ4_REG 0xDB
+#define LM49453_P0_HSD_IRQ_MASK1_REG 0xDC
+#define LM49453_P0_HSD_IRQ_MASK2_REG 0xDD
+#define LM49453_P0_HSD_IRQ_MASK3_REG 0xDE
+#define LM49453_P0_HSD_R_HPLL_REG 0xE0
+#define LM49453_P0_HSD_R_HPLH_REG 0xE1
+#define LM49453_P0_HSD_R_HPLU_REG 0xE2
+#define LM49453_P0_HSD_R_HPRL_REG 0xE3
+#define LM49453_P0_HSD_R_HPRH_REG 0xE4
+#define LM49453_P0_HSD_R_HPRU_REG 0xE5
+#define LM49453_P0_HSD_VEL_L_FINALL_REG 0xE6
+#define LM49453_P0_HSD_VEL_L_FINALH_REG 0xE7
+#define LM49453_P0_HSD_VEL_L_FINALU_REG 0xE8
+#define LM49453_P0_HSD_RO_FINALL_REG 0xE9
+#define LM49453_P0_HSD_RO_FINALH_REG 0xEA
+#define LM49453_P0_HSD_RO_FINALU_REG 0xEB
+#define LM49453_P0_HSD_VMIC_BIAS_FINALL_REG 0xEC
+#define LM49453_P0_HSD_VMIC_BIAS_FINALH_REG 0xED
+#define LM49453_P0_HSD_VMIC_BIAS_FINALU_REG 0xEE
+#define LM49453_P0_HSD_PIN_CONFIG_REG 0xEF
+#define LM49453_P0_HSD_PLUG_DETECT_BB_IRQ_STATUS1_REG 0xF1
+#define LM49453_P0_HSD_PLUG_DETECT_BB_IRQ_STATUS2_REG 0xF2
+#define LM49453_P0_HSD_PLUG_DETECT_BB_IRQ_STATUS3_REG 0xF3
+#define LM49453_P0_HSD_PLUG_DETECT_BB_IRQ_STATEL_REG 0xF4
+#define LM49453_P0_HSD_PLUG_DETECT_BB_IRQ_STATEH_REG 0xF5
+
+/* I/O PULLDOWN CONFIG */
+#define LM49453_P0_PULL_CONFIG1_REG 0xF8
+#define LM49453_P0_PULL_CONFIG2_REG 0xF9
+#define LM49453_P0_PULL_CONFIG3_REG 0xFA
+
+/* RESET */
+#define LM49453_P0_RESET_REG 0xFE
+
+/* PAGE */
+#define LM49453_PAGE_REG 0xFF
+
+#define LM49453_MAX_REGISTER (0xFF+1)
+
+/* LM49453_P0_PMC_SETUP_REG (0x00h) */
+#define LM49453_PMC_SETUP_CHIP_EN (BIT(1)|BIT(0))
+#define LM49453_PMC_SETUP_PLL_EN BIT(2)
+#define LM49453_PMC_SETUP_PLL_P2_EN BIT(3)
+#define LM49453_PMC_SETUP_PLL_FLL BIT(4)
+#define LM49453_PMC_SETUP_MCLK_OVER BIT(5)
+#define LM49453_PMC_SETUP_RTC_CLK_OVER BIT(6)
+#define LM49453_PMC_SETUP_CHIP_ACTIVE BIT(7)
+
+/* Chip Enable bits */
+#define LM49453_CHIP_EN_SHUTDOWN 0x00
+#define LM49453_CHIP_EN 0x01
+#define LM49453_CHIP_EN_HSD_DETECT 0x02
+#define LM49453_CHIP_EN_INVALID_HSD 0x03
+
+/* LM49453_P0_PLL_CLK_SEL1_REG (0x01h) */
+#define LM49453_CLK_SEL1_MCLK_SEL 0x11
+#define LM49453_CLK_SEL1_RTC_SEL 0x11
+#define LM49453_CLK_SEL1_PORT1_SEL 0x10
+#define LM49453_CLK_SEL1_PORT2_SEL 0x11
+
+/* LM49453_P0_PLL_CLK_SEL2_REG (0x02h) */
+#define LM49453_CLK_SEL2_ADC_CLK_SEL 0x38
+
+/* LM49453_P0_FLL_REF_FREQL_REG (0x0F) */
+#define LM49453_FLL_REF_FREQ_VAL 0x8ca0001
+
+/* LM49453_P0_VCO_TARGETLL_REG (0x11) */
+#define LM49453_VCO_TARGET_VAL 0x8ca0001
+
+/* LM49453_P0_ADC_DSP_REG (0x30h) */
+#define LM49453_ADC_DSP_ADC_MUTEL BIT(0)
+#define LM49453_ADC_DSP_ADC_MUTER BIT(1)
+#define LM49453_ADC_DSP_DMIC1_MUTEL BIT(2)
+#define LM49453_ADC_DSP_DMIC1_MUTER BIT(3)
+#define LM49453_ADC_DSP_DMIC2_MUTEL BIT(4)
+#define LM49453_ADC_DSP_DMIC2_MUTER BIT(5)
+#define LM49453_ADC_DSP_MUTE_ALL 0x3F
+
+/* LM49453_P0_DAC_DSP_REG (0x31h) */
+#define LM49453_DAC_DSP_MUTE_ALL 0xFF
+
+/* LM49453_P0_AUDIO_PORT1_BASIC_REG (0x60h) */
+#define LM49453_AUDIO_PORT1_BASIC_FMT_MASK (BIT(4)|BIT(3))
+#define LM49453_AUDIO_PORT1_BASIC_CLK_MS BIT(3)
+#define LM49453_AUDIO_PORT1_BASIC_SYNC_MS BIT(4)
+
+/* LM49453_P0_RESET_REG (0xFEh) */
+#define LM49453_RESET_REG_RST BIT(0)
+
+/* Page select register bits (0xFF) */
+#define LM49453_PAGE0_SELECT 0x0
+#define LM49453_PAGE1_SELECT 0x1
+
+/* LM49453_P0_HSD_PIN3_4_CFG_REG (Jack Pin config - 0xD7) */
+#define LM49453_JACK_DISABLE 0x00
+#define LM49453_JACK_CONFIG1 0x01
+#define LM49453_JACK_CONFIG2 0x02
+#define LM49453_JACK_CONFIG3 0x03
+#define LM49453_JACK_CONFIG4 0x04
+#define LM49453_JACK_CONFIG5 0x05
+
+/* Page 1 REGISTERS */
+
+/* SIDETONE */
+#define LM49453_P1_SIDETONE_SA0L_REG 0x80
+#define LM49453_P1_SIDETONE_SA0H_REG 0x81
+#define LM49453_P1_SIDETONE_SAB0U_REG 0x82
+#define LM49453_P1_SIDETONE_SB0L_REG 0x83
+#define LM49453_P1_SIDETONE_SB0H_REG 0x84
+#define LM49453_P1_SIDETONE_SH0L_REG 0x85
+#define LM49453_P1_SIDETONE_SH0H_REG 0x86
+#define LM49453_P1_SIDETONE_SH0U_REG 0x87
+#define LM49453_P1_SIDETONE_SA1L_REG 0x88
+#define LM49453_P1_SIDETONE_SA1H_REG 0x89
+#define LM49453_P1_SIDETONE_SAB1U_REG 0x8A
+#define LM49453_P1_SIDETONE_SB1L_REG 0x8B
+#define LM49453_P1_SIDETONE_SB1H_REG 0x8C
+#define LM49453_P1_SIDETONE_SH1L_REG 0x8D
+#define LM49453_P1_SIDETONE_SH1H_REG 0x8E
+#define LM49453_P1_SIDETONE_SH1U_REG 0x8F
+#define LM49453_P1_SIDETONE_SA2L_REG 0x90
+#define LM49453_P1_SIDETONE_SA2H_REG 0x91
+#define LM49453_P1_SIDETONE_SAB2U_REG 0x92
+#define LM49453_P1_SIDETONE_SB2L_REG 0x93
+#define LM49453_P1_SIDETONE_SB2H_REG 0x94
+#define LM49453_P1_SIDETONE_SH2L_REG 0x95
+#define LM49453_P1_SIDETONE_SH2H_REG 0x96
+#define LM49453_P1_SIDETONE_SH2U_REG 0x97
+#define LM49453_P1_SIDETONE_SA3L_REG 0x98
+#define LM49453_P1_SIDETONE_SA3H_REG 0x99
+#define LM49453_P1_SIDETONE_SAB3U_REG 0x9A
+#define LM49453_P1_SIDETONE_SB3L_REG 0x9B
+#define LM49453_P1_SIDETONE_SB3H_REG 0x9C
+#define LM49453_P1_SIDETONE_SH3L_REG 0x9D
+#define LM49453_P1_SIDETONE_SH3H_REG 0x9E
+#define LM49453_P1_SIDETONE_SH3U_REG 0x9F
+#define LM49453_P1_SIDETONE_SA4L_REG 0xA0
+#define LM49453_P1_SIDETONE_SA4H_REG 0xA1
+#define LM49453_P1_SIDETONE_SAB4U_REG 0xA2
+#define LM49453_P1_SIDETONE_SB4L_REG 0xA3
+#define LM49453_P1_SIDETONE_SB4H_REG 0xA4
+#define LM49453_P1_SIDETONE_SH4L_REG 0xA5
+#define LM49453_P1_SIDETONE_SH4H_REG 0xA6
+#define LM49453_P1_SIDETONE_SH4U_REG 0xA7
+#define LM49453_P1_SIDETONE_SA5L_REG 0xA8
+#define LM49453_P1_SIDETONE_SA5H_REG 0xA9
+#define LM49453_P1_SIDETONE_SAB5U_REG 0xAA
+#define LM49453_P1_SIDETONE_SB5L_REG 0xAB
+#define LM49453_P1_SIDETONE_SB5H_REG 0xAC
+#define LM49453_P1_SIDETONE_SH5L_REG 0xAD
+#define LM49453_P1_SIDETONE_SH5H_REG 0xAE
+#define LM49453_P1_SIDETONE_SH5U_REG 0xAF
+
+/* CHARGE PUMP CONFIG */
+#define LM49453_P1_CP_CONFIG1_REG 0xB0
+#define LM49453_P1_CP_CONFIG2_REG 0xB1
+#define LM49453_P1_CP_CONFIG3_REG 0xB2
+#define LM49453_P1_CP_CONFIG4_REG 0xB3
+#define LM49453_P1_CP_LA_VTH1L_REG 0xB4
+#define LM49453_P1_CP_LA_VTH1M_REG 0xB5
+#define LM49453_P1_CP_LA_VTH2L_REG 0xB6
+#define LM49453_P1_CP_LA_VTH2M_REG 0xB7
+#define LM49453_P1_CP_LA_VTH3L_REG 0xB8
+#define LM49453_P1_CP_LA_VTH3H_REG 0xB9
+#define LM49453_P1_CP_CLK_DIV_REG 0xBA
+
+/* DAC */
+#define LM49453_P1_DAC_CHOP_REG 0xC0
+
+#define LM49453_CLK_SRC_MCLK 1
+#endif
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 0bb511a0388d..35179e2c23c9 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -24,6 +24,7 @@
#include <linux/slab.h>
#include <asm/div64.h>
#include <sound/max98095.h>
+#include <sound/jack.h>
#include "max98095.h"
enum max98095_type {
@@ -51,6 +52,8 @@ struct max98095_priv {
u8 lin_state;
unsigned int mic1pre;
unsigned int mic2pre;
+ struct snd_soc_jack *headphone_jack;
+ struct snd_soc_jack *mic_jack;
};
static const u8 max98095_reg_def[M98095_REG_CNT] = {
@@ -2173,9 +2176,125 @@ static void max98095_handle_pdata(struct snd_soc_codec *codec)
max98095_handle_bq_pdata(codec);
}
+static irqreturn_t max98095_report_jack(int irq, void *data)
+{
+ struct snd_soc_codec *codec = data;
+ struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
+ unsigned int value;
+ int hp_report = 0;
+ int mic_report = 0;
+
+ /* Read the Jack Status Register */
+ value = snd_soc_read(codec, M98095_007_JACK_AUTO_STS);
+
+ /* If ddone is not set, then detection isn't finished yet */
+ if ((value & M98095_DDONE) == 0)
+ return IRQ_NONE;
+
+ /* if hp, check its bit, and if set, clear it */
+ if ((value & M98095_HP_IN || value & M98095_LO_IN) &&
+ max98095->headphone_jack)
+ hp_report |= SND_JACK_HEADPHONE;
+
+ /* if mic, check its bit, and if set, clear it */
+ if ((value & M98095_MIC_IN) && max98095->mic_jack)
+ mic_report |= SND_JACK_MICROPHONE;
+
+ if (max98095->headphone_jack == max98095->mic_jack) {
+ snd_soc_jack_report(max98095->headphone_jack,
+ hp_report | mic_report,
+ SND_JACK_HEADSET);
+ } else {
+ if (max98095->headphone_jack)
+ snd_soc_jack_report(max98095->headphone_jack,
+ hp_report, SND_JACK_HEADPHONE);
+ if (max98095->mic_jack)
+ snd_soc_jack_report(max98095->mic_jack,
+ mic_report, SND_JACK_MICROPHONE);
+ }
+
+ return IRQ_HANDLED;
+}
+
+int max98095_jack_detect_enable(struct snd_soc_codec *codec)
+{
+ struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+ int detect_enable = M98095_JDEN;
+ unsigned int slew = M98095_DEFAULT_SLEW_DELAY;
+
+ if (max98095->pdata->jack_detect_pin5en)
+ detect_enable |= M98095_PIN5EN;
+
+ if (max98095->pdata->jack_detect_delay)
+ slew = max98095->pdata->jack_detect_delay;
+
+ ret = snd_soc_write(codec, M98095_08E_JACK_DC_SLEW, slew);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to cfg auto detect %d\n", ret);
+ return ret;
+ }
+
+ /* configure auto detection to be enabled */
+ ret = snd_soc_write(codec, M98095_089_JACK_DET_AUTO, detect_enable);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to cfg auto detect %d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+int max98095_jack_detect_disable(struct snd_soc_codec *codec)
+{
+ int ret = 0;
+
+ /* configure auto detection to be disabled */
+ ret = snd_soc_write(codec, M98095_089_JACK_DET_AUTO, 0x0);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to cfg auto detect %d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+int max98095_jack_detect(struct snd_soc_codec *codec,
+ struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack)
+{
+ struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
+ struct i2c_client *client = to_i2c_client(codec->dev);
+ int ret = 0;
+
+ max98095->headphone_jack = hp_jack;
+ max98095->mic_jack = mic_jack;
+
+ /* only progress if we have at least 1 jack pointer */
+ if (!hp_jack && !mic_jack)
+ return -EINVAL;
+
+ max98095_jack_detect_enable(codec);
+
+ /* enable interrupts for headphone jack detection */
+ ret = snd_soc_update_bits(codec, M98095_013_JACK_INT_EN,
+ M98095_IDDONE, M98095_IDDONE);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to cfg jack irqs %d\n", ret);
+ return ret;
+ }
+
+ max98095_report_jack(client->irq, codec);
+ return 0;
+}
+
#ifdef CONFIG_PM
static int max98095_suspend(struct snd_soc_codec *codec)
{
+ struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
+
+ if (max98095->headphone_jack || max98095->mic_jack)
+ max98095_jack_detect_disable(codec);
+
max98095_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -2183,8 +2302,16 @@ static int max98095_suspend(struct snd_soc_codec *codec)
static int max98095_resume(struct snd_soc_codec *codec)
{
+ struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
+ struct i2c_client *client = to_i2c_client(codec->dev);
+
max98095_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ if (max98095->headphone_jack || max98095->mic_jack) {
+ max98095_jack_detect_enable(codec);
+ max98095_report_jack(client->irq, codec);
+ }
+
return 0;
}
#else
@@ -2227,6 +2354,7 @@ static int max98095_probe(struct snd_soc_codec *codec)
{
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
struct max98095_cdata *cdata;
+ struct i2c_client *client;
int ret = 0;
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
@@ -2238,6 +2366,8 @@ static int max98095_probe(struct snd_soc_codec *codec)
/* reset the codec, the DSP core, and disable all interrupts */
max98095_reset(codec);
+ client = to_i2c_client(codec->dev);
+
/* initialize private data */
max98095->sysclk = (unsigned)-1;
@@ -2266,11 +2396,23 @@ static int max98095_probe(struct snd_soc_codec *codec)
max98095->mic1pre = 0;
max98095->mic2pre = 0;
+ if (client->irq) {
+ /* register an audio interrupt */
+ ret = request_threaded_irq(client->irq, NULL,
+ max98095_report_jack,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ "max98095", codec);
+ if (ret) {
+ dev_err(codec->dev, "Failed to request IRQ: %d\n", ret);
+ goto err_access;
+ }
+ }
+
ret = snd_soc_read(codec, M98095_0FF_REV_ID);
if (ret < 0) {
dev_err(codec->dev, "Failure reading hardware revision: %d\n",
ret);
- goto err_access;
+ goto err_irq;
}
dev_info(codec->dev, "Hardware revision: %c\n", ret - 0x40 + 'A');
@@ -2306,14 +2448,28 @@ static int max98095_probe(struct snd_soc_codec *codec)
max98095_add_widgets(codec);
+ return 0;
+
+err_irq:
+ if (client->irq)
+ free_irq(client->irq, codec);
err_access:
return ret;
}
static int max98095_remove(struct snd_soc_codec *codec)
{
+ struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
+ struct i2c_client *client = to_i2c_client(codec->dev);
+
max98095_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ if (max98095->headphone_jack || max98095->mic_jack)
+ max98095_jack_detect_disable(codec);
+
+ if (client->irq)
+ free_irq(client->irq, codec);
+
return 0;
}
diff --git a/sound/soc/codecs/max98095.h b/sound/soc/codecs/max98095.h
index 891584a0eb03..2ebbe4e894bf 100644
--- a/sound/soc/codecs/max98095.h
+++ b/sound/soc/codecs/max98095.h
@@ -175,11 +175,23 @@
/* MAX98095 Registers Bit Fields */
+/* M98095_007_JACK_AUTO_STS */
+ #define M98095_MIC_IN (1<<3)
+ #define M98095_LO_IN (1<<5)
+ #define M98095_HP_IN (1<<6)
+ #define M98095_DDONE (1<<7)
+
/* M98095_00F_HOST_CFG */
#define M98095_SEG (1<<0)
#define M98095_XTEN (1<<1)
#define M98095_MDLLEN (1<<2)
+/* M98095_013_JACK_INT_EN */
+ #define M98095_IMIC_IN (1<<3)
+ #define M98095_ILO_IN (1<<5)
+ #define M98095_IHP_IN (1<<6)
+ #define M98095_IDDONE (1<<7)
+
/* M98095_027_DAI1_CLKMODE, M98095_031_DAI2_CLKMODE, M98095_03B_DAI3_CLKMODE */
#define M98095_CLKMODE_MASK 0xFF
@@ -255,6 +267,10 @@
#define M98095_EQ2EN (1<<1)
#define M98095_EQ1EN (1<<0)
+/* M98095_089_JACK_DET_AUTO */
+ #define M98095_PIN5EN (1<<2)
+ #define M98095_JDEN (1<<7)
+
/* M98095_090_PWR_EN_IN */
#define M98095_INEN (1<<7)
#define M98095_MB2EN (1<<3)
@@ -296,4 +312,10 @@
#define M98095_174_DAI1_BQ_BASE 0x74
#define M98095_17E_DAI2_BQ_BASE 0x7E
+/* Default Delay used in Slew Rate Calculation for Jack detection */
+#define M98095_DEFAULT_SLEW_DELAY 0x18
+
+extern int max98095_jack_detect(struct snd_soc_codec *codec,
+ struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack);
+
#endif
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
new file mode 100644
index 000000000000..6276e352125f
--- /dev/null
+++ b/sound/soc/codecs/mc13783.c
@@ -0,0 +1,786 @@
+/*
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ * Copyright 2009 Sascha Hauer, s.hauer@pengutronix.de
+ * Copyright 2012 Philippe Retornaz, philippe.retornaz@epfl.ch
+ *
+ * Initial development of this code was funded by
+ * Phytec Messtechnik GmbH, http://www.phytec.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/mfd/mc13xxx.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/soc-dapm.h>
+
+#include "mc13783.h"
+
+#define MC13783_AUDIO_RX0 36
+#define MC13783_AUDIO_RX1 37
+#define MC13783_AUDIO_TX 38
+#define MC13783_SSI_NETWORK 39
+#define MC13783_AUDIO_CODEC 40
+#define MC13783_AUDIO_DAC 41
+
+#define AUDIO_RX0_ALSPEN (1 << 5)
+#define AUDIO_RX0_ALSPSEL (1 << 7)
+#define AUDIO_RX0_ADDCDC (1 << 21)
+#define AUDIO_RX0_ADDSTDC (1 << 22)
+#define AUDIO_RX0_ADDRXIN (1 << 23)
+
+#define AUDIO_RX1_PGARXEN (1 << 0);
+#define AUDIO_RX1_PGASTEN (1 << 5)
+#define AUDIO_RX1_ARXINEN (1 << 10)
+
+#define AUDIO_TX_AMC1REN (1 << 5)
+#define AUDIO_TX_AMC1LEN (1 << 7)
+#define AUDIO_TX_AMC2EN (1 << 9)
+#define AUDIO_TX_ATXINEN (1 << 11)
+#define AUDIO_TX_RXINREC (1 << 13)
+
+#define SSI_NETWORK_CDCTXRXSLOT(x) (((x) & 0x3) << 2)
+#define SSI_NETWORK_CDCTXSECSLOT(x) (((x) & 0x3) << 4)
+#define SSI_NETWORK_CDCRXSECSLOT(x) (((x) & 0x3) << 6)
+#define SSI_NETWORK_CDCRXSECGAIN(x) (((x) & 0x3) << 8)
+#define SSI_NETWORK_CDCSUMGAIN(x) (1 << 10)
+#define SSI_NETWORK_CDCFSDLY(x) (1 << 11)
+#define SSI_NETWORK_DAC_SLOTS_8 (1 << 12)
+#define SSI_NETWORK_DAC_SLOTS_4 (2 << 12)
+#define SSI_NETWORK_DAC_SLOTS_2 (3 << 12)
+#define SSI_NETWORK_DAC_SLOT_MASK (3 << 12)
+#define SSI_NETWORK_DAC_RXSLOT_0_1 (0 << 14)
+#define SSI_NETWORK_DAC_RXSLOT_2_3 (1 << 14)
+#define SSI_NETWORK_DAC_RXSLOT_4_5 (2 << 14)
+#define SSI_NETWORK_DAC_RXSLOT_6_7 (3 << 14)
+#define SSI_NETWORK_DAC_RXSLOT_MASK (3 << 14)
+#define SSI_NETWORK_STDCRXSECSLOT(x) (((x) & 0x3) << 16)
+#define SSI_NETWORK_STDCRXSECGAIN(x) (((x) & 0x3) << 18)
+#define SSI_NETWORK_STDCSUMGAIN (1 << 20)
+
+/*
+ * MC13783_AUDIO_CODEC and MC13783_AUDIO_DAC mostly share the same
+ * register layout
+ */
+#define AUDIO_SSI_SEL (1 << 0)
+#define AUDIO_CLK_SEL (1 << 1)
+#define AUDIO_CSM (1 << 2)
+#define AUDIO_BCL_INV (1 << 3)
+#define AUDIO_CFS_INV (1 << 4)
+#define AUDIO_CFS(x) (((x) & 0x3) << 5)
+#define AUDIO_CLK(x) (((x) & 0x7) << 7)
+#define AUDIO_C_EN (1 << 11)
+#define AUDIO_C_CLK_EN (1 << 12)
+#define AUDIO_C_RESET (1 << 15)
+
+#define AUDIO_CODEC_CDCFS8K16K (1 << 10)
+#define AUDIO_DAC_CFS_DLY_B (1 << 10)
+
+struct mc13783_priv {
+ struct snd_soc_codec codec;
+ struct mc13xxx *mc13xxx;
+
+ enum mc13783_ssi_port adc_ssi_port;
+ enum mc13783_ssi_port dac_ssi_port;
+};
+
+static unsigned int mc13783_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
+ unsigned int value = 0;
+
+ mc13xxx_lock(priv->mc13xxx);
+
+ mc13xxx_reg_read(priv->mc13xxx, reg, &value);
+
+ mc13xxx_unlock(priv->mc13xxx);
+
+ return value;
+}
+
+static int mc13783_write(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int value)
+{
+ struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ mc13xxx_lock(priv->mc13xxx);
+
+ ret = mc13xxx_reg_write(priv->mc13xxx, reg, value);
+
+ mc13xxx_unlock(priv->mc13xxx);
+
+ return ret;
+}
+
+/* Mapping between sample rates and register value */
+static unsigned int mc13783_rates[] = {
+ 8000, 11025, 12000, 16000,
+ 22050, 24000, 32000, 44100,
+ 48000, 64000, 96000
+};
+
+static int mc13783_pcm_hw_params_dac(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ unsigned int rate = params_rate(params);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mc13783_rates); i++) {
+ if (rate == mc13783_rates[i]) {
+ snd_soc_update_bits(codec, MC13783_AUDIO_DAC,
+ 0xf << 17, i << 17);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int mc13783_pcm_hw_params_codec(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ unsigned int rate = params_rate(params);
+ unsigned int val;
+
+ switch (rate) {
+ case 8000:
+ val = 0;
+ break;
+ case 16000:
+ val = AUDIO_CODEC_CDCFS8K16K;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, MC13783_AUDIO_CODEC, AUDIO_CODEC_CDCFS8K16K,
+ val);
+
+ return 0;
+}
+
+static int mc13783_pcm_hw_params_sync(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return mc13783_pcm_hw_params_dac(substream, params, dai);
+ else
+ return mc13783_pcm_hw_params_codec(substream, params, dai);
+}
+
+static int mc13783_set_fmt(struct snd_soc_dai *dai, unsigned int fmt,
+ unsigned int reg)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int val = 0;
+ unsigned int mask = AUDIO_CFS(3) | AUDIO_BCL_INV | AUDIO_CFS_INV |
+ AUDIO_CSM | AUDIO_C_CLK_EN | AUDIO_C_RESET;
+
+
+ /* DAI mode */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ val |= AUDIO_CFS(2);
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ val |= AUDIO_CFS(1);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* DAI clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ val |= AUDIO_BCL_INV;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ val |= AUDIO_BCL_INV | AUDIO_CFS_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ val |= AUDIO_CFS_INV;
+ break;
+ }
+
+ /* DAI clock master masks */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ val |= AUDIO_C_CLK_EN;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ val |= AUDIO_CSM;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ case SND_SOC_DAIFMT_CBS_CFM:
+ return -EINVAL;
+ }
+
+ val |= AUDIO_C_RESET;
+
+ snd_soc_update_bits(codec, reg, mask, val);
+
+ return 0;
+}
+
+static int mc13783_set_fmt_async(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ if (dai->id == MC13783_ID_STEREO_DAC)
+ return mc13783_set_fmt(dai, fmt, MC13783_AUDIO_DAC);
+ else
+ return mc13783_set_fmt(dai, fmt, MC13783_AUDIO_CODEC);
+}
+
+static int mc13783_set_fmt_sync(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ int ret;
+
+ ret = mc13783_set_fmt(dai, fmt, MC13783_AUDIO_DAC);
+ if (ret)
+ return ret;
+
+ /*
+ * In synchronous mode force the voice codec into slave mode
+ * so that the clock / framesync from the stereo DAC is used
+ */
+ fmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
+ fmt |= SND_SOC_DAIFMT_CBS_CFS;
+ ret = mc13783_set_fmt(dai, fmt, MC13783_AUDIO_CODEC);
+
+ return ret;
+}
+
+static int mc13783_sysclk[] = {
+ 13000000,
+ 15360000,
+ 16800000,
+ -1,
+ 26000000,
+ -1, /* 12000000, invalid for voice codec */
+ -1, /* 3686400, invalid for voice codec */
+ 33600000,
+};
+
+static int mc13783_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir,
+ unsigned int reg)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int clk;
+ unsigned int val = 0;
+ unsigned int mask = AUDIO_CLK(0x7) | AUDIO_CLK_SEL;
+
+ for (clk = 0; clk < ARRAY_SIZE(mc13783_sysclk); clk++) {
+ if (mc13783_sysclk[clk] < 0)
+ continue;
+ if (mc13783_sysclk[clk] == freq)
+ break;
+ }
+
+ if (clk == ARRAY_SIZE(mc13783_sysclk))
+ return -EINVAL;
+
+ if (clk_id == MC13783_CLK_CLIB)
+ val |= AUDIO_CLK_SEL;
+
+ val |= AUDIO_CLK(clk);
+
+ snd_soc_update_bits(codec, reg, mask, val);
+
+ return 0;
+}
+
+static int mc13783_set_sysclk_dac(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ return mc13783_set_sysclk(dai, clk_id, freq, dir, MC13783_AUDIO_DAC);
+}
+
+static int mc13783_set_sysclk_codec(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ return mc13783_set_sysclk(dai, clk_id, freq, dir, MC13783_AUDIO_CODEC);
+}
+
+static int mc13783_set_sysclk_sync(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ int ret;
+
+ ret = mc13783_set_sysclk(dai, clk_id, freq, dir, MC13783_AUDIO_DAC);
+ if (ret)
+ return ret;
+
+ return mc13783_set_sysclk(dai, clk_id, freq, dir, MC13783_AUDIO_CODEC);
+}
+
+static int mc13783_set_tdm_slot_dac(struct snd_soc_dai *dai,
+ unsigned int tx_mask, unsigned int rx_mask, int slots,
+ int slot_width)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int val = 0;
+ unsigned int mask = SSI_NETWORK_DAC_SLOT_MASK |
+ SSI_NETWORK_DAC_RXSLOT_MASK;
+
+ switch (slots) {
+ case 2:
+ val |= SSI_NETWORK_DAC_SLOTS_2;
+ break;
+ case 4:
+ val |= SSI_NETWORK_DAC_SLOTS_4;
+ break;
+ case 8:
+ val |= SSI_NETWORK_DAC_SLOTS_8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (rx_mask) {
+ case 0xfffffffc:
+ val |= SSI_NETWORK_DAC_RXSLOT_0_1;
+ break;
+ case 0xfffffff3:
+ val |= SSI_NETWORK_DAC_RXSLOT_2_3;
+ break;
+ case 0xffffffcf:
+ val |= SSI_NETWORK_DAC_RXSLOT_4_5;
+ break;
+ case 0xffffff3f:
+ val |= SSI_NETWORK_DAC_RXSLOT_6_7;
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ snd_soc_update_bits(codec, MC13783_SSI_NETWORK, mask, val);
+
+ return 0;
+}
+
+static int mc13783_set_tdm_slot_codec(struct snd_soc_dai *dai,
+ unsigned int tx_mask, unsigned int rx_mask, int slots,
+ int slot_width)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int val = 0;
+ unsigned int mask = 0x3f;
+
+ if (slots != 4)
+ return -EINVAL;
+
+ if (tx_mask != 0xfffffffc)
+ return -EINVAL;
+
+ val |= (0x00 << 2); /* primary timeslot RX/TX(?) is 0 */
+ val |= (0x01 << 4); /* secondary timeslot TX is 1 */
+
+ snd_soc_update_bits(codec, MC13783_SSI_NETWORK, mask, val);
+
+ return 0;
+}
+
+static int mc13783_set_tdm_slot_sync(struct snd_soc_dai *dai,
+ unsigned int tx_mask, unsigned int rx_mask, int slots,
+ int slot_width)
+{
+ int ret;
+
+ ret = mc13783_set_tdm_slot_dac(dai, tx_mask, rx_mask, slots,
+ slot_width);
+ if (ret)
+ return ret;
+
+ ret = mc13783_set_tdm_slot_codec(dai, tx_mask, rx_mask, slots,
+ slot_width);
+
+ return ret;
+}
+
+static const struct snd_kcontrol_new mc1l_amp_ctl =
+ SOC_DAPM_SINGLE("Switch", 38, 7, 1, 0);
+
+static const struct snd_kcontrol_new mc1r_amp_ctl =
+ SOC_DAPM_SINGLE("Switch", 38, 5, 1, 0);
+
+static const struct snd_kcontrol_new mc2_amp_ctl =
+ SOC_DAPM_SINGLE("Switch", 38, 9, 1, 0);
+
+static const struct snd_kcontrol_new atx_amp_ctl =
+ SOC_DAPM_SINGLE("Switch", 38, 11, 1, 0);
+
+
+/* Virtual mux. The chip does the input selection automatically
+ * as soon as we enable one input. */
+static const char * const adcl_enum_text[] = {
+ "MC1L", "RXINL",
+};
+
+static const struct soc_enum adcl_enum =
+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcl_enum_text), adcl_enum_text);
+
+static const struct snd_kcontrol_new left_input_mux =
+ SOC_DAPM_ENUM_VIRT("Route", adcl_enum);
+
+static const char * const adcr_enum_text[] = {
+ "MC1R", "MC2", "RXINR", "TXIN",
+};
+
+static const struct soc_enum adcr_enum =
+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcr_enum_text), adcr_enum_text);
+
+static const struct snd_kcontrol_new right_input_mux =
+ SOC_DAPM_ENUM_VIRT("Route", adcr_enum);
+
+static const struct snd_kcontrol_new samp_ctl =
+ SOC_DAPM_SINGLE("Switch", 36, 3, 1, 0);
+
+static const struct snd_kcontrol_new lamp_ctl =
+ SOC_DAPM_SINGLE("Switch", 36, 5, 1, 0);
+
+static const struct snd_kcontrol_new hlamp_ctl =
+ SOC_DAPM_SINGLE("Switch", 36, 10, 1, 0);
+
+static const struct snd_kcontrol_new hramp_ctl =
+ SOC_DAPM_SINGLE("Switch", 36, 9, 1, 0);
+
+static const struct snd_kcontrol_new llamp_ctl =
+ SOC_DAPM_SINGLE("Switch", 36, 16, 1, 0);
+
+static const struct snd_kcontrol_new lramp_ctl =
+ SOC_DAPM_SINGLE("Switch", 36, 15, 1, 0);
+
+static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = {
+/* Input */
+ SND_SOC_DAPM_INPUT("MC1LIN"),
+ SND_SOC_DAPM_INPUT("MC1RIN"),
+ SND_SOC_DAPM_INPUT("MC2IN"),
+ SND_SOC_DAPM_INPUT("RXINR"),
+ SND_SOC_DAPM_INPUT("RXINL"),
+ SND_SOC_DAPM_INPUT("TXIN"),
+
+ SND_SOC_DAPM_SUPPLY("MC1 Bias", 38, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("MC2 Bias", 38, 1, 0, NULL, 0),
+
+ SND_SOC_DAPM_SWITCH("MC1L Amp", 38, 7, 0, &mc1l_amp_ctl),
+ SND_SOC_DAPM_SWITCH("MC1R Amp", 38, 5, 0, &mc1r_amp_ctl),
+ SND_SOC_DAPM_SWITCH("MC2 Amp", 38, 9, 0, &mc2_amp_ctl),
+ SND_SOC_DAPM_SWITCH("TXIN Amp", 38, 11, 0, &atx_amp_ctl),
+
+ SND_SOC_DAPM_VIRT_MUX("PGA Left Input Mux", SND_SOC_NOPM, 0, 0,
+ &left_input_mux),
+ SND_SOC_DAPM_VIRT_MUX("PGA Right Input Mux", SND_SOC_NOPM, 0, 0,
+ &right_input_mux),
+
+ SND_SOC_DAPM_PGA("PGA Left Input", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("PGA Right Input", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_ADC("ADC", "Capture", 40, 11, 0),
+ SND_SOC_DAPM_SUPPLY("ADC_Reset", 40, 15, 0, NULL, 0),
+
+/* Output */
+ SND_SOC_DAPM_SUPPLY("DAC_E", 41, 11, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DAC_Reset", 41, 15, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("RXOUTL"),
+ SND_SOC_DAPM_OUTPUT("RXOUTR"),
+ SND_SOC_DAPM_OUTPUT("HSL"),
+ SND_SOC_DAPM_OUTPUT("HSR"),
+ SND_SOC_DAPM_OUTPUT("LSP"),
+ SND_SOC_DAPM_OUTPUT("SP"),
+
+ SND_SOC_DAPM_SWITCH("Speaker Amp", 36, 3, 0, &samp_ctl),
+ SND_SOC_DAPM_SWITCH("Loudspeaker Amp", SND_SOC_NOPM, 0, 0, &lamp_ctl),
+ SND_SOC_DAPM_SWITCH("Headset Amp Left", 36, 10, 0, &hlamp_ctl),
+ SND_SOC_DAPM_SWITCH("Headset Amp Right", 36, 9, 0, &hramp_ctl),
+ SND_SOC_DAPM_SWITCH("Line out Amp Left", 36, 16, 0, &llamp_ctl),
+ SND_SOC_DAPM_SWITCH("Line out Amp Right", 36, 15, 0, &lramp_ctl),
+ SND_SOC_DAPM_DAC("DAC", "Playback", 36, 22, 0),
+ SND_SOC_DAPM_PGA("DAC PGA", 37, 5, 0, NULL, 0),
+};
+
+static struct snd_soc_dapm_route mc13783_routes[] = {
+/* Input */
+ { "MC1L Amp", NULL, "MC1LIN"},
+ { "MC1R Amp", NULL, "MC1RIN" },
+ { "MC2 Amp", NULL, "MC2IN" },
+ { "TXIN Amp", NULL, "TXIN"},
+
+ { "PGA Left Input Mux", "MC1L", "MC1L Amp" },
+ { "PGA Left Input Mux", "RXINL", "RXINL"},
+ { "PGA Right Input Mux", "MC1R", "MC1R Amp" },
+ { "PGA Right Input Mux", "MC2", "MC2 Amp"},
+ { "PGA Right Input Mux", "TXIN", "TXIN Amp"},
+ { "PGA Right Input Mux", "RXINR", "RXINR"},
+
+ { "PGA Left Input", NULL, "PGA Left Input Mux"},
+ { "PGA Right Input", NULL, "PGA Right Input Mux"},
+
+ { "ADC", NULL, "PGA Left Input"},
+ { "ADC", NULL, "PGA Right Input"},
+ { "ADC", NULL, "ADC_Reset"},
+
+/* Output */
+ { "HSL", NULL, "Headset Amp Left" },
+ { "HSR", NULL, "Headset Amp Right"},
+ { "RXOUTL", NULL, "Line out Amp Left"},
+ { "RXOUTR", NULL, "Line out Amp Right"},
+ { "SP", NULL, "Speaker Amp"},
+ { "Speaker Amp", NULL, "DAC PGA"},
+ { "LSP", NULL, "DAC PGA"},
+ { "Headset Amp Left", NULL, "DAC PGA"},
+ { "Headset Amp Right", NULL, "DAC PGA"},
+ { "Line out Amp Left", NULL, "DAC PGA"},
+ { "Line out Amp Right", NULL, "DAC PGA"},
+ { "DAC PGA", NULL, "DAC"},
+ { "DAC", NULL, "DAC_E"},
+};
+
+static const char * const mc13783_3d_mixer[] = {"Stereo", "Phase Mix",
+ "Mono", "Mono Mix"};
+
+static const struct soc_enum mc13783_enum_3d_mixer =
+ SOC_ENUM_SINGLE(MC13783_AUDIO_RX1, 16, ARRAY_SIZE(mc13783_3d_mixer),
+ mc13783_3d_mixer);
+
+static struct snd_kcontrol_new mc13783_control_list[] = {
+ SOC_SINGLE("Loudspeaker enable", MC13783_AUDIO_RX0, 5, 1, 0),
+ SOC_SINGLE("PCM Playback Volume", MC13783_AUDIO_RX1, 6, 15, 0),
+ SOC_DOUBLE("PCM Capture Volume", MC13783_AUDIO_TX, 19, 14, 31, 0),
+ SOC_ENUM("3D Control", mc13783_enum_3d_mixer),
+};
+
+static int mc13783_probe(struct snd_soc_codec *codec)
+{
+ struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ mc13xxx_lock(priv->mc13xxx);
+
+ /* these are the reset values */
+ mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_RX0, 0x25893);
+ mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_RX1, 0x00d35A);
+ mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_TX, 0x420000);
+ mc13xxx_reg_write(priv->mc13xxx, MC13783_SSI_NETWORK, 0x013060);
+ mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_CODEC, 0x180027);
+ mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_DAC, 0x0e0004);
+
+ if (priv->adc_ssi_port == MC13783_SSI1_PORT)
+ mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_CODEC,
+ AUDIO_SSI_SEL, 0);
+ else
+ mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_CODEC,
+ 0, AUDIO_SSI_SEL);
+
+ if (priv->dac_ssi_port == MC13783_SSI1_PORT)
+ mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC,
+ AUDIO_SSI_SEL, 0);
+ else
+ mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC,
+ 0, AUDIO_SSI_SEL);
+
+ mc13xxx_unlock(priv->mc13xxx);
+
+ return 0;
+}
+
+static int mc13783_remove(struct snd_soc_codec *codec)
+{
+ struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ mc13xxx_lock(priv->mc13xxx);
+
+ /* Make sure VAUDIOON is off */
+ mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_RX0, 0x3, 0);
+
+ mc13xxx_unlock(priv->mc13xxx);
+
+ return 0;
+}
+
+#define MC13783_RATES_RECORD (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
+
+#define MC13783_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops mc13783_ops_dac = {
+ .hw_params = mc13783_pcm_hw_params_dac,
+ .set_fmt = mc13783_set_fmt_async,
+ .set_sysclk = mc13783_set_sysclk_dac,
+ .set_tdm_slot = mc13783_set_tdm_slot_dac,
+};
+
+static struct snd_soc_dai_ops mc13783_ops_codec = {
+ .hw_params = mc13783_pcm_hw_params_codec,
+ .set_fmt = mc13783_set_fmt_async,
+ .set_sysclk = mc13783_set_sysclk_codec,
+ .set_tdm_slot = mc13783_set_tdm_slot_codec,
+};
+
+/*
+ * The mc13783 has two SSI ports, both of them can be routed either
+ * to the voice codec or the stereo DAC. When two different SSI ports
+ * are used for the voice codec and the stereo DAC we can do different
+ * formats and sysclock settings for playback and capture
+ * (mc13783-hifi-playback and mc13783-hifi-capture). Using the same port
+ * forces us to use symmetric rates (mc13783-hifi).
+ */
+static struct snd_soc_dai_driver mc13783_dai_async[] = {
+ {
+ .name = "mc13783-hifi-playback",
+ .id = MC13783_ID_STEREO_DAC,
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = MC13783_FORMATS,
+ },
+ .ops = &mc13783_ops_dac,
+ }, {
+ .name = "mc13783-hifi-capture",
+ .id = MC13783_ID_STEREO_CODEC,
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MC13783_RATES_RECORD,
+ .formats = MC13783_FORMATS,
+ },
+ .ops = &mc13783_ops_codec,
+ },
+};
+
+static struct snd_soc_dai_ops mc13783_ops_sync = {
+ .hw_params = mc13783_pcm_hw_params_sync,
+ .set_fmt = mc13783_set_fmt_sync,
+ .set_sysclk = mc13783_set_sysclk_sync,
+ .set_tdm_slot = mc13783_set_tdm_slot_sync,
+};
+
+static struct snd_soc_dai_driver mc13783_dai_sync[] = {
+ {
+ .name = "mc13783-hifi",
+ .id = MC13783_ID_SYNC,
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = MC13783_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MC13783_RATES_RECORD,
+ .formats = MC13783_FORMATS,
+ },
+ .ops = &mc13783_ops_sync,
+ .symmetric_rates = 1,
+ }
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_mc13783 = {
+ .probe = mc13783_probe,
+ .remove = mc13783_remove,
+ .read = mc13783_read,
+ .write = mc13783_write,
+ .controls = mc13783_control_list,
+ .num_controls = ARRAY_SIZE(mc13783_control_list),
+ .dapm_widgets = mc13783_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(mc13783_dapm_widgets),
+ .dapm_routes = mc13783_routes,
+ .num_dapm_routes = ARRAY_SIZE(mc13783_routes),
+};
+
+static int mc13783_codec_probe(struct platform_device *pdev)
+{
+ struct mc13xxx *mc13xxx;
+ struct mc13783_priv *priv;
+ struct mc13xxx_codec_platform_data *pdata = pdev->dev.platform_data;
+ int ret;
+
+ mc13xxx = dev_get_drvdata(pdev->dev.parent);
+
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+
+ dev_set_drvdata(&pdev->dev, priv);
+ priv->mc13xxx = mc13xxx;
+ if (pdata) {
+ priv->adc_ssi_port = pdata->adc_ssi_port;
+ priv->dac_ssi_port = pdata->dac_ssi_port;
+ } else {
+ priv->adc_ssi_port = MC13783_SSI1_PORT;
+ priv->dac_ssi_port = MC13783_SSI2_PORT;
+ }
+
+ if (priv->adc_ssi_port == priv->dac_ssi_port)
+ ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783,
+ mc13783_dai_sync, ARRAY_SIZE(mc13783_dai_sync));
+ else
+ ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783,
+ mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async));
+
+ if (ret)
+ goto err_register_codec;
+
+ return 0;
+
+err_register_codec:
+ dev_err(&pdev->dev, "register codec failed with %d\n", ret);
+
+ return ret;
+}
+
+static int mc13783_codec_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+
+ return 0;
+}
+
+static struct platform_driver mc13783_codec_driver = {
+ .driver = {
+ .name = "mc13783-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = mc13783_codec_probe,
+ .remove = __devexit_p(mc13783_codec_remove),
+};
+
+module_platform_driver(mc13783_codec_driver);
+
+MODULE_DESCRIPTION("ASoC MC13783 driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>");
+MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/mc13783.h b/sound/soc/codecs/mc13783.h
new file mode 100644
index 000000000000..3a6d1993a217
--- /dev/null
+++ b/sound/soc/codecs/mc13783.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef MC13783_MIXER_H
+#define MC13783_MIXER_H
+
+#define MC13783_CLK_CLIA 1
+#define MC13783_CLK_CLIB 2
+
+#define MC13783_ID_STEREO_DAC 1
+#define MC13783_ID_STEREO_CODEC 2
+#define MC13783_ID_SYNC 3
+
+#endif /* MC13783_MIXER_H */
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
new file mode 100644
index 000000000000..22cb5bf59273
--- /dev/null
+++ b/sound/soc/codecs/ml26124.c
@@ -0,0 +1,681 @@
+/*
+ * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include "ml26124.h"
+
+#define DVOL_CTL_DVMUTE_ON BIT(4) /* Digital volume MUTE On */
+#define DVOL_CTL_DVMUTE_OFF 0 /* Digital volume MUTE Off */
+#define ML26124_SAI_NO_DELAY BIT(1)
+#define ML26124_SAI_FRAME_SYNC (BIT(5) | BIT(0)) /* For mono (Telecodec) */
+#define ML26134_CACHESIZE 212
+#define ML26124_VMID BIT(1)
+#define ML26124_RATES (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 |\
+ SNDRV_PCM_RATE_48000)
+#define ML26124_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S32_LE)
+#define ML26124_NUM_REGISTER ML26134_CACHESIZE
+
+struct ml26124_priv {
+ u32 mclk;
+ u32 rate;
+ struct regmap *regmap;
+ int clk_in;
+ struct snd_pcm_substream *substream;
+};
+
+struct clk_coeff {
+ u32 mclk;
+ u32 rate;
+ u8 pllnl;
+ u8 pllnh;
+ u8 pllml;
+ u8 pllmh;
+ u8 plldiv;
+};
+
+/* ML26124 configuration */
+static const DECLARE_TLV_DB_SCALE(digital_tlv, -7150, 50, 0);
+
+static const DECLARE_TLV_DB_SCALE(alclvl, -2250, 150, 0);
+static const DECLARE_TLV_DB_SCALE(mingain, -1200, 600, 0);
+static const DECLARE_TLV_DB_SCALE(maxgain, -675, 600, 0);
+static const DECLARE_TLV_DB_SCALE(boost_vol, -1200, 75, 0);
+static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0);
+
+static const char * const ml26124_companding[] = {"16bit PCM", "u-law",
+ "A-law"};
+
+static const struct soc_enum ml26124_adc_companding_enum
+ = SOC_ENUM_SINGLE(ML26124_SAI_TRANS_CTL, 6, 3, ml26124_companding);
+
+static const struct soc_enum ml26124_dac_companding_enum
+ = SOC_ENUM_SINGLE(ML26124_SAI_RCV_CTL, 6, 3, ml26124_companding);
+
+static const struct snd_kcontrol_new ml26124_snd_controls[] = {
+ SOC_SINGLE_TLV("Capture Digital Volume", ML26124_RECORD_DIG_VOL, 0,
+ 0xff, 1, digital_tlv),
+ SOC_SINGLE_TLV("Playback Digital Volume", ML26124_PLBAK_DIG_VOL, 0,
+ 0xff, 1, digital_tlv),
+ SOC_SINGLE_TLV("Digital Boost Volume", ML26124_DIGI_BOOST_VOL, 0,
+ 0x3f, 0, boost_vol),
+ SOC_SINGLE_TLV("EQ Band0 Volume", ML26124_EQ_GAIN_BRAND0, 0,
+ 0xff, 1, digital_tlv),
+ SOC_SINGLE_TLV("EQ Band1 Volume", ML26124_EQ_GAIN_BRAND1, 0,
+ 0xff, 1, digital_tlv),
+ SOC_SINGLE_TLV("EQ Band2 Volume", ML26124_EQ_GAIN_BRAND2, 0,
+ 0xff, 1, digital_tlv),
+ SOC_SINGLE_TLV("EQ Band3 Volume", ML26124_EQ_GAIN_BRAND3, 0,
+ 0xff, 1, digital_tlv),
+ SOC_SINGLE_TLV("EQ Band4 Volume", ML26124_EQ_GAIN_BRAND4, 0,
+ 0xff, 1, digital_tlv),
+ SOC_SINGLE_TLV("ALC Target Level", ML26124_ALC_TARGET_LEV, 0,
+ 0xf, 1, alclvl),
+ SOC_SINGLE_TLV("ALC Min Input Volume", ML26124_ALC_MAXMIN_GAIN, 0,
+ 7, 0, mingain),
+ SOC_SINGLE_TLV("ALC Max Input Volume", ML26124_ALC_MAXMIN_GAIN, 4,
+ 7, 1, maxgain),
+ SOC_SINGLE_TLV("Playback Limiter Min Input Volume",
+ ML26124_PL_MAXMIN_GAIN, 0, 7, 0, mingain),
+ SOC_SINGLE_TLV("Playback Limiter Max Input Volume",
+ ML26124_PL_MAXMIN_GAIN, 4, 7, 1, maxgain),
+ SOC_SINGLE_TLV("Playback Boost Volume", ML26124_PLYBAK_BOST_VOL, 0,
+ 0x3f, 0, boost_vol),
+ SOC_SINGLE("DC High Pass Filter Switch", ML26124_FILTER_EN, 0, 1, 0),
+ SOC_SINGLE("Noise High Pass Filter Switch", ML26124_FILTER_EN, 1, 1, 0),
+ SOC_SINGLE("ZC Switch", ML26124_PW_ZCCMP_PW_MNG, 1,
+ 1, 0),
+ SOC_SINGLE("EQ Band0 Switch", ML26124_FILTER_EN, 2, 1, 0),
+ SOC_SINGLE("EQ Band1 Switch", ML26124_FILTER_EN, 3, 1, 0),
+ SOC_SINGLE("EQ Band2 Switch", ML26124_FILTER_EN, 4, 1, 0),
+ SOC_SINGLE("EQ Band3 Switch", ML26124_FILTER_EN, 5, 1, 0),
+ SOC_SINGLE("EQ Band4 Switch", ML26124_FILTER_EN, 6, 1, 0),
+ SOC_SINGLE("Play Limiter", ML26124_DVOL_CTL, 0, 1, 0),
+ SOC_SINGLE("Capture Limiter", ML26124_DVOL_CTL, 1, 1, 0),
+ SOC_SINGLE("Digital Volume Fade Switch", ML26124_DVOL_CTL, 3, 1, 0),
+ SOC_SINGLE("Digital Switch", ML26124_DVOL_CTL, 4, 1, 0),
+ SOC_ENUM("DAC Companding", ml26124_dac_companding_enum),
+ SOC_ENUM("ADC Companding", ml26124_adc_companding_enum),
+};
+
+static const struct snd_kcontrol_new ml26124_output_mixer_controls[] = {
+ SOC_DAPM_SINGLE("DAC Switch", ML26124_SPK_AMP_OUT, 1, 1, 0),
+ SOC_DAPM_SINGLE("Line in loopback Switch", ML26124_SPK_AMP_OUT, 3, 1,
+ 0),
+ SOC_DAPM_SINGLE("PGA Switch", ML26124_SPK_AMP_OUT, 5, 1, 0),
+};
+
+/* Input mux */
+static const char * const ml26124_input_select[] = {"Analog MIC SingleEnded in",
+ "Digital MIC in", "Analog MIC Differential in"};
+
+static const struct soc_enum ml26124_insel_enum =
+ SOC_ENUM_SINGLE(ML26124_MIC_IF_CTL, 0, 3, ml26124_input_select);
+
+static const struct snd_kcontrol_new ml26124_input_mux_controls =
+ SOC_DAPM_ENUM("Input Select", ml26124_insel_enum);
+
+static const struct snd_kcontrol_new ml26124_line_control =
+ SOC_DAPM_SINGLE("Switch", ML26124_PW_LOUT_PW_MNG, 1, 1, 0);
+
+static const struct snd_soc_dapm_widget ml26124_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("MCLKEN", ML26124_CLK_EN, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("PLLEN", ML26124_CLK_EN, 1, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("PLLOE", ML26124_CLK_EN, 2, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("MICBIAS", ML26124_PW_REF_PW_MNG, 2, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0,
+ &ml26124_output_mixer_controls[0],
+ ARRAY_SIZE(ml26124_output_mixer_controls)),
+ SND_SOC_DAPM_DAC("DAC", "Playback", ML26124_PW_DAC_PW_MNG, 1, 0),
+ SND_SOC_DAPM_ADC("ADC", "Capture", ML26124_PW_IN_PW_MNG, 1, 0),
+ SND_SOC_DAPM_PGA("PGA", ML26124_PW_IN_PW_MNG, 3, 0, NULL, 0),
+ SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0,
+ &ml26124_input_mux_controls),
+ SND_SOC_DAPM_SWITCH("Line Out Enable", SND_SOC_NOPM, 0, 0,
+ &ml26124_line_control),
+ SND_SOC_DAPM_INPUT("MDIN"),
+ SND_SOC_DAPM_INPUT("MIN"),
+ SND_SOC_DAPM_INPUT("LIN"),
+ SND_SOC_DAPM_OUTPUT("SPOUT"),
+ SND_SOC_DAPM_OUTPUT("LOUT"),
+};
+
+static const struct snd_soc_dapm_route ml26124_intercon[] = {
+ /* Supply */
+ {"DAC", NULL, "MCLKEN"},
+ {"ADC", NULL, "MCLKEN"},
+ {"DAC", NULL, "PLLEN"},
+ {"ADC", NULL, "PLLEN"},
+ {"DAC", NULL, "PLLOE"},
+ {"ADC", NULL, "PLLOE"},
+
+ /* output mixer */
+ {"Output Mixer", "DAC Switch", "DAC"},
+ {"Output Mixer", "Line in loopback Switch", "LIN"},
+
+ /* outputs */
+ {"LOUT", NULL, "Output Mixer"},
+ {"SPOUT", NULL, "Output Mixer"},
+ {"Line Out Enable", NULL, "LOUT"},
+
+ /* input */
+ {"ADC", NULL, "Input Mux"},
+ {"Input Mux", "Analog MIC SingleEnded in", "PGA"},
+ {"Input Mux", "Analog MIC Differential in", "PGA"},
+ {"PGA", NULL, "MIN"},
+};
+
+/* PLLOutputFreq(Hz) = InputMclkFreq(Hz) * PLLM / (PLLN * PLLDIV) */
+static const struct clk_coeff coeff_div[] = {
+ {12288000, 16000, 0xc, 0x0, 0x20, 0x0, 0x4},
+ {12288000, 32000, 0xc, 0x0, 0x20, 0x0, 0x4},
+ {12288000, 48000, 0xc, 0x0, 0x30, 0x0, 0x4},
+};
+
+static struct reg_default ml26124_reg[] = {
+ /* CLOCK control Register */
+ {0x00, 0x00 }, /* Sampling Rate */
+ {0x02, 0x00}, /* PLL NL */
+ {0x04, 0x00}, /* PLLNH */
+ {0x06, 0x00}, /* PLLML */
+ {0x08, 0x00}, /* MLLMH */
+ {0x0a, 0x00}, /* PLLDIV */
+ {0x0c, 0x00}, /* Clock Enable */
+ {0x0e, 0x00}, /* CLK Input/Output Control */
+
+ /* System Control Register */
+ {0x10, 0x00}, /* Software RESET */
+ {0x12, 0x00}, /* Record/Playback Run */
+ {0x14, 0x00}, /* Mic Input/Output control */
+
+ /* Power Management Register */
+ {0x20, 0x00}, /* Reference Power Management */
+ {0x22, 0x00}, /* Input Power Management */
+ {0x24, 0x00}, /* DAC Power Management */
+ {0x26, 0x00}, /* SP-AMP Power Management */
+ {0x28, 0x00}, /* LINEOUT Power Management */
+ {0x2a, 0x00}, /* VIDEO Power Management */
+ {0x2e, 0x00}, /* AC-CMP Power Management */
+
+ /* Analog reference Control Register */
+ {0x30, 0x04}, /* MICBIAS Voltage Control */
+
+ /* Input/Output Amplifier Control Register */
+ {0x32, 0x10}, /* MIC Input Volume */
+ {0x38, 0x00}, /* Mic Boost Volume */
+ {0x3a, 0x33}, /* Speaker AMP Volume */
+ {0x48, 0x00}, /* AMP Volume Control Function Enable */
+ {0x4a, 0x00}, /* Amplifier Volume Fader Control */
+
+ /* Analog Path Control Register */
+ {0x54, 0x00}, /* Speaker AMP Output Control */
+ {0x5a, 0x00}, /* Mic IF Control */
+ {0xe8, 0x01}, /* Mic Select Control */
+
+ /* Audio Interface Control Register */
+ {0x60, 0x00}, /* SAI-Trans Control */
+ {0x62, 0x00}, /* SAI-Receive Control */
+ {0x64, 0x00}, /* SAI Mode select */
+
+ /* DSP Control Register */
+ {0x66, 0x01}, /* Filter Func Enable */
+ {0x68, 0x00}, /* Volume Control Func Enable */
+ {0x6A, 0x00}, /* Mixer & Volume Control*/
+ {0x6C, 0xff}, /* Record Digital Volume */
+ {0x70, 0xff}, /* Playback Digital Volume */
+ {0x72, 0x10}, /* Digital Boost Volume */
+ {0x74, 0xe7}, /* EQ gain Band0 */
+ {0x76, 0xe7}, /* EQ gain Band1 */
+ {0x78, 0xe7}, /* EQ gain Band2 */
+ {0x7A, 0xe7}, /* EQ gain Band3 */
+ {0x7C, 0xe7}, /* EQ gain Band4 */
+ {0x7E, 0x00}, /* HPF2 CutOff*/
+ {0x80, 0x00}, /* EQ Band0 Coef0L */
+ {0x82, 0x00}, /* EQ Band0 Coef0H */
+ {0x84, 0x00}, /* EQ Band0 Coef0L */
+ {0x86, 0x00}, /* EQ Band0 Coef0H */
+ {0x88, 0x00}, /* EQ Band1 Coef0L */
+ {0x8A, 0x00}, /* EQ Band1 Coef0H */
+ {0x8C, 0x00}, /* EQ Band1 Coef0L */
+ {0x8E, 0x00}, /* EQ Band1 Coef0H */
+ {0x90, 0x00}, /* EQ Band2 Coef0L */
+ {0x92, 0x00}, /* EQ Band2 Coef0H */
+ {0x94, 0x00}, /* EQ Band2 Coef0L */
+ {0x96, 0x00}, /* EQ Band2 Coef0H */
+ {0x98, 0x00}, /* EQ Band3 Coef0L */
+ {0x9A, 0x00}, /* EQ Band3 Coef0H */
+ {0x9C, 0x00}, /* EQ Band3 Coef0L */
+ {0x9E, 0x00}, /* EQ Band3 Coef0H */
+ {0xA0, 0x00}, /* EQ Band4 Coef0L */
+ {0xA2, 0x00}, /* EQ Band4 Coef0H */
+ {0xA4, 0x00}, /* EQ Band4 Coef0L */
+ {0xA6, 0x00}, /* EQ Band4 Coef0H */
+
+ /* ALC Control Register */
+ {0xb0, 0x00}, /* ALC Mode */
+ {0xb2, 0x02}, /* ALC Attack Time */
+ {0xb4, 0x03}, /* ALC Decay Time */
+ {0xb6, 0x00}, /* ALC Hold Time */
+ {0xb8, 0x0b}, /* ALC Target Level */
+ {0xba, 0x70}, /* ALC Max/Min Gain */
+ {0xbc, 0x00}, /* Noise Gate Threshold */
+ {0xbe, 0x00}, /* ALC ZeroCross TimeOut */
+
+ /* Playback Limiter Control Register */
+ {0xc0, 0x04}, /* PL Attack Time */
+ {0xc2, 0x05}, /* PL Decay Time */
+ {0xc4, 0x0d}, /* PL Target Level */
+ {0xc6, 0x70}, /* PL Max/Min Gain */
+ {0xc8, 0x10}, /* Playback Boost Volume */
+ {0xca, 0x00}, /* PL ZeroCross TimeOut */
+
+ /* Video Amplifier Control Register */
+ {0xd0, 0x01}, /* VIDEO AMP Gain Control */
+ {0xd2, 0x01}, /* VIDEO AMP Setup 1 */
+ {0xd4, 0x01}, /* VIDEO AMP Control2 */
+};
+
+/* Get sampling rate value of sampling rate setting register (0x0) */
+static inline int get_srate(int rate)
+{
+ int srate;
+
+ switch (rate) {
+ case 16000:
+ srate = 3;
+ break;
+ case 32000:
+ srate = 6;
+ break;
+ case 48000:
+ srate = 8;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return srate;
+}
+
+static inline int get_coeff(int mclk, int rate)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
+ if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
+ return i;
+ }
+ return -EINVAL;
+}
+
+static int ml26124_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
+ int i = get_coeff(priv->mclk, params_rate(hw_params));
+
+ priv->substream = substream;
+ priv->rate = params_rate(hw_params);
+
+ if (priv->clk_in) {
+ switch (priv->mclk / params_rate(hw_params)) {
+ case 256:
+ snd_soc_update_bits(codec, ML26124_CLK_CTL,
+ BIT(0) | BIT(1), 1);
+ break;
+ case 512:
+ snd_soc_update_bits(codec, ML26124_CLK_CTL,
+ BIT(0) | BIT(1), 2);
+ break;
+ case 1024:
+ snd_soc_update_bits(codec, ML26124_CLK_CTL,
+ BIT(0) | BIT(1), 3);
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported MCLKI\n");
+ break;
+ }
+ } else {
+ snd_soc_update_bits(codec, ML26124_CLK_CTL,
+ BIT(0) | BIT(1), 0);
+ }
+
+ switch (params_rate(hw_params)) {
+ case 16000:
+ snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf,
+ get_srate(params_rate(hw_params)));
+ snd_soc_update_bits(codec, ML26124_PLLNL, 0xff,
+ coeff_div[i].pllnl);
+ snd_soc_update_bits(codec, ML26124_PLLNH, 0x1,
+ coeff_div[i].pllnh);
+ snd_soc_update_bits(codec, ML26124_PLLML, 0xff,
+ coeff_div[i].pllml);
+ snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f,
+ coeff_div[i].pllmh);
+ snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f,
+ coeff_div[i].plldiv);
+ break;
+ case 32000:
+ snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf,
+ get_srate(params_rate(hw_params)));
+ snd_soc_update_bits(codec, ML26124_PLLNL, 0xff,
+ coeff_div[i].pllnl);
+ snd_soc_update_bits(codec, ML26124_PLLNH, 0x1,
+ coeff_div[i].pllnh);
+ snd_soc_update_bits(codec, ML26124_PLLML, 0xff,
+ coeff_div[i].pllml);
+ snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f,
+ coeff_div[i].pllmh);
+ snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f,
+ coeff_div[i].plldiv);
+ break;
+ case 48000:
+ snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf,
+ get_srate(params_rate(hw_params)));
+ snd_soc_update_bits(codec, ML26124_PLLNL, 0xff,
+ coeff_div[i].pllnl);
+ snd_soc_update_bits(codec, ML26124_PLLNH, 0x1,
+ coeff_div[i].pllnh);
+ snd_soc_update_bits(codec, ML26124_PLLML, 0xff,
+ coeff_div[i].pllml);
+ snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f,
+ coeff_div[i].pllmh);
+ snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f,
+ coeff_div[i].plldiv);
+ break;
+ default:
+ pr_err("%s:this rate is no support for ml26124\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ml26124_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ switch (priv->substream->stream) {
+ case SNDRV_PCM_STREAM_CAPTURE:
+ snd_soc_update_bits(codec, ML26124_REC_PLYBAK_RUN, BIT(0), 1);
+ break;
+ case SNDRV_PCM_STREAM_PLAYBACK:
+ snd_soc_update_bits(codec, ML26124_REC_PLYBAK_RUN, BIT(1), 2);
+ break;
+ }
+
+ if (mute)
+ snd_soc_update_bits(codec, ML26124_DVOL_CTL, BIT(4),
+ DVOL_CTL_DVMUTE_ON);
+ else
+ snd_soc_update_bits(codec, ML26124_DVOL_CTL, BIT(4),
+ DVOL_CTL_DVMUTE_OFF);
+
+ return 0;
+}
+
+static int ml26124_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ unsigned char mode;
+ struct snd_soc_codec *codec = codec_dai->codec;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ mode = 1;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ mode = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, ML26124_SAI_MODE_SEL, BIT(0), mode);
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ml26124_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ switch (clk_id) {
+ case ML26124_USE_PLLOUT:
+ priv->clk_in = ML26124_USE_PLLOUT;
+ break;
+ case ML26124_USE_MCLKI:
+ priv->clk_in = ML26124_USE_MCLKI;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ priv->mclk = freq;
+
+ return 0;
+}
+
+static int ml26124_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ snd_soc_update_bits(codec, ML26124_PW_SPAMP_PW_MNG,
+ ML26124_R26_MASK, ML26124_BLT_PREAMP_ON);
+ msleep(100);
+ snd_soc_update_bits(codec, ML26124_PW_SPAMP_PW_MNG,
+ ML26124_R26_MASK,
+ ML26124_MICBEN_ON | ML26124_BLT_ALL_ON);
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ /* VMID ON */
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ snd_soc_update_bits(codec, ML26124_PW_REF_PW_MNG,
+ ML26124_VMID, ML26124_VMID);
+ msleep(500);
+ regcache_sync(priv->regmap);
+ }
+ break;
+ case SND_SOC_BIAS_OFF:
+ /* VMID OFF */
+ snd_soc_update_bits(codec, ML26124_PW_REF_PW_MNG,
+ ML26124_VMID, 0);
+ break;
+ }
+ codec->dapm.bias_level = level;
+ return 0;
+}
+
+static const struct snd_soc_dai_ops ml26124_dai_ops = {
+ .hw_params = ml26124_hw_params,
+ .digital_mute = ml26124_mute,
+ .set_fmt = ml26124_set_dai_fmt,
+ .set_sysclk = ml26124_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_driver ml26124_dai = {
+ .name = "ml26124-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ML26124_RATES,
+ .formats = ML26124_FORMATS,},
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ML26124_RATES,
+ .formats = ML26124_FORMATS,},
+ .ops = &ml26124_dai_ops,
+ .symmetric_rates = 1,
+};
+
+#ifdef CONFIG_PM
+static int ml26124_suspend(struct snd_soc_codec *codec)
+{
+ ml26124_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static int ml26124_resume(struct snd_soc_codec *codec)
+{
+ ml26124_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ return 0;
+}
+#else
+#define ml26124_suspend NULL
+#define ml26124_resume NULL
+#endif
+
+static int ml26124_probe(struct snd_soc_codec *codec)
+{
+ int ret;
+ struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
+ codec->control_data = priv->regmap;
+
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ /* Software Reset */
+ snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 1);
+ snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 0);
+
+ ml26124_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_ml26124 = {
+ .probe = ml26124_probe,
+ .suspend = ml26124_suspend,
+ .resume = ml26124_resume,
+ .set_bias_level = ml26124_set_bias_level,
+ .dapm_widgets = ml26124_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(ml26124_dapm_widgets),
+ .dapm_routes = ml26124_intercon,
+ .num_dapm_routes = ARRAY_SIZE(ml26124_intercon),
+ .controls = ml26124_snd_controls,
+ .num_controls = ARRAY_SIZE(ml26124_snd_controls),
+};
+
+static const struct regmap_config ml26124_i2c_regmap = {
+ .val_bits = 8,
+ .reg_bits = 8,
+ .max_register = ML26124_NUM_REGISTER,
+ .reg_defaults = ml26124_reg,
+ .num_reg_defaults = ARRAY_SIZE(ml26124_reg),
+ .cache_type = REGCACHE_RBTREE,
+ .write_flag_mask = 0x01,
+};
+
+static __devinit int ml26124_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct ml26124_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, priv);
+
+ priv->regmap = regmap_init_i2c(i2c, &ml26124_i2c_regmap);
+ if (IS_ERR(priv->regmap)) {
+ ret = PTR_ERR(priv->regmap);
+ dev_err(&i2c->dev, "regmap_init_i2c() failed: %d\n", ret);
+ return ret;
+ }
+
+ return snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_ml26124, &ml26124_dai, 1);
+}
+
+static __devexit int ml26124_i2c_remove(struct i2c_client *client)
+{
+ struct ml26124_priv *priv = i2c_get_clientdata(client);
+
+ snd_soc_unregister_codec(&client->dev);
+ regmap_exit(priv->regmap);
+ return 0;
+}
+
+static const struct i2c_device_id ml26124_i2c_id[] = {
+ { "ml26124", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ml26124_i2c_id);
+
+static struct i2c_driver ml26124_i2c_driver = {
+ .driver = {
+ .name = "ml26124",
+ .owner = THIS_MODULE,
+ },
+ .probe = ml26124_i2c_probe,
+ .remove = __devexit_p(ml26124_i2c_remove),
+ .id_table = ml26124_i2c_id,
+};
+
+module_i2c_driver(ml26124_i2c_driver);
+
+MODULE_AUTHOR("Tomoya MORINAGA <tomoya.rohm@gmail.com>");
+MODULE_DESCRIPTION("LAPIS Semiconductor ML26124 ALSA SoC codec driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ml26124.h b/sound/soc/codecs/ml26124.h
new file mode 100644
index 000000000000..5ea0cbb8c46c
--- /dev/null
+++ b/sound/soc/codecs/ml26124.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef ML26124_H
+#define ML26124_H
+
+/* Clock Control Register */
+#define ML26124_SMPLING_RATE 0x00
+#define ML26124_PLLNL 0x02
+#define ML26124_PLLNH 0x04
+#define ML26124_PLLML 0x06
+#define ML26124_PLLMH 0x08
+#define ML26124_PLLDIV 0x0a
+#define ML26124_CLK_EN 0x0c
+#define ML26124_CLK_CTL 0x0e
+
+/* System Control Register */
+#define ML26124_SW_RST 0x10
+#define ML26124_REC_PLYBAK_RUN 0x12
+#define ML26124_MIC_TIM 0x14
+
+/* Power Mnagement Register */
+#define ML26124_PW_REF_PW_MNG 0x20
+#define ML26124_PW_IN_PW_MNG 0x22
+#define ML26124_PW_DAC_PW_MNG 0x24
+#define ML26124_PW_SPAMP_PW_MNG 0x26
+#define ML26124_PW_LOUT_PW_MNG 0x28
+#define ML26124_PW_VOUT_PW_MNG 0x2a
+#define ML26124_PW_ZCCMP_PW_MNG 0x2e
+
+/* Analog Reference Control Register */
+#define ML26124_PW_MICBIAS_VOL 0x30
+
+/* Input/Output Amplifier Control Register */
+#define ML26124_PW_MIC_IN_VOL 0x32
+#define ML26124_PW_MIC_BOST_VOL 0x38
+#define ML26124_PW_SPK_AMP_VOL 0x3a
+#define ML26124_PW_AMP_VOL_FUNC 0x48
+#define ML26124_PW_AMP_VOL_FADE 0x4a
+
+/* Analog Path Control Register */
+#define ML26124_SPK_AMP_OUT 0x54
+#define ML26124_MIC_IF_CTL 0x5a
+#define ML26124_MIC_SELECT 0xe8
+
+/* Audio Interface Control Register */
+#define ML26124_SAI_TRANS_CTL 0x60
+#define ML26124_SAI_RCV_CTL 0x62
+#define ML26124_SAI_MODE_SEL 0x64
+
+/* DSP Control Register */
+#define ML26124_FILTER_EN 0x66
+#define ML26124_DVOL_CTL 0x68
+#define ML26124_MIXER_VOL_CTL 0x6a
+#define ML26124_RECORD_DIG_VOL 0x6c
+#define ML26124_PLBAK_DIG_VOL 0x70
+#define ML26124_DIGI_BOOST_VOL 0x72
+#define ML26124_EQ_GAIN_BRAND0 0x74
+#define ML26124_EQ_GAIN_BRAND1 0x76
+#define ML26124_EQ_GAIN_BRAND2 0x78
+#define ML26124_EQ_GAIN_BRAND3 0x7a
+#define ML26124_EQ_GAIN_BRAND4 0x7c
+#define ML26124_HPF2_CUTOFF 0x7e
+#define ML26124_EQBRAND0_F0L 0x80
+#define ML26124_EQBRAND0_F0H 0x82
+#define ML26124_EQBRAND0_F1L 0x84
+#define ML26124_EQBRAND0_F1H 0x86
+#define ML26124_EQBRAND1_F0L 0x88
+#define ML26124_EQBRAND1_F0H 0x8a
+#define ML26124_EQBRAND1_F1L 0x8c
+#define ML26124_EQBRAND1_F1H 0x8e
+#define ML26124_EQBRAND2_F0L 0x90
+#define ML26124_EQBRAND2_F0H 0x92
+#define ML26124_EQBRAND2_F1L 0x94
+#define ML26124_EQBRAND2_F1H 0x96
+#define ML26124_EQBRAND3_F0L 0x98
+#define ML26124_EQBRAND3_F0H 0x9a
+#define ML26124_EQBRAND3_F1L 0x9c
+#define ML26124_EQBRAND3_F1H 0x9e
+#define ML26124_EQBRAND4_F0L 0xa0
+#define ML26124_EQBRAND4_F0H 0xa2
+#define ML26124_EQBRAND4_F1L 0xa4
+#define ML26124_EQBRAND4_F1H 0xa6
+
+/* ALC Control Register */
+#define ML26124_ALC_MODE 0xb0
+#define ML26124_ALC_ATTACK_TIM 0xb2
+#define ML26124_ALC_DECAY_TIM 0xb4
+#define ML26124_ALC_HOLD_TIM 0xb6
+#define ML26124_ALC_TARGET_LEV 0xb8
+#define ML26124_ALC_MAXMIN_GAIN 0xba
+#define ML26124_NOIS_GATE_THRSH 0xbc
+#define ML26124_ALC_ZERO_TIMOUT 0xbe
+
+/* Playback Limiter Control Register */
+#define ML26124_PL_ATTACKTIME 0xc0
+#define ML26124_PL_DECAYTIME 0xc2
+#define ML26124_PL_TARGETTIME 0xc4
+#define ML26124_PL_MAXMIN_GAIN 0xc6
+#define ML26124_PLYBAK_BOST_VOL 0xc8
+#define ML26124_PL_0CROSS_TIMOUT 0xca
+
+/* Video Amplifer Control Register */
+#define ML26124_VIDEO_AMP_GAIN_CTL 0xd0
+#define ML26124_VIDEO_AMP_SETUP1 0xd2
+#define ML26124_VIDEO_AMP_CTL2 0xd4
+
+/* Clock select for machine driver */
+#define ML26124_USE_PLL 0
+#define ML26124_USE_MCLKI_256FS 1
+#define ML26124_USE_MCLKI_512FS 2
+#define ML26124_USE_MCLKI_1024FS 3
+
+/* Register Mask */
+#define ML26124_R0_MASK 0xf
+#define ML26124_R2_MASK 0xff
+#define ML26124_R4_MASK 0x1
+#define ML26124_R6_MASK 0xf
+#define ML26124_R8_MASK 0x3f
+#define ML26124_Ra_MASK 0x1f
+#define ML26124_Rc_MASK 0x1f
+#define ML26124_Re_MASK 0x7
+#define ML26124_R10_MASK 0x1
+#define ML26124_R12_MASK 0x17
+#define ML26124_R14_MASK 0x3f
+#define ML26124_R20_MASK 0x47
+#define ML26124_R22_MASK 0xa
+#define ML26124_R24_MASK 0x2
+#define ML26124_R26_MASK 0x1f
+#define ML26124_R28_MASK 0x2
+#define ML26124_R2a_MASK 0x2
+#define ML26124_R2e_MASK 0x2
+#define ML26124_R30_MASK 0x7
+#define ML26124_R32_MASK 0x3f
+#define ML26124_R38_MASK 0x38
+#define ML26124_R3a_MASK 0x3f
+#define ML26124_R48_MASK 0x3
+#define ML26124_R4a_MASK 0x7
+#define ML26124_R54_MASK 0x2a
+#define ML26124_R5a_MASK 0x3
+#define ML26124_Re8_MASK 0x3
+#define ML26124_R60_MASK 0xff
+#define ML26124_R62_MASK 0xff
+#define ML26124_R64_MASK 0x1
+#define ML26124_R66_MASK 0xff
+#define ML26124_R68_MASK 0x3b
+#define ML26124_R6a_MASK 0xf3
+#define ML26124_R6c_MASK 0xff
+#define ML26124_R70_MASK 0xff
+
+#define ML26124_MCLKEN BIT(0)
+#define ML26124_PLLEN BIT(1)
+#define ML26124_PLLOE BIT(2)
+#define ML26124_MCLKOE BIT(3)
+
+#define ML26124_BLT_ALL_ON 0x1f
+#define ML26124_BLT_PREAMP_ON 0x13
+
+#define ML26124_MICBEN_ON BIT(2)
+
+enum ml26124_regs {
+ ML26124_MCLK = 0,
+};
+
+enum ml26124_clk_in {
+ ML26124_USE_PLLOUT = 0,
+ ML26124_USE_MCLKI,
+};
+
+#endif
diff --git a/sound/soc/codecs/omap-hdmi.c b/sound/soc/codecs/omap-hdmi.c
new file mode 100644
index 000000000000..1bf5c74f5f96
--- /dev/null
+++ b/sound/soc/codecs/omap-hdmi.c
@@ -0,0 +1,69 @@
+/*
+ * ALSA SoC codec driver for HDMI audio on OMAP processors.
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Ricardo Neri <ricardo.neri@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#include <linux/module.h>
+#include <sound/soc.h>
+
+#define DRV_NAME "hdmi-audio-codec"
+
+static struct snd_soc_codec_driver omap_hdmi_codec;
+
+static struct snd_soc_dai_driver omap_hdmi_codec_dai = {
+ .name = "omap-hdmi-hifi",
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_32000 |
+ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE,
+ },
+};
+
+static __devinit int omap_hdmi_codec_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev, &omap_hdmi_codec,
+ &omap_hdmi_codec_dai, 1);
+}
+
+static __devexit int omap_hdmi_codec_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver omap_hdmi_codec_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+
+ .probe = omap_hdmi_codec_probe,
+ .remove = __devexit_p(omap_hdmi_codec_remove),
+};
+
+module_platform_driver(omap_hdmi_codec_driver);
+
+MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
+MODULE_DESCRIPTION("ASoC OMAP HDMI codec driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
index 20c324c7c349..960d0e93cce9 100644
--- a/sound/soc/codecs/rt5631.c
+++ b/sound/soc/codecs/rt5631.c
@@ -18,7 +18,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/spi/spi.h>
+#include <linux/regmap.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -30,6 +30,7 @@
#include "rt5631.h"
struct rt5631_priv {
+ struct regmap *regmap;
int codec_version;
int master;
int sysclk;
@@ -38,33 +39,33 @@ struct rt5631_priv {
int dmic_used_flag;
};
-static const u16 rt5631_reg[RT5631_VENDOR_ID2 + 1] = {
- [RT5631_SPK_OUT_VOL] = 0x8888,
- [RT5631_HP_OUT_VOL] = 0x8080,
- [RT5631_MONO_AXO_1_2_VOL] = 0xa080,
- [RT5631_AUX_IN_VOL] = 0x0808,
- [RT5631_ADC_REC_MIXER] = 0xf0f0,
- [RT5631_VDAC_DIG_VOL] = 0x0010,
- [RT5631_OUTMIXER_L_CTRL] = 0xffc0,
- [RT5631_OUTMIXER_R_CTRL] = 0xffc0,
- [RT5631_AXO1MIXER_CTRL] = 0x88c0,
- [RT5631_AXO2MIXER_CTRL] = 0x88c0,
- [RT5631_DIG_MIC_CTRL] = 0x3000,
- [RT5631_MONO_INPUT_VOL] = 0x8808,
- [RT5631_SPK_MIXER_CTRL] = 0xf8f8,
- [RT5631_SPK_MONO_OUT_CTRL] = 0xfc00,
- [RT5631_SPK_MONO_HP_OUT_CTRL] = 0x4440,
- [RT5631_SDP_CTRL] = 0x8000,
- [RT5631_MONO_SDP_CTRL] = 0x8000,
- [RT5631_STEREO_AD_DA_CLK_CTRL] = 0x2010,
- [RT5631_GEN_PUR_CTRL_REG] = 0x0e00,
- [RT5631_INT_ST_IRQ_CTRL_2] = 0x071a,
- [RT5631_MISC_CTRL] = 0x2040,
- [RT5631_DEPOP_FUN_CTRL_2] = 0x8000,
- [RT5631_SOFT_VOL_CTRL] = 0x07e0,
- [RT5631_ALC_CTRL_1] = 0x0206,
- [RT5631_ALC_CTRL_3] = 0x2000,
- [RT5631_PSEUDO_SPATL_CTRL] = 0x0553,
+static const struct reg_default rt5631_reg[] = {
+ { RT5631_SPK_OUT_VOL, 0x8888 },
+ { RT5631_HP_OUT_VOL, 0x8080 },
+ { RT5631_MONO_AXO_1_2_VOL, 0xa080 },
+ { RT5631_AUX_IN_VOL, 0x0808 },
+ { RT5631_ADC_REC_MIXER, 0xf0f0 },
+ { RT5631_VDAC_DIG_VOL, 0x0010 },
+ { RT5631_OUTMIXER_L_CTRL, 0xffc0 },
+ { RT5631_OUTMIXER_R_CTRL, 0xffc0 },
+ { RT5631_AXO1MIXER_CTRL, 0x88c0 },
+ { RT5631_AXO2MIXER_CTRL, 0x88c0 },
+ { RT5631_DIG_MIC_CTRL, 0x3000 },
+ { RT5631_MONO_INPUT_VOL, 0x8808 },
+ { RT5631_SPK_MIXER_CTRL, 0xf8f8 },
+ { RT5631_SPK_MONO_OUT_CTRL, 0xfc00 },
+ { RT5631_SPK_MONO_HP_OUT_CTRL, 0x4440 },
+ { RT5631_SDP_CTRL, 0x8000 },
+ { RT5631_MONO_SDP_CTRL, 0x8000 },
+ { RT5631_STEREO_AD_DA_CLK_CTRL, 0x2010 },
+ { RT5631_GEN_PUR_CTRL_REG, 0x0e00 },
+ { RT5631_INT_ST_IRQ_CTRL_2, 0x071a },
+ { RT5631_MISC_CTRL, 0x2040 },
+ { RT5631_DEPOP_FUN_CTRL_2, 0x8000 },
+ { RT5631_SOFT_VOL_CTRL, 0x07e0 },
+ { RT5631_ALC_CTRL_1, 0x0206 },
+ { RT5631_ALC_CTRL_3, 0x2000 },
+ { RT5631_PSEUDO_SPATL_CTRL, 0x0553 },
};
/**
@@ -96,8 +97,7 @@ static int rt5631_reset(struct snd_soc_codec *codec)
return snd_soc_write(codec, RT5631_RESET, 0);
}
-static int rt5631_volatile_register(struct snd_soc_codec *codec,
- unsigned int reg)
+static bool rt5631_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT5631_RESET:
@@ -111,8 +111,7 @@ static int rt5631_volatile_register(struct snd_soc_codec *codec,
}
}
-static int rt5631_readable_register(struct snd_soc_codec *codec,
- unsigned int reg)
+static bool rt5631_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT5631_RESET:
@@ -1361,8 +1360,7 @@ static int get_coeff(int mclk, int rate, int timesofbclk)
static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
int timesofbclk = 32, coeff;
unsigned int iface = 0;
@@ -1544,6 +1542,8 @@ static int rt5631_codec_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
static int rt5631_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
switch (level) {
case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
@@ -1561,8 +1561,8 @@ static int rt5631_set_bias_level(struct snd_soc_codec *codec,
snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
RT5631_PWR_FAST_VREF_CTRL,
RT5631_PWR_FAST_VREF_CTRL);
- codec->cache_only = false;
- snd_soc_cache_sync(codec);
+ regcache_cache_only(rt5631->regmap, false);
+ regcache_sync(rt5631->regmap);
}
break;
@@ -1587,7 +1587,9 @@ static int rt5631_probe(struct snd_soc_codec *codec)
unsigned int val;
int ret;
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+ codec->control_data = rt5631->regmap;
+
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -1698,12 +1700,6 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5631 = {
.suspend = rt5631_suspend,
.resume = rt5631_resume,
.set_bias_level = rt5631_set_bias_level,
- .reg_cache_size = RT5631_VENDOR_ID2 + 1,
- .reg_word_size = sizeof(u16),
- .reg_cache_default = rt5631_reg,
- .volatile_register = rt5631_volatile_register,
- .readable_register = rt5631_readable_register,
- .reg_cache_step = 1,
.controls = rt5631_snd_controls,
.num_controls = ARRAY_SIZE(rt5631_snd_controls),
.dapm_widgets = rt5631_dapm_widgets,
@@ -1718,6 +1714,18 @@ static const struct i2c_device_id rt5631_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id);
+static const struct regmap_config rt5631_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .readable_reg = rt5631_readable_register,
+ .volatile_reg = rt5631_volatile_register,
+ .max_register = RT5631_VENDOR_ID2,
+ .reg_defaults = rt5631_reg,
+ .num_reg_defaults = ARRAY_SIZE(rt5631_reg),
+ .cache_type = REGCACHE_RBTREE,
+};
+
static int rt5631_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -1731,6 +1739,10 @@ static int rt5631_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, rt5631);
+ rt5631->regmap = devm_regmap_init_i2c(i2c, &rt5631_regmap_config);
+ if (IS_ERR(rt5631->regmap))
+ return PTR_ERR(rt5631->regmap);
+
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5631,
rt5631_dai, ARRAY_SIZE(rt5631_dai));
return ret;
@@ -1752,17 +1764,7 @@ static struct i2c_driver rt5631_i2c_driver = {
.id_table = rt5631_i2c_id,
};
-static int __init rt5631_modinit(void)
-{
- return i2c_add_driver(&rt5631_i2c_driver);
-}
-module_init(rt5631_modinit);
-
-static void __exit rt5631_modexit(void)
-{
- i2c_del_driver(&rt5631_i2c_driver);
-}
-module_exit(rt5631_modexit);
+module_i2c_driver(rt5631_i2c_driver);
MODULE_DESCRIPTION("ASoC RT5631 driver");
MODULE_AUTHOR("flove <flove@realtek.com>");
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 8e92fb88ed09..8af6a5245b18 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -84,8 +84,8 @@ static struct regulator_consumer_supply ldo_consumer[] = {
static struct regulator_init_data ldo_init_data = {
.constraints = {
- .min_uV = 850000,
- .max_uV = 1600000,
+ .min_uV = 1200000,
+ .max_uV = 1200000,
.valid_modes_mask = REGULATOR_MODE_NORMAL,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
@@ -197,9 +197,9 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("HP_OUT"),
SND_SOC_DAPM_OUTPUT("LINE_OUT"),
- SND_SOC_DAPM_MICBIAS_E("Mic Bias", SGTL5000_CHIP_MIC_CTRL, 8, 0,
- mic_bias_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_SUPPLY("Mic Bias", SGTL5000_CHIP_MIC_CTRL, 8, 0,
+ mic_bias_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_PGA("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0),
SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0),
@@ -665,8 +665,7 @@ static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
int channels = params_channels(params);
int i2s_ctl = 0;
@@ -809,6 +808,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
{
struct ldo_regulator *ldo;
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+ struct regulator_config config = { };
ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL);
@@ -832,8 +832,11 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
ldo->codec_data = codec;
ldo->voltage = voltage;
- ldo->dev = regulator_register(&ldo->desc, codec->dev,
- init_data, ldo, NULL);
+ config.dev = codec->dev;
+ config.driver_data = ldo;
+ config.init_data = init_data;
+
+ ldo->dev = regulator_register(&ldo->desc, &config);
if (IS_ERR(ldo->dev)) {
int ret = PTR_ERR(ldo->dev);
@@ -1451,17 +1454,7 @@ static struct i2c_driver sgtl5000_i2c_driver = {
.id_table = sgtl5000_id,
};
-static int __init sgtl5000_modinit(void)
-{
- return i2c_add_driver(&sgtl5000_i2c_driver);
-}
-module_init(sgtl5000_modinit);
-
-static void __exit sgtl5000_exit(void)
-{
- i2c_del_driver(&sgtl5000_i2c_driver);
-}
-module_exit(sgtl5000_exit);
+module_i2c_driver(sgtl5000_i2c_driver);
MODULE_DESCRIPTION("Freescale SGTL5000 ALSA SoC Codec Driver");
MODULE_AUTHOR("Zeng Zhaoming <zengzm.kernel@gmail.com>");
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index de2b20544ceb..079066fef425 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -33,6 +33,7 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -43,8 +44,6 @@
#include "ssm2602.h"
-#define SSM2602_VERSION "0.1"
-
enum ssm2602_type {
SSM2602,
SSM2604,
@@ -53,10 +52,12 @@ enum ssm2602_type {
/* codec private data */
struct ssm2602_priv {
unsigned int sysclk;
- enum snd_soc_control_type control_type;
+ struct snd_pcm_hw_constraint_list *sysclk_constraints;
struct snd_pcm_substream *master_substream;
struct snd_pcm_substream *slave_substream;
+ struct regmap *regmap;
+
enum ssm2602_type type;
unsigned int clk_out_pwr;
};
@@ -73,7 +74,6 @@ static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = {
0x0000, 0x0000
};
-#define ssm2602_reset(c) snd_soc_write(c, SSM2602_RESET, 0)
/*Appending several "None"s just for OSS mixer use*/
static const char *ssm2602_input_select[] = {
@@ -195,6 +195,24 @@ static const struct snd_soc_dapm_route ssm2604_routes[] = {
{"ADC", NULL, "Line Input"},
};
+static const unsigned int ssm2602_rates_12288000[] = {
+ 8000, 32000, 48000, 96000,
+};
+
+static struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = {
+ .list = ssm2602_rates_12288000,
+ .count = ARRAY_SIZE(ssm2602_rates_12288000),
+};
+
+static const unsigned int ssm2602_rates_11289600[] = {
+ 8000, 44100, 88200,
+};
+
+static struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = {
+ .list = ssm2602_rates_11289600,
+ .count = ARRAY_SIZE(ssm2602_rates_11289600),
+};
+
struct ssm2602_coeff {
u32 mclk;
u32 rate;
@@ -254,11 +272,10 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
- u16 iface = snd_soc_read(codec, SSM2602_IFACE) & 0xfff3;
int srate = ssm2602_get_coeff(ssm2602->sysclk, params_rate(params));
+ unsigned int iface;
if (substream == ssm2602->slave_substream) {
dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n");
@@ -268,31 +285,34 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
if (srate < 0)
return srate;
- snd_soc_write(codec, SSM2602_SRATE, srate);
+ regmap_write(ssm2602->regmap, SSM2602_SRATE, srate);
/* bit size */
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
+ iface = 0x0;
break;
case SNDRV_PCM_FORMAT_S20_3LE:
- iface |= 0x0004;
+ iface = 0x4;
break;
case SNDRV_PCM_FORMAT_S24_LE:
- iface |= 0x0008;
+ iface = 0x8;
break;
case SNDRV_PCM_FORMAT_S32_LE:
- iface |= 0x000c;
+ iface = 0xc;
break;
+ default:
+ return -EINVAL;
}
- snd_soc_write(codec, SSM2602_IFACE, iface);
+ regmap_update_bits(ssm2602->regmap, SSM2602_IFACE,
+ IFACE_AUDIO_DATA_LEN, iface);
return 0;
}
static int ssm2602_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
struct snd_pcm_runtime *master_runtime;
@@ -322,14 +342,19 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
} else
ssm2602->master_substream = substream;
+ if (ssm2602->sysclk_constraints) {
+ snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ ssm2602->sysclk_constraints);
+ }
+
return 0;
}
static void ssm2602_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
if (ssm2602->master_substream == substream)
@@ -341,14 +366,14 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
{
- struct snd_soc_codec *codec = dai->codec;
+ struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(dai->codec);
if (mute)
- snd_soc_update_bits(codec, SSM2602_APDIGI,
+ regmap_update_bits(ssm2602->regmap, SSM2602_APDIGI,
APDIGI_ENABLE_DAC_MUTE,
APDIGI_ENABLE_DAC_MUTE);
else
- snd_soc_update_bits(codec, SSM2602_APDIGI,
+ regmap_update_bits(ssm2602->regmap, SSM2602_APDIGI,
APDIGI_ENABLE_DAC_MUTE, 0);
return 0;
}
@@ -364,16 +389,21 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai,
return -EINVAL;
switch (freq) {
- case 11289600:
- case 12000000:
case 12288000:
- case 16934400:
case 18432000:
- ssm2602->sysclk = freq;
+ ssm2602->sysclk_constraints = &ssm2602_constraints_12288000;
+ break;
+ case 11289600:
+ case 16934400:
+ ssm2602->sysclk_constraints = &ssm2602_constraints_11289600;
+ break;
+ case 12000000:
+ ssm2602->sysclk_constraints = NULL;
break;
default:
return -EINVAL;
}
+ ssm2602->sysclk = freq;
} else {
unsigned int mask;
@@ -393,7 +423,7 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai,
else
ssm2602->clk_out_pwr &= ~mask;
- snd_soc_update_bits(codec, SSM2602_PWR,
+ regmap_update_bits(ssm2602->regmap, SSM2602_PWR,
PWR_CLK_OUT_PDN | PWR_OSC_PDN, ssm2602->clk_out_pwr);
}
@@ -403,8 +433,8 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai,
static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
- struct snd_soc_codec *codec = codec_dai->codec;
- u16 iface = 0;
+ struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec_dai->codec);
+ unsigned int iface = 0;
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -455,7 +485,7 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
}
/* set iface */
- snd_soc_write(codec, SSM2602_IFACE, iface);
+ regmap_write(ssm2602->regmap, SSM2602_IFACE, iface);
return 0;
}
@@ -467,7 +497,7 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
switch (level) {
case SND_SOC_BIAS_ON:
/* vref/mid on, osc and clkout on if enabled */
- snd_soc_update_bits(codec, SSM2602_PWR,
+ regmap_update_bits(ssm2602->regmap, SSM2602_PWR,
PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
ssm2602->clk_out_pwr);
break;
@@ -475,13 +505,13 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
break;
case SND_SOC_BIAS_STANDBY:
/* everything off except vref/vmid, */
- snd_soc_update_bits(codec, SSM2602_PWR,
+ regmap_update_bits(ssm2602->regmap, SSM2602_PWR,
PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
PWR_CLK_OUT_PDN | PWR_OSC_PDN);
break;
case SND_SOC_BIAS_OFF:
/* everything off */
- snd_soc_update_bits(codec, SSM2602_PWR,
+ regmap_update_bits(ssm2602->regmap, SSM2602_PWR,
PWR_POWER_OFF, PWR_POWER_OFF);
break;
@@ -540,12 +570,13 @@ static int ssm2602_resume(struct snd_soc_codec *codec)
static int ssm2602_probe(struct snd_soc_codec *codec)
{
+ struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret;
- snd_soc_update_bits(codec, SSM2602_LOUT1V,
+ regmap_update_bits(ssm2602->regmap, SSM2602_LOUT1V,
LOUT1V_LRHP_BOTH, LOUT1V_LRHP_BOTH);
- snd_soc_update_bits(codec, SSM2602_ROUT1V,
+ regmap_update_bits(ssm2602->regmap, SSM2602_ROUT1V,
ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH);
ret = snd_soc_add_codec_controls(codec, ssm2602_snd_controls,
@@ -581,27 +612,26 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
int ret;
- pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
-
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, ssm2602->control_type);
+ codec->control_data = ssm2602->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- ret = ssm2602_reset(codec);
+ ret = regmap_write(ssm2602->regmap, SSM2602_RESET, 0);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
return ret;
}
/* set the update bits */
- snd_soc_update_bits(codec, SSM2602_LINVOL,
+ regmap_update_bits(ssm2602->regmap, SSM2602_LINVOL,
LINVOL_LRIN_BOTH, LINVOL_LRIN_BOTH);
- snd_soc_update_bits(codec, SSM2602_RINVOL,
+ regmap_update_bits(ssm2602->regmap, SSM2602_RINVOL,
RINVOL_RLIN_BOTH, RINVOL_RLIN_BOTH);
/*select Line in as default input*/
- snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC |
+ regmap_write(ssm2602->regmap, SSM2602_APANA, APANA_SELECT_DAC |
APANA_ENABLE_MIC_BOOST);
switch (ssm2602->type) {
@@ -634,9 +664,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
.suspend = ssm2602_suspend,
.resume = ssm2602_resume,
.set_bias_level = ssm2602_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(ssm2602_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = ssm2602_reg,
.controls = ssm260x_snd_controls,
.num_controls = ARRAY_SIZE(ssm260x_snd_controls),
@@ -646,6 +673,23 @@ static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
.num_dapm_routes = ARRAY_SIZE(ssm260x_routes),
};
+static bool ssm2602_register_volatile(struct device *dev, unsigned int reg)
+{
+ return reg == SSM2602_RESET;
+}
+
+static const struct regmap_config ssm2602_regmap_config = {
+ .val_bits = 9,
+ .reg_bits = 7,
+
+ .max_register = SSM2602_RESET,
+ .volatile_reg = ssm2602_register_volatile,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults_raw = ssm2602_reg,
+ .num_reg_defaults_raw = ARRAY_SIZE(ssm2602_reg),
+};
+
#if defined(CONFIG_SPI_MASTER)
static int __devinit ssm2602_spi_probe(struct spi_device *spi)
{
@@ -658,9 +702,12 @@ static int __devinit ssm2602_spi_probe(struct spi_device *spi)
return -ENOMEM;
spi_set_drvdata(spi, ssm2602);
- ssm2602->control_type = SND_SOC_SPI;
ssm2602->type = SSM2602;
+ ssm2602->regmap = devm_regmap_init_spi(spi, &ssm2602_regmap_config);
+ if (IS_ERR(ssm2602->regmap))
+ return PTR_ERR(ssm2602->regmap);
+
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_ssm2602, &ssm2602_dai, 1);
return ret;
@@ -701,9 +748,12 @@ static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
i2c_set_clientdata(i2c, ssm2602);
- ssm2602->control_type = SND_SOC_I2C;
ssm2602->type = id->driver_data;
+ ssm2602->regmap = devm_regmap_init_i2c(i2c, &ssm2602_regmap_config);
+ if (IS_ERR(ssm2602->regmap))
+ return PTR_ERR(ssm2602->regmap);
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_ssm2602, &ssm2602_dai, 1);
return ret;
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index 7db6fa515028..8d717f4b5a87 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -609,8 +609,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
unsigned int rate;
int i, mcs = -1, ir = -1;
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index df1e07ffac32..31762ebdd774 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -34,8 +34,6 @@
#include "tlv320aic23.h"
-#define AIC23_VERSION "0.1"
-
/*
* AIC23 register cache
*/
@@ -325,8 +323,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 iface_reg;
int ret;
struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
@@ -371,8 +368,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
/* set active */
snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0001);
@@ -383,8 +379,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
/* deactivate */
@@ -548,8 +543,6 @@ static int tlv320aic23_probe(struct snd_soc_codec *codec)
struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
int ret;
- printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
-
ret = snd_soc_codec_set_cache_io(codec, 7, 9, aic23->control_type);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 802064b5030d..85944e953578 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -126,8 +126,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
int fsref, divisor, wlen, pval, jval, dval, qval;
u16 reg;
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 8d20f6ec20f3..64d2a4fa34b2 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -802,8 +802,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec =rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
@@ -1161,24 +1160,6 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
- int headset_debounce, int button_debounce)
-{
- u8 val;
-
- val = ((detect & AIC3X_HEADSET_DETECT_MASK)
- << AIC3X_HEADSET_DETECT_SHIFT) |
- ((headset_debounce & AIC3X_HEADSET_DEBOUNCE_MASK)
- << AIC3X_HEADSET_DEBOUNCE_SHIFT) |
- ((button_debounce & AIC3X_BUTTON_DEBOUNCE_MASK)
- << AIC3X_BUTTON_DEBOUNCE_SHIFT);
-
- if (detect & AIC3X_HEADSET_DETECT_MASK)
- val |= AIC3X_HEADSET_DETECT_ENABLED;
-
- snd_soc_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
-}
-
#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 4587ddd0fbf8..0dd41077ab79 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -62,8 +62,10 @@
#define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \
(((samples)*5000) / (((burstrate)*5000) / ((burstrate) - (playrate))))
-static void dac33_calculate_times(struct snd_pcm_substream *substream);
-static int dac33_prepare_chip(struct snd_pcm_substream *substream);
+static void dac33_calculate_times(struct snd_pcm_substream *substream,
+ struct snd_soc_codec *codec);
+static int dac33_prepare_chip(struct snd_pcm_substream *substream,
+ struct snd_soc_codec *codec);
enum dac33_state {
DAC33_IDLE = 0,
@@ -427,8 +429,8 @@ static int dac33_playback_event(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (likely(dac33->substream)) {
- dac33_calculate_times(dac33->substream);
- dac33_prepare_chip(dac33->substream);
+ dac33_calculate_times(dac33->substream, w->codec);
+ dac33_prepare_chip(dac33->substream, w->codec);
}
break;
case SND_SOC_DAPM_POST_PMD:
@@ -799,8 +801,7 @@ static void dac33_oscwait(struct snd_soc_codec *codec)
static int dac33_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
/* Stream started, save the substream pointer */
@@ -812,8 +813,7 @@ static int dac33_startup(struct snd_pcm_substream *substream,
static void dac33_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
dac33->substream = NULL;
@@ -825,8 +825,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
/* Check parameters for validity */
@@ -868,10 +867,9 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,
* writes happens in different order, than dac33 might end up in unknown state.
* Use the known, working sequence of register writes to initialize the dac33.
*/
-static int dac33_prepare_chip(struct snd_pcm_substream *substream)
+static int dac33_prepare_chip(struct snd_pcm_substream *substream,
+ struct snd_soc_codec *codec)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
unsigned int oscset, ratioset, pwr_ctrl, reg_tmp;
u8 aictrl_a, aictrl_b, fifoctrl_a;
@@ -1067,10 +1065,9 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
return 0;
}
-static void dac33_calculate_times(struct snd_pcm_substream *substream)
+static void dac33_calculate_times(struct snd_pcm_substream *substream,
+ struct snd_soc_codec *codec)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
unsigned int period_size = substream->runtime->period_size;
unsigned int rate = substream->runtime->rate;
@@ -1128,8 +1125,7 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream)
static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
@@ -1161,8 +1157,7 @@ static snd_pcm_sframes_t dac33_dai_delay(
struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
unsigned long long t0, t1, t_now;
unsigned int time_delta, uthr;
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 170cf9a8fc79..391fcfc7b63b 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -1685,8 +1685,7 @@ static void twl4030_tdm_enable(struct snd_soc_codec *codec, int direction,
static int twl4030_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
if (twl4030->master_substream) {
@@ -1715,8 +1714,7 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
static void twl4030_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
if (twl4030->master_substream == substream)
@@ -1740,8 +1738,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
u8 mode, old_mode, format, old_format;
@@ -1974,8 +1971,7 @@ static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction,
static int twl4030_voice_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
u8 mode;
@@ -2007,8 +2003,7 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
static void twl4030_voice_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
/* Enable voice digital filters */
twl4030_voice_enable(codec, substream->stream, 0);
@@ -2017,8 +2012,7 @@ static void twl4030_voice_shutdown(struct snd_pcm_substream *substream,
static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
u8 old_mode, mode;
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index dc7509b9d53a..a36e9fcdf184 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -46,17 +46,6 @@
#define TWL6040_OUTHF_0dB 0x03
#define TWL6040_OUTHF_M52dB 0x1D
-#define TWL6040_RAMP_NONE 0
-#define TWL6040_RAMP_UP 1
-#define TWL6040_RAMP_DOWN 2
-
-#define TWL6040_HSL_VOL_MASK 0x0F
-#define TWL6040_HSL_VOL_SHIFT 0
-#define TWL6040_HSR_VOL_MASK 0xF0
-#define TWL6040_HSR_VOL_SHIFT 4
-#define TWL6040_HF_VOL_MASK 0x1F
-#define TWL6040_HF_VOL_SHIFT 0
-
/* Shadow register used by the driver */
#define TWL6040_REG_SW_SHADOW 0x2F
#define TWL6040_CACHEREGNUM (TWL6040_REG_SW_SHADOW + 1)
@@ -64,18 +53,6 @@
/* TWL6040_REG_SW_SHADOW (0x2F) fields */
#define TWL6040_EAR_PATH_ENABLE 0x01
-struct twl6040_output {
- u16 active;
- u16 left_vol;
- u16 right_vol;
- u16 left_step;
- u16 right_step;
- unsigned int step_delay;
- u16 ramp;
- struct delayed_work work;
- struct completion ramp_done;
-};
-
struct twl6040_jack_data {
struct snd_soc_jack *jack;
struct delayed_work work;
@@ -100,8 +77,6 @@ struct twl6040_data {
struct snd_soc_codec *codec;
struct workqueue_struct *workqueue;
struct mutex mutex;
- struct twl6040_output headset;
- struct twl6040_output handsfree;
};
/*
@@ -311,318 +286,6 @@ static void twl6040_restore_regs(struct snd_soc_codec *codec)
}
}
-/*
- * Ramp HS PGA volume to minimise pops at stream startup and shutdown.
- */
-static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
- unsigned int left_step, unsigned int right_step)
-{
-
- struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
- struct twl6040_output *headset = &priv->headset;
- int left_complete = 0, right_complete = 0;
- u8 reg, val;
-
- /* left channel */
- left_step = (left_step > 0xF) ? 0xF : left_step;
- reg = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN);
- val = (~reg & TWL6040_HSL_VOL_MASK);
-
- if (headset->ramp == TWL6040_RAMP_UP) {
- /* ramp step up */
- if (val < headset->left_vol) {
- if (val + left_step > headset->left_vol)
- val = headset->left_vol;
- else
- val += left_step;
-
- reg &= ~TWL6040_HSL_VOL_MASK;
- twl6040_write(codec, TWL6040_REG_HSGAIN,
- (reg | (~val & TWL6040_HSL_VOL_MASK)));
- } else {
- left_complete = 1;
- }
- } else if (headset->ramp == TWL6040_RAMP_DOWN) {
- /* ramp step down */
- if (val > 0x0) {
- if ((int)val - (int)left_step < 0)
- val = 0;
- else
- val -= left_step;
-
- reg &= ~TWL6040_HSL_VOL_MASK;
- twl6040_write(codec, TWL6040_REG_HSGAIN, reg |
- (~val & TWL6040_HSL_VOL_MASK));
- } else {
- left_complete = 1;
- }
- }
-
- /* right channel */
- right_step = (right_step > 0xF) ? 0xF : right_step;
- reg = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN);
- val = (~reg & TWL6040_HSR_VOL_MASK) >> TWL6040_HSR_VOL_SHIFT;
-
- if (headset->ramp == TWL6040_RAMP_UP) {
- /* ramp step up */
- if (val < headset->right_vol) {
- if (val + right_step > headset->right_vol)
- val = headset->right_vol;
- else
- val += right_step;
-
- reg &= ~TWL6040_HSR_VOL_MASK;
- twl6040_write(codec, TWL6040_REG_HSGAIN,
- (reg | (~val << TWL6040_HSR_VOL_SHIFT)));
- } else {
- right_complete = 1;
- }
- } else if (headset->ramp == TWL6040_RAMP_DOWN) {
- /* ramp step down */
- if (val > 0x0) {
- if ((int)val - (int)right_step < 0)
- val = 0;
- else
- val -= right_step;
-
- reg &= ~TWL6040_HSR_VOL_MASK;
- twl6040_write(codec, TWL6040_REG_HSGAIN,
- reg | (~val << TWL6040_HSR_VOL_SHIFT));
- } else {
- right_complete = 1;
- }
- }
-
- return left_complete & right_complete;
-}
-
-/*
- * Ramp HF PGA volume to minimise pops at stream startup and shutdown.
- */
-static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
- unsigned int left_step, unsigned int right_step)
-{
- struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
- struct twl6040_output *handsfree = &priv->handsfree;
- int left_complete = 0, right_complete = 0;
- u16 reg, val;
-
- /* left channel */
- left_step = (left_step > 0x1D) ? 0x1D : left_step;
- reg = twl6040_read_reg_cache(codec, TWL6040_REG_HFLGAIN);
- reg = 0x1D - reg;
- val = (reg & TWL6040_HF_VOL_MASK);
- if (handsfree->ramp == TWL6040_RAMP_UP) {
- /* ramp step up */
- if (val < handsfree->left_vol) {
- if (val + left_step > handsfree->left_vol)
- val = handsfree->left_vol;
- else
- val += left_step;
-
- reg &= ~TWL6040_HF_VOL_MASK;
- twl6040_write(codec, TWL6040_REG_HFLGAIN,
- reg | (0x1D - val));
- } else {
- left_complete = 1;
- }
- } else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
- /* ramp step down */
- if (val > 0) {
- if ((int)val - (int)left_step < 0)
- val = 0;
- else
- val -= left_step;
-
- reg &= ~TWL6040_HF_VOL_MASK;
- twl6040_write(codec, TWL6040_REG_HFLGAIN,
- reg | (0x1D - val));
- } else {
- left_complete = 1;
- }
- }
-
- /* right channel */
- right_step = (right_step > 0x1D) ? 0x1D : right_step;
- reg = twl6040_read_reg_cache(codec, TWL6040_REG_HFRGAIN);
- reg = 0x1D - reg;
- val = (reg & TWL6040_HF_VOL_MASK);
- if (handsfree->ramp == TWL6040_RAMP_UP) {
- /* ramp step up */
- if (val < handsfree->right_vol) {
- if (val + right_step > handsfree->right_vol)
- val = handsfree->right_vol;
- else
- val += right_step;
-
- reg &= ~TWL6040_HF_VOL_MASK;
- twl6040_write(codec, TWL6040_REG_HFRGAIN,
- reg | (0x1D - val));
- } else {
- right_complete = 1;
- }
- } else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
- /* ramp step down */
- if (val > 0) {
- if ((int)val - (int)right_step < 0)
- val = 0;
- else
- val -= right_step;
-
- reg &= ~TWL6040_HF_VOL_MASK;
- twl6040_write(codec, TWL6040_REG_HFRGAIN,
- reg | (0x1D - val));
- }
- }
-
- return left_complete & right_complete;
-}
-
-/*
- * This work ramps both output PGAs at stream start/stop time to
- * minimise pop associated with DAPM power switching.
- */
-static void twl6040_pga_hs_work(struct work_struct *work)
-{
- struct twl6040_data *priv =
- container_of(work, struct twl6040_data, headset.work.work);
- struct snd_soc_codec *codec = priv->codec;
- struct twl6040_output *headset = &priv->headset;
- int i, headset_complete;
-
- /* do we need to ramp at all ? */
- if (headset->ramp == TWL6040_RAMP_NONE)
- return;
-
- /* HS PGA gain range: 0x0 - 0xf (0 - 15) */
- for (i = 0; i < 16; i++) {
- headset_complete = twl6040_hs_ramp_step(codec,
- headset->left_step,
- headset->right_step);
-
- /* ramp finished ? */
- if (headset_complete)
- break;
-
- schedule_timeout_interruptible(
- msecs_to_jiffies(headset->step_delay));
- }
-
- if (headset->ramp == TWL6040_RAMP_DOWN) {
- headset->active = 0;
- complete(&headset->ramp_done);
- } else {
- headset->active = 1;
- }
- headset->ramp = TWL6040_RAMP_NONE;
-}
-
-static void twl6040_pga_hf_work(struct work_struct *work)
-{
- struct twl6040_data *priv =
- container_of(work, struct twl6040_data, handsfree.work.work);
- struct snd_soc_codec *codec = priv->codec;
- struct twl6040_output *handsfree = &priv->handsfree;
- int i, handsfree_complete;
-
- /* do we need to ramp at all ? */
- if (handsfree->ramp == TWL6040_RAMP_NONE)
- return;
-
- /*
- * HF PGA gain range: 0x00 - 0x1d (0 - 29) */
- for (i = 0; i < 30; i++) {
- handsfree_complete = twl6040_hf_ramp_step(codec,
- handsfree->left_step,
- handsfree->right_step);
-
- /* ramp finished ? */
- if (handsfree_complete)
- break;
-
- schedule_timeout_interruptible(
- msecs_to_jiffies(handsfree->step_delay));
- }
-
-
- if (handsfree->ramp == TWL6040_RAMP_DOWN) {
- handsfree->active = 0;
- complete(&handsfree->ramp_done);
- } else
- handsfree->active = 1;
- handsfree->ramp = TWL6040_RAMP_NONE;
-}
-
-static int out_drv_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
- struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
- struct twl6040_output *out;
- struct delayed_work *work;
-
- switch (w->shift) {
- case 2: /* Headset output driver */
- out = &priv->headset;
- work = &out->work;
- /*
- * Make sure, that we do not mess up variables for already
- * executing work.
- */
- cancel_delayed_work_sync(work);
-
- out->left_step = priv->hs_left_step;
- out->right_step = priv->hs_right_step;
- out->step_delay = 5; /* 5 ms between volume ramp steps */
- break;
- case 4: /* Handsfree output driver */
- out = &priv->handsfree;
- work = &out->work;
- /*
- * Make sure, that we do not mess up variables for already
- * executing work.
- */
- cancel_delayed_work_sync(work);
-
- out->left_step = priv->hf_left_step;
- out->right_step = priv->hf_right_step;
- out->step_delay = 5; /* 5 ms between volume ramp steps */
- break;
- default:
- return -1;
- }
-
- switch (event) {
- case SND_SOC_DAPM_POST_PMU:
- if (out->active)
- break;
-
- /* don't use volume ramp for power-up */
- out->ramp = TWL6040_RAMP_UP;
- out->left_step = out->left_vol;
- out->right_step = out->right_vol;
-
- queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1));
- break;
-
- case SND_SOC_DAPM_PRE_PMD:
- if (!out->active)
- break;
-
- /* use volume ramp for power-down */
- out->ramp = TWL6040_RAMP_DOWN;
- INIT_COMPLETION(out->ramp_done);
-
- queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1));
-
- wait_for_completion_timeout(&out->ramp_done,
- msecs_to_jiffies(2000));
- break;
- }
-
- return 0;
-}
-
/* set headset dac and driver power mode */
static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
{
@@ -747,71 +410,6 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data)
return IRQ_HANDLED;
}
-static int twl6040_put_volsw(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
- struct twl6040_output *out = NULL;
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- int ret;
-
- /* For HS and HF we shadow the values and only actually write
- * them out when active in order to ensure the amplifier comes on
- * as quietly as possible. */
- switch (mc->reg) {
- case TWL6040_REG_HSGAIN:
- out = &twl6040_priv->headset;
- break;
- case TWL6040_REG_HFLGAIN:
- out = &twl6040_priv->handsfree;
- break;
- default:
- dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n",
- __func__, mc->reg);
- return -EINVAL;
- }
-
- out->left_vol = ucontrol->value.integer.value[0];
- out->right_vol = ucontrol->value.integer.value[1];
- if (!out->active)
- return 1;
-
- ret = snd_soc_put_volsw(kcontrol, ucontrol);
- if (ret < 0)
- return ret;
-
- return 1;
-}
-
-static int twl6040_get_volsw(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
- struct twl6040_output *out = &twl6040_priv->headset;
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
-
- switch (mc->reg) {
- case TWL6040_REG_HSGAIN:
- out = &twl6040_priv->headset;
- break;
- case TWL6040_REG_HFLGAIN:
- out = &twl6040_priv->handsfree;
- break;
- default:
- dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n",
- __func__, mc->reg);
- return -EINVAL;
- }
-
- ucontrol->value.integer.value[0] = out->left_vol;
- ucontrol->value.integer.value[1] = out->right_vol;
- return 0;
-}
-
static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -1076,12 +674,10 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = {
TWL6040_REG_LINEGAIN, 0, 3, 7, 0, afm_amp_tlv),
/* Playback gains */
- SOC_DOUBLE_EXT_TLV("Headset Playback Volume",
- TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, twl6040_get_volsw,
- twl6040_put_volsw, hs_tlv),
- SOC_DOUBLE_R_EXT_TLV("Handsfree Playback Volume",
- TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1,
- twl6040_get_volsw, twl6040_put_volsw, hf_tlv),
+ SOC_DOUBLE_TLV("Headset Playback Volume",
+ TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
+ SOC_DOUBLE_R_TLV("Handsfree Playback Volume",
+ TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
SOC_SINGLE_TLV("Earphone Playback Volume",
TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
@@ -1180,22 +776,14 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
&auxr_switch_control),
/* Analog playback drivers */
- SND_SOC_DAPM_OUT_DRV_E("HF Left Driver",
- TWL6040_REG_HFLCTL, 4, 0, NULL, 0,
- out_drv_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_OUT_DRV_E("HF Right Driver",
- TWL6040_REG_HFRCTL, 4, 0, NULL, 0,
- out_drv_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_OUT_DRV_E("HS Left Driver",
- TWL6040_REG_HSLCTL, 2, 0, NULL, 0,
- out_drv_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_OUT_DRV_E("HS Right Driver",
- TWL6040_REG_HSRCTL, 2, 0, NULL, 0,
- out_drv_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_OUT_DRV("HF Left Driver",
+ TWL6040_REG_HFLCTL, 4, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("HF Right Driver",
+ TWL6040_REG_HFRCTL, 4, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("HS Left Driver",
+ TWL6040_REG_HSLCTL, 2, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("HS Right Driver",
+ TWL6040_REG_HSRCTL, 2, 0, NULL, 0),
SND_SOC_DAPM_OUT_DRV_E("Earphone Driver",
TWL6040_REG_EARCTL, 0, 0, NULL, 0,
twl6040_ep_drv_event,
@@ -1339,8 +927,7 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
static int twl6040_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
snd_pcm_hw_constraint_list(substream->runtime, 0,
@@ -1354,8 +941,7 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
int rate;
@@ -1391,8 +977,7 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
static int twl6040_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct twl6040 *twl6040 = codec->control_data;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
int ret;
@@ -1570,14 +1155,9 @@ static int twl6040_probe(struct snd_soc_codec *codec)
}
INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work);
- INIT_DELAYED_WORK(&priv->headset.work, twl6040_pga_hs_work);
- INIT_DELAYED_WORK(&priv->handsfree.work, twl6040_pga_hf_work);
mutex_init(&priv->mutex);
- init_completion(&priv->headset.ramp_done);
- init_completion(&priv->handsfree.ramp_done);
-
ret = request_threaded_irq(priv->plug_irq, NULL, twl6040_audio_handler,
0, "twl6040_irq_plug", codec);
if (ret) {
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index 797b0dde2c68..6c3d43b8ee85 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -159,8 +159,7 @@ static int uda134x_mute(struct snd_soc_dai *dai, int mute)
static int uda134x_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec =rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
struct snd_pcm_runtime *master_runtime;
@@ -191,8 +190,7 @@ static int uda134x_startup(struct snd_pcm_substream *substream,
static void uda134x_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
if (uda134x->master_substream == substream)
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 4f1b23d7e404..2502214b84ab 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -502,8 +502,7 @@ static int uda1380_set_dai_fmt_capture(struct snd_soc_dai *codec_dai,
static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec);
int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER);
@@ -528,8 +527,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
/* set WSPLL power and divider if running from this clock */
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index 3d868dc40092..7b24d6d192e1 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -293,8 +293,7 @@ static const struct snd_kcontrol_new wl1273_controls[] = {
static int wl1273_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
switch (wl1273->mode) {
@@ -329,8 +328,7 @@ static int wl1273_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(rtd->codec);
+ struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(dai->codec);
struct wl1273_core *core = wl1273->core;
unsigned int rate, width, r;
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c
index aefb4f89be0e..e0b51e9f8b12 100644
--- a/sound/soc/codecs/wm1250-ev1.c
+++ b/sound/soc/codecs/wm1250-ev1.c
@@ -79,22 +79,65 @@ static const struct snd_soc_dapm_route wm1250_ev1_dapm_routes[] = {
{ "WM1250 Output", NULL, "DAC" },
};
+static int wm1250_ev1_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct wm1250_priv *wm1250 = snd_soc_codec_get_drvdata(dai->codec);
+
+ switch (params_rate(params)) {
+ case 8000:
+ gpio_set_value(wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL0].gpio,
+ 1);
+ gpio_set_value(wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL1].gpio,
+ 1);
+ break;
+ case 16000:
+ gpio_set_value(wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL0].gpio,
+ 0);
+ gpio_set_value(wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL1].gpio,
+ 1);
+ break;
+ case 32000:
+ gpio_set_value(wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL0].gpio,
+ 1);
+ gpio_set_value(wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL1].gpio,
+ 0);
+ break;
+ case 64000:
+ gpio_set_value(wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL0].gpio,
+ 0);
+ gpio_set_value(wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL1].gpio,
+ 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops wm1250_ev1_ops = {
+ .hw_params = wm1250_ev1_hw_params,
+};
+
static struct snd_soc_dai_driver wm1250_ev1_dai = {
.name = "wm1250-ev1",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
- .channels_max = 1,
+ .channels_max = 2,
.rates = SNDRV_PCM_RATE_8000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
- .channels_max = 1,
+ .channels_max = 2,
.rates = SNDRV_PCM_RATE_8000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
+ .ops = &wm1250_ev1_ops,
};
static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = {
@@ -215,23 +258,7 @@ static struct i2c_driver wm1250_ev1_i2c_driver = {
.id_table = wm1250_ev1_i2c_id,
};
-static int __init wm1250_ev1_modinit(void)
-{
- int ret = 0;
-
- ret = i2c_add_driver(&wm1250_ev1_i2c_driver);
- if (ret != 0)
- pr_err("Failed to register WM1250-EV1 I2C driver: %d\n", ret);
-
- return ret;
-}
-module_init(wm1250_ev1_modinit);
-
-static void __exit wm1250_ev1_exit(void)
-{
- i2c_del_driver(&wm1250_ev1_i2c_driver);
-}
-module_exit(wm1250_ev1_exit);
+module_i2c_driver(wm1250_ev1_i2c_driver);
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_DESCRIPTION("WM1250-EV1 audio I/O module driver");
diff --git a/sound/soc/codecs/wm5100-tables.c b/sound/soc/codecs/wm5100-tables.c
index 9a18fae68204..e167207a19cc 100644
--- a/sound/soc/codecs/wm5100-tables.c
+++ b/sound/soc/codecs/wm5100-tables.c
@@ -32,7 +32,18 @@ bool wm5100_volatile_register(struct device *dev, unsigned int reg)
case WM5100_MIC_DETECT_3:
return 1;
default:
- return 0;
+ if ((reg >= WM5100_DSP1_PM_0 && reg <= WM5100_DSP1_PM_1535) ||
+ (reg >= WM5100_DSP1_ZM_0 && reg <= WM5100_DSP1_ZM_2047) ||
+ (reg >= WM5100_DSP1_DM_0 && reg <= WM5100_DSP1_DM_511) ||
+ (reg >= WM5100_DSP2_PM_0 && reg <= WM5100_DSP2_PM_1535) ||
+ (reg >= WM5100_DSP2_ZM_0 && reg <= WM5100_DSP2_ZM_2047) ||
+ (reg >= WM5100_DSP2_DM_0 && reg <= WM5100_DSP2_DM_511) ||
+ (reg >= WM5100_DSP3_PM_0 && reg <= WM5100_DSP3_PM_1535) ||
+ (reg >= WM5100_DSP3_ZM_0 && reg <= WM5100_DSP3_ZM_2047) ||
+ (reg >= WM5100_DSP3_DM_0 && reg <= WM5100_DSP3_DM_511))
+ return 1;
+ else
+ return 0;
}
}
@@ -697,9 +708,110 @@ bool wm5100_readable_register(struct device *dev, unsigned int reg)
case WM5100_HPLPF3_2:
case WM5100_HPLPF4_1:
case WM5100_HPLPF4_2:
+ case WM5100_DSP1_CONTROL_1:
+ case WM5100_DSP1_CONTROL_2:
+ case WM5100_DSP1_CONTROL_3:
+ case WM5100_DSP1_CONTROL_4:
+ case WM5100_DSP1_CONTROL_5:
+ case WM5100_DSP1_CONTROL_6:
+ case WM5100_DSP1_CONTROL_7:
+ case WM5100_DSP1_CONTROL_8:
+ case WM5100_DSP1_CONTROL_9:
+ case WM5100_DSP1_CONTROL_10:
+ case WM5100_DSP1_CONTROL_11:
+ case WM5100_DSP1_CONTROL_12:
+ case WM5100_DSP1_CONTROL_13:
+ case WM5100_DSP1_CONTROL_14:
+ case WM5100_DSP1_CONTROL_15:
+ case WM5100_DSP1_CONTROL_16:
+ case WM5100_DSP1_CONTROL_17:
+ case WM5100_DSP1_CONTROL_18:
+ case WM5100_DSP1_CONTROL_19:
+ case WM5100_DSP1_CONTROL_20:
+ case WM5100_DSP1_CONTROL_21:
+ case WM5100_DSP1_CONTROL_22:
+ case WM5100_DSP1_CONTROL_23:
+ case WM5100_DSP1_CONTROL_24:
+ case WM5100_DSP1_CONTROL_25:
+ case WM5100_DSP1_CONTROL_26:
+ case WM5100_DSP1_CONTROL_27:
+ case WM5100_DSP1_CONTROL_28:
+ case WM5100_DSP1_CONTROL_29:
+ case WM5100_DSP1_CONTROL_30:
+ case WM5100_DSP2_CONTROL_1:
+ case WM5100_DSP2_CONTROL_2:
+ case WM5100_DSP2_CONTROL_3:
+ case WM5100_DSP2_CONTROL_4:
+ case WM5100_DSP2_CONTROL_5:
+ case WM5100_DSP2_CONTROL_6:
+ case WM5100_DSP2_CONTROL_7:
+ case WM5100_DSP2_CONTROL_8:
+ case WM5100_DSP2_CONTROL_9:
+ case WM5100_DSP2_CONTROL_10:
+ case WM5100_DSP2_CONTROL_11:
+ case WM5100_DSP2_CONTROL_12:
+ case WM5100_DSP2_CONTROL_13:
+ case WM5100_DSP2_CONTROL_14:
+ case WM5100_DSP2_CONTROL_15:
+ case WM5100_DSP2_CONTROL_16:
+ case WM5100_DSP2_CONTROL_17:
+ case WM5100_DSP2_CONTROL_18:
+ case WM5100_DSP2_CONTROL_19:
+ case WM5100_DSP2_CONTROL_20:
+ case WM5100_DSP2_CONTROL_21:
+ case WM5100_DSP2_CONTROL_22:
+ case WM5100_DSP2_CONTROL_23:
+ case WM5100_DSP2_CONTROL_24:
+ case WM5100_DSP2_CONTROL_25:
+ case WM5100_DSP2_CONTROL_26:
+ case WM5100_DSP2_CONTROL_27:
+ case WM5100_DSP2_CONTROL_28:
+ case WM5100_DSP2_CONTROL_29:
+ case WM5100_DSP2_CONTROL_30:
+ case WM5100_DSP3_CONTROL_1:
+ case WM5100_DSP3_CONTROL_2:
+ case WM5100_DSP3_CONTROL_3:
+ case WM5100_DSP3_CONTROL_4:
+ case WM5100_DSP3_CONTROL_5:
+ case WM5100_DSP3_CONTROL_6:
+ case WM5100_DSP3_CONTROL_7:
+ case WM5100_DSP3_CONTROL_8:
+ case WM5100_DSP3_CONTROL_9:
+ case WM5100_DSP3_CONTROL_10:
+ case WM5100_DSP3_CONTROL_11:
+ case WM5100_DSP3_CONTROL_12:
+ case WM5100_DSP3_CONTROL_13:
+ case WM5100_DSP3_CONTROL_14:
+ case WM5100_DSP3_CONTROL_15:
+ case WM5100_DSP3_CONTROL_16:
+ case WM5100_DSP3_CONTROL_17:
+ case WM5100_DSP3_CONTROL_18:
+ case WM5100_DSP3_CONTROL_19:
+ case WM5100_DSP3_CONTROL_20:
+ case WM5100_DSP3_CONTROL_21:
+ case WM5100_DSP3_CONTROL_22:
+ case WM5100_DSP3_CONTROL_23:
+ case WM5100_DSP3_CONTROL_24:
+ case WM5100_DSP3_CONTROL_25:
+ case WM5100_DSP3_CONTROL_26:
+ case WM5100_DSP3_CONTROL_27:
+ case WM5100_DSP3_CONTROL_28:
+ case WM5100_DSP3_CONTROL_29:
+ case WM5100_DSP3_CONTROL_30:
return 1;
default:
- return 0;
+ if ((reg >= WM5100_DSP1_PM_0 && reg <= WM5100_DSP1_PM_1535) ||
+ (reg >= WM5100_DSP1_ZM_0 && reg <= WM5100_DSP1_ZM_2047) ||
+ (reg >= WM5100_DSP1_DM_0 && reg <= WM5100_DSP1_DM_511) ||
+ (reg >= WM5100_DSP2_PM_0 && reg <= WM5100_DSP2_PM_1535) ||
+ (reg >= WM5100_DSP2_ZM_0 && reg <= WM5100_DSP2_ZM_2047) ||
+ (reg >= WM5100_DSP2_DM_0 && reg <= WM5100_DSP2_DM_511) ||
+ (reg >= WM5100_DSP3_PM_0 && reg <= WM5100_DSP3_PM_1535) ||
+ (reg >= WM5100_DSP3_ZM_0 && reg <= WM5100_DSP3_ZM_2047) ||
+ (reg >= WM5100_DSP3_DM_0 && reg <= WM5100_DSP3_DM_511))
+ return 1;
+ else
+ return 0;
}
}
@@ -1361,4 +1473,13 @@ struct reg_default wm5100_reg_defaults[WM5100_REGISTER_COUNT] = {
{ 0x0EC9, 0x0000 }, /* R3785 - HPLPF3_2 */
{ 0x0ECC, 0x0000 }, /* R3788 - HPLPF4_1 */
{ 0x0ECD, 0x0000 }, /* R3789 - HPLPF4_2 */
+ { 0x0F02, 0x0000 }, /* R3842 - DSP1 Control 2 */
+ { 0x0F03, 0x0000 }, /* R3843 - DSP1 Control 3 */
+ { 0x0F04, 0x0000 }, /* R3844 - DSP1 Control 4 */
+ { 0x1002, 0x0000 }, /* R4098 - DSP2 Control 2 */
+ { 0x1003, 0x0000 }, /* R4099 - DSP2 Control 3 */
+ { 0x1004, 0x0000 }, /* R4100 - DSP2 Control 4 */
+ { 0x1102, 0x0000 }, /* R4354 - DSP3 Control 2 */
+ { 0x1103, 0x0000 }, /* R4355 - DSP3 Control 3 */
+ { 0x1104, 0x0000 }, /* R4356 - DSP3 Control 4 */
};
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index b9c185ce64e4..cb6d5372103a 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -1265,29 +1265,12 @@ static const __devinitdata struct reg_default wm5100_reva_patches[] = {
{ WM5100_AUDIO_IF_3_19, 1 },
};
-static int wm5100_dai_to_base(struct snd_soc_dai *dai)
-{
- switch (dai->id) {
- case 0:
- return WM5100_AUDIO_IF_1_1 - 1;
- case 1:
- return WM5100_AUDIO_IF_2_1 - 1;
- case 2:
- return WM5100_AUDIO_IF_3_1 - 1;
- default:
- BUG();
- return -EINVAL;
- }
-}
-
static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_codec *codec = dai->codec;
int lrclk, bclk, mask, base;
- base = wm5100_dai_to_base(dai);
- if (base < 0)
- return base;
+ base = dai->driver->base;
lrclk = 0;
bclk = 0;
@@ -1414,9 +1397,7 @@ static int wm5100_hw_params(struct snd_pcm_substream *substream,
int i, base, bclk, aif_rate, lrclk, wl, fl, sr;
int *bclk_rates;
- base = wm5100_dai_to_base(dai);
- if (base < 0)
- return base;
+ base = dai->driver->base;
/* Data sizes if not using TDM */
wl = snd_pcm_format_width(params_format(params));
@@ -1897,6 +1878,7 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
static struct snd_soc_dai_driver wm5100_dai[] = {
{
.name = "wm5100-aif1",
+ .base = WM5100_AUDIO_IF_1_1 - 1,
.playback = {
.stream_name = "AIF1 Playback",
.channels_min = 2,
@@ -1916,6 +1898,7 @@ static struct snd_soc_dai_driver wm5100_dai[] = {
{
.name = "wm5100-aif2",
.id = 1,
+ .base = WM5100_AUDIO_IF_2_1 - 1,
.playback = {
.stream_name = "AIF2 Playback",
.channels_min = 2,
@@ -1935,6 +1918,7 @@ static struct snd_soc_dai_driver wm5100_dai[] = {
{
.name = "wm5100-aif3",
.id = 2,
+ .base = WM5100_AUDIO_IF_3_1 - 1,
.playback = {
.stream_name = "AIF3 Playback",
.channels_min = 2,
@@ -2454,7 +2438,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
wm5100->dev = &i2c->dev;
- wm5100->regmap = regmap_init_i2c(i2c, &wm5100_regmap);
+ wm5100->regmap = devm_regmap_init_i2c(i2c, &wm5100_regmap);
if (IS_ERR(wm5100->regmap)) {
ret = PTR_ERR(wm5100->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -2479,7 +2463,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
if (ret != 0) {
dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
ret);
- goto err_regmap;
+ goto err;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
@@ -2487,7 +2471,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
ret);
- goto err_regmap;
+ goto err;
}
if (wm5100->pdata.ldo_ena) {
@@ -2660,8 +2644,6 @@ err_ldo:
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
wm5100->core_supplies);
-err_regmap:
- regmap_exit(wm5100->regmap);
err:
return ret;
}
@@ -2682,7 +2664,6 @@ static __devexit int wm5100_i2c_remove(struct i2c_client *i2c)
gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
gpio_free(wm5100->pdata.ldo_ena);
}
- regmap_exit(wm5100->regmap);
return 0;
}
@@ -2749,17 +2730,7 @@ static struct i2c_driver wm5100_i2c_driver = {
.id_table = wm5100_i2c_id,
};
-static int __init wm5100_modinit(void)
-{
- return i2c_add_driver(&wm5100_i2c_driver);
-}
-module_init(wm5100_modinit);
-
-static void __exit wm5100_exit(void)
-{
- i2c_del_driver(&wm5100_i2c_driver);
-}
-module_exit(wm5100_exit);
+module_i2c_driver(wm5100_i2c_driver);
MODULE_DESCRIPTION("ASoC WM5100 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm5100.h b/sound/soc/codecs/wm5100.h
index 25cb6016f9d7..935a9b7fb274 100644
--- a/sound/soc/codecs/wm5100.h
+++ b/sound/soc/codecs/wm5100.h
@@ -709,6 +709,96 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
#define WM5100_HPLPF3_2 0xEC9
#define WM5100_HPLPF4_1 0xECC
#define WM5100_HPLPF4_2 0xECD
+#define WM5100_DSP1_CONTROL_1 0xF00
+#define WM5100_DSP1_CONTROL_2 0xF02
+#define WM5100_DSP1_CONTROL_3 0xF03
+#define WM5100_DSP1_CONTROL_4 0xF04
+#define WM5100_DSP1_CONTROL_5 0xF06
+#define WM5100_DSP1_CONTROL_6 0xF07
+#define WM5100_DSP1_CONTROL_7 0xF08
+#define WM5100_DSP1_CONTROL_8 0xF09
+#define WM5100_DSP1_CONTROL_9 0xF0A
+#define WM5100_DSP1_CONTROL_10 0xF0B
+#define WM5100_DSP1_CONTROL_11 0xF0C
+#define WM5100_DSP1_CONTROL_12 0xF0D
+#define WM5100_DSP1_CONTROL_13 0xF0F
+#define WM5100_DSP1_CONTROL_14 0xF10
+#define WM5100_DSP1_CONTROL_15 0xF11
+#define WM5100_DSP1_CONTROL_16 0xF12
+#define WM5100_DSP1_CONTROL_17 0xF13
+#define WM5100_DSP1_CONTROL_18 0xF14
+#define WM5100_DSP1_CONTROL_19 0xF16
+#define WM5100_DSP1_CONTROL_20 0xF17
+#define WM5100_DSP1_CONTROL_21 0xF18
+#define WM5100_DSP1_CONTROL_22 0xF1A
+#define WM5100_DSP1_CONTROL_23 0xF1B
+#define WM5100_DSP1_CONTROL_24 0xF1C
+#define WM5100_DSP1_CONTROL_25 0xF1E
+#define WM5100_DSP1_CONTROL_26 0xF20
+#define WM5100_DSP1_CONTROL_27 0xF21
+#define WM5100_DSP1_CONTROL_28 0xF22
+#define WM5100_DSP1_CONTROL_29 0xF23
+#define WM5100_DSP1_CONTROL_30 0xF24
+#define WM5100_DSP2_CONTROL_1 0x1000
+#define WM5100_DSP2_CONTROL_2 0x1002
+#define WM5100_DSP2_CONTROL_3 0x1003
+#define WM5100_DSP2_CONTROL_4 0x1004
+#define WM5100_DSP2_CONTROL_5 0x1006
+#define WM5100_DSP2_CONTROL_6 0x1007
+#define WM5100_DSP2_CONTROL_7 0x1008
+#define WM5100_DSP2_CONTROL_8 0x1009
+#define WM5100_DSP2_CONTROL_9 0x100A
+#define WM5100_DSP2_CONTROL_10 0x100B
+#define WM5100_DSP2_CONTROL_11 0x100C
+#define WM5100_DSP2_CONTROL_12 0x100D
+#define WM5100_DSP2_CONTROL_13 0x100F
+#define WM5100_DSP2_CONTROL_14 0x1010
+#define WM5100_DSP2_CONTROL_15 0x1011
+#define WM5100_DSP2_CONTROL_16 0x1012
+#define WM5100_DSP2_CONTROL_17 0x1013
+#define WM5100_DSP2_CONTROL_18 0x1014
+#define WM5100_DSP2_CONTROL_19 0x1016
+#define WM5100_DSP2_CONTROL_20 0x1017
+#define WM5100_DSP2_CONTROL_21 0x1018
+#define WM5100_DSP2_CONTROL_22 0x101A
+#define WM5100_DSP2_CONTROL_23 0x101B
+#define WM5100_DSP2_CONTROL_24 0x101C
+#define WM5100_DSP2_CONTROL_25 0x101E
+#define WM5100_DSP2_CONTROL_26 0x1020
+#define WM5100_DSP2_CONTROL_27 0x1021
+#define WM5100_DSP2_CONTROL_28 0x1022
+#define WM5100_DSP2_CONTROL_29 0x1023
+#define WM5100_DSP2_CONTROL_30 0x1024
+#define WM5100_DSP3_CONTROL_1 0x1100
+#define WM5100_DSP3_CONTROL_2 0x1102
+#define WM5100_DSP3_CONTROL_3 0x1103
+#define WM5100_DSP3_CONTROL_4 0x1104
+#define WM5100_DSP3_CONTROL_5 0x1106
+#define WM5100_DSP3_CONTROL_6 0x1107
+#define WM5100_DSP3_CONTROL_7 0x1108
+#define WM5100_DSP3_CONTROL_8 0x1109
+#define WM5100_DSP3_CONTROL_9 0x110A
+#define WM5100_DSP3_CONTROL_10 0x110B
+#define WM5100_DSP3_CONTROL_11 0x110C
+#define WM5100_DSP3_CONTROL_12 0x110D
+#define WM5100_DSP3_CONTROL_13 0x110F
+#define WM5100_DSP3_CONTROL_14 0x1110
+#define WM5100_DSP3_CONTROL_15 0x1111
+#define WM5100_DSP3_CONTROL_16 0x1112
+#define WM5100_DSP3_CONTROL_17 0x1113
+#define WM5100_DSP3_CONTROL_18 0x1114
+#define WM5100_DSP3_CONTROL_19 0x1116
+#define WM5100_DSP3_CONTROL_20 0x1117
+#define WM5100_DSP3_CONTROL_21 0x1118
+#define WM5100_DSP3_CONTROL_22 0x111A
+#define WM5100_DSP3_CONTROL_23 0x111B
+#define WM5100_DSP3_CONTROL_24 0x111C
+#define WM5100_DSP3_CONTROL_25 0x111E
+#define WM5100_DSP3_CONTROL_26 0x1120
+#define WM5100_DSP3_CONTROL_27 0x1121
+#define WM5100_DSP3_CONTROL_28 0x1122
+#define WM5100_DSP3_CONTROL_29 0x1123
+#define WM5100_DSP3_CONTROL_30 0x1124
#define WM5100_DSP1_DM_0 0x4000
#define WM5100_DSP1_DM_1 0x4001
#define WM5100_DSP1_DM_2 0x4002
@@ -4561,6 +4651,75 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
#define WM5100_LHPF4_COEFF_WIDTH 16 /* LHPF4_COEFF - [15:0] */
/*
+ * R4132 (0x1024) - DSP2 Control 30
+ */
+#define WM5100_DSP2_RATE_MASK 0xC000 /* DSP2_RATE - [15:14] */
+#define WM5100_DSP2_RATE_SHIFT 14 /* DSP2_RATE - [15:14] */
+#define WM5100_DSP2_RATE_WIDTH 2 /* DSP2_RATE - [15:14] */
+#define WM5100_DSP2_DBG_CLK_ENA 0x0008 /* DSP2_DBG_CLK_ENA */
+#define WM5100_DSP2_DBG_CLK_ENA_MASK 0x0008 /* DSP2_DBG_CLK_ENA */
+#define WM5100_DSP2_DBG_CLK_ENA_SHIFT 3 /* DSP2_DBG_CLK_ENA */
+#define WM5100_DSP2_DBG_CLK_ENA_WIDTH 1 /* DSP2_DBG_CLK_ENA */
+#define WM5100_DSP2_SYS_ENA 0x0004 /* DSP2_SYS_ENA */
+#define WM5100_DSP2_SYS_ENA_MASK 0x0004 /* DSP2_SYS_ENA */
+#define WM5100_DSP2_SYS_ENA_SHIFT 2 /* DSP2_SYS_ENA */
+#define WM5100_DSP2_SYS_ENA_WIDTH 1 /* DSP2_SYS_ENA */
+#define WM5100_DSP2_CORE_ENA 0x0002 /* DSP2_CORE_ENA */
+#define WM5100_DSP2_CORE_ENA_MASK 0x0002 /* DSP2_CORE_ENA */
+#define WM5100_DSP2_CORE_ENA_SHIFT 1 /* DSP2_CORE_ENA */
+#define WM5100_DSP2_CORE_ENA_WIDTH 1 /* DSP2_CORE_ENA */
+#define WM5100_DSP2_START 0x0001 /* DSP2_START */
+#define WM5100_DSP2_START_MASK 0x0001 /* DSP2_START */
+#define WM5100_DSP2_START_SHIFT 0 /* DSP2_START */
+#define WM5100_DSP2_START_WIDTH 1 /* DSP2_START */
+
+/*
+ * R3876 (0xF24) - DSP1 Control 30
+ */
+#define WM5100_DSP1_RATE_MASK 0xC000 /* DSP1_RATE - [15:14] */
+#define WM5100_DSP1_RATE_SHIFT 14 /* DSP1_RATE - [15:14] */
+#define WM5100_DSP1_RATE_WIDTH 2 /* DSP1_RATE - [15:14] */
+#define WM5100_DSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */
+#define WM5100_DSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */
+#define WM5100_DSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */
+#define WM5100_DSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */
+#define WM5100_DSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */
+#define WM5100_DSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */
+#define WM5100_DSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */
+#define WM5100_DSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */
+#define WM5100_DSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */
+#define WM5100_DSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */
+#define WM5100_DSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */
+#define WM5100_DSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */
+#define WM5100_DSP1_START 0x0001 /* DSP1_START */
+#define WM5100_DSP1_START_MASK 0x0001 /* DSP1_START */
+#define WM5100_DSP1_START_SHIFT 0 /* DSP1_START */
+#define WM5100_DSP1_START_WIDTH 1 /* DSP1_START */
+
+/*
+ * R4388 (0x1124) - DSP3 Control 30
+ */
+#define WM5100_DSP3_RATE_MASK 0xC000 /* DSP3_RATE - [15:14] */
+#define WM5100_DSP3_RATE_SHIFT 14 /* DSP3_RATE - [15:14] */
+#define WM5100_DSP3_RATE_WIDTH 2 /* DSP3_RATE - [15:14] */
+#define WM5100_DSP3_DBG_CLK_ENA 0x0008 /* DSP3_DBG_CLK_ENA */
+#define WM5100_DSP3_DBG_CLK_ENA_MASK 0x0008 /* DSP3_DBG_CLK_ENA */
+#define WM5100_DSP3_DBG_CLK_ENA_SHIFT 3 /* DSP3_DBG_CLK_ENA */
+#define WM5100_DSP3_DBG_CLK_ENA_WIDTH 1 /* DSP3_DBG_CLK_ENA */
+#define WM5100_DSP3_SYS_ENA 0x0004 /* DSP3_SYS_ENA */
+#define WM5100_DSP3_SYS_ENA_MASK 0x0004 /* DSP3_SYS_ENA */
+#define WM5100_DSP3_SYS_ENA_SHIFT 2 /* DSP3_SYS_ENA */
+#define WM5100_DSP3_SYS_ENA_WIDTH 1 /* DSP3_SYS_ENA */
+#define WM5100_DSP3_CORE_ENA 0x0002 /* DSP3_CORE_ENA */
+#define WM5100_DSP3_CORE_ENA_MASK 0x0002 /* DSP3_CORE_ENA */
+#define WM5100_DSP3_CORE_ENA_SHIFT 1 /* DSP3_CORE_ENA */
+#define WM5100_DSP3_CORE_ENA_WIDTH 1 /* DSP3_CORE_ENA */
+#define WM5100_DSP3_START 0x0001 /* DSP3_START */
+#define WM5100_DSP3_START_MASK 0x0001 /* DSP3_START */
+#define WM5100_DSP3_START_SHIFT 0 /* DSP3_START */
+#define WM5100_DSP3_START_WIDTH 1 /* DSP3_START */
+
+/*
* R16384 (0x4000) - DSP1 DM 0
*/
#define WM5100_DSP1_DM_START_1_MASK 0x00FF /* DSP1_DM_START - [7:0] */
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index aa12c6b6beeb..555ee146ae0d 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -71,13 +71,6 @@ struct wm8350_data {
int fll_freq_in;
};
-static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- struct wm8350 *wm8350 = codec->control_data;
- return wm8350->reg_cache[reg];
-}
-
static unsigned int wm8350_codec_read(struct snd_soc_codec *codec,
unsigned int reg)
{
@@ -99,7 +92,7 @@ static inline int wm8350_out1_ramp_step(struct snd_soc_codec *codec)
{
struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec);
struct wm8350_output *out1 = &wm8350_data->out1;
- struct wm8350 *wm8350 = codec->control_data;
+ struct wm8350 *wm8350 = wm8350_data->wm8350;
int left_complete = 0, right_complete = 0;
u16 reg, val;
@@ -165,7 +158,7 @@ static inline int wm8350_out2_ramp_step(struct snd_soc_codec *codec)
{
struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec);
struct wm8350_output *out2 = &wm8350_data->out2;
- struct wm8350 *wm8350 = codec->control_data;
+ struct wm8350 *wm8350 = wm8350_data->wm8350;
int left_complete = 0, right_complete = 0;
u16 reg, val;
@@ -360,8 +353,8 @@ static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
return ret;
/* now hit the volume update bits (always bit 8) */
- val = wm8350_codec_read(codec, reg);
- wm8350_codec_write(codec, reg, val | WM8350_OUT1_VU);
+ val = snd_soc_read(codec, reg);
+ snd_soc_write(codec, reg, val | WM8350_OUT1_VU);
return 1;
}
@@ -781,7 +774,8 @@ static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
- struct wm8350 *wm8350 = codec->control_data;
+ struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec);
+ struct wm8350 *wm8350 = wm8350_data->wm8350;
u16 fll_4;
switch (clk_id) {
@@ -795,9 +789,9 @@ static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
case WM8350_MCLK_SEL_PLL_32K:
wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_1,
WM8350_MCLK_SEL);
- fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) &
+ fll_4 = snd_soc_read(codec, WM8350_FLL_CONTROL_4) &
~WM8350_FLL_CLK_SRC_MASK;
- wm8350_codec_write(codec, WM8350_FLL_CONTROL_4, fll_4 | clk_id);
+ snd_soc_write(codec, WM8350_FLL_CONTROL_4, fll_4 | clk_id);
break;
}
@@ -819,39 +813,39 @@ static int wm8350_set_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div)
switch (div_id) {
case WM8350_ADC_CLKDIV:
- val = wm8350_codec_read(codec, WM8350_ADC_DIVIDER) &
+ val = snd_soc_read(codec, WM8350_ADC_DIVIDER) &
~WM8350_ADC_CLKDIV_MASK;
- wm8350_codec_write(codec, WM8350_ADC_DIVIDER, val | div);
+ snd_soc_write(codec, WM8350_ADC_DIVIDER, val | div);
break;
case WM8350_DAC_CLKDIV:
- val = wm8350_codec_read(codec, WM8350_DAC_CLOCK_CONTROL) &
+ val = snd_soc_read(codec, WM8350_DAC_CLOCK_CONTROL) &
~WM8350_DAC_CLKDIV_MASK;
- wm8350_codec_write(codec, WM8350_DAC_CLOCK_CONTROL, val | div);
+ snd_soc_write(codec, WM8350_DAC_CLOCK_CONTROL, val | div);
break;
case WM8350_BCLK_CLKDIV:
- val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) &
+ val = snd_soc_read(codec, WM8350_CLOCK_CONTROL_1) &
~WM8350_BCLK_DIV_MASK;
- wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
+ snd_soc_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
break;
case WM8350_OPCLK_CLKDIV:
- val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) &
+ val = snd_soc_read(codec, WM8350_CLOCK_CONTROL_1) &
~WM8350_OPCLK_DIV_MASK;
- wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
+ snd_soc_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
break;
case WM8350_SYS_CLKDIV:
- val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) &
+ val = snd_soc_read(codec, WM8350_CLOCK_CONTROL_1) &
~WM8350_MCLK_DIV_MASK;
- wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
+ snd_soc_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
break;
case WM8350_DACLR_CLKDIV:
- val = wm8350_codec_read(codec, WM8350_DAC_LR_RATE) &
+ val = snd_soc_read(codec, WM8350_DAC_LR_RATE) &
~WM8350_DACLRC_RATE_MASK;
- wm8350_codec_write(codec, WM8350_DAC_LR_RATE, val | div);
+ snd_soc_write(codec, WM8350_DAC_LR_RATE, val | div);
break;
case WM8350_ADCLR_CLKDIV:
- val = wm8350_codec_read(codec, WM8350_ADC_LR_RATE) &
+ val = snd_soc_read(codec, WM8350_ADC_LR_RATE) &
~WM8350_ADCLRC_RATE_MASK;
- wm8350_codec_write(codec, WM8350_ADC_LR_RATE, val | div);
+ snd_soc_write(codec, WM8350_ADC_LR_RATE, val | div);
break;
default:
return -EINVAL;
@@ -863,13 +857,13 @@ static int wm8350_set_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div)
static int wm8350_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
- u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) &
+ u16 iface = snd_soc_read(codec, WM8350_AI_FORMATING) &
~(WM8350_AIF_BCLK_INV | WM8350_AIF_LRCLK_INV | WM8350_AIF_FMT_MASK);
- u16 master = wm8350_codec_read(codec, WM8350_AI_DAC_CONTROL) &
+ u16 master = snd_soc_read(codec, WM8350_AI_DAC_CONTROL) &
~WM8350_BCLK_MSTR;
- u16 dac_lrc = wm8350_codec_read(codec, WM8350_DAC_LR_RATE) &
+ u16 dac_lrc = snd_soc_read(codec, WM8350_DAC_LR_RATE) &
~WM8350_DACLRC_ENA;
- u16 adc_lrc = wm8350_codec_read(codec, WM8350_ADC_LR_RATE) &
+ u16 adc_lrc = snd_soc_read(codec, WM8350_ADC_LR_RATE) &
~WM8350_ADCLRC_ENA;
/* set master/slave audio interface */
@@ -922,42 +916,10 @@ static int wm8350_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
return -EINVAL;
}
- wm8350_codec_write(codec, WM8350_AI_FORMATING, iface);
- wm8350_codec_write(codec, WM8350_AI_DAC_CONTROL, master);
- wm8350_codec_write(codec, WM8350_DAC_LR_RATE, dac_lrc);
- wm8350_codec_write(codec, WM8350_ADC_LR_RATE, adc_lrc);
- return 0;
-}
-
-static int wm8350_pcm_trigger(struct snd_pcm_substream *substream,
- int cmd, struct snd_soc_dai *codec_dai)
-{
- struct snd_soc_codec *codec = codec_dai->codec;
- int master = wm8350_codec_cache_read(codec, WM8350_AI_DAC_CONTROL) &
- WM8350_BCLK_MSTR;
- int enabled = 0;
-
- /* Check that the DACs or ADCs are enabled since they are
- * required for LRC in master mode. The DACs or ADCs need a
- * valid audio path i.e. pin -> ADC or DAC -> pin before
- * the LRC will be enabled in master mode. */
- if (!master || cmd != SNDRV_PCM_TRIGGER_START)
- return 0;
-
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- enabled = wm8350_codec_cache_read(codec, WM8350_POWER_MGMT_4) &
- (WM8350_ADCR_ENA | WM8350_ADCL_ENA);
- } else {
- enabled = wm8350_codec_cache_read(codec, WM8350_POWER_MGMT_4) &
- (WM8350_DACR_ENA | WM8350_DACL_ENA);
- }
-
- if (!enabled) {
- dev_err(codec->dev,
- "%s: invalid audio path - no clocks available\n",
- __func__);
- return -EINVAL;
- }
+ snd_soc_write(codec, WM8350_AI_FORMATING, iface);
+ snd_soc_write(codec, WM8350_AI_DAC_CONTROL, master);
+ snd_soc_write(codec, WM8350_DAC_LR_RATE, dac_lrc);
+ snd_soc_write(codec, WM8350_ADC_LR_RATE, adc_lrc);
return 0;
}
@@ -966,8 +928,9 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai)
{
struct snd_soc_codec *codec = codec_dai->codec;
- struct wm8350 *wm8350 = codec->control_data;
- u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) &
+ struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec);
+ struct wm8350 *wm8350 = wm8350_data->wm8350;
+ u16 iface = snd_soc_read(codec, WM8350_AI_FORMATING) &
~WM8350_AIF_WL_MASK;
/* bit size */
@@ -985,7 +948,7 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
break;
}
- wm8350_codec_write(codec, WM8350_AI_FORMATING, iface);
+ snd_soc_write(codec, WM8350_AI_FORMATING, iface);
/* The sloping stopband filter is recommended for use with
* lower sample rates to improve performance.
@@ -1005,12 +968,15 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
static int wm8350_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
- struct wm8350 *wm8350 = codec->control_data;
+ unsigned int val;
if (mute)
- wm8350_set_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA);
+ val = WM8350_DAC_MUTE_ENA;
else
- wm8350_clear_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA);
+ val = 0;
+
+ snd_soc_update_bits(codec, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA, val);
+
return 0;
}
@@ -1079,8 +1045,8 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
unsigned int freq_out)
{
struct snd_soc_codec *codec = codec_dai->codec;
- struct wm8350 *wm8350 = codec->control_data;
struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec);
+ struct wm8350 *wm8350 = priv->wm8350;
struct _fll_div fll_div;
int ret = 0;
u16 fll_1, fll_4;
@@ -1104,17 +1070,17 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
fll_div.ratio);
/* set up N.K & dividers */
- fll_1 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_1) &
+ fll_1 = snd_soc_read(codec, WM8350_FLL_CONTROL_1) &
~(WM8350_FLL_OUTDIV_MASK | WM8350_FLL_RSP_RATE_MASK | 0xc000);
- wm8350_codec_write(codec, WM8350_FLL_CONTROL_1,
+ snd_soc_write(codec, WM8350_FLL_CONTROL_1,
fll_1 | (fll_div.div << 8) | 0x50);
- wm8350_codec_write(codec, WM8350_FLL_CONTROL_2,
+ snd_soc_write(codec, WM8350_FLL_CONTROL_2,
(fll_div.ratio << 11) | (fll_div.
n & WM8350_FLL_N_MASK));
- wm8350_codec_write(codec, WM8350_FLL_CONTROL_3, fll_div.k);
- fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) &
+ snd_soc_write(codec, WM8350_FLL_CONTROL_3, fll_div.k);
+ fll_4 = snd_soc_read(codec, WM8350_FLL_CONTROL_4) &
~(WM8350_FLL_FRAC | WM8350_FLL_SLOW_LOCK_REF);
- wm8350_codec_write(codec, WM8350_FLL_CONTROL_4,
+ snd_soc_write(codec, WM8350_FLL_CONTROL_4,
fll_4 | (fll_div.k ? WM8350_FLL_FRAC : 0) |
(fll_div.ratio == 8 ? WM8350_FLL_SLOW_LOCK_REF : 0));
@@ -1131,8 +1097,8 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
static int wm8350_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- struct wm8350 *wm8350 = codec->control_data;
struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec);
+ struct wm8350 *wm8350 = priv->wm8350;
struct wm8350_audio_platform_data *platform =
wm8350->codec.platform_data;
u16 pm1;
@@ -1339,35 +1305,36 @@ static void wm8350_hpr_work(struct work_struct *work)
wm8350_hp_work(priv, &priv->hpr, WM8350_JACK_R_LVL);
}
-static irqreturn_t wm8350_hp_jack_handler(int irq, void *data)
+static irqreturn_t wm8350_hpl_jack_handler(int irq, void *data)
{
struct wm8350_data *priv = data;
struct wm8350 *wm8350 = priv->wm8350;
- struct wm8350_jack_data *jack = NULL;
- switch (irq - wm8350->irq_base) {
- case WM8350_IRQ_CODEC_JCK_DET_L:
#ifndef CONFIG_SND_SOC_WM8350_MODULE
- trace_snd_soc_jack_irq("WM8350 HPL");
+ trace_snd_soc_jack_irq("WM8350 HPL");
#endif
- jack = &priv->hpl;
- break;
- case WM8350_IRQ_CODEC_JCK_DET_R:
+ if (device_may_wakeup(wm8350->dev))
+ pm_wakeup_event(wm8350->dev, 250);
+
+ schedule_delayed_work(&priv->hpl.work, 200);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t wm8350_hpr_jack_handler(int irq, void *data)
+{
+ struct wm8350_data *priv = data;
+ struct wm8350 *wm8350 = priv->wm8350;
+
#ifndef CONFIG_SND_SOC_WM8350_MODULE
- trace_snd_soc_jack_irq("WM8350 HPR");
+ trace_snd_soc_jack_irq("WM8350 HPR");
#endif
- jack = &priv->hpr;
- break;
-
- default:
- BUG();
- }
if (device_may_wakeup(wm8350->dev))
pm_wakeup_event(wm8350->dev, 250);
- schedule_delayed_work(&jack->work, 200);
+ schedule_delayed_work(&priv->hpr.work, 200);
return IRQ_HANDLED;
}
@@ -1387,7 +1354,7 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
struct snd_soc_jack *jack, int report)
{
struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec);
- struct wm8350 *wm8350 = codec->control_data;
+ struct wm8350 *wm8350 = priv->wm8350;
int irq;
int ena;
@@ -1418,7 +1385,14 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
}
/* Sync status */
- wm8350_hp_jack_handler(irq + wm8350->irq_base, priv);
+ switch (which) {
+ case WM8350_JDL:
+ wm8350_hpl_jack_handler(0, priv);
+ break;
+ case WM8350_JDR:
+ wm8350_hpr_jack_handler(0, priv);
+ break;
+ }
return 0;
}
@@ -1463,7 +1437,7 @@ int wm8350_mic_jack_detect(struct snd_soc_codec *codec,
int detect_report, int short_report)
{
struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec);
- struct wm8350 *wm8350 = codec->control_data;
+ struct wm8350 *wm8350 = priv->wm8350;
priv->mic.jack = jack;
priv->mic.report = detect_report;
@@ -1491,7 +1465,6 @@ EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect);
static const struct snd_soc_dai_ops wm8350_dai_ops = {
.hw_params = wm8350_pcm_hw_params,
.digital_mute = wm8350_mute,
- .trigger = wm8350_pcm_trigger,
.set_fmt = wm8350_set_dai_fmt,
.set_sysclk = wm8350_set_dai_sysclk,
.set_pll = wm8350_set_fll,
@@ -1559,9 +1532,9 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec)
wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
/* Enable robust clocking mode in ADC */
- wm8350_codec_write(codec, WM8350_SECURITY, 0xa7);
- wm8350_codec_write(codec, 0xde, 0x13);
- wm8350_codec_write(codec, WM8350_SECURITY, 0);
+ snd_soc_write(codec, WM8350_SECURITY, 0xa7);
+ snd_soc_write(codec, 0xde, 0x13);
+ snd_soc_write(codec, WM8350_SECURITY, 0);
/* read OUT1 & OUT2 volumes */
out1 = &priv->out1;
@@ -1601,10 +1574,10 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec)
WM8350_JDL_ENA | WM8350_JDR_ENA);
wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L,
- wm8350_hp_jack_handler, 0, "Left jack detect",
+ wm8350_hpl_jack_handler, 0, "Left jack detect",
priv);
wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R,
- wm8350_hp_jack_handler, 0, "Right jack detect",
+ wm8350_hpr_jack_handler, 0, "Right jack detect",
priv);
wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICSCD,
wm8350_mic_handler, 0, "Microphone short", priv);
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 898979d23010..5dc31ebcd0e7 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -138,8 +138,8 @@ static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
return ret;
/* now hit the volume update bits (always bit 8) */
- val = wm8400_read(codec, reg);
- return wm8400_write(codec, reg, val | 0x0100);
+ val = snd_soc_read(codec, reg);
+ return snd_soc_write(codec, reg, val | 0x0100);
}
#define WM8400_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert, tlv_array) \
@@ -362,8 +362,8 @@ static int inmixer_event (struct snd_soc_dapm_widget *w,
{
u16 reg, fakepower;
- reg = wm8400_read(w->codec, WM8400_POWER_MANAGEMENT_2);
- fakepower = wm8400_read(w->codec, WM8400_INTDRIVBITS);
+ reg = snd_soc_read(w->codec, WM8400_POWER_MANAGEMENT_2);
+ fakepower = snd_soc_read(w->codec, WM8400_INTDRIVBITS);
if (fakepower & ((1 << WM8400_INMIXL_PWR) |
(1 << WM8400_AINLMUX_PWR))) {
@@ -378,7 +378,7 @@ static int inmixer_event (struct snd_soc_dapm_widget *w,
} else {
reg &= ~WM8400_AINR_ENA;
}
- wm8400_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg);
+ snd_soc_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg);
return 0;
}
@@ -394,7 +394,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w,
switch (reg_shift) {
case WM8400_SPEAKER_MIXER | (WM8400_LDSPK << 8) :
- reg = wm8400_read(w->codec, WM8400_OUTPUT_MIXER1);
+ reg = snd_soc_read(w->codec, WM8400_OUTPUT_MIXER1);
if (reg & WM8400_LDLO) {
printk(KERN_WARNING
"Cannot set as Output Mixer 1 LDLO Set\n");
@@ -402,7 +402,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w,
}
break;
case WM8400_SPEAKER_MIXER | (WM8400_RDSPK << 8):
- reg = wm8400_read(w->codec, WM8400_OUTPUT_MIXER2);
+ reg = snd_soc_read(w->codec, WM8400_OUTPUT_MIXER2);
if (reg & WM8400_RDRO) {
printk(KERN_WARNING
"Cannot set as Output Mixer 2 RDRO Set\n");
@@ -410,7 +410,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w,
}
break;
case WM8400_OUTPUT_MIXER1 | (WM8400_LDLO << 8):
- reg = wm8400_read(w->codec, WM8400_SPEAKER_MIXER);
+ reg = snd_soc_read(w->codec, WM8400_SPEAKER_MIXER);
if (reg & WM8400_LDSPK) {
printk(KERN_WARNING
"Cannot set as Speaker Mixer LDSPK Set\n");
@@ -418,7 +418,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w,
}
break;
case WM8400_OUTPUT_MIXER2 | (WM8400_RDRO << 8):
- reg = wm8400_read(w->codec, WM8400_SPEAKER_MIXER);
+ reg = snd_soc_read(w->codec, WM8400_SPEAKER_MIXER);
if (reg & WM8400_RDSPK) {
printk(KERN_WARNING
"Cannot set as Speaker Mixer RDSPK Set\n");
@@ -1021,13 +1021,13 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
wm8400->fll_in = freq_in;
/* We *must* disable the FLL before any changes */
- reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_2);
+ reg = snd_soc_read(codec, WM8400_POWER_MANAGEMENT_2);
reg &= ~WM8400_FLL_ENA;
- wm8400_write(codec, WM8400_POWER_MANAGEMENT_2, reg);
+ snd_soc_write(codec, WM8400_POWER_MANAGEMENT_2, reg);
- reg = wm8400_read(codec, WM8400_FLL_CONTROL_1);
+ reg = snd_soc_read(codec, WM8400_FLL_CONTROL_1);
reg &= ~WM8400_FLL_OSC_ENA;
- wm8400_write(codec, WM8400_FLL_CONTROL_1, reg);
+ snd_soc_write(codec, WM8400_FLL_CONTROL_1, reg);
if (!freq_out)
return 0;
@@ -1035,15 +1035,15 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
reg &= ~(WM8400_FLL_REF_FREQ | WM8400_FLL_FRATIO_MASK);
reg |= WM8400_FLL_FRAC | factors.fratio;
reg |= factors.freq_ref << WM8400_FLL_REF_FREQ_SHIFT;
- wm8400_write(codec, WM8400_FLL_CONTROL_1, reg);
+ snd_soc_write(codec, WM8400_FLL_CONTROL_1, reg);
- wm8400_write(codec, WM8400_FLL_CONTROL_2, factors.k);
- wm8400_write(codec, WM8400_FLL_CONTROL_3, factors.n);
+ snd_soc_write(codec, WM8400_FLL_CONTROL_2, factors.k);
+ snd_soc_write(codec, WM8400_FLL_CONTROL_3, factors.n);
- reg = wm8400_read(codec, WM8400_FLL_CONTROL_4);
+ reg = snd_soc_read(codec, WM8400_FLL_CONTROL_4);
reg &= ~WM8400_FLL_OUTDIV_MASK;
reg |= factors.outdiv;
- wm8400_write(codec, WM8400_FLL_CONTROL_4, reg);
+ snd_soc_write(codec, WM8400_FLL_CONTROL_4, reg);
return 0;
}
@@ -1057,8 +1057,8 @@ static int wm8400_set_dai_fmt(struct snd_soc_dai *codec_dai,
struct snd_soc_codec *codec = codec_dai->codec;
u16 audio1, audio3;
- audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1);
- audio3 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_3);
+ audio1 = snd_soc_read(codec, WM8400_AUDIO_INTERFACE_1);
+ audio3 = snd_soc_read(codec, WM8400_AUDIO_INTERFACE_3);
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1099,8 +1099,8 @@ static int wm8400_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL;
}
- wm8400_write(codec, WM8400_AUDIO_INTERFACE_1, audio1);
- wm8400_write(codec, WM8400_AUDIO_INTERFACE_3, audio3);
+ snd_soc_write(codec, WM8400_AUDIO_INTERFACE_1, audio1);
+ snd_soc_write(codec, WM8400_AUDIO_INTERFACE_3, audio3);
return 0;
}
@@ -1112,24 +1112,24 @@ static int wm8400_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch (div_id) {
case WM8400_MCLK_DIV:
- reg = wm8400_read(codec, WM8400_CLOCKING_2) &
+ reg = snd_soc_read(codec, WM8400_CLOCKING_2) &
~WM8400_MCLK_DIV_MASK;
- wm8400_write(codec, WM8400_CLOCKING_2, reg | div);
+ snd_soc_write(codec, WM8400_CLOCKING_2, reg | div);
break;
case WM8400_DACCLK_DIV:
- reg = wm8400_read(codec, WM8400_CLOCKING_2) &
+ reg = snd_soc_read(codec, WM8400_CLOCKING_2) &
~WM8400_DAC_CLKDIV_MASK;
- wm8400_write(codec, WM8400_CLOCKING_2, reg | div);
+ snd_soc_write(codec, WM8400_CLOCKING_2, reg | div);
break;
case WM8400_ADCCLK_DIV:
- reg = wm8400_read(codec, WM8400_CLOCKING_2) &
+ reg = snd_soc_read(codec, WM8400_CLOCKING_2) &
~WM8400_ADC_CLKDIV_MASK;
- wm8400_write(codec, WM8400_CLOCKING_2, reg | div);
+ snd_soc_write(codec, WM8400_CLOCKING_2, reg | div);
break;
case WM8400_BCLK_DIV:
- reg = wm8400_read(codec, WM8400_CLOCKING_1) &
+ reg = snd_soc_read(codec, WM8400_CLOCKING_1) &
~WM8400_BCLK_DIV_MASK;
- wm8400_write(codec, WM8400_CLOCKING_1, reg | div);
+ snd_soc_write(codec, WM8400_CLOCKING_1, reg | div);
break;
default:
return -EINVAL;
@@ -1145,9 +1145,8 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
- u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1);
+ struct snd_soc_codec *codec = dai->codec;
+ u16 audio1 = snd_soc_read(codec, WM8400_AUDIO_INTERFACE_1);
audio1 &= ~WM8400_AIF_WL_MASK;
/* bit size */
@@ -1165,19 +1164,19 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream,
break;
}
- wm8400_write(codec, WM8400_AUDIO_INTERFACE_1, audio1);
+ snd_soc_write(codec, WM8400_AUDIO_INTERFACE_1, audio1);
return 0;
}
static int wm8400_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
- u16 val = wm8400_read(codec, WM8400_DAC_CTRL) & ~WM8400_DAC_MUTE;
+ u16 val = snd_soc_read(codec, WM8400_DAC_CTRL) & ~WM8400_DAC_MUTE;
if (mute)
- wm8400_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE);
+ snd_soc_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE);
else
- wm8400_write(codec, WM8400_DAC_CTRL, val);
+ snd_soc_write(codec, WM8400_DAC_CTRL, val);
return 0;
}
@@ -1196,9 +1195,9 @@ static int wm8400_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_PREPARE:
/* VMID=2*50k */
- val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1) &
+ val = snd_soc_read(codec, WM8400_POWER_MANAGEMENT_1) &
~WM8400_VMID_MODE_MASK;
- wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x2);
+ snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x2);
break;
case SND_SOC_BIAS_STANDBY:
@@ -1212,74 +1211,74 @@ static int wm8400_set_bias_level(struct snd_soc_codec *codec,
return ret;
}
- wm8400_write(codec, WM8400_POWER_MANAGEMENT_1,
+ snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1,
WM8400_CODEC_ENA | WM8400_SYSCLK_ENA);
/* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */
- wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST |
+ snd_soc_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST |
WM8400_BUFDCOPEN | WM8400_POBCTRL);
msleep(50);
/* Enable VREF & VMID at 2x50k */
- val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1);
+ val = snd_soc_read(codec, WM8400_POWER_MANAGEMENT_1);
val |= 0x2 | WM8400_VREF_ENA;
- wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val);
+ snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1, val);
/* Enable BUFIOEN */
- wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST |
+ snd_soc_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST |
WM8400_BUFDCOPEN | WM8400_POBCTRL |
WM8400_BUFIOEN);
/* disable POBCTRL, SOFT_ST and BUFDCOPEN */
- wm8400_write(codec, WM8400_ANTIPOP2, WM8400_BUFIOEN);
+ snd_soc_write(codec, WM8400_ANTIPOP2, WM8400_BUFIOEN);
}
/* VMID=2*300k */
- val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1) &
+ val = snd_soc_read(codec, WM8400_POWER_MANAGEMENT_1) &
~WM8400_VMID_MODE_MASK;
- wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x4);
+ snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x4);
break;
case SND_SOC_BIAS_OFF:
/* Enable POBCTRL and SOFT_ST */
- wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST |
+ snd_soc_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST |
WM8400_POBCTRL | WM8400_BUFIOEN);
/* Enable POBCTRL, SOFT_ST and BUFDCOPEN */
- wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST |
+ snd_soc_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST |
WM8400_BUFDCOPEN | WM8400_POBCTRL |
WM8400_BUFIOEN);
/* mute DAC */
- val = wm8400_read(codec, WM8400_DAC_CTRL);
- wm8400_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE);
+ val = snd_soc_read(codec, WM8400_DAC_CTRL);
+ snd_soc_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE);
/* Enable any disabled outputs */
- val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1);
+ val = snd_soc_read(codec, WM8400_POWER_MANAGEMENT_1);
val |= WM8400_SPK_ENA | WM8400_OUT3_ENA |
WM8400_OUT4_ENA | WM8400_LOUT_ENA |
WM8400_ROUT_ENA;
- wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val);
+ snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1, val);
/* Disable VMID */
val &= ~WM8400_VMID_MODE_MASK;
- wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val);
+ snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1, val);
msleep(300);
/* Enable all output discharge bits */
- wm8400_write(codec, WM8400_ANTIPOP1, WM8400_DIS_LLINE |
+ snd_soc_write(codec, WM8400_ANTIPOP1, WM8400_DIS_LLINE |
WM8400_DIS_RLINE | WM8400_DIS_OUT3 |
WM8400_DIS_OUT4 | WM8400_DIS_LOUT |
WM8400_DIS_ROUT);
/* Disable VREF */
val &= ~WM8400_VREF_ENA;
- wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val);
+ snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1, val);
/* disable POBCTRL, SOFT_ST and BUFDCOPEN */
- wm8400_write(codec, WM8400_ANTIPOP2, 0x0);
+ snd_soc_write(codec, WM8400_ANTIPOP2, 0x0);
ret = regulator_bulk_disable(ARRAY_SIZE(power),
&power[0]);
@@ -1385,19 +1384,19 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
wm8400_codec_reset(codec);
- reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1);
- wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, reg | WM8400_CODEC_ENA);
+ reg = snd_soc_read(codec, WM8400_POWER_MANAGEMENT_1);
+ snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1, reg | WM8400_CODEC_ENA);
/* Latch volume update bits */
- reg = wm8400_read(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME);
- wm8400_write(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME,
+ reg = snd_soc_read(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME);
+ snd_soc_write(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME,
reg & WM8400_IPVU);
- reg = wm8400_read(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME);
- wm8400_write(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME,
+ reg = snd_soc_read(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME);
+ snd_soc_write(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME,
reg & WM8400_IPVU);
- wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
- wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
+ snd_soc_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
+ snd_soc_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
if (!schedule_work(&priv->work)) {
ret = -EINVAL;
@@ -1414,8 +1413,8 @@ static int wm8400_codec_remove(struct snd_soc_codec *codec)
{
u16 reg;
- reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1);
- wm8400_write(codec, WM8400_POWER_MANAGEMENT_1,
+ reg = snd_soc_read(codec, WM8400_POWER_MANAGEMENT_1);
+ snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1,
reg & (~WM8400_CODEC_ENA));
regulator_bulk_free(ARRAY_SIZE(power), power);
@@ -1428,7 +1427,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
.remove = wm8400_codec_remove,
.suspend = wm8400_suspend,
.resume = wm8400_resume,
- .read = wm8400_read,
+ .read = snd_soc_read,
.write = wm8400_write,
.set_bias_level = wm8400_set_bias_level,
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 9166126bd312..56a049555e2c 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -392,8 +392,7 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f;
u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1;
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 7fea2c3bf7e7..1c3ffb290cdc 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -145,8 +145,7 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
int i;
u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index fc3d59e49084..1467f97dce21 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -88,8 +88,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 dac = snd_soc_read(codec, WM8728_DACCTL);
dac &= ~0x18;
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index a32caa72bd7d..9d1b9b0271f1 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -635,16 +635,17 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
struct wm8731_priv *wm8731;
int ret;
- wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
+ wm8731 = devm_kzalloc(&spi->dev, sizeof(struct wm8731_priv),
+ GFP_KERNEL);
if (wm8731 == NULL)
return -ENOMEM;
- wm8731->regmap = regmap_init_spi(spi, &wm8731_regmap);
+ wm8731->regmap = devm_regmap_init_spi(spi, &wm8731_regmap);
if (IS_ERR(wm8731->regmap)) {
ret = PTR_ERR(wm8731->regmap);
dev_err(&spi->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ return ret;
}
spi_set_drvdata(spi, wm8731);
@@ -653,25 +654,15 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
&soc_codec_dev_wm8731, &wm8731_dai, 1);
if (ret != 0) {
dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret);
- goto err_regmap;
+ return ret;
}
return 0;
-
-err_regmap:
- regmap_exit(wm8731->regmap);
-err:
- kfree(wm8731);
- return ret;
}
static int __devexit wm8731_spi_remove(struct spi_device *spi)
{
- struct wm8731_priv *wm8731 = spi_get_drvdata(spi);
-
snd_soc_unregister_codec(&spi->dev);
- regmap_exit(wm8731->regmap);
- kfree(wm8731);
return 0;
}
@@ -693,16 +684,17 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
struct wm8731_priv *wm8731;
int ret;
- wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
+ wm8731 = devm_kzalloc(&i2c->dev, sizeof(struct wm8731_priv),
+ GFP_KERNEL);
if (wm8731 == NULL)
return -ENOMEM;
- wm8731->regmap = regmap_init_i2c(i2c, &wm8731_regmap);
+ wm8731->regmap = devm_regmap_init_i2c(i2c, &wm8731_regmap);
if (IS_ERR(wm8731->regmap)) {
ret = PTR_ERR(wm8731->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ return ret;
}
i2c_set_clientdata(i2c, wm8731);
@@ -711,24 +703,15 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
&soc_codec_dev_wm8731, &wm8731_dai, 1);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
- goto err_regmap;
+ return ret;
}
return 0;
-
-err_regmap:
- regmap_exit(wm8731->regmap);
-err:
- kfree(wm8731);
- return ret;
}
static __devexit int wm8731_i2c_remove(struct i2c_client *client)
{
- struct wm8731_priv *wm8731 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm8731->regmap);
- kfree(wm8731);
return 0;
}
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
index 4fe9d191e277..d0520124616d 100644
--- a/sound/soc/codecs/wm8737.c
+++ b/sound/soc/codecs/wm8737.c
@@ -329,8 +329,7 @@ static int wm8737_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec);
int i;
u16 clocking = 0;
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 3941f50bf187..6e849cb04243 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -203,8 +203,7 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC;
int i;
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index e4c50ce7d9c0..89151ca5e776 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -547,8 +547,7 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3;
u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0;
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index e27e7b62b365..a26482cd7654 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -931,8 +931,7 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01f3;
u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f;
@@ -1161,8 +1160,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x01c0;
u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01f3;
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index f18c554efc98..077c9628c70d 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -610,8 +610,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 reg;
reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60;
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index c91fb2f99c13..86b8a2926591 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -1432,8 +1432,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec =rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
int fs = params_rate(params);
int bclk;
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index d2883affea3b..481a3d9cfe48 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -371,8 +371,7 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F;
u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1;
u16 companding = snd_soc_read(codec,
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 840d72086d04..8bc659d8dd2e 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -505,8 +505,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3;
int i;
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 15d467ff91b4..0cfce9999c89 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -1478,7 +1478,8 @@ static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
static int wm8962_dsp2_write_config(struct snd_soc_codec *codec)
{
- return 0;
+ return regcache_sync_region(codec->control_data,
+ WM8962_HDBASS_AI_1, WM8962_MAX_REGISTER);
}
static int wm8962_dsp2_set_enable(struct snd_soc_codec *codec, u16 val)
@@ -1755,10 +1756,22 @@ SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23,
SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23,
WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv),
+SOC_SINGLE("3D Switch", WM8962_THREED1, 0, 1, 0),
+SND_SOC_BYTES_MASK("3D Coefficients", WM8962_THREED1, 4, WM8962_THREED_ENA),
+
+SOC_SINGLE("DF1 Switch", WM8962_DF1, 0, 1, 0),
+SND_SOC_BYTES_MASK("DF1 Coefficients", WM8962_DF1, 7, WM8962_DF1_ENA),
+
+SOC_SINGLE("DRC Switch", WM8962_DRC_1, 0, 1, 0),
+SND_SOC_BYTES_MASK("DRC Coefficients", WM8962_DRC_1, 5, WM8962_DRC_ENA),
+
WM8962_DSP2_ENABLE("VSS Switch", WM8962_VSS_ENA_SHIFT),
+SND_SOC_BYTES("VSS Coefficients", WM8962_VSS_XHD2_1, 148),
WM8962_DSP2_ENABLE("HPF1 Switch", WM8962_HPF1_ENA_SHIFT),
WM8962_DSP2_ENABLE("HPF2 Switch", WM8962_HPF2_ENA_SHIFT),
+SND_SOC_BYTES("HPF Coefficients", WM8962_LHPF2, 1),
WM8962_DSP2_ENABLE("HD Bass Switch", WM8962_HDBASS_ENA_SHIFT),
+SND_SOC_BYTES("HD Bass Coefficients", WM8962_HDBASS_AI_1, 30),
};
static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = {
@@ -2519,8 +2532,7 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
int i;
int aif0 = 0;
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 28fe59e3ce01..eef783f6b6d6 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -478,8 +478,7 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);
u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3;
u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0;
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 72d5fdcd3cc2..a5be3adecf75 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -723,8 +723,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
/* Word length mask = 0x60 */
u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60;
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 6cdf6a2bc283..1d4c5cf47b06 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -668,8 +668,7 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3;
u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180;
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 9d242351e6e8..db63c97ddf51 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -1112,8 +1112,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1);
audio1 &= ~WM8990_AIF_WL_MASK;
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index d256a9340644..36acfccab999 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -218,7 +218,6 @@ struct wm8993_priv {
unsigned int sysclk_rate;
unsigned int fs;
unsigned int bclk;
- int class_w_users;
unsigned int fll_fref;
unsigned int fll_fout;
int fll_src;
@@ -824,84 +823,6 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w,
return 0;
}
-/*
- * When used with DAC outputs only the WM8993 charge pump supports
- * operation in class W mode, providing very low power consumption
- * when used with digital sources. Enable and disable this mode
- * automatically depending on the mixer configuration.
- *
- * Currently the only supported paths are the direct DAC->headphone
- * paths (which provide minimum power consumption anyway).
- */
-static int class_w_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
- struct snd_soc_dapm_widget *widget = wlist->widgets[0];
- struct snd_soc_codec *codec = widget->codec;
- struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- /* Turn it off if we're using the main output mixer */
- if (ucontrol->value.integer.value[0] == 0) {
- if (wm8993->class_w_users == 0) {
- dev_dbg(codec->dev, "Disabling Class W\n");
- snd_soc_update_bits(codec, WM8993_CLASS_W_0,
- WM8993_CP_DYN_FREQ |
- WM8993_CP_DYN_V,
- 0);
- }
- wm8993->class_w_users++;
- wm8993->hubs_data.class_w = true;
- }
-
- /* Implement the change */
- ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
-
- /* Enable it if we're using the direct DAC path */
- if (ucontrol->value.integer.value[0] == 1) {
- if (wm8993->class_w_users == 1) {
- dev_dbg(codec->dev, "Enabling Class W\n");
- snd_soc_update_bits(codec, WM8993_CLASS_W_0,
- WM8993_CP_DYN_FREQ |
- WM8993_CP_DYN_V,
- WM8993_CP_DYN_FREQ |
- WM8993_CP_DYN_V);
- }
- wm8993->class_w_users--;
- wm8993->hubs_data.class_w = false;
- }
-
- dev_dbg(codec->dev, "Indirect DAC use count now %d\n",
- wm8993->class_w_users);
-
- return ret;
-}
-
-#define SOC_DAPM_ENUM_W(xname, xenum) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
- .info = snd_soc_info_enum_double, \
- .get = snd_soc_dapm_get_enum_double, \
- .put = class_w_put, \
- .private_value = (unsigned long)&xenum }
-
-static const char *hp_mux_text[] = {
- "Mixer",
- "DAC",
-};
-
-static const struct soc_enum hpl_enum =
- SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text);
-
-static const struct snd_kcontrol_new hpl_mux =
- SOC_DAPM_ENUM_W("Left Headphone Mux", hpl_enum);
-
-static const struct soc_enum hpr_enum =
- SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text);
-
-static const struct snd_kcontrol_new hpr_mux =
- SOC_DAPM_ENUM_W("Right Headphone Mux", hpr_enum);
-
static const struct snd_kcontrol_new left_speaker_mixer[] = {
SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 7, 1, 0),
SOC_DAPM_SINGLE("IN1LP Switch", WM8993_SPEAKER_MIXER, 5, 1, 0),
@@ -988,8 +909,8 @@ SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &sidetoner_mux),
SND_SOC_DAPM_DAC("DACL", NULL, WM8993_POWER_MANAGEMENT_3, 1, 0),
SND_SOC_DAPM_DAC("DACR", NULL, WM8993_POWER_MANAGEMENT_3, 0, 0),
-SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
-SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
+SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpl_mux),
+SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpr_mux),
SND_SOC_DAPM_MIXER("SPKL", WM8993_POWER_MANAGEMENT_3, 8, 0,
left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
@@ -1579,9 +1500,6 @@ static int wm8993_probe(struct snd_soc_codec *codec)
return ret;
}
- /* By default we're using the output mixers */
- wm8993->class_w_users = 2;
-
/* Latch volume update bits and default ZC on */
snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
WM8993_DAC_VU, WM8993_DAC_VU);
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 2de12ebe43b5..993639d694ce 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -70,8 +70,8 @@ static const struct wm8958_micd_rate micdet_rates[] = {
static const struct wm8958_micd_rate jackdet_rates[] = {
{ 32768, true, 0, 1 },
{ 32768, false, 0, 1 },
- { 44100 * 256, true, 7, 10 },
- { 44100 * 256, false, 7, 10 },
+ { 44100 * 256, true, 10, 10 },
+ { 44100 * 256, false, 7, 8 },
};
static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
@@ -82,7 +82,8 @@ static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
const struct wm8958_micd_rate *rates;
int num_rates;
- if (wm8994->jack_cb != wm8958_default_micdet)
+ if (!(wm8994->pdata && wm8994->pdata->micd_rates) &&
+ wm8994->jack_cb != wm8958_default_micdet)
return;
idle = !wm8994->jack_mic;
@@ -118,6 +119,10 @@ static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
val = rates[best].start << WM8958_MICD_BIAS_STARTTIME_SHIFT
| rates[best].rate << WM8958_MICD_RATE_SHIFT;
+ dev_dbg(codec->dev, "MICD rate %d,%d for %dHz %s\n",
+ rates[best].start, rates[best].rate, sysclk,
+ idle ? "idle" : "active");
+
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
WM8958_MICD_BIAS_STARTTIME_MASK |
WM8958_MICD_RATE_MASK, val);
@@ -398,7 +403,7 @@ static void wm8994_set_retune_mobile(struct snd_soc_codec *codec, int block)
wm8994->dac_rates[iface]);
/* The EQ will be disabled while reconfiguring it, remember the
- * current configuration.
+ * current configuration.
*/
save = snd_soc_read(codec, base);
save &= WM8994_AIF1DAC1_EQ_ENA;
@@ -689,6 +694,9 @@ static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
if (!wm8994->jackdet || !wm8994->jack_cb)
return;
+ if (!wm8994->jackdet || !wm8994->jack_cb)
+ return;
+
if (wm8994->active_refcount)
mode = WM1811_JACKDET_MODE_AUDIO;
@@ -784,7 +792,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
switch (wm8994->vmid_mode) {
default:
- WARN_ON(0 == "Invalid VMID mode");
+ WARN_ON(NULL == "Invalid VMID mode");
case WM8994_VMID_NORMAL:
/* Startup bias, VMID ramp & buffer */
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
@@ -937,27 +945,12 @@ static int vmid_event(struct snd_soc_dapm_widget *w,
return 0;
}
-static void wm8994_update_class_w(struct snd_soc_codec *codec)
+static bool wm8994_check_class_w_digital(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- int enable = 1;
int source = 0; /* GCC flow analysis can't track enable */
int reg, reg_r;
- /* Only support direct DAC->headphone paths */
- reg = snd_soc_read(codec, WM8994_OUTPUT_MIXER_1);
- if (!(reg & WM8994_DAC1L_TO_HPOUT1L)) {
- dev_vdbg(codec->dev, "HPL connected to output mixer\n");
- enable = 0;
- }
-
- reg = snd_soc_read(codec, WM8994_OUTPUT_MIXER_2);
- if (!(reg & WM8994_DAC1R_TO_HPOUT1R)) {
- dev_vdbg(codec->dev, "HPR connected to output mixer\n");
- enable = 0;
- }
-
- /* We also need the same setting for L/R and only one path */
+ /* We also need the same AIF source for L/R and only one path */
reg = snd_soc_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING);
switch (reg) {
case WM8994_AIF2DACL_TO_DAC1L:
@@ -974,30 +967,20 @@ static void wm8994_update_class_w(struct snd_soc_codec *codec)
break;
default:
dev_vdbg(codec->dev, "DAC mixer setting: %x\n", reg);
- enable = 0;
- break;
+ return false;
}
reg_r = snd_soc_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING);
if (reg_r != reg) {
dev_vdbg(codec->dev, "Left and right DAC mixers different\n");
- enable = 0;
+ return false;
}
- if (enable) {
- dev_dbg(codec->dev, "Class W enabled\n");
- snd_soc_update_bits(codec, WM8994_CLASS_W_1,
- WM8994_CP_DYN_PWR |
- WM8994_CP_DYN_SRC_SEL_MASK,
- source | WM8994_CP_DYN_PWR);
- wm8994->hubs.class_w = true;
-
- } else {
- dev_dbg(codec->dev, "Class W disabled\n");
- snd_soc_update_bits(codec, WM8994_CLASS_W_1,
- WM8994_CP_DYN_PWR, 0);
- wm8994->hubs.class_w = false;
- }
+ /* Set the source up */
+ snd_soc_update_bits(codec, WM8994_CLASS_W_1,
+ WM8994_CP_DYN_SRC_SEL_MASK, source);
+
+ return true;
}
static int aif1clk_ev(struct snd_soc_dapm_widget *w,
@@ -1280,45 +1263,6 @@ static int dac_ev(struct snd_soc_dapm_widget *w,
return 0;
}
-static const char *hp_mux_text[] = {
- "Mixer",
- "DAC",
-};
-
-#define WM8994_HP_ENUM(xname, xenum) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
- .info = snd_soc_info_enum_double, \
- .get = snd_soc_dapm_get_enum_double, \
- .put = wm8994_put_hp_enum, \
- .private_value = (unsigned long)&xenum }
-
-static int wm8994_put_hp_enum(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
- struct snd_soc_dapm_widget *w = wlist->widgets[0];
- struct snd_soc_codec *codec = w->codec;
- int ret;
-
- ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
-
- wm8994_update_class_w(codec);
-
- return ret;
-}
-
-static const struct soc_enum hpl_enum =
- SOC_ENUM_SINGLE(WM8994_OUTPUT_MIXER_1, 8, 2, hp_mux_text);
-
-static const struct snd_kcontrol_new hpl_mux =
- WM8994_HP_ENUM("Left Headphone Mux", hpl_enum);
-
-static const struct soc_enum hpr_enum =
- SOC_ENUM_SINGLE(WM8994_OUTPUT_MIXER_2, 8, 2, hp_mux_text);
-
-static const struct snd_kcontrol_new hpr_mux =
- WM8994_HP_ENUM("Right Headphone Mux", hpr_enum);
-
static const char *adc_mux_text[] = {
"ADC",
"DMIC",
@@ -1430,7 +1374,7 @@ static int wm8994_put_class_w(struct snd_kcontrol *kcontrol,
ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
- wm8994_update_class_w(codec);
+ wm_hubs_update_class_w(codec);
return ret;
}
@@ -1524,7 +1468,7 @@ static const struct snd_kcontrol_new wm8958_aif3adc_mux =
SOC_DAPM_ENUM("AIF3ADC Mux", wm8958_aif3adc_enum);
static const char *mono_pcm_out_text[] = {
- "None", "AIF2ADCL", "AIF2ADCR",
+ "None", "AIF2ADCL", "AIF2ADCR",
};
static const struct soc_enum mono_pcm_out_enum =
@@ -1573,9 +1517,9 @@ SND_SOC_DAPM_MIXER_E("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
SND_SOC_DAPM_MIXER_E("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0,
right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer),
late_enable_ev, SND_SOC_DAPM_PRE_PMU),
-SND_SOC_DAPM_MUX_E("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux,
+SND_SOC_DAPM_MUX_E("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpl_mux,
late_enable_ev, SND_SOC_DAPM_PRE_PMU),
-SND_SOC_DAPM_MUX_E("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux,
+SND_SOC_DAPM_MUX_E("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpr_mux,
late_enable_ev, SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev)
@@ -1591,8 +1535,8 @@ SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0,
right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
-SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
-SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
+SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpl_mux),
+SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpr_mux),
};
static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = {
@@ -1732,6 +1676,7 @@ SND_SOC_DAPM_MUX("AIF3ADC Mux", SND_SOC_NOPM, 0, 0, &wm8994_aif3adc_mux),
};
static const struct snd_soc_dapm_widget wm8958_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("AIF3", WM8994_POWER_MANAGEMENT_6, 5, 1, NULL, 0),
SND_SOC_DAPM_MUX("Mono PCM Out Mux", SND_SOC_NOPM, 0, 0, &mono_pcm_out_mux),
SND_SOC_DAPM_MUX("AIF2DACL Mux", SND_SOC_NOPM, 0, 0, &aif2dacl_src_mux),
SND_SOC_DAPM_MUX("AIF2DACR Mux", SND_SOC_NOPM, 0, 0, &aif2dacr_src_mux),
@@ -1972,6 +1917,9 @@ static const struct snd_soc_dapm_route wm8958_intercon[] = {
{ "AIF2DACR Mux", "AIF2", "AIF2DAC Mux" },
{ "AIF2DACR Mux", "AIF3", "AIF3DACDAT" },
+ { "AIF3DACDAT", NULL, "AIF3" },
+ { "AIF3ADCDAT", NULL, "AIF3" },
+
{ "Mono PCM Out Mux", "AIF2ADCL", "AIF2ADCL" },
{ "Mono PCM Out Mux", "AIF2ADCR", "AIF2ADCR" },
@@ -2068,24 +2016,20 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
struct wm8994 *control = wm8994->wm8994;
int reg_offset, ret;
struct fll_div fll;
- u16 reg, aif1, aif2;
+ u16 reg, clk1, aif_reg, aif_src;
unsigned long timeout;
bool was_enabled;
- aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1)
- & WM8994_AIF1CLK_ENA;
-
- aif2 = snd_soc_read(codec, WM8994_AIF2_CLOCKING_1)
- & WM8994_AIF2CLK_ENA;
-
switch (id) {
case WM8994_FLL1:
reg_offset = 0;
id = 0;
+ aif_src = 0x10;
break;
case WM8994_FLL2:
reg_offset = 0x20;
id = 1;
+ aif_src = 0x18;
break;
default:
return -EINVAL;
@@ -2127,16 +2071,33 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
if (ret < 0)
return ret;
- /* Gate the AIF clocks while we reclock */
- snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1,
- WM8994_AIF1CLK_ENA, 0);
- snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1,
- WM8994_AIF2CLK_ENA, 0);
+ /* Make sure that we're not providing SYSCLK right now */
+ clk1 = snd_soc_read(codec, WM8994_CLOCKING_1);
+ if (clk1 & WM8994_SYSCLK_SRC)
+ aif_reg = WM8994_AIF2_CLOCKING_1;
+ else
+ aif_reg = WM8994_AIF1_CLOCKING_1;
+ reg = snd_soc_read(codec, aif_reg);
+
+ if ((reg & WM8994_AIF1CLK_ENA) &&
+ (reg & WM8994_AIF1CLK_SRC_MASK) == aif_src) {
+ dev_err(codec->dev, "FLL%d is currently providing SYSCLK\n",
+ id + 1);
+ return -EBUSY;
+ }
/* We always need to disable the FLL while reconfiguring */
snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset,
WM8994_FLL1_ENA, 0);
+ if (wm8994->fll_byp && src == WM8994_FLL_SRC_BCLK &&
+ freq_in == freq_out && freq_out) {
+ dev_dbg(codec->dev, "Bypassing FLL%d\n", id + 1);
+ snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset,
+ WM8958_FLL1_BYP, WM8958_FLL1_BYP);
+ goto out;
+ }
+
reg = (fll.outdiv << WM8994_FLL1_OUTDIV_SHIFT) |
(fll.fll_fratio << WM8994_FLL1_FRATIO_SHIFT);
snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_2 + reg_offset,
@@ -2151,6 +2112,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
fll.n << WM8994_FLL1_N_SHIFT);
snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset,
+ WM8958_FLL1_BYP |
WM8994_FLL1_REFCLK_DIV_MASK |
WM8994_FLL1_REFCLK_SRC_MASK,
(fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) |
@@ -2213,16 +2175,11 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
}
}
+out:
wm8994->fll[id].in = freq_in;
wm8994->fll[id].out = freq_out;
wm8994->fll[id].src = src;
- /* Enable any gated AIF clocks */
- snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1,
- WM8994_AIF1CLK_ENA, aif1);
- snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1,
- WM8994_AIF2CLK_ENA, aif2);
-
configure_clock(codec);
return 0;
@@ -2290,7 +2247,7 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
case WM8994_SYSCLK_OPCLK:
/* Special case - a division (times 10) is given and
- * no effect on main clocking.
+ * no effect on main clocking.
*/
if (freq) {
for (i = 0; i < ARRAY_SIZE(opclk_divs); i++)
@@ -2792,33 +2749,6 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream,
return snd_soc_update_bits(codec, aif1_reg, WM8994_AIF1_WL_MASK, aif1);
}
-static void wm8994_aif_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_codec *codec = dai->codec;
- int rate_reg = 0;
-
- switch (dai->id) {
- case 1:
- rate_reg = WM8994_AIF1_RATE;
- break;
- case 2:
- rate_reg = WM8994_AIF2_RATE;
- break;
- default:
- break;
- }
-
- /* If the DAI is idle then configure the divider tree for the
- * lowest output rate to save a little power if the clock is
- * still active (eg, because it is system clock).
- */
- if (rate_reg && !dai->playback_active && !dai->capture_active)
- snd_soc_update_bits(codec, rate_reg,
- WM8994_AIF1_SR_MASK |
- WM8994_AIF1CLK_RATE_MASK, 0x9);
-}
-
static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute)
{
struct snd_soc_codec *codec = codec_dai->codec;
@@ -2860,10 +2790,6 @@ static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate)
reg = WM8994_AIF2_MASTER_SLAVE;
mask = WM8994_AIF2_TRI;
break;
- case 3:
- reg = WM8994_POWER_MANAGEMENT_6;
- mask = WM8994_AIF3_TRI;
- break;
default:
return -EINVAL;
}
@@ -2900,7 +2826,6 @@ static const struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
.set_sysclk = wm8994_set_dai_sysclk,
.set_fmt = wm8994_set_dai_fmt,
.hw_params = wm8994_hw_params,
- .shutdown = wm8994_aif_shutdown,
.digital_mute = wm8994_aif_mute,
.set_pll = wm8994_set_fll,
.set_tristate = wm8994_set_tristate,
@@ -2910,7 +2835,6 @@ static const struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
.set_sysclk = wm8994_set_dai_sysclk,
.set_fmt = wm8994_set_dai_fmt,
.hw_params = wm8994_hw_params,
- .shutdown = wm8994_aif_shutdown,
.digital_mute = wm8994_aif_mute,
.set_pll = wm8994_set_fll,
.set_tristate = wm8994_set_tristate,
@@ -2918,7 +2842,6 @@ static const struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
static const struct snd_soc_dai_ops wm8994_aif3_dai_ops = {
.hw_params = wm8994_aif3_hw_params,
- .set_tristate = wm8994_set_tristate,
};
static struct snd_soc_dai_driver wm8994_dai[] = {
@@ -3126,14 +3049,14 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
/* Expand the array... */
t = krealloc(wm8994->retune_mobile_texts,
- sizeof(char *) *
+ sizeof(char *) *
(wm8994->num_retune_mobile_texts + 1),
GFP_KERNEL);
if (t == NULL)
continue;
/* ...store the new entry... */
- t[wm8994->num_retune_mobile_texts] =
+ t[wm8994->num_retune_mobile_texts] =
pdata->retune_mobile_cfgs[i].name;
/* ...and remember the new version. */
@@ -3304,25 +3227,25 @@ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
}
EXPORT_SYMBOL_GPL(wm8994_mic_detect);
-static irqreturn_t wm8994_mic_irq(int irq, void *data)
+static void wm8994_mic_work(struct work_struct *work)
{
- struct wm8994_priv *priv = data;
- struct snd_soc_codec *codec = priv->codec;
- int reg;
+ struct wm8994_priv *priv = container_of(work,
+ struct wm8994_priv,
+ mic_work.work);
+ struct regmap *regmap = priv->wm8994->regmap;
+ struct device *dev = priv->wm8994->dev;
+ unsigned int reg;
+ int ret;
int report;
-#ifndef CONFIG_SND_SOC_WM8994_MODULE
- trace_snd_soc_jack_irq(dev_name(codec->dev));
-#endif
-
- reg = snd_soc_read(codec, WM8994_INTERRUPT_RAW_STATUS_2);
- if (reg < 0) {
- dev_err(codec->dev, "Failed to read microphone status: %d\n",
- reg);
- return IRQ_HANDLED;
+ ret = regmap_read(regmap, WM8994_INTERRUPT_RAW_STATUS_2, &reg);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read microphone status: %d\n",
+ ret);
+ return;
}
- dev_dbg(codec->dev, "Microphone status: %x\n", reg);
+ dev_dbg(dev, "Microphone status: %x\n", reg);
report = 0;
if (reg & WM8994_MIC1_DET_STS) {
@@ -3361,6 +3284,20 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
snd_soc_jack_report(priv->micdet[1].jack, report,
SND_JACK_HEADSET | SND_JACK_BTN_0);
+}
+
+static irqreturn_t wm8994_mic_irq(int irq, void *data)
+{
+ struct wm8994_priv *priv = data;
+ struct snd_soc_codec *codec = priv->codec;
+
+#ifndef CONFIG_SND_SOC_WM8994_MODULE
+ trace_snd_soc_jack_irq(dev_name(codec->dev));
+#endif
+
+ pm_wakeup_event(codec->dev, 300);
+
+ schedule_delayed_work(&priv->mic_work, msecs_to_jiffies(250));
return IRQ_HANDLED;
}
@@ -3415,9 +3352,6 @@ static void wm8958_default_micdet(u16 status, void *data)
wm8958_micd_set_rate(codec);
- snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE,
- SND_JACK_HEADSET);
-
/* If we have jackdet that will detect removal */
if (wm8994->jackdet) {
mutex_lock(&wm8994->accdet_lock);
@@ -3430,14 +3364,13 @@ static void wm8958_default_micdet(u16 status, void *data)
mutex_unlock(&wm8994->accdet_lock);
- if (wm8994->pdata->jd_ext_cap) {
- mutex_lock(&codec->mutex);
+ if (wm8994->pdata->jd_ext_cap)
snd_soc_dapm_disable_pin(&codec->dapm,
"MICBIAS2");
- snd_soc_dapm_sync(&codec->dapm);
- mutex_unlock(&codec->mutex);
- }
}
+
+ snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE,
+ SND_JACK_HEADSET);
}
/* Report short circuit as a button */
@@ -3489,6 +3422,8 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
if (present) {
dev_dbg(codec->dev, "Jack detected\n");
+ wm8958_micd_set_rate(codec);
+
snd_soc_update_bits(codec, WM8958_MICBIAS2,
WM8958_MICB2_DISCH, 0);
@@ -3526,16 +3461,11 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
/* If required for an external cap force MICBIAS on */
if (wm8994->pdata->jd_ext_cap) {
- mutex_lock(&codec->mutex);
-
if (present)
snd_soc_dapm_force_enable_pin(&codec->dapm,
"MICBIAS2");
else
snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
-
- snd_soc_dapm_sync(&codec->dapm);
- mutex_unlock(&codec->mutex);
}
if (present)
@@ -3740,6 +3670,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8994->codec = codec;
mutex_init(&wm8994->accdet_lock);
+ INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
init_completion(&wm8994->fll_locked[i]);
@@ -3783,13 +3714,22 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
case WM8958:
wm8994->hubs.dcs_readback_mode = 1;
wm8994->hubs.hp_startup_mode = 1;
+
+ switch (wm8994->revision) {
+ case 0:
+ break;
+ default:
+ wm8994->fll_byp = true;
+ break;
+ }
break;
case WM1811:
wm8994->hubs.dcs_readback_mode = 2;
wm8994->hubs.no_series_update = 1;
wm8994->hubs.hp_startup_mode = 1;
- wm8994->hubs.no_cache_class_w = true;
+ wm8994->hubs.no_cache_dac_hp_direct = true;
+ wm8994->fll_byp = true;
switch (wm8994->revision) {
case 0:
@@ -4010,7 +3950,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
break;
}
- wm8994_update_class_w(codec);
+ wm8994->hubs.check_class_w_digital = wm8994_check_class_w_digital;
+ wm_hubs_update_class_w(codec);
wm8994_handle_pdata(wm8994);
@@ -4075,7 +4016,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
ARRAY_SIZE(wm8994_dac_widgets));
break;
}
-
wm_hubs_add_analogue_routes(codec, 0, 0);
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
@@ -4140,7 +4080,7 @@ err_irq:
return ret;
}
-static int wm8994_codec_remove(struct snd_soc_codec *codec)
+static int wm8994_codec_remove(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
@@ -4181,14 +4121,10 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
free_irq(wm8994->micdet_irq, wm8994);
break;
}
- if (wm8994->mbc)
- release_firmware(wm8994->mbc);
- if (wm8994->mbc_vss)
- release_firmware(wm8994->mbc_vss);
- if (wm8994->enh_eq)
- release_firmware(wm8994->enh_eq);
+ release_firmware(wm8994->mbc);
+ release_firmware(wm8994->mbc_vss);
+ release_firmware(wm8994->enh_eq);
kfree(wm8994->retune_mobile_texts);
-
return 0;
}
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index c724112998d8..d77e06f0a675 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -12,6 +12,7 @@
#include <sound/soc.h>
#include <linux/firmware.h>
#include <linux/completion.h>
+#include <linux/workqueue.h>
#include "wm_hubs.h"
@@ -79,6 +80,7 @@ struct wm8994_priv {
struct wm8994_fll_config fll[2], fll_suspend[2];
struct completion fll_locked[2];
bool fll_locked_irq;
+ bool fll_byp;
int vmid_refcount;
int active_refcount;
@@ -126,6 +128,7 @@ struct wm8994_priv {
struct mutex accdet_lock;
struct wm8994_micdet micdet[2];
+ struct delayed_work mic_work;
bool mic_detecting;
bool jack_mic;
int btn_mask;
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 1fd635494045..8af422e38fd0 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -1770,7 +1770,13 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec,
switch (level) {
case SND_SOC_BIAS_ON:
+ break;
case SND_SOC_BIAS_PREPARE:
+ /* Put the MICBIASes into regulating mode */
+ snd_soc_update_bits(codec, WM8996_MICBIAS_1,
+ WM8996_MICB1_MODE, 0);
+ snd_soc_update_bits(codec, WM8996_MICBIAS_2,
+ WM8996_MICB2_MODE, 0);
break;
case SND_SOC_BIAS_STANDBY:
@@ -1793,6 +1799,12 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec,
regcache_cache_only(codec->control_data, false);
regcache_sync(codec->control_data);
}
+
+ /* Bypass the MICBIASes for lowest power */
+ snd_soc_update_bits(codec, WM8996_MICBIAS_1,
+ WM8996_MICB1_MODE, WM8996_MICB1_MODE);
+ snd_soc_update_bits(codec, WM8996_MICBIAS_2,
+ WM8996_MICB2_MODE, WM8996_MICB2_MODE);
break;
case SND_SOC_BIAS_OFF:
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 076c126ed9b1..9328270df16c 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -774,7 +774,7 @@ static const struct snd_soc_dapm_widget wm9081_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("IN1"),
SND_SOC_DAPM_INPUT("IN2"),
-SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM9081_POWER_MANAGEMENT, 0, 0),
+SND_SOC_DAPM_DAC("DAC", NULL, WM9081_POWER_MANAGEMENT, 0, 0),
SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0,
mixer, ARRAY_SIZE(mixer)),
@@ -799,6 +799,7 @@ SND_SOC_DAPM_SUPPLY("TSENSE", WM9081_POWER_MANAGEMENT, 7, 0, NULL, 0),
static const struct snd_soc_dapm_route wm9081_audio_paths[] = {
{ "DAC", NULL, "CLK_SYS" },
{ "DAC", NULL, "CLK_DSP" },
+ { "DAC", NULL, "AIF" },
{ "Mixer", "IN1 Switch", "IN1" },
{ "Mixer", "IN2 Switch", "IN2" },
@@ -1252,7 +1253,7 @@ static const struct snd_soc_dai_ops wm9081_dai_ops = {
static struct snd_soc_dai_driver wm9081_dai = {
.name = "wm9081-hifi",
.playback = {
- .stream_name = "HiFi Playback",
+ .stream_name = "AIF",
.channels_min = 1,
.channels_max = 2,
.rates = WM9081_RATES,
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index cacc6a86b46f..e8e782a0c78d 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -236,9 +236,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
static int ac97_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
int reg;
u16 vra;
@@ -250,7 +248,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
else
reg = AC97_PCM_LR_ADC_RATE;
- return ac97_write(codec, reg, runtime->rate);
+ return ac97_write(codec, reg, substream->runtime->rate);
}
#define WM9705_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index b342ae50bcd6..a1541414d904 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -467,11 +467,10 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
static int ac97_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec =rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
int reg;
u16 vra;
+ struct snd_pcm_runtime *runtime = substream->runtime;
vra = ac97_read(codec, AC97_EXTENDED_STATUS);
ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
@@ -487,10 +486,9 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
static int ac97_aux_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 vra, xsle;
+ struct snd_pcm_runtime *runtime = substream->runtime;
vra = ac97_read(codec, AC97_EXTENDED_STATUS);
ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 6c028c470601..dfe957a47f29 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -109,12 +109,103 @@ irqreturn_t wm_hubs_dcs_done(int irq, void *data)
}
EXPORT_SYMBOL_GPL(wm_hubs_dcs_done);
+static bool wm_hubs_dac_hp_direct(struct snd_soc_codec *codec)
+{
+ int reg;
+
+ /* If we're going via the mixer we'll need to do additional checks */
+ reg = snd_soc_read(codec, WM8993_OUTPUT_MIXER1);
+ if (!(reg & WM8993_DACL_TO_HPOUT1L)) {
+ if (reg & ~WM8993_DACL_TO_MIXOUTL) {
+ dev_vdbg(codec->dev, "Analogue paths connected: %x\n",
+ reg & ~WM8993_DACL_TO_HPOUT1L);
+ return false;
+ } else {
+ dev_vdbg(codec->dev, "HPL connected to mixer\n");
+ }
+ } else {
+ dev_vdbg(codec->dev, "HPL connected to DAC\n");
+ }
+
+ reg = snd_soc_read(codec, WM8993_OUTPUT_MIXER2);
+ if (!(reg & WM8993_DACR_TO_HPOUT1R)) {
+ if (reg & ~WM8993_DACR_TO_MIXOUTR) {
+ dev_vdbg(codec->dev, "Analogue paths connected: %x\n",
+ reg & ~WM8993_DACR_TO_HPOUT1R);
+ return false;
+ } else {
+ dev_vdbg(codec->dev, "HPR connected to mixer\n");
+ }
+ } else {
+ dev_vdbg(codec->dev, "HPR connected to DAC\n");
+ }
+
+ return true;
+}
+
+struct wm_hubs_dcs_cache {
+ struct list_head list;
+ unsigned int left;
+ unsigned int right;
+ u16 dcs_cfg;
+};
+
+static bool wm_hubs_dcs_cache_get(struct snd_soc_codec *codec,
+ struct wm_hubs_dcs_cache **entry)
+{
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+ struct wm_hubs_dcs_cache *cache;
+ unsigned int left, right;
+
+ left = snd_soc_read(codec, WM8993_LEFT_OUTPUT_VOLUME);
+ left &= WM8993_HPOUT1L_VOL_MASK;
+
+ right = snd_soc_read(codec, WM8993_RIGHT_OUTPUT_VOLUME);
+ right &= WM8993_HPOUT1R_VOL_MASK;
+
+ list_for_each_entry(cache, &hubs->dcs_cache, list) {
+ if (cache->left != left || cache->right != right)
+ continue;
+
+ *entry = cache;
+ return true;
+ }
+
+ return false;
+}
+
+static void wm_hubs_dcs_cache_set(struct snd_soc_codec *codec, u16 dcs_cfg)
+{
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+ struct wm_hubs_dcs_cache *cache;
+
+ if (hubs->no_cache_dac_hp_direct)
+ return;
+
+ cache = devm_kzalloc(codec->dev, sizeof(*cache), GFP_KERNEL);
+ if (!cache) {
+ dev_err(codec->dev, "Failed to allocate DCS cache entry\n");
+ return;
+ }
+
+ cache->left = snd_soc_read(codec, WM8993_LEFT_OUTPUT_VOLUME);
+ cache->left &= WM8993_HPOUT1L_VOL_MASK;
+
+ cache->right = snd_soc_read(codec, WM8993_RIGHT_OUTPUT_VOLUME);
+ cache->right &= WM8993_HPOUT1R_VOL_MASK;
+
+ cache->dcs_cfg = dcs_cfg;
+
+ list_add_tail(&cache->list, &hubs->dcs_cache);
+}
+
/*
* Startup calibration of the DC servo
*/
static void calibrate_dc_servo(struct snd_soc_codec *codec)
{
struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+ struct wm_hubs_dcs_cache *cache;
s8 offset;
u16 reg, reg_l, reg_r, dcs_cfg, dcs_reg;
@@ -129,10 +220,11 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
/* If we're using a digital only path and have a previously
* callibrated DC servo offset stored then use that. */
- if (hubs->class_w && hubs->class_w_dcs) {
- dev_dbg(codec->dev, "Using cached DC servo offset %x\n",
- hubs->class_w_dcs);
- snd_soc_write(codec, dcs_reg, hubs->class_w_dcs);
+ if (wm_hubs_dac_hp_direct(codec) &&
+ wm_hubs_dcs_cache_get(codec, &cache)) {
+ dev_dbg(codec->dev, "Using cached DCS offset %x for %d,%d\n",
+ cache->dcs_cfg, cache->left, cache->right);
+ snd_soc_write(codec, dcs_reg, cache->dcs_cfg);
wait_for_dc_servo(codec,
WM8993_DCS_TRIG_DAC_WR_0 |
WM8993_DCS_TRIG_DAC_WR_1);
@@ -207,8 +299,8 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
/* Save the callibrated offset if we're in class W mode and
* therefore don't have any analogue signal mixed in. */
- if (hubs->class_w && !hubs->no_cache_class_w)
- hubs->class_w_dcs = dcs_cfg;
+ if (wm_hubs_dac_hp_direct(codec))
+ wm_hubs_dcs_cache_set(codec, dcs_cfg);
}
/*
@@ -223,9 +315,6 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
ret = snd_soc_put_volsw(kcontrol, ucontrol);
- /* Updating the analogue gains invalidates the DC servo cache */
- hubs->class_w_dcs = 0;
-
/* If we're applying an offset correction then updating the
* callibration would be likely to introduce further offsets. */
if (hubs->dcs_codes_l || hubs->dcs_codes_r || hubs->no_series_update)
@@ -530,6 +619,86 @@ static int lineout_event(struct snd_soc_dapm_widget *w,
return 0;
}
+void wm_hubs_update_class_w(struct snd_soc_codec *codec)
+{
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+ int enable = WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ;
+
+ if (!wm_hubs_dac_hp_direct(codec))
+ enable = false;
+
+ if (hubs->check_class_w_digital && !hubs->check_class_w_digital(codec))
+ enable = false;
+
+ dev_vdbg(codec->dev, "Class W %s\n", enable ? "enabled" : "disabled");
+
+ snd_soc_update_bits(codec, WM8993_CLASS_W_0,
+ WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ, enable);
+}
+EXPORT_SYMBOL_GPL(wm_hubs_update_class_w);
+
+#define WM_HUBS_SINGLE_W(xname, reg, shift, max, invert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_soc_info_volsw, \
+ .get = snd_soc_dapm_get_volsw, .put = class_w_put_volsw, \
+ .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
+
+static int class_w_put_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ struct snd_soc_codec *codec = widget->codec;
+ int ret;
+
+ ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
+
+ wm_hubs_update_class_w(codec);
+
+ return ret;
+}
+
+#define WM_HUBS_ENUM_W(xname, xenum) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_soc_info_enum_double, \
+ .get = snd_soc_dapm_get_enum_double, \
+ .put = class_w_put_double, \
+ .private_value = (unsigned long)&xenum }
+
+static int class_w_put_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ struct snd_soc_codec *codec = widget->codec;
+ int ret;
+
+ ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+ wm_hubs_update_class_w(codec);
+
+ return ret;
+}
+
+static const char *hp_mux_text[] = {
+ "Mixer",
+ "DAC",
+};
+
+static const struct soc_enum hpl_enum =
+ SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text);
+
+const struct snd_kcontrol_new wm_hubs_hpl_mux =
+ WM_HUBS_ENUM_W("Left Headphone Mux", hpl_enum);
+EXPORT_SYMBOL_GPL(wm_hubs_hpl_mux);
+
+static const struct soc_enum hpr_enum =
+ SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text);
+
+const struct snd_kcontrol_new wm_hubs_hpr_mux =
+ WM_HUBS_ENUM_W("Right Headphone Mux", hpr_enum);
+EXPORT_SYMBOL_GPL(wm_hubs_hpr_mux);
+
static const struct snd_kcontrol_new in1l_pga[] = {
SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0),
SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0),
@@ -561,25 +730,25 @@ SOC_DAPM_SINGLE("IN1R Switch", WM8993_INPUT_MIXER4, 5, 1, 0),
};
static const struct snd_kcontrol_new left_output_mixer[] = {
-SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0),
-SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0),
-SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0),
-SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0),
-SOC_DAPM_SINGLE("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0),
-SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0),
-SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0),
-SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0),
+WM_HUBS_SINGLE_W("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0),
+WM_HUBS_SINGLE_W("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0),
+WM_HUBS_SINGLE_W("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0),
+WM_HUBS_SINGLE_W("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0),
+WM_HUBS_SINGLE_W("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0),
+WM_HUBS_SINGLE_W("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0),
+WM_HUBS_SINGLE_W("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0),
+WM_HUBS_SINGLE_W("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0),
};
static const struct snd_kcontrol_new right_output_mixer[] = {
-SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0),
-SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0),
-SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0),
-SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0),
-SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0),
-SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0),
-SOC_DAPM_SINGLE("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0),
-SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0),
+WM_HUBS_SINGLE_W("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0),
+WM_HUBS_SINGLE_W("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0),
+WM_HUBS_SINGLE_W("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0),
+WM_HUBS_SINGLE_W("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0),
+WM_HUBS_SINGLE_W("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0),
+WM_HUBS_SINGLE_W("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0),
+WM_HUBS_SINGLE_W("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0),
+WM_HUBS_SINGLE_W("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0),
};
static const struct snd_kcontrol_new earpiece_mixer[] = {
@@ -943,6 +1112,7 @@ int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec,
struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
+ INIT_LIST_HEAD(&hubs->dcs_cache);
init_completion(&hubs->dcs_done);
snd_soc_dapm_add_routes(dapm, analogue_routes,
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
index 5705276f4943..da2dc899ce6d 100644
--- a/sound/soc/codecs/wm_hubs.h
+++ b/sound/soc/codecs/wm_hubs.h
@@ -16,6 +16,8 @@
#include <linux/completion.h>
#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <sound/control.h>
struct snd_soc_codec;
@@ -30,9 +32,9 @@ struct wm_hubs_data {
int series_startup;
int no_series_update;
- bool no_cache_class_w;
- bool class_w;
- u16 class_w_dcs;
+ bool no_cache_dac_hp_direct;
+ struct list_head dcs_cache;
+ bool (*check_class_w_digital)(struct snd_soc_codec *);
bool lineout1_se;
bool lineout1n_ena;
@@ -58,5 +60,9 @@ extern irqreturn_t wm_hubs_dcs_done(int irq, void *data);
extern void wm_hubs_vmid_ena(struct snd_soc_codec *codec);
extern void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level);
+extern void wm_hubs_update_class_w(struct snd_soc_codec *codec);
+
+extern const struct snd_kcontrol_new wm_hubs_hpl_mux;
+extern const struct snd_kcontrol_new wm_hubs_hpr_mux;
#endif
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/ep93xx/ep93xx-ac97.c
index 0678637abd66..bdffab33e160 100644
--- a/sound/soc/ep93xx/ep93xx-ac97.c
+++ b/sound/soc/ep93xx/ep93xx-ac97.c
@@ -87,17 +87,13 @@
* struct ep93xx_ac97_info - EP93xx AC97 controller info structure
* @lock: mutex serializing access to the bus (slot 1 & 2 ops)
* @dev: pointer to the platform device dev structure
- * @mem: physical memory resource for the registers
* @regs: mapped AC97 controller registers
- * @irq: AC97 interrupt number
* @done: bus ops wait here for an interrupt
*/
struct ep93xx_ac97_info {
struct mutex lock;
struct device *dev;
- struct resource *mem;
void __iomem *regs;
- int irq;
struct completion done;
};
@@ -359,66 +355,50 @@ static struct snd_soc_dai_driver ep93xx_ac97_dai = {
static int __devinit ep93xx_ac97_probe(struct platform_device *pdev)
{
struct ep93xx_ac97_info *info;
+ struct resource *res;
+ unsigned int irq;
int ret;
- info = kzalloc(sizeof(struct ep93xx_ac97_info), GFP_KERNEL);
+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- dev_set_drvdata(&pdev->dev, info);
-
- mutex_init(&info->lock);
- init_completion(&info->done);
- info->dev = &pdev->dev;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
- info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!info->mem) {
- ret = -ENXIO;
- goto fail_free_info;
- }
+ info->regs = devm_request_and_ioremap(&pdev->dev, res);
+ if (!info->regs)
+ return -ENXIO;
- info->irq = platform_get_irq(pdev, 0);
- if (!info->irq) {
- ret = -ENXIO;
- goto fail_free_info;
- }
+ irq = platform_get_irq(pdev, 0);
+ if (!irq)
+ return -ENODEV;
- if (!request_mem_region(info->mem->start, resource_size(info->mem),
- pdev->name)) {
- ret = -EBUSY;
- goto fail_free_info;
- }
+ ret = devm_request_irq(&pdev->dev, irq, ep93xx_ac97_interrupt,
+ IRQF_TRIGGER_HIGH, pdev->name, info);
+ if (ret)
+ goto fail;
- info->regs = ioremap(info->mem->start, resource_size(info->mem));
- if (!info->regs) {
- ret = -ENOMEM;
- goto fail_release_mem;
- }
+ dev_set_drvdata(&pdev->dev, info);
- ret = request_irq(info->irq, ep93xx_ac97_interrupt, IRQF_TRIGGER_HIGH,
- pdev->name, info);
- if (ret)
- goto fail_unmap_mem;
+ mutex_init(&info->lock);
+ init_completion(&info->done);
+ info->dev = &pdev->dev;
ep93xx_ac97_info = info;
platform_set_drvdata(pdev, info);
ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai);
if (ret)
- goto fail_free_irq;
+ goto fail;
return 0;
-fail_free_irq:
+fail:
platform_set_drvdata(pdev, NULL);
- free_irq(info->irq, info);
-fail_unmap_mem:
- iounmap(info->regs);
-fail_release_mem:
- release_mem_region(info->mem->start, resource_size(info->mem));
-fail_free_info:
- kfree(info);
-
+ ep93xx_ac97_info = NULL;
+ dev_set_drvdata(&pdev->dev, NULL);
return ret;
}
@@ -431,11 +411,9 @@ static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
/* disable the AC97 controller */
ep93xx_ac97_write_reg(info, AC97GCR, 0);
- free_irq(info->irq, info);
- iounmap(info->regs);
- release_mem_region(info->mem->start, resource_size(info->mem));
platform_set_drvdata(pdev, NULL);
- kfree(info);
+ ep93xx_ac97_info = NULL;
+ dev_set_drvdata(&pdev->dev, NULL);
return 0;
}
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c
index f7a62348e3fe..8df8f6dc474f 100644
--- a/sound/soc/ep93xx/ep93xx-i2s.c
+++ b/sound/soc/ep93xx/ep93xx-i2s.c
@@ -63,7 +63,6 @@ struct ep93xx_i2s_info {
struct clk *sclk;
struct clk *lrclk;
struct ep93xx_pcm_dma_params *dma_params;
- struct resource *mem;
void __iomem *regs;
};
@@ -373,38 +372,22 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
struct resource *res;
int err;
- info = kzalloc(sizeof(struct ep93xx_i2s_info), GFP_KERNEL);
- if (!info) {
- err = -ENOMEM;
- goto fail;
- }
-
- dev_set_drvdata(&pdev->dev, info);
- info->dma_params = ep93xx_i2s_dma_params;
+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- err = -ENODEV;
- goto fail_free_info;
- }
+ if (!res)
+ return -ENODEV;
- info->mem = request_mem_region(res->start, resource_size(res),
- pdev->name);
- if (!info->mem) {
- err = -EBUSY;
- goto fail_free_info;
- }
-
- info->regs = ioremap(info->mem->start, resource_size(info->mem));
- if (!info->regs) {
- err = -ENXIO;
- goto fail_release_mem;
- }
+ info->regs = devm_request_and_ioremap(&pdev->dev, res);
+ if (!info->regs)
+ return -ENXIO;
info->mclk = clk_get(&pdev->dev, "mclk");
if (IS_ERR(info->mclk)) {
err = PTR_ERR(info->mclk);
- goto fail_unmap_mem;
+ goto fail;
}
info->sclk = clk_get(&pdev->dev, "sclk");
@@ -419,6 +402,9 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
goto fail_put_sclk;
}
+ dev_set_drvdata(&pdev->dev, info);
+ info->dma_params = ep93xx_i2s_dma_params;
+
err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai);
if (err)
goto fail_put_lrclk;
@@ -426,17 +412,12 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
return 0;
fail_put_lrclk:
+ dev_set_drvdata(&pdev->dev, NULL);
clk_put(info->lrclk);
fail_put_sclk:
clk_put(info->sclk);
fail_put_mclk:
clk_put(info->mclk);
-fail_unmap_mem:
- iounmap(info->regs);
-fail_release_mem:
- release_mem_region(info->mem->start, resource_size(info->mem));
-fail_free_info:
- kfree(info);
fail:
return err;
}
@@ -446,12 +427,10 @@ static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
snd_soc_unregister_dai(&pdev->dev);
+ dev_set_drvdata(&pdev->dev, NULL);
clk_put(info->lrclk);
clk_put(info->sclk);
clk_put(info->mclk);
- iounmap(info->regs);
- release_mem_region(info->mem->start, resource_size(info->mem));
- kfree(info);
return 0;
}
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index d754d34d68a6..d70133086ac3 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -1,18 +1,31 @@
-config SND_MPC52xx_DMA
+config SND_SOC_FSL_SSI
tristate
-# ASoC platform support for the Freescale PowerPC SOCs that have an SSI and
-# an Elo DMA controller, such as the MPC8610 and P1022. You will still need to
-# select a platform driver and a codec driver.
-config SND_SOC_POWERPC_SSI
+config SND_SOC_FSL_UTILS
tristate
+
+menuconfig SND_POWERPC_SOC
+ tristate "SoC Audio for Freescale PowerPC CPUs"
depends on FSL_SOC
+ help
+ Say Y or M if you want to add support for codecs attached to
+ the PowerPC CPUs.
+
+if SND_POWERPC_SOC
+
+config SND_MPC52xx_DMA
+ tristate
+
+config SND_SOC_POWERPC_DMA
+ tristate
config SND_SOC_MPC8610_HPCD
tristate "ALSA SoC support for the Freescale MPC8610 HPCD board"
# I2C is necessary for the CS4270 driver
depends on MPC8610_HPCD && I2C
- select SND_SOC_POWERPC_SSI
+ select SND_SOC_FSL_SSI
+ select SND_SOC_FSL_UTILS
+ select SND_SOC_POWERPC_DMA
select SND_SOC_CS4270
select SND_SOC_CS4270_VD33_ERRATA
default y if MPC8610_HPCD
@@ -23,7 +36,9 @@ config SND_SOC_P1022_DS
tristate "ALSA SoC support for the Freescale P1022 DS board"
# I2C is necessary for the WM8776 driver
depends on P1022_DS && I2C
- select SND_SOC_POWERPC_SSI
+ select SND_SOC_FSL_SSI
+ select SND_SOC_FSL_UTILS
+ select SND_SOC_POWERPC_DMA
select SND_SOC_WM8776
default y if P1022_DS
help
@@ -65,3 +80,103 @@ config SND_MPC52xx_SOC_EFIKA
help
Say Y if you want to add support for sound on the Efika.
+endif # SND_POWERPC_SOC
+
+menuconfig SND_IMX_SOC
+ tristate "SoC Audio for Freescale i.MX CPUs"
+ depends on ARCH_MXC
+ help
+ Say Y or M if you want to add support for codecs attached to
+ the i.MX CPUs.
+
+if SND_IMX_SOC
+
+config SND_SOC_IMX_SSI
+ tristate
+
+config SND_SOC_IMX_PCM
+ tristate
+
+config SND_SOC_IMX_PCM_FIQ
+ tristate
+ select FIQ
+ select SND_SOC_IMX_PCM
+
+config SND_SOC_IMX_PCM_DMA
+ tristate
+ select SND_SOC_DMAENGINE_PCM
+ select SND_SOC_IMX_PCM
+
+config SND_SOC_IMX_AUDMUX
+ tristate
+
+config SND_MXC_SOC_WM1133_EV1
+ tristate "Audio on the i.MX31ADS with WM1133-EV1 fitted"
+ depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
+ select SND_SOC_WM8350
+ select SND_SOC_IMX_PCM_FIQ
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_IMX_SSI
+ help
+ Enable support for audio on the i.MX31ADS with the WM1133-EV1
+ PMIC board with WM8835x fitted.
+
+config SND_SOC_MX27VIS_AIC32X4
+ tristate "SoC audio support for Visstrim M10 boards"
+ depends on MACH_IMX27_VISSTRIM_M10 && I2C
+ select SND_SOC_TLV320AIC32X4
+ select SND_SOC_IMX_PCM_DMA
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_IMX_SSI
+ help
+ Say Y if you want to add support for SoC audio on Visstrim SM10
+ board with TLV320AIC32X4 codec.
+
+config SND_SOC_PHYCORE_AC97
+ tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
+ depends on MACH_PCM043 || MACH_PCA100
+ select SND_SOC_AC97_BUS
+ select SND_SOC_WM9712
+ select SND_SOC_IMX_PCM_FIQ
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_IMX_SSI
+ help
+ Say Y if you want to add support for SoC audio on Phytec phyCORE
+ and phyCARD boards in AC97 mode
+
+config SND_SOC_EUKREA_TLV320
+ tristate "Eukrea TLV320"
+ depends on MACH_EUKREA_MBIMX27_BASEBOARD \
+ || MACH_EUKREA_MBIMXSD25_BASEBOARD \
+ || MACH_EUKREA_MBIMXSD35_BASEBOARD \
+ || MACH_EUKREA_MBIMXSD51_BASEBOARD
+ depends on I2C
+ select SND_SOC_TLV320AIC23
+ select SND_SOC_IMX_PCM_FIQ
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_IMX_SSI
+ help
+ Enable I2S based access to the TLV320AIC23B codec attached
+ to the SSI interface
+
+config SND_SOC_IMX_SGTL5000
+ tristate "SoC Audio support for i.MX boards with sgtl5000"
+ depends on OF && I2C
+ select SND_SOC_SGTL5000
+ select SND_SOC_IMX_PCM_DMA
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_FSL_SSI
+ select SND_SOC_FSL_UTILS
+ help
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a sgtl5000 codec.
+
+config SND_SOC_IMX_MC13783
+ tristate "SoC Audio support for I.MX boards with mc13783"
+ depends on MFD_MC13783
+ select SND_SOC_IMX_SSI
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_MC13783
+ select SND_SOC_IMX_PCM_DMA
+
+endif # SND_IMX_SOC
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index b4a38c0ac58c..5f3cf3f52ea0 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -8,8 +8,11 @@ obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o
# Freescale PowerPC SSI/DMA Platform Support
snd-soc-fsl-ssi-objs := fsl_ssi.o
+snd-soc-fsl-utils-objs := fsl_utils.o
snd-soc-fsl-dma-objs := fsl_dma.o
-obj-$(CONFIG_SND_SOC_POWERPC_SSI) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o
+obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o
+obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o
+obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
# MPC5200 Platform Support
obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
@@ -20,3 +23,29 @@ obj-$(CONFIG_SND_SOC_MPC5200_AC97) += mpc5200_psc_ac97.o
obj-$(CONFIG_SND_MPC52xx_SOC_PCM030) += pcm030-audio-fabric.o
obj-$(CONFIG_SND_MPC52xx_SOC_EFIKA) += efika-audio-fabric.o
+# i.MX Platform Support
+snd-soc-imx-ssi-objs := imx-ssi.o
+snd-soc-imx-audmux-objs := imx-audmux.o
+
+obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
+obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
+
+obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o
+snd-soc-imx-pcm-y := imx-pcm.o
+snd-soc-imx-pcm-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
+snd-soc-imx-pcm-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
+
+# i.MX Machine Support
+snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
+snd-soc-phycore-ac97-objs := phycore-ac97.o
+snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o
+snd-soc-wm1133-ev1-objs := wm1133-ev1.o
+snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
+snd-soc-imx-mc13783-objs := imx-mc13783.o
+
+obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
+obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
+obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o
+obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
+obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
+obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o
diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c
index 7d4475cfdb24..efb9ede01208 100644
--- a/sound/soc/imx/eukrea-tlv320.c
+++ b/sound/soc/fsl/eukrea-tlv320.c
@@ -7,7 +7,7 @@
* which is Copyright 2009 Simtec Electronics
* and on sound/soc/imx/phycore-ac97.c which is
* Copyright 2009 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
- *
+ *
* 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
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 2eb407fa3b48..4ed2afd47782 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -11,11 +11,15 @@
*/
#include <linux/init.h>
+#include <linux/io.h>
#include <linux/module.h>
#include <linux/interrupt.h>
+#include <linux/clk.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <sound/core.h>
@@ -25,6 +29,26 @@
#include <sound/soc.h>
#include "fsl_ssi.h"
+#include "imx-pcm.h"
+
+#ifdef PPC
+#define read_ssi(addr) in_be32(addr)
+#define write_ssi(val, addr) out_be32(addr, val)
+#define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set)
+#elif defined ARM
+#define read_ssi(addr) readl(addr)
+#define write_ssi(val, addr) writel(val, addr)
+/*
+ * FIXME: Proper locking should be added at write_ssi_mask caller level
+ * to ensure this register read/modify/write sequence is race free.
+ */
+static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set)
+{
+ u32 val = readl(addr);
+ val = (val & ~clear) | set;
+ writel(val, addr);
+}
+#endif
/**
* FSLSSI_I2S_RATES: sample rates supported by the I2S
@@ -94,6 +118,13 @@ struct fsl_ssi_private {
struct device_attribute dev_attr;
struct platform_device *pdev;
+ bool new_binding;
+ bool ssi_on_imx;
+ struct clk *clk;
+ struct platform_device *imx_pcm_pdev;
+ struct imx_pcm_dma_params dma_params_tx;
+ struct imx_pcm_dma_params dma_params_rx;
+
struct {
unsigned int rfrc;
unsigned int tfrc;
@@ -145,7 +176,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
were interrupted for. We mask it with the Interrupt Enable register
so that we only check for events that we're interested in.
*/
- sisr = in_be32(&ssi->sisr) & SIER_FLAGS;
+ sisr = read_ssi(&ssi->sisr) & SIER_FLAGS;
if (sisr & CCSR_SSI_SISR_RFRC) {
ssi_private->stats.rfrc++;
@@ -260,7 +291,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
/* Clear the bits that we set */
if (sisr2)
- out_be32(&ssi->sisr, sisr2);
+ write_ssi(sisr2, &ssi->sisr);
return ret;
}
@@ -295,7 +326,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
* SSI needs to be disabled before updating the registers we set
* here.
*/
- clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
+ write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
/*
* Program the SSI into I2S Slave Non-Network Synchronous mode.
@@ -303,20 +334,18 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
*
* FIXME: Little-endian samples require a different shift dir
*/
- clrsetbits_be32(&ssi->scr,
+ write_ssi_mask(&ssi->scr,
CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE
| (synchronous ? CCSR_SSI_SCR_SYN : 0));
- out_be32(&ssi->stcr,
- CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
+ write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS |
- CCSR_SSI_STCR_TSCKP);
+ CCSR_SSI_STCR_TSCKP, &ssi->stcr);
- out_be32(&ssi->srcr,
- CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 |
+ write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 |
CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS |
- CCSR_SSI_SRCR_RSCKP);
+ CCSR_SSI_SRCR_RSCKP, &ssi->srcr);
/*
* The DC and PM bits are only used if the SSI is the clock
@@ -324,7 +353,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
*/
/* Enable the interrupts and DMA requests */
- out_be32(&ssi->sier, SIER_FLAGS);
+ write_ssi(SIER_FLAGS, &ssi->sier);
/*
* Set the watermark for transmit FIFI 0 and receive FIFO 0. We
@@ -339,9 +368,9 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
* make this value larger (and maybe we should), but this way
* data will be written to memory as soon as it's available.
*/
- out_be32(&ssi->sfcsr,
- CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) |
- CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2));
+ write_ssi(CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) |
+ CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2),
+ &ssi->sfcsr);
/*
* We keep the SSI disabled because if we enable it, then the
@@ -393,6 +422,12 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
ssi_private->second_stream = substream;
}
+ if (ssi_private->ssi_on_imx)
+ snd_soc_dai_set_dma_data(dai, substream,
+ (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ &ssi_private->dma_params_tx :
+ &ssi_private->dma_params_rx);
+
return 0;
}
@@ -417,7 +452,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
unsigned int sample_size =
snd_pcm_format_width(params_format(hw_params));
u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
- int enabled = in_be32(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
+ int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
/*
* If we're in synchronous mode, and the SSI is already enabled,
@@ -439,9 +474,9 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
/* In synchronous mode, the SSI uses STCCR for capture */
if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
ssi_private->cpu_dai_drv.symmetric_rates)
- clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
+ write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
else
- clrsetbits_be32(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
+ write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
return 0;
}
@@ -466,19 +501,19 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- setbits32(&ssi->scr,
+ write_ssi_mask(&ssi->scr, 0,
CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE);
else
- setbits32(&ssi->scr,
+ write_ssi_mask(&ssi->scr, 0,
CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- clrbits32(&ssi->scr, CCSR_SSI_SCR_TE);
+ write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0);
else
- clrbits32(&ssi->scr, CCSR_SSI_SCR_RE);
+ write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0);
break;
default:
@@ -510,7 +545,7 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
if (!ssi_private->first_stream) {
struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
- clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
+ write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
}
}
@@ -622,12 +657,6 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
if (!of_device_is_available(np))
return -ENODEV;
- /* Check for a codec-handle property. */
- if (!of_get_property(np, "codec-handle", NULL)) {
- dev_err(&pdev->dev, "missing codec-handle property\n");
- return -ENODEV;
- }
-
/* We only support the SSI in "I2S Slave" mode */
sprop = of_get_property(np, "fsl,mode", NULL);
if (!sprop || strcmp(sprop, "i2s-slave")) {
@@ -692,6 +721,50 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
/* Older 8610 DTs didn't have the fifo-depth property */
ssi_private->fifo_depth = 8;
+ if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) {
+ u32 dma_events[2];
+ ssi_private->ssi_on_imx = true;
+
+ ssi_private->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(ssi_private->clk)) {
+ ret = PTR_ERR(ssi_private->clk);
+ dev_err(&pdev->dev, "could not get clock: %d\n", ret);
+ goto error_irq;
+ }
+ clk_prepare_enable(ssi_private->clk);
+
+ /*
+ * We have burstsize be "fifo_depth - 2" to match the SSI
+ * watermark setting in fsl_ssi_startup().
+ */
+ ssi_private->dma_params_tx.burstsize =
+ ssi_private->fifo_depth - 2;
+ ssi_private->dma_params_rx.burstsize =
+ ssi_private->fifo_depth - 2;
+ ssi_private->dma_params_tx.dma_addr =
+ ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0);
+ ssi_private->dma_params_rx.dma_addr =
+ ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0);
+ /*
+ * TODO: This is a temporary solution and should be changed
+ * to use generic DMA binding later when the helplers get in.
+ */
+ ret = of_property_read_u32_array(pdev->dev.of_node,
+ "fsl,ssi-dma-events", dma_events, 2);
+ if (ret) {
+ dev_err(&pdev->dev, "could not get dma events\n");
+ goto error_clk;
+ }
+ ssi_private->dma_params_tx.dma = dma_events[0];
+ ssi_private->dma_params_rx.dma = dma_events[1];
+
+ ssi_private->dma_params_tx.shared_peripheral =
+ of_device_is_compatible(of_get_parent(np),
+ "fsl,spba-bus");
+ ssi_private->dma_params_rx.shared_peripheral =
+ ssi_private->dma_params_tx.shared_peripheral;
+ }
+
/* Initialize the the device_attribute structure */
dev_attr = &ssi_private->dev_attr;
sysfs_attr_init(&dev_attr->attr);
@@ -715,6 +788,26 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
goto error_dev;
}
+ if (ssi_private->ssi_on_imx) {
+ ssi_private->imx_pcm_pdev =
+ platform_device_register_simple("imx-pcm-audio",
+ -1, NULL, 0);
+ if (IS_ERR(ssi_private->imx_pcm_pdev)) {
+ ret = PTR_ERR(ssi_private->imx_pcm_pdev);
+ goto error_dev;
+ }
+ }
+
+ /*
+ * If codec-handle property is missing from SSI node, we assume
+ * that the machine driver uses new binding which does not require
+ * SSI driver to trigger machine driver's probe.
+ */
+ if (!of_get_property(np, "codec-handle", NULL)) {
+ ssi_private->new_binding = true;
+ goto done;
+ }
+
/* Trigger the machine driver's probe function. The platform driver
* name of the machine driver is taken from /compatible property of the
* device tree. We also pass the address of the CPU DAI driver
@@ -736,15 +829,24 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
goto error_dai;
}
+done:
return 0;
error_dai:
+ if (ssi_private->ssi_on_imx)
+ platform_device_unregister(ssi_private->imx_pcm_pdev);
snd_soc_unregister_dai(&pdev->dev);
error_dev:
dev_set_drvdata(&pdev->dev, NULL);
device_remove_file(&pdev->dev, dev_attr);
+error_clk:
+ if (ssi_private->ssi_on_imx) {
+ clk_disable_unprepare(ssi_private->clk);
+ clk_put(ssi_private->clk);
+ }
+
error_irq:
free_irq(ssi_private->irq, ssi_private);
@@ -764,7 +866,13 @@ static int fsl_ssi_remove(struct platform_device *pdev)
{
struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev);
- platform_device_unregister(ssi_private->pdev);
+ if (!ssi_private->new_binding)
+ platform_device_unregister(ssi_private->pdev);
+ if (ssi_private->ssi_on_imx) {
+ platform_device_unregister(ssi_private->imx_pcm_pdev);
+ clk_disable_unprepare(ssi_private->clk);
+ clk_put(ssi_private->clk);
+ }
snd_soc_unregister_dai(&pdev->dev);
device_remove_file(&pdev->dev, &ssi_private->dev_attr);
@@ -779,6 +887,7 @@ static int fsl_ssi_remove(struct platform_device *pdev)
static const struct of_device_id fsl_ssi_ids[] = {
{ .compatible = "fsl,mpc8610-ssi", },
+ { .compatible = "fsl,imx21-ssi", },
{}
};
MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
diff --git a/sound/soc/fsl/fsl_utils.c b/sound/soc/fsl/fsl_utils.c
new file mode 100644
index 000000000000..b9e42b503a37
--- /dev/null
+++ b/sound/soc/fsl/fsl_utils.c
@@ -0,0 +1,91 @@
+/**
+ * Freescale ALSA SoC Machine driver utility
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <sound/soc.h>
+
+#include "fsl_utils.h"
+
+/**
+ * fsl_asoc_get_dma_channel - determine the dma channel for a SSI node
+ *
+ * @ssi_np: pointer to the SSI device tree node
+ * @name: name of the phandle pointing to the dma channel
+ * @dai: ASoC DAI link pointer to be filled with platform_name
+ * @dma_channel_id: dma channel id to be returned
+ * @dma_id: dma id to be returned
+ *
+ * This function determines the dma and channel id for given SSI node. It
+ * also discovers the platform_name for the ASoC DAI link.
+ */
+int fsl_asoc_get_dma_channel(struct device_node *ssi_np,
+ const char *name,
+ struct snd_soc_dai_link *dai,
+ unsigned int *dma_channel_id,
+ unsigned int *dma_id)
+{
+ struct resource res;
+ struct device_node *dma_channel_np, *dma_np;
+ const u32 *iprop;
+ int ret;
+
+ dma_channel_np = of_parse_phandle(ssi_np, name, 0);
+ if (!dma_channel_np)
+ return -EINVAL;
+
+ if (!of_device_is_compatible(dma_channel_np, "fsl,ssi-dma-channel")) {
+ of_node_put(dma_channel_np);
+ return -EINVAL;
+ }
+
+ /* Determine the dev_name for the device_node. This code mimics the
+ * behavior of of_device_make_bus_id(). We need this because ASoC uses
+ * the dev_name() of the device to match the platform (DMA) device with
+ * the CPU (SSI) device. It's all ugly and hackish, but it works (for
+ * now).
+ *
+ * dai->platform name should already point to an allocated buffer.
+ */
+ ret = of_address_to_resource(dma_channel_np, 0, &res);
+ if (ret) {
+ of_node_put(dma_channel_np);
+ return ret;
+ }
+ snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s",
+ (unsigned long long) res.start, dma_channel_np->name);
+
+ iprop = of_get_property(dma_channel_np, "cell-index", NULL);
+ if (!iprop) {
+ of_node_put(dma_channel_np);
+ return -EINVAL;
+ }
+ *dma_channel_id = be32_to_cpup(iprop);
+
+ dma_np = of_get_parent(dma_channel_np);
+ iprop = of_get_property(dma_np, "cell-index", NULL);
+ if (!iprop) {
+ of_node_put(dma_np);
+ return -EINVAL;
+ }
+ *dma_id = be32_to_cpup(iprop);
+
+ of_node_put(dma_np);
+ of_node_put(dma_channel_np);
+
+ return 0;
+}
+EXPORT_SYMBOL(fsl_asoc_get_dma_channel);
+
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_DESCRIPTION("Freescale ASoC utility code");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/fsl_utils.h b/sound/soc/fsl/fsl_utils.h
new file mode 100644
index 000000000000..b2951126527c
--- /dev/null
+++ b/sound/soc/fsl/fsl_utils.h
@@ -0,0 +1,26 @@
+/**
+ * Freescale ALSA SoC Machine driver utility
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef _FSL_UTILS_H
+#define _FSL_UTILS_H
+
+#define DAI_NAME_SIZE 32
+
+struct snd_soc_dai_link;
+struct device_node;
+
+int fsl_asoc_get_dma_channel(struct device_node *ssi_np, const char *name,
+ struct snd_soc_dai_link *dai,
+ unsigned int *dma_channel_id,
+ unsigned int *dma_id);
+
+#endif /* _FSL_UTILS_H */
diff --git a/sound/soc/imx/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index f23700359c67..f23700359c67 100644
--- a/sound/soc/imx/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
diff --git a/sound/soc/imx/imx-audmux.h b/sound/soc/fsl/imx-audmux.h
index 04ebbab8d7b9..04ebbab8d7b9 100644
--- a/sound/soc/imx/imx-audmux.h
+++ b/sound/soc/fsl/imx-audmux.h
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c
new file mode 100644
index 000000000000..f59c34943662
--- /dev/null
+++ b/sound/soc/fsl/imx-mc13783.c
@@ -0,0 +1,156 @@
+/*
+ * imx-mc13783.c -- SoC audio for imx based boards with mc13783 codec
+ *
+ * Copyright 2012 Philippe Retornaz, <philippe.retornaz@epfl.ch>
+ *
+ * Heavly based on phycore-mc13783:
+ * Copyright 2009 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/mach-types.h>
+
+#include "../codecs/mc13783.h"
+#include "imx-ssi.h"
+#include "imx-audmux.h"
+
+#define FMT_SSI (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | \
+ SND_SOC_DAIFMT_CBM_CFM)
+
+static int imx_mc13783_hifi_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int ret;
+
+ ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xfffffffc, 0xfffffffc,
+ 4, 16);
+ if (ret)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, MC13783_CLK_CLIA, 26000000, 0);
+ if (ret)
+ return ret;
+
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x0, 0xfffffffc, 2, 16);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops imx_mc13783_hifi_ops = {
+ .hw_params = imx_mc13783_hifi_hw_params,
+};
+
+static struct snd_soc_dai_link imx_mc13783_dai_mc13783[] = {
+ {
+ .name = "MC13783",
+ .stream_name = "Sound",
+ .codec_dai_name = "mc13783-hifi",
+ .codec_name = "mc13783-codec",
+ .cpu_dai_name = "imx-ssi.0",
+ .platform_name = "imx-pcm-audio.0",
+ .ops = &imx_mc13783_hifi_ops,
+ .symmetric_rates = 1,
+ .dai_fmt = FMT_SSI,
+ },
+};
+
+static const struct snd_soc_dapm_widget imx_mc13783_widget[] = {
+ SND_SOC_DAPM_MIC("Mic", NULL),
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_SPK("Speaker", NULL),
+};
+
+static const struct snd_soc_dapm_route imx_mc13783_routes[] = {
+ {"Speaker", NULL, "LSP"},
+ {"Headphone", NULL, "HSL"},
+ {"Headphone", NULL, "HSR"},
+
+ {"MC1LIN", NULL, "MC1 Bias"},
+ {"MC2IN", NULL, "MC2 Bias"},
+ {"MC1 Bias", NULL, "Mic"},
+ {"MC2 Bias", NULL, "Mic"},
+};
+
+static struct snd_soc_card imx_mc13783 = {
+ .name = "imx_mc13783",
+ .dai_link = imx_mc13783_dai_mc13783,
+ .num_links = ARRAY_SIZE(imx_mc13783_dai_mc13783),
+ .dapm_widgets = imx_mc13783_widget,
+ .num_dapm_widgets = ARRAY_SIZE(imx_mc13783_widget),
+ .dapm_routes = imx_mc13783_routes,
+ .num_dapm_routes = ARRAY_SIZE(imx_mc13783_routes),
+};
+
+static int __devinit imx_mc13783_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ imx_mc13783.dev = &pdev->dev;
+
+ ret = snd_soc_register_card(&imx_mc13783);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ return ret;
+ }
+
+ imx_audmux_v2_configure_port(MX31_AUDMUX_PORT4_SSI_PINS_4,
+ IMX_AUDMUX_V2_PTCR_SYN,
+ IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0) |
+ IMX_AUDMUX_V2_PDCR_MODE(1) |
+ IMX_AUDMUX_V2_PDCR_INMMASK(0xfc));
+ imx_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0,
+ IMX_AUDMUX_V2_PTCR_SYN |
+ IMX_AUDMUX_V2_PTCR_TFSDIR |
+ IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) |
+ IMX_AUDMUX_V2_PTCR_TCLKDIR |
+ IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) |
+ IMX_AUDMUX_V2_PTCR_RFSDIR |
+ IMX_AUDMUX_V2_PTCR_RFSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) |
+ IMX_AUDMUX_V2_PTCR_RCLKDIR |
+ IMX_AUDMUX_V2_PTCR_RCSEL(MX31_AUDMUX_PORT4_SSI_PINS_4),
+ IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT4_SSI_PINS_4));
+
+ return ret;
+}
+
+static int __devexit imx_mc13783_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_card(&imx_mc13783);
+
+ return 0;
+}
+
+static struct platform_driver imx_mc13783_audio_driver = {
+ .driver = {
+ .name = "imx_mc13783",
+ .owner = THIS_MODULE,
+ },
+ .probe = imx_mc13783_probe,
+ .remove = __devexit_p(imx_mc13783_remove)
+};
+
+module_platform_driver(imx_mc13783_audio_driver);
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch");
+MODULE_DESCRIPTION("imx with mc13783 codec ALSA SoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:imx_mc13783");
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/fsl/imx-pcm-dma.c
index 6b818de2fc03..f3c0a5ef35c8 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -109,7 +109,8 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
- dma_data->peripheral_type = IMX_DMATYPE_SSI;
+ dma_data->peripheral_type = dma_params->shared_peripheral ?
+ IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI;
dma_data->priority = DMA_PRIO_HIGH;
dma_data->dma_request = dma_params->dma;
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
index 456b7d723d66..456b7d723d66 100644
--- a/sound/soc/imx/imx-pcm-fiq.c
+++ b/sound/soc/fsl/imx-pcm-fiq.c
diff --git a/sound/soc/imx/imx-pcm.c b/sound/soc/fsl/imx-pcm.c
index 93dc360b1777..93dc360b1777 100644
--- a/sound/soc/imx/imx-pcm.c
+++ b/sound/soc/fsl/imx-pcm.c
diff --git a/sound/soc/imx/imx-pcm.h b/sound/soc/fsl/imx-pcm.h
index b5f5c3acf34d..83c0ed7d55c9 100644
--- a/sound/soc/imx/imx-pcm.h
+++ b/sound/soc/fsl/imx-pcm.h
@@ -22,6 +22,7 @@ struct imx_pcm_dma_params {
int dma;
unsigned long dma_addr;
int burstsize;
+ bool shared_peripheral; /* The peripheral is on SPBA bus */
};
int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
new file mode 100644
index 000000000000..3a729caeb8c8
--- /dev/null
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_i2c.h>
+#include <linux/clk.h>
+#include <sound/soc.h>
+
+#include "../codecs/sgtl5000.h"
+#include "imx-audmux.h"
+
+#define DAI_NAME_SIZE 32
+
+struct imx_sgtl5000_data {
+ struct snd_soc_dai_link dai;
+ struct snd_soc_card card;
+ char codec_dai_name[DAI_NAME_SIZE];
+ char platform_name[DAI_NAME_SIZE];
+ struct clk *codec_clk;
+ unsigned int clk_frequency;
+};
+
+static int imx_sgtl5000_dai_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct imx_sgtl5000_data *data = container_of(rtd->card,
+ struct imx_sgtl5000_data, card);
+ struct device *dev = rtd->card->dev;
+ int ret;
+
+ ret = snd_soc_dai_set_sysclk(rtd->codec_dai, SGTL5000_SYSCLK,
+ data->clk_frequency, SND_SOC_CLOCK_IN);
+ if (ret) {
+ dev_err(dev, "could not set codec driver clock params\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget imx_sgtl5000_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("Mic Jack", NULL),
+ SND_SOC_DAPM_LINE("Line In Jack", NULL),
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_SPK("Line Out Jack", NULL),
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+static int __devinit imx_sgtl5000_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *ssi_np, *codec_np;
+ struct platform_device *ssi_pdev;
+ struct i2c_client *codec_dev;
+ struct imx_sgtl5000_data *data;
+ int int_port, ext_port;
+ int ret;
+
+ ret = of_property_read_u32(np, "mux-int-port", &int_port);
+ if (ret) {
+ dev_err(&pdev->dev, "mux-int-port missing or invalid\n");
+ return ret;
+ }
+ ret = of_property_read_u32(np, "mux-ext-port", &ext_port);
+ if (ret) {
+ dev_err(&pdev->dev, "mux-ext-port missing or invalid\n");
+ return ret;
+ }
+
+ /*
+ * The port numbering in the hardware manual starts at 1, while
+ * the audmux API expects it starts at 0.
+ */
+ int_port--;
+ ext_port--;
+ ret = imx_audmux_v2_configure_port(int_port,
+ IMX_AUDMUX_V2_PTCR_SYN |
+ IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |
+ IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) |
+ IMX_AUDMUX_V2_PTCR_TFSDIR |
+ IMX_AUDMUX_V2_PTCR_TCLKDIR,
+ IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port));
+ if (ret) {
+ dev_err(&pdev->dev, "audmux internal port setup failed\n");
+ return ret;
+ }
+ imx_audmux_v2_configure_port(ext_port,
+ IMX_AUDMUX_V2_PTCR_SYN |
+ IMX_AUDMUX_V2_PTCR_TCSEL(int_port),
+ IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));
+ if (ret) {
+ dev_err(&pdev->dev, "audmux external port setup failed\n");
+ return ret;
+ }
+
+ ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0);
+ codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
+ if (!ssi_np || !codec_np) {
+ dev_err(&pdev->dev, "phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ssi_pdev = of_find_device_by_node(ssi_np);
+ if (!ssi_pdev) {
+ dev_err(&pdev->dev, "failed to find SSI platform device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+ codec_dev = of_find_i2c_device_by_node(codec_np);
+ if (!codec_dev) {
+ dev_err(&pdev->dev, "failed to find codec platform device\n");
+ return -EINVAL;
+ }
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ data->codec_clk = clk_get(&codec_dev->dev, NULL);
+ if (IS_ERR(data->codec_clk)) {
+ /* assuming clock enabled by default */
+ data->codec_clk = NULL;
+ ret = of_property_read_u32(codec_np, "clock-frequency",
+ &data->clk_frequency);
+ if (ret) {
+ dev_err(&codec_dev->dev,
+ "clock-frequency missing or invalid\n");
+ goto fail;
+ }
+ } else {
+ data->clk_frequency = clk_get_rate(data->codec_clk);
+ clk_prepare_enable(data->codec_clk);
+ }
+
+ data->dai.name = "HiFi";
+ data->dai.stream_name = "HiFi";
+ data->dai.codec_dai_name = "sgtl5000";
+ data->dai.codec_of_node = codec_np;
+ data->dai.cpu_dai_name = dev_name(&ssi_pdev->dev);
+ data->dai.platform_name = "imx-pcm-audio";
+ data->dai.init = &imx_sgtl5000_dai_init;
+ data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
+
+ data->card.dev = &pdev->dev;
+ ret = snd_soc_of_parse_card_name(&data->card, "model");
+ if (ret)
+ goto clk_fail;
+ ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
+ if (ret)
+ goto clk_fail;
+ data->card.num_links = 1;
+ data->card.dai_link = &data->dai;
+ data->card.dapm_widgets = imx_sgtl5000_dapm_widgets;
+ data->card.num_dapm_widgets = ARRAY_SIZE(imx_sgtl5000_dapm_widgets);
+
+ ret = snd_soc_register_card(&data->card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+ goto clk_fail;
+ }
+
+ platform_set_drvdata(pdev, data);
+clk_fail:
+ clk_put(data->codec_clk);
+fail:
+ if (ssi_np)
+ of_node_put(ssi_np);
+ if (codec_np)
+ of_node_put(codec_np);
+
+ return ret;
+}
+
+static int __devexit imx_sgtl5000_remove(struct platform_device *pdev)
+{
+ struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
+
+ if (data->codec_clk) {
+ clk_disable_unprepare(data->codec_clk);
+ clk_put(data->codec_clk);
+ }
+ snd_soc_unregister_card(&data->card);
+
+ return 0;
+}
+
+static const struct of_device_id imx_sgtl5000_dt_ids[] = {
+ { .compatible = "fsl,imx-audio-sgtl5000", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_sgtl5000_dt_ids);
+
+static struct platform_driver imx_sgtl5000_driver = {
+ .driver = {
+ .name = "imx-sgtl5000",
+ .owner = THIS_MODULE,
+ .of_match_table = imx_sgtl5000_dt_ids,
+ },
+ .probe = imx_sgtl5000_probe,
+ .remove = __devexit_p(imx_sgtl5000_remove),
+};
+module_platform_driver(imx_sgtl5000_driver);
+
+MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
+MODULE_DESCRIPTION("Freescale i.MX SGTL5000 ASoC machine driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:imx-sgtl5000");
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/fsl/imx-ssi.c
index 4f81ed456325..cf3ed0362c9c 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/fsl/imx-ssi.c
@@ -28,7 +28,7 @@
* value. When we read the same register two times (and the register still
* contains the same value) these status bits are not set. We work
* around this by not polling these bits but only wait a fixed delay.
- *
+ *
*/
#include <linux/clk.h>
diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/fsl/imx-ssi.h
index 5744e86ca878..5744e86ca878 100644
--- a/sound/soc/imx/imx-ssi.h
+++ b/sound/soc/fsl/imx-ssi.h
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 3fea5a15ffe8..60bcba1bc30e 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -14,18 +14,16 @@
#include <linux/interrupt.h>
#include <linux/of_device.h>
#include <linux/slab.h>
-#include <linux/of_i2c.h>
#include <sound/soc.h>
#include <asm/fsl_guts.h>
#include "fsl_dma.h"
#include "fsl_ssi.h"
+#include "fsl_utils.h"
/* There's only one global utilities register */
static phys_addr_t guts_phys;
-#define DAI_NAME_SIZE 32
-
/**
* mpc8610_hpcd_data: machine-specific ASoC device data
*
@@ -43,7 +41,6 @@ struct mpc8610_hpcd_data {
unsigned int dma_id[2]; /* 0 = DMA1, 1 = DMA2, etc */
unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/
char codec_dai_name[DAI_NAME_SIZE];
- char codec_name[DAI_NAME_SIZE];
char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */
};
@@ -181,141 +178,6 @@ static struct snd_soc_ops mpc8610_hpcd_ops = {
};
/**
- * get_node_by_phandle_name - get a node by its phandle name
- *
- * This function takes a node, the name of a property in that node, and a
- * compatible string. Assuming the property is a phandle to another node,
- * it returns that node, (optionally) if that node is compatible.
- *
- * If the property is not a phandle, or the node it points to is not compatible
- * with the specific string, then NULL is returned.
- */
-static struct device_node *get_node_by_phandle_name(struct device_node *np,
- const char *name,
- const char *compatible)
-{
- const phandle *ph;
- int len;
-
- ph = of_get_property(np, name, &len);
- if (!ph || (len != sizeof(phandle)))
- return NULL;
-
- np = of_find_node_by_phandle(*ph);
- if (!np)
- return NULL;
-
- if (compatible && !of_device_is_compatible(np, compatible)) {
- of_node_put(np);
- return NULL;
- }
-
- return np;
-}
-
-/**
- * get_parent_cell_index -- return the cell-index of the parent of a node
- *
- * Return the value of the cell-index property of the parent of the given
- * node. This is used for DMA channel nodes that need to know the DMA ID
- * of the controller they are on.
- */
-static int get_parent_cell_index(struct device_node *np)
-{
- struct device_node *parent = of_get_parent(np);
- const u32 *iprop;
-
- if (!parent)
- return -1;
-
- iprop = of_get_property(parent, "cell-index", NULL);
- of_node_put(parent);
-
- if (!iprop)
- return -1;
-
- return be32_to_cpup(iprop);
-}
-
-/**
- * codec_node_dev_name - determine the dev_name for a codec node
- *
- * This function determines the dev_name for an I2C node. This is the name
- * that would be returned by dev_name() if this device_node were part of a
- * 'struct device' It's ugly and hackish, but it works.
- *
- * The dev_name for such devices include the bus number and I2C address. For
- * example, "cs4270.0-004f".
- */
-static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
-{
- const u32 *iprop;
- int addr;
- char temp[DAI_NAME_SIZE];
- struct i2c_client *i2c;
-
- of_modalias_node(np, temp, DAI_NAME_SIZE);
-
- iprop = of_get_property(np, "reg", NULL);
- if (!iprop)
- return -EINVAL;
-
- addr = be32_to_cpup(iprop);
-
- /* We need the adapter number */
- i2c = of_find_i2c_device_by_node(np);
- if (!i2c)
- return -ENODEV;
-
- snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr);
-
- return 0;
-}
-
-static int get_dma_channel(struct device_node *ssi_np,
- const char *name,
- struct snd_soc_dai_link *dai,
- unsigned int *dma_channel_id,
- unsigned int *dma_id)
-{
- struct resource res;
- struct device_node *dma_channel_np;
- const u32 *iprop;
- int ret;
-
- dma_channel_np = get_node_by_phandle_name(ssi_np, name,
- "fsl,ssi-dma-channel");
- if (!dma_channel_np)
- return -EINVAL;
-
- /* Determine the dev_name for the device_node. This code mimics the
- * behavior of of_device_make_bus_id(). We need this because ASoC uses
- * the dev_name() of the device to match the platform (DMA) device with
- * the CPU (SSI) device. It's all ugly and hackish, but it works (for
- * now).
- *
- * dai->platform name should already point to an allocated buffer.
- */
- ret = of_address_to_resource(dma_channel_np, 0, &res);
- if (ret)
- return ret;
- snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s",
- (unsigned long long) res.start, dma_channel_np->name);
-
- iprop = of_get_property(dma_channel_np, "cell-index", NULL);
- if (!iprop) {
- of_node_put(dma_channel_np);
- return -EINVAL;
- }
-
- *dma_channel_id = be32_to_cpup(iprop);
- *dma_id = get_parent_cell_index(dma_channel_np);
- of_node_put(dma_channel_np);
-
- return 0;
-}
-
-/**
* mpc8610_hpcd_probe: platform probe function for the machine driver
*
* Although this is a machine driver, the SSI node is the "master" node with
@@ -352,16 +214,8 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
machine_data->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev);
machine_data->dai[0].ops = &mpc8610_hpcd_ops;
- /* Determine the codec name, it will be used as the codec DAI name */
- ret = codec_node_dev_name(codec_np, machine_data->codec_name,
- DAI_NAME_SIZE);
- if (ret) {
- dev_err(&pdev->dev, "invalid codec node %s\n",
- codec_np->full_name);
- ret = -EINVAL;
- goto error;
- }
- machine_data->dai[0].codec_name = machine_data->codec_name;
+ /* ASoC core can match codec with device node */
+ machine_data->dai[0].codec_of_node = codec_np;
/* The DAI name from the codec (snd_soc_dai_driver.name) */
machine_data->dai[0].codec_dai_name = "cs4270-hifi";
@@ -458,9 +312,10 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
/* Find the playback DMA channel to use. */
machine_data->dai[0].platform_name = machine_data->platform_name[0];
- ret = get_dma_channel(np, "fsl,playback-dma", &machine_data->dai[0],
- &machine_data->dma_channel_id[0],
- &machine_data->dma_id[0]);
+ ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma",
+ &machine_data->dai[0],
+ &machine_data->dma_channel_id[0],
+ &machine_data->dma_id[0]);
if (ret) {
dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n");
goto error;
@@ -468,9 +323,10 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
/* Find the capture DMA channel to use. */
machine_data->dai[1].platform_name = machine_data->platform_name[1];
- ret = get_dma_channel(np, "fsl,capture-dma", &machine_data->dai[1],
- &machine_data->dma_channel_id[1],
- &machine_data->dma_id[1]);
+ ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma",
+ &machine_data->dai[1],
+ &machine_data->dma_channel_id[1],
+ &machine_data->dma_id[1]);
if (ret) {
dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n");
goto error;
diff --git a/sound/soc/imx/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c
index f6d04ad4bb39..f6d04ad4bb39 100644
--- a/sound/soc/imx/mx27vis-aic32x4.c
+++ b/sound/soc/fsl/mx27vis-aic32x4.c
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index 982a1c944983..50adf4032bcc 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -14,12 +14,12 @@
#include <linux/interrupt.h>
#include <linux/of_device.h>
#include <linux/slab.h>
-#include <linux/of_i2c.h>
#include <sound/soc.h>
#include <asm/fsl_guts.h>
#include "fsl_dma.h"
#include "fsl_ssi.h"
+#include "fsl_utils.h"
/* P1022-specific PMUXCR and DMUXCR bit definitions */
@@ -57,8 +57,6 @@ static inline void guts_set_dmuxcr(struct ccsr_guts __iomem *guts,
/* There's only one global utilities register */
static phys_addr_t guts_phys;
-#define DAI_NAME_SIZE 32
-
/**
* machine_data: machine-specific ASoC device data
*
@@ -75,7 +73,6 @@ struct machine_data {
unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */
unsigned int dma_id[2]; /* 0 = DMA1, 1 = DMA2, etc */
unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/
- char codec_name[DAI_NAME_SIZE];
char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */
};
@@ -191,136 +188,6 @@ static struct snd_soc_ops p1022_ds_ops = {
};
/**
- * get_node_by_phandle_name - get a node by its phandle name
- *
- * This function takes a node, the name of a property in that node, and a
- * compatible string. Assuming the property is a phandle to another node,
- * it returns that node, (optionally) if that node is compatible.
- *
- * If the property is not a phandle, or the node it points to is not compatible
- * with the specific string, then NULL is returned.
- */
-static struct device_node *get_node_by_phandle_name(struct device_node *np,
- const char *name, const char *compatible)
-{
- np = of_parse_phandle(np, name, 0);
- if (!np)
- return NULL;
-
- if (!of_device_is_compatible(np, compatible)) {
- of_node_put(np);
- return NULL;
- }
-
- return np;
-}
-
-/**
- * get_parent_cell_index -- return the cell-index of the parent of a node
- *
- * Return the value of the cell-index property of the parent of the given
- * node. This is used for DMA channel nodes that need to know the DMA ID
- * of the controller they are on.
- */
-static int get_parent_cell_index(struct device_node *np)
-{
- struct device_node *parent = of_get_parent(np);
- const u32 *iprop;
- int ret = -1;
-
- if (!parent)
- return -1;
-
- iprop = of_get_property(parent, "cell-index", NULL);
- if (iprop)
- ret = be32_to_cpup(iprop);
-
- of_node_put(parent);
-
- return ret;
-}
-
-/**
- * codec_node_dev_name - determine the dev_name for a codec node
- *
- * This function determines the dev_name for an I2C node. This is the name
- * that would be returned by dev_name() if this device_node were part of a
- * 'struct device' It's ugly and hackish, but it works.
- *
- * The dev_name for such devices include the bus number and I2C address. For
- * example, "cs4270-codec.0-004f".
- */
-static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
-{
- const u32 *iprop;
- int addr;
- char temp[DAI_NAME_SIZE];
- struct i2c_client *i2c;
-
- of_modalias_node(np, temp, DAI_NAME_SIZE);
-
- iprop = of_get_property(np, "reg", NULL);
- if (!iprop)
- return -EINVAL;
-
- addr = be32_to_cpup(iprop);
-
- /* We need the adapter number */
- i2c = of_find_i2c_device_by_node(np);
- if (!i2c)
- return -ENODEV;
-
- snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr);
-
- return 0;
-}
-
-static int get_dma_channel(struct device_node *ssi_np,
- const char *name,
- struct snd_soc_dai_link *dai,
- unsigned int *dma_channel_id,
- unsigned int *dma_id)
-{
- struct resource res;
- struct device_node *dma_channel_np;
- const u32 *iprop;
- int ret;
-
- dma_channel_np = get_node_by_phandle_name(ssi_np, name,
- "fsl,ssi-dma-channel");
- if (!dma_channel_np)
- return -EINVAL;
-
- /* Determine the dev_name for the device_node. This code mimics the
- * behavior of of_device_make_bus_id(). We need this because ASoC uses
- * the dev_name() of the device to match the platform (DMA) device with
- * the CPU (SSI) device. It's all ugly and hackish, but it works (for
- * now).
- *
- * dai->platform name should already point to an allocated buffer.
- */
- ret = of_address_to_resource(dma_channel_np, 0, &res);
- if (ret) {
- of_node_put(dma_channel_np);
- return ret;
- }
- snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s",
- (unsigned long long) res.start, dma_channel_np->name);
-
- iprop = of_get_property(dma_channel_np, "cell-index", NULL);
- if (!iprop) {
- of_node_put(dma_channel_np);
- return -EINVAL;
- }
-
- *dma_channel_id = be32_to_cpup(iprop);
- *dma_id = get_parent_cell_index(dma_channel_np);
- of_node_put(dma_channel_np);
-
- return 0;
-}
-
-/**
* p1022_ds_probe: platform probe function for the machine driver
*
* Although this is a machine driver, the SSI node is the "master" node with
@@ -357,15 +224,8 @@ static int p1022_ds_probe(struct platform_device *pdev)
mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev);
mdata->dai[0].ops = &p1022_ds_ops;
- /* Determine the codec name, it will be used as the codec DAI name */
- ret = codec_node_dev_name(codec_np, mdata->codec_name, DAI_NAME_SIZE);
- if (ret) {
- dev_err(&pdev->dev, "invalid codec node %s\n",
- codec_np->full_name);
- ret = -EINVAL;
- goto error;
- }
- mdata->dai[0].codec_name = mdata->codec_name;
+ /* ASoC core can match codec with device node */
+ mdata->dai[0].codec_of_node = codec_np;
/* We register two DAIs per SSI, one for playback and the other for
* capture. We support codecs that have separate DAIs for both playback
@@ -462,9 +322,9 @@ static int p1022_ds_probe(struct platform_device *pdev)
/* Find the playback DMA channel to use. */
mdata->dai[0].platform_name = mdata->platform_name[0];
- ret = get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0],
- &mdata->dma_channel_id[0],
- &mdata->dma_id[0]);
+ ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0],
+ &mdata->dma_channel_id[0],
+ &mdata->dma_id[0]);
if (ret) {
dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n");
goto error;
@@ -472,9 +332,9 @@ static int p1022_ds_probe(struct platform_device *pdev)
/* Find the capture DMA channel to use. */
mdata->dai[1].platform_name = mdata->platform_name[1];
- ret = get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1],
- &mdata->dma_channel_id[1],
- &mdata->dma_id[1]);
+ ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1],
+ &mdata->dma_channel_id[1],
+ &mdata->dma_id[1]);
if (ret) {
dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n");
goto error;
diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/fsl/phycore-ac97.c
index f8da6dd115ed..f8da6dd115ed 100644
--- a/sound/soc/imx/phycore-ac97.c
+++ b/sound/soc/fsl/phycore-ac97.c
diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c
index fe54a69073e5..fe54a69073e5 100644
--- a/sound/soc/imx/wm1133-ev1.c
+++ b/sound/soc/fsl/wm1133-ev1.c
diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig
new file mode 100644
index 000000000000..610f61251640
--- /dev/null
+++ b/sound/soc/generic/Kconfig
@@ -0,0 +1,4 @@
+config SND_SIMPLE_CARD
+ tristate "ASoC Simple sound card support"
+ help
+ This option enables generic simple sound card support
diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile
new file mode 100644
index 000000000000..9c3b246792bf
--- /dev/null
+++ b/sound/soc/generic/Makefile
@@ -0,0 +1,3 @@
+snd-soc-simple-card-objs := simple-card.o
+
+obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
new file mode 100644
index 000000000000..b4b4cab30232
--- /dev/null
+++ b/sound/soc/generic/simple-card.c
@@ -0,0 +1,114 @@
+/*
+ * ASoC simple sound card support
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.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/platform_device.h>
+#include <linux/module.h>
+#include <sound/simple_card.h>
+
+#define asoc_simple_get_card_info(p) \
+ container_of(p->dai_link, struct asoc_simple_card_info, snd_link)
+
+static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct asoc_simple_card_info *cinfo = asoc_simple_get_card_info(rtd);
+ struct asoc_simple_dai_init_info *iinfo = cinfo->init;
+ struct snd_soc_dai *codec = rtd->codec_dai;
+ struct snd_soc_dai *cpu = rtd->cpu_dai;
+ unsigned int cpu_daifmt = iinfo->fmt | iinfo->cpu_daifmt;
+ unsigned int codec_daifmt = iinfo->fmt | iinfo->codec_daifmt;
+ int ret;
+
+ if (codec_daifmt) {
+ ret = snd_soc_dai_set_fmt(codec, codec_daifmt);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (iinfo->sysclk) {
+ ret = snd_soc_dai_set_sysclk(codec, 0, iinfo->sysclk, 0);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (cpu_daifmt) {
+ ret = snd_soc_dai_set_fmt(cpu, cpu_daifmt);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int asoc_simple_card_probe(struct platform_device *pdev)
+{
+ struct asoc_simple_card_info *cinfo = pdev->dev.platform_data;
+
+ if (!cinfo) {
+ dev_err(&pdev->dev, "no info for asoc-simple-card\n");
+ return -EINVAL;
+ }
+
+ if (!cinfo->name ||
+ !cinfo->card ||
+ !cinfo->cpu_dai ||
+ !cinfo->codec ||
+ !cinfo->platform ||
+ !cinfo->codec_dai) {
+ dev_err(&pdev->dev, "insufficient asoc_simple_card_info settings\n");
+ return -EINVAL;
+ }
+
+ /*
+ * init snd_soc_dai_link
+ */
+ cinfo->snd_link.name = cinfo->name;
+ cinfo->snd_link.stream_name = cinfo->name;
+ cinfo->snd_link.cpu_dai_name = cinfo->cpu_dai;
+ cinfo->snd_link.platform_name = cinfo->platform;
+ cinfo->snd_link.codec_name = cinfo->codec;
+ cinfo->snd_link.codec_dai_name = cinfo->codec_dai;
+
+ /* enable snd_link.init if cinfo has settings */
+ if (cinfo->init)
+ cinfo->snd_link.init = asoc_simple_card_dai_init;
+
+ /*
+ * init snd_soc_card
+ */
+ cinfo->snd_card.name = cinfo->card;
+ cinfo->snd_card.owner = THIS_MODULE;
+ cinfo->snd_card.dai_link = &cinfo->snd_link;
+ cinfo->snd_card.num_links = 1;
+ cinfo->snd_card.dev = &pdev->dev;
+
+ return snd_soc_register_card(&cinfo->snd_card);
+}
+
+static int asoc_simple_card_remove(struct platform_device *pdev)
+{
+ struct asoc_simple_card_info *cinfo = pdev->dev.platform_data;
+
+ return snd_soc_unregister_card(&cinfo->snd_card);
+}
+
+static struct platform_driver asoc_simple_card = {
+ .driver = {
+ .name = "asoc-simple-card",
+ },
+ .probe = asoc_simple_card_probe,
+ .remove = asoc_simple_card_remove,
+};
+
+module_platform_driver(asoc_simple_card);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ASoC Simple Sound Card");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
deleted file mode 100644
index 810acaa09009..000000000000
--- a/sound/soc/imx/Kconfig
+++ /dev/null
@@ -1,79 +0,0 @@
-menuconfig SND_IMX_SOC
- tristate "SoC Audio for Freescale i.MX CPUs"
- depends on ARCH_MXC
- help
- Say Y or M if you want to add support for codecs attached to
- the i.MX SSI interface.
-
-
-if SND_IMX_SOC
-
-config SND_SOC_IMX_SSI
- tristate
-
-config SND_SOC_IMX_PCM
- tristate
-
-config SND_MXC_SOC_FIQ
- tristate
- select FIQ
- select SND_SOC_IMX_PCM
-
-config SND_MXC_SOC_MX2
- select SND_SOC_DMAENGINE_PCM
- tristate
- select SND_SOC_IMX_PCM
-
-config SND_SOC_IMX_AUDMUX
- tristate
-
-config SND_MXC_SOC_WM1133_EV1
- tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted"
- depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
- select SND_SOC_WM8350
- select SND_MXC_SOC_FIQ
- select SND_SOC_IMX_AUDMUX
- select SND_SOC_IMX_SSI
- help
- Enable support for audio on the i.MX31ADS with the WM1133-EV1
- PMIC board with WM8835x fitted.
-
-config SND_SOC_MX27VIS_AIC32X4
- tristate "SoC audio support for Visstrim M10 boards"
- depends on MACH_IMX27_VISSTRIM_M10 && I2C
- select SND_SOC_TLV320AIC32X4
- select SND_MXC_SOC_MX2
- select SND_SOC_IMX_AUDMUX
- select SND_SOC_IMX_SSI
- help
- Say Y if you want to add support for SoC audio on Visstrim SM10
- board with TLV320AIC32X4 codec.
-
-config SND_SOC_PHYCORE_AC97
- tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
- depends on MACH_PCM043 || MACH_PCA100
- select SND_SOC_AC97_BUS
- select SND_SOC_WM9712
- select SND_MXC_SOC_FIQ
- select SND_SOC_IMX_AUDMUX
- select SND_SOC_IMX_SSI
- help
- Say Y if you want to add support for SoC audio on Phytec phyCORE
- and phyCARD boards in AC97 mode
-
-config SND_SOC_EUKREA_TLV320
- tristate "Eukrea TLV320"
- depends on MACH_EUKREA_MBIMX27_BASEBOARD \
- || MACH_EUKREA_MBIMXSD25_BASEBOARD \
- || MACH_EUKREA_MBIMXSD35_BASEBOARD \
- || MACH_EUKREA_MBIMXSD51_BASEBOARD
- depends on I2C
- select SND_SOC_TLV320AIC23
- select SND_MXC_SOC_FIQ
- select SND_SOC_IMX_AUDMUX
- select SND_SOC_IMX_SSI
- help
- Enable I2S based access to the TLV320AIC23B codec attached
- to the SSI interface
-
-endif # SND_IMX_SOC
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
deleted file mode 100644
index f5db3e92d0d1..000000000000
--- a/sound/soc/imx/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-# i.MX Platform Support
-snd-soc-imx-ssi-objs := imx-ssi.o
-snd-soc-imx-audmux-objs := imx-audmux.o
-
-obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
-obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
-
-obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o
-snd-soc-imx-pcm-y := imx-pcm.o
-snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_FIQ) += imx-pcm-fiq.o
-snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_MX2) += imx-pcm-dma-mx2.o
-
-# i.MX Machine Support
-snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
-snd-soc-phycore-ac97-objs := phycore-ac97.o
-snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o
-snd-soc-wm1133-ev1-objs := wm1133-ev1.o
-
-obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
-obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
-obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o
-obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index a5af7c42e62b..41349670adab 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -346,7 +346,7 @@ static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
/* Playback */
dma_config = &i2s->pcm_config_playback.dma_config;
- dma_config->src_width = JZ4740_DMA_WIDTH_32BIT,
+ dma_config->src_width = JZ4740_DMA_WIDTH_32BIT;
dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT;
dma_config->flags = JZ4740_DMA_SRC_AUTOINC;
@@ -355,7 +355,7 @@ static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
/* Capture */
dma_config = &i2s->pcm_config_capture.dma_config;
- dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT,
+ dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT;
dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE;
dma_config->flags = JZ4740_DMA_DST_AUTOINC;
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index e373fbbc97a0..373dec90579f 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -220,28 +220,16 @@ static struct snd_soc_platform_driver mxs_soc_platform = {
.pcm_free = mxs_pcm_free,
};
-static int __devinit mxs_soc_platform_probe(struct platform_device *pdev)
+int __devinit mxs_pcm_platform_register(struct device *dev)
{
- return snd_soc_register_platform(&pdev->dev, &mxs_soc_platform);
+ return snd_soc_register_platform(dev, &mxs_soc_platform);
}
+EXPORT_SYMBOL_GPL(mxs_pcm_platform_register);
-static int __devexit mxs_soc_platform_remove(struct platform_device *pdev)
+void __devexit mxs_pcm_platform_unregister(struct device *dev)
{
- snd_soc_unregister_platform(&pdev->dev);
-
- return 0;
+ snd_soc_unregister_platform(dev);
}
-
-static struct platform_driver mxs_pcm_driver = {
- .driver = {
- .name = "mxs-pcm-audio",
- .owner = THIS_MODULE,
- },
- .probe = mxs_soc_platform_probe,
- .remove = __devexit_p(mxs_soc_platform_remove),
-};
-
-module_platform_driver(mxs_pcm_driver);
+EXPORT_SYMBOL_GPL(mxs_pcm_platform_unregister);
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:mxs-pcm-audio");
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h
index 5f01a9124b3d..35ba2ca42384 100644
--- a/sound/soc/mxs/mxs-pcm.h
+++ b/sound/soc/mxs/mxs-pcm.h
@@ -24,4 +24,7 @@ struct mxs_pcm_dma_params {
int chan_num;
};
+int mxs_pcm_platform_register(struct device *dev);
+void mxs_pcm_platform_unregister(struct device *dev);
+
#endif
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index 53f4fd8feced..aba71bfa33b1 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -18,6 +18,8 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
@@ -25,6 +27,7 @@
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/fsl/mxs-dma.h>
+#include <linux/pinctrl/consumer.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -620,34 +623,61 @@ static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int mxs_saif_probe(struct platform_device *pdev)
+static int __devinit mxs_saif_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
struct resource *iores, *dmares;
struct mxs_saif *saif;
struct mxs_saif_platform_data *pdata;
+ struct pinctrl *pinctrl;
int ret = 0;
- if (pdev->id >= ARRAY_SIZE(mxs_saif))
+
+ if (!np && pdev->id >= ARRAY_SIZE(mxs_saif))
return -EINVAL;
saif = devm_kzalloc(&pdev->dev, sizeof(*saif), GFP_KERNEL);
if (!saif)
return -ENOMEM;
- mxs_saif[pdev->id] = saif;
- saif->id = pdev->id;
-
- pdata = pdev->dev.platform_data;
- if (pdata && !pdata->master_mode) {
- saif->master_id = pdata->master_id;
- if (saif->master_id < 0 ||
- saif->master_id >= ARRAY_SIZE(mxs_saif) ||
- saif->master_id == saif->id) {
- dev_err(&pdev->dev, "get wrong master id\n");
- return -EINVAL;
+ if (np) {
+ struct device_node *master;
+ saif->id = of_alias_get_id(np, "saif");
+ if (saif->id < 0)
+ return saif->id;
+ /*
+ * If there is no "fsl,saif-master" phandle, it's a saif
+ * master. Otherwise, it's a slave and its phandle points
+ * to the master.
+ */
+ master = of_parse_phandle(np, "fsl,saif-master", 0);
+ if (!master) {
+ saif->master_id = saif->id;
+ } else {
+ saif->master_id = of_alias_get_id(master, "saif");
+ if (saif->master_id < 0)
+ return saif->master_id;
}
} else {
- saif->master_id = saif->id;
+ saif->id = pdev->id;
+ pdata = pdev->dev.platform_data;
+ if (pdata && !pdata->master_mode)
+ saif->master_id = pdata->master_id;
+ else
+ saif->master_id = saif->id;
+ }
+
+ if (saif->master_id < 0 || saif->master_id >= ARRAY_SIZE(mxs_saif)) {
+ dev_err(&pdev->dev, "get wrong master id\n");
+ return -EINVAL;
+ }
+
+ mxs_saif[saif->id] = saif;
+
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ return ret;
}
saif->clk = clk_get(&pdev->dev, NULL);
@@ -669,12 +699,19 @@ static int mxs_saif_probe(struct platform_device *pdev)
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (!dmares) {
- ret = -ENODEV;
- dev_err(&pdev->dev, "failed to get dma resource: %d\n",
- ret);
- goto failed_get_resource;
+ /*
+ * TODO: This is a temporary solution and should be changed
+ * to use generic DMA binding later when the helplers get in.
+ */
+ ret = of_property_read_u32(np, "fsl,saif-dma-channel",
+ &saif->dma_param.chan_num);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get dma channel\n");
+ goto failed_get_resource;
+ }
+ } else {
+ saif->dma_param.chan_num = dmares->start;
}
- saif->dma_param.chan_num = dmares->start;
saif->irq = platform_get_irq(pdev, 0);
if (saif->irq < 0) {
@@ -708,24 +745,14 @@ static int mxs_saif_probe(struct platform_device *pdev)
goto failed_get_resource;
}
- saif->soc_platform_pdev = platform_device_alloc(
- "mxs-pcm-audio", pdev->id);
- if (!saif->soc_platform_pdev) {
- ret = -ENOMEM;
- goto failed_pdev_alloc;
- }
-
- platform_set_drvdata(saif->soc_platform_pdev, saif);
- ret = platform_device_add(saif->soc_platform_pdev);
+ ret = mxs_pcm_platform_register(&pdev->dev);
if (ret) {
- dev_err(&pdev->dev, "failed to add soc platform device\n");
- goto failed_pdev_add;
+ dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
+ goto failed_pdev_alloc;
}
return 0;
-failed_pdev_add:
- platform_device_put(saif->soc_platform_pdev);
failed_pdev_alloc:
snd_soc_unregister_dai(&pdev->dev);
failed_get_resource:
@@ -738,13 +765,19 @@ static int __devexit mxs_saif_remove(struct platform_device *pdev)
{
struct mxs_saif *saif = platform_get_drvdata(pdev);
- platform_device_unregister(saif->soc_platform_pdev);
+ mxs_pcm_platform_unregister(&pdev->dev);
snd_soc_unregister_dai(&pdev->dev);
clk_put(saif->clk);
return 0;
}
+static const struct of_device_id mxs_saif_dt_ids[] = {
+ { .compatible = "fsl,imx28-saif", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxs_saif_dt_ids);
+
static struct platform_driver mxs_saif_driver = {
.probe = mxs_saif_probe,
.remove = __devexit_p(mxs_saif_remove),
@@ -752,6 +785,7 @@ static struct platform_driver mxs_saif_driver = {
.driver = {
.name = "mxs-saif",
.owner = THIS_MODULE,
+ .of_match_table = mxs_saif_dt_ids,
},
};
diff --git a/sound/soc/mxs/mxs-saif.h b/sound/soc/mxs/mxs-saif.h
index 12c91e4eb941..3cb342e5bc90 100644
--- a/sound/soc/mxs/mxs-saif.h
+++ b/sound/soc/mxs/mxs-saif.h
@@ -123,7 +123,6 @@ struct mxs_saif {
unsigned int cur_rate;
unsigned int ongoing;
- struct platform_device *soc_platform_pdev;
u32 fifo_underrun;
u32 fifo_overrun;
};
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
index 60f052b7cf22..3e6e8764b2e6 100644
--- a/sound/soc/mxs/mxs-sgtl5000.c
+++ b/sound/soc/mxs/mxs-sgtl5000.c
@@ -18,6 +18,8 @@
#include <linux/module.h>
#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -90,7 +92,7 @@ static struct snd_soc_dai_link mxs_sgtl5000_dai[] = {
.codec_dai_name = "sgtl5000",
.codec_name = "sgtl5000.0-000a",
.cpu_dai_name = "mxs-saif.0",
- .platform_name = "mxs-pcm-audio.0",
+ .platform_name = "mxs-saif.0",
.ops = &mxs_sgtl5000_hifi_ops,
}, {
.name = "HiFi Rx",
@@ -98,7 +100,7 @@ static struct snd_soc_dai_link mxs_sgtl5000_dai[] = {
.codec_dai_name = "sgtl5000",
.codec_name = "sgtl5000.0-000a",
.cpu_dai_name = "mxs-saif.1",
- .platform_name = "mxs-pcm-audio.1",
+ .platform_name = "mxs-saif.1",
.ops = &mxs_sgtl5000_hifi_ops,
},
};
@@ -110,11 +112,48 @@ static struct snd_soc_card mxs_sgtl5000 = {
.num_links = ARRAY_SIZE(mxs_sgtl5000_dai),
};
+static int __devinit mxs_sgtl5000_probe_dt(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *saif_np[2], *codec_np;
+ int i, ret = 0;
+
+ if (!np)
+ return 1; /* no device tree */
+
+ saif_np[0] = of_parse_phandle(np, "saif-controllers", 0);
+ saif_np[1] = of_parse_phandle(np, "saif-controllers", 1);
+ codec_np = of_parse_phandle(np, "audio-codec", 0);
+ if (!saif_np[0] || !saif_np[1] || !codec_np) {
+ dev_err(&pdev->dev, "phandle missing or invalid\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < 2; i++) {
+ mxs_sgtl5000_dai[i].codec_name = NULL;
+ mxs_sgtl5000_dai[i].codec_of_node = codec_np;
+ mxs_sgtl5000_dai[i].cpu_dai_name = NULL;
+ mxs_sgtl5000_dai[i].cpu_dai_of_node = saif_np[i];
+ mxs_sgtl5000_dai[i].platform_name = NULL;
+ mxs_sgtl5000_dai[i].platform_of_node = saif_np[i];
+ }
+
+ of_node_put(codec_np);
+ of_node_put(saif_np[0]);
+ of_node_put(saif_np[1]);
+
+ return ret;
+}
+
static int __devinit mxs_sgtl5000_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &mxs_sgtl5000;
int ret;
+ ret = mxs_sgtl5000_probe_dt(pdev);
+ if (ret < 0)
+ return ret;
+
/*
* Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w).
* The Sgtl5000 sysclk is derived from saif0 mclk and it's range
@@ -148,10 +187,17 @@ static int __devexit mxs_sgtl5000_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id mxs_sgtl5000_dt_ids[] = {
+ { .compatible = "fsl,mxs-audio-sgtl5000", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxs_sgtl5000_dt_ids);
+
static struct platform_driver mxs_sgtl5000_audio_driver = {
.driver = {
.name = "mxs-sgtl5000",
.owner = THIS_MODULE,
+ .of_match_table = mxs_sgtl5000_dt_ids,
},
.probe = mxs_sgtl5000_probe,
.remove = __devexit_p(mxs_sgtl5000_remove),
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index deafbfaacdbf..9ccfa5e1c11b 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -113,6 +113,7 @@ config SND_OMAP_SOC_OMAP4_HDMI
tristate "SoC Audio support for Texas Instruments OMAP4 HDMI"
depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS && ARCH_OMAP4
select SND_OMAP_SOC_HDMI
+ select SND_SOC_OMAP_HDMI_CODEC
help
Say Y if you want to add support for SoC HDMI audio on Texas Instruments
OMAP4 chips
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index fd04ce139031..1c2aa7fab3fd 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -85,14 +85,12 @@ struct pxa2xx_pcm_dma_data {
char name[20];
};
-static struct pxa2xx_pcm_dma_params *
-pxa_ssp_get_dma_params(struct ssp_device *ssp, int width4, int out)
+static void pxa_ssp_set_dma_params(struct ssp_device *ssp, int width4,
+ int out, struct pxa2xx_pcm_dma_params *dma_data)
{
struct pxa2xx_pcm_dma_data *dma;
- dma = kzalloc(sizeof(struct pxa2xx_pcm_dma_data), GFP_KERNEL);
- if (dma == NULL)
- return NULL;
+ dma = container_of(dma_data, struct pxa2xx_pcm_dma_data, params);
snprintf(dma->name, 20, "SSP%d PCM %s %s", ssp->port_id,
width4 ? "32-bit" : "16-bit", out ? "out" : "in");
@@ -103,8 +101,6 @@ pxa_ssp_get_dma_params(struct ssp_device *ssp, int width4, int out)
(DCMD_INCTRGADDR | DCMD_FLOWSRC)) |
(width4 ? DCMD_WIDTH4 : DCMD_WIDTH2) | DCMD_BURST16;
dma->params.dev_addr = ssp->phys_base + SSDR;
-
- return &dma->params;
}
static int pxa_ssp_startup(struct snd_pcm_substream *substream,
@@ -112,6 +108,7 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
{
struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
struct ssp_device *ssp = priv->ssp;
+ struct pxa2xx_pcm_dma_data *dma;
int ret = 0;
if (!cpu_dai->active) {
@@ -119,8 +116,10 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
pxa_ssp_disable(ssp);
}
- kfree(snd_soc_dai_get_dma_data(cpu_dai, substream));
- snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
+ dma = kzalloc(sizeof(struct pxa2xx_pcm_dma_data), GFP_KERNEL);
+ if (!dma)
+ return -ENOMEM;
+ snd_soc_dai_set_dma_data(cpu_dai, substream, &dma->params);
return ret;
}
@@ -573,18 +572,13 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);
- /* generate correct DMA params */
- kfree(dma_data);
-
/* Network mode with one active slot (ttsa == 1) can be used
* to force 16-bit frame width on the wire (for S16_LE), even
* with two channels. Use 16-bit DMA transfers for this case.
*/
- dma_data = pxa_ssp_get_dma_params(ssp,
- ((chn == 2) && (ttsa != 1)) || (width == 32),
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
-
- snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
+ pxa_ssp_set_dma_params(ssp,
+ ((chn == 2) && (ttsa != 1)) || (width == 32),
+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK, dma_data);
/* we can only change the settings if the port is not in use */
if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index d08583790d23..3075a426124c 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -166,7 +166,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
struct pxa2xx_pcm_dma_params *dma_data;
BUG_ON(IS_ERR(clk_i2s));
- clk_enable(clk_i2s);
+ clk_prepare_enable(clk_i2s);
clk_ena = 1;
pxa_i2s_wait();
@@ -259,7 +259,7 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
SACR0 &= ~SACR0_ENB;
pxa_i2s_wait();
if (clk_ena) {
- clk_disable(clk_i2s);
+ clk_disable_unprepare(clk_i2s);
clk_ena = 0;
}
}
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
index e7416851bf7d..c82c646b8a08 100644
--- a/sound/soc/samsung/littlemill.c
+++ b/sound/soc/samsung/littlemill.c
@@ -23,10 +23,10 @@ static int littlemill_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai;
int ret;
- if (dapm->dev != codec_dai->dev)
+ if (dapm->dev != aif1_dai->dev)
return 0;
switch (level) {
@@ -36,7 +36,7 @@ static int littlemill_set_bias_level(struct snd_soc_card *card,
* then do so now, otherwise these are noops.
*/
if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
- ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1,
+ ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1,
WM8994_FLL_SRC_MCLK2, 32768,
sample_rate * 512);
if (ret < 0) {
@@ -44,7 +44,7 @@ static int littlemill_set_bias_level(struct snd_soc_card *card,
return ret;
}
- ret = snd_soc_dai_set_sysclk(codec_dai,
+ ret = snd_soc_dai_set_sysclk(aif1_dai,
WM8994_SYSCLK_FLL1,
sample_rate * 512,
SND_SOC_CLOCK_IN);
@@ -66,25 +66,25 @@ static int littlemill_set_bias_level_post(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai;
int ret;
- if (dapm->dev != codec_dai->dev)
+ if (dapm->dev != aif1_dai->dev)
return 0;
switch (level) {
case SND_SOC_BIAS_STANDBY:
- ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK2,
+ ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2,
32768, SND_SOC_CLOCK_IN);
if (ret < 0) {
- pr_err("Failed to switch away from FLL: %d\n", ret);
+ pr_err("Failed to switch away from FLL1: %d\n", ret);
return ret;
}
- ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1,
+ ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1,
0, 0, 0);
if (ret < 0) {
- pr_err("Failed to stop FLL: %d\n", ret);
+ pr_err("Failed to stop FLL1: %d\n", ret);
return ret;
}
break;
@@ -131,6 +131,14 @@ static struct snd_soc_ops littlemill_ops = {
.hw_params = littlemill_hw_params,
};
+static const struct snd_soc_pcm_stream baseband_params = {
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+ .rate_min = 8000,
+ .rate_max = 8000,
+ .channels_min = 2,
+ .channels_max = 2,
+};
+
static struct snd_soc_dai_link littlemill_dai[] = {
{
.name = "CPU",
@@ -143,13 +151,75 @@ static struct snd_soc_dai_link littlemill_dai[] = {
| SND_SOC_DAIFMT_CBM_CFM,
.ops = &littlemill_ops,
},
+ {
+ .name = "Baseband",
+ .stream_name = "Baseband",
+ .cpu_dai_name = "wm8994-aif2",
+ .codec_dai_name = "wm1250-ev1",
+ .codec_name = "wm1250-ev1.1-0027",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM,
+ .ignore_suspend = 1,
+ .params = &baseband_params,
+ },
};
+static int bbclk_ev(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_card *card = w->dapm->card;
+ struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai;
+ int ret;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ ret = snd_soc_dai_set_pll(aif2_dai, WM8994_FLL2,
+ WM8994_FLL_SRC_BCLK, 64 * 8000,
+ 8000 * 256);
+ if (ret < 0) {
+ pr_err("Failed to start FLL: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(aif2_dai, WM8994_SYSCLK_FLL2,
+ 8000 * 256,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ pr_err("Failed to set SYSCLK: %d\n", ret);
+ return ret;
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ ret = snd_soc_dai_set_sysclk(aif2_dai, WM8994_SYSCLK_MCLK2,
+ 32768, SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ pr_err("Failed to switch away from FLL2: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_pll(aif2_dai, WM8994_FLL2,
+ 0, 0, 0);
+ if (ret < 0) {
+ pr_err("Failed to stop FLL2: %d\n", ret);
+ return ret;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static struct snd_soc_dapm_widget widgets[] = {
SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("AMIC", NULL),
SND_SOC_DAPM_MIC("DMIC", NULL),
+
+ SND_SOC_DAPM_SUPPLY_S("Baseband Clock", -1, SND_SOC_NOPM, 0, 0,
+ bbclk_ev,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
};
static struct snd_soc_dapm_route audio_paths[] = {
@@ -162,6 +232,8 @@ static struct snd_soc_dapm_route audio_paths[] = {
{ "DMIC", NULL, "MICBIAS2" }, /* Default for DMICBIAS jumper */
{ "DMIC1DAT", NULL, "DMIC" },
{ "DMIC2DAT", NULL, "DMIC" },
+
+ { "AIF2CLK", NULL, "Baseband Clock" },
};
static struct snd_soc_jack littlemill_headset;
@@ -169,10 +241,16 @@ static struct snd_soc_jack littlemill_headset;
static int littlemill_late_probe(struct snd_soc_card *card)
{
struct snd_soc_codec *codec = card->rtd[0].codec;
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai;
+ struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai;
int ret;
- ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK2,
+ ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2,
+ 32768, SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(aif2_dai, WM8994_SYSCLK_MCLK2,
32768, SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c
index 4adff934f771..6abf341c4a2a 100644
--- a/sound/soc/samsung/lowland.c
+++ b/sound/soc/samsung/lowland.c
@@ -21,33 +21,6 @@
#define MCLK1_RATE (44100 * 512)
#define CLKOUT_RATE (44100 * 256)
-static int lowland_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- int ret;
-
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
- | SND_SOC_DAIFMT_NB_NF
- | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
- | SND_SOC_DAIFMT_NB_NF
- | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static struct snd_soc_ops lowland_ops = {
- .hw_params = lowland_hw_params,
-};
-
static struct snd_soc_jack lowland_headset;
/* Headset jack detection DAPM pins */
@@ -101,6 +74,25 @@ static int lowland_wm5100_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
+static int lowland_wm9081_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+
+ snd_soc_dapm_nc_pin(&codec->dapm, "LINEOUT");
+
+ /* At any time the WM9081 is active it will have this clock */
+ return snd_soc_codec_set_sysclk(codec, WM9081_SYSCLK_MCLK, 0,
+ CLKOUT_RATE, 0);
+}
+
+static const struct snd_soc_pcm_stream sub_params = {
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+ .rate_min = 44100,
+ .rate_max = 44100,
+ .channels_min = 2,
+ .channels_max = 2,
+};
+
static struct snd_soc_dai_link lowland_dai[] = {
{
.name = "CPU",
@@ -109,7 +101,8 @@ static struct snd_soc_dai_link lowland_dai[] = {
.codec_dai_name = "wm5100-aif1",
.platform_name = "samsung-audio",
.codec_name = "wm5100.1-001a",
- .ops = &lowland_ops,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.init = lowland_wm5100_init,
},
{
@@ -118,24 +111,20 @@ static struct snd_soc_dai_link lowland_dai[] = {
.cpu_dai_name = "wm5100-aif2",
.codec_dai_name = "wm1250-ev1",
.codec_name = "wm1250-ev1.1-0027",
- .ops = &lowland_ops,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.ignore_suspend = 1,
},
-};
-
-static int lowland_wm9081_init(struct snd_soc_dapm_context *dapm)
-{
- snd_soc_dapm_nc_pin(dapm, "LINEOUT");
-
- /* At any time the WM9081 is active it will have this clock */
- return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK, 0,
- CLKOUT_RATE, 0);
-}
-
-static struct snd_soc_aux_dev lowland_aux_dev[] = {
{
- .name = "wm9081",
+ .name = "Sub Speaker",
+ .stream_name = "Sub Speaker",
+ .cpu_dai_name = "wm5100-aif3",
+ .codec_dai_name = "wm9081-hifi",
.codec_name = "wm9081.1-006c",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
+ .ignore_suspend = 1,
+ .params = &sub_params,
.init = lowland_wm9081_init,
},
};
@@ -180,8 +169,6 @@ static struct snd_soc_card lowland = {
.owner = THIS_MODULE,
.dai_link = lowland_dai,
.num_links = ARRAY_SIZE(lowland_dai),
- .aux_dev = lowland_aux_dev,
- .num_aux_devs = ARRAY_SIZE(lowland_aux_dev),
.codec_conf = lowland_codec_conf,
.num_configs = ARRAY_SIZE(lowland_codec_conf),
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c
index f9ab7707a3e4..a4a9fc7e8c76 100644
--- a/sound/soc/samsung/speyside.c
+++ b/sound/soc/samsung/speyside.c
@@ -92,33 +92,6 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card,
return 0;
}
-static int speyside_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- int ret;
-
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
- | SND_SOC_DAIFMT_NB_NF
- | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
- | SND_SOC_DAIFMT_NB_NF
- | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static struct snd_soc_ops speyside_ops = {
- .hw_params = speyside_hw_params,
-};
-
static struct snd_soc_jack speyside_headset;
/* Headset jack detection DAPM pins */
@@ -208,7 +181,8 @@ static struct snd_soc_dai_link speyside_dai[] = {
.platform_name = "samsung-audio",
.codec_name = "wm8996.1-001a",
.init = speyside_wm8996_init,
- .ops = &speyside_ops,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM,
},
{
.name = "Baseband",
@@ -216,7 +190,8 @@ static struct snd_soc_dai_link speyside_dai[] = {
.cpu_dai_name = "wm8996-aif2",
.codec_dai_name = "wm1250-ev1",
.codec_name = "wm1250-ev1.1-0027",
- .ops = &speyside_ops,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM,
.ignore_suspend = 1,
},
};
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index d8e06a607a22..6bcb1164d599 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -22,6 +22,7 @@ config SND_SOC_SH4_SSI
config SND_SOC_SH4_FSI
tristate "SH4 FSI support"
+ select SND_SIMPLE_CARD
help
This option enables FSI sound support
@@ -46,29 +47,6 @@ config SND_SH7760_AC97
This option enables generic sound support for the first
AC97 unit of the SH7760.
-config SND_FSI_AK4642
- tristate "FSI-AK4642 sound support"
- depends on SND_SOC_SH4_FSI && I2C
- select SND_SOC_AK4642
- help
- This option enables generic sound support for the
- FSI - AK4642 unit
-
-config SND_FSI_DA7210
- tristate "FSI-DA7210 sound support"
- depends on SND_SOC_SH4_FSI && I2C
- select SND_SOC_DA7210
- help
- This option enables generic sound support for the
- FSI - DA7210 unit
-
-config SND_FSI_HDMI
- tristate "FSI-HDMI sound support"
- depends on SND_SOC_SH4_FSI && FB_SH_MOBILE_HDMI
- help
- This option enables generic sound support for the
- FSI - HDMI unit
-
config SND_SIU_MIGOR
tristate "SIU sound support on Migo-R"
depends on SH_MIGOR
diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
index 94476d4c0fd5..849b387d17d9 100644
--- a/sound/soc/sh/Makefile
+++ b/sound/soc/sh/Makefile
@@ -14,13 +14,7 @@ obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o
## boards
snd-soc-sh7760-ac97-objs := sh7760-ac97.o
-snd-soc-fsi-ak4642-objs := fsi-ak4642.o
-snd-soc-fsi-da7210-objs := fsi-da7210.o
-snd-soc-fsi-hdmi-objs := fsi-hdmi.o
snd-soc-migor-objs := migor.o
obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o
-obj-$(CONFIG_SND_FSI_AK4642) += snd-soc-fsi-ak4642.o
-obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o
-obj-$(CONFIG_SND_FSI_HDMI) += snd-soc-fsi-hdmi.o
obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
deleted file mode 100644
index 97f540aabbdd..000000000000
--- a/sound/soc/sh/fsi-ak4642.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * FSI-AK464x sound support for ms7724se
- *
- * Copyright (C) 2009 Renesas Solutions Corp.
- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <sound/sh_fsi.h>
-
-struct fsi_ak4642_data {
- const char *name;
- const char *card;
- const char *cpu_dai;
- const char *codec;
- const char *platform;
- int id;
-};
-
-static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_dai *codec = rtd->codec_dai;
- struct snd_soc_dai *cpu = rtd->cpu_dai;
- int ret;
-
- ret = snd_soc_dai_set_fmt(codec, SND_SOC_DAIFMT_LEFT_J |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_sysclk(codec, 0, 11289600, 0);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_LEFT_J |
- SND_SOC_DAIFMT_CBS_CFS);
-
- return ret;
-}
-
-static struct snd_soc_dai_link fsi_dai_link = {
- .codec_dai_name = "ak4642-hifi",
- .init = fsi_ak4642_dai_init,
-};
-
-static struct snd_soc_card fsi_soc_card = {
- .owner = THIS_MODULE,
- .dai_link = &fsi_dai_link,
- .num_links = 1,
-};
-
-static struct platform_device *fsi_snd_device;
-
-static int fsi_ak4642_probe(struct platform_device *pdev)
-{
- int ret = -ENOMEM;
- struct fsi_ak4642_info *pinfo = pdev->dev.platform_data;
-
- if (!pinfo) {
- dev_err(&pdev->dev, "no info for fsi ak4642\n");
- goto out;
- }
-
- fsi_snd_device = platform_device_alloc("soc-audio", pinfo->id);
- if (!fsi_snd_device)
- goto out;
-
- fsi_dai_link.name = pinfo->name;
- fsi_dai_link.stream_name = pinfo->name;
- fsi_dai_link.cpu_dai_name = pinfo->cpu_dai;
- fsi_dai_link.platform_name = pinfo->platform;
- fsi_dai_link.codec_name = pinfo->codec;
- fsi_soc_card.name = pinfo->card;
-
- platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
- ret = platform_device_add(fsi_snd_device);
-
- if (ret)
- platform_device_put(fsi_snd_device);
-
-out:
- return ret;
-}
-
-static int fsi_ak4642_remove(struct platform_device *pdev)
-{
- platform_device_unregister(fsi_snd_device);
- return 0;
-}
-
-static struct platform_driver fsi_ak4642 = {
- .driver = {
- .name = "fsi-ak4642-audio",
- },
- .probe = fsi_ak4642_probe,
- .remove = fsi_ak4642_remove,
-};
-
-module_platform_driver(fsi_ak4642);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic SH4 FSI-AK4642 sound card");
-MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c
deleted file mode 100644
index 1dd3354c7411..000000000000
--- a/sound/soc/sh/fsi-da7210.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * fsi-da7210.c
- *
- * Copyright (C) 2009 Renesas Solutions Corp.
- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <sound/sh_fsi.h>
-
-static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_dai *codec = rtd->codec_dai;
- struct snd_soc_dai *cpu = rtd->cpu_dai;
- int ret;
-
- ret = snd_soc_dai_set_fmt(codec,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_CBS_CFS);
-
- return ret;
-}
-
-static struct snd_soc_dai_link fsi_da7210_dai = {
- .name = "DA7210",
- .stream_name = "DA7210",
- .cpu_dai_name = "fsib-dai", /* FSI B */
- .codec_dai_name = "da7210-hifi",
- .platform_name = "sh_fsi.0",
- .codec_name = "da7210-codec.0-001a",
- .init = fsi_da7210_init,
-};
-
-static struct snd_soc_card fsi_soc_card = {
- .name = "FSI-DA7210",
- .owner = THIS_MODULE,
- .dai_link = &fsi_da7210_dai,
- .num_links = 1,
-};
-
-static struct platform_device *fsi_da7210_snd_device;
-
-static int __init fsi_da7210_sound_init(void)
-{
- int ret;
-
- fsi_da7210_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B);
- if (!fsi_da7210_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(fsi_da7210_snd_device, &fsi_soc_card);
- ret = platform_device_add(fsi_da7210_snd_device);
- if (ret)
- platform_device_put(fsi_da7210_snd_device);
-
- return ret;
-}
-
-static void __exit fsi_da7210_sound_exit(void)
-{
- platform_device_unregister(fsi_da7210_snd_device);
-}
-
-module_init(fsi_da7210_sound_init);
-module_exit(fsi_da7210_sound_exit);
-
-/* Module information */
-MODULE_DESCRIPTION("ALSA SoC FSI DA2710");
-MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c
deleted file mode 100644
index 6e41908323e8..000000000000
--- a/sound/soc/sh/fsi-hdmi.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * FSI - HDMI sound support
- *
- * Copyright (C) 2010 Renesas Solutions Corp.
- * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <sound/sh_fsi.h>
-
-struct fsi_hdmi_data {
- const char *cpu_dai;
- const char *card;
- int id;
-};
-
-static int fsi_hdmi_dai_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_dai *cpu = rtd->cpu_dai;
- int ret;
-
- ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBM_CFM);
-
- return ret;
-}
-
-static struct snd_soc_dai_link fsi_dai_link = {
- .name = "HDMI",
- .stream_name = "HDMI",
- .codec_dai_name = "sh_mobile_hdmi-hifi",
- .platform_name = "sh_fsi2",
- .codec_name = "sh-mobile-hdmi",
- .init = fsi_hdmi_dai_init,
-};
-
-static struct snd_soc_card fsi_soc_card = {
- .owner = THIS_MODULE,
- .dai_link = &fsi_dai_link,
- .num_links = 1,
-};
-
-static struct platform_device *fsi_snd_device;
-
-static int fsi_hdmi_probe(struct platform_device *pdev)
-{
- int ret = -ENOMEM;
- const struct platform_device_id *id_entry;
- struct fsi_hdmi_data *pdata;
-
- id_entry = pdev->id_entry;
- if (!id_entry) {
- dev_err(&pdev->dev, "unknown fsi hdmi\n");
- return -ENODEV;
- }
-
- pdata = (struct fsi_hdmi_data *)id_entry->driver_data;
-
- fsi_snd_device = platform_device_alloc("soc-audio", pdata->id);
- if (!fsi_snd_device)
- goto out;
-
- fsi_dai_link.cpu_dai_name = pdata->cpu_dai;
- fsi_soc_card.name = pdata->card;
-
- platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
- ret = platform_device_add(fsi_snd_device);
-
- if (ret)
- platform_device_put(fsi_snd_device);
-
-out:
- return ret;
-}
-
-static int fsi_hdmi_remove(struct platform_device *pdev)
-{
- platform_device_unregister(fsi_snd_device);
- return 0;
-}
-
-static struct fsi_hdmi_data fsi2_a_hdmi = {
- .cpu_dai = "fsia-dai",
- .card = "FSI2A-HDMI",
- .id = FSI_PORT_A,
-};
-
-static struct fsi_hdmi_data fsi2_b_hdmi = {
- .cpu_dai = "fsib-dai",
- .card = "FSI2B-HDMI",
- .id = FSI_PORT_B,
-};
-
-static struct platform_device_id fsi_id_table[] = {
- /* FSI 2 */
- { "sh_fsi2_a_hdmi", (kernel_ulong_t)&fsi2_a_hdmi },
- { "sh_fsi2_b_hdmi", (kernel_ulong_t)&fsi2_b_hdmi },
- {},
-};
-
-static struct platform_driver fsi_hdmi = {
- .driver = {
- .name = "fsi-hdmi-audio",
- },
- .probe = fsi_hdmi_probe,
- .remove = fsi_hdmi_remove,
- .id_table = fsi_id_table,
-};
-
-module_platform_driver(fsi_hdmi);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic SH4 FSI-HDMI sound card");
-MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 74ed2dffbffd..7cee22515d9d 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -132,6 +132,25 @@
typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
/*
+ * bus options
+ *
+ * 0x000000BA
+ *
+ * A : sample widtht 16bit setting
+ * B : sample widtht 24bit setting
+ */
+
+#define SHIFT_16DATA 0
+#define SHIFT_24DATA 4
+
+#define PACKAGE_24BITBUS_BACK 0
+#define PACKAGE_24BITBUS_FRONT 1
+#define PACKAGE_16BITBUS_STREAM 2
+
+#define BUSOP_SET(s, a) ((a) << SHIFT_ ## s ## DATA)
+#define BUSOP_GET(s, a) (((a) >> SHIFT_ ## s ## DATA) & 0xF)
+
+/*
* FSI driver use below type name for variable
*
* xxx_num : number of data
@@ -189,6 +208,11 @@ struct fsi_stream {
int oerr_num;
/*
+ * bus options
+ */
+ u32 bus_option;
+
+ /*
* thse are initialized by fsi_handler_init()
*/
struct fsi_stream_handler *handler;
@@ -211,8 +235,7 @@ struct fsi_priv {
struct fsi_stream playback;
struct fsi_stream capture;
- u32 do_fmt;
- u32 di_fmt;
+ u32 fmt;
int chan_num:16;
int clk_master:1;
@@ -321,6 +344,10 @@ static void _fsi_master_mask_set(struct fsi_master *master,
/*
* basic function
*/
+static int fsi_version(struct fsi_master *master)
+{
+ return master->core->ver;
+}
static struct fsi_master *fsi_get_master(struct fsi_priv *fsi)
{
@@ -495,6 +522,7 @@ static void fsi_stream_init(struct fsi_priv *fsi,
io->period_samples = fsi_frame2sample(fsi, runtime->period_size);
io->period_pos = 0;
io->sample_width = samples_to_bytes(runtime, 1);
+ io->bus_option = 0;
io->oerr_num = -1; /* ignore 1st err */
io->uerr_num = -1; /* ignore 1st err */
fsi_stream_handler_call(io, init, fsi, io);
@@ -522,6 +550,7 @@ static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io)
io->period_samples = 0;
io->period_pos = 0;
io->sample_width = 0;
+ io->bus_option = 0;
io->oerr_num = 0;
io->uerr_num = 0;
spin_unlock_irqrestore(&master->lock, flags);
@@ -581,6 +610,53 @@ static int fsi_stream_remove(struct fsi_priv *fsi)
}
/*
+ * format/bus/dma setting
+ */
+static void fsi_format_bus_setup(struct fsi_priv *fsi, struct fsi_stream *io,
+ u32 bus, struct device *dev)
+{
+ struct fsi_master *master = fsi_get_master(fsi);
+ int is_play = fsi_stream_is_play(fsi, io);
+ u32 fmt = fsi->fmt;
+
+ if (fsi_version(master) >= 2) {
+ u32 dma = 0;
+
+ /*
+ * FSI2 needs DMA/Bus setting
+ */
+ switch (bus) {
+ case PACKAGE_24BITBUS_FRONT:
+ fmt |= CR_BWS_24;
+ dma |= VDMD_FRONT;
+ dev_dbg(dev, "24bit bus / package in front\n");
+ break;
+ case PACKAGE_16BITBUS_STREAM:
+ fmt |= CR_BWS_16;
+ dma |= VDMD_STREAM;
+ dev_dbg(dev, "16bit bus / stream mode\n");
+ break;
+ case PACKAGE_24BITBUS_BACK:
+ default:
+ fmt |= CR_BWS_24;
+ dma |= VDMD_BACK;
+ dev_dbg(dev, "24bit bus / package in back\n");
+ break;
+ }
+
+ if (is_play)
+ fsi_reg_write(fsi, OUT_DMAC, dma);
+ else
+ fsi_reg_write(fsi, IN_DMAC, dma);
+ }
+
+ if (is_play)
+ fsi_reg_write(fsi, DO_FMT, fmt);
+ else
+ fsi_reg_write(fsi, DI_FMT, fmt);
+}
+
+/*
* irq function
*/
@@ -629,11 +705,6 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
struct fsi_master *master = fsi_get_master(fsi);
u32 mask, val;
- if (master->core->ver < 2) {
- pr_err("fsi: register access err (%s)\n", __func__);
- return;
- }
-
mask = BP | SE;
val = enable ? mask : 0;
@@ -648,9 +719,7 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
long rate, int enable)
{
- struct fsi_master *master = fsi_get_master(fsi);
set_rate_func set_rate = fsi_get_info_set_rate(fsi);
- int fsi_ver = master->core->ver;
int ret;
if (!set_rate)
@@ -682,10 +751,7 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
data |= (0x3 << 12);
break;
case SH_FSI_ACKMD_32:
- if (fsi_ver < 2)
- dev_err(dev, "unsupported ACKMD\n");
- else
- data |= (0x4 << 12);
+ data |= (0x4 << 12);
break;
}
@@ -708,10 +774,7 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
data |= (0x4 << 8);
break;
case SH_FSI_BPFMD_16:
- if (fsi_ver < 2)
- dev_err(dev, "unsupported ACKMD\n");
- else
- data |= (0x7 << 8);
+ data |= (0x7 << 8);
break;
}
@@ -728,11 +791,26 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
*/
static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
{
- u16 *buf = (u16 *)_buf;
+ u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
int i;
- for (i = 0; i < samples; i++)
- fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
+ if (enable_stream) {
+ /*
+ * stream mode
+ * see
+ * fsi_pio_push_init()
+ */
+ u32 *buf = (u32 *)_buf;
+
+ for (i = 0; i < samples / 2; i++)
+ fsi_reg_write(fsi, DODT, buf[i]);
+ } else {
+ /* normal mode */
+ u16 *buf = (u16 *)_buf;
+
+ for (i = 0; i < samples; i++)
+ fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
+ }
}
static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples)
@@ -872,12 +950,44 @@ static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
}
+static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
+
+ /*
+ * we can use 16bit stream mode
+ * when "playback" and "16bit data"
+ * and platform allows "stream mode"
+ * see
+ * fsi_pio_push16()
+ */
+ if (enable_stream)
+ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
+ BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
+ else
+ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
+ BUSOP_SET(16, PACKAGE_24BITBUS_BACK);
+ return 0;
+}
+
+static int fsi_pio_pop_init(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ /*
+ * always 24bit bus, package back when "capture"
+ */
+ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
+ BUSOP_SET(16, PACKAGE_24BITBUS_BACK);
+ return 0;
+}
+
static struct fsi_stream_handler fsi_pio_push_handler = {
+ .init = fsi_pio_push_init,
.transfer = fsi_pio_push,
.start_stop = fsi_pio_start_stop,
};
static struct fsi_stream_handler fsi_pio_pop_handler = {
+ .init = fsi_pio_pop_init,
.transfer = fsi_pio_pop,
.start_stop = fsi_pio_start_stop,
};
@@ -919,6 +1029,13 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ /*
+ * 24bit data : 24bit bus / package in back
+ * 16bit data : 16bit bus / stream mode
+ */
+ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
+ BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
+
io->dma = dma_map_single(dai->dev, runtime->dma_area,
snd_pcm_lib_buffer_bytes(io->substream), dir);
return 0;
@@ -1055,25 +1172,9 @@ static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
int start)
{
- u32 bws;
- u32 dma;
+ u32 enable = start ? DMA_ON : 0;
- switch (io->sample_width * start) {
- case 2:
- bws = CR_BWS_16;
- dma = VDMD_STREAM | DMA_ON;
- break;
- case 4:
- bws = CR_BWS_24;
- dma = VDMD_BACK | DMA_ON;
- break;
- default:
- bws = 0;
- dma = 0;
- }
-
- fsi_reg_mask_set(fsi, DO_FMT, CR_BWS_MASK, bws);
- fsi_reg_write(fsi, OUT_DMAC, dma);
+ fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable);
}
static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
@@ -1176,8 +1277,6 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
struct fsi_stream *io,
struct device *dev)
{
- struct fsi_master *master = fsi_get_master(fsi);
- int fsi_ver = master->core->ver;
u32 flags = fsi_get_info_flags(fsi);
u32 data = 0;
@@ -1200,10 +1299,6 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
fsi_reg_write(fsi, CKG2, data);
- /* set format */
- fsi_reg_write(fsi, DO_FMT, fsi->do_fmt);
- fsi_reg_write(fsi, DI_FMT, fsi->di_fmt);
-
/* spdif ? */
if (fsi_is_spdif(fsi)) {
fsi_spdif_clk_ctrl(fsi, 1);
@@ -1211,15 +1306,18 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
}
/*
- * FIXME
- *
- * FSI driver assumed that data package is in-back.
- * FSI2 chip can select it.
+ * get bus settings
*/
- if (fsi_ver >= 2) {
- fsi_reg_write(fsi, OUT_DMAC, (1 << 4));
- fsi_reg_write(fsi, IN_DMAC, (1 << 4));
+ data = 0;
+ switch (io->sample_width) {
+ case 2:
+ data = BUSOP_GET(16, io->bus_option);
+ break;
+ case 4:
+ data = BUSOP_GET(24, io->bus_option);
+ break;
}
+ fsi_format_bus_setup(fsi, io, data, dev);
/* irq clear */
fsi_irq_disable(fsi, io);
@@ -1243,7 +1341,9 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- return fsi_hw_startup(fsi, fsi_stream_get(fsi, substream), dai->dev);
+ fsi->rate = 0;
+
+ return 0;
}
static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
@@ -1251,7 +1351,6 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- fsi_hw_shutdown(fsi, dai->dev);
fsi->rate = 0;
}
@@ -1265,11 +1364,13 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
fsi_stream_init(fsi, io, substream);
+ fsi_hw_startup(fsi, io, dai->dev);
ret = fsi_stream_transfer(io);
if (0 == ret)
fsi_stream_start(fsi, io);
break;
case SNDRV_PCM_TRIGGER_STOP:
+ fsi_hw_shutdown(fsi, dai->dev);
fsi_stream_stop(fsi, io);
fsi_stream_quit(fsi, io);
break;
@@ -1280,42 +1381,33 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt)
{
- u32 data = 0;
-
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
- data = CR_I2S;
+ fsi->fmt = CR_I2S;
fsi->chan_num = 2;
break;
case SND_SOC_DAIFMT_LEFT_J:
- data = CR_PCM;
+ fsi->fmt = CR_PCM;
fsi->chan_num = 2;
break;
default:
return -EINVAL;
}
- fsi->do_fmt = data;
- fsi->di_fmt = data;
-
return 0;
}
static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
{
struct fsi_master *master = fsi_get_master(fsi);
- u32 data = 0;
- if (master->core->ver < 2)
+ if (fsi_version(master) < 2)
return -EINVAL;
- data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
+ fsi->fmt = CR_DTMD_SPDIF_PCM | CR_PCM;
fsi->chan_num = 2;
fsi->spdif = 1;
- fsi->do_fmt = data;
- fsi->di_fmt = data;
-
return 0;
}
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index c88d9741b9e7..b37ee8077ed1 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -39,6 +39,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/soc-dpcm.h>
#include <sound/initval.h>
#define CREATE_TRACE_POINTS
@@ -54,7 +55,6 @@ EXPORT_SYMBOL_GPL(snd_soc_debugfs_root);
#endif
static DEFINE_MUTEX(client_mutex);
-static LIST_HEAD(card_list);
static LIST_HEAD(dai_list);
static LIST_HEAD(platform_list);
static LIST_HEAD(codec_list);
@@ -465,6 +465,35 @@ static inline void soc_cleanup_card_debugfs(struct snd_soc_card *card)
}
#endif
+struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
+ const char *dai_link, int stream)
+{
+ int i;
+
+ for (i = 0; i < card->num_links; i++) {
+ if (card->rtd[i].dai_link->no_pcm &&
+ !strcmp(card->rtd[i].dai_link->name, dai_link))
+ return card->rtd[i].pcm->streams[stream].substream;
+ }
+ dev_dbg(card->dev, "failed to find dai link %s\n", dai_link);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_dai_substream);
+
+struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
+ const char *dai_link)
+{
+ int i;
+
+ for (i = 0; i < card->num_links; i++) {
+ if (!strcmp(card->rtd[i].dai_link->name, dai_link))
+ return &card->rtd[i];
+ }
+ dev_dbg(card->dev, "failed to find rtd %s\n", dai_link);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime);
+
#ifdef CONFIG_SND_SOC_AC97_BUS
/* unregister ac97 codec */
static int soc_ac97_dev_unregister(struct snd_soc_codec *codec)
@@ -567,19 +596,16 @@ int snd_soc_suspend(struct device *dev)
}
for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
if (card->rtd[i].dai_link->ignore_suspend)
continue;
snd_soc_dapm_stream_event(&card->rtd[i],
SNDRV_PCM_STREAM_PLAYBACK,
- codec_dai,
SND_SOC_DAPM_STREAM_SUSPEND);
snd_soc_dapm_stream_event(&card->rtd[i],
SNDRV_PCM_STREAM_CAPTURE,
- codec_dai,
SND_SOC_DAPM_STREAM_SUSPEND);
}
@@ -683,17 +709,16 @@ static void soc_resume_deferred(struct work_struct *work)
}
for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
if (card->rtd[i].dai_link->ignore_suspend)
continue;
snd_soc_dapm_stream_event(&card->rtd[i],
- SNDRV_PCM_STREAM_PLAYBACK, codec_dai,
+ SNDRV_PCM_STREAM_PLAYBACK,
SND_SOC_DAPM_STREAM_RESUME);
snd_soc_dapm_stream_event(&card->rtd[i],
- SNDRV_PCM_STREAM_CAPTURE, codec_dai,
+ SNDRV_PCM_STREAM_CAPTURE,
SND_SOC_DAPM_STREAM_RESUME);
}
@@ -783,15 +808,9 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
struct snd_soc_dai *codec_dai, *cpu_dai;
const char *platform_name;
- if (rtd->complete)
- return 1;
dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num);
- /* do we already have the CPU DAI for this link ? */
- if (rtd->cpu_dai) {
- goto find_codec;
- }
- /* no, then find CPU DAI from registered DAIs*/
+ /* Find CPU DAI from registered DAIs*/
list_for_each_entry(cpu_dai, &dai_list, list) {
if (dai_link->cpu_dai_of_node) {
if (cpu_dai->dev->of_node != dai_link->cpu_dai_of_node)
@@ -802,18 +821,15 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
}
rtd->cpu_dai = cpu_dai;
- goto find_codec;
}
- dev_dbg(card->dev, "CPU DAI %s not registered\n",
- dai_link->cpu_dai_name);
-find_codec:
- /* do we already have the CODEC for this link ? */
- if (rtd->codec) {
- goto find_platform;
+ if (!rtd->cpu_dai) {
+ dev_dbg(card->dev, "CPU DAI %s not registered\n",
+ dai_link->cpu_dai_name);
+ return -EPROBE_DEFER;
}
- /* no, then find CODEC from registered CODECs*/
+ /* Find CODEC from registered CODECs */
list_for_each_entry(codec, &codec_list, list) {
if (dai_link->codec_of_node) {
if (codec->dev->of_node != dai_link->codec_of_node)
@@ -835,28 +851,28 @@ find_codec:
dai_link->codec_dai_name)) {
rtd->codec_dai = codec_dai;
- goto find_platform;
}
}
- dev_dbg(card->dev, "CODEC DAI %s not registered\n",
- dai_link->codec_dai_name);
- goto find_platform;
+ if (!rtd->codec_dai) {
+ dev_dbg(card->dev, "CODEC DAI %s not registered\n",
+ dai_link->codec_dai_name);
+ return -EPROBE_DEFER;
+ }
}
- dev_dbg(card->dev, "CODEC %s not registered\n",
- dai_link->codec_name);
-find_platform:
- /* do we need a platform? */
- if (rtd->platform)
- goto out;
+ if (!rtd->codec) {
+ dev_dbg(card->dev, "CODEC %s not registered\n",
+ dai_link->codec_name);
+ return -EPROBE_DEFER;
+ }
/* if there's no platform we match on the empty platform */
platform_name = dai_link->platform_name;
if (!platform_name && !dai_link->platform_of_node)
platform_name = "snd-soc-dummy";
- /* no, then find one from the set of registered platforms */
+ /* find one from the set of registered platforms */
list_for_each_entry(platform, &platform_list, list) {
if (dai_link->platform_of_node) {
if (platform->dev->of_node !=
@@ -868,20 +884,16 @@ find_platform:
}
rtd->platform = platform;
- goto out;
}
-
- dev_dbg(card->dev, "platform %s not registered\n",
+ if (!rtd->platform) {
+ dev_dbg(card->dev, "platform %s not registered\n",
dai_link->platform_name);
- return 0;
-
-out:
- /* mark rtd as complete if we found all 4 of our client devices */
- if (rtd->codec && rtd->codec_dai && rtd->platform && rtd->cpu_dai) {
- rtd->complete = 1;
- card->num_rtd++;
+ return -EPROBE_DEFER;
}
- return 1;
+
+ card->num_rtd++;
+
+ return 0;
}
static void soc_remove_codec(struct snd_soc_codec *codec)
@@ -1068,6 +1080,7 @@ static int soc_probe_platform(struct snd_soc_card *card,
{
int ret = 0;
const struct snd_soc_platform_driver *driver = platform->driver;
+ struct snd_soc_dai *dai;
platform->card = card;
platform->dapm.card = card;
@@ -1081,6 +1094,14 @@ static int soc_probe_platform(struct snd_soc_card *card,
snd_soc_dapm_new_controls(&platform->dapm,
driver->dapm_widgets, driver->num_dapm_widgets);
+ /* Create DAPM widgets for each DAI stream */
+ list_for_each_entry(dai, &dai_list, list) {
+ if (dai->dev != platform->dev)
+ continue;
+
+ snd_soc_dapm_new_dai_widgets(&platform->dapm, dai);
+ }
+
platform->dapm.idle_bias_off = 1;
if (driver->probe) {
@@ -1170,6 +1191,10 @@ static int soc_post_component_init(struct snd_soc_card *card,
rtd->dev->init_name = name;
dev_set_drvdata(rtd->dev, rtd);
mutex_init(&rtd->pcm_mutex);
+ INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients);
+ INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients);
+ INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients);
+ INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients);
ret = device_add(rtd->dev);
if (ret < 0) {
dev_err(card->dev,
@@ -1191,6 +1216,17 @@ static int soc_post_component_init(struct snd_soc_card *card,
dev_err(codec->dev,
"asoc: failed to add codec sysfs files: %d\n", ret);
+#ifdef CONFIG_DEBUG_FS
+ /* add DPCM sysfs entries */
+ if (!dailess && !dai_link->dynamic)
+ goto out;
+
+ ret = soc_dpcm_debugfs_add(rtd);
+ if (ret < 0)
+ dev_err(rtd->dev, "asoc: failed to add dpcm sysfs entries: %d\n", ret);
+
+out:
+#endif
return 0;
}
@@ -1200,14 +1236,15 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_platform *platform = rtd->platform;
- struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dapm_widget *play_w, *capture_w;
int ret;
dev_dbg(card->dev, "probe %s dai link %d late %d\n",
card->name, num, order);
/* config components */
- codec_dai->codec = codec;
cpu_dai->platform = platform;
codec_dai->card = card;
cpu_dai->card = card;
@@ -1218,9 +1255,12 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
/* probe the cpu_dai */
if (!cpu_dai->probed &&
cpu_dai->driver->probe_order == order) {
+ cpu_dai->dapm.card = card;
if (!try_module_get(cpu_dai->dev->driver->owner))
return -ENODEV;
+ snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai);
+
if (cpu_dai->driver->probe) {
ret = cpu_dai->driver->probe(cpu_dai);
if (ret < 0) {
@@ -1279,12 +1319,39 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
if (ret < 0)
pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret);
- /* create the pcm */
- ret = soc_new_pcm(rtd, num);
- if (ret < 0) {
- pr_err("asoc: can't create pcm %s :%d\n",
- dai_link->stream_name, ret);
- return ret;
+ if (!dai_link->params) {
+ /* create the pcm */
+ ret = soc_new_pcm(rtd, num);
+ if (ret < 0) {
+ pr_err("asoc: can't create pcm %s :%d\n",
+ dai_link->stream_name, ret);
+ return ret;
+ }
+ } else {
+ /* link the DAI widgets */
+ play_w = codec_dai->playback_widget;
+ capture_w = cpu_dai->capture_widget;
+ if (play_w && capture_w) {
+ ret = snd_soc_dapm_new_pcm(card, dai_link->params,
+ capture_w, play_w);
+ if (ret != 0) {
+ dev_err(card->dev, "Can't link %s to %s: %d\n",
+ play_w->name, capture_w->name, ret);
+ return ret;
+ }
+ }
+
+ play_w = cpu_dai->playback_widget;
+ capture_w = codec_dai->capture_widget;
+ if (play_w && capture_w) {
+ ret = snd_soc_dapm_new_pcm(card, dai_link->params,
+ capture_w, play_w);
+ if (ret != 0) {
+ dev_err(card->dev, "Can't link %s to %s: %d\n",
+ play_w->name, capture_w->name, ret);
+ return ret;
+ }
+ }
}
/* add platform data for AC97 devices */
@@ -1334,6 +1401,20 @@ static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec)
}
#endif
+static int soc_check_aux_dev(struct snd_soc_card *card, int num)
+{
+ struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
+ struct snd_soc_codec *codec;
+
+ /* find CODEC from registered CODECs*/
+ list_for_each_entry(codec, &codec_list, list) {
+ if (!strcmp(codec->name, aux_dev->codec_name))
+ return 0;
+ }
+
+ return -EPROBE_DEFER;
+}
+
static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
{
struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
@@ -1354,7 +1435,7 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
}
/* codec not found */
dev_err(card->dev, "asoc: codec %s not found", aux_dev->codec_name);
- goto out;
+ return -EPROBE_DEFER;
found:
ret = soc_probe_codec(card, codec);
@@ -1404,29 +1485,28 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
return 0;
}
-static void snd_soc_instantiate_card(struct snd_soc_card *card)
+static int snd_soc_instantiate_card(struct snd_soc_card *card)
{
struct snd_soc_codec *codec;
struct snd_soc_codec_conf *codec_conf;
enum snd_soc_compress_type compress_type;
struct snd_soc_dai_link *dai_link;
- int ret, i, order;
+ int ret, i, order, dai_fmt;
- mutex_lock(&card->mutex);
-
- if (card->instantiated) {
- mutex_unlock(&card->mutex);
- return;
- }
+ mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT);
/* bind DAIs */
- for (i = 0; i < card->num_links; i++)
- soc_bind_dai_link(card, i);
+ for (i = 0; i < card->num_links; i++) {
+ ret = soc_bind_dai_link(card, i);
+ if (ret != 0)
+ goto base_error;
+ }
- /* bind completed ? */
- if (card->num_rtd != card->num_links) {
- mutex_unlock(&card->mutex);
- return;
+ /* check aux_devs too */
+ for (i = 0; i < card->num_aux_devs; i++) {
+ ret = soc_check_aux_dev(card, i);
+ if (ret != 0)
+ goto base_error;
}
/* initialize the register cache for each available codec */
@@ -1446,10 +1526,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
}
}
ret = snd_soc_init_codec_cache(codec, compress_type);
- if (ret < 0) {
- mutex_unlock(&card->mutex);
- return;
- }
+ if (ret < 0)
+ goto base_error;
}
/* card bind complete so register a sound card */
@@ -1458,8 +1536,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
if (ret < 0) {
pr_err("asoc: can't create sound card for card %s: %d\n",
card->name, ret);
- mutex_unlock(&card->mutex);
- return;
+ goto base_error;
}
card->snd_card->dev = card->dev;
@@ -1523,17 +1600,47 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
for (i = 0; i < card->num_links; i++) {
dai_link = &card->dai_link[i];
+ dai_fmt = dai_link->dai_fmt;
- if (dai_link->dai_fmt) {
+ if (dai_fmt) {
ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai,
- dai_link->dai_fmt);
+ dai_fmt);
if (ret != 0 && ret != -ENOTSUPP)
dev_warn(card->rtd[i].codec_dai->dev,
"Failed to set DAI format: %d\n",
ret);
+ }
+ /* If this is a regular CPU link there will be a platform */
+ if (dai_fmt &&
+ (dai_link->platform_name || dai_link->platform_of_node)) {
ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
- dai_link->dai_fmt);
+ dai_fmt);
+ if (ret != 0 && ret != -ENOTSUPP)
+ dev_warn(card->rtd[i].cpu_dai->dev,
+ "Failed to set DAI format: %d\n",
+ ret);
+ } else if (dai_fmt) {
+ /* Flip the polarity for the "CPU" end */
+ dai_fmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
+ switch (dai_link->dai_fmt &
+ SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ dai_fmt |= SND_SOC_DAIFMT_CBS_CFM;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFM:
+ dai_fmt |= SND_SOC_DAIFMT_CBM_CFS;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
+ break;
+ }
+
+ ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
+ dai_fmt);
if (ret != 0 && ret != -ENOTSUPP)
dev_warn(card->rtd[i].cpu_dai->dev,
"Failed to set DAI format: %d\n",
@@ -1599,7 +1706,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
card->instantiated = 1;
snd_soc_dapm_sync(&card->dapm);
mutex_unlock(&card->mutex);
- return;
+
+ return 0;
probe_aux_dev_err:
for (i = 0; i < card->num_aux_devs; i++)
@@ -1614,18 +1722,10 @@ card_probe_error:
snd_card_free(card->snd_card);
+base_error:
mutex_unlock(&card->mutex);
-}
-/*
- * Attempt to initialise any uninitialised cards. Must be called with
- * client_mutex.
- */
-static void snd_soc_instantiate_cards(void)
-{
- struct snd_soc_card *card;
- list_for_each_entry(card, &card_list, list)
- snd_soc_instantiate_card(card);
+ return ret;
}
/* probes a new socdev */
@@ -2527,6 +2627,87 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
/**
+ * snd_soc_get_volsw_sx - single mixer get callback
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * Callback to get the value of a single mixer control, or a double mixer
+ * control that spans 2 registers.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ unsigned int shift = mc->shift;
+ unsigned int rshift = mc->rshift;
+ int max = mc->max;
+ int min = mc->min;
+ int mask = (1 << (fls(min + max) - 1)) - 1;
+
+ ucontrol->value.integer.value[0] =
+ ((snd_soc_read(codec, reg) >> shift) - min) & mask;
+
+ if (snd_soc_volsw_is_stereo(mc))
+ ucontrol->value.integer.value[1] =
+ ((snd_soc_read(codec, reg2) >> rshift) - min) & mask;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx);
+
+/**
+ * snd_soc_put_volsw_sx - double mixer set callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to set the value of a double mixer control that spans 2 registers.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ unsigned int shift = mc->shift;
+ unsigned int rshift = mc->rshift;
+ int max = mc->max;
+ int min = mc->min;
+ int mask = (1 << (fls(min + max) - 1)) - 1;
+ int err = 0;
+ unsigned short val, val_mask, val2 = 0;
+
+ val_mask = mask << shift;
+ val = (ucontrol->value.integer.value[0] + min) & mask;
+ val = val << shift;
+
+ if (snd_soc_update_bits_locked(codec, reg, val_mask, val))
+ return err;
+
+ if (snd_soc_volsw_is_stereo(mc)) {
+ val_mask = mask << rshift;
+ val2 = (ucontrol->value.integer.value[1] + min) & mask;
+ val2 = val2 << rshift;
+
+ if (snd_soc_update_bits_locked(codec, reg2, val_mask, val2))
+ return err;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx);
+
+/**
* snd_soc_info_volsw_s8 - signed mixer info callback
* @kcontrol: mixer control
* @uinfo: control element information
@@ -2647,99 +2828,6 @@ int snd_soc_limit_volume(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL_GPL(snd_soc_limit_volume);
-/**
- * snd_soc_info_volsw_2r_sx - double with tlv and variable data size
- * mixer info callback
- * @kcontrol: mixer control
- * @uinfo: control element information
- *
- * Returns 0 for success.
- */
-int snd_soc_info_volsw_2r_sx(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- int max = mc->max;
- int min = mc->min;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = max-min;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r_sx);
-
-/**
- * snd_soc_get_volsw_2r_sx - double with tlv and variable data size
- * mixer get callback
- * @kcontrol: mixer control
- * @uinfo: control element information
- *
- * Returns 0 for success.
- */
-int snd_soc_get_volsw_2r_sx(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned int mask = (1<<mc->shift)-1;
- int min = mc->min;
- int val = snd_soc_read(codec, mc->reg) & mask;
- int valr = snd_soc_read(codec, mc->rreg) & mask;
-
- ucontrol->value.integer.value[0] = ((val & 0xff)-min) & mask;
- ucontrol->value.integer.value[1] = ((valr & 0xff)-min) & mask;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r_sx);
-
-/**
- * snd_soc_put_volsw_2r_sx - double with tlv and variable data size
- * mixer put callback
- * @kcontrol: mixer control
- * @uinfo: control element information
- *
- * Returns 0 for success.
- */
-int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned int mask = (1<<mc->shift)-1;
- int min = mc->min;
- int ret;
- unsigned int val, valr, oval, ovalr;
-
- val = ((ucontrol->value.integer.value[0]+min) & 0xff);
- val &= mask;
- valr = ((ucontrol->value.integer.value[1]+min) & 0xff);
- valr &= mask;
-
- oval = snd_soc_read(codec, mc->reg) & mask;
- ovalr = snd_soc_read(codec, mc->rreg) & mask;
-
- ret = 0;
- if (oval != val) {
- ret = snd_soc_write(codec, mc->reg, val);
- if (ret < 0)
- return ret;
- }
- if (ovalr != valr) {
- ret = snd_soc_write(codec, mc->rreg, valr);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx);
-
int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
@@ -2850,6 +2938,186 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
EXPORT_SYMBOL_GPL(snd_soc_bytes_put);
/**
+ * snd_soc_info_xr_sx - signed multi register info callback
+ * @kcontrol: mreg control
+ * @uinfo: control element information
+ *
+ * Callback to provide information of a control that can
+ * span multiple codec registers which together
+ * forms a single signed value in a MSB/LSB manner.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct soc_mreg_control *mc =
+ (struct soc_mreg_control *)kcontrol->private_value;
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = mc->min;
+ uinfo->value.integer.max = mc->max;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx);
+
+/**
+ * snd_soc_get_xr_sx - signed multi register get callback
+ * @kcontrol: mreg control
+ * @ucontrol: control element information
+ *
+ * Callback to get the value of a control that can span
+ * multiple codec registers which together forms a single
+ * signed value in a MSB/LSB manner. The control supports
+ * specifying total no of bits used to allow for bitfields
+ * across the multiple codec registers.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mreg_control *mc =
+ (struct soc_mreg_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int regbase = mc->regbase;
+ unsigned int regcount = mc->regcount;
+ unsigned int regwshift = codec->driver->reg_word_size * BITS_PER_BYTE;
+ unsigned int regwmask = (1<<regwshift)-1;
+ unsigned int invert = mc->invert;
+ unsigned long mask = (1UL<<mc->nbits)-1;
+ long min = mc->min;
+ long max = mc->max;
+ long val = 0;
+ unsigned long regval;
+ unsigned int i;
+
+ for (i = 0; i < regcount; i++) {
+ regval = snd_soc_read(codec, regbase+i) & regwmask;
+ val |= regval << (regwshift*(regcount-i-1));
+ }
+ val &= mask;
+ if (min < 0 && val > max)
+ val |= ~mask;
+ if (invert)
+ val = max - val;
+ ucontrol->value.integer.value[0] = val;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx);
+
+/**
+ * snd_soc_put_xr_sx - signed multi register get callback
+ * @kcontrol: mreg control
+ * @ucontrol: control element information
+ *
+ * Callback to set the value of a control that can span
+ * multiple codec registers which together forms a single
+ * signed value in a MSB/LSB manner. The control supports
+ * specifying total no of bits used to allow for bitfields
+ * across the multiple codec registers.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mreg_control *mc =
+ (struct soc_mreg_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int regbase = mc->regbase;
+ unsigned int regcount = mc->regcount;
+ unsigned int regwshift = codec->driver->reg_word_size * BITS_PER_BYTE;
+ unsigned int regwmask = (1<<regwshift)-1;
+ unsigned int invert = mc->invert;
+ unsigned long mask = (1UL<<mc->nbits)-1;
+ long max = mc->max;
+ long val = ucontrol->value.integer.value[0];
+ unsigned int i, regval, regmask;
+ int err;
+
+ if (invert)
+ val = max - val;
+ val &= mask;
+ for (i = 0; i < regcount; i++) {
+ regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
+ regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
+ err = snd_soc_update_bits_locked(codec, regbase+i,
+ regmask, regval);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx);
+
+/**
+ * snd_soc_get_strobe - strobe get callback
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * Callback get the value of a strobe mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_get_strobe(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int shift = mc->shift;
+ unsigned int mask = 1 << shift;
+ unsigned int invert = mc->invert != 0;
+ unsigned int val = snd_soc_read(codec, reg) & mask;
+
+ if (shift != 0 && val != 0)
+ val = val >> shift;
+ ucontrol->value.enumerated.item[0] = val ^ invert;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_strobe);
+
+/**
+ * snd_soc_put_strobe - strobe put callback
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * Callback strobe a register bit to high then low (or the inverse)
+ * in one pass of a single mixer enum control.
+ *
+ * Returns 1 for success.
+ */
+int snd_soc_put_strobe(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int shift = mc->shift;
+ unsigned int mask = 1 << shift;
+ unsigned int invert = mc->invert != 0;
+ unsigned int strobe = ucontrol->value.enumerated.item[0] != 0;
+ unsigned int val1 = (strobe ^ invert) ? mask : 0;
+ unsigned int val2 = (strobe ^ invert) ? 0 : mask;
+ int err;
+
+ err = snd_soc_update_bits_locked(codec, reg, mask, val1);
+ if (err < 0)
+ return err;
+
+ err = snd_soc_update_bits_locked(codec, reg, mask, val2);
+ return err;
+}
+EXPORT_SYMBOL_GPL(snd_soc_put_strobe);
+
+/**
* snd_soc_dai_set_sysclk - configure DAI system or master clock.
* @dai: DAI
* @clk_id: DAI specific clock ID
@@ -3048,7 +3316,7 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
if (dai->driver && dai->driver->ops->digital_mute)
return dai->driver->ops->digital_mute(dai, mute);
else
- return -EINVAL;
+ return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
@@ -3060,7 +3328,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
*/
int snd_soc_register_card(struct snd_soc_card *card)
{
- int i;
+ int i, ret;
if (!card->name || !card->dev)
return -EINVAL;
@@ -3123,15 +3391,13 @@ int snd_soc_register_card(struct snd_soc_card *card)
INIT_LIST_HEAD(&card->dapm_dirty);
card->instantiated = 0;
mutex_init(&card->mutex);
+ mutex_init(&card->dapm_mutex);
- mutex_lock(&client_mutex);
- list_add(&card->list, &card_list);
- snd_soc_instantiate_cards();
- mutex_unlock(&client_mutex);
-
- dev_dbg(card->dev, "Registered card '%s'\n", card->name);
+ ret = snd_soc_instantiate_card(card);
+ if (ret != 0)
+ soc_cleanup_card_debugfs(card);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_register_card);
@@ -3145,9 +3411,6 @@ int snd_soc_unregister_card(struct snd_soc_card *card)
{
if (card->instantiated)
soc_cleanup_card_resources(card);
- mutex_lock(&client_mutex);
- list_del(&card->list);
- mutex_unlock(&client_mutex);
dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);
return 0;
@@ -3221,6 +3484,7 @@ static inline char *fmt_multiple_name(struct device *dev,
int snd_soc_register_dai(struct device *dev,
struct snd_soc_dai_driver *dai_drv)
{
+ struct snd_soc_codec *codec;
struct snd_soc_dai *dai;
dev_dbg(dev, "dai register %s\n", dev_name(dev));
@@ -3238,12 +3502,23 @@ int snd_soc_register_dai(struct device *dev,
dai->dev = dev;
dai->driver = dai_drv;
+ dai->dapm.dev = dev;
if (!dai->driver->ops)
dai->driver->ops = &null_dai_ops;
mutex_lock(&client_mutex);
+
+ list_for_each_entry(codec, &codec_list, list) {
+ if (codec->dev == dev) {
+ dev_dbg(dev, "Mapped DAI %s to CODEC %s\n",
+ dai->name, codec->name);
+ dai->codec = codec;
+ break;
+ }
+ }
+
list_add(&dai->list, &dai_list);
- snd_soc_instantiate_cards();
+
mutex_unlock(&client_mutex);
pr_debug("Registered DAI '%s'\n", dai->name);
@@ -3287,6 +3562,7 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
int snd_soc_register_dais(struct device *dev,
struct snd_soc_dai_driver *dai_drv, size_t count)
{
+ struct snd_soc_codec *codec;
struct snd_soc_dai *dai;
int i, ret = 0;
@@ -3314,19 +3590,28 @@ int snd_soc_register_dais(struct device *dev,
dai->id = dai->driver->id;
else
dai->id = i;
+ dai->dapm.dev = dev;
if (!dai->driver->ops)
dai->driver->ops = &null_dai_ops;
mutex_lock(&client_mutex);
+
+ list_for_each_entry(codec, &codec_list, list) {
+ if (codec->dev == dev) {
+ dev_dbg(dev, "Mapped DAI %s to CODEC %s\n",
+ dai->name, codec->name);
+ dai->codec = codec;
+ break;
+ }
+ }
+
list_add(&dai->list, &dai_list);
+
mutex_unlock(&client_mutex);
pr_debug("Registered DAI '%s'\n", dai->name);
}
- mutex_lock(&client_mutex);
- snd_soc_instantiate_cards();
- mutex_unlock(&client_mutex);
return 0;
err:
@@ -3384,7 +3669,6 @@ int snd_soc_register_platform(struct device *dev,
mutex_lock(&client_mutex);
list_add(&platform->list, &platform_list);
- snd_soc_instantiate_cards();
mutex_unlock(&client_mutex);
pr_debug("Registered platform '%s'\n", platform->name);
@@ -3534,18 +3818,18 @@ int snd_soc_register_codec(struct device *dev,
fixup_codec_formats(&dai_drv[i].capture);
}
+ mutex_lock(&client_mutex);
+ list_add(&codec->list, &codec_list);
+ mutex_unlock(&client_mutex);
+
/* register any DAIs */
if (num_dai) {
ret = snd_soc_register_dais(dev, dai_drv, num_dai);
if (ret < 0)
- goto fail;
+ dev_err(codec->dev, "Failed to regster DAIs: %d\n",
+ ret);
}
- mutex_lock(&client_mutex);
- list_add(&codec->list, &codec_list);
- snd_soc_instantiate_cards();
- mutex_unlock(&client_mutex);
-
pr_debug("Registered codec '%s'\n", codec->name);
return 0;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 1bb6d4a63cd8..90ee77d2409d 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -52,6 +52,7 @@ static int dapm_up_seq[] = {
[snd_soc_dapm_supply] = 1,
[snd_soc_dapm_regulator_supply] = 1,
[snd_soc_dapm_micbias] = 2,
+ [snd_soc_dapm_dai_link] = 2,
[snd_soc_dapm_dai] = 3,
[snd_soc_dapm_aif_in] = 3,
[snd_soc_dapm_aif_out] = 3,
@@ -90,9 +91,10 @@ static int dapm_down_seq[] = {
[snd_soc_dapm_aif_in] = 10,
[snd_soc_dapm_aif_out] = 10,
[snd_soc_dapm_dai] = 10,
- [snd_soc_dapm_regulator_supply] = 11,
- [snd_soc_dapm_supply] = 11,
- [snd_soc_dapm_post] = 12,
+ [snd_soc_dapm_dai_link] = 11,
+ [snd_soc_dapm_regulator_supply] = 12,
+ [snd_soc_dapm_supply] = 12,
+ [snd_soc_dapm_post] = 13,
};
static void pop_wait(u32 pop_time)
@@ -208,7 +210,23 @@ static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
return -1;
}
-static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
+static inline void soc_widget_lock(struct snd_soc_dapm_widget *w)
+{
+ if (w->codec && !w->codec->using_regmap)
+ mutex_lock(&w->codec->mutex);
+ else if (w->platform)
+ mutex_lock(&w->platform->mutex);
+}
+
+static inline void soc_widget_unlock(struct snd_soc_dapm_widget *w)
+{
+ if (w->codec && !w->codec->using_regmap)
+ mutex_unlock(&w->codec->mutex);
+ else if (w->platform)
+ mutex_unlock(&w->platform->mutex);
+}
+
+static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
unsigned short reg, unsigned int mask, unsigned int value)
{
bool change;
@@ -221,18 +239,24 @@ static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
if (ret != 0)
return ret;
} else {
+ soc_widget_lock(w);
ret = soc_widget_read(w, reg);
- if (ret < 0)
+ if (ret < 0) {
+ soc_widget_unlock(w);
return ret;
+ }
old = ret;
new = (old & ~mask) | (value & mask);
change = old != new;
if (change) {
ret = soc_widget_write(w, reg, new);
- if (ret < 0)
+ if (ret < 0) {
+ soc_widget_unlock(w);
return ret;
+ }
}
+ soc_widget_unlock(w);
}
return change;
@@ -374,6 +398,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
case snd_soc_dapm_mic:
case snd_soc_dapm_spk:
case snd_soc_dapm_line:
+ case snd_soc_dapm_dai_link:
p->connect = 1;
break;
/* does affect routing - dynamically connected */
@@ -682,11 +707,51 @@ static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
}
}
+/* add widget to list if it's not already in the list */
+static int dapm_list_add_widget(struct snd_soc_dapm_widget_list **list,
+ struct snd_soc_dapm_widget *w)
+{
+ struct snd_soc_dapm_widget_list *wlist;
+ int wlistsize, wlistentries, i;
+
+ if (*list == NULL)
+ return -EINVAL;
+
+ wlist = *list;
+
+ /* is this widget already in the list */
+ for (i = 0; i < wlist->num_widgets; i++) {
+ if (wlist->widgets[i] == w)
+ return 0;
+ }
+
+ /* allocate some new space */
+ wlistentries = wlist->num_widgets + 1;
+ wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
+ wlistentries * sizeof(struct snd_soc_dapm_widget *);
+ *list = krealloc(wlist, wlistsize, GFP_KERNEL);
+ if (*list == NULL) {
+ dev_err(w->dapm->dev, "can't allocate widget list for %s\n",
+ w->name);
+ return -ENOMEM;
+ }
+ wlist = *list;
+
+ /* insert the widget */
+ dev_dbg(w->dapm->dev, "added %s in widget list pos %d\n",
+ w->name, wlist->num_widgets);
+
+ wlist->widgets[wlist->num_widgets] = w;
+ wlist->num_widgets++;
+ return 1;
+}
+
/*
* Recursively check for a completed path to an active or physically connected
* output widget. Returns number of complete paths.
*/
-static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
+static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
+ struct snd_soc_dapm_widget_list **list)
{
struct snd_soc_dapm_path *path;
int con = 0;
@@ -742,9 +807,23 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
if (path->walked)
continue;
+ trace_snd_soc_dapm_output_path(widget, path);
+
if (path->sink && path->connect) {
path->walked = 1;
- con += is_connected_output_ep(path->sink);
+
+ /* do we need to add this widget to the list ? */
+ if (list) {
+ int err;
+ err = dapm_list_add_widget(list, path->sink);
+ if (err < 0) {
+ dev_err(widget->dapm->dev, "could not add widget %s\n",
+ widget->name);
+ return con;
+ }
+ }
+
+ con += is_connected_output_ep(path->sink, list);
}
}
@@ -757,7 +836,8 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
* Recursively check for a completed path to an active or physically connected
* input widget. Returns number of complete paths.
*/
-static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
+static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
+ struct snd_soc_dapm_widget_list **list)
{
struct snd_soc_dapm_path *path;
int con = 0;
@@ -825,9 +905,23 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
if (path->walked)
continue;
+ trace_snd_soc_dapm_input_path(widget, path);
+
if (path->source && path->connect) {
path->walked = 1;
- con += is_connected_input_ep(path->source);
+
+ /* do we need to add this widget to the list ? */
+ if (list) {
+ int err;
+ err = dapm_list_add_widget(list, path->sink);
+ if (err < 0) {
+ dev_err(widget->dapm->dev, "could not add widget %s\n",
+ widget->name);
+ return con;
+ }
+ }
+
+ con += is_connected_input_ep(path->source, list);
}
}
@@ -836,6 +930,39 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
return con;
}
+/**
+ * snd_soc_dapm_get_connected_widgets - query audio path and it's widgets.
+ * @dai: the soc DAI.
+ * @stream: stream direction.
+ * @list: list of active widgets for this stream.
+ *
+ * Queries DAPM graph as to whether an valid audio stream path exists for
+ * the initial stream specified by name. This takes into account
+ * current mixer and mux kcontrol settings. Creates list of valid widgets.
+ *
+ * Returns the number of valid paths or negative error.
+ */
+int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
+ struct snd_soc_dapm_widget_list **list)
+{
+ struct snd_soc_card *card = dai->card;
+ int paths;
+
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+ dapm_reset(card);
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ paths = is_connected_output_ep(dai->playback_widget, list);
+ else
+ paths = is_connected_input_ep(dai->playback_widget, list);
+
+ trace_snd_soc_dapm_connected(paths, stream);
+ dapm_clear_walk(&card->dapm);
+ mutex_unlock(&card->dapm_mutex);
+
+ return paths;
+}
+
/*
* Handler for generic register modifier widget.
*/
@@ -849,7 +976,7 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
else
val = w->off_val;
- soc_widget_update_bits(w, -(w->reg + 1),
+ soc_widget_update_bits_locked(w, -(w->reg + 1),
w->mask << w->shift, val << w->shift);
return 0;
@@ -863,9 +990,9 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
if (SND_SOC_DAPM_EVENT_ON(event))
- return regulator_enable(w->priv);
+ return regulator_enable(w->regulator);
else
- return regulator_disable_deferred(w->priv, w->shift);
+ return regulator_disable_deferred(w->regulator, w->shift);
}
EXPORT_SYMBOL_GPL(dapm_regulator_event);
@@ -892,9 +1019,9 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
DAPM_UPDATE_STAT(w, power_checks);
- in = is_connected_input_ep(w);
+ in = is_connected_input_ep(w, NULL);
dapm_clear_walk(w->dapm);
- out = is_connected_output_ep(w);
+ out = is_connected_output_ep(w, NULL);
dapm_clear_walk(w->dapm);
return out != 0 && in != 0;
}
@@ -903,7 +1030,10 @@ static int dapm_dai_check_power(struct snd_soc_dapm_widget *w)
{
DAPM_UPDATE_STAT(w, power_checks);
- return w->active;
+ if (w->active)
+ return w->active;
+
+ return dapm_generic_check_power(w);
}
/* Check to see if an ADC has power */
@@ -914,7 +1044,7 @@ static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
DAPM_UPDATE_STAT(w, power_checks);
if (w->active) {
- in = is_connected_input_ep(w);
+ in = is_connected_input_ep(w, NULL);
dapm_clear_walk(w->dapm);
return in != 0;
} else {
@@ -930,7 +1060,7 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
DAPM_UPDATE_STAT(w, power_checks);
if (w->active) {
- out = is_connected_output_ep(w);
+ out = is_connected_output_ep(w, NULL);
dapm_clear_walk(w->dapm);
return out != 0;
} else {
@@ -1107,7 +1237,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
"pop test : Applying 0x%x/0x%x to %x in %dms\n",
value, mask, reg, card->pop_time);
pop_wait(card->pop_time);
- soc_widget_update_bits(w, reg, mask, value);
+ soc_widget_update_bits_locked(w, reg, mask, value);
}
list_for_each_entry(w, pending, power_list) {
@@ -1237,7 +1367,7 @@ static void dapm_widget_update(struct snd_soc_dapm_context *dapm)
w->name, ret);
}
- ret = snd_soc_update_bits(w->codec, update->reg, update->mask,
+ ret = soc_widget_update_bits_locked(w, update->reg, update->mask,
update->val);
if (ret < 0)
pr_err("%s DAPM update failed: %d\n", w->name, ret);
@@ -1421,12 +1551,10 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
trace_snd_soc_dapm_start(card);
list_for_each_entry(d, &card->dapm_list, list) {
- if (d->n_widgets || d->codec == NULL) {
- if (d->idle_bias_off)
- d->target_bias_level = SND_SOC_BIAS_OFF;
- else
- d->target_bias_level = SND_SOC_BIAS_STANDBY;
- }
+ if (d->idle_bias_off)
+ d->target_bias_level = SND_SOC_BIAS_OFF;
+ else
+ d->target_bias_level = SND_SOC_BIAS_STANDBY;
}
dapm_reset(card);
@@ -1471,32 +1599,6 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
}
- /* If there are no DAPM widgets then try to figure out power from the
- * event type.
- */
- if (!dapm->n_widgets) {
- switch (event) {
- case SND_SOC_DAPM_STREAM_START:
- case SND_SOC_DAPM_STREAM_RESUME:
- dapm->target_bias_level = SND_SOC_BIAS_ON;
- break;
- case SND_SOC_DAPM_STREAM_STOP:
- if (dapm->codec && dapm->codec->active)
- dapm->target_bias_level = SND_SOC_BIAS_ON;
- else
- dapm->target_bias_level = SND_SOC_BIAS_STANDBY;
- break;
- case SND_SOC_DAPM_STREAM_SUSPEND:
- dapm->target_bias_level = SND_SOC_BIAS_STANDBY;
- break;
- case SND_SOC_DAPM_STREAM_NOP:
- dapm->target_bias_level = dapm->bias_level;
- break;
- default:
- break;
- }
- }
-
/* Force all contexts in the card to the same bias state if
* they're not ground referenced.
*/
@@ -1560,9 +1662,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
if (!buf)
return -ENOMEM;
- in = is_connected_input_ep(w);
+ in = is_connected_input_ep(w, NULL);
dapm_clear_walk(w->dapm);
- out = is_connected_output_ep(w);
+ out = is_connected_output_ep(w, NULL);
dapm_clear_walk(w->dapm);
ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d",
@@ -1709,7 +1811,7 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
#endif
/* test and update the power status of a mux widget */
-int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
{
struct snd_soc_dapm_path *path;
@@ -1746,12 +1848,26 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
}
- return 0;
+ return found;
+}
+
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
+{
+ struct snd_soc_card *card = widget->dapm->card;
+ int ret;
+
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+ ret = soc_dapm_mux_update_power(widget, kcontrol, mux, e);
+ mutex_unlock(&card->dapm_mutex);
+ if (ret > 0)
+ soc_dpcm_runtime_update(widget);
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
/* test and update the power status of a mixer or switch widget */
-int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+static int soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
struct snd_kcontrol *kcontrol, int connect)
{
struct snd_soc_dapm_path *path;
@@ -1778,7 +1894,21 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
}
- return 0;
+ return found;
+}
+
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *kcontrol, int connect)
+{
+ struct snd_soc_card *card = widget->dapm->card;
+ int ret;
+
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+ ret = soc_dapm_mixer_update_power(widget, kcontrol, connect);
+ mutex_unlock(&card->dapm_mutex);
+ if (ret > 0)
+ soc_dpcm_runtime_update(widget);
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
@@ -1939,6 +2069,8 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
*/
int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
{
+ int ret;
+
/*
* Suppress early reports (eg, jacks syncing their state) to avoid
* silly DAPM runs during card startup.
@@ -1946,7 +2078,10 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
if (!dapm->card || !dapm->card->instantiated)
return 0;
- return dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+ ret = dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
+ mutex_unlock(&dapm->card->dapm_mutex);
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
@@ -2055,6 +2190,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
case snd_soc_dapm_aif_in:
case snd_soc_dapm_aif_out:
case snd_soc_dapm_dai:
+ case snd_soc_dapm_dai_link:
list_add(&path->list, &dapm->card->paths);
list_add(&path->list_sink, &wsink->sources);
list_add(&path->list_source, &wsource->sinks);
@@ -2110,19 +2246,21 @@ err:
int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num)
{
- int i, ret;
+ int i, ret = 0;
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
for (i = 0; i < num; i++) {
ret = snd_soc_dapm_add_route(dapm, route);
if (ret < 0) {
dev_err(dapm->dev, "Failed to add route %s->%s\n",
route->source, route->sink);
- return ret;
+ break;
}
route++;
}
+ mutex_unlock(&dapm->card->dapm_mutex);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
@@ -2193,12 +2331,14 @@ int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
int i, err;
int ret = 0;
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
for (i = 0; i < num; i++) {
err = snd_soc_dapm_weak_route(dapm, route);
if (err)
ret = err;
route++;
}
+ mutex_unlock(&dapm->card->dapm_mutex);
return ret;
}
@@ -2217,6 +2357,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
struct snd_soc_dapm_widget *w;
unsigned int val;
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
+
list_for_each_entry(w, &dapm->card->widgets, list)
{
if (w->new)
@@ -2226,8 +2368,10 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
w->kcontrols = kzalloc(w->num_kcontrols *
sizeof(struct snd_kcontrol *),
GFP_KERNEL);
- if (!w->kcontrols)
+ if (!w->kcontrols) {
+ mutex_unlock(&dapm->card->dapm_mutex);
return -ENOMEM;
+ }
}
switch(w->id) {
@@ -2267,6 +2411,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
}
dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
+ mutex_unlock(&dapm->card->dapm_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
@@ -2326,6 +2471,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
struct snd_soc_codec *codec = widget->codec;
+ struct snd_soc_card *card = codec->card;
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
@@ -2352,7 +2498,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
/* old connection must be powered down */
connect = invert ? 1 : 0;
- mutex_lock(&codec->mutex);
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
change = snd_soc_test_bits(widget->codec, reg, mask, val);
if (change) {
@@ -2368,13 +2514,13 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- snd_soc_dapm_mixer_update_power(widget, kcontrol, connect);
+ soc_dapm_mixer_update_power(widget, kcontrol, connect);
widget->dapm->update = NULL;
}
}
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->dapm_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
@@ -2423,6 +2569,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
struct snd_soc_codec *codec = widget->codec;
+ struct snd_soc_card *card = codec->card;
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int val, mux, change;
unsigned int mask, bitmask;
@@ -2443,7 +2590,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
mask |= (bitmask - 1) << e->shift_r;
}
- mutex_lock(&codec->mutex);
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
if (change) {
@@ -2459,13 +2606,13 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
+ soc_dapm_mux_update_power(widget, kcontrol, mux, e);
widget->dapm->update = NULL;
}
}
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->dapm_mutex);
return change;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
@@ -2502,6 +2649,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
struct snd_soc_codec *codec = widget->codec;
+ struct snd_soc_card *card = codec->card;
struct soc_enum *e =
(struct soc_enum *)kcontrol->private_value;
int change;
@@ -2511,7 +2659,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
if (ucontrol->value.enumerated.item[0] >= e->max)
return -EINVAL;
- mutex_lock(&codec->mutex);
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
change = widget->value != ucontrol->value.enumerated.item[0];
if (change) {
@@ -2520,11 +2668,11 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
widget->value = ucontrol->value.enumerated.item[0];
- snd_soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
+ soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
}
}
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->dapm_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
@@ -2589,6 +2737,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
struct snd_soc_codec *codec = widget->codec;
+ struct snd_soc_card *card = codec->card;
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int val, mux, change;
unsigned int mask;
@@ -2607,7 +2756,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
mask |= e->mask << e->shift_r;
}
- mutex_lock(&codec->mutex);
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
if (change) {
@@ -2623,13 +2772,13 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
+ soc_dapm_mux_update_power(widget, kcontrol, mux, e);
widget->dapm->update = NULL;
}
}
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->dapm_mutex);
return change;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
@@ -2666,12 +2815,12 @@ int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
const char *pin = (const char *)kcontrol->private_value;
- mutex_lock(&card->mutex);
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ucontrol->value.integer.value[0] =
snd_soc_dapm_get_pin_status(&card->dapm, pin);
- mutex_unlock(&card->mutex);
+ mutex_unlock(&card->dapm_mutex);
return 0;
}
@@ -2689,17 +2838,16 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
const char *pin = (const char *)kcontrol->private_value;
- mutex_lock(&card->mutex);
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
if (ucontrol->value.integer.value[0])
snd_soc_dapm_enable_pin(&card->dapm, pin);
else
snd_soc_dapm_disable_pin(&card->dapm, pin);
- snd_soc_dapm_sync(&card->dapm);
-
- mutex_unlock(&card->mutex);
+ mutex_unlock(&card->dapm_mutex);
+ snd_soc_dapm_sync(&card->dapm);
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
@@ -2717,9 +2865,9 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
switch (w->id) {
case snd_soc_dapm_regulator_supply:
- w->priv = devm_regulator_get(dapm->dev, w->name);
- if (IS_ERR(w->priv)) {
- ret = PTR_ERR(w->priv);
+ w->regulator = devm_regulator_get(dapm->dev, w->name);
+ if (IS_ERR(w->regulator)) {
+ ret = PTR_ERR(w->regulator);
dev_err(dapm->dev, "Failed to request %s: %d\n",
w->name, ret);
return NULL;
@@ -2771,6 +2919,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
case snd_soc_dapm_hp:
case snd_soc_dapm_mic:
case snd_soc_dapm_line:
+ case snd_soc_dapm_dai_link:
w->power_check = dapm_generic_check_power;
break;
case snd_soc_dapm_supply:
@@ -2816,21 +2965,177 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
{
struct snd_soc_dapm_widget *w;
int i;
+ int ret = 0;
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
for (i = 0; i < num; i++) {
w = snd_soc_dapm_new_control(dapm, widget);
if (!w) {
dev_err(dapm->dev,
"ASoC: Failed to create DAPM control %s\n",
widget->name);
- return -ENOMEM;
+ ret = -ENOMEM;
+ break;
}
widget++;
}
- return 0;
+ mutex_unlock(&dapm->card->dapm_mutex);
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
+static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_dapm_path *source_p, *sink_p;
+ struct snd_soc_dai *source, *sink;
+ const struct snd_soc_pcm_stream *config = w->params;
+ struct snd_pcm_substream substream;
+ struct snd_pcm_hw_params *params = NULL;
+ u64 fmt;
+ int ret;
+
+ BUG_ON(!config);
+ BUG_ON(list_empty(&w->sources) || list_empty(&w->sinks));
+
+ /* We only support a single source and sink, pick the first */
+ source_p = list_first_entry(&w->sources, struct snd_soc_dapm_path,
+ list_sink);
+ sink_p = list_first_entry(&w->sinks, struct snd_soc_dapm_path,
+ list_source);
+
+ BUG_ON(!source_p || !sink_p);
+ BUG_ON(!sink_p->source || !source_p->sink);
+ BUG_ON(!source_p->source || !sink_p->sink);
+
+ source = source_p->source->priv;
+ sink = sink_p->sink->priv;
+
+ /* Be a little careful as we don't want to overflow the mask array */
+ if (config->formats) {
+ fmt = ffs(config->formats) - 1;
+ } else {
+ dev_warn(w->dapm->dev, "Invalid format %llx specified\n",
+ config->formats);
+ fmt = 0;
+ }
+
+ /* Currently very limited parameter selection */
+ params = kzalloc(sizeof(*params), GFP_KERNEL);
+ if (!params) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt);
+
+ hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min =
+ config->rate_min;
+ hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max =
+ config->rate_max;
+
+ hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min
+ = config->channels_min;
+ hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max
+ = config->channels_max;
+
+ memset(&substream, 0, sizeof(substream));
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (source->driver->ops && source->driver->ops->hw_params) {
+ substream.stream = SNDRV_PCM_STREAM_CAPTURE;
+ ret = source->driver->ops->hw_params(&substream,
+ params, source);
+ if (ret != 0) {
+ dev_err(source->dev,
+ "hw_params() failed: %d\n", ret);
+ goto out;
+ }
+ }
+
+ if (sink->driver->ops && sink->driver->ops->hw_params) {
+ substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
+ ret = sink->driver->ops->hw_params(&substream, params,
+ sink);
+ if (ret != 0) {
+ dev_err(sink->dev,
+ "hw_params() failed: %d\n", ret);
+ goto out;
+ }
+ }
+ break;
+
+ case SND_SOC_DAPM_POST_PMU:
+ ret = snd_soc_dai_digital_mute(sink, 0);
+ if (ret != 0 && ret != -ENOTSUPP)
+ dev_warn(sink->dev, "Failed to unmute: %d\n", ret);
+ ret = 0;
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ ret = snd_soc_dai_digital_mute(sink, 1);
+ if (ret != 0 && ret != -ENOTSUPP)
+ dev_warn(sink->dev, "Failed to mute: %d\n", ret);
+ ret = 0;
+ break;
+
+ default:
+ BUG();
+ return -EINVAL;
+ }
+
+out:
+ kfree(params);
+ return ret;
+}
+
+int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
+ const struct snd_soc_pcm_stream *params,
+ struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_dapm_route routes[2];
+ struct snd_soc_dapm_widget template;
+ struct snd_soc_dapm_widget *w;
+ size_t len;
+ char *link_name;
+
+ len = strlen(source->name) + strlen(sink->name) + 2;
+ link_name = devm_kzalloc(card->dev, len, GFP_KERNEL);
+ if (!link_name)
+ return -ENOMEM;
+ snprintf(link_name, len, "%s-%s", source->name, sink->name);
+
+ memset(&template, 0, sizeof(template));
+ template.reg = SND_SOC_NOPM;
+ template.id = snd_soc_dapm_dai_link;
+ template.name = link_name;
+ template.event = snd_soc_dai_link_event;
+ template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD;
+
+ dev_dbg(card->dev, "adding %s widget\n", link_name);
+
+ w = snd_soc_dapm_new_control(&card->dapm, &template);
+ if (!w) {
+ dev_err(card->dev, "Failed to create %s widget\n",
+ link_name);
+ return -ENOMEM;
+ }
+
+ w->params = params;
+
+ memset(&routes, 0, sizeof(routes));
+
+ routes[0].source = source->name;
+ routes[0].sink = link_name;
+ routes[1].source = link_name;
+ routes[1].sink = sink->name;
+
+ return snd_soc_dapm_add_routes(&card->dapm, routes,
+ ARRAY_SIZE(routes));
+}
+
int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
struct snd_soc_dai *dai)
{
@@ -2934,37 +3239,61 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
return 0;
}
-static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
- int stream, struct snd_soc_dai *dai,
- int event)
+static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
+ int event)
{
- struct snd_soc_dapm_widget *w;
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- w = dai->playback_widget;
- else
- w = dai->capture_widget;
+ struct snd_soc_dapm_widget *w_cpu, *w_codec;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
- if (!w)
- return;
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ w_cpu = cpu_dai->playback_widget;
+ w_codec = codec_dai->playback_widget;
+ } else {
+ w_cpu = cpu_dai->capture_widget;
+ w_codec = codec_dai->capture_widget;
+ }
- dapm_mark_dirty(w, "stream event");
+ if (w_cpu) {
- switch (event) {
- case SND_SOC_DAPM_STREAM_START:
- w->active = 1;
- break;
- case SND_SOC_DAPM_STREAM_STOP:
- w->active = 0;
- break;
- case SND_SOC_DAPM_STREAM_SUSPEND:
- case SND_SOC_DAPM_STREAM_RESUME:
- case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
- case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
- break;
+ dapm_mark_dirty(w_cpu, "stream event");
+
+ switch (event) {
+ case SND_SOC_DAPM_STREAM_START:
+ w_cpu->active = 1;
+ break;
+ case SND_SOC_DAPM_STREAM_STOP:
+ w_cpu->active = 0;
+ break;
+ case SND_SOC_DAPM_STREAM_SUSPEND:
+ case SND_SOC_DAPM_STREAM_RESUME:
+ case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
+ case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
+ break;
+ }
+ }
+
+ if (w_codec) {
+
+ dapm_mark_dirty(w_codec, "stream event");
+
+ switch (event) {
+ case SND_SOC_DAPM_STREAM_START:
+ w_codec->active = 1;
+ break;
+ case SND_SOC_DAPM_STREAM_STOP:
+ w_codec->active = 0;
+ break;
+ case SND_SOC_DAPM_STREAM_SUSPEND:
+ case SND_SOC_DAPM_STREAM_RESUME:
+ case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
+ case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
+ break;
+ }
}
- dapm_power_widgets(dapm, event);
+ dapm_power_widgets(&rtd->card->dapm, event);
}
/**
@@ -2978,15 +3307,14 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
*
* Returns 0 for success else error.
*/
-int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
- struct snd_soc_dai *dai, int event)
+void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
+ int event)
{
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *card = rtd->card;
- mutex_lock(&codec->mutex);
- soc_dapm_stream_event(&codec->dapm, stream, dai, event);
- mutex_unlock(&codec->mutex);
- return 0;
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+ soc_dapm_stream_event(rtd, stream, event);
+ mutex_unlock(&card->dapm_mutex);
}
/**
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index ee4353f843ea..7f8b3b7428bb 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -36,6 +36,7 @@
int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
struct snd_soc_jack *jack)
{
+ mutex_init(&jack->mutex);
jack->codec = codec;
INIT_LIST_HEAD(&jack->pins);
INIT_LIST_HEAD(&jack->jack_zones);
@@ -75,7 +76,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
codec = jack->codec;
dapm = &codec->dapm;
- mutex_lock(&codec->mutex);
+ mutex_lock(&jack->mutex);
oldstatus = jack->status;
@@ -109,7 +110,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
snd_jack_report(jack->jack, jack->status);
out:
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&jack->mutex);
}
EXPORT_SYMBOL_GPL(snd_soc_jack_report);
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 0ad8dcacd2f3..bedd1717a373 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -22,12 +22,38 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
+#include <linux/export.h>
+#include <linux/debugfs.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/soc-dpcm.h>
#include <sound/initval.h>
+#define DPCM_MAX_BE_USERS 8
+
+/* DPCM stream event, send event to FE and all active BEs. */
+static int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
+ int event)
+{
+ struct snd_soc_dpcm *dpcm;
+
+ list_for_each_entry(dpcm, &fe->dpcm[dir].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+
+ dev_dbg(be->dev, "pm: BE %s event %d dir %d\n",
+ be->dai_link->name, event, dir);
+
+ snd_soc_dapm_stream_event(be, dir, event);
+ }
+
+ snd_soc_dapm_stream_event(fe, dir, event);
+
+ return 0;
+}
+
static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
struct snd_soc_dai *soc_dai)
{
@@ -156,6 +182,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
}
}
+ /* Dynamic PCM DAI links compat checks use dynamic capabilities */
+ if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm)
+ goto dynamic;
+
/* Check that the codec and cpu DAIs are compatible */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
runtime->hw.rate_min =
@@ -248,6 +278,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
runtime->hw.rate_max);
+dynamic:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
cpu_dai->playback_active++;
codec_dai->playback_active++;
@@ -308,7 +339,7 @@ static void close_delayed_work(struct work_struct *work)
if (codec_dai->pop_wait == 1) {
codec_dai->pop_wait = 0;
snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
- codec_dai, SND_SOC_DAPM_STREAM_STOP);
+ SND_SOC_DAPM_STREAM_STOP);
}
mutex_unlock(&rtd->pcm_mutex);
@@ -373,7 +404,6 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
/* powered down playback stream now */
snd_soc_dapm_stream_event(rtd,
SNDRV_PCM_STREAM_PLAYBACK,
- codec_dai,
SND_SOC_DAPM_STREAM_STOP);
} else {
/* start delayed pop wq here for playback streams */
@@ -384,7 +414,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
} else {
/* capture streams can be powered down now */
snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
- codec_dai, SND_SOC_DAPM_STREAM_STOP);
+ SND_SOC_DAPM_STREAM_STOP);
}
mutex_unlock(&rtd->pcm_mutex);
@@ -453,8 +483,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
cancel_delayed_work(&rtd->delayed_work);
}
- snd_soc_dapm_stream_event(rtd, substream->stream, codec_dai,
- SND_SOC_DAPM_STREAM_START);
+ snd_soc_dapm_stream_event(rtd, substream->stream,
+ SND_SOC_DAPM_STREAM_START);
snd_soc_dai_digital_mute(codec_dai, 0);
@@ -602,6 +632,34 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return 0;
}
+static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int ret;
+
+ if (codec_dai->driver->ops->bespoke_trigger) {
+ ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (platform->driver->bespoke_trigger) {
+ ret = platform->driver->bespoke_trigger(substream, cmd);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (cpu_dai->driver->ops->bespoke_trigger) {
+ ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai);
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
/*
* soc level wrapper for pointer callback
* If cpu_dai, codec_dai, platform driver has the delay callback, than
@@ -634,6 +692,1308 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
return offset;
}
+/* connect a FE and BE */
+static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
+ struct snd_soc_pcm_runtime *be, int stream)
+{
+ struct snd_soc_dpcm *dpcm;
+
+ /* only add new dpcms */
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+ if (dpcm->be == be && dpcm->fe == fe)
+ return 0;
+ }
+
+ dpcm = kzalloc(sizeof(struct snd_soc_dpcm), GFP_KERNEL);
+ if (!dpcm)
+ return -ENOMEM;
+
+ dpcm->be = be;
+ dpcm->fe = fe;
+ be->dpcm[stream].runtime = fe->dpcm[stream].runtime;
+ dpcm->state = SND_SOC_DPCM_LINK_STATE_NEW;
+ list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients);
+ list_add(&dpcm->list_fe, &be->dpcm[stream].fe_clients);
+
+ dev_dbg(fe->dev, " connected new DPCM %s path %s %s %s\n",
+ stream ? "capture" : "playback", fe->dai_link->name,
+ stream ? "<-" : "->", be->dai_link->name);
+
+#ifdef CONFIG_DEBUG_FS
+ dpcm->debugfs_state = debugfs_create_u32(be->dai_link->name, 0644,
+ fe->debugfs_dpcm_root, &dpcm->state);
+#endif
+ return 1;
+}
+
+/* reparent a BE onto another FE */
+static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe,
+ struct snd_soc_pcm_runtime *be, int stream)
+{
+ struct snd_soc_dpcm *dpcm;
+ struct snd_pcm_substream *fe_substream, *be_substream;
+
+ /* reparent if BE is connected to other FEs */
+ if (!be->dpcm[stream].users)
+ return;
+
+ be_substream = snd_soc_dpcm_get_substream(be, stream);
+
+ list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) {
+ if (dpcm->fe == fe)
+ continue;
+
+ dev_dbg(fe->dev, " reparent %s path %s %s %s\n",
+ stream ? "capture" : "playback",
+ dpcm->fe->dai_link->name,
+ stream ? "<-" : "->", dpcm->be->dai_link->name);
+
+ fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, stream);
+ be_substream->runtime = fe_substream->runtime;
+ break;
+ }
+}
+
+/* disconnect a BE and FE */
+static void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dpcm *dpcm, *d;
+
+ list_for_each_entry_safe(dpcm, d, &fe->dpcm[stream].be_clients, list_be) {
+ dev_dbg(fe->dev, "BE %s disconnect check for %s\n",
+ stream ? "capture" : "playback",
+ dpcm->be->dai_link->name);
+
+ if (dpcm->state != SND_SOC_DPCM_LINK_STATE_FREE)
+ continue;
+
+ dev_dbg(fe->dev, " freed DSP %s path %s %s %s\n",
+ stream ? "capture" : "playback", fe->dai_link->name,
+ stream ? "<-" : "->", dpcm->be->dai_link->name);
+
+ /* BEs still alive need new FE */
+ dpcm_be_reparent(fe, dpcm->be, stream);
+
+#ifdef CONFIG_DEBUG_FS
+ debugfs_remove(dpcm->debugfs_state);
+#endif
+ list_del(&dpcm->list_be);
+ list_del(&dpcm->list_fe);
+ kfree(dpcm);
+ }
+}
+
+/* get BE for DAI widget and stream */
+static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
+ struct snd_soc_dapm_widget *widget, int stream)
+{
+ struct snd_soc_pcm_runtime *be;
+ int i;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ for (i = 0; i < card->num_links; i++) {
+ be = &card->rtd[i];
+
+ if (be->cpu_dai->playback_widget == widget ||
+ be->codec_dai->playback_widget == widget)
+ return be;
+ }
+ } else {
+
+ for (i = 0; i < card->num_links; i++) {
+ be = &card->rtd[i];
+
+ if (be->cpu_dai->capture_widget == widget ||
+ be->codec_dai->capture_widget == widget)
+ return be;
+ }
+ }
+
+ dev_err(card->dev, "can't get %s BE for %s\n",
+ stream ? "capture" : "playback", widget->name);
+ return NULL;
+}
+
+static inline struct snd_soc_dapm_widget *
+ rtd_get_cpu_widget(struct snd_soc_pcm_runtime *rtd, int stream)
+{
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return rtd->cpu_dai->playback_widget;
+ else
+ return rtd->cpu_dai->capture_widget;
+}
+
+static inline struct snd_soc_dapm_widget *
+ rtd_get_codec_widget(struct snd_soc_pcm_runtime *rtd, int stream)
+{
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return rtd->codec_dai->playback_widget;
+ else
+ return rtd->codec_dai->capture_widget;
+}
+
+static int widget_in_list(struct snd_soc_dapm_widget_list *list,
+ struct snd_soc_dapm_widget *widget)
+{
+ int i;
+
+ for (i = 0; i < list->num_widgets; i++) {
+ if (widget == list->widgets[i])
+ return 1;
+ }
+
+ return 0;
+}
+
+static int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
+ int stream, struct snd_soc_dapm_widget_list **list_)
+{
+ struct snd_soc_dai *cpu_dai = fe->cpu_dai;
+ struct snd_soc_dapm_widget_list *list;
+ int paths;
+
+ list = kzalloc(sizeof(struct snd_soc_dapm_widget_list) +
+ sizeof(struct snd_soc_dapm_widget *), GFP_KERNEL);
+ if (list == NULL)
+ return -ENOMEM;
+
+ /* get number of valid DAI paths and their widgets */
+ paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, &list);
+
+ dev_dbg(fe->dev, "found %d audio %s paths\n", paths,
+ stream ? "capture" : "playback");
+
+ *list_ = list;
+ return paths;
+}
+
+static inline void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
+{
+ kfree(*list);
+}
+
+static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
+ struct snd_soc_dapm_widget_list **list_)
+{
+ struct snd_soc_dpcm *dpcm;
+ struct snd_soc_dapm_widget_list *list = *list_;
+ struct snd_soc_dapm_widget *widget;
+ int prune = 0;
+
+ /* Destroy any old FE <--> BE connections */
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+
+ /* is there a valid CPU DAI widget for this BE */
+ widget = rtd_get_cpu_widget(dpcm->be, stream);
+
+ /* prune the BE if it's no longer in our active list */
+ if (widget && widget_in_list(list, widget))
+ continue;
+
+ /* is there a valid CODEC DAI widget for this BE */
+ widget = rtd_get_codec_widget(dpcm->be, stream);
+
+ /* prune the BE if it's no longer in our active list */
+ if (widget && widget_in_list(list, widget))
+ continue;
+
+ dev_dbg(fe->dev, "pruning %s BE %s for %s\n",
+ stream ? "capture" : "playback",
+ dpcm->be->dai_link->name, fe->dai_link->name);
+ dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
+ dpcm->be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
+ prune++;
+ }
+
+ dev_dbg(fe->dev, "found %d old BE paths for pruning\n", prune);
+ return prune;
+}
+
+static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
+ struct snd_soc_dapm_widget_list **list_)
+{
+ struct snd_soc_card *card = fe->card;
+ struct snd_soc_dapm_widget_list *list = *list_;
+ struct snd_soc_pcm_runtime *be;
+ int i, new = 0, err;
+
+ /* Create any new FE <--> BE connections */
+ for (i = 0; i < list->num_widgets; i++) {
+
+ if (list->widgets[i]->id != snd_soc_dapm_dai)
+ continue;
+
+ /* is there a valid BE rtd for this widget */
+ be = dpcm_get_be(card, list->widgets[i], stream);
+ if (!be) {
+ dev_err(fe->dev, "no BE found for %s\n",
+ list->widgets[i]->name);
+ continue;
+ }
+
+ /* make sure BE is a real BE */
+ if (!be->dai_link->no_pcm)
+ continue;
+
+ /* don't connect if FE is not running */
+ if (!fe->dpcm[stream].runtime)
+ continue;
+
+ /* newly connected FE and BE */
+ err = dpcm_be_connect(fe, be, stream);
+ if (err < 0) {
+ dev_err(fe->dev, "can't connect %s\n",
+ list->widgets[i]->name);
+ break;
+ } else if (err == 0) /* already connected */
+ continue;
+
+ /* new */
+ be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
+ new++;
+ }
+
+ dev_dbg(fe->dev, "found %d new BE paths\n", new);
+ return new;
+}
+
+/*
+ * Find the corresponding BE DAIs that source or sink audio to this
+ * FE substream.
+ */
+static int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
+ int stream, struct snd_soc_dapm_widget_list **list, int new)
+{
+ if (new)
+ return dpcm_add_paths(fe, stream, list);
+ else
+ return dpcm_prune_paths(fe, stream, list);
+}
+
+static void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dpcm *dpcm;
+
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
+ dpcm->be->dpcm[stream].runtime_update =
+ SND_SOC_DPCM_UPDATE_NO;
+}
+
+static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe,
+ int stream)
+{
+ struct snd_soc_dpcm *dpcm;
+
+ /* disable any enabled and non active backends */
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dpcm_get_substream(be, stream);
+
+ if (be->dpcm[stream].users == 0)
+ dev_err(be->dev, "no users %s at close - state %d\n",
+ stream ? "capture" : "playback",
+ be->dpcm[stream].state);
+
+ if (--be->dpcm[stream].users != 0)
+ continue;
+
+ if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)
+ continue;
+
+ soc_pcm_close(be_substream);
+ be_substream->runtime = NULL;
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
+ }
+}
+
+static int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dpcm *dpcm;
+ int err, count = 0;
+
+ /* only startup BE DAIs that are either sinks or sources to this FE DAI */
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dpcm_get_substream(be, stream);
+
+ /* is this op for this BE ? */
+ if (!snd_soc_dpcm_be_can_update(fe, be, stream))
+ continue;
+
+ /* first time the dpcm is open ? */
+ if (be->dpcm[stream].users == DPCM_MAX_BE_USERS)
+ dev_err(be->dev, "too many users %s at open %d\n",
+ stream ? "capture" : "playback",
+ be->dpcm[stream].state);
+
+ if (be->dpcm[stream].users++ != 0)
+ continue;
+
+ if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
+ continue;
+
+ dev_dbg(be->dev, "dpcm: open BE %s\n", be->dai_link->name);
+
+ be_substream->runtime = be->dpcm[stream].runtime;
+ err = soc_pcm_open(be_substream);
+ if (err < 0) {
+ dev_err(be->dev, "BE open failed %d\n", err);
+ be->dpcm[stream].users--;
+ if (be->dpcm[stream].users < 0)
+ dev_err(be->dev, "no users %s at unwind %d\n",
+ stream ? "capture" : "playback",
+ be->dpcm[stream].state);
+
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
+ goto unwind;
+ }
+
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
+ count++;
+ }
+
+ return count;
+
+unwind:
+ /* disable any enabled and non active backends */
+ list_for_each_entry_continue_reverse(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dpcm_get_substream(be, stream);
+
+ if (!snd_soc_dpcm_be_can_update(fe, be, stream))
+ continue;
+
+ if (be->dpcm[stream].users == 0)
+ dev_err(be->dev, "no users %s at close %d\n",
+ stream ? "capture" : "playback",
+ be->dpcm[stream].state);
+
+ if (--be->dpcm[stream].users != 0)
+ continue;
+
+ if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)
+ continue;
+
+ soc_pcm_close(be_substream);
+ be_substream->runtime = NULL;
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
+ }
+
+ return err;
+}
+
+static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ runtime->hw.rate_min = cpu_dai_drv->playback.rate_min;
+ runtime->hw.rate_max = cpu_dai_drv->playback.rate_max;
+ runtime->hw.channels_min = cpu_dai_drv->playback.channels_min;
+ runtime->hw.channels_max = cpu_dai_drv->playback.channels_max;
+ runtime->hw.formats &= cpu_dai_drv->playback.formats;
+ runtime->hw.rates = cpu_dai_drv->playback.rates;
+ } else {
+ runtime->hw.rate_min = cpu_dai_drv->capture.rate_min;
+ runtime->hw.rate_max = cpu_dai_drv->capture.rate_max;
+ runtime->hw.channels_min = cpu_dai_drv->capture.channels_min;
+ runtime->hw.channels_max = cpu_dai_drv->capture.channels_max;
+ runtime->hw.formats &= cpu_dai_drv->capture.formats;
+ runtime->hw.rates = cpu_dai_drv->capture.rates;
+ }
+}
+
+static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
+{
+ struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
+ struct snd_pcm_runtime *runtime = fe_substream->runtime;
+ int stream = fe_substream->stream, ret = 0;
+
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+
+ ret = dpcm_be_dai_startup(fe, fe_substream->stream);
+ if (ret < 0) {
+ dev_err(fe->dev,"dpcm: failed to start some BEs %d\n", ret);
+ goto be_err;
+ }
+
+ dev_dbg(fe->dev, "dpcm: open FE %s\n", fe->dai_link->name);
+
+ /* start the DAI frontend */
+ ret = soc_pcm_open(fe_substream);
+ if (ret < 0) {
+ dev_err(fe->dev,"dpcm: failed to start FE %d\n", ret);
+ goto unwind;
+ }
+
+ fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
+
+ dpcm_set_fe_runtime(fe_substream);
+ snd_pcm_limit_hw_rates(runtime);
+
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+ return 0;
+
+unwind:
+ dpcm_be_dai_startup_unwind(fe, fe_substream->stream);
+be_err:
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+ return ret;
+}
+
+static int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dpcm *dpcm;
+
+ /* only shutdown BEs that are either sinks or sources to this FE DAI */
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dpcm_get_substream(be, stream);
+
+ /* is this op for this BE ? */
+ if (!snd_soc_dpcm_be_can_update(fe, be, stream))
+ continue;
+
+ if (be->dpcm[stream].users == 0)
+ dev_err(be->dev, "no users %s at close - state %d\n",
+ stream ? "capture" : "playback",
+ be->dpcm[stream].state);
+
+ if (--be->dpcm[stream].users != 0)
+ continue;
+
+ if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN))
+ continue;
+
+ dev_dbg(be->dev, "dpcm: close BE %s\n",
+ dpcm->fe->dai_link->name);
+
+ soc_pcm_close(be_substream);
+ be_substream->runtime = NULL;
+
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
+ }
+ return 0;
+}
+
+static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ int stream = substream->stream;
+
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+
+ /* shutdown the BEs */
+ dpcm_be_dai_shutdown(fe, substream->stream);
+
+ dev_dbg(fe->dev, "dpcm: close FE %s\n", fe->dai_link->name);
+
+ /* now shutdown the frontend */
+ soc_pcm_close(substream);
+
+ /* run the stream event for each BE */
+ dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
+
+ fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+ return 0;
+}
+
+static int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dpcm *dpcm;
+
+ /* only hw_params backends that are either sinks or sources
+ * to this frontend DAI */
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dpcm_get_substream(be, stream);
+
+ /* is this op for this BE ? */
+ if (!snd_soc_dpcm_be_can_update(fe, be, stream))
+ continue;
+
+ /* only free hw when no longer used - check all FEs */
+ if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
+ continue;
+
+ if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
+ continue;
+
+ dev_dbg(be->dev, "dpcm: hw_free BE %s\n",
+ dpcm->fe->dai_link->name);
+
+ soc_pcm_hw_free(be_substream);
+
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
+ }
+
+ return 0;
+}
+
+static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ int err, stream = substream->stream;
+
+ mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+
+ dev_dbg(fe->dev, "dpcm: hw_free FE %s\n", fe->dai_link->name);
+
+ /* call hw_free on the frontend */
+ err = soc_pcm_hw_free(substream);
+ if (err < 0)
+ dev_err(fe->dev,"dpcm: hw_free FE %s failed\n",
+ fe->dai_link->name);
+
+ /* only hw_params backends that are either sinks or sources
+ * to this frontend DAI */
+ err = dpcm_be_dai_hw_free(fe, stream);
+
+ fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+
+ mutex_unlock(&fe->card->mutex);
+ return 0;
+}
+
+static int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dpcm *dpcm;
+ int ret;
+
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dpcm_get_substream(be, stream);
+
+ /* is this op for this BE ? */
+ if (!snd_soc_dpcm_be_can_update(fe, be, stream))
+ continue;
+
+ /* only allow hw_params() if no connected FEs are running */
+ if (!snd_soc_dpcm_can_be_params(fe, be, stream))
+ continue;
+
+ if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE))
+ continue;
+
+ dev_dbg(be->dev, "dpcm: hw_params BE %s\n",
+ dpcm->fe->dai_link->name);
+
+ /* copy params for each dpcm */
+ memcpy(&dpcm->hw_params, &fe->dpcm[stream].hw_params,
+ sizeof(struct snd_pcm_hw_params));
+
+ /* perform any hw_params fixups */
+ if (be->dai_link->be_hw_params_fixup) {
+ ret = be->dai_link->be_hw_params_fixup(be,
+ &dpcm->hw_params);
+ if (ret < 0) {
+ dev_err(be->dev,
+ "dpcm: hw_params BE fixup failed %d\n",
+ ret);
+ goto unwind;
+ }
+ }
+
+ ret = soc_pcm_hw_params(be_substream, &dpcm->hw_params);
+ if (ret < 0) {
+ dev_err(dpcm->be->dev,
+ "dpcm: hw_params BE failed %d\n", ret);
+ goto unwind;
+ }
+
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
+ }
+ return 0;
+
+unwind:
+ /* disable any enabled and non active backends */
+ list_for_each_entry_continue_reverse(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dpcm_get_substream(be, stream);
+
+ if (!snd_soc_dpcm_be_can_update(fe, be, stream))
+ continue;
+
+ /* only allow hw_free() if no connected FEs are running */
+ if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
+ continue;
+
+ if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
+ continue;
+
+ soc_pcm_hw_free(be_substream);
+ }
+
+ return ret;
+}
+
+static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ int ret, stream = substream->stream;
+
+ mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+
+ memcpy(&fe->dpcm[substream->stream].hw_params, params,
+ sizeof(struct snd_pcm_hw_params));
+ ret = dpcm_be_dai_hw_params(fe, substream->stream);
+ if (ret < 0) {
+ dev_err(fe->dev,"dpcm: hw_params BE failed %d\n", ret);
+ goto out;
+ }
+
+ dev_dbg(fe->dev, "dpcm: hw_params FE %s rate %d chan %x fmt %d\n",
+ fe->dai_link->name, params_rate(params),
+ params_channels(params), params_format(params));
+
+ /* call hw_params on the frontend */
+ ret = soc_pcm_hw_params(substream, params);
+ if (ret < 0) {
+ dev_err(fe->dev,"dpcm: hw_params FE failed %d\n", ret);
+ dpcm_be_dai_hw_free(fe, stream);
+ } else
+ fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
+
+out:
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+ mutex_unlock(&fe->card->mutex);
+ return ret;
+}
+
+static int dpcm_do_trigger(struct snd_soc_dpcm *dpcm,
+ struct snd_pcm_substream *substream, int cmd)
+{
+ int ret;
+
+ dev_dbg(dpcm->be->dev, "dpcm: trigger BE %s cmd %d\n",
+ dpcm->fe->dai_link->name, cmd);
+
+ ret = soc_pcm_trigger(substream, cmd);
+ if (ret < 0)
+ dev_err(dpcm->be->dev,"dpcm: trigger BE failed %d\n", ret);
+
+ return ret;
+}
+
+static int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,
+ int cmd)
+{
+ struct snd_soc_dpcm *dpcm;
+ int ret = 0;
+
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dpcm_get_substream(be, stream);
+
+ /* is this op for this BE ? */
+ if (!snd_soc_dpcm_be_can_update(fe, be, stream))
+ continue;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
+ continue;
+
+ ret = dpcm_do_trigger(dpcm, be_substream, cmd);
+ if (ret)
+ return ret;
+
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
+ break;
+ case SNDRV_PCM_TRIGGER_RESUME:
+ if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
+ continue;
+
+ ret = dpcm_do_trigger(dpcm, be_substream, cmd);
+ if (ret)
+ return ret;
+
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
+ continue;
+
+ ret = dpcm_do_trigger(dpcm, be_substream, cmd);
+ if (ret)
+ return ret;
+
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
+ continue;
+
+ if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
+ continue;
+
+ ret = dpcm_do_trigger(dpcm, be_substream, cmd);
+ if (ret)
+ return ret;
+
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)
+ continue;
+
+ if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
+ continue;
+
+ ret = dpcm_do_trigger(dpcm, be_substream, cmd);
+ if (ret)
+ return ret;
+
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_SUSPEND;
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
+ continue;
+
+ if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
+ continue;
+
+ ret = dpcm_do_trigger(dpcm, be_substream, cmd);
+ if (ret)
+ return ret;
+
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
+ break;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger);
+
+static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ int stream = substream->stream, ret;
+ enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
+
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+
+ switch (trigger) {
+ case SND_SOC_DPCM_TRIGGER_PRE:
+ /* call trigger on the frontend before the backend. */
+
+ dev_dbg(fe->dev, "dpcm: pre trigger FE %s cmd %d\n",
+ fe->dai_link->name, cmd);
+
+ ret = soc_pcm_trigger(substream, cmd);
+ if (ret < 0) {
+ dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
+ goto out;
+ }
+
+ ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
+ break;
+ case SND_SOC_DPCM_TRIGGER_POST:
+ /* call trigger on the frontend after the backend. */
+
+ ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
+ if (ret < 0) {
+ dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
+ goto out;
+ }
+
+ dev_dbg(fe->dev, "dpcm: post trigger FE %s cmd %d\n",
+ fe->dai_link->name, cmd);
+
+ ret = soc_pcm_trigger(substream, cmd);
+ break;
+ case SND_SOC_DPCM_TRIGGER_BESPOKE:
+ /* bespoke trigger() - handles both FE and BEs */
+
+ dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd %d\n",
+ fe->dai_link->name, cmd);
+
+ ret = soc_pcm_bespoke_trigger(substream, cmd);
+ if (ret < 0) {
+ dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
+ goto out;
+ }
+ break;
+ default:
+ dev_err(fe->dev, "dpcm: invalid trigger cmd %d for %s\n", cmd,
+ fe->dai_link->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
+ break;
+ }
+
+out:
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+ return ret;
+}
+
+static int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_soc_dpcm *dpcm;
+ int ret = 0;
+
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dpcm_get_substream(be, stream);
+
+ /* is this op for this BE ? */
+ if (!snd_soc_dpcm_be_can_update(fe, be, stream))
+ continue;
+
+ if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
+ continue;
+
+ dev_dbg(be->dev, "dpcm: prepare BE %s\n",
+ dpcm->fe->dai_link->name);
+
+ ret = soc_pcm_prepare(be_substream);
+ if (ret < 0) {
+ dev_err(be->dev, "dpcm: backend prepare failed %d\n",
+ ret);
+ break;
+ }
+
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
+ }
+ return ret;
+}
+
+static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *fe = substream->private_data;
+ int stream = substream->stream, ret = 0;
+
+ mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
+
+ dev_dbg(fe->dev, "dpcm: prepare FE %s\n", fe->dai_link->name);
+
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+
+ /* there is no point preparing this FE if there are no BEs */
+ if (list_empty(&fe->dpcm[stream].be_clients)) {
+ dev_err(fe->dev, "dpcm: no backend DAIs enabled for %s\n",
+ fe->dai_link->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = dpcm_be_dai_prepare(fe, substream->stream);
+ if (ret < 0)
+ goto out;
+
+ /* call prepare on the frontend */
+ ret = soc_pcm_prepare(substream);
+ if (ret < 0) {
+ dev_err(fe->dev,"dpcm: prepare FE %s failed\n",
+ fe->dai_link->name);
+ goto out;
+ }
+
+ /* run the stream event for each BE */
+ dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
+ fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
+
+out:
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+ mutex_unlock(&fe->card->mutex);
+
+ return ret;
+}
+
+static int soc_pcm_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_platform *platform = rtd->platform;
+
+ if (platform->driver->ops->ioctl)
+ return platform->driver->ops->ioctl(substream, cmd, arg);
+ return snd_pcm_lib_ioctl(substream, cmd, arg);
+}
+
+static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_pcm_substream *substream =
+ snd_soc_dpcm_get_substream(fe, stream);
+ enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
+ int err;
+
+ dev_dbg(fe->dev, "runtime %s close on FE %s\n",
+ stream ? "capture" : "playback", fe->dai_link->name);
+
+ if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
+ /* call bespoke trigger - FE takes care of all BE triggers */
+ dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd stop\n",
+ fe->dai_link->name);
+
+ err = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
+ if (err < 0)
+ dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
+ } else {
+ dev_dbg(fe->dev, "dpcm: trigger FE %s cmd stop\n",
+ fe->dai_link->name);
+
+ err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
+ if (err < 0)
+ dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
+ }
+
+ err = dpcm_be_dai_hw_free(fe, stream);
+ if (err < 0)
+ dev_err(fe->dev,"dpcm: hw_free FE failed %d\n", err);
+
+ err = dpcm_be_dai_shutdown(fe, stream);
+ if (err < 0)
+ dev_err(fe->dev,"dpcm: shutdown FE failed %d\n", err);
+
+ /* run the stream event for each BE */
+ dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_NOP);
+
+ return 0;
+}
+
+static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_pcm_substream *substream =
+ snd_soc_dpcm_get_substream(fe, stream);
+ struct snd_soc_dpcm *dpcm;
+ enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
+ int ret;
+
+ dev_dbg(fe->dev, "runtime %s open on FE %s\n",
+ stream ? "capture" : "playback", fe->dai_link->name);
+
+ /* Only start the BE if the FE is ready */
+ if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE ||
+ fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
+ return -EINVAL;
+
+ /* startup must always be called for new BEs */
+ ret = dpcm_be_dai_startup(fe, stream);
+ if (ret < 0) {
+ goto disconnect;
+ return ret;
+ }
+
+ /* keep going if FE state is > open */
+ if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_OPEN)
+ return 0;
+
+ ret = dpcm_be_dai_hw_params(fe, stream);
+ if (ret < 0) {
+ goto close;
+ return ret;
+ }
+
+ /* keep going if FE state is > hw_params */
+ if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_PARAMS)
+ return 0;
+
+
+ ret = dpcm_be_dai_prepare(fe, stream);
+ if (ret < 0) {
+ goto hw_free;
+ return ret;
+ }
+
+ /* run the stream event for each BE */
+ dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_NOP);
+
+ /* keep going if FE state is > prepare */
+ if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PREPARE ||
+ fe->dpcm[stream].state == SND_SOC_DPCM_STATE_STOP)
+ return 0;
+
+ if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
+ /* call trigger on the frontend - FE takes care of all BE triggers */
+ dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd start\n",
+ fe->dai_link->name);
+
+ ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
+ if (ret < 0) {
+ dev_err(fe->dev,"dpcm: bespoke trigger FE failed %d\n", ret);
+ goto hw_free;
+ }
+ } else {
+ dev_dbg(fe->dev, "dpcm: trigger FE %s cmd start\n",
+ fe->dai_link->name);
+
+ ret = dpcm_be_dai_trigger(fe, stream,
+ SNDRV_PCM_TRIGGER_START);
+ if (ret < 0) {
+ dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
+ goto hw_free;
+ }
+ }
+
+ return 0;
+
+hw_free:
+ dpcm_be_dai_hw_free(fe, stream);
+close:
+ dpcm_be_dai_shutdown(fe, stream);
+disconnect:
+ /* disconnect any non started BEs */
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
+ dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
+ }
+
+ return ret;
+}
+
+static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ int ret;
+
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
+ ret = dpcm_run_update_startup(fe, stream);
+ if (ret < 0)
+ dev_err(fe->dev, "failed to startup some BEs\n");
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+
+ return ret;
+}
+
+static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ int ret;
+
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
+ ret = dpcm_run_update_shutdown(fe, stream);
+ if (ret < 0)
+ dev_err(fe->dev, "failed to shutdown some BEs\n");
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+
+ return ret;
+}
+
+/* Called by DAPM mixer/mux changes to update audio routing between PCMs and
+ * any DAI links.
+ */
+int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget)
+{
+ struct snd_soc_card *card;
+ int i, old, new, paths;
+
+ if (widget->codec)
+ card = widget->codec->card;
+ else if (widget->platform)
+ card = widget->platform->card;
+ else
+ return -EINVAL;
+
+ mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
+ for (i = 0; i < card->num_rtd; i++) {
+ struct snd_soc_dapm_widget_list *list;
+ struct snd_soc_pcm_runtime *fe = &card->rtd[i];
+
+ /* make sure link is FE */
+ if (!fe->dai_link->dynamic)
+ continue;
+
+ /* only check active links */
+ if (!fe->cpu_dai->active)
+ continue;
+
+ /* DAPM sync will call this to update DSP paths */
+ dev_dbg(fe->dev, "DPCM runtime update for FE %s\n",
+ fe->dai_link->name);
+
+ /* skip if FE doesn't have playback capability */
+ if (!fe->cpu_dai->driver->playback.channels_min)
+ goto capture;
+
+ paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list);
+ if (paths < 0) {
+ dev_warn(fe->dev, "%s no valid %s path\n",
+ fe->dai_link->name, "playback");
+ mutex_unlock(&card->mutex);
+ return paths;
+ }
+
+ /* update any new playback paths */
+ new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 1);
+ if (new) {
+ dpcm_run_new_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ }
+
+ /* update any old playback paths */
+ old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 0);
+ if (old) {
+ dpcm_run_old_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ }
+
+capture:
+ /* skip if FE doesn't have capture capability */
+ if (!fe->cpu_dai->driver->capture.channels_min)
+ continue;
+
+ paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list);
+ if (paths < 0) {
+ dev_warn(fe->dev, "%s no valid %s path\n",
+ fe->dai_link->name, "capture");
+ mutex_unlock(&card->mutex);
+ return paths;
+ }
+
+ /* update any new capture paths */
+ new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 1);
+ if (new) {
+ dpcm_run_new_update(fe, SNDRV_PCM_STREAM_CAPTURE);
+ dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_CAPTURE);
+ dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
+ }
+
+ /* update any old capture paths */
+ old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 0);
+ if (old) {
+ dpcm_run_old_update(fe, SNDRV_PCM_STREAM_CAPTURE);
+ dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_CAPTURE);
+ dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
+ }
+
+ dpcm_path_put(&list);
+ }
+
+ mutex_unlock(&card->mutex);
+ return 0;
+}
+int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
+{
+ struct snd_soc_dpcm *dpcm;
+ struct list_head *clients =
+ &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients;
+
+ list_for_each_entry(dpcm, clients, list_be) {
+
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_soc_dai *dai = be->codec_dai;
+ struct snd_soc_dai_driver *drv = dai->driver;
+
+ if (be->dai_link->ignore_suspend)
+ continue;
+
+ dev_dbg(be->dev, "BE digital mute %s\n", be->dai_link->name);
+
+ if (drv->ops->digital_mute && dai->playback_active)
+ drv->ops->digital_mute(dai, mute);
+ }
+
+ return 0;
+}
+
+static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
+{
+ struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
+ struct snd_soc_dpcm *dpcm;
+ struct snd_soc_dapm_widget_list *list;
+ int ret;
+ int stream = fe_substream->stream;
+
+ mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
+ fe->dpcm[stream].runtime = fe_substream->runtime;
+
+ if (dpcm_path_get(fe, stream, &list) <= 0) {
+ dev_warn(fe->dev, "asoc: %s no valid %s route\n",
+ fe->dai_link->name, stream ? "capture" : "playback");
+ mutex_unlock(&fe->card->mutex);
+ return -EINVAL;
+ }
+
+ /* calculate valid and active FE <-> BE dpcms */
+ dpcm_process_paths(fe, stream, &list, 1);
+
+ ret = dpcm_fe_dai_startup(fe_substream);
+ if (ret < 0) {
+ /* clean up all links */
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
+ dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
+
+ dpcm_be_disconnect(fe, stream);
+ fe->dpcm[stream].runtime = NULL;
+ }
+
+ dpcm_clear_pending_state(fe, stream);
+ dpcm_path_put(&list);
+ mutex_unlock(&fe->card->mutex);
+ return ret;
+}
+
+static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
+{
+ struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
+ struct snd_soc_dpcm *dpcm;
+ int stream = fe_substream->stream, ret;
+
+ mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
+ ret = dpcm_fe_dai_shutdown(fe_substream);
+
+ /* mark FE's links ready to prune */
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
+ dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
+
+ dpcm_be_disconnect(fe, stream);
+
+ fe->dpcm[stream].runtime = NULL;
+ mutex_unlock(&fe->card->mutex);
+ return ret;
+}
+
/* create a new pcm */
int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
{
@@ -641,56 +2001,94 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
struct snd_soc_platform *platform = rtd->platform;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_pcm_ops *soc_pcm_ops = &rtd->ops;
struct snd_pcm *pcm;
char new_name[64];
int ret = 0, playback = 0, capture = 0;
- soc_pcm_ops->open = soc_pcm_open;
- soc_pcm_ops->close = soc_pcm_close;
- soc_pcm_ops->hw_params = soc_pcm_hw_params;
- soc_pcm_ops->hw_free = soc_pcm_hw_free;
- soc_pcm_ops->prepare = soc_pcm_prepare;
- soc_pcm_ops->trigger = soc_pcm_trigger;
- soc_pcm_ops->pointer = soc_pcm_pointer;
-
- /* check client and interface hw capabilities */
- snprintf(new_name, sizeof(new_name), "%s %s-%d",
- rtd->dai_link->stream_name, codec_dai->name, num);
-
- if (codec_dai->driver->playback.channels_min)
- playback = 1;
- if (codec_dai->driver->capture.channels_min)
- capture = 1;
-
- dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name);
- ret = snd_pcm_new(rtd->card->snd_card, new_name,
- num, playback, capture, &pcm);
+ if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
+ if (cpu_dai->driver->playback.channels_min)
+ playback = 1;
+ if (cpu_dai->driver->capture.channels_min)
+ capture = 1;
+ } else {
+ if (codec_dai->driver->playback.channels_min)
+ playback = 1;
+ if (codec_dai->driver->capture.channels_min)
+ capture = 1;
+ }
+
+ /* create the PCM */
+ if (rtd->dai_link->no_pcm) {
+ snprintf(new_name, sizeof(new_name), "(%s)",
+ rtd->dai_link->stream_name);
+
+ ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
+ playback, capture, &pcm);
+ } else {
+ if (rtd->dai_link->dynamic)
+ snprintf(new_name, sizeof(new_name), "%s (*)",
+ rtd->dai_link->stream_name);
+ else
+ snprintf(new_name, sizeof(new_name), "%s %s-%d",
+ rtd->dai_link->stream_name, codec_dai->name, num);
+
+ ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
+ capture, &pcm);
+ }
if (ret < 0) {
printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
return ret;
}
+ dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num, new_name);
/* DAPM dai link stream work */
INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
rtd->pcm = pcm;
pcm->private_data = rtd;
+
+ if (rtd->dai_link->no_pcm) {
+ if (playback)
+ pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
+ if (capture)
+ pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
+ goto out;
+ }
+
+ /* ASoC PCM operations */
+ if (rtd->dai_link->dynamic) {
+ rtd->ops.open = dpcm_fe_dai_open;
+ rtd->ops.hw_params = dpcm_fe_dai_hw_params;
+ rtd->ops.prepare = dpcm_fe_dai_prepare;
+ rtd->ops.trigger = dpcm_fe_dai_trigger;
+ rtd->ops.hw_free = dpcm_fe_dai_hw_free;
+ rtd->ops.close = dpcm_fe_dai_close;
+ rtd->ops.pointer = soc_pcm_pointer;
+ rtd->ops.ioctl = soc_pcm_ioctl;
+ } else {
+ rtd->ops.open = soc_pcm_open;
+ rtd->ops.hw_params = soc_pcm_hw_params;
+ rtd->ops.prepare = soc_pcm_prepare;
+ rtd->ops.trigger = soc_pcm_trigger;
+ rtd->ops.hw_free = soc_pcm_hw_free;
+ rtd->ops.close = soc_pcm_close;
+ rtd->ops.pointer = soc_pcm_pointer;
+ rtd->ops.ioctl = soc_pcm_ioctl;
+ }
+
if (platform->driver->ops) {
- soc_pcm_ops->mmap = platform->driver->ops->mmap;
- soc_pcm_ops->pointer = platform->driver->ops->pointer;
- soc_pcm_ops->ioctl = platform->driver->ops->ioctl;
- soc_pcm_ops->copy = platform->driver->ops->copy;
- soc_pcm_ops->silence = platform->driver->ops->silence;
- soc_pcm_ops->ack = platform->driver->ops->ack;
- soc_pcm_ops->page = platform->driver->ops->page;
+ rtd->ops.ack = platform->driver->ops->ack;
+ rtd->ops.copy = platform->driver->ops->copy;
+ rtd->ops.silence = platform->driver->ops->silence;
+ rtd->ops.page = platform->driver->ops->page;
+ rtd->ops.mmap = platform->driver->ops->mmap;
}
if (playback)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, soc_pcm_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &rtd->ops);
if (capture)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, soc_pcm_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops);
if (platform->driver->pcm_new) {
ret = platform->driver->pcm_new(rtd);
@@ -701,7 +2099,257 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
}
pcm->private_free = platform->driver->pcm_free;
+out:
printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
cpu_dai->name);
return ret;
}
+
+/* is the current PCM operation for this FE ? */
+int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ if (fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_FE)
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dpcm_fe_can_update);
+
+/* is the current PCM operation for this BE ? */
+int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe,
+ struct snd_soc_pcm_runtime *be, int stream)
+{
+ if ((fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_FE) ||
+ ((fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_BE) &&
+ be->dpcm[stream].runtime_update))
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dpcm_be_can_update);
+
+/* get the substream for this BE */
+struct snd_pcm_substream *
+ snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream)
+{
+ return be->pcm->streams[stream].substream;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dpcm_get_substream);
+
+/* get the BE runtime state */
+enum snd_soc_dpcm_state
+ snd_soc_dpcm_be_get_state(struct snd_soc_pcm_runtime *be, int stream)
+{
+ return be->dpcm[stream].state;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dpcm_be_get_state);
+
+/* set the BE runtime state */
+void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be,
+ int stream, enum snd_soc_dpcm_state state)
+{
+ be->dpcm[stream].state = state;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dpcm_be_set_state);
+
+/*
+ * We can only hw_free, stop, pause or suspend a BE DAI if any of it's FE
+ * are not running, paused or suspended for the specified stream direction.
+ */
+int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
+ struct snd_soc_pcm_runtime *be, int stream)
+{
+ struct snd_soc_dpcm *dpcm;
+ int state;
+
+ list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) {
+
+ if (dpcm->fe == fe)
+ continue;
+
+ state = dpcm->fe->dpcm[stream].state;
+ if (state == SND_SOC_DPCM_STATE_START ||
+ state == SND_SOC_DPCM_STATE_PAUSED ||
+ state == SND_SOC_DPCM_STATE_SUSPEND)
+ return 0;
+ }
+
+ /* it's safe to free/stop this BE DAI */
+ return 1;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_free_stop);
+
+/*
+ * We can only change hw params a BE DAI if any of it's FE are not prepared,
+ * running, paused or suspended for the specified stream direction.
+ */
+int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
+ struct snd_soc_pcm_runtime *be, int stream)
+{
+ struct snd_soc_dpcm *dpcm;
+ int state;
+
+ list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) {
+
+ if (dpcm->fe == fe)
+ continue;
+
+ state = dpcm->fe->dpcm[stream].state;
+ if (state == SND_SOC_DPCM_STATE_START ||
+ state == SND_SOC_DPCM_STATE_PAUSED ||
+ state == SND_SOC_DPCM_STATE_SUSPEND ||
+ state == SND_SOC_DPCM_STATE_PREPARE)
+ return 0;
+ }
+
+ /* it's safe to change hw_params */
+ return 1;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
+
+int snd_soc_platform_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_platform *platform)
+{
+ if (platform->driver->ops->trigger)
+ return platform->driver->ops->trigger(substream, cmd);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_platform_trigger);
+
+#ifdef CONFIG_DEBUG_FS
+static char *dpcm_state_string(enum snd_soc_dpcm_state state)
+{
+ switch (state) {
+ case SND_SOC_DPCM_STATE_NEW:
+ return "new";
+ case SND_SOC_DPCM_STATE_OPEN:
+ return "open";
+ case SND_SOC_DPCM_STATE_HW_PARAMS:
+ return "hw_params";
+ case SND_SOC_DPCM_STATE_PREPARE:
+ return "prepare";
+ case SND_SOC_DPCM_STATE_START:
+ return "start";
+ case SND_SOC_DPCM_STATE_STOP:
+ return "stop";
+ case SND_SOC_DPCM_STATE_SUSPEND:
+ return "suspend";
+ case SND_SOC_DPCM_STATE_PAUSED:
+ return "paused";
+ case SND_SOC_DPCM_STATE_HW_FREE:
+ return "hw_free";
+ case SND_SOC_DPCM_STATE_CLOSE:
+ return "close";
+ }
+
+ return "unknown";
+}
+
+static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
+ int stream, char *buf, size_t size)
+{
+ struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
+ struct snd_soc_dpcm *dpcm;
+ ssize_t offset = 0;
+
+ /* FE state */
+ offset += snprintf(buf + offset, size - offset,
+ "[%s - %s]\n", fe->dai_link->name,
+ stream ? "Capture" : "Playback");
+
+ offset += snprintf(buf + offset, size - offset, "State: %s\n",
+ dpcm_state_string(fe->dpcm[stream].state));
+
+ if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
+ (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
+ offset += snprintf(buf + offset, size - offset,
+ "Hardware Params: "
+ "Format = %s, Channels = %d, Rate = %d\n",
+ snd_pcm_format_name(params_format(params)),
+ params_channels(params),
+ params_rate(params));
+
+ /* BEs state */
+ offset += snprintf(buf + offset, size - offset, "Backends:\n");
+
+ if (list_empty(&fe->dpcm[stream].be_clients)) {
+ offset += snprintf(buf + offset, size - offset,
+ " No active DSP links\n");
+ goto out;
+ }
+
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ params = &dpcm->hw_params;
+
+ offset += snprintf(buf + offset, size - offset,
+ "- %s\n", be->dai_link->name);
+
+ offset += snprintf(buf + offset, size - offset,
+ " State: %s\n",
+ dpcm_state_string(be->dpcm[stream].state));
+
+ if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
+ (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
+ offset += snprintf(buf + offset, size - offset,
+ " Hardware Params: "
+ "Format = %s, Channels = %d, Rate = %d\n",
+ snd_pcm_format_name(params_format(params)),
+ params_channels(params),
+ params_rate(params));
+ }
+
+out:
+ return offset;
+}
+
+static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct snd_soc_pcm_runtime *fe = file->private_data;
+ ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0;
+ char *buf;
+
+ buf = kmalloc(out_count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ if (fe->cpu_dai->driver->playback.channels_min)
+ offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_PLAYBACK,
+ buf + offset, out_count - offset);
+
+ if (fe->cpu_dai->driver->capture.channels_min)
+ offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_CAPTURE,
+ buf + offset, out_count - offset);
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
+
+ kfree(buf);
+ return ret;
+}
+
+static const struct file_operations dpcm_state_fops = {
+ .open = simple_open,
+ .read = dpcm_state_read_file,
+ .llseek = default_llseek,
+};
+
+int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
+{
+ if (!rtd->dai_link)
+ return 0;
+
+ rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name,
+ rtd->card->debugfs_card_root);
+ if (!rtd->debugfs_dpcm_root) {
+ dev_dbg(rtd->dev,
+ "ASoC: Failed to create dpcm debugfs directory %s\n",
+ rtd->dai_link->name);
+ return -EINVAL;
+ }
+
+ rtd->debugfs_dpcm_state = debugfs_create_file("state", 0444,
+ rtd->debugfs_dpcm_root,
+ rtd, &dpcm_state_fops);
+
+ return 0;
+}
+#endif
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index ce1b773c351f..c1c8e955f4d3 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -1,26 +1,63 @@
config SND_SOC_TEGRA
tristate "SoC Audio for the Tegra System-on-Chip"
depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA
+ select REGMAP_MMIO
help
Say Y or M here if you want support for SoC audio on Tegra.
-config SND_SOC_TEGRA_I2S
+config SND_SOC_TEGRA20_DAS
tristate
- depends on SND_SOC_TEGRA
+ depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
+ help
+ Say Y or M if you want to add support for the Tegra20 DAS module.
+ You will also need to select the individual machine drivers to
+ support below.
+
+config SND_SOC_TEGRA20_I2S
+ tristate
+ depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
+ select SND_SOC_TEGRA20_DAS
help
Say Y or M if you want to add support for codecs attached to the
- Tegra I2S interface. You will also need to select the individual
+ Tegra20 I2S interface. You will also need to select the individual
machine drivers to support below.
-config SND_SOC_TEGRA_SPDIF
+config SND_SOC_TEGRA20_SPDIF
tristate
- depends on SND_SOC_TEGRA
+ depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
default m
help
- Say Y or M if you want to add support for the SPDIF interface.
+ Say Y or M if you want to add support for the Tegra20 SPDIF interface.
You will also need to select the individual machine drivers to support
below.
+config SND_SOC_TEGRA30_AHUB
+ tristate
+ depends on SND_SOC_TEGRA && ARCH_TEGRA_3x_SOC
+ help
+ Say Y or M if you want to add support for the Tegra20 AHUB module.
+ You will also need to select the individual machine drivers to
+ support below.
+
+config SND_SOC_TEGRA30_I2S
+ tristate
+ depends on SND_SOC_TEGRA && ARCH_TEGRA_3x_SOC
+ select SND_SOC_TEGRA30_AHUB
+ help
+ Say Y or M if you want to add support for codecs attached to the
+ Tegra30 I2S interface. You will also need to select the individual
+ machine drivers to support below.
+
+config SND_SOC_TEGRA_WM8753
+ tristate "SoC Audio support for Tegra boards using a WM8753 codec"
+ depends on SND_SOC_TEGRA && I2C
+ select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
+ select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
+ select SND_SOC_WM8753
+ help
+ Say Y or M here if you want to add support for SoC audio on Tegra
+ boards using the WM8753 codec, such as Whistler.
+
config MACH_HAS_SND_SOC_TEGRA_WM8903
bool
help
@@ -32,7 +69,8 @@ config SND_SOC_TEGRA_WM8903
tristate "SoC Audio support for Tegra boards using a WM8903 codec"
depends on SND_SOC_TEGRA && I2C
depends on MACH_HAS_SND_SOC_TEGRA_WM8903
- select SND_SOC_TEGRA_I2S
+ select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
+ select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
select SND_SOC_WM8903
help
Say Y or M here if you want to add support for SoC audio on Tegra
@@ -42,17 +80,17 @@ config SND_SOC_TEGRA_WM8903
config SND_SOC_TEGRA_TRIMSLICE
tristate "SoC Audio support for TrimSlice board"
depends on SND_SOC_TEGRA && MACH_TRIMSLICE && I2C
- select SND_SOC_TEGRA_I2S
+ select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
select SND_SOC_TLV320AIC23
help
Say Y or M here if you want to add support for SoC audio on the
TrimSlice platform.
config SND_SOC_TEGRA_ALC5632
- tristate "SoC Audio support for Tegra boards using an ALC5632 codec"
- depends on SND_SOC_TEGRA && I2C
- select SND_SOC_TEGRA_I2S
- select SND_SOC_ALC5632
- help
- Say Y or M here if you want to add support for SoC audio on the
- Toshiba AC100 netbook.
+ tristate "SoC Audio support for Tegra boards using an ALC5632 codec"
+ depends on SND_SOC_TEGRA && I2C
+ select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
+ select SND_SOC_ALC5632
+ help
+ Say Y or M here if you want to add support for SoC audio on the
+ Toshiba AC100 netbook.
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 8e584b8fcfba..391e78a34c06 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -1,21 +1,27 @@
# Tegra platform Support
-snd-soc-tegra-das-objs := tegra_das.o
snd-soc-tegra-pcm-objs := tegra_pcm.o
-snd-soc-tegra-i2s-objs := tegra_i2s.o
-snd-soc-tegra-spdif-objs := tegra_spdif.o
snd-soc-tegra-utils-objs += tegra_asoc_utils.o
+snd-soc-tegra20-das-objs := tegra20_das.o
+snd-soc-tegra20-i2s-objs := tegra20_i2s.o
+snd-soc-tegra20-spdif-objs := tegra20_spdif.o
+snd-soc-tegra30-ahub-objs := tegra30_ahub.o
+snd-soc-tegra30-i2s-objs := tegra30_i2s.o
-obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o
-obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-das.o
obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
-obj-$(CONFIG_SND_SOC_TEGRA_I2S) += snd-soc-tegra-i2s.o
-obj-$(CONFIG_SND_SOC_TEGRA_SPDIF) += snd-soc-tegra-spdif.o
+obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o
+obj-$(CONFIG_SND_SOC_TEGRA20_DAS) += snd-soc-tegra20-das.o
+obj-$(CONFIG_SND_SOC_TEGRA20_I2S) += snd-soc-tegra20-i2s.o
+obj-$(CONFIG_SND_SOC_TEGRA20_SPDIF) += snd-soc-tegra20-spdif.o
+obj-$(CONFIG_SND_SOC_TEGRA30_AHUB) += snd-soc-tegra30-ahub.o
+obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o
# Tegra machine Support
+snd-soc-tegra-wm8753-objs := tegra_wm8753.o
snd-soc-tegra-wm8903-objs := tegra_wm8903.o
snd-soc-tegra-trimslice-objs := trimslice.o
snd-soc-tegra-alc5632-objs := tegra_alc5632.o
+obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c
new file mode 100644
index 000000000000..bf99296bce95
--- /dev/null
+++ b/sound/soc/tegra/tegra20_das.c
@@ -0,0 +1,233 @@
+/*
+ * tegra20_das.c - Tegra20 DAS driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010 - NVIDIA, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include "tegra20_das.h"
+
+#define DRV_NAME "tegra20-das"
+
+static struct tegra20_das *das;
+
+static inline void tegra20_das_write(u32 reg, u32 val)
+{
+ regmap_write(das->regmap, reg, val);
+}
+
+static inline u32 tegra20_das_read(u32 reg)
+{
+ u32 val;
+ regmap_read(das->regmap, reg, &val);
+ return val;
+}
+
+int tegra20_das_connect_dap_to_dac(int dap, int dac)
+{
+ u32 addr;
+ u32 reg;
+
+ if (!das)
+ return -ENODEV;
+
+ addr = TEGRA20_DAS_DAP_CTRL_SEL +
+ (dap * TEGRA20_DAS_DAP_CTRL_SEL_STRIDE);
+ reg = dac << TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P;
+
+ tegra20_das_write(addr, reg);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra20_das_connect_dap_to_dac);
+
+int tegra20_das_connect_dap_to_dap(int dap, int otherdap, int master,
+ int sdata1rx, int sdata2rx)
+{
+ u32 addr;
+ u32 reg;
+
+ if (!das)
+ return -ENODEV;
+
+ addr = TEGRA20_DAS_DAP_CTRL_SEL +
+ (dap * TEGRA20_DAS_DAP_CTRL_SEL_STRIDE);
+ reg = otherdap << TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P |
+ !!sdata2rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P |
+ !!sdata1rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P |
+ !!master << TEGRA20_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P;
+
+ tegra20_das_write(addr, reg);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra20_das_connect_dap_to_dap);
+
+int tegra20_das_connect_dac_to_dap(int dac, int dap)
+{
+ u32 addr;
+ u32 reg;
+
+ if (!das)
+ return -ENODEV;
+
+ addr = TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL +
+ (dac * TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
+ reg = dap << TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P |
+ dap << TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P |
+ dap << TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P;
+
+ tegra20_das_write(addr, reg);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra20_das_connect_dac_to_dap);
+
+#define LAST_REG(name) \
+ (TEGRA20_DAS_##name + \
+ (TEGRA20_DAS_##name##_STRIDE * (TEGRA20_DAS_##name##_COUNT - 1)))
+
+static bool tegra20_das_wr_rd_reg(struct device *dev, unsigned int reg)
+{
+ if ((reg >= TEGRA20_DAS_DAP_CTRL_SEL) &&
+ (reg <= LAST_REG(DAP_CTRL_SEL)))
+ return true;
+ if ((reg >= TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL) &&
+ (reg <= LAST_REG(DAC_INPUT_DATA_CLK_SEL)))
+ return true;
+
+ return false;
+}
+
+static const struct regmap_config tegra20_das_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = LAST_REG(DAC_INPUT_DATA_CLK_SEL),
+ .writeable_reg = tegra20_das_wr_rd_reg,
+ .readable_reg = tegra20_das_wr_rd_reg,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit tegra20_das_probe(struct platform_device *pdev)
+{
+ struct resource *res, *region;
+ void __iomem *regs;
+ int ret = 0;
+
+ if (das)
+ return -ENODEV;
+
+ das = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_das), GFP_KERNEL);
+ if (!das) {
+ dev_err(&pdev->dev, "Can't allocate tegra20_das\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ das->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "No memory resource\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ region = devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), pdev->name);
+ if (!region) {
+ dev_err(&pdev->dev, "Memory region already claimed\n");
+ ret = -EBUSY;
+ goto err;
+ }
+
+ regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!regs) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ das->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
+ &tegra20_das_regmap_config);
+ if (IS_ERR(das->regmap)) {
+ dev_err(&pdev->dev, "regmap init failed\n");
+ ret = PTR_ERR(das->regmap);
+ goto err;
+ }
+
+ ret = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_1,
+ TEGRA20_DAS_DAP_SEL_DAC1);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't set up DAS DAP connection\n");
+ goto err;
+ }
+ ret = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAC_ID_1,
+ TEGRA20_DAS_DAC_SEL_DAP1);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't set up DAS DAC connection\n");
+ goto err;
+ }
+
+ platform_set_drvdata(pdev, das);
+
+ return 0;
+
+err:
+ das = NULL;
+ return ret;
+}
+
+static int __devexit tegra20_das_remove(struct platform_device *pdev)
+{
+ if (!das)
+ return -ENODEV;
+
+ das = NULL;
+
+ return 0;
+}
+
+static const struct of_device_id tegra20_das_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra20-das", },
+ {},
+};
+
+static struct platform_driver tegra20_das_driver = {
+ .probe = tegra20_das_probe,
+ .remove = __devexit_p(tegra20_das_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = tegra20_das_of_match,
+ },
+};
+module_platform_driver(tegra20_das_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra20 DAS driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra20_das_of_match);
diff --git a/sound/soc/tegra/tegra20_das.h b/sound/soc/tegra/tegra20_das.h
new file mode 100644
index 000000000000..be217f3d3a75
--- /dev/null
+++ b/sound/soc/tegra/tegra20_das.h
@@ -0,0 +1,134 @@
+/*
+ * tegra20_das.h - Definitions for Tegra20 DAS driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010,2012 - NVIDIA, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __TEGRA20_DAS_H__
+#define __TEGRA20_DAS_H__
+
+/* Register TEGRA20_DAS_DAP_CTRL_SEL */
+#define TEGRA20_DAS_DAP_CTRL_SEL 0x00
+#define TEGRA20_DAS_DAP_CTRL_SEL_COUNT 5
+#define TEGRA20_DAS_DAP_CTRL_SEL_STRIDE 4
+#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P 31
+#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_MS_SEL_S 1
+#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P 30
+#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_S 1
+#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P 29
+#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_S 1
+#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P 0
+#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_S 5
+
+/* Values for field TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL */
+#define TEGRA20_DAS_DAP_SEL_DAC1 0
+#define TEGRA20_DAS_DAP_SEL_DAC2 1
+#define TEGRA20_DAS_DAP_SEL_DAC3 2
+#define TEGRA20_DAS_DAP_SEL_DAP1 16
+#define TEGRA20_DAS_DAP_SEL_DAP2 17
+#define TEGRA20_DAS_DAP_SEL_DAP3 18
+#define TEGRA20_DAS_DAP_SEL_DAP4 19
+#define TEGRA20_DAS_DAP_SEL_DAP5 20
+
+/* Register TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL */
+#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL 0x40
+#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_COUNT 3
+#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE 4
+#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P 28
+#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_S 4
+#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P 24
+#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_S 4
+#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P 0
+#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_S 4
+
+/*
+ * Values for:
+ * TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL
+ * TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL
+ * TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL
+ */
+#define TEGRA20_DAS_DAC_SEL_DAP1 0
+#define TEGRA20_DAS_DAC_SEL_DAP2 1
+#define TEGRA20_DAS_DAC_SEL_DAP3 2
+#define TEGRA20_DAS_DAC_SEL_DAP4 3
+#define TEGRA20_DAS_DAC_SEL_DAP5 4
+
+/*
+ * Names/IDs of the DACs/DAPs.
+ */
+
+#define TEGRA20_DAS_DAP_ID_1 0
+#define TEGRA20_DAS_DAP_ID_2 1
+#define TEGRA20_DAS_DAP_ID_3 2
+#define TEGRA20_DAS_DAP_ID_4 3
+#define TEGRA20_DAS_DAP_ID_5 4
+
+#define TEGRA20_DAS_DAC_ID_1 0
+#define TEGRA20_DAS_DAC_ID_2 1
+#define TEGRA20_DAS_DAC_ID_3 2
+
+struct tegra20_das {
+ struct device *dev;
+ struct regmap *regmap;
+};
+
+/*
+ * Terminology:
+ * DAS: Digital audio switch (HW module controlled by this driver)
+ * DAP: Digital audio port (port/pins on Tegra device)
+ * DAC: Digital audio controller (e.g. I2S or AC97 controller elsewhere)
+ *
+ * The Tegra DAS is a mux/cross-bar which can connect each DAP to a specific
+ * DAC, or another DAP. When DAPs are connected, one must be the master and
+ * one the slave. Each DAC allows selection of a specific DAP for input, to
+ * cater for the case where N DAPs are connected to 1 DAC for broadcast
+ * output.
+ *
+ * This driver is dumb; no attempt is made to ensure that a valid routing
+ * configuration is programmed.
+ */
+
+/*
+ * Connect a DAP to to a DAC
+ * dap_id: DAP to connect: TEGRA20_DAS_DAP_ID_*
+ * dac_sel: DAC to connect to: TEGRA20_DAS_DAP_SEL_DAC*
+ */
+extern int tegra20_das_connect_dap_to_dac(int dap_id, int dac_sel);
+
+/*
+ * Connect a DAP to to another DAP
+ * dap_id: DAP to connect: TEGRA20_DAS_DAP_ID_*
+ * other_dap_sel: DAP to connect to: TEGRA20_DAS_DAP_SEL_DAP*
+ * master: Is this DAP the master (1) or slave (0)
+ * sdata1rx: Is this DAP's SDATA1 pin RX (1) or TX (0)
+ * sdata2rx: Is this DAP's SDATA2 pin RX (1) or TX (0)
+ */
+extern int tegra20_das_connect_dap_to_dap(int dap_id, int other_dap_sel,
+ int master, int sdata1rx,
+ int sdata2rx);
+
+/*
+ * Connect a DAC's input to a DAP
+ * (DAC outputs are selected by the DAP)
+ * dac_id: DAC ID to connect: TEGRA20_DAS_DAC_ID_*
+ * dap_sel: DAP to receive input from: TEGRA20_DAS_DAC_SEL_DAP*
+ */
+extern int tegra20_das_connect_dac_to_dap(int dac_id, int dap_sel);
+
+#endif
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
new file mode 100644
index 000000000000..0c7af63d444b
--- /dev/null
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -0,0 +1,494 @@
+/*
+ * tegra20_i2s.c - Tegra20 I2S driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010,2012 - NVIDIA, Inc.
+ *
+ * Based on code copyright/by:
+ *
+ * Copyright (c) 2009-2010, NVIDIA Corporation.
+ * Scott Peterson <speterson@nvidia.com>
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Iliyan Malchev <malchev@google.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra20_i2s.h"
+
+#define DRV_NAME "tegra20-i2s"
+
+static inline void tegra20_i2s_write(struct tegra20_i2s *i2s, u32 reg, u32 val)
+{
+ regmap_write(i2s->regmap, reg, val);
+}
+
+static inline u32 tegra20_i2s_read(struct tegra20_i2s *i2s, u32 reg)
+{
+ u32 val;
+ regmap_read(i2s->regmap, reg, &val);
+ return val;
+}
+
+static int tegra20_i2s_runtime_suspend(struct device *dev)
+{
+ struct tegra20_i2s *i2s = dev_get_drvdata(dev);
+
+ clk_disable(i2s->clk_i2s);
+
+ return 0;
+}
+
+static int tegra20_i2s_runtime_resume(struct device *dev)
+{
+ struct tegra20_i2s *i2s = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_enable(i2s->clk_i2s);
+ if (ret) {
+ dev_err(dev, "clk_enable failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
+ unsigned int fmt)
+{
+ struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_MASTER_ENABLE;
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ i2s->reg_ctrl &= ~(TEGRA20_I2S_CTRL_BIT_FORMAT_MASK |
+ TEGRA20_I2S_CTRL_LRCK_MASK);
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_R_LOW;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S;
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM;
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM;
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct device *dev = substream->pcm->card->dev;
+ struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+ u32 reg;
+ int ret, sample_size, srate, i2sclock, bitcnt;
+
+ i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_BIT_SIZE_MASK;
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_16;
+ sample_size = 16;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_24;
+ sample_size = 24;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_32;
+ sample_size = 32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ srate = params_rate(params);
+
+ /* Final "* 2" required by Tegra hardware */
+ i2sclock = srate * params_channels(params) * sample_size * 2;
+
+ ret = clk_set_rate(i2s->clk_i2s, i2sclock);
+ if (ret) {
+ dev_err(dev, "Can't set I2S clock rate: %d\n", ret);
+ return ret;
+ }
+
+ bitcnt = (i2sclock / (2 * srate)) - 1;
+ if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US)
+ return -EINVAL;
+ reg = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
+
+ if (i2sclock % (2 * srate))
+ reg |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE;
+
+ tegra20_i2s_write(i2s, TEGRA20_I2S_TIMING, reg);
+
+ tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR,
+ TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
+ TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
+
+ return 0;
+}
+
+static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s)
+{
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO1_ENABLE;
+ tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
+}
+
+static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s)
+{
+ i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO1_ENABLE;
+ tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
+}
+
+static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s)
+{
+ i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO2_ENABLE;
+ tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
+}
+
+static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s)
+{
+ i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO2_ENABLE;
+ tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
+}
+
+static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tegra20_i2s_start_playback(i2s);
+ else
+ tegra20_i2s_start_capture(i2s);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tegra20_i2s_stop_playback(i2s);
+ else
+ tegra20_i2s_stop_capture(i2s);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tegra20_i2s_probe(struct snd_soc_dai *dai)
+{
+ struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+ dai->capture_dma_data = &i2s->capture_dma_data;
+ dai->playback_dma_data = &i2s->playback_dma_data;
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = {
+ .set_fmt = tegra20_i2s_set_fmt,
+ .hw_params = tegra20_i2s_hw_params,
+ .trigger = tegra20_i2s_trigger,
+};
+
+static const struct snd_soc_dai_driver tegra20_i2s_dai_template = {
+ .probe = tegra20_i2s_probe,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .ops = &tegra20_i2s_dai_ops,
+ .symmetric_rates = 1,
+};
+
+static bool tegra20_i2s_wr_rd_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA20_I2S_CTRL:
+ case TEGRA20_I2S_STATUS:
+ case TEGRA20_I2S_TIMING:
+ case TEGRA20_I2S_FIFO_SCR:
+ case TEGRA20_I2S_PCM_CTRL:
+ case TEGRA20_I2S_NW_CTRL:
+ case TEGRA20_I2S_TDM_CTRL:
+ case TEGRA20_I2S_TDM_TX_RX_CTRL:
+ case TEGRA20_I2S_FIFO1:
+ case TEGRA20_I2S_FIFO2:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static bool tegra20_i2s_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA20_I2S_STATUS:
+ case TEGRA20_I2S_FIFO_SCR:
+ case TEGRA20_I2S_FIFO1:
+ case TEGRA20_I2S_FIFO2:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static bool tegra20_i2s_precious_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA20_I2S_FIFO1:
+ case TEGRA20_I2S_FIFO2:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static const struct regmap_config tegra20_i2s_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = TEGRA20_I2S_FIFO2,
+ .writeable_reg = tegra20_i2s_wr_rd_reg,
+ .readable_reg = tegra20_i2s_wr_rd_reg,
+ .volatile_reg = tegra20_i2s_volatile_reg,
+ .precious_reg = tegra20_i2s_precious_reg,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev)
+{
+ struct tegra20_i2s *i2s;
+ struct resource *mem, *memregion, *dmareq;
+ u32 of_dma[2];
+ u32 dma_ch;
+ void __iomem *regs;
+ int ret;
+
+ i2s = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_i2s), GFP_KERNEL);
+ if (!i2s) {
+ dev_err(&pdev->dev, "Can't allocate tegra20_i2s\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ dev_set_drvdata(&pdev->dev, i2s);
+
+ i2s->dai = tegra20_i2s_dai_template;
+ i2s->dai.name = dev_name(&pdev->dev);
+
+ i2s->clk_i2s = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(i2s->clk_i2s)) {
+ dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
+ ret = PTR_ERR(i2s->clk_i2s);
+ goto err;
+ }
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "No memory resource\n");
+ ret = -ENODEV;
+ goto err_clk_put;
+ }
+
+ dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!dmareq) {
+ if (of_property_read_u32_array(pdev->dev.of_node,
+ "nvidia,dma-request-selector",
+ of_dma, 2) < 0) {
+ dev_err(&pdev->dev, "No DMA resource\n");
+ ret = -ENODEV;
+ goto err_clk_put;
+ }
+ dma_ch = of_dma[1];
+ } else {
+ dma_ch = dmareq->start;
+ }
+
+ memregion = devm_request_mem_region(&pdev->dev, mem->start,
+ resource_size(mem), DRV_NAME);
+ if (!memregion) {
+ dev_err(&pdev->dev, "Memory region already claimed\n");
+ ret = -EBUSY;
+ goto err_clk_put;
+ }
+
+ regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+ if (!regs) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto err_clk_put;
+ }
+
+ i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
+ &tegra20_i2s_regmap_config);
+ if (IS_ERR(i2s->regmap)) {
+ dev_err(&pdev->dev, "regmap init failed\n");
+ ret = PTR_ERR(i2s->regmap);
+ goto err_clk_put;
+ }
+
+ i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2;
+ i2s->capture_dma_data.wrap = 4;
+ i2s->capture_dma_data.width = 32;
+ i2s->capture_dma_data.req_sel = dma_ch;
+
+ i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1;
+ i2s->playback_dma_data.wrap = 4;
+ i2s->playback_dma_data.width = 32;
+ i2s->playback_dma_data.req_sel = dma_ch;
+
+ i2s->reg_ctrl = TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED;
+
+ pm_runtime_enable(&pdev->dev);
+ if (!pm_runtime_enabled(&pdev->dev)) {
+ ret = tegra20_i2s_runtime_resume(&pdev->dev);
+ if (ret)
+ goto err_pm_disable;
+ }
+
+ ret = snd_soc_register_dai(&pdev->dev, &i2s->dai);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
+ ret = -ENOMEM;
+ goto err_suspend;
+ }
+
+ ret = tegra_pcm_platform_register(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
+ goto err_unregister_dai;
+ }
+
+ return 0;
+
+err_unregister_dai:
+ snd_soc_unregister_dai(&pdev->dev);
+err_suspend:
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ tegra20_i2s_runtime_suspend(&pdev->dev);
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+err_clk_put:
+ clk_put(i2s->clk_i2s);
+err:
+ return ret;
+}
+
+static int __devexit tegra20_i2s_platform_remove(struct platform_device *pdev)
+{
+ struct tegra20_i2s *i2s = dev_get_drvdata(&pdev->dev);
+
+ pm_runtime_disable(&pdev->dev);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ tegra20_i2s_runtime_suspend(&pdev->dev);
+
+ tegra_pcm_platform_unregister(&pdev->dev);
+ snd_soc_unregister_dai(&pdev->dev);
+
+ clk_put(i2s->clk_i2s);
+
+ return 0;
+}
+
+static const struct of_device_id tegra20_i2s_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra20-i2s", },
+ {},
+};
+
+static const struct dev_pm_ops tegra20_i2s_pm_ops __devinitconst = {
+ SET_RUNTIME_PM_OPS(tegra20_i2s_runtime_suspend,
+ tegra20_i2s_runtime_resume, NULL)
+};
+
+static struct platform_driver tegra20_i2s_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = tegra20_i2s_of_match,
+ .pm = &tegra20_i2s_pm_ops,
+ },
+ .probe = tegra20_i2s_platform_probe,
+ .remove = __devexit_p(tegra20_i2s_platform_remove),
+};
+module_platform_driver(tegra20_i2s_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra20 I2S ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra20_i2s_of_match);
diff --git a/sound/soc/tegra/tegra20_i2s.h b/sound/soc/tegra/tegra20_i2s.h
new file mode 100644
index 000000000000..a57efc6a597e
--- /dev/null
+++ b/sound/soc/tegra/tegra20_i2s.h
@@ -0,0 +1,164 @@
+/*
+ * tegra20_i2s.h - Definitions for Tegra20 I2S driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010,2012 - NVIDIA, Inc.
+ *
+ * Based on code copyright/by:
+ *
+ * Copyright (c) 2009-2010, NVIDIA Corporation.
+ * Scott Peterson <speterson@nvidia.com>
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Iliyan Malchev <malchev@google.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __TEGRA20_I2S_H__
+#define __TEGRA20_I2S_H__
+
+#include "tegra_pcm.h"
+
+/* Register offsets from TEGRA20_I2S1_BASE and TEGRA20_I2S2_BASE */
+
+#define TEGRA20_I2S_CTRL 0x00
+#define TEGRA20_I2S_STATUS 0x04
+#define TEGRA20_I2S_TIMING 0x08
+#define TEGRA20_I2S_FIFO_SCR 0x0c
+#define TEGRA20_I2S_PCM_CTRL 0x10
+#define TEGRA20_I2S_NW_CTRL 0x14
+#define TEGRA20_I2S_TDM_CTRL 0x20
+#define TEGRA20_I2S_TDM_TX_RX_CTRL 0x24
+#define TEGRA20_I2S_FIFO1 0x40
+#define TEGRA20_I2S_FIFO2 0x80
+
+/* Fields in TEGRA20_I2S_CTRL */
+
+#define TEGRA20_I2S_CTRL_FIFO2_TX_ENABLE (1 << 30)
+#define TEGRA20_I2S_CTRL_FIFO1_ENABLE (1 << 29)
+#define TEGRA20_I2S_CTRL_FIFO2_ENABLE (1 << 28)
+#define TEGRA20_I2S_CTRL_FIFO1_RX_ENABLE (1 << 27)
+#define TEGRA20_I2S_CTRL_FIFO_LPBK_ENABLE (1 << 26)
+#define TEGRA20_I2S_CTRL_MASTER_ENABLE (1 << 25)
+
+#define TEGRA20_I2S_LRCK_LEFT_LOW 0
+#define TEGRA20_I2S_LRCK_RIGHT_LOW 1
+
+#define TEGRA20_I2S_CTRL_LRCK_SHIFT 24
+#define TEGRA20_I2S_CTRL_LRCK_MASK (1 << TEGRA20_I2S_CTRL_LRCK_SHIFT)
+#define TEGRA20_I2S_CTRL_LRCK_L_LOW (TEGRA20_I2S_LRCK_LEFT_LOW << TEGRA20_I2S_CTRL_LRCK_SHIFT)
+#define TEGRA20_I2S_CTRL_LRCK_R_LOW (TEGRA20_I2S_LRCK_RIGHT_LOW << TEGRA20_I2S_CTRL_LRCK_SHIFT)
+
+#define TEGRA20_I2S_BIT_FORMAT_I2S 0
+#define TEGRA20_I2S_BIT_FORMAT_RJM 1
+#define TEGRA20_I2S_BIT_FORMAT_LJM 2
+#define TEGRA20_I2S_BIT_FORMAT_DSP 3
+
+#define TEGRA20_I2S_CTRL_BIT_FORMAT_SHIFT 10
+#define TEGRA20_I2S_CTRL_BIT_FORMAT_MASK (3 << TEGRA20_I2S_CTRL_BIT_FORMAT_SHIFT)
+#define TEGRA20_I2S_CTRL_BIT_FORMAT_I2S (TEGRA20_I2S_BIT_FORMAT_I2S << TEGRA20_I2S_CTRL_BIT_FORMAT_SHIFT)
+#define TEGRA20_I2S_CTRL_BIT_FORMAT_RJM (TEGRA20_I2S_BIT_FORMAT_RJM << TEGRA20_I2S_CTRL_BIT_FORMAT_SHIFT)
+#define TEGRA20_I2S_CTRL_BIT_FORMAT_LJM (TEGRA20_I2S_BIT_FORMAT_LJM << TEGRA20_I2S_CTRL_BIT_FORMAT_SHIFT)
+#define TEGRA20_I2S_CTRL_BIT_FORMAT_DSP (TEGRA20_I2S_BIT_FORMAT_DSP << TEGRA20_I2S_CTRL_BIT_FORMAT_SHIFT)
+
+#define TEGRA20_I2S_BIT_SIZE_16 0
+#define TEGRA20_I2S_BIT_SIZE_20 1
+#define TEGRA20_I2S_BIT_SIZE_24 2
+#define TEGRA20_I2S_BIT_SIZE_32 3
+
+#define TEGRA20_I2S_CTRL_BIT_SIZE_SHIFT 8
+#define TEGRA20_I2S_CTRL_BIT_SIZE_MASK (3 << TEGRA20_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA20_I2S_CTRL_BIT_SIZE_16 (TEGRA20_I2S_BIT_SIZE_16 << TEGRA20_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA20_I2S_CTRL_BIT_SIZE_20 (TEGRA20_I2S_BIT_SIZE_20 << TEGRA20_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA20_I2S_CTRL_BIT_SIZE_24 (TEGRA20_I2S_BIT_SIZE_24 << TEGRA20_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA20_I2S_CTRL_BIT_SIZE_32 (TEGRA20_I2S_BIT_SIZE_32 << TEGRA20_I2S_CTRL_BIT_SIZE_SHIFT)
+
+#define TEGRA20_I2S_FIFO_16_LSB 0
+#define TEGRA20_I2S_FIFO_20_LSB 1
+#define TEGRA20_I2S_FIFO_24_LSB 2
+#define TEGRA20_I2S_FIFO_32 3
+#define TEGRA20_I2S_FIFO_PACKED 7
+
+#define TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT 4
+#define TEGRA20_I2S_CTRL_FIFO_FORMAT_MASK (7 << TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT)
+#define TEGRA20_I2S_CTRL_FIFO_FORMAT_16_LSB (TEGRA20_I2S_FIFO_16_LSB << TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT)
+#define TEGRA20_I2S_CTRL_FIFO_FORMAT_20_LSB (TEGRA20_I2S_FIFO_20_LSB << TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT)
+#define TEGRA20_I2S_CTRL_FIFO_FORMAT_24_LSB (TEGRA20_I2S_FIFO_24_LSB << TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT)
+#define TEGRA20_I2S_CTRL_FIFO_FORMAT_32 (TEGRA20_I2S_FIFO_32 << TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT)
+#define TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED (TEGRA20_I2S_FIFO_PACKED << TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT)
+
+#define TEGRA20_I2S_CTRL_IE_FIFO1_ERR (1 << 3)
+#define TEGRA20_I2S_CTRL_IE_FIFO2_ERR (1 << 2)
+#define TEGRA20_I2S_CTRL_QE_FIFO1 (1 << 1)
+#define TEGRA20_I2S_CTRL_QE_FIFO2 (1 << 0)
+
+/* Fields in TEGRA20_I2S_STATUS */
+
+#define TEGRA20_I2S_STATUS_FIFO1_RDY (1 << 31)
+#define TEGRA20_I2S_STATUS_FIFO2_RDY (1 << 30)
+#define TEGRA20_I2S_STATUS_FIFO1_BSY (1 << 29)
+#define TEGRA20_I2S_STATUS_FIFO2_BSY (1 << 28)
+#define TEGRA20_I2S_STATUS_FIFO1_ERR (1 << 3)
+#define TEGRA20_I2S_STATUS_FIFO2_ERR (1 << 2)
+#define TEGRA20_I2S_STATUS_QS_FIFO1 (1 << 1)
+#define TEGRA20_I2S_STATUS_QS_FIFO2 (1 << 0)
+
+/* Fields in TEGRA20_I2S_TIMING */
+
+#define TEGRA20_I2S_TIMING_NON_SYM_ENABLE (1 << 12)
+#define TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT 0
+#define TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US 0x7fff
+#define TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK (TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT)
+
+/* Fields in TEGRA20_I2S_FIFO_SCR */
+
+#define TEGRA20_I2S_FIFO_SCR_FIFO2_FULL_EMPTY_COUNT_SHIFT 24
+#define TEGRA20_I2S_FIFO_SCR_FIFO1_FULL_EMPTY_COUNT_SHIFT 16
+#define TEGRA20_I2S_FIFO_SCR_FIFO_FULL_EMPTY_COUNT_MASK 0x3f
+
+#define TEGRA20_I2S_FIFO_SCR_FIFO2_CLR (1 << 12)
+#define TEGRA20_I2S_FIFO_SCR_FIFO1_CLR (1 << 8)
+
+#define TEGRA20_I2S_FIFO_ATN_LVL_ONE_SLOT 0
+#define TEGRA20_I2S_FIFO_ATN_LVL_FOUR_SLOTS 1
+#define TEGRA20_I2S_FIFO_ATN_LVL_EIGHT_SLOTS 2
+#define TEGRA20_I2S_FIFO_ATN_LVL_TWELVE_SLOTS 3
+
+#define TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT 4
+#define TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_MASK (3 << TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
+#define TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_ONE_SLOT (TEGRA20_I2S_FIFO_ATN_LVL_ONE_SLOT << TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
+#define TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS (TEGRA20_I2S_FIFO_ATN_LVL_FOUR_SLOTS << TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
+#define TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_EIGHT_SLOTS (TEGRA20_I2S_FIFO_ATN_LVL_EIGHT_SLOTS << TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
+#define TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_TWELVE_SLOTS (TEGRA20_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
+
+#define TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT 0
+#define TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_MASK (3 << TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
+#define TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_ONE_SLOT (TEGRA20_I2S_FIFO_ATN_LVL_ONE_SLOT << TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
+#define TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS (TEGRA20_I2S_FIFO_ATN_LVL_FOUR_SLOTS << TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
+#define TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_EIGHT_SLOTS (TEGRA20_I2S_FIFO_ATN_LVL_EIGHT_SLOTS << TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
+#define TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_TWELVE_SLOTS (TEGRA20_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
+
+struct tegra20_i2s {
+ struct snd_soc_dai_driver dai;
+ struct clk *clk_i2s;
+ struct tegra_pcm_dma_params capture_dma_data;
+ struct tegra_pcm_dma_params playback_dma_data;
+ struct regmap *regmap;
+ u32 reg_ctrl;
+};
+
+#endif
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
new file mode 100644
index 000000000000..f9b57418bd08
--- /dev/null
+++ b/sound/soc/tegra/tegra20_spdif.c
@@ -0,0 +1,404 @@
+/*
+ * tegra20_spdif.c - Tegra20 SPDIF driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2011-2012 - NVIDIA, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra20_spdif.h"
+
+#define DRV_NAME "tegra20-spdif"
+
+static inline void tegra20_spdif_write(struct tegra20_spdif *spdif, u32 reg,
+ u32 val)
+{
+ regmap_write(spdif->regmap, reg, val);
+}
+
+static inline u32 tegra20_spdif_read(struct tegra20_spdif *spdif, u32 reg)
+{
+ u32 val;
+ regmap_read(spdif->regmap, reg, &val);
+ return val;
+}
+
+static int tegra20_spdif_runtime_suspend(struct device *dev)
+{
+ struct tegra20_spdif *spdif = dev_get_drvdata(dev);
+
+ clk_disable(spdif->clk_spdif_out);
+
+ return 0;
+}
+
+static int tegra20_spdif_runtime_resume(struct device *dev)
+{
+ struct tegra20_spdif *spdif = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_enable(spdif->clk_spdif_out);
+ if (ret) {
+ dev_err(dev, "clk_enable failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct device *dev = substream->pcm->card->dev;
+ struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+ int ret, spdifclock;
+
+ spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_PACK;
+ spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_PACK;
+ spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (params_rate(params)) {
+ case 32000:
+ spdifclock = 4096000;
+ break;
+ case 44100:
+ spdifclock = 5644800;
+ break;
+ case 48000:
+ spdifclock = 6144000;
+ break;
+ case 88200:
+ spdifclock = 11289600;
+ break;
+ case 96000:
+ spdifclock = 12288000;
+ break;
+ case 176400:
+ spdifclock = 22579200;
+ break;
+ case 192000:
+ spdifclock = 24576000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = clk_set_rate(spdif->clk_spdif_out, spdifclock);
+ if (ret) {
+ dev_err(dev, "Can't set SPDIF clock rate: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void tegra20_spdif_start_playback(struct tegra20_spdif *spdif)
+{
+ spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_TX_EN;
+ tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl);
+}
+
+static void tegra20_spdif_stop_playback(struct tegra20_spdif *spdif)
+{
+ spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_TX_EN;
+ tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl);
+}
+
+static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ tegra20_spdif_start_playback(spdif);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ tegra20_spdif_stop_playback(spdif);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tegra20_spdif_probe(struct snd_soc_dai *dai)
+{
+ struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+
+ dai->capture_dma_data = NULL;
+ dai->playback_dma_data = &spdif->playback_dma_data;
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops tegra20_spdif_dai_ops = {
+ .hw_params = tegra20_spdif_hw_params,
+ .trigger = tegra20_spdif_trigger,
+};
+
+static struct snd_soc_dai_driver tegra20_spdif_dai = {
+ .name = DRV_NAME,
+ .probe = tegra20_spdif_probe,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .ops = &tegra20_spdif_dai_ops,
+};
+
+static bool tegra20_spdif_wr_rd_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA20_SPDIF_CTRL:
+ case TEGRA20_SPDIF_STATUS:
+ case TEGRA20_SPDIF_STROBE_CTRL:
+ case TEGRA20_SPDIF_DATA_FIFO_CSR:
+ case TEGRA20_SPDIF_DATA_OUT:
+ case TEGRA20_SPDIF_DATA_IN:
+ case TEGRA20_SPDIF_CH_STA_RX_A:
+ case TEGRA20_SPDIF_CH_STA_RX_B:
+ case TEGRA20_SPDIF_CH_STA_RX_C:
+ case TEGRA20_SPDIF_CH_STA_RX_D:
+ case TEGRA20_SPDIF_CH_STA_RX_E:
+ case TEGRA20_SPDIF_CH_STA_RX_F:
+ case TEGRA20_SPDIF_CH_STA_TX_A:
+ case TEGRA20_SPDIF_CH_STA_TX_B:
+ case TEGRA20_SPDIF_CH_STA_TX_C:
+ case TEGRA20_SPDIF_CH_STA_TX_D:
+ case TEGRA20_SPDIF_CH_STA_TX_E:
+ case TEGRA20_SPDIF_CH_STA_TX_F:
+ case TEGRA20_SPDIF_USR_STA_RX_A:
+ case TEGRA20_SPDIF_USR_DAT_TX_A:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static bool tegra20_spdif_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA20_SPDIF_STATUS:
+ case TEGRA20_SPDIF_DATA_FIFO_CSR:
+ case TEGRA20_SPDIF_DATA_OUT:
+ case TEGRA20_SPDIF_DATA_IN:
+ case TEGRA20_SPDIF_CH_STA_RX_A:
+ case TEGRA20_SPDIF_CH_STA_RX_B:
+ case TEGRA20_SPDIF_CH_STA_RX_C:
+ case TEGRA20_SPDIF_CH_STA_RX_D:
+ case TEGRA20_SPDIF_CH_STA_RX_E:
+ case TEGRA20_SPDIF_CH_STA_RX_F:
+ case TEGRA20_SPDIF_USR_STA_RX_A:
+ case TEGRA20_SPDIF_USR_DAT_TX_A:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static bool tegra20_spdif_precious_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA20_SPDIF_DATA_OUT:
+ case TEGRA20_SPDIF_DATA_IN:
+ case TEGRA20_SPDIF_USR_STA_RX_A:
+ case TEGRA20_SPDIF_USR_DAT_TX_A:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static const struct regmap_config tegra20_spdif_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = TEGRA20_SPDIF_USR_DAT_TX_A,
+ .writeable_reg = tegra20_spdif_wr_rd_reg,
+ .readable_reg = tegra20_spdif_wr_rd_reg,
+ .volatile_reg = tegra20_spdif_volatile_reg,
+ .precious_reg = tegra20_spdif_precious_reg,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static __devinit int tegra20_spdif_platform_probe(struct platform_device *pdev)
+{
+ struct tegra20_spdif *spdif;
+ struct resource *mem, *memregion, *dmareq;
+ void __iomem *regs;
+ int ret;
+
+ spdif = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_spdif),
+ GFP_KERNEL);
+ if (!spdif) {
+ dev_err(&pdev->dev, "Can't allocate tegra20_spdif\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ dev_set_drvdata(&pdev->dev, spdif);
+
+ spdif->clk_spdif_out = clk_get(&pdev->dev, "spdif_out");
+ if (IS_ERR(spdif->clk_spdif_out)) {
+ pr_err("Can't retrieve spdif clock\n");
+ ret = PTR_ERR(spdif->clk_spdif_out);
+ goto err;
+ }
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "No memory resource\n");
+ ret = -ENODEV;
+ goto err_clk_put;
+ }
+
+ dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!dmareq) {
+ dev_err(&pdev->dev, "No DMA resource\n");
+ ret = -ENODEV;
+ goto err_clk_put;
+ }
+
+ memregion = devm_request_mem_region(&pdev->dev, mem->start,
+ resource_size(mem), DRV_NAME);
+ if (!memregion) {
+ dev_err(&pdev->dev, "Memory region already claimed\n");
+ ret = -EBUSY;
+ goto err_clk_put;
+ }
+
+ regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+ if (!regs) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto err_clk_put;
+ }
+
+ spdif->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
+ &tegra20_spdif_regmap_config);
+ if (IS_ERR(spdif->regmap)) {
+ dev_err(&pdev->dev, "regmap init failed\n");
+ ret = PTR_ERR(spdif->regmap);
+ goto err_clk_put;
+ }
+
+ spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT;
+ spdif->playback_dma_data.wrap = 4;
+ spdif->playback_dma_data.width = 32;
+ spdif->playback_dma_data.req_sel = dmareq->start;
+
+ pm_runtime_enable(&pdev->dev);
+ if (!pm_runtime_enabled(&pdev->dev)) {
+ ret = tegra20_spdif_runtime_resume(&pdev->dev);
+ if (ret)
+ goto err_pm_disable;
+ }
+
+ ret = snd_soc_register_dai(&pdev->dev, &tegra20_spdif_dai);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
+ ret = -ENOMEM;
+ goto err_suspend;
+ }
+
+ ret = tegra_pcm_platform_register(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
+ goto err_unregister_dai;
+ }
+
+ return 0;
+
+err_unregister_dai:
+ snd_soc_unregister_dai(&pdev->dev);
+err_suspend:
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ tegra20_spdif_runtime_suspend(&pdev->dev);
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+err_clk_put:
+ clk_put(spdif->clk_spdif_out);
+err:
+ return ret;
+}
+
+static int __devexit tegra20_spdif_platform_remove(struct platform_device *pdev)
+{
+ struct tegra20_spdif *spdif = dev_get_drvdata(&pdev->dev);
+
+ pm_runtime_disable(&pdev->dev);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ tegra20_spdif_runtime_suspend(&pdev->dev);
+
+ tegra_pcm_platform_unregister(&pdev->dev);
+ snd_soc_unregister_dai(&pdev->dev);
+
+ clk_put(spdif->clk_spdif_out);
+
+ return 0;
+}
+
+static const struct dev_pm_ops tegra20_spdif_pm_ops __devinitconst = {
+ SET_RUNTIME_PM_OPS(tegra20_spdif_runtime_suspend,
+ tegra20_spdif_runtime_resume, NULL)
+};
+
+static struct platform_driver tegra20_spdif_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &tegra20_spdif_pm_ops,
+ },
+ .probe = tegra20_spdif_platform_probe,
+ .remove = __devexit_p(tegra20_spdif_platform_remove),
+};
+
+module_platform_driver(tegra20_spdif_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra20 SPDIF ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra20_spdif.h b/sound/soc/tegra/tegra20_spdif.h
new file mode 100644
index 000000000000..ed756527efea
--- /dev/null
+++ b/sound/soc/tegra/tegra20_spdif.h
@@ -0,0 +1,471 @@
+/*
+ * tegra20_spdif.h - Definitions for Tegra20 SPDIF driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2011 - NVIDIA, Inc.
+ *
+ * Based on code copyright/by:
+ * Copyright (c) 2008-2009, NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __TEGRA20_SPDIF_H__
+#define __TEGRA20_SPDIF_H__
+
+#include "tegra_pcm.h"
+
+/* Offsets from TEGRA20_SPDIF_BASE */
+
+#define TEGRA20_SPDIF_CTRL 0x0
+#define TEGRA20_SPDIF_STATUS 0x4
+#define TEGRA20_SPDIF_STROBE_CTRL 0x8
+#define TEGRA20_SPDIF_DATA_FIFO_CSR 0x0C
+#define TEGRA20_SPDIF_DATA_OUT 0x40
+#define TEGRA20_SPDIF_DATA_IN 0x80
+#define TEGRA20_SPDIF_CH_STA_RX_A 0x100
+#define TEGRA20_SPDIF_CH_STA_RX_B 0x104
+#define TEGRA20_SPDIF_CH_STA_RX_C 0x108
+#define TEGRA20_SPDIF_CH_STA_RX_D 0x10C
+#define TEGRA20_SPDIF_CH_STA_RX_E 0x110
+#define TEGRA20_SPDIF_CH_STA_RX_F 0x114
+#define TEGRA20_SPDIF_CH_STA_TX_A 0x140
+#define TEGRA20_SPDIF_CH_STA_TX_B 0x144
+#define TEGRA20_SPDIF_CH_STA_TX_C 0x148
+#define TEGRA20_SPDIF_CH_STA_TX_D 0x14C
+#define TEGRA20_SPDIF_CH_STA_TX_E 0x150
+#define TEGRA20_SPDIF_CH_STA_TX_F 0x154
+#define TEGRA20_SPDIF_USR_STA_RX_A 0x180
+#define TEGRA20_SPDIF_USR_DAT_TX_A 0x1C0
+
+/* Fields in TEGRA20_SPDIF_CTRL */
+
+/* Start capturing from 0=right, 1=left channel */
+#define TEGRA20_SPDIF_CTRL_CAP_LC (1 << 30)
+
+/* SPDIF receiver(RX) enable */
+#define TEGRA20_SPDIF_CTRL_RX_EN (1 << 29)
+
+/* SPDIF Transmitter(TX) enable */
+#define TEGRA20_SPDIF_CTRL_TX_EN (1 << 28)
+
+/* Transmit Channel status */
+#define TEGRA20_SPDIF_CTRL_TC_EN (1 << 27)
+
+/* Transmit user Data */
+#define TEGRA20_SPDIF_CTRL_TU_EN (1 << 26)
+
+/* Interrupt on transmit error */
+#define TEGRA20_SPDIF_CTRL_IE_TXE (1 << 25)
+
+/* Interrupt on receive error */
+#define TEGRA20_SPDIF_CTRL_IE_RXE (1 << 24)
+
+/* Interrupt on invalid preamble */
+#define TEGRA20_SPDIF_CTRL_IE_P (1 << 23)
+
+/* Interrupt on "B" preamble */
+#define TEGRA20_SPDIF_CTRL_IE_B (1 << 22)
+
+/* Interrupt when block of channel status received */
+#define TEGRA20_SPDIF_CTRL_IE_C (1 << 21)
+
+/* Interrupt when a valid information unit (IU) is received */
+#define TEGRA20_SPDIF_CTRL_IE_U (1 << 20)
+
+/* Interrupt when RX user FIFO attention level is reached */
+#define TEGRA20_SPDIF_CTRL_QE_RU (1 << 19)
+
+/* Interrupt when TX user FIFO attention level is reached */
+#define TEGRA20_SPDIF_CTRL_QE_TU (1 << 18)
+
+/* Interrupt when RX data FIFO attention level is reached */
+#define TEGRA20_SPDIF_CTRL_QE_RX (1 << 17)
+
+/* Interrupt when TX data FIFO attention level is reached */
+#define TEGRA20_SPDIF_CTRL_QE_TX (1 << 16)
+
+/* Loopback test mode enable */
+#define TEGRA20_SPDIF_CTRL_LBK_EN (1 << 15)
+
+/*
+ * Pack data mode:
+ * 0 = Single data (16 bit needs to be padded to match the
+ * interface data bit size).
+ * 1 = Packeted left/right channel data into a single word.
+ */
+#define TEGRA20_SPDIF_CTRL_PACK (1 << 14)
+
+/*
+ * 00 = 16bit data
+ * 01 = 20bit data
+ * 10 = 24bit data
+ * 11 = raw data
+ */
+#define TEGRA20_SPDIF_BIT_MODE_16BIT 0
+#define TEGRA20_SPDIF_BIT_MODE_20BIT 1
+#define TEGRA20_SPDIF_BIT_MODE_24BIT 2
+#define TEGRA20_SPDIF_BIT_MODE_RAW 3
+
+#define TEGRA20_SPDIF_CTRL_BIT_MODE_SHIFT 12
+#define TEGRA20_SPDIF_CTRL_BIT_MODE_MASK (3 << TEGRA20_SPDIF_CTRL_BIT_MODE_SHIFT)
+#define TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT (TEGRA20_SPDIF_BIT_MODE_16BIT << TEGRA20_SPDIF_CTRL_BIT_MODE_SHIFT)
+#define TEGRA20_SPDIF_CTRL_BIT_MODE_20BIT (TEGRA20_SPDIF_BIT_MODE_20BIT << TEGRA20_SPDIF_CTRL_BIT_MODE_SHIFT)
+#define TEGRA20_SPDIF_CTRL_BIT_MODE_24BIT (TEGRA20_SPDIF_BIT_MODE_24BIT << TEGRA20_SPDIF_CTRL_BIT_MODE_SHIFT)
+#define TEGRA20_SPDIF_CTRL_BIT_MODE_RAW (TEGRA20_SPDIF_BIT_MODE_RAW << TEGRA20_SPDIF_CTRL_BIT_MODE_SHIFT)
+
+/* Fields in TEGRA20_SPDIF_STATUS */
+
+/*
+ * Note: IS_P, IS_B, IS_C, and IS_U are sticky bits. Software must
+ * write a 1 to the corresponding bit location to clear the status.
+ */
+
+/*
+ * Receiver(RX) shifter is busy receiving data.
+ * This bit is asserted when the receiver first locked onto the
+ * preamble of the data stream after RX_EN is asserted. This bit is
+ * deasserted when either,
+ * (a) the end of a frame is reached after RX_EN is deeasserted, or
+ * (b) the SPDIF data stream becomes inactive.
+ */
+#define TEGRA20_SPDIF_STATUS_RX_BSY (1 << 29)
+
+/*
+ * Transmitter(TX) shifter is busy transmitting data.
+ * This bit is asserted when TX_EN is asserted.
+ * This bit is deasserted when the end of a frame is reached after
+ * TX_EN is deasserted.
+ */
+#define TEGRA20_SPDIF_STATUS_TX_BSY (1 << 28)
+
+/*
+ * TX is busy shifting out channel status.
+ * This bit is asserted when both TX_EN and TC_EN are asserted and
+ * data from CH_STA_TX_A register is loaded into the internal shifter.
+ * This bit is deasserted when either,
+ * (a) the end of a frame is reached after TX_EN is deasserted, or
+ * (b) CH_STA_TX_F register is loaded into the internal shifter.
+ */
+#define TEGRA20_SPDIF_STATUS_TC_BSY (1 << 27)
+
+/*
+ * TX User data FIFO busy.
+ * This bit is asserted when TX_EN and TXU_EN are asserted and
+ * there's data in the TX user FIFO. This bit is deassert when either,
+ * (a) the end of a frame is reached after TX_EN is deasserted, or
+ * (b) there's no data left in the TX user FIFO.
+ */
+#define TEGRA20_SPDIF_STATUS_TU_BSY (1 << 26)
+
+/* TX FIFO Underrun error status */
+#define TEGRA20_SPDIF_STATUS_TX_ERR (1 << 25)
+
+/* RX FIFO Overrun error status */
+#define TEGRA20_SPDIF_STATUS_RX_ERR (1 << 24)
+
+/* Preamble status: 0=Preamble OK, 1=bad/missing preamble */
+#define TEGRA20_SPDIF_STATUS_IS_P (1 << 23)
+
+/* B-preamble detection status: 0=not detected, 1=B-preamble detected */
+#define TEGRA20_SPDIF_STATUS_IS_B (1 << 22)
+
+/*
+ * RX channel block data receive status:
+ * 0=entire block not recieved yet.
+ * 1=received entire block of channel status,
+ */
+#define TEGRA20_SPDIF_STATUS_IS_C (1 << 21)
+
+/* RX User Data Valid flag: 1=valid IU detected, 0 = no IU detected. */
+#define TEGRA20_SPDIF_STATUS_IS_U (1 << 20)
+
+/*
+ * RX User FIFO Status:
+ * 1=attention level reached, 0=attention level not reached.
+ */
+#define TEGRA20_SPDIF_STATUS_QS_RU (1 << 19)
+
+/*
+ * TX User FIFO Status:
+ * 1=attention level reached, 0=attention level not reached.
+ */
+#define TEGRA20_SPDIF_STATUS_QS_TU (1 << 18)
+
+/*
+ * RX Data FIFO Status:
+ * 1=attention level reached, 0=attention level not reached.
+ */
+#define TEGRA20_SPDIF_STATUS_QS_RX (1 << 17)
+
+/*
+ * TX Data FIFO Status:
+ * 1=attention level reached, 0=attention level not reached.
+ */
+#define TEGRA20_SPDIF_STATUS_QS_TX (1 << 16)
+
+/* Fields in TEGRA20_SPDIF_STROBE_CTRL */
+
+/*
+ * Indicates the approximate number of detected SPDIFIN clocks within a
+ * bi-phase period.
+ */
+#define TEGRA20_SPDIF_STROBE_CTRL_PERIOD_SHIFT 16
+#define TEGRA20_SPDIF_STROBE_CTRL_PERIOD_MASK (0xff << TEGRA20_SPDIF_STROBE_CTRL_PERIOD_SHIFT)
+
+/* Data strobe mode: 0=Auto-locked 1=Manual locked */
+#define TEGRA20_SPDIF_STROBE_CTRL_STROBE (1 << 15)
+
+/*
+ * Manual data strobe time within the bi-phase clock period (in terms of
+ * the number of over-sampling clocks).
+ */
+#define TEGRA20_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT 8
+#define TEGRA20_SPDIF_STROBE_CTRL_DATA_STROBES_MASK (0x1f << TEGRA20_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT)
+
+/*
+ * Manual SPDIFIN bi-phase clock period (in terms of the number of
+ * over-sampling clocks).
+ */
+#define TEGRA20_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT 0
+#define TEGRA20_SPDIF_STROBE_CTRL_CLOCK_PERIOD_MASK (0x3f << TEGRA20_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT)
+
+/* Fields in SPDIF_DATA_FIFO_CSR */
+
+/* Clear Receiver User FIFO (RX USR.FIFO) */
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_CLR (1 << 31)
+
+#define TEGRA20_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT 0
+#define TEGRA20_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS 1
+#define TEGRA20_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS 2
+#define TEGRA20_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS 3
+
+/* RU FIFO attention level */
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT 29
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_MASK \
+ (0x3 << TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU1_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT << TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU2_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU3_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU4_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
+
+/* Number of RX USR.FIFO levels with valid data. */
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_SHIFT 24
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_MASK (0x1f << TEGRA20_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_SHIFT)
+
+/* Clear Transmitter User FIFO (TX USR.FIFO) */
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_CLR (1 << 23)
+
+/* TU FIFO attention level */
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT 21
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_MASK \
+ (0x3 << TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU1_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT << TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU2_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU3_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU4_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
+
+/* Number of TX USR.FIFO levels that could be filled. */
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_SHIFT 16
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_MASK (0x1f << SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_SHIFT)
+
+/* Clear Receiver Data FIFO (RX DATA.FIFO) */
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_CLR (1 << 15)
+
+#define TEGRA20_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT 0
+#define TEGRA20_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS 1
+#define TEGRA20_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS 2
+#define TEGRA20_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS 3
+
+/* RU FIFO attention level */
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT 13
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_MASK \
+ (0x3 << TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU1_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT << TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU4_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU8_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU12_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
+
+/* Number of RX DATA.FIFO levels with valid data. */
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_SHIFT 8
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_MASK (0x1f << TEGRA20_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_SHIFT)
+
+/* Clear Transmitter Data FIFO (TX DATA.FIFO) */
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_CLR (1 << 7)
+
+/* TU FIFO attention level */
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT 5
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_MASK \
+ (0x3 << TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU1_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT << TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU4_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU8_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU12_WORD_FULL \
+ (TEGRA20_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
+
+/* Number of TX DATA.FIFO levels that could be filled. */
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_SHIFT 0
+#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_MASK (0x1f << SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_SHIFT)
+
+/* Fields in TEGRA20_SPDIF_DATA_OUT */
+
+/*
+ * This register has 5 different formats:
+ * 16-bit (BIT_MODE=00, PACK=0)
+ * 20-bit (BIT_MODE=01, PACK=0)
+ * 24-bit (BIT_MODE=10, PACK=0)
+ * raw (BIT_MODE=11, PACK=0)
+ * 16-bit packed (BIT_MODE=00, PACK=1)
+ */
+
+#define TEGRA20_SPDIF_DATA_OUT_DATA_16_SHIFT 0
+#define TEGRA20_SPDIF_DATA_OUT_DATA_16_MASK (0xffff << TEGRA20_SPDIF_DATA_OUT_DATA_16_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_OUT_DATA_20_SHIFT 0
+#define TEGRA20_SPDIF_DATA_OUT_DATA_20_MASK (0xfffff << TEGRA20_SPDIF_DATA_OUT_DATA_20_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_OUT_DATA_24_SHIFT 0
+#define TEGRA20_SPDIF_DATA_OUT_DATA_24_MASK (0xffffff << TEGRA20_SPDIF_DATA_OUT_DATA_24_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_P (1 << 31)
+#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_C (1 << 30)
+#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_U (1 << 29)
+#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_V (1 << 28)
+
+#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_DATA_SHIFT 8
+#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_DATA_MASK (0xfffff << TEGRA20_SPDIF_DATA_OUT_DATA_RAW_DATA_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_AUX_SHIFT 4
+#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_AUX_MASK (0xf << TEGRA20_SPDIF_DATA_OUT_DATA_RAW_AUX_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_SHIFT 0
+#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_MASK (0xf << TEGRA20_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_SHIFT 16
+#define TEGRA20_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_MASK (0xffff << TEGRA20_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_SHIFT 0
+#define TEGRA20_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_MASK (0xffff << TEGRA20_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_SHIFT)
+
+/* Fields in TEGRA20_SPDIF_DATA_IN */
+
+/*
+ * This register has 5 different formats:
+ * 16-bit (BIT_MODE=00, PACK=0)
+ * 20-bit (BIT_MODE=01, PACK=0)
+ * 24-bit (BIT_MODE=10, PACK=0)
+ * raw (BIT_MODE=11, PACK=0)
+ * 16-bit packed (BIT_MODE=00, PACK=1)
+ *
+ * Bits 31:24 are common to all modes except 16-bit packed
+ */
+
+#define TEGRA20_SPDIF_DATA_IN_DATA_P (1 << 31)
+#define TEGRA20_SPDIF_DATA_IN_DATA_C (1 << 30)
+#define TEGRA20_SPDIF_DATA_IN_DATA_U (1 << 29)
+#define TEGRA20_SPDIF_DATA_IN_DATA_V (1 << 28)
+
+#define TEGRA20_SPDIF_DATA_IN_DATA_PREAMBLE_SHIFT 24
+#define TEGRA20_SPDIF_DATA_IN_DATA_PREAMBLE_MASK (0xf << TEGRA20_SPDIF_DATA_IN_DATA_PREAMBLE_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_IN_DATA_16_SHIFT 0
+#define TEGRA20_SPDIF_DATA_IN_DATA_16_MASK (0xffff << TEGRA20_SPDIF_DATA_IN_DATA_16_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_IN_DATA_20_SHIFT 0
+#define TEGRA20_SPDIF_DATA_IN_DATA_20_MASK (0xfffff << TEGRA20_SPDIF_DATA_IN_DATA_20_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_IN_DATA_24_SHIFT 0
+#define TEGRA20_SPDIF_DATA_IN_DATA_24_MASK (0xffffff << TEGRA20_SPDIF_DATA_IN_DATA_24_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_IN_DATA_RAW_DATA_SHIFT 8
+#define TEGRA20_SPDIF_DATA_IN_DATA_RAW_DATA_MASK (0xfffff << TEGRA20_SPDIF_DATA_IN_DATA_RAW_DATA_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_IN_DATA_RAW_AUX_SHIFT 4
+#define TEGRA20_SPDIF_DATA_IN_DATA_RAW_AUX_MASK (0xf << TEGRA20_SPDIF_DATA_IN_DATA_RAW_AUX_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_SHIFT 0
+#define TEGRA20_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_MASK (0xf << TEGRA20_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_SHIFT 16
+#define TEGRA20_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_MASK (0xffff << TEGRA20_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_SHIFT)
+
+#define TEGRA20_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_SHIFT 0
+#define TEGRA20_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_MASK (0xffff << TEGRA20_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_SHIFT)
+
+/* Fields in TEGRA20_SPDIF_CH_STA_RX_A */
+/* Fields in TEGRA20_SPDIF_CH_STA_RX_B */
+/* Fields in TEGRA20_SPDIF_CH_STA_RX_C */
+/* Fields in TEGRA20_SPDIF_CH_STA_RX_D */
+/* Fields in TEGRA20_SPDIF_CH_STA_RX_E */
+/* Fields in TEGRA20_SPDIF_CH_STA_RX_F */
+
+/*
+ * The 6-word receive channel data page buffer holds a block (192 frames) of
+ * channel status information. The order of receive is from LSB to MSB
+ * bit, and from CH_STA_RX_A to CH_STA_RX_F then back to CH_STA_RX_A.
+ */
+
+/* Fields in TEGRA20_SPDIF_CH_STA_TX_A */
+/* Fields in TEGRA20_SPDIF_CH_STA_TX_B */
+/* Fields in TEGRA20_SPDIF_CH_STA_TX_C */
+/* Fields in TEGRA20_SPDIF_CH_STA_TX_D */
+/* Fields in TEGRA20_SPDIF_CH_STA_TX_E */
+/* Fields in TEGRA20_SPDIF_CH_STA_TX_F */
+
+/*
+ * The 6-word transmit channel data page buffer holds a block (192 frames) of
+ * channel status information. The order of transmission is from LSB to MSB
+ * bit, and from CH_STA_TX_A to CH_STA_TX_F then back to CH_STA_TX_A.
+ */
+
+/* Fields in TEGRA20_SPDIF_USR_STA_RX_A */
+
+/*
+ * This 4-word deep FIFO receives user FIFO field information. The order of
+ * receive is from LSB to MSB bit.
+ */
+
+/* Fields in TEGRA20_SPDIF_USR_DAT_TX_A */
+
+/*
+ * This 4-word deep FIFO transmits user FIFO field information. The order of
+ * transmission is from LSB to MSB bit.
+ */
+
+struct tegra20_spdif {
+ struct clk *clk_spdif_out;
+ struct tegra_pcm_dma_params capture_dma_data;
+ struct tegra_pcm_dma_params playback_dma_data;
+ struct regmap *regmap;
+ u32 reg_ctrl;
+};
+
+#endif
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
new file mode 100644
index 000000000000..57cd419f743e
--- /dev/null
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -0,0 +1,631 @@
+/*
+ * tegra30_ahub.c - Tegra30 AHUB driver
+ *
+ * Copyright (c) 2011,2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <mach/clk.h>
+#include <mach/dma.h>
+#include <sound/soc.h>
+#include "tegra30_ahub.h"
+
+#define DRV_NAME "tegra30-ahub"
+
+static struct tegra30_ahub *ahub;
+
+static inline void tegra30_apbif_write(u32 reg, u32 val)
+{
+ regmap_write(ahub->regmap_apbif, reg, val);
+}
+
+static inline u32 tegra30_apbif_read(u32 reg)
+{
+ u32 val;
+ regmap_read(ahub->regmap_apbif, reg, &val);
+ return val;
+}
+
+static inline void tegra30_audio_write(u32 reg, u32 val)
+{
+ regmap_write(ahub->regmap_ahub, reg, val);
+}
+
+static int tegra30_ahub_runtime_suspend(struct device *dev)
+{
+ regcache_cache_only(ahub->regmap_apbif, true);
+ regcache_cache_only(ahub->regmap_ahub, true);
+
+ clk_disable(ahub->clk_apbif);
+ clk_disable(ahub->clk_d_audio);
+
+ return 0;
+}
+
+/*
+ * clk_apbif isn't required for an I2S<->I2S configuration where no PCM data
+ * is read from or sent to memory. However, that's not something the rest of
+ * the driver supports right now, so we'll just treat the two clocks as one
+ * for now.
+ *
+ * These functions should not be a plain ref-count. Instead, each active stream
+ * contributes some requirement to the minimum clock rate, so starting or
+ * stopping streams should dynamically adjust the clock as required. However,
+ * this is not yet implemented.
+ */
+static int tegra30_ahub_runtime_resume(struct device *dev)
+{
+ int ret;
+
+ ret = clk_enable(ahub->clk_d_audio);
+ if (ret) {
+ dev_err(dev, "clk_enable d_audio failed: %d\n", ret);
+ return ret;
+ }
+ ret = clk_enable(ahub->clk_apbif);
+ if (ret) {
+ dev_err(dev, "clk_enable apbif failed: %d\n", ret);
+ clk_disable(ahub->clk_d_audio);
+ return ret;
+ }
+
+ regcache_cache_only(ahub->regmap_apbif, false);
+ regcache_cache_only(ahub->regmap_ahub, false);
+
+ return 0;
+}
+
+int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
+ unsigned long *fiforeg,
+ unsigned long *reqsel)
+{
+ int channel;
+ u32 reg, val;
+
+ channel = find_first_zero_bit(ahub->rx_usage,
+ TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
+ if (channel >= TEGRA30_AHUB_CHANNEL_CTRL_COUNT)
+ return -EBUSY;
+
+ __set_bit(channel, ahub->rx_usage);
+
+ *rxcif = TEGRA30_AHUB_RXCIF_APBIF_RX0 + channel;
+ *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_RXFIFO +
+ (channel * TEGRA30_AHUB_CHANNEL_RXFIFO_STRIDE);
+ *reqsel = ahub->dma_sel + channel;
+
+ reg = TEGRA30_AHUB_CHANNEL_CTRL +
+ (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
+ val = tegra30_apbif_read(reg);
+ val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_MASK |
+ TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_MASK);
+ val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_SHIFT) |
+ TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_EN |
+ TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16;
+ tegra30_apbif_write(reg, val);
+
+ reg = TEGRA30_AHUB_CIF_RX_CTRL +
+ (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
+ val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
+ (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
+ (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
+ TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
+ TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
+ TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
+ tegra30_apbif_write(reg, val);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_allocate_rx_fifo);
+
+int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif)
+{
+ int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
+ int reg, val;
+
+ reg = TEGRA30_AHUB_CHANNEL_CTRL +
+ (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
+ val = tegra30_apbif_read(reg);
+ val |= TEGRA30_AHUB_CHANNEL_CTRL_RX_EN;
+ tegra30_apbif_write(reg, val);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_enable_rx_fifo);
+
+int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif)
+{
+ int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
+ int reg, val;
+
+ reg = TEGRA30_AHUB_CHANNEL_CTRL +
+ (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
+ val = tegra30_apbif_read(reg);
+ val &= ~TEGRA30_AHUB_CHANNEL_CTRL_RX_EN;
+ tegra30_apbif_write(reg, val);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_disable_rx_fifo);
+
+int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif)
+{
+ int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
+
+ __clear_bit(channel, ahub->rx_usage);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_free_rx_fifo);
+
+int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
+ unsigned long *fiforeg,
+ unsigned long *reqsel)
+{
+ int channel;
+ u32 reg, val;
+
+ channel = find_first_zero_bit(ahub->tx_usage,
+ TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
+ if (channel >= TEGRA30_AHUB_CHANNEL_CTRL_COUNT)
+ return -EBUSY;
+
+ __set_bit(channel, ahub->tx_usage);
+
+ *txcif = TEGRA30_AHUB_TXCIF_APBIF_TX0 + channel;
+ *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_TXFIFO +
+ (channel * TEGRA30_AHUB_CHANNEL_TXFIFO_STRIDE);
+ *reqsel = ahub->dma_sel + channel;
+
+ reg = TEGRA30_AHUB_CHANNEL_CTRL +
+ (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
+ val = tegra30_apbif_read(reg);
+ val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_MASK |
+ TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_MASK);
+ val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_SHIFT) |
+ TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_EN |
+ TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16;
+ tegra30_apbif_write(reg, val);
+
+ reg = TEGRA30_AHUB_CIF_TX_CTRL +
+ (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
+ val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
+ (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
+ (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
+ TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
+ TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
+ TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
+ tegra30_apbif_write(reg, val);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_allocate_tx_fifo);
+
+int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif)
+{
+ int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
+ int reg, val;
+
+ reg = TEGRA30_AHUB_CHANNEL_CTRL +
+ (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
+ val = tegra30_apbif_read(reg);
+ val |= TEGRA30_AHUB_CHANNEL_CTRL_TX_EN;
+ tegra30_apbif_write(reg, val);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_enable_tx_fifo);
+
+int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif)
+{
+ int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
+ int reg, val;
+
+ reg = TEGRA30_AHUB_CHANNEL_CTRL +
+ (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
+ val = tegra30_apbif_read(reg);
+ val &= ~TEGRA30_AHUB_CHANNEL_CTRL_TX_EN;
+ tegra30_apbif_write(reg, val);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_disable_tx_fifo);
+
+int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif)
+{
+ int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
+
+ __clear_bit(channel, ahub->tx_usage);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_free_tx_fifo);
+
+int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif,
+ enum tegra30_ahub_txcif txcif)
+{
+ int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
+ int reg;
+
+ reg = TEGRA30_AHUB_AUDIO_RX +
+ (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE);
+ tegra30_audio_write(reg, 1 << txcif);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_set_rx_cif_source);
+
+int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif)
+{
+ int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
+ int reg;
+
+ reg = TEGRA30_AHUB_AUDIO_RX +
+ (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE);
+ tegra30_audio_write(reg, 0);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source);
+
+static const char * const configlink_clocks[] __devinitconst = {
+ "i2s0",
+ "i2s1",
+ "i2s2",
+ "i2s3",
+ "i2s4",
+ "dam0",
+ "dam1",
+ "dam2",
+ "spdif_in",
+};
+
+struct of_dev_auxdata ahub_auxdata[] __devinitdata = {
+ OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080300, "tegra30-i2s.0", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080400, "tegra30-i2s.1", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080500, "tegra30-i2s.2", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080600, "tegra30-i2s.3", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080700, "tegra30-i2s.4", NULL),
+ {}
+};
+
+#define LAST_REG(name) \
+ (TEGRA30_AHUB_##name + \
+ (TEGRA30_AHUB_##name##_STRIDE * TEGRA30_AHUB_##name##_COUNT) - 4)
+
+#define REG_IN_ARRAY(reg, name) \
+ ((reg >= TEGRA30_AHUB_##name) && \
+ (reg <= LAST_REG(name) && \
+ (!((reg - TEGRA30_AHUB_##name) % TEGRA30_AHUB_##name##_STRIDE))))
+
+static bool tegra30_ahub_apbif_wr_rd_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA30_AHUB_CONFIG_LINK_CTRL:
+ case TEGRA30_AHUB_MISC_CTRL:
+ case TEGRA30_AHUB_APBDMA_LIVE_STATUS:
+ case TEGRA30_AHUB_I2S_LIVE_STATUS:
+ case TEGRA30_AHUB_SPDIF_LIVE_STATUS:
+ case TEGRA30_AHUB_I2S_INT_MASK:
+ case TEGRA30_AHUB_DAM_INT_MASK:
+ case TEGRA30_AHUB_SPDIF_INT_MASK:
+ case TEGRA30_AHUB_APBIF_INT_MASK:
+ case TEGRA30_AHUB_I2S_INT_STATUS:
+ case TEGRA30_AHUB_DAM_INT_STATUS:
+ case TEGRA30_AHUB_SPDIF_INT_STATUS:
+ case TEGRA30_AHUB_APBIF_INT_STATUS:
+ case TEGRA30_AHUB_I2S_INT_SOURCE:
+ case TEGRA30_AHUB_DAM_INT_SOURCE:
+ case TEGRA30_AHUB_SPDIF_INT_SOURCE:
+ case TEGRA30_AHUB_APBIF_INT_SOURCE:
+ case TEGRA30_AHUB_I2S_INT_SET:
+ case TEGRA30_AHUB_DAM_INT_SET:
+ case TEGRA30_AHUB_SPDIF_INT_SET:
+ case TEGRA30_AHUB_APBIF_INT_SET:
+ return true;
+ default:
+ break;
+ };
+
+ if (REG_IN_ARRAY(reg, CHANNEL_CTRL) ||
+ REG_IN_ARRAY(reg, CHANNEL_CLEAR) ||
+ REG_IN_ARRAY(reg, CHANNEL_STATUS) ||
+ REG_IN_ARRAY(reg, CHANNEL_TXFIFO) ||
+ REG_IN_ARRAY(reg, CHANNEL_RXFIFO) ||
+ REG_IN_ARRAY(reg, CIF_TX_CTRL) ||
+ REG_IN_ARRAY(reg, CIF_RX_CTRL) ||
+ REG_IN_ARRAY(reg, DAM_LIVE_STATUS))
+ return true;
+
+ return false;
+}
+
+static bool tegra30_ahub_apbif_volatile_reg(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA30_AHUB_CONFIG_LINK_CTRL:
+ case TEGRA30_AHUB_MISC_CTRL:
+ case TEGRA30_AHUB_APBDMA_LIVE_STATUS:
+ case TEGRA30_AHUB_I2S_LIVE_STATUS:
+ case TEGRA30_AHUB_SPDIF_LIVE_STATUS:
+ case TEGRA30_AHUB_I2S_INT_STATUS:
+ case TEGRA30_AHUB_DAM_INT_STATUS:
+ case TEGRA30_AHUB_SPDIF_INT_STATUS:
+ case TEGRA30_AHUB_APBIF_INT_STATUS:
+ case TEGRA30_AHUB_I2S_INT_SET:
+ case TEGRA30_AHUB_DAM_INT_SET:
+ case TEGRA30_AHUB_SPDIF_INT_SET:
+ case TEGRA30_AHUB_APBIF_INT_SET:
+ return true;
+ default:
+ break;
+ };
+
+ if (REG_IN_ARRAY(reg, CHANNEL_CLEAR) ||
+ REG_IN_ARRAY(reg, CHANNEL_STATUS) ||
+ REG_IN_ARRAY(reg, CHANNEL_TXFIFO) ||
+ REG_IN_ARRAY(reg, CHANNEL_RXFIFO) ||
+ REG_IN_ARRAY(reg, DAM_LIVE_STATUS))
+ return true;
+
+ return false;
+}
+
+static bool tegra30_ahub_apbif_precious_reg(struct device *dev,
+ unsigned int reg)
+{
+ if (REG_IN_ARRAY(reg, CHANNEL_TXFIFO) ||
+ REG_IN_ARRAY(reg, CHANNEL_RXFIFO))
+ return true;
+
+ return false;
+}
+
+static const struct regmap_config tegra30_ahub_apbif_regmap_config = {
+ .name = "apbif",
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = TEGRA30_AHUB_APBIF_INT_SET,
+ .writeable_reg = tegra30_ahub_apbif_wr_rd_reg,
+ .readable_reg = tegra30_ahub_apbif_wr_rd_reg,
+ .volatile_reg = tegra30_ahub_apbif_volatile_reg,
+ .precious_reg = tegra30_ahub_apbif_precious_reg,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static bool tegra30_ahub_ahub_wr_rd_reg(struct device *dev, unsigned int reg)
+{
+ if (REG_IN_ARRAY(reg, AUDIO_RX))
+ return true;
+
+ return false;
+}
+
+static const struct regmap_config tegra30_ahub_ahub_regmap_config = {
+ .name = "ahub",
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = LAST_REG(AUDIO_RX),
+ .writeable_reg = tegra30_ahub_ahub_wr_rd_reg,
+ .readable_reg = tegra30_ahub_ahub_wr_rd_reg,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit tegra30_ahub_probe(struct platform_device *pdev)
+{
+ struct clk *clk;
+ int i;
+ struct resource *res0, *res1, *region;
+ u32 of_dma[2];
+ void __iomem *regs_apbif, *regs_ahub;
+ int ret = 0;
+
+ if (ahub)
+ return -ENODEV;
+
+ /*
+ * The AHUB hosts a register bus: the "configlink". For this to
+ * operate correctly, all devices on this bus must be out of reset.
+ * Ensure that here.
+ */
+ for (i = 0; i < ARRAY_SIZE(configlink_clocks); i++) {
+ clk = clk_get_sys(NULL, configlink_clocks[i]);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "Can't get clock %s\n",
+ configlink_clocks[i]);
+ ret = PTR_ERR(clk);
+ goto err;
+ }
+ tegra_periph_reset_deassert(clk);
+ clk_put(clk);
+ }
+
+ ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub),
+ GFP_KERNEL);
+ if (!ahub) {
+ dev_err(&pdev->dev, "Can't allocate tegra30_ahub\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ dev_set_drvdata(&pdev->dev, ahub);
+
+ ahub->dev = &pdev->dev;
+
+ ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio");
+ if (IS_ERR(ahub->clk_d_audio)) {
+ dev_err(&pdev->dev, "Can't retrieve ahub d_audio clock\n");
+ ret = PTR_ERR(ahub->clk_d_audio);
+ goto err;
+ }
+
+ ahub->clk_apbif = clk_get(&pdev->dev, "apbif");
+ if (IS_ERR(ahub->clk_apbif)) {
+ dev_err(&pdev->dev, "Can't retrieve ahub apbif clock\n");
+ ret = PTR_ERR(ahub->clk_apbif);
+ goto err_clk_put_d_audio;
+ }
+
+ if (of_property_read_u32_array(pdev->dev.of_node,
+ "nvidia,dma-request-selector",
+ of_dma, 2) < 0) {
+ dev_err(&pdev->dev,
+ "Missing property nvidia,dma-request-selector\n");
+ ret = -ENODEV;
+ goto err_clk_put_d_audio;
+ }
+ ahub->dma_sel = of_dma[1];
+
+ res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res0) {
+ dev_err(&pdev->dev, "No apbif memory resource\n");
+ ret = -ENODEV;
+ goto err_clk_put_apbif;
+ }
+
+ region = devm_request_mem_region(&pdev->dev, res0->start,
+ resource_size(res0), DRV_NAME);
+ if (!region) {
+ dev_err(&pdev->dev, "request region apbif failed\n");
+ ret = -EBUSY;
+ goto err_clk_put_apbif;
+ }
+ ahub->apbif_addr = res0->start;
+
+ regs_apbif = devm_ioremap(&pdev->dev, res0->start,
+ resource_size(res0));
+ if (!regs_apbif) {
+ dev_err(&pdev->dev, "ioremap apbif failed\n");
+ ret = -ENOMEM;
+ goto err_clk_put_apbif;
+ }
+
+ ahub->regmap_apbif = devm_regmap_init_mmio(&pdev->dev, regs_apbif,
+ &tegra30_ahub_apbif_regmap_config);
+ if (IS_ERR(ahub->regmap_apbif)) {
+ dev_err(&pdev->dev, "apbif regmap init failed\n");
+ ret = PTR_ERR(ahub->regmap_apbif);
+ goto err_clk_put_apbif;
+ }
+ regcache_cache_only(ahub->regmap_apbif, true);
+
+ res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res1) {
+ dev_err(&pdev->dev, "No ahub memory resource\n");
+ ret = -ENODEV;
+ goto err_clk_put_apbif;
+ }
+
+ region = devm_request_mem_region(&pdev->dev, res1->start,
+ resource_size(res1), DRV_NAME);
+ if (!region) {
+ dev_err(&pdev->dev, "request region ahub failed\n");
+ ret = -EBUSY;
+ goto err_clk_put_apbif;
+ }
+
+ regs_ahub = devm_ioremap(&pdev->dev, res1->start,
+ resource_size(res1));
+ if (!regs_ahub) {
+ dev_err(&pdev->dev, "ioremap ahub failed\n");
+ ret = -ENOMEM;
+ goto err_clk_put_apbif;
+ }
+
+ ahub->regmap_ahub = devm_regmap_init_mmio(&pdev->dev, regs_ahub,
+ &tegra30_ahub_ahub_regmap_config);
+ if (IS_ERR(ahub->regmap_ahub)) {
+ dev_err(&pdev->dev, "ahub regmap init failed\n");
+ ret = PTR_ERR(ahub->regmap_ahub);
+ goto err_clk_put_apbif;
+ }
+ regcache_cache_only(ahub->regmap_ahub, true);
+
+ pm_runtime_enable(&pdev->dev);
+ if (!pm_runtime_enabled(&pdev->dev)) {
+ ret = tegra30_ahub_runtime_resume(&pdev->dev);
+ if (ret)
+ goto err_pm_disable;
+ }
+
+ of_platform_populate(pdev->dev.of_node, NULL, ahub_auxdata,
+ &pdev->dev);
+
+ return 0;
+
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+err_clk_put_apbif:
+ clk_put(ahub->clk_apbif);
+err_clk_put_d_audio:
+ clk_put(ahub->clk_d_audio);
+ ahub = 0;
+err:
+ return ret;
+}
+
+static int __devexit tegra30_ahub_remove(struct platform_device *pdev)
+{
+ if (!ahub)
+ return -ENODEV;
+
+ pm_runtime_disable(&pdev->dev);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ tegra30_ahub_runtime_suspend(&pdev->dev);
+
+ clk_put(ahub->clk_apbif);
+ clk_put(ahub->clk_d_audio);
+
+ ahub = 0;
+
+ return 0;
+}
+
+static const struct of_device_id tegra30_ahub_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra30-ahub", },
+ {},
+};
+
+static const struct dev_pm_ops tegra30_ahub_pm_ops __devinitconst = {
+ SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend,
+ tegra30_ahub_runtime_resume, NULL)
+};
+
+static struct platform_driver tegra30_ahub_driver = {
+ .probe = tegra30_ahub_probe,
+ .remove = __devexit_p(tegra30_ahub_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = tegra30_ahub_of_match,
+ .pm = &tegra30_ahub_pm_ops,
+ },
+};
+module_platform_driver(tegra30_ahub_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra30 AHUB driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h
new file mode 100644
index 000000000000..e690e2eecc92
--- /dev/null
+++ b/sound/soc/tegra/tegra30_ahub.h
@@ -0,0 +1,483 @@
+/*
+ * tegra30_ahub.h - Definitions for Tegra30 AHUB driver
+ *
+ * Copyright (c) 2011,2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TEGRA30_AHUB_H__
+#define __TEGRA30_AHUB_H__
+
+/* Fields in *_CIF_RX/TX_CTRL; used by AHUB FIFOs, and all other audio modules */
+
+#define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT 28
+#define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US 0xf
+#define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK (TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT)
+
+/* Channel count minus 1 */
+#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT 24
+#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US 7
+#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT)
+
+/* Channel count minus 1 */
+#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT 16
+#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US 7
+#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT)
+
+#define TEGRA30_AUDIOCIF_BITS_4 0
+#define TEGRA30_AUDIOCIF_BITS_8 1
+#define TEGRA30_AUDIOCIF_BITS_12 2
+#define TEGRA30_AUDIOCIF_BITS_16 3
+#define TEGRA30_AUDIOCIF_BITS_20 4
+#define TEGRA30_AUDIOCIF_BITS_24 5
+#define TEGRA30_AUDIOCIF_BITS_28 6
+#define TEGRA30_AUDIOCIF_BITS_32 7
+
+#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT 12
+#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_MASK (7 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_4 (TEGRA30_AUDIOCIF_BITS_4 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_8 (TEGRA30_AUDIOCIF_BITS_8 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_12 (TEGRA30_AUDIOCIF_BITS_12 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 (TEGRA30_AUDIOCIF_BITS_16 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_20 (TEGRA30_AUDIOCIF_BITS_20 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_24 (TEGRA30_AUDIOCIF_BITS_24 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_28 (TEGRA30_AUDIOCIF_BITS_28 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_32 (TEGRA30_AUDIOCIF_BITS_32 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
+
+#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT 8
+#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_MASK (7 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_4 (TEGRA30_AUDIOCIF_BITS_4 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_8 (TEGRA30_AUDIOCIF_BITS_8 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_12 (TEGRA30_AUDIOCIF_BITS_12 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 (TEGRA30_AUDIOCIF_BITS_16 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_20 (TEGRA30_AUDIOCIF_BITS_20 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_24 (TEGRA30_AUDIOCIF_BITS_24 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_28 (TEGRA30_AUDIOCIF_BITS_28 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_32 (TEGRA30_AUDIOCIF_BITS_32 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
+
+#define TEGRA30_AUDIOCIF_EXPAND_ZERO 0
+#define TEGRA30_AUDIOCIF_EXPAND_ONE 1
+#define TEGRA30_AUDIOCIF_EXPAND_LFSR 2
+
+#define TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT 6
+#define TEGRA30_AUDIOCIF_CTRL_EXPAND_MASK (3 << TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_EXPAND_ZERO (TEGRA30_AUDIOCIF_EXPAND_ZERO << TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_EXPAND_ONE (TEGRA30_AUDIOCIF_EXPAND_ONE << TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_EXPAND_LFSR (TEGRA30_AUDIOCIF_EXPAND_LFSR << TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT)
+
+#define TEGRA30_AUDIOCIF_STEREO_CONV_CH0 0
+#define TEGRA30_AUDIOCIF_STEREO_CONV_CH1 1
+#define TEGRA30_AUDIOCIF_STEREO_CONV_AVG 2
+
+#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT 4
+#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_MASK (3 << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_CH0 (TEGRA30_AUDIOCIF_STEREO_CONV_CH0 << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_CH1 (TEGRA30_AUDIOCIF_STEREO_CONV_CH1 << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_AVG (TEGRA30_AUDIOCIF_STEREO_CONV_AVG << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
+
+#define TEGRA30_AUDIOCIF_CTRL_REPLICATE 3
+
+#define TEGRA30_AUDIOCIF_DIRECTION_TX 0
+#define TEGRA30_AUDIOCIF_DIRECTION_RX 1
+
+#define TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT 2
+#define TEGRA30_AUDIOCIF_CTRL_DIRECTION_MASK (1 << TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX (TEGRA30_AUDIOCIF_DIRECTION_TX << TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX (TEGRA30_AUDIOCIF_DIRECTION_RX << TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT)
+
+#define TEGRA30_AUDIOCIF_TRUNCATE_ROUND 0
+#define TEGRA30_AUDIOCIF_TRUNCATE_CHOP 1
+
+#define TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT 1
+#define TEGRA30_AUDIOCIF_CTRL_TRUNCATE_MASK (1 << TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_TRUNCATE_ROUND (TEGRA30_AUDIOCIF_TRUNCATE_ROUND << TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_TRUNCATE_CHOP (TEGRA30_AUDIOCIF_TRUNCATE_CHOP << TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT)
+
+#define TEGRA30_AUDIOCIF_MONO_CONV_ZERO 0
+#define TEGRA30_AUDIOCIF_MONO_CONV_COPY 1
+
+#define TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT 0
+#define TEGRA30_AUDIOCIF_CTRL_MONO_CONV_MASK (1 << TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_MONO_CONV_ZERO (TEGRA30_AUDIOCIF_MONO_CONV_ZERO << TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT)
+#define TEGRA30_AUDIOCIF_CTRL_MONO_CONV_COPY (TEGRA30_AUDIOCIF_MONO_CONV_COPY << TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT)
+
+/* Registers within TEGRA30_AUDIO_CLUSTER_BASE */
+
+/* TEGRA30_AHUB_CHANNEL_CTRL */
+
+#define TEGRA30_AHUB_CHANNEL_CTRL 0x0
+#define TEGRA30_AHUB_CHANNEL_CTRL_STRIDE 0x20
+#define TEGRA30_AHUB_CHANNEL_CTRL_COUNT 4
+#define TEGRA30_AHUB_CHANNEL_CTRL_TX_EN (1 << 31)
+#define TEGRA30_AHUB_CHANNEL_CTRL_RX_EN (1 << 30)
+#define TEGRA30_AHUB_CHANNEL_CTRL_LOOPBACK (1 << 29)
+
+#define TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_SHIFT 16
+#define TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_MASK_US 0xff
+#define TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_MASK (TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_MASK_US << TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_SHIFT)
+
+#define TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_SHIFT 8
+#define TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_MASK_US 0xff
+#define TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_MASK (TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_MASK_US << TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_SHIFT)
+
+#define TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_EN (1 << 6)
+
+#define TEGRA30_PACK_8_4 2
+#define TEGRA30_PACK_16 3
+
+#define TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_SHIFT 4
+#define TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_MASK_US 3
+#define TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_MASK (TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_MASK_US << TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_SHIFT)
+#define TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_8_4 (TEGRA30_PACK_8_4 << TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_SHIFT)
+#define TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16 (TEGRA30_PACK_16 << TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_SHIFT)
+
+#define TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_EN (1 << 2)
+
+#define TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_SHIFT 0
+#define TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_MASK_US 3
+#define TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_MASK (TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_MASK_US << TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_SHIFT)
+#define TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_8_4 (TEGRA30_PACK_8_4 << TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_SHIFT)
+#define TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16 (TEGRA30_PACK_16 << TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_SHIFT)
+
+/* TEGRA30_AHUB_CHANNEL_CLEAR */
+
+#define TEGRA30_AHUB_CHANNEL_CLEAR 0x4
+#define TEGRA30_AHUB_CHANNEL_CLEAR_STRIDE 0x20
+#define TEGRA30_AHUB_CHANNEL_CLEAR_COUNT 4
+#define TEGRA30_AHUB_CHANNEL_CLEAR_TX_SOFT_RESET (1 << 31)
+#define TEGRA30_AHUB_CHANNEL_CLEAR_RX_SOFT_RESET (1 << 30)
+
+/* TEGRA30_AHUB_CHANNEL_STATUS */
+
+#define TEGRA30_AHUB_CHANNEL_STATUS 0x8
+#define TEGRA30_AHUB_CHANNEL_STATUS_STRIDE 0x20
+#define TEGRA30_AHUB_CHANNEL_STATUS_COUNT 4
+#define TEGRA30_AHUB_CHANNEL_STATUS_TX_FREE_SHIFT 24
+#define TEGRA30_AHUB_CHANNEL_STATUS_TX_FREE_MASK_US 0xff
+#define TEGRA30_AHUB_CHANNEL_STATUS_TX_FREE_MASK (TEGRA30_AHUB_CHANNEL_STATUS_TX_FREE_MASK_US << TEGRA30_AHUB_CHANNEL_STATUS_TX_FREE_SHIFT)
+#define TEGRA30_AHUB_CHANNEL_STATUS_RX_FREE_SHIFT 16
+#define TEGRA30_AHUB_CHANNEL_STATUS_RX_FREE_MASK_US 0xff
+#define TEGRA30_AHUB_CHANNEL_STATUS_RX_FREE_MASK (TEGRA30_AHUB_CHANNEL_STATUS_RX_FREE_MASK_US << TEGRA30_AHUB_CHANNEL_STATUS_RX_FREE_SHIFT)
+#define TEGRA30_AHUB_CHANNEL_STATUS_TX_TRIG (1 << 1)
+#define TEGRA30_AHUB_CHANNEL_STATUS_RX_TRIG (1 << 0)
+
+/* TEGRA30_AHUB_CHANNEL_TXFIFO */
+
+#define TEGRA30_AHUB_CHANNEL_TXFIFO 0xc
+#define TEGRA30_AHUB_CHANNEL_TXFIFO_STRIDE 0x20
+#define TEGRA30_AHUB_CHANNEL_TXFIFO_COUNT 4
+
+/* TEGRA30_AHUB_CHANNEL_RXFIFO */
+
+#define TEGRA30_AHUB_CHANNEL_RXFIFO 0x10
+#define TEGRA30_AHUB_CHANNEL_RXFIFO_STRIDE 0x20
+#define TEGRA30_AHUB_CHANNEL_RXFIFO_COUNT 4
+
+/* TEGRA30_AHUB_CIF_TX_CTRL */
+
+#define TEGRA30_AHUB_CIF_TX_CTRL 0x14
+#define TEGRA30_AHUB_CIF_TX_CTRL_STRIDE 0x20
+#define TEGRA30_AHUB_CIF_TX_CTRL_COUNT 4
+/* Uses field from TEGRA30_AUDIOCIF_CTRL_* */
+
+/* TEGRA30_AHUB_CIF_RX_CTRL */
+
+#define TEGRA30_AHUB_CIF_RX_CTRL 0x18
+#define TEGRA30_AHUB_CIF_RX_CTRL_STRIDE 0x20
+#define TEGRA30_AHUB_CIF_RX_CTRL_COUNT 4
+/* Uses field from TEGRA30_AUDIOCIF_CTRL_* */
+
+/* TEGRA30_AHUB_CONFIG_LINK_CTRL */
+
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL 0x80
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL_MASTER_FIFO_FULL_CNT_SHIFT 28
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL_MASTER_FIFO_FULL_CNT_MASK_US 0xf
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL_MASTER_FIFO_FULL_CNT_MASK (TEGRA30_AHUB_CONFIG_LINK_CTRL_MASTER_FIFO_FULL_CNT_MASK_US << TEGRA30_AHUB_CONFIG_LINK_CTRL_MASTER_FIFO_FULL_CNT_SHIFT)
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_SHIFT 16
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_MASK_US 0xfff
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_MASK (TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_MASK_US << TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_SHIFT)
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_SHIFT 4
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_MASK_US 0xfff
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_MASK (TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_MASK_US << TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_SHIFT)
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL_CG_EN (1 << 2)
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL_CLEAR_TIMEOUT_CNTR (1 << 1)
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL_SOFT_RESET (1 << 0)
+
+/* TEGRA30_AHUB_MISC_CTRL */
+
+#define TEGRA30_AHUB_MISC_CTRL 0x84
+#define TEGRA30_AHUB_MISC_CTRL_AUDIO_ACTIVE (1 << 31)
+#define TEGRA30_AHUB_MISC_CTRL_AUDIO_CG_EN (1 << 8)
+#define TEGRA30_AHUB_MISC_CTRL_AUDIO_OBS_SEL_SHIFT 0
+#define TEGRA30_AHUB_MISC_CTRL_AUDIO_OBS_SEL_MASK (0x1f << TEGRA30_AHUB_MISC_CTRL_AUDIO_OBS_SEL_SHIFT)
+
+/* TEGRA30_AHUB_APBDMA_LIVE_STATUS */
+
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS 0x88
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_RX_CIF_FIFO_FULL (1 << 31)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_TX_CIF_FIFO_FULL (1 << 30)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_RX_CIF_FIFO_FULL (1 << 29)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_TX_CIF_FIFO_FULL (1 << 28)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_RX_CIF_FIFO_FULL (1 << 27)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_TX_CIF_FIFO_FULL (1 << 26)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_RX_CIF_FIFO_FULL (1 << 25)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_TX_CIF_FIFO_FULL (1 << 24)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_RX_CIF_FIFO_EMPTY (1 << 23)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_TX_CIF_FIFO_EMPTY (1 << 22)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_RX_CIF_FIFO_EMPTY (1 << 21)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_TX_CIF_FIFO_EMPTY (1 << 20)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_RX_CIF_FIFO_EMPTY (1 << 19)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_TX_CIF_FIFO_EMPTY (1 << 18)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_RX_CIF_FIFO_EMPTY (1 << 17)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_TX_CIF_FIFO_EMPTY (1 << 16)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_RX_DMA_FIFO_FULL (1 << 15)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_TX_DMA_FIFO_FULL (1 << 14)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_RX_DMA_FIFO_FULL (1 << 13)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_TX_DMA_FIFO_FULL (1 << 12)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_RX_DMA_FIFO_FULL (1 << 11)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_TX_DMA_FIFO_FULL (1 << 10)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_RX_DMA_FIFO_FULL (1 << 9)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_TX_DMA_FIFO_FULL (1 << 8)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_RX_DMA_FIFO_EMPTY (1 << 7)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_TX_DMA_FIFO_EMPTY (1 << 6)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_RX_DMA_FIFO_EMPTY (1 << 5)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_TX_DMA_FIFO_EMPTY (1 << 4)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_RX_DMA_FIFO_EMPTY (1 << 3)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_TX_DMA_FIFO_EMPTY (1 << 2)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_RX_DMA_FIFO_EMPTY (1 << 1)
+#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_TX_DMA_FIFO_EMPTY (1 << 0)
+
+/* TEGRA30_AHUB_I2S_LIVE_STATUS */
+
+#define TEGRA30_AHUB_I2S_LIVE_STATUS 0x8c
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S4_RX_FIFO_FULL (1 << 29)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S4_TX_FIFO_FULL (1 << 28)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S3_RX_FIFO_FULL (1 << 27)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S3_TX_FIFO_FULL (1 << 26)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S2_RX_FIFO_FULL (1 << 25)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S2_TX_FIFO_FULL (1 << 24)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S1_RX_FIFO_FULL (1 << 23)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S1_TX_FIFO_FULL (1 << 22)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_RX_FIFO_FULL (1 << 21)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_TX_FIFO_FULL (1 << 20)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S4_RX_FIFO_ENABLED (1 << 19)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S4_TX_FIFO_ENABLED (1 << 18)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S3_RX_FIFO_ENABLED (1 << 17)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S3_TX_FIFO_ENABLED (1 << 16)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S2_RX_FIFO_ENABLED (1 << 15)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S2_TX_FIFO_ENABLED (1 << 14)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S1_RX_FIFO_ENABLED (1 << 13)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S1_TX_FIFO_ENABLED (1 << 12)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_RX_FIFO_ENABLED (1 << 11)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_TX_FIFO_ENABLED (1 << 10)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S4_RX_FIFO_EMPTY (1 << 9)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S4_TX_FIFO_EMPTY (1 << 8)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S3_RX_FIFO_EMPTY (1 << 7)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S3_TX_FIFO_EMPTY (1 << 6)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S2_RX_FIFO_EMPTY (1 << 5)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S2_TX_FIFO_EMPTY (1 << 4)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S1_RX_FIFO_EMPTY (1 << 3)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S1_TX_FIFO_EMPTY (1 << 2)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_RX_FIFO_EMPTY (1 << 1)
+#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_TX_FIFO_EMPTY (1 << 0)
+
+/* TEGRA30_AHUB_DAM0_LIVE_STATUS */
+
+#define TEGRA30_AHUB_DAM_LIVE_STATUS 0x90
+#define TEGRA30_AHUB_DAM_LIVE_STATUS_STRIDE 0x8
+#define TEGRA30_AHUB_DAM_LIVE_STATUS_COUNT 3
+#define TEGRA30_AHUB_DAM_LIVE_STATUS_TX_ENABLED (1 << 26)
+#define TEGRA30_AHUB_DAM_LIVE_STATUS_RX1_ENABLED (1 << 25)
+#define TEGRA30_AHUB_DAM_LIVE_STATUS_RX0_ENABLED (1 << 24)
+#define TEGRA30_AHUB_DAM_LIVE_STATUS_TXFIFO_FULL (1 << 15)
+#define TEGRA30_AHUB_DAM_LIVE_STATUS_RX1FIFO_FULL (1 << 9)
+#define TEGRA30_AHUB_DAM_LIVE_STATUS_RX0FIFO_FULL (1 << 8)
+#define TEGRA30_AHUB_DAM_LIVE_STATUS_TXFIFO_EMPTY (1 << 7)
+#define TEGRA30_AHUB_DAM_LIVE_STATUS_RX1FIFO_EMPTY (1 << 1)
+#define TEGRA30_AHUB_DAM_LIVE_STATUS_RX0FIFO_EMPTY (1 << 0)
+
+/* TEGRA30_AHUB_SPDIF_LIVE_STATUS */
+
+#define TEGRA30_AHUB_SPDIF_LIVE_STATUS 0xa8
+#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_USER_TX_ENABLED (1 << 11)
+#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_USER_RX_ENABLED (1 << 10)
+#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_DATA_TX_ENABLED (1 << 9)
+#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_DATA_RX_ENABLED (1 << 8)
+#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_USER_TXFIFO_FULL (1 << 7)
+#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_USER_RXFIFO_FULL (1 << 6)
+#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_DATA_TXFIFO_FULL (1 << 5)
+#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_DATA_RXFIFO_FULL (1 << 4)
+#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_USER_TXFIFO_EMPTY (1 << 3)
+#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_USER_RXFIFO_EMPTY (1 << 2)
+#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_DATA_TXFIFO_EMPTY (1 << 1)
+#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_DATA_RXFIFO_EMPTY (1 << 0)
+
+/* TEGRA30_AHUB_I2S_INT_MASK */
+
+#define TEGRA30_AHUB_I2S_INT_MASK 0xb0
+
+/* TEGRA30_AHUB_DAM_INT_MASK */
+
+#define TEGRA30_AHUB_DAM_INT_MASK 0xb4
+
+/* TEGRA30_AHUB_SPDIF_INT_MASK */
+
+#define TEGRA30_AHUB_SPDIF_INT_MASK 0xbc
+
+/* TEGRA30_AHUB_APBIF_INT_MASK */
+
+#define TEGRA30_AHUB_APBIF_INT_MASK 0xc0
+
+/* TEGRA30_AHUB_I2S_INT_STATUS */
+
+#define TEGRA30_AHUB_I2S_INT_STATUS 0xc8
+
+/* TEGRA30_AHUB_DAM_INT_STATUS */
+
+#define TEGRA30_AHUB_DAM_INT_STATUS 0xcc
+
+/* TEGRA30_AHUB_SPDIF_INT_STATUS */
+
+#define TEGRA30_AHUB_SPDIF_INT_STATUS 0xd4
+
+/* TEGRA30_AHUB_APBIF_INT_STATUS */
+
+#define TEGRA30_AHUB_APBIF_INT_STATUS 0xd8
+
+/* TEGRA30_AHUB_I2S_INT_SOURCE */
+
+#define TEGRA30_AHUB_I2S_INT_SOURCE 0xe0
+
+/* TEGRA30_AHUB_DAM_INT_SOURCE */
+
+#define TEGRA30_AHUB_DAM_INT_SOURCE 0xe4
+
+/* TEGRA30_AHUB_SPDIF_INT_SOURCE */
+
+#define TEGRA30_AHUB_SPDIF_INT_SOURCE 0xec
+
+/* TEGRA30_AHUB_APBIF_INT_SOURCE */
+
+#define TEGRA30_AHUB_APBIF_INT_SOURCE 0xf0
+
+/* TEGRA30_AHUB_I2S_INT_SET */
+
+#define TEGRA30_AHUB_I2S_INT_SET 0xf8
+
+/* TEGRA30_AHUB_DAM_INT_SET */
+
+#define TEGRA30_AHUB_DAM_INT_SET 0xfc
+
+/* TEGRA30_AHUB_SPDIF_INT_SET */
+
+#define TEGRA30_AHUB_SPDIF_INT_SET 0x100
+
+/* TEGRA30_AHUB_APBIF_INT_SET */
+
+#define TEGRA30_AHUB_APBIF_INT_SET 0x104
+
+/* Registers within TEGRA30_AHUB_BASE */
+
+#define TEGRA30_AHUB_AUDIO_RX 0x0
+#define TEGRA30_AHUB_AUDIO_RX_STRIDE 0x4
+#define TEGRA30_AHUB_AUDIO_RX_COUNT 17
+/* This register repeats once for each entry in enum tegra30_ahub_rxcif */
+/* The fields in this register are 1 bit per entry in tegra30_ahub_txcif */
+
+/*
+ * Terminology:
+ * AHUB: Audio Hub; a cross-bar switch between the audio devices: DMA FIFOs,
+ * I2S controllers, SPDIF controllers, and DAMs.
+ * XBAR: The core cross-bar component of the AHUB.
+ * CIF: Client Interface; the HW module connecting an audio device to the
+ * XBAR.
+ * DAM: Digital Audio Mixer: A HW module that mixes multiple audio streams,
+ * possibly including sample-rate conversion.
+ *
+ * Each TX CIF transmits data into the XBAR. Each RX CIF can receive audio
+ * transmitted by a particular TX CIF.
+ *
+ * This driver is currently very simplistic; many HW features are not
+ * exposed; DAMs are not supported, only 16-bit stereo audio is supported,
+ * etc.
+ */
+
+enum tegra30_ahub_txcif {
+ TEGRA30_AHUB_TXCIF_APBIF_TX0,
+ TEGRA30_AHUB_TXCIF_APBIF_TX1,
+ TEGRA30_AHUB_TXCIF_APBIF_TX2,
+ TEGRA30_AHUB_TXCIF_APBIF_TX3,
+ TEGRA30_AHUB_TXCIF_I2S0_TX0,
+ TEGRA30_AHUB_TXCIF_I2S1_TX0,
+ TEGRA30_AHUB_TXCIF_I2S2_TX0,
+ TEGRA30_AHUB_TXCIF_I2S3_TX0,
+ TEGRA30_AHUB_TXCIF_I2S4_TX0,
+ TEGRA30_AHUB_TXCIF_DAM0_TX0,
+ TEGRA30_AHUB_TXCIF_DAM1_TX0,
+ TEGRA30_AHUB_TXCIF_DAM2_TX0,
+ TEGRA30_AHUB_TXCIF_SPDIF_TX0,
+ TEGRA30_AHUB_TXCIF_SPDIF_TX1,
+};
+
+enum tegra30_ahub_rxcif {
+ TEGRA30_AHUB_RXCIF_APBIF_RX0,
+ TEGRA30_AHUB_RXCIF_APBIF_RX1,
+ TEGRA30_AHUB_RXcIF_APBIF_RX2,
+ TEGRA30_AHUB_RXCIF_APBIF_RX3,
+ TEGRA30_AHUB_RXCIF_I2S0_RX0,
+ TEGRA30_AHUB_RXCIF_I2S1_RX0,
+ TEGRA30_AHUB_RXCIF_I2S2_RX0,
+ TEGRA30_AHUB_RXCIF_I2S3_RX0,
+ TEGRA30_AHUB_RXCIF_I2S4_RX0,
+ TEGRA30_AHUB_RXCIF_DAM0_RX0,
+ TEGRA30_AHUB_RXCIF_DAM0_RX1,
+ TEGRA30_AHUB_RXCIF_DAM1_RX0,
+ TEGRA30_AHUB_RXCIF_DAM2_RX1,
+ TEGRA30_AHUB_RXCIF_DAM3_RX0,
+ TEGRA30_AHUB_RXCIF_DAM3_RX1,
+ TEGRA30_AHUB_RXCIF_SPDIF_RX0,
+ TEGRA30_AHUB_RXCIF_SPDIF_RX1,
+};
+
+extern int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
+ unsigned long *fiforeg,
+ unsigned long *reqsel);
+extern int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif);
+extern int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif);
+extern int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif);
+
+extern int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
+ unsigned long *fiforeg,
+ unsigned long *reqsel);
+extern int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif);
+extern int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif);
+extern int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif);
+
+extern int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif,
+ enum tegra30_ahub_txcif txcif);
+extern int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif);
+
+struct tegra30_ahub {
+ struct device *dev;
+ struct clk *clk_d_audio;
+ struct clk *clk_apbif;
+ int dma_sel;
+ resource_size_t apbif_addr;
+ struct regmap *regmap_apbif;
+ struct regmap *regmap_ahub;
+ DECLARE_BITMAP(rx_usage, TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
+ DECLARE_BITMAP(tx_usage, TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
+};
+
+#endif
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
new file mode 100644
index 000000000000..8596032985dc
--- /dev/null
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -0,0 +1,536 @@
+/*
+ * tegra30_i2s.c - Tegra30 I2S driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Based on code copyright/by:
+ *
+ * Copyright (c) 2009-2010, NVIDIA Corporation.
+ * Scott Peterson <speterson@nvidia.com>
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Iliyan Malchev <malchev@google.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra30_ahub.h"
+#include "tegra30_i2s.h"
+
+#define DRV_NAME "tegra30-i2s"
+
+static inline void tegra30_i2s_write(struct tegra30_i2s *i2s, u32 reg, u32 val)
+{
+ regmap_write(i2s->regmap, reg, val);
+}
+
+static inline u32 tegra30_i2s_read(struct tegra30_i2s *i2s, u32 reg)
+{
+ u32 val;
+ regmap_read(i2s->regmap, reg, &val);
+ return val;
+}
+
+static int tegra30_i2s_runtime_suspend(struct device *dev)
+{
+ struct tegra30_i2s *i2s = dev_get_drvdata(dev);
+
+ regcache_cache_only(i2s->regmap, true);
+
+ clk_disable(i2s->clk_i2s);
+
+ return 0;
+}
+
+static int tegra30_i2s_runtime_resume(struct device *dev)
+{
+ struct tegra30_i2s *i2s = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_enable(i2s->clk_i2s);
+ if (ret) {
+ dev_err(dev, "clk_enable failed: %d\n", ret);
+ return ret;
+ }
+
+ regcache_cache_only(i2s->regmap, false);
+
+ return 0;
+}
+
+int tegra30_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+ int ret;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ ret = tegra30_ahub_allocate_tx_fifo(&i2s->playback_fifo_cif,
+ &i2s->playback_dma_data.addr,
+ &i2s->playback_dma_data.req_sel);
+ i2s->playback_dma_data.wrap = 4;
+ i2s->playback_dma_data.width = 32;
+ tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif,
+ i2s->playback_fifo_cif);
+ } else {
+ ret = tegra30_ahub_allocate_rx_fifo(&i2s->capture_fifo_cif,
+ &i2s->capture_dma_data.addr,
+ &i2s->capture_dma_data.req_sel);
+ i2s->capture_dma_data.wrap = 4;
+ i2s->capture_dma_data.width = 32;
+ tegra30_ahub_set_rx_cif_source(i2s->capture_fifo_cif,
+ i2s->capture_i2s_cif);
+ }
+
+ return ret;
+}
+
+void tegra30_i2s_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ tegra30_ahub_unset_rx_cif_source(i2s->playback_i2s_cif);
+ tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif);
+ } else {
+ tegra30_ahub_unset_rx_cif_source(i2s->capture_fifo_cif);
+ tegra30_ahub_free_rx_fifo(i2s->capture_fifo_cif);
+ }
+}
+
+static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
+ unsigned int fmt)
+{
+ struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_MASTER_ENABLE;
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ i2s->reg_ctrl &= ~(TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
+ TEGRA30_I2S_CTRL_LRCK_MASK);
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct device *dev = substream->pcm->card->dev;
+ struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+ u32 val;
+ int ret, sample_size, srate, i2sclock, bitcnt;
+
+ if (params_channels(params) != 2)
+ return -EINVAL;
+
+ i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_BIT_SIZE_MASK;
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_16;
+ sample_size = 16;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ srate = params_rate(params);
+
+ /* Final "* 2" required by Tegra hardware */
+ i2sclock = srate * params_channels(params) * sample_size * 2;
+
+ bitcnt = (i2sclock / (2 * srate)) - 1;
+ if (bitcnt < 0 || bitcnt > TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US)
+ return -EINVAL;
+
+ ret = clk_set_rate(i2s->clk_i2s, i2sclock);
+ if (ret) {
+ dev_err(dev, "Can't set I2S clock rate: %d\n", ret);
+ return ret;
+ }
+
+ val = bitcnt << TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
+
+ if (i2sclock % (2 * srate))
+ val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
+
+ tegra30_i2s_write(i2s, TEGRA30_I2S_TIMING, val);
+
+ val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
+ (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
+ (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
+ TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
+ TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
+ tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_RX_CTRL, val);
+ } else {
+ val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
+ tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_TX_CTRL, val);
+ }
+
+ val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
+ (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
+ tegra30_i2s_write(i2s, TEGRA30_I2S_OFFSET, val);
+
+ return 0;
+}
+
+static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s)
+{
+ tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif);
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
+ tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
+}
+
+static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s)
+{
+ tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif);
+ i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
+ tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
+}
+
+static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s)
+{
+ tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif);
+ i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX;
+ tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
+}
+
+static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s)
+{
+ tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif);
+ i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
+ tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
+}
+
+static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tegra30_i2s_start_playback(i2s);
+ else
+ tegra30_i2s_start_capture(i2s);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tegra30_i2s_stop_playback(i2s);
+ else
+ tegra30_i2s_stop_capture(i2s);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tegra30_i2s_probe(struct snd_soc_dai *dai)
+{
+ struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+ dai->capture_dma_data = &i2s->capture_dma_data;
+ dai->playback_dma_data = &i2s->playback_dma_data;
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops tegra30_i2s_dai_ops = {
+ .startup = tegra30_i2s_startup,
+ .shutdown = tegra30_i2s_shutdown,
+ .set_fmt = tegra30_i2s_set_fmt,
+ .hw_params = tegra30_i2s_hw_params,
+ .trigger = tegra30_i2s_trigger,
+};
+
+static const struct snd_soc_dai_driver tegra30_i2s_dai_template = {
+ .probe = tegra30_i2s_probe,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .ops = &tegra30_i2s_dai_ops,
+ .symmetric_rates = 1,
+};
+
+static bool tegra30_i2s_wr_rd_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA30_I2S_CTRL:
+ case TEGRA30_I2S_TIMING:
+ case TEGRA30_I2S_OFFSET:
+ case TEGRA30_I2S_CH_CTRL:
+ case TEGRA30_I2S_SLOT_CTRL:
+ case TEGRA30_I2S_CIF_RX_CTRL:
+ case TEGRA30_I2S_CIF_TX_CTRL:
+ case TEGRA30_I2S_FLOWCTL:
+ case TEGRA30_I2S_TX_STEP:
+ case TEGRA30_I2S_FLOW_STATUS:
+ case TEGRA30_I2S_FLOW_TOTAL:
+ case TEGRA30_I2S_FLOW_OVER:
+ case TEGRA30_I2S_FLOW_UNDER:
+ case TEGRA30_I2S_LCOEF_1_4_0:
+ case TEGRA30_I2S_LCOEF_1_4_1:
+ case TEGRA30_I2S_LCOEF_1_4_2:
+ case TEGRA30_I2S_LCOEF_1_4_3:
+ case TEGRA30_I2S_LCOEF_1_4_4:
+ case TEGRA30_I2S_LCOEF_1_4_5:
+ case TEGRA30_I2S_LCOEF_2_4_0:
+ case TEGRA30_I2S_LCOEF_2_4_1:
+ case TEGRA30_I2S_LCOEF_2_4_2:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static bool tegra30_i2s_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA30_I2S_FLOW_STATUS:
+ case TEGRA30_I2S_FLOW_TOTAL:
+ case TEGRA30_I2S_FLOW_OVER:
+ case TEGRA30_I2S_FLOW_UNDER:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static const struct regmap_config tegra30_i2s_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = TEGRA30_I2S_LCOEF_2_4_2,
+ .writeable_reg = tegra30_i2s_wr_rd_reg,
+ .readable_reg = tegra30_i2s_wr_rd_reg,
+ .volatile_reg = tegra30_i2s_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static __devinit int tegra30_i2s_platform_probe(struct platform_device *pdev)
+{
+ struct tegra30_i2s *i2s;
+ u32 cif_ids[2];
+ struct resource *mem, *memregion;
+ void __iomem *regs;
+ int ret;
+
+ i2s = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_i2s), GFP_KERNEL);
+ if (!i2s) {
+ dev_err(&pdev->dev, "Can't allocate tegra30_i2s\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ dev_set_drvdata(&pdev->dev, i2s);
+
+ i2s->dai = tegra30_i2s_dai_template;
+ i2s->dai.name = dev_name(&pdev->dev);
+
+ ret = of_property_read_u32_array(pdev->dev.of_node,
+ "nvidia,ahub-cif-ids", cif_ids,
+ ARRAY_SIZE(cif_ids));
+ if (ret < 0)
+ goto err;
+
+ i2s->playback_i2s_cif = cif_ids[0];
+ i2s->capture_i2s_cif = cif_ids[1];
+
+ i2s->clk_i2s = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(i2s->clk_i2s)) {
+ dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
+ ret = PTR_ERR(i2s->clk_i2s);
+ goto err;
+ }
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "No memory resource\n");
+ ret = -ENODEV;
+ goto err_clk_put;
+ }
+
+ memregion = devm_request_mem_region(&pdev->dev, mem->start,
+ resource_size(mem), DRV_NAME);
+ if (!memregion) {
+ dev_err(&pdev->dev, "Memory region already claimed\n");
+ ret = -EBUSY;
+ goto err_clk_put;
+ }
+
+ regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+ if (!regs) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto err_clk_put;
+ }
+
+ i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
+ &tegra30_i2s_regmap_config);
+ if (IS_ERR(i2s->regmap)) {
+ dev_err(&pdev->dev, "regmap init failed\n");
+ ret = PTR_ERR(i2s->regmap);
+ goto err_clk_put;
+ }
+ regcache_cache_only(i2s->regmap, true);
+
+ pm_runtime_enable(&pdev->dev);
+ if (!pm_runtime_enabled(&pdev->dev)) {
+ ret = tegra30_i2s_runtime_resume(&pdev->dev);
+ if (ret)
+ goto err_pm_disable;
+ }
+
+ ret = snd_soc_register_dai(&pdev->dev, &i2s->dai);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
+ ret = -ENOMEM;
+ goto err_suspend;
+ }
+
+ ret = tegra_pcm_platform_register(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
+ goto err_unregister_dai;
+ }
+
+ return 0;
+
+err_unregister_dai:
+ snd_soc_unregister_dai(&pdev->dev);
+err_suspend:
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ tegra30_i2s_runtime_suspend(&pdev->dev);
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+err_clk_put:
+ clk_put(i2s->clk_i2s);
+err:
+ return ret;
+}
+
+static int __devexit tegra30_i2s_platform_remove(struct platform_device *pdev)
+{
+ struct tegra30_i2s *i2s = dev_get_drvdata(&pdev->dev);
+
+ pm_runtime_disable(&pdev->dev);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ tegra30_i2s_runtime_suspend(&pdev->dev);
+
+ tegra_pcm_platform_unregister(&pdev->dev);
+ snd_soc_unregister_dai(&pdev->dev);
+
+ clk_put(i2s->clk_i2s);
+
+ return 0;
+}
+
+static const struct of_device_id tegra30_i2s_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra30-i2s", },
+ {},
+};
+
+static const struct dev_pm_ops tegra30_i2s_pm_ops __devinitconst = {
+ SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend,
+ tegra30_i2s_runtime_resume, NULL)
+};
+
+static struct platform_driver tegra30_i2s_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = tegra30_i2s_of_match,
+ .pm = &tegra30_i2s_pm_ops,
+ },
+ .probe = tegra30_i2s_platform_probe,
+ .remove = __devexit_p(tegra30_i2s_platform_remove),
+};
+module_platform_driver(tegra30_i2s_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra30 I2S ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra30_i2s_of_match);
diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h
new file mode 100644
index 000000000000..91adf29c7a87
--- /dev/null
+++ b/sound/soc/tegra/tegra30_i2s.h
@@ -0,0 +1,242 @@
+/*
+ * tegra30_i2s.h - Definitions for Tegra30 I2S driver
+ *
+ * Copyright (c) 2011,2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TEGRA30_I2S_H__
+#define __TEGRA30_I2S_H__
+
+#include "tegra_pcm.h"
+
+/* Register offsets from TEGRA30_I2S*_BASE */
+
+#define TEGRA30_I2S_CTRL 0x0
+#define TEGRA30_I2S_TIMING 0x4
+#define TEGRA30_I2S_OFFSET 0x08
+#define TEGRA30_I2S_CH_CTRL 0x0c
+#define TEGRA30_I2S_SLOT_CTRL 0x10
+#define TEGRA30_I2S_CIF_RX_CTRL 0x14
+#define TEGRA30_I2S_CIF_TX_CTRL 0x18
+#define TEGRA30_I2S_FLOWCTL 0x1c
+#define TEGRA30_I2S_TX_STEP 0x20
+#define TEGRA30_I2S_FLOW_STATUS 0x24
+#define TEGRA30_I2S_FLOW_TOTAL 0x28
+#define TEGRA30_I2S_FLOW_OVER 0x2c
+#define TEGRA30_I2S_FLOW_UNDER 0x30
+#define TEGRA30_I2S_LCOEF_1_4_0 0x34
+#define TEGRA30_I2S_LCOEF_1_4_1 0x38
+#define TEGRA30_I2S_LCOEF_1_4_2 0x3c
+#define TEGRA30_I2S_LCOEF_1_4_3 0x40
+#define TEGRA30_I2S_LCOEF_1_4_4 0x44
+#define TEGRA30_I2S_LCOEF_1_4_5 0x48
+#define TEGRA30_I2S_LCOEF_2_4_0 0x4c
+#define TEGRA30_I2S_LCOEF_2_4_1 0x50
+#define TEGRA30_I2S_LCOEF_2_4_2 0x54
+
+/* Fields in TEGRA30_I2S_CTRL */
+
+#define TEGRA30_I2S_CTRL_XFER_EN_TX (1 << 31)
+#define TEGRA30_I2S_CTRL_XFER_EN_RX (1 << 30)
+#define TEGRA30_I2S_CTRL_CG_EN (1 << 29)
+#define TEGRA30_I2S_CTRL_SOFT_RESET (1 << 28)
+#define TEGRA30_I2S_CTRL_TX_FLOWCTL_EN (1 << 27)
+
+#define TEGRA30_I2S_CTRL_OBS_SEL_SHIFT 24
+#define TEGRA30_I2S_CTRL_OBS_SEL_MASK (7 << TEGRA30_I2S_CTRL_OBS_SEL_SHIFT)
+
+#define TEGRA30_I2S_FRAME_FORMAT_LRCK 0
+#define TEGRA30_I2S_FRAME_FORMAT_FSYNC 1
+
+#define TEGRA30_I2S_CTRL_FRAME_FORMAT_SHIFT 12
+#define TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK (7 << TEGRA30_I2S_CTRL_FRAME_FORMAT_SHIFT)
+#define TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK (TEGRA30_I2S_FRAME_FORMAT_LRCK << TEGRA30_I2S_CTRL_FRAME_FORMAT_SHIFT)
+#define TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC (TEGRA30_I2S_FRAME_FORMAT_FSYNC << TEGRA30_I2S_CTRL_FRAME_FORMAT_SHIFT)
+
+#define TEGRA30_I2S_CTRL_MASTER_ENABLE (1 << 10)
+
+#define TEGRA30_I2S_LRCK_LEFT_LOW 0
+#define TEGRA30_I2S_LRCK_RIGHT_LOW 1
+
+#define TEGRA30_I2S_CTRL_LRCK_SHIFT 9
+#define TEGRA30_I2S_CTRL_LRCK_MASK (1 << TEGRA30_I2S_CTRL_LRCK_SHIFT)
+#define TEGRA30_I2S_CTRL_LRCK_L_LOW (TEGRA30_I2S_LRCK_LEFT_LOW << TEGRA30_I2S_CTRL_LRCK_SHIFT)
+#define TEGRA30_I2S_CTRL_LRCK_R_LOW (TEGRA30_I2S_LRCK_RIGHT_LOW << TEGRA30_I2S_CTRL_LRCK_SHIFT)
+
+#define TEGRA30_I2S_CTRL_LPBK_ENABLE (1 << 8)
+
+#define TEGRA30_I2S_BIT_CODE_LINEAR 0
+#define TEGRA30_I2S_BIT_CODE_ULAW 1
+#define TEGRA30_I2S_BIT_CODE_ALAW 2
+
+#define TEGRA30_I2S_CTRL_BIT_CODE_SHIFT 4
+#define TEGRA30_I2S_CTRL_BIT_CODE_MASK (3 << TEGRA30_I2S_CTRL_BIT_CODE_SHIFT)
+#define TEGRA30_I2S_CTRL_BIT_CODE_LINEAR (TEGRA30_I2S_BIT_CODE_LINEAR << TEGRA30_I2S_CTRL_BIT_CODE_SHIFT)
+#define TEGRA30_I2S_CTRL_BIT_CODE_ULAW (TEGRA30_I2S_BIT_CODE_ULAW << TEGRA30_I2S_CTRL_BIT_CODE_SHIFT)
+#define TEGRA30_I2S_CTRL_BIT_CODE_ALAW (TEGRA30_I2S_BIT_CODE_ALAW << TEGRA30_I2S_CTRL_BIT_CODE_SHIFT)
+
+#define TEGRA30_I2S_BITS_8 1
+#define TEGRA30_I2S_BITS_12 2
+#define TEGRA30_I2S_BITS_16 3
+#define TEGRA30_I2S_BITS_20 4
+#define TEGRA30_I2S_BITS_24 5
+#define TEGRA30_I2S_BITS_28 6
+#define TEGRA30_I2S_BITS_32 7
+
+/* Sample container size; see {RX,TX}_MASK field in CH_CTRL below */
+#define TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT 0
+#define TEGRA30_I2S_CTRL_BIT_SIZE_MASK (7 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA30_I2S_CTRL_BIT_SIZE_8 (TEGRA30_I2S_BITS_8 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA30_I2S_CTRL_BIT_SIZE_12 (TEGRA30_I2S_BITS_12 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA30_I2S_CTRL_BIT_SIZE_16 (TEGRA30_I2S_BITS_16 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA30_I2S_CTRL_BIT_SIZE_20 (TEGRA30_I2S_BITS_20 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA30_I2S_CTRL_BIT_SIZE_24 (TEGRA30_I2S_BITS_24 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA30_I2S_CTRL_BIT_SIZE_28 (TEGRA30_I2S_BITS_28 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA30_I2S_CTRL_BIT_SIZE_32 (TEGRA30_I2S_BITS_32 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
+
+/* Fields in TEGRA30_I2S_TIMING */
+
+#define TEGRA30_I2S_TIMING_NON_SYM_ENABLE (1 << 12)
+#define TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT 0
+#define TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US 0x7fff
+#define TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_MASK (TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US << TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT)
+
+/* Fields in TEGRA30_I2S_OFFSET */
+
+#define TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT 16
+#define TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_MASK_US 0x7ff
+#define TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_MASK (TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_MASK_US << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT)
+#define TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT 0
+#define TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_MASK_US 0x7ff
+#define TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_MASK (TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_MASK_US << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT)
+
+/* Fields in TEGRA30_I2S_CH_CTRL */
+
+/* (FSYNC width - 1) in bit clocks */
+#define TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_SHIFT 24
+#define TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_MASK_US 0xff
+#define TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_MASK (TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_MASK_US << TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_SHIFT)
+
+#define TEGRA30_I2S_HIGHZ_NO 0
+#define TEGRA30_I2S_HIGHZ_YES 1
+#define TEGRA30_I2S_HIGHZ_ON_HALF_BIT_CLK 2
+
+#define TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_SHIFT 12
+#define TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_MASK (3 << TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_SHIFT)
+#define TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_NO (TEGRA30_I2S_HIGHZ_NO << TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_SHIFT)
+#define TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_YES (TEGRA30_I2S_HIGHZ_YES << TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_SHIFT)
+#define TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_ON_HALF_BIT_CLK (TEGRA30_I2S_HIGHZ_ON_HALF_BIT_CLK << TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_SHIFT)
+
+#define TEGRA30_I2S_MSB_FIRST 0
+#define TEGRA30_I2S_LSB_FIRST 1
+
+#define TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_SHIFT 10
+#define TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_MASK (1 << TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_SHIFT)
+#define TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_MSB_FIRST (TEGRA30_I2S_MSB_FIRST << TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_SHIFT)
+#define TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_LSB_FIRST (TEGRA30_I2S_LSB_FIRST << TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_SHIFT)
+#define TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_SHIFT 9
+#define TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_MASK (1 << TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_SHIFT)
+#define TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_MSB_FIRST (TEGRA30_I2S_MSB_FIRST << TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_SHIFT)
+#define TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_LSB_FIRST (TEGRA30_I2S_LSB_FIRST << TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_SHIFT)
+
+#define TEGRA30_I2S_POS_EDGE 0
+#define TEGRA30_I2S_NEG_EDGE 1
+
+#define TEGRA30_I2S_CH_CTRL_EGDE_CTRL_SHIFT 8
+#define TEGRA30_I2S_CH_CTRL_EGDE_CTRL_MASK (1 << TEGRA30_I2S_CH_CTRL_EGDE_CTRL_SHIFT)
+#define TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE (TEGRA30_I2S_POS_EDGE << TEGRA30_I2S_CH_CTRL_EGDE_CTRL_SHIFT)
+#define TEGRA30_I2S_CH_CTRL_EGDE_CTRL_NEG_EDGE (TEGRA30_I2S_NEG_EDGE << TEGRA30_I2S_CH_CTRL_EGDE_CTRL_SHIFT)
+
+/* Sample size is # bits from BIT_SIZE minus this field */
+#define TEGRA30_I2S_CH_CTRL_RX_MASK_BITS_SHIFT 4
+#define TEGRA30_I2S_CH_CTRL_RX_MASK_BITS_MASK_US 7
+#define TEGRA30_I2S_CH_CTRL_RX_MASK_BITS_MASK (TEGRA30_I2S_CH_CTRL_RX_MASK_BITS_MASK_US << TEGRA30_I2S_CH_CTRL_RX_MASK_BITS_SHIFT)
+
+#define TEGRA30_I2S_CH_CTRL_TX_MASK_BITS_SHIFT 0
+#define TEGRA30_I2S_CH_CTRL_TX_MASK_BITS_MASK_US 7
+#define TEGRA30_I2S_CH_CTRL_TX_MASK_BITS_MASK (TEGRA30_I2S_CH_CTRL_TX_MASK_BITS_MASK_US << TEGRA30_I2S_CH_CTRL_TX_MASK_BITS_SHIFT)
+
+/* Fields in TEGRA30_I2S_SLOT_CTRL */
+
+/* Number of slots in frame, minus 1 */
+#define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT 16
+#define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK_US 7
+#define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK (TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOT_MASK_US << TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOT_SHIFT)
+
+/* TDM mode slot enable bitmask */
+#define TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT 8
+#define TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_MASK (0xff << TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT)
+
+#define TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_SHIFT 0
+#define TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_MASK (0xff << TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_SHIFT)
+
+/* Fields in TEGRA30_I2S_CIF_RX_CTRL */
+/* Uses field from TEGRA30_AUDIOCIF_CTRL_* in tegra30_ahub.h */
+
+/* Fields in TEGRA30_I2S_CIF_TX_CTRL */
+/* Uses field from TEGRA30_AUDIOCIF_CTRL_* in tegra30_ahub.h */
+
+/* Fields in TEGRA30_I2S_FLOWCTL */
+
+#define TEGRA30_I2S_FILTER_LINEAR 0
+#define TEGRA30_I2S_FILTER_QUAD 1
+
+#define TEGRA30_I2S_FLOWCTL_FILTER_SHIFT 31
+#define TEGRA30_I2S_FLOWCTL_FILTER_MASK (1 << TEGRA30_I2S_FLOWCTL_FILTER_SHIFT)
+#define TEGRA30_I2S_FLOWCTL_FILTER_LINEAR (TEGRA30_I2S_FILTER_LINEAR << TEGRA30_I2S_FLOWCTL_FILTER_SHIFT)
+#define TEGRA30_I2S_FLOWCTL_FILTER_QUAD (TEGRA30_I2S_FILTER_QUAD << TEGRA30_I2S_FLOWCTL_FILTER_SHIFT)
+
+/* Fields in TEGRA30_I2S_TX_STEP */
+
+#define TEGRA30_I2S_TX_STEP_SHIFT 0
+#define TEGRA30_I2S_TX_STEP_MASK_US 0xffff
+#define TEGRA30_I2S_TX_STEP_MASK (TEGRA30_I2S_TX_STEP_MASK_US << TEGRA30_I2S_TX_STEP_SHIFT)
+
+/* Fields in TEGRA30_I2S_FLOW_STATUS */
+
+#define TEGRA30_I2S_FLOW_STATUS_UNDERFLOW (1 << 31)
+#define TEGRA30_I2S_FLOW_STATUS_OVERFLOW (1 << 30)
+#define TEGRA30_I2S_FLOW_STATUS_MONITOR_INT_EN (1 << 4)
+#define TEGRA30_I2S_FLOW_STATUS_COUNTER_CLR (1 << 3)
+#define TEGRA30_I2S_FLOW_STATUS_MONITOR_CLR (1 << 2)
+#define TEGRA30_I2S_FLOW_STATUS_COUNTER_EN (1 << 1)
+#define TEGRA30_I2S_FLOW_STATUS_MONITOR_EN (1 << 0)
+
+/*
+ * There are no fields in TEGRA30_I2S_FLOW_TOTAL, TEGRA30_I2S_FLOW_OVER,
+ * TEGRA30_I2S_FLOW_UNDER; they are counters taking the whole register.
+ */
+
+/* Fields in TEGRA30_I2S_LCOEF_* */
+
+#define TEGRA30_I2S_LCOEF_COEF_SHIFT 0
+#define TEGRA30_I2S_LCOEF_COEF_MASK_US 0xffff
+#define TEGRA30_I2S_LCOEF_COEF_MASK (TEGRA30_I2S_LCOEF_COEF_MASK_US << TEGRA30_I2S_LCOEF_COEF_SHIFT)
+
+struct tegra30_i2s {
+ struct snd_soc_dai_driver dai;
+ int cif_id;
+ struct clk *clk_i2s;
+ enum tegra30_ahub_txcif capture_i2s_cif;
+ enum tegra30_ahub_rxcif capture_fifo_cif;
+ struct tegra_pcm_dma_params capture_dma_data;
+ enum tegra30_ahub_rxcif playback_i2s_cif;
+ enum tegra30_ahub_txcif playback_fifo_cif;
+ struct tegra_pcm_dma_params playback_dma_data;
+ struct regmap *regmap;
+ u32 reg_ctrl;
+};
+
+#endif
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index e45ccd851f6a..32de7006daf0 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -1,16 +1,17 @@
/*
-* tegra_alc5632.c -- Toshiba AC100(PAZ00) machine ASoC driver
-*
-* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
-*
-* Authors: Leon Romanovsky <leon@leon.nu>
-* Andrey Danin <danindrey@mail.ru>
-* Marc Dietrich <marvin24@gmx.de>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License version 2 as
-* published by the Free Software Foundation.
-*/
+ * tegra_alc5632.c -- Toshiba AC100(PAZ00) machine ASoC driver
+ *
+ * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
+ * Copyright (C) 2012 - NVIDIA, Inc.
+ *
+ * Authors: Leon Romanovsky <leon@leon.nu>
+ * Andrey Danin <danindrey@mail.ru>
+ * Marc Dietrich <marvin24@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
#include <asm/mach-types.h>
@@ -28,9 +29,6 @@
#include "../codecs/alc5632.h"
-#include "tegra_das.h"
-#include "tegra_i2s.h"
-#include "tegra_pcm.h"
#include "tegra_asoc_utils.h"
#define DRV_NAME "tegra-alc5632"
@@ -39,7 +37,6 @@
struct tegra_alc5632 {
struct tegra_asoc_utils_data util_data;
- struct platform_device *pcm_dev;
int gpio_requested;
int gpio_hp_det;
};
@@ -140,7 +137,6 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
static struct snd_soc_dai_link tegra_alc5632_dai = {
.name = "ALC5632",
.stream_name = "ALC5632 PCM",
- .platform_name = "tegra-pcm-audio",
.codec_dai_name = "alc5632-hifi",
.init = tegra_alc5632_asoc_init,
.ops = &tegra_alc5632_asoc_ops,
@@ -179,8 +175,6 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, alc5632);
- alc5632->pcm_dev = ERR_PTR(-EINVAL);
-
if (!(pdev->dev.of_node)) {
dev_err(&pdev->dev, "Must be instantiated using device tree\n");
ret = -EINVAL;
@@ -214,18 +208,11 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
goto err;
}
- alc5632->pcm_dev = platform_device_register_simple(
- "tegra-pcm-audio", -1, NULL, 0);
- if (IS_ERR(alc5632->pcm_dev)) {
- dev_err(&pdev->dev,
- "Can't instantiate tegra-pcm-audio\n");
- ret = PTR_ERR(alc5632->pcm_dev);
- goto err;
- }
+ tegra_alc5632_dai.platform_of_node = tegra_alc5632_dai.cpu_dai_of_node;
ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev);
if (ret)
- goto err_unregister;
+ goto err;
ret = snd_soc_register_card(card);
if (ret) {
@@ -238,9 +225,6 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
err_fini_utils:
tegra_asoc_utils_fini(&alc5632->util_data);
-err_unregister:
- if (!IS_ERR(alc5632->pcm_dev))
- platform_device_unregister(alc5632->pcm_dev);
err:
return ret;
}
@@ -259,8 +243,6 @@ static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
snd_soc_unregister_card(card);
tegra_asoc_utils_fini(&machine->util_data);
- if (!IS_ERR(machine->pcm_dev))
- platform_device_unregister(machine->pcm_dev);
return 0;
}
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index f8428e410e05..9515ce58ea02 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -2,7 +2,7 @@
* tegra_asoc_utils.c - Harmony machine ASoC driver
*
* Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2010 - NVIDIA, Inc.
+ * Copyright (C) 2010,2012 - NVIDIA, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -25,6 +25,7 @@
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of.h>
#include "tegra_asoc_utils.h"
@@ -40,7 +41,10 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
case 22050:
case 44100:
case 88200:
- new_baseclock = 56448000;
+ if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
+ new_baseclock = 56448000;
+ else
+ new_baseclock = 564480000;
break;
case 8000:
case 16000:
@@ -48,7 +52,10 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
case 48000:
case 64000:
case 96000:
- new_baseclock = 73728000;
+ if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
+ new_baseclock = 73728000;
+ else
+ new_baseclock = 552960000;
break;
default:
return -EINVAL;
@@ -78,7 +85,7 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
return err;
}
- /* Don't set cdev1 rate; its locked to pll_a_out0 */
+ /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */
err = clk_enable(data->clk_pll_a);
if (err) {
@@ -112,6 +119,17 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
data->dev = dev;
+ if (of_machine_is_compatible("nvidia,tegra20"))
+ data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20;
+ else if (of_machine_is_compatible("nvidia,tegra30"))
+ data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30;
+ else if (!dev->of_node)
+ /* non-DT is always Tegra20 */
+ data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20;
+ else
+ /* DT boot, but unknown SoC */
+ return -EINVAL;
+
data->clk_pll_a = clk_get_sys(NULL, "pll_a");
if (IS_ERR(data->clk_pll_a)) {
dev_err(data->dev, "Can't retrieve clk pll_a\n");
@@ -126,15 +144,24 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
goto err_put_pll_a;
}
- data->clk_cdev1 = clk_get_sys(NULL, "cdev1");
+ if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
+ data->clk_cdev1 = clk_get_sys(NULL, "cdev1");
+ else
+ data->clk_cdev1 = clk_get_sys("extern1", NULL);
if (IS_ERR(data->clk_cdev1)) {
dev_err(data->dev, "Can't retrieve clk cdev1\n");
ret = PTR_ERR(data->clk_cdev1);
goto err_put_pll_a_out0;
}
+ ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100);
+ if (ret)
+ goto err_put_cdev1;
+
return 0;
+err_put_cdev1:
+ clk_put(data->clk_cdev1);
err_put_pll_a_out0:
clk_put(data->clk_pll_a_out0);
err_put_pll_a:
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
index 4818195da25c..44db1dbb8f21 100644
--- a/sound/soc/tegra/tegra_asoc_utils.h
+++ b/sound/soc/tegra/tegra_asoc_utils.h
@@ -2,7 +2,7 @@
* tegra_asoc_utils.h - Definitions for Tegra DAS driver
*
* Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2010 - NVIDIA, Inc.
+ * Copyright (C) 2010,2012 - NVIDIA, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -26,8 +26,14 @@
struct clk;
struct device;
+enum tegra_asoc_utils_soc {
+ TEGRA_ASOC_UTILS_SOC_TEGRA20,
+ TEGRA_ASOC_UTILS_SOC_TEGRA30,
+};
+
struct tegra_asoc_utils_data {
struct device *dev;
+ enum tegra_asoc_utils_soc soc;
struct clk *clk_pll_a;
struct clk *clk_pll_a_out0;
struct clk *clk_cdev1;
@@ -42,4 +48,3 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data);
#endif
-
diff --git a/sound/soc/tegra/tegra_das.c b/sound/soc/tegra/tegra_das.c
deleted file mode 100644
index 3b3c1ba4d235..000000000000
--- a/sound/soc/tegra/tegra_das.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * tegra_das.c - Tegra DAS driver
- *
- * Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2010 - NVIDIA, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/debugfs.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <mach/iomap.h>
-#include <sound/soc.h>
-#include "tegra_das.h"
-
-#define DRV_NAME "tegra-das"
-
-static struct tegra_das *das;
-
-static inline void tegra_das_write(u32 reg, u32 val)
-{
- __raw_writel(val, das->regs + reg);
-}
-
-static inline u32 tegra_das_read(u32 reg)
-{
- return __raw_readl(das->regs + reg);
-}
-
-int tegra_das_connect_dap_to_dac(int dap, int dac)
-{
- u32 addr;
- u32 reg;
-
- if (!das)
- return -ENODEV;
-
- addr = TEGRA_DAS_DAP_CTRL_SEL +
- (dap * TEGRA_DAS_DAP_CTRL_SEL_STRIDE);
- reg = dac << TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P;
-
- tegra_das_write(addr, reg);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(tegra_das_connect_dap_to_dac);
-
-int tegra_das_connect_dap_to_dap(int dap, int otherdap, int master,
- int sdata1rx, int sdata2rx)
-{
- u32 addr;
- u32 reg;
-
- if (!das)
- return -ENODEV;
-
- addr = TEGRA_DAS_DAP_CTRL_SEL +
- (dap * TEGRA_DAS_DAP_CTRL_SEL_STRIDE);
- reg = otherdap << TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P |
- !!sdata2rx << TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P |
- !!sdata1rx << TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P |
- !!master << TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P;
-
- tegra_das_write(addr, reg);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(tegra_das_connect_dap_to_dap);
-
-int tegra_das_connect_dac_to_dap(int dac, int dap)
-{
- u32 addr;
- u32 reg;
-
- if (!das)
- return -ENODEV;
-
- addr = TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL +
- (dac * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
- reg = dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P |
- dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P |
- dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P;
-
- tegra_das_write(addr, reg);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(tegra_das_connect_dac_to_dap);
-
-#ifdef CONFIG_DEBUG_FS
-static int tegra_das_show(struct seq_file *s, void *unused)
-{
- int i;
- u32 addr;
- u32 reg;
-
- for (i = 0; i < TEGRA_DAS_DAP_CTRL_SEL_COUNT; i++) {
- addr = TEGRA_DAS_DAP_CTRL_SEL +
- (i * TEGRA_DAS_DAP_CTRL_SEL_STRIDE);
- reg = tegra_das_read(addr);
- seq_printf(s, "TEGRA_DAS_DAP_CTRL_SEL[%d] = %08x\n", i, reg);
- }
-
- for (i = 0; i < TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_COUNT; i++) {
- addr = TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL +
- (i * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
- reg = tegra_das_read(addr);
- seq_printf(s, "TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL[%d] = %08x\n",
- i, reg);
- }
-
- return 0;
-}
-
-static int tegra_das_debug_open(struct inode *inode, struct file *file)
-{
- return single_open(file, tegra_das_show, inode->i_private);
-}
-
-static const struct file_operations tegra_das_debug_fops = {
- .open = tegra_das_debug_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static void tegra_das_debug_add(struct tegra_das *das)
-{
- das->debug = debugfs_create_file(DRV_NAME, S_IRUGO,
- snd_soc_debugfs_root, das,
- &tegra_das_debug_fops);
-}
-
-static void tegra_das_debug_remove(struct tegra_das *das)
-{
- if (das->debug)
- debugfs_remove(das->debug);
-}
-#else
-static inline void tegra_das_debug_add(struct tegra_das *das)
-{
-}
-
-static inline void tegra_das_debug_remove(struct tegra_das *das)
-{
-}
-#endif
-
-static int __devinit tegra_das_probe(struct platform_device *pdev)
-{
- struct resource *res, *region;
- int ret = 0;
-
- if (das)
- return -ENODEV;
-
- das = devm_kzalloc(&pdev->dev, sizeof(struct tegra_das), GFP_KERNEL);
- if (!das) {
- dev_err(&pdev->dev, "Can't allocate tegra_das\n");
- ret = -ENOMEM;
- goto err;
- }
- das->dev = &pdev->dev;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "No memory resource\n");
- ret = -ENODEV;
- goto err;
- }
-
- region = devm_request_mem_region(&pdev->dev, res->start,
- resource_size(res), pdev->name);
- if (!region) {
- dev_err(&pdev->dev, "Memory region already claimed\n");
- ret = -EBUSY;
- goto err;
- }
-
- das->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!das->regs) {
- dev_err(&pdev->dev, "ioremap failed\n");
- ret = -ENOMEM;
- goto err;
- }
-
- ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1,
- TEGRA_DAS_DAP_SEL_DAC1);
- if (ret) {
- dev_err(&pdev->dev, "Can't set up DAS DAP connection\n");
- goto err;
- }
- ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1,
- TEGRA_DAS_DAC_SEL_DAP1);
- if (ret) {
- dev_err(&pdev->dev, "Can't set up DAS DAC connection\n");
- goto err;
- }
-
- tegra_das_debug_add(das);
-
- platform_set_drvdata(pdev, das);
-
- return 0;
-
-err:
- das = NULL;
- return ret;
-}
-
-static int __devexit tegra_das_remove(struct platform_device *pdev)
-{
- if (!das)
- return -ENODEV;
-
- tegra_das_debug_remove(das);
-
- das = NULL;
-
- return 0;
-}
-
-static const struct of_device_id tegra_das_of_match[] __devinitconst = {
- { .compatible = "nvidia,tegra20-das", },
- {},
-};
-
-static struct platform_driver tegra_das_driver = {
- .probe = tegra_das_probe,
- .remove = __devexit_p(tegra_das_remove),
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- .of_match_table = tegra_das_of_match,
- },
-};
-module_platform_driver(tegra_das_driver);
-
-MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
-MODULE_DESCRIPTION("Tegra DAS driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
-MODULE_DEVICE_TABLE(of, tegra_das_of_match);
diff --git a/sound/soc/tegra/tegra_das.h b/sound/soc/tegra/tegra_das.h
deleted file mode 100644
index 2c96c7b3c459..000000000000
--- a/sound/soc/tegra/tegra_das.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * tegra_das.h - Definitions for Tegra DAS driver
- *
- * Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2010 - NVIDIA, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __TEGRA_DAS_H__
-#define __TEGRA_DAS_H__
-
-/* Register TEGRA_DAS_DAP_CTRL_SEL */
-#define TEGRA_DAS_DAP_CTRL_SEL 0x00
-#define TEGRA_DAS_DAP_CTRL_SEL_COUNT 5
-#define TEGRA_DAS_DAP_CTRL_SEL_STRIDE 4
-#define TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P 31
-#define TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_S 1
-#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P 30
-#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_S 1
-#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P 29
-#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_S 1
-#define TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P 0
-#define TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_S 5
-
-/* Values for field TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL */
-#define TEGRA_DAS_DAP_SEL_DAC1 0
-#define TEGRA_DAS_DAP_SEL_DAC2 1
-#define TEGRA_DAS_DAP_SEL_DAC3 2
-#define TEGRA_DAS_DAP_SEL_DAP1 16
-#define TEGRA_DAS_DAP_SEL_DAP2 17
-#define TEGRA_DAS_DAP_SEL_DAP3 18
-#define TEGRA_DAS_DAP_SEL_DAP4 19
-#define TEGRA_DAS_DAP_SEL_DAP5 20
-
-/* Register TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL */
-#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL 0x40
-#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_COUNT 3
-#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE 4
-#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P 28
-#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_S 4
-#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P 24
-#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_S 4
-#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P 0
-#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_S 4
-
-/*
- * Values for:
- * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL
- * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL
- * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL
- */
-#define TEGRA_DAS_DAC_SEL_DAP1 0
-#define TEGRA_DAS_DAC_SEL_DAP2 1
-#define TEGRA_DAS_DAC_SEL_DAP3 2
-#define TEGRA_DAS_DAC_SEL_DAP4 3
-#define TEGRA_DAS_DAC_SEL_DAP5 4
-
-/*
- * Names/IDs of the DACs/DAPs.
- */
-
-#define TEGRA_DAS_DAP_ID_1 0
-#define TEGRA_DAS_DAP_ID_2 1
-#define TEGRA_DAS_DAP_ID_3 2
-#define TEGRA_DAS_DAP_ID_4 3
-#define TEGRA_DAS_DAP_ID_5 4
-
-#define TEGRA_DAS_DAC_ID_1 0
-#define TEGRA_DAS_DAC_ID_2 1
-#define TEGRA_DAS_DAC_ID_3 2
-
-struct tegra_das {
- struct device *dev;
- void __iomem *regs;
- struct dentry *debug;
-};
-
-/*
- * Terminology:
- * DAS: Digital audio switch (HW module controlled by this driver)
- * DAP: Digital audio port (port/pins on Tegra device)
- * DAC: Digital audio controller (e.g. I2S or AC97 controller elsewhere)
- *
- * The Tegra DAS is a mux/cross-bar which can connect each DAP to a specific
- * DAC, or another DAP. When DAPs are connected, one must be the master and
- * one the slave. Each DAC allows selection of a specific DAP for input, to
- * cater for the case where N DAPs are connected to 1 DAC for broadcast
- * output.
- *
- * This driver is dumb; no attempt is made to ensure that a valid routing
- * configuration is programmed.
- */
-
-/*
- * Connect a DAP to to a DAC
- * dap_id: DAP to connect: TEGRA_DAS_DAP_ID_*
- * dac_sel: DAC to connect to: TEGRA_DAS_DAP_SEL_DAC*
- */
-extern int tegra_das_connect_dap_to_dac(int dap_id, int dac_sel);
-
-/*
- * Connect a DAP to to another DAP
- * dap_id: DAP to connect: TEGRA_DAS_DAP_ID_*
- * other_dap_sel: DAP to connect to: TEGRA_DAS_DAP_SEL_DAP*
- * master: Is this DAP the master (1) or slave (0)
- * sdata1rx: Is this DAP's SDATA1 pin RX (1) or TX (0)
- * sdata2rx: Is this DAP's SDATA2 pin RX (1) or TX (0)
- */
-extern int tegra_das_connect_dap_to_dap(int dap_id, int other_dap_sel,
- int master, int sdata1rx,
- int sdata2rx);
-
-/*
- * Connect a DAC's input to a DAP
- * (DAC outputs are selected by the DAP)
- * dac_id: DAC ID to connect: TEGRA_DAS_DAC_ID_*
- * dap_sel: DAP to receive input from: TEGRA_DAS_DAC_SEL_DAP*
- */
-extern int tegra_das_connect_dac_to_dap(int dac_id, int dap_sel);
-
-#endif
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c
deleted file mode 100644
index e53349912b2e..000000000000
--- a/sound/soc/tegra/tegra_i2s.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * tegra_i2s.c - Tegra I2S driver
- *
- * Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2010 - NVIDIA, Inc.
- *
- * Based on code copyright/by:
- *
- * Copyright (c) 2009-2010, NVIDIA Corporation.
- * Scott Peterson <speterson@nvidia.com>
- *
- * Copyright (C) 2010 Google, Inc.
- * Iliyan Malchev <malchev@google.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/debugfs.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <mach/iomap.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include "tegra_i2s.h"
-
-#define DRV_NAME "tegra-i2s"
-
-static inline void tegra_i2s_write(struct tegra_i2s *i2s, u32 reg, u32 val)
-{
- __raw_writel(val, i2s->regs + reg);
-}
-
-static inline u32 tegra_i2s_read(struct tegra_i2s *i2s, u32 reg)
-{
- return __raw_readl(i2s->regs + reg);
-}
-
-#ifdef CONFIG_DEBUG_FS
-static int tegra_i2s_show(struct seq_file *s, void *unused)
-{
-#define REG(r) { r, #r }
- static const struct {
- int offset;
- const char *name;
- } regs[] = {
- REG(TEGRA_I2S_CTRL),
- REG(TEGRA_I2S_STATUS),
- REG(TEGRA_I2S_TIMING),
- REG(TEGRA_I2S_FIFO_SCR),
- REG(TEGRA_I2S_PCM_CTRL),
- REG(TEGRA_I2S_NW_CTRL),
- REG(TEGRA_I2S_TDM_CTRL),
- REG(TEGRA_I2S_TDM_TX_RX_CTRL),
- };
-#undef REG
-
- struct tegra_i2s *i2s = s->private;
- int i;
-
- clk_enable(i2s->clk_i2s);
-
- for (i = 0; i < ARRAY_SIZE(regs); i++) {
- u32 val = tegra_i2s_read(i2s, regs[i].offset);
- seq_printf(s, "%s = %08x\n", regs[i].name, val);
- }
-
- clk_disable(i2s->clk_i2s);
-
- return 0;
-}
-
-static int tegra_i2s_debug_open(struct inode *inode, struct file *file)
-{
- return single_open(file, tegra_i2s_show, inode->i_private);
-}
-
-static const struct file_operations tegra_i2s_debug_fops = {
- .open = tegra_i2s_debug_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static void tegra_i2s_debug_add(struct tegra_i2s *i2s)
-{
- i2s->debug = debugfs_create_file(i2s->dai.name, S_IRUGO,
- snd_soc_debugfs_root, i2s,
- &tegra_i2s_debug_fops);
-}
-
-static void tegra_i2s_debug_remove(struct tegra_i2s *i2s)
-{
- if (i2s->debug)
- debugfs_remove(i2s->debug);
-}
-#else
-static inline void tegra_i2s_debug_add(struct tegra_i2s *i2s)
-{
-}
-
-static inline void tegra_i2s_debug_remove(struct tegra_i2s *i2s)
-{
-}
-#endif
-
-static int tegra_i2s_set_fmt(struct snd_soc_dai *dai,
- unsigned int fmt)
-{
- struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_NF:
- break;
- default:
- return -EINVAL;
- }
-
- i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_MASTER_ENABLE;
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBS_CFS:
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_MASTER_ENABLE;
- break;
- case SND_SOC_DAIFMT_CBM_CFM:
- break;
- default:
- return -EINVAL;
- }
-
- i2s->reg_ctrl &= ~(TEGRA_I2S_CTRL_BIT_FORMAT_MASK |
- TEGRA_I2S_CTRL_LRCK_MASK);
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_DSP_A:
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_DSP;
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
- break;
- case SND_SOC_DAIFMT_DSP_B:
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_DSP;
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_R_LOW;
- break;
- case SND_SOC_DAIFMT_I2S:
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_I2S;
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
- break;
- case SND_SOC_DAIFMT_RIGHT_J:
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_RJM;
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
- break;
- case SND_SOC_DAIFMT_LEFT_J:
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_LJM;
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int tegra_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct device *dev = substream->pcm->card->dev;
- struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai);
- u32 reg;
- int ret, sample_size, srate, i2sclock, bitcnt;
-
- i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_BIT_SIZE_MASK;
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_16;
- sample_size = 16;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_24;
- sample_size = 24;
- break;
- case SNDRV_PCM_FORMAT_S32_LE:
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_32;
- sample_size = 32;
- break;
- default:
- return -EINVAL;
- }
-
- srate = params_rate(params);
-
- /* Final "* 2" required by Tegra hardware */
- i2sclock = srate * params_channels(params) * sample_size * 2;
-
- ret = clk_set_rate(i2s->clk_i2s, i2sclock);
- if (ret) {
- dev_err(dev, "Can't set I2S clock rate: %d\n", ret);
- return ret;
- }
-
- bitcnt = (i2sclock / (2 * srate)) - 1;
- if (bitcnt < 0 || bitcnt > TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US)
- return -EINVAL;
- reg = bitcnt << TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
-
- if (i2sclock % (2 * srate))
- reg |= TEGRA_I2S_TIMING_NON_SYM_ENABLE;
-
- if (!i2s->clk_refs)
- clk_enable(i2s->clk_i2s);
-
- tegra_i2s_write(i2s, TEGRA_I2S_TIMING, reg);
-
- tegra_i2s_write(i2s, TEGRA_I2S_FIFO_SCR,
- TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
- TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
-
- if (!i2s->clk_refs)
- clk_disable(i2s->clk_i2s);
-
- return 0;
-}
-
-static void tegra_i2s_start_playback(struct tegra_i2s *i2s)
-{
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_FIFO1_ENABLE;
- tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
-}
-
-static void tegra_i2s_stop_playback(struct tegra_i2s *i2s)
-{
- i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO1_ENABLE;
- tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
-}
-
-static void tegra_i2s_start_capture(struct tegra_i2s *i2s)
-{
- i2s->reg_ctrl |= TEGRA_I2S_CTRL_FIFO2_ENABLE;
- tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
-}
-
-static void tegra_i2s_stop_capture(struct tegra_i2s *i2s)
-{
- i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO2_ENABLE;
- tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
-}
-
-static int tegra_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- case SNDRV_PCM_TRIGGER_RESUME:
- if (!i2s->clk_refs)
- clk_enable(i2s->clk_i2s);
- i2s->clk_refs++;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- tegra_i2s_start_playback(i2s);
- else
- tegra_i2s_start_capture(i2s);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- tegra_i2s_stop_playback(i2s);
- else
- tegra_i2s_stop_capture(i2s);
- i2s->clk_refs--;
- if (!i2s->clk_refs)
- clk_disable(i2s->clk_i2s);
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int tegra_i2s_probe(struct snd_soc_dai *dai)
-{
- struct tegra_i2s * i2s = snd_soc_dai_get_drvdata(dai);
-
- dai->capture_dma_data = &i2s->capture_dma_data;
- dai->playback_dma_data = &i2s->playback_dma_data;
-
- return 0;
-}
-
-static const struct snd_soc_dai_ops tegra_i2s_dai_ops = {
- .set_fmt = tegra_i2s_set_fmt,
- .hw_params = tegra_i2s_hw_params,
- .trigger = tegra_i2s_trigger,
-};
-
-static const struct snd_soc_dai_driver tegra_i2s_dai_template = {
- .probe = tegra_i2s_probe,
- .playback = {
- .channels_min = 2,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_96000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- .capture = {
- .channels_min = 2,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_96000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- .ops = &tegra_i2s_dai_ops,
- .symmetric_rates = 1,
-};
-
-static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev)
-{
- struct tegra_i2s * i2s;
- struct resource *mem, *memregion, *dmareq;
- u32 of_dma[2];
- u32 dma_ch;
- int ret;
-
- i2s = devm_kzalloc(&pdev->dev, sizeof(struct tegra_i2s), GFP_KERNEL);
- if (!i2s) {
- dev_err(&pdev->dev, "Can't allocate tegra_i2s\n");
- ret = -ENOMEM;
- goto err;
- }
- dev_set_drvdata(&pdev->dev, i2s);
-
- i2s->dai = tegra_i2s_dai_template;
- i2s->dai.name = dev_name(&pdev->dev);
-
- i2s->clk_i2s = clk_get(&pdev->dev, NULL);
- if (IS_ERR(i2s->clk_i2s)) {
- dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
- ret = PTR_ERR(i2s->clk_i2s);
- goto err;
- }
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(&pdev->dev, "No memory resource\n");
- ret = -ENODEV;
- goto err_clk_put;
- }
-
- dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (!dmareq) {
- if (of_property_read_u32_array(pdev->dev.of_node,
- "nvidia,dma-request-selector",
- of_dma, 2) < 0) {
- dev_err(&pdev->dev, "No DMA resource\n");
- ret = -ENODEV;
- goto err_clk_put;
- }
- dma_ch = of_dma[1];
- } else {
- dma_ch = dmareq->start;
- }
-
- memregion = devm_request_mem_region(&pdev->dev, mem->start,
- resource_size(mem), DRV_NAME);
- if (!memregion) {
- dev_err(&pdev->dev, "Memory region already claimed\n");
- ret = -EBUSY;
- goto err_clk_put;
- }
-
- i2s->regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
- if (!i2s->regs) {
- dev_err(&pdev->dev, "ioremap failed\n");
- ret = -ENOMEM;
- goto err_clk_put;
- }
-
- i2s->capture_dma_data.addr = mem->start + TEGRA_I2S_FIFO2;
- i2s->capture_dma_data.wrap = 4;
- i2s->capture_dma_data.width = 32;
- i2s->capture_dma_data.req_sel = dma_ch;
-
- i2s->playback_dma_data.addr = mem->start + TEGRA_I2S_FIFO1;
- i2s->playback_dma_data.wrap = 4;
- i2s->playback_dma_data.width = 32;
- i2s->playback_dma_data.req_sel = dma_ch;
-
- i2s->reg_ctrl = TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED;
-
- ret = snd_soc_register_dai(&pdev->dev, &i2s->dai);
- if (ret) {
- dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
- ret = -ENOMEM;
- goto err_clk_put;
- }
-
- tegra_i2s_debug_add(i2s);
-
- return 0;
-
-err_clk_put:
- clk_put(i2s->clk_i2s);
-err:
- return ret;
-}
-
-static int __devexit tegra_i2s_platform_remove(struct platform_device *pdev)
-{
- struct tegra_i2s *i2s = dev_get_drvdata(&pdev->dev);
-
- snd_soc_unregister_dai(&pdev->dev);
-
- tegra_i2s_debug_remove(i2s);
-
- clk_put(i2s->clk_i2s);
-
- return 0;
-}
-
-static const struct of_device_id tegra_i2s_of_match[] __devinitconst = {
- { .compatible = "nvidia,tegra20-i2s", },
- {},
-};
-
-static struct platform_driver tegra_i2s_driver = {
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- .of_match_table = tegra_i2s_of_match,
- },
- .probe = tegra_i2s_platform_probe,
- .remove = __devexit_p(tegra_i2s_platform_remove),
-};
-module_platform_driver(tegra_i2s_driver);
-
-MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
-MODULE_DESCRIPTION("Tegra I2S ASoC driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
-MODULE_DEVICE_TABLE(of, tegra_i2s_of_match);
diff --git a/sound/soc/tegra/tegra_i2s.h b/sound/soc/tegra/tegra_i2s.h
deleted file mode 100644
index 15ce1e2e8bde..000000000000
--- a/sound/soc/tegra/tegra_i2s.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * tegra_i2s.h - Definitions for Tegra I2S driver
- *
- * Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2010 - NVIDIA, Inc.
- *
- * Based on code copyright/by:
- *
- * Copyright (c) 2009-2010, NVIDIA Corporation.
- * Scott Peterson <speterson@nvidia.com>
- *
- * Copyright (C) 2010 Google, Inc.
- * Iliyan Malchev <malchev@google.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __TEGRA_I2S_H__
-#define __TEGRA_I2S_H__
-
-#include "tegra_pcm.h"
-
-/* Register offsets from TEGRA_I2S1_BASE and TEGRA_I2S2_BASE */
-
-#define TEGRA_I2S_CTRL 0x00
-#define TEGRA_I2S_STATUS 0x04
-#define TEGRA_I2S_TIMING 0x08
-#define TEGRA_I2S_FIFO_SCR 0x0c
-#define TEGRA_I2S_PCM_CTRL 0x10
-#define TEGRA_I2S_NW_CTRL 0x14
-#define TEGRA_I2S_TDM_CTRL 0x20
-#define TEGRA_I2S_TDM_TX_RX_CTRL 0x24
-#define TEGRA_I2S_FIFO1 0x40
-#define TEGRA_I2S_FIFO2 0x80
-
-/* Fields in TEGRA_I2S_CTRL */
-
-#define TEGRA_I2S_CTRL_FIFO2_TX_ENABLE (1 << 30)
-#define TEGRA_I2S_CTRL_FIFO1_ENABLE (1 << 29)
-#define TEGRA_I2S_CTRL_FIFO2_ENABLE (1 << 28)
-#define TEGRA_I2S_CTRL_FIFO1_RX_ENABLE (1 << 27)
-#define TEGRA_I2S_CTRL_FIFO_LPBK_ENABLE (1 << 26)
-#define TEGRA_I2S_CTRL_MASTER_ENABLE (1 << 25)
-
-#define TEGRA_I2S_LRCK_LEFT_LOW 0
-#define TEGRA_I2S_LRCK_RIGHT_LOW 1
-
-#define TEGRA_I2S_CTRL_LRCK_SHIFT 24
-#define TEGRA_I2S_CTRL_LRCK_MASK (1 << TEGRA_I2S_CTRL_LRCK_SHIFT)
-#define TEGRA_I2S_CTRL_LRCK_L_LOW (TEGRA_I2S_LRCK_LEFT_LOW << TEGRA_I2S_CTRL_LRCK_SHIFT)
-#define TEGRA_I2S_CTRL_LRCK_R_LOW (TEGRA_I2S_LRCK_RIGHT_LOW << TEGRA_I2S_CTRL_LRCK_SHIFT)
-
-#define TEGRA_I2S_BIT_FORMAT_I2S 0
-#define TEGRA_I2S_BIT_FORMAT_RJM 1
-#define TEGRA_I2S_BIT_FORMAT_LJM 2
-#define TEGRA_I2S_BIT_FORMAT_DSP 3
-
-#define TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT 10
-#define TEGRA_I2S_CTRL_BIT_FORMAT_MASK (3 << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
-#define TEGRA_I2S_CTRL_BIT_FORMAT_I2S (TEGRA_I2S_BIT_FORMAT_I2S << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
-#define TEGRA_I2S_CTRL_BIT_FORMAT_RJM (TEGRA_I2S_BIT_FORMAT_RJM << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
-#define TEGRA_I2S_CTRL_BIT_FORMAT_LJM (TEGRA_I2S_BIT_FORMAT_LJM << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
-#define TEGRA_I2S_CTRL_BIT_FORMAT_DSP (TEGRA_I2S_BIT_FORMAT_DSP << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
-
-#define TEGRA_I2S_BIT_SIZE_16 0
-#define TEGRA_I2S_BIT_SIZE_20 1
-#define TEGRA_I2S_BIT_SIZE_24 2
-#define TEGRA_I2S_BIT_SIZE_32 3
-
-#define TEGRA_I2S_CTRL_BIT_SIZE_SHIFT 8
-#define TEGRA_I2S_CTRL_BIT_SIZE_MASK (3 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
-#define TEGRA_I2S_CTRL_BIT_SIZE_16 (TEGRA_I2S_BIT_SIZE_16 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
-#define TEGRA_I2S_CTRL_BIT_SIZE_20 (TEGRA_I2S_BIT_SIZE_20 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
-#define TEGRA_I2S_CTRL_BIT_SIZE_24 (TEGRA_I2S_BIT_SIZE_24 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
-#define TEGRA_I2S_CTRL_BIT_SIZE_32 (TEGRA_I2S_BIT_SIZE_32 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
-
-#define TEGRA_I2S_FIFO_16_LSB 0
-#define TEGRA_I2S_FIFO_20_LSB 1
-#define TEGRA_I2S_FIFO_24_LSB 2
-#define TEGRA_I2S_FIFO_32 3
-#define TEGRA_I2S_FIFO_PACKED 7
-
-#define TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT 4
-#define TEGRA_I2S_CTRL_FIFO_FORMAT_MASK (7 << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
-#define TEGRA_I2S_CTRL_FIFO_FORMAT_16_LSB (TEGRA_I2S_FIFO_16_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
-#define TEGRA_I2S_CTRL_FIFO_FORMAT_20_LSB (TEGRA_I2S_FIFO_20_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
-#define TEGRA_I2S_CTRL_FIFO_FORMAT_24_LSB (TEGRA_I2S_FIFO_24_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
-#define TEGRA_I2S_CTRL_FIFO_FORMAT_32 (TEGRA_I2S_FIFO_32 << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
-#define TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED (TEGRA_I2S_FIFO_PACKED << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
-
-#define TEGRA_I2S_CTRL_IE_FIFO1_ERR (1 << 3)
-#define TEGRA_I2S_CTRL_IE_FIFO2_ERR (1 << 2)
-#define TEGRA_I2S_CTRL_QE_FIFO1 (1 << 1)
-#define TEGRA_I2S_CTRL_QE_FIFO2 (1 << 0)
-
-/* Fields in TEGRA_I2S_STATUS */
-
-#define TEGRA_I2S_STATUS_FIFO1_RDY (1 << 31)
-#define TEGRA_I2S_STATUS_FIFO2_RDY (1 << 30)
-#define TEGRA_I2S_STATUS_FIFO1_BSY (1 << 29)
-#define TEGRA_I2S_STATUS_FIFO2_BSY (1 << 28)
-#define TEGRA_I2S_STATUS_FIFO1_ERR (1 << 3)
-#define TEGRA_I2S_STATUS_FIFO2_ERR (1 << 2)
-#define TEGRA_I2S_STATUS_QS_FIFO1 (1 << 1)
-#define TEGRA_I2S_STATUS_QS_FIFO2 (1 << 0)
-
-/* Fields in TEGRA_I2S_TIMING */
-
-#define TEGRA_I2S_TIMING_NON_SYM_ENABLE (1 << 12)
-#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT 0
-#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US 0x7fff
-#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK (TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US << TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT)
-
-/* Fields in TEGRA_I2S_FIFO_SCR */
-
-#define TEGRA_I2S_FIFO_SCR_FIFO2_FULL_EMPTY_COUNT_SHIFT 24
-#define TEGRA_I2S_FIFO_SCR_FIFO1_FULL_EMPTY_COUNT_SHIFT 16
-#define TEGRA_I2S_FIFO_SCR_FIFO_FULL_EMPTY_COUNT_MASK 0x3f
-
-#define TEGRA_I2S_FIFO_SCR_FIFO2_CLR (1 << 12)
-#define TEGRA_I2S_FIFO_SCR_FIFO1_CLR (1 << 8)
-
-#define TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT 0
-#define TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS 1
-#define TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS 2
-#define TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS 3
-
-#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT 4
-#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_MASK (3 << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
-#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_ONE_SLOT (TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
-#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
-#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_EIGHT_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
-#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_TWELVE_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
-
-#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT 0
-#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_MASK (3 << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
-#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_ONE_SLOT (TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
-#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
-#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_EIGHT_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
-#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_TWELVE_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
-
-struct tegra_i2s {
- struct snd_soc_dai_driver dai;
- struct clk *clk_i2s;
- int clk_refs;
- struct tegra_pcm_dma_params capture_dma_data;
- struct tegra_pcm_dma_params playback_dma_data;
- void __iomem *regs;
- struct dentry *debug;
- u32 reg_ctrl;
-};
-
-#endif
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 8b4457137c7c..127348dc09b1 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -2,7 +2,7 @@
* tegra_pcm.c - Tegra PCM driver
*
* Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2010 - NVIDIA, Inc.
+ * Copyright (C) 2010,2012 - NVIDIA, Inc.
*
* Based on code copyright/by:
*
@@ -29,8 +29,8 @@
*
*/
-#include <linux/module.h>
#include <linux/dma-mapping.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -39,8 +39,6 @@
#include "tegra_pcm.h"
-#define DRV_NAME "tegra-pcm-audio"
-
static const struct snd_pcm_hardware tegra_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -372,28 +370,18 @@ static struct snd_soc_platform_driver tegra_pcm_platform = {
.pcm_free = tegra_pcm_free,
};
-static int __devinit tegra_pcm_platform_probe(struct platform_device *pdev)
+int __devinit tegra_pcm_platform_register(struct device *dev)
{
- return snd_soc_register_platform(&pdev->dev, &tegra_pcm_platform);
+ return snd_soc_register_platform(dev, &tegra_pcm_platform);
}
+EXPORT_SYMBOL_GPL(tegra_pcm_platform_register);
-static int __devexit tegra_pcm_platform_remove(struct platform_device *pdev)
+void __devexit tegra_pcm_platform_unregister(struct device *dev)
{
- snd_soc_unregister_platform(&pdev->dev);
- return 0;
+ snd_soc_unregister_platform(dev);
}
-
-static struct platform_driver tegra_pcm_driver = {
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- },
- .probe = tegra_pcm_platform_probe,
- .remove = __devexit_p(tegra_pcm_platform_remove),
-};
-module_platform_driver(tegra_pcm_driver);
+EXPORT_SYMBOL_GPL(tegra_pcm_platform_unregister);
MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra PCM ASoC driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h
index dbb90339fe0d..985d418a35e7 100644
--- a/sound/soc/tegra/tegra_pcm.h
+++ b/sound/soc/tegra/tegra_pcm.h
@@ -2,7 +2,7 @@
* tegra_pcm.h - Definitions for Tegra PCM driver
*
* Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2010 - NVIDIA, Inc.
+ * Copyright (C) 2010,2012 - NVIDIA, Inc.
*
* Based on code copyright/by:
*
@@ -52,4 +52,7 @@ struct tegra_runtime_data {
struct tegra_dma_channel *dma_chan;
};
+int tegra_pcm_platform_register(struct device *dev);
+void tegra_pcm_platform_unregister(struct device *dev);
+
#endif
diff --git a/sound/soc/tegra/tegra_spdif.c b/sound/soc/tegra/tegra_spdif.c
deleted file mode 100644
index 9ff2c601445f..000000000000
--- a/sound/soc/tegra/tegra_spdif.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * tegra_spdif.c - Tegra SPDIF driver
- *
- * Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2011 - NVIDIA, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/debugfs.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <mach/iomap.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include "tegra_spdif.h"
-
-#define DRV_NAME "tegra-spdif"
-
-static inline void tegra_spdif_write(struct tegra_spdif *spdif, u32 reg,
- u32 val)
-{
- __raw_writel(val, spdif->regs + reg);
-}
-
-static inline u32 tegra_spdif_read(struct tegra_spdif *spdif, u32 reg)
-{
- return __raw_readl(spdif->regs + reg);
-}
-
-#ifdef CONFIG_DEBUG_FS
-static int tegra_spdif_show(struct seq_file *s, void *unused)
-{
-#define REG(r) { r, #r }
- static const struct {
- int offset;
- const char *name;
- } regs[] = {
- REG(TEGRA_SPDIF_CTRL),
- REG(TEGRA_SPDIF_STATUS),
- REG(TEGRA_SPDIF_STROBE_CTRL),
- REG(TEGRA_SPDIF_DATA_FIFO_CSR),
- REG(TEGRA_SPDIF_CH_STA_RX_A),
- REG(TEGRA_SPDIF_CH_STA_RX_B),
- REG(TEGRA_SPDIF_CH_STA_RX_C),
- REG(TEGRA_SPDIF_CH_STA_RX_D),
- REG(TEGRA_SPDIF_CH_STA_RX_E),
- REG(TEGRA_SPDIF_CH_STA_RX_F),
- REG(TEGRA_SPDIF_CH_STA_TX_A),
- REG(TEGRA_SPDIF_CH_STA_TX_B),
- REG(TEGRA_SPDIF_CH_STA_TX_C),
- REG(TEGRA_SPDIF_CH_STA_TX_D),
- REG(TEGRA_SPDIF_CH_STA_TX_E),
- REG(TEGRA_SPDIF_CH_STA_TX_F),
- };
-#undef REG
-
- struct tegra_spdif *spdif = s->private;
- int i;
-
- clk_enable(spdif->clk_spdif_out);
-
- for (i = 0; i < ARRAY_SIZE(regs); i++) {
- u32 val = tegra_spdif_read(spdif, regs[i].offset);
- seq_printf(s, "%s = %08x\n", regs[i].name, val);
- }
-
- clk_disable(spdif->clk_spdif_out);
-
- return 0;
-}
-
-static int tegra_spdif_debug_open(struct inode *inode, struct file *file)
-{
- return single_open(file, tegra_spdif_show, inode->i_private);
-}
-
-static const struct file_operations tegra_spdif_debug_fops = {
- .open = tegra_spdif_debug_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static void tegra_spdif_debug_add(struct tegra_spdif *spdif)
-{
- spdif->debug = debugfs_create_file(DRV_NAME, S_IRUGO,
- snd_soc_debugfs_root, spdif,
- &tegra_spdif_debug_fops);
-}
-
-static void tegra_spdif_debug_remove(struct tegra_spdif *spdif)
-{
- if (spdif->debug)
- debugfs_remove(spdif->debug);
-}
-#else
-static inline void tegra_spdif_debug_add(struct tegra_spdif *spdif)
-{
-}
-
-static inline void tegra_spdif_debug_remove(struct tegra_spdif *spdif)
-{
-}
-#endif
-
-static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct device *dev = substream->pcm->card->dev;
- struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai);
- int ret, spdifclock;
-
- spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_PACK;
- spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_BIT_MODE_MASK;
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- spdif->reg_ctrl |= TEGRA_SPDIF_CTRL_PACK;
- spdif->reg_ctrl |= TEGRA_SPDIF_CTRL_BIT_MODE_16BIT;
- break;
- default:
- return -EINVAL;
- }
-
- switch (params_rate(params)) {
- case 32000:
- spdifclock = 4096000;
- break;
- case 44100:
- spdifclock = 5644800;
- break;
- case 48000:
- spdifclock = 6144000;
- break;
- case 88200:
- spdifclock = 11289600;
- break;
- case 96000:
- spdifclock = 12288000;
- break;
- case 176400:
- spdifclock = 22579200;
- break;
- case 192000:
- spdifclock = 24576000;
- break;
- default:
- return -EINVAL;
- }
-
- ret = clk_set_rate(spdif->clk_spdif_out, spdifclock);
- if (ret) {
- dev_err(dev, "Can't set SPDIF clock rate: %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-static void tegra_spdif_start_playback(struct tegra_spdif *spdif)
-{
- spdif->reg_ctrl |= TEGRA_SPDIF_CTRL_TX_EN;
- tegra_spdif_write(spdif, TEGRA_SPDIF_CTRL, spdif->reg_ctrl);
-}
-
-static void tegra_spdif_stop_playback(struct tegra_spdif *spdif)
-{
- spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_TX_EN;
- tegra_spdif_write(spdif, TEGRA_SPDIF_CTRL, spdif->reg_ctrl);
-}
-
-static int tegra_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- case SNDRV_PCM_TRIGGER_RESUME:
- if (!spdif->clk_refs)
- clk_enable(spdif->clk_spdif_out);
- spdif->clk_refs++;
- tegra_spdif_start_playback(spdif);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- tegra_spdif_stop_playback(spdif);
- spdif->clk_refs--;
- if (!spdif->clk_refs)
- clk_disable(spdif->clk_spdif_out);
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int tegra_spdif_probe(struct snd_soc_dai *dai)
-{
- struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai);
-
- dai->capture_dma_data = NULL;
- dai->playback_dma_data = &spdif->playback_dma_data;
-
- return 0;
-}
-
-static const struct snd_soc_dai_ops tegra_spdif_dai_ops = {
- .hw_params = tegra_spdif_hw_params,
- .trigger = tegra_spdif_trigger,
-};
-
-static struct snd_soc_dai_driver tegra_spdif_dai = {
- .name = DRV_NAME,
- .probe = tegra_spdif_probe,
- .playback = {
- .channels_min = 2,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- .ops = &tegra_spdif_dai_ops,
-};
-
-static __devinit int tegra_spdif_platform_probe(struct platform_device *pdev)
-{
- struct tegra_spdif *spdif;
- struct resource *mem, *memregion, *dmareq;
- int ret;
-
- spdif = kzalloc(sizeof(struct tegra_spdif), GFP_KERNEL);
- if (!spdif) {
- dev_err(&pdev->dev, "Can't allocate tegra_spdif\n");
- ret = -ENOMEM;
- goto exit;
- }
- dev_set_drvdata(&pdev->dev, spdif);
-
- spdif->clk_spdif_out = clk_get(&pdev->dev, "spdif_out");
- if (IS_ERR(spdif->clk_spdif_out)) {
- pr_err("Can't retrieve spdif clock\n");
- ret = PTR_ERR(spdif->clk_spdif_out);
- goto err_free;
- }
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(&pdev->dev, "No memory resource\n");
- ret = -ENODEV;
- goto err_clk_put;
- }
-
- dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (!dmareq) {
- dev_err(&pdev->dev, "No DMA resource\n");
- ret = -ENODEV;
- goto err_clk_put;
- }
-
- memregion = request_mem_region(mem->start, resource_size(mem),
- DRV_NAME);
- if (!memregion) {
- dev_err(&pdev->dev, "Memory region already claimed\n");
- ret = -EBUSY;
- goto err_clk_put;
- }
-
- spdif->regs = ioremap(mem->start, resource_size(mem));
- if (!spdif->regs) {
- dev_err(&pdev->dev, "ioremap failed\n");
- ret = -ENOMEM;
- goto err_release;
- }
-
- spdif->playback_dma_data.addr = mem->start + TEGRA_SPDIF_DATA_OUT;
- spdif->playback_dma_data.wrap = 4;
- spdif->playback_dma_data.width = 32;
- spdif->playback_dma_data.req_sel = dmareq->start;
-
- ret = snd_soc_register_dai(&pdev->dev, &tegra_spdif_dai);
- if (ret) {
- dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
- ret = -ENOMEM;
- goto err_unmap;
- }
-
- tegra_spdif_debug_add(spdif);
-
- return 0;
-
-err_unmap:
- iounmap(spdif->regs);
-err_release:
- release_mem_region(mem->start, resource_size(mem));
-err_clk_put:
- clk_put(spdif->clk_spdif_out);
-err_free:
- kfree(spdif);
-exit:
- return ret;
-}
-
-static int __devexit tegra_spdif_platform_remove(struct platform_device *pdev)
-{
- struct tegra_spdif *spdif = dev_get_drvdata(&pdev->dev);
- struct resource *res;
-
- snd_soc_unregister_dai(&pdev->dev);
-
- tegra_spdif_debug_remove(spdif);
-
- iounmap(spdif->regs);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, resource_size(res));
-
- clk_put(spdif->clk_spdif_out);
-
- kfree(spdif);
-
- return 0;
-}
-
-static struct platform_driver tegra_spdif_driver = {
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- },
- .probe = tegra_spdif_platform_probe,
- .remove = __devexit_p(tegra_spdif_platform_remove),
-};
-
-module_platform_driver(tegra_spdif_driver);
-
-MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
-MODULE_DESCRIPTION("Tegra SPDIF ASoC driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_spdif.h b/sound/soc/tegra/tegra_spdif.h
deleted file mode 100644
index 2e03db430279..000000000000
--- a/sound/soc/tegra/tegra_spdif.h
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * tegra_spdif.h - Definitions for Tegra SPDIF driver
- *
- * Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2011 - NVIDIA, Inc.
- *
- * Based on code copyright/by:
- * Copyright (c) 2008-2009, NVIDIA Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __TEGRA_SPDIF_H__
-#define __TEGRA_SPDIF_H__
-
-#include "tegra_pcm.h"
-
-/* Offsets from TEGRA_SPDIF_BASE */
-
-#define TEGRA_SPDIF_CTRL 0x0
-#define TEGRA_SPDIF_STATUS 0x4
-#define TEGRA_SPDIF_STROBE_CTRL 0x8
-#define TEGRA_SPDIF_DATA_FIFO_CSR 0x0C
-#define TEGRA_SPDIF_DATA_OUT 0x40
-#define TEGRA_SPDIF_DATA_IN 0x80
-#define TEGRA_SPDIF_CH_STA_RX_A 0x100
-#define TEGRA_SPDIF_CH_STA_RX_B 0x104
-#define TEGRA_SPDIF_CH_STA_RX_C 0x108
-#define TEGRA_SPDIF_CH_STA_RX_D 0x10C
-#define TEGRA_SPDIF_CH_STA_RX_E 0x110
-#define TEGRA_SPDIF_CH_STA_RX_F 0x114
-#define TEGRA_SPDIF_CH_STA_TX_A 0x140
-#define TEGRA_SPDIF_CH_STA_TX_B 0x144
-#define TEGRA_SPDIF_CH_STA_TX_C 0x148
-#define TEGRA_SPDIF_CH_STA_TX_D 0x14C
-#define TEGRA_SPDIF_CH_STA_TX_E 0x150
-#define TEGRA_SPDIF_CH_STA_TX_F 0x154
-#define TEGRA_SPDIF_USR_STA_RX_A 0x180
-#define TEGRA_SPDIF_USR_DAT_TX_A 0x1C0
-
-/* Fields in TEGRA_SPDIF_CTRL */
-
-/* Start capturing from 0=right, 1=left channel */
-#define TEGRA_SPDIF_CTRL_CAP_LC (1 << 30)
-
-/* SPDIF receiver(RX) enable */
-#define TEGRA_SPDIF_CTRL_RX_EN (1 << 29)
-
-/* SPDIF Transmitter(TX) enable */
-#define TEGRA_SPDIF_CTRL_TX_EN (1 << 28)
-
-/* Transmit Channel status */
-#define TEGRA_SPDIF_CTRL_TC_EN (1 << 27)
-
-/* Transmit user Data */
-#define TEGRA_SPDIF_CTRL_TU_EN (1 << 26)
-
-/* Interrupt on transmit error */
-#define TEGRA_SPDIF_CTRL_IE_TXE (1 << 25)
-
-/* Interrupt on receive error */
-#define TEGRA_SPDIF_CTRL_IE_RXE (1 << 24)
-
-/* Interrupt on invalid preamble */
-#define TEGRA_SPDIF_CTRL_IE_P (1 << 23)
-
-/* Interrupt on "B" preamble */
-#define TEGRA_SPDIF_CTRL_IE_B (1 << 22)
-
-/* Interrupt when block of channel status received */
-#define TEGRA_SPDIF_CTRL_IE_C (1 << 21)
-
-/* Interrupt when a valid information unit (IU) is received */
-#define TEGRA_SPDIF_CTRL_IE_U (1 << 20)
-
-/* Interrupt when RX user FIFO attention level is reached */
-#define TEGRA_SPDIF_CTRL_QE_RU (1 << 19)
-
-/* Interrupt when TX user FIFO attention level is reached */
-#define TEGRA_SPDIF_CTRL_QE_TU (1 << 18)
-
-/* Interrupt when RX data FIFO attention level is reached */
-#define TEGRA_SPDIF_CTRL_QE_RX (1 << 17)
-
-/* Interrupt when TX data FIFO attention level is reached */
-#define TEGRA_SPDIF_CTRL_QE_TX (1 << 16)
-
-/* Loopback test mode enable */
-#define TEGRA_SPDIF_CTRL_LBK_EN (1 << 15)
-
-/*
- * Pack data mode:
- * 0 = Single data (16 bit needs to be padded to match the
- * interface data bit size).
- * 1 = Packeted left/right channel data into a single word.
- */
-#define TEGRA_SPDIF_CTRL_PACK (1 << 14)
-
-/*
- * 00 = 16bit data
- * 01 = 20bit data
- * 10 = 24bit data
- * 11 = raw data
- */
-#define TEGRA_SPDIF_BIT_MODE_16BIT 0
-#define TEGRA_SPDIF_BIT_MODE_20BIT 1
-#define TEGRA_SPDIF_BIT_MODE_24BIT 2
-#define TEGRA_SPDIF_BIT_MODE_RAW 3
-
-#define TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT 12
-#define TEGRA_SPDIF_CTRL_BIT_MODE_MASK (3 << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
-#define TEGRA_SPDIF_CTRL_BIT_MODE_16BIT (TEGRA_SPDIF_BIT_MODE_16BIT << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
-#define TEGRA_SPDIF_CTRL_BIT_MODE_20BIT (TEGRA_SPDIF_BIT_MODE_20BIT << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
-#define TEGRA_SPDIF_CTRL_BIT_MODE_24BIT (TEGRA_SPDIF_BIT_MODE_24BIT << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
-#define TEGRA_SPDIF_CTRL_BIT_MODE_RAW (TEGRA_SPDIF_BIT_MODE_RAW << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
-
-/* Fields in TEGRA_SPDIF_STATUS */
-
-/*
- * Note: IS_P, IS_B, IS_C, and IS_U are sticky bits. Software must
- * write a 1 to the corresponding bit location to clear the status.
- */
-
-/*
- * Receiver(RX) shifter is busy receiving data.
- * This bit is asserted when the receiver first locked onto the
- * preamble of the data stream after RX_EN is asserted. This bit is
- * deasserted when either,
- * (a) the end of a frame is reached after RX_EN is deeasserted, or
- * (b) the SPDIF data stream becomes inactive.
- */
-#define TEGRA_SPDIF_STATUS_RX_BSY (1 << 29)
-
-/*
- * Transmitter(TX) shifter is busy transmitting data.
- * This bit is asserted when TX_EN is asserted.
- * This bit is deasserted when the end of a frame is reached after
- * TX_EN is deasserted.
- */
-#define TEGRA_SPDIF_STATUS_TX_BSY (1 << 28)
-
-/*
- * TX is busy shifting out channel status.
- * This bit is asserted when both TX_EN and TC_EN are asserted and
- * data from CH_STA_TX_A register is loaded into the internal shifter.
- * This bit is deasserted when either,
- * (a) the end of a frame is reached after TX_EN is deasserted, or
- * (b) CH_STA_TX_F register is loaded into the internal shifter.
- */
-#define TEGRA_SPDIF_STATUS_TC_BSY (1 << 27)
-
-/*
- * TX User data FIFO busy.
- * This bit is asserted when TX_EN and TXU_EN are asserted and
- * there's data in the TX user FIFO. This bit is deassert when either,
- * (a) the end of a frame is reached after TX_EN is deasserted, or
- * (b) there's no data left in the TX user FIFO.
- */
-#define TEGRA_SPDIF_STATUS_TU_BSY (1 << 26)
-
-/* TX FIFO Underrun error status */
-#define TEGRA_SPDIF_STATUS_TX_ERR (1 << 25)
-
-/* RX FIFO Overrun error status */
-#define TEGRA_SPDIF_STATUS_RX_ERR (1 << 24)
-
-/* Preamble status: 0=Preamble OK, 1=bad/missing preamble */
-#define TEGRA_SPDIF_STATUS_IS_P (1 << 23)
-
-/* B-preamble detection status: 0=not detected, 1=B-preamble detected */
-#define TEGRA_SPDIF_STATUS_IS_B (1 << 22)
-
-/*
- * RX channel block data receive status:
- * 0=entire block not recieved yet.
- * 1=received entire block of channel status,
- */
-#define TEGRA_SPDIF_STATUS_IS_C (1 << 21)
-
-/* RX User Data Valid flag: 1=valid IU detected, 0 = no IU detected. */
-#define TEGRA_SPDIF_STATUS_IS_U (1 << 20)
-
-/*
- * RX User FIFO Status:
- * 1=attention level reached, 0=attention level not reached.
- */
-#define TEGRA_SPDIF_STATUS_QS_RU (1 << 19)
-
-/*
- * TX User FIFO Status:
- * 1=attention level reached, 0=attention level not reached.
- */
-#define TEGRA_SPDIF_STATUS_QS_TU (1 << 18)
-
-/*
- * RX Data FIFO Status:
- * 1=attention level reached, 0=attention level not reached.
- */
-#define TEGRA_SPDIF_STATUS_QS_RX (1 << 17)
-
-/*
- * TX Data FIFO Status:
- * 1=attention level reached, 0=attention level not reached.
- */
-#define TEGRA_SPDIF_STATUS_QS_TX (1 << 16)
-
-/* Fields in TEGRA_SPDIF_STROBE_CTRL */
-
-/*
- * Indicates the approximate number of detected SPDIFIN clocks within a
- * bi-phase period.
- */
-#define TEGRA_SPDIF_STROBE_CTRL_PERIOD_SHIFT 16
-#define TEGRA_SPDIF_STROBE_CTRL_PERIOD_MASK (0xff << TEGRA_SPDIF_STROBE_CTRL_PERIOD_SHIFT)
-
-/* Data strobe mode: 0=Auto-locked 1=Manual locked */
-#define TEGRA_SPDIF_STROBE_CTRL_STROBE (1 << 15)
-
-/*
- * Manual data strobe time within the bi-phase clock period (in terms of
- * the number of over-sampling clocks).
- */
-#define TEGRA_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT 8
-#define TEGRA_SPDIF_STROBE_CTRL_DATA_STROBES_MASK (0x1f << TEGRA_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT)
-
-/*
- * Manual SPDIFIN bi-phase clock period (in terms of the number of
- * over-sampling clocks).
- */
-#define TEGRA_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT 0
-#define TEGRA_SPDIF_STROBE_CTRL_CLOCK_PERIOD_MASK (0x3f << TEGRA_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT)
-
-/* Fields in SPDIF_DATA_FIFO_CSR */
-
-/* Clear Receiver User FIFO (RX USR.FIFO) */
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_CLR (1 << 31)
-
-#define TEGRA_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT 0
-#define TEGRA_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS 1
-#define TEGRA_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS 2
-#define TEGRA_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS 3
-
-/* RU FIFO attention level */
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT 29
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_MASK \
- (0x3 << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU1_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU2_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU3_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU4_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
-
-/* Number of RX USR.FIFO levels with valid data. */
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_SHIFT 24
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_MASK (0x1f << TEGRA_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_SHIFT)
-
-/* Clear Transmitter User FIFO (TX USR.FIFO) */
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_CLR (1 << 23)
-
-/* TU FIFO attention level */
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT 21
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_MASK \
- (0x3 << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU1_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU2_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU3_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU4_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
-
-/* Number of TX USR.FIFO levels that could be filled. */
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_SHIFT 16
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_MASK (0x1f << SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_SHIFT)
-
-/* Clear Receiver Data FIFO (RX DATA.FIFO) */
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_CLR (1 << 15)
-
-#define TEGRA_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT 0
-#define TEGRA_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS 1
-#define TEGRA_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS 2
-#define TEGRA_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS 3
-
-/* RU FIFO attention level */
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT 13
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_MASK \
- (0x3 << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU1_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU4_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU8_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU12_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
-
-/* Number of RX DATA.FIFO levels with valid data. */
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_SHIFT 8
-#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_MASK (0x1f << TEGRA_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_SHIFT)
-
-/* Clear Transmitter Data FIFO (TX DATA.FIFO) */
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_CLR (1 << 7)
-
-/* TU FIFO attention level */
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT 5
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_MASK \
- (0x3 << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU1_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU4_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU8_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU12_WORD_FULL \
- (TEGRA_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
-
-/* Number of TX DATA.FIFO levels that could be filled. */
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_SHIFT 0
-#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_MASK (0x1f << SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_SHIFT)
-
-/* Fields in TEGRA_SPDIF_DATA_OUT */
-
-/*
- * This register has 5 different formats:
- * 16-bit (BIT_MODE=00, PACK=0)
- * 20-bit (BIT_MODE=01, PACK=0)
- * 24-bit (BIT_MODE=10, PACK=0)
- * raw (BIT_MODE=11, PACK=0)
- * 16-bit packed (BIT_MODE=00, PACK=1)
- */
-
-#define TEGRA_SPDIF_DATA_OUT_DATA_16_SHIFT 0
-#define TEGRA_SPDIF_DATA_OUT_DATA_16_MASK (0xffff << TEGRA_SPDIF_DATA_OUT_DATA_16_SHIFT)
-
-#define TEGRA_SPDIF_DATA_OUT_DATA_20_SHIFT 0
-#define TEGRA_SPDIF_DATA_OUT_DATA_20_MASK (0xfffff << TEGRA_SPDIF_DATA_OUT_DATA_20_SHIFT)
-
-#define TEGRA_SPDIF_DATA_OUT_DATA_24_SHIFT 0
-#define TEGRA_SPDIF_DATA_OUT_DATA_24_MASK (0xffffff << TEGRA_SPDIF_DATA_OUT_DATA_24_SHIFT)
-
-#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_P (1 << 31)
-#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_C (1 << 30)
-#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_U (1 << 29)
-#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_V (1 << 28)
-
-#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_DATA_SHIFT 8
-#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_DATA_MASK (0xfffff << TEGRA_SPDIF_DATA_OUT_DATA_RAW_DATA_SHIFT)
-
-#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_AUX_SHIFT 4
-#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_AUX_MASK (0xf << TEGRA_SPDIF_DATA_OUT_DATA_RAW_AUX_SHIFT)
-
-#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_SHIFT 0
-#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_MASK (0xf << TEGRA_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_SHIFT)
-
-#define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_SHIFT 16
-#define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_MASK (0xffff << TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_SHIFT)
-
-#define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_SHIFT 0
-#define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_MASK (0xffff << TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_SHIFT)
-
-/* Fields in TEGRA_SPDIF_DATA_IN */
-
-/*
- * This register has 5 different formats:
- * 16-bit (BIT_MODE=00, PACK=0)
- * 20-bit (BIT_MODE=01, PACK=0)
- * 24-bit (BIT_MODE=10, PACK=0)
- * raw (BIT_MODE=11, PACK=0)
- * 16-bit packed (BIT_MODE=00, PACK=1)
- *
- * Bits 31:24 are common to all modes except 16-bit packed
- */
-
-#define TEGRA_SPDIF_DATA_IN_DATA_P (1 << 31)
-#define TEGRA_SPDIF_DATA_IN_DATA_C (1 << 30)
-#define TEGRA_SPDIF_DATA_IN_DATA_U (1 << 29)
-#define TEGRA_SPDIF_DATA_IN_DATA_V (1 << 28)
-
-#define TEGRA_SPDIF_DATA_IN_DATA_PREAMBLE_SHIFT 24
-#define TEGRA_SPDIF_DATA_IN_DATA_PREAMBLE_MASK (0xf << TEGRA_SPDIF_DATA_IN_DATA_PREAMBLE_SHIFT)
-
-#define TEGRA_SPDIF_DATA_IN_DATA_16_SHIFT 0
-#define TEGRA_SPDIF_DATA_IN_DATA_16_MASK (0xffff << TEGRA_SPDIF_DATA_IN_DATA_16_SHIFT)
-
-#define TEGRA_SPDIF_DATA_IN_DATA_20_SHIFT 0
-#define TEGRA_SPDIF_DATA_IN_DATA_20_MASK (0xfffff << TEGRA_SPDIF_DATA_IN_DATA_20_SHIFT)
-
-#define TEGRA_SPDIF_DATA_IN_DATA_24_SHIFT 0
-#define TEGRA_SPDIF_DATA_IN_DATA_24_MASK (0xffffff << TEGRA_SPDIF_DATA_IN_DATA_24_SHIFT)
-
-#define TEGRA_SPDIF_DATA_IN_DATA_RAW_DATA_SHIFT 8
-#define TEGRA_SPDIF_DATA_IN_DATA_RAW_DATA_MASK (0xfffff << TEGRA_SPDIF_DATA_IN_DATA_RAW_DATA_SHIFT)
-
-#define TEGRA_SPDIF_DATA_IN_DATA_RAW_AUX_SHIFT 4
-#define TEGRA_SPDIF_DATA_IN_DATA_RAW_AUX_MASK (0xf << TEGRA_SPDIF_DATA_IN_DATA_RAW_AUX_SHIFT)
-
-#define TEGRA_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_SHIFT 0
-#define TEGRA_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_MASK (0xf << TEGRA_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_SHIFT)
-
-#define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_SHIFT 16
-#define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_MASK (0xffff << TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_SHIFT)
-
-#define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_SHIFT 0
-#define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_MASK (0xffff << TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_SHIFT)
-
-/* Fields in TEGRA_SPDIF_CH_STA_RX_A */
-/* Fields in TEGRA_SPDIF_CH_STA_RX_B */
-/* Fields in TEGRA_SPDIF_CH_STA_RX_C */
-/* Fields in TEGRA_SPDIF_CH_STA_RX_D */
-/* Fields in TEGRA_SPDIF_CH_STA_RX_E */
-/* Fields in TEGRA_SPDIF_CH_STA_RX_F */
-
-/*
- * The 6-word receive channel data page buffer holds a block (192 frames) of
- * channel status information. The order of receive is from LSB to MSB
- * bit, and from CH_STA_RX_A to CH_STA_RX_F then back to CH_STA_RX_A.
- */
-
-/* Fields in TEGRA_SPDIF_CH_STA_TX_A */
-/* Fields in TEGRA_SPDIF_CH_STA_TX_B */
-/* Fields in TEGRA_SPDIF_CH_STA_TX_C */
-/* Fields in TEGRA_SPDIF_CH_STA_TX_D */
-/* Fields in TEGRA_SPDIF_CH_STA_TX_E */
-/* Fields in TEGRA_SPDIF_CH_STA_TX_F */
-
-/*
- * The 6-word transmit channel data page buffer holds a block (192 frames) of
- * channel status information. The order of transmission is from LSB to MSB
- * bit, and from CH_STA_TX_A to CH_STA_TX_F then back to CH_STA_TX_A.
- */
-
-/* Fields in TEGRA_SPDIF_USR_STA_RX_A */
-
-/*
- * This 4-word deep FIFO receives user FIFO field information. The order of
- * receive is from LSB to MSB bit.
- */
-
-/* Fields in TEGRA_SPDIF_USR_DAT_TX_A */
-
-/*
- * This 4-word deep FIFO transmits user FIFO field information. The order of
- * transmission is from LSB to MSB bit.
- */
-
-struct tegra_spdif {
- struct clk *clk_spdif_out;
- int clk_refs;
- struct tegra_pcm_dma_params capture_dma_data;
- struct tegra_pcm_dma_params playback_dma_data;
- void __iomem *regs;
- struct dentry *debug;
- u32 reg_ctrl;
-};
-
-#endif
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
new file mode 100644
index 000000000000..4e77026807a2
--- /dev/null
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -0,0 +1,224 @@
+/*
+ * tegra_wm8753.c - Tegra machine ASoC driver for boards using WM8753 codec.
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010-2012 - NVIDIA, Inc.
+ *
+ * Based on code copyright/by:
+ *
+ * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
+ *
+ * Copyright 2007 Wolfson Microelectronics PLC.
+ * Author: Graeme Gregory
+ * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <asm/mach-types.h>
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "../codecs/wm8753.h"
+
+#include "tegra_asoc_utils.h"
+
+#define DRV_NAME "tegra-snd-wm8753"
+
+struct tegra_wm8753 {
+ struct tegra_asoc_utils_data util_data;
+};
+
+static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *card = codec->card;
+ struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
+ int srate, mclk;
+ int err;
+
+ srate = params_rate(params);
+ switch (srate) {
+ case 11025:
+ case 22050:
+ case 44100:
+ case 88200:
+ mclk = 11289600;
+ break;
+ default:
+ mclk = 12288000;
+ break;
+ }
+
+ err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
+ if (err < 0) {
+ dev_err(card->dev, "Can't configure clocks\n");
+ return err;
+ }
+
+ err = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, mclk,
+ SND_SOC_CLOCK_IN);
+ if (err < 0) {
+ dev_err(card->dev, "codec_dai clock not set\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops tegra_wm8753_ops = {
+ .hw_params = tegra_wm8753_hw_params,
+};
+
+static const struct snd_soc_dapm_widget tegra_wm8753_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_MIC("Mic Jack", NULL),
+};
+
+static struct snd_soc_dai_link tegra_wm8753_dai = {
+ .name = "WM8753",
+ .stream_name = "WM8753 PCM",
+ .codec_dai_name = "wm8753-hifi",
+ .ops = &tegra_wm8753_ops,
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+};
+
+static struct snd_soc_card snd_soc_tegra_wm8753 = {
+ .name = "tegra-wm8753",
+ .owner = THIS_MODULE,
+ .dai_link = &tegra_wm8753_dai,
+ .num_links = 1,
+
+ .dapm_widgets = tegra_wm8753_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tegra_wm8753_dapm_widgets),
+ .fully_routed = true,
+};
+
+static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &snd_soc_tegra_wm8753;
+ struct tegra_wm8753 *machine;
+ int ret;
+
+ machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm8753),
+ GFP_KERNEL);
+ if (!machine) {
+ dev_err(&pdev->dev, "Can't allocate tegra_wm8753 struct\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ card->dev = &pdev->dev;
+ platform_set_drvdata(pdev, card);
+ snd_soc_card_set_drvdata(card, machine);
+
+ ret = snd_soc_of_parse_card_name(card, "nvidia,model");
+ if (ret)
+ goto err;
+
+ ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
+ if (ret)
+ goto err;
+
+ tegra_wm8753_dai.codec_of_node = of_parse_phandle(
+ pdev->dev.of_node, "nvidia,audio-codec", 0);
+ if (!tegra_wm8753_dai.codec_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,audio-codec' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ tegra_wm8753_dai.cpu_dai_of_node = of_parse_phandle(
+ pdev->dev.of_node, "nvidia,i2s-controller", 0);
+ if (!tegra_wm8753_dai.cpu_dai_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,i2s-controller' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ tegra_wm8753_dai.platform_of_node =
+ tegra_wm8753_dai.cpu_dai_of_node;
+
+ ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
+ if (ret)
+ goto err;
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ goto err_fini_utils;
+ }
+
+ return 0;
+
+err_fini_utils:
+ tegra_asoc_utils_fini(&machine->util_data);
+err:
+ return ret;
+}
+
+static int __devexit tegra_wm8753_driver_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
+
+ snd_soc_unregister_card(card);
+
+ tegra_asoc_utils_fini(&machine->util_data);
+
+ return 0;
+}
+
+static const struct of_device_id tegra_wm8753_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra-audio-wm8753", },
+ {},
+};
+
+static struct platform_driver tegra_wm8753_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = tegra_wm8753_of_match,
+ },
+ .probe = tegra_wm8753_driver_probe,
+ .remove = __devexit_p(tegra_wm8753_driver_remove),
+};
+module_platform_driver(tegra_wm8753_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra+WM8753 machine ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_wm8753_of_match);
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index 566655e23b7d..0b0df49d9d33 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -2,7 +2,7 @@
* tegra_wm8903.c - Tegra machine ASoC driver for boards using WM8903 codec.
*
* Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2010-2011 - NVIDIA, Inc.
+ * Copyright (C) 2010-2012 - NVIDIA, Inc.
*
* Based on code copyright/by:
*
@@ -46,9 +46,6 @@
#include "../codecs/wm8903.h"
-#include "tegra_das.h"
-#include "tegra_i2s.h"
-#include "tegra_pcm.h"
#include "tegra_asoc_utils.h"
#define DRV_NAME "tegra-snd-wm8903"
@@ -61,7 +58,6 @@
struct tegra_wm8903 {
struct tegra_wm8903_platform_data pdata;
- struct platform_device *pcm_dev;
struct tegra_asoc_utils_data util_data;
int gpio_requested;
};
@@ -354,8 +350,8 @@ static struct snd_soc_dai_link tegra_wm8903_dai = {
.name = "WM8903",
.stream_name = "WM8903 PCM",
.codec_name = "wm8903.0-001a",
- .platform_name = "tegra-pcm-audio",
- .cpu_dai_name = "tegra-i2s.0",
+ .platform_name = "tegra20-i2s.0",
+ .cpu_dai_name = "tegra20-i2s.0",
.codec_dai_name = "wm8903-hifi",
.init = tegra_wm8903_init,
.ops = &tegra_wm8903_ops,
@@ -392,7 +388,6 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
ret = -ENOMEM;
goto err;
}
- machine->pcm_dev = ERR_PTR(-EINVAL);
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
@@ -428,14 +423,9 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
goto err;
}
- machine->pcm_dev = platform_device_register_simple(
- "tegra-pcm-audio", -1, NULL, 0);
- if (IS_ERR(machine->pcm_dev)) {
- dev_err(&pdev->dev,
- "Can't instantiate tegra-pcm-audio\n");
- ret = PTR_ERR(machine->pcm_dev);
- goto err;
- }
+ tegra_wm8903_dai.platform_name = NULL;
+ tegra_wm8903_dai.platform_of_node =
+ tegra_wm8903_dai.cpu_dai_of_node;
} else {
if (machine_is_harmony()) {
card->dapm_routes = harmony_audio_map;
@@ -454,7 +444,7 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
if (ret)
- goto err_unregister;
+ goto err;
ret = snd_soc_register_card(card);
if (ret) {
@@ -467,9 +457,6 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
err_fini_utils:
tegra_asoc_utils_fini(&machine->util_data);
-err_unregister:
- if (!IS_ERR(machine->pcm_dev))
- platform_device_unregister(machine->pcm_dev);
err:
return ret;
}
@@ -497,8 +484,6 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
snd_soc_unregister_card(card);
tegra_asoc_utils_fini(&machine->util_data);
- if (!IS_ERR(machine->pcm_dev))
- platform_device_unregister(machine->pcm_dev);
return 0;
}
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
index 2bdfc550cff8..4a8d5b672c9f 100644
--- a/sound/soc/tegra/trimslice.c
+++ b/sound/soc/tegra/trimslice.c
@@ -27,6 +27,7 @@
#include <asm/mach-types.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -38,9 +39,6 @@
#include "../codecs/tlv320aic23.h"
-#include "tegra_das.h"
-#include "tegra_i2s.h"
-#include "tegra_pcm.h"
#include "tegra_asoc_utils.h"
#define DRV_NAME "tegra-snd-trimslice"
@@ -119,8 +117,8 @@ static struct snd_soc_dai_link trimslice_tlv320aic23_dai = {
.name = "TLV320AIC23",
.stream_name = "AIC23",
.codec_name = "tlv320aic23-codec.2-001a",
- .platform_name = "tegra-pcm-audio",
- .cpu_dai_name = "tegra-i2s.0",
+ .platform_name = "tegra20-i2s.0",
+ .cpu_dai_name = "tegra20-i2s.0",
.codec_dai_name = "tlv320aic23-hifi",
.ops = &trimslice_asoc_ops,
};
@@ -152,6 +150,32 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
goto err;
}
+ if (pdev->dev.of_node) {
+ trimslice_tlv320aic23_dai.codec_name = NULL;
+ trimslice_tlv320aic23_dai.codec_of_node = of_parse_phandle(
+ pdev->dev.of_node, "nvidia,audio-codec", 0);
+ if (!trimslice_tlv320aic23_dai.codec_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,audio-codec' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ trimslice_tlv320aic23_dai.cpu_dai_name = NULL;
+ trimslice_tlv320aic23_dai.cpu_dai_of_node = of_parse_phandle(
+ pdev->dev.of_node, "nvidia,i2s-controller", 0);
+ if (!trimslice_tlv320aic23_dai.cpu_dai_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,i2s-controller' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ trimslice_tlv320aic23_dai.platform_name = NULL;
+ trimslice_tlv320aic23_dai.platform_of_node =
+ trimslice_tlv320aic23_dai.cpu_dai_of_node;
+ }
+
ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev);
if (ret)
goto err;
@@ -187,10 +211,17 @@ static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id trimslice_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra-audio-trimslice", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, trimslice_of_match);
+
static struct platform_driver tegra_snd_trimslice_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
+ .of_match_table = trimslice_of_match,
},
.probe = tegra_snd_trimslice_probe,
.remove = __devexit_p(tegra_snd_trimslice_remove),
diff --git a/sound/soc/ux500/Kconfig b/sound/soc/ux500/Kconfig
new file mode 100644
index 000000000000..44cf43404cd9
--- /dev/null
+++ b/sound/soc/ux500/Kconfig
@@ -0,0 +1,14 @@
+#
+# Ux500 SoC audio configuration
+#
+menuconfig SND_SOC_UX500
+ tristate "SoC Audio support for Ux500 platform"
+ depends on SND_SOC
+ depends on MFD_DB8500_PRCMU
+ help
+ Say Y if you want to enable ASoC-support for
+ any of the Ux500 platforms (e.g. U8500).
+
+config SND_SOC_UX500_PLAT_MSP_I2S
+ tristate
+ depends on SND_SOC_UX500
diff --git a/sound/soc/ux500/Makefile b/sound/soc/ux500/Makefile
new file mode 100644
index 000000000000..19974c5a2ea1
--- /dev/null
+++ b/sound/soc/ux500/Makefile
@@ -0,0 +1,4 @@
+# Ux500 Platform Support
+
+snd-soc-ux500-plat-msp-i2s-objs := ux500_msp_dai.o ux500_msp_i2s.o
+obj-$(CONFIG_SND_SOC_UX500_PLAT_MSP_I2S) += snd-soc-ux500-plat-msp-i2s.o
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
new file mode 100644
index 000000000000..93c6c40e724c
--- /dev/null
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -0,0 +1,843 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
+ * Roger Nilsson <roger.xr.nilsson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/dbx500-prcmu.h>
+
+#include <mach/hardware.h>
+#include <mach/board-mop500-msp.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+
+#include "ux500_msp_i2s.h"
+#include "ux500_msp_dai.h"
+
+static int setup_pcm_multichan(struct snd_soc_dai *dai,
+ struct ux500_msp_config *msp_config)
+{
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+ struct msp_multichannel_config *multi =
+ &msp_config->multichannel_config;
+
+ if (drvdata->slots > 1) {
+ msp_config->multichannel_configured = 1;
+
+ multi->tx_multichannel_enable = true;
+ multi->rx_multichannel_enable = true;
+ multi->rx_comparison_enable_mode = MSP_COMPARISON_DISABLED;
+
+ multi->tx_channel_0_enable = drvdata->tx_mask;
+ multi->tx_channel_1_enable = 0;
+ multi->tx_channel_2_enable = 0;
+ multi->tx_channel_3_enable = 0;
+
+ multi->rx_channel_0_enable = drvdata->rx_mask;
+ multi->rx_channel_1_enable = 0;
+ multi->rx_channel_2_enable = 0;
+ multi->rx_channel_3_enable = 0;
+
+ dev_dbg(dai->dev,
+ "%s: Multichannel enabled. Slots: %d, TX: %u, RX: %u\n",
+ __func__, drvdata->slots, multi->tx_channel_0_enable,
+ multi->rx_channel_0_enable);
+ }
+
+ return 0;
+}
+
+static int setup_frameper(struct snd_soc_dai *dai, unsigned int rate,
+ struct msp_protdesc *prot_desc)
+{
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+
+ switch (drvdata->slots) {
+ case 1:
+ switch (rate) {
+ case 8000:
+ prot_desc->frame_period =
+ FRAME_PER_SINGLE_SLOT_8_KHZ;
+ break;
+
+ case 16000:
+ prot_desc->frame_period =
+ FRAME_PER_SINGLE_SLOT_16_KHZ;
+ break;
+
+ case 44100:
+ prot_desc->frame_period =
+ FRAME_PER_SINGLE_SLOT_44_1_KHZ;
+ break;
+
+ case 48000:
+ prot_desc->frame_period =
+ FRAME_PER_SINGLE_SLOT_48_KHZ;
+ break;
+
+ default:
+ dev_err(dai->dev,
+ "%s: Error: Unsupported sample-rate (freq = %d)!\n",
+ __func__, rate);
+ return -EINVAL;
+ }
+ break;
+
+ case 2:
+ prot_desc->frame_period = FRAME_PER_2_SLOTS;
+ break;
+
+ case 8:
+ prot_desc->frame_period = FRAME_PER_8_SLOTS;
+ break;
+
+ case 16:
+ prot_desc->frame_period = FRAME_PER_16_SLOTS;
+ break;
+ default:
+ dev_err(dai->dev,
+ "%s: Error: Unsupported slot-count (slots = %d)!\n",
+ __func__, drvdata->slots);
+ return -EINVAL;
+ }
+
+ prot_desc->clocks_per_frame =
+ prot_desc->frame_period+1;
+
+ dev_dbg(dai->dev, "%s: Clocks per frame: %u\n",
+ __func__,
+ prot_desc->clocks_per_frame);
+
+ return 0;
+}
+
+static int setup_pcm_framing(struct snd_soc_dai *dai, unsigned int rate,
+ struct msp_protdesc *prot_desc)
+{
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+
+ u32 frame_length = MSP_FRAME_LEN_1;
+ prot_desc->frame_width = 0;
+
+ switch (drvdata->slots) {
+ case 1:
+ frame_length = MSP_FRAME_LEN_1;
+ break;
+
+ case 2:
+ frame_length = MSP_FRAME_LEN_2;
+ break;
+
+ case 8:
+ frame_length = MSP_FRAME_LEN_8;
+ break;
+
+ case 16:
+ frame_length = MSP_FRAME_LEN_16;
+ break;
+ default:
+ dev_err(dai->dev,
+ "%s: Error: Unsupported slot-count (slots = %d)!\n",
+ __func__, drvdata->slots);
+ return -EINVAL;
+ }
+
+ prot_desc->tx_frame_len_1 = frame_length;
+ prot_desc->rx_frame_len_1 = frame_length;
+ prot_desc->tx_frame_len_2 = frame_length;
+ prot_desc->rx_frame_len_2 = frame_length;
+
+ prot_desc->tx_elem_len_1 = MSP_ELEM_LEN_16;
+ prot_desc->rx_elem_len_1 = MSP_ELEM_LEN_16;
+ prot_desc->tx_elem_len_2 = MSP_ELEM_LEN_16;
+ prot_desc->rx_elem_len_2 = MSP_ELEM_LEN_16;
+
+ return setup_frameper(dai, rate, prot_desc);
+}
+
+static int setup_clocking(struct snd_soc_dai *dai,
+ unsigned int fmt,
+ struct ux500_msp_config *msp_config)
+{
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+
+ case SND_SOC_DAIFMT_NB_IF:
+ msp_config->tx_fsync_pol ^= 1 << TFSPOL_SHIFT;
+ msp_config->rx_fsync_pol ^= 1 << RFSPOL_SHIFT;
+
+ break;
+
+ default:
+ dev_err(dai->dev,
+ "%s: Error: Unsopported inversion (fmt = 0x%x)!\n",
+ __func__, fmt);
+
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ dev_dbg(dai->dev, "%s: Codec is master.\n", __func__);
+
+ msp_config->iodelay = 0x20;
+ msp_config->rx_fsync_sel = 0;
+ msp_config->tx_fsync_sel = 1 << TFSSEL_SHIFT;
+ msp_config->tx_clk_sel = 0;
+ msp_config->rx_clk_sel = 0;
+ msp_config->srg_clk_sel = 0x2 << SCKSEL_SHIFT;
+
+ break;
+
+ case SND_SOC_DAIFMT_CBS_CFS:
+ dev_dbg(dai->dev, "%s: Codec is slave.\n", __func__);
+
+ msp_config->tx_clk_sel = TX_CLK_SEL_SRG;
+ msp_config->tx_fsync_sel = TX_SYNC_SRG_PROG;
+ msp_config->rx_clk_sel = RX_CLK_SEL_SRG;
+ msp_config->rx_fsync_sel = RX_SYNC_SRG;
+ msp_config->srg_clk_sel = 1 << SCKSEL_SHIFT;
+
+ break;
+
+ default:
+ dev_err(dai->dev, "%s: Error: Unsopported master (fmt = 0x%x)!\n",
+ __func__, fmt);
+
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int setup_pcm_protdesc(struct snd_soc_dai *dai,
+ unsigned int fmt,
+ struct msp_protdesc *prot_desc)
+{
+ prot_desc->rx_phase_mode = MSP_SINGLE_PHASE;
+ prot_desc->tx_phase_mode = MSP_SINGLE_PHASE;
+ prot_desc->rx_phase2_start_mode = MSP_PHASE2_START_MODE_IMEDIATE;
+ prot_desc->tx_phase2_start_mode = MSP_PHASE2_START_MODE_IMEDIATE;
+ prot_desc->rx_byte_order = MSP_BTF_MS_BIT_FIRST;
+ prot_desc->tx_byte_order = MSP_BTF_MS_BIT_FIRST;
+ prot_desc->tx_fsync_pol = MSP_FSYNC_POL(MSP_FSYNC_POL_ACT_HI);
+ prot_desc->rx_fsync_pol = MSP_FSYNC_POL_ACT_HI << RFSPOL_SHIFT;
+
+ if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_DSP_A) {
+ dev_dbg(dai->dev, "%s: DSP_A.\n", __func__);
+ prot_desc->rx_clk_pol = MSP_RISING_EDGE;
+ prot_desc->tx_clk_pol = MSP_FALLING_EDGE;
+
+ prot_desc->rx_data_delay = MSP_DELAY_1;
+ prot_desc->tx_data_delay = MSP_DELAY_1;
+ } else {
+ dev_dbg(dai->dev, "%s: DSP_B.\n", __func__);
+ prot_desc->rx_clk_pol = MSP_FALLING_EDGE;
+ prot_desc->tx_clk_pol = MSP_RISING_EDGE;
+
+ prot_desc->rx_data_delay = MSP_DELAY_0;
+ prot_desc->tx_data_delay = MSP_DELAY_0;
+ }
+
+ prot_desc->rx_half_word_swap = MSP_SWAP_NONE;
+ prot_desc->tx_half_word_swap = MSP_SWAP_NONE;
+ prot_desc->compression_mode = MSP_COMPRESS_MODE_LINEAR;
+ prot_desc->expansion_mode = MSP_EXPAND_MODE_LINEAR;
+ prot_desc->frame_sync_ignore = MSP_FSYNC_IGNORE;
+
+ return 0;
+}
+
+static int setup_i2s_protdesc(struct msp_protdesc *prot_desc)
+{
+ prot_desc->rx_phase_mode = MSP_DUAL_PHASE;
+ prot_desc->tx_phase_mode = MSP_DUAL_PHASE;
+ prot_desc->rx_phase2_start_mode = MSP_PHASE2_START_MODE_FSYNC;
+ prot_desc->tx_phase2_start_mode = MSP_PHASE2_START_MODE_FSYNC;
+ prot_desc->rx_byte_order = MSP_BTF_MS_BIT_FIRST;
+ prot_desc->tx_byte_order = MSP_BTF_MS_BIT_FIRST;
+ prot_desc->tx_fsync_pol = MSP_FSYNC_POL(MSP_FSYNC_POL_ACT_LO);
+ prot_desc->rx_fsync_pol = MSP_FSYNC_POL_ACT_LO << RFSPOL_SHIFT;
+
+ prot_desc->rx_frame_len_1 = MSP_FRAME_LEN_1;
+ prot_desc->rx_frame_len_2 = MSP_FRAME_LEN_1;
+ prot_desc->tx_frame_len_1 = MSP_FRAME_LEN_1;
+ prot_desc->tx_frame_len_2 = MSP_FRAME_LEN_1;
+ prot_desc->rx_elem_len_1 = MSP_ELEM_LEN_16;
+ prot_desc->rx_elem_len_2 = MSP_ELEM_LEN_16;
+ prot_desc->tx_elem_len_1 = MSP_ELEM_LEN_16;
+ prot_desc->tx_elem_len_2 = MSP_ELEM_LEN_16;
+
+ prot_desc->rx_clk_pol = MSP_RISING_EDGE;
+ prot_desc->tx_clk_pol = MSP_FALLING_EDGE;
+
+ prot_desc->rx_data_delay = MSP_DELAY_0;
+ prot_desc->tx_data_delay = MSP_DELAY_0;
+
+ prot_desc->tx_half_word_swap = MSP_SWAP_NONE;
+ prot_desc->rx_half_word_swap = MSP_SWAP_NONE;
+ prot_desc->compression_mode = MSP_COMPRESS_MODE_LINEAR;
+ prot_desc->expansion_mode = MSP_EXPAND_MODE_LINEAR;
+ prot_desc->frame_sync_ignore = MSP_FSYNC_IGNORE;
+
+ return 0;
+}
+
+static int setup_msp_config(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai,
+ struct ux500_msp_config *msp_config)
+{
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+ struct msp_protdesc *prot_desc = &msp_config->protdesc;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned int fmt = drvdata->fmt;
+ int ret;
+
+ memset(msp_config, 0, sizeof(*msp_config));
+
+ msp_config->f_inputclk = drvdata->master_clk;
+
+ msp_config->tx_fifo_config = TX_FIFO_ENABLE;
+ msp_config->rx_fifo_config = RX_FIFO_ENABLE;
+ msp_config->def_elem_len = 1;
+ msp_config->direction = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+ MSP_DIR_TX : MSP_DIR_RX;
+ msp_config->data_size = MSP_DATA_BITS_32;
+ msp_config->frame_freq = runtime->rate;
+
+ dev_dbg(dai->dev, "%s: f_inputclk = %u, frame_freq = %u.\n",
+ __func__, msp_config->f_inputclk, msp_config->frame_freq);
+ /* To avoid division by zero */
+ prot_desc->clocks_per_frame = 1;
+
+ dev_dbg(dai->dev, "%s: rate: %u, channels: %d.\n", __func__,
+ runtime->rate, runtime->channels);
+ switch (fmt &
+ (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
+ dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__);
+
+ msp_config->default_protdesc = 1;
+ msp_config->protocol = MSP_I2S_PROTOCOL;
+ break;
+
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
+ dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__);
+
+ msp_config->data_size = MSP_DATA_BITS_16;
+ msp_config->protocol = MSP_I2S_PROTOCOL;
+
+ ret = setup_i2s_protdesc(prot_desc);
+ if (ret < 0)
+ return ret;
+
+ break;
+
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
+ case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS:
+ case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM:
+ dev_dbg(dai->dev, "%s: PCM format.\n", __func__);
+
+ msp_config->data_size = MSP_DATA_BITS_16;
+ msp_config->protocol = MSP_PCM_PROTOCOL;
+
+ ret = setup_pcm_protdesc(dai, fmt, prot_desc);
+ if (ret < 0)
+ return ret;
+
+ ret = setup_pcm_multichan(dai, msp_config);
+ if (ret < 0)
+ return ret;
+
+ ret = setup_pcm_framing(dai, runtime->rate, prot_desc);
+ if (ret < 0)
+ return ret;
+
+ break;
+
+ default:
+ dev_err(dai->dev, "%s: Error: Unsopported format (%d)!\n",
+ __func__, fmt);
+ return -EINVAL;
+ }
+
+ return setup_clocking(dai, fmt, msp_config);
+}
+
+static int ux500_msp_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ int ret = 0;
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+
+ dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
+ snd_pcm_stream_str(substream));
+
+ /* Enable regulator */
+ ret = regulator_enable(drvdata->reg_vape);
+ if (ret != 0) {
+ dev_err(drvdata->msp->dev,
+ "%s: Failed to enable regulator!\n", __func__);
+ return ret;
+ }
+
+ /* Enable clock */
+ dev_dbg(dai->dev, "%s: Enabling MSP-clock.\n", __func__);
+ clk_enable(drvdata->clk);
+
+ return 0;
+}
+
+static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ int ret;
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+ bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+
+ dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
+ snd_pcm_stream_str(substream));
+
+ if (drvdata->vape_opp_constraint == 1) {
+ prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
+ "ux500_msp_i2s", 50);
+ drvdata->vape_opp_constraint = 0;
+ }
+
+ if (ux500_msp_i2s_close(drvdata->msp,
+ is_playback ? MSP_DIR_TX : MSP_DIR_RX)) {
+ dev_err(dai->dev,
+ "%s: Error: MSP %d (%s): Unable to close i2s.\n",
+ __func__, dai->id, snd_pcm_stream_str(substream));
+ }
+
+ /* Disable clock */
+ clk_disable(drvdata->clk);
+
+ /* Disable regulator */
+ ret = regulator_disable(drvdata->reg_vape);
+ if (ret < 0)
+ dev_err(dai->dev,
+ "%s: ERROR: Failed to disable regulator (%d)!\n",
+ __func__, ret);
+}
+
+static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ int ret = 0;
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct ux500_msp_config msp_config;
+
+ dev_dbg(dai->dev, "%s: MSP %d (%s): Enter (rate = %d).\n", __func__,
+ dai->id, snd_pcm_stream_str(substream), runtime->rate);
+
+ setup_msp_config(substream, dai, &msp_config);
+
+ ret = ux500_msp_i2s_open(drvdata->msp, &msp_config);
+ if (ret < 0) {
+ dev_err(dai->dev, "%s: Error: msp_setup failed (ret = %d)!\n",
+ __func__, ret);
+ return ret;
+ }
+
+ /* Set OPP-level */
+ if ((drvdata->fmt & SND_SOC_DAIFMT_MASTER_MASK) &&
+ (drvdata->msp->f_bitclk > 19200000)) {
+ /* If the bit-clock is higher than 19.2MHz, Vape should be
+ * run in 100% OPP. Only when bit-clock is used (MSP master) */
+ prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
+ "ux500-msp-i2s", 100);
+ drvdata->vape_opp_constraint = 1;
+ } else {
+ prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
+ "ux500-msp-i2s", 50);
+ drvdata->vape_opp_constraint = 0;
+ }
+
+ return ret;
+}
+
+static int ux500_msp_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ unsigned int mask, slots_active;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+
+ dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n",
+ __func__, dai->id, snd_pcm_stream_str(substream));
+
+ switch (drvdata->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ 1, 2);
+ break;
+
+ case SND_SOC_DAIFMT_DSP_B:
+ case SND_SOC_DAIFMT_DSP_A:
+ mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+ drvdata->tx_mask :
+ drvdata->rx_mask;
+
+ slots_active = hweight32(mask);
+ dev_dbg(dai->dev, "TDM-slots active: %d", slots_active);
+
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ slots_active, slots_active);
+ break;
+
+ default:
+ dev_err(dai->dev,
+ "%s: Error: Unsupported protocol (fmt = 0x%x)!\n",
+ __func__, drvdata->fmt);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ux500_msp_dai_set_dai_fmt(struct snd_soc_dai *dai,
+ unsigned int fmt)
+{
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+
+ dev_dbg(dai->dev, "%s: MSP %d: Enter.\n", __func__, dai->id);
+
+ switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK |
+ SND_SOC_DAIFMT_MASTER_MASK)) {
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
+ case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS:
+ case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM:
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
+ break;
+
+ default:
+ dev_err(dai->dev,
+ "%s: Error: Unsupported protocol/master (fmt = 0x%x)!\n",
+ __func__, drvdata->fmt);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ case SND_SOC_DAIFMT_NB_IF:
+ case SND_SOC_DAIFMT_IB_IF:
+ break;
+
+ default:
+ dev_err(dai->dev,
+ "%s: Error: Unsupported inversion (fmt = 0x%x)!\n",
+ __func__, drvdata->fmt);
+ return -EINVAL;
+ }
+
+ drvdata->fmt = fmt;
+ return 0;
+}
+
+static int ux500_msp_dai_set_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int tx_mask,
+ unsigned int rx_mask,
+ int slots, int slot_width)
+{
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+ unsigned int cap;
+
+ switch (slots) {
+ case 1:
+ cap = 0x01;
+ break;
+ case 2:
+ cap = 0x03;
+ break;
+ case 8:
+ cap = 0xFF;
+ break;
+ case 16:
+ cap = 0xFFFF;
+ break;
+ default:
+ dev_err(dai->dev, "%s: Error: Unsupported slot-count (%d)!\n",
+ __func__, slots);
+ return -EINVAL;
+ }
+ drvdata->slots = slots;
+
+ if (!(slot_width == 16)) {
+ dev_err(dai->dev, "%s: Error: Unsupported slot-width (%d)!\n",
+ __func__, slot_width);
+ return -EINVAL;
+ }
+ drvdata->slot_width = slot_width;
+
+ drvdata->tx_mask = tx_mask & cap;
+ drvdata->rx_mask = rx_mask & cap;
+
+ return 0;
+}
+
+static int ux500_msp_dai_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+
+ dev_dbg(dai->dev, "%s: MSP %d: Enter. clk-id: %d, freq: %u.\n",
+ __func__, dai->id, clk_id, freq);
+
+ switch (clk_id) {
+ case UX500_MSP_MASTER_CLOCK:
+ drvdata->master_clk = freq;
+ break;
+
+ default:
+ dev_err(dai->dev, "%s: MSP %d: Invalid clk-id (%d)!\n",
+ __func__, dai->id, clk_id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ int ret = 0;
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+
+ dev_dbg(dai->dev, "%s: MSP %d (%s): Enter (msp->id = %d, cmd = %d).\n",
+ __func__, dai->id, snd_pcm_stream_str(substream),
+ (int)drvdata->msp->id, cmd);
+
+ ret = ux500_msp_i2s_trigger(drvdata->msp, cmd, substream->stream);
+
+ return ret;
+}
+
+static int ux500_msp_dai_probe(struct snd_soc_dai *dai)
+{
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+
+ drvdata->playback_dma_data.dma_cfg = drvdata->msp->dma_cfg_tx;
+ drvdata->capture_dma_data.dma_cfg = drvdata->msp->dma_cfg_rx;
+
+ dai->playback_dma_data = &drvdata->playback_dma_data;
+ dai->capture_dma_data = &drvdata->capture_dma_data;
+
+ drvdata->playback_dma_data.data_size = drvdata->slot_width;
+ drvdata->capture_dma_data.data_size = drvdata->slot_width;
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops ux500_msp_dai_ops[] = {
+ {
+ .set_sysclk = ux500_msp_dai_set_dai_sysclk,
+ .set_fmt = ux500_msp_dai_set_dai_fmt,
+ .set_tdm_slot = ux500_msp_dai_set_tdm_slot,
+ .startup = ux500_msp_dai_startup,
+ .shutdown = ux500_msp_dai_shutdown,
+ .prepare = ux500_msp_dai_prepare,
+ .trigger = ux500_msp_dai_trigger,
+ .hw_params = ux500_msp_dai_hw_params,
+ }
+};
+
+static struct snd_soc_dai_driver ux500_msp_dai_drv[UX500_NBR_OF_DAI] = {
+ {
+ .name = "ux500-msp-i2s.0",
+ .probe = ux500_msp_dai_probe,
+ .id = 0,
+ .suspend = NULL,
+ .resume = NULL,
+ .playback = {
+ .channels_min = UX500_MSP_MIN_CHANNELS,
+ .channels_max = UX500_MSP_MAX_CHANNELS,
+ .rates = UX500_I2S_RATES,
+ .formats = UX500_I2S_FORMATS,
+ },
+ .capture = {
+ .channels_min = UX500_MSP_MIN_CHANNELS,
+ .channels_max = UX500_MSP_MAX_CHANNELS,
+ .rates = UX500_I2S_RATES,
+ .formats = UX500_I2S_FORMATS,
+ },
+ .ops = ux500_msp_dai_ops,
+ },
+ {
+ .name = "ux500-msp-i2s.1",
+ .probe = ux500_msp_dai_probe,
+ .id = 1,
+ .suspend = NULL,
+ .resume = NULL,
+ .playback = {
+ .channels_min = UX500_MSP_MIN_CHANNELS,
+ .channels_max = UX500_MSP_MAX_CHANNELS,
+ .rates = UX500_I2S_RATES,
+ .formats = UX500_I2S_FORMATS,
+ },
+ .capture = {
+ .channels_min = UX500_MSP_MIN_CHANNELS,
+ .channels_max = UX500_MSP_MAX_CHANNELS,
+ .rates = UX500_I2S_RATES,
+ .formats = UX500_I2S_FORMATS,
+ },
+ .ops = ux500_msp_dai_ops,
+ },
+ {
+ .name = "ux500-msp-i2s.2",
+ .id = 2,
+ .probe = ux500_msp_dai_probe,
+ .suspend = NULL,
+ .resume = NULL,
+ .playback = {
+ .channels_min = UX500_MSP_MIN_CHANNELS,
+ .channels_max = UX500_MSP_MAX_CHANNELS,
+ .rates = UX500_I2S_RATES,
+ .formats = UX500_I2S_FORMATS,
+ },
+ .capture = {
+ .channels_min = UX500_MSP_MIN_CHANNELS,
+ .channels_max = UX500_MSP_MAX_CHANNELS,
+ .rates = UX500_I2S_RATES,
+ .formats = UX500_I2S_FORMATS,
+ },
+ .ops = ux500_msp_dai_ops,
+ },
+ {
+ .name = "ux500-msp-i2s.3",
+ .probe = ux500_msp_dai_probe,
+ .id = 3,
+ .suspend = NULL,
+ .resume = NULL,
+ .playback = {
+ .channels_min = UX500_MSP_MIN_CHANNELS,
+ .channels_max = UX500_MSP_MAX_CHANNELS,
+ .rates = UX500_I2S_RATES,
+ .formats = UX500_I2S_FORMATS,
+ },
+ .capture = {
+ .channels_min = UX500_MSP_MIN_CHANNELS,
+ .channels_max = UX500_MSP_MAX_CHANNELS,
+ .rates = UX500_I2S_RATES,
+ .formats = UX500_I2S_FORMATS,
+ },
+ .ops = ux500_msp_dai_ops,
+ },
+};
+
+static int __devinit ux500_msp_drv_probe(struct platform_device *pdev)
+{
+ struct ux500_msp_i2s_drvdata *drvdata;
+ int ret = 0;
+
+ dev_dbg(&pdev->dev, "%s: Enter (pdev->name = %s).\n", __func__,
+ pdev->name);
+
+ drvdata = devm_kzalloc(&pdev->dev,
+ sizeof(struct ux500_msp_i2s_drvdata),
+ GFP_KERNEL);
+ drvdata->fmt = 0;
+ drvdata->slots = 1;
+ drvdata->tx_mask = 0x01;
+ drvdata->rx_mask = 0x01;
+ drvdata->slot_width = 16;
+ drvdata->master_clk = MSP_INPUT_FREQ_APB;
+
+ drvdata->reg_vape = devm_regulator_get(&pdev->dev, "v-ape");
+ if (IS_ERR(drvdata->reg_vape)) {
+ ret = (int)PTR_ERR(drvdata->reg_vape);
+ dev_err(&pdev->dev,
+ "%s: ERROR: Failed to get Vape supply (%d)!\n",
+ __func__, ret);
+ return ret;
+ }
+ prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char *)pdev->name, 50);
+
+ drvdata->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(drvdata->clk)) {
+ ret = (int)PTR_ERR(drvdata->clk);
+ dev_err(&pdev->dev, "%s: ERROR: clk_get failed (%d)!\n",
+ __func__, ret);
+ goto err_clk;
+ }
+
+ ret = ux500_msp_i2s_init_msp(pdev, &drvdata->msp,
+ pdev->dev.platform_data);
+ if (!drvdata->msp) {
+ dev_err(&pdev->dev,
+ "%s: ERROR: Failed to init MSP-struct (%d)!",
+ __func__, ret);
+ goto err_init_msp;
+ }
+ dev_set_drvdata(&pdev->dev, drvdata);
+
+ ret = snd_soc_register_dai(&pdev->dev,
+ &ux500_msp_dai_drv[drvdata->msp->id]);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n",
+ __func__, drvdata->msp->id);
+ goto err_init_msp;
+ }
+
+ return 0;
+
+err_init_msp:
+ clk_put(drvdata->clk);
+
+err_clk:
+ devm_regulator_put(drvdata->reg_vape);
+
+ return ret;
+}
+
+static int __devexit ux500_msp_drv_remove(struct platform_device *pdev)
+{
+ struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
+
+ snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(ux500_msp_dai_drv));
+
+ devm_regulator_put(drvdata->reg_vape);
+ prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s");
+
+ clk_put(drvdata->clk);
+
+ ux500_msp_i2s_cleanup_msp(pdev, drvdata->msp);
+
+ return 0;
+}
+
+static struct platform_driver msp_i2s_driver = {
+ .driver = {
+ .name = "ux500-msp-i2s",
+ .owner = THIS_MODULE,
+ },
+ .probe = ux500_msp_drv_probe,
+ .remove = ux500_msp_drv_remove,
+};
+module_platform_driver(msp_i2s_driver);
+
+MODULE_LICENSE("GPLv2");
diff --git a/sound/soc/ux500/ux500_msp_dai.h b/sound/soc/ux500/ux500_msp_dai.h
new file mode 100644
index 000000000000..98202a34a5dd
--- /dev/null
+++ b/sound/soc/ux500/ux500_msp_dai.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
+ * Roger Nilsson <roger.xr.nilsson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms:
+ *
+ * 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 UX500_msp_dai_H
+#define UX500_msp_dai_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+
+#include "ux500_msp_i2s.h"
+
+#define UX500_NBR_OF_DAI 4
+
+#define UX500_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \
+ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+
+#define UX500_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
+
+#define FRAME_PER_SINGLE_SLOT_8_KHZ 31
+#define FRAME_PER_SINGLE_SLOT_16_KHZ 124
+#define FRAME_PER_SINGLE_SLOT_44_1_KHZ 63
+#define FRAME_PER_SINGLE_SLOT_48_KHZ 49
+#define FRAME_PER_2_SLOTS 31
+#define FRAME_PER_8_SLOTS 138
+#define FRAME_PER_16_SLOTS 277
+
+#ifndef CONFIG_SND_SOC_UX500_AB5500
+#define UX500_MSP_INTERNAL_CLOCK_FREQ 40000000
+#define UX500_MSP1_INTERNAL_CLOCK_FREQ UX500_MSP_INTERNAL_CLOCK_FREQ
+#else
+#define UX500_MSP_INTERNAL_CLOCK_FREQ 13000000
+#define UX500_MSP1_INTERNAL_CLOCK_FREQ (UX500_MSP_INTERNAL_CLOCK_FREQ * 2)
+#endif
+
+#define UX500_MSP_MIN_CHANNELS 1
+#define UX500_MSP_MAX_CHANNELS 8
+
+#define PLAYBACK_CONFIGURED 1
+#define CAPTURE_CONFIGURED 2
+
+enum ux500_msp_clock_id {
+ UX500_MSP_MASTER_CLOCK,
+};
+
+struct ux500_msp_i2s_drvdata {
+ struct ux500_msp *msp;
+ struct regulator *reg_vape;
+ struct ux500_msp_dma_params playback_dma_data;
+ struct ux500_msp_dma_params capture_dma_data;
+ unsigned int fmt;
+ unsigned int tx_mask;
+ unsigned int rx_mask;
+ int slots;
+ int slot_width;
+ u8 configured;
+ int data_delay;
+
+ /* Clocks */
+ unsigned int master_clk;
+ struct clk *clk;
+
+ /* Regulators */
+ int vape_opp_constraint;
+};
+
+int ux500_msp_dai_set_data_delay(struct snd_soc_dai *dai, int delay);
+
+#endif
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c
new file mode 100644
index 000000000000..496dec10c96e
--- /dev/null
+++ b/sound/soc/ux500/ux500_msp_i2s.c
@@ -0,0 +1,742 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
+ * Roger Nilsson <roger.xr.nilsson@stericsson.com>,
+ * Sandeep Kaushik <sandeep.kaushik@st.com>
+ * for ST-Ericsson.
+ *
+ * License terms:
+ *
+ * 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/slab.h>
+
+#include <mach/hardware.h>
+#include <mach/board-mop500-msp.h>
+
+#include <sound/soc.h>
+
+#include "ux500_msp_i2s.h"
+
+ /* Protocol desciptors */
+static const struct msp_protdesc prot_descs[] = {
+ { /* I2S */
+ MSP_SINGLE_PHASE,
+ MSP_SINGLE_PHASE,
+ MSP_PHASE2_START_MODE_IMEDIATE,
+ MSP_PHASE2_START_MODE_IMEDIATE,
+ MSP_BTF_MS_BIT_FIRST,
+ MSP_BTF_MS_BIT_FIRST,
+ MSP_FRAME_LEN_1,
+ MSP_FRAME_LEN_1,
+ MSP_FRAME_LEN_1,
+ MSP_FRAME_LEN_1,
+ MSP_ELEM_LEN_32,
+ MSP_ELEM_LEN_32,
+ MSP_ELEM_LEN_32,
+ MSP_ELEM_LEN_32,
+ MSP_DELAY_1,
+ MSP_DELAY_1,
+ MSP_RISING_EDGE,
+ MSP_FALLING_EDGE,
+ MSP_FSYNC_POL_ACT_LO,
+ MSP_FSYNC_POL_ACT_LO,
+ MSP_SWAP_NONE,
+ MSP_SWAP_NONE,
+ MSP_COMPRESS_MODE_LINEAR,
+ MSP_EXPAND_MODE_LINEAR,
+ MSP_FSYNC_IGNORE,
+ 31,
+ 15,
+ 32,
+ }, { /* PCM */
+ MSP_DUAL_PHASE,
+ MSP_DUAL_PHASE,
+ MSP_PHASE2_START_MODE_FSYNC,
+ MSP_PHASE2_START_MODE_FSYNC,
+ MSP_BTF_MS_BIT_FIRST,
+ MSP_BTF_MS_BIT_FIRST,
+ MSP_FRAME_LEN_1,
+ MSP_FRAME_LEN_1,
+ MSP_FRAME_LEN_1,
+ MSP_FRAME_LEN_1,
+ MSP_ELEM_LEN_16,
+ MSP_ELEM_LEN_16,
+ MSP_ELEM_LEN_16,
+ MSP_ELEM_LEN_16,
+ MSP_DELAY_0,
+ MSP_DELAY_0,
+ MSP_RISING_EDGE,
+ MSP_FALLING_EDGE,
+ MSP_FSYNC_POL_ACT_HI,
+ MSP_FSYNC_POL_ACT_HI,
+ MSP_SWAP_NONE,
+ MSP_SWAP_NONE,
+ MSP_COMPRESS_MODE_LINEAR,
+ MSP_EXPAND_MODE_LINEAR,
+ MSP_FSYNC_IGNORE,
+ 255,
+ 0,
+ 256,
+ }, { /* Companded PCM */
+ MSP_SINGLE_PHASE,
+ MSP_SINGLE_PHASE,
+ MSP_PHASE2_START_MODE_FSYNC,
+ MSP_PHASE2_START_MODE_FSYNC,
+ MSP_BTF_MS_BIT_FIRST,
+ MSP_BTF_MS_BIT_FIRST,
+ MSP_FRAME_LEN_1,
+ MSP_FRAME_LEN_1,
+ MSP_FRAME_LEN_1,
+ MSP_FRAME_LEN_1,
+ MSP_ELEM_LEN_8,
+ MSP_ELEM_LEN_8,
+ MSP_ELEM_LEN_8,
+ MSP_ELEM_LEN_8,
+ MSP_DELAY_0,
+ MSP_DELAY_0,
+ MSP_RISING_EDGE,
+ MSP_RISING_EDGE,
+ MSP_FSYNC_POL_ACT_HI,
+ MSP_FSYNC_POL_ACT_HI,
+ MSP_SWAP_NONE,
+ MSP_SWAP_NONE,
+ MSP_COMPRESS_MODE_LINEAR,
+ MSP_EXPAND_MODE_LINEAR,
+ MSP_FSYNC_IGNORE,
+ 255,
+ 0,
+ 256,
+ },
+};
+
+static void set_prot_desc_tx(struct ux500_msp *msp,
+ struct msp_protdesc *protdesc,
+ enum msp_data_size data_size)
+{
+ u32 temp_reg = 0;
+
+ temp_reg |= MSP_P2_ENABLE_BIT(protdesc->tx_phase_mode);
+ temp_reg |= MSP_P2_START_MODE_BIT(protdesc->tx_phase2_start_mode);
+ temp_reg |= MSP_P1_FRAME_LEN_BITS(protdesc->tx_frame_len_1);
+ temp_reg |= MSP_P2_FRAME_LEN_BITS(protdesc->tx_frame_len_2);
+ if (msp->def_elem_len) {
+ temp_reg |= MSP_P1_ELEM_LEN_BITS(protdesc->tx_elem_len_1);
+ temp_reg |= MSP_P2_ELEM_LEN_BITS(protdesc->tx_elem_len_2);
+ } else {
+ temp_reg |= MSP_P1_ELEM_LEN_BITS(data_size);
+ temp_reg |= MSP_P2_ELEM_LEN_BITS(data_size);
+ }
+ temp_reg |= MSP_DATA_DELAY_BITS(protdesc->tx_data_delay);
+ temp_reg |= MSP_SET_ENDIANNES_BIT(protdesc->tx_byte_order);
+ temp_reg |= MSP_FSYNC_POL(protdesc->tx_fsync_pol);
+ temp_reg |= MSP_DATA_WORD_SWAP(protdesc->tx_half_word_swap);
+ temp_reg |= MSP_SET_COMPANDING_MODE(protdesc->compression_mode);
+ temp_reg |= MSP_SET_FSYNC_IGNORE(protdesc->frame_sync_ignore);
+
+ writel(temp_reg, msp->registers + MSP_TCF);
+}
+
+static void set_prot_desc_rx(struct ux500_msp *msp,
+ struct msp_protdesc *protdesc,
+ enum msp_data_size data_size)
+{
+ u32 temp_reg = 0;
+
+ temp_reg |= MSP_P2_ENABLE_BIT(protdesc->rx_phase_mode);
+ temp_reg |= MSP_P2_START_MODE_BIT(protdesc->rx_phase2_start_mode);
+ temp_reg |= MSP_P1_FRAME_LEN_BITS(protdesc->rx_frame_len_1);
+ temp_reg |= MSP_P2_FRAME_LEN_BITS(protdesc->rx_frame_len_2);
+ if (msp->def_elem_len) {
+ temp_reg |= MSP_P1_ELEM_LEN_BITS(protdesc->rx_elem_len_1);
+ temp_reg |= MSP_P2_ELEM_LEN_BITS(protdesc->rx_elem_len_2);
+ } else {
+ temp_reg |= MSP_P1_ELEM_LEN_BITS(data_size);
+ temp_reg |= MSP_P2_ELEM_LEN_BITS(data_size);
+ }
+
+ temp_reg |= MSP_DATA_DELAY_BITS(protdesc->rx_data_delay);
+ temp_reg |= MSP_SET_ENDIANNES_BIT(protdesc->rx_byte_order);
+ temp_reg |= MSP_FSYNC_POL(protdesc->rx_fsync_pol);
+ temp_reg |= MSP_DATA_WORD_SWAP(protdesc->rx_half_word_swap);
+ temp_reg |= MSP_SET_COMPANDING_MODE(protdesc->expansion_mode);
+ temp_reg |= MSP_SET_FSYNC_IGNORE(protdesc->frame_sync_ignore);
+
+ writel(temp_reg, msp->registers + MSP_RCF);
+}
+
+static int configure_protocol(struct ux500_msp *msp,
+ struct ux500_msp_config *config)
+{
+ struct msp_protdesc *protdesc;
+ enum msp_data_size data_size;
+ u32 temp_reg = 0;
+
+ data_size = config->data_size;
+ msp->def_elem_len = config->def_elem_len;
+ if (config->default_protdesc == 1) {
+ if (config->protocol >= MSP_INVALID_PROTOCOL) {
+ dev_err(msp->dev, "%s: ERROR: Invalid protocol!\n",
+ __func__);
+ return -EINVAL;
+ }
+ protdesc =
+ (struct msp_protdesc *)&prot_descs[config->protocol];
+ } else {
+ protdesc = (struct msp_protdesc *)&config->protdesc;
+ }
+
+ if (data_size < MSP_DATA_BITS_DEFAULT || data_size > MSP_DATA_BITS_32) {
+ dev_err(msp->dev,
+ "%s: ERROR: Invalid data-size requested (data_size = %d)!\n",
+ __func__, data_size);
+ return -EINVAL;
+ }
+
+ if (config->direction & MSP_DIR_TX)
+ set_prot_desc_tx(msp, protdesc, data_size);
+ if (config->direction & MSP_DIR_RX)
+ set_prot_desc_rx(msp, protdesc, data_size);
+
+ /* The code below should not be separated. */
+ temp_reg = readl(msp->registers + MSP_GCR) & ~TX_CLK_POL_RISING;
+ temp_reg |= MSP_TX_CLKPOL_BIT(~protdesc->tx_clk_pol);
+ writel(temp_reg, msp->registers + MSP_GCR);
+ temp_reg = readl(msp->registers + MSP_GCR) & ~RX_CLK_POL_RISING;
+ temp_reg |= MSP_RX_CLKPOL_BIT(protdesc->rx_clk_pol);
+ writel(temp_reg, msp->registers + MSP_GCR);
+
+ return 0;
+}
+
+static int setup_bitclk(struct ux500_msp *msp, struct ux500_msp_config *config)
+{
+ u32 reg_val_GCR;
+ u32 frame_per = 0;
+ u32 sck_div = 0;
+ u32 frame_width = 0;
+ u32 temp_reg = 0;
+ struct msp_protdesc *protdesc = NULL;
+
+ reg_val_GCR = readl(msp->registers + MSP_GCR);
+ writel(reg_val_GCR & ~SRG_ENABLE, msp->registers + MSP_GCR);
+
+ if (config->default_protdesc)
+ protdesc =
+ (struct msp_protdesc *)&prot_descs[config->protocol];
+ else
+ protdesc = (struct msp_protdesc *)&config->protdesc;
+
+ switch (config->protocol) {
+ case MSP_PCM_PROTOCOL:
+ case MSP_PCM_COMPAND_PROTOCOL:
+ frame_width = protdesc->frame_width;
+ sck_div = config->f_inputclk / (config->frame_freq *
+ (protdesc->clocks_per_frame));
+ frame_per = protdesc->frame_period;
+ break;
+ case MSP_I2S_PROTOCOL:
+ frame_width = protdesc->frame_width;
+ sck_div = config->f_inputclk / (config->frame_freq *
+ (protdesc->clocks_per_frame));
+ frame_per = protdesc->frame_period;
+ break;
+ default:
+ dev_err(msp->dev, "%s: ERROR: Unknown protocol (%d)!\n",
+ __func__,
+ config->protocol);
+ return -EINVAL;
+ }
+
+ temp_reg = (sck_div - 1) & SCK_DIV_MASK;
+ temp_reg |= FRAME_WIDTH_BITS(frame_width);
+ temp_reg |= FRAME_PERIOD_BITS(frame_per);
+ writel(temp_reg, msp->registers + MSP_SRG);
+
+ msp->f_bitclk = (config->f_inputclk)/(sck_div + 1);
+
+ /* Enable bit-clock */
+ udelay(100);
+ reg_val_GCR = readl(msp->registers + MSP_GCR);
+ writel(reg_val_GCR | SRG_ENABLE, msp->registers + MSP_GCR);
+ udelay(100);
+
+ return 0;
+}
+
+static int configure_multichannel(struct ux500_msp *msp,
+ struct ux500_msp_config *config)
+{
+ struct msp_protdesc *protdesc;
+ struct msp_multichannel_config *mcfg;
+ u32 reg_val_MCR;
+
+ if (config->default_protdesc == 1) {
+ if (config->protocol >= MSP_INVALID_PROTOCOL) {
+ dev_err(msp->dev,
+ "%s: ERROR: Invalid protocol (%d)!\n",
+ __func__, config->protocol);
+ return -EINVAL;
+ }
+ protdesc = (struct msp_protdesc *)
+ &prot_descs[config->protocol];
+ } else {
+ protdesc = (struct msp_protdesc *)&config->protdesc;
+ }
+
+ mcfg = &config->multichannel_config;
+ if (mcfg->tx_multichannel_enable) {
+ if (protdesc->tx_phase_mode == MSP_SINGLE_PHASE) {
+ reg_val_MCR = readl(msp->registers + MSP_MCR);
+ writel(reg_val_MCR | (mcfg->tx_multichannel_enable ?
+ 1 << TMCEN_BIT : 0),
+ msp->registers + MSP_MCR);
+ writel(mcfg->tx_channel_0_enable,
+ msp->registers + MSP_TCE0);
+ writel(mcfg->tx_channel_1_enable,
+ msp->registers + MSP_TCE1);
+ writel(mcfg->tx_channel_2_enable,
+ msp->registers + MSP_TCE2);
+ writel(mcfg->tx_channel_3_enable,
+ msp->registers + MSP_TCE3);
+ } else {
+ dev_err(msp->dev,
+ "%s: ERROR: Only single-phase supported (TX-mode: %d)!\n",
+ __func__, protdesc->tx_phase_mode);
+ return -EINVAL;
+ }
+ }
+ if (mcfg->rx_multichannel_enable) {
+ if (protdesc->rx_phase_mode == MSP_SINGLE_PHASE) {
+ reg_val_MCR = readl(msp->registers + MSP_MCR);
+ writel(reg_val_MCR | (mcfg->rx_multichannel_enable ?
+ 1 << RMCEN_BIT : 0),
+ msp->registers + MSP_MCR);
+ writel(mcfg->rx_channel_0_enable,
+ msp->registers + MSP_RCE0);
+ writel(mcfg->rx_channel_1_enable,
+ msp->registers + MSP_RCE1);
+ writel(mcfg->rx_channel_2_enable,
+ msp->registers + MSP_RCE2);
+ writel(mcfg->rx_channel_3_enable,
+ msp->registers + MSP_RCE3);
+ } else {
+ dev_err(msp->dev,
+ "%s: ERROR: Only single-phase supported (RX-mode: %d)!\n",
+ __func__, protdesc->rx_phase_mode);
+ return -EINVAL;
+ }
+ if (mcfg->rx_comparison_enable_mode) {
+ reg_val_MCR = readl(msp->registers + MSP_MCR);
+ writel(reg_val_MCR |
+ (mcfg->rx_comparison_enable_mode << RCMPM_BIT),
+ msp->registers + MSP_MCR);
+
+ writel(mcfg->comparison_mask,
+ msp->registers + MSP_RCM);
+ writel(mcfg->comparison_value,
+ msp->registers + MSP_RCV);
+
+ }
+ }
+
+ return 0;
+}
+
+static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config)
+{
+ int status = 0;
+ u32 reg_val_DMACR, reg_val_GCR;
+
+ /* Check msp state whether in RUN or CONFIGURED Mode */
+ if ((msp->msp_state == MSP_STATE_IDLE) && (msp->plat_init)) {
+ status = msp->plat_init();
+ if (status) {
+ dev_err(msp->dev, "%s: ERROR: Failed to init MSP (%d)!\n",
+ __func__, status);
+ return status;
+ }
+ }
+
+ /* Configure msp with protocol dependent settings */
+ configure_protocol(msp, config);
+ setup_bitclk(msp, config);
+ if (config->multichannel_configured == 1) {
+ status = configure_multichannel(msp, config);
+ if (status)
+ dev_warn(msp->dev,
+ "%s: WARN: configure_multichannel failed (%d)!\n",
+ __func__, status);
+ }
+
+ /* Make sure the correct DMA-directions are configured */
+ if ((config->direction & MSP_DIR_RX) && (!msp->dma_cfg_rx)) {
+ dev_err(msp->dev, "%s: ERROR: MSP RX-mode is not configured!",
+ __func__);
+ return -EINVAL;
+ }
+ if ((config->direction == MSP_DIR_TX) && (!msp->dma_cfg_tx)) {
+ dev_err(msp->dev, "%s: ERROR: MSP TX-mode is not configured!",
+ __func__);
+ return -EINVAL;
+ }
+
+ reg_val_DMACR = readl(msp->registers + MSP_DMACR);
+ if (config->direction & MSP_DIR_RX)
+ reg_val_DMACR |= RX_DMA_ENABLE;
+ if (config->direction & MSP_DIR_TX)
+ reg_val_DMACR |= TX_DMA_ENABLE;
+ writel(reg_val_DMACR, msp->registers + MSP_DMACR);
+
+ writel(config->iodelay, msp->registers + MSP_IODLY);
+
+ /* Enable frame generation logic */
+ reg_val_GCR = readl(msp->registers + MSP_GCR);
+ writel(reg_val_GCR | FRAME_GEN_ENABLE, msp->registers + MSP_GCR);
+
+ return status;
+}
+
+static void flush_fifo_rx(struct ux500_msp *msp)
+{
+ u32 reg_val_DR, reg_val_GCR, reg_val_FLR;
+ u32 limit = 32;
+
+ reg_val_GCR = readl(msp->registers + MSP_GCR);
+ writel(reg_val_GCR | RX_ENABLE, msp->registers + MSP_GCR);
+
+ reg_val_FLR = readl(msp->registers + MSP_FLR);
+ while (!(reg_val_FLR & RX_FIFO_EMPTY) && limit--) {
+ reg_val_DR = readl(msp->registers + MSP_DR);
+ reg_val_FLR = readl(msp->registers + MSP_FLR);
+ }
+
+ writel(reg_val_GCR, msp->registers + MSP_GCR);
+}
+
+static void flush_fifo_tx(struct ux500_msp *msp)
+{
+ u32 reg_val_TSTDR, reg_val_GCR, reg_val_FLR;
+ u32 limit = 32;
+
+ reg_val_GCR = readl(msp->registers + MSP_GCR);
+ writel(reg_val_GCR | TX_ENABLE, msp->registers + MSP_GCR);
+ writel(MSP_ITCR_ITEN | MSP_ITCR_TESTFIFO, msp->registers + MSP_ITCR);
+
+ reg_val_FLR = readl(msp->registers + MSP_FLR);
+ while (!(reg_val_FLR & TX_FIFO_EMPTY) && limit--) {
+ reg_val_TSTDR = readl(msp->registers + MSP_TSTDR);
+ reg_val_FLR = readl(msp->registers + MSP_FLR);
+ }
+ writel(0x0, msp->registers + MSP_ITCR);
+ writel(reg_val_GCR, msp->registers + MSP_GCR);
+}
+
+int ux500_msp_i2s_open(struct ux500_msp *msp,
+ struct ux500_msp_config *config)
+{
+ u32 old_reg, new_reg, mask;
+ int res;
+ unsigned int tx_sel, rx_sel, tx_busy, rx_busy;
+
+ if (in_interrupt()) {
+ dev_err(msp->dev,
+ "%s: ERROR: Open called in interrupt context!\n",
+ __func__);
+ return -1;
+ }
+
+ tx_sel = (config->direction & MSP_DIR_TX) > 0;
+ rx_sel = (config->direction & MSP_DIR_RX) > 0;
+ if (!tx_sel && !rx_sel) {
+ dev_err(msp->dev, "%s: Error: No direction selected!\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ tx_busy = (msp->dir_busy & MSP_DIR_TX) > 0;
+ rx_busy = (msp->dir_busy & MSP_DIR_RX) > 0;
+ if (tx_busy && tx_sel) {
+ dev_err(msp->dev, "%s: Error: TX is in use!\n", __func__);
+ return -EBUSY;
+ }
+ if (rx_busy && rx_sel) {
+ dev_err(msp->dev, "%s: Error: RX is in use!\n", __func__);
+ return -EBUSY;
+ }
+
+ msp->dir_busy |= (tx_sel ? MSP_DIR_TX : 0) | (rx_sel ? MSP_DIR_RX : 0);
+
+ /* First do the global config register */
+ mask = RX_CLK_SEL_MASK | TX_CLK_SEL_MASK | RX_FSYNC_MASK |
+ TX_FSYNC_MASK | RX_SYNC_SEL_MASK | TX_SYNC_SEL_MASK |
+ RX_FIFO_ENABLE_MASK | TX_FIFO_ENABLE_MASK | SRG_CLK_SEL_MASK |
+ LOOPBACK_MASK | TX_EXTRA_DELAY_MASK;
+
+ new_reg = (config->tx_clk_sel | config->rx_clk_sel |
+ config->rx_fsync_pol | config->tx_fsync_pol |
+ config->rx_fsync_sel | config->tx_fsync_sel |
+ config->rx_fifo_config | config->tx_fifo_config |
+ config->srg_clk_sel | config->loopback_enable |
+ config->tx_data_enable);
+
+ old_reg = readl(msp->registers + MSP_GCR);
+ old_reg &= ~mask;
+ new_reg |= old_reg;
+ writel(new_reg, msp->registers + MSP_GCR);
+
+ res = enable_msp(msp, config);
+ if (res < 0) {
+ dev_err(msp->dev, "%s: ERROR: enable_msp failed (%d)!\n",
+ __func__, res);
+ return -EBUSY;
+ }
+ if (config->loopback_enable & 0x80)
+ msp->loopback_enable = 1;
+
+ /* Flush FIFOs */
+ flush_fifo_tx(msp);
+ flush_fifo_rx(msp);
+
+ msp->msp_state = MSP_STATE_CONFIGURED;
+ return 0;
+}
+
+static void disable_msp_rx(struct ux500_msp *msp)
+{
+ u32 reg_val_GCR, reg_val_DMACR, reg_val_IMSC;
+
+ reg_val_GCR = readl(msp->registers + MSP_GCR);
+ writel(reg_val_GCR & ~RX_ENABLE, msp->registers + MSP_GCR);
+ reg_val_DMACR = readl(msp->registers + MSP_DMACR);
+ writel(reg_val_DMACR & ~RX_DMA_ENABLE, msp->registers + MSP_DMACR);
+ reg_val_IMSC = readl(msp->registers + MSP_IMSC);
+ writel(reg_val_IMSC &
+ ~(RX_SERVICE_INT | RX_OVERRUN_ERROR_INT),
+ msp->registers + MSP_IMSC);
+
+ msp->dir_busy &= ~MSP_DIR_RX;
+}
+
+static void disable_msp_tx(struct ux500_msp *msp)
+{
+ u32 reg_val_GCR, reg_val_DMACR, reg_val_IMSC;
+
+ reg_val_GCR = readl(msp->registers + MSP_GCR);
+ writel(reg_val_GCR & ~TX_ENABLE, msp->registers + MSP_GCR);
+ reg_val_DMACR = readl(msp->registers + MSP_DMACR);
+ writel(reg_val_DMACR & ~TX_DMA_ENABLE, msp->registers + MSP_DMACR);
+ reg_val_IMSC = readl(msp->registers + MSP_IMSC);
+ writel(reg_val_IMSC &
+ ~(TX_SERVICE_INT | TX_UNDERRUN_ERR_INT),
+ msp->registers + MSP_IMSC);
+
+ msp->dir_busy &= ~MSP_DIR_TX;
+}
+
+static int disable_msp(struct ux500_msp *msp, unsigned int dir)
+{
+ u32 reg_val_GCR;
+ int status = 0;
+ unsigned int disable_tx, disable_rx;
+
+ reg_val_GCR = readl(msp->registers + MSP_GCR);
+ disable_tx = dir & MSP_DIR_TX;
+ disable_rx = dir & MSP_DIR_TX;
+ if (disable_tx && disable_rx) {
+ reg_val_GCR = readl(msp->registers + MSP_GCR);
+ writel(reg_val_GCR | LOOPBACK_MASK,
+ msp->registers + MSP_GCR);
+
+ /* Flush TX-FIFO */
+ flush_fifo_tx(msp);
+
+ /* Disable TX-channel */
+ writel((readl(msp->registers + MSP_GCR) &
+ (~TX_ENABLE)), msp->registers + MSP_GCR);
+
+ /* Flush RX-FIFO */
+ flush_fifo_rx(msp);
+
+ /* Disable Loopback and Receive channel */
+ writel((readl(msp->registers + MSP_GCR) &
+ (~(RX_ENABLE | LOOPBACK_MASK))),
+ msp->registers + MSP_GCR);
+
+ disable_msp_tx(msp);
+ disable_msp_rx(msp);
+ } else if (disable_tx)
+ disable_msp_tx(msp);
+ else if (disable_rx)
+ disable_msp_rx(msp);
+
+ return status;
+}
+
+int ux500_msp_i2s_trigger(struct ux500_msp *msp, int cmd, int direction)
+{
+ u32 reg_val_GCR, enable_bit;
+
+ if (msp->msp_state == MSP_STATE_IDLE) {
+ dev_err(msp->dev, "%s: ERROR: MSP is not configured!\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+ enable_bit = TX_ENABLE;
+ else
+ enable_bit = RX_ENABLE;
+ reg_val_GCR = readl(msp->registers + MSP_GCR);
+ writel(reg_val_GCR | enable_bit, msp->registers + MSP_GCR);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+ disable_msp_tx(msp);
+ else
+ disable_msp_rx(msp);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+
+int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)
+{
+ int status = 0;
+
+ dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir);
+
+ status = disable_msp(msp, dir);
+ if (msp->dir_busy == 0) {
+ /* disable sample rate and frame generators */
+ msp->msp_state = MSP_STATE_IDLE;
+ writel((readl(msp->registers + MSP_GCR) &
+ (~(FRAME_GEN_ENABLE | SRG_ENABLE))),
+ msp->registers + MSP_GCR);
+ if (msp->plat_exit)
+ status = msp->plat_exit();
+ if (status)
+ dev_warn(msp->dev,
+ "%s: WARN: ux500_msp_i2s_exit failed (%d)!\n",
+ __func__, status);
+ writel(0, msp->registers + MSP_GCR);
+ writel(0, msp->registers + MSP_TCF);
+ writel(0, msp->registers + MSP_RCF);
+ writel(0, msp->registers + MSP_DMACR);
+ writel(0, msp->registers + MSP_SRG);
+ writel(0, msp->registers + MSP_MCR);
+ writel(0, msp->registers + MSP_RCM);
+ writel(0, msp->registers + MSP_RCV);
+ writel(0, msp->registers + MSP_TCE0);
+ writel(0, msp->registers + MSP_TCE1);
+ writel(0, msp->registers + MSP_TCE2);
+ writel(0, msp->registers + MSP_TCE3);
+ writel(0, msp->registers + MSP_RCE0);
+ writel(0, msp->registers + MSP_RCE1);
+ writel(0, msp->registers + MSP_RCE2);
+ writel(0, msp->registers + MSP_RCE3);
+ }
+
+ return status;
+
+}
+
+int ux500_msp_i2s_init_msp(struct platform_device *pdev,
+ struct ux500_msp **msp_p,
+ struct msp_i2s_platform_data *platform_data)
+{
+ int ret = 0;
+ struct resource *res = NULL;
+ struct i2s_controller *i2s_cont;
+ struct ux500_msp *msp;
+
+ dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__,
+ pdev->name, platform_data->id);
+
+ *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL);
+ msp = *msp_p;
+
+ msp->id = platform_data->id;
+ msp->dev = &pdev->dev;
+ msp->plat_init = platform_data->msp_i2s_init;
+ msp->plat_exit = platform_data->msp_i2s_exit;
+ msp->dma_cfg_rx = platform_data->msp_i2s_dma_rx;
+ msp->dma_cfg_tx = platform_data->msp_i2s_dma_tx;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "%s: ERROR: Unable to get resource!\n",
+ __func__);
+ ret = -ENOMEM;
+ goto err_res;
+ }
+
+ msp->registers = ioremap(res->start, (res->end - res->start + 1));
+ if (msp->registers == NULL) {
+ dev_err(&pdev->dev, "%s: ERROR: ioremap failed!\n", __func__);
+ ret = -ENOMEM;
+ goto err_res;
+ }
+
+ msp->msp_state = MSP_STATE_IDLE;
+ msp->loopback_enable = 0;
+
+ /* I2S-controller is allocated and added in I2S controller class. */
+ i2s_cont = devm_kzalloc(&pdev->dev, sizeof(*i2s_cont), GFP_KERNEL);
+ if (!i2s_cont) {
+ dev_err(&pdev->dev,
+ "%s: ERROR: Failed to allocate I2S-controller!\n",
+ __func__);
+ goto err_i2s_cont;
+ }
+ i2s_cont->dev.parent = &pdev->dev;
+ i2s_cont->data = (void *)msp;
+ i2s_cont->id = (s16)msp->id;
+ snprintf(i2s_cont->name, sizeof(i2s_cont->name), "ux500-msp-i2s.%04x",
+ msp->id);
+ dev_dbg(&pdev->dev, "I2S device-name: '%s'\n", i2s_cont->name);
+ msp->i2s_cont = i2s_cont;
+
+ return 0;
+
+err_i2s_cont:
+ iounmap(msp->registers);
+
+err_res:
+ devm_kfree(&pdev->dev, msp);
+
+ return ret;
+}
+
+void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,
+ struct ux500_msp *msp)
+{
+ dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id);
+
+ device_unregister(&msp->i2s_cont->dev);
+ devm_kfree(&pdev->dev, msp->i2s_cont);
+
+ iounmap(msp->registers);
+
+ devm_kfree(&pdev->dev, msp);
+}
+
+MODULE_LICENSE("GPLv2");
diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h
new file mode 100644
index 000000000000..7f71b4a0d4bc
--- /dev/null
+++ b/sound/soc/ux500/ux500_msp_i2s.h
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
+ * for ST-Ericsson.
+ *
+ * License terms:
+ *
+ * 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 UX500_MSP_I2S_H
+#define UX500_MSP_I2S_H
+
+#include <linux/platform_device.h>
+
+#include <mach/board-mop500-msp.h>
+
+#define MSP_INPUT_FREQ_APB 48000000
+
+/*** Stereo mode. Used for APB data accesses as 16 bits accesses (mono),
+ * 32 bits accesses (stereo).
+ ***/
+enum msp_stereo_mode {
+ MSP_MONO,
+ MSP_STEREO
+};
+
+/* Direction (Transmit/Receive mode) */
+enum msp_direction {
+ MSP_TX = 1,
+ MSP_RX = 2
+};
+
+/* Transmit and receive configuration register */
+#define MSP_BIG_ENDIAN 0x00000000
+#define MSP_LITTLE_ENDIAN 0x00001000
+#define MSP_UNEXPECTED_FS_ABORT 0x00000000
+#define MSP_UNEXPECTED_FS_IGNORE 0x00008000
+#define MSP_NON_MODE_BIT_MASK 0x00009000
+
+/* Global configuration register */
+#define RX_ENABLE 0x00000001
+#define RX_FIFO_ENABLE 0x00000002
+#define RX_SYNC_SRG 0x00000010
+#define RX_CLK_POL_RISING 0x00000020
+#define RX_CLK_SEL_SRG 0x00000040
+#define TX_ENABLE 0x00000100
+#define TX_FIFO_ENABLE 0x00000200
+#define TX_SYNC_SRG_PROG 0x00001800
+#define TX_SYNC_SRG_AUTO 0x00001000
+#define TX_CLK_POL_RISING 0x00002000
+#define TX_CLK_SEL_SRG 0x00004000
+#define TX_EXTRA_DELAY_ENABLE 0x00008000
+#define SRG_ENABLE 0x00010000
+#define FRAME_GEN_ENABLE 0x00100000
+#define SRG_CLK_SEL_APB 0x00000000
+#define RX_FIFO_SYNC_HI 0x00000000
+#define TX_FIFO_SYNC_HI 0x00000000
+#define SPI_CLK_MODE_NORMAL 0x00000000
+
+#define MSP_FRAME_SIZE_AUTO -1
+
+#define MSP_DR 0x00
+#define MSP_GCR 0x04
+#define MSP_TCF 0x08
+#define MSP_RCF 0x0c
+#define MSP_SRG 0x10
+#define MSP_FLR 0x14
+#define MSP_DMACR 0x18
+
+#define MSP_IMSC 0x20
+#define MSP_RIS 0x24
+#define MSP_MIS 0x28
+#define MSP_ICR 0x2c
+#define MSP_MCR 0x30
+#define MSP_RCV 0x34
+#define MSP_RCM 0x38
+
+#define MSP_TCE0 0x40
+#define MSP_TCE1 0x44
+#define MSP_TCE2 0x48
+#define MSP_TCE3 0x4c
+
+#define MSP_RCE0 0x60
+#define MSP_RCE1 0x64
+#define MSP_RCE2 0x68
+#define MSP_RCE3 0x6c
+#define MSP_IODLY 0x70
+
+#define MSP_ITCR 0x80
+#define MSP_ITIP 0x84
+#define MSP_ITOP 0x88
+#define MSP_TSTDR 0x8c
+
+#define MSP_PID0 0xfe0
+#define MSP_PID1 0xfe4
+#define MSP_PID2 0xfe8
+#define MSP_PID3 0xfec
+
+#define MSP_CID0 0xff0
+#define MSP_CID1 0xff4
+#define MSP_CID2 0xff8
+#define MSP_CID3 0xffc
+
+/* Protocol dependant parameters list */
+#define RX_ENABLE_MASK BIT(0)
+#define RX_FIFO_ENABLE_MASK BIT(1)
+#define RX_FSYNC_MASK BIT(2)
+#define DIRECT_COMPANDING_MASK BIT(3)
+#define RX_SYNC_SEL_MASK BIT(4)
+#define RX_CLK_POL_MASK BIT(5)
+#define RX_CLK_SEL_MASK BIT(6)
+#define LOOPBACK_MASK BIT(7)
+#define TX_ENABLE_MASK BIT(8)
+#define TX_FIFO_ENABLE_MASK BIT(9)
+#define TX_FSYNC_MASK BIT(10)
+#define TX_MSP_TDR_TSR BIT(11)
+#define TX_SYNC_SEL_MASK (BIT(12) | BIT(11))
+#define TX_CLK_POL_MASK BIT(13)
+#define TX_CLK_SEL_MASK BIT(14)
+#define TX_EXTRA_DELAY_MASK BIT(15)
+#define SRG_ENABLE_MASK BIT(16)
+#define SRG_CLK_POL_MASK BIT(17)
+#define SRG_CLK_SEL_MASK (BIT(19) | BIT(18))
+#define FRAME_GEN_EN_MASK BIT(20)
+#define SPI_CLK_MODE_MASK (BIT(22) | BIT(21))
+#define SPI_BURST_MODE_MASK BIT(23)
+
+#define RXEN_SHIFT 0
+#define RFFEN_SHIFT 1
+#define RFSPOL_SHIFT 2
+#define DCM_SHIFT 3
+#define RFSSEL_SHIFT 4
+#define RCKPOL_SHIFT 5
+#define RCKSEL_SHIFT 6
+#define LBM_SHIFT 7
+#define TXEN_SHIFT 8
+#define TFFEN_SHIFT 9
+#define TFSPOL_SHIFT 10
+#define TFSSEL_SHIFT 11
+#define TCKPOL_SHIFT 13
+#define TCKSEL_SHIFT 14
+#define TXDDL_SHIFT 15
+#define SGEN_SHIFT 16
+#define SCKPOL_SHIFT 17
+#define SCKSEL_SHIFT 18
+#define FGEN_SHIFT 20
+#define SPICKM_SHIFT 21
+#define TBSWAP_SHIFT 28
+
+#define RCKPOL_MASK BIT(0)
+#define TCKPOL_MASK BIT(0)
+#define SPICKM_MASK (BIT(1) | BIT(0))
+#define MSP_RX_CLKPOL_BIT(n) ((n & RCKPOL_MASK) << RCKPOL_SHIFT)
+#define MSP_TX_CLKPOL_BIT(n) ((n & TCKPOL_MASK) << TCKPOL_SHIFT)
+
+#define P1ELEN_SHIFT 0
+#define P1FLEN_SHIFT 3
+#define DTYP_SHIFT 10
+#define ENDN_SHIFT 12
+#define DDLY_SHIFT 13
+#define FSIG_SHIFT 15
+#define P2ELEN_SHIFT 16
+#define P2FLEN_SHIFT 19
+#define P2SM_SHIFT 26
+#define P2EN_SHIFT 27
+#define FSYNC_SHIFT 15
+
+#define P1ELEN_MASK 0x00000007
+#define P2ELEN_MASK 0x00070000
+#define P1FLEN_MASK 0x00000378
+#define P2FLEN_MASK 0x03780000
+#define DDLY_MASK 0x00003000
+#define DTYP_MASK 0x00000600
+#define P2SM_MASK 0x04000000
+#define P2EN_MASK 0x08000000
+#define ENDN_MASK 0x00001000
+#define TFSPOL_MASK 0x00000400
+#define TBSWAP_MASK 0x30000000
+#define COMPANDING_MODE_MASK 0x00000c00
+#define FSYNC_MASK 0x00008000
+
+#define MSP_P1_ELEM_LEN_BITS(n) (n & P1ELEN_MASK)
+#define MSP_P2_ELEM_LEN_BITS(n) (((n) << P2ELEN_SHIFT) & P2ELEN_MASK)
+#define MSP_P1_FRAME_LEN_BITS(n) (((n) << P1FLEN_SHIFT) & P1FLEN_MASK)
+#define MSP_P2_FRAME_LEN_BITS(n) (((n) << P2FLEN_SHIFT) & P2FLEN_MASK)
+#define MSP_DATA_DELAY_BITS(n) (((n) << DDLY_SHIFT) & DDLY_MASK)
+#define MSP_DATA_TYPE_BITS(n) (((n) << DTYP_SHIFT) & DTYP_MASK)
+#define MSP_P2_START_MODE_BIT(n) ((n << P2SM_SHIFT) & P2SM_MASK)
+#define MSP_P2_ENABLE_BIT(n) ((n << P2EN_SHIFT) & P2EN_MASK)
+#define MSP_SET_ENDIANNES_BIT(n) ((n << ENDN_SHIFT) & ENDN_MASK)
+#define MSP_FSYNC_POL(n) ((n << TFSPOL_SHIFT) & TFSPOL_MASK)
+#define MSP_DATA_WORD_SWAP(n) ((n << TBSWAP_SHIFT) & TBSWAP_MASK)
+#define MSP_SET_COMPANDING_MODE(n) ((n << DTYP_SHIFT) & \
+ COMPANDING_MODE_MASK)
+#define MSP_SET_FSYNC_IGNORE(n) ((n << FSYNC_SHIFT) & FSYNC_MASK)
+
+/* Flag register */
+#define RX_BUSY BIT(0)
+#define RX_FIFO_EMPTY BIT(1)
+#define RX_FIFO_FULL BIT(2)
+#define TX_BUSY BIT(3)
+#define TX_FIFO_EMPTY BIT(4)
+#define TX_FIFO_FULL BIT(5)
+
+#define RBUSY_SHIFT 0
+#define RFE_SHIFT 1
+#define RFU_SHIFT 2
+#define TBUSY_SHIFT 3
+#define TFE_SHIFT 4
+#define TFU_SHIFT 5
+
+/* Multichannel control register */
+#define RMCEN_SHIFT 0
+#define RMCSF_SHIFT 1
+#define RCMPM_SHIFT 3
+#define TMCEN_SHIFT 5
+#define TNCSF_SHIFT 6
+
+/* Sample rate generator register */
+#define SCKDIV_SHIFT 0
+#define FRWID_SHIFT 10
+#define FRPER_SHIFT 16
+
+#define SCK_DIV_MASK 0x0000003FF
+#define FRAME_WIDTH_BITS(n) (((n) << FRWID_SHIFT) & 0x0000FC00)
+#define FRAME_PERIOD_BITS(n) (((n) << FRPER_SHIFT) & 0x1FFF0000)
+
+/* DMA controller register */
+#define RX_DMA_ENABLE BIT(0)
+#define TX_DMA_ENABLE BIT(1)
+
+#define RDMAE_SHIFT 0
+#define TDMAE_SHIFT 1
+
+/* Interrupt Register */
+#define RX_SERVICE_INT BIT(0)
+#define RX_OVERRUN_ERROR_INT BIT(1)
+#define RX_FSYNC_ERR_INT BIT(2)
+#define RX_FSYNC_INT BIT(3)
+#define TX_SERVICE_INT BIT(4)
+#define TX_UNDERRUN_ERR_INT BIT(5)
+#define TX_FSYNC_ERR_INT BIT(6)
+#define TX_FSYNC_INT BIT(7)
+#define ALL_INT 0x000000ff
+
+/* MSP test control register */
+#define MSP_ITCR_ITEN BIT(0)
+#define MSP_ITCR_TESTFIFO BIT(1)
+
+#define RMCEN_BIT 0
+#define RMCSF_BIT 1
+#define RCMPM_BIT 3
+#define TMCEN_BIT 5
+#define TNCSF_BIT 6
+
+/* Single or dual phase mode */
+enum msp_phase_mode {
+ MSP_SINGLE_PHASE,
+ MSP_DUAL_PHASE
+};
+
+/* Frame length */
+enum msp_frame_length {
+ MSP_FRAME_LEN_1 = 0,
+ MSP_FRAME_LEN_2 = 1,
+ MSP_FRAME_LEN_4 = 3,
+ MSP_FRAME_LEN_8 = 7,
+ MSP_FRAME_LEN_12 = 11,
+ MSP_FRAME_LEN_16 = 15,
+ MSP_FRAME_LEN_20 = 19,
+ MSP_FRAME_LEN_32 = 31,
+ MSP_FRAME_LEN_48 = 47,
+ MSP_FRAME_LEN_64 = 63
+};
+
+/* Element length */
+enum msp_elem_length {
+ MSP_ELEM_LEN_8 = 0,
+ MSP_ELEM_LEN_10 = 1,
+ MSP_ELEM_LEN_12 = 2,
+ MSP_ELEM_LEN_14 = 3,
+ MSP_ELEM_LEN_16 = 4,
+ MSP_ELEM_LEN_20 = 5,
+ MSP_ELEM_LEN_24 = 6,
+ MSP_ELEM_LEN_32 = 7
+};
+
+enum msp_data_xfer_width {
+ MSP_DATA_TRANSFER_WIDTH_BYTE,
+ MSP_DATA_TRANSFER_WIDTH_HALFWORD,
+ MSP_DATA_TRANSFER_WIDTH_WORD
+};
+
+enum msp_frame_sync {
+ MSP_FSYNC_UNIGNORE = 0,
+ MSP_FSYNC_IGNORE = 1,
+};
+
+enum msp_phase2_start_mode {
+ MSP_PHASE2_START_MODE_IMEDIATE,
+ MSP_PHASE2_START_MODE_FSYNC
+};
+
+enum msp_btf {
+ MSP_BTF_MS_BIT_FIRST = 0,
+ MSP_BTF_LS_BIT_FIRST = 1
+};
+
+enum msp_fsync_pol {
+ MSP_FSYNC_POL_ACT_HI = 0,
+ MSP_FSYNC_POL_ACT_LO = 1
+};
+
+/* Data delay (in bit clock cycles) */
+enum msp_delay {
+ MSP_DELAY_0 = 0,
+ MSP_DELAY_1 = 1,
+ MSP_DELAY_2 = 2,
+ MSP_DELAY_3 = 3
+};
+
+/* Configurations of clocks (transmit, receive or sample rate generator) */
+enum msp_edge {
+ MSP_FALLING_EDGE = 0,
+ MSP_RISING_EDGE = 1,
+};
+
+enum msp_hws {
+ MSP_SWAP_NONE = 0,
+ MSP_SWAP_BYTE_PER_WORD = 1,
+ MSP_SWAP_BYTE_PER_HALF_WORD = 2,
+ MSP_SWAP_HALF_WORD_PER_WORD = 3
+};
+
+enum msp_compress_mode {
+ MSP_COMPRESS_MODE_LINEAR = 0,
+ MSP_COMPRESS_MODE_MU_LAW = 2,
+ MSP_COMPRESS_MODE_A_LAW = 3
+};
+
+enum msp_spi_burst_mode {
+ MSP_SPI_BURST_MODE_DISABLE = 0,
+ MSP_SPI_BURST_MODE_ENABLE = 1
+};
+
+enum msp_expand_mode {
+ MSP_EXPAND_MODE_LINEAR = 0,
+ MSP_EXPAND_MODE_LINEAR_SIGNED = 1,
+ MSP_EXPAND_MODE_MU_LAW = 2,
+ MSP_EXPAND_MODE_A_LAW = 3
+};
+
+#define MSP_FRAME_PERIOD_IN_MONO_MODE 256
+#define MSP_FRAME_PERIOD_IN_STEREO_MODE 32
+#define MSP_FRAME_WIDTH_IN_STEREO_MODE 16
+
+enum msp_protocol {
+ MSP_I2S_PROTOCOL,
+ MSP_PCM_PROTOCOL,
+ MSP_PCM_COMPAND_PROTOCOL,
+ MSP_INVALID_PROTOCOL
+};
+
+/*
+ * No of registers to backup during
+ * suspend resume
+ */
+#define MAX_MSP_BACKUP_REGS 36
+
+enum enum_i2s_controller {
+ MSP_0_I2S_CONTROLLER = 0,
+ MSP_1_I2S_CONTROLLER,
+ MSP_2_I2S_CONTROLLER,
+ MSP_3_I2S_CONTROLLER,
+};
+
+enum i2s_direction_t {
+ MSP_DIR_TX = 0x01,
+ MSP_DIR_RX = 0x02,
+};
+
+enum msp_data_size {
+ MSP_DATA_BITS_DEFAULT = -1,
+ MSP_DATA_BITS_8 = 0x00,
+ MSP_DATA_BITS_10,
+ MSP_DATA_BITS_12,
+ MSP_DATA_BITS_14,
+ MSP_DATA_BITS_16,
+ MSP_DATA_BITS_20,
+ MSP_DATA_BITS_24,
+ MSP_DATA_BITS_32,
+};
+
+enum msp_state {
+ MSP_STATE_IDLE = 0,
+ MSP_STATE_CONFIGURED = 1,
+ MSP_STATE_RUNNING = 2,
+};
+
+enum msp_rx_comparison_enable_mode {
+ MSP_COMPARISON_DISABLED = 0,
+ MSP_COMPARISON_NONEQUAL_ENABLED = 2,
+ MSP_COMPARISON_EQUAL_ENABLED = 3
+};
+
+struct msp_multichannel_config {
+ bool rx_multichannel_enable;
+ bool tx_multichannel_enable;
+ enum msp_rx_comparison_enable_mode rx_comparison_enable_mode;
+ u8 padding;
+ u32 comparison_value;
+ u32 comparison_mask;
+ u32 rx_channel_0_enable;
+ u32 rx_channel_1_enable;
+ u32 rx_channel_2_enable;
+ u32 rx_channel_3_enable;
+ u32 tx_channel_0_enable;
+ u32 tx_channel_1_enable;
+ u32 tx_channel_2_enable;
+ u32 tx_channel_3_enable;
+};
+
+struct msp_protdesc {
+ u32 rx_phase_mode;
+ u32 tx_phase_mode;
+ u32 rx_phase2_start_mode;
+ u32 tx_phase2_start_mode;
+ u32 rx_byte_order;
+ u32 tx_byte_order;
+ u32 rx_frame_len_1;
+ u32 rx_frame_len_2;
+ u32 tx_frame_len_1;
+ u32 tx_frame_len_2;
+ u32 rx_elem_len_1;
+ u32 rx_elem_len_2;
+ u32 tx_elem_len_1;
+ u32 tx_elem_len_2;
+ u32 rx_data_delay;
+ u32 tx_data_delay;
+ u32 rx_clk_pol;
+ u32 tx_clk_pol;
+ u32 rx_fsync_pol;
+ u32 tx_fsync_pol;
+ u32 rx_half_word_swap;
+ u32 tx_half_word_swap;
+ u32 compression_mode;
+ u32 expansion_mode;
+ u32 frame_sync_ignore;
+ u32 frame_period;
+ u32 frame_width;
+ u32 clocks_per_frame;
+};
+
+struct i2s_message {
+ enum i2s_direction_t i2s_direction;
+ void *txdata;
+ void *rxdata;
+ size_t txbytes;
+ size_t rxbytes;
+ int dma_flag;
+ int tx_offset;
+ int rx_offset;
+ bool cyclic_dma;
+ dma_addr_t buf_addr;
+ size_t buf_len;
+ size_t period_len;
+};
+
+struct i2s_controller {
+ struct module *owner;
+ unsigned int id;
+ unsigned int class;
+ const struct i2s_algorithm *algo; /* the algorithm to access the bus */
+ void *data;
+ struct mutex bus_lock;
+ struct device dev; /* the controller device */
+ char name[48];
+};
+
+struct ux500_msp_config {
+ unsigned int f_inputclk;
+ unsigned int rx_clk_sel;
+ unsigned int tx_clk_sel;
+ unsigned int srg_clk_sel;
+ unsigned int rx_fsync_pol;
+ unsigned int tx_fsync_pol;
+ unsigned int rx_fsync_sel;
+ unsigned int tx_fsync_sel;
+ unsigned int rx_fifo_config;
+ unsigned int tx_fifo_config;
+ unsigned int spi_clk_mode;
+ unsigned int spi_burst_mode;
+ unsigned int loopback_enable;
+ unsigned int tx_data_enable;
+ unsigned int default_protdesc;
+ struct msp_protdesc protdesc;
+ int multichannel_configured;
+ struct msp_multichannel_config multichannel_config;
+ unsigned int direction;
+ unsigned int protocol;
+ unsigned int frame_freq;
+ unsigned int frame_size;
+ enum msp_data_size data_size;
+ unsigned int def_elem_len;
+ unsigned int iodelay;
+ void (*handler) (void *data);
+ void *tx_callback_data;
+ void *rx_callback_data;
+};
+
+struct ux500_msp {
+ enum enum_i2s_controller id;
+ void __iomem *registers;
+ struct device *dev;
+ struct i2s_controller *i2s_cont;
+ struct stedma40_chan_cfg *dma_cfg_rx;
+ struct stedma40_chan_cfg *dma_cfg_tx;
+ struct dma_chan *tx_pipeid;
+ struct dma_chan *rx_pipeid;
+ enum msp_state msp_state;
+ int (*transfer) (struct ux500_msp *msp, struct i2s_message *message);
+ int (*plat_init) (void);
+ int (*plat_exit) (void);
+ struct timer_list notify_timer;
+ int def_elem_len;
+ unsigned int dir_busy;
+ int loopback_enable;
+ u32 backup_regs[MAX_MSP_BACKUP_REGS];
+ unsigned int f_bitclk;
+};
+
+struct ux500_msp_dma_params {
+ unsigned int data_size;
+ struct stedma40_chan_cfg *dma_cfg;
+};
+
+int ux500_msp_i2s_init_msp(struct platform_device *pdev,
+ struct ux500_msp **msp_p,
+ struct msp_i2s_platform_data *platform_data);
+void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,
+ struct ux500_msp *msp);
+int ux500_msp_i2s_open(struct ux500_msp *msp, struct ux500_msp_config *config);
+int ux500_msp_i2s_close(struct ux500_msp *msp,
+ unsigned int dir);
+int ux500_msp_i2s_trigger(struct ux500_msp *msp, int cmd,
+ int direction);
+
+#endif
diff --git a/sound/sound_core.c b/sound/sound_core.c
index c6e81fb928e9..fb9255cca214 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -361,7 +361,7 @@ int register_sound_special_device(const struct file_operations *fops, int unit,
struct device *dev)
{
const int chain = unit % SOUND_STEP;
- int max_unit = 128 + chain;
+ int max_unit = 256;
const char *name;
char _name[16];
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 4a7be7b98331..d5b5c3388e28 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -131,8 +131,9 @@ static void snd_usb_stream_disconnect(struct list_head *head)
subs = &as->substream[idx];
if (!subs->num_formats)
continue;
- snd_usb_release_substream_urbs(subs, 1);
subs->interface = -1;
+ subs->data_endpoint = NULL;
+ subs->sync_endpoint = NULL;
}
}
@@ -276,6 +277,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
static int snd_usb_audio_free(struct snd_usb_audio *chip)
{
+ mutex_destroy(&chip->mutex);
kfree(chip);
return 0;
}
@@ -336,6 +338,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
return -ENOMEM;
}
+ mutex_init(&chip->mutex);
mutex_init(&chip->shutdown_mutex);
chip->index = idx;
chip->dev = dev;
@@ -348,6 +351,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
INIT_LIST_HEAD(&chip->pcm_list);
+ INIT_LIST_HEAD(&chip->ep_list);
INIT_LIST_HEAD(&chip->midi_list);
INIT_LIST_HEAD(&chip->mixer_list);
@@ -565,6 +569,10 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
list_for_each(p, &chip->pcm_list) {
snd_usb_stream_disconnect(p);
}
+ /* release the endpoint resources */
+ list_for_each(p, &chip->ep_list) {
+ snd_usb_endpoint_free(p);
+ }
/* release the midi resources */
list_for_each(p, &chip->midi_list) {
snd_usbmidi_disconnect(p);
diff --git a/sound/usb/card.h b/sound/usb/card.h
index da5fa1ac4eda..0d37238b8457 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -30,20 +30,71 @@ struct audioformat {
};
struct snd_usb_substream;
+struct snd_usb_endpoint;
struct snd_urb_ctx {
struct urb *urb;
unsigned int buffer_size; /* size of data buffer, if data URB */
struct snd_usb_substream *subs;
+ struct snd_usb_endpoint *ep;
int index; /* index for urb array */
int packets; /* number of packets per urb */
+ int packet_size[MAX_PACKS_HS]; /* size of packets for next submission */
+ struct list_head ready_list;
};
-struct snd_urb_ops {
- int (*prepare)(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *u);
- int (*retire)(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *u);
- int (*prepare_sync)(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *u);
- int (*retire_sync)(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *u);
+struct snd_usb_endpoint {
+ struct snd_usb_audio *chip;
+
+ int use_count;
+ int ep_num; /* the referenced endpoint number */
+ int type; /* SND_USB_ENDPOINT_TYPE_* */
+ unsigned long flags;
+
+ void (*prepare_data_urb) (struct snd_usb_substream *subs,
+ struct urb *urb);
+ void (*retire_data_urb) (struct snd_usb_substream *subs,
+ struct urb *urb);
+
+ struct snd_usb_substream *data_subs;
+ struct snd_usb_endpoint *sync_master;
+ struct snd_usb_endpoint *sync_slave;
+
+ struct snd_urb_ctx urb[MAX_URBS];
+
+ struct snd_usb_packet_info {
+ uint32_t packet_size[MAX_PACKS_HS];
+ int packets;
+ } next_packet[MAX_URBS];
+ int next_packet_read_pos, next_packet_write_pos;
+ struct list_head ready_playback_urbs;
+
+ unsigned int nurbs; /* # urbs */
+ unsigned long active_mask; /* bitmask of active urbs */
+ unsigned long unlink_mask; /* bitmask of unlinked urbs */
+ char *syncbuf; /* sync buffer for all sync URBs */
+ dma_addr_t sync_dma; /* DMA address of syncbuf */
+
+ unsigned int pipe; /* the data i/o pipe */
+ unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */
+ unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */
+ int freqshift; /* how much to shift the feedback value to get Q16.16 */
+ unsigned int freqmax; /* maximum sampling rate, used for buffer management */
+ unsigned int phase; /* phase accumulator */
+ unsigned int maxpacksize; /* max packet size in bytes */
+ unsigned int maxframesize; /* max packet size in frames */
+ unsigned int curpacksize; /* current packet size in bytes (for capture) */
+ unsigned int curframesize; /* current packet size in frames (for capture) */
+ unsigned int syncmaxsize; /* sync endpoint packet size */
+ unsigned int fill_max:1; /* fill max packet size always */
+ unsigned int datainterval; /* log_2 of data packet interval */
+ unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */
+ unsigned char silence_value;
+ unsigned int stride;
+ int iface, alt_idx;
+
+ spinlock_t lock;
+ struct list_head list;
};
struct snd_usb_substream {
@@ -57,21 +108,6 @@ struct snd_usb_substream {
unsigned int cur_rate; /* current rate (for hw_params callback) */
unsigned int period_bytes; /* current period bytes (for hw_params callback) */
unsigned int altset_idx; /* USB data format: index of alternate setting */
- unsigned int datapipe; /* the data i/o pipe */
- unsigned int syncpipe; /* 1 - async out or adaptive in */
- unsigned int datainterval; /* log_2 of data packet interval */
- unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */
- unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */
- unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */
- int freqshift; /* how much to shift the feedback value to get Q16.16 */
- unsigned int freqmax; /* maximum sampling rate, used for buffer management */
- unsigned int phase; /* phase accumulator */
- unsigned int maxpacksize; /* max packet size in bytes */
- unsigned int maxframesize; /* max packet size in frames */
- unsigned int curpacksize; /* current packet size in bytes (for capture) */
- unsigned int curframesize; /* current packet size in frames (for capture) */
- unsigned int syncmaxsize; /* sync endpoint packet size */
- unsigned int fill_max: 1; /* fill max packet size always */
unsigned int txfr_quirk:1; /* allow sub-frame alignment */
unsigned int fmt_type; /* USB audio format type (1-3) */
@@ -82,11 +118,10 @@ struct snd_usb_substream {
unsigned long active_mask; /* bitmask of active urbs */
unsigned long unlink_mask; /* bitmask of unlinked urbs */
- unsigned int nurbs; /* # urbs */
- struct snd_urb_ctx dataurb[MAX_URBS]; /* data urb table */
- struct snd_urb_ctx syncurb[SYNC_URBS]; /* sync urb table */
- char *syncbuf; /* sync buffer for all sync URBs */
- dma_addr_t sync_dma; /* DMA address of syncbuf */
+ /* data and sync endpoints for this stream */
+ struct snd_usb_endpoint *data_endpoint;
+ struct snd_usb_endpoint *sync_endpoint;
+ unsigned long flags;
u64 formats; /* format bitmasks (all or'ed) */
unsigned int num_formats; /* number of supported audio formats (list) */
@@ -94,7 +129,6 @@ struct snd_usb_substream {
struct snd_pcm_hw_constraint_list rate_list; /* limited rates */
spinlock_t lock;
- struct snd_urb_ops ops; /* callbacks (must be filled at init) */
int last_frame_number; /* stored frame number */
int last_delay; /* stored delay */
};
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 08dcce53720b..e6906901debb 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -20,9 +20,11 @@
#include <linux/ratelimit.h>
#include <linux/usb.h>
#include <linux/usb/audio.h>
+#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
+#include <sound/pcm_params.h>
#include "usbaudio.h"
#include "helper.h"
@@ -30,6 +32,36 @@
#include "endpoint.h"
#include "pcm.h"
+#define EP_FLAG_ACTIVATED 0
+#define EP_FLAG_RUNNING 1
+
+/*
+ * snd_usb_endpoint is a model that abstracts everything related to an
+ * USB endpoint and its streaming.
+ *
+ * There are functions to activate and deactivate the streaming URBs and
+ * optional callbacks to let the pcm logic handle the actual content of the
+ * packets for playback and record. Thus, the bus streaming and the audio
+ * handlers are fully decoupled.
+ *
+ * There are two different types of endpoints in audio applications.
+ *
+ * SND_USB_ENDPOINT_TYPE_DATA handles full audio data payload for both
+ * inbound and outbound traffic.
+ *
+ * SND_USB_ENDPOINT_TYPE_SYNC endpoints are for inbound traffic only and
+ * expect the payload to carry Q10.14 / Q16.16 formatted sync information
+ * (3 or 4 bytes).
+ *
+ * Each endpoint has to be configured prior to being used by calling
+ * snd_usb_endpoint_set_params().
+ *
+ * The model incorporates a reference counting, so that multiple users
+ * can call snd_usb_endpoint_start() and snd_usb_endpoint_stop(), and
+ * only the first user will effectively start the URBs, and only the last
+ * one to stop it will tear the URBs down again.
+ */
+
/*
* convert a sampling rate into our full speed format (fs/1000 in Q16.16)
* this will overflow at approx 524 kHz
@@ -49,71 +81,415 @@ static inline unsigned get_usb_high_speed_rate(unsigned int rate)
}
/*
- * unlink active urbs.
+ * release a urb data
*/
-static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sleep)
+static void release_urb_ctx(struct snd_urb_ctx *u)
{
- struct snd_usb_audio *chip = subs->stream->chip;
- unsigned int i;
- int async;
+ if (u->buffer_size)
+ usb_free_coherent(u->ep->chip->dev, u->buffer_size,
+ u->urb->transfer_buffer,
+ u->urb->transfer_dma);
+ usb_free_urb(u->urb);
+ u->urb = NULL;
+}
+
+static const char *usb_error_string(int err)
+{
+ switch (err) {
+ case -ENODEV:
+ return "no device";
+ case -ENOENT:
+ return "endpoint not enabled";
+ case -EPIPE:
+ return "endpoint stalled";
+ case -ENOSPC:
+ return "not enough bandwidth";
+ case -ESHUTDOWN:
+ return "device disabled";
+ case -EHOSTUNREACH:
+ return "device suspended";
+ case -EINVAL:
+ case -EAGAIN:
+ case -EFBIG:
+ case -EMSGSIZE:
+ return "internal error";
+ default:
+ return "unknown error";
+ }
+}
+
+/**
+ * snd_usb_endpoint_implicit_feedback_sink: Report endpoint usage type
+ *
+ * @ep: The snd_usb_endpoint
+ *
+ * Determine whether an endpoint is driven by an implicit feedback
+ * data endpoint source.
+ */
+int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep)
+{
+ return ep->sync_master &&
+ ep->sync_master->type == SND_USB_ENDPOINT_TYPE_DATA &&
+ ep->type == SND_USB_ENDPOINT_TYPE_DATA &&
+ usb_pipeout(ep->pipe);
+}
- subs->running = 0;
+/*
+ * For streaming based on information derived from sync endpoints,
+ * prepare_outbound_urb_sizes() will call next_packet_size() to
+ * determine the number of samples to be sent in the next packet.
+ *
+ * For implicit feedback, next_packet_size() is unused.
+ */
+static int next_packet_size(struct snd_usb_endpoint *ep)
+{
+ unsigned long flags;
+ int ret;
- if (!force && subs->stream->chip->shutdown) /* to be sure... */
- return -EBADFD;
+ if (ep->fill_max)
+ return ep->maxframesize;
- async = !can_sleep && chip->async_unlink;
+ spin_lock_irqsave(&ep->lock, flags);
+ ep->phase = (ep->phase & 0xffff)
+ + (ep->freqm << ep->datainterval);
+ ret = min(ep->phase >> 16, ep->maxframesize);
+ spin_unlock_irqrestore(&ep->lock, flags);
- if (!async && in_interrupt())
- return 0;
+ return ret;
+}
- for (i = 0; i < subs->nurbs; i++) {
- if (test_bit(i, &subs->active_mask)) {
- if (!test_and_set_bit(i, &subs->unlink_mask)) {
- struct urb *u = subs->dataurb[i].urb;
- if (async)
- usb_unlink_urb(u);
- else
- usb_kill_urb(u);
+static void retire_outbound_urb(struct snd_usb_endpoint *ep,
+ struct snd_urb_ctx *urb_ctx)
+{
+ if (ep->retire_data_urb)
+ ep->retire_data_urb(ep->data_subs, urb_ctx->urb);
+}
+
+static void retire_inbound_urb(struct snd_usb_endpoint *ep,
+ struct snd_urb_ctx *urb_ctx)
+{
+ struct urb *urb = urb_ctx->urb;
+
+ if (ep->sync_slave)
+ snd_usb_handle_sync_urb(ep->sync_slave, ep, urb);
+
+ if (ep->retire_data_urb)
+ ep->retire_data_urb(ep->data_subs, urb);
+}
+
+static void prepare_outbound_urb_sizes(struct snd_usb_endpoint *ep,
+ struct snd_urb_ctx *ctx)
+{
+ int i;
+
+ for (i = 0; i < ctx->packets; ++i)
+ ctx->packet_size[i] = next_packet_size(ep);
+}
+
+/*
+ * Prepare a PLAYBACK urb for submission to the bus.
+ */
+static void prepare_outbound_urb(struct snd_usb_endpoint *ep,
+ struct snd_urb_ctx *ctx)
+{
+ int i;
+ struct urb *urb = ctx->urb;
+ unsigned char *cp = urb->transfer_buffer;
+
+ urb->dev = ep->chip->dev; /* we need to set this at each time */
+
+ switch (ep->type) {
+ case SND_USB_ENDPOINT_TYPE_DATA:
+ if (ep->prepare_data_urb) {
+ ep->prepare_data_urb(ep->data_subs, urb);
+ } else {
+ /* no data provider, so send silence */
+ unsigned int offs = 0;
+ for (i = 0; i < ctx->packets; ++i) {
+ int counts = ctx->packet_size[i];
+ urb->iso_frame_desc[i].offset = offs * ep->stride;
+ urb->iso_frame_desc[i].length = counts * ep->stride;
+ offs += counts;
}
+
+ urb->number_of_packets = ctx->packets;
+ urb->transfer_buffer_length = offs * ep->stride;
+ memset(urb->transfer_buffer, ep->silence_value,
+ offs * ep->stride);
}
+ break;
+
+ case SND_USB_ENDPOINT_TYPE_SYNC:
+ if (snd_usb_get_speed(ep->chip->dev) >= USB_SPEED_HIGH) {
+ /*
+ * fill the length and offset of each urb descriptor.
+ * the fixed 12.13 frequency is passed as 16.16 through the pipe.
+ */
+ urb->iso_frame_desc[0].length = 4;
+ urb->iso_frame_desc[0].offset = 0;
+ cp[0] = ep->freqn;
+ cp[1] = ep->freqn >> 8;
+ cp[2] = ep->freqn >> 16;
+ cp[3] = ep->freqn >> 24;
+ } else {
+ /*
+ * fill the length and offset of each urb descriptor.
+ * the fixed 10.14 frequency is passed through the pipe.
+ */
+ urb->iso_frame_desc[0].length = 3;
+ urb->iso_frame_desc[0].offset = 0;
+ cp[0] = ep->freqn >> 2;
+ cp[1] = ep->freqn >> 10;
+ cp[2] = ep->freqn >> 18;
+ }
+
+ break;
}
- if (subs->syncpipe) {
- for (i = 0; i < SYNC_URBS; i++) {
- if (test_bit(i+16, &subs->active_mask)) {
- if (!test_and_set_bit(i+16, &subs->unlink_mask)) {
- struct urb *u = subs->syncurb[i].urb;
- if (async)
- usb_unlink_urb(u);
- else
- usb_kill_urb(u);
- }
- }
+}
+
+/*
+ * Prepare a CAPTURE or SYNC urb for submission to the bus.
+ */
+static inline void prepare_inbound_urb(struct snd_usb_endpoint *ep,
+ struct snd_urb_ctx *urb_ctx)
+{
+ int i, offs;
+ struct urb *urb = urb_ctx->urb;
+
+ urb->dev = ep->chip->dev; /* we need to set this at each time */
+
+ switch (ep->type) {
+ case SND_USB_ENDPOINT_TYPE_DATA:
+ offs = 0;
+ for (i = 0; i < urb_ctx->packets; i++) {
+ urb->iso_frame_desc[i].offset = offs;
+ urb->iso_frame_desc[i].length = ep->curpacksize;
+ offs += ep->curpacksize;
}
+
+ urb->transfer_buffer_length = offs;
+ urb->number_of_packets = urb_ctx->packets;
+ break;
+
+ case SND_USB_ENDPOINT_TYPE_SYNC:
+ urb->iso_frame_desc[0].length = min(4u, ep->syncmaxsize);
+ urb->iso_frame_desc[0].offset = 0;
+ break;
}
- return 0;
}
+/*
+ * Send output urbs that have been prepared previously. URBs are dequeued
+ * from ep->ready_playback_urbs and in case there there aren't any available
+ * or there are no packets that have been prepared, this function does
+ * nothing.
+ *
+ * The reason why the functionality of sending and preparing URBs is separated
+ * is that host controllers don't guarantee the order in which they return
+ * inbound and outbound packets to their submitters.
+ *
+ * This function is only used for implicit feedback endpoints. For endpoints
+ * driven by dedicated sync endpoints, URBs are immediately re-submitted
+ * from their completion handler.
+ */
+static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
+{
+ while (test_bit(EP_FLAG_RUNNING, &ep->flags)) {
+
+ unsigned long flags;
+ struct snd_usb_packet_info *uninitialized_var(packet);
+ struct snd_urb_ctx *ctx = NULL;
+ struct urb *urb;
+ int err, i;
+
+ spin_lock_irqsave(&ep->lock, flags);
+ if (ep->next_packet_read_pos != ep->next_packet_write_pos) {
+ packet = ep->next_packet + ep->next_packet_read_pos;
+ ep->next_packet_read_pos++;
+ ep->next_packet_read_pos %= MAX_URBS;
+
+ /* take URB out of FIFO */
+ if (!list_empty(&ep->ready_playback_urbs))
+ ctx = list_first_entry(&ep->ready_playback_urbs,
+ struct snd_urb_ctx, ready_list);
+ }
+ spin_unlock_irqrestore(&ep->lock, flags);
+
+ if (ctx == NULL)
+ return;
+
+ list_del_init(&ctx->ready_list);
+ urb = ctx->urb;
+
+ /* copy over the length information */
+ for (i = 0; i < packet->packets; i++)
+ ctx->packet_size[i] = packet->packet_size[i];
+
+ /* call the data handler to fill in playback data */
+ prepare_outbound_urb(ep, ctx);
+
+ err = usb_submit_urb(ctx->urb, GFP_ATOMIC);
+ if (err < 0)
+ snd_printk(KERN_ERR "Unable to submit urb #%d: %d (urb %p)\n",
+ ctx->index, err, ctx->urb);
+ else
+ set_bit(ctx->index, &ep->active_mask);
+ }
+}
/*
- * release a urb data
+ * complete callback for urbs
*/
-static void release_urb_ctx(struct snd_urb_ctx *u)
+static void snd_complete_urb(struct urb *urb)
+{
+ struct snd_urb_ctx *ctx = urb->context;
+ struct snd_usb_endpoint *ep = ctx->ep;
+ int err;
+
+ if (unlikely(urb->status == -ENOENT || /* unlinked */
+ urb->status == -ENODEV || /* device removed */
+ urb->status == -ECONNRESET || /* unlinked */
+ urb->status == -ESHUTDOWN || /* device disabled */
+ ep->chip->shutdown)) /* device disconnected */
+ goto exit_clear;
+
+ if (usb_pipeout(ep->pipe)) {
+ retire_outbound_urb(ep, ctx);
+ /* can be stopped during retire callback */
+ if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+ goto exit_clear;
+
+ if (snd_usb_endpoint_implict_feedback_sink(ep)) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&ep->lock, flags);
+ list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
+ spin_unlock_irqrestore(&ep->lock, flags);
+ queue_pending_output_urbs(ep);
+
+ goto exit_clear;
+ }
+
+ prepare_outbound_urb_sizes(ep, ctx);
+ prepare_outbound_urb(ep, ctx);
+ } else {
+ retire_inbound_urb(ep, ctx);
+ /* can be stopped during retire callback */
+ if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+ goto exit_clear;
+
+ prepare_inbound_urb(ep, ctx);
+ }
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err == 0)
+ return;
+
+ snd_printk(KERN_ERR "cannot submit urb (err = %d)\n", err);
+ //snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+
+exit_clear:
+ clear_bit(ctx->index, &ep->active_mask);
+}
+
+/**
+ * snd_usb_add_endpoint: Add an endpoint to an USB audio chip
+ *
+ * @chip: The chip
+ * @alts: The USB host interface
+ * @ep_num: The number of the endpoint to use
+ * @direction: SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE
+ * @type: SND_USB_ENDPOINT_TYPE_DATA or SND_USB_ENDPOINT_TYPE_SYNC
+ *
+ * If the requested endpoint has not been added to the given chip before,
+ * a new instance is created. Otherwise, a pointer to the previoulsy
+ * created instance is returned. In case of any error, NULL is returned.
+ *
+ * New endpoints will be added to chip->ep_list and must be freed by
+ * calling snd_usb_endpoint_free().
+ */
+struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
+ struct usb_host_interface *alts,
+ int ep_num, int direction, int type)
{
- if (u->urb) {
- if (u->buffer_size)
- usb_free_coherent(u->subs->dev, u->buffer_size,
- u->urb->transfer_buffer,
- u->urb->transfer_dma);
- usb_free_urb(u->urb);
- u->urb = NULL;
+ struct list_head *p;
+ struct snd_usb_endpoint *ep;
+ int ret, is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK;
+
+ mutex_lock(&chip->mutex);
+
+ list_for_each(p, &chip->ep_list) {
+ ep = list_entry(p, struct snd_usb_endpoint, list);
+ if (ep->ep_num == ep_num &&
+ ep->iface == alts->desc.bInterfaceNumber &&
+ ep->alt_idx == alts->desc.bAlternateSetting) {
+ snd_printdd(KERN_DEBUG "Re-using EP %x in iface %d,%d @%p\n",
+ ep_num, ep->iface, ep->alt_idx, ep);
+ goto __exit_unlock;
+ }
+ }
+
+ snd_printdd(KERN_DEBUG "Creating new %s %s endpoint #%x\n",
+ is_playback ? "playback" : "capture",
+ type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync",
+ ep_num);
+
+ /* select the alt setting once so the endpoints become valid */
+ ret = usb_set_interface(chip->dev, alts->desc.bInterfaceNumber,
+ alts->desc.bAlternateSetting);
+ if (ret < 0) {
+ snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n",
+ __func__, ret);
+ ep = NULL;
+ goto __exit_unlock;
}
+
+ ep = kzalloc(sizeof(*ep), GFP_KERNEL);
+ if (!ep)
+ goto __exit_unlock;
+
+ ep->chip = chip;
+ spin_lock_init(&ep->lock);
+ ep->type = type;
+ ep->ep_num = ep_num;
+ ep->iface = alts->desc.bInterfaceNumber;
+ ep->alt_idx = alts->desc.bAlternateSetting;
+ INIT_LIST_HEAD(&ep->ready_playback_urbs);
+ ep_num &= USB_ENDPOINT_NUMBER_MASK;
+
+ if (is_playback)
+ ep->pipe = usb_sndisocpipe(chip->dev, ep_num);
+ else
+ ep->pipe = usb_rcvisocpipe(chip->dev, ep_num);
+
+ if (type == SND_USB_ENDPOINT_TYPE_SYNC) {
+ if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
+ get_endpoint(alts, 1)->bRefresh >= 1 &&
+ get_endpoint(alts, 1)->bRefresh <= 9)
+ ep->syncinterval = get_endpoint(alts, 1)->bRefresh;
+ else if (snd_usb_get_speed(chip->dev) == USB_SPEED_FULL)
+ ep->syncinterval = 1;
+ else if (get_endpoint(alts, 1)->bInterval >= 1 &&
+ get_endpoint(alts, 1)->bInterval <= 16)
+ ep->syncinterval = get_endpoint(alts, 1)->bInterval - 1;
+ else
+ ep->syncinterval = 3;
+
+ ep->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
+ }
+
+ list_add_tail(&ep->list, &chip->ep_list);
+
+__exit_unlock:
+ mutex_unlock(&chip->mutex);
+
+ return ep;
}
/*
* wait until all urbs are processed.
*/
-static int wait_clear_urbs(struct snd_usb_substream *subs)
+static int wait_clear_urbs(struct snd_usb_endpoint *ep)
{
unsigned long end_time = jiffies + msecs_to_jiffies(1000);
unsigned int i;
@@ -121,153 +497,148 @@ static int wait_clear_urbs(struct snd_usb_substream *subs)
do {
alive = 0;
- for (i = 0; i < subs->nurbs; i++) {
- if (test_bit(i, &subs->active_mask))
+ for (i = 0; i < ep->nurbs; i++)
+ if (test_bit(i, &ep->active_mask))
alive++;
- }
- if (subs->syncpipe) {
- for (i = 0; i < SYNC_URBS; i++) {
- if (test_bit(i + 16, &subs->active_mask))
- alive++;
- }
- }
- if (! alive)
+
+ if (!alive)
break;
+
schedule_timeout_uninterruptible(1);
} while (time_before(jiffies, end_time));
+
if (alive)
- snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
+ snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n",
+ alive, ep->ep_num);
+
return 0;
}
/*
- * release a substream
+ * unlink active urbs.
*/
-void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force)
+static int deactivate_urbs(struct snd_usb_endpoint *ep, int force, int can_sleep)
{
- int i;
+ unsigned int i;
+ int async;
- /* stop urbs (to be sure) */
- deactivate_urbs(subs, force, 1);
- wait_clear_urbs(subs);
-
- for (i = 0; i < MAX_URBS; i++)
- release_urb_ctx(&subs->dataurb[i]);
- for (i = 0; i < SYNC_URBS; i++)
- release_urb_ctx(&subs->syncurb[i]);
- usb_free_coherent(subs->dev, SYNC_URBS * 4,
- subs->syncbuf, subs->sync_dma);
- subs->syncbuf = NULL;
- subs->nurbs = 0;
-}
+ if (!force && ep->chip->shutdown) /* to be sure... */
+ return -EBADFD;
-/*
- * complete callback from data urb
- */
-static void snd_complete_urb(struct urb *urb)
-{
- struct snd_urb_ctx *ctx = urb->context;
- struct snd_usb_substream *subs = ctx->subs;
- struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
- int err = 0;
-
- if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
- !subs->running || /* can be stopped during retire callback */
- (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
- (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
- clear_bit(ctx->index, &subs->active_mask);
- if (err < 0) {
- snd_printd(KERN_ERR "cannot submit urb (err = %d)\n", err);
- snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+ async = !can_sleep && ep->chip->async_unlink;
+
+ clear_bit(EP_FLAG_RUNNING, &ep->flags);
+
+ INIT_LIST_HEAD(&ep->ready_playback_urbs);
+ ep->next_packet_read_pos = 0;
+ ep->next_packet_write_pos = 0;
+
+ if (!async && in_interrupt())
+ return 0;
+
+ for (i = 0; i < ep->nurbs; i++) {
+ if (test_bit(i, &ep->active_mask)) {
+ if (!test_and_set_bit(i, &ep->unlink_mask)) {
+ struct urb *u = ep->urb[i].urb;
+ if (async)
+ usb_unlink_urb(u);
+ else
+ usb_kill_urb(u);
+ }
}
}
-}
+ return 0;
+}
/*
- * complete callback from sync urb
+ * release an endpoint's urbs
*/
-static void snd_complete_sync_urb(struct urb *urb)
+static void release_urbs(struct snd_usb_endpoint *ep, int force)
{
- struct snd_urb_ctx *ctx = urb->context;
- struct snd_usb_substream *subs = ctx->subs;
- struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
- int err = 0;
-
- if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
- !subs->running || /* can be stopped during retire callback */
- (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
- (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
- clear_bit(ctx->index + 16, &subs->active_mask);
- if (err < 0) {
- snd_printd(KERN_ERR "cannot submit sync urb (err = %d)\n", err);
- snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
- }
- }
-}
+ int i;
+ /* route incoming urbs to nirvana */
+ ep->retire_data_urb = NULL;
+ ep->prepare_data_urb = NULL;
+
+ /* stop urbs */
+ deactivate_urbs(ep, force, 1);
+ wait_clear_urbs(ep);
+
+ for (i = 0; i < ep->nurbs; i++)
+ release_urb_ctx(&ep->urb[i]);
+
+ if (ep->syncbuf)
+ usb_free_coherent(ep->chip->dev, SYNC_URBS * 4,
+ ep->syncbuf, ep->sync_dma);
+
+ ep->syncbuf = NULL;
+ ep->nurbs = 0;
+}
/*
- * initialize a substream for plaback/capture
+ * configure a data endpoint
*/
-int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
- unsigned int period_bytes,
- unsigned int rate,
- unsigned int frame_bits)
+static int data_ep_set_params(struct snd_usb_endpoint *ep,
+ struct snd_pcm_hw_params *hw_params,
+ struct audioformat *fmt,
+ struct snd_usb_endpoint *sync_ep)
{
- unsigned int maxsize, i;
- int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
- unsigned int urb_packs, total_packs, packs_per_ms;
- struct snd_usb_audio *chip = subs->stream->chip;
+ unsigned int maxsize, i, urb_packs, total_packs, packs_per_ms;
+ int period_bytes = params_period_bytes(hw_params);
+ int format = params_format(hw_params);
+ int is_playback = usb_pipeout(ep->pipe);
+ int frame_bits = snd_pcm_format_physical_width(params_format(hw_params)) *
+ params_channels(hw_params);
+
+ ep->datainterval = fmt->datainterval;
+ ep->stride = frame_bits >> 3;
+ ep->silence_value = format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0;
- /* calculate the frequency in 16.16 format */
- if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
- subs->freqn = get_usb_full_speed_rate(rate);
- else
- subs->freqn = get_usb_high_speed_rate(rate);
- subs->freqm = subs->freqn;
- subs->freqshift = INT_MIN;
/* calculate max. frequency */
- if (subs->maxpacksize) {
+ if (ep->maxpacksize) {
/* whatever fits into a max. size packet */
- maxsize = subs->maxpacksize;
- subs->freqmax = (maxsize / (frame_bits >> 3))
- << (16 - subs->datainterval);
+ maxsize = ep->maxpacksize;
+ ep->freqmax = (maxsize / (frame_bits >> 3))
+ << (16 - ep->datainterval);
} else {
/* no max. packet size: just take 25% higher than nominal */
- subs->freqmax = subs->freqn + (subs->freqn >> 2);
- maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3))
- >> (16 - subs->datainterval);
+ ep->freqmax = ep->freqn + (ep->freqn >> 2);
+ maxsize = ((ep->freqmax + 0xffff) * (frame_bits >> 3))
+ >> (16 - ep->datainterval);
}
- subs->phase = 0;
- if (subs->fill_max)
- subs->curpacksize = subs->maxpacksize;
+ if (ep->fill_max)
+ ep->curpacksize = ep->maxpacksize;
else
- subs->curpacksize = maxsize;
+ ep->curpacksize = maxsize;
- if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
- packs_per_ms = 8 >> subs->datainterval;
+ if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL)
+ packs_per_ms = 8 >> ep->datainterval;
else
packs_per_ms = 1;
- if (is_playback) {
- urb_packs = max(chip->nrpacks, 1);
- urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
- } else
+ if (is_playback && !snd_usb_endpoint_implict_feedback_sink(ep)) {
+ urb_packs = max(ep->chip->nrpacks, 1);
+ urb_packs = min(urb_packs, (unsigned int) MAX_PACKS);
+ } else {
urb_packs = 1;
+ }
+
urb_packs *= packs_per_ms;
- if (subs->syncpipe)
- urb_packs = min(urb_packs, 1U << subs->syncinterval);
+
+ if (sync_ep && !snd_usb_endpoint_implict_feedback_sink(ep))
+ urb_packs = min(urb_packs, 1U << sync_ep->syncinterval);
/* decide how many packets to be used */
- if (is_playback) {
+ if (is_playback && !snd_usb_endpoint_implict_feedback_sink(ep)) {
unsigned int minsize, maxpacks;
/* determine how small a packet can be */
- minsize = (subs->freqn >> (16 - subs->datainterval))
+ minsize = (ep->freqn >> (16 - ep->datainterval))
* (frame_bits >> 3);
/* with sync from device, assume it can be 12% lower */
- if (subs->syncpipe)
+ if (sync_ep)
minsize -= minsize >> 3;
minsize = max(minsize, 1u);
total_packs = (period_bytes + minsize - 1) / minsize;
@@ -284,284 +655,472 @@ int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
urb_packs >>= 1;
total_packs = MAX_URBS * urb_packs;
}
- subs->nurbs = (total_packs + urb_packs - 1) / urb_packs;
- if (subs->nurbs > MAX_URBS) {
+
+ ep->nurbs = (total_packs + urb_packs - 1) / urb_packs;
+ if (ep->nurbs > MAX_URBS) {
/* too much... */
- subs->nurbs = MAX_URBS;
+ ep->nurbs = MAX_URBS;
total_packs = MAX_URBS * urb_packs;
- } else if (subs->nurbs < 2) {
+ } else if (ep->nurbs < 2) {
/* too little - we need at least two packets
* to ensure contiguous playback/capture
*/
- subs->nurbs = 2;
+ ep->nurbs = 2;
}
/* allocate and initialize data urbs */
- for (i = 0; i < subs->nurbs; i++) {
- struct snd_urb_ctx *u = &subs->dataurb[i];
+ for (i = 0; i < ep->nurbs; i++) {
+ struct snd_urb_ctx *u = &ep->urb[i];
u->index = i;
- u->subs = subs;
- u->packets = (i + 1) * total_packs / subs->nurbs
- - i * total_packs / subs->nurbs;
+ u->ep = ep;
+ u->packets = (i + 1) * total_packs / ep->nurbs
+ - i * total_packs / ep->nurbs;
u->buffer_size = maxsize * u->packets;
- if (subs->fmt_type == UAC_FORMAT_TYPE_II)
+
+ if (fmt->fmt_type == UAC_FORMAT_TYPE_II)
u->packets++; /* for transfer delimiter */
u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
if (!u->urb)
goto out_of_memory;
+
u->urb->transfer_buffer =
- usb_alloc_coherent(subs->dev, u->buffer_size,
+ usb_alloc_coherent(ep->chip->dev, u->buffer_size,
GFP_KERNEL, &u->urb->transfer_dma);
if (!u->urb->transfer_buffer)
goto out_of_memory;
- u->urb->pipe = subs->datapipe;
+ u->urb->pipe = ep->pipe;
u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
- u->urb->interval = 1 << subs->datainterval;
+ u->urb->interval = 1 << ep->datainterval;
u->urb->context = u;
u->urb->complete = snd_complete_urb;
+ INIT_LIST_HEAD(&u->ready_list);
}
- if (subs->syncpipe) {
- /* allocate and initialize sync urbs */
- subs->syncbuf = usb_alloc_coherent(subs->dev, SYNC_URBS * 4,
- GFP_KERNEL, &subs->sync_dma);
- if (!subs->syncbuf)
- goto out_of_memory;
- for (i = 0; i < SYNC_URBS; i++) {
- struct snd_urb_ctx *u = &subs->syncurb[i];
- u->index = i;
- u->subs = subs;
- u->packets = 1;
- u->urb = usb_alloc_urb(1, GFP_KERNEL);
- if (!u->urb)
- goto out_of_memory;
- u->urb->transfer_buffer = subs->syncbuf + i * 4;
- u->urb->transfer_dma = subs->sync_dma + i * 4;
- u->urb->transfer_buffer_length = 4;
- u->urb->pipe = subs->syncpipe;
- u->urb->transfer_flags = URB_ISO_ASAP |
- URB_NO_TRANSFER_DMA_MAP;
- u->urb->number_of_packets = 1;
- u->urb->interval = 1 << subs->syncinterval;
- u->urb->context = u;
- u->urb->complete = snd_complete_sync_urb;
- }
- }
return 0;
out_of_memory:
- snd_usb_release_substream_urbs(subs, 0);
+ release_urbs(ep, 0);
return -ENOMEM;
}
/*
- * prepare urb for full speed capture sync pipe
- *
- * fill the length and offset of each urb descriptor.
- * the fixed 10.14 frequency is passed through the pipe.
+ * configure a sync endpoint
*/
-static int prepare_capture_sync_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
+static int sync_ep_set_params(struct snd_usb_endpoint *ep,
+ struct snd_pcm_hw_params *hw_params,
+ struct audioformat *fmt)
{
- unsigned char *cp = urb->transfer_buffer;
- struct snd_urb_ctx *ctx = urb->context;
+ int i;
+
+ ep->syncbuf = usb_alloc_coherent(ep->chip->dev, SYNC_URBS * 4,
+ GFP_KERNEL, &ep->sync_dma);
+ if (!ep->syncbuf)
+ return -ENOMEM;
+
+ for (i = 0; i < SYNC_URBS; i++) {
+ struct snd_urb_ctx *u = &ep->urb[i];
+ u->index = i;
+ u->ep = ep;
+ u->packets = 1;
+ u->urb = usb_alloc_urb(1, GFP_KERNEL);
+ if (!u->urb)
+ goto out_of_memory;
+ u->urb->transfer_buffer = ep->syncbuf + i * 4;
+ u->urb->transfer_dma = ep->sync_dma + i * 4;
+ u->urb->transfer_buffer_length = 4;
+ u->urb->pipe = ep->pipe;
+ u->urb->transfer_flags = URB_ISO_ASAP |
+ URB_NO_TRANSFER_DMA_MAP;
+ u->urb->number_of_packets = 1;
+ u->urb->interval = 1 << ep->syncinterval;
+ u->urb->context = u;
+ u->urb->complete = snd_complete_urb;
+ }
+
+ ep->nurbs = SYNC_URBS;
- urb->dev = ctx->subs->dev; /* we need to set this at each time */
- urb->iso_frame_desc[0].length = 3;
- urb->iso_frame_desc[0].offset = 0;
- cp[0] = subs->freqn >> 2;
- cp[1] = subs->freqn >> 10;
- cp[2] = subs->freqn >> 18;
return 0;
+
+out_of_memory:
+ release_urbs(ep, 0);
+ return -ENOMEM;
}
-/*
- * prepare urb for high speed capture sync pipe
+/**
+ * snd_usb_endpoint_set_params: configure an snd_usb_endpoint
+ *
+ * @ep: the snd_usb_endpoint to configure
+ * @hw_params: the hardware parameters
+ * @fmt: the USB audio format information
+ * @sync_ep: the sync endpoint to use, if any
*
- * fill the length and offset of each urb descriptor.
- * the fixed 12.13 frequency is passed as 16.16 through the pipe.
+ * Determine the number of URBs to be used on this endpoint.
+ * An endpoint must be configured before it can be started.
+ * An endpoint that is already running can not be reconfigured.
*/
-static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
+int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
+ struct snd_pcm_hw_params *hw_params,
+ struct audioformat *fmt,
+ struct snd_usb_endpoint *sync_ep)
{
- unsigned char *cp = urb->transfer_buffer;
- struct snd_urb_ctx *ctx = urb->context;
+ int err;
- urb->dev = ctx->subs->dev; /* we need to set this at each time */
- urb->iso_frame_desc[0].length = 4;
- urb->iso_frame_desc[0].offset = 0;
- cp[0] = subs->freqn;
- cp[1] = subs->freqn >> 8;
- cp[2] = subs->freqn >> 16;
- cp[3] = subs->freqn >> 24;
- return 0;
+ if (ep->use_count != 0) {
+ snd_printk(KERN_WARNING "Unable to change format on ep #%x: already in use\n",
+ ep->ep_num);
+ return -EBUSY;
+ }
+
+ /* release old buffers, if any */
+ release_urbs(ep, 0);
+
+ ep->datainterval = fmt->datainterval;
+ ep->maxpacksize = fmt->maxpacksize;
+ ep->fill_max = !!(fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX);
+
+ if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_FULL)
+ ep->freqn = get_usb_full_speed_rate(params_rate(hw_params));
+ else
+ ep->freqn = get_usb_high_speed_rate(params_rate(hw_params));
+
+ /* calculate the frequency in 16.16 format */
+ ep->freqm = ep->freqn;
+ ep->freqshift = INT_MIN;
+
+ ep->phase = 0;
+
+ switch (ep->type) {
+ case SND_USB_ENDPOINT_TYPE_DATA:
+ err = data_ep_set_params(ep, hw_params, fmt, sync_ep);
+ break;
+ case SND_USB_ENDPOINT_TYPE_SYNC:
+ err = sync_ep_set_params(ep, hw_params, fmt);
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ snd_printdd(KERN_DEBUG "Setting params for ep #%x (type %d, %d urbs), ret=%d\n",
+ ep->ep_num, ep->type, ep->nurbs, err);
+
+ return err;
}
-/*
- * process after capture sync complete
- * - nothing to do
+/**
+ * snd_usb_endpoint_start: start an snd_usb_endpoint
+ *
+ * @ep: the endpoint to start
+ *
+ * A call to this function will increment the use count of the endpoint.
+ * In case it is not already running, the URBs for this endpoint will be
+ * submitted. Otherwise, this function does nothing.
+ *
+ * Must be balanced to calls of snd_usb_endpoint_stop().
+ *
+ * Returns an error if the URB submission failed, 0 in all other cases.
*/
-static int retire_capture_sync_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
{
+ int err;
+ unsigned int i;
+
+ if (ep->chip->shutdown)
+ return -EBADFD;
+
+ /* already running? */
+ if (++ep->use_count != 1)
+ return 0;
+
+ if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags)))
+ return -EINVAL;
+
+ /* just to be sure */
+ deactivate_urbs(ep, 0, 1);
+ wait_clear_urbs(ep);
+
+ ep->active_mask = 0;
+ ep->unlink_mask = 0;
+ ep->phase = 0;
+
+ /*
+ * If this endpoint has a data endpoint as implicit feedback source,
+ * don't start the urbs here. Instead, mark them all as available,
+ * wait for the record urbs to return and queue the playback urbs
+ * from that context.
+ */
+
+ set_bit(EP_FLAG_RUNNING, &ep->flags);
+
+ if (snd_usb_endpoint_implict_feedback_sink(ep)) {
+ for (i = 0; i < ep->nurbs; i++) {
+ struct snd_urb_ctx *ctx = ep->urb + i;
+ list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
+ }
+
+ return 0;
+ }
+
+ for (i = 0; i < ep->nurbs; i++) {
+ struct urb *urb = ep->urb[i].urb;
+
+ if (snd_BUG_ON(!urb))
+ goto __error;
+
+ if (usb_pipeout(ep->pipe)) {
+ prepare_outbound_urb_sizes(ep, urb->context);
+ prepare_outbound_urb(ep, urb->context);
+ } else {
+ prepare_inbound_urb(ep, urb->context);
+ }
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ snd_printk(KERN_ERR "cannot submit urb %d, error %d: %s\n",
+ i, err, usb_error_string(err));
+ goto __error;
+ }
+ set_bit(i, &ep->active_mask);
+ }
+
return 0;
+
+__error:
+ clear_bit(EP_FLAG_RUNNING, &ep->flags);
+ ep->use_count--;
+ deactivate_urbs(ep, 0, 0);
+ return -EPIPE;
}
-/*
- * prepare urb for capture data pipe
+/**
+ * snd_usb_endpoint_stop: stop an snd_usb_endpoint
+ *
+ * @ep: the endpoint to stop (may be NULL)
*
- * fill the offset and length of each descriptor.
+ * A call to this function will decrement the use count of the endpoint.
+ * In case the last user has requested the endpoint stop, the URBs will
+ * actually be deactivated.
*
- * we use a temporary buffer to write the captured data.
- * since the length of written data is determined by host, we cannot
- * write onto the pcm buffer directly... the data is thus copied
- * later at complete callback to the global buffer.
+ * Must be balanced to calls of snd_usb_endpoint_start().
*/
-static int prepare_capture_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
+void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
+ int force, int can_sleep, int wait)
{
- int i, offs;
- struct snd_urb_ctx *ctx = urb->context;
+ if (!ep)
+ return;
- offs = 0;
- urb->dev = ctx->subs->dev; /* we need to set this at each time */
- for (i = 0; i < ctx->packets; i++) {
- urb->iso_frame_desc[i].offset = offs;
- urb->iso_frame_desc[i].length = subs->curpacksize;
- offs += subs->curpacksize;
+ if (snd_BUG_ON(ep->use_count == 0))
+ return;
+
+ if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags)))
+ return;
+
+ if (--ep->use_count == 0) {
+ deactivate_urbs(ep, force, can_sleep);
+ ep->data_subs = NULL;
+ ep->sync_slave = NULL;
+ ep->retire_data_urb = NULL;
+ ep->prepare_data_urb = NULL;
+
+ if (wait)
+ wait_clear_urbs(ep);
}
- urb->transfer_buffer_length = offs;
- urb->number_of_packets = ctx->packets;
- return 0;
}
-/*
- * process after capture complete
+/**
+ * snd_usb_endpoint_activate: activate an snd_usb_endpoint
+ *
+ * @ep: the endpoint to activate
+ *
+ * If the endpoint is not currently in use, this functions will select the
+ * correct alternate interface setting for the interface of this endpoint.
*
- * copy the data from each desctiptor to the pcm buffer, and
- * update the current position.
+ * In case of any active users, this functions does nothing.
+ *
+ * Returns an error if usb_set_interface() failed, 0 in all other
+ * cases.
*/
-static int retire_capture_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
+int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep)
{
- unsigned long flags;
- unsigned char *cp;
- int i;
- unsigned int stride, frames, bytes, oldptr;
- int period_elapsed = 0;
+ if (ep->use_count != 0)
+ return 0;
- stride = runtime->frame_bits >> 3;
+ if (!ep->chip->shutdown &&
+ !test_and_set_bit(EP_FLAG_ACTIVATED, &ep->flags)) {
+ int ret;
- for (i = 0; i < urb->number_of_packets; i++) {
- cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
- if (urb->iso_frame_desc[i].status && printk_ratelimit()) {
- snd_printdd("frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
- // continue;
- }
- bytes = urb->iso_frame_desc[i].actual_length;
- frames = bytes / stride;
- if (!subs->txfr_quirk)
- bytes = frames * stride;
- if (bytes % (runtime->sample_bits >> 3) != 0) {
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- int oldbytes = bytes;
-#endif
- bytes = frames * stride;
- snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n",
- oldbytes, bytes);
- }
- /* update the current pointer */
- spin_lock_irqsave(&subs->lock, flags);
- oldptr = subs->hwptr_done;
- subs->hwptr_done += bytes;
- if (subs->hwptr_done >= runtime->buffer_size * stride)
- subs->hwptr_done -= runtime->buffer_size * stride;
- frames = (bytes + (oldptr % stride)) / stride;
- subs->transfer_done += frames;
- if (subs->transfer_done >= runtime->period_size) {
- subs->transfer_done -= runtime->period_size;
- period_elapsed = 1;
- }
- spin_unlock_irqrestore(&subs->lock, flags);
- /* copy a data chunk */
- if (oldptr + bytes > runtime->buffer_size * stride) {
- unsigned int bytes1 =
- runtime->buffer_size * stride - oldptr;
- memcpy(runtime->dma_area + oldptr, cp, bytes1);
- memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
- } else {
- memcpy(runtime->dma_area + oldptr, cp, bytes);
+ ret = usb_set_interface(ep->chip->dev, ep->iface, ep->alt_idx);
+ if (ret < 0) {
+ snd_printk(KERN_ERR "%s() usb_set_interface() failed, ret = %d\n",
+ __func__, ret);
+ clear_bit(EP_FLAG_ACTIVATED, &ep->flags);
+ return ret;
}
+
+ return 0;
}
- if (period_elapsed)
- snd_pcm_period_elapsed(subs->pcm_substream);
- return 0;
+
+ return -EBUSY;
}
-/*
- * Process after capture complete when paused. Nothing to do.
+/**
+ * snd_usb_endpoint_deactivate: deactivate an snd_usb_endpoint
+ *
+ * @ep: the endpoint to deactivate
+ *
+ * If the endpoint is not currently in use, this functions will select the
+ * alternate interface setting 0 for the interface of this endpoint.
+ *
+ * In case of any active users, this functions does nothing.
+ *
+ * Returns an error if usb_set_interface() failed, 0 in all other
+ * cases.
*/
-static int retire_paused_capture_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
+int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
{
- return 0;
-}
+ if (!ep)
+ return -EINVAL;
+ if (ep->use_count != 0)
+ return 0;
-/*
- * prepare urb for playback sync pipe
+ if (!ep->chip->shutdown &&
+ test_and_clear_bit(EP_FLAG_ACTIVATED, &ep->flags)) {
+ int ret;
+
+ ret = usb_set_interface(ep->chip->dev, ep->iface, 0);
+ if (ret < 0) {
+ snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ return 0;
+ }
+
+ return -EBUSY;
+}
+
+/**
+ * snd_usb_endpoint_free: Free the resources of an snd_usb_endpoint
+ *
+ * @ep: the list header of the endpoint to free
*
- * set up the offset and length to receive the current frequency.
+ * This function does not care for the endpoint's use count but will tear
+ * down all the streaming URBs immediately and free all resources.
*/
-static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
+void snd_usb_endpoint_free(struct list_head *head)
{
- struct snd_urb_ctx *ctx = urb->context;
+ struct snd_usb_endpoint *ep;
- urb->dev = ctx->subs->dev; /* we need to set this at each time */
- urb->iso_frame_desc[0].length = min(4u, ctx->subs->syncmaxsize);
- urb->iso_frame_desc[0].offset = 0;
- return 0;
+ ep = list_entry(head, struct snd_usb_endpoint, list);
+ release_urbs(ep, 1);
+ kfree(ep);
}
-/*
- * process after playback sync complete
- *
- * Full speed devices report feedback values in 10.14 format as samples per
- * frame, high speed devices in 16.16 format as samples per microframe.
- * Because the Audio Class 1 spec was written before USB 2.0, many high speed
- * devices use a wrong interpretation, some others use an entirely different
- * format. Therefore, we cannot predict what format any particular device uses
- * and must detect it automatically.
+/**
+ * snd_usb_handle_sync_urb: parse an USB sync packet
+ *
+ * @ep: the endpoint to handle the packet
+ * @sender: the sending endpoint
+ * @urb: the received packet
+ *
+ * This function is called from the context of an endpoint that received
+ * the packet and is used to let another endpoint object handle the payload.
*/
-static int retire_playback_sync_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
+void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
+ struct snd_usb_endpoint *sender,
+ const struct urb *urb)
{
- unsigned int f;
int shift;
+ unsigned int f;
unsigned long flags;
+ snd_BUG_ON(ep == sender);
+
+ /*
+ * In case the endpoint is operating in implicit feedback mode, prepare
+ * a new outbound URB that has the same layout as the received packet
+ * and add it to the list of pending urbs. queue_pending_output_urbs()
+ * will take care of them later.
+ */
+ if (snd_usb_endpoint_implict_feedback_sink(ep) &&
+ ep->use_count != 0) {
+
+ /* implicit feedback case */
+ int i, bytes = 0;
+ struct snd_urb_ctx *in_ctx;
+ struct snd_usb_packet_info *out_packet;
+
+ in_ctx = urb->context;
+
+ /* Count overall packet size */
+ for (i = 0; i < in_ctx->packets; i++)
+ if (urb->iso_frame_desc[i].status == 0)
+ bytes += urb->iso_frame_desc[i].actual_length;
+
+ /*
+ * skip empty packets. At least M-Audio's Fast Track Ultra stops
+ * streaming once it received a 0-byte OUT URB
+ */
+ if (bytes == 0)
+ return;
+
+ spin_lock_irqsave(&ep->lock, flags);
+ out_packet = ep->next_packet + ep->next_packet_write_pos;
+
+ /*
+ * Iterate through the inbound packet and prepare the lengths
+ * for the output packet. The OUT packet we are about to send
+ * will have the same amount of payload bytes than the IN
+ * packet we just received.
+ */
+
+ out_packet->packets = in_ctx->packets;
+ for (i = 0; i < in_ctx->packets; i++) {
+ if (urb->iso_frame_desc[i].status == 0)
+ out_packet->packet_size[i] =
+ urb->iso_frame_desc[i].actual_length / ep->stride;
+ else
+ out_packet->packet_size[i] = 0;
+ }
+
+ ep->next_packet_write_pos++;
+ ep->next_packet_write_pos %= MAX_URBS;
+ spin_unlock_irqrestore(&ep->lock, flags);
+ queue_pending_output_urbs(ep);
+
+ return;
+ }
+
+ /*
+ * process after playback sync complete
+ *
+ * Full speed devices report feedback values in 10.14 format as samples
+ * per frame, high speed devices in 16.16 format as samples per
+ * microframe.
+ *
+ * Because the Audio Class 1 spec was written before USB 2.0, many high
+ * speed devices use a wrong interpretation, some others use an
+ * entirely different format.
+ *
+ * Therefore, we cannot predict what format any particular device uses
+ * and must detect it automatically.
+ */
+
if (urb->iso_frame_desc[0].status != 0 ||
urb->iso_frame_desc[0].actual_length < 3)
- return 0;
+ return;
f = le32_to_cpup(urb->transfer_buffer);
if (urb->iso_frame_desc[0].actual_length == 3)
f &= 0x00ffffff;
else
f &= 0x0fffffff;
+
if (f == 0)
- return 0;
+ return;
- if (unlikely(subs->freqshift == INT_MIN)) {
+ if (unlikely(ep->freqshift == INT_MIN)) {
/*
* The first time we see a feedback value, determine its format
* by shifting it left or right until it matches the nominal
@@ -569,398 +1128,34 @@ static int retire_playback_sync_urb(struct snd_usb_substream *subs,
* differ from the nominal value more than +50% or -25%.
*/
shift = 0;
- while (f < subs->freqn - subs->freqn / 4) {
+ while (f < ep->freqn - ep->freqn / 4) {
f <<= 1;
shift++;
}
- while (f > subs->freqn + subs->freqn / 2) {
+ while (f > ep->freqn + ep->freqn / 2) {
f >>= 1;
shift--;
}
- subs->freqshift = shift;
- }
- else if (subs->freqshift >= 0)
- f <<= subs->freqshift;
+ ep->freqshift = shift;
+ } else if (ep->freqshift >= 0)
+ f <<= ep->freqshift;
else
- f >>= -subs->freqshift;
+ f >>= -ep->freqshift;
- if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) {
+ if (likely(f >= ep->freqn - ep->freqn / 8 && f <= ep->freqmax)) {
/*
* If the frequency looks valid, set it.
* This value is referred to in prepare_playback_urb().
*/
- spin_lock_irqsave(&subs->lock, flags);
- subs->freqm = f;
- spin_unlock_irqrestore(&subs->lock, flags);
+ spin_lock_irqsave(&ep->lock, flags);
+ ep->freqm = f;
+ spin_unlock_irqrestore(&ep->lock, flags);
} else {
/*
* Out of range; maybe the shift value is wrong.
* Reset it so that we autodetect again the next time.
*/
- subs->freqshift = INT_MIN;
- }
-
- return 0;
-}
-
-/* determine the number of frames in the next packet */
-static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
-{
- if (subs->fill_max)
- return subs->maxframesize;
- else {
- subs->phase = (subs->phase & 0xffff)
- + (subs->freqm << subs->datainterval);
- return min(subs->phase >> 16, subs->maxframesize);
+ ep->freqshift = INT_MIN;
}
}
-/*
- * Prepare urb for streaming before playback starts or when paused.
- *
- * We don't have any data, so we send silence.
- */
-static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- unsigned int i, offs, counts;
- struct snd_urb_ctx *ctx = urb->context;
- int stride = runtime->frame_bits >> 3;
-
- offs = 0;
- urb->dev = ctx->subs->dev;
- for (i = 0; i < ctx->packets; ++i) {
- counts = snd_usb_audio_next_packet_size(subs);
- urb->iso_frame_desc[i].offset = offs * stride;
- urb->iso_frame_desc[i].length = counts * stride;
- offs += counts;
- }
- urb->number_of_packets = ctx->packets;
- urb->transfer_buffer_length = offs * stride;
- memset(urb->transfer_buffer,
- runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
- offs * stride);
- return 0;
-}
-
-/*
- * prepare urb for playback data pipe
- *
- * Since a URB can handle only a single linear buffer, we must use double
- * buffering when the data to be transferred overflows the buffer boundary.
- * To avoid inconsistencies when updating hwptr_done, we use double buffering
- * for all URBs.
- */
-static int prepare_playback_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- int i, stride;
- unsigned int counts, frames, bytes;
- unsigned long flags;
- int period_elapsed = 0;
- struct snd_urb_ctx *ctx = urb->context;
-
- stride = runtime->frame_bits >> 3;
-
- frames = 0;
- urb->dev = ctx->subs->dev; /* we need to set this at each time */
- urb->number_of_packets = 0;
- spin_lock_irqsave(&subs->lock, flags);
- for (i = 0; i < ctx->packets; i++) {
- counts = snd_usb_audio_next_packet_size(subs);
- /* set up descriptor */
- urb->iso_frame_desc[i].offset = frames * stride;
- urb->iso_frame_desc[i].length = counts * stride;
- frames += counts;
- urb->number_of_packets++;
- subs->transfer_done += counts;
- if (subs->transfer_done >= runtime->period_size) {
- subs->transfer_done -= runtime->period_size;
- period_elapsed = 1;
- if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
- if (subs->transfer_done > 0) {
- /* FIXME: fill-max mode is not
- * supported yet */
- frames -= subs->transfer_done;
- counts -= subs->transfer_done;
- urb->iso_frame_desc[i].length =
- counts * stride;
- subs->transfer_done = 0;
- }
- i++;
- if (i < ctx->packets) {
- /* add a transfer delimiter */
- urb->iso_frame_desc[i].offset =
- frames * stride;
- urb->iso_frame_desc[i].length = 0;
- urb->number_of_packets++;
- }
- break;
- }
- }
- if (period_elapsed) /* finish at the period boundary */
- break;
- }
- bytes = frames * stride;
- if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
- /* err, the transferred area goes over buffer boundary. */
- unsigned int bytes1 =
- runtime->buffer_size * stride - subs->hwptr_done;
- memcpy(urb->transfer_buffer,
- runtime->dma_area + subs->hwptr_done, bytes1);
- memcpy(urb->transfer_buffer + bytes1,
- runtime->dma_area, bytes - bytes1);
- } else {
- memcpy(urb->transfer_buffer,
- runtime->dma_area + subs->hwptr_done, bytes);
- }
- subs->hwptr_done += bytes;
- if (subs->hwptr_done >= runtime->buffer_size * stride)
- subs->hwptr_done -= runtime->buffer_size * stride;
-
- /* update delay with exact number of samples queued */
- runtime->delay = subs->last_delay;
- runtime->delay += frames;
- subs->last_delay = runtime->delay;
-
- /* realign last_frame_number */
- subs->last_frame_number = usb_get_current_frame_number(subs->dev);
- subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
-
- spin_unlock_irqrestore(&subs->lock, flags);
- urb->transfer_buffer_length = bytes;
- if (period_elapsed)
- snd_pcm_period_elapsed(subs->pcm_substream);
- return 0;
-}
-
-/*
- * process after playback data complete
- * - decrease the delay count again
- */
-static int retire_playback_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- unsigned long flags;
- int stride = runtime->frame_bits >> 3;
- int processed = urb->transfer_buffer_length / stride;
- int est_delay;
-
- spin_lock_irqsave(&subs->lock, flags);
-
- est_delay = snd_usb_pcm_delay(subs, runtime->rate);
- /* update delay with exact number of samples played */
- if (processed > subs->last_delay)
- subs->last_delay = 0;
- else
- subs->last_delay -= processed;
- runtime->delay = subs->last_delay;
-
- /*
- * Report when delay estimate is off by more than 2ms.
- * The error should be lower than 2ms since the estimate relies
- * on two reads of a counter updated every ms.
- */
- if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
- snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
- est_delay, subs->last_delay);
-
- spin_unlock_irqrestore(&subs->lock, flags);
- return 0;
-}
-
-static const char *usb_error_string(int err)
-{
- switch (err) {
- case -ENODEV:
- return "no device";
- case -ENOENT:
- return "endpoint not enabled";
- case -EPIPE:
- return "endpoint stalled";
- case -ENOSPC:
- return "not enough bandwidth";
- case -ESHUTDOWN:
- return "device disabled";
- case -EHOSTUNREACH:
- return "device suspended";
- case -EINVAL:
- case -EAGAIN:
- case -EFBIG:
- case -EMSGSIZE:
- return "internal error";
- default:
- return "unknown error";
- }
-}
-
-/*
- * set up and start data/sync urbs
- */
-static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime)
-{
- unsigned int i;
- int err;
-
- if (subs->stream->chip->shutdown)
- return -EBADFD;
-
- for (i = 0; i < subs->nurbs; i++) {
- if (snd_BUG_ON(!subs->dataurb[i].urb))
- return -EINVAL;
- if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) {
- snd_printk(KERN_ERR "cannot prepare datapipe for urb %d\n", i);
- goto __error;
- }
- }
- if (subs->syncpipe) {
- for (i = 0; i < SYNC_URBS; i++) {
- if (snd_BUG_ON(!subs->syncurb[i].urb))
- return -EINVAL;
- if (subs->ops.prepare_sync(subs, runtime, subs->syncurb[i].urb) < 0) {
- snd_printk(KERN_ERR "cannot prepare syncpipe for urb %d\n", i);
- goto __error;
- }
- }
- }
-
- subs->active_mask = 0;
- subs->unlink_mask = 0;
- subs->running = 1;
- for (i = 0; i < subs->nurbs; i++) {
- err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC);
- if (err < 0) {
- snd_printk(KERN_ERR "cannot submit datapipe "
- "for urb %d, error %d: %s\n",
- i, err, usb_error_string(err));
- goto __error;
- }
- set_bit(i, &subs->active_mask);
- }
- if (subs->syncpipe) {
- for (i = 0; i < SYNC_URBS; i++) {
- err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC);
- if (err < 0) {
- snd_printk(KERN_ERR "cannot submit syncpipe "
- "for urb %d, error %d: %s\n",
- i, err, usb_error_string(err));
- goto __error;
- }
- set_bit(i + 16, &subs->active_mask);
- }
- }
- return 0;
-
- __error:
- // snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
- deactivate_urbs(subs, 0, 0);
- return -EPIPE;
-}
-
-
-/*
- */
-static struct snd_urb_ops audio_urb_ops[2] = {
- {
- .prepare = prepare_nodata_playback_urb,
- .retire = retire_playback_urb,
- .prepare_sync = prepare_playback_sync_urb,
- .retire_sync = retire_playback_sync_urb,
- },
- {
- .prepare = prepare_capture_urb,
- .retire = retire_capture_urb,
- .prepare_sync = prepare_capture_sync_urb,
- .retire_sync = retire_capture_sync_urb,
- },
-};
-
-/*
- * initialize the substream instance.
- */
-
-void snd_usb_init_substream(struct snd_usb_stream *as,
- int stream, struct audioformat *fp)
-{
- struct snd_usb_substream *subs = &as->substream[stream];
-
- INIT_LIST_HEAD(&subs->fmt_list);
- spin_lock_init(&subs->lock);
-
- subs->stream = as;
- subs->direction = stream;
- subs->dev = as->chip->dev;
- subs->txfr_quirk = as->chip->txfr_quirk;
- subs->ops = audio_urb_ops[stream];
- if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH)
- subs->ops.prepare_sync = prepare_capture_sync_urb_hs;
-
- snd_usb_set_pcm_ops(as->pcm, stream);
-
- list_add_tail(&fp->list, &subs->fmt_list);
- subs->formats |= fp->formats;
- subs->endpoint = fp->endpoint;
- subs->num_formats++;
- subs->fmt_type = fp->fmt_type;
-}
-
-int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_usb_substream *subs = substream->runtime->private_data;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- subs->ops.prepare = prepare_playback_urb;
- return 0;
- case SNDRV_PCM_TRIGGER_STOP:
- return deactivate_urbs(subs, 0, 0);
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- subs->ops.prepare = prepare_nodata_playback_urb;
- return 0;
- }
-
- return -EINVAL;
-}
-
-int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_usb_substream *subs = substream->runtime->private_data;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- subs->ops.retire = retire_capture_urb;
- return start_urbs(subs, substream->runtime);
- case SNDRV_PCM_TRIGGER_STOP:
- return deactivate_urbs(subs, 0, 0);
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- subs->ops.retire = retire_paused_capture_urb;
- return 0;
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- subs->ops.retire = retire_capture_urb;
- return 0;
- }
-
- return -EINVAL;
-}
-
-int snd_usb_substream_prepare(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime)
-{
- /* clear urbs (to be sure) */
- deactivate_urbs(subs, 0, 1);
- wait_clear_urbs(subs);
-
- /* for playback, submit the URBs now; otherwise, the first hwptr_done
- * updates for all URBs would happen at the same time when starting */
- if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
- subs->ops.prepare = prepare_nodata_playback_urb;
- return start_urbs(subs, runtime);
- }
-
- return 0;
-}
-
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 88eb63a636eb..ee2723fb174f 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -1,21 +1,29 @@
#ifndef __USBAUDIO_ENDPOINT_H
#define __USBAUDIO_ENDPOINT_H
-void snd_usb_init_substream(struct snd_usb_stream *as,
- int stream,
- struct audioformat *fp);
+#define SND_USB_ENDPOINT_TYPE_DATA 0
+#define SND_USB_ENDPOINT_TYPE_SYNC 1
-int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
- unsigned int period_bytes,
- unsigned int rate,
- unsigned int frame_bits);
+struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
+ struct usb_host_interface *alts,
+ int ep_num, int direction, int type);
-void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force);
+int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
+ struct snd_pcm_hw_params *hw_params,
+ struct audioformat *fmt,
+ struct snd_usb_endpoint *sync_ep);
-int snd_usb_substream_prepare(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime);
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep);
+void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
+ int force, int can_sleep, int wait);
+int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
+int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
+void snd_usb_endpoint_free(struct list_head *head);
-int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd);
-int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd);
+int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep);
+
+void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
+ struct snd_usb_endpoint *sender,
+ const struct urb *urb);
#endif /* __USBAUDIO_ENDPOINT_H */
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index ab23869c01bb..4f40ba823163 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -486,7 +486,7 @@ static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
/*
* TLV callback for mixer volume controls
*/
-static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *_tlv)
{
struct usb_mixer_elem_info *cval = kcontrol->private_data;
@@ -770,6 +770,26 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
struct snd_kcontrol *kctl)
{
switch (cval->mixer->chip->usb_id) {
+ case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
+ case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
+ if (strcmp(kctl->id.name, "Effect Duration") == 0) {
+ snd_printk(KERN_INFO
+ "usb-audio: set quirk for FTU Effect Duration\n");
+ cval->min = 0x0000;
+ cval->max = 0x7f00;
+ cval->res = 0x0100;
+ break;
+ }
+ if (strcmp(kctl->id.name, "Effect Volume") == 0 ||
+ strcmp(kctl->id.name, "Effect Feedback Volume") == 0) {
+ snd_printk(KERN_INFO
+ "usb-audio: set quirks for FTU Effect Feedback/Volume\n");
+ cval->min = 0x00;
+ cval->max = 0x7f;
+ break;
+ }
+ break;
+
case USB_ID(0x0471, 0x0101):
case USB_ID(0x0471, 0x0104):
case USB_ID(0x0471, 0x0105):
@@ -1121,9 +1141,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
len = snd_usb_copy_string_desc(state, nameid,
kctl->id.name, sizeof(kctl->id.name));
- /* get min/max values */
- get_min_max_with_quirks(cval, 0, kctl);
-
switch (control) {
case UAC_FU_MUTE:
case UAC_FU_VOLUME:
@@ -1155,17 +1172,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
}
append_ctl_name(kctl, control == UAC_FU_MUTE ?
" Switch" : " Volume");
- if (control == UAC_FU_VOLUME) {
- check_mapped_dB(map, cval);
- if (cval->dBmin < cval->dBmax || !cval->initialized) {
- kctl->tlv.c = mixer_vol_tlv;
- kctl->vd[0].access |=
- SNDRV_CTL_ELEM_ACCESS_TLV_READ |
- SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
- }
- }
break;
-
default:
if (! len)
strlcpy(kctl->id.name, audio_feature_info[control-1].name,
@@ -1173,6 +1180,19 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
break;
}
+ /* get min/max values */
+ get_min_max_with_quirks(cval, 0, kctl);
+
+ if (control == UAC_FU_VOLUME) {
+ check_mapped_dB(map, cval);
+ if (cval->dBmin < cval->dBmax || !cval->initialized) {
+ kctl->tlv.c = snd_usb_mixer_vol_tlv;
+ kctl->vd[0].access |=
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
+ }
+ }
+
range = (cval->max - cval->min) / cval->res;
/* Are there devices with volume range more than 255? I use a bit more
* to be sure. 384 is a resolution magic number found on Logitech
@@ -1388,7 +1408,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *r
for (pin = 0; pin < input_pins; pin++) {
err = parse_audio_unit(state, desc->baSourceID[pin]);
if (err < 0)
- return err;
+ continue;
err = check_input_term(state, desc->baSourceID[pin], &iterm);
if (err < 0)
return err;
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index 81b2d8a32fb0..a7f3d45a8acf 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -68,4 +68,7 @@ int snd_usb_mixer_activate(struct usb_mixer_interface *mixer);
int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
struct snd_kcontrol *kctl);
+int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+ unsigned int size, unsigned int __user *_tlv);
+
#endif /* __USBMIXER_H */
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index f1324c423835..41daaa24c25f 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -288,6 +288,15 @@ static struct usbmix_name_map scratch_live_map[] = {
{ 0 } /* terminator */
};
+static struct usbmix_name_map ebox44_map[] = {
+ { 4, NULL }, /* FU */
+ { 6, NULL }, /* MU */
+ { 7, NULL }, /* FU */
+ { 10, NULL }, /* FU */
+ { 11, NULL }, /* MU */
+ { 0 }
+};
+
/* "Gamesurround Muse Pocket LT" looks same like "Sound Blaster MP3+"
* most importand difference is SU[8], it should be set to "Capture Source"
* to make alsamixer and PA working properly.
@@ -371,6 +380,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
.map = scratch_live_map,
.ignore_ctl_error = 1,
},
+ {
+ .id = USB_ID(0x200c, 0x1018),
+ .map = ebox44_map,
+ },
{ 0 } /* terminator */
};
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index ab125ee0b0f0..41f4b6911920 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -42,6 +42,77 @@
extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
+/* private_free callback */
+static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
+{
+ kfree(kctl->private_data);
+ kctl->private_data = NULL;
+}
+
+/* This function allows for the creation of standard UAC controls.
+ * See the quirks for M-Audio FTUs or Ebox-44.
+ * If you don't want to set a TLV callback pass NULL.
+ *
+ * Since there doesn't seem to be a devices that needs a multichannel
+ * version, we keep it mono for simplicity.
+ */
+static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
+ unsigned int unitid,
+ unsigned int control,
+ unsigned int cmask,
+ int val_type,
+ const char *name,
+ snd_kcontrol_tlv_rw_t *tlv_callback)
+{
+ int err;
+ struct usb_mixer_elem_info *cval;
+ struct snd_kcontrol *kctl;
+
+ cval = kzalloc(sizeof(*cval), GFP_KERNEL);
+ if (!cval)
+ return -ENOMEM;
+
+ cval->id = unitid;
+ cval->mixer = mixer;
+ cval->val_type = val_type;
+ cval->channels = 1;
+ cval->control = control;
+ cval->cmask = cmask;
+
+ /* get_min_max() is called only for integer volumes later,
+ * so provide a short-cut for booleans */
+ cval->min = 0;
+ cval->max = 1;
+ cval->res = 0;
+ cval->dBmin = 0;
+ cval->dBmax = 0;
+
+ /* Create control */
+ kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval);
+ if (!kctl) {
+ kfree(cval);
+ return -ENOMEM;
+ }
+
+ /* Set name */
+ snprintf(kctl->id.name, sizeof(kctl->id.name), name);
+ kctl->private_free = usb_mixer_elem_free;
+
+ /* set TLV */
+ if (tlv_callback) {
+ kctl->tlv.c = tlv_callback;
+ kctl->vd[0].access |=
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
+ }
+ /* Add control to mixer */
+ err = snd_usb_mixer_add_control(mixer, kctl);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
/*
* Sound Blaster remote control configuration
*
@@ -495,60 +566,218 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
}
/* M-Audio FastTrack Ultra quirks */
+/* FTU Effect switch */
+struct snd_ftu_eff_switch_priv_val {
+ struct usb_mixer_interface *mixer;
+ int cached_value;
+ int is_cached;
+};
-/* private_free callback */
-static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
+static int snd_ftu_eff_switch_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
- kfree(kctl->private_data);
- kctl->private_data = NULL;
+ static const char *texts[8] = {"Room 1",
+ "Room 2",
+ "Room 3",
+ "Hall 1",
+ "Hall 2",
+ "Plate",
+ "Delay",
+ "Echo"
+ };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 8;
+ if (uinfo->value.enumerated.item > 7)
+ uinfo->value.enumerated.item = 7;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+
+ return 0;
}
-static int snd_maudio_ftu_create_ctl(struct usb_mixer_interface *mixer,
- int in, int out, const char *name)
+static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *cval;
+ struct snd_usb_audio *chip;
+ struct usb_mixer_interface *mixer;
+ struct snd_ftu_eff_switch_priv_val *pval;
+ int err;
+ unsigned char value[2];
+
+ const int id = 6;
+ const int validx = 1;
+ const int val_len = 2;
+
+ value[0] = 0x00;
+ value[1] = 0x00;
+
+ pval = (struct snd_ftu_eff_switch_priv_val *)
+ kctl->private_value;
+
+ if (pval->is_cached) {
+ ucontrol->value.enumerated.item[0] = pval->cached_value;
+ return 0;
+ }
+
+ mixer = (struct usb_mixer_interface *) pval->mixer;
+ if (snd_BUG_ON(!mixer))
+ return -EINVAL;
+
+ chip = (struct snd_usb_audio *) mixer->chip;
+ if (snd_BUG_ON(!chip))
+ return -EINVAL;
+
+
+ err = snd_usb_ctl_msg(chip->dev,
+ usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
+ USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+ validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
+ value, val_len);
+ if (err < 0)
+ return err;
+
+ ucontrol->value.enumerated.item[0] = value[0];
+ pval->cached_value = value[0];
+ pval->is_cached = 1;
+
+ return 0;
+}
+
+static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_usb_audio *chip;
+ struct snd_ftu_eff_switch_priv_val *pval;
+
+ struct usb_mixer_interface *mixer;
+ int changed, cur_val, err, new_val;
+ unsigned char value[2];
+
+
+ const int id = 6;
+ const int validx = 1;
+ const int val_len = 2;
+
+ changed = 0;
+
+ pval = (struct snd_ftu_eff_switch_priv_val *)
+ kctl->private_value;
+ cur_val = pval->cached_value;
+ new_val = ucontrol->value.enumerated.item[0];
+
+ mixer = (struct usb_mixer_interface *) pval->mixer;
+ if (snd_BUG_ON(!mixer))
+ return -EINVAL;
+
+ chip = (struct snd_usb_audio *) mixer->chip;
+ if (snd_BUG_ON(!chip))
+ return -EINVAL;
+
+ if (!pval->is_cached) {
+ /* Read current value */
+ err = snd_usb_ctl_msg(chip->dev,
+ usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
+ USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+ validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
+ value, val_len);
+ if (err < 0)
+ return err;
+
+ cur_val = value[0];
+ pval->cached_value = cur_val;
+ pval->is_cached = 1;
+ }
+ /* update value if needed */
+ if (cur_val != new_val) {
+ value[0] = new_val;
+ value[1] = 0;
+ err = snd_usb_ctl_msg(chip->dev,
+ usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
+ USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+ validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
+ value, val_len);
+ if (err < 0)
+ return err;
+
+ pval->cached_value = new_val;
+ pval->is_cached = 1;
+ changed = 1;
+ }
+
+ return changed;
+}
+
+static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer)
+{
+ static struct snd_kcontrol_new template = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Effect Program Switch",
+ .index = 0,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_ftu_eff_switch_info,
+ .get = snd_ftu_eff_switch_get,
+ .put = snd_ftu_eff_switch_put
+ };
+
+ int err;
struct snd_kcontrol *kctl;
+ struct snd_ftu_eff_switch_priv_val *pval;
- cval = kzalloc(sizeof(*cval), GFP_KERNEL);
- if (!cval)
+ pval = kzalloc(sizeof(*pval), GFP_KERNEL);
+ if (!pval)
return -ENOMEM;
- cval->id = 5;
- cval->mixer = mixer;
- cval->val_type = USB_MIXER_S16;
- cval->channels = 1;
- cval->control = out + 1;
- cval->cmask = 1 << in;
+ pval->cached_value = 0;
+ pval->is_cached = 0;
+ pval->mixer = mixer;
- kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval);
+ template.private_value = (unsigned long) pval;
+ kctl = snd_ctl_new1(&template, mixer->chip);
if (!kctl) {
- kfree(cval);
+ kfree(pval);
return -ENOMEM;
}
- snprintf(kctl->id.name, sizeof(kctl->id.name), name);
- kctl->private_free = usb_mixer_elem_free;
- return snd_usb_mixer_add_control(mixer, kctl);
+ err = snd_ctl_add(mixer->chip->card, kctl);
+ if (err < 0)
+ return err;
+
+ return 0;
}
-static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer)
+/* Create volume controls for FTU devices*/
+static int snd_ftu_create_volume_ctls(struct usb_mixer_interface *mixer)
{
char name[64];
+ unsigned int control, cmask;
int in, out, err;
+ const unsigned int id = 5;
+ const int val_type = USB_MIXER_S16;
+
for (out = 0; out < 8; out++) {
+ control = out + 1;
for (in = 0; in < 8; in++) {
+ cmask = 1 << in;
snprintf(name, sizeof(name),
- "AIn%d - Out%d Capture Volume", in + 1, out + 1);
- err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
+ "AIn%d - Out%d Capture Volume",
+ in + 1, out + 1);
+ err = snd_create_std_mono_ctl(mixer, id, control,
+ cmask, val_type, name,
+ &snd_usb_mixer_vol_tlv);
if (err < 0)
return err;
}
-
for (in = 8; in < 16; in++) {
+ cmask = 1 << in;
snprintf(name, sizeof(name),
- "DIn%d - Out%d Playback Volume", in - 7, out + 1);
- err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
+ "DIn%d - Out%d Playback Volume",
+ in - 7, out + 1);
+ err = snd_create_std_mono_ctl(mixer, id, control,
+ cmask, val_type, name,
+ &snd_usb_mixer_vol_tlv);
if (err < 0)
return err;
}
@@ -557,6 +786,191 @@ static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer)
return 0;
}
+/* This control needs a volume quirk, see mixer.c */
+static int snd_ftu_create_effect_volume_ctl(struct usb_mixer_interface *mixer)
+{
+ static const char name[] = "Effect Volume";
+ const unsigned int id = 6;
+ const int val_type = USB_MIXER_U8;
+ const unsigned int control = 2;
+ const unsigned int cmask = 0;
+
+ return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
+ name, snd_usb_mixer_vol_tlv);
+}
+
+/* This control needs a volume quirk, see mixer.c */
+static int snd_ftu_create_effect_duration_ctl(struct usb_mixer_interface *mixer)
+{
+ static const char name[] = "Effect Duration";
+ const unsigned int id = 6;
+ const int val_type = USB_MIXER_S16;
+ const unsigned int control = 3;
+ const unsigned int cmask = 0;
+
+ return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
+ name, snd_usb_mixer_vol_tlv);
+}
+
+/* This control needs a volume quirk, see mixer.c */
+static int snd_ftu_create_effect_feedback_ctl(struct usb_mixer_interface *mixer)
+{
+ static const char name[] = "Effect Feedback Volume";
+ const unsigned int id = 6;
+ const int val_type = USB_MIXER_U8;
+ const unsigned int control = 4;
+ const unsigned int cmask = 0;
+
+ return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
+ name, NULL);
+}
+
+static int snd_ftu_create_effect_return_ctls(struct usb_mixer_interface *mixer)
+{
+ unsigned int cmask;
+ int err, ch;
+ char name[48];
+
+ const unsigned int id = 7;
+ const int val_type = USB_MIXER_S16;
+ const unsigned int control = 7;
+
+ for (ch = 0; ch < 4; ++ch) {
+ cmask = 1 << ch;
+ snprintf(name, sizeof(name),
+ "Effect Return %d Volume", ch + 1);
+ err = snd_create_std_mono_ctl(mixer, id, control,
+ cmask, val_type, name,
+ snd_usb_mixer_vol_tlv);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int snd_ftu_create_effect_send_ctls(struct usb_mixer_interface *mixer)
+{
+ unsigned int cmask;
+ int err, ch;
+ char name[48];
+
+ const unsigned int id = 5;
+ const int val_type = USB_MIXER_S16;
+ const unsigned int control = 9;
+
+ for (ch = 0; ch < 8; ++ch) {
+ cmask = 1 << ch;
+ snprintf(name, sizeof(name),
+ "Effect Send AIn%d Volume", ch + 1);
+ err = snd_create_std_mono_ctl(mixer, id, control, cmask,
+ val_type, name,
+ snd_usb_mixer_vol_tlv);
+ if (err < 0)
+ return err;
+ }
+ for (ch = 8; ch < 16; ++ch) {
+ cmask = 1 << ch;
+ snprintf(name, sizeof(name),
+ "Effect Send DIn%d Volume", ch - 7);
+ err = snd_create_std_mono_ctl(mixer, id, control, cmask,
+ val_type, name,
+ snd_usb_mixer_vol_tlv);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
+static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer)
+{
+ int err;
+
+ err = snd_ftu_create_volume_ctls(mixer);
+ if (err < 0)
+ return err;
+
+ err = snd_ftu_create_effect_switch(mixer);
+ if (err < 0)
+ return err;
+ err = snd_ftu_create_effect_volume_ctl(mixer);
+ if (err < 0)
+ return err;
+
+ err = snd_ftu_create_effect_duration_ctl(mixer);
+ if (err < 0)
+ return err;
+
+ err = snd_ftu_create_effect_feedback_ctl(mixer);
+ if (err < 0)
+ return err;
+
+ err = snd_ftu_create_effect_return_ctls(mixer);
+ if (err < 0)
+ return err;
+
+ err = snd_ftu_create_effect_send_ctls(mixer);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+
+/*
+ * Create mixer for Electrix Ebox-44
+ *
+ * The mixer units from this device are corrupt, and even where they
+ * are valid they presents mono controls as L and R channels of
+ * stereo. So we create a good mixer in code.
+ */
+
+static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer)
+{
+ int err;
+
+ err = snd_create_std_mono_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN,
+ "Headphone Playback Switch", NULL);
+ if (err < 0)
+ return err;
+ err = snd_create_std_mono_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16,
+ "Headphone A Mix Playback Volume", NULL);
+ if (err < 0)
+ return err;
+ err = snd_create_std_mono_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16,
+ "Headphone B Mix Playback Volume", NULL);
+ if (err < 0)
+ return err;
+
+ err = snd_create_std_mono_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN,
+ "Output Playback Switch", NULL);
+ if (err < 0)
+ return err;
+ err = snd_create_std_mono_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16,
+ "Output A Playback Volume", NULL);
+ if (err < 0)
+ return err;
+ err = snd_create_std_mono_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16,
+ "Output B Playback Volume", NULL);
+ if (err < 0)
+ return err;
+
+ err = snd_create_std_mono_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN,
+ "Input Capture Switch", NULL);
+ if (err < 0)
+ return err;
+ err = snd_create_std_mono_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16,
+ "Input A Capture Volume", NULL);
+ if (err < 0)
+ return err;
+ err = snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16,
+ "Input B Capture Volume", NULL);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
unsigned char samplerate_id)
{
@@ -600,7 +1014,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
- err = snd_maudio_ftu_create_mixer(mixer);
+ err = snd_ftu_create_mixer(mixer);
break;
case USB_ID(0x0b05, 0x1739):
@@ -619,6 +1033,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
snd_nativeinstruments_ta10_mixers,
ARRAY_SIZE(snd_nativeinstruments_ta10_mixers));
break;
+
+ case USB_ID(0x200c, 0x1018): /* Electrix Ebox-44 */
+ err = snd_ebox44_create_mixer(mixer);
+ break;
}
return err;
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 0eed6115c2d4..24839d932648 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/ratelimit.h>
#include <linux/usb.h>
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>
@@ -34,6 +35,9 @@
#include "clock.h"
#include "power.h"
+#define SUBSTREAM_FLAG_DATA_EP_STARTED 0
+#define SUBSTREAM_FLAG_SYNC_EP_STARTED 1
+
/* return the estimated delay based on USB frame counters */
snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
unsigned int rate)
@@ -208,6 +212,84 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
}
}
+static int start_endpoints(struct snd_usb_substream *subs)
+{
+ int err;
+
+ if (!subs->data_endpoint)
+ return -EINVAL;
+
+ if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
+ struct snd_usb_endpoint *ep = subs->data_endpoint;
+
+ snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep);
+
+ ep->data_subs = subs;
+ err = snd_usb_endpoint_start(ep);
+ if (err < 0) {
+ clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
+ return err;
+ }
+ }
+
+ if (subs->sync_endpoint &&
+ !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
+ struct snd_usb_endpoint *ep = subs->sync_endpoint;
+
+ snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep);
+
+ ep->sync_slave = subs->data_endpoint;
+ err = snd_usb_endpoint_start(ep);
+ if (err < 0) {
+ clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static void stop_endpoints(struct snd_usb_substream *subs,
+ int force, int can_sleep, int wait)
+{
+ if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags))
+ snd_usb_endpoint_stop(subs->sync_endpoint,
+ force, can_sleep, wait);
+
+ if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags))
+ snd_usb_endpoint_stop(subs->data_endpoint,
+ force, can_sleep, wait);
+}
+
+static int activate_endpoints(struct snd_usb_substream *subs)
+{
+ if (subs->sync_endpoint) {
+ int ret;
+
+ ret = snd_usb_endpoint_activate(subs->sync_endpoint);
+ if (ret < 0)
+ return ret;
+ }
+
+ return snd_usb_endpoint_activate(subs->data_endpoint);
+}
+
+static int deactivate_endpoints(struct snd_usb_substream *subs)
+{
+ int reta, retb;
+
+ reta = snd_usb_endpoint_deactivate(subs->sync_endpoint);
+ retb = snd_usb_endpoint_deactivate(subs->data_endpoint);
+
+ if (reta < 0)
+ return reta;
+
+ if (retb < 0)
+ return retb;
+
+ return 0;
+}
+
/*
* find a matching format and set up the interface
*/
@@ -219,7 +301,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
struct usb_interface *iface;
unsigned int ep, attr;
int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
- int err;
+ int err, implicit_fb = 0;
iface = usb_ifnum_to_if(dev, fmt->iface);
if (WARN_ON(!iface))
@@ -232,40 +314,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
if (fmt == subs->cur_audiofmt)
return 0;
- /* close the old interface */
- if (subs->interface >= 0 && subs->interface != fmt->iface) {
- if (usb_set_interface(subs->dev, subs->interface, 0) < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed\n",
- dev->devnum, fmt->iface, fmt->altsetting);
- return -EIO;
- }
- subs->interface = -1;
- subs->altset_idx = 0;
- }
-
- /* set interface */
- if (subs->interface != fmt->iface || subs->altset_idx != fmt->altset_idx) {
- if (usb_set_interface(dev, fmt->iface, fmt->altsetting) < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed\n",
- dev->devnum, fmt->iface, fmt->altsetting);
- return -EIO;
- }
- snd_printdd(KERN_INFO "setting usb interface %d:%d\n", fmt->iface, fmt->altsetting);
- subs->interface = fmt->iface;
- subs->altset_idx = fmt->altset_idx;
- }
-
- /* create a data pipe */
- ep = fmt->endpoint & USB_ENDPOINT_NUMBER_MASK;
- if (is_playback)
- subs->datapipe = usb_sndisocpipe(dev, ep);
- else
- subs->datapipe = usb_rcvisocpipe(dev, ep);
- subs->datainterval = fmt->datainterval;
- subs->syncpipe = subs->syncinterval = 0;
- subs->maxpacksize = fmt->maxpacksize;
- subs->syncmaxsize = 0;
- subs->fill_max = 0;
+ subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip,
+ alts, fmt->endpoint, subs->direction,
+ SND_USB_ENDPOINT_TYPE_DATA);
+ if (!subs->data_endpoint)
+ return -EINVAL;
/* we need a sync pipe in async OUT or adaptive IN mode */
/* check the number of EP, since some devices have broken
@@ -273,8 +326,25 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
* assume it as adaptive-out or sync-in.
*/
attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
+
+ switch (subs->stream->chip->usb_id) {
+ case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
+ case USB_ID(0x0763, 0x2081):
+ if (is_playback) {
+ implicit_fb = 1;
+ ep = 0x81;
+ iface = usb_ifnum_to_if(dev, 2);
+
+ if (!iface || iface->num_altsetting == 0)
+ return -EINVAL;
+
+ alts = &iface->altsetting[1];
+ goto add_sync_ep;
+ }
+ }
+
if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) ||
- (! is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) &&
+ (!is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) &&
altsd->bNumEndpoints >= 2) {
/* check sync-pipe endpoint */
/* ... and check descriptor size before accessing bSynchAddress
@@ -282,7 +352,8 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
the audio fields in the endpoint descriptors */
if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != 0x01 ||
(get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
- get_endpoint(alts, 1)->bSynchAddress != 0)) {
+ get_endpoint(alts, 1)->bSynchAddress != 0 &&
+ !implicit_fb)) {
snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n",
dev->devnum, fmt->iface, fmt->altsetting);
return -EINVAL;
@@ -290,33 +361,27 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
ep = get_endpoint(alts, 1)->bEndpointAddress;
if (get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
(( is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) ||
- (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) {
+ (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)) ||
+ ( is_playback && !implicit_fb))) {
snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n",
dev->devnum, fmt->iface, fmt->altsetting);
return -EINVAL;
}
- ep &= USB_ENDPOINT_NUMBER_MASK;
- if (is_playback)
- subs->syncpipe = usb_rcvisocpipe(dev, ep);
- else
- subs->syncpipe = usb_sndisocpipe(dev, ep);
- if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
- get_endpoint(alts, 1)->bRefresh >= 1 &&
- get_endpoint(alts, 1)->bRefresh <= 9)
- subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
- else if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
- subs->syncinterval = 1;
- else if (get_endpoint(alts, 1)->bInterval >= 1 &&
- get_endpoint(alts, 1)->bInterval <= 16)
- subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1;
- else
- subs->syncinterval = 3;
- subs->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
- }
-
- /* always fill max packet size */
- if (fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX)
- subs->fill_max = 1;
+
+ implicit_fb = (get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_USAGE_MASK)
+ == USB_ENDPOINT_USAGE_IMPLICIT_FB;
+
+add_sync_ep:
+ subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip,
+ alts, ep, !subs->direction,
+ implicit_fb ?
+ SND_USB_ENDPOINT_TYPE_DATA :
+ SND_USB_ENDPOINT_TYPE_SYNC);
+ if (!subs->sync_endpoint)
+ return -EINVAL;
+
+ subs->data_endpoint->sync_master = subs->sync_endpoint;
+ }
if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0)
return err;
@@ -390,15 +455,30 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
if (changed) {
mutex_lock(&subs->stream->chip->shutdown_mutex);
/* format changed */
- snd_usb_release_substream_urbs(subs, 0);
- /* influenced: period_bytes, channels, rate, format, */
- ret = snd_usb_init_substream_urbs(subs, params_period_bytes(hw_params),
- params_rate(hw_params),
- snd_pcm_format_physical_width(params_format(hw_params)) *
- params_channels(hw_params));
+ stop_endpoints(subs, 0, 0, 0);
+ deactivate_endpoints(subs);
+
+ ret = activate_endpoints(subs);
+ if (ret < 0)
+ goto unlock;
+
+ ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt,
+ subs->sync_endpoint);
+ if (ret < 0)
+ goto unlock;
+
+ if (subs->sync_endpoint)
+ ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
+ hw_params, fmt, NULL);
+unlock:
mutex_unlock(&subs->stream->chip->shutdown_mutex);
}
+ if (ret == 0) {
+ subs->interface = fmt->iface;
+ subs->altset_idx = fmt->altset_idx;
+ }
+
return ret;
}
@@ -415,7 +495,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
subs->cur_rate = 0;
subs->period_bytes = 0;
mutex_lock(&subs->stream->chip->shutdown_mutex);
- snd_usb_release_substream_urbs(subs, 0);
+ stop_endpoints(subs, 0, 1, 1);
mutex_unlock(&subs->stream->chip->shutdown_mutex);
return snd_pcm_lib_free_vmalloc_buffer(substream);
}
@@ -435,19 +515,28 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
return -ENXIO;
}
+ if (snd_BUG_ON(!subs->data_endpoint))
+ return -EIO;
+
/* some unit conversions in runtime */
- subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize);
- subs->curframesize = bytes_to_frames(runtime, subs->curpacksize);
+ subs->data_endpoint->maxframesize =
+ bytes_to_frames(runtime, subs->data_endpoint->maxpacksize);
+ subs->data_endpoint->curframesize =
+ bytes_to_frames(runtime, subs->data_endpoint->curpacksize);
/* reset the pointer */
subs->hwptr_done = 0;
subs->transfer_done = 0;
- subs->phase = 0;
subs->last_delay = 0;
subs->last_frame_number = 0;
runtime->delay = 0;
- return snd_usb_substream_prepare(subs, runtime);
+ /* for playback, submit the URBs now; otherwise, the first hwptr_done
+ * updates for all URBs would happen at the same time when starting */
+ if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
+ return start_endpoints(subs);
+
+ return 0;
}
static struct snd_pcm_hardware snd_usb_hardware =
@@ -842,16 +931,171 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
{
+ int ret;
struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
struct snd_usb_substream *subs = &as->substream[direction];
- if (!as->chip->shutdown && subs->interface >= 0) {
- usb_set_interface(subs->dev, subs->interface, 0);
- subs->interface = -1;
- }
+ stop_endpoints(subs, 0, 0, 0);
+ ret = deactivate_endpoints(subs);
subs->pcm_substream = NULL;
snd_usb_autosuspend(subs->stream->chip);
- return 0;
+
+ return ret;
+}
+
+/* Since a URB can handle only a single linear buffer, we must use double
+ * buffering when the data to be transferred overflows the buffer boundary.
+ * To avoid inconsistencies when updating hwptr_done, we use double buffering
+ * for all URBs.
+ */
+static void retire_capture_urb(struct snd_usb_substream *subs,
+ struct urb *urb)
+{
+ struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
+ unsigned int stride, frames, bytes, oldptr;
+ int i, period_elapsed = 0;
+ unsigned long flags;
+ unsigned char *cp;
+
+ stride = runtime->frame_bits >> 3;
+
+ for (i = 0; i < urb->number_of_packets; i++) {
+ cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+ if (urb->iso_frame_desc[i].status && printk_ratelimit()) {
+ snd_printdd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
+ // continue;
+ }
+ bytes = urb->iso_frame_desc[i].actual_length;
+ frames = bytes / stride;
+ if (!subs->txfr_quirk)
+ bytes = frames * stride;
+ if (bytes % (runtime->sample_bits >> 3) != 0) {
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ int oldbytes = bytes;
+#endif
+ bytes = frames * stride;
+ snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n",
+ oldbytes, bytes);
+ }
+ /* update the current pointer */
+ spin_lock_irqsave(&subs->lock, flags);
+ oldptr = subs->hwptr_done;
+ subs->hwptr_done += bytes;
+ if (subs->hwptr_done >= runtime->buffer_size * stride)
+ subs->hwptr_done -= runtime->buffer_size * stride;
+ frames = (bytes + (oldptr % stride)) / stride;
+ subs->transfer_done += frames;
+ if (subs->transfer_done >= runtime->period_size) {
+ subs->transfer_done -= runtime->period_size;
+ period_elapsed = 1;
+ }
+ spin_unlock_irqrestore(&subs->lock, flags);
+ /* copy a data chunk */
+ if (oldptr + bytes > runtime->buffer_size * stride) {
+ unsigned int bytes1 =
+ runtime->buffer_size * stride - oldptr;
+ memcpy(runtime->dma_area + oldptr, cp, bytes1);
+ memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
+ } else {
+ memcpy(runtime->dma_area + oldptr, cp, bytes);
+ }
+ }
+
+ if (period_elapsed)
+ snd_pcm_period_elapsed(subs->pcm_substream);
+}
+
+static void prepare_playback_urb(struct snd_usb_substream *subs,
+ struct urb *urb)
+{
+ struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
+ struct snd_urb_ctx *ctx = urb->context;
+ unsigned int counts, frames, bytes;
+ int i, stride, period_elapsed = 0;
+ unsigned long flags;
+
+ stride = runtime->frame_bits >> 3;
+
+ frames = 0;
+ urb->number_of_packets = 0;
+ spin_lock_irqsave(&subs->lock, flags);
+ for (i = 0; i < ctx->packets; i++) {
+ counts = ctx->packet_size[i];
+ /* set up descriptor */
+ urb->iso_frame_desc[i].offset = frames * stride;
+ urb->iso_frame_desc[i].length = counts * stride;
+ frames += counts;
+ urb->number_of_packets++;
+ subs->transfer_done += counts;
+ if (subs->transfer_done >= runtime->period_size) {
+ subs->transfer_done -= runtime->period_size;
+ period_elapsed = 1;
+ if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
+ if (subs->transfer_done > 0) {
+ /* FIXME: fill-max mode is not
+ * supported yet */
+ frames -= subs->transfer_done;
+ counts -= subs->transfer_done;
+ urb->iso_frame_desc[i].length =
+ counts * stride;
+ subs->transfer_done = 0;
+ }
+ i++;
+ if (i < ctx->packets) {
+ /* add a transfer delimiter */
+ urb->iso_frame_desc[i].offset =
+ frames * stride;
+ urb->iso_frame_desc[i].length = 0;
+ urb->number_of_packets++;
+ }
+ break;
+ }
+ }
+ if (period_elapsed &&
+ !snd_usb_endpoint_implict_feedback_sink(subs->data_endpoint)) /* finish at the period boundary */
+ break;
+ }
+ bytes = frames * stride;
+ if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
+ /* err, the transferred area goes over buffer boundary. */
+ unsigned int bytes1 =
+ runtime->buffer_size * stride - subs->hwptr_done;
+ memcpy(urb->transfer_buffer,
+ runtime->dma_area + subs->hwptr_done, bytes1);
+ memcpy(urb->transfer_buffer + bytes1,
+ runtime->dma_area, bytes - bytes1);
+ } else {
+ memcpy(urb->transfer_buffer,
+ runtime->dma_area + subs->hwptr_done, bytes);
+ }
+ subs->hwptr_done += bytes;
+ if (subs->hwptr_done >= runtime->buffer_size * stride)
+ subs->hwptr_done -= runtime->buffer_size * stride;
+ runtime->delay += frames;
+ spin_unlock_irqrestore(&subs->lock, flags);
+ urb->transfer_buffer_length = bytes;
+ if (period_elapsed)
+ snd_pcm_period_elapsed(subs->pcm_substream);
+}
+
+/*
+ * process after playback data complete
+ * - decrease the delay count again
+ */
+static void retire_playback_urb(struct snd_usb_substream *subs,
+ struct urb *urb)
+{
+ unsigned long flags;
+ struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
+ int stride = runtime->frame_bits >> 3;
+ int processed = urb->transfer_buffer_length / stride;
+
+ spin_lock_irqsave(&subs->lock, flags);
+ if (processed > runtime->delay)
+ runtime->delay = 0;
+ else
+ runtime->delay -= processed;
+ spin_unlock_irqrestore(&subs->lock, flags);
}
static int snd_usb_playback_open(struct snd_pcm_substream *substream)
@@ -874,6 +1118,63 @@ static int snd_usb_capture_close(struct snd_pcm_substream *substream)
return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_CAPTURE);
}
+static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ struct snd_usb_substream *subs = substream->runtime->private_data;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ subs->data_endpoint->prepare_data_urb = prepare_playback_urb;
+ subs->data_endpoint->retire_data_urb = retire_playback_urb;
+ subs->running = 1;
+ return 0;
+ case SNDRV_PCM_TRIGGER_STOP:
+ stop_endpoints(subs, 0, 0, 0);
+ subs->running = 0;
+ return 0;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ subs->data_endpoint->prepare_data_urb = NULL;
+ subs->data_endpoint->retire_data_urb = NULL;
+ subs->running = 0;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ int err;
+ struct snd_usb_substream *subs = substream->runtime->private_data;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ err = start_endpoints(subs);
+ if (err < 0)
+ return err;
+
+ subs->data_endpoint->retire_data_urb = retire_capture_urb;
+ subs->running = 1;
+ return 0;
+ case SNDRV_PCM_TRIGGER_STOP:
+ stop_endpoints(subs, 0, 0, 0);
+ subs->running = 0;
+ return 0;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ subs->data_endpoint->retire_data_urb = NULL;
+ subs->running = 0;
+ return 0;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ subs->data_endpoint->retire_data_urb = retire_capture_urb;
+ subs->running = 1;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
static struct snd_pcm_ops snd_usb_playback_ops = {
.open = snd_usb_playback_open,
.close = snd_usb_playback_close,
diff --git a/sound/usb/proc.c b/sound/usb/proc.c
index 961c9a250686..ebc1a5b5b3f1 100644
--- a/sound/usb/proc.c
+++ b/sound/usb/proc.c
@@ -25,6 +25,7 @@
#include "usbaudio.h"
#include "helper.h"
#include "card.h"
+#include "endpoint.h"
#include "proc.h"
/* convert our full speed USB rate into sampling rate in Hz */
@@ -115,28 +116,33 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
}
}
+static void proc_dump_ep_status(struct snd_usb_substream *subs,
+ struct snd_usb_endpoint *ep,
+ struct snd_info_buffer *buffer)
+{
+ if (!ep)
+ return;
+ snd_iprintf(buffer, " Packet Size = %d\n", ep->curpacksize);
+ snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n",
+ snd_usb_get_speed(subs->dev) == USB_SPEED_FULL
+ ? get_full_speed_hz(ep->freqm)
+ : get_high_speed_hz(ep->freqm),
+ ep->freqm >> 16, ep->freqm & 0xffff);
+ if (ep->freqshift != INT_MIN) {
+ int res = 16 - ep->freqshift;
+ snd_iprintf(buffer, " Feedback Format = %d.%d\n",
+ (ep->syncmaxsize > 3 ? 32 : 24) - res, res);
+ }
+}
+
static void proc_dump_substream_status(struct snd_usb_substream *subs, struct snd_info_buffer *buffer)
{
if (subs->running) {
- unsigned int i;
snd_iprintf(buffer, " Status: Running\n");
snd_iprintf(buffer, " Interface = %d\n", subs->interface);
snd_iprintf(buffer, " Altset = %d\n", subs->altset_idx);
- snd_iprintf(buffer, " URBs = %d [ ", subs->nurbs);
- for (i = 0; i < subs->nurbs; i++)
- snd_iprintf(buffer, "%d ", subs->dataurb[i].packets);
- snd_iprintf(buffer, "]\n");
- snd_iprintf(buffer, " Packet Size = %d\n", subs->curpacksize);
- snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n",
- snd_usb_get_speed(subs->dev) == USB_SPEED_FULL
- ? get_full_speed_hz(subs->freqm)
- : get_high_speed_hz(subs->freqm),
- subs->freqm >> 16, subs->freqm & 0xffff);
- if (subs->freqshift != INT_MIN)
- snd_iprintf(buffer, " Feedback Format = %d.%d\n",
- (subs->syncmaxsize > 3 ? 32 : 24)
- - (16 - subs->freqshift),
- 16 - subs->freqshift);
+ proc_dump_ep_status(subs, subs->data_endpoint, buffer);
+ proc_dump_ep_status(subs, subs->sync_endpoint, buffer);
} else {
snd_iprintf(buffer, " Status: Stop\n");
}
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 5ff8010b2d6f..6b7d7a2b7baa 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -73,6 +73,31 @@ static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
}
}
+/*
+ * initialize the substream instance.
+ */
+
+static void snd_usb_init_substream(struct snd_usb_stream *as,
+ int stream,
+ struct audioformat *fp)
+{
+ struct snd_usb_substream *subs = &as->substream[stream];
+
+ INIT_LIST_HEAD(&subs->fmt_list);
+ spin_lock_init(&subs->lock);
+
+ subs->stream = as;
+ subs->direction = stream;
+ subs->dev = as->chip->dev;
+ subs->txfr_quirk = as->chip->txfr_quirk;
+
+ snd_usb_set_pcm_ops(as->pcm, stream);
+
+ list_add_tail(&fp->list, &subs->fmt_list);
+ subs->formats |= fp->formats;
+ subs->num_formats++;
+ subs->fmt_type = fp->fmt_type;
+}
/*
* add this endpoint to the chip instance.
@@ -94,9 +119,9 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
if (as->fmt_type != fp->fmt_type)
continue;
subs = &as->substream[stream];
- if (!subs->endpoint)
+ if (!subs->data_endpoint)
continue;
- if (subs->endpoint == fp->endpoint) {
+ if (subs->data_endpoint->ep_num == fp->endpoint) {
list_add_tail(&fp->list, &subs->fmt_list);
subs->num_formats++;
subs->formats |= fp->formats;
@@ -109,7 +134,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
if (as->fmt_type != fp->fmt_type)
continue;
subs = &as->substream[stream];
- if (subs->endpoint)
+ if (subs->data_endpoint)
continue;
err = snd_pcm_new_stream(as->pcm, stream, 1);
if (err < 0)
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 3e2b03577936..b8233ebe250f 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -36,6 +36,7 @@ struct snd_usb_audio {
struct snd_card *card;
struct usb_interface *pm_intf;
u32 usb_id;
+ struct mutex mutex;
struct mutex shutdown_mutex;
unsigned int shutdown:1;
unsigned int probing:1;
@@ -46,6 +47,7 @@ struct snd_usb_audio {
int num_suspended_intf;
struct list_head pcm_list; /* list of pcm streams */
+ struct list_head ep_list; /* list of audio-related endpoints */
int pcm_devs;
struct list_head midi_list; /* list of midi interfaces */
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644
index 000000000000..3ae43947a171
--- /dev/null
+++ b/tools/Makefile
@@ -0,0 +1,77 @@
+include scripts/Makefile.include
+
+help:
+ @echo 'Possible targets:'
+ @echo ''
+ @echo ' cpupower - a tool for all things x86 CPU power'
+ @echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer'
+ @echo ' lguest - a minimal 32-bit x86 hypervisor'
+ @echo ' perf - Linux performance measurement and analysis tool'
+ @echo ' selftests - various kernel selftests'
+ @echo ' turbostat - Intel CPU idle stats and freq reporting tool'
+ @echo ' usb - USB testing tools'
+ @echo ' virtio - vhost test module'
+ @echo ' vm - misc vm tools'
+ @echo ' x86_energy_perf_policy - Intel energy policy tool'
+ @echo ''
+ @echo 'You can do:'
+ @echo ' $$ make -C tools/<tool>_install'
+ @echo ''
+ @echo ' from the kernel command line to build and install one of'
+ @echo ' the tools above'
+ @echo ''
+ @echo ' $$ make tools/install'
+ @echo ''
+ @echo ' installs all tools.'
+ @echo ''
+ @echo 'Cleaning targets:'
+ @echo ''
+ @echo ' all of the above with the "_clean" string appended cleans'
+ @echo ' the respective build directory.'
+ @echo ' clean: a summary clean target to clean _all_ folders'
+
+cpupower: FORCE
+ $(QUIET_SUBDIR0)power/$@/ $(QUIET_SUBDIR1)
+
+firewire lguest perf usb virtio vm: FORCE
+ $(QUIET_SUBDIR0)$@/ $(QUIET_SUBDIR1)
+
+selftests: FORCE
+ $(QUIET_SUBDIR0)testing/$@/ $(QUIET_SUBDIR1)
+
+turbostat x86_energy_perf_policy: FORCE
+ $(QUIET_SUBDIR0)power/x86/$@/ $(QUIET_SUBDIR1)
+
+cpupower_install:
+ $(QUIET_SUBDIR0)power/$(@:_install=)/ $(QUIET_SUBDIR1) install
+
+firewire_install lguest_install perf_install usb_install virtio_install vm_install:
+ $(QUIET_SUBDIR0)$(@:_install=)/ $(QUIET_SUBDIR1) install
+
+selftests_install:
+ $(QUIET_SUBDIR0)testing/$(@:_clean=)/ $(QUIET_SUBDIR1) install
+
+turbostat_install x86_energy_perf_policy_install:
+ $(QUIET_SUBDIR0)power/x86/$(@:_install=)/ $(QUIET_SUBDIR1) install
+
+install: cpupower_install firewire_install lguest_install perf_install \
+ selftests_install turbostat_install usb_install virtio_install \
+ vm_install x86_energy_perf_policy_install
+
+cpupower_clean:
+ $(QUIET_SUBDIR0)power/cpupower/ $(QUIET_SUBDIR1) clean
+
+firewire_clean lguest_clean perf_clean usb_clean virtio_clean vm_clean:
+ $(QUIET_SUBDIR0)$(@:_clean=)/ $(QUIET_SUBDIR1) clean
+
+selftests_clean:
+ $(QUIET_SUBDIR0)testing/$(@:_clean=)/ $(QUIET_SUBDIR1) clean
+
+turbostat_clean x86_energy_perf_policy_clean:
+ $(QUIET_SUBDIR0)power/x86/$(@:_clean=)/ $(QUIET_SUBDIR1) clean
+
+clean: cpupower_clean firewire_clean lguest_clean perf_clean selftests_clean \
+ turbostat_clean usb_clean virtio_clean vm_clean \
+ x86_energy_perf_policy_clean
+
+.PHONY: FORCE
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
new file mode 100644
index 000000000000..3d69aa9ff51e
--- /dev/null
+++ b/tools/lib/traceevent/Makefile
@@ -0,0 +1,303 @@
+# trace-cmd version
+EP_VERSION = 1
+EP_PATCHLEVEL = 1
+EP_EXTRAVERSION = 0
+
+# file format version
+FILE_VERSION = 6
+
+MAKEFLAGS += --no-print-directory
+
+
+# Makefiles suck: This macro sets a default value of $(2) for the
+# variable named by $(1), unless the variable has been set by
+# environment or command line. This is necessary for CC and AR
+# because make sets default values, so the simpler ?= approach
+# won't work as expected.
+define allow-override
+ $(if $(or $(findstring environment,$(origin $(1))),\
+ $(findstring command line,$(origin $(1)))),,\
+ $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+
+EXT = -std=gnu99
+INSTALL = install
+
+# Use DESTDIR for installing into a different root directory.
+# This is useful for building a package. The program will be
+# installed in this directory as if it was the root directory.
+# Then the build tool can move it later.
+DESTDIR ?=
+DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
+
+prefix ?= /usr/local
+bindir_relative = bin
+bindir = $(prefix)/$(bindir_relative)
+man_dir = $(prefix)/share/man
+man_dir_SQ = '$(subst ','\'',$(man_dir))'
+html_install = $(prefix)/share/kernelshark/html
+html_install_SQ = '$(subst ','\'',$(html_install))'
+img_install = $(prefix)/share/kernelshark/html/images
+img_install_SQ = '$(subst ','\'',$(img_install))'
+
+export man_dir man_dir_SQ html_install html_install_SQ INSTALL
+export img_install img_install_SQ
+export DESTDIR DESTDIR_SQ
+
+# copy a bit from Linux kbuild
+
+ifeq ("$(origin V)", "command line")
+ VERBOSE = $(V)
+endif
+ifndef VERBOSE
+ VERBOSE = 0
+endif
+
+ifeq ("$(origin O)", "command line")
+ BUILD_OUTPUT := $(O)
+endif
+
+ifeq ($(BUILD_SRC),)
+ifneq ($(BUILD_OUTPUT),)
+
+define build_output
+ $(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) \
+ BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
+endef
+
+saved-output := $(BUILD_OUTPUT)
+BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
+$(if $(BUILD_OUTPUT),, \
+ $(error output directory "$(saved-output)" does not exist))
+
+all: sub-make
+
+gui: force
+ $(call build_output, all_cmd)
+
+$(filter-out gui,$(MAKECMDGOALS)): sub-make
+
+sub-make: force
+ $(call build_output, $(MAKECMDGOALS))
+
+
+# Leave processing to above invocation of make
+skip-makefile := 1
+
+endif # BUILD_OUTPUT
+endif # BUILD_SRC
+
+# We process the rest of the Makefile if this is the final invocation of make
+ifeq ($(skip-makefile),)
+
+srctree := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR))
+objtree := $(CURDIR)
+src := $(srctree)
+obj := $(objtree)
+
+export prefix bindir src obj
+
+# Shell quotes
+bindir_SQ = $(subst ','\'',$(bindir))
+bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
+
+LIB_FILE = libtraceevent.a libtraceevent.so
+
+CONFIG_INCLUDES =
+CONFIG_LIBS =
+CONFIG_FLAGS =
+
+VERSION = $(EP_VERSION)
+PATCHLEVEL = $(EP_PATCHLEVEL)
+EXTRAVERSION = $(EP_EXTRAVERSION)
+
+OBJ = $@
+N =
+
+export Q VERBOSE
+
+EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
+
+INCLUDES = -I. -I/usr/local/include $(CONFIG_INCLUDES)
+
+# Set compile option CFLAGS if not set elsewhere
+CFLAGS ?= -g -Wall
+
+# Append required CFLAGS
+override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
+override CFLAGS += $(udis86-flags)
+
+ifeq ($(VERBOSE),1)
+ Q =
+ print_compile =
+ print_app_build =
+ print_fpic_compile =
+ print_shared_lib_compile =
+ print_plugin_obj_compile =
+ print_plugin_build =
+ print_install =
+else
+ Q = @
+ print_compile = echo ' CC '$(OBJ);
+ print_app_build = echo ' BUILD '$(OBJ);
+ print_fpic_compile = echo ' CC FPIC '$(OBJ);
+ print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ);
+ print_plugin_obj_compile = echo ' CC PLUGIN OBJ '$(OBJ);
+ print_plugin_build = echo ' CC PLUGI '$(OBJ);
+ print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ);
+ print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
+endif
+
+do_fpic_compile = \
+ ($(print_fpic_compile) \
+ $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
+
+do_app_build = \
+ ($(print_app_build) \
+ $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
+
+do_compile_shared_library = \
+ ($(print_shared_lib_compile) \
+ $(CC) --shared $^ -o $@)
+
+do_compile_plugin_obj = \
+ ($(print_plugin_obj_compile) \
+ $(CC) -c $(CFLAGS) -fPIC -o $@ $<)
+
+do_plugin_build = \
+ ($(print_plugin_build) \
+ $(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<)
+
+do_build_static_lib = \
+ ($(print_static_lib_build) \
+ $(RM) $@; $(AR) rcs $@ $^)
+
+
+define do_compile
+ $(print_compile) \
+ $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
+endef
+
+$(obj)/%.o: $(src)/%.c
+ $(Q)$(call do_compile)
+
+%.o: $(src)/%.c
+ $(Q)$(call do_compile)
+
+PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o
+
+ALL_OBJS = $(PEVENT_LIB_OBJS)
+
+CMD_TARGETS = $(LIB_FILE)
+
+TARGETS = $(CMD_TARGETS)
+
+
+all: all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+libtraceevent.so: $(PEVENT_LIB_OBJS)
+ $(Q)$(do_compile_shared_library)
+
+libtraceevent.a: $(PEVENT_LIB_OBJS)
+ $(Q)$(do_build_static_lib)
+
+$(PEVENT_LIB_OBJS): %.o: $(src)/%.c
+ $(Q)$(do_fpic_compile)
+
+define make_version.h
+ (echo '/* This file is automatically generated. Do not modify. */'; \
+ echo \#define VERSION_CODE $(shell \
+ expr $(VERSION) \* 256 + $(PATCHLEVEL)); \
+ echo '#define EXTRAVERSION ' $(EXTRAVERSION); \
+ echo '#define VERSION_STRING "'$(VERSION).$(PATCHLEVEL).$(EXTRAVERSION)'"'; \
+ echo '#define FILE_VERSION '$(FILE_VERSION); \
+ ) > $1
+endef
+
+define update_version.h
+ ($(call make_version.h, $@.tmp); \
+ if [ -r $@ ] && cmp -s $@ $@.tmp; then \
+ rm -f $@.tmp; \
+ else \
+ echo ' UPDATE $@'; \
+ mv -f $@.tmp $@; \
+ fi);
+endef
+
+ep_version.h: force
+ $(Q)$(N)$(call update_version.h)
+
+VERSION_FILES = ep_version.h
+
+define update_dir
+ (echo $1 > $@.tmp; \
+ if [ -r $@ ] && cmp -s $@ $@.tmp; then \
+ rm -f $@.tmp; \
+ else \
+ echo ' UPDATE $@'; \
+ mv -f $@.tmp $@; \
+ fi);
+endef
+
+## make deps
+
+all_objs := $(sort $(ALL_OBJS))
+all_deps := $(all_objs:%.o=.%.d)
+
+define check_deps
+ $(CC) -M $(CFLAGS) $< > $@;
+endef
+
+$(gui_deps): ks_version.h
+$(non_gui_deps): tc_version.h
+
+$(all_deps): .%.d: $(src)/%.c
+ $(Q)$(call check_deps)
+
+$(all_objs) : %.o : .%.d
+
+dep_includes := $(wildcard $(all_deps))
+
+ifneq ($(dep_includes),)
+ include $(dep_includes)
+endif
+
+tags: force
+ $(RM) tags
+ find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px
+
+TAGS: force
+ $(RM) TAGS
+ find . -name '*.[ch]' | xargs etags
+
+define do_install
+ $(print_install) \
+ if [ ! -d '$(DESTDIR_SQ)$2' ]; then \
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
+ fi; \
+ $(INSTALL) $1 '$(DESTDIR_SQ)$2'
+endef
+
+install_lib: all_cmd install_plugins install_python
+ $(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ))
+
+install: install_lib
+
+clean:
+ $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES).*.d
+ $(RM) tags TAGS
+
+endif # skip-makefile
+
+PHONY += force
+force:
+
+# Declare the contents of the .PHONY variable as phony. We keep that
+# information in a variable so we can use it in if_changed and friends.
+.PHONY: $(PHONY)
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
new file mode 100644
index 000000000000..998534992197
--- /dev/null
+++ b/tools/lib/traceevent/event-parse.c
@@ -0,0 +1,5065 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The parts for function graph printing was taken and modified from the
+ * Linux Kernel that were written by
+ * - Copyright (C) 2009 Frederic Weisbecker,
+ * Frederic Weisbecker gave his permission to relicense the code to
+ * the Lesser General Public License.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "event-parse.h"
+#include "event-utils.h"
+
+static const char *input_buf;
+static unsigned long long input_buf_ptr;
+static unsigned long long input_buf_siz;
+
+static int is_flag_field;
+static int is_symbolic_field;
+
+static int show_warning = 1;
+
+#define do_warning(fmt, ...) \
+ do { \
+ if (show_warning) \
+ warning(fmt, ##__VA_ARGS__); \
+ } while (0)
+
+static void init_input_buf(const char *buf, unsigned long long size)
+{
+ input_buf = buf;
+ input_buf_siz = size;
+ input_buf_ptr = 0;
+}
+
+const char *pevent_get_input_buf(void)
+{
+ return input_buf;
+}
+
+unsigned long long pevent_get_input_buf_ptr(void)
+{
+ return input_buf_ptr;
+}
+
+struct event_handler {
+ struct event_handler *next;
+ int id;
+ const char *sys_name;
+ const char *event_name;
+ pevent_event_handler_func func;
+ void *context;
+};
+
+struct pevent_func_params {
+ struct pevent_func_params *next;
+ enum pevent_func_arg_type type;
+};
+
+struct pevent_function_handler {
+ struct pevent_function_handler *next;
+ enum pevent_func_arg_type ret_type;
+ char *name;
+ pevent_func_handler func;
+ struct pevent_func_params *params;
+ int nr_args;
+};
+
+static unsigned long long
+process_defined_func(struct trace_seq *s, void *data, int size,
+ struct event_format *event, struct print_arg *arg);
+
+static void free_func_handle(struct pevent_function_handler *func);
+
+/**
+ * pevent_buffer_init - init buffer for parsing
+ * @buf: buffer to parse
+ * @size: the size of the buffer
+ *
+ * For use with pevent_read_token(), this initializes the internal
+ * buffer that pevent_read_token() will parse.
+ */
+void pevent_buffer_init(const char *buf, unsigned long long size)
+{
+ init_input_buf(buf, size);
+}
+
+void breakpoint(void)
+{
+ static int x;
+ x++;
+}
+
+struct print_arg *alloc_arg(void)
+{
+ struct print_arg *arg;
+
+ arg = malloc_or_die(sizeof(*arg));
+ if (!arg)
+ return NULL;
+ memset(arg, 0, sizeof(*arg));
+
+ return arg;
+}
+
+struct cmdline {
+ char *comm;
+ int pid;
+};
+
+static int cmdline_cmp(const void *a, const void *b)
+{
+ const struct cmdline *ca = a;
+ const struct cmdline *cb = b;
+
+ if (ca->pid < cb->pid)
+ return -1;
+ if (ca->pid > cb->pid)
+ return 1;
+
+ return 0;
+}
+
+struct cmdline_list {
+ struct cmdline_list *next;
+ char *comm;
+ int pid;
+};
+
+static int cmdline_init(struct pevent *pevent)
+{
+ struct cmdline_list *cmdlist = pevent->cmdlist;
+ struct cmdline_list *item;
+ struct cmdline *cmdlines;
+ int i;
+
+ cmdlines = malloc_or_die(sizeof(*cmdlines) * pevent->cmdline_count);
+
+ i = 0;
+ while (cmdlist) {
+ cmdlines[i].pid = cmdlist->pid;
+ cmdlines[i].comm = cmdlist->comm;
+ i++;
+ item = cmdlist;
+ cmdlist = cmdlist->next;
+ free(item);
+ }
+
+ qsort(cmdlines, pevent->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
+
+ pevent->cmdlines = cmdlines;
+ pevent->cmdlist = NULL;
+
+ return 0;
+}
+
+static char *find_cmdline(struct pevent *pevent, int pid)
+{
+ const struct cmdline *comm;
+ struct cmdline key;
+
+ if (!pid)
+ return "<idle>";
+
+ if (!pevent->cmdlines)
+ cmdline_init(pevent);
+
+ key.pid = pid;
+
+ comm = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
+ sizeof(*pevent->cmdlines), cmdline_cmp);
+
+ if (comm)
+ return comm->comm;
+ return "<...>";
+}
+
+/**
+ * pevent_pid_is_registered - return if a pid has a cmdline registered
+ * @pevent: handle for the pevent
+ * @pid: The pid to check if it has a cmdline registered with.
+ *
+ * Returns 1 if the pid has a cmdline mapped to it
+ * 0 otherwise.
+ */
+int pevent_pid_is_registered(struct pevent *pevent, int pid)
+{
+ const struct cmdline *comm;
+ struct cmdline key;
+
+ if (!pid)
+ return 1;
+
+ if (!pevent->cmdlines)
+ cmdline_init(pevent);
+
+ key.pid = pid;
+
+ comm = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
+ sizeof(*pevent->cmdlines), cmdline_cmp);
+
+ if (comm)
+ return 1;
+ return 0;
+}
+
+/*
+ * If the command lines have been converted to an array, then
+ * we must add this pid. This is much slower than when cmdlines
+ * are added before the array is initialized.
+ */
+static int add_new_comm(struct pevent *pevent, const char *comm, int pid)
+{
+ struct cmdline *cmdlines = pevent->cmdlines;
+ const struct cmdline *cmdline;
+ struct cmdline key;
+
+ if (!pid)
+ return 0;
+
+ /* avoid duplicates */
+ key.pid = pid;
+
+ cmdline = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
+ sizeof(*pevent->cmdlines), cmdline_cmp);
+ if (cmdline) {
+ errno = EEXIST;
+ return -1;
+ }
+
+ cmdlines = realloc(cmdlines, sizeof(*cmdlines) * (pevent->cmdline_count + 1));
+ if (!cmdlines) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ cmdlines[pevent->cmdline_count].pid = pid;
+ cmdlines[pevent->cmdline_count].comm = strdup(comm);
+ if (!cmdlines[pevent->cmdline_count].comm)
+ die("malloc comm");
+
+ if (cmdlines[pevent->cmdline_count].comm)
+ pevent->cmdline_count++;
+
+ qsort(cmdlines, pevent->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
+ pevent->cmdlines = cmdlines;
+
+ return 0;
+}
+
+/**
+ * pevent_register_comm - register a pid / comm mapping
+ * @pevent: handle for the pevent
+ * @comm: the command line to register
+ * @pid: the pid to map the command line to
+ *
+ * This adds a mapping to search for command line names with
+ * a given pid. The comm is duplicated.
+ */
+int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
+{
+ struct cmdline_list *item;
+
+ if (pevent->cmdlines)
+ return add_new_comm(pevent, comm, pid);
+
+ item = malloc_or_die(sizeof(*item));
+ item->comm = strdup(comm);
+ if (!item->comm)
+ die("malloc comm");
+ item->pid = pid;
+ item->next = pevent->cmdlist;
+
+ pevent->cmdlist = item;
+ pevent->cmdline_count++;
+
+ return 0;
+}
+
+struct func_map {
+ unsigned long long addr;
+ char *func;
+ char *mod;
+};
+
+struct func_list {
+ struct func_list *next;
+ unsigned long long addr;
+ char *func;
+ char *mod;
+};
+
+static int func_cmp(const void *a, const void *b)
+{
+ const struct func_map *fa = a;
+ const struct func_map *fb = b;
+
+ if (fa->addr < fb->addr)
+ return -1;
+ if (fa->addr > fb->addr)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * We are searching for a record in between, not an exact
+ * match.
+ */
+static int func_bcmp(const void *a, const void *b)
+{
+ const struct func_map *fa = a;
+ const struct func_map *fb = b;
+
+ if ((fa->addr == fb->addr) ||
+
+ (fa->addr > fb->addr &&
+ fa->addr < (fb+1)->addr))
+ return 0;
+
+ if (fa->addr < fb->addr)
+ return -1;
+
+ return 1;
+}
+
+static int func_map_init(struct pevent *pevent)
+{
+ struct func_list *funclist;
+ struct func_list *item;
+ struct func_map *func_map;
+ int i;
+
+ func_map = malloc_or_die(sizeof(*func_map) * (pevent->func_count + 1));
+ funclist = pevent->funclist;
+
+ i = 0;
+ while (funclist) {
+ func_map[i].func = funclist->func;
+ func_map[i].addr = funclist->addr;
+ func_map[i].mod = funclist->mod;
+ i++;
+ item = funclist;
+ funclist = funclist->next;
+ free(item);
+ }
+
+ qsort(func_map, pevent->func_count, sizeof(*func_map), func_cmp);
+
+ /*
+ * Add a special record at the end.
+ */
+ func_map[pevent->func_count].func = NULL;
+ func_map[pevent->func_count].addr = 0;
+ func_map[pevent->func_count].mod = NULL;
+
+ pevent->func_map = func_map;
+ pevent->funclist = NULL;
+
+ return 0;
+}
+
+static struct func_map *
+find_func(struct pevent *pevent, unsigned long long addr)
+{
+ struct func_map *func;
+ struct func_map key;
+
+ if (!pevent->func_map)
+ func_map_init(pevent);
+
+ key.addr = addr;
+
+ func = bsearch(&key, pevent->func_map, pevent->func_count,
+ sizeof(*pevent->func_map), func_bcmp);
+
+ return func;
+}
+
+/**
+ * pevent_find_function - find a function by a given address
+ * @pevent: handle for the pevent
+ * @addr: the address to find the function with
+ *
+ * Returns a pointer to the function stored that has the given
+ * address. Note, the address does not have to be exact, it
+ * will select the function that would contain the address.
+ */
+const char *pevent_find_function(struct pevent *pevent, unsigned long long addr)
+{
+ struct func_map *map;
+
+ map = find_func(pevent, addr);
+ if (!map)
+ return NULL;
+
+ return map->func;
+}
+
+/**
+ * pevent_find_function_address - find a function address by a given address
+ * @pevent: handle for the pevent
+ * @addr: the address to find the function with
+ *
+ * Returns the address the function starts at. This can be used in
+ * conjunction with pevent_find_function to print both the function
+ * name and the function offset.
+ */
+unsigned long long
+pevent_find_function_address(struct pevent *pevent, unsigned long long addr)
+{
+ struct func_map *map;
+
+ map = find_func(pevent, addr);
+ if (!map)
+ return 0;
+
+ return map->addr;
+}
+
+/**
+ * pevent_register_function - register a function with a given address
+ * @pevent: handle for the pevent
+ * @function: the function name to register
+ * @addr: the address the function starts at
+ * @mod: the kernel module the function may be in (NULL for none)
+ *
+ * This registers a function name with an address and module.
+ * The @func passed in is duplicated.
+ */
+int pevent_register_function(struct pevent *pevent, char *func,
+ unsigned long long addr, char *mod)
+{
+ struct func_list *item;
+
+ item = malloc_or_die(sizeof(*item));
+
+ item->next = pevent->funclist;
+ item->func = strdup(func);
+ if (mod)
+ item->mod = strdup(mod);
+ else
+ item->mod = NULL;
+ item->addr = addr;
+
+ pevent->funclist = item;
+
+ pevent->func_count++;
+
+ return 0;
+}
+
+/**
+ * pevent_print_funcs - print out the stored functions
+ * @pevent: handle for the pevent
+ *
+ * This prints out the stored functions.
+ */
+void pevent_print_funcs(struct pevent *pevent)
+{
+ int i;
+
+ if (!pevent->func_map)
+ func_map_init(pevent);
+
+ for (i = 0; i < (int)pevent->func_count; i++) {
+ printf("%016llx %s",
+ pevent->func_map[i].addr,
+ pevent->func_map[i].func);
+ if (pevent->func_map[i].mod)
+ printf(" [%s]\n", pevent->func_map[i].mod);
+ else
+ printf("\n");
+ }
+}
+
+struct printk_map {
+ unsigned long long addr;
+ char *printk;
+};
+
+struct printk_list {
+ struct printk_list *next;
+ unsigned long long addr;
+ char *printk;
+};
+
+static int printk_cmp(const void *a, const void *b)
+{
+ const struct func_map *fa = a;
+ const struct func_map *fb = b;
+
+ if (fa->addr < fb->addr)
+ return -1;
+ if (fa->addr > fb->addr)
+ return 1;
+
+ return 0;
+}
+
+static void printk_map_init(struct pevent *pevent)
+{
+ struct printk_list *printklist;
+ struct printk_list *item;
+ struct printk_map *printk_map;
+ int i;
+
+ printk_map = malloc_or_die(sizeof(*printk_map) * (pevent->printk_count + 1));
+
+ printklist = pevent->printklist;
+
+ i = 0;
+ while (printklist) {
+ printk_map[i].printk = printklist->printk;
+ printk_map[i].addr = printklist->addr;
+ i++;
+ item = printklist;
+ printklist = printklist->next;
+ free(item);
+ }
+
+ qsort(printk_map, pevent->printk_count, sizeof(*printk_map), printk_cmp);
+
+ pevent->printk_map = printk_map;
+ pevent->printklist = NULL;
+}
+
+static struct printk_map *
+find_printk(struct pevent *pevent, unsigned long long addr)
+{
+ struct printk_map *printk;
+ struct printk_map key;
+
+ if (!pevent->printk_map)
+ printk_map_init(pevent);
+
+ key.addr = addr;
+
+ printk = bsearch(&key, pevent->printk_map, pevent->printk_count,
+ sizeof(*pevent->printk_map), printk_cmp);
+
+ return printk;
+}
+
+/**
+ * pevent_register_print_string - register a string by its address
+ * @pevent: handle for the pevent
+ * @fmt: the string format to register
+ * @addr: the address the string was located at
+ *
+ * This registers a string by the address it was stored in the kernel.
+ * The @fmt passed in is duplicated.
+ */
+int pevent_register_print_string(struct pevent *pevent, char *fmt,
+ unsigned long long addr)
+{
+ struct printk_list *item;
+
+ item = malloc_or_die(sizeof(*item));
+
+ item->next = pevent->printklist;
+ pevent->printklist = item;
+ item->printk = strdup(fmt);
+ item->addr = addr;
+
+ pevent->printk_count++;
+
+ return 0;
+}
+
+/**
+ * pevent_print_printk - print out the stored strings
+ * @pevent: handle for the pevent
+ *
+ * This prints the string formats that were stored.
+ */
+void pevent_print_printk(struct pevent *pevent)
+{
+ int i;
+
+ if (!pevent->printk_map)
+ printk_map_init(pevent);
+
+ for (i = 0; i < (int)pevent->printk_count; i++) {
+ printf("%016llx %s\n",
+ pevent->printk_map[i].addr,
+ pevent->printk_map[i].printk);
+ }
+}
+
+static struct event_format *alloc_event(void)
+{
+ struct event_format *event;
+
+ event = malloc_or_die(sizeof(*event));
+ memset(event, 0, sizeof(*event));
+
+ return event;
+}
+
+static void add_event(struct pevent *pevent, struct event_format *event)
+{
+ int i;
+
+ if (!pevent->events)
+ pevent->events = malloc_or_die(sizeof(event));
+ else
+ pevent->events =
+ realloc(pevent->events, sizeof(event) *
+ (pevent->nr_events + 1));
+ if (!pevent->events)
+ die("Can not allocate events");
+
+ for (i = 0; i < pevent->nr_events; i++) {
+ if (pevent->events[i]->id > event->id)
+ break;
+ }
+ if (i < pevent->nr_events)
+ memmove(&pevent->events[i + 1],
+ &pevent->events[i],
+ sizeof(event) * (pevent->nr_events - i));
+
+ pevent->events[i] = event;
+ pevent->nr_events++;
+
+ event->pevent = pevent;
+}
+
+static int event_item_type(enum event_type type)
+{
+ switch (type) {
+ case EVENT_ITEM ... EVENT_SQUOTE:
+ return 1;
+ case EVENT_ERROR ... EVENT_DELIM:
+ default:
+ return 0;
+ }
+}
+
+static void free_flag_sym(struct print_flag_sym *fsym)
+{
+ struct print_flag_sym *next;
+
+ while (fsym) {
+ next = fsym->next;
+ free(fsym->value);
+ free(fsym->str);
+ free(fsym);
+ fsym = next;
+ }
+}
+
+static void free_arg(struct print_arg *arg)
+{
+ struct print_arg *farg;
+
+ if (!arg)
+ return;
+
+ switch (arg->type) {
+ case PRINT_ATOM:
+ free(arg->atom.atom);
+ break;
+ case PRINT_FIELD:
+ free(arg->field.name);
+ break;
+ case PRINT_FLAGS:
+ free_arg(arg->flags.field);
+ free(arg->flags.delim);
+ free_flag_sym(arg->flags.flags);
+ break;
+ case PRINT_SYMBOL:
+ free_arg(arg->symbol.field);
+ free_flag_sym(arg->symbol.symbols);
+ break;
+ case PRINT_TYPE:
+ free(arg->typecast.type);
+ free_arg(arg->typecast.item);
+ break;
+ case PRINT_STRING:
+ case PRINT_BSTRING:
+ free(arg->string.string);
+ break;
+ case PRINT_DYNAMIC_ARRAY:
+ free(arg->dynarray.index);
+ break;
+ case PRINT_OP:
+ free(arg->op.op);
+ free_arg(arg->op.left);
+ free_arg(arg->op.right);
+ break;
+ case PRINT_FUNC:
+ while (arg->func.args) {
+ farg = arg->func.args;
+ arg->func.args = farg->next;
+ free_arg(farg);
+ }
+ break;
+
+ case PRINT_NULL:
+ default:
+ break;
+ }
+
+ free(arg);
+}
+
+static enum event_type get_type(int ch)
+{
+ if (ch == '\n')
+ return EVENT_NEWLINE;
+ if (isspace(ch))
+ return EVENT_SPACE;
+ if (isalnum(ch) || ch == '_')
+ return EVENT_ITEM;
+ if (ch == '\'')
+ return EVENT_SQUOTE;
+ if (ch == '"')
+ return EVENT_DQUOTE;
+ if (!isprint(ch))
+ return EVENT_NONE;
+ if (ch == '(' || ch == ')' || ch == ',')
+ return EVENT_DELIM;
+
+ return EVENT_OP;
+}
+
+static int __read_char(void)
+{
+ if (input_buf_ptr >= input_buf_siz)
+ return -1;
+
+ return input_buf[input_buf_ptr++];
+}
+
+static int __peek_char(void)
+{
+ if (input_buf_ptr >= input_buf_siz)
+ return -1;
+
+ return input_buf[input_buf_ptr];
+}
+
+/**
+ * pevent_peek_char - peek at the next character that will be read
+ *
+ * Returns the next character read, or -1 if end of buffer.
+ */
+int pevent_peek_char(void)
+{
+ return __peek_char();
+}
+
+static enum event_type force_token(const char *str, char **tok);
+
+static enum event_type __read_token(char **tok)
+{
+ char buf[BUFSIZ];
+ int ch, last_ch, quote_ch, next_ch;
+ int i = 0;
+ int tok_size = 0;
+ enum event_type type;
+
+ *tok = NULL;
+
+
+ ch = __read_char();
+ if (ch < 0)
+ return EVENT_NONE;
+
+ type = get_type(ch);
+ if (type == EVENT_NONE)
+ return type;
+
+ buf[i++] = ch;
+
+ switch (type) {
+ case EVENT_NEWLINE:
+ case EVENT_DELIM:
+ *tok = malloc_or_die(2);
+ (*tok)[0] = ch;
+ (*tok)[1] = 0;
+ return type;
+
+ case EVENT_OP:
+ switch (ch) {
+ case '-':
+ next_ch = __peek_char();
+ if (next_ch == '>') {
+ buf[i++] = __read_char();
+ break;
+ }
+ /* fall through */
+ case '+':
+ case '|':
+ case '&':
+ case '>':
+ case '<':
+ last_ch = ch;
+ ch = __peek_char();
+ if (ch != last_ch)
+ goto test_equal;
+ buf[i++] = __read_char();
+ switch (last_ch) {
+ case '>':
+ case '<':
+ goto test_equal;
+ default:
+ break;
+ }
+ break;
+ case '!':
+ case '=':
+ goto test_equal;
+ default: /* what should we do instead? */
+ break;
+ }
+ buf[i] = 0;
+ *tok = strdup(buf);
+ return type;
+
+ test_equal:
+ ch = __peek_char();
+ if (ch == '=')
+ buf[i++] = __read_char();
+ goto out;
+
+ case EVENT_DQUOTE:
+ case EVENT_SQUOTE:
+ /* don't keep quotes */
+ i--;
+ quote_ch = ch;
+ last_ch = 0;
+ concat:
+ do {
+ if (i == (BUFSIZ - 1)) {
+ buf[i] = 0;
+ if (*tok) {
+ *tok = realloc(*tok, tok_size + BUFSIZ);
+ if (!*tok)
+ return EVENT_NONE;
+ strcat(*tok, buf);
+ } else
+ *tok = strdup(buf);
+
+ if (!*tok)
+ return EVENT_NONE;
+ tok_size += BUFSIZ;
+ i = 0;
+ }
+ last_ch = ch;
+ ch = __read_char();
+ buf[i++] = ch;
+ /* the '\' '\' will cancel itself */
+ if (ch == '\\' && last_ch == '\\')
+ last_ch = 0;
+ } while (ch != quote_ch || last_ch == '\\');
+ /* remove the last quote */
+ i--;
+
+ /*
+ * For strings (double quotes) check the next token.
+ * If it is another string, concatinate the two.
+ */
+ if (type == EVENT_DQUOTE) {
+ unsigned long long save_input_buf_ptr = input_buf_ptr;
+
+ do {
+ ch = __read_char();
+ } while (isspace(ch));
+ if (ch == '"')
+ goto concat;
+ input_buf_ptr = save_input_buf_ptr;
+ }
+
+ goto out;
+
+ case EVENT_ERROR ... EVENT_SPACE:
+ case EVENT_ITEM:
+ default:
+ break;
+ }
+
+ while (get_type(__peek_char()) == type) {
+ if (i == (BUFSIZ - 1)) {
+ buf[i] = 0;
+ if (*tok) {
+ *tok = realloc(*tok, tok_size + BUFSIZ);
+ if (!*tok)
+ return EVENT_NONE;
+ strcat(*tok, buf);
+ } else
+ *tok = strdup(buf);
+
+ if (!*tok)
+ return EVENT_NONE;
+ tok_size += BUFSIZ;
+ i = 0;
+ }
+ ch = __read_char();
+ buf[i++] = ch;
+ }
+
+ out:
+ buf[i] = 0;
+ if (*tok) {
+ *tok = realloc(*tok, tok_size + i);
+ if (!*tok)
+ return EVENT_NONE;
+ strcat(*tok, buf);
+ } else
+ *tok = strdup(buf);
+ if (!*tok)
+ return EVENT_NONE;
+
+ if (type == EVENT_ITEM) {
+ /*
+ * Older versions of the kernel has a bug that
+ * creates invalid symbols and will break the mac80211
+ * parsing. This is a work around to that bug.
+ *
+ * See Linux kernel commit:
+ * 811cb50baf63461ce0bdb234927046131fc7fa8b
+ */
+ if (strcmp(*tok, "LOCAL_PR_FMT") == 0) {
+ free(*tok);
+ *tok = NULL;
+ return force_token("\"\%s\" ", tok);
+ } else if (strcmp(*tok, "STA_PR_FMT") == 0) {
+ free(*tok);
+ *tok = NULL;
+ return force_token("\" sta:%pM\" ", tok);
+ } else if (strcmp(*tok, "VIF_PR_FMT") == 0) {
+ free(*tok);
+ *tok = NULL;
+ return force_token("\" vif:%p(%d)\" ", tok);
+ }
+ }
+
+ return type;
+}
+
+static enum event_type force_token(const char *str, char **tok)
+{
+ const char *save_input_buf;
+ unsigned long long save_input_buf_ptr;
+ unsigned long long save_input_buf_siz;
+ enum event_type type;
+
+ /* save off the current input pointers */
+ save_input_buf = input_buf;
+ save_input_buf_ptr = input_buf_ptr;
+ save_input_buf_siz = input_buf_siz;
+
+ init_input_buf(str, strlen(str));
+
+ type = __read_token(tok);
+
+ /* reset back to original token */
+ input_buf = save_input_buf;
+ input_buf_ptr = save_input_buf_ptr;
+ input_buf_siz = save_input_buf_siz;
+
+ return type;
+}
+
+static void free_token(char *tok)
+{
+ if (tok)
+ free(tok);
+}
+
+static enum event_type read_token(char **tok)
+{
+ enum event_type type;
+
+ for (;;) {
+ type = __read_token(tok);
+ if (type != EVENT_SPACE)
+ return type;
+
+ free_token(*tok);
+ }
+
+ /* not reached */
+ *tok = NULL;
+ return EVENT_NONE;
+}
+
+/**
+ * pevent_read_token - access to utilites to use the pevent parser
+ * @tok: The token to return
+ *
+ * This will parse tokens from the string given by
+ * pevent_init_data().
+ *
+ * Returns the token type.
+ */
+enum event_type pevent_read_token(char **tok)
+{
+ return read_token(tok);
+}
+
+/**
+ * pevent_free_token - free a token returned by pevent_read_token
+ * @token: the token to free
+ */
+void pevent_free_token(char *token)
+{
+ free_token(token);
+}
+
+/* no newline */
+static enum event_type read_token_item(char **tok)
+{
+ enum event_type type;
+
+ for (;;) {
+ type = __read_token(tok);
+ if (type != EVENT_SPACE && type != EVENT_NEWLINE)
+ return type;
+ free_token(*tok);
+ *tok = NULL;
+ }
+
+ /* not reached */
+ *tok = NULL;
+ return EVENT_NONE;
+}
+
+static int test_type(enum event_type type, enum event_type expect)
+{
+ if (type != expect) {
+ do_warning("Error: expected type %d but read %d",
+ expect, type);
+ return -1;
+ }
+ return 0;
+}
+
+static int test_type_token(enum event_type type, const char *token,
+ enum event_type expect, const char *expect_tok)
+{
+ if (type != expect) {
+ do_warning("Error: expected type %d but read %d",
+ expect, type);
+ return -1;
+ }
+
+ if (strcmp(token, expect_tok) != 0) {
+ do_warning("Error: expected '%s' but read '%s'",
+ expect_tok, token);
+ return -1;
+ }
+ return 0;
+}
+
+static int __read_expect_type(enum event_type expect, char **tok, int newline_ok)
+{
+ enum event_type type;
+
+ if (newline_ok)
+ type = read_token(tok);
+ else
+ type = read_token_item(tok);
+ return test_type(type, expect);
+}
+
+static int read_expect_type(enum event_type expect, char **tok)
+{
+ return __read_expect_type(expect, tok, 1);
+}
+
+static int __read_expected(enum event_type expect, const char *str,
+ int newline_ok)
+{
+ enum event_type type;
+ char *token;
+ int ret;
+
+ if (newline_ok)
+ type = read_token(&token);
+ else
+ type = read_token_item(&token);
+
+ ret = test_type_token(type, token, expect, str);
+
+ free_token(token);
+
+ return ret;
+}
+
+static int read_expected(enum event_type expect, const char *str)
+{
+ return __read_expected(expect, str, 1);
+}
+
+static int read_expected_item(enum event_type expect, const char *str)
+{
+ return __read_expected(expect, str, 0);
+}
+
+static char *event_read_name(void)
+{
+ char *token;
+
+ if (read_expected(EVENT_ITEM, "name") < 0)
+ return NULL;
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ return NULL;
+
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+
+ return token;
+
+ fail:
+ free_token(token);
+ return NULL;
+}
+
+static int event_read_id(void)
+{
+ char *token;
+ int id;
+
+ if (read_expected_item(EVENT_ITEM, "ID") < 0)
+ return -1;
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ return -1;
+
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+
+ id = strtoul(token, NULL, 0);
+ free_token(token);
+ return id;
+
+ fail:
+ free_token(token);
+ return -1;
+}
+
+static int field_is_string(struct format_field *field)
+{
+ if ((field->flags & FIELD_IS_ARRAY) &&
+ (strstr(field->type, "char") || strstr(field->type, "u8") ||
+ strstr(field->type, "s8")))
+ return 1;
+
+ return 0;
+}
+
+static int field_is_dynamic(struct format_field *field)
+{
+ if (strncmp(field->type, "__data_loc", 10) == 0)
+ return 1;
+
+ return 0;
+}
+
+static int field_is_long(struct format_field *field)
+{
+ /* includes long long */
+ if (strstr(field->type, "long"))
+ return 1;
+
+ return 0;
+}
+
+static int event_read_fields(struct event_format *event, struct format_field **fields)
+{
+ struct format_field *field = NULL;
+ enum event_type type;
+ char *token;
+ char *last_token;
+ int count = 0;
+
+ do {
+ type = read_token(&token);
+ if (type == EVENT_NEWLINE) {
+ free_token(token);
+ return count;
+ }
+
+ count++;
+
+ if (test_type_token(type, token, EVENT_ITEM, "field"))
+ goto fail;
+ free_token(token);
+
+ type = read_token(&token);
+ /*
+ * The ftrace fields may still use the "special" name.
+ * Just ignore it.
+ */
+ if (event->flags & EVENT_FL_ISFTRACE &&
+ type == EVENT_ITEM && strcmp(token, "special") == 0) {
+ free_token(token);
+ type = read_token(&token);
+ }
+
+ if (test_type_token(type, token, EVENT_OP, ":") < 0)
+ goto fail;
+
+ free_token(token);
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+
+ last_token = token;
+
+ field = malloc_or_die(sizeof(*field));
+ memset(field, 0, sizeof(*field));
+ field->event = event;
+
+ /* read the rest of the type */
+ for (;;) {
+ type = read_token(&token);
+ if (type == EVENT_ITEM ||
+ (type == EVENT_OP && strcmp(token, "*") == 0) ||
+ /*
+ * Some of the ftrace fields are broken and have
+ * an illegal "." in them.
+ */
+ (event->flags & EVENT_FL_ISFTRACE &&
+ type == EVENT_OP && strcmp(token, ".") == 0)) {
+
+ if (strcmp(token, "*") == 0)
+ field->flags |= FIELD_IS_POINTER;
+
+ if (field->type) {
+ field->type = realloc(field->type,
+ strlen(field->type) +
+ strlen(last_token) + 2);
+ strcat(field->type, " ");
+ strcat(field->type, last_token);
+ free(last_token);
+ } else
+ field->type = last_token;
+ last_token = token;
+ continue;
+ }
+
+ break;
+ }
+
+ if (!field->type) {
+ die("no type found");
+ goto fail;
+ }
+ field->name = last_token;
+
+ if (test_type(type, EVENT_OP))
+ goto fail;
+
+ if (strcmp(token, "[") == 0) {
+ enum event_type last_type = type;
+ char *brackets = token;
+ int len;
+
+ field->flags |= FIELD_IS_ARRAY;
+
+ type = read_token(&token);
+
+ if (type == EVENT_ITEM)
+ field->arraylen = strtoul(token, NULL, 0);
+ else
+ field->arraylen = 0;
+
+ while (strcmp(token, "]") != 0) {
+ if (last_type == EVENT_ITEM &&
+ type == EVENT_ITEM)
+ len = 2;
+ else
+ len = 1;
+ last_type = type;
+
+ brackets = realloc(brackets,
+ strlen(brackets) +
+ strlen(token) + len);
+ if (len == 2)
+ strcat(brackets, " ");
+ strcat(brackets, token);
+ /* We only care about the last token */
+ field->arraylen = strtoul(token, NULL, 0);
+ free_token(token);
+ type = read_token(&token);
+ if (type == EVENT_NONE) {
+ die("failed to find token");
+ goto fail;
+ }
+ }
+
+ free_token(token);
+
+ brackets = realloc(brackets, strlen(brackets) + 2);
+ strcat(brackets, "]");
+
+ /* add brackets to type */
+
+ type = read_token(&token);
+ /*
+ * If the next token is not an OP, then it is of
+ * the format: type [] item;
+ */
+ if (type == EVENT_ITEM) {
+ field->type = realloc(field->type,
+ strlen(field->type) +
+ strlen(field->name) +
+ strlen(brackets) + 2);
+ strcat(field->type, " ");
+ strcat(field->type, field->name);
+ free_token(field->name);
+ strcat(field->type, brackets);
+ field->name = token;
+ type = read_token(&token);
+ } else {
+ field->type = realloc(field->type,
+ strlen(field->type) +
+ strlen(brackets) + 1);
+ strcat(field->type, brackets);
+ }
+ free(brackets);
+ }
+
+ if (field_is_string(field))
+ field->flags |= FIELD_IS_STRING;
+ if (field_is_dynamic(field))
+ field->flags |= FIELD_IS_DYNAMIC;
+ if (field_is_long(field))
+ field->flags |= FIELD_IS_LONG;
+
+ if (test_type_token(type, token, EVENT_OP, ";"))
+ goto fail;
+ free_token(token);
+
+ if (read_expected(EVENT_ITEM, "offset") < 0)
+ goto fail_expect;
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ goto fail_expect;
+
+ if (read_expect_type(EVENT_ITEM, &token))
+ goto fail;
+ field->offset = strtoul(token, NULL, 0);
+ free_token(token);
+
+ if (read_expected(EVENT_OP, ";") < 0)
+ goto fail_expect;
+
+ if (read_expected(EVENT_ITEM, "size") < 0)
+ goto fail_expect;
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ goto fail_expect;
+
+ if (read_expect_type(EVENT_ITEM, &token))
+ goto fail;
+ field->size = strtoul(token, NULL, 0);
+ free_token(token);
+
+ if (read_expected(EVENT_OP, ";") < 0)
+ goto fail_expect;
+
+ type = read_token(&token);
+ if (type != EVENT_NEWLINE) {
+ /* newer versions of the kernel have a "signed" type */
+ if (test_type_token(type, token, EVENT_ITEM, "signed"))
+ goto fail;
+
+ free_token(token);
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ goto fail_expect;
+
+ if (read_expect_type(EVENT_ITEM, &token))
+ goto fail;
+
+ /* add signed type */
+
+ free_token(token);
+ if (read_expected(EVENT_OP, ";") < 0)
+ goto fail_expect;
+
+ if (read_expect_type(EVENT_NEWLINE, &token))
+ goto fail;
+ }
+
+ free_token(token);
+
+ if (field->flags & FIELD_IS_ARRAY) {
+ if (field->arraylen)
+ field->elementsize = field->size / field->arraylen;
+ else if (field->flags & FIELD_IS_STRING)
+ field->elementsize = 1;
+ else
+ field->elementsize = event->pevent->long_size;
+ } else
+ field->elementsize = field->size;
+
+ *fields = field;
+ fields = &field->next;
+
+ } while (1);
+
+ return 0;
+
+fail:
+ free_token(token);
+fail_expect:
+ if (field)
+ free(field);
+ return -1;
+}
+
+static int event_read_format(struct event_format *event)
+{
+ char *token;
+ int ret;
+
+ if (read_expected_item(EVENT_ITEM, "format") < 0)
+ return -1;
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ return -1;
+
+ if (read_expect_type(EVENT_NEWLINE, &token))
+ goto fail;
+ free_token(token);
+
+ ret = event_read_fields(event, &event->format.common_fields);
+ if (ret < 0)
+ return ret;
+ event->format.nr_common = ret;
+
+ ret = event_read_fields(event, &event->format.fields);
+ if (ret < 0)
+ return ret;
+ event->format.nr_fields = ret;
+
+ return 0;
+
+ fail:
+ free_token(token);
+ return -1;
+}
+
+static enum event_type
+process_arg_token(struct event_format *event, struct print_arg *arg,
+ char **tok, enum event_type type);
+
+static enum event_type
+process_arg(struct event_format *event, struct print_arg *arg, char **tok)
+{
+ enum event_type type;
+ char *token;
+
+ type = read_token(&token);
+ *tok = token;
+
+ return process_arg_token(event, arg, tok, type);
+}
+
+static enum event_type
+process_op(struct event_format *event, struct print_arg *arg, char **tok);
+
+static enum event_type
+process_cond(struct event_format *event, struct print_arg *top, char **tok)
+{
+ struct print_arg *arg, *left, *right;
+ enum event_type type;
+ char *token = NULL;
+
+ arg = alloc_arg();
+ left = alloc_arg();
+ right = alloc_arg();
+
+ arg->type = PRINT_OP;
+ arg->op.left = left;
+ arg->op.right = right;
+
+ *tok = NULL;
+ type = process_arg(event, left, &token);
+
+ again:
+ /* Handle other operations in the arguments */
+ if (type == EVENT_OP && strcmp(token, ":") != 0) {
+ type = process_op(event, left, &token);
+ goto again;
+ }
+
+ if (test_type_token(type, token, EVENT_OP, ":"))
+ goto out_free;
+
+ arg->op.op = token;
+
+ type = process_arg(event, right, &token);
+
+ top->op.right = arg;
+
+ *tok = token;
+ return type;
+
+out_free:
+ /* Top may point to itself */
+ top->op.right = NULL;
+ free_token(token);
+ free_arg(arg);
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_array(struct event_format *event, struct print_arg *top, char **tok)
+{
+ struct print_arg *arg;
+ enum event_type type;
+ char *token = NULL;
+
+ arg = alloc_arg();
+
+ *tok = NULL;
+ type = process_arg(event, arg, &token);
+ if (test_type_token(type, token, EVENT_OP, "]"))
+ goto out_free;
+
+ top->op.right = arg;
+
+ free_token(token);
+ type = read_token_item(&token);
+ *tok = token;
+
+ return type;
+
+out_free:
+ free_token(*tok);
+ *tok = NULL;
+ free_arg(arg);
+ return EVENT_ERROR;
+}
+
+static int get_op_prio(char *op)
+{
+ if (!op[1]) {
+ switch (op[0]) {
+ case '~':
+ case '!':
+ return 4;
+ case '*':
+ case '/':
+ case '%':
+ return 6;
+ case '+':
+ case '-':
+ return 7;
+ /* '>>' and '<<' are 8 */
+ case '<':
+ case '>':
+ return 9;
+ /* '==' and '!=' are 10 */
+ case '&':
+ return 11;
+ case '^':
+ return 12;
+ case '|':
+ return 13;
+ case '?':
+ return 16;
+ default:
+ do_warning("unknown op '%c'", op[0]);
+ return -1;
+ }
+ } else {
+ if (strcmp(op, "++") == 0 ||
+ strcmp(op, "--") == 0) {
+ return 3;
+ } else if (strcmp(op, ">>") == 0 ||
+ strcmp(op, "<<") == 0) {
+ return 8;
+ } else if (strcmp(op, ">=") == 0 ||
+ strcmp(op, "<=") == 0) {
+ return 9;
+ } else if (strcmp(op, "==") == 0 ||
+ strcmp(op, "!=") == 0) {
+ return 10;
+ } else if (strcmp(op, "&&") == 0) {
+ return 14;
+ } else if (strcmp(op, "||") == 0) {
+ return 15;
+ } else {
+ do_warning("unknown op '%s'", op);
+ return -1;
+ }
+ }
+}
+
+static int set_op_prio(struct print_arg *arg)
+{
+
+ /* single ops are the greatest */
+ if (!arg->op.left || arg->op.left->type == PRINT_NULL)
+ arg->op.prio = 0;
+ else
+ arg->op.prio = get_op_prio(arg->op.op);
+
+ return arg->op.prio;
+}
+
+/* Note, *tok does not get freed, but will most likely be saved */
+static enum event_type
+process_op(struct event_format *event, struct print_arg *arg, char **tok)
+{
+ struct print_arg *left, *right = NULL;
+ enum event_type type;
+ char *token;
+
+ /* the op is passed in via tok */
+ token = *tok;
+
+ if (arg->type == PRINT_OP && !arg->op.left) {
+ /* handle single op */
+ if (token[1]) {
+ die("bad op token %s", token);
+ goto out_free;
+ }
+ switch (token[0]) {
+ case '~':
+ case '!':
+ case '+':
+ case '-':
+ break;
+ default:
+ do_warning("bad op token %s", token);
+ goto out_free;
+
+ }
+
+ /* make an empty left */
+ left = alloc_arg();
+ left->type = PRINT_NULL;
+ arg->op.left = left;
+
+ right = alloc_arg();
+ arg->op.right = right;
+
+ /* do not free the token, it belongs to an op */
+ *tok = NULL;
+ type = process_arg(event, right, tok);
+
+ } else if (strcmp(token, "?") == 0) {
+
+ left = alloc_arg();
+ /* copy the top arg to the left */
+ *left = *arg;
+
+ arg->type = PRINT_OP;
+ arg->op.op = token;
+ arg->op.left = left;
+ arg->op.prio = 0;
+
+ type = process_cond(event, arg, tok);
+
+ } else if (strcmp(token, ">>") == 0 ||
+ strcmp(token, "<<") == 0 ||
+ strcmp(token, "&") == 0 ||
+ strcmp(token, "|") == 0 ||
+ strcmp(token, "&&") == 0 ||
+ strcmp(token, "||") == 0 ||
+ strcmp(token, "-") == 0 ||
+ strcmp(token, "+") == 0 ||
+ strcmp(token, "*") == 0 ||
+ strcmp(token, "^") == 0 ||
+ strcmp(token, "/") == 0 ||
+ strcmp(token, "<") == 0 ||
+ strcmp(token, ">") == 0 ||
+ strcmp(token, "==") == 0 ||
+ strcmp(token, "!=") == 0) {
+
+ left = alloc_arg();
+
+ /* copy the top arg to the left */
+ *left = *arg;
+
+ arg->type = PRINT_OP;
+ arg->op.op = token;
+ arg->op.left = left;
+
+ if (set_op_prio(arg) == -1) {
+ event->flags |= EVENT_FL_FAILED;
+ goto out_free;
+ }
+
+ type = read_token_item(&token);
+ *tok = token;
+
+ /* could just be a type pointer */
+ if ((strcmp(arg->op.op, "*") == 0) &&
+ type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
+ if (left->type != PRINT_ATOM)
+ die("bad pointer type");
+ left->atom.atom = realloc(left->atom.atom,
+ strlen(left->atom.atom) + 3);
+ strcat(left->atom.atom, " *");
+ free(arg->op.op);
+ *arg = *left;
+ free(left);
+
+ return type;
+ }
+
+ right = alloc_arg();
+ type = process_arg_token(event, right, tok, type);
+ arg->op.right = right;
+
+ } else if (strcmp(token, "[") == 0) {
+
+ left = alloc_arg();
+ *left = *arg;
+
+ arg->type = PRINT_OP;
+ arg->op.op = token;
+ arg->op.left = left;
+
+ arg->op.prio = 0;
+
+ type = process_array(event, arg, tok);
+
+ } else {
+ do_warning("unknown op '%s'", token);
+ event->flags |= EVENT_FL_FAILED;
+ /* the arg is now the left side */
+ goto out_free;
+ }
+
+ if (type == EVENT_OP && strcmp(*tok, ":") != 0) {
+ int prio;
+
+ /* higher prios need to be closer to the root */
+ prio = get_op_prio(*tok);
+
+ if (prio > arg->op.prio)
+ return process_op(event, arg, tok);
+
+ return process_op(event, right, tok);
+ }
+
+ return type;
+
+ out_free:
+ free_token(token);
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_entry(struct event_format *event __unused, struct print_arg *arg,
+ char **tok)
+{
+ enum event_type type;
+ char *field;
+ char *token;
+
+ if (read_expected(EVENT_OP, "->") < 0)
+ goto out_err;
+
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto out_free;
+ field = token;
+
+ arg->type = PRINT_FIELD;
+ arg->field.name = field;
+
+ if (is_flag_field) {
+ arg->field.field = pevent_find_any_field(event, arg->field.name);
+ arg->field.field->flags |= FIELD_IS_FLAG;
+ is_flag_field = 0;
+ } else if (is_symbolic_field) {
+ arg->field.field = pevent_find_any_field(event, arg->field.name);
+ arg->field.field->flags |= FIELD_IS_SYMBOLIC;
+ is_symbolic_field = 0;
+ }
+
+ type = read_token(&token);
+ *tok = token;
+
+ return type;
+
+ out_free:
+ free_token(token);
+ out_err:
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+static char *arg_eval (struct print_arg *arg);
+
+static unsigned long long
+eval_type_str(unsigned long long val, const char *type, int pointer)
+{
+ int sign = 0;
+ char *ref;
+ int len;
+
+ len = strlen(type);
+
+ if (pointer) {
+
+ if (type[len-1] != '*') {
+ do_warning("pointer expected with non pointer type");
+ return val;
+ }
+
+ ref = malloc_or_die(len);
+ memcpy(ref, type, len);
+
+ /* chop off the " *" */
+ ref[len - 2] = 0;
+
+ val = eval_type_str(val, ref, 0);
+ free(ref);
+ return val;
+ }
+
+ /* check if this is a pointer */
+ if (type[len - 1] == '*')
+ return val;
+
+ /* Try to figure out the arg size*/
+ if (strncmp(type, "struct", 6) == 0)
+ /* all bets off */
+ return val;
+
+ if (strcmp(type, "u8") == 0)
+ return val & 0xff;
+
+ if (strcmp(type, "u16") == 0)
+ return val & 0xffff;
+
+ if (strcmp(type, "u32") == 0)
+ return val & 0xffffffff;
+
+ if (strcmp(type, "u64") == 0 ||
+ strcmp(type, "s64"))
+ return val;
+
+ if (strcmp(type, "s8") == 0)
+ return (unsigned long long)(char)val & 0xff;
+
+ if (strcmp(type, "s16") == 0)
+ return (unsigned long long)(short)val & 0xffff;
+
+ if (strcmp(type, "s32") == 0)
+ return (unsigned long long)(int)val & 0xffffffff;
+
+ if (strncmp(type, "unsigned ", 9) == 0) {
+ sign = 0;
+ type += 9;
+ }
+
+ if (strcmp(type, "char") == 0) {
+ if (sign)
+ return (unsigned long long)(char)val & 0xff;
+ else
+ return val & 0xff;
+ }
+
+ if (strcmp(type, "short") == 0) {
+ if (sign)
+ return (unsigned long long)(short)val & 0xffff;
+ else
+ return val & 0xffff;
+ }
+
+ if (strcmp(type, "int") == 0) {
+ if (sign)
+ return (unsigned long long)(int)val & 0xffffffff;
+ else
+ return val & 0xffffffff;
+ }
+
+ return val;
+}
+
+/*
+ * Try to figure out the type.
+ */
+static unsigned long long
+eval_type(unsigned long long val, struct print_arg *arg, int pointer)
+{
+ if (arg->type != PRINT_TYPE)
+ die("expected type argument");
+
+ return eval_type_str(val, arg->typecast.type, pointer);
+}
+
+static int arg_num_eval(struct print_arg *arg, long long *val)
+{
+ long long left, right;
+ int ret = 1;
+
+ switch (arg->type) {
+ case PRINT_ATOM:
+ *val = strtoll(arg->atom.atom, NULL, 0);
+ break;
+ case PRINT_TYPE:
+ ret = arg_num_eval(arg->typecast.item, val);
+ if (!ret)
+ break;
+ *val = eval_type(*val, arg, 0);
+ break;
+ case PRINT_OP:
+ switch (arg->op.op[0]) {
+ case '|':
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+ if (arg->op.op[1])
+ *val = left || right;
+ else
+ *val = left | right;
+ break;
+ case '&':
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+ if (arg->op.op[1])
+ *val = left && right;
+ else
+ *val = left & right;
+ break;
+ case '<':
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+ switch (arg->op.op[1]) {
+ case 0:
+ *val = left < right;
+ break;
+ case '<':
+ *val = left << right;
+ break;
+ case '=':
+ *val = left <= right;
+ break;
+ default:
+ do_warning("unknown op '%s'", arg->op.op);
+ ret = 0;
+ }
+ break;
+ case '>':
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+ switch (arg->op.op[1]) {
+ case 0:
+ *val = left > right;
+ break;
+ case '>':
+ *val = left >> right;
+ break;
+ case '=':
+ *val = left >= right;
+ break;
+ default:
+ do_warning("unknown op '%s'", arg->op.op);
+ ret = 0;
+ }
+ break;
+ case '=':
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+
+ if (arg->op.op[1] != '=') {
+ do_warning("unknown op '%s'", arg->op.op);
+ ret = 0;
+ } else
+ *val = left == right;
+ break;
+ case '!':
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+
+ switch (arg->op.op[1]) {
+ case '=':
+ *val = left != right;
+ break;
+ default:
+ do_warning("unknown op '%s'", arg->op.op);
+ ret = 0;
+ }
+ break;
+ case '-':
+ /* check for negative */
+ if (arg->op.left->type == PRINT_NULL)
+ left = 0;
+ else
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+ *val = left - right;
+ break;
+ case '+':
+ if (arg->op.left->type == PRINT_NULL)
+ left = 0;
+ else
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+ *val = left + right;
+ break;
+ default:
+ do_warning("unknown op '%s'", arg->op.op);
+ ret = 0;
+ }
+ break;
+
+ case PRINT_NULL:
+ case PRINT_FIELD ... PRINT_SYMBOL:
+ case PRINT_STRING:
+ case PRINT_BSTRING:
+ default:
+ do_warning("invalid eval type %d", arg->type);
+ ret = 0;
+
+ }
+ return ret;
+}
+
+static char *arg_eval (struct print_arg *arg)
+{
+ long long val;
+ static char buf[20];
+
+ switch (arg->type) {
+ case PRINT_ATOM:
+ return arg->atom.atom;
+ case PRINT_TYPE:
+ return arg_eval(arg->typecast.item);
+ case PRINT_OP:
+ if (!arg_num_eval(arg, &val))
+ break;
+ sprintf(buf, "%lld", val);
+ return buf;
+
+ case PRINT_NULL:
+ case PRINT_FIELD ... PRINT_SYMBOL:
+ case PRINT_STRING:
+ case PRINT_BSTRING:
+ default:
+ die("invalid eval type %d", arg->type);
+ break;
+ }
+
+ return NULL;
+}
+
+static enum event_type
+process_fields(struct event_format *event, struct print_flag_sym **list, char **tok)
+{
+ enum event_type type;
+ struct print_arg *arg = NULL;
+ struct print_flag_sym *field;
+ char *token = *tok;
+ char *value;
+
+ do {
+ free_token(token);
+ type = read_token_item(&token);
+ if (test_type_token(type, token, EVENT_OP, "{"))
+ break;
+
+ arg = alloc_arg();
+
+ free_token(token);
+ type = process_arg(event, arg, &token);
+ if (test_type_token(type, token, EVENT_DELIM, ","))
+ goto out_free;
+
+ field = malloc_or_die(sizeof(*field));
+ memset(field, 0, sizeof(*field));
+
+ value = arg_eval(arg);
+ if (value == NULL)
+ goto out_free;
+ field->value = strdup(value);
+
+ free_arg(arg);
+ arg = alloc_arg();
+
+ free_token(token);
+ type = process_arg(event, arg, &token);
+ if (test_type_token(type, token, EVENT_OP, "}"))
+ goto out_free;
+
+ value = arg_eval(arg);
+ if (value == NULL)
+ goto out_free;
+ field->str = strdup(value);
+ free_arg(arg);
+ arg = NULL;
+
+ *list = field;
+ list = &field->next;
+
+ free_token(token);
+ type = read_token_item(&token);
+ } while (type == EVENT_DELIM && strcmp(token, ",") == 0);
+
+ *tok = token;
+ return type;
+
+out_free:
+ free_arg(arg);
+ free_token(token);
+ *tok = NULL;
+
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_flags(struct event_format *event, struct print_arg *arg, char **tok)
+{
+ struct print_arg *field;
+ enum event_type type;
+ char *token;
+
+ memset(arg, 0, sizeof(*arg));
+ arg->type = PRINT_FLAGS;
+
+ field = alloc_arg();
+
+ type = process_arg(event, field, &token);
+
+ /* Handle operations in the first argument */
+ while (type == EVENT_OP)
+ type = process_op(event, field, &token);
+
+ if (test_type_token(type, token, EVENT_DELIM, ","))
+ goto out_free;
+ free_token(token);
+
+ arg->flags.field = field;
+
+ type = read_token_item(&token);
+ if (event_item_type(type)) {
+ arg->flags.delim = token;
+ type = read_token_item(&token);
+ }
+
+ if (test_type_token(type, token, EVENT_DELIM, ","))
+ goto out_free;
+
+ type = process_fields(event, &arg->flags.flags, &token);
+ if (test_type_token(type, token, EVENT_DELIM, ")"))
+ goto out_free;
+
+ free_token(token);
+ type = read_token_item(tok);
+ return type;
+
+ out_free:
+ free_token(token);
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
+{
+ struct print_arg *field;
+ enum event_type type;
+ char *token;
+
+ memset(arg, 0, sizeof(*arg));
+ arg->type = PRINT_SYMBOL;
+
+ field = alloc_arg();
+
+ type = process_arg(event, field, &token);
+ if (test_type_token(type, token, EVENT_DELIM, ","))
+ goto out_free;
+
+ arg->symbol.field = field;
+
+ type = process_fields(event, &arg->symbol.symbols, &token);
+ if (test_type_token(type, token, EVENT_DELIM, ")"))
+ goto out_free;
+
+ free_token(token);
+ type = read_token_item(tok);
+ return type;
+
+ out_free:
+ free_token(token);
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok)
+{
+ struct format_field *field;
+ enum event_type type;
+ char *token;
+
+ memset(arg, 0, sizeof(*arg));
+ arg->type = PRINT_DYNAMIC_ARRAY;
+
+ /*
+ * The item within the parenthesis is another field that holds
+ * the index into where the array starts.
+ */
+ type = read_token(&token);
+ *tok = token;
+ if (type != EVENT_ITEM)
+ goto out_free;
+
+ /* Find the field */
+
+ field = pevent_find_field(event, token);
+ if (!field)
+ goto out_free;
+
+ arg->dynarray.field = field;
+ arg->dynarray.index = 0;
+
+ if (read_expected(EVENT_DELIM, ")") < 0)
+ goto out_free;
+
+ free_token(token);
+ type = read_token_item(&token);
+ *tok = token;
+ if (type != EVENT_OP || strcmp(token, "[") != 0)
+ return type;
+
+ free_token(token);
+ arg = alloc_arg();
+ type = process_arg(event, arg, &token);
+ if (type == EVENT_ERROR)
+ goto out_free;
+
+ if (!test_type_token(type, token, EVENT_OP, "]"))
+ goto out_free;
+
+ free_token(token);
+ type = read_token_item(tok);
+ return type;
+
+ out_free:
+ free(arg);
+ free_token(token);
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_paren(struct event_format *event, struct print_arg *arg, char **tok)
+{
+ struct print_arg *item_arg;
+ enum event_type type;
+ char *token;
+
+ type = process_arg(event, arg, &token);
+
+ if (type == EVENT_ERROR)
+ goto out_free;
+
+ if (type == EVENT_OP)
+ type = process_op(event, arg, &token);
+
+ if (type == EVENT_ERROR)
+ goto out_free;
+
+ if (test_type_token(type, token, EVENT_DELIM, ")"))
+ goto out_free;
+
+ free_token(token);
+ type = read_token_item(&token);
+
+ /*
+ * If the next token is an item or another open paren, then
+ * this was a typecast.
+ */
+ if (event_item_type(type) ||
+ (type == EVENT_DELIM && strcmp(token, "(") == 0)) {
+
+ /* make this a typecast and contine */
+
+ /* prevous must be an atom */
+ if (arg->type != PRINT_ATOM)
+ die("previous needed to be PRINT_ATOM");
+
+ item_arg = alloc_arg();
+
+ arg->type = PRINT_TYPE;
+ arg->typecast.type = arg->atom.atom;
+ arg->typecast.item = item_arg;
+ type = process_arg_token(event, item_arg, &token, type);
+
+ }
+
+ *tok = token;
+ return type;
+
+ out_free:
+ free_token(token);
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+
+static enum event_type
+process_str(struct event_format *event __unused, struct print_arg *arg, char **tok)
+{
+ enum event_type type;
+ char *token;
+
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto out_free;
+
+ arg->type = PRINT_STRING;
+ arg->string.string = token;
+ arg->string.offset = -1;
+
+ if (read_expected(EVENT_DELIM, ")") < 0)
+ goto out_err;
+
+ type = read_token(&token);
+ *tok = token;
+
+ return type;
+
+ out_free:
+ free_token(token);
+ out_err:
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+static struct pevent_function_handler *
+find_func_handler(struct pevent *pevent, char *func_name)
+{
+ struct pevent_function_handler *func;
+
+ for (func = pevent->func_handlers; func; func = func->next) {
+ if (strcmp(func->name, func_name) == 0)
+ break;
+ }
+
+ return func;
+}
+
+static void remove_func_handler(struct pevent *pevent, char *func_name)
+{
+ struct pevent_function_handler *func;
+ struct pevent_function_handler **next;
+
+ next = &pevent->func_handlers;
+ while ((func = *next)) {
+ if (strcmp(func->name, func_name) == 0) {
+ *next = func->next;
+ free_func_handle(func);
+ break;
+ }
+ next = &func->next;
+ }
+}
+
+static enum event_type
+process_func_handler(struct event_format *event, struct pevent_function_handler *func,
+ struct print_arg *arg, char **tok)
+{
+ struct print_arg **next_arg;
+ struct print_arg *farg;
+ enum event_type type;
+ char *token;
+ char *test;
+ int i;
+
+ arg->type = PRINT_FUNC;
+ arg->func.func = func;
+
+ *tok = NULL;
+
+ next_arg = &(arg->func.args);
+ for (i = 0; i < func->nr_args; i++) {
+ farg = alloc_arg();
+ type = process_arg(event, farg, &token);
+ if (i < (func->nr_args - 1))
+ test = ",";
+ else
+ test = ")";
+
+ if (test_type_token(type, token, EVENT_DELIM, test)) {
+ free_arg(farg);
+ free_token(token);
+ return EVENT_ERROR;
+ }
+
+ *next_arg = farg;
+ next_arg = &(farg->next);
+ free_token(token);
+ }
+
+ type = read_token(&token);
+ *tok = token;
+
+ return type;
+}
+
+static enum event_type
+process_function(struct event_format *event, struct print_arg *arg,
+ char *token, char **tok)
+{
+ struct pevent_function_handler *func;
+
+ if (strcmp(token, "__print_flags") == 0) {
+ free_token(token);
+ is_flag_field = 1;
+ return process_flags(event, arg, tok);
+ }
+ if (strcmp(token, "__print_symbolic") == 0) {
+ free_token(token);
+ is_symbolic_field = 1;
+ return process_symbols(event, arg, tok);
+ }
+ if (strcmp(token, "__get_str") == 0) {
+ free_token(token);
+ return process_str(event, arg, tok);
+ }
+ if (strcmp(token, "__get_dynamic_array") == 0) {
+ free_token(token);
+ return process_dynamic_array(event, arg, tok);
+ }
+
+ func = find_func_handler(event->pevent, token);
+ if (func) {
+ free_token(token);
+ return process_func_handler(event, func, arg, tok);
+ }
+
+ do_warning("function %s not defined", token);
+ free_token(token);
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_arg_token(struct event_format *event, struct print_arg *arg,
+ char **tok, enum event_type type)
+{
+ char *token;
+ char *atom;
+
+ token = *tok;
+
+ switch (type) {
+ case EVENT_ITEM:
+ if (strcmp(token, "REC") == 0) {
+ free_token(token);
+ type = process_entry(event, arg, &token);
+ break;
+ }
+ atom = token;
+ /* test the next token */
+ type = read_token_item(&token);
+
+ /*
+ * If the next token is a parenthesis, then this
+ * is a function.
+ */
+ if (type == EVENT_DELIM && strcmp(token, "(") == 0) {
+ free_token(token);
+ token = NULL;
+ /* this will free atom. */
+ type = process_function(event, arg, atom, &token);
+ break;
+ }
+ /* atoms can be more than one token long */
+ while (type == EVENT_ITEM) {
+ atom = realloc(atom, strlen(atom) + strlen(token) + 2);
+ strcat(atom, " ");
+ strcat(atom, token);
+ free_token(token);
+ type = read_token_item(&token);
+ }
+
+ arg->type = PRINT_ATOM;
+ arg->atom.atom = atom;
+ break;
+
+ case EVENT_DQUOTE:
+ case EVENT_SQUOTE:
+ arg->type = PRINT_ATOM;
+ arg->atom.atom = token;
+ type = read_token_item(&token);
+ break;
+ case EVENT_DELIM:
+ if (strcmp(token, "(") == 0) {
+ free_token(token);
+ type = process_paren(event, arg, &token);
+ break;
+ }
+ case EVENT_OP:
+ /* handle single ops */
+ arg->type = PRINT_OP;
+ arg->op.op = token;
+ arg->op.left = NULL;
+ type = process_op(event, arg, &token);
+
+ /* On error, the op is freed */
+ if (type == EVENT_ERROR)
+ arg->op.op = NULL;
+
+ /* return error type if errored */
+ break;
+
+ case EVENT_ERROR ... EVENT_NEWLINE:
+ default:
+ die("unexpected type %d", type);
+ }
+ *tok = token;
+
+ return type;
+}
+
+static int event_read_print_args(struct event_format *event, struct print_arg **list)
+{
+ enum event_type type = EVENT_ERROR;
+ struct print_arg *arg;
+ char *token;
+ int args = 0;
+
+ do {
+ if (type == EVENT_NEWLINE) {
+ type = read_token_item(&token);
+ continue;
+ }
+
+ arg = alloc_arg();
+
+ type = process_arg(event, arg, &token);
+
+ if (type == EVENT_ERROR) {
+ free_token(token);
+ free_arg(arg);
+ return -1;
+ }
+
+ *list = arg;
+ args++;
+
+ if (type == EVENT_OP) {
+ type = process_op(event, arg, &token);
+ free_token(token);
+ if (type == EVENT_ERROR) {
+ *list = NULL;
+ free_arg(arg);
+ return -1;
+ }
+ list = &arg->next;
+ continue;
+ }
+
+ if (type == EVENT_DELIM && strcmp(token, ",") == 0) {
+ free_token(token);
+ *list = arg;
+ list = &arg->next;
+ continue;
+ }
+ break;
+ } while (type != EVENT_NONE);
+
+ if (type != EVENT_NONE && type != EVENT_ERROR)
+ free_token(token);
+
+ return args;
+}
+
+static int event_read_print(struct event_format *event)
+{
+ enum event_type type;
+ char *token;
+ int ret;
+
+ if (read_expected_item(EVENT_ITEM, "print") < 0)
+ return -1;
+
+ if (read_expected(EVENT_ITEM, "fmt") < 0)
+ return -1;
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ return -1;
+
+ if (read_expect_type(EVENT_DQUOTE, &token) < 0)
+ goto fail;
+
+ concat:
+ event->print_fmt.format = token;
+ event->print_fmt.args = NULL;
+
+ /* ok to have no arg */
+ type = read_token_item(&token);
+
+ if (type == EVENT_NONE)
+ return 0;
+
+ /* Handle concatenation of print lines */
+ if (type == EVENT_DQUOTE) {
+ char *cat;
+
+ cat = malloc_or_die(strlen(event->print_fmt.format) +
+ strlen(token) + 1);
+ strcpy(cat, event->print_fmt.format);
+ strcat(cat, token);
+ free_token(token);
+ free_token(event->print_fmt.format);
+ event->print_fmt.format = NULL;
+ token = cat;
+ goto concat;
+ }
+
+ if (test_type_token(type, token, EVENT_DELIM, ","))
+ goto fail;
+
+ free_token(token);
+
+ ret = event_read_print_args(event, &event->print_fmt.args);
+ if (ret < 0)
+ return -1;
+
+ return ret;
+
+ fail:
+ free_token(token);
+ return -1;
+}
+
+/**
+ * pevent_find_common_field - return a common field by event
+ * @event: handle for the event
+ * @name: the name of the common field to return
+ *
+ * Returns a common field from the event by the given @name.
+ * This only searchs the common fields and not all field.
+ */
+struct format_field *
+pevent_find_common_field(struct event_format *event, const char *name)
+{
+ struct format_field *format;
+
+ for (format = event->format.common_fields;
+ format; format = format->next) {
+ if (strcmp(format->name, name) == 0)
+ break;
+ }
+
+ return format;
+}
+
+/**
+ * pevent_find_field - find a non-common field
+ * @event: handle for the event
+ * @name: the name of the non-common field
+ *
+ * Returns a non-common field by the given @name.
+ * This does not search common fields.
+ */
+struct format_field *
+pevent_find_field(struct event_format *event, const char *name)
+{
+ struct format_field *format;
+
+ for (format = event->format.fields;
+ format; format = format->next) {
+ if (strcmp(format->name, name) == 0)
+ break;
+ }
+
+ return format;
+}
+
+/**
+ * pevent_find_any_field - find any field by name
+ * @event: handle for the event
+ * @name: the name of the field
+ *
+ * Returns a field by the given @name.
+ * This searchs the common field names first, then
+ * the non-common ones if a common one was not found.
+ */
+struct format_field *
+pevent_find_any_field(struct event_format *event, const char *name)
+{
+ struct format_field *format;
+
+ format = pevent_find_common_field(event, name);
+ if (format)
+ return format;
+ return pevent_find_field(event, name);
+}
+
+/**
+ * pevent_read_number - read a number from data
+ * @pevent: handle for the pevent
+ * @ptr: the raw data
+ * @size: the size of the data that holds the number
+ *
+ * Returns the number (converted to host) from the
+ * raw data.
+ */
+unsigned long long pevent_read_number(struct pevent *pevent,
+ const void *ptr, int size)
+{
+ switch (size) {
+ case 1:
+ return *(unsigned char *)ptr;
+ case 2:
+ return data2host2(pevent, ptr);
+ case 4:
+ return data2host4(pevent, ptr);
+ case 8:
+ return data2host8(pevent, ptr);
+ default:
+ /* BUG! */
+ return 0;
+ }
+}
+
+/**
+ * pevent_read_number_field - read a number from data
+ * @field: a handle to the field
+ * @data: the raw data to read
+ * @value: the value to place the number in
+ *
+ * Reads raw data according to a field offset and size,
+ * and translates it into @value.
+ *
+ * Returns 0 on success, -1 otherwise.
+ */
+int pevent_read_number_field(struct format_field *field, const void *data,
+ unsigned long long *value)
+{
+ if (!field)
+ return -1;
+ switch (field->size) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ *value = pevent_read_number(field->event->pevent,
+ data + field->offset, field->size);
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+static int get_common_info(struct pevent *pevent,
+ const char *type, int *offset, int *size)
+{
+ struct event_format *event;
+ struct format_field *field;
+
+ /*
+ * All events should have the same common elements.
+ * Pick any event to find where the type is;
+ */
+ if (!pevent->events)
+ die("no event_list!");
+
+ event = pevent->events[0];
+ field = pevent_find_common_field(event, type);
+ if (!field)
+ die("field '%s' not found", type);
+
+ *offset = field->offset;
+ *size = field->size;
+
+ return 0;
+}
+
+static int __parse_common(struct pevent *pevent, void *data,
+ int *size, int *offset, const char *name)
+{
+ int ret;
+
+ if (!*size) {
+ ret = get_common_info(pevent, name, offset, size);
+ if (ret < 0)
+ return ret;
+ }
+ return pevent_read_number(pevent, data + *offset, *size);
+}
+
+static int trace_parse_common_type(struct pevent *pevent, void *data)
+{
+ return __parse_common(pevent, data,
+ &pevent->type_size, &pevent->type_offset,
+ "common_type");
+}
+
+static int parse_common_pid(struct pevent *pevent, void *data)
+{
+ return __parse_common(pevent, data,
+ &pevent->pid_size, &pevent->pid_offset,
+ "common_pid");
+}
+
+static int parse_common_pc(struct pevent *pevent, void *data)
+{
+ return __parse_common(pevent, data,
+ &pevent->pc_size, &pevent->pc_offset,
+ "common_preempt_count");
+}
+
+static int parse_common_flags(struct pevent *pevent, void *data)
+{
+ return __parse_common(pevent, data,
+ &pevent->flags_size, &pevent->flags_offset,
+ "common_flags");
+}
+
+static int parse_common_lock_depth(struct pevent *pevent, void *data)
+{
+ int ret;
+
+ ret = __parse_common(pevent, data,
+ &pevent->ld_size, &pevent->ld_offset,
+ "common_lock_depth");
+ if (ret < 0)
+ return -1;
+
+ return ret;
+}
+
+static int events_id_cmp(const void *a, const void *b);
+
+/**
+ * pevent_find_event - find an event by given id
+ * @pevent: a handle to the pevent
+ * @id: the id of the event
+ *
+ * Returns an event that has a given @id.
+ */
+struct event_format *pevent_find_event(struct pevent *pevent, int id)
+{
+ struct event_format **eventptr;
+ struct event_format key;
+ struct event_format *pkey = &key;
+
+ /* Check cache first */
+ if (pevent->last_event && pevent->last_event->id == id)
+ return pevent->last_event;
+
+ key.id = id;
+
+ eventptr = bsearch(&pkey, pevent->events, pevent->nr_events,
+ sizeof(*pevent->events), events_id_cmp);
+
+ if (eventptr) {
+ pevent->last_event = *eventptr;
+ return *eventptr;
+ }
+
+ return NULL;
+}
+
+/**
+ * pevent_find_event_by_name - find an event by given name
+ * @pevent: a handle to the pevent
+ * @sys: the system name to search for
+ * @name: the name of the event to search for
+ *
+ * This returns an event with a given @name and under the system
+ * @sys. If @sys is NULL the first event with @name is returned.
+ */
+struct event_format *
+pevent_find_event_by_name(struct pevent *pevent,
+ const char *sys, const char *name)
+{
+ struct event_format *event;
+ int i;
+
+ if (pevent->last_event &&
+ strcmp(pevent->last_event->name, name) == 0 &&
+ (!sys || strcmp(pevent->last_event->system, sys) == 0))
+ return pevent->last_event;
+
+ for (i = 0; i < pevent->nr_events; i++) {
+ event = pevent->events[i];
+ if (strcmp(event->name, name) == 0) {
+ if (!sys)
+ break;
+ if (strcmp(event->system, sys) == 0)
+ break;
+ }
+ }
+ if (i == pevent->nr_events)
+ event = NULL;
+
+ pevent->last_event = event;
+ return event;
+}
+
+static unsigned long long
+eval_num_arg(void *data, int size, struct event_format *event, struct print_arg *arg)
+{
+ struct pevent *pevent = event->pevent;
+ unsigned long long val = 0;
+ unsigned long long left, right;
+ struct print_arg *typearg = NULL;
+ struct print_arg *larg;
+ unsigned long offset;
+ unsigned int field_size;
+
+ switch (arg->type) {
+ case PRINT_NULL:
+ /* ?? */
+ return 0;
+ case PRINT_ATOM:
+ return strtoull(arg->atom.atom, NULL, 0);
+ case PRINT_FIELD:
+ if (!arg->field.field) {
+ arg->field.field = pevent_find_any_field(event, arg->field.name);
+ if (!arg->field.field)
+ die("field %s not found", arg->field.name);
+ }
+ /* must be a number */
+ val = pevent_read_number(pevent, data + arg->field.field->offset,
+ arg->field.field->size);
+ break;
+ case PRINT_FLAGS:
+ case PRINT_SYMBOL:
+ break;
+ case PRINT_TYPE:
+ val = eval_num_arg(data, size, event, arg->typecast.item);
+ return eval_type(val, arg, 0);
+ case PRINT_STRING:
+ case PRINT_BSTRING:
+ return 0;
+ case PRINT_FUNC: {
+ struct trace_seq s;
+ trace_seq_init(&s);
+ val = process_defined_func(&s, data, size, event, arg);
+ trace_seq_destroy(&s);
+ return val;
+ }
+ case PRINT_OP:
+ if (strcmp(arg->op.op, "[") == 0) {
+ /*
+ * Arrays are special, since we don't want
+ * to read the arg as is.
+ */
+ right = eval_num_arg(data, size, event, arg->op.right);
+
+ /* handle typecasts */
+ larg = arg->op.left;
+ while (larg->type == PRINT_TYPE) {
+ if (!typearg)
+ typearg = larg;
+ larg = larg->typecast.item;
+ }
+
+ /* Default to long size */
+ field_size = pevent->long_size;
+
+ switch (larg->type) {
+ case PRINT_DYNAMIC_ARRAY:
+ offset = pevent_read_number(pevent,
+ data + larg->dynarray.field->offset,
+ larg->dynarray.field->size);
+ if (larg->dynarray.field->elementsize)
+ field_size = larg->dynarray.field->elementsize;
+ /*
+ * The actual length of the dynamic array is stored
+ * in the top half of the field, and the offset
+ * is in the bottom half of the 32 bit field.
+ */
+ offset &= 0xffff;
+ offset += right;
+ break;
+ case PRINT_FIELD:
+ if (!larg->field.field) {
+ larg->field.field =
+ pevent_find_any_field(event, larg->field.name);
+ if (!larg->field.field)
+ die("field %s not found", larg->field.name);
+ }
+ field_size = larg->field.field->elementsize;
+ offset = larg->field.field->offset +
+ right * larg->field.field->elementsize;
+ break;
+ default:
+ goto default_op; /* oops, all bets off */
+ }
+ val = pevent_read_number(pevent,
+ data + offset, field_size);
+ if (typearg)
+ val = eval_type(val, typearg, 1);
+ break;
+ } else if (strcmp(arg->op.op, "?") == 0) {
+ left = eval_num_arg(data, size, event, arg->op.left);
+ arg = arg->op.right;
+ if (left)
+ val = eval_num_arg(data, size, event, arg->op.left);
+ else
+ val = eval_num_arg(data, size, event, arg->op.right);
+ break;
+ }
+ default_op:
+ left = eval_num_arg(data, size, event, arg->op.left);
+ right = eval_num_arg(data, size, event, arg->op.right);
+ switch (arg->op.op[0]) {
+ case '!':
+ switch (arg->op.op[1]) {
+ case 0:
+ val = !right;
+ break;
+ case '=':
+ val = left != right;
+ break;
+ default:
+ die("unknown op '%s'", arg->op.op);
+ }
+ break;
+ case '~':
+ val = ~right;
+ break;
+ case '|':
+ if (arg->op.op[1])
+ val = left || right;
+ else
+ val = left | right;
+ break;
+ case '&':
+ if (arg->op.op[1])
+ val = left && right;
+ else
+ val = left & right;
+ break;
+ case '<':
+ switch (arg->op.op[1]) {
+ case 0:
+ val = left < right;
+ break;
+ case '<':
+ val = left << right;
+ break;
+ case '=':
+ val = left <= right;
+ break;
+ default:
+ die("unknown op '%s'", arg->op.op);
+ }
+ break;
+ case '>':
+ switch (arg->op.op[1]) {
+ case 0:
+ val = left > right;
+ break;
+ case '>':
+ val = left >> right;
+ break;
+ case '=':
+ val = left >= right;
+ break;
+ default:
+ die("unknown op '%s'", arg->op.op);
+ }
+ break;
+ case '=':
+ if (arg->op.op[1] != '=')
+ die("unknown op '%s'", arg->op.op);
+ val = left == right;
+ break;
+ case '-':
+ val = left - right;
+ break;
+ case '+':
+ val = left + right;
+ break;
+ case '/':
+ val = left / right;
+ break;
+ case '*':
+ val = left * right;
+ break;
+ default:
+ die("unknown op '%s'", arg->op.op);
+ }
+ break;
+ default: /* not sure what to do there */
+ return 0;
+ }
+ return val;
+}
+
+struct flag {
+ const char *name;
+ unsigned long long value;
+};
+
+static const struct flag flags[] = {
+ { "HI_SOFTIRQ", 0 },
+ { "TIMER_SOFTIRQ", 1 },
+ { "NET_TX_SOFTIRQ", 2 },
+ { "NET_RX_SOFTIRQ", 3 },
+ { "BLOCK_SOFTIRQ", 4 },
+ { "BLOCK_IOPOLL_SOFTIRQ", 5 },
+ { "TASKLET_SOFTIRQ", 6 },
+ { "SCHED_SOFTIRQ", 7 },
+ { "HRTIMER_SOFTIRQ", 8 },
+ { "RCU_SOFTIRQ", 9 },
+
+ { "HRTIMER_NORESTART", 0 },
+ { "HRTIMER_RESTART", 1 },
+};
+
+static unsigned long long eval_flag(const char *flag)
+{
+ int i;
+
+ /*
+ * Some flags in the format files do not get converted.
+ * If the flag is not numeric, see if it is something that
+ * we already know about.
+ */
+ if (isdigit(flag[0]))
+ return strtoull(flag, NULL, 0);
+
+ for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
+ if (strcmp(flags[i].name, flag) == 0)
+ return flags[i].value;
+
+ return 0;
+}
+
+static void print_str_to_seq(struct trace_seq *s, const char *format,
+ int len_arg, const char *str)
+{
+ if (len_arg >= 0)
+ trace_seq_printf(s, format, len_arg, str);
+ else
+ trace_seq_printf(s, format, str);
+}
+
+static void print_str_arg(struct trace_seq *s, void *data, int size,
+ struct event_format *event, const char *format,
+ int len_arg, struct print_arg *arg)
+{
+ struct pevent *pevent = event->pevent;
+ struct print_flag_sym *flag;
+ unsigned long long val, fval;
+ unsigned long addr;
+ char *str;
+ int print;
+ int len;
+
+ switch (arg->type) {
+ case PRINT_NULL:
+ /* ?? */
+ return;
+ case PRINT_ATOM:
+ print_str_to_seq(s, format, len_arg, arg->atom.atom);
+ return;
+ case PRINT_FIELD:
+ if (!arg->field.field) {
+ arg->field.field = pevent_find_any_field(event, arg->field.name);
+ if (!arg->field.field)
+ die("field %s not found", arg->field.name);
+ }
+ /* Zero sized fields, mean the rest of the data */
+ len = arg->field.field->size ? : size - arg->field.field->offset;
+
+ /*
+ * Some events pass in pointers. If this is not an array
+ * and the size is the same as long_size, assume that it
+ * is a pointer.
+ */
+ if (!(arg->field.field->flags & FIELD_IS_ARRAY) &&
+ arg->field.field->size == pevent->long_size) {
+ addr = *(unsigned long *)(data + arg->field.field->offset);
+ trace_seq_printf(s, "%lx", addr);
+ break;
+ }
+ str = malloc_or_die(len + 1);
+ memcpy(str, data + arg->field.field->offset, len);
+ str[len] = 0;
+ print_str_to_seq(s, format, len_arg, str);
+ free(str);
+ break;
+ case PRINT_FLAGS:
+ val = eval_num_arg(data, size, event, arg->flags.field);
+ print = 0;
+ for (flag = arg->flags.flags; flag; flag = flag->next) {
+ fval = eval_flag(flag->value);
+ if (!val && !fval) {
+ print_str_to_seq(s, format, len_arg, flag->str);
+ break;
+ }
+ if (fval && (val & fval) == fval) {
+ if (print && arg->flags.delim)
+ trace_seq_puts(s, arg->flags.delim);
+ print_str_to_seq(s, format, len_arg, flag->str);
+ print = 1;
+ val &= ~fval;
+ }
+ }
+ break;
+ case PRINT_SYMBOL:
+ val = eval_num_arg(data, size, event, arg->symbol.field);
+ for (flag = arg->symbol.symbols; flag; flag = flag->next) {
+ fval = eval_flag(flag->value);
+ if (val == fval) {
+ print_str_to_seq(s, format, len_arg, flag->str);
+ break;
+ }
+ }
+ break;
+
+ case PRINT_TYPE:
+ break;
+ case PRINT_STRING: {
+ int str_offset;
+
+ if (arg->string.offset == -1) {
+ struct format_field *f;
+
+ f = pevent_find_any_field(event, arg->string.string);
+ arg->string.offset = f->offset;
+ }
+ str_offset = data2host4(pevent, data + arg->string.offset);
+ str_offset &= 0xffff;
+ print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset);
+ break;
+ }
+ case PRINT_BSTRING:
+ trace_seq_printf(s, format, arg->string.string);
+ break;
+ case PRINT_OP:
+ /*
+ * The only op for string should be ? :
+ */
+ if (arg->op.op[0] != '?')
+ return;
+ val = eval_num_arg(data, size, event, arg->op.left);
+ if (val)
+ print_str_arg(s, data, size, event,
+ format, len_arg, arg->op.right->op.left);
+ else
+ print_str_arg(s, data, size, event,
+ format, len_arg, arg->op.right->op.right);
+ break;
+ case PRINT_FUNC:
+ process_defined_func(s, data, size, event, arg);
+ break;
+ default:
+ /* well... */
+ break;
+ }
+}
+
+static unsigned long long
+process_defined_func(struct trace_seq *s, void *data, int size,
+ struct event_format *event, struct print_arg *arg)
+{
+ struct pevent_function_handler *func_handle = arg->func.func;
+ struct pevent_func_params *param;
+ unsigned long long *args;
+ unsigned long long ret;
+ struct print_arg *farg;
+ struct trace_seq str;
+ struct save_str {
+ struct save_str *next;
+ char *str;
+ } *strings = NULL, *string;
+ int i;
+
+ if (!func_handle->nr_args) {
+ ret = (*func_handle->func)(s, NULL);
+ goto out;
+ }
+
+ farg = arg->func.args;
+ param = func_handle->params;
+
+ args = malloc_or_die(sizeof(*args) * func_handle->nr_args);
+ for (i = 0; i < func_handle->nr_args; i++) {
+ switch (param->type) {
+ case PEVENT_FUNC_ARG_INT:
+ case PEVENT_FUNC_ARG_LONG:
+ case PEVENT_FUNC_ARG_PTR:
+ args[i] = eval_num_arg(data, size, event, farg);
+ break;
+ case PEVENT_FUNC_ARG_STRING:
+ trace_seq_init(&str);
+ print_str_arg(&str, data, size, event, "%s", -1, farg);
+ trace_seq_terminate(&str);
+ string = malloc_or_die(sizeof(*string));
+ string->next = strings;
+ string->str = strdup(str.buffer);
+ strings = string;
+ trace_seq_destroy(&str);
+ break;
+ default:
+ /*
+ * Something went totally wrong, this is not
+ * an input error, something in this code broke.
+ */
+ die("Unexpected end of arguments\n");
+ break;
+ }
+ farg = farg->next;
+ }
+
+ ret = (*func_handle->func)(s, args);
+ free(args);
+ while (strings) {
+ string = strings;
+ strings = string->next;
+ free(string->str);
+ free(string);
+ }
+
+ out:
+ /* TBD : handle return type here */
+ return ret;
+}
+
+static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event_format *event)
+{
+ struct pevent *pevent = event->pevent;
+ struct format_field *field, *ip_field;
+ struct print_arg *args, *arg, **next;
+ unsigned long long ip, val;
+ char *ptr;
+ void *bptr;
+
+ field = pevent->bprint_buf_field;
+ ip_field = pevent->bprint_ip_field;
+
+ if (!field) {
+ field = pevent_find_field(event, "buf");
+ if (!field)
+ die("can't find buffer field for binary printk");
+ ip_field = pevent_find_field(event, "ip");
+ if (!ip_field)
+ die("can't find ip field for binary printk");
+ pevent->bprint_buf_field = field;
+ pevent->bprint_ip_field = ip_field;
+ }
+
+ ip = pevent_read_number(pevent, data + ip_field->offset, ip_field->size);
+
+ /*
+ * The first arg is the IP pointer.
+ */
+ args = alloc_arg();
+ arg = args;
+ arg->next = NULL;
+ next = &arg->next;
+
+ arg->type = PRINT_ATOM;
+ arg->atom.atom = malloc_or_die(32);
+ sprintf(arg->atom.atom, "%lld", ip);
+
+ /* skip the first "%pf : " */
+ for (ptr = fmt + 6, bptr = data + field->offset;
+ bptr < data + size && *ptr; ptr++) {
+ int ls = 0;
+
+ if (*ptr == '%') {
+ process_again:
+ ptr++;
+ switch (*ptr) {
+ case '%':
+ break;
+ case 'l':
+ ls++;
+ goto process_again;
+ case 'L':
+ ls = 2;
+ goto process_again;
+ case '0' ... '9':
+ goto process_again;
+ case 'p':
+ ls = 1;
+ /* fall through */
+ case 'd':
+ case 'u':
+ case 'x':
+ case 'i':
+ /* the pointers are always 4 bytes aligned */
+ bptr = (void *)(((unsigned long)bptr + 3) &
+ ~3);
+ switch (ls) {
+ case 0:
+ ls = 4;
+ break;
+ case 1:
+ ls = pevent->long_size;
+ break;
+ case 2:
+ ls = 8;
+ default:
+ break;
+ }
+ val = pevent_read_number(pevent, bptr, ls);
+ bptr += ls;
+ arg = alloc_arg();
+ arg->next = NULL;
+ arg->type = PRINT_ATOM;
+ arg->atom.atom = malloc_or_die(32);
+ sprintf(arg->atom.atom, "%lld", val);
+ *next = arg;
+ next = &arg->next;
+ break;
+ case 's':
+ arg = alloc_arg();
+ arg->next = NULL;
+ arg->type = PRINT_BSTRING;
+ arg->string.string = strdup(bptr);
+ bptr += strlen(bptr) + 1;
+ *next = arg;
+ next = &arg->next;
+ default:
+ break;
+ }
+ }
+ }
+
+ return args;
+}
+
+static void free_args(struct print_arg *args)
+{
+ struct print_arg *next;
+
+ while (args) {
+ next = args->next;
+
+ free_arg(args);
+ args = next;
+ }
+}
+
+static char *
+get_bprint_format(void *data, int size __unused, struct event_format *event)
+{
+ struct pevent *pevent = event->pevent;
+ unsigned long long addr;
+ struct format_field *field;
+ struct printk_map *printk;
+ char *format;
+ char *p;
+
+ field = pevent->bprint_fmt_field;
+
+ if (!field) {
+ field = pevent_find_field(event, "fmt");
+ if (!field)
+ die("can't find format field for binary printk");
+ pevent->bprint_fmt_field = field;
+ }
+
+ addr = pevent_read_number(pevent, data + field->offset, field->size);
+
+ printk = find_printk(pevent, addr);
+ if (!printk) {
+ format = malloc_or_die(45);
+ sprintf(format, "%%pf : (NO FORMAT FOUND at %llx)\n",
+ addr);
+ return format;
+ }
+
+ p = printk->printk;
+ /* Remove any quotes. */
+ if (*p == '"')
+ p++;
+ format = malloc_or_die(strlen(p) + 10);
+ sprintf(format, "%s : %s", "%pf", p);
+ /* remove ending quotes and new line since we will add one too */
+ p = format + strlen(format) - 1;
+ if (*p == '"')
+ *p = 0;
+
+ p -= 2;
+ if (strcmp(p, "\\n") == 0)
+ *p = 0;
+
+ return format;
+}
+
+static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
+ struct event_format *event, struct print_arg *arg)
+{
+ unsigned char *buf;
+ char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x";
+
+ if (arg->type == PRINT_FUNC) {
+ process_defined_func(s, data, size, event, arg);
+ return;
+ }
+
+ if (arg->type != PRINT_FIELD) {
+ trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d",
+ arg->type);
+ return;
+ }
+
+ if (mac == 'm')
+ fmt = "%.2x%.2x%.2x%.2x%.2x%.2x";
+ if (!arg->field.field) {
+ arg->field.field =
+ pevent_find_any_field(event, arg->field.name);
+ if (!arg->field.field)
+ die("field %s not found", arg->field.name);
+ }
+ if (arg->field.field->size != 6) {
+ trace_seq_printf(s, "INVALIDMAC");
+ return;
+ }
+ buf = data + arg->field.field->offset;
+ trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+}
+
+static void print_event_fields(struct trace_seq *s, void *data, int size,
+ struct event_format *event)
+{
+ struct format_field *field;
+ unsigned long long val;
+ unsigned int offset, len, i;
+
+ field = event->format.fields;
+ while (field) {
+ trace_seq_printf(s, " %s=", field->name);
+ if (field->flags & FIELD_IS_ARRAY) {
+ offset = field->offset;
+ len = field->size;
+ if (field->flags & FIELD_IS_DYNAMIC) {
+ val = pevent_read_number(event->pevent, data + offset, len);
+ offset = val;
+ len = offset >> 16;
+ offset &= 0xffff;
+ }
+ if (field->flags & FIELD_IS_STRING) {
+ trace_seq_printf(s, "%s", (char *)data + offset);
+ } else {
+ trace_seq_puts(s, "ARRAY[");
+ for (i = 0; i < len; i++) {
+ if (i)
+ trace_seq_puts(s, ", ");
+ trace_seq_printf(s, "%02x",
+ *((unsigned char *)data + offset + i));
+ }
+ trace_seq_putc(s, ']');
+ }
+ } else {
+ val = pevent_read_number(event->pevent, data + field->offset,
+ field->size);
+ if (field->flags & FIELD_IS_POINTER) {
+ trace_seq_printf(s, "0x%llx", val);
+ } else if (field->flags & FIELD_IS_SIGNED) {
+ switch (field->size) {
+ case 4:
+ /*
+ * If field is long then print it in hex.
+ * A long usually stores pointers.
+ */
+ if (field->flags & FIELD_IS_LONG)
+ trace_seq_printf(s, "0x%x", (int)val);
+ else
+ trace_seq_printf(s, "%d", (int)val);
+ break;
+ case 2:
+ trace_seq_printf(s, "%2d", (short)val);
+ break;
+ case 1:
+ trace_seq_printf(s, "%1d", (char)val);
+ break;
+ default:
+ trace_seq_printf(s, "%lld", val);
+ }
+ } else {
+ if (field->flags & FIELD_IS_LONG)
+ trace_seq_printf(s, "0x%llx", val);
+ else
+ trace_seq_printf(s, "%llu", val);
+ }
+ }
+ field = field->next;
+ }
+}
+
+static void pretty_print(struct trace_seq *s, void *data, int size, struct event_format *event)
+{
+ struct pevent *pevent = event->pevent;
+ struct print_fmt *print_fmt = &event->print_fmt;
+ struct print_arg *arg = print_fmt->args;
+ struct print_arg *args = NULL;
+ const char *ptr = print_fmt->format;
+ unsigned long long val;
+ struct func_map *func;
+ const char *saveptr;
+ char *bprint_fmt = NULL;
+ char format[32];
+ int show_func;
+ int len_as_arg;
+ int len_arg;
+ int len;
+ int ls;
+
+ if (event->flags & EVENT_FL_FAILED) {
+ trace_seq_printf(s, "[FAILED TO PARSE]");
+ print_event_fields(s, data, size, event);
+ return;
+ }
+
+ if (event->flags & EVENT_FL_ISBPRINT) {
+ bprint_fmt = get_bprint_format(data, size, event);
+ args = make_bprint_args(bprint_fmt, data, size, event);
+ arg = args;
+ ptr = bprint_fmt;
+ }
+
+ for (; *ptr; ptr++) {
+ ls = 0;
+ if (*ptr == '\\') {
+ ptr++;
+ switch (*ptr) {
+ case 'n':
+ trace_seq_putc(s, '\n');
+ break;
+ case 't':
+ trace_seq_putc(s, '\t');
+ break;
+ case 'r':
+ trace_seq_putc(s, '\r');
+ break;
+ case '\\':
+ trace_seq_putc(s, '\\');
+ break;
+ default:
+ trace_seq_putc(s, *ptr);
+ break;
+ }
+
+ } else if (*ptr == '%') {
+ saveptr = ptr;
+ show_func = 0;
+ len_as_arg = 0;
+ cont_process:
+ ptr++;
+ switch (*ptr) {
+ case '%':
+ trace_seq_putc(s, '%');
+ break;
+ case '#':
+ /* FIXME: need to handle properly */
+ goto cont_process;
+ case 'h':
+ ls--;
+ goto cont_process;
+ case 'l':
+ ls++;
+ goto cont_process;
+ case 'L':
+ ls = 2;
+ goto cont_process;
+ case '*':
+ /* The argument is the length. */
+ if (!arg)
+ die("no argument match");
+ len_arg = eval_num_arg(data, size, event, arg);
+ len_as_arg = 1;
+ arg = arg->next;
+ goto cont_process;
+ case '.':
+ case 'z':
+ case 'Z':
+ case '0' ... '9':
+ goto cont_process;
+ case 'p':
+ if (pevent->long_size == 4)
+ ls = 1;
+ else
+ ls = 2;
+
+ if (*(ptr+1) == 'F' ||
+ *(ptr+1) == 'f') {
+ ptr++;
+ show_func = *ptr;
+ } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') {
+ print_mac_arg(s, *(ptr+1), data, size, event, arg);
+ ptr++;
+ break;
+ }
+
+ /* fall through */
+ case 'd':
+ case 'i':
+ case 'x':
+ case 'X':
+ case 'u':
+ if (!arg)
+ die("no argument match");
+
+ len = ((unsigned long)ptr + 1) -
+ (unsigned long)saveptr;
+
+ /* should never happen */
+ if (len > 31)
+ die("bad format!");
+
+ memcpy(format, saveptr, len);
+ format[len] = 0;
+
+ val = eval_num_arg(data, size, event, arg);
+ arg = arg->next;
+
+ if (show_func) {
+ func = find_func(pevent, val);
+ if (func) {
+ trace_seq_puts(s, func->func);
+ if (show_func == 'F')
+ trace_seq_printf(s,
+ "+0x%llx",
+ val - func->addr);
+ break;
+ }
+ }
+ if (pevent->long_size == 8 && ls) {
+ char *p;
+
+ ls = 2;
+ /* make %l into %ll */
+ p = strchr(format, 'l');
+ if (p)
+ memmove(p, p+1, strlen(p)+1);
+ else if (strcmp(format, "%p") == 0)
+ strcpy(format, "0x%llx");
+ }
+ switch (ls) {
+ case -2:
+ if (len_as_arg)
+ trace_seq_printf(s, format, len_arg, (char)val);
+ else
+ trace_seq_printf(s, format, (char)val);
+ break;
+ case -1:
+ if (len_as_arg)
+ trace_seq_printf(s, format, len_arg, (short)val);
+ else
+ trace_seq_printf(s, format, (short)val);
+ break;
+ case 0:
+ if (len_as_arg)
+ trace_seq_printf(s, format, len_arg, (int)val);
+ else
+ trace_seq_printf(s, format, (int)val);
+ break;
+ case 1:
+ if (len_as_arg)
+ trace_seq_printf(s, format, len_arg, (long)val);
+ else
+ trace_seq_printf(s, format, (long)val);
+ break;
+ case 2:
+ if (len_as_arg)
+ trace_seq_printf(s, format, len_arg,
+ (long long)val);
+ else
+ trace_seq_printf(s, format, (long long)val);
+ break;
+ default:
+ die("bad count (%d)", ls);
+ }
+ break;
+ case 's':
+ if (!arg)
+ die("no matching argument");
+
+ len = ((unsigned long)ptr + 1) -
+ (unsigned long)saveptr;
+
+ /* should never happen */
+ if (len > 31)
+ die("bad format!");
+
+ memcpy(format, saveptr, len);
+ format[len] = 0;
+ if (!len_as_arg)
+ len_arg = -1;
+ print_str_arg(s, data, size, event,
+ format, len_arg, arg);
+ arg = arg->next;
+ break;
+ default:
+ trace_seq_printf(s, ">%c<", *ptr);
+
+ }
+ } else
+ trace_seq_putc(s, *ptr);
+ }
+
+ if (args) {
+ free_args(args);
+ free(bprint_fmt);
+ }
+}
+
+/**
+ * pevent_data_lat_fmt - parse the data for the latency format
+ * @pevent: a handle to the pevent
+ * @s: the trace_seq to write to
+ * @data: the raw data to read from
+ * @size: currently unused.
+ *
+ * This parses out the Latency format (interrupts disabled,
+ * need rescheduling, in hard/soft interrupt, preempt count
+ * and lock depth) and places it into the trace_seq.
+ */
+void pevent_data_lat_fmt(struct pevent *pevent,
+ struct trace_seq *s, struct pevent_record *record)
+{
+ static int check_lock_depth = 1;
+ static int lock_depth_exists;
+ unsigned int lat_flags;
+ unsigned int pc;
+ int lock_depth;
+ int hardirq;
+ int softirq;
+ void *data = record->data;
+
+ lat_flags = parse_common_flags(pevent, data);
+ pc = parse_common_pc(pevent, data);
+ /* lock_depth may not always exist */
+ if (check_lock_depth) {
+ struct format_field *field;
+ struct event_format *event;
+
+ check_lock_depth = 0;
+ event = pevent->events[0];
+ field = pevent_find_common_field(event, "common_lock_depth");
+ if (field)
+ lock_depth_exists = 1;
+ }
+ if (lock_depth_exists)
+ lock_depth = parse_common_lock_depth(pevent, data);
+
+ hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
+ softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
+
+ trace_seq_printf(s, "%c%c%c",
+ (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
+ (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
+ 'X' : '.',
+ (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
+ 'N' : '.',
+ (hardirq && softirq) ? 'H' :
+ hardirq ? 'h' : softirq ? 's' : '.');
+
+ if (pc)
+ trace_seq_printf(s, "%x", pc);
+ else
+ trace_seq_putc(s, '.');
+
+ if (lock_depth_exists) {
+ if (lock_depth < 0)
+ trace_seq_putc(s, '.');
+ else
+ trace_seq_printf(s, "%d", lock_depth);
+ }
+
+ trace_seq_terminate(s);
+}
+
+/**
+ * pevent_data_type - parse out the given event type
+ * @pevent: a handle to the pevent
+ * @rec: the record to read from
+ *
+ * This returns the event id from the @rec.
+ */
+int pevent_data_type(struct pevent *pevent, struct pevent_record *rec)
+{
+ return trace_parse_common_type(pevent, rec->data);
+}
+
+/**
+ * pevent_data_event_from_type - find the event by a given type
+ * @pevent: a handle to the pevent
+ * @type: the type of the event.
+ *
+ * This returns the event form a given @type;
+ */
+struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type)
+{
+ return pevent_find_event(pevent, type);
+}
+
+/**
+ * pevent_data_pid - parse the PID from raw data
+ * @pevent: a handle to the pevent
+ * @rec: the record to parse
+ *
+ * This returns the PID from a raw data.
+ */
+int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec)
+{
+ return parse_common_pid(pevent, rec->data);
+}
+
+/**
+ * pevent_data_comm_from_pid - return the command line from PID
+ * @pevent: a handle to the pevent
+ * @pid: the PID of the task to search for
+ *
+ * This returns a pointer to the command line that has the given
+ * @pid.
+ */
+const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
+{
+ const char *comm;
+
+ comm = find_cmdline(pevent, pid);
+ return comm;
+}
+
+/**
+ * pevent_data_comm_from_pid - parse the data into the print format
+ * @s: the trace_seq to write to
+ * @event: the handle to the event
+ * @cpu: the cpu the event was recorded on
+ * @data: the raw data
+ * @size: the size of the raw data
+ * @nsecs: the timestamp of the event
+ *
+ * This parses the raw @data using the given @event information and
+ * writes the print format into the trace_seq.
+ */
+void pevent_event_info(struct trace_seq *s, struct event_format *event,
+ struct pevent_record *record)
+{
+ int print_pretty = 1;
+
+ if (event->pevent->print_raw)
+ print_event_fields(s, record->data, record->size, event);
+ else {
+
+ if (event->handler)
+ print_pretty = event->handler(s, record, event,
+ event->context);
+
+ if (print_pretty)
+ pretty_print(s, record->data, record->size, event);
+ }
+
+ trace_seq_terminate(s);
+}
+
+void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
+ struct pevent_record *record)
+{
+ static char *spaces = " "; /* 20 spaces */
+ struct event_format *event;
+ unsigned long secs;
+ unsigned long usecs;
+ unsigned long nsecs;
+ const char *comm;
+ void *data = record->data;
+ int type;
+ int pid;
+ int len;
+ int p;
+
+ secs = record->ts / NSECS_PER_SEC;
+ nsecs = record->ts - secs * NSECS_PER_SEC;
+
+ if (record->size < 0) {
+ do_warning("ug! negative record size %d", record->size);
+ return;
+ }
+
+ type = trace_parse_common_type(pevent, data);
+
+ event = pevent_find_event(pevent, type);
+ if (!event) {
+ do_warning("ug! no event found for type %d", type);
+ return;
+ }
+
+ pid = parse_common_pid(pevent, data);
+ comm = find_cmdline(pevent, pid);
+
+ if (pevent->latency_format) {
+ trace_seq_printf(s, "%8.8s-%-5d %3d",
+ comm, pid, record->cpu);
+ pevent_data_lat_fmt(pevent, s, record);
+ } else
+ trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);
+
+ if (pevent->flags & PEVENT_NSEC_OUTPUT) {
+ usecs = nsecs;
+ p = 9;
+ } else {
+ usecs = (nsecs + 500) / NSECS_PER_USEC;
+ p = 6;
+ }
+
+ trace_seq_printf(s, " %5lu.%0*lu: %s: ", secs, p, usecs, event->name);
+
+ /* Space out the event names evenly. */
+ len = strlen(event->name);
+ if (len < 20)
+ trace_seq_printf(s, "%.*s", 20 - len, spaces);
+
+ pevent_event_info(s, event, record);
+}
+
+static int events_id_cmp(const void *a, const void *b)
+{
+ struct event_format * const * ea = a;
+ struct event_format * const * eb = b;
+
+ if ((*ea)->id < (*eb)->id)
+ return -1;
+
+ if ((*ea)->id > (*eb)->id)
+ return 1;
+
+ return 0;
+}
+
+static int events_name_cmp(const void *a, const void *b)
+{
+ struct event_format * const * ea = a;
+ struct event_format * const * eb = b;
+ int res;
+
+ res = strcmp((*ea)->name, (*eb)->name);
+ if (res)
+ return res;
+
+ res = strcmp((*ea)->system, (*eb)->system);
+ if (res)
+ return res;
+
+ return events_id_cmp(a, b);
+}
+
+static int events_system_cmp(const void *a, const void *b)
+{
+ struct event_format * const * ea = a;
+ struct event_format * const * eb = b;
+ int res;
+
+ res = strcmp((*ea)->system, (*eb)->system);
+ if (res)
+ return res;
+
+ res = strcmp((*ea)->name, (*eb)->name);
+ if (res)
+ return res;
+
+ return events_id_cmp(a, b);
+}
+
+struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type sort_type)
+{
+ struct event_format **events;
+ int (*sort)(const void *a, const void *b);
+
+ events = pevent->sort_events;
+
+ if (events && pevent->last_type == sort_type)
+ return events;
+
+ if (!events) {
+ events = malloc(sizeof(*events) * (pevent->nr_events + 1));
+ if (!events)
+ return NULL;
+
+ memcpy(events, pevent->events, sizeof(*events) * pevent->nr_events);
+ events[pevent->nr_events] = NULL;
+
+ pevent->sort_events = events;
+
+ /* the internal events are sorted by id */
+ if (sort_type == EVENT_SORT_ID) {
+ pevent->last_type = sort_type;
+ return events;
+ }
+ }
+
+ switch (sort_type) {
+ case EVENT_SORT_ID:
+ sort = events_id_cmp;
+ break;
+ case EVENT_SORT_NAME:
+ sort = events_name_cmp;
+ break;
+ case EVENT_SORT_SYSTEM:
+ sort = events_system_cmp;
+ break;
+ default:
+ return events;
+ }
+
+ qsort(events, pevent->nr_events, sizeof(*events), sort);
+ pevent->last_type = sort_type;
+
+ return events;
+}
+
+static struct format_field **
+get_event_fields(const char *type, const char *name,
+ int count, struct format_field *list)
+{
+ struct format_field **fields;
+ struct format_field *field;
+ int i = 0;
+
+ fields = malloc_or_die(sizeof(*fields) * (count + 1));
+ for (field = list; field; field = field->next) {
+ fields[i++] = field;
+ if (i == count + 1) {
+ do_warning("event %s has more %s fields than specified",
+ name, type);
+ i--;
+ break;
+ }
+ }
+
+ if (i != count)
+ do_warning("event %s has less %s fields than specified",
+ name, type);
+
+ fields[i] = NULL;
+
+ return fields;
+}
+
+/**
+ * pevent_event_common_fields - return a list of common fields for an event
+ * @event: the event to return the common fields of.
+ *
+ * Returns an allocated array of fields. The last item in the array is NULL.
+ * The array must be freed with free().
+ */
+struct format_field **pevent_event_common_fields(struct event_format *event)
+{
+ return get_event_fields("common", event->name,
+ event->format.nr_common,
+ event->format.common_fields);
+}
+
+/**
+ * pevent_event_fields - return a list of event specific fields for an event
+ * @event: the event to return the fields of.
+ *
+ * Returns an allocated array of fields. The last item in the array is NULL.
+ * The array must be freed with free().
+ */
+struct format_field **pevent_event_fields(struct event_format *event)
+{
+ return get_event_fields("event", event->name,
+ event->format.nr_fields,
+ event->format.fields);
+}
+
+static void print_fields(struct trace_seq *s, struct print_flag_sym *field)
+{
+ trace_seq_printf(s, "{ %s, %s }", field->value, field->str);
+ if (field->next) {
+ trace_seq_puts(s, ", ");
+ print_fields(s, field->next);
+ }
+}
+
+/* for debugging */
+static void print_args(struct print_arg *args)
+{
+ int print_paren = 1;
+ struct trace_seq s;
+
+ switch (args->type) {
+ case PRINT_NULL:
+ printf("null");
+ break;
+ case PRINT_ATOM:
+ printf("%s", args->atom.atom);
+ break;
+ case PRINT_FIELD:
+ printf("REC->%s", args->field.name);
+ break;
+ case PRINT_FLAGS:
+ printf("__print_flags(");
+ print_args(args->flags.field);
+ printf(", %s, ", args->flags.delim);
+ trace_seq_init(&s);
+ print_fields(&s, args->flags.flags);
+ trace_seq_do_printf(&s);
+ trace_seq_destroy(&s);
+ printf(")");
+ break;
+ case PRINT_SYMBOL:
+ printf("__print_symbolic(");
+ print_args(args->symbol.field);
+ printf(", ");
+ trace_seq_init(&s);
+ print_fields(&s, args->symbol.symbols);
+ trace_seq_do_printf(&s);
+ trace_seq_destroy(&s);
+ printf(")");
+ break;
+ case PRINT_STRING:
+ case PRINT_BSTRING:
+ printf("__get_str(%s)", args->string.string);
+ break;
+ case PRINT_TYPE:
+ printf("(%s)", args->typecast.type);
+ print_args(args->typecast.item);
+ break;
+ case PRINT_OP:
+ if (strcmp(args->op.op, ":") == 0)
+ print_paren = 0;
+ if (print_paren)
+ printf("(");
+ print_args(args->op.left);
+ printf(" %s ", args->op.op);
+ print_args(args->op.right);
+ if (print_paren)
+ printf(")");
+ break;
+ default:
+ /* we should warn... */
+ return;
+ }
+ if (args->next) {
+ printf("\n");
+ print_args(args->next);
+ }
+}
+
+static void parse_header_field(const char *field,
+ int *offset, int *size, int mandatory)
+{
+ unsigned long long save_input_buf_ptr;
+ unsigned long long save_input_buf_siz;
+ char *token;
+ int type;
+
+ save_input_buf_ptr = input_buf_ptr;
+ save_input_buf_siz = input_buf_siz;
+
+ if (read_expected(EVENT_ITEM, "field") < 0)
+ return;
+ if (read_expected(EVENT_OP, ":") < 0)
+ return;
+
+ /* type */
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+ free_token(token);
+
+ /*
+ * If this is not a mandatory field, then test it first.
+ */
+ if (mandatory) {
+ if (read_expected(EVENT_ITEM, field) < 0)
+ return;
+ } else {
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+ if (strcmp(token, field) != 0)
+ goto discard;
+ free_token(token);
+ }
+
+ if (read_expected(EVENT_OP, ";") < 0)
+ return;
+ if (read_expected(EVENT_ITEM, "offset") < 0)
+ return;
+ if (read_expected(EVENT_OP, ":") < 0)
+ return;
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+ *offset = atoi(token);
+ free_token(token);
+ if (read_expected(EVENT_OP, ";") < 0)
+ return;
+ if (read_expected(EVENT_ITEM, "size") < 0)
+ return;
+ if (read_expected(EVENT_OP, ":") < 0)
+ return;
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+ *size = atoi(token);
+ free_token(token);
+ if (read_expected(EVENT_OP, ";") < 0)
+ return;
+ type = read_token(&token);
+ if (type != EVENT_NEWLINE) {
+ /* newer versions of the kernel have a "signed" type */
+ if (type != EVENT_ITEM)
+ goto fail;
+
+ if (strcmp(token, "signed") != 0)
+ goto fail;
+
+ free_token(token);
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ return;
+
+ if (read_expect_type(EVENT_ITEM, &token))
+ goto fail;
+
+ free_token(token);
+ if (read_expected(EVENT_OP, ";") < 0)
+ return;
+
+ if (read_expect_type(EVENT_NEWLINE, &token))
+ goto fail;
+ }
+ fail:
+ free_token(token);
+ return;
+
+ discard:
+ input_buf_ptr = save_input_buf_ptr;
+ input_buf_siz = save_input_buf_siz;
+ *offset = 0;
+ *size = 0;
+ free_token(token);
+}
+
+/**
+ * pevent_parse_header_page - parse the data stored in the header page
+ * @pevent: the handle to the pevent
+ * @buf: the buffer storing the header page format string
+ * @size: the size of @buf
+ * @long_size: the long size to use if there is no header
+ *
+ * This parses the header page format for information on the
+ * ring buffer used. The @buf should be copied from
+ *
+ * /sys/kernel/debug/tracing/events/header_page
+ */
+int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
+ int long_size)
+{
+ int ignore;
+
+ if (!size) {
+ /*
+ * Old kernels did not have header page info.
+ * Sorry but we just use what we find here in user space.
+ */
+ pevent->header_page_ts_size = sizeof(long long);
+ pevent->header_page_size_size = long_size;
+ pevent->header_page_data_offset = sizeof(long long) + long_size;
+ pevent->old_format = 1;
+ return -1;
+ }
+ init_input_buf(buf, size);
+
+ parse_header_field("timestamp", &pevent->header_page_ts_offset,
+ &pevent->header_page_ts_size, 1);
+ parse_header_field("commit", &pevent->header_page_size_offset,
+ &pevent->header_page_size_size, 1);
+ parse_header_field("overwrite", &pevent->header_page_overwrite,
+ &ignore, 0);
+ parse_header_field("data", &pevent->header_page_data_offset,
+ &pevent->header_page_data_size, 1);
+
+ return 0;
+}
+
+static int event_matches(struct event_format *event,
+ int id, const char *sys_name,
+ const char *event_name)
+{
+ if (id >= 0 && id != event->id)
+ return 0;
+
+ if (event_name && (strcmp(event_name, event->name) != 0))
+ return 0;
+
+ if (sys_name && (strcmp(sys_name, event->system) != 0))
+ return 0;
+
+ return 1;
+}
+
+static void free_handler(struct event_handler *handle)
+{
+ free((void *)handle->sys_name);
+ free((void *)handle->event_name);
+ free(handle);
+}
+
+static int find_event_handle(struct pevent *pevent, struct event_format *event)
+{
+ struct event_handler *handle, **next;
+
+ for (next = &pevent->handlers; *next;
+ next = &(*next)->next) {
+ handle = *next;
+ if (event_matches(event, handle->id,
+ handle->sys_name,
+ handle->event_name))
+ break;
+ }
+
+ if (!(*next))
+ return 0;
+
+ pr_stat("overriding event (%d) %s:%s with new print handler",
+ event->id, event->system, event->name);
+
+ event->handler = handle->func;
+ event->context = handle->context;
+
+ *next = handle->next;
+ free_handler(handle);
+
+ return 1;
+}
+
+/**
+ * pevent_parse_event - parse the event format
+ * @pevent: the handle to the pevent
+ * @buf: the buffer storing the event format string
+ * @size: the size of @buf
+ * @sys: the system the event belongs to
+ *
+ * This parses the event format and creates an event structure
+ * to quickly parse raw data for a given event.
+ *
+ * These files currently come from:
+ *
+ * /sys/kernel/debug/tracing/events/.../.../format
+ */
+int pevent_parse_event(struct pevent *pevent,
+ const char *buf, unsigned long size,
+ const char *sys)
+{
+ struct event_format *event;
+ int ret;
+
+ init_input_buf(buf, size);
+
+ event = alloc_event();
+ if (!event)
+ return -ENOMEM;
+
+ event->name = event_read_name();
+ if (!event->name) {
+ /* Bad event? */
+ free(event);
+ return -1;
+ }
+
+ if (strcmp(sys, "ftrace") == 0) {
+
+ event->flags |= EVENT_FL_ISFTRACE;
+
+ if (strcmp(event->name, "bprint") == 0)
+ event->flags |= EVENT_FL_ISBPRINT;
+ }
+
+ event->id = event_read_id();
+ if (event->id < 0)
+ die("failed to read event id");
+
+ event->system = strdup(sys);
+
+ /* Add pevent to event so that it can be referenced */
+ event->pevent = pevent;
+
+ ret = event_read_format(event);
+ if (ret < 0) {
+ do_warning("failed to read event format for %s", event->name);
+ goto event_failed;
+ }
+
+ /*
+ * If the event has an override, don't print warnings if the event
+ * print format fails to parse.
+ */
+ if (find_event_handle(pevent, event))
+ show_warning = 0;
+
+ ret = event_read_print(event);
+ if (ret < 0) {
+ do_warning("failed to read event print fmt for %s",
+ event->name);
+ show_warning = 1;
+ goto event_failed;
+ }
+ show_warning = 1;
+
+ add_event(pevent, event);
+
+ if (!ret && (event->flags & EVENT_FL_ISFTRACE)) {
+ struct format_field *field;
+ struct print_arg *arg, **list;
+
+ /* old ftrace had no args */
+
+ list = &event->print_fmt.args;
+ for (field = event->format.fields; field; field = field->next) {
+ arg = alloc_arg();
+ *list = arg;
+ list = &arg->next;
+ arg->type = PRINT_FIELD;
+ arg->field.name = strdup(field->name);
+ arg->field.field = field;
+ }
+ return 0;
+ }
+
+#define PRINT_ARGS 0
+ if (PRINT_ARGS && event->print_fmt.args)
+ print_args(event->print_fmt.args);
+
+ return 0;
+
+ event_failed:
+ event->flags |= EVENT_FL_FAILED;
+ /* still add it even if it failed */
+ add_event(pevent, event);
+ return -1;
+}
+
+int get_field_val(struct trace_seq *s, struct format_field *field,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err)
+{
+ if (!field) {
+ if (err)
+ trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
+ return -1;
+ }
+
+ if (pevent_read_number_field(field, record->data, val)) {
+ if (err)
+ trace_seq_printf(s, " %s=INVALID", name);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * pevent_get_field_raw - return the raw pointer into the data field
+ * @s: The seq to print to on error
+ * @event: the event that the field is for
+ * @name: The name of the field
+ * @record: The record with the field name.
+ * @len: place to store the field length.
+ * @err: print default error if failed.
+ *
+ * Returns a pointer into record->data of the field and places
+ * the length of the field in @len.
+ *
+ * On failure, it returns NULL.
+ */
+void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ int *len, int err)
+{
+ struct format_field *field;
+ void *data = record->data;
+ unsigned offset;
+ int dummy;
+
+ if (!event)
+ return NULL;
+
+ field = pevent_find_field(event, name);
+
+ if (!field) {
+ if (err)
+ trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
+ return NULL;
+ }
+
+ /* Allow @len to be NULL */
+ if (!len)
+ len = &dummy;
+
+ offset = field->offset;
+ if (field->flags & FIELD_IS_DYNAMIC) {
+ offset = pevent_read_number(event->pevent,
+ data + offset, field->size);
+ *len = offset >> 16;
+ offset &= 0xffff;
+ } else
+ *len = field->size;
+
+ return data + offset;
+}
+
+/**
+ * pevent_get_field_val - find a field and return its value
+ * @s: The seq to print to on error
+ * @event: the event that the field is for
+ * @name: The name of the field
+ * @record: The record with the field name.
+ * @val: place to store the value of the field.
+ * @err: print default error if failed.
+ *
+ * Returns 0 on success -1 on field not found.
+ */
+int pevent_get_field_val(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err)
+{
+ struct format_field *field;
+
+ if (!event)
+ return -1;
+
+ field = pevent_find_field(event, name);
+
+ return get_field_val(s, field, name, record, val, err);
+}
+
+/**
+ * pevent_get_common_field_val - find a common field and return its value
+ * @s: The seq to print to on error
+ * @event: the event that the field is for
+ * @name: The name of the field
+ * @record: The record with the field name.
+ * @val: place to store the value of the field.
+ * @err: print default error if failed.
+ *
+ * Returns 0 on success -1 on field not found.
+ */
+int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err)
+{
+ struct format_field *field;
+
+ if (!event)
+ return -1;
+
+ field = pevent_find_common_field(event, name);
+
+ return get_field_val(s, field, name, record, val, err);
+}
+
+/**
+ * pevent_get_any_field_val - find a any field and return its value
+ * @s: The seq to print to on error
+ * @event: the event that the field is for
+ * @name: The name of the field
+ * @record: The record with the field name.
+ * @val: place to store the value of the field.
+ * @err: print default error if failed.
+ *
+ * Returns 0 on success -1 on field not found.
+ */
+int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err)
+{
+ struct format_field *field;
+
+ if (!event)
+ return -1;
+
+ field = pevent_find_any_field(event, name);
+
+ return get_field_val(s, field, name, record, val, err);
+}
+
+/**
+ * pevent_print_num_field - print a field and a format
+ * @s: The seq to print to
+ * @fmt: The printf format to print the field with.
+ * @event: the event that the field is for
+ * @name: The name of the field
+ * @record: The record with the field name.
+ * @err: print default error if failed.
+ *
+ * Returns: 0 on success, -1 field not fould, or 1 if buffer is full.
+ */
+int pevent_print_num_field(struct trace_seq *s, const char *fmt,
+ struct event_format *event, const char *name,
+ struct pevent_record *record, int err)
+{
+ struct format_field *field = pevent_find_field(event, name);
+ unsigned long long val;
+
+ if (!field)
+ goto failed;
+
+ if (pevent_read_number_field(field, record->data, &val))
+ goto failed;
+
+ return trace_seq_printf(s, fmt, val);
+
+ failed:
+ if (err)
+ trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
+ return -1;
+}
+
+static void free_func_handle(struct pevent_function_handler *func)
+{
+ struct pevent_func_params *params;
+
+ free(func->name);
+
+ while (func->params) {
+ params = func->params;
+ func->params = params->next;
+ free(params);
+ }
+
+ free(func);
+}
+
+/**
+ * pevent_register_print_function - register a helper function
+ * @pevent: the handle to the pevent
+ * @func: the function to process the helper function
+ * @name: the name of the helper function
+ * @parameters: A list of enum pevent_func_arg_type
+ *
+ * Some events may have helper functions in the print format arguments.
+ * This allows a plugin to dynmically create a way to process one
+ * of these functions.
+ *
+ * The @parameters is a variable list of pevent_func_arg_type enums that
+ * must end with PEVENT_FUNC_ARG_VOID.
+ */
+int pevent_register_print_function(struct pevent *pevent,
+ pevent_func_handler func,
+ enum pevent_func_arg_type ret_type,
+ char *name, ...)
+{
+ struct pevent_function_handler *func_handle;
+ struct pevent_func_params **next_param;
+ struct pevent_func_params *param;
+ enum pevent_func_arg_type type;
+ va_list ap;
+
+ func_handle = find_func_handler(pevent, name);
+ if (func_handle) {
+ /*
+ * This is most like caused by the users own
+ * plugins updating the function. This overrides the
+ * system defaults.
+ */
+ pr_stat("override of function helper '%s'", name);
+ remove_func_handler(pevent, name);
+ }
+
+ func_handle = malloc_or_die(sizeof(*func_handle));
+ memset(func_handle, 0, sizeof(*func_handle));
+
+ func_handle->ret_type = ret_type;
+ func_handle->name = strdup(name);
+ func_handle->func = func;
+ if (!func_handle->name)
+ die("Failed to allocate function name");
+
+ next_param = &(func_handle->params);
+ va_start(ap, name);
+ for (;;) {
+ type = va_arg(ap, enum pevent_func_arg_type);
+ if (type == PEVENT_FUNC_ARG_VOID)
+ break;
+
+ if (type < 0 || type >= PEVENT_FUNC_ARG_MAX_TYPES) {
+ warning("Invalid argument type %d", type);
+ goto out_free;
+ }
+
+ param = malloc_or_die(sizeof(*param));
+ param->type = type;
+ param->next = NULL;
+
+ *next_param = param;
+ next_param = &(param->next);
+
+ func_handle->nr_args++;
+ }
+ va_end(ap);
+
+ func_handle->next = pevent->func_handlers;
+ pevent->func_handlers = func_handle;
+
+ return 0;
+ out_free:
+ va_end(ap);
+ free_func_handle(func_handle);
+ return -1;
+}
+
+/**
+ * pevent_register_event_handle - register a way to parse an event
+ * @pevent: the handle to the pevent
+ * @id: the id of the event to register
+ * @sys_name: the system name the event belongs to
+ * @event_name: the name of the event
+ * @func: the function to call to parse the event information
+ *
+ * This function allows a developer to override the parsing of
+ * a given event. If for some reason the default print format
+ * is not sufficient, this function will register a function
+ * for an event to be used to parse the data instead.
+ *
+ * If @id is >= 0, then it is used to find the event.
+ * else @sys_name and @event_name are used.
+ */
+int pevent_register_event_handler(struct pevent *pevent,
+ int id, char *sys_name, char *event_name,
+ pevent_event_handler_func func,
+ void *context)
+{
+ struct event_format *event;
+ struct event_handler *handle;
+
+ if (id >= 0) {
+ /* search by id */
+ event = pevent_find_event(pevent, id);
+ if (!event)
+ goto not_found;
+ if (event_name && (strcmp(event_name, event->name) != 0))
+ goto not_found;
+ if (sys_name && (strcmp(sys_name, event->system) != 0))
+ goto not_found;
+ } else {
+ event = pevent_find_event_by_name(pevent, sys_name, event_name);
+ if (!event)
+ goto not_found;
+ }
+
+ pr_stat("overriding event (%d) %s:%s with new print handler",
+ event->id, event->system, event->name);
+
+ event->handler = func;
+ event->context = context;
+ return 0;
+
+ not_found:
+ /* Save for later use. */
+ handle = malloc_or_die(sizeof(*handle));
+ memset(handle, 0, sizeof(*handle));
+ handle->id = id;
+ if (event_name)
+ handle->event_name = strdup(event_name);
+ if (sys_name)
+ handle->sys_name = strdup(sys_name);
+
+ handle->func = func;
+ handle->next = pevent->handlers;
+ pevent->handlers = handle;
+ handle->context = context;
+
+ return -1;
+}
+
+/**
+ * pevent_alloc - create a pevent handle
+ */
+struct pevent *pevent_alloc(void)
+{
+ struct pevent *pevent;
+
+ pevent = malloc(sizeof(*pevent));
+ if (!pevent)
+ return NULL;
+ memset(pevent, 0, sizeof(*pevent));
+ pevent->ref_count = 1;
+
+ return pevent;
+}
+
+void pevent_ref(struct pevent *pevent)
+{
+ pevent->ref_count++;
+}
+
+static void free_format_fields(struct format_field *field)
+{
+ struct format_field *next;
+
+ while (field) {
+ next = field->next;
+ free(field->type);
+ free(field->name);
+ free(field);
+ field = next;
+ }
+}
+
+static void free_formats(struct format *format)
+{
+ free_format_fields(format->common_fields);
+ free_format_fields(format->fields);
+}
+
+static void free_event(struct event_format *event)
+{
+ free(event->name);
+ free(event->system);
+
+ free_formats(&event->format);
+
+ free(event->print_fmt.format);
+ free_args(event->print_fmt.args);
+
+ free(event);
+}
+
+/**
+ * pevent_free - free a pevent handle
+ * @pevent: the pevent handle to free
+ */
+void pevent_free(struct pevent *pevent)
+{
+ struct cmdline_list *cmdlist, *cmdnext;
+ struct func_list *funclist, *funcnext;
+ struct printk_list *printklist, *printknext;
+ struct pevent_function_handler *func_handler;
+ struct event_handler *handle;
+ int i;
+
+ if (!pevent)
+ return;
+
+ cmdlist = pevent->cmdlist;
+ funclist = pevent->funclist;
+ printklist = pevent->printklist;
+
+ pevent->ref_count--;
+ if (pevent->ref_count)
+ return;
+
+ if (pevent->cmdlines) {
+ for (i = 0; i < pevent->cmdline_count; i++)
+ free(pevent->cmdlines[i].comm);
+ free(pevent->cmdlines);
+ }
+
+ while (cmdlist) {
+ cmdnext = cmdlist->next;
+ free(cmdlist->comm);
+ free(cmdlist);
+ cmdlist = cmdnext;
+ }
+
+ if (pevent->func_map) {
+ for (i = 0; i < pevent->func_count; i++) {
+ free(pevent->func_map[i].func);
+ free(pevent->func_map[i].mod);
+ }
+ free(pevent->func_map);
+ }
+
+ while (funclist) {
+ funcnext = funclist->next;
+ free(funclist->func);
+ free(funclist->mod);
+ free(funclist);
+ funclist = funcnext;
+ }
+
+ while (pevent->func_handlers) {
+ func_handler = pevent->func_handlers;
+ pevent->func_handlers = func_handler->next;
+ free_func_handle(func_handler);
+ }
+
+ if (pevent->printk_map) {
+ for (i = 0; i < pevent->printk_count; i++)
+ free(pevent->printk_map[i].printk);
+ free(pevent->printk_map);
+ }
+
+ while (printklist) {
+ printknext = printklist->next;
+ free(printklist->printk);
+ free(printklist);
+ printklist = printknext;
+ }
+
+ for (i = 0; i < pevent->nr_events; i++)
+ free_event(pevent->events[i]);
+
+ while (pevent->handlers) {
+ handle = pevent->handlers;
+ pevent->handlers = handle->next;
+ free_handler(handle);
+ }
+
+ free(pevent->events);
+ free(pevent->sort_events);
+
+ free(pevent);
+}
+
+void pevent_unref(struct pevent *pevent)
+{
+ pevent_free(pevent);
+}
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
new file mode 100644
index 000000000000..ac997bc7b592
--- /dev/null
+++ b/tools/lib/traceevent/event-parse.h
@@ -0,0 +1,804 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#ifndef _PARSE_EVENTS_H
+#define _PARSE_EVENTS_H
+
+#include <stdarg.h>
+#include <regex.h>
+
+#ifndef __unused
+#define __unused __attribute__ ((unused))
+#endif
+
+/* ----------------------- trace_seq ----------------------- */
+
+
+#ifndef TRACE_SEQ_BUF_SIZE
+#define TRACE_SEQ_BUF_SIZE 4096
+#endif
+
+#ifndef DEBUG_RECORD
+#define DEBUG_RECORD 0
+#endif
+
+struct pevent_record {
+ unsigned long long ts;
+ unsigned long long offset;
+ long long missed_events; /* buffer dropped events before */
+ int record_size; /* size of binary record */
+ int size; /* size of data */
+ void *data;
+ int cpu;
+ int ref_count;
+ int locked; /* Do not free, even if ref_count is zero */
+ void *private;
+#if DEBUG_RECORD
+ struct pevent_record *prev;
+ struct pevent_record *next;
+ long alloc_addr;
+#endif
+};
+
+/*
+ * Trace sequences are used to allow a function to call several other functions
+ * to create a string of data to use (up to a max of PAGE_SIZE).
+ */
+
+struct trace_seq {
+ char *buffer;
+ unsigned int buffer_size;
+ unsigned int len;
+ unsigned int readpos;
+};
+
+void trace_seq_init(struct trace_seq *s);
+void trace_seq_destroy(struct trace_seq *s);
+
+extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
+ __attribute__ ((format (printf, 2, 0)));
+
+extern int trace_seq_puts(struct trace_seq *s, const char *str);
+extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
+
+extern void trace_seq_terminate(struct trace_seq *s);
+
+extern int trace_seq_do_printf(struct trace_seq *s);
+
+
+/* ----------------------- pevent ----------------------- */
+
+struct pevent;
+struct event_format;
+
+typedef int (*pevent_event_handler_func)(struct trace_seq *s,
+ struct pevent_record *record,
+ struct event_format *event,
+ void *context);
+
+typedef int (*pevent_plugin_load_func)(struct pevent *pevent);
+typedef int (*pevent_plugin_unload_func)(void);
+
+struct plugin_option {
+ struct plugin_option *next;
+ void *handle;
+ char *file;
+ char *name;
+ char *plugin_alias;
+ char *description;
+ char *value;
+ void *private;
+ int set;
+};
+
+/*
+ * Plugin hooks that can be called:
+ *
+ * PEVENT_PLUGIN_LOADER: (required)
+ * The function name to initialized the plugin.
+ *
+ * int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+ *
+ * PEVENT_PLUGIN_UNLOADER: (optional)
+ * The function called just before unloading
+ *
+ * int PEVENT_PLUGIN_UNLOADER(void)
+ *
+ * PEVENT_PLUGIN_OPTIONS: (optional)
+ * Plugin options that can be set before loading
+ *
+ * struct plugin_option PEVENT_PLUGIN_OPTIONS[] = {
+ * {
+ * .name = "option-name",
+ * .plugin_alias = "overide-file-name", (optional)
+ * .description = "description of option to show users",
+ * },
+ * {
+ * .name = NULL,
+ * },
+ * };
+ *
+ * Array must end with .name = NULL;
+ *
+ *
+ * .plugin_alias is used to give a shorter name to access
+ * the vairable. Useful if a plugin handles more than one event.
+ *
+ * PEVENT_PLUGIN_ALIAS: (optional)
+ * The name to use for finding options (uses filename if not defined)
+ */
+#define PEVENT_PLUGIN_LOADER pevent_plugin_loader
+#define PEVENT_PLUGIN_UNLOADER pevent_plugin_unloader
+#define PEVENT_PLUGIN_OPTIONS pevent_plugin_options
+#define PEVENT_PLUGIN_ALIAS pevent_plugin_alias
+#define _MAKE_STR(x) #x
+#define MAKE_STR(x) _MAKE_STR(x)
+#define PEVENT_PLUGIN_LOADER_NAME MAKE_STR(PEVENT_PLUGIN_LOADER)
+#define PEVENT_PLUGIN_UNLOADER_NAME MAKE_STR(PEVENT_PLUGIN_UNLOADER)
+#define PEVENT_PLUGIN_OPTIONS_NAME MAKE_STR(PEVENT_PLUGIN_OPTIONS)
+#define PEVENT_PLUGIN_ALIAS_NAME MAKE_STR(PEVENT_PLUGIN_ALIAS)
+
+#define NSECS_PER_SEC 1000000000ULL
+#define NSECS_PER_USEC 1000ULL
+
+enum format_flags {
+ FIELD_IS_ARRAY = 1,
+ FIELD_IS_POINTER = 2,
+ FIELD_IS_SIGNED = 4,
+ FIELD_IS_STRING = 8,
+ FIELD_IS_DYNAMIC = 16,
+ FIELD_IS_LONG = 32,
+ FIELD_IS_FLAG = 64,
+ FIELD_IS_SYMBOLIC = 128,
+};
+
+struct format_field {
+ struct format_field *next;
+ struct event_format *event;
+ char *type;
+ char *name;
+ int offset;
+ int size;
+ unsigned int arraylen;
+ unsigned int elementsize;
+ unsigned long flags;
+};
+
+struct format {
+ int nr_common;
+ int nr_fields;
+ struct format_field *common_fields;
+ struct format_field *fields;
+};
+
+struct print_arg_atom {
+ char *atom;
+};
+
+struct print_arg_string {
+ char *string;
+ int offset;
+};
+
+struct print_arg_field {
+ char *name;
+ struct format_field *field;
+};
+
+struct print_flag_sym {
+ struct print_flag_sym *next;
+ char *value;
+ char *str;
+};
+
+struct print_arg_typecast {
+ char *type;
+ struct print_arg *item;
+};
+
+struct print_arg_flags {
+ struct print_arg *field;
+ char *delim;
+ struct print_flag_sym *flags;
+};
+
+struct print_arg_symbol {
+ struct print_arg *field;
+ struct print_flag_sym *symbols;
+};
+
+struct print_arg_dynarray {
+ struct format_field *field;
+ struct print_arg *index;
+};
+
+struct print_arg;
+
+struct print_arg_op {
+ char *op;
+ int prio;
+ struct print_arg *left;
+ struct print_arg *right;
+};
+
+struct pevent_function_handler;
+
+struct print_arg_func {
+ struct pevent_function_handler *func;
+ struct print_arg *args;
+};
+
+enum print_arg_type {
+ PRINT_NULL,
+ PRINT_ATOM,
+ PRINT_FIELD,
+ PRINT_FLAGS,
+ PRINT_SYMBOL,
+ PRINT_TYPE,
+ PRINT_STRING,
+ PRINT_BSTRING,
+ PRINT_DYNAMIC_ARRAY,
+ PRINT_OP,
+ PRINT_FUNC,
+};
+
+struct print_arg {
+ struct print_arg *next;
+ enum print_arg_type type;
+ union {
+ struct print_arg_atom atom;
+ struct print_arg_field field;
+ struct print_arg_typecast typecast;
+ struct print_arg_flags flags;
+ struct print_arg_symbol symbol;
+ struct print_arg_func func;
+ struct print_arg_string string;
+ struct print_arg_op op;
+ struct print_arg_dynarray dynarray;
+ };
+};
+
+struct print_fmt {
+ char *format;
+ struct print_arg *args;
+};
+
+struct event_format {
+ struct pevent *pevent;
+ char *name;
+ int id;
+ int flags;
+ struct format format;
+ struct print_fmt print_fmt;
+ char *system;
+ pevent_event_handler_func handler;
+ void *context;
+};
+
+enum {
+ EVENT_FL_ISFTRACE = 0x01,
+ EVENT_FL_ISPRINT = 0x02,
+ EVENT_FL_ISBPRINT = 0x04,
+ EVENT_FL_ISFUNCENT = 0x10,
+ EVENT_FL_ISFUNCRET = 0x20,
+
+ EVENT_FL_FAILED = 0x80000000
+};
+
+enum event_sort_type {
+ EVENT_SORT_ID,
+ EVENT_SORT_NAME,
+ EVENT_SORT_SYSTEM,
+};
+
+enum event_type {
+ EVENT_ERROR,
+ EVENT_NONE,
+ EVENT_SPACE,
+ EVENT_NEWLINE,
+ EVENT_OP,
+ EVENT_DELIM,
+ EVENT_ITEM,
+ EVENT_DQUOTE,
+ EVENT_SQUOTE,
+};
+
+typedef unsigned long long (*pevent_func_handler)(struct trace_seq *s,
+ unsigned long long *args);
+
+enum pevent_func_arg_type {
+ PEVENT_FUNC_ARG_VOID,
+ PEVENT_FUNC_ARG_INT,
+ PEVENT_FUNC_ARG_LONG,
+ PEVENT_FUNC_ARG_STRING,
+ PEVENT_FUNC_ARG_PTR,
+ PEVENT_FUNC_ARG_MAX_TYPES
+};
+
+enum pevent_flag {
+ PEVENT_NSEC_OUTPUT = 1, /* output in NSECS */
+};
+
+struct cmdline;
+struct cmdline_list;
+struct func_map;
+struct func_list;
+struct event_handler;
+
+struct pevent {
+ int ref_count;
+
+ int header_page_ts_offset;
+ int header_page_ts_size;
+ int header_page_size_offset;
+ int header_page_size_size;
+ int header_page_data_offset;
+ int header_page_data_size;
+ int header_page_overwrite;
+
+ int file_bigendian;
+ int host_bigendian;
+
+ int latency_format;
+
+ int old_format;
+
+ int cpus;
+ int long_size;
+
+ struct cmdline *cmdlines;
+ struct cmdline_list *cmdlist;
+ int cmdline_count;
+
+ struct func_map *func_map;
+ struct func_list *funclist;
+ unsigned int func_count;
+
+ struct printk_map *printk_map;
+ struct printk_list *printklist;
+ unsigned int printk_count;
+
+
+ struct event_format **events;
+ int nr_events;
+ struct event_format **sort_events;
+ enum event_sort_type last_type;
+
+ int type_offset;
+ int type_size;
+
+ int pid_offset;
+ int pid_size;
+
+ int pc_offset;
+ int pc_size;
+
+ int flags_offset;
+ int flags_size;
+
+ int ld_offset;
+ int ld_size;
+
+ int print_raw;
+
+ int test_filters;
+
+ int flags;
+
+ struct format_field *bprint_ip_field;
+ struct format_field *bprint_fmt_field;
+ struct format_field *bprint_buf_field;
+
+ struct event_handler *handlers;
+ struct pevent_function_handler *func_handlers;
+
+ /* cache */
+ struct event_format *last_event;
+};
+
+static inline void pevent_set_flag(struct pevent *pevent, int flag)
+{
+ pevent->flags |= flag;
+}
+
+static inline unsigned short
+__data2host2(struct pevent *pevent, unsigned short data)
+{
+ unsigned short swap;
+
+ if (pevent->host_bigendian == pevent->file_bigendian)
+ return data;
+
+ swap = ((data & 0xffULL) << 8) |
+ ((data & (0xffULL << 8)) >> 8);
+
+ return swap;
+}
+
+static inline unsigned int
+__data2host4(struct pevent *pevent, unsigned int data)
+{
+ unsigned int swap;
+
+ if (pevent->host_bigendian == pevent->file_bigendian)
+ return data;
+
+ swap = ((data & 0xffULL) << 24) |
+ ((data & (0xffULL << 8)) << 8) |
+ ((data & (0xffULL << 16)) >> 8) |
+ ((data & (0xffULL << 24)) >> 24);
+
+ return swap;
+}
+
+static inline unsigned long long
+__data2host8(struct pevent *pevent, unsigned long long data)
+{
+ unsigned long long swap;
+
+ if (pevent->host_bigendian == pevent->file_bigendian)
+ return data;
+
+ swap = ((data & 0xffULL) << 56) |
+ ((data & (0xffULL << 8)) << 40) |
+ ((data & (0xffULL << 16)) << 24) |
+ ((data & (0xffULL << 24)) << 8) |
+ ((data & (0xffULL << 32)) >> 8) |
+ ((data & (0xffULL << 40)) >> 24) |
+ ((data & (0xffULL << 48)) >> 40) |
+ ((data & (0xffULL << 56)) >> 56);
+
+ return swap;
+}
+
+#define data2host2(pevent, ptr) __data2host2(pevent, *(unsigned short *)(ptr))
+#define data2host4(pevent, ptr) __data2host4(pevent, *(unsigned int *)(ptr))
+#define data2host8(pevent, ptr) \
+({ \
+ unsigned long long __val; \
+ \
+ memcpy(&__val, (ptr), sizeof(unsigned long long)); \
+ __data2host8(pevent, __val); \
+})
+
+/* taken from kernel/trace/trace.h */
+enum trace_flag_type {
+ TRACE_FLAG_IRQS_OFF = 0x01,
+ TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
+ TRACE_FLAG_NEED_RESCHED = 0x04,
+ TRACE_FLAG_HARDIRQ = 0x08,
+ TRACE_FLAG_SOFTIRQ = 0x10,
+};
+
+int pevent_register_comm(struct pevent *pevent, const char *comm, int pid);
+int pevent_register_function(struct pevent *pevent, char *name,
+ unsigned long long addr, char *mod);
+int pevent_register_print_string(struct pevent *pevent, char *fmt,
+ unsigned long long addr);
+int pevent_pid_is_registered(struct pevent *pevent, int pid);
+
+void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
+ struct pevent_record *record);
+
+int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
+ int long_size);
+
+int pevent_parse_event(struct pevent *pevent, const char *buf,
+ unsigned long size, const char *sys);
+
+void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ int *len, int err);
+
+int pevent_get_field_val(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err);
+int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err);
+int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err);
+
+int pevent_print_num_field(struct trace_seq *s, const char *fmt,
+ struct event_format *event, const char *name,
+ struct pevent_record *record, int err);
+
+int pevent_register_event_handler(struct pevent *pevent, int id, char *sys_name, char *event_name,
+ pevent_event_handler_func func, void *context);
+int pevent_register_print_function(struct pevent *pevent,
+ pevent_func_handler func,
+ enum pevent_func_arg_type ret_type,
+ char *name, ...);
+
+struct format_field *pevent_find_common_field(struct event_format *event, const char *name);
+struct format_field *pevent_find_field(struct event_format *event, const char *name);
+struct format_field *pevent_find_any_field(struct event_format *event, const char *name);
+
+const char *pevent_find_function(struct pevent *pevent, unsigned long long addr);
+unsigned long long
+pevent_find_function_address(struct pevent *pevent, unsigned long long addr);
+unsigned long long pevent_read_number(struct pevent *pevent, const void *ptr, int size);
+int pevent_read_number_field(struct format_field *field, const void *data,
+ unsigned long long *value);
+
+struct event_format *pevent_find_event(struct pevent *pevent, int id);
+
+struct event_format *
+pevent_find_event_by_name(struct pevent *pevent, const char *sys, const char *name);
+
+void pevent_data_lat_fmt(struct pevent *pevent,
+ struct trace_seq *s, struct pevent_record *record);
+int pevent_data_type(struct pevent *pevent, struct pevent_record *rec);
+struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type);
+int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec);
+const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid);
+void pevent_event_info(struct trace_seq *s, struct event_format *event,
+ struct pevent_record *record);
+
+struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type);
+struct format_field **pevent_event_common_fields(struct event_format *event);
+struct format_field **pevent_event_fields(struct event_format *event);
+
+static inline int pevent_get_cpus(struct pevent *pevent)
+{
+ return pevent->cpus;
+}
+
+static inline void pevent_set_cpus(struct pevent *pevent, int cpus)
+{
+ pevent->cpus = cpus;
+}
+
+static inline int pevent_get_long_size(struct pevent *pevent)
+{
+ return pevent->long_size;
+}
+
+static inline void pevent_set_long_size(struct pevent *pevent, int long_size)
+{
+ pevent->long_size = long_size;
+}
+
+static inline int pevent_is_file_bigendian(struct pevent *pevent)
+{
+ return pevent->file_bigendian;
+}
+
+static inline void pevent_set_file_bigendian(struct pevent *pevent, int endian)
+{
+ pevent->file_bigendian = endian;
+}
+
+static inline int pevent_is_host_bigendian(struct pevent *pevent)
+{
+ return pevent->host_bigendian;
+}
+
+static inline void pevent_set_host_bigendian(struct pevent *pevent, int endian)
+{
+ pevent->host_bigendian = endian;
+}
+
+static inline int pevent_is_latency_format(struct pevent *pevent)
+{
+ return pevent->latency_format;
+}
+
+static inline void pevent_set_latency_format(struct pevent *pevent, int lat)
+{
+ pevent->latency_format = lat;
+}
+
+struct pevent *pevent_alloc(void);
+void pevent_free(struct pevent *pevent);
+void pevent_ref(struct pevent *pevent);
+void pevent_unref(struct pevent *pevent);
+
+/* access to the internal parser */
+void pevent_buffer_init(const char *buf, unsigned long long size);
+enum event_type pevent_read_token(char **tok);
+void pevent_free_token(char *token);
+int pevent_peek_char(void);
+const char *pevent_get_input_buf(void);
+unsigned long long pevent_get_input_buf_ptr(void);
+
+/* for debugging */
+void pevent_print_funcs(struct pevent *pevent);
+void pevent_print_printk(struct pevent *pevent);
+
+/* ----------------------- filtering ----------------------- */
+
+enum filter_boolean_type {
+ FILTER_FALSE,
+ FILTER_TRUE,
+};
+
+enum filter_op_type {
+ FILTER_OP_AND = 1,
+ FILTER_OP_OR,
+ FILTER_OP_NOT,
+};
+
+enum filter_cmp_type {
+ FILTER_CMP_NONE,
+ FILTER_CMP_EQ,
+ FILTER_CMP_NE,
+ FILTER_CMP_GT,
+ FILTER_CMP_LT,
+ FILTER_CMP_GE,
+ FILTER_CMP_LE,
+ FILTER_CMP_MATCH,
+ FILTER_CMP_NOT_MATCH,
+ FILTER_CMP_REGEX,
+ FILTER_CMP_NOT_REGEX,
+};
+
+enum filter_exp_type {
+ FILTER_EXP_NONE,
+ FILTER_EXP_ADD,
+ FILTER_EXP_SUB,
+ FILTER_EXP_MUL,
+ FILTER_EXP_DIV,
+ FILTER_EXP_MOD,
+ FILTER_EXP_RSHIFT,
+ FILTER_EXP_LSHIFT,
+ FILTER_EXP_AND,
+ FILTER_EXP_OR,
+ FILTER_EXP_XOR,
+ FILTER_EXP_NOT,
+};
+
+enum filter_arg_type {
+ FILTER_ARG_NONE,
+ FILTER_ARG_BOOLEAN,
+ FILTER_ARG_VALUE,
+ FILTER_ARG_FIELD,
+ FILTER_ARG_EXP,
+ FILTER_ARG_OP,
+ FILTER_ARG_NUM,
+ FILTER_ARG_STR,
+};
+
+enum filter_value_type {
+ FILTER_NUMBER,
+ FILTER_STRING,
+ FILTER_CHAR
+};
+
+struct fliter_arg;
+
+struct filter_arg_boolean {
+ enum filter_boolean_type value;
+};
+
+struct filter_arg_field {
+ struct format_field *field;
+};
+
+struct filter_arg_value {
+ enum filter_value_type type;
+ union {
+ char *str;
+ unsigned long long val;
+ };
+};
+
+struct filter_arg_op {
+ enum filter_op_type type;
+ struct filter_arg *left;
+ struct filter_arg *right;
+};
+
+struct filter_arg_exp {
+ enum filter_exp_type type;
+ struct filter_arg *left;
+ struct filter_arg *right;
+};
+
+struct filter_arg_num {
+ enum filter_cmp_type type;
+ struct filter_arg *left;
+ struct filter_arg *right;
+};
+
+struct filter_arg_str {
+ enum filter_cmp_type type;
+ struct format_field *field;
+ char *val;
+ char *buffer;
+ regex_t reg;
+};
+
+struct filter_arg {
+ enum filter_arg_type type;
+ union {
+ struct filter_arg_boolean boolean;
+ struct filter_arg_field field;
+ struct filter_arg_value value;
+ struct filter_arg_op op;
+ struct filter_arg_exp exp;
+ struct filter_arg_num num;
+ struct filter_arg_str str;
+ };
+};
+
+struct filter_type {
+ int event_id;
+ struct event_format *event;
+ struct filter_arg *filter;
+};
+
+struct event_filter {
+ struct pevent *pevent;
+ int filters;
+ struct filter_type *event_filters;
+};
+
+struct event_filter *pevent_filter_alloc(struct pevent *pevent);
+
+#define FILTER_NONE -2
+#define FILTER_NOEXIST -1
+#define FILTER_MISS 0
+#define FILTER_MATCH 1
+
+enum filter_trivial_type {
+ FILTER_TRIVIAL_FALSE,
+ FILTER_TRIVIAL_TRUE,
+ FILTER_TRIVIAL_BOTH,
+};
+
+int pevent_filter_add_filter_str(struct event_filter *filter,
+ const char *filter_str,
+ char **error_str);
+
+
+int pevent_filter_match(struct event_filter *filter,
+ struct pevent_record *record);
+
+int pevent_event_filtered(struct event_filter *filter,
+ int event_id);
+
+void pevent_filter_reset(struct event_filter *filter);
+
+void pevent_filter_clear_trivial(struct event_filter *filter,
+ enum filter_trivial_type type);
+
+void pevent_filter_free(struct event_filter *filter);
+
+char *pevent_filter_make_string(struct event_filter *filter, int event_id);
+
+int pevent_filter_remove_event(struct event_filter *filter,
+ int event_id);
+
+int pevent_filter_event_has_trivial(struct event_filter *filter,
+ int event_id,
+ enum filter_trivial_type type);
+
+int pevent_filter_copy(struct event_filter *dest, struct event_filter *source);
+
+int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
+ enum filter_trivial_type type);
+
+int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2);
+
+#endif /* _PARSE_EVENTS_H */
diff --git a/tools/lib/traceevent/event-utils.h b/tools/lib/traceevent/event-utils.h
new file mode 100644
index 000000000000..08296383d1e6
--- /dev/null
+++ b/tools/lib/traceevent/event-utils.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#ifndef __UTIL_H
+#define __UTIL_H
+
+#include <ctype.h>
+
+/* Can be overridden */
+void die(const char *fmt, ...);
+void *malloc_or_die(unsigned int size);
+void warning(const char *fmt, ...);
+void pr_stat(const char *fmt, ...);
+void vpr_stat(const char *fmt, va_list ap);
+
+/* Always available */
+void __die(const char *fmt, ...);
+void __warning(const char *fmt, ...);
+void __pr_stat(const char *fmt, ...);
+
+void __vdie(const char *fmt, ...);
+void __vwarning(const char *fmt, ...);
+void __vpr_stat(const char *fmt, ...);
+
+static inline char *strim(char *string)
+{
+ char *ret;
+
+ if (!string)
+ return NULL;
+ while (*string) {
+ if (!isspace(*string))
+ break;
+ string++;
+ }
+ ret = string;
+
+ string = ret + strlen(ret) - 1;
+ while (string > ret) {
+ if (!isspace(*string))
+ break;
+ string--;
+ }
+ string[1] = 0;
+
+ return ret;
+}
+
+static inline int has_text(const char *text)
+{
+ if (!text)
+ return 0;
+
+ while (*text) {
+ if (!isspace(*text))
+ return 1;
+ text++;
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
new file mode 100644
index 000000000000..2d40c5ed81d6
--- /dev/null
+++ b/tools/lib/traceevent/parse-filter.c
@@ -0,0 +1,2262 @@
+/*
+ * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include "event-parse.h"
+#include "event-utils.h"
+
+#define COMM "COMM"
+
+static struct format_field comm = {
+ .name = "COMM",
+};
+
+struct event_list {
+ struct event_list *next;
+ struct event_format *event;
+};
+
+#define MAX_ERR_STR_SIZE 256
+
+static void show_error(char **error_str, const char *fmt, ...)
+{
+ unsigned long long index;
+ const char *input;
+ char *error;
+ va_list ap;
+ int len;
+ int i;
+
+ if (!error_str)
+ return;
+
+ input = pevent_get_input_buf();
+ index = pevent_get_input_buf_ptr();
+ len = input ? strlen(input) : 0;
+
+ error = malloc_or_die(MAX_ERR_STR_SIZE + (len*2) + 3);
+
+ if (len) {
+ strcpy(error, input);
+ error[len] = '\n';
+ for (i = 1; i < len && i < index; i++)
+ error[len+i] = ' ';
+ error[len + i] = '^';
+ error[len + i + 1] = '\n';
+ len += i+2;
+ }
+
+ va_start(ap, fmt);
+ vsnprintf(error + len, MAX_ERR_STR_SIZE, fmt, ap);
+ va_end(ap);
+
+ *error_str = error;
+}
+
+static void free_token(char *token)
+{
+ pevent_free_token(token);
+}
+
+static enum event_type read_token(char **tok)
+{
+ enum event_type type;
+ char *token = NULL;
+
+ do {
+ free_token(token);
+ type = pevent_read_token(&token);
+ } while (type == EVENT_NEWLINE || type == EVENT_SPACE);
+
+ /* If token is = or ! check to see if the next char is ~ */
+ if (token &&
+ (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
+ pevent_peek_char() == '~') {
+ /* append it */
+ *tok = malloc(3);
+ sprintf(*tok, "%c%c", *token, '~');
+ free_token(token);
+ /* Now remove the '~' from the buffer */
+ pevent_read_token(&token);
+ free_token(token);
+ } else
+ *tok = token;
+
+ return type;
+}
+
+static int filter_cmp(const void *a, const void *b)
+{
+ const struct filter_type *ea = a;
+ const struct filter_type *eb = b;
+
+ if (ea->event_id < eb->event_id)
+ return -1;
+
+ if (ea->event_id > eb->event_id)
+ return 1;
+
+ return 0;
+}
+
+static struct filter_type *
+find_filter_type(struct event_filter *filter, int id)
+{
+ struct filter_type *filter_type;
+ struct filter_type key;
+
+ key.event_id = id;
+
+ filter_type = bsearch(&key, filter->event_filters,
+ filter->filters,
+ sizeof(*filter->event_filters),
+ filter_cmp);
+
+ return filter_type;
+}
+
+static struct filter_type *
+add_filter_type(struct event_filter *filter, int id)
+{
+ struct filter_type *filter_type;
+ int i;
+
+ filter_type = find_filter_type(filter, id);
+ if (filter_type)
+ return filter_type;
+
+ if (!filter->filters)
+ filter->event_filters =
+ malloc_or_die(sizeof(*filter->event_filters));
+ else {
+ filter->event_filters =
+ realloc(filter->event_filters,
+ sizeof(*filter->event_filters) *
+ (filter->filters + 1));
+ if (!filter->event_filters)
+ die("Could not allocate filter");
+ }
+
+ for (i = 0; i < filter->filters; i++) {
+ if (filter->event_filters[i].event_id > id)
+ break;
+ }
+
+ if (i < filter->filters)
+ memmove(&filter->event_filters[i+1],
+ &filter->event_filters[i],
+ sizeof(*filter->event_filters) *
+ (filter->filters - i));
+
+ filter_type = &filter->event_filters[i];
+ filter_type->event_id = id;
+ filter_type->event = pevent_find_event(filter->pevent, id);
+ filter_type->filter = NULL;
+
+ filter->filters++;
+
+ return filter_type;
+}
+
+/**
+ * pevent_filter_alloc - create a new event filter
+ * @pevent: The pevent that this filter is associated with
+ */
+struct event_filter *pevent_filter_alloc(struct pevent *pevent)
+{
+ struct event_filter *filter;
+
+ filter = malloc_or_die(sizeof(*filter));
+ memset(filter, 0, sizeof(*filter));
+ filter->pevent = pevent;
+ pevent_ref(pevent);
+
+ return filter;
+}
+
+static struct filter_arg *allocate_arg(void)
+{
+ struct filter_arg *arg;
+
+ arg = malloc_or_die(sizeof(*arg));
+ memset(arg, 0, sizeof(*arg));
+
+ return arg;
+}
+
+static void free_arg(struct filter_arg *arg)
+{
+ if (!arg)
+ return;
+
+ switch (arg->type) {
+ case FILTER_ARG_NONE:
+ case FILTER_ARG_BOOLEAN:
+ case FILTER_ARG_NUM:
+ break;
+
+ case FILTER_ARG_STR:
+ free(arg->str.val);
+ regfree(&arg->str.reg);
+ free(arg->str.buffer);
+ break;
+
+ case FILTER_ARG_OP:
+ free_arg(arg->op.left);
+ free_arg(arg->op.right);
+ default:
+ break;
+ }
+
+ free(arg);
+}
+
+static void add_event(struct event_list **events,
+ struct event_format *event)
+{
+ struct event_list *list;
+
+ list = malloc_or_die(sizeof(*list));
+ list->next = *events;
+ *events = list;
+ list->event = event;
+}
+
+static int event_match(struct event_format *event,
+ regex_t *sreg, regex_t *ereg)
+{
+ if (sreg) {
+ return !regexec(sreg, event->system, 0, NULL, 0) &&
+ !regexec(ereg, event->name, 0, NULL, 0);
+ }
+
+ return !regexec(ereg, event->system, 0, NULL, 0) ||
+ !regexec(ereg, event->name, 0, NULL, 0);
+}
+
+static int
+find_event(struct pevent *pevent, struct event_list **events,
+ char *sys_name, char *event_name)
+{
+ struct event_format *event;
+ regex_t ereg;
+ regex_t sreg;
+ int match = 0;
+ char *reg;
+ int ret;
+ int i;
+
+ if (!event_name) {
+ /* if no name is given, then swap sys and name */
+ event_name = sys_name;
+ sys_name = NULL;
+ }
+
+ reg = malloc_or_die(strlen(event_name) + 3);
+ sprintf(reg, "^%s$", event_name);
+
+ ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
+ free(reg);
+
+ if (ret)
+ return -1;
+
+ if (sys_name) {
+ reg = malloc_or_die(strlen(sys_name) + 3);
+ sprintf(reg, "^%s$", sys_name);
+ ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
+ free(reg);
+ if (ret) {
+ regfree(&ereg);
+ return -1;
+ }
+ }
+
+ for (i = 0; i < pevent->nr_events; i++) {
+ event = pevent->events[i];
+ if (event_match(event, sys_name ? &sreg : NULL, &ereg)) {
+ match = 1;
+ add_event(events, event);
+ }
+ }
+
+ regfree(&ereg);
+ if (sys_name)
+ regfree(&sreg);
+
+ if (!match)
+ return -1;
+
+ return 0;
+}
+
+static void free_events(struct event_list *events)
+{
+ struct event_list *event;
+
+ while (events) {
+ event = events;
+ events = events->next;
+ free(event);
+ }
+}
+
+static struct filter_arg *
+create_arg_item(struct event_format *event,
+ const char *token, enum filter_arg_type type,
+ char **error_str)
+{
+ struct format_field *field;
+ struct filter_arg *arg;
+
+ arg = allocate_arg();
+
+ switch (type) {
+
+ case EVENT_SQUOTE:
+ case EVENT_DQUOTE:
+ arg->type = FILTER_ARG_VALUE;
+ arg->value.type =
+ type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR;
+ arg->value.str = strdup(token);
+ if (!arg->value.str)
+ die("malloc string");
+ break;
+ case EVENT_ITEM:
+ /* if it is a number, then convert it */
+ if (isdigit(token[0])) {
+ arg->type = FILTER_ARG_VALUE;
+ arg->value.type = FILTER_NUMBER;
+ arg->value.val = strtoull(token, NULL, 0);
+ break;
+ }
+ /* Consider this a field */
+ field = pevent_find_any_field(event, token);
+ if (!field) {
+ if (strcmp(token, COMM) != 0) {
+ /* not a field, Make it false */
+ arg->type = FILTER_ARG_BOOLEAN;
+ arg->boolean.value = FILTER_FALSE;
+ break;
+ }
+ /* If token is 'COMM' then it is special */
+ field = &comm;
+ }
+ arg->type = FILTER_ARG_FIELD;
+ arg->field.field = field;
+ break;
+ default:
+ free_arg(arg);
+ show_error(error_str, "expected a value but found %s",
+ token);
+ return NULL;
+ }
+ return arg;
+}
+
+static struct filter_arg *
+create_arg_op(enum filter_op_type btype)
+{
+ struct filter_arg *arg;
+
+ arg = allocate_arg();
+ arg->type = FILTER_ARG_OP;
+ arg->op.type = btype;
+
+ return arg;
+}
+
+static struct filter_arg *
+create_arg_exp(enum filter_exp_type etype)
+{
+ struct filter_arg *arg;
+
+ arg = allocate_arg();
+ arg->type = FILTER_ARG_EXP;
+ arg->op.type = etype;
+
+ return arg;
+}
+
+static struct filter_arg *
+create_arg_cmp(enum filter_exp_type etype)
+{
+ struct filter_arg *arg;
+
+ arg = allocate_arg();
+ /* Use NUM and change if necessary */
+ arg->type = FILTER_ARG_NUM;
+ arg->op.type = etype;
+
+ return arg;
+}
+
+static int add_right(struct filter_arg *op, struct filter_arg *arg,
+ char **error_str)
+{
+ struct filter_arg *left;
+ char *str;
+ int op_type;
+ int ret;
+
+ switch (op->type) {
+ case FILTER_ARG_EXP:
+ if (op->exp.right)
+ goto out_fail;
+ op->exp.right = arg;
+ break;
+
+ case FILTER_ARG_OP:
+ if (op->op.right)
+ goto out_fail;
+ op->op.right = arg;
+ break;
+
+ case FILTER_ARG_NUM:
+ if (op->op.right)
+ goto out_fail;
+ /*
+ * The arg must be num, str, or field
+ */
+ switch (arg->type) {
+ case FILTER_ARG_VALUE:
+ case FILTER_ARG_FIELD:
+ break;
+ default:
+ show_error(error_str,
+ "Illegal rvalue");
+ return -1;
+ }
+
+ /*
+ * Depending on the type, we may need to
+ * convert this to a string or regex.
+ */
+ switch (arg->value.type) {
+ case FILTER_CHAR:
+ /*
+ * A char should be converted to number if
+ * the string is 1 byte, and the compare
+ * is not a REGEX.
+ */
+ if (strlen(arg->value.str) == 1 &&
+ op->num.type != FILTER_CMP_REGEX &&
+ op->num.type != FILTER_CMP_NOT_REGEX) {
+ arg->value.type = FILTER_NUMBER;
+ goto do_int;
+ }
+ /* fall through */
+ case FILTER_STRING:
+
+ /* convert op to a string arg */
+ op_type = op->num.type;
+ left = op->num.left;
+ str = arg->value.str;
+
+ /* reset the op for the new field */
+ memset(op, 0, sizeof(*op));
+
+ /*
+ * If left arg was a field not found then
+ * NULL the entire op.
+ */
+ if (left->type == FILTER_ARG_BOOLEAN) {
+ free_arg(left);
+ free_arg(arg);
+ op->type = FILTER_ARG_BOOLEAN;
+ op->boolean.value = FILTER_FALSE;
+ break;
+ }
+
+ /* Left arg must be a field */
+ if (left->type != FILTER_ARG_FIELD) {
+ show_error(error_str,
+ "Illegal lvalue for string comparison");
+ return -1;
+ }
+
+ /* Make sure this is a valid string compare */
+ switch (op_type) {
+ case FILTER_CMP_EQ:
+ op_type = FILTER_CMP_MATCH;
+ break;
+ case FILTER_CMP_NE:
+ op_type = FILTER_CMP_NOT_MATCH;
+ break;
+
+ case FILTER_CMP_REGEX:
+ case FILTER_CMP_NOT_REGEX:
+ ret = regcomp(&op->str.reg, str, REG_ICASE|REG_NOSUB);
+ if (ret) {
+ show_error(error_str,
+ "RegEx '%s' did not compute",
+ str);
+ return -1;
+ }
+ break;
+ default:
+ show_error(error_str,
+ "Illegal comparison for string");
+ return -1;
+ }
+
+ op->type = FILTER_ARG_STR;
+ op->str.type = op_type;
+ op->str.field = left->field.field;
+ op->str.val = strdup(str);
+ if (!op->str.val)
+ die("malloc string");
+ /*
+ * Need a buffer to copy data for tests
+ */
+ op->str.buffer = malloc_or_die(op->str.field->size + 1);
+ /* Null terminate this buffer */
+ op->str.buffer[op->str.field->size] = 0;
+
+ /* We no longer have left or right args */
+ free_arg(arg);
+ free_arg(left);
+
+ break;
+
+ case FILTER_NUMBER:
+
+ do_int:
+ switch (op->num.type) {
+ case FILTER_CMP_REGEX:
+ case FILTER_CMP_NOT_REGEX:
+ show_error(error_str,
+ "Op not allowed with integers");
+ return -1;
+
+ default:
+ break;
+ }
+
+ /* numeric compare */
+ op->num.right = arg;
+ break;
+ default:
+ goto out_fail;
+ }
+ break;
+ default:
+ goto out_fail;
+ }
+
+ return 0;
+
+ out_fail:
+ show_error(error_str,
+ "Syntax error");
+ return -1;
+}
+
+static struct filter_arg *
+rotate_op_right(struct filter_arg *a, struct filter_arg *b)
+{
+ struct filter_arg *arg;
+
+ arg = a->op.right;
+ a->op.right = b;
+ return arg;
+}
+
+static int add_left(struct filter_arg *op, struct filter_arg *arg)
+{
+ switch (op->type) {
+ case FILTER_ARG_EXP:
+ if (arg->type == FILTER_ARG_OP)
+ arg = rotate_op_right(arg, op);
+ op->exp.left = arg;
+ break;
+
+ case FILTER_ARG_OP:
+ op->op.left = arg;
+ break;
+ case FILTER_ARG_NUM:
+ if (arg->type == FILTER_ARG_OP)
+ arg = rotate_op_right(arg, op);
+
+ /* left arg of compares must be a field */
+ if (arg->type != FILTER_ARG_FIELD &&
+ arg->type != FILTER_ARG_BOOLEAN)
+ return -1;
+ op->num.left = arg;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+enum op_type {
+ OP_NONE,
+ OP_BOOL,
+ OP_NOT,
+ OP_EXP,
+ OP_CMP,
+};
+
+static enum op_type process_op(const char *token,
+ enum filter_op_type *btype,
+ enum filter_cmp_type *ctype,
+ enum filter_exp_type *etype)
+{
+ *btype = FILTER_OP_NOT;
+ *etype = FILTER_EXP_NONE;
+ *ctype = FILTER_CMP_NONE;
+
+ if (strcmp(token, "&&") == 0)
+ *btype = FILTER_OP_AND;
+ else if (strcmp(token, "||") == 0)
+ *btype = FILTER_OP_OR;
+ else if (strcmp(token, "!") == 0)
+ return OP_NOT;
+
+ if (*btype != FILTER_OP_NOT)
+ return OP_BOOL;
+
+ /* Check for value expressions */
+ if (strcmp(token, "+") == 0) {
+ *etype = FILTER_EXP_ADD;
+ } else if (strcmp(token, "-") == 0) {
+ *etype = FILTER_EXP_SUB;
+ } else if (strcmp(token, "*") == 0) {
+ *etype = FILTER_EXP_MUL;
+ } else if (strcmp(token, "/") == 0) {
+ *etype = FILTER_EXP_DIV;
+ } else if (strcmp(token, "%") == 0) {
+ *etype = FILTER_EXP_MOD;
+ } else if (strcmp(token, ">>") == 0) {
+ *etype = FILTER_EXP_RSHIFT;
+ } else if (strcmp(token, "<<") == 0) {
+ *etype = FILTER_EXP_LSHIFT;
+ } else if (strcmp(token, "&") == 0) {
+ *etype = FILTER_EXP_AND;
+ } else if (strcmp(token, "|") == 0) {
+ *etype = FILTER_EXP_OR;
+ } else if (strcmp(token, "^") == 0) {
+ *etype = FILTER_EXP_XOR;
+ } else if (strcmp(token, "~") == 0)
+ *etype = FILTER_EXP_NOT;
+
+ if (*etype != FILTER_EXP_NONE)
+ return OP_EXP;
+
+ /* Check for compares */
+ if (strcmp(token, "==") == 0)
+ *ctype = FILTER_CMP_EQ;
+ else if (strcmp(token, "!=") == 0)
+ *ctype = FILTER_CMP_NE;
+ else if (strcmp(token, "<") == 0)
+ *ctype = FILTER_CMP_LT;
+ else if (strcmp(token, ">") == 0)
+ *ctype = FILTER_CMP_GT;
+ else if (strcmp(token, "<=") == 0)
+ *ctype = FILTER_CMP_LE;
+ else if (strcmp(token, ">=") == 0)
+ *ctype = FILTER_CMP_GE;
+ else if (strcmp(token, "=~") == 0)
+ *ctype = FILTER_CMP_REGEX;
+ else if (strcmp(token, "!~") == 0)
+ *ctype = FILTER_CMP_NOT_REGEX;
+ else
+ return OP_NONE;
+
+ return OP_CMP;
+}
+
+static int check_op_done(struct filter_arg *arg)
+{
+ switch (arg->type) {
+ case FILTER_ARG_EXP:
+ return arg->exp.right != NULL;
+
+ case FILTER_ARG_OP:
+ return arg->op.right != NULL;
+
+ case FILTER_ARG_NUM:
+ return arg->num.right != NULL;
+
+ case FILTER_ARG_STR:
+ /* A string conversion is always done */
+ return 1;
+
+ case FILTER_ARG_BOOLEAN:
+ /* field not found, is ok */
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+enum filter_vals {
+ FILTER_VAL_NORM,
+ FILTER_VAL_FALSE,
+ FILTER_VAL_TRUE,
+};
+
+void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
+ struct filter_arg *arg)
+{
+ struct filter_arg *other_child;
+ struct filter_arg **ptr;
+
+ if (parent->type != FILTER_ARG_OP &&
+ arg->type != FILTER_ARG_OP)
+ die("can not reparent other than OP");
+
+ /* Get the sibling */
+ if (old_child->op.right == arg) {
+ ptr = &old_child->op.right;
+ other_child = old_child->op.left;
+ } else if (old_child->op.left == arg) {
+ ptr = &old_child->op.left;
+ other_child = old_child->op.right;
+ } else
+ die("Error in reparent op, find other child");
+
+ /* Detach arg from old_child */
+ *ptr = NULL;
+
+ /* Check for root */
+ if (parent == old_child) {
+ free_arg(other_child);
+ *parent = *arg;
+ /* Free arg without recussion */
+ free(arg);
+ return;
+ }
+
+ if (parent->op.right == old_child)
+ ptr = &parent->op.right;
+ else if (parent->op.left == old_child)
+ ptr = &parent->op.left;
+ else
+ die("Error in reparent op");
+ *ptr = arg;
+
+ free_arg(old_child);
+}
+
+enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg)
+{
+ enum filter_vals lval, rval;
+
+ switch (arg->type) {
+
+ /* bad case */
+ case FILTER_ARG_BOOLEAN:
+ return FILTER_VAL_FALSE + arg->boolean.value;
+
+ /* good cases: */
+ case FILTER_ARG_STR:
+ case FILTER_ARG_VALUE:
+ case FILTER_ARG_FIELD:
+ return FILTER_VAL_NORM;
+
+ case FILTER_ARG_EXP:
+ lval = test_arg(arg, arg->exp.left);
+ if (lval != FILTER_VAL_NORM)
+ return lval;
+ rval = test_arg(arg, arg->exp.right);
+ if (rval != FILTER_VAL_NORM)
+ return rval;
+ return FILTER_VAL_NORM;
+
+ case FILTER_ARG_NUM:
+ lval = test_arg(arg, arg->num.left);
+ if (lval != FILTER_VAL_NORM)
+ return lval;
+ rval = test_arg(arg, arg->num.right);
+ if (rval != FILTER_VAL_NORM)
+ return rval;
+ return FILTER_VAL_NORM;
+
+ case FILTER_ARG_OP:
+ if (arg->op.type != FILTER_OP_NOT) {
+ lval = test_arg(arg, arg->op.left);
+ switch (lval) {
+ case FILTER_VAL_NORM:
+ break;
+ case FILTER_VAL_TRUE:
+ if (arg->op.type == FILTER_OP_OR)
+ return FILTER_VAL_TRUE;
+ rval = test_arg(arg, arg->op.right);
+ if (rval != FILTER_VAL_NORM)
+ return rval;
+
+ reparent_op_arg(parent, arg, arg->op.right);
+ return FILTER_VAL_NORM;
+
+ case FILTER_VAL_FALSE:
+ if (arg->op.type == FILTER_OP_AND)
+ return FILTER_VAL_FALSE;
+ rval = test_arg(arg, arg->op.right);
+ if (rval != FILTER_VAL_NORM)
+ return rval;
+
+ reparent_op_arg(parent, arg, arg->op.right);
+ return FILTER_VAL_NORM;
+ }
+ }
+
+ rval = test_arg(arg, arg->op.right);
+ switch (rval) {
+ case FILTER_VAL_NORM:
+ break;
+ case FILTER_VAL_TRUE:
+ if (arg->op.type == FILTER_OP_OR)
+ return FILTER_VAL_TRUE;
+ if (arg->op.type == FILTER_OP_NOT)
+ return FILTER_VAL_FALSE;
+
+ reparent_op_arg(parent, arg, arg->op.left);
+ return FILTER_VAL_NORM;
+
+ case FILTER_VAL_FALSE:
+ if (arg->op.type == FILTER_OP_AND)
+ return FILTER_VAL_FALSE;
+ if (arg->op.type == FILTER_OP_NOT)
+ return FILTER_VAL_TRUE;
+
+ reparent_op_arg(parent, arg, arg->op.left);
+ return FILTER_VAL_NORM;
+ }
+
+ return FILTER_VAL_NORM;
+ default:
+ die("bad arg in filter tree");
+ }
+ return FILTER_VAL_NORM;
+}
+
+/* Remove any unknown event fields */
+static struct filter_arg *collapse_tree(struct filter_arg *arg)
+{
+ enum filter_vals ret;
+
+ ret = test_arg(arg, arg);
+ switch (ret) {
+ case FILTER_VAL_NORM:
+ return arg;
+
+ case FILTER_VAL_TRUE:
+ case FILTER_VAL_FALSE:
+ free_arg(arg);
+ arg = allocate_arg();
+ arg->type = FILTER_ARG_BOOLEAN;
+ arg->boolean.value = ret == FILTER_VAL_TRUE;
+ }
+
+ return arg;
+}
+
+static int
+process_filter(struct event_format *event, struct filter_arg **parg,
+ char **error_str, int not)
+{
+ enum event_type type;
+ char *token = NULL;
+ struct filter_arg *current_op = NULL;
+ struct filter_arg *current_exp = NULL;
+ struct filter_arg *left_item = NULL;
+ struct filter_arg *arg = NULL;
+ enum op_type op_type;
+ enum filter_op_type btype;
+ enum filter_exp_type etype;
+ enum filter_cmp_type ctype;
+ int ret;
+
+ *parg = NULL;
+
+ do {
+ free(token);
+ type = read_token(&token);
+ switch (type) {
+ case EVENT_SQUOTE:
+ case EVENT_DQUOTE:
+ case EVENT_ITEM:
+ arg = create_arg_item(event, token, type, error_str);
+ if (!arg)
+ goto fail;
+ if (!left_item)
+ left_item = arg;
+ else if (current_exp) {
+ ret = add_right(current_exp, arg, error_str);
+ if (ret < 0)
+ goto fail;
+ left_item = NULL;
+ /* Not's only one one expression */
+ if (not) {
+ arg = NULL;
+ if (current_op)
+ goto fail_print;
+ free(token);
+ *parg = current_exp;
+ return 0;
+ }
+ } else
+ goto fail_print;
+ arg = NULL;
+ break;
+
+ case EVENT_DELIM:
+ if (*token == ',') {
+ show_error(error_str,
+ "Illegal token ','");
+ goto fail;
+ }
+
+ if (*token == '(') {
+ if (left_item) {
+ show_error(error_str,
+ "Open paren can not come after item");
+ goto fail;
+ }
+ if (current_exp) {
+ show_error(error_str,
+ "Open paren can not come after expression");
+ goto fail;
+ }
+
+ ret = process_filter(event, &arg, error_str, 0);
+ if (ret != 1) {
+ if (ret == 0)
+ show_error(error_str,
+ "Unbalanced number of '('");
+ goto fail;
+ }
+ ret = 0;
+
+ /* A not wants just one expression */
+ if (not) {
+ if (current_op)
+ goto fail_print;
+ *parg = arg;
+ return 0;
+ }
+
+ if (current_op)
+ ret = add_right(current_op, arg, error_str);
+ else
+ current_exp = arg;
+
+ if (ret < 0)
+ goto fail;
+
+ } else { /* ')' */
+ if (!current_op && !current_exp)
+ goto fail_print;
+
+ /* Make sure everything is finished at this level */
+ if (current_exp && !check_op_done(current_exp))
+ goto fail_print;
+ if (current_op && !check_op_done(current_op))
+ goto fail_print;
+
+ if (current_op)
+ *parg = current_op;
+ else
+ *parg = current_exp;
+ return 1;
+ }
+ break;
+
+ case EVENT_OP:
+ op_type = process_op(token, &btype, &ctype, &etype);
+
+ /* All expect a left arg except for NOT */
+ switch (op_type) {
+ case OP_BOOL:
+ /* Logic ops need a left expression */
+ if (!current_exp && !current_op)
+ goto fail_print;
+ /* fall through */
+ case OP_NOT:
+ /* logic only processes ops and exp */
+ if (left_item)
+ goto fail_print;
+ break;
+ case OP_EXP:
+ case OP_CMP:
+ if (!left_item)
+ goto fail_print;
+ break;
+ case OP_NONE:
+ show_error(error_str,
+ "Unknown op token %s", token);
+ goto fail;
+ }
+
+ ret = 0;
+ switch (op_type) {
+ case OP_BOOL:
+ arg = create_arg_op(btype);
+ if (current_op)
+ ret = add_left(arg, current_op);
+ else
+ ret = add_left(arg, current_exp);
+ current_op = arg;
+ current_exp = NULL;
+ break;
+
+ case OP_NOT:
+ arg = create_arg_op(btype);
+ if (current_op)
+ ret = add_right(current_op, arg, error_str);
+ if (ret < 0)
+ goto fail;
+ current_exp = arg;
+ ret = process_filter(event, &arg, error_str, 1);
+ if (ret < 0)
+ goto fail;
+ ret = add_right(current_exp, arg, error_str);
+ if (ret < 0)
+ goto fail;
+ break;
+
+ case OP_EXP:
+ case OP_CMP:
+ if (op_type == OP_EXP)
+ arg = create_arg_exp(etype);
+ else
+ arg = create_arg_cmp(ctype);
+
+ if (current_op)
+ ret = add_right(current_op, arg, error_str);
+ if (ret < 0)
+ goto fail;
+ ret = add_left(arg, left_item);
+ if (ret < 0) {
+ arg = NULL;
+ goto fail_print;
+ }
+ current_exp = arg;
+ break;
+ default:
+ break;
+ }
+ arg = NULL;
+ if (ret < 0)
+ goto fail_print;
+ break;
+ case EVENT_NONE:
+ break;
+ default:
+ goto fail_print;
+ }
+ } while (type != EVENT_NONE);
+
+ if (!current_op && !current_exp)
+ goto fail_print;
+
+ if (!current_op)
+ current_op = current_exp;
+
+ current_op = collapse_tree(current_op);
+
+ *parg = current_op;
+
+ return 0;
+
+ fail_print:
+ show_error(error_str, "Syntax error");
+ fail:
+ free_arg(current_op);
+ free_arg(current_exp);
+ free_arg(arg);
+ free(token);
+ return -1;
+}
+
+static int
+process_event(struct event_format *event, const char *filter_str,
+ struct filter_arg **parg, char **error_str)
+{
+ int ret;
+
+ pevent_buffer_init(filter_str, strlen(filter_str));
+
+ ret = process_filter(event, parg, error_str, 0);
+ if (ret == 1) {
+ show_error(error_str,
+ "Unbalanced number of ')'");
+ return -1;
+ }
+ if (ret < 0)
+ return ret;
+
+ /* If parg is NULL, then make it into FALSE */
+ if (!*parg) {
+ *parg = allocate_arg();
+ (*parg)->type = FILTER_ARG_BOOLEAN;
+ (*parg)->boolean.value = FILTER_FALSE;
+ }
+
+ return 0;
+}
+
+static int filter_event(struct event_filter *filter,
+ struct event_format *event,
+ const char *filter_str, char **error_str)
+{
+ struct filter_type *filter_type;
+ struct filter_arg *arg;
+ int ret;
+
+ if (filter_str) {
+ ret = process_event(event, filter_str, &arg, error_str);
+ if (ret < 0)
+ return ret;
+
+ } else {
+ /* just add a TRUE arg */
+ arg = allocate_arg();
+ arg->type = FILTER_ARG_BOOLEAN;
+ arg->boolean.value = FILTER_TRUE;
+ }
+
+ filter_type = add_filter_type(filter, event->id);
+ if (filter_type->filter)
+ free_arg(filter_type->filter);
+ filter_type->filter = arg;
+
+ return 0;
+}
+
+/**
+ * pevent_filter_add_filter_str - add a new filter
+ * @filter: the event filter to add to
+ * @filter_str: the filter string that contains the filter
+ * @error_str: string containing reason for failed filter
+ *
+ * Returns 0 if the filter was successfully added
+ * -1 if there was an error.
+ *
+ * On error, if @error_str points to a string pointer,
+ * it is set to the reason that the filter failed.
+ * This string must be freed with "free".
+ */
+int pevent_filter_add_filter_str(struct event_filter *filter,
+ const char *filter_str,
+ char **error_str)
+{
+ struct pevent *pevent = filter->pevent;
+ struct event_list *event;
+ struct event_list *events = NULL;
+ const char *filter_start;
+ const char *next_event;
+ char *this_event;
+ char *event_name = NULL;
+ char *sys_name = NULL;
+ char *sp;
+ int rtn = 0;
+ int len;
+ int ret;
+
+ /* clear buffer to reset show error */
+ pevent_buffer_init("", 0);
+
+ if (error_str)
+ *error_str = NULL;
+
+ filter_start = strchr(filter_str, ':');
+ if (filter_start)
+ len = filter_start - filter_str;
+ else
+ len = strlen(filter_str);
+
+
+ do {
+ next_event = strchr(filter_str, ',');
+ if (next_event &&
+ (!filter_start || next_event < filter_start))
+ len = next_event - filter_str;
+ else if (filter_start)
+ len = filter_start - filter_str;
+ else
+ len = strlen(filter_str);
+
+ this_event = malloc_or_die(len + 1);
+ memcpy(this_event, filter_str, len);
+ this_event[len] = 0;
+
+ if (next_event)
+ next_event++;
+
+ filter_str = next_event;
+
+ sys_name = strtok_r(this_event, "/", &sp);
+ event_name = strtok_r(NULL, "/", &sp);
+
+ if (!sys_name) {
+ show_error(error_str, "No filter found");
+ /* This can only happen when events is NULL, but still */
+ free_events(events);
+ free(this_event);
+ return -1;
+ }
+
+ /* Find this event */
+ ret = find_event(pevent, &events, strim(sys_name), strim(event_name));
+ if (ret < 0) {
+ if (event_name)
+ show_error(error_str,
+ "No event found under '%s.%s'",
+ sys_name, event_name);
+ else
+ show_error(error_str,
+ "No event found under '%s'",
+ sys_name);
+ free_events(events);
+ free(this_event);
+ return -1;
+ }
+ free(this_event);
+ } while (filter_str);
+
+ /* Skip the ':' */
+ if (filter_start)
+ filter_start++;
+
+ /* filter starts here */
+ for (event = events; event; event = event->next) {
+ ret = filter_event(filter, event->event, filter_start,
+ error_str);
+ /* Failures are returned if a parse error happened */
+ if (ret < 0)
+ rtn = ret;
+
+ if (ret >= 0 && pevent->test_filters) {
+ char *test;
+ test = pevent_filter_make_string(filter, event->event->id);
+ printf(" '%s: %s'\n", event->event->name, test);
+ free(test);
+ }
+ }
+
+ free_events(events);
+
+ if (rtn >= 0 && pevent->test_filters)
+ exit(0);
+
+ return rtn;
+}
+
+static void free_filter_type(struct filter_type *filter_type)
+{
+ free_arg(filter_type->filter);
+}
+
+/**
+ * pevent_filter_remove_event - remove a filter for an event
+ * @filter: the event filter to remove from
+ * @event_id: the event to remove a filter for
+ *
+ * Removes the filter saved for an event defined by @event_id
+ * from the @filter.
+ *
+ * Returns 1: if an event was removed
+ * 0: if the event was not found
+ */
+int pevent_filter_remove_event(struct event_filter *filter,
+ int event_id)
+{
+ struct filter_type *filter_type;
+ unsigned long len;
+
+ if (!filter->filters)
+ return 0;
+
+ filter_type = find_filter_type(filter, event_id);
+
+ if (!filter_type)
+ return 0;
+
+ free_filter_type(filter_type);
+
+ /* The filter_type points into the event_filters array */
+ len = (unsigned long)(filter->event_filters + filter->filters) -
+ (unsigned long)(filter_type + 1);
+
+ memmove(filter_type, filter_type + 1, len);
+ filter->filters--;
+
+ memset(&filter->event_filters[filter->filters], 0,
+ sizeof(*filter_type));
+
+ return 1;
+}
+
+/**
+ * pevent_filter_reset - clear all filters in a filter
+ * @filter: the event filter to reset
+ *
+ * Removes all filters from a filter and resets it.
+ */
+void pevent_filter_reset(struct event_filter *filter)
+{
+ int i;
+
+ for (i = 0; i < filter->filters; i++)
+ free_filter_type(&filter->event_filters[i]);
+
+ free(filter->event_filters);
+ filter->filters = 0;
+ filter->event_filters = NULL;
+}
+
+void pevent_filter_free(struct event_filter *filter)
+{
+ pevent_unref(filter->pevent);
+
+ pevent_filter_reset(filter);
+
+ free(filter);
+}
+
+static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg);
+
+static int copy_filter_type(struct event_filter *filter,
+ struct event_filter *source,
+ struct filter_type *filter_type)
+{
+ struct filter_arg *arg;
+ struct event_format *event;
+ const char *sys;
+ const char *name;
+ char *str;
+
+ /* Can't assume that the pevent's are the same */
+ sys = filter_type->event->system;
+ name = filter_type->event->name;
+ event = pevent_find_event_by_name(filter->pevent, sys, name);
+ if (!event)
+ return -1;
+
+ str = arg_to_str(source, filter_type->filter);
+ if (!str)
+ return -1;
+
+ if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
+ /* Add trivial event */
+ arg = allocate_arg();
+ arg->type = FILTER_ARG_BOOLEAN;
+ if (strcmp(str, "TRUE") == 0)
+ arg->boolean.value = 1;
+ else
+ arg->boolean.value = 0;
+
+ filter_type = add_filter_type(filter, event->id);
+ filter_type->filter = arg;
+
+ free(str);
+ return 0;
+ }
+
+ filter_event(filter, event, str, NULL);
+ free(str);
+
+ return 0;
+}
+
+/**
+ * pevent_filter_copy - copy a filter using another filter
+ * @dest - the filter to copy to
+ * @source - the filter to copy from
+ *
+ * Returns 0 on success and -1 if not all filters were copied
+ */
+int pevent_filter_copy(struct event_filter *dest, struct event_filter *source)
+{
+ int ret = 0;
+ int i;
+
+ pevent_filter_reset(dest);
+
+ for (i = 0; i < source->filters; i++) {
+ if (copy_filter_type(dest, source, &source->event_filters[i]))
+ ret = -1;
+ }
+ return ret;
+}
+
+
+/**
+ * pevent_update_trivial - update the trivial filters with the given filter
+ * @dest - the filter to update
+ * @source - the filter as the source of the update
+ * @type - the type of trivial filter to update.
+ *
+ * Scan dest for trivial events matching @type to replace with the source.
+ *
+ * Returns 0 on success and -1 if there was a problem updating, but
+ * events may have still been updated on error.
+ */
+int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
+ enum filter_trivial_type type)
+{
+ struct pevent *src_pevent;
+ struct pevent *dest_pevent;
+ struct event_format *event;
+ struct filter_type *filter_type;
+ struct filter_arg *arg;
+ char *str;
+ int i;
+
+ src_pevent = source->pevent;
+ dest_pevent = dest->pevent;
+
+ /* Do nothing if either of the filters has nothing to filter */
+ if (!dest->filters || !source->filters)
+ return 0;
+
+ for (i = 0; i < dest->filters; i++) {
+ filter_type = &dest->event_filters[i];
+ arg = filter_type->filter;
+ if (arg->type != FILTER_ARG_BOOLEAN)
+ continue;
+ if ((arg->boolean.value && type == FILTER_TRIVIAL_FALSE) ||
+ (!arg->boolean.value && type == FILTER_TRIVIAL_TRUE))
+ continue;
+
+ event = filter_type->event;
+
+ if (src_pevent != dest_pevent) {
+ /* do a look up */
+ event = pevent_find_event_by_name(src_pevent,
+ event->system,
+ event->name);
+ if (!event)
+ return -1;
+ }
+
+ str = pevent_filter_make_string(source, event->id);
+ if (!str)
+ continue;
+
+ /* Don't bother if the filter is trivial too */
+ if (strcmp(str, "TRUE") != 0 && strcmp(str, "FALSE") != 0)
+ filter_event(dest, event, str, NULL);
+ free(str);
+ }
+ return 0;
+}
+
+/**
+ * pevent_filter_clear_trivial - clear TRUE and FALSE filters
+ * @filter: the filter to remove trivial filters from
+ * @type: remove only true, false, or both
+ *
+ * Removes filters that only contain a TRUE or FALES boolean arg.
+ */
+void pevent_filter_clear_trivial(struct event_filter *filter,
+ enum filter_trivial_type type)
+{
+ struct filter_type *filter_type;
+ int count = 0;
+ int *ids;
+ int i;
+
+ if (!filter->filters)
+ return;
+
+ /*
+ * Two steps, first get all ids with trivial filters.
+ * then remove those ids.
+ */
+ for (i = 0; i < filter->filters; i++) {
+ filter_type = &filter->event_filters[i];
+ if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
+ continue;
+ switch (type) {
+ case FILTER_TRIVIAL_FALSE:
+ if (filter_type->filter->boolean.value)
+ continue;
+ case FILTER_TRIVIAL_TRUE:
+ if (!filter_type->filter->boolean.value)
+ continue;
+ default:
+ break;
+ }
+ if (count)
+ ids = realloc(ids, sizeof(*ids) * (count + 1));
+ else
+ ids = malloc(sizeof(*ids));
+ if (!ids)
+ die("Can't allocate ids");
+ ids[count++] = filter_type->event_id;
+ }
+
+ if (!count)
+ return;
+
+ for (i = 0; i < count; i++)
+ pevent_filter_remove_event(filter, ids[i]);
+
+ free(ids);
+}
+
+/**
+ * pevent_filter_event_has_trivial - return true event contains trivial filter
+ * @filter: the filter with the information
+ * @event_id: the id of the event to test
+ * @type: trivial type to test for (TRUE, FALSE, EITHER)
+ *
+ * Returns 1 if the event contains a matching trivial type
+ * otherwise 0.
+ */
+int pevent_filter_event_has_trivial(struct event_filter *filter,
+ int event_id,
+ enum filter_trivial_type type)
+{
+ struct filter_type *filter_type;
+
+ if (!filter->filters)
+ return 0;
+
+ filter_type = find_filter_type(filter, event_id);
+
+ if (!filter_type)
+ return 0;
+
+ if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
+ return 0;
+
+ switch (type) {
+ case FILTER_TRIVIAL_FALSE:
+ return !filter_type->filter->boolean.value;
+
+ case FILTER_TRIVIAL_TRUE:
+ return filter_type->filter->boolean.value;
+ default:
+ return 1;
+ }
+}
+
+static int test_filter(struct event_format *event,
+ struct filter_arg *arg, struct pevent_record *record);
+
+static const char *
+get_comm(struct event_format *event, struct pevent_record *record)
+{
+ const char *comm;
+ int pid;
+
+ pid = pevent_data_pid(event->pevent, record);
+ comm = pevent_data_comm_from_pid(event->pevent, pid);
+ return comm;
+}
+
+static unsigned long long
+get_value(struct event_format *event,
+ struct format_field *field, struct pevent_record *record)
+{
+ unsigned long long val;
+
+ /* Handle our dummy "comm" field */
+ if (field == &comm) {
+ const char *name;
+
+ name = get_comm(event, record);
+ return (unsigned long long)name;
+ }
+
+ pevent_read_number_field(field, record->data, &val);
+
+ if (!(field->flags & FIELD_IS_SIGNED))
+ return val;
+
+ switch (field->size) {
+ case 1:
+ return (char)val;
+ case 2:
+ return (short)val;
+ case 4:
+ return (int)val;
+ case 8:
+ return (long long)val;
+ }
+ return val;
+}
+
+static unsigned long long
+get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record);
+
+static unsigned long long
+get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record)
+{
+ unsigned long long lval, rval;
+
+ lval = get_arg_value(event, arg->exp.left, record);
+ rval = get_arg_value(event, arg->exp.right, record);
+
+ switch (arg->exp.type) {
+ case FILTER_EXP_ADD:
+ return lval + rval;
+
+ case FILTER_EXP_SUB:
+ return lval - rval;
+
+ case FILTER_EXP_MUL:
+ return lval * rval;
+
+ case FILTER_EXP_DIV:
+ return lval / rval;
+
+ case FILTER_EXP_MOD:
+ return lval % rval;
+
+ case FILTER_EXP_RSHIFT:
+ return lval >> rval;
+
+ case FILTER_EXP_LSHIFT:
+ return lval << rval;
+
+ case FILTER_EXP_AND:
+ return lval & rval;
+
+ case FILTER_EXP_OR:
+ return lval | rval;
+
+ case FILTER_EXP_XOR:
+ return lval ^ rval;
+
+ case FILTER_EXP_NOT:
+ default:
+ die("error in exp");
+ }
+ return 0;
+}
+
+static unsigned long long
+get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record)
+{
+ switch (arg->type) {
+ case FILTER_ARG_FIELD:
+ return get_value(event, arg->field.field, record);
+
+ case FILTER_ARG_VALUE:
+ if (arg->value.type != FILTER_NUMBER)
+ die("must have number field!");
+ return arg->value.val;
+
+ case FILTER_ARG_EXP:
+ return get_exp_value(event, arg, record);
+
+ default:
+ die("oops in filter");
+ }
+ return 0;
+}
+
+static int test_num(struct event_format *event,
+ struct filter_arg *arg, struct pevent_record *record)
+{
+ unsigned long long lval, rval;
+
+ lval = get_arg_value(event, arg->num.left, record);
+ rval = get_arg_value(event, arg->num.right, record);
+
+ switch (arg->num.type) {
+ case FILTER_CMP_EQ:
+ return lval == rval;
+
+ case FILTER_CMP_NE:
+ return lval != rval;
+
+ case FILTER_CMP_GT:
+ return lval > rval;
+
+ case FILTER_CMP_LT:
+ return lval < rval;
+
+ case FILTER_CMP_GE:
+ return lval >= rval;
+
+ case FILTER_CMP_LE:
+ return lval <= rval;
+
+ default:
+ /* ?? */
+ return 0;
+ }
+}
+
+static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
+{
+ const char *val = record->data + arg->str.field->offset;
+
+ /*
+ * We need to copy the data since we can't be sure the field
+ * is null terminated.
+ */
+ if (*(val + arg->str.field->size - 1)) {
+ /* copy it */
+ memcpy(arg->str.buffer, val, arg->str.field->size);
+ /* the buffer is already NULL terminated */
+ val = arg->str.buffer;
+ }
+ return val;
+}
+
+static int test_str(struct event_format *event,
+ struct filter_arg *arg, struct pevent_record *record)
+{
+ const char *val;
+
+ if (arg->str.field == &comm)
+ val = get_comm(event, record);
+ else
+ val = get_field_str(arg, record);
+
+ switch (arg->str.type) {
+ case FILTER_CMP_MATCH:
+ return strcmp(val, arg->str.val) == 0;
+
+ case FILTER_CMP_NOT_MATCH:
+ return strcmp(val, arg->str.val) != 0;
+
+ case FILTER_CMP_REGEX:
+ /* Returns zero on match */
+ return !regexec(&arg->str.reg, val, 0, NULL, 0);
+
+ case FILTER_CMP_NOT_REGEX:
+ return regexec(&arg->str.reg, val, 0, NULL, 0);
+
+ default:
+ /* ?? */
+ return 0;
+ }
+}
+
+static int test_op(struct event_format *event,
+ struct filter_arg *arg, struct pevent_record *record)
+{
+ switch (arg->op.type) {
+ case FILTER_OP_AND:
+ return test_filter(event, arg->op.left, record) &&
+ test_filter(event, arg->op.right, record);
+
+ case FILTER_OP_OR:
+ return test_filter(event, arg->op.left, record) ||
+ test_filter(event, arg->op.right, record);
+
+ case FILTER_OP_NOT:
+ return !test_filter(event, arg->op.right, record);
+
+ default:
+ /* ?? */
+ return 0;
+ }
+}
+
+static int test_filter(struct event_format *event,
+ struct filter_arg *arg, struct pevent_record *record)
+{
+ switch (arg->type) {
+ case FILTER_ARG_BOOLEAN:
+ /* easy case */
+ return arg->boolean.value;
+
+ case FILTER_ARG_OP:
+ return test_op(event, arg, record);
+
+ case FILTER_ARG_NUM:
+ return test_num(event, arg, record);
+
+ case FILTER_ARG_STR:
+ return test_str(event, arg, record);
+
+ case FILTER_ARG_EXP:
+ case FILTER_ARG_VALUE:
+ case FILTER_ARG_FIELD:
+ /*
+ * Expressions, fields and values evaluate
+ * to true if they return non zero
+ */
+ return !!get_arg_value(event, arg, record);
+
+ default:
+ die("oops!");
+ /* ?? */
+ return 0;
+ }
+}
+
+/**
+ * pevent_event_filtered - return true if event has filter
+ * @filter: filter struct with filter information
+ * @event_id: event id to test if filter exists
+ *
+ * Returns 1 if filter found for @event_id
+ * otherwise 0;
+ */
+int pevent_event_filtered(struct event_filter *filter,
+ int event_id)
+{
+ struct filter_type *filter_type;
+
+ if (!filter->filters)
+ return 0;
+
+ filter_type = find_filter_type(filter, event_id);
+
+ return filter_type ? 1 : 0;
+}
+
+/**
+ * pevent_filter_match - test if a record matches a filter
+ * @filter: filter struct with filter information
+ * @record: the record to test against the filter
+ *
+ * Returns:
+ * 1 - filter found for event and @record matches
+ * 0 - filter found for event and @record does not match
+ * -1 - no filter found for @record's event
+ * -2 - if no filters exist
+ */
+int pevent_filter_match(struct event_filter *filter,
+ struct pevent_record *record)
+{
+ struct pevent *pevent = filter->pevent;
+ struct filter_type *filter_type;
+ int event_id;
+
+ if (!filter->filters)
+ return FILTER_NONE;
+
+ event_id = pevent_data_type(pevent, record);
+
+ filter_type = find_filter_type(filter, event_id);
+
+ if (!filter_type)
+ return FILTER_NOEXIST;
+
+ return test_filter(filter_type->event, filter_type->filter, record) ?
+ FILTER_MATCH : FILTER_MISS;
+}
+
+static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ char *str = NULL;
+ char *left = NULL;
+ char *right = NULL;
+ char *op = NULL;
+ int left_val = -1;
+ int right_val = -1;
+ int val;
+ int len;
+
+ switch (arg->op.type) {
+ case FILTER_OP_AND:
+ op = "&&";
+ /* fall through */
+ case FILTER_OP_OR:
+ if (!op)
+ op = "||";
+
+ left = arg_to_str(filter, arg->op.left);
+ right = arg_to_str(filter, arg->op.right);
+ if (!left || !right)
+ break;
+
+ /* Try to consolidate boolean values */
+ if (strcmp(left, "TRUE") == 0)
+ left_val = 1;
+ else if (strcmp(left, "FALSE") == 0)
+ left_val = 0;
+
+ if (strcmp(right, "TRUE") == 0)
+ right_val = 1;
+ else if (strcmp(right, "FALSE") == 0)
+ right_val = 0;
+
+ if (left_val >= 0) {
+ if ((arg->op.type == FILTER_OP_AND && !left_val) ||
+ (arg->op.type == FILTER_OP_OR && left_val)) {
+ /* Just return left value */
+ str = left;
+ left = NULL;
+ break;
+ }
+ if (right_val >= 0) {
+ /* just evaluate this. */
+ val = 0;
+ switch (arg->op.type) {
+ case FILTER_OP_AND:
+ val = left_val && right_val;
+ break;
+ case FILTER_OP_OR:
+ val = left_val || right_val;
+ break;
+ default:
+ break;
+ }
+ str = malloc_or_die(6);
+ if (val)
+ strcpy(str, "TRUE");
+ else
+ strcpy(str, "FALSE");
+ break;
+ }
+ }
+ if (right_val >= 0) {
+ if ((arg->op.type == FILTER_OP_AND && !right_val) ||
+ (arg->op.type == FILTER_OP_OR && right_val)) {
+ /* Just return right value */
+ str = right;
+ right = NULL;
+ break;
+ }
+ /* The right value is meaningless */
+ str = left;
+ left = NULL;
+ break;
+ }
+
+ len = strlen(left) + strlen(right) + strlen(op) + 10;
+ str = malloc_or_die(len);
+ snprintf(str, len, "(%s) %s (%s)",
+ left, op, right);
+ break;
+
+ case FILTER_OP_NOT:
+ op = "!";
+ right = arg_to_str(filter, arg->op.right);
+ if (!right)
+ break;
+
+ /* See if we can consolidate */
+ if (strcmp(right, "TRUE") == 0)
+ right_val = 1;
+ else if (strcmp(right, "FALSE") == 0)
+ right_val = 0;
+ if (right_val >= 0) {
+ /* just return the opposite */
+ str = malloc_or_die(6);
+ if (right_val)
+ strcpy(str, "FALSE");
+ else
+ strcpy(str, "TRUE");
+ break;
+ }
+ len = strlen(right) + strlen(op) + 3;
+ str = malloc_or_die(len);
+ snprintf(str, len, "%s(%s)", op, right);
+ break;
+
+ default:
+ /* ?? */
+ break;
+ }
+ free(left);
+ free(right);
+ return str;
+}
+
+static char *val_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ char *str;
+
+ str = malloc_or_die(30);
+
+ snprintf(str, 30, "%lld", arg->value.val);
+
+ return str;
+}
+
+static char *field_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ return strdup(arg->field.field->name);
+}
+
+static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ char *lstr;
+ char *rstr;
+ char *op;
+ char *str;
+ int len;
+
+ lstr = arg_to_str(filter, arg->exp.left);
+ rstr = arg_to_str(filter, arg->exp.right);
+
+ switch (arg->exp.type) {
+ case FILTER_EXP_ADD:
+ op = "+";
+ break;
+ case FILTER_EXP_SUB:
+ op = "-";
+ break;
+ case FILTER_EXP_MUL:
+ op = "*";
+ break;
+ case FILTER_EXP_DIV:
+ op = "/";
+ break;
+ case FILTER_EXP_MOD:
+ op = "%";
+ break;
+ case FILTER_EXP_RSHIFT:
+ op = ">>";
+ break;
+ case FILTER_EXP_LSHIFT:
+ op = "<<";
+ break;
+ case FILTER_EXP_AND:
+ op = "&";
+ break;
+ case FILTER_EXP_OR:
+ op = "|";
+ break;
+ case FILTER_EXP_XOR:
+ op = "^";
+ break;
+ default:
+ die("oops in exp");
+ }
+
+ len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
+ str = malloc_or_die(len);
+ snprintf(str, len, "%s %s %s", lstr, op, rstr);
+ free(lstr);
+ free(rstr);
+
+ return str;
+}
+
+static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ char *lstr;
+ char *rstr;
+ char *str = NULL;
+ char *op = NULL;
+ int len;
+
+ lstr = arg_to_str(filter, arg->num.left);
+ rstr = arg_to_str(filter, arg->num.right);
+
+ switch (arg->num.type) {
+ case FILTER_CMP_EQ:
+ op = "==";
+ /* fall through */
+ case FILTER_CMP_NE:
+ if (!op)
+ op = "!=";
+ /* fall through */
+ case FILTER_CMP_GT:
+ if (!op)
+ op = ">";
+ /* fall through */
+ case FILTER_CMP_LT:
+ if (!op)
+ op = "<";
+ /* fall through */
+ case FILTER_CMP_GE:
+ if (!op)
+ op = ">=";
+ /* fall through */
+ case FILTER_CMP_LE:
+ if (!op)
+ op = "<=";
+
+ len = strlen(lstr) + strlen(op) + strlen(rstr) + 4;
+ str = malloc_or_die(len);
+ sprintf(str, "%s %s %s", lstr, op, rstr);
+
+ break;
+
+ default:
+ /* ?? */
+ break;
+ }
+
+ free(lstr);
+ free(rstr);
+ return str;
+}
+
+static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ char *str = NULL;
+ char *op = NULL;
+ int len;
+
+ switch (arg->str.type) {
+ case FILTER_CMP_MATCH:
+ op = "==";
+ /* fall through */
+ case FILTER_CMP_NOT_MATCH:
+ if (!op)
+ op = "!=";
+ /* fall through */
+ case FILTER_CMP_REGEX:
+ if (!op)
+ op = "=~";
+ /* fall through */
+ case FILTER_CMP_NOT_REGEX:
+ if (!op)
+ op = "!~";
+
+ len = strlen(arg->str.field->name) + strlen(op) +
+ strlen(arg->str.val) + 6;
+ str = malloc_or_die(len);
+ snprintf(str, len, "%s %s \"%s\"",
+ arg->str.field->name,
+ op, arg->str.val);
+ break;
+
+ default:
+ /* ?? */
+ break;
+ }
+ return str;
+}
+
+static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ char *str;
+
+ switch (arg->type) {
+ case FILTER_ARG_BOOLEAN:
+ str = malloc_or_die(6);
+ if (arg->boolean.value)
+ strcpy(str, "TRUE");
+ else
+ strcpy(str, "FALSE");
+ return str;
+
+ case FILTER_ARG_OP:
+ return op_to_str(filter, arg);
+
+ case FILTER_ARG_NUM:
+ return num_to_str(filter, arg);
+
+ case FILTER_ARG_STR:
+ return str_to_str(filter, arg);
+
+ case FILTER_ARG_VALUE:
+ return val_to_str(filter, arg);
+
+ case FILTER_ARG_FIELD:
+ return field_to_str(filter, arg);
+
+ case FILTER_ARG_EXP:
+ return exp_to_str(filter, arg);
+
+ default:
+ /* ?? */
+ return NULL;
+ }
+
+}
+
+/**
+ * pevent_filter_make_string - return a string showing the filter
+ * @filter: filter struct with filter information
+ * @event_id: the event id to return the filter string with
+ *
+ * Returns a string that displays the filter contents.
+ * This string must be freed with free(str).
+ * NULL is returned if no filter is found.
+ */
+char *
+pevent_filter_make_string(struct event_filter *filter, int event_id)
+{
+ struct filter_type *filter_type;
+
+ if (!filter->filters)
+ return NULL;
+
+ filter_type = find_filter_type(filter, event_id);
+
+ if (!filter_type)
+ return NULL;
+
+ return arg_to_str(filter, filter_type->filter);
+}
+
+/**
+ * pevent_filter_compare - compare two filters and return if they are the same
+ * @filter1: Filter to compare with @filter2
+ * @filter2: Filter to compare with @filter1
+ *
+ * Returns:
+ * 1 if the two filters hold the same content.
+ * 0 if they do not.
+ */
+int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2)
+{
+ struct filter_type *filter_type1;
+ struct filter_type *filter_type2;
+ char *str1, *str2;
+ int result;
+ int i;
+
+ /* Do the easy checks first */
+ if (filter1->filters != filter2->filters)
+ return 0;
+ if (!filter1->filters && !filter2->filters)
+ return 1;
+
+ /*
+ * Now take a look at each of the events to see if they have the same
+ * filters to them.
+ */
+ for (i = 0; i < filter1->filters; i++) {
+ filter_type1 = &filter1->event_filters[i];
+ filter_type2 = find_filter_type(filter2, filter_type1->event_id);
+ if (!filter_type2)
+ break;
+ if (filter_type1->filter->type != filter_type2->filter->type)
+ break;
+ switch (filter_type1->filter->type) {
+ case FILTER_TRIVIAL_FALSE:
+ case FILTER_TRIVIAL_TRUE:
+ /* trivial types just need the type compared */
+ continue;
+ default:
+ break;
+ }
+ /* The best way to compare complex filters is with strings */
+ str1 = arg_to_str(filter1, filter_type1->filter);
+ str2 = arg_to_str(filter2, filter_type2->filter);
+ result = strcmp(str1, str2) != 0;
+ free(str1);
+ free(str2);
+ if (result)
+ break;
+ }
+
+ if (i < filter1->filters)
+ return 0;
+ return 1;
+}
+
diff --git a/tools/lib/traceevent/parse-utils.c b/tools/lib/traceevent/parse-utils.c
new file mode 100644
index 000000000000..f023a133abb6
--- /dev/null
+++ b/tools/lib/traceevent/parse-utils.c
@@ -0,0 +1,110 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#define __weak __attribute__((weak))
+
+void __vdie(const char *fmt, va_list ap)
+{
+ int ret = errno;
+
+ if (errno)
+ perror("trace-cmd");
+ else
+ ret = -1;
+
+ fprintf(stderr, " ");
+ vfprintf(stderr, fmt, ap);
+
+ fprintf(stderr, "\n");
+ exit(ret);
+}
+
+void __die(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vdie(fmt, ap);
+ va_end(ap);
+}
+
+void __weak die(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vdie(fmt, ap);
+ va_end(ap);
+}
+
+void __vwarning(const char *fmt, va_list ap)
+{
+ if (errno)
+ perror("trace-cmd");
+ errno = 0;
+
+ fprintf(stderr, " ");
+ vfprintf(stderr, fmt, ap);
+
+ fprintf(stderr, "\n");
+}
+
+void __warning(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vwarning(fmt, ap);
+ va_end(ap);
+}
+
+void __weak warning(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vwarning(fmt, ap);
+ va_end(ap);
+}
+
+void __vpr_stat(const char *fmt, va_list ap)
+{
+ vprintf(fmt, ap);
+ printf("\n");
+}
+
+void __pr_stat(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vpr_stat(fmt, ap);
+ va_end(ap);
+}
+
+void __weak vpr_stat(const char *fmt, va_list ap)
+{
+ __vpr_stat(fmt, ap);
+}
+
+void __weak pr_stat(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vpr_stat(fmt, ap);
+ va_end(ap);
+}
+
+void __weak *malloc_or_die(unsigned int size)
+{
+ void *data;
+
+ data = malloc(size);
+ if (!data)
+ die("malloc");
+ return data;
+}
diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c
new file mode 100644
index 000000000000..b1ccc923e8a5
--- /dev/null
+++ b/tools/lib/traceevent/trace-seq.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "event-parse.h"
+#include "event-utils.h"
+
+/*
+ * The TRACE_SEQ_POISON is to catch the use of using
+ * a trace_seq structure after it was destroyed.
+ */
+#define TRACE_SEQ_POISON ((void *)0xdeadbeef)
+#define TRACE_SEQ_CHECK(s) \
+do { \
+ if ((s)->buffer == TRACE_SEQ_POISON) \
+ die("Usage of trace_seq after it was destroyed"); \
+} while (0)
+
+/**
+ * trace_seq_init - initialize the trace_seq structure
+ * @s: a pointer to the trace_seq structure to initialize
+ */
+void trace_seq_init(struct trace_seq *s)
+{
+ s->len = 0;
+ s->readpos = 0;
+ s->buffer_size = TRACE_SEQ_BUF_SIZE;
+ s->buffer = malloc_or_die(s->buffer_size);
+}
+
+/**
+ * trace_seq_destroy - free up memory of a trace_seq
+ * @s: a pointer to the trace_seq to free the buffer
+ *
+ * Only frees the buffer, not the trace_seq struct itself.
+ */
+void trace_seq_destroy(struct trace_seq *s)
+{
+ if (!s)
+ return;
+ TRACE_SEQ_CHECK(s);
+ free(s->buffer);
+ s->buffer = TRACE_SEQ_POISON;
+}
+
+static void expand_buffer(struct trace_seq *s)
+{
+ s->buffer_size += TRACE_SEQ_BUF_SIZE;
+ s->buffer = realloc(s->buffer, s->buffer_size);
+ if (!s->buffer)
+ die("Can't allocate trace_seq buffer memory");
+}
+
+/**
+ * trace_seq_printf - sequence printing of trace information
+ * @s: trace sequence descriptor
+ * @fmt: printf format string
+ *
+ * It returns 0 if the trace oversizes the buffer's free
+ * space, 1 otherwise.
+ *
+ * The tracer may use either sequence operations or its own
+ * copy to user routines. To simplify formating of a trace
+ * trace_seq_printf is used to store strings into a special
+ * buffer (@s). Then the output may be either used by
+ * the sequencer or pulled into another buffer.
+ */
+int
+trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
+{
+ va_list ap;
+ int len;
+ int ret;
+
+ TRACE_SEQ_CHECK(s);
+
+ try_again:
+ len = (s->buffer_size - 1) - s->len;
+
+ va_start(ap, fmt);
+ ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
+ va_end(ap);
+
+ if (ret >= len) {
+ expand_buffer(s);
+ goto try_again;
+ }
+
+ s->len += ret;
+
+ return 1;
+}
+
+/**
+ * trace_seq_vprintf - sequence printing of trace information
+ * @s: trace sequence descriptor
+ * @fmt: printf format string
+ *
+ * The tracer may use either sequence operations or its own
+ * copy to user routines. To simplify formating of a trace
+ * trace_seq_printf is used to store strings into a special
+ * buffer (@s). Then the output may be either used by
+ * the sequencer or pulled into another buffer.
+ */
+int
+trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
+{
+ int len;
+ int ret;
+
+ TRACE_SEQ_CHECK(s);
+
+ try_again:
+ len = (s->buffer_size - 1) - s->len;
+
+ ret = vsnprintf(s->buffer + s->len, len, fmt, args);
+
+ if (ret >= len) {
+ expand_buffer(s);
+ goto try_again;
+ }
+
+ s->len += ret;
+
+ return len;
+}
+
+/**
+ * trace_seq_puts - trace sequence printing of simple string
+ * @s: trace sequence descriptor
+ * @str: simple string to record
+ *
+ * The tracer may use either the sequence operations or its own
+ * copy to user routines. This function records a simple string
+ * into a special buffer (@s) for later retrieval by a sequencer
+ * or other mechanism.
+ */
+int trace_seq_puts(struct trace_seq *s, const char *str)
+{
+ int len;
+
+ TRACE_SEQ_CHECK(s);
+
+ len = strlen(str);
+
+ while (len > ((s->buffer_size - 1) - s->len))
+ expand_buffer(s);
+
+ memcpy(s->buffer + s->len, str, len);
+ s->len += len;
+
+ return len;
+}
+
+int trace_seq_putc(struct trace_seq *s, unsigned char c)
+{
+ TRACE_SEQ_CHECK(s);
+
+ while (s->len >= (s->buffer_size - 1))
+ expand_buffer(s);
+
+ s->buffer[s->len++] = c;
+
+ return 1;
+}
+
+void trace_seq_terminate(struct trace_seq *s)
+{
+ TRACE_SEQ_CHECK(s);
+
+ /* There's always one character left on the buffer */
+ s->buffer[s->len] = 0;
+}
+
+int trace_seq_do_printf(struct trace_seq *s)
+{
+ TRACE_SEQ_CHECK(s);
+ return printf("%.*s", s->len, s->buffer);
+}
diff --git a/tools/perf/Documentation/perf-evlist.txt b/tools/perf/Documentation/perf-evlist.txt
index 0507ec7bad71..15217345c2fa 100644
--- a/tools/perf/Documentation/perf-evlist.txt
+++ b/tools/perf/Documentation/perf-evlist.txt
@@ -20,6 +20,14 @@ OPTIONS
--input=::
Input file name. (default: perf.data unless stdin is a fifo)
+-F::
+--freq=::
+ Show just the sample frequency used for each event.
+
+-v::
+--verbose=::
+ Show all fields.
+
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-list[1],
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index a1386b2fff00..b38a1f9ad460 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -168,7 +168,7 @@ following filters are defined:
- any: any type of branches
- any_call: any function call or system call
- any_ret: any function return or system call return
- - any_ind: any indirect branch
+ - ind_call: any indirect branch
- u: only when the branch target is at the user level
- k: only when the branch target is in the kernel
- hv: only when the target is at the hypervisor level
diff --git a/tools/perf/Documentation/perfconfig.example b/tools/perf/Documentation/perfconfig.example
index d1448668f4d4..42c6fd2ae85d 100644
--- a/tools/perf/Documentation/perfconfig.example
+++ b/tools/perf/Documentation/perfconfig.example
@@ -6,6 +6,7 @@
normal = black, lightgray
selected = lightgray, magenta
code = blue, lightgray
+ addr = magenta, lightgray
[tui]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 9bf3fc759344..1d3d513beb9b 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -1,18 +1,10 @@
-ifeq ("$(origin O)", "command line")
- OUTPUT := $(O)/
-endif
+include ../scripts/Makefile.include
# The default target of this Makefile is...
all:
include config/utilities.mak
-ifneq ($(OUTPUT),)
-# check that the output directory actually exists
-OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd)
-$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
-endif
-
# Define V to have a more verbose compile.
#
# Define O to save output files in a separate directory.
@@ -84,31 +76,6 @@ ifneq ($(WERROR),0)
CFLAGS_WERROR := -Werror
endif
-#
-# Include saner warnings here, which can catch bugs:
-#
-
-EXTRA_WARNINGS := -Wformat
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-security
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-y2k
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wshadow
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Winit-self
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wpacked
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wredundant-decls
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-aliasing=3
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-default
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-enum
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wno-system-headers
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wundef
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wwrite-strings
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wbad-function-cast
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-declarations
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-prototypes
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wnested-externs
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wold-style-definition
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-prototypes
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wdeclaration-after-statement
-
ifeq ("$(origin DEBUG)", "command line")
PERF_DEBUG = $(DEBUG)
endif
@@ -116,7 +83,13 @@ ifndef PERF_DEBUG
CFLAGS_OPTIMIZE = -O6
endif
-CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
+ifdef PARSER_DEBUG
+ PARSER_DEBUG_BISON := -t
+ PARSER_DEBUG_FLEX := -d
+ PARSER_DEBUG_CFLAGS := -DPARSER_DEBUG
+endif
+
+CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS)
EXTLIBS = -lpthread -lrt -lelf -lm
ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
ALL_LDFLAGS = $(LDFLAGS)
@@ -182,7 +155,7 @@ endif
### --- END CONFIGURATION SECTION ---
-BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
+BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
BASIC_LDFLAGS =
# Guard against environment variables
@@ -211,6 +184,17 @@ $(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
+TRACE_EVENT_DIR = ../lib/traceevent/
+
+ifeq ("$(origin O)", "command line")
+ TE_PATH=$(OUTPUT)/
+else
+ TE_PATH=$(TRACE_EVENT_DIR)/
+endif
+
+LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
+TE_LIB := -L$(TE_PATH) -ltraceevent
+
#
# Single 'perf' binary right now:
#
@@ -238,10 +222,10 @@ FLEX = flex
BISON= bison
$(OUTPUT)util/parse-events-flex.c: util/parse-events.l
- $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
+ $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
- $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c
+ $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c
$(OUTPUT)util/pmu-flex.c: util/pmu.l
$(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
@@ -333,6 +317,8 @@ LIB_H += util/cpumap.h
LIB_H += util/top.h
LIB_H += $(ARCH_INCLUDE)
LIB_H += util/cgroup.h
+LIB_H += $(TRACE_EVENT_DIR)event-parse.h
+LIB_H += util/target.h
LIB_OBJS += $(OUTPUT)util/abspath.o
LIB_OBJS += $(OUTPUT)util/alias.o
@@ -352,6 +338,7 @@ LIB_OBJS += $(OUTPUT)util/help.o
LIB_OBJS += $(OUTPUT)util/levenshtein.o
LIB_OBJS += $(OUTPUT)util/parse-options.o
LIB_OBJS += $(OUTPUT)util/parse-events.o
+LIB_OBJS += $(OUTPUT)util/parse-events-test.o
LIB_OBJS += $(OUTPUT)util/path.o
LIB_OBJS += $(OUTPUT)util/rbtree.o
LIB_OBJS += $(OUTPUT)util/bitmap.o
@@ -394,6 +381,7 @@ LIB_OBJS += $(OUTPUT)util/util.o
LIB_OBJS += $(OUTPUT)util/xyarray.o
LIB_OBJS += $(OUTPUT)util/cpumap.o
LIB_OBJS += $(OUTPUT)util/cgroup.o
+LIB_OBJS += $(OUTPUT)util/target.o
BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
@@ -429,7 +417,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
BUILTIN_OBJS += $(OUTPUT)builtin-test.o
BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
-PERFLIBS = $(LIB_FILE)
+PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
# Files needed for the python binding, perf.so
# pyrf is just an internal name needed for all those wrappers.
@@ -506,22 +494,23 @@ else
# Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
BASIC_CFLAGS += -I/usr/include/slang
EXTLIBS += -lnewt -lslang
- LIB_OBJS += $(OUTPUT)util/ui/setup.o
- LIB_OBJS += $(OUTPUT)util/ui/browser.o
- LIB_OBJS += $(OUTPUT)util/ui/browsers/annotate.o
- LIB_OBJS += $(OUTPUT)util/ui/browsers/hists.o
- LIB_OBJS += $(OUTPUT)util/ui/browsers/map.o
- LIB_OBJS += $(OUTPUT)util/ui/helpline.o
- LIB_OBJS += $(OUTPUT)util/ui/progress.o
- LIB_OBJS += $(OUTPUT)util/ui/util.o
- LIB_H += util/ui/browser.h
- LIB_H += util/ui/browsers/map.h
- LIB_H += util/ui/helpline.h
- LIB_H += util/ui/keysyms.h
- LIB_H += util/ui/libslang.h
- LIB_H += util/ui/progress.h
- LIB_H += util/ui/util.h
- LIB_H += util/ui/ui.h
+ LIB_OBJS += $(OUTPUT)ui/setup.o
+ LIB_OBJS += $(OUTPUT)ui/browser.o
+ LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
+ LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
+ LIB_OBJS += $(OUTPUT)ui/browsers/map.o
+ LIB_OBJS += $(OUTPUT)ui/helpline.o
+ LIB_OBJS += $(OUTPUT)ui/progress.o
+ LIB_OBJS += $(OUTPUT)ui/util.o
+ LIB_OBJS += $(OUTPUT)ui/tui/setup.o
+ LIB_H += ui/browser.h
+ LIB_H += ui/browsers/map.h
+ LIB_H += ui/helpline.h
+ LIB_H += ui/keysyms.h
+ LIB_H += ui/libslang.h
+ LIB_H += ui/progress.h
+ LIB_H += ui/util.h
+ LIB_H += ui/ui.h
endif
endif
@@ -535,7 +524,12 @@ else
else
BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0)
EXTLIBS += $(shell pkg-config --libs gtk+-2.0)
- LIB_OBJS += $(OUTPUT)util/gtk/browser.o
+ LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
+ LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
+ # Make sure that it'd be included only once.
+ ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),)
+ LIB_OBJS += $(OUTPUT)ui/setup.o
+ endif
endif
endif
@@ -678,18 +672,6 @@ else
endif
endif
-ifneq ($(findstring $(MAKEFLAGS),s),s)
-ifndef V
- QUIET_CC = @echo ' ' CC $@;
- QUIET_AR = @echo ' ' AR $@;
- QUIET_LINK = @echo ' ' LINK $@;
- QUIET_MKDIR = @echo ' ' MKDIR $@;
- QUIET_GEN = @echo ' ' GEN $@;
- QUIET_FLEX = @echo ' ' FLEX $@;
- QUIET_BISON = @echo ' ' BISON $@;
-endif
-endif
-
ifdef ASCIIDOC8
export ASCIIDOC8
endif
@@ -774,10 +756,10 @@ $(OUTPUT)perf.o perf.spec \
# over the general rule for .o
$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
- $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $<
+ $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Iutil/ -w $<
$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
- $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $<
+ $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -Iutil/ -w $<
$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
@@ -800,16 +782,16 @@ $(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
-$(OUTPUT)util/ui/browser.o: util/ui/browser.c $(OUTPUT)PERF-CFLAGS
+$(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
-$(OUTPUT)util/ui/browsers/annotate.o: util/ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
+$(OUTPUT)ui/browsers/annotate.o: ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
-$(OUTPUT)util/ui/browsers/hists.o: util/ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
+$(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
-$(OUTPUT)util/ui/browsers/map.o: util/ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
+$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
@@ -844,6 +826,10 @@ $(sort $(dir $(DIRECTORY_DEPS))):
$(LIB_FILE): $(LIB_OBJS)
$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
+# libtraceevent.a
+$(LIBTRACEEVENT):
+ $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) $(COMMAND_O) libtraceevent.a
+
help:
@echo 'Perf make targets:'
@echo ' doc - make *all* documentation (see below)'
@@ -990,6 +976,6 @@ clean:
$(RM) $(OUTPUT)util/*-{bison,flex}*
$(python-clean)
-.PHONY: all install clean strip
+.PHONY: all install clean strip $(LIBTRACEEVENT)
.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
.PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 52480467e9ff..6b2bcfbde150 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -84,7 +84,11 @@ static int perf_session__list_build_ids(void)
if (filename__fprintf_build_id(session->filename, stdout))
goto out;
- if (with_hits)
+ /*
+ * in pipe-mode, the only way to get the buildids is to parse
+ * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
+ */
+ if (with_hits || session->fd_pipe)
perf_session__process_events(session, &build_id__mark_dso_hit_ops);
perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 26760322c4f4..e52d77ec7084 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -15,9 +15,40 @@
#include "util/parse-options.h"
#include "util/session.h"
-static const char *input_name;
+struct perf_attr_details {
+ bool freq;
+ bool verbose;
+};
+
+static int comma_printf(bool *first, const char *fmt, ...)
+{
+ va_list args;
+ int ret = 0;
+
+ if (!*first) {
+ ret += printf(",");
+ } else {
+ ret += printf(":");
+ *first = false;
+ }
+
+ va_start(args, fmt);
+ ret += vprintf(fmt, args);
+ va_end(args);
+ return ret;
+}
+
+static int __if_print(bool *first, const char *field, u64 value)
+{
+ if (value == 0)
+ return 0;
+
+ return comma_printf(first, " %s: %" PRIu64, field, value);
+}
+
+#define if_print(field) __if_print(&first, #field, pos->attr.field)
-static int __cmd_evlist(void)
+static int __cmd_evlist(const char *input_name, struct perf_attr_details *details)
{
struct perf_session *session;
struct perf_evsel *pos;
@@ -26,8 +57,52 @@ static int __cmd_evlist(void)
if (session == NULL)
return -ENOMEM;
- list_for_each_entry(pos, &session->evlist->entries, node)
- printf("%s\n", event_name(pos));
+ list_for_each_entry(pos, &session->evlist->entries, node) {
+ bool first = true;
+
+ printf("%s", event_name(pos));
+
+ if (details->verbose || details->freq) {
+ comma_printf(&first, " sample_freq=%" PRIu64,
+ (u64)pos->attr.sample_freq);
+ }
+
+ if (details->verbose) {
+ if_print(type);
+ if_print(config);
+ if_print(config1);
+ if_print(config2);
+ if_print(size);
+ if_print(sample_type);
+ if_print(read_format);
+ if_print(disabled);
+ if_print(inherit);
+ if_print(pinned);
+ if_print(exclusive);
+ if_print(exclude_user);
+ if_print(exclude_kernel);
+ if_print(exclude_hv);
+ if_print(exclude_idle);
+ if_print(mmap);
+ if_print(comm);
+ if_print(freq);
+ if_print(inherit_stat);
+ if_print(enable_on_exec);
+ if_print(task);
+ if_print(watermark);
+ if_print(precise_ip);
+ if_print(mmap_data);
+ if_print(sample_id_all);
+ if_print(exclude_host);
+ if_print(exclude_guest);
+ if_print(__reserved_1);
+ if_print(wakeup_events);
+ if_print(bp_type);
+ if_print(branch_sample_type);
+ }
+
+ putchar('\n');
+ }
perf_session__delete(session);
return 0;
@@ -38,17 +113,23 @@ static const char * const evlist_usage[] = {
NULL
};
-static const struct option options[] = {
- OPT_STRING('i', "input", &input_name, "file",
- "input file name"),
- OPT_END()
-};
-
int cmd_evlist(int argc, const char **argv, const char *prefix __used)
{
+ struct perf_attr_details details = { .verbose = false, };
+ const char *input_name;
+ const struct option options[] = {
+ OPT_STRING('i', "input", &input_name, "file",
+ "Input file name"),
+ OPT_BOOLEAN('F', "freq", &details.freq,
+ "Show the sample frequency"),
+ OPT_BOOLEAN('v', "verbose", &details.verbose,
+ "Show all event attr details"),
+ OPT_END()
+ };
+
argc = parse_options(argc, argv, options, evlist_usage, 0);
if (argc)
usage_with_options(evlist_usage, options);
- return __cmd_evlist();
+ return __cmd_evlist(input_name, &details);
}
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 09c106193e65..3beab489afc5 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -60,6 +60,11 @@ static int perf_event__repipe_tracing_data_synth(union perf_event *event,
static int perf_event__repipe_attr(union perf_event *event,
struct perf_evlist **pevlist __used)
{
+ int ret;
+ ret = perf_event__process_attr(event, pevlist);
+ if (ret)
+ return ret;
+
return perf_event__repipe_synth(NULL, event, NULL);
}
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 39104c0beea3..547af48deb4f 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -192,7 +192,7 @@ static void insert_caller_stat(unsigned long call_site,
}
static void process_alloc_event(void *data,
- struct event *event,
+ struct event_format *event,
int cpu,
u64 timestamp __used,
struct thread *thread __used,
@@ -253,7 +253,7 @@ static struct alloc_stat *search_alloc_stat(unsigned long ptr,
}
static void process_free_event(void *data,
- struct event *event,
+ struct event_format *event,
int cpu,
u64 timestamp __used,
struct thread *thread __used)
@@ -281,7 +281,7 @@ static void process_free_event(void *data,
static void process_raw_event(union perf_event *raw_event __used, void *data,
int cpu, u64 timestamp, struct thread *thread)
{
- struct event *event;
+ struct event_format *event;
int type;
type = trace_parse_common_type(data);
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 12c814838993..fd53319de20d 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -356,25 +356,25 @@ struct trace_release_event {
struct trace_lock_handler {
void (*acquire_event)(struct trace_acquire_event *,
- struct event *,
+ struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*acquired_event)(struct trace_acquired_event *,
- struct event *,
+ struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*contended_event)(struct trace_contended_event *,
- struct event *,
+ struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*release_event)(struct trace_release_event *,
- struct event *,
+ struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
@@ -416,7 +416,7 @@ enum acquire_flags {
static void
report_lock_acquire_event(struct trace_acquire_event *acquire_event,
- struct event *__event __used,
+ struct event_format *__event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
@@ -480,7 +480,7 @@ end:
static void
report_lock_acquired_event(struct trace_acquired_event *acquired_event,
- struct event *__event __used,
+ struct event_format *__event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
@@ -536,7 +536,7 @@ end:
static void
report_lock_contended_event(struct trace_contended_event *contended_event,
- struct event *__event __used,
+ struct event_format *__event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
@@ -583,7 +583,7 @@ end:
static void
report_lock_release_event(struct trace_release_event *release_event,
- struct event *__event __used,
+ struct event_format *__event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
@@ -647,7 +647,7 @@ static struct trace_lock_handler *trace_handler;
static void
process_lock_acquire_event(void *data,
- struct event *event __used,
+ struct event_format *event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
@@ -666,7 +666,7 @@ process_lock_acquire_event(void *data,
static void
process_lock_acquired_event(void *data,
- struct event *event __used,
+ struct event_format *event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
@@ -684,7 +684,7 @@ process_lock_acquired_event(void *data,
static void
process_lock_contended_event(void *data,
- struct event *event __used,
+ struct event_format *event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
@@ -702,7 +702,7 @@ process_lock_contended_event(void *data,
static void
process_lock_release_event(void *data,
- struct event *event __used,
+ struct event_format *event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
@@ -721,7 +721,7 @@ process_lock_release_event(void *data,
static void
process_raw_event(void *data, int cpu, u64 timestamp, struct thread *thread)
{
- struct event *event;
+ struct event_format *event;
int type;
type = trace_parse_common_type(data);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index be4e1eee782e..e5cb08427e13 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -44,7 +44,6 @@ struct perf_record {
struct perf_evlist *evlist;
struct perf_session *session;
const char *progname;
- const char *uid_str;
int output;
unsigned int page_size;
int realtime_prio;
@@ -218,7 +217,7 @@ try_again:
if (err == EPERM || err == EACCES) {
ui__error_paranoid();
exit(EXIT_FAILURE);
- } else if (err == ENODEV && opts->cpu_list) {
+ } else if (err == ENODEV && opts->target.cpu_list) {
die("No such device - did you specify"
" an out-of-range profile CPU?\n");
} else if (err == EINVAL) {
@@ -243,9 +242,13 @@ try_again:
/*
* If it's cycles then fall back to hrtimer
* based cpu-clock-tick sw counter, which
- * is always available even if no PMU support:
+ * is always available even if no PMU support.
+ *
+ * PPC returns ENXIO until 2.6.37 (behavior changed
+ * with commit b0a873e).
*/
- if (attr->type == PERF_TYPE_HARDWARE
+ if ((err == ENOENT || err == ENXIO)
+ && attr->type == PERF_TYPE_HARDWARE
&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {
if (verbose)
@@ -253,6 +256,10 @@ try_again:
"trying to fall back to cpu-clock-ticks\n");
attr->type = PERF_TYPE_SOFTWARE;
attr->config = PERF_COUNT_SW_CPU_CLOCK;
+ if (pos->name) {
+ free(pos->name);
+ pos->name = NULL;
+ }
goto try_again;
}
@@ -389,7 +396,7 @@ static void perf_record__mmap_read_all(struct perf_record *rec)
perf_record__mmap_read(rec, &rec->evlist->mmap[i]);
}
- if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO))
+ if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
write_output(rec, &finished_round_event, sizeof(finished_round_event));
}
@@ -471,7 +478,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
if (!have_tracepoints(&evsel_list->entries))
- perf_header__clear_feat(&session->header, HEADER_TRACE_INFO);
+ perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
if (!rec->opts.branch_stack)
perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
@@ -578,7 +585,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
perf_session__process_machines(session, tool,
perf_event__synthesize_guest_os);
- if (!opts->system_wide)
+ if (!opts->target.system_wide)
perf_event__synthesize_thread_map(tool, evsel_list->threads,
process_synthesized_event,
machine);
@@ -746,7 +753,10 @@ static struct perf_record record = {
.mmap_pages = UINT_MAX,
.user_freq = UINT_MAX,
.user_interval = ULLONG_MAX,
- .freq = 1000,
+ .freq = 4000,
+ .target = {
+ .uses_mmap = true,
+ },
},
.write_mode = WRITE_FORCE,
.file_new = true,
@@ -765,9 +775,9 @@ const struct option record_options[] = {
parse_events_option),
OPT_CALLBACK(0, "filter", &record.evlist, "filter",
"event filter", parse_filter),
- OPT_STRING('p', "pid", &record.opts.target_pid, "pid",
+ OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
"record events on existing process id"),
- OPT_STRING('t', "tid", &record.opts.target_tid, "tid",
+ OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
"record events on existing thread id"),
OPT_INTEGER('r', "realtime", &record.realtime_prio,
"collect data with this RT SCHED_FIFO priority"),
@@ -775,11 +785,11 @@ const struct option record_options[] = {
"collect data without buffering"),
OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
"collect raw sample records from all opened counters"),
- OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide,
+ OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
"system-wide collection from all CPUs"),
OPT_BOOLEAN('A', "append", &record.append_file,
"append to the output file to do incremental profiling"),
- OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu",
+ OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
"list of cpus to monitor"),
OPT_BOOLEAN('f', "force", &record.force,
"overwrite existing data file (deprecated)"),
@@ -813,7 +823,8 @@ const struct option record_options[] = {
OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
"monitor event in cgroup name only",
parse_cgroups),
- OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"),
+ OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
+ "user to profile"),
OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
"branch any", "sample any taken branches",
@@ -831,6 +842,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
struct perf_evsel *pos;
struct perf_evlist *evsel_list;
struct perf_record *rec = &record;
+ char errbuf[BUFSIZ];
perf_header__set_cmdline(argc, argv);
@@ -842,8 +854,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
argc = parse_options(argc, argv, record_options, record_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
- if (!argc && !rec->opts.target_pid && !rec->opts.target_tid &&
- !rec->opts.system_wide && !rec->opts.cpu_list && !rec->uid_str)
+ if (!argc && perf_target__none(&rec->opts.target))
usage_with_options(record_usage, record_options);
if (rec->force && rec->append_file) {
@@ -856,7 +867,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
rec->write_mode = WRITE_FORCE;
}
- if (nr_cgroups && !rec->opts.system_wide) {
+ if (nr_cgroups && !rec->opts.target.system_wide) {
fprintf(stderr, "cgroup monitoring only available in"
" system-wide mode\n");
usage_with_options(record_usage, record_options);
@@ -883,17 +894,25 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
goto out_symbol_exit;
}
- rec->opts.uid = parse_target_uid(rec->uid_str, rec->opts.target_tid,
- rec->opts.target_pid);
- if (rec->uid_str != NULL && rec->opts.uid == UINT_MAX - 1)
- goto out_free_fd;
+ err = perf_target__validate(&rec->opts.target);
+ if (err) {
+ perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
+ ui__warning("%s", errbuf);
+ }
+
+ err = perf_target__parse_uid(&rec->opts.target);
+ if (err) {
+ int saved_errno = errno;
- if (rec->opts.target_pid)
- rec->opts.target_tid = rec->opts.target_pid;
+ perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
+ ui__warning("%s", errbuf);
+
+ err = -saved_errno;
+ goto out_free_fd;
+ }
- if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid,
- rec->opts.target_tid, rec->opts.uid,
- rec->opts.cpu_list) < 0)
+ err = -ENOMEM;
+ if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
usage_with_options(record_usage, record_options);
list_for_each_entry(pos, &evsel_list->entries, node) {
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index cdae9b2db1cc..d58e41445d0d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -296,12 +296,15 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self,
{
size_t ret;
char unit;
- unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE];
+ unsigned long nr_samples = self->stats.nr_events[PERF_RECORD_SAMPLE];
+ u64 nr_events = self->stats.total_period;
- nr_events = convert_unit(nr_events, &unit);
- ret = fprintf(fp, "# Events: %lu%c", nr_events, unit);
+ nr_samples = convert_unit(nr_samples, &unit);
+ ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
if (evname != NULL)
- ret += fprintf(fp, " %s", evname);
+ ret += fprintf(fp, " of event '%s'", evname);
+
+ ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
return ret + fprintf(fp, "\n#\n");
}
@@ -680,14 +683,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
}
- if (strcmp(report.input_name, "-") != 0) {
- if (report.use_gtk)
- perf_gtk_setup_browser(argc, argv, true);
- else
- setup_browser(true);
- } else {
+ if (strcmp(report.input_name, "-") != 0)
+ setup_browser(true);
+ else
use_browser = 0;
- }
/*
* Only in the newt browser we are doing integrated annotation,
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 1cad3af4bf4c..b125e07eb399 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -728,34 +728,34 @@ struct trace_migrate_task_event {
struct trace_sched_handler {
void (*switch_event)(struct trace_switch_event *,
struct machine *,
- struct event *,
+ struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*runtime_event)(struct trace_runtime_event *,
struct machine *,
- struct event *,
+ struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*wakeup_event)(struct trace_wakeup_event *,
struct machine *,
- struct event *,
+ struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*fork_event)(struct trace_fork_event *,
- struct event *,
+ struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*migrate_task_event)(struct trace_migrate_task_event *,
struct machine *machine,
- struct event *,
+ struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
@@ -765,7 +765,7 @@ struct trace_sched_handler {
static void
replay_wakeup_event(struct trace_wakeup_event *wakeup_event,
struct machine *machine __used,
- struct event *event,
+ struct event_format *event,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
@@ -792,7 +792,7 @@ static u64 cpu_last_switched[MAX_CPUS];
static void
replay_switch_event(struct trace_switch_event *switch_event,
struct machine *machine __used,
- struct event *event,
+ struct event_format *event,
int cpu,
u64 timestamp,
struct thread *thread __used)
@@ -835,7 +835,7 @@ replay_switch_event(struct trace_switch_event *switch_event,
static void
replay_fork_event(struct trace_fork_event *fork_event,
- struct event *event,
+ struct event_format *event,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
@@ -944,7 +944,7 @@ static void thread_atoms_insert(struct thread *thread)
static void
latency_fork_event(struct trace_fork_event *fork_event __used,
- struct event *event __used,
+ struct event_format *event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
@@ -1026,7 +1026,7 @@ add_sched_in_event(struct work_atoms *atoms, u64 timestamp)
static void
latency_switch_event(struct trace_switch_event *switch_event,
struct machine *machine,
- struct event *event __used,
+ struct event_format *event __used,
int cpu,
u64 timestamp,
struct thread *thread __used)
@@ -1079,7 +1079,7 @@ latency_switch_event(struct trace_switch_event *switch_event,
static void
latency_runtime_event(struct trace_runtime_event *runtime_event,
struct machine *machine,
- struct event *event __used,
+ struct event_format *event __used,
int cpu,
u64 timestamp,
struct thread *this_thread __used)
@@ -1102,7 +1102,7 @@ latency_runtime_event(struct trace_runtime_event *runtime_event,
static void
latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
struct machine *machine,
- struct event *__event __used,
+ struct event_format *__event __used,
int cpu __used,
u64 timestamp,
struct thread *thread __used)
@@ -1150,7 +1150,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
static void
latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
struct machine *machine,
- struct event *__event __used,
+ struct event_format *__event __used,
int cpu __used,
u64 timestamp,
struct thread *thread __used)
@@ -1361,7 +1361,7 @@ static struct trace_sched_handler *trace_handler;
static void
process_sched_wakeup_event(struct perf_tool *tool __used,
- struct event *event,
+ struct event_format *event,
struct perf_sample *sample,
struct machine *machine,
struct thread *thread)
@@ -1398,7 +1398,7 @@ static char next_shortname2 = '0';
static void
map_switch_event(struct trace_switch_event *switch_event,
struct machine *machine,
- struct event *event __used,
+ struct event_format *event __used,
int this_cpu,
u64 timestamp,
struct thread *thread __used)
@@ -1476,7 +1476,7 @@ map_switch_event(struct trace_switch_event *switch_event,
static void
process_sched_switch_event(struct perf_tool *tool __used,
- struct event *event,
+ struct event_format *event,
struct perf_sample *sample,
struct machine *machine,
struct thread *thread)
@@ -1512,7 +1512,7 @@ process_sched_switch_event(struct perf_tool *tool __used,
static void
process_sched_runtime_event(struct perf_tool *tool __used,
- struct event *event,
+ struct event_format *event,
struct perf_sample *sample,
struct machine *machine,
struct thread *thread)
@@ -1532,7 +1532,7 @@ process_sched_runtime_event(struct perf_tool *tool __used,
static void
process_sched_fork_event(struct perf_tool *tool __used,
- struct event *event,
+ struct event_format *event,
struct perf_sample *sample,
struct machine *machine __used,
struct thread *thread)
@@ -1554,7 +1554,7 @@ process_sched_fork_event(struct perf_tool *tool __used,
static void
process_sched_exit_event(struct perf_tool *tool __used,
- struct event *event,
+ struct event_format *event,
struct perf_sample *sample __used,
struct machine *machine __used,
struct thread *thread __used)
@@ -1565,7 +1565,7 @@ process_sched_exit_event(struct perf_tool *tool __used,
static void
process_sched_migrate_task_event(struct perf_tool *tool __used,
- struct event *event,
+ struct event_format *event,
struct perf_sample *sample,
struct machine *machine,
struct thread *thread)
@@ -1586,7 +1586,7 @@ process_sched_migrate_task_event(struct perf_tool *tool __used,
sample->time, thread);
}
-typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event *event,
+typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event_format *event,
struct perf_sample *sample,
struct machine *machine,
struct thread *thread);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index d4ce733b9eba..8e395a538eb9 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -261,7 +261,7 @@ static void print_sample_start(struct perf_sample *sample,
struct perf_event_attr *attr)
{
int type;
- struct event *event;
+ struct event_format *event;
const char *evname = NULL;
unsigned long secs;
unsigned long usecs;
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index c941bb640f49..62ae30d34fa6 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -173,24 +173,23 @@ static struct perf_event_attr very_very_detailed_attrs[] = {
-struct perf_evlist *evsel_list;
+static struct perf_evlist *evsel_list;
-static bool system_wide = false;
-static int run_idx = 0;
+static struct perf_target target = {
+ .uid = UINT_MAX,
+};
+static int run_idx = 0;
static int run_count = 1;
static bool no_inherit = false;
static bool scale = true;
static bool no_aggr = false;
-static const char *target_pid;
-static const char *target_tid;
static pid_t child_pid = -1;
static bool null_run = false;
static int detailed_run = 0;
static bool sync_run = false;
static bool big_num = true;
static int big_num_opt = -1;
-static const char *cpu_list;
static const char *csv_sep = NULL;
static bool csv_output = false;
static bool group = false;
@@ -265,24 +264,26 @@ static double stddev_stats(struct stats *stats)
return sqrt(variance_mean);
}
-struct stats runtime_nsecs_stats[MAX_NR_CPUS];
-struct stats runtime_cycles_stats[MAX_NR_CPUS];
-struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS];
-struct stats runtime_stalled_cycles_back_stats[MAX_NR_CPUS];
-struct stats runtime_branches_stats[MAX_NR_CPUS];
-struct stats runtime_cacherefs_stats[MAX_NR_CPUS];
-struct stats runtime_l1_dcache_stats[MAX_NR_CPUS];
-struct stats runtime_l1_icache_stats[MAX_NR_CPUS];
-struct stats runtime_ll_cache_stats[MAX_NR_CPUS];
-struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
-struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
-struct stats walltime_nsecs_stats;
+static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
+static struct stats runtime_cycles_stats[MAX_NR_CPUS];
+static struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS];
+static struct stats runtime_stalled_cycles_back_stats[MAX_NR_CPUS];
+static struct stats runtime_branches_stats[MAX_NR_CPUS];
+static struct stats runtime_cacherefs_stats[MAX_NR_CPUS];
+static struct stats runtime_l1_dcache_stats[MAX_NR_CPUS];
+static struct stats runtime_l1_icache_stats[MAX_NR_CPUS];
+static struct stats runtime_ll_cache_stats[MAX_NR_CPUS];
+static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
+static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
+static struct stats walltime_nsecs_stats;
static int create_perf_stat_counter(struct perf_evsel *evsel,
struct perf_evsel *first)
{
struct perf_event_attr *attr = &evsel->attr;
struct xyarray *group_fd = NULL;
+ bool exclude_guest_missing = false;
+ int ret;
if (group && evsel != first)
group_fd = first->fd;
@@ -293,16 +294,39 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
attr->inherit = !no_inherit;
- if (system_wide)
- return perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
- group, group_fd);
- if (!target_pid && !target_tid && (!group || evsel == first)) {
+retry:
+ if (exclude_guest_missing)
+ evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
+
+ if (perf_target__has_cpu(&target)) {
+ ret = perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
+ group, group_fd);
+ if (ret)
+ goto check_ret;
+ return 0;
+ }
+
+ if (!perf_target__has_task(&target) && (!group || evsel == first)) {
attr->disabled = 1;
attr->enable_on_exec = 1;
}
- return perf_evsel__open_per_thread(evsel, evsel_list->threads,
- group, group_fd);
+ ret = perf_evsel__open_per_thread(evsel, evsel_list->threads,
+ group, group_fd);
+ if (!ret)
+ return 0;
+ /* fall through */
+check_ret:
+ if (ret && errno == EINVAL) {
+ if (!exclude_guest_missing &&
+ (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
+ pr_debug("Old kernel, cannot exclude "
+ "guest or host samples.\n");
+ exclude_guest_missing = true;
+ goto retry;
+ }
+ }
+ return ret;
}
/*
@@ -446,7 +470,7 @@ static int run_perf_stat(int argc __used, const char **argv)
exit(-1);
}
- if (!target_tid && !target_pid && !system_wide)
+ if (perf_target__none(&target))
evsel_list->threads->map[0] = child_pid;
/*
@@ -463,8 +487,13 @@ static int run_perf_stat(int argc __used, const char **argv)
list_for_each_entry(counter, &evsel_list->entries, node) {
if (create_perf_stat_counter(counter, first) < 0) {
+ /*
+ * PPC returns ENXIO for HW counters until 2.6.37
+ * (behavior changed with commit b0a873e).
+ */
if (errno == EINVAL || errno == ENOSYS ||
- errno == ENOENT || errno == EOPNOTSUPP) {
+ errno == ENOENT || errno == EOPNOTSUPP ||
+ errno == ENXIO) {
if (verbose)
ui__warning("%s event is not supported by the kernel.\n",
event_name(counter));
@@ -476,7 +505,7 @@ static int run_perf_stat(int argc __used, const char **argv)
error("You may not have permission to collect %sstats.\n"
"\t Consider tweaking"
" /proc/sys/kernel/perf_event_paranoid or running as root.",
- system_wide ? "system-wide " : "");
+ target.system_wide ? "system-wide " : "");
} else {
error("open_counter returned with %d (%s). "
"/bin/dmesg may provide additional information.\n",
@@ -968,14 +997,14 @@ static void print_stat(int argc, const char **argv)
if (!csv_output) {
fprintf(output, "\n");
fprintf(output, " Performance counter stats for ");
- if (!target_pid && !target_tid) {
+ if (!perf_target__has_task(&target)) {
fprintf(output, "\'%s", argv[0]);
for (i = 1; i < argc; i++)
fprintf(output, " %s", argv[i]);
- } else if (target_pid)
- fprintf(output, "process id \'%s", target_pid);
+ } else if (target.pid)
+ fprintf(output, "process id \'%s", target.pid);
else
- fprintf(output, "thread id \'%s", target_tid);
+ fprintf(output, "thread id \'%s", target.tid);
fprintf(output, "\'");
if (run_count > 1)
@@ -1049,11 +1078,11 @@ static const struct option options[] = {
"event filter", parse_filter),
OPT_BOOLEAN('i', "no-inherit", &no_inherit,
"child tasks do not inherit counters"),
- OPT_STRING('p', "pid", &target_pid, "pid",
+ OPT_STRING('p', "pid", &target.pid, "pid",
"stat events on existing process id"),
- OPT_STRING('t', "tid", &target_tid, "tid",
+ OPT_STRING('t', "tid", &target.tid, "tid",
"stat events on existing thread id"),
- OPT_BOOLEAN('a', "all-cpus", &system_wide,
+ OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
"system-wide collection from all CPUs"),
OPT_BOOLEAN('g', "group", &group,
"put the counters into a counter group"),
@@ -1072,7 +1101,7 @@ static const struct option options[] = {
OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
"print large numbers with thousands\' separators",
stat__set_big_num),
- OPT_STRING('C', "cpu", &cpu_list, "cpu",
+ OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
"list of cpus to monitor in system-wide"),
OPT_BOOLEAN('A', "no-aggr", &no_aggr,
"disable CPU count aggregation"),
@@ -1190,13 +1219,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
} else if (big_num_opt == 0) /* User passed --no-big-num */
big_num = false;
- if (!argc && !target_pid && !target_tid)
+ if (!argc && !perf_target__has_task(&target))
usage_with_options(stat_usage, options);
if (run_count <= 0)
usage_with_options(stat_usage, options);
/* no_aggr, cgroup are for system-wide only */
- if ((no_aggr || nr_cgroups) && !system_wide) {
+ if ((no_aggr || nr_cgroups) && !perf_target__has_cpu(&target)) {
fprintf(stderr, "both cgroup and no-aggregation "
"modes only available in system-wide mode\n");
@@ -1206,23 +1235,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
if (add_default_attributes())
goto out;
- if (target_pid)
- target_tid = target_pid;
+ perf_target__validate(&target);
- evsel_list->threads = thread_map__new_str(target_pid,
- target_tid, UINT_MAX);
- if (evsel_list->threads == NULL) {
- pr_err("Problems finding threads of monitor\n");
- usage_with_options(stat_usage, options);
- }
-
- if (system_wide)
- evsel_list->cpus = cpu_map__new(cpu_list);
- else
- evsel_list->cpus = cpu_map__dummy_new();
+ if (perf_evlist__create_maps(evsel_list, &target) < 0) {
+ if (perf_target__has_task(&target))
+ pr_err("Problems finding threads of monitor\n");
+ if (perf_target__has_cpu(&target))
+ perror("failed to parse CPUs map");
- if (evsel_list->cpus == NULL) {
- perror("failed to parse CPUs map");
usage_with_options(stat_usage, options);
return -1;
}
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 223ffdcc0fd8..5a8727c08757 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -604,556 +604,6 @@ out_free_threads:
#undef nsyscalls
}
-#define TEST_ASSERT_VAL(text, cond) \
-do { \
- if (!(cond)) { \
- pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
- return -1; \
- } \
-} while (0)
-
-static int test__checkevent_tracepoint(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong sample_type",
- (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
- evsel->attr.sample_type);
- TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
- return 0;
-}
-
-static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel;
-
- TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
-
- list_for_each_entry(evsel, &evlist->entries, node) {
- TEST_ASSERT_VAL("wrong type",
- PERF_TYPE_TRACEPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong sample_type",
- (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU)
- == evsel->attr.sample_type);
- TEST_ASSERT_VAL("wrong sample_period",
- 1 == evsel->attr.sample_period);
- }
- return 0;
-}
-
-static int test__checkevent_raw(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 0x1a == evsel->attr.config);
- return 0;
-}
-
-static int test__checkevent_numeric(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
- return 0;
-}
-
-static int test__checkevent_symbolic_name(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
- return 0;
-}
-
-static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
- TEST_ASSERT_VAL("wrong period",
- 100000 == evsel->attr.sample_period);
- TEST_ASSERT_VAL("wrong config1",
- 0 == evsel->attr.config1);
- TEST_ASSERT_VAL("wrong config2",
- 1 == evsel->attr.config2);
- return 0;
-}
-
-static int test__checkevent_symbolic_alias(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config",
- PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config);
- return 0;
-}
-
-static int test__checkevent_genhw(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", (1 << 16) == evsel->attr.config);
- return 0;
-}
-
-static int test__checkevent_breakpoint(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
- TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) ==
- evsel->attr.bp_type);
- TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_4 ==
- evsel->attr.bp_len);
- return 0;
-}
-
-static int test__checkevent_breakpoint_x(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
- TEST_ASSERT_VAL("wrong bp_type",
- HW_BREAKPOINT_X == evsel->attr.bp_type);
- TEST_ASSERT_VAL("wrong bp_len", sizeof(long) == evsel->attr.bp_len);
- return 0;
-}
-
-static int test__checkevent_breakpoint_r(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type",
- PERF_TYPE_BREAKPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
- TEST_ASSERT_VAL("wrong bp_type",
- HW_BREAKPOINT_R == evsel->attr.bp_type);
- TEST_ASSERT_VAL("wrong bp_len",
- HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
- return 0;
-}
-
-static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type",
- PERF_TYPE_BREAKPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
- TEST_ASSERT_VAL("wrong bp_type",
- HW_BREAKPOINT_W == evsel->attr.bp_type);
- TEST_ASSERT_VAL("wrong bp_len",
- HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
- return 0;
-}
-
-static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
-
- return test__checkevent_tracepoint(evlist);
-}
-
-static int
-test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel;
-
- TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
-
- list_for_each_entry(evsel, &evlist->entries, node) {
- TEST_ASSERT_VAL("wrong exclude_user",
- !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel",
- evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- }
-
- return test__checkevent_tracepoint_multi(evlist);
-}
-
-static int test__checkevent_raw_modifier(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
-
- return test__checkevent_raw(evlist);
-}
-
-static int test__checkevent_numeric_modifier(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
-
- return test__checkevent_numeric(evlist);
-}
-
-static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
-
- return test__checkevent_symbolic_name(evlist);
-}
-
-static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
-
- return test__checkevent_symbolic_name(evlist);
-}
-
-static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
- TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
-
- return test__checkevent_symbolic_name(evlist);
-}
-
-static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
-
- return test__checkevent_symbolic_alias(evlist);
-}
-
-static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
-
- return test__checkevent_genhw(evlist);
-}
-
-static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
-
- return test__checkevent_breakpoint(evlist);
-}
-
-static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
-
- return test__checkevent_breakpoint_x(evlist);
-}
-
-static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
-
- return test__checkevent_breakpoint_r(evlist);
-}
-
-static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
-
- return test__checkevent_breakpoint_w(evlist);
-}
-
-static int test__checkevent_pmu(struct perf_evlist *evlist)
-{
-
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
-
- TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 10 == evsel->attr.config);
- TEST_ASSERT_VAL("wrong config1", 1 == evsel->attr.config1);
- TEST_ASSERT_VAL("wrong config2", 3 == evsel->attr.config2);
- TEST_ASSERT_VAL("wrong period", 1000 == evsel->attr.sample_period);
-
- return 0;
-}
-
-static int test__checkevent_list(struct perf_evlist *evlist)
-{
- struct perf_evsel *evsel;
-
- TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
-
- /* r1 */
- evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
- TEST_ASSERT_VAL("wrong config1", 0 == evsel->attr.config1);
- TEST_ASSERT_VAL("wrong config2", 0 == evsel->attr.config2);
- TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
-
- /* syscalls:sys_enter_open:k */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
- TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
- TEST_ASSERT_VAL("wrong sample_type",
- (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
- evsel->attr.sample_type);
- TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
-
- /* 1:1:hp */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
- TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
- TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
- TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
- TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
- TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
- TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
-
- return 0;
-}
-
-static struct test__event_st {
- const char *name;
- __u32 type;
- int (*check)(struct perf_evlist *evlist);
-} test__events[] = {
- {
- .name = "syscalls:sys_enter_open",
- .check = test__checkevent_tracepoint,
- },
- {
- .name = "syscalls:*",
- .check = test__checkevent_tracepoint_multi,
- },
- {
- .name = "r1a",
- .check = test__checkevent_raw,
- },
- {
- .name = "1:1",
- .check = test__checkevent_numeric,
- },
- {
- .name = "instructions",
- .check = test__checkevent_symbolic_name,
- },
- {
- .name = "cycles/period=100000,config2/",
- .check = test__checkevent_symbolic_name_config,
- },
- {
- .name = "faults",
- .check = test__checkevent_symbolic_alias,
- },
- {
- .name = "L1-dcache-load-miss",
- .check = test__checkevent_genhw,
- },
- {
- .name = "mem:0",
- .check = test__checkevent_breakpoint,
- },
- {
- .name = "mem:0:x",
- .check = test__checkevent_breakpoint_x,
- },
- {
- .name = "mem:0:r",
- .check = test__checkevent_breakpoint_r,
- },
- {
- .name = "mem:0:w",
- .check = test__checkevent_breakpoint_w,
- },
- {
- .name = "syscalls:sys_enter_open:k",
- .check = test__checkevent_tracepoint_modifier,
- },
- {
- .name = "syscalls:*:u",
- .check = test__checkevent_tracepoint_multi_modifier,
- },
- {
- .name = "r1a:kp",
- .check = test__checkevent_raw_modifier,
- },
- {
- .name = "1:1:hp",
- .check = test__checkevent_numeric_modifier,
- },
- {
- .name = "instructions:h",
- .check = test__checkevent_symbolic_name_modifier,
- },
- {
- .name = "faults:u",
- .check = test__checkevent_symbolic_alias_modifier,
- },
- {
- .name = "L1-dcache-load-miss:kp",
- .check = test__checkevent_genhw_modifier,
- },
- {
- .name = "mem:0:u",
- .check = test__checkevent_breakpoint_modifier,
- },
- {
- .name = "mem:0:x:k",
- .check = test__checkevent_breakpoint_x_modifier,
- },
- {
- .name = "mem:0:r:hp",
- .check = test__checkevent_breakpoint_r_modifier,
- },
- {
- .name = "mem:0:w:up",
- .check = test__checkevent_breakpoint_w_modifier,
- },
- {
- .name = "cpu/config=10,config1,config2=3,period=1000/u",
- .check = test__checkevent_pmu,
- },
- {
- .name = "r1,syscalls:sys_enter_open:k,1:1:hp",
- .check = test__checkevent_list,
- },
- {
- .name = "instructions:G",
- .check = test__checkevent_exclude_host_modifier,
- },
- {
- .name = "instructions:H",
- .check = test__checkevent_exclude_guest_modifier,
- },
-};
-
-#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
-
-static int test__parse_events(void)
-{
- struct perf_evlist *evlist;
- u_int i;
- int ret = 0;
-
- for (i = 0; i < TEST__EVENTS_CNT; i++) {
- struct test__event_st *e = &test__events[i];
-
- evlist = perf_evlist__new(NULL, NULL);
- if (evlist == NULL)
- break;
-
- ret = parse_events(evlist, e->name, 0);
- if (ret) {
- pr_debug("failed to parse event '%s', err %d\n",
- e->name, ret);
- break;
- }
-
- ret = e->check(evlist);
- perf_evlist__delete(evlist);
- if (ret)
- break;
- }
-
- return ret;
-}
-
static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t **maskp,
size_t *sizep)
{
@@ -1195,6 +645,10 @@ realloc:
static int test__PERF_RECORD(void)
{
struct perf_record_opts opts = {
+ .target = {
+ .uid = UINT_MAX,
+ .uses_mmap = true,
+ },
.no_delay = true,
.freq = 10,
.mmap_pages = 256,
@@ -1237,8 +691,7 @@ static int test__PERF_RECORD(void)
* perf_evlist__prepare_workload we'll fill in the only thread
* we're monitoring, the one forked there.
*/
- err = perf_evlist__create_maps(evlist, opts.target_pid,
- opts.target_tid, UINT_MAX, opts.cpu_list);
+ err = perf_evlist__create_maps(evlist, &opts.target);
if (err < 0) {
pr_debug("Not enough memory to create thread/cpu maps\n");
goto out_delete_evlist;
@@ -1579,8 +1032,6 @@ static int __test__rdpmc(void)
sa.sa_sigaction = segfault_handler;
sigaction(SIGSEGV, &sa, NULL);
- fprintf(stderr, "\n\n");
-
fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
if (fd < 0) {
die("Error: sys_perf_event_open() syscall returned "
@@ -1605,7 +1056,7 @@ static int __test__rdpmc(void)
loops *= 10;
delta = now - stamp;
- fprintf(stderr, "%14d: %14Lu\n", n, (long long)delta);
+ pr_debug("%14d: %14Lu\n", n, (long long)delta);
delta_sum += delta;
}
@@ -1613,7 +1064,7 @@ static int __test__rdpmc(void)
munmap(addr, page_size);
close(fd);
- fprintf(stderr, " ");
+ pr_debug(" ");
if (!delta_sum)
return -1;
@@ -1674,7 +1125,7 @@ static struct test {
},
{
.desc = "parse events tests",
- .func = test__parse_events,
+ .func = parse_events__test,
},
#if defined(__x86_64__) || defined(__i386__)
{
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 8ef59f8262bb..6031dce0429f 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -588,7 +588,7 @@ static void *display_thread_tui(void *arg)
* via --uid.
*/
list_for_each_entry(pos, &top->evlist->entries, node)
- pos->hists.uid_filter_str = top->uid_str;
+ pos->hists.uid_filter_str = top->target.uid_str;
perf_evlist__tui_browse_hists(top->evlist, help,
perf_top__sort_new_samples,
@@ -900,6 +900,9 @@ static void perf_top__start_counters(struct perf_top *top)
attr->read_format |= PERF_FORMAT_ID;
}
+ if (perf_target__has_cpu(&top->target))
+ attr->sample_type |= PERF_SAMPLE_CPU;
+
if (symbol_conf.use_callchain)
attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
@@ -948,6 +951,10 @@ try_again:
attr->type = PERF_TYPE_SOFTWARE;
attr->config = PERF_COUNT_SW_CPU_CLOCK;
+ if (counter->name) {
+ free(counter->name);
+ counter->name = strdup(event_name(counter));
+ }
goto try_again;
}
@@ -1016,7 +1023,7 @@ static int __cmd_top(struct perf_top *top)
if (ret)
goto out_delete;
- if (top->target_tid || top->uid != UINT_MAX)
+ if (perf_target__has_task(&top->target))
perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
perf_event__process,
&top->session->host_machine);
@@ -1150,14 +1157,17 @@ static const char * const top_usage[] = {
int cmd_top(int argc, const char **argv, const char *prefix __used)
{
struct perf_evsel *pos;
- int status = -ENOMEM;
+ int status;
+ char errbuf[BUFSIZ];
struct perf_top top = {
.count_filter = 5,
.delay_secs = 2,
- .uid = UINT_MAX,
- .freq = 1000, /* 1 KHz */
+ .freq = 4000, /* 4 KHz */
.mmap_pages = 128,
.sym_pcnt_filter = 5,
+ .target = {
+ .uses_mmap = true,
+ },
};
char callchain_default_opt[] = "fractal,0.5,callee";
const struct option options[] = {
@@ -1166,13 +1176,13 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
parse_events_option),
OPT_INTEGER('c', "count", &top.default_interval,
"event period to sample"),
- OPT_STRING('p', "pid", &top.target_pid, "pid",
+ OPT_STRING('p', "pid", &top.target.pid, "pid",
"profile events on existing process id"),
- OPT_STRING('t', "tid", &top.target_tid, "tid",
+ OPT_STRING('t', "tid", &top.target.tid, "tid",
"profile events on existing thread id"),
- OPT_BOOLEAN('a', "all-cpus", &top.system_wide,
+ OPT_BOOLEAN('a', "all-cpus", &top.target.system_wide,
"system-wide collection from all CPUs"),
- OPT_STRING('C', "cpu", &top.cpu_list, "cpu",
+ OPT_STRING('C', "cpu", &top.target.cpu_list, "cpu",
"list of cpus to monitor"),
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
"file", "vmlinux pathname"),
@@ -1227,7 +1237,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
"Display raw encoding of assembly instructions (default)"),
OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
"Specify disassembler style (e.g. -M intel for intel syntax)"),
- OPT_STRING('u', "uid", &top.uid_str, "user", "user to profile"),
+ OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"),
OPT_END()
};
@@ -1253,22 +1263,27 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
setup_browser(false);
- top.uid = parse_target_uid(top.uid_str, top.target_tid, top.target_pid);
- if (top.uid_str != NULL && top.uid == UINT_MAX - 1)
- goto out_delete_evlist;
+ status = perf_target__validate(&top.target);
+ if (status) {
+ perf_target__strerror(&top.target, status, errbuf, BUFSIZ);
+ ui__warning("%s", errbuf);
+ }
- /* CPU and PID are mutually exclusive */
- if (top.target_tid && top.cpu_list) {
- printf("WARNING: PID switch overriding CPU\n");
- sleep(1);
- top.cpu_list = NULL;
+ status = perf_target__parse_uid(&top.target);
+ if (status) {
+ int saved_errno = errno;
+
+ perf_target__strerror(&top.target, status, errbuf, BUFSIZ);
+ ui__warning("%s", errbuf);
+
+ status = -saved_errno;
+ goto out_delete_evlist;
}
- if (top.target_pid)
- top.target_tid = top.target_pid;
+ if (perf_target__none(&top.target))
+ top.target.system_wide = true;
- if (perf_evlist__create_maps(top.evlist, top.target_pid,
- top.target_tid, top.uid, top.cpu_list) < 0)
+ if (perf_evlist__create_maps(top.evlist, &top.target) < 0)
usage_with_options(top_usage, options);
if (!top.evlist->nr_entries &&
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 89e3355ab173..14f1034f14f9 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -207,10 +207,10 @@ extern const char perf_version_string[];
void pthread__unblock_sigwinch(void);
+#include "util/target.h"
+
struct perf_record_opts {
- const char *target_pid;
- const char *target_tid;
- uid_t uid;
+ struct perf_target target;
bool call_graph;
bool group;
bool inherit_stat;
@@ -223,7 +223,6 @@ struct perf_record_opts {
bool sample_time;
bool sample_id_all_missing;
bool exclude_guest_missing;
- bool system_wide;
bool period;
unsigned int freq;
unsigned int mmap_pages;
@@ -231,7 +230,6 @@ struct perf_record_opts {
int branch_stack;
u64 default_interval;
u64 user_interval;
- const char *cpu_list;
};
#endif
diff --git a/tools/perf/util/ui/browser.c b/tools/perf/ui/browser.c
index 556829124b02..cde4d0f0ddb9 100644
--- a/tools/perf/util/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -27,9 +27,12 @@ static int ui_browser__percent_color(struct ui_browser *browser,
return HE_COLORSET_NORMAL;
}
-void ui_browser__set_color(struct ui_browser *self __used, int color)
+int ui_browser__set_color(struct ui_browser *browser, int color)
{
+ int ret = browser->current_color;
+ browser->current_color = color;
SLsmg_set_color(color);
+ return ret;
}
void ui_browser__set_percent_color(struct ui_browser *self,
@@ -503,6 +506,12 @@ static struct ui_browser__colorset {
.bg = "default",
},
{
+ .colorset = HE_COLORSET_ADDR,
+ .name = "addr",
+ .fg = "magenta",
+ .bg = "default",
+ },
+ {
.name = NULL,
}
};
@@ -584,6 +593,111 @@ unsigned int ui_browser__argv_refresh(struct ui_browser *browser)
return row;
}
+void __ui_browser__vline(struct ui_browser *browser, unsigned int column,
+ u16 start, u16 end)
+{
+ SLsmg_set_char_set(1);
+ ui_browser__gotorc(browser, start, column);
+ SLsmg_draw_vline(end - start + 1);
+ SLsmg_set_char_set(0);
+}
+
+void ui_browser__write_graph(struct ui_browser *browser __used, int graph)
+{
+ SLsmg_set_char_set(1);
+ SLsmg_write_char(graph);
+ SLsmg_set_char_set(0);
+}
+
+static void __ui_browser__line_arrow_up(struct ui_browser *browser,
+ unsigned int column,
+ u64 start, u64 end)
+{
+ unsigned int row, end_row;
+
+ SLsmg_set_char_set(1);
+
+ if (start < browser->top_idx + browser->height) {
+ row = start - browser->top_idx;
+ ui_browser__gotorc(browser, row, column);
+ SLsmg_write_char(SLSMG_LLCORN_CHAR);
+ ui_browser__gotorc(browser, row, column + 1);
+ SLsmg_draw_hline(2);
+
+ if (row-- == 0)
+ goto out;
+ } else
+ row = browser->height - 1;
+
+ if (end > browser->top_idx)
+ end_row = end - browser->top_idx;
+ else
+ end_row = 0;
+
+ ui_browser__gotorc(browser, end_row, column);
+ SLsmg_draw_vline(row - end_row + 1);
+
+ ui_browser__gotorc(browser, end_row, column);
+ if (end >= browser->top_idx) {
+ SLsmg_write_char(SLSMG_ULCORN_CHAR);
+ ui_browser__gotorc(browser, end_row, column + 1);
+ SLsmg_write_char(SLSMG_HLINE_CHAR);
+ ui_browser__gotorc(browser, end_row, column + 2);
+ SLsmg_write_char(SLSMG_RARROW_CHAR);
+ }
+out:
+ SLsmg_set_char_set(0);
+}
+
+static void __ui_browser__line_arrow_down(struct ui_browser *browser,
+ unsigned int column,
+ u64 start, u64 end)
+{
+ unsigned int row, end_row;
+
+ SLsmg_set_char_set(1);
+
+ if (start >= browser->top_idx) {
+ row = start - browser->top_idx;
+ ui_browser__gotorc(browser, row, column);
+ SLsmg_write_char(SLSMG_ULCORN_CHAR);
+ ui_browser__gotorc(browser, row, column + 1);
+ SLsmg_draw_hline(2);
+
+ if (row++ == 0)
+ goto out;
+ } else
+ row = 0;
+
+ if (end >= browser->top_idx + browser->height)
+ end_row = browser->height - 1;
+ else
+ end_row = end - browser->top_idx;;
+
+ ui_browser__gotorc(browser, row, column);
+ SLsmg_draw_vline(end_row - row + 1);
+
+ ui_browser__gotorc(browser, end_row, column);
+ if (end < browser->top_idx + browser->height) {
+ SLsmg_write_char(SLSMG_LLCORN_CHAR);
+ ui_browser__gotorc(browser, end_row, column + 1);
+ SLsmg_write_char(SLSMG_HLINE_CHAR);
+ ui_browser__gotorc(browser, end_row, column + 2);
+ SLsmg_write_char(SLSMG_RARROW_CHAR);
+ }
+out:
+ SLsmg_set_char_set(0);
+}
+
+void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
+ u64 start, u64 end)
+{
+ if (start > end)
+ __ui_browser__line_arrow_up(browser, column, start, end);
+ else
+ __ui_browser__line_arrow_down(browser, column, start, end);
+}
+
void ui_browser__init(void)
{
int i = 0;
diff --git a/tools/perf/util/ui/browser.h b/tools/perf/ui/browser.h
index 6ee82f60feaf..dd96d8229902 100644
--- a/tools/perf/util/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -10,11 +10,13 @@
#define HE_COLORSET_NORMAL 52
#define HE_COLORSET_SELECTED 53
#define HE_COLORSET_CODE 54
+#define HE_COLORSET_ADDR 55
struct ui_browser {
u64 index, top_idx;
void *top, *entries;
u16 y, x, width, height;
+ int current_color;
void *priv;
const char *title;
char *helpline;
@@ -27,7 +29,7 @@ struct ui_browser {
bool use_navkeypressed;
};
-void ui_browser__set_color(struct ui_browser *self, int color);
+int ui_browser__set_color(struct ui_browser *browser, int color);
void ui_browser__set_percent_color(struct ui_browser *self,
double percent, bool current);
bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row);
@@ -35,6 +37,9 @@ void ui_browser__refresh_dimensions(struct ui_browser *self);
void ui_browser__reset_index(struct ui_browser *self);
void ui_browser__gotorc(struct ui_browser *self, int y, int x);
+void ui_browser__write_graph(struct ui_browser *browser, int graph);
+void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
+ u64 start, u64 end);
void __ui_browser__show_title(struct ui_browser *browser, const char *title);
void ui_browser__show_title(struct ui_browser *browser, const char *title);
int ui_browser__show(struct ui_browser *self, const char *title,
@@ -44,6 +49,8 @@ int ui_browser__refresh(struct ui_browser *self);
int ui_browser__run(struct ui_browser *browser, int delay_secs);
void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries);
void ui_browser__handle_resize(struct ui_browser *browser);
+void __ui_browser__vline(struct ui_browser *browser, unsigned int column,
+ u16 start, u16 end);
int ui_browser__warning(struct ui_browser *browser, int timeout,
const char *format, ...);
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
new file mode 100644
index 000000000000..6e0ef79be169
--- /dev/null
+++ b/tools/perf/ui/browsers/annotate.c
@@ -0,0 +1,867 @@
+#include "../../util/util.h"
+#include "../browser.h"
+#include "../helpline.h"
+#include "../libslang.h"
+#include "../ui.h"
+#include "../util.h"
+#include "../../util/annotate.h"
+#include "../../util/hist.h"
+#include "../../util/sort.h"
+#include "../../util/symbol.h"
+#include <pthread.h>
+#include <newt.h>
+
+struct browser_disasm_line {
+ struct rb_node rb_node;
+ double percent;
+ u32 idx;
+ int idx_asm;
+ int jump_sources;
+};
+
+struct annotate_browser {
+ struct ui_browser b;
+ struct rb_root entries;
+ struct rb_node *curr_hot;
+ struct disasm_line *selection;
+ struct disasm_line **offsets;
+ u64 start;
+ int nr_asm_entries;
+ int nr_entries;
+ int max_jump_sources;
+ int nr_jumps;
+ bool hide_src_code;
+ bool use_offset;
+ bool jump_arrows;
+ bool show_nr_jumps;
+ bool searching_backwards;
+ u8 addr_width;
+ u8 jumps_width;
+ u8 target_width;
+ u8 min_addr_width;
+ u8 max_addr_width;
+ char search_bf[128];
+};
+
+static inline struct browser_disasm_line *disasm_line__browser(struct disasm_line *dl)
+{
+ return (struct browser_disasm_line *)(dl + 1);
+}
+
+static bool disasm_line__filter(struct ui_browser *browser, void *entry)
+{
+ struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
+
+ if (ab->hide_src_code) {
+ struct disasm_line *dl = list_entry(entry, struct disasm_line, node);
+ return dl->offset == -1;
+ }
+
+ return false;
+}
+
+static int annotate_browser__jumps_percent_color(struct annotate_browser *browser,
+ int nr, bool current)
+{
+ if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed))
+ return HE_COLORSET_SELECTED;
+ if (nr == browser->max_jump_sources)
+ return HE_COLORSET_TOP;
+ if (nr > 1)
+ return HE_COLORSET_MEDIUM;
+ return HE_COLORSET_NORMAL;
+}
+
+static int annotate_browser__set_jumps_percent_color(struct annotate_browser *browser,
+ int nr, bool current)
+{
+ int color = annotate_browser__jumps_percent_color(browser, nr, current);
+ return ui_browser__set_color(&browser->b, color);
+}
+
+static void annotate_browser__write(struct ui_browser *self, void *entry, int row)
+{
+ struct annotate_browser *ab = container_of(self, struct annotate_browser, b);
+ struct disasm_line *dl = list_entry(entry, struct disasm_line, node);
+ struct browser_disasm_line *bdl = disasm_line__browser(dl);
+ bool current_entry = ui_browser__is_current_entry(self, row);
+ bool change_color = (!ab->hide_src_code &&
+ (!current_entry || (self->use_navkeypressed &&
+ !self->navkeypressed)));
+ int width = self->width, printed;
+ char bf[256];
+
+ if (dl->offset != -1 && bdl->percent != 0.0) {
+ ui_browser__set_percent_color(self, bdl->percent, current_entry);
+ slsmg_printf("%6.2f ", bdl->percent);
+ } else {
+ ui_browser__set_percent_color(self, 0, current_entry);
+ slsmg_write_nstring(" ", 7);
+ }
+
+ SLsmg_write_char(' ');
+
+ /* The scroll bar isn't being used */
+ if (!self->navkeypressed)
+ width += 1;
+
+ if (!*dl->line)
+ slsmg_write_nstring(" ", width - 7);
+ else if (dl->offset == -1) {
+ printed = scnprintf(bf, sizeof(bf), "%*s ",
+ ab->addr_width, " ");
+ slsmg_write_nstring(bf, printed);
+ slsmg_write_nstring(dl->line, width - printed - 6);
+ } else {
+ u64 addr = dl->offset;
+ int color = -1;
+
+ if (!ab->use_offset)
+ addr += ab->start;
+
+ if (!ab->use_offset) {
+ printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
+ } else {
+ if (bdl->jump_sources) {
+ if (ab->show_nr_jumps) {
+ int prev;
+ printed = scnprintf(bf, sizeof(bf), "%*d ",
+ ab->jumps_width,
+ bdl->jump_sources);
+ prev = annotate_browser__set_jumps_percent_color(ab, bdl->jump_sources,
+ current_entry);
+ slsmg_write_nstring(bf, printed);
+ ui_browser__set_color(self, prev);
+ }
+
+ printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
+ ab->target_width, addr);
+ } else {
+ printed = scnprintf(bf, sizeof(bf), "%*s ",
+ ab->addr_width, " ");
+ }
+ }
+
+ if (change_color)
+ color = ui_browser__set_color(self, HE_COLORSET_ADDR);
+ slsmg_write_nstring(bf, printed);
+ if (change_color)
+ ui_browser__set_color(self, color);
+ if (dl->ins && dl->ins->ops->scnprintf) {
+ if (ins__is_jump(dl->ins)) {
+ bool fwd = dl->ops.target.offset > (u64)dl->offset;
+
+ ui_browser__write_graph(self, fwd ? SLSMG_DARROW_CHAR :
+ SLSMG_UARROW_CHAR);
+ SLsmg_write_char(' ');
+ } else if (ins__is_call(dl->ins)) {
+ ui_browser__write_graph(self, SLSMG_RARROW_CHAR);
+ SLsmg_write_char(' ');
+ } else {
+ slsmg_write_nstring(" ", 2);
+ }
+ } else {
+ if (strcmp(dl->name, "retq")) {
+ slsmg_write_nstring(" ", 2);
+ } else {
+ ui_browser__write_graph(self, SLSMG_LARROW_CHAR);
+ SLsmg_write_char(' ');
+ }
+ }
+
+ disasm_line__scnprintf(dl, bf, sizeof(bf), !ab->use_offset);
+ slsmg_write_nstring(bf, width - 10 - printed);
+ }
+
+ if (current_entry)
+ ab->selection = dl;
+}
+
+static void annotate_browser__draw_current_jump(struct ui_browser *browser)
+{
+ struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
+ struct disasm_line *cursor = ab->selection, *target;
+ struct browser_disasm_line *btarget, *bcursor;
+ unsigned int from, to;
+
+ if (!cursor->ins || !ins__is_jump(cursor->ins) ||
+ !disasm_line__has_offset(cursor))
+ return;
+
+ target = ab->offsets[cursor->ops.target.offset];
+ if (!target)
+ return;
+
+ bcursor = disasm_line__browser(cursor);
+ btarget = disasm_line__browser(target);
+
+ if (ab->hide_src_code) {
+ from = bcursor->idx_asm;
+ to = btarget->idx_asm;
+ } else {
+ from = (u64)bcursor->idx;
+ to = (u64)btarget->idx;
+ }
+
+ ui_browser__set_color(browser, HE_COLORSET_CODE);
+ __ui_browser__line_arrow(browser, 9 + ab->addr_width, from, to);
+}
+
+static unsigned int annotate_browser__refresh(struct ui_browser *browser)
+{
+ struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
+ int ret = ui_browser__list_head_refresh(browser);
+
+ if (ab->jump_arrows)
+ annotate_browser__draw_current_jump(browser);
+
+ ui_browser__set_color(browser, HE_COLORSET_NORMAL);
+ __ui_browser__vline(browser, 7, 0, browser->height - 1);
+ return ret;
+}
+
+static double disasm_line__calc_percent(struct disasm_line *dl, struct symbol *sym, int evidx)
+{
+ double percent = 0.0;
+
+ if (dl->offset != -1) {
+ int len = sym->end - sym->start;
+ unsigned int hits = 0;
+ struct annotation *notes = symbol__annotation(sym);
+ struct source_line *src_line = notes->src->lines;
+ struct sym_hist *h = annotation__histogram(notes, evidx);
+ s64 offset = dl->offset;
+ struct disasm_line *next;
+
+ next = disasm__get_next_ip_line(&notes->src->source, dl);
+ while (offset < (s64)len &&
+ (next == NULL || offset < next->offset)) {
+ if (src_line) {
+ percent += src_line[offset].percent;
+ } else
+ hits += h->addr[offset];
+
+ ++offset;
+ }
+ /*
+ * If the percentage wasn't already calculated in
+ * symbol__get_source_line, do it now:
+ */
+ if (src_line == NULL && h->sum)
+ percent = 100.0 * hits / h->sum;
+ }
+
+ return percent;
+}
+
+static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl)
+{
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ struct browser_disasm_line *l;
+
+ while (*p != NULL) {
+ parent = *p;
+ l = rb_entry(parent, struct browser_disasm_line, rb_node);
+ if (bdl->percent < l->percent)
+ p = &(*p)->rb_left;
+ else
+ p = &(*p)->rb_right;
+ }
+ rb_link_node(&bdl->rb_node, parent, p);
+ rb_insert_color(&bdl->rb_node, root);
+}
+
+static void annotate_browser__set_top(struct annotate_browser *self,
+ struct disasm_line *pos, u32 idx)
+{
+ unsigned back;
+
+ ui_browser__refresh_dimensions(&self->b);
+ back = self->b.height / 2;
+ self->b.top_idx = self->b.index = idx;
+
+ while (self->b.top_idx != 0 && back != 0) {
+ pos = list_entry(pos->node.prev, struct disasm_line, node);
+
+ if (disasm_line__filter(&self->b, &pos->node))
+ continue;
+
+ --self->b.top_idx;
+ --back;
+ }
+
+ self->b.top = pos;
+ self->b.navkeypressed = true;
+}
+
+static void annotate_browser__set_rb_top(struct annotate_browser *browser,
+ struct rb_node *nd)
+{
+ struct browser_disasm_line *bpos;
+ struct disasm_line *pos;
+
+ bpos = rb_entry(nd, struct browser_disasm_line, rb_node);
+ pos = ((struct disasm_line *)bpos) - 1;
+ annotate_browser__set_top(browser, pos, bpos->idx);
+ browser->curr_hot = nd;
+}
+
+static void annotate_browser__calc_percent(struct annotate_browser *browser,
+ int evidx)
+{
+ struct map_symbol *ms = browser->b.priv;
+ struct symbol *sym = ms->sym;
+ struct annotation *notes = symbol__annotation(sym);
+ struct disasm_line *pos;
+
+ browser->entries = RB_ROOT;
+
+ pthread_mutex_lock(&notes->lock);
+
+ list_for_each_entry(pos, &notes->src->source, node) {
+ struct browser_disasm_line *bpos = disasm_line__browser(pos);
+ bpos->percent = disasm_line__calc_percent(pos, sym, evidx);
+ if (bpos->percent < 0.01) {
+ RB_CLEAR_NODE(&bpos->rb_node);
+ continue;
+ }
+ disasm_rb_tree__insert(&browser->entries, bpos);
+ }
+ pthread_mutex_unlock(&notes->lock);
+
+ browser->curr_hot = rb_last(&browser->entries);
+}
+
+static bool annotate_browser__toggle_source(struct annotate_browser *browser)
+{
+ struct disasm_line *dl;
+ struct browser_disasm_line *bdl;
+ off_t offset = browser->b.index - browser->b.top_idx;
+
+ browser->b.seek(&browser->b, offset, SEEK_CUR);
+ dl = list_entry(browser->b.top, struct disasm_line, node);
+ bdl = disasm_line__browser(dl);
+
+ if (browser->hide_src_code) {
+ if (bdl->idx_asm < offset)
+ offset = bdl->idx;
+
+ browser->b.nr_entries = browser->nr_entries;
+ browser->hide_src_code = false;
+ browser->b.seek(&browser->b, -offset, SEEK_CUR);
+ browser->b.top_idx = bdl->idx - offset;
+ browser->b.index = bdl->idx;
+ } else {
+ if (bdl->idx_asm < 0) {
+ ui_helpline__puts("Only available for assembly lines.");
+ browser->b.seek(&browser->b, -offset, SEEK_CUR);
+ return false;
+ }
+
+ if (bdl->idx_asm < offset)
+ offset = bdl->idx_asm;
+
+ browser->b.nr_entries = browser->nr_asm_entries;
+ browser->hide_src_code = true;
+ browser->b.seek(&browser->b, -offset, SEEK_CUR);
+ browser->b.top_idx = bdl->idx_asm - offset;
+ browser->b.index = bdl->idx_asm;
+ }
+
+ return true;
+}
+
+static bool annotate_browser__callq(struct annotate_browser *browser,
+ int evidx, void (*timer)(void *arg),
+ void *arg, int delay_secs)
+{
+ struct map_symbol *ms = browser->b.priv;
+ struct disasm_line *dl = browser->selection;
+ struct symbol *sym = ms->sym;
+ struct annotation *notes;
+ struct symbol *target;
+ u64 ip;
+
+ if (!ins__is_call(dl->ins))
+ return false;
+
+ ip = ms->map->map_ip(ms->map, dl->ops.target.addr);
+ target = map__find_symbol(ms->map, ip, NULL);
+ if (target == NULL) {
+ ui_helpline__puts("The called function was not found.");
+ return true;
+ }
+
+ notes = symbol__annotation(target);
+ pthread_mutex_lock(&notes->lock);
+
+ if (notes->src == NULL && symbol__alloc_hist(target) < 0) {
+ pthread_mutex_unlock(&notes->lock);
+ ui__warning("Not enough memory for annotating '%s' symbol!\n",
+ target->name);
+ return true;
+ }
+
+ pthread_mutex_unlock(&notes->lock);
+ symbol__tui_annotate(target, ms->map, evidx, timer, arg, delay_secs);
+ ui_browser__show_title(&browser->b, sym->name);
+ return true;
+}
+
+static
+struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser,
+ s64 offset, s64 *idx)
+{
+ struct map_symbol *ms = browser->b.priv;
+ struct symbol *sym = ms->sym;
+ struct annotation *notes = symbol__annotation(sym);
+ struct disasm_line *pos;
+
+ *idx = 0;
+ list_for_each_entry(pos, &notes->src->source, node) {
+ if (pos->offset == offset)
+ return pos;
+ if (!disasm_line__filter(&browser->b, &pos->node))
+ ++*idx;
+ }
+
+ return NULL;
+}
+
+static bool annotate_browser__jump(struct annotate_browser *browser)
+{
+ struct disasm_line *dl = browser->selection;
+ s64 idx;
+
+ if (!ins__is_jump(dl->ins))
+ return false;
+
+ dl = annotate_browser__find_offset(browser, dl->ops.target.offset, &idx);
+ if (dl == NULL) {
+ ui_helpline__puts("Invallid jump offset");
+ return true;
+ }
+
+ annotate_browser__set_top(browser, dl, idx);
+
+ return true;
+}
+
+static
+struct disasm_line *annotate_browser__find_string(struct annotate_browser *browser,
+ char *s, s64 *idx)
+{
+ struct map_symbol *ms = browser->b.priv;
+ struct symbol *sym = ms->sym;
+ struct annotation *notes = symbol__annotation(sym);
+ struct disasm_line *pos = browser->selection;
+
+ *idx = browser->b.index;
+ list_for_each_entry_continue(pos, &notes->src->source, node) {
+ if (disasm_line__filter(&browser->b, &pos->node))
+ continue;
+
+ ++*idx;
+
+ if (pos->line && strstr(pos->line, s) != NULL)
+ return pos;
+ }
+
+ return NULL;
+}
+
+static bool __annotate_browser__search(struct annotate_browser *browser)
+{
+ struct disasm_line *dl;
+ s64 idx;
+
+ dl = annotate_browser__find_string(browser, browser->search_bf, &idx);
+ if (dl == NULL) {
+ ui_helpline__puts("String not found!");
+ return false;
+ }
+
+ annotate_browser__set_top(browser, dl, idx);
+ browser->searching_backwards = false;
+ return true;
+}
+
+static
+struct disasm_line *annotate_browser__find_string_reverse(struct annotate_browser *browser,
+ char *s, s64 *idx)
+{
+ struct map_symbol *ms = browser->b.priv;
+ struct symbol *sym = ms->sym;
+ struct annotation *notes = symbol__annotation(sym);
+ struct disasm_line *pos = browser->selection;
+
+ *idx = browser->b.index;
+ list_for_each_entry_continue_reverse(pos, &notes->src->source, node) {
+ if (disasm_line__filter(&browser->b, &pos->node))
+ continue;
+
+ --*idx;
+
+ if (pos->line && strstr(pos->line, s) != NULL)
+ return pos;
+ }
+
+ return NULL;
+}
+
+static bool __annotate_browser__search_reverse(struct annotate_browser *browser)
+{
+ struct disasm_line *dl;
+ s64 idx;
+
+ dl = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx);
+ if (dl == NULL) {
+ ui_helpline__puts("String not found!");
+ return false;
+ }
+
+ annotate_browser__set_top(browser, dl, idx);
+ browser->searching_backwards = true;
+ return true;
+}
+
+static bool annotate_browser__search_window(struct annotate_browser *browser,
+ int delay_secs)
+{
+ if (ui_browser__input_window("Search", "String: ", browser->search_bf,
+ "ENTER: OK, ESC: Cancel",
+ delay_secs * 2) != K_ENTER ||
+ !*browser->search_bf)
+ return false;
+
+ return true;
+}
+
+static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs)
+{
+ if (annotate_browser__search_window(browser, delay_secs))
+ return __annotate_browser__search(browser);
+
+ return false;
+}
+
+static bool annotate_browser__continue_search(struct annotate_browser *browser,
+ int delay_secs)
+{
+ if (!*browser->search_bf)
+ return annotate_browser__search(browser, delay_secs);
+
+ return __annotate_browser__search(browser);
+}
+
+static bool annotate_browser__search_reverse(struct annotate_browser *browser,
+ int delay_secs)
+{
+ if (annotate_browser__search_window(browser, delay_secs))
+ return __annotate_browser__search_reverse(browser);
+
+ return false;
+}
+
+static
+bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
+ int delay_secs)
+{
+ if (!*browser->search_bf)
+ return annotate_browser__search_reverse(browser, delay_secs);
+
+ return __annotate_browser__search_reverse(browser);
+}
+
+static int annotate_browser__run(struct annotate_browser *self, int evidx,
+ void(*timer)(void *arg),
+ void *arg, int delay_secs)
+{
+ struct rb_node *nd = NULL;
+ struct map_symbol *ms = self->b.priv;
+ struct symbol *sym = ms->sym;
+ const char *help = "Press 'h' for help on key bindings";
+ int key;
+
+ if (ui_browser__show(&self->b, sym->name, help) < 0)
+ return -1;
+
+ annotate_browser__calc_percent(self, evidx);
+
+ if (self->curr_hot) {
+ annotate_browser__set_rb_top(self, self->curr_hot);
+ self->b.navkeypressed = false;
+ }
+
+ nd = self->curr_hot;
+
+ while (1) {
+ key = ui_browser__run(&self->b, delay_secs);
+
+ if (delay_secs != 0) {
+ annotate_browser__calc_percent(self, evidx);
+ /*
+ * Current line focus got out of the list of most active
+ * lines, NULL it so that if TAB|UNTAB is pressed, we
+ * move to curr_hot (current hottest line).
+ */
+ if (nd != NULL && RB_EMPTY_NODE(nd))
+ nd = NULL;
+ }
+
+ switch (key) {
+ case K_TIMER:
+ if (timer != NULL)
+ timer(arg);
+
+ if (delay_secs != 0)
+ symbol__annotate_decay_histogram(sym, evidx);
+ continue;
+ case K_TAB:
+ if (nd != NULL) {
+ nd = rb_prev(nd);
+ if (nd == NULL)
+ nd = rb_last(&self->entries);
+ } else
+ nd = self->curr_hot;
+ break;
+ case K_UNTAB:
+ if (nd != NULL)
+ nd = rb_next(nd);
+ if (nd == NULL)
+ nd = rb_first(&self->entries);
+ else
+ nd = self->curr_hot;
+ break;
+ case K_F1:
+ case 'h':
+ ui_browser__help_window(&self->b,
+ "UP/DOWN/PGUP\n"
+ "PGDN/SPACE Navigate\n"
+ "q/ESC/CTRL+C Exit\n\n"
+ "-> Go to target\n"
+ "<- Exit\n"
+ "h Cycle thru hottest instructions\n"
+ "j Toggle showing jump to target arrows\n"
+ "J Toggle showing number of jump sources on targets\n"
+ "n Search next string\n"
+ "o Toggle disassembler output/simplified view\n"
+ "s Toggle source code view\n"
+ "/ Search string\n"
+ "? Search previous string\n");
+ continue;
+ case 'H':
+ nd = self->curr_hot;
+ break;
+ case 's':
+ if (annotate_browser__toggle_source(self))
+ ui_helpline__puts(help);
+ continue;
+ case 'o':
+ self->use_offset = !self->use_offset;
+ if (self->use_offset)
+ self->target_width = self->min_addr_width;
+ else
+ self->target_width = self->max_addr_width;
+update_addr_width:
+ self->addr_width = self->target_width;
+ if (self->show_nr_jumps)
+ self->addr_width += self->jumps_width + 1;
+ continue;
+ case 'j':
+ self->jump_arrows = !self->jump_arrows;
+ continue;
+ case 'J':
+ self->show_nr_jumps = !self->show_nr_jumps;
+ goto update_addr_width;
+ case '/':
+ if (annotate_browser__search(self, delay_secs)) {
+show_help:
+ ui_helpline__puts(help);
+ }
+ continue;
+ case 'n':
+ if (self->searching_backwards ?
+ annotate_browser__continue_search_reverse(self, delay_secs) :
+ annotate_browser__continue_search(self, delay_secs))
+ goto show_help;
+ continue;
+ case '?':
+ if (annotate_browser__search_reverse(self, delay_secs))
+ goto show_help;
+ continue;
+ case K_ENTER:
+ case K_RIGHT:
+ if (self->selection == NULL)
+ ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
+ else if (self->selection->offset == -1)
+ ui_helpline__puts("Actions are only available for assembly lines.");
+ else if (!self->selection->ins) {
+ if (strcmp(self->selection->name, "retq"))
+ goto show_sup_ins;
+ goto out;
+ } else if (!(annotate_browser__jump(self) ||
+ annotate_browser__callq(self, evidx, timer, arg, delay_secs))) {
+show_sup_ins:
+ ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions.");
+ }
+ continue;
+ case K_LEFT:
+ case K_ESC:
+ case 'q':
+ case CTRL('c'):
+ goto out;
+ default:
+ continue;
+ }
+
+ if (nd != NULL)
+ annotate_browser__set_rb_top(self, nd);
+ }
+out:
+ ui_browser__hide(&self->b);
+ return key;
+}
+
+int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
+ void(*timer)(void *arg), void *arg, int delay_secs)
+{
+ return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx,
+ timer, arg, delay_secs);
+}
+
+static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
+ size_t size)
+{
+ u64 offset;
+
+ for (offset = 0; offset < size; ++offset) {
+ struct disasm_line *dl = browser->offsets[offset], *dlt;
+ struct browser_disasm_line *bdlt;
+
+ if (!dl || !dl->ins || !ins__is_jump(dl->ins) ||
+ !disasm_line__has_offset(dl))
+ continue;
+
+ if (dl->ops.target.offset >= size) {
+ ui__error("jump to after symbol!\n"
+ "size: %zx, jump target: %" PRIx64,
+ size, dl->ops.target.offset);
+ continue;
+ }
+
+ dlt = browser->offsets[dl->ops.target.offset];
+ /*
+ * FIXME: Oops, no jump target? Buggy disassembler? Or do we
+ * have to adjust to the previous offset?
+ */
+ if (dlt == NULL)
+ continue;
+
+ bdlt = disasm_line__browser(dlt);
+ if (++bdlt->jump_sources > browser->max_jump_sources)
+ browser->max_jump_sources = bdlt->jump_sources;
+
+ ++browser->nr_jumps;
+ }
+
+}
+
+static inline int width_jumps(int n)
+{
+ if (n >= 100)
+ return 5;
+ if (n / 10)
+ return 2;
+ return 1;
+}
+
+int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
+ void(*timer)(void *arg), void *arg,
+ int delay_secs)
+{
+ struct disasm_line *pos, *n;
+ struct annotation *notes;
+ const size_t size = symbol__size(sym);
+ struct map_symbol ms = {
+ .map = map,
+ .sym = sym,
+ };
+ struct annotate_browser browser = {
+ .b = {
+ .refresh = annotate_browser__refresh,
+ .seek = ui_browser__list_head_seek,
+ .write = annotate_browser__write,
+ .filter = disasm_line__filter,
+ .priv = &ms,
+ .use_navkeypressed = true,
+ },
+ .use_offset = true,
+ .jump_arrows = true,
+ };
+ int ret = -1;
+
+ if (sym == NULL)
+ return -1;
+
+ if (map->dso->annotate_warned)
+ return -1;
+
+ browser.offsets = zalloc(size * sizeof(struct disasm_line *));
+ if (browser.offsets == NULL) {
+ ui__error("Not enough memory!");
+ return -1;
+ }
+
+ if (symbol__annotate(sym, map, sizeof(struct browser_disasm_line)) < 0) {
+ ui__error("%s", ui_helpline__last_msg);
+ goto out_free_offsets;
+ }
+
+ ui_helpline__push("Press <- or ESC to exit");
+
+ notes = symbol__annotation(sym);
+ browser.start = map__rip_2objdump(map, sym->start);
+
+ list_for_each_entry(pos, &notes->src->source, node) {
+ struct browser_disasm_line *bpos;
+ size_t line_len = strlen(pos->line);
+
+ if (browser.b.width < line_len)
+ browser.b.width = line_len;
+ bpos = disasm_line__browser(pos);
+ bpos->idx = browser.nr_entries++;
+ if (pos->offset != -1) {
+ bpos->idx_asm = browser.nr_asm_entries++;
+ /*
+ * FIXME: short term bandaid to cope with assembly
+ * routines that comes with labels in the same column
+ * as the address in objdump, sigh.
+ *
+ * E.g. copy_user_generic_unrolled
+ */
+ if (pos->offset < (s64)size)
+ browser.offsets[pos->offset] = pos;
+ } else
+ bpos->idx_asm = -1;
+ }
+
+ annotate_browser__mark_jump_targets(&browser, size);
+
+ browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size);
+ browser.max_addr_width = hex_width(sym->end);
+ browser.jumps_width = width_jumps(browser.max_jump_sources);
+ browser.b.nr_entries = browser.nr_entries;
+ browser.b.entries = &notes->src->source,
+ browser.b.width += 18; /* Percentage */
+ ret = annotate_browser__run(&browser, evidx, timer, arg, delay_secs);
+ list_for_each_entry_safe(pos, n, &notes->src->source, node) {
+ list_del(&pos->node);
+ disasm_line__free(pos);
+ }
+
+out_free_offsets:
+ free(browser.offsets);
+ return ret;
+}
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 2f83e5dc9967..a372a4b02635 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -5,12 +5,12 @@
#include <newt.h>
#include <linux/rbtree.h>
-#include "../../evsel.h"
-#include "../../evlist.h"
-#include "../../hist.h"
-#include "../../pstack.h"
-#include "../../sort.h"
-#include "../../util.h"
+#include "../../util/evsel.h"
+#include "../../util/evlist.h"
+#include "../../util/hist.h"
+#include "../../util/pstack.h"
+#include "../../util/sort.h"
+#include "../../util/util.h"
#include "../browser.h"
#include "../helpline.h"
@@ -840,10 +840,14 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size,
int printed;
const struct dso *dso = self->dso_filter;
const struct thread *thread = self->thread_filter;
- unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE];
+ unsigned long nr_samples = self->stats.nr_events[PERF_RECORD_SAMPLE];
+ u64 nr_events = self->stats.total_period;
+
+ nr_samples = convert_unit(nr_samples, &unit);
+ printed = scnprintf(bf, size,
+ "Samples: %lu%c of event '%s', Event count (approx.): %lu",
+ nr_samples, unit, ev_name, nr_events);
- nr_events = convert_unit(nr_events, &unit);
- printed = scnprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name);
if (self->uid_filter_str)
printed += snprintf(bf + printed, size - printed,
@@ -937,7 +941,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
goto zoom_dso;
case 't':
goto zoom_thread;
- case 's':
+ case '/':
if (ui_browser__input_window("Symbol to show",
"Please enter the name of symbol you want to see",
buf, "ENTER: OK, ESC: Cancel",
@@ -965,7 +969,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
"E Expand all callchains\n"
"d Zoom into current DSO\n"
"t Zoom into current Thread\n"
- "s Filter symbol by name");
+ "/ Filter symbol by name");
continue;
case K_ENTER:
case K_RIGHT:
diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/ui/browsers/map.c
index eca6575abfd0..98851d55a53e 100644
--- a/tools/perf/util/ui/browsers/map.c
+++ b/tools/perf/ui/browsers/map.c
@@ -5,9 +5,9 @@
#include <sys/ttydefaults.h>
#include <string.h>
#include <linux/bitops.h>
-#include "../../util.h"
-#include "../../debug.h"
-#include "../../symbol.h"
+#include "../../util/util.h"
+#include "../../util/debug.h"
+#include "../../util/symbol.h"
#include "../browser.h"
#include "../helpline.h"
#include "map.h"
diff --git a/tools/perf/util/ui/browsers/map.h b/tools/perf/ui/browsers/map.h
index df8581a43e17..df8581a43e17 100644
--- a/tools/perf/util/ui/browsers/map.h
+++ b/tools/perf/ui/browsers/map.h
diff --git a/tools/perf/util/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index 258352a2356c..0656c381a89c 100644
--- a/tools/perf/util/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -9,24 +9,13 @@
#define MAX_COLUMNS 32
-void perf_gtk_setup_browser(int argc, const char *argv[],
- bool fallback_to_pager __used)
-{
- gtk_init(&argc, (char ***)&argv);
-}
-
-void perf_gtk_exit_browser(bool wait_for_ok __used)
-{
- gtk_main_quit();
-}
-
-static void perf_gtk_signal(int sig)
+static void perf_gtk__signal(int sig)
{
psignal(sig, "perf");
gtk_main_quit();
}
-static void perf_gtk_resize_window(GtkWidget *window)
+static void perf_gtk__resize_window(GtkWidget *window)
{
GdkRectangle rect;
GdkScreen *screen;
@@ -46,7 +35,7 @@ static void perf_gtk_resize_window(GtkWidget *window)
gtk_window_resize(GTK_WINDOW(window), width, height);
}
-static void perf_gtk_show_hists(GtkWidget *window, struct hists *hists)
+static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
{
GType col_types[MAX_COLUMNS];
GtkCellRenderer *renderer;
@@ -142,11 +131,11 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
GtkWidget *notebook;
GtkWidget *window;
- signal(SIGSEGV, perf_gtk_signal);
- signal(SIGFPE, perf_gtk_signal);
- signal(SIGINT, perf_gtk_signal);
- signal(SIGQUIT, perf_gtk_signal);
- signal(SIGTERM, perf_gtk_signal);
+ signal(SIGSEGV, perf_gtk__signal);
+ signal(SIGFPE, perf_gtk__signal);
+ signal(SIGINT, perf_gtk__signal);
+ signal(SIGQUIT, perf_gtk__signal);
+ signal(SIGTERM, perf_gtk__signal);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
@@ -168,7 +157,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
- perf_gtk_show_hists(scrolled_window, hists);
+ perf_gtk__show_hists(scrolled_window, hists);
tab_label = gtk_label_new(evname);
@@ -179,7 +168,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
gtk_widget_show_all(window);
- perf_gtk_resize_window(window);
+ perf_gtk__resize_window(window);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
diff --git a/tools/perf/util/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h
index 75177ee04032..75177ee04032 100644
--- a/tools/perf/util/gtk/gtk.h
+++ b/tools/perf/ui/gtk/gtk.h
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c
new file mode 100644
index 000000000000..829529957766
--- /dev/null
+++ b/tools/perf/ui/gtk/setup.c
@@ -0,0 +1,12 @@
+#include "gtk.h"
+#include "../../util/cache.h"
+
+int perf_gtk__init(void)
+{
+ return gtk_init_check(NULL, NULL) ? 0 : -1;
+}
+
+void perf_gtk__exit(bool wait_for_ok __used)
+{
+ gtk_main_quit();
+}
diff --git a/tools/perf/util/ui/helpline.c b/tools/perf/ui/helpline.c
index 2f950c2641c8..2f950c2641c8 100644
--- a/tools/perf/util/ui/helpline.c
+++ b/tools/perf/ui/helpline.c
diff --git a/tools/perf/util/ui/helpline.h b/tools/perf/ui/helpline.h
index 7bab6b34e35e..7bab6b34e35e 100644
--- a/tools/perf/util/ui/helpline.h
+++ b/tools/perf/ui/helpline.h
diff --git a/tools/perf/util/ui/keysyms.h b/tools/perf/ui/keysyms.h
index 809eca5707fa..809eca5707fa 100644
--- a/tools/perf/util/ui/keysyms.h
+++ b/tools/perf/ui/keysyms.h
diff --git a/tools/perf/util/ui/libslang.h b/tools/perf/ui/libslang.h
index 4d54b6450f5b..4d54b6450f5b 100644
--- a/tools/perf/util/ui/libslang.h
+++ b/tools/perf/ui/libslang.h
diff --git a/tools/perf/util/ui/progress.c b/tools/perf/ui/progress.c
index 13aa64e50e11..13aa64e50e11 100644
--- a/tools/perf/util/ui/progress.c
+++ b/tools/perf/ui/progress.c
diff --git a/tools/perf/util/ui/progress.h b/tools/perf/ui/progress.h
index d9c205b59aa1..d9c205b59aa1 100644
--- a/tools/perf/util/ui/progress.h
+++ b/tools/perf/ui/progress.h
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
new file mode 100644
index 000000000000..9f5f888f73e3
--- /dev/null
+++ b/tools/perf/ui/setup.c
@@ -0,0 +1,45 @@
+#include "../cache.h"
+#include "../debug.h"
+
+
+void setup_browser(bool fallback_to_pager)
+{
+ if (!isatty(1) || dump_trace)
+ use_browser = 0;
+
+ /* default to TUI */
+ if (use_browser < 0)
+ use_browser = 1;
+
+ switch (use_browser) {
+ case 2:
+ if (perf_gtk__init() == 0)
+ break;
+ /* fall through */
+ case 1:
+ use_browser = 1;
+ if (ui__init() == 0)
+ break;
+ /* fall through */
+ default:
+ if (fallback_to_pager)
+ setup_pager();
+ break;
+ }
+}
+
+void exit_browser(bool wait_for_ok)
+{
+ switch (use_browser) {
+ case 2:
+ perf_gtk__exit(wait_for_ok);
+ break;
+
+ case 1:
+ ui__exit(wait_for_ok);
+ break;
+
+ default:
+ break;
+ }
+}
diff --git a/tools/perf/util/ui/setup.c b/tools/perf/ui/tui/setup.c
index 85a69faa09aa..d33e943ac434 100644
--- a/tools/perf/util/ui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -2,14 +2,14 @@
#include <signal.h>
#include <stdbool.h>
-#include "../cache.h"
-#include "../debug.h"
-#include "browser.h"
-#include "helpline.h"
-#include "ui.h"
-#include "util.h"
-#include "libslang.h"
-#include "keysyms.h"
+#include "../../util/cache.h"
+#include "../../util/debug.h"
+#include "../browser.h"
+#include "../helpline.h"
+#include "../ui.h"
+#include "../util.h"
+#include "../libslang.h"
+#include "../keysyms.h"
pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
@@ -93,45 +93,26 @@ static void newt_suspend(void *d __used)
newtResume();
}
-static int ui__init(void)
-{
- int err = SLkp_init();
-
- if (err < 0)
- goto out;
-
- SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB);
-out:
- return err;
-}
-
-static void ui__exit(void)
-{
- SLtt_set_cursor_visibility(1);
- SLsmg_refresh();
- SLsmg_reset_smg();
- SLang_reset_tty();
-}
-
static void ui__signal(int sig)
{
- ui__exit();
+ ui__exit(false);
psignal(sig, "perf");
exit(0);
}
-void setup_browser(bool fallback_to_pager)
+int ui__init(void)
{
- if (!isatty(1) || !use_browser || dump_trace) {
- use_browser = 0;
- if (fallback_to_pager)
- setup_pager();
- return;
- }
+ int err;
- use_browser = 1;
newtInit();
- ui__init();
+ err = SLkp_init();
+ if (err < 0) {
+ pr_err("TUI initialization failed.\n");
+ goto out;
+ }
+
+ SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB);
+
newtSetSuspendCallback(newt_suspend, NULL);
ui_helpline__init();
ui_browser__init();
@@ -141,15 +122,19 @@ void setup_browser(bool fallback_to_pager)
signal(SIGINT, ui__signal);
signal(SIGQUIT, ui__signal);
signal(SIGTERM, ui__signal);
+out:
+ return err;
}
-void exit_browser(bool wait_for_ok)
+void ui__exit(bool wait_for_ok)
{
- if (use_browser > 0) {
- if (wait_for_ok)
- ui__question_window("Fatal Error",
- ui_helpline__last_msg,
- "Press any key...", 0);
- ui__exit();
- }
+ if (wait_for_ok)
+ ui__question_window("Fatal Error",
+ ui_helpline__last_msg,
+ "Press any key...", 0);
+
+ SLtt_set_cursor_visibility(1);
+ SLsmg_refresh();
+ SLsmg_reset_smg();
+ SLang_reset_tty();
}
diff --git a/tools/perf/util/ui/ui.h b/tools/perf/ui/ui.h
index 7b67045479f6..7b67045479f6 100644
--- a/tools/perf/util/ui/ui.h
+++ b/tools/perf/ui/ui.h
diff --git a/tools/perf/util/ui/util.c b/tools/perf/ui/util.c
index ad4374a16bb0..ad4374a16bb0 100644
--- a/tools/perf/util/ui/util.c
+++ b/tools/perf/ui/util.c
diff --git a/tools/perf/util/ui/util.h b/tools/perf/ui/util.h
index 2d1738bd71c8..2d1738bd71c8 100644
--- a/tools/perf/util/ui/util.h
+++ b/tools/perf/ui/util.h
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 08c6d138a655..8069dfb5ba77 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -18,6 +18,403 @@
const char *disassembler_style;
+static struct ins *ins__find(const char *name);
+static int disasm_line__parse(char *line, char **namep, char **rawp);
+
+static void ins__delete(struct ins_operands *ops)
+{
+ free(ops->source.raw);
+ free(ops->source.name);
+ free(ops->target.raw);
+ free(ops->target.name);
+}
+
+static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops)
+{
+ return scnprintf(bf, size, "%-6.6s %s", ins->name, ops->raw);
+}
+
+int ins__scnprintf(struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops)
+{
+ if (ins->ops->scnprintf)
+ return ins->ops->scnprintf(ins, bf, size, ops);
+
+ return ins__raw_scnprintf(ins, bf, size, ops);
+}
+
+static int call__parse(struct ins_operands *ops)
+{
+ char *endptr, *tok, *name;
+
+ ops->target.addr = strtoull(ops->raw, &endptr, 16);
+
+ name = strchr(endptr, '<');
+ if (name == NULL)
+ goto indirect_call;
+
+ name++;
+
+ tok = strchr(name, '>');
+ if (tok == NULL)
+ return -1;
+
+ *tok = '\0';
+ ops->target.name = strdup(name);
+ *tok = '>';
+
+ return ops->target.name == NULL ? -1 : 0;
+
+indirect_call:
+ tok = strchr(endptr, '(');
+ if (tok != NULL) {
+ ops->target.addr = 0;
+ return 0;
+ }
+
+ tok = strchr(endptr, '*');
+ if (tok == NULL)
+ return -1;
+
+ ops->target.addr = strtoull(tok + 1, NULL, 16);
+ return 0;
+}
+
+static int call__scnprintf(struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops)
+{
+ if (ops->target.name)
+ return scnprintf(bf, size, "%-6.6s %s", ins->name, ops->target.name);
+
+ if (ops->target.addr == 0)
+ return ins__raw_scnprintf(ins, bf, size, ops);
+
+ return scnprintf(bf, size, "%-6.6s *%" PRIx64, ins->name, ops->target.addr);
+}
+
+static struct ins_ops call_ops = {
+ .parse = call__parse,
+ .scnprintf = call__scnprintf,
+};
+
+bool ins__is_call(const struct ins *ins)
+{
+ return ins->ops == &call_ops;
+}
+
+static int jump__parse(struct ins_operands *ops)
+{
+ const char *s = strchr(ops->raw, '+');
+
+ ops->target.addr = strtoll(ops->raw, NULL, 16);
+
+ if (s++ != NULL)
+ ops->target.offset = strtoll(s, NULL, 16);
+ else
+ ops->target.offset = UINT64_MAX;
+
+ return 0;
+}
+
+static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops)
+{
+ return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset);
+}
+
+static struct ins_ops jump_ops = {
+ .parse = jump__parse,
+ .scnprintf = jump__scnprintf,
+};
+
+bool ins__is_jump(const struct ins *ins)
+{
+ return ins->ops == &jump_ops;
+}
+
+static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
+{
+ char *endptr, *name, *t;
+
+ if (strstr(raw, "(%rip)") == NULL)
+ return 0;
+
+ *addrp = strtoull(comment, &endptr, 16);
+ name = strchr(endptr, '<');
+ if (name == NULL)
+ return -1;
+
+ name++;
+
+ t = strchr(name, '>');
+ if (t == NULL)
+ return 0;
+
+ *t = '\0';
+ *namep = strdup(name);
+ *t = '>';
+
+ return 0;
+}
+
+static int lock__parse(struct ins_operands *ops)
+{
+ char *name;
+
+ ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
+ if (ops->locked.ops == NULL)
+ return 0;
+
+ if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0)
+ goto out_free_ops;
+
+ ops->locked.ins = ins__find(name);
+ if (ops->locked.ins == NULL)
+ goto out_free_ops;
+
+ if (!ops->locked.ins->ops)
+ return 0;
+
+ if (ops->locked.ins->ops->parse)
+ ops->locked.ins->ops->parse(ops->locked.ops);
+
+ return 0;
+
+out_free_ops:
+ free(ops->locked.ops);
+ ops->locked.ops = NULL;
+ return 0;
+}
+
+static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops)
+{
+ int printed;
+
+ if (ops->locked.ins == NULL)
+ return ins__raw_scnprintf(ins, bf, size, ops);
+
+ printed = scnprintf(bf, size, "%-6.6s ", ins->name);
+ return printed + ins__scnprintf(ops->locked.ins, bf + printed,
+ size - printed, ops->locked.ops);
+}
+
+static void lock__delete(struct ins_operands *ops)
+{
+ free(ops->locked.ops);
+ free(ops->target.raw);
+ free(ops->target.name);
+}
+
+static struct ins_ops lock_ops = {
+ .free = lock__delete,
+ .parse = lock__parse,
+ .scnprintf = lock__scnprintf,
+};
+
+static int mov__parse(struct ins_operands *ops)
+{
+ char *s = strchr(ops->raw, ','), *target, *comment, prev;
+
+ if (s == NULL)
+ return -1;
+
+ *s = '\0';
+ ops->source.raw = strdup(ops->raw);
+ *s = ',';
+
+ if (ops->source.raw == NULL)
+ return -1;
+
+ target = ++s;
+
+ while (s[0] != '\0' && !isspace(s[0]))
+ ++s;
+ prev = *s;
+ *s = '\0';
+
+ ops->target.raw = strdup(target);
+ *s = prev;
+
+ if (ops->target.raw == NULL)
+ goto out_free_source;
+
+ comment = strchr(s, '#');
+ if (comment == NULL)
+ return 0;
+
+ while (comment[0] != '\0' && isspace(comment[0]))
+ ++comment;
+
+ comment__symbol(ops->source.raw, comment, &ops->source.addr, &ops->source.name);
+ comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name);
+
+ return 0;
+
+out_free_source:
+ free(ops->source.raw);
+ ops->source.raw = NULL;
+ return -1;
+}
+
+static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops)
+{
+ return scnprintf(bf, size, "%-6.6s %s,%s", ins->name,
+ ops->source.name ?: ops->source.raw,
+ ops->target.name ?: ops->target.raw);
+}
+
+static struct ins_ops mov_ops = {
+ .parse = mov__parse,
+ .scnprintf = mov__scnprintf,
+};
+
+static int dec__parse(struct ins_operands *ops)
+{
+ char *target, *comment, *s, prev;
+
+ target = s = ops->raw;
+
+ while (s[0] != '\0' && !isspace(s[0]))
+ ++s;
+ prev = *s;
+ *s = '\0';
+
+ ops->target.raw = strdup(target);
+ *s = prev;
+
+ if (ops->target.raw == NULL)
+ return -1;
+
+ comment = strchr(s, '#');
+ if (comment == NULL)
+ return 0;
+
+ while (comment[0] != '\0' && isspace(comment[0]))
+ ++comment;
+
+ comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name);
+
+ return 0;
+}
+
+static int dec__scnprintf(struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops)
+{
+ return scnprintf(bf, size, "%-6.6s %s", ins->name,
+ ops->target.name ?: ops->target.raw);
+}
+
+static struct ins_ops dec_ops = {
+ .parse = dec__parse,
+ .scnprintf = dec__scnprintf,
+};
+
+static int nop__scnprintf(struct ins *ins __used, char *bf, size_t size,
+ struct ins_operands *ops __used)
+{
+ return scnprintf(bf, size, "%-6.6s", "nop");
+}
+
+static struct ins_ops nop_ops = {
+ .scnprintf = nop__scnprintf,
+};
+
+/*
+ * Must be sorted by name!
+ */
+static struct ins instructions[] = {
+ { .name = "add", .ops = &mov_ops, },
+ { .name = "addl", .ops = &mov_ops, },
+ { .name = "addq", .ops = &mov_ops, },
+ { .name = "addw", .ops = &mov_ops, },
+ { .name = "and", .ops = &mov_ops, },
+ { .name = "bts", .ops = &mov_ops, },
+ { .name = "call", .ops = &call_ops, },
+ { .name = "callq", .ops = &call_ops, },
+ { .name = "cmp", .ops = &mov_ops, },
+ { .name = "cmpb", .ops = &mov_ops, },
+ { .name = "cmpl", .ops = &mov_ops, },
+ { .name = "cmpq", .ops = &mov_ops, },
+ { .name = "cmpw", .ops = &mov_ops, },
+ { .name = "cmpxch", .ops = &mov_ops, },
+ { .name = "dec", .ops = &dec_ops, },
+ { .name = "decl", .ops = &dec_ops, },
+ { .name = "imul", .ops = &mov_ops, },
+ { .name = "inc", .ops = &dec_ops, },
+ { .name = "incl", .ops = &dec_ops, },
+ { .name = "ja", .ops = &jump_ops, },
+ { .name = "jae", .ops = &jump_ops, },
+ { .name = "jb", .ops = &jump_ops, },
+ { .name = "jbe", .ops = &jump_ops, },
+ { .name = "jc", .ops = &jump_ops, },
+ { .name = "jcxz", .ops = &jump_ops, },
+ { .name = "je", .ops = &jump_ops, },
+ { .name = "jecxz", .ops = &jump_ops, },
+ { .name = "jg", .ops = &jump_ops, },
+ { .name = "jge", .ops = &jump_ops, },
+ { .name = "jl", .ops = &jump_ops, },
+ { .name = "jle", .ops = &jump_ops, },
+ { .name = "jmp", .ops = &jump_ops, },
+ { .name = "jmpq", .ops = &jump_ops, },
+ { .name = "jna", .ops = &jump_ops, },
+ { .name = "jnae", .ops = &jump_ops, },
+ { .name = "jnb", .ops = &jump_ops, },
+ { .name = "jnbe", .ops = &jump_ops, },
+ { .name = "jnc", .ops = &jump_ops, },
+ { .name = "jne", .ops = &jump_ops, },
+ { .name = "jng", .ops = &jump_ops, },
+ { .name = "jnge", .ops = &jump_ops, },
+ { .name = "jnl", .ops = &jump_ops, },
+ { .name = "jnle", .ops = &jump_ops, },
+ { .name = "jno", .ops = &jump_ops, },
+ { .name = "jnp", .ops = &jump_ops, },
+ { .name = "jns", .ops = &jump_ops, },
+ { .name = "jnz", .ops = &jump_ops, },
+ { .name = "jo", .ops = &jump_ops, },
+ { .name = "jp", .ops = &jump_ops, },
+ { .name = "jpe", .ops = &jump_ops, },
+ { .name = "jpo", .ops = &jump_ops, },
+ { .name = "jrcxz", .ops = &jump_ops, },
+ { .name = "js", .ops = &jump_ops, },
+ { .name = "jz", .ops = &jump_ops, },
+ { .name = "lea", .ops = &mov_ops, },
+ { .name = "lock", .ops = &lock_ops, },
+ { .name = "mov", .ops = &mov_ops, },
+ { .name = "movb", .ops = &mov_ops, },
+ { .name = "movdqa",.ops = &mov_ops, },
+ { .name = "movl", .ops = &mov_ops, },
+ { .name = "movq", .ops = &mov_ops, },
+ { .name = "movslq", .ops = &mov_ops, },
+ { .name = "movzbl", .ops = &mov_ops, },
+ { .name = "movzwl", .ops = &mov_ops, },
+ { .name = "nop", .ops = &nop_ops, },
+ { .name = "nopl", .ops = &nop_ops, },
+ { .name = "nopw", .ops = &nop_ops, },
+ { .name = "or", .ops = &mov_ops, },
+ { .name = "orl", .ops = &mov_ops, },
+ { .name = "test", .ops = &mov_ops, },
+ { .name = "testb", .ops = &mov_ops, },
+ { .name = "testl", .ops = &mov_ops, },
+ { .name = "xadd", .ops = &mov_ops, },
+};
+
+static int ins__cmp(const void *name, const void *insp)
+{
+ const struct ins *ins = insp;
+
+ return strcmp(name, ins->name);
+}
+
+static struct ins *ins__find(const char *name)
+{
+ const int nmemb = ARRAY_SIZE(instructions);
+
+ return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp);
+}
+
int symbol__annotate_init(struct map *map __used, struct symbol *sym)
{
struct annotation *notes = symbol__annotation(sym);
@@ -28,7 +425,7 @@ int symbol__annotate_init(struct map *map __used, struct symbol *sym)
int symbol__alloc_hist(struct symbol *sym)
{
struct annotation *notes = symbol__annotation(sym);
- const size_t size = sym->end - sym->start + 1;
+ const size_t size = symbol__size(sym);
size_t sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64));
notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist);
@@ -78,31 +475,110 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
return 0;
}
-static struct objdump_line *objdump_line__new(s64 offset, char *line, size_t privsize)
+static void disasm_line__init_ins(struct disasm_line *dl)
+{
+ dl->ins = ins__find(dl->name);
+
+ if (dl->ins == NULL)
+ return;
+
+ if (!dl->ins->ops)
+ return;
+
+ if (dl->ins->ops->parse)
+ dl->ins->ops->parse(&dl->ops);
+}
+
+static int disasm_line__parse(char *line, char **namep, char **rawp)
+{
+ char *name = line, tmp;
+
+ while (isspace(name[0]))
+ ++name;
+
+ if (name[0] == '\0')
+ return -1;
+
+ *rawp = name + 1;
+
+ while ((*rawp)[0] != '\0' && !isspace((*rawp)[0]))
+ ++*rawp;
+
+ tmp = (*rawp)[0];
+ (*rawp)[0] = '\0';
+ *namep = strdup(name);
+
+ if (*namep == NULL)
+ goto out_free_name;
+
+ (*rawp)[0] = tmp;
+
+ if ((*rawp)[0] != '\0') {
+ (*rawp)++;
+ while (isspace((*rawp)[0]))
+ ++(*rawp);
+ }
+
+ return 0;
+
+out_free_name:
+ free(*namep);
+ *namep = NULL;
+ return -1;
+}
+
+static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize)
{
- struct objdump_line *self = malloc(sizeof(*self) + privsize);
+ struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
- if (self != NULL) {
- self->offset = offset;
- self->line = line;
+ if (dl != NULL) {
+ dl->offset = offset;
+ dl->line = strdup(line);
+ if (dl->line == NULL)
+ goto out_delete;
+
+ if (offset != -1) {
+ if (disasm_line__parse(dl->line, &dl->name, &dl->ops.raw) < 0)
+ goto out_free_line;
+
+ disasm_line__init_ins(dl);
+ }
}
- return self;
+ return dl;
+
+out_free_line:
+ free(dl->line);
+out_delete:
+ free(dl);
+ return NULL;
+}
+
+void disasm_line__free(struct disasm_line *dl)
+{
+ free(dl->line);
+ free(dl->name);
+ if (dl->ins && dl->ins->ops->free)
+ dl->ins->ops->free(&dl->ops);
+ else
+ ins__delete(&dl->ops);
+ free(dl);
}
-void objdump_line__free(struct objdump_line *self)
+int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw)
{
- free(self->line);
- free(self);
+ if (raw || !dl->ins)
+ return scnprintf(bf, size, "%-6.6s %s", dl->name, dl->ops.raw);
+
+ return ins__scnprintf(dl->ins, bf, size, &dl->ops);
}
-static void objdump__add_line(struct list_head *head, struct objdump_line *line)
+static void disasm__add(struct list_head *head, struct disasm_line *line)
{
list_add_tail(&line->node, head);
}
-struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
- struct objdump_line *pos)
+struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos)
{
list_for_each_entry_continue(pos, head, node)
if (pos->offset >= 0)
@@ -111,15 +587,14 @@ struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
return NULL;
}
-static int objdump_line__print(struct objdump_line *oline, struct symbol *sym,
- int evidx, u64 len, int min_pcnt,
- int printed, int max_lines,
- struct objdump_line *queue)
+static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 start,
+ int evidx, u64 len, int min_pcnt, int printed,
+ int max_lines, struct disasm_line *queue)
{
static const char *prev_line;
static const char *prev_color;
- if (oline->offset != -1) {
+ if (dl->offset != -1) {
const char *path = NULL;
unsigned int hits = 0;
double percent = 0.0;
@@ -127,10 +602,11 @@ static int objdump_line__print(struct objdump_line *oline, struct symbol *sym,
struct annotation *notes = symbol__annotation(sym);
struct source_line *src_line = notes->src->lines;
struct sym_hist *h = annotation__histogram(notes, evidx);
- s64 offset = oline->offset;
- struct objdump_line *next;
+ s64 offset = dl->offset;
+ const u64 addr = start + offset;
+ struct disasm_line *next;
- next = objdump__get_next_ip_line(&notes->src->source, oline);
+ next = disasm__get_next_ip_line(&notes->src->source, dl);
while (offset < (s64)len &&
(next == NULL || offset < next->offset)) {
@@ -155,9 +631,9 @@ static int objdump_line__print(struct objdump_line *oline, struct symbol *sym,
if (queue != NULL) {
list_for_each_entry_from(queue, &notes->src->source, node) {
- if (queue == oline)
+ if (queue == dl)
break;
- objdump_line__print(queue, sym, evidx, len,
+ disasm_line__print(queue, sym, start, evidx, len,
0, 0, 1, NULL);
}
}
@@ -180,17 +656,18 @@ static int objdump_line__print(struct objdump_line *oline, struct symbol *sym,
color_fprintf(stdout, color, " %7.2f", percent);
printf(" : ");
- color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", oline->line);
+ color_fprintf(stdout, PERF_COLOR_MAGENTA, " %" PRIx64 ":", addr);
+ color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", dl->line);
} else if (max_lines && printed >= max_lines)
return 1;
else {
if (queue)
return -1;
- if (!*oline->line)
+ if (!*dl->line)
printf(" :\n");
else
- printf(" : %s\n", oline->line);
+ printf(" : %s\n", dl->line);
}
return 0;
@@ -200,8 +677,8 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
FILE *file, size_t privsize)
{
struct annotation *notes = symbol__annotation(sym);
- struct objdump_line *objdump_line;
- char *line = NULL, *tmp, *tmp2, *c;
+ struct disasm_line *dl;
+ char *line = NULL, *parsed_line, *tmp, *tmp2, *c;
size_t line_len;
s64 line_ip, offset = -1;
@@ -219,6 +696,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
*c = 0;
line_ip = -1;
+ parsed_line = line;
/*
* Strip leading spaces:
@@ -246,14 +724,17 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
offset = line_ip - start;
if (offset < 0 || (u64)line_ip > end)
offset = -1;
+ else
+ parsed_line = tmp2 + 1;
}
- objdump_line = objdump_line__new(offset, line, privsize);
- if (objdump_line == NULL) {
- free(line);
+ dl = disasm_line__new(offset, parsed_line, privsize);
+ free(line);
+
+ if (dl == NULL)
return -1;
- }
- objdump__add_line(&notes->src->source, objdump_line);
+
+ disasm__add(&notes->src->source, dl);
return 0;
}
@@ -476,7 +957,7 @@ static void symbol__annotate_hits(struct symbol *sym, int evidx)
{
struct annotation *notes = symbol__annotation(sym);
struct sym_hist *h = annotation__histogram(notes, evidx);
- u64 len = sym->end - sym->start, offset;
+ u64 len = symbol__size(sym), offset;
for (offset = 0; offset < len; ++offset)
if (h->addr[offset] != 0)
@@ -492,7 +973,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
struct dso *dso = map->dso;
const char *filename = dso->long_name, *d_filename;
struct annotation *notes = symbol__annotation(sym);
- struct objdump_line *pos, *queue = NULL;
+ struct disasm_line *pos, *queue = NULL;
+ u64 start = map__rip_2objdump(map, sym->start);
int printed = 2, queue_len = 0;
int more = 0;
u64 len;
@@ -502,7 +984,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
else
d_filename = basename(filename);
- len = sym->end - sym->start;
+ len = symbol__size(sym);
printf(" Percent | Source code & Disassembly of %s\n", d_filename);
printf("------------------------------------------------\n");
@@ -516,8 +998,9 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
queue_len = 0;
}
- switch (objdump_line__print(pos, sym, evidx, len, min_pcnt,
- printed, max_lines, queue)) {
+ switch (disasm_line__print(pos, sym, start, evidx, len,
+ min_pcnt, printed, max_lines,
+ queue)) {
case 0:
++printed;
if (context) {
@@ -561,7 +1044,7 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
{
struct annotation *notes = symbol__annotation(sym);
struct sym_hist *h = annotation__histogram(notes, evidx);
- int len = sym->end - sym->start, offset;
+ int len = symbol__size(sym), offset;
h->sum = 0;
for (offset = 0; offset < len; ++offset) {
@@ -570,14 +1053,42 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
}
}
-void objdump_line_list__purge(struct list_head *head)
+void disasm__purge(struct list_head *head)
{
- struct objdump_line *pos, *n;
+ struct disasm_line *pos, *n;
list_for_each_entry_safe(pos, n, head, node) {
list_del(&pos->node);
- objdump_line__free(pos);
+ disasm_line__free(pos);
+ }
+}
+
+static size_t disasm_line__fprintf(struct disasm_line *dl, FILE *fp)
+{
+ size_t printed;
+
+ if (dl->offset == -1)
+ return fprintf(fp, "%s\n", dl->line);
+
+ printed = fprintf(fp, "%#" PRIx64 " %s", dl->offset, dl->name);
+
+ if (dl->ops.raw[0] != '\0') {
+ printed += fprintf(fp, "%.*s %s\n", 6 - (int)printed, " ",
+ dl->ops.raw);
}
+
+ return printed + fprintf(fp, "\n");
+}
+
+size_t disasm__fprintf(struct list_head *head, FILE *fp)
+{
+ struct disasm_line *pos;
+ size_t printed = 0;
+
+ list_for_each_entry(pos, head, node)
+ printed += disasm_line__fprintf(pos, fp);
+
+ return printed;
}
int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
@@ -592,7 +1103,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
if (symbol__annotate(sym, map, 0) < 0)
return -1;
- len = sym->end - sym->start;
+ len = symbol__size(sym);
if (print_lines) {
symbol__get_source_line(sym, map, evidx, &source_line,
@@ -605,7 +1116,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
if (print_lines)
symbol__free_source_line(sym, len);
- objdump_line_list__purge(&symbol__annotation(sym)->src->source);
+ disasm__purge(&symbol__annotation(sym)->src->source);
return 0;
}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index efa5dc82bfae..78a5692dd718 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -2,20 +2,69 @@
#define __PERF_ANNOTATE_H
#include <stdbool.h>
+#include <stdint.h>
#include "types.h"
#include "symbol.h"
#include <linux/list.h>
#include <linux/rbtree.h>
-struct objdump_line {
- struct list_head node;
- s64 offset;
- char *line;
+struct ins;
+
+struct ins_operands {
+ char *raw;
+ struct {
+ char *raw;
+ char *name;
+ u64 addr;
+ u64 offset;
+ } target;
+ union {
+ struct {
+ char *raw;
+ char *name;
+ u64 addr;
+ } source;
+ struct {
+ struct ins *ins;
+ struct ins_operands *ops;
+ } locked;
+ };
};
-void objdump_line__free(struct objdump_line *self);
-struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
- struct objdump_line *pos);
+struct ins_ops {
+ void (*free)(struct ins_operands *ops);
+ int (*parse)(struct ins_operands *ops);
+ int (*scnprintf)(struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops);
+};
+
+struct ins {
+ const char *name;
+ struct ins_ops *ops;
+};
+
+bool ins__is_jump(const struct ins *ins);
+bool ins__is_call(const struct ins *ins);
+int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops);
+
+struct disasm_line {
+ struct list_head node;
+ s64 offset;
+ char *line;
+ char *name;
+ struct ins *ins;
+ struct ins_operands ops;
+};
+
+static inline bool disasm_line__has_offset(const struct disasm_line *dl)
+{
+ return dl->ops.target.offset != UINT64_MAX;
+}
+
+void disasm_line__free(struct disasm_line *dl);
+struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos);
+int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
+size_t disasm__fprintf(struct list_head *head, FILE *fp);
struct sym_hist {
u64 sum;
@@ -32,7 +81,7 @@ struct source_line {
*
* @histogram: Array of addr hit histograms per event being monitored
* @lines: If 'print_lines' is specified, per source code line percentages
- * @source: source parsed from objdump -dS
+ * @source: source parsed from a disassembler like objdump -dS
*
* lines is allocated, percentages calculated and all sorted by percentage
* when the annotation is about to be presented, so the percentages are for
@@ -82,7 +131,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
int context);
void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
-void objdump_line_list__purge(struct list_head *head);
+void disasm__purge(struct list_head *head);
int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
bool print_lines, bool full_paths, int min_pcnt,
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index dff9c7a725f4..fd9a5944b627 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -65,6 +65,8 @@ struct perf_tool build_id__mark_dso_hit_ops = {
.mmap = perf_event__process_mmap,
.fork = perf_event__process_task,
.exit = perf_event__exit_del_thread,
+ .attr = perf_event__process_attr,
+ .build_id = perf_event__process_build_id,
};
char *dso__build_id_filename(struct dso *self, char *bf, size_t size)
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 8dd224df3e54..cff18c617d13 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -33,7 +33,7 @@ extern int pager_use_color;
extern int use_browser;
-#ifdef NO_NEWT_SUPPORT
+#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
static inline void setup_browser(bool fallback_to_pager)
{
if (fallback_to_pager)
@@ -43,19 +43,29 @@ static inline void exit_browser(bool wait_for_ok __used) {}
#else
void setup_browser(bool fallback_to_pager);
void exit_browser(bool wait_for_ok);
+
+#ifdef NO_NEWT_SUPPORT
+static inline int ui__init(void)
+{
+ return -1;
+}
+static inline void ui__exit(bool wait_for_ok __used) {}
+#else
+int ui__init(void);
+void ui__exit(bool wait_for_ok);
#endif
#ifdef NO_GTK2_SUPPORT
-static inline void perf_gtk_setup_browser(int argc __used, const char *argv[] __used, bool fallback_to_pager)
+static inline int perf_gtk__init(void)
{
- if (fallback_to_pager)
- setup_pager();
+ return -1;
}
-static inline void perf_gtk_exit_browser(bool wait_for_ok __used) {}
+static inline void perf_gtk__exit(bool wait_for_ok __used) {}
#else
-void perf_gtk_setup_browser(int argc, const char *argv[], bool fallback_to_pager);
-void perf_gtk_exit_browser(bool wait_for_ok);
+int perf_gtk__init(void);
+void perf_gtk__exit(bool wait_for_ok);
#endif
+#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
char *alias_lookup(const char *alias);
int split_cmdline(char *cmdline, const char ***argv);
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 26817daa2961..efb1fce259a4 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -11,6 +11,7 @@
#include "event.h"
#include "debug.h"
#include "util.h"
+#include "target.h"
int verbose;
bool dump_trace = false, quiet = false;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index f2ce88d04f54..6bebe7f0a20c 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -26,7 +26,7 @@ static inline void ui_progress__update(u64 curr __used, u64 total __used,
#else
extern char ui_helpline__last_msg[];
int ui_helpline__show_help(const char *format, va_list ap);
-#include "ui/progress.h"
+#include "../ui/progress.h"
int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
#endif
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 1986d8051bd1..4ac5f5ae4ce9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -11,6 +11,7 @@
#include <poll.h>
#include "cpumap.h"
#include "thread_map.h"
+#include "target.h"
#include "evlist.h"
#include "evsel.h"
#include <unistd.h>
@@ -599,18 +600,21 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
return perf_evlist__mmap_per_cpu(evlist, prot, mask);
}
-int perf_evlist__create_maps(struct perf_evlist *evlist, const char *target_pid,
- const char *target_tid, uid_t uid, const char *cpu_list)
+int perf_evlist__create_maps(struct perf_evlist *evlist,
+ struct perf_target *target)
{
- evlist->threads = thread_map__new_str(target_pid, target_tid, uid);
+ evlist->threads = thread_map__new_str(target->pid, target->tid,
+ target->uid);
if (evlist->threads == NULL)
return -1;
- if (uid != UINT_MAX || (cpu_list == NULL && target_tid))
+ if (perf_target__has_task(target))
+ evlist->cpus = cpu_map__dummy_new();
+ else if (!perf_target__has_cpu(target) && !target->uses_mmap)
evlist->cpus = cpu_map__dummy_new();
else
- evlist->cpus = cpu_map__new(cpu_list);
+ evlist->cpus = cpu_map__new(target->cpu_list);
if (evlist->cpus == NULL)
goto out_delete_threads;
@@ -827,7 +831,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
exit(-1);
}
- if (!opts->system_wide && !opts->target_tid && !opts->target_pid)
+ if (perf_target__none(&opts->target))
evlist->threads->map[0] = evlist->workload.pid;
close(child_ready_pipe[1]);
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 21f1c9e57f13..58abb63ac13a 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -106,8 +106,8 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
evlist->threads = threads;
}
-int perf_evlist__create_maps(struct perf_evlist *evlist, const char *target_pid,
- const char *tid, uid_t uid, const char *cpu_list);
+int perf_evlist__create_maps(struct perf_evlist *evlist,
+ struct perf_target *target);
void perf_evlist__delete_maps(struct perf_evlist *evlist);
int perf_evlist__set_filters(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 8c13dbcb84b9..57e4ce57bbcc 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -14,6 +14,7 @@
#include "util.h"
#include "cpumap.h"
#include "thread_map.h"
+#include "target.h"
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
@@ -69,6 +70,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
struct perf_event_attr *attr = &evsel->attr;
int track = !evsel->idx; /* only the first counter needs these */
+ attr->disabled = 1;
attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
attr->inherit = !opts->no_inherit;
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
@@ -106,15 +108,15 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
if (opts->call_graph)
attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
- if (opts->system_wide)
+ if (perf_target__has_cpu(&opts->target))
attr->sample_type |= PERF_SAMPLE_CPU;
if (opts->period)
attr->sample_type |= PERF_SAMPLE_PERIOD;
if (!opts->sample_id_all_missing &&
- (opts->sample_time || opts->system_wide ||
- !opts->no_inherit || opts->cpu_list))
+ (opts->sample_time || !opts->no_inherit ||
+ perf_target__has_cpu(&opts->target)))
attr->sample_type |= PERF_SAMPLE_TIME;
if (opts->raw_samples) {
@@ -135,9 +137,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
attr->mmap = track;
attr->comm = track;
- if (!opts->target_pid && !opts->target_tid && !opts->system_wide &&
+ if (perf_target__none(&opts->target) &&
(!opts->group || evsel == first)) {
- attr->disabled = 1;
attr->enable_on_exec = 1;
}
}
@@ -461,10 +462,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
* used for cross-endian analysis. See git commit 65014ab3
* for why this goofiness is needed.
*/
- union {
- u64 val64;
- u32 val32[2];
- } u;
+ union u64_swap u;
memset(data, 0, sizeof(*data));
data->cpu = data->pid = data->tid = -1;
@@ -607,10 +605,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
* used for cross-endian analysis. See git commit 65014ab3
* for why this goofiness is needed.
*/
- union {
- u64 val64;
- u32 val32[2];
- } u;
+ union u64_swap u;
array = event->sample.array;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 4c7c2d73251f..2dd5edf161b7 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -31,21 +31,16 @@ static const char **header_argv;
int perf_header__push_event(u64 id, const char *name)
{
+ struct perf_trace_event_type *nevents;
+
if (strlen(name) > MAX_EVENT_NAME)
pr_warning("Event %s will be truncated\n", name);
- if (!events) {
- events = malloc(sizeof(struct perf_trace_event_type));
- if (events == NULL)
- return -ENOMEM;
- } else {
- struct perf_trace_event_type *nevents;
+ nevents = realloc(events, (event_count + 1) * sizeof(*events));
+ if (nevents == NULL)
+ return -ENOMEM;
+ events = nevents;
- nevents = realloc(events, (event_count + 1) * sizeof(*events));
- if (nevents == NULL)
- return -ENOMEM;
- events = nevents;
- }
memset(&events[event_count], 0, sizeof(struct perf_trace_event_type));
events[event_count].event_id = id;
strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1);
@@ -296,7 +291,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
if (mkdir_p(filename, 0755))
goto out_free;
- snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id);
+ snprintf(filename + len, size - len, "/%s", sbuild_id);
if (access(filename, F_OK)) {
if (is_kallsyms) {
@@ -442,7 +437,7 @@ static bool perf_session__read_build_ids(struct perf_session *session, bool with
return ret;
}
-static int write_trace_info(int fd, struct perf_header *h __used,
+static int write_tracing_data(int fd, struct perf_header *h __used,
struct perf_evlist *evlist)
{
return read_tracing_data(fd, &evlist->entries);
@@ -1477,7 +1472,7 @@ out:
return err;
}
-static int process_trace_info(struct perf_file_section *section __unused,
+static int process_tracing_data(struct perf_file_section *section __unused,
struct perf_header *ph __unused,
int feat __unused, int fd)
{
@@ -1513,11 +1508,11 @@ struct feature_ops {
.full_only = true }
/* feature_ops not implemented: */
-#define print_trace_info NULL
-#define print_build_id NULL
+#define print_tracing_data NULL
+#define print_build_id NULL
static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
- FEAT_OPP(HEADER_TRACE_INFO, trace_info),
+ FEAT_OPP(HEADER_TRACING_DATA, tracing_data),
FEAT_OPP(HEADER_BUILD_ID, build_id),
FEAT_OPA(HEADER_HOSTNAME, hostname),
FEAT_OPA(HEADER_OSRELEASE, osrelease),
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 21a6be09c129..2d42b3e1826f 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -12,7 +12,7 @@
enum {
HEADER_RESERVED = 0, /* always cleared */
HEADER_FIRST_FEATURE = 1,
- HEADER_TRACE_INFO = 1,
+ HEADER_TRACING_DATA = 1,
HEADER_BUILD_ID,
HEADER_HOSTNAME,
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 9f6d630d5316..1293b5ebea4d 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -599,7 +599,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
if (chain->ms.sym)
ret += fprintf(fp, "%s\n", chain->ms.sym->name);
else
- ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
+ ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip);
return ret;
}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 2cae9df40e04..cfc64e293f90 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -138,7 +138,7 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
#define K_LEFT -1
#define K_RIGHT -2
#else
-#include "ui/keysyms.h"
+#include "../ui/keysyms.h"
int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
void(*timer)(void *arg), void *arg, int delay_secs);
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
new file mode 100644
index 000000000000..76b98e2a587d
--- /dev/null
+++ b/tools/perf/util/parse-events-test.c
@@ -0,0 +1,625 @@
+
+#include "parse-events.h"
+#include "evsel.h"
+#include "evlist.h"
+#include "sysfs.h"
+#include "../../../include/linux/hw_breakpoint.h"
+
+#define TEST_ASSERT_VAL(text, cond) \
+do { \
+ if (!(cond)) { \
+ pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
+ return -1; \
+ } \
+} while (0)
+
+static int test__checkevent_tracepoint(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong sample_type",
+ (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
+ evsel->attr.sample_type);
+ TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
+ return 0;
+}
+
+static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel;
+
+ TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
+
+ list_for_each_entry(evsel, &evlist->entries, node) {
+ TEST_ASSERT_VAL("wrong type",
+ PERF_TYPE_TRACEPOINT == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong sample_type",
+ (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU)
+ == evsel->attr.sample_type);
+ TEST_ASSERT_VAL("wrong sample_period",
+ 1 == evsel->attr.sample_period);
+ }
+ return 0;
+}
+
+static int test__checkevent_raw(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", 0x1a == evsel->attr.config);
+ return 0;
+}
+
+static int test__checkevent_numeric(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
+ return 0;
+}
+
+static int test__checkevent_symbolic_name(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
+ return 0;
+}
+
+static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong period",
+ 100000 == evsel->attr.sample_period);
+ TEST_ASSERT_VAL("wrong config1",
+ 0 == evsel->attr.config1);
+ TEST_ASSERT_VAL("wrong config2",
+ 1 == evsel->attr.config2);
+ return 0;
+}
+
+static int test__checkevent_symbolic_alias(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config);
+ return 0;
+}
+
+static int test__checkevent_genhw(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", (1 << 16) == evsel->attr.config);
+ return 0;
+}
+
+static int test__checkevent_breakpoint(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) ==
+ evsel->attr.bp_type);
+ TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_4 ==
+ evsel->attr.bp_len);
+ return 0;
+}
+
+static int test__checkevent_breakpoint_x(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong bp_type",
+ HW_BREAKPOINT_X == evsel->attr.bp_type);
+ TEST_ASSERT_VAL("wrong bp_len", sizeof(long) == evsel->attr.bp_len);
+ return 0;
+}
+
+static int test__checkevent_breakpoint_r(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type",
+ PERF_TYPE_BREAKPOINT == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong bp_type",
+ HW_BREAKPOINT_R == evsel->attr.bp_type);
+ TEST_ASSERT_VAL("wrong bp_len",
+ HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
+ return 0;
+}
+
+static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type",
+ PERF_TYPE_BREAKPOINT == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong bp_type",
+ HW_BREAKPOINT_W == evsel->attr.bp_type);
+ TEST_ASSERT_VAL("wrong bp_len",
+ HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
+ return 0;
+}
+
+static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+
+ return test__checkevent_tracepoint(evlist);
+}
+
+static int
+test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel;
+
+ TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
+
+ list_for_each_entry(evsel, &evlist->entries, node) {
+ TEST_ASSERT_VAL("wrong exclude_user",
+ !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel",
+ evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ }
+
+ return test__checkevent_tracepoint_multi(evlist);
+}
+
+static int test__checkevent_raw_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+
+ return test__checkevent_raw(evlist);
+}
+
+static int test__checkevent_numeric_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+
+ return test__checkevent_numeric(evlist);
+}
+
+static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+
+ return test__checkevent_symbolic_name(evlist);
+}
+
+static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
+
+ return test__checkevent_symbolic_name(evlist);
+}
+
+static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
+
+ return test__checkevent_symbolic_name(evlist);
+}
+
+static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+
+ return test__checkevent_symbolic_alias(evlist);
+}
+
+static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+
+ return test__checkevent_genhw(evlist);
+}
+
+static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+
+ return test__checkevent_breakpoint(evlist);
+}
+
+static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+
+ return test__checkevent_breakpoint_x(evlist);
+}
+
+static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+
+ return test__checkevent_breakpoint_r(evlist);
+}
+
+static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+
+ return test__checkevent_breakpoint_w(evlist);
+}
+
+static int test__checkevent_pmu(struct perf_evlist *evlist)
+{
+
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", 10 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong config1", 1 == evsel->attr.config1);
+ TEST_ASSERT_VAL("wrong config2", 3 == evsel->attr.config2);
+ TEST_ASSERT_VAL("wrong period", 1000 == evsel->attr.sample_period);
+
+ return 0;
+}
+
+static int test__checkevent_list(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel;
+
+ TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
+
+ /* r1 */
+ evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong config1", 0 == evsel->attr.config1);
+ TEST_ASSERT_VAL("wrong config2", 0 == evsel->attr.config2);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+
+ /* syscalls:sys_enter_open:k */
+ evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong sample_type",
+ (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
+ evsel->attr.sample_type);
+ TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+
+ /* 1:1:hp */
+ evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+
+ return 0;
+}
+
+static int test__checkevent_pmu_name(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel;
+
+ /* cpu/config=1,name=krava1/u */
+ evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "krava"));
+
+ /* cpu/config=2/" */
+ evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "raw 0x2"));
+
+ return 0;
+}
+
+struct test__event_st {
+ const char *name;
+ __u32 type;
+ int (*check)(struct perf_evlist *evlist);
+};
+
+static struct test__event_st test__events[] = {
+ [0] = {
+ .name = "syscalls:sys_enter_open",
+ .check = test__checkevent_tracepoint,
+ },
+ [1] = {
+ .name = "syscalls:*",
+ .check = test__checkevent_tracepoint_multi,
+ },
+ [2] = {
+ .name = "r1a",
+ .check = test__checkevent_raw,
+ },
+ [3] = {
+ .name = "1:1",
+ .check = test__checkevent_numeric,
+ },
+ [4] = {
+ .name = "instructions",
+ .check = test__checkevent_symbolic_name,
+ },
+ [5] = {
+ .name = "cycles/period=100000,config2/",
+ .check = test__checkevent_symbolic_name_config,
+ },
+ [6] = {
+ .name = "faults",
+ .check = test__checkevent_symbolic_alias,
+ },
+ [7] = {
+ .name = "L1-dcache-load-miss",
+ .check = test__checkevent_genhw,
+ },
+ [8] = {
+ .name = "mem:0",
+ .check = test__checkevent_breakpoint,
+ },
+ [9] = {
+ .name = "mem:0:x",
+ .check = test__checkevent_breakpoint_x,
+ },
+ [10] = {
+ .name = "mem:0:r",
+ .check = test__checkevent_breakpoint_r,
+ },
+ [11] = {
+ .name = "mem:0:w",
+ .check = test__checkevent_breakpoint_w,
+ },
+ [12] = {
+ .name = "syscalls:sys_enter_open:k",
+ .check = test__checkevent_tracepoint_modifier,
+ },
+ [13] = {
+ .name = "syscalls:*:u",
+ .check = test__checkevent_tracepoint_multi_modifier,
+ },
+ [14] = {
+ .name = "r1a:kp",
+ .check = test__checkevent_raw_modifier,
+ },
+ [15] = {
+ .name = "1:1:hp",
+ .check = test__checkevent_numeric_modifier,
+ },
+ [16] = {
+ .name = "instructions:h",
+ .check = test__checkevent_symbolic_name_modifier,
+ },
+ [17] = {
+ .name = "faults:u",
+ .check = test__checkevent_symbolic_alias_modifier,
+ },
+ [18] = {
+ .name = "L1-dcache-load-miss:kp",
+ .check = test__checkevent_genhw_modifier,
+ },
+ [19] = {
+ .name = "mem:0:u",
+ .check = test__checkevent_breakpoint_modifier,
+ },
+ [20] = {
+ .name = "mem:0:x:k",
+ .check = test__checkevent_breakpoint_x_modifier,
+ },
+ [21] = {
+ .name = "mem:0:r:hp",
+ .check = test__checkevent_breakpoint_r_modifier,
+ },
+ [22] = {
+ .name = "mem:0:w:up",
+ .check = test__checkevent_breakpoint_w_modifier,
+ },
+ [23] = {
+ .name = "r1,syscalls:sys_enter_open:k,1:1:hp",
+ .check = test__checkevent_list,
+ },
+ [24] = {
+ .name = "instructions:G",
+ .check = test__checkevent_exclude_host_modifier,
+ },
+ [25] = {
+ .name = "instructions:H",
+ .check = test__checkevent_exclude_guest_modifier,
+ },
+};
+
+#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
+
+static struct test__event_st test__events_pmu[] = {
+ [0] = {
+ .name = "cpu/config=10,config1,config2=3,period=1000/u",
+ .check = test__checkevent_pmu,
+ },
+ [1] = {
+ .name = "cpu/config=1,name=krava/u,cpu/config=2/u",
+ .check = test__checkevent_pmu_name,
+ },
+};
+
+#define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \
+ sizeof(struct test__event_st))
+
+static int test(struct test__event_st *e)
+{
+ struct perf_evlist *evlist;
+ int ret;
+
+ evlist = perf_evlist__new(NULL, NULL);
+ if (evlist == NULL)
+ return -ENOMEM;
+
+ ret = parse_events(evlist, e->name, 0);
+ if (ret) {
+ pr_debug("failed to parse event '%s', err %d\n",
+ e->name, ret);
+ return ret;
+ }
+
+ ret = e->check(evlist);
+ perf_evlist__delete(evlist);
+
+ return ret;
+}
+
+static int test_events(struct test__event_st *events, unsigned cnt)
+{
+ int ret = 0;
+ unsigned i;
+
+ for (i = 0; i < cnt; i++) {
+ struct test__event_st *e = &events[i];
+
+ pr_debug("running test %d '%s'\n", i, e->name);
+ ret = test(e);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+static int test_pmu(void)
+{
+ struct stat st;
+ char path[PATH_MAX];
+ int ret;
+
+ snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/format/",
+ sysfs_find_mountpoint());
+
+ ret = stat(path, &st);
+ if (ret)
+ pr_debug("ommiting PMU cpu tests\n");
+ return !ret;
+}
+
+int parse_events__test(void)
+{
+ int ret;
+
+ ret = test_events(test__events, TEST__EVENTS_CNT);
+ if (!ret && test_pmu())
+ ret = test_events(test__events_pmu, TEST__EVENTS_PMU_CNT);
+
+ return ret;
+}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 5b3a0ef4e232..fac7d59309b8 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -23,8 +23,10 @@ struct event_symbol {
const char *alias;
};
-int parse_events_parse(struct list_head *list, struct list_head *list_tmp,
- int *idx);
+#ifdef PARSER_DEBUG
+extern int parse_events_debug;
+#endif
+int parse_events_parse(struct list_head *list, int *idx);
#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
@@ -355,20 +357,30 @@ const char *__event_name(int type, u64 config)
return "unknown";
}
-static int add_event(struct list_head *list, int *idx,
+static int add_event(struct list_head **_list, int *idx,
struct perf_event_attr *attr, char *name)
{
struct perf_evsel *evsel;
+ struct list_head *list = *_list;
+
+ if (!list) {
+ list = malloc(sizeof(*list));
+ if (!list)
+ return -ENOMEM;
+ INIT_LIST_HEAD(list);
+ }
event_attr_init(attr);
evsel = perf_evsel__new(attr, (*idx)++);
- if (!evsel)
+ if (!evsel) {
+ free(list);
return -ENOMEM;
-
- list_add_tail(&evsel->node, list);
+ }
evsel->name = strdup(name);
+ list_add_tail(&evsel->node, list);
+ *_list = list;
return 0;
}
@@ -390,7 +402,7 @@ static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size)
return -1;
}
-int parse_events_add_cache(struct list_head *list, int *idx,
+int parse_events_add_cache(struct list_head **list, int *idx,
char *type, char *op_result1, char *op_result2)
{
struct perf_event_attr attr;
@@ -451,7 +463,7 @@ int parse_events_add_cache(struct list_head *list, int *idx,
return add_event(list, idx, &attr, name);
}
-static int add_tracepoint(struct list_head *list, int *idx,
+static int add_tracepoint(struct list_head **list, int *idx,
char *sys_name, char *evt_name)
{
struct perf_event_attr attr;
@@ -488,7 +500,7 @@ static int add_tracepoint(struct list_head *list, int *idx,
return add_event(list, idx, &attr, name);
}
-static int add_tracepoint_multi(struct list_head *list, int *idx,
+static int add_tracepoint_multi(struct list_head **list, int *idx,
char *sys_name, char *evt_name)
{
char evt_path[MAXPATHLEN];
@@ -519,7 +531,7 @@ static int add_tracepoint_multi(struct list_head *list, int *idx,
return ret;
}
-int parse_events_add_tracepoint(struct list_head *list, int *idx,
+int parse_events_add_tracepoint(struct list_head **list, int *idx,
char *sys, char *event)
{
int ret;
@@ -563,7 +575,7 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
return 0;
}
-int parse_events_add_breakpoint(struct list_head *list, int *idx,
+int parse_events_add_breakpoint(struct list_head **list, int *idx,
void *ptr, char *type)
{
struct perf_event_attr attr;
@@ -593,17 +605,27 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
static int config_term(struct perf_event_attr *attr,
struct parse_events__term *term)
{
- switch (term->type) {
+#define CHECK_TYPE_VAL(type) \
+do { \
+ if (PARSE_EVENTS__TERM_TYPE_ ## type != term->type_val) \
+ return -EINVAL; \
+} while (0)
+
+ switch (term->type_term) {
case PARSE_EVENTS__TERM_TYPE_CONFIG:
+ CHECK_TYPE_VAL(NUM);
attr->config = term->val.num;
break;
case PARSE_EVENTS__TERM_TYPE_CONFIG1:
+ CHECK_TYPE_VAL(NUM);
attr->config1 = term->val.num;
break;
case PARSE_EVENTS__TERM_TYPE_CONFIG2:
+ CHECK_TYPE_VAL(NUM);
attr->config2 = term->val.num;
break;
case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
+ CHECK_TYPE_VAL(NUM);
attr->sample_period = term->val.num;
break;
case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
@@ -612,10 +634,15 @@ static int config_term(struct perf_event_attr *attr,
* attr->branch_sample_type = term->val.num;
*/
break;
+ case PARSE_EVENTS__TERM_TYPE_NAME:
+ CHECK_TYPE_VAL(STR);
+ break;
default:
return -EINVAL;
}
+
return 0;
+#undef CHECK_TYPE_VAL
}
static int config_attr(struct perf_event_attr *attr,
@@ -630,7 +657,7 @@ static int config_attr(struct perf_event_attr *attr,
return 0;
}
-int parse_events_add_numeric(struct list_head *list, int *idx,
+int parse_events_add_numeric(struct list_head **list, int *idx,
unsigned long type, unsigned long config,
struct list_head *head_config)
{
@@ -648,7 +675,24 @@ int parse_events_add_numeric(struct list_head *list, int *idx,
(char *) __event_name(type, config));
}
-int parse_events_add_pmu(struct list_head *list, int *idx,
+static int parse_events__is_name_term(struct parse_events__term *term)
+{
+ return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
+}
+
+static char *pmu_event_name(struct perf_event_attr *attr,
+ struct list_head *head_terms)
+{
+ struct parse_events__term *term;
+
+ list_for_each_entry(term, head_terms, list)
+ if (parse_events__is_name_term(term))
+ return term->val.str;
+
+ return (char *) __event_name(PERF_TYPE_RAW, attr->config);
+}
+
+int parse_events_add_pmu(struct list_head **list, int *idx,
char *name, struct list_head *head_config)
{
struct perf_event_attr attr;
@@ -669,7 +713,8 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
if (perf_pmu__config(pmu, &attr, head_config))
return -EINVAL;
- return add_event(list, idx, &attr, (char *) "pmu");
+ return add_event(list, idx, &attr,
+ pmu_event_name(&attr, head_config));
}
void parse_events_update_lists(struct list_head *list_event,
@@ -681,7 +726,7 @@ void parse_events_update_lists(struct list_head *list_event,
* list, for next event definition.
*/
list_splice_tail(list_event, list_all);
- INIT_LIST_HEAD(list_event);
+ free(list_event);
}
int parse_events_modifier(struct list_head *list, char *str)
@@ -756,10 +801,14 @@ int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
buffer = parse_events__scan_string(str);
- ret = parse_events_parse(&list, &list_tmp, &idx);
+#ifdef PARSER_DEBUG
+ parse_events_debug = 1;
+#endif
+ ret = parse_events_parse(&list, &idx);
parse_events__flush_buffer(buffer);
parse_events__delete_buffer(buffer);
+ parse_events_lex_destroy();
if (!ret) {
int entries = idx - evlist->nr_entries;
@@ -1015,11 +1064,12 @@ void print_events(const char *event_glob)
int parse_events__is_hardcoded_term(struct parse_events__term *term)
{
- return term->type <= PARSE_EVENTS__TERM_TYPE_HARDCODED_MAX;
+ return term->type_term != PARSE_EVENTS__TERM_TYPE_USER;
}
-int parse_events__new_term(struct parse_events__term **_term, int type,
- char *config, char *str, long num)
+static int new_term(struct parse_events__term **_term, int type_val,
+ int type_term, char *config,
+ char *str, long num)
{
struct parse_events__term *term;
@@ -1028,15 +1078,11 @@ int parse_events__new_term(struct parse_events__term **_term, int type,
return -ENOMEM;
INIT_LIST_HEAD(&term->list);
- term->type = type;
+ term->type_val = type_val;
+ term->type_term = type_term;
term->config = config;
- switch (type) {
- case PARSE_EVENTS__TERM_TYPE_CONFIG:
- case PARSE_EVENTS__TERM_TYPE_CONFIG1:
- case PARSE_EVENTS__TERM_TYPE_CONFIG2:
- case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
- case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
+ switch (type_val) {
case PARSE_EVENTS__TERM_TYPE_NUM:
term->val.num = num;
break;
@@ -1051,6 +1097,20 @@ int parse_events__new_term(struct parse_events__term **_term, int type,
return 0;
}
+int parse_events__term_num(struct parse_events__term **term,
+ int type_term, char *config, long num)
+{
+ return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
+ config, NULL, num);
+}
+
+int parse_events__term_str(struct parse_events__term **term,
+ int type_term, char *config, char *str)
+{
+ return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term,
+ config, str, 0);
+}
+
void parse_events__free_terms(struct list_head *terms)
{
struct parse_events__term *term, *h;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ca069f893381..8cac57ab4ee6 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -4,7 +4,11 @@
* Parse symbolic events/counts passed in as options:
*/
+#include <linux/list.h>
+#include <stdbool.h>
+#include "types.h"
#include "../../../include/linux/perf_event.h"
+#include "types.h"
struct list_head;
struct perf_evsel;
@@ -34,16 +38,18 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);
#define EVENTS_HELP_MAX (128*1024)
enum {
+ PARSE_EVENTS__TERM_TYPE_NUM,
+ PARSE_EVENTS__TERM_TYPE_STR,
+};
+
+enum {
+ PARSE_EVENTS__TERM_TYPE_USER,
PARSE_EVENTS__TERM_TYPE_CONFIG,
PARSE_EVENTS__TERM_TYPE_CONFIG1,
PARSE_EVENTS__TERM_TYPE_CONFIG2,
+ PARSE_EVENTS__TERM_TYPE_NAME,
PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD,
PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
- PARSE_EVENTS__TERM_TYPE_NUM,
- PARSE_EVENTS__TERM_TYPE_STR,
-
- PARSE_EVENTS__TERM_TYPE_HARDCODED_MAX =
- PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
};
struct parse_events__term {
@@ -52,35 +58,34 @@ struct parse_events__term {
char *str;
long num;
} val;
- int type;
-
+ int type_val;
+ int type_term;
struct list_head list;
};
int parse_events__is_hardcoded_term(struct parse_events__term *term);
-int parse_events__new_term(struct parse_events__term **term, int type,
- char *config, char *str, long num);
+int parse_events__term_num(struct parse_events__term **_term,
+ int type_term, char *config, long num);
+int parse_events__term_str(struct parse_events__term **_term,
+ int type_term, char *config, char *str);
void parse_events__free_terms(struct list_head *terms);
-int parse_events_modifier(struct list_head *list __used, char *str __used);
-int parse_events_add_tracepoint(struct list_head *list, int *idx,
+int parse_events_modifier(struct list_head *list, char *str);
+int parse_events_add_tracepoint(struct list_head **list, int *idx,
char *sys, char *event);
-int parse_events_add_raw(struct perf_evlist *evlist, unsigned long config,
- unsigned long config1, unsigned long config2,
- char *mod);
-int parse_events_add_numeric(struct list_head *list, int *idx,
+int parse_events_add_numeric(struct list_head **list, int *idx,
unsigned long type, unsigned long config,
struct list_head *head_config);
-int parse_events_add_cache(struct list_head *list, int *idx,
+int parse_events_add_cache(struct list_head **list, int *idx,
char *type, char *op_result1, char *op_result2);
-int parse_events_add_breakpoint(struct list_head *list, int *idx,
+int parse_events_add_breakpoint(struct list_head **list, int *idx,
void *ptr, char *type);
-int parse_events_add_pmu(struct list_head *list, int *idx,
+int parse_events_add_pmu(struct list_head **list, int *idx,
char *pmu , struct list_head *head_config);
void parse_events_update_lists(struct list_head *list_event,
struct list_head *list_all);
void parse_events_error(struct list_head *list_all,
- struct list_head *list_event,
int *idx, char const *msg);
+int parse_events__test(void);
void print_events(const char *event_glob);
void print_events_type(u8 type);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 1fcf1bbc5458..618a8e788399 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -1,5 +1,6 @@
%option prefix="parse_events_"
+%option stack
%{
#include <errno.h>
@@ -50,6 +51,8 @@ static int term(int type)
%}
+%x mem
+
num_dec [0-9]+
num_hex 0x[a-fA-F0-9]+
num_raw_hex [a-fA-F0-9]+
@@ -102,16 +105,16 @@ misses|miss { return str(PE_NAME_CACHE_OP_RESULT); }
config { return term(PARSE_EVENTS__TERM_TYPE_CONFIG); }
config1 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG1); }
config2 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG2); }
+name { return term(PARSE_EVENTS__TERM_TYPE_NAME); }
period { return term(PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
branch_type { return term(PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
-mem: { return PE_PREFIX_MEM; }
+mem: { BEGIN(mem); return PE_PREFIX_MEM; }
r{num_raw_hex} { return raw(); }
{num_dec} { return value(10); }
{num_hex} { return value(16); }
{modifier_event} { return str(PE_MODIFIER_EVENT); }
-{modifier_bp} { return str(PE_MODIFIER_BP); }
{name} { return str(PE_NAME); }
"/" { return '/'; }
- { return '-'; }
@@ -119,6 +122,25 @@ r{num_raw_hex} { return raw(); }
: { return ':'; }
= { return '='; }
+<mem>{
+{modifier_bp} { return str(PE_MODIFIER_BP); }
+: { return ':'; }
+{num_dec} { return value(10); }
+{num_hex} { return value(16); }
+ /*
+ * We need to separate 'mem:' scanner part, in order to get specific
+ * modifier bits parsed out. Otherwise we would need to handle PE_NAME
+ * and we'd need to parse it manually. During the escape from <mem>
+ * state we need to put the escaping char back, so we dont miss it.
+ */
+. { unput(*parse_events_text); BEGIN(INITIAL); }
+ /*
+ * We destroy the scanner after reaching EOF,
+ * but anyway just to be sure get back to INIT state.
+ */
+<<EOF>> { BEGIN(INITIAL); }
+}
+
%%
int parse_events_wrap(void)
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index d9637da7333c..362cc59332ae 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -1,7 +1,6 @@
%name-prefix "parse_events_"
%parse-param {struct list_head *list_all}
-%parse-param {struct list_head *list_event}
%parse-param {int *idx}
%{
@@ -41,6 +40,14 @@ do { \
%type <str> PE_MODIFIER_BP
%type <head> event_config
%type <term> event_term
+%type <head> event_pmu
+%type <head> event_legacy_symbol
+%type <head> event_legacy_cache
+%type <head> event_legacy_mem
+%type <head> event_legacy_tracepoint
+%type <head> event_legacy_numeric
+%type <head> event_legacy_raw
+%type <head> event_def
%union
{
@@ -62,13 +69,13 @@ event_def PE_MODIFIER_EVENT
* (there could be more events added for multiple tracepoint
* definitions via '*?'.
*/
- ABORT_ON(parse_events_modifier(list_event, $2));
- parse_events_update_lists(list_event, list_all);
+ ABORT_ON(parse_events_modifier($1, $2));
+ parse_events_update_lists($1, list_all);
}
|
event_def
{
- parse_events_update_lists(list_event, list_all);
+ parse_events_update_lists($1, list_all);
}
event_def: event_pmu |
@@ -82,71 +89,102 @@ event_def: event_pmu |
event_pmu:
PE_NAME '/' event_config '/'
{
- ABORT_ON(parse_events_add_pmu(list_event, idx, $1, $3));
+ struct list_head *list = NULL;
+
+ ABORT_ON(parse_events_add_pmu(&list, idx, $1, $3));
parse_events__free_terms($3);
+ $$ = list;
}
event_legacy_symbol:
PE_VALUE_SYM '/' event_config '/'
{
+ struct list_head *list = NULL;
int type = $1 >> 16;
int config = $1 & 255;
- ABORT_ON(parse_events_add_numeric(list_event, idx, type, config, $3));
+ ABORT_ON(parse_events_add_numeric(&list, idx, type, config, $3));
parse_events__free_terms($3);
+ $$ = list;
}
|
PE_VALUE_SYM sep_slash_dc
{
+ struct list_head *list = NULL;
int type = $1 >> 16;
int config = $1 & 255;
- ABORT_ON(parse_events_add_numeric(list_event, idx, type, config, NULL));
+ ABORT_ON(parse_events_add_numeric(&list, idx, type, config, NULL));
+ $$ = list;
}
event_legacy_cache:
PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
{
- ABORT_ON(parse_events_add_cache(list_event, idx, $1, $3, $5));
+ struct list_head *list = NULL;
+
+ ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, $5));
+ $$ = list;
}
|
PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
{
- ABORT_ON(parse_events_add_cache(list_event, idx, $1, $3, NULL));
+ struct list_head *list = NULL;
+
+ ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, NULL));
+ $$ = list;
}
|
PE_NAME_CACHE_TYPE
{
- ABORT_ON(parse_events_add_cache(list_event, idx, $1, NULL, NULL));
+ struct list_head *list = NULL;
+
+ ABORT_ON(parse_events_add_cache(&list, idx, $1, NULL, NULL));
+ $$ = list;
}
event_legacy_mem:
PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
{
- ABORT_ON(parse_events_add_breakpoint(list_event, idx, (void *) $2, $4));
+ struct list_head *list = NULL;
+
+ ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, $4));
+ $$ = list;
}
|
PE_PREFIX_MEM PE_VALUE sep_dc
{
- ABORT_ON(parse_events_add_breakpoint(list_event, idx, (void *) $2, NULL));
+ struct list_head *list = NULL;
+
+ ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, NULL));
+ $$ = list;
}
event_legacy_tracepoint:
PE_NAME ':' PE_NAME
{
- ABORT_ON(parse_events_add_tracepoint(list_event, idx, $1, $3));
+ struct list_head *list = NULL;
+
+ ABORT_ON(parse_events_add_tracepoint(&list, idx, $1, $3));
+ $$ = list;
}
event_legacy_numeric:
PE_VALUE ':' PE_VALUE
{
- ABORT_ON(parse_events_add_numeric(list_event, idx, $1, $3, NULL));
+ struct list_head *list = NULL;
+
+ ABORT_ON(parse_events_add_numeric(&list, idx, $1, $3, NULL));
+ $$ = list;
}
event_legacy_raw:
PE_RAW
{
- ABORT_ON(parse_events_add_numeric(list_event, idx, PERF_TYPE_RAW, $1, NULL));
+ struct list_head *list = NULL;
+
+ ABORT_ON(parse_events_add_numeric(&list, idx, PERF_TYPE_RAW, $1, NULL));
+ $$ = list;
}
event_config:
@@ -176,8 +214,8 @@ PE_NAME '=' PE_NAME
{
struct parse_events__term *term;
- ABORT_ON(parse_events__new_term(&term, PARSE_EVENTS__TERM_TYPE_STR,
- $1, $3, 0));
+ ABORT_ON(parse_events__term_str(&term, PARSE_EVENTS__TERM_TYPE_USER,
+ $1, $3));
$$ = term;
}
|
@@ -185,8 +223,8 @@ PE_NAME '=' PE_VALUE
{
struct parse_events__term *term;
- ABORT_ON(parse_events__new_term(&term, PARSE_EVENTS__TERM_TYPE_NUM,
- $1, NULL, $3));
+ ABORT_ON(parse_events__term_num(&term, PARSE_EVENTS__TERM_TYPE_USER,
+ $1, $3));
$$ = term;
}
|
@@ -194,8 +232,16 @@ PE_NAME
{
struct parse_events__term *term;
- ABORT_ON(parse_events__new_term(&term, PARSE_EVENTS__TERM_TYPE_NUM,
- $1, NULL, 1));
+ ABORT_ON(parse_events__term_num(&term, PARSE_EVENTS__TERM_TYPE_USER,
+ $1, 1));
+ $$ = term;
+}
+|
+PE_TERM '=' PE_NAME
+{
+ struct parse_events__term *term;
+
+ ABORT_ON(parse_events__term_str(&term, $1, NULL, $3));
$$ = term;
}
|
@@ -203,7 +249,7 @@ PE_TERM '=' PE_VALUE
{
struct parse_events__term *term;
- ABORT_ON(parse_events__new_term(&term, $1, NULL, NULL, $3));
+ ABORT_ON(parse_events__term_num(&term, $1, NULL, $3));
$$ = term;
}
|
@@ -211,7 +257,7 @@ PE_TERM
{
struct parse_events__term *term;
- ABORT_ON(parse_events__new_term(&term, $1, NULL, NULL, 1));
+ ABORT_ON(parse_events__term_num(&term, $1, NULL, 1));
$$ = term;
}
@@ -222,7 +268,6 @@ sep_slash_dc: '/' | ':' |
%%
void parse_events_error(struct list_head *list_all __used,
- struct list_head *list_event __used,
int *idx __used,
char const *msg __used)
{
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index cb08a118e811..a119a5371699 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -225,7 +225,7 @@ static int pmu_config_term(struct list_head *formats,
if (parse_events__is_hardcoded_term(term))
return 0;
- if (term->type != PARSE_EVENTS__TERM_TYPE_NUM)
+ if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
return -EINVAL;
format = pmu_find_format(formats, term->config);
@@ -246,6 +246,11 @@ static int pmu_config_term(struct list_head *formats,
return -EINVAL;
}
+ /*
+ * XXX If we ever decide to go with string values for
+ * non-hardcoded terms, here's the place to translate
+ * them into value.
+ */
*vp |= pmu_format_value(format->bits, term->val.num);
return 0;
}
@@ -253,9 +258,9 @@ static int pmu_config_term(struct list_head *formats,
static int pmu_config(struct list_head *formats, struct perf_event_attr *attr,
struct list_head *head_terms)
{
- struct parse_events__term *term, *h;
+ struct parse_events__term *term;
- list_for_each_entry_safe(term, h, head_terms, list)
+ list_for_each_entry(term, head_terms, list)
if (pmu_config_term(formats, attr, term))
return -EINVAL;
@@ -324,49 +329,58 @@ static struct test_format {
/* Simulated users input. */
static struct parse_events__term test_terms[] = {
{
- .config = (char *) "krava01",
- .val.num = 15,
- .type = PARSE_EVENTS__TERM_TYPE_NUM,
+ .config = (char *) "krava01",
+ .val.num = 15,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
},
{
- .config = (char *) "krava02",
- .val.num = 170,
- .type = PARSE_EVENTS__TERM_TYPE_NUM,
+ .config = (char *) "krava02",
+ .val.num = 170,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
},
{
- .config = (char *) "krava03",
- .val.num = 1,
- .type = PARSE_EVENTS__TERM_TYPE_NUM,
+ .config = (char *) "krava03",
+ .val.num = 1,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
},
{
- .config = (char *) "krava11",
- .val.num = 27,
- .type = PARSE_EVENTS__TERM_TYPE_NUM,
+ .config = (char *) "krava11",
+ .val.num = 27,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
},
{
- .config = (char *) "krava12",
- .val.num = 1,
- .type = PARSE_EVENTS__TERM_TYPE_NUM,
+ .config = (char *) "krava12",
+ .val.num = 1,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
},
{
- .config = (char *) "krava13",
- .val.num = 2,
- .type = PARSE_EVENTS__TERM_TYPE_NUM,
+ .config = (char *) "krava13",
+ .val.num = 2,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
},
{
- .config = (char *) "krava21",
- .val.num = 119,
- .type = PARSE_EVENTS__TERM_TYPE_NUM,
+ .config = (char *) "krava21",
+ .val.num = 119,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
},
{
- .config = (char *) "krava22",
- .val.num = 11,
- .type = PARSE_EVENTS__TERM_TYPE_NUM,
+ .config = (char *) "krava22",
+ .val.num = 11,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
},
{
- .config = (char *) "krava23",
- .val.num = 2,
- .type = PARSE_EVENTS__TERM_TYPE_NUM,
+ .config = (char *) "krava23",
+ .val.num = 2,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
},
};
#define TERMS_CNT (sizeof(test_terms) / sizeof(struct parse_events__term))
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index e30749e38a9b..4c1b3d72a1d2 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -56,7 +56,7 @@ INTERP my_perl;
#define FTRACE_MAX_EVENT \
((1 << (sizeof(unsigned short) * 8)) - 1)
-struct event *events[FTRACE_MAX_EVENT];
+struct event_format *events[FTRACE_MAX_EVENT];
extern struct scripting_context *scripting_context;
@@ -181,7 +181,7 @@ static void define_flag_field(const char *ev_name,
LEAVE;
}
-static void define_event_symbols(struct event *event,
+static void define_event_symbols(struct event_format *event,
const char *ev_name,
struct print_arg *args)
{
@@ -209,6 +209,8 @@ static void define_event_symbols(struct event *event,
define_symbolic_values(args->symbol.symbols, ev_name,
cur_field_name);
break;
+ case PRINT_BSTRING:
+ case PRINT_DYNAMIC_ARRAY:
case PRINT_STRING:
break;
case PRINT_TYPE:
@@ -220,7 +222,9 @@ static void define_event_symbols(struct event *event,
define_event_symbols(event, ev_name, args->op.left);
define_event_symbols(event, ev_name, args->op.right);
break;
+ case PRINT_FUNC:
default:
+ pr_err("Unsupported print arg type\n");
/* we should warn... */
return;
}
@@ -229,10 +233,10 @@ static void define_event_symbols(struct event *event,
define_event_symbols(event, ev_name, args->next);
}
-static inline struct event *find_cache_event(int type)
+static inline struct event_format *find_cache_event(int type)
{
static char ev_name[256];
- struct event *event;
+ struct event_format *event;
if (events[type])
return events[type];
@@ -258,7 +262,7 @@ static void perl_process_tracepoint(union perf_event *pevent __unused,
static char handler[256];
unsigned long long val;
unsigned long s, ns;
- struct event *event;
+ struct event_format *event;
int type;
int pid;
int cpu = sample->cpu;
@@ -446,7 +450,7 @@ static int perl_stop_script(void)
static int perl_generate_script(const char *outfile)
{
- struct event *event = NULL;
+ struct event_format *event = NULL;
struct format_field *f;
char fname[PATH_MAX];
int not_first, count;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index c2623c6f9b51..acb9795286c4 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -37,7 +37,7 @@ PyMODINIT_FUNC initperf_trace_context(void);
#define FTRACE_MAX_EVENT \
((1 << (sizeof(unsigned short) * 8)) - 1)
-struct event *events[FTRACE_MAX_EVENT];
+struct event_format *events[FTRACE_MAX_EVENT];
#define MAX_FIELDS 64
#define N_COMMON_FIELDS 7
@@ -136,7 +136,7 @@ static void define_field(enum print_arg_type field_type,
Py_DECREF(t);
}
-static void define_event_symbols(struct event *event,
+static void define_event_symbols(struct event_format *event,
const char *ev_name,
struct print_arg *args)
{
@@ -178,6 +178,10 @@ static void define_event_symbols(struct event *event,
define_event_symbols(event, ev_name, args->op.right);
break;
default:
+ /* gcc warns for these? */
+ case PRINT_BSTRING:
+ case PRINT_DYNAMIC_ARRAY:
+ case PRINT_FUNC:
/* we should warn... */
return;
}
@@ -186,10 +190,10 @@ static void define_event_symbols(struct event *event,
define_event_symbols(event, ev_name, args->next);
}
-static inline struct event *find_cache_event(int type)
+static inline struct event_format *find_cache_event(int type)
{
static char ev_name[256];
- struct event *event;
+ struct event_format *event;
if (events[type])
return events[type];
@@ -216,7 +220,7 @@ static void python_process_event(union perf_event *pevent __unused,
struct format_field *field;
unsigned long long val;
unsigned long s, ns;
- struct event *event;
+ struct event_format *event;
unsigned n = 0;
int type;
int pid;
@@ -436,7 +440,7 @@ out:
static int python_generate_script(const char *outfile)
{
- struct event *event = NULL;
+ struct event_format *event = NULL;
struct format_field *f;
char fname[PATH_MAX];
int not_first, count;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 1efd3bee6336..93d355d27109 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -481,6 +481,38 @@ static void perf_event__read_swap(union perf_event *event)
event->read.id = bswap_64(event->read.id);
}
+static u8 revbyte(u8 b)
+{
+ int rev = (b >> 4) | ((b & 0xf) << 4);
+ rev = ((rev & 0xcc) >> 2) | ((rev & 0x33) << 2);
+ rev = ((rev & 0xaa) >> 1) | ((rev & 0x55) << 1);
+ return (u8) rev;
+}
+
+/*
+ * XXX this is hack in attempt to carry flags bitfield
+ * throught endian village. ABI says:
+ *
+ * Bit-fields are allocated from right to left (least to most significant)
+ * on little-endian implementations and from left to right (most to least
+ * significant) on big-endian implementations.
+ *
+ * The above seems to be byte specific, so we need to reverse each
+ * byte of the bitfield. 'Internet' also says this might be implementation
+ * specific and we probably need proper fix and carry perf_event_attr
+ * bitfield flags in separate data file FEAT_ section. Thought this seems
+ * to work for now.
+ */
+static void swap_bitfield(u8 *p, unsigned len)
+{
+ unsigned i;
+
+ for (i = 0; i < len; i++) {
+ *p = revbyte(*p);
+ p++;
+ }
+}
+
/* exported for swapping attributes in file header */
void perf_event__attr_swap(struct perf_event_attr *attr)
{
@@ -494,6 +526,8 @@ void perf_event__attr_swap(struct perf_event_attr *attr)
attr->bp_type = bswap_32(attr->bp_type);
attr->bp_addr = bswap_64(attr->bp_addr);
attr->bp_len = bswap_64(attr->bp_len);
+
+ swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64));
}
static void perf_event__hdr_attr_swap(union perf_event *event)
@@ -1064,8 +1098,9 @@ volatile int session_done;
static int __perf_session__process_pipe_events(struct perf_session *self,
struct perf_tool *tool)
{
- union perf_event event;
- uint32_t size;
+ union perf_event *event;
+ uint32_t size, cur_size = 0;
+ void *buf = NULL;
int skip = 0;
u64 head;
int err;
@@ -1074,8 +1109,14 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
perf_tool__fill_defaults(tool);
head = 0;
+ cur_size = sizeof(union perf_event);
+
+ buf = malloc(cur_size);
+ if (!buf)
+ return -errno;
more:
- err = readn(self->fd, &event, sizeof(struct perf_event_header));
+ event = buf;
+ err = readn(self->fd, event, sizeof(struct perf_event_header));
if (err <= 0) {
if (err == 0)
goto done;
@@ -1085,13 +1126,23 @@ more:
}
if (self->header.needs_swap)
- perf_event_header__bswap(&event.header);
+ perf_event_header__bswap(&event->header);
- size = event.header.size;
+ size = event->header.size;
if (size == 0)
size = 8;
- p = &event;
+ if (size > cur_size) {
+ void *new = realloc(buf, size);
+ if (!new) {
+ pr_err("failed to allocate memory to read event\n");
+ goto out_err;
+ }
+ buf = new;
+ cur_size = size;
+ event = buf;
+ }
+ p = event;
p += sizeof(struct perf_event_header);
if (size - sizeof(struct perf_event_header)) {
@@ -1107,17 +1158,11 @@ more:
}
}
- if ((skip = perf_session__process_event(self, &event, tool, head)) < 0) {
- dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
- head, event.header.size, event.header.type);
- /*
- * assume we lost track of the stream, check alignment, and
- * increment a single u64 in the hope to catch on again 'soon'.
- */
- if (unlikely(head & 7))
- head &= ~7ULL;
-
- size = 8;
+ if ((skip = perf_session__process_event(self, event, tool, head)) < 0) {
+ pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
+ head, event->header.size, event->header.type);
+ err = -EINVAL;
+ goto out_err;
}
head += size;
@@ -1130,6 +1175,7 @@ more:
done:
err = 0;
out_err:
+ free(buf);
perf_session__warn_about_errors(self, tool);
perf_session_free_sample_buffers(self);
return err;
@@ -1226,17 +1272,11 @@ more:
if (size == 0 ||
perf_session__process_event(session, event, tool, file_pos) < 0) {
- dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
- file_offset + head, event->header.size,
- event->header.type);
- /*
- * assume we lost track of the stream, check alignment, and
- * increment a single u64 in the hope to catch on again 'soon'.
- */
- if (unlikely(head & 7))
- head &= ~7ULL;
-
- size = 8;
+ pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
+ file_offset + head, event->header.size,
+ event->header.type);
+ err = -EINVAL;
+ goto out_err;
}
head += size;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index ac49ef208a5f..1f003884f1ab 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -65,6 +65,11 @@ struct symbol {
void symbol__delete(struct symbol *sym);
+static inline size_t symbol__size(const struct symbol *sym)
+{
+ return sym->end - sym->start + 1;
+}
+
struct strlist;
struct symbol_conf {
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
new file mode 100644
index 000000000000..1064d5b148ad
--- /dev/null
+++ b/tools/perf/util/target.c
@@ -0,0 +1,142 @@
+/*
+ * Helper functions for handling target threads/cpus
+ *
+ * Copyright (C) 2012, LG Electronics, Namhyung Kim <namhyung.kim@lge.com>
+ *
+ * Released under the GPL v2.
+ */
+
+#include "target.h"
+#include "debug.h"
+
+#include <pwd.h>
+#include <string.h>
+
+
+enum perf_target_errno perf_target__validate(struct perf_target *target)
+{
+ enum perf_target_errno ret = PERF_ERRNO_TARGET__SUCCESS;
+
+ if (target->pid)
+ target->tid = target->pid;
+
+ /* CPU and PID are mutually exclusive */
+ if (target->tid && target->cpu_list) {
+ target->cpu_list = NULL;
+ if (ret == PERF_ERRNO_TARGET__SUCCESS)
+ ret = PERF_ERRNO_TARGET__PID_OVERRIDE_CPU;
+ }
+
+ /* UID and PID are mutually exclusive */
+ if (target->tid && target->uid_str) {
+ target->uid_str = NULL;
+ if (ret == PERF_ERRNO_TARGET__SUCCESS)
+ ret = PERF_ERRNO_TARGET__PID_OVERRIDE_UID;
+ }
+
+ /* UID and CPU are mutually exclusive */
+ if (target->uid_str && target->cpu_list) {
+ target->cpu_list = NULL;
+ if (ret == PERF_ERRNO_TARGET__SUCCESS)
+ ret = PERF_ERRNO_TARGET__UID_OVERRIDE_CPU;
+ }
+
+ /* PID and SYSTEM are mutually exclusive */
+ if (target->tid && target->system_wide) {
+ target->system_wide = false;
+ if (ret == PERF_ERRNO_TARGET__SUCCESS)
+ ret = PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM;
+ }
+
+ /* UID and SYSTEM are mutually exclusive */
+ if (target->uid_str && target->system_wide) {
+ target->system_wide = false;
+ if (ret == PERF_ERRNO_TARGET__SUCCESS)
+ ret = PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM;
+ }
+
+ return ret;
+}
+
+enum perf_target_errno perf_target__parse_uid(struct perf_target *target)
+{
+ struct passwd pwd, *result;
+ char buf[1024];
+ const char *str = target->uid_str;
+
+ target->uid = UINT_MAX;
+ if (str == NULL)
+ return PERF_ERRNO_TARGET__SUCCESS;
+
+ /* Try user name first */
+ getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
+
+ if (result == NULL) {
+ /*
+ * The user name not found. Maybe it's a UID number.
+ */
+ char *endptr;
+ int uid = strtol(str, &endptr, 10);
+
+ if (*endptr != '\0')
+ return PERF_ERRNO_TARGET__INVALID_UID;
+
+ getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
+
+ if (result == NULL)
+ return PERF_ERRNO_TARGET__USER_NOT_FOUND;
+ }
+
+ target->uid = result->pw_uid;
+ return PERF_ERRNO_TARGET__SUCCESS;
+}
+
+/*
+ * This must have a same ordering as the enum perf_target_errno.
+ */
+static const char *perf_target__error_str[] = {
+ "PID/TID switch overriding CPU",
+ "PID/TID switch overriding UID",
+ "UID switch overriding CPU",
+ "PID/TID switch overriding SYSTEM",
+ "UID switch overriding SYSTEM",
+ "Invalid User: %s",
+ "Problems obtaining information for user %s",
+};
+
+int perf_target__strerror(struct perf_target *target, int errnum,
+ char *buf, size_t buflen)
+{
+ int idx;
+ const char *msg;
+
+ if (errnum >= 0) {
+ strerror_r(errnum, buf, buflen);
+ return 0;
+ }
+
+ if (errnum < __PERF_ERRNO_TARGET__START ||
+ errnum >= __PERF_ERRNO_TARGET__END)
+ return -1;
+
+ idx = errnum - __PERF_ERRNO_TARGET__START;
+ msg = perf_target__error_str[idx];
+
+ switch (errnum) {
+ case PERF_ERRNO_TARGET__PID_OVERRIDE_CPU
+ ... PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM:
+ snprintf(buf, buflen, "%s", msg);
+ break;
+
+ case PERF_ERRNO_TARGET__INVALID_UID:
+ case PERF_ERRNO_TARGET__USER_NOT_FOUND:
+ snprintf(buf, buflen, msg, target->uid_str);
+ break;
+
+ default:
+ /* cannot reach here */
+ break;
+ }
+
+ return 0;
+}
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h
new file mode 100644
index 000000000000..a4be8575fda5
--- /dev/null
+++ b/tools/perf/util/target.h
@@ -0,0 +1,65 @@
+#ifndef _PERF_TARGET_H
+#define _PERF_TARGET_H
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+struct perf_target {
+ const char *pid;
+ const char *tid;
+ const char *cpu_list;
+ const char *uid_str;
+ uid_t uid;
+ bool system_wide;
+ bool uses_mmap;
+};
+
+enum perf_target_errno {
+ PERF_ERRNO_TARGET__SUCCESS = 0,
+
+ /*
+ * Choose an arbitrary negative big number not to clash with standard
+ * errno since SUS requires the errno has distinct positive values.
+ * See 'Issue 6' in the link below.
+ *
+ * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
+ */
+ __PERF_ERRNO_TARGET__START = -10000,
+
+
+ /* for perf_target__validate() */
+ PERF_ERRNO_TARGET__PID_OVERRIDE_CPU = __PERF_ERRNO_TARGET__START,
+ PERF_ERRNO_TARGET__PID_OVERRIDE_UID,
+ PERF_ERRNO_TARGET__UID_OVERRIDE_CPU,
+ PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM,
+ PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM,
+
+ /* for perf_target__parse_uid() */
+ PERF_ERRNO_TARGET__INVALID_UID,
+ PERF_ERRNO_TARGET__USER_NOT_FOUND,
+
+ __PERF_ERRNO_TARGET__END,
+};
+
+enum perf_target_errno perf_target__validate(struct perf_target *target);
+enum perf_target_errno perf_target__parse_uid(struct perf_target *target);
+
+int perf_target__strerror(struct perf_target *target, int errnum, char *buf,
+ size_t buflen);
+
+static inline bool perf_target__has_task(struct perf_target *target)
+{
+ return target->tid || target->pid || target->uid_str;
+}
+
+static inline bool perf_target__has_cpu(struct perf_target *target)
+{
+ return target->system_wide || target->cpu_list;
+}
+
+static inline bool perf_target__none(struct perf_target *target)
+{
+ return !perf_target__has_task(target) && !perf_target__has_cpu(target);
+}
+
+#endif /* _PERF_TARGET_H */
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 7da80f14418b..f718df8a3c59 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -6,7 +6,7 @@
struct thread_map {
int nr;
- int map[];
+ pid_t map[];
};
struct thread_map *thread_map__new_by_pid(pid_t pid);
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 09fe579ccafb..abe0e8e95068 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -69,23 +69,24 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
ret += SNPRINTF(bf + ret, size - ret, "], ");
- if (top->target_pid)
+ if (top->target.pid)
ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s",
- top->target_pid);
- else if (top->target_tid)
+ top->target.pid);
+ else if (top->target.tid)
ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s",
- top->target_tid);
- else if (top->uid_str != NULL)
+ top->target.tid);
+ else if (top->target.uid_str != NULL)
ret += SNPRINTF(bf + ret, size - ret, " (uid: %s",
- top->uid_str);
+ top->target.uid_str);
else
ret += SNPRINTF(bf + ret, size - ret, " (all");
- if (top->cpu_list)
+ if (top->target.cpu_list)
ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)",
- top->evlist->cpus->nr > 1 ? "s" : "", top->cpu_list);
+ top->evlist->cpus->nr > 1 ? "s" : "",
+ top->target.cpu_list);
else {
- if (top->target_tid)
+ if (top->target.tid)
ret += SNPRINTF(bf + ret, size - ret, ")");
else
ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index ce61cb2d1acf..33347ca89ee4 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -13,6 +13,7 @@ struct perf_session;
struct perf_top {
struct perf_tool tool;
struct perf_evlist *evlist;
+ struct perf_target target;
/*
* Symbols will be added here in perf_event__process_sample and will
* get out after decayed.
@@ -23,10 +24,7 @@ struct perf_top {
u64 guest_us_samples, guest_kernel_samples;
int print_entries, count_filter, delay_secs;
int freq;
- const char *target_pid, *target_tid;
- uid_t uid;
bool hide_kernel_symbols, hide_user_symbols, zero;
- bool system_wide;
bool use_tui, use_stdio;
bool sort_has_symbols;
bool dont_use_callchains;
@@ -37,7 +35,6 @@ struct perf_top {
bool sample_id_all_missing;
bool exclude_guest_missing;
bool dump_symtab;
- const char *cpu_list;
struct hist_entry *sym_filter_entry;
struct perf_evsel *sym_evsel;
struct perf_session *session;
@@ -47,7 +44,6 @@ struct perf_top {
int realtime_prio;
int sym_pcnt_filter;
const char *sym_filter;
- const char *uid_str;
};
size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index fc22cf5c605f..a8d81c35ef66 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -68,7 +68,7 @@ struct events {
};
-void *malloc_or_die(unsigned int size)
+static void *malloc_or_die(unsigned int size)
{
void *data;
@@ -448,6 +448,8 @@ static void tracing_data_header(void)
else
buf[0] = 0;
+ read_trace_init(buf[0], buf[0]);
+
write_or_die(buf, 1);
/* save size of long */
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index dfd1bd8371a4..df2fddbf0cd2 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -17,2169 +17,305 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * The parts for function graph printing was taken and modified from the
- * Linux Kernel that were written by Frederic Weisbecker.
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include <errno.h>
#include "../perf.h"
#include "util.h"
#include "trace-event.h"
-int header_page_ts_offset;
-int header_page_ts_size;
-int header_page_size_offset;
int header_page_size_size;
-int header_page_overwrite_offset;
-int header_page_overwrite_size;
+int header_page_ts_size;
int header_page_data_offset;
-int header_page_data_size;
-
-bool latency_format;
-
-static char *input_buf;
-static unsigned long long input_buf_ptr;
-static unsigned long long input_buf_siz;
-
-static int cpus;
-static int long_size;
-static int is_flag_field;
-static int is_symbolic_field;
-
-static struct format_field *
-find_any_field(struct event *event, const char *name);
-
-static void init_input_buf(char *buf, unsigned long long size)
-{
- input_buf = buf;
- input_buf_siz = size;
- input_buf_ptr = 0;
-}
-
-struct cmdline {
- char *comm;
- int pid;
-};
-
-static struct cmdline *cmdlines;
-static int cmdline_count;
-
-static int cmdline_cmp(const void *a, const void *b)
-{
- const struct cmdline *ca = a;
- const struct cmdline *cb = b;
-
- if (ca->pid < cb->pid)
- return -1;
- if (ca->pid > cb->pid)
- return 1;
-
- return 0;
-}
-void parse_cmdlines(char *file, int size __unused)
-{
- struct cmdline_list {
- struct cmdline_list *next;
- char *comm;
- int pid;
- } *list = NULL, *item;
- char *line;
- char *next = NULL;
- int i;
+struct pevent *perf_pevent;
+static struct pevent *pevent;
- line = strtok_r(file, "\n", &next);
- while (line) {
- item = malloc_or_die(sizeof(*item));
- sscanf(line, "%d %as", &item->pid,
- (float *)(void *)&item->comm); /* workaround gcc warning */
- item->next = list;
- list = item;
- line = strtok_r(NULL, "\n", &next);
- cmdline_count++;
- }
-
- cmdlines = malloc_or_die(sizeof(*cmdlines) * cmdline_count);
-
- i = 0;
- while (list) {
- cmdlines[i].pid = list->pid;
- cmdlines[i].comm = list->comm;
- i++;
- item = list;
- list = list->next;
- free(item);
- }
-
- qsort(cmdlines, cmdline_count, sizeof(*cmdlines), cmdline_cmp);
-}
-
-static struct func_map {
- unsigned long long addr;
- char *func;
- char *mod;
-} *func_list;
-static unsigned int func_count;
-
-static int func_cmp(const void *a, const void *b)
-{
- const struct func_map *fa = a;
- const struct func_map *fb = b;
-
- if (fa->addr < fb->addr)
- return -1;
- if (fa->addr > fb->addr)
- return 1;
-
- return 0;
-}
-
-void parse_proc_kallsyms(char *file, unsigned int size __unused)
-{
- struct func_list {
- struct func_list *next;
- unsigned long long addr;
- char *func;
- char *mod;
- } *list = NULL, *item;
- char *line;
- char *next = NULL;
- char *addr_str;
- char ch;
- int ret __used;
- int i;
-
- line = strtok_r(file, "\n", &next);
- while (line) {
- item = malloc_or_die(sizeof(*item));
- item->mod = NULL;
- ret = sscanf(line, "%as %c %as\t[%as",
- (float *)(void *)&addr_str, /* workaround gcc warning */
- &ch,
- (float *)(void *)&item->func,
- (float *)(void *)&item->mod);
- item->addr = strtoull(addr_str, NULL, 16);
- free(addr_str);
-
- /* truncate the extra ']' */
- if (item->mod)
- item->mod[strlen(item->mod) - 1] = 0;
-
-
- item->next = list;
- list = item;
- line = strtok_r(NULL, "\n", &next);
- func_count++;
- }
-
- func_list = malloc_or_die(sizeof(*func_list) * (func_count + 1));
-
- i = 0;
- while (list) {
- func_list[i].func = list->func;
- func_list[i].addr = list->addr;
- func_list[i].mod = list->mod;
- i++;
- item = list;
- list = list->next;
- free(item);
- }
-
- qsort(func_list, func_count, sizeof(*func_list), func_cmp);
-
- /*
- * Add a special record at the end.
- */
- func_list[func_count].func = NULL;
- func_list[func_count].addr = 0;
- func_list[func_count].mod = NULL;
-}
+bool latency_format;
-/*
- * We are searching for a record in between, not an exact
- * match.
- */
-static int func_bcmp(const void *a, const void *b)
+int read_trace_init(int file_bigendian, int host_bigendian)
{
- const struct func_map *fa = a;
- const struct func_map *fb = b;
-
- if ((fa->addr == fb->addr) ||
-
- (fa->addr > fb->addr &&
- fa->addr < (fb+1)->addr))
+ if (pevent)
return 0;
- if (fa->addr < fb->addr)
- return -1;
-
- return 1;
-}
-
-static struct func_map *find_func(unsigned long long addr)
-{
- struct func_map *func;
- struct func_map key;
-
- key.addr = addr;
-
- func = bsearch(&key, func_list, func_count, sizeof(*func_list),
- func_bcmp);
-
- return func;
-}
-
-void print_funcs(void)
-{
- int i;
-
- for (i = 0; i < (int)func_count; i++) {
- printf("%016llx %s",
- func_list[i].addr,
- func_list[i].func);
- if (func_list[i].mod)
- printf(" [%s]\n", func_list[i].mod);
- else
- printf("\n");
- }
-}
+ perf_pevent = pevent_alloc();
+ pevent = perf_pevent;
-static struct printk_map {
- unsigned long long addr;
- char *printk;
-} *printk_list;
-static unsigned int printk_count;
-
-static int printk_cmp(const void *a, const void *b)
-{
- const struct func_map *fa = a;
- const struct func_map *fb = b;
-
- if (fa->addr < fb->addr)
- return -1;
- if (fa->addr > fb->addr)
- return 1;
+ pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
+ pevent_set_file_bigendian(pevent, file_bigendian);
+ pevent_set_host_bigendian(pevent, host_bigendian);
return 0;
}
-static struct printk_map *find_printk(unsigned long long addr)
-{
- struct printk_map *printk;
- struct printk_map key;
-
- key.addr = addr;
-
- printk = bsearch(&key, printk_list, printk_count, sizeof(*printk_list),
- printk_cmp);
-
- return printk;
-}
-
-void parse_ftrace_printk(char *file, unsigned int size __unused)
-{
- struct printk_list {
- struct printk_list *next;
- unsigned long long addr;
- char *printk;
- } *list = NULL, *item;
- char *line;
- char *next = NULL;
- char *addr_str;
- int i;
-
- line = strtok_r(file, "\n", &next);
- while (line) {
- addr_str = strsep(&line, ":");
- if (!line) {
- warning("error parsing print strings");
- break;
- }
- item = malloc_or_die(sizeof(*item));
- item->addr = strtoull(addr_str, NULL, 16);
- /* fmt still has a space, skip it */
- item->printk = strdup(line+1);
- item->next = list;
- list = item;
- line = strtok_r(NULL, "\n", &next);
- printk_count++;
- }
-
- printk_list = malloc_or_die(sizeof(*printk_list) * printk_count + 1);
-
- i = 0;
- while (list) {
- printk_list[i].printk = list->printk;
- printk_list[i].addr = list->addr;
- i++;
- item = list;
- list = list->next;
- free(item);
- }
-
- qsort(printk_list, printk_count, sizeof(*printk_list), printk_cmp);
-}
-
-void print_printk(void)
-{
- int i;
-
- for (i = 0; i < (int)printk_count; i++) {
- printf("%016llx %s\n",
- printk_list[i].addr,
- printk_list[i].printk);
- }
-}
-
-static struct event *alloc_event(void)
-{
- struct event *event;
-
- event = malloc_or_die(sizeof(*event));
- memset(event, 0, sizeof(*event));
-
- return event;
-}
-
-enum event_type {
- EVENT_ERROR,
- EVENT_NONE,
- EVENT_SPACE,
- EVENT_NEWLINE,
- EVENT_OP,
- EVENT_DELIM,
- EVENT_ITEM,
- EVENT_DQUOTE,
- EVENT_SQUOTE,
-};
-
-static struct event *event_list;
-
-static void add_event(struct event *event)
+static int get_common_field(struct scripting_context *context,
+ int *offset, int *size, const char *type)
{
- event->next = event_list;
- event_list = event;
-}
-
-static int event_item_type(enum event_type type)
-{
- switch (type) {
- case EVENT_ITEM ... EVENT_SQUOTE:
- return 1;
- case EVENT_ERROR ... EVENT_DELIM:
- default:
- return 0;
- }
-}
-
-static void free_arg(struct print_arg *arg)
-{
- if (!arg)
- return;
-
- switch (arg->type) {
- case PRINT_ATOM:
- if (arg->atom.atom)
- free(arg->atom.atom);
- break;
- case PRINT_NULL:
- case PRINT_FIELD ... PRINT_OP:
- default:
- /* todo */
- break;
- }
-
- free(arg);
-}
-
-static enum event_type get_type(int ch)
-{
- if (ch == '\n')
- return EVENT_NEWLINE;
- if (isspace(ch))
- return EVENT_SPACE;
- if (isalnum(ch) || ch == '_')
- return EVENT_ITEM;
- if (ch == '\'')
- return EVENT_SQUOTE;
- if (ch == '"')
- return EVENT_DQUOTE;
- if (!isprint(ch))
- return EVENT_NONE;
- if (ch == '(' || ch == ')' || ch == ',')
- return EVENT_DELIM;
-
- return EVENT_OP;
-}
-
-static int __read_char(void)
-{
- if (input_buf_ptr >= input_buf_siz)
- return -1;
-
- return input_buf[input_buf_ptr++];
-}
-
-static int __peek_char(void)
-{
- if (input_buf_ptr >= input_buf_siz)
- return -1;
-
- return input_buf[input_buf_ptr];
-}
-
-static enum event_type __read_token(char **tok)
-{
- char buf[BUFSIZ];
- int ch, last_ch, quote_ch, next_ch;
- int i = 0;
- int tok_size = 0;
- enum event_type type;
-
- *tok = NULL;
-
-
- ch = __read_char();
- if (ch < 0)
- return EVENT_NONE;
-
- type = get_type(ch);
- if (type == EVENT_NONE)
- return type;
-
- buf[i++] = ch;
-
- switch (type) {
- case EVENT_NEWLINE:
- case EVENT_DELIM:
- *tok = malloc_or_die(2);
- (*tok)[0] = ch;
- (*tok)[1] = 0;
- return type;
-
- case EVENT_OP:
- switch (ch) {
- case '-':
- next_ch = __peek_char();
- if (next_ch == '>') {
- buf[i++] = __read_char();
- break;
- }
- /* fall through */
- case '+':
- case '|':
- case '&':
- case '>':
- case '<':
- last_ch = ch;
- ch = __peek_char();
- if (ch != last_ch)
- goto test_equal;
- buf[i++] = __read_char();
- switch (last_ch) {
- case '>':
- case '<':
- goto test_equal;
- default:
- break;
- }
- break;
- case '!':
- case '=':
- goto test_equal;
- default: /* what should we do instead? */
- break;
- }
- buf[i] = 0;
- *tok = strdup(buf);
- return type;
-
- test_equal:
- ch = __peek_char();
- if (ch == '=')
- buf[i++] = __read_char();
- break;
-
- case EVENT_DQUOTE:
- case EVENT_SQUOTE:
- /* don't keep quotes */
- i--;
- quote_ch = ch;
- last_ch = 0;
- do {
- if (i == (BUFSIZ - 1)) {
- buf[i] = 0;
- if (*tok) {
- *tok = realloc(*tok, tok_size + BUFSIZ);
- if (!*tok)
- return EVENT_NONE;
- strcat(*tok, buf);
- } else
- *tok = strdup(buf);
-
- if (!*tok)
- return EVENT_NONE;
- tok_size += BUFSIZ;
- i = 0;
- }
- last_ch = ch;
- ch = __read_char();
- buf[i++] = ch;
- /* the '\' '\' will cancel itself */
- if (ch == '\\' && last_ch == '\\')
- last_ch = 0;
- } while (ch != quote_ch || last_ch == '\\');
- /* remove the last quote */
- i--;
- goto out;
-
- case EVENT_ERROR ... EVENT_SPACE:
- case EVENT_ITEM:
- default:
- break;
- }
-
- while (get_type(__peek_char()) == type) {
- if (i == (BUFSIZ - 1)) {
- buf[i] = 0;
- if (*tok) {
- *tok = realloc(*tok, tok_size + BUFSIZ);
- if (!*tok)
- return EVENT_NONE;
- strcat(*tok, buf);
- } else
- *tok = strdup(buf);
-
- if (!*tok)
- return EVENT_NONE;
- tok_size += BUFSIZ;
- i = 0;
- }
- ch = __read_char();
- buf[i++] = ch;
- }
-
- out:
- buf[i] = 0;
- if (*tok) {
- *tok = realloc(*tok, tok_size + i);
- if (!*tok)
- return EVENT_NONE;
- strcat(*tok, buf);
- } else
- *tok = strdup(buf);
- if (!*tok)
- return EVENT_NONE;
-
- return type;
-}
-
-static void free_token(char *tok)
-{
- if (tok)
- free(tok);
-}
-
-static enum event_type read_token(char **tok)
-{
- enum event_type type;
-
- for (;;) {
- type = __read_token(tok);
- if (type != EVENT_SPACE)
- return type;
-
- free_token(*tok);
- }
-
- /* not reached */
- return EVENT_NONE;
-}
-
-/* no newline */
-static enum event_type read_token_item(char **tok)
-{
- enum event_type type;
-
- for (;;) {
- type = __read_token(tok);
- if (type != EVENT_SPACE && type != EVENT_NEWLINE)
- return type;
-
- free_token(*tok);
- }
-
- /* not reached */
- return EVENT_NONE;
-}
-
-static int test_type(enum event_type type, enum event_type expect)
-{
- if (type != expect) {
- warning("Error: expected type %d but read %d",
- expect, type);
- return -1;
- }
- return 0;
-}
+ struct event_format *event;
+ struct format_field *field;
-static int __test_type_token(enum event_type type, char *token,
- enum event_type expect, const char *expect_tok,
- bool warn)
-{
- if (type != expect) {
- if (warn)
- warning("Error: expected type %d but read %d",
- expect, type);
- return -1;
- }
+ if (!*size) {
+ if (!pevent->events)
+ return 0;
- if (strcmp(token, expect_tok) != 0) {
- if (warn)
- warning("Error: expected '%s' but read '%s'",
- expect_tok, token);
- return -1;
+ event = pevent->events[0];
+ field = pevent_find_common_field(event, type);
+ if (!field)
+ return 0;
+ *offset = field->offset;
+ *size = field->size;
}
- return 0;
-}
-static int test_type_token(enum event_type type, char *token,
- enum event_type expect, const char *expect_tok)
-{
- return __test_type_token(type, token, expect, expect_tok, true);
+ return pevent_read_number(pevent, context->event_data + *offset, *size);
}
-static int __read_expect_type(enum event_type expect, char **tok, int newline_ok)
-{
- enum event_type type;
-
- if (newline_ok)
- type = read_token(tok);
- else
- type = read_token_item(tok);
- return test_type(type, expect);
-}
-
-static int read_expect_type(enum event_type expect, char **tok)
-{
- return __read_expect_type(expect, tok, 1);
-}
-
-static int __read_expected(enum event_type expect, const char *str,
- int newline_ok, bool warn)
+int common_lock_depth(struct scripting_context *context)
{
- enum event_type type;
- char *token;
+ static int offset;
+ static int size;
int ret;
- if (newline_ok)
- type = read_token(&token);
- else
- type = read_token_item(&token);
-
- ret = __test_type_token(type, token, expect, str, warn);
-
- free_token(token);
+ ret = get_common_field(context, &size, &offset,
+ "common_lock_depth");
+ if (ret < 0)
+ return -1;
return ret;
}
-static int read_expected(enum event_type expect, const char *str)
-{
- return __read_expected(expect, str, 1, true);
-}
-
-static int read_expected_item(enum event_type expect, const char *str)
-{
- return __read_expected(expect, str, 0, true);
-}
-
-static char *event_read_name(void)
-{
- char *token;
-
- if (read_expected(EVENT_ITEM, "name") < 0)
- return NULL;
-
- if (read_expected(EVENT_OP, ":") < 0)
- return NULL;
-
- if (read_expect_type(EVENT_ITEM, &token) < 0)
- goto fail;
-
- return token;
-
- fail:
- free_token(token);
- return NULL;
-}
-
-static int event_read_id(void)
+int common_flags(struct scripting_context *context)
{
- char *token;
- int id = -1;
-
- if (read_expected_item(EVENT_ITEM, "ID") < 0)
- return -1;
+ static int offset;
+ static int size;
+ int ret;
- if (read_expected(EVENT_OP, ":") < 0)
+ ret = get_common_field(context, &size, &offset,
+ "common_flags");
+ if (ret < 0)
return -1;
- if (read_expect_type(EVENT_ITEM, &token) < 0)
- goto free;
-
- id = strtoul(token, NULL, 0);
-
- free:
- free_token(token);
- return id;
-}
-
-static int field_is_string(struct format_field *field)
-{
- if ((field->flags & FIELD_IS_ARRAY) &&
- (!strstr(field->type, "char") || !strstr(field->type, "u8") ||
- !strstr(field->type, "s8")))
- return 1;
-
- return 0;
-}
-
-static int field_is_dynamic(struct format_field *field)
-{
- if (!strncmp(field->type, "__data_loc", 10))
- return 1;
-
- return 0;
-}
-
-static int event_read_fields(struct event *event, struct format_field **fields)
-{
- struct format_field *field = NULL;
- enum event_type type;
- char *token;
- char *last_token;
- int count = 0;
-
- do {
- type = read_token(&token);
- if (type == EVENT_NEWLINE) {
- free_token(token);
- return count;
- }
-
- count++;
-
- if (test_type_token(type, token, EVENT_ITEM, "field"))
- goto fail;
- free_token(token);
-
- type = read_token(&token);
- /*
- * The ftrace fields may still use the "special" name.
- * Just ignore it.
- */
- if (event->flags & EVENT_FL_ISFTRACE &&
- type == EVENT_ITEM && strcmp(token, "special") == 0) {
- free_token(token);
- type = read_token(&token);
- }
-
- if (test_type_token(type, token, EVENT_OP, ":") < 0)
- return -1;
-
- if (read_expect_type(EVENT_ITEM, &token) < 0)
- goto fail;
-
- last_token = token;
-
- field = malloc_or_die(sizeof(*field));
- memset(field, 0, sizeof(*field));
-
- /* read the rest of the type */
- for (;;) {
- type = read_token(&token);
- if (type == EVENT_ITEM ||
- (type == EVENT_OP && strcmp(token, "*") == 0) ||
- /*
- * Some of the ftrace fields are broken and have
- * an illegal "." in them.
- */
- (event->flags & EVENT_FL_ISFTRACE &&
- type == EVENT_OP && strcmp(token, ".") == 0)) {
-
- if (strcmp(token, "*") == 0)
- field->flags |= FIELD_IS_POINTER;
-
- if (field->type) {
- field->type = realloc(field->type,
- strlen(field->type) +
- strlen(last_token) + 2);
- strcat(field->type, " ");
- strcat(field->type, last_token);
- } else
- field->type = last_token;
- last_token = token;
- continue;
- }
-
- break;
- }
-
- if (!field->type) {
- die("no type found");
- goto fail;
- }
- field->name = last_token;
-
- if (test_type(type, EVENT_OP))
- goto fail;
-
- if (strcmp(token, "[") == 0) {
- enum event_type last_type = type;
- char *brackets = token;
- int len;
-
- field->flags |= FIELD_IS_ARRAY;
-
- type = read_token(&token);
- while (strcmp(token, "]") != 0) {
- if (last_type == EVENT_ITEM &&
- type == EVENT_ITEM)
- len = 2;
- else
- len = 1;
- last_type = type;
-
- brackets = realloc(brackets,
- strlen(brackets) +
- strlen(token) + len);
- if (len == 2)
- strcat(brackets, " ");
- strcat(brackets, token);
- free_token(token);
- type = read_token(&token);
- if (type == EVENT_NONE) {
- die("failed to find token");
- goto fail;
- }
- }
-
- free_token(token);
-
- brackets = realloc(brackets, strlen(brackets) + 2);
- strcat(brackets, "]");
-
- /* add brackets to type */
-
- type = read_token(&token);
- /*
- * If the next token is not an OP, then it is of
- * the format: type [] item;
- */
- if (type == EVENT_ITEM) {
- field->type = realloc(field->type,
- strlen(field->type) +
- strlen(field->name) +
- strlen(brackets) + 2);
- strcat(field->type, " ");
- strcat(field->type, field->name);
- free_token(field->name);
- strcat(field->type, brackets);
- field->name = token;
- type = read_token(&token);
- } else {
- field->type = realloc(field->type,
- strlen(field->type) +
- strlen(brackets) + 1);
- strcat(field->type, brackets);
- }
- free(brackets);
- }
-
- if (field_is_string(field)) {
- field->flags |= FIELD_IS_STRING;
- if (field_is_dynamic(field))
- field->flags |= FIELD_IS_DYNAMIC;
- }
-
- if (test_type_token(type, token, EVENT_OP, ";"))
- goto fail;
- free_token(token);
-
- if (read_expected(EVENT_ITEM, "offset") < 0)
- goto fail_expect;
-
- if (read_expected(EVENT_OP, ":") < 0)
- goto fail_expect;
-
- if (read_expect_type(EVENT_ITEM, &token))
- goto fail;
- field->offset = strtoul(token, NULL, 0);
- free_token(token);
-
- if (read_expected(EVENT_OP, ";") < 0)
- goto fail_expect;
-
- if (read_expected(EVENT_ITEM, "size") < 0)
- goto fail_expect;
-
- if (read_expected(EVENT_OP, ":") < 0)
- goto fail_expect;
-
- if (read_expect_type(EVENT_ITEM, &token))
- goto fail;
- field->size = strtoul(token, NULL, 0);
- free_token(token);
-
- if (read_expected(EVENT_OP, ";") < 0)
- goto fail_expect;
-
- type = read_token(&token);
- if (type != EVENT_NEWLINE) {
- /* newer versions of the kernel have a "signed" type */
- if (test_type_token(type, token, EVENT_ITEM, "signed"))
- goto fail;
-
- free_token(token);
-
- if (read_expected(EVENT_OP, ":") < 0)
- goto fail_expect;
-
- if (read_expect_type(EVENT_ITEM, &token))
- goto fail;
-
- if (strtoul(token, NULL, 0))
- field->flags |= FIELD_IS_SIGNED;
-
- free_token(token);
- if (read_expected(EVENT_OP, ";") < 0)
- goto fail_expect;
-
- if (read_expect_type(EVENT_NEWLINE, &token))
- goto fail;
- }
-
- free_token(token);
-
- *fields = field;
- fields = &field->next;
-
- } while (1);
-
- return 0;
-
-fail:
- free_token(token);
-fail_expect:
- if (field)
- free(field);
- return -1;
+ return ret;
}
-static int event_read_format(struct event *event)
+int common_pc(struct scripting_context *context)
{
- char *token;
+ static int offset;
+ static int size;
int ret;
- if (read_expected_item(EVENT_ITEM, "format") < 0)
- return -1;
-
- if (read_expected(EVENT_OP, ":") < 0)
- return -1;
-
- if (read_expect_type(EVENT_NEWLINE, &token))
- goto fail;
- free_token(token);
-
- ret = event_read_fields(event, &event->format.common_fields);
+ ret = get_common_field(context, &size, &offset,
+ "common_preempt_count");
if (ret < 0)
- return ret;
- event->format.nr_common = ret;
-
- ret = event_read_fields(event, &event->format.fields);
- if (ret < 0)
- return ret;
- event->format.nr_fields = ret;
-
- return 0;
-
- fail:
- free_token(token);
- return -1;
-}
-
-enum event_type
-process_arg_token(struct event *event, struct print_arg *arg,
- char **tok, enum event_type type);
-
-static enum event_type
-process_arg(struct event *event, struct print_arg *arg, char **tok)
-{
- enum event_type type;
- char *token;
-
- type = read_token(&token);
- *tok = token;
+ return -1;
- return process_arg_token(event, arg, tok, type);
+ return ret;
}
-static enum event_type
-process_cond(struct event *event, struct print_arg *top, char **tok)
+unsigned long long
+raw_field_value(struct event_format *event, const char *name, void *data)
{
- struct print_arg *arg, *left, *right;
- enum event_type type;
- char *token = NULL;
-
- arg = malloc_or_die(sizeof(*arg));
- memset(arg, 0, sizeof(*arg));
-
- left = malloc_or_die(sizeof(*left));
-
- right = malloc_or_die(sizeof(*right));
-
- arg->type = PRINT_OP;
- arg->op.left = left;
- arg->op.right = right;
-
- *tok = NULL;
- type = process_arg(event, left, &token);
- if (test_type_token(type, token, EVENT_OP, ":"))
- goto out_free;
-
- arg->op.op = token;
-
- type = process_arg(event, right, &token);
+ struct format_field *field;
+ unsigned long long val;
- top->op.right = arg;
+ field = pevent_find_any_field(event, name);
+ if (!field)
+ return 0ULL;
- *tok = token;
- return type;
+ pevent_read_number_field(field, data, &val);
-out_free:
- free_token(*tok);
- free(right);
- free(left);
- free_arg(arg);
- return EVENT_ERROR;
+ return val;
}
-static enum event_type
-process_array(struct event *event, struct print_arg *top, char **tok)
+void *raw_field_ptr(struct event_format *event, const char *name, void *data)
{
- struct print_arg *arg;
- enum event_type type;
- char *token = NULL;
-
- arg = malloc_or_die(sizeof(*arg));
- memset(arg, 0, sizeof(*arg));
-
- *tok = NULL;
- type = process_arg(event, arg, &token);
- if (test_type_token(type, token, EVENT_OP, "]"))
- goto out_free;
-
- top->op.right = arg;
-
- free_token(token);
- type = read_token_item(&token);
- *tok = token;
-
- return type;
+ struct format_field *field;
-out_free:
- free_token(*tok);
- free_arg(arg);
- return EVENT_ERROR;
-}
+ field = pevent_find_any_field(event, name);
+ if (!field)
+ return NULL;
-static int get_op_prio(char *op)
-{
- if (!op[1]) {
- switch (op[0]) {
- case '*':
- case '/':
- case '%':
- return 6;
- case '+':
- case '-':
- return 7;
- /* '>>' and '<<' are 8 */
- case '<':
- case '>':
- return 9;
- /* '==' and '!=' are 10 */
- case '&':
- return 11;
- case '^':
- return 12;
- case '|':
- return 13;
- case '?':
- return 16;
- default:
- die("unknown op '%c'", op[0]);
- return -1;
- }
- } else {
- if (strcmp(op, "++") == 0 ||
- strcmp(op, "--") == 0) {
- return 3;
- } else if (strcmp(op, ">>") == 0 ||
- strcmp(op, "<<") == 0) {
- return 8;
- } else if (strcmp(op, ">=") == 0 ||
- strcmp(op, "<=") == 0) {
- return 9;
- } else if (strcmp(op, "==") == 0 ||
- strcmp(op, "!=") == 0) {
- return 10;
- } else if (strcmp(op, "&&") == 0) {
- return 14;
- } else if (strcmp(op, "||") == 0) {
- return 15;
- } else {
- die("unknown op '%s'", op);
- return -1;
- }
- }
-}
+ if (field->flags & FIELD_IS_DYNAMIC) {
+ int offset;
-static void set_op_prio(struct print_arg *arg)
-{
+ offset = *(int *)(data + field->offset);
+ offset &= 0xffff;
- /* single ops are the greatest */
- if (!arg->op.left || arg->op.left->type == PRINT_NULL) {
- arg->op.prio = 0;
- return;
+ return data + offset;
}
- arg->op.prio = get_op_prio(arg->op.op);
+ return data + field->offset;
}
-static enum event_type
-process_op(struct event *event, struct print_arg *arg, char **tok)
+int trace_parse_common_type(void *data)
{
- struct print_arg *left, *right = NULL;
- enum event_type type;
- char *token;
-
- /* the op is passed in via tok */
- token = *tok;
-
- if (arg->type == PRINT_OP && !arg->op.left) {
- /* handle single op */
- if (token[1]) {
- die("bad op token %s", token);
- return EVENT_ERROR;
- }
- switch (token[0]) {
- case '!':
- case '+':
- case '-':
- break;
- default:
- die("bad op token %s", token);
- return EVENT_ERROR;
- }
-
- /* make an empty left */
- left = malloc_or_die(sizeof(*left));
- left->type = PRINT_NULL;
- arg->op.left = left;
-
- right = malloc_or_die(sizeof(*right));
- arg->op.right = right;
-
- type = process_arg(event, right, tok);
-
- } else if (strcmp(token, "?") == 0) {
-
- left = malloc_or_die(sizeof(*left));
- /* copy the top arg to the left */
- *left = *arg;
-
- arg->type = PRINT_OP;
- arg->op.op = token;
- arg->op.left = left;
- arg->op.prio = 0;
-
- type = process_cond(event, arg, tok);
-
- } else if (strcmp(token, ">>") == 0 ||
- strcmp(token, "<<") == 0 ||
- strcmp(token, "&") == 0 ||
- strcmp(token, "|") == 0 ||
- strcmp(token, "&&") == 0 ||
- strcmp(token, "||") == 0 ||
- strcmp(token, "-") == 0 ||
- strcmp(token, "+") == 0 ||
- strcmp(token, "*") == 0 ||
- strcmp(token, "^") == 0 ||
- strcmp(token, "/") == 0 ||
- strcmp(token, "<") == 0 ||
- strcmp(token, ">") == 0 ||
- strcmp(token, "==") == 0 ||
- strcmp(token, "!=") == 0) {
-
- left = malloc_or_die(sizeof(*left));
-
- /* copy the top arg to the left */
- *left = *arg;
-
- arg->type = PRINT_OP;
- arg->op.op = token;
- arg->op.left = left;
-
- set_op_prio(arg);
-
- right = malloc_or_die(sizeof(*right));
-
- type = read_token_item(&token);
- *tok = token;
-
- /* could just be a type pointer */
- if ((strcmp(arg->op.op, "*") == 0) &&
- type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
- if (left->type != PRINT_ATOM)
- die("bad pointer type");
- left->atom.atom = realloc(left->atom.atom,
- sizeof(left->atom.atom) + 3);
- strcat(left->atom.atom, " *");
- *arg = *left;
- free(arg);
-
- return type;
- }
-
- type = process_arg_token(event, right, tok, type);
-
- arg->op.right = right;
-
- } else if (strcmp(token, "[") == 0) {
-
- left = malloc_or_die(sizeof(*left));
- *left = *arg;
-
- arg->type = PRINT_OP;
- arg->op.op = token;
- arg->op.left = left;
-
- arg->op.prio = 0;
- type = process_array(event, arg, tok);
-
- } else {
- warning("unknown op '%s'", token);
- event->flags |= EVENT_FL_FAILED;
- /* the arg is now the left side */
- return EVENT_NONE;
- }
-
- if (type == EVENT_OP) {
- int prio;
-
- /* higher prios need to be closer to the root */
- prio = get_op_prio(*tok);
-
- if (prio > arg->op.prio)
- return process_op(event, arg, tok);
+ struct pevent_record record;
- return process_op(event, right, tok);
- }
-
- return type;
+ record.data = data;
+ return pevent_data_type(pevent, &record);
}
-static enum event_type
-process_entry(struct event *event __unused, struct print_arg *arg,
- char **tok)
+int trace_parse_common_pid(void *data)
{
- enum event_type type;
- char *field;
- char *token;
-
- if (read_expected(EVENT_OP, "->") < 0)
- return EVENT_ERROR;
-
- if (read_expect_type(EVENT_ITEM, &token) < 0)
- goto fail;
- field = token;
-
- arg->type = PRINT_FIELD;
- arg->field.name = field;
-
- if (is_flag_field) {
- arg->field.field = find_any_field(event, arg->field.name);
- arg->field.field->flags |= FIELD_IS_FLAG;
- is_flag_field = 0;
- } else if (is_symbolic_field) {
- arg->field.field = find_any_field(event, arg->field.name);
- arg->field.field->flags |= FIELD_IS_SYMBOLIC;
- is_symbolic_field = 0;
- }
-
- type = read_token(&token);
- *tok = token;
+ struct pevent_record record;
- return type;
-
-fail:
- free_token(token);
- return EVENT_ERROR;
+ record.data = data;
+ return pevent_data_pid(pevent, &record);
}
-static char *arg_eval (struct print_arg *arg);
-
-static long long arg_num_eval(struct print_arg *arg)
+unsigned long long read_size(void *ptr, int size)
{
- long long left, right;
- long long val = 0;
-
- switch (arg->type) {
- case PRINT_ATOM:
- val = strtoll(arg->atom.atom, NULL, 0);
- break;
- case PRINT_TYPE:
- val = arg_num_eval(arg->typecast.item);
- break;
- case PRINT_OP:
- switch (arg->op.op[0]) {
- case '|':
- left = arg_num_eval(arg->op.left);
- right = arg_num_eval(arg->op.right);
- if (arg->op.op[1])
- val = left || right;
- else
- val = left | right;
- break;
- case '&':
- left = arg_num_eval(arg->op.left);
- right = arg_num_eval(arg->op.right);
- if (arg->op.op[1])
- val = left && right;
- else
- val = left & right;
- break;
- case '<':
- left = arg_num_eval(arg->op.left);
- right = arg_num_eval(arg->op.right);
- switch (arg->op.op[1]) {
- case 0:
- val = left < right;
- break;
- case '<':
- val = left << right;
- break;
- case '=':
- val = left <= right;
- break;
- default:
- die("unknown op '%s'", arg->op.op);
- }
- break;
- case '>':
- left = arg_num_eval(arg->op.left);
- right = arg_num_eval(arg->op.right);
- switch (arg->op.op[1]) {
- case 0:
- val = left > right;
- break;
- case '>':
- val = left >> right;
- break;
- case '=':
- val = left >= right;
- break;
- default:
- die("unknown op '%s'", arg->op.op);
- }
- break;
- case '=':
- left = arg_num_eval(arg->op.left);
- right = arg_num_eval(arg->op.right);
-
- if (arg->op.op[1] != '=')
- die("unknown op '%s'", arg->op.op);
-
- val = left == right;
- break;
- case '!':
- left = arg_num_eval(arg->op.left);
- right = arg_num_eval(arg->op.right);
-
- switch (arg->op.op[1]) {
- case '=':
- val = left != right;
- break;
- default:
- die("unknown op '%s'", arg->op.op);
- }
- break;
- case '+':
- left = arg_num_eval(arg->op.left);
- right = arg_num_eval(arg->op.right);
- val = left + right;
- break;
- default:
- die("unknown op '%s'", arg->op.op);
- }
- break;
-
- case PRINT_NULL:
- case PRINT_FIELD ... PRINT_SYMBOL:
- case PRINT_STRING:
- default:
- die("invalid eval type %d", arg->type);
-
- }
- return val;
+ return pevent_read_number(pevent, ptr, size);
}
-static char *arg_eval (struct print_arg *arg)
+struct event_format *trace_find_event(int type)
{
- long long val;
- static char buf[20];
-
- switch (arg->type) {
- case PRINT_ATOM:
- return arg->atom.atom;
- case PRINT_TYPE:
- return arg_eval(arg->typecast.item);
- case PRINT_OP:
- val = arg_num_eval(arg);
- sprintf(buf, "%lld", val);
- return buf;
-
- case PRINT_NULL:
- case PRINT_FIELD ... PRINT_SYMBOL:
- case PRINT_STRING:
- default:
- die("invalid eval type %d", arg->type);
- break;
- }
-
- return NULL;
+ return pevent_find_event(pevent, type);
}
-static enum event_type
-process_fields(struct event *event, struct print_flag_sym **list, char **tok)
-{
- enum event_type type;
- struct print_arg *arg = NULL;
- struct print_flag_sym *field;
- char *token = NULL;
- char *value;
-
- do {
- free_token(token);
- type = read_token_item(&token);
- if (test_type_token(type, token, EVENT_OP, "{"))
- break;
-
- arg = malloc_or_die(sizeof(*arg));
-
- free_token(token);
- type = process_arg(event, arg, &token);
-
- if (type == EVENT_OP)
- type = process_op(event, arg, &token);
-
- if (type == EVENT_ERROR)
- goto out_free;
-
- if (test_type_token(type, token, EVENT_DELIM, ","))
- goto out_free;
-
- field = malloc_or_die(sizeof(*field));
- memset(field, 0, sizeof(*field));
-
- value = arg_eval(arg);
- field->value = strdup(value);
-
- free_token(token);
- type = process_arg(event, arg, &token);
- if (test_type_token(type, token, EVENT_OP, "}"))
- goto out_free;
-
- value = arg_eval(arg);
- field->str = strdup(value);
- free_arg(arg);
- arg = NULL;
-
- *list = field;
- list = &field->next;
- free_token(token);
- type = read_token_item(&token);
- } while (type == EVENT_DELIM && strcmp(token, ",") == 0);
-
- *tok = token;
- return type;
-
-out_free:
- free_arg(arg);
- free_token(token);
-
- return EVENT_ERROR;
-}
-
-static enum event_type
-process_flags(struct event *event, struct print_arg *arg, char **tok)
+void print_trace_event(int cpu, void *data, int size)
{
- struct print_arg *field;
- enum event_type type;
- char *token;
-
- memset(arg, 0, sizeof(*arg));
- arg->type = PRINT_FLAGS;
-
- if (read_expected_item(EVENT_DELIM, "(") < 0)
- return EVENT_ERROR;
-
- field = malloc_or_die(sizeof(*field));
-
- type = process_arg(event, field, &token);
- while (type == EVENT_OP)
- type = process_op(event, field, &token);
- if (test_type_token(type, token, EVENT_DELIM, ","))
- goto out_free;
+ struct event_format *event;
+ struct pevent_record record;
+ struct trace_seq s;
+ int type;
- arg->flags.field = field;
+ type = trace_parse_common_type(data);
- type = read_token_item(&token);
- if (event_item_type(type)) {
- arg->flags.delim = token;
- type = read_token_item(&token);
+ event = trace_find_event(type);
+ if (!event) {
+ warning("ug! no event found for type %d", type);
+ return;
}
- if (test_type_token(type, token, EVENT_DELIM, ","))
- goto out_free;
-
- type = process_fields(event, &arg->flags.flags, &token);
- if (test_type_token(type, token, EVENT_DELIM, ")"))
- goto out_free;
+ memset(&record, 0, sizeof(record));
+ record.cpu = cpu;
+ record.size = size;
+ record.data = data;
- free_token(token);
- type = read_token_item(tok);
- return type;
-
-out_free:
- free_token(token);
- return EVENT_ERROR;
+ trace_seq_init(&s);
+ pevent_print_event(pevent, &s, &record);
+ trace_seq_do_printf(&s);
+ printf("\n");
}
-static enum event_type
-process_symbols(struct event *event, struct print_arg *arg, char **tok)
+void print_event(int cpu, void *data, int size, unsigned long long nsecs,
+ char *comm)
{
- struct print_arg *field;
- enum event_type type;
- char *token;
-
- memset(arg, 0, sizeof(*arg));
- arg->type = PRINT_SYMBOL;
-
- if (read_expected_item(EVENT_DELIM, "(") < 0)
- return EVENT_ERROR;
-
- field = malloc_or_die(sizeof(*field));
-
- type = process_arg(event, field, &token);
- if (test_type_token(type, token, EVENT_DELIM, ","))
- goto out_free;
+ struct pevent_record record;
+ struct trace_seq s;
+ int pid;
- arg->symbol.field = field;
+ pevent->latency_format = latency_format;
- type = process_fields(event, &arg->symbol.symbols, &token);
- if (test_type_token(type, token, EVENT_DELIM, ")"))
- goto out_free;
+ record.ts = nsecs;
+ record.cpu = cpu;
+ record.size = size;
+ record.data = data;
+ pid = pevent_data_pid(pevent, &record);
- free_token(token);
- type = read_token_item(tok);
- return type;
+ if (!pevent_pid_is_registered(pevent, pid))
+ pevent_register_comm(pevent, comm, pid);
-out_free:
- free_token(token);
- return EVENT_ERROR;
+ trace_seq_init(&s);
+ pevent_print_event(pevent, &s, &record);
+ trace_seq_do_printf(&s);
+ printf("\n");
}
-static enum event_type
-process_paren(struct event *event, struct print_arg *arg, char **tok)
+void parse_proc_kallsyms(char *file, unsigned int size __unused)
{
- struct print_arg *item_arg;
- enum event_type type;
- char *token;
-
- type = process_arg(event, arg, &token);
-
- if (type == EVENT_ERROR)
- return EVENT_ERROR;
-
- if (type == EVENT_OP)
- type = process_op(event, arg, &token);
-
- if (type == EVENT_ERROR)
- return EVENT_ERROR;
-
- if (test_type_token(type, token, EVENT_DELIM, ")")) {
- free_token(token);
- return EVENT_ERROR;
- }
-
- free_token(token);
- type = read_token_item(&token);
-
- /*
- * If the next token is an item or another open paren, then
- * this was a typecast.
- */
- if (event_item_type(type) ||
- (type == EVENT_DELIM && strcmp(token, "(") == 0)) {
-
- /* make this a typecast and contine */
+ unsigned long long addr;
+ char *func;
+ char *line;
+ char *next = NULL;
+ char *addr_str;
+ char *mod;
+ char ch;
- /* prevous must be an atom */
- if (arg->type != PRINT_ATOM)
- die("previous needed to be PRINT_ATOM");
+ line = strtok_r(file, "\n", &next);
+ while (line) {
+ mod = NULL;
+ sscanf(line, "%as %c %as\t[%as",
+ (float *)(void *)&addr_str, /* workaround gcc warning */
+ &ch, (float *)(void *)&func, (float *)(void *)&mod);
+ addr = strtoull(addr_str, NULL, 16);
+ free(addr_str);
- item_arg = malloc_or_die(sizeof(*item_arg));
+ /* truncate the extra ']' */
+ if (mod)
+ mod[strlen(mod) - 1] = 0;
- arg->type = PRINT_TYPE;
- arg->typecast.type = arg->atom.atom;
- arg->typecast.item = item_arg;
- type = process_arg_token(event, item_arg, &token, type);
+ pevent_register_function(pevent, func, addr, mod);
+ free(func);
+ free(mod);
+ line = strtok_r(NULL, "\n", &next);
}
-
- *tok = token;
- return type;
}
-
-static enum event_type
-process_str(struct event *event __unused, struct print_arg *arg, char **tok)
+void parse_ftrace_printk(char *file, unsigned int size __unused)
{
- enum event_type type;
- char *token;
-
- if (read_expected(EVENT_DELIM, "(") < 0)
- return EVENT_ERROR;
-
- if (read_expect_type(EVENT_ITEM, &token) < 0)
- goto fail;
-
- arg->type = PRINT_STRING;
- arg->string.string = token;
- arg->string.offset = -1;
-
- if (read_expected(EVENT_DELIM, ")") < 0)
- return EVENT_ERROR;
-
- type = read_token(&token);
- *tok = token;
-
- return type;
-fail:
- free_token(token);
- return EVENT_ERROR;
-}
+ unsigned long long addr;
+ char *printk;
+ char *line;
+ char *next = NULL;
+ char *addr_str;
+ char *fmt;
-enum event_type
-process_arg_token(struct event *event, struct print_arg *arg,
- char **tok, enum event_type type)
-{
- char *token;
- char *atom;
-
- token = *tok;
-
- switch (type) {
- case EVENT_ITEM:
- if (strcmp(token, "REC") == 0) {
- free_token(token);
- type = process_entry(event, arg, &token);
- } else if (strcmp(token, "__print_flags") == 0) {
- free_token(token);
- is_flag_field = 1;
- type = process_flags(event, arg, &token);
- } else if (strcmp(token, "__print_symbolic") == 0) {
- free_token(token);
- is_symbolic_field = 1;
- type = process_symbols(event, arg, &token);
- } else if (strcmp(token, "__get_str") == 0) {
- free_token(token);
- type = process_str(event, arg, &token);
- } else {
- atom = token;
- /* test the next token */
- type = read_token_item(&token);
-
- /* atoms can be more than one token long */
- while (type == EVENT_ITEM) {
- atom = realloc(atom, strlen(atom) + strlen(token) + 2);
- strcat(atom, " ");
- strcat(atom, token);
- free_token(token);
- type = read_token_item(&token);
- }
-
- /* todo, test for function */
-
- arg->type = PRINT_ATOM;
- arg->atom.atom = atom;
- }
- break;
- case EVENT_DQUOTE:
- case EVENT_SQUOTE:
- arg->type = PRINT_ATOM;
- arg->atom.atom = token;
- type = read_token_item(&token);
- break;
- case EVENT_DELIM:
- if (strcmp(token, "(") == 0) {
- free_token(token);
- type = process_paren(event, arg, &token);
+ line = strtok_r(file, "\n", &next);
+ while (line) {
+ addr_str = strtok_r(line, ":", &fmt);
+ if (!addr_str) {
+ warning("printk format with empty entry");
break;
}
- case EVENT_OP:
- /* handle single ops */
- arg->type = PRINT_OP;
- arg->op.op = token;
- arg->op.left = NULL;
- type = process_op(event, arg, &token);
-
- break;
-
- case EVENT_ERROR ... EVENT_NEWLINE:
- default:
- die("unexpected type %d", type);
- }
- *tok = token;
-
- return type;
-}
-
-static int event_read_print_args(struct event *event, struct print_arg **list)
-{
- enum event_type type = EVENT_ERROR;
- struct print_arg *arg;
- char *token;
- int args = 0;
-
- do {
- if (type == EVENT_NEWLINE) {
- free_token(token);
- type = read_token_item(&token);
- continue;
- }
-
- arg = malloc_or_die(sizeof(*arg));
- memset(arg, 0, sizeof(*arg));
-
- type = process_arg(event, arg, &token);
-
- if (type == EVENT_ERROR) {
- free_arg(arg);
- return -1;
- }
-
- *list = arg;
- args++;
-
- if (type == EVENT_OP) {
- type = process_op(event, arg, &token);
- list = &arg->next;
- continue;
- }
-
- if (type == EVENT_DELIM && strcmp(token, ",") == 0) {
- free_token(token);
- *list = arg;
- list = &arg->next;
- continue;
- }
- break;
- } while (type != EVENT_NONE);
-
- if (type != EVENT_NONE)
- free_token(token);
-
- return args;
-}
-
-static int event_read_print(struct event *event)
-{
- enum event_type type;
- char *token;
- int ret;
-
- if (read_expected_item(EVENT_ITEM, "print") < 0)
- return -1;
-
- if (read_expected(EVENT_ITEM, "fmt") < 0)
- return -1;
-
- if (read_expected(EVENT_OP, ":") < 0)
- return -1;
-
- if (read_expect_type(EVENT_DQUOTE, &token) < 0)
- goto fail;
-
- concat:
- event->print_fmt.format = token;
- event->print_fmt.args = NULL;
-
- /* ok to have no arg */
- type = read_token_item(&token);
-
- if (type == EVENT_NONE)
- return 0;
-
- /* Handle concatination of print lines */
- if (type == EVENT_DQUOTE) {
- char *cat;
-
- cat = malloc_or_die(strlen(event->print_fmt.format) +
- strlen(token) + 1);
- strcpy(cat, event->print_fmt.format);
- strcat(cat, token);
- free_token(token);
- free_token(event->print_fmt.format);
- event->print_fmt.format = NULL;
- token = cat;
- goto concat;
- }
-
- if (test_type_token(type, token, EVENT_DELIM, ","))
- goto fail;
-
- free_token(token);
-
- ret = event_read_print_args(event, &event->print_fmt.args);
- if (ret < 0)
- return -1;
-
- return ret;
-
- fail:
- free_token(token);
- return -1;
-}
-
-static struct format_field *
-find_common_field(struct event *event, const char *name)
-{
- struct format_field *format;
-
- for (format = event->format.common_fields;
- format; format = format->next) {
- if (strcmp(format->name, name) == 0)
- break;
- }
-
- return format;
-}
-
-static struct format_field *
-find_field(struct event *event, const char *name)
-{
- struct format_field *format;
-
- for (format = event->format.fields;
- format; format = format->next) {
- if (strcmp(format->name, name) == 0)
- break;
+ addr = strtoull(addr_str, NULL, 16);
+ /* fmt still has a space, skip it */
+ printk = strdup(fmt+1);
+ line = strtok_r(NULL, "\n", &next);
+ pevent_register_print_string(pevent, printk, addr);
}
-
- return format;
}
-static struct format_field *
-find_any_field(struct event *event, const char *name)
+int parse_ftrace_file(char *buf, unsigned long size)
{
- struct format_field *format;
-
- format = find_common_field(event, name);
- if (format)
- return format;
- return find_field(event, name);
+ return pevent_parse_event(pevent, buf, size, "ftrace");
}
-unsigned long long read_size(void *ptr, int size)
+int parse_event_file(char *buf, unsigned long size, char *sys)
{
- switch (size) {
- case 1:
- return *(unsigned char *)ptr;
- case 2:
- return data2host2(ptr);
- case 4:
- return data2host4(ptr);
- case 8:
- return data2host8(ptr);
- default:
- /* BUG! */
- return 0;
- }
+ return pevent_parse_event(pevent, buf, size, sys);
}
-unsigned long long
-raw_field_value(struct event *event, const char *name, void *data)
+struct event_format *trace_find_next_event(struct event_format *event)
{
- struct format_field *field;
-
- field = find_any_field(event, name);
- if (!field)
- return 0ULL;
+ static int idx;
- return read_size(data + field->offset, field->size);
-}
-
-void *raw_field_ptr(struct event *event, const char *name, void *data)
-{
- struct format_field *field;
-
- field = find_any_field(event, name);
- if (!field)
+ if (!pevent->events)
return NULL;
- if (field->flags & FIELD_IS_DYNAMIC) {
- int offset;
-
- offset = *(int *)(data + field->offset);
- offset &= 0xffff;
-
- return data + offset;
- }
-
- return data + field->offset;
-}
-
-static int get_common_info(const char *type, int *offset, int *size)
-{
- struct event *event;
- struct format_field *field;
-
- /*
- * All events should have the same common elements.
- * Pick any event to find where the type is;
- */
- if (!event_list)
- die("no event_list!");
-
- event = event_list;
- field = find_common_field(event, type);
- if (!field)
- die("field '%s' not found", type);
-
- *offset = field->offset;
- *size = field->size;
-
- return 0;
-}
-
-static int __parse_common(void *data, int *size, int *offset,
- const char *name)
-{
- int ret;
-
- if (!*size) {
- ret = get_common_info(name, offset, size);
- if (ret < 0)
- return ret;
+ if (!event) {
+ idx = 0;
+ return pevent->events[0];
}
- return read_size(data + *offset, *size);
-}
-
-int trace_parse_common_type(void *data)
-{
- static int type_offset;
- static int type_size;
-
- return __parse_common(data, &type_size, &type_offset,
- "common_type");
-}
-
-int trace_parse_common_pid(void *data)
-{
- static int pid_offset;
- static int pid_size;
-
- return __parse_common(data, &pid_size, &pid_offset,
- "common_pid");
-}
-
-int parse_common_pc(void *data)
-{
- static int pc_offset;
- static int pc_size;
-
- return __parse_common(data, &pc_size, &pc_offset,
- "common_preempt_count");
-}
-
-int parse_common_flags(void *data)
-{
- static int flags_offset;
- static int flags_size;
-
- return __parse_common(data, &flags_size, &flags_offset,
- "common_flags");
-}
-
-int parse_common_lock_depth(void *data)
-{
- static int ld_offset;
- static int ld_size;
- int ret;
- ret = __parse_common(data, &ld_size, &ld_offset,
- "common_lock_depth");
- if (ret < 0)
- return -1;
-
- return ret;
-}
-
-struct event *trace_find_event(int id)
-{
- struct event *event;
-
- for (event = event_list; event; event = event->next) {
- if (event->id == id)
- break;
+ if (idx < pevent->nr_events && event == pevent->events[idx]) {
+ idx++;
+ if (idx == pevent->nr_events)
+ return NULL;
+ return pevent->events[idx];
}
- return event;
-}
-
-struct event *trace_find_next_event(struct event *event)
-{
- if (!event)
- return event_list;
-
- return event->next;
-}
-
-static unsigned long long eval_num_arg(void *data, int size,
- struct event *event, struct print_arg *arg)
-{
- unsigned long long val = 0;
- unsigned long long left, right;
- struct print_arg *larg;
- switch (arg->type) {
- case PRINT_NULL:
- /* ?? */
- return 0;
- case PRINT_ATOM:
- return strtoull(arg->atom.atom, NULL, 0);
- case PRINT_FIELD:
- if (!arg->field.field) {
- arg->field.field = find_any_field(event, arg->field.name);
- if (!arg->field.field)
- die("field %s not found", arg->field.name);
- }
- /* must be a number */
- val = read_size(data + arg->field.field->offset,
- arg->field.field->size);
- break;
- case PRINT_FLAGS:
- case PRINT_SYMBOL:
- break;
- case PRINT_TYPE:
- return eval_num_arg(data, size, event, arg->typecast.item);
- case PRINT_STRING:
- return 0;
- break;
- case PRINT_OP:
- if (strcmp(arg->op.op, "[") == 0) {
- /*
- * Arrays are special, since we don't want
- * to read the arg as is.
- */
- if (arg->op.left->type != PRINT_FIELD)
- goto default_op; /* oops, all bets off */
- larg = arg->op.left;
- if (!larg->field.field) {
- larg->field.field =
- find_any_field(event, larg->field.name);
- if (!larg->field.field)
- die("field %s not found", larg->field.name);
- }
- right = eval_num_arg(data, size, event, arg->op.right);
- val = read_size(data + larg->field.field->offset +
- right * long_size, long_size);
- break;
- }
- default_op:
- left = eval_num_arg(data, size, event, arg->op.left);
- right = eval_num_arg(data, size, event, arg->op.right);
- switch (arg->op.op[0]) {
- case '|':
- if (arg->op.op[1])
- val = left || right;
- else
- val = left | right;
- break;
- case '&':
- if (arg->op.op[1])
- val = left && right;
- else
- val = left & right;
- break;
- case '<':
- switch (arg->op.op[1]) {
- case 0:
- val = left < right;
- break;
- case '<':
- val = left << right;
- break;
- case '=':
- val = left <= right;
- break;
- default:
- die("unknown op '%s'", arg->op.op);
- }
- break;
- case '>':
- switch (arg->op.op[1]) {
- case 0:
- val = left > right;
- break;
- case '>':
- val = left >> right;
- break;
- case '=':
- val = left >= right;
- break;
- default:
- die("unknown op '%s'", arg->op.op);
- }
- break;
- case '=':
- if (arg->op.op[1] != '=')
- die("unknown op '%s'", arg->op.op);
- val = left == right;
- break;
- case '-':
- val = left - right;
- break;
- case '+':
- val = left + right;
- break;
- default:
- die("unknown op '%s'", arg->op.op);
- }
- break;
- default: /* not sure what to do there */
- return 0;
+ for (idx = 1; idx < pevent->nr_events; idx++) {
+ if (event == pevent->events[idx - 1])
+ return pevent->events[idx];
}
- return val;
+ return NULL;
}
struct flag {
@@ -2221,933 +357,3 @@ unsigned long long eval_flag(const char *flag)
return 0;
}
-
-static void print_str_arg(void *data, int size,
- struct event *event, struct print_arg *arg)
-{
- struct print_flag_sym *flag;
- unsigned long long val, fval;
- char *str;
- int print;
-
- switch (arg->type) {
- case PRINT_NULL:
- /* ?? */
- return;
- case PRINT_ATOM:
- printf("%s", arg->atom.atom);
- return;
- case PRINT_FIELD:
- if (!arg->field.field) {
- arg->field.field = find_any_field(event, arg->field.name);
- if (!arg->field.field)
- die("field %s not found", arg->field.name);
- }
- str = malloc_or_die(arg->field.field->size + 1);
- memcpy(str, data + arg->field.field->offset,
- arg->field.field->size);
- str[arg->field.field->size] = 0;
- printf("%s", str);
- free(str);
- break;
- case PRINT_FLAGS:
- val = eval_num_arg(data, size, event, arg->flags.field);
- print = 0;
- for (flag = arg->flags.flags; flag; flag = flag->next) {
- fval = eval_flag(flag->value);
- if (!val && !fval) {
- printf("%s", flag->str);
- break;
- }
- if (fval && (val & fval) == fval) {
- if (print && arg->flags.delim)
- printf("%s", arg->flags.delim);
- printf("%s", flag->str);
- print = 1;
- val &= ~fval;
- }
- }
- break;
- case PRINT_SYMBOL:
- val = eval_num_arg(data, size, event, arg->symbol.field);
- for (flag = arg->symbol.symbols; flag; flag = flag->next) {
- fval = eval_flag(flag->value);
- if (val == fval) {
- printf("%s", flag->str);
- break;
- }
- }
- break;
-
- case PRINT_TYPE:
- break;
- case PRINT_STRING: {
- int str_offset;
-
- if (arg->string.offset == -1) {
- struct format_field *f;
-
- f = find_any_field(event, arg->string.string);
- arg->string.offset = f->offset;
- }
- str_offset = *(int *)(data + arg->string.offset);
- str_offset &= 0xffff;
- printf("%s", ((char *)data) + str_offset);
- break;
- }
- case PRINT_OP:
- /*
- * The only op for string should be ? :
- */
- if (arg->op.op[0] != '?')
- return;
- val = eval_num_arg(data, size, event, arg->op.left);
- if (val)
- print_str_arg(data, size, event, arg->op.right->op.left);
- else
- print_str_arg(data, size, event, arg->op.right->op.right);
- break;
- default:
- /* well... */
- break;
- }
-}
-
-static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event *event)
-{
- static struct format_field *field, *ip_field;
- struct print_arg *args, *arg, **next;
- unsigned long long ip, val;
- char *ptr;
- void *bptr;
-
- if (!field) {
- field = find_field(event, "buf");
- if (!field)
- die("can't find buffer field for binary printk");
- ip_field = find_field(event, "ip");
- if (!ip_field)
- die("can't find ip field for binary printk");
- }
-
- ip = read_size(data + ip_field->offset, ip_field->size);
-
- /*
- * The first arg is the IP pointer.
- */
- args = malloc_or_die(sizeof(*args));
- arg = args;
- arg->next = NULL;
- next = &arg->next;
-
- arg->type = PRINT_ATOM;
- arg->atom.atom = malloc_or_die(32);
- sprintf(arg->atom.atom, "%lld", ip);
-
- /* skip the first "%pf : " */
- for (ptr = fmt + 6, bptr = data + field->offset;
- bptr < data + size && *ptr; ptr++) {
- int ls = 0;
-
- if (*ptr == '%') {
- process_again:
- ptr++;
- switch (*ptr) {
- case '%':
- break;
- case 'l':
- ls++;
- goto process_again;
- case 'L':
- ls = 2;
- goto process_again;
- case '0' ... '9':
- goto process_again;
- case 'p':
- ls = 1;
- /* fall through */
- case 'd':
- case 'u':
- case 'x':
- case 'i':
- /* the pointers are always 4 bytes aligned */
- bptr = (void *)(((unsigned long)bptr + 3) &
- ~3);
- switch (ls) {
- case 0:
- case 1:
- ls = long_size;
- break;
- case 2:
- ls = 8;
- default:
- break;
- }
- val = read_size(bptr, ls);
- bptr += ls;
- arg = malloc_or_die(sizeof(*arg));
- arg->next = NULL;
- arg->type = PRINT_ATOM;
- arg->atom.atom = malloc_or_die(32);
- sprintf(arg->atom.atom, "%lld", val);
- *next = arg;
- next = &arg->next;
- break;
- case 's':
- arg = malloc_or_die(sizeof(*arg));
- arg->next = NULL;
- arg->type = PRINT_STRING;
- arg->string.string = strdup(bptr);
- bptr += strlen(bptr) + 1;
- *next = arg;
- next = &arg->next;
- default:
- break;
- }
- }
- }
-
- return args;
-}
-
-static void free_args(struct print_arg *args)
-{
- struct print_arg *next;
-
- while (args) {
- next = args->next;
-
- if (args->type == PRINT_ATOM)
- free(args->atom.atom);
- else
- free(args->string.string);
- free(args);
- args = next;
- }
-}
-
-static char *get_bprint_format(void *data, int size __unused, struct event *event)
-{
- unsigned long long addr;
- static struct format_field *field;
- struct printk_map *printk;
- char *format;
- char *p;
-
- if (!field) {
- field = find_field(event, "fmt");
- if (!field)
- die("can't find format field for binary printk");
- printf("field->offset = %d size=%d\n", field->offset, field->size);
- }
-
- addr = read_size(data + field->offset, field->size);
-
- printk = find_printk(addr);
- if (!printk) {
- format = malloc_or_die(45);
- sprintf(format, "%%pf : (NO FORMAT FOUND at %llx)\n",
- addr);
- return format;
- }
-
- p = printk->printk;
- /* Remove any quotes. */
- if (*p == '"')
- p++;
- format = malloc_or_die(strlen(p) + 10);
- sprintf(format, "%s : %s", "%pf", p);
- /* remove ending quotes and new line since we will add one too */
- p = format + strlen(format) - 1;
- if (*p == '"')
- *p = 0;
-
- p -= 2;
- if (strcmp(p, "\\n") == 0)
- *p = 0;
-
- return format;
-}
-
-static void pretty_print(void *data, int size, struct event *event)
-{
- struct print_fmt *print_fmt = &event->print_fmt;
- struct print_arg *arg = print_fmt->args;
- struct print_arg *args = NULL;
- const char *ptr = print_fmt->format;
- unsigned long long val;
- struct func_map *func;
- const char *saveptr;
- char *bprint_fmt = NULL;
- char format[32];
- int show_func;
- int len;
- int ls;
-
- if (event->flags & EVENT_FL_ISFUNC)
- ptr = " %pF <-- %pF";
-
- if (event->flags & EVENT_FL_ISBPRINT) {
- bprint_fmt = get_bprint_format(data, size, event);
- args = make_bprint_args(bprint_fmt, data, size, event);
- arg = args;
- ptr = bprint_fmt;
- }
-
- for (; *ptr; ptr++) {
- ls = 0;
- if (*ptr == '\\') {
- ptr++;
- switch (*ptr) {
- case 'n':
- printf("\n");
- break;
- case 't':
- printf("\t");
- break;
- case 'r':
- printf("\r");
- break;
- case '\\':
- printf("\\");
- break;
- default:
- printf("%c", *ptr);
- break;
- }
-
- } else if (*ptr == '%') {
- saveptr = ptr;
- show_func = 0;
- cont_process:
- ptr++;
- switch (*ptr) {
- case '%':
- printf("%%");
- break;
- case 'l':
- ls++;
- goto cont_process;
- case 'L':
- ls = 2;
- goto cont_process;
- case 'z':
- case 'Z':
- case '0' ... '9':
- goto cont_process;
- case 'p':
- if (long_size == 4)
- ls = 1;
- else
- ls = 2;
-
- if (*(ptr+1) == 'F' ||
- *(ptr+1) == 'f') {
- ptr++;
- show_func = *ptr;
- }
-
- /* fall through */
- case 'd':
- case 'i':
- case 'x':
- case 'X':
- case 'u':
- if (!arg)
- die("no argument match");
-
- len = ((unsigned long)ptr + 1) -
- (unsigned long)saveptr;
-
- /* should never happen */
- if (len > 32)
- die("bad format!");
-
- memcpy(format, saveptr, len);
- format[len] = 0;
-
- val = eval_num_arg(data, size, event, arg);
- arg = arg->next;
-
- if (show_func) {
- func = find_func(val);
- if (func) {
- printf("%s", func->func);
- if (show_func == 'F')
- printf("+0x%llx",
- val - func->addr);
- break;
- }
- }
- switch (ls) {
- case 0:
- printf(format, (int)val);
- break;
- case 1:
- printf(format, (long)val);
- break;
- case 2:
- printf(format, (long long)val);
- break;
- default:
- die("bad count (%d)", ls);
- }
- break;
- case 's':
- if (!arg)
- die("no matching argument");
-
- print_str_arg(data, size, event, arg);
- arg = arg->next;
- break;
- default:
- printf(">%c<", *ptr);
-
- }
- } else
- printf("%c", *ptr);
- }
-
- if (args) {
- free_args(args);
- free(bprint_fmt);
- }
-}
-
-static inline int log10_cpu(int nb)
-{
- if (nb / 100)
- return 3;
- if (nb / 10)
- return 2;
- return 1;
-}
-
-static void print_lat_fmt(void *data, int size __unused)
-{
- unsigned int lat_flags;
- unsigned int pc;
- int lock_depth;
- int hardirq;
- int softirq;
-
- lat_flags = parse_common_flags(data);
- pc = parse_common_pc(data);
- lock_depth = parse_common_lock_depth(data);
-
- hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
- softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
-
- printf("%c%c%c",
- (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
- (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
- 'X' : '.',
- (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
- 'N' : '.',
- (hardirq && softirq) ? 'H' :
- hardirq ? 'h' : softirq ? 's' : '.');
-
- if (pc)
- printf("%x", pc);
- else
- printf(".");
-
- if (lock_depth < 0)
- printf(". ");
- else
- printf("%d ", lock_depth);
-}
-
-#define TRACE_GRAPH_INDENT 2
-
-static struct record *
-get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func,
- struct record *next)
-{
- struct format_field *field;
- struct event *event;
- unsigned long val;
- int type;
- int pid;
-
- type = trace_parse_common_type(next->data);
- event = trace_find_event(type);
- if (!event)
- return NULL;
-
- if (!(event->flags & EVENT_FL_ISFUNCRET))
- return NULL;
-
- pid = trace_parse_common_pid(next->data);
- field = find_field(event, "func");
- if (!field)
- die("function return does not have field func");
-
- val = read_size(next->data + field->offset, field->size);
-
- if (cur_pid != pid || cur_func != val)
- return NULL;
-
- /* this is a leaf, now advance the iterator */
- return trace_read_data(cpu);
-}
-
-/* Signal a overhead of time execution to the output */
-static void print_graph_overhead(unsigned long long duration)
-{
- /* Non nested entry or return */
- if (duration == ~0ULL)
- return (void)printf(" ");
-
- /* Duration exceeded 100 msecs */
- if (duration > 100000ULL)
- return (void)printf("! ");
-
- /* Duration exceeded 10 msecs */
- if (duration > 10000ULL)
- return (void)printf("+ ");
-
- printf(" ");
-}
-
-static void print_graph_duration(unsigned long long duration)
-{
- unsigned long usecs = duration / 1000;
- unsigned long nsecs_rem = duration % 1000;
- /* log10(ULONG_MAX) + '\0' */
- char msecs_str[21];
- char nsecs_str[5];
- int len;
- int i;
-
- sprintf(msecs_str, "%lu", usecs);
-
- /* Print msecs */
- len = printf("%lu", usecs);
-
- /* Print nsecs (we don't want to exceed 7 numbers) */
- if (len < 7) {
- snprintf(nsecs_str, 8 - len, "%03lu", nsecs_rem);
- len += printf(".%s", nsecs_str);
- }
-
- printf(" us ");
-
- /* Print remaining spaces to fit the row's width */
- for (i = len; i < 7; i++)
- printf(" ");
-
- printf("| ");
-}
-
-static void
-print_graph_entry_leaf(struct event *event, void *data, struct record *ret_rec)
-{
- unsigned long long rettime, calltime;
- unsigned long long duration, depth;
- unsigned long long val;
- struct format_field *field;
- struct func_map *func;
- struct event *ret_event;
- int type;
- int i;
-
- type = trace_parse_common_type(ret_rec->data);
- ret_event = trace_find_event(type);
-
- field = find_field(ret_event, "rettime");
- if (!field)
- die("can't find rettime in return graph");
- rettime = read_size(ret_rec->data + field->offset, field->size);
-
- field = find_field(ret_event, "calltime");
- if (!field)
- die("can't find rettime in return graph");
- calltime = read_size(ret_rec->data + field->offset, field->size);
-
- duration = rettime - calltime;
-
- /* Overhead */
- print_graph_overhead(duration);
-
- /* Duration */
- print_graph_duration(duration);
-
- field = find_field(event, "depth");
- if (!field)
- die("can't find depth in entry graph");
- depth = read_size(data + field->offset, field->size);
-
- /* Function */
- for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
- printf(" ");
-
- field = find_field(event, "func");
- if (!field)
- die("can't find func in entry graph");
- val = read_size(data + field->offset, field->size);
- func = find_func(val);
-
- if (func)
- printf("%s();", func->func);
- else
- printf("%llx();", val);
-}
-
-static void print_graph_nested(struct event *event, void *data)
-{
- struct format_field *field;
- unsigned long long depth;
- unsigned long long val;
- struct func_map *func;
- int i;
-
- /* No overhead */
- print_graph_overhead(-1);
-
- /* No time */
- printf(" | ");
-
- field = find_field(event, "depth");
- if (!field)
- die("can't find depth in entry graph");
- depth = read_size(data + field->offset, field->size);
-
- /* Function */
- for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
- printf(" ");
-
- field = find_field(event, "func");
- if (!field)
- die("can't find func in entry graph");
- val = read_size(data + field->offset, field->size);
- func = find_func(val);
-
- if (func)
- printf("%s() {", func->func);
- else
- printf("%llx() {", val);
-}
-
-static void
-pretty_print_func_ent(void *data, int size, struct event *event,
- int cpu, int pid)
-{
- struct format_field *field;
- struct record *rec;
- void *copy_data;
- unsigned long val;
-
- if (latency_format) {
- print_lat_fmt(data, size);
- printf(" | ");
- }
-
- field = find_field(event, "func");
- if (!field)
- die("function entry does not have func field");
-
- val = read_size(data + field->offset, field->size);
-
- /*
- * peek_data may unmap the data pointer. Copy it first.
- */
- copy_data = malloc_or_die(size);
- memcpy(copy_data, data, size);
- data = copy_data;
-
- rec = trace_peek_data(cpu);
- if (rec) {
- rec = get_return_for_leaf(cpu, pid, val, rec);
- if (rec) {
- print_graph_entry_leaf(event, data, rec);
- goto out_free;
- }
- }
- print_graph_nested(event, data);
-out_free:
- free(data);
-}
-
-static void
-pretty_print_func_ret(void *data, int size __unused, struct event *event)
-{
- unsigned long long rettime, calltime;
- unsigned long long duration, depth;
- struct format_field *field;
- int i;
-
- if (latency_format) {
- print_lat_fmt(data, size);
- printf(" | ");
- }
-
- field = find_field(event, "rettime");
- if (!field)
- die("can't find rettime in return graph");
- rettime = read_size(data + field->offset, field->size);
-
- field = find_field(event, "calltime");
- if (!field)
- die("can't find calltime in return graph");
- calltime = read_size(data + field->offset, field->size);
-
- duration = rettime - calltime;
-
- /* Overhead */
- print_graph_overhead(duration);
-
- /* Duration */
- print_graph_duration(duration);
-
- field = find_field(event, "depth");
- if (!field)
- die("can't find depth in entry graph");
- depth = read_size(data + field->offset, field->size);
-
- /* Function */
- for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
- printf(" ");
-
- printf("}");
-}
-
-static void
-pretty_print_func_graph(void *data, int size, struct event *event,
- int cpu, int pid)
-{
- if (event->flags & EVENT_FL_ISFUNCENT)
- pretty_print_func_ent(data, size, event, cpu, pid);
- else if (event->flags & EVENT_FL_ISFUNCRET)
- pretty_print_func_ret(data, size, event);
- printf("\n");
-}
-
-void print_trace_event(int cpu, void *data, int size)
-{
- struct event *event;
- int type;
- int pid;
-
- type = trace_parse_common_type(data);
-
- event = trace_find_event(type);
- if (!event) {
- warning("ug! no event found for type %d", type);
- return;
- }
-
- pid = trace_parse_common_pid(data);
-
- if (event->flags & (EVENT_FL_ISFUNCENT | EVENT_FL_ISFUNCRET))
- return pretty_print_func_graph(data, size, event, cpu, pid);
-
- if (latency_format)
- print_lat_fmt(data, size);
-
- if (event->flags & EVENT_FL_FAILED) {
- printf("EVENT '%s' FAILED TO PARSE\n",
- event->name);
- return;
- }
-
- pretty_print(data, size, event);
-}
-
-static void print_fields(struct print_flag_sym *field)
-{
- printf("{ %s, %s }", field->value, field->str);
- if (field->next) {
- printf(", ");
- print_fields(field->next);
- }
-}
-
-static void print_args(struct print_arg *args)
-{
- int print_paren = 1;
-
- switch (args->type) {
- case PRINT_NULL:
- printf("null");
- break;
- case PRINT_ATOM:
- printf("%s", args->atom.atom);
- break;
- case PRINT_FIELD:
- printf("REC->%s", args->field.name);
- break;
- case PRINT_FLAGS:
- printf("__print_flags(");
- print_args(args->flags.field);
- printf(", %s, ", args->flags.delim);
- print_fields(args->flags.flags);
- printf(")");
- break;
- case PRINT_SYMBOL:
- printf("__print_symbolic(");
- print_args(args->symbol.field);
- printf(", ");
- print_fields(args->symbol.symbols);
- printf(")");
- break;
- case PRINT_STRING:
- printf("__get_str(%s)", args->string.string);
- break;
- case PRINT_TYPE:
- printf("(%s)", args->typecast.type);
- print_args(args->typecast.item);
- break;
- case PRINT_OP:
- if (strcmp(args->op.op, ":") == 0)
- print_paren = 0;
- if (print_paren)
- printf("(");
- print_args(args->op.left);
- printf(" %s ", args->op.op);
- print_args(args->op.right);
- if (print_paren)
- printf(")");
- break;
- default:
- /* we should warn... */
- return;
- }
- if (args->next) {
- printf("\n");
- print_args(args->next);
- }
-}
-
-int parse_ftrace_file(char *buf, unsigned long size)
-{
- struct format_field *field;
- struct print_arg *arg, **list;
- struct event *event;
- int ret;
-
- init_input_buf(buf, size);
-
- event = alloc_event();
- if (!event)
- return -ENOMEM;
-
- event->flags |= EVENT_FL_ISFTRACE;
-
- event->name = event_read_name();
- if (!event->name)
- die("failed to read ftrace event name");
-
- if (strcmp(event->name, "function") == 0)
- event->flags |= EVENT_FL_ISFUNC;
-
- else if (strcmp(event->name, "funcgraph_entry") == 0)
- event->flags |= EVENT_FL_ISFUNCENT;
-
- else if (strcmp(event->name, "funcgraph_exit") == 0)
- event->flags |= EVENT_FL_ISFUNCRET;
-
- else if (strcmp(event->name, "bprint") == 0)
- event->flags |= EVENT_FL_ISBPRINT;
-
- event->id = event_read_id();
- if (event->id < 0)
- die("failed to read ftrace event id");
-
- add_event(event);
-
- ret = event_read_format(event);
- if (ret < 0)
- die("failed to read ftrace event format");
-
- ret = event_read_print(event);
- if (ret < 0)
- die("failed to read ftrace event print fmt");
-
- /* New ftrace handles args */
- if (ret > 0)
- return 0;
- /*
- * The arguments for ftrace files are parsed by the fields.
- * Set up the fields as their arguments.
- */
- list = &event->print_fmt.args;
- for (field = event->format.fields; field; field = field->next) {
- arg = malloc_or_die(sizeof(*arg));
- memset(arg, 0, sizeof(*arg));
- *list = arg;
- list = &arg->next;
- arg->type = PRINT_FIELD;
- arg->field.name = field->name;
- arg->field.field = field;
- }
- return 0;
-}
-
-int parse_event_file(char *buf, unsigned long size, char *sys)
-{
- struct event *event;
- int ret;
-
- init_input_buf(buf, size);
-
- event = alloc_event();
- if (!event)
- return -ENOMEM;
-
- event->name = event_read_name();
- if (!event->name)
- die("failed to read event name");
-
- event->id = event_read_id();
- if (event->id < 0)
- die("failed to read event id");
-
- ret = event_read_format(event);
- if (ret < 0) {
- warning("failed to read event format for %s", event->name);
- goto event_failed;
- }
-
- ret = event_read_print(event);
- if (ret < 0) {
- warning("failed to read event print fmt for %s", event->name);
- goto event_failed;
- }
-
- event->system = strdup(sys);
-
-#define PRINT_ARGS 0
- if (PRINT_ARGS && event->print_fmt.args)
- print_args(event->print_fmt.args);
-
- add_event(event);
- return 0;
-
- event_failed:
- event->flags |= EVENT_FL_FAILED;
- /* still add it even if it failed */
- add_event(event);
- return -1;
-}
-
-void parse_set_info(int nr_cpus, int long_sz)
-{
- cpus = nr_cpus;
- long_size = long_sz;
-}
-
-int common_pc(struct scripting_context *context)
-{
- return parse_common_pc(context->event_data);
-}
-
-int common_flags(struct scripting_context *context)
-{
- return parse_common_flags(context->event_data);
-}
-
-int common_lock_depth(struct scripting_context *context)
-{
- return parse_common_lock_depth(context->event_data);
-}
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index b9592e0de8d7..f097e0dd6c5c 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -52,6 +52,16 @@ static unsigned long page_size;
static ssize_t calc_data_size;
static bool repipe;
+static void *malloc_or_die(int size)
+{
+ void *ret;
+
+ ret = malloc(size);
+ if (!ret)
+ die("malloc");
+ return ret;
+}
+
static int do_read(int fd, void *buf, int size)
{
int rsize = size;
@@ -109,7 +119,7 @@ static unsigned int read4(void)
unsigned int data;
read_or_die(&data, 4);
- return __data2host4(data);
+ return __data2host4(perf_pevent, data);
}
static unsigned long long read8(void)
@@ -117,7 +127,7 @@ static unsigned long long read8(void)
unsigned long long data;
read_or_die(&data, 8);
- return __data2host8(data);
+ return __data2host8(perf_pevent, data);
}
static char *read_string(void)
@@ -282,7 +292,7 @@ struct cpu_data {
unsigned long long offset;
unsigned long long size;
unsigned long long timestamp;
- struct record *next;
+ struct pevent_record *next;
char *page;
int cpu;
int index;
@@ -367,9 +377,9 @@ static int calc_index(void *ptr, int cpu)
return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page;
}
-struct record *trace_peek_data(int cpu)
+struct pevent_record *trace_peek_data(int cpu)
{
- struct record *data;
+ struct pevent_record *data;
void *page = cpu_data[cpu].page;
int idx = cpu_data[cpu].index;
void *ptr = page + idx;
@@ -389,15 +399,15 @@ struct record *trace_peek_data(int cpu)
/* FIXME: handle header page */
if (header_page_ts_size != 8)
die("expected a long long type for timestamp");
- cpu_data[cpu].timestamp = data2host8(ptr);
+ cpu_data[cpu].timestamp = data2host8(perf_pevent, ptr);
ptr += 8;
switch (header_page_size_size) {
case 4:
- cpu_data[cpu].page_size = data2host4(ptr);
+ cpu_data[cpu].page_size = data2host4(perf_pevent, ptr);
ptr += 4;
break;
case 8:
- cpu_data[cpu].page_size = data2host8(ptr);
+ cpu_data[cpu].page_size = data2host8(perf_pevent, ptr);
ptr += 8;
break;
default:
@@ -414,7 +424,7 @@ read_again:
return trace_peek_data(cpu);
}
- type_len_ts = data2host4(ptr);
+ type_len_ts = data2host4(perf_pevent, ptr);
ptr += 4;
type_len = type_len4host(type_len_ts);
@@ -424,14 +434,14 @@ read_again:
case RINGBUF_TYPE_PADDING:
if (!delta)
die("error, hit unexpected end of page");
- length = data2host4(ptr);
+ length = data2host4(perf_pevent, ptr);
ptr += 4;
length *= 4;
ptr += length;
goto read_again;
case RINGBUF_TYPE_TIME_EXTEND:
- extend = data2host4(ptr);
+ extend = data2host4(perf_pevent, ptr);
ptr += 4;
extend <<= TS_SHIFT;
extend += delta;
@@ -442,7 +452,7 @@ read_again:
ptr += 12;
break;
case 0:
- length = data2host4(ptr);
+ length = data2host4(perf_pevent, ptr);
ptr += 4;
die("here! length=%d", length);
break;
@@ -467,9 +477,9 @@ read_again:
return data;
}
-struct record *trace_read_data(int cpu)
+struct pevent_record *trace_read_data(int cpu)
{
- struct record *data;
+ struct pevent_record *data;
data = trace_peek_data(cpu);
cpu_data[cpu].next = NULL;
@@ -509,6 +519,8 @@ ssize_t trace_report(int fd, bool __repipe)
file_bigendian = buf[0];
host_bigendian = bigendian();
+ read_trace_init(file_bigendian, host_bigendian);
+
read_or_die(buf, 1);
long_size = buf[0];
@@ -526,11 +538,11 @@ ssize_t trace_report(int fd, bool __repipe)
repipe = false;
if (show_funcs) {
- print_funcs();
+ pevent_print_funcs(perf_pevent);
return size;
}
if (show_printk) {
- print_printk();
+ pevent_print_printk(perf_pevent);
return size;
}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 58ae14c5baac..639852ac1117 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -1,20 +1,21 @@
-#ifndef __PERF_TRACE_EVENTS_H
-#define __PERF_TRACE_EVENTS_H
+#ifndef _PERF_UTIL_TRACE_EVENT_H
+#define _PERF_UTIL_TRACE_EVENT_H
-#include <stdbool.h>
#include "parse-events.h"
+#include "event-parse.h"
+#include "session.h"
struct machine;
struct perf_sample;
union perf_event;
struct thread;
-#define __unused __attribute__((unused))
-
+extern int header_page_size_size;
+extern int header_page_ts_size;
+extern int header_page_data_offset;
-#ifndef PAGE_MASK
-#define PAGE_MASK (page_size - 1)
-#endif
+extern bool latency_format;
+extern struct pevent *perf_pevent;
enum {
RINGBUF_TYPE_PADDING = 29,
@@ -26,246 +27,37 @@ enum {
#define TS_SHIFT 27
#endif
-#define NSECS_PER_SEC 1000000000ULL
-#define NSECS_PER_USEC 1000ULL
-
-enum format_flags {
- FIELD_IS_ARRAY = 1,
- FIELD_IS_POINTER = 2,
- FIELD_IS_SIGNED = 4,
- FIELD_IS_STRING = 8,
- FIELD_IS_DYNAMIC = 16,
- FIELD_IS_FLAG = 32,
- FIELD_IS_SYMBOLIC = 64,
-};
-
-struct format_field {
- struct format_field *next;
- char *type;
- char *name;
- int offset;
- int size;
- unsigned long flags;
-};
-
-struct format {
- int nr_common;
- int nr_fields;
- struct format_field *common_fields;
- struct format_field *fields;
-};
-
-struct print_arg_atom {
- char *atom;
-};
-
-struct print_arg_string {
- char *string;
- int offset;
-};
-
-struct print_arg_field {
- char *name;
- struct format_field *field;
-};
-
-struct print_flag_sym {
- struct print_flag_sym *next;
- char *value;
- char *str;
-};
-
-struct print_arg_typecast {
- char *type;
- struct print_arg *item;
-};
-
-struct print_arg_flags {
- struct print_arg *field;
- char *delim;
- struct print_flag_sym *flags;
-};
-
-struct print_arg_symbol {
- struct print_arg *field;
- struct print_flag_sym *symbols;
-};
-
-struct print_arg;
-
-struct print_arg_op {
- char *op;
- int prio;
- struct print_arg *left;
- struct print_arg *right;
-};
-
-struct print_arg_func {
- char *name;
- struct print_arg *args;
-};
-
-enum print_arg_type {
- PRINT_NULL,
- PRINT_ATOM,
- PRINT_FIELD,
- PRINT_FLAGS,
- PRINT_SYMBOL,
- PRINT_TYPE,
- PRINT_STRING,
- PRINT_OP,
-};
-
-struct print_arg {
- struct print_arg *next;
- enum print_arg_type type;
- union {
- struct print_arg_atom atom;
- struct print_arg_field field;
- struct print_arg_typecast typecast;
- struct print_arg_flags flags;
- struct print_arg_symbol symbol;
- struct print_arg_func func;
- struct print_arg_string string;
- struct print_arg_op op;
- };
-};
-
-struct print_fmt {
- char *format;
- struct print_arg *args;
-};
-
-struct event {
- struct event *next;
- char *name;
- int id;
- int flags;
- struct format format;
- struct print_fmt print_fmt;
- char *system;
-};
-
-enum {
- EVENT_FL_ISFTRACE = 0x01,
- EVENT_FL_ISPRINT = 0x02,
- EVENT_FL_ISBPRINT = 0x04,
- EVENT_FL_ISFUNC = 0x08,
- EVENT_FL_ISFUNCENT = 0x10,
- EVENT_FL_ISFUNCRET = 0x20,
-
- EVENT_FL_FAILED = 0x80000000
-};
-
-struct record {
- unsigned long long ts;
- int size;
- void *data;
-};
-
-struct record *trace_peek_data(int cpu);
-struct record *trace_read_data(int cpu);
-
-void parse_set_info(int nr_cpus, int long_sz);
-
-ssize_t trace_report(int fd, bool repipe);
-
-void *malloc_or_die(unsigned int size);
+int bigendian(void);
-void parse_cmdlines(char *file, int size);
-void parse_proc_kallsyms(char *file, unsigned int size);
-void parse_ftrace_printk(char *file, unsigned int size);
+int read_trace_init(int file_bigendian, int host_bigendian);
+void print_trace_event(int cpu, void *data, int size);
-void print_funcs(void);
-void print_printk(void);
+void print_event(int cpu, void *data, int size, unsigned long long nsecs,
+ char *comm);
int parse_ftrace_file(char *buf, unsigned long size);
int parse_event_file(char *buf, unsigned long size, char *sys);
-void print_trace_event(int cpu, void *data, int size);
-
-extern int file_bigendian;
-extern int host_bigendian;
-
-int bigendian(void);
-
-static inline unsigned short __data2host2(unsigned short data)
-{
- unsigned short swap;
-
- if (host_bigendian == file_bigendian)
- return data;
- swap = ((data & 0xffULL) << 8) |
- ((data & (0xffULL << 8)) >> 8);
+struct pevent_record *trace_peek_data(int cpu);
+struct event_format *trace_find_event(int type);
- return swap;
-}
-
-static inline unsigned int __data2host4(unsigned int data)
-{
- unsigned int swap;
-
- if (host_bigendian == file_bigendian)
- return data;
-
- swap = ((data & 0xffULL) << 24) |
- ((data & (0xffULL << 8)) << 8) |
- ((data & (0xffULL << 16)) >> 8) |
- ((data & (0xffULL << 24)) >> 24);
-
- return swap;
-}
-
-static inline unsigned long long __data2host8(unsigned long long data)
-{
- unsigned long long swap;
-
- if (host_bigendian == file_bigendian)
- return data;
-
- swap = ((data & 0xffULL) << 56) |
- ((data & (0xffULL << 8)) << 40) |
- ((data & (0xffULL << 16)) << 24) |
- ((data & (0xffULL << 24)) << 8) |
- ((data & (0xffULL << 32)) >> 8) |
- ((data & (0xffULL << 40)) >> 24) |
- ((data & (0xffULL << 48)) >> 40) |
- ((data & (0xffULL << 56)) >> 56);
-
- return swap;
-}
+unsigned long long
+raw_field_value(struct event_format *event, const char *name, void *data);
+void *raw_field_ptr(struct event_format *event, const char *name, void *data);
-#define data2host2(ptr) __data2host2(*(unsigned short *)ptr)
-#define data2host4(ptr) __data2host4(*(unsigned int *)ptr)
-#define data2host8(ptr) ({ \
- unsigned long long __val; \
- \
- memcpy(&__val, (ptr), sizeof(unsigned long long)); \
- __data2host8(__val); \
-})
+void parse_proc_kallsyms(char *file, unsigned int size __unused);
+void parse_ftrace_printk(char *file, unsigned int size __unused);
-extern int header_page_ts_offset;
-extern int header_page_ts_size;
-extern int header_page_size_offset;
-extern int header_page_size_size;
-extern int header_page_data_offset;
-extern int header_page_data_size;
-
-extern bool latency_format;
+ssize_t trace_report(int fd, bool repipe);
int trace_parse_common_type(void *data);
int trace_parse_common_pid(void *data);
-int parse_common_pc(void *data);
-int parse_common_flags(void *data);
-int parse_common_lock_depth(void *data);
-struct event *trace_find_event(int id);
-struct event *trace_find_next_event(struct event *event);
+
+struct event_format *trace_find_next_event(struct event_format *event);
unsigned long long read_size(void *ptr, int size);
-unsigned long long
-raw_field_value(struct event *event, const char *name, void *data);
-void *raw_field_ptr(struct event *event, const char *name, void *data);
unsigned long long eval_flag(const char *flag);
+struct pevent_record *trace_read_data(int cpu);
int read_tracing_data(int fd, struct list_head *pattrs);
struct tracing_data {
@@ -280,15 +72,6 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,
void tracing_data_put(struct tracing_data *tdata);
-/* taken from kernel/trace/trace.h */
-enum trace_flag_type {
- TRACE_FLAG_IRQS_OFF = 0x01,
- TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
- TRACE_FLAG_NEED_RESCHED = 0x04,
- TRACE_FLAG_HARDIRQ = 0x08,
- TRACE_FLAG_SOFTIRQ = 0x10,
-};
-
struct scripting_ops {
const char *name;
int (*start_script) (const char *script, int argc, const char **argv);
@@ -314,4 +97,4 @@ int common_pc(struct scripting_context *context);
int common_flags(struct scripting_context *context);
int common_lock_depth(struct scripting_context *context);
-#endif /* __PERF_TRACE_EVENTS_H */
+#endif /* _PERF_UTIL_TRACE_EVENT_H */
diff --git a/tools/perf/util/types.h b/tools/perf/util/types.h
index 5f3689a3d085..c51fa6b70a28 100644
--- a/tools/perf/util/types.h
+++ b/tools/perf/util/types.h
@@ -16,4 +16,9 @@ typedef signed short s16;
typedef unsigned char u8;
typedef signed char s8;
+union u64_swap {
+ u64 val64;
+ u32 val32[2];
+};
+
#endif /* __PERF_TYPES_H */
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
deleted file mode 100644
index 57a4c6ef3fd2..000000000000
--- a/tools/perf/util/ui/browsers/annotate.c
+++ /dev/null
@@ -1,433 +0,0 @@
-#include "../../util.h"
-#include "../browser.h"
-#include "../helpline.h"
-#include "../libslang.h"
-#include "../ui.h"
-#include "../util.h"
-#include "../../annotate.h"
-#include "../../hist.h"
-#include "../../sort.h"
-#include "../../symbol.h"
-#include <pthread.h>
-#include <newt.h>
-
-struct annotate_browser {
- struct ui_browser b;
- struct rb_root entries;
- struct rb_node *curr_hot;
- struct objdump_line *selection;
- int nr_asm_entries;
- int nr_entries;
- bool hide_src_code;
-};
-
-struct objdump_line_rb_node {
- struct rb_node rb_node;
- double percent;
- u32 idx;
- int idx_asm;
-};
-
-static inline
-struct objdump_line_rb_node *objdump_line__rb(struct objdump_line *self)
-{
- return (struct objdump_line_rb_node *)(self + 1);
-}
-
-static bool objdump_line__filter(struct ui_browser *browser, void *entry)
-{
- struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
-
- if (ab->hide_src_code) {
- struct objdump_line *ol = list_entry(entry, struct objdump_line, node);
- return ol->offset == -1;
- }
-
- return false;
-}
-
-static void annotate_browser__write(struct ui_browser *self, void *entry, int row)
-{
- struct annotate_browser *ab = container_of(self, struct annotate_browser, b);
- struct objdump_line *ol = list_entry(entry, struct objdump_line, node);
- bool current_entry = ui_browser__is_current_entry(self, row);
- int width = self->width;
-
- if (ol->offset != -1) {
- struct objdump_line_rb_node *olrb = objdump_line__rb(ol);
- ui_browser__set_percent_color(self, olrb->percent, current_entry);
- slsmg_printf(" %7.2f ", olrb->percent);
- } else {
- ui_browser__set_percent_color(self, 0, current_entry);
- slsmg_write_nstring(" ", 9);
- }
-
- SLsmg_write_char(':');
- slsmg_write_nstring(" ", 8);
-
- /* The scroll bar isn't being used */
- if (!self->navkeypressed)
- width += 1;
-
- if (!ab->hide_src_code && ol->offset != -1)
- if (!current_entry || (self->use_navkeypressed &&
- !self->navkeypressed))
- ui_browser__set_color(self, HE_COLORSET_CODE);
-
- if (!*ol->line)
- slsmg_write_nstring(" ", width - 18);
- else
- slsmg_write_nstring(ol->line, width - 18);
-
- if (current_entry)
- ab->selection = ol;
-}
-
-static double objdump_line__calc_percent(struct objdump_line *self,
- struct symbol *sym, int evidx)
-{
- double percent = 0.0;
-
- if (self->offset != -1) {
- int len = sym->end - sym->start;
- unsigned int hits = 0;
- struct annotation *notes = symbol__annotation(sym);
- struct source_line *src_line = notes->src->lines;
- struct sym_hist *h = annotation__histogram(notes, evidx);
- s64 offset = self->offset;
- struct objdump_line *next;
-
- next = objdump__get_next_ip_line(&notes->src->source, self);
- while (offset < (s64)len &&
- (next == NULL || offset < next->offset)) {
- if (src_line) {
- percent += src_line[offset].percent;
- } else
- hits += h->addr[offset];
-
- ++offset;
- }
- /*
- * If the percentage wasn't already calculated in
- * symbol__get_source_line, do it now:
- */
- if (src_line == NULL && h->sum)
- percent = 100.0 * hits / h->sum;
- }
-
- return percent;
-}
-
-static void objdump__insert_line(struct rb_root *self,
- struct objdump_line_rb_node *line)
-{
- struct rb_node **p = &self->rb_node;
- struct rb_node *parent = NULL;
- struct objdump_line_rb_node *l;
-
- while (*p != NULL) {
- parent = *p;
- l = rb_entry(parent, struct objdump_line_rb_node, rb_node);
- if (line->percent < l->percent)
- p = &(*p)->rb_left;
- else
- p = &(*p)->rb_right;
- }
- rb_link_node(&line->rb_node, parent, p);
- rb_insert_color(&line->rb_node, self);
-}
-
-static void annotate_browser__set_top(struct annotate_browser *self,
- struct rb_node *nd)
-{
- struct objdump_line_rb_node *rbpos;
- struct objdump_line *pos;
- unsigned back;
-
- ui_browser__refresh_dimensions(&self->b);
- back = self->b.height / 2;
- rbpos = rb_entry(nd, struct objdump_line_rb_node, rb_node);
- pos = ((struct objdump_line *)rbpos) - 1;
- self->b.top_idx = self->b.index = rbpos->idx;
-
- while (self->b.top_idx != 0 && back != 0) {
- pos = list_entry(pos->node.prev, struct objdump_line, node);
-
- --self->b.top_idx;
- --back;
- }
-
- self->b.top = pos;
- self->curr_hot = nd;
-}
-
-static void annotate_browser__calc_percent(struct annotate_browser *browser,
- int evidx)
-{
- struct map_symbol *ms = browser->b.priv;
- struct symbol *sym = ms->sym;
- struct annotation *notes = symbol__annotation(sym);
- struct objdump_line *pos;
-
- browser->entries = RB_ROOT;
-
- pthread_mutex_lock(&notes->lock);
-
- list_for_each_entry(pos, &notes->src->source, node) {
- struct objdump_line_rb_node *rbpos = objdump_line__rb(pos);
- rbpos->percent = objdump_line__calc_percent(pos, sym, evidx);
- if (rbpos->percent < 0.01) {
- RB_CLEAR_NODE(&rbpos->rb_node);
- continue;
- }
- objdump__insert_line(&browser->entries, rbpos);
- }
- pthread_mutex_unlock(&notes->lock);
-
- browser->curr_hot = rb_last(&browser->entries);
-}
-
-static bool annotate_browser__toggle_source(struct annotate_browser *browser)
-{
- struct objdump_line *ol;
- struct objdump_line_rb_node *olrb;
- off_t offset = browser->b.index - browser->b.top_idx;
-
- browser->b.seek(&browser->b, offset, SEEK_CUR);
- ol = list_entry(browser->b.top, struct objdump_line, node);
- olrb = objdump_line__rb(ol);
-
- if (browser->hide_src_code) {
- if (olrb->idx_asm < offset)
- offset = olrb->idx;
-
- browser->b.nr_entries = browser->nr_entries;
- browser->hide_src_code = false;
- browser->b.seek(&browser->b, -offset, SEEK_CUR);
- browser->b.top_idx = olrb->idx - offset;
- browser->b.index = olrb->idx;
- } else {
- if (olrb->idx_asm < 0) {
- ui_helpline__puts("Only available for assembly lines.");
- browser->b.seek(&browser->b, -offset, SEEK_CUR);
- return false;
- }
-
- if (olrb->idx_asm < offset)
- offset = olrb->idx_asm;
-
- browser->b.nr_entries = browser->nr_asm_entries;
- browser->hide_src_code = true;
- browser->b.seek(&browser->b, -offset, SEEK_CUR);
- browser->b.top_idx = olrb->idx_asm - offset;
- browser->b.index = olrb->idx_asm;
- }
-
- return true;
-}
-
-static int annotate_browser__run(struct annotate_browser *self, int evidx,
- void(*timer)(void *arg),
- void *arg, int delay_secs)
-{
- struct rb_node *nd = NULL;
- struct map_symbol *ms = self->b.priv;
- struct symbol *sym = ms->sym;
- const char *help = "<-/ESC: Exit, TAB/shift+TAB: Cycle hot lines, "
- "H: Go to hottest line, ->/ENTER: Line action, "
- "S: Toggle source code view";
- int key;
-
- if (ui_browser__show(&self->b, sym->name, help) < 0)
- return -1;
-
- annotate_browser__calc_percent(self, evidx);
-
- if (self->curr_hot)
- annotate_browser__set_top(self, self->curr_hot);
-
- nd = self->curr_hot;
-
- while (1) {
- key = ui_browser__run(&self->b, delay_secs);
-
- if (delay_secs != 0) {
- annotate_browser__calc_percent(self, evidx);
- /*
- * Current line focus got out of the list of most active
- * lines, NULL it so that if TAB|UNTAB is pressed, we
- * move to curr_hot (current hottest line).
- */
- if (nd != NULL && RB_EMPTY_NODE(nd))
- nd = NULL;
- }
-
- switch (key) {
- case K_TIMER:
- if (timer != NULL)
- timer(arg);
-
- if (delay_secs != 0)
- symbol__annotate_decay_histogram(sym, evidx);
- continue;
- case K_TAB:
- if (nd != NULL) {
- nd = rb_prev(nd);
- if (nd == NULL)
- nd = rb_last(&self->entries);
- } else
- nd = self->curr_hot;
- break;
- case K_UNTAB:
- if (nd != NULL)
- nd = rb_next(nd);
- if (nd == NULL)
- nd = rb_first(&self->entries);
- else
- nd = self->curr_hot;
- break;
- case 'H':
- case 'h':
- nd = self->curr_hot;
- break;
- case 'S':
- case 's':
- if (annotate_browser__toggle_source(self))
- ui_helpline__puts(help);
- continue;
- case K_ENTER:
- case K_RIGHT:
- if (self->selection == NULL) {
- ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
- continue;
- }
-
- if (self->selection->offset == -1) {
- ui_helpline__puts("Actions are only available for assembly lines.");
- continue;
- } else {
- char *s = strstr(self->selection->line, "callq ");
- struct annotation *notes;
- struct symbol *target;
- u64 ip;
-
- if (s == NULL) {
- ui_helpline__puts("Actions are only available for the 'callq' instruction.");
- continue;
- }
-
- s = strchr(s, ' ');
- if (s++ == NULL) {
- ui_helpline__puts("Invallid callq instruction.");
- continue;
- }
-
- ip = strtoull(s, NULL, 16);
- ip = ms->map->map_ip(ms->map, ip);
- target = map__find_symbol(ms->map, ip, NULL);
- if (target == NULL) {
- ui_helpline__puts("The called function was not found.");
- continue;
- }
-
- notes = symbol__annotation(target);
- pthread_mutex_lock(&notes->lock);
-
- if (notes->src == NULL && symbol__alloc_hist(target) < 0) {
- pthread_mutex_unlock(&notes->lock);
- ui__warning("Not enough memory for annotating '%s' symbol!\n",
- target->name);
- continue;
- }
-
- pthread_mutex_unlock(&notes->lock);
- symbol__tui_annotate(target, ms->map, evidx,
- timer, arg, delay_secs);
- ui_browser__show_title(&self->b, sym->name);
- }
- continue;
- case K_LEFT:
- case K_ESC:
- case 'q':
- case CTRL('c'):
- goto out;
- default:
- continue;
- }
-
- if (nd != NULL)
- annotate_browser__set_top(self, nd);
- }
-out:
- ui_browser__hide(&self->b);
- return key;
-}
-
-int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
- void(*timer)(void *arg), void *arg, int delay_secs)
-{
- return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx,
- timer, arg, delay_secs);
-}
-
-int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
- void(*timer)(void *arg), void *arg,
- int delay_secs)
-{
- struct objdump_line *pos, *n;
- struct annotation *notes;
- struct map_symbol ms = {
- .map = map,
- .sym = sym,
- };
- struct annotate_browser browser = {
- .b = {
- .refresh = ui_browser__list_head_refresh,
- .seek = ui_browser__list_head_seek,
- .write = annotate_browser__write,
- .filter = objdump_line__filter,
- .priv = &ms,
- .use_navkeypressed = true,
- },
- };
- int ret;
-
- if (sym == NULL)
- return -1;
-
- if (map->dso->annotate_warned)
- return -1;
-
- if (symbol__annotate(sym, map, sizeof(struct objdump_line_rb_node)) < 0) {
- ui__error("%s", ui_helpline__last_msg);
- return -1;
- }
-
- ui_helpline__push("Press <- or ESC to exit");
-
- notes = symbol__annotation(sym);
-
- list_for_each_entry(pos, &notes->src->source, node) {
- struct objdump_line_rb_node *rbpos;
- size_t line_len = strlen(pos->line);
-
- if (browser.b.width < line_len)
- browser.b.width = line_len;
- rbpos = objdump_line__rb(pos);
- rbpos->idx = browser.nr_entries++;
- if (pos->offset != -1)
- rbpos->idx_asm = browser.nr_asm_entries++;
- else
- rbpos->idx_asm = -1;
- }
-
- browser.b.nr_entries = browser.nr_entries;
- browser.b.entries = &notes->src->source,
- browser.b.width += 18; /* Percentage */
- ret = annotate_browser__run(&browser, evidx, timer, arg, delay_secs);
- list_for_each_entry_safe(pos, n, &notes->src->source, node) {
- list_del(&pos->node);
- objdump_line__free(pos);
- }
- return ret;
-}
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c
index 52bb07c6442a..4007aca8e0ca 100644
--- a/tools/perf/util/usage.c
+++ b/tools/perf/util/usage.c
@@ -82,41 +82,3 @@ void warning(const char *warn, ...)
warn_routine(warn, params);
va_end(params);
}
-
-uid_t parse_target_uid(const char *str, const char *tid, const char *pid)
-{
- struct passwd pwd, *result;
- char buf[1024];
-
- if (str == NULL)
- return UINT_MAX;
-
- /* UID and PID are mutually exclusive */
- if (tid || pid) {
- ui__warning("PID/TID switch overriding UID\n");
- sleep(1);
- return UINT_MAX;
- }
-
- getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
-
- if (result == NULL) {
- char *endptr;
- int uid = strtol(str, &endptr, 10);
-
- if (*endptr != '\0') {
- ui__error("Invalid user %s\n", str);
- return UINT_MAX - 1;
- }
-
- getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
-
- if (result == NULL) {
- ui__error("Problems obtaining information for user %s\n",
- str);
- return UINT_MAX - 1;
- }
- }
-
- return result->pw_uid;
-}
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 8109a907841e..d03599fbe78b 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -148,3 +148,13 @@ int readn(int fd, void *buf, size_t n)
return buf - buf_start;
}
+
+size_t hex_width(u64 v)
+{
+ size_t n = 1;
+
+ while ((v >>= 4))
+ ++n;
+
+ return n;
+}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 0f99f394d8e0..2daaedb83d84 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -74,7 +74,6 @@
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
-#include <pwd.h>
#include <inttypes.h>
#include "../../../include/linux/magic.h"
#include "types.h"
@@ -249,8 +248,6 @@ struct perf_event_attr;
void event_attr_init(struct perf_event_attr *attr);
-uid_t parse_target_uid(const char *str, const char *tid, const char *pid);
-
#define _STR(x) #x
#define STR(x) _STR(x)
@@ -265,4 +262,6 @@ bool is_power_of_2(unsigned long n)
return (n != 0 && ((n & (n - 1)) == 0));
}
+size_t hex_width(u64 v);
+
#endif
diff --git a/tools/power/cpupower/man/cpupower-set.1 b/tools/power/cpupower/man/cpupower-set.1
index c4954a9fe4e7..9dbd536518ab 100644
--- a/tools/power/cpupower/man/cpupower-set.1
+++ b/tools/power/cpupower/man/cpupower-set.1
@@ -85,15 +85,6 @@ Possible values are:
savings
.RE
-sched_mc_power_savings is dependent upon SCHED_MC, which is
-itself architecture dependent.
-
-sched_smt_power_savings is dependent upon SCHED_SMT, which
-is itself architecture dependent.
-
-The two files are independent of each other. It is possible
-that one file may be present without the other.
-
.SH "SEE ALSO"
cpupower-info(1), cpupower-monitor(1), powertop(1)
.PP
diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c
index c6343024a611..96e28c124b5c 100644
--- a/tools/power/cpupower/utils/helpers/sysfs.c
+++ b/tools/power/cpupower/utils/helpers/sysfs.c
@@ -362,22 +362,7 @@ char *sysfs_get_cpuidle_driver(void)
*/
int sysfs_get_sched(const char *smt_mc)
{
- unsigned long value;
- char linebuf[MAX_LINE_LEN];
- char *endp;
- char path[SYSFS_PATH_MAX];
-
- if (strcmp("mc", smt_mc) && strcmp("smt", smt_mc))
- return -EINVAL;
-
- snprintf(path, sizeof(path),
- PATH_TO_CPU "sched_%s_power_savings", smt_mc);
- if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
- return -1;
- value = strtoul(linebuf, &endp, 0);
- if (endp == linebuf || errno == ERANGE)
- return -1;
- return value;
+ return -ENODEV;
}
/*
@@ -388,21 +373,5 @@ int sysfs_get_sched(const char *smt_mc)
*/
int sysfs_set_sched(const char *smt_mc, int val)
{
- char linebuf[MAX_LINE_LEN];
- char path[SYSFS_PATH_MAX];
- struct stat statbuf;
-
- if (strcmp("mc", smt_mc) && strcmp("smt", smt_mc))
- return -EINVAL;
-
- snprintf(path, sizeof(path),
- PATH_TO_CPU "sched_%s_power_savings", smt_mc);
- sprintf(linebuf, "%d", val);
-
- if (stat(path, &statbuf) != 0)
- return -ENODEV;
-
- if (sysfs_write_file(path, linebuf, MAX_LINE_LEN) == 0)
- return -1;
- return 0;
+ return -ENODEV;
}
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
new file mode 100644
index 000000000000..bde8521d56bb
--- /dev/null
+++ b/tools/scripts/Makefile.include
@@ -0,0 +1,58 @@
+ifeq ("$(origin O)", "command line")
+ OUTPUT := $(O)/
+ COMMAND_O := O=$(O)
+endif
+
+ifneq ($(OUTPUT),)
+# check that the output directory actually exists
+OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd)
+$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
+endif
+
+#
+# Include saner warnings here, which can catch bugs:
+#
+EXTRA_WARNINGS := -Wbad-function-cast
+EXTRA_WARNINGS += -Wdeclaration-after-statement
+EXTRA_WARNINGS += -Wformat-security
+EXTRA_WARNINGS += -Wformat-y2k
+EXTRA_WARNINGS += -Winit-self
+EXTRA_WARNINGS += -Wmissing-declarations
+EXTRA_WARNINGS += -Wmissing-prototypes
+EXTRA_WARNINGS += -Wnested-externs
+EXTRA_WARNINGS += -Wno-system-headers
+EXTRA_WARNINGS += -Wold-style-definition
+EXTRA_WARNINGS += -Wpacked
+EXTRA_WARNINGS += -Wredundant-decls
+EXTRA_WARNINGS += -Wshadow
+EXTRA_WARNINGS += -Wstrict-aliasing=3
+EXTRA_WARNINGS += -Wstrict-prototypes
+EXTRA_WARNINGS += -Wswitch-default
+EXTRA_WARNINGS += -Wswitch-enum
+EXTRA_WARNINGS += -Wundef
+EXTRA_WARNINGS += -Wwrite-strings
+EXTRA_WARNINGS += -Wformat
+
+ifneq ($(findstring $(MAKEFLAGS), w),w)
+PRINT_DIR = --no-print-directory
+else
+NO_SUBDIR = :
+endif
+
+QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
+QUIET_SUBDIR1 =
+
+ifneq ($(findstring $(MAKEFLAGS),s),s)
+ifndef V
+ QUIET_CC = @echo ' ' CC $@;
+ QUIET_AR = @echo ' ' AR $@;
+ QUIET_LINK = @echo ' ' LINK $@;
+ QUIET_MKDIR = @echo ' ' MKDIR $@;
+ QUIET_GEN = @echo ' ' GEN $@;
+ QUIET_SUBDIR0 = +@subdir=
+ QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
+ $(MAKE) $(PRINT_DIR) -C $$subdir
+ QUIET_FLEX = @echo ' ' FLEX $@;
+ QUIET_BISON = @echo ' ' BISON $@;
+endif
+endif
diff --git a/tools/testing/ktest/examples/README b/tools/testing/ktest/examples/README
new file mode 100644
index 000000000000..a12d295a09d8
--- /dev/null
+++ b/tools/testing/ktest/examples/README
@@ -0,0 +1,32 @@
+This directory contains example configs to use ktest for various tasks.
+The configs still need to be customized for your environment, but it
+is broken up by task which makes it easier to understand how to set up
+ktest.
+
+The configs are based off of real working configs but have been modified
+and commented to show more generic use cases that are more helpful for
+developers.
+
+crosstests.conf - this config shows an example of testing a git repo against
+ lots of different architectures. It only does build tests, but makes
+ it easy to compile test different archs. You can download the arch
+ cross compilers from:
+ http://kernel.org/pub/tools/crosstool/files/bin/x86_64/
+
+test.conf - A generic example of a config. This is based on an actual config
+ used to perform real testing.
+
+kvm.conf - A example of a config that is used to test a virtual guest running
+ on a host.
+
+snowball.conf - An example config that was used to demo ktest.pl against
+ a snowball ARM board.
+
+include/ - The include directory holds default configs that can be
+ included into other configs. This is a real use example that shows how
+ to reuse configs for various machines or set ups. The files here
+ are included by other config files, where the other config files define
+ options and variables that will make the included config work for the
+ given environment.
+
+
diff --git a/tools/testing/ktest/examples/crosstests.conf b/tools/testing/ktest/examples/crosstests.conf
new file mode 100644
index 000000000000..46736604c26c
--- /dev/null
+++ b/tools/testing/ktest/examples/crosstests.conf
@@ -0,0 +1,260 @@
+#
+# Example config for cross compiling
+#
+# In this config, it is expected that the tool chains from:
+#
+# http://kernel.org/pub/tools/crosstool/files/bin/x86_64/
+#
+# running on a x86_64 system have been downloaded and installed into:
+#
+# /usr/local/
+#
+# such that the compiler binaries are something like:
+#
+# /usr/local/gcc-4.5.2-nolibc/mips-linux/bin/mips-linux-gcc
+#
+# Some of the archs will use gcc-4.5.1 instead of gcc-4.5.2
+# this config uses variables to differentiate them.
+#
+# Comments describe some of the options, but full descriptions of
+# options are described in the samples.conf file.
+
+# ${PWD} is defined by ktest.pl to be the directory that the user
+# was in when they executed ktest.pl. It may be better to hardcode the
+# path name here. THIS_DIR is the variable used through out the config file
+# in case you want to change it.
+
+THIS_DIR := ${PWD}
+
+# Update the BUILD_DIR option to the location of your git repo you want to test.
+BUILD_DIR = ${THIS_DIR}/linux.git
+
+# The build will go into this directory. It will be created when you run the test.
+OUTPUT_DIR = ${THIS_DIR}/cross-compile
+
+# The build will be compiled with -j8
+BUILD_OPTIONS = -j8
+
+# The test will not stop when it hits a failure.
+DIE_ON_FAILURE = 0
+
+# If you want to have ktest.pl store the failure somewhere, uncomment this option
+# and change the directory where ktest should store the failures.
+#STORE_FAILURES = ${THIS_DIR}/failures
+
+# The log file is stored in the OUTPUT_DIR called cross.log
+# If you enable this, you need to create the OUTPUT_DIR. It wont be created for you.
+LOG_FILE = ${OUTPUT_DIR}/cross.log
+
+# The log file will be cleared each time you run ktest.
+CLEAR_LOG = 1
+
+# As some archs do not build with the defconfig, they have been marked
+# to be ignored. If you want to test them anyway, change DO_FAILED to 1.
+# If a test that has been marked as DO_FAILED passes, then you should change
+# that test to be DO_DEFAULT
+
+DO_FAILED := 0
+DO_DEFAULT := 1
+
+# By setting both DO_FAILED and DO_DEFAULT to zero, you can pick a single
+# arch that you want to test. (uncomment RUN and chose your arch)
+#RUN := m32r
+
+# At the bottom of the config file exists a bisect test. You can update that
+# test and set DO_FAILED and DO_DEFAULT to zero, and uncomment this variable
+# to run the bisect on the arch.
+#RUN := bisect
+
+# By default all tests will be running gcc 4.5.2. Some tests are using 4.5.1
+# and they select that in the test.
+# Note: GCC_VER is declared as on option and not a variable ('=' instead of ':=')
+# This is important. A variable is used only in the config file and if it is set
+# it stays that way for the rest of the config file until it is change again.
+# Here we want GCC_VER to remain persistent and change for each test, as it is used in
+# the MAKE_CMD. By using '=' instead of ':=' we achieve our goal.
+
+GCC_VER = 4.5.2
+MAKE_CMD = PATH=/usr/local/gcc-${GCC_VER}-nolibc/${CROSS}/bin:$PATH CROSS_COMPILE=${CROSS}- make ARCH=${ARCH}
+
+# all tests are only doing builds.
+TEST_TYPE = build
+
+# If you want to add configs on top of the defconfig, you can add those configs into
+# the add-config file and uncomment this option. This is useful if you want to test
+# all cross compiles with PREEMPT set, or TRACING on, etc.
+#ADD_CONFIG = ${THIS_DIR}/add-config
+
+# All tests are using defconfig
+BUILD_TYPE = defconfig
+
+# The test names will have the arch and cross compiler used. This will be shown in
+# the results.
+TEST_NAME = ${ARCH} ${CROSS}
+
+# alpha
+TEST_START IF ${RUN} == alpha || ${DO_DEFAULT}
+# Notice that CROSS and ARCH are also options and not variables (again '=' instead
+# of ':='). This is because TEST_NAME and MAKE_CMD wil use them for each test.
+# Only options are available during runs. Variables are only present in parsing the
+# config file.
+CROSS = alpha-linux
+ARCH = alpha
+
+# arm
+TEST_START IF ${RUN} == arm || ${DO_DEFAULT}
+CROSS = arm-unknown-linux-gnueabi
+ARCH = arm
+
+# black fin
+TEST_START IF ${RUN} == bfin || ${DO_DEFAULT}
+CROSS = bfin-uclinux
+ARCH = blackfin
+BUILD_OPTIONS = -j8 vmlinux
+
+# cris - FAILS?
+TEST_START IF ${RUN} == cris || ${RUN} == cris64 || ${DO_FAILED}
+CROSS = cris-linux
+ARCH = cris
+
+# cris32 - not right arch?
+TEST_START IF ${RUN} == cris || ${RUN} == cris32 || ${DO_FAILED}
+CROSS = crisv32-linux
+ARCH = cris
+
+# ia64
+TEST_START IF ${RUN} == ia64 || ${DO_DEFAULT}
+CROSS = ia64-linux
+ARCH = ia64
+
+# frv
+TEST_START IF ${RUN} == frv || ${DO_FAILED}
+CROSS = frv-linux
+ARCH = frv
+GCC_VER = 4.5.1
+
+# h8300 - failed make defconfig??
+TEST_START IF ${RUN} == h8300 || ${DO_FAILED}
+CROSS = h8300-elf
+ARCH = h8300
+GCC_VER = 4.5.1
+
+# m68k fails with error?
+TEST_START IF ${RUN} == m68k || ${DO_DEFAULT}
+CROSS = m68k-linux
+ARCH = m68k
+
+# mips64
+TEST_START IF ${RUN} == mips || ${RUN} == mips64 || ${DO_DEFAULT}
+CROSS = mips64-linux
+ARCH = mips
+
+# mips32
+TEST_START IF ${RUN} == mips || ${RUN} == mips32 || ${DO_DEFAULT}
+CROSS = mips-linux
+ARCH = mips
+
+# m32r
+TEST_START IF ${RUN} == m32r || ${DO_FAILED}
+CROSS = m32r-linux
+ARCH = m32r
+GCC_VER = 4.5.1
+BUILD_OPTIONS = -j8 vmlinux
+
+# parisc64 failed?
+TEST_START IF ${RUN} == hppa || ${RUN} == hppa64 || ${DO_FAILED}
+CROSS = hppa64-linux
+ARCH = parisc
+
+# parisc
+TEST_START IF ${RUN} == hppa || ${RUN} == hppa32 || ${DO_FAILED}
+CROSS = hppa-linux
+ARCH = parisc
+
+# ppc
+TEST_START IF ${RUN} == ppc || ${RUN} == ppc32 || ${DO_DEFAULT}
+CROSS = powerpc-linux
+ARCH = powerpc
+
+# ppc64
+TEST_START IF ${RUN} == ppc || ${RUN} == ppc64 || ${DO_DEFAULT}
+CROSS = powerpc64-linux
+ARCH = powerpc
+
+# s390
+TEST_START IF ${RUN} == s390 || ${DO_DEFAULT}
+CROSS = s390x-linux
+ARCH = s390
+
+# sh
+TEST_START IF ${RUN} == sh || ${DO_DEFAULT}
+CROSS = sh4-linux
+ARCH = sh
+
+# sparc64
+TEST_START IF ${RUN} == sparc || ${RUN} == sparc64 || ${DO_DEFAULT}
+CROSS = sparc64-linux
+ARCH = sparc64
+
+# sparc
+TEST_START IF ${RUN} == sparc || ${RUN} == sparc32 || ${DO_DEFAULT}
+CROSS = sparc-linux
+ARCH = sparc
+
+# xtensa failed
+TEST_START IF ${RUN} == xtensa || ${DO_FAILED}
+CROSS = xtensa-linux
+ARCH = xtensa
+
+# UML
+TEST_START IF ${RUN} == uml || ${DO_DEFAULT}
+MAKE_CMD = make ARCH=um SUBARCH=x86_64
+ARCH = uml
+CROSS =
+
+TEST_START IF ${RUN} == x86 || ${RUN} == i386 || ${DO_DEFAULT}
+MAKE_CMD = make ARCH=i386
+ARCH = i386
+CROSS =
+
+TEST_START IF ${RUN} == x86 || ${RUN} == x86_64 || ${DO_DEFAULT}
+MAKE_CMD = make ARCH=x86_64
+ARCH = x86_64
+CROSS =
+
+#################################
+
+# This is a bisect if needed. You need to give it a MIN_CONFIG that
+# will be the config file it uses. Basically, just copy the created defconfig
+# for the arch someplace and point MIN_CONFIG to it.
+TEST_START IF ${RUN} == bisect
+MIN_CONFIG = ${THIS_DIR}/min-config
+CROSS = s390x-linux
+ARCH = s390
+TEST_TYPE = bisect
+BISECT_TYPE = build
+BISECT_GOOD = v3.1
+BISECT_BAD = v3.2
+CHECKOUT = v3.2
+
+#################################
+
+# These defaults are needed to keep ktest.pl from complaining. They are
+# ignored because the test does not go pass the build. No install or
+# booting of the target images.
+
+DEFAULTS
+MACHINE = crosstest
+SSH_USER = root
+BUILD_TARGET = cross
+TARGET_IMAGE = image
+POWER_CYCLE = cycle
+CONSOLE = console
+LOCALVERSION = version
+GRUB_MENU = grub
+
+REBOOT_ON_ERROR = 0
+POWEROFF_ON_ERROR = 0
+POWEROFF_ON_SUCCESS = 0
+REBOOT_ON_SUCCESS = 0
+
diff --git a/tools/testing/ktest/examples/include/bisect.conf b/tools/testing/ktest/examples/include/bisect.conf
new file mode 100644
index 000000000000..009bea65bfb6
--- /dev/null
+++ b/tools/testing/ktest/examples/include/bisect.conf
@@ -0,0 +1,90 @@
+#
+# This example shows the bisect tests (git bisect and config bisect)
+#
+
+
+# The config that includes this file may define a RUN_TEST
+# variable that will tell this config what test to run.
+# (what to set the TEST option to).
+#
+DEFAULTS IF NOT DEFINED RUN_TEST
+# Requires that hackbench is in the PATH
+RUN_TEST := ${SSH} hackbench 50
+
+
+# Set TEST to 'bisect' to do a normal git bisect. You need
+# to modify the options below to make it bisect the exact
+# commits you are interested in.
+#
+TEST_START IF ${TEST} == bisect
+TEST_TYPE = bisect
+# You must set the commit that was considered good (git bisect good)
+BISECT_GOOD = v3.3
+# You must set the commit that was considered bad (git bisect bad)
+BISECT_BAD = HEAD
+# It's best to specify the branch to checkout before starting the bisect.
+CHECKOUT = origin/master
+# This can be build, boot, or test. Here we are doing a bisect
+# that requires to run a test to know if the bisect was good or bad.
+# The test should exit with 0 on good, non-zero for bad. But see
+# the BISECT_RET_* options in samples.conf to override this.
+BISECT_TYPE = test
+TEST = ${RUN_TEST}
+# It is usually a good idea to confirm that the GOOD and the BAD
+# commits are truly good and bad respectively. Having BISECT_CHECK
+# set to 1 will check both that the good commit works and the bad
+# commit fails. If you only want to check one or the other,
+# set BISECT_CHECK to 'good' or to 'bad'.
+BISECT_CHECK = 1
+#BISECT_CHECK = good
+#BISECT_CHECK = bad
+
+# Usually it's a good idea to specify the exact config you
+# want to use throughout the entire bisect. Here we placed
+# it in the directory we called ktest.pl from and named it
+# 'config-bisect'.
+MIN_CONFIG = ${THIS_DIR}/config-bisect
+# By default, if we are doing a BISECT_TYPE = test run but the
+# build or boot fails, ktest.pl will do a 'git bisect skip'.
+# Uncomment the below option to make ktest stop testing on such
+# an error.
+#BISECT_SKIP = 0
+# Now if you had BISECT_SKIP = 0 and the test fails, you can
+# examine what happened and then do 'git bisect log > /tmp/replay'
+# Set BISECT_REPLAY to /tmp/replay and ktest.pl will run the
+# 'git bisect replay /tmp/replay' before continuing the bisect test.
+#BISECT_REPLAY = /tmp/replay
+# If you used BISECT_REPLAY after the bisect test failed, you may
+# not want to continue the bisect on that commit that failed.
+# By setting BISECT_START to a new commit. ktest.pl will checkout
+# that commit after it has performed the 'git bisect replay' but
+# before it continues running the bisect test.
+#BISECT_START = 2545eb6198e7e1ec50daa0cfc64a4cdfecf24ec9
+
+# Now if you don't trust ktest.pl to make the decisions for you, then
+# set BISECT_MANUAL to 1. This will cause ktest.pl not to decide
+# if the commit was good or bad. Instead, it will ask you to tell
+# it if the current commit was good. In the mean time, you could
+# take the result, load it on any machine you want. Run several tests,
+# or whatever you feel like. Then, when you are happy, you can tell
+# ktest if you think it was good or not and ktest.pl will continue
+# the git bisect. You can even change what commit it is currently at.
+#BISECT_MANUAL = 1
+
+
+# One of the unique tests that ktest does is the config bisect.
+# Currently (which hopefully will be fixed soon), the bad config
+# must be a superset of the good config. This is because it only
+# searches for a config that causes the target to fail. If the
+# good config is not a subset of the bad config, or if the target
+# fails because of a lack of a config, then it will not find
+# the config for you.
+TEST_START IF ${TEST} == config-bisect
+TEST_TYPE = config_bisect
+# set to build, boot, test
+CONFIG_BISECT_TYPE = boot
+# Set the config that is considered bad.
+CONFIG_BISECT = ${THIS_DIR}/config-bad
+# This config is optional. By default it uses the
+# MIN_CONFIG as the good config.
+CONFIG_BISECT_GOOD = ${THIS_DIR}/config-good
diff --git a/tools/testing/ktest/examples/include/defaults.conf b/tools/testing/ktest/examples/include/defaults.conf
new file mode 100644
index 000000000000..323a552ce642
--- /dev/null
+++ b/tools/testing/ktest/examples/include/defaults.conf
@@ -0,0 +1,157 @@
+# This file holds defaults for most the tests. It defines the options that
+# are most common to tests that are likely to be shared.
+#
+# Note, after including this file, a config file may override any option
+# with a DEFAULTS OVERRIDE section.
+#
+
+# For those cases that use the same machine to boot a 64 bit
+# and a 32 bit version. The MACHINE is the DNS name to get to the
+# box (usually different if it was 64 bit or 32 bit) but the
+# BOX here is defined as a variable that will be the name of the box
+# itself. It is useful for calling scripts that will power cycle
+# the box, as only one script needs to be created to power cycle
+# even though the box itself has multiple operating systems on it.
+# By default, BOX and MACHINE are the same.
+
+DEFAULTS IF NOT DEFINED BOX
+BOX := ${MACHINE}
+
+
+# Consider each box as 64 bit box, unless the config including this file
+# has defined BITS = 32
+
+DEFAULTS IF NOT DEFINED BITS
+BITS := 64
+
+
+DEFAULTS
+
+# THIS_DIR is used through out the configs and defaults to ${PWD} which
+# is the directory that ktest.pl was called from.
+
+THIS_DIR := ${PWD}
+
+
+# to orginize your configs, having each machine save their configs
+# into a separate directly is useful.
+CONFIG_DIR := ${THIS_DIR}/configs/${MACHINE}
+
+# Reset the log before running each test.
+CLEAR_LOG = 1
+
+# As installing kernels usually requires root privilege, default the
+# user on the target as root. It is also required that the target
+# allows ssh to root from the host without asking for a password.
+
+SSH_USER = root
+
+# For accesing the machine, we will ssh to root@machine.
+SSH := ssh ${SSH_USER}@${MACHINE}
+
+# Update this. The default here is ktest will ssh to the target box
+# and run a script called 'run-test' located on that box.
+TEST = ${SSH} run-test
+
+# Point build dir to the git repo you use
+BUILD_DIR = ${THIS_DIR}/linux.git
+
+# Each machine will have its own output build directory.
+OUTPUT_DIR = ${THIS_DIR}/build/${MACHINE}
+
+# Yes this config is focused on x86 (but ktest works for other archs too)
+BUILD_TARGET = arch/x86/boot/bzImage
+TARGET_IMAGE = /boot/vmlinuz-test
+
+# have directory for the scripts to reboot and power cycle the boxes
+SCRIPTS_DIR := ${THIS_DIR}/scripts
+
+# You can have each box/machine have a script to power cycle it.
+# Name your script <box>-cycle.
+POWER_CYCLE = ${SCRIPTS_DIR}/${BOX}-cycle
+
+# This script is used to power off the box.
+POWER_OFF = ${SCRIPTS_DIR}/${BOX}-poweroff
+
+# Keep your test kernels separate from your other kernels.
+LOCALVERSION = -test
+
+# The /boot/grub/menu.lst is searched for the line:
+# title Test Kernel
+# and ktest will use that kernel to reboot into.
+# For grub2 or other boot loaders, you need to set BOOT_TYPE
+# to 'script' and define other ways to load the kernel.
+# See snowball.conf example.
+#
+GRUB_MENU = Test Kernel
+
+# The kernel build will use this option.
+BUILD_OPTIONS = -j8
+
+# Keeping the log file with the output dir is convenient.
+LOG_FILE = ${OUTPUT_DIR}/${MACHINE}.log
+
+# Each box should have their own minum configuration
+# See min-config.conf
+MIN_CONFIG = ${CONFIG_DIR}/config-min
+
+# For things like randconfigs, there may be configs you find that
+# are already broken, or there may be some configs that you always
+# want set. Uncomment ADD_CONFIG and point it to the make config files
+# that set the configs you want to keep on (or off) in your build.
+# ADD_CONFIG is usually something to add configs to all machines,
+# where as, MIN_CONFIG is specific per machine.
+#ADD_CONFIG = ${THIS_DIR}/config-broken ${THIS_DIR}/config-general
+
+# To speed up reboots for bisects and patchcheck, instead of
+# waiting 60 seconds for the console to be idle, if this line is
+# seen in the console output, ktest will know the good kernel has
+# finished rebooting and it will be able to continue the tests.
+REBOOT_SUCCESS_LINE = ${MACHINE} login:
+
+# The following is different ways to end the test.
+# by setting the variable REBOOT to: none, error, fail or
+# something else, ktest will power cycle or reboot the target box
+# at the end of the tests.
+#
+# REBOOT := none
+# Don't do anything at the end of the test.
+#
+# REBOOT := error
+# Reboot the box if ktest detects an error
+#
+# REBOOT := fail
+# Do not stop on failure, and after all tests are complete
+# power off the box (for both success and error)
+# This is good to run over a weekend and you don't want to waste
+# electricity.
+#
+
+DEFAULTS IF ${REBOOT} == none
+REBOOT_ON_SUCCESS = 0
+REBOOT_ON_ERROR = 0
+POWEROFF_ON_ERROR = 0
+POWEROFF_ON_SUCCESS = 0
+
+DEFAULTS ELSE IF ${REBOOT} == error
+REBOOT_ON_SUCCESS = 0
+REBOOT_ON_ERROR = 1
+POWEROFF_ON_ERROR = 0
+POWEROFF_ON_SUCCESS = 0
+
+DEFAULTS ELSE IF ${REBOOT} == fail
+REBOOT_ON_SUCCESS = 0
+POWEROFF_ON_ERROR = 1
+POWEROFF_ON_SUCCESS = 1
+POWEROFF_AFTER_HALT = 120
+DIE_ON_FAILURE = 0
+
+# Store the failure information into this directory
+# such as the .config, dmesg, and build log.
+STORE_FAILURES = ${THIS_DIR}/failures
+
+DEFAULTS ELSE
+REBOOT_ON_SUCCESS = 1
+REBOOT_ON_ERROR = 1
+POWEROFF_ON_ERROR = 0
+POWEROFF_ON_SUCCESS = 0
diff --git a/tools/testing/ktest/examples/include/min-config.conf b/tools/testing/ktest/examples/include/min-config.conf
new file mode 100644
index 000000000000..c703cc46d151
--- /dev/null
+++ b/tools/testing/ktest/examples/include/min-config.conf
@@ -0,0 +1,60 @@
+#
+# This file has some examples for creating a MIN_CONFIG.
+# (A .config file that is the minimum for a machine to boot, or
+# to boot and make a network connection.)
+#
+# A MIN_CONFIG is very useful as it is the minimum configuration
+# needed to boot a given machine. You can debug someone else's
+# .config by only setting the configs in your MIN_CONFIG. The closer
+# your MIN_CONFIG is to the true minimum set of configs needed to
+# boot your machine, the closer the config you test with will be
+# to the users config that had the failure.
+#
+# The make_min_config test allows you to create a MIN_CONFIG that
+# is truly the minimum set of configs needed to boot a box.
+#
+# In this example, the final config will reside in
+# ${CONFIG_DIR}/config-new-min and ${CONFIG_DIR}/config-new-min-net.
+# Just move one to the location you have set for MIN_CONFIG.
+#
+# The first test creates a MIN_CONFIG that will be the minimum
+# configuration to boot ${MACHINE} and be able to ssh to it.
+#
+# The second test creates a MIN_CONFIG that will only boot
+# the target and most likely will not let you ssh to it. (Notice
+# how the second test uses the first test's result to continue with.
+# This is because the second test config is a subset of the first).
+#
+# The ${CONFIG_DIR}/config-skip (and -net) will hold the configs
+# that ktest.pl found would not boot the target without them set.
+# The config-new-min holds configs that ktest.pl could not test
+# directly because another config that was needed to boot the box
+# selected them. Sometimes it is possible that this file will hold
+# the true minimum configuration. You can test to see if this is
+# the case by running the boot test with BOOT_TYPE = allnoconfig and
+# setting setting the MIN_CONFIG to ${CONFIG_DIR}/config-skip. If the
+# machine still boots, then you can use the config-skip as your MIN_CONFIG.
+#
+# These tests can run for several hours (and perhaps days).
+# It's OK to kill the test with a Ctrl^C. By restarting without
+# modifying this config, ktest.pl will notice that the config-new-min(-net)
+# exists, and will use that instead as the starting point.
+# The USE_OUTPUT_MIN_CONFIG is set to 1 to keep ktest.pl from asking
+# you if you want to use the OUTPUT_MIN_CONFIG as the starting point.
+# By using the OUTPUT_MIN_CONFIG as the starting point will allow ktest.pl to
+# start almost where it left off.
+#
+TEST_START IF ${TEST} == min-config
+TEST_TYPE = make_min_config
+OUTPUT_MIN_CONFIG = ${CONFIG_DIR}/config-new-min-net
+IGNORE_CONFIG = ${CONFIG_DIR}/config-skip-net
+MIN_CONFIG_TYPE = test
+TEST = ${SSH} echo hi
+USE_OUTPUT_MIN_CONFIG = 1
+
+TEST_START IF ${TEST} == min-config && ${MULTI}
+TEST_TYPE = make_min_config
+OUTPUT_MIN_CONFIG = ${CONFIG_DIR}/config-new-min
+IGNORE_CONFIG = ${CONFIG_DIR}/config-skip
+MIN_CONFIG = ${CONFIG_DIR}/config-new-min-net
+USE_OUTPUT_MIN_CONFIG = 1
diff --git a/tools/testing/ktest/examples/include/patchcheck.conf b/tools/testing/ktest/examples/include/patchcheck.conf
new file mode 100644
index 000000000000..339d3e1700ff
--- /dev/null
+++ b/tools/testing/ktest/examples/include/patchcheck.conf
@@ -0,0 +1,74 @@
+# patchcheck.conf
+#
+# This contains a test that takes two git commits and will test each
+# commit between the two. The build test will look at what files the
+# commit has touched, and if any of those files produce a warning, then
+# the build will fail.
+
+
+# PATCH_START is the commit to begin with and PATCH_END is the commit
+# to end with (inclusive). This is similar to doing a git rebase -i PATCH_START~1
+# and then testing each commit and doing a git rebase --continue.
+# You can use a SHA1, a git tag, or anything that git will accept for a checkout
+
+PATCH_START := HEAD~3
+PATCH_END := HEAD
+
+# Change PATCH_CHECKOUT to be the branch you want to test. The test will
+# do a git checkout of this branch before starting. Obviously both
+# PATCH_START and PATCH_END must be in this branch (and PATCH_START must
+# be contained by PATCH_END).
+
+PATCH_CHECKOUT := test/branch
+
+# Usually it's a good idea to have a set config to use for testing individual
+# patches.
+PATCH_CONFIG := ${CONFIG_DIR}/config-patchcheck
+
+# Change PATCH_TEST to run some test for each patch. Each commit that is
+# tested, after it is built and installed on the test machine, this command
+# will be executed. Usually what is done is to ssh to the target box and
+# run some test scripts. If you just want to boot test your patches
+# comment PATCH_TEST out.
+PATCH_TEST := ${SSH} "/usr/local/bin/ktest-test-script"
+
+DEFAULTS IF DEFINED PATCH_TEST
+PATCH_TEST_TYPE := test
+
+DEFAULTS ELSE
+PATCH_TEST_TYPE := boot
+
+# If for some reason a file has a warning that one of your patches touch
+# but you do not care about it, set IGNORE_WARNINGS to that commit(s)
+# (space delimited)
+#IGNORE_WARNINGS = 39eaf7ef884dcc44f7ff1bac803ca2a1dcf43544 6edb2a8a385f0cdef51dae37ff23e74d76d8a6ce
+
+# If you are running a multi test, and the test failed on the first
+# test but on, say the 5th patch. If you want to restart on the
+# fifth patch, set PATCH_START1. This will make the first test start
+# from this commit instead of the PATCH_START commit.
+# Note, do not change this option. Just define PATCH_START1 in the
+# top config (the one you pass to ktest.pl), and this will use it,
+# otherwise it will just use PATCH_START if PATCH_START1 is not defined.
+DEFAULTS IF NOT DEFINED PATCH_START1
+PATCH_START1 := ${PATCH_START}
+
+TEST_START IF ${TEST} == patchcheck
+TEST_TYPE = patchcheck
+MIN_CONFIG = ${PATCH_CONFIG}
+TEST = ${PATCH_TEST}
+PATCHCHECK_TYPE = ${PATCH_TEST_TYPE}
+PATCHCHECK_START = ${PATCH_START1}
+PATCHCHECK_END = ${PATCH_END}
+CHECKOUT = ${PATCH_CHECKOUT}
+
+TEST_START IF ${TEST} == patchcheck && ${MULTI}
+TEST_TYPE = patchcheck
+MIN_CONFIG = ${PATCH_CONFIG}
+TEST = ${PATCH_TEST}
+PATCHCHECK_TYPE = ${PATCH_TEST_TYPE}
+PATCHCHECK_START = ${PATCH_START}
+PATCHCHECK_END = ${PATCH_END}
+CHECKOUT = ${PATCH_CHECKOUT}
+# Use multi to test different compilers?
+MAKE_CMD = CC=gcc-4.5.1 make
diff --git a/tools/testing/ktest/examples/include/tests.conf b/tools/testing/ktest/examples/include/tests.conf
new file mode 100644
index 000000000000..4fdb811bd810
--- /dev/null
+++ b/tools/testing/ktest/examples/include/tests.conf
@@ -0,0 +1,74 @@
+#
+# This is an example of various tests that you can run
+#
+# The variable TEST can be of boot, build, randconfig, or test.
+#
+# Note that TEST is a variable created with ':=' and only exists
+# throughout the config processing (not during the tests itself).
+#
+# The TEST option (defined with '=') is used to tell ktest.pl
+# what test to run after a successful boot. The TEST option is
+# persistent into the test runs.
+#
+
+# The config that includes this file may define a BOOT_TYPE
+# variable that tells this config what type of boot test to run.
+# If it's not defined, the below DEFAULTS will set the default
+# to 'oldconfig'.
+#
+DEFAULTS IF NOT DEFINED BOOT_TYPE
+BOOT_TYPE := oldconfig
+
+# The config that includes this file may define a RUN_TEST
+# variable that will tell this config what test to run.
+# (what to set the TEST option to).
+#
+DEFAULTS IF NOT DEFINED RUN_TEST
+# Requires that hackbench is in the PATH
+RUN_TEST := ${SSH} hackbench 50
+
+
+# If TEST is set to 'boot' then just build a kernel and boot
+# the target.
+TEST_START IF ${TEST} == boot
+TEST_TYPE = boot
+# Notice how we set the BUILD_TYPE option to the BOOT_TYPE variable.
+BUILD_TYPE = ${BOOT_TYPE}
+# Do not do a make mrproper.
+BUILD_NOCLEAN = 1
+
+# If you only want to build the kernel, and perhaps install
+# and test it yourself, then just set TEST to build.
+TEST_START IF ${TEST} == build
+TEST_TYPE = build
+BUILD_TYPE = ${BOOT_TYPE}
+BUILD_NOCLEAN = 1
+
+# Build, install, boot and test with a randconfg 10 times.
+# It is important that you have set MIN_CONFIG in the config
+# that includes this file otherwise it is likely that the
+# randconfig will not have the neccessary configs needed to
+# boot your box. This version of the test requires a min
+# config that has enough to make sure the target has network
+# working.
+TEST_START ITERATE 10 IF ${TEST} == randconfig
+MIN_CONFIG = ${CONFIG_DIR}/config-min-net
+TEST_TYPE = test
+BUILD_TYPE = randconfig
+TEST = ${RUN_TEST}
+
+# This is the same as above, but only tests to a boot prompt.
+# The MIN_CONFIG used here does not need to have networking
+# working.
+TEST_START ITERATE 10 IF ${TEST} == randconfig && ${MULTI}
+TEST_TYPE = boot
+BUILD_TYPE = randconfig
+MIN_CONFIG = ${CONFIG_DIR}/config-min
+MAKE_CMD = make
+
+# This builds, installs, boots and tests the target.
+TEST_START IF ${TEST} == test
+TEST_TYPE = test
+BUILD_TYPE = ${BOOT_TYPE}
+TEST = ${RUN_TEST}
+BUILD_NOCLEAN = 1
diff --git a/tools/testing/ktest/examples/kvm.conf b/tools/testing/ktest/examples/kvm.conf
new file mode 100644
index 000000000000..831c7c5395f1
--- /dev/null
+++ b/tools/testing/ktest/examples/kvm.conf
@@ -0,0 +1,88 @@
+#
+# This config is an example usage of ktest.pl with a kvm guest
+#
+# The guest is called 'Guest' and this would be something that
+# could be run on the host to test a virtual machine target.
+
+MACHINE = Guest
+
+
+# Use virsh to read the serial console of the guest
+CONSOLE = virsh console ${MACHINE}
+
+#*************************************#
+# This part is the same as test.conf #
+#*************************************#
+
+# The include files will set up the type of test to run. Just set TEST to
+# which test you want to run.
+#
+# TESTS = patchcheck, randconfig, boot, test, config-bisect, bisect, min-config
+#
+# See the include/*.conf files that define these tests
+#
+TEST := patchcheck
+
+# Some tests may have more than one test to run. Define MULTI := 1 to run
+# the extra tests.
+MULTI := 0
+
+# In case you want to differentiate which type of system you are testing
+BITS := 64
+
+# REBOOT = none, error, fail, empty
+# See include/defaults.conf
+REBOOT := empty
+
+
+# The defaults file will set up various settings that can be used by all
+# machine configs.
+INCLUDE include/defaults.conf
+
+
+#*************************************#
+# Now we are different from test.conf #
+#*************************************#
+
+
+# The example here assumes that Guest is running a Fedora release
+# that uses dracut for its initfs. The POST_INSTALL will be executed
+# after the install of the kernel and modules are complete.
+#
+POST_INSTALL = ${SSH} /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION
+
+# Guests sometimes get stuck on reboot. We wait 3 seconds after running
+# the reboot command and then do a full power-cycle of the guest.
+# This forces the guest to restart.
+#
+POWERCYCLE_AFTER_REBOOT = 3
+
+# We do the same after the halt command, but this time we wait 20 seconds.
+POWEROFF_AFTER_HALT = 20
+
+
+# As the defaults.conf file has a POWER_CYCLE option already defined,
+# and options can not be defined in the same section more than once
+# (all DEFAULTS sections are considered the same). We use the
+# DEFAULTS OVERRIDE to tell ktest.pl to ignore the previous defined
+# options, for the options set in the OVERRIDE section.
+#
+DEFAULTS OVERRIDE
+
+# Instead of using the default POWER_CYCLE option defined in
+# defaults.conf, we use virsh to cycle it. To do so, we destroy
+# the guest, wait 5 seconds, and then start it up again.
+# Crude, but effective.
+#
+POWER_CYCLE = virsh destroy ${MACHINE}; sleep 5; virsh start ${MACHINE}
+
+
+DEFAULTS
+
+# The following files each handle a different test case.
+# Having them included allows you to set up more than one machine and share
+# the same tests.
+INCLUDE include/patchcheck.conf
+INCLUDE include/tests.conf
+INCLUDE include/bisect.conf
+INCLUDE include/min-config.conf
diff --git a/tools/testing/ktest/examples/snowball.conf b/tools/testing/ktest/examples/snowball.conf
new file mode 100644
index 000000000000..a82a3c5bc2b7
--- /dev/null
+++ b/tools/testing/ktest/examples/snowball.conf
@@ -0,0 +1,53 @@
+# This example was used to boot the snowball ARM board.
+# See http://people.redhat.com/srostedt/ktest-embedded-2012/
+
+# PWD is a ktest.pl variable that will result in the process working
+# directory that ktest.pl is executed in.
+
+# THIS_DIR is automatically assigned the PWD of the path that generated
+# the config file. It is best to use this variable when assigning other
+# directory paths within this directory. This allows you to easily
+# move the test cases to other locations or to other machines.
+#
+THIS_DIR := /home/rostedt/work/demo/ktest-embed
+LOG_FILE = ${OUTPUT_DIR}/snowball.log
+CLEAR_LOG = 1
+MAKE_CMD = PATH=/usr/local/gcc-4.5.2-nolibc/arm-unknown-linux-gnueabi/bin:$PATH CROSS_COMPILE=arm-unknown-linux-gnueabi- make ARCH=arm
+ADD_CONFIG = ${THIS_DIR}/addconfig
+
+SCP_TO_TARGET = echo "don't do scp"
+
+TFTPBOOT := /var/lib/tftpboot
+TFTPDEF := ${TFTPBOOT}/snowball-default
+TFTPTEST := ${OUTPUT_DIR}/${BUILD_TARGET}
+
+SWITCH_TO_GOOD = cp ${TFTPDEF} ${TARGET_IMAGE}
+SWITCH_TO_TEST = cp ${TFTPTEST} ${TARGET_IMAGE}
+
+# Define each test with TEST_START
+# The config options below it will override the defaults
+TEST_START SKIP
+TEST_TYPE = boot
+BUILD_TYPE = u8500_defconfig
+BUILD_NOCLEAN = 1
+
+TEST_START
+TEST_TYPE = make_min_config
+OUTPUT_MIN_CONFIG = ${THIS_DIR}/config.newmin
+START_MIN_CONFIG = ${THIS_DIR}/config.orig
+IGNORE_CONFIG = ${THIS_DIR}/config.ignore
+BUILD_NOCLEAN = 1
+
+
+DEFAULTS
+LOCALVERSION = -test
+POWER_CYCLE = echo use the thumb luke; read a
+CONSOLE = cat ${THIS_DIR}/snowball-cat
+REBOOT_TYPE = script
+SSH_USER = root
+BUILD_OPTIONS = -j8 uImage
+BUILD_DIR = ${THIS_DIR}/linux.git
+OUTPUT_DIR = ${THIS_DIR}/snowball-build
+MACHINE = snowball
+TARGET_IMAGE = /var/lib/tftpboot/snowball-image
+BUILD_TARGET = arch/arm/boot/uImage
diff --git a/tools/testing/ktest/examples/test.conf b/tools/testing/ktest/examples/test.conf
new file mode 100644
index 000000000000..b725210efb7f
--- /dev/null
+++ b/tools/testing/ktest/examples/test.conf
@@ -0,0 +1,62 @@
+#
+# Generic config for a machine
+#
+
+# Name your machine (the DNS name, what you ssh to)
+MACHINE = foo
+
+# BOX can be different than foo, if the machine BOX has
+# multiple partitions with different systems installed. For example,
+# you may have a i386 and x86_64 installation on a test box.
+# If this is the case, MACHINE defines the way to connect to the
+# machine, which may be different between which system the machine
+# is booting into. BOX is used for the scripts to reboot and power cycle
+# the machine, where it does not matter which system the machine boots into.
+#
+#BOX := bar
+
+# Define a way to read the console
+CONSOLE = stty -F /dev/ttyS0 115200 parodd; cat /dev/ttyS0
+
+# The include files will set up the type of test to run. Just set TEST to
+# which test you want to run.
+#
+# TESTS = patchcheck, randconfig, boot, test, config-bisect, bisect, min-config
+#
+# See the include/*.conf files that define these tests
+#
+TEST := patchcheck
+
+# Some tests may have more than one test to run. Define MULTI := 1 to run
+# the extra tests.
+MULTI := 0
+
+# In case you want to differentiate which type of system you are testing
+BITS := 64
+
+# REBOOT = none, error, fail, empty
+# See include/defaults.conf
+REBOOT := empty
+
+# The defaults file will set up various settings that can be used by all
+# machine configs.
+INCLUDE include/defaults.conf
+
+# In case you need to add a patch for a bisect or something
+#PRE_BUILD = patch -p1 < ${THIS_DIR}/fix.patch
+
+# Reset the repo after the build and remove all 'test' modules from the target
+# Notice that DO_POST_BUILD is a variable (defined by ':=') and POST_BUILD
+# is the option (defined by '=')
+
+DO_POST_BUILD := git reset --hard
+POST_BUILD = ${SSH} 'rm -rf /lib/modules/*-test*'; ${DO_POST_BUILD}
+
+# The following files each handle a different test case.
+# Having them included allows you to set up more than one machine and share
+# the same tests.
+INCLUDE include/patchcheck.conf
+INCLUDE include/tests.conf
+INCLUDE include/bisect.conf
+INCLUDE include/min-config.conf
+
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index 4915408f6a98..292b13ad03f5 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -39,6 +39,7 @@ my %default = (
"CLEAR_LOG" => 0,
"BISECT_MANUAL" => 0,
"BISECT_SKIP" => 1,
+ "MIN_CONFIG_TYPE" => "boot",
"SUCCESS_LINE" => "login:",
"DETECT_TRIPLE_FAULT" => 1,
"NO_INSTALL" => 0,
@@ -66,6 +67,7 @@ my %default = (
my $ktest_config;
my $version;
+my $have_version = 0;
my $machine;
my $ssh_user;
my $tmpdir;
@@ -106,6 +108,8 @@ my $minconfig;
my $start_minconfig;
my $start_minconfig_defined;
my $output_minconfig;
+my $minconfig_type;
+my $use_output_minconfig;
my $ignore_config;
my $ignore_errors;
my $addconfig;
@@ -205,6 +209,8 @@ my %option_map = (
"MIN_CONFIG" => \$minconfig,
"OUTPUT_MIN_CONFIG" => \$output_minconfig,
"START_MIN_CONFIG" => \$start_minconfig,
+ "MIN_CONFIG_TYPE" => \$minconfig_type,
+ "USE_OUTPUT_MIN_CONFIG" => \$use_output_minconfig,
"IGNORE_CONFIG" => \$ignore_config,
"TEST" => \$run_test,
"ADD_CONFIG" => \$addconfig,
@@ -1702,10 +1708,12 @@ sub install {
sub get_version {
# get the release name
+ return if ($have_version);
doprint "$make kernelrelease ... ";
$version = `$make kernelrelease | tail -1`;
chomp($version);
doprint "$version\n";
+ $have_version = 1;
}
sub start_monitor_and_boot {
@@ -1828,6 +1836,9 @@ sub build {
my $save_no_reboot = $no_reboot;
$no_reboot = 1;
+ # Calculate a new version from here.
+ $have_version = 0;
+
if (defined($pre_build)) {
my $ret = run_command $pre_build;
if (!$ret && defined($pre_build_die) &&
@@ -1887,6 +1898,9 @@ sub build {
undef $redirect;
if (defined($post_build)) {
+ # Because a post build may change the kernel version
+ # do it now.
+ get_version;
my $ret = run_command $post_build;
if (!$ret && defined($post_build_die) &&
$post_build_die) {
@@ -3119,6 +3133,12 @@ sub test_this_config {
sub make_min_config {
my ($i) = @_;
+ my $type = $minconfig_type;
+ if ($type ne "boot" && $type ne "test") {
+ fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" .
+ " make_min_config works only with 'boot' and 'test'\n" and return;
+ }
+
if (!defined($output_minconfig)) {
fail "OUTPUT_MIN_CONFIG not defined" and return;
}
@@ -3128,8 +3148,15 @@ sub make_min_config {
# that instead.
if (-f $output_minconfig && !$start_minconfig_defined) {
print "$output_minconfig exists\n";
- if (read_yn " Use it as minconfig?") {
+ if (!defined($use_output_minconfig)) {
+ if (read_yn " Use it as minconfig?") {
+ $start_minconfig = $output_minconfig;
+ }
+ } elsif ($use_output_minconfig > 0) {
+ doprint "Using $output_minconfig as MIN_CONFIG\n";
$start_minconfig = $output_minconfig;
+ } else {
+ doprint "Set to still use MIN_CONFIG as starting point\n";
}
}
@@ -3278,6 +3305,11 @@ sub make_min_config {
build "oldconfig" or $failed = 1;
if (!$failed) {
start_monitor_and_boot or $failed = 1;
+
+ if ($type eq "test" && !$failed) {
+ do_run_test or $failed = 1;
+ }
+
end_monitor;
}
@@ -3474,6 +3506,8 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
$no_reboot = 1;
$reboot_success = 0;
+ $have_version = 0;
+
$iteration = $i;
my $makecmd = set_test_option("MAKE_CMD", $i);
diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf
index b682456afda8..cf362b3d1ec9 100644
--- a/tools/testing/ktest/sample.conf
+++ b/tools/testing/ktest/sample.conf
@@ -158,7 +158,7 @@
#
# TEST_START IF (DEFINED ALL_TESTS || ${MYTEST} == boottest) && ${MACHINE} == gandalf
#
-# Notice the use of paranthesis. Without any paranthesis the above would be
+# Notice the use of parentheses. Without any parentheses the above would be
# processed the same as:
#
# TEST_START IF DEFINED ALL_TESTS || (${MYTEST} == boottest && ${MACHINE} == gandalf)
@@ -1105,10 +1105,26 @@
# and will not be tested again in later runs.
# (optional)
#
+# MIN_CONFIG_TYPE can be either 'boot' or 'test'. With 'boot' it will
+# test if the created config can just boot the machine. If this is
+# set to 'test', then the TEST option must be defined and the created
+# config will not only boot the target, but also make sure that the
+# config lets the test succeed. This is useful to make sure the final
+# config that is generated allows network activity (ssh).
+# (optional)
+#
+# USE_OUTPUT_MIN_CONFIG set this to 1 if you do not want to be prompted
+# about using the OUTPUT_MIN_CONFIG as the MIN_CONFIG as the starting
+# point. Set it to 0 if you want to always just use the given MIN_CONFIG.
+# If it is not defined, it will prompt you to pick which config
+# to start with (MIN_CONFIG or OUTPUT_MIN_CONFIG).
+#
# Example:
#
# TEST_TYPE = make_min_config
# OUTPUT_MIN_CONFIG = /path/to/config-new-min
# START_MIN_CONFIG = /path/to/config-min
# IGNORE_CONFIG = /path/to/config-tested
+# MIN_CONFIG_TYPE = test
+# TEST = ssh ${USER}@${MACHINE} echo hi
#
diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c
index 4b107b5e623f..8674b9ec14f6 100644
--- a/tools/usb/ffs-test.c
+++ b/tools/usb/ffs-test.c
@@ -297,7 +297,7 @@ static void *start_thread_helper(void *arg)
ret = t->in(t, t->buf, t->buf_size);
if (ret > 0) {
- ret = t->out(t, t->buf, t->buf_size);
+ ret = t->out(t, t->buf, ret);
name = out_name;
op = "write";
} else {
diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c
index 6e0f56701e44..82d7c590c026 100644
--- a/tools/usb/testusb.c
+++ b/tools/usb/testusb.c
@@ -358,6 +358,7 @@ static const char *usbfs_dir_find(void)
{
static char usbfs_path_0[] = "/dev/usb/devices";
static char usbfs_path_1[] = "/proc/bus/usb/devices";
+ static char udev_usb_path[] = "/dev/bus/usb";
static char *const usbfs_paths[] = {
usbfs_path_0, usbfs_path_1
@@ -376,6 +377,10 @@ static const char *usbfs_dir_find(void)
}
} while (++it != end);
+ /* real device-nodes managed by udev */
+ if (access(udev_usb_path, F_OK) == 0)
+ return udev_usb_path;
+
return NULL;
}